From df9fcf9850dc9aabe121cfe1e6cf7d18444d34b6 Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Thu, 22 Jun 2023 06:09:00 +0200 Subject: [PATCH 0001/2101] Make ethernet_info work with esp-idf framework (#4976) --- .../components/ethernet_info/ethernet_info_text_sensor.cpp | 4 ++-- esphome/components/ethernet_info/ethernet_info_text_sensor.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/ethernet_info/ethernet_info_text_sensor.cpp b/esphome/components/ethernet_info/ethernet_info_text_sensor.cpp index e69872c290..f841875396 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_FRAMEWORK_ARDUINO +#ifdef USE_ESP32 namespace esphome { namespace ethernet_info { @@ -13,4 +13,4 @@ void IPAddressEthernetInfo::dump_config() { LOG_TEXT_SENSOR("", "EthernetInfo IP } // namespace ethernet_info } // namespace esphome -#endif // USE_ESP32_FRAMEWORK_ARDUINO +#endif // USE_ESP32 diff --git a/esphome/components/ethernet_info/ethernet_info_text_sensor.h b/esphome/components/ethernet_info/ethernet_info_text_sensor.h index aad8f362b5..2d46fe18eb 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_FRAMEWORK_ARDUINO +#ifdef USE_ESP32 namespace esphome { namespace ethernet_info { @@ -30,4 +30,4 @@ class IPAddressEthernetInfo : public PollingComponent, public text_sensor::TextS } // namespace ethernet_info } // namespace esphome -#endif // USE_ESP32_FRAMEWORK_ARDUINO +#endif // USE_ESP32 From a90d266017fd10e1c927865fbed7b3c7f987d589 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20Trzci=C5=84ski?= Date: Thu, 22 Jun 2023 21:18:29 +0200 Subject: [PATCH 0002/2101] display: fix white screen on binary displays (#4991) --- esphome/components/display/display_buffer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/display/display_buffer.cpp b/esphome/components/display/display_buffer.cpp index 672c6a22b0..791f7350e6 100644 --- a/esphome/components/display/display_buffer.cpp +++ b/esphome/components/display/display_buffer.cpp @@ -16,7 +16,7 @@ namespace display { static const char *const TAG = "display"; -const Color COLOR_OFF(0, 0, 0, 255); +const Color COLOR_OFF(0, 0, 0, 0); const Color COLOR_ON(255, 255, 255, 255); void Rect::expand(int16_t horizontal, int16_t vertical) { From dec6f044996657864491383e10b442944cbb2298 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 23 Jun 2023 07:34:55 +1200 Subject: [PATCH 0003/2101] Bump version to 2023.6.1 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index f49cff3b61..e06862072a 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2023.6.0" +__version__ = "2023.6.1" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 595ac84779cc0401912289b8db054523f252125c Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Thu, 22 Jun 2023 18:03:31 -0700 Subject: [PATCH 0004/2101] remove unused static declarations (#4993) --- esphome/core/time.cpp | 20 ++++++++++---------- esphome/core/time.h | 4 ---- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/esphome/core/time.cpp b/esphome/core/time.cpp index c03506fd2a..bc5bfa173e 100644 --- a/esphome/core/time.cpp +++ b/esphome/core/time.cpp @@ -2,6 +2,16 @@ namespace esphome { +static bool is_leap_year(uint32_t year) { return (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0); } + +static 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}; + uint8_t days = DAYS_IN_MONTH[month]; + if (month == 2 && is_leap_year(year)) + return 29; + return days; +} + size_t ESPTime::strftime(char *buffer, size_t buffer_len, const char *format) { struct tm c_tm = this->to_c_tm(); return ::strftime(buffer, buffer_len, format, &c_tm); @@ -158,14 +168,4 @@ template bool increment_time_value(T ¤t, uint16_t begin, uint1 return false; } -static bool is_leap_year(uint32_t year) { return (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0); } - -static 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}; - uint8_t days = DAYS_IN_MONTH[month]; - if (month == 2 && is_leap_year(year)) - return 29; - return days; -} - } // namespace esphome diff --git a/esphome/core/time.h b/esphome/core/time.h index e1bdc8c839..e16e449f0b 100644 --- a/esphome/core/time.h +++ b/esphome/core/time.h @@ -8,10 +8,6 @@ namespace esphome { template bool increment_time_value(T ¤t, uint16_t begin, uint16_t end); -static bool is_leap_year(uint32_t year); - -static uint8_t days_in_month(uint8_t month, uint16_t year); - /// A more user-friendly version of struct tm from time.h struct ESPTime { /** seconds after the minute [0-60] From fbfb4e2a73320630a2518b6c1e8b2ed5e07e8d9e Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 23 Jun 2023 16:42:37 +1200 Subject: [PATCH 0005/2101] Fix rp2040 pio tool download (#4994) --- esphome/components/rp2040/__init__.py | 24 ++++------ esphome/components/rp2040/build_pio.py.script | 47 +++++++++++++++++++ esphome/components/rp2040_pio/__init__.py | 40 ++++++++++++++++ .../components/rp2040_pio_led_strip/light.py | 7 +-- 4 files changed, 97 insertions(+), 21 deletions(-) create mode 100644 esphome/components/rp2040/build_pio.py.script create mode 100644 esphome/components/rp2040_pio/__init__.py diff --git a/esphome/components/rp2040/__init__.py b/esphome/components/rp2040/__init__.py index ad66ce6d18..030d586626 100644 --- a/esphome/components/rp2040/__init__.py +++ b/esphome/components/rp2040/__init__.py @@ -16,8 +16,7 @@ from esphome.const import ( KEY_TARGET_PLATFORM, ) from esphome.core import CORE, coroutine_with_priority, EsphomeError -from esphome.helpers import mkdir_p, write_file -import esphome.platformio_api as api +from esphome.helpers import mkdir_p, write_file, copy_file_if_changed from .const import KEY_BOARD, KEY_PIO_FILES, KEY_RP2040, rp2040_ns @@ -193,25 +192,20 @@ def generate_pio_files() -> bool: pio_path = CORE.relative_build_path(f"src/pio/{key}.pio") mkdir_p(os.path.dirname(pio_path)) write_file(pio_path, data) - _LOGGER.info("Assembling PIO assembly code") - retval = api.run_platformio_cli( - "pkg", - "exec", - "--package", - "earlephilhower/tool-pioasm-rp2040-earlephilhower", - "--", - "pioasm", - pio_path, - pio_path + ".h", - ) includes.append(f"pio/{key}.pio.h") - if retval != 0: - raise EsphomeError("PIO assembly failed") write_file( CORE.relative_build_path("src/pio_includes.h"), "#pragma once\n" + "\n".join([f'#include "{include}"' for include in includes]), ) + + dir = os.path.dirname(__file__) + build_pio_file = os.path.join(dir, "build_pio.py.script") + copy_file_if_changed( + build_pio_file, + CORE.relative_build_path("build_pio.py"), + ) + return True diff --git a/esphome/components/rp2040/build_pio.py.script b/esphome/components/rp2040/build_pio.py.script new file mode 100644 index 0000000000..c3e0767ed6 --- /dev/null +++ b/esphome/components/rp2040/build_pio.py.script @@ -0,0 +1,47 @@ +""" +Custom pioasm compiler script for platformio. +(c) 2022 by P.Z. + +Sourced 2023/06/23 from https://gist.github.com/hexeguitar/f4533bc697c956ac1245b6843e2ef438 + +Modified by jesserockz 2023/06/23 +""" + +from os.path import join +import glob +import sys + +import subprocess + +# pylint: disable=E0602 +Import("env") # noqa + +from SCons.Script import ARGUMENTS + + +platform = env.PioPlatform() +PROJ_SRC = env["PROJECT_SRC_DIR"] +PIO_FILES = glob.glob(join(PROJ_SRC, "**", "*.pio"), recursive=True) + +verbose = bool(int(ARGUMENTS.get("PIOVERBOSE", "0"))) + + +if PIO_FILES: + if verbose: + print("==============================================") + print("PIO ASSEMBLY COMPILER") + try: + PIOASM_DIR = platform.get_package_dir("tool-pioasm-rp2040-earlephilhower") + except: + print("tool-pioasm-rp2040-earlephilhower not supported on your system!") + sys.exit() + + PIOASM_EXE = join(PIOASM_DIR, "pioasm") + if verbose: + print("PIO files found:") + for filename in PIO_FILES: + if verbose: + print(f" {filename}") + subprocess.run([PIOASM_EXE, "-o", "c-sdk", filename, f"{filename}.h"]) + if verbose: + print("==============================================") diff --git a/esphome/components/rp2040_pio/__init__.py b/esphome/components/rp2040_pio/__init__.py new file mode 100644 index 0000000000..af884d5ac2 --- /dev/null +++ b/esphome/components/rp2040_pio/__init__.py @@ -0,0 +1,40 @@ +import platform + +import esphome.codegen as cg + + +DEPENDENCIES = ["rp2040"] + + +PIOASM_REPO_VERSION = "1.5.0-b" +PIOASM_REPO_BASE = f"https://github.com/earlephilhower/pico-quick-toolchain/releases/download/{PIOASM_REPO_VERSION}" +PIOASM_VERSION = "pioasm-2e6142b.230216" +PIOASM_DOWNLOADS = { + "linux": { + "aarch64": f"aarch64-linux-gnu.{PIOASM_VERSION}.tar.gz", + "armv7l": f"arm-linux-gnueabihf.{PIOASM_VERSION}.tar.gz", + "x86_64": f"x86_64-linux-gnu.{PIOASM_VERSION}.tar.gz", + }, + "windows": { + "amd64": f"x86_64-w64-mingw32.{PIOASM_VERSION}.zip", + }, + "darwin": { + "x86_64": f"x86_64-apple-darwin14.{PIOASM_VERSION}.tar.gz", + "arm64": f"x86_64-apple-darwin14.{PIOASM_VERSION}.tar.gz", + }, +} + + +async def to_code(config): + # cg.add_platformio_option( + # "platform_packages", + # [ + # "earlephilhower/tool-pioasm-rp2040-earlephilhower", + # ], + # ) + file = PIOASM_DOWNLOADS[platform.system().lower()][platform.machine().lower()] + cg.add_platformio_option( + "platform_packages", + [f"earlephilhower/tool-pioasm-rp2040-earlephilhower@{PIOASM_REPO_BASE}/{file}"], + ) + cg.add_platformio_option("extra_scripts", ["pre:build_pio.py"]) diff --git a/esphome/components/rp2040_pio_led_strip/light.py b/esphome/components/rp2040_pio_led_strip/light.py index a2ba72318f..6c51b57e97 100644 --- a/esphome/components/rp2040_pio_led_strip/light.py +++ b/esphome/components/rp2040_pio_led_strip/light.py @@ -127,6 +127,7 @@ def time_to_cycles(time_us): CONF_PIO = "pio" +AUTO_LOAD = ["rp2040_pio"] CODEOWNERS = ["@Papa-DMan"] DEPENDENCIES = ["rp2040"] @@ -265,9 +266,3 @@ async def to_code(config): time_to_cycles(config[CONF_BIT1_LOW]), ), ) - cg.add_platformio_option( - "platform_packages", - [ - "earlephilhower/tool-pioasm-rp2040-earlephilhower", - ], - ) From 39948db59af9e2467ecab13822124586da5c7388 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 23 Jun 2023 17:17:43 +1200 Subject: [PATCH 0006/2101] Bump version to 2023.6.2 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index e06862072a..48e62b9b86 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2023.6.1" +__version__ = "2023.6.2" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 604d4eec792b277e1a979aeaa34f2c6ef629d53d Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 26 Jun 2023 10:27:03 +1200 Subject: [PATCH 0007/2101] Update webserver to 56d73b5 (#5007) --- esphome/components/web_server/server_index.h | 1179 +++++++++--------- 1 file changed, 590 insertions(+), 589 deletions(-) diff --git a/esphome/components/web_server/server_index.h b/esphome/components/web_server/server_index.h index 4e6e136f8c..2dbb839c5e 100644 --- a/esphome/components/web_server/server_index.h +++ b/esphome/components/web_server/server_index.h @@ -6,596 +6,597 @@ namespace esphome { namespace web_server { const uint8_t INDEX_GZ[] PROGMEM = { - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xbd, 0x7d, 0xd9, 0x76, 0xe3, 0xc6, 0x92, 0xe0, 0xf3, - 0x9c, 0x33, 0x7f, 0x30, 0x2f, 0x28, 0x58, 0x5d, 0x05, 0x5c, 0x81, 0x10, 0x49, 0x95, 0xaa, 0xca, 0xa0, 0x40, 0x5e, - 0xd5, 0x62, 0x57, 0xd9, 0xb5, 0xb9, 0xa4, 0xb2, 0xaf, 0x2d, 0xeb, 0x4a, 0x10, 0x99, 0x14, 0xe1, 0x02, 0x01, 0x1a, - 0x48, 0x6a, 0x31, 0x85, 0x3e, 0xfd, 0xd4, 0x4f, 0x7d, 0xce, 0x6c, 0xfd, 0xd0, 0x0f, 0xd3, 0xa7, 0xfb, 0x61, 0x3e, - 0x62, 0x9e, 0xfb, 0x53, 0xee, 0x0f, 0x4c, 0x7f, 0xc2, 0x44, 0x44, 0x2e, 0x48, 0x80, 0xa4, 0x24, 0xbb, 0x7d, 0xe7, - 0x78, 0x11, 0x90, 0x6b, 0x44, 0x64, 0x64, 0x6c, 0x19, 0x09, 0xee, 0xde, 0x1b, 0x65, 0x43, 0x7e, 0x35, 0x63, 0xd6, - 0x84, 0x4f, 0x93, 0xfe, 0xae, 0xfc, 0x3f, 0x8b, 0x46, 0xfd, 0xdd, 0x24, 0x4e, 0x3f, 0x59, 0x39, 0x4b, 0xc2, 0x78, - 0x98, 0xa5, 0xd6, 0x24, 0x67, 0xe3, 0x70, 0x14, 0xf1, 0x28, 0x88, 0xa7, 0xd1, 0x19, 0xb3, 0xb6, 0xfa, 0xbb, 0x53, - 0xc6, 0x23, 0x6b, 0x38, 0x89, 0xf2, 0x82, 0xf1, 0xf0, 0xe3, 0xc1, 0x17, 0xad, 0x27, 0xfd, 0xdd, 0x62, 0x98, 0xc7, - 0x33, 0x6e, 0xe1, 0x90, 0xe1, 0x34, 0x1b, 0xcd, 0x13, 0xd6, 0x3f, 0x8f, 0x72, 0xeb, 0x05, 0x0b, 0xdf, 0x9d, 0xfe, - 0xc4, 0x86, 0xdc, 0x1f, 0xb1, 0x71, 0x9c, 0xb2, 0xf7, 0x79, 0x36, 0x63, 0x39, 0xbf, 0xf2, 0xf6, 0x57, 0x57, 0xc4, - 0xac, 0xf0, 0x9e, 0xe9, 0xaa, 0x33, 0xc6, 0xdf, 0x5d, 0xa4, 0xaa, 0xcf, 0x73, 0x26, 0x26, 0xc9, 0xf2, 0xc2, 0x8b, - 0xd7, 0xb4, 0xd9, 0xbf, 0x9a, 0x9e, 0x66, 0x49, 0xe1, 0x7d, 0xd2, 0xf5, 0xb3, 0x3c, 0xe3, 0x19, 0x82, 0xe5, 0x4f, - 0xa2, 0xc2, 0x68, 0xe9, 0xbd, 0x5b, 0xd1, 0x64, 0x26, 0x2b, 0x5f, 0x15, 0x2f, 0xd2, 0xf9, 0x94, 0xe5, 0xd1, 0x69, - 0xc2, 0xbc, 0x9c, 0x85, 0x0e, 0xf3, 0xb8, 0x17, 0xbb, 0x61, 0x9f, 0x5b, 0x71, 0x6a, 0xb1, 0xc1, 0x0b, 0x46, 0x25, - 0x0b, 0xa6, 0x5b, 0x05, 0xf7, 0xda, 0x1e, 0x90, 0x6b, 0x1c, 0x9f, 0xcd, 0xf5, 0xfb, 0x45, 0x1e, 0x73, 0xf5, 0x7c, - 0x1e, 0x25, 0x73, 0x16, 0xc4, 0xa5, 0x1b, 0xb0, 0x43, 0x7e, 0x14, 0xc6, 0xde, 0x27, 0x1a, 0x14, 0x86, 0x5c, 0x8c, - 0xb3, 0xdc, 0x41, 0x5a, 0xc5, 0x38, 0x36, 0xbf, 0xbe, 0x76, 0x78, 0xb8, 0x28, 0x5d, 0xf7, 0x13, 0xf3, 0x87, 0x51, - 0x92, 0x38, 0x38, 0xf1, 0xfd, 0xfb, 0x39, 0xce, 0x18, 0x7b, 0xfc, 0x30, 0x3e, 0x72, 0x7b, 0xf1, 0xd8, 0x89, 0x99, - 0x5b, 0xf5, 0xcb, 0xc6, 0x56, 0xcc, 0x1c, 0xee, 0xba, 0xef, 0xd6, 0xf7, 0xc9, 0x19, 0x9f, 0xe7, 0x00, 0x7b, 0xe9, - 0xbd, 0x53, 0x33, 0xef, 0x63, 0xfd, 0x33, 0xea, 0xd8, 0x03, 0xd8, 0x0b, 0x6e, 0x7d, 0x11, 0x5e, 0xc4, 0xe9, 0x28, - 0xbb, 0xf0, 0xf7, 0x27, 0x11, 0xfc, 0xf9, 0x90, 0x65, 0xfc, 0xfe, 0x7d, 0xe7, 0x3c, 0x8b, 0x47, 0x56, 0x3b, 0x0c, - 0xcd, 0xca, 0xab, 0x67, 0xfb, 0xfb, 0xd7, 0xd7, 0x8d, 0x02, 0x3f, 0x8d, 0x78, 0x7c, 0xce, 0x44, 0x67, 0x00, 0xc0, - 0x86, 0xbf, 0x33, 0xce, 0x46, 0xfb, 0xfc, 0x2a, 0x81, 0x52, 0xc6, 0x78, 0x61, 0x03, 0x8e, 0xcf, 0xb3, 0x21, 0x90, - 0x2d, 0x35, 0x08, 0x0f, 0x4d, 0x73, 0x36, 0x4b, 0xa2, 0x21, 0xc3, 0x7a, 0x18, 0xa9, 0xea, 0x51, 0x35, 0xf2, 0xbe, - 0x0b, 0xc5, 0xf2, 0x3a, 0xae, 0x97, 0xb1, 0x30, 0x65, 0x17, 0xd6, 0x9b, 0x68, 0xd6, 0x1b, 0x26, 0x51, 0x51, 0x58, - 0x29, 0x5b, 0x10, 0x0a, 0xf9, 0x7c, 0x08, 0x0c, 0x42, 0x08, 0x2e, 0x80, 0x4c, 0x7c, 0x12, 0x17, 0xfe, 0xf1, 0xc6, - 0xb0, 0x28, 0x3e, 0xb0, 0x62, 0x9e, 0xf0, 0x8d, 0x10, 0xd6, 0x82, 0xdf, 0x0b, 0xc3, 0xef, 0x5c, 0x3e, 0xc9, 0xb3, - 0x0b, 0xeb, 0x45, 0x9e, 0x43, 0x73, 0x1b, 0xa6, 0x14, 0x0d, 0xac, 0x18, 0xc6, 0xca, 0xb8, 0xa5, 0x07, 0xc3, 0x05, - 0xf4, 0xad, 0x8f, 0x05, 0xb3, 0x4e, 0xe6, 0x69, 0x11, 0x8d, 0x19, 0x34, 0x3d, 0xb1, 0xb2, 0xdc, 0x3a, 0x81, 0x41, - 0x4f, 0x60, 0xc9, 0x0a, 0x0e, 0xbb, 0xc6, 0xb7, 0xdd, 0x1e, 0xcd, 0x05, 0x85, 0x07, 0xec, 0x92, 0x87, 0xac, 0x04, - 0xc6, 0xb4, 0x0a, 0x8d, 0x86, 0xe3, 0x2e, 0x12, 0x28, 0x60, 0x61, 0xc6, 0x90, 0x65, 0x1d, 0xb3, 0xb1, 0x5e, 0x9c, - 0x2f, 0xee, 0xdf, 0xd7, 0xb4, 0x06, 0x9a, 0x38, 0xd0, 0xb6, 0x68, 0xb4, 0xf5, 0x04, 0xe2, 0x35, 0x12, 0xb9, 0x1e, - 0xf3, 0x25, 0xf9, 0xf6, 0xaf, 0xd2, 0x61, 0x7d, 0x6c, 0xa8, 0x2c, 0x79, 0xb6, 0xcf, 0xf3, 0x38, 0x3d, 0x03, 0x20, - 0xe4, 0x4c, 0x66, 0x93, 0xb2, 0x14, 0x8b, 0xff, 0x9e, 0x85, 0x2c, 0xec, 0xe3, 0xe8, 0x29, 0x73, 0xec, 0x82, 0x7a, - 0xd8, 0x61, 0x88, 0xa4, 0x07, 0x06, 0x63, 0x03, 0x16, 0xb0, 0x4d, 0xdb, 0xf6, 0xbe, 0x73, 0xbd, 0x2b, 0xe4, 0x20, - 0xdf, 0xf7, 0x89, 0x7d, 0x45, 0xe7, 0x38, 0xec, 0x20, 0xd0, 0x7e, 0xc2, 0xd2, 0x33, 0x3e, 0x19, 0xb0, 0xc3, 0xf6, - 0x51, 0xc0, 0x01, 0xaa, 0xd1, 0x7c, 0xc8, 0x1c, 0xe4, 0x47, 0x2f, 0xc7, 0xed, 0xb3, 0xe9, 0xc0, 0x14, 0xb8, 0x30, - 0xf7, 0x08, 0xc7, 0xda, 0xd2, 0xb8, 0x8a, 0x45, 0x15, 0x60, 0xc8, 0xe7, 0x36, 0xec, 0xb0, 0x53, 0x96, 0x1b, 0x70, - 0xe8, 0x66, 0xbd, 0xda, 0x0a, 0xce, 0x61, 0x85, 0xa0, 0x9f, 0x35, 0x9e, 0xa7, 0x43, 0x1e, 0x83, 0xe0, 0xb2, 0x37, - 0x01, 0x5c, 0xb1, 0x72, 0x7a, 0xe1, 0x6c, 0xb7, 0x74, 0x9d, 0xd8, 0xdd, 0x64, 0x87, 0xf9, 0x66, 0xe7, 0xc8, 0x43, - 0x28, 0x35, 0xf1, 0x25, 0xe2, 0x31, 0x20, 0x58, 0x7a, 0x1f, 0x99, 0xde, 0x9e, 0x5f, 0x0c, 0x98, 0xbf, 0xcc, 0xc7, - 0x21, 0xf7, 0xa7, 0xd1, 0x0c, 0xb1, 0x61, 0xc4, 0x03, 0x51, 0x3a, 0x44, 0xe8, 0x6a, 0xeb, 0x82, 0x14, 0xf3, 0x2b, - 0x16, 0x70, 0x81, 0x20, 0xb0, 0x67, 0x5f, 0x44, 0xc3, 0x09, 0x6c, 0xf1, 0x8a, 0x70, 0x23, 0xb5, 0x1d, 0x86, 0x39, - 0x8b, 0x38, 0x7b, 0x91, 0x30, 0x7c, 0xc3, 0x15, 0x80, 0x9e, 0xb6, 0xeb, 0xe5, 0x6a, 0xdf, 0x25, 0x31, 0x7f, 0x9b, - 0xc1, 0x3c, 0x3d, 0xc1, 0x24, 0xc0, 0xc5, 0xf9, 0xfd, 0xfb, 0x31, 0xb2, 0xc8, 0x1e, 0x87, 0xd5, 0x3a, 0x9d, 0x73, - 0x58, 0xb7, 0x14, 0x5b, 0xd8, 0x40, 0x6d, 0x2f, 0xf6, 0x39, 0x10, 0xf1, 0x59, 0x96, 0x72, 0x18, 0x0e, 0xe0, 0xd5, - 0x1c, 0xe4, 0x47, 0xb3, 0x19, 0x4b, 0x47, 0xcf, 0x26, 0x71, 0x32, 0x02, 0x6a, 0x94, 0x80, 0x6f, 0xc2, 0x42, 0xc0, - 0x13, 0x90, 0x09, 0x6e, 0xc6, 0x88, 0x96, 0x0f, 0x19, 0x99, 0x87, 0xb6, 0xdd, 0x43, 0x09, 0x24, 0xb1, 0x40, 0x19, - 0x44, 0x0b, 0xf7, 0x01, 0x44, 0x7f, 0xe1, 0xf2, 0xcd, 0x30, 0xd6, 0xcb, 0x28, 0x09, 0xfc, 0x1e, 0x25, 0x0d, 0xd0, - 0x9f, 0x81, 0x0c, 0xec, 0xa1, 0xe0, 0xfa, 0x4a, 0x4a, 0x9d, 0x88, 0x29, 0x0c, 0x81, 0x00, 0x43, 0x94, 0x20, 0x92, - 0x06, 0xef, 0xb3, 0xe4, 0x6a, 0x1c, 0x27, 0xc9, 0xfe, 0x7c, 0x36, 0xcb, 0x72, 0xee, 0x7d, 0x1d, 0x2e, 0x78, 0x56, - 0xe1, 0x4a, 0x9b, 0xbc, 0xb8, 0x88, 0x39, 0x12, 0xd4, 0x5d, 0x0c, 0x23, 0x58, 0xea, 0xa7, 0x59, 0x96, 0xb0, 0x28, - 0x05, 0x34, 0xd8, 0xc0, 0xb6, 0x83, 0x74, 0x9e, 0x24, 0xbd, 0x53, 0x18, 0xf6, 0x53, 0x8f, 0xaa, 0x85, 0xc4, 0x0f, - 0xe8, 0x79, 0x2f, 0xcf, 0xa3, 0x2b, 0x68, 0x88, 0x6d, 0x80, 0x17, 0x61, 0xb5, 0xbe, 0xda, 0x7f, 0xf7, 0xd6, 0x17, - 0x8c, 0x1f, 0x8f, 0xaf, 0x00, 0xd0, 0xb2, 0x92, 0x9a, 0xe3, 0x3c, 0x9b, 0x36, 0xa6, 0x46, 0x3a, 0xc4, 0x21, 0xeb, - 0xad, 0x01, 0x21, 0xa6, 0x91, 0x61, 0x95, 0x98, 0x09, 0xc1, 0x5b, 0xe2, 0x67, 0x59, 0x89, 0x7b, 0x60, 0x80, 0x0f, - 0x81, 0x28, 0x86, 0x29, 0x6f, 0x86, 0x96, 0xe7, 0x57, 0x8b, 0x38, 0x24, 0x38, 0x67, 0xa8, 0x7f, 0x11, 0xc6, 0x61, - 0x04, 0xb3, 0x2f, 0xc4, 0x80, 0xa5, 0x82, 0x38, 0x2e, 0x4b, 0x6f, 0xa2, 0x99, 0x18, 0x25, 0x1e, 0x0a, 0x14, 0x0e, - 0xdb, 0xe8, 0xfa, 0x9a, 0xc1, 0x8b, 0xeb, 0x7d, 0x13, 0x2e, 0x22, 0x85, 0x0f, 0x6a, 0x28, 0xdc, 0x5f, 0x81, 0x90, - 0x13, 0xa8, 0xc9, 0xce, 0x41, 0x0f, 0x02, 0x9c, 0x5f, 0x83, 0xfa, 0x1b, 0x27, 0x08, 0xc5, 0xbd, 0x8e, 0x07, 0x1a, - 0xf4, 0xd9, 0x24, 0x4a, 0xcf, 0xd8, 0x28, 0x98, 0xb0, 0x52, 0x4a, 0xde, 0x3d, 0x0b, 0xd6, 0x18, 0xd8, 0xa9, 0xb0, - 0x5e, 0x1e, 0xbc, 0x79, 0x2d, 0x57, 0xae, 0x26, 0x8c, 0x61, 0x91, 0xe6, 0xa0, 0x56, 0x41, 0x6c, 0x4b, 0x71, 0xfc, - 0x82, 0x2b, 0xe9, 0x2d, 0x4a, 0xe2, 0xe2, 0xe3, 0x0c, 0x4c, 0x0c, 0xf6, 0x1e, 0x86, 0x81, 0xe9, 0x43, 0x98, 0x8a, - 0xca, 0x61, 0x3e, 0x51, 0x31, 0xd2, 0x45, 0xd0, 0x59, 0x60, 0x2a, 0x5e, 0x33, 0xc7, 0x2d, 0x81, 0x55, 0x79, 0x3c, - 0xb4, 0xa2, 0xd1, 0xe8, 0x55, 0x1a, 0xf3, 0x38, 0x4a, 0xe2, 0x5f, 0x88, 0x92, 0x0b, 0xe4, 0x31, 0xde, 0x93, 0x8b, - 0x00, 0xb8, 0x53, 0x8f, 0xc4, 0x55, 0x42, 0xf6, 0x1e, 0x11, 0x43, 0x48, 0xcb, 0x24, 0x3c, 0x3c, 0x92, 0xe0, 0x25, - 0xfe, 0x6c, 0x5e, 0x4c, 0x90, 0xb0, 0x72, 0x60, 0x14, 0xe4, 0xd9, 0x69, 0xc1, 0xf2, 0x73, 0x36, 0xd2, 0x1c, 0x50, - 0x00, 0x56, 0xd4, 0x1c, 0x8c, 0x17, 0x9a, 0xd1, 0x51, 0x3a, 0x94, 0xc1, 0x50, 0x3d, 0x53, 0xcc, 0x32, 0xc9, 0xcc, - 0xda, 0xc2, 0xd1, 0x52, 0xc0, 0x11, 0x46, 0x85, 0x94, 0x04, 0x79, 0xa8, 0x30, 0x9c, 0x80, 0x14, 0x02, 0xad, 0x60, - 0x6e, 0x73, 0xa5, 0xc9, 0x5e, 0xcc, 0x49, 0x25, 0xe4, 0xd0, 0x11, 0x36, 0x32, 0x41, 0x9a, 0xbb, 0xb0, 0xab, 0x40, - 0xca, 0x4b, 0x70, 0x85, 0x14, 0x51, 0x66, 0x0e, 0x32, 0x40, 0xf8, 0x8d, 0xd0, 0x85, 0x3e, 0xb6, 0x20, 0x36, 0xf0, - 0xf5, 0xca, 0x03, 0x61, 0x25, 0xde, 0x15, 0x22, 0xde, 0x1a, 0xb0, 0x71, 0x62, 0xe4, 0x27, 0xef, 0x1e, 0xf7, 0xd3, - 0x6c, 0x6f, 0x38, 0x64, 0x45, 0x91, 0x01, 0x6c, 0xf7, 0xa8, 0xfd, 0x3a, 0x43, 0x0b, 0x28, 0xe9, 0x6a, 0x59, 0x67, - 0x17, 0xa4, 0xc1, 0x4d, 0xb5, 0xa2, 0x74, 0x7a, 0x60, 0x1f, 0x1f, 0x83, 0xcc, 0xf6, 0x24, 0x19, 0x80, 0xea, 0xcb, - 0x86, 0x9f, 0xb0, 0x67, 0xea, 0x94, 0x59, 0x69, 0x5f, 0x3a, 0x75, 0x90, 0x3c, 0x18, 0xd6, 0x2d, 0x8d, 0x05, 0x5d, - 0x39, 0x34, 0xae, 0x86, 0x54, 0x90, 0x8b, 0x33, 0x52, 0xd9, 0xc6, 0x32, 0x82, 0xd5, 0x56, 0x7a, 0x44, 0x7a, 0x85, - 0x4d, 0x41, 0x80, 0x1e, 0xb2, 0xa3, 0x9e, 0xac, 0x0f, 0x73, 0x41, 0xb9, 0x9c, 0xfd, 0x3c, 0x67, 0x05, 0x17, 0xac, - 0x0b, 0xe3, 0x82, 0xb9, 0x0a, 0x22, 0xb6, 0x69, 0x1d, 0xd6, 0x6c, 0xc7, 0x55, 0xb0, 0xbd, 0x9b, 0xa1, 0x1e, 0x2b, - 0x90, 0x93, 0x6f, 0x66, 0x27, 0x84, 0x95, 0xb9, 0xd7, 0xd7, 0xdf, 0xa8, 0x41, 0xaa, 0xa5, 0xd4, 0x36, 0x50, 0x63, - 0x4d, 0x6c, 0xd5, 0x64, 0x64, 0xbb, 0x52, 0xa1, 0xde, 0xeb, 0xf4, 0x6a, 0x7c, 0x00, 0x7b, 0xae, 0xad, 0x59, 0xba, - 0x32, 0xb6, 0xdf, 0x2b, 0x9a, 0xbe, 0x13, 0x23, 0x93, 0x35, 0xca, 0x6e, 0xe7, 0x1e, 0xb5, 0xe3, 0xa1, 0xed, 0x52, - 0x5d, 0x25, 0x18, 0xe6, 0x75, 0xc1, 0xd0, 0x84, 0x7a, 0xa6, 0xbb, 0xd8, 0x9a, 0xa9, 0x58, 0xa8, 0xd6, 0x5a, 0x39, - 0x10, 0x3c, 0x3c, 0x04, 0xe3, 0x64, 0xa5, 0x7f, 0xf0, 0x36, 0x9a, 0x32, 0xa4, 0xa8, 0xb7, 0xae, 0x81, 0x74, 0x20, - 0xa0, 0xc9, 0x51, 0x53, 0xbd, 0x71, 0x57, 0x58, 0x4d, 0xf5, 0xfd, 0x15, 0x83, 0x15, 0x01, 0xf6, 0x75, 0xb9, 0x62, - 0x89, 0x48, 0x6f, 0x0a, 0x2e, 0xd1, 0xf4, 0x11, 0x65, 0x62, 0x4d, 0x48, 0xc1, 0x03, 0xf2, 0xb0, 0xfc, 0x8d, 0x85, - 0x93, 0xad, 0x98, 0xc2, 0x91, 0xa3, 0x4c, 0x01, 0x3a, 0x93, 0x12, 0x00, 0x71, 0x49, 0x7f, 0x6b, 0x1b, 0x0b, 0xc9, - 0xb6, 0x8f, 0x7c, 0xe0, 0x8f, 0x93, 0x88, 0x3b, 0x9d, 0xad, 0xb6, 0x0b, 0x7c, 0x08, 0x42, 0x1c, 0x74, 0x04, 0x98, - 0xf7, 0x15, 0x2a, 0x8c, 0xbc, 0x05, 0x97, 0xfb, 0x60, 0x14, 0x4d, 0xe2, 0x31, 0x77, 0x12, 0x54, 0x22, 0x6e, 0xc9, - 0x12, 0x50, 0x32, 0x7a, 0x5f, 0x81, 0x94, 0xe0, 0x42, 0xba, 0x88, 0x6a, 0x2d, 0xd0, 0x14, 0xa4, 0x24, 0xa5, 0x48, - 0x0b, 0x2a, 0x08, 0x0c, 0xa1, 0xd2, 0x53, 0x1c, 0x05, 0xfa, 0x2d, 0x1e, 0x88, 0x41, 0x83, 0x25, 0x8b, 0x32, 0x1e, - 0xc4, 0xcb, 0x85, 0xa0, 0x86, 0x7d, 0x9e, 0xbd, 0xce, 0x2e, 0x58, 0xfe, 0x2c, 0x42, 0xd8, 0x03, 0xd1, 0xbd, 0x04, - 0x49, 0x4f, 0x02, 0x9d, 0xf5, 0x14, 0xaf, 0x9c, 0x13, 0xd2, 0xb0, 0x10, 0xd3, 0x18, 0x15, 0x21, 0x68, 0x39, 0xa2, - 0x7d, 0x8a, 0x5b, 0x8a, 0xf6, 0x1e, 0xaa, 0x12, 0xa6, 0x79, 0x6b, 0xef, 0x75, 0x9d, 0xb7, 0x60, 0x84, 0x99, 0xe2, - 0xd6, 0xfa, 0x8e, 0x75, 0x3d, 0xa9, 0x9b, 0x1d, 0xc9, 0x5b, 0x86, 0x32, 0x03, 0xfd, 0x71, 0x7d, 0x5d, 0x19, 0xe9, - 0xa0, 0x4c, 0xb5, 0x34, 0x47, 0xcb, 0x49, 0x6c, 0x09, 0xb7, 0x04, 0x65, 0x84, 0x86, 0x57, 0x9e, 0x25, 0x89, 0xa1, - 0x8b, 0xbc, 0xb8, 0xe7, 0x34, 0xd4, 0x11, 0x40, 0x31, 0xad, 0x69, 0xa4, 0x01, 0x0f, 0x74, 0x05, 0x2a, 0x25, 0xa5, - 0x8d, 0xbc, 0xaa, 0x89, 0x80, 0x38, 0x1d, 0xb1, 0x5c, 0x38, 0x68, 0x52, 0x87, 0xc2, 0x84, 0x29, 0x30, 0x34, 0x1b, - 0x81, 0x84, 0x57, 0x08, 0x80, 0x79, 0xe2, 0x4f, 0xb2, 0x82, 0xeb, 0x3a, 0x13, 0xfa, 0xf8, 0xfa, 0x3a, 0x16, 0xfe, - 0x22, 0x32, 0x40, 0xce, 0xa6, 0xd9, 0x39, 0x5b, 0x01, 0x75, 0x4f, 0x0d, 0x66, 0x82, 0x6c, 0x0c, 0x03, 0x4a, 0x14, - 0x54, 0xcb, 0x2c, 0x89, 0x87, 0x4c, 0x6b, 0xa9, 0xa9, 0x0f, 0x06, 0x1d, 0xbb, 0x04, 0x19, 0xc1, 0xdc, 0x7e, 0xbf, - 0xdf, 0xf6, 0x3a, 0x6e, 0x29, 0x08, 0xbe, 0x58, 0xa2, 0xe8, 0x0d, 0xfa, 0x51, 0x9a, 0xe0, 0xab, 0x64, 0x01, 0x77, - 0x0d, 0xa5, 0xc8, 0x85, 0x9f, 0xe4, 0x49, 0x41, 0xec, 0x7a, 0x23, 0x18, 0x94, 0x33, 0x25, 0xb8, 0xd1, 0xc4, 0x15, + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xbd, 0x7d, 0xdb, 0x76, 0xe3, 0x46, 0x92, 0xe0, 0xf3, + 0x9e, 0xb3, 0x7f, 0xb0, 0x2f, 0x28, 0x58, 0x53, 0x05, 0xb4, 0x40, 0x88, 0xa4, 0x4a, 0x55, 0x65, 0x50, 0x20, 0x5b, + 0x75, 0xb1, 0xab, 0xec, 0xba, 0xb9, 0xa4, 0xb2, 0xdb, 0x96, 0xd5, 0x12, 0x44, 0x26, 0x45, 0xb8, 0x40, 0x80, 0x06, + 0x92, 0xba, 0x98, 0xc2, 0x9c, 0x79, 0x9a, 0xa7, 0x39, 0x67, 0x6f, 0xf3, 0x30, 0x0f, 0x3b, 0x67, 0xe6, 0x61, 0x3f, + 0x62, 0x9f, 0xe7, 0x53, 0xfa, 0x07, 0x76, 0x3e, 0x61, 0x23, 0x22, 0x2f, 0x48, 0x80, 0xa4, 0x24, 0x7b, 0xdc, 0x7b, + 0xdc, 0xd5, 0x02, 0xf2, 0x1a, 0x11, 0x19, 0x19, 0xb7, 0x8c, 0x04, 0x77, 0xef, 0x8d, 0xb2, 0x21, 0xbf, 0x9a, 0x31, + 0x6b, 0xc2, 0xa7, 0x49, 0x7f, 0x57, 0xfe, 0x3f, 0x8b, 0x46, 0xfd, 0xdd, 0x24, 0x4e, 0x3f, 0x59, 0x39, 0x4b, 0xc2, + 0x78, 0x98, 0xa5, 0xd6, 0x24, 0x67, 0xe3, 0x70, 0x14, 0xf1, 0x28, 0x88, 0xa7, 0xd1, 0x19, 0xb3, 0xb6, 0xfa, 0xbb, + 0x53, 0xc6, 0x23, 0x6b, 0x38, 0x89, 0xf2, 0x82, 0xf1, 0xf0, 0xe3, 0xc1, 0x17, 0xad, 0x27, 0xfd, 0xdd, 0x62, 0x98, + 0xc7, 0x33, 0x6e, 0xe1, 0x90, 0xe1, 0x34, 0x1b, 0xcd, 0x13, 0xd6, 0x3f, 0x8f, 0x72, 0xeb, 0x05, 0x0b, 0xdf, 0x9d, + 0xfe, 0xc4, 0x86, 0xdc, 0x1f, 0xb1, 0x71, 0x9c, 0xb2, 0xf7, 0x79, 0x36, 0x63, 0x39, 0xbf, 0xf2, 0xf6, 0x57, 0x57, + 0xc4, 0xac, 0xf0, 0x9e, 0xe9, 0xaa, 0x33, 0xc6, 0xdf, 0x5d, 0xa4, 0xaa, 0xcf, 0x73, 0x26, 0x26, 0xc9, 0xf2, 0xc2, + 0x8b, 0xd7, 0xb4, 0xd9, 0xbf, 0x9a, 0x9e, 0x66, 0x49, 0xe1, 0x7d, 0xd2, 0xf5, 0xb3, 0x3c, 0xe3, 0x19, 0x82, 0xe5, + 0x4f, 0xa2, 0xc2, 0x68, 0xe9, 0xbd, 0x5b, 0xd1, 0x64, 0x26, 0x2b, 0x5f, 0x15, 0x2f, 0xd2, 0xf9, 0x94, 0xe5, 0xd1, + 0x69, 0xc2, 0xbc, 0x9c, 0x85, 0x0e, 0xf7, 0x98, 0x17, 0xbb, 0x61, 0x9f, 0x59, 0x71, 0x6a, 0xf1, 0xc1, 0x0b, 0x46, + 0x25, 0x0b, 0xa6, 0x5b, 0x05, 0xf7, 0xda, 0x1e, 0x90, 0x6b, 0x1c, 0x9f, 0xcd, 0xf5, 0xfb, 0x45, 0x1e, 0x73, 0xf5, + 0x7c, 0x1e, 0x25, 0x73, 0x16, 0xc4, 0xa5, 0x1b, 0xf0, 0x43, 0x76, 0x14, 0xc6, 0xde, 0x27, 0x1a, 0x14, 0x86, 0x5c, + 0x8c, 0xb3, 0xdc, 0x41, 0x5a, 0xc5, 0x38, 0x36, 0xbb, 0xbe, 0x76, 0x58, 0xb8, 0x28, 0x5d, 0xf7, 0x13, 0xf3, 0x87, + 0x51, 0x92, 0x38, 0x38, 0xf1, 0xfd, 0xfb, 0x39, 0xce, 0x18, 0x7b, 0xec, 0x30, 0x3e, 0x72, 0x7b, 0xf1, 0xd8, 0x89, + 0x99, 0x5b, 0xf5, 0xcb, 0xc6, 0x56, 0xcc, 0x1c, 0xe6, 0xba, 0xef, 0xd6, 0xf7, 0xc9, 0x19, 0x9f, 0xe7, 0x00, 0x7b, + 0xe9, 0xbd, 0x53, 0x33, 0xef, 0x63, 0xfd, 0x33, 0xea, 0xd8, 0x03, 0xd8, 0x0b, 0x6e, 0x7d, 0x11, 0x5e, 0xc4, 0xe9, + 0x28, 0xbb, 0xf0, 0xf7, 0x27, 0x11, 0xfc, 0xf9, 0x90, 0x65, 0xfc, 0xfe, 0x7d, 0xe7, 0x3c, 0x8b, 0x47, 0x56, 0x3b, + 0x0c, 0xcd, 0xca, 0xab, 0x67, 0xfb, 0xfb, 0xd7, 0xd7, 0x8d, 0x02, 0x3f, 0x8d, 0x78, 0x7c, 0xce, 0x44, 0x67, 0x00, + 0xc0, 0x86, 0xbf, 0x33, 0xce, 0x46, 0xfb, 0xfc, 0x2a, 0x81, 0x52, 0xc6, 0x78, 0x61, 0x03, 0x8e, 0xcf, 0xb3, 0x21, + 0x90, 0x2d, 0x35, 0x08, 0x0f, 0x4d, 0x73, 0x36, 0x4b, 0xa2, 0x21, 0xc3, 0x7a, 0x18, 0xa9, 0xea, 0x51, 0x35, 0xf2, + 0xbe, 0x0b, 0xc5, 0xf2, 0x3a, 0xae, 0x97, 0xb1, 0x30, 0x65, 0x17, 0xd6, 0x9b, 0x68, 0xd6, 0x1b, 0x26, 0x51, 0x51, + 0x58, 0x29, 0x5b, 0x10, 0x0a, 0xf9, 0x7c, 0x08, 0x0c, 0x42, 0x08, 0x2e, 0x80, 0x4c, 0x7c, 0x12, 0x17, 0xfe, 0xf1, + 0xc6, 0xb0, 0x28, 0x3e, 0xb0, 0x62, 0x9e, 0xf0, 0x8d, 0x10, 0xd6, 0x82, 0xdd, 0x0b, 0xc3, 0xef, 0x5c, 0x3e, 0xc9, + 0xb3, 0x0b, 0xeb, 0x45, 0x9e, 0x43, 0x73, 0x1b, 0xa6, 0x14, 0x0d, 0xac, 0x18, 0xc6, 0xca, 0xb8, 0xa5, 0x07, 0xc3, + 0x05, 0xf4, 0xad, 0x8f, 0x05, 0xb3, 0x4e, 0xe6, 0x69, 0x11, 0x8d, 0x19, 0x34, 0x3d, 0xb1, 0xb2, 0xdc, 0x3a, 0x81, + 0x41, 0x4f, 0x60, 0xc9, 0x0a, 0x0e, 0xbb, 0xc6, 0xb7, 0xdd, 0x1e, 0xcd, 0x05, 0x85, 0x07, 0xec, 0x92, 0x87, 0xbc, + 0x04, 0xc6, 0xb4, 0x0a, 0x8d, 0x86, 0xe3, 0x2e, 0x12, 0x28, 0xe0, 0x61, 0xc6, 0x90, 0x65, 0x1d, 0xb3, 0xb1, 0x5e, + 0x9c, 0x2f, 0xee, 0xdf, 0xd7, 0xb4, 0x46, 0xc2, 0x43, 0xdb, 0xa2, 0xd1, 0xd6, 0xe3, 0x84, 0x78, 0x8d, 0x44, 0xae, + 0xc7, 0x7d, 0x49, 0xbe, 0xfd, 0xab, 0x74, 0x58, 0x1f, 0x1b, 0x2a, 0x4b, 0x9e, 0xed, 0xf3, 0x3c, 0x4e, 0xcf, 0x00, + 0x08, 0xc5, 0x06, 0x46, 0x93, 0xb2, 0x14, 0x8b, 0xff, 0x9e, 0x85, 0x3c, 0xec, 0xe3, 0xe8, 0x29, 0x73, 0xec, 0x82, + 0x7a, 0xd8, 0x00, 0x08, 0x90, 0x1e, 0x18, 0x8c, 0x0f, 0x78, 0xc0, 0x37, 0x6d, 0xdb, 0xfb, 0xce, 0xf5, 0xae, 0x90, + 0x83, 0x7c, 0xdf, 0x27, 0xf6, 0x15, 0x9d, 0xe3, 0xb0, 0x83, 0x40, 0xfb, 0x09, 0x4b, 0xcf, 0xf8, 0x64, 0xc0, 0x0f, + 0xdb, 0x47, 0x01, 0x03, 0xa8, 0x46, 0xf3, 0x21, 0x73, 0x90, 0x1f, 0xbd, 0x1c, 0xb7, 0xcf, 0xa6, 0x03, 0x53, 0xe0, + 0xc2, 0xdc, 0x23, 0x1c, 0x6b, 0x4b, 0xe3, 0x2a, 0xd8, 0x14, 0x60, 0xc8, 0xe7, 0x36, 0xec, 0xb0, 0x53, 0x96, 0x1b, + 0x70, 0xe8, 0x66, 0xbd, 0xda, 0x0a, 0xce, 0x61, 0x85, 0xa0, 0x9f, 0x35, 0x9e, 0xa7, 0x43, 0x1e, 0x83, 0xe0, 0xb2, + 0x37, 0x01, 0x5c, 0xb1, 0x72, 0x7a, 0xe1, 0x6c, 0xb7, 0x74, 0x9d, 0xd8, 0xdd, 0xe4, 0x87, 0xf9, 0x66, 0xe7, 0xc8, + 0x43, 0x28, 0x35, 0xf1, 0x25, 0xe2, 0x31, 0x20, 0x58, 0x7a, 0x1f, 0x99, 0xde, 0x9e, 0x5f, 0x0c, 0xb8, 0xbf, 0xcc, + 0xc7, 0x21, 0xf3, 0xa7, 0xd1, 0x0c, 0xb1, 0xe1, 0xc4, 0x03, 0x51, 0x3a, 0x44, 0xe8, 0x6a, 0xeb, 0x82, 0x14, 0xf3, + 0x2b, 0x16, 0x70, 0x81, 0x20, 0xb0, 0x67, 0x5f, 0x44, 0xc3, 0x09, 0x6c, 0xf1, 0x8a, 0x70, 0x23, 0xb5, 0x1d, 0x86, + 0x39, 0x8b, 0x38, 0x7b, 0x91, 0x30, 0x7c, 0xc3, 0x15, 0x80, 0x9e, 0xb6, 0xeb, 0xe5, 0x6a, 0xdf, 0x25, 0x31, 0x7f, + 0x9b, 0xc1, 0x3c, 0x3d, 0xc1, 0x24, 0xc0, 0xc5, 0xf9, 0xfd, 0xfb, 0x31, 0xb2, 0xc8, 0x1e, 0x87, 0xd5, 0x3a, 0x9d, + 0x73, 0x58, 0xb7, 0x14, 0x5b, 0xd8, 0x40, 0x6d, 0x2f, 0xf6, 0x39, 0x10, 0xf1, 0x59, 0x96, 0x72, 0x18, 0x0e, 0xe0, + 0xd5, 0x1c, 0xe4, 0x47, 0xb3, 0x19, 0x4b, 0x47, 0xcf, 0x26, 0x71, 0x32, 0x02, 0x6a, 0x94, 0x80, 0x6f, 0xc2, 0x42, + 0xc0, 0x13, 0x90, 0x09, 0x6e, 0xc6, 0x88, 0x96, 0x0f, 0x19, 0x99, 0x85, 0xb6, 0xdd, 0x43, 0x09, 0x24, 0xb1, 0x40, + 0x19, 0x44, 0x0b, 0xf7, 0x01, 0x44, 0x7f, 0xe1, 0xb2, 0xcd, 0x30, 0xd6, 0xcb, 0x28, 0x09, 0xfc, 0x1e, 0x25, 0x0d, + 0xd0, 0x1f, 0x08, 0xc1, 0x7b, 0x28, 0xb8, 0xbe, 0x92, 0x52, 0x27, 0x62, 0x0a, 0x43, 0x20, 0xc0, 0x10, 0x25, 0x88, + 0xa4, 0xc1, 0xfb, 0x2c, 0xb9, 0x1a, 0xc7, 0x49, 0xb2, 0x3f, 0x9f, 0xcd, 0xb2, 0x9c, 0x7b, 0x5f, 0x87, 0x0b, 0x9e, + 0x55, 0xb8, 0xd2, 0x26, 0x2f, 0x2e, 0x62, 0x8e, 0x04, 0x75, 0x17, 0xc3, 0x08, 0x96, 0xfa, 0x69, 0x96, 0x25, 0x2c, + 0x4a, 0x01, 0x0d, 0x3e, 0xb0, 0xed, 0x20, 0x9d, 0x27, 0x49, 0xef, 0x14, 0x86, 0xfd, 0xd4, 0xa3, 0x6a, 0x21, 0xf1, + 0x03, 0x7a, 0xde, 0xcb, 0xf3, 0xe8, 0x0a, 0x1a, 0x62, 0x1b, 0x60, 0x2f, 0x58, 0xad, 0xaf, 0xf6, 0xdf, 0xbd, 0xf5, + 0x05, 0xe3, 0xc7, 0xe3, 0x2b, 0x00, 0xb4, 0xac, 0xa4, 0xe6, 0x38, 0xcf, 0xa6, 0x8d, 0xa9, 0x91, 0x0e, 0x71, 0xc8, + 0x7b, 0x6b, 0x40, 0x88, 0x69, 0x64, 0x58, 0x25, 0x6e, 0x42, 0xf0, 0x96, 0xf8, 0x59, 0x56, 0xe2, 0x1e, 0x18, 0xe0, + 0x43, 0x20, 0x8a, 0x61, 0xca, 0x5b, 0xa0, 0xcd, 0xaf, 0x16, 0x71, 0x48, 0x70, 0xce, 0x50, 0xff, 0x22, 0x8c, 0xc3, + 0x08, 0x66, 0x5f, 0x88, 0x01, 0x4b, 0x05, 0x71, 0x5c, 0x96, 0xde, 0x44, 0x33, 0x31, 0x4a, 0x3c, 0x14, 0x28, 0x2c, + 0x0c, 0x41, 0xc1, 0x70, 0x78, 0x71, 0xbd, 0x6f, 0xc2, 0x45, 0xa4, 0xf0, 0x41, 0x0d, 0x85, 0xfb, 0x2b, 0x10, 0x72, + 0x02, 0x35, 0xd9, 0x39, 0xe8, 0x41, 0x80, 0xf3, 0x6b, 0x50, 0x7f, 0xe3, 0x04, 0xa1, 0xb8, 0xd7, 0xf1, 0x40, 0x83, + 0x3e, 0x9b, 0x44, 0xe9, 0x19, 0x1b, 0x05, 0x13, 0x56, 0x4a, 0xc9, 0xbb, 0x67, 0xc1, 0x1a, 0x03, 0x3b, 0x15, 0xd6, + 0xcb, 0x83, 0x37, 0xaf, 0xe5, 0xca, 0xd5, 0x84, 0x31, 0x2c, 0xd2, 0x1c, 0xd4, 0x2a, 0x88, 0x6d, 0x29, 0x8e, 0x5f, + 0x70, 0x25, 0xbd, 0x45, 0x49, 0x5c, 0x7c, 0x9c, 0x81, 0x89, 0xc1, 0xde, 0xc3, 0x30, 0x30, 0x7d, 0x08, 0x53, 0x51, + 0x39, 0xcc, 0x27, 0x2a, 0x46, 0xba, 0x08, 0x3a, 0x0b, 0x4c, 0xc5, 0x6b, 0xe6, 0xb8, 0x25, 0xb0, 0x2a, 0x8f, 0x87, + 0x56, 0x34, 0x1a, 0xbd, 0x4a, 0x63, 0x1e, 0x47, 0x49, 0xfc, 0x0b, 0x51, 0x72, 0x81, 0x3c, 0xc6, 0x7a, 0x72, 0x11, + 0x00, 0x77, 0xea, 0x91, 0xb8, 0x4a, 0xc8, 0xde, 0x23, 0x62, 0x08, 0x69, 0x99, 0x84, 0x87, 0x47, 0x12, 0xbc, 0xc4, + 0x9f, 0xcd, 0x8b, 0x09, 0x12, 0x56, 0x0e, 0x8c, 0x82, 0x3c, 0x3b, 0x2d, 0x58, 0x7e, 0xce, 0x46, 0x9a, 0x03, 0x0a, + 0xc0, 0x8a, 0x9a, 0x83, 0xf1, 0x42, 0x33, 0x3a, 0x4a, 0x87, 0x72, 0x18, 0xaa, 0x67, 0x8a, 0x59, 0x26, 0x99, 0x59, + 0x5b, 0x38, 0x5a, 0x0a, 0x38, 0xc2, 0xa8, 0x90, 0x92, 0x20, 0x0f, 0x15, 0x86, 0x13, 0x90, 0x42, 0xcc, 0xad, 0x6d, + 0x73, 0xa5, 0xc9, 0x5e, 0xcc, 0x49, 0x25, 0xe4, 0xd0, 0x11, 0x36, 0x32, 0x41, 0x9a, 0xbb, 0xb0, 0xab, 0x40, 0xca, + 0x4b, 0x70, 0x85, 0x14, 0x51, 0x66, 0x0e, 0x32, 0x40, 0xf8, 0x0d, 0xe9, 0x42, 0x50, 0x26, 0xd0, 0x82, 0x21, 0x1b, + 0xf8, 0x7a, 0xe5, 0x81, 0xb0, 0x12, 0xef, 0x0a, 0x11, 0x6f, 0x0d, 0xd8, 0xa4, 0x8b, 0x00, 0x30, 0xef, 0x1e, 0xf3, + 0xd3, 0x6c, 0x6f, 0x38, 0x64, 0x45, 0x91, 0x01, 0x6c, 0xf7, 0xa8, 0xfd, 0x3a, 0x43, 0x0b, 0x28, 0xe9, 0x6a, 0x59, + 0x67, 0x17, 0xa4, 0xc1, 0x4d, 0xb5, 0xa2, 0x74, 0x7a, 0x60, 0x1f, 0x1f, 0x83, 0xcc, 0xf6, 0x24, 0x19, 0x80, 0xea, + 0xcb, 0x86, 0x9f, 0xb0, 0x67, 0xea, 0x94, 0x59, 0x69, 0x5f, 0x3a, 0x75, 0x90, 0x3c, 0x18, 0xd6, 0x2d, 0x8d, 0x05, + 0x5d, 0x39, 0x34, 0xae, 0x86, 0x54, 0x90, 0x8b, 0x33, 0x52, 0xd9, 0xc6, 0x32, 0x82, 0xd5, 0x56, 0x7a, 0x44, 0x7a, + 0x85, 0x4d, 0x41, 0x80, 0x1e, 0xf2, 0xa3, 0x9e, 0xac, 0x0f, 0x73, 0x41, 0xb9, 0x9c, 0xfd, 0x3c, 0x67, 0x05, 0x17, + 0xac, 0x0b, 0xe3, 0x82, 0xb9, 0x0a, 0x22, 0xb6, 0x69, 0x1d, 0xd6, 0x6c, 0xc7, 0x55, 0xb0, 0xbd, 0x9b, 0xa1, 0x1e, + 0x2b, 0x90, 0x93, 0x6f, 0x66, 0x27, 0xb2, 0x27, 0xdc, 0xeb, 0xeb, 0x6f, 0xd4, 0x20, 0xd5, 0x52, 0x6a, 0x1b, 0xa8, + 0xb1, 0x26, 0xb6, 0x6a, 0x32, 0xb2, 0x5d, 0xa9, 0x50, 0xef, 0x75, 0x7a, 0x35, 0x3e, 0x80, 0x3d, 0xd7, 0xd6, 0x2c, + 0x5d, 0x19, 0xdb, 0xef, 0x15, 0x4d, 0xdf, 0x89, 0x91, 0xc9, 0x1a, 0xe5, 0xb7, 0x73, 0x8f, 0xda, 0xf1, 0xd0, 0x76, + 0xa9, 0xae, 0x12, 0x0c, 0xf3, 0xba, 0x60, 0x68, 0x42, 0x3d, 0xd3, 0x5d, 0x6c, 0xcd, 0x54, 0x3c, 0x54, 0x6b, 0xad, + 0x1c, 0x08, 0x16, 0x1e, 0x82, 0x71, 0xb2, 0xd2, 0x3f, 0x78, 0x1b, 0x4d, 0x19, 0x52, 0xd4, 0x5b, 0xd7, 0x40, 0x3a, + 0x10, 0xd0, 0xe4, 0xa8, 0xa9, 0xde, 0x98, 0x2b, 0xac, 0xa6, 0xfa, 0xfe, 0x8a, 0xc1, 0x8a, 0x00, 0xfb, 0xba, 0x5c, + 0xb1, 0x44, 0xa4, 0x37, 0x05, 0x97, 0x68, 0xfa, 0x88, 0x32, 0xb1, 0x26, 0xa4, 0xe0, 0x01, 0x79, 0x58, 0xfe, 0xc6, + 0xc2, 0xa9, 0x56, 0x0a, 0x47, 0x86, 0x32, 0x05, 0xe8, 0x4c, 0x4a, 0x00, 0xc4, 0x25, 0xfd, 0xad, 0x6d, 0x2c, 0x24, + 0xdb, 0x3e, 0xf2, 0x81, 0x3f, 0x4e, 0x22, 0xee, 0x74, 0xb6, 0xda, 0x2e, 0xf0, 0x21, 0x08, 0x71, 0xd0, 0x11, 0x60, + 0xde, 0x57, 0xa8, 0x70, 0xf2, 0x16, 0x5c, 0xe6, 0x83, 0x51, 0x34, 0x89, 0xc7, 0xdc, 0x49, 0x50, 0x89, 0xb8, 0x25, + 0x4b, 0x40, 0xc9, 0xe8, 0x7d, 0x05, 0xca, 0x82, 0x09, 0xe9, 0x22, 0xaa, 0x95, 0x40, 0x63, 0x0a, 0x52, 0x92, 0x52, + 0xa4, 0x05, 0x15, 0x04, 0x86, 0x50, 0xe9, 0x29, 0x8e, 0x02, 0xfd, 0x16, 0x0f, 0xc4, 0xa0, 0xc1, 0x92, 0x45, 0x19, + 0x0f, 0xe2, 0xe5, 0x42, 0x50, 0xc3, 0x3e, 0xcf, 0x5e, 0x67, 0x17, 0x2c, 0x7f, 0x16, 0x21, 0xec, 0x81, 0xe8, 0x5e, + 0x82, 0xa4, 0x27, 0x81, 0xce, 0x7b, 0x8a, 0x57, 0xce, 0x09, 0x69, 0x58, 0x88, 0x69, 0x8c, 0x8a, 0x10, 0xec, 0x16, + 0xa2, 0x7d, 0x8a, 0x5b, 0x8a, 0xf6, 0x1e, 0xaa, 0x12, 0xae, 0x79, 0x6b, 0xef, 0x75, 0x9d, 0xb7, 0x60, 0x84, 0x99, + 0xe2, 0xd6, 0xfa, 0x8e, 0x75, 0x3d, 0xa9, 0x9b, 0x1d, 0xc9, 0x5b, 0x86, 0x32, 0x03, 0xfd, 0x71, 0x7d, 0x5d, 0x19, + 0xe9, 0xa0, 0x4c, 0xb5, 0x34, 0x47, 0x08, 0xc4, 0x96, 0x70, 0x4b, 0x50, 0x46, 0x68, 0x78, 0xe5, 0x59, 0x92, 0x18, + 0xba, 0xc8, 0x8b, 0x7b, 0x4e, 0x43, 0x1d, 0x01, 0x14, 0xd3, 0x9a, 0x46, 0x1a, 0xb0, 0x40, 0x57, 0xa0, 0x52, 0x52, + 0xda, 0xc8, 0xab, 0xd6, 0x46, 0x40, 0x9c, 0x8e, 0x58, 0x2e, 0x1c, 0x34, 0xa9, 0x43, 0x61, 0xc2, 0x14, 0x18, 0x9a, + 0x8d, 0x40, 0xc2, 0x2b, 0x04, 0xc0, 0x3c, 0xf1, 0x27, 0x59, 0xc1, 0x75, 0x9d, 0x09, 0x7d, 0x7c, 0x7d, 0x1d, 0x0b, + 0x7f, 0x11, 0x19, 0x20, 0x67, 0xd3, 0xec, 0x9c, 0xad, 0x80, 0xba, 0xa7, 0x06, 0x33, 0x41, 0x36, 0x86, 0x01, 0x25, + 0x0a, 0xaa, 0x65, 0x96, 0xc4, 0x60, 0xe9, 0xeb, 0x06, 0x3e, 0x18, 0x74, 0xec, 0x12, 0x65, 0x84, 0xdb, 0xef, 0xf7, + 0xdb, 0x5e, 0xc7, 0x2d, 0x05, 0xc1, 0x17, 0x4b, 0x14, 0xbd, 0x41, 0x3f, 0x4a, 0x13, 0x7c, 0x95, 0x2c, 0x60, 0xae, + 0xa1, 0x14, 0x39, 0xe9, 0x26, 0xe6, 0x49, 0x41, 0xec, 0x7a, 0x23, 0x18, 0x94, 0x33, 0x25, 0xb8, 0xd1, 0xc4, 0x15, 0xdb, 0xf6, 0x83, 0x26, 0x9b, 0x66, 0x27, 0xb5, 0xc3, 0xd4, 0xc2, 0xc8, 0x35, 0x2f, 0xb4, 0x07, 0x6c, 0x2e, 0x0f, - 0x5a, 0x89, 0x54, 0x0d, 0xbc, 0x0e, 0x10, 0x0a, 0x4f, 0xd7, 0x59, 0x42, 0xa9, 0xea, 0x2c, 0x85, 0xb8, 0xde, 0x40, - 0x1f, 0x99, 0x04, 0x73, 0x15, 0x09, 0xf6, 0xa5, 0x40, 0xe0, 0xe8, 0x91, 0x89, 0xf5, 0x7a, 0x06, 0xcb, 0x73, 0x1a, - 0x0d, 0x3f, 0x69, 0x70, 0x2b, 0xb2, 0x37, 0xd9, 0xc0, 0x69, 0x94, 0x84, 0x86, 0xb8, 0x32, 0xf1, 0x56, 0x12, 0xba, - 0xb6, 0x51, 0xc0, 0x21, 0x5b, 0x62, 0xfb, 0xe6, 0x42, 0x37, 0xb9, 0x5d, 0xb2, 0x87, 0xf2, 0x9f, 0x34, 0x97, 0xdc, - 0xc0, 0x72, 0x5c, 0x49, 0x03, 0xae, 0x18, 0x0f, 0x96, 0xa6, 0x01, 0x09, 0xf0, 0x5d, 0x39, 0x8a, 0x8b, 0xf5, 0x24, - 0xf8, 0x5d, 0xc1, 0x7c, 0x6e, 0xcc, 0x74, 0x2b, 0xa4, 0x5a, 0xc2, 0x49, 0x33, 0x58, 0x83, 0x26, 0x8d, 0x07, 0x25, - 0x6a, 0xbe, 0x46, 0x43, 0x85, 0x38, 0xfe, 0x4c, 0x54, 0xa1, 0x09, 0x86, 0x60, 0xe4, 0x5e, 0x21, 0x19, 0x2e, 0x5b, - 0x16, 0x2d, 0x52, 0xa6, 0xc6, 0xa4, 0x52, 0x35, 0xcb, 0x65, 0x60, 0x60, 0xd1, 0x6e, 0xf5, 0xa5, 0x25, 0xae, 0x44, - 0x6e, 0x1a, 0x6a, 0x61, 0x52, 0x28, 0x6f, 0xc2, 0xc9, 0xd1, 0xef, 0x52, 0xd6, 0xbb, 0x89, 0x4f, 0xae, 0xf0, 0xc9, - 0x7d, 0xc3, 0x87, 0x32, 0x79, 0xbb, 0x18, 0x14, 0xc1, 0xd7, 0xb5, 0x4a, 0xb4, 0x4f, 0x7d, 0x14, 0xcc, 0xae, 0x16, - 0xba, 0x20, 0x50, 0x24, 0x9b, 0xa4, 0x03, 0xc9, 0x6f, 0x28, 0x36, 0x2a, 0xcf, 0x28, 0x73, 0xc5, 0x06, 0xa9, 0x79, - 0xa5, 0x99, 0x97, 0xba, 0x0d, 0xfb, 0xbd, 0x2c, 0x25, 0x9d, 0xb8, 0xa0, 0x4c, 0xec, 0xdd, 0x44, 0x1b, 0x2f, 0x0d, - 0x33, 0x61, 0xfd, 0x0a, 0x63, 0xa7, 0x46, 0xa1, 0x54, 0x8a, 0x40, 0x1c, 0x1b, 0x5f, 0x2b, 0xcb, 0x20, 0xf3, 0x57, - 0xd8, 0x53, 0x00, 0x4a, 0x02, 0x8b, 0xaf, 0xa9, 0xe4, 0x45, 0x61, 0x9d, 0x8e, 0xf7, 0x88, 0x8e, 0x95, 0x08, 0xad, - 0x89, 0x7c, 0xad, 0xcf, 0x62, 0xbf, 0xe6, 0x12, 0x9a, 0x94, 0xcc, 0x07, 0x79, 0x60, 0xab, 0x40, 0x44, 0xa5, 0xdb, - 0x92, 0x41, 0x42, 0x0e, 0xe9, 0x32, 0xd1, 0x6b, 0x23, 0x19, 0xb4, 0x4e, 0x85, 0x44, 0x4b, 0x8f, 0xc2, 0xc8, 0x41, - 0xc7, 0x9d, 0xd6, 0x62, 0x89, 0x90, 0x4d, 0x7b, 0x93, 0x58, 0x11, 0x9d, 0xd3, 0x1c, 0x4d, 0x38, 0x53, 0xa7, 0x3b, - 0x0e, 0xa0, 0x03, 0x62, 0x7f, 0x89, 0xf5, 0x56, 0x9a, 0x9d, 0xae, 0x5f, 0x39, 0x7c, 0xd7, 0xd7, 0x13, 0xe4, 0x07, - 0x61, 0xf0, 0xc2, 0x9a, 0x0d, 0x94, 0xec, 0xdd, 0x7b, 0x8d, 0xad, 0xc8, 0xfe, 0xac, 0x4a, 0x2a, 0x4f, 0xa1, 0xc6, - 0xb9, 0xf5, 0x75, 0x62, 0x66, 0x68, 0x51, 0x55, 0xec, 0x1b, 0x52, 0x7d, 0x5f, 0x29, 0xec, 0x0a, 0xe5, 0x7d, 0x39, - 0x74, 0xec, 0xba, 0x6e, 0x90, 0x93, 0xf3, 0x72, 0x6f, 0x95, 0x0b, 0x79, 0xff, 0xbe, 0xe9, 0x33, 0x9d, 0xeb, 0xe1, - 0x9f, 0x39, 0xa8, 0x9c, 0x8b, 0xab, 0x94, 0x2c, 0x98, 0x67, 0x4a, 0x1d, 0x2d, 0x39, 0xa0, 0xed, 0x1e, 0x7a, 0xda, - 0xd1, 0x45, 0x14, 0x73, 0x4b, 0x8f, 0x22, 0x3c, 0x6d, 0x94, 0x4f, 0xd2, 0xe8, 0x00, 0xbc, 0xd0, 0x84, 0x24, 0x27, - 0xdc, 0xb4, 0x45, 0x8b, 0xe1, 0x84, 0x61, 0x08, 0x5c, 0xd9, 0x13, 0xa6, 0xec, 0xb9, 0x87, 0x78, 0x8b, 0x81, 0xd9, - 0x6a, 0xd8, 0xcb, 0x66, 0xf7, 0x9a, 0xf9, 0x0f, 0x6b, 0x04, 0xb2, 0x6d, 0xaa, 0xea, 0xca, 0xc6, 0xbb, 0x14, 0x91, - 0x18, 0x61, 0x5b, 0x35, 0xb6, 0xb4, 0xf5, 0x7b, 0x0d, 0xf7, 0xba, 0x72, 0xcc, 0x6b, 0x4a, 0xb5, 0xa1, 0x87, 0x95, - 0x9b, 0xc3, 0x4c, 0x47, 0x5e, 0xac, 0xa0, 0xdb, 0x13, 0x41, 0x21, 0x70, 0x22, 0xb4, 0x3d, 0xa8, 0xb8, 0x81, 0x48, - 0xc9, 0x95, 0x56, 0xcd, 0xe6, 0xc9, 0x48, 0x02, 0x0b, 0x2e, 0x2c, 0x97, 0x7c, 0x74, 0x11, 0x27, 0x49, 0x55, 0xfa, - 0xbb, 0x0a, 0x78, 0x31, 0xec, 0x6d, 0xa2, 0x5d, 0x60, 0x34, 0x57, 0x20, 0xb8, 0xda, 0x08, 0xfb, 0xe8, 0xb8, 0xd5, - 0xba, 0x8b, 0x88, 0x23, 0x37, 0xa3, 0x11, 0x50, 0x8f, 0x11, 0x56, 0xcd, 0xda, 0x7b, 0x2f, 0x30, 0xa4, 0x66, 0xe0, - 0x83, 0xea, 0x8c, 0x8a, 0x7f, 0x95, 0x3d, 0xf5, 0x2b, 0xd1, 0xbb, 0x55, 0x75, 0x35, 0x03, 0x2a, 0x2a, 0xf0, 0x61, - 0x86, 0x58, 0xda, 0x2a, 0x10, 0x90, 0xeb, 0x61, 0x51, 0x0a, 0x98, 0xa4, 0xc1, 0x82, 0x52, 0x60, 0xad, 0x95, 0xdd, - 0xeb, 0xdb, 0x82, 0x39, 0x14, 0x0a, 0x17, 0xfd, 0x9f, 0x65, 0xd3, 0x19, 0x5a, 0x66, 0x0d, 0xa6, 0x86, 0x06, 0x1f, - 0x1b, 0xf5, 0xe5, 0x8a, 0xb2, 0x5a, 0x1f, 0xda, 0x91, 0x35, 0x7e, 0xd2, 0x8e, 0x32, 0x38, 0x54, 0x73, 0x5d, 0x54, - 0xb7, 0x9b, 0x9b, 0x22, 0x66, 0x15, 0x8f, 0xfb, 0xa4, 0xb7, 0xb5, 0x35, 0xe9, 0x69, 0x1a, 0x90, 0x4c, 0x92, 0x0c, - 0x6f, 0x32, 0x40, 0x59, 0x11, 0x67, 0x51, 0x36, 0xc8, 0xb7, 0x28, 0x4b, 0x5c, 0xbf, 0x1f, 0x7a, 0x7b, 0x35, 0xcf, - 0xda, 0xdb, 0x5b, 0xef, 0x22, 0x57, 0x75, 0xd2, 0x83, 0x3c, 0x3c, 0x82, 0xa2, 0x25, 0x9b, 0x32, 0x5c, 0x4c, 0xb3, - 0x11, 0x0b, 0x6c, 0xe8, 0x9e, 0xda, 0xa5, 0xdc, 0x34, 0x11, 0x6c, 0x8e, 0x88, 0x39, 0x8b, 0x0f, 0xf5, 0x48, 0x6a, - 0xb0, 0x07, 0x2c, 0xa0, 0xcd, 0x85, 0xaf, 0xc2, 0xb3, 0x24, 0x3b, 0x8d, 0x92, 0x03, 0xa1, 0xc0, 0x6b, 0x2d, 0xbf, - 0x05, 0x97, 0x91, 0x2c, 0x56, 0x43, 0x49, 0x7d, 0x35, 0xf8, 0x2a, 0xb8, 0xbd, 0x47, 0xe5, 0xad, 0xd8, 0x1d, 0xbf, - 0xed, 0x77, 0x6c, 0x15, 0x11, 0xfb, 0xc9, 0x9c, 0x0e, 0x34, 0x4e, 0x01, 0x94, 0x39, 0x00, 0x4d, 0x56, 0x78, 0x43, - 0x16, 0xfe, 0x34, 0xf8, 0x49, 0xb9, 0xd4, 0x19, 0xb8, 0x10, 0xe0, 0xe4, 0x27, 0x31, 0x6f, 0xe1, 0x79, 0xa4, 0xed, - 0x2d, 0x44, 0x05, 0xc6, 0x15, 0x29, 0x2e, 0x5d, 0x2a, 0x6f, 0xd0, 0x3b, 0x0e, 0x4f, 0xa0, 0xd9, 0xc6, 0xc6, 0xc2, - 0x79, 0x13, 0xf1, 0x89, 0x9f, 0x47, 0xe9, 0x28, 0x9b, 0x3a, 0xee, 0xa6, 0x6d, 0xbb, 0x7e, 0x41, 0x9e, 0xc8, 0xe7, - 0x6e, 0xb9, 0x71, 0x02, 0x7e, 0x40, 0x68, 0x0f, 0xec, 0xcd, 0x63, 0xef, 0x80, 0x85, 0x27, 0xbb, 0x1b, 0x8b, 0x11, - 0x2b, 0xfb, 0x27, 0xde, 0xa5, 0x8e, 0xb9, 0x7b, 0xef, 0x51, 0xca, 0x40, 0xaf, 0xb0, 0x7f, 0x29, 0xc1, 0x00, 0x76, - 0xa3, 0xf8, 0x3b, 0x48, 0xb9, 0x8f, 0x74, 0x20, 0x22, 0xe3, 0xb4, 0xd7, 0xd7, 0x76, 0x46, 0x11, 0x03, 0xfb, 0x9e, - 0x76, 0x56, 0xef, 0xdf, 0xaf, 0xd4, 0x7c, 0x55, 0xea, 0xcd, 0x59, 0x58, 0xf3, 0xd4, 0xbd, 0x97, 0x74, 0xb4, 0x52, - 0xdf, 0xc8, 0x73, 0x46, 0x4a, 0x73, 0xd9, 0x4e, 0x70, 0x8c, 0x2d, 0xbe, 0x7a, 0x5b, 0x1f, 0x8a, 0x28, 0x85, 0x1f, - 0x83, 0xf5, 0x12, 0x81, 0xfa, 0x06, 0x07, 0xc7, 0x3b, 0x08, 0xb7, 0x76, 0x9d, 0x41, 0xe0, 0xdc, 0x6b, 0xb5, 0xae, - 0x7f, 0xdc, 0x3a, 0xfc, 0x73, 0xd4, 0xfa, 0x65, 0xaf, 0xf5, 0xc3, 0x91, 0x7b, 0xed, 0xfc, 0xb8, 0x35, 0x38, 0x94, - 0x6f, 0x87, 0x7f, 0xee, 0xff, 0x58, 0x1c, 0xfd, 0x41, 0x14, 0x6e, 0xb8, 0xee, 0xd6, 0x99, 0x37, 0x63, 0xe1, 0x56, - 0xab, 0xd5, 0x87, 0xa7, 0x33, 0x78, 0xc2, 0xbf, 0x17, 0xf0, 0xe7, 0xfa, 0xd0, 0xfa, 0x4f, 0x3f, 0xa6, 0xff, 0xf9, - 0xc7, 0xfc, 0x08, 0xc7, 0x3c, 0xfc, 0xf3, 0x8f, 0x85, 0xfd, 0xa0, 0x1f, 0x6e, 0x1d, 0x6d, 0xba, 0x8e, 0xae, 0xf9, - 0x43, 0x58, 0x3d, 0x42, 0xab, 0xc3, 0x3f, 0xcb, 0x37, 0xfb, 0xc1, 0xc9, 0x6e, 0x3f, 0x3c, 0xba, 0x76, 0xec, 0xeb, - 0x07, 0xee, 0xb5, 0xeb, 0x5e, 0x6f, 0xe0, 0x3c, 0xe7, 0x30, 0xfa, 0x03, 0xf8, 0x3b, 0x86, 0xbf, 0x36, 0xfc, 0x9d, - 0xc2, 0xdf, 0x3f, 0x43, 0x37, 0x11, 0x7f, 0xbb, 0xa6, 0x58, 0xc8, 0x35, 0x1e, 0x58, 0x44, 0xb0, 0x0a, 0xee, 0xc6, - 0x56, 0xec, 0x6d, 0x10, 0xd1, 0x60, 0x1f, 0xfa, 0xbe, 0x8f, 0x61, 0x52, 0x67, 0x71, 0xbc, 0x01, 0x8b, 0x8e, 0x9c, - 0xb3, 0x11, 0x30, 0x4f, 0x44, 0x0e, 0x8a, 0x80, 0x8b, 0xb3, 0xd5, 0x02, 0x0f, 0x57, 0xbd, 0x61, 0xb8, 0xc1, 0x1c, - 0x30, 0x0a, 0xde, 0x32, 0x7c, 0xe8, 0xba, 0xde, 0x0b, 0x79, 0x66, 0x88, 0xfb, 0x5c, 0xb0, 0x56, 0x9a, 0x09, 0x93, - 0xc6, 0x76, 0xbd, 0xd9, 0x8a, 0x4a, 0xd8, 0xd6, 0xe9, 0x19, 0xd4, 0x9d, 0x8a, 0x83, 0xb6, 0xef, 0x58, 0xf4, 0x09, - 0xb7, 0xe4, 0x1b, 0xe3, 0x10, 0x78, 0xc9, 0x92, 0x6f, 0x1a, 0x8d, 0x86, 0x8d, 0x28, 0xdc, 0xb1, 0xa7, 0x0c, 0x66, - 0x58, 0x32, 0x11, 0x39, 0x29, 0x4d, 0x61, 0xd9, 0xc2, 0xe4, 0xef, 0xa3, 0x9c, 0x6f, 0x54, 0x86, 0x6d, 0x58, 0xb3, - 0x64, 0x9b, 0x96, 0xfe, 0x1d, 0xa6, 0x40, 0xd3, 0x92, 0xce, 0x3f, 0xcc, 0xf1, 0xc3, 0x94, 0xd0, 0x7a, 0xeb, 0x70, - 0xf0, 0xd0, 0x0b, 0x90, 0x3b, 0xa2, 0x9f, 0xf3, 0x1e, 0xd5, 0x18, 0xfc, 0x2b, 0xc3, 0x0c, 0x9e, 0x98, 0x0f, 0x43, - 0x34, 0x8b, 0x52, 0x07, 0xb7, 0x52, 0x14, 0xf7, 0xaf, 0x70, 0x67, 0xa4, 0xa5, 0xb7, 0x1f, 0xaa, 0x1d, 0x73, 0x90, - 0x33, 0xf6, 0x5d, 0x94, 0x7c, 0x62, 0xb9, 0x73, 0xe9, 0x75, 0xba, 0x9f, 0x53, 0x67, 0x0f, 0x6d, 0xb3, 0x0f, 0xd5, - 0x31, 0x9a, 0x32, 0x0b, 0xd4, 0x11, 0x61, 0xab, 0xe3, 0xe5, 0x18, 0xd5, 0x42, 0x12, 0x14, 0x5e, 0x16, 0x76, 0x89, - 0xc3, 0xed, 0xdd, 0xe2, 0xfc, 0xac, 0x6f, 0x07, 0xb6, 0x0d, 0x16, 0xff, 0x01, 0x85, 0xad, 0x84, 0x61, 0x01, 0x06, - 0xd9, 0x6e, 0xdc, 0xe3, 0x9b, 0x9b, 0x55, 0xc0, 0x09, 0x0f, 0xd2, 0xa9, 0x7b, 0xe2, 0x45, 0xde, 0x24, 0x84, 0x01, - 0x87, 0xd0, 0x0c, 0xbb, 0xf4, 0x86, 0xbb, 0xb1, 0x9c, 0x06, 0x63, 0x21, 0x7e, 0x12, 0x15, 0xfc, 0x15, 0xc6, 0x23, - 0xc2, 0x21, 0x1a, 0xfb, 0x3e, 0xbb, 0x64, 0x43, 0x65, 0x67, 0x00, 0xa1, 0x22, 0xb7, 0xe7, 0x0e, 0x43, 0xa3, 0x19, - 0xcc, 0x1d, 0x86, 0x07, 0x03, 0x1b, 0xf6, 0x12, 0xec, 0xca, 0x30, 0x3a, 0xec, 0x1c, 0x0d, 0xd2, 0x70, 0xc6, 0x02, - 0x4d, 0x5b, 0x59, 0x74, 0x56, 0x2b, 0xea, 0x1e, 0x0d, 0x9c, 0x29, 0x18, 0xe9, 0x60, 0x8b, 0x3b, 0xf8, 0x86, 0x11, - 0x8a, 0x22, 0xfc, 0xc0, 0xce, 0x5e, 0x5c, 0xce, 0x1c, 0x7b, 0x77, 0xcb, 0xde, 0xc4, 0x52, 0xcf, 0x06, 0xf6, 0x82, - 0xb9, 0xc3, 0x0b, 0xd7, 0xec, 0xbc, 0x7d, 0x84, 0xa0, 0x62, 0x21, 0x4e, 0x7e, 0x31, 0xb0, 0xfb, 0x62, 0xea, 0x36, - 0x0c, 0x9a, 0xca, 0xe5, 0xc7, 0x15, 0x3d, 0x20, 0x54, 0x55, 0x57, 0x05, 0x1d, 0x94, 0x75, 0x03, 0x67, 0x62, 0x22, - 0xd1, 0xc2, 0xc9, 0x24, 0x15, 0xc0, 0xe1, 0xc1, 0x66, 0x30, 0xa9, 0xd1, 0x6d, 0xfb, 0x68, 0x70, 0x11, 0x3c, 0xb0, - 0x1f, 0xa8, 0x97, 0x31, 0x20, 0xc3, 0xc4, 0xf4, 0x63, 0x90, 0x76, 0xf8, 0xf7, 0x9c, 0x01, 0x92, 0x17, 0x54, 0x34, - 0x93, 0x45, 0x67, 0x58, 0x74, 0x10, 0x20, 0xa8, 0x5e, 0xa1, 0xad, 0x3f, 0xb1, 0x26, 0xa3, 0x90, 0x60, 0xbf, 0x7f, - 0x1f, 0x96, 0x66, 0xb3, 0x73, 0x84, 0xe7, 0x0d, 0x39, 0x2f, 0xbe, 0x8b, 0x39, 0xa8, 0x84, 0xad, 0xbe, 0xed, 0x0e, - 0x6c, 0x0b, 0x97, 0xb6, 0x97, 0x6d, 0x86, 0x82, 0xc2, 0xf1, 0xe6, 0x01, 0x0b, 0x26, 0xfd, 0xb0, 0x3d, 0x70, 0x72, - 0x19, 0x6e, 0xc4, 0x73, 0x4b, 0x21, 0xc1, 0xdb, 0xde, 0x04, 0x04, 0x3a, 0x72, 0xee, 0x86, 0xbd, 0xa9, 0x0a, 0xa1, - 0xe8, 0x78, 0x73, 0xe4, 0x06, 0x31, 0xfc, 0x71, 0x5a, 0xc8, 0x34, 0x13, 0xdd, 0x57, 0x6b, 0x66, 0x37, 0x18, 0x29, - 0x8b, 0x3c, 0x09, 0xb3, 0x4d, 0x07, 0x23, 0xb4, 0x20, 0x69, 0x77, 0x07, 0x00, 0xc3, 0xa6, 0xa3, 0x38, 0x6d, 0x4b, - 0xb1, 0x9a, 0xb2, 0xcf, 0x0f, 0xf5, 0x72, 0x0c, 0xd9, 0x60, 0xc8, 0xfc, 0x4a, 0xfb, 0x00, 0x58, 0x41, 0xe2, 0xe5, - 0x47, 0xea, 0xcc, 0xeb, 0x65, 0xed, 0x7c, 0x6b, 0xa1, 0x44, 0x11, 0xf3, 0x0c, 0x09, 0xc5, 0x4b, 0xed, 0x86, 0x09, - 0x73, 0x7b, 0x86, 0xc4, 0xd0, 0x2c, 0x1f, 0xb6, 0x81, 0xe9, 0x55, 0x80, 0x3d, 0x35, 0xb7, 0x45, 0x12, 0x56, 0xcd, - 0xbd, 0x43, 0x60, 0xed, 0x23, 0xe0, 0x21, 0xda, 0x46, 0x3d, 0x15, 0xcd, 0x67, 0x49, 0xf8, 0xb2, 0x71, 0x5c, 0x1c, - 0xe1, 0x89, 0xd0, 0xbe, 0x3f, 0x9c, 0xe7, 0x20, 0x0f, 0xf8, 0x5b, 0xb0, 0x0c, 0x42, 0xd9, 0x14, 0x1d, 0x3d, 0x3c, - 0x02, 0xf6, 0x08, 0xf1, 0x46, 0xd8, 0xdc, 0xa8, 0x46, 0x8b, 0x92, 0x8c, 0x17, 0x3a, 0x18, 0xee, 0x71, 0xe9, 0xda, - 0xa3, 0x60, 0x90, 0x27, 0xc6, 0x0e, 0x9e, 0xf9, 0xfb, 0x43, 0xac, 0xc6, 0x09, 0x0a, 0xb7, 0xa4, 0xdd, 0x56, 0x89, - 0xbf, 0x7d, 0x3f, 0x05, 0x09, 0x8e, 0x75, 0xe0, 0x67, 0xdd, 0xbf, 0x9f, 0x48, 0xa4, 0x76, 0xd3, 0x1e, 0x9d, 0x44, - 0x60, 0x3c, 0x38, 0xf7, 0x53, 0xa8, 0x46, 0x12, 0x51, 0x51, 0x8e, 0x16, 0xa8, 0x79, 0xaa, 0x56, 0xc1, 0x77, 0x68, - 0x46, 0xe0, 0x39, 0x86, 0xad, 0xc9, 0x4f, 0xd5, 0x8d, 0x45, 0x2c, 0xdf, 0x75, 0xe9, 0x68, 0x0b, 0x0f, 0x20, 0x05, - 0xa3, 0x09, 0x86, 0x71, 0x29, 0x28, 0x59, 0xf1, 0xdf, 0xb1, 0x11, 0x2b, 0x9f, 0x1c, 0x66, 0x9b, 0x9b, 0x47, 0xe2, - 0xdc, 0x82, 0x18, 0x87, 0x1b, 0xd1, 0xd5, 0xb8, 0x02, 0xa0, 0x3e, 0x9d, 0x13, 0xd7, 0x03, 0xd3, 0x8a, 0x35, 0x5d, - 0x8a, 0x7d, 0x72, 0x98, 0x01, 0x28, 0xb8, 0xe5, 0x1c, 0xfa, 0x83, 0x3f, 0x1e, 0x81, 0x7b, 0xec, 0xff, 0xc1, 0xdd, - 0x52, 0x82, 0xa6, 0x27, 0xcf, 0x14, 0x17, 0x74, 0xc6, 0xda, 0xf1, 0x28, 0x36, 0x1a, 0x14, 0x5e, 0x0a, 0x18, 0x80, - 0x36, 0x07, 0x99, 0x50, 0x71, 0x10, 0x72, 0x54, 0x60, 0xfb, 0xb8, 0xf9, 0x39, 0xee, 0xec, 0xe7, 0x60, 0xe1, 0x0d, - 0xf4, 0xdb, 0x6b, 0x78, 0xfb, 0xa3, 0x7e, 0xfb, 0x89, 0x05, 0xbf, 0x94, 0x32, 0x74, 0x5f, 0x9b, 0xe2, 0x91, 0x9a, - 0xa2, 0x14, 0x4b, 0x64, 0xd0, 0x90, 0xb9, 0xf9, 0x52, 0xcc, 0x86, 0xbb, 0x25, 0x10, 0x43, 0x89, 0xae, 0xdc, 0xe7, - 0xd1, 0x19, 0x12, 0xd7, 0x35, 0x49, 0x61, 0xe4, 0x12, 0x98, 0x08, 0x57, 0x7c, 0x4b, 0xcc, 0xd9, 0x6f, 0x83, 0x0d, - 0x5e, 0xcb, 0x3b, 0x40, 0xfb, 0x8e, 0x4d, 0x67, 0xfc, 0x6a, 0x9f, 0x14, 0x7d, 0x20, 0xd3, 0x06, 0xc4, 0xd9, 0x79, - 0xbb, 0x17, 0xef, 0xf2, 0x5e, 0x0c, 0x52, 0x3d, 0x57, 0x2c, 0x86, 0x7b, 0xd5, 0x7b, 0x8f, 0x51, 0x4a, 0x93, 0x99, - 0xbc, 0x1a, 0x7a, 0x5d, 0x89, 0xde, 0xe6, 0x26, 0x20, 0xd8, 0x33, 0xba, 0x72, 0xd1, 0xb5, 0x2c, 0x05, 0x4d, 0x00, - 0xa2, 0x27, 0x75, 0x96, 0x23, 0x8e, 0xc3, 0x6c, 0x36, 0x28, 0x1e, 0x31, 0x77, 0xe5, 0xa8, 0x38, 0x26, 0x76, 0x97, - 0x09, 0x3b, 0x80, 0x19, 0x71, 0x79, 0xab, 0x23, 0xa2, 0xc3, 0xa2, 0xbf, 0x8e, 0x6f, 0x1f, 0x7b, 0x6c, 0xb3, 0xe3, - 0x82, 0x06, 0xa9, 0x8d, 0xf5, 0xb8, 0x1a, 0x0b, 0xea, 0xc3, 0x63, 0x4d, 0xa5, 0xb2, 0xd8, 0xdc, 0x2c, 0xeb, 0x47, - 0xb5, 0x6a, 0x07, 0xd7, 0x4e, 0x53, 0x2e, 0x9b, 0xd9, 0x20, 0x1c, 0x88, 0x98, 0x40, 0x81, 0x96, 0x56, 0x56, 0x0c, - 0x30, 0xa4, 0x2c, 0x47, 0xf9, 0x14, 0x32, 0x2f, 0x2e, 0x4b, 0x9d, 0xfa, 0xf2, 0x4c, 0x06, 0x1d, 0xf1, 0xd4, 0x93, - 0x8c, 0x15, 0x50, 0xb0, 0x5e, 0xea, 0x25, 0xb4, 0x44, 0x80, 0xf9, 0x0b, 0x95, 0x43, 0x23, 0x2c, 0x90, 0x28, 0x34, - 0xcc, 0x12, 0x65, 0x7c, 0x16, 0x61, 0x0c, 0xda, 0xfe, 0x59, 0x2d, 0xf6, 0x55, 0x28, 0xa3, 0xa3, 0x38, 0xcc, 0x8f, - 0x02, 0xaa, 0x9f, 0x4b, 0x09, 0x36, 0x09, 0x3f, 0x02, 0x1b, 0x55, 0x8e, 0x27, 0x09, 0xc2, 0xe7, 0x71, 0xce, 0xc8, - 0x53, 0xd8, 0x90, 0x30, 0x4b, 0xd3, 0x36, 0x52, 0xed, 0x22, 0x33, 0x08, 0xe5, 0xc2, 0xfc, 0x13, 0xe3, 0xec, 0x22, - 0x0b, 0x97, 0x5a, 0x83, 0xf9, 0xf1, 0xce, 0x04, 0x28, 0xbb, 0xbe, 0xce, 0x84, 0x8f, 0x1b, 0x91, 0xbd, 0xa1, 0x2b, - 0x26, 0x03, 0x85, 0x54, 0xe0, 0x44, 0x64, 0xf1, 0xd0, 0x19, 0x0a, 0x8d, 0x70, 0x40, 0xa7, 0xc8, 0xb9, 0x6b, 0x6c, - 0xfa, 0x7c, 0xa0, 0x7d, 0xa3, 0x34, 0x74, 0x12, 0x10, 0x02, 0x02, 0x77, 0xc3, 0x9a, 0x4a, 0x07, 0x69, 0x90, 0x50, - 0x29, 0xfa, 0x39, 0x80, 0x7f, 0x18, 0x49, 0x0a, 0x80, 0xfd, 0x50, 0x8d, 0x14, 0x51, 0x96, 0x05, 0x2e, 0x00, 0xcd, - 0xb5, 0x8f, 0x2b, 0xe1, 0x0b, 0x03, 0x15, 0xa6, 0xa7, 0x59, 0x79, 0x29, 0x94, 0xc8, 0xd3, 0x15, 0x29, 0x6b, 0x24, - 0x93, 0xcf, 0xd1, 0xe1, 0x53, 0xde, 0xf5, 0x5b, 0x89, 0x87, 0x2e, 0x78, 0x0e, 0xcb, 0xaa, 0x9e, 0xdf, 0x84, 0x9c, - 0x9c, 0x6b, 0xd0, 0x15, 0x52, 0xe8, 0x2f, 0x39, 0xc9, 0x7b, 0x6f, 0xfc, 0xaa, 0x96, 0x1a, 0x43, 0xd9, 0xc7, 0x55, - 0xcd, 0xb0, 0xbc, 0x9c, 0x55, 0x61, 0x0a, 0x02, 0x6e, 0xc1, 0x92, 0x60, 0x21, 0x35, 0x04, 0x58, 0xd8, 0x1e, 0x69, - 0xa5, 0x20, 0x2f, 0x75, 0x78, 0xe7, 0x39, 0x58, 0x01, 0xc6, 0xa1, 0x96, 0x4a, 0xa6, 0x91, 0xc4, 0x97, 0x4a, 0x14, - 0x98, 0x72, 0x7f, 0x08, 0x7e, 0x6a, 0xf3, 0xa4, 0xeb, 0xd2, 0xf5, 0xe3, 0x29, 0xa6, 0xf6, 0x10, 0xe8, 0xb1, 0x77, - 0x0f, 0x4c, 0x89, 0xba, 0x0e, 0x2b, 0x88, 0x43, 0xb3, 0x9a, 0x66, 0x01, 0x33, 0xa6, 0x0d, 0x5a, 0xb2, 0x0d, 0xb6, - 0x5c, 0x0e, 0xf6, 0x91, 0xd8, 0x9e, 0xd5, 0x0a, 0x08, 0x5d, 0x83, 0x06, 0x86, 0xdc, 0xa5, 0x42, 0x0b, 0xf3, 0x5e, - 0x97, 0x8a, 0x70, 0x7f, 0x0e, 0xb8, 0xb4, 0x82, 0x33, 0x2f, 0xa3, 0x81, 0xf7, 0xe3, 0xd3, 0x04, 0x13, 0x5f, 0x10, - 0x2b, 0xb0, 0x83, 0x83, 0x4e, 0xb3, 0x29, 0x70, 0x2a, 0x2e, 0x52, 0x06, 0xcb, 0x8a, 0x52, 0x1b, 0xfe, 0x48, 0x91, - 0xad, 0xbb, 0x3c, 0xd2, 0x5d, 0x88, 0x05, 0xb0, 0xd3, 0x2f, 0x18, 0xf9, 0x96, 0xf5, 0x32, 0x60, 0x70, 0xae, 0x35, - 0x0e, 0x02, 0xbf, 0xb9, 0x99, 0x1c, 0x95, 0x29, 0xb1, 0x5d, 0x93, 0xd5, 0x05, 0xe4, 0x98, 0x04, 0xd8, 0xc0, 0x1d, - 0x84, 0xa5, 0xb2, 0xc7, 0x8b, 0x72, 0x8a, 0xcb, 0xa5, 0x2c, 0xe4, 0xe6, 0x79, 0x35, 0xcd, 0xe7, 0x56, 0x9a, 0x4d, - 0xc7, 0x5b, 0xf1, 0x45, 0xc1, 0x3f, 0x70, 0x62, 0x69, 0xd5, 0x53, 0x6a, 0x85, 0x47, 0x99, 0x5b, 0xb2, 0x4e, 0x49, - 0xad, 0xae, 0x1b, 0xa8, 0x46, 0x78, 0x9a, 0x86, 0x8d, 0x40, 0x88, 0x09, 0x2e, 0x7e, 0xdb, 0x64, 0x62, 0xda, 0x5b, - 0x42, 0xea, 0x08, 0xbb, 0x87, 0x72, 0x82, 0xbb, 0x9a, 0x67, 0x5f, 0x86, 0xb3, 0xf5, 0xcc, 0xbd, 0x67, 0x30, 0xf7, - 0xd3, 0x90, 0x1b, 0x8c, 0x1e, 0xcb, 0x84, 0x1f, 0x19, 0xfb, 0xc8, 0x55, 0xd5, 0xb3, 0xb3, 0xb0, 0x12, 0x59, 0xe2, - 0xc9, 0x38, 0xea, 0x30, 0x4e, 0x45, 0x6b, 0x82, 0xec, 0xfa, 0xba, 0x30, 0xf7, 0x02, 0x05, 0x4d, 0x3d, 0x5e, 0x8f, - 0xd3, 0x56, 0xec, 0x6c, 0x44, 0x22, 0xf7, 0xde, 0xd4, 0x22, 0x91, 0x15, 0x9f, 0xe3, 0x48, 0x6b, 0x0e, 0x72, 0x9f, - 0x9d, 0x2d, 0x6f, 0x52, 0xa1, 0x5b, 0x34, 0xda, 0xc6, 0x1e, 0xd5, 0x07, 0x92, 0x7a, 0x46, 0x05, 0x56, 0x35, 0xf6, - 0xfd, 0xfb, 0x1d, 0x91, 0x6e, 0xa9, 0x14, 0x1b, 0x2c, 0x2d, 0x8c, 0x66, 0x8c, 0x82, 0x41, 0x49, 0x91, 0x81, 0x1a, - 0xe5, 0x6b, 0x04, 0xc3, 0x1e, 0x35, 0x00, 0xc5, 0xb9, 0xba, 0xfa, 0x69, 0x29, 0xd9, 0x42, 0x40, 0xe2, 0x2e, 0x18, - 0x88, 0x35, 0xc1, 0xcc, 0xc8, 0x27, 0x1f, 0x81, 0xf3, 0x06, 0x0c, 0x1d, 0x03, 0xf0, 0x0b, 0xc4, 0xa6, 0x07, 0x13, - 0xdb, 0x26, 0xa2, 0xe8, 0xb3, 0x81, 0x97, 0x00, 0xec, 0xac, 0x0a, 0x8d, 0x7e, 0xa8, 0x52, 0xc0, 0x90, 0x0d, 0xdc, - 0x80, 0x55, 0x61, 0xb9, 0xbd, 0x97, 0xe0, 0x36, 0xc0, 0xeb, 0x0b, 0xd9, 0x7c, 0x03, 0xf3, 0x04, 0xab, 0xb3, 0x0b, - 0xbf, 0xb2, 0xac, 0xc5, 0xb9, 0xd3, 0x41, 0xa3, 0x5e, 0x51, 0x42, 0xd4, 0xee, 0x63, 0xed, 0x4b, 0x8c, 0xb0, 0x88, - 0xf7, 0x37, 0xf8, 0xae, 0xc7, 0x2d, 0xf7, 0x34, 0x5a, 0x84, 0xe9, 0x32, 0x69, 0x0c, 0x4a, 0xd6, 0xfd, 0x64, 0xc4, - 0xbd, 0xdc, 0x17, 0xb1, 0xe0, 0x0a, 0x47, 0x56, 0x85, 0x14, 0x1b, 0x48, 0xd2, 0xd3, 0x1e, 0x1d, 0xb0, 0x6f, 0x34, - 0x7b, 0x01, 0x65, 0x3e, 0x56, 0xa4, 0x92, 0x90, 0xd2, 0xec, 0x86, 0x48, 0x12, 0xd6, 0x8a, 0x3c, 0x75, 0xde, 0x77, - 0xb4, 0xcf, 0xad, 0x24, 0x82, 0x11, 0x9c, 0x84, 0xe9, 0x58, 0x79, 0xd0, 0x14, 0xe0, 0x2a, 0x3a, 0x62, 0xfa, 0x26, - 0x20, 0xbf, 0x19, 0xc8, 0xed, 0xa5, 0xe4, 0xda, 0x5c, 0xc3, 0xf0, 0x0c, 0x09, 0x56, 0x45, 0x22, 0xf0, 0x88, 0x1a, - 0x70, 0xcc, 0x57, 0x79, 0x1e, 0x60, 0xc2, 0xd7, 0xf6, 0x26, 0x00, 0x94, 0x93, 0xab, 0xe2, 0x2c, 0x05, 0xba, 0x01, - 0xcb, 0xd5, 0x71, 0x6a, 0x54, 0x24, 0x2e, 0x6e, 0x4c, 0x57, 0xb7, 0xf4, 0xa7, 0x68, 0x39, 0x93, 0x21, 0xa6, 0x83, - 0x20, 0x20, 0x53, 0x9f, 0x32, 0x47, 0xc8, 0x5c, 0x61, 0x7d, 0xce, 0x9c, 0xda, 0xd4, 0x3d, 0x46, 0xdd, 0x3c, 0x49, - 0x2d, 0x5e, 0xa7, 0x4d, 0x29, 0x11, 0x93, 0x12, 0xf3, 0x54, 0xa4, 0x62, 0x33, 0x25, 0xee, 0xdc, 0xfa, 0x46, 0x0b, - 0x69, 0xa3, 0x9d, 0x8a, 0x1c, 0x6c, 0x56, 0xc9, 0x7b, 0x02, 0xe3, 0xa5, 0x20, 0x7c, 0x89, 0x8c, 0xb5, 0x98, 0x33, - 0xc7, 0x44, 0xb0, 0x7a, 0x31, 0x15, 0xf9, 0x07, 0x47, 0xa7, 0xd9, 0x1b, 0xf4, 0x20, 0xf5, 0x06, 0x12, 0xb3, 0x26, - 0xbe, 0x0b, 0x69, 0xa8, 0x23, 0x04, 0x2a, 0xa3, 0x5a, 0xa6, 0xe3, 0xc4, 0x2a, 0x7c, 0x23, 0xf8, 0xea, 0xbd, 0x3e, - 0xce, 0x37, 0x9e, 0x1b, 0xab, 0x11, 0xc4, 0xe0, 0x2d, 0xe4, 0x47, 0x9e, 0x14, 0xe1, 0x40, 0xb8, 0x7c, 0x73, 0xb3, - 0x97, 0xef, 0xf2, 0x2a, 0x44, 0x52, 0xc1, 0x18, 0x63, 0x46, 0x31, 0xee, 0x89, 0x9a, 0x5a, 0xcc, 0x61, 0x60, 0xd9, - 0x3a, 0xcc, 0xf1, 0x00, 0x00, 0x5a, 0x9a, 0xd2, 0xab, 0xa6, 0x42, 0xe5, 0x79, 0x2e, 0xe1, 0x53, 0x1d, 0xa2, 0xaa, - 0xc6, 0xef, 0x57, 0x67, 0xa0, 0x10, 0xdc, 0xf7, 0x3a, 0x1e, 0x1e, 0x42, 0xc0, 0x2a, 0x0a, 0x59, 0xa0, 0x37, 0x68, - 0xaf, 0x4a, 0x84, 0x62, 0xe6, 0x64, 0x3d, 0x66, 0x38, 0xa9, 0x60, 0x0b, 0x95, 0xb0, 0x54, 0x5a, 0xe0, 0x57, 0x1b, - 0xa1, 0x79, 0xca, 0xb8, 0xf7, 0xa6, 0xc2, 0x19, 0xf4, 0x07, 0xf3, 0x96, 0x19, 0xf5, 0xfd, 0xd2, 0x89, 0x4c, 0x05, - 0x26, 0x6e, 0x66, 0xa9, 0xfd, 0x7e, 0x59, 0xa5, 0xfd, 0xbc, 0x42, 0xee, 0x73, 0xd2, 0x7c, 0x9d, 0x3b, 0x68, 0x3e, - 0x19, 0xee, 0x57, 0xca, 0x0f, 0x2d, 0x8c, 0x9a, 0xf2, 0xcb, 0xeb, 0xca, 0xaf, 0xf0, 0x54, 0x78, 0xab, 0xdf, 0x45, - 0xa1, 0x8b, 0xfa, 0x1c, 0x0c, 0x21, 0xfd, 0x08, 0xae, 0xa1, 0xc1, 0x83, 0x22, 0x59, 0x2c, 0xd6, 0x2e, 0x88, 0xeb, - 0x63, 0x4e, 0xb5, 0x43, 0x19, 0x63, 0xc4, 0xd3, 0x92, 0x83, 0x24, 0x83, 0x83, 0xf1, 0x1b, 0x18, 0x10, 0x93, 0x92, - 0x90, 0x0e, 0xa1, 0xb3, 0x32, 0x13, 0x51, 0xb9, 0x8b, 0xb7, 0x1b, 0x97, 0x35, 0x85, 0x22, 0xec, 0x04, 0x33, 0x95, - 0x52, 0x41, 0x20, 0x4d, 0xbe, 0x7b, 0x9d, 0x5a, 0x30, 0xb4, 0x70, 0x4d, 0x05, 0xe4, 0xb5, 0x5d, 0x0f, 0x9a, 0x7c, - 0xa4, 0x18, 0xfa, 0x2a, 0x35, 0xe2, 0x65, 0x06, 0x5f, 0xc3, 0xe6, 0xaf, 0x89, 0x92, 0x3c, 0x64, 0x22, 0xf6, 0x0a, - 0x3e, 0x11, 0xb2, 0x29, 0xd8, 0x99, 0x40, 0x3f, 0xb4, 0x2b, 0x7b, 0xe9, 0x6e, 0x51, 0xb9, 0xb4, 0x68, 0x6c, 0x25, - 0x6a, 0xd6, 0xfc, 0x30, 0xde, 0x4c, 0x61, 0x3f, 0x7b, 0x94, 0x40, 0x40, 0x9a, 0xca, 0x49, 0xaa, 0x79, 0x0f, 0xd3, - 0x23, 0x00, 0x09, 0x76, 0x3f, 0x81, 0x85, 0x7e, 0x53, 0x62, 0x82, 0x45, 0xd5, 0xd8, 0x6d, 0x06, 0x5a, 0x73, 0x46, - 0x9a, 0x6f, 0x86, 0x5a, 0x7b, 0x53, 0x59, 0xcf, 0x98, 0x1d, 0x60, 0xdb, 0xee, 0x66, 0x71, 0x98, 0x6e, 0x76, 0x8e, - 0x0c, 0xc1, 0x85, 0xc7, 0xff, 0x49, 0x89, 0x69, 0x20, 0xb9, 0xd4, 0x8d, 0x9f, 0x50, 0x87, 0xe1, 0xff, 0x16, 0xa4, - 0x80, 0x07, 0xb5, 0xd5, 0x58, 0x72, 0xee, 0x15, 0x47, 0xc9, 0x65, 0x55, 0xed, 0x6a, 0x09, 0x1a, 0xba, 0x91, 0x8c, - 0x89, 0x62, 0x9e, 0x13, 0x00, 0xa3, 0xd8, 0xfc, 0x39, 0xd3, 0x49, 0xde, 0xbf, 0xac, 0x4c, 0xed, 0xf6, 0x7d, 0x3f, - 0xca, 0xcf, 0xe8, 0x48, 0x45, 0x65, 0x73, 0x12, 0xf3, 0x6f, 0x0b, 0x30, 0xcd, 0x89, 0x0f, 0xf5, 0x5c, 0x47, 0xa1, - 0x00, 0x5f, 0xd9, 0x50, 0x6a, 0xb6, 0xd7, 0xbf, 0x75, 0xb6, 0x87, 0x92, 0x28, 0x82, 0x05, 0x1a, 0x74, 0x59, 0x83, - 0x2f, 0x60, 0x19, 0xdc, 0x91, 0x7e, 0x0a, 0xbe, 0x9f, 0xd6, 0xc1, 0x67, 0xec, 0x7f, 0x01, 0x68, 0x55, 0x60, 0x40, - 0xb9, 0xd3, 0x34, 0xac, 0x84, 0xb8, 0x44, 0x85, 0x59, 0xc5, 0xf9, 0xe3, 0x3a, 0xaf, 0x9b, 0x96, 0x25, 0x06, 0xe5, - 0x67, 0xae, 0xe1, 0xc6, 0xf7, 0x1a, 0xf9, 0xe3, 0x7b, 0x2f, 0x41, 0xb7, 0x13, 0x69, 0xef, 0xdf, 0xcf, 0xef, 0x91, - 0x85, 0x86, 0xf7, 0xc2, 0x66, 0xd0, 0x16, 0xe9, 0x92, 0xab, 0x67, 0x2c, 0xc6, 0xdb, 0x22, 0x54, 0x86, 0x0f, 0x58, - 0x30, 0x03, 0x0c, 0xc1, 0x63, 0xa7, 0x32, 0xf9, 0x0c, 0x1b, 0x4d, 0xb1, 0x6b, 0x2e, 0x0c, 0x3e, 0x50, 0x95, 0x85, - 0xe4, 0xc5, 0x3a, 0xd9, 0x5e, 0x9c, 0xc3, 0xf3, 0xeb, 0xb8, 0x00, 0xea, 0x00, 0xfa, 0x15, 0x95, 0xc5, 0x06, 0x72, - 0x71, 0x53, 0xd6, 0x7a, 0x45, 0xa3, 0xd1, 0x8d, 0x5d, 0x58, 0x5d, 0x81, 0x4f, 0xa2, 0x74, 0x94, 0x88, 0x49, 0xcc, - 0xa4, 0xca, 0x15, 0xb9, 0x36, 0xba, 0x97, 0xb6, 0x68, 0x5e, 0x0a, 0x09, 0x5e, 0x11, 0xb8, 0x21, 0xf4, 0x95, 0xbe, - 0x5c, 0x6d, 0xa0, 0xe0, 0x51, 0x7b, 0x73, 0x11, 0x4c, 0x4c, 0x3c, 0x66, 0x48, 0x4d, 0xbf, 0x0e, 0xa7, 0x56, 0x16, - 0x4b, 0x0e, 0xbf, 0xce, 0x19, 0x6b, 0x28, 0x00, 0xe2, 0x93, 0x47, 0xeb, 0xdd, 0xa4, 0x37, 0x4a, 0x3b, 0x28, 0x8d, - 0x10, 0xdf, 0x55, 0xf8, 0xba, 0x0b, 0xc5, 0x57, 0xae, 0xba, 0xf7, 0x75, 0xcc, 0x8c, 0x0b, 0x46, 0x2f, 0xf9, 0x34, - 0x69, 0x5c, 0xbb, 0xa1, 0xbb, 0x3a, 0xdf, 0x7b, 0x5f, 0xca, 0xbc, 0x85, 0x63, 0x60, 0x93, 0x63, 0xe6, 0xbc, 0xf4, - 0xde, 0x1a, 0x27, 0xca, 0x3f, 0x98, 0x47, 0xbc, 0x72, 0x98, 0x55, 0x27, 0xc9, 0x3f, 0x0c, 0x7e, 0x08, 0xd6, 0xb7, - 0x34, 0x4e, 0x90, 0xbb, 0xea, 0x04, 0x99, 0x28, 0xb7, 0xa1, 0x37, 0xdc, 0xde, 0x5d, 0x05, 0x82, 0x38, 0x15, 0xd3, - 0x47, 0xe5, 0xb8, 0x7e, 0xb4, 0x40, 0xa5, 0x22, 0xe2, 0x73, 0x95, 0xbb, 0xb2, 0x36, 0x35, 0xd4, 0xe3, 0x3a, 0x99, - 0x85, 0xa6, 0x59, 0x91, 0x4b, 0xd9, 0xf4, 0x18, 0x99, 0x66, 0xa7, 0xda, 0xfc, 0xee, 0xda, 0x43, 0x3a, 0x86, 0xe6, - 0x62, 0xad, 0x16, 0xdc, 0xef, 0x2a, 0x0a, 0xef, 0x7a, 0xb1, 0x91, 0xca, 0x50, 0xb3, 0x1e, 0x45, 0x1f, 0xc7, 0x6d, - 0xe6, 0xf2, 0x28, 0xfb, 0xb3, 0x06, 0x80, 0xe9, 0x08, 0x8b, 0xee, 0xa6, 0x67, 0xec, 0x09, 0xf4, 0xf4, 0x44, 0x06, - 0x89, 0xde, 0xe8, 0x7c, 0xd5, 0x2a, 0xb1, 0x74, 0x05, 0x81, 0xdd, 0x1b, 0x32, 0x56, 0x25, 0xed, 0x96, 0xeb, 0x97, - 0xf3, 0x7c, 0x9e, 0xf3, 0xa5, 0x3c, 0x9f, 0x9a, 0x45, 0x77, 0xaf, 0xed, 0xde, 0x9c, 0x1a, 0x2a, 0xe6, 0x5a, 0xdd, - 0xe4, 0x37, 0x4c, 0xd7, 0xc1, 0x50, 0x8b, 0x20, 0xb3, 0xda, 0x55, 0x2f, 0xca, 0x72, 0xa3, 0x9e, 0xc9, 0xb1, 0x21, - 0x7c, 0x53, 0xe9, 0x0e, 0xd1, 0x0d, 0x53, 0x35, 0xd3, 0xf7, 0x8d, 0x6d, 0x21, 0xdb, 0xbc, 0xbc, 0x1a, 0xe5, 0x40, - 0x69, 0xb9, 0xbf, 0x4c, 0x18, 0xbe, 0xbf, 0xbe, 0xfe, 0x5e, 0xc8, 0xa9, 0xaa, 0xa3, 0xb7, 0x78, 0xad, 0x7b, 0x06, - 0x1b, 0xa5, 0x72, 0x22, 0x2e, 0xd8, 0xea, 0xc1, 0x9b, 0xbb, 0x57, 0xc0, 0x72, 0x01, 0xd8, 0x5d, 0x30, 0xa7, 0x31, - 0x54, 0xb5, 0x81, 0xbf, 0x5c, 0x3d, 0xd8, 0xaa, 0x3d, 0xfc, 0xe5, 0xe0, 0xcb, 0xe0, 0xc6, 0xc6, 0xc6, 0x36, 0xde, - 0xae, 0x25, 0x82, 0xbc, 0xc1, 0x03, 0x7d, 0xbc, 0xfa, 0x28, 0x68, 0xb9, 0x4a, 0x6c, 0x0f, 0x1c, 0x0a, 0x5b, 0x83, - 0x7c, 0x93, 0x32, 0x69, 0x38, 0x2f, 0x78, 0x36, 0x95, 0x33, 0x14, 0xf2, 0x9a, 0x8f, 0x83, 0xb6, 0x23, 0xfc, 0x1b, - 0x38, 0xb5, 0xe3, 0xe5, 0xc5, 0x27, 0xe8, 0x03, 0x9e, 0xae, 0x94, 0xa6, 0x22, 0x4e, 0x29, 0xb7, 0xe8, 0x72, 0x9d, - 0x07, 0x23, 0xc5, 0xc5, 0x04, 0x95, 0x8e, 0xbb, 0xb8, 0x71, 0x36, 0x72, 0xfa, 0x4b, 0xbc, 0xba, 0x48, 0x97, 0x8f, - 0x44, 0xb6, 0x6a, 0xe9, 0xfd, 0xac, 0x4f, 0xb7, 0xed, 0x29, 0xe3, 0x93, 0x6c, 0x44, 0x07, 0x33, 0x3e, 0x4e, 0x84, - 0xd7, 0x27, 0x46, 0xfa, 0x6e, 0x11, 0x98, 0x6e, 0x8e, 0x4d, 0x7e, 0x38, 0x5e, 0x6f, 0x36, 0x6b, 0xdc, 0xc1, 0x3b, - 0xe7, 0x93, 0xb3, 0x28, 0x31, 0xa2, 0xb2, 0xd0, 0xf0, 0x80, 0x56, 0x88, 0x9b, 0xf7, 0x4c, 0x60, 0x5c, 0x76, 0x45, - 0x52, 0xdb, 0x0d, 0x04, 0x2e, 0xf6, 0x38, 0x66, 0xc9, 0xc8, 0xf6, 0xa0, 0x3c, 0xd0, 0x17, 0xa3, 0xe9, 0x16, 0x30, - 0x2d, 0xaf, 0x9d, 0x5d, 0xa4, 0xb6, 0x57, 0x4d, 0x15, 0xc0, 0x2c, 0x59, 0x1e, 0x9f, 0x21, 0xeb, 0x7e, 0x0d, 0x5d, - 0xc4, 0x80, 0xb1, 0x71, 0x65, 0xce, 0x5d, 0xac, 0x5a, 0x11, 0xdf, 0x68, 0x22, 0x4d, 0xea, 0x43, 0xea, 0x7b, 0x14, - 0xd6, 0xea, 0x2a, 0x07, 0x09, 0xdc, 0x23, 0xef, 0x8e, 0xb8, 0xf4, 0xf4, 0x99, 0xc5, 0xb8, 0x4a, 0xdf, 0x52, 0xd7, - 0xe2, 0x9a, 0x61, 0xaf, 0x78, 0x00, 0xf6, 0x07, 0xc6, 0x2d, 0x62, 0x11, 0x6f, 0xe7, 0xb5, 0x14, 0xd6, 0xc6, 0x1c, - 0x68, 0x6e, 0xb8, 0xc1, 0xcf, 0xac, 0x5a, 0x33, 0x30, 0xc3, 0x8c, 0x33, 0x92, 0x0f, 0xc6, 0xbd, 0xaa, 0xb1, 0x23, - 0x57, 0x01, 0x44, 0xdf, 0x82, 0x2e, 0xc9, 0xe1, 0x95, 0x2c, 0x57, 0x9d, 0x21, 0xbf, 0x82, 0x75, 0xd6, 0x8b, 0x13, - 0x30, 0x93, 0xa6, 0xbc, 0xc4, 0xc4, 0x14, 0x71, 0xb9, 0x59, 0xc6, 0x3c, 0x4d, 0x9f, 0x45, 0x3b, 0x38, 0xb9, 0x91, - 0xc0, 0x11, 0xfb, 0xc6, 0x32, 0x34, 0x13, 0x36, 0x62, 0x22, 0x8d, 0x4a, 0x29, 0xe1, 0x03, 0xb9, 0xd4, 0x92, 0xbf, - 0xcc, 0xe5, 0xd5, 0x97, 0xdb, 0x04, 0x07, 0xe4, 0x35, 0xb0, 0x1c, 0x1a, 0xc7, 0x2d, 0x03, 0x89, 0x58, 0x0c, 0x88, - 0x51, 0xab, 0x72, 0x39, 0x19, 0xd5, 0xc9, 0x7c, 0x85, 0x5c, 0xa8, 0xc8, 0x83, 0x5b, 0x02, 0x25, 0x7f, 0x8e, 0xa9, - 0x83, 0x59, 0xa9, 0xdd, 0xb4, 0xd8, 0x24, 0x79, 0xcf, 0x0c, 0x48, 0xae, 0xbe, 0x86, 0x87, 0xc6, 0x2f, 0x5e, 0x99, - 0x53, 0xc2, 0x17, 0x65, 0x2c, 0x2d, 0x8d, 0xb9, 0xf4, 0xdf, 0xca, 0xfb, 0xb4, 0x12, 0xb0, 0x57, 0x20, 0xa6, 0x0c, - 0x5c, 0x62, 0xe3, 0x82, 0xa4, 0xbc, 0x96, 0xa7, 0xec, 0xbe, 0x86, 0xf2, 0x5d, 0x32, 0xe9, 0x2a, 0x95, 0xb5, 0xc6, - 0xaa, 0xfb, 0x79, 0xce, 0xf2, 0xab, 0x7d, 0x86, 0xb9, 0xc9, 0x68, 0x90, 0x2d, 0x99, 0xd9, 0x94, 0x5f, 0xed, 0xdd, - 0xf8, 0x95, 0x87, 0x92, 0x0e, 0xd5, 0x2a, 0xdd, 0xbc, 0x74, 0xc3, 0x31, 0x6e, 0xdc, 0x70, 0x04, 0xb0, 0x31, 0xec, - 0x54, 0x91, 0x5a, 0xe7, 0xbf, 0x2f, 0x87, 0x9f, 0x68, 0xaf, 0x1d, 0xe9, 0x5d, 0x77, 0xb4, 0x32, 0x3d, 0xfd, 0x06, - 0x54, 0x8d, 0x2c, 0xa1, 0x9b, 0x50, 0xc5, 0x64, 0x24, 0x4a, 0x4c, 0x57, 0x29, 0x8f, 0xfa, 0x1a, 0x71, 0x0e, 0xe2, - 0x86, 0xf2, 0x17, 0xff, 0x14, 0x5e, 0x9d, 0x04, 0x68, 0x44, 0x2d, 0xc6, 0x59, 0xca, 0x5b, 0xe3, 0x68, 0x1a, 0x27, - 0x57, 0xc1, 0x3c, 0x6e, 0x4d, 0xb3, 0x34, 0x2b, 0x66, 0xc0, 0x95, 0x5e, 0x71, 0x05, 0x36, 0xfc, 0xb4, 0x35, 0x8f, - 0xbd, 0x97, 0x2c, 0x39, 0x67, 0x3c, 0x1e, 0x46, 0x9e, 0xbd, 0x97, 0x83, 0x78, 0xb0, 0xde, 0x46, 0x79, 0x9e, 0x5d, - 0xd8, 0xde, 0x87, 0xec, 0x14, 0x98, 0xd6, 0x7b, 0x77, 0x79, 0x75, 0xc6, 0x52, 0xef, 0xe3, 0xe9, 0x3c, 0xe5, 0x73, - 0xaf, 0x88, 0xd2, 0xa2, 0x55, 0xb0, 0x3c, 0x1e, 0x83, 0x9a, 0x48, 0xb2, 0xbc, 0x85, 0xf9, 0xcf, 0x53, 0x16, 0x24, - 0xf1, 0xd9, 0x84, 0x5b, 0xa3, 0x28, 0xff, 0xd4, 0x6b, 0xb5, 0x66, 0x79, 0x3c, 0x8d, 0xf2, 0xab, 0x16, 0xb5, 0x08, - 0x3e, 0x6b, 0x6f, 0x47, 0x9f, 0x8f, 0x1f, 0xf6, 0x78, 0x0e, 0x7d, 0x63, 0xa4, 0x62, 0x00, 0xc2, 0xc7, 0xda, 0xde, - 0x69, 0x4f, 0x8b, 0x7b, 0xe2, 0x44, 0x29, 0x4a, 0x79, 0x79, 0xe2, 0x5d, 0x31, 0x80, 0xdb, 0x3f, 0xe5, 0xa9, 0x07, - 0xbe, 0x1c, 0xcf, 0xd2, 0xc5, 0x70, 0x9e, 0x17, 0x30, 0xc0, 0x2c, 0x8b, 0x53, 0xce, 0xf2, 0xde, 0x69, 0x96, 0x03, - 0xd9, 0x5a, 0x79, 0x34, 0x8a, 0xe7, 0x45, 0xf0, 0x70, 0x76, 0xd9, 0x43, 0x5b, 0xe1, 0x2c, 0xcf, 0xe6, 0xe9, 0x48, - 0xce, 0x15, 0xa7, 0xb0, 0x31, 0x62, 0x6e, 0x56, 0xd0, 0x97, 0x50, 0x00, 0xbe, 0x94, 0x45, 0x79, 0xeb, 0x0c, 0x3b, - 0xa3, 0xa1, 0xdf, 0x1e, 0xb1, 0x33, 0x2f, 0x3f, 0x3b, 0x8d, 0x9c, 0x4e, 0xf7, 0xb1, 0xa7, 0xfe, 0xf3, 0x77, 0x5c, - 0x30, 0xdc, 0x57, 0x16, 0x77, 0xda, 0xed, 0xbf, 0x71, 0x7b, 0x8d, 0x59, 0x08, 0xa0, 0xa0, 0x33, 0xbb, 0xb4, 0x8a, - 0x2c, 0x81, 0xf5, 0x59, 0xd5, 0xb3, 0x37, 0x03, 0xbf, 0x29, 0x4e, 0xcf, 0x82, 0xee, 0xec, 0xb2, 0x44, 0xec, 0x02, - 0x91, 0x90, 0x29, 0x91, 0x94, 0x6f, 0x8b, 0xdf, 0x0a, 0xf1, 0x93, 0xd5, 0x10, 0x77, 0x15, 0xc4, 0x15, 0xd5, 0x5b, - 0x23, 0xd8, 0x07, 0x44, 0xfe, 0x4e, 0x21, 0x00, 0x99, 0x80, 0x13, 0x98, 0x2b, 0x38, 0xe8, 0xe5, 0x37, 0x83, 0xd1, - 0x5d, 0x0d, 0xc6, 0x93, 0xdb, 0xc0, 0xc8, 0xd3, 0xd1, 0xa2, 0xbe, 0xae, 0x1d, 0x70, 0x4e, 0x7b, 0x13, 0x86, 0xfc, - 0x14, 0x74, 0xf1, 0xf9, 0x22, 0x1e, 0xf1, 0x89, 0x78, 0x24, 0x76, 0xbe, 0x10, 0x75, 0x3b, 0xed, 0xb6, 0x78, 0x2f, - 0x40, 0xa1, 0x05, 0x1d, 0x1f, 0x1b, 0x00, 0x13, 0x7d, 0xb1, 0xee, 0x23, 0x36, 0xdf, 0xdd, 0xfa, 0xa5, 0x1a, 0x8f, - 0xa9, 0xbc, 0x41, 0xa1, 0x22, 0xd4, 0x37, 0x5b, 0x30, 0xe3, 0x2d, 0xef, 0x77, 0xf4, 0x41, 0xd5, 0xe0, 0x3b, 0x46, - 0x5a, 0x2f, 0xe0, 0x9e, 0x99, 0x0b, 0xd4, 0x4b, 0xfb, 0x18, 0x92, 0x6a, 0xb5, 0x5c, 0xd0, 0x1b, 0x0c, 0x43, 0x48, - 0x74, 0x20, 0xe8, 0xe4, 0x83, 0x82, 0xbe, 0xa9, 0x91, 0xb9, 0x41, 0xe1, 0x64, 0x2e, 0x6c, 0xf9, 0x4c, 0xcb, 0x75, - 0x50, 0xd2, 0xe0, 0x65, 0x7f, 0xc1, 0x64, 0x03, 0x90, 0xde, 0x95, 0xa4, 0xe5, 0xd5, 0xd1, 0x93, 0x72, 0xf9, 0xb2, - 0x21, 0x51, 0x0e, 0x7c, 0x7d, 0x3e, 0x41, 0xbf, 0x5b, 0x7f, 0x28, 0xc6, 0x48, 0xa9, 0xd9, 0xb2, 0xdd, 0x01, 0xd3, - 0x59, 0x59, 0x98, 0x7d, 0xc6, 0x4a, 0x1c, 0xe5, 0x2b, 0xb0, 0xa4, 0x31, 0xf4, 0xfa, 0x73, 0x28, 0xdc, 0x34, 0xe5, - 0xa4, 0x6d, 0xdc, 0x74, 0xfd, 0x1f, 0x56, 0x3c, 0xa6, 0x6c, 0x67, 0x15, 0x1b, 0x07, 0xd7, 0xe5, 0x78, 0x28, 0xae, - 0x1d, 0x16, 0x98, 0x2d, 0xfe, 0xdb, 0x3d, 0x09, 0x47, 0xa3, 0x55, 0x64, 0xf3, 0x7c, 0x48, 0xa1, 0xc1, 0xe5, 0x10, - 0x83, 0x4d, 0x1a, 0xde, 0xf6, 0x98, 0x56, 0x2c, 0xe8, 0x77, 0xd7, 0xbe, 0xaa, 0xc0, 0xe9, 0xd4, 0x45, 0x5c, 0x6a, - 0x90, 0x61, 0x15, 0x05, 0x36, 0xea, 0xca, 0x11, 0x25, 0xd8, 0xd1, 0x85, 0x4f, 0x7f, 0x9e, 0xc6, 0x20, 0x5a, 0x8f, - 0xe3, 0x11, 0x5d, 0x74, 0x89, 0x47, 0x74, 0xf2, 0xd1, 0xa2, 0x4c, 0x27, 0x0c, 0xa5, 0x43, 0x81, 0x24, 0x38, 0x3e, - 0xcb, 0xcc, 0x19, 0xbb, 0x65, 0xe3, 0xe9, 0x85, 0xa1, 0x9b, 0x47, 0xd9, 0x34, 0x8a, 0xd3, 0x00, 0x3f, 0x48, 0xe2, - 0xe9, 0x11, 0x03, 0xec, 0xe2, 0xc1, 0x5f, 0x45, 0xfb, 0x8e, 0xeb, 0xff, 0x04, 0x82, 0x8b, 0xfa, 0x97, 0xd2, 0xf1, - 0xd3, 0x70, 0xa9, 0x73, 0xe5, 0x7a, 0x29, 0x08, 0x3b, 0xae, 0x8c, 0x64, 0x46, 0x81, 0x95, 0x5d, 0x4e, 0x7f, 0x06, - 0xad, 0x4e, 0xa0, 0xae, 0xfe, 0x9b, 0x2b, 0x60, 0x5c, 0x0c, 0xa8, 0x56, 0x85, 0x4a, 0xe4, 0x1b, 0xcc, 0x21, 0xf9, - 0xf3, 0xfa, 0x5a, 0x7f, 0x3c, 0xa0, 0x71, 0x81, 0x56, 0xa4, 0xdf, 0xc8, 0x4b, 0x98, 0x84, 0x85, 0x7e, 0x16, 0x98, - 0x56, 0xef, 0x1a, 0x5b, 0x4f, 0x6e, 0x25, 0x8c, 0x39, 0x9d, 0xa5, 0x4e, 0x0d, 0x0d, 0x3a, 0xbe, 0x58, 0x33, 0x95, - 0x5b, 0x46, 0xc4, 0xdc, 0x4f, 0x49, 0xe6, 0xd4, 0xaf, 0x3f, 0xe1, 0x55, 0xa7, 0x7a, 0xd6, 0x96, 0x62, 0xef, 0xe1, - 0xc9, 0xae, 0x10, 0x52, 0x16, 0xb1, 0x6e, 0x68, 0x83, 0xd4, 0xb0, 0xad, 0x3f, 0x0e, 0x81, 0xce, 0x9f, 0x42, 0x7b, - 0x63, 0xe1, 0xa8, 0xbb, 0x00, 0x39, 0xcc, 0xb5, 0x27, 0x14, 0x35, 0x7d, 0x44, 0xc0, 0xee, 0x6f, 0x2c, 0x78, 0xb9, - 0xbb, 0x25, 0x7a, 0xf7, 0x4f, 0xca, 0x82, 0x74, 0xaa, 0x19, 0xfb, 0xab, 0xa6, 0x10, 0x75, 0x30, 0x2c, 0x65, 0x1c, - 0xe3, 0xb8, 0xb9, 0xb6, 0x13, 0x45, 0x90, 0x5b, 0x32, 0x6e, 0x81, 0x19, 0x56, 0x51, 0x0e, 0x62, 0x44, 0xe7, 0xd0, - 0x14, 0x22, 0x6d, 0xa4, 0xb7, 0x0c, 0xc5, 0x09, 0x42, 0x30, 0xd8, 0x58, 0xc4, 0x65, 0xb8, 0xb1, 0x60, 0xe9, 0x30, - 0x1b, 0xb1, 0x8f, 0x1f, 0x5e, 0xe1, 0x35, 0x89, 0x2c, 0x45, 0x79, 0x9a, 0xb9, 0xe5, 0x09, 0x18, 0x58, 0x08, 0x69, - 0xae, 0xbe, 0x52, 0x03, 0xc0, 0x88, 0x58, 0x91, 0x45, 0xa3, 0x22, 0x28, 0xac, 0xb4, 0xad, 0x81, 0x80, 0x10, 0x1c, - 0x59, 0x2c, 0x00, 0x13, 0x94, 0x7a, 0x31, 0xc0, 0x4f, 0xb4, 0xee, 0xc3, 0x40, 0xbb, 0x5b, 0xa2, 0x11, 0xe0, 0x9a, - 0x23, 0x1a, 0x15, 0xaa, 0x98, 0x55, 0x64, 0xa2, 0x3b, 0x8a, 0xcf, 0x35, 0x39, 0x29, 0xc5, 0xba, 0xbf, 0x9b, 0x44, - 0xa7, 0x2c, 0x81, 0x21, 0x81, 0xaf, 0xda, 0x30, 0x92, 0x78, 0xb5, 0x76, 0xe3, 0x74, 0x36, 0x97, 0x5f, 0x0b, 0x83, - 0x89, 0x3b, 0x78, 0x80, 0x8b, 0x97, 0x19, 0x06, 0xea, 0x44, 0x32, 0x90, 0x03, 0x00, 0x88, 0x74, 0x18, 0x82, 0xd0, - 0x55, 0xac, 0x02, 0xa5, 0xf1, 0x68, 0xb9, 0x0c, 0xf6, 0xf7, 0x0c, 0x4b, 0x53, 0x78, 0x9e, 0xc6, 0x29, 0x3e, 0x16, - 0xf8, 0x18, 0x5d, 0xe2, 0x63, 0x06, 0x8f, 0x1a, 0xf7, 0xbc, 0xb4, 0xff, 0xaa, 0xab, 0x92, 0xc9, 0x15, 0xb0, 0x34, - 0x01, 0xb2, 0xeb, 0x6b, 0x50, 0x5b, 0x9a, 0x04, 0xbb, 0x5b, 0x40, 0x2c, 0xe4, 0x1e, 0xf1, 0xed, 0x18, 0x66, 0x92, - 0x91, 0x15, 0xb3, 0x96, 0x28, 0xb7, 0xc8, 0x38, 0x08, 0xc1, 0x77, 0xcc, 0x9d, 0x86, 0x0d, 0xe4, 0xc9, 0x2c, 0x99, - 0x67, 0xf8, 0xe2, 0xda, 0x96, 0xf8, 0xb8, 0x87, 0x20, 0x0a, 0x3d, 0x22, 0x86, 0xba, 0x8c, 0xcb, 0xcf, 0xf6, 0xc4, - 0xa1, 0x8d, 0xb3, 0x80, 0x19, 0x8a, 0xca, 0x8c, 0x47, 0x71, 0x22, 0x1a, 0xaf, 0xc0, 0xa7, 0x91, 0xee, 0x48, 0xe8, - 0xec, 0x6e, 0x55, 0xb0, 0x01, 0xf0, 0x4a, 0x22, 0x88, 0x54, 0x4e, 0x5b, 0x94, 0x53, 0x0a, 0x80, 0xdc, 0xe6, 0xd5, - 0x27, 0x9d, 0x80, 0x29, 0xc0, 0x88, 0x1e, 0x1d, 0xd3, 0x6c, 0x83, 0x21, 0x12, 0x0b, 0x67, 0x6c, 0x6c, 0x5d, 0xfb, - 0x2f, 0xff, 0xfc, 0x0f, 0xb6, 0x27, 0x40, 0xcc, 0xc6, 0x63, 0x90, 0x72, 0xd6, 0xba, 0x86, 0xff, 0xeb, 0x1f, 0xff, - 0xef, 0xff, 0xf9, 0xaf, 0xba, 0x6d, 0x0a, 0x4d, 0x4f, 0x02, 0x71, 0xb4, 0xa0, 0x49, 0x4a, 0x29, 0x9e, 0xf6, 0x38, - 0x4a, 0x57, 0x80, 0x74, 0x08, 0x54, 0x9a, 0x31, 0x36, 0xf2, 0x6c, 0x0b, 0x34, 0x81, 0x78, 0x3e, 0x4e, 0xd8, 0x39, - 0x93, 0x1f, 0x96, 0xd1, 0x83, 0xe8, 0xca, 0x21, 0x58, 0x30, 0x5c, 0xde, 0x79, 0x95, 0xdb, 0x40, 0xd1, 0x52, 0x52, - 0xbc, 0x4e, 0x30, 0xcf, 0x36, 0x06, 0x6d, 0xce, 0xd1, 0xae, 0x0f, 0xeb, 0x81, 0x4a, 0xb5, 0x6d, 0x01, 0x2f, 0x99, - 0xbd, 0xab, 0x20, 0x5e, 0x82, 0xeb, 0x34, 0xc7, 0xa6, 0x29, 0x2b, 0x8a, 0x55, 0x60, 0x01, 0x4d, 0x3c, 0xbb, 0x6a, - 0x62, 0xd7, 0x3a, 0x00, 0x00, 0xdd, 0x9d, 0x1d, 0x31, 0x2d, 0x54, 0xb0, 0xf1, 0x18, 0x36, 0x38, 0xea, 0xb6, 0x84, - 0xe3, 0xb1, 0x45, 0xd8, 0xb7, 0xdf, 0x82, 0x2c, 0xb1, 0xc1, 0x3f, 0x74, 0xf5, 0x01, 0x34, 0x4d, 0xaf, 0x84, 0x9d, - 0x31, 0x87, 0xe8, 0x6c, 0x0c, 0xa3, 0x9f, 0x0c, 0xa4, 0xb2, 0xe1, 0xa7, 0x55, 0x8c, 0xb1, 0x96, 0x11, 0xfe, 0xfd, - 0x5f, 0xfe, 0xf1, 0xbf, 0xc1, 0xd8, 0xd4, 0x6f, 0x3d, 0x17, 0x40, 0xab, 0xff, 0x09, 0xad, 0xe6, 0xe9, 0x2d, 0xed, - 0xfe, 0xf2, 0xf7, 0xff, 0x1d, 0x9a, 0xd1, 0x45, 0x29, 0xe0, 0x13, 0x82, 0x68, 0x88, 0xb6, 0xe9, 0xaf, 0x02, 0xa9, - 0x36, 0xc8, 0xda, 0x99, 0xfe, 0x09, 0xc1, 0x2e, 0x78, 0x36, 0xbb, 0x11, 0x1c, 0x84, 0x7a, 0x98, 0x64, 0x05, 0xd3, - 0xf0, 0x08, 0x7d, 0xf2, 0xeb, 0x00, 0xa2, 0xb9, 0x66, 0xb0, 0x6b, 0x0b, 0x4b, 0x8f, 0x23, 0x56, 0x68, 0xd5, 0x38, - 0x8d, 0x05, 0x2c, 0x18, 0x27, 0x74, 0x28, 0xdc, 0x03, 0x4b, 0x26, 0x9e, 0xe0, 0x81, 0x04, 0x9c, 0x5b, 0xff, 0xf8, - 0xda, 0xea, 0xc1, 0x34, 0xc3, 0x89, 0xb1, 0x44, 0x84, 0x4b, 0x8d, 0x00, 0x7f, 0x41, 0x08, 0x1f, 0xeb, 0xe7, 0xe8, - 0x52, 0x3f, 0xa3, 0xa0, 0x16, 0x13, 0x80, 0xbe, 0x9d, 0xa2, 0x31, 0x66, 0xce, 0x20, 0xb2, 0x33, 0x2a, 0xf7, 0xde, - 0x48, 0xf2, 0x11, 0xc2, 0xf8, 0x18, 0x73, 0x61, 0xf1, 0xe6, 0xd3, 0x3c, 0x67, 0xc7, 0x49, 0x76, 0x81, 0x31, 0x43, - 0x24, 0xd2, 0xba, 0xfa, 0xf2, 0xdf, 0xfe, 0xd5, 0xf7, 0xff, 0xed, 0x5f, 0xd7, 0x34, 0x98, 0xc0, 0x9e, 0x00, 0x23, - 0x9f, 0x87, 0x9a, 0xce, 0x0d, 0xb4, 0x56, 0x0f, 0x8a, 0x78, 0xae, 0xae, 0x91, 0x88, 0x63, 0xa9, 0xc4, 0x5b, 0x3e, - 0x12, 0xda, 0x9a, 0x29, 0x6e, 0x9f, 0x05, 0x21, 0x5b, 0x33, 0x0d, 0x56, 0xdd, 0x32, 0xcf, 0x89, 0x1b, 0xdc, 0x40, - 0x97, 0x5f, 0x89, 0xf1, 0x6a, 0x30, 0x6e, 0x85, 0xc0, 0x03, 0x6d, 0x26, 0xf4, 0xdd, 0x33, 0xa1, 0xad, 0x02, 0xb1, - 0x0c, 0x52, 0x77, 0xd5, 0x00, 0xf2, 0xac, 0x03, 0x9a, 0x80, 0x9a, 0xc4, 0x95, 0xad, 0x40, 0xe6, 0xd6, 0x69, 0xde, - 0x7f, 0x83, 0x97, 0x1d, 0x2d, 0xec, 0x8d, 0x96, 0x42, 0x41, 0x86, 0x0d, 0x27, 0xc3, 0x46, 0x6a, 0x54, 0xd3, 0xa6, - 0x40, 0xc7, 0x2f, 0x5b, 0x6d, 0x3b, 0x1c, 0x63, 0xf7, 0x9a, 0xf6, 0xe7, 0x52, 0xfb, 0xc7, 0xd2, 0xde, 0x97, 0xda, - 0x1f, 0x3f, 0x69, 0xd3, 0xd0, 0xfe, 0xf1, 0x5a, 0xed, 0x8f, 0x94, 0x1b, 0xe0, 0xc8, 0xa1, 0xbd, 0x89, 0xd1, 0x2d, - 0xc3, 0xd6, 0xe0, 0x68, 0x67, 0x0d, 0x27, 0x6c, 0xf8, 0x49, 0x9a, 0x59, 0x84, 0x00, 0x86, 0x77, 0xb4, 0x31, 0x29, - 0x30, 0x00, 0x93, 0xe1, 0xa4, 0xd4, 0x9b, 0x1e, 0x1f, 0x8d, 0x09, 0xb8, 0xbb, 0x18, 0x33, 0x14, 0xfd, 0xb0, 0x66, - 0x5f, 0xb1, 0x72, 0x0b, 0xc7, 0x11, 0x1b, 0x46, 0x3c, 0x03, 0x66, 0x5b, 0x38, 0xd8, 0x89, 0xb7, 0x10, 0xc1, 0xc2, - 0xc0, 0x7e, 0xff, 0x6e, 0xff, 0xc0, 0xf6, 0x4e, 0xb3, 0xd1, 0x55, 0x60, 0x83, 0x33, 0x06, 0xd6, 0x94, 0xeb, 0xf3, - 0x09, 0x4b, 0x1d, 0xe5, 0xf9, 0x64, 0x09, 0xb8, 0x9a, 0xd9, 0x99, 0xf8, 0xb6, 0x45, 0xf3, 0xa0, 0x03, 0x08, 0x4b, - 0x1f, 0xbf, 0xec, 0xef, 0x72, 0xf1, 0x5d, 0x58, 0x9e, 0xe3, 0x63, 0x1f, 0x53, 0x3d, 0x76, 0xb7, 0xe0, 0x01, 0x5f, - 0xf6, 0x51, 0xef, 0xd1, 0xdb, 0xc6, 0x62, 0xc9, 0x6d, 0x18, 0xe0, 0x10, 0x93, 0xbe, 0x40, 0xa1, 0xa0, 0x56, 0x27, - 0x01, 0x22, 0x06, 0x8f, 0x30, 0xd6, 0x96, 0x1a, 0x17, 0x21, 0x54, 0xfd, 0xb5, 0xe3, 0x52, 0xd9, 0xad, 0x34, 0xef, - 0x08, 0xcd, 0x52, 0x72, 0x5c, 0xb0, 0xf7, 0x48, 0x97, 0x08, 0x53, 0x87, 0x8a, 0xd6, 0x41, 0xa0, 0x6b, 0x2a, 0x73, - 0x45, 0x74, 0x30, 0x80, 0x21, 0x33, 0x57, 0x00, 0x02, 0x7f, 0x09, 0xed, 0x13, 0xf3, 0xfb, 0x6f, 0xe2, 0x53, 0x4d, - 0x9a, 0x38, 0x87, 0x7f, 0xf2, 0xae, 0x98, 0x77, 0x75, 0x42, 0x2d, 0x55, 0xb0, 0x01, 0xa3, 0x60, 0x18, 0x94, 0x69, - 0xab, 0xa8, 0x12, 0xd8, 0x69, 0x49, 0x34, 0x2b, 0x58, 0xa0, 0x1e, 0x64, 0xdc, 0x01, 0xc3, 0x17, 0xcb, 0x81, 0x1e, - 0xd3, 0x9e, 0x2b, 0xf9, 0x64, 0x61, 0x06, 0x26, 0x1e, 0xb5, 0xdb, 0x3d, 0xbc, 0x54, 0xd1, 0x8a, 0xc0, 0x3a, 0x48, - 0x83, 0x84, 0x8d, 0x79, 0xc9, 0xf1, 0xd6, 0xfe, 0x42, 0x45, 0x82, 0xfc, 0xee, 0x4e, 0xce, 0xa6, 0x96, 0x8f, 0xff, - 0xbf, 0x6d, 0xec, 0x51, 0x90, 0xf2, 0x49, 0x8b, 0xae, 0xf1, 0xe0, 0x15, 0x49, 0x80, 0xc8, 0x7c, 0x5f, 0x18, 0x13, - 0x0d, 0x19, 0x46, 0xc9, 0x4a, 0x9e, 0x83, 0xbc, 0xf7, 0x78, 0x6e, 0xb6, 0x03, 0x39, 0xbd, 0x14, 0x2a, 0x5b, 0x0e, - 0xd6, 0x6c, 0xbb, 0xd2, 0x3f, 0x5a, 0x6e, 0xac, 0x22, 0x5e, 0xf5, 0xb7, 0x25, 0x0a, 0x19, 0xb1, 0xb9, 0x52, 0xa8, - 0xa8, 0x85, 0xe8, 0x61, 0xe2, 0xb4, 0x1c, 0xb5, 0xbb, 0xd5, 0x62, 0x2e, 0x49, 0x5c, 0x1c, 0x92, 0xb8, 0x20, 0xf1, - 0x77, 0xb4, 0x10, 0x73, 0x0f, 0xa3, 0x64, 0xe8, 0x20, 0x00, 0x56, 0xcb, 0x7a, 0x02, 0xd4, 0x74, 0x55, 0xe4, 0xc8, - 0x7f, 0x8c, 0xc4, 0x2d, 0x85, 0xb0, 0x5c, 0x41, 0xa5, 0x93, 0xa3, 0xb2, 0xec, 0x31, 0xe6, 0x1c, 0x7e, 0x90, 0x97, - 0x40, 0xc4, 0xdd, 0x5f, 0xfd, 0xfd, 0xc4, 0x76, 0xe9, 0x1e, 0x79, 0x3f, 0x1b, 0x1f, 0xa5, 0xb3, 0x15, 0xb3, 0xdb, - 0x1e, 0x2c, 0x83, 0xd9, 0x53, 0x7e, 0x42, 0xf2, 0xa6, 0xbe, 0x26, 0x9b, 0x53, 0xff, 0x9f, 0x43, 0x1c, 0xe1, 0x8d, - 0x63, 0xa3, 0x89, 0x4e, 0x23, 0x5f, 0xb5, 0x88, 0x3f, 0x6d, 0xec, 0x2a, 0x8e, 0x40, 0xbe, 0x5e, 0x17, 0xc9, 0xfa, - 0xe6, 0xf6, 0x48, 0x56, 0x71, 0xc7, 0x48, 0xd6, 0x37, 0xbf, 0x73, 0x24, 0xeb, 0x6b, 0x33, 0x92, 0x85, 0x02, 0xfa, - 0xd5, 0xaf, 0x89, 0x36, 0xe5, 0xd9, 0x45, 0x11, 0x76, 0x64, 0xe6, 0x04, 0xc8, 0x3a, 0x0c, 0x3b, 0xfd, 0xf5, 0x23, - 0x4c, 0x30, 0x51, 0x23, 0xbe, 0x44, 0x01, 0x25, 0x91, 0xec, 0x09, 0x6a, 0x45, 0x86, 0x73, 0xda, 0x3a, 0xab, 0xb2, - 0xf5, 0x50, 0x5d, 0x23, 0x03, 0xd7, 0xd7, 0xd5, 0xa1, 0xb6, 0xae, 0x0a, 0xf8, 0x04, 0xf4, 0x1d, 0x58, 0xdd, 0xb1, - 0xbb, 0xa9, 0xd2, 0xf9, 0xcc, 0x11, 0x7a, 0xea, 0x94, 0x46, 0x30, 0xd1, 0xc2, 0xfe, 0x2f, 0x87, 0x9d, 0xde, 0x76, - 0x67, 0x0a, 0xbd, 0x41, 0x81, 0xc3, 0x5b, 0xbb, 0xb7, 0xbd, 0x8d, 0x6f, 0x17, 0xea, 0xad, 0x8b, 0x6f, 0xb1, 0x7a, - 0xdb, 0xc1, 0xb7, 0xa1, 0x7a, 0x7b, 0x84, 0x6f, 0x23, 0xf5, 0xf6, 0x18, 0xdf, 0xce, 0xed, 0xf2, 0x90, 0x6b, 0xe0, - 0x1e, 0x03, 0x5f, 0x91, 0x37, 0x13, 0xa8, 0x32, 0xd8, 0xf4, 0x78, 0xfd, 0x32, 0x3a, 0x0b, 0x62, 0x4f, 0x78, 0x97, - 0x41, 0xee, 0x5d, 0x80, 0xc6, 0x09, 0x28, 0xdb, 0xf0, 0x39, 0x7e, 0x87, 0x03, 0x9c, 0xa4, 0x83, 0x78, 0xca, 0xd4, - 0x07, 0x89, 0x15, 0xd6, 0x60, 0xc0, 0x1e, 0xb6, 0x8f, 0xca, 0x9e, 0x5e, 0x27, 0x11, 0xcf, 0x52, 0xd9, 0x1c, 0xb4, - 0x72, 0x55, 0x9d, 0x98, 0xae, 0xa5, 0x57, 0x78, 0x8d, 0xfe, 0x32, 0xe2, 0x11, 0x63, 0x30, 0xcc, 0x5a, 0x97, 0xe0, - 0xc1, 0xae, 0xd4, 0x69, 0x08, 0x91, 0xd6, 0x69, 0x84, 0x93, 0x7e, 0x3b, 0x88, 0xce, 0xf4, 0xf3, 0x1b, 0xb0, 0xb4, - 0xa3, 0x33, 0xd9, 0x72, 0xbd, 0x0e, 0x23, 0x10, 0x4d, 0xfd, 0xa5, 0x80, 0x20, 0x53, 0x0c, 0x96, 0x06, 0x3d, 0x69, - 0xa9, 0xbf, 0x90, 0x3a, 0x75, 0x8d, 0x46, 0xd3, 0xd7, 0x8b, 0x80, 0xa2, 0x55, 0xc1, 0x2e, 0x18, 0xfc, 0x54, 0x2a, - 0x28, 0x0c, 0x15, 0x58, 0x20, 0xaa, 0xd7, 0xa8, 0x32, 0x1d, 0x6c, 0x58, 0xab, 0xd0, 0x2c, 0xa5, 0xcb, 0xcc, 0xd3, - 0x1d, 0x7d, 0xb4, 0xb3, 0x2c, 0x5e, 0x3f, 0xeb, 0x0c, 0xf1, 0x1f, 0x29, 0xbc, 0x3f, 0x1b, 0x8f, 0xc7, 0x37, 0xea, - 0xb6, 0xcf, 0x46, 0x63, 0xd6, 0x65, 0x3b, 0x3d, 0x8c, 0xfc, 0xb7, 0xa4, 0x38, 0xed, 0x94, 0x44, 0xbb, 0xc5, 0xdd, - 0x1a, 0xa3, 0xe4, 0x05, 0x75, 0x77, 0x77, 0x25, 0x58, 0x02, 0x55, 0x16, 0x20, 0xfc, 0xcf, 0xe2, 0x34, 0x68, 0x97, - 0xfe, 0xb9, 0xd4, 0x1a, 0x9f, 0x3d, 0x79, 0xf2, 0xa4, 0xf4, 0x47, 0xea, 0xad, 0x3d, 0x1a, 0x95, 0xfe, 0x70, 0xa1, - 0xd1, 0x68, 0xb7, 0xc7, 0xe3, 0xd2, 0x8f, 0x55, 0xc1, 0x76, 0x77, 0x38, 0xda, 0xee, 0x96, 0xfe, 0x85, 0xd1, 0xa2, - 0xf4, 0x99, 0x7c, 0xcb, 0xd9, 0xa8, 0x76, 0x7c, 0xf0, 0xb8, 0x0d, 0x95, 0x82, 0xd1, 0x16, 0xe8, 0x5d, 0x8a, 0xc7, - 0x20, 0x9a, 0xf3, 0x0c, 0x0c, 0xbb, 0xb2, 0x57, 0x80, 0x7c, 0x1e, 0x4b, 0x09, 0x2f, 0xbe, 0xf7, 0x8b, 0x52, 0xfd, - 0x95, 0x29, 0xd5, 0x91, 0x99, 0x49, 0x9a, 0x17, 0xa4, 0x0d, 0x9a, 0xd5, 0xc8, 0x59, 0x54, 0xfd, 0x2a, 0x2c, 0x2a, - 0x61, 0x8f, 0xd2, 0x06, 0x5b, 0x0a, 0x19, 0xff, 0xc3, 0x3a, 0x19, 0xff, 0xfd, 0xed, 0x32, 0xfe, 0xf4, 0x6e, 0x22, - 0xfe, 0xfb, 0xdf, 0x59, 0xc4, 0xff, 0x60, 0x8a, 0x78, 0x21, 0xc4, 0xf6, 0xc0, 0x74, 0x26, 0x9b, 0xf9, 0x34, 0xbb, - 0x6c, 0xe1, 0x96, 0xc8, 0x6d, 0x92, 0x9e, 0xd3, 0x3b, 0x09, 0xff, 0x15, 0xf9, 0x60, 0x6a, 0x30, 0xe3, 0xe3, 0xc1, - 0x3c, 0x3b, 0x3b, 0x4b, 0x98, 0x92, 0xf1, 0x46, 0x05, 0x99, 0xe3, 0xef, 0xd2, 0xd0, 0x7e, 0x07, 0x9e, 0xb1, 0x51, - 0x32, 0x1e, 0x43, 0xd1, 0x78, 0x6c, 0xab, 0x7c, 0x69, 0x90, 0x67, 0xd4, 0xea, 0x6d, 0xad, 0x84, 0x5a, 0x7d, 0xf1, - 0x85, 0x59, 0x66, 0x16, 0xc8, 0x90, 0x9e, 0x69, 0x8c, 0xc8, 0x9a, 0x51, 0x5c, 0xe0, 0x1e, 0xac, 0x3e, 0x76, 0x8c, - 0xf6, 0xce, 0x14, 0x94, 0x4a, 0x3c, 0xc4, 0x73, 0x91, 0xe6, 0x87, 0x65, 0x44, 0x6e, 0xfb, 0x32, 0x72, 0xd5, 0xf9, - 0xb7, 0xf1, 0x0d, 0xc3, 0xea, 0xcc, 0x1b, 0x16, 0x5f, 0xe6, 0xb7, 0x3c, 0xbd, 0x7a, 0x35, 0x72, 0xf6, 0xc0, 0x1a, - 0x8e, 0x8b, 0x77, 0x69, 0x23, 0x6f, 0x50, 0x80, 0x1d, 0x86, 0x26, 0xa6, 0xa5, 0x20, 0x58, 0x75, 0x81, 0xa2, 0xaa, - 0xec, 0x19, 0x9d, 0x64, 0x7a, 0x19, 0x0e, 0x39, 0xa8, 0x91, 0x25, 0x30, 0x07, 0x93, 0xba, 0x90, 0x3e, 0x66, 0x2f, - 0x92, 0x6e, 0xce, 0xe5, 0x57, 0xcf, 0xe9, 0x70, 0x66, 0x21, 0xf5, 0x87, 0x4c, 0xc7, 0xa8, 0x7a, 0xe2, 0x79, 0x88, - 0x98, 0x61, 0x54, 0xaa, 0x33, 0x10, 0x20, 0xdc, 0x0c, 0x3f, 0xd1, 0x24, 0x86, 0x50, 0x07, 0x05, 0x15, 0xf5, 0xae, - 0xaf, 0xcd, 0x2f, 0x85, 0xd6, 0xbe, 0x2a, 0xd9, 0xe0, 0x01, 0x86, 0x9f, 0xf8, 0x45, 0x6d, 0x90, 0xcd, 0xb9, 0xe3, - 0x50, 0x2b, 0xc7, 0x2d, 0xbd, 0x9d, 0x76, 0x1b, 0x54, 0x8c, 0x2f, 0xbe, 0x03, 0xe5, 0xe8, 0xce, 0x12, 0xdf, 0x75, - 0xe7, 0x12, 0x4b, 0xdf, 0x65, 0xd3, 0x24, 0xc6, 0x0f, 0xc7, 0x08, 0x44, 0x8d, 0xbb, 0x43, 0x6a, 0x11, 0x9b, 0xef, - 0xbe, 0xf2, 0x1d, 0x0d, 0xc2, 0xba, 0xab, 0x38, 0x58, 0xe6, 0xd6, 0xd6, 0x0b, 0xb1, 0xad, 0xb0, 0x6a, 0x96, 0xc1, - 0xb9, 0x45, 0x67, 0x16, 0x17, 0x46, 0x00, 0xbf, 0xb6, 0x0d, 0x4a, 0x15, 0xc1, 0x17, 0x61, 0xf8, 0x3d, 0x0c, 0x36, - 0x0b, 0xc7, 0x5b, 0x01, 0x5d, 0x77, 0x79, 0x0d, 0xc8, 0xd1, 0x19, 0xd6, 0x8c, 0xae, 0xaa, 0x54, 0x41, 0x69, 0x1e, - 0xc1, 0x18, 0xc8, 0x50, 0x24, 0x1d, 0xd6, 0x38, 0x15, 0x7a, 0x0b, 0xa6, 0x21, 0x01, 0xac, 0xfd, 0x3a, 0x74, 0x6b, - 0x6c, 0x05, 0xb6, 0x90, 0x16, 0xa0, 0xf4, 0xb0, 0x43, 0xdf, 0xaa, 0x81, 0x9e, 0x2e, 0x07, 0xe0, 0x6f, 0x74, 0xf2, - 0x4e, 0xfc, 0xe2, 0xc2, 0x83, 0xff, 0xac, 0x3f, 0x2c, 0x40, 0xca, 0x9f, 0x7e, 0x8a, 0x39, 0xd8, 0xd4, 0xb3, 0x16, - 0x86, 0x5f, 0x28, 0x4e, 0x2b, 0xd5, 0x21, 0x1d, 0x45, 0x8b, 0x2b, 0x63, 0xbd, 0x79, 0x81, 0xbe, 0x20, 0x39, 0x3d, - 0x41, 0x9a, 0xa5, 0xac, 0x57, 0x4f, 0x39, 0x30, 0xfd, 0x0e, 0x45, 0xac, 0xa3, 0x45, 0x86, 0xbe, 0x23, 0xbf, 0x02, - 0xdf, 0x51, 0xa8, 0xd1, 0xb6, 0x72, 0x3a, 0xda, 0x2b, 0xdb, 0x07, 0x92, 0xb6, 0x9b, 0x64, 0x2d, 0xe4, 0xcb, 0xce, - 0xd5, 0x3a, 0xe7, 0xe8, 0xb6, 0x03, 0x78, 0x0c, 0x0a, 0xab, 0xff, 0x8c, 0xcc, 0x85, 0x66, 0x31, 0x1d, 0xc0, 0xdf, - 0x05, 0xb2, 0x20, 0x1a, 0xe3, 0x17, 0x16, 0xef, 0xd2, 0xf2, 0x94, 0xb2, 0x5f, 0x17, 0xa8, 0xd6, 0x83, 0xce, 0x13, - 0xf0, 0xf6, 0xee, 0x3c, 0xfc, 0xcd, 0xe8, 0x97, 0x92, 0x46, 0xea, 0x12, 0xb3, 0x6d, 0xf7, 0x50, 0x5e, 0x24, 0xd1, - 0x15, 0x38, 0x9d, 0x64, 0x63, 0x9c, 0x62, 0xf4, 0xb8, 0x37, 0xcb, 0x64, 0x26, 0x49, 0xce, 0x12, 0xfa, 0x19, 0x13, - 0xb9, 0x14, 0xdb, 0x8f, 0x66, 0x97, 0x6a, 0x35, 0x3a, 0x8d, 0x0c, 0x91, 0xdf, 0x35, 0x11, 0x64, 0x7d, 0xe6, 0x49, - 0x3d, 0x99, 0x61, 0x07, 0x60, 0x10, 0x86, 0x4d, 0x2b, 0x17, 0x50, 0xb5, 0xa1, 0xc4, 0x48, 0x85, 0xa9, 0x06, 0xb2, - 0xfc, 0x6d, 0x50, 0x95, 0x51, 0xc1, 0x7a, 0xf8, 0xa9, 0xcb, 0x18, 0x5c, 0x5b, 0x69, 0x3c, 0x4d, 0xe3, 0xd1, 0x28, - 0x61, 0x3d, 0x65, 0x1f, 0x59, 0x9d, 0x47, 0x98, 0x49, 0x62, 0x2e, 0x59, 0x7d, 0x55, 0x0c, 0xe2, 0x69, 0x3a, 0x45, - 0xa7, 0x60, 0xaf, 0xe1, 0xf7, 0x2a, 0x57, 0x92, 0x53, 0xa6, 0x58, 0xb4, 0x2b, 0xe2, 0xd1, 0x73, 0x1d, 0x97, 0x1d, - 0x30, 0x16, 0x69, 0xc1, 0xdb, 0x3d, 0x9e, 0xcd, 0x82, 0xd6, 0x76, 0x1d, 0x11, 0xac, 0xd2, 0x28, 0x78, 0x2b, 0xd0, - 0xf2, 0xd0, 0x3a, 0x10, 0x5a, 0xce, 0xf2, 0x3b, 0xb2, 0x8c, 0x06, 0xc0, 0x6f, 0x22, 0xea, 0xa2, 0xb2, 0x8e, 0xcc, - 0x5f, 0x67, 0xb7, 0x7c, 0xbe, 0x7a, 0xb7, 0x7c, 0xae, 0x76, 0xcb, 0xcd, 0x1c, 0xfb, 0xd9, 0xb8, 0x83, 0xff, 0xf4, - 0x2a, 0x84, 0x60, 0x55, 0x80, 0x1c, 0x16, 0xda, 0xc5, 0xad, 0x2e, 0xfc, 0x8f, 0x86, 0x6e, 0x7b, 0xf8, 0x8f, 0x0f, - 0x16, 0x60, 0xdb, 0xc2, 0x42, 0xfc, 0xaf, 0x5d, 0xab, 0xea, 0x3c, 0xc4, 0x3a, 0xec, 0xb5, 0xb3, 0x5c, 0xd7, 0xbd, - 0x79, 0xd3, 0x82, 0xbc, 0xe2, 0x4e, 0xa0, 0x84, 0x31, 0xb8, 0x6a, 0xd1, 0xe9, 0x29, 0x94, 0x8e, 0xb3, 0xe1, 0xbc, - 0xf8, 0x5b, 0x09, 0xbf, 0x24, 0xe2, 0x8d, 0x5b, 0xba, 0x31, 0x8e, 0xea, 0x2a, 0xd2, 0x92, 0xd4, 0x08, 0x0b, 0xbd, - 0x4e, 0x41, 0x01, 0x8c, 0xc9, 0x9c, 0xae, 0xff, 0x70, 0xc5, 0x26, 0xf8, 0xff, 0xb2, 0x36, 0x2b, 0x91, 0xf9, 0x8f, - 0x12, 0xe3, 0x46, 0x22, 0xfc, 0x2a, 0x1a, 0x98, 0x6b, 0xd8, 0x7e, 0xb2, 0x1a, 0xdc, 0x43, 0x35, 0xd3, 0x91, 0x52, - 0x0a, 0x52, 0xef, 0x80, 0x17, 0x10, 0xcd, 0x13, 0x7e, 0xf3, 0xa8, 0xeb, 0x38, 0x63, 0x69, 0xd4, 0x1b, 0x04, 0x7a, - 0xd5, 0xf6, 0x8e, 0x52, 0xfa, 0xb3, 0xcf, 0x1f, 0xe2, 0x3f, 0x22, 0x70, 0x76, 0x5a, 0xf9, 0x46, 0x22, 0x36, 0x80, - 0xbe, 0xd1, 0xb4, 0xe6, 0xfc, 0x08, 0x0d, 0x4e, 0xfe, 0xcf, 0x5d, 0x5b, 0xa3, 0xb1, 0x7e, 0xa7, 0xe6, 0xd2, 0x2a, - 0xfd, 0x55, 0xad, 0x7f, 0xdd, 0xe0, 0x77, 0x6c, 0x3b, 0x14, 0x0e, 0x41, 0xbd, 0xad, 0x8c, 0x07, 0x2e, 0x35, 0x56, - 0x14, 0xbf, 0x6b, 0xfb, 0xca, 0x24, 0xa6, 0x1e, 0xd3, 0xf0, 0x54, 0x3b, 0x91, 0xf2, 0xf0, 0x1e, 0x7b, 0x08, 0x3f, - 0xf2, 0x4b, 0x16, 0x3e, 0xc0, 0xaf, 0xb1, 0x59, 0x97, 0xd3, 0x24, 0x05, 0xb3, 0x6a, 0xc2, 0xf9, 0x2c, 0xd8, 0xda, - 0xba, 0xb8, 0xb8, 0xf0, 0x2f, 0xb6, 0xfd, 0x2c, 0x3f, 0xdb, 0xea, 0xb6, 0xdb, 0x6d, 0xfc, 0x88, 0x96, 0x6d, 0x9d, - 0xc7, 0xec, 0xe2, 0x29, 0xb8, 0x1f, 0xf6, 0x63, 0xeb, 0x89, 0xf5, 0x78, 0xdb, 0xda, 0x79, 0x64, 0x5b, 0xa4, 0x00, - 0xa0, 0x64, 0xdb, 0xb6, 0x84, 0x02, 0x08, 0x6d, 0x28, 0xee, 0xef, 0x9e, 0x29, 0x1b, 0x0e, 0x2f, 0x29, 0x08, 0x0b, - 0x09, 0xfc, 0xb7, 0xec, 0x13, 0xab, 0x6f, 0x75, 0x51, 0xd6, 0x92, 0x6a, 0x44, 0xbd, 0xe2, 0x7e, 0x1f, 0x46, 0xb3, - 0x80, 0xd8, 0xc8, 0x2c, 0xc4, 0x30, 0x99, 0x28, 0xa5, 0x29, 0xd0, 0x2e, 0x3d, 0x85, 0x27, 0xcc, 0x6a, 0xb3, 0xe0, - 0xf9, 0x4d, 0xf7, 0x31, 0xe8, 0xb8, 0xf3, 0xd6, 0xc3, 0x61, 0xbb, 0xd5, 0xb1, 0x3a, 0xad, 0xae, 0xff, 0xd8, 0xea, - 0x8a, 0xff, 0x83, 0x8c, 0xdc, 0xb6, 0x3a, 0xf0, 0xb4, 0x6d, 0xc1, 0xfb, 0xf9, 0x43, 0x91, 0x5b, 0x12, 0xd9, 0x5b, - 0xfd, 0x5d, 0xfc, 0x4d, 0x29, 0x40, 0xea, 0x73, 0x5b, 0xfc, 0x0a, 0x9e, 0xfd, 0x99, 0x59, 0xda, 0x79, 0xb2, 0xb2, - 0xb8, 0xfb, 0x78, 0x65, 0xf1, 0xf6, 0xa3, 0x95, 0xc5, 0x0f, 0x77, 0xea, 0xc5, 0x5b, 0x67, 0xa2, 0x4a, 0xcb, 0x85, - 0xd0, 0x9e, 0x46, 0xc0, 0x28, 0x97, 0x4e, 0x07, 0xe0, 0x6c, 0x5b, 0x2d, 0xfc, 0xf3, 0xb8, 0xeb, 0xea, 0x5e, 0xa7, - 0xd8, 0x4b, 0x63, 0xf9, 0xf8, 0x09, 0x60, 0xf9, 0xb2, 0xfb, 0x68, 0x88, 0xed, 0x08, 0x51, 0xf8, 0xef, 0x7c, 0xfb, - 0xc9, 0x10, 0x34, 0x82, 0x85, 0xff, 0xc1, 0x3f, 0x93, 0x9d, 0xee, 0x50, 0xbc, 0xb4, 0xb1, 0xfe, 0xdb, 0xce, 0xe3, - 0x02, 0x9a, 0xe2, 0x3f, 0xbf, 0x68, 0x13, 0x1a, 0x0d, 0x78, 0x73, 0xdc, 0x87, 0x40, 0xa3, 0x27, 0x93, 0xae, 0xff, - 0xf9, 0xf9, 0x63, 0xff, 0xc9, 0xa4, 0xf3, 0xf8, 0x5b, 0xf1, 0x96, 0x00, 0x05, 0x3f, 0xc7, 0xff, 0xbe, 0xdd, 0x6e, - 0x4f, 0x5a, 0x1d, 0xff, 0xc9, 0xf9, 0xb6, 0xbf, 0x9d, 0xb4, 0x1e, 0xf9, 0x4f, 0xf0, 0xbf, 0x6a, 0xb8, 0x49, 0x36, - 0x65, 0xb6, 0x85, 0xeb, 0xdd, 0xf0, 0x7b, 0xcd, 0x39, 0xba, 0x0f, 0xad, 0x9d, 0x87, 0x2f, 0x9f, 0xc0, 0x1a, 0x4d, - 0x3a, 0x5d, 0xf8, 0xff, 0xba, 0xc7, 0x6f, 0x91, 0xf0, 0x72, 0xe0, 0x88, 0x61, 0x7a, 0xb1, 0x22, 0x1c, 0x7d, 0xd0, - 0xed, 0x81, 0xf7, 0xa7, 0x75, 0x01, 0x10, 0xc6, 0x6f, 0x0d, 0x80, 0x70, 0x7e, 0xb7, 0x08, 0x08, 0xfd, 0xda, 0xc0, - 0xef, 0x18, 0x01, 0xf9, 0x53, 0x33, 0xc8, 0x7d, 0xc9, 0x96, 0x02, 0x1d, 0x4d, 0x67, 0xed, 0x2d, 0x73, 0x0e, 0xbf, - 0x64, 0x47, 0x98, 0x4a, 0x0f, 0xad, 0x39, 0x37, 0xe3, 0x41, 0x19, 0x6e, 0xe4, 0x4b, 0x26, 0x76, 0x72, 0xc1, 0xd7, - 0x10, 0x24, 0xbe, 0x9d, 0x20, 0xdf, 0xde, 0x8d, 0x1e, 0xf1, 0xef, 0x4c, 0x8f, 0x82, 0x1b, 0xf4, 0xa8, 0x45, 0xdc, - 0x29, 0x62, 0x40, 0x8e, 0xfe, 0x3e, 0xbd, 0x3b, 0x9c, 0xbe, 0xc5, 0xb6, 0xc5, 0xb0, 0xa8, 0xb0, 0x45, 0xce, 0xe6, - 0xd3, 0x5f, 0x73, 0x44, 0x20, 0xd2, 0xcd, 0x43, 0x5b, 0x46, 0x61, 0x66, 0xf8, 0xd1, 0x62, 0xf5, 0x72, 0x2e, 0xae, - 0x34, 0x85, 0x74, 0x1f, 0x71, 0x47, 0x47, 0x70, 0xf0, 0x06, 0x40, 0xb8, 0xc8, 0x78, 0x84, 0xbf, 0x8a, 0x05, 0xe4, - 0xa6, 0xdf, 0xcf, 0x8a, 0x79, 0x82, 0x97, 0xa6, 0xbd, 0xa1, 0xf8, 0x80, 0x2c, 0x3c, 0xca, 0xbb, 0x86, 0x98, 0xc2, - 0xfe, 0x0d, 0xa6, 0xdf, 0xab, 0xb3, 0x83, 0x29, 0xc6, 0x11, 0xde, 0xb0, 0x51, 0x1c, 0x39, 0xb6, 0x33, 0x83, 0x8d, - 0x0c, 0xb3, 0xb4, 0x6a, 0xb9, 0xef, 0x94, 0xf6, 0xee, 0xda, 0xea, 0xa7, 0x99, 0x72, 0xfc, 0xd4, 0x5d, 0x78, 0x28, - 0xe3, 0x8e, 0xb6, 0x74, 0x0c, 0x60, 0x7c, 0x55, 0x92, 0xa3, 0x0e, 0xa8, 0x8c, 0x09, 0x5b, 0x58, 0x13, 0x1d, 0xbf, - 0x0b, 0xde, 0x05, 0x15, 0xe3, 0xa7, 0xc3, 0xbe, 0x77, 0x5a, 0xdb, 0x60, 0xed, 0x18, 0xdd, 0xf4, 0x40, 0x47, 0xfa, - 0x97, 0x7e, 0xf4, 0xaf, 0xd1, 0xd5, 0x2f, 0x0c, 0xd8, 0x82, 0x23, 0x3e, 0x13, 0xb8, 0xdb, 0xf4, 0x89, 0x06, 0x99, - 0x50, 0x82, 0x17, 0xe6, 0xa0, 0xcc, 0x31, 0x7f, 0x95, 0x4c, 0x7c, 0x9a, 0x4c, 0xfc, 0x00, 0x61, 0x59, 0x35, 0x61, - 0xd5, 0xcf, 0x7f, 0x20, 0x05, 0x99, 0xa7, 0x67, 0x23, 0xea, 0x61, 0x86, 0x07, 0xfe, 0xad, 0x8a, 0xd5, 0x83, 0x8c, - 0x58, 0x81, 0x17, 0x8f, 0xbf, 0xe9, 0x42, 0x7f, 0x96, 0xe2, 0x61, 0x22, 0xca, 0xd1, 0x28, 0xad, 0x86, 0xaa, 0xe2, - 0x5e, 0xc5, 0xd3, 0xab, 0x03, 0xf9, 0x41, 0x03, 0x1b, 0x43, 0xd0, 0x74, 0xf4, 0x50, 0x7d, 0x4c, 0x6d, 0x13, 0xf4, - 0x1e, 0xfd, 0xc4, 0x29, 0x65, 0x0f, 0xa0, 0x6a, 0xc3, 0xfb, 0x04, 0x96, 0x74, 0x81, 0x42, 0x5b, 0x28, 0xb6, 0x11, - 0x3b, 0x8f, 0x87, 0x52, 0x3f, 0x79, 0x96, 0xbc, 0x07, 0xd5, 0x22, 0xba, 0x87, 0x1d, 0x4f, 0x04, 0x01, 0xe0, 0x05, - 0xd5, 0x73, 0x98, 0x66, 0x76, 0xff, 0x41, 0x6f, 0x1d, 0x65, 0xf1, 0xf7, 0x56, 0x0f, 0xc1, 0xe9, 0xfc, 0xdb, 0xf0, - 0x01, 0xfe, 0xe2, 0xea, 0x83, 0x23, 0xdb, 0xf5, 0x49, 0xba, 0x3f, 0xa8, 0x7e, 0x76, 0x15, 0x45, 0xdb, 0x26, 0x28, - 0x62, 0xef, 0xae, 0x1a, 0x59, 0x6a, 0xdf, 0xee, 0x4e, 0xa5, 0x7d, 0xe1, 0xd9, 0x10, 0xb7, 0xa0, 0x09, 0xba, 0xfe, - 0x8e, 0x21, 0xd3, 0xcf, 0x5b, 0xf8, 0xb7, 0x26, 0xd5, 0x1f, 0x42, 0x03, 0x25, 0xd6, 0x5f, 0x43, 0xf3, 0x6d, 0xa1, - 0x41, 0xa0, 0xdf, 0x0f, 0x24, 0x73, 0x85, 0xbc, 0xad, 0xf3, 0xf8, 0x8a, 0xd3, 0x30, 0x91, 0x69, 0x61, 0x7b, 0x46, - 0xe0, 0x4c, 0x6c, 0x39, 0x19, 0x16, 0x7a, 0x0e, 0x7d, 0x1d, 0xfd, 0x8d, 0xf2, 0x55, 0x75, 0x5e, 0x4d, 0x04, 0xac, - 0x98, 0x02, 0x37, 0x6d, 0xe3, 0xc4, 0xad, 0x27, 0x92, 0xb8, 0xf5, 0x47, 0x4e, 0xd6, 0x73, 0xab, 0xcc, 0xf6, 0x76, - 0x8d, 0xfd, 0xcf, 0xe9, 0x3b, 0xaa, 0x34, 0xc9, 0xab, 0x51, 0xd9, 0x9c, 0x1f, 0x6c, 0x16, 0xfc, 0xd1, 0xc9, 0xea, - 0x0a, 0x8f, 0xbc, 0x9b, 0x8b, 0xf9, 0x14, 0xa3, 0x38, 0xa7, 0x2b, 0xdf, 0x0a, 0xf4, 0x5a, 0x54, 0xb5, 0xa2, 0x12, - 0x89, 0x00, 0x56, 0x0c, 0x6c, 0x2c, 0xb2, 0x03, 0x99, 0xf5, 0x67, 0x7e, 0x48, 0xdc, 0xbc, 0x93, 0x3b, 0x12, 0x09, - 0x7f, 0xf8, 0x43, 0x0b, 0xb6, 0xa0, 0x8f, 0x0d, 0xa2, 0x74, 0xed, 0x2e, 0x21, 0x03, 0x0b, 0x71, 0xad, 0x7e, 0x39, - 0xcb, 0x94, 0x2e, 0xb6, 0x49, 0x68, 0x3d, 0x2e, 0x91, 0xd0, 0x95, 0x74, 0x3a, 0x65, 0x11, 0xf7, 0xa3, 0x94, 0x92, - 0xb3, 0x1c, 0x43, 0x06, 0x79, 0x1d, 0xb6, 0xed, 0x96, 0x20, 0xf8, 0x8c, 0x9f, 0x16, 0x13, 0x9b, 0xd9, 0x87, 0x42, - 0xfd, 0x59, 0xab, 0x7a, 0xa2, 0xf5, 0xa4, 0xdb, 0x7f, 0x77, 0xb0, 0x67, 0x89, 0x4d, 0xb9, 0xbb, 0x05, 0xaf, 0xbb, - 0xe4, 0x9e, 0x8b, 0x3c, 0x95, 0x50, 0xe4, 0xa9, 0x58, 0x22, 0xbb, 0x4d, 0x24, 0x26, 0x6f, 0x09, 0xb4, 0x6d, 0x8b, - 0xa5, 0x43, 0x11, 0x57, 0x9c, 0x82, 0x0b, 0x13, 0xe3, 0xc7, 0xe7, 0xb6, 0xb0, 0x6b, 0x0b, 0x17, 0xcc, 0x56, 0x29, - 0x3f, 0xca, 0x68, 0xe1, 0xa9, 0x8a, 0x42, 0x82, 0xa9, 0xc1, 0x54, 0xf6, 0x8f, 0x1c, 0x4a, 0x27, 0x1d, 0x2f, 0xb7, - 0x2e, 0xe6, 0xa7, 0x53, 0x10, 0x82, 0x2a, 0x63, 0xe7, 0xa3, 0xec, 0xb0, 0x4b, 0x53, 0xf5, 0x4f, 0x4a, 0x19, 0x26, - 0x55, 0x1f, 0x06, 0x6f, 0xfc, 0x88, 0xaa, 0xc0, 0x5e, 0x0a, 0x7d, 0x4c, 0x38, 0x99, 0x6c, 0x1b, 0x09, 0x27, 0x46, - 0x5d, 0x09, 0xa8, 0x6f, 0xf7, 0x4f, 0x82, 0x99, 0x1c, 0xef, 0x75, 0xb6, 0xf4, 0x83, 0xac, 0xa2, 0x3d, 0x28, 0x94, - 0x01, 0x25, 0x8f, 0x8b, 0x4b, 0x1b, 0x12, 0x60, 0x58, 0x41, 0x80, 0x49, 0xea, 0x77, 0x8b, 0xce, 0xb5, 0xed, 0x9d, - 0xb6, 0xca, 0xc9, 0x85, 0x32, 0xdc, 0x90, 0xa2, 0x8b, 0x31, 0x49, 0x2d, 0xb6, 0x3b, 0xe9, 0xf4, 0x77, 0x23, 0x69, - 0x39, 0xa2, 0xf0, 0x28, 0x40, 0x7a, 0x40, 0x67, 0x34, 0xcf, 0xfc, 0x38, 0xdb, 0xba, 0x60, 0xa7, 0xad, 0x68, 0x16, - 0x57, 0x81, 0x54, 0xb4, 0x23, 0xf4, 0x94, 0x59, 0x35, 0x13, 0x3e, 0x46, 0x0d, 0x24, 0x49, 0x70, 0x97, 0x32, 0x4a, - 0x4b, 0xe6, 0x37, 0xb0, 0x10, 0x50, 0x98, 0xe4, 0xba, 0x8a, 0xe6, 0x4a, 0x75, 0x5a, 0xda, 0xfd, 0xbf, 0xfc, 0xf3, - 0xff, 0x96, 0x01, 0x5a, 0xa0, 0x4a, 0x47, 0x8d, 0xd5, 0x20, 0x74, 0xb9, 0x8b, 0xf9, 0x4d, 0xd5, 0x11, 0x2e, 0xbb, - 0x04, 0x4f, 0x3f, 0x1e, 0xb5, 0x26, 0x51, 0x32, 0x06, 0xc0, 0xd6, 0x12, 0xc8, 0xcc, 0x7e, 0x90, 0x50, 0xd7, 0x8b, - 0x90, 0x05, 0x7f, 0x53, 0x96, 0xb5, 0xca, 0x6e, 0xa7, 0xdd, 0x6a, 0xe4, 0x5c, 0x1b, 0x1b, 0xaa, 0x96, 0x77, 0xad, - 0x7e, 0x95, 0x4c, 0x0a, 0x35, 0x56, 0x4b, 0xba, 0x86, 0x96, 0xfa, 0xa4, 0xe9, 0xdf, 0xff, 0xe5, 0x1f, 0xfe, 0x87, - 0x7a, 0xc5, 0x03, 0xa4, 0xbf, 0xfc, 0xd3, 0xdf, 0x61, 0x7e, 0xb3, 0xa5, 0x0f, 0x99, 0x48, 0x4e, 0x58, 0xd5, 0x09, - 0x93, 0x10, 0x18, 0x56, 0xe5, 0xd1, 0xd5, 0x93, 0xb3, 0xf7, 0x69, 0x42, 0xda, 0x6c, 0x12, 0x3a, 0xda, 0xb4, 0x65, - 0xc5, 0x23, 0x35, 0x92, 0x13, 0x2f, 0x42, 0x25, 0xd2, 0xfb, 0x4e, 0x99, 0x4f, 0xbe, 0x5e, 0x8d, 0x85, 0x0a, 0xff, - 0x61, 0x49, 0x59, 0x95, 0x5b, 0x18, 0x97, 0x5f, 0xe0, 0x6b, 0xd0, 0x35, 0x8a, 0x69, 0xf1, 0x6a, 0x7d, 0x7a, 0x3f, - 0xcd, 0x01, 0xfe, 0x31, 0x52, 0x5c, 0x04, 0x19, 0xe9, 0xcc, 0xb9, 0x85, 0x06, 0x5d, 0x72, 0x55, 0xd2, 0x28, 0xc2, - 0x0b, 0x7c, 0xf8, 0xe4, 0x6f, 0xca, 0x3f, 0x4e, 0xd1, 0x6c, 0xb2, 0x9c, 0x69, 0x74, 0x29, 0x7d, 0xc3, 0x47, 0xed, - 0xf6, 0xec, 0xd2, 0x5d, 0x54, 0x33, 0x78, 0xeb, 0x26, 0xa3, 0xc0, 0xa4, 0x39, 0x20, 0x1d, 0x56, 0xeb, 0x18, 0x28, - 0xb8, 0x43, 0x6d, 0x0c, 0x99, 0x95, 0xe5, 0x1f, 0x16, 0x14, 0x86, 0x8b, 0x7f, 0xc1, 0x43, 0x65, 0x19, 0xb1, 0x84, - 0x12, 0x03, 0x8b, 0x85, 0xd1, 0xab, 0x2b, 0x7a, 0x4d, 0x3a, 0xcb, 0x39, 0x41, 0xe6, 0xa1, 0xb8, 0x79, 0x9c, 0xfd, - 0x10, 0x0f, 0xa8, 0x27, 0x1d, 0x6f, 0xd2, 0x5d, 0xe8, 0xe1, 0x39, 0xcf, 0xa6, 0xe6, 0x29, 0x38, 0x8b, 0xd8, 0x90, - 0x8d, 0x55, 0xa4, 0x57, 0xd6, 0x8b, 0x13, 0xee, 0x72, 0xb2, 0xbd, 0x62, 0x2e, 0x09, 0x12, 0x9d, 0x7e, 0x03, 0x3c, - 0x9f, 0xe1, 0x06, 0x04, 0xfa, 0x67, 0x11, 0x0f, 0x88, 0x5f, 0x7b, 0xe6, 0x59, 0x7a, 0x84, 0x52, 0x26, 0x5b, 0x18, - 0xf0, 0xf4, 0x44, 0x53, 0x8c, 0xb9, 0xd6, 0x73, 0xb2, 0x4a, 0x9f, 0xba, 0x9b, 0x43, 0x89, 0x90, 0xcd, 0xb7, 0xf2, - 0x88, 0xfa, 0x69, 0x2d, 0xd6, 0x21, 0x55, 0x4c, 0xd7, 0xf5, 0x56, 0xd6, 0x0b, 0x4d, 0x2d, 0x6a, 0xbf, 0x05, 0x03, - 0x8c, 0xc0, 0xb4, 0x9b, 0xad, 0xa8, 0x10, 0x5b, 0x3d, 0x0d, 0xbf, 0xd5, 0x7e, 0x4d, 0x34, 0x9b, 0x51, 0x43, 0x17, - 0x98, 0x98, 0xac, 0x51, 0x94, 0x1d, 0x94, 0x7e, 0x21, 0xb2, 0x1d, 0x64, 0x1b, 0xb9, 0x11, 0xc4, 0x93, 0xcc, 0x83, - 0xa0, 0xdf, 0xb7, 0xff, 0x7f, 0x47, 0x48, 0x09, 0x5d, 0xf5, 0x7e, 0x00, 0x00}; + 0xd9, 0xf4, 0x58, 0x0d, 0xbc, 0x0e, 0x10, 0x0a, 0x4f, 0xd7, 0x59, 0x42, 0xa9, 0xea, 0x2c, 0x85, 0xb8, 0xde, 0x40, + 0x1f, 0x99, 0x04, 0x73, 0x15, 0x09, 0xf6, 0xa5, 0x40, 0x60, 0xe8, 0x91, 0x89, 0xf5, 0x7a, 0x06, 0xcb, 0x73, 0x1a, + 0x0d, 0x3f, 0x69, 0x70, 0x2b, 0xde, 0x6b, 0xb2, 0x81, 0xd3, 0x28, 0x09, 0x0d, 0x71, 0x65, 0xe2, 0xad, 0x24, 0x74, + 0x6d, 0xa3, 0x80, 0x43, 0xb6, 0xc4, 0xf6, 0xcd, 0x85, 0x6e, 0x72, 0xbb, 0x64, 0x0f, 0xe5, 0x3f, 0x55, 0x5c, 0xb2, + 0x9e, 0xe5, 0x98, 0x92, 0x06, 0x4c, 0x31, 0x1e, 0x2c, 0x4d, 0x03, 0x12, 0xe0, 0xbb, 0x72, 0x14, 0x17, 0xeb, 0x49, + 0xf0, 0xbb, 0x82, 0xf9, 0xdc, 0x98, 0xe9, 0x56, 0x48, 0xb5, 0x84, 0x93, 0x66, 0xb0, 0x06, 0x4d, 0x1a, 0x0f, 0x4a, + 0xd4, 0x7c, 0x8d, 0x86, 0x0a, 0x71, 0xfc, 0x99, 0xa8, 0x42, 0x13, 0x0c, 0xc1, 0xc8, 0xbd, 0x42, 0x32, 0x5c, 0xb6, + 0x2c, 0x5a, 0xa4, 0x4c, 0x8d, 0x49, 0xa5, 0x6a, 0x96, 0xcb, 0xc0, 0xc0, 0xa2, 0xdd, 0xea, 0x4b, 0x4b, 0x5c, 0x89, + 0xdc, 0x34, 0xd4, 0xc2, 0xa4, 0x50, 0xde, 0x84, 0x93, 0xa3, 0xdf, 0xa5, 0xac, 0x77, 0x13, 0x9f, 0x5c, 0xe1, 0x93, + 0xfb, 0x86, 0x0f, 0x65, 0xf2, 0x76, 0x31, 0x28, 0x82, 0xaf, 0x6b, 0x95, 0x68, 0x9f, 0xfa, 0x28, 0x98, 0x5d, 0x2d, + 0x74, 0x41, 0xa0, 0x48, 0x36, 0x49, 0x07, 0x92, 0xdf, 0x50, 0x6c, 0x54, 0x9e, 0x51, 0xe6, 0x8a, 0x0d, 0x52, 0xf3, + 0x4a, 0x33, 0x2f, 0x75, 0x1b, 0xf6, 0x7b, 0x59, 0x4a, 0x3a, 0x31, 0x41, 0x99, 0xd8, 0xbb, 0x89, 0x36, 0x5e, 0x1a, + 0x66, 0xc2, 0xfa, 0x15, 0xc6, 0x4e, 0x8d, 0x42, 0xa9, 0x14, 0x81, 0x38, 0x36, 0xbe, 0x56, 0x96, 0x41, 0xe6, 0xaf, + 0xb0, 0xa7, 0x00, 0x94, 0x04, 0x16, 0x5f, 0x53, 0xc9, 0x8b, 0xc2, 0x3a, 0x1d, 0xef, 0x11, 0x1d, 0x2b, 0x11, 0x5a, + 0x13, 0xf9, 0x5a, 0x9f, 0xc5, 0x7e, 0xcd, 0x25, 0x34, 0x29, 0x99, 0x0f, 0xf2, 0xc0, 0x56, 0x81, 0x88, 0x4a, 0xb7, + 0x25, 0x83, 0x84, 0x1c, 0xd2, 0x65, 0xa2, 0xd7, 0x46, 0x32, 0x68, 0x9d, 0x0a, 0x89, 0x96, 0x1e, 0x85, 0x11, 0x8a, + 0x0d, 0xb1, 0x16, 0x4b, 0x84, 0x6c, 0xda, 0x9b, 0xc4, 0x8a, 0xe8, 0x9c, 0xe6, 0x68, 0xc2, 0x99, 0x3a, 0xdd, 0x71, + 0x00, 0x1d, 0x10, 0xfb, 0x4b, 0xac, 0xb7, 0xd2, 0xec, 0x74, 0xfd, 0xca, 0xe1, 0xbb, 0xbe, 0x9e, 0x00, 0x3f, 0x48, + 0x83, 0x17, 0xd6, 0x6c, 0xa0, 0x64, 0xef, 0xde, 0x6b, 0x6c, 0x45, 0xf6, 0x67, 0x55, 0x52, 0x79, 0x0a, 0x35, 0xce, + 0xad, 0xaf, 0x53, 0x2d, 0xb4, 0xa8, 0x2a, 0xf6, 0x0d, 0xa9, 0xbe, 0xaf, 0x14, 0x76, 0x85, 0xf2, 0xbe, 0x1c, 0x3a, + 0x76, 0x5d, 0x37, 0xc8, 0xc9, 0x79, 0xb9, 0xb7, 0xca, 0x85, 0xbc, 0x7f, 0xdf, 0xf4, 0x99, 0xce, 0xf5, 0xf0, 0xcf, + 0x1c, 0x54, 0xce, 0xc5, 0x55, 0x4a, 0x16, 0xcc, 0x33, 0xa5, 0x8e, 0x96, 0x1c, 0xd0, 0x76, 0x0f, 0x3d, 0xed, 0xe8, + 0x22, 0x8a, 0xb9, 0xa5, 0x47, 0x11, 0x9e, 0x36, 0xca, 0x27, 0x69, 0x74, 0x00, 0x5e, 0x68, 0x42, 0x92, 0x13, 0x6e, + 0xda, 0xa2, 0xc5, 0x70, 0xc2, 0x30, 0x04, 0xae, 0xec, 0x09, 0x53, 0xf6, 0xdc, 0x43, 0xbc, 0xe5, 0xc0, 0xab, 0x61, + 0x2f, 0x9b, 0xdd, 0x6b, 0xe6, 0x3f, 0xac, 0x11, 0xc8, 0xb6, 0xa9, 0xaa, 0x2b, 0x1b, 0xef, 0x52, 0x44, 0x62, 0x84, + 0x6d, 0xd5, 0xd8, 0xd2, 0xd6, 0xef, 0x35, 0xdc, 0xeb, 0xca, 0x31, 0xaf, 0x29, 0xd5, 0x86, 0x1e, 0x56, 0x6e, 0x0e, + 0x37, 0x1d, 0x79, 0xb1, 0x82, 0x6e, 0x4f, 0x04, 0x85, 0xc0, 0x89, 0x50, 0xf6, 0xa0, 0xe6, 0x06, 0x22, 0x25, 0x53, + 0x5a, 0x35, 0x9b, 0x27, 0x23, 0x09, 0x2c, 0xb8, 0xb0, 0x4c, 0xf2, 0xd1, 0x45, 0x9c, 0x24, 0x55, 0xe9, 0xef, 0x2a, + 0xe0, 0xc5, 0xb0, 0xb7, 0x89, 0x76, 0x81, 0xd1, 0x5c, 0x81, 0xe0, 0x6a, 0x23, 0xec, 0xa3, 0xe3, 0x56, 0xeb, 0x2e, + 0x22, 0x8e, 0xcc, 0x8c, 0x46, 0x7c, 0x44, 0x1b, 0xb2, 0x64, 0x9a, 0xb5, 0xf7, 0x5e, 0x60, 0x48, 0xcd, 0xc0, 0x07, + 0xd5, 0x19, 0x15, 0xff, 0x2a, 0x7b, 0xea, 0x57, 0xa2, 0x77, 0xab, 0xea, 0x6a, 0x06, 0x54, 0x54, 0xe0, 0xc3, 0x0c, + 0xb1, 0xb4, 0x55, 0x20, 0x20, 0xd7, 0xc3, 0x3a, 0xdc, 0xad, 0x91, 0x06, 0x0b, 0x4a, 0x81, 0xb5, 0x56, 0x76, 0xaf, + 0x6f, 0x0b, 0xe6, 0x50, 0x28, 0x5c, 0xf4, 0x7f, 0x96, 0x4d, 0x67, 0x68, 0x99, 0x35, 0x98, 0x1a, 0x1a, 0x7c, 0x6c, + 0xd4, 0x97, 0x2b, 0xca, 0x6a, 0x7d, 0x68, 0x47, 0xd6, 0xf8, 0x49, 0x3b, 0xca, 0xe0, 0x50, 0xcd, 0x75, 0x51, 0xdd, + 0x6e, 0x6e, 0x8a, 0x98, 0x55, 0x3c, 0xee, 0x93, 0xde, 0xd6, 0xd6, 0xa4, 0xa7, 0x69, 0x40, 0x32, 0x49, 0x32, 0xbc, + 0xc9, 0x00, 0x65, 0x45, 0x9c, 0x45, 0xd9, 0x20, 0xdf, 0xa2, 0x2c, 0x71, 0xfd, 0x7e, 0xe8, 0xed, 0xd5, 0x3c, 0x6b, + 0x6f, 0x6f, 0xbd, 0x8b, 0x5c, 0xd5, 0x49, 0x0f, 0xf2, 0xf0, 0x08, 0x8a, 0x96, 0x6c, 0xca, 0x70, 0x31, 0xcd, 0x46, + 0x2c, 0xb0, 0xa1, 0x7b, 0x6a, 0x97, 0x72, 0xd3, 0x44, 0xc0, 0x3d, 0x11, 0x73, 0x16, 0x1f, 0xea, 0x91, 0xd4, 0x60, + 0x0f, 0x58, 0x40, 0x9b, 0x0b, 0x5f, 0x85, 0x67, 0x49, 0x76, 0x1a, 0x25, 0x07, 0x42, 0x81, 0xd7, 0x5a, 0x7e, 0x0b, + 0x2e, 0x23, 0x59, 0xac, 0x86, 0x92, 0xfa, 0x6a, 0xf0, 0x55, 0x70, 0x7b, 0x8f, 0xca, 0x5b, 0xb1, 0x3b, 0x7e, 0xdb, + 0xef, 0xd8, 0x2a, 0x22, 0xf6, 0x93, 0x39, 0x1d, 0x68, 0x9c, 0x02, 0x28, 0x73, 0x00, 0x9a, 0xac, 0xf0, 0x86, 0x2c, + 0xfc, 0x69, 0xf0, 0x93, 0x72, 0xa9, 0x33, 0x70, 0x21, 0xc0, 0xc9, 0x4f, 0x62, 0xde, 0xc2, 0xf3, 0x48, 0xdb, 0x5b, + 0x88, 0x0a, 0x8c, 0x2b, 0x52, 0x5c, 0xba, 0x54, 0xde, 0xa0, 0x77, 0x1c, 0x9e, 0x40, 0xb3, 0x8d, 0x8d, 0x85, 0xf3, + 0x26, 0xe2, 0x13, 0x3f, 0x8f, 0xd2, 0x51, 0x36, 0x75, 0xdc, 0x4d, 0xdb, 0x76, 0xfd, 0x82, 0x3c, 0x91, 0xcf, 0xdd, + 0x72, 0xe3, 0x04, 0xfc, 0x80, 0xd0, 0x1e, 0xd8, 0x9b, 0xc7, 0xde, 0x01, 0x0b, 0x4f, 0x76, 0x37, 0x16, 0x23, 0x56, + 0xf6, 0x4f, 0xbc, 0x4b, 0x1d, 0x73, 0xf7, 0xde, 0xa3, 0x94, 0x81, 0x5e, 0x61, 0xff, 0x52, 0x82, 0x01, 0xec, 0x46, + 0xf1, 0x77, 0x90, 0x72, 0x1f, 0xe9, 0x40, 0x44, 0xc6, 0x69, 0xaf, 0xaf, 0xed, 0x8c, 0x22, 0x06, 0xf6, 0x3d, 0xed, + 0xac, 0xde, 0xbf, 0x5f, 0xa9, 0xf9, 0xaa, 0xd4, 0x9b, 0xb3, 0xb0, 0xe6, 0xa9, 0x7b, 0x2f, 0xe9, 0x68, 0xa5, 0xbe, + 0x91, 0xe7, 0x8c, 0x94, 0xe6, 0xb2, 0x9d, 0xe0, 0x18, 0x5b, 0x7c, 0xf5, 0xb6, 0x3e, 0x14, 0x51, 0x0a, 0x3f, 0x06, + 0xeb, 0x25, 0x02, 0xf5, 0x0d, 0x0e, 0x8e, 0x77, 0x10, 0x6e, 0xed, 0x3a, 0x83, 0xc0, 0xb9, 0xd7, 0x6a, 0x5d, 0xff, + 0xb8, 0x75, 0xf8, 0xe7, 0xa8, 0xf5, 0xcb, 0x5e, 0xeb, 0x87, 0x23, 0xf7, 0xda, 0xf9, 0x71, 0x6b, 0x70, 0x28, 0xdf, + 0x0e, 0xff, 0xdc, 0xff, 0xb1, 0x38, 0xfa, 0x83, 0x28, 0xdc, 0x70, 0xdd, 0xad, 0x33, 0x6f, 0xc6, 0xc2, 0xad, 0x56, + 0xab, 0x0f, 0x4f, 0x67, 0xf0, 0x84, 0x7f, 0x2f, 0xe0, 0xcf, 0xf5, 0xa1, 0xf5, 0x9f, 0x7e, 0x4c, 0xff, 0xf3, 0x8f, + 0xf9, 0x11, 0x8e, 0x79, 0xf8, 0xe7, 0x1f, 0x0b, 0xfb, 0x41, 0x3f, 0xdc, 0x3a, 0xda, 0x74, 0x1d, 0x5d, 0xf3, 0x87, + 0xb0, 0x7a, 0x84, 0x56, 0x87, 0x7f, 0x96, 0x6f, 0xf6, 0x83, 0x93, 0xdd, 0x7e, 0x78, 0x74, 0xed, 0xd8, 0xd7, 0x0f, + 0xdc, 0x6b, 0xd7, 0xbd, 0xde, 0xc0, 0x79, 0xce, 0x61, 0xf4, 0x07, 0xf0, 0x77, 0x0c, 0x7f, 0x6d, 0xf8, 0x3b, 0x85, + 0xbf, 0x7f, 0x86, 0x6e, 0x22, 0xfe, 0x76, 0x4d, 0xb1, 0x90, 0x6b, 0x3c, 0xb0, 0x88, 0x60, 0x15, 0xdc, 0x8d, 0xad, + 0xd8, 0xdb, 0x20, 0xa2, 0xc1, 0x3e, 0xf4, 0x7d, 0x1f, 0xc3, 0xa4, 0xce, 0xe2, 0x78, 0x03, 0x16, 0x1d, 0x39, 0x67, + 0x23, 0xe0, 0x9e, 0x88, 0x1c, 0x14, 0x01, 0x13, 0x67, 0xab, 0x05, 0x1e, 0xae, 0x7a, 0xc3, 0x70, 0x83, 0x39, 0x60, + 0x14, 0xbc, 0x65, 0xf8, 0xd0, 0x75, 0xbd, 0x17, 0xf2, 0xcc, 0x10, 0xf7, 0xb9, 0x60, 0xad, 0x34, 0x13, 0x26, 0x8d, + 0xed, 0x7a, 0xb3, 0x15, 0x95, 0xb0, 0xad, 0xd3, 0x33, 0xa8, 0x3b, 0x15, 0x27, 0x8c, 0xdf, 0xb1, 0xe8, 0x13, 0x6e, + 0xc9, 0x37, 0xc6, 0x21, 0xf0, 0x92, 0x25, 0xdf, 0x34, 0x1a, 0x0d, 0x1b, 0x51, 0xb8, 0x63, 0x4f, 0x19, 0xcc, 0xb0, + 0x64, 0x22, 0x32, 0x52, 0x9a, 0xc2, 0xb2, 0x85, 0xc9, 0xdf, 0x47, 0x39, 0xdf, 0xa8, 0x0c, 0xdb, 0xb0, 0x66, 0xc9, + 0x36, 0x2d, 0xfd, 0x3b, 0x4c, 0x81, 0xa6, 0x25, 0x9d, 0x7f, 0x98, 0xe3, 0x87, 0x29, 0xa1, 0xf5, 0xd6, 0x61, 0xe0, + 0xa1, 0x17, 0x20, 0x77, 0x44, 0x3f, 0xe7, 0x3d, 0xaa, 0x31, 0xf8, 0x9f, 0x0c, 0x33, 0x78, 0x62, 0x3e, 0x0c, 0xd1, + 0x2c, 0x4a, 0x1d, 0xdc, 0x4a, 0x51, 0xdc, 0xbf, 0xc2, 0x9d, 0x91, 0x96, 0xde, 0x7e, 0xa8, 0x76, 0xcc, 0x41, 0xce, + 0xd8, 0x77, 0x51, 0xf2, 0x89, 0xe5, 0xce, 0xa5, 0xd7, 0xe9, 0x7e, 0x4e, 0x9d, 0x3d, 0xb4, 0xcd, 0x3e, 0x54, 0xc7, + 0x68, 0xda, 0x2c, 0x90, 0x47, 0x84, 0xad, 0x8e, 0x97, 0x63, 0x54, 0x0b, 0x49, 0x50, 0x78, 0x59, 0xd8, 0x25, 0x0e, + 0xb7, 0x77, 0x8b, 0xf3, 0xb3, 0xbe, 0x1d, 0xd8, 0x36, 0x58, 0xfc, 0x07, 0x14, 0xb6, 0x12, 0x86, 0x45, 0xbb, 0xc7, + 0x76, 0xe3, 0x1e, 0xdb, 0xdc, 0xac, 0x02, 0x4e, 0x78, 0x90, 0x4e, 0xdd, 0x13, 0x2f, 0xf2, 0x26, 0x21, 0x0c, 0x38, + 0x84, 0x66, 0xd8, 0xa5, 0x37, 0xdc, 0x8d, 0xe5, 0x34, 0x18, 0x0b, 0xf1, 0x93, 0xa8, 0xe0, 0xaf, 0x30, 0x1e, 0x11, + 0x0e, 0xd1, 0xd8, 0xf7, 0xd9, 0x25, 0x1b, 0x2a, 0x3b, 0x03, 0x08, 0x15, 0xb9, 0x3d, 0x77, 0x18, 0x1a, 0xcd, 0x60, + 0xee, 0x30, 0x3c, 0x18, 0xd8, 0xb0, 0x97, 0x60, 0x57, 0x86, 0xd1, 0x61, 0xe7, 0x68, 0x90, 0x86, 0x33, 0x16, 0x68, + 0xda, 0xca, 0xa2, 0xb3, 0x5a, 0x51, 0xf7, 0x68, 0xe0, 0x4c, 0x99, 0xcf, 0xc1, 0x16, 0x77, 0xf0, 0x0d, 0x23, 0x14, + 0x45, 0xf8, 0x81, 0x9d, 0xbd, 0xb8, 0x9c, 0x39, 0xf6, 0xee, 0x96, 0xbd, 0x89, 0xa5, 0x9e, 0x0d, 0xec, 0x05, 0x73, + 0x87, 0x17, 0xae, 0xd9, 0x79, 0xfb, 0x08, 0x41, 0xc5, 0x42, 0x9c, 0xfc, 0x62, 0x60, 0xf7, 0xc5, 0xd4, 0x6d, 0x18, + 0x34, 0x95, 0xcb, 0x8f, 0x2b, 0x7a, 0x40, 0xa8, 0xaa, 0xae, 0x0a, 0x3a, 0x28, 0xeb, 0x06, 0xce, 0xc4, 0x44, 0xa2, + 0x85, 0x93, 0x49, 0x2a, 0x80, 0xc3, 0x83, 0xcd, 0x60, 0x52, 0xa3, 0xdb, 0xf6, 0xd1, 0xe0, 0x22, 0x78, 0x60, 0x3f, + 0x50, 0x2f, 0x63, 0x40, 0x86, 0x89, 0xe9, 0xc7, 0xa0, 0x45, 0xf0, 0xef, 0x39, 0x03, 0x24, 0x2f, 0xa8, 0x68, 0x26, + 0x8b, 0xce, 0xb0, 0xe8, 0x20, 0x40, 0x50, 0xbd, 0x42, 0x5b, 0x7f, 0x62, 0x4d, 0x46, 0x21, 0xc1, 0x0e, 0xb6, 0xd0, + 0x21, 0xdb, 0xec, 0x1c, 0xe1, 0x79, 0x43, 0xce, 0x8b, 0xef, 0x62, 0x0e, 0x2a, 0x61, 0xab, 0x6f, 0xbb, 0x03, 0xdb, + 0xc2, 0xa5, 0xed, 0x65, 0x9b, 0xa1, 0xa0, 0x70, 0xbc, 0x79, 0xc0, 0x82, 0x49, 0x3f, 0x6c, 0x0f, 0x9c, 0x5c, 0x86, + 0x1b, 0xf1, 0xdc, 0x52, 0x48, 0xf0, 0xb6, 0x37, 0x01, 0x81, 0x8e, 0x9c, 0xbb, 0x61, 0x6f, 0xaa, 0x42, 0x28, 0x3a, + 0xde, 0x1c, 0xb9, 0x41, 0x0c, 0x7f, 0x9c, 0x16, 0x32, 0xcd, 0x44, 0xf7, 0x55, 0x9a, 0x19, 0x90, 0x18, 0x29, 0x8b, + 0x3c, 0x09, 0xb3, 0x4d, 0x07, 0x23, 0xb4, 0x20, 0x69, 0x77, 0x07, 0x00, 0xc3, 0xa6, 0xa3, 0x38, 0x6d, 0x4b, 0xb1, + 0x9a, 0xb2, 0xcf, 0x0f, 0xf5, 0x72, 0x0c, 0xd9, 0x60, 0xc8, 0xfc, 0x4a, 0xfb, 0x00, 0x58, 0x41, 0xe2, 0xe5, 0x47, + 0xea, 0xcc, 0xeb, 0x65, 0xed, 0x7c, 0x6b, 0xa1, 0x44, 0x11, 0xf7, 0x0c, 0x09, 0xc5, 0x4a, 0xed, 0x86, 0x09, 0x73, + 0x7b, 0x86, 0xc4, 0xd0, 0x2c, 0x1f, 0xb6, 0x81, 0xe9, 0x55, 0x80, 0x3d, 0x35, 0xb7, 0x45, 0x12, 0x56, 0xcd, 0xbd, + 0x43, 0x60, 0xed, 0x23, 0xe0, 0x21, 0xda, 0x46, 0x3d, 0x15, 0xcd, 0x67, 0x49, 0xf8, 0xb2, 0x71, 0x5c, 0x1c, 0xe1, + 0x89, 0xd0, 0xbe, 0x3f, 0x9c, 0xe7, 0x20, 0x0f, 0xf8, 0x5b, 0xb0, 0x0c, 0x42, 0xd9, 0x14, 0x1d, 0x3d, 0x3c, 0x02, + 0xf6, 0x08, 0xf1, 0x46, 0xd8, 0xdc, 0xa8, 0x46, 0x8b, 0x92, 0x8c, 0x17, 0x3a, 0x18, 0xee, 0x31, 0xe9, 0xda, 0xa3, + 0x60, 0x90, 0x27, 0xc6, 0x0e, 0x9e, 0xf9, 0xfb, 0x43, 0xac, 0xc6, 0x09, 0x0a, 0xb7, 0xa4, 0xdd, 0x56, 0x89, 0xbf, + 0x7d, 0x3f, 0x05, 0x09, 0x8e, 0x75, 0xe0, 0x67, 0xdd, 0xbf, 0x9f, 0x48, 0xa4, 0x76, 0xd3, 0x1e, 0x9d, 0x44, 0x60, + 0x3c, 0x38, 0xf7, 0x53, 0xa8, 0x46, 0x12, 0x51, 0x51, 0x8e, 0x16, 0xa8, 0x79, 0xaa, 0x56, 0xc1, 0x77, 0x68, 0x46, + 0xe0, 0x19, 0x86, 0xad, 0xc9, 0x4f, 0xd5, 0x8d, 0x45, 0x2c, 0xdf, 0x75, 0xe9, 0x68, 0x0b, 0x0f, 0x20, 0x05, 0xa3, + 0x09, 0x86, 0x71, 0x29, 0x28, 0x59, 0xf1, 0xdf, 0xb1, 0x11, 0x2b, 0x9f, 0x1c, 0x66, 0x9b, 0x9b, 0x47, 0xe2, 0xdc, + 0x82, 0x18, 0x87, 0x19, 0xd1, 0xd5, 0xb8, 0x02, 0xa0, 0x3e, 0x9d, 0x13, 0xd7, 0x03, 0xd3, 0x8a, 0x35, 0x5d, 0x8a, + 0x7d, 0x72, 0x98, 0x01, 0x28, 0xb8, 0xe5, 0x1c, 0xfa, 0x83, 0x3f, 0x1e, 0x81, 0x7b, 0xec, 0xff, 0xc1, 0xdd, 0x52, + 0x82, 0xa6, 0x27, 0xcf, 0x14, 0x17, 0x74, 0xc6, 0xda, 0xf1, 0x28, 0x36, 0x1a, 0x14, 0x5e, 0x0a, 0x18, 0x80, 0x36, + 0x07, 0x99, 0x50, 0x71, 0x10, 0x72, 0x54, 0x60, 0xfb, 0xb8, 0xf9, 0x19, 0xee, 0xec, 0xe7, 0x60, 0xe1, 0x0d, 0xf4, + 0xdb, 0x6b, 0x78, 0xfb, 0xa3, 0x7e, 0xfb, 0x89, 0x05, 0xbf, 0x94, 0x32, 0x74, 0x5f, 0x9b, 0xe2, 0x91, 0x9a, 0xa2, + 0x14, 0x4b, 0x64, 0xd0, 0x90, 0xbb, 0xf9, 0x52, 0xcc, 0x86, 0xb9, 0x25, 0x10, 0x43, 0x89, 0xae, 0xdc, 0xe7, 0xd1, + 0x19, 0x12, 0xd7, 0x35, 0x49, 0x61, 0xe4, 0x12, 0x98, 0x08, 0x57, 0x7c, 0x8b, 0xf4, 0x64, 0xfd, 0x36, 0xd8, 0xe0, + 0xb5, 0xbc, 0x03, 0xb4, 0xef, 0xd8, 0x74, 0xc6, 0xaf, 0xf6, 0x49, 0xd1, 0x07, 0x32, 0x6d, 0x40, 0x9c, 0x9d, 0xb7, + 0x7b, 0xf1, 0x2e, 0xeb, 0xc5, 0x20, 0xd5, 0x73, 0xc5, 0x62, 0xb8, 0x57, 0xbd, 0xf7, 0x18, 0xa5, 0x34, 0x99, 0xc9, + 0xab, 0xa1, 0xd7, 0x95, 0xe8, 0x6d, 0x6e, 0x02, 0x82, 0x3d, 0xa3, 0x2b, 0x13, 0x5d, 0xcb, 0x52, 0xd0, 0x04, 0x20, + 0x7a, 0x52, 0x67, 0x39, 0xe2, 0x38, 0xcc, 0x66, 0x83, 0xe2, 0x11, 0x73, 0x57, 0x8e, 0x8a, 0x63, 0x62, 0x77, 0x99, + 0xb0, 0x03, 0x98, 0x11, 0x97, 0xb7, 0x3a, 0x22, 0x3a, 0x2c, 0xfa, 0xeb, 0xf8, 0xf6, 0xb1, 0xc7, 0x37, 0x3b, 0x2e, + 0x68, 0x90, 0xda, 0x58, 0x8f, 0xab, 0xb1, 0xa0, 0x3e, 0x3c, 0xd6, 0x54, 0x2a, 0x8b, 0xcd, 0xcd, 0xb2, 0x7e, 0x54, + 0xab, 0x76, 0x70, 0xed, 0x34, 0xe5, 0xb2, 0x99, 0x0d, 0xc2, 0x81, 0x88, 0x09, 0x14, 0x68, 0x69, 0x65, 0xc5, 0x00, + 0x43, 0xca, 0x72, 0x94, 0x4f, 0x21, 0xf7, 0xe2, 0xb2, 0xd4, 0xa9, 0x2f, 0xcf, 0x64, 0xd0, 0x11, 0x4f, 0x3d, 0xc9, + 0x58, 0x01, 0x05, 0xeb, 0xa5, 0x5e, 0x42, 0x4b, 0x04, 0x98, 0xbf, 0x50, 0x39, 0x34, 0xc2, 0x02, 0x89, 0x42, 0xc3, + 0x2c, 0x51, 0xc6, 0x67, 0x11, 0xc6, 0xa0, 0xed, 0x9f, 0xd5, 0x62, 0x5f, 0x85, 0x32, 0x3a, 0x8a, 0xc3, 0xfc, 0x28, + 0xa0, 0xfa, 0xb9, 0x94, 0x60, 0x93, 0xf0, 0x23, 0xb0, 0x51, 0xe5, 0x78, 0x92, 0x20, 0x7c, 0x1e, 0xe7, 0x8c, 0x3c, + 0x85, 0x0d, 0x09, 0xb3, 0x34, 0x6d, 0x23, 0xd5, 0x2e, 0x32, 0x83, 0x50, 0x2e, 0xcc, 0x3f, 0x31, 0xce, 0x2e, 0xb2, + 0x70, 0xa9, 0x35, 0x98, 0x1f, 0xef, 0x4c, 0x80, 0xb2, 0xeb, 0xeb, 0x4c, 0xf8, 0xb8, 0x11, 0xd9, 0x1b, 0xba, 0x62, + 0x32, 0x50, 0x48, 0x05, 0x4e, 0x44, 0x16, 0x0f, 0x9d, 0xa1, 0xd0, 0x08, 0x07, 0x74, 0x8a, 0x9c, 0xbb, 0xc6, 0xa6, + 0xcf, 0x07, 0xda, 0x37, 0x4a, 0x43, 0x27, 0x01, 0x21, 0x20, 0x70, 0x37, 0xac, 0xa9, 0x74, 0x90, 0x06, 0x09, 0x95, + 0xa2, 0x9f, 0x03, 0xf8, 0x87, 0x91, 0xa4, 0x00, 0xd8, 0x0f, 0xd5, 0x48, 0x11, 0x65, 0x59, 0xe0, 0x02, 0xd0, 0x5c, + 0xfb, 0xb8, 0x12, 0xbe, 0x30, 0x50, 0x61, 0x7a, 0x9a, 0x95, 0x95, 0x42, 0x89, 0x3c, 0x5d, 0x91, 0xb2, 0x46, 0x32, + 0xf9, 0x1c, 0x1d, 0x3e, 0xe5, 0x5d, 0xbf, 0x95, 0x78, 0xe8, 0x82, 0xe7, 0xb0, 0xac, 0xea, 0xf9, 0x4d, 0xc8, 0xc8, + 0xb9, 0x06, 0x5d, 0x21, 0x85, 0xfe, 0x92, 0x93, 0xbc, 0xf7, 0xc6, 0xaf, 0x6a, 0xa9, 0x31, 0x94, 0x7d, 0x5c, 0xd5, + 0x0c, 0xcb, 0xcb, 0x59, 0x15, 0xa6, 0x20, 0xe0, 0x16, 0x2c, 0x09, 0x16, 0x52, 0x43, 0x80, 0x85, 0xed, 0x91, 0x56, + 0x0a, 0xf2, 0x52, 0x87, 0x77, 0x9e, 0x83, 0x15, 0x60, 0x1c, 0x6a, 0xa9, 0x64, 0x1a, 0x49, 0x7c, 0x99, 0xd4, 0x04, + 0x4c, 0xb9, 0x3f, 0x04, 0x3f, 0xb5, 0x79, 0xd2, 0x75, 0xe9, 0xfa, 0xf1, 0x14, 0x53, 0x7b, 0x08, 0xf4, 0xd8, 0xbb, + 0x07, 0xa6, 0x44, 0x5d, 0x87, 0x15, 0xc4, 0xa1, 0x59, 0x4d, 0xb3, 0x80, 0x19, 0xd3, 0x06, 0x2d, 0xd9, 0x06, 0x5b, + 0x2e, 0x07, 0xfb, 0x48, 0x6c, 0xcf, 0x6a, 0x05, 0x84, 0xae, 0x41, 0x03, 0x43, 0xee, 0x52, 0xa1, 0x85, 0x59, 0xaf, + 0x4b, 0x45, 0xb8, 0x3f, 0x07, 0x4c, 0x5a, 0xc1, 0x99, 0x97, 0xd1, 0xc0, 0xfb, 0xf1, 0x69, 0x82, 0x89, 0x2f, 0x88, + 0x15, 0xd8, 0xc1, 0x41, 0xa7, 0xd9, 0x14, 0x38, 0x15, 0x17, 0x29, 0x83, 0x65, 0x45, 0xa9, 0x0d, 0x7f, 0xa4, 0xc8, + 0xd6, 0x5d, 0x1e, 0xe9, 0x2e, 0xc4, 0x02, 0xd8, 0xe9, 0x17, 0x8c, 0x7c, 0xcb, 0x7a, 0x19, 0x30, 0x38, 0xd7, 0x1a, + 0x07, 0x81, 0xdf, 0xdc, 0x4c, 0x8e, 0xca, 0x94, 0xd8, 0xae, 0xc9, 0xea, 0x02, 0x72, 0x4c, 0x02, 0x6c, 0xe0, 0x0e, + 0xc2, 0x52, 0xd9, 0xe3, 0x45, 0x39, 0xc5, 0xe5, 0x52, 0x16, 0x72, 0x33, 0x1d, 0x8b, 0xe6, 0x73, 0x2b, 0xcd, 0xa6, + 0xe3, 0xad, 0xf8, 0xa2, 0xe0, 0x1f, 0x38, 0xb1, 0xb4, 0xea, 0x29, 0xb5, 0xc2, 0xa3, 0xcc, 0x2d, 0x59, 0xa7, 0xa4, + 0x56, 0xd7, 0x0d, 0x54, 0x23, 0x3c, 0x4d, 0xc3, 0x46, 0x20, 0xc4, 0x04, 0x17, 0xbf, 0x6d, 0x32, 0x31, 0xed, 0x2d, + 0x21, 0x75, 0x84, 0xdd, 0x43, 0x39, 0xc1, 0x5d, 0xcd, 0xb3, 0x2f, 0xc3, 0xd9, 0x7a, 0xe6, 0xde, 0x33, 0x98, 0xfb, + 0x69, 0xc8, 0x0c, 0x46, 0x8f, 0x65, 0xc2, 0x8f, 0x8c, 0x7d, 0xe4, 0xaa, 0xea, 0xd9, 0x59, 0x58, 0x89, 0x2c, 0xf1, + 0x64, 0x1c, 0x75, 0x18, 0xa7, 0xa2, 0x35, 0x41, 0x76, 0x7d, 0x5d, 0x98, 0x7b, 0x81, 0x82, 0xa6, 0x1e, 0xab, 0xc7, + 0x69, 0x2b, 0x76, 0x36, 0x22, 0x91, 0x7b, 0x6f, 0x6a, 0x91, 0xc8, 0x8a, 0xcf, 0x71, 0xa4, 0x35, 0x07, 0xb9, 0xcf, + 0xce, 0x96, 0x37, 0xa9, 0xd0, 0x2d, 0x1a, 0x6d, 0x63, 0x8f, 0xea, 0x03, 0x49, 0x3d, 0xa3, 0x02, 0xab, 0x1a, 0xfb, + 0xfe, 0xfd, 0x8e, 0x48, 0xb7, 0x54, 0x8a, 0x0d, 0x43, 0x5a, 0x21, 0x33, 0x46, 0xc1, 0xa0, 0xa4, 0xc8, 0x40, 0x8d, + 0xf2, 0x35, 0x82, 0x61, 0x8f, 0x1a, 0x80, 0xe2, 0x5c, 0x5d, 0xfd, 0xb4, 0x94, 0x6c, 0x21, 0x20, 0x01, 0xd9, 0x84, + 0x62, 0x8d, 0x98, 0x19, 0xf9, 0xe4, 0x23, 0x70, 0xde, 0x80, 0xa3, 0x63, 0x00, 0x7e, 0x81, 0xd8, 0xf4, 0x60, 0x62, + 0xdb, 0x44, 0x14, 0x7d, 0x36, 0xf0, 0x12, 0x80, 0x9d, 0x55, 0xa1, 0xd1, 0x0f, 0x55, 0x0a, 0x18, 0xb2, 0x81, 0x1b, + 0xf0, 0x2a, 0x2c, 0xb7, 0xf7, 0x12, 0xda, 0xc1, 0xeb, 0x0b, 0xd9, 0x7c, 0x03, 0xf3, 0x04, 0xab, 0xd8, 0x9d, 0x5f, + 0x59, 0xd6, 0xe2, 0xdc, 0xe9, 0xa0, 0x51, 0xaf, 0x28, 0x21, 0x6a, 0xf7, 0xb1, 0xf6, 0x25, 0x23, 0x18, 0xf1, 0xfd, + 0x0d, 0x65, 0x1d, 0xaa, 0x71, 0xcb, 0x3d, 0x8d, 0x16, 0x61, 0xba, 0x4c, 0x1a, 0x83, 0x92, 0x75, 0x3f, 0x19, 0x71, + 0x2f, 0xf7, 0x45, 0x2c, 0xb8, 0xc2, 0xd1, 0x08, 0x9b, 0x37, 0x90, 0xa4, 0xa7, 0x3d, 0x3a, 0x60, 0xdf, 0x68, 0xf6, + 0x02, 0xca, 0x7c, 0xac, 0x48, 0x25, 0x21, 0xa5, 0xd9, 0x0d, 0x91, 0x24, 0xac, 0x15, 0x79, 0xea, 0xbc, 0xef, 0x68, + 0x9f, 0x5b, 0x49, 0x04, 0x23, 0x38, 0x89, 0xd3, 0x95, 0x07, 0x4d, 0x01, 0xae, 0xa2, 0x23, 0xa6, 0x6f, 0x82, 0xf2, + 0x1b, 0xe4, 0xf6, 0x52, 0x72, 0x6d, 0xae, 0x61, 0x78, 0x86, 0x04, 0xab, 0x22, 0x11, 0x78, 0x44, 0x0d, 0x38, 0xe6, + 0xab, 0x3c, 0x0f, 0x30, 0xe1, 0x6b, 0x7b, 0x13, 0x00, 0xca, 0xc9, 0x55, 0x71, 0x96, 0x02, 0xdd, 0x80, 0xe5, 0xea, + 0x38, 0x35, 0x2a, 0x12, 0x17, 0x37, 0xa6, 0xab, 0x5b, 0xfa, 0x53, 0xb4, 0x9c, 0xc9, 0x10, 0xd3, 0x41, 0x10, 0x90, + 0xa9, 0x4f, 0x99, 0x23, 0x64, 0xae, 0xb0, 0x3e, 0x67, 0x4e, 0x6d, 0xea, 0x1e, 0xa7, 0x6e, 0x9e, 0xa4, 0x16, 0xab, + 0xd3, 0xa6, 0x94, 0x88, 0x49, 0x89, 0x79, 0x2a, 0x53, 0xb1, 0x95, 0xb8, 0x73, 0xeb, 0x1b, 0x2d, 0xa4, 0x8d, 0x76, + 0x2a, 0x73, 0xb0, 0xb5, 0xbc, 0x17, 0xa2, 0xfd, 0x25, 0x11, 0x9e, 0x95, 0xc8, 0x58, 0x8b, 0x39, 0x73, 0x4c, 0x04, + 0xab, 0x17, 0x53, 0x91, 0x7f, 0x70, 0x74, 0x9a, 0xbd, 0x41, 0x0f, 0x52, 0x6f, 0x20, 0x31, 0x6b, 0xe2, 0xbb, 0x90, + 0x86, 0x3a, 0x42, 0xa0, 0x32, 0xaa, 0x65, 0x3a, 0x4e, 0x2c, 0x15, 0x97, 0xe4, 0xab, 0xf7, 0xfa, 0x38, 0xdf, 0x78, + 0x6e, 0xac, 0x46, 0x10, 0x83, 0xb7, 0x90, 0x1f, 0x79, 0x52, 0x84, 0x03, 0xe1, 0xf2, 0xcd, 0xcd, 0x5e, 0xbe, 0xcb, + 0xaa, 0x10, 0x49, 0x05, 0x63, 0x8c, 0x19, 0xc5, 0xb8, 0x27, 0x6a, 0x6a, 0x31, 0x07, 0x54, 0x65, 0xeb, 0x30, 0xc7, + 0x03, 0x00, 0x68, 0x69, 0x4a, 0x2f, 0xb3, 0xad, 0x3a, 0xcf, 0x25, 0x7c, 0x8c, 0x3c, 0x14, 0xd9, 0xf8, 0xfd, 0x9a, + 0x0c, 0x14, 0x84, 0xfb, 0x5e, 0xc7, 0xc3, 0xc4, 0x38, 0x58, 0x45, 0x21, 0x0b, 0xf4, 0x06, 0xed, 0x55, 0x89, 0x50, + 0xdc, 0x9c, 0xac, 0xc7, 0x0d, 0x27, 0x15, 0x6c, 0xa1, 0x12, 0x96, 0x4a, 0x0b, 0xfc, 0x6a, 0x23, 0x34, 0x4f, 0x19, + 0xf7, 0xde, 0x54, 0x38, 0x83, 0xfe, 0xe0, 0xde, 0x32, 0xa3, 0xbe, 0x5f, 0x3a, 0x91, 0xa9, 0xc0, 0xc4, 0xcd, 0x2c, + 0xb5, 0xdf, 0x2f, 0xab, 0xb4, 0x9f, 0x57, 0xc8, 0x7d, 0x4e, 0x9a, 0xaf, 0x73, 0x07, 0xcd, 0x27, 0xc3, 0xfd, 0x4a, + 0xf9, 0xa1, 0x85, 0x51, 0x53, 0x7e, 0x79, 0x5d, 0xf9, 0x15, 0x9e, 0x0a, 0x6f, 0xf5, 0xbb, 0x28, 0x74, 0x51, 0x9f, + 0x83, 0x21, 0xa4, 0x1f, 0xc1, 0x35, 0x34, 0x78, 0x50, 0x24, 0x8b, 0xc5, 0xda, 0x05, 0x71, 0x7d, 0xcc, 0xa9, 0x76, + 0x28, 0x63, 0x8c, 0x78, 0x5a, 0x72, 0x90, 0x64, 0x70, 0x30, 0x7e, 0x03, 0x03, 0x62, 0x52, 0x12, 0xd2, 0x21, 0x74, + 0x56, 0x66, 0x22, 0x2a, 0x77, 0xf1, 0x76, 0xe3, 0xb2, 0xa6, 0x50, 0x84, 0x9d, 0x60, 0xa6, 0x52, 0x2a, 0x08, 0xa4, + 0xc9, 0x77, 0xaf, 0x53, 0x0b, 0x86, 0x82, 0x68, 0x30, 0x14, 0x90, 0xd7, 0x76, 0x3d, 0x68, 0xf2, 0x51, 0x1c, 0x3c, + 0xaf, 0x50, 0x23, 0x5e, 0x66, 0xf0, 0x35, 0x6c, 0xfe, 0x9a, 0x28, 0xc9, 0x43, 0x2e, 0x62, 0xaf, 0xe0, 0x13, 0x21, + 0x9b, 0xf2, 0xb0, 0x00, 0xfa, 0xa1, 0x5d, 0xd9, 0x4b, 0x77, 0x8b, 0xca, 0xa5, 0x45, 0x63, 0x2b, 0x51, 0xb3, 0xe6, + 0x87, 0xf1, 0x66, 0x7a, 0x04, 0x53, 0x53, 0x02, 0x01, 0x69, 0x2a, 0x27, 0xa9, 0xe6, 0x3d, 0x4c, 0x8f, 0x00, 0x24, + 0xd8, 0xfd, 0x04, 0x16, 0xfa, 0x4d, 0x89, 0x09, 0x16, 0x55, 0x63, 0xb7, 0x19, 0x68, 0xcd, 0x19, 0x69, 0xbe, 0x19, + 0x42, 0xb8, 0xa9, 0xac, 0x67, 0xcc, 0x0e, 0xb0, 0x6d, 0x77, 0xb3, 0x38, 0x4c, 0x37, 0x3b, 0x47, 0x86, 0xe0, 0xc2, + 0xe3, 0xff, 0xa4, 0xc4, 0x34, 0x90, 0x5c, 0xea, 0xc6, 0x4f, 0xa8, 0xc3, 0x3e, 0x91, 0x3a, 0x11, 0x03, 0x9a, 0xab, + 0xd1, 0x74, 0xee, 0x35, 0x47, 0xc9, 0x65, 0x55, 0xed, 0x6a, 0x09, 0x1a, 0xba, 0x91, 0x8c, 0x89, 0x62, 0x9e, 0x13, + 0x00, 0xa3, 0xd8, 0xfc, 0x39, 0xd3, 0x49, 0xde, 0xbf, 0xac, 0x4c, 0xed, 0xf6, 0x7d, 0x3f, 0xca, 0xcf, 0xe8, 0x48, + 0x45, 0x65, 0x73, 0x12, 0xf3, 0x6f, 0x4b, 0x30, 0x8d, 0x89, 0x0f, 0xf5, 0x5c, 0x47, 0xa1, 0x00, 0x5f, 0xd9, 0x50, + 0x6a, 0xb6, 0xd7, 0xbf, 0x75, 0xb6, 0x87, 0x72, 0x36, 0xc1, 0x02, 0x0d, 0xba, 0xac, 0xc1, 0x17, 0xb0, 0x0c, 0xee, + 0x48, 0x3f, 0x05, 0xdf, 0x4f, 0xeb, 0xe0, 0x33, 0xf6, 0xbf, 0x00, 0xb4, 0x2a, 0x30, 0xa0, 0xdc, 0x69, 0x1a, 0x56, + 0x42, 0x5c, 0xa2, 0xc2, 0xac, 0xe2, 0xfc, 0x71, 0x9d, 0xd7, 0x4d, 0xcb, 0x12, 0x83, 0xf2, 0x33, 0xd7, 0x70, 0xe3, + 0x7b, 0x8d, 0xfc, 0xf1, 0xbd, 0x97, 0xa0, 0xdb, 0x89, 0xb4, 0xf7, 0xef, 0xe7, 0xf7, 0xc8, 0x42, 0x03, 0x3f, 0x2c, + 0x9a, 0x41, 0x5b, 0xbc, 0x08, 0x90, 0xab, 0x67, 0x2c, 0xc6, 0xdb, 0x22, 0x54, 0x86, 0x0f, 0x58, 0x30, 0x03, 0x0c, + 0xc1, 0x63, 0xa7, 0x32, 0xf9, 0x0c, 0x1b, 0x4d, 0xb1, 0x6b, 0x2e, 0x0c, 0x3e, 0x50, 0x95, 0x85, 0xe4, 0xc5, 0x3a, + 0xd9, 0x5e, 0x9c, 0xc3, 0xf3, 0xeb, 0xb8, 0x00, 0xea, 0x20, 0xfa, 0x9a, 0xca, 0x62, 0x03, 0xb9, 0xb8, 0x29, 0x6b, + 0xbd, 0xa2, 0xd1, 0xe8, 0xc6, 0x2e, 0xbc, 0xae, 0xc0, 0x27, 0x51, 0x3a, 0x4a, 0xc4, 0x24, 0x66, 0x52, 0xe5, 0x8a, + 0x5c, 0x1b, 0xdd, 0x4b, 0x5b, 0x34, 0x2f, 0x85, 0x04, 0xaf, 0x08, 0xdc, 0x10, 0xfa, 0x4a, 0x5f, 0xae, 0x36, 0x50, + 0xf0, 0xa8, 0xbd, 0xb9, 0x08, 0x26, 0x26, 0x1e, 0x37, 0xa4, 0xa6, 0x5f, 0x87, 0x53, 0x2b, 0x8b, 0x25, 0x87, 0x5f, + 0xe7, 0x8c, 0x35, 0x14, 0x00, 0xf1, 0xc9, 0xa3, 0xf5, 0x6e, 0xd2, 0x1b, 0xa5, 0x1d, 0x94, 0x46, 0x88, 0xef, 0x2a, + 0x7c, 0xdd, 0x85, 0xe2, 0x2b, 0x57, 0xdd, 0xfb, 0x3a, 0x66, 0xc6, 0x05, 0xa3, 0x97, 0x7c, 0x9a, 0x34, 0xae, 0xdd, + 0xd0, 0x5d, 0x9d, 0xef, 0xbd, 0x2f, 0x65, 0xde, 0xc2, 0x31, 0xb0, 0xc9, 0x31, 0x73, 0x5e, 0x7a, 0x6f, 0x8d, 0x13, + 0xe5, 0x1f, 0xcc, 0x23, 0x5e, 0x39, 0xcc, 0xaa, 0x93, 0xe4, 0x1f, 0x06, 0x3f, 0x04, 0xeb, 0x5b, 0x1a, 0x27, 0xc8, + 0x5d, 0x75, 0x82, 0x4c, 0x94, 0xdb, 0xd0, 0x1b, 0x6e, 0xef, 0xae, 0x02, 0x41, 0x9c, 0x8a, 0xe9, 0xa3, 0x72, 0x5c, + 0x3f, 0x5a, 0xa0, 0x52, 0x11, 0xf1, 0xb9, 0xca, 0x5d, 0x59, 0x9b, 0x1a, 0xea, 0x31, 0x9d, 0xcc, 0x42, 0xd3, 0xac, + 0xc8, 0xa5, 0x6c, 0x7a, 0x8c, 0x5c, 0xb3, 0x53, 0x6d, 0x7e, 0x77, 0xed, 0x21, 0x1d, 0xc7, 0xfb, 0x9e, 0xb5, 0x5a, + 0x70, 0xbf, 0xab, 0x28, 0xbc, 0xeb, 0xc5, 0x46, 0x2a, 0x43, 0xcd, 0x7a, 0x14, 0x7d, 0x1c, 0xb7, 0x99, 0xcb, 0xa3, + 0xec, 0xcf, 0x1a, 0x00, 0xa6, 0x23, 0x2c, 0xba, 0x9b, 0x9e, 0xb1, 0x27, 0xd0, 0xd3, 0x13, 0x19, 0x24, 0x7a, 0xa3, + 0xf3, 0x55, 0xab, 0xc4, 0xd2, 0x15, 0x04, 0x76, 0x6f, 0xc8, 0x58, 0x95, 0xb4, 0x5b, 0xae, 0x5f, 0xce, 0xf3, 0x79, + 0xce, 0x97, 0xf2, 0x7c, 0x6a, 0x16, 0xdd, 0xbd, 0xb6, 0x7b, 0x73, 0x6a, 0xa8, 0x98, 0x6b, 0x75, 0x93, 0xdf, 0x30, + 0x5d, 0x07, 0x43, 0x2d, 0x82, 0xcc, 0x6a, 0x57, 0xbd, 0x28, 0xcb, 0x8d, 0x7a, 0x26, 0xc7, 0x86, 0xf0, 0x4d, 0xa5, + 0x3b, 0x44, 0x37, 0x4c, 0xd5, 0x4c, 0xdf, 0x37, 0xb6, 0x85, 0x6c, 0xf3, 0xf2, 0x6a, 0x94, 0x03, 0xa5, 0xe5, 0xfe, + 0x32, 0x61, 0xf8, 0xfe, 0xfa, 0xfa, 0x7b, 0x21, 0xa7, 0xaa, 0x8e, 0xde, 0xe2, 0xb5, 0xee, 0x19, 0x6c, 0x94, 0xca, + 0x89, 0xb8, 0x60, 0xab, 0x07, 0x6f, 0xee, 0x5e, 0x01, 0xcb, 0x05, 0xec, 0xda, 0x0b, 0xe6, 0x34, 0x86, 0xaa, 0x36, + 0xf0, 0x97, 0xab, 0x07, 0x5b, 0xb5, 0x87, 0xbf, 0x1c, 0x7c, 0x19, 0xdc, 0xd8, 0xd8, 0xd8, 0xc6, 0xdb, 0xb5, 0x44, + 0x90, 0x37, 0x78, 0xa0, 0x8f, 0x57, 0x1f, 0x05, 0x2d, 0x57, 0x88, 0x6d, 0x36, 0x70, 0x28, 0x6c, 0x0d, 0xf2, 0x4d, + 0xca, 0xa4, 0xe1, 0xbc, 0xe0, 0xd9, 0x54, 0xce, 0x50, 0xc8, 0x6b, 0x3e, 0x0e, 0xda, 0x8e, 0xf0, 0xbf, 0xc0, 0xa9, + 0x1d, 0x2f, 0x2f, 0x3e, 0x41, 0x1f, 0xf0, 0x74, 0xa5, 0x34, 0xa5, 0x38, 0xa5, 0x0a, 0xea, 0x2c, 0xd7, 0x79, 0x30, + 0x52, 0x5c, 0x4c, 0x60, 0x71, 0xc1, 0x65, 0xb9, 0x71, 0x36, 0x72, 0xfa, 0x4b, 0xbc, 0xba, 0x48, 0x97, 0x8f, 0x44, + 0xb6, 0x6a, 0xe9, 0xfd, 0xac, 0x4f, 0xb7, 0xed, 0x29, 0xe3, 0x93, 0x6c, 0x44, 0x07, 0x33, 0x3e, 0x4e, 0x84, 0xd7, + 0x27, 0x46, 0xfa, 0x6e, 0x11, 0x98, 0x6e, 0x8e, 0x4d, 0x7e, 0x38, 0x5e, 0x6f, 0x36, 0x6b, 0xdc, 0xc1, 0x3b, 0xe7, + 0x93, 0xb3, 0x28, 0x31, 0xa2, 0xb2, 0xd0, 0xf0, 0x80, 0x56, 0x88, 0x9b, 0xf7, 0x4c, 0x60, 0x5c, 0x76, 0x45, 0x52, + 0xdb, 0x0d, 0x04, 0x2e, 0xf6, 0x38, 0x66, 0xc9, 0xc8, 0xf6, 0xa0, 0x3c, 0xd0, 0x17, 0xa3, 0xe9, 0x16, 0x30, 0x2d, + 0xaf, 0x9d, 0x5d, 0xa4, 0xb6, 0x57, 0x4d, 0x15, 0xc0, 0x2c, 0x59, 0x1e, 0x9f, 0x21, 0xeb, 0x7e, 0x0d, 0x5d, 0xc4, + 0x80, 0xb1, 0x71, 0x65, 0xce, 0x5d, 0xac, 0x5a, 0x11, 0xdf, 0x68, 0x22, 0x4d, 0xea, 0x43, 0xea, 0x7b, 0x14, 0xd6, + 0xea, 0x2a, 0x07, 0x09, 0xdc, 0x23, 0xef, 0x8e, 0xb8, 0xf4, 0xf4, 0x99, 0xc5, 0xb8, 0x4a, 0xdf, 0x52, 0xd7, 0xe2, + 0x9a, 0x61, 0xaf, 0x78, 0x00, 0xf6, 0x07, 0xc6, 0x2d, 0x62, 0x11, 0x6f, 0x67, 0xb5, 0x14, 0xd6, 0xc6, 0x1c, 0x68, + 0x6e, 0xb8, 0xc1, 0xcf, 0xac, 0x5a, 0x33, 0x30, 0xc3, 0x8c, 0x33, 0x92, 0x0f, 0xc6, 0xbd, 0xaa, 0xb1, 0x23, 0x57, + 0x01, 0x44, 0xdf, 0x82, 0x2e, 0xc9, 0xe1, 0x95, 0x2c, 0x57, 0x9d, 0x21, 0xbf, 0x82, 0x75, 0xd6, 0x8b, 0x13, 0x70, + 0x93, 0xa6, 0xac, 0xc4, 0xc4, 0x14, 0x71, 0xb9, 0x59, 0xc6, 0x3c, 0x4d, 0x9f, 0x45, 0x3b, 0x38, 0xb9, 0x91, 0xc0, + 0x11, 0xfb, 0xc6, 0x32, 0x34, 0x13, 0x36, 0x62, 0x22, 0x8d, 0x4a, 0x29, 0x61, 0x03, 0xb9, 0xd4, 0x92, 0xbf, 0xcc, + 0xe5, 0xd5, 0x97, 0xdb, 0x04, 0x07, 0xe4, 0x35, 0xb0, 0x1c, 0x1a, 0xc7, 0x2d, 0x03, 0x89, 0x58, 0x0c, 0x88, 0x51, + 0xab, 0x72, 0x39, 0x19, 0xd5, 0xc9, 0x7c, 0x85, 0x5c, 0xa8, 0xc8, 0x83, 0x5b, 0x02, 0x2f, 0x54, 0xe4, 0x98, 0x3a, + 0x98, 0x95, 0xda, 0x4d, 0x8b, 0x4d, 0x92, 0xf7, 0xcc, 0x80, 0xe4, 0xea, 0x6b, 0x78, 0x68, 0xfc, 0x32, 0xbc, 0xa1, + 0xe8, 0xe9, 0x18, 0x21, 0xa7, 0xa5, 0x31, 0x97, 0xfe, 0x5b, 0x79, 0x9f, 0x56, 0x02, 0xf6, 0x0a, 0xc4, 0x94, 0x81, + 0x4b, 0x6c, 0x5c, 0x90, 0x94, 0xd7, 0xf2, 0x94, 0xdd, 0xd7, 0x50, 0xbe, 0x4b, 0x26, 0x5d, 0xa5, 0xb2, 0xd6, 0x58, + 0x75, 0x3f, 0xcf, 0x59, 0x7e, 0xb5, 0xcf, 0x30, 0x37, 0x19, 0x0d, 0xb2, 0x25, 0x33, 0x9b, 0xf2, 0xab, 0xbd, 0x1b, + 0xbf, 0xf2, 0x50, 0xd2, 0xa1, 0x5a, 0xa5, 0x9b, 0x97, 0x6e, 0x38, 0xc6, 0x8d, 0x1b, 0x8e, 0x00, 0x36, 0x86, 0x9d, + 0x2a, 0x52, 0xeb, 0xfc, 0xf7, 0xa5, 0xf0, 0x93, 0xd8, 0x6b, 0x47, 0x7a, 0xd7, 0x1d, 0xad, 0x4c, 0x4f, 0xbf, 0x01, + 0x55, 0x23, 0x4b, 0xe8, 0x26, 0x54, 0x31, 0x19, 0x89, 0x12, 0xd3, 0x55, 0xca, 0xa3, 0xbe, 0x46, 0x9c, 0x83, 0xb8, + 0xa1, 0xfc, 0xc5, 0x3f, 0x85, 0x57, 0x27, 0x01, 0x1a, 0x51, 0x8b, 0x71, 0x96, 0xf2, 0xd6, 0x38, 0x9a, 0xc6, 0xc9, + 0x55, 0x30, 0x8f, 0x5b, 0xd3, 0x2c, 0xcd, 0x8a, 0x19, 0x70, 0xa5, 0x57, 0x5c, 0x81, 0x0d, 0x3f, 0x6d, 0xcd, 0x63, + 0xef, 0x25, 0x4b, 0xce, 0x19, 0x8f, 0x87, 0x91, 0x67, 0xef, 0xe5, 0x20, 0x1e, 0xac, 0xb7, 0x51, 0x9e, 0x67, 0x17, + 0xb6, 0xf7, 0x21, 0x3b, 0x05, 0xa6, 0xf5, 0xde, 0x5d, 0x5e, 0x9d, 0xb1, 0xd4, 0xfb, 0x78, 0x3a, 0x4f, 0xf9, 0xdc, + 0x2b, 0xa2, 0xb4, 0x68, 0x15, 0x2c, 0x8f, 0xc7, 0xa0, 0x26, 0x92, 0x2c, 0x6f, 0x61, 0xfe, 0xf3, 0x94, 0x05, 0x49, + 0x7c, 0x36, 0xe1, 0xd6, 0x28, 0xca, 0x3f, 0xf5, 0x5a, 0xad, 0x59, 0x1e, 0x4f, 0xa3, 0xfc, 0xaa, 0x45, 0x2d, 0x82, + 0xcf, 0xda, 0xdb, 0xd1, 0xe7, 0xe3, 0x87, 0x3d, 0x9e, 0x43, 0xdf, 0x18, 0xa9, 0x18, 0x80, 0xf0, 0xb1, 0xb6, 0x77, + 0xda, 0xd3, 0xe2, 0x9e, 0x38, 0x51, 0x8a, 0x52, 0x5e, 0x9e, 0x78, 0x57, 0x0c, 0xe0, 0xf6, 0x4f, 0x79, 0xea, 0x81, + 0x2f, 0xc7, 0xb3, 0x74, 0x31, 0x9c, 0xe7, 0x05, 0x0c, 0x30, 0xcb, 0xe2, 0x94, 0xb3, 0xbc, 0x77, 0x9a, 0xe5, 0x40, + 0xb6, 0x56, 0x1e, 0x8d, 0xe2, 0x79, 0x11, 0x3c, 0x9c, 0x5d, 0xf6, 0xd0, 0x56, 0x38, 0xcb, 0xb3, 0x79, 0x3a, 0x92, + 0x73, 0xc5, 0x29, 0x6c, 0x8c, 0x98, 0x9b, 0x15, 0xf4, 0x25, 0x14, 0x80, 0x2f, 0x65, 0x51, 0xde, 0x3a, 0xc3, 0xce, + 0x68, 0xe8, 0xb7, 0x47, 0xec, 0xcc, 0xcb, 0xcf, 0x4e, 0x23, 0xa7, 0xd3, 0x7d, 0xec, 0xa9, 0x7f, 0xfe, 0x8e, 0x0b, + 0x86, 0xfb, 0xca, 0xe2, 0x4e, 0xbb, 0xfd, 0x37, 0x6e, 0xaf, 0x31, 0x0b, 0x01, 0x14, 0x74, 0x66, 0x97, 0x56, 0x91, + 0x25, 0xb0, 0x3e, 0xab, 0x7a, 0xf6, 0x66, 0xe0, 0x37, 0xc5, 0xe9, 0x59, 0xd0, 0x9d, 0x5d, 0x96, 0x88, 0x5d, 0x20, + 0x12, 0x32, 0x25, 0x92, 0xf2, 0x6d, 0xf1, 0x5b, 0x21, 0x7e, 0xb2, 0x1a, 0xe2, 0xae, 0x82, 0xb8, 0xa2, 0x7a, 0x6b, + 0x04, 0xfb, 0x80, 0xc8, 0xdf, 0x29, 0x04, 0x20, 0x13, 0x70, 0x02, 0x73, 0x05, 0x07, 0xbd, 0xfc, 0x66, 0x30, 0xba, + 0xab, 0xc1, 0x78, 0x72, 0x1b, 0x18, 0x79, 0x3a, 0x5a, 0xd4, 0xd7, 0xb5, 0x03, 0xce, 0x69, 0x6f, 0xc2, 0x90, 0x9f, + 0x82, 0x2e, 0x3e, 0x5f, 0xc4, 0x23, 0x3e, 0x11, 0x8f, 0xc4, 0xce, 0x17, 0xa2, 0x6e, 0xa7, 0xdd, 0x16, 0xef, 0x05, + 0x28, 0xb4, 0xa0, 0xe3, 0x63, 0x03, 0x60, 0xa2, 0x2f, 0xd6, 0x7d, 0xc4, 0xe6, 0xbb, 0x5b, 0xbf, 0x54, 0xe3, 0x31, + 0x95, 0x37, 0x28, 0x54, 0x84, 0xfa, 0x66, 0x0b, 0x66, 0xbc, 0xe5, 0xfd, 0x8e, 0x3e, 0xa8, 0x1a, 0x7c, 0xc7, 0x48, + 0xeb, 0x05, 0xcc, 0x33, 0x73, 0x81, 0x7a, 0x69, 0x1f, 0x43, 0x52, 0xad, 0x96, 0x0b, 0x7a, 0x83, 0x63, 0x08, 0x89, + 0x0e, 0x04, 0x9d, 0x7c, 0x50, 0xd0, 0x37, 0x35, 0x32, 0x37, 0x28, 0x9c, 0xcc, 0x85, 0x2d, 0x9f, 0x69, 0xb9, 0x0e, + 0x4a, 0x1a, 0xbc, 0xec, 0x2f, 0x98, 0x6c, 0x00, 0xd2, 0xbb, 0x92, 0xb4, 0xbc, 0x3a, 0x7a, 0x52, 0x2e, 0x5f, 0x36, + 0x24, 0xca, 0x81, 0xaf, 0xcf, 0x27, 0xe8, 0x77, 0xeb, 0xab, 0xeb, 0x46, 0x4a, 0xcd, 0x96, 0xed, 0x0e, 0xb8, 0xce, + 0xca, 0xc2, 0xec, 0x33, 0x5e, 0xe2, 0x28, 0x5f, 0x81, 0x9c, 0xc5, 0xd0, 0xeb, 0xcf, 0xa1, 0x70, 0xd3, 0x94, 0x93, + 0xb6, 0x71, 0xd3, 0xf5, 0x7f, 0x58, 0xf1, 0x98, 0xb2, 0x9d, 0x55, 0x6c, 0x1c, 0x5c, 0x97, 0xe3, 0xa1, 0xb8, 0x76, + 0x58, 0x60, 0xb6, 0xf8, 0x6f, 0xf7, 0x24, 0x1c, 0x8d, 0x56, 0x91, 0xcd, 0xf3, 0x21, 0x26, 0xfd, 0xaf, 0x08, 0x31, + 0xd8, 0xa4, 0xe1, 0x6d, 0x8f, 0x6b, 0xc5, 0xc2, 0x30, 0x7f, 0xc2, 0xfc, 0xaa, 0x02, 0xa3, 0x53, 0x17, 0x71, 0xa9, + 0x41, 0x86, 0x55, 0x14, 0xd8, 0xa8, 0x2b, 0x47, 0x94, 0x60, 0x47, 0x17, 0x3e, 0xfd, 0x79, 0x1a, 0x83, 0x68, 0x3d, + 0x8e, 0x47, 0x74, 0xd1, 0x25, 0x1e, 0xd1, 0xc9, 0x47, 0x8b, 0x32, 0x9d, 0x30, 0x94, 0x0e, 0x05, 0x92, 0xe0, 0xf8, + 0x2c, 0x33, 0x67, 0xec, 0x96, 0x8d, 0xa7, 0x17, 0x86, 0x6e, 0x1e, 0x65, 0xd3, 0x28, 0x4e, 0x03, 0xfc, 0x20, 0x89, + 0xa7, 0x47, 0x0c, 0xb0, 0x8b, 0x07, 0x7f, 0x15, 0xed, 0x3b, 0xae, 0xff, 0x13, 0x08, 0x2e, 0xea, 0x5f, 0x4a, 0xc7, + 0x4f, 0xc3, 0xa5, 0xce, 0x95, 0xeb, 0xa5, 0x20, 0xec, 0xb8, 0xce, 0x6d, 0xa7, 0xc0, 0xca, 0x2e, 0xa3, 0x3f, 0x83, + 0x56, 0x27, 0xe8, 0xb8, 0xcb, 0x2b, 0x60, 0x5c, 0x0c, 0xa8, 0x56, 0x85, 0x4a, 0xe4, 0x1b, 0xcc, 0x21, 0xf9, 0xf3, + 0xfa, 0x5a, 0x7f, 0x3c, 0xa0, 0x71, 0x81, 0x56, 0xa4, 0xdf, 0xc8, 0x4b, 0x98, 0x84, 0x85, 0x7e, 0x16, 0x98, 0x56, + 0xef, 0x1a, 0x5b, 0x4f, 0x6e, 0x25, 0x8c, 0x39, 0x9d, 0xa5, 0x4e, 0x0d, 0x0d, 0x3a, 0xbe, 0x58, 0x33, 0x95, 0x5b, + 0x46, 0xc4, 0xdc, 0x4f, 0x49, 0xe6, 0xd4, 0xaf, 0x3f, 0xc5, 0x18, 0xb8, 0xaf, 0x65, 0x6d, 0x29, 0xf6, 0x1e, 0x9e, + 0xec, 0x0a, 0x21, 0x65, 0x11, 0xeb, 0x86, 0x36, 0x48, 0x0d, 0xdb, 0xfa, 0xe3, 0x10, 0xe8, 0xfc, 0x29, 0xb4, 0x37, + 0x16, 0x8e, 0xba, 0x0b, 0x90, 0xc3, 0x5c, 0x7b, 0x42, 0x51, 0xd3, 0x47, 0x04, 0xec, 0xfe, 0xc6, 0x82, 0x95, 0xbb, + 0x5b, 0xa2, 0x77, 0xff, 0xa4, 0x2c, 0x48, 0xa7, 0x9a, 0xb1, 0xbf, 0x6a, 0x0a, 0x51, 0x07, 0xc3, 0x52, 0xc6, 0x31, + 0x8e, 0x9b, 0x6b, 0x3b, 0x51, 0x04, 0xb9, 0x25, 0xe3, 0x16, 0x98, 0x61, 0x15, 0xe5, 0x20, 0x46, 0x74, 0x0e, 0x4d, + 0x21, 0xd2, 0x46, 0x7a, 0xcb, 0x50, 0x9c, 0x20, 0x04, 0x83, 0x8d, 0x45, 0x5c, 0x86, 0xf0, 0x94, 0x0e, 0xb3, 0x11, + 0xfb, 0xf8, 0xe1, 0x15, 0x5e, 0x93, 0xc8, 0x52, 0x94, 0xa7, 0x99, 0x5b, 0x9e, 0x80, 0x81, 0x85, 0x90, 0xe6, 0xea, + 0x2b, 0x35, 0x00, 0x8c, 0x88, 0x15, 0x59, 0x34, 0x2a, 0x82, 0xc2, 0x4b, 0xdb, 0x1a, 0x08, 0x08, 0xc1, 0x91, 0xc5, + 0x02, 0x30, 0x41, 0xa9, 0x17, 0x07, 0xfc, 0x44, 0xeb, 0x3e, 0x0c, 0xb4, 0xbb, 0x25, 0x1a, 0x01, 0xae, 0x39, 0xa2, + 0x51, 0xa1, 0x8a, 0x59, 0x45, 0x26, 0xba, 0xa3, 0xf8, 0x5c, 0x93, 0x93, 0x52, 0xac, 0xfb, 0xbb, 0x49, 0x74, 0xca, + 0x12, 0x18, 0x12, 0xf8, 0xaa, 0x0d, 0x23, 0x89, 0x57, 0x6b, 0x37, 0x4e, 0x67, 0x73, 0xf9, 0xb5, 0x30, 0x98, 0xb8, + 0x83, 0x07, 0xb8, 0x78, 0x99, 0x61, 0xa0, 0x4e, 0x24, 0x03, 0x39, 0x00, 0x80, 0x48, 0x87, 0x21, 0x08, 0x5d, 0xc5, + 0x2a, 0x50, 0x1a, 0x8f, 0x96, 0xcb, 0x60, 0x7f, 0xcf, 0xb0, 0x34, 0x85, 0xe7, 0x69, 0x9c, 0xe2, 0x63, 0x81, 0x8f, + 0xd1, 0x25, 0x3e, 0x66, 0xf0, 0xa8, 0x71, 0xcf, 0x4b, 0xfb, 0xaf, 0xba, 0x2a, 0x99, 0x5c, 0x01, 0x4b, 0x13, 0x20, + 0xbb, 0xbe, 0x06, 0xb5, 0xa5, 0x49, 0xb0, 0xbb, 0x05, 0xc4, 0x42, 0xee, 0x11, 0xdf, 0x8e, 0xe1, 0x26, 0x19, 0x59, + 0x31, 0x6b, 0x89, 0x72, 0x8b, 0x8c, 0x83, 0x10, 0x7c, 0xc7, 0xdc, 0x69, 0xd8, 0x40, 0x9e, 0xcc, 0x92, 0x79, 0x86, + 0x2f, 0xae, 0x6d, 0x89, 0x8f, 0x7b, 0x08, 0xa2, 0xd0, 0x23, 0x62, 0xa8, 0xcb, 0x98, 0xfc, 0x6c, 0x4f, 0x1c, 0xda, + 0x38, 0x0b, 0x98, 0xa1, 0xe8, 0x85, 0xf2, 0x28, 0x4e, 0x44, 0xe3, 0x15, 0xf8, 0x34, 0xd2, 0x1d, 0x09, 0x9d, 0xdd, + 0xad, 0x0a, 0x36, 0x00, 0x5e, 0x49, 0x04, 0x4e, 0x19, 0x37, 0xb6, 0x28, 0xa7, 0x14, 0x00, 0xb9, 0xcd, 0xab, 0x4f, + 0x3a, 0x01, 0x53, 0x80, 0x11, 0x3d, 0x3a, 0xa6, 0xd9, 0x06, 0x43, 0x20, 0x16, 0xcd, 0xd8, 0xd8, 0xba, 0xf6, 0x5f, + 0xfe, 0xf9, 0x1f, 0x6c, 0x4f, 0x80, 0x98, 0x8d, 0xc7, 0x20, 0xe5, 0xac, 0x75, 0x0d, 0xff, 0xd7, 0x3f, 0xfe, 0xdf, + 0xff, 0xf3, 0x5f, 0x75, 0xdb, 0x14, 0x9a, 0x9e, 0x04, 0xe2, 0x68, 0x41, 0x93, 0x94, 0x52, 0x3c, 0xed, 0x71, 0x94, + 0xae, 0x00, 0xe9, 0x10, 0xb3, 0x18, 0x19, 0x1b, 0x79, 0xb6, 0x05, 0x9a, 0x40, 0x3c, 0x1f, 0x27, 0xec, 0x9c, 0xc9, + 0x0f, 0xcb, 0xe8, 0x41, 0x74, 0xe5, 0x10, 0x2c, 0x18, 0x2e, 0xef, 0xbc, 0xca, 0x6d, 0xa0, 0x68, 0x29, 0x29, 0x5e, + 0x27, 0x98, 0x67, 0x1b, 0x83, 0x36, 0xe7, 0x68, 0xd7, 0x87, 0xf5, 0x40, 0xa5, 0xda, 0xb6, 0x80, 0x97, 0xcc, 0xde, + 0x95, 0x10, 0x37, 0xe1, 0x3a, 0xcd, 0xb1, 0x69, 0xca, 0x8a, 0x62, 0x15, 0x58, 0x40, 0x13, 0xcf, 0xae, 0x9a, 0xd8, + 0xb5, 0x0e, 0x00, 0x40, 0x77, 0x67, 0x47, 0x4c, 0x0b, 0x15, 0x6c, 0x3c, 0x86, 0x0d, 0x8e, 0xba, 0x2d, 0xe1, 0x18, + 0x84, 0x0f, 0xfb, 0xf6, 0x5b, 0x90, 0x25, 0x78, 0xa7, 0xc5, 0xd5, 0x9f, 0xf4, 0xa2, 0xe9, 0x95, 0xb0, 0x33, 0xe6, + 0x10, 0x9d, 0x8d, 0x61, 0xf4, 0x93, 0x81, 0x54, 0x36, 0xfc, 0xb4, 0x8a, 0x31, 0xd6, 0x32, 0xc2, 0xbf, 0xff, 0xcb, + 0x3f, 0xfe, 0x37, 0x18, 0x9b, 0xfa, 0xad, 0xe7, 0x02, 0x68, 0xf5, 0x3f, 0xa1, 0xd5, 0x3c, 0xbd, 0xa5, 0xdd, 0x5f, + 0xfe, 0xfe, 0xbf, 0x43, 0x33, 0xba, 0x28, 0x05, 0x7c, 0x42, 0x10, 0x0d, 0xd1, 0x36, 0xfd, 0x55, 0x20, 0xd5, 0x06, + 0x59, 0x3b, 0xd3, 0x3f, 0x21, 0xd8, 0x05, 0xcf, 0x66, 0x37, 0x82, 0x83, 0x50, 0x0f, 0x93, 0xac, 0x60, 0x1a, 0x1e, + 0xa1, 0x4f, 0x7e, 0x1d, 0x40, 0x34, 0xd7, 0x0c, 0x76, 0x6d, 0x61, 0xe9, 0x71, 0xc4, 0x0a, 0xad, 0xdc, 0x84, 0xf5, + 0x05, 0x2c, 0x18, 0x27, 0x74, 0x28, 0xdc, 0x03, 0x4b, 0x26, 0x9e, 0xe0, 0x81, 0x04, 0x9c, 0x5b, 0xff, 0xf8, 0xda, + 0xea, 0xc1, 0x34, 0xc3, 0x89, 0xb1, 0x44, 0x84, 0x4b, 0x8d, 0x00, 0x7f, 0x41, 0x08, 0x1f, 0xeb, 0xe7, 0xe8, 0x52, + 0x3f, 0xa3, 0xa0, 0x16, 0x13, 0x80, 0xbe, 0x9d, 0xa2, 0x31, 0x66, 0xce, 0x20, 0xb2, 0x33, 0x2a, 0xf7, 0xde, 0x48, + 0xf2, 0x11, 0xc2, 0xf8, 0x18, 0x73, 0x61, 0xf1, 0xe6, 0xd3, 0x3c, 0x67, 0xc7, 0x49, 0x76, 0x81, 0x31, 0x43, 0x22, + 0xd2, 0x9a, 0xfa, 0xf2, 0xdf, 0xfe, 0xd5, 0xf7, 0xff, 0xed, 0x5f, 0xd7, 0x34, 0x98, 0xc0, 0x9e, 0x00, 0x23, 0x9f, + 0x85, 0x9a, 0xce, 0x0d, 0xb4, 0x56, 0x0f, 0x8a, 0x78, 0xae, 0xae, 0x91, 0x88, 0x63, 0xa9, 0xc4, 0x5b, 0x3e, 0x12, + 0xda, 0x9a, 0x29, 0x6e, 0x9f, 0x05, 0x21, 0x5b, 0x33, 0x0d, 0x56, 0xdd, 0x32, 0xcf, 0x89, 0x1b, 0xdc, 0x40, 0x97, + 0x5f, 0x89, 0xf1, 0x6a, 0x30, 0x6e, 0x85, 0xc0, 0x03, 0x6d, 0x26, 0xf4, 0xdd, 0x33, 0xa1, 0xad, 0x02, 0xb1, 0x0c, + 0x52, 0x77, 0xd5, 0x00, 0xf2, 0xac, 0x03, 0x9a, 0x80, 0x9a, 0xc4, 0x95, 0xad, 0x40, 0xe6, 0xd6, 0x69, 0xde, 0x7f, + 0x83, 0x97, 0x1d, 0x91, 0x78, 0x64, 0x29, 0x14, 0x64, 0xd8, 0x30, 0x32, 0x6c, 0xa4, 0x46, 0x35, 0x6d, 0x0a, 0x74, + 0xfc, 0xb2, 0xd5, 0xb6, 0xc3, 0x31, 0x76, 0xaf, 0x69, 0x7f, 0x26, 0xb5, 0x7f, 0x2c, 0xed, 0x7d, 0xa9, 0xfd, 0xf1, + 0x93, 0x36, 0x0d, 0xed, 0x1f, 0xaf, 0xd5, 0xfe, 0x48, 0xb9, 0x01, 0x8e, 0x1c, 0xda, 0x9b, 0x18, 0xdd, 0x32, 0x6c, + 0x0d, 0xd4, 0xc4, 0x83, 0xe1, 0x84, 0x0d, 0x3f, 0x49, 0x33, 0x8b, 0x10, 0xc0, 0x40, 0x94, 0x36, 0x26, 0x05, 0x06, + 0x60, 0x32, 0x9c, 0x94, 0x7a, 0xd3, 0xe3, 0xa3, 0x31, 0x01, 0x73, 0x17, 0x63, 0x86, 0xa2, 0x1f, 0xd6, 0xec, 0x2b, + 0x56, 0x6e, 0xe1, 0x38, 0x62, 0xc3, 0x88, 0x67, 0xc0, 0x6c, 0x0b, 0x07, 0x3b, 0xf1, 0x16, 0x22, 0x58, 0x18, 0xd8, + 0xef, 0xdf, 0xed, 0x1f, 0xd8, 0xde, 0x69, 0x36, 0xba, 0x0a, 0x6c, 0x70, 0xc6, 0xc0, 0x9a, 0x72, 0x7d, 0x3e, 0x61, + 0xa9, 0xa3, 0x3c, 0x9f, 0x2c, 0x61, 0xe0, 0x00, 0x9e, 0x89, 0x6f, 0x5b, 0x34, 0x0f, 0x3a, 0x80, 0xb0, 0xf4, 0xf1, + 0xcb, 0xfe, 0x2e, 0x17, 0xdf, 0x85, 0xe5, 0x39, 0x3e, 0xf6, 0x31, 0xd5, 0x63, 0x77, 0x0b, 0x1e, 0xf0, 0x65, 0x1f, + 0xf5, 0x1e, 0xbd, 0x6d, 0x2c, 0x96, 0xdc, 0x86, 0x01, 0x0e, 0x31, 0xe9, 0x0b, 0x14, 0x0a, 0x6a, 0x75, 0x12, 0x20, + 0x62, 0xf0, 0x08, 0x63, 0x6d, 0xa9, 0x71, 0x11, 0x42, 0xd5, 0x5f, 0x3b, 0x2e, 0x95, 0xdd, 0x4a, 0xf3, 0x8e, 0xb0, + 0x01, 0x39, 0x2e, 0xd8, 0x7b, 0xa4, 0x4b, 0x84, 0xa9, 0x43, 0x45, 0xeb, 0x20, 0xd0, 0x35, 0x95, 0xb9, 0x22, 0x3a, + 0x18, 0xc0, 0x90, 0x99, 0x2b, 0x00, 0x81, 0xbf, 0x84, 0xf6, 0x89, 0xf9, 0xfd, 0x37, 0xf1, 0xa9, 0x26, 0x4d, 0x9c, + 0xc3, 0x3f, 0x79, 0x57, 0xcc, 0xbb, 0x3a, 0xa1, 0x96, 0x2a, 0xd8, 0x80, 0x51, 0x30, 0x0c, 0xca, 0xb4, 0x55, 0x54, + 0x09, 0xec, 0xb4, 0x24, 0x9a, 0x15, 0x2c, 0x50, 0x0f, 0x32, 0xee, 0x80, 0xe1, 0x8b, 0xe5, 0x40, 0x8f, 0x69, 0xcf, + 0x95, 0x7c, 0xb2, 0x30, 0x03, 0x13, 0x8f, 0xda, 0xed, 0x1e, 0x5e, 0xaa, 0x68, 0x45, 0x60, 0x1d, 0xa4, 0x41, 0xc2, + 0xc6, 0xbc, 0xe4, 0x78, 0x6b, 0x7f, 0xa1, 0x22, 0x41, 0x7e, 0x77, 0x27, 0x67, 0x53, 0xcb, 0xc7, 0xff, 0xbf, 0x6d, + 0xec, 0x51, 0x90, 0xf2, 0x49, 0x8b, 0xae, 0xf1, 0xe0, 0x15, 0x49, 0x80, 0xc8, 0x7c, 0x5f, 0x18, 0x13, 0x0d, 0x19, + 0x46, 0xc9, 0x4a, 0x0e, 0xce, 0x37, 0x88, 0x9b, 0xdc, 0x6c, 0x07, 0x72, 0x7a, 0x29, 0x54, 0xb6, 0x1c, 0xac, 0xd9, + 0x76, 0xa5, 0x7f, 0xb4, 0xdc, 0x58, 0x45, 0xbc, 0xea, 0x6f, 0x4b, 0x14, 0x32, 0x62, 0x73, 0xa5, 0x50, 0x51, 0x0b, + 0xd1, 0xc3, 0xc4, 0x69, 0x39, 0x6a, 0x77, 0xab, 0xc5, 0x5c, 0x92, 0xb8, 0x38, 0x24, 0x71, 0x41, 0xe2, 0xef, 0x68, + 0x21, 0xe6, 0x1e, 0x46, 0xc9, 0xd0, 0x41, 0x00, 0xac, 0x96, 0xf5, 0x04, 0xa8, 0xe9, 0xaa, 0xc8, 0x91, 0xff, 0x18, + 0x89, 0x5b, 0x0a, 0x61, 0xb9, 0x82, 0x4a, 0x27, 0x47, 0x65, 0xd9, 0x63, 0xcc, 0x39, 0xfc, 0x20, 0x2f, 0x81, 0x88, + 0xbb, 0xbf, 0xfa, 0xfb, 0x89, 0xed, 0xd2, 0x3d, 0xf2, 0x7e, 0x36, 0x3e, 0x4a, 0x67, 0x2b, 0x66, 0xb7, 0x3d, 0x58, + 0x06, 0xb3, 0xa7, 0xfc, 0x84, 0xe4, 0x4d, 0x7d, 0x4d, 0x36, 0xa7, 0xfe, 0x3f, 0x87, 0x38, 0xc2, 0x1b, 0xc7, 0x46, + 0x13, 0x9d, 0x46, 0xbe, 0x6a, 0x11, 0x7f, 0xda, 0xd8, 0x55, 0x1c, 0x81, 0x7c, 0xbd, 0x2e, 0x92, 0xf5, 0xcd, 0xed, + 0x91, 0xac, 0xe2, 0x8e, 0x91, 0xac, 0x6f, 0x7e, 0xe7, 0x48, 0xd6, 0xd7, 0x66, 0x24, 0x0b, 0x05, 0xf4, 0xab, 0x5f, + 0x13, 0x6d, 0xca, 0xb3, 0x8b, 0x22, 0xec, 0xc8, 0xcc, 0x09, 0x90, 0x75, 0x18, 0x76, 0xfa, 0xeb, 0x47, 0x98, 0x60, + 0xa2, 0x46, 0x7c, 0x89, 0x02, 0x4a, 0x22, 0xd9, 0x13, 0xd4, 0x8a, 0x0c, 0xe7, 0xb4, 0x75, 0x56, 0x65, 0xeb, 0xa1, + 0xba, 0x46, 0x06, 0xae, 0xaf, 0xab, 0x43, 0x6d, 0x5d, 0x15, 0xf0, 0x09, 0xe8, 0x3b, 0xb0, 0xba, 0x63, 0x77, 0x53, + 0xa5, 0xf3, 0x99, 0x23, 0xf4, 0xd4, 0x29, 0x8d, 0x60, 0xa2, 0x85, 0xfd, 0x5f, 0x0e, 0x3b, 0xbd, 0xed, 0xce, 0x14, + 0x7a, 0x83, 0x02, 0x87, 0xb7, 0x76, 0x6f, 0x7b, 0x1b, 0xdf, 0x2e, 0xd4, 0x5b, 0x17, 0xdf, 0x62, 0xf5, 0xb6, 0x83, + 0x6f, 0x43, 0xf5, 0xf6, 0x08, 0xdf, 0x46, 0xea, 0xed, 0x31, 0xbe, 0x9d, 0xdb, 0xe5, 0x21, 0xd3, 0xc0, 0x3d, 0x06, + 0xbe, 0x22, 0x6f, 0x26, 0x50, 0x65, 0xb0, 0xe9, 0xf1, 0xc3, 0x08, 0xd1, 0x59, 0x10, 0x7b, 0xc2, 0xbb, 0x0c, 0x72, + 0xef, 0x02, 0x34, 0x4e, 0x40, 0xd9, 0x86, 0xcf, 0xf1, 0x3b, 0x1c, 0xe0, 0x24, 0x1d, 0xc4, 0x53, 0xa6, 0x3e, 0x48, + 0xac, 0xb0, 0x06, 0x03, 0xf6, 0xb0, 0x7d, 0x54, 0xf6, 0xf4, 0x3a, 0x89, 0x78, 0x96, 0xca, 0xe6, 0xa0, 0x95, 0xab, + 0xea, 0xc4, 0x74, 0x2d, 0xbd, 0xc2, 0x6b, 0xf4, 0x97, 0x11, 0x8f, 0x18, 0x83, 0x61, 0xd6, 0xba, 0x04, 0x0f, 0x76, + 0xa5, 0x4e, 0x43, 0x88, 0xb4, 0x4e, 0x23, 0x9c, 0xf4, 0xdb, 0x41, 0x74, 0xa6, 0x9f, 0xdf, 0x80, 0xa5, 0x1d, 0x9d, + 0xc9, 0x96, 0xeb, 0x75, 0x18, 0x81, 0x68, 0xea, 0x2f, 0x05, 0x04, 0x99, 0x62, 0xb0, 0x34, 0xe8, 0x49, 0x4b, 0xfd, + 0x85, 0xd4, 0xa9, 0x6b, 0x34, 0x9a, 0xbe, 0x5e, 0x04, 0x14, 0xad, 0x0a, 0x76, 0xc1, 0xe0, 0xa7, 0x52, 0x41, 0x61, + 0xa8, 0xc0, 0x02, 0x51, 0xbd, 0x46, 0x95, 0xe9, 0x60, 0xc3, 0x5a, 0x85, 0x66, 0x29, 0x5d, 0x66, 0x9e, 0xee, 0xe8, + 0xa3, 0x9d, 0x65, 0xf1, 0xfa, 0x59, 0x67, 0x88, 0xff, 0x49, 0xe1, 0xfd, 0xd9, 0x78, 0x3c, 0xbe, 0x51, 0xb7, 0x7d, + 0x36, 0x1a, 0xb3, 0x2e, 0xdb, 0xe9, 0x61, 0xe4, 0xbf, 0x25, 0xc5, 0x69, 0xa7, 0x24, 0xda, 0x2d, 0xee, 0xd6, 0x18, + 0x25, 0x2f, 0xa8, 0xbb, 0xbb, 0x2b, 0xc1, 0x12, 0xa8, 0xb2, 0x00, 0xe1, 0x7f, 0x16, 0xa7, 0x41, 0xbb, 0xf4, 0xcf, + 0xa5, 0xd6, 0xf8, 0xec, 0xc9, 0x93, 0x27, 0xa5, 0x3f, 0x52, 0x6f, 0xed, 0xd1, 0xa8, 0xf4, 0x87, 0x0b, 0x8d, 0x46, + 0xbb, 0x3d, 0x1e, 0x97, 0x7e, 0xac, 0x0a, 0xb6, 0xbb, 0xc3, 0xd1, 0x76, 0xb7, 0xf4, 0x2f, 0x8c, 0x16, 0xa5, 0xcf, + 0xe4, 0x5b, 0xce, 0x46, 0xb5, 0xe3, 0x83, 0xc7, 0x6d, 0xa8, 0x14, 0x8c, 0xb6, 0x40, 0xef, 0x52, 0x3c, 0x06, 0xd1, + 0x9c, 0x67, 0x60, 0xd8, 0x95, 0xbd, 0x02, 0xe4, 0xf3, 0x58, 0x4a, 0x78, 0xf1, 0xbd, 0x5f, 0x94, 0xea, 0xaf, 0x4c, + 0xa9, 0x8e, 0xcc, 0x4c, 0xd2, 0xbc, 0x20, 0x6d, 0xd0, 0xac, 0x46, 0xce, 0xa2, 0xea, 0x57, 0x61, 0x51, 0x09, 0x7b, + 0x94, 0x36, 0xd8, 0x52, 0xc8, 0xf8, 0x1f, 0xd6, 0xc9, 0xf8, 0xef, 0x6f, 0x97, 0xf1, 0xa7, 0x77, 0x13, 0xf1, 0xdf, + 0xff, 0xce, 0x22, 0xfe, 0x07, 0x53, 0xc4, 0x0b, 0x21, 0xb6, 0x07, 0xa6, 0x33, 0xd9, 0xcc, 0xa7, 0xd9, 0x65, 0x0b, + 0xb7, 0x44, 0x6e, 0x93, 0xf4, 0x9c, 0xde, 0x49, 0xf8, 0xaf, 0xc8, 0x07, 0x53, 0x83, 0x19, 0x1f, 0x0f, 0xe6, 0xd9, + 0xd9, 0x59, 0xc2, 0x94, 0x8c, 0x37, 0x2a, 0xc8, 0x1c, 0x7f, 0x97, 0x86, 0xf6, 0x3b, 0xf4, 0x8c, 0xab, 0x92, 0xf1, + 0x18, 0x8a, 0xc6, 0x63, 0x5b, 0xe5, 0x4b, 0x83, 0x3c, 0xa3, 0x56, 0x6f, 0x6b, 0x25, 0xd4, 0xea, 0x8b, 0x2f, 0xcc, + 0x32, 0xb3, 0x40, 0x86, 0xf4, 0x4c, 0x63, 0x44, 0xd6, 0x8c, 0xe2, 0x02, 0xf7, 0x60, 0xf5, 0xb1, 0x63, 0xb4, 0x77, + 0xa6, 0xa0, 0x54, 0xe2, 0x21, 0x9e, 0x8b, 0x34, 0x3f, 0x2c, 0x23, 0x72, 0xdb, 0x97, 0x91, 0xab, 0xce, 0xbf, 0x8d, + 0x6f, 0x18, 0x56, 0x67, 0xde, 0xb0, 0xf8, 0x32, 0xbf, 0xe5, 0xe9, 0xd5, 0xab, 0x91, 0xb3, 0x87, 0x97, 0x7f, 0x8b, + 0x77, 0x69, 0x23, 0x6f, 0x50, 0x80, 0x1d, 0x86, 0x26, 0xa6, 0xa5, 0x20, 0x58, 0x75, 0x81, 0xa2, 0xaa, 0xec, 0x19, + 0x9d, 0x64, 0x7a, 0x19, 0x0e, 0x39, 0xa8, 0x91, 0x25, 0x30, 0x07, 0x93, 0xba, 0x90, 0x3e, 0x66, 0x2f, 0x92, 0x6e, + 0xce, 0xe5, 0x57, 0xcf, 0xe9, 0x70, 0x66, 0x21, 0xf5, 0x87, 0x4c, 0xc7, 0xa8, 0x7a, 0xd2, 0x79, 0x08, 0xcd, 0x30, + 0x2a, 0xd5, 0x19, 0x08, 0x10, 0x6e, 0x86, 0x9f, 0x68, 0x12, 0x43, 0xa8, 0x83, 0x82, 0x8a, 0x7a, 0xd7, 0xd7, 0xe6, + 0x97, 0x42, 0x6b, 0x5f, 0x95, 0x6c, 0xf0, 0x00, 0xc7, 0x4f, 0xfc, 0xa2, 0x36, 0xc8, 0xe6, 0xdc, 0xc1, 0x33, 0x80, + 0x05, 0x1e, 0x31, 0x78, 0x3b, 0xed, 0x36, 0xa8, 0x18, 0x5f, 0x7c, 0x07, 0xca, 0xd1, 0x9d, 0x05, 0xbe, 0x6c, 0xdd, + 0xb9, 0xc4, 0xd2, 0x77, 0xd9, 0x2a, 0x12, 0xdf, 0xbf, 0x2f, 0x11, 0x35, 0xee, 0x0e, 0xa9, 0x45, 0x6c, 0xbe, 0xfb, + 0xca, 0x77, 0x34, 0x08, 0xeb, 0xae, 0xe2, 0x60, 0x99, 0x5b, 0x5b, 0x2f, 0xc4, 0xb6, 0xc2, 0xaa, 0x59, 0x06, 0xe7, + 0x16, 0x9d, 0x59, 0x5c, 0x18, 0x01, 0xfc, 0xda, 0x36, 0x28, 0x55, 0x04, 0x5f, 0x84, 0xe1, 0xf7, 0xd0, 0xc5, 0x15, + 0x8e, 0xb7, 0x02, 0xba, 0xe1, 0xf2, 0x56, 0x90, 0xa3, 0x33, 0xac, 0x19, 0x5d, 0x55, 0xa9, 0x82, 0xd2, 0x3c, 0x82, + 0x31, 0x90, 0xa1, 0x48, 0x3a, 0xac, 0x71, 0x2a, 0xf4, 0x16, 0x4c, 0x43, 0x02, 0x58, 0xfb, 0x75, 0xe8, 0xd6, 0xd8, + 0x0a, 0x6c, 0x21, 0x2d, 0x40, 0xe9, 0x61, 0x87, 0xbe, 0x55, 0x03, 0x3d, 0x5d, 0x0e, 0xc0, 0xdf, 0xe8, 0xe4, 0x9d, + 0xf8, 0xc5, 0x85, 0x07, 0xff, 0xac, 0x3f, 0x2c, 0x40, 0xca, 0x9f, 0x7e, 0x8a, 0x39, 0xd8, 0xd4, 0xb3, 0x16, 0x86, + 0x5f, 0x28, 0x4e, 0x2b, 0xd5, 0x21, 0x1d, 0x45, 0x8b, 0x2b, 0x63, 0xbd, 0x79, 0x81, 0xbe, 0x20, 0x39, 0x3d, 0x41, + 0x9a, 0xa5, 0xac, 0x57, 0x4f, 0x39, 0x30, 0xfd, 0x0e, 0x45, 0xac, 0xa3, 0x45, 0x86, 0xbe, 0x23, 0xbf, 0x02, 0xdf, + 0x51, 0xa8, 0xd1, 0xb6, 0x72, 0x3a, 0xda, 0x2b, 0xdb, 0x07, 0x92, 0xb6, 0x9b, 0x64, 0x2d, 0xe4, 0xcb, 0xce, 0xd5, + 0x3a, 0xe7, 0xe8, 0xb6, 0x03, 0x78, 0x0c, 0x0a, 0xab, 0x7f, 0x46, 0xe6, 0x42, 0xb3, 0x98, 0x0e, 0xe0, 0xef, 0x02, + 0x59, 0x10, 0x8d, 0xf1, 0x0b, 0x8b, 0x77, 0x69, 0x79, 0x4a, 0xd9, 0xaf, 0x0b, 0x54, 0xeb, 0x41, 0xe7, 0x09, 0x78, + 0x7b, 0x77, 0x1e, 0xfe, 0x66, 0xf4, 0x4b, 0x49, 0x23, 0x75, 0x89, 0xd9, 0xb6, 0x7b, 0x28, 0x2f, 0x92, 0xe8, 0x0a, + 0x9c, 0x4e, 0xb2, 0x31, 0x4e, 0x31, 0x7a, 0xdc, 0x9b, 0x65, 0x32, 0x93, 0x24, 0x67, 0x09, 0xfd, 0x8c, 0x89, 0x5c, + 0x8a, 0xed, 0x47, 0xb3, 0x4b, 0xb5, 0x1a, 0x9d, 0x46, 0x86, 0xc8, 0xef, 0x9a, 0x08, 0xb2, 0x3e, 0xf3, 0xa4, 0x9e, + 0xcc, 0xb0, 0x03, 0x30, 0x08, 0xc3, 0xa6, 0x95, 0x0b, 0xa8, 0xda, 0x50, 0x62, 0xa4, 0xc2, 0x54, 0x03, 0x59, 0xfe, + 0x36, 0xa8, 0xca, 0xa8, 0x60, 0x3d, 0xfc, 0xd4, 0x65, 0x0c, 0xae, 0xad, 0x34, 0x9e, 0xa6, 0xf1, 0x68, 0x94, 0xb0, + 0x9e, 0xb2, 0x8f, 0xac, 0xce, 0x23, 0xcc, 0x24, 0x31, 0x97, 0xac, 0xbe, 0x2a, 0x06, 0xf1, 0x34, 0x9d, 0xa2, 0x53, + 0xb0, 0xd7, 0xf0, 0x7b, 0x95, 0x2b, 0xc9, 0x29, 0x53, 0x2c, 0xda, 0x15, 0xf1, 0xe8, 0xb9, 0x8e, 0xcb, 0x0e, 0x18, + 0x8b, 0xb4, 0xe0, 0xed, 0x1e, 0xcf, 0x66, 0x41, 0x6b, 0xbb, 0x8e, 0x08, 0x56, 0x69, 0x14, 0xbc, 0x15, 0x68, 0x79, + 0x68, 0x1d, 0x08, 0x2d, 0x67, 0xf9, 0x1d, 0x59, 0x46, 0x03, 0xe0, 0x37, 0x11, 0x75, 0x51, 0x59, 0x47, 0xe6, 0xaf, + 0xb3, 0x5b, 0x3e, 0x5f, 0xbd, 0x5b, 0x3e, 0x57, 0xbb, 0xe5, 0x66, 0x8e, 0xfd, 0x6c, 0xdc, 0xc1, 0xff, 0x7a, 0x15, + 0x42, 0xb0, 0x2a, 0x40, 0x0e, 0x0b, 0xed, 0xe2, 0x56, 0x17, 0xfe, 0x8f, 0x86, 0x6e, 0x7b, 0xf8, 0x9f, 0x0f, 0x16, + 0x60, 0xdb, 0xc2, 0x42, 0xfc, 0xd7, 0xae, 0x55, 0x75, 0x1e, 0x62, 0x1d, 0xf6, 0xda, 0x59, 0xae, 0xeb, 0xde, 0xbc, + 0x69, 0x41, 0x5e, 0x71, 0x27, 0x50, 0xc2, 0x18, 0x5c, 0xb5, 0xe8, 0xf4, 0x14, 0x4a, 0xc7, 0xd9, 0x70, 0x5e, 0xfc, + 0xad, 0x84, 0x5f, 0x12, 0xf1, 0xc6, 0x2d, 0xdd, 0x18, 0x47, 0x75, 0x15, 0x69, 0x49, 0x6a, 0x84, 0x85, 0x5e, 0xa7, + 0xa0, 0x00, 0xc6, 0x64, 0x4e, 0xd7, 0x7f, 0xb8, 0x62, 0x13, 0xfc, 0x7f, 0x59, 0x9b, 0x95, 0xc8, 0xfc, 0x47, 0x89, + 0x71, 0x23, 0x11, 0x7e, 0x15, 0x0d, 0xcc, 0x35, 0x6c, 0x3f, 0x59, 0x0d, 0xee, 0xa1, 0x9a, 0xe9, 0x48, 0x29, 0x05, + 0xa9, 0x77, 0xc0, 0x0b, 0x88, 0xe6, 0x09, 0xbf, 0x79, 0xd4, 0x75, 0x9c, 0xb1, 0x34, 0xea, 0x0d, 0x02, 0xbd, 0x6a, + 0x7b, 0x47, 0x29, 0xfd, 0xd9, 0xe7, 0x0f, 0xf1, 0x3f, 0x11, 0x38, 0x3b, 0xad, 0x7c, 0x23, 0x11, 0x1b, 0x40, 0xdf, + 0x68, 0x5a, 0x73, 0x7e, 0x84, 0x06, 0x27, 0xff, 0xe7, 0xae, 0xad, 0xd1, 0x58, 0xbf, 0x53, 0x73, 0x69, 0x95, 0xfe, + 0xaa, 0xd6, 0xbf, 0x6e, 0xf0, 0x3b, 0xb6, 0x1d, 0x0a, 0x87, 0xa0, 0xde, 0x56, 0xc6, 0x03, 0x97, 0x1a, 0x2b, 0x8a, + 0xdf, 0xb5, 0x7d, 0x65, 0x12, 0x53, 0x8f, 0x69, 0x78, 0xaa, 0x9d, 0x48, 0x79, 0x78, 0x8f, 0x3d, 0x84, 0x1f, 0xf9, + 0x25, 0x0b, 0x1f, 0xe0, 0xd7, 0xd8, 0xac, 0xcb, 0x69, 0x92, 0x82, 0x59, 0x35, 0xe1, 0x7c, 0x16, 0x6c, 0x6d, 0x5d, + 0x5c, 0x5c, 0xf8, 0x17, 0xdb, 0x7e, 0x96, 0x9f, 0x6d, 0x75, 0xdb, 0xed, 0x36, 0x7e, 0x44, 0xcb, 0xb6, 0xce, 0x63, + 0x76, 0xf1, 0x14, 0xdc, 0x0f, 0xfb, 0xb1, 0xf5, 0xc4, 0x7a, 0xbc, 0x6d, 0xed, 0x3c, 0xb2, 0x2d, 0x52, 0x00, 0x50, + 0xb2, 0x6d, 0x5b, 0x42, 0x01, 0x84, 0x36, 0x14, 0xf7, 0x77, 0xcf, 0x94, 0x0d, 0x87, 0x97, 0x14, 0x84, 0x85, 0x04, + 0xfe, 0x5b, 0xf6, 0x89, 0xd5, 0xb7, 0xba, 0x28, 0x6b, 0x49, 0x35, 0xa2, 0x5e, 0x71, 0xbf, 0x0f, 0xa3, 0x59, 0x40, + 0x6c, 0x64, 0x16, 0x62, 0x98, 0x4c, 0x94, 0xd2, 0x14, 0x68, 0x97, 0x9e, 0xc2, 0x13, 0x66, 0xb5, 0x59, 0xf0, 0xfc, + 0xa6, 0xfb, 0x18, 0x74, 0xdc, 0x79, 0xeb, 0xe1, 0xb0, 0xdd, 0xea, 0x58, 0x9d, 0x56, 0xd7, 0x7f, 0x6c, 0x75, 0xc5, + 0xff, 0x83, 0x8c, 0xdc, 0xb6, 0x3a, 0xf0, 0xb4, 0x6d, 0xc1, 0xfb, 0xf9, 0x43, 0x91, 0x5b, 0x12, 0xd9, 0x5b, 0xfd, + 0x5d, 0xfc, 0x4d, 0x29, 0x40, 0xea, 0x73, 0x5b, 0xfc, 0x0a, 0x9e, 0xfd, 0x99, 0x59, 0xda, 0x79, 0xb2, 0xb2, 0xb8, + 0xfb, 0x78, 0x65, 0xf1, 0xf6, 0xa3, 0x95, 0xc5, 0x0f, 0x77, 0xea, 0xc5, 0x5b, 0x67, 0xa2, 0x4a, 0xcb, 0x85, 0xd0, + 0x9e, 0x46, 0xc0, 0x28, 0x97, 0x4e, 0x07, 0xe0, 0x6c, 0x5b, 0x2d, 0xfc, 0xf3, 0xb8, 0xeb, 0xea, 0x5e, 0xa7, 0xd8, + 0x4b, 0x63, 0xf9, 0xf8, 0x09, 0x60, 0xf9, 0xb2, 0xfb, 0x68, 0x88, 0xed, 0x08, 0x51, 0xf8, 0x77, 0xbe, 0xfd, 0x64, + 0x08, 0x1a, 0xc1, 0xc2, 0x7f, 0xf0, 0xdf, 0x64, 0xa7, 0x3b, 0x14, 0x2f, 0x6d, 0xac, 0xff, 0xb6, 0xf3, 0xb8, 0x80, + 0xa6, 0xf8, 0xdf, 0x2f, 0xda, 0x84, 0x46, 0x03, 0xde, 0x1c, 0xf7, 0x21, 0xd0, 0xe8, 0xc9, 0xa4, 0xeb, 0x7f, 0x7e, + 0xfe, 0xd8, 0x7f, 0x32, 0xe9, 0x3c, 0xfe, 0x56, 0xbc, 0x25, 0x40, 0xc1, 0xcf, 0xf1, 0xdf, 0xb7, 0xdb, 0xed, 0x49, + 0xab, 0xe3, 0x3f, 0x39, 0xdf, 0xf6, 0xb7, 0x93, 0xd6, 0x23, 0xff, 0x09, 0xfe, 0xab, 0x86, 0x9b, 0x64, 0x53, 0x66, + 0x5b, 0xb8, 0xde, 0x0d, 0xbf, 0xd7, 0x9c, 0xa3, 0xfb, 0xd0, 0xda, 0x79, 0xf8, 0xf2, 0x09, 0xac, 0xd1, 0xa4, 0xd3, + 0x85, 0xff, 0x5f, 0xf7, 0xf8, 0x2d, 0x12, 0x5e, 0x0e, 0x1c, 0x31, 0x4c, 0x2f, 0x56, 0x84, 0xa3, 0x0f, 0xba, 0x3d, + 0xf0, 0xfe, 0xb4, 0x2e, 0x00, 0xc2, 0xf8, 0xad, 0x01, 0x10, 0xce, 0xef, 0x16, 0x01, 0xa1, 0x5f, 0x1b, 0xf8, 0x1d, + 0x23, 0x20, 0x7f, 0x6a, 0x06, 0xb9, 0x2f, 0xd9, 0x52, 0xa0, 0xa3, 0xe9, 0xac, 0xbd, 0x65, 0xce, 0xe1, 0x97, 0xf8, + 0xe3, 0x06, 0x65, 0x0f, 0x5a, 0x73, 0x6e, 0xc6, 0x83, 0x32, 0xdc, 0xc8, 0x97, 0xf2, 0xe2, 0x43, 0xc1, 0xd7, 0x10, + 0x24, 0xbe, 0x9d, 0x20, 0xdf, 0xde, 0x8d, 0x1e, 0xf1, 0xef, 0x4c, 0x8f, 0x82, 0x1b, 0xf4, 0xa8, 0x45, 0xdc, 0x29, + 0x62, 0x40, 0x8e, 0xfe, 0x3e, 0xbd, 0x3b, 0x9c, 0xbe, 0xc5, 0xb6, 0xc5, 0xb0, 0xa8, 0xb0, 0x45, 0xce, 0xe6, 0xd3, + 0x5f, 0x73, 0x44, 0x20, 0xd2, 0xcd, 0x43, 0x5b, 0x46, 0x61, 0x66, 0xf8, 0xd1, 0x62, 0xf5, 0x72, 0x2e, 0xae, 0x34, + 0x85, 0x74, 0x1f, 0x71, 0x47, 0x47, 0x70, 0xf0, 0x06, 0x40, 0xb8, 0xc8, 0x78, 0x84, 0xbf, 0x8a, 0x05, 0xe4, 0xa6, + 0xdf, 0xcf, 0x8a, 0x79, 0xc2, 0x30, 0x9d, 0x66, 0x28, 0x3e, 0x20, 0x0b, 0x8f, 0xf2, 0xae, 0x21, 0xa6, 0xb0, 0x7f, + 0x83, 0xe9, 0xf7, 0xea, 0xec, 0x60, 0x8a, 0x71, 0x84, 0x37, 0x6c, 0x14, 0x47, 0x8e, 0xed, 0xcc, 0x60, 0x23, 0xc3, + 0x2c, 0xad, 0x5a, 0xee, 0x3b, 0xa5, 0xbd, 0xbb, 0xb6, 0xfa, 0x69, 0xa6, 0x1c, 0x3f, 0x75, 0x17, 0x1e, 0xca, 0xb8, + 0xa3, 0x2d, 0x1d, 0x03, 0x18, 0x5f, 0x95, 0xe4, 0xa8, 0x03, 0x2a, 0x63, 0xc2, 0x16, 0xd6, 0x44, 0xc7, 0xef, 0x82, + 0x77, 0x41, 0xc5, 0xf8, 0xe9, 0xb0, 0xef, 0x9d, 0xd6, 0x36, 0x58, 0x3b, 0x46, 0x37, 0x3d, 0xd0, 0x91, 0xfe, 0xa5, + 0x1f, 0xfd, 0x6b, 0x74, 0xf5, 0x0b, 0x03, 0xb6, 0xe0, 0x88, 0xcf, 0x04, 0xee, 0xb6, 0xf8, 0x44, 0x83, 0x48, 0x28, + 0xc1, 0x0b, 0x73, 0x50, 0xe6, 0x98, 0xbf, 0x4a, 0x26, 0x3e, 0x4d, 0x26, 0x7e, 0x80, 0xb0, 0xac, 0x9a, 0x70, 0x77, + 0x41, 0x67, 0x23, 0xf8, 0x23, 0x9a, 0x98, 0x68, 0x8a, 0xa1, 0xf2, 0xd0, 0xa0, 0x29, 0xbe, 0xbb, 0x35, 0x22, 0x73, + 0x4f, 0x03, 0x44, 0x04, 0x0e, 0xe5, 0xdf, 0xaa, 0x58, 0x3d, 0xc8, 0xa0, 0x16, 0x38, 0xfa, 0xf8, 0xb3, 0x2f, 0xf4, + 0x67, 0x29, 0x64, 0x26, 0x02, 0x21, 0x8d, 0xd2, 0x6a, 0xa8, 0x2a, 0x34, 0x56, 0x3c, 0xbd, 0x3a, 0x90, 0xdf, 0x3c, + 0xb0, 0x31, 0x4a, 0x4d, 0xa7, 0x13, 0xd5, 0xf7, 0xd6, 0x36, 0x41, 0x35, 0xd2, 0xaf, 0xa0, 0x52, 0x82, 0x01, 0x6a, + 0x3f, 0xbc, 0x72, 0x60, 0x49, 0x2f, 0x29, 0xb4, 0x85, 0xee, 0x1b, 0xb1, 0xf3, 0x78, 0x28, 0x55, 0x98, 0x67, 0xc9, + 0xab, 0x52, 0x2d, 0x5a, 0x9a, 0xb0, 0xe3, 0x89, 0x38, 0x01, 0xbc, 0xa0, 0x06, 0x0f, 0xd3, 0xcc, 0xee, 0x3f, 0xe8, + 0xad, 0x23, 0x3e, 0xfe, 0x24, 0xeb, 0x21, 0xf8, 0xa5, 0x7f, 0x1b, 0x3e, 0xc0, 0x1f, 0x65, 0x7d, 0x70, 0x64, 0xbb, + 0x3e, 0x29, 0x80, 0x07, 0xd5, 0x2f, 0xb3, 0xa2, 0xf4, 0xdb, 0x04, 0x5d, 0xed, 0xdd, 0x55, 0x69, 0x4b, 0x05, 0xdd, + 0xdd, 0xa9, 0x14, 0x34, 0x3c, 0x1b, 0x12, 0x19, 0x94, 0x45, 0xd7, 0xdf, 0x31, 0xc4, 0xfe, 0x79, 0x0b, 0xff, 0xd6, + 0x04, 0xff, 0x43, 0x68, 0xa0, 0x24, 0xff, 0x6b, 0x68, 0xbe, 0x2d, 0x94, 0x0c, 0xf4, 0xfb, 0x81, 0xc4, 0xb2, 0x10, + 0xc9, 0xf5, 0x6d, 0xb0, 0xe2, 0xc0, 0x4c, 0x24, 0x63, 0xd8, 0x9e, 0x11, 0x5b, 0x13, 0xbb, 0x52, 0x46, 0x8e, 0x9e, + 0x43, 0x5f, 0x47, 0x7f, 0xc6, 0x7c, 0x55, 0x9d, 0x57, 0x93, 0x12, 0x2b, 0xa6, 0xc0, 0x7d, 0xdd, 0x38, 0x94, 0xeb, + 0x89, 0x3c, 0x6f, 0xfd, 0x1d, 0x94, 0xf5, 0x0c, 0x2d, 0x13, 0xc2, 0x5d, 0x43, 0x44, 0x30, 0xfa, 0xd4, 0x2a, 0x4d, + 0xf2, 0x6a, 0x54, 0x36, 0xe7, 0x07, 0xb3, 0x06, 0x7f, 0x97, 0xb2, 0xba, 0xe5, 0x23, 0xaf, 0xef, 0x62, 0xca, 0xc5, + 0x28, 0xce, 0xe9, 0x56, 0xb8, 0x02, 0xbd, 0x16, 0x78, 0xad, 0xa8, 0x44, 0x52, 0x82, 0x15, 0x03, 0x1b, 0x8b, 0xec, + 0x40, 0x26, 0x06, 0x9a, 0xdf, 0x1a, 0x37, 0xaf, 0xed, 0x8e, 0x44, 0x4e, 0x20, 0xfe, 0x16, 0x83, 0x2d, 0xe8, 0x63, + 0x83, 0xb4, 0x5d, 0xbb, 0x4b, 0xc8, 0x06, 0x43, 0x5c, 0xab, 0x1f, 0xd7, 0x32, 0x05, 0x90, 0x6d, 0x12, 0x5a, 0x8f, + 0x4b, 0x24, 0x74, 0x25, 0x9d, 0x4e, 0x59, 0xc4, 0xfd, 0x28, 0xa5, 0xfc, 0x2d, 0xc7, 0x10, 0x53, 0x5e, 0x87, 0x6d, + 0xbb, 0x25, 0xc8, 0x46, 0xe3, 0xd7, 0xc7, 0xe4, 0xee, 0x86, 0x42, 0xfd, 0xe5, 0xab, 0x7a, 0x2e, 0xf6, 0xa4, 0xdb, + 0x7f, 0x77, 0xb0, 0x67, 0x89, 0x4d, 0xb9, 0xbb, 0x05, 0xaf, 0xbb, 0xe4, 0xc1, 0x8b, 0x54, 0x96, 0x50, 0xa4, 0xb2, + 0x58, 0x22, 0x01, 0x4e, 0xe4, 0x2e, 0x6f, 0x09, 0xb4, 0x6d, 0x8b, 0xa5, 0x43, 0x11, 0x7a, 0x9c, 0x82, 0x97, 0x13, + 0xe3, 0xf7, 0xe9, 0xb6, 0xb0, 0x6b, 0x0b, 0x17, 0xcc, 0x56, 0x59, 0x41, 0xca, 0xae, 0xe1, 0xa9, 0x0a, 0x54, 0x82, + 0x35, 0xc2, 0x54, 0x82, 0x90, 0x1c, 0x4a, 0xe7, 0x25, 0x2f, 0xb7, 0x2e, 0xe6, 0xa7, 0x53, 0x90, 0x93, 0x2a, 0xa9, + 0xe7, 0xa3, 0xec, 0xb0, 0x4b, 0x53, 0xf5, 0x4f, 0x4a, 0x19, 0x49, 0x55, 0xdf, 0x0e, 0x6f, 0xfc, 0xce, 0xaa, 0xc0, + 0x5e, 0xea, 0x05, 0xcc, 0x49, 0x99, 0x6c, 0x1b, 0x39, 0x29, 0x46, 0x5d, 0x09, 0xa8, 0x6f, 0xf7, 0x4f, 0x82, 0x99, + 0x1c, 0xef, 0x75, 0xb6, 0xf4, 0x9b, 0xad, 0x5a, 0x4e, 0x0e, 0x28, 0xbf, 0x5c, 0xdc, 0xeb, 0x90, 0x00, 0xc3, 0x0a, + 0x02, 0x4c, 0xd2, 0x04, 0xb0, 0xe8, 0xe8, 0xdb, 0xde, 0x69, 0xab, 0xb4, 0x5d, 0x28, 0xc3, 0x0d, 0x29, 0xba, 0x18, + 0x93, 0xd4, 0xc2, 0xbf, 0x93, 0x4e, 0x7f, 0x37, 0x92, 0xc6, 0x25, 0x0a, 0x8f, 0x02, 0xa4, 0x07, 0x74, 0x46, 0x0b, + 0xce, 0x8f, 0xb3, 0xad, 0x0b, 0x76, 0xda, 0x8a, 0x66, 0x71, 0x15, 0x6b, 0x45, 0x53, 0x43, 0x4f, 0x99, 0x55, 0x33, + 0xe1, 0x63, 0xd4, 0x40, 0x92, 0x04, 0x77, 0x29, 0x03, 0xb9, 0x64, 0xa1, 0x03, 0x0b, 0x01, 0x85, 0x49, 0xae, 0xab, + 0x80, 0xaf, 0xd4, 0xb8, 0xa5, 0xdd, 0xff, 0xcb, 0x3f, 0xff, 0x6f, 0x19, 0xc3, 0x05, 0xaa, 0x74, 0xd4, 0x58, 0x0d, + 0x42, 0x97, 0xbb, 0x98, 0x02, 0x55, 0x9d, 0xf2, 0xb2, 0xcb, 0xd6, 0x59, 0x1e, 0x8f, 0x5a, 0x93, 0x28, 0x19, 0x03, + 0x60, 0x6b, 0x09, 0x64, 0x26, 0x48, 0x48, 0xa8, 0xeb, 0x45, 0xc8, 0x82, 0xbf, 0x29, 0x11, 0x5b, 0x25, 0xc0, 0xd3, + 0x6e, 0x35, 0xd3, 0xb2, 0xab, 0x0d, 0x55, 0x4b, 0xcd, 0x56, 0x3f, 0x5c, 0xa6, 0x84, 0x5a, 0x2d, 0x2f, 0x1b, 0x5a, + 0xea, 0xc3, 0xa8, 0x7f, 0xff, 0x97, 0x7f, 0xf8, 0x1f, 0xea, 0x15, 0xcf, 0x98, 0xfe, 0xf2, 0x4f, 0x7f, 0x87, 0x29, + 0xd0, 0x96, 0x3e, 0x87, 0x22, 0x39, 0x61, 0x55, 0x87, 0x50, 0x42, 0x60, 0x58, 0x95, 0xd3, 0x57, 0xcf, 0xdf, 0xde, + 0xa7, 0x09, 0x69, 0xb3, 0x49, 0xe8, 0x68, 0xd3, 0x96, 0x15, 0x8f, 0xd4, 0x48, 0x4e, 0xbc, 0x08, 0x95, 0x48, 0xef, + 0x3b, 0x25, 0x47, 0xf9, 0x7a, 0x35, 0x16, 0x2a, 0x42, 0x88, 0x25, 0x65, 0x55, 0x6e, 0x61, 0xe8, 0x7e, 0x81, 0xaf, + 0x41, 0xd7, 0x28, 0xa6, 0xc5, 0xab, 0xf5, 0xe9, 0xfd, 0x34, 0x07, 0xf8, 0xc7, 0x48, 0x71, 0x11, 0x87, 0xa4, 0x63, + 0xe9, 0x16, 0xda, 0x7c, 0xc9, 0x55, 0x49, 0xa3, 0x08, 0x47, 0xf1, 0xe1, 0x93, 0xbf, 0x29, 0xff, 0x38, 0x45, 0xcb, + 0xca, 0x72, 0xa6, 0xd1, 0xa5, 0x74, 0x1f, 0x1f, 0xb5, 0xdb, 0xb3, 0x4b, 0x77, 0x51, 0xcd, 0xe0, 0xad, 0x9b, 0x8c, + 0x62, 0x97, 0xe6, 0x80, 0x74, 0x9e, 0xad, 0xc3, 0xa4, 0xe0, 0x31, 0xb5, 0x31, 0xaa, 0x56, 0x96, 0x7f, 0x58, 0x50, + 0xa4, 0x2e, 0xfe, 0x05, 0xcf, 0x9d, 0x65, 0x50, 0x13, 0x4a, 0x0c, 0x2c, 0x16, 0x46, 0xaf, 0xae, 0xe8, 0x35, 0xe9, + 0x2c, 0xa7, 0x0d, 0x99, 0xe7, 0xe6, 0xe6, 0x89, 0xf7, 0x43, 0x3c, 0xc3, 0x9e, 0x74, 0xbc, 0x49, 0x77, 0xa1, 0x87, + 0xe7, 0x3c, 0x9b, 0x9a, 0x07, 0xe5, 0x2c, 0x62, 0x43, 0x36, 0x56, 0xc1, 0x60, 0x59, 0x2f, 0x0e, 0xc1, 0xcb, 0xc9, + 0xf6, 0x8a, 0xb9, 0x24, 0x48, 0x74, 0x40, 0x0e, 0xf0, 0x7c, 0x86, 0x1b, 0x10, 0xe8, 0x9f, 0x45, 0x3c, 0x20, 0x7e, + 0xed, 0x99, 0xc7, 0xed, 0x11, 0x4a, 0x99, 0x6c, 0x61, 0xc0, 0xd3, 0x13, 0x4d, 0x31, 0x2c, 0x5b, 0x4f, 0xdb, 0x2a, + 0x7d, 0xea, 0x6e, 0x0e, 0x25, 0xa2, 0x3a, 0xdf, 0xca, 0x53, 0xec, 0xa7, 0xb5, 0x70, 0x88, 0x54, 0x31, 0x5d, 0xd7, + 0x5b, 0x59, 0x2f, 0x34, 0xb5, 0xa8, 0xfd, 0x16, 0x0c, 0x30, 0x02, 0xd3, 0x6e, 0xb6, 0xa2, 0x42, 0x6c, 0xf5, 0x34, + 0xfc, 0x56, 0xbb, 0x3e, 0xd1, 0x6c, 0x46, 0x0d, 0x5d, 0x60, 0x62, 0x32, 0x58, 0x51, 0x76, 0x50, 0x86, 0x86, 0x48, + 0x88, 0x90, 0x6d, 0xe4, 0x46, 0x10, 0x4f, 0x32, 0x55, 0x02, 0x7f, 0x72, 0xa2, 0xff, 0xff, 0x00, 0x69, 0x5b, 0x88, + 0x58, 0x18, 0x7f, 0x00, 0x00}; } // namespace web_server } // namespace esphome From 70de2f527824a5cd7d22b6627f7e15884a32723b Mon Sep 17 00:00:00 2001 From: esphomebot Date: Wed, 28 Jun 2023 10:19:36 +1200 Subject: [PATCH 0008/2101] Synchronise Device Classes from Home Assistant (#5018) --- esphome/components/button/__init__.py | 2 ++ esphome/const.py | 1 + 2 files changed, 3 insertions(+) diff --git a/esphome/components/button/__init__.py b/esphome/components/button/__init__.py index 55f2fe794a..a999c6d91e 100644 --- a/esphome/components/button/__init__.py +++ b/esphome/components/button/__init__.py @@ -12,6 +12,7 @@ from esphome.const import ( CONF_TRIGGER_ID, CONF_MQTT_ID, DEVICE_CLASS_EMPTY, + DEVICE_CLASS_IDENTIFY, DEVICE_CLASS_RESTART, DEVICE_CLASS_UPDATE, ) @@ -24,6 +25,7 @@ IS_PLATFORM_COMPONENT = True DEVICE_CLASSES = [ DEVICE_CLASS_EMPTY, + DEVICE_CLASS_IDENTIFY, DEVICE_CLASS_RESTART, DEVICE_CLASS_UPDATE, ] diff --git a/esphome/const.py b/esphome/const.py index 48e62b9b86..3036d13801 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -968,6 +968,7 @@ DEVICE_CLASS_GAS = "gas" DEVICE_CLASS_GATE = "gate" DEVICE_CLASS_HEAT = "heat" DEVICE_CLASS_HUMIDITY = "humidity" +DEVICE_CLASS_IDENTIFY = "identify" DEVICE_CLASS_ILLUMINANCE = "illuminance" DEVICE_CLASS_IRRADIANCE = "irradiance" DEVICE_CLASS_LIGHT = "light" From 832ba38f1b0c58b7117a3a7c6db9c011a310592a Mon Sep 17 00:00:00 2001 From: "F.D.Castel" Date: Tue, 27 Jun 2023 20:13:14 -0300 Subject: [PATCH 0009/2101] Fixes compressed downloads (#5014) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/dashboard/dashboard.py | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/esphome/dashboard/dashboard.py b/esphome/dashboard/dashboard.py index 22bbe0aae9..dd800f534c 100644 --- a/esphome/dashboard/dashboard.py +++ b/esphome/dashboard/dashboard.py @@ -546,22 +546,11 @@ class DownloadBinaryRequestHandler(BaseHandler): return with open(path, "rb") as f: - while True: - # For a 528KB image used as benchmark: - # - using 256KB blocks resulted in the smallest file size. - # - blocks larger than 256KB didn't improve the size of compressed file. - # - blocks smaller than 256KB hindered compression, making the output file larger. + data = f.read() + if compressed: + data = gzip.compress(data, 9) + self.write(data) - # Read file in blocks of 256KB. - data = f.read(256 * 1024) - - if not data: - break - - if compressed: - data = gzip.compress(data, 9) - - self.write(data) self.finish() From abc8e903c11d479f1832296d1eac7cd6c1592ee3 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 28 Jun 2023 11:35:35 +1200 Subject: [PATCH 0010/2101] Add CONFIG_BT_BLE_42_FEATURES_SUPPORTED for ble (#5008) --- esphome/components/esp32_ble/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/esp32_ble/__init__.py b/esphome/components/esp32_ble/__init__.py index f508cecb87..b4cb595da0 100644 --- a/esphome/components/esp32_ble/__init__.py +++ b/esphome/components/esp32_ble/__init__.py @@ -55,3 +55,4 @@ async def to_code(config): if CORE.using_esp_idf: add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True) + add_idf_sdkconfig_option("CONFIG_BT_BLE_42_FEATURES_SUPPORTED", True) From d34c074b92796c41ec6f10c9a7bccda3fdc95c5f Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 28 Jun 2023 12:35:16 +1200 Subject: [PATCH 0011/2101] Bump version to 2023.6.3 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 3036d13801..0d5b211c18 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2023.6.2" +__version__ = "2023.6.3" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From c3ef12d5807bc58400a2a837ceda138b735013f6 Mon Sep 17 00:00:00 2001 From: Ryan DeShone Date: Wed, 28 Jun 2023 19:42:39 -0400 Subject: [PATCH 0012/2101] [SCD30] Disable negative temperature offset (#4850) --- esphome/components/scd30/scd30.cpp | 19 ++++++++++++------- esphome/components/scd30/sensor.py | 5 ++++- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/esphome/components/scd30/scd30.cpp b/esphome/components/scd30/scd30.cpp index 01abca0a1f..3eeca23800 100644 --- a/esphome/components/scd30/scd30.cpp +++ b/esphome/components/scd30/scd30.cpp @@ -42,13 +42,18 @@ void SCD30Component::setup() { ESP_LOGD(TAG, "SCD30 Firmware v%0d.%02d", (uint16_t(raw_firmware_version[0]) >> 8), uint16_t(raw_firmware_version[0] & 0xFF)); - if (this->temperature_offset_ != 0) { - if (!this->write_command(SCD30_CMD_TEMPERATURE_OFFSET, (uint16_t) (temperature_offset_ * 100.0))) { - ESP_LOGE(TAG, "Sensor SCD30 error setting temperature offset."); - this->error_code_ = MEASUREMENT_INIT_FAILED; - this->mark_failed(); - return; - } + uint16_t temp_offset; + if (this->temperature_offset_ > 0) { + temp_offset = (this->temperature_offset_ * 100); + } else { + temp_offset = 0; + } + + if (!this->write_command(SCD30_CMD_TEMPERATURE_OFFSET, temp_offset)) { + ESP_LOGE(TAG, "Sensor SCD30 error setting temperature offset."); + this->error_code_ = MEASUREMENT_INIT_FAILED; + this->mark_failed(); + return; } #ifdef USE_ESP32 // According ESP32 clock stretching is typically 30ms and up to 150ms "due to diff --git a/esphome/components/scd30/sensor.py b/esphome/components/scd30/sensor.py index 1ddf0f1e85..f72b43fd37 100644 --- a/esphome/components/scd30/sensor.py +++ b/esphome/components/scd30/sensor.py @@ -68,7 +68,10 @@ CONFIG_SCHEMA = ( cv.int_range(min=0, max=0xFFFF, max_included=False), ), cv.Optional(CONF_AMBIENT_PRESSURE_COMPENSATION, default=0): cv.pressure, - cv.Optional(CONF_TEMPERATURE_OFFSET): cv.temperature, + cv.Optional(CONF_TEMPERATURE_OFFSET): cv.All( + cv.temperature, + cv.float_range(min=0, max=655.35), + ), cv.Optional(CONF_UPDATE_INTERVAL, default="60s"): cv.All( cv.positive_time_period_seconds, cv.Range( From e823067a6b1bd2eff4d579e5612da2c067353219 Mon Sep 17 00:00:00 2001 From: Sergey Dudanov Date: Tue, 4 Jul 2023 04:18:51 +0400 Subject: [PATCH 0013/2101] fix template binary_sensor publish_initial_state option (#5033) --- .../binary_sensor/template_binary_sensor.cpp | 16 +++++++++++++--- .../binary_sensor/template_binary_sensor.h | 3 ++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/esphome/components/template/binary_sensor/template_binary_sensor.cpp b/esphome/components/template/binary_sensor/template_binary_sensor.cpp index 66ff4be4c4..fce11f63d6 100644 --- a/esphome/components/template/binary_sensor/template_binary_sensor.cpp +++ b/esphome/components/template/binary_sensor/template_binary_sensor.cpp @@ -6,11 +6,21 @@ namespace template_ { static const char *const TAG = "template.binary_sensor"; -void TemplateBinarySensor::loop() { - if (!this->f_.has_value()) +void TemplateBinarySensor::setup() { + if (!this->publish_initial_state_) return; - auto s = (*this->f_)(); + if (this->f_ != nullptr) { + this->publish_initial_state(*this->f_()); + } else { + this->publish_initial_state(false); + } +} +void TemplateBinarySensor::loop() { + if (this->f_ == nullptr) + return; + + auto s = this->f_(); if (s.has_value()) { this->publish_state(*s); } diff --git a/esphome/components/template/binary_sensor/template_binary_sensor.h b/esphome/components/template/binary_sensor/template_binary_sensor.h index a28929b122..5e5624d82e 100644 --- a/esphome/components/template/binary_sensor/template_binary_sensor.h +++ b/esphome/components/template/binary_sensor/template_binary_sensor.h @@ -10,13 +10,14 @@ class TemplateBinarySensor : public Component, public binary_sensor::BinarySenso public: void set_template(std::function()> &&f) { this->f_ = f; } + void setup() override; void loop() override; void dump_config() override; float get_setup_priority() const override { return setup_priority::HARDWARE; } protected: - optional()>> f_{}; + std::function()> f_{nullptr}; }; } // namespace template_ From 36782f13bf0bec2d7c0c989b3a8100903fa224f3 Mon Sep 17 00:00:00 2001 From: Graham Brown Date: Tue, 4 Jul 2023 02:28:19 +0200 Subject: [PATCH 0014/2101] Add alarm to reserved ids (#5042) --- esphome/config_validation.py | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/config_validation.py b/esphome/config_validation.py index 0a6b2dfbb0..cf0b1d3aca 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -108,6 +108,7 @@ ROOT_CONFIG_PATH = object() RESERVED_IDS = [ # C++ keywords http://en.cppreference.com/w/cpp/keyword + "alarm", "alignas", "alignof", "and", From 8df455f55b8251005e0d150b2ffbaca0fc8079eb Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 3 Jul 2023 19:52:42 -0500 Subject: [PATCH 0015/2101] Advertise noise is enabled (#5034) --- esphome/components/mdns/mdns_component.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/esphome/components/mdns/mdns_component.cpp b/esphome/components/mdns/mdns_component.cpp index cdb9aa8e74..581758cf2d 100644 --- a/esphome/components/mdns/mdns_component.cpp +++ b/esphome/components/mdns/mdns_component.cpp @@ -57,6 +57,10 @@ void MDNSComponent::compile_records_() { service.txt_records.push_back({"network", "ethernet"}); #endif +#ifdef USE_API_NOISE + service.txt_records.push_back({"api_encryption", "Noise_NNpsk0_25519_ChaChaPoly_SHA256"}); +#endif + #ifdef ESPHOME_PROJECT_NAME service.txt_records.push_back({"project_name", ESPHOME_PROJECT_NAME}); service.txt_records.push_back({"project_version", ESPHOME_PROJECT_VERSION}); From 8dd509ba53084f9177550d5ff577bc3d8e6825b0 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 4 Jul 2023 13:45:06 +1200 Subject: [PATCH 0016/2101] Update webserver to ea86d81 (#5023) --- esphome/components/web_server/server_index.h | 1185 +++++++++--------- 1 file changed, 594 insertions(+), 591 deletions(-) diff --git a/esphome/components/web_server/server_index.h b/esphome/components/web_server/server_index.h index 2dbb839c5e..180dffab67 100644 --- a/esphome/components/web_server/server_index.h +++ b/esphome/components/web_server/server_index.h @@ -6,597 +6,600 @@ namespace esphome { namespace web_server { const uint8_t INDEX_GZ[] PROGMEM = { - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xbd, 0x7d, 0xdb, 0x76, 0xe3, 0x46, 0x92, 0xe0, 0xf3, - 0x9e, 0xb3, 0x7f, 0xb0, 0x2f, 0x28, 0x58, 0x53, 0x05, 0xb4, 0x40, 0x88, 0xa4, 0x4a, 0x55, 0x65, 0x50, 0x20, 0x5b, - 0x75, 0xb1, 0xab, 0xec, 0xba, 0xb9, 0xa4, 0xb2, 0xdb, 0x96, 0xd5, 0x12, 0x44, 0x26, 0x45, 0xb8, 0x40, 0x80, 0x06, - 0x92, 0xba, 0x98, 0xc2, 0x9c, 0x79, 0x9a, 0xa7, 0x39, 0x67, 0x6f, 0xf3, 0x30, 0x0f, 0x3b, 0x67, 0xe6, 0x61, 0x3f, - 0x62, 0x9f, 0xe7, 0x53, 0xfa, 0x07, 0x76, 0x3e, 0x61, 0x23, 0x22, 0x2f, 0x48, 0x80, 0xa4, 0x24, 0x7b, 0xdc, 0x7b, - 0xdc, 0xd5, 0x02, 0xf2, 0x1a, 0x11, 0x19, 0x19, 0xb7, 0x8c, 0x04, 0x77, 0xef, 0x8d, 0xb2, 0x21, 0xbf, 0x9a, 0x31, - 0x6b, 0xc2, 0xa7, 0x49, 0x7f, 0x57, 0xfe, 0x3f, 0x8b, 0x46, 0xfd, 0xdd, 0x24, 0x4e, 0x3f, 0x59, 0x39, 0x4b, 0xc2, - 0x78, 0x98, 0xa5, 0xd6, 0x24, 0x67, 0xe3, 0x70, 0x14, 0xf1, 0x28, 0x88, 0xa7, 0xd1, 0x19, 0xb3, 0xb6, 0xfa, 0xbb, - 0x53, 0xc6, 0x23, 0x6b, 0x38, 0x89, 0xf2, 0x82, 0xf1, 0xf0, 0xe3, 0xc1, 0x17, 0xad, 0x27, 0xfd, 0xdd, 0x62, 0x98, - 0xc7, 0x33, 0x6e, 0xe1, 0x90, 0xe1, 0x34, 0x1b, 0xcd, 0x13, 0xd6, 0x3f, 0x8f, 0x72, 0xeb, 0x05, 0x0b, 0xdf, 0x9d, - 0xfe, 0xc4, 0x86, 0xdc, 0x1f, 0xb1, 0x71, 0x9c, 0xb2, 0xf7, 0x79, 0x36, 0x63, 0x39, 0xbf, 0xf2, 0xf6, 0x57, 0x57, - 0xc4, 0xac, 0xf0, 0x9e, 0xe9, 0xaa, 0x33, 0xc6, 0xdf, 0x5d, 0xa4, 0xaa, 0xcf, 0x73, 0x26, 0x26, 0xc9, 0xf2, 0xc2, - 0x8b, 0xd7, 0xb4, 0xd9, 0xbf, 0x9a, 0x9e, 0x66, 0x49, 0xe1, 0x7d, 0xd2, 0xf5, 0xb3, 0x3c, 0xe3, 0x19, 0x82, 0xe5, - 0x4f, 0xa2, 0xc2, 0x68, 0xe9, 0xbd, 0x5b, 0xd1, 0x64, 0x26, 0x2b, 0x5f, 0x15, 0x2f, 0xd2, 0xf9, 0x94, 0xe5, 0xd1, - 0x69, 0xc2, 0xbc, 0x9c, 0x85, 0x0e, 0xf7, 0x98, 0x17, 0xbb, 0x61, 0x9f, 0x59, 0x71, 0x6a, 0xf1, 0xc1, 0x0b, 0x46, - 0x25, 0x0b, 0xa6, 0x5b, 0x05, 0xf7, 0xda, 0x1e, 0x90, 0x6b, 0x1c, 0x9f, 0xcd, 0xf5, 0xfb, 0x45, 0x1e, 0x73, 0xf5, - 0x7c, 0x1e, 0x25, 0x73, 0x16, 0xc4, 0xa5, 0x1b, 0xf0, 0x43, 0x76, 0x14, 0xc6, 0xde, 0x27, 0x1a, 0x14, 0x86, 0x5c, - 0x8c, 0xb3, 0xdc, 0x41, 0x5a, 0xc5, 0x38, 0x36, 0xbb, 0xbe, 0x76, 0x58, 0xb8, 0x28, 0x5d, 0xf7, 0x13, 0xf3, 0x87, - 0x51, 0x92, 0x38, 0x38, 0xf1, 0xfd, 0xfb, 0x39, 0xce, 0x18, 0x7b, 0xec, 0x30, 0x3e, 0x72, 0x7b, 0xf1, 0xd8, 0x89, - 0x99, 0x5b, 0xf5, 0xcb, 0xc6, 0x56, 0xcc, 0x1c, 0xe6, 0xba, 0xef, 0xd6, 0xf7, 0xc9, 0x19, 0x9f, 0xe7, 0x00, 0x7b, - 0xe9, 0xbd, 0x53, 0x33, 0xef, 0x63, 0xfd, 0x33, 0xea, 0xd8, 0x03, 0xd8, 0x0b, 0x6e, 0x7d, 0x11, 0x5e, 0xc4, 0xe9, - 0x28, 0xbb, 0xf0, 0xf7, 0x27, 0x11, 0xfc, 0xf9, 0x90, 0x65, 0xfc, 0xfe, 0x7d, 0xe7, 0x3c, 0x8b, 0x47, 0x56, 0x3b, - 0x0c, 0xcd, 0xca, 0xab, 0x67, 0xfb, 0xfb, 0xd7, 0xd7, 0x8d, 0x02, 0x3f, 0x8d, 0x78, 0x7c, 0xce, 0x44, 0x67, 0x00, - 0xc0, 0x86, 0xbf, 0x33, 0xce, 0x46, 0xfb, 0xfc, 0x2a, 0x81, 0x52, 0xc6, 0x78, 0x61, 0x03, 0x8e, 0xcf, 0xb3, 0x21, - 0x90, 0x2d, 0x35, 0x08, 0x0f, 0x4d, 0x73, 0x36, 0x4b, 0xa2, 0x21, 0xc3, 0x7a, 0x18, 0xa9, 0xea, 0x51, 0x35, 0xf2, - 0xbe, 0x0b, 0xc5, 0xf2, 0x3a, 0xae, 0x97, 0xb1, 0x30, 0x65, 0x17, 0xd6, 0x9b, 0x68, 0xd6, 0x1b, 0x26, 0x51, 0x51, - 0x58, 0x29, 0x5b, 0x10, 0x0a, 0xf9, 0x7c, 0x08, 0x0c, 0x42, 0x08, 0x2e, 0x80, 0x4c, 0x7c, 0x12, 0x17, 0xfe, 0xf1, - 0xc6, 0xb0, 0x28, 0x3e, 0xb0, 0x62, 0x9e, 0xf0, 0x8d, 0x10, 0xd6, 0x82, 0xdd, 0x0b, 0xc3, 0xef, 0x5c, 0x3e, 0xc9, - 0xb3, 0x0b, 0xeb, 0x45, 0x9e, 0x43, 0x73, 0x1b, 0xa6, 0x14, 0x0d, 0xac, 0x18, 0xc6, 0xca, 0xb8, 0xa5, 0x07, 0xc3, - 0x05, 0xf4, 0xad, 0x8f, 0x05, 0xb3, 0x4e, 0xe6, 0x69, 0x11, 0x8d, 0x19, 0x34, 0x3d, 0xb1, 0xb2, 0xdc, 0x3a, 0x81, - 0x41, 0x4f, 0x60, 0xc9, 0x0a, 0x0e, 0xbb, 0xc6, 0xb7, 0xdd, 0x1e, 0xcd, 0x05, 0x85, 0x07, 0xec, 0x92, 0x87, 0xbc, - 0x04, 0xc6, 0xb4, 0x0a, 0x8d, 0x86, 0xe3, 0x2e, 0x12, 0x28, 0xe0, 0x61, 0xc6, 0x90, 0x65, 0x1d, 0xb3, 0xb1, 0x5e, - 0x9c, 0x2f, 0xee, 0xdf, 0xd7, 0xb4, 0x46, 0xc2, 0x43, 0xdb, 0xa2, 0xd1, 0xd6, 0xe3, 0x84, 0x78, 0x8d, 0x44, 0xae, - 0xc7, 0x7d, 0x49, 0xbe, 0xfd, 0xab, 0x74, 0x58, 0x1f, 0x1b, 0x2a, 0x4b, 0x9e, 0xed, 0xf3, 0x3c, 0x4e, 0xcf, 0x00, - 0x08, 0xc5, 0x06, 0x46, 0x93, 0xb2, 0x14, 0x8b, 0xff, 0x9e, 0x85, 0x3c, 0xec, 0xe3, 0xe8, 0x29, 0x73, 0xec, 0x82, - 0x7a, 0xd8, 0x00, 0x08, 0x90, 0x1e, 0x18, 0x8c, 0x0f, 0x78, 0xc0, 0x37, 0x6d, 0xdb, 0xfb, 0xce, 0xf5, 0xae, 0x90, - 0x83, 0x7c, 0xdf, 0x27, 0xf6, 0x15, 0x9d, 0xe3, 0xb0, 0x83, 0x40, 0xfb, 0x09, 0x4b, 0xcf, 0xf8, 0x64, 0xc0, 0x0f, - 0xdb, 0x47, 0x01, 0x03, 0xa8, 0x46, 0xf3, 0x21, 0x73, 0x90, 0x1f, 0xbd, 0x1c, 0xb7, 0xcf, 0xa6, 0x03, 0x53, 0xe0, - 0xc2, 0xdc, 0x23, 0x1c, 0x6b, 0x4b, 0xe3, 0x2a, 0xd8, 0x14, 0x60, 0xc8, 0xe7, 0x36, 0xec, 0xb0, 0x53, 0x96, 0x1b, - 0x70, 0xe8, 0x66, 0xbd, 0xda, 0x0a, 0xce, 0x61, 0x85, 0xa0, 0x9f, 0x35, 0x9e, 0xa7, 0x43, 0x1e, 0x83, 0xe0, 0xb2, - 0x37, 0x01, 0x5c, 0xb1, 0x72, 0x7a, 0xe1, 0x6c, 0xb7, 0x74, 0x9d, 0xd8, 0xdd, 0xe4, 0x87, 0xf9, 0x66, 0xe7, 0xc8, - 0x43, 0x28, 0x35, 0xf1, 0x25, 0xe2, 0x31, 0x20, 0x58, 0x7a, 0x1f, 0x99, 0xde, 0x9e, 0x5f, 0x0c, 0xb8, 0xbf, 0xcc, - 0xc7, 0x21, 0xf3, 0xa7, 0xd1, 0x0c, 0xb1, 0xe1, 0xc4, 0x03, 0x51, 0x3a, 0x44, 0xe8, 0x6a, 0xeb, 0x82, 0x14, 0xf3, - 0x2b, 0x16, 0x70, 0x81, 0x20, 0xb0, 0x67, 0x5f, 0x44, 0xc3, 0x09, 0x6c, 0xf1, 0x8a, 0x70, 0x23, 0xb5, 0x1d, 0x86, - 0x39, 0x8b, 0x38, 0x7b, 0x91, 0x30, 0x7c, 0xc3, 0x15, 0x80, 0x9e, 0xb6, 0xeb, 0xe5, 0x6a, 0xdf, 0x25, 0x31, 0x7f, - 0x9b, 0xc1, 0x3c, 0x3d, 0xc1, 0x24, 0xc0, 0xc5, 0xf9, 0xfd, 0xfb, 0x31, 0xb2, 0xc8, 0x1e, 0x87, 0xd5, 0x3a, 0x9d, - 0x73, 0x58, 0xb7, 0x14, 0x5b, 0xd8, 0x40, 0x6d, 0x2f, 0xf6, 0x39, 0x10, 0xf1, 0x59, 0x96, 0x72, 0x18, 0x0e, 0xe0, - 0xd5, 0x1c, 0xe4, 0x47, 0xb3, 0x19, 0x4b, 0x47, 0xcf, 0x26, 0x71, 0x32, 0x02, 0x6a, 0x94, 0x80, 0x6f, 0xc2, 0x42, - 0xc0, 0x13, 0x90, 0x09, 0x6e, 0xc6, 0x88, 0x96, 0x0f, 0x19, 0x99, 0x85, 0xb6, 0xdd, 0x43, 0x09, 0x24, 0xb1, 0x40, - 0x19, 0x44, 0x0b, 0xf7, 0x01, 0x44, 0x7f, 0xe1, 0xb2, 0xcd, 0x30, 0xd6, 0xcb, 0x28, 0x09, 0xfc, 0x1e, 0x25, 0x0d, - 0xd0, 0x1f, 0x08, 0xc1, 0x7b, 0x28, 0xb8, 0xbe, 0x92, 0x52, 0x27, 0x62, 0x0a, 0x43, 0x20, 0xc0, 0x10, 0x25, 0x88, - 0xa4, 0xc1, 0xfb, 0x2c, 0xb9, 0x1a, 0xc7, 0x49, 0xb2, 0x3f, 0x9f, 0xcd, 0xb2, 0x9c, 0x7b, 0x5f, 0x87, 0x0b, 0x9e, - 0x55, 0xb8, 0xd2, 0x26, 0x2f, 0x2e, 0x62, 0x8e, 0x04, 0x75, 0x17, 0xc3, 0x08, 0x96, 0xfa, 0x69, 0x96, 0x25, 0x2c, - 0x4a, 0x01, 0x0d, 0x3e, 0xb0, 0xed, 0x20, 0x9d, 0x27, 0x49, 0xef, 0x14, 0x86, 0xfd, 0xd4, 0xa3, 0x6a, 0x21, 0xf1, - 0x03, 0x7a, 0xde, 0xcb, 0xf3, 0xe8, 0x0a, 0x1a, 0x62, 0x1b, 0x60, 0x2f, 0x58, 0xad, 0xaf, 0xf6, 0xdf, 0xbd, 0xf5, - 0x05, 0xe3, 0xc7, 0xe3, 0x2b, 0x00, 0xb4, 0xac, 0xa4, 0xe6, 0x38, 0xcf, 0xa6, 0x8d, 0xa9, 0x91, 0x0e, 0x71, 0xc8, - 0x7b, 0x6b, 0x40, 0x88, 0x69, 0x64, 0x58, 0x25, 0x6e, 0x42, 0xf0, 0x96, 0xf8, 0x59, 0x56, 0xe2, 0x1e, 0x18, 0xe0, - 0x43, 0x20, 0x8a, 0x61, 0xca, 0x5b, 0xa0, 0xcd, 0xaf, 0x16, 0x71, 0x48, 0x70, 0xce, 0x50, 0xff, 0x22, 0x8c, 0xc3, - 0x08, 0x66, 0x5f, 0x88, 0x01, 0x4b, 0x05, 0x71, 0x5c, 0x96, 0xde, 0x44, 0x33, 0x31, 0x4a, 0x3c, 0x14, 0x28, 0x2c, - 0x0c, 0x41, 0xc1, 0x70, 0x78, 0x71, 0xbd, 0x6f, 0xc2, 0x45, 0xa4, 0xf0, 0x41, 0x0d, 0x85, 0xfb, 0x2b, 0x10, 0x72, - 0x02, 0x35, 0xd9, 0x39, 0xe8, 0x41, 0x80, 0xf3, 0x6b, 0x50, 0x7f, 0xe3, 0x04, 0xa1, 0xb8, 0xd7, 0xf1, 0x40, 0x83, - 0x3e, 0x9b, 0x44, 0xe9, 0x19, 0x1b, 0x05, 0x13, 0x56, 0x4a, 0xc9, 0xbb, 0x67, 0xc1, 0x1a, 0x03, 0x3b, 0x15, 0xd6, - 0xcb, 0x83, 0x37, 0xaf, 0xe5, 0xca, 0xd5, 0x84, 0x31, 0x2c, 0xd2, 0x1c, 0xd4, 0x2a, 0x88, 0x6d, 0x29, 0x8e, 0x5f, - 0x70, 0x25, 0xbd, 0x45, 0x49, 0x5c, 0x7c, 0x9c, 0x81, 0x89, 0xc1, 0xde, 0xc3, 0x30, 0x30, 0x7d, 0x08, 0x53, 0x51, - 0x39, 0xcc, 0x27, 0x2a, 0x46, 0xba, 0x08, 0x3a, 0x0b, 0x4c, 0xc5, 0x6b, 0xe6, 0xb8, 0x25, 0xb0, 0x2a, 0x8f, 0x87, - 0x56, 0x34, 0x1a, 0xbd, 0x4a, 0x63, 0x1e, 0x47, 0x49, 0xfc, 0x0b, 0x51, 0x72, 0x81, 0x3c, 0xc6, 0x7a, 0x72, 0x11, - 0x00, 0x77, 0xea, 0x91, 0xb8, 0x4a, 0xc8, 0xde, 0x23, 0x62, 0x08, 0x69, 0x99, 0x84, 0x87, 0x47, 0x12, 0xbc, 0xc4, - 0x9f, 0xcd, 0x8b, 0x09, 0x12, 0x56, 0x0e, 0x8c, 0x82, 0x3c, 0x3b, 0x2d, 0x58, 0x7e, 0xce, 0x46, 0x9a, 0x03, 0x0a, - 0xc0, 0x8a, 0x9a, 0x83, 0xf1, 0x42, 0x33, 0x3a, 0x4a, 0x87, 0x72, 0x18, 0xaa, 0x67, 0x8a, 0x59, 0x26, 0x99, 0x59, - 0x5b, 0x38, 0x5a, 0x0a, 0x38, 0xc2, 0xa8, 0x90, 0x92, 0x20, 0x0f, 0x15, 0x86, 0x13, 0x90, 0x42, 0xcc, 0xad, 0x6d, - 0x73, 0xa5, 0xc9, 0x5e, 0xcc, 0x49, 0x25, 0xe4, 0xd0, 0x11, 0x36, 0x32, 0x41, 0x9a, 0xbb, 0xb0, 0xab, 0x40, 0xca, - 0x4b, 0x70, 0x85, 0x14, 0x51, 0x66, 0x0e, 0x32, 0x40, 0xf8, 0x0d, 0xe9, 0x42, 0x50, 0x26, 0xd0, 0x82, 0x21, 0x1b, - 0xf8, 0x7a, 0xe5, 0x81, 0xb0, 0x12, 0xef, 0x0a, 0x11, 0x6f, 0x0d, 0xd8, 0xa4, 0x8b, 0x00, 0x30, 0xef, 0x1e, 0xf3, - 0xd3, 0x6c, 0x6f, 0x38, 0x64, 0x45, 0x91, 0x01, 0x6c, 0xf7, 0xa8, 0xfd, 0x3a, 0x43, 0x0b, 0x28, 0xe9, 0x6a, 0x59, - 0x67, 0x17, 0xa4, 0xc1, 0x4d, 0xb5, 0xa2, 0x74, 0x7a, 0x60, 0x1f, 0x1f, 0x83, 0xcc, 0xf6, 0x24, 0x19, 0x80, 0xea, - 0xcb, 0x86, 0x9f, 0xb0, 0x67, 0xea, 0x94, 0x59, 0x69, 0x5f, 0x3a, 0x75, 0x90, 0x3c, 0x18, 0xd6, 0x2d, 0x8d, 0x05, - 0x5d, 0x39, 0x34, 0xae, 0x86, 0x54, 0x90, 0x8b, 0x33, 0x52, 0xd9, 0xc6, 0x32, 0x82, 0xd5, 0x56, 0x7a, 0x44, 0x7a, - 0x85, 0x4d, 0x41, 0x80, 0x1e, 0xf2, 0xa3, 0x9e, 0xac, 0x0f, 0x73, 0x41, 0xb9, 0x9c, 0xfd, 0x3c, 0x67, 0x05, 0x17, - 0xac, 0x0b, 0xe3, 0x82, 0xb9, 0x0a, 0x22, 0xb6, 0x69, 0x1d, 0xd6, 0x6c, 0xc7, 0x55, 0xb0, 0xbd, 0x9b, 0xa1, 0x1e, - 0x2b, 0x90, 0x93, 0x6f, 0x66, 0x27, 0xb2, 0x27, 0xdc, 0xeb, 0xeb, 0x6f, 0xd4, 0x20, 0xd5, 0x52, 0x6a, 0x1b, 0xa8, - 0xb1, 0x26, 0xb6, 0x6a, 0x32, 0xb2, 0x5d, 0xa9, 0x50, 0xef, 0x75, 0x7a, 0x35, 0x3e, 0x80, 0x3d, 0xd7, 0xd6, 0x2c, - 0x5d, 0x19, 0xdb, 0xef, 0x15, 0x4d, 0xdf, 0x89, 0x91, 0xc9, 0x1a, 0xe5, 0xb7, 0x73, 0x8f, 0xda, 0xf1, 0xd0, 0x76, - 0xa9, 0xae, 0x12, 0x0c, 0xf3, 0xba, 0x60, 0x68, 0x42, 0x3d, 0xd3, 0x5d, 0x6c, 0xcd, 0x54, 0x3c, 0x54, 0x6b, 0xad, - 0x1c, 0x08, 0x16, 0x1e, 0x82, 0x71, 0xb2, 0xd2, 0x3f, 0x78, 0x1b, 0x4d, 0x19, 0x52, 0xd4, 0x5b, 0xd7, 0x40, 0x3a, - 0x10, 0xd0, 0xe4, 0xa8, 0xa9, 0xde, 0x98, 0x2b, 0xac, 0xa6, 0xfa, 0xfe, 0x8a, 0xc1, 0x8a, 0x00, 0xfb, 0xba, 0x5c, - 0xb1, 0x44, 0xa4, 0x37, 0x05, 0x97, 0x68, 0xfa, 0x88, 0x32, 0xb1, 0x26, 0xa4, 0xe0, 0x01, 0x79, 0x58, 0xfe, 0xc6, - 0xc2, 0xa9, 0x56, 0x0a, 0x47, 0x86, 0x32, 0x05, 0xe8, 0x4c, 0x4a, 0x00, 0xc4, 0x25, 0xfd, 0xad, 0x6d, 0x2c, 0x24, - 0xdb, 0x3e, 0xf2, 0x81, 0x3f, 0x4e, 0x22, 0xee, 0x74, 0xb6, 0xda, 0x2e, 0xf0, 0x21, 0x08, 0x71, 0xd0, 0x11, 0x60, - 0xde, 0x57, 0xa8, 0x70, 0xf2, 0x16, 0x5c, 0xe6, 0x83, 0x51, 0x34, 0x89, 0xc7, 0xdc, 0x49, 0x50, 0x89, 0xb8, 0x25, - 0x4b, 0x40, 0xc9, 0xe8, 0x7d, 0x05, 0xca, 0x82, 0x09, 0xe9, 0x22, 0xaa, 0x95, 0x40, 0x63, 0x0a, 0x52, 0x92, 0x52, - 0xa4, 0x05, 0x15, 0x04, 0x86, 0x50, 0xe9, 0x29, 0x8e, 0x02, 0xfd, 0x16, 0x0f, 0xc4, 0xa0, 0xc1, 0x92, 0x45, 0x19, - 0x0f, 0xe2, 0xe5, 0x42, 0x50, 0xc3, 0x3e, 0xcf, 0x5e, 0x67, 0x17, 0x2c, 0x7f, 0x16, 0x21, 0xec, 0x81, 0xe8, 0x5e, - 0x82, 0xa4, 0x27, 0x81, 0xce, 0x7b, 0x8a, 0x57, 0xce, 0x09, 0x69, 0x58, 0x88, 0x69, 0x8c, 0x8a, 0x10, 0xec, 0x16, - 0xa2, 0x7d, 0x8a, 0x5b, 0x8a, 0xf6, 0x1e, 0xaa, 0x12, 0xae, 0x79, 0x6b, 0xef, 0x75, 0x9d, 0xb7, 0x60, 0x84, 0x99, - 0xe2, 0xd6, 0xfa, 0x8e, 0x75, 0x3d, 0xa9, 0x9b, 0x1d, 0xc9, 0x5b, 0x86, 0x32, 0x03, 0xfd, 0x71, 0x7d, 0x5d, 0x19, - 0xe9, 0xa0, 0x4c, 0xb5, 0x34, 0x47, 0x08, 0xc4, 0x96, 0x70, 0x4b, 0x50, 0x46, 0x68, 0x78, 0xe5, 0x59, 0x92, 0x18, - 0xba, 0xc8, 0x8b, 0x7b, 0x4e, 0x43, 0x1d, 0x01, 0x14, 0xd3, 0x9a, 0x46, 0x1a, 0xb0, 0x40, 0x57, 0xa0, 0x52, 0x52, - 0xda, 0xc8, 0xab, 0xd6, 0x46, 0x40, 0x9c, 0x8e, 0x58, 0x2e, 0x1c, 0x34, 0xa9, 0x43, 0x61, 0xc2, 0x14, 0x18, 0x9a, - 0x8d, 0x40, 0xc2, 0x2b, 0x04, 0xc0, 0x3c, 0xf1, 0x27, 0x59, 0xc1, 0x75, 0x9d, 0x09, 0x7d, 0x7c, 0x7d, 0x1d, 0x0b, - 0x7f, 0x11, 0x19, 0x20, 0x67, 0xd3, 0xec, 0x9c, 0xad, 0x80, 0xba, 0xa7, 0x06, 0x33, 0x41, 0x36, 0x86, 0x01, 0x25, - 0x0a, 0xaa, 0x65, 0x96, 0xc4, 0x60, 0xe9, 0xeb, 0x06, 0x3e, 0x18, 0x74, 0xec, 0x12, 0x65, 0x84, 0xdb, 0xef, 0xf7, - 0xdb, 0x5e, 0xc7, 0x2d, 0x05, 0xc1, 0x17, 0x4b, 0x14, 0xbd, 0x41, 0x3f, 0x4a, 0x13, 0x7c, 0x95, 0x2c, 0x60, 0xae, - 0xa1, 0x14, 0x39, 0xe9, 0x26, 0xe6, 0x49, 0x41, 0xec, 0x7a, 0x23, 0x18, 0x94, 0x33, 0x25, 0xb8, 0xd1, 0xc4, 0x15, - 0xdb, 0xf6, 0x83, 0x26, 0x9b, 0x66, 0x27, 0xb5, 0xc3, 0xd4, 0xc2, 0xc8, 0x35, 0x2f, 0xb4, 0x07, 0x6c, 0x2e, 0x0f, - 0xd9, 0xf4, 0x58, 0x0d, 0xbc, 0x0e, 0x10, 0x0a, 0x4f, 0xd7, 0x59, 0x42, 0xa9, 0xea, 0x2c, 0x85, 0xb8, 0xde, 0x40, - 0x1f, 0x99, 0x04, 0x73, 0x15, 0x09, 0xf6, 0xa5, 0x40, 0x60, 0xe8, 0x91, 0x89, 0xf5, 0x7a, 0x06, 0xcb, 0x73, 0x1a, - 0x0d, 0x3f, 0x69, 0x70, 0x2b, 0xde, 0x6b, 0xb2, 0x81, 0xd3, 0x28, 0x09, 0x0d, 0x71, 0x65, 0xe2, 0xad, 0x24, 0x74, - 0x6d, 0xa3, 0x80, 0x43, 0xb6, 0xc4, 0xf6, 0xcd, 0x85, 0x6e, 0x72, 0xbb, 0x64, 0x0f, 0xe5, 0x3f, 0x55, 0x5c, 0xb2, - 0x9e, 0xe5, 0x98, 0x92, 0x06, 0x4c, 0x31, 0x1e, 0x2c, 0x4d, 0x03, 0x12, 0xe0, 0xbb, 0x72, 0x14, 0x17, 0xeb, 0x49, - 0xf0, 0xbb, 0x82, 0xf9, 0xdc, 0x98, 0xe9, 0x56, 0x48, 0xb5, 0x84, 0x93, 0x66, 0xb0, 0x06, 0x4d, 0x1a, 0x0f, 0x4a, - 0xd4, 0x7c, 0x8d, 0x86, 0x0a, 0x71, 0xfc, 0x99, 0xa8, 0x42, 0x13, 0x0c, 0xc1, 0xc8, 0xbd, 0x42, 0x32, 0x5c, 0xb6, - 0x2c, 0x5a, 0xa4, 0x4c, 0x8d, 0x49, 0xa5, 0x6a, 0x96, 0xcb, 0xc0, 0xc0, 0xa2, 0xdd, 0xea, 0x4b, 0x4b, 0x5c, 0x89, - 0xdc, 0x34, 0xd4, 0xc2, 0xa4, 0x50, 0xde, 0x84, 0x93, 0xa3, 0xdf, 0xa5, 0xac, 0x77, 0x13, 0x9f, 0x5c, 0xe1, 0x93, - 0xfb, 0x86, 0x0f, 0x65, 0xf2, 0x76, 0x31, 0x28, 0x82, 0xaf, 0x6b, 0x95, 0x68, 0x9f, 0xfa, 0x28, 0x98, 0x5d, 0x2d, - 0x74, 0x41, 0xa0, 0x48, 0x36, 0x49, 0x07, 0x92, 0xdf, 0x50, 0x6c, 0x54, 0x9e, 0x51, 0xe6, 0x8a, 0x0d, 0x52, 0xf3, - 0x4a, 0x33, 0x2f, 0x75, 0x1b, 0xf6, 0x7b, 0x59, 0x4a, 0x3a, 0x31, 0x41, 0x99, 0xd8, 0xbb, 0x89, 0x36, 0x5e, 0x1a, - 0x66, 0xc2, 0xfa, 0x15, 0xc6, 0x4e, 0x8d, 0x42, 0xa9, 0x14, 0x81, 0x38, 0x36, 0xbe, 0x56, 0x96, 0x41, 0xe6, 0xaf, - 0xb0, 0xa7, 0x00, 0x94, 0x04, 0x16, 0x5f, 0x53, 0xc9, 0x8b, 0xc2, 0x3a, 0x1d, 0xef, 0x11, 0x1d, 0x2b, 0x11, 0x5a, - 0x13, 0xf9, 0x5a, 0x9f, 0xc5, 0x7e, 0xcd, 0x25, 0x34, 0x29, 0x99, 0x0f, 0xf2, 0xc0, 0x56, 0x81, 0x88, 0x4a, 0xb7, - 0x25, 0x83, 0x84, 0x1c, 0xd2, 0x65, 0xa2, 0xd7, 0x46, 0x32, 0x68, 0x9d, 0x0a, 0x89, 0x96, 0x1e, 0x85, 0x11, 0x8a, - 0x0d, 0xb1, 0x16, 0x4b, 0x84, 0x6c, 0xda, 0x9b, 0xc4, 0x8a, 0xe8, 0x9c, 0xe6, 0x68, 0xc2, 0x99, 0x3a, 0xdd, 0x71, - 0x00, 0x1d, 0x10, 0xfb, 0x4b, 0xac, 0xb7, 0xd2, 0xec, 0x74, 0xfd, 0xca, 0xe1, 0xbb, 0xbe, 0x9e, 0x00, 0x3f, 0x48, - 0x83, 0x17, 0xd6, 0x6c, 0xa0, 0x64, 0xef, 0xde, 0x6b, 0x6c, 0x45, 0xf6, 0x67, 0x55, 0x52, 0x79, 0x0a, 0x35, 0xce, - 0xad, 0xaf, 0x53, 0x2d, 0xb4, 0xa8, 0x2a, 0xf6, 0x0d, 0xa9, 0xbe, 0xaf, 0x14, 0x76, 0x85, 0xf2, 0xbe, 0x1c, 0x3a, - 0x76, 0x5d, 0x37, 0xc8, 0xc9, 0x79, 0xb9, 0xb7, 0xca, 0x85, 0xbc, 0x7f, 0xdf, 0xf4, 0x99, 0xce, 0xf5, 0xf0, 0xcf, - 0x1c, 0x54, 0xce, 0xc5, 0x55, 0x4a, 0x16, 0xcc, 0x33, 0xa5, 0x8e, 0x96, 0x1c, 0xd0, 0x76, 0x0f, 0x3d, 0xed, 0xe8, - 0x22, 0x8a, 0xb9, 0xa5, 0x47, 0x11, 0x9e, 0x36, 0xca, 0x27, 0x69, 0x74, 0x00, 0x5e, 0x68, 0x42, 0x92, 0x13, 0x6e, - 0xda, 0xa2, 0xc5, 0x70, 0xc2, 0x30, 0x04, 0xae, 0xec, 0x09, 0x53, 0xf6, 0xdc, 0x43, 0xbc, 0xe5, 0xc0, 0xab, 0x61, - 0x2f, 0x9b, 0xdd, 0x6b, 0xe6, 0x3f, 0xac, 0x11, 0xc8, 0xb6, 0xa9, 0xaa, 0x2b, 0x1b, 0xef, 0x52, 0x44, 0x62, 0x84, - 0x6d, 0xd5, 0xd8, 0xd2, 0xd6, 0xef, 0x35, 0xdc, 0xeb, 0xca, 0x31, 0xaf, 0x29, 0xd5, 0x86, 0x1e, 0x56, 0x6e, 0x0e, - 0x37, 0x1d, 0x79, 0xb1, 0x82, 0x6e, 0x4f, 0x04, 0x85, 0xc0, 0x89, 0x50, 0xf6, 0xa0, 0xe6, 0x06, 0x22, 0x25, 0x53, - 0x5a, 0x35, 0x9b, 0x27, 0x23, 0x09, 0x2c, 0xb8, 0xb0, 0x4c, 0xf2, 0xd1, 0x45, 0x9c, 0x24, 0x55, 0xe9, 0xef, 0x2a, - 0xe0, 0xc5, 0xb0, 0xb7, 0x89, 0x76, 0x81, 0xd1, 0x5c, 0x81, 0xe0, 0x6a, 0x23, 0xec, 0xa3, 0xe3, 0x56, 0xeb, 0x2e, - 0x22, 0x8e, 0xcc, 0x8c, 0x46, 0x7c, 0x44, 0x1b, 0xb2, 0x64, 0x9a, 0xb5, 0xf7, 0x5e, 0x60, 0x48, 0xcd, 0xc0, 0x07, - 0xd5, 0x19, 0x15, 0xff, 0x2a, 0x7b, 0xea, 0x57, 0xa2, 0x77, 0xab, 0xea, 0x6a, 0x06, 0x54, 0x54, 0xe0, 0xc3, 0x0c, - 0xb1, 0xb4, 0x55, 0x20, 0x20, 0xd7, 0xc3, 0x3a, 0xdc, 0xad, 0x91, 0x06, 0x0b, 0x4a, 0x81, 0xb5, 0x56, 0x76, 0xaf, - 0x6f, 0x0b, 0xe6, 0x50, 0x28, 0x5c, 0xf4, 0x7f, 0x96, 0x4d, 0x67, 0x68, 0x99, 0x35, 0x98, 0x1a, 0x1a, 0x7c, 0x6c, - 0xd4, 0x97, 0x2b, 0xca, 0x6a, 0x7d, 0x68, 0x47, 0xd6, 0xf8, 0x49, 0x3b, 0xca, 0xe0, 0x50, 0xcd, 0x75, 0x51, 0xdd, - 0x6e, 0x6e, 0x8a, 0x98, 0x55, 0x3c, 0xee, 0x93, 0xde, 0xd6, 0xd6, 0xa4, 0xa7, 0x69, 0x40, 0x32, 0x49, 0x32, 0xbc, - 0xc9, 0x00, 0x65, 0x45, 0x9c, 0x45, 0xd9, 0x20, 0xdf, 0xa2, 0x2c, 0x71, 0xfd, 0x7e, 0xe8, 0xed, 0xd5, 0x3c, 0x6b, - 0x6f, 0x6f, 0xbd, 0x8b, 0x5c, 0xd5, 0x49, 0x0f, 0xf2, 0xf0, 0x08, 0x8a, 0x96, 0x6c, 0xca, 0x70, 0x31, 0xcd, 0x46, - 0x2c, 0xb0, 0xa1, 0x7b, 0x6a, 0x97, 0x72, 0xd3, 0x44, 0xc0, 0x3d, 0x11, 0x73, 0x16, 0x1f, 0xea, 0x91, 0xd4, 0x60, - 0x0f, 0x58, 0x40, 0x9b, 0x0b, 0x5f, 0x85, 0x67, 0x49, 0x76, 0x1a, 0x25, 0x07, 0x42, 0x81, 0xd7, 0x5a, 0x7e, 0x0b, - 0x2e, 0x23, 0x59, 0xac, 0x86, 0x92, 0xfa, 0x6a, 0xf0, 0x55, 0x70, 0x7b, 0x8f, 0xca, 0x5b, 0xb1, 0x3b, 0x7e, 0xdb, - 0xef, 0xd8, 0x2a, 0x22, 0xf6, 0x93, 0x39, 0x1d, 0x68, 0x9c, 0x02, 0x28, 0x73, 0x00, 0x9a, 0xac, 0xf0, 0x86, 0x2c, - 0xfc, 0x69, 0xf0, 0x93, 0x72, 0xa9, 0x33, 0x70, 0x21, 0xc0, 0xc9, 0x4f, 0x62, 0xde, 0xc2, 0xf3, 0x48, 0xdb, 0x5b, - 0x88, 0x0a, 0x8c, 0x2b, 0x52, 0x5c, 0xba, 0x54, 0xde, 0xa0, 0x77, 0x1c, 0x9e, 0x40, 0xb3, 0x8d, 0x8d, 0x85, 0xf3, - 0x26, 0xe2, 0x13, 0x3f, 0x8f, 0xd2, 0x51, 0x36, 0x75, 0xdc, 0x4d, 0xdb, 0x76, 0xfd, 0x82, 0x3c, 0x91, 0xcf, 0xdd, - 0x72, 0xe3, 0x04, 0xfc, 0x80, 0xd0, 0x1e, 0xd8, 0x9b, 0xc7, 0xde, 0x01, 0x0b, 0x4f, 0x76, 0x37, 0x16, 0x23, 0x56, - 0xf6, 0x4f, 0xbc, 0x4b, 0x1d, 0x73, 0xf7, 0xde, 0xa3, 0x94, 0x81, 0x5e, 0x61, 0xff, 0x52, 0x82, 0x01, 0xec, 0x46, - 0xf1, 0x77, 0x90, 0x72, 0x1f, 0xe9, 0x40, 0x44, 0xc6, 0x69, 0xaf, 0xaf, 0xed, 0x8c, 0x22, 0x06, 0xf6, 0x3d, 0xed, - 0xac, 0xde, 0xbf, 0x5f, 0xa9, 0xf9, 0xaa, 0xd4, 0x9b, 0xb3, 0xb0, 0xe6, 0xa9, 0x7b, 0x2f, 0xe9, 0x68, 0xa5, 0xbe, - 0x91, 0xe7, 0x8c, 0x94, 0xe6, 0xb2, 0x9d, 0xe0, 0x18, 0x5b, 0x7c, 0xf5, 0xb6, 0x3e, 0x14, 0x51, 0x0a, 0x3f, 0x06, - 0xeb, 0x25, 0x02, 0xf5, 0x0d, 0x0e, 0x8e, 0x77, 0x10, 0x6e, 0xed, 0x3a, 0x83, 0xc0, 0xb9, 0xd7, 0x6a, 0x5d, 0xff, - 0xb8, 0x75, 0xf8, 0xe7, 0xa8, 0xf5, 0xcb, 0x5e, 0xeb, 0x87, 0x23, 0xf7, 0xda, 0xf9, 0x71, 0x6b, 0x70, 0x28, 0xdf, - 0x0e, 0xff, 0xdc, 0xff, 0xb1, 0x38, 0xfa, 0x83, 0x28, 0xdc, 0x70, 0xdd, 0xad, 0x33, 0x6f, 0xc6, 0xc2, 0xad, 0x56, - 0xab, 0x0f, 0x4f, 0x67, 0xf0, 0x84, 0x7f, 0x2f, 0xe0, 0xcf, 0xf5, 0xa1, 0xf5, 0x9f, 0x7e, 0x4c, 0xff, 0xf3, 0x8f, - 0xf9, 0x11, 0x8e, 0x79, 0xf8, 0xe7, 0x1f, 0x0b, 0xfb, 0x41, 0x3f, 0xdc, 0x3a, 0xda, 0x74, 0x1d, 0x5d, 0xf3, 0x87, - 0xb0, 0x7a, 0x84, 0x56, 0x87, 0x7f, 0x96, 0x6f, 0xf6, 0x83, 0x93, 0xdd, 0x7e, 0x78, 0x74, 0xed, 0xd8, 0xd7, 0x0f, - 0xdc, 0x6b, 0xd7, 0xbd, 0xde, 0xc0, 0x79, 0xce, 0x61, 0xf4, 0x07, 0xf0, 0x77, 0x0c, 0x7f, 0x6d, 0xf8, 0x3b, 0x85, - 0xbf, 0x7f, 0x86, 0x6e, 0x22, 0xfe, 0x76, 0x4d, 0xb1, 0x90, 0x6b, 0x3c, 0xb0, 0x88, 0x60, 0x15, 0xdc, 0x8d, 0xad, - 0xd8, 0xdb, 0x20, 0xa2, 0xc1, 0x3e, 0xf4, 0x7d, 0x1f, 0xc3, 0xa4, 0xce, 0xe2, 0x78, 0x03, 0x16, 0x1d, 0x39, 0x67, - 0x23, 0xe0, 0x9e, 0x88, 0x1c, 0x14, 0x01, 0x13, 0x67, 0xab, 0x05, 0x1e, 0xae, 0x7a, 0xc3, 0x70, 0x83, 0x39, 0x60, - 0x14, 0xbc, 0x65, 0xf8, 0xd0, 0x75, 0xbd, 0x17, 0xf2, 0xcc, 0x10, 0xf7, 0xb9, 0x60, 0xad, 0x34, 0x13, 0x26, 0x8d, - 0xed, 0x7a, 0xb3, 0x15, 0x95, 0xb0, 0xad, 0xd3, 0x33, 0xa8, 0x3b, 0x15, 0x27, 0x8c, 0xdf, 0xb1, 0xe8, 0x13, 0x6e, - 0xc9, 0x37, 0xc6, 0x21, 0xf0, 0x92, 0x25, 0xdf, 0x34, 0x1a, 0x0d, 0x1b, 0x51, 0xb8, 0x63, 0x4f, 0x19, 0xcc, 0xb0, - 0x64, 0x22, 0x32, 0x52, 0x9a, 0xc2, 0xb2, 0x85, 0xc9, 0xdf, 0x47, 0x39, 0xdf, 0xa8, 0x0c, 0xdb, 0xb0, 0x66, 0xc9, - 0x36, 0x2d, 0xfd, 0x3b, 0x4c, 0x81, 0xa6, 0x25, 0x9d, 0x7f, 0x98, 0xe3, 0x87, 0x29, 0xa1, 0xf5, 0xd6, 0x61, 0xe0, - 0xa1, 0x17, 0x20, 0x77, 0x44, 0x3f, 0xe7, 0x3d, 0xaa, 0x31, 0xf8, 0x9f, 0x0c, 0x33, 0x78, 0x62, 0x3e, 0x0c, 0xd1, - 0x2c, 0x4a, 0x1d, 0xdc, 0x4a, 0x51, 0xdc, 0xbf, 0xc2, 0x9d, 0x91, 0x96, 0xde, 0x7e, 0xa8, 0x76, 0xcc, 0x41, 0xce, - 0xd8, 0x77, 0x51, 0xf2, 0x89, 0xe5, 0xce, 0xa5, 0xd7, 0xe9, 0x7e, 0x4e, 0x9d, 0x3d, 0xb4, 0xcd, 0x3e, 0x54, 0xc7, - 0x68, 0xda, 0x2c, 0x90, 0x47, 0x84, 0xad, 0x8e, 0x97, 0x63, 0x54, 0x0b, 0x49, 0x50, 0x78, 0x59, 0xd8, 0x25, 0x0e, - 0xb7, 0x77, 0x8b, 0xf3, 0xb3, 0xbe, 0x1d, 0xd8, 0x36, 0x58, 0xfc, 0x07, 0x14, 0xb6, 0x12, 0x86, 0x45, 0xbb, 0xc7, - 0x76, 0xe3, 0x1e, 0xdb, 0xdc, 0xac, 0x02, 0x4e, 0x78, 0x90, 0x4e, 0xdd, 0x13, 0x2f, 0xf2, 0x26, 0x21, 0x0c, 0x38, - 0x84, 0x66, 0xd8, 0xa5, 0x37, 0xdc, 0x8d, 0xe5, 0x34, 0x18, 0x0b, 0xf1, 0x93, 0xa8, 0xe0, 0xaf, 0x30, 0x1e, 0x11, - 0x0e, 0xd1, 0xd8, 0xf7, 0xd9, 0x25, 0x1b, 0x2a, 0x3b, 0x03, 0x08, 0x15, 0xb9, 0x3d, 0x77, 0x18, 0x1a, 0xcd, 0x60, - 0xee, 0x30, 0x3c, 0x18, 0xd8, 0xb0, 0x97, 0x60, 0x57, 0x86, 0xd1, 0x61, 0xe7, 0x68, 0x90, 0x86, 0x33, 0x16, 0x68, - 0xda, 0xca, 0xa2, 0xb3, 0x5a, 0x51, 0xf7, 0x68, 0xe0, 0x4c, 0x99, 0xcf, 0xc1, 0x16, 0x77, 0xf0, 0x0d, 0x23, 0x14, - 0x45, 0xf8, 0x81, 0x9d, 0xbd, 0xb8, 0x9c, 0x39, 0xf6, 0xee, 0x96, 0xbd, 0x89, 0xa5, 0x9e, 0x0d, 0xec, 0x05, 0x73, - 0x87, 0x17, 0xae, 0xd9, 0x79, 0xfb, 0x08, 0x41, 0xc5, 0x42, 0x9c, 0xfc, 0x62, 0x60, 0xf7, 0xc5, 0xd4, 0x6d, 0x18, - 0x34, 0x95, 0xcb, 0x8f, 0x2b, 0x7a, 0x40, 0xa8, 0xaa, 0xae, 0x0a, 0x3a, 0x28, 0xeb, 0x06, 0xce, 0xc4, 0x44, 0xa2, - 0x85, 0x93, 0x49, 0x2a, 0x80, 0xc3, 0x83, 0xcd, 0x60, 0x52, 0xa3, 0xdb, 0xf6, 0xd1, 0xe0, 0x22, 0x78, 0x60, 0x3f, - 0x50, 0x2f, 0x63, 0x40, 0x86, 0x89, 0xe9, 0xc7, 0xa0, 0x45, 0xf0, 0xef, 0x39, 0x03, 0x24, 0x2f, 0xa8, 0x68, 0x26, - 0x8b, 0xce, 0xb0, 0xe8, 0x20, 0x40, 0x50, 0xbd, 0x42, 0x5b, 0x7f, 0x62, 0x4d, 0x46, 0x21, 0xc1, 0x0e, 0xb6, 0xd0, - 0x21, 0xdb, 0xec, 0x1c, 0xe1, 0x79, 0x43, 0xce, 0x8b, 0xef, 0x62, 0x0e, 0x2a, 0x61, 0xab, 0x6f, 0xbb, 0x03, 0xdb, - 0xc2, 0xa5, 0xed, 0x65, 0x9b, 0xa1, 0xa0, 0x70, 0xbc, 0x79, 0xc0, 0x82, 0x49, 0x3f, 0x6c, 0x0f, 0x9c, 0x5c, 0x86, - 0x1b, 0xf1, 0xdc, 0x52, 0x48, 0xf0, 0xb6, 0x37, 0x01, 0x81, 0x8e, 0x9c, 0xbb, 0x61, 0x6f, 0xaa, 0x42, 0x28, 0x3a, - 0xde, 0x1c, 0xb9, 0x41, 0x0c, 0x7f, 0x9c, 0x16, 0x32, 0xcd, 0x44, 0xf7, 0x55, 0x9a, 0x19, 0x90, 0x18, 0x29, 0x8b, - 0x3c, 0x09, 0xb3, 0x4d, 0x07, 0x23, 0xb4, 0x20, 0x69, 0x77, 0x07, 0x00, 0xc3, 0xa6, 0xa3, 0x38, 0x6d, 0x4b, 0xb1, - 0x9a, 0xb2, 0xcf, 0x0f, 0xf5, 0x72, 0x0c, 0xd9, 0x60, 0xc8, 0xfc, 0x4a, 0xfb, 0x00, 0x58, 0x41, 0xe2, 0xe5, 0x47, - 0xea, 0xcc, 0xeb, 0x65, 0xed, 0x7c, 0x6b, 0xa1, 0x44, 0x11, 0xf7, 0x0c, 0x09, 0xc5, 0x4a, 0xed, 0x86, 0x09, 0x73, - 0x7b, 0x86, 0xc4, 0xd0, 0x2c, 0x1f, 0xb6, 0x81, 0xe9, 0x55, 0x80, 0x3d, 0x35, 0xb7, 0x45, 0x12, 0x56, 0xcd, 0xbd, - 0x43, 0x60, 0xed, 0x23, 0xe0, 0x21, 0xda, 0x46, 0x3d, 0x15, 0xcd, 0x67, 0x49, 0xf8, 0xb2, 0x71, 0x5c, 0x1c, 0xe1, - 0x89, 0xd0, 0xbe, 0x3f, 0x9c, 0xe7, 0x20, 0x0f, 0xf8, 0x5b, 0xb0, 0x0c, 0x42, 0xd9, 0x14, 0x1d, 0x3d, 0x3c, 0x02, - 0xf6, 0x08, 0xf1, 0x46, 0xd8, 0xdc, 0xa8, 0x46, 0x8b, 0x92, 0x8c, 0x17, 0x3a, 0x18, 0xee, 0x31, 0xe9, 0xda, 0xa3, - 0x60, 0x90, 0x27, 0xc6, 0x0e, 0x9e, 0xf9, 0xfb, 0x43, 0xac, 0xc6, 0x09, 0x0a, 0xb7, 0xa4, 0xdd, 0x56, 0x89, 0xbf, - 0x7d, 0x3f, 0x05, 0x09, 0x8e, 0x75, 0xe0, 0x67, 0xdd, 0xbf, 0x9f, 0x48, 0xa4, 0x76, 0xd3, 0x1e, 0x9d, 0x44, 0x60, - 0x3c, 0x38, 0xf7, 0x53, 0xa8, 0x46, 0x12, 0x51, 0x51, 0x8e, 0x16, 0xa8, 0x79, 0xaa, 0x56, 0xc1, 0x77, 0x68, 0x46, - 0xe0, 0x19, 0x86, 0xad, 0xc9, 0x4f, 0xd5, 0x8d, 0x45, 0x2c, 0xdf, 0x75, 0xe9, 0x68, 0x0b, 0x0f, 0x20, 0x05, 0xa3, - 0x09, 0x86, 0x71, 0x29, 0x28, 0x59, 0xf1, 0xdf, 0xb1, 0x11, 0x2b, 0x9f, 0x1c, 0x66, 0x9b, 0x9b, 0x47, 0xe2, 0xdc, - 0x82, 0x18, 0x87, 0x19, 0xd1, 0xd5, 0xb8, 0x02, 0xa0, 0x3e, 0x9d, 0x13, 0xd7, 0x03, 0xd3, 0x8a, 0x35, 0x5d, 0x8a, - 0x7d, 0x72, 0x98, 0x01, 0x28, 0xb8, 0xe5, 0x1c, 0xfa, 0x83, 0x3f, 0x1e, 0x81, 0x7b, 0xec, 0xff, 0xc1, 0xdd, 0x52, - 0x82, 0xa6, 0x27, 0xcf, 0x14, 0x17, 0x74, 0xc6, 0xda, 0xf1, 0x28, 0x36, 0x1a, 0x14, 0x5e, 0x0a, 0x18, 0x80, 0x36, - 0x07, 0x99, 0x50, 0x71, 0x10, 0x72, 0x54, 0x60, 0xfb, 0xb8, 0xf9, 0x19, 0xee, 0xec, 0xe7, 0x60, 0xe1, 0x0d, 0xf4, - 0xdb, 0x6b, 0x78, 0xfb, 0xa3, 0x7e, 0xfb, 0x89, 0x05, 0xbf, 0x94, 0x32, 0x74, 0x5f, 0x9b, 0xe2, 0x91, 0x9a, 0xa2, - 0x14, 0x4b, 0x64, 0xd0, 0x90, 0xbb, 0xf9, 0x52, 0xcc, 0x86, 0xb9, 0x25, 0x10, 0x43, 0x89, 0xae, 0xdc, 0xe7, 0xd1, - 0x19, 0x12, 0xd7, 0x35, 0x49, 0x61, 0xe4, 0x12, 0x98, 0x08, 0x57, 0x7c, 0x8b, 0xf4, 0x64, 0xfd, 0x36, 0xd8, 0xe0, - 0xb5, 0xbc, 0x03, 0xb4, 0xef, 0xd8, 0x74, 0xc6, 0xaf, 0xf6, 0x49, 0xd1, 0x07, 0x32, 0x6d, 0x40, 0x9c, 0x9d, 0xb7, - 0x7b, 0xf1, 0x2e, 0xeb, 0xc5, 0x20, 0xd5, 0x73, 0xc5, 0x62, 0xb8, 0x57, 0xbd, 0xf7, 0x18, 0xa5, 0x34, 0x99, 0xc9, - 0xab, 0xa1, 0xd7, 0x95, 0xe8, 0x6d, 0x6e, 0x02, 0x82, 0x3d, 0xa3, 0x2b, 0x13, 0x5d, 0xcb, 0x52, 0xd0, 0x04, 0x20, - 0x7a, 0x52, 0x67, 0x39, 0xe2, 0x38, 0xcc, 0x66, 0x83, 0xe2, 0x11, 0x73, 0x57, 0x8e, 0x8a, 0x63, 0x62, 0x77, 0x99, - 0xb0, 0x03, 0x98, 0x11, 0x97, 0xb7, 0x3a, 0x22, 0x3a, 0x2c, 0xfa, 0xeb, 0xf8, 0xf6, 0xb1, 0xc7, 0x37, 0x3b, 0x2e, - 0x68, 0x90, 0xda, 0x58, 0x8f, 0xab, 0xb1, 0xa0, 0x3e, 0x3c, 0xd6, 0x54, 0x2a, 0x8b, 0xcd, 0xcd, 0xb2, 0x7e, 0x54, - 0xab, 0x76, 0x70, 0xed, 0x34, 0xe5, 0xb2, 0x99, 0x0d, 0xc2, 0x81, 0x88, 0x09, 0x14, 0x68, 0x69, 0x65, 0xc5, 0x00, - 0x43, 0xca, 0x72, 0x94, 0x4f, 0x21, 0xf7, 0xe2, 0xb2, 0xd4, 0xa9, 0x2f, 0xcf, 0x64, 0xd0, 0x11, 0x4f, 0x3d, 0xc9, - 0x58, 0x01, 0x05, 0xeb, 0xa5, 0x5e, 0x42, 0x4b, 0x04, 0x98, 0xbf, 0x50, 0x39, 0x34, 0xc2, 0x02, 0x89, 0x42, 0xc3, - 0x2c, 0x51, 0xc6, 0x67, 0x11, 0xc6, 0xa0, 0xed, 0x9f, 0xd5, 0x62, 0x5f, 0x85, 0x32, 0x3a, 0x8a, 0xc3, 0xfc, 0x28, - 0xa0, 0xfa, 0xb9, 0x94, 0x60, 0x93, 0xf0, 0x23, 0xb0, 0x51, 0xe5, 0x78, 0x92, 0x20, 0x7c, 0x1e, 0xe7, 0x8c, 0x3c, - 0x85, 0x0d, 0x09, 0xb3, 0x34, 0x6d, 0x23, 0xd5, 0x2e, 0x32, 0x83, 0x50, 0x2e, 0xcc, 0x3f, 0x31, 0xce, 0x2e, 0xb2, - 0x70, 0xa9, 0x35, 0x98, 0x1f, 0xef, 0x4c, 0x80, 0xb2, 0xeb, 0xeb, 0x4c, 0xf8, 0xb8, 0x11, 0xd9, 0x1b, 0xba, 0x62, - 0x32, 0x50, 0x48, 0x05, 0x4e, 0x44, 0x16, 0x0f, 0x9d, 0xa1, 0xd0, 0x08, 0x07, 0x74, 0x8a, 0x9c, 0xbb, 0xc6, 0xa6, - 0xcf, 0x07, 0xda, 0x37, 0x4a, 0x43, 0x27, 0x01, 0x21, 0x20, 0x70, 0x37, 0xac, 0xa9, 0x74, 0x90, 0x06, 0x09, 0x95, - 0xa2, 0x9f, 0x03, 0xf8, 0x87, 0x91, 0xa4, 0x00, 0xd8, 0x0f, 0xd5, 0x48, 0x11, 0x65, 0x59, 0xe0, 0x02, 0xd0, 0x5c, - 0xfb, 0xb8, 0x12, 0xbe, 0x30, 0x50, 0x61, 0x7a, 0x9a, 0x95, 0x95, 0x42, 0x89, 0x3c, 0x5d, 0x91, 0xb2, 0x46, 0x32, - 0xf9, 0x1c, 0x1d, 0x3e, 0xe5, 0x5d, 0xbf, 0x95, 0x78, 0xe8, 0x82, 0xe7, 0xb0, 0xac, 0xea, 0xf9, 0x4d, 0xc8, 0xc8, - 0xb9, 0x06, 0x5d, 0x21, 0x85, 0xfe, 0x92, 0x93, 0xbc, 0xf7, 0xc6, 0xaf, 0x6a, 0xa9, 0x31, 0x94, 0x7d, 0x5c, 0xd5, - 0x0c, 0xcb, 0xcb, 0x59, 0x15, 0xa6, 0x20, 0xe0, 0x16, 0x2c, 0x09, 0x16, 0x52, 0x43, 0x80, 0x85, 0xed, 0x91, 0x56, - 0x0a, 0xf2, 0x52, 0x87, 0x77, 0x9e, 0x83, 0x15, 0x60, 0x1c, 0x6a, 0xa9, 0x64, 0x1a, 0x49, 0x7c, 0x99, 0xd4, 0x04, - 0x4c, 0xb9, 0x3f, 0x04, 0x3f, 0xb5, 0x79, 0xd2, 0x75, 0xe9, 0xfa, 0xf1, 0x14, 0x53, 0x7b, 0x08, 0xf4, 0xd8, 0xbb, - 0x07, 0xa6, 0x44, 0x5d, 0x87, 0x15, 0xc4, 0xa1, 0x59, 0x4d, 0xb3, 0x80, 0x19, 0xd3, 0x06, 0x2d, 0xd9, 0x06, 0x5b, - 0x2e, 0x07, 0xfb, 0x48, 0x6c, 0xcf, 0x6a, 0x05, 0x84, 0xae, 0x41, 0x03, 0x43, 0xee, 0x52, 0xa1, 0x85, 0x59, 0xaf, - 0x4b, 0x45, 0xb8, 0x3f, 0x07, 0x4c, 0x5a, 0xc1, 0x99, 0x97, 0xd1, 0xc0, 0xfb, 0xf1, 0x69, 0x82, 0x89, 0x2f, 0x88, - 0x15, 0xd8, 0xc1, 0x41, 0xa7, 0xd9, 0x14, 0x38, 0x15, 0x17, 0x29, 0x83, 0x65, 0x45, 0xa9, 0x0d, 0x7f, 0xa4, 0xc8, - 0xd6, 0x5d, 0x1e, 0xe9, 0x2e, 0xc4, 0x02, 0xd8, 0xe9, 0x17, 0x8c, 0x7c, 0xcb, 0x7a, 0x19, 0x30, 0x38, 0xd7, 0x1a, - 0x07, 0x81, 0xdf, 0xdc, 0x4c, 0x8e, 0xca, 0x94, 0xd8, 0xae, 0xc9, 0xea, 0x02, 0x72, 0x4c, 0x02, 0x6c, 0xe0, 0x0e, - 0xc2, 0x52, 0xd9, 0xe3, 0x45, 0x39, 0xc5, 0xe5, 0x52, 0x16, 0x72, 0x33, 0x1d, 0x8b, 0xe6, 0x73, 0x2b, 0xcd, 0xa6, - 0xe3, 0xad, 0xf8, 0xa2, 0xe0, 0x1f, 0x38, 0xb1, 0xb4, 0xea, 0x29, 0xb5, 0xc2, 0xa3, 0xcc, 0x2d, 0x59, 0xa7, 0xa4, - 0x56, 0xd7, 0x0d, 0x54, 0x23, 0x3c, 0x4d, 0xc3, 0x46, 0x20, 0xc4, 0x04, 0x17, 0xbf, 0x6d, 0x32, 0x31, 0xed, 0x2d, - 0x21, 0x75, 0x84, 0xdd, 0x43, 0x39, 0xc1, 0x5d, 0xcd, 0xb3, 0x2f, 0xc3, 0xd9, 0x7a, 0xe6, 0xde, 0x33, 0x98, 0xfb, - 0x69, 0xc8, 0x0c, 0x46, 0x8f, 0x65, 0xc2, 0x8f, 0x8c, 0x7d, 0xe4, 0xaa, 0xea, 0xd9, 0x59, 0x58, 0x89, 0x2c, 0xf1, - 0x64, 0x1c, 0x75, 0x18, 0xa7, 0xa2, 0x35, 0x41, 0x76, 0x7d, 0x5d, 0x98, 0x7b, 0x81, 0x82, 0xa6, 0x1e, 0xab, 0xc7, - 0x69, 0x2b, 0x76, 0x36, 0x22, 0x91, 0x7b, 0x6f, 0x6a, 0x91, 0xc8, 0x8a, 0xcf, 0x71, 0xa4, 0x35, 0x07, 0xb9, 0xcf, - 0xce, 0x96, 0x37, 0xa9, 0xd0, 0x2d, 0x1a, 0x6d, 0x63, 0x8f, 0xea, 0x03, 0x49, 0x3d, 0xa3, 0x02, 0xab, 0x1a, 0xfb, - 0xfe, 0xfd, 0x8e, 0x48, 0xb7, 0x54, 0x8a, 0x0d, 0x43, 0x5a, 0x21, 0x33, 0x46, 0xc1, 0xa0, 0xa4, 0xc8, 0x40, 0x8d, - 0xf2, 0x35, 0x82, 0x61, 0x8f, 0x1a, 0x80, 0xe2, 0x5c, 0x5d, 0xfd, 0xb4, 0x94, 0x6c, 0x21, 0x20, 0x01, 0xd9, 0x84, - 0x62, 0x8d, 0x98, 0x19, 0xf9, 0xe4, 0x23, 0x70, 0xde, 0x80, 0xa3, 0x63, 0x00, 0x7e, 0x81, 0xd8, 0xf4, 0x60, 0x62, - 0xdb, 0x44, 0x14, 0x7d, 0x36, 0xf0, 0x12, 0x80, 0x9d, 0x55, 0xa1, 0xd1, 0x0f, 0x55, 0x0a, 0x18, 0xb2, 0x81, 0x1b, - 0xf0, 0x2a, 0x2c, 0xb7, 0xf7, 0x12, 0xda, 0xc1, 0xeb, 0x0b, 0xd9, 0x7c, 0x03, 0xf3, 0x04, 0xab, 0xd8, 0x9d, 0x5f, - 0x59, 0xd6, 0xe2, 0xdc, 0xe9, 0xa0, 0x51, 0xaf, 0x28, 0x21, 0x6a, 0xf7, 0xb1, 0xf6, 0x25, 0x23, 0x18, 0xf1, 0xfd, - 0x0d, 0x65, 0x1d, 0xaa, 0x71, 0xcb, 0x3d, 0x8d, 0x16, 0x61, 0xba, 0x4c, 0x1a, 0x83, 0x92, 0x75, 0x3f, 0x19, 0x71, - 0x2f, 0xf7, 0x45, 0x2c, 0xb8, 0xc2, 0xd1, 0x08, 0x9b, 0x37, 0x90, 0xa4, 0xa7, 0x3d, 0x3a, 0x60, 0xdf, 0x68, 0xf6, - 0x02, 0xca, 0x7c, 0xac, 0x48, 0x25, 0x21, 0xa5, 0xd9, 0x0d, 0x91, 0x24, 0xac, 0x15, 0x79, 0xea, 0xbc, 0xef, 0x68, - 0x9f, 0x5b, 0x49, 0x04, 0x23, 0x38, 0x89, 0xd3, 0x95, 0x07, 0x4d, 0x01, 0xae, 0xa2, 0x23, 0xa6, 0x6f, 0x82, 0xf2, - 0x1b, 0xe4, 0xf6, 0x52, 0x72, 0x6d, 0xae, 0x61, 0x78, 0x86, 0x04, 0xab, 0x22, 0x11, 0x78, 0x44, 0x0d, 0x38, 0xe6, - 0xab, 0x3c, 0x0f, 0x30, 0xe1, 0x6b, 0x7b, 0x13, 0x00, 0xca, 0xc9, 0x55, 0x71, 0x96, 0x02, 0xdd, 0x80, 0xe5, 0xea, - 0x38, 0x35, 0x2a, 0x12, 0x17, 0x37, 0xa6, 0xab, 0x5b, 0xfa, 0x53, 0xb4, 0x9c, 0xc9, 0x10, 0xd3, 0x41, 0x10, 0x90, - 0xa9, 0x4f, 0x99, 0x23, 0x64, 0xae, 0xb0, 0x3e, 0x67, 0x4e, 0x6d, 0xea, 0x1e, 0xa7, 0x6e, 0x9e, 0xa4, 0x16, 0xab, - 0xd3, 0xa6, 0x94, 0x88, 0x49, 0x89, 0x79, 0x2a, 0x53, 0xb1, 0x95, 0xb8, 0x73, 0xeb, 0x1b, 0x2d, 0xa4, 0x8d, 0x76, - 0x2a, 0x73, 0xb0, 0xb5, 0xbc, 0x17, 0xa2, 0xfd, 0x25, 0x11, 0x9e, 0x95, 0xc8, 0x58, 0x8b, 0x39, 0x73, 0x4c, 0x04, - 0xab, 0x17, 0x53, 0x91, 0x7f, 0x70, 0x74, 0x9a, 0xbd, 0x41, 0x0f, 0x52, 0x6f, 0x20, 0x31, 0x6b, 0xe2, 0xbb, 0x90, - 0x86, 0x3a, 0x42, 0xa0, 0x32, 0xaa, 0x65, 0x3a, 0x4e, 0x2c, 0x15, 0x97, 0xe4, 0xab, 0xf7, 0xfa, 0x38, 0xdf, 0x78, - 0x6e, 0xac, 0x46, 0x10, 0x83, 0xb7, 0x90, 0x1f, 0x79, 0x52, 0x84, 0x03, 0xe1, 0xf2, 0xcd, 0xcd, 0x5e, 0xbe, 0xcb, - 0xaa, 0x10, 0x49, 0x05, 0x63, 0x8c, 0x19, 0xc5, 0xb8, 0x27, 0x6a, 0x6a, 0x31, 0x07, 0x54, 0x65, 0xeb, 0x30, 0xc7, - 0x03, 0x00, 0x68, 0x69, 0x4a, 0x2f, 0xb3, 0xad, 0x3a, 0xcf, 0x25, 0x7c, 0x8c, 0x3c, 0x14, 0xd9, 0xf8, 0xfd, 0x9a, - 0x0c, 0x14, 0x84, 0xfb, 0x5e, 0xc7, 0xc3, 0xc4, 0x38, 0x58, 0x45, 0x21, 0x0b, 0xf4, 0x06, 0xed, 0x55, 0x89, 0x50, - 0xdc, 0x9c, 0xac, 0xc7, 0x0d, 0x27, 0x15, 0x6c, 0xa1, 0x12, 0x96, 0x4a, 0x0b, 0xfc, 0x6a, 0x23, 0x34, 0x4f, 0x19, - 0xf7, 0xde, 0x54, 0x38, 0x83, 0xfe, 0xe0, 0xde, 0x32, 0xa3, 0xbe, 0x5f, 0x3a, 0x91, 0xa9, 0xc0, 0xc4, 0xcd, 0x2c, - 0xb5, 0xdf, 0x2f, 0xab, 0xb4, 0x9f, 0x57, 0xc8, 0x7d, 0x4e, 0x9a, 0xaf, 0x73, 0x07, 0xcd, 0x27, 0xc3, 0xfd, 0x4a, - 0xf9, 0xa1, 0x85, 0x51, 0x53, 0x7e, 0x79, 0x5d, 0xf9, 0x15, 0x9e, 0x0a, 0x6f, 0xf5, 0xbb, 0x28, 0x74, 0x51, 0x9f, - 0x83, 0x21, 0xa4, 0x1f, 0xc1, 0x35, 0x34, 0x78, 0x50, 0x24, 0x8b, 0xc5, 0xda, 0x05, 0x71, 0x7d, 0xcc, 0xa9, 0x76, - 0x28, 0x63, 0x8c, 0x78, 0x5a, 0x72, 0x90, 0x64, 0x70, 0x30, 0x7e, 0x03, 0x03, 0x62, 0x52, 0x12, 0xd2, 0x21, 0x74, - 0x56, 0x66, 0x22, 0x2a, 0x77, 0xf1, 0x76, 0xe3, 0xb2, 0xa6, 0x50, 0x84, 0x9d, 0x60, 0xa6, 0x52, 0x2a, 0x08, 0xa4, - 0xc9, 0x77, 0xaf, 0x53, 0x0b, 0x86, 0x82, 0x68, 0x30, 0x14, 0x90, 0xd7, 0x76, 0x3d, 0x68, 0xf2, 0x51, 0x1c, 0x3c, - 0xaf, 0x50, 0x23, 0x5e, 0x66, 0xf0, 0x35, 0x6c, 0xfe, 0x9a, 0x28, 0xc9, 0x43, 0x2e, 0x62, 0xaf, 0xe0, 0x13, 0x21, - 0x9b, 0xf2, 0xb0, 0x00, 0xfa, 0xa1, 0x5d, 0xd9, 0x4b, 0x77, 0x8b, 0xca, 0xa5, 0x45, 0x63, 0x2b, 0x51, 0xb3, 0xe6, - 0x87, 0xf1, 0x66, 0x7a, 0x04, 0x53, 0x53, 0x02, 0x01, 0x69, 0x2a, 0x27, 0xa9, 0xe6, 0x3d, 0x4c, 0x8f, 0x00, 0x24, - 0xd8, 0xfd, 0x04, 0x16, 0xfa, 0x4d, 0x89, 0x09, 0x16, 0x55, 0x63, 0xb7, 0x19, 0x68, 0xcd, 0x19, 0x69, 0xbe, 0x19, - 0x42, 0xb8, 0xa9, 0xac, 0x67, 0xcc, 0x0e, 0xb0, 0x6d, 0x77, 0xb3, 0x38, 0x4c, 0x37, 0x3b, 0x47, 0x86, 0xe0, 0xc2, - 0xe3, 0xff, 0xa4, 0xc4, 0x34, 0x90, 0x5c, 0xea, 0xc6, 0x4f, 0xa8, 0xc3, 0x3e, 0x91, 0x3a, 0x11, 0x03, 0x9a, 0xab, - 0xd1, 0x74, 0xee, 0x35, 0x47, 0xc9, 0x65, 0x55, 0xed, 0x6a, 0x09, 0x1a, 0xba, 0x91, 0x8c, 0x89, 0x62, 0x9e, 0x13, - 0x00, 0xa3, 0xd8, 0xfc, 0x39, 0xd3, 0x49, 0xde, 0xbf, 0xac, 0x4c, 0xed, 0xf6, 0x7d, 0x3f, 0xca, 0xcf, 0xe8, 0x48, - 0x45, 0x65, 0x73, 0x12, 0xf3, 0x6f, 0x4b, 0x30, 0x8d, 0x89, 0x0f, 0xf5, 0x5c, 0x47, 0xa1, 0x00, 0x5f, 0xd9, 0x50, - 0x6a, 0xb6, 0xd7, 0xbf, 0x75, 0xb6, 0x87, 0x72, 0x36, 0xc1, 0x02, 0x0d, 0xba, 0xac, 0xc1, 0x17, 0xb0, 0x0c, 0xee, - 0x48, 0x3f, 0x05, 0xdf, 0x4f, 0xeb, 0xe0, 0x33, 0xf6, 0xbf, 0x00, 0xb4, 0x2a, 0x30, 0xa0, 0xdc, 0x69, 0x1a, 0x56, - 0x42, 0x5c, 0xa2, 0xc2, 0xac, 0xe2, 0xfc, 0x71, 0x9d, 0xd7, 0x4d, 0xcb, 0x12, 0x83, 0xf2, 0x33, 0xd7, 0x70, 0xe3, - 0x7b, 0x8d, 0xfc, 0xf1, 0xbd, 0x97, 0xa0, 0xdb, 0x89, 0xb4, 0xf7, 0xef, 0xe7, 0xf7, 0xc8, 0x42, 0x03, 0x3f, 0x2c, - 0x9a, 0x41, 0x5b, 0xbc, 0x08, 0x90, 0xab, 0x67, 0x2c, 0xc6, 0xdb, 0x22, 0x54, 0x86, 0x0f, 0x58, 0x30, 0x03, 0x0c, - 0xc1, 0x63, 0xa7, 0x32, 0xf9, 0x0c, 0x1b, 0x4d, 0xb1, 0x6b, 0x2e, 0x0c, 0x3e, 0x50, 0x95, 0x85, 0xe4, 0xc5, 0x3a, - 0xd9, 0x5e, 0x9c, 0xc3, 0xf3, 0xeb, 0xb8, 0x00, 0xea, 0x20, 0xfa, 0x9a, 0xca, 0x62, 0x03, 0xb9, 0xb8, 0x29, 0x6b, - 0xbd, 0xa2, 0xd1, 0xe8, 0xc6, 0x2e, 0xbc, 0xae, 0xc0, 0x27, 0x51, 0x3a, 0x4a, 0xc4, 0x24, 0x66, 0x52, 0xe5, 0x8a, - 0x5c, 0x1b, 0xdd, 0x4b, 0x5b, 0x34, 0x2f, 0x85, 0x04, 0xaf, 0x08, 0xdc, 0x10, 0xfa, 0x4a, 0x5f, 0xae, 0x36, 0x50, - 0xf0, 0xa8, 0xbd, 0xb9, 0x08, 0x26, 0x26, 0x1e, 0x37, 0xa4, 0xa6, 0x5f, 0x87, 0x53, 0x2b, 0x8b, 0x25, 0x87, 0x5f, - 0xe7, 0x8c, 0x35, 0x14, 0x00, 0xf1, 0xc9, 0xa3, 0xf5, 0x6e, 0xd2, 0x1b, 0xa5, 0x1d, 0x94, 0x46, 0x88, 0xef, 0x2a, - 0x7c, 0xdd, 0x85, 0xe2, 0x2b, 0x57, 0xdd, 0xfb, 0x3a, 0x66, 0xc6, 0x05, 0xa3, 0x97, 0x7c, 0x9a, 0x34, 0xae, 0xdd, - 0xd0, 0x5d, 0x9d, 0xef, 0xbd, 0x2f, 0x65, 0xde, 0xc2, 0x31, 0xb0, 0xc9, 0x31, 0x73, 0x5e, 0x7a, 0x6f, 0x8d, 0x13, - 0xe5, 0x1f, 0xcc, 0x23, 0x5e, 0x39, 0xcc, 0xaa, 0x93, 0xe4, 0x1f, 0x06, 0x3f, 0x04, 0xeb, 0x5b, 0x1a, 0x27, 0xc8, - 0x5d, 0x75, 0x82, 0x4c, 0x94, 0xdb, 0xd0, 0x1b, 0x6e, 0xef, 0xae, 0x02, 0x41, 0x9c, 0x8a, 0xe9, 0xa3, 0x72, 0x5c, - 0x3f, 0x5a, 0xa0, 0x52, 0x11, 0xf1, 0xb9, 0xca, 0x5d, 0x59, 0x9b, 0x1a, 0xea, 0x31, 0x9d, 0xcc, 0x42, 0xd3, 0xac, - 0xc8, 0xa5, 0x6c, 0x7a, 0x8c, 0x5c, 0xb3, 0x53, 0x6d, 0x7e, 0x77, 0xed, 0x21, 0x1d, 0xc7, 0xfb, 0x9e, 0xb5, 0x5a, - 0x70, 0xbf, 0xab, 0x28, 0xbc, 0xeb, 0xc5, 0x46, 0x2a, 0x43, 0xcd, 0x7a, 0x14, 0x7d, 0x1c, 0xb7, 0x99, 0xcb, 0xa3, - 0xec, 0xcf, 0x1a, 0x00, 0xa6, 0x23, 0x2c, 0xba, 0x9b, 0x9e, 0xb1, 0x27, 0xd0, 0xd3, 0x13, 0x19, 0x24, 0x7a, 0xa3, - 0xf3, 0x55, 0xab, 0xc4, 0xd2, 0x15, 0x04, 0x76, 0x6f, 0xc8, 0x58, 0x95, 0xb4, 0x5b, 0xae, 0x5f, 0xce, 0xf3, 0x79, - 0xce, 0x97, 0xf2, 0x7c, 0x6a, 0x16, 0xdd, 0xbd, 0xb6, 0x7b, 0x73, 0x6a, 0xa8, 0x98, 0x6b, 0x75, 0x93, 0xdf, 0x30, - 0x5d, 0x07, 0x43, 0x2d, 0x82, 0xcc, 0x6a, 0x57, 0xbd, 0x28, 0xcb, 0x8d, 0x7a, 0x26, 0xc7, 0x86, 0xf0, 0x4d, 0xa5, - 0x3b, 0x44, 0x37, 0x4c, 0xd5, 0x4c, 0xdf, 0x37, 0xb6, 0x85, 0x6c, 0xf3, 0xf2, 0x6a, 0x94, 0x03, 0xa5, 0xe5, 0xfe, - 0x32, 0x61, 0xf8, 0xfe, 0xfa, 0xfa, 0x7b, 0x21, 0xa7, 0xaa, 0x8e, 0xde, 0xe2, 0xb5, 0xee, 0x19, 0x6c, 0x94, 0xca, - 0x89, 0xb8, 0x60, 0xab, 0x07, 0x6f, 0xee, 0x5e, 0x01, 0xcb, 0x05, 0xec, 0xda, 0x0b, 0xe6, 0x34, 0x86, 0xaa, 0x36, - 0xf0, 0x97, 0xab, 0x07, 0x5b, 0xb5, 0x87, 0xbf, 0x1c, 0x7c, 0x19, 0xdc, 0xd8, 0xd8, 0xd8, 0xc6, 0xdb, 0xb5, 0x44, - 0x90, 0x37, 0x78, 0xa0, 0x8f, 0x57, 0x1f, 0x05, 0x2d, 0x57, 0x88, 0x6d, 0x36, 0x70, 0x28, 0x6c, 0x0d, 0xf2, 0x4d, - 0xca, 0xa4, 0xe1, 0xbc, 0xe0, 0xd9, 0x54, 0xce, 0x50, 0xc8, 0x6b, 0x3e, 0x0e, 0xda, 0x8e, 0xf0, 0xbf, 0xc0, 0xa9, - 0x1d, 0x2f, 0x2f, 0x3e, 0x41, 0x1f, 0xf0, 0x74, 0xa5, 0x34, 0xa5, 0x38, 0xa5, 0x0a, 0xea, 0x2c, 0xd7, 0x79, 0x30, - 0x52, 0x5c, 0x4c, 0x60, 0x71, 0xc1, 0x65, 0xb9, 0x71, 0x36, 0x72, 0xfa, 0x4b, 0xbc, 0xba, 0x48, 0x97, 0x8f, 0x44, - 0xb6, 0x6a, 0xe9, 0xfd, 0xac, 0x4f, 0xb7, 0xed, 0x29, 0xe3, 0x93, 0x6c, 0x44, 0x07, 0x33, 0x3e, 0x4e, 0x84, 0xd7, - 0x27, 0x46, 0xfa, 0x6e, 0x11, 0x98, 0x6e, 0x8e, 0x4d, 0x7e, 0x38, 0x5e, 0x6f, 0x36, 0x6b, 0xdc, 0xc1, 0x3b, 0xe7, - 0x93, 0xb3, 0x28, 0x31, 0xa2, 0xb2, 0xd0, 0xf0, 0x80, 0x56, 0x88, 0x9b, 0xf7, 0x4c, 0x60, 0x5c, 0x76, 0x45, 0x52, - 0xdb, 0x0d, 0x04, 0x2e, 0xf6, 0x38, 0x66, 0xc9, 0xc8, 0xf6, 0xa0, 0x3c, 0xd0, 0x17, 0xa3, 0xe9, 0x16, 0x30, 0x2d, - 0xaf, 0x9d, 0x5d, 0xa4, 0xb6, 0x57, 0x4d, 0x15, 0xc0, 0x2c, 0x59, 0x1e, 0x9f, 0x21, 0xeb, 0x7e, 0x0d, 0x5d, 0xc4, - 0x80, 0xb1, 0x71, 0x65, 0xce, 0x5d, 0xac, 0x5a, 0x11, 0xdf, 0x68, 0x22, 0x4d, 0xea, 0x43, 0xea, 0x7b, 0x14, 0xd6, - 0xea, 0x2a, 0x07, 0x09, 0xdc, 0x23, 0xef, 0x8e, 0xb8, 0xf4, 0xf4, 0x99, 0xc5, 0xb8, 0x4a, 0xdf, 0x52, 0xd7, 0xe2, - 0x9a, 0x61, 0xaf, 0x78, 0x00, 0xf6, 0x07, 0xc6, 0x2d, 0x62, 0x11, 0x6f, 0x67, 0xb5, 0x14, 0xd6, 0xc6, 0x1c, 0x68, - 0x6e, 0xb8, 0xc1, 0xcf, 0xac, 0x5a, 0x33, 0x30, 0xc3, 0x8c, 0x33, 0x92, 0x0f, 0xc6, 0xbd, 0xaa, 0xb1, 0x23, 0x57, - 0x01, 0x44, 0xdf, 0x82, 0x2e, 0xc9, 0xe1, 0x95, 0x2c, 0x57, 0x9d, 0x21, 0xbf, 0x82, 0x75, 0xd6, 0x8b, 0x13, 0x70, - 0x93, 0xa6, 0xac, 0xc4, 0xc4, 0x14, 0x71, 0xb9, 0x59, 0xc6, 0x3c, 0x4d, 0x9f, 0x45, 0x3b, 0x38, 0xb9, 0x91, 0xc0, - 0x11, 0xfb, 0xc6, 0x32, 0x34, 0x13, 0x36, 0x62, 0x22, 0x8d, 0x4a, 0x29, 0x61, 0x03, 0xb9, 0xd4, 0x92, 0xbf, 0xcc, - 0xe5, 0xd5, 0x97, 0xdb, 0x04, 0x07, 0xe4, 0x35, 0xb0, 0x1c, 0x1a, 0xc7, 0x2d, 0x03, 0x89, 0x58, 0x0c, 0x88, 0x51, - 0xab, 0x72, 0x39, 0x19, 0xd5, 0xc9, 0x7c, 0x85, 0x5c, 0xa8, 0xc8, 0x83, 0x5b, 0x02, 0x2f, 0x54, 0xe4, 0x98, 0x3a, - 0x98, 0x95, 0xda, 0x4d, 0x8b, 0x4d, 0x92, 0xf7, 0xcc, 0x80, 0xe4, 0xea, 0x6b, 0x78, 0x68, 0xfc, 0x32, 0xbc, 0xa1, - 0xe8, 0xe9, 0x18, 0x21, 0xa7, 0xa5, 0x31, 0x97, 0xfe, 0x5b, 0x79, 0x9f, 0x56, 0x02, 0xf6, 0x0a, 0xc4, 0x94, 0x81, - 0x4b, 0x6c, 0x5c, 0x90, 0x94, 0xd7, 0xf2, 0x94, 0xdd, 0xd7, 0x50, 0xbe, 0x4b, 0x26, 0x5d, 0xa5, 0xb2, 0xd6, 0x58, - 0x75, 0x3f, 0xcf, 0x59, 0x7e, 0xb5, 0xcf, 0x30, 0x37, 0x19, 0x0d, 0xb2, 0x25, 0x33, 0x9b, 0xf2, 0xab, 0xbd, 0x1b, - 0xbf, 0xf2, 0x50, 0xd2, 0xa1, 0x5a, 0xa5, 0x9b, 0x97, 0x6e, 0x38, 0xc6, 0x8d, 0x1b, 0x8e, 0x00, 0x36, 0x86, 0x9d, - 0x2a, 0x52, 0xeb, 0xfc, 0xf7, 0xa5, 0xf0, 0x93, 0xd8, 0x6b, 0x47, 0x7a, 0xd7, 0x1d, 0xad, 0x4c, 0x4f, 0xbf, 0x01, - 0x55, 0x23, 0x4b, 0xe8, 0x26, 0x54, 0x31, 0x19, 0x89, 0x12, 0xd3, 0x55, 0xca, 0xa3, 0xbe, 0x46, 0x9c, 0x83, 0xb8, - 0xa1, 0xfc, 0xc5, 0x3f, 0x85, 0x57, 0x27, 0x01, 0x1a, 0x51, 0x8b, 0x71, 0x96, 0xf2, 0xd6, 0x38, 0x9a, 0xc6, 0xc9, - 0x55, 0x30, 0x8f, 0x5b, 0xd3, 0x2c, 0xcd, 0x8a, 0x19, 0x70, 0xa5, 0x57, 0x5c, 0x81, 0x0d, 0x3f, 0x6d, 0xcd, 0x63, - 0xef, 0x25, 0x4b, 0xce, 0x19, 0x8f, 0x87, 0x91, 0x67, 0xef, 0xe5, 0x20, 0x1e, 0xac, 0xb7, 0x51, 0x9e, 0x67, 0x17, - 0xb6, 0xf7, 0x21, 0x3b, 0x05, 0xa6, 0xf5, 0xde, 0x5d, 0x5e, 0x9d, 0xb1, 0xd4, 0xfb, 0x78, 0x3a, 0x4f, 0xf9, 0xdc, - 0x2b, 0xa2, 0xb4, 0x68, 0x15, 0x2c, 0x8f, 0xc7, 0xa0, 0x26, 0x92, 0x2c, 0x6f, 0x61, 0xfe, 0xf3, 0x94, 0x05, 0x49, - 0x7c, 0x36, 0xe1, 0xd6, 0x28, 0xca, 0x3f, 0xf5, 0x5a, 0xad, 0x59, 0x1e, 0x4f, 0xa3, 0xfc, 0xaa, 0x45, 0x2d, 0x82, - 0xcf, 0xda, 0xdb, 0xd1, 0xe7, 0xe3, 0x87, 0x3d, 0x9e, 0x43, 0xdf, 0x18, 0xa9, 0x18, 0x80, 0xf0, 0xb1, 0xb6, 0x77, - 0xda, 0xd3, 0xe2, 0x9e, 0x38, 0x51, 0x8a, 0x52, 0x5e, 0x9e, 0x78, 0x57, 0x0c, 0xe0, 0xf6, 0x4f, 0x79, 0xea, 0x81, - 0x2f, 0xc7, 0xb3, 0x74, 0x31, 0x9c, 0xe7, 0x05, 0x0c, 0x30, 0xcb, 0xe2, 0x94, 0xb3, 0xbc, 0x77, 0x9a, 0xe5, 0x40, - 0xb6, 0x56, 0x1e, 0x8d, 0xe2, 0x79, 0x11, 0x3c, 0x9c, 0x5d, 0xf6, 0xd0, 0x56, 0x38, 0xcb, 0xb3, 0x79, 0x3a, 0x92, - 0x73, 0xc5, 0x29, 0x6c, 0x8c, 0x98, 0x9b, 0x15, 0xf4, 0x25, 0x14, 0x80, 0x2f, 0x65, 0x51, 0xde, 0x3a, 0xc3, 0xce, - 0x68, 0xe8, 0xb7, 0x47, 0xec, 0xcc, 0xcb, 0xcf, 0x4e, 0x23, 0xa7, 0xd3, 0x7d, 0xec, 0xa9, 0x7f, 0xfe, 0x8e, 0x0b, - 0x86, 0xfb, 0xca, 0xe2, 0x4e, 0xbb, 0xfd, 0x37, 0x6e, 0xaf, 0x31, 0x0b, 0x01, 0x14, 0x74, 0x66, 0x97, 0x56, 0x91, - 0x25, 0xb0, 0x3e, 0xab, 0x7a, 0xf6, 0x66, 0xe0, 0x37, 0xc5, 0xe9, 0x59, 0xd0, 0x9d, 0x5d, 0x96, 0x88, 0x5d, 0x20, - 0x12, 0x32, 0x25, 0x92, 0xf2, 0x6d, 0xf1, 0x5b, 0x21, 0x7e, 0xb2, 0x1a, 0xe2, 0xae, 0x82, 0xb8, 0xa2, 0x7a, 0x6b, - 0x04, 0xfb, 0x80, 0xc8, 0xdf, 0x29, 0x04, 0x20, 0x13, 0x70, 0x02, 0x73, 0x05, 0x07, 0xbd, 0xfc, 0x66, 0x30, 0xba, - 0xab, 0xc1, 0x78, 0x72, 0x1b, 0x18, 0x79, 0x3a, 0x5a, 0xd4, 0xd7, 0xb5, 0x03, 0xce, 0x69, 0x6f, 0xc2, 0x90, 0x9f, - 0x82, 0x2e, 0x3e, 0x5f, 0xc4, 0x23, 0x3e, 0x11, 0x8f, 0xc4, 0xce, 0x17, 0xa2, 0x6e, 0xa7, 0xdd, 0x16, 0xef, 0x05, - 0x28, 0xb4, 0xa0, 0xe3, 0x63, 0x03, 0x60, 0xa2, 0x2f, 0xd6, 0x7d, 0xc4, 0xe6, 0xbb, 0x5b, 0xbf, 0x54, 0xe3, 0x31, - 0x95, 0x37, 0x28, 0x54, 0x84, 0xfa, 0x66, 0x0b, 0x66, 0xbc, 0xe5, 0xfd, 0x8e, 0x3e, 0xa8, 0x1a, 0x7c, 0xc7, 0x48, - 0xeb, 0x05, 0xcc, 0x33, 0x73, 0x81, 0x7a, 0x69, 0x1f, 0x43, 0x52, 0xad, 0x96, 0x0b, 0x7a, 0x83, 0x63, 0x08, 0x89, - 0x0e, 0x04, 0x9d, 0x7c, 0x50, 0xd0, 0x37, 0x35, 0x32, 0x37, 0x28, 0x9c, 0xcc, 0x85, 0x2d, 0x9f, 0x69, 0xb9, 0x0e, - 0x4a, 0x1a, 0xbc, 0xec, 0x2f, 0x98, 0x6c, 0x00, 0xd2, 0xbb, 0x92, 0xb4, 0xbc, 0x3a, 0x7a, 0x52, 0x2e, 0x5f, 0x36, - 0x24, 0xca, 0x81, 0xaf, 0xcf, 0x27, 0xe8, 0x77, 0xeb, 0xab, 0xeb, 0x46, 0x4a, 0xcd, 0x96, 0xed, 0x0e, 0xb8, 0xce, - 0xca, 0xc2, 0xec, 0x33, 0x5e, 0xe2, 0x28, 0x5f, 0x81, 0x9c, 0xc5, 0xd0, 0xeb, 0xcf, 0xa1, 0x70, 0xd3, 0x94, 0x93, - 0xb6, 0x71, 0xd3, 0xf5, 0x7f, 0x58, 0xf1, 0x98, 0xb2, 0x9d, 0x55, 0x6c, 0x1c, 0x5c, 0x97, 0xe3, 0xa1, 0xb8, 0x76, - 0x58, 0x60, 0xb6, 0xf8, 0x6f, 0xf7, 0x24, 0x1c, 0x8d, 0x56, 0x91, 0xcd, 0xf3, 0x21, 0x26, 0xfd, 0xaf, 0x08, 0x31, - 0xd8, 0xa4, 0xe1, 0x6d, 0x8f, 0x6b, 0xc5, 0xc2, 0x30, 0x7f, 0xc2, 0xfc, 0xaa, 0x02, 0xa3, 0x53, 0x17, 0x71, 0xa9, - 0x41, 0x86, 0x55, 0x14, 0xd8, 0xa8, 0x2b, 0x47, 0x94, 0x60, 0x47, 0x17, 0x3e, 0xfd, 0x79, 0x1a, 0x83, 0x68, 0x3d, - 0x8e, 0x47, 0x74, 0xd1, 0x25, 0x1e, 0xd1, 0xc9, 0x47, 0x8b, 0x32, 0x9d, 0x30, 0x94, 0x0e, 0x05, 0x92, 0xe0, 0xf8, - 0x2c, 0x33, 0x67, 0xec, 0x96, 0x8d, 0xa7, 0x17, 0x86, 0x6e, 0x1e, 0x65, 0xd3, 0x28, 0x4e, 0x03, 0xfc, 0x20, 0x89, - 0xa7, 0x47, 0x0c, 0xb0, 0x8b, 0x07, 0x7f, 0x15, 0xed, 0x3b, 0xae, 0xff, 0x13, 0x08, 0x2e, 0xea, 0x5f, 0x4a, 0xc7, - 0x4f, 0xc3, 0xa5, 0xce, 0x95, 0xeb, 0xa5, 0x20, 0xec, 0xb8, 0xce, 0x6d, 0xa7, 0xc0, 0xca, 0x2e, 0xa3, 0x3f, 0x83, - 0x56, 0x27, 0xe8, 0xb8, 0xcb, 0x2b, 0x60, 0x5c, 0x0c, 0xa8, 0x56, 0x85, 0x4a, 0xe4, 0x1b, 0xcc, 0x21, 0xf9, 0xf3, - 0xfa, 0x5a, 0x7f, 0x3c, 0xa0, 0x71, 0x81, 0x56, 0xa4, 0xdf, 0xc8, 0x4b, 0x98, 0x84, 0x85, 0x7e, 0x16, 0x98, 0x56, - 0xef, 0x1a, 0x5b, 0x4f, 0x6e, 0x25, 0x8c, 0x39, 0x9d, 0xa5, 0x4e, 0x0d, 0x0d, 0x3a, 0xbe, 0x58, 0x33, 0x95, 0x5b, - 0x46, 0xc4, 0xdc, 0x4f, 0x49, 0xe6, 0xd4, 0xaf, 0x3f, 0xc5, 0x18, 0xb8, 0xaf, 0x65, 0x6d, 0x29, 0xf6, 0x1e, 0x9e, - 0xec, 0x0a, 0x21, 0x65, 0x11, 0xeb, 0x86, 0x36, 0x48, 0x0d, 0xdb, 0xfa, 0xe3, 0x10, 0xe8, 0xfc, 0x29, 0xb4, 0x37, - 0x16, 0x8e, 0xba, 0x0b, 0x90, 0xc3, 0x5c, 0x7b, 0x42, 0x51, 0xd3, 0x47, 0x04, 0xec, 0xfe, 0xc6, 0x82, 0x95, 0xbb, - 0x5b, 0xa2, 0x77, 0xff, 0xa4, 0x2c, 0x48, 0xa7, 0x9a, 0xb1, 0xbf, 0x6a, 0x0a, 0x51, 0x07, 0xc3, 0x52, 0xc6, 0x31, - 0x8e, 0x9b, 0x6b, 0x3b, 0x51, 0x04, 0xb9, 0x25, 0xe3, 0x16, 0x98, 0x61, 0x15, 0xe5, 0x20, 0x46, 0x74, 0x0e, 0x4d, - 0x21, 0xd2, 0x46, 0x7a, 0xcb, 0x50, 0x9c, 0x20, 0x04, 0x83, 0x8d, 0x45, 0x5c, 0x86, 0xf0, 0x94, 0x0e, 0xb3, 0x11, - 0xfb, 0xf8, 0xe1, 0x15, 0x5e, 0x93, 0xc8, 0x52, 0x94, 0xa7, 0x99, 0x5b, 0x9e, 0x80, 0x81, 0x85, 0x90, 0xe6, 0xea, - 0x2b, 0x35, 0x00, 0x8c, 0x88, 0x15, 0x59, 0x34, 0x2a, 0x82, 0xc2, 0x4b, 0xdb, 0x1a, 0x08, 0x08, 0xc1, 0x91, 0xc5, - 0x02, 0x30, 0x41, 0xa9, 0x17, 0x07, 0xfc, 0x44, 0xeb, 0x3e, 0x0c, 0xb4, 0xbb, 0x25, 0x1a, 0x01, 0xae, 0x39, 0xa2, - 0x51, 0xa1, 0x8a, 0x59, 0x45, 0x26, 0xba, 0xa3, 0xf8, 0x5c, 0x93, 0x93, 0x52, 0xac, 0xfb, 0xbb, 0x49, 0x74, 0xca, - 0x12, 0x18, 0x12, 0xf8, 0xaa, 0x0d, 0x23, 0x89, 0x57, 0x6b, 0x37, 0x4e, 0x67, 0x73, 0xf9, 0xb5, 0x30, 0x98, 0xb8, - 0x83, 0x07, 0xb8, 0x78, 0x99, 0x61, 0xa0, 0x4e, 0x24, 0x03, 0x39, 0x00, 0x80, 0x48, 0x87, 0x21, 0x08, 0x5d, 0xc5, - 0x2a, 0x50, 0x1a, 0x8f, 0x96, 0xcb, 0x60, 0x7f, 0xcf, 0xb0, 0x34, 0x85, 0xe7, 0x69, 0x9c, 0xe2, 0x63, 0x81, 0x8f, - 0xd1, 0x25, 0x3e, 0x66, 0xf0, 0xa8, 0x71, 0xcf, 0x4b, 0xfb, 0xaf, 0xba, 0x2a, 0x99, 0x5c, 0x01, 0x4b, 0x13, 0x20, - 0xbb, 0xbe, 0x06, 0xb5, 0xa5, 0x49, 0xb0, 0xbb, 0x05, 0xc4, 0x42, 0xee, 0x11, 0xdf, 0x8e, 0xe1, 0x26, 0x19, 0x59, - 0x31, 0x6b, 0x89, 0x72, 0x8b, 0x8c, 0x83, 0x10, 0x7c, 0xc7, 0xdc, 0x69, 0xd8, 0x40, 0x9e, 0xcc, 0x92, 0x79, 0x86, - 0x2f, 0xae, 0x6d, 0x89, 0x8f, 0x7b, 0x08, 0xa2, 0xd0, 0x23, 0x62, 0xa8, 0xcb, 0x98, 0xfc, 0x6c, 0x4f, 0x1c, 0xda, - 0x38, 0x0b, 0x98, 0xa1, 0xe8, 0x85, 0xf2, 0x28, 0x4e, 0x44, 0xe3, 0x15, 0xf8, 0x34, 0xd2, 0x1d, 0x09, 0x9d, 0xdd, - 0xad, 0x0a, 0x36, 0x00, 0x5e, 0x49, 0x04, 0x4e, 0x19, 0x37, 0xb6, 0x28, 0xa7, 0x14, 0x00, 0xb9, 0xcd, 0xab, 0x4f, - 0x3a, 0x01, 0x53, 0x80, 0x11, 0x3d, 0x3a, 0xa6, 0xd9, 0x06, 0x43, 0x20, 0x16, 0xcd, 0xd8, 0xd8, 0xba, 0xf6, 0x5f, - 0xfe, 0xf9, 0x1f, 0x6c, 0x4f, 0x80, 0x98, 0x8d, 0xc7, 0x20, 0xe5, 0xac, 0x75, 0x0d, 0xff, 0xd7, 0x3f, 0xfe, 0xdf, - 0xff, 0xf3, 0x5f, 0x75, 0xdb, 0x14, 0x9a, 0x9e, 0x04, 0xe2, 0x68, 0x41, 0x93, 0x94, 0x52, 0x3c, 0xed, 0x71, 0x94, - 0xae, 0x00, 0xe9, 0x10, 0xb3, 0x18, 0x19, 0x1b, 0x79, 0xb6, 0x05, 0x9a, 0x40, 0x3c, 0x1f, 0x27, 0xec, 0x9c, 0xc9, - 0x0f, 0xcb, 0xe8, 0x41, 0x74, 0xe5, 0x10, 0x2c, 0x18, 0x2e, 0xef, 0xbc, 0xca, 0x6d, 0xa0, 0x68, 0x29, 0x29, 0x5e, - 0x27, 0x98, 0x67, 0x1b, 0x83, 0x36, 0xe7, 0x68, 0xd7, 0x87, 0xf5, 0x40, 0xa5, 0xda, 0xb6, 0x80, 0x97, 0xcc, 0xde, - 0x95, 0x10, 0x37, 0xe1, 0x3a, 0xcd, 0xb1, 0x69, 0xca, 0x8a, 0x62, 0x15, 0x58, 0x40, 0x13, 0xcf, 0xae, 0x9a, 0xd8, - 0xb5, 0x0e, 0x00, 0x40, 0x77, 0x67, 0x47, 0x4c, 0x0b, 0x15, 0x6c, 0x3c, 0x86, 0x0d, 0x8e, 0xba, 0x2d, 0xe1, 0x18, - 0x84, 0x0f, 0xfb, 0xf6, 0x5b, 0x90, 0x25, 0x78, 0xa7, 0xc5, 0xd5, 0x9f, 0xf4, 0xa2, 0xe9, 0x95, 0xb0, 0x33, 0xe6, - 0x10, 0x9d, 0x8d, 0x61, 0xf4, 0x93, 0x81, 0x54, 0x36, 0xfc, 0xb4, 0x8a, 0x31, 0xd6, 0x32, 0xc2, 0xbf, 0xff, 0xcb, - 0x3f, 0xfe, 0x37, 0x18, 0x9b, 0xfa, 0xad, 0xe7, 0x02, 0x68, 0xf5, 0x3f, 0xa1, 0xd5, 0x3c, 0xbd, 0xa5, 0xdd, 0x5f, - 0xfe, 0xfe, 0xbf, 0x43, 0x33, 0xba, 0x28, 0x05, 0x7c, 0x42, 0x10, 0x0d, 0xd1, 0x36, 0xfd, 0x55, 0x20, 0xd5, 0x06, - 0x59, 0x3b, 0xd3, 0x3f, 0x21, 0xd8, 0x05, 0xcf, 0x66, 0x37, 0x82, 0x83, 0x50, 0x0f, 0x93, 0xac, 0x60, 0x1a, 0x1e, - 0xa1, 0x4f, 0x7e, 0x1d, 0x40, 0x34, 0xd7, 0x0c, 0x76, 0x6d, 0x61, 0xe9, 0x71, 0xc4, 0x0a, 0xad, 0xdc, 0x84, 0xf5, - 0x05, 0x2c, 0x18, 0x27, 0x74, 0x28, 0xdc, 0x03, 0x4b, 0x26, 0x9e, 0xe0, 0x81, 0x04, 0x9c, 0x5b, 0xff, 0xf8, 0xda, - 0xea, 0xc1, 0x34, 0xc3, 0x89, 0xb1, 0x44, 0x84, 0x4b, 0x8d, 0x00, 0x7f, 0x41, 0x08, 0x1f, 0xeb, 0xe7, 0xe8, 0x52, - 0x3f, 0xa3, 0xa0, 0x16, 0x13, 0x80, 0xbe, 0x9d, 0xa2, 0x31, 0x66, 0xce, 0x20, 0xb2, 0x33, 0x2a, 0xf7, 0xde, 0x48, - 0xf2, 0x11, 0xc2, 0xf8, 0x18, 0x73, 0x61, 0xf1, 0xe6, 0xd3, 0x3c, 0x67, 0xc7, 0x49, 0x76, 0x81, 0x31, 0x43, 0x22, - 0xd2, 0x9a, 0xfa, 0xf2, 0xdf, 0xfe, 0xd5, 0xf7, 0xff, 0xed, 0x5f, 0xd7, 0x34, 0x98, 0xc0, 0x9e, 0x00, 0x23, 0x9f, - 0x85, 0x9a, 0xce, 0x0d, 0xb4, 0x56, 0x0f, 0x8a, 0x78, 0xae, 0xae, 0x91, 0x88, 0x63, 0xa9, 0xc4, 0x5b, 0x3e, 0x12, - 0xda, 0x9a, 0x29, 0x6e, 0x9f, 0x05, 0x21, 0x5b, 0x33, 0x0d, 0x56, 0xdd, 0x32, 0xcf, 0x89, 0x1b, 0xdc, 0x40, 0x97, - 0x5f, 0x89, 0xf1, 0x6a, 0x30, 0x6e, 0x85, 0xc0, 0x03, 0x6d, 0x26, 0xf4, 0xdd, 0x33, 0xa1, 0xad, 0x02, 0xb1, 0x0c, - 0x52, 0x77, 0xd5, 0x00, 0xf2, 0xac, 0x03, 0x9a, 0x80, 0x9a, 0xc4, 0x95, 0xad, 0x40, 0xe6, 0xd6, 0x69, 0xde, 0x7f, - 0x83, 0x97, 0x1d, 0x91, 0x78, 0x64, 0x29, 0x14, 0x64, 0xd8, 0x30, 0x32, 0x6c, 0xa4, 0x46, 0x35, 0x6d, 0x0a, 0x74, - 0xfc, 0xb2, 0xd5, 0xb6, 0xc3, 0x31, 0x76, 0xaf, 0x69, 0x7f, 0x26, 0xb5, 0x7f, 0x2c, 0xed, 0x7d, 0xa9, 0xfd, 0xf1, - 0x93, 0x36, 0x0d, 0xed, 0x1f, 0xaf, 0xd5, 0xfe, 0x48, 0xb9, 0x01, 0x8e, 0x1c, 0xda, 0x9b, 0x18, 0xdd, 0x32, 0x6c, - 0x0d, 0xd4, 0xc4, 0x83, 0xe1, 0x84, 0x0d, 0x3f, 0x49, 0x33, 0x8b, 0x10, 0xc0, 0x40, 0x94, 0x36, 0x26, 0x05, 0x06, - 0x60, 0x32, 0x9c, 0x94, 0x7a, 0xd3, 0xe3, 0xa3, 0x31, 0x01, 0x73, 0x17, 0x63, 0x86, 0xa2, 0x1f, 0xd6, 0xec, 0x2b, - 0x56, 0x6e, 0xe1, 0x38, 0x62, 0xc3, 0x88, 0x67, 0xc0, 0x6c, 0x0b, 0x07, 0x3b, 0xf1, 0x16, 0x22, 0x58, 0x18, 0xd8, - 0xef, 0xdf, 0xed, 0x1f, 0xd8, 0xde, 0x69, 0x36, 0xba, 0x0a, 0x6c, 0x70, 0xc6, 0xc0, 0x9a, 0x72, 0x7d, 0x3e, 0x61, - 0xa9, 0xa3, 0x3c, 0x9f, 0x2c, 0x61, 0xe0, 0x00, 0x9e, 0x89, 0x6f, 0x5b, 0x34, 0x0f, 0x3a, 0x80, 0xb0, 0xf4, 0xf1, - 0xcb, 0xfe, 0x2e, 0x17, 0xdf, 0x85, 0xe5, 0x39, 0x3e, 0xf6, 0x31, 0xd5, 0x63, 0x77, 0x0b, 0x1e, 0xf0, 0x65, 0x1f, - 0xf5, 0x1e, 0xbd, 0x6d, 0x2c, 0x96, 0xdc, 0x86, 0x01, 0x0e, 0x31, 0xe9, 0x0b, 0x14, 0x0a, 0x6a, 0x75, 0x12, 0x20, - 0x62, 0xf0, 0x08, 0x63, 0x6d, 0xa9, 0x71, 0x11, 0x42, 0xd5, 0x5f, 0x3b, 0x2e, 0x95, 0xdd, 0x4a, 0xf3, 0x8e, 0xb0, - 0x01, 0x39, 0x2e, 0xd8, 0x7b, 0xa4, 0x4b, 0x84, 0xa9, 0x43, 0x45, 0xeb, 0x20, 0xd0, 0x35, 0x95, 0xb9, 0x22, 0x3a, - 0x18, 0xc0, 0x90, 0x99, 0x2b, 0x00, 0x81, 0xbf, 0x84, 0xf6, 0x89, 0xf9, 0xfd, 0x37, 0xf1, 0xa9, 0x26, 0x4d, 0x9c, - 0xc3, 0x3f, 0x79, 0x57, 0xcc, 0xbb, 0x3a, 0xa1, 0x96, 0x2a, 0xd8, 0x80, 0x51, 0x30, 0x0c, 0xca, 0xb4, 0x55, 0x54, - 0x09, 0xec, 0xb4, 0x24, 0x9a, 0x15, 0x2c, 0x50, 0x0f, 0x32, 0xee, 0x80, 0xe1, 0x8b, 0xe5, 0x40, 0x8f, 0x69, 0xcf, - 0x95, 0x7c, 0xb2, 0x30, 0x03, 0x13, 0x8f, 0xda, 0xed, 0x1e, 0x5e, 0xaa, 0x68, 0x45, 0x60, 0x1d, 0xa4, 0x41, 0xc2, - 0xc6, 0xbc, 0xe4, 0x78, 0x6b, 0x7f, 0xa1, 0x22, 0x41, 0x7e, 0x77, 0x27, 0x67, 0x53, 0xcb, 0xc7, 0xff, 0xbf, 0x6d, - 0xec, 0x51, 0x90, 0xf2, 0x49, 0x8b, 0xae, 0xf1, 0xe0, 0x15, 0x49, 0x80, 0xc8, 0x7c, 0x5f, 0x18, 0x13, 0x0d, 0x19, - 0x46, 0xc9, 0x4a, 0x0e, 0xce, 0x37, 0x88, 0x9b, 0xdc, 0x6c, 0x07, 0x72, 0x7a, 0x29, 0x54, 0xb6, 0x1c, 0xac, 0xd9, - 0x76, 0xa5, 0x7f, 0xb4, 0xdc, 0x58, 0x45, 0xbc, 0xea, 0x6f, 0x4b, 0x14, 0x32, 0x62, 0x73, 0xa5, 0x50, 0x51, 0x0b, - 0xd1, 0xc3, 0xc4, 0x69, 0x39, 0x6a, 0x77, 0xab, 0xc5, 0x5c, 0x92, 0xb8, 0x38, 0x24, 0x71, 0x41, 0xe2, 0xef, 0x68, - 0x21, 0xe6, 0x1e, 0x46, 0xc9, 0xd0, 0x41, 0x00, 0xac, 0x96, 0xf5, 0x04, 0xa8, 0xe9, 0xaa, 0xc8, 0x91, 0xff, 0x18, - 0x89, 0x5b, 0x0a, 0x61, 0xb9, 0x82, 0x4a, 0x27, 0x47, 0x65, 0xd9, 0x63, 0xcc, 0x39, 0xfc, 0x20, 0x2f, 0x81, 0x88, - 0xbb, 0xbf, 0xfa, 0xfb, 0x89, 0xed, 0xd2, 0x3d, 0xf2, 0x7e, 0x36, 0x3e, 0x4a, 0x67, 0x2b, 0x66, 0xb7, 0x3d, 0x58, - 0x06, 0xb3, 0xa7, 0xfc, 0x84, 0xe4, 0x4d, 0x7d, 0x4d, 0x36, 0xa7, 0xfe, 0x3f, 0x87, 0x38, 0xc2, 0x1b, 0xc7, 0x46, - 0x13, 0x9d, 0x46, 0xbe, 0x6a, 0x11, 0x7f, 0xda, 0xd8, 0x55, 0x1c, 0x81, 0x7c, 0xbd, 0x2e, 0x92, 0xf5, 0xcd, 0xed, - 0x91, 0xac, 0xe2, 0x8e, 0x91, 0xac, 0x6f, 0x7e, 0xe7, 0x48, 0xd6, 0xd7, 0x66, 0x24, 0x0b, 0x05, 0xf4, 0xab, 0x5f, - 0x13, 0x6d, 0xca, 0xb3, 0x8b, 0x22, 0xec, 0xc8, 0xcc, 0x09, 0x90, 0x75, 0x18, 0x76, 0xfa, 0xeb, 0x47, 0x98, 0x60, - 0xa2, 0x46, 0x7c, 0x89, 0x02, 0x4a, 0x22, 0xd9, 0x13, 0xd4, 0x8a, 0x0c, 0xe7, 0xb4, 0x75, 0x56, 0x65, 0xeb, 0xa1, - 0xba, 0x46, 0x06, 0xae, 0xaf, 0xab, 0x43, 0x6d, 0x5d, 0x15, 0xf0, 0x09, 0xe8, 0x3b, 0xb0, 0xba, 0x63, 0x77, 0x53, - 0xa5, 0xf3, 0x99, 0x23, 0xf4, 0xd4, 0x29, 0x8d, 0x60, 0xa2, 0x85, 0xfd, 0x5f, 0x0e, 0x3b, 0xbd, 0xed, 0xce, 0x14, - 0x7a, 0x83, 0x02, 0x87, 0xb7, 0x76, 0x6f, 0x7b, 0x1b, 0xdf, 0x2e, 0xd4, 0x5b, 0x17, 0xdf, 0x62, 0xf5, 0xb6, 0x83, - 0x6f, 0x43, 0xf5, 0xf6, 0x08, 0xdf, 0x46, 0xea, 0xed, 0x31, 0xbe, 0x9d, 0xdb, 0xe5, 0x21, 0xd3, 0xc0, 0x3d, 0x06, - 0xbe, 0x22, 0x6f, 0x26, 0x50, 0x65, 0xb0, 0xe9, 0xf1, 0xc3, 0x08, 0xd1, 0x59, 0x10, 0x7b, 0xc2, 0xbb, 0x0c, 0x72, - 0xef, 0x02, 0x34, 0x4e, 0x40, 0xd9, 0x86, 0xcf, 0xf1, 0x3b, 0x1c, 0xe0, 0x24, 0x1d, 0xc4, 0x53, 0xa6, 0x3e, 0x48, - 0xac, 0xb0, 0x06, 0x03, 0xf6, 0xb0, 0x7d, 0x54, 0xf6, 0xf4, 0x3a, 0x89, 0x78, 0x96, 0xca, 0xe6, 0xa0, 0x95, 0xab, - 0xea, 0xc4, 0x74, 0x2d, 0xbd, 0xc2, 0x6b, 0xf4, 0x97, 0x11, 0x8f, 0x18, 0x83, 0x61, 0xd6, 0xba, 0x04, 0x0f, 0x76, - 0xa5, 0x4e, 0x43, 0x88, 0xb4, 0x4e, 0x23, 0x9c, 0xf4, 0xdb, 0x41, 0x74, 0xa6, 0x9f, 0xdf, 0x80, 0xa5, 0x1d, 0x9d, - 0xc9, 0x96, 0xeb, 0x75, 0x18, 0x81, 0x68, 0xea, 0x2f, 0x05, 0x04, 0x99, 0x62, 0xb0, 0x34, 0xe8, 0x49, 0x4b, 0xfd, - 0x85, 0xd4, 0xa9, 0x6b, 0x34, 0x9a, 0xbe, 0x5e, 0x04, 0x14, 0xad, 0x0a, 0x76, 0xc1, 0xe0, 0xa7, 0x52, 0x41, 0x61, - 0xa8, 0xc0, 0x02, 0x51, 0xbd, 0x46, 0x95, 0xe9, 0x60, 0xc3, 0x5a, 0x85, 0x66, 0x29, 0x5d, 0x66, 0x9e, 0xee, 0xe8, - 0xa3, 0x9d, 0x65, 0xf1, 0xfa, 0x59, 0x67, 0x88, 0xff, 0x49, 0xe1, 0xfd, 0xd9, 0x78, 0x3c, 0xbe, 0x51, 0xb7, 0x7d, - 0x36, 0x1a, 0xb3, 0x2e, 0xdb, 0xe9, 0x61, 0xe4, 0xbf, 0x25, 0xc5, 0x69, 0xa7, 0x24, 0xda, 0x2d, 0xee, 0xd6, 0x18, - 0x25, 0x2f, 0xa8, 0xbb, 0xbb, 0x2b, 0xc1, 0x12, 0xa8, 0xb2, 0x00, 0xe1, 0x7f, 0x16, 0xa7, 0x41, 0xbb, 0xf4, 0xcf, - 0xa5, 0xd6, 0xf8, 0xec, 0xc9, 0x93, 0x27, 0xa5, 0x3f, 0x52, 0x6f, 0xed, 0xd1, 0xa8, 0xf4, 0x87, 0x0b, 0x8d, 0x46, - 0xbb, 0x3d, 0x1e, 0x97, 0x7e, 0xac, 0x0a, 0xb6, 0xbb, 0xc3, 0xd1, 0x76, 0xb7, 0xf4, 0x2f, 0x8c, 0x16, 0xa5, 0xcf, - 0xe4, 0x5b, 0xce, 0x46, 0xb5, 0xe3, 0x83, 0xc7, 0x6d, 0xa8, 0x14, 0x8c, 0xb6, 0x40, 0xef, 0x52, 0x3c, 0x06, 0xd1, - 0x9c, 0x67, 0x60, 0xd8, 0x95, 0xbd, 0x02, 0xe4, 0xf3, 0x58, 0x4a, 0x78, 0xf1, 0xbd, 0x5f, 0x94, 0xea, 0xaf, 0x4c, - 0xa9, 0x8e, 0xcc, 0x4c, 0xd2, 0xbc, 0x20, 0x6d, 0xd0, 0xac, 0x46, 0xce, 0xa2, 0xea, 0x57, 0x61, 0x51, 0x09, 0x7b, - 0x94, 0x36, 0xd8, 0x52, 0xc8, 0xf8, 0x1f, 0xd6, 0xc9, 0xf8, 0xef, 0x6f, 0x97, 0xf1, 0xa7, 0x77, 0x13, 0xf1, 0xdf, - 0xff, 0xce, 0x22, 0xfe, 0x07, 0x53, 0xc4, 0x0b, 0x21, 0xb6, 0x07, 0xa6, 0x33, 0xd9, 0xcc, 0xa7, 0xd9, 0x65, 0x0b, - 0xb7, 0x44, 0x6e, 0x93, 0xf4, 0x9c, 0xde, 0x49, 0xf8, 0xaf, 0xc8, 0x07, 0x53, 0x83, 0x19, 0x1f, 0x0f, 0xe6, 0xd9, - 0xd9, 0x59, 0xc2, 0x94, 0x8c, 0x37, 0x2a, 0xc8, 0x1c, 0x7f, 0x97, 0x86, 0xf6, 0x3b, 0xf4, 0x8c, 0xab, 0x92, 0xf1, - 0x18, 0x8a, 0xc6, 0x63, 0x5b, 0xe5, 0x4b, 0x83, 0x3c, 0xa3, 0x56, 0x6f, 0x6b, 0x25, 0xd4, 0xea, 0x8b, 0x2f, 0xcc, - 0x32, 0xb3, 0x40, 0x86, 0xf4, 0x4c, 0x63, 0x44, 0xd6, 0x8c, 0xe2, 0x02, 0xf7, 0x60, 0xf5, 0xb1, 0x63, 0xb4, 0x77, - 0xa6, 0xa0, 0x54, 0xe2, 0x21, 0x9e, 0x8b, 0x34, 0x3f, 0x2c, 0x23, 0x72, 0xdb, 0x97, 0x91, 0xab, 0xce, 0xbf, 0x8d, - 0x6f, 0x18, 0x56, 0x67, 0xde, 0xb0, 0xf8, 0x32, 0xbf, 0xe5, 0xe9, 0xd5, 0xab, 0x91, 0xb3, 0x87, 0x97, 0x7f, 0x8b, - 0x77, 0x69, 0x23, 0x6f, 0x50, 0x80, 0x1d, 0x86, 0x26, 0xa6, 0xa5, 0x20, 0x58, 0x75, 0x81, 0xa2, 0xaa, 0xec, 0x19, - 0x9d, 0x64, 0x7a, 0x19, 0x0e, 0x39, 0xa8, 0x91, 0x25, 0x30, 0x07, 0x93, 0xba, 0x90, 0x3e, 0x66, 0x2f, 0x92, 0x6e, - 0xce, 0xe5, 0x57, 0xcf, 0xe9, 0x70, 0x66, 0x21, 0xf5, 0x87, 0x4c, 0xc7, 0xa8, 0x7a, 0xd2, 0x79, 0x08, 0xcd, 0x30, - 0x2a, 0xd5, 0x19, 0x08, 0x10, 0x6e, 0x86, 0x9f, 0x68, 0x12, 0x43, 0xa8, 0x83, 0x82, 0x8a, 0x7a, 0xd7, 0xd7, 0xe6, - 0x97, 0x42, 0x6b, 0x5f, 0x95, 0x6c, 0xf0, 0x00, 0xc7, 0x4f, 0xfc, 0xa2, 0x36, 0xc8, 0xe6, 0xdc, 0xc1, 0x33, 0x80, - 0x05, 0x1e, 0x31, 0x78, 0x3b, 0xed, 0x36, 0xa8, 0x18, 0x5f, 0x7c, 0x07, 0xca, 0xd1, 0x9d, 0x05, 0xbe, 0x6c, 0xdd, - 0xb9, 0xc4, 0xd2, 0x77, 0xd9, 0x2a, 0x12, 0xdf, 0xbf, 0x2f, 0x11, 0x35, 0xee, 0x0e, 0xa9, 0x45, 0x6c, 0xbe, 0xfb, - 0xca, 0x77, 0x34, 0x08, 0xeb, 0xae, 0xe2, 0x60, 0x99, 0x5b, 0x5b, 0x2f, 0xc4, 0xb6, 0xc2, 0xaa, 0x59, 0x06, 0xe7, - 0x16, 0x9d, 0x59, 0x5c, 0x18, 0x01, 0xfc, 0xda, 0x36, 0x28, 0x55, 0x04, 0x5f, 0x84, 0xe1, 0xf7, 0xd0, 0xc5, 0x15, - 0x8e, 0xb7, 0x02, 0xba, 0xe1, 0xf2, 0x56, 0x90, 0xa3, 0x33, 0xac, 0x19, 0x5d, 0x55, 0xa9, 0x82, 0xd2, 0x3c, 0x82, - 0x31, 0x90, 0xa1, 0x48, 0x3a, 0xac, 0x71, 0x2a, 0xf4, 0x16, 0x4c, 0x43, 0x02, 0x58, 0xfb, 0x75, 0xe8, 0xd6, 0xd8, - 0x0a, 0x6c, 0x21, 0x2d, 0x40, 0xe9, 0x61, 0x87, 0xbe, 0x55, 0x03, 0x3d, 0x5d, 0x0e, 0xc0, 0xdf, 0xe8, 0xe4, 0x9d, - 0xf8, 0xc5, 0x85, 0x07, 0xff, 0xac, 0x3f, 0x2c, 0x40, 0xca, 0x9f, 0x7e, 0x8a, 0x39, 0xd8, 0xd4, 0xb3, 0x16, 0x86, - 0x5f, 0x28, 0x4e, 0x2b, 0xd5, 0x21, 0x1d, 0x45, 0x8b, 0x2b, 0x63, 0xbd, 0x79, 0x81, 0xbe, 0x20, 0x39, 0x3d, 0x41, - 0x9a, 0xa5, 0xac, 0x57, 0x4f, 0x39, 0x30, 0xfd, 0x0e, 0x45, 0xac, 0xa3, 0x45, 0x86, 0xbe, 0x23, 0xbf, 0x02, 0xdf, - 0x51, 0xa8, 0xd1, 0xb6, 0x72, 0x3a, 0xda, 0x2b, 0xdb, 0x07, 0x92, 0xb6, 0x9b, 0x64, 0x2d, 0xe4, 0xcb, 0xce, 0xd5, - 0x3a, 0xe7, 0xe8, 0xb6, 0x03, 0x78, 0x0c, 0x0a, 0xab, 0x7f, 0x46, 0xe6, 0x42, 0xb3, 0x98, 0x0e, 0xe0, 0xef, 0x02, - 0x59, 0x10, 0x8d, 0xf1, 0x0b, 0x8b, 0x77, 0x69, 0x79, 0x4a, 0xd9, 0xaf, 0x0b, 0x54, 0xeb, 0x41, 0xe7, 0x09, 0x78, - 0x7b, 0x77, 0x1e, 0xfe, 0x66, 0xf4, 0x4b, 0x49, 0x23, 0x75, 0x89, 0xd9, 0xb6, 0x7b, 0x28, 0x2f, 0x92, 0xe8, 0x0a, - 0x9c, 0x4e, 0xb2, 0x31, 0x4e, 0x31, 0x7a, 0xdc, 0x9b, 0x65, 0x32, 0x93, 0x24, 0x67, 0x09, 0xfd, 0x8c, 0x89, 0x5c, - 0x8a, 0xed, 0x47, 0xb3, 0x4b, 0xb5, 0x1a, 0x9d, 0x46, 0x86, 0xc8, 0xef, 0x9a, 0x08, 0xb2, 0x3e, 0xf3, 0xa4, 0x9e, - 0xcc, 0xb0, 0x03, 0x30, 0x08, 0xc3, 0xa6, 0x95, 0x0b, 0xa8, 0xda, 0x50, 0x62, 0xa4, 0xc2, 0x54, 0x03, 0x59, 0xfe, - 0x36, 0xa8, 0xca, 0xa8, 0x60, 0x3d, 0xfc, 0xd4, 0x65, 0x0c, 0xae, 0xad, 0x34, 0x9e, 0xa6, 0xf1, 0x68, 0x94, 0xb0, - 0x9e, 0xb2, 0x8f, 0xac, 0xce, 0x23, 0xcc, 0x24, 0x31, 0x97, 0xac, 0xbe, 0x2a, 0x06, 0xf1, 0x34, 0x9d, 0xa2, 0x53, - 0xb0, 0xd7, 0xf0, 0x7b, 0x95, 0x2b, 0xc9, 0x29, 0x53, 0x2c, 0xda, 0x15, 0xf1, 0xe8, 0xb9, 0x8e, 0xcb, 0x0e, 0x18, - 0x8b, 0xb4, 0xe0, 0xed, 0x1e, 0xcf, 0x66, 0x41, 0x6b, 0xbb, 0x8e, 0x08, 0x56, 0x69, 0x14, 0xbc, 0x15, 0x68, 0x79, - 0x68, 0x1d, 0x08, 0x2d, 0x67, 0xf9, 0x1d, 0x59, 0x46, 0x03, 0xe0, 0x37, 0x11, 0x75, 0x51, 0x59, 0x47, 0xe6, 0xaf, - 0xb3, 0x5b, 0x3e, 0x5f, 0xbd, 0x5b, 0x3e, 0x57, 0xbb, 0xe5, 0x66, 0x8e, 0xfd, 0x6c, 0xdc, 0xc1, 0xff, 0x7a, 0x15, - 0x42, 0xb0, 0x2a, 0x40, 0x0e, 0x0b, 0xed, 0xe2, 0x56, 0x17, 0xfe, 0x8f, 0x86, 0x6e, 0x7b, 0xf8, 0x9f, 0x0f, 0x16, - 0x60, 0xdb, 0xc2, 0x42, 0xfc, 0xd7, 0xae, 0x55, 0x75, 0x1e, 0x62, 0x1d, 0xf6, 0xda, 0x59, 0xae, 0xeb, 0xde, 0xbc, - 0x69, 0x41, 0x5e, 0x71, 0x27, 0x50, 0xc2, 0x18, 0x5c, 0xb5, 0xe8, 0xf4, 0x14, 0x4a, 0xc7, 0xd9, 0x70, 0x5e, 0xfc, - 0xad, 0x84, 0x5f, 0x12, 0xf1, 0xc6, 0x2d, 0xdd, 0x18, 0x47, 0x75, 0x15, 0x69, 0x49, 0x6a, 0x84, 0x85, 0x5e, 0xa7, - 0xa0, 0x00, 0xc6, 0x64, 0x4e, 0xd7, 0x7f, 0xb8, 0x62, 0x13, 0xfc, 0x7f, 0x59, 0x9b, 0x95, 0xc8, 0xfc, 0x47, 0x89, - 0x71, 0x23, 0x11, 0x7e, 0x15, 0x0d, 0xcc, 0x35, 0x6c, 0x3f, 0x59, 0x0d, 0xee, 0xa1, 0x9a, 0xe9, 0x48, 0x29, 0x05, - 0xa9, 0x77, 0xc0, 0x0b, 0x88, 0xe6, 0x09, 0xbf, 0x79, 0xd4, 0x75, 0x9c, 0xb1, 0x34, 0xea, 0x0d, 0x02, 0xbd, 0x6a, - 0x7b, 0x47, 0x29, 0xfd, 0xd9, 0xe7, 0x0f, 0xf1, 0x3f, 0x11, 0x38, 0x3b, 0xad, 0x7c, 0x23, 0x11, 0x1b, 0x40, 0xdf, - 0x68, 0x5a, 0x73, 0x7e, 0x84, 0x06, 0x27, 0xff, 0xe7, 0xae, 0xad, 0xd1, 0x58, 0xbf, 0x53, 0x73, 0x69, 0x95, 0xfe, - 0xaa, 0xd6, 0xbf, 0x6e, 0xf0, 0x3b, 0xb6, 0x1d, 0x0a, 0x87, 0xa0, 0xde, 0x56, 0xc6, 0x03, 0x97, 0x1a, 0x2b, 0x8a, - 0xdf, 0xb5, 0x7d, 0x65, 0x12, 0x53, 0x8f, 0x69, 0x78, 0xaa, 0x9d, 0x48, 0x79, 0x78, 0x8f, 0x3d, 0x84, 0x1f, 0xf9, - 0x25, 0x0b, 0x1f, 0xe0, 0xd7, 0xd8, 0xac, 0xcb, 0x69, 0x92, 0x82, 0x59, 0x35, 0xe1, 0x7c, 0x16, 0x6c, 0x6d, 0x5d, - 0x5c, 0x5c, 0xf8, 0x17, 0xdb, 0x7e, 0x96, 0x9f, 0x6d, 0x75, 0xdb, 0xed, 0x36, 0x7e, 0x44, 0xcb, 0xb6, 0xce, 0x63, - 0x76, 0xf1, 0x14, 0xdc, 0x0f, 0xfb, 0xb1, 0xf5, 0xc4, 0x7a, 0xbc, 0x6d, 0xed, 0x3c, 0xb2, 0x2d, 0x52, 0x00, 0x50, - 0xb2, 0x6d, 0x5b, 0x42, 0x01, 0x84, 0x36, 0x14, 0xf7, 0x77, 0xcf, 0x94, 0x0d, 0x87, 0x97, 0x14, 0x84, 0x85, 0x04, - 0xfe, 0x5b, 0xf6, 0x89, 0xd5, 0xb7, 0xba, 0x28, 0x6b, 0x49, 0x35, 0xa2, 0x5e, 0x71, 0xbf, 0x0f, 0xa3, 0x59, 0x40, - 0x6c, 0x64, 0x16, 0x62, 0x98, 0x4c, 0x94, 0xd2, 0x14, 0x68, 0x97, 0x9e, 0xc2, 0x13, 0x66, 0xb5, 0x59, 0xf0, 0xfc, - 0xa6, 0xfb, 0x18, 0x74, 0xdc, 0x79, 0xeb, 0xe1, 0xb0, 0xdd, 0xea, 0x58, 0x9d, 0x56, 0xd7, 0x7f, 0x6c, 0x75, 0xc5, - 0xff, 0x83, 0x8c, 0xdc, 0xb6, 0x3a, 0xf0, 0xb4, 0x6d, 0xc1, 0xfb, 0xf9, 0x43, 0x91, 0x5b, 0x12, 0xd9, 0x5b, 0xfd, - 0x5d, 0xfc, 0x4d, 0x29, 0x40, 0xea, 0x73, 0x5b, 0xfc, 0x0a, 0x9e, 0xfd, 0x99, 0x59, 0xda, 0x79, 0xb2, 0xb2, 0xb8, - 0xfb, 0x78, 0x65, 0xf1, 0xf6, 0xa3, 0x95, 0xc5, 0x0f, 0x77, 0xea, 0xc5, 0x5b, 0x67, 0xa2, 0x4a, 0xcb, 0x85, 0xd0, - 0x9e, 0x46, 0xc0, 0x28, 0x97, 0x4e, 0x07, 0xe0, 0x6c, 0x5b, 0x2d, 0xfc, 0xf3, 0xb8, 0xeb, 0xea, 0x5e, 0xa7, 0xd8, - 0x4b, 0x63, 0xf9, 0xf8, 0x09, 0x60, 0xf9, 0xb2, 0xfb, 0x68, 0x88, 0xed, 0x08, 0x51, 0xf8, 0x77, 0xbe, 0xfd, 0x64, - 0x08, 0x1a, 0xc1, 0xc2, 0x7f, 0xf0, 0xdf, 0x64, 0xa7, 0x3b, 0x14, 0x2f, 0x6d, 0xac, 0xff, 0xb6, 0xf3, 0xb8, 0x80, - 0xa6, 0xf8, 0xdf, 0x2f, 0xda, 0x84, 0x46, 0x03, 0xde, 0x1c, 0xf7, 0x21, 0xd0, 0xe8, 0xc9, 0xa4, 0xeb, 0x7f, 0x7e, - 0xfe, 0xd8, 0x7f, 0x32, 0xe9, 0x3c, 0xfe, 0x56, 0xbc, 0x25, 0x40, 0xc1, 0xcf, 0xf1, 0xdf, 0xb7, 0xdb, 0xed, 0x49, - 0xab, 0xe3, 0x3f, 0x39, 0xdf, 0xf6, 0xb7, 0x93, 0xd6, 0x23, 0xff, 0x09, 0xfe, 0xab, 0x86, 0x9b, 0x64, 0x53, 0x66, - 0x5b, 0xb8, 0xde, 0x0d, 0xbf, 0xd7, 0x9c, 0xa3, 0xfb, 0xd0, 0xda, 0x79, 0xf8, 0xf2, 0x09, 0xac, 0xd1, 0xa4, 0xd3, - 0x85, 0xff, 0x5f, 0xf7, 0xf8, 0x2d, 0x12, 0x5e, 0x0e, 0x1c, 0x31, 0x4c, 0x2f, 0x56, 0x84, 0xa3, 0x0f, 0xba, 0x3d, - 0xf0, 0xfe, 0xb4, 0x2e, 0x00, 0xc2, 0xf8, 0xad, 0x01, 0x10, 0xce, 0xef, 0x16, 0x01, 0xa1, 0x5f, 0x1b, 0xf8, 0x1d, - 0x23, 0x20, 0x7f, 0x6a, 0x06, 0xb9, 0x2f, 0xd9, 0x52, 0xa0, 0xa3, 0xe9, 0xac, 0xbd, 0x65, 0xce, 0xe1, 0x97, 0xf8, - 0xe3, 0x06, 0x65, 0x0f, 0x5a, 0x73, 0x6e, 0xc6, 0x83, 0x32, 0xdc, 0xc8, 0x97, 0xf2, 0xe2, 0x43, 0xc1, 0xd7, 0x10, - 0x24, 0xbe, 0x9d, 0x20, 0xdf, 0xde, 0x8d, 0x1e, 0xf1, 0xef, 0x4c, 0x8f, 0x82, 0x1b, 0xf4, 0xa8, 0x45, 0xdc, 0x29, - 0x62, 0x40, 0x8e, 0xfe, 0x3e, 0xbd, 0x3b, 0x9c, 0xbe, 0xc5, 0xb6, 0xc5, 0xb0, 0xa8, 0xb0, 0x45, 0xce, 0xe6, 0xd3, - 0x5f, 0x73, 0x44, 0x20, 0xd2, 0xcd, 0x43, 0x5b, 0x46, 0x61, 0x66, 0xf8, 0xd1, 0x62, 0xf5, 0x72, 0x2e, 0xae, 0x34, - 0x85, 0x74, 0x1f, 0x71, 0x47, 0x47, 0x70, 0xf0, 0x06, 0x40, 0xb8, 0xc8, 0x78, 0x84, 0xbf, 0x8a, 0x05, 0xe4, 0xa6, - 0xdf, 0xcf, 0x8a, 0x79, 0xc2, 0x30, 0x9d, 0x66, 0x28, 0x3e, 0x20, 0x0b, 0x8f, 0xf2, 0xae, 0x21, 0xa6, 0xb0, 0x7f, - 0x83, 0xe9, 0xf7, 0xea, 0xec, 0x60, 0x8a, 0x71, 0x84, 0x37, 0x6c, 0x14, 0x47, 0x8e, 0xed, 0xcc, 0x60, 0x23, 0xc3, - 0x2c, 0xad, 0x5a, 0xee, 0x3b, 0xa5, 0xbd, 0xbb, 0xb6, 0xfa, 0x69, 0xa6, 0x1c, 0x3f, 0x75, 0x17, 0x1e, 0xca, 0xb8, - 0xa3, 0x2d, 0x1d, 0x03, 0x18, 0x5f, 0x95, 0xe4, 0xa8, 0x03, 0x2a, 0x63, 0xc2, 0x16, 0xd6, 0x44, 0xc7, 0xef, 0x82, - 0x77, 0x41, 0xc5, 0xf8, 0xe9, 0xb0, 0xef, 0x9d, 0xd6, 0x36, 0x58, 0x3b, 0x46, 0x37, 0x3d, 0xd0, 0x91, 0xfe, 0xa5, - 0x1f, 0xfd, 0x6b, 0x74, 0xf5, 0x0b, 0x03, 0xb6, 0xe0, 0x88, 0xcf, 0x04, 0xee, 0xb6, 0xf8, 0x44, 0x83, 0x48, 0x28, - 0xc1, 0x0b, 0x73, 0x50, 0xe6, 0x98, 0xbf, 0x4a, 0x26, 0x3e, 0x4d, 0x26, 0x7e, 0x80, 0xb0, 0xac, 0x9a, 0x70, 0x77, - 0x41, 0x67, 0x23, 0xf8, 0x23, 0x9a, 0x98, 0x68, 0x8a, 0xa1, 0xf2, 0xd0, 0xa0, 0x29, 0xbe, 0xbb, 0x35, 0x22, 0x73, - 0x4f, 0x03, 0x44, 0x04, 0x0e, 0xe5, 0xdf, 0xaa, 0x58, 0x3d, 0xc8, 0xa0, 0x16, 0x38, 0xfa, 0xf8, 0xb3, 0x2f, 0xf4, - 0x67, 0x29, 0x64, 0x26, 0x02, 0x21, 0x8d, 0xd2, 0x6a, 0xa8, 0x2a, 0x34, 0x56, 0x3c, 0xbd, 0x3a, 0x90, 0xdf, 0x3c, - 0xb0, 0x31, 0x4a, 0x4d, 0xa7, 0x13, 0xd5, 0xf7, 0xd6, 0x36, 0x41, 0x35, 0xd2, 0xaf, 0xa0, 0x52, 0x82, 0x01, 0x6a, - 0x3f, 0xbc, 0x72, 0x60, 0x49, 0x2f, 0x29, 0xb4, 0x85, 0xee, 0x1b, 0xb1, 0xf3, 0x78, 0x28, 0x55, 0x98, 0x67, 0xc9, - 0xab, 0x52, 0x2d, 0x5a, 0x9a, 0xb0, 0xe3, 0x89, 0x38, 0x01, 0xbc, 0xa0, 0x06, 0x0f, 0xd3, 0xcc, 0xee, 0x3f, 0xe8, - 0xad, 0x23, 0x3e, 0xfe, 0x24, 0xeb, 0x21, 0xf8, 0xa5, 0x7f, 0x1b, 0x3e, 0xc0, 0x1f, 0x65, 0x7d, 0x70, 0x64, 0xbb, - 0x3e, 0x29, 0x80, 0x07, 0xd5, 0x2f, 0xb3, 0xa2, 0xf4, 0xdb, 0x04, 0x5d, 0xed, 0xdd, 0x55, 0x69, 0x4b, 0x05, 0xdd, - 0xdd, 0xa9, 0x14, 0x34, 0x3c, 0x1b, 0x12, 0x19, 0x94, 0x45, 0xd7, 0xdf, 0x31, 0xc4, 0xfe, 0x79, 0x0b, 0xff, 0xd6, - 0x04, 0xff, 0x43, 0x68, 0xa0, 0x24, 0xff, 0x6b, 0x68, 0xbe, 0x2d, 0x94, 0x0c, 0xf4, 0xfb, 0x81, 0xc4, 0xb2, 0x10, - 0xc9, 0xf5, 0x6d, 0xb0, 0xe2, 0xc0, 0x4c, 0x24, 0x63, 0xd8, 0x9e, 0x11, 0x5b, 0x13, 0xbb, 0x52, 0x46, 0x8e, 0x9e, - 0x43, 0x5f, 0x47, 0x7f, 0xc6, 0x7c, 0x55, 0x9d, 0x57, 0x93, 0x12, 0x2b, 0xa6, 0xc0, 0x7d, 0xdd, 0x38, 0x94, 0xeb, - 0x89, 0x3c, 0x6f, 0xfd, 0x1d, 0x94, 0xf5, 0x0c, 0x2d, 0x13, 0xc2, 0x5d, 0x43, 0x44, 0x30, 0xfa, 0xd4, 0x2a, 0x4d, - 0xf2, 0x6a, 0x54, 0x36, 0xe7, 0x07, 0xb3, 0x06, 0x7f, 0x97, 0xb2, 0xba, 0xe5, 0x23, 0xaf, 0xef, 0x62, 0xca, 0xc5, - 0x28, 0xce, 0xe9, 0x56, 0xb8, 0x02, 0xbd, 0x16, 0x78, 0xad, 0xa8, 0x44, 0x52, 0x82, 0x15, 0x03, 0x1b, 0x8b, 0xec, - 0x40, 0x26, 0x06, 0x9a, 0xdf, 0x1a, 0x37, 0xaf, 0xed, 0x8e, 0x44, 0x4e, 0x20, 0xfe, 0x16, 0x83, 0x2d, 0xe8, 0x63, - 0x83, 0xb4, 0x5d, 0xbb, 0x4b, 0xc8, 0x06, 0x43, 0x5c, 0xab, 0x1f, 0xd7, 0x32, 0x05, 0x90, 0x6d, 0x12, 0x5a, 0x8f, - 0x4b, 0x24, 0x74, 0x25, 0x9d, 0x4e, 0x59, 0xc4, 0xfd, 0x28, 0xa5, 0xfc, 0x2d, 0xc7, 0x10, 0x53, 0x5e, 0x87, 0x6d, - 0xbb, 0x25, 0xc8, 0x46, 0xe3, 0xd7, 0xc7, 0xe4, 0xee, 0x86, 0x42, 0xfd, 0xe5, 0xab, 0x7a, 0x2e, 0xf6, 0xa4, 0xdb, - 0x7f, 0x77, 0xb0, 0x67, 0x89, 0x4d, 0xb9, 0xbb, 0x05, 0xaf, 0xbb, 0xe4, 0xc1, 0x8b, 0x54, 0x96, 0x50, 0xa4, 0xb2, - 0x58, 0x22, 0x01, 0x4e, 0xe4, 0x2e, 0x6f, 0x09, 0xb4, 0x6d, 0x8b, 0xa5, 0x43, 0x11, 0x7a, 0x9c, 0x82, 0x97, 0x13, - 0xe3, 0xf7, 0xe9, 0xb6, 0xb0, 0x6b, 0x0b, 0x17, 0xcc, 0x56, 0x59, 0x41, 0xca, 0xae, 0xe1, 0xa9, 0x0a, 0x54, 0x82, - 0x35, 0xc2, 0x54, 0x82, 0x90, 0x1c, 0x4a, 0xe7, 0x25, 0x2f, 0xb7, 0x2e, 0xe6, 0xa7, 0x53, 0x90, 0x93, 0x2a, 0xa9, - 0xe7, 0xa3, 0xec, 0xb0, 0x4b, 0x53, 0xf5, 0x4f, 0x4a, 0x19, 0x49, 0x55, 0xdf, 0x0e, 0x6f, 0xfc, 0xce, 0xaa, 0xc0, - 0x5e, 0xea, 0x05, 0xcc, 0x49, 0x99, 0x6c, 0x1b, 0x39, 0x29, 0x46, 0x5d, 0x09, 0xa8, 0x6f, 0xf7, 0x4f, 0x82, 0x99, - 0x1c, 0xef, 0x75, 0xb6, 0xf4, 0x9b, 0xad, 0x5a, 0x4e, 0x0e, 0x28, 0xbf, 0x5c, 0xdc, 0xeb, 0x90, 0x00, 0xc3, 0x0a, - 0x02, 0x4c, 0xd2, 0x04, 0xb0, 0xe8, 0xe8, 0xdb, 0xde, 0x69, 0xab, 0xb4, 0x5d, 0x28, 0xc3, 0x0d, 0x29, 0xba, 0x18, - 0x93, 0xd4, 0xc2, 0xbf, 0x93, 0x4e, 0x7f, 0x37, 0x92, 0xc6, 0x25, 0x0a, 0x8f, 0x02, 0xa4, 0x07, 0x74, 0x46, 0x0b, - 0xce, 0x8f, 0xb3, 0xad, 0x0b, 0x76, 0xda, 0x8a, 0x66, 0x71, 0x15, 0x6b, 0x45, 0x53, 0x43, 0x4f, 0x99, 0x55, 0x33, - 0xe1, 0x63, 0xd4, 0x40, 0x92, 0x04, 0x77, 0x29, 0x03, 0xb9, 0x64, 0xa1, 0x03, 0x0b, 0x01, 0x85, 0x49, 0xae, 0xab, - 0x80, 0xaf, 0xd4, 0xb8, 0xa5, 0xdd, 0xff, 0xcb, 0x3f, 0xff, 0x6f, 0x19, 0xc3, 0x05, 0xaa, 0x74, 0xd4, 0x58, 0x0d, - 0x42, 0x97, 0xbb, 0x98, 0x02, 0x55, 0x9d, 0xf2, 0xb2, 0xcb, 0xd6, 0x59, 0x1e, 0x8f, 0x5a, 0x93, 0x28, 0x19, 0x03, - 0x60, 0x6b, 0x09, 0x64, 0x26, 0x48, 0x48, 0xa8, 0xeb, 0x45, 0xc8, 0x82, 0xbf, 0x29, 0x11, 0x5b, 0x25, 0xc0, 0xd3, - 0x6e, 0x35, 0xd3, 0xb2, 0xab, 0x0d, 0x55, 0x4b, 0xcd, 0x56, 0x3f, 0x5c, 0xa6, 0x84, 0x5a, 0x2d, 0x2f, 0x1b, 0x5a, - 0xea, 0xc3, 0xa8, 0x7f, 0xff, 0x97, 0x7f, 0xf8, 0x1f, 0xea, 0x15, 0xcf, 0x98, 0xfe, 0xf2, 0x4f, 0x7f, 0x87, 0x29, - 0xd0, 0x96, 0x3e, 0x87, 0x22, 0x39, 0x61, 0x55, 0x87, 0x50, 0x42, 0x60, 0x58, 0x95, 0xd3, 0x57, 0xcf, 0xdf, 0xde, - 0xa7, 0x09, 0x69, 0xb3, 0x49, 0xe8, 0x68, 0xd3, 0x96, 0x15, 0x8f, 0xd4, 0x48, 0x4e, 0xbc, 0x08, 0x95, 0x48, 0xef, - 0x3b, 0x25, 0x47, 0xf9, 0x7a, 0x35, 0x16, 0x2a, 0x42, 0x88, 0x25, 0x65, 0x55, 0x6e, 0x61, 0xe8, 0x7e, 0x81, 0xaf, - 0x41, 0xd7, 0x28, 0xa6, 0xc5, 0xab, 0xf5, 0xe9, 0xfd, 0x34, 0x07, 0xf8, 0xc7, 0x48, 0x71, 0x11, 0x87, 0xa4, 0x63, - 0xe9, 0x16, 0xda, 0x7c, 0xc9, 0x55, 0x49, 0xa3, 0x08, 0x47, 0xf1, 0xe1, 0x93, 0xbf, 0x29, 0xff, 0x38, 0x45, 0xcb, - 0xca, 0x72, 0xa6, 0xd1, 0xa5, 0x74, 0x1f, 0x1f, 0xb5, 0xdb, 0xb3, 0x4b, 0x77, 0x51, 0xcd, 0xe0, 0xad, 0x9b, 0x8c, - 0x62, 0x97, 0xe6, 0x80, 0x74, 0x9e, 0xad, 0xc3, 0xa4, 0xe0, 0x31, 0xb5, 0x31, 0xaa, 0x56, 0x96, 0x7f, 0x58, 0x50, - 0xa4, 0x2e, 0xfe, 0x05, 0xcf, 0x9d, 0x65, 0x50, 0x13, 0x4a, 0x0c, 0x2c, 0x16, 0x46, 0xaf, 0xae, 0xe8, 0x35, 0xe9, - 0x2c, 0xa7, 0x0d, 0x99, 0xe7, 0xe6, 0xe6, 0x89, 0xf7, 0x43, 0x3c, 0xc3, 0x9e, 0x74, 0xbc, 0x49, 0x77, 0xa1, 0x87, - 0xe7, 0x3c, 0x9b, 0x9a, 0x07, 0xe5, 0x2c, 0x62, 0x43, 0x36, 0x56, 0xc1, 0x60, 0x59, 0x2f, 0x0e, 0xc1, 0xcb, 0xc9, - 0xf6, 0x8a, 0xb9, 0x24, 0x48, 0x74, 0x40, 0x0e, 0xf0, 0x7c, 0x86, 0x1b, 0x10, 0xe8, 0x9f, 0x45, 0x3c, 0x20, 0x7e, - 0xed, 0x99, 0xc7, 0xed, 0x11, 0x4a, 0x99, 0x6c, 0x61, 0xc0, 0xd3, 0x13, 0x4d, 0x31, 0x2c, 0x5b, 0x4f, 0xdb, 0x2a, - 0x7d, 0xea, 0x6e, 0x0e, 0x25, 0xa2, 0x3a, 0xdf, 0xca, 0x53, 0xec, 0xa7, 0xb5, 0x70, 0x88, 0x54, 0x31, 0x5d, 0xd7, - 0x5b, 0x59, 0x2f, 0x34, 0xb5, 0xa8, 0xfd, 0x16, 0x0c, 0x30, 0x02, 0xd3, 0x6e, 0xb6, 0xa2, 0x42, 0x6c, 0xf5, 0x34, - 0xfc, 0x56, 0xbb, 0x3e, 0xd1, 0x6c, 0x46, 0x0d, 0x5d, 0x60, 0x62, 0x32, 0x58, 0x51, 0x76, 0x50, 0x86, 0x86, 0x48, - 0x88, 0x90, 0x6d, 0xe4, 0x46, 0x10, 0x4f, 0x32, 0x55, 0x02, 0x7f, 0x72, 0xa2, 0xff, 0xff, 0x00, 0x69, 0x5b, 0x88, - 0x58, 0x18, 0x7f, 0x00, 0x00}; + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc5, 0x7d, 0xd9, 0x76, 0xe3, 0xc6, 0x92, 0xe0, 0xf3, + 0x9c, 0x33, 0x7f, 0x30, 0x2f, 0x10, 0x4a, 0xad, 0x02, 0xae, 0x40, 0x88, 0xa4, 0x6a, 0x33, 0x28, 0x90, 0x57, 0xb5, + 0xd8, 0x55, 0x76, 0x6d, 0x2e, 0xa9, 0xec, 0x6b, 0xcb, 0xb4, 0x04, 0x91, 0x49, 0x11, 0x2e, 0x10, 0xa0, 0x81, 0xa4, + 0x16, 0x53, 0xe8, 0x33, 0x4f, 0xf3, 0xd4, 0xe7, 0xcc, 0xd6, 0x0f, 0xfd, 0x30, 0x7d, 0xba, 0x1f, 0xe6, 0x23, 0xe6, + 0xb9, 0x3f, 0xe5, 0xfe, 0xc0, 0xf4, 0x27, 0x4c, 0x44, 0xe4, 0x82, 0x04, 0x17, 0x49, 0x5e, 0xba, 0xe7, 0xd8, 0x2a, + 0x12, 0xb9, 0x46, 0x44, 0x46, 0xc6, 0x96, 0x91, 0xe0, 0xde, 0xc6, 0x30, 0x1b, 0xf0, 0xab, 0x29, 0xb3, 0xc6, 0x7c, + 0x92, 0x74, 0xf7, 0xe4, 0xbf, 0x2c, 0x1a, 0x76, 0xf7, 0x92, 0x38, 0xfd, 0x64, 0xe5, 0x2c, 0x09, 0xe3, 0x41, 0x96, + 0x5a, 0xe3, 0x9c, 0x8d, 0xc2, 0x61, 0xc4, 0xa3, 0x20, 0x9e, 0x44, 0x67, 0xcc, 0xda, 0xe9, 0xee, 0x4d, 0x18, 0x8f, + 0xac, 0xc1, 0x38, 0xca, 0x0b, 0xc6, 0xc3, 0x8f, 0x87, 0x9f, 0x37, 0x9e, 0x74, 0xf7, 0x8a, 0x41, 0x1e, 0x4f, 0xb9, + 0x85, 0x43, 0x86, 0x93, 0x6c, 0x38, 0x4b, 0x58, 0xf7, 0x3c, 0xca, 0xad, 0x17, 0x3c, 0x7c, 0x77, 0xfa, 0x13, 0x1b, + 0x70, 0x7f, 0xc8, 0x46, 0x71, 0xca, 0xde, 0xe7, 0xd9, 0x94, 0xe5, 0xfc, 0xca, 0x3b, 0x58, 0x5d, 0x11, 0xb3, 0xc2, + 0x7b, 0xa6, 0xab, 0xce, 0x18, 0x7f, 0x77, 0x91, 0xaa, 0x3e, 0xcf, 0x99, 0x98, 0x24, 0xcb, 0x0b, 0xaf, 0x58, 0xd3, + 0xe6, 0xe0, 0x6a, 0x72, 0x9a, 0x25, 0x85, 0xf7, 0x49, 0xd7, 0x4f, 0xf3, 0x8c, 0x67, 0x08, 0x96, 0x3f, 0x8e, 0x0a, + 0xa3, 0xa5, 0xf7, 0x6e, 0x45, 0x93, 0xa9, 0xac, 0x7c, 0x55, 0xbc, 0x48, 0x67, 0x13, 0x96, 0x47, 0xa7, 0x09, 0xf3, + 0x72, 0x1e, 0x3a, 0xdc, 0x63, 0x5e, 0xec, 0x86, 0x5d, 0x66, 0xc5, 0xa9, 0xc5, 0x7b, 0x2f, 0x38, 0x95, 0xcc, 0x99, + 0x6e, 0x15, 0x6c, 0x34, 0x3d, 0x20, 0xd7, 0x28, 0x3e, 0x9b, 0xe9, 0xe7, 0x8b, 0x3c, 0xe6, 0xea, 0xfb, 0x79, 0x94, + 0xcc, 0x58, 0x10, 0x97, 0x6e, 0xc0, 0x8f, 0x58, 0x3f, 0x8c, 0xbd, 0x4f, 0x34, 0x28, 0x0c, 0x39, 0x1f, 0x65, 0xb9, + 0x83, 0xb4, 0x8a, 0x71, 0x6c, 0x76, 0x7d, 0xed, 0xb0, 0x70, 0x5e, 0xba, 0xee, 0x27, 0xee, 0x0f, 0xa2, 0x24, 0x71, + 0x70, 0xe2, 0xad, 0xad, 0x1c, 0x67, 0x8c, 0x3d, 0x76, 0x14, 0xf7, 0xdd, 0x4e, 0x3c, 0x72, 0x0a, 0xee, 0x56, 0xfd, + 0xb2, 0x91, 0x55, 0x70, 0x87, 0xb9, 0xee, 0xbb, 0xf5, 0x7d, 0x72, 0xc6, 0x67, 0x39, 0xc0, 0x5e, 0x7a, 0xef, 0xd4, + 0xcc, 0x07, 0x58, 0xff, 0x8c, 0x3a, 0x76, 0x00, 0xf6, 0x82, 0x5b, 0x9f, 0x87, 0x17, 0x71, 0x3a, 0xcc, 0x2e, 0xfc, + 0x83, 0x71, 0x04, 0x1f, 0x1f, 0xb2, 0x8c, 0x6f, 0x6d, 0x39, 0xe7, 0x59, 0x3c, 0xb4, 0x9a, 0x61, 0x68, 0x56, 0x5e, + 0x3d, 0x3b, 0x38, 0xb8, 0xbe, 0x5e, 0x28, 0xf0, 0xd3, 0x88, 0xc7, 0xe7, 0x4c, 0x74, 0x06, 0x00, 0x6c, 0xf8, 0x9c, + 0x72, 0x36, 0x3c, 0xe0, 0x57, 0x09, 0x94, 0x32, 0xc6, 0x0b, 0x1b, 0x70, 0x7c, 0x9e, 0x0d, 0x80, 0x6c, 0xa9, 0x41, + 0x78, 0x68, 0x9a, 0xb3, 0x69, 0x12, 0x0d, 0x18, 0xd6, 0xc3, 0x48, 0x55, 0x8f, 0xaa, 0x91, 0xf7, 0x6d, 0x28, 0x96, + 0xd7, 0x71, 0xbd, 0x94, 0x87, 0x29, 0xbb, 0xb0, 0xde, 0x44, 0xd3, 0xce, 0x20, 0x89, 0x8a, 0xc2, 0xca, 0xf8, 0x9c, + 0x50, 0xc8, 0x67, 0x03, 0x60, 0x10, 0x42, 0x70, 0x0e, 0x64, 0xe2, 0xe3, 0xb8, 0xf0, 0x8f, 0x37, 0x07, 0x45, 0xf1, + 0x81, 0x15, 0xb3, 0x84, 0x6f, 0x86, 0xb0, 0x16, 0x6c, 0x23, 0x0c, 0xbf, 0x75, 0xf9, 0x38, 0xcf, 0x2e, 0xac, 0x17, + 0x79, 0x0e, 0xcd, 0x6d, 0x98, 0x52, 0x34, 0xb0, 0xe2, 0xc2, 0x4a, 0x33, 0x6e, 0xe9, 0xc1, 0x70, 0x01, 0x7d, 0xeb, + 0x63, 0xc1, 0xac, 0x93, 0x59, 0x5a, 0x44, 0x23, 0x06, 0x4d, 0x4f, 0xac, 0x2c, 0xb7, 0x4e, 0x60, 0xd0, 0x13, 0x58, + 0xb2, 0x82, 0xc3, 0xae, 0xf1, 0x6d, 0xb7, 0x43, 0x73, 0x41, 0xe1, 0x21, 0xbb, 0xe4, 0x21, 0x2f, 0x81, 0x31, 0x61, + 0x55, 0x14, 0x1a, 0x8e, 0x3b, 0x4f, 0xa0, 0x00, 0xc0, 0x26, 0x96, 0x75, 0xcc, 0xc6, 0x7a, 0x71, 0x3e, 0xdf, 0xda, + 0xd2, 0xb4, 0x46, 0xc2, 0x43, 0xdb, 0x62, 0xa1, 0xad, 0x27, 0x10, 0xaf, 0x91, 0xc8, 0xf5, 0xb8, 0x2f, 0xc9, 0x77, + 0x70, 0x95, 0x0e, 0xea, 0x63, 0x43, 0x65, 0xc9, 0xb3, 0x03, 0x9e, 0xc7, 0xe9, 0x19, 0x00, 0xa1, 0xd8, 0xc0, 0x68, + 0x52, 0x96, 0x62, 0xf1, 0xdf, 0x03, 0xd4, 0x61, 0x17, 0x47, 0xcf, 0xb8, 0x63, 0x17, 0xd4, 0xc3, 0x06, 0x40, 0x80, + 0xf4, 0xc0, 0x60, 0xbc, 0xc7, 0x03, 0xbe, 0x6d, 0xdb, 0xde, 0xb7, 0xae, 0x77, 0x81, 0x1c, 0xe4, 0xfb, 0x3e, 0xb1, + 0xaf, 0xe8, 0x1c, 0x87, 0x2d, 0x04, 0xda, 0x4f, 0x58, 0x7a, 0xc6, 0xc7, 0x3d, 0x7e, 0xd4, 0xec, 0x07, 0x0c, 0xa0, + 0x1a, 0xce, 0x06, 0xcc, 0x41, 0x7e, 0xf4, 0x0a, 0xdc, 0x3e, 0xdb, 0x0e, 0x4c, 0x81, 0x0b, 0xb3, 0x41, 0x38, 0xd6, + 0x96, 0xc6, 0x55, 0xb0, 0x29, 0xc0, 0x90, 0xcf, 0x6d, 0xd8, 0x61, 0xa7, 0x2c, 0x37, 0xe0, 0xd0, 0xcd, 0x3a, 0xb5, + 0x15, 0x9c, 0xc1, 0x0a, 0x41, 0x3f, 0x6b, 0x34, 0x4b, 0x07, 0x3c, 0x06, 0xc1, 0x65, 0x6f, 0x03, 0xb8, 0x62, 0xe5, + 0xf4, 0xc2, 0xd9, 0x6e, 0xe9, 0x3a, 0xb1, 0xbb, 0xcd, 0x8f, 0x8a, 0xed, 0x56, 0xdf, 0x43, 0x28, 0x35, 0xf1, 0x25, + 0xe2, 0x31, 0x20, 0x58, 0x7a, 0x1f, 0xb9, 0xde, 0x9e, 0x9f, 0xf7, 0xb8, 0xbf, 0xcc, 0xc7, 0x21, 0xf3, 0x27, 0xd1, + 0x14, 0xb1, 0xe1, 0xc4, 0x03, 0x51, 0x3a, 0x40, 0xe8, 0x6a, 0xeb, 0x82, 0x14, 0xf3, 0x2b, 0x16, 0x70, 0x81, 0x20, + 0xb0, 0x67, 0x5f, 0x44, 0x83, 0x31, 0x6c, 0xf1, 0x8a, 0x70, 0x43, 0xb5, 0x1d, 0x06, 0x39, 0x8b, 0x38, 0x7b, 0x91, + 0x30, 0x7c, 0xc2, 0x15, 0x80, 0x9e, 0xb6, 0xeb, 0x15, 0x6a, 0xdf, 0x25, 0x31, 0x7f, 0x9b, 0xc1, 0x3c, 0x1d, 0xc1, + 0x24, 0xc0, 0xc5, 0xc5, 0xd6, 0x56, 0x8c, 0x2c, 0xb2, 0xcf, 0x61, 0xb5, 0x4e, 0x67, 0x9c, 0x01, 0xbd, 0xb0, 0x85, + 0x0d, 0xd4, 0xf6, 0x62, 0x9f, 0x03, 0x11, 0x9f, 0x65, 0x29, 0x87, 0xe1, 0x00, 0x5e, 0xcd, 0x41, 0x7e, 0x34, 0x9d, + 0xb2, 0x74, 0xf8, 0x6c, 0x1c, 0x27, 0x43, 0xa0, 0x46, 0x09, 0xf8, 0x26, 0x3c, 0x04, 0x3c, 0x01, 0x99, 0xe0, 0x66, + 0x8c, 0x68, 0xf9, 0x90, 0x91, 0x59, 0x68, 0xdb, 0x1d, 0x94, 0x40, 0x12, 0x0b, 0x94, 0x41, 0xb4, 0x70, 0x1f, 0x40, + 0xf4, 0x17, 0x2e, 0xdb, 0x0e, 0x63, 0xbd, 0x8c, 0x92, 0xc0, 0xef, 0x51, 0xd2, 0x00, 0xfd, 0x81, 0x10, 0xbc, 0x83, + 0x82, 0xeb, 0x4b, 0x29, 0x75, 0x22, 0xae, 0x30, 0x04, 0x02, 0x0c, 0x50, 0x82, 0x48, 0x1a, 0xbc, 0xcf, 0x92, 0xab, + 0x51, 0x9c, 0x24, 0x07, 0xb3, 0xe9, 0x34, 0xcb, 0xb9, 0xf7, 0x55, 0x38, 0xe7, 0x59, 0x85, 0x2b, 0x6d, 0xf2, 0xe2, + 0x22, 0xe6, 0x48, 0x50, 0x77, 0x3e, 0x88, 0x60, 0xa9, 0x9f, 0x66, 0x59, 0xc2, 0xa2, 0x14, 0xd0, 0xe0, 0x3d, 0xdb, + 0x0e, 0xd2, 0x59, 0x92, 0x74, 0x4e, 0x61, 0xd8, 0x4f, 0x1d, 0xaa, 0x16, 0x12, 0x3f, 0xa0, 0xef, 0xfb, 0x79, 0x1e, + 0x5d, 0x41, 0x43, 0x6c, 0x03, 0xec, 0x05, 0xab, 0xf5, 0xe5, 0xc1, 0xbb, 0xb7, 0xbe, 0x60, 0xfc, 0x78, 0x74, 0x05, + 0x80, 0x96, 0x95, 0xd4, 0x1c, 0xe5, 0xd9, 0x64, 0x61, 0x6a, 0xa4, 0x43, 0x1c, 0xf2, 0xce, 0x1a, 0x10, 0x62, 0x1a, + 0x19, 0x56, 0x89, 0x9b, 0x10, 0xbc, 0x25, 0x7e, 0x96, 0x95, 0xb8, 0x07, 0x7a, 0xf8, 0x25, 0x10, 0xc5, 0x30, 0xe5, + 0x2d, 0xd0, 0xe6, 0x57, 0xf3, 0x38, 0x24, 0x38, 0xa7, 0xa8, 0x7f, 0x11, 0xc6, 0x41, 0x04, 0xb3, 0xcf, 0xc5, 0x80, + 0xa5, 0x82, 0x38, 0x2e, 0x4b, 0x6f, 0xac, 0x99, 0x18, 0x25, 0x1e, 0x0a, 0x14, 0x16, 0x86, 0xa0, 0x60, 0x38, 0x3c, + 0xb8, 0xde, 0xd7, 0xe1, 0x3c, 0x52, 0xf8, 0xa0, 0x86, 0xc2, 0xfd, 0x15, 0x08, 0x39, 0x81, 0x9a, 0xec, 0x1c, 0xf4, + 0x20, 0xc0, 0xf9, 0x95, 0x07, 0xfa, 0x3f, 0x41, 0x28, 0x36, 0x5a, 0x1e, 0x68, 0xd0, 0x67, 0xe3, 0x28, 0x3d, 0x63, + 0xc3, 0x60, 0xcc, 0x4b, 0x29, 0x79, 0xf7, 0x2d, 0x58, 0x63, 0x60, 0xa7, 0xc2, 0x7a, 0x79, 0xf8, 0xe6, 0xb5, 0x5c, + 0xb9, 0x9a, 0x30, 0x86, 0x45, 0x9a, 0x81, 0x5a, 0x05, 0xb1, 0x2d, 0xc5, 0xf1, 0x0b, 0x2d, 0xbd, 0x45, 0x49, 0x5c, + 0x7c, 0x9c, 0x82, 0x89, 0xc1, 0xde, 0xc3, 0x30, 0x30, 0x7d, 0x08, 0x53, 0x51, 0x39, 0xcc, 0x27, 0x2a, 0x86, 0xba, + 0x08, 0x3a, 0x0b, 0x4c, 0xc5, 0x63, 0xe6, 0xb8, 0x25, 0xb0, 0x2a, 0x8f, 0x07, 0x56, 0x34, 0x1c, 0xbe, 0x4a, 0x63, + 0x1e, 0x47, 0x49, 0xfc, 0x0b, 0x51, 0x72, 0x8e, 0x3c, 0xc6, 0x3a, 0x72, 0x11, 0x00, 0x77, 0xea, 0x91, 0xb8, 0x4a, + 0xc8, 0x6e, 0x10, 0x31, 0x84, 0xb4, 0x4c, 0xc2, 0xa3, 0xbe, 0x04, 0x2f, 0xf1, 0xa7, 0xb3, 0x62, 0x8c, 0x84, 0x95, + 0x03, 0xa3, 0x20, 0xcf, 0x4e, 0x0b, 0x96, 0x9f, 0xb3, 0xa1, 0xe6, 0x80, 0x02, 0xb0, 0xa2, 0xe6, 0x60, 0xbc, 0xd0, + 0x8c, 0x8e, 0xd2, 0xa1, 0x1c, 0x86, 0xea, 0x98, 0x62, 0x96, 0x49, 0x66, 0xd6, 0x16, 0x8e, 0x96, 0x02, 0x8e, 0x30, + 0x2a, 0xa4, 0x24, 0x28, 0x42, 0x85, 0xe1, 0x18, 0xa4, 0x10, 0x73, 0x6b, 0xdb, 0x5c, 0x69, 0xb2, 0x17, 0x33, 0x52, + 0x09, 0x05, 0x74, 0x84, 0x8d, 0x4c, 0x90, 0x16, 0x2e, 0xec, 0x2a, 0x90, 0xf2, 0x12, 0x5c, 0x21, 0x45, 0x94, 0x99, + 0x83, 0x0c, 0x10, 0x7e, 0x4d, 0xba, 0x90, 0xf9, 0xd8, 0x82, 0x21, 0x1b, 0xf8, 0x7a, 0xe5, 0x81, 0xb0, 0x12, 0xef, + 0x0a, 0x11, 0x6f, 0x0d, 0xd8, 0xa4, 0x8b, 0x00, 0x30, 0x6f, 0x83, 0xf9, 0x69, 0xb6, 0x3f, 0x18, 0xb0, 0xa2, 0xc8, + 0xf2, 0xad, 0xad, 0x0d, 0x6a, 0xbf, 0xce, 0xd0, 0x02, 0x4a, 0xba, 0x5a, 0xd6, 0xd9, 0x05, 0x69, 0x70, 0x53, 0xad, + 0x28, 0x9d, 0x1e, 0xd8, 0xc7, 0xc7, 0x20, 0xb3, 0x3d, 0x49, 0x06, 0xa0, 0xfa, 0xb2, 0xe1, 0x27, 0xec, 0x99, 0x3a, + 0x65, 0x56, 0xda, 0x97, 0x4e, 0x1d, 0x24, 0x0f, 0x86, 0x75, 0x4b, 0x63, 0x41, 0x57, 0x0e, 0x8d, 0xab, 0x21, 0x15, + 0xe4, 0xfc, 0x8c, 0x54, 0xb6, 0xb1, 0x8c, 0x60, 0xb5, 0x95, 0x1e, 0x91, 0x5e, 0x61, 0x93, 0x13, 0xa0, 0x47, 0xbc, + 0xdf, 0x91, 0xf5, 0x61, 0x21, 0x28, 0x97, 0xb3, 0x9f, 0x67, 0xac, 0xe0, 0x82, 0x75, 0x61, 0xdc, 0x1c, 0xc6, 0x2d, + 0x97, 0xac, 0xc3, 0x9a, 0xed, 0xb8, 0x0a, 0xb6, 0x77, 0x53, 0xd4, 0x63, 0x05, 0x72, 0xf2, 0xcd, 0xec, 0x44, 0xf6, + 0x84, 0x7b, 0x7d, 0xfd, 0xb5, 0x1a, 0xa4, 0x5a, 0x4a, 0x6d, 0x03, 0x2d, 0xac, 0x89, 0xad, 0x9a, 0x0c, 0x6d, 0x57, + 0x2a, 0xd4, 0x8d, 0x56, 0xa7, 0xc6, 0x07, 0xb0, 0xe7, 0x9a, 0x9a, 0xa5, 0x2b, 0x63, 0xfb, 0xbd, 0xa2, 0xe9, 0x3b, + 0x31, 0x32, 0x59, 0xa3, 0xfc, 0x76, 0xee, 0x51, 0x3b, 0x1e, 0xda, 0x2e, 0xd5, 0x55, 0x82, 0x61, 0x56, 0x17, 0x0c, + 0x8b, 0x50, 0x4f, 0x75, 0x17, 0x5b, 0x33, 0x15, 0x0f, 0xd5, 0x5a, 0x2b, 0x07, 0x82, 0x85, 0x47, 0x60, 0x9c, 0xac, + 0xf4, 0x0f, 0xde, 0x46, 0x13, 0x86, 0x14, 0xf5, 0xd6, 0x35, 0x90, 0x0e, 0x04, 0x34, 0xe9, 0x2f, 0xaa, 0x37, 0xe6, + 0x0a, 0xab, 0xa9, 0xbe, 0xbf, 0x62, 0xb0, 0x22, 0xc0, 0xbe, 0x2e, 0x57, 0x2c, 0x11, 0xe9, 0x4d, 0xc9, 0xce, 0x8a, + 0x3e, 0xa2, 0x4c, 0xac, 0x09, 0x29, 0x78, 0x40, 0x1e, 0x96, 0x7f, 0x61, 0xe1, 0x54, 0x2b, 0x85, 0x23, 0x43, 0x99, + 0x02, 0x74, 0x26, 0x25, 0x00, 0xe2, 0x92, 0x3e, 0x6b, 0x1b, 0x0b, 0xc9, 0x76, 0x80, 0x7c, 0xe0, 0x8f, 0x92, 0x88, + 0x3b, 0xad, 0x9d, 0xa6, 0x0b, 0x7c, 0x08, 0x42, 0x1c, 0x74, 0x04, 0x98, 0xf7, 0x15, 0x2a, 0x1c, 0x51, 0x89, 0x5d, + 0xe6, 0x83, 0x51, 0x34, 0x8e, 0x47, 0xdc, 0x49, 0x90, 0x79, 0xdc, 0x92, 0x25, 0xa0, 0x64, 0xf4, 0xbe, 0x02, 0x65, + 0xc1, 0x84, 0x74, 0x11, 0xd5, 0x4a, 0xa0, 0x31, 0x05, 0x29, 0x49, 0x29, 0xd2, 0x82, 0x0a, 0x02, 0x43, 0xa8, 0x74, + 0x14, 0x47, 0x81, 0x7e, 0x8b, 0x7b, 0x62, 0xd0, 0x60, 0xc9, 0xa2, 0x8c, 0x7b, 0xf1, 0x72, 0x21, 0xa8, 0x61, 0x9f, + 0x67, 0xaf, 0xb3, 0x0b, 0x96, 0x3f, 0x8b, 0x10, 0xf6, 0x40, 0x74, 0x2f, 0x41, 0xd2, 0x93, 0x40, 0xe7, 0x1d, 0xc5, + 0x2b, 0xe7, 0x84, 0x34, 0x2c, 0xc4, 0x24, 0x46, 0x45, 0x08, 0x76, 0x0b, 0xd1, 0x3e, 0xc5, 0x2d, 0x45, 0x7b, 0x0f, + 0x55, 0x09, 0xd7, 0xbc, 0xb5, 0xff, 0xba, 0xce, 0x5b, 0x30, 0xc2, 0x54, 0x71, 0x6b, 0x7d, 0xc7, 0x82, 0x7b, 0x21, + 0x74, 0xb3, 0x23, 0x79, 0xcb, 0x50, 0x66, 0xa0, 0x3f, 0xae, 0xaf, 0x2b, 0x23, 0x1d, 0x94, 0xa9, 0x96, 0xe6, 0x08, + 0x81, 0xd8, 0x12, 0x6e, 0x09, 0xca, 0x08, 0x0d, 0xaf, 0x3c, 0x4b, 0x12, 0x43, 0x17, 0x79, 0x71, 0xc7, 0x59, 0x50, + 0x47, 0x00, 0xc5, 0xa4, 0xa6, 0x91, 0x7a, 0x2c, 0xd0, 0x15, 0xa8, 0x94, 0x94, 0x36, 0xf2, 0xaa, 0xb5, 0x11, 0x10, + 0xa7, 0x43, 0x96, 0x0b, 0x07, 0x4d, 0xea, 0x50, 0x98, 0x30, 0x05, 0x86, 0x66, 0x43, 0xf4, 0x1c, 0x24, 0x02, 0x60, + 0x9e, 0xf8, 0xe3, 0xac, 0xe0, 0xba, 0xce, 0x84, 0x3e, 0xbe, 0xbe, 0x8e, 0x85, 0xbf, 0x88, 0x0c, 0x90, 0xb3, 0x49, + 0x76, 0xce, 0x56, 0x40, 0xdd, 0x51, 0x83, 0x99, 0x20, 0x1b, 0xc3, 0x80, 0x12, 0x05, 0xd5, 0x32, 0x4d, 0x62, 0xb0, + 0xf4, 0x75, 0x03, 0x1f, 0x0c, 0x3a, 0x76, 0x89, 0x32, 0xc2, 0xed, 0x76, 0xbb, 0x4d, 0xaf, 0xe5, 0x96, 0x82, 0xe0, + 0xf3, 0x25, 0x8a, 0xde, 0xa0, 0x1f, 0xa5, 0x09, 0xbe, 0x4a, 0x16, 0x30, 0xd7, 0x50, 0x8a, 0xc2, 0x4f, 0x62, 0x9e, + 0x14, 0xc4, 0xae, 0x37, 0x84, 0x41, 0x39, 0x53, 0x82, 0x1b, 0x4d, 0x5c, 0xb1, 0x6d, 0x3f, 0x68, 0xb2, 0x69, 0x76, + 0x52, 0x3b, 0x4c, 0x2d, 0x8c, 0x5c, 0xf3, 0x42, 0x7b, 0xc0, 0xe6, 0xf2, 0x90, 0x4d, 0x8f, 0xd5, 0xc0, 0xeb, 0x00, + 0xa1, 0xf0, 0x74, 0x9d, 0x25, 0x94, 0xaa, 0xce, 0x52, 0x88, 0xeb, 0x0d, 0xf4, 0x51, 0x81, 0xb9, 0x8a, 0x04, 0x07, + 0x52, 0x20, 0x30, 0xf4, 0xc8, 0xc4, 0x7a, 0x3d, 0x83, 0xe5, 0x39, 0x8d, 0x06, 0x9f, 0x34, 0xb8, 0x15, 0xef, 0x2d, + 0xb2, 0x81, 0xb3, 0x50, 0x12, 0x1a, 0xe2, 0xca, 0xc4, 0x5b, 0x49, 0xe8, 0xda, 0x46, 0x01, 0x87, 0x6c, 0x89, 0xed, + 0x17, 0x17, 0x7a, 0x91, 0xdb, 0x25, 0x7b, 0x28, 0xff, 0xa9, 0xe2, 0x92, 0xf5, 0x2c, 0xc7, 0x94, 0x34, 0x60, 0x8a, + 0xf1, 0x60, 0x69, 0x16, 0x20, 0x01, 0xbe, 0x2b, 0x87, 0x71, 0xb1, 0x9e, 0x04, 0x7f, 0x28, 0x98, 0xcf, 0x8d, 0x99, + 0x6e, 0x85, 0x54, 0x4b, 0x38, 0x69, 0x06, 0x6b, 0xd0, 0xa4, 0xf1, 0xa0, 0x44, 0xcd, 0x57, 0x68, 0xa8, 0x10, 0xc7, + 0x9f, 0x89, 0x2a, 0x34, 0xc1, 0x10, 0x8c, 0xc2, 0xcb, 0x25, 0xc3, 0xa5, 0xcb, 0xa2, 0x45, 0xca, 0xd4, 0x98, 0x54, + 0xaa, 0x66, 0xb9, 0x14, 0x0c, 0x2c, 0xda, 0xad, 0xbe, 0xb4, 0xc4, 0x95, 0xc8, 0xcd, 0x42, 0x2d, 0x4c, 0x72, 0xe5, + 0x4d, 0x38, 0x05, 0xfa, 0x5d, 0xca, 0x7a, 0x37, 0xf1, 0x29, 0x14, 0x3e, 0x85, 0x6f, 0xf8, 0x50, 0x26, 0x6f, 0xe7, + 0x3d, 0x30, 0xf7, 0x6b, 0x95, 0x68, 0x9f, 0xfa, 0x28, 0x98, 0x5d, 0x2d, 0x74, 0x41, 0xa0, 0x48, 0x36, 0xc9, 0x7a, + 0x92, 0xdf, 0x50, 0x6c, 0x54, 0x9e, 0x51, 0xea, 0x8a, 0x0d, 0x52, 0xf3, 0x4a, 0x53, 0x2f, 0x73, 0x17, 0xec, 0xf7, + 0xb2, 0x94, 0x74, 0x62, 0x82, 0x32, 0xb1, 0x77, 0x13, 0x6d, 0xbc, 0x2c, 0x4c, 0x85, 0xf5, 0x2b, 0x8c, 0x9d, 0x1a, + 0x85, 0x32, 0x29, 0x02, 0x71, 0x6c, 0x7c, 0xac, 0x2c, 0x83, 0xd4, 0x5f, 0x61, 0x4f, 0x01, 0x28, 0x09, 0x2c, 0xbe, + 0xa6, 0x92, 0x17, 0x85, 0x75, 0x3a, 0x6e, 0x10, 0x1d, 0x2b, 0x11, 0x5a, 0x13, 0xf9, 0x5a, 0x9f, 0xc5, 0x7e, 0xcd, + 0x25, 0x34, 0x29, 0x59, 0xf4, 0x8a, 0xc0, 0x56, 0x81, 0x88, 0x4a, 0xb7, 0x25, 0xbd, 0x84, 0x1c, 0xd2, 0x65, 0xa2, + 0xd7, 0x46, 0x32, 0x68, 0x9d, 0x09, 0x89, 0x96, 0xf5, 0xc3, 0x08, 0xc5, 0x86, 0x58, 0x8b, 0x25, 0x42, 0x2e, 0xda, + 0x9b, 0xc4, 0x8a, 0xe8, 0x9c, 0x16, 0x68, 0xc2, 0x99, 0x3a, 0xdd, 0x71, 0x00, 0x1d, 0x10, 0xfb, 0x4b, 0xac, 0xb7, + 0xd2, 0xec, 0x74, 0xfd, 0xca, 0xe1, 0xbb, 0xbe, 0x1e, 0x73, 0xd7, 0x91, 0x06, 0x2f, 0xac, 0x59, 0x4f, 0xc9, 0xde, + 0xfd, 0xd7, 0xd8, 0x8a, 0xec, 0xcf, 0xaa, 0xa4, 0xf2, 0x14, 0x6a, 0x9c, 0x5b, 0x5f, 0xa7, 0x5a, 0x68, 0x51, 0x55, + 0x1c, 0x18, 0x52, 0xfd, 0x40, 0x29, 0xec, 0x0a, 0xe5, 0x03, 0x39, 0x74, 0xec, 0xba, 0x6e, 0x50, 0x90, 0xf3, 0xb2, + 0xb1, 0xca, 0x85, 0xdc, 0xda, 0x32, 0x7d, 0xa6, 0x73, 0x3d, 0xfc, 0x33, 0x07, 0x95, 0x73, 0x71, 0x95, 0x92, 0x05, + 0xf3, 0x4c, 0xa9, 0xa3, 0x25, 0x07, 0xb4, 0xd9, 0x41, 0x4f, 0x3b, 0xba, 0x88, 0x62, 0x6e, 0xe9, 0x51, 0x84, 0xa7, + 0x8d, 0xf2, 0x49, 0x1a, 0x1d, 0x80, 0x17, 0x9a, 0x90, 0xe4, 0x84, 0x9b, 0xb6, 0x68, 0x31, 0x18, 0x33, 0x0c, 0x81, + 0x2b, 0x7b, 0xc2, 0x94, 0x3d, 0x1b, 0x88, 0xb7, 0x1c, 0x78, 0x35, 0xec, 0xe5, 0x62, 0xf7, 0x9a, 0xf9, 0x0f, 0x6b, + 0x04, 0xb2, 0x6d, 0xa2, 0xea, 0xca, 0x85, 0x67, 0x29, 0x22, 0x31, 0xc2, 0xb6, 0x6a, 0x6c, 0x69, 0xeb, 0x77, 0x16, + 0xdc, 0xeb, 0xca, 0x31, 0xaf, 0x29, 0xd5, 0x05, 0x3d, 0xac, 0xdc, 0x1c, 0x6e, 0x3a, 0xf2, 0x62, 0x05, 0xdd, 0x8e, + 0x08, 0x0a, 0x81, 0x13, 0xa1, 0xec, 0x41, 0xcd, 0x0d, 0x44, 0x4a, 0xa6, 0xb4, 0x6a, 0x36, 0x4b, 0x86, 0x12, 0x58, + 0x70, 0x61, 0x99, 0xe4, 0xa3, 0x8b, 0x38, 0x49, 0xaa, 0xd2, 0x3f, 0x54, 0xc0, 0x8b, 0x61, 0x6f, 0x13, 0xed, 0x02, + 0xa3, 0x99, 0x02, 0xc1, 0xd5, 0x46, 0xd8, 0x47, 0xc7, 0xad, 0xd6, 0x5d, 0x44, 0x1c, 0x99, 0x19, 0x8d, 0xf8, 0x88, + 0x36, 0x64, 0xc9, 0x34, 0x6b, 0xef, 0xbf, 0xc0, 0x90, 0x9a, 0x81, 0x0f, 0xaa, 0x33, 0x2a, 0xfe, 0x55, 0xf6, 0xd4, + 0xaf, 0x44, 0xef, 0x56, 0xd5, 0xb5, 0x18, 0x50, 0x51, 0x81, 0x0f, 0x33, 0xc4, 0xd2, 0x54, 0x81, 0x80, 0x5c, 0x0f, + 0xeb, 0x70, 0xb7, 0x46, 0x1a, 0x2c, 0x28, 0x05, 0xd6, 0x5a, 0xd9, 0xbd, 0xbe, 0x2d, 0x98, 0x43, 0xa1, 0x70, 0xd1, + 0xff, 0x59, 0x36, 0x99, 0xa2, 0x65, 0xb6, 0xc0, 0xd4, 0xd0, 0xe0, 0xe3, 0x42, 0x7d, 0xb9, 0xa2, 0xac, 0xd6, 0x87, + 0x76, 0x64, 0x8d, 0x9f, 0xb4, 0xa3, 0x0c, 0x0e, 0xd5, 0x4c, 0x17, 0xd5, 0xed, 0xe6, 0x45, 0x11, 0xb3, 0x8a, 0xc7, + 0x7d, 0xd2, 0xdb, 0xda, 0x9a, 0xf4, 0x34, 0x0d, 0x48, 0x26, 0x49, 0x86, 0x37, 0x19, 0xa0, 0xac, 0x88, 0x33, 0x2f, + 0x17, 0xc8, 0x37, 0x2f, 0x4b, 0x5c, 0xbf, 0xef, 0x3b, 0xfb, 0x35, 0xcf, 0xda, 0xdb, 0x5f, 0xef, 0x22, 0x57, 0x75, + 0xd2, 0x83, 0x3c, 0xea, 0x43, 0xd1, 0x92, 0x4d, 0x19, 0xce, 0x27, 0xd9, 0x90, 0x05, 0x36, 0x74, 0x4f, 0xed, 0x52, + 0x6e, 0x9a, 0x08, 0x36, 0x07, 0xf8, 0x7f, 0xf3, 0x0f, 0xf5, 0x48, 0x6a, 0xb0, 0x0f, 0x2c, 0xa0, 0xcd, 0x85, 0x2f, + 0xc3, 0xb3, 0x24, 0x3b, 0x8d, 0x92, 0x43, 0xa1, 0xc0, 0x6b, 0x2d, 0xbf, 0x01, 0x97, 0x91, 0x2c, 0x56, 0x43, 0x49, + 0x7d, 0xd9, 0xfb, 0x32, 0xb8, 0xbd, 0x47, 0xe5, 0xad, 0xd8, 0x2d, 0xbf, 0xe9, 0xb7, 0x6c, 0x15, 0x11, 0xfb, 0xc9, + 0x9c, 0x0e, 0x34, 0x4e, 0x01, 0x94, 0x39, 0x04, 0x4d, 0x56, 0x78, 0x03, 0x1e, 0xfe, 0xd4, 0xfb, 0x49, 0xb9, 0xd4, + 0x19, 0xb8, 0x10, 0xe0, 0xe4, 0x27, 0x31, 0x6f, 0xe0, 0x79, 0xa4, 0xed, 0xcd, 0x45, 0x05, 0xc6, 0x15, 0x29, 0x2e, + 0x5d, 0x2a, 0x6f, 0xd0, 0x3b, 0x0e, 0x4f, 0xa0, 0xd9, 0xe6, 0xe6, 0xdc, 0x79, 0x13, 0xf1, 0xb1, 0x9f, 0x47, 0xe9, + 0x30, 0x9b, 0x38, 0xee, 0xb6, 0x6d, 0xbb, 0x7e, 0x41, 0x9e, 0xc8, 0x67, 0x6e, 0xb9, 0x79, 0xe2, 0x0d, 0x79, 0x68, + 0xf7, 0xec, 0xed, 0x63, 0xef, 0x90, 0x87, 0x27, 0x7b, 0x9b, 0xf3, 0x21, 0x2f, 0xbb, 0x27, 0xde, 0xa5, 0x8e, 0xb9, + 0x7b, 0xef, 0x51, 0xca, 0x40, 0xaf, 0xb0, 0x7b, 0x29, 0xc1, 0x00, 0x76, 0xa3, 0xf8, 0x3b, 0x48, 0xb9, 0x8f, 0x74, + 0x20, 0x22, 0xe3, 0xb4, 0xd7, 0xd7, 0x76, 0x46, 0x11, 0x03, 0x7b, 0x43, 0x3b, 0xab, 0x5b, 0x5b, 0x95, 0x9a, 0xaf, + 0x4a, 0xbd, 0x19, 0x0f, 0x6b, 0x9e, 0xba, 0xf7, 0x92, 0x8e, 0x56, 0xea, 0x1b, 0x79, 0x26, 0x82, 0x36, 0xcb, 0x76, + 0x82, 0x63, 0x6c, 0xf1, 0xd5, 0xdb, 0xfa, 0x48, 0x44, 0x29, 0xfc, 0x18, 0xac, 0x97, 0x08, 0xd4, 0x37, 0x38, 0x38, + 0xde, 0x61, 0xb8, 0xb3, 0xe7, 0xf4, 0x02, 0x67, 0xa3, 0xd1, 0xb8, 0xfe, 0x61, 0xe7, 0xe8, 0xc7, 0xa8, 0xf1, 0xcb, + 0x7e, 0xe3, 0xfb, 0xbe, 0x7b, 0xed, 0xfc, 0xb0, 0xd3, 0x3b, 0x92, 0x4f, 0x47, 0x3f, 0x76, 0x7f, 0x28, 0xfa, 0x7f, + 0x12, 0x85, 0x9b, 0xae, 0xbb, 0x73, 0xe6, 0x4d, 0x79, 0xb8, 0xd3, 0x68, 0x74, 0xe1, 0xdb, 0x19, 0x7c, 0xc3, 0xcf, + 0x53, 0xf8, 0xb8, 0x3e, 0xb2, 0xfe, 0xc3, 0x0f, 0xe9, 0x7f, 0xfc, 0x21, 0xef, 0xe3, 0x98, 0x47, 0x3f, 0xfe, 0x50, + 0xd8, 0xf7, 0xbb, 0xe1, 0x4e, 0x7f, 0xdb, 0x75, 0x74, 0xcd, 0x9f, 0xc2, 0xea, 0x2b, 0xb4, 0x3a, 0xfa, 0x51, 0x3e, + 0xd9, 0xf7, 0x4f, 0xf6, 0xba, 0x61, 0xff, 0xda, 0xb1, 0xaf, 0xef, 0xbb, 0xd7, 0xae, 0x7b, 0xbd, 0x89, 0xf3, 0x9c, + 0xc3, 0xe8, 0xf7, 0xe1, 0x73, 0x04, 0x9f, 0x36, 0x7c, 0x6e, 0xc2, 0xe7, 0x8f, 0xd0, 0x4d, 0xc4, 0xdf, 0xae, 0x29, + 0x16, 0x72, 0x8d, 0x07, 0x16, 0x11, 0xac, 0x82, 0xbb, 0xb9, 0x13, 0x7b, 0x13, 0x22, 0x1a, 0xec, 0x43, 0xdf, 0xf7, + 0x31, 0x4c, 0xea, 0xcc, 0x8f, 0x37, 0x61, 0xd1, 0x91, 0x73, 0x36, 0x03, 0xee, 0x89, 0xc8, 0x41, 0x11, 0x30, 0x71, + 0xb6, 0x5a, 0xe0, 0xe1, 0xaa, 0x37, 0x0c, 0x27, 0xdc, 0x01, 0xa3, 0xe0, 0x03, 0xc7, 0x2f, 0x6d, 0xd7, 0x7b, 0x21, + 0xcf, 0x0c, 0x71, 0x9f, 0x0b, 0xd6, 0x4a, 0x33, 0x61, 0xd2, 0xd8, 0xae, 0x37, 0x5d, 0x51, 0x09, 0xdb, 0x3a, 0x3d, + 0x83, 0xba, 0x63, 0x11, 0xa3, 0xfe, 0x96, 0x45, 0x9f, 0x70, 0x4b, 0xbe, 0x35, 0x0e, 0x81, 0x97, 0x2c, 0xf9, 0x45, + 0xa3, 0xd1, 0xb0, 0x11, 0x85, 0x3b, 0xf6, 0x94, 0xc1, 0x0c, 0x4b, 0x26, 0x22, 0x23, 0xa5, 0x29, 0x2c, 0x5b, 0x98, + 0xfc, 0x7d, 0x94, 0xf3, 0xcd, 0xca, 0xb0, 0x0d, 0xeb, 0x96, 0xec, 0x82, 0xa5, 0x7f, 0x87, 0x29, 0xd0, 0xb4, 0xa4, + 0xf3, 0x0f, 0x73, 0xfc, 0x30, 0x23, 0xb4, 0x3e, 0x38, 0x0c, 0x3c, 0xf4, 0x02, 0xe4, 0x8e, 0xe8, 0xe7, 0xbc, 0x47, + 0x35, 0x06, 0xff, 0xcb, 0x30, 0x83, 0x27, 0xe6, 0xc3, 0x10, 0xcd, 0xbc, 0xd4, 0xc1, 0xad, 0x0c, 0xc5, 0xfd, 0x2b, + 0xdc, 0x19, 0x59, 0xe9, 0x1d, 0x84, 0x6a, 0xc7, 0x1c, 0xe6, 0x8c, 0x7d, 0x1b, 0x25, 0x9f, 0x58, 0xee, 0x5c, 0x7a, + 0xad, 0xf6, 0x67, 0xd4, 0xd9, 0x43, 0xdb, 0xec, 0x4d, 0x75, 0x8c, 0xa6, 0xcd, 0x02, 0x79, 0x44, 0xd8, 0x68, 0x79, + 0x28, 0x31, 0x88, 0x04, 0xb9, 0x97, 0x86, 0x6d, 0xe2, 0x70, 0x7b, 0xaf, 0x38, 0x3f, 0xeb, 0xda, 0x81, 0x6d, 0x83, + 0xc5, 0x7f, 0x48, 0x61, 0x2b, 0x61, 0x58, 0x34, 0x3b, 0x6c, 0x2f, 0xee, 0xb0, 0xed, 0xed, 0x2a, 0xe0, 0x84, 0x07, + 0xe9, 0xd4, 0x3d, 0xf1, 0x22, 0x6f, 0x1c, 0xc2, 0x80, 0x03, 0x68, 0x86, 0x5d, 0x3a, 0x83, 0xbd, 0x58, 0x4e, 0x03, + 0xb2, 0x3e, 0xf3, 0x93, 0xa8, 0xe0, 0xaf, 0x30, 0x1e, 0x11, 0x0e, 0xc0, 0xd8, 0xcf, 0x7c, 0x76, 0xc9, 0x06, 0xca, + 0xce, 0x00, 0x42, 0x45, 0x6e, 0xc7, 0x1d, 0x84, 0x46, 0x33, 0x98, 0x3b, 0x0c, 0x0f, 0x7b, 0x36, 0xec, 0x25, 0xd8, + 0x95, 0x61, 0x74, 0xd4, 0xea, 0xf7, 0xb2, 0x70, 0xca, 0x03, 0x4d, 0x5b, 0x59, 0x74, 0x56, 0x2b, 0x6a, 0xf7, 0x7b, + 0xce, 0x26, 0x18, 0xe9, 0x60, 0x8b, 0x3b, 0xf8, 0x84, 0x11, 0x8a, 0x3c, 0xfc, 0xc0, 0xce, 0x5e, 0x5c, 0x4e, 0x1d, + 0x7b, 0x6f, 0xc7, 0xde, 0xc6, 0x52, 0xcf, 0x06, 0xf6, 0x02, 0x0a, 0x86, 0xa7, 0xae, 0xd9, 0x79, 0xb7, 0x8f, 0xa0, + 0x62, 0x21, 0x4e, 0x7e, 0xda, 0xb3, 0xbb, 0x62, 0xea, 0x26, 0x0c, 0x9a, 0xc9, 0xe5, 0xc7, 0x15, 0x3d, 0x24, 0x54, + 0x55, 0x57, 0x05, 0x1d, 0x94, 0xb5, 0x03, 0x67, 0x6c, 0x22, 0xd1, 0xc0, 0xc9, 0x24, 0x15, 0xc0, 0xe1, 0xc1, 0x66, + 0x30, 0xa9, 0xd1, 0x6d, 0xb7, 0xdf, 0x3b, 0x0d, 0xee, 0xdb, 0xf7, 0xd5, 0xc3, 0x08, 0x90, 0xe1, 0x62, 0xfa, 0x11, + 0x48, 0x3b, 0xfc, 0x3c, 0xe7, 0x80, 0xe4, 0x29, 0x15, 0x4d, 0x65, 0xd1, 0x19, 0x16, 0x1d, 0x06, 0x08, 0xaa, 0x97, + 0x6b, 0xeb, 0x4f, 0xac, 0xc9, 0x30, 0x24, 0xd8, 0xc1, 0x16, 0x3a, 0x62, 0xdb, 0xad, 0x3e, 0x9e, 0x37, 0xe4, 0xbc, + 0xf8, 0x36, 0xe6, 0xa0, 0x12, 0x76, 0xba, 0xb6, 0xdb, 0xb3, 0x2d, 0x5c, 0xda, 0x4e, 0xba, 0x1d, 0x0a, 0x0a, 0xc7, + 0xdb, 0x87, 0x3c, 0x18, 0x77, 0xc3, 0x66, 0xcf, 0x29, 0x64, 0xb8, 0x11, 0xcf, 0x2d, 0x85, 0x04, 0x6f, 0x7a, 0x63, + 0x10, 0xe8, 0xc8, 0xb9, 0x9b, 0xf6, 0xb6, 0x2a, 0x84, 0xa2, 0xe3, 0xed, 0xa1, 0x1b, 0xc4, 0xf0, 0xe1, 0x34, 0x90, + 0x69, 0xc6, 0xba, 0xaf, 0xd2, 0xcc, 0xcc, 0x0d, 0x86, 0xca, 0x22, 0x4f, 0xc2, 0x74, 0xdb, 0xc1, 0x08, 0x2d, 0x48, + 0xda, 0xbd, 0x1e, 0xc0, 0xb0, 0xed, 0x28, 0x4e, 0xdb, 0x51, 0xac, 0xa6, 0xec, 0xf3, 0x23, 0xbd, 0x1c, 0x03, 0xde, + 0x1b, 0xa8, 0xf3, 0x58, 0xd4, 0x3e, 0x00, 0x56, 0x90, 0x78, 0x45, 0x5f, 0x9d, 0x79, 0xbd, 0xac, 0x9d, 0x6f, 0xcd, + 0x95, 0x28, 0xe2, 0x9e, 0x21, 0xa1, 0x58, 0xa9, 0xdd, 0x30, 0x61, 0x6e, 0x4f, 0x91, 0x18, 0x9a, 0xe5, 0x43, 0xd8, + 0x63, 0xa1, 0x0a, 0xb0, 0x67, 0xe6, 0xb6, 0x48, 0xc2, 0xaa, 0xb9, 0x77, 0x04, 0xac, 0xdd, 0x0f, 0xdf, 0x08, 0x77, + 0xaa, 0xa3, 0xa2, 0xf9, 0x2c, 0x09, 0x5f, 0x2e, 0x1c, 0x17, 0x47, 0x78, 0x22, 0x74, 0xe0, 0x0f, 0x66, 0x39, 0xc8, + 0x03, 0xfe, 0x16, 0x2c, 0x83, 0x50, 0x36, 0x45, 0x47, 0x0f, 0x8f, 0x80, 0x3d, 0x42, 0x7c, 0x21, 0x6c, 0x6e, 0x54, + 0xa3, 0x45, 0x49, 0xc6, 0x0b, 0x1d, 0x0c, 0x77, 0x98, 0x74, 0xed, 0x51, 0x30, 0xc8, 0x13, 0x63, 0x07, 0xcf, 0xfc, + 0xfd, 0x01, 0x56, 0xe3, 0x04, 0x85, 0x5b, 0xd2, 0x6e, 0xab, 0xc4, 0xdf, 0x81, 0x9f, 0x82, 0x04, 0xc7, 0x3a, 0xf0, + 0xb3, 0xb6, 0xb6, 0x12, 0x89, 0xd4, 0x5e, 0xd6, 0xa1, 0x93, 0x08, 0x8c, 0x07, 0x17, 0x7e, 0x0a, 0xd5, 0x48, 0x22, + 0x2a, 0x22, 0x0b, 0xd4, 0x3c, 0x55, 0xab, 0xe0, 0x3b, 0x32, 0x23, 0xf0, 0x8c, 0x92, 0x5c, 0xd0, 0x50, 0xd4, 0x8d, + 0x45, 0x2c, 0xdf, 0x75, 0xe9, 0x68, 0x0b, 0x0f, 0x20, 0x05, 0xa3, 0x09, 0x86, 0x71, 0x29, 0x28, 0x59, 0xf1, 0xdf, + 0xb1, 0x11, 0x2b, 0x1f, 0x1f, 0xa5, 0xdb, 0xdb, 0x7d, 0x71, 0x6e, 0x41, 0x8c, 0xc3, 0x8c, 0xe8, 0x6a, 0x5c, 0x01, + 0x50, 0x9f, 0xce, 0x89, 0xeb, 0x81, 0x69, 0xc5, 0x9a, 0x2e, 0xc5, 0x3e, 0x39, 0xcc, 0x00, 0x14, 0xdc, 0x71, 0x8e, + 0xfc, 0xde, 0x9f, 0xfb, 0xe0, 0x1e, 0xfb, 0x7f, 0x72, 0x77, 0x94, 0xa0, 0xe9, 0xc8, 0x33, 0xc5, 0x39, 0x9d, 0xb1, + 0xb6, 0x3c, 0x8a, 0x8d, 0x06, 0x20, 0xf5, 0x00, 0x03, 0xd0, 0xe6, 0x20, 0x13, 0x2a, 0x0e, 0x42, 0x8e, 0x0a, 0x6c, + 0x1f, 0x37, 0x3f, 0xc3, 0x9d, 0xfd, 0x9c, 0x07, 0x60, 0xc1, 0xa8, 0xa7, 0xd7, 0xf0, 0xf4, 0x67, 0xfd, 0xf4, 0x13, + 0x0f, 0x7e, 0x29, 0x65, 0xe8, 0xbe, 0x36, 0xc5, 0x23, 0x35, 0x45, 0x29, 0x96, 0xc8, 0xa0, 0x21, 0x77, 0x97, 0x63, + 0x36, 0xcc, 0x2d, 0x81, 0x18, 0x4a, 0x74, 0x81, 0x8d, 0x16, 0x9d, 0x21, 0x71, 0x5d, 0x93, 0x14, 0x46, 0x2e, 0x81, + 0x89, 0x70, 0xc5, 0xb7, 0x48, 0x4f, 0xd6, 0x6d, 0xba, 0xf3, 0x5a, 0x5b, 0xb2, 0xef, 0xd8, 0x64, 0xca, 0xaf, 0x0e, + 0x48, 0xd1, 0x07, 0x32, 0x6d, 0x40, 0x9c, 0x9d, 0x37, 0x3b, 0xf1, 0x1e, 0xeb, 0xc4, 0x20, 0xd5, 0x0b, 0xc5, 0x62, + 0xb8, 0x57, 0xbd, 0xf7, 0x18, 0xa5, 0x34, 0x99, 0xc9, 0xab, 0xa1, 0xd7, 0x96, 0xe8, 0x6d, 0x6f, 0x03, 0x82, 0x1d, + 0xa3, 0x2b, 0x13, 0x5d, 0xcb, 0x52, 0xd0, 0x04, 0x20, 0x7a, 0x52, 0x67, 0x39, 0xe2, 0x38, 0xcc, 0x66, 0x83, 0xe2, + 0x21, 0x77, 0x57, 0x8e, 0x8a, 0x63, 0x62, 0x77, 0x99, 0xb0, 0x03, 0x98, 0x11, 0x97, 0x37, 0x5a, 0x22, 0x3a, 0x2c, + 0xfa, 0xeb, 0xf8, 0xf6, 0xb1, 0xc7, 0xb7, 0x5b, 0x2e, 0x68, 0x90, 0xda, 0x58, 0x8f, 0xab, 0xb1, 0xa0, 0x3e, 0x3c, + 0xd6, 0x54, 0x2a, 0xf3, 0xed, 0xed, 0xb2, 0x7e, 0x54, 0xab, 0x76, 0x70, 0xed, 0x34, 0xe5, 0x72, 0x31, 0x1b, 0x84, + 0x03, 0x11, 0x13, 0x28, 0xd0, 0xd2, 0xca, 0x8a, 0x01, 0x86, 0x94, 0xe5, 0x28, 0x9f, 0x42, 0xee, 0xc5, 0x65, 0xa9, + 0x53, 0x5f, 0x9e, 0xc9, 0xa0, 0x23, 0x9e, 0x7a, 0x92, 0xb1, 0x02, 0xac, 0xe6, 0x65, 0x5e, 0x42, 0x4b, 0x04, 0x98, + 0xbf, 0x50, 0x39, 0x34, 0xc2, 0x02, 0x89, 0x42, 0xc3, 0x2c, 0x51, 0xc6, 0x67, 0x1e, 0xc6, 0xa0, 0xed, 0x9f, 0xd5, + 0x62, 0x5f, 0xb9, 0x32, 0x3a, 0xf2, 0xa3, 0xa2, 0x1f, 0x50, 0xfd, 0x4c, 0x4a, 0xb0, 0x71, 0xf8, 0x11, 0xd8, 0xa8, + 0x72, 0x3c, 0x49, 0x10, 0x3e, 0x8f, 0x73, 0x46, 0x9e, 0xc2, 0xa6, 0x84, 0x59, 0x9a, 0xb6, 0x91, 0x6a, 0x17, 0x99, + 0x41, 0x28, 0x17, 0xe6, 0x1f, 0x1b, 0x67, 0x17, 0x69, 0xb8, 0xd4, 0x1a, 0xcc, 0x8f, 0x77, 0x26, 0x40, 0xe9, 0xf5, + 0x75, 0x2a, 0x7c, 0xdc, 0x88, 0xec, 0x0d, 0x5d, 0x31, 0xee, 0x29, 0xa4, 0x02, 0x27, 0x22, 0x8b, 0x87, 0xce, 0x50, + 0x68, 0x84, 0x43, 0x3a, 0x45, 0x2e, 0x5c, 0x63, 0xd3, 0x17, 0x3d, 0xed, 0x1b, 0x65, 0xa1, 0x93, 0x80, 0x10, 0x10, + 0xb8, 0x1b, 0xd6, 0x54, 0xd6, 0xcb, 0x82, 0x84, 0x4a, 0xd1, 0xcf, 0x01, 0xfc, 0xc3, 0x48, 0x52, 0x00, 0xec, 0x87, + 0x6a, 0xa4, 0x88, 0xb2, 0x2c, 0x70, 0x01, 0x68, 0xae, 0x03, 0x5c, 0x09, 0x5f, 0x18, 0xa8, 0x30, 0x3d, 0xcd, 0xca, + 0x4a, 0xa1, 0x44, 0x9e, 0xae, 0x48, 0x59, 0x23, 0x99, 0x7c, 0x8e, 0x0e, 0x9f, 0xf2, 0xae, 0xdf, 0x4a, 0x3c, 0x74, + 0xc1, 0x73, 0x58, 0x56, 0xf5, 0xfd, 0x4d, 0xc8, 0xc8, 0xb9, 0x06, 0x5d, 0x21, 0x85, 0xfe, 0x92, 0x93, 0xbc, 0xff, + 0xc6, 0xaf, 0x6a, 0xa9, 0x31, 0x94, 0x7d, 0x5c, 0xd5, 0x0c, 0xcb, 0xcb, 0x69, 0x15, 0xa6, 0x20, 0xe0, 0xe6, 0x2c, + 0x09, 0xe6, 0x52, 0x43, 0x80, 0x85, 0xed, 0x91, 0x56, 0x0a, 0x8a, 0x52, 0x87, 0x77, 0x9e, 0x83, 0x15, 0x60, 0x1c, + 0x6a, 0xa9, 0x64, 0x1a, 0x49, 0x7c, 0xa9, 0x44, 0x81, 0x29, 0x0f, 0x06, 0xe0, 0xa7, 0x2e, 0x9e, 0x74, 0x5d, 0xba, + 0x7e, 0x3c, 0xc1, 0xd4, 0x1e, 0x02, 0x3d, 0xf6, 0x36, 0xc0, 0x94, 0xa8, 0xeb, 0xb0, 0x9c, 0x38, 0x34, 0xad, 0x69, + 0x16, 0x30, 0x63, 0x9a, 0xa0, 0x25, 0x9b, 0x60, 0xcb, 0x15, 0x60, 0x1f, 0x89, 0xed, 0x59, 0xad, 0x80, 0xd0, 0x35, + 0x68, 0x60, 0xc8, 0x5d, 0x2a, 0xb4, 0x30, 0xeb, 0xb4, 0xa9, 0x08, 0xf7, 0x67, 0x8f, 0x49, 0x2b, 0x38, 0xf5, 0x52, + 0x1a, 0xf8, 0x20, 0x3e, 0x4d, 0x30, 0xf1, 0x05, 0xb1, 0x02, 0x3b, 0x38, 0x68, 0x2d, 0x36, 0x05, 0x4e, 0xc5, 0x45, + 0x4a, 0x61, 0x59, 0x51, 0x6a, 0xc3, 0x87, 0x14, 0xd9, 0xba, 0xcb, 0x23, 0xdd, 0x85, 0x58, 0x00, 0x3b, 0xfd, 0xc2, + 0xa1, 0x83, 0xac, 0x97, 0x01, 0x83, 0x73, 0xad, 0x71, 0x10, 0xf8, 0xed, 0xed, 0xa4, 0x5f, 0x66, 0x48, 0xb9, 0x25, + 0x56, 0x17, 0x90, 0xe3, 0x76, 0x58, 0xc0, 0x1d, 0x84, 0xa5, 0xb2, 0xc7, 0xf3, 0x72, 0x82, 0xcb, 0xa5, 0x2c, 0xe4, + 0xc5, 0x74, 0x2c, 0x9a, 0xcf, 0xad, 0x34, 0x9b, 0x8e, 0xb7, 0xe2, 0x83, 0x82, 0xbf, 0xe7, 0xc4, 0xd2, 0xaa, 0xa7, + 0xd4, 0x0a, 0x8f, 0x32, 0xb7, 0x64, 0x9d, 0x92, 0x5a, 0x6d, 0x37, 0x50, 0x8d, 0xf0, 0x34, 0x0d, 0x1b, 0x81, 0x10, + 0x13, 0x5c, 0xfc, 0x61, 0x91, 0x89, 0x69, 0x6f, 0x09, 0xa9, 0x23, 0xec, 0x1e, 0xca, 0x09, 0x6e, 0x6b, 0x9e, 0x7d, + 0x19, 0x4e, 0xd7, 0x33, 0xf7, 0xbe, 0xc1, 0xdc, 0x4f, 0x43, 0x66, 0x30, 0x7a, 0x2c, 0x13, 0x7e, 0x64, 0xec, 0xa3, + 0x50, 0x55, 0xcf, 0xce, 0xc2, 0x4a, 0x64, 0x89, 0x6f, 0xc6, 0x51, 0x87, 0x71, 0x2a, 0x5a, 0x13, 0x64, 0xd7, 0xd7, + 0xb9, 0xb9, 0x17, 0x28, 0x68, 0xea, 0xb1, 0x7a, 0x9c, 0xb6, 0x62, 0x67, 0x23, 0x12, 0xb9, 0xff, 0xa6, 0x16, 0x89, + 0xac, 0xf8, 0x1c, 0x47, 0x5a, 0x73, 0x90, 0xfb, 0xec, 0x6c, 0x79, 0x93, 0x0a, 0xdd, 0xa2, 0xd1, 0x36, 0xf6, 0xa8, + 0x3e, 0x90, 0xd4, 0x33, 0x2a, 0xb0, 0xaa, 0xb1, 0xb7, 0xb6, 0x5a, 0x22, 0xdd, 0x52, 0x29, 0x36, 0x0c, 0x69, 0x85, + 0xcc, 0x18, 0x05, 0x83, 0x92, 0x22, 0x03, 0x35, 0xca, 0xd7, 0x08, 0x86, 0x7d, 0x6a, 0x00, 0x8a, 0x73, 0x75, 0xf5, + 0xd3, 0x52, 0xb2, 0x85, 0x80, 0x04, 0x64, 0x13, 0x8a, 0x35, 0x62, 0x66, 0xe4, 0x93, 0x8f, 0xc0, 0x79, 0x3d, 0x8e, + 0x8e, 0x01, 0xc8, 0x60, 0xb1, 0xe9, 0xc1, 0xc4, 0xb6, 0x89, 0x28, 0xfa, 0x6c, 0xe0, 0x25, 0x00, 0x3b, 0xad, 0x42, + 0xa3, 0x1f, 0xaa, 0x14, 0x30, 0x64, 0x03, 0x37, 0xe0, 0x55, 0x58, 0x6e, 0xff, 0x25, 0xb4, 0x83, 0xc7, 0x17, 0xb2, + 0xf9, 0x26, 0xe6, 0x09, 0x56, 0xb1, 0x3b, 0xbf, 0xb2, 0xac, 0xc5, 0xb9, 0xd3, 0xe1, 0x42, 0xbd, 0xa2, 0x84, 0xa8, + 0x3d, 0xc0, 0xda, 0x97, 0x9c, 0x60, 0xc4, 0xe7, 0x37, 0x94, 0x75, 0xa8, 0xc6, 0x2d, 0xf7, 0x35, 0x5a, 0x84, 0xe9, + 0x32, 0x69, 0x0c, 0x4a, 0xd6, 0xfd, 0x64, 0xc4, 0xbd, 0x3c, 0x10, 0xb1, 0xe0, 0x0a, 0x47, 0x23, 0x6c, 0xbe, 0x80, + 0x24, 0x7d, 0xdb, 0xa7, 0x03, 0xf6, 0xcd, 0xc5, 0x5e, 0x40, 0x99, 0x8f, 0x15, 0xa9, 0x24, 0xa4, 0x34, 0xbb, 0x21, + 0x92, 0x84, 0xb5, 0x22, 0x4f, 0x9d, 0x0f, 0x1c, 0xed, 0x73, 0x2b, 0x89, 0x60, 0x04, 0x27, 0x71, 0xba, 0xf2, 0x70, + 0x51, 0x80, 0xab, 0xe8, 0x88, 0xe9, 0x9b, 0xa0, 0xfc, 0x06, 0xb9, 0xbd, 0x94, 0x5c, 0x5b, 0x68, 0x18, 0x9e, 0x21, + 0xc1, 0xaa, 0x48, 0x04, 0x3a, 0x0a, 0x80, 0xe3, 0x4a, 0xcf, 0x03, 0x4c, 0xf8, 0xda, 0xde, 0x04, 0x80, 0x44, 0x56, + 0x90, 0xb3, 0x14, 0xe8, 0x06, 0x2c, 0x57, 0xc7, 0xa9, 0x51, 0x91, 0xb8, 0xb8, 0x31, 0x5d, 0xdd, 0xd2, 0x9f, 0xa0, + 0xe5, 0x4c, 0x86, 0x98, 0x0e, 0x82, 0x80, 0x4c, 0x7d, 0xca, 0x9d, 0x9c, 0xa6, 0x13, 0xd6, 0xe7, 0xd4, 0xa9, 0x4d, + 0xdd, 0xe1, 0xd4, 0xcd, 0x93, 0xd4, 0x62, 0x75, 0xda, 0x94, 0x12, 0x31, 0x29, 0x31, 0x8f, 0x65, 0x2a, 0xb6, 0x12, + 0x77, 0x6e, 0x7d, 0xa3, 0x85, 0xb4, 0xd1, 0x8e, 0x65, 0x0e, 0xb6, 0x96, 0xf7, 0x42, 0xb4, 0xbf, 0x24, 0xc2, 0xb3, + 0x12, 0x19, 0x6b, 0x3e, 0xe3, 0x8e, 0x89, 0x60, 0xf5, 0x60, 0x2a, 0xf2, 0x0f, 0x8e, 0x4e, 0xb3, 0x37, 0xe8, 0x41, + 0xea, 0x0d, 0x24, 0x66, 0x4d, 0x7c, 0xe7, 0xd2, 0x50, 0x47, 0x08, 0x54, 0x46, 0xb5, 0x4c, 0xc7, 0x89, 0xa5, 0xe2, + 0x92, 0x7c, 0xf5, 0x5e, 0x1f, 0xe7, 0x1b, 0xdf, 0x17, 0x56, 0x23, 0x88, 0xc1, 0x5b, 0x28, 0xfa, 0x9e, 0x14, 0xe1, + 0x39, 0x2c, 0xcf, 0xf6, 0x76, 0xa7, 0xd8, 0x63, 0x55, 0x88, 0xa4, 0x82, 0x31, 0xc6, 0x8c, 0x62, 0xdc, 0x13, 0x35, + 0xb5, 0x88, 0xc4, 0x96, 0xad, 0xc3, 0x02, 0x0f, 0x00, 0xa0, 0xa5, 0x29, 0xbd, 0xcc, 0xb6, 0xea, 0x3c, 0x97, 0xf0, + 0x31, 0xf2, 0x50, 0x64, 0xe3, 0xf7, 0x6b, 0x32, 0x50, 0x10, 0xee, 0x8d, 0x96, 0x87, 0x89, 0x71, 0xb0, 0x8a, 0x42, + 0x16, 0xe8, 0x0d, 0xda, 0xa9, 0x12, 0xa1, 0xb8, 0x39, 0x59, 0x87, 0x1b, 0x4e, 0x2a, 0xd8, 0x42, 0x25, 0x2c, 0x95, + 0x16, 0xf8, 0xd5, 0x46, 0x58, 0x3c, 0x65, 0xdc, 0x7f, 0x53, 0xe1, 0x0c, 0xfa, 0x83, 0x7b, 0xcb, 0x8c, 0xfa, 0x7e, + 0xe9, 0x44, 0xa6, 0x02, 0x13, 0x37, 0xb3, 0xd4, 0x7e, 0xbf, 0xac, 0xd2, 0x7e, 0x5e, 0x2e, 0xf7, 0x39, 0x69, 0xbe, + 0xd6, 0x1d, 0x34, 0x9f, 0x0c, 0xf7, 0x2b, 0xe5, 0x87, 0x16, 0x46, 0x4d, 0xf9, 0xd5, 0x97, 0x34, 0xcc, 0x3d, 0x15, + 0xde, 0xea, 0xb6, 0x51, 0xe8, 0xa2, 0x3e, 0x07, 0x43, 0x48, 0x7f, 0x05, 0xd7, 0xd0, 0xe0, 0x41, 0x91, 0x2c, 0x16, + 0x6b, 0x17, 0xc4, 0xf5, 0x31, 0xa7, 0xda, 0xa1, 0x8c, 0x31, 0xe2, 0x69, 0xc9, 0x41, 0x92, 0xc1, 0xc1, 0xf8, 0x0d, + 0x0c, 0x88, 0x49, 0x49, 0x48, 0x87, 0xd0, 0x59, 0x99, 0x89, 0xa8, 0xdc, 0xc5, 0xdb, 0x8d, 0xcb, 0x9a, 0x42, 0x11, + 0x76, 0x82, 0x99, 0x4a, 0xa9, 0x20, 0x90, 0x26, 0xdf, 0x46, 0xab, 0x16, 0x0c, 0x05, 0xd1, 0x60, 0x28, 0x20, 0x0f, + 0xd3, 0x55, 0xc2, 0x8d, 0x8f, 0xe2, 0xe0, 0x79, 0x85, 0x1a, 0xf1, 0x52, 0x83, 0xaf, 0x61, 0xf3, 0xd7, 0x44, 0x49, + 0x11, 0x72, 0x11, 0x7b, 0x05, 0x9f, 0x08, 0xd9, 0x94, 0x87, 0x39, 0xd0, 0x0f, 0xed, 0xca, 0x4e, 0xb6, 0x97, 0x57, + 0x2e, 0x2d, 0x1a, 0x5b, 0x89, 0x9a, 0xb5, 0x38, 0x8a, 0xb7, 0xb3, 0x3e, 0x4c, 0x4d, 0x09, 0x04, 0xa4, 0xa9, 0x9c, + 0xa4, 0x9a, 0xf7, 0x28, 0xeb, 0x03, 0x48, 0xb0, 0xfb, 0x09, 0x2c, 0xf4, 0x9b, 0x12, 0x13, 0x2c, 0xaa, 0xc6, 0x6e, + 0x53, 0xd0, 0x9a, 0x53, 0xd2, 0x7c, 0x53, 0x84, 0x70, 0x5b, 0x59, 0xcf, 0x98, 0x1d, 0x60, 0xdb, 0xee, 0x76, 0x7e, + 0x94, 0x6d, 0xb7, 0xfa, 0x86, 0xe0, 0xc2, 0xe3, 0xff, 0xa4, 0xc4, 0x34, 0x90, 0x42, 0xea, 0xc6, 0x4f, 0xa8, 0xc3, + 0x3e, 0x91, 0x3a, 0x11, 0x03, 0x9a, 0xab, 0xb1, 0xe8, 0xdc, 0x6b, 0x8e, 0x92, 0xcb, 0xaa, 0xda, 0xd5, 0x12, 0x34, + 0x74, 0x23, 0x19, 0x13, 0xc5, 0x3c, 0x27, 0x00, 0x46, 0xb1, 0xf9, 0x73, 0xae, 0x93, 0xbc, 0x7f, 0x59, 0x99, 0xda, + 0xed, 0xfb, 0x7e, 0x94, 0x9f, 0xd1, 0x91, 0x8a, 0xca, 0xe6, 0x24, 0xe6, 0xdf, 0x95, 0x60, 0x1a, 0x13, 0x1f, 0xe9, + 0xb9, 0xfa, 0xa1, 0x00, 0x5f, 0xd9, 0x50, 0x6a, 0xb6, 0xd7, 0xbf, 0x75, 0xb6, 0x07, 0x72, 0x36, 0xc1, 0x02, 0x0b, + 0x74, 0x59, 0x83, 0x2f, 0x60, 0x19, 0xdc, 0x91, 0x7e, 0x0a, 0xbe, 0x9f, 0xd6, 0xc1, 0x67, 0xec, 0x7f, 0x01, 0x68, + 0x55, 0x60, 0x40, 0xf9, 0x70, 0xd1, 0xb0, 0x12, 0xe2, 0x12, 0x15, 0x66, 0x15, 0xe7, 0x8f, 0xeb, 0xbc, 0x6e, 0x5a, + 0x96, 0x18, 0x94, 0x9f, 0xba, 0x86, 0x1b, 0xdf, 0x59, 0xc8, 0x1f, 0xdf, 0x7f, 0x09, 0xba, 0x9d, 0x48, 0xbb, 0xb5, + 0x55, 0x6c, 0x90, 0x85, 0x86, 0xf7, 0xc2, 0xa6, 0xd0, 0x16, 0x2f, 0x02, 0x14, 0xea, 0x3b, 0x16, 0xe3, 0x6d, 0x11, + 0x2a, 0xc3, 0x2f, 0x58, 0x30, 0x05, 0x0c, 0xc1, 0x63, 0xa7, 0x32, 0xf9, 0x1d, 0x36, 0x9a, 0x62, 0xd7, 0x42, 0x18, + 0x7c, 0x39, 0xa8, 0x4a, 0xc9, 0x8b, 0x75, 0xb2, 0xbd, 0x38, 0x87, 0xef, 0xaf, 0xe3, 0x02, 0xa8, 0x83, 0xe8, 0x6b, + 0x2a, 0x8b, 0x0d, 0xe4, 0xe2, 0xa6, 0xac, 0xf5, 0x8a, 0x86, 0xc3, 0x1b, 0xbb, 0xf0, 0xba, 0x02, 0x1f, 0x47, 0xe9, + 0x30, 0x11, 0x93, 0x98, 0x49, 0x95, 0x2b, 0x72, 0x6d, 0x74, 0x2f, 0x6d, 0xd1, 0xbc, 0x14, 0x12, 0xbc, 0x22, 0xf0, + 0x82, 0xd0, 0x57, 0xfa, 0x72, 0xb5, 0x81, 0x82, 0x47, 0xed, 0x8b, 0x8b, 0x60, 0x62, 0xe2, 0x71, 0x43, 0x6a, 0xfa, + 0x75, 0x38, 0xb5, 0xb2, 0x58, 0x72, 0xf8, 0x75, 0xce, 0xd8, 0x82, 0x02, 0x20, 0x3e, 0x79, 0xb4, 0xde, 0x4d, 0x7a, + 0xa3, 0xb4, 0x83, 0xd2, 0x08, 0xf1, 0x5d, 0x85, 0xaf, 0x3b, 0x57, 0x7c, 0xe5, 0xaa, 0x7b, 0x5f, 0x57, 0xdc, 0xb8, + 0x60, 0xf4, 0x92, 0x4f, 0x92, 0x85, 0x6b, 0x37, 0x74, 0x57, 0xe7, 0x3b, 0xef, 0x0b, 0x99, 0xb7, 0x70, 0x05, 0x76, + 0xfe, 0x15, 0x77, 0x5e, 0x7a, 0x1f, 0x8c, 0x13, 0xe5, 0xef, 0xcd, 0x23, 0x5e, 0x39, 0xcc, 0xaa, 0x93, 0xe4, 0xef, + 0x7b, 0xdf, 0x07, 0xeb, 0x5b, 0x1a, 0x27, 0xc8, 0x6d, 0x75, 0x82, 0x4c, 0x94, 0x1b, 0xe9, 0x0d, 0xb7, 0x7f, 0x57, + 0x81, 0x20, 0x4e, 0xc5, 0xf4, 0x51, 0x39, 0xae, 0x1f, 0x2d, 0x50, 0xa9, 0x88, 0xf8, 0x5c, 0xe5, 0xae, 0xac, 0x4d, + 0x0d, 0xf5, 0x98, 0x4e, 0x66, 0xa1, 0x69, 0x56, 0xe4, 0x52, 0x2e, 0x7a, 0x8c, 0x5c, 0xb3, 0x53, 0x6d, 0x7e, 0x77, + 0xed, 0x21, 0x1d, 0xc7, 0xfb, 0x9e, 0xb5, 0x5a, 0x70, 0xbf, 0xab, 0x28, 0xbc, 0xeb, 0xc5, 0x46, 0x2a, 0x43, 0xcd, + 0x7a, 0x14, 0x7d, 0x1c, 0x77, 0x31, 0x97, 0x47, 0xd9, 0x9f, 0x35, 0x00, 0x4c, 0x47, 0x58, 0x74, 0x37, 0x3d, 0x63, + 0x4f, 0xa0, 0xa7, 0x27, 0x32, 0x48, 0xf4, 0x56, 0xe7, 0xab, 0x56, 0x89, 0xa5, 0x2b, 0x08, 0xec, 0xde, 0x90, 0xb1, + 0x2a, 0x69, 0xb7, 0x5c, 0xbf, 0x9c, 0xe7, 0xf3, 0x9c, 0x2f, 0xe5, 0xf9, 0xd4, 0x2c, 0xba, 0x8d, 0xa6, 0x7b, 0x73, + 0x6a, 0xa8, 0x98, 0x6b, 0x75, 0x93, 0xdf, 0x30, 0x5d, 0x0b, 0x43, 0x2d, 0x82, 0xcc, 0x6a, 0x57, 0xbd, 0x28, 0xcb, + 0x51, 0x3d, 0x93, 0x63, 0x24, 0x7c, 0x53, 0xe9, 0x0e, 0xd1, 0x0d, 0x53, 0x35, 0xd3, 0x77, 0x0b, 0xdb, 0x42, 0xb6, + 0x79, 0x79, 0x35, 0xcc, 0x81, 0xd2, 0x72, 0x7f, 0x99, 0x30, 0x7c, 0x77, 0x7d, 0xfd, 0x9d, 0x90, 0x53, 0x55, 0x47, + 0x6f, 0xfe, 0x5a, 0xf7, 0x0c, 0x46, 0xa5, 0x72, 0x22, 0x4e, 0xf9, 0xea, 0xc1, 0x17, 0x77, 0xaf, 0x80, 0xe5, 0x14, + 0xb0, 0x3b, 0xe5, 0xce, 0xc2, 0x50, 0xd5, 0x06, 0xfe, 0x62, 0xf5, 0x60, 0xab, 0xf6, 0xf0, 0x17, 0xbd, 0x2f, 0x82, + 0x1b, 0x1b, 0x1b, 0xdb, 0x78, 0xb7, 0x96, 0x08, 0xf2, 0x16, 0x0f, 0xf4, 0xf1, 0xea, 0xa3, 0xa0, 0xe5, 0x0a, 0xb1, + 0xcd, 0x7a, 0x0e, 0x85, 0xad, 0x41, 0xbe, 0x49, 0x99, 0x34, 0x98, 0x15, 0x3c, 0x9b, 0xc8, 0x19, 0x0a, 0x79, 0xcd, + 0xc7, 0x41, 0xdb, 0x11, 0xfe, 0x0f, 0x9c, 0xda, 0xf1, 0xf2, 0xfc, 0x13, 0xf4, 0x01, 0x4f, 0x57, 0x4a, 0x53, 0x8a, + 0x53, 0xaa, 0xa0, 0xce, 0x72, 0x9d, 0x07, 0x23, 0xc5, 0xc5, 0x18, 0x16, 0x17, 0x5c, 0x96, 0x1b, 0x67, 0x23, 0xa7, + 0xbf, 0xc4, 0xab, 0x8b, 0x74, 0xf9, 0x48, 0x64, 0xab, 0x96, 0xde, 0x2b, 0x7d, 0xba, 0x6d, 0x4f, 0x18, 0x1f, 0x67, + 0x43, 0x3a, 0x98, 0xf1, 0x71, 0x22, 0xbc, 0x3e, 0x31, 0xd4, 0x77, 0x8b, 0xc0, 0x74, 0x73, 0x6c, 0xf2, 0xc3, 0xf1, + 0x7a, 0xb3, 0x59, 0xe3, 0xf6, 0xde, 0x39, 0x9f, 0x9c, 0x79, 0x89, 0x11, 0x95, 0xb9, 0x86, 0x07, 0xb4, 0x42, 0xbc, + 0x78, 0xcf, 0x04, 0xc6, 0x65, 0x57, 0x24, 0xb5, 0xdd, 0x40, 0xe0, 0x62, 0x8f, 0x62, 0x96, 0x0c, 0x6d, 0x0f, 0xca, + 0x03, 0x7d, 0x31, 0x9a, 0x6e, 0x01, 0xd3, 0xf2, 0xda, 0xd9, 0x45, 0x6a, 0x7b, 0xd5, 0x54, 0x01, 0xcc, 0x92, 0xe5, + 0xf1, 0x19, 0xb2, 0xee, 0x57, 0xd0, 0x45, 0x0c, 0x18, 0x1b, 0x57, 0xe6, 0xdc, 0xf9, 0xaa, 0x15, 0xf1, 0x8d, 0x26, + 0xd2, 0xa4, 0x3e, 0xa2, 0xbe, 0xfd, 0xb0, 0x56, 0x57, 0x39, 0x48, 0xe0, 0x1e, 0x79, 0x77, 0xc4, 0xa5, 0xa3, 0xcf, + 0x2c, 0x36, 0xab, 0xf4, 0x2d, 0x75, 0x2d, 0x6e, 0x31, 0xec, 0x15, 0xf7, 0xc0, 0xfe, 0xc0, 0xb8, 0x45, 0x2c, 0xe2, + 0xed, 0xac, 0x96, 0xc2, 0xba, 0x30, 0x47, 0x8e, 0xb1, 0xf6, 0xe0, 0x15, 0xaf, 0xd6, 0x0c, 0xcc, 0x30, 0xe3, 0x8c, + 0xe4, 0x8d, 0x71, 0xaf, 0x6a, 0xd3, 0x91, 0xab, 0x00, 0xa2, 0x6f, 0x4e, 0x97, 0xe4, 0xf0, 0x4a, 0x96, 0xab, 0xce, + 0x90, 0x7f, 0x86, 0x75, 0xd6, 0x8b, 0x13, 0x70, 0x93, 0xa6, 0xac, 0xc4, 0xc4, 0x14, 0x71, 0xb9, 0x59, 0xc6, 0x3c, + 0x4d, 0x9f, 0x45, 0x3b, 0x38, 0x85, 0x91, 0xc0, 0x11, 0xfb, 0xc6, 0x32, 0x2c, 0x26, 0x6c, 0xc4, 0x44, 0x1a, 0x95, + 0x52, 0xc2, 0x7a, 0x72, 0xa9, 0x25, 0x7f, 0x99, 0xcb, 0xab, 0x2f, 0xb7, 0x09, 0x0e, 0x28, 0x6a, 0x60, 0x39, 0x34, + 0x8e, 0x5b, 0x06, 0x12, 0xb1, 0x18, 0x10, 0xa3, 0x56, 0xe5, 0x72, 0x32, 0xaa, 0x93, 0xfa, 0x0a, 0xb9, 0x50, 0x91, + 0x07, 0xb7, 0x04, 0x4a, 0xfe, 0x02, 0x53, 0x07, 0xd3, 0x52, 0xbb, 0x69, 0xb1, 0x49, 0xf2, 0x8e, 0x19, 0x90, 0x5c, + 0x7d, 0x0d, 0x0f, 0x8d, 0x5f, 0x86, 0x37, 0x14, 0x3d, 0x1d, 0x23, 0xe4, 0xb4, 0x34, 0xe6, 0xd2, 0x7f, 0x23, 0xcf, + 0xbe, 0x24, 0x60, 0x3f, 0x83, 0x98, 0x32, 0x70, 0x89, 0x8d, 0x0b, 0x92, 0xf2, 0x5a, 0x9e, 0xb2, 0xfb, 0x16, 0x94, + 0xef, 0x92, 0x49, 0x57, 0xa9, 0xac, 0x35, 0x56, 0xdd, 0xcf, 0x33, 0x96, 0x5f, 0x1d, 0x30, 0xcc, 0x4d, 0x46, 0x83, + 0x6c, 0xc9, 0xcc, 0xa6, 0xfc, 0x6a, 0xef, 0xc6, 0xb7, 0x3c, 0x94, 0x74, 0xa8, 0x56, 0xe9, 0xe6, 0xa5, 0x1b, 0x8e, + 0xf1, 0xc2, 0x0d, 0xc7, 0xb8, 0x43, 0xe7, 0xca, 0x15, 0xa9, 0x75, 0xfe, 0xfb, 0x52, 0xf8, 0x49, 0xec, 0xb5, 0xbe, + 0xde, 0x75, 0xfd, 0x95, 0xe9, 0xe9, 0x37, 0xa0, 0x6a, 0x64, 0x09, 0xdd, 0x84, 0x2a, 0x26, 0x23, 0x51, 0x62, 0xba, + 0x4a, 0x79, 0xd4, 0xd7, 0x88, 0x0b, 0x10, 0x37, 0x94, 0xbf, 0xf8, 0x97, 0xf0, 0xe2, 0x24, 0x40, 0x23, 0x6a, 0x3e, + 0xca, 0x52, 0xde, 0x18, 0x45, 0x93, 0x38, 0xb9, 0x0a, 0x66, 0x71, 0x63, 0x92, 0xa5, 0x59, 0x31, 0x05, 0xae, 0xf4, + 0x8a, 0x2b, 0xb0, 0xe1, 0x27, 0x8d, 0x59, 0xec, 0xbd, 0x64, 0xc9, 0x39, 0xe3, 0xf1, 0x20, 0xf2, 0xec, 0xfd, 0x1c, + 0xc4, 0x83, 0xf5, 0x36, 0xca, 0xf3, 0xec, 0xc2, 0xf6, 0x3e, 0x64, 0xa7, 0xc0, 0xb4, 0xde, 0xbb, 0xcb, 0xab, 0x33, + 0x96, 0x7a, 0x1f, 0x4f, 0x67, 0x29, 0x9f, 0x79, 0x45, 0x94, 0x16, 0x8d, 0x82, 0xe5, 0xf1, 0x08, 0xd4, 0x44, 0x92, + 0xe5, 0x0d, 0xcc, 0x7f, 0x9e, 0xb0, 0x20, 0x89, 0xcf, 0xc6, 0xdc, 0x1a, 0x46, 0xf9, 0xa7, 0x4e, 0xa3, 0x31, 0xcd, + 0xe3, 0x49, 0x94, 0x5f, 0x35, 0xa8, 0x45, 0x70, 0xaf, 0xb9, 0x1b, 0x7d, 0x36, 0x7a, 0xd0, 0xe1, 0x39, 0xf4, 0x8d, + 0x91, 0x8a, 0x01, 0x08, 0x1f, 0x6b, 0xf7, 0x61, 0x73, 0x52, 0x6c, 0x88, 0x13, 0xa5, 0x28, 0xe5, 0xe5, 0x89, 0x77, + 0x01, 0xb6, 0xed, 0x89, 0x7f, 0xca, 0x53, 0x0f, 0x7c, 0x39, 0x9e, 0xa5, 0xf3, 0xc1, 0x2c, 0x2f, 0x60, 0x80, 0x69, + 0x16, 0xa7, 0x9c, 0xe5, 0x9d, 0xd3, 0x2c, 0x07, 0xb2, 0x35, 0xf2, 0x68, 0x18, 0xcf, 0x8a, 0xe0, 0xc1, 0xf4, 0xb2, + 0x83, 0xb6, 0xc2, 0x59, 0x9e, 0xcd, 0xd2, 0xa1, 0x9c, 0x2b, 0x4e, 0x61, 0x63, 0xc4, 0xdc, 0xac, 0xa0, 0x37, 0xa1, + 0x00, 0x7c, 0x29, 0x8b, 0xf2, 0xc6, 0x19, 0x76, 0x46, 0x43, 0xbf, 0x39, 0x64, 0x67, 0x5e, 0x7e, 0x76, 0x1a, 0x39, + 0xad, 0xf6, 0x63, 0x4f, 0xfd, 0xf9, 0x0f, 0x5d, 0x30, 0xdc, 0x57, 0x16, 0xb7, 0x9a, 0xcd, 0xbf, 0x71, 0x3b, 0x0b, + 0xb3, 0x10, 0x40, 0x41, 0x6b, 0x7a, 0x69, 0x15, 0x59, 0x02, 0xeb, 0xb3, 0xaa, 0x67, 0x67, 0x0a, 0x7e, 0x53, 0x9c, + 0x9e, 0x05, 0xed, 0xe9, 0x65, 0x89, 0xd8, 0x05, 0x22, 0x21, 0x53, 0x22, 0x29, 0x9f, 0xe6, 0xbf, 0x15, 0xe2, 0x27, + 0xab, 0x21, 0x6e, 0x2b, 0x88, 0x2b, 0xaa, 0x37, 0x86, 0xb0, 0x0f, 0x88, 0xfc, 0xad, 0x42, 0x00, 0x32, 0x06, 0x27, + 0x30, 0x57, 0x70, 0xd0, 0xc3, 0x6f, 0x06, 0xa3, 0xbd, 0x1a, 0x8c, 0x27, 0xb7, 0x81, 0x91, 0xa7, 0xc3, 0x79, 0x7d, + 0x5d, 0x5b, 0xe0, 0x9c, 0x76, 0xc6, 0x0c, 0xf9, 0x29, 0x68, 0xe3, 0xf7, 0x8b, 0x78, 0xc8, 0xc7, 0xe2, 0x2b, 0xb1, + 0xf3, 0x85, 0xa8, 0x7b, 0xd8, 0x6c, 0x8a, 0xe7, 0x02, 0x14, 0x5a, 0xd0, 0xf2, 0xb1, 0x01, 0x30, 0xd1, 0xe7, 0xeb, + 0x5e, 0x62, 0xf3, 0xed, 0xad, 0x6f, 0xaa, 0xf1, 0xb8, 0xca, 0x1b, 0x14, 0x2a, 0x42, 0xbd, 0xb3, 0x05, 0x33, 0xde, + 0x8a, 0x6e, 0x4b, 0x1f, 0x54, 0xf5, 0xbe, 0xe5, 0xa4, 0xf5, 0x02, 0xe6, 0x99, 0xb9, 0x40, 0x9d, 0xac, 0x8b, 0x21, + 0xa9, 0x46, 0xc3, 0x05, 0xbd, 0xc1, 0x31, 0x84, 0x44, 0x07, 0x82, 0x4e, 0xd1, 0xcb, 0xe9, 0x9d, 0x1a, 0xa9, 0x1b, + 0xe4, 0x4e, 0xea, 0xc2, 0x96, 0x4f, 0xb5, 0x5c, 0x2f, 0xb6, 0xb6, 0xc0, 0xcb, 0xfe, 0x9c, 0xcb, 0x06, 0x20, 0xbd, + 0x2b, 0x49, 0x6b, 0xbc, 0x87, 0x44, 0xb9, 0x7c, 0xd9, 0x80, 0x28, 0x07, 0xbe, 0x3e, 0x1f, 0xa3, 0xdf, 0xad, 0xaf, + 0xae, 0x1b, 0x29, 0x35, 0x3b, 0xb6, 0xdb, 0xe3, 0x3a, 0x2b, 0x0b, 0xb3, 0xcf, 0x78, 0x89, 0xa3, 0x7c, 0xc9, 0x43, + 0x1c, 0xd1, 0x7b, 0x15, 0x0a, 0x37, 0x4d, 0x39, 0x69, 0xa3, 0xbb, 0x3a, 0x69, 0xf0, 0x35, 0xa6, 0xcc, 0x67, 0x15, + 0x27, 0x07, 0x37, 0xe6, 0x78, 0x20, 0xae, 0x20, 0x16, 0x55, 0x96, 0x7d, 0x44, 0xd0, 0x0b, 0xbf, 0x0b, 0x94, 0x14, + 0x46, 0x2e, 0xbf, 0xe2, 0xbf, 0xc3, 0xe3, 0x70, 0x34, 0xfa, 0x45, 0x36, 0xcb, 0x07, 0x78, 0x39, 0x60, 0x45, 0x28, + 0xc2, 0x26, 0x4b, 0xc0, 0xf6, 0xb8, 0x56, 0x40, 0x0c, 0xf3, 0x2c, 0xcc, 0xb7, 0x2f, 0x30, 0x3a, 0x9d, 0x11, 0x97, + 0x1f, 0x64, 0xf8, 0x45, 0xa1, 0x84, 0x3a, 0x75, 0x48, 0x89, 0x78, 0x74, 0x31, 0xd4, 0x9f, 0xa5, 0x31, 0x88, 0xe0, + 0xe3, 0x78, 0x48, 0x17, 0x62, 0xe2, 0x21, 0x9d, 0x90, 0x34, 0x28, 0x23, 0x0a, 0x43, 0xee, 0x50, 0x20, 0x17, 0x06, + 0xbf, 0xcb, 0x0c, 0x1b, 0xbb, 0x61, 0xe3, 0x29, 0x87, 0xa1, 0xc3, 0x87, 0xd9, 0x24, 0x8a, 0xd3, 0x00, 0x5f, 0x5c, + 0xe2, 0xe9, 0x11, 0x03, 0xec, 0xe2, 0xc1, 0xa7, 0x5a, 0xa3, 0x96, 0xeb, 0xff, 0x04, 0x02, 0x8e, 0xfa, 0x63, 0x32, + 0x0b, 0x91, 0x55, 0x10, 0x31, 0x54, 0x64, 0xde, 0x57, 0x7a, 0xde, 0x33, 0xab, 0x55, 0xcc, 0xb4, 0xbe, 0x0e, 0xcd, + 0x85, 0xe5, 0xd2, 0x67, 0xd8, 0xf5, 0x52, 0x10, 0xac, 0x5c, 0xe7, 0xd1, 0x53, 0x10, 0x67, 0x8f, 0xd1, 0x47, 0xaf, + 0xd1, 0x0a, 0x5a, 0xda, 0x2f, 0xaf, 0x5d, 0xb5, 0x15, 0x89, 0x3a, 0xf2, 0xba, 0x26, 0xe1, 0xa1, 0xbf, 0x0b, 0x5c, + 0xab, 0x67, 0x8d, 0xaf, 0x27, 0x37, 0x1d, 0x46, 0xa7, 0xce, 0x52, 0xa7, 0x06, 0x04, 0x1d, 0x74, 0xac, 0x99, 0xca, + 0x2d, 0x2b, 0xbc, 0xb5, 0xf1, 0x67, 0x0b, 0xcd, 0x89, 0xaf, 0x1e, 0x90, 0x33, 0xd2, 0x2b, 0x9e, 0x56, 0xf0, 0x5d, + 0x29, 0x09, 0xb2, 0x78, 0x21, 0x7f, 0xa1, 0x99, 0x00, 0xe5, 0x4a, 0x1f, 0x64, 0x2f, 0xd4, 0x8a, 0x47, 0x26, 0x22, + 0xde, 0xab, 0x9b, 0x50, 0xd6, 0xd8, 0x32, 0x5c, 0xe8, 0x8b, 0x16, 0x5c, 0xc1, 0x8f, 0x06, 0xd3, 0x88, 0xe1, 0xbd, + 0x94, 0x93, 0xcd, 0xf9, 0x97, 0xbc, 0xdc, 0xd9, 0x9c, 0xab, 0x86, 0xe2, 0x7b, 0x3c, 0xc4, 0x4f, 0x06, 0xf2, 0x6b, + 0x2e, 0xac, 0xc7, 0xc0, 0x7e, 0xff, 0xee, 0xe0, 0xd0, 0xf6, 0x4e, 0xb3, 0xe1, 0x55, 0x60, 0xc3, 0xee, 0x64, 0x76, + 0xe9, 0xfa, 0x7c, 0xcc, 0x52, 0x47, 0xb1, 0x78, 0x96, 0x30, 0x90, 0x08, 0x67, 0xe2, 0xb2, 0xe3, 0xa2, 0xe7, 0x3b, + 0x3c, 0xd9, 0xa3, 0xb7, 0x21, 0x75, 0xf7, 0xb8, 0x78, 0x51, 0x18, 0xcf, 0xf1, 0x6b, 0x17, 0x63, 0xff, 0x7b, 0x3b, + 0xf0, 0x05, 0x1f, 0x0e, 0x70, 0xcf, 0xd0, 0xd3, 0xe6, 0x7c, 0x89, 0x93, 0x7a, 0x38, 0xc4, 0xb8, 0x2b, 0x50, 0x28, + 0xa8, 0xd5, 0x49, 0x30, 0x3c, 0x39, 0x29, 0xe1, 0x2b, 0x8c, 0xb5, 0xa3, 0xc6, 0x45, 0x08, 0x55, 0x7f, 0xcd, 0x5d, + 0xf2, 0x75, 0x3b, 0x38, 0x04, 0xce, 0x3b, 0xc4, 0x06, 0xc4, 0x5d, 0xd8, 0x7b, 0xa8, 0x4b, 0x68, 0xd3, 0x8a, 0xa2, + 0x75, 0x10, 0x88, 0x86, 0x15, 0xd3, 0x8b, 0x10, 0x61, 0xb5, 0xba, 0x0a, 0xa4, 0xa1, 0x09, 0xdd, 0x89, 0x8b, 0x9f, + 0x04, 0x19, 0x7c, 0x12, 0x1d, 0x4e, 0xcc, 0x37, 0x84, 0x88, 0xcb, 0xfc, 0x9a, 0x5a, 0x47, 0x7f, 0x01, 0xdb, 0xc3, + 0xbb, 0x38, 0xa1, 0x96, 0x4a, 0x1d, 0xa1, 0x9d, 0x84, 0x6a, 0xbb, 0xa9, 0xec, 0x0e, 0xd0, 0xfd, 0x49, 0x34, 0x2d, + 0x58, 0xa0, 0xbe, 0x48, 0xcd, 0x84, 0x0a, 0x6e, 0xd9, 0x14, 0x90, 0x79, 0x31, 0xcf, 0xd0, 0x60, 0x58, 0xb6, 0x53, + 0x40, 0xf4, 0x39, 0x8d, 0xc6, 0xa0, 0x71, 0x7a, 0xe6, 0x96, 0x7c, 0x3c, 0x37, 0xf5, 0xda, 0x23, 0xd0, 0x6b, 0x98, + 0x93, 0xd7, 0x00, 0x4f, 0xed, 0x2c, 0x0d, 0x12, 0x36, 0xe2, 0x25, 0xc7, 0x4b, 0x5f, 0x73, 0x65, 0x48, 0xf8, 0xed, + 0x87, 0xa0, 0xeb, 0x2c, 0x1f, 0xff, 0xbd, 0x79, 0x62, 0xe8, 0x18, 0xa4, 0xa0, 0x9b, 0x28, 0x0b, 0x14, 0x33, 0xec, + 0x01, 0x5c, 0xf3, 0x79, 0x6e, 0x4c, 0x34, 0x60, 0x68, 0x64, 0x95, 0x1c, 0x64, 0xf2, 0xd8, 0xe3, 0xb9, 0xd9, 0x2e, + 0x75, 0xe7, 0x4b, 0x18, 0x2c, 0xeb, 0xfa, 0x5d, 0xb7, 0x2c, 0xc8, 0x64, 0x5d, 0x6e, 0xac, 0x0c, 0xa6, 0xfa, 0xd3, + 0x12, 0xf9, 0x0c, 0xd3, 0xae, 0x14, 0xc1, 0xd2, 0xb9, 0xe8, 0x71, 0x17, 0x62, 0xd6, 0x8c, 0x4e, 0xcf, 0xec, 0xe1, + 0x96, 0x71, 0x3a, 0x9d, 0xf1, 0x23, 0x0a, 0xd4, 0xe6, 0x78, 0x9d, 0xa0, 0x3f, 0x17, 0x73, 0x83, 0x17, 0x3c, 0x70, + 0x10, 0x00, 0xab, 0x61, 0x3d, 0x01, 0x6a, 0xba, 0xca, 0xf0, 0xf0, 0x1f, 0x23, 0x71, 0x4b, 0x9f, 0x5a, 0xaf, 0xa0, + 0xd2, 0x09, 0x58, 0xdd, 0x1d, 0xce, 0x9d, 0xa3, 0x37, 0x8e, 0xdb, 0xf7, 0x5e, 0x19, 0x2f, 0x2f, 0xb1, 0xd5, 0x1e, + 0xb0, 0x3d, 0xa4, 0xf7, 0xca, 0x26, 0x26, 0x93, 0x53, 0xb3, 0x57, 0x21, 0x36, 0x7c, 0xeb, 0xd8, 0xac, 0x98, 0x36, + 0x84, 0x48, 0x6a, 0x10, 0x33, 0xda, 0xd8, 0x55, 0x05, 0x56, 0xbf, 0xe2, 0x73, 0x92, 0x36, 0x5c, 0xbf, 0x29, 0xe4, + 0x88, 0xf7, 0xcd, 0x5b, 0x2d, 0xb5, 0x80, 0x3a, 0xd4, 0xb9, 0x86, 0xe4, 0x83, 0x47, 0xf9, 0xd6, 0x1b, 0x25, 0x37, + 0x4e, 0xf6, 0xeb, 0x92, 0x0c, 0xf6, 0x59, 0xa9, 0xdf, 0xa8, 0x06, 0x5a, 0x18, 0xe7, 0x87, 0x8d, 0x24, 0xf7, 0xdd, + 0x53, 0xb2, 0x12, 0x55, 0x1c, 0x9c, 0xae, 0x2c, 0xaa, 0x13, 0x0d, 0xa1, 0x50, 0x63, 0x3c, 0x77, 0xad, 0x25, 0xdd, + 0x76, 0x2a, 0x59, 0x24, 0x6c, 0x4c, 0x8b, 0xf0, 0x08, 0x6d, 0x30, 0xfa, 0x6c, 0xeb, 0xcf, 0x03, 0x50, 0x7f, 0x9f, + 0x42, 0x7b, 0x73, 0xee, 0xb8, 0xab, 0xef, 0xcd, 0x29, 0xcf, 0x50, 0x49, 0x61, 0x23, 0x63, 0xb1, 0x26, 0x5c, 0xd1, + 0x41, 0xb5, 0xbb, 0x28, 0x3e, 0xf7, 0x76, 0xc4, 0x44, 0xb0, 0xdb, 0x8f, 0xe5, 0x8b, 0x9e, 0xb8, 0x29, 0x12, 0x91, + 0xbc, 0xa2, 0xdc, 0x22, 0x36, 0x09, 0xed, 0x5b, 0x79, 0xc7, 0xb6, 0x84, 0x94, 0x42, 0x40, 0x95, 0xc0, 0x02, 0xe0, + 0x75, 0x19, 0x93, 0xb0, 0xc7, 0x92, 0x0c, 0x36, 0xce, 0x05, 0x8a, 0x00, 0x03, 0x47, 0x3c, 0x8a, 0x13, 0xd1, 0x45, + 0x06, 0xf6, 0x94, 0x03, 0xa8, 0x31, 0xc2, 0x23, 0xf5, 0x3a, 0x2e, 0x75, 0x12, 0x12, 0x66, 0x7b, 0x3b, 0x15, 0xdc, + 0x84, 0x19, 0xed, 0x32, 0xf3, 0x00, 0xab, 0xc2, 0x50, 0xd4, 0x01, 0x71, 0xe9, 0xda, 0x0c, 0x02, 0x58, 0xa8, 0x60, + 0x87, 0x97, 0xaa, 0x2b, 0x2c, 0x02, 0x96, 0x1c, 0x13, 0x85, 0xc1, 0xc8, 0x63, 0x5c, 0x13, 0x36, 0x17, 0xd9, 0x8f, + 0x0a, 0xda, 0x74, 0x09, 0xda, 0xb4, 0x0e, 0xed, 0x09, 0x12, 0xbd, 0xb7, 0x39, 0x8f, 0xcb, 0x10, 0xbe, 0xa5, 0x83, + 0x6c, 0xc8, 0x3e, 0x7e, 0x78, 0x85, 0x77, 0x00, 0xa1, 0x3d, 0x38, 0x0b, 0x99, 0x5b, 0x9e, 0xc8, 0xc5, 0x31, 0x75, + 0x82, 0xd8, 0xdb, 0x16, 0xcd, 0x45, 0x74, 0x05, 0x8a, 0xf6, 0x04, 0xe4, 0x6c, 0x48, 0x05, 0x61, 0x98, 0x53, 0x2f, + 0x0e, 0x4b, 0x2a, 0x5a, 0x0b, 0x99, 0x2e, 0x1a, 0x21, 0x11, 0x68, 0x67, 0x56, 0x34, 0xc0, 0x9c, 0x59, 0x93, 0x0e, + 0xc3, 0xf8, 0x5c, 0x73, 0x1b, 0x5d, 0x20, 0xea, 0xee, 0x01, 0x43, 0xb3, 0x04, 0xc6, 0xcc, 0xaf, 0xaf, 0x9b, 0x30, + 0x94, 0x78, 0xb4, 0xf6, 0x48, 0x36, 0x88, 0x77, 0x61, 0xc2, 0xcc, 0x2d, 0x4c, 0x4f, 0xc2, 0xab, 0x7a, 0x3d, 0x95, + 0x6f, 0x13, 0xc8, 0x01, 0x00, 0x46, 0x3a, 0xea, 0x27, 0x3e, 0xd0, 0xe6, 0x0d, 0x94, 0xc6, 0xc3, 0xe5, 0x32, 0xb0, + 0x4a, 0xa7, 0x58, 0x9a, 0x5d, 0x5f, 0xb7, 0xe0, 0x71, 0x12, 0xa7, 0xf8, 0x04, 0x33, 0xd3, 0x0d, 0x38, 0x78, 0x04, + 0xd3, 0x1c, 0xd8, 0x16, 0x6a, 0xa2, 0x4b, 0xac, 0x49, 0x55, 0x4d, 0x74, 0x09, 0xf2, 0x48, 0x54, 0x69, 0xf2, 0x14, + 0xc8, 0x70, 0xff, 0x1f, 0x16, 0x34, 0x93, 0x8b, 0x67, 0x69, 0xd2, 0x01, 0x98, 0x20, 0x2d, 0x35, 0xf1, 0xf6, 0x76, + 0x80, 0xcc, 0xb0, 0x18, 0xd2, 0xfa, 0x91, 0x3b, 0xae, 0x7a, 0x8f, 0x91, 0x90, 0x64, 0x6e, 0x2d, 0x0d, 0x81, 0x8a, + 0xd0, 0x1a, 0x04, 0xdf, 0x62, 0x78, 0x4c, 0x9b, 0x03, 0xf4, 0xbc, 0xd4, 0xfe, 0x0b, 0xb2, 0xa6, 0xea, 0xe0, 0xd9, + 0x7f, 0xfd, 0xc7, 0xbf, 0xb3, 0x3d, 0xb1, 0xb9, 0xb2, 0xd1, 0x08, 0x4c, 0x65, 0xeb, 0x0e, 0x7d, 0xfe, 0xd7, 0xdf, + 0xff, 0xdf, 0xff, 0xf3, 0x5f, 0x75, 0xb7, 0x14, 0x7a, 0x9d, 0xc8, 0x83, 0x3f, 0x25, 0x1d, 0x0c, 0x30, 0x15, 0x1a, + 0xa3, 0x28, 0x5d, 0x87, 0xc3, 0x91, 0x89, 0x43, 0x31, 0x65, 0x6c, 0xe8, 0xd9, 0x96, 0xed, 0x2d, 0x95, 0x1e, 0x27, + 0xec, 0x9c, 0xc9, 0xb7, 0x9e, 0xad, 0x9a, 0x6a, 0x45, 0x8f, 0x01, 0x28, 0x34, 0x2e, 0xcf, 0x3f, 0x25, 0x6f, 0x9b, + 0xa8, 0x48, 0xa9, 0x52, 0xeb, 0x87, 0xb4, 0xab, 0x8b, 0x0b, 0xcf, 0x36, 0xa6, 0x5f, 0x0b, 0x57, 0x6f, 0x4d, 0x79, + 0xd0, 0xf4, 0x9a, 0xeb, 0x20, 0xf3, 0xc0, 0x8f, 0xb4, 0xed, 0xbe, 0xa2, 0x11, 0x85, 0x7b, 0xcc, 0x0b, 0xec, 0xeb, + 0x68, 0x75, 0x2b, 0xf6, 0xa7, 0x39, 0x0e, 0x95, 0xb2, 0xa2, 0xb8, 0x05, 0x79, 0x58, 0x3e, 0xcf, 0xae, 0x5a, 0xdb, + 0x6b, 0x46, 0x01, 0x14, 0xda, 0x0f, 0x1f, 0x0a, 0x70, 0x3d, 0x47, 0xbb, 0x90, 0x66, 0x63, 0x36, 0x1a, 0x81, 0x10, + 0x29, 0xdc, 0x2a, 0x1f, 0x74, 0x14, 0x27, 0x1c, 0xcf, 0xb3, 0xc3, 0xae, 0xfd, 0x16, 0x36, 0x06, 0x5e, 0x0f, 0x75, + 0xa5, 0x5f, 0xaf, 0x32, 0xfd, 0x94, 0xd0, 0x5d, 0x0d, 0x97, 0x18, 0xb2, 0x0e, 0x93, 0x9c, 0xe6, 0xfa, 0x5a, 0xf9, + 0xcb, 0xb5, 0xf2, 0x3a, 0x39, 0x33, 0x72, 0x88, 0x57, 0xef, 0x9b, 0xbb, 0xec, 0x8e, 0x7f, 0xfd, 0xa7, 0xbf, 0xff, + 0x6f, 0x00, 0x06, 0x8e, 0x73, 0xb7, 0xad, 0x01, 0x1d, 0xfe, 0x27, 0x74, 0x98, 0xa5, 0x77, 0xef, 0xf2, 0xd7, 0xff, + 0xf2, 0xdf, 0xa1, 0x07, 0x5d, 0x60, 0x86, 0x7d, 0xa4, 0x40, 0x1f, 0x60, 0xd8, 0xe8, 0x77, 0xc1, 0x5e, 0x1b, 0xf7, + 0x2e, 0x70, 0xfc, 0x03, 0xa2, 0x5a, 0xf0, 0x6c, 0x7a, 0x57, 0xb8, 0x11, 0xd3, 0x41, 0x92, 0x15, 0xcc, 0x04, 0x5c, + 0x58, 0x0a, 0xbf, 0x0f, 0x72, 0x82, 0x64, 0x0a, 0x12, 0xb4, 0xb0, 0xcc, 0xa1, 0x25, 0xaf, 0xdc, 0x28, 0x08, 0x57, + 0x32, 0x54, 0xc1, 0x38, 0x91, 0x82, 0xac, 0xb9, 0x1a, 0xd3, 0x88, 0xb2, 0x25, 0x5e, 0x22, 0xe9, 0xae, 0x25, 0x97, + 0xd0, 0x58, 0xb7, 0xcc, 0xbb, 0x62, 0x7f, 0x89, 0x69, 0xc5, 0x99, 0xd7, 0xf2, 0xf0, 0xb5, 0x12, 0x50, 0x5d, 0xc7, + 0x2b, 0x4a, 0xa3, 0xcb, 0x15, 0xa5, 0xa8, 0x04, 0x35, 0x6c, 0x60, 0xed, 0x4d, 0xc4, 0x4b, 0x2f, 0xf4, 0xeb, 0x2e, + 0x6a, 0xd0, 0x91, 0x2a, 0xc3, 0x53, 0xfc, 0xfa, 0x2b, 0x00, 0xe4, 0x50, 0x42, 0xad, 0x1d, 0xe3, 0xbd, 0x1a, 0xbc, + 0x45, 0x3d, 0xcb, 0x19, 0xec, 0x99, 0x0b, 0xf3, 0x68, 0xfe, 0xe6, 0xc6, 0x63, 0x10, 0x0f, 0x3d, 0xb0, 0x27, 0xf5, + 0xaa, 0xde, 0x38, 0x6e, 0xf9, 0x2f, 0xff, 0xec, 0xfb, 0xff, 0xf2, 0xcf, 0xb7, 0x36, 0xc5, 0x51, 0xc1, 0x65, 0xe7, + 0xd5, 0xb0, 0xeb, 0xa9, 0xbb, 0x7a, 0xa6, 0x3a, 0xb9, 0x57, 0xb7, 0x59, 0xa2, 0x3f, 0xd6, 0x2f, 0x91, 0x7f, 0xa9, + 0x50, 0x50, 0xdf, 0xfa, 0x2d, 0x80, 0x21, 0x5e, 0xb7, 0x42, 0x86, 0x8d, 0x7e, 0x17, 0x68, 0x27, 0x6e, 0x70, 0xa7, + 0x15, 0xf9, 0xed, 0x14, 0xbe, 0x0d, 0x87, 0xdf, 0x09, 0xbe, 0x48, 0x07, 0x06, 0xd0, 0x4e, 0xd4, 0x8d, 0xa9, 0x5a, + 0x57, 0xbc, 0x74, 0xd9, 0x5b, 0x2a, 0x91, 0x6a, 0x25, 0x68, 0xba, 0xdd, 0xe6, 0xd6, 0x96, 0x83, 0xdd, 0xdf, 0xe0, + 0x9b, 0x21, 0xf6, 0x4e, 0x73, 0x15, 0x03, 0xb9, 0x41, 0x34, 0xe0, 0x10, 0x75, 0xac, 0x68, 0xd0, 0x25, 0xb9, 0x80, + 0xa5, 0x98, 0x61, 0x8a, 0x60, 0x7a, 0x60, 0x0e, 0x0b, 0x7b, 0xed, 0x99, 0x70, 0x6c, 0x82, 0x45, 0xd6, 0x96, 0x0e, + 0x4f, 0x8d, 0xe8, 0x9e, 0x75, 0x48, 0xf4, 0xa2, 0xc6, 0xac, 0xb2, 0x97, 0xc9, 0x4b, 0x44, 0x03, 0xf1, 0x44, 0xbc, + 0x2b, 0xe3, 0xeb, 0x75, 0xf1, 0xf6, 0xef, 0x6f, 0x8f, 0xb7, 0xc7, 0x77, 0x8c, 0xb7, 0x7f, 0xff, 0x07, 0xc7, 0xdb, + 0xbf, 0x36, 0xe3, 0xed, 0xb8, 0x88, 0x3f, 0xdf, 0x29, 0x26, 0xae, 0x22, 0x95, 0xd9, 0x45, 0x11, 0xb6, 0xa4, 0xa5, + 0x04, 0x8e, 0x34, 0x06, 0xc4, 0xff, 0xed, 0xe3, 0xdb, 0x30, 0xd1, 0x42, 0x74, 0x9b, 0xc2, 0xd9, 0x92, 0x07, 0x99, + 0x0a, 0x26, 0x37, 0x75, 0xee, 0x77, 0xe3, 0x81, 0xba, 0xec, 0x0a, 0x2e, 0x8c, 0xab, 0x0f, 0x04, 0xda, 0x2a, 0xdc, + 0x1c, 0xd0, 0xdb, 0xaa, 0x75, 0xc7, 0xf6, 0xb6, 0x4a, 0x3a, 0x36, 0x47, 0xe8, 0xa8, 0xb3, 0x64, 0x71, 0x53, 0x72, + 0x6e, 0xff, 0xa7, 0xa3, 0x56, 0x67, 0xb7, 0x35, 0x81, 0xde, 0xc0, 0x87, 0xf0, 0xd4, 0xec, 0xec, 0xee, 0xe2, 0xd3, + 0x85, 0x7a, 0x6a, 0xe3, 0x53, 0xac, 0x9e, 0x1e, 0xe2, 0xd3, 0x40, 0x3d, 0x3d, 0xc2, 0xa7, 0xa1, 0x7a, 0x7a, 0x8c, + 0x4f, 0xe7, 0x76, 0x79, 0xc4, 0x34, 0x70, 0x8f, 0xdd, 0xbe, 0x27, 0x4c, 0x51, 0x55, 0xf6, 0xd8, 0x6b, 0x61, 0x40, + 0x3b, 0x3a, 0x0b, 0x62, 0x4f, 0x38, 0xd4, 0x41, 0xe1, 0x5d, 0x8c, 0x59, 0x1a, 0x50, 0x4e, 0xf4, 0x73, 0x7c, 0x5b, + 0x10, 0xd8, 0xc0, 0x87, 0xf1, 0x84, 0xa9, 0xd7, 0xa6, 0x2b, 0xac, 0x41, 0x25, 0x1f, 0x35, 0xfb, 0x65, 0x47, 0xaf, + 0x93, 0x88, 0x84, 0xab, 0xf4, 0x4e, 0x5a, 0xb9, 0xaa, 0x4e, 0x4c, 0xd7, 0xd0, 0x2b, 0xbc, 0x26, 0xa8, 0x6a, 0xf8, + 0x95, 0x23, 0x90, 0xcd, 0x8d, 0x4b, 0x70, 0x2c, 0x57, 0x06, 0x5a, 0x11, 0x22, 0x1d, 0x68, 0x25, 0x9c, 0xf4, 0xd3, + 0x61, 0x74, 0xa6, 0xbf, 0xbf, 0x01, 0xdb, 0x21, 0x3a, 0x93, 0x2d, 0xd7, 0x07, 0x56, 0x09, 0x44, 0x33, 0xa8, 0xaa, + 0x80, 0x40, 0xc7, 0x13, 0x97, 0x06, 0xc3, 0x04, 0x32, 0x56, 0x8a, 0xd4, 0xa9, 0x87, 0x59, 0x69, 0xfa, 0x7a, 0x11, + 0x50, 0xb4, 0x2a, 0xd8, 0x03, 0x13, 0x86, 0x4a, 0x05, 0x85, 0xa1, 0x02, 0x0b, 0x44, 0xf5, 0x9a, 0x70, 0xaa, 0x72, + 0xfd, 0xd6, 0x07, 0x55, 0x2d, 0x15, 0x4f, 0x35, 0xcf, 0xa0, 0xf5, 0x01, 0xf4, 0x72, 0x14, 0xef, 0x5e, 0x6b, 0x80, + 0xff, 0xc9, 0x18, 0xe1, 0xbd, 0xd1, 0x68, 0x74, 0x63, 0x7c, 0xf5, 0xde, 0x70, 0xc4, 0xda, 0xec, 0x61, 0x07, 0xcf, + 0x27, 0x1b, 0x32, 0x6a, 0xd7, 0x2a, 0x89, 0x76, 0xf3, 0xbb, 0x35, 0xc6, 0x00, 0x1f, 0x1f, 0xcf, 0xef, 0x1e, 0x6b, + 0x2d, 0x81, 0x2a, 0xf3, 0x09, 0x48, 0xc5, 0x38, 0x0d, 0x9a, 0xa5, 0x7f, 0x2e, 0x83, 0x93, 0xf7, 0x9e, 0x3c, 0x79, + 0x52, 0xfa, 0x43, 0xf5, 0xd4, 0x1c, 0x0e, 0x4b, 0x7f, 0x30, 0xd7, 0x68, 0x34, 0x9b, 0xa3, 0x51, 0xe9, 0xc7, 0xaa, + 0x60, 0xb7, 0x3d, 0x18, 0xee, 0xb6, 0x4b, 0xff, 0xc2, 0x68, 0x51, 0xfa, 0x4c, 0x3e, 0xe5, 0x6c, 0x58, 0x3b, 0xe4, + 0x7c, 0x0c, 0xde, 0xb6, 0x2f, 0x18, 0x6d, 0x8e, 0x86, 0xb6, 0xf8, 0x1a, 0x44, 0x33, 0x9e, 0xa1, 0x00, 0xee, 0x00, + 0x9f, 0x1f, 0x6d, 0xca, 0x6b, 0xcc, 0xe2, 0xad, 0xe4, 0x25, 0x6c, 0xa1, 0x9f, 0xcd, 0x60, 0x23, 0x32, 0x33, 0x05, + 0x19, 0x63, 0x15, 0x8b, 0xac, 0x55, 0x23, 0x67, 0x51, 0xf5, 0xcf, 0x61, 0x5c, 0xc5, 0x20, 0x51, 0xda, 0x60, 0x4b, + 0x91, 0x8c, 0xf3, 0xdd, 0x3a, 0x19, 0xff, 0xc5, 0xed, 0x32, 0xfe, 0xea, 0x6e, 0x22, 0xfe, 0x8b, 0x3f, 0x58, 0xc4, + 0x7f, 0x67, 0x8a, 0x78, 0x21, 0xc4, 0xf6, 0x79, 0x68, 0x0f, 0xc6, 0x6c, 0xf0, 0xe9, 0x34, 0xbb, 0x6c, 0xe0, 0x96, + 0xc8, 0x6d, 0x92, 0x9e, 0x93, 0xdf, 0x7a, 0x20, 0xaa, 0x06, 0x33, 0x5e, 0x71, 0x4e, 0x4a, 0xf2, 0x5d, 0x1a, 0xda, + 0xef, 0x94, 0xfd, 0x2e, 0x4a, 0x46, 0x23, 0x28, 0x1a, 0x8d, 0x6c, 0x75, 0x79, 0x03, 0xc4, 0x16, 0xb5, 0x7a, 0x5b, + 0x2b, 0xa1, 0x56, 0x9f, 0x7f, 0x6e, 0x96, 0x99, 0x05, 0x32, 0x64, 0x69, 0x86, 0x27, 0x65, 0xcd, 0x30, 0x2e, 0x70, + 0xab, 0xe1, 0x9b, 0xd7, 0x97, 0x5e, 0x69, 0x25, 0x02, 0xab, 0xcb, 0x00, 0x57, 0xf1, 0x55, 0xe3, 0xed, 0xa9, 0x55, + 0x84, 0x15, 0x16, 0x54, 0x66, 0xd6, 0x3d, 0xbd, 0x7a, 0x35, 0x74, 0xf6, 0xb9, 0x5b, 0xc6, 0xc5, 0xbb, 0x74, 0x21, + 0x63, 0x59, 0xc0, 0x18, 0x86, 0x26, 0x5a, 0x25, 0xcf, 0xce, 0xce, 0x92, 0xe5, 0x1c, 0x58, 0xd1, 0xbd, 0x57, 0xc3, + 0x37, 0x30, 0x3b, 0x4a, 0x5d, 0x46, 0x3f, 0x99, 0x21, 0x52, 0xfb, 0x28, 0x27, 0x5b, 0x1d, 0xed, 0xce, 0xa5, 0xfc, + 0x97, 0x49, 0x5f, 0x8c, 0x0e, 0x51, 0x69, 0xe0, 0x61, 0x59, 0xca, 0xcc, 0x5a, 0x20, 0xc4, 0x14, 0xdf, 0xff, 0x26, + 0x7a, 0xc6, 0xb7, 0x89, 0xf0, 0xe2, 0xc2, 0x88, 0x0b, 0xd6, 0x96, 0xab, 0x54, 0x81, 0x41, 0x11, 0xdd, 0xdb, 0xc7, + 0x10, 0xa5, 0x88, 0x11, 0x2a, 0x22, 0xda, 0x56, 0x8f, 0xbe, 0xca, 0x88, 0x65, 0x85, 0x21, 0x06, 0x33, 0xf5, 0x82, + 0xa8, 0x2a, 0x55, 0x50, 0x9a, 0x81, 0x6f, 0xaa, 0x11, 0xd4, 0xa2, 0x30, 0x1b, 0xc0, 0x9e, 0x0a, 0x31, 0x0a, 0xd3, + 0x90, 0x3c, 0xd8, 0x9c, 0x57, 0x2b, 0x0f, 0x5d, 0x25, 0xd8, 0x82, 0x79, 0x41, 0x06, 0x63, 0x87, 0xae, 0x55, 0x03, + 0x3d, 0x5d, 0x8a, 0xce, 0xdd, 0x7c, 0xee, 0x75, 0xe2, 0x17, 0x17, 0x1e, 0xfc, 0x59, 0x7f, 0x9a, 0x83, 0xd0, 0x39, + 0xfd, 0x14, 0xf3, 0x06, 0x8f, 0xa6, 0x0d, 0xb4, 0xee, 0x29, 0xc8, 0x23, 0xa5, 0x33, 0xe5, 0x6f, 0x88, 0x7b, 0x96, + 0x9d, 0x59, 0x81, 0xc7, 0x63, 0x64, 0xa3, 0x06, 0x69, 0x96, 0xb2, 0x4e, 0x3d, 0x4f, 0xc7, 0x3c, 0x6d, 0x51, 0xc4, + 0xea, 0xcf, 0x33, 0x3c, 0x4e, 0xe3, 0x57, 0x41, 0x53, 0x4a, 0xf5, 0xa6, 0x3a, 0x6a, 0x69, 0xae, 0x6c, 0x1f, 0x48, + 0xda, 0x6e, 0x93, 0xf2, 0xca, 0x97, 0x8f, 0x94, 0xd6, 0x1d, 0x09, 0xdd, 0x96, 0xb5, 0x82, 0xc1, 0x21, 0xf5, 0x67, + 0xa4, 0xfb, 0x2c, 0x16, 0x53, 0xd6, 0xca, 0x5d, 0x20, 0x0b, 0xa2, 0x11, 0xbe, 0x96, 0xf4, 0x2e, 0x2d, 0x4f, 0x29, + 0x65, 0x7c, 0x8e, 0x5a, 0x26, 0x68, 0x3d, 0x99, 0x5e, 0xde, 0x7d, 0xf8, 0x9b, 0xd1, 0x2f, 0x25, 0x8d, 0xd4, 0xcd, + 0x7f, 0xdb, 0xee, 0xe0, 0x3e, 0x48, 0xa2, 0xab, 0x20, 0x4e, 0x49, 0xe5, 0x9d, 0x62, 0x94, 0xa7, 0x33, 0xcd, 0x64, + 0xfa, 0x55, 0xce, 0x12, 0xfa, 0xed, 0x1f, 0xb9, 0x14, 0xbb, 0x8f, 0xa6, 0x97, 0x6a, 0x35, 0x5a, 0x0b, 0x69, 0x55, + 0x7f, 0x68, 0xf6, 0xd4, 0xfa, 0x74, 0xad, 0x7a, 0x06, 0xd0, 0x43, 0x80, 0x41, 0xe8, 0xd9, 0x46, 0x2e, 0xa0, 0x6a, + 0x42, 0x89, 0x91, 0x3f, 0x56, 0x0d, 0x64, 0xf9, 0xbb, 0x20, 0xb9, 0xa3, 0x82, 0x75, 0xf0, 0xfd, 0xb0, 0xf1, 0x20, + 0x4a, 0xa4, 0x2e, 0x9f, 0xc4, 0xc3, 0x61, 0xc2, 0x3a, 0x4a, 0x5d, 0x5b, 0xad, 0x47, 0x98, 0x7e, 0x65, 0x2e, 0x59, + 0x7d, 0x55, 0x0c, 0xe2, 0x69, 0x3a, 0x45, 0xa7, 0x60, 0x3e, 0xe0, 0x4b, 0x5e, 0x57, 0x92, 0x53, 0xe6, 0x25, 0x35, + 0x2b, 0xe2, 0xd1, 0xf7, 0x3a, 0x2e, 0x0f, 0xc1, 0x76, 0xa1, 0x05, 0x6f, 0x76, 0x78, 0x36, 0x0d, 0x1a, 0xbb, 0x75, + 0x44, 0xb0, 0x4a, 0xa3, 0xe0, 0xad, 0x40, 0xcb, 0x43, 0x65, 0x25, 0x04, 0xb4, 0xe5, 0xb7, 0x64, 0x19, 0x0d, 0x80, + 0x2f, 0x12, 0xd5, 0x45, 0x65, 0x1d, 0x99, 0x7f, 0x9b, 0xdd, 0xf2, 0xd9, 0xea, 0xdd, 0xf2, 0x99, 0xda, 0x2d, 0x37, + 0x73, 0xec, 0xbd, 0x51, 0x0b, 0xff, 0xeb, 0x54, 0x08, 0xc1, 0xaa, 0x00, 0x39, 0x2c, 0x34, 0xd3, 0x1a, 0x6d, 0xf8, + 0x87, 0x86, 0xc6, 0x18, 0x74, 0x13, 0xf3, 0xc9, 0xbc, 0xa6, 0x85, 0x85, 0xf8, 0xd7, 0xac, 0x55, 0xb5, 0x1e, 0x60, + 0x1d, 0xf6, 0x7a, 0xb8, 0x5c, 0xd7, 0xbe, 0x79, 0xd3, 0x82, 0xbc, 0xe2, 0x4e, 0xa0, 0x84, 0x31, 0x78, 0x0e, 0xd1, + 0xe9, 0x29, 0x94, 0x8e, 0xb2, 0xc1, 0xac, 0xf8, 0x5b, 0x09, 0xbf, 0x24, 0xe2, 0x8d, 0x5b, 0x7a, 0x61, 0x1c, 0xd5, + 0x55, 0xe4, 0xf2, 0xa9, 0x11, 0xe6, 0x7a, 0x9d, 0x82, 0x02, 0x18, 0x93, 0x39, 0x6d, 0xff, 0xc1, 0x8a, 0x4d, 0xf0, + 0xef, 0xb2, 0x36, 0x2b, 0x91, 0xf9, 0xbd, 0xc4, 0xb8, 0x91, 0x08, 0xbf, 0x8a, 0x06, 0xe6, 0x1a, 0x36, 0x9f, 0xac, + 0x06, 0xf7, 0x48, 0xcd, 0xd4, 0x57, 0x4a, 0x41, 0xea, 0x1d, 0x30, 0x4a, 0xa3, 0x59, 0xc2, 0x6f, 0x1e, 0x75, 0x1d, + 0x67, 0x2c, 0x8d, 0x7a, 0x83, 0x40, 0xaf, 0xda, 0xde, 0x51, 0x4a, 0xdf, 0xfb, 0xec, 0x01, 0xfe, 0x27, 0xd2, 0x05, + 0xae, 0x2a, 0x53, 0x5d, 0xb8, 0xaa, 0x68, 0xaa, 0x4f, 0x6a, 0xb6, 0xb8, 0xd0, 0xe0, 0x64, 0x8e, 0xdf, 0xb5, 0x35, + 0x1a, 0x95, 0x77, 0x6a, 0x2e, 0x8d, 0xac, 0x5f, 0xd5, 0xfa, 0xd7, 0x0d, 0x7e, 0xc7, 0xb6, 0x03, 0x61, 0xb8, 0xd6, + 0xdb, 0xca, 0xdf, 0x61, 0x5a, 0x6a, 0xac, 0x28, 0x4e, 0xed, 0x27, 0xe1, 0x95, 0xf6, 0x50, 0xc4, 0xb9, 0x12, 0x3a, + 0x29, 0x13, 0xe1, 0xa4, 0xfc, 0x85, 0x87, 0xf7, 0xf1, 0x85, 0x84, 0xd6, 0xe5, 0x24, 0x49, 0xc1, 0x48, 0x1a, 0x73, + 0x3e, 0x0d, 0x76, 0x76, 0x2e, 0x2e, 0x2e, 0xfc, 0x8b, 0x5d, 0x3f, 0xcb, 0xcf, 0x76, 0xda, 0xcd, 0x66, 0x13, 0xdf, + 0x23, 0x67, 0x5b, 0xe7, 0x31, 0xbb, 0x78, 0x0a, 0x76, 0xb0, 0xfd, 0xd8, 0x7a, 0x62, 0x3d, 0xde, 0xb5, 0x1e, 0x3e, + 0xb2, 0x2d, 0x12, 0xe7, 0x50, 0xb2, 0x6b, 0x5b, 0x42, 0x9c, 0x87, 0x36, 0x14, 0x77, 0xf7, 0xce, 0x94, 0x45, 0x86, + 0xf7, 0x74, 0x84, 0xbd, 0x03, 0xce, 0x41, 0xf6, 0x89, 0xd5, 0x37, 0xae, 0x28, 0x6b, 0x48, 0xa5, 0xa0, 0x1e, 0x71, + 0xf7, 0x0e, 0xa2, 0x69, 0x40, 0x4c, 0x61, 0x16, 0x62, 0x0c, 0x46, 0x94, 0xd2, 0x14, 0x68, 0x65, 0x9e, 0xc2, 0x37, + 0x4c, 0xec, 0xb4, 0xe0, 0xfb, 0x9b, 0xf6, 0x63, 0xd0, 0x58, 0xe7, 0x8d, 0x07, 0x83, 0x66, 0xa3, 0x65, 0xb5, 0x1a, + 0x6d, 0xff, 0xb1, 0xd5, 0x16, 0xff, 0x82, 0xc4, 0xdb, 0xb5, 0x5a, 0xf0, 0x6d, 0xd7, 0x82, 0xe7, 0xf3, 0x07, 0xe2, + 0x00, 0x3a, 0xb2, 0x77, 0xba, 0x7b, 0xf8, 0xb3, 0x6a, 0x80, 0xd4, 0x67, 0xb6, 0xf8, 0x21, 0x48, 0xfb, 0x9e, 0x59, + 0xda, 0x7a, 0xb2, 0xb2, 0xb8, 0xfd, 0x78, 0x65, 0xf1, 0xee, 0xa3, 0x95, 0xc5, 0x0f, 0x1e, 0xd6, 0x8b, 0x77, 0xce, + 0x44, 0x95, 0xde, 0xe5, 0xa1, 0x3d, 0x89, 0x60, 0xd9, 0x2f, 0x9d, 0x16, 0xc0, 0xd9, 0xb4, 0x1a, 0xf8, 0xf1, 0xb8, + 0xed, 0xea, 0x5e, 0xa7, 0xd8, 0x4b, 0x63, 0xf9, 0xf8, 0x09, 0x60, 0xf9, 0xb2, 0xfd, 0x68, 0x80, 0xed, 0x08, 0x51, + 0xf8, 0x3b, 0xdf, 0x7d, 0x32, 0x00, 0xf9, 0x6e, 0xe1, 0x1f, 0xfc, 0x37, 0x7e, 0xd8, 0x1e, 0x88, 0x87, 0x26, 0xd6, + 0x7f, 0xd3, 0x7a, 0x5c, 0x40, 0x53, 0xfc, 0xef, 0x17, 0x6d, 0x10, 0xa3, 0x39, 0x6e, 0x8e, 0xfb, 0x00, 0x68, 0xf4, + 0x64, 0xdc, 0xf6, 0x3f, 0x3b, 0x7f, 0xec, 0x3f, 0x19, 0xb7, 0x1e, 0x7f, 0x23, 0x9e, 0x12, 0xa0, 0xe0, 0x67, 0xf8, + 0xf7, 0xcd, 0x6e, 0x13, 0xbc, 0x4b, 0xff, 0xc9, 0xf9, 0xae, 0xbf, 0x9b, 0x34, 0x1e, 0xf9, 0x4f, 0xf0, 0xaf, 0x1a, + 0x6e, 0x9c, 0x4d, 0x98, 0x6d, 0xe1, 0x7a, 0x2f, 0x78, 0x5b, 0xe6, 0x1c, 0xed, 0x07, 0xd6, 0xc3, 0x07, 0x2f, 0x9f, + 0xc0, 0x1a, 0x8d, 0x5b, 0x6d, 0xf8, 0x77, 0xdd, 0xd7, 0x6f, 0x90, 0xf0, 0x72, 0xe0, 0x88, 0x61, 0x86, 0xbd, 0x22, + 0x1c, 0xbd, 0xd3, 0xf0, 0xbe, 0x07, 0x0e, 0xd4, 0x6a, 0xef, 0x9a, 0xb1, 0xdb, 0x23, 0xa8, 0xec, 0x6e, 0xee, 0x35, + 0x63, 0x7f, 0xac, 0x7b, 0xcd, 0xd9, 0x42, 0x04, 0xf5, 0x92, 0x2f, 0x79, 0xd1, 0x8b, 0xae, 0xd7, 0x07, 0xee, 0x1c, + 0xfd, 0x85, 0xf7, 0xf1, 0x36, 0x09, 0xb4, 0x8e, 0x99, 0x19, 0x6c, 0xc8, 0x70, 0x23, 0xe3, 0x8f, 0x2b, 0xd2, 0xdd, + 0x9f, 0x75, 0x04, 0xc9, 0x6f, 0x27, 0xc8, 0x37, 0x77, 0xa3, 0x47, 0xfe, 0x07, 0xd3, 0xa3, 0x30, 0xe9, 0x51, 0x0b, + 0xe7, 0x92, 0x3b, 0x4b, 0xee, 0xe8, 0x01, 0x3d, 0x3b, 0x98, 0x84, 0xbd, 0x6d, 0xef, 0x30, 0x2c, 0x2a, 0x6c, 0x71, + 0x88, 0xf0, 0xf4, 0xd7, 0xc4, 0x9f, 0xc5, 0x8d, 0x8b, 0xd0, 0x96, 0xbe, 0xff, 0x14, 0xdf, 0xdb, 0xad, 0x1e, 0xce, + 0xc5, 0xad, 0xbe, 0x90, 0xae, 0xe4, 0x3e, 0xd4, 0x71, 0x03, 0xbc, 0x04, 0x13, 0xce, 0x33, 0x1e, 0xe1, 0x0f, 0xc3, + 0x01, 0xb9, 0xe9, 0x27, 0xe4, 0x62, 0x9e, 0x30, 0x3c, 0x24, 0x1f, 0x88, 0x77, 0x28, 0xc3, 0x57, 0x79, 0xdd, 0x16, + 0x6f, 0x71, 0x7c, 0x8d, 0x37, 0x50, 0x54, 0x60, 0x7a, 0x82, 0x2e, 0xf5, 0x1b, 0x36, 0x8c, 0x23, 0xc7, 0x76, 0xa6, + 0xb0, 0x91, 0x61, 0x96, 0x46, 0xed, 0xfa, 0x07, 0xdd, 0xfc, 0x70, 0x6d, 0xf5, 0xeb, 0x64, 0x39, 0xbe, 0xed, 0x31, + 0x3c, 0x92, 0x41, 0x2d, 0x5b, 0x9a, 0xf9, 0x30, 0xbe, 0x2a, 0xc9, 0x51, 0xa2, 0x57, 0xa6, 0x81, 0x2d, 0x6c, 0x83, + 0x96, 0xdf, 0x06, 0x5f, 0x81, 0x8a, 0xf1, 0xed, 0x79, 0xdf, 0x39, 0x8d, 0x5d, 0xb0, 0x5d, 0x8c, 0x6e, 0x7a, 0xa0, + 0xbe, 0xfe, 0xb1, 0x2b, 0xfd, 0x83, 0x8c, 0xf5, 0x3b, 0x33, 0xb6, 0xe0, 0x88, 0x7b, 0x02, 0x77, 0x5b, 0xbc, 0xa5, + 0x84, 0xa8, 0x47, 0x77, 0x46, 0xa1, 0xcc, 0x31, 0x7f, 0x98, 0x4f, 0xbc, 0x9d, 0x4f, 0xfc, 0x06, 0x67, 0x59, 0x35, + 0xe1, 0xee, 0x9c, 0x02, 0xef, 0x98, 0x64, 0x8c, 0x57, 0x75, 0x31, 0x0e, 0x1b, 0x1a, 0x34, 0xc5, 0x67, 0xb7, 0x46, + 0x64, 0xee, 0x69, 0x80, 0x88, 0xc0, 0xa1, 0xfc, 0xac, 0x8a, 0xd5, 0x17, 0x19, 0x5d, 0x01, 0xb7, 0x1d, 0x7f, 0xf9, + 0x88, 0x3e, 0x96, 0x62, 0x37, 0xe2, 0xec, 0x60, 0xa1, 0xb4, 0x1a, 0xaa, 0x8a, 0xd1, 0x14, 0x4f, 0xaf, 0x0e, 0xe5, + 0x6b, 0x3f, 0x6c, 0x0c, 0x81, 0x52, 0xe8, 0xbb, 0x7a, 0xe5, 0xe0, 0x36, 0xa8, 0x46, 0xfa, 0x21, 0x60, 0xca, 0x60, + 0x42, 0xed, 0x87, 0xb7, 0x6e, 0x2c, 0xe9, 0xf3, 0x84, 0xb6, 0xd0, 0x7d, 0x43, 0x76, 0x1e, 0x0f, 0xa4, 0x0a, 0xf3, + 0x2c, 0x79, 0x5b, 0xb0, 0x41, 0x4b, 0x13, 0xb6, 0x3c, 0xe1, 0xf5, 0xc3, 0x03, 0xea, 0xe3, 0x30, 0xcd, 0xec, 0xee, + 0xfd, 0xce, 0x3a, 0xe2, 0xe3, 0xaf, 0x12, 0x1f, 0x81, 0x97, 0xf9, 0xb7, 0xe1, 0x7d, 0xfc, 0x5d, 0xe2, 0xfb, 0x7d, + 0xdb, 0xf5, 0x49, 0x01, 0xdc, 0xaf, 0x7e, 0x9c, 0x18, 0xa5, 0xdf, 0x36, 0xe8, 0x6a, 0xef, 0xae, 0x4a, 0x5b, 0x2a, + 0xe8, 0xf6, 0xc3, 0x4a, 0x41, 0xc3, 0x77, 0x43, 0x22, 0x83, 0xb2, 0x68, 0xfb, 0x0f, 0x0d, 0xb1, 0x7f, 0xde, 0xc0, + 0xcf, 0x9a, 0xe0, 0x7f, 0x00, 0x0d, 0x94, 0xe4, 0x7f, 0x0d, 0xcd, 0x77, 0x85, 0x92, 0x81, 0x7e, 0xdf, 0x93, 0x58, + 0x96, 0x22, 0xb9, 0xb6, 0x0d, 0x56, 0x9c, 0xc6, 0x88, 0x6c, 0x2c, 0xdb, 0x73, 0xf4, 0x2f, 0x1e, 0xc9, 0x5d, 0x29, + 0xe3, 0x40, 0xcf, 0xa1, 0xaf, 0xa3, 0xdf, 0xe4, 0xbf, 0xaa, 0xce, 0xab, 0x49, 0x89, 0x15, 0x53, 0xe0, 0xbe, 0x5e, + 0x38, 0xf1, 0xe9, 0x88, 0x2b, 0x0c, 0xfa, 0x55, 0x40, 0xeb, 0x19, 0x5a, 0xde, 0x75, 0x70, 0x0d, 0x11, 0xc1, 0xe8, + 0x6d, 0xc3, 0x34, 0xc9, 0xab, 0x61, 0xb9, 0x38, 0x3f, 0xa6, 0x83, 0xe5, 0x99, 0x71, 0xa7, 0x50, 0x46, 0xef, 0x30, + 0x59, 0x74, 0x18, 0xe7, 0xf4, 0x62, 0x04, 0x05, 0x7a, 0x2d, 0x02, 0x58, 0x51, 0x89, 0xa4, 0x04, 0x2b, 0x7a, 0x36, + 0x16, 0xd9, 0x81, 0x4d, 0xe1, 0x23, 0xdb, 0x7c, 0xdd, 0xbe, 0x79, 0x73, 0x9d, 0x38, 0x99, 0x12, 0xbb, 0x71, 0xaf, + 0x22, 0x7d, 0x6c, 0x90, 0xb6, 0x6b, 0x77, 0x09, 0xd9, 0x60, 0x88, 0x6b, 0xf5, 0xfb, 0x72, 0xa6, 0x00, 0xb2, 0x4d, + 0x42, 0xeb, 0x71, 0x89, 0x84, 0xae, 0xa4, 0xd3, 0x29, 0x8b, 0xb8, 0x1f, 0xa5, 0x22, 0x0b, 0xc1, 0x10, 0x53, 0x5e, + 0x8b, 0xed, 0xba, 0x25, 0xc8, 0x46, 0x23, 0x6f, 0x42, 0xee, 0x6e, 0x28, 0x54, 0x17, 0x3d, 0x18, 0xaf, 0xe5, 0xb3, + 0x8e, 0xdb, 0xdd, 0x77, 0x87, 0xfb, 0x96, 0xd8, 0x94, 0x7b, 0x3b, 0xf0, 0xb8, 0x47, 0xfe, 0xb8, 0x48, 0xde, 0x0f, + 0x45, 0xf2, 0xbe, 0x25, 0x6f, 0x71, 0x50, 0x86, 0xe3, 0x8e, 0x40, 0xdb, 0xb6, 0x58, 0x3a, 0x10, 0x81, 0xc4, 0x09, + 0xf8, 0x2c, 0x31, 0xbe, 0xa2, 0x71, 0x07, 0xbb, 0x36, 0x70, 0xc1, 0x80, 0x9b, 0x45, 0xd4, 0x51, 0xd9, 0x35, 0x3c, + 0x55, 0x61, 0x47, 0xb0, 0x46, 0x98, 0xca, 0x40, 0x94, 0x43, 0xe9, 0xe4, 0xc5, 0xe5, 0xd6, 0xc5, 0xec, 0x74, 0x02, + 0x72, 0x52, 0xe5, 0x10, 0x7e, 0x94, 0x1d, 0xf6, 0x68, 0xaa, 0xee, 0x49, 0x29, 0xe3, 0xa2, 0xea, 0xf5, 0xf9, 0x0b, + 0x3f, 0x35, 0x2c, 0xb0, 0x97, 0x7a, 0x01, 0xb3, 0xf0, 0xc7, 0xbb, 0x5d, 0x1d, 0x89, 0x34, 0xeb, 0x4a, 0x40, 0x7d, + 0xb7, 0x7b, 0x12, 0x4c, 0xe5, 0x78, 0xaf, 0xb3, 0xa5, 0x9f, 0x2d, 0xd6, 0x72, 0xb2, 0x47, 0xd9, 0xa9, 0xe2, 0x6a, + 0x93, 0x04, 0x18, 0x56, 0x10, 0x60, 0x92, 0x26, 0x80, 0x45, 0xe7, 0xaa, 0xf6, 0xc3, 0xa6, 0x4a, 0x78, 0x85, 0x32, + 0xdc, 0x90, 0xa2, 0x8b, 0x31, 0x49, 0x2d, 0x98, 0x3b, 0x6e, 0x75, 0xf7, 0x22, 0x69, 0x5c, 0xa2, 0xf0, 0x28, 0x40, + 0x7a, 0x40, 0x67, 0xb4, 0xe0, 0xfc, 0x38, 0xdb, 0xb9, 0x60, 0xa7, 0x8d, 0x68, 0x1a, 0x57, 0x91, 0x53, 0x34, 0x35, + 0xf4, 0x94, 0x59, 0x35, 0x13, 0x7e, 0x8d, 0x16, 0x90, 0x24, 0xc1, 0x5d, 0xca, 0xb0, 0x2c, 0x59, 0xe8, 0xc0, 0x42, + 0x40, 0x61, 0x92, 0xeb, 0x2a, 0x7c, 0x2b, 0x35, 0x6e, 0x69, 0x77, 0xff, 0xfa, 0x8f, 0xff, 0x5b, 0x46, 0x64, 0x81, + 0x2a, 0x2d, 0x35, 0xd6, 0x02, 0xa1, 0xcb, 0x3d, 0xba, 0xb5, 0xa2, 0x8f, 0x10, 0xd9, 0x25, 0xb8, 0xf6, 0xf1, 0xb0, + 0x31, 0x8e, 0x92, 0x11, 0x00, 0xb6, 0x96, 0x40, 0x66, 0x52, 0xb8, 0x84, 0xba, 0x5e, 0x84, 0x2c, 0xf8, 0x9b, 0xd2, + 0x9b, 0x55, 0x96, 0x2c, 0xed, 0x56, 0x33, 0xd9, 0xb9, 0xda, 0x50, 0xb5, 0x84, 0x67, 0xf5, 0xdb, 0x7d, 0x4a, 0xa8, + 0xd5, 0xf2, 0x9c, 0xa1, 0xa5, 0x3e, 0x02, 0xf9, 0xd7, 0x7f, 0xfa, 0xbb, 0xff, 0xa1, 0x1e, 0xf1, 0x64, 0xe3, 0xaf, + 0xff, 0xf0, 0x9f, 0x31, 0x1b, 0xd3, 0xd2, 0xa7, 0x1f, 0x24, 0x27, 0xac, 0xea, 0xe8, 0x43, 0x08, 0x0c, 0x0b, 0x53, + 0x9d, 0x26, 0x20, 0x06, 0xe3, 0x41, 0x3d, 0xf3, 0xf9, 0x80, 0x26, 0xa4, 0xcd, 0x26, 0xa1, 0xa3, 0x4d, 0x5b, 0x56, + 0x3c, 0x52, 0x23, 0x39, 0xf1, 0x22, 0x54, 0x22, 0xbd, 0xef, 0x74, 0xfb, 0xc3, 0xd7, 0xab, 0x31, 0x57, 0xf1, 0x3e, + 0x2c, 0x29, 0xab, 0x72, 0x0b, 0x03, 0xf1, 0x73, 0x7c, 0x0c, 0xda, 0x46, 0x31, 0x2d, 0x5e, 0xad, 0x4f, 0xe7, 0xa7, + 0x19, 0xc0, 0x3f, 0x42, 0x8a, 0x8b, 0xa8, 0x22, 0x9d, 0x79, 0x36, 0xd0, 0xe6, 0x4b, 0xae, 0x4a, 0x1a, 0x45, 0x38, + 0x8a, 0x0f, 0x9e, 0xfc, 0x4d, 0xf9, 0xe7, 0x09, 0x5a, 0x56, 0x96, 0x33, 0x89, 0x2e, 0xa5, 0xfb, 0xf8, 0xa8, 0xd9, + 0x9c, 0x5e, 0xba, 0xf3, 0x6a, 0x06, 0x6f, 0xdd, 0x64, 0x14, 0x89, 0x34, 0x07, 0xa4, 0xc3, 0x52, 0x1d, 0xf4, 0x04, + 0x8f, 0xa9, 0x89, 0x31, 0xb2, 0xb2, 0xfc, 0xd3, 0x9c, 0xe2, 0x6e, 0xf1, 0x2f, 0x78, 0xa8, 0x29, 0x43, 0x94, 0x50, + 0x62, 0x60, 0x31, 0x37, 0x7a, 0xb5, 0x45, 0xaf, 0x71, 0x6b, 0xf9, 0xea, 0x83, 0x79, 0x28, 0x6b, 0x1e, 0xa7, 0x3e, + 0xc0, 0x03, 0xd2, 0x71, 0xcb, 0x1b, 0xb7, 0xe7, 0x7a, 0x78, 0xce, 0xb3, 0x89, 0x79, 0x0a, 0xcb, 0x22, 0x36, 0x60, + 0x23, 0x15, 0xda, 0x95, 0xf5, 0xe2, 0x84, 0xb5, 0x1c, 0xef, 0xae, 0x98, 0x4b, 0x82, 0x44, 0xa7, 0xaf, 0x00, 0xcf, + 0x3d, 0xdc, 0x80, 0x40, 0xff, 0x2c, 0xe2, 0x01, 0xf1, 0x6b, 0xc7, 0x3c, 0xcb, 0x8d, 0x50, 0xca, 0x64, 0x73, 0x03, + 0x9e, 0x8e, 0x68, 0x8a, 0x41, 0xd6, 0xfa, 0xd5, 0x93, 0xd2, 0xa7, 0xee, 0xe6, 0x50, 0x22, 0x46, 0xf3, 0x8d, 0x3c, + 0x22, 0x7d, 0x5a, 0x0b, 0x6e, 0x48, 0x15, 0xd3, 0x76, 0xbd, 0x95, 0xf5, 0x42, 0x53, 0x8b, 0xda, 0x6f, 0xb8, 0x63, + 0x13, 0x98, 0xf6, 0x62, 0x2b, 0x2a, 0xc4, 0x56, 0x4f, 0xc3, 0x6f, 0xb4, 0xeb, 0x13, 0x4d, 0xa7, 0xd4, 0xd0, 0x05, + 0x26, 0x26, 0x83, 0x15, 0x65, 0x07, 0x1d, 0xff, 0x8b, 0xd3, 0x76, 0xd9, 0x46, 0x6e, 0x04, 0xf1, 0x4d, 0x9e, 0xc3, + 0xe3, 0xaf, 0xae, 0x74, 0xff, 0x1f, 0x1c, 0x1d, 0xa5, 0x5f, 0x1b, 0x82, 0x00, 0x00}; } // namespace web_server } // namespace esphome From 98277f6cebfd03c5cc00517727fd1839f1338162 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 4 Jul 2023 14:03:58 +1200 Subject: [PATCH 0017/2101] Bump version to 2023.6.4 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 0d5b211c18..d8eda3fd63 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2023.6.3" +__version__ = "2023.6.4" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 62aee36f82bf0b88c61dbed0ebb067abfd0c3798 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 9 Jul 2023 11:08:46 -1000 Subject: [PATCH 0018/2101] Fix bulk and single Bluetooth parser coexistence (#5073) --- .../bluetooth_proxy/bluetooth_connection.cpp | 4 ++ .../bluetooth_proxy/bluetooth_connection.h | 1 + .../bluetooth_proxy/bluetooth_proxy.cpp | 8 ++++ .../bluetooth_proxy/bluetooth_proxy.h | 1 + .../esp32_ble_tracker/esp32_ble_tracker.cpp | 42 +++++++++++++++---- .../esp32_ble_tracker/esp32_ble_tracker.h | 17 +++++--- 6 files changed, 60 insertions(+), 13 deletions(-) diff --git a/esphome/components/bluetooth_proxy/bluetooth_connection.cpp b/esphome/components/bluetooth_proxy/bluetooth_connection.cpp index 26304325c1..97a25262cb 100644 --- a/esphome/components/bluetooth_proxy/bluetooth_connection.cpp +++ b/esphome/components/bluetooth_proxy/bluetooth_connection.cpp @@ -275,6 +275,10 @@ esp_err_t BluetoothConnection::notify_characteristic(uint16_t handle, bool enabl return ESP_OK; } +esp32_ble_tracker::AdvertisementParserType BluetoothConnection::get_advertisement_parser_type() { + return this->proxy_->get_advertisement_parser_type(); +} + } // namespace bluetooth_proxy } // namespace esphome diff --git a/esphome/components/bluetooth_proxy/bluetooth_connection.h b/esphome/components/bluetooth_proxy/bluetooth_connection.h index 8b13f4d1c2..e6ab3cbccc 100644 --- a/esphome/components/bluetooth_proxy/bluetooth_connection.h +++ b/esphome/components/bluetooth_proxy/bluetooth_connection.h @@ -14,6 +14,7 @@ class BluetoothConnection : public esp32_ble_client::BLEClientBase { bool 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; + esp32_ble_tracker::AdvertisementParserType get_advertisement_parser_type() override; esp_err_t read_characteristic(uint16_t handle); esp_err_t write_characteristic(uint16_t handle, const std::string &data, bool response); diff --git a/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp b/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp index b633fe2430..f188439d0e 100644 --- a/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +++ b/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp @@ -198,6 +198,12 @@ void BluetoothProxy::loop() { } } +esp32_ble_tracker::AdvertisementParserType BluetoothProxy::get_advertisement_parser_type() { + if (this->raw_advertisements_) + return esp32_ble_tracker::AdvertisementParserType::RAW_ADVERTISEMENTS; + return esp32_ble_tracker::AdvertisementParserType::PARSED_ADVERTISEMENTS; +} + BluetoothConnection *BluetoothProxy::get_connection_(uint64_t address, bool reserve) { for (auto *connection : this->connections_) { if (connection->get_address() == address) @@ -435,6 +441,7 @@ void BluetoothProxy::subscribe_api_connection(api::APIConnection *api_connection } this->api_connection_ = api_connection; this->raw_advertisements_ = flags & BluetoothProxySubscriptionFlag::SUBSCRIPTION_RAW_ADVERTISEMENTS; + this->parent_->recalculate_advertisement_parser_types(); } void BluetoothProxy::unsubscribe_api_connection(api::APIConnection *api_connection) { @@ -444,6 +451,7 @@ void BluetoothProxy::unsubscribe_api_connection(api::APIConnection *api_connecti } this->api_connection_ = nullptr; this->raw_advertisements_ = false; + this->parent_->recalculate_advertisement_parser_types(); } void BluetoothProxy::send_device_connection(uint64_t address, bool connected, uint16_t mtu, esp_err_t error) { diff --git a/esphome/components/bluetooth_proxy/bluetooth_proxy.h b/esphome/components/bluetooth_proxy/bluetooth_proxy.h index 97b6396b55..35a37f934a 100644 --- a/esphome/components/bluetooth_proxy/bluetooth_proxy.h +++ b/esphome/components/bluetooth_proxy/bluetooth_proxy.h @@ -51,6 +51,7 @@ class BluetoothProxy : public esp32_ble_tracker::ESPBTDeviceListener, public Com bool parse_devices(esp_ble_gap_cb_param_t::ble_scan_result_evt_param *advertisements, size_t count) override; void dump_config() override; void loop() override; + esp32_ble_tracker::AdvertisementParserType get_advertisement_parser_type() override; void register_connection(BluetoothConnection *connection) { this->connections_.push_back(connection); diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp index 0f6c4117d2..1569ea0dd5 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp @@ -107,16 +107,16 @@ void ESP32BLETracker::loop() { ESP_LOGW(TAG, "Too many BLE events to process. Some devices may not show up."); } - bool bulk_parsed = false; - - for (auto *listener : this->listeners_) { - bulk_parsed |= listener->parse_devices(this->scan_result_buffer_, this->scan_result_index_); - } - for (auto *client : this->clients_) { - bulk_parsed |= client->parse_devices(this->scan_result_buffer_, this->scan_result_index_); + if (this->raw_advertisements_) { + for (auto *listener : this->listeners_) { + listener->parse_devices(this->scan_result_buffer_, this->scan_result_index_); + } + for (auto *client : this->clients_) { + client->parse_devices(this->scan_result_buffer_, this->scan_result_index_); + } } - if (!bulk_parsed) { + if (this->parse_advertisements_) { for (size_t i = 0; i < index; i++) { ESPBTDevice device; device.parse_scan_rst(this->scan_result_buffer_[i]); @@ -284,6 +284,32 @@ void ESP32BLETracker::end_of_scan_() { void ESP32BLETracker::register_client(ESPBTClient *client) { client->app_id = ++this->app_id_; this->clients_.push_back(client); + this->recalculate_advertisement_parser_types(); +} + +void ESP32BLETracker::register_listener(ESPBTDeviceListener *listener) { + listener->set_parent(this); + this->listeners_.push_back(listener); + this->recalculate_advertisement_parser_types(); +} + +void ESP32BLETracker::recalculate_advertisement_parser_types() { + this->raw_advertisements_ = false; + this->parse_advertisements_ = false; + for (auto *listener : this->listeners_) { + if (listener->get_advertisement_parser_type() == AdvertisementParserType::PARSED_ADVERTISEMENTS) { + this->parse_advertisements_ = true; + } else { + this->raw_advertisements_ = true; + } + } + for (auto *client : this->clients_) { + if (client->get_advertisement_parser_type() == AdvertisementParserType::PARSED_ADVERTISEMENTS) { + this->parse_advertisements_ = true; + } else { + this->raw_advertisements_ = true; + } + } } void ESP32BLETracker::gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) { diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h index 43e88fbf2b..6efdded3ff 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h @@ -27,6 +27,11 @@ using namespace esp32_ble; using adv_data_t = std::vector; +enum AdvertisementParserType { + PARSED_ADVERTISEMENTS, + RAW_ADVERTISEMENTS, +}; + struct ServiceData { ESPBTUUID uuid; adv_data_t data; @@ -116,6 +121,9 @@ class ESPBTDeviceListener { virtual bool parse_devices(esp_ble_gap_cb_param_t::ble_scan_result_evt_param *advertisements, size_t count) { return false; }; + virtual AdvertisementParserType get_advertisement_parser_type() { + return AdvertisementParserType::PARSED_ADVERTISEMENTS; + }; void set_parent(ESP32BLETracker *parent) { parent_ = parent; } protected: @@ -184,12 +192,9 @@ class ESP32BLETracker : public Component, public GAPEventHandler, public GATTcEv void loop() override; - void register_listener(ESPBTDeviceListener *listener) { - listener->set_parent(this); - this->listeners_.push_back(listener); - } - + void register_listener(ESPBTDeviceListener *listener); void register_client(ESPBTClient *client); + void recalculate_advertisement_parser_types(); void print_bt_device_info(const ESPBTDevice &device); @@ -231,6 +236,8 @@ class ESP32BLETracker : public Component, public GAPEventHandler, public GATTcEv bool scan_continuous_; bool scan_active_; bool scanner_idle_; + bool raw_advertisements_{false}; + bool parse_advertisements_{false}; SemaphoreHandle_t scan_result_lock_; SemaphoreHandle_t scan_end_lock_; size_t scan_result_index_{0}; From d7bfdd0efce65920404d2e947f1dfd2a63b00b78 Mon Sep 17 00:00:00 2001 From: "Kevin P. Fleming" Date: Sun, 9 Jul 2023 17:55:02 -0400 Subject: [PATCH 0019/2101] binary_sensor: Validate max_length for on_click/on_double_click (#5068) --- esphome/components/binary_sensor/__init__.py | 58 +++++++++++++------- 1 file changed, 38 insertions(+), 20 deletions(-) diff --git a/esphome/components/binary_sensor/__init__.py b/esphome/components/binary_sensor/__init__.py index f4a5c95b12..eaf11c056a 100644 --- a/esphome/components/binary_sensor/__init__.py +++ b/esphome/components/binary_sensor/__init__.py @@ -323,6 +323,18 @@ def validate_multi_click_timing(value): validate_device_class = cv.one_of(*DEVICE_CLASSES, lower=True, space="_") +def validate_click_timing(value): + for v in value: + min_length = v.get(CONF_MIN_LENGTH) + max_length = v.get(CONF_MAX_LENGTH) + if max_length < min_length: + raise cv.Invalid( + f"Max length ({max_length}) must be larger than min length ({min_length})." + ) + + return value + + BINARY_SENSOR_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMPONENT_SCHEMA).extend( { cv.GenerateID(): cv.declare_id(BinarySensor), @@ -342,27 +354,33 @@ BINARY_SENSOR_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMPONENT_SCHEMA).ex cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ReleaseTrigger), } ), - cv.Optional(CONF_ON_CLICK): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ClickTrigger), - cv.Optional( - CONF_MIN_LENGTH, default="50ms" - ): cv.positive_time_period_milliseconds, - cv.Optional( - CONF_MAX_LENGTH, default="350ms" - ): cv.positive_time_period_milliseconds, - } + cv.Optional(CONF_ON_CLICK): cv.All( + automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ClickTrigger), + cv.Optional( + CONF_MIN_LENGTH, default="50ms" + ): cv.positive_time_period_milliseconds, + cv.Optional( + CONF_MAX_LENGTH, default="350ms" + ): cv.positive_time_period_milliseconds, + } + ), + validate_click_timing, ), - cv.Optional(CONF_ON_DOUBLE_CLICK): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(DoubleClickTrigger), - cv.Optional( - CONF_MIN_LENGTH, default="50ms" - ): cv.positive_time_period_milliseconds, - cv.Optional( - CONF_MAX_LENGTH, default="350ms" - ): cv.positive_time_period_milliseconds, - } + cv.Optional(CONF_ON_DOUBLE_CLICK): cv.All( + automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(DoubleClickTrigger), + cv.Optional( + CONF_MIN_LENGTH, default="50ms" + ): cv.positive_time_period_milliseconds, + cv.Optional( + CONF_MAX_LENGTH, default="350ms" + ): cv.positive_time_period_milliseconds, + } + ), + validate_click_timing, ), cv.Optional(CONF_ON_MULTI_CLICK): automation.validate_automation( { From a77cf1beec9454b21568cc6ef4413ebafb04e5f9 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 10 Jul 2023 11:24:49 +1200 Subject: [PATCH 0020/2101] Bump version to 2023.6.5 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index d8eda3fd63..ea660723e4 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2023.6.4" +__version__ = "2023.6.5" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 76b438f79c6d3087d162a6eaaee29048c5105bb0 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 13 Jul 2023 09:50:48 +1200 Subject: [PATCH 0021/2101] Bump version to 2023.7.0b1 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 3442c392c7..e74f23e9b4 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2023.7.0-dev" +__version__ = "2023.7.0b1" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From d7945de0013772a9f242afb8c7d843b9521e67ea Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 13 Jul 2023 12:19:04 +1200 Subject: [PATCH 0022/2101] Dont do mqtt ip lookup if `use_address` has ip address (#5096) * Dont do mqtt ip lookup id `use_address` is in config * Fix after actually testing =) --- esphome/__main__.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/esphome/__main__.py b/esphome/__main__.py index c7c83ad83b..ecf0092b05 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -32,7 +32,7 @@ from esphome.const import ( SECRETS_FILES, ) from esphome.core import CORE, EsphomeError, coroutine -from esphome.helpers import indent +from esphome.helpers import indent, is_ip_address from esphome.util import ( run_external_command, run_external_process, @@ -308,8 +308,10 @@ def upload_program(config, args, host): password = ota_conf.get(CONF_PASSWORD, "") if ( - get_port_type(host) == "MQTT" or config[CONF_MDNS][CONF_DISABLED] - ) and CONF_MQTT in config: + not is_ip_address(CORE.address) + and (get_port_type(host) == "MQTT" or config[CONF_MDNS][CONF_DISABLED]) + and CONF_MQTT in config + ): from esphome import mqtt host = mqtt.get_esphome_device_ip( From 6bdc0c92fe2ac8b9bc4ca5ce23ee6aceac71c2a5 Mon Sep 17 00:00:00 2001 From: Pierre-Alexis Ciavaldini Date: Sun, 16 Jul 2023 21:42:01 +0200 Subject: [PATCH 0023/2101] ESP32 enable ADC2 when wifi is disabled (#4381) Co-authored-by: Keith Burzinski --- esphome/components/adc/__init__.py | 59 +++++++++++++++-- esphome/components/adc/adc_sensor.cpp | 93 ++++++++++++++++++--------- esphome/components/adc/adc_sensor.h | 20 ++++-- esphome/components/adc/sensor.py | 40 ++++++++++-- 4 files changed, 166 insertions(+), 46 deletions(-) diff --git a/esphome/components/adc/__init__.py b/esphome/components/adc/__init__.py index cceaa594ef..99dad68501 100644 --- a/esphome/components/adc/__init__.py +++ b/esphome/components/adc/__init__.py @@ -24,6 +24,7 @@ ATTENUATION_MODES = { } adc1_channel_t = cg.global_ns.enum("adc1_channel_t") +adc2_channel_t = cg.global_ns.enum("adc2_channel_t") # From https://github.com/espressif/esp-idf/blob/master/components/driver/include/driver/adc_common.h # pin to adc1 channel mapping @@ -78,6 +79,49 @@ ESP32_VARIANT_ADC1_PIN_TO_CHANNEL = { }, } +ESP32_VARIANT_ADC2_PIN_TO_CHANNEL = { + # TODO: add other variants + VARIANT_ESP32: { + 4: adc2_channel_t.ADC2_CHANNEL_0, + 0: adc2_channel_t.ADC2_CHANNEL_1, + 2: adc2_channel_t.ADC2_CHANNEL_2, + 15: adc2_channel_t.ADC2_CHANNEL_3, + 13: adc2_channel_t.ADC2_CHANNEL_4, + 12: adc2_channel_t.ADC2_CHANNEL_5, + 14: adc2_channel_t.ADC2_CHANNEL_6, + 27: adc2_channel_t.ADC2_CHANNEL_7, + 25: adc2_channel_t.ADC2_CHANNEL_8, + 26: adc2_channel_t.ADC2_CHANNEL_9, + }, + VARIANT_ESP32S2: { + 11: adc2_channel_t.ADC2_CHANNEL_0, + 12: adc2_channel_t.ADC2_CHANNEL_1, + 13: adc2_channel_t.ADC2_CHANNEL_2, + 14: adc2_channel_t.ADC2_CHANNEL_3, + 15: adc2_channel_t.ADC2_CHANNEL_4, + 16: adc2_channel_t.ADC2_CHANNEL_5, + 17: adc2_channel_t.ADC2_CHANNEL_6, + 18: adc2_channel_t.ADC2_CHANNEL_7, + 19: adc2_channel_t.ADC2_CHANNEL_8, + 20: adc2_channel_t.ADC2_CHANNEL_9, + }, + VARIANT_ESP32S3: { + 11: adc2_channel_t.ADC2_CHANNEL_0, + 12: adc2_channel_t.ADC2_CHANNEL_1, + 13: adc2_channel_t.ADC2_CHANNEL_2, + 14: adc2_channel_t.ADC2_CHANNEL_3, + 15: adc2_channel_t.ADC2_CHANNEL_4, + 16: adc2_channel_t.ADC2_CHANNEL_5, + 17: adc2_channel_t.ADC2_CHANNEL_6, + 18: adc2_channel_t.ADC2_CHANNEL_7, + 19: adc2_channel_t.ADC2_CHANNEL_8, + 20: adc2_channel_t.ADC2_CHANNEL_9, + }, + VARIANT_ESP32C3: { + 5: adc2_channel_t.ADC2_CHANNEL_0, + }, +} + def validate_adc_pin(value): if str(value).upper() == "VCC": @@ -89,11 +133,18 @@ def validate_adc_pin(value): if CORE.is_esp32: value = pins.internal_gpio_input_pin_number(value) variant = get_esp32_variant() - if variant not in ESP32_VARIANT_ADC1_PIN_TO_CHANNEL: + if ( + variant not in ESP32_VARIANT_ADC1_PIN_TO_CHANNEL + and variant not in ESP32_VARIANT_ADC2_PIN_TO_CHANNEL + ): raise cv.Invalid(f"This ESP32 variant ({variant}) is not supported") - if value not in ESP32_VARIANT_ADC1_PIN_TO_CHANNEL[variant]: + if ( + value not in ESP32_VARIANT_ADC1_PIN_TO_CHANNEL[variant] + and value not in ESP32_VARIANT_ADC2_PIN_TO_CHANNEL[variant] + ): raise cv.Invalid(f"{variant} doesn't support ADC on this pin") + return pins.internal_gpio_input_pin_schema(value) if CORE.is_esp8266: @@ -104,7 +155,7 @@ def validate_adc_pin(value): ) if value != 17: # A0 - raise cv.Invalid("ESP8266: Only pin A0 (GPIO17) supports ADC.") + raise cv.Invalid("ESP8266: Only pin A0 (GPIO17) supports ADC") return pins.gpio_pin_schema( {CONF_ANALOG: True, CONF_INPUT: True}, internal=True )(value) @@ -112,7 +163,7 @@ def validate_adc_pin(value): if CORE.is_rp2040: value = pins.internal_gpio_input_pin_number(value) if value not in (26, 27, 28, 29): - raise cv.Invalid("RP2040: Only pins 26, 27, 28 and 29 support ADC.") + raise cv.Invalid("RP2040: Only pins 26, 27, 28 and 29 support ADC") return pins.internal_gpio_input_pin_schema(value) raise NotImplementedError diff --git a/esphome/components/adc/adc_sensor.cpp b/esphome/components/adc/adc_sensor.cpp index 9bfe0f5eed..bb6a7a8c85 100644 --- a/esphome/components/adc/adc_sensor.cpp +++ b/esphome/components/adc/adc_sensor.cpp @@ -20,20 +20,20 @@ namespace adc { static const char *const TAG = "adc"; -// 13bit for S2, and 12bit for all other esp32 variants +// 13-bit for S2, 12-bit for all other ESP32 variants #ifdef USE_ESP32 static const adc_bits_width_t ADC_WIDTH_MAX_SOC_BITS = static_cast(ADC_WIDTH_MAX - 1); #ifndef SOC_ADC_RTC_MAX_BITWIDTH #if USE_ESP32_VARIANT_ESP32S2 -static const int SOC_ADC_RTC_MAX_BITWIDTH = 13; +static const int32_t SOC_ADC_RTC_MAX_BITWIDTH = 13; #else -static const int SOC_ADC_RTC_MAX_BITWIDTH = 12; +static const int32_t SOC_ADC_RTC_MAX_BITWIDTH = 12; #endif #endif -static const int ADC_MAX = (1 << SOC_ADC_RTC_MAX_BITWIDTH) - 1; // 4095 (12 bit) or 8191 (13 bit) -static const int ADC_HALF = (1 << SOC_ADC_RTC_MAX_BITWIDTH) >> 1; // 2048 (12 bit) or 4096 (13 bit) +static const int32_t ADC_MAX = (1 << SOC_ADC_RTC_MAX_BITWIDTH) - 1; // 4095 (12 bit) or 8191 (13 bit) +static const int32_t ADC_HALF = (1 << SOC_ADC_RTC_MAX_BITWIDTH) >> 1; // 2048 (12 bit) or 4096 (13 bit) #endif #ifdef USE_RP2040 @@ -47,14 +47,21 @@ extern "C" #endif #ifdef USE_ESP32 - adc1_config_width(ADC_WIDTH_MAX_SOC_BITS); - if (!autorange_) { - adc1_config_channel_atten(channel_, attenuation_); + if (channel1_ != ADC1_CHANNEL_MAX) { + adc1_config_width(ADC_WIDTH_MAX_SOC_BITS); + if (!autorange_) { + adc1_config_channel_atten(channel1_, attenuation_); + } + } else if (channel2_ != ADC2_CHANNEL_MAX) { + if (!autorange_) { + adc2_config_channel_atten(channel2_, attenuation_); + } } // load characteristics for each attenuation - for (int i = 0; i < (int) ADC_ATTEN_MAX; i++) { - auto cal_value = esp_adc_cal_characterize(ADC_UNIT_1, (adc_atten_t) i, ADC_WIDTH_MAX_SOC_BITS, + for (int32_t i = 0; i < (int32_t) ADC_ATTEN_MAX; i++) { + auto adc_unit = channel1_ != ADC1_CHANNEL_MAX ? ADC_UNIT_1 : ADC_UNIT_2; + auto cal_value = esp_adc_cal_characterize(adc_unit, (adc_atten_t) i, ADC_WIDTH_MAX_SOC_BITS, 1100, // default vref &cal_characteristics_[i]); switch (cal_value) { @@ -136,9 +143,9 @@ void ADCSensor::update() { #ifdef USE_ESP8266 float ADCSensor::sample() { #ifdef USE_ADC_SENSOR_VCC - int raw = ESP.getVcc(); // NOLINT(readability-static-accessed-through-instance) + int32_t raw = ESP.getVcc(); // NOLINT(readability-static-accessed-through-instance) #else - int raw = analogRead(this->pin_->get_pin()); // NOLINT + int32_t raw = analogRead(this->pin_->get_pin()); // NOLINT #endif if (output_raw_) { return raw; @@ -150,29 +157,53 @@ float ADCSensor::sample() { #ifdef USE_ESP32 float ADCSensor::sample() { if (!autorange_) { - int raw = adc1_get_raw(channel_); + int32_t raw = -1; + if (channel1_ != ADC1_CHANNEL_MAX) { + raw = adc1_get_raw(channel1_); + } else if (channel2_ != ADC2_CHANNEL_MAX) { + adc2_get_raw(channel2_, ADC_WIDTH_MAX_SOC_BITS, &raw); + } + if (raw == -1) { return NAN; } if (output_raw_) { return raw; } - uint32_t mv = esp_adc_cal_raw_to_voltage(raw, &cal_characteristics_[(int) attenuation_]); + uint32_t mv = esp_adc_cal_raw_to_voltage(raw, &cal_characteristics_[(int32_t) attenuation_]); return mv / 1000.0f; } - int raw11, raw6 = ADC_MAX, raw2 = ADC_MAX, raw0 = ADC_MAX; - adc1_config_channel_atten(channel_, ADC_ATTEN_DB_11); - raw11 = adc1_get_raw(channel_); - if (raw11 < ADC_MAX) { - adc1_config_channel_atten(channel_, ADC_ATTEN_DB_6); - raw6 = adc1_get_raw(channel_); - if (raw6 < ADC_MAX) { - adc1_config_channel_atten(channel_, ADC_ATTEN_DB_2_5); - raw2 = adc1_get_raw(channel_); - if (raw2 < ADC_MAX) { - adc1_config_channel_atten(channel_, ADC_ATTEN_DB_0); - raw0 = adc1_get_raw(channel_); + int32_t raw11 = ADC_MAX, raw6 = ADC_MAX, raw2 = ADC_MAX, raw0 = ADC_MAX; + + if (channel1_ != ADC1_CHANNEL_MAX) { + adc1_config_channel_atten(channel1_, ADC_ATTEN_DB_11); + raw11 = adc1_get_raw(channel1_); + if (raw11 < ADC_MAX) { + adc1_config_channel_atten(channel1_, ADC_ATTEN_DB_6); + raw6 = adc1_get_raw(channel1_); + if (raw6 < ADC_MAX) { + adc1_config_channel_atten(channel1_, ADC_ATTEN_DB_2_5); + raw2 = adc1_get_raw(channel1_); + if (raw2 < ADC_MAX) { + adc1_config_channel_atten(channel1_, ADC_ATTEN_DB_0); + raw0 = adc1_get_raw(channel1_); + } + } + } + } else if (channel2_ != ADC2_CHANNEL_MAX) { + adc2_config_channel_atten(channel2_, ADC_ATTEN_DB_11); + adc2_get_raw(channel2_, ADC_WIDTH_MAX_SOC_BITS, &raw11); + if (raw11 < ADC_MAX) { + adc2_config_channel_atten(channel2_, ADC_ATTEN_DB_6); + adc2_get_raw(channel2_, ADC_WIDTH_MAX_SOC_BITS, &raw6); + if (raw6 < ADC_MAX) { + adc2_config_channel_atten(channel2_, ADC_ATTEN_DB_2_5); + adc2_get_raw(channel2_, ADC_WIDTH_MAX_SOC_BITS, &raw2); + if (raw2 < ADC_MAX) { + adc2_config_channel_atten(channel2_, ADC_ATTEN_DB_0); + adc2_get_raw(channel2_, ADC_WIDTH_MAX_SOC_BITS, &raw0); + } } } } @@ -181,10 +212,10 @@ float ADCSensor::sample() { return NAN; } - uint32_t mv11 = esp_adc_cal_raw_to_voltage(raw11, &cal_characteristics_[(int) ADC_ATTEN_DB_11]); - uint32_t mv6 = esp_adc_cal_raw_to_voltage(raw6, &cal_characteristics_[(int) ADC_ATTEN_DB_6]); - uint32_t mv2 = esp_adc_cal_raw_to_voltage(raw2, &cal_characteristics_[(int) ADC_ATTEN_DB_2_5]); - uint32_t mv0 = esp_adc_cal_raw_to_voltage(raw0, &cal_characteristics_[(int) ADC_ATTEN_DB_0]); + uint32_t mv11 = esp_adc_cal_raw_to_voltage(raw11, &cal_characteristics_[(int32_t) ADC_ATTEN_DB_11]); + uint32_t mv6 = esp_adc_cal_raw_to_voltage(raw6, &cal_characteristics_[(int32_t) ADC_ATTEN_DB_6]); + uint32_t mv2 = esp_adc_cal_raw_to_voltage(raw2, &cal_characteristics_[(int32_t) ADC_ATTEN_DB_2_5]); + uint32_t mv0 = esp_adc_cal_raw_to_voltage(raw0, &cal_characteristics_[(int32_t) ADC_ATTEN_DB_0]); // Contribution of each value, in range 0-2048 (12 bit ADC) or 0-4096 (13 bit ADC) uint32_t c11 = std::min(raw11, ADC_HALF); @@ -212,7 +243,7 @@ float ADCSensor::sample() { adc_select_input(pin - 26); } - int raw = adc_read(); + int32_t raw = adc_read(); if (this->is_temperature_) { adc_set_temp_sensor_enabled(false); } diff --git a/esphome/components/adc/adc_sensor.h b/esphome/components/adc/adc_sensor.h index 22cddde6f8..a905177790 100644 --- a/esphome/components/adc/adc_sensor.h +++ b/esphome/components/adc/adc_sensor.h @@ -19,16 +19,23 @@ class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage #ifdef USE_ESP32 /// Set the attenuation for this pin. Only available on the ESP32. void set_attenuation(adc_atten_t attenuation) { attenuation_ = attenuation; } - void set_channel(adc1_channel_t channel) { channel_ = channel; } + void set_channel1(adc1_channel_t channel) { + channel1_ = channel; + channel2_ = ADC2_CHANNEL_MAX; + } + void set_channel2(adc2_channel_t channel) { + channel2_ = channel; + channel1_ = ADC1_CHANNEL_MAX; + } void set_autorange(bool autorange) { autorange_ = autorange; } #endif - /// Update adc values. + /// Update ADC values void update() override; - /// Setup ADc + /// Setup ADC void setup() override; void dump_config() override; - /// `HARDWARE_LATE` setup priority. + /// `HARDWARE_LATE` setup priority float get_setup_priority() const override; void set_pin(InternalGPIOPin *pin) { this->pin_ = pin; } void set_output_raw(bool output_raw) { output_raw_ = output_raw; } @@ -52,9 +59,10 @@ class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage #ifdef USE_ESP32 adc_atten_t attenuation_{ADC_ATTEN_DB_0}; - adc1_channel_t channel_{}; + adc1_channel_t channel1_{ADC1_CHANNEL_MAX}; + adc2_channel_t channel2_{ADC2_CHANNEL_MAX}; bool autorange_{false}; - esp_adc_cal_characteristics_t cal_characteristics_[(int) ADC_ATTEN_MAX] = {}; + esp_adc_cal_characteristics_t cal_characteristics_[(int32_t) ADC_ATTEN_MAX] = {}; #endif }; diff --git a/esphome/components/adc/sensor.py b/esphome/components/adc/sensor.py index 4695e96570..a0eda1d659 100644 --- a/esphome/components/adc/sensor.py +++ b/esphome/components/adc/sensor.py @@ -1,5 +1,7 @@ import esphome.codegen as cg import esphome.config_validation as cv +import esphome.final_validate as fv +from esphome.core import CORE from esphome.components import sensor, voltage_sampler from esphome.components.esp32 import get_esp32_variant from esphome.const import ( @@ -8,15 +10,15 @@ from esphome.const import ( CONF_NUMBER, CONF_PIN, CONF_RAW, + CONF_WIFI, DEVICE_CLASS_VOLTAGE, STATE_CLASS_MEASUREMENT, UNIT_VOLT, ) -from esphome.core import CORE - from . import ( ATTENUATION_MODES, ESP32_VARIANT_ADC1_PIN_TO_CHANNEL, + ESP32_VARIANT_ADC2_PIN_TO_CHANNEL, validate_adc_pin, ) @@ -25,7 +27,23 @@ AUTO_LOAD = ["voltage_sampler"] def validate_config(config): if config[CONF_RAW] and config.get(CONF_ATTENUATION, None) == "auto": - raise cv.Invalid("Automatic attenuation cannot be used when raw output is set.") + raise cv.Invalid("Automatic attenuation cannot be used when raw output is set") + + return config + + +def final_validate_config(config): + if CORE.is_esp32: + variant = get_esp32_variant() + if ( + CONF_WIFI in fv.full_config.get() + and config[CONF_PIN][CONF_NUMBER] + in ESP32_VARIANT_ADC2_PIN_TO_CHANNEL[variant] + ): + raise cv.Invalid( + f"{variant} doesn't support ADC on this pin when Wi-Fi is configured" + ) + return config @@ -55,6 +73,8 @@ CONFIG_SCHEMA = cv.All( validate_config, ) +FINAL_VALIDATE_SCHEMA = final_validate_config + async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) @@ -81,5 +101,15 @@ async def to_code(config): if CORE.is_esp32: variant = get_esp32_variant() pin_num = config[CONF_PIN][CONF_NUMBER] - chan = ESP32_VARIANT_ADC1_PIN_TO_CHANNEL[variant][pin_num] - cg.add(var.set_channel(chan)) + if ( + variant in ESP32_VARIANT_ADC1_PIN_TO_CHANNEL + and pin_num in ESP32_VARIANT_ADC1_PIN_TO_CHANNEL[variant] + ): + chan = ESP32_VARIANT_ADC1_PIN_TO_CHANNEL[variant][pin_num] + cg.add(var.set_channel1(chan)) + elif ( + variant in ESP32_VARIANT_ADC2_PIN_TO_CHANNEL + and pin_num in ESP32_VARIANT_ADC2_PIN_TO_CHANNEL[variant] + ): + chan = ESP32_VARIANT_ADC2_PIN_TO_CHANNEL[variant][pin_num] + cg.add(var.set_channel2(chan)) From 74e062fdb30bacd6cfc872d0a2ef0fc277e80e79 Mon Sep 17 00:00:00 2001 From: Ilia Sotnikov Date: Sun, 16 Jul 2023 23:28:31 +0300 Subject: [PATCH 0024/2101] [Sprinkler] Resume fixes (#5100) --- esphome/components/sprinkler/sprinkler.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/esphome/components/sprinkler/sprinkler.cpp b/esphome/components/sprinkler/sprinkler.cpp index 095884997c..8afafcb5ce 100644 --- a/esphome/components/sprinkler/sprinkler.cpp +++ b/esphome/components/sprinkler/sprinkler.cpp @@ -954,10 +954,18 @@ void Sprinkler::pause() { } void Sprinkler::resume() { + if (this->standby()) { + ESP_LOGD(TAG, "resume called but standby is enabled; no action taken"); + return; + } + if (this->paused_valve_.has_value() && (this->resume_duration_.has_value())) { - ESP_LOGD(TAG, "Resuming valve %u with %u seconds remaining", this->paused_valve_.value_or(0), - this->resume_duration_.value_or(0)); - this->fsm_request_(this->paused_valve_.value(), this->resume_duration_.value()); + // Resume only if valve has not been completed yet + if (!this->valve_cycle_complete_(this->paused_valve_.value())) { + ESP_LOGD(TAG, "Resuming valve %u with %u seconds remaining", this->paused_valve_.value_or(0), + this->resume_duration_.value_or(0)); + this->fsm_request_(this->paused_valve_.value(), this->resume_duration_.value()); + } this->reset_resume(); } else { ESP_LOGD(TAG, "No valve to resume!"); From d57a5d1793a84a9351c0003668da5d0fb0e12060 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 17 Jul 2023 09:11:43 +1200 Subject: [PATCH 0025/2101] Remove template switch restore_state (#5106) --- esphome/components/template/switch/__init__.py | 5 +++-- esphome/components/template/switch/template_switch.cpp | 5 ----- esphome/components/template/switch/template_switch.h | 2 -- tests/test1.yaml | 2 -- 4 files changed, 3 insertions(+), 11 deletions(-) diff --git a/esphome/components/template/switch/__init__.py b/esphome/components/template/switch/__init__.py index e002c4e3d8..a221cbaa60 100644 --- a/esphome/components/template/switch/__init__.py +++ b/esphome/components/template/switch/__init__.py @@ -43,7 +43,9 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_TURN_ON_ACTION): automation.validate_automation( single=True ), - cv.Optional(CONF_RESTORE_STATE, default=False): cv.boolean, + cv.Optional(CONF_RESTORE_STATE): cv.invalid( + "The restore_state option has been removed in 2023.7.0. Use the restore_mode option instead" + ), } ) .extend(cv.COMPONENT_SCHEMA), @@ -70,7 +72,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_state(config[CONF_RESTORE_STATE])) @automation.register_action( diff --git a/esphome/components/template/switch/template_switch.cpp b/esphome/components/template/switch/template_switch.cpp index 5db346b99f..b2a221669e 100644 --- a/esphome/components/template/switch/template_switch.cpp +++ b/esphome/components/template/switch/template_switch.cpp @@ -40,9 +40,6 @@ float TemplateSwitch::get_setup_priority() const { return setup_priority::HARDWA Trigger<> *TemplateSwitch::get_turn_on_trigger() const { return this->turn_on_trigger_; } Trigger<> *TemplateSwitch::get_turn_off_trigger() const { return this->turn_off_trigger_; } void TemplateSwitch::setup() { - if (!this->restore_state_) - return; - optional initial_state = this->get_initial_state_with_restore_mode(); if (initial_state.has_value()) { @@ -57,10 +54,8 @@ void TemplateSwitch::setup() { } void TemplateSwitch::dump_config() { LOG_SWITCH("", "Template Switch", this); - ESP_LOGCONFIG(TAG, " Restore State: %s", YESNO(this->restore_state_)); ESP_LOGCONFIG(TAG, " Optimistic: %s", YESNO(this->optimistic_)); } -void TemplateSwitch::set_restore_state(bool restore_state) { this->restore_state_ = restore_state; } void TemplateSwitch::set_assumed_state(bool assumed_state) { this->assumed_state_ = assumed_state; } } // namespace template_ diff --git a/esphome/components/template/switch/template_switch.h b/esphome/components/template/switch/template_switch.h index ef9b567451..bfe9ac25d6 100644 --- a/esphome/components/template/switch/template_switch.h +++ b/esphome/components/template/switch/template_switch.h @@ -15,7 +15,6 @@ class TemplateSwitch : public switch_::Switch, public Component { void dump_config() override; void set_state_lambda(std::function()> &&f); - void set_restore_state(bool restore_state); Trigger<> *get_turn_on_trigger() const; Trigger<> *get_turn_off_trigger() const; void set_optimistic(bool optimistic); @@ -35,7 +34,6 @@ class TemplateSwitch : public switch_::Switch, public Component { Trigger<> *turn_on_trigger_; Trigger<> *turn_off_trigger_; Trigger<> *prev_trigger_{nullptr}; - bool restore_state_{false}; }; } // namespace template_ diff --git a/tests/test1.yaml b/tests/test1.yaml index d0c9801933..bf099e2844 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -2475,7 +2475,6 @@ switch: level: !lambda "return 0.5;" turn_off_action: - switch.turn_on: living_room_lights_off - restore_state: false on_turn_on: - switch.template.publish: id: livingroom_lights @@ -2511,7 +2510,6 @@ switch: } optimistic: true assumed_state: false - restore_state: true on_turn_off: - switch.template.publish: id: my_switch From c4b906574972b279c0f11023d648dead71306a0a Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Mon, 17 Jul 2023 07:17:31 +1000 Subject: [PATCH 0026/2101] Add timeout filter (#5104) --- esphome/components/sensor/__init__.py | 10 ++++++++++ esphome/components/sensor/filter.cpp | 11 +++++++++++ esphome/components/sensor/filter.h | 12 ++++++++++++ tests/test3.1.yaml | 1 + 4 files changed, 34 insertions(+) diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index 06b96171a7..caaffd9701 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -217,6 +217,7 @@ OffsetFilter = sensor_ns.class_("OffsetFilter", Filter) MultiplyFilter = sensor_ns.class_("MultiplyFilter", Filter) FilterOutValueFilter = sensor_ns.class_("FilterOutValueFilter", Filter) ThrottleFilter = sensor_ns.class_("ThrottleFilter", Filter) +TimeoutFilter = sensor_ns.class_("TimeoutFilter", Filter, cg.Component) DebounceFilter = sensor_ns.class_("DebounceFilter", Filter, cg.Component) HeartbeatFilter = sensor_ns.class_("HeartbeatFilter", Filter, cg.Component) DeltaFilter = sensor_ns.class_("DeltaFilter", Filter) @@ -536,6 +537,15 @@ async def heartbeat_filter_to_code(config, filter_id): return var +@FILTER_REGISTRY.register( + "timeout", TimeoutFilter, cv.positive_time_period_milliseconds +) +async def timeout_filter_to_code(config, filter_id): + var = cg.new_Pvariable(filter_id, config) + await cg.register_component(var, {}) + return var + + @FILTER_REGISTRY.register( "debounce", DebounceFilter, cv.positive_time_period_milliseconds ) diff --git a/esphome/components/sensor/filter.cpp b/esphome/components/sensor/filter.cpp index 472649ebdc..ccefa556b6 100644 --- a/esphome/components/sensor/filter.cpp +++ b/esphome/components/sensor/filter.cpp @@ -373,6 +373,17 @@ void OrFilter::initialize(Sensor *parent, Filter *next) { this->phi_.initialize(parent, nullptr); } +// TimeoutFilter +optional TimeoutFilter::new_value(float value) { + this->set_timeout("timeout", this->time_period_, [this]() { this->output(NAN); }); + this->output(value); + + return {}; +} + +TimeoutFilter::TimeoutFilter(uint32_t time_period) : time_period_(time_period) {} +float TimeoutFilter::get_setup_priority() const { return setup_priority::HARDWARE; } + // DebounceFilter optional DebounceFilter::new_value(float value) { this->set_timeout("debounce", this->time_period_, [this, value]() { this->output(value); }); diff --git a/esphome/components/sensor/filter.h b/esphome/components/sensor/filter.h index 05934a26e8..296990f34f 100644 --- a/esphome/components/sensor/filter.h +++ b/esphome/components/sensor/filter.h @@ -313,6 +313,18 @@ class ThrottleFilter : public Filter { uint32_t min_time_between_inputs_; }; +class TimeoutFilter : public Filter, public Component { + public: + explicit TimeoutFilter(uint32_t time_period); + + optional new_value(float value) override; + + float get_setup_priority() const override; + + protected: + uint32_t time_period_; +}; + class DebounceFilter : public Filter, public Component { public: explicit DebounceFilter(uint32_t time_period); diff --git a/tests/test3.1.yaml b/tests/test3.1.yaml index 5f1d3ff28f..104f4bbda8 100644 --- a/tests/test3.1.yaml +++ b/tests/test3.1.yaml @@ -86,6 +86,7 @@ sensor: - delta: 100 - throttle: 100ms - debounce: 500s + - timeout: 10min - calibrate_linear: - 0 -> 0 - 100 -> 100 From 68affce274d34eb05aa508f9b6c359101d55ec37 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 17 Jul 2023 09:29:32 +1200 Subject: [PATCH 0027/2101] Bump version to 2023.7.0b2 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index e74f23e9b4..8e0efaca09 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2023.7.0b1" +__version__ = "2023.7.0b2" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 553132443fbf777664fb0959301d8788ad26e8c0 Mon Sep 17 00:00:00 2001 From: bwynants Date: Mon, 17 Jul 2023 00:42:49 +0200 Subject: [PATCH 0028/2101] P1 values for capacity tariff in Belgium (#5081) --- esphome/components/dsmr/__init__.py | 2 +- esphome/components/dsmr/sensor.py | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/esphome/components/dsmr/__init__.py b/esphome/components/dsmr/__init__.py index d3d20ca2a7..9f56dc3465 100644 --- a/esphome/components/dsmr/__init__.py +++ b/esphome/components/dsmr/__init__.py @@ -87,7 +87,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("glmnet/Dsmr", "0.7") + cg.add_library("glmnet/Dsmr", "0.8") # Crypto cg.add_library("rweather/Crypto", "0.4.0") diff --git a/esphome/components/dsmr/sensor.py b/esphome/components/dsmr/sensor.py index 2e2050ecab..f2398d1908 100644 --- a/esphome/components/dsmr/sensor.py +++ b/esphome/components/dsmr/sensor.py @@ -243,6 +243,30 @@ CONFIG_SCHEMA = cv.Schema( device_class=DEVICE_CLASS_WATER, state_class=STATE_CLASS_TOTAL_INCREASING, ), + cv.Optional( + "active_energy_import_current_average_demand" + ): sensor.sensor_schema( + unit_of_measurement=UNIT_KILOWATT, + accuracy_decimals=3, + device_class=DEVICE_CLASS_POWER, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional( + "active_energy_import_maximum_demand_running_month" + ): sensor.sensor_schema( + unit_of_measurement=UNIT_KILOWATT, + accuracy_decimals=3, + device_class=DEVICE_CLASS_POWER, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional( + "active_energy_import_maximum_demand_last_13_months" + ): sensor.sensor_schema( + unit_of_measurement=UNIT_KILOWATT, + accuracy_decimals=3, + device_class=DEVICE_CLASS_POWER, + state_class=STATE_CLASS_MEASUREMENT, + ), } ).extend(cv.COMPONENT_SCHEMA) From f840eee1b7633333d3a23abc457c5cc38a419cef Mon Sep 17 00:00:00 2001 From: "Kevin P. Fleming" Date: Sun, 16 Jul 2023 15:43:57 -0700 Subject: [PATCH 0029/2101] airthings_wave: Silence compiler warnings (#5098) --- .../components/airthings_wave_base/airthings_wave_base.cpp | 2 +- .../components/airthings_wave_plus/airthings_wave_plus.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/airthings_wave_base/airthings_wave_base.cpp b/esphome/components/airthings_wave_base/airthings_wave_base.cpp index eff466f413..16789ff454 100644 --- a/esphome/components/airthings_wave_base/airthings_wave_base.cpp +++ b/esphome/components/airthings_wave_base/airthings_wave_base.cpp @@ -76,7 +76,7 @@ void AirthingsWaveBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt } } -bool AirthingsWaveBase::is_valid_voc_value_(uint16_t voc) { return 0 <= voc && voc <= 16383; } +bool AirthingsWaveBase::is_valid_voc_value_(uint16_t voc) { return voc <= 16383; } void AirthingsWaveBase::update() { if (this->node_state != espbt::ClientState::ESTABLISHED) { diff --git a/esphome/components/airthings_wave_plus/airthings_wave_plus.cpp b/esphome/components/airthings_wave_plus/airthings_wave_plus.cpp index e44d5fbcaa..a32128e992 100644 --- a/esphome/components/airthings_wave_plus/airthings_wave_plus.cpp +++ b/esphome/components/airthings_wave_plus/airthings_wave_plus.cpp @@ -51,9 +51,9 @@ void AirthingsWavePlus::read_sensors(uint8_t *raw_value, uint16_t value_len) { this->response_received_(); } -bool AirthingsWavePlus::is_valid_radon_value_(uint16_t radon) { return 0 <= radon && radon <= 16383; } +bool AirthingsWavePlus::is_valid_radon_value_(uint16_t radon) { return radon <= 16383; } -bool AirthingsWavePlus::is_valid_co2_value_(uint16_t co2) { return 0 <= co2 && co2 <= 16383; } +bool AirthingsWavePlus::is_valid_co2_value_(uint16_t co2) { return co2 <= 16383; } void AirthingsWavePlus::dump_config() { // these really don't belong here, but there doesn't seem to be a From 036e14ab7fb72bb25be026f9c9099aaf3ac95856 Mon Sep 17 00:00:00 2001 From: PlainTechEnthusiast <135363826+PlainTechEnthusiast@users.noreply.github.com> Date: Mon, 17 Jul 2023 20:49:04 -0400 Subject: [PATCH 0030/2101] Sigma delta fix (#4911) --- .../sigma_delta_output/sigma_delta_output.cpp | 57 +++++++++++++++++++ .../sigma_delta_output/sigma_delta_output.h | 31 ++-------- 2 files changed, 63 insertions(+), 25 deletions(-) create mode 100644 esphome/components/sigma_delta_output/sigma_delta_output.cpp diff --git a/esphome/components/sigma_delta_output/sigma_delta_output.cpp b/esphome/components/sigma_delta_output/sigma_delta_output.cpp new file mode 100644 index 0000000000..d386f8db1a --- /dev/null +++ b/esphome/components/sigma_delta_output/sigma_delta_output.cpp @@ -0,0 +1,57 @@ +#include "sigma_delta_output.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace sigma_delta_output { + +static const char *const TAG = "output.sigma_delta"; + +void SigmaDeltaOutput::setup() { + if (this->pin_) + this->pin_->setup(); +} + +void SigmaDeltaOutput::dump_config() { + ESP_LOGCONFIG(TAG, "Sigma Delta Output:"); + LOG_PIN(" Pin: ", this->pin_); + if (this->state_change_trigger_) { + ESP_LOGCONFIG(TAG, " State change automation configured"); + } + if (this->turn_on_trigger_) { + ESP_LOGCONFIG(TAG, " Turn on automation configured"); + } + if (this->turn_off_trigger_) { + ESP_LOGCONFIG(TAG, " Turn off automation configured"); + } + LOG_UPDATE_INTERVAL(this); + LOG_FLOAT_OUTPUT(this); +} + +void SigmaDeltaOutput::update() { + this->accum_ += this->state_; + const bool next_value = this->accum_ > 0; + + if (next_value) { + this->accum_ -= 1.; + } + + if (next_value != this->value_) { + this->value_ = next_value; + if (this->pin_) { + this->pin_->digital_write(next_value); + } + + if (this->state_change_trigger_) { + this->state_change_trigger_->trigger(next_value); + } + + if (next_value && this->turn_on_trigger_) { + this->turn_on_trigger_->trigger(); + } else if (!next_value && this->turn_off_trigger_) { + this->turn_off_trigger_->trigger(); + } + } +} + +} // namespace sigma_delta_output +} // namespace esphome diff --git a/esphome/components/sigma_delta_output/sigma_delta_output.h b/esphome/components/sigma_delta_output/sigma_delta_output.h index 5a5acd2dfb..8fd1e1f761 100644 --- a/esphome/components/sigma_delta_output/sigma_delta_output.h +++ b/esphome/components/sigma_delta_output/sigma_delta_output.h @@ -1,9 +1,12 @@ #pragma once +#include "esphome/core/automation.h" #include "esphome/core/component.h" +#include "esphome/core/hal.h" #include "esphome/components/output/float_output.h" namespace esphome { namespace sigma_delta_output { + class SigmaDeltaOutput : public PollingComponent, public output::FloatOutput { public: Trigger<> *get_turn_on_trigger() { @@ -25,31 +28,9 @@ class SigmaDeltaOutput : public PollingComponent, public output::FloatOutput { void set_pin(GPIOPin *pin) { this->pin_ = pin; }; void write_state(float state) override { this->state_ = state; } - void update() override { - this->accum_ += this->state_; - const bool next_value = this->accum_ > 0; - - if (next_value) { - this->accum_ -= 1.; - } - - if (next_value != this->value_) { - this->value_ = next_value; - if (this->pin_) { - this->pin_->digital_write(next_value); - } - - if (this->state_change_trigger_) { - this->state_change_trigger_->trigger(next_value); - } - - if (next_value && this->turn_on_trigger_) { - this->turn_on_trigger_->trigger(); - } else if (!next_value && this->turn_off_trigger_) { - this->turn_off_trigger_->trigger(); - } - } - } + void setup() override; + void dump_config() override; + void update() override; protected: GPIOPin *pin_{nullptr}; From 4449248c6f65a2ad4e70fbdc96e7f1db0cc3542c Mon Sep 17 00:00:00 2001 From: voed Date: Tue, 18 Jul 2023 03:50:32 +0300 Subject: [PATCH 0031/2101] [LD2410] Remove baud_rate check (#5112) --- esphome/components/ld2410/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/esphome/components/ld2410/__init__.py b/esphome/components/ld2410/__init__.py index be39cc2979..47c4cdb0bd 100644 --- a/esphome/components/ld2410/__init__.py +++ b/esphome/components/ld2410/__init__.py @@ -112,7 +112,6 @@ CONFIG_SCHEMA = cv.All( FINAL_VALIDATE_SCHEMA = uart.final_validate_device_schema( "ld2410", - baud_rate=256000, require_tx=True, require_rx=True, parity="NONE", From 746488cabf2d4ac8db4b0d7883dc72dd8c5aa73c Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 19 Jul 2023 11:38:47 +1200 Subject: [PATCH 0032/2101] Fix silence detection flag on voice assistant (#5120) --- esphome/components/api/api.proto | 1 + esphome/components/api/api_connection.cpp | 3 ++- esphome/components/api/api_connection.h | 2 +- esphome/components/api/api_pb2.cpp | 9 +++++++++ esphome/components/api/api_pb2.h | 1 + esphome/components/api/api_server.cpp | 6 +++--- esphome/components/api/api_server.h | 2 +- esphome/components/voice_assistant/voice_assistant.cpp | 2 +- esphome/components/voice_assistant/voice_assistant.h | 6 +----- 9 files changed, 20 insertions(+), 12 deletions(-) diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index 0d68d9fe55..86685aa5e6 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -1420,6 +1420,7 @@ message VoiceAssistantRequest { bool start = 1; string conversation_id = 2; + bool use_vad = 3; } message VoiceAssistantResponse { diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 858ff0e525..a46efd80e5 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -907,12 +907,13 @@ BluetoothConnectionsFreeResponse APIConnection::subscribe_bluetooth_connections_ #endif #ifdef USE_VOICE_ASSISTANT -bool APIConnection::request_voice_assistant(bool start, const std::string &conversation_id) { +bool APIConnection::request_voice_assistant(bool start, const std::string &conversation_id, bool use_vad) { if (!this->voice_assistant_subscription_) return false; VoiceAssistantRequest msg; msg.start = start; msg.conversation_id = conversation_id; + msg.use_vad = use_vad; return this->send_voice_assistant_request(msg); } void APIConnection::on_voice_assistant_response(const VoiceAssistantResponse &msg) { diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index c146adff02..acc4578661 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -124,7 +124,7 @@ class APIConnection : public APIServerConnection { void subscribe_voice_assistant(const SubscribeVoiceAssistantRequest &msg) override { this->voice_assistant_subscription_ = msg.subscribe; } - bool request_voice_assistant(bool start, const std::string &conversation_id); + bool request_voice_assistant(bool start, const std::string &conversation_id, bool use_vad); void on_voice_assistant_response(const VoiceAssistantResponse &msg) override; void on_voice_assistant_event_response(const VoiceAssistantEventResponse &msg) override; #endif diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index 8c7f6d0c4a..3a2d980e57 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -6348,6 +6348,10 @@ bool VoiceAssistantRequest::decode_varint(uint32_t field_id, ProtoVarInt value) this->start = value.as_bool(); return true; } + case 3: { + this->use_vad = value.as_bool(); + return true; + } default: return false; } @@ -6365,6 +6369,7 @@ bool VoiceAssistantRequest::decode_length(uint32_t field_id, ProtoLengthDelimite void VoiceAssistantRequest::encode(ProtoWriteBuffer buffer) const { buffer.encode_bool(1, this->start); buffer.encode_string(2, this->conversation_id); + buffer.encode_bool(3, this->use_vad); } #ifdef HAS_PROTO_MESSAGE_DUMP void VoiceAssistantRequest::dump_to(std::string &out) const { @@ -6377,6 +6382,10 @@ void VoiceAssistantRequest::dump_to(std::string &out) const { out.append(" conversation_id: "); out.append("'").append(this->conversation_id).append("'"); out.append("\n"); + + out.append(" use_vad: "); + out.append(YESNO(this->use_vad)); + out.append("\n"); out.append("}"); } #endif diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index 769f7aaff5..627165953d 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -1655,6 +1655,7 @@ class VoiceAssistantRequest : public ProtoMessage { public: bool start{false}; std::string conversation_id{}; + bool use_vad{false}; void encode(ProtoWriteBuffer buffer) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; diff --git a/esphome/components/api/api_server.cpp b/esphome/components/api/api_server.cpp index 87b5f9e63f..f70d45ecd0 100644 --- a/esphome/components/api/api_server.cpp +++ b/esphome/components/api/api_server.cpp @@ -323,16 +323,16 @@ void APIServer::on_shutdown() { } #ifdef USE_VOICE_ASSISTANT -bool APIServer::start_voice_assistant(const std::string &conversation_id) { +bool APIServer::start_voice_assistant(const std::string &conversation_id, bool use_vad) { for (auto &c : this->clients_) { - if (c->request_voice_assistant(true, conversation_id)) + if (c->request_voice_assistant(true, conversation_id, use_vad)) return true; } return false; } void APIServer::stop_voice_assistant() { for (auto &c : this->clients_) { - if (c->request_voice_assistant(false, "")) + if (c->request_voice_assistant(false, "", false)) return; } } diff --git a/esphome/components/api/api_server.h b/esphome/components/api/api_server.h index be124f42ff..9b40a5ef02 100644 --- a/esphome/components/api/api_server.h +++ b/esphome/components/api/api_server.h @@ -81,7 +81,7 @@ class APIServer : public Component, public Controller { #endif #ifdef USE_VOICE_ASSISTANT - bool start_voice_assistant(const std::string &conversation_id); + bool start_voice_assistant(const std::string &conversation_id, bool use_vad); void stop_voice_assistant(); #endif diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index 44d640ff39..217ddb6354 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -130,7 +130,7 @@ void VoiceAssistant::start(struct sockaddr_storage *addr, uint16_t port) { void VoiceAssistant::request_start(bool continuous) { ESP_LOGD(TAG, "Requesting start..."); - if (!api::global_api_server->start_voice_assistant(this->conversation_id_)) { + if (!api::global_api_server->start_voice_assistant(this->conversation_id_, this->silence_detection_)) { ESP_LOGW(TAG, "Could not request start."); this->error_trigger_->trigger("not-connected", "Could not request start."); this->continuous_ = false; diff --git a/esphome/components/voice_assistant/voice_assistant.h b/esphome/components/voice_assistant/voice_assistant.h index b103584509..e67baaee65 100644 --- a/esphome/components/voice_assistant/voice_assistant.h +++ b/esphome/components/voice_assistant/voice_assistant.h @@ -25,10 +25,9 @@ namespace voice_assistant { // Version 1: Initial version // Version 2: Adds raw speaker support -// Version 3: Adds continuous support +// Version 3: Unused/skip static const uint32_t INITIAL_VERSION = 1; static const uint32_t SPEAKER_SUPPORT = 2; -static const uint32_t SILENCE_DETECTION_SUPPORT = 3; class VoiceAssistant : public Component { public: @@ -48,9 +47,6 @@ class VoiceAssistant : public Component { uint32_t get_version() const { #ifdef USE_SPEAKER if (this->speaker_ != nullptr) { - if (this->silence_detection_) { - return SILENCE_DETECTION_SUPPORT; - } return SPEAKER_SUPPORT; } #endif From f4a4956dd40f43e89a1aea3e8ecc64cb2558a622 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 19 Jul 2023 11:41:24 +1200 Subject: [PATCH 0033/2101] Bump version to 2023.7.0b3 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 8e0efaca09..8dd947b26b 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2023.7.0b2" +__version__ = "2023.7.0b3" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From f5e98eb86f584c455851d9bfc5ce3e470c39973b Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 19 Jul 2023 12:59:51 +1200 Subject: [PATCH 0034/2101] Bump version to 2023.7.0 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 8dd947b26b..f04e19c359 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2023.7.0b3" +__version__ = "2023.7.0" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 2a7aa2fc0dc940b85738c3e2d8f57f9e507b85c4 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 19 Jul 2023 14:07:42 +1200 Subject: [PATCH 0035/2101] bump pyyaml to 6.0.1 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 618fc94e0b..74c15c9213 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ voluptuous==0.13.1 -PyYAML==6.0 +PyYAML==6.0.1 paho-mqtt==1.6.1 colorama==0.4.6 tornado==6.3.2 From 73db164fb13807ce8bbf0431035041fc293dede7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Wed, 19 Jul 2023 22:39:35 +0200 Subject: [PATCH 0036/2101] Dashboard: use Popen() on Windows (#5110) --- esphome/dashboard/dashboard.py | 60 +++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 9 deletions(-) diff --git a/esphome/dashboard/dashboard.py b/esphome/dashboard/dashboard.py index dd800f534c..a3a44de9ed 100644 --- a/esphome/dashboard/dashboard.py +++ b/esphome/dashboard/dashboard.py @@ -25,6 +25,7 @@ import tornado.ioloop import tornado.iostream import tornado.netutil import tornado.process +import tornado.queues import tornado.web import tornado.websocket import yaml @@ -202,7 +203,11 @@ class EsphomeCommandWebSocket(tornado.websocket.WebSocketHandler): def __init__(self, application, request, **kwargs): super().__init__(application, request, **kwargs) self._proc = None + self._queue = None self._is_closed = False + # Windows doesn't support non-blocking pipes, + # use Popen() with a reading thread instead + self._use_popen = os.name == "nt" @authenticated def on_message(self, message): @@ -224,13 +229,28 @@ class EsphomeCommandWebSocket(tornado.websocket.WebSocketHandler): return command = self.build_command(json_message) _LOGGER.info("Running command '%s'", " ".join(shlex_quote(x) for x in command)) - self._proc = tornado.process.Subprocess( - command, - stdout=tornado.process.Subprocess.STREAM, - stderr=subprocess.STDOUT, - stdin=tornado.process.Subprocess.STREAM, - ) - self._proc.set_exit_callback(self._proc_on_exit) + + if self._use_popen: + self._queue = tornado.queues.Queue() + # pylint: disable=consider-using-with + self._proc = subprocess.Popen( + command, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + ) + stdout_thread = threading.Thread(target=self._stdout_thread) + stdout_thread.daemon = True + stdout_thread.start() + else: + self._proc = tornado.process.Subprocess( + command, + stdout=tornado.process.Subprocess.STREAM, + stderr=subprocess.STDOUT, + stdin=tornado.process.Subprocess.STREAM, + ) + self._proc.set_exit_callback(self._proc_on_exit) + tornado.ioloop.IOLoop.current().spawn_callback(self._redirect_stdout) @property @@ -252,7 +272,13 @@ class EsphomeCommandWebSocket(tornado.websocket.WebSocketHandler): while True: try: - data = yield self._proc.stdout.read_until_regex(reg) + if self._use_popen: + data = yield self._queue.get() + if data is None: + self._proc_on_exit(self._proc.poll()) + break + else: + data = yield self._proc.stdout.read_until_regex(reg) except tornado.iostream.StreamClosedError: break data = codecs.decode(data, "utf8", "replace") @@ -260,6 +286,19 @@ class EsphomeCommandWebSocket(tornado.websocket.WebSocketHandler): _LOGGER.debug("> stdout: %s", data) self.write_message({"event": "line", "data": data}) + def _stdout_thread(self): + if not self._use_popen: + return + while True: + data = self._proc.stdout.readline() + if data: + data = data.replace(b"\r", b"") + self._queue.put_nowait(data) + if self._proc.poll() is not None: + break + self._proc.wait(1.0) + self._queue.put_nowait(None) + def _proc_on_exit(self, returncode): if not self._is_closed: # Check if the proc was not forcibly closed @@ -270,7 +309,10 @@ class EsphomeCommandWebSocket(tornado.websocket.WebSocketHandler): # Check if proc exists (if 'start' has been run) if self.is_process_active: _LOGGER.debug("Terminating process") - self._proc.proc.terminate() + if self._use_popen: + self._proc.terminate() + else: + self._proc.proc.terminate() # Shutdown proc on WS close self._is_closed = True From 3843d21dbf4d2869b1a5fcb6d5c0bb8952f931fc Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Sun, 30 Jul 2023 16:19:06 -0500 Subject: [PATCH 0037/2101] Swap ADC back to use 'int' because C3 (#5151) --- esphome/components/adc/adc_sensor.cpp | 10 +++++----- esphome/components/adc/adc_sensor.h | 2 +- tests/test7.yaml | 8 ++++++++ 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/esphome/components/adc/adc_sensor.cpp b/esphome/components/adc/adc_sensor.cpp index bb6a7a8c85..665ecfd6b5 100644 --- a/esphome/components/adc/adc_sensor.cpp +++ b/esphome/components/adc/adc_sensor.cpp @@ -32,8 +32,8 @@ static const int32_t SOC_ADC_RTC_MAX_BITWIDTH = 12; #endif #endif -static const int32_t ADC_MAX = (1 << SOC_ADC_RTC_MAX_BITWIDTH) - 1; // 4095 (12 bit) or 8191 (13 bit) -static const int32_t ADC_HALF = (1 << SOC_ADC_RTC_MAX_BITWIDTH) >> 1; // 2048 (12 bit) or 4096 (13 bit) +static const int ADC_MAX = (1 << SOC_ADC_RTC_MAX_BITWIDTH) - 1; // 4095 (12 bit) or 8191 (13 bit) +static const int ADC_HALF = (1 << SOC_ADC_RTC_MAX_BITWIDTH) >> 1; // 2048 (12 bit) or 4096 (13 bit) #endif #ifdef USE_RP2040 @@ -59,7 +59,7 @@ extern "C" } // load characteristics for each attenuation - for (int32_t i = 0; i < (int32_t) ADC_ATTEN_MAX; i++) { + for (int32_t i = 0; i <= ADC_ATTEN_DB_11; i++) { auto adc_unit = channel1_ != ADC1_CHANNEL_MAX ? ADC_UNIT_1 : ADC_UNIT_2; auto cal_value = esp_adc_cal_characterize(adc_unit, (adc_atten_t) i, ADC_WIDTH_MAX_SOC_BITS, 1100, // default vref @@ -157,7 +157,7 @@ float ADCSensor::sample() { #ifdef USE_ESP32 float ADCSensor::sample() { if (!autorange_) { - int32_t raw = -1; + int raw = -1; if (channel1_ != ADC1_CHANNEL_MAX) { raw = adc1_get_raw(channel1_); } else if (channel2_ != ADC2_CHANNEL_MAX) { @@ -174,7 +174,7 @@ float ADCSensor::sample() { return mv / 1000.0f; } - int32_t raw11 = ADC_MAX, raw6 = ADC_MAX, raw2 = ADC_MAX, raw0 = ADC_MAX; + int raw11 = ADC_MAX, raw6 = ADC_MAX, raw2 = ADC_MAX, raw0 = ADC_MAX; if (channel1_ != ADC1_CHANNEL_MAX) { adc1_config_channel_atten(channel1_, ADC_ATTEN_DB_11); diff --git a/esphome/components/adc/adc_sensor.h b/esphome/components/adc/adc_sensor.h index a905177790..7d9c8959da 100644 --- a/esphome/components/adc/adc_sensor.h +++ b/esphome/components/adc/adc_sensor.h @@ -62,7 +62,7 @@ class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage adc1_channel_t channel1_{ADC1_CHANNEL_MAX}; adc2_channel_t channel2_{ADC2_CHANNEL_MAX}; bool autorange_{false}; - esp_adc_cal_characteristics_t cal_characteristics_[(int32_t) ADC_ATTEN_MAX] = {}; + esp_adc_cal_characteristics_t cal_characteristics_[ADC_ATTEN_MAX] = {}; #endif }; diff --git a/tests/test7.yaml b/tests/test7.yaml index 10e1b035ab..8d48c9a601 100644 --- a/tests/test7.yaml +++ b/tests/test7.yaml @@ -31,3 +31,11 @@ logger: http_request: useragent: esphome/tagreader timeout: 10s + +sensor: + - platform: adc + id: adc_sensor_p4 + name: ADC pin 4 + pin: 4 + attenuation: 11db + update_interval: 1s From 9b19c45735d6135e5dd4b968429f665a562a9a13 Mon Sep 17 00:00:00 2001 From: Stijn Tintel Date: Mon, 31 Jul 2023 00:23:30 +0300 Subject: [PATCH 0038/2101] wifi: handle WIFI_REASON_ROAMING reason in event (#5153) --- esphome/components/wifi/wifi_component_esp_idf.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index 744fc755fe..086a80cad0 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -569,6 +569,8 @@ const char *get_disconnect_reason_str(uint8_t reason) { return "Handshake Failed"; case WIFI_REASON_CONNECTION_FAIL: return "Connection Failed"; + case WIFI_REASON_ROAMING: + return "Station Roaming"; case WIFI_REASON_UNSPECIFIED: default: return "Unspecified"; @@ -631,7 +633,9 @@ void WiFiComponent::wifi_process_event_(IDFWiFiEvent *data) { if (it.reason == WIFI_REASON_NO_AP_FOUND) { ESP_LOGW(TAG, "Event: Disconnected ssid='%s' reason='Probe Request Unsuccessful'", buf); s_sta_connect_not_found = true; - + } else if (it.reason == WIFI_REASON_ROAMING) { + ESP_LOGI(TAG, "Event: Disconnected ssid='%s' reason='Station Roaming'", buf); + return; } else { ESP_LOGW(TAG, "Event: Disconnected ssid='%s' bssid=" LOG_SECRET("%s") " reason='%s'", buf, format_mac_addr(it.bssid).c_str(), get_disconnect_reason_str(it.reason)); From 91e920c498dfbd15a94b56ca44a431a337b194ef Mon Sep 17 00:00:00 2001 From: cvwillegen Date: Sun, 30 Jul 2023 23:32:09 +0200 Subject: [PATCH 0039/2101] Slightly lower template switch setup priority (#5163) --- esphome/components/template/switch/template_switch.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/template/switch/template_switch.cpp b/esphome/components/template/switch/template_switch.cpp index b2a221669e..fa236f6364 100644 --- a/esphome/components/template/switch/template_switch.cpp +++ b/esphome/components/template/switch/template_switch.cpp @@ -36,7 +36,7 @@ void TemplateSwitch::write_state(bool state) { void TemplateSwitch::set_optimistic(bool optimistic) { this->optimistic_ = optimistic; } bool TemplateSwitch::assumed_state() { return this->assumed_state_; } void TemplateSwitch::set_state_lambda(std::function()> &&f) { this->f_ = f; } -float TemplateSwitch::get_setup_priority() const { return setup_priority::HARDWARE; } +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_; } void TemplateSwitch::setup() { From 2a12ec09fb0d93bdf46271f1bda0a7aa85662ec7 Mon Sep 17 00:00:00 2001 From: PlainTechEnthusiast <135363826+PlainTechEnthusiast@users.noreply.github.com> Date: Sun, 30 Jul 2023 17:40:55 -0400 Subject: [PATCH 0040/2101] update "Can't convert" warning to match others in homeassistant_sensor (#5162) --- .../components/homeassistant/sensor/homeassistant_sensor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/homeassistant/sensor/homeassistant_sensor.cpp b/esphome/components/homeassistant/sensor/homeassistant_sensor.cpp index f5e73c8854..35e660f7c1 100644 --- a/esphome/components/homeassistant/sensor/homeassistant_sensor.cpp +++ b/esphome/components/homeassistant/sensor/homeassistant_sensor.cpp @@ -12,7 +12,7 @@ void HomeassistantSensor::setup() { this->entity_id_, this->attribute_, [this](const std::string &state) { auto val = parse_number(state); if (!val.has_value()) { - ESP_LOGW(TAG, "Can't convert '%s' to number!", state.c_str()); + ESP_LOGW(TAG, "'%s': Can't convert '%s' to number!", this->entity_id_.c_str(), state.c_str()); this->publish_state(NAN); return; } From dec044ad8b4083219015dff939304ed7fc348a5b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 30 Jul 2023 15:23:52 -0700 Subject: [PATCH 0041/2101] Increase maximum number of BLE notifications (#5155) --- esphome/components/esp32_ble_tracker/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/esp32_ble_tracker/__init__.py b/esphome/components/esp32_ble_tracker/__init__.py index 30589f1a3f..8ba77c7db7 100644 --- a/esphome/components/esp32_ble_tracker/__init__.py +++ b/esphome/components/esp32_ble_tracker/__init__.py @@ -263,6 +263,7 @@ async def to_code(config): # Match arduino CONFIG_BTU_TASK_STACK_SIZE # https://github.com/espressif/arduino-esp32/blob/fd72cf46ad6fc1a6de99c1d83ba8eba17d80a4ee/tools/sdk/esp32/sdkconfig#L1866 add_idf_sdkconfig_option("CONFIG_BTU_TASK_STACK_SIZE", 8192) + add_idf_sdkconfig_option("CONFIG_BT_ACL_CONNECTIONS", 9) cg.add_define("USE_OTA_STATE_CALLBACK") # To be notified when an OTA update starts cg.add_define("USE_ESP32_BLE_CLIENT") From c63cdae84fb1dc348bcdecfaa05f428c0ddbccf8 Mon Sep 17 00:00:00 2001 From: Joris S <100357138+Jorre05@users.noreply.github.com> Date: Mon, 31 Jul 2023 00:30:21 +0200 Subject: [PATCH 0042/2101] invert min_rssi check (#5150) --- esphome/components/ble_presence/binary_sensor.py | 2 +- esphome/components/ble_presence/ble_presence_device.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/ble_presence/binary_sensor.py b/esphome/components/ble_presence/binary_sensor.py index d54b7678e1..75366ce864 100644 --- a/esphome/components/ble_presence/binary_sensor.py +++ b/esphome/components/ble_presence/binary_sensor.py @@ -39,7 +39,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_IBEACON_MINOR): cv.uint16_t, cv.Optional(CONF_IBEACON_UUID): cv.uuid, cv.Optional(CONF_MIN_RSSI): cv.All( - cv.decibel, cv.int_range(min=-90, max=-30) + cv.decibel, cv.int_range(min=-100, max=-30) ), } ) diff --git a/esphome/components/ble_presence/ble_presence_device.h b/esphome/components/ble_presence/ble_presence_device.h index 953ea460a8..1be9adeb30 100644 --- a/esphome/components/ble_presence/ble_presence_device.h +++ b/esphome/components/ble_presence/ble_presence_device.h @@ -51,7 +51,7 @@ class BLEPresenceDevice : public binary_sensor::BinarySensorInitiallyOff, this->found_ = false; } bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override { - if (this->check_minimum_rssi_ && this->minimum_rssi_ <= device.get_rssi()) { + if (this->check_minimum_rssi_ && this->minimum_rssi_ > device.get_rssi()) { return false; } switch (this->match_by_) { From b3d5a4dfdba90301ef24aea3f20d769c5008a795 Mon Sep 17 00:00:00 2001 From: Maxime Michel Date: Tue, 1 Aug 2023 02:03:34 +0200 Subject: [PATCH 0043/2101] Fix graininess & streaks for 7.50inV2alt Waveshare e-paper (#5168) --- .../components/waveshare_epaper/waveshare_epaper.cpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/esphome/components/waveshare_epaper/waveshare_epaper.cpp b/esphome/components/waveshare_epaper/waveshare_epaper.cpp index d64a5500dd..d17f8230de 100644 --- a/esphome/components/waveshare_epaper/waveshare_epaper.cpp +++ b/esphome/components/waveshare_epaper/waveshare_epaper.cpp @@ -1492,11 +1492,10 @@ void WaveshareEPaper7P5InV2alt::initialize() { this->command(0x01); // 1-0=11: internal power - this->data(0x17); - + this->data(0x07); this->data(0x17); // VGH&VGL this->data(0x3F); // VSH - this->data(0x3F); // VSL + this->data(0x26); // VSL this->data(0x11); // VSHR // VCOM DC Setting @@ -1510,10 +1509,6 @@ void WaveshareEPaper7P5InV2alt::initialize() { this->data(0x2F); this->data(0x17); - // OSC Setting - this->command(0x30); - this->data(0x06); // 2-0=100: N=4 ; 5-3=111: M=7 ; 3C=50Hz 3A=100HZ - // POWER ON this->command(0x04); @@ -1535,7 +1530,7 @@ void WaveshareEPaper7P5InV2alt::initialize() { // COMMAND VCOM AND DATA INTERVAL SETTING this->command(0x50); this->data(0x10); - this->data(0x07); + this->data(0x00); // COMMAND TCON SETTING this->command(0x60); this->data(0x22); From 956e19be7de7fd73fc16f30d123414fc92eee91c Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 1 Aug 2023 12:08:36 +1200 Subject: [PATCH 0044/2101] Bump version to 2023.7.1 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index f04e19c359..139555f19b 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2023.7.0" +__version__ = "2023.7.1" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 02ed2c0ebeaa975e1d869b05f1b0fd669e02e5b7 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 10 Aug 2023 17:30:26 +1200 Subject: [PATCH 0045/2101] Bump version to 2023.8.0b1 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 4977726361..6b442dd633 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2023.8.0-dev" +__version__ = "2023.8.0b1" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 72e72d7d4b4556876817a0e4af5eef6536eb1c89 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 10 Aug 2023 18:40:13 +1200 Subject: [PATCH 0046/2101] Fix duplicate --- esphome/components/sensor/__init__.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index c8cd2f9f7f..8f7d581b2d 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -560,15 +560,6 @@ async def timeout_filter_to_code(config, filter_id): return var -@FILTER_REGISTRY.register( - "timeout", TimeoutFilter, cv.positive_time_period_milliseconds -) -async def timeout_filter_to_code(config, filter_id): - var = cg.new_Pvariable(filter_id, config) - await cg.register_component(var, {}) - return var - - @FILTER_REGISTRY.register( "debounce", DebounceFilter, cv.positive_time_period_milliseconds ) From 44a917929d5d3af8d803c8363e5031f56be42b7c Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 11 Aug 2023 16:20:58 +1200 Subject: [PATCH 0047/2101] Read string of bool env and match against well known values (#5232) --- esphome/helpers.py | 9 ++++++++- tests/unit_tests/test_helpers.py | 4 ++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/esphome/helpers.py b/esphome/helpers.py index fd8893ad99..4012b2067f 100644 --- a/esphome/helpers.py +++ b/esphome/helpers.py @@ -144,7 +144,14 @@ def resolve_ip_address(host): def get_bool_env(var, default=False): - return bool(os.getenv(var, default)) + value = os.getenv(var, default) + if isinstance(value, str): + value = value.lower() + if value in ["1", "true"]: + return True + if value in ["0", "false"]: + return False + return bool(value) def get_str_env(var, default=None): diff --git a/tests/unit_tests/test_helpers.py b/tests/unit_tests/test_helpers.py index b98838024f..67fabd7af8 100644 --- a/tests/unit_tests/test_helpers.py +++ b/tests/unit_tests/test_helpers.py @@ -108,6 +108,10 @@ def test_is_ip_address__valid(value): ("FOO", None, False, False), ("FOO", None, True, True), ("FOO", "", False, False), + ("FOO", "False", False, False), + ("FOO", "True", False, True), + ("FOO", "FALSE", True, False), + ("FOO", "fAlSe", True, False), ("FOO", "Yes", False, True), ("FOO", "123", False, True), ), From 2fa79a2e2f606b42b33dccc49dae72e97a221a6b Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Thu, 10 Aug 2023 21:21:24 -0700 Subject: [PATCH 0048/2101] fix aeha data template (#5231) Co-authored-by: Samuel Sieb --- esphome/components/remote_base/__init__.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/esphome/components/remote_base/__init__.py b/esphome/components/remote_base/__init__.py index 0666b96d1e..24993e84d3 100644 --- a/esphome/components/remote_base/__init__.py +++ b/esphome/components/remote_base/__init__.py @@ -1569,4 +1569,7 @@ def aeha_dumper(var, config): async def aeha_action(var, config, args): template_ = await cg.templatable(config[CONF_ADDRESS], args, cg.uint16) cg.add(var.set_address(template_)) - cg.add(var.set_data(config[CONF_DATA])) + template_ = await cg.templatable( + config[CONF_DATA], args, cg.std_vector.template(cg.uint8) + ) + cg.add(var.set_data(template_)) From 351e7ea16b0a9af8d126b9019294f53c55d767c9 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 11 Aug 2023 16:21:44 +1200 Subject: [PATCH 0049/2101] Expose start to speaker interface (#5228) --- esphome/components/i2s_audio/speaker/i2s_audio_speaker.h | 2 +- esphome/components/speaker/speaker.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h index f2e83142b3..b075722e1b 100644 --- a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +++ b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h @@ -51,7 +51,7 @@ class I2SAudioSpeaker : public Component, public speaker::Speaker, public I2SAud #endif void set_external_dac_channels(uint8_t channels) { this->external_dac_channels_ = channels; } - void start(); + void start() override; void stop() override; size_t play(const uint8_t *data, size_t length) override; diff --git a/esphome/components/speaker/speaker.h b/esphome/components/speaker/speaker.h index 53f97da5ac..3f520e3c5e 100644 --- a/esphome/components/speaker/speaker.h +++ b/esphome/components/speaker/speaker.h @@ -13,8 +13,9 @@ enum State : uint8_t { class Speaker { public: virtual size_t play(const uint8_t *data, size_t length) = 0; - virtual size_t play(const std::vector &data) { return this->play(data.data(), data.size()); } + size_t play(const std::vector &data) { return this->play(data.data(), data.size()); } + virtual void start() = 0; virtual void stop() = 0; bool is_running() const { return this->state_ == STATE_RUNNING; } From 99a765dc0639f559e1a8fcdb9447869f7df78313 Mon Sep 17 00:00:00 2001 From: Pavlo Dudnytskyi Date: Fri, 11 Aug 2023 07:51:53 +0200 Subject: [PATCH 0050/2101] New features added for Haier integration (#5196) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/haier/climate.py | 74 ++++++- esphome/components/haier/haier_base.cpp | 75 +++++-- esphome/components/haier/haier_base.h | 43 ++-- esphome/components/haier/hon_climate.cpp | 144 ++++++------- esphome/components/haier/hon_climate.h | 5 +- esphome/components/haier/hon_packet.h | 16 +- .../components/haier/smartair2_climate.cpp | 204 +++++++++++++----- esphome/components/haier/smartair2_climate.h | 13 +- esphome/components/haier/smartair2_packet.h | 7 +- platformio.ini | 2 +- 10 files changed, 394 insertions(+), 189 deletions(-) diff --git a/esphome/components/haier/climate.py b/esphome/components/haier/climate.py index c518282bfa..fec39d2967 100644 --- a/esphome/components/haier/climate.py +++ b/esphome/components/haier/climate.py @@ -14,7 +14,10 @@ from esphome.const import ( CONF_MIN_TEMPERATURE, CONF_PROTOCOL, CONF_SUPPORTED_MODES, + CONF_SUPPORTED_PRESETS, CONF_SUPPORTED_SWING_MODES, + CONF_TARGET_TEMPERATURE, + CONF_TEMPERATURE_STEP, CONF_VISUAL, CONF_WIFI, DEVICE_CLASS_TEMPERATURE, @@ -23,25 +26,29 @@ from esphome.const import ( UNIT_CELSIUS, ) from esphome.components.climate import ( - ClimateSwingMode, ClimateMode, + ClimatePreset, + ClimateSwingMode, + CONF_CURRENT_TEMPERATURE, ) _LOGGER = logging.getLogger(__name__) PROTOCOL_MIN_TEMPERATURE = 16.0 PROTOCOL_MAX_TEMPERATURE = 30.0 -PROTOCOL_TEMPERATURE_STEP = 1.0 +PROTOCOL_TARGET_TEMPERATURE_STEP = 1.0 +PROTOCOL_CURRENT_TEMPERATURE_STEP = 0.5 CODEOWNERS = ["@paveldn"] AUTO_LOAD = ["sensor"] DEPENDENCIES = ["climate", "uart"] CONF_WIFI_SIGNAL = "wifi_signal" +CONF_ANSWER_TIMEOUT = "answer_timeout" +CONF_DISPLAY = "display" CONF_OUTDOOR_TEMPERATURE = "outdoor_temperature" CONF_VERTICAL_AIRFLOW = "vertical_airflow" CONF_HORIZONTAL_AIRFLOW = "horizontal_airflow" - PROTOCOL_HON = "HON" PROTOCOL_SMARTAIR2 = "SMARTAIR2" PROTOCOLS_SUPPORTED = [PROTOCOL_HON, PROTOCOL_SMARTAIR2] @@ -89,6 +96,17 @@ SUPPORTED_CLIMATE_MODES_OPTIONS = { "FAN_ONLY": ClimateMode.CLIMATE_MODE_FAN_ONLY, } +SUPPORTED_CLIMATE_PRESETS_SMARTAIR2_OPTIONS = { + "BOOST": ClimatePreset.CLIMATE_PRESET_BOOST, + "COMFORT": ClimatePreset.CLIMATE_PRESET_COMFORT, +} + +SUPPORTED_CLIMATE_PRESETS_HON_OPTIONS = { + "ECO": ClimatePreset.CLIMATE_PRESET_ECO, + "BOOST": ClimatePreset.CLIMATE_PRESET_BOOST, + "SLEEP": ClimatePreset.CLIMATE_PRESET_SLEEP, +} + def validate_visual(config): if CONF_VISUAL in config: @@ -109,10 +127,29 @@ def validate_visual(config): ) else: config[CONF_VISUAL][CONF_MAX_TEMPERATURE] = PROTOCOL_MAX_TEMPERATURE + if CONF_TEMPERATURE_STEP in visual_config: + temp_step = config[CONF_VISUAL][CONF_TEMPERATURE_STEP][ + CONF_TARGET_TEMPERATURE + ] + if ((int)(temp_step * 2)) / 2 != temp_step: + raise cv.Invalid( + f"Configured visual temperature step {temp_step} is wrong, it should be a multiple of 0.5" + ) + else: + config[CONF_VISUAL][CONF_TEMPERATURE_STEP] = ( + { + CONF_TARGET_TEMPERATURE: PROTOCOL_TARGET_TEMPERATURE_STEP, + CONF_CURRENT_TEMPERATURE: PROTOCOL_CURRENT_TEMPERATURE_STEP, + }, + ) else: config[CONF_VISUAL] = { CONF_MIN_TEMPERATURE: PROTOCOL_MIN_TEMPERATURE, CONF_MAX_TEMPERATURE: PROTOCOL_MAX_TEMPERATURE, + CONF_TEMPERATURE_STEP: { + CONF_TARGET_TEMPERATURE: PROTOCOL_TARGET_TEMPERATURE_STEP, + CONF_CURRENT_TEMPERATURE: PROTOCOL_CURRENT_TEMPERATURE_STEP, + }, } return config @@ -132,6 +169,11 @@ BASE_CONFIG_SCHEMA = ( "BOTH", ], ): cv.ensure_list(cv.enum(SUPPORTED_SWING_MODES_OPTIONS, upper=True)), + cv.Optional(CONF_WIFI_SIGNAL, default=False): cv.boolean, + cv.Optional(CONF_DISPLAY): cv.boolean, + cv.Optional( + CONF_ANSWER_TIMEOUT, + ): cv.positive_time_period_milliseconds, } ) .extend(uart.UART_DEVICE_SCHEMA) @@ -144,13 +186,26 @@ CONFIG_SCHEMA = cv.All( PROTOCOL_SMARTAIR2: BASE_CONFIG_SCHEMA.extend( { cv.GenerateID(): cv.declare_id(Smartair2Climate), + cv.Optional( + CONF_SUPPORTED_PRESETS, + default=list( + SUPPORTED_CLIMATE_PRESETS_SMARTAIR2_OPTIONS.keys() + ), + ): cv.ensure_list( + cv.enum(SUPPORTED_CLIMATE_PRESETS_SMARTAIR2_OPTIONS, upper=True) + ), } ), PROTOCOL_HON: BASE_CONFIG_SCHEMA.extend( { cv.GenerateID(): cv.declare_id(HonClimate), - cv.Optional(CONF_WIFI_SIGNAL, default=True): cv.boolean, cv.Optional(CONF_BEEPER, default=True): cv.boolean, + cv.Optional( + CONF_SUPPORTED_PRESETS, + default=list(SUPPORTED_CLIMATE_PRESETS_HON_OPTIONS.keys()), + ): cv.ensure_list( + cv.enum(SUPPORTED_CLIMATE_PRESETS_HON_OPTIONS, upper=True) + ), cv.Optional(CONF_OUTDOOR_TEMPERATURE): sensor.sensor_schema( unit_of_measurement=UNIT_CELSIUS, icon=ICON_THERMOMETER, @@ -354,10 +409,11 @@ async def to_code(config): await uart.register_uart_device(var, config) await climate.register_climate(var, config) - if (CONF_WIFI_SIGNAL in config) and (config[CONF_WIFI_SIGNAL]): - cg.add(var.set_send_wifi(config[CONF_WIFI_SIGNAL])) + cg.add(var.set_send_wifi(config[CONF_WIFI_SIGNAL])) if CONF_BEEPER in config: cg.add(var.set_beeper_state(config[CONF_BEEPER])) + if CONF_DISPLAY in config: + cg.add(var.set_display_state(config[CONF_DISPLAY])) if CONF_OUTDOOR_TEMPERATURE in config: sens = await sensor.new_sensor(config[CONF_OUTDOOR_TEMPERATURE]) cg.add(var.set_outdoor_temperature_sensor(sens)) @@ -365,5 +421,9 @@ async def to_code(config): cg.add(var.set_supported_modes(config[CONF_SUPPORTED_MODES])) if CONF_SUPPORTED_SWING_MODES in config: cg.add(var.set_supported_swing_modes(config[CONF_SUPPORTED_SWING_MODES])) + if CONF_SUPPORTED_PRESETS in config: + cg.add(var.set_supported_presets(config[CONF_SUPPORTED_PRESETS])) + if CONF_ANSWER_TIMEOUT in config: + cg.add(var.set_answer_timeout(config[CONF_ANSWER_TIMEOUT])) # https://github.com/paveldn/HaierProtocol - cg.add_library("pavlodn/HaierProtocol", "0.9.18") + cg.add_library("pavlodn/HaierProtocol", "0.9.20") diff --git a/esphome/components/haier/haier_base.cpp b/esphome/components/haier/haier_base.cpp index d9349cb8fe..5faee5207b 100644 --- a/esphome/components/haier/haier_base.cpp +++ b/esphome/components/haier/haier_base.cpp @@ -2,6 +2,9 @@ #include #include "esphome/components/climate/climate.h" #include "esphome/components/uart/uart.h" +#ifdef USE_WIFI +#include "esphome/components/wifi/wifi_component.h" +#endif #include "haier_base.h" using namespace esphome::climate; @@ -24,14 +27,15 @@ constexpr size_t NO_COMMAND = 0xFF; // Indicate that there is no command suppli const char *HaierClimateBase::phase_to_string_(ProtocolPhases phase) { static const char *phase_names[] = { "SENDING_INIT_1", - "WAITING_ANSWER_INIT_1", + "WAITING_INIT_1_ANSWER", "SENDING_INIT_2", - "WAITING_ANSWER_INIT_2", + "WAITING_INIT_2_ANSWER", "SENDING_FIRST_STATUS_REQUEST", "WAITING_FIRST_STATUS_ANSWER", "SENDING_ALARM_STATUS_REQUEST", "WAITING_ALARM_STATUS_ANSWER", "IDLE", + "UNKNOWN", "SENDING_STATUS_REQUEST", "WAITING_STATUS_ANSWER", "SENDING_UPDATE_SIGNAL_REQUEST", @@ -63,7 +67,8 @@ HaierClimateBase::HaierClimateBase() forced_publish_(false), forced_request_status_(false), first_control_attempt_(false), - reset_protocol_request_(false) { + reset_protocol_request_(false), + send_wifi_signal_(true) { this->traits_ = climate::ClimateTraits(); this->traits_.set_supported_modes({climate::CLIMATE_MODE_OFF, climate::CLIMATE_MODE_COOL, climate::CLIMATE_MODE_HEAT, climate::CLIMATE_MODE_FAN_ONLY, climate::CLIMATE_MODE_DRY, @@ -77,7 +82,7 @@ HaierClimateBase::HaierClimateBase() HaierClimateBase::~HaierClimateBase() {} -void HaierClimateBase::set_phase_(ProtocolPhases phase) { +void HaierClimateBase::set_phase(ProtocolPhases phase) { if (this->protocol_phase_ != phase) { #if (HAIER_LOG_LEVEL > 4) ESP_LOGV(TAG, "Phase transition: %s => %s", phase_to_string_(this->protocol_phase_), phase_to_string_(phase)); @@ -109,10 +114,27 @@ bool HaierClimateBase::is_control_message_interval_exceeded_(std::chrono::steady return this->check_timeout_(now, this->last_request_timestamp_, CONTROL_MESSAGES_INTERVAL_MS); } -bool HaierClimateBase::is_protocol_initialisation_interval_exceded_(std::chrono::steady_clock::time_point now) { +bool HaierClimateBase::is_protocol_initialisation_interval_exceeded_(std::chrono::steady_clock::time_point now) { return this->check_timeout_(now, this->last_request_timestamp_, PROTOCOL_INITIALIZATION_INTERVAL); } +#ifdef USE_WIFI +haier_protocol::HaierMessage HaierClimateBase::get_wifi_signal_message_(uint8_t message_type) { + static uint8_t wifi_status_data[4] = {0x00, 0x00, 0x00, 0x00}; + if (wifi::global_wifi_component->is_connected()) { + wifi_status_data[1] = 0; + int8_t rssi = wifi::global_wifi_component->wifi_rssi(); + wifi_status_data[3] = uint8_t((128 + rssi) / 1.28f); + ESP_LOGD(TAG, "WiFi signal is: %ddBm => %d%%", rssi, wifi_status_data[3]); + } else { + ESP_LOGD(TAG, "WiFi is not connected"); + wifi_status_data[1] = 1; + wifi_status_data[3] = 0; + } + return haier_protocol::HaierMessage(message_type, wifi_status_data, sizeof(wifi_status_data)); +} +#endif + bool HaierClimateBase::get_display_state() const { return this->display_status_; } void HaierClimateBase::set_display_state(bool state) { @@ -136,10 +158,15 @@ void HaierClimateBase::send_power_on_command() { this->action_request_ = ActionR void HaierClimateBase::send_power_off_command() { this->action_request_ = ActionRequest::TURN_POWER_OFF; } void HaierClimateBase::toggle_power() { this->action_request_ = ActionRequest::TOGGLE_POWER; } + void HaierClimateBase::set_supported_swing_modes(const std::set &modes) { this->traits_.set_supported_swing_modes(modes); - this->traits_.add_supported_swing_mode(climate::CLIMATE_SWING_OFF); // Always available - this->traits_.add_supported_swing_mode(climate::CLIMATE_SWING_VERTICAL); // Always available + if (!modes.empty()) + this->traits_.add_supported_swing_mode(climate::CLIMATE_SWING_OFF); +} + +void HaierClimateBase::set_answer_timeout(uint32_t timeout) { + this->answer_timeout_ = std::chrono::milliseconds(timeout); } void HaierClimateBase::set_supported_modes(const std::set &modes) { @@ -148,6 +175,14 @@ void HaierClimateBase::set_supported_modes(const std::set this->traits_.add_supported_mode(climate::CLIMATE_MODE_AUTO); // Always available } +void HaierClimateBase::set_supported_presets(const std::set &presets) { + this->traits_.set_supported_presets(presets); + if (!presets.empty()) + this->traits_.add_supported_preset(climate::CLIMATE_PRESET_NONE); +} + +void HaierClimateBase::set_send_wifi(bool send_wifi) { this->send_wifi_signal_ = send_wifi; } + haier_protocol::HandlerError HaierClimateBase::answer_preprocess_(uint8_t request_message_type, uint8_t expected_request_message_type, uint8_t answer_message_type, @@ -155,9 +190,9 @@ haier_protocol::HandlerError HaierClimateBase::answer_preprocess_(uint8_t reques ProtocolPhases expected_phase) { haier_protocol::HandlerError result = haier_protocol::HandlerError::HANDLER_OK; if ((expected_request_message_type != NO_COMMAND) && (request_message_type != expected_request_message_type)) - result = haier_protocol::HandlerError::UNSUPORTED_MESSAGE; + result = haier_protocol::HandlerError::UNSUPPORTED_MESSAGE; if ((expected_answer_message_type != NO_COMMAND) && (answer_message_type != expected_answer_message_type)) - result = haier_protocol::HandlerError::UNSUPORTED_MESSAGE; + result = haier_protocol::HandlerError::UNSUPPORTED_MESSAGE; if ((expected_phase != ProtocolPhases::UNKNOWN) && (expected_phase != this->protocol_phase_)) result = haier_protocol::HandlerError::UNEXPECTED_MESSAGE; if (is_message_invalid(answer_message_type)) @@ -172,9 +207,9 @@ haier_protocol::HandlerError HaierClimateBase::timeout_default_handler_(uint8_t ESP_LOGW(TAG, "Answer timeout for command %02X, phase %d", request_type, (int) this->protocol_phase_); #endif if (this->protocol_phase_ > ProtocolPhases::IDLE) { - this->set_phase_(ProtocolPhases::IDLE); + this->set_phase(ProtocolPhases::IDLE); } else { - this->set_phase_(ProtocolPhases::SENDING_INIT_1); + this->set_phase(ProtocolPhases::SENDING_INIT_1); } return haier_protocol::HandlerError::HANDLER_OK; } @@ -183,8 +218,8 @@ void HaierClimateBase::setup() { ESP_LOGI(TAG, "Haier initialization..."); // Set timestamp here to give AC time to boot this->last_request_timestamp_ = std::chrono::steady_clock::now(); - this->set_phase_(ProtocolPhases::SENDING_INIT_1); - this->set_answers_handlers(); + this->set_phase(ProtocolPhases::SENDING_INIT_1); + this->set_handlers(); this->haier_protocol_.set_default_timeout_handler( std::bind(&esphome::haier::HaierClimateBase::timeout_default_handler_, this, std::placeholders::_1)); } @@ -212,7 +247,7 @@ void HaierClimateBase::loop() { this->set_force_send_control_(false); if (this->hvac_settings_.valid) this->hvac_settings_.reset(); - this->set_phase_(ProtocolPhases::SENDING_INIT_1); + this->set_phase(ProtocolPhases::SENDING_INIT_1); return; } else { // No need to reset protocol if we didn't pass initialization phase @@ -229,7 +264,7 @@ void HaierClimateBase::loop() { this->process_pending_action(); } else if (this->hvac_settings_.valid || this->force_send_control_) { ESP_LOGV(TAG, "Control packet is pending..."); - this->set_phase_(ProtocolPhases::SENDING_CONTROL); + this->set_phase(ProtocolPhases::SENDING_CONTROL); } } this->process_phase(now); @@ -243,10 +278,10 @@ void HaierClimateBase::process_pending_action() { } switch (request) { case ActionRequest::TURN_POWER_ON: - this->set_phase_(ProtocolPhases::SENDING_POWER_ON_COMMAND); + this->set_phase(ProtocolPhases::SENDING_POWER_ON_COMMAND); break; case ActionRequest::TURN_POWER_OFF: - this->set_phase_(ProtocolPhases::SENDING_POWER_OFF_COMMAND); + this->set_phase(ProtocolPhases::SENDING_POWER_OFF_COMMAND); break; case ActionRequest::TOGGLE_POWER: case ActionRequest::NO_ACTION: @@ -303,7 +338,11 @@ void HaierClimateBase::set_force_send_control_(bool status) { } void HaierClimateBase::send_message_(const haier_protocol::HaierMessage &command, bool use_crc) { - this->haier_protocol_.send_message(command, use_crc); + if (this->answer_timeout_.has_value()) { + this->haier_protocol_.send_message(command, use_crc, this->answer_timeout_.value()); + } else { + this->haier_protocol_.send_message(command, use_crc); + } this->last_request_timestamp_ = std::chrono::steady_clock::now(); } diff --git a/esphome/components/haier/haier_base.h b/esphome/components/haier/haier_base.h index 046b59af96..b2446d6fb5 100644 --- a/esphome/components/haier/haier_base.h +++ b/esphome/components/haier/haier_base.h @@ -44,6 +44,7 @@ class HaierClimateBase : public esphome::Component, void reset_protocol() { this->reset_protocol_request_ = true; }; void set_supported_modes(const std::set &modes); void set_supported_swing_modes(const std::set &modes); + void set_supported_presets(const std::set &presets); size_t available() noexcept override { return esphome::uart::UARTDevice::available(); }; size_t read_array(uint8_t *data, size_t len) noexcept override { return esphome::uart::UARTDevice::read_array(data, len) ? len : 0; @@ -52,39 +53,41 @@ class HaierClimateBase : public esphome::Component, esphome::uart::UARTDevice::write_array(data, len); }; bool can_send_message() const { return haier_protocol_.get_outgoing_queue_size() == 0; }; + void set_answer_timeout(uint32_t timeout); + void set_send_wifi(bool send_wifi); protected: enum class ProtocolPhases { UNKNOWN = -1, // INITIALIZATION SENDING_INIT_1 = 0, - WAITING_ANSWER_INIT_1 = 1, + WAITING_INIT_1_ANSWER = 1, SENDING_INIT_2 = 2, - WAITING_ANSWER_INIT_2 = 3, + WAITING_INIT_2_ANSWER = 3, SENDING_FIRST_STATUS_REQUEST = 4, WAITING_FIRST_STATUS_ANSWER = 5, SENDING_ALARM_STATUS_REQUEST = 6, WAITING_ALARM_STATUS_ANSWER = 7, // FUNCTIONAL STATE IDLE = 8, - SENDING_STATUS_REQUEST = 9, - WAITING_STATUS_ANSWER = 10, - SENDING_UPDATE_SIGNAL_REQUEST = 11, - WAITING_UPDATE_SIGNAL_ANSWER = 12, - SENDING_SIGNAL_LEVEL = 13, - WAITING_SIGNAL_LEVEL_ANSWER = 14, - SENDING_CONTROL = 15, - WAITING_CONTROL_ANSWER = 16, - SENDING_POWER_ON_COMMAND = 17, - WAITING_POWER_ON_ANSWER = 18, - SENDING_POWER_OFF_COMMAND = 19, - WAITING_POWER_OFF_ANSWER = 20, + SENDING_STATUS_REQUEST = 10, + WAITING_STATUS_ANSWER = 11, + SENDING_UPDATE_SIGNAL_REQUEST = 12, + WAITING_UPDATE_SIGNAL_ANSWER = 13, + SENDING_SIGNAL_LEVEL = 14, + WAITING_SIGNAL_LEVEL_ANSWER = 15, + SENDING_CONTROL = 16, + WAITING_CONTROL_ANSWER = 17, + SENDING_POWER_ON_COMMAND = 18, + WAITING_POWER_ON_ANSWER = 19, + SENDING_POWER_OFF_COMMAND = 20, + WAITING_POWER_OFF_ANSWER = 21, NUM_PROTOCOL_PHASES }; #if (HAIER_LOG_LEVEL > 4) const char *phase_to_string_(ProtocolPhases phase); #endif - virtual void set_answers_handlers() = 0; + virtual void set_handlers() = 0; virtual void process_phase(std::chrono::steady_clock::time_point now) = 0; virtual haier_protocol::HaierMessage get_control_message() = 0; virtual bool is_message_invalid(uint8_t message_type) = 0; @@ -99,14 +102,17 @@ class HaierClimateBase : public esphome::Component, // Helper functions void set_force_send_control_(bool status); void send_message_(const haier_protocol::HaierMessage &command, bool use_crc); - void set_phase_(ProtocolPhases phase); + virtual void set_phase(ProtocolPhases phase); bool check_timeout_(std::chrono::steady_clock::time_point now, std::chrono::steady_clock::time_point tpoint, size_t timeout); bool is_message_interval_exceeded_(std::chrono::steady_clock::time_point now); bool is_status_request_interval_exceeded_(std::chrono::steady_clock::time_point now); bool is_control_message_timeout_exceeded_(std::chrono::steady_clock::time_point now); bool is_control_message_interval_exceeded_(std::chrono::steady_clock::time_point now); - bool is_protocol_initialisation_interval_exceded_(std::chrono::steady_clock::time_point now); + bool is_protocol_initialisation_interval_exceeded_(std::chrono::steady_clock::time_point now); +#ifdef USE_WIFI + haier_protocol::HaierMessage get_wifi_signal_message_(uint8_t message_type); +#endif struct HvacSettings { esphome::optional mode; @@ -136,6 +142,9 @@ class HaierClimateBase : public esphome::Component, std::chrono::steady_clock::time_point last_valid_status_timestamp_; // For protocol timeout std::chrono::steady_clock::time_point last_status_request_; // To request AC status std::chrono::steady_clock::time_point control_request_timestamp_; // To send control message + optional answer_timeout_; // Message answer timeout + bool send_wifi_signal_; + std::chrono::steady_clock::time_point last_signal_request_; // To send WiFI signal level }; } // namespace haier diff --git a/esphome/components/haier/hon_climate.cpp b/esphome/components/haier/hon_climate.cpp index 3950b34724..feb1e019d8 100644 --- a/esphome/components/haier/hon_climate.cpp +++ b/esphome/components/haier/hon_climate.cpp @@ -2,9 +2,6 @@ #include #include "esphome/components/climate/climate.h" #include "esphome/components/uart/uart.h" -#ifdef USE_WIFI -#include "esphome/components/wifi/wifi_component.h" -#endif #include "hon_climate.h" #include "hon_packet.h" @@ -58,14 +55,7 @@ HonClimate::HonClimate() hvac_functions_{false, false, false, false, false}, use_crc_(hvac_functions_[2]), active_alarms_{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - outdoor_sensor_(nullptr), - send_wifi_signal_(true) { - this->traits_.set_supported_presets({ - climate::CLIMATE_PRESET_NONE, - climate::CLIMATE_PRESET_ECO, - climate::CLIMATE_PRESET_BOOST, - climate::CLIMATE_PRESET_SLEEP, - }); + outdoor_sensor_(nullptr) { this->fan_mode_speed_ = (uint8_t) hon_protocol::FanMode::FAN_MID; this->other_modes_fan_speed_ = (uint8_t) hon_protocol::FanMode::FAN_AUTO; } @@ -121,17 +111,22 @@ void HonClimate::start_steri_cleaning() { } } -void HonClimate::set_send_wifi(bool send_wifi) { this->send_wifi_signal_ = send_wifi; } - haier_protocol::HandlerError HonClimate::get_device_version_answer_handler_(uint8_t request_type, uint8_t message_type, const uint8_t *data, size_t data_size) { + // Should check this before preprocess + if (message_type == (uint8_t) hon_protocol::FrameType::INVALID) { + ESP_LOGW(TAG, "It looks like your ESPHome Haier climate configuration is wrong. You should use the smartAir2 " + "protocol instead of hOn"); + this->set_phase(ProtocolPhases::SENDING_INIT_1); + return haier_protocol::HandlerError::INVALID_ANSWER; + } haier_protocol::HandlerError result = this->answer_preprocess_( request_type, (uint8_t) hon_protocol::FrameType::GET_DEVICE_VERSION, message_type, - (uint8_t) hon_protocol::FrameType::GET_DEVICE_VERSION_RESPONSE, ProtocolPhases::WAITING_ANSWER_INIT_1); + (uint8_t) hon_protocol::FrameType::GET_DEVICE_VERSION_RESPONSE, ProtocolPhases::WAITING_INIT_1_ANSWER); if (result == haier_protocol::HandlerError::HANDLER_OK) { if (data_size < sizeof(hon_protocol::DeviceVersionAnswer)) { // Wrong structure - this->set_phase_(ProtocolPhases::SENDING_INIT_1); + this->set_phase(ProtocolPhases::SENDING_INIT_1); return haier_protocol::HandlerError::WRONG_MESSAGE_STRUCTURE; } // All OK @@ -152,11 +147,11 @@ haier_protocol::HandlerError HonClimate::get_device_version_answer_handler_(uint this->hvac_functions_[3] = (answr->functions[1] & 0x08) != 0; // multiple AC support this->hvac_functions_[4] = (answr->functions[1] & 0x20) != 0; // roles support this->hvac_hardware_info_available_ = true; - this->set_phase_(ProtocolPhases::SENDING_INIT_2); + this->set_phase(ProtocolPhases::SENDING_INIT_2); return result; } else { - this->set_phase_((this->protocol_phase_ >= ProtocolPhases::IDLE) ? ProtocolPhases::IDLE - : ProtocolPhases::SENDING_INIT_1); + this->set_phase((this->protocol_phase_ >= ProtocolPhases::IDLE) ? ProtocolPhases::IDLE + : ProtocolPhases::SENDING_INIT_1); return result; } } @@ -165,13 +160,13 @@ haier_protocol::HandlerError HonClimate::get_device_id_answer_handler_(uint8_t r const uint8_t *data, size_t data_size) { haier_protocol::HandlerError result = this->answer_preprocess_( request_type, (uint8_t) hon_protocol::FrameType::GET_DEVICE_ID, message_type, - (uint8_t) hon_protocol::FrameType::GET_DEVICE_ID_RESPONSE, ProtocolPhases::WAITING_ANSWER_INIT_2); + (uint8_t) hon_protocol::FrameType::GET_DEVICE_ID_RESPONSE, ProtocolPhases::WAITING_INIT_2_ANSWER); if (result == haier_protocol::HandlerError::HANDLER_OK) { - this->set_phase_(ProtocolPhases::SENDING_FIRST_STATUS_REQUEST); + this->set_phase(ProtocolPhases::SENDING_FIRST_STATUS_REQUEST); return result; } else { - this->set_phase_((this->protocol_phase_ >= ProtocolPhases::IDLE) ? ProtocolPhases::IDLE - : ProtocolPhases::SENDING_INIT_1); + this->set_phase((this->protocol_phase_ >= ProtocolPhases::IDLE) ? ProtocolPhases::IDLE + : ProtocolPhases::SENDING_INIT_1); return result; } } @@ -185,8 +180,8 @@ haier_protocol::HandlerError HonClimate::status_handler_(uint8_t request_type, u result = this->process_status_message_(data, data_size); if (result != haier_protocol::HandlerError::HANDLER_OK) { ESP_LOGW(TAG, "Error %d while parsing Status packet", (int) result); - this->set_phase_((this->protocol_phase_ >= ProtocolPhases::IDLE) ? ProtocolPhases::IDLE - : ProtocolPhases::SENDING_INIT_1); + this->set_phase((this->protocol_phase_ >= ProtocolPhases::IDLE) ? ProtocolPhases::IDLE + : ProtocolPhases::SENDING_INIT_1); } else { if (data_size >= sizeof(hon_protocol::HaierPacketControl) + 2) { memcpy(this->last_status_message_.get(), data + 2, sizeof(hon_protocol::HaierPacketControl)); @@ -196,13 +191,13 @@ haier_protocol::HandlerError HonClimate::status_handler_(uint8_t request_type, u } if (this->protocol_phase_ == ProtocolPhases::WAITING_FIRST_STATUS_ANSWER) { ESP_LOGI(TAG, "First HVAC status received"); - this->set_phase_(ProtocolPhases::SENDING_ALARM_STATUS_REQUEST); + this->set_phase(ProtocolPhases::SENDING_ALARM_STATUS_REQUEST); } else if ((this->protocol_phase_ == ProtocolPhases::WAITING_STATUS_ANSWER) || (this->protocol_phase_ == ProtocolPhases::WAITING_POWER_ON_ANSWER) || (this->protocol_phase_ == ProtocolPhases::WAITING_POWER_OFF_ANSWER)) { - this->set_phase_(ProtocolPhases::IDLE); + this->set_phase(ProtocolPhases::IDLE); } else if (this->protocol_phase_ == ProtocolPhases::WAITING_CONTROL_ANSWER) { - this->set_phase_(ProtocolPhases::IDLE); + this->set_phase(ProtocolPhases::IDLE); this->set_force_send_control_(false); if (this->hvac_settings_.valid) this->hvac_settings_.reset(); @@ -210,8 +205,8 @@ haier_protocol::HandlerError HonClimate::status_handler_(uint8_t request_type, u } return result; } else { - this->set_phase_((this->protocol_phase_ >= ProtocolPhases::IDLE) ? ProtocolPhases::IDLE - : ProtocolPhases::SENDING_INIT_1); + this->set_phase((this->protocol_phase_ >= ProtocolPhases::IDLE) ? ProtocolPhases::IDLE + : ProtocolPhases::SENDING_INIT_1); return result; } } @@ -225,10 +220,10 @@ haier_protocol::HandlerError HonClimate::get_management_information_answer_handl message_type, (uint8_t) hon_protocol::FrameType::GET_MANAGEMENT_INFORMATION_RESPONSE, ProtocolPhases::WAITING_UPDATE_SIGNAL_ANSWER); if (result == haier_protocol::HandlerError::HANDLER_OK) { - this->set_phase_(ProtocolPhases::SENDING_SIGNAL_LEVEL); + this->set_phase(ProtocolPhases::SENDING_SIGNAL_LEVEL); return result; } else { - this->set_phase_(ProtocolPhases::IDLE); + this->set_phase(ProtocolPhases::IDLE); return result; } } @@ -239,7 +234,7 @@ haier_protocol::HandlerError HonClimate::report_network_status_answer_handler_(u haier_protocol::HandlerError result = this->answer_preprocess_(request_type, (uint8_t) hon_protocol::FrameType::REPORT_NETWORK_STATUS, message_type, (uint8_t) hon_protocol::FrameType::CONFIRM, ProtocolPhases::WAITING_SIGNAL_LEVEL_ANSWER); - this->set_phase_(ProtocolPhases::IDLE); + this->set_phase(ProtocolPhases::IDLE); return result; } @@ -248,24 +243,24 @@ haier_protocol::HandlerError HonClimate::get_alarm_status_answer_handler_(uint8_ if (request_type == (uint8_t) hon_protocol::FrameType::GET_ALARM_STATUS) { if (message_type != (uint8_t) hon_protocol::FrameType::GET_ALARM_STATUS_RESPONSE) { // Unexpected answer to request - this->set_phase_(ProtocolPhases::IDLE); - return haier_protocol::HandlerError::UNSUPORTED_MESSAGE; + this->set_phase(ProtocolPhases::IDLE); + return haier_protocol::HandlerError::UNSUPPORTED_MESSAGE; } if (this->protocol_phase_ != ProtocolPhases::WAITING_ALARM_STATUS_ANSWER) { // Don't expect this answer now - this->set_phase_(ProtocolPhases::IDLE); + this->set_phase(ProtocolPhases::IDLE); return haier_protocol::HandlerError::UNEXPECTED_MESSAGE; } memcpy(this->active_alarms_, data + 2, 8); - this->set_phase_(ProtocolPhases::IDLE); + this->set_phase(ProtocolPhases::IDLE); return haier_protocol::HandlerError::HANDLER_OK; } else { - this->set_phase_(ProtocolPhases::IDLE); - return haier_protocol::HandlerError::UNSUPORTED_MESSAGE; + this->set_phase(ProtocolPhases::IDLE); + return haier_protocol::HandlerError::UNSUPPORTED_MESSAGE; } } -void HonClimate::set_answers_handlers() { +void HonClimate::set_handlers() { // Set handlers this->haier_protocol_.set_answer_handler( (uint8_t) (hon_protocol::FrameType::GET_DEVICE_VERSION), @@ -311,7 +306,7 @@ void HonClimate::dump_config() { void HonClimate::process_phase(std::chrono::steady_clock::time_point now) { switch (this->protocol_phase_) { case ProtocolPhases::SENDING_INIT_1: - if (this->can_send_message() && this->is_protocol_initialisation_interval_exceded_(now)) { + if (this->can_send_message() && this->is_protocol_initialisation_interval_exceeded_(now)) { this->hvac_hardware_info_available_ = false; // Indicate device capabilities: // bit 0 - if 1 module support interactive mode @@ -323,24 +318,24 @@ void HonClimate::process_phase(std::chrono::steady_clock::time_point now) { static const haier_protocol::HaierMessage DEVICE_VERSION_REQUEST( (uint8_t) hon_protocol::FrameType::GET_DEVICE_VERSION, module_capabilities, sizeof(module_capabilities)); this->send_message_(DEVICE_VERSION_REQUEST, this->use_crc_); - this->set_phase_(ProtocolPhases::WAITING_ANSWER_INIT_1); + this->set_phase(ProtocolPhases::WAITING_INIT_1_ANSWER); } break; case ProtocolPhases::SENDING_INIT_2: if (this->can_send_message() && this->is_message_interval_exceeded_(now)) { static const haier_protocol::HaierMessage DEVICEID_REQUEST((uint8_t) hon_protocol::FrameType::GET_DEVICE_ID); this->send_message_(DEVICEID_REQUEST, this->use_crc_); - this->set_phase_(ProtocolPhases::WAITING_ANSWER_INIT_2); + this->set_phase(ProtocolPhases::WAITING_INIT_2_ANSWER); } break; case ProtocolPhases::SENDING_FIRST_STATUS_REQUEST: case ProtocolPhases::SENDING_STATUS_REQUEST: if (this->can_send_message() && this->is_message_interval_exceeded_(now)) { static const haier_protocol::HaierMessage STATUS_REQUEST( - (uint8_t) hon_protocol::FrameType::CONTROL, (uint16_t) hon_protocol::SubcomandsControl::GET_USER_DATA); + (uint8_t) hon_protocol::FrameType::CONTROL, (uint16_t) hon_protocol::SubcommandsControl::GET_USER_DATA); this->send_message_(STATUS_REQUEST, this->use_crc_); this->last_status_request_ = now; - this->set_phase_((ProtocolPhases) ((uint8_t) this->protocol_phase_ + 1)); + this->set_phase((ProtocolPhases) ((uint8_t) this->protocol_phase_ + 1)); } break; #ifdef USE_WIFI @@ -350,26 +345,14 @@ void HonClimate::process_phase(std::chrono::steady_clock::time_point now) { (uint8_t) hon_protocol::FrameType::GET_MANAGEMENT_INFORMATION); this->send_message_(UPDATE_SIGNAL_REQUEST, this->use_crc_); this->last_signal_request_ = now; - this->set_phase_(ProtocolPhases::WAITING_UPDATE_SIGNAL_ANSWER); + this->set_phase(ProtocolPhases::WAITING_UPDATE_SIGNAL_ANSWER); } break; case ProtocolPhases::SENDING_SIGNAL_LEVEL: if (this->can_send_message() && this->is_message_interval_exceeded_(now)) { - static uint8_t wifi_status_data[4] = {0x00, 0x00, 0x00, 0x00}; - if (wifi::global_wifi_component->is_connected()) { - wifi_status_data[1] = 0; - int8_t rssi = wifi::global_wifi_component->wifi_rssi(); - wifi_status_data[3] = uint8_t((128 + rssi) / 1.28f); - ESP_LOGD(TAG, "WiFi signal is: %ddBm => %d%%", rssi, wifi_status_data[3]); - } else { - ESP_LOGD(TAG, "WiFi is not connected"); - wifi_status_data[1] = 1; - wifi_status_data[3] = 0; - } - haier_protocol::HaierMessage wifi_status_request((uint8_t) hon_protocol::FrameType::REPORT_NETWORK_STATUS, - wifi_status_data, sizeof(wifi_status_data)); - this->send_message_(wifi_status_request, this->use_crc_); - this->set_phase_(ProtocolPhases::WAITING_SIGNAL_LEVEL_ANSWER); + this->send_message_(this->get_wifi_signal_message_((uint8_t) hon_protocol::FrameType::REPORT_NETWORK_STATUS), + this->use_crc_); + this->set_phase(ProtocolPhases::WAITING_SIGNAL_LEVEL_ANSWER); } break; case ProtocolPhases::WAITING_UPDATE_SIGNAL_ANSWER: @@ -380,7 +363,7 @@ void HonClimate::process_phase(std::chrono::steady_clock::time_point now) { case ProtocolPhases::SENDING_SIGNAL_LEVEL: case ProtocolPhases::WAITING_UPDATE_SIGNAL_ANSWER: case ProtocolPhases::WAITING_SIGNAL_LEVEL_ANSWER: - this->set_phase_(ProtocolPhases::IDLE); + this->set_phase(ProtocolPhases::IDLE); break; #endif case ProtocolPhases::SENDING_ALARM_STATUS_REQUEST: @@ -388,7 +371,7 @@ void HonClimate::process_phase(std::chrono::steady_clock::time_point now) { static const haier_protocol::HaierMessage ALARM_STATUS_REQUEST( (uint8_t) hon_protocol::FrameType::GET_ALARM_STATUS); this->send_message_(ALARM_STATUS_REQUEST, this->use_crc_); - this->set_phase_(ProtocolPhases::WAITING_ALARM_STATUS_ANSWER); + this->set_phase(ProtocolPhases::WAITING_ALARM_STATUS_ANSWER); } break; case ProtocolPhases::SENDING_CONTROL: @@ -403,12 +386,12 @@ void HonClimate::process_phase(std::chrono::steady_clock::time_point now) { this->hvac_settings_.reset(); this->forced_request_status_ = true; this->forced_publish_ = true; - this->set_phase_(ProtocolPhases::IDLE); + this->set_phase(ProtocolPhases::IDLE); } else if (this->can_send_message() && this->is_control_message_interval_exceeded_(now)) { haier_protocol::HaierMessage control_message = get_control_message(); this->send_message_(control_message, this->use_crc_); ESP_LOGI(TAG, "Control packet sent"); - this->set_phase_(ProtocolPhases::WAITING_CONTROL_ANSWER); + this->set_phase(ProtocolPhases::WAITING_CONTROL_ANSWER); } break; case ProtocolPhases::SENDING_POWER_ON_COMMAND: @@ -418,17 +401,17 @@ void HonClimate::process_phase(std::chrono::steady_clock::time_point now) { if (this->protocol_phase_ == ProtocolPhases::SENDING_POWER_ON_COMMAND) pwr_cmd_buf[1] = 0x01; haier_protocol::HaierMessage power_cmd((uint8_t) hon_protocol::FrameType::CONTROL, - ((uint16_t) hon_protocol::SubcomandsControl::SET_SINGLE_PARAMETER) + 1, + ((uint16_t) hon_protocol::SubcommandsControl::SET_SINGLE_PARAMETER) + 1, pwr_cmd_buf, sizeof(pwr_cmd_buf)); this->send_message_(power_cmd, this->use_crc_); - this->set_phase_(this->protocol_phase_ == ProtocolPhases::SENDING_POWER_ON_COMMAND - ? ProtocolPhases::WAITING_POWER_ON_ANSWER - : ProtocolPhases::WAITING_POWER_OFF_ANSWER); + this->set_phase(this->protocol_phase_ == ProtocolPhases::SENDING_POWER_ON_COMMAND + ? ProtocolPhases::WAITING_POWER_ON_ANSWER + : ProtocolPhases::WAITING_POWER_OFF_ANSWER); } break; - case ProtocolPhases::WAITING_ANSWER_INIT_1: - case ProtocolPhases::WAITING_ANSWER_INIT_2: + case ProtocolPhases::WAITING_INIT_1_ANSWER: + case ProtocolPhases::WAITING_INIT_2_ANSWER: case ProtocolPhases::WAITING_FIRST_STATUS_ANSWER: case ProtocolPhases::WAITING_ALARM_STATUS_ANSWER: case ProtocolPhases::WAITING_STATUS_ANSWER: @@ -438,14 +421,14 @@ void HonClimate::process_phase(std::chrono::steady_clock::time_point now) { break; case ProtocolPhases::IDLE: { if (this->forced_request_status_ || this->is_status_request_interval_exceeded_(now)) { - this->set_phase_(ProtocolPhases::SENDING_STATUS_REQUEST); + this->set_phase(ProtocolPhases::SENDING_STATUS_REQUEST); this->forced_request_status_ = false; } #ifdef USE_WIFI else if (this->send_wifi_signal_ && (std::chrono::duration_cast(now - this->last_signal_request_).count() > SIGNAL_LEVEL_UPDATE_INTERVAL_MS)) - this->set_phase_(ProtocolPhases::SENDING_UPDATE_SIGNAL_REQUEST); + this->set_phase(ProtocolPhases::SENDING_UPDATE_SIGNAL_REQUEST); #endif } break; default: @@ -456,7 +439,7 @@ void HonClimate::process_phase(std::chrono::steady_clock::time_point now) { #else ESP_LOGE(TAG, "Wrong protocol handler state: %d, resetting communication", (int) this->protocol_phase_); #endif - this->set_phase_(ProtocolPhases::SENDING_INIT_1); + this->set_phase(ProtocolPhases::SENDING_INIT_1); break; } } @@ -551,11 +534,12 @@ haier_protocol::HaierMessage HonClimate::get_control_message() { } } if (climate_control.target_temperature.has_value()) { - out_data->set_point = - climate_control.target_temperature.value() - 16; // set the temperature at our offset, subtract 16. + float target_temp = climate_control.target_temperature.value(); + out_data->set_point = ((int) target_temp) - 16; // set the temperature at our offset, subtract 16. + out_data->half_degree = (target_temp - ((int) target_temp) >= 0.49) ? 1 : 0; } if (out_data->ac_power == 0) { - // If AC is off - no presets alowed + // If AC is off - no presets allowed out_data->quiet_mode = 0; out_data->fast_mode = 0; out_data->sleep_mode = 0; @@ -631,7 +615,7 @@ haier_protocol::HaierMessage HonClimate::get_control_message() { break; } return haier_protocol::HaierMessage((uint8_t) hon_protocol::FrameType::CONTROL, - (uint16_t) hon_protocol::SubcomandsControl::SET_GROUP_PARAMETERS, + (uint16_t) hon_protocol::SubcommandsControl::SET_GROUP_PARAMETERS, control_out_buffer, sizeof(hon_protocol::HaierPacketControl)); } @@ -669,7 +653,7 @@ haier_protocol::HandlerError HonClimate::process_status_message_(const uint8_t * { // Target temperature float old_target_temperature = this->target_temperature; - this->target_temperature = packet.control.set_point + 16.0f; + this->target_temperature = packet.control.set_point + 16.0f + ((packet.control.half_degree == 1) ? 0.5f : 0.0f); should_publish = should_publish || (old_target_temperature != this->target_temperature); } { @@ -747,7 +731,7 @@ haier_protocol::HandlerError HonClimate::process_status_message_(const uint8_t * if (new_cleaning != this->cleaning_status_) { ESP_LOGD(TAG, "Cleaning status change: %d => %d", (uint8_t) this->cleaning_status_, (uint8_t) new_cleaning); if (new_cleaning == CleaningState::NO_CLEANING) { - // Turnuin AC off after cleaning + // Turning AC off after cleaning this->action_request_ = ActionRequest::TURN_POWER_OFF; } this->cleaning_status_ = new_cleaning; @@ -837,7 +821,7 @@ void HonClimate::process_pending_action() { case ActionRequest::START_SELF_CLEAN: case ActionRequest::START_STERI_CLEAN: // Will reset action with control message sending - this->set_phase_(ProtocolPhases::SENDING_CONTROL); + this->set_phase(ProtocolPhases::SENDING_CONTROL); break; default: HaierClimateBase::process_pending_action(); diff --git a/esphome/components/haier/hon_climate.h b/esphome/components/haier/hon_climate.h index ab913f44e2..cf566e3b8e 100644 --- a/esphome/components/haier/hon_climate.h +++ b/esphome/components/haier/hon_climate.h @@ -48,10 +48,9 @@ class HonClimate : public HaierClimateBase { CleaningState get_cleaning_status() const; void start_self_cleaning(); void start_steri_cleaning(); - void set_send_wifi(bool send_wifi); protected: - void set_answers_handlers() override; + void set_handlers() override; void process_phase(std::chrono::steady_clock::time_point now) override; haier_protocol::HaierMessage get_control_message() override; bool is_message_invalid(uint8_t message_type) override; @@ -87,8 +86,6 @@ class HonClimate : public HaierClimateBase { bool &use_crc_; uint8_t active_alarms_[8]; esphome::sensor::Sensor *outdoor_sensor_; - bool send_wifi_signal_; - std::chrono::steady_clock::time_point last_signal_request_; // To send WiFI signal level }; } // namespace haier diff --git a/esphome/components/haier/hon_packet.h b/esphome/components/haier/hon_packet.h index d572ce80d9..c6b32df200 100644 --- a/esphome/components/haier/hon_packet.h +++ b/esphome/components/haier/hon_packet.h @@ -53,12 +53,12 @@ struct HaierPacketControl { // 13 uint8_t : 8; // 14 - uint8_t ten_degree : 1; // 10 degree status - uint8_t display_status : 1; // If 0 disables AC's display - uint8_t half_degree : 1; // Use half degree - uint8_t intelegence_status : 1; // Intelligence status - uint8_t pmv_status : 1; // Comfort/PMV status - uint8_t use_fahrenheit : 1; // Use Fahrenheit instead of Celsius + uint8_t ten_degree : 1; // 10 degree status + uint8_t display_status : 1; // If 0 disables AC's display + uint8_t half_degree : 1; // Use half degree + uint8_t intelligence_status : 1; // Intelligence status + uint8_t pmv_status : 1; // Comfort/PMV status + uint8_t use_fahrenheit : 1; // Use Fahrenheit instead of Celsius uint8_t : 1; uint8_t steri_clean : 1; // 15 @@ -153,7 +153,7 @@ enum class FrameType : uint8_t { // <-> device, required) REPORT = 0x06, // Report frame (module <-> device, interactive, required) STOP_FAULT_ALARM = 0x09, // Stop fault alarm frame (module -> device, interactive, required) - SYSTEM_DOWNLIK = 0x11, // System downlink frame (module -> device, optional) + SYSTEM_DOWNLINK = 0x11, // System downlink frame (module -> device, optional) DEVICE_UPLINK = 0x12, // Device uplink frame (module <- device , interactive, optional) SYSTEM_QUERY = 0x13, // System query frame (module -> device, optional) SYSTEM_QUERY_RESPONSE = 0x14, // System query response frame (module <- device , optional) @@ -210,7 +210,7 @@ enum class FrameType : uint8_t { WAKE_UP = 0xFE, // Request to wake up (module <-> device, optional) }; -enum class SubcomandsControl : uint16_t { +enum class SubcommandsControl : uint16_t { GET_PARAMETERS = 0x4C01, // Request specific parameters (packet content: parameter ID1 + parameter ID2 + ...) GET_USER_DATA = 0x4D01, // Request all user data from device (packet content: None) GET_BIG_DATA = 0x4DFE, // Request big data information from device (packet content: None) diff --git a/esphome/components/haier/smartair2_climate.cpp b/esphome/components/haier/smartair2_climate.cpp index 9c0fbac350..91b6bb0545 100644 --- a/esphome/components/haier/smartair2_climate.cpp +++ b/esphome/components/haier/smartair2_climate.cpp @@ -11,15 +11,10 @@ namespace esphome { namespace haier { static const char *const TAG = "haier.climate"; +constexpr size_t SIGNAL_LEVEL_UPDATE_INTERVAL_MS = 10000; Smartair2Climate::Smartair2Climate() - : last_status_message_(new uint8_t[sizeof(smartair2_protocol::HaierPacketControl)]) { - this->traits_.set_supported_presets({ - climate::CLIMATE_PRESET_NONE, - climate::CLIMATE_PRESET_BOOST, - climate::CLIMATE_PRESET_COMFORT, - }); -} + : last_status_message_(new uint8_t[sizeof(smartair2_protocol::HaierPacketControl)]), timeouts_counter_(0) {} haier_protocol::HandlerError Smartair2Climate::status_handler_(uint8_t request_type, uint8_t message_type, const uint8_t *data, size_t data_size) { @@ -30,8 +25,8 @@ haier_protocol::HandlerError Smartair2Climate::status_handler_(uint8_t request_t result = this->process_status_message_(data, data_size); if (result != haier_protocol::HandlerError::HANDLER_OK) { ESP_LOGW(TAG, "Error %d while parsing Status packet", (int) result); - this->set_phase_((this->protocol_phase_ >= ProtocolPhases::IDLE) ? ProtocolPhases::IDLE - : ProtocolPhases::SENDING_FIRST_STATUS_REQUEST); + this->set_phase((this->protocol_phase_ >= ProtocolPhases::IDLE) ? ProtocolPhases::IDLE + : ProtocolPhases::SENDING_FIRST_STATUS_REQUEST); } else { if (data_size >= sizeof(smartair2_protocol::HaierPacketControl) + 2) { memcpy(this->last_status_message_.get(), data + 2, sizeof(smartair2_protocol::HaierPacketControl)); @@ -41,11 +36,11 @@ haier_protocol::HandlerError Smartair2Climate::status_handler_(uint8_t request_t } if (this->protocol_phase_ == ProtocolPhases::WAITING_FIRST_STATUS_ANSWER) { ESP_LOGI(TAG, "First HVAC status received"); - this->set_phase_(ProtocolPhases::IDLE); + this->set_phase(ProtocolPhases::IDLE); } else if (this->protocol_phase_ == ProtocolPhases::WAITING_STATUS_ANSWER) { - this->set_phase_(ProtocolPhases::IDLE); + this->set_phase(ProtocolPhases::IDLE); } else if (this->protocol_phase_ == ProtocolPhases::WAITING_CONTROL_ANSWER) { - this->set_phase_(ProtocolPhases::IDLE); + this->set_phase(ProtocolPhases::IDLE); this->set_force_send_control_(false); if (this->hvac_settings_.valid) this->hvac_settings_.reset(); @@ -53,17 +48,82 @@ haier_protocol::HandlerError Smartair2Climate::status_handler_(uint8_t request_t } return result; } else { - this->set_phase_((this->protocol_phase_ >= ProtocolPhases::IDLE) ? ProtocolPhases::IDLE - : ProtocolPhases::SENDING_FIRST_STATUS_REQUEST); + this->set_phase((this->protocol_phase_ >= ProtocolPhases::IDLE) ? ProtocolPhases::IDLE + : ProtocolPhases::SENDING_FIRST_STATUS_REQUEST); return result; } } -void Smartair2Climate::set_answers_handlers() { +haier_protocol::HandlerError Smartair2Climate::get_device_version_answer_handler_(uint8_t request_type, + uint8_t message_type, + const uint8_t *data, + size_t data_size) { + if (request_type != (uint8_t) smartair2_protocol::FrameType::GET_DEVICE_VERSION) + return haier_protocol::HandlerError::UNSUPPORTED_MESSAGE; + if (ProtocolPhases::WAITING_INIT_1_ANSWER != this->protocol_phase_) + return haier_protocol::HandlerError::UNEXPECTED_MESSAGE; + // Invalid packet is expected answer + if ((message_type == (uint8_t) smartair2_protocol::FrameType::GET_DEVICE_VERSION_RESPONSE) && (data_size >= 39) && + ((data[37] & 0x04) != 0)) { + ESP_LOGW(TAG, "It looks like your ESPHome Haier climate configuration is wrong. You should use the hOn protocol " + "instead of smartAir2"); + } + this->set_phase(ProtocolPhases::SENDING_INIT_2); + return haier_protocol::HandlerError::HANDLER_OK; +} + +haier_protocol::HandlerError Smartair2Climate::report_network_status_answer_handler_(uint8_t request_type, + uint8_t message_type, + const uint8_t *data, + size_t data_size) { + haier_protocol::HandlerError result = this->answer_preprocess_( + request_type, (uint8_t) smartair2_protocol::FrameType::REPORT_NETWORK_STATUS, message_type, + (uint8_t) smartair2_protocol::FrameType::CONFIRM, ProtocolPhases::WAITING_SIGNAL_LEVEL_ANSWER); + this->set_phase(ProtocolPhases::IDLE); + return result; +} + +haier_protocol::HandlerError Smartair2Climate::initial_messages_timeout_handler_(uint8_t message_type) { + if (this->protocol_phase_ >= ProtocolPhases::IDLE) + return HaierClimateBase::timeout_default_handler_(message_type); + this->timeouts_counter_++; + ESP_LOGI(TAG, "Answer timeout for command %02X, phase %d, timeout counter %d", message_type, + (int) this->protocol_phase_, this->timeouts_counter_); + if (this->timeouts_counter_ >= 3) { + ProtocolPhases new_phase = (ProtocolPhases) ((int) this->protocol_phase_ + 1); + if (new_phase >= ProtocolPhases::SENDING_ALARM_STATUS_REQUEST) + new_phase = ProtocolPhases::SENDING_INIT_1; + this->set_phase(new_phase); + } else { + // Returning to the previous state to try again + this->set_phase((ProtocolPhases) ((int) this->protocol_phase_ - 1)); + } + return haier_protocol::HandlerError::HANDLER_OK; +} + +void Smartair2Climate::set_handlers() { + // Set handlers + this->haier_protocol_.set_answer_handler( + (uint8_t) (smartair2_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_.set_answer_handler( (uint8_t) (smartair2_protocol::FrameType::CONTROL), std::bind(&Smartair2Climate::status_handler_, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)); + this->haier_protocol_.set_answer_handler( + (uint8_t) (smartair2_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_.set_timeout_handler( + (uint8_t) (smartair2_protocol::FrameType::GET_DEVICE_ID), + std::bind(&Smartair2Climate::initial_messages_timeout_handler_, this, std::placeholders::_1)); + this->haier_protocol_.set_timeout_handler( + (uint8_t) (smartair2_protocol::FrameType::GET_DEVICE_VERSION), + std::bind(&Smartair2Climate::initial_messages_timeout_handler_, this, std::placeholders::_1)); + this->haier_protocol_.set_timeout_handler( + (uint8_t) (smartair2_protocol::FrameType::CONTROL), + std::bind(&Smartair2Climate::initial_messages_timeout_handler_, this, std::placeholders::_1)); } void Smartair2Climate::dump_config() { @@ -74,39 +134,60 @@ void Smartair2Climate::dump_config() { void Smartair2Climate::process_phase(std::chrono::steady_clock::time_point now) { switch (this->protocol_phase_) { case ProtocolPhases::SENDING_INIT_1: - this->set_phase_(ProtocolPhases::SENDING_FIRST_STATUS_REQUEST); - break; - case ProtocolPhases::WAITING_ANSWER_INIT_1: - case ProtocolPhases::SENDING_INIT_2: - case ProtocolPhases::WAITING_ANSWER_INIT_2: - case ProtocolPhases::SENDING_ALARM_STATUS_REQUEST: - case ProtocolPhases::WAITING_ALARM_STATUS_ANSWER: - this->set_phase_(ProtocolPhases::SENDING_INIT_1); - break; - case ProtocolPhases::SENDING_UPDATE_SIGNAL_REQUEST: - case ProtocolPhases::WAITING_UPDATE_SIGNAL_ANSWER: - case ProtocolPhases::SENDING_SIGNAL_LEVEL: - case ProtocolPhases::WAITING_SIGNAL_LEVEL_ANSWER: - this->set_phase_(ProtocolPhases::IDLE); - break; - case ProtocolPhases::SENDING_FIRST_STATUS_REQUEST: - if (this->can_send_message() && this->is_protocol_initialisation_interval_exceded_(now)) { - static const haier_protocol::HaierMessage STATUS_REQUEST((uint8_t) smartair2_protocol::FrameType::CONTROL, - 0x4D01); - this->send_message_(STATUS_REQUEST, false); - this->last_status_request_ = now; - this->set_phase_(ProtocolPhases::WAITING_FIRST_STATUS_ANSWER); + if (this->can_send_message() && + (((this->timeouts_counter_ == 0) && (this->is_protocol_initialisation_interval_exceeded_(now))) || + ((this->timeouts_counter_ > 0) && (this->is_message_interval_exceeded_(now))))) { + // Indicate device capabilities: + // bit 0 - if 1 module support interactive mode + // bit 1 - if 1 module support controller-device mode + // bit 2 - if 1 module support crc + // bit 3 - if 1 module support multiple devices + // bit 4..bit 15 - not used + uint8_t module_capabilities[2] = {0b00000000, 0b00000111}; + static const haier_protocol::HaierMessage DEVICE_VERSION_REQUEST( + (uint8_t) smartair2_protocol::FrameType::GET_DEVICE_VERSION, module_capabilities, + sizeof(module_capabilities)); + this->send_message_(DEVICE_VERSION_REQUEST, false); + this->set_phase(ProtocolPhases::WAITING_INIT_1_ANSWER); } break; + case ProtocolPhases::SENDING_INIT_2: + case ProtocolPhases::WAITING_INIT_2_ANSWER: + this->set_phase(ProtocolPhases::SENDING_FIRST_STATUS_REQUEST); + break; + case ProtocolPhases::SENDING_FIRST_STATUS_REQUEST: case ProtocolPhases::SENDING_STATUS_REQUEST: if (this->can_send_message() && this->is_message_interval_exceeded_(now)) { static const haier_protocol::HaierMessage STATUS_REQUEST((uint8_t) smartair2_protocol::FrameType::CONTROL, 0x4D01); this->send_message_(STATUS_REQUEST, false); this->last_status_request_ = now; - this->set_phase_(ProtocolPhases::WAITING_STATUS_ANSWER); + this->set_phase((ProtocolPhases) ((uint8_t) this->protocol_phase_ + 1)); } break; +#ifdef USE_WIFI + case ProtocolPhases::SENDING_SIGNAL_LEVEL: + if (this->can_send_message() && this->is_message_interval_exceeded_(now)) { + this->send_message_( + this->get_wifi_signal_message_((uint8_t) smartair2_protocol::FrameType::REPORT_NETWORK_STATUS), false); + this->last_signal_request_ = now; + this->set_phase(ProtocolPhases::WAITING_SIGNAL_LEVEL_ANSWER); + } + break; + case ProtocolPhases::WAITING_SIGNAL_LEVEL_ANSWER: + break; +#else + case ProtocolPhases::SENDING_SIGNAL_LEVEL: + case ProtocolPhases::WAITING_SIGNAL_LEVEL_ANSWER this->set_phase(ProtocolPhases::IDLE); break; +#endif + case ProtocolPhases::SENDING_UPDATE_SIGNAL_REQUEST: + case ProtocolPhases::WAITING_UPDATE_SIGNAL_ANSWER: + this->set_phase(ProtocolPhases::SENDING_SIGNAL_LEVEL); + break; + case ProtocolPhases::SENDING_ALARM_STATUS_REQUEST: + case ProtocolPhases::WAITING_ALARM_STATUS_ANSWER: + this->set_phase(ProtocolPhases::SENDING_INIT_1); + break; case ProtocolPhases::SENDING_CONTROL: if (this->first_control_attempt_) { this->control_request_timestamp_ = now; @@ -119,14 +200,14 @@ void Smartair2Climate::process_phase(std::chrono::steady_clock::time_point now) this->hvac_settings_.reset(); this->forced_request_status_ = true; this->forced_publish_ = true; - this->set_phase_(ProtocolPhases::IDLE); + this->set_phase(ProtocolPhases::IDLE); } else if (this->can_send_message() && this->is_control_message_interval_exceeded_( now)) // Using CONTROL_MESSAGES_INTERVAL_MS to speedup requests { haier_protocol::HaierMessage control_message = get_control_message(); this->send_message_(control_message, false); ESP_LOGI(TAG, "Control packet sent"); - this->set_phase_(ProtocolPhases::WAITING_CONTROL_ANSWER); + this->set_phase(ProtocolPhases::WAITING_CONTROL_ANSWER); } break; case ProtocolPhases::SENDING_POWER_ON_COMMAND: @@ -136,11 +217,12 @@ void Smartair2Climate::process_phase(std::chrono::steady_clock::time_point now) (uint8_t) smartair2_protocol::FrameType::CONTROL, this->protocol_phase_ == ProtocolPhases::SENDING_POWER_ON_COMMAND ? 0x4D02 : 0x4D03); this->send_message_(power_cmd, false); - this->set_phase_(this->protocol_phase_ == ProtocolPhases::SENDING_POWER_ON_COMMAND - ? ProtocolPhases::WAITING_POWER_ON_ANSWER - : ProtocolPhases::WAITING_POWER_OFF_ANSWER); + this->set_phase(this->protocol_phase_ == ProtocolPhases::SENDING_POWER_ON_COMMAND + ? ProtocolPhases::WAITING_POWER_ON_ANSWER + : ProtocolPhases::WAITING_POWER_OFF_ANSWER); } break; + case ProtocolPhases::WAITING_INIT_1_ANSWER: case ProtocolPhases::WAITING_FIRST_STATUS_ANSWER: case ProtocolPhases::WAITING_STATUS_ANSWER: case ProtocolPhases::WAITING_CONTROL_ANSWER: @@ -149,14 +231,25 @@ void Smartair2Climate::process_phase(std::chrono::steady_clock::time_point now) break; case ProtocolPhases::IDLE: { if (this->forced_request_status_ || this->is_status_request_interval_exceeded_(now)) { - this->set_phase_(ProtocolPhases::SENDING_STATUS_REQUEST); + this->set_phase(ProtocolPhases::SENDING_STATUS_REQUEST); this->forced_request_status_ = false; } +#ifdef USE_WIFI + else if (this->send_wifi_signal_ && + (std::chrono::duration_cast(now - this->last_signal_request_).count() > + SIGNAL_LEVEL_UPDATE_INTERVAL_MS)) + this->set_phase(ProtocolPhases::SENDING_UPDATE_SIGNAL_REQUEST); +#endif } break; default: // Shouldn't get here +#if (HAIER_LOG_LEVEL > 4) + ESP_LOGE(TAG, "Wrong protocol handler state: %s (%d), resetting communication", + phase_to_string_(this->protocol_phase_), (int) this->protocol_phase_); +#else ESP_LOGE(TAG, "Wrong protocol handler state: %d, resetting communication", (int) this->protocol_phase_); - this->set_phase_(ProtocolPhases::SENDING_FIRST_STATUS_REQUEST); +#endif + this->set_phase(ProtocolPhases::SENDING_INIT_1); break; } } @@ -256,11 +349,12 @@ haier_protocol::HaierMessage Smartair2Climate::get_control_message() { } } if (climate_control.target_temperature.has_value()) { - out_data->set_point = - climate_control.target_temperature.value() - 16; // set the temperature at our offset, subtract 16. + float target_temp = climate_control.target_temperature.value(); + out_data->set_point = target_temp - 16; // set the temperature with offset 16 + out_data->half_degree = (target_temp - ((int) target_temp) >= 0.49) ? 1 : 0; } if (out_data->ac_power == 0) { - // If AC is off - no presets alowed + // If AC is off - no presets allowed out_data->turbo_mode = 0; out_data->quiet_mode = 0; } else if (climate_control.preset.has_value()) { @@ -312,7 +406,7 @@ haier_protocol::HandlerError Smartair2Climate::process_status_message_(const uin { // Target temperature float old_target_temperature = this->target_temperature; - this->target_temperature = packet.control.set_point + 16.0f; + this->target_temperature = packet.control.set_point + 16.0f + ((packet.control.half_degree == 1) ? 0.5f : 0.0f); should_publish = should_publish || (old_target_temperature != this->target_temperature); } { @@ -333,7 +427,7 @@ haier_protocol::HandlerError Smartair2Climate::process_status_message_(const uin } switch (packet.control.fan_mode) { case (uint8_t) smartair2_protocol::FanMode::FAN_AUTO: - // Somtimes AC reports in fan only mode that fan speed is auto + // Sometimes AC reports in fan only mode that fan speed is auto // but never accept this value back if (packet.control.ac_mode != (uint8_t) smartair2_protocol::ConditioningMode::FAN) { this->fan_mode = CLIMATE_FAN_AUTO; @@ -453,5 +547,15 @@ bool Smartair2Climate::is_message_invalid(uint8_t message_type) { return message_type == (uint8_t) smartair2_protocol::FrameType::INVALID; } +void Smartair2Climate::set_phase(HaierClimateBase::ProtocolPhases phase) { + int old_phase = (int) this->protocol_phase_; + int new_phase = (int) phase; + int min_p = std::min(old_phase, new_phase); + int max_p = std::max(old_phase, new_phase); + if ((min_p % 2 != 0) || (max_p - min_p > 1)) + this->timeouts_counter_ = 0; + HaierClimateBase::set_phase(phase); +} + } // namespace haier } // namespace esphome diff --git a/esphome/components/haier/smartair2_climate.h b/esphome/components/haier/smartair2_climate.h index c89d1f0be9..f173b10749 100644 --- a/esphome/components/haier/smartair2_climate.h +++ b/esphome/components/haier/smartair2_climate.h @@ -15,16 +15,25 @@ class Smartair2Climate : public HaierClimateBase { void dump_config() override; protected: - void set_answers_handlers() override; + void set_handlers() override; void process_phase(std::chrono::steady_clock::time_point now) override; haier_protocol::HaierMessage get_control_message() override; bool is_message_invalid(uint8_t message_type) override; - // Answers handlers + void set_phase(HaierClimateBase::ProtocolPhases phase) override; + // Answer and timeout handlers haier_protocol::HandlerError status_handler_(uint8_t request_type, uint8_t message_type, const uint8_t *data, size_t data_size); + haier_protocol::HandlerError get_device_version_answer_handler_(uint8_t request_type, uint8_t message_type, + const uint8_t *data, size_t data_size); + haier_protocol::HandlerError get_device_id_answer_handler_(uint8_t request_type, uint8_t message_type, + const uint8_t *data, size_t data_size); + haier_protocol::HandlerError report_network_status_answer_handler_(uint8_t request_type, uint8_t message_type, + const uint8_t *data, size_t data_size); + haier_protocol::HandlerError initial_messages_timeout_handler_(uint8_t message_type); // Helper functions haier_protocol::HandlerError process_status_message_(const uint8_t *packet, uint8_t size); std::unique_ptr last_status_message_; + unsigned int timeouts_counter_; }; } // namespace haier diff --git a/esphome/components/haier/smartair2_packet.h b/esphome/components/haier/smartair2_packet.h index 8046516c5f..f791c21af2 100644 --- a/esphome/components/haier/smartair2_packet.h +++ b/esphome/components/haier/smartair2_packet.h @@ -53,8 +53,8 @@ struct HaierPacketControl { uint8_t : 2; uint8_t health_mode : 1; // Health mode on or off uint8_t compressor : 1; // Compressor on or off ??? - uint8_t : 1; - uint8_t ten_degree : 1; // 10 degree status (only work in heat mode) + uint8_t half_degree : 1; // Use half degree + uint8_t ten_degree : 1; // 10 degree status (only work in heat mode) uint8_t : 0; // 28 uint8_t : 8; @@ -88,6 +88,9 @@ enum class FrameType : uint8_t { INVALID = 0x03, CONFIRM = 0x05, GET_DEVICE_VERSION = 0x61, + GET_DEVICE_VERSION_RESPONSE = 0x62, + GET_DEVICE_ID = 0x70, + GET_DEVICE_ID_RESPONSE = 0x71, REPORT_NETWORK_STATUS = 0xF7, NO_COMMAND = 0xFF, }; diff --git a/platformio.ini b/platformio.ini index ba149ce99e..5da3b9f978 100644 --- a/platformio.ini +++ b/platformio.ini @@ -39,7 +39,7 @@ lib_deps = bblanchon/ArduinoJson@6.18.5 ; json wjtje/qr-code-generator-library@1.7.0 ; qr_code functionpointer/arduino-MLX90393@1.0.0 ; mlx90393 - pavlodn/HaierProtocol@0.9.18 ; haier + pavlodn/HaierProtocol@0.9.20 ; haier ; 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 build_flags = From be6f95d43eaaa419ed65641965fb384ec94c3a5f Mon Sep 17 00:00:00 2001 From: Steve Rodgers Date: Fri, 11 Aug 2023 17:50:33 -0700 Subject: [PATCH 0051/2101] pca9554 cache reads (#5137) --- esphome/components/pca9554/pca9554.cpp | 25 +++++++++++++++++++++++-- esphome/components/pca9554/pca9554.h | 6 ++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/esphome/components/pca9554/pca9554.cpp b/esphome/components/pca9554/pca9554.cpp index 39093fcf54..74c64dffaa 100644 --- a/esphome/components/pca9554/pca9554.cpp +++ b/esphome/components/pca9554/pca9554.cpp @@ -26,7 +26,7 @@ void PCA9554Component::setup() { this->config_mask_ = 0; // Invert mask as the part sees a 1 as an input this->write_register_(CONFIG_REG, ~this->config_mask_); - // All ouputs low + // All outputs low this->output_mask_ = 0; this->write_register_(OUTPUT_REG, this->output_mask_); // Read the inputs @@ -34,6 +34,14 @@ void PCA9554Component::setup() { ESP_LOGD(TAG, "Initialization complete. Warning: %d, Error: %d", this->status_has_warning(), this->status_has_error()); } + +void PCA9554Component::loop() { + // The read_inputs_() method will cache the input values from the chip. + this->read_inputs_(); + // Clear all the previously read flags. + this->was_previously_read_ = 0x00; +} + void PCA9554Component::dump_config() { ESP_LOGCONFIG(TAG, "PCA9554:"); LOG_I2C_DEVICE(this) @@ -43,7 +51,16 @@ void PCA9554Component::dump_config() { } bool PCA9554Component::digital_read(uint8_t pin) { - this->read_inputs_(); + // Note: We want to try and avoid doing any I2C bus read transactions here + // to conserve I2C bus bandwidth. So what we do is check to see if we + // have seen a read during the time esphome is running this loop. If we have, + // we do an I2C bus transaction to get the latest value. If we haven't + // we return a cached value which was read at the time loop() was called. + if (this->was_previously_read_ & (1 << pin)) + this->read_inputs_(); // Force a read of a new value + // Indicate we saw a read request for this pin in case a + // read happens later in the same loop. + this->was_previously_read_ |= (1 << pin); return this->input_mask_ & (1 << pin); } @@ -98,6 +115,10 @@ bool PCA9554Component::write_register_(uint8_t reg, uint8_t value) { float PCA9554Component::get_setup_priority() const { return setup_priority::IO; } +// Run our loop() method very early in the loop, so that we cache read values before +// before other components call our digital_read() method. +float PCA9554Component::get_loop_priority() const { return 9.0f; } // Just after WIFI + 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 d1bfc36bec..c2aa5c30ed 100644 --- a/esphome/components/pca9554/pca9554.h +++ b/esphome/components/pca9554/pca9554.h @@ -13,6 +13,8 @@ class PCA9554Component : public Component, public i2c::I2CDevice { /// 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. @@ -22,6 +24,8 @@ class PCA9554Component : public Component, public i2c::I2CDevice { float get_setup_priority() const override; + float get_loop_priority() const override; + void dump_config() override; protected: @@ -35,6 +39,8 @@ class PCA9554Component : public Component, public i2c::I2CDevice { uint8_t output_mask_{0x00}; /// The state of the actual input pin states - 1 means HIGH, 0 means LOW uint8_t input_mask_{0x00}; + /// Flags to check if read previously during this loop + uint8_t was_previously_read_ = {0x00}; /// Storage for last I2C error seen esphome::i2c::ErrorCode last_error_; }; From 3717e34bbab1fa21861a282e8621894a2cad2c7e Mon Sep 17 00:00:00 2001 From: Sergey Dudanov Date: Mon, 14 Aug 2023 01:06:04 +0400 Subject: [PATCH 0052/2101] fix midea: undo approved PR#4053 (#5233) --- esphome/components/remote_base/__init__.py | 18 +++++++---------- .../components/remote_base/midea_protocol.h | 20 +++++-------------- tests/test1.yaml | 2 ++ 3 files changed, 14 insertions(+), 26 deletions(-) diff --git a/esphome/components/remote_base/__init__.py b/esphome/components/remote_base/__init__.py index 24993e84d3..9e46506b3c 100644 --- a/esphome/components/remote_base/__init__.py +++ b/esphome/components/remote_base/__init__.py @@ -1488,11 +1488,9 @@ MideaData, MideaBinarySensor, MideaTrigger, MideaAction, MideaDumper = declare_p MideaAction = ns.class_("MideaAction", RemoteTransmitterActionBase) MIDEA_SCHEMA = cv.Schema( { - cv.Required(CONF_CODE): cv.templatable( - cv.All( - [cv.Any(cv.hex_uint8_t, cv.uint8_t)], - cv.Length(min=5, max=5), - ) + cv.Required(CONF_CODE): cv.All( + [cv.Any(cv.hex_uint8_t, cv.uint8_t)], + cv.Length(min=5, max=5), ), } ) @@ -1519,12 +1517,10 @@ def midea_dumper(var, config): MIDEA_SCHEMA, ) async def midea_action(var, config, args): - code_ = config[CONF_CODE] - if cg.is_template(code_): - template_ = await cg.templatable(code_, args, cg.std_vector.template(cg.uint8)) - cg.add(var.set_code_template(template_)) - else: - cg.add(var.set_code_static(code_)) + template_ = await cg.templatable( + config[CONF_CODE], args, cg.std_vector.template(cg.uint8) + ) + cg.add(var.set_code(template_)) # AEHA diff --git a/esphome/components/remote_base/midea_protocol.h b/esphome/components/remote_base/midea_protocol.h index d81a50241b..f5db313579 100644 --- a/esphome/components/remote_base/midea_protocol.h +++ b/esphome/components/remote_base/midea_protocol.h @@ -1,11 +1,11 @@ #pragma once +#include +#include + #include "esphome/core/component.h" #include "esphome/core/helpers.h" #include "remote_base.h" -#include -#include -#include namespace esphome { namespace remote_base { @@ -84,23 +84,13 @@ using MideaDumper = RemoteReceiverDumper; template class MideaAction : public RemoteTransmitterActionBase { TEMPLATABLE_VALUE(std::vector, code) - void set_code_static(std::vector code) { code_static_ = std::move(code); } - void set_code_template(std::function(Ts...)> func) { this->code_func_ = func; } + void set_code(std::initializer_list code) { this->code_ = code; } void encode(RemoteTransmitData *dst, Ts... x) override { - MideaData data; - if (!this->code_static_.empty()) { - data = MideaData(this->code_static_); - } else { - data = MideaData(this->code_func_(x...)); - } + MideaData data(this->code_.value(x...)); data.finalize(); MideaProtocol().encode(dst, data); } - - protected: - std::function(Ts...)> code_func_{}; - std::vector code_static_{}; }; } // namespace remote_base diff --git a/tests/test1.yaml b/tests/test1.yaml index 5c9b83a915..4eb78515c9 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -2333,6 +2333,8 @@ switch: second: !lambda "return 0xB21F98;" - remote_transmitter.transmit_midea: code: [0xA2, 0x08, 0xFF, 0xFF, 0xFF] + - remote_transmitter.transmit_midea: + code: !lambda "return {0xA2, 0x08, 0xFF, 0xFF, 0xFF};" - platform: gpio name: "MCP23S08 Pin #0" pin: From f26238e824d8df401eea8392633d7e1c3e042ed7 Mon Sep 17 00:00:00 2001 From: Pavlo Dudnytskyi Date: Sun, 13 Aug 2023 23:08:18 +0200 Subject: [PATCH 0053/2101] Fixing smartair2 protocol implementation if no Wi-Fi (#5238) --- esphome/components/haier/smartair2_climate.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/esphome/components/haier/smartair2_climate.cpp b/esphome/components/haier/smartair2_climate.cpp index 91b6bb0545..8bee37dadf 100644 --- a/esphome/components/haier/smartair2_climate.cpp +++ b/esphome/components/haier/smartair2_climate.cpp @@ -178,7 +178,9 @@ void Smartair2Climate::process_phase(std::chrono::steady_clock::time_point now) break; #else case ProtocolPhases::SENDING_SIGNAL_LEVEL: - case ProtocolPhases::WAITING_SIGNAL_LEVEL_ANSWER this->set_phase(ProtocolPhases::IDLE); break; + case ProtocolPhases::WAITING_SIGNAL_LEVEL_ANSWER: + this->set_phase(ProtocolPhases::IDLE); + break; #endif case ProtocolPhases::SENDING_UPDATE_SIGNAL_REQUEST: case ProtocolPhases::WAITING_UPDATE_SIGNAL_ANSWER: From 3a899e28dc5016ed9be8575b864f968a9d28b85f Mon Sep 17 00:00:00 2001 From: Kjell Braden Date: Sun, 13 Aug 2023 23:09:51 +0200 Subject: [PATCH 0054/2101] tuya: add time sync callback only once to prevent memleak (#5234) --- esphome/components/tuya/tuya.cpp | 9 +++++++-- esphome/components/tuya/tuya.h | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/esphome/components/tuya/tuya.cpp b/esphome/components/tuya/tuya.cpp index 7e6b1d53fe..0fad151488 100644 --- a/esphome/components/tuya/tuya.cpp +++ b/esphome/components/tuya/tuya.cpp @@ -246,8 +246,13 @@ void Tuya::handle_command_(uint8_t command, uint8_t version, const uint8_t *buff #ifdef USE_TIME if (this->time_id_.has_value()) { this->send_local_time_(); - auto *time_id = *this->time_id_; - time_id->add_on_time_sync_callback([this] { this->send_local_time_(); }); + + if (!this->time_sync_callback_registered_) { + // tuya mcu supports time, so we let them know when our time changed + auto *time_id = *this->time_id_; + time_id->add_on_time_sync_callback([this] { this->send_local_time_(); }); + this->time_sync_callback_registered_ = true; + } } else { ESP_LOGW(TAG, "LOCAL_TIME_QUERY is not handled because time is not configured"); } diff --git a/esphome/components/tuya/tuya.h b/esphome/components/tuya/tuya.h index b9901dd5e7..26f6f65912 100644 --- a/esphome/components/tuya/tuya.h +++ b/esphome/components/tuya/tuya.h @@ -130,6 +130,7 @@ class Tuya : public Component, public uart::UARTDevice { #ifdef USE_TIME void send_local_time_(); optional time_id_{}; + bool time_sync_callback_registered_{false}; #endif TuyaInitState init_state_ = TuyaInitState::INIT_HEARTBEAT; bool init_failed_{false}; From b05a3fbb55da3b655a3c8f7dce0948296299ec06 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 14 Aug 2023 10:09:20 +1200 Subject: [PATCH 0055/2101] Fix duplicate tuya time warning (#5243) --- esphome/components/tuya/tuya.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/esphome/components/tuya/tuya.cpp b/esphome/components/tuya/tuya.cpp index 0fad151488..daf5080e7a 100644 --- a/esphome/components/tuya/tuya.cpp +++ b/esphome/components/tuya/tuya.cpp @@ -1,9 +1,9 @@ #include "tuya.h" #include "esphome/components/network/util.h" +#include "esphome/core/gpio.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" #include "esphome/core/util.h" -#include "esphome/core/gpio.h" #ifdef USE_WIFI #include "esphome/components/wifi/wifi_component.h" @@ -253,12 +253,11 @@ void Tuya::handle_command_(uint8_t command, uint8_t version, const uint8_t *buff time_id->add_on_time_sync_callback([this] { this->send_local_time_(); }); this->time_sync_callback_registered_ = true; } - } else { + } else +#endif + { ESP_LOGW(TAG, "LOCAL_TIME_QUERY is not handled because time is not configured"); } -#else - ESP_LOGE(TAG, "LOCAL_TIME_QUERY is not handled"); -#endif break; case TuyaCommandType::VACUUM_MAP_UPLOAD: this->send_command_( From 560e36a65c3df089856c9c77bea5f2133d467310 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 14 Aug 2023 11:09:49 +1200 Subject: [PATCH 0056/2101] Bump version to 2023.8.0b2 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 6b442dd633..1442ebde9d 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2023.8.0b1" +__version__ = "2023.8.0b2" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 6089526975ee74b73d5b4975b7b481f37d50ac58 Mon Sep 17 00:00:00 2001 From: mulder-fbi Date: Wed, 16 Aug 2023 00:52:56 +0200 Subject: [PATCH 0057/2101] Fix 24 bit signed integer parsing in sml parser (#5250) --- esphome/components/sml/sml_parser.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/esphome/components/sml/sml_parser.cpp b/esphome/components/sml/sml_parser.cpp index ff7da4cabd..91b320a30e 100644 --- a/esphome/components/sml/sml_parser.cpp +++ b/esphome/components/sml/sml_parser.cpp @@ -88,6 +88,11 @@ uint64_t bytes_to_uint(const bytes &buffer) { for (auto const value : buffer) { val = (val << 8) + value; } + // Some smart meters send 24 bit signed integers. Sign extend to 64 bit if the + // 24 bit value is negative. + if (buffer.size() == 3 && buffer[0] & 0x80) { + val |= 0xFFFFFFFFFF000000; + } return val; } From 4a518e3e7adec588aad250f211b2f13ad03be98e Mon Sep 17 00:00:00 2001 From: Sergey Dudanov Date: Wed, 16 Aug 2023 03:11:44 +0400 Subject: [PATCH 0058/2101] remote_base: change dumpers log level (#5253) --- esphome/components/remote_base/aeha_protocol.cpp | 2 +- esphome/components/remote_base/canalsat_protocol.cpp | 4 ++-- esphome/components/remote_base/coolix_protocol.cpp | 6 +++--- esphome/components/remote_base/dish_protocol.cpp | 2 +- esphome/components/remote_base/drayton_protocol.cpp | 2 +- esphome/components/remote_base/jvc_protocol.cpp | 2 +- esphome/components/remote_base/lg_protocol.cpp | 2 +- esphome/components/remote_base/magiquest_protocol.cpp | 2 +- esphome/components/remote_base/midea_protocol.cpp | 2 +- esphome/components/remote_base/nec_protocol.cpp | 2 +- esphome/components/remote_base/nexa_protocol.cpp | 2 +- esphome/components/remote_base/panasonic_protocol.cpp | 2 +- esphome/components/remote_base/pioneer_protocol.cpp | 4 ++-- esphome/components/remote_base/pronto_protocol.cpp | 4 ++-- esphome/components/remote_base/raw_protocol.cpp | 4 ++-- esphome/components/remote_base/rc5_protocol.cpp | 2 +- esphome/components/remote_base/rc6_protocol.cpp | 2 +- esphome/components/remote_base/rc_switch_protocol.cpp | 2 +- esphome/components/remote_base/samsung36_protocol.cpp | 2 +- esphome/components/remote_base/samsung_protocol.cpp | 2 +- esphome/components/remote_base/sony_protocol.cpp | 2 +- esphome/components/remote_base/toshiba_ac_protocol.cpp | 4 ++-- 22 files changed, 29 insertions(+), 29 deletions(-) diff --git a/esphome/components/remote_base/aeha_protocol.cpp b/esphome/components/remote_base/aeha_protocol.cpp index ee1616ed6d..40bdadf634 100644 --- a/esphome/components/remote_base/aeha_protocol.cpp +++ b/esphome/components/remote_base/aeha_protocol.cpp @@ -96,7 +96,7 @@ std::string AEHAProtocol::format_data_(const std::vector &data) { void AEHAProtocol::dump(const AEHAData &data) { auto data_str = format_data_(data.data); - ESP_LOGD(TAG, "Received AEHA: address=0x%04X, data=[%s]", data.address, data_str.c_str()); + ESP_LOGI(TAG, "Received AEHA: address=0x%04X, data=[%s]", data.address, data_str.c_str()); } } // namespace remote_base diff --git a/esphome/components/remote_base/canalsat_protocol.cpp b/esphome/components/remote_base/canalsat_protocol.cpp index 1ea47750fd..bee3d57fd8 100644 --- a/esphome/components/remote_base/canalsat_protocol.cpp +++ b/esphome/components/remote_base/canalsat_protocol.cpp @@ -96,10 +96,10 @@ optional CanalSatBaseProtocol::decode(RemoteReceiveData src) { void CanalSatBaseProtocol::dump(const CanalSatData &data) { if (this->tag_ == CANALSATLD_TAG) { - ESP_LOGD(this->tag_, "Received CanalSatLD: device=0x%02X, address=0x%02X, command=0x%02X, repeat=0x%X", data.device, + ESP_LOGI(this->tag_, "Received CanalSatLD: device=0x%02X, address=0x%02X, command=0x%02X, repeat=0x%X", data.device, data.address, data.command, data.repeat); } else { - ESP_LOGD(this->tag_, "Received CanalSat: device=0x%02X, address=0x%02X, command=0x%02X, repeat=0x%X", data.device, + ESP_LOGI(this->tag_, "Received CanalSat: device=0x%02X, address=0x%02X, command=0x%02X, repeat=0x%X", data.device, data.address, data.command, data.repeat); } } diff --git a/esphome/components/remote_base/coolix_protocol.cpp b/esphome/components/remote_base/coolix_protocol.cpp index 3c9dadcd1c..295fccb762 100644 --- a/esphome/components/remote_base/coolix_protocol.cpp +++ b/esphome/components/remote_base/coolix_protocol.cpp @@ -101,11 +101,11 @@ optional CoolixProtocol::decode(RemoteReceiveData data) { void CoolixProtocol::dump(const CoolixData &data) { if (data.is_strict()) { - ESP_LOGD(TAG, "Received Coolix: 0x%06X", data.first); + ESP_LOGI(TAG, "Received Coolix: 0x%06X", data.first); } else if (data.has_second()) { - ESP_LOGD(TAG, "Received unstrict Coolix: [0x%06X, 0x%06X]", data.first, data.second); + ESP_LOGI(TAG, "Received unstrict Coolix: [0x%06X, 0x%06X]", data.first, data.second); } else { - ESP_LOGD(TAG, "Received unstrict Coolix: [0x%06X]", data.first); + ESP_LOGI(TAG, "Received unstrict Coolix: [0x%06X]", data.first); } } diff --git a/esphome/components/remote_base/dish_protocol.cpp b/esphome/components/remote_base/dish_protocol.cpp index 47bfdc5c58..754b6c3b12 100644 --- a/esphome/components/remote_base/dish_protocol.cpp +++ b/esphome/components/remote_base/dish_protocol.cpp @@ -87,7 +87,7 @@ optional DishProtocol::decode(RemoteReceiveData src) { } void DishProtocol::dump(const DishData &data) { - ESP_LOGD(TAG, "Received Dish: address=0x%02X, command=0x%02X", data.address, data.command); + ESP_LOGI(TAG, "Received Dish: address=0x%02X, command=0x%02X", data.address, data.command); } } // namespace remote_base diff --git a/esphome/components/remote_base/drayton_protocol.cpp b/esphome/components/remote_base/drayton_protocol.cpp index f5eae49058..56a3dec1e0 100644 --- a/esphome/components/remote_base/drayton_protocol.cpp +++ b/esphome/components/remote_base/drayton_protocol.cpp @@ -205,7 +205,7 @@ optional DraytonProtocol::decode(RemoteReceiveData src) { return out; } void DraytonProtocol::dump(const DraytonData &data) { - ESP_LOGD(TAG, "Received Drayton: address=0x%04X (0x%04x), channel=0x%03x command=0x%03X", data.address, + ESP_LOGI(TAG, "Received Drayton: address=0x%04X (0x%04x), channel=0x%03x command=0x%03X", data.address, ((data.address << 1) & 0xffff), data.channel, data.command); } diff --git a/esphome/components/remote_base/jvc_protocol.cpp b/esphome/components/remote_base/jvc_protocol.cpp index 169b1d00bf..3d34cc614e 100644 --- a/esphome/components/remote_base/jvc_protocol.cpp +++ b/esphome/components/remote_base/jvc_protocol.cpp @@ -46,7 +46,7 @@ optional JVCProtocol::decode(RemoteReceiveData src) { } return out; } -void JVCProtocol::dump(const JVCData &data) { ESP_LOGD(TAG, "Received JVC: data=0x%04X", data.data); } +void JVCProtocol::dump(const JVCData &data) { ESP_LOGI(TAG, "Received JVC: data=0x%04X", data.data); } } // namespace remote_base } // namespace esphome diff --git a/esphome/components/remote_base/lg_protocol.cpp b/esphome/components/remote_base/lg_protocol.cpp index 8040b0f3fc..d7d3a5ac7d 100644 --- a/esphome/components/remote_base/lg_protocol.cpp +++ b/esphome/components/remote_base/lg_protocol.cpp @@ -51,7 +51,7 @@ optional LGProtocol::decode(RemoteReceiveData src) { return out; } void LGProtocol::dump(const LGData &data) { - ESP_LOGD(TAG, "Received LG: data=0x%08X, nbits=%d", data.data, data.nbits); + ESP_LOGI(TAG, "Received LG: data=0x%08X, nbits=%d", data.data, data.nbits); } } // namespace remote_base diff --git a/esphome/components/remote_base/magiquest_protocol.cpp b/esphome/components/remote_base/magiquest_protocol.cpp index 20b40ef201..76024b1eaf 100644 --- a/esphome/components/remote_base/magiquest_protocol.cpp +++ b/esphome/components/remote_base/magiquest_protocol.cpp @@ -76,7 +76,7 @@ optional MagiQuestProtocol::decode(RemoteReceiveData src) { return data; } void MagiQuestProtocol::dump(const MagiQuestData &data) { - ESP_LOGD(TAG, "Received MagiQuest: wand_id=0x%08X, magnitude=0x%04X", data.wand_id, data.magnitude); + ESP_LOGI(TAG, "Received MagiQuest: wand_id=0x%08X, magnitude=0x%04X", data.wand_id, data.magnitude); } } // namespace remote_base diff --git a/esphome/components/remote_base/midea_protocol.cpp b/esphome/components/remote_base/midea_protocol.cpp index f619d201bc..8006fe4048 100644 --- a/esphome/components/remote_base/midea_protocol.cpp +++ b/esphome/components/remote_base/midea_protocol.cpp @@ -70,7 +70,7 @@ optional MideaProtocol::decode(RemoteReceiveData src) { return {}; } -void MideaProtocol::dump(const MideaData &data) { ESP_LOGD(TAG, "Received Midea: %s", data.to_string().c_str()); } +void MideaProtocol::dump(const MideaData &data) { ESP_LOGI(TAG, "Received Midea: %s", data.to_string().c_str()); } } // namespace remote_base } // namespace esphome diff --git a/esphome/components/remote_base/nec_protocol.cpp b/esphome/components/remote_base/nec_protocol.cpp index ee3fec5992..d5c68784ee 100644 --- a/esphome/components/remote_base/nec_protocol.cpp +++ b/esphome/components/remote_base/nec_protocol.cpp @@ -67,7 +67,7 @@ optional NECProtocol::decode(RemoteReceiveData src) { return data; } void NECProtocol::dump(const NECData &data) { - ESP_LOGD(TAG, "Received NEC: address=0x%04X, command=0x%04X", data.address, data.command); + ESP_LOGI(TAG, "Received NEC: address=0x%04X, command=0x%04X", data.address, data.command); } } // namespace remote_base diff --git a/esphome/components/remote_base/nexa_protocol.cpp b/esphome/components/remote_base/nexa_protocol.cpp index a0066ea5d4..f4e7d14187 100644 --- a/esphome/components/remote_base/nexa_protocol.cpp +++ b/esphome/components/remote_base/nexa_protocol.cpp @@ -232,7 +232,7 @@ optional NexaProtocol::decode(RemoteReceiveData src) { } void NexaProtocol::dump(const NexaData &data) { - ESP_LOGD(TAG, "Received NEXA: device=0x%04X group=%d state=%d channel=%d level=%d", data.device, data.group, + ESP_LOGI(TAG, "Received NEXA: device=0x%04X group=%d state=%d channel=%d level=%d", data.device, data.group, data.state, data.channel, data.level); } diff --git a/esphome/components/remote_base/panasonic_protocol.cpp b/esphome/components/remote_base/panasonic_protocol.cpp index fe1060e935..460ca3b164 100644 --- a/esphome/components/remote_base/panasonic_protocol.cpp +++ b/esphome/components/remote_base/panasonic_protocol.cpp @@ -67,7 +67,7 @@ optional PanasonicProtocol::decode(RemoteReceiveData src) { return out; } void PanasonicProtocol::dump(const PanasonicData &data) { - ESP_LOGD(TAG, "Received Panasonic: address=0x%04X, command=0x%08X", data.address, data.command); + ESP_LOGI(TAG, "Received Panasonic: address=0x%04X, command=0x%08X", data.address, data.command); } } // namespace remote_base diff --git a/esphome/components/remote_base/pioneer_protocol.cpp b/esphome/components/remote_base/pioneer_protocol.cpp index 5c10eab48d..043565282d 100644 --- a/esphome/components/remote_base/pioneer_protocol.cpp +++ b/esphome/components/remote_base/pioneer_protocol.cpp @@ -146,9 +146,9 @@ optional PioneerProtocol::decode(RemoteReceiveData src) { } void PioneerProtocol::dump(const PioneerData &data) { if (data.rc_code_2 == 0) { - ESP_LOGD(TAG, "Received Pioneer: rc_code_X=0x%04X", data.rc_code_1); + ESP_LOGI(TAG, "Received Pioneer: rc_code_X=0x%04X", data.rc_code_1); } else { - ESP_LOGD(TAG, "Received Pioneer: rc_code_1=0x%04X, rc_code_2=0x%04X", data.rc_code_1, data.rc_code_2); + ESP_LOGI(TAG, "Received Pioneer: rc_code_1=0x%04X, rc_code_2=0x%04X", data.rc_code_1, data.rc_code_2); } } diff --git a/esphome/components/remote_base/pronto_protocol.cpp b/esphome/components/remote_base/pronto_protocol.cpp index 81ac176666..4b6977e1a2 100644 --- a/esphome/components/remote_base/pronto_protocol.cpp +++ b/esphome/components/remote_base/pronto_protocol.cpp @@ -234,9 +234,9 @@ void ProntoProtocol::dump(const ProntoData &data) { first = data.data.substr(0, 229); rest = data.data.substr(230); } - ESP_LOGD(TAG, "Received Pronto: data=%s", first.c_str()); + ESP_LOGI(TAG, "Received Pronto: data=%s", first.c_str()); if (!rest.empty()) { - ESP_LOGD(TAG, "%s", rest.c_str()); + ESP_LOGI(TAG, "%s", rest.c_str()); } } diff --git a/esphome/components/remote_base/raw_protocol.cpp b/esphome/components/remote_base/raw_protocol.cpp index 3446dcdbb8..9304aa3e3d 100644 --- a/esphome/components/remote_base/raw_protocol.cpp +++ b/esphome/components/remote_base/raw_protocol.cpp @@ -25,7 +25,7 @@ bool RawDumper::dump(RemoteReceiveData src) { if (written < 0 || written >= int(remaining_length)) { // write failed, flush... buffer[buffer_offset] = '\0'; - ESP_LOGD(TAG, "%s", buffer); + ESP_LOGI(TAG, "%s", buffer); buffer_offset = 0; written = sprintf(buffer, " "); if (i + 1 < src.size()) { @@ -38,7 +38,7 @@ bool RawDumper::dump(RemoteReceiveData src) { buffer_offset += written; } if (buffer_offset != 0) { - ESP_LOGD(TAG, "%s", buffer); + ESP_LOGI(TAG, "%s", buffer); } return true; } diff --git a/esphome/components/remote_base/rc5_protocol.cpp b/esphome/components/remote_base/rc5_protocol.cpp index cb6eed4c6c..08f2f2eaa3 100644 --- a/esphome/components/remote_base/rc5_protocol.cpp +++ b/esphome/components/remote_base/rc5_protocol.cpp @@ -83,7 +83,7 @@ optional RC5Protocol::decode(RemoteReceiveData src) { return out; } void RC5Protocol::dump(const RC5Data &data) { - ESP_LOGD(TAG, "Received RC5: address=0x%02X, command=0x%02X", data.address, data.command); + ESP_LOGI(TAG, "Received RC5: address=0x%02X, command=0x%02X", data.address, data.command); } } // namespace remote_base diff --git a/esphome/components/remote_base/rc6_protocol.cpp b/esphome/components/remote_base/rc6_protocol.cpp index ad12c7c208..fcb4da11a4 100644 --- a/esphome/components/remote_base/rc6_protocol.cpp +++ b/esphome/components/remote_base/rc6_protocol.cpp @@ -173,7 +173,7 @@ optional RC6Protocol::decode(RemoteReceiveData src) { } void RC6Protocol::dump(const RC6Data &data) { - ESP_LOGD(RC6_TAG, "Received RC6: mode=0x%X, address=0x%02X, command=0x%02X, toggle=0x%X", data.mode, data.address, + ESP_LOGI(RC6_TAG, "Received RC6: mode=0x%X, address=0x%02X, command=0x%02X, toggle=0x%X", data.mode, data.address, data.command, data.toggle); } diff --git a/esphome/components/remote_base/rc_switch_protocol.cpp b/esphome/components/remote_base/rc_switch_protocol.cpp index 5b6284a86f..1f38fdca67 100644 --- a/esphome/components/remote_base/rc_switch_protocol.cpp +++ b/esphome/components/remote_base/rc_switch_protocol.cpp @@ -258,7 +258,7 @@ bool RCSwitchDumper::dump(RemoteReceiveData src) { buffer[j] = (out_data & ((uint64_t) 1 << (out_nbits - j - 1))) ? '1' : '0'; buffer[out_nbits] = '\0'; - ESP_LOGD(TAG, "Received RCSwitch Raw: protocol=%u data='%s'", i, buffer); + ESP_LOGI(TAG, "Received RCSwitch Raw: protocol=%u data='%s'", i, buffer); // only send first decoded protocol return true; diff --git a/esphome/components/remote_base/samsung36_protocol.cpp b/esphome/components/remote_base/samsung36_protocol.cpp index 9ef8ade205..2396986670 100644 --- a/esphome/components/remote_base/samsung36_protocol.cpp +++ b/esphome/components/remote_base/samsung36_protocol.cpp @@ -96,7 +96,7 @@ optional Samsung36Protocol::decode(RemoteReceiveData src) { return out; } void Samsung36Protocol::dump(const Samsung36Data &data) { - ESP_LOGD(TAG, "Received Samsung36: address=0x%04X, command=0x%08X", data.address, data.command); + ESP_LOGI(TAG, "Received Samsung36: address=0x%04X, command=0x%08X", data.address, data.command); } } // namespace remote_base diff --git a/esphome/components/remote_base/samsung_protocol.cpp b/esphome/components/remote_base/samsung_protocol.cpp index 20e8285a03..2d6d5531e5 100644 --- a/esphome/components/remote_base/samsung_protocol.cpp +++ b/esphome/components/remote_base/samsung_protocol.cpp @@ -58,7 +58,7 @@ optional SamsungProtocol::decode(RemoteReceiveData src) { return out; } void SamsungProtocol::dump(const SamsungData &data) { - ESP_LOGD(TAG, "Received Samsung: data=0x%" PRIX64 ", nbits=%d", data.data, data.nbits); + ESP_LOGI(TAG, "Received Samsung: data=0x%" PRIX64 ", nbits=%d", data.data, data.nbits); } } // namespace remote_base diff --git a/esphome/components/remote_base/sony_protocol.cpp b/esphome/components/remote_base/sony_protocol.cpp index 8634cf7d61..bcd8e4c8cf 100644 --- a/esphome/components/remote_base/sony_protocol.cpp +++ b/esphome/components/remote_base/sony_protocol.cpp @@ -62,7 +62,7 @@ optional SonyProtocol::decode(RemoteReceiveData src) { return out; } void SonyProtocol::dump(const SonyData &data) { - ESP_LOGD(TAG, "Received Sony: data=0x%08X, nbits=%d", data.data, data.nbits); + ESP_LOGI(TAG, "Received Sony: data=0x%08X, nbits=%d", data.data, data.nbits); } } // namespace remote_base diff --git a/esphome/components/remote_base/toshiba_ac_protocol.cpp b/esphome/components/remote_base/toshiba_ac_protocol.cpp index 1a19f534f8..42241eea8c 100644 --- a/esphome/components/remote_base/toshiba_ac_protocol.cpp +++ b/esphome/components/remote_base/toshiba_ac_protocol.cpp @@ -105,9 +105,9 @@ optional ToshibaAcProtocol::decode(RemoteReceiveData src) { void ToshibaAcProtocol::dump(const ToshibaAcData &data) { if (data.rc_code_2 != 0) { - ESP_LOGD(TAG, "Received Toshiba AC: rc_code_1=0x%" PRIX64 ", rc_code_2=0x%" PRIX64, data.rc_code_1, data.rc_code_2); + ESP_LOGI(TAG, "Received Toshiba AC: rc_code_1=0x%" PRIX64 ", rc_code_2=0x%" PRIX64, data.rc_code_1, data.rc_code_2); } else { - ESP_LOGD(TAG, "Received Toshiba AC: rc_code_1=0x%" PRIX64, data.rc_code_1); + ESP_LOGI(TAG, "Received Toshiba AC: rc_code_1=0x%" PRIX64, data.rc_code_1); } } From 87629191b31fb96bf0df15d06657827c56862a34 Mon Sep 17 00:00:00 2001 From: Carson Full Date: Tue, 15 Aug 2023 18:13:43 -0500 Subject: [PATCH 0059/2101] Fix IDFI2CBus::writev ignoring stop parameter (#4840) Co-authored-by: Alexander Dimitrov --- esphome/components/i2c/i2c_bus_esp_idf.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/esphome/components/i2c/i2c_bus_esp_idf.cpp b/esphome/components/i2c/i2c_bus_esp_idf.cpp index e2c7e7ddcb..5d35c1968b 100644 --- a/esphome/components/i2c/i2c_bus_esp_idf.cpp +++ b/esphome/components/i2c/i2c_bus_esp_idf.cpp @@ -202,11 +202,13 @@ ErrorCode IDFI2CBus::writev(uint8_t address, WriteBuffer *buffers, size_t cnt, b return ERROR_UNKNOWN; } } - err = i2c_master_stop(cmd); - if (err != ESP_OK) { - ESP_LOGVV(TAG, "TX to %02X master stop failed: %s", address, esp_err_to_name(err)); - i2c_cmd_link_delete(cmd); - return ERROR_UNKNOWN; + if (stop) { + err = i2c_master_stop(cmd); + if (err != ESP_OK) { + ESP_LOGVV(TAG, "TX to %02X master stop failed: %s", address, esp_err_to_name(err)); + i2c_cmd_link_delete(cmd); + return ERROR_UNKNOWN; + } } err = i2c_master_cmd_begin(port_, cmd, 20 / portTICK_PERIOD_MS); i2c_cmd_link_delete(cmd); From 5cb5594288f65fe4639e442a0c3772ed7c96e578 Mon Sep 17 00:00:00 2001 From: Regev Brody Date: Wed, 16 Aug 2023 02:31:18 +0300 Subject: [PATCH 0060/2101] Add configuration flow abilites to the ld2410 component (#4434) --- CODEOWNERS | 2 +- esphome/components/ld2410/__init__.py | 188 +++--- esphome/components/ld2410/automation.h | 22 + esphome/components/ld2410/binary_sensor.py | 45 +- esphome/components/ld2410/button/__init__.py | 57 ++ .../components/ld2410/button/query_button.cpp | 9 + .../components/ld2410/button/query_button.h | 18 + .../components/ld2410/button/reset_button.cpp | 9 + .../components/ld2410/button/reset_button.h | 18 + .../ld2410/button/restart_button.cpp | 9 + .../components/ld2410/button/restart_button.h | 18 + esphome/components/ld2410/ld2410.cpp | 557 +++++++++++++++--- esphome/components/ld2410/ld2410.h | 207 +++++-- esphome/components/ld2410/number/__init__.py | 128 ++++ .../ld2410/number/gate_threshold_number.cpp | 14 + .../ld2410/number/gate_threshold_number.h | 19 + .../ld2410/number/light_threshold_number.cpp | 12 + .../ld2410/number/light_threshold_number.h | 18 + .../number/max_distance_timeout_number.cpp | 12 + .../number/max_distance_timeout_number.h | 18 + esphome/components/ld2410/select/__init__.py | 81 +++ .../ld2410/select/baud_rate_select.cpp | 12 + .../ld2410/select/baud_rate_select.h | 18 + .../select/distance_resolution_select.cpp | 12 + .../select/distance_resolution_select.h | 18 + .../select/light_out_control_select.cpp | 12 + .../ld2410/select/light_out_control_select.h | 18 + esphome/components/ld2410/sensor.py | 111 +++- esphome/components/ld2410/switch/__init__.py | 44 ++ .../ld2410/switch/bluetooth_switch.cpp | 12 + .../ld2410/switch/bluetooth_switch.h | 18 + .../ld2410/switch/engineering_mode_switch.cpp | 12 + .../ld2410/switch/engineering_mode_switch.h | 18 + esphome/components/ld2410/text_sensor.py | 33 ++ tests/test1.yaml | 149 ++++- 35 files changed, 1621 insertions(+), 327 deletions(-) create mode 100644 esphome/components/ld2410/automation.h create mode 100644 esphome/components/ld2410/button/__init__.py create mode 100644 esphome/components/ld2410/button/query_button.cpp create mode 100644 esphome/components/ld2410/button/query_button.h create mode 100644 esphome/components/ld2410/button/reset_button.cpp create mode 100644 esphome/components/ld2410/button/reset_button.h create mode 100644 esphome/components/ld2410/button/restart_button.cpp create mode 100644 esphome/components/ld2410/button/restart_button.h create mode 100644 esphome/components/ld2410/number/__init__.py create mode 100644 esphome/components/ld2410/number/gate_threshold_number.cpp create mode 100644 esphome/components/ld2410/number/gate_threshold_number.h create mode 100644 esphome/components/ld2410/number/light_threshold_number.cpp create mode 100644 esphome/components/ld2410/number/light_threshold_number.h create mode 100644 esphome/components/ld2410/number/max_distance_timeout_number.cpp create mode 100644 esphome/components/ld2410/number/max_distance_timeout_number.h create mode 100644 esphome/components/ld2410/select/__init__.py create mode 100644 esphome/components/ld2410/select/baud_rate_select.cpp create mode 100644 esphome/components/ld2410/select/baud_rate_select.h create mode 100644 esphome/components/ld2410/select/distance_resolution_select.cpp create mode 100644 esphome/components/ld2410/select/distance_resolution_select.h create mode 100644 esphome/components/ld2410/select/light_out_control_select.cpp create mode 100644 esphome/components/ld2410/select/light_out_control_select.h create mode 100644 esphome/components/ld2410/switch/__init__.py create mode 100644 esphome/components/ld2410/switch/bluetooth_switch.cpp create mode 100644 esphome/components/ld2410/switch/bluetooth_switch.h create mode 100644 esphome/components/ld2410/switch/engineering_mode_switch.cpp create mode 100644 esphome/components/ld2410/switch/engineering_mode_switch.h create mode 100644 esphome/components/ld2410/text_sensor.py diff --git a/CODEOWNERS b/CODEOWNERS index d815252ba3..f50700c502 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -144,7 +144,7 @@ esphome/components/key_collector/* @ssieb esphome/components/key_provider/* @ssieb esphome/components/kuntze/* @ssieb esphome/components/lcd_menu/* @numo68 -esphome/components/ld2410/* @sebcaps +esphome/components/ld2410/* @regevbr @sebcaps esphome/components/ledc/* @OttoWinter esphome/components/light/* @esphome/core esphome/components/lilygo_t5_47/touchscreen/* @jesserockz diff --git a/esphome/components/ld2410/__init__.py b/esphome/components/ld2410/__init__.py index 47c4cdb0bd..2b30b65f46 100644 --- a/esphome/components/ld2410/__init__.py +++ b/esphome/components/ld2410/__init__.py @@ -1,113 +1,64 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import uart -from esphome.const import CONF_ID, CONF_TIMEOUT +from esphome.const import CONF_ID, CONF_THROTTLE, CONF_TIMEOUT, CONF_PASSWORD from esphome import automation from esphome.automation import maybe_simple_id DEPENDENCIES = ["uart"] -CODEOWNERS = ["@sebcaps"] +CODEOWNERS = ["@sebcaps", "@regevbr"] MULTI_CONF = True ld2410_ns = cg.esphome_ns.namespace("ld2410") LD2410Component = ld2410_ns.class_("LD2410Component", cg.Component, uart.UARTDevice) -LD2410Restart = ld2410_ns.class_("LD2410Restart", automation.Action) + CONF_LD2410_ID = "ld2410_id" + CONF_MAX_MOVE_DISTANCE = "max_move_distance" CONF_MAX_STILL_DISTANCE = "max_still_distance" -CONF_G0_MOVE_THRESHOLD = "g0_move_threshold" -CONF_G0_STILL_THRESHOLD = "g0_still_threshold" -CONF_G1_MOVE_THRESHOLD = "g1_move_threshold" -CONF_G1_STILL_THRESHOLD = "g1_still_threshold" -CONF_G2_MOVE_THRESHOLD = "g2_move_threshold" -CONF_G2_STILL_THRESHOLD = "g2_still_threshold" -CONF_G3_MOVE_THRESHOLD = "g3_move_threshold" -CONF_G3_STILL_THRESHOLD = "g3_still_threshold" -CONF_G4_MOVE_THRESHOLD = "g4_move_threshold" -CONF_G4_STILL_THRESHOLD = "g4_still_threshold" -CONF_G5_MOVE_THRESHOLD = "g5_move_threshold" -CONF_G5_STILL_THRESHOLD = "g5_still_threshold" -CONF_G6_MOVE_THRESHOLD = "g6_move_threshold" -CONF_G6_STILL_THRESHOLD = "g6_still_threshold" -CONF_G7_MOVE_THRESHOLD = "g7_move_threshold" -CONF_G7_STILL_THRESHOLD = "g7_still_threshold" -CONF_G8_MOVE_THRESHOLD = "g8_move_threshold" -CONF_G8_STILL_THRESHOLD = "g8_still_threshold" +CONF_STILL_THRESHOLDS = [f"g{x}_still_threshold" for x in range(9)] +CONF_MOVE_THRESHOLDS = [f"g{x}_move_threshold" for x in range(9)] -DISTANCES = [0.75, 1.5, 2.25, 3, 3.75, 4.5, 5.25, 6] +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.declare_id(LD2410Component), + cv.Optional(CONF_THROTTLE, default="1000ms"): cv.All( + cv.positive_time_period_milliseconds, + cv.Range(min=cv.TimePeriod(milliseconds=1)), + ), + cv.Optional(CONF_MAX_MOVE_DISTANCE): cv.invalid( + f"The '{CONF_MAX_MOVE_DISTANCE}' option has been moved to the '{CONF_MAX_MOVE_DISTANCE}'" + f" number component" + ), + cv.Optional(CONF_MAX_STILL_DISTANCE): cv.invalid( + f"The '{CONF_MAX_STILL_DISTANCE}' option has been moved to the '{CONF_MAX_STILL_DISTANCE}'" + f" number component" + ), + cv.Optional(CONF_TIMEOUT): cv.invalid( + f"The '{CONF_TIMEOUT}' option has been moved to the '{CONF_TIMEOUT}'" + f" number component" + ), + } +) + +for i in range(9): + CONFIG_SCHEMA = CONFIG_SCHEMA.extend( + cv.Schema( + { + cv.Optional(CONF_MOVE_THRESHOLDS[i]): cv.invalid( + f"The '{CONF_MOVE_THRESHOLDS[i]}' option has been moved to the '{CONF_MOVE_THRESHOLDS[i]}'" + f" number component" + ), + cv.Optional(CONF_STILL_THRESHOLDS[i]): cv.invalid( + f"The '{CONF_STILL_THRESHOLDS[i]}' option has been moved to the '{CONF_STILL_THRESHOLDS[i]}'" + f" number component" + ), + } + ) + ) CONFIG_SCHEMA = cv.All( - cv.Schema( - { - cv.GenerateID(): cv.declare_id(LD2410Component), - cv.Optional(CONF_MAX_MOVE_DISTANCE, default="4.5m"): cv.All( - cv.distance, cv.one_of(*DISTANCES, float=True) - ), - cv.Optional(CONF_MAX_STILL_DISTANCE, default="4.5m"): cv.All( - cv.distance, cv.one_of(*DISTANCES, float=True) - ), - cv.Optional(CONF_TIMEOUT, default="5s"): cv.All( - cv.positive_time_period_seconds, - cv.Range(max=cv.TimePeriod(seconds=32767)), - ), - cv.Optional(CONF_G0_MOVE_THRESHOLD, default=50): cv.int_range( - min=0, max=100 - ), - cv.Optional(CONF_G0_STILL_THRESHOLD, default=0): cv.int_range( - min=0, max=100 - ), - cv.Optional(CONF_G1_MOVE_THRESHOLD, default=50): cv.int_range( - min=0, max=100 - ), - cv.Optional(CONF_G1_STILL_THRESHOLD, default=0): cv.int_range( - min=0, max=100 - ), - cv.Optional(CONF_G2_MOVE_THRESHOLD, default=40): cv.int_range( - min=0, max=100 - ), - cv.Optional(CONF_G2_STILL_THRESHOLD, default=40): cv.int_range( - min=0, max=100 - ), - cv.Optional(CONF_G3_MOVE_THRESHOLD, default=40): cv.int_range( - min=0, max=100 - ), - cv.Optional(CONF_G3_STILL_THRESHOLD, default=40): cv.int_range( - min=0, max=100 - ), - cv.Optional(CONF_G4_MOVE_THRESHOLD, default=40): cv.int_range( - min=0, max=100 - ), - cv.Optional(CONF_G4_STILL_THRESHOLD, default=40): cv.int_range( - min=0, max=100 - ), - cv.Optional(CONF_G5_MOVE_THRESHOLD, default=40): cv.int_range( - min=0, max=100 - ), - cv.Optional(CONF_G5_STILL_THRESHOLD, default=40): cv.int_range( - min=0, max=100 - ), - cv.Optional(CONF_G6_MOVE_THRESHOLD, default=30): cv.int_range( - min=0, max=100 - ), - cv.Optional(CONF_G6_STILL_THRESHOLD, default=15): cv.int_range( - min=0, max=100 - ), - cv.Optional(CONF_G7_MOVE_THRESHOLD, default=30): cv.int_range( - min=0, max=100 - ), - cv.Optional(CONF_G7_STILL_THRESHOLD, default=15): cv.int_range( - min=0, max=100 - ), - cv.Optional(CONF_G8_MOVE_THRESHOLD, default=30): cv.int_range( - min=0, max=100 - ), - cv.Optional(CONF_G8_STILL_THRESHOLD, default=15): cv.int_range( - min=0, max=100 - ), - } - ) - .extend(uart.UART_DEVICE_SCHEMA) - .extend(cv.COMPONENT_SCHEMA) + CONFIG_SCHEMA.extend(uart.UART_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA) ) FINAL_VALIDATE_SCHEMA = uart.final_validate_device_schema( @@ -123,31 +74,7 @@ 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(var.set_timeout(config[CONF_TIMEOUT])) - cg.add(var.set_max_move_distance(int(config[CONF_MAX_MOVE_DISTANCE] / 0.75))) - cg.add(var.set_max_still_distance(int(config[CONF_MAX_STILL_DISTANCE] / 0.75))) - cg.add( - var.set_range_config( - config[CONF_G0_MOVE_THRESHOLD], - config[CONF_G0_STILL_THRESHOLD], - config[CONF_G1_MOVE_THRESHOLD], - config[CONF_G1_STILL_THRESHOLD], - config[CONF_G2_MOVE_THRESHOLD], - config[CONF_G2_STILL_THRESHOLD], - config[CONF_G3_MOVE_THRESHOLD], - config[CONF_G3_STILL_THRESHOLD], - config[CONF_G4_MOVE_THRESHOLD], - config[CONF_G4_STILL_THRESHOLD], - config[CONF_G5_MOVE_THRESHOLD], - config[CONF_G5_STILL_THRESHOLD], - config[CONF_G6_MOVE_THRESHOLD], - config[CONF_G6_STILL_THRESHOLD], - config[CONF_G7_MOVE_THRESHOLD], - config[CONF_G7_STILL_THRESHOLD], - config[CONF_G8_MOVE_THRESHOLD], - config[CONF_G8_STILL_THRESHOLD], - ) - ) + cg.add(var.set_throttle(config[CONF_THROTTLE])) CALIBRATION_ACTION_SCHEMA = maybe_simple_id( @@ -155,3 +82,28 @@ CALIBRATION_ACTION_SCHEMA = maybe_simple_id( cv.Required(CONF_ID): cv.use_id(LD2410Component), } ) + + +# Actions +BluetoothPasswordSetAction = ld2410_ns.class_( + "BluetoothPasswordSetAction", automation.Action +) + + +BLUETOOTH_PASSWORD_SET_SCHEMA = cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(LD2410Component), + cv.Required(CONF_PASSWORD): cv.templatable(cv.string_strict), + } +) + + +@automation.register_action( + "bluetooth_password.set", BluetoothPasswordSetAction, BLUETOOTH_PASSWORD_SET_SCHEMA +) +async def bluetooth_password_set_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_PASSWORD], args, cg.std_string) + cg.add(var.set_password(template_)) + return var diff --git a/esphome/components/ld2410/automation.h b/esphome/components/ld2410/automation.h new file mode 100644 index 0000000000..7cb9855f84 --- /dev/null +++ b/esphome/components/ld2410/automation.h @@ -0,0 +1,22 @@ +#pragma once + +#include "esphome/core/automation.h" +#include "esphome/core/component.h" +#include "ld2410.h" + +namespace esphome { +namespace ld2410 { + +template class BluetoothPasswordSetAction : public Action { + public: + explicit BluetoothPasswordSetAction(LD2410Component *ld2410_comp) : ld2410_comp_(ld2410_comp) {} + TEMPLATABLE_VALUE(std::string, password) + + void play(Ts... x) override { this->ld2410_comp_->set_bluetooth_password(this->password_.value(x...)); } + + protected: + LD2410Component *ld2410_comp_; +}; + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/binary_sensor.py b/esphome/components/ld2410/binary_sensor.py index 02f73d57b7..3057480d25 100644 --- a/esphome/components/ld2410/binary_sensor.py +++ b/esphome/components/ld2410/binary_sensor.py @@ -1,36 +1,55 @@ import esphome.codegen as cg from esphome.components import binary_sensor import esphome.config_validation as cv -from esphome.const import DEVICE_CLASS_MOTION, DEVICE_CLASS_OCCUPANCY +from esphome.const import ( + DEVICE_CLASS_MOTION, + DEVICE_CLASS_OCCUPANCY, + DEVICE_CLASS_PRESENCE, + ENTITY_CATEGORY_DIAGNOSTIC, + ICON_MOTION_SENSOR, + ICON_ACCOUNT, +) from . import CONF_LD2410_ID, LD2410Component DEPENDENCIES = ["ld2410"] CONF_HAS_TARGET = "has_target" CONF_HAS_MOVING_TARGET = "has_moving_target" CONF_HAS_STILL_TARGET = "has_still_target" +CONF_OUT_PIN_PRESENCE_STATUS = "out_pin_presence_status" CONFIG_SCHEMA = { cv.GenerateID(CONF_LD2410_ID): cv.use_id(LD2410Component), cv.Optional(CONF_HAS_TARGET): binary_sensor.binary_sensor_schema( - device_class=DEVICE_CLASS_OCCUPANCY + device_class=DEVICE_CLASS_OCCUPANCY, + icon=ICON_ACCOUNT, ), cv.Optional(CONF_HAS_MOVING_TARGET): binary_sensor.binary_sensor_schema( - device_class=DEVICE_CLASS_MOTION + device_class=DEVICE_CLASS_MOTION, + icon=ICON_MOTION_SENSOR, ), cv.Optional(CONF_HAS_STILL_TARGET): binary_sensor.binary_sensor_schema( - device_class=DEVICE_CLASS_OCCUPANCY + device_class=DEVICE_CLASS_OCCUPANCY, + icon=ICON_MOTION_SENSOR, + ), + cv.Optional(CONF_OUT_PIN_PRESENCE_STATUS): binary_sensor.binary_sensor_schema( + device_class=DEVICE_CLASS_PRESENCE, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + icon=ICON_ACCOUNT, ), } async def to_code(config): ld2410_component = await cg.get_variable(config[CONF_LD2410_ID]) - if CONF_HAS_TARGET in config: - sens = await binary_sensor.new_binary_sensor(config[CONF_HAS_TARGET]) - cg.add(ld2410_component.set_target_sensor(sens)) - if CONF_HAS_MOVING_TARGET in config: - sens = await binary_sensor.new_binary_sensor(config[CONF_HAS_MOVING_TARGET]) - cg.add(ld2410_component.set_moving_target_sensor(sens)) - if CONF_HAS_STILL_TARGET in config: - sens = await binary_sensor.new_binary_sensor(config[CONF_HAS_STILL_TARGET]) - cg.add(ld2410_component.set_still_target_sensor(sens)) + if has_target_config := config.get(CONF_HAS_TARGET): + sens = await binary_sensor.new_binary_sensor(has_target_config) + cg.add(ld2410_component.set_target_binary_sensor(sens)) + if has_moving_target_config := config.get(CONF_HAS_MOVING_TARGET): + sens = await binary_sensor.new_binary_sensor(has_moving_target_config) + cg.add(ld2410_component.set_moving_target_binary_sensor(sens)) + if has_still_target_config := config.get(CONF_HAS_STILL_TARGET): + sens = await binary_sensor.new_binary_sensor(has_still_target_config) + cg.add(ld2410_component.set_still_target_binary_sensor(sens)) + if out_pin_presence_status_config := config.get(CONF_OUT_PIN_PRESENCE_STATUS): + sens = await binary_sensor.new_binary_sensor(out_pin_presence_status_config) + cg.add(ld2410_component.set_out_pin_presence_status_binary_sensor(sens)) diff --git a/esphome/components/ld2410/button/__init__.py b/esphome/components/ld2410/button/__init__.py new file mode 100644 index 0000000000..3567114c2c --- /dev/null +++ b/esphome/components/ld2410/button/__init__.py @@ -0,0 +1,57 @@ +import esphome.codegen as cg +from esphome.components import button +import esphome.config_validation as cv +from esphome.const import ( + DEVICE_CLASS_RESTART, + ENTITY_CATEGORY_DIAGNOSTIC, + ENTITY_CATEGORY_CONFIG, + ICON_RESTART, + ICON_RESTART_ALERT, + ICON_DATABASE, +) +from .. import CONF_LD2410_ID, LD2410Component, ld2410_ns + +QueryButton = ld2410_ns.class_("QueryButton", button.Button) +ResetButton = ld2410_ns.class_("ResetButton", button.Button) +RestartButton = ld2410_ns.class_("RestartButton", button.Button) + +CONF_FACTORY_RESET = "factory_reset" +CONF_RESTART = "restart" +CONF_QUERY_PARAMS = "query_params" + +CONFIG_SCHEMA = { + cv.GenerateID(CONF_LD2410_ID): cv.use_id(LD2410Component), + cv.Optional(CONF_FACTORY_RESET): button.button_schema( + ResetButton, + device_class=DEVICE_CLASS_RESTART, + entity_category=ENTITY_CATEGORY_CONFIG, + icon=ICON_RESTART_ALERT, + ), + cv.Optional(CONF_RESTART): button.button_schema( + RestartButton, + device_class=DEVICE_CLASS_RESTART, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + icon=ICON_RESTART, + ), + cv.Optional(CONF_QUERY_PARAMS): button.button_schema( + QueryButton, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + icon=ICON_DATABASE, + ), +} + + +async def to_code(config): + ld2410_component = await cg.get_variable(config[CONF_LD2410_ID]) + if factory_reset_config := config.get(CONF_FACTORY_RESET): + b = await button.new_button(factory_reset_config) + await cg.register_parented(b, config[CONF_LD2410_ID]) + cg.add(ld2410_component.set_reset_button(b)) + if restart_config := config.get(CONF_RESTART): + b = await button.new_button(restart_config) + await cg.register_parented(b, config[CONF_LD2410_ID]) + cg.add(ld2410_component.set_restart_button(b)) + if query_params_config := config.get(CONF_QUERY_PARAMS): + b = await button.new_button(query_params_config) + await cg.register_parented(b, config[CONF_LD2410_ID]) + cg.add(ld2410_component.set_query_button(b)) diff --git a/esphome/components/ld2410/button/query_button.cpp b/esphome/components/ld2410/button/query_button.cpp new file mode 100644 index 0000000000..47ab416f5a --- /dev/null +++ b/esphome/components/ld2410/button/query_button.cpp @@ -0,0 +1,9 @@ +#include "query_button.h" + +namespace esphome { +namespace ld2410 { + +void QueryButton::press_action() { this->parent_->read_all_info(); } + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/button/query_button.h b/esphome/components/ld2410/button/query_button.h new file mode 100644 index 0000000000..c7a47e32d8 --- /dev/null +++ b/esphome/components/ld2410/button/query_button.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/button/button.h" +#include "../ld2410.h" + +namespace esphome { +namespace ld2410 { + +class QueryButton : public button::Button, public Parented { + public: + QueryButton() = default; + + protected: + void press_action() override; +}; + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/button/reset_button.cpp b/esphome/components/ld2410/button/reset_button.cpp new file mode 100644 index 0000000000..f16c5faa79 --- /dev/null +++ b/esphome/components/ld2410/button/reset_button.cpp @@ -0,0 +1,9 @@ +#include "reset_button.h" + +namespace esphome { +namespace ld2410 { + +void ResetButton::press_action() { this->parent_->factory_reset(); } + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/button/reset_button.h b/esphome/components/ld2410/button/reset_button.h new file mode 100644 index 0000000000..78dd92c9f5 --- /dev/null +++ b/esphome/components/ld2410/button/reset_button.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/button/button.h" +#include "../ld2410.h" + +namespace esphome { +namespace ld2410 { + +class ResetButton : public button::Button, public Parented { + public: + ResetButton() = default; + + protected: + void press_action() override; +}; + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/button/restart_button.cpp b/esphome/components/ld2410/button/restart_button.cpp new file mode 100644 index 0000000000..de0d36c1ef --- /dev/null +++ b/esphome/components/ld2410/button/restart_button.cpp @@ -0,0 +1,9 @@ +#include "restart_button.h" + +namespace esphome { +namespace ld2410 { + +void RestartButton::press_action() { this->parent_->restart_and_read_all_info(); } + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/button/restart_button.h b/esphome/components/ld2410/button/restart_button.h new file mode 100644 index 0000000000..d00dc05a53 --- /dev/null +++ b/esphome/components/ld2410/button/restart_button.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/button/button.h" +#include "../ld2410.h" + +namespace esphome { +namespace ld2410 { + +class RestartButton : public button::Button, public Parented { + public: + RestartButton() = default; + + protected: + void press_action() override; +}; + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/ld2410.cpp b/esphome/components/ld2410/ld2410.cpp index 8e67ba54d7..c3b57815d6 100644 --- a/esphome/components/ld2410/ld2410.cpp +++ b/esphome/components/ld2410/ld2410.cpp @@ -1,5 +1,13 @@ #include "ld2410.h" +#include +#ifdef USE_NUMBER +#include "esphome/components/number/number.h" +#endif +#ifdef USE_SENSOR +#include "esphome/components/sensor/sensor.h" +#endif + #define highbyte(val) (uint8_t)((val) >> 8) #define lowbyte(val) (uint8_t)((val) &0xff) @@ -8,48 +16,97 @@ namespace ld2410 { static const char *const TAG = "ld2410"; +LD2410Component::LD2410Component() {} + void LD2410Component::dump_config() { ESP_LOGCONFIG(TAG, "LD2410:"); #ifdef USE_BINARY_SENSOR - LOG_BINARY_SENSOR(" ", "HasTargetSensor", this->target_binary_sensor_); - LOG_BINARY_SENSOR(" ", "MovingSensor", this->moving_binary_sensor_); - LOG_BINARY_SENSOR(" ", "StillSensor", this->still_binary_sensor_); + LOG_BINARY_SENSOR(" ", "TargetBinarySensor", this->target_binary_sensor_); + LOG_BINARY_SENSOR(" ", "MovingTargetBinarySensor", this->moving_target_binary_sensor_); + LOG_BINARY_SENSOR(" ", "StillTargetBinarySensor", this->still_target_binary_sensor_); + LOG_BINARY_SENSOR(" ", "OutPinPresenceStatusBinarySensor", this->out_pin_presence_status_binary_sensor_); +#endif +#ifdef USE_SWITCH + LOG_SWITCH(" ", "EngineeringModeSwitch", this->engineering_mode_switch_); + LOG_SWITCH(" ", "BluetoothSwitch", this->bluetooth_switch_); +#endif +#ifdef USE_BUTTON + LOG_BUTTON(" ", "ResetButton", this->reset_button_); + LOG_BUTTON(" ", "RestartButton", this->restart_button_); + LOG_BUTTON(" ", "QueryButton", this->query_button_); #endif #ifdef USE_SENSOR - LOG_SENSOR(" ", "Moving Distance", this->moving_target_distance_sensor_); - LOG_SENSOR(" ", "Still Distance", this->still_target_distance_sensor_); - LOG_SENSOR(" ", "Moving Energy", this->moving_target_energy_sensor_); - LOG_SENSOR(" ", "Still Energy", this->still_target_energy_sensor_); - LOG_SENSOR(" ", "Detection Distance", this->detection_distance_sensor_); + LOG_SENSOR(" ", "LightSensor", this->light_sensor_); + LOG_SENSOR(" ", "MovingTargetDistanceSensor", this->moving_target_distance_sensor_); + LOG_SENSOR(" ", "StillTargetDistanceSensor", this->still_target_distance_sensor_); + LOG_SENSOR(" ", "MovingTargetEnergySensor", this->moving_target_energy_sensor_); + LOG_SENSOR(" ", "StillTargetEnergySensor", this->still_target_energy_sensor_); + LOG_SENSOR(" ", "DetectionDistanceSensor", this->detection_distance_sensor_); + for (sensor::Sensor *s : this->gate_still_sensors_) { + LOG_SENSOR(" ", "NthGateStillSesnsor", s); + } + for (sensor::Sensor *s : this->gate_move_sensors_) { + LOG_SENSOR(" ", "NthGateMoveSesnsor", s); + } #endif - this->set_config_mode_(true); - this->get_version_(); - this->set_config_mode_(false); - ESP_LOGCONFIG(TAG, " Firmware Version : %u.%u.%u%u%u%u", this->version_[0], this->version_[1], this->version_[2], - this->version_[3], this->version_[4], this->version_[5]); +#ifdef USE_TEXT_SENSOR + LOG_TEXT_SENSOR(" ", "VersionTextSensor", this->version_text_sensor_); + LOG_TEXT_SENSOR(" ", "MacTextSensor", this->mac_text_sensor_); +#endif +#ifdef USE_SELECT + LOG_SELECT(" ", "LightFunctionSelect", this->light_function_select_); + LOG_SELECT(" ", "OutPinLevelSelect", this->out_pin_level_select_); + LOG_SELECT(" ", "DistanceResolutionSelect", this->distance_resolution_select_); + LOG_SELECT(" ", "BaudRateSelect", this->baud_rate_select_); +#endif +#ifdef USE_NUMBER + LOG_NUMBER(" ", "LightThresholdNumber", this->light_threshold_number_); + LOG_NUMBER(" ", "MaxStillDistanceGateNumber", this->max_still_distance_gate_number_); + LOG_NUMBER(" ", "MaxMoveDistanceGateNumber", this->max_move_distance_gate_number_); + LOG_NUMBER(" ", "TimeoutNumber", this->timeout_number_); + for (number::Number *n : this->gate_still_threshold_numbers_) { + LOG_NUMBER(" ", "Still Thresholds Number", n); + } + for (number::Number *n : this->gate_move_threshold_numbers_) { + LOG_NUMBER(" ", "Move Thresholds Number", n); + } +#endif + this->read_all_info(); + ESP_LOGCONFIG(TAG, " Throttle_ : %ums", this->throttle_); + ESP_LOGCONFIG(TAG, " MAC Address : %s", const_cast(this->mac_.c_str())); + ESP_LOGCONFIG(TAG, " Firmware Version : %s", const_cast(this->version_.c_str())); } void LD2410Component::setup() { ESP_LOGCONFIG(TAG, "Setting up LD2410..."); - this->set_config_mode_(true); - this->set_max_distances_timeout_(this->max_move_distance_, this->max_still_distance_, this->timeout_); - // Configure Gates sensitivity - this->set_gate_threshold_(0, this->rg0_move_threshold_, this->rg0_still_threshold_); - this->set_gate_threshold_(1, this->rg1_move_threshold_, this->rg1_still_threshold_); - this->set_gate_threshold_(2, this->rg2_move_threshold_, this->rg2_still_threshold_); - this->set_gate_threshold_(3, this->rg3_move_threshold_, this->rg3_still_threshold_); - this->set_gate_threshold_(4, this->rg4_move_threshold_, this->rg4_still_threshold_); - this->set_gate_threshold_(5, this->rg5_move_threshold_, this->rg5_still_threshold_); - this->set_gate_threshold_(6, this->rg6_move_threshold_, this->rg6_still_threshold_); - this->set_gate_threshold_(7, this->rg7_move_threshold_, this->rg7_still_threshold_); - this->set_gate_threshold_(8, this->rg8_move_threshold_, this->rg8_still_threshold_); - this->get_version_(); - this->set_config_mode_(false); - ESP_LOGCONFIG(TAG, "Firmware Version : %u.%u.%u%u%u%u", this->version_[0], this->version_[1], this->version_[2], - this->version_[3], this->version_[4], this->version_[5]); + this->read_all_info(); + ESP_LOGCONFIG(TAG, "Mac Address : %s", const_cast(this->mac_.c_str())); + ESP_LOGCONFIG(TAG, "Firmware Version : %s", const_cast(this->version_.c_str())); ESP_LOGCONFIG(TAG, "LD2410 setup complete."); } +void LD2410Component::read_all_info() { + this->set_config_mode_(true); + this->get_version_(); + this->get_mac_(); + this->get_distance_resolution_(); + this->get_light_control_(); + this->query_parameters_(); + this->set_config_mode_(false); +#ifdef USE_SELECT + const auto baud_rate = std::to_string(this->parent_->get_baud_rate()); + if (this->baud_rate_select_ != nullptr && this->baud_rate_select_->state != baud_rate) { + this->baud_rate_select_->publish_state(baud_rate); + } +#endif +} + +void LD2410Component::restart_and_read_all_info() { + this->set_config_mode_(true); + this->restart_(); + this->set_timeout(1000, [this]() { this->read_all_info(); }); +} + void LD2410Component::loop() { const int max_line_length = 80; static uint8_t buffer[max_line_length]; @@ -59,9 +116,8 @@ void LD2410Component::loop() { } } -void LD2410Component::send_command_(uint8_t command, uint8_t *command_value, int command_value_len) { - // lastCommandSuccess->publish_state(false); - +void LD2410Component::send_command_(uint8_t command, const uint8_t *command_value, int command_value_len) { + ESP_LOGV(TAG, "Sending COMMAND %02X", command); // frame start bytes this->write_array(CMD_FRAME_HEADER, 4); // length bytes @@ -95,40 +151,43 @@ void LD2410Component::handle_periodic_data_(uint8_t *buffer, int len) { if (buffer[7] != HEAD || buffer[len - 6] != END || buffer[len - 5] != CHECK) // Check constant values return; // data head=0xAA, data end=0x55, crc=0x00 - /* - Data Type: 6th - 0x01: Engineering mode - 0x02: Normal mode - */ - // char data_type = buffer[DATA_TYPES]; - /* - Target states: 9th - 0x00 = No target - 0x01 = Moving targets - 0x02 = Still targets - 0x03 = Moving+Still targets - */ -#ifdef USE_BINARY_SENSOR - char target_state = buffer[TARGET_STATES]; - if (this->target_binary_sensor_ != nullptr) { - this->target_binary_sensor_->publish_state(target_state != 0x00); - } -#endif - /* Reduce data update rate to prevent home assistant database size grow fast */ int32_t current_millis = millis(); - if (current_millis - last_periodic_millis < 1000) + if (current_millis - last_periodic_millis_ < this->throttle_) return; - last_periodic_millis = current_millis; + last_periodic_millis_ = current_millis; -#ifdef USE_BINARY_SENSOR - if (this->moving_binary_sensor_ != nullptr) { - this->moving_binary_sensor_->publish_state(CHECK_BIT(target_state, 0)); + /* + Data Type: 7th + 0x01: Engineering mode + 0x02: Normal mode + */ + bool engineering_mode = buffer[DATA_TYPES] == 0x01; +#ifdef USE_SWITCH + if (this->engineering_mode_switch_ != nullptr && + current_millis - last_engineering_mode_change_millis_ > this->throttle_) { + this->engineering_mode_switch_->publish_state(engineering_mode); } - if (this->still_binary_sensor_ != nullptr) { - this->still_binary_sensor_->publish_state(CHECK_BIT(target_state, 1)); +#endif +#ifdef USE_BINARY_SENSOR + /* + Target states: 9th + 0x00 = No target + 0x01 = Moving targets + 0x02 = Still targets + 0x03 = Moving+Still targets + */ + char target_state = buffer[TARGET_STATES]; + if (this->target_binary_sensor_ != nullptr) { + this->target_binary_sensor_->publish_state(target_state != 0x00); + } + if (this->moving_target_binary_sensor_ != nullptr) { + this->moving_target_binary_sensor_->publish_state(CHECK_BIT(target_state, 0)); + } + if (this->still_target_binary_sensor_ != nullptr) { + this->still_target_binary_sensor_->publish_state(CHECK_BIT(target_state, 1)); } #endif /* @@ -164,26 +223,126 @@ void LD2410Component::handle_periodic_data_(uint8_t *buffer, int len) { if (this->detection_distance_sensor_->get_state() != new_detect_distance) this->detection_distance_sensor_->publish_state(new_detect_distance); } + if (engineering_mode) { + /* + Moving distance range: 18th byte + Still distance range: 19th byte + Moving enery: 20~28th bytes + */ + for (std::vector::size_type i = 0; i != this->gate_move_sensors_.size(); i++) { + sensor::Sensor *s = this->gate_move_sensors_[i]; + if (s != nullptr) { + s->publish_state(buffer[MOVING_SENSOR_START + i]); + } + } + /* + Still energy: 29~37th bytes + */ + for (std::vector::size_type i = 0; i != this->gate_still_sensors_.size(); i++) { + sensor::Sensor *s = this->gate_still_sensors_[i]; + if (s != nullptr) { + s->publish_state(buffer[STILL_SENSOR_START + i]); + } + } + /* + Light sensor: 38th bytes + */ + if (this->light_sensor_ != nullptr) { + int new_light_sensor = buffer[LIGHT_SENSOR]; + if (this->light_sensor_->get_state() != new_light_sensor) + this->light_sensor_->publish_state(new_light_sensor); + } + } else { + for (auto *s : this->gate_move_sensors_) { + if (s != nullptr && !std::isnan(s->get_state())) { + s->publish_state(NAN); + } + } + for (auto *s : this->gate_still_sensors_) { + if (s != nullptr && !std::isnan(s->get_state())) { + s->publish_state(NAN); + } + } + if (this->light_sensor_ != nullptr && !std::isnan(this->light_sensor_->get_state())) { + this->light_sensor_->publish_state(NAN); + } + } +#endif +#ifdef USE_BINARY_SENSOR + if (engineering_mode) { + if (this->out_pin_presence_status_binary_sensor_ != nullptr) { + this->out_pin_presence_status_binary_sensor_->publish_state(buffer[OUT_PIN_SENSOR] == 0x01); + } + } else { + if (this->out_pin_presence_status_binary_sensor_ != nullptr) { + this->out_pin_presence_status_binary_sensor_->publish_state(false); + } + } #endif } -void LD2410Component::handle_ack_data_(uint8_t *buffer, int len) { - ESP_LOGV(TAG, "Handling ACK DATA for COMMAND"); +const char VERSION_FMT[] = "%u.%02X.%02X%02X%02X%02X"; + +std::string format_version(uint8_t *buffer) { + std::string::size_type version_size = 256; + std::string version; + do { + version.resize(version_size + 1); + version_size = std::snprintf(&version[0], version.size(), VERSION_FMT, buffer[13], buffer[12], buffer[17], + buffer[16], buffer[15], buffer[14]); + } while (version_size + 1 > version.size()); + version.resize(version_size); + return version; +} + +const char MAC_FMT[] = "%02X:%02X:%02X:%02X:%02X:%02X"; + +const std::string UNKNOWN_MAC("unknown"); +const std::string NO_MAC("08:05:04:03:02:01"); + +std::string format_mac(uint8_t *buffer) { + std::string::size_type mac_size = 256; + std::string mac; + do { + mac.resize(mac_size + 1); + mac_size = std::snprintf(&mac[0], mac.size(), MAC_FMT, buffer[10], buffer[11], buffer[12], buffer[13], buffer[14], + buffer[15]); + } while (mac_size + 1 > mac.size()); + mac.resize(mac_size); + if (mac == NO_MAC) { + return UNKNOWN_MAC; + } + return mac; +} + +#ifdef USE_NUMBER +std::function set_number_value(number::Number *n, float value) { + float normalized_value = value * 1.0; + if (n != nullptr && (!n->has_state() || n->state != normalized_value)) { + n->state = normalized_value; + return [n, normalized_value]() { n->publish_state(normalized_value); }; + } + return []() {}; +} +#endif + +bool LD2410Component::handle_ack_data_(uint8_t *buffer, int len) { + ESP_LOGV(TAG, "Handling ACK DATA for COMMAND %02X", buffer[COMMAND]); if (len < 10) { ESP_LOGE(TAG, "Error with last command : incorrect length"); - return; + return true; } if (buffer[0] != 0xFD || buffer[1] != 0xFC || buffer[2] != 0xFB || buffer[3] != 0xFA) { // check 4 frame start bytes ESP_LOGE(TAG, "Error with last command : incorrect Header"); - return; + return true; } if (buffer[COMMAND_STATUS] != 0x01) { ESP_LOGE(TAG, "Error with last command : status != 0x01"); - return; + return true; } if (this->two_byte_to_int_(buffer[8], buffer[9]) != 0x00) { ESP_LOGE(TAG, "Error with last command , last buffer was: %u , %u", buffer[8], buffer[9]); - return; + return true; } switch (buffer[COMMAND]) { @@ -193,49 +352,127 @@ void LD2410Component::handle_ack_data_(uint8_t *buffer, int len) { case lowbyte(CMD_DISABLE_CONF): ESP_LOGV(TAG, "Handled Disabled conf command"); break; + case lowbyte(CMD_SET_BAUD_RATE): + ESP_LOGV(TAG, "Handled baud rate change command"); +#ifdef USE_SELECT + if (this->baud_rate_select_ != nullptr) { + ESP_LOGE(TAG, "Change baud rate component config to %s and reinstall", this->baud_rate_select_->state.c_str()); + } +#endif + break; case lowbyte(CMD_VERSION): - ESP_LOGV(TAG, "FW Version is: %u.%u.%u%u%u%u", buffer[13], buffer[12], buffer[17], buffer[16], buffer[15], - buffer[14]); - this->version_[0] = buffer[13]; - this->version_[1] = buffer[12]; - this->version_[2] = buffer[17]; - this->version_[3] = buffer[16]; - this->version_[4] = buffer[15]; - this->version_[5] = buffer[14]; - + this->version_ = format_version(buffer); + ESP_LOGV(TAG, "FW Version is: %s", const_cast(this->version_.c_str())); +#ifdef USE_TEXT_SENSOR + if (this->version_text_sensor_ != nullptr) { + this->version_text_sensor_->publish_state(this->version_); + } +#endif + break; + case lowbyte(CMD_QUERY_DISTANCE_RESOLUTION): { + std::string distance_resolution = + DISTANCE_RESOLUTION_INT_TO_ENUM.at(this->two_byte_to_int_(buffer[10], buffer[11])); + ESP_LOGV(TAG, "Distance resolution is: %s", const_cast(distance_resolution.c_str())); +#ifdef USE_SELECT + if (this->distance_resolution_select_ != nullptr && + this->distance_resolution_select_->state != distance_resolution) { + this->distance_resolution_select_->publish_state(distance_resolution); + } +#endif + } break; + case lowbyte(CMD_QUERY_LIGHT_CONTROL): { + this->light_function_ = LIGHT_FUNCTION_INT_TO_ENUM.at(buffer[10]); + this->light_threshold_ = buffer[11] * 1.0; + this->out_pin_level_ = OUT_PIN_LEVEL_INT_TO_ENUM.at(buffer[12]); + ESP_LOGV(TAG, "Light function is: %s", const_cast(this->light_function_.c_str())); + ESP_LOGV(TAG, "Light threshold is: %f", this->light_threshold_); + ESP_LOGV(TAG, "Out pin level is: %s", const_cast(this->out_pin_level_.c_str())); +#ifdef USE_SELECT + if (this->light_function_select_ != nullptr && this->light_function_select_->state != this->light_function_) { + this->light_function_select_->publish_state(this->light_function_); + } + if (this->out_pin_level_select_ != nullptr && this->out_pin_level_select_->state != this->out_pin_level_) { + this->out_pin_level_select_->publish_state(this->out_pin_level_); + } +#endif +#ifdef USE_NUMBER + if (this->light_threshold_number_ != nullptr && + (!this->light_threshold_number_->has_state() || + this->light_threshold_number_->state != this->light_threshold_)) { + this->light_threshold_number_->publish_state(this->light_threshold_); + } +#endif + } break; + case lowbyte(CMD_MAC): + if (len < 20) { + return false; + } + this->mac_ = format_mac(buffer); + ESP_LOGV(TAG, "MAC Address is: %s", const_cast(this->mac_.c_str())); +#ifdef USE_TEXT_SENSOR + if (this->mac_text_sensor_ != nullptr) { + this->mac_text_sensor_->publish_state(this->mac_); + } +#endif +#ifdef USE_SWITCH + if (this->bluetooth_switch_ != nullptr) { + this->bluetooth_switch_->publish_state(this->mac_ != UNKNOWN_MAC); + } +#endif break; case lowbyte(CMD_GATE_SENS): ESP_LOGV(TAG, "Handled sensitivity command"); break; + case lowbyte(CMD_BLUETOOTH): + ESP_LOGV(TAG, "Handled bluetooth command"); + break; + case lowbyte(CMD_SET_DISTANCE_RESOLUTION): + ESP_LOGV(TAG, "Handled set distance resolution command"); + break; + case lowbyte(CMD_SET_LIGHT_CONTROL): + ESP_LOGV(TAG, "Handled set light control command"); + break; + case lowbyte(CMD_BT_PASSWORD): + ESP_LOGV(TAG, "Handled set bluetooth password command"); + break; case lowbyte(CMD_QUERY): // Query parameters response { if (buffer[10] != 0xAA) - return; // value head=0xAA + return true; // value head=0xAA +#ifdef USE_NUMBER /* Moving distance range: 13th byte Still distance range: 14th byte */ - // TODO - // maxMovingDistanceRange->publish_state(buffer[12]); - // maxStillDistanceRange->publish_state(buffer[13]); + std::vector> updates; + updates.push_back(set_number_value(this->max_move_distance_gate_number_, buffer[12])); + updates.push_back(set_number_value(this->max_still_distance_gate_number_, buffer[13])); /* Moving Sensitivities: 15~23th bytes + */ + for (std::vector::size_type i = 0; i != this->gate_move_threshold_numbers_.size(); i++) { + updates.push_back(set_number_value(this->gate_move_threshold_numbers_[i], buffer[14 + i])); + } + /* Still Sensitivities: 24~32th bytes */ - for (int i = 0; i < 9; i++) { - moving_sensitivities[i] = buffer[14 + i]; - } - for (int i = 0; i < 9; i++) { - still_sensitivities[i] = buffer[23 + i]; + for (std::vector::size_type i = 0; i != this->gate_still_threshold_numbers_.size(); i++) { + updates.push_back(set_number_value(this->gate_still_threshold_numbers_[i], buffer[23 + i])); } /* None Duration: 33~34th bytes */ - // noneDuration->publish_state(this->two_byte_to_int_(buffer[32], buffer[33])); + updates.push_back(set_number_value(this->timeout_number_, this->two_byte_to_int_(buffer[32], buffer[33]))); + for (auto &update : updates) { + update(); + } +#endif } break; default: break; } + + return true; } void LD2410Component::readline_(int readch, uint8_t *buffer, int len) { @@ -256,8 +493,11 @@ void LD2410Component::readline_(int readch, uint8_t *buffer, int len) { } else if (buffer[pos - 4] == 0x04 && buffer[pos - 3] == 0x03 && buffer[pos - 2] == 0x02 && buffer[pos - 1] == 0x01) { ESP_LOGV(TAG, "Will handle ACK Data"); - this->handle_ack_data_(buffer, pos); - pos = 0; // Reset position index ready for next time + if (this->handle_ack_data_(buffer, pos)) { + pos = 0; // Reset position index ready for next time + } else { + ESP_LOGV(TAG, "ACK Data incomplete"); + } } } } @@ -269,21 +509,85 @@ void LD2410Component::set_config_mode_(bool enable) { this->send_command_(cmd, enable ? cmd_value : nullptr, 2); } +void LD2410Component::set_bluetooth(bool enable) { + this->set_config_mode_(true); + uint8_t enable_cmd_value[2] = {0x01, 0x00}; + uint8_t disable_cmd_value[2] = {0x00, 0x00}; + this->send_command_(CMD_BLUETOOTH, enable ? enable_cmd_value : disable_cmd_value, 2); + this->set_timeout(200, [this]() { this->restart_and_read_all_info(); }); +} + +void LD2410Component::set_distance_resolution(const std::string &state) { + this->set_config_mode_(true); + uint8_t cmd_value[2] = {DISTANCE_RESOLUTION_ENUM_TO_INT.at(state), 0x00}; + this->send_command_(CMD_SET_DISTANCE_RESOLUTION, cmd_value, 2); + this->set_timeout(200, [this]() { this->restart_and_read_all_info(); }); +} + +void LD2410Component::set_baud_rate(const std::string &state) { + this->set_config_mode_(true); + uint8_t cmd_value[2] = {BAUD_RATE_ENUM_TO_INT.at(state), 0x00}; + this->send_command_(CMD_SET_BAUD_RATE, cmd_value, 2); + this->set_timeout(200, [this]() { this->restart_(); }); +} + +void LD2410Component::set_bluetooth_password(const std::string &password) { + if (password.length() != 6) { + ESP_LOGE(TAG, "set_bluetooth_password(): invalid password length, must be exactly 6 chars '%s'", password.c_str()); + return; + } + this->set_config_mode_(true); + uint8_t cmd_value[6]; + std::copy(password.begin(), password.end(), std::begin(cmd_value)); + this->send_command_(CMD_BT_PASSWORD, cmd_value, 6); + this->set_config_mode_(false); +} + +void LD2410Component::set_engineering_mode(bool enable) { + this->set_config_mode_(true); + last_engineering_mode_change_millis_ = millis(); + uint8_t cmd = enable ? CMD_ENABLE_ENG : CMD_DISABLE_ENG; + this->send_command_(cmd, nullptr, 0); + this->set_config_mode_(false); +} + +void LD2410Component::factory_reset() { + this->set_config_mode_(true); + this->send_command_(CMD_RESET, nullptr, 0); + this->set_timeout(200, [this]() { this->restart_and_read_all_info(); }); +} + +void LD2410Component::restart_() { this->send_command_(CMD_RESTART, nullptr, 0); } + void LD2410Component::query_parameters_() { this->send_command_(CMD_QUERY, nullptr, 0); } void LD2410Component::get_version_() { this->send_command_(CMD_VERSION, nullptr, 0); } +void LD2410Component::get_mac_() { + uint8_t cmd_value[2] = {0x01, 0x00}; + this->send_command_(CMD_MAC, cmd_value, 2); +} +void LD2410Component::get_distance_resolution_() { this->send_command_(CMD_QUERY_DISTANCE_RESOLUTION, nullptr, 0); } -void LD2410Component::set_max_distances_timeout_(uint8_t max_moving_distance_range, uint8_t max_still_distance_range, - uint16_t timeout) { +void LD2410Component::get_light_control_() { this->send_command_(CMD_QUERY_LIGHT_CONTROL, nullptr, 0); } + +#ifdef USE_NUMBER +void LD2410Component::set_max_distances_timeout() { + if (!this->max_move_distance_gate_number_->has_state() || !this->max_still_distance_gate_number_->has_state() || + !this->timeout_number_->has_state()) { + return; + } + int max_moving_distance_gate_range = static_cast(this->max_move_distance_gate_number_->state); + int max_still_distance_gate_range = static_cast(this->max_still_distance_gate_number_->state); + int timeout = static_cast(this->timeout_number_->state); uint8_t value[18] = {0x00, 0x00, - lowbyte(max_moving_distance_range), - highbyte(max_moving_distance_range), + lowbyte(max_moving_distance_gate_range), + highbyte(max_moving_distance_gate_range), 0x00, 0x00, 0x01, 0x00, - lowbyte(max_still_distance_range), - highbyte(max_still_distance_range), + lowbyte(max_still_distance_gate_range), + highbyte(max_still_distance_gate_range), 0x00, 0x00, 0x02, @@ -292,10 +596,25 @@ void LD2410Component::set_max_distances_timeout_(uint8_t max_moving_distance_ran highbyte(timeout), 0x00, 0x00}; + this->set_config_mode_(true); this->send_command_(CMD_MAXDIST_DURATION, value, 18); + delay(50); // NOLINT this->query_parameters_(); + this->set_timeout(200, [this]() { this->restart_and_read_all_info(); }); + this->set_config_mode_(false); } -void LD2410Component::set_gate_threshold_(uint8_t gate, uint8_t motionsens, uint8_t stillsens) { + +void LD2410Component::set_gate_threshold(uint8_t gate) { + number::Number *motionsens = this->gate_move_threshold_numbers_[gate]; + number::Number *stillsens = this->gate_still_threshold_numbers_[gate]; + + if (!motionsens->has_state() || !stillsens->has_state()) { + return; + } + int motion = static_cast(motionsens->state); + int still = static_cast(stillsens->state); + + this->set_config_mode_(true); // reference // https://drive.google.com/drive/folders/1p4dhbEJA3YubyIjIIC7wwVsSo8x29Fq-?spm=a2g0o.detail.1000023.17.93465697yFwVxH // Send data: configure the motion sensitivity of distance gate 3 to 40, and the static sensitivity of 40 @@ -305,11 +624,57 @@ void LD2410Component::set_gate_threshold_(uint8_t gate, uint8_t motionsens, uint // 28 00 00 00 (value) // 02 00 (still sensitivtiy) // 28 00 00 00 (value) - uint8_t value[18] = {0x00, 0x00, lowbyte(gate), highbyte(gate), 0x00, 0x00, - 0x01, 0x00, lowbyte(motionsens), highbyte(motionsens), 0x00, 0x00, - 0x02, 0x00, lowbyte(stillsens), highbyte(stillsens), 0x00, 0x00}; + uint8_t value[18] = {0x00, 0x00, lowbyte(gate), highbyte(gate), 0x00, 0x00, + 0x01, 0x00, lowbyte(motion), highbyte(motion), 0x00, 0x00, + 0x02, 0x00, lowbyte(still), highbyte(still), 0x00, 0x00}; this->send_command_(CMD_GATE_SENS, value, 18); + delay(50); // NOLINT + this->query_parameters_(); + this->set_config_mode_(false); } +void LD2410Component::set_gate_still_threshold_number(int gate, number::Number *n) { + this->gate_still_threshold_numbers_[gate] = n; +} + +void LD2410Component::set_gate_move_threshold_number(int gate, number::Number *n) { + this->gate_move_threshold_numbers_[gate] = n; +} +#endif + +void LD2410Component::set_light_out_control() { +#ifdef USE_NUMBER + if (this->light_threshold_number_ != nullptr && this->light_threshold_number_->has_state()) { + this->light_threshold_ = this->light_threshold_number_->state; + } +#endif +#ifdef USE_SELECT + if (this->light_function_select_ != nullptr && this->light_function_select_->has_state()) { + this->light_function_ = this->light_function_select_->state; + } + if (this->out_pin_level_select_ != nullptr && this->out_pin_level_select_->has_state()) { + this->out_pin_level_ = this->out_pin_level_select_->state; + } +#endif + if (this->light_function_.empty() || this->out_pin_level_.empty() || this->light_threshold_ < 0) { + return; + } + this->set_config_mode_(true); + uint8_t light_function = LIGHT_FUNCTION_ENUM_TO_INT.at(this->light_function_); + uint8_t light_threshold = static_cast(this->light_threshold_); + uint8_t out_pin_level = OUT_PIN_LEVEL_ENUM_TO_INT.at(this->out_pin_level_); + uint8_t value[4] = {light_function, light_threshold, out_pin_level, 0x00}; + this->send_command_(CMD_SET_LIGHT_CONTROL, value, 4); + delay(50); // NOLINT + this->get_light_control_(); + this->set_timeout(200, [this]() { this->restart_and_read_all_info(); }); + this->set_config_mode_(false); +} + +#ifdef USE_SENSOR +void LD2410Component::set_gate_move_sensor(int gate, sensor::Sensor *s) { this->gate_move_sensors_[gate] = s; } +void LD2410Component::set_gate_still_sensor(int gate, sensor::Sensor *s) { this->gate_still_sensors_[gate] = s; } +#endif + } // namespace ld2410 } // namespace esphome diff --git a/esphome/components/ld2410/ld2410.h b/esphome/components/ld2410/ld2410.h index 8edb83a8d5..8084d4c33e 100644 --- a/esphome/components/ld2410/ld2410.h +++ b/esphome/components/ld2410/ld2410.h @@ -7,10 +7,27 @@ #ifdef USE_SENSOR #include "esphome/components/sensor/sensor.h" #endif +#ifdef USE_NUMBER +#include "esphome/components/number/number.h" +#endif +#ifdef USE_SWITCH +#include "esphome/components/switch/switch.h" +#endif +#ifdef USE_BUTTON +#include "esphome/components/button/button.h" +#endif +#ifdef USE_SELECT +#include "esphome/components/select/select.h" +#endif +#ifdef USE_TEXT_SENSOR +#include "esphome/components/text_sensor/text_sensor.h" +#endif #include "esphome/components/uart/uart.h" #include "esphome/core/automation.h" #include "esphome/core/helpers.h" +#include + namespace esphome { namespace ld2410 { @@ -19,10 +36,63 @@ namespace ld2410 { // Commands static const uint8_t CMD_ENABLE_CONF = 0x00FF; static const uint8_t CMD_DISABLE_CONF = 0x00FE; +static const uint8_t CMD_ENABLE_ENG = 0x0062; +static const uint8_t CMD_DISABLE_ENG = 0x0063; static const uint8_t CMD_MAXDIST_DURATION = 0x0060; static const uint8_t CMD_QUERY = 0x0061; static const uint8_t CMD_GATE_SENS = 0x0064; static const uint8_t CMD_VERSION = 0x00A0; +static const uint8_t CMD_QUERY_DISTANCE_RESOLUTION = 0x00AB; +static const uint8_t CMD_SET_DISTANCE_RESOLUTION = 0x00AA; +static const uint8_t CMD_QUERY_LIGHT_CONTROL = 0x00AE; +static const uint8_t CMD_SET_LIGHT_CONTROL = 0x00AD; +static const uint8_t CMD_SET_BAUD_RATE = 0x00A1; +static const uint8_t CMD_BT_PASSWORD = 0x00A9; +static const uint8_t CMD_MAC = 0x00A5; +static const uint8_t CMD_RESET = 0x00A2; +static const uint8_t CMD_RESTART = 0x00A3; +static const uint8_t CMD_BLUETOOTH = 0x00A4; + +enum BaudRateStructure : uint8_t { + BAUD_RATE_9600 = 1, + BAUD_RATE_19200 = 2, + BAUD_RATE_38400 = 3, + BAUD_RATE_57600 = 4, + BAUD_RATE_115200 = 5, + BAUD_RATE_230400 = 6, + BAUD_RATE_256000 = 7, + BAUD_RATE_460800 = 8 +}; + +static const std::map BAUD_RATE_ENUM_TO_INT{ + {"9600", BAUD_RATE_9600}, {"19200", BAUD_RATE_19200}, {"38400", BAUD_RATE_38400}, + {"57600", BAUD_RATE_57600}, {"115200", BAUD_RATE_115200}, {"230400", BAUD_RATE_230400}, + {"256000", BAUD_RATE_256000}, {"460800", BAUD_RATE_460800}}; + +enum DistanceResolutionStructure : uint8_t { DISTANCE_RESOLUTION_0_2 = 0x01, DISTANCE_RESOLUTION_0_75 = 0x00 }; + +static const std::map DISTANCE_RESOLUTION_ENUM_TO_INT{{"0.2m", DISTANCE_RESOLUTION_0_2}, + {"0.75m", DISTANCE_RESOLUTION_0_75}}; +static const std::map DISTANCE_RESOLUTION_INT_TO_ENUM{{DISTANCE_RESOLUTION_0_2, "0.2m"}, + {DISTANCE_RESOLUTION_0_75, "0.75m"}}; + +enum LightFunctionStructure : uint8_t { + LIGHT_FUNCTION_OFF = 0x00, + LIGHT_FUNCTION_BELOW = 0x01, + LIGHT_FUNCTION_ABOVE = 0x02 +}; + +static const std::map LIGHT_FUNCTION_ENUM_TO_INT{ + {"off", LIGHT_FUNCTION_OFF}, {"below", LIGHT_FUNCTION_BELOW}, {"above", LIGHT_FUNCTION_ABOVE}}; +static const std::map LIGHT_FUNCTION_INT_TO_ENUM{ + {LIGHT_FUNCTION_OFF, "off"}, {LIGHT_FUNCTION_BELOW, "below"}, {LIGHT_FUNCTION_ABOVE, "above"}}; + +enum OutPinLevelStructure : uint8_t { OUT_PIN_LEVEL_LOW = 0x00, OUT_PIN_LEVEL_HIGH = 0x01 }; + +static const std::map OUT_PIN_LEVEL_ENUM_TO_INT{{"low", OUT_PIN_LEVEL_LOW}, + {"high", OUT_PIN_LEVEL_HIGH}}; +static const std::map OUT_PIN_LEVEL_INT_TO_ENUM{{OUT_PIN_LEVEL_LOW, "low"}, + {OUT_PIN_LEVEL_HIGH, "high"}}; // Commands values static const uint8_t CMD_MAX_MOVE_VALUE = 0x0000; @@ -44,7 +114,7 @@ Target states: 9th byte Detect distance: 16~17th bytes */ enum PeriodicDataStructure : uint8_t { - DATA_TYPES = 5, + DATA_TYPES = 6, TARGET_STATES = 8, MOVING_TARGET_LOW = 9, MOVING_TARGET_HIGH = 10, @@ -54,6 +124,10 @@ enum PeriodicDataStructure : uint8_t { STILL_ENERGY = 14, DETECT_DISTANCE_LOW = 15, DETECT_DISTANCE_HIGH = 16, + MOVING_SENSOR_START = 19, + STILL_SENSOR_START = 28, + LIGHT_SENSOR = 37, + OUT_PIN_SENSOR = 38, }; enum PeriodicDataValue : uint8_t { HEAD = 0XAA, END = 0x55, CHECK = 0x00 }; @@ -66,80 +140,97 @@ class LD2410Component : public Component, public uart::UARTDevice { SUB_SENSOR(still_target_distance) SUB_SENSOR(moving_target_energy) SUB_SENSOR(still_target_energy) + SUB_SENSOR(light) SUB_SENSOR(detection_distance) #endif +#ifdef USE_BINARY_SENSOR + SUB_BINARY_SENSOR(target) + SUB_BINARY_SENSOR(moving_target) + SUB_BINARY_SENSOR(still_target) + SUB_BINARY_SENSOR(out_pin_presence_status) +#endif +#ifdef USE_TEXT_SENSOR + SUB_TEXT_SENSOR(version) + SUB_TEXT_SENSOR(mac) +#endif +#ifdef USE_SELECT + SUB_SELECT(distance_resolution) + SUB_SELECT(baud_rate) + SUB_SELECT(light_function) + SUB_SELECT(out_pin_level) +#endif +#ifdef USE_SWITCH + SUB_SWITCH(engineering_mode) + SUB_SWITCH(bluetooth) +#endif +#ifdef USE_BUTTON + SUB_BUTTON(reset) + SUB_BUTTON(restart) + SUB_BUTTON(query) +#endif +#ifdef USE_NUMBER + SUB_NUMBER(max_still_distance_gate) + SUB_NUMBER(max_move_distance_gate) + SUB_NUMBER(timeout) + SUB_NUMBER(light_threshold) +#endif public: + LD2410Component(); void setup() override; void dump_config() override; void loop() override; - -#ifdef USE_BINARY_SENSOR - void set_target_sensor(binary_sensor::BinarySensor *sens) { this->target_binary_sensor_ = sens; }; - void set_moving_target_sensor(binary_sensor::BinarySensor *sens) { this->moving_binary_sensor_ = sens; }; - void set_still_target_sensor(binary_sensor::BinarySensor *sens) { this->still_binary_sensor_ = sens; }; + void set_light_out_control(); +#ifdef USE_NUMBER + void set_gate_still_threshold_number(int gate, number::Number *n); + void set_gate_move_threshold_number(int gate, number::Number *n); + void set_max_distances_timeout(); + void set_gate_threshold(uint8_t gate); #endif - - void set_timeout(uint16_t value) { this->timeout_ = value; }; - void set_max_move_distance(uint8_t value) { this->max_move_distance_ = value; }; - void set_max_still_distance(uint8_t value) { this->max_still_distance_ = value; }; - void set_range_config(int rg0_move, int rg0_still, int rg1_move, int rg1_still, int rg2_move, int rg2_still, - int rg3_move, int rg3_still, int rg4_move, int rg4_still, int rg5_move, int rg5_still, - int rg6_move, int rg6_still, int rg7_move, int rg7_still, int rg8_move, int rg8_still) { - this->rg0_move_threshold_ = rg0_move; - this->rg0_still_threshold_ = rg0_still; - this->rg1_move_threshold_ = rg1_move; - this->rg1_still_threshold_ = rg1_still; - this->rg2_move_threshold_ = rg2_move; - this->rg2_still_threshold_ = rg2_still; - this->rg3_move_threshold_ = rg3_move; - this->rg3_still_threshold_ = rg3_still; - this->rg4_move_threshold_ = rg4_move; - this->rg4_still_threshold_ = rg4_still; - this->rg5_move_threshold_ = rg5_move; - this->rg5_still_threshold_ = rg5_still; - this->rg6_move_threshold_ = rg6_move; - this->rg6_still_threshold_ = rg6_still; - this->rg7_move_threshold_ = rg7_move; - this->rg7_still_threshold_ = rg7_still; - this->rg8_move_threshold_ = rg8_move; - this->rg8_still_threshold_ = rg8_still; - }; - int moving_sensitivities[9] = {0}; - int still_sensitivities[9] = {0}; - - int32_t last_periodic_millis = millis(); +#ifdef USE_SENSOR + void set_gate_move_sensor(int gate, sensor::Sensor *s); + void set_gate_still_sensor(int gate, sensor::Sensor *s); +#endif + void set_throttle(uint16_t value) { this->throttle_ = value; }; + void set_bluetooth_password(const std::string &password); + void set_engineering_mode(bool enable); + void read_all_info(); + void restart_and_read_all_info(); + void set_bluetooth(bool enable); + void set_distance_resolution(const std::string &state); + void set_baud_rate(const std::string &state); + void factory_reset(); protected: -#ifdef USE_BINARY_SENSOR - binary_sensor::BinarySensor *target_binary_sensor_{nullptr}; - binary_sensor::BinarySensor *moving_binary_sensor_{nullptr}; - binary_sensor::BinarySensor *still_binary_sensor_{nullptr}; -#endif - - std::vector rx_buffer_; int two_byte_to_int_(char firstbyte, char secondbyte) { return (int16_t) (secondbyte << 8) + firstbyte; } - void send_command_(uint8_t command_str, uint8_t *command_value, int command_value_len); - - void set_max_distances_timeout_(uint8_t max_moving_distance_range, uint8_t max_still_distance_range, - uint16_t timeout); - void set_gate_threshold_(uint8_t gate, uint8_t motionsens, uint8_t stillsens); + void send_command_(uint8_t command_str, const uint8_t *command_value, int command_value_len); void set_config_mode_(bool enable); void handle_periodic_data_(uint8_t *buffer, int len); - void handle_ack_data_(uint8_t *buffer, int len); + bool handle_ack_data_(uint8_t *buffer, int len); void readline_(int readch, uint8_t *buffer, int len); void query_parameters_(); void get_version_(); + void get_mac_(); + void get_distance_resolution_(); + void get_light_control_(); + void restart_(); - uint16_t timeout_; - uint8_t max_move_distance_; - uint8_t max_still_distance_; - - uint8_t version_[6]; - uint8_t rg0_move_threshold_, rg0_still_threshold_, rg1_move_threshold_, rg1_still_threshold_, rg2_move_threshold_, - rg2_still_threshold_, rg3_move_threshold_, rg3_still_threshold_, rg4_move_threshold_, rg4_still_threshold_, - rg5_move_threshold_, rg5_still_threshold_, rg6_move_threshold_, rg6_still_threshold_, rg7_move_threshold_, - rg7_still_threshold_, rg8_move_threshold_, rg8_still_threshold_; + int32_t last_periodic_millis_ = millis(); + int32_t last_engineering_mode_change_millis_ = millis(); + uint16_t throttle_; + std::string version_; + std::string mac_; + std::string out_pin_level_; + std::string light_function_; + float light_threshold_ = -1; +#ifdef USE_NUMBER + std::vector gate_still_threshold_numbers_ = std::vector(9); + std::vector gate_move_threshold_numbers_ = std::vector(9); +#endif +#ifdef USE_SENSOR + std::vector gate_still_sensors_ = std::vector(9); + std::vector gate_move_sensors_ = std::vector(9); +#endif }; } // namespace ld2410 diff --git a/esphome/components/ld2410/number/__init__.py b/esphome/components/ld2410/number/__init__.py new file mode 100644 index 0000000000..557b226dfe --- /dev/null +++ b/esphome/components/ld2410/number/__init__.py @@ -0,0 +1,128 @@ +import esphome.codegen as cg +from esphome.components import number +import esphome.config_validation as cv +from esphome.const import ( + CONF_ID, + CONF_TIMEOUT, + DEVICE_CLASS_DISTANCE, + DEVICE_CLASS_SIGNAL_STRENGTH, + DEVICE_CLASS_ILLUMINANCE, + UNIT_SECOND, + UNIT_PERCENT, + ENTITY_CATEGORY_CONFIG, + ICON_MOTION_SENSOR, + ICON_TIMELAPSE, + ICON_LIGHTBULB, +) +from .. import CONF_LD2410_ID, LD2410Component, ld2410_ns + +GateThresholdNumber = ld2410_ns.class_("GateThresholdNumber", number.Number) +LightThresholdNumber = ld2410_ns.class_("LightThresholdNumber", number.Number) +MaxDistanceTimeoutNumber = ld2410_ns.class_("MaxDistanceTimeoutNumber", number.Number) + +CONF_MAX_MOVE_DISTANCE_GATE = "max_move_distance_gate" +CONF_MAX_STILL_DISTANCE_GATE = "max_still_distance_gate" +CONF_LIGHT_THRESHOLD = "light_threshold" +CONF_STILL_THRESHOLD = "still_threshold" +CONF_MOVE_THRESHOLD = "move_threshold" + +TIMEOUT_GROUP = "timeout" + +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(CONF_LD2410_ID): cv.use_id(LD2410Component), + cv.Inclusive(CONF_TIMEOUT, TIMEOUT_GROUP): number.number_schema( + MaxDistanceTimeoutNumber, + unit_of_measurement=UNIT_SECOND, + entity_category=ENTITY_CATEGORY_CONFIG, + icon=ICON_TIMELAPSE, + ), + cv.Inclusive(CONF_MAX_MOVE_DISTANCE_GATE, TIMEOUT_GROUP): number.number_schema( + MaxDistanceTimeoutNumber, + device_class=DEVICE_CLASS_DISTANCE, + entity_category=ENTITY_CATEGORY_CONFIG, + icon=ICON_MOTION_SENSOR, + ), + cv.Inclusive(CONF_MAX_STILL_DISTANCE_GATE, TIMEOUT_GROUP): number.number_schema( + MaxDistanceTimeoutNumber, + device_class=DEVICE_CLASS_DISTANCE, + entity_category=ENTITY_CATEGORY_CONFIG, + icon=ICON_MOTION_SENSOR, + ), + cv.Optional(CONF_LIGHT_THRESHOLD): number.number_schema( + LightThresholdNumber, + device_class=DEVICE_CLASS_ILLUMINANCE, + entity_category=ENTITY_CATEGORY_CONFIG, + icon=ICON_LIGHTBULB, + ), + } +) + +CONFIG_SCHEMA = CONFIG_SCHEMA.extend( + { + cv.Optional(f"g{x}"): cv.Schema( + { + cv.Required(CONF_MOVE_THRESHOLD): number.number_schema( + GateThresholdNumber, + device_class=DEVICE_CLASS_SIGNAL_STRENGTH, + unit_of_measurement=UNIT_PERCENT, + entity_category=ENTITY_CATEGORY_CONFIG, + icon=ICON_MOTION_SENSOR, + ), + cv.Required(CONF_STILL_THRESHOLD): number.number_schema( + GateThresholdNumber, + device_class=DEVICE_CLASS_SIGNAL_STRENGTH, + unit_of_measurement=UNIT_PERCENT, + entity_category=ENTITY_CATEGORY_CONFIG, + icon=ICON_MOTION_SENSOR, + ), + } + ) + for x in range(9) + } +) + + +async def to_code(config): + ld2410_component = await cg.get_variable(config[CONF_LD2410_ID]) + if timeout_config := config.get(CONF_TIMEOUT): + n = await number.new_number( + timeout_config, min_value=0, max_value=65535, step=1 + ) + await cg.register_parented(n, config[CONF_LD2410_ID]) + cg.add(ld2410_component.set_timeout_number(n)) + if max_move_distance_gate_config := config.get(CONF_MAX_MOVE_DISTANCE_GATE): + n = await number.new_number( + max_move_distance_gate_config, min_value=2, max_value=8, step=1 + ) + await cg.register_parented(n, config[CONF_LD2410_ID]) + cg.add(ld2410_component.set_max_move_distance_gate_number(n)) + if max_still_distance_gate_config := config.get(CONF_MAX_STILL_DISTANCE_GATE): + n = await number.new_number( + max_still_distance_gate_config, min_value=2, max_value=8, step=1 + ) + await cg.register_parented(n, config[CONF_LD2410_ID]) + cg.add(ld2410_component.set_max_still_distance_gate_number(n)) + if light_threshold_config := config.get(CONF_LIGHT_THRESHOLD): + n = await number.new_number( + light_threshold_config, min_value=0, max_value=255, step=1 + ) + await cg.register_parented(n, config[CONF_LD2410_ID]) + cg.add(ld2410_component.set_light_threshold_number(n)) + for x in range(9): + if gate_conf := config.get(f"g{x}"): + move_config = gate_conf[CONF_MOVE_THRESHOLD] + n = cg.new_Pvariable(move_config[CONF_ID], x) + await number.register_number( + n, move_config, min_value=0, max_value=100, step=1 + ) + await cg.register_parented(n, config[CONF_LD2410_ID]) + cg.add(ld2410_component.set_gate_move_threshold_number(x, n)) + + still_config = gate_conf[CONF_STILL_THRESHOLD] + n = cg.new_Pvariable(still_config[CONF_ID], x) + await number.register_number( + n, still_config, min_value=0, max_value=100, step=1 + ) + await cg.register_parented(n, config[CONF_LD2410_ID]) + cg.add(ld2410_component.set_gate_still_threshold_number(x, n)) diff --git a/esphome/components/ld2410/number/gate_threshold_number.cpp b/esphome/components/ld2410/number/gate_threshold_number.cpp new file mode 100644 index 0000000000..5d040554d7 --- /dev/null +++ b/esphome/components/ld2410/number/gate_threshold_number.cpp @@ -0,0 +1,14 @@ +#include "gate_threshold_number.h" + +namespace esphome { +namespace ld2410 { + +GateThresholdNumber::GateThresholdNumber(uint8_t gate) : gate_(gate) {} + +void GateThresholdNumber::control(float value) { + this->publish_state(value); + this->parent_->set_gate_threshold(this->gate_); +} + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/number/gate_threshold_number.h b/esphome/components/ld2410/number/gate_threshold_number.h new file mode 100644 index 0000000000..2806ecce63 --- /dev/null +++ b/esphome/components/ld2410/number/gate_threshold_number.h @@ -0,0 +1,19 @@ +#pragma once + +#include "esphome/components/number/number.h" +#include "../ld2410.h" + +namespace esphome { +namespace ld2410 { + +class GateThresholdNumber : public number::Number, public Parented { + public: + GateThresholdNumber(uint8_t gate); + + protected: + uint8_t gate_; + void control(float value) override; +}; + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/number/light_threshold_number.cpp b/esphome/components/ld2410/number/light_threshold_number.cpp new file mode 100644 index 0000000000..0ff35782cd --- /dev/null +++ b/esphome/components/ld2410/number/light_threshold_number.cpp @@ -0,0 +1,12 @@ +#include "light_threshold_number.h" + +namespace esphome { +namespace ld2410 { + +void LightThresholdNumber::control(float value) { + this->publish_state(value); + this->parent_->set_light_out_control(); +} + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/number/light_threshold_number.h b/esphome/components/ld2410/number/light_threshold_number.h new file mode 100644 index 0000000000..8f014373c0 --- /dev/null +++ b/esphome/components/ld2410/number/light_threshold_number.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/number/number.h" +#include "../ld2410.h" + +namespace esphome { +namespace ld2410 { + +class LightThresholdNumber : public number::Number, public Parented { + public: + LightThresholdNumber() = default; + + protected: + void control(float value) override; +}; + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/number/max_distance_timeout_number.cpp b/esphome/components/ld2410/number/max_distance_timeout_number.cpp new file mode 100644 index 0000000000..8a946f7ea9 --- /dev/null +++ b/esphome/components/ld2410/number/max_distance_timeout_number.cpp @@ -0,0 +1,12 @@ +#include "max_distance_timeout_number.h" + +namespace esphome { +namespace ld2410 { + +void MaxDistanceTimeoutNumber::control(float value) { + this->publish_state(value); + this->parent_->set_max_distances_timeout(); +} + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/number/max_distance_timeout_number.h b/esphome/components/ld2410/number/max_distance_timeout_number.h new file mode 100644 index 0000000000..7d91b4b5fe --- /dev/null +++ b/esphome/components/ld2410/number/max_distance_timeout_number.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/number/number.h" +#include "../ld2410.h" + +namespace esphome { +namespace ld2410 { + +class MaxDistanceTimeoutNumber : public number::Number, public Parented { + public: + MaxDistanceTimeoutNumber() = default; + + protected: + void control(float value) override; +}; + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/select/__init__.py b/esphome/components/ld2410/select/__init__.py new file mode 100644 index 0000000000..6c34a85ac6 --- /dev/null +++ b/esphome/components/ld2410/select/__init__.py @@ -0,0 +1,81 @@ +import esphome.codegen as cg +from esphome.components import select +import esphome.config_validation as cv +from esphome.const import ( + ENTITY_CATEGORY_CONFIG, + CONF_BAUD_RATE, + ICON_THERMOMETER, + ICON_SCALE, + ICON_LIGHTBULB, + ICON_RULER, +) +from .. import CONF_LD2410_ID, LD2410Component, ld2410_ns + +BaudRateSelect = ld2410_ns.class_("BaudRateSelect", select.Select) +DistanceResolutionSelect = ld2410_ns.class_("DistanceResolutionSelect", select.Select) +LightOutControlSelect = ld2410_ns.class_("LightOutControlSelect", select.Select) + +CONF_DISTANCE_RESOLUTION = "distance_resolution" +CONF_LIGHT_FUNCTION = "light_function" +CONF_OUT_PIN_LEVEL = "out_pin_level" + + +CONFIG_SCHEMA = { + cv.GenerateID(CONF_LD2410_ID): cv.use_id(LD2410Component), + cv.Optional(CONF_DISTANCE_RESOLUTION): select.select_schema( + DistanceResolutionSelect, + entity_category=ENTITY_CATEGORY_CONFIG, + icon=ICON_RULER, + ), + cv.Optional(CONF_LIGHT_FUNCTION): select.select_schema( + LightOutControlSelect, + entity_category=ENTITY_CATEGORY_CONFIG, + icon=ICON_LIGHTBULB, + ), + cv.Optional(CONF_OUT_PIN_LEVEL): select.select_schema( + LightOutControlSelect, + entity_category=ENTITY_CATEGORY_CONFIG, + icon=ICON_SCALE, + ), + cv.Optional(CONF_BAUD_RATE): select.select_schema( + BaudRateSelect, + entity_category=ENTITY_CATEGORY_CONFIG, + icon=ICON_THERMOMETER, + ), +} + + +async def to_code(config): + ld2410_component = await cg.get_variable(config[CONF_LD2410_ID]) + if distance_resolution_config := config.get(CONF_DISTANCE_RESOLUTION): + s = await select.new_select( + distance_resolution_config, options=["0.2m", "0.75m"] + ) + await cg.register_parented(s, config[CONF_LD2410_ID]) + cg.add(ld2410_component.set_distance_resolution_select(s)) + if out_pin_level_config := config.get(CONF_OUT_PIN_LEVEL): + s = await select.new_select(out_pin_level_config, options=["low", "high"]) + await cg.register_parented(s, config[CONF_LD2410_ID]) + cg.add(ld2410_component.set_out_pin_level_select(s)) + if light_function_config := config.get(CONF_LIGHT_FUNCTION): + s = await select.new_select( + light_function_config, options=["off", "below", "above"] + ) + await cg.register_parented(s, config[CONF_LD2410_ID]) + cg.add(ld2410_component.set_light_function_select(s)) + if baud_rate_config := config.get(CONF_BAUD_RATE): + s = await select.new_select( + baud_rate_config, + options=[ + "9600", + "19200", + "38400", + "57600", + "115200", + "230400", + "256000", + "460800", + ], + ) + await cg.register_parented(s, config[CONF_LD2410_ID]) + cg.add(ld2410_component.set_baud_rate_select(s)) diff --git a/esphome/components/ld2410/select/baud_rate_select.cpp b/esphome/components/ld2410/select/baud_rate_select.cpp new file mode 100644 index 0000000000..f4e0b90e2e --- /dev/null +++ b/esphome/components/ld2410/select/baud_rate_select.cpp @@ -0,0 +1,12 @@ +#include "baud_rate_select.h" + +namespace esphome { +namespace ld2410 { + +void BaudRateSelect::control(const std::string &value) { + this->publish_state(value); + this->parent_->set_baud_rate(state); +} + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/select/baud_rate_select.h b/esphome/components/ld2410/select/baud_rate_select.h new file mode 100644 index 0000000000..3827b6a48a --- /dev/null +++ b/esphome/components/ld2410/select/baud_rate_select.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/select/select.h" +#include "../ld2410.h" + +namespace esphome { +namespace ld2410 { + +class BaudRateSelect : public select::Select, public Parented { + public: + BaudRateSelect() = default; + + protected: + void control(const std::string &value) override; +}; + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/select/distance_resolution_select.cpp b/esphome/components/ld2410/select/distance_resolution_select.cpp new file mode 100644 index 0000000000..eef34bda63 --- /dev/null +++ b/esphome/components/ld2410/select/distance_resolution_select.cpp @@ -0,0 +1,12 @@ +#include "distance_resolution_select.h" + +namespace esphome { +namespace ld2410 { + +void DistanceResolutionSelect::control(const std::string &value) { + this->publish_state(value); + this->parent_->set_distance_resolution(state); +} + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/select/distance_resolution_select.h b/esphome/components/ld2410/select/distance_resolution_select.h new file mode 100644 index 0000000000..d6affb1020 --- /dev/null +++ b/esphome/components/ld2410/select/distance_resolution_select.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/select/select.h" +#include "../ld2410.h" + +namespace esphome { +namespace ld2410 { + +class DistanceResolutionSelect : public select::Select, public Parented { + public: + DistanceResolutionSelect() = default; + + protected: + void control(const std::string &value) override; +}; + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/select/light_out_control_select.cpp b/esphome/components/ld2410/select/light_out_control_select.cpp new file mode 100644 index 0000000000..ac23248a64 --- /dev/null +++ b/esphome/components/ld2410/select/light_out_control_select.cpp @@ -0,0 +1,12 @@ +#include "light_out_control_select.h" + +namespace esphome { +namespace ld2410 { + +void LightOutControlSelect::control(const std::string &value) { + this->publish_state(value); + this->parent_->set_light_out_control(); +} + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/select/light_out_control_select.h b/esphome/components/ld2410/select/light_out_control_select.h new file mode 100644 index 0000000000..5d72e1774e --- /dev/null +++ b/esphome/components/ld2410/select/light_out_control_select.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/select/select.h" +#include "../ld2410.h" + +namespace esphome { +namespace ld2410 { + +class LightOutControlSelect : public select::Select, public Parented { + public: + LightOutControlSelect() = default; + + protected: + void control(const std::string &value) override; +}; + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/sensor.py b/esphome/components/ld2410/sensor.py index b941263134..83361db58a 100644 --- a/esphome/components/ld2410/sensor.py +++ b/esphome/components/ld2410/sensor.py @@ -3,9 +3,15 @@ from esphome.components import sensor import esphome.config_validation as cv from esphome.const import ( DEVICE_CLASS_DISTANCE, - DEVICE_CLASS_ENERGY, UNIT_CENTIMETER, UNIT_PERCENT, + CONF_LIGHT, + DEVICE_CLASS_ILLUMINANCE, + ENTITY_CATEGORY_DIAGNOSTIC, + ICON_SIGNAL, + ICON_FLASH, + ICON_MOTION_SENSOR, + ICON_LIGHTBULB, ) from . import CONF_LD2410_ID, LD2410Component @@ -15,41 +21,88 @@ CONF_STILL_DISTANCE = "still_distance" CONF_MOVING_ENERGY = "moving_energy" CONF_STILL_ENERGY = "still_energy" CONF_DETECTION_DISTANCE = "detection_distance" +CONF_MOVE_ENERGY = "move_energy" -CONFIG_SCHEMA = { - cv.GenerateID(CONF_LD2410_ID): cv.use_id(LD2410Component), - cv.Optional(CONF_MOVING_DISTANCE): sensor.sensor_schema( - device_class=DEVICE_CLASS_DISTANCE, unit_of_measurement=UNIT_CENTIMETER - ), - cv.Optional(CONF_STILL_DISTANCE): sensor.sensor_schema( - device_class=DEVICE_CLASS_DISTANCE, unit_of_measurement=UNIT_CENTIMETER - ), - cv.Optional(CONF_MOVING_ENERGY): sensor.sensor_schema( - device_class=DEVICE_CLASS_ENERGY, unit_of_measurement=UNIT_PERCENT - ), - cv.Optional(CONF_STILL_ENERGY): sensor.sensor_schema( - device_class=DEVICE_CLASS_ENERGY, unit_of_measurement=UNIT_PERCENT - ), - cv.Optional(CONF_DETECTION_DISTANCE): sensor.sensor_schema( - device_class=DEVICE_CLASS_DISTANCE, unit_of_measurement=UNIT_CENTIMETER - ), -} +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(CONF_LD2410_ID): cv.use_id(LD2410Component), + cv.Optional(CONF_MOVING_DISTANCE): sensor.sensor_schema( + device_class=DEVICE_CLASS_DISTANCE, + unit_of_measurement=UNIT_CENTIMETER, + icon=ICON_SIGNAL, + ), + cv.Optional(CONF_STILL_DISTANCE): sensor.sensor_schema( + device_class=DEVICE_CLASS_DISTANCE, + unit_of_measurement=UNIT_CENTIMETER, + icon=ICON_SIGNAL, + ), + cv.Optional(CONF_MOVING_ENERGY): sensor.sensor_schema( + unit_of_measurement=UNIT_PERCENT, + icon=ICON_MOTION_SENSOR, + ), + cv.Optional(CONF_STILL_ENERGY): sensor.sensor_schema( + unit_of_measurement=UNIT_PERCENT, + icon=ICON_FLASH, + ), + cv.Optional(CONF_LIGHT): sensor.sensor_schema( + device_class=DEVICE_CLASS_ILLUMINANCE, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + icon=ICON_LIGHTBULB, + ), + cv.Optional(CONF_DETECTION_DISTANCE): sensor.sensor_schema( + device_class=DEVICE_CLASS_DISTANCE, + unit_of_measurement=UNIT_CENTIMETER, + icon=ICON_SIGNAL, + ), + } +) + +CONFIG_SCHEMA = CONFIG_SCHEMA.extend( + { + cv.Optional(f"g{x}"): cv.Schema( + { + cv.Optional(CONF_MOVE_ENERGY): sensor.sensor_schema( + unit_of_measurement=UNIT_PERCENT, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + icon=ICON_MOTION_SENSOR, + ), + cv.Optional(CONF_STILL_ENERGY): sensor.sensor_schema( + unit_of_measurement=UNIT_PERCENT, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + icon=ICON_FLASH, + ), + } + ) + for x in range(9) + } +) async def to_code(config): ld2410_component = await cg.get_variable(config[CONF_LD2410_ID]) - if CONF_MOVING_DISTANCE in config: - sens = await sensor.new_sensor(config[CONF_MOVING_DISTANCE]) + if moving_distance_config := config.get(CONF_MOVING_DISTANCE): + sens = await sensor.new_sensor(moving_distance_config) cg.add(ld2410_component.set_moving_target_distance_sensor(sens)) - if CONF_STILL_DISTANCE in config: - sens = await sensor.new_sensor(config[CONF_STILL_DISTANCE]) + if still_distance_config := config.get(CONF_STILL_DISTANCE): + sens = await sensor.new_sensor(still_distance_config) cg.add(ld2410_component.set_still_target_distance_sensor(sens)) - if CONF_MOVING_ENERGY in config: - sens = await sensor.new_sensor(config[CONF_MOVING_ENERGY]) + if moving_energy_config := config.get(CONF_MOVING_ENERGY): + sens = await sensor.new_sensor(moving_energy_config) cg.add(ld2410_component.set_moving_target_energy_sensor(sens)) - if CONF_STILL_ENERGY in config: - sens = await sensor.new_sensor(config[CONF_STILL_ENERGY]) + if still_energy_config := config.get(CONF_STILL_ENERGY): + sens = await sensor.new_sensor(still_energy_config) cg.add(ld2410_component.set_still_target_energy_sensor(sens)) - if CONF_DETECTION_DISTANCE in config: - sens = await sensor.new_sensor(config[CONF_DETECTION_DISTANCE]) + if light_config := config.get(CONF_LIGHT): + sens = await sensor.new_sensor(light_config) + cg.add(ld2410_component.set_light_sensor(sens)) + if detection_distance_config := config.get(CONF_DETECTION_DISTANCE): + sens = await sensor.new_sensor(detection_distance_config) cg.add(ld2410_component.set_detection_distance_sensor(sens)) + for x in range(9): + if gate_conf := config.get(f"g{x}"): + if move_config := gate_conf.get(CONF_MOVE_ENERGY): + sens = await sensor.new_sensor(move_config) + cg.add(ld2410_component.set_gate_move_sensor(x, sens)) + if still_config := gate_conf.get(CONF_STILL_ENERGY): + sens = await sensor.new_sensor(still_config) + cg.add(ld2410_component.set_gate_still_sensor(x, sens)) diff --git a/esphome/components/ld2410/switch/__init__.py b/esphome/components/ld2410/switch/__init__.py new file mode 100644 index 0000000000..096cb5f67a --- /dev/null +++ b/esphome/components/ld2410/switch/__init__.py @@ -0,0 +1,44 @@ +import esphome.codegen as cg +from esphome.components import switch +import esphome.config_validation as cv +from esphome.const import ( + DEVICE_CLASS_SWITCH, + ICON_BLUETOOTH, + ENTITY_CATEGORY_CONFIG, + ICON_PULSE, +) +from .. import CONF_LD2410_ID, LD2410Component, ld2410_ns + +BluetoothSwitch = ld2410_ns.class_("BluetoothSwitch", switch.Switch) +EngineeringModeSwitch = ld2410_ns.class_("EngineeringModeSwitch", switch.Switch) + +CONF_ENGINEERING_MODE = "engineering_mode" +CONF_BLUETOOTH = "bluetooth" + +CONFIG_SCHEMA = { + cv.GenerateID(CONF_LD2410_ID): cv.use_id(LD2410Component), + cv.Optional(CONF_ENGINEERING_MODE): switch.switch_schema( + EngineeringModeSwitch, + device_class=DEVICE_CLASS_SWITCH, + entity_category=ENTITY_CATEGORY_CONFIG, + icon=ICON_PULSE, + ), + cv.Optional(CONF_BLUETOOTH): switch.switch_schema( + BluetoothSwitch, + device_class=DEVICE_CLASS_SWITCH, + entity_category=ENTITY_CATEGORY_CONFIG, + icon=ICON_BLUETOOTH, + ), +} + + +async def to_code(config): + ld2410_component = await cg.get_variable(config[CONF_LD2410_ID]) + if engineering_mode_config := config.get(CONF_ENGINEERING_MODE): + s = await switch.new_switch(engineering_mode_config) + await cg.register_parented(s, config[CONF_LD2410_ID]) + cg.add(ld2410_component.set_engineering_mode_switch(s)) + if bluetooth_config := config.get(CONF_BLUETOOTH): + s = await switch.new_switch(bluetooth_config) + await cg.register_parented(s, config[CONF_LD2410_ID]) + cg.add(ld2410_component.set_bluetooth_switch(s)) diff --git a/esphome/components/ld2410/switch/bluetooth_switch.cpp b/esphome/components/ld2410/switch/bluetooth_switch.cpp new file mode 100644 index 0000000000..9bcee9b049 --- /dev/null +++ b/esphome/components/ld2410/switch/bluetooth_switch.cpp @@ -0,0 +1,12 @@ +#include "bluetooth_switch.h" + +namespace esphome { +namespace ld2410 { + +void BluetoothSwitch::write_state(bool state) { + this->publish_state(state); + this->parent_->set_bluetooth(state); +} + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/switch/bluetooth_switch.h b/esphome/components/ld2410/switch/bluetooth_switch.h new file mode 100644 index 0000000000..35ae1ec0c9 --- /dev/null +++ b/esphome/components/ld2410/switch/bluetooth_switch.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/switch/switch.h" +#include "../ld2410.h" + +namespace esphome { +namespace ld2410 { + +class BluetoothSwitch : public switch_::Switch, public Parented { + public: + BluetoothSwitch() = default; + + protected: + void write_state(bool state) override; +}; + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/switch/engineering_mode_switch.cpp b/esphome/components/ld2410/switch/engineering_mode_switch.cpp new file mode 100644 index 0000000000..967c87c887 --- /dev/null +++ b/esphome/components/ld2410/switch/engineering_mode_switch.cpp @@ -0,0 +1,12 @@ +#include "engineering_mode_switch.h" + +namespace esphome { +namespace ld2410 { + +void EngineeringModeSwitch::write_state(bool state) { + this->publish_state(state); + this->parent_->set_engineering_mode(state); +} + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/switch/engineering_mode_switch.h b/esphome/components/ld2410/switch/engineering_mode_switch.h new file mode 100644 index 0000000000..e521200cd6 --- /dev/null +++ b/esphome/components/ld2410/switch/engineering_mode_switch.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/switch/switch.h" +#include "../ld2410.h" + +namespace esphome { +namespace ld2410 { + +class EngineeringModeSwitch : public switch_::Switch, public Parented { + public: + EngineeringModeSwitch() = default; + + protected: + void write_state(bool state) override; +}; + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/text_sensor.py b/esphome/components/ld2410/text_sensor.py new file mode 100644 index 0000000000..d64472a7d3 --- /dev/null +++ b/esphome/components/ld2410/text_sensor.py @@ -0,0 +1,33 @@ +import esphome.codegen as cg +from esphome.components import text_sensor +import esphome.config_validation as cv +from esphome.const import ( + ENTITY_CATEGORY_DIAGNOSTIC, + CONF_VERSION, + CONF_MAC_ADDRESS, + ICON_BLUETOOTH, + ICON_CHIP, +) +from . import CONF_LD2410_ID, LD2410Component + +DEPENDENCIES = ["ld2410"] + +CONFIG_SCHEMA = { + 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 + ), + cv.Optional(CONF_MAC_ADDRESS): text_sensor.text_sensor_schema( + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, icon=ICON_BLUETOOTH + ), +} + + +async def to_code(config): + ld2410_component = await cg.get_variable(config[CONF_LD2410_ID]) + if version_config := config.get(CONF_VERSION): + sens = await text_sensor.new_text_sensor(version_config) + cg.add(ld2410_component.set_version_text_sensor(sens)) + if mac_address_config := config.get(CONF_MAC_ADDRESS): + sens = await text_sensor.new_text_sensor(mac_address_config) + cg.add(ld2410_component.set_mac_text_sensor(sens)) diff --git a/tests/test1.yaml b/tests/test1.yaml index 4eb78515c9..66caad961a 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -170,6 +170,9 @@ mqtt: id: uart_0 data: !lambda |- return {}; + - bluetooth_password.set: + id: my_ld2410 + password: abcdef on_connect: - light.turn_on: ${roomname}_lights - mqtt.publish: @@ -1333,16 +1336,64 @@ sensor: speed: name: "Radiator Pump Speed" - platform: ld2410 + light: + name: light moving_distance: name: "Moving distance (cm)" still_distance: name: "Still Distance (cm)" moving_energy: - name: "Move Energy" + name: "Move Energy (%)" still_energy: - name: "Still Energy" + name: "Still Energy (%)" detection_distance: - name: "Distance Detection" + name: "Distance Detection (cm)" + g0: + move_energy: + name: g0 move energy + still_energy: + name: g0 still energy + g1: + move_energy: + name: g1 move energy + still_energy: + name: g1 still energy + g2: + move_energy: + name: g2 move energy + still_energy: + name: g2 still energy + g3: + move_energy: + name: g3 move energy + still_energy: + name: g3 still energy + g4: + move_energy: + name: g4 move energy + still_energy: + name: g4 still energy + g5: + move_energy: + name: g5 move energy + still_energy: + name: g5 still energy + g6: + move_energy: + name: g6 move energy + still_energy: + name: g6 still energy + g7: + move_energy: + name: g7 move energy + still_energy: + name: g7 still energy + g8: + move_energy: + name: g8 move energy + still_energy: + name: g8 still energy + - platform: sen21231 name: "Person Sensor" i2c_id: i2c_bus @@ -1684,6 +1735,8 @@ binary_sensor: name: movement has_still_target: name: still + out_pin_presence_status: + name: out pin presence status pca9685: frequency: 500 @@ -2626,6 +2679,11 @@ switch: id: outlet_switch optimistic: true device_class: outlet + - platform: ld2410 + engineering_mode: + name: "control ld2410 engineering mode" + bluetooth: + name: "control ld2410 bluetooth" fan: - platform: binary @@ -3207,6 +3265,11 @@ text_sensor: tag_name: OPTARIF name: optarif teleinfo_id: myteleinfo + - platform: ld2410 + version: + name: "presenece sensor version" + mac_address: + name: "presenece sensor mac address" sn74hc595: - id: sn74hc595_hub @@ -3311,6 +3374,61 @@ number: step: 1 max_value: 10 optimistic: true + - platform: ld2410 + light_threshold: + name: light threshold + timeout: + name: timeout + max_move_distance_gate: + name: max move distance gate + max_still_distance_gate: + name: max still distance gate + g0: + move_threshold: + name: g0 move threshold + still_threshold: + name: g0 still threshold + g1: + move_threshold: + name: g1 move threshold + still_threshold: + name: g1 still threshold + g2: + move_threshold: + name: g2 move threshold + still_threshold: + name: g2 still threshold + g3: + move_threshold: + name: g3 move threshold + still_threshold: + name: g3 still threshold + g4: + move_threshold: + name: g4 move threshold + still_threshold: + name: g4 still threshold + g5: + move_threshold: + name: g5 move threshold + still_threshold: + name: g5 still threshold + g6: + move_threshold: + name: g6 move threshold + still_threshold: + name: g6 still threshold + g7: + move_threshold: + name: g7 move threshold + still_threshold: + name: g7 still threshold + g8: + move_threshold: + name: g8 move threshold + still_threshold: + name: g8 still threshold + select: - platform: template @@ -3324,6 +3442,15 @@ select: - platform: copy source_id: test_select name: Test Select Copy + - platform: ld2410 + distance_resolution: + name: distance resolution + baud_rate: + name: baud rate + light_function: + name: light function + out_pin_level: + name: out ping level qr_code: - id: homepage_qr @@ -3386,19 +3513,17 @@ button: name: Midea Power Inverse on_press: midea_ac.power_toggle: + - platform: ld2410 + factory_reset: + name: "factory reset" + restart: + name: "restart" + query_params: + name: query params ld2410: id: my_ld2410 uart_id: ld2410_uart - timeout: 150s - max_move_distance: 6m - max_still_distance: 0.75m - g0_move_threshold: 10 - g0_still_threshold: 20 - g2_move_threshold: 20 - g2_still_threshold: 21 - g8_move_threshold: 80 - g8_still_threshold: 81 lcd_menu: display_id: my_lcd_gpio From 67b06a88b22bbd661f349e2fff442739d3606f90 Mon Sep 17 00:00:00 2001 From: MrEditor97 Date: Mon, 14 Aug 2023 20:14:08 +0100 Subject: [PATCH 0061/2101] Change XL9535 `setup_priority` to IO (#5246) --- esphome/components/xl9535/xl9535.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/xl9535/xl9535.h b/esphome/components/xl9535/xl9535.h index 8f0a868c42..dd67990fa8 100644 --- a/esphome/components/xl9535/xl9535.h +++ b/esphome/components/xl9535/xl9535.h @@ -26,7 +26,7 @@ class XL9535Component : public Component, public i2c::I2CDevice { void setup() override; void dump_config() override; - float get_setup_priority() const override { return setup_priority::DATA; } + float get_setup_priority() const override { return setup_priority::IO; } }; class XL9535GPIOPin : public GPIOPin { From afd26c6f1a57508d9936f4887641a59992be199a Mon Sep 17 00:00:00 2001 From: Sergey Dudanov Date: Mon, 14 Aug 2023 23:21:22 +0400 Subject: [PATCH 0062/2101] rmt_base additional minor changes (#5245) --- esphome/components/remote_base/__init__.py | 21 +++++-------------- .../components/remote_base/midea_protocol.h | 1 - 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/esphome/components/remote_base/__init__.py b/esphome/components/remote_base/__init__.py index 9e46506b3c..e2d96c9472 100644 --- a/esphome/components/remote_base/__init__.py +++ b/esphome/components/remote_base/__init__.py @@ -1488,10 +1488,7 @@ MideaData, MideaBinarySensor, MideaTrigger, MideaAction, MideaDumper = declare_p MideaAction = ns.class_("MideaAction", RemoteTransmitterActionBase) MIDEA_SCHEMA = cv.Schema( { - cv.Required(CONF_CODE): cv.All( - [cv.Any(cv.hex_uint8_t, cv.uint8_t)], - cv.Length(min=5, max=5), - ), + cv.Required(CONF_CODE): cv.All([cv.hex_uint8_t], cv.Length(min=5, max=5)), } ) @@ -1511,15 +1508,10 @@ def midea_dumper(var, config): pass -@register_action( - "midea", - MideaAction, - MIDEA_SCHEMA, -) +@register_action("midea", MideaAction, MIDEA_SCHEMA) async def midea_action(var, config, args): - template_ = await cg.templatable( - config[CONF_CODE], args, cg.std_vector.template(cg.uint8) - ) + vec_ = cg.std_vector.template(cg.uint8) + template_ = await cg.templatable(config[CONF_CODE], args, vec_, vec_) cg.add(var.set_code(template_)) @@ -1530,10 +1522,7 @@ AEHAData, AEHABinarySensor, AEHATrigger, AEHAAction, AEHADumper = declare_protoc AEHA_SCHEMA = cv.Schema( { cv.Required(CONF_ADDRESS): cv.hex_uint16_t, - cv.Required(CONF_DATA): cv.All( - [cv.Any(cv.hex_uint8_t, cv.uint8_t)], - cv.Length(min=2, max=35), - ), + cv.Required(CONF_DATA): cv.All([cv.hex_uint8_t], cv.Length(min=2, max=35)), } ) diff --git a/esphome/components/remote_base/midea_protocol.h b/esphome/components/remote_base/midea_protocol.h index f5db313579..6925686b34 100644 --- a/esphome/components/remote_base/midea_protocol.h +++ b/esphome/components/remote_base/midea_protocol.h @@ -84,7 +84,6 @@ using MideaDumper = RemoteReceiverDumper; template class MideaAction : public RemoteTransmitterActionBase { TEMPLATABLE_VALUE(std::vector, code) - void set_code(std::initializer_list code) { this->code_ = code; } void encode(RemoteTransmitData *dst, Ts... x) override { MideaData data(this->code_.value(x...)); From ff8a73c2d140ee1847c308fc6d0bd4f3f3109a62 Mon Sep 17 00:00:00 2001 From: mulder-fbi Date: Wed, 16 Aug 2023 00:52:56 +0200 Subject: [PATCH 0063/2101] Fix 24 bit signed integer parsing in sml parser (#5250) --- esphome/components/sml/sml_parser.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/esphome/components/sml/sml_parser.cpp b/esphome/components/sml/sml_parser.cpp index ff7da4cabd..91b320a30e 100644 --- a/esphome/components/sml/sml_parser.cpp +++ b/esphome/components/sml/sml_parser.cpp @@ -88,6 +88,11 @@ uint64_t bytes_to_uint(const bytes &buffer) { for (auto const value : buffer) { val = (val << 8) + value; } + // Some smart meters send 24 bit signed integers. Sign extend to 64 bit if the + // 24 bit value is negative. + if (buffer.size() == 3 && buffer[0] & 0x80) { + val |= 0xFFFFFFFFFF000000; + } return val; } From 48e4cb5ae24145ca6da22f3206eb2dcb85ef71d0 Mon Sep 17 00:00:00 2001 From: Carson Full Date: Tue, 15 Aug 2023 18:13:43 -0500 Subject: [PATCH 0064/2101] Fix IDFI2CBus::writev ignoring stop parameter (#4840) Co-authored-by: Alexander Dimitrov --- esphome/components/i2c/i2c_bus_esp_idf.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/esphome/components/i2c/i2c_bus_esp_idf.cpp b/esphome/components/i2c/i2c_bus_esp_idf.cpp index e2c7e7ddcb..5d35c1968b 100644 --- a/esphome/components/i2c/i2c_bus_esp_idf.cpp +++ b/esphome/components/i2c/i2c_bus_esp_idf.cpp @@ -202,11 +202,13 @@ ErrorCode IDFI2CBus::writev(uint8_t address, WriteBuffer *buffers, size_t cnt, b return ERROR_UNKNOWN; } } - err = i2c_master_stop(cmd); - if (err != ESP_OK) { - ESP_LOGVV(TAG, "TX to %02X master stop failed: %s", address, esp_err_to_name(err)); - i2c_cmd_link_delete(cmd); - return ERROR_UNKNOWN; + if (stop) { + err = i2c_master_stop(cmd); + if (err != ESP_OK) { + ESP_LOGVV(TAG, "TX to %02X master stop failed: %s", address, esp_err_to_name(err)); + i2c_cmd_link_delete(cmd); + return ERROR_UNKNOWN; + } } err = i2c_master_cmd_begin(port_, cmd, 20 / portTICK_PERIOD_MS); i2c_cmd_link_delete(cmd); From 63fa922547fb904f61553dc226bdd949d62e4010 Mon Sep 17 00:00:00 2001 From: Regev Brody Date: Wed, 16 Aug 2023 02:31:18 +0300 Subject: [PATCH 0065/2101] Add configuration flow abilites to the ld2410 component (#4434) --- CODEOWNERS | 2 +- esphome/components/ld2410/__init__.py | 188 +++--- esphome/components/ld2410/automation.h | 22 + esphome/components/ld2410/binary_sensor.py | 45 +- esphome/components/ld2410/button/__init__.py | 57 ++ .../components/ld2410/button/query_button.cpp | 9 + .../components/ld2410/button/query_button.h | 18 + .../components/ld2410/button/reset_button.cpp | 9 + .../components/ld2410/button/reset_button.h | 18 + .../ld2410/button/restart_button.cpp | 9 + .../components/ld2410/button/restart_button.h | 18 + esphome/components/ld2410/ld2410.cpp | 557 +++++++++++++++--- esphome/components/ld2410/ld2410.h | 207 +++++-- esphome/components/ld2410/number/__init__.py | 128 ++++ .../ld2410/number/gate_threshold_number.cpp | 14 + .../ld2410/number/gate_threshold_number.h | 19 + .../ld2410/number/light_threshold_number.cpp | 12 + .../ld2410/number/light_threshold_number.h | 18 + .../number/max_distance_timeout_number.cpp | 12 + .../number/max_distance_timeout_number.h | 18 + esphome/components/ld2410/select/__init__.py | 81 +++ .../ld2410/select/baud_rate_select.cpp | 12 + .../ld2410/select/baud_rate_select.h | 18 + .../select/distance_resolution_select.cpp | 12 + .../select/distance_resolution_select.h | 18 + .../select/light_out_control_select.cpp | 12 + .../ld2410/select/light_out_control_select.h | 18 + esphome/components/ld2410/sensor.py | 111 +++- esphome/components/ld2410/switch/__init__.py | 44 ++ .../ld2410/switch/bluetooth_switch.cpp | 12 + .../ld2410/switch/bluetooth_switch.h | 18 + .../ld2410/switch/engineering_mode_switch.cpp | 12 + .../ld2410/switch/engineering_mode_switch.h | 18 + esphome/components/ld2410/text_sensor.py | 33 ++ tests/test1.yaml | 149 ++++- 35 files changed, 1621 insertions(+), 327 deletions(-) create mode 100644 esphome/components/ld2410/automation.h create mode 100644 esphome/components/ld2410/button/__init__.py create mode 100644 esphome/components/ld2410/button/query_button.cpp create mode 100644 esphome/components/ld2410/button/query_button.h create mode 100644 esphome/components/ld2410/button/reset_button.cpp create mode 100644 esphome/components/ld2410/button/reset_button.h create mode 100644 esphome/components/ld2410/button/restart_button.cpp create mode 100644 esphome/components/ld2410/button/restart_button.h create mode 100644 esphome/components/ld2410/number/__init__.py create mode 100644 esphome/components/ld2410/number/gate_threshold_number.cpp create mode 100644 esphome/components/ld2410/number/gate_threshold_number.h create mode 100644 esphome/components/ld2410/number/light_threshold_number.cpp create mode 100644 esphome/components/ld2410/number/light_threshold_number.h create mode 100644 esphome/components/ld2410/number/max_distance_timeout_number.cpp create mode 100644 esphome/components/ld2410/number/max_distance_timeout_number.h create mode 100644 esphome/components/ld2410/select/__init__.py create mode 100644 esphome/components/ld2410/select/baud_rate_select.cpp create mode 100644 esphome/components/ld2410/select/baud_rate_select.h create mode 100644 esphome/components/ld2410/select/distance_resolution_select.cpp create mode 100644 esphome/components/ld2410/select/distance_resolution_select.h create mode 100644 esphome/components/ld2410/select/light_out_control_select.cpp create mode 100644 esphome/components/ld2410/select/light_out_control_select.h create mode 100644 esphome/components/ld2410/switch/__init__.py create mode 100644 esphome/components/ld2410/switch/bluetooth_switch.cpp create mode 100644 esphome/components/ld2410/switch/bluetooth_switch.h create mode 100644 esphome/components/ld2410/switch/engineering_mode_switch.cpp create mode 100644 esphome/components/ld2410/switch/engineering_mode_switch.h create mode 100644 esphome/components/ld2410/text_sensor.py diff --git a/CODEOWNERS b/CODEOWNERS index 408caee4f2..b3ac833ee4 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -144,7 +144,7 @@ esphome/components/key_collector/* @ssieb esphome/components/key_provider/* @ssieb esphome/components/kuntze/* @ssieb esphome/components/lcd_menu/* @numo68 -esphome/components/ld2410/* @sebcaps +esphome/components/ld2410/* @regevbr @sebcaps esphome/components/ledc/* @OttoWinter esphome/components/light/* @esphome/core esphome/components/lilygo_t5_47/touchscreen/* @jesserockz diff --git a/esphome/components/ld2410/__init__.py b/esphome/components/ld2410/__init__.py index 47c4cdb0bd..2b30b65f46 100644 --- a/esphome/components/ld2410/__init__.py +++ b/esphome/components/ld2410/__init__.py @@ -1,113 +1,64 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import uart -from esphome.const import CONF_ID, CONF_TIMEOUT +from esphome.const import CONF_ID, CONF_THROTTLE, CONF_TIMEOUT, CONF_PASSWORD from esphome import automation from esphome.automation import maybe_simple_id DEPENDENCIES = ["uart"] -CODEOWNERS = ["@sebcaps"] +CODEOWNERS = ["@sebcaps", "@regevbr"] MULTI_CONF = True ld2410_ns = cg.esphome_ns.namespace("ld2410") LD2410Component = ld2410_ns.class_("LD2410Component", cg.Component, uart.UARTDevice) -LD2410Restart = ld2410_ns.class_("LD2410Restart", automation.Action) + CONF_LD2410_ID = "ld2410_id" + CONF_MAX_MOVE_DISTANCE = "max_move_distance" CONF_MAX_STILL_DISTANCE = "max_still_distance" -CONF_G0_MOVE_THRESHOLD = "g0_move_threshold" -CONF_G0_STILL_THRESHOLD = "g0_still_threshold" -CONF_G1_MOVE_THRESHOLD = "g1_move_threshold" -CONF_G1_STILL_THRESHOLD = "g1_still_threshold" -CONF_G2_MOVE_THRESHOLD = "g2_move_threshold" -CONF_G2_STILL_THRESHOLD = "g2_still_threshold" -CONF_G3_MOVE_THRESHOLD = "g3_move_threshold" -CONF_G3_STILL_THRESHOLD = "g3_still_threshold" -CONF_G4_MOVE_THRESHOLD = "g4_move_threshold" -CONF_G4_STILL_THRESHOLD = "g4_still_threshold" -CONF_G5_MOVE_THRESHOLD = "g5_move_threshold" -CONF_G5_STILL_THRESHOLD = "g5_still_threshold" -CONF_G6_MOVE_THRESHOLD = "g6_move_threshold" -CONF_G6_STILL_THRESHOLD = "g6_still_threshold" -CONF_G7_MOVE_THRESHOLD = "g7_move_threshold" -CONF_G7_STILL_THRESHOLD = "g7_still_threshold" -CONF_G8_MOVE_THRESHOLD = "g8_move_threshold" -CONF_G8_STILL_THRESHOLD = "g8_still_threshold" +CONF_STILL_THRESHOLDS = [f"g{x}_still_threshold" for x in range(9)] +CONF_MOVE_THRESHOLDS = [f"g{x}_move_threshold" for x in range(9)] -DISTANCES = [0.75, 1.5, 2.25, 3, 3.75, 4.5, 5.25, 6] +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.declare_id(LD2410Component), + cv.Optional(CONF_THROTTLE, default="1000ms"): cv.All( + cv.positive_time_period_milliseconds, + cv.Range(min=cv.TimePeriod(milliseconds=1)), + ), + cv.Optional(CONF_MAX_MOVE_DISTANCE): cv.invalid( + f"The '{CONF_MAX_MOVE_DISTANCE}' option has been moved to the '{CONF_MAX_MOVE_DISTANCE}'" + f" number component" + ), + cv.Optional(CONF_MAX_STILL_DISTANCE): cv.invalid( + f"The '{CONF_MAX_STILL_DISTANCE}' option has been moved to the '{CONF_MAX_STILL_DISTANCE}'" + f" number component" + ), + cv.Optional(CONF_TIMEOUT): cv.invalid( + f"The '{CONF_TIMEOUT}' option has been moved to the '{CONF_TIMEOUT}'" + f" number component" + ), + } +) + +for i in range(9): + CONFIG_SCHEMA = CONFIG_SCHEMA.extend( + cv.Schema( + { + cv.Optional(CONF_MOVE_THRESHOLDS[i]): cv.invalid( + f"The '{CONF_MOVE_THRESHOLDS[i]}' option has been moved to the '{CONF_MOVE_THRESHOLDS[i]}'" + f" number component" + ), + cv.Optional(CONF_STILL_THRESHOLDS[i]): cv.invalid( + f"The '{CONF_STILL_THRESHOLDS[i]}' option has been moved to the '{CONF_STILL_THRESHOLDS[i]}'" + f" number component" + ), + } + ) + ) CONFIG_SCHEMA = cv.All( - cv.Schema( - { - cv.GenerateID(): cv.declare_id(LD2410Component), - cv.Optional(CONF_MAX_MOVE_DISTANCE, default="4.5m"): cv.All( - cv.distance, cv.one_of(*DISTANCES, float=True) - ), - cv.Optional(CONF_MAX_STILL_DISTANCE, default="4.5m"): cv.All( - cv.distance, cv.one_of(*DISTANCES, float=True) - ), - cv.Optional(CONF_TIMEOUT, default="5s"): cv.All( - cv.positive_time_period_seconds, - cv.Range(max=cv.TimePeriod(seconds=32767)), - ), - cv.Optional(CONF_G0_MOVE_THRESHOLD, default=50): cv.int_range( - min=0, max=100 - ), - cv.Optional(CONF_G0_STILL_THRESHOLD, default=0): cv.int_range( - min=0, max=100 - ), - cv.Optional(CONF_G1_MOVE_THRESHOLD, default=50): cv.int_range( - min=0, max=100 - ), - cv.Optional(CONF_G1_STILL_THRESHOLD, default=0): cv.int_range( - min=0, max=100 - ), - cv.Optional(CONF_G2_MOVE_THRESHOLD, default=40): cv.int_range( - min=0, max=100 - ), - cv.Optional(CONF_G2_STILL_THRESHOLD, default=40): cv.int_range( - min=0, max=100 - ), - cv.Optional(CONF_G3_MOVE_THRESHOLD, default=40): cv.int_range( - min=0, max=100 - ), - cv.Optional(CONF_G3_STILL_THRESHOLD, default=40): cv.int_range( - min=0, max=100 - ), - cv.Optional(CONF_G4_MOVE_THRESHOLD, default=40): cv.int_range( - min=0, max=100 - ), - cv.Optional(CONF_G4_STILL_THRESHOLD, default=40): cv.int_range( - min=0, max=100 - ), - cv.Optional(CONF_G5_MOVE_THRESHOLD, default=40): cv.int_range( - min=0, max=100 - ), - cv.Optional(CONF_G5_STILL_THRESHOLD, default=40): cv.int_range( - min=0, max=100 - ), - cv.Optional(CONF_G6_MOVE_THRESHOLD, default=30): cv.int_range( - min=0, max=100 - ), - cv.Optional(CONF_G6_STILL_THRESHOLD, default=15): cv.int_range( - min=0, max=100 - ), - cv.Optional(CONF_G7_MOVE_THRESHOLD, default=30): cv.int_range( - min=0, max=100 - ), - cv.Optional(CONF_G7_STILL_THRESHOLD, default=15): cv.int_range( - min=0, max=100 - ), - cv.Optional(CONF_G8_MOVE_THRESHOLD, default=30): cv.int_range( - min=0, max=100 - ), - cv.Optional(CONF_G8_STILL_THRESHOLD, default=15): cv.int_range( - min=0, max=100 - ), - } - ) - .extend(uart.UART_DEVICE_SCHEMA) - .extend(cv.COMPONENT_SCHEMA) + CONFIG_SCHEMA.extend(uart.UART_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA) ) FINAL_VALIDATE_SCHEMA = uart.final_validate_device_schema( @@ -123,31 +74,7 @@ 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(var.set_timeout(config[CONF_TIMEOUT])) - cg.add(var.set_max_move_distance(int(config[CONF_MAX_MOVE_DISTANCE] / 0.75))) - cg.add(var.set_max_still_distance(int(config[CONF_MAX_STILL_DISTANCE] / 0.75))) - cg.add( - var.set_range_config( - config[CONF_G0_MOVE_THRESHOLD], - config[CONF_G0_STILL_THRESHOLD], - config[CONF_G1_MOVE_THRESHOLD], - config[CONF_G1_STILL_THRESHOLD], - config[CONF_G2_MOVE_THRESHOLD], - config[CONF_G2_STILL_THRESHOLD], - config[CONF_G3_MOVE_THRESHOLD], - config[CONF_G3_STILL_THRESHOLD], - config[CONF_G4_MOVE_THRESHOLD], - config[CONF_G4_STILL_THRESHOLD], - config[CONF_G5_MOVE_THRESHOLD], - config[CONF_G5_STILL_THRESHOLD], - config[CONF_G6_MOVE_THRESHOLD], - config[CONF_G6_STILL_THRESHOLD], - config[CONF_G7_MOVE_THRESHOLD], - config[CONF_G7_STILL_THRESHOLD], - config[CONF_G8_MOVE_THRESHOLD], - config[CONF_G8_STILL_THRESHOLD], - ) - ) + cg.add(var.set_throttle(config[CONF_THROTTLE])) CALIBRATION_ACTION_SCHEMA = maybe_simple_id( @@ -155,3 +82,28 @@ CALIBRATION_ACTION_SCHEMA = maybe_simple_id( cv.Required(CONF_ID): cv.use_id(LD2410Component), } ) + + +# Actions +BluetoothPasswordSetAction = ld2410_ns.class_( + "BluetoothPasswordSetAction", automation.Action +) + + +BLUETOOTH_PASSWORD_SET_SCHEMA = cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(LD2410Component), + cv.Required(CONF_PASSWORD): cv.templatable(cv.string_strict), + } +) + + +@automation.register_action( + "bluetooth_password.set", BluetoothPasswordSetAction, BLUETOOTH_PASSWORD_SET_SCHEMA +) +async def bluetooth_password_set_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_PASSWORD], args, cg.std_string) + cg.add(var.set_password(template_)) + return var diff --git a/esphome/components/ld2410/automation.h b/esphome/components/ld2410/automation.h new file mode 100644 index 0000000000..7cb9855f84 --- /dev/null +++ b/esphome/components/ld2410/automation.h @@ -0,0 +1,22 @@ +#pragma once + +#include "esphome/core/automation.h" +#include "esphome/core/component.h" +#include "ld2410.h" + +namespace esphome { +namespace ld2410 { + +template class BluetoothPasswordSetAction : public Action { + public: + explicit BluetoothPasswordSetAction(LD2410Component *ld2410_comp) : ld2410_comp_(ld2410_comp) {} + TEMPLATABLE_VALUE(std::string, password) + + void play(Ts... x) override { this->ld2410_comp_->set_bluetooth_password(this->password_.value(x...)); } + + protected: + LD2410Component *ld2410_comp_; +}; + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/binary_sensor.py b/esphome/components/ld2410/binary_sensor.py index 02f73d57b7..3057480d25 100644 --- a/esphome/components/ld2410/binary_sensor.py +++ b/esphome/components/ld2410/binary_sensor.py @@ -1,36 +1,55 @@ import esphome.codegen as cg from esphome.components import binary_sensor import esphome.config_validation as cv -from esphome.const import DEVICE_CLASS_MOTION, DEVICE_CLASS_OCCUPANCY +from esphome.const import ( + DEVICE_CLASS_MOTION, + DEVICE_CLASS_OCCUPANCY, + DEVICE_CLASS_PRESENCE, + ENTITY_CATEGORY_DIAGNOSTIC, + ICON_MOTION_SENSOR, + ICON_ACCOUNT, +) from . import CONF_LD2410_ID, LD2410Component DEPENDENCIES = ["ld2410"] CONF_HAS_TARGET = "has_target" CONF_HAS_MOVING_TARGET = "has_moving_target" CONF_HAS_STILL_TARGET = "has_still_target" +CONF_OUT_PIN_PRESENCE_STATUS = "out_pin_presence_status" CONFIG_SCHEMA = { cv.GenerateID(CONF_LD2410_ID): cv.use_id(LD2410Component), cv.Optional(CONF_HAS_TARGET): binary_sensor.binary_sensor_schema( - device_class=DEVICE_CLASS_OCCUPANCY + device_class=DEVICE_CLASS_OCCUPANCY, + icon=ICON_ACCOUNT, ), cv.Optional(CONF_HAS_MOVING_TARGET): binary_sensor.binary_sensor_schema( - device_class=DEVICE_CLASS_MOTION + device_class=DEVICE_CLASS_MOTION, + icon=ICON_MOTION_SENSOR, ), cv.Optional(CONF_HAS_STILL_TARGET): binary_sensor.binary_sensor_schema( - device_class=DEVICE_CLASS_OCCUPANCY + device_class=DEVICE_CLASS_OCCUPANCY, + icon=ICON_MOTION_SENSOR, + ), + cv.Optional(CONF_OUT_PIN_PRESENCE_STATUS): binary_sensor.binary_sensor_schema( + device_class=DEVICE_CLASS_PRESENCE, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + icon=ICON_ACCOUNT, ), } async def to_code(config): ld2410_component = await cg.get_variable(config[CONF_LD2410_ID]) - if CONF_HAS_TARGET in config: - sens = await binary_sensor.new_binary_sensor(config[CONF_HAS_TARGET]) - cg.add(ld2410_component.set_target_sensor(sens)) - if CONF_HAS_MOVING_TARGET in config: - sens = await binary_sensor.new_binary_sensor(config[CONF_HAS_MOVING_TARGET]) - cg.add(ld2410_component.set_moving_target_sensor(sens)) - if CONF_HAS_STILL_TARGET in config: - sens = await binary_sensor.new_binary_sensor(config[CONF_HAS_STILL_TARGET]) - cg.add(ld2410_component.set_still_target_sensor(sens)) + if has_target_config := config.get(CONF_HAS_TARGET): + sens = await binary_sensor.new_binary_sensor(has_target_config) + cg.add(ld2410_component.set_target_binary_sensor(sens)) + if has_moving_target_config := config.get(CONF_HAS_MOVING_TARGET): + sens = await binary_sensor.new_binary_sensor(has_moving_target_config) + cg.add(ld2410_component.set_moving_target_binary_sensor(sens)) + if has_still_target_config := config.get(CONF_HAS_STILL_TARGET): + sens = await binary_sensor.new_binary_sensor(has_still_target_config) + cg.add(ld2410_component.set_still_target_binary_sensor(sens)) + if out_pin_presence_status_config := config.get(CONF_OUT_PIN_PRESENCE_STATUS): + sens = await binary_sensor.new_binary_sensor(out_pin_presence_status_config) + cg.add(ld2410_component.set_out_pin_presence_status_binary_sensor(sens)) diff --git a/esphome/components/ld2410/button/__init__.py b/esphome/components/ld2410/button/__init__.py new file mode 100644 index 0000000000..3567114c2c --- /dev/null +++ b/esphome/components/ld2410/button/__init__.py @@ -0,0 +1,57 @@ +import esphome.codegen as cg +from esphome.components import button +import esphome.config_validation as cv +from esphome.const import ( + DEVICE_CLASS_RESTART, + ENTITY_CATEGORY_DIAGNOSTIC, + ENTITY_CATEGORY_CONFIG, + ICON_RESTART, + ICON_RESTART_ALERT, + ICON_DATABASE, +) +from .. import CONF_LD2410_ID, LD2410Component, ld2410_ns + +QueryButton = ld2410_ns.class_("QueryButton", button.Button) +ResetButton = ld2410_ns.class_("ResetButton", button.Button) +RestartButton = ld2410_ns.class_("RestartButton", button.Button) + +CONF_FACTORY_RESET = "factory_reset" +CONF_RESTART = "restart" +CONF_QUERY_PARAMS = "query_params" + +CONFIG_SCHEMA = { + cv.GenerateID(CONF_LD2410_ID): cv.use_id(LD2410Component), + cv.Optional(CONF_FACTORY_RESET): button.button_schema( + ResetButton, + device_class=DEVICE_CLASS_RESTART, + entity_category=ENTITY_CATEGORY_CONFIG, + icon=ICON_RESTART_ALERT, + ), + cv.Optional(CONF_RESTART): button.button_schema( + RestartButton, + device_class=DEVICE_CLASS_RESTART, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + icon=ICON_RESTART, + ), + cv.Optional(CONF_QUERY_PARAMS): button.button_schema( + QueryButton, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + icon=ICON_DATABASE, + ), +} + + +async def to_code(config): + ld2410_component = await cg.get_variable(config[CONF_LD2410_ID]) + if factory_reset_config := config.get(CONF_FACTORY_RESET): + b = await button.new_button(factory_reset_config) + await cg.register_parented(b, config[CONF_LD2410_ID]) + cg.add(ld2410_component.set_reset_button(b)) + if restart_config := config.get(CONF_RESTART): + b = await button.new_button(restart_config) + await cg.register_parented(b, config[CONF_LD2410_ID]) + cg.add(ld2410_component.set_restart_button(b)) + if query_params_config := config.get(CONF_QUERY_PARAMS): + b = await button.new_button(query_params_config) + await cg.register_parented(b, config[CONF_LD2410_ID]) + cg.add(ld2410_component.set_query_button(b)) diff --git a/esphome/components/ld2410/button/query_button.cpp b/esphome/components/ld2410/button/query_button.cpp new file mode 100644 index 0000000000..47ab416f5a --- /dev/null +++ b/esphome/components/ld2410/button/query_button.cpp @@ -0,0 +1,9 @@ +#include "query_button.h" + +namespace esphome { +namespace ld2410 { + +void QueryButton::press_action() { this->parent_->read_all_info(); } + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/button/query_button.h b/esphome/components/ld2410/button/query_button.h new file mode 100644 index 0000000000..c7a47e32d8 --- /dev/null +++ b/esphome/components/ld2410/button/query_button.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/button/button.h" +#include "../ld2410.h" + +namespace esphome { +namespace ld2410 { + +class QueryButton : public button::Button, public Parented { + public: + QueryButton() = default; + + protected: + void press_action() override; +}; + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/button/reset_button.cpp b/esphome/components/ld2410/button/reset_button.cpp new file mode 100644 index 0000000000..f16c5faa79 --- /dev/null +++ b/esphome/components/ld2410/button/reset_button.cpp @@ -0,0 +1,9 @@ +#include "reset_button.h" + +namespace esphome { +namespace ld2410 { + +void ResetButton::press_action() { this->parent_->factory_reset(); } + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/button/reset_button.h b/esphome/components/ld2410/button/reset_button.h new file mode 100644 index 0000000000..78dd92c9f5 --- /dev/null +++ b/esphome/components/ld2410/button/reset_button.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/button/button.h" +#include "../ld2410.h" + +namespace esphome { +namespace ld2410 { + +class ResetButton : public button::Button, public Parented { + public: + ResetButton() = default; + + protected: + void press_action() override; +}; + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/button/restart_button.cpp b/esphome/components/ld2410/button/restart_button.cpp new file mode 100644 index 0000000000..de0d36c1ef --- /dev/null +++ b/esphome/components/ld2410/button/restart_button.cpp @@ -0,0 +1,9 @@ +#include "restart_button.h" + +namespace esphome { +namespace ld2410 { + +void RestartButton::press_action() { this->parent_->restart_and_read_all_info(); } + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/button/restart_button.h b/esphome/components/ld2410/button/restart_button.h new file mode 100644 index 0000000000..d00dc05a53 --- /dev/null +++ b/esphome/components/ld2410/button/restart_button.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/button/button.h" +#include "../ld2410.h" + +namespace esphome { +namespace ld2410 { + +class RestartButton : public button::Button, public Parented { + public: + RestartButton() = default; + + protected: + void press_action() override; +}; + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/ld2410.cpp b/esphome/components/ld2410/ld2410.cpp index 8e67ba54d7..c3b57815d6 100644 --- a/esphome/components/ld2410/ld2410.cpp +++ b/esphome/components/ld2410/ld2410.cpp @@ -1,5 +1,13 @@ #include "ld2410.h" +#include +#ifdef USE_NUMBER +#include "esphome/components/number/number.h" +#endif +#ifdef USE_SENSOR +#include "esphome/components/sensor/sensor.h" +#endif + #define highbyte(val) (uint8_t)((val) >> 8) #define lowbyte(val) (uint8_t)((val) &0xff) @@ -8,48 +16,97 @@ namespace ld2410 { static const char *const TAG = "ld2410"; +LD2410Component::LD2410Component() {} + void LD2410Component::dump_config() { ESP_LOGCONFIG(TAG, "LD2410:"); #ifdef USE_BINARY_SENSOR - LOG_BINARY_SENSOR(" ", "HasTargetSensor", this->target_binary_sensor_); - LOG_BINARY_SENSOR(" ", "MovingSensor", this->moving_binary_sensor_); - LOG_BINARY_SENSOR(" ", "StillSensor", this->still_binary_sensor_); + LOG_BINARY_SENSOR(" ", "TargetBinarySensor", this->target_binary_sensor_); + LOG_BINARY_SENSOR(" ", "MovingTargetBinarySensor", this->moving_target_binary_sensor_); + LOG_BINARY_SENSOR(" ", "StillTargetBinarySensor", this->still_target_binary_sensor_); + LOG_BINARY_SENSOR(" ", "OutPinPresenceStatusBinarySensor", this->out_pin_presence_status_binary_sensor_); +#endif +#ifdef USE_SWITCH + LOG_SWITCH(" ", "EngineeringModeSwitch", this->engineering_mode_switch_); + LOG_SWITCH(" ", "BluetoothSwitch", this->bluetooth_switch_); +#endif +#ifdef USE_BUTTON + LOG_BUTTON(" ", "ResetButton", this->reset_button_); + LOG_BUTTON(" ", "RestartButton", this->restart_button_); + LOG_BUTTON(" ", "QueryButton", this->query_button_); #endif #ifdef USE_SENSOR - LOG_SENSOR(" ", "Moving Distance", this->moving_target_distance_sensor_); - LOG_SENSOR(" ", "Still Distance", this->still_target_distance_sensor_); - LOG_SENSOR(" ", "Moving Energy", this->moving_target_energy_sensor_); - LOG_SENSOR(" ", "Still Energy", this->still_target_energy_sensor_); - LOG_SENSOR(" ", "Detection Distance", this->detection_distance_sensor_); + LOG_SENSOR(" ", "LightSensor", this->light_sensor_); + LOG_SENSOR(" ", "MovingTargetDistanceSensor", this->moving_target_distance_sensor_); + LOG_SENSOR(" ", "StillTargetDistanceSensor", this->still_target_distance_sensor_); + LOG_SENSOR(" ", "MovingTargetEnergySensor", this->moving_target_energy_sensor_); + LOG_SENSOR(" ", "StillTargetEnergySensor", this->still_target_energy_sensor_); + LOG_SENSOR(" ", "DetectionDistanceSensor", this->detection_distance_sensor_); + for (sensor::Sensor *s : this->gate_still_sensors_) { + LOG_SENSOR(" ", "NthGateStillSesnsor", s); + } + for (sensor::Sensor *s : this->gate_move_sensors_) { + LOG_SENSOR(" ", "NthGateMoveSesnsor", s); + } #endif - this->set_config_mode_(true); - this->get_version_(); - this->set_config_mode_(false); - ESP_LOGCONFIG(TAG, " Firmware Version : %u.%u.%u%u%u%u", this->version_[0], this->version_[1], this->version_[2], - this->version_[3], this->version_[4], this->version_[5]); +#ifdef USE_TEXT_SENSOR + LOG_TEXT_SENSOR(" ", "VersionTextSensor", this->version_text_sensor_); + LOG_TEXT_SENSOR(" ", "MacTextSensor", this->mac_text_sensor_); +#endif +#ifdef USE_SELECT + LOG_SELECT(" ", "LightFunctionSelect", this->light_function_select_); + LOG_SELECT(" ", "OutPinLevelSelect", this->out_pin_level_select_); + LOG_SELECT(" ", "DistanceResolutionSelect", this->distance_resolution_select_); + LOG_SELECT(" ", "BaudRateSelect", this->baud_rate_select_); +#endif +#ifdef USE_NUMBER + LOG_NUMBER(" ", "LightThresholdNumber", this->light_threshold_number_); + LOG_NUMBER(" ", "MaxStillDistanceGateNumber", this->max_still_distance_gate_number_); + LOG_NUMBER(" ", "MaxMoveDistanceGateNumber", this->max_move_distance_gate_number_); + LOG_NUMBER(" ", "TimeoutNumber", this->timeout_number_); + for (number::Number *n : this->gate_still_threshold_numbers_) { + LOG_NUMBER(" ", "Still Thresholds Number", n); + } + for (number::Number *n : this->gate_move_threshold_numbers_) { + LOG_NUMBER(" ", "Move Thresholds Number", n); + } +#endif + this->read_all_info(); + ESP_LOGCONFIG(TAG, " Throttle_ : %ums", this->throttle_); + ESP_LOGCONFIG(TAG, " MAC Address : %s", const_cast(this->mac_.c_str())); + ESP_LOGCONFIG(TAG, " Firmware Version : %s", const_cast(this->version_.c_str())); } void LD2410Component::setup() { ESP_LOGCONFIG(TAG, "Setting up LD2410..."); - this->set_config_mode_(true); - this->set_max_distances_timeout_(this->max_move_distance_, this->max_still_distance_, this->timeout_); - // Configure Gates sensitivity - this->set_gate_threshold_(0, this->rg0_move_threshold_, this->rg0_still_threshold_); - this->set_gate_threshold_(1, this->rg1_move_threshold_, this->rg1_still_threshold_); - this->set_gate_threshold_(2, this->rg2_move_threshold_, this->rg2_still_threshold_); - this->set_gate_threshold_(3, this->rg3_move_threshold_, this->rg3_still_threshold_); - this->set_gate_threshold_(4, this->rg4_move_threshold_, this->rg4_still_threshold_); - this->set_gate_threshold_(5, this->rg5_move_threshold_, this->rg5_still_threshold_); - this->set_gate_threshold_(6, this->rg6_move_threshold_, this->rg6_still_threshold_); - this->set_gate_threshold_(7, this->rg7_move_threshold_, this->rg7_still_threshold_); - this->set_gate_threshold_(8, this->rg8_move_threshold_, this->rg8_still_threshold_); - this->get_version_(); - this->set_config_mode_(false); - ESP_LOGCONFIG(TAG, "Firmware Version : %u.%u.%u%u%u%u", this->version_[0], this->version_[1], this->version_[2], - this->version_[3], this->version_[4], this->version_[5]); + this->read_all_info(); + ESP_LOGCONFIG(TAG, "Mac Address : %s", const_cast(this->mac_.c_str())); + ESP_LOGCONFIG(TAG, "Firmware Version : %s", const_cast(this->version_.c_str())); ESP_LOGCONFIG(TAG, "LD2410 setup complete."); } +void LD2410Component::read_all_info() { + this->set_config_mode_(true); + this->get_version_(); + this->get_mac_(); + this->get_distance_resolution_(); + this->get_light_control_(); + this->query_parameters_(); + this->set_config_mode_(false); +#ifdef USE_SELECT + const auto baud_rate = std::to_string(this->parent_->get_baud_rate()); + if (this->baud_rate_select_ != nullptr && this->baud_rate_select_->state != baud_rate) { + this->baud_rate_select_->publish_state(baud_rate); + } +#endif +} + +void LD2410Component::restart_and_read_all_info() { + this->set_config_mode_(true); + this->restart_(); + this->set_timeout(1000, [this]() { this->read_all_info(); }); +} + void LD2410Component::loop() { const int max_line_length = 80; static uint8_t buffer[max_line_length]; @@ -59,9 +116,8 @@ void LD2410Component::loop() { } } -void LD2410Component::send_command_(uint8_t command, uint8_t *command_value, int command_value_len) { - // lastCommandSuccess->publish_state(false); - +void LD2410Component::send_command_(uint8_t command, const uint8_t *command_value, int command_value_len) { + ESP_LOGV(TAG, "Sending COMMAND %02X", command); // frame start bytes this->write_array(CMD_FRAME_HEADER, 4); // length bytes @@ -95,40 +151,43 @@ void LD2410Component::handle_periodic_data_(uint8_t *buffer, int len) { if (buffer[7] != HEAD || buffer[len - 6] != END || buffer[len - 5] != CHECK) // Check constant values return; // data head=0xAA, data end=0x55, crc=0x00 - /* - Data Type: 6th - 0x01: Engineering mode - 0x02: Normal mode - */ - // char data_type = buffer[DATA_TYPES]; - /* - Target states: 9th - 0x00 = No target - 0x01 = Moving targets - 0x02 = Still targets - 0x03 = Moving+Still targets - */ -#ifdef USE_BINARY_SENSOR - char target_state = buffer[TARGET_STATES]; - if (this->target_binary_sensor_ != nullptr) { - this->target_binary_sensor_->publish_state(target_state != 0x00); - } -#endif - /* Reduce data update rate to prevent home assistant database size grow fast */ int32_t current_millis = millis(); - if (current_millis - last_periodic_millis < 1000) + if (current_millis - last_periodic_millis_ < this->throttle_) return; - last_periodic_millis = current_millis; + last_periodic_millis_ = current_millis; -#ifdef USE_BINARY_SENSOR - if (this->moving_binary_sensor_ != nullptr) { - this->moving_binary_sensor_->publish_state(CHECK_BIT(target_state, 0)); + /* + Data Type: 7th + 0x01: Engineering mode + 0x02: Normal mode + */ + bool engineering_mode = buffer[DATA_TYPES] == 0x01; +#ifdef USE_SWITCH + if (this->engineering_mode_switch_ != nullptr && + current_millis - last_engineering_mode_change_millis_ > this->throttle_) { + this->engineering_mode_switch_->publish_state(engineering_mode); } - if (this->still_binary_sensor_ != nullptr) { - this->still_binary_sensor_->publish_state(CHECK_BIT(target_state, 1)); +#endif +#ifdef USE_BINARY_SENSOR + /* + Target states: 9th + 0x00 = No target + 0x01 = Moving targets + 0x02 = Still targets + 0x03 = Moving+Still targets + */ + char target_state = buffer[TARGET_STATES]; + if (this->target_binary_sensor_ != nullptr) { + this->target_binary_sensor_->publish_state(target_state != 0x00); + } + if (this->moving_target_binary_sensor_ != nullptr) { + this->moving_target_binary_sensor_->publish_state(CHECK_BIT(target_state, 0)); + } + if (this->still_target_binary_sensor_ != nullptr) { + this->still_target_binary_sensor_->publish_state(CHECK_BIT(target_state, 1)); } #endif /* @@ -164,26 +223,126 @@ void LD2410Component::handle_periodic_data_(uint8_t *buffer, int len) { if (this->detection_distance_sensor_->get_state() != new_detect_distance) this->detection_distance_sensor_->publish_state(new_detect_distance); } + if (engineering_mode) { + /* + Moving distance range: 18th byte + Still distance range: 19th byte + Moving enery: 20~28th bytes + */ + for (std::vector::size_type i = 0; i != this->gate_move_sensors_.size(); i++) { + sensor::Sensor *s = this->gate_move_sensors_[i]; + if (s != nullptr) { + s->publish_state(buffer[MOVING_SENSOR_START + i]); + } + } + /* + Still energy: 29~37th bytes + */ + for (std::vector::size_type i = 0; i != this->gate_still_sensors_.size(); i++) { + sensor::Sensor *s = this->gate_still_sensors_[i]; + if (s != nullptr) { + s->publish_state(buffer[STILL_SENSOR_START + i]); + } + } + /* + Light sensor: 38th bytes + */ + if (this->light_sensor_ != nullptr) { + int new_light_sensor = buffer[LIGHT_SENSOR]; + if (this->light_sensor_->get_state() != new_light_sensor) + this->light_sensor_->publish_state(new_light_sensor); + } + } else { + for (auto *s : this->gate_move_sensors_) { + if (s != nullptr && !std::isnan(s->get_state())) { + s->publish_state(NAN); + } + } + for (auto *s : this->gate_still_sensors_) { + if (s != nullptr && !std::isnan(s->get_state())) { + s->publish_state(NAN); + } + } + if (this->light_sensor_ != nullptr && !std::isnan(this->light_sensor_->get_state())) { + this->light_sensor_->publish_state(NAN); + } + } +#endif +#ifdef USE_BINARY_SENSOR + if (engineering_mode) { + if (this->out_pin_presence_status_binary_sensor_ != nullptr) { + this->out_pin_presence_status_binary_sensor_->publish_state(buffer[OUT_PIN_SENSOR] == 0x01); + } + } else { + if (this->out_pin_presence_status_binary_sensor_ != nullptr) { + this->out_pin_presence_status_binary_sensor_->publish_state(false); + } + } #endif } -void LD2410Component::handle_ack_data_(uint8_t *buffer, int len) { - ESP_LOGV(TAG, "Handling ACK DATA for COMMAND"); +const char VERSION_FMT[] = "%u.%02X.%02X%02X%02X%02X"; + +std::string format_version(uint8_t *buffer) { + std::string::size_type version_size = 256; + std::string version; + do { + version.resize(version_size + 1); + version_size = std::snprintf(&version[0], version.size(), VERSION_FMT, buffer[13], buffer[12], buffer[17], + buffer[16], buffer[15], buffer[14]); + } while (version_size + 1 > version.size()); + version.resize(version_size); + return version; +} + +const char MAC_FMT[] = "%02X:%02X:%02X:%02X:%02X:%02X"; + +const std::string UNKNOWN_MAC("unknown"); +const std::string NO_MAC("08:05:04:03:02:01"); + +std::string format_mac(uint8_t *buffer) { + std::string::size_type mac_size = 256; + std::string mac; + do { + mac.resize(mac_size + 1); + mac_size = std::snprintf(&mac[0], mac.size(), MAC_FMT, buffer[10], buffer[11], buffer[12], buffer[13], buffer[14], + buffer[15]); + } while (mac_size + 1 > mac.size()); + mac.resize(mac_size); + if (mac == NO_MAC) { + return UNKNOWN_MAC; + } + return mac; +} + +#ifdef USE_NUMBER +std::function set_number_value(number::Number *n, float value) { + float normalized_value = value * 1.0; + if (n != nullptr && (!n->has_state() || n->state != normalized_value)) { + n->state = normalized_value; + return [n, normalized_value]() { n->publish_state(normalized_value); }; + } + return []() {}; +} +#endif + +bool LD2410Component::handle_ack_data_(uint8_t *buffer, int len) { + ESP_LOGV(TAG, "Handling ACK DATA for COMMAND %02X", buffer[COMMAND]); if (len < 10) { ESP_LOGE(TAG, "Error with last command : incorrect length"); - return; + return true; } if (buffer[0] != 0xFD || buffer[1] != 0xFC || buffer[2] != 0xFB || buffer[3] != 0xFA) { // check 4 frame start bytes ESP_LOGE(TAG, "Error with last command : incorrect Header"); - return; + return true; } if (buffer[COMMAND_STATUS] != 0x01) { ESP_LOGE(TAG, "Error with last command : status != 0x01"); - return; + return true; } if (this->two_byte_to_int_(buffer[8], buffer[9]) != 0x00) { ESP_LOGE(TAG, "Error with last command , last buffer was: %u , %u", buffer[8], buffer[9]); - return; + return true; } switch (buffer[COMMAND]) { @@ -193,49 +352,127 @@ void LD2410Component::handle_ack_data_(uint8_t *buffer, int len) { case lowbyte(CMD_DISABLE_CONF): ESP_LOGV(TAG, "Handled Disabled conf command"); break; + case lowbyte(CMD_SET_BAUD_RATE): + ESP_LOGV(TAG, "Handled baud rate change command"); +#ifdef USE_SELECT + if (this->baud_rate_select_ != nullptr) { + ESP_LOGE(TAG, "Change baud rate component config to %s and reinstall", this->baud_rate_select_->state.c_str()); + } +#endif + break; case lowbyte(CMD_VERSION): - ESP_LOGV(TAG, "FW Version is: %u.%u.%u%u%u%u", buffer[13], buffer[12], buffer[17], buffer[16], buffer[15], - buffer[14]); - this->version_[0] = buffer[13]; - this->version_[1] = buffer[12]; - this->version_[2] = buffer[17]; - this->version_[3] = buffer[16]; - this->version_[4] = buffer[15]; - this->version_[5] = buffer[14]; - + this->version_ = format_version(buffer); + ESP_LOGV(TAG, "FW Version is: %s", const_cast(this->version_.c_str())); +#ifdef USE_TEXT_SENSOR + if (this->version_text_sensor_ != nullptr) { + this->version_text_sensor_->publish_state(this->version_); + } +#endif + break; + case lowbyte(CMD_QUERY_DISTANCE_RESOLUTION): { + std::string distance_resolution = + DISTANCE_RESOLUTION_INT_TO_ENUM.at(this->two_byte_to_int_(buffer[10], buffer[11])); + ESP_LOGV(TAG, "Distance resolution is: %s", const_cast(distance_resolution.c_str())); +#ifdef USE_SELECT + if (this->distance_resolution_select_ != nullptr && + this->distance_resolution_select_->state != distance_resolution) { + this->distance_resolution_select_->publish_state(distance_resolution); + } +#endif + } break; + case lowbyte(CMD_QUERY_LIGHT_CONTROL): { + this->light_function_ = LIGHT_FUNCTION_INT_TO_ENUM.at(buffer[10]); + this->light_threshold_ = buffer[11] * 1.0; + this->out_pin_level_ = OUT_PIN_LEVEL_INT_TO_ENUM.at(buffer[12]); + ESP_LOGV(TAG, "Light function is: %s", const_cast(this->light_function_.c_str())); + ESP_LOGV(TAG, "Light threshold is: %f", this->light_threshold_); + ESP_LOGV(TAG, "Out pin level is: %s", const_cast(this->out_pin_level_.c_str())); +#ifdef USE_SELECT + if (this->light_function_select_ != nullptr && this->light_function_select_->state != this->light_function_) { + this->light_function_select_->publish_state(this->light_function_); + } + if (this->out_pin_level_select_ != nullptr && this->out_pin_level_select_->state != this->out_pin_level_) { + this->out_pin_level_select_->publish_state(this->out_pin_level_); + } +#endif +#ifdef USE_NUMBER + if (this->light_threshold_number_ != nullptr && + (!this->light_threshold_number_->has_state() || + this->light_threshold_number_->state != this->light_threshold_)) { + this->light_threshold_number_->publish_state(this->light_threshold_); + } +#endif + } break; + case lowbyte(CMD_MAC): + if (len < 20) { + return false; + } + this->mac_ = format_mac(buffer); + ESP_LOGV(TAG, "MAC Address is: %s", const_cast(this->mac_.c_str())); +#ifdef USE_TEXT_SENSOR + if (this->mac_text_sensor_ != nullptr) { + this->mac_text_sensor_->publish_state(this->mac_); + } +#endif +#ifdef USE_SWITCH + if (this->bluetooth_switch_ != nullptr) { + this->bluetooth_switch_->publish_state(this->mac_ != UNKNOWN_MAC); + } +#endif break; case lowbyte(CMD_GATE_SENS): ESP_LOGV(TAG, "Handled sensitivity command"); break; + case lowbyte(CMD_BLUETOOTH): + ESP_LOGV(TAG, "Handled bluetooth command"); + break; + case lowbyte(CMD_SET_DISTANCE_RESOLUTION): + ESP_LOGV(TAG, "Handled set distance resolution command"); + break; + case lowbyte(CMD_SET_LIGHT_CONTROL): + ESP_LOGV(TAG, "Handled set light control command"); + break; + case lowbyte(CMD_BT_PASSWORD): + ESP_LOGV(TAG, "Handled set bluetooth password command"); + break; case lowbyte(CMD_QUERY): // Query parameters response { if (buffer[10] != 0xAA) - return; // value head=0xAA + return true; // value head=0xAA +#ifdef USE_NUMBER /* Moving distance range: 13th byte Still distance range: 14th byte */ - // TODO - // maxMovingDistanceRange->publish_state(buffer[12]); - // maxStillDistanceRange->publish_state(buffer[13]); + std::vector> updates; + updates.push_back(set_number_value(this->max_move_distance_gate_number_, buffer[12])); + updates.push_back(set_number_value(this->max_still_distance_gate_number_, buffer[13])); /* Moving Sensitivities: 15~23th bytes + */ + for (std::vector::size_type i = 0; i != this->gate_move_threshold_numbers_.size(); i++) { + updates.push_back(set_number_value(this->gate_move_threshold_numbers_[i], buffer[14 + i])); + } + /* Still Sensitivities: 24~32th bytes */ - for (int i = 0; i < 9; i++) { - moving_sensitivities[i] = buffer[14 + i]; - } - for (int i = 0; i < 9; i++) { - still_sensitivities[i] = buffer[23 + i]; + for (std::vector::size_type i = 0; i != this->gate_still_threshold_numbers_.size(); i++) { + updates.push_back(set_number_value(this->gate_still_threshold_numbers_[i], buffer[23 + i])); } /* None Duration: 33~34th bytes */ - // noneDuration->publish_state(this->two_byte_to_int_(buffer[32], buffer[33])); + updates.push_back(set_number_value(this->timeout_number_, this->two_byte_to_int_(buffer[32], buffer[33]))); + for (auto &update : updates) { + update(); + } +#endif } break; default: break; } + + return true; } void LD2410Component::readline_(int readch, uint8_t *buffer, int len) { @@ -256,8 +493,11 @@ void LD2410Component::readline_(int readch, uint8_t *buffer, int len) { } else if (buffer[pos - 4] == 0x04 && buffer[pos - 3] == 0x03 && buffer[pos - 2] == 0x02 && buffer[pos - 1] == 0x01) { ESP_LOGV(TAG, "Will handle ACK Data"); - this->handle_ack_data_(buffer, pos); - pos = 0; // Reset position index ready for next time + if (this->handle_ack_data_(buffer, pos)) { + pos = 0; // Reset position index ready for next time + } else { + ESP_LOGV(TAG, "ACK Data incomplete"); + } } } } @@ -269,21 +509,85 @@ void LD2410Component::set_config_mode_(bool enable) { this->send_command_(cmd, enable ? cmd_value : nullptr, 2); } +void LD2410Component::set_bluetooth(bool enable) { + this->set_config_mode_(true); + uint8_t enable_cmd_value[2] = {0x01, 0x00}; + uint8_t disable_cmd_value[2] = {0x00, 0x00}; + this->send_command_(CMD_BLUETOOTH, enable ? enable_cmd_value : disable_cmd_value, 2); + this->set_timeout(200, [this]() { this->restart_and_read_all_info(); }); +} + +void LD2410Component::set_distance_resolution(const std::string &state) { + this->set_config_mode_(true); + uint8_t cmd_value[2] = {DISTANCE_RESOLUTION_ENUM_TO_INT.at(state), 0x00}; + this->send_command_(CMD_SET_DISTANCE_RESOLUTION, cmd_value, 2); + this->set_timeout(200, [this]() { this->restart_and_read_all_info(); }); +} + +void LD2410Component::set_baud_rate(const std::string &state) { + this->set_config_mode_(true); + uint8_t cmd_value[2] = {BAUD_RATE_ENUM_TO_INT.at(state), 0x00}; + this->send_command_(CMD_SET_BAUD_RATE, cmd_value, 2); + this->set_timeout(200, [this]() { this->restart_(); }); +} + +void LD2410Component::set_bluetooth_password(const std::string &password) { + if (password.length() != 6) { + ESP_LOGE(TAG, "set_bluetooth_password(): invalid password length, must be exactly 6 chars '%s'", password.c_str()); + return; + } + this->set_config_mode_(true); + uint8_t cmd_value[6]; + std::copy(password.begin(), password.end(), std::begin(cmd_value)); + this->send_command_(CMD_BT_PASSWORD, cmd_value, 6); + this->set_config_mode_(false); +} + +void LD2410Component::set_engineering_mode(bool enable) { + this->set_config_mode_(true); + last_engineering_mode_change_millis_ = millis(); + uint8_t cmd = enable ? CMD_ENABLE_ENG : CMD_DISABLE_ENG; + this->send_command_(cmd, nullptr, 0); + this->set_config_mode_(false); +} + +void LD2410Component::factory_reset() { + this->set_config_mode_(true); + this->send_command_(CMD_RESET, nullptr, 0); + this->set_timeout(200, [this]() { this->restart_and_read_all_info(); }); +} + +void LD2410Component::restart_() { this->send_command_(CMD_RESTART, nullptr, 0); } + void LD2410Component::query_parameters_() { this->send_command_(CMD_QUERY, nullptr, 0); } void LD2410Component::get_version_() { this->send_command_(CMD_VERSION, nullptr, 0); } +void LD2410Component::get_mac_() { + uint8_t cmd_value[2] = {0x01, 0x00}; + this->send_command_(CMD_MAC, cmd_value, 2); +} +void LD2410Component::get_distance_resolution_() { this->send_command_(CMD_QUERY_DISTANCE_RESOLUTION, nullptr, 0); } -void LD2410Component::set_max_distances_timeout_(uint8_t max_moving_distance_range, uint8_t max_still_distance_range, - uint16_t timeout) { +void LD2410Component::get_light_control_() { this->send_command_(CMD_QUERY_LIGHT_CONTROL, nullptr, 0); } + +#ifdef USE_NUMBER +void LD2410Component::set_max_distances_timeout() { + if (!this->max_move_distance_gate_number_->has_state() || !this->max_still_distance_gate_number_->has_state() || + !this->timeout_number_->has_state()) { + return; + } + int max_moving_distance_gate_range = static_cast(this->max_move_distance_gate_number_->state); + int max_still_distance_gate_range = static_cast(this->max_still_distance_gate_number_->state); + int timeout = static_cast(this->timeout_number_->state); uint8_t value[18] = {0x00, 0x00, - lowbyte(max_moving_distance_range), - highbyte(max_moving_distance_range), + lowbyte(max_moving_distance_gate_range), + highbyte(max_moving_distance_gate_range), 0x00, 0x00, 0x01, 0x00, - lowbyte(max_still_distance_range), - highbyte(max_still_distance_range), + lowbyte(max_still_distance_gate_range), + highbyte(max_still_distance_gate_range), 0x00, 0x00, 0x02, @@ -292,10 +596,25 @@ void LD2410Component::set_max_distances_timeout_(uint8_t max_moving_distance_ran highbyte(timeout), 0x00, 0x00}; + this->set_config_mode_(true); this->send_command_(CMD_MAXDIST_DURATION, value, 18); + delay(50); // NOLINT this->query_parameters_(); + this->set_timeout(200, [this]() { this->restart_and_read_all_info(); }); + this->set_config_mode_(false); } -void LD2410Component::set_gate_threshold_(uint8_t gate, uint8_t motionsens, uint8_t stillsens) { + +void LD2410Component::set_gate_threshold(uint8_t gate) { + number::Number *motionsens = this->gate_move_threshold_numbers_[gate]; + number::Number *stillsens = this->gate_still_threshold_numbers_[gate]; + + if (!motionsens->has_state() || !stillsens->has_state()) { + return; + } + int motion = static_cast(motionsens->state); + int still = static_cast(stillsens->state); + + this->set_config_mode_(true); // reference // https://drive.google.com/drive/folders/1p4dhbEJA3YubyIjIIC7wwVsSo8x29Fq-?spm=a2g0o.detail.1000023.17.93465697yFwVxH // Send data: configure the motion sensitivity of distance gate 3 to 40, and the static sensitivity of 40 @@ -305,11 +624,57 @@ void LD2410Component::set_gate_threshold_(uint8_t gate, uint8_t motionsens, uint // 28 00 00 00 (value) // 02 00 (still sensitivtiy) // 28 00 00 00 (value) - uint8_t value[18] = {0x00, 0x00, lowbyte(gate), highbyte(gate), 0x00, 0x00, - 0x01, 0x00, lowbyte(motionsens), highbyte(motionsens), 0x00, 0x00, - 0x02, 0x00, lowbyte(stillsens), highbyte(stillsens), 0x00, 0x00}; + uint8_t value[18] = {0x00, 0x00, lowbyte(gate), highbyte(gate), 0x00, 0x00, + 0x01, 0x00, lowbyte(motion), highbyte(motion), 0x00, 0x00, + 0x02, 0x00, lowbyte(still), highbyte(still), 0x00, 0x00}; this->send_command_(CMD_GATE_SENS, value, 18); + delay(50); // NOLINT + this->query_parameters_(); + this->set_config_mode_(false); } +void LD2410Component::set_gate_still_threshold_number(int gate, number::Number *n) { + this->gate_still_threshold_numbers_[gate] = n; +} + +void LD2410Component::set_gate_move_threshold_number(int gate, number::Number *n) { + this->gate_move_threshold_numbers_[gate] = n; +} +#endif + +void LD2410Component::set_light_out_control() { +#ifdef USE_NUMBER + if (this->light_threshold_number_ != nullptr && this->light_threshold_number_->has_state()) { + this->light_threshold_ = this->light_threshold_number_->state; + } +#endif +#ifdef USE_SELECT + if (this->light_function_select_ != nullptr && this->light_function_select_->has_state()) { + this->light_function_ = this->light_function_select_->state; + } + if (this->out_pin_level_select_ != nullptr && this->out_pin_level_select_->has_state()) { + this->out_pin_level_ = this->out_pin_level_select_->state; + } +#endif + if (this->light_function_.empty() || this->out_pin_level_.empty() || this->light_threshold_ < 0) { + return; + } + this->set_config_mode_(true); + uint8_t light_function = LIGHT_FUNCTION_ENUM_TO_INT.at(this->light_function_); + uint8_t light_threshold = static_cast(this->light_threshold_); + uint8_t out_pin_level = OUT_PIN_LEVEL_ENUM_TO_INT.at(this->out_pin_level_); + uint8_t value[4] = {light_function, light_threshold, out_pin_level, 0x00}; + this->send_command_(CMD_SET_LIGHT_CONTROL, value, 4); + delay(50); // NOLINT + this->get_light_control_(); + this->set_timeout(200, [this]() { this->restart_and_read_all_info(); }); + this->set_config_mode_(false); +} + +#ifdef USE_SENSOR +void LD2410Component::set_gate_move_sensor(int gate, sensor::Sensor *s) { this->gate_move_sensors_[gate] = s; } +void LD2410Component::set_gate_still_sensor(int gate, sensor::Sensor *s) { this->gate_still_sensors_[gate] = s; } +#endif + } // namespace ld2410 } // namespace esphome diff --git a/esphome/components/ld2410/ld2410.h b/esphome/components/ld2410/ld2410.h index 8edb83a8d5..8084d4c33e 100644 --- a/esphome/components/ld2410/ld2410.h +++ b/esphome/components/ld2410/ld2410.h @@ -7,10 +7,27 @@ #ifdef USE_SENSOR #include "esphome/components/sensor/sensor.h" #endif +#ifdef USE_NUMBER +#include "esphome/components/number/number.h" +#endif +#ifdef USE_SWITCH +#include "esphome/components/switch/switch.h" +#endif +#ifdef USE_BUTTON +#include "esphome/components/button/button.h" +#endif +#ifdef USE_SELECT +#include "esphome/components/select/select.h" +#endif +#ifdef USE_TEXT_SENSOR +#include "esphome/components/text_sensor/text_sensor.h" +#endif #include "esphome/components/uart/uart.h" #include "esphome/core/automation.h" #include "esphome/core/helpers.h" +#include + namespace esphome { namespace ld2410 { @@ -19,10 +36,63 @@ namespace ld2410 { // Commands static const uint8_t CMD_ENABLE_CONF = 0x00FF; static const uint8_t CMD_DISABLE_CONF = 0x00FE; +static const uint8_t CMD_ENABLE_ENG = 0x0062; +static const uint8_t CMD_DISABLE_ENG = 0x0063; static const uint8_t CMD_MAXDIST_DURATION = 0x0060; static const uint8_t CMD_QUERY = 0x0061; static const uint8_t CMD_GATE_SENS = 0x0064; static const uint8_t CMD_VERSION = 0x00A0; +static const uint8_t CMD_QUERY_DISTANCE_RESOLUTION = 0x00AB; +static const uint8_t CMD_SET_DISTANCE_RESOLUTION = 0x00AA; +static const uint8_t CMD_QUERY_LIGHT_CONTROL = 0x00AE; +static const uint8_t CMD_SET_LIGHT_CONTROL = 0x00AD; +static const uint8_t CMD_SET_BAUD_RATE = 0x00A1; +static const uint8_t CMD_BT_PASSWORD = 0x00A9; +static const uint8_t CMD_MAC = 0x00A5; +static const uint8_t CMD_RESET = 0x00A2; +static const uint8_t CMD_RESTART = 0x00A3; +static const uint8_t CMD_BLUETOOTH = 0x00A4; + +enum BaudRateStructure : uint8_t { + BAUD_RATE_9600 = 1, + BAUD_RATE_19200 = 2, + BAUD_RATE_38400 = 3, + BAUD_RATE_57600 = 4, + BAUD_RATE_115200 = 5, + BAUD_RATE_230400 = 6, + BAUD_RATE_256000 = 7, + BAUD_RATE_460800 = 8 +}; + +static const std::map BAUD_RATE_ENUM_TO_INT{ + {"9600", BAUD_RATE_9600}, {"19200", BAUD_RATE_19200}, {"38400", BAUD_RATE_38400}, + {"57600", BAUD_RATE_57600}, {"115200", BAUD_RATE_115200}, {"230400", BAUD_RATE_230400}, + {"256000", BAUD_RATE_256000}, {"460800", BAUD_RATE_460800}}; + +enum DistanceResolutionStructure : uint8_t { DISTANCE_RESOLUTION_0_2 = 0x01, DISTANCE_RESOLUTION_0_75 = 0x00 }; + +static const std::map DISTANCE_RESOLUTION_ENUM_TO_INT{{"0.2m", DISTANCE_RESOLUTION_0_2}, + {"0.75m", DISTANCE_RESOLUTION_0_75}}; +static const std::map DISTANCE_RESOLUTION_INT_TO_ENUM{{DISTANCE_RESOLUTION_0_2, "0.2m"}, + {DISTANCE_RESOLUTION_0_75, "0.75m"}}; + +enum LightFunctionStructure : uint8_t { + LIGHT_FUNCTION_OFF = 0x00, + LIGHT_FUNCTION_BELOW = 0x01, + LIGHT_FUNCTION_ABOVE = 0x02 +}; + +static const std::map LIGHT_FUNCTION_ENUM_TO_INT{ + {"off", LIGHT_FUNCTION_OFF}, {"below", LIGHT_FUNCTION_BELOW}, {"above", LIGHT_FUNCTION_ABOVE}}; +static const std::map LIGHT_FUNCTION_INT_TO_ENUM{ + {LIGHT_FUNCTION_OFF, "off"}, {LIGHT_FUNCTION_BELOW, "below"}, {LIGHT_FUNCTION_ABOVE, "above"}}; + +enum OutPinLevelStructure : uint8_t { OUT_PIN_LEVEL_LOW = 0x00, OUT_PIN_LEVEL_HIGH = 0x01 }; + +static const std::map OUT_PIN_LEVEL_ENUM_TO_INT{{"low", OUT_PIN_LEVEL_LOW}, + {"high", OUT_PIN_LEVEL_HIGH}}; +static const std::map OUT_PIN_LEVEL_INT_TO_ENUM{{OUT_PIN_LEVEL_LOW, "low"}, + {OUT_PIN_LEVEL_HIGH, "high"}}; // Commands values static const uint8_t CMD_MAX_MOVE_VALUE = 0x0000; @@ -44,7 +114,7 @@ Target states: 9th byte Detect distance: 16~17th bytes */ enum PeriodicDataStructure : uint8_t { - DATA_TYPES = 5, + DATA_TYPES = 6, TARGET_STATES = 8, MOVING_TARGET_LOW = 9, MOVING_TARGET_HIGH = 10, @@ -54,6 +124,10 @@ enum PeriodicDataStructure : uint8_t { STILL_ENERGY = 14, DETECT_DISTANCE_LOW = 15, DETECT_DISTANCE_HIGH = 16, + MOVING_SENSOR_START = 19, + STILL_SENSOR_START = 28, + LIGHT_SENSOR = 37, + OUT_PIN_SENSOR = 38, }; enum PeriodicDataValue : uint8_t { HEAD = 0XAA, END = 0x55, CHECK = 0x00 }; @@ -66,80 +140,97 @@ class LD2410Component : public Component, public uart::UARTDevice { SUB_SENSOR(still_target_distance) SUB_SENSOR(moving_target_energy) SUB_SENSOR(still_target_energy) + SUB_SENSOR(light) SUB_SENSOR(detection_distance) #endif +#ifdef USE_BINARY_SENSOR + SUB_BINARY_SENSOR(target) + SUB_BINARY_SENSOR(moving_target) + SUB_BINARY_SENSOR(still_target) + SUB_BINARY_SENSOR(out_pin_presence_status) +#endif +#ifdef USE_TEXT_SENSOR + SUB_TEXT_SENSOR(version) + SUB_TEXT_SENSOR(mac) +#endif +#ifdef USE_SELECT + SUB_SELECT(distance_resolution) + SUB_SELECT(baud_rate) + SUB_SELECT(light_function) + SUB_SELECT(out_pin_level) +#endif +#ifdef USE_SWITCH + SUB_SWITCH(engineering_mode) + SUB_SWITCH(bluetooth) +#endif +#ifdef USE_BUTTON + SUB_BUTTON(reset) + SUB_BUTTON(restart) + SUB_BUTTON(query) +#endif +#ifdef USE_NUMBER + SUB_NUMBER(max_still_distance_gate) + SUB_NUMBER(max_move_distance_gate) + SUB_NUMBER(timeout) + SUB_NUMBER(light_threshold) +#endif public: + LD2410Component(); void setup() override; void dump_config() override; void loop() override; - -#ifdef USE_BINARY_SENSOR - void set_target_sensor(binary_sensor::BinarySensor *sens) { this->target_binary_sensor_ = sens; }; - void set_moving_target_sensor(binary_sensor::BinarySensor *sens) { this->moving_binary_sensor_ = sens; }; - void set_still_target_sensor(binary_sensor::BinarySensor *sens) { this->still_binary_sensor_ = sens; }; + void set_light_out_control(); +#ifdef USE_NUMBER + void set_gate_still_threshold_number(int gate, number::Number *n); + void set_gate_move_threshold_number(int gate, number::Number *n); + void set_max_distances_timeout(); + void set_gate_threshold(uint8_t gate); #endif - - void set_timeout(uint16_t value) { this->timeout_ = value; }; - void set_max_move_distance(uint8_t value) { this->max_move_distance_ = value; }; - void set_max_still_distance(uint8_t value) { this->max_still_distance_ = value; }; - void set_range_config(int rg0_move, int rg0_still, int rg1_move, int rg1_still, int rg2_move, int rg2_still, - int rg3_move, int rg3_still, int rg4_move, int rg4_still, int rg5_move, int rg5_still, - int rg6_move, int rg6_still, int rg7_move, int rg7_still, int rg8_move, int rg8_still) { - this->rg0_move_threshold_ = rg0_move; - this->rg0_still_threshold_ = rg0_still; - this->rg1_move_threshold_ = rg1_move; - this->rg1_still_threshold_ = rg1_still; - this->rg2_move_threshold_ = rg2_move; - this->rg2_still_threshold_ = rg2_still; - this->rg3_move_threshold_ = rg3_move; - this->rg3_still_threshold_ = rg3_still; - this->rg4_move_threshold_ = rg4_move; - this->rg4_still_threshold_ = rg4_still; - this->rg5_move_threshold_ = rg5_move; - this->rg5_still_threshold_ = rg5_still; - this->rg6_move_threshold_ = rg6_move; - this->rg6_still_threshold_ = rg6_still; - this->rg7_move_threshold_ = rg7_move; - this->rg7_still_threshold_ = rg7_still; - this->rg8_move_threshold_ = rg8_move; - this->rg8_still_threshold_ = rg8_still; - }; - int moving_sensitivities[9] = {0}; - int still_sensitivities[9] = {0}; - - int32_t last_periodic_millis = millis(); +#ifdef USE_SENSOR + void set_gate_move_sensor(int gate, sensor::Sensor *s); + void set_gate_still_sensor(int gate, sensor::Sensor *s); +#endif + void set_throttle(uint16_t value) { this->throttle_ = value; }; + void set_bluetooth_password(const std::string &password); + void set_engineering_mode(bool enable); + void read_all_info(); + void restart_and_read_all_info(); + void set_bluetooth(bool enable); + void set_distance_resolution(const std::string &state); + void set_baud_rate(const std::string &state); + void factory_reset(); protected: -#ifdef USE_BINARY_SENSOR - binary_sensor::BinarySensor *target_binary_sensor_{nullptr}; - binary_sensor::BinarySensor *moving_binary_sensor_{nullptr}; - binary_sensor::BinarySensor *still_binary_sensor_{nullptr}; -#endif - - std::vector rx_buffer_; int two_byte_to_int_(char firstbyte, char secondbyte) { return (int16_t) (secondbyte << 8) + firstbyte; } - void send_command_(uint8_t command_str, uint8_t *command_value, int command_value_len); - - void set_max_distances_timeout_(uint8_t max_moving_distance_range, uint8_t max_still_distance_range, - uint16_t timeout); - void set_gate_threshold_(uint8_t gate, uint8_t motionsens, uint8_t stillsens); + void send_command_(uint8_t command_str, const uint8_t *command_value, int command_value_len); void set_config_mode_(bool enable); void handle_periodic_data_(uint8_t *buffer, int len); - void handle_ack_data_(uint8_t *buffer, int len); + bool handle_ack_data_(uint8_t *buffer, int len); void readline_(int readch, uint8_t *buffer, int len); void query_parameters_(); void get_version_(); + void get_mac_(); + void get_distance_resolution_(); + void get_light_control_(); + void restart_(); - uint16_t timeout_; - uint8_t max_move_distance_; - uint8_t max_still_distance_; - - uint8_t version_[6]; - uint8_t rg0_move_threshold_, rg0_still_threshold_, rg1_move_threshold_, rg1_still_threshold_, rg2_move_threshold_, - rg2_still_threshold_, rg3_move_threshold_, rg3_still_threshold_, rg4_move_threshold_, rg4_still_threshold_, - rg5_move_threshold_, rg5_still_threshold_, rg6_move_threshold_, rg6_still_threshold_, rg7_move_threshold_, - rg7_still_threshold_, rg8_move_threshold_, rg8_still_threshold_; + int32_t last_periodic_millis_ = millis(); + int32_t last_engineering_mode_change_millis_ = millis(); + uint16_t throttle_; + std::string version_; + std::string mac_; + std::string out_pin_level_; + std::string light_function_; + float light_threshold_ = -1; +#ifdef USE_NUMBER + std::vector gate_still_threshold_numbers_ = std::vector(9); + std::vector gate_move_threshold_numbers_ = std::vector(9); +#endif +#ifdef USE_SENSOR + std::vector gate_still_sensors_ = std::vector(9); + std::vector gate_move_sensors_ = std::vector(9); +#endif }; } // namespace ld2410 diff --git a/esphome/components/ld2410/number/__init__.py b/esphome/components/ld2410/number/__init__.py new file mode 100644 index 0000000000..557b226dfe --- /dev/null +++ b/esphome/components/ld2410/number/__init__.py @@ -0,0 +1,128 @@ +import esphome.codegen as cg +from esphome.components import number +import esphome.config_validation as cv +from esphome.const import ( + CONF_ID, + CONF_TIMEOUT, + DEVICE_CLASS_DISTANCE, + DEVICE_CLASS_SIGNAL_STRENGTH, + DEVICE_CLASS_ILLUMINANCE, + UNIT_SECOND, + UNIT_PERCENT, + ENTITY_CATEGORY_CONFIG, + ICON_MOTION_SENSOR, + ICON_TIMELAPSE, + ICON_LIGHTBULB, +) +from .. import CONF_LD2410_ID, LD2410Component, ld2410_ns + +GateThresholdNumber = ld2410_ns.class_("GateThresholdNumber", number.Number) +LightThresholdNumber = ld2410_ns.class_("LightThresholdNumber", number.Number) +MaxDistanceTimeoutNumber = ld2410_ns.class_("MaxDistanceTimeoutNumber", number.Number) + +CONF_MAX_MOVE_DISTANCE_GATE = "max_move_distance_gate" +CONF_MAX_STILL_DISTANCE_GATE = "max_still_distance_gate" +CONF_LIGHT_THRESHOLD = "light_threshold" +CONF_STILL_THRESHOLD = "still_threshold" +CONF_MOVE_THRESHOLD = "move_threshold" + +TIMEOUT_GROUP = "timeout" + +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(CONF_LD2410_ID): cv.use_id(LD2410Component), + cv.Inclusive(CONF_TIMEOUT, TIMEOUT_GROUP): number.number_schema( + MaxDistanceTimeoutNumber, + unit_of_measurement=UNIT_SECOND, + entity_category=ENTITY_CATEGORY_CONFIG, + icon=ICON_TIMELAPSE, + ), + cv.Inclusive(CONF_MAX_MOVE_DISTANCE_GATE, TIMEOUT_GROUP): number.number_schema( + MaxDistanceTimeoutNumber, + device_class=DEVICE_CLASS_DISTANCE, + entity_category=ENTITY_CATEGORY_CONFIG, + icon=ICON_MOTION_SENSOR, + ), + cv.Inclusive(CONF_MAX_STILL_DISTANCE_GATE, TIMEOUT_GROUP): number.number_schema( + MaxDistanceTimeoutNumber, + device_class=DEVICE_CLASS_DISTANCE, + entity_category=ENTITY_CATEGORY_CONFIG, + icon=ICON_MOTION_SENSOR, + ), + cv.Optional(CONF_LIGHT_THRESHOLD): number.number_schema( + LightThresholdNumber, + device_class=DEVICE_CLASS_ILLUMINANCE, + entity_category=ENTITY_CATEGORY_CONFIG, + icon=ICON_LIGHTBULB, + ), + } +) + +CONFIG_SCHEMA = CONFIG_SCHEMA.extend( + { + cv.Optional(f"g{x}"): cv.Schema( + { + cv.Required(CONF_MOVE_THRESHOLD): number.number_schema( + GateThresholdNumber, + device_class=DEVICE_CLASS_SIGNAL_STRENGTH, + unit_of_measurement=UNIT_PERCENT, + entity_category=ENTITY_CATEGORY_CONFIG, + icon=ICON_MOTION_SENSOR, + ), + cv.Required(CONF_STILL_THRESHOLD): number.number_schema( + GateThresholdNumber, + device_class=DEVICE_CLASS_SIGNAL_STRENGTH, + unit_of_measurement=UNIT_PERCENT, + entity_category=ENTITY_CATEGORY_CONFIG, + icon=ICON_MOTION_SENSOR, + ), + } + ) + for x in range(9) + } +) + + +async def to_code(config): + ld2410_component = await cg.get_variable(config[CONF_LD2410_ID]) + if timeout_config := config.get(CONF_TIMEOUT): + n = await number.new_number( + timeout_config, min_value=0, max_value=65535, step=1 + ) + await cg.register_parented(n, config[CONF_LD2410_ID]) + cg.add(ld2410_component.set_timeout_number(n)) + if max_move_distance_gate_config := config.get(CONF_MAX_MOVE_DISTANCE_GATE): + n = await number.new_number( + max_move_distance_gate_config, min_value=2, max_value=8, step=1 + ) + await cg.register_parented(n, config[CONF_LD2410_ID]) + cg.add(ld2410_component.set_max_move_distance_gate_number(n)) + if max_still_distance_gate_config := config.get(CONF_MAX_STILL_DISTANCE_GATE): + n = await number.new_number( + max_still_distance_gate_config, min_value=2, max_value=8, step=1 + ) + await cg.register_parented(n, config[CONF_LD2410_ID]) + cg.add(ld2410_component.set_max_still_distance_gate_number(n)) + if light_threshold_config := config.get(CONF_LIGHT_THRESHOLD): + n = await number.new_number( + light_threshold_config, min_value=0, max_value=255, step=1 + ) + await cg.register_parented(n, config[CONF_LD2410_ID]) + cg.add(ld2410_component.set_light_threshold_number(n)) + for x in range(9): + if gate_conf := config.get(f"g{x}"): + move_config = gate_conf[CONF_MOVE_THRESHOLD] + n = cg.new_Pvariable(move_config[CONF_ID], x) + await number.register_number( + n, move_config, min_value=0, max_value=100, step=1 + ) + await cg.register_parented(n, config[CONF_LD2410_ID]) + cg.add(ld2410_component.set_gate_move_threshold_number(x, n)) + + still_config = gate_conf[CONF_STILL_THRESHOLD] + n = cg.new_Pvariable(still_config[CONF_ID], x) + await number.register_number( + n, still_config, min_value=0, max_value=100, step=1 + ) + await cg.register_parented(n, config[CONF_LD2410_ID]) + cg.add(ld2410_component.set_gate_still_threshold_number(x, n)) diff --git a/esphome/components/ld2410/number/gate_threshold_number.cpp b/esphome/components/ld2410/number/gate_threshold_number.cpp new file mode 100644 index 0000000000..5d040554d7 --- /dev/null +++ b/esphome/components/ld2410/number/gate_threshold_number.cpp @@ -0,0 +1,14 @@ +#include "gate_threshold_number.h" + +namespace esphome { +namespace ld2410 { + +GateThresholdNumber::GateThresholdNumber(uint8_t gate) : gate_(gate) {} + +void GateThresholdNumber::control(float value) { + this->publish_state(value); + this->parent_->set_gate_threshold(this->gate_); +} + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/number/gate_threshold_number.h b/esphome/components/ld2410/number/gate_threshold_number.h new file mode 100644 index 0000000000..2806ecce63 --- /dev/null +++ b/esphome/components/ld2410/number/gate_threshold_number.h @@ -0,0 +1,19 @@ +#pragma once + +#include "esphome/components/number/number.h" +#include "../ld2410.h" + +namespace esphome { +namespace ld2410 { + +class GateThresholdNumber : public number::Number, public Parented { + public: + GateThresholdNumber(uint8_t gate); + + protected: + uint8_t gate_; + void control(float value) override; +}; + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/number/light_threshold_number.cpp b/esphome/components/ld2410/number/light_threshold_number.cpp new file mode 100644 index 0000000000..0ff35782cd --- /dev/null +++ b/esphome/components/ld2410/number/light_threshold_number.cpp @@ -0,0 +1,12 @@ +#include "light_threshold_number.h" + +namespace esphome { +namespace ld2410 { + +void LightThresholdNumber::control(float value) { + this->publish_state(value); + this->parent_->set_light_out_control(); +} + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/number/light_threshold_number.h b/esphome/components/ld2410/number/light_threshold_number.h new file mode 100644 index 0000000000..8f014373c0 --- /dev/null +++ b/esphome/components/ld2410/number/light_threshold_number.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/number/number.h" +#include "../ld2410.h" + +namespace esphome { +namespace ld2410 { + +class LightThresholdNumber : public number::Number, public Parented { + public: + LightThresholdNumber() = default; + + protected: + void control(float value) override; +}; + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/number/max_distance_timeout_number.cpp b/esphome/components/ld2410/number/max_distance_timeout_number.cpp new file mode 100644 index 0000000000..8a946f7ea9 --- /dev/null +++ b/esphome/components/ld2410/number/max_distance_timeout_number.cpp @@ -0,0 +1,12 @@ +#include "max_distance_timeout_number.h" + +namespace esphome { +namespace ld2410 { + +void MaxDistanceTimeoutNumber::control(float value) { + this->publish_state(value); + this->parent_->set_max_distances_timeout(); +} + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/number/max_distance_timeout_number.h b/esphome/components/ld2410/number/max_distance_timeout_number.h new file mode 100644 index 0000000000..7d91b4b5fe --- /dev/null +++ b/esphome/components/ld2410/number/max_distance_timeout_number.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/number/number.h" +#include "../ld2410.h" + +namespace esphome { +namespace ld2410 { + +class MaxDistanceTimeoutNumber : public number::Number, public Parented { + public: + MaxDistanceTimeoutNumber() = default; + + protected: + void control(float value) override; +}; + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/select/__init__.py b/esphome/components/ld2410/select/__init__.py new file mode 100644 index 0000000000..6c34a85ac6 --- /dev/null +++ b/esphome/components/ld2410/select/__init__.py @@ -0,0 +1,81 @@ +import esphome.codegen as cg +from esphome.components import select +import esphome.config_validation as cv +from esphome.const import ( + ENTITY_CATEGORY_CONFIG, + CONF_BAUD_RATE, + ICON_THERMOMETER, + ICON_SCALE, + ICON_LIGHTBULB, + ICON_RULER, +) +from .. import CONF_LD2410_ID, LD2410Component, ld2410_ns + +BaudRateSelect = ld2410_ns.class_("BaudRateSelect", select.Select) +DistanceResolutionSelect = ld2410_ns.class_("DistanceResolutionSelect", select.Select) +LightOutControlSelect = ld2410_ns.class_("LightOutControlSelect", select.Select) + +CONF_DISTANCE_RESOLUTION = "distance_resolution" +CONF_LIGHT_FUNCTION = "light_function" +CONF_OUT_PIN_LEVEL = "out_pin_level" + + +CONFIG_SCHEMA = { + cv.GenerateID(CONF_LD2410_ID): cv.use_id(LD2410Component), + cv.Optional(CONF_DISTANCE_RESOLUTION): select.select_schema( + DistanceResolutionSelect, + entity_category=ENTITY_CATEGORY_CONFIG, + icon=ICON_RULER, + ), + cv.Optional(CONF_LIGHT_FUNCTION): select.select_schema( + LightOutControlSelect, + entity_category=ENTITY_CATEGORY_CONFIG, + icon=ICON_LIGHTBULB, + ), + cv.Optional(CONF_OUT_PIN_LEVEL): select.select_schema( + LightOutControlSelect, + entity_category=ENTITY_CATEGORY_CONFIG, + icon=ICON_SCALE, + ), + cv.Optional(CONF_BAUD_RATE): select.select_schema( + BaudRateSelect, + entity_category=ENTITY_CATEGORY_CONFIG, + icon=ICON_THERMOMETER, + ), +} + + +async def to_code(config): + ld2410_component = await cg.get_variable(config[CONF_LD2410_ID]) + if distance_resolution_config := config.get(CONF_DISTANCE_RESOLUTION): + s = await select.new_select( + distance_resolution_config, options=["0.2m", "0.75m"] + ) + await cg.register_parented(s, config[CONF_LD2410_ID]) + cg.add(ld2410_component.set_distance_resolution_select(s)) + if out_pin_level_config := config.get(CONF_OUT_PIN_LEVEL): + s = await select.new_select(out_pin_level_config, options=["low", "high"]) + await cg.register_parented(s, config[CONF_LD2410_ID]) + cg.add(ld2410_component.set_out_pin_level_select(s)) + if light_function_config := config.get(CONF_LIGHT_FUNCTION): + s = await select.new_select( + light_function_config, options=["off", "below", "above"] + ) + await cg.register_parented(s, config[CONF_LD2410_ID]) + cg.add(ld2410_component.set_light_function_select(s)) + if baud_rate_config := config.get(CONF_BAUD_RATE): + s = await select.new_select( + baud_rate_config, + options=[ + "9600", + "19200", + "38400", + "57600", + "115200", + "230400", + "256000", + "460800", + ], + ) + await cg.register_parented(s, config[CONF_LD2410_ID]) + cg.add(ld2410_component.set_baud_rate_select(s)) diff --git a/esphome/components/ld2410/select/baud_rate_select.cpp b/esphome/components/ld2410/select/baud_rate_select.cpp new file mode 100644 index 0000000000..f4e0b90e2e --- /dev/null +++ b/esphome/components/ld2410/select/baud_rate_select.cpp @@ -0,0 +1,12 @@ +#include "baud_rate_select.h" + +namespace esphome { +namespace ld2410 { + +void BaudRateSelect::control(const std::string &value) { + this->publish_state(value); + this->parent_->set_baud_rate(state); +} + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/select/baud_rate_select.h b/esphome/components/ld2410/select/baud_rate_select.h new file mode 100644 index 0000000000..3827b6a48a --- /dev/null +++ b/esphome/components/ld2410/select/baud_rate_select.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/select/select.h" +#include "../ld2410.h" + +namespace esphome { +namespace ld2410 { + +class BaudRateSelect : public select::Select, public Parented { + public: + BaudRateSelect() = default; + + protected: + void control(const std::string &value) override; +}; + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/select/distance_resolution_select.cpp b/esphome/components/ld2410/select/distance_resolution_select.cpp new file mode 100644 index 0000000000..eef34bda63 --- /dev/null +++ b/esphome/components/ld2410/select/distance_resolution_select.cpp @@ -0,0 +1,12 @@ +#include "distance_resolution_select.h" + +namespace esphome { +namespace ld2410 { + +void DistanceResolutionSelect::control(const std::string &value) { + this->publish_state(value); + this->parent_->set_distance_resolution(state); +} + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/select/distance_resolution_select.h b/esphome/components/ld2410/select/distance_resolution_select.h new file mode 100644 index 0000000000..d6affb1020 --- /dev/null +++ b/esphome/components/ld2410/select/distance_resolution_select.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/select/select.h" +#include "../ld2410.h" + +namespace esphome { +namespace ld2410 { + +class DistanceResolutionSelect : public select::Select, public Parented { + public: + DistanceResolutionSelect() = default; + + protected: + void control(const std::string &value) override; +}; + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/select/light_out_control_select.cpp b/esphome/components/ld2410/select/light_out_control_select.cpp new file mode 100644 index 0000000000..ac23248a64 --- /dev/null +++ b/esphome/components/ld2410/select/light_out_control_select.cpp @@ -0,0 +1,12 @@ +#include "light_out_control_select.h" + +namespace esphome { +namespace ld2410 { + +void LightOutControlSelect::control(const std::string &value) { + this->publish_state(value); + this->parent_->set_light_out_control(); +} + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/select/light_out_control_select.h b/esphome/components/ld2410/select/light_out_control_select.h new file mode 100644 index 0000000000..5d72e1774e --- /dev/null +++ b/esphome/components/ld2410/select/light_out_control_select.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/select/select.h" +#include "../ld2410.h" + +namespace esphome { +namespace ld2410 { + +class LightOutControlSelect : public select::Select, public Parented { + public: + LightOutControlSelect() = default; + + protected: + void control(const std::string &value) override; +}; + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/sensor.py b/esphome/components/ld2410/sensor.py index b941263134..83361db58a 100644 --- a/esphome/components/ld2410/sensor.py +++ b/esphome/components/ld2410/sensor.py @@ -3,9 +3,15 @@ from esphome.components import sensor import esphome.config_validation as cv from esphome.const import ( DEVICE_CLASS_DISTANCE, - DEVICE_CLASS_ENERGY, UNIT_CENTIMETER, UNIT_PERCENT, + CONF_LIGHT, + DEVICE_CLASS_ILLUMINANCE, + ENTITY_CATEGORY_DIAGNOSTIC, + ICON_SIGNAL, + ICON_FLASH, + ICON_MOTION_SENSOR, + ICON_LIGHTBULB, ) from . import CONF_LD2410_ID, LD2410Component @@ -15,41 +21,88 @@ CONF_STILL_DISTANCE = "still_distance" CONF_MOVING_ENERGY = "moving_energy" CONF_STILL_ENERGY = "still_energy" CONF_DETECTION_DISTANCE = "detection_distance" +CONF_MOVE_ENERGY = "move_energy" -CONFIG_SCHEMA = { - cv.GenerateID(CONF_LD2410_ID): cv.use_id(LD2410Component), - cv.Optional(CONF_MOVING_DISTANCE): sensor.sensor_schema( - device_class=DEVICE_CLASS_DISTANCE, unit_of_measurement=UNIT_CENTIMETER - ), - cv.Optional(CONF_STILL_DISTANCE): sensor.sensor_schema( - device_class=DEVICE_CLASS_DISTANCE, unit_of_measurement=UNIT_CENTIMETER - ), - cv.Optional(CONF_MOVING_ENERGY): sensor.sensor_schema( - device_class=DEVICE_CLASS_ENERGY, unit_of_measurement=UNIT_PERCENT - ), - cv.Optional(CONF_STILL_ENERGY): sensor.sensor_schema( - device_class=DEVICE_CLASS_ENERGY, unit_of_measurement=UNIT_PERCENT - ), - cv.Optional(CONF_DETECTION_DISTANCE): sensor.sensor_schema( - device_class=DEVICE_CLASS_DISTANCE, unit_of_measurement=UNIT_CENTIMETER - ), -} +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(CONF_LD2410_ID): cv.use_id(LD2410Component), + cv.Optional(CONF_MOVING_DISTANCE): sensor.sensor_schema( + device_class=DEVICE_CLASS_DISTANCE, + unit_of_measurement=UNIT_CENTIMETER, + icon=ICON_SIGNAL, + ), + cv.Optional(CONF_STILL_DISTANCE): sensor.sensor_schema( + device_class=DEVICE_CLASS_DISTANCE, + unit_of_measurement=UNIT_CENTIMETER, + icon=ICON_SIGNAL, + ), + cv.Optional(CONF_MOVING_ENERGY): sensor.sensor_schema( + unit_of_measurement=UNIT_PERCENT, + icon=ICON_MOTION_SENSOR, + ), + cv.Optional(CONF_STILL_ENERGY): sensor.sensor_schema( + unit_of_measurement=UNIT_PERCENT, + icon=ICON_FLASH, + ), + cv.Optional(CONF_LIGHT): sensor.sensor_schema( + device_class=DEVICE_CLASS_ILLUMINANCE, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + icon=ICON_LIGHTBULB, + ), + cv.Optional(CONF_DETECTION_DISTANCE): sensor.sensor_schema( + device_class=DEVICE_CLASS_DISTANCE, + unit_of_measurement=UNIT_CENTIMETER, + icon=ICON_SIGNAL, + ), + } +) + +CONFIG_SCHEMA = CONFIG_SCHEMA.extend( + { + cv.Optional(f"g{x}"): cv.Schema( + { + cv.Optional(CONF_MOVE_ENERGY): sensor.sensor_schema( + unit_of_measurement=UNIT_PERCENT, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + icon=ICON_MOTION_SENSOR, + ), + cv.Optional(CONF_STILL_ENERGY): sensor.sensor_schema( + unit_of_measurement=UNIT_PERCENT, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + icon=ICON_FLASH, + ), + } + ) + for x in range(9) + } +) async def to_code(config): ld2410_component = await cg.get_variable(config[CONF_LD2410_ID]) - if CONF_MOVING_DISTANCE in config: - sens = await sensor.new_sensor(config[CONF_MOVING_DISTANCE]) + if moving_distance_config := config.get(CONF_MOVING_DISTANCE): + sens = await sensor.new_sensor(moving_distance_config) cg.add(ld2410_component.set_moving_target_distance_sensor(sens)) - if CONF_STILL_DISTANCE in config: - sens = await sensor.new_sensor(config[CONF_STILL_DISTANCE]) + if still_distance_config := config.get(CONF_STILL_DISTANCE): + sens = await sensor.new_sensor(still_distance_config) cg.add(ld2410_component.set_still_target_distance_sensor(sens)) - if CONF_MOVING_ENERGY in config: - sens = await sensor.new_sensor(config[CONF_MOVING_ENERGY]) + if moving_energy_config := config.get(CONF_MOVING_ENERGY): + sens = await sensor.new_sensor(moving_energy_config) cg.add(ld2410_component.set_moving_target_energy_sensor(sens)) - if CONF_STILL_ENERGY in config: - sens = await sensor.new_sensor(config[CONF_STILL_ENERGY]) + if still_energy_config := config.get(CONF_STILL_ENERGY): + sens = await sensor.new_sensor(still_energy_config) cg.add(ld2410_component.set_still_target_energy_sensor(sens)) - if CONF_DETECTION_DISTANCE in config: - sens = await sensor.new_sensor(config[CONF_DETECTION_DISTANCE]) + if light_config := config.get(CONF_LIGHT): + sens = await sensor.new_sensor(light_config) + cg.add(ld2410_component.set_light_sensor(sens)) + if detection_distance_config := config.get(CONF_DETECTION_DISTANCE): + sens = await sensor.new_sensor(detection_distance_config) cg.add(ld2410_component.set_detection_distance_sensor(sens)) + for x in range(9): + if gate_conf := config.get(f"g{x}"): + if move_config := gate_conf.get(CONF_MOVE_ENERGY): + sens = await sensor.new_sensor(move_config) + cg.add(ld2410_component.set_gate_move_sensor(x, sens)) + if still_config := gate_conf.get(CONF_STILL_ENERGY): + sens = await sensor.new_sensor(still_config) + cg.add(ld2410_component.set_gate_still_sensor(x, sens)) diff --git a/esphome/components/ld2410/switch/__init__.py b/esphome/components/ld2410/switch/__init__.py new file mode 100644 index 0000000000..096cb5f67a --- /dev/null +++ b/esphome/components/ld2410/switch/__init__.py @@ -0,0 +1,44 @@ +import esphome.codegen as cg +from esphome.components import switch +import esphome.config_validation as cv +from esphome.const import ( + DEVICE_CLASS_SWITCH, + ICON_BLUETOOTH, + ENTITY_CATEGORY_CONFIG, + ICON_PULSE, +) +from .. import CONF_LD2410_ID, LD2410Component, ld2410_ns + +BluetoothSwitch = ld2410_ns.class_("BluetoothSwitch", switch.Switch) +EngineeringModeSwitch = ld2410_ns.class_("EngineeringModeSwitch", switch.Switch) + +CONF_ENGINEERING_MODE = "engineering_mode" +CONF_BLUETOOTH = "bluetooth" + +CONFIG_SCHEMA = { + cv.GenerateID(CONF_LD2410_ID): cv.use_id(LD2410Component), + cv.Optional(CONF_ENGINEERING_MODE): switch.switch_schema( + EngineeringModeSwitch, + device_class=DEVICE_CLASS_SWITCH, + entity_category=ENTITY_CATEGORY_CONFIG, + icon=ICON_PULSE, + ), + cv.Optional(CONF_BLUETOOTH): switch.switch_schema( + BluetoothSwitch, + device_class=DEVICE_CLASS_SWITCH, + entity_category=ENTITY_CATEGORY_CONFIG, + icon=ICON_BLUETOOTH, + ), +} + + +async def to_code(config): + ld2410_component = await cg.get_variable(config[CONF_LD2410_ID]) + if engineering_mode_config := config.get(CONF_ENGINEERING_MODE): + s = await switch.new_switch(engineering_mode_config) + await cg.register_parented(s, config[CONF_LD2410_ID]) + cg.add(ld2410_component.set_engineering_mode_switch(s)) + if bluetooth_config := config.get(CONF_BLUETOOTH): + s = await switch.new_switch(bluetooth_config) + await cg.register_parented(s, config[CONF_LD2410_ID]) + cg.add(ld2410_component.set_bluetooth_switch(s)) diff --git a/esphome/components/ld2410/switch/bluetooth_switch.cpp b/esphome/components/ld2410/switch/bluetooth_switch.cpp new file mode 100644 index 0000000000..9bcee9b049 --- /dev/null +++ b/esphome/components/ld2410/switch/bluetooth_switch.cpp @@ -0,0 +1,12 @@ +#include "bluetooth_switch.h" + +namespace esphome { +namespace ld2410 { + +void BluetoothSwitch::write_state(bool state) { + this->publish_state(state); + this->parent_->set_bluetooth(state); +} + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/switch/bluetooth_switch.h b/esphome/components/ld2410/switch/bluetooth_switch.h new file mode 100644 index 0000000000..35ae1ec0c9 --- /dev/null +++ b/esphome/components/ld2410/switch/bluetooth_switch.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/switch/switch.h" +#include "../ld2410.h" + +namespace esphome { +namespace ld2410 { + +class BluetoothSwitch : public switch_::Switch, public Parented { + public: + BluetoothSwitch() = default; + + protected: + void write_state(bool state) override; +}; + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/switch/engineering_mode_switch.cpp b/esphome/components/ld2410/switch/engineering_mode_switch.cpp new file mode 100644 index 0000000000..967c87c887 --- /dev/null +++ b/esphome/components/ld2410/switch/engineering_mode_switch.cpp @@ -0,0 +1,12 @@ +#include "engineering_mode_switch.h" + +namespace esphome { +namespace ld2410 { + +void EngineeringModeSwitch::write_state(bool state) { + this->publish_state(state); + this->parent_->set_engineering_mode(state); +} + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/switch/engineering_mode_switch.h b/esphome/components/ld2410/switch/engineering_mode_switch.h new file mode 100644 index 0000000000..e521200cd6 --- /dev/null +++ b/esphome/components/ld2410/switch/engineering_mode_switch.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/switch/switch.h" +#include "../ld2410.h" + +namespace esphome { +namespace ld2410 { + +class EngineeringModeSwitch : public switch_::Switch, public Parented { + public: + EngineeringModeSwitch() = default; + + protected: + void write_state(bool state) override; +}; + +} // namespace ld2410 +} // namespace esphome diff --git a/esphome/components/ld2410/text_sensor.py b/esphome/components/ld2410/text_sensor.py new file mode 100644 index 0000000000..d64472a7d3 --- /dev/null +++ b/esphome/components/ld2410/text_sensor.py @@ -0,0 +1,33 @@ +import esphome.codegen as cg +from esphome.components import text_sensor +import esphome.config_validation as cv +from esphome.const import ( + ENTITY_CATEGORY_DIAGNOSTIC, + CONF_VERSION, + CONF_MAC_ADDRESS, + ICON_BLUETOOTH, + ICON_CHIP, +) +from . import CONF_LD2410_ID, LD2410Component + +DEPENDENCIES = ["ld2410"] + +CONFIG_SCHEMA = { + 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 + ), + cv.Optional(CONF_MAC_ADDRESS): text_sensor.text_sensor_schema( + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, icon=ICON_BLUETOOTH + ), +} + + +async def to_code(config): + ld2410_component = await cg.get_variable(config[CONF_LD2410_ID]) + if version_config := config.get(CONF_VERSION): + sens = await text_sensor.new_text_sensor(version_config) + cg.add(ld2410_component.set_version_text_sensor(sens)) + if mac_address_config := config.get(CONF_MAC_ADDRESS): + sens = await text_sensor.new_text_sensor(mac_address_config) + cg.add(ld2410_component.set_mac_text_sensor(sens)) diff --git a/tests/test1.yaml b/tests/test1.yaml index 4eb78515c9..66caad961a 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -170,6 +170,9 @@ mqtt: id: uart_0 data: !lambda |- return {}; + - bluetooth_password.set: + id: my_ld2410 + password: abcdef on_connect: - light.turn_on: ${roomname}_lights - mqtt.publish: @@ -1333,16 +1336,64 @@ sensor: speed: name: "Radiator Pump Speed" - platform: ld2410 + light: + name: light moving_distance: name: "Moving distance (cm)" still_distance: name: "Still Distance (cm)" moving_energy: - name: "Move Energy" + name: "Move Energy (%)" still_energy: - name: "Still Energy" + name: "Still Energy (%)" detection_distance: - name: "Distance Detection" + name: "Distance Detection (cm)" + g0: + move_energy: + name: g0 move energy + still_energy: + name: g0 still energy + g1: + move_energy: + name: g1 move energy + still_energy: + name: g1 still energy + g2: + move_energy: + name: g2 move energy + still_energy: + name: g2 still energy + g3: + move_energy: + name: g3 move energy + still_energy: + name: g3 still energy + g4: + move_energy: + name: g4 move energy + still_energy: + name: g4 still energy + g5: + move_energy: + name: g5 move energy + still_energy: + name: g5 still energy + g6: + move_energy: + name: g6 move energy + still_energy: + name: g6 still energy + g7: + move_energy: + name: g7 move energy + still_energy: + name: g7 still energy + g8: + move_energy: + name: g8 move energy + still_energy: + name: g8 still energy + - platform: sen21231 name: "Person Sensor" i2c_id: i2c_bus @@ -1684,6 +1735,8 @@ binary_sensor: name: movement has_still_target: name: still + out_pin_presence_status: + name: out pin presence status pca9685: frequency: 500 @@ -2626,6 +2679,11 @@ switch: id: outlet_switch optimistic: true device_class: outlet + - platform: ld2410 + engineering_mode: + name: "control ld2410 engineering mode" + bluetooth: + name: "control ld2410 bluetooth" fan: - platform: binary @@ -3207,6 +3265,11 @@ text_sensor: tag_name: OPTARIF name: optarif teleinfo_id: myteleinfo + - platform: ld2410 + version: + name: "presenece sensor version" + mac_address: + name: "presenece sensor mac address" sn74hc595: - id: sn74hc595_hub @@ -3311,6 +3374,61 @@ number: step: 1 max_value: 10 optimistic: true + - platform: ld2410 + light_threshold: + name: light threshold + timeout: + name: timeout + max_move_distance_gate: + name: max move distance gate + max_still_distance_gate: + name: max still distance gate + g0: + move_threshold: + name: g0 move threshold + still_threshold: + name: g0 still threshold + g1: + move_threshold: + name: g1 move threshold + still_threshold: + name: g1 still threshold + g2: + move_threshold: + name: g2 move threshold + still_threshold: + name: g2 still threshold + g3: + move_threshold: + name: g3 move threshold + still_threshold: + name: g3 still threshold + g4: + move_threshold: + name: g4 move threshold + still_threshold: + name: g4 still threshold + g5: + move_threshold: + name: g5 move threshold + still_threshold: + name: g5 still threshold + g6: + move_threshold: + name: g6 move threshold + still_threshold: + name: g6 still threshold + g7: + move_threshold: + name: g7 move threshold + still_threshold: + name: g7 still threshold + g8: + move_threshold: + name: g8 move threshold + still_threshold: + name: g8 still threshold + select: - platform: template @@ -3324,6 +3442,15 @@ select: - platform: copy source_id: test_select name: Test Select Copy + - platform: ld2410 + distance_resolution: + name: distance resolution + baud_rate: + name: baud rate + light_function: + name: light function + out_pin_level: + name: out ping level qr_code: - id: homepage_qr @@ -3386,19 +3513,17 @@ button: name: Midea Power Inverse on_press: midea_ac.power_toggle: + - platform: ld2410 + factory_reset: + name: "factory reset" + restart: + name: "restart" + query_params: + name: query params ld2410: id: my_ld2410 uart_id: ld2410_uart - timeout: 150s - max_move_distance: 6m - max_still_distance: 0.75m - g0_move_threshold: 10 - g0_still_threshold: 20 - g2_move_threshold: 20 - g2_still_threshold: 21 - g8_move_threshold: 80 - g8_still_threshold: 81 lcd_menu: display_id: my_lcd_gpio From 532163738e82d0b392302abb74f5f6268cb6fb01 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 16 Aug 2023 11:49:08 +1200 Subject: [PATCH 0066/2101] Bump version to 2023.8.0b3 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 1442ebde9d..aff72531bb 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2023.8.0b2" +__version__ = "2023.8.0b3" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 5f99ed943ae81892e62ea1a542e3d48c1e1cf100 Mon Sep 17 00:00:00 2001 From: Pierre Gordon <16200219+pierlon@users.noreply.github.com> Date: Wed, 16 Aug 2023 20:22:04 -0400 Subject: [PATCH 0067/2101] Add `libfreetype-dev` Debian package for armv7 Docker builds (#5262) --- docker/Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index e1f3c46a3e..4aaea9da89 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -35,7 +35,8 @@ RUN \ python3-dev=3.9.2-3 \ zlib1g-dev=1:1.2.11.dfsg-2+deb11u2 \ libjpeg-dev=1:2.0.6-4 \ - libcairo2=1.16.0-5; \ + libcairo2=1.16.0-5 \ + libfreetype-dev=2.10.4+dfsg-1+deb11u1; \ fi; \ rm -rf \ /tmp/* \ From 63fc16d8722ca913b6def0eda53fbb6d15197338 Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Thu, 17 Aug 2023 02:22:37 +0200 Subject: [PATCH 0068/2101] Add delay before enabling ipv6 (#5256) --- esphome/components/wifi/wifi_component_esp32_arduino.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/wifi/wifi_component_esp32_arduino.cpp b/esphome/components/wifi/wifi_component_esp32_arduino.cpp index 995e5e587e..5bfb6bb9a8 100644 --- a/esphome/components/wifi/wifi_component_esp32_arduino.cpp +++ b/esphome/components/wifi/wifi_component_esp32_arduino.cpp @@ -486,7 +486,7 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_ ESP_LOGV(TAG, "Event: Connected ssid='%s' bssid=" LOG_SECRET("%s") " channel=%u, authmode=%s", buf, format_mac_addr(it.bssid).c_str(), it.channel, get_auth_mode_str(it.authmode)); #if LWIP_IPV6 - WiFi.enableIpV6(); + this->set_timeout(100, [] { WiFi.enableIpV6(); }); #endif /* LWIP_IPV6 */ break; From c5be5e6d12316035b70175bed1a2cae5be0dc41b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 17 Aug 2023 12:23:44 +1200 Subject: [PATCH 0069/2101] Bump zeroconf from 0.74.0 to 0.80.0 (#5260) 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 6330a0996e..a1f73d930a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,7 +11,7 @@ esptool==4.6.2 click==8.1.6 esphome-dashboard==20230711.0 aioesphomeapi==15.0.0 -zeroconf==0.74.0 +zeroconf==0.80.0 # esp-idf requires this, but doesn't bundle it by default # https://github.com/espressif/esp-idf/blob/220590d599e134d7a5e7f1e683cc4550349ffbf8/requirements.txt#L24 From a27e72362ab5045bfc52616fb6d8fe8744e8155c Mon Sep 17 00:00:00 2001 From: Pierre Gordon <16200219+pierlon@users.noreply.github.com> Date: Wed, 16 Aug 2023 20:22:04 -0400 Subject: [PATCH 0070/2101] Add `libfreetype-dev` Debian package for armv7 Docker builds (#5262) --- docker/Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index e1f3c46a3e..4aaea9da89 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -35,7 +35,8 @@ RUN \ python3-dev=3.9.2-3 \ zlib1g-dev=1:1.2.11.dfsg-2+deb11u2 \ libjpeg-dev=1:2.0.6-4 \ - libcairo2=1.16.0-5; \ + libcairo2=1.16.0-5 \ + libfreetype-dev=2.10.4+dfsg-1+deb11u1; \ fi; \ rm -rf \ /tmp/* \ From cb66ce069e2f8d092095167403489a16fe408466 Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Thu, 17 Aug 2023 02:22:37 +0200 Subject: [PATCH 0071/2101] Add delay before enabling ipv6 (#5256) --- esphome/components/wifi/wifi_component_esp32_arduino.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/wifi/wifi_component_esp32_arduino.cpp b/esphome/components/wifi/wifi_component_esp32_arduino.cpp index 995e5e587e..5bfb6bb9a8 100644 --- a/esphome/components/wifi/wifi_component_esp32_arduino.cpp +++ b/esphome/components/wifi/wifi_component_esp32_arduino.cpp @@ -486,7 +486,7 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_ ESP_LOGV(TAG, "Event: Connected ssid='%s' bssid=" LOG_SECRET("%s") " channel=%u, authmode=%s", buf, format_mac_addr(it.bssid).c_str(), it.channel, get_auth_mode_str(it.authmode)); #if LWIP_IPV6 - WiFi.enableIpV6(); + this->set_timeout(100, [] { WiFi.enableIpV6(); }); #endif /* LWIP_IPV6 */ break; From 7c129a4018305ba2525e2fdca5064412eca0b49a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 17 Aug 2023 12:23:44 +1200 Subject: [PATCH 0072/2101] Bump zeroconf from 0.74.0 to 0.80.0 (#5260) 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 6330a0996e..a1f73d930a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,7 +11,7 @@ esptool==4.6.2 click==8.1.6 esphome-dashboard==20230711.0 aioesphomeapi==15.0.0 -zeroconf==0.74.0 +zeroconf==0.80.0 # esp-idf requires this, but doesn't bundle it by default # https://github.com/espressif/esp-idf/blob/220590d599e134d7a5e7f1e683cc4550349ffbf8/requirements.txt#L24 From 2aaba1d2b855126cd32d601c1b9a04a37f6ee152 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 17 Aug 2023 13:04:32 +1200 Subject: [PATCH 0073/2101] Bump version to 2023.8.0b4 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index aff72531bb..ffac22fc58 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2023.8.0b3" +__version__ = "2023.8.0b4" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 7e4ee32b5404d83d6046721e5195b271df3396b1 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 17 Aug 2023 14:33:35 +1200 Subject: [PATCH 0074/2101] Bump version to 2023.8.0 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index ffac22fc58..f0a6efda94 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2023.8.0b4" +__version__ = "2023.8.0" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 9fc50e8dbc287f1ea5bed9acbaff612cb196998f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 17 Aug 2023 19:41:24 +0000 Subject: [PATCH 0075/2101] Bump click from 8.1.6 to 8.1.7 (#5272) 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 a1f73d930a..4a046014d6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,7 +8,7 @@ tzdata>=2021.1 # from time pyserial==3.5 platformio==6.1.9 # When updating platformio, also update Dockerfile esptool==4.6.2 -click==8.1.6 +click==8.1.7 esphome-dashboard==20230711.0 aioesphomeapi==15.0.0 zeroconf==0.80.0 From 2b4ed0c2738cae095f5803d539d1a1d0d4a738a9 Mon Sep 17 00:00:00 2001 From: Mat931 <49403702+Mat931@users.noreply.github.com> Date: Thu, 17 Aug 2023 19:57:18 +0000 Subject: [PATCH 0076/2101] Fix checksum calculation for sml (#5271) --- esphome/components/sml/sml.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/sml/sml.cpp b/esphome/components/sml/sml.cpp index 87dc25c220..921623d4fd 100644 --- a/esphome/components/sml/sml.cpp +++ b/esphome/components/sml/sml.cpp @@ -100,14 +100,14 @@ bool check_sml_data(const bytes &buffer) { } uint16_t crc_received = (buffer.at(buffer.size() - 2) << 8) | buffer.at(buffer.size() - 1); - uint16_t crc_calculated = crc16(buffer.data(), buffer.size(), 0x6e23, 0x8408, true, true); + uint16_t crc_calculated = crc16(buffer.data(), buffer.size() - 2, 0x6e23, 0x8408, true, true); crc_calculated = (crc_calculated >> 8) | (crc_calculated << 8); if (crc_received == crc_calculated) { ESP_LOGV(TAG, "Checksum verification successful with CRC16/X25."); return true; } - crc_calculated = crc16(buffer.data(), buffer.size(), 0xed50, 0x8408); + crc_calculated = crc16(buffer.data(), buffer.size() - 2, 0xed50, 0x8408); if (crc_received == crc_calculated) { ESP_LOGV(TAG, "Checksum verification successful with CRC16/KERMIT."); return true; From 0af8d0b7eac67807749c16b2eea2b7d98debdd56 Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Thu, 17 Aug 2023 22:02:57 +0200 Subject: [PATCH 0077/2101] Remove support for ESP-IDF version < 4 (#5261) --- esphome/components/debug/debug_component.cpp | 4 -- esphome/components/esp32/core.cpp | 12 +--- esphome/components/esp32_touch/esp32_touch.h | 4 -- .../components/socket/bsd_sockets_impl.cpp | 41 +----------- esphome/components/wifi/wifi_component.h | 4 -- .../wifi/wifi_component_esp32_arduino.cpp | 63 ------------------- .../wifi/wifi_component_esp_idf.cpp | 4 -- 7 files changed, 3 insertions(+), 129 deletions(-) diff --git a/esphome/components/debug/debug_component.cpp b/esphome/components/debug/debug_component.cpp index 8b6a97068b..baf537a12b 100644 --- a/esphome/components/debug/debug_component.cpp +++ b/esphome/components/debug/debug_component.cpp @@ -12,12 +12,8 @@ #include #include -#if ESP_IDF_VERSION_MAJOR >= 4 #include #include -#else -#include -#endif #endif // USE_ESP32 diff --git a/esphome/components/esp32/core.cpp b/esphome/components/esp32/core.cpp index 512a8857b6..16aa93c232 100644 --- a/esphome/components/esp32/core.cpp +++ b/esphome/components/esp32/core.cpp @@ -10,9 +10,7 @@ #include #include -#if ESP_IDF_VERSION_MAJOR >= 4 #include -#endif #ifdef USE_ARDUINO #include @@ -55,15 +53,7 @@ void arch_init() { void IRAM_ATTR 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() { -#if ESP_IDF_VERSION_MAJOR >= 4 - return cpu_hal_get_cycle_count(); -#else - uint32_t ccount; - __asm__ __volatile__("esync; rsr %0,ccount" : "=a"(ccount)); - return ccount; -#endif -} +uint32_t arch_get_cpu_cycle_count() { return cpu_hal_get_cycle_count(); } uint32_t arch_get_cpu_freq_hz() { return rtc_clk_apb_freq_get(); } #ifdef USE_ESP_IDF diff --git a/esphome/components/esp32_touch/esp32_touch.h b/esphome/components/esp32_touch/esp32_touch.h index 0ba7ed6255..0eac590ce7 100644 --- a/esphome/components/esp32_touch/esp32_touch.h +++ b/esphome/components/esp32_touch/esp32_touch.h @@ -8,11 +8,7 @@ #include -#if ESP_IDF_VERSION_MAJOR >= 4 #include -#else -#include -#endif namespace esphome { namespace esp32_touch { diff --git a/esphome/components/socket/bsd_sockets_impl.cpp b/esphome/components/socket/bsd_sockets_impl.cpp index 2dea4af277..5d44cd7689 100644 --- a/esphome/components/socket/bsd_sockets_impl.cpp +++ b/esphome/components/socket/bsd_sockets_impl.cpp @@ -87,25 +87,7 @@ class BSDSocketImpl : public Socket { int listen(int backlog) override { return ::listen(fd_, backlog); } ssize_t read(void *buf, size_t len) override { return ::read(fd_, buf, len); } ssize_t readv(const struct iovec *iov, int iovcnt) override { -#if defined(USE_ESP32) && ESP_IDF_VERSION_MAJOR < 4 - // esp-idf v3 doesn't have readv, emulate it - ssize_t ret = 0; - for (int i = 0; i < iovcnt; i++) { - ssize_t err = this->read(reinterpret_cast(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 (err != iov[i].iov_len) - break; - } - return ret; -#elif defined(USE_ESP32) - // ESP-IDF v4 only has symbol lwip_readv +#if defined(USE_ESP32) return ::lwip_readv(fd_, iov, iovcnt); #else return ::readv(fd_, iov, iovcnt); @@ -114,26 +96,7 @@ class BSDSocketImpl : public Socket { ssize_t write(const void *buf, size_t len) override { return ::write(fd_, buf, len); } ssize_t send(void *buf, size_t len, int flags) { return ::send(fd_, buf, len, flags); } ssize_t writev(const struct iovec *iov, int iovcnt) override { -#if defined(USE_ESP32) && ESP_IDF_VERSION_MAJOR < 4 - // esp-idf v3 doesn't have writev, emulate it - ssize_t ret = 0; - for (int i = 0; i < iovcnt; i++) { - ssize_t err = - this->send(reinterpret_cast(iov[i].iov_base), iov[i].iov_len, i == iovcnt - 1 ? 0 : MSG_MORE); - if (err == -1) { - if (ret != 0) { - // if we already wrote some don't return an error - break; - } - return err; - } - ret += err; - if (err != iov[i].iov_len) - break; - } - return ret; -#elif defined(USE_ESP32) - // ESP-IDF v4 only has symbol lwip_writev +#if defined(USE_ESP32) return ::lwip_writev(fd_, iov, iovcnt); #else return ::writev(fd_, iov, iovcnt); diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index d39b062990..c17246fd00 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -324,11 +324,7 @@ class WiFiComponent : public Component { #endif #ifdef USE_ESP32_FRAMEWORK_ARDUINO -#if ESP_IDF_VERSION_MAJOR >= 4 void wifi_event_callback_(arduino_event_id_t event, arduino_event_info_t info); -#else - void wifi_event_callback_(system_event_id_t event, system_event_info_t info); -#endif void wifi_scan_done_callback_(); #endif #ifdef USE_ESP_IDF diff --git a/esphome/components/wifi/wifi_component_esp32_arduino.cpp b/esphome/components/wifi/wifi_component_esp32_arduino.cpp index 5bfb6bb9a8..95f4e2ce92 100644 --- a/esphome/components/wifi/wifi_component_esp32_arduino.cpp +++ b/esphome/components/wifi/wifi_component_esp32_arduino.cpp @@ -203,12 +203,10 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) { // Units: AP beacon intervals. Defaults to 3 if set to 0. conf.sta.listen_interval = 0; -#if ESP_IDF_VERSION_MAJOR >= 4 // Protected Management Frame // Device will prefer to connect in PMF mode if other device also advertises PMF capability. conf.sta.pmf_cfg.capable = true; conf.sta.pmf_cfg.required = false; -#endif // note, we do our own filtering // The minimum rssi to accept in the fast scan mode @@ -314,11 +312,7 @@ const char *get_auth_mode_str(uint8_t mode) { } } -#if ESP_IDF_VERSION_MAJOR >= 4 using esphome_ip4_addr_t = esp_ip4_addr_t; -#else -using esphome_ip4_addr_t = ip4_addr_t; -#endif std::string format_ip4_addr(const esphome_ip4_addr_t &ip) { char buf[20]; @@ -404,8 +398,6 @@ const char *get_disconnect_reason_str(uint8_t reason) { } } -#if ESP_IDF_VERSION_MAJOR >= 4 - #define ESPHOME_EVENT_ID_WIFI_READY ARDUINO_EVENT_WIFI_READY #define ESPHOME_EVENT_ID_WIFI_SCAN_DONE ARDUINO_EVENT_WIFI_SCAN_DONE #define ESPHOME_EVENT_ID_WIFI_STA_START ARDUINO_EVENT_WIFI_STA_START @@ -426,28 +418,6 @@ const char *get_disconnect_reason_str(uint8_t reason) { using esphome_wifi_event_id_t = arduino_event_id_t; using esphome_wifi_event_info_t = arduino_event_info_t; -#else // ESP_IDF_VERSION_MAJOR >= 4 - -#define ESPHOME_EVENT_ID_WIFI_READY SYSTEM_EVENT_WIFI_READY -#define ESPHOME_EVENT_ID_WIFI_SCAN_DONE SYSTEM_EVENT_SCAN_DONE -#define ESPHOME_EVENT_ID_WIFI_STA_START SYSTEM_EVENT_STA_START -#define ESPHOME_EVENT_ID_WIFI_STA_STOP SYSTEM_EVENT_STA_STOP -#define ESPHOME_EVENT_ID_WIFI_STA_CONNECTED SYSTEM_EVENT_STA_CONNECTED -#define ESPHOME_EVENT_ID_WIFI_STA_DISCONNECTED SYSTEM_EVENT_STA_DISCONNECTED -#define ESPHOME_EVENT_ID_WIFI_STA_AUTHMODE_CHANGE SYSTEM_EVENT_STA_AUTHMODE_CHANGE -#define ESPHOME_EVENT_ID_WIFI_STA_GOT_IP SYSTEM_EVENT_STA_GOT_IP -#define ESPHOME_EVENT_ID_WIFI_STA_LOST_IP SYSTEM_EVENT_STA_LOST_IP -#define ESPHOME_EVENT_ID_WIFI_AP_START SYSTEM_EVENT_AP_START -#define ESPHOME_EVENT_ID_WIFI_AP_STOP SYSTEM_EVENT_AP_STOP -#define ESPHOME_EVENT_ID_WIFI_AP_STACONNECTED SYSTEM_EVENT_AP_STACONNECTED -#define ESPHOME_EVENT_ID_WIFI_AP_STADISCONNECTED SYSTEM_EVENT_AP_STADISCONNECTED -#define ESPHOME_EVENT_ID_WIFI_AP_STAIPASSIGNED SYSTEM_EVENT_AP_STAIPASSIGNED -#define ESPHOME_EVENT_ID_WIFI_AP_PROBEREQRECVED SYSTEM_EVENT_AP_PROBEREQRECVED -using esphome_wifi_event_id_t = system_event_id_t; -using esphome_wifi_event_info_t = system_event_info_t; - -#endif // !(ESP_IDF_VERSION_MAJOR >= 4) - void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_wifi_event_info_t info) { switch (event) { case ESPHOME_EVENT_ID_WIFI_READY: { @@ -455,11 +425,7 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_ break; } case ESPHOME_EVENT_ID_WIFI_SCAN_DONE: { -#if ESP_IDF_VERSION_MAJOR >= 4 auto it = info.wifi_scan_done; -#else - auto it = info.scan_done; -#endif ESP_LOGV(TAG, "Event: WiFi Scan Done status=%u number=%u scan_id=%u", it.status, it.number, it.scan_id); this->wifi_scan_done_callback_(); @@ -475,11 +441,7 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_ break; } case ESPHOME_EVENT_ID_WIFI_STA_CONNECTED: { -#if ESP_IDF_VERSION_MAJOR >= 4 auto it = info.wifi_sta_connected; -#else - auto it = info.connected; -#endif char buf[33]; memcpy(buf, it.ssid, it.ssid_len); buf[it.ssid_len] = '\0'; @@ -492,11 +454,7 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_ break; } case ESPHOME_EVENT_ID_WIFI_STA_DISCONNECTED: { -#if ESP_IDF_VERSION_MAJOR >= 4 auto it = info.wifi_sta_disconnected; -#else - auto it = info.disconnected; -#endif char buf[33]; memcpy(buf, it.ssid, it.ssid_len); buf[it.ssid_len] = '\0'; @@ -522,11 +480,7 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_ break; } case ESPHOME_EVENT_ID_WIFI_STA_AUTHMODE_CHANGE: { -#if ESP_IDF_VERSION_MAJOR >= 4 auto it = info.wifi_sta_authmode_change; -#else - auto it = info.auth_change; -#endif ESP_LOGV(TAG, "Event: Authmode Change old=%s new=%s", get_auth_mode_str(it.old_mode), get_auth_mode_str(it.new_mode)); // Mitigate CVE-2020-12638 @@ -570,24 +524,14 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_ break; } case ESPHOME_EVENT_ID_WIFI_AP_STACONNECTED: { -#if ESP_IDF_VERSION_MAJOR >= 4 auto it = info.wifi_sta_connected; auto &mac = it.bssid; -#else - auto it = info.sta_connected; - auto &mac = it.mac; -#endif ESP_LOGV(TAG, "Event: AP client connected MAC=%s", format_mac_addr(mac).c_str()); break; } case ESPHOME_EVENT_ID_WIFI_AP_STADISCONNECTED: { -#if ESP_IDF_VERSION_MAJOR >= 4 auto it = info.wifi_sta_disconnected; auto &mac = it.bssid; -#else - auto it = info.sta_disconnected; - auto &mac = it.mac; -#endif ESP_LOGV(TAG, "Event: AP client disconnected MAC=%s", format_mac_addr(mac).c_str()); break; } @@ -596,11 +540,7 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_ break; } case ESPHOME_EVENT_ID_WIFI_AP_PROBEREQRECVED: { -#if ESP_IDF_VERSION_MAJOR >= 4 auto it = info.wifi_ap_probereqrecved; -#else - auto it = info.ap_probereqrecved; -#endif ESP_LOGVV(TAG, "Event: AP receive Probe Request MAC=%s RSSI=%d", format_mac_addr(it.mac).c_str(), it.rssi); break; } @@ -742,10 +682,7 @@ bool WiFiComponent::wifi_start_ap_(const WiFiAP &ap) { strncpy(reinterpret_cast(conf.ap.password), ap.get_password().c_str(), sizeof(conf.ap.ssid)); } -#if ESP_IDF_VERSION_MAJOR >= 4 - // pairwise cipher of SoftAP, group cipher will be derived using this. conf.ap.pairwise_cipher = WIFI_CIPHER_TYPE_CCMP; -#endif esp_err_t err = esp_wifi_set_config(WIFI_IF_AP, &conf); if (err != ESP_OK) { diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index e9d74116cf..9041679ccf 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -312,12 +312,10 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) { // Units: AP beacon intervals. Defaults to 3 if set to 0. conf.sta.listen_interval = 0; -#if ESP_IDF_VERSION_MAJOR >= 4 // Protected Management Frame // Device will prefer to connect in PMF mode if other device also advertises PMF capability. conf.sta.pmf_cfg.capable = true; conf.sta.pmf_cfg.required = false; -#endif // note, we do our own filtering // The minimum rssi to accept in the fast scan mode @@ -838,10 +836,8 @@ bool WiFiComponent::wifi_start_ap_(const WiFiAP &ap) { strncpy(reinterpret_cast(conf.ap.password), ap.get_password().c_str(), sizeof(conf.ap.password)); } -#if ESP_IDF_VERSION_MAJOR >= 4 // pairwise cipher of SoftAP, group cipher will be derived using this. conf.ap.pairwise_cipher = WIFI_CIPHER_TYPE_CCMP; -#endif esp_err_t err = esp_wifi_set_config(WIFI_IF_AP, &conf); if (err != ESP_OK) { From c11c4dad2f4721d52c3f7eb895c79154393f3570 Mon Sep 17 00:00:00 2001 From: SeByDocKy Date: Thu, 17 Aug 2023 22:03:39 +0200 Subject: [PATCH 0078/2101] Add pmwcs3 capacitive soil moisture & temperature sensor component (#4624) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- CODEOWNERS | 1 + esphome/components/pmwcs3/__init__.py | 1 + esphome/components/pmwcs3/pmwcs3.cpp | 115 +++++++++++++++++++++ esphome/components/pmwcs3/pmwcs3.h | 70 +++++++++++++ esphome/components/pmwcs3/sensor.py | 140 ++++++++++++++++++++++++++ tests/test1.yaml | 10 ++ 6 files changed, 337 insertions(+) create mode 100644 esphome/components/pmwcs3/__init__.py create mode 100644 esphome/components/pmwcs3/pmwcs3.cpp create mode 100644 esphome/components/pmwcs3/pmwcs3.h create mode 100644 esphome/components/pmwcs3/sensor.py diff --git a/CODEOWNERS b/CODEOWNERS index f50700c502..0cea8d48ba 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -212,6 +212,7 @@ esphome/components/pid/* @OttoWinter esphome/components/pipsolar/* @andreashergert1984 esphome/components/pm1006/* @habbie esphome/components/pmsa003i/* @sjtrny +esphome/components/pmwcs3/* @SeByDocKy esphome/components/pn532/* @OttoWinter @jesserockz esphome/components/pn532_i2c/* @OttoWinter @jesserockz esphome/components/pn532_spi/* @OttoWinter @jesserockz diff --git a/esphome/components/pmwcs3/__init__.py b/esphome/components/pmwcs3/__init__.py new file mode 100644 index 0000000000..b04c30a005 --- /dev/null +++ b/esphome/components/pmwcs3/__init__.py @@ -0,0 +1 @@ +CODEOWNERS = ["@SeByDocKy"] diff --git a/esphome/components/pmwcs3/pmwcs3.cpp b/esphome/components/pmwcs3/pmwcs3.cpp new file mode 100644 index 0000000000..812018b52e --- /dev/null +++ b/esphome/components/pmwcs3/pmwcs3.cpp @@ -0,0 +1,115 @@ +#include "pmwcs3.h" +#include "esphome/core/hal.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace pmwcs3 { + +static const uint8_t PMWCS3_I2C_ADDRESS = 0x63; +static const uint8_t PMWCS3_REG_READ_START = 0x01; +static const uint8_t PMWCS3_REG_READ_E25 = 0x02; +static const uint8_t PMWCS3_REG_READ_EC = 0x03; +static const uint8_t PMWCS3_REG_READ_TEMP = 0x04; +static const uint8_t PMWCS3_REG_READ_VWC = 0x05; +static const uint8_t PMWCS3_REG_CALIBRATE_AIR = 0x06; +static const uint8_t PMWCS3_REG_CALIBRATE_WATER = 0x07; +static const uint8_t PMWCS3_SET_I2C_ADDRESS = 0x08; +static const uint8_t PMWCS3_REG_GET_DATA = 0x09; +static const uint8_t PMWCS3_REG_CALIBRATE_EC = 0x10; +static const uint8_t PMWCS3_REG_CAP = 0x0A; +static const uint8_t PMWCS3_REG_RES = 0x0B; +static const uint8_t PMWCS3_REG_RC = 0x0C; +static const uint8_t PMWCS3_REG_RT = 0x0D; + +static const char *const TAG = "pmwcs3"; + +void PMWCS3Component::new_i2c_address(uint8_t address) { + if (!this->write_byte(PMWCS3_SET_I2C_ADDRESS, address)) { + this->status_set_warning(); + ESP_LOGW(TAG, "couldn't write the new I2C address %d", address); + return; + } + this->set_i2c_address(address); // Allows device to continue working until new firmware is written with new address. + ESP_LOGVV(TAG, "changed I2C address to %d", address); + this->status_clear_warning(); +} + +void PMWCS3Component::air_calibration() { + if (!this->write_bytes(PMWCS3_REG_CALIBRATE_AIR, nullptr, 0)) { + this->status_set_warning(); + ESP_LOGW(TAG, "couldn't start air calibration"); + return; + } + ESP_LOGW(TAG, "Start air calibration during the next 300s"); +} +void PMWCS3Component::water_calibration() { + if (!this->write_bytes(PMWCS3_REG_CALIBRATE_WATER, nullptr, 0)) { + this->status_set_warning(); + ESP_LOGW(TAG, "couldn't start water calibration"); + return; + } + ESP_LOGW(TAG, "Start water calibration during the next 300s"); +} + +void PMWCS3Component::setup() { ESP_LOGCONFIG(TAG, "Setting up PMWCS3..."); } + +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); + if (this->is_failed()) { + ESP_LOGE(TAG, "Communication with PMWCS3 failed!"); + } + ESP_LOGI(TAG, "%s", this->is_failed() ? "FAILED" : "OK"); + + LOG_UPDATE_INTERVAL(this); + LOG_SENSOR(" ", "e25", this->e25_sensor_); + LOG_SENSOR(" ", "ec", this->ec_sensor_); + LOG_SENSOR(" ", "temperature", this->temperature_sensor_); + LOG_SENSOR(" ", "vwc", this->vwc_sensor_); +} +void PMWCS3Component::read_data_() { + uint8_t data[8]; + float e25, ec, temperature, vwc; + + /////// Super important !!!! first activate reading PMWCS3_REG_READ_START (if not, return always the same values) //// + + if (!this->write_bytes(PMWCS3_REG_READ_START, nullptr, 0)) { + this->status_set_warning(); + ESP_LOGVV(TAG, "Failed to write into REG_READ_START register !!!"); + return; + } + // NOLINT delay(100); + + if (!this->read_bytes(PMWCS3_REG_GET_DATA, (uint8_t *) &data, 8)) { + ESP_LOGVV(TAG, "Error reading PMWCS3_REG_GET_DATA registers"); + this->mark_failed(); + return; + } + if (this->e25_sensor_ != nullptr) { + e25 = ((data[1] << 8) | data[0]) / 100.0; + this->e25_sensor_->publish_state(e25); + ESP_LOGVV(TAG, "e25: data[0]=%d, data[1]=%d, result=%f", data[0], data[1], e25); + } + if (this->ec_sensor_ != nullptr) { + ec = ((data[3] << 8) | data[2]) / 10.0; + this->ec_sensor_->publish_state(ec); + ESP_LOGVV(TAG, "ec: data[2]=%d, data[3]=%d, result=%f", data[2], data[3], ec); + } + if (this->temperature_sensor_ != nullptr) { + temperature = ((data[5] << 8) | data[4]) / 100.0; + this->temperature_sensor_->publish_state(temperature); + ESP_LOGVV(TAG, "temp: data[4]=%d, data[5]=%d, result=%f", data[4], data[5], temperature); + } + if (this->vwc_sensor_ != nullptr) { + vwc = ((data[7] << 8) | data[6]) / 10.0; + this->vwc_sensor_->publish_state(vwc); + ESP_LOGVV(TAG, "vwc: data[6]=%d, data[7]=%d, result=%f", data[6], data[7], vwc); + } +} + +} // namespace pmwcs3 +} // namespace esphome diff --git a/esphome/components/pmwcs3/pmwcs3.h b/esphome/components/pmwcs3/pmwcs3.h new file mode 100644 index 0000000000..f3916bb868 --- /dev/null +++ b/esphome/components/pmwcs3/pmwcs3.h @@ -0,0 +1,70 @@ +#pragma once +#include "esphome/core/automation.h" +#include "esphome/core/component.h" +#include "esphome/components/sensor/sensor.h" +#include "esphome/components/i2c/i2c.h" + +// ref: +// https://github.com/tinovi/i2cArduino/blob/master/i2cArduino.h + +namespace esphome { +namespace pmwcs3 { + +class PMWCS3Component : public PollingComponent, public i2c::I2CDevice { + public: + void setup() override; + 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; } + void set_temperature_sensor(sensor::Sensor *temperature_sensor) { temperature_sensor_ = temperature_sensor; } + void set_vwc_sensor(sensor::Sensor *vwc_sensor) { vwc_sensor_ = vwc_sensor; } + + void new_i2c_address(uint8_t newaddress); + void air_calibration(); + void water_calibration(); + + protected: + void read_data_(); + + sensor::Sensor *e25_sensor_{nullptr}; + sensor::Sensor *ec_sensor_{nullptr}; + sensor::Sensor *temperature_sensor_{nullptr}; + sensor::Sensor *vwc_sensor_{nullptr}; +}; + +template class PMWCS3AirCalibrationAction : public Action { + public: + PMWCS3AirCalibrationAction(PMWCS3Component *parent) : parent_(parent) {} + + void play(Ts... x) override { this->parent_->air_calibration(); } + + protected: + PMWCS3Component *parent_; +}; + +template class PMWCS3WaterCalibrationAction : public Action { + public: + PMWCS3WaterCalibrationAction(PMWCS3Component *parent) : parent_(parent) {} + + void play(Ts... x) override { this->parent_->water_calibration(); } + + protected: + PMWCS3Component *parent_; +}; + +template class PMWCS3NewI2cAddressAction : public Action { + public: + PMWCS3NewI2cAddressAction(PMWCS3Component *parent) : parent_(parent) {} + TEMPLATABLE_VALUE(int, new_address) + + void play(Ts... x) override { this->parent_->new_i2c_address(this->new_address_.value(x...)); } + + protected: + PMWCS3Component *parent_; +}; + +} // namespace pmwcs3 +} // namespace esphome diff --git a/esphome/components/pmwcs3/sensor.py b/esphome/components/pmwcs3/sensor.py new file mode 100644 index 0000000000..81be327d14 --- /dev/null +++ b/esphome/components/pmwcs3/sensor.py @@ -0,0 +1,140 @@ +import esphome.codegen as cg +from esphome import automation +import esphome.config_validation as cv +from esphome.components import i2c, sensor +from esphome.const import ( + CONF_ID, + CONF_ADDRESS, + CONF_TEMPERATURE, + CONF_EC, + STATE_CLASS_MEASUREMENT, + ICON_THERMOMETER, +) + +CODEOWNERS = ["@SeByDocKy"] +DEPENDENCIES = ["i2c"] + +CONF_E25 = "e25" +CONF_VWC = "vwc" + +ICON_EPSILON = "mdi:epsilon" +ICON_SIGMA = "mdi:sigma-lower" +ICON_ALPHA = "mdi:alpha-h-circle-outline" + +pmwcs3_ns = cg.esphome_ns.namespace("pmwcs3") +PMWCS3Component = pmwcs3_ns.class_( + "PMWCS3Component", cg.PollingComponent, i2c.I2CDevice +) + +# Actions +PMWCS3AirCalibrationAction = pmwcs3_ns.class_( + "PMWCS3AirCalibrationAction", automation.Action +) +PMWCS3WaterCalibrationAction = pmwcs3_ns.class_( + "PMWCS3WaterCalibrationAction", automation.Action +) +PMWCS3NewI2cAddressAction = pmwcs3_ns.class_( + "PMWCS3NewI2cAddressAction", automation.Action +) + +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(PMWCS3Component), + cv.Optional(CONF_E25): sensor.sensor_schema( + icon=ICON_EPSILON, + accuracy_decimals=3, + unit_of_measurement="dS/m", + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_EC): sensor.sensor_schema( + icon=ICON_SIGMA, + accuracy_decimals=2, + unit_of_measurement="mS/m", + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema( + icon=ICON_THERMOMETER, + accuracy_decimals=3, + unit_of_measurement="°C", + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_VWC): sensor.sensor_schema( + icon=ICON_ALPHA, + accuracy_decimals=3, + unit_of_measurement="cm3cm−3", + state_class=STATE_CLASS_MEASUREMENT, + ), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x63)) +) + + +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_E25 in config: + sens = await sensor.new_sensor(config[CONF_E25]) + cg.add(var.set_e25_sensor(sens)) + + if CONF_EC in config: + sens = await sensor.new_sensor(config[CONF_EC]) + cg.add(var.set_ec_sensor(sens)) + + if CONF_TEMPERATURE in config: + sens = await sensor.new_sensor(config[CONF_TEMPERATURE]) + cg.add(var.set_temperature_sensor(sens)) + + if CONF_VWC in config: + sens = await sensor.new_sensor(config[CONF_VWC]) + cg.add(var.set_vwc_sensor(sens)) + + +# Actions +PMWCS3_CALIBRATION_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.use_id(PMWCS3Component), + } +) + + +@automation.register_action( + "pmwcs3.air_calibration", + PMWCS3AirCalibrationAction, + PMWCS3_CALIBRATION_SCHEMA, +) +@automation.register_action( + "pmwcs3.water_calibration", + PMWCS3WaterCalibrationAction, + PMWCS3_CALIBRATION_SCHEMA, +) +async def pmwcs3_calibration_to_code(config, action_id, template_arg, args): + parent = await cg.get_variable(config[CONF_ID]) + var = cg.new_Pvariable(action_id, template_arg, parent) + return var + + +PMWCS3_NEW_I2C_ADDRESS_SCHEMA = cv.maybe_simple_value( + { + cv.GenerateID(): cv.use_id(PMWCS3Component), + cv.Required(CONF_ADDRESS): cv.templatable(cv.i2c_address), + }, + key=CONF_ADDRESS, +) + + +@automation.register_action( + "pmwcs3.new_i2c_address", + PMWCS3NewI2cAddressAction, + PMWCS3_NEW_I2C_ADDRESS_SCHEMA, +) +async def pmwcs3newi2caddress_to_code(config, action_id, template_arg, args): + parent = await cg.get_variable(config[CONF_ID]) + var = cg.new_Pvariable(action_id, template_arg, parent) + address = await cg.templatable(config[CONF_ADDRESS], args, int) + cg.add(var.set_new_address(address)) + return var diff --git a/tests/test1.yaml b/tests/test1.yaml index 66caad961a..80cd9e3987 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -348,6 +348,16 @@ mcp23s17: deviceaddress: 1 sensor: + - platform: pmwcs3 + i2c_id: i2c_bus + e25: + name: pmwcs3_e25 + ec: + name: pmwcs3_ec + temperature: + name: pmwcs3_temperature + vwc: + name: pmwcs3_vwc - platform: gcja5 pm_1_0: name: "Particulate Matter <1.0µm Concentration" From 164d05fdcea31ea295e3ac98cd06966aacb236a1 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Fri, 18 Aug 2023 06:05:25 +1000 Subject: [PATCH 0079/2101] Add manufacturer data config to BLE server (#5251) --- CODEOWNERS | 2 +- .../components/esp32_ble/ble_advertising.cpp | 37 ++++++++++++------- .../components/esp32_ble/ble_advertising.h | 2 +- .../components/esp32_ble_server/__init__.py | 6 ++- .../esp32_ble_server/ble_server.cpp | 8 ++++ .../components/esp32_ble_server/ble_server.h | 6 +++ tests/test2.yaml | 5 +++ 7 files changed, 50 insertions(+), 16 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index 0cea8d48ba..49746cf013 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -87,7 +87,7 @@ esphome/components/ens210/* @itn3rd77 esphome/components/esp32/* @esphome/core esphome/components/esp32_ble/* @jesserockz esphome/components/esp32_ble_client/* @jesserockz -esphome/components/esp32_ble_server/* @jesserockz +esphome/components/esp32_ble_server/* @clydebarrow @jesserockz esphome/components/esp32_camera_web_server/* @ayufan esphome/components/esp32_can/* @Sympatron esphome/components/esp32_improv/* @jesserockz diff --git a/esphome/components/esp32_ble/ble_advertising.cpp b/esphome/components/esp32_ble/ble_advertising.cpp index 2083bf5f08..072bb38c07 100644 --- a/esphome/components/esp32_ble/ble_advertising.cpp +++ b/esphome/components/esp32_ble/ble_advertising.cpp @@ -42,9 +42,15 @@ void BLEAdvertising::remove_service_uuid(ESPBTUUID uuid) { this->advertising_uuids_.end()); } -void BLEAdvertising::set_manufacturer_data(uint8_t *data, uint16_t size) { - this->advertising_data_.p_manufacturer_data = data; - this->advertising_data_.manufacturer_len = size; +void BLEAdvertising::set_manufacturer_data(const std::vector &data) { + delete[] this->advertising_data_.p_manufacturer_data; + this->advertising_data_.p_manufacturer_data = nullptr; + this->advertising_data_.manufacturer_len = data.size(); + if (!data.empty()) { + // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) + this->advertising_data_.p_manufacturer_data = new uint8_t[data.size()]; + memcpy(this->advertising_data_.p_manufacturer_data, data.data(), data.size()); + } } void BLEAdvertising::start() { @@ -74,16 +80,21 @@ void BLEAdvertising::start() { return; } - memcpy(&this->scan_response_data_, &this->advertising_data_, sizeof(esp_ble_adv_data_t)); - this->scan_response_data_.set_scan_rsp = true; - this->scan_response_data_.include_name = true; - this->scan_response_data_.include_txpower = true; - this->scan_response_data_.appearance = 0; - this->scan_response_data_.flag = 0; - err = esp_ble_gap_config_adv_data(&this->scan_response_data_); - if (err != ESP_OK) { - ESP_LOGE(TAG, "esp_ble_gap_config_adv_data failed (Scan response): %d", err); - return; + if (this->scan_response_) { + memcpy(&this->scan_response_data_, &this->advertising_data_, sizeof(esp_ble_adv_data_t)); + this->scan_response_data_.set_scan_rsp = true; + this->scan_response_data_.include_name = true; + this->scan_response_data_.include_txpower = true; + this->scan_response_data_.min_interval = 0; + this->scan_response_data_.max_interval = 0; + this->scan_response_data_.manufacturer_len = 0; + this->scan_response_data_.appearance = 0; + this->scan_response_data_.flag = 0; + err = esp_ble_gap_config_adv_data(&this->scan_response_data_); + if (err != ESP_OK) { + ESP_LOGE(TAG, "esp_ble_gap_config_adv_data failed (Scan response): %d", err); + return; + } } if (this->advertising_data_.service_uuid_len > 0) { diff --git a/esphome/components/esp32_ble/ble_advertising.h b/esphome/components/esp32_ble/ble_advertising.h index 079bd6c14c..9e4e2b7701 100644 --- a/esphome/components/esp32_ble/ble_advertising.h +++ b/esphome/components/esp32_ble/ble_advertising.h @@ -20,7 +20,7 @@ class BLEAdvertising { void remove_service_uuid(ESPBTUUID uuid); void set_scan_response(bool scan_response) { this->scan_response_ = scan_response; } void set_min_preferred_interval(uint16_t interval) { this->advertising_data_.min_interval = interval; } - void set_manufacturer_data(uint8_t *data, uint16_t size); + void set_manufacturer_data(const std::vector &data); void start(); void stop(); diff --git a/esphome/components/esp32_ble_server/__init__.py b/esphome/components/esp32_ble_server/__init__.py index 0ddfa62c1b..5e1ad71501 100644 --- a/esphome/components/esp32_ble_server/__init__.py +++ b/esphome/components/esp32_ble_server/__init__.py @@ -6,11 +6,12 @@ from esphome.core import CORE from esphome.components.esp32 import add_idf_sdkconfig_option AUTO_LOAD = ["esp32_ble"] -CODEOWNERS = ["@jesserockz"] +CODEOWNERS = ["@jesserockz", "@clydebarrow"] CONFLICTS_WITH = ["esp32_ble_beacon"] DEPENDENCIES = ["esp32"] CONF_MANUFACTURER = "manufacturer" +CONF_MANUFACTURER_DATA = "manufacturer_data" esp32_ble_server_ns = cg.esphome_ns.namespace("esp32_ble_server") BLEServer = esp32_ble_server_ns.class_( @@ -27,6 +28,7 @@ CONFIG_SCHEMA = cv.Schema( cv.GenerateID(): cv.declare_id(BLEServer), cv.GenerateID(esp32_ble.CONF_BLE_ID): cv.use_id(esp32_ble.ESP32BLE), cv.Optional(CONF_MANUFACTURER, default="ESPHome"): cv.string, + cv.Optional(CONF_MANUFACTURER_DATA): cv.Schema([cv.hex_uint8_t]), cv.Optional(CONF_MODEL): cv.string, } ).extend(cv.COMPONENT_SCHEMA) @@ -42,6 +44,8 @@ async def to_code(config): cg.add(var.set_parent(parent)) cg.add(var.set_manufacturer(config[CONF_MANUFACTURER])) + if CONF_MANUFACTURER_DATA in config: + cg.add(var.set_manufacturer_data(config[CONF_MANUFACTURER_DATA])) if CONF_MODEL in config: cg.add(var.set_model(config[CONF_MODEL])) cg.add_define("USE_ESP32_BLE_SERVER") diff --git a/esphome/components/esp32_ble_server/ble_server.cpp b/esphome/components/esp32_ble_server/ble_server.cpp index 7cbf40c076..ca244aba95 100644 --- a/esphome/components/esp32_ble_server/ble_server.cpp +++ b/esphome/components/esp32_ble_server/ble_server.cpp @@ -68,6 +68,7 @@ void BLEServer::loop() { if (this->device_information_service_->is_running()) { this->state_ = RUNNING; this->can_proceed_ = true; + this->restart_advertising_(); ESP_LOGD(TAG, "BLE server setup successfully"); } else if (!this->device_information_service_->is_starting()) { this->device_information_service_->start(); @@ -77,6 +78,13 @@ void BLEServer::loop() { } } +void BLEServer::restart_advertising_() { + if (this->state_ == RUNNING) { + esp32_ble::global_ble->get_advertising()->set_manufacturer_data(this->manufacturer_data_); + esp32_ble::global_ble->get_advertising()->start(); + } +} + bool BLEServer::create_device_characteristics_() { if (this->model_.has_value()) { BLECharacteristic *model = diff --git a/esphome/components/esp32_ble_server/ble_server.h b/esphome/components/esp32_ble_server/ble_server.h index ac759f2dcd..14c88be1a2 100644 --- a/esphome/components/esp32_ble_server/ble_server.h +++ b/esphome/components/esp32_ble_server/ble_server.h @@ -45,6 +45,10 @@ class BLEServer : public Component, public GATTsEventHandler, public Parentedmanufacturer_ = manufacturer; } void set_model(const std::string &model) { this->model_ = model; } + void set_manufacturer_data(const std::vector &data) { + this->manufacturer_data_ = data; + this->restart_advertising_(); + } std::shared_ptr create_service(const uint8_t *uuid, bool advertise = false); std::shared_ptr create_service(uint16_t uuid, bool advertise = false); @@ -63,6 +67,7 @@ class BLEServer : public Component, public GATTsEventHandler, public Parentedclients_.insert(std::pair(conn_id, client)); @@ -73,6 +78,7 @@ class BLEServer : public Component, public GATTsEventHandler, public Parented model_; + std::vector manufacturer_data_; esp_gatt_if_t gatts_if_{0}; bool registered_{false}; diff --git a/tests/test2.yaml b/tests/test2.yaml index 291dc240dc..d1508632b3 100644 --- a/tests/test2.yaml +++ b/tests/test2.yaml @@ -768,3 +768,8 @@ switch: characteristic_uuid: 6490FAFE-0734-732C-8705-91B653A081FC value: !lambda |- return {0x13, 0x37}; + + +esp32_ble_server: + id: ble + manufacturer_data: [0x72, 0x4, 0x00, 0x23] From c287e529a88e70dc7ec2fd8115a74d81e8c72fa3 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 18 Aug 2023 08:06:21 +1200 Subject: [PATCH 0080/2101] Change haier from AUTO to HEAT_COOL (#5267) --- esphome/components/haier/climate.py | 2 +- esphome/components/haier/haier_base.cpp | 6 +++--- esphome/components/haier/hon_climate.cpp | 4 ++-- esphome/components/haier/smartair2_climate.cpp | 4 ++-- tests/test3.yaml | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/esphome/components/haier/climate.py b/esphome/components/haier/climate.py index fec39d2967..acb079c822 100644 --- a/esphome/components/haier/climate.py +++ b/esphome/components/haier/climate.py @@ -89,7 +89,7 @@ SUPPORTED_SWING_MODES_OPTIONS = { SUPPORTED_CLIMATE_MODES_OPTIONS = { "OFF": ClimateMode.CLIMATE_MODE_OFF, # always available - "AUTO": ClimateMode.CLIMATE_MODE_AUTO, # always available + "HEAT_COOL": ClimateMode.CLIMATE_MODE_HEAT_COOL, # always available "COOL": ClimateMode.CLIMATE_MODE_COOL, "HEAT": ClimateMode.CLIMATE_MODE_HEAT, "DRY": ClimateMode.CLIMATE_MODE_DRY, diff --git a/esphome/components/haier/haier_base.cpp b/esphome/components/haier/haier_base.cpp index 5faee5207b..22899b1a70 100644 --- a/esphome/components/haier/haier_base.cpp +++ b/esphome/components/haier/haier_base.cpp @@ -72,7 +72,7 @@ HaierClimateBase::HaierClimateBase() this->traits_ = climate::ClimateTraits(); this->traits_.set_supported_modes({climate::CLIMATE_MODE_OFF, climate::CLIMATE_MODE_COOL, climate::CLIMATE_MODE_HEAT, climate::CLIMATE_MODE_FAN_ONLY, climate::CLIMATE_MODE_DRY, - climate::CLIMATE_MODE_AUTO}); + climate::CLIMATE_MODE_HEAT_COOL}); this->traits_.set_supported_fan_modes( {climate::CLIMATE_FAN_AUTO, climate::CLIMATE_FAN_LOW, climate::CLIMATE_FAN_MEDIUM, climate::CLIMATE_FAN_HIGH}); this->traits_.set_supported_swing_modes({climate::CLIMATE_SWING_OFF, climate::CLIMATE_SWING_BOTH, @@ -171,8 +171,8 @@ void HaierClimateBase::set_answer_timeout(uint32_t timeout) { void HaierClimateBase::set_supported_modes(const std::set &modes) { this->traits_.set_supported_modes(modes); - this->traits_.add_supported_mode(climate::CLIMATE_MODE_OFF); // Always available - this->traits_.add_supported_mode(climate::CLIMATE_MODE_AUTO); // Always available + this->traits_.add_supported_mode(climate::CLIMATE_MODE_OFF); // Always available + this->traits_.add_supported_mode(climate::CLIMATE_MODE_HEAT_COOL); // Always available } void HaierClimateBase::set_supported_presets(const std::set &presets) { diff --git a/esphome/components/haier/hon_climate.cpp b/esphome/components/haier/hon_climate.cpp index feb1e019d8..d4944410f7 100644 --- a/esphome/components/haier/hon_climate.cpp +++ b/esphome/components/haier/hon_climate.cpp @@ -458,7 +458,7 @@ haier_protocol::HaierMessage HonClimate::get_control_message() { case CLIMATE_MODE_OFF: out_data->ac_power = 0; break; - case CLIMATE_MODE_AUTO: + case CLIMATE_MODE_HEAT_COOL: out_data->ac_power = 1; out_data->ac_mode = (uint8_t) hon_protocol::ConditioningMode::AUTO; out_data->fan_mode = this->other_modes_fan_speed_; @@ -758,7 +758,7 @@ haier_protocol::HandlerError HonClimate::process_status_message_(const uint8_t * this->mode = CLIMATE_MODE_FAN_ONLY; break; case (uint8_t) hon_protocol::ConditioningMode::AUTO: - this->mode = CLIMATE_MODE_AUTO; + this->mode = CLIMATE_MODE_HEAT_COOL; break; } } diff --git a/esphome/components/haier/smartair2_climate.cpp b/esphome/components/haier/smartair2_climate.cpp index 8bee37dadf..f29f840088 100644 --- a/esphome/components/haier/smartair2_climate.cpp +++ b/esphome/components/haier/smartair2_climate.cpp @@ -270,7 +270,7 @@ haier_protocol::HaierMessage Smartair2Climate::get_control_message() { out_data->ac_power = 0; break; - case CLIMATE_MODE_AUTO: + case CLIMATE_MODE_HEAT_COOL: out_data->ac_power = 1; out_data->ac_mode = (uint8_t) smartair2_protocol::ConditioningMode::AUTO; out_data->fan_mode = this->other_modes_fan_speed_; @@ -487,7 +487,7 @@ haier_protocol::HandlerError Smartair2Climate::process_status_message_(const uin this->mode = CLIMATE_MODE_FAN_ONLY; break; case (uint8_t) smartair2_protocol::ConditioningMode::AUTO: - this->mode = CLIMATE_MODE_AUTO; + this->mode = CLIMATE_MODE_HEAT_COOL; break; } } diff --git a/tests/test3.yaml b/tests/test3.yaml index 5bda0afb1b..471b7d97b6 100644 --- a/tests/test3.yaml +++ b/tests/test3.yaml @@ -957,7 +957,7 @@ climate: temperature_step: 1 °C supported_modes: - 'OFF' - - AUTO + - HEAT_COOL - COOL - HEAT - DRY From b566c78f001745cb65a94bbd6e3d4efc02dd3b45 Mon Sep 17 00:00:00 2001 From: Mat931 <49403702+Mat931@users.noreply.github.com> Date: Thu, 17 Aug 2023 19:57:18 +0000 Subject: [PATCH 0081/2101] Fix checksum calculation for sml (#5271) --- esphome/components/sml/sml.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/sml/sml.cpp b/esphome/components/sml/sml.cpp index 87dc25c220..921623d4fd 100644 --- a/esphome/components/sml/sml.cpp +++ b/esphome/components/sml/sml.cpp @@ -100,14 +100,14 @@ bool check_sml_data(const bytes &buffer) { } uint16_t crc_received = (buffer.at(buffer.size() - 2) << 8) | buffer.at(buffer.size() - 1); - uint16_t crc_calculated = crc16(buffer.data(), buffer.size(), 0x6e23, 0x8408, true, true); + uint16_t crc_calculated = crc16(buffer.data(), buffer.size() - 2, 0x6e23, 0x8408, true, true); crc_calculated = (crc_calculated >> 8) | (crc_calculated << 8); if (crc_received == crc_calculated) { ESP_LOGV(TAG, "Checksum verification successful with CRC16/X25."); return true; } - crc_calculated = crc16(buffer.data(), buffer.size(), 0xed50, 0x8408); + crc_calculated = crc16(buffer.data(), buffer.size() - 2, 0xed50, 0x8408); if (crc_received == crc_calculated) { ESP_LOGV(TAG, "Checksum verification successful with CRC16/KERMIT."); return true; From 0789657fd52aeacda56790504af4a91ea4034440 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 18 Aug 2023 08:06:21 +1200 Subject: [PATCH 0082/2101] Change haier from AUTO to HEAT_COOL (#5267) --- esphome/components/haier/climate.py | 2 +- esphome/components/haier/haier_base.cpp | 6 +++--- esphome/components/haier/hon_climate.cpp | 4 ++-- esphome/components/haier/smartair2_climate.cpp | 4 ++-- tests/test3.yaml | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/esphome/components/haier/climate.py b/esphome/components/haier/climate.py index fec39d2967..acb079c822 100644 --- a/esphome/components/haier/climate.py +++ b/esphome/components/haier/climate.py @@ -89,7 +89,7 @@ SUPPORTED_SWING_MODES_OPTIONS = { SUPPORTED_CLIMATE_MODES_OPTIONS = { "OFF": ClimateMode.CLIMATE_MODE_OFF, # always available - "AUTO": ClimateMode.CLIMATE_MODE_AUTO, # always available + "HEAT_COOL": ClimateMode.CLIMATE_MODE_HEAT_COOL, # always available "COOL": ClimateMode.CLIMATE_MODE_COOL, "HEAT": ClimateMode.CLIMATE_MODE_HEAT, "DRY": ClimateMode.CLIMATE_MODE_DRY, diff --git a/esphome/components/haier/haier_base.cpp b/esphome/components/haier/haier_base.cpp index 5faee5207b..22899b1a70 100644 --- a/esphome/components/haier/haier_base.cpp +++ b/esphome/components/haier/haier_base.cpp @@ -72,7 +72,7 @@ HaierClimateBase::HaierClimateBase() this->traits_ = climate::ClimateTraits(); this->traits_.set_supported_modes({climate::CLIMATE_MODE_OFF, climate::CLIMATE_MODE_COOL, climate::CLIMATE_MODE_HEAT, climate::CLIMATE_MODE_FAN_ONLY, climate::CLIMATE_MODE_DRY, - climate::CLIMATE_MODE_AUTO}); + climate::CLIMATE_MODE_HEAT_COOL}); this->traits_.set_supported_fan_modes( {climate::CLIMATE_FAN_AUTO, climate::CLIMATE_FAN_LOW, climate::CLIMATE_FAN_MEDIUM, climate::CLIMATE_FAN_HIGH}); this->traits_.set_supported_swing_modes({climate::CLIMATE_SWING_OFF, climate::CLIMATE_SWING_BOTH, @@ -171,8 +171,8 @@ void HaierClimateBase::set_answer_timeout(uint32_t timeout) { void HaierClimateBase::set_supported_modes(const std::set &modes) { this->traits_.set_supported_modes(modes); - this->traits_.add_supported_mode(climate::CLIMATE_MODE_OFF); // Always available - this->traits_.add_supported_mode(climate::CLIMATE_MODE_AUTO); // Always available + this->traits_.add_supported_mode(climate::CLIMATE_MODE_OFF); // Always available + this->traits_.add_supported_mode(climate::CLIMATE_MODE_HEAT_COOL); // Always available } void HaierClimateBase::set_supported_presets(const std::set &presets) { diff --git a/esphome/components/haier/hon_climate.cpp b/esphome/components/haier/hon_climate.cpp index feb1e019d8..d4944410f7 100644 --- a/esphome/components/haier/hon_climate.cpp +++ b/esphome/components/haier/hon_climate.cpp @@ -458,7 +458,7 @@ haier_protocol::HaierMessage HonClimate::get_control_message() { case CLIMATE_MODE_OFF: out_data->ac_power = 0; break; - case CLIMATE_MODE_AUTO: + case CLIMATE_MODE_HEAT_COOL: out_data->ac_power = 1; out_data->ac_mode = (uint8_t) hon_protocol::ConditioningMode::AUTO; out_data->fan_mode = this->other_modes_fan_speed_; @@ -758,7 +758,7 @@ haier_protocol::HandlerError HonClimate::process_status_message_(const uint8_t * this->mode = CLIMATE_MODE_FAN_ONLY; break; case (uint8_t) hon_protocol::ConditioningMode::AUTO: - this->mode = CLIMATE_MODE_AUTO; + this->mode = CLIMATE_MODE_HEAT_COOL; break; } } diff --git a/esphome/components/haier/smartair2_climate.cpp b/esphome/components/haier/smartair2_climate.cpp index 8bee37dadf..f29f840088 100644 --- a/esphome/components/haier/smartair2_climate.cpp +++ b/esphome/components/haier/smartair2_climate.cpp @@ -270,7 +270,7 @@ haier_protocol::HaierMessage Smartair2Climate::get_control_message() { out_data->ac_power = 0; break; - case CLIMATE_MODE_AUTO: + case CLIMATE_MODE_HEAT_COOL: out_data->ac_power = 1; out_data->ac_mode = (uint8_t) smartair2_protocol::ConditioningMode::AUTO; out_data->fan_mode = this->other_modes_fan_speed_; @@ -487,7 +487,7 @@ haier_protocol::HandlerError Smartair2Climate::process_status_message_(const uin this->mode = CLIMATE_MODE_FAN_ONLY; break; case (uint8_t) smartair2_protocol::ConditioningMode::AUTO: - this->mode = CLIMATE_MODE_AUTO; + this->mode = CLIMATE_MODE_HEAT_COOL; break; } } diff --git a/tests/test3.yaml b/tests/test3.yaml index 5bda0afb1b..471b7d97b6 100644 --- a/tests/test3.yaml +++ b/tests/test3.yaml @@ -957,7 +957,7 @@ climate: temperature_step: 1 °C supported_modes: - 'OFF' - - AUTO + - HEAT_COOL - COOL - HEAT - DRY From 427866420859957be626e86799ac2edae19b333c Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 18 Aug 2023 08:12:42 +1200 Subject: [PATCH 0083/2101] Bump version to 2023.8.1 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index f0a6efda94..b8c910cd9e 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2023.8.0" +__version__ = "2023.8.1" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From f16a24ddf460c48176391b06078a70bdedd974b1 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 18 Aug 2023 19:13:46 +1200 Subject: [PATCH 0084/2101] Move libcairo to all architectures in docker (#5276) --- docker/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 4aaea9da89..b942b650cb 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -28,14 +28,14 @@ RUN \ git=1:2.30.2-1+deb11u2 \ curl=7.74.0-1.3+deb11u7 \ openssh-client=1:8.4p1-5+deb11u1 \ - python3-cffi=1.14.5-1; \ + python3-cffi=1.14.5-1 \ + libcairo2=1.16.0-5; \ if [ "$TARGETARCH$TARGETVARIANT" = "armv7" ]; then \ apt-get install -y --no-install-recommends \ build-essential=12.9 \ python3-dev=3.9.2-3 \ zlib1g-dev=1:1.2.11.dfsg-2+deb11u2 \ libjpeg-dev=1:2.0.6-4 \ - libcairo2=1.16.0-5 \ libfreetype-dev=2.10.4+dfsg-1+deb11u1; \ fi; \ rm -rf \ From c47c1a78675ace5a314cddf3ab059684f07d98d8 Mon Sep 17 00:00:00 2001 From: mwolter805 <24851651+mwolter805@users.noreply.github.com> Date: Sun, 20 Aug 2023 12:15:45 -0700 Subject: [PATCH 0085/2101] Resolve offline ESPs in dashboard when using ESPHOME_DASHBOARD_USE_PING=true (#5281) --- esphome/dashboard/dashboard.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/esphome/dashboard/dashboard.py b/esphome/dashboard/dashboard.py index b33cb2df5e..eae004fa09 100644 --- a/esphome/dashboard/dashboard.py +++ b/esphome/dashboard/dashboard.py @@ -868,9 +868,6 @@ class PingStatusThread(threading.Thread): entries = _list_dashboard_entries() queue = collections.deque() for entry in entries: - if entry.no_mdns is True: - continue - if entry.address is None: PING_RESULT[entry.filename] = None continue From bfdcfa476664ea1dc4c14731a8c6a60dd0d7737c Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Mon, 21 Aug 2023 06:57:02 +1000 Subject: [PATCH 0086/2101] Align SPI data rates in C++ code with Python (#5284) --- esphome/components/spi/__init__.py | 2 ++ esphome/components/spi/spi.h | 1 + 2 files changed, 3 insertions(+) diff --git a/esphome/components/spi/__init__.py b/esphome/components/spi/__init__.py index 1528a05734..57a4fa9f4e 100644 --- a/esphome/components/spi/__init__.py +++ b/esphome/components/spi/__init__.py @@ -23,7 +23,9 @@ SPI_DATA_RATE_OPTIONS = { 40e6: SPIDataRate.DATA_RATE_40MHZ, 20e6: SPIDataRate.DATA_RATE_20MHZ, 10e6: SPIDataRate.DATA_RATE_10MHZ, + 8e6: SPIDataRate.DATA_RATE_8MHZ, 5e6: SPIDataRate.DATA_RATE_5MHZ, + 4e6: SPIDataRate.DATA_RATE_4MHZ, 2e6: SPIDataRate.DATA_RATE_2MHZ, 1e6: SPIDataRate.DATA_RATE_1MHZ, 2e5: SPIDataRate.DATA_RATE_200KHZ, diff --git a/esphome/components/spi/spi.h b/esphome/components/spi/spi.h index f19518caae..159d117533 100644 --- a/esphome/components/spi/spi.h +++ b/esphome/components/spi/spi.h @@ -63,6 +63,7 @@ enum SPIDataRate : uint32_t { DATA_RATE_1MHZ = 1000000, DATA_RATE_2MHZ = 2000000, DATA_RATE_4MHZ = 4000000, + DATA_RATE_5MHZ = 5000000, DATA_RATE_8MHZ = 8000000, DATA_RATE_10MHZ = 10000000, DATA_RATE_20MHZ = 20000000, From d19bf5d6ee585ec1033c04397dbcadb251d03c42 Mon Sep 17 00:00:00 2001 From: jayme-github Date: Sun, 20 Aug 2023 23:34:50 +0200 Subject: [PATCH 0087/2101] Add support for ESP32-{S2,S3,C3} to debug component (#4731) --- esphome/components/debug/debug_component.cpp | 75 +++++++++++++++++--- 1 file changed, 67 insertions(+), 8 deletions(-) diff --git a/esphome/components/debug/debug_component.cpp b/esphome/components/debug/debug_component.cpp index baf537a12b..5ee1960267 100644 --- a/esphome/components/debug/debug_component.cpp +++ b/esphome/components/debug/debug_component.cpp @@ -12,8 +12,16 @@ #include #include -#include #include +#if defined(USE_ESP32_VARIANT_ESP32) +#include +#elif defined(USE_ESP32_VARIANT_ESP32C3) +#include +#elif defined(USE_ESP32_VARIANT_ESP32S2) +#include +#elif defined(USE_ESP32_VARIANT_ESP32S3) +#include +#endif #endif // USE_ESP32 @@ -105,13 +113,19 @@ void DebugComponent::dump_config() { esp_chip_info_t info; esp_chip_info(&info); const char *model; - switch (info.model) { - case CHIP_ESP32: - model = "ESP32"; - break; - default: - model = "UNKNOWN"; - } +#if defined(USE_ESP32_VARIANT_ESP32) + model = "ESP32"; +#elif defined(USE_ESP32_VARIANT_ESP32C3) + model = "ESP32-C3"; +#elif defined(USE_ESP32_VARIANT_ESP32S2) + model = "ESP32-S2"; +#elif defined(USE_ESP32_VARIANT_ESP32S3) + model = "ESP32-S3"; +#elif defined(USE_ESP32_VARIANT_ESP32H2) + model = "ESP32-H2"; +#else + model = "UNKNOWN"; +#endif std::string features; if (info.features & CHIP_FEATURE_EMB_FLASH) { features += "EMB_FLASH,"; @@ -153,18 +167,26 @@ void DebugComponent::dump_config() { case POWERON_RESET: reset_reason = "Power On Reset"; break; +#if defined(USE_ESP32_VARIANT_ESP32) case SW_RESET: +#elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) + case RTC_SW_SYS_RESET: +#endif reset_reason = "Software Reset Digital Core"; break; +#if defined(USE_ESP32_VARIANT_ESP32) case OWDT_RESET: reset_reason = "Watch Dog Reset Digital Core"; break; +#endif case DEEPSLEEP_RESET: reset_reason = "Deep Sleep Reset Digital Core"; break; +#if defined(USE_ESP32_VARIANT_ESP32) case SDIO_RESET: reset_reason = "SLC Module Reset Digital Core"; break; +#endif case TG0WDT_SYS_RESET: reset_reason = "Timer Group 0 Watch Dog Reset Digital Core"; break; @@ -177,24 +199,61 @@ void DebugComponent::dump_config() { case INTRUSION_RESET: reset_reason = "Intrusion Reset CPU"; break; +#if defined(USE_ESP32_VARIANT_ESP32) case TGWDT_CPU_RESET: reset_reason = "Timer Group Reset CPU"; break; +#elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) + case TG0WDT_CPU_RESET: + reset_reason = "Timer Group 0 Reset CPU"; + break; +#endif +#if defined(USE_ESP32_VARIANT_ESP32) case SW_CPU_RESET: +#elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) + case RTC_SW_CPU_RESET: +#endif reset_reason = "Software Reset CPU"; break; case RTCWDT_CPU_RESET: reset_reason = "RTC Watch Dog Reset CPU"; break; +#if defined(USE_ESP32_VARIANT_ESP32) case EXT_CPU_RESET: reset_reason = "External CPU Reset"; break; +#endif case RTCWDT_BROWN_OUT_RESET: reset_reason = "Voltage Unstable Reset"; break; case RTCWDT_RTC_RESET: reset_reason = "RTC Watch Dog Reset Digital Core And RTC Module"; break; +#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) + case TG1WDT_CPU_RESET: + reset_reason = "Timer Group 1 Reset CPU"; + break; + case SUPER_WDT_RESET: + reset_reason = "Super Watchdog Reset Digital Core And RTC Module"; + break; + case GLITCH_RTC_RESET: + reset_reason = "Glitch Reset Digital Core And RTC Module"; + break; + case EFUSE_RESET: + reset_reason = "eFuse Reset Digital Core"; + break; +#endif +#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S3) + case USB_UART_CHIP_RESET: + reset_reason = "USB UART Reset Digital Core"; + break; + case USB_JTAG_CHIP_RESET: + reset_reason = "USB JTAG Reset Digital Core"; + break; + case POWER_GLITCH_RESET: + reset_reason = "Power Glitch Reset Digital Core And RTC Module"; + break; +#endif default: reset_reason = "Unknown Reset Reason"; } From fe7893d1b3178912ad8e016d0ffba2bf6836928d Mon Sep 17 00:00:00 2001 From: Austin Date: Sun, 20 Aug 2023 17:42:03 -0400 Subject: [PATCH 0088/2101] Support for ESP32-C2 & ESP32-C6 (#4377) Co-authored-by: Stijn Tintel --- esphome/components/adc/__init__.py | 18 +++++++ esphome/components/deep_sleep/__init__.py | 4 ++ esphome/components/esp32/__init__.py | 1 - esphome/components/esp32/const.py | 6 +++ esphome/components/esp32/gpio.py | 12 +++++ esphome/components/esp32/gpio_esp32_c2.py | 37 ++++++++++++++ esphome/components/esp32/gpio_esp32_c6.py | 50 +++++++++++++++++++ .../components/esp32_rmt_led_strip/light.py | 1 + esphome/components/logger/__init__.py | 4 ++ esphome/components/logger/logger.cpp | 16 +++--- esphome/components/logger/logger.h | 5 +- esphome/components/spi/spi.cpp | 3 +- 12 files changed, 146 insertions(+), 11 deletions(-) create mode 100644 esphome/components/esp32/gpio_esp32_c2.py create mode 100644 esphome/components/esp32/gpio_esp32_c6.py diff --git a/esphome/components/adc/__init__.py b/esphome/components/adc/__init__.py index 99dad68501..015d6edd21 100644 --- a/esphome/components/adc/__init__.py +++ b/esphome/components/adc/__init__.py @@ -7,7 +7,9 @@ from esphome.core import CORE from esphome.components.esp32 import get_esp32_variant from esphome.components.esp32.const import ( VARIANT_ESP32, + VARIANT_ESP32C2, VARIANT_ESP32C3, + VARIANT_ESP32C6, VARIANT_ESP32H2, VARIANT_ESP32S2, VARIANT_ESP32S3, @@ -70,6 +72,22 @@ ESP32_VARIANT_ADC1_PIN_TO_CHANNEL = { 3: adc1_channel_t.ADC1_CHANNEL_3, 4: adc1_channel_t.ADC1_CHANNEL_4, }, + VARIANT_ESP32C2: { + 0: adc1_channel_t.ADC1_CHANNEL_0, + 1: adc1_channel_t.ADC1_CHANNEL_1, + 2: adc1_channel_t.ADC1_CHANNEL_2, + 3: adc1_channel_t.ADC1_CHANNEL_3, + 4: adc1_channel_t.ADC1_CHANNEL_4, + }, + VARIANT_ESP32C6: { + 0: adc1_channel_t.ADC1_CHANNEL_0, + 1: adc1_channel_t.ADC1_CHANNEL_1, + 2: adc1_channel_t.ADC1_CHANNEL_2, + 3: adc1_channel_t.ADC1_CHANNEL_3, + 4: adc1_channel_t.ADC1_CHANNEL_4, + 5: adc1_channel_t.ADC1_CHANNEL_5, + 6: adc1_channel_t.ADC1_CHANNEL_6, + }, VARIANT_ESP32H2: { 0: adc1_channel_t.ADC1_CHANNEL_0, 1: adc1_channel_t.ADC1_CHANNEL_1, diff --git a/esphome/components/deep_sleep/__init__.py b/esphome/components/deep_sleep/__init__.py index bbd10d58c5..6e71f7bbf6 100644 --- a/esphome/components/deep_sleep/__init__.py +++ b/esphome/components/deep_sleep/__init__.py @@ -22,6 +22,8 @@ from esphome.components.esp32.const import ( VARIANT_ESP32C3, VARIANT_ESP32S2, VARIANT_ESP32S3, + VARIANT_ESP32C2, + VARIANT_ESP32C6, ) WAKEUP_PINS = { @@ -94,6 +96,8 @@ WAKEUP_PINS = { 20, 21, ], + VARIANT_ESP32C2: [0, 1, 2, 3, 4, 5], + VARIANT_ESP32C6: [0, 1, 2, 3, 4, 5, 6, 7], } diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index aa9f8cd66e..d158528066 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -44,7 +44,6 @@ from .const import ( # noqa KEY_SDKCONFIG_OPTIONS, KEY_SUBMODULES, KEY_VARIANT, - VARIANT_ESP32C3, VARIANT_FRIENDLY, VARIANTS, ) diff --git a/esphome/components/esp32/const.py b/esphome/components/esp32/const.py index 698310dacb..9e997bdeb5 100644 --- a/esphome/components/esp32/const.py +++ b/esphome/components/esp32/const.py @@ -14,13 +14,17 @@ KEY_SUBMODULES = "submodules" VARIANT_ESP32 = "ESP32" VARIANT_ESP32S2 = "ESP32S2" VARIANT_ESP32S3 = "ESP32S3" +VARIANT_ESP32C2 = "ESP32C2" VARIANT_ESP32C3 = "ESP32C3" +VARIANT_ESP32C6 = "ESP32C6" VARIANT_ESP32H2 = "ESP32H2" VARIANTS = [ VARIANT_ESP32, VARIANT_ESP32S2, VARIANT_ESP32S3, + VARIANT_ESP32C2, VARIANT_ESP32C3, + VARIANT_ESP32C6, VARIANT_ESP32H2, ] @@ -28,7 +32,9 @@ VARIANT_FRIENDLY = { VARIANT_ESP32: "ESP32", VARIANT_ESP32S2: "ESP32-S2", VARIANT_ESP32S3: "ESP32-S3", + VARIANT_ESP32C2: "ESP32-C2", VARIANT_ESP32C3: "ESP32-C3", + VARIANT_ESP32C6: "ESP32-C6", VARIANT_ESP32H2: "ESP32-H2", } diff --git a/esphome/components/esp32/gpio.py b/esphome/components/esp32/gpio.py index 7848d1d552..6950cd58a0 100644 --- a/esphome/components/esp32/gpio.py +++ b/esphome/components/esp32/gpio.py @@ -26,6 +26,8 @@ from .const import ( VARIANT_ESP32C3, VARIANT_ESP32S2, VARIANT_ESP32S3, + VARIANT_ESP32C2, + VARIANT_ESP32C6, VARIANT_ESP32H2, esp32_ns, ) @@ -35,6 +37,8 @@ from .gpio_esp32 import esp32_validate_gpio_pin, esp32_validate_supports from .gpio_esp32_s2 import esp32_s2_validate_gpio_pin, esp32_s2_validate_supports from .gpio_esp32_c3 import esp32_c3_validate_gpio_pin, esp32_c3_validate_supports from .gpio_esp32_s3 import esp32_s3_validate_gpio_pin, esp32_s3_validate_supports +from .gpio_esp32_c2 import esp32_c2_validate_gpio_pin, esp32_c2_validate_supports +from .gpio_esp32_c6 import esp32_c6_validate_gpio_pin, esp32_c6_validate_supports from .gpio_esp32_h2 import esp32_h2_validate_gpio_pin, esp32_h2_validate_supports @@ -95,6 +99,14 @@ _esp32_validations = { pin_validation=esp32_s3_validate_gpio_pin, usage_validation=esp32_s3_validate_supports, ), + VARIANT_ESP32C2: ESP32ValidationFunctions( + pin_validation=esp32_c2_validate_gpio_pin, + usage_validation=esp32_c2_validate_supports, + ), + VARIANT_ESP32C6: ESP32ValidationFunctions( + pin_validation=esp32_c6_validate_gpio_pin, + usage_validation=esp32_c6_validate_supports, + ), VARIANT_ESP32H2: ESP32ValidationFunctions( pin_validation=esp32_h2_validate_gpio_pin, usage_validation=esp32_h2_validate_supports, diff --git a/esphome/components/esp32/gpio_esp32_c2.py b/esphome/components/esp32/gpio_esp32_c2.py new file mode 100644 index 0000000000..c444f804a3 --- /dev/null +++ b/esphome/components/esp32/gpio_esp32_c2.py @@ -0,0 +1,37 @@ +import logging + +from esphome.const import CONF_INPUT, CONF_MODE, CONF_NUMBER + +import esphome.config_validation as cv + +_ESP32C2_STRAPPING_PINS = {8, 9} + +_LOGGER = logging.getLogger(__name__) + + +def esp32_c2_validate_gpio_pin(value): + if value < 0 or value > 20: + raise cv.Invalid(f"Invalid pin number: {value} (must be 0-20)") + if value in _ESP32C2_STRAPPING_PINS: + _LOGGER.warning( + "GPIO%d is a Strapping PIN and should be avoided.\n" + "Attaching external pullup/down resistors to strapping pins can cause unexpected failures.\n" + "See https://esphome.io/guides/faq.html#why-am-i-getting-a-warning-about-strapping-pins", + value, + ) + + return value + + +def esp32_c2_validate_supports(value): + num = value[CONF_NUMBER] + mode = value[CONF_MODE] + is_input = mode[CONF_INPUT] + + if num < 0 or num > 20: + raise cv.Invalid(f"Invalid pin number: {value} (must be 0-20)") + + if is_input: + # All ESP32 pins support input mode + pass + return value diff --git a/esphome/components/esp32/gpio_esp32_c6.py b/esphome/components/esp32/gpio_esp32_c6.py new file mode 100644 index 0000000000..b26b6bc6b4 --- /dev/null +++ b/esphome/components/esp32/gpio_esp32_c6.py @@ -0,0 +1,50 @@ +import logging + +from esphome.const import CONF_INPUT, CONF_MODE, CONF_NUMBER + +import esphome.config_validation as cv + +_ESP32C6_SPI_PSRAM_PINS = { + 24: "SPICS0", + 25: "SPIQ", + 26: "SPIWP", + 27: "VDD_SPI", + 28: "SPIHD", + 29: "SPICLK", + 30: "SPID", +} + +_ESP32C6_STRAPPING_PINS = {8, 9, 15} + +_LOGGER = logging.getLogger(__name__) + + +def esp32_c6_validate_gpio_pin(value): + 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: + 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_STRAPPING_PINS: + _LOGGER.warning( + "GPIO%d is a Strapping PIN and should be avoided.\n" + "Attaching external pullup/down resistors to strapping pins can cause unexpected failures.\n" + "See https://esphome.io/guides/faq.html#why-am-i-getting-a-warning-about-strapping-pins", + value, + ) + + return value + + +def esp32_c6_validate_supports(value): + num = value[CONF_NUMBER] + mode = value[CONF_MODE] + is_input = mode[CONF_INPUT] + + if num < 0 or num > 23: + raise cv.Invalid(f"Invalid pin number: {value} (must be 0-23)") + if is_input: + # All ESP32 pins support input mode + pass + return value diff --git a/esphome/components/esp32_rmt_led_strip/light.py b/esphome/components/esp32_rmt_led_strip/light.py index 3ca758c1e1..5b65ecdabf 100644 --- a/esphome/components/esp32_rmt_led_strip/light.py +++ b/esphome/components/esp32_rmt_led_strip/light.py @@ -63,6 +63,7 @@ RMT_CHANNELS = { esp32.const.VARIANT_ESP32S2: [0, 1, 2, 3], esp32.const.VARIANT_ESP32S3: [0, 1, 2, 3], esp32.const.VARIANT_ESP32C3: [0, 1], + esp32.const.VARIANT_ESP32C6: [0, 1], } diff --git a/esphome/components/logger/__init__.py b/esphome/components/logger/__init__.py index af96b03c8e..5c87bb9d91 100644 --- a/esphome/components/logger/__init__.py +++ b/esphome/components/logger/__init__.py @@ -28,6 +28,8 @@ from esphome.components.esp32.const import ( VARIANT_ESP32S2, VARIANT_ESP32C3, VARIANT_ESP32S3, + VARIANT_ESP32C2, + VARIANT_ESP32C6, ) CODEOWNERS = ["@esphome/core"] @@ -74,6 +76,8 @@ UART_SELECTION_ESP32 = { VARIANT_ESP32S2: [UART0, UART1, USB_CDC], VARIANT_ESP32S3: [UART0, UART1, USB_CDC, USB_SERIAL_JTAG], VARIANT_ESP32C3: [UART0, UART1, USB_SERIAL_JTAG], + VARIANT_ESP32C2: [UART0, UART1], + VARIANT_ESP32C6: [UART0, UART1, USB_CDC, USB_SERIAL_JTAG], } UART_SELECTION_ESP8266 = [UART0, UART0_SWAP, UART1] diff --git a/esphome/components/logger/logger.cpp b/esphome/components/logger/logger.cpp index ca4cc64007..86ebb53764 100644 --- a/esphome/components/logger/logger.cpp +++ b/esphome/components/logger/logger.cpp @@ -120,7 +120,7 @@ void HOT Logger::log_message_(int level, const char *tag, int offset) { if ( #if defined(USE_ESP32_VARIANT_ESP32S2) uart_ == UART_SELECTION_USB_CDC -#elif defined(USE_ESP32_VARIANT_ESP32C3) +#elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) uart_ == UART_SELECTION_USB_SERIAL_JTAG #elif defined(USE_ESP32_VARIANT_ESP32S3) uart_ == UART_SELECTION_USB_CDC || uart_ == UART_SELECTION_USB_SERIAL_JTAG @@ -191,8 +191,8 @@ void Logger::pre_setup() { Serial1.setDebugOutput(ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE); #endif break; -#if defined(USE_ESP32) && !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32S2) && \ - !defined(USE_ESP32_VARIANT_ESP32S3) +#if defined(USE_ESP32) && !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32C6) && \ + !defined(USE_ESP32_VARIANT_ESP32S2) && !defined(USE_ESP32_VARIANT_ESP32S3) case UART_SELECTION_UART2: this->hw_serial_ = &Serial2; Serial2.begin(this->baud_rate_); @@ -215,7 +215,8 @@ void Logger::pre_setup() { case UART_SELECTION_UART1: uart_num_ = UART_NUM_1; break; -#if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32S2) && !defined(USE_ESP32_VARIANT_ESP32S3) +#if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32C6) && \ + !defined(USE_ESP32_VARIANT_ESP32S2) && !defined(USE_ESP32_VARIANT_ESP32S3) case UART_SELECTION_UART2: uart_num_ = UART_NUM_2; break; @@ -225,11 +226,11 @@ void Logger::pre_setup() { uart_num_ = -1; break; #endif // USE_ESP32_VARIANT_ESP32S2 || USE_ESP32_VARIANT_ESP32S3 -#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S3) +#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S3) case UART_SELECTION_USB_SERIAL_JTAG: uart_num_ = -1; break; -#endif // USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32S3 +#endif // USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C6 || USE_ESP32_VARIANT_ESP32S3 } if (uart_num_ >= 0) { uart_config_t uart_config{}; @@ -278,7 +279,8 @@ const char *const LOG_LEVELS[] = {"NONE", "ERROR", "WARN", "INFO", "CONFIG", "DE #ifdef USE_ESP32 const char *const UART_SELECTIONS[] = { "UART0", "UART1", -#if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32S2) && !defined(USE_ESP32_VARIANT_ESP32S3) +#if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32C6) && \ + !defined(USE_ESP32_VARIANT_ESP32S2) && !defined(USE_ESP32_VARIANT_ESP32S3) "UART2", #endif // !USE_ESP32_VARIANT_ESP32C3 && !USE_ESP32_VARIANT_ESP32S2 && !USE_ESP32_VARIANT_ESP32S3 #if defined(USE_ESP_IDF) diff --git a/esphome/components/logger/logger.h b/esphome/components/logger/logger.h index 54a5236cd8..47cde45c29 100644 --- a/esphome/components/logger/logger.h +++ b/esphome/components/logger/logger.h @@ -34,14 +34,15 @@ enum UARTSelection { UART_SELECTION_UART0 = 0, UART_SELECTION_UART1, #if defined(USE_ESP32) -#if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32S2) && !defined(USE_ESP32_VARIANT_ESP32S3) +#if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32C6) && \ + !defined(USE_ESP32_VARIANT_ESP32S2) && !defined(USE_ESP32_VARIANT_ESP32S3) UART_SELECTION_UART2, #endif // !USE_ESP32_VARIANT_ESP32C3 && !USE_ESP32_VARIANT_ESP32S2 && !USE_ESP32_VARIANT_ESP32S3 #ifdef USE_ESP_IDF #if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) UART_SELECTION_USB_CDC, #endif // USE_ESP32_VARIANT_ESP32S2 || USE_ESP32_VARIANT_ESP32S3 -#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S3) +#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S3) UART_SELECTION_USB_SERIAL_JTAG, #endif // USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32S3 #endif // USE_ESP_IDF diff --git a/esphome/components/spi/spi.cpp b/esphome/components/spi/spi.cpp index c9bb075fb5..33630897f6 100644 --- a/esphome/components/spi/spi.cpp +++ b/esphome/components/spi/spi.cpp @@ -76,7 +76,8 @@ void SPIComponent::setup() { if (spi_bus_num == 0) { this->hw_spi_ = &SPI; } else { -#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) +#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) || \ + defined(USE_ESP32_VARIANT_ESP32C2) || defined(USE_ESP32_VARIANT_ESP32C6) this->hw_spi_ = new SPIClass(FSPI); // NOLINT(cppcoreguidelines-owning-memory) #else this->hw_spi_ = new SPIClass(HSPI); // NOLINT(cppcoreguidelines-owning-memory) From da8afd36b26a23eed3d1863b4f94fcdad40366ea Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 21 Aug 2023 12:16:14 +1200 Subject: [PATCH 0089/2101] Change htu21d sensors from required to optional (#5285) --- esphome/components/htu21d/sensor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/htu21d/sensor.py b/esphome/components/htu21d/sensor.py index 37422f0329..2ed318f1c9 100644 --- a/esphome/components/htu21d/sensor.py +++ b/esphome/components/htu21d/sensor.py @@ -23,13 +23,13 @@ CONFIG_SCHEMA = ( cv.Schema( { cv.GenerateID(): cv.declare_id(HTU21DComponent), - cv.Required(CONF_TEMPERATURE): sensor.sensor_schema( + 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.Required(CONF_HUMIDITY): sensor.sensor_schema( + cv.Optional(CONF_HUMIDITY): sensor.sensor_schema( unit_of_measurement=UNIT_PERCENT, accuracy_decimals=1, device_class=DEVICE_CLASS_HUMIDITY, From 03ab23fec8c66680c38b1286b26c25f7805fd7e4 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Mon, 21 Aug 2023 10:17:22 +1000 Subject: [PATCH 0090/2101] Reserve keyword "clock" (#5279) --- esphome/config_validation.py | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/config_validation.py b/esphome/config_validation.py index cf0b1d3aca..3720757828 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -125,6 +125,7 @@ RESERVED_IDS = [ "char16_t", "char32_t", "class", + "clock", "compl", "concept", "const", From 04433103853f0430e1e73a0817661f729bdd2792 Mon Sep 17 00:00:00 2001 From: Rob Deutsch Date: Mon, 21 Aug 2023 10:20:00 +1000 Subject: [PATCH 0091/2101] Bump arduino-heatpumpir to v1.0.23 (#5269) --- esphome/components/heatpumpir/climate.py | 3 ++- esphome/components/heatpumpir/heatpumpir.cpp | 1 + esphome/components/heatpumpir/heatpumpir.h | 1 + platformio.ini | 2 +- tests/test1.yaml | 7 +++++++ 5 files changed, 12 insertions(+), 2 deletions(-) diff --git a/esphome/components/heatpumpir/climate.py b/esphome/components/heatpumpir/climate.py index cc8e75dcbd..a043b4a61b 100644 --- a/esphome/components/heatpumpir/climate.py +++ b/esphome/components/heatpumpir/climate.py @@ -33,6 +33,7 @@ PROTOCOLS = { "greeya": Protocol.PROTOCOL_GREEYAA, "greeyan": Protocol.PROTOCOL_GREEYAN, "greeyac": Protocol.PROTOCOL_GREEYAC, + "greeyt": Protocol.PROTOCOL_GREEYT, "hisense_aud": Protocol.PROTOCOL_HISENSE_AUD, "hitachi": Protocol.PROTOCOL_HITACHI, "hyundai": Protocol.PROTOCOL_HYUNDAI, @@ -115,7 +116,7 @@ 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.20") + cg.add_library("tonia/HeatpumpIR", "1.0.23") if CORE.is_esp8266 or CORE.is_esp32: cg.add_library("crankyoldgit/IRremoteESP8266", "2.7.12") diff --git a/esphome/components/heatpumpir/heatpumpir.cpp b/esphome/components/heatpumpir/heatpumpir.cpp index bed1dc76c0..5e7237b63c 100644 --- a/esphome/components/heatpumpir/heatpumpir.cpp +++ b/esphome/components/heatpumpir/heatpumpir.cpp @@ -27,6 +27,7 @@ const std::map> PROTOCOL_CONSTRUCTOR_MAP {PROTOCOL_GREEYAA, []() { return new GreeYAAHeatpumpIR(); }}, // NOLINT {PROTOCOL_GREEYAN, []() { return new GreeYANHeatpumpIR(); }}, // NOLINT {PROTOCOL_GREEYAC, []() { return new GreeYACHeatpumpIR(); }}, // NOLINT + {PROTOCOL_GREEYT, []() { return new GreeYTHeatpumpIR(); }}, // NOLINT {PROTOCOL_HISENSE_AUD, []() { return new HisenseHeatpumpIR(); }}, // NOLINT {PROTOCOL_HITACHI, []() { return new HitachiHeatpumpIR(); }}, // NOLINT {PROTOCOL_HYUNDAI, []() { return new HyundaiHeatpumpIR(); }}, // NOLINT diff --git a/esphome/components/heatpumpir/heatpumpir.h b/esphome/components/heatpumpir/heatpumpir.h index c60b944111..e8b03b4c26 100644 --- a/esphome/components/heatpumpir/heatpumpir.h +++ b/esphome/components/heatpumpir/heatpumpir.h @@ -27,6 +27,7 @@ enum Protocol { PROTOCOL_GREEYAA, PROTOCOL_GREEYAN, PROTOCOL_GREEYAC, + PROTOCOL_GREEYT, PROTOCOL_HISENSE_AUD, PROTOCOL_HITACHI, PROTOCOL_HYUNDAI, diff --git a/platformio.ini b/platformio.ini index 5da3b9f978..6341d7bde5 100644 --- a/platformio.ini +++ b/platformio.ini @@ -64,7 +64,7 @@ lib_deps = glmnet/Dsmr@0.7 ; dsmr rweather/Crypto@0.4.0 ; dsmr dudanov/MideaUART@1.1.8 ; midea - tonia/HeatpumpIR@1.0.20 ; heatpumpir + tonia/HeatpumpIR@1.0.23 ; heatpumpir build_flags = ${common.build_flags} -DUSE_ARDUINO diff --git a/tests/test1.yaml b/tests/test1.yaml index 80cd9e3987..3a6cfa0c4b 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -2299,6 +2299,13 @@ climate: name: HeatpumpIR Climate min_temperature: 18 max_temperature: 30 + - platform: heatpumpir + protocol: greeyt + horizontal_default: left + vertical_default: up + name: HeatpumpIR Climate + min_temperature: 18 + max_temperature: 30 - platform: midea_ir name: Midea IR use_fahrenheit: true From 5e19a3b892b4580cf5c9457dc227da483892e78e Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 18 Aug 2023 19:13:46 +1200 Subject: [PATCH 0092/2101] Move libcairo to all architectures in docker (#5276) --- docker/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 4aaea9da89..b942b650cb 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -28,14 +28,14 @@ RUN \ git=1:2.30.2-1+deb11u2 \ curl=7.74.0-1.3+deb11u7 \ openssh-client=1:8.4p1-5+deb11u1 \ - python3-cffi=1.14.5-1; \ + python3-cffi=1.14.5-1 \ + libcairo2=1.16.0-5; \ if [ "$TARGETARCH$TARGETVARIANT" = "armv7" ]; then \ apt-get install -y --no-install-recommends \ build-essential=12.9 \ python3-dev=3.9.2-3 \ zlib1g-dev=1:1.2.11.dfsg-2+deb11u2 \ libjpeg-dev=1:2.0.6-4 \ - libcairo2=1.16.0-5 \ libfreetype-dev=2.10.4+dfsg-1+deb11u1; \ fi; \ rm -rf \ From e600784ebfed1ff2a64e28d6a1bb3979915c3d90 Mon Sep 17 00:00:00 2001 From: mwolter805 <24851651+mwolter805@users.noreply.github.com> Date: Sun, 20 Aug 2023 12:15:45 -0700 Subject: [PATCH 0093/2101] Resolve offline ESPs in dashboard when using ESPHOME_DASHBOARD_USE_PING=true (#5281) --- esphome/dashboard/dashboard.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/esphome/dashboard/dashboard.py b/esphome/dashboard/dashboard.py index b33cb2df5e..eae004fa09 100644 --- a/esphome/dashboard/dashboard.py +++ b/esphome/dashboard/dashboard.py @@ -868,9 +868,6 @@ class PingStatusThread(threading.Thread): entries = _list_dashboard_entries() queue = collections.deque() for entry in entries: - if entry.no_mdns is True: - continue - if entry.address is None: PING_RESULT[entry.filename] = None continue From 02a71cb6a758e25a5587b587e205203df372150f Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Mon, 21 Aug 2023 06:57:02 +1000 Subject: [PATCH 0094/2101] Align SPI data rates in C++ code with Python (#5284) --- esphome/components/spi/__init__.py | 2 ++ esphome/components/spi/spi.h | 1 + 2 files changed, 3 insertions(+) diff --git a/esphome/components/spi/__init__.py b/esphome/components/spi/__init__.py index 1528a05734..57a4fa9f4e 100644 --- a/esphome/components/spi/__init__.py +++ b/esphome/components/spi/__init__.py @@ -23,7 +23,9 @@ SPI_DATA_RATE_OPTIONS = { 40e6: SPIDataRate.DATA_RATE_40MHZ, 20e6: SPIDataRate.DATA_RATE_20MHZ, 10e6: SPIDataRate.DATA_RATE_10MHZ, + 8e6: SPIDataRate.DATA_RATE_8MHZ, 5e6: SPIDataRate.DATA_RATE_5MHZ, + 4e6: SPIDataRate.DATA_RATE_4MHZ, 2e6: SPIDataRate.DATA_RATE_2MHZ, 1e6: SPIDataRate.DATA_RATE_1MHZ, 2e5: SPIDataRate.DATA_RATE_200KHZ, diff --git a/esphome/components/spi/spi.h b/esphome/components/spi/spi.h index f19518caae..159d117533 100644 --- a/esphome/components/spi/spi.h +++ b/esphome/components/spi/spi.h @@ -63,6 +63,7 @@ enum SPIDataRate : uint32_t { DATA_RATE_1MHZ = 1000000, DATA_RATE_2MHZ = 2000000, DATA_RATE_4MHZ = 4000000, + DATA_RATE_5MHZ = 5000000, DATA_RATE_8MHZ = 8000000, DATA_RATE_10MHZ = 10000000, DATA_RATE_20MHZ = 20000000, From e44a60e8141c90cbff263bdb0c3c6e6a7027fc22 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 21 Aug 2023 12:16:14 +1200 Subject: [PATCH 0095/2101] Change htu21d sensors from required to optional (#5285) --- esphome/components/htu21d/sensor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/htu21d/sensor.py b/esphome/components/htu21d/sensor.py index 37422f0329..2ed318f1c9 100644 --- a/esphome/components/htu21d/sensor.py +++ b/esphome/components/htu21d/sensor.py @@ -23,13 +23,13 @@ CONFIG_SCHEMA = ( cv.Schema( { cv.GenerateID(): cv.declare_id(HTU21DComponent), - cv.Required(CONF_TEMPERATURE): sensor.sensor_schema( + 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.Required(CONF_HUMIDITY): sensor.sensor_schema( + cv.Optional(CONF_HUMIDITY): sensor.sensor_schema( unit_of_measurement=UNIT_PERCENT, accuracy_decimals=1, device_class=DEVICE_CLASS_HUMIDITY, From d2bccbe8ac0d0ca62024f1faa7d22d7ae47907f5 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Mon, 21 Aug 2023 10:17:22 +1000 Subject: [PATCH 0096/2101] Reserve keyword "clock" (#5279) --- esphome/config_validation.py | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/config_validation.py b/esphome/config_validation.py index cf0b1d3aca..3720757828 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -125,6 +125,7 @@ RESERVED_IDS = [ "char16_t", "char32_t", "class", + "clock", "compl", "concept", "const", From 9fb8e9edef1ee65bf9b615ab69a5f61bcf2c4815 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 21 Aug 2023 12:33:49 +1200 Subject: [PATCH 0097/2101] Bump version to 2023.8.2 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index b8c910cd9e..c22dde6986 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2023.8.1" +__version__ = "2023.8.2" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 2a48b810a4bed9853b899d5fa7e7efaf6f76ef2d Mon Sep 17 00:00:00 2001 From: Stefan Rado Date: Mon, 21 Aug 2023 02:35:13 +0200 Subject: [PATCH 0098/2101] Fix equality check when setting current-based cover position (#5167) --- esphome/components/current_based/current_based_cover.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/current_based/current_based_cover.cpp b/esphome/components/current_based/current_based_cover.cpp index ff5ad43997..17f67002a3 100644 --- a/esphome/components/current_based/current_based_cover.cpp +++ b/esphome/components/current_based/current_based_cover.cpp @@ -38,7 +38,7 @@ void CurrentBasedCover::control(const CoverCall &call) { } if (call.get_position().has_value()) { auto pos = *call.get_position(); - if (pos == this->position) { + if (fabsf(this->position - pos) < 0.01) { // already at target } else { auto op = pos < this->position ? COVER_OPERATION_CLOSING : COVER_OPERATION_OPENING; From f814b6d47c6de9cef53b374c65e3671d2e10a879 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Aug 2023 04:27:17 +0000 Subject: [PATCH 0099/2101] Bump platformio from 6.1.9 to 6.1.10 (#5237) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- docker/Dockerfile | 2 +- requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index b942b650cb..a590445de9 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -61,7 +61,7 @@ RUN \ # Ubuntu python3-pip is missing wheel pip3 install --no-cache-dir \ wheel==0.37.1 \ - platformio==6.1.7 \ + platformio==6.1.10 \ # Change some platformio settings && platformio settings set enable_telemetry No \ && platformio settings set check_platformio_interval 1000000 \ diff --git a/requirements.txt b/requirements.txt index 4a046014d6..dccb418e8d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,7 +6,7 @@ tornado==6.3.2 tzlocal==5.0.1 # from time tzdata>=2021.1 # from time pyserial==3.5 -platformio==6.1.9 # When updating platformio, also update Dockerfile +platformio==6.1.10 # When updating platformio, also update Dockerfile esptool==4.6.2 click==8.1.7 esphome-dashboard==20230711.0 From 11ed2d5f1830a475dc7325f4c2e678b316bd14af Mon Sep 17 00:00:00 2001 From: Christian Date: Tue, 22 Aug 2023 23:13:38 +0100 Subject: [PATCH 0100/2101] Add Invert method for SSD1306 (#5292) --- esphome/components/ssd1306_base/ssd1306_base.cpp | 8 +++++++- esphome/components/ssd1306_base/ssd1306_base.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/esphome/components/ssd1306_base/ssd1306_base.cpp b/esphome/components/ssd1306_base/ssd1306_base.cpp index 730e1c8f35..3cacd473d1 100644 --- a/esphome/components/ssd1306_base/ssd1306_base.cpp +++ b/esphome/components/ssd1306_base/ssd1306_base.cpp @@ -132,7 +132,7 @@ void SSD1306::setup() { this->command(SSD1306_COMMAND_DISPLAY_ALL_ON_RESUME); // Inverse display mode (0xA6, 0xA7) - this->command(SSD1306_COMMAND_NORMAL_DISPLAY | this->invert_); + this->set_invert(this->invert_); // Disable scrolling mode (0x2E) this->command(SSD1306_COMMAND_DEACTIVATE_SCROLL); @@ -190,6 +190,12 @@ void SSD1306::update() { this->do_update_(); this->display(); } + +void SSD1306::set_invert(bool invert) { + this->invert_ = invert; + // Inverse display mode (0xA6, 0xA7) + this->command(SSD1306_COMMAND_NORMAL_DISPLAY | this->invert_); +} void SSD1306::set_contrast(float contrast) { // validation this->contrast_ = clamp(contrast, 0.0F, 1.0F); diff --git a/esphome/components/ssd1306_base/ssd1306_base.h b/esphome/components/ssd1306_base/ssd1306_base.h index 7402ae3af2..4b0e9bb80e 100644 --- a/esphome/components/ssd1306_base/ssd1306_base.h +++ b/esphome/components/ssd1306_base/ssd1306_base.h @@ -43,6 +43,7 @@ class SSD1306 : public PollingComponent, public display::DisplayBuffer { void init_offset_x(uint8_t offset_x) { this->offset_x_ = offset_x; } void init_offset_y(uint8_t offset_y) { this->offset_y_ = offset_y; } void init_invert(bool invert) { this->invert_ = invert; } + void set_invert(bool invert); bool is_on(); void turn_on(); void turn_off(); From b20bae23ccac3903239ca68bfb3a4add25b7b44d Mon Sep 17 00:00:00 2001 From: Sebastian Rasor <92653912+sebastianrasor@users.noreply.github.com> Date: Tue, 22 Aug 2023 20:01:34 -0500 Subject: [PATCH 0101/2101] Introduce cv.temperature_delta and fix problematic thermostat configuration behavior (#5297) --- esphome/components/thermostat/climate.py | 14 +++++++------- esphome/config_validation.py | 21 +++++++++++++++++++++ 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/esphome/components/thermostat/climate.py b/esphome/components/thermostat/climate.py index 9a57f6a337..cca46609db 100644 --- a/esphome/components/thermostat/climate.py +++ b/esphome/components/thermostat/climate.py @@ -591,11 +591,11 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_DEFAULT_TARGET_TEMPERATURE_LOW): cv.temperature, cv.Optional( CONF_SET_POINT_MINIMUM_DIFFERENTIAL, default=0.5 - ): cv.temperature, - cv.Optional(CONF_COOL_DEADBAND, default=0.5): cv.temperature, - cv.Optional(CONF_COOL_OVERRUN, default=0.5): cv.temperature, - cv.Optional(CONF_HEAT_DEADBAND, default=0.5): cv.temperature, - cv.Optional(CONF_HEAT_OVERRUN, default=0.5): cv.temperature, + ): cv.temperature_delta, + cv.Optional(CONF_COOL_DEADBAND, default=0.5): cv.temperature_delta, + cv.Optional(CONF_COOL_OVERRUN, default=0.5): cv.temperature_delta, + cv.Optional(CONF_HEAT_DEADBAND, default=0.5): cv.temperature_delta, + cv.Optional(CONF_HEAT_OVERRUN, default=0.5): cv.temperature_delta, cv.Optional(CONF_MAX_COOLING_RUN_TIME): cv.positive_time_period_seconds, cv.Optional(CONF_MAX_HEATING_RUN_TIME): cv.positive_time_period_seconds, cv.Optional(CONF_MIN_COOLING_OFF_TIME): cv.positive_time_period_seconds, @@ -608,8 +608,8 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_MIN_HEATING_OFF_TIME): cv.positive_time_period_seconds, cv.Optional(CONF_MIN_HEATING_RUN_TIME): cv.positive_time_period_seconds, cv.Required(CONF_MIN_IDLE_TIME): cv.positive_time_period_seconds, - cv.Optional(CONF_SUPPLEMENTAL_COOLING_DELTA): cv.temperature, - cv.Optional(CONF_SUPPLEMENTAL_HEATING_DELTA): cv.temperature, + cv.Optional(CONF_SUPPLEMENTAL_COOLING_DELTA): cv.temperature_delta, + cv.Optional(CONF_SUPPLEMENTAL_HEATING_DELTA): cv.temperature_delta, cv.Optional( CONF_FAN_ONLY_ACTION_USES_FAN_MODE_TIMER, default=False ): cv.boolean, diff --git a/esphome/config_validation.py b/esphome/config_validation.py index 3720757828..ed87e98078 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -929,6 +929,27 @@ def temperature(value): raise err +def temperature_delta(value): + err = None + try: + return _temperature_c(value) + except Invalid as orig_err: + err = orig_err + + try: + return _temperature_k(value) + except Invalid: + pass + + try: + fahrenheit = _temperature_f(value) + return fahrenheit * (5 / 9) + except Invalid: + pass + + raise err + + _color_temperature_mireds = float_with_unit("Color Temperature", r"(mireds|Mireds)") _color_temperature_kelvin = float_with_unit("Color Temperature", r"(K|Kelvin)") From c4adb30ab2b355a28c6977088a68c59d95ea1c5e Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Tue, 29 Aug 2023 00:11:58 -0500 Subject: [PATCH 0102/2101] Update PSRAM config params for IDF4+ (#5298) --- esphome/components/psram/__init__.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/esphome/components/psram/__init__.py b/esphome/components/psram/__init__.py index ac6d034514..9399e51ded 100644 --- a/esphome/components/psram/__init__.py +++ b/esphome/components/psram/__init__.py @@ -1,6 +1,6 @@ import esphome.codegen as cg import esphome.config_validation as cv -from esphome.components.esp32 import add_idf_sdkconfig_option +from esphome.components.esp32 import add_idf_sdkconfig_option, get_esp32_variant from esphome.core import CORE from esphome.const import ( CONF_ID, @@ -21,7 +21,11 @@ async def to_code(config): cg.add_build_flag("-DBOARD_HAS_PSRAM") if CORE.using_esp_idf: - add_idf_sdkconfig_option("CONFIG_ESP32_SPIRAM_SUPPORT", True) + add_idf_sdkconfig_option( + f"CONFIG_{get_esp32_variant().upper()}_SPIRAM_SUPPORT", True + ) + add_idf_sdkconfig_option("CONFIG_SPIRAM", True) + add_idf_sdkconfig_option("CONFIG_SPIRAM_USE", True) add_idf_sdkconfig_option("CONFIG_SPIRAM_USE_CAPS_ALLOC", True) add_idf_sdkconfig_option("CONFIG_SPIRAM_IGNORE_NOTFOUND", True) From 45879e3100c27c49ff103e70e9e4d12a8cdac713 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 29 Aug 2023 00:25:43 -0500 Subject: [PATCH 0103/2101] Fix legacy zeroconf record update method (#5294) --- esphome/zeroconf.py | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/esphome/zeroconf.py b/esphome/zeroconf.py index b0dddfd152..924d7253df 100644 --- a/esphome/zeroconf.py +++ b/esphome/zeroconf.py @@ -1,19 +1,19 @@ +import logging import socket import threading import time -from typing import Optional -import logging from dataclasses import dataclass +from typing import Optional from zeroconf import ( DNSAddress, DNSOutgoing, - DNSRecord, DNSQuestion, + RecordUpdate, RecordUpdateListener, - Zeroconf, ServiceBrowser, ServiceStateChange, + Zeroconf, current_time_millis, ) @@ -24,17 +24,28 @@ _LOGGER = logging.getLogger(__name__) class HostResolver(RecordUpdateListener): + """Resolve a host name to an IP address.""" + def __init__(self, name: str): self.name = name self.address: Optional[bytes] = None - def update_record(self, zc: Zeroconf, now: float, record: DNSRecord) -> None: - if record is None: - return - if record.type == _TYPE_A: - assert isinstance(record, DNSAddress) - if record.name == self.name: - self.address = record.address + def async_update_records( + self, zc: Zeroconf, now: float, records: list[RecordUpdate] + ) -> None: + """Update multiple records in one shot. + + This will run in zeroconf's event loop thread so it + must be thread-safe. + """ + for record_update in records: + record, _ = record_update + if record is None: + continue + if record.type == _TYPE_A: + assert isinstance(record, DNSAddress) + if record.name == self.name: + self.address = record.address def request(self, zc: Zeroconf, timeout: float) -> bool: now = time.time() From 45152ad55edf0d05500e28d5aaa590889b4c897a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Aug 2023 19:04:37 +1200 Subject: [PATCH 0104/2101] Bump zeroconf from 0.80.0 to 0.86.0 (#5308) 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 dccb418e8d..b23964828c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,7 +11,7 @@ esptool==4.6.2 click==8.1.7 esphome-dashboard==20230711.0 aioesphomeapi==15.0.0 -zeroconf==0.80.0 +zeroconf==0.86.0 # esp-idf requires this, but doesn't bundle it by default # https://github.com/espressif/esp-idf/blob/220590d599e134d7a5e7f1e683cc4550349ffbf8/requirements.txt#L24 From 78cb0986914aa3763058f9f46175782ce4218bf2 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Tue, 29 Aug 2023 03:50:29 -0500 Subject: [PATCH 0105/2101] Add PSRAM mode and speed config (#5312) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/psram/__init__.py | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/esphome/components/psram/__init__.py b/esphome/components/psram/__init__.py index 9399e51ded..f7a2ef7b92 100644 --- a/esphome/components/psram/__init__.py +++ b/esphome/components/psram/__init__.py @@ -4,6 +4,8 @@ from esphome.components.esp32 import add_idf_sdkconfig_option, get_esp32_variant from esphome.core import CORE from esphome.const import ( CONF_ID, + CONF_MODE, + CONF_SPEED, ) CODEOWNERS = ["@esphome/core"] @@ -11,8 +13,26 @@ CODEOWNERS = ["@esphome/core"] psram_ns = cg.esphome_ns.namespace("psram") PsramComponent = psram_ns.class_("PsramComponent", cg.Component) +SPIRAM_MODES = { + "quad": "CONFIG_SPIRAM_MODE_QUAD", + "octal": "CONFIG_SPIRAM_MODE_OCT", +} + +SPIRAM_SPEEDS = { + 40e6: "CONFIG_SPIRAM_SPEED_40M", + 80e6: "CONFIG_SPIRAM_SPEED_80M", + 120e6: "CONFIG_SPIRAM_SPEED_120M", +} + CONFIG_SCHEMA = cv.All( - cv.Schema({cv.GenerateID(): cv.declare_id(PsramComponent)}), cv.only_on_esp32 + cv.Schema( + { + cv.GenerateID(): cv.declare_id(PsramComponent), + cv.Optional(CONF_MODE): cv.enum(SPIRAM_MODES, lower=True), + cv.Optional(CONF_SPEED): cv.All(cv.frequency, cv.one_of(*SPIRAM_SPEEDS)), + } + ), + cv.only_on_esp32, ) @@ -29,5 +49,10 @@ async def to_code(config): add_idf_sdkconfig_option("CONFIG_SPIRAM_USE_CAPS_ALLOC", True) add_idf_sdkconfig_option("CONFIG_SPIRAM_IGNORE_NOTFOUND", True) + if CONF_MODE in config: + add_idf_sdkconfig_option(f"{SPIRAM_MODES[config[CONF_MODE]]}", True) + if CONF_SPEED in config: + add_idf_sdkconfig_option(f"{SPIRAM_SPEEDS[config[CONF_SPEED]]}", True) + var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) From cdb67fc90e974cca8d463b7c466c3ca29225956e Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Thu, 31 Aug 2023 19:12:25 +1000 Subject: [PATCH 0106/2101] Add extra SLPOUT for waking up some ST7789 chips (#5319) --- esphome/components/st7789v/st7789v.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/st7789v/st7789v.cpp b/esphome/components/st7789v/st7789v.cpp index 0e7c9b9123..c1e3f07e38 100644 --- a/esphome/components/st7789v/st7789v.cpp +++ b/esphome/components/st7789v/st7789v.cpp @@ -19,6 +19,7 @@ void ST7789V::setup() { this->write_command_(ST7789_SLPOUT); // Sleep out delay(120); // NOLINT + this->write_command_(ST7789_SLPOUT); // this->write_command_(ST7789_NORON); // Normal display mode on From 01f6791d1c1fc2efd64575784663643f64c5f6bf Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Fri, 1 Sep 2023 09:43:24 +1000 Subject: [PATCH 0107/2101] 7789 controller fixes take 2 (#5320) * Fix 7789 clock mode and increase clock rate. * Reverse change from dev. * Speed up 8 bit color. * Tweak buffer size --- esphome/components/st7789v/st7789v.cpp | 17 +++++++++++++---- esphome/components/st7789v/st7789v.h | 4 ++-- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/esphome/components/st7789v/st7789v.cpp b/esphome/components/st7789v/st7789v.cpp index c1e3f07e38..f29182e634 100644 --- a/esphome/components/st7789v/st7789v.cpp +++ b/esphome/components/st7789v/st7789v.cpp @@ -5,6 +5,7 @@ namespace esphome { namespace st7789v { static const char *const TAG = "st7789v"; +static const size_t TEMP_BUFFER_SIZE = 128; void ST7789V::setup() { ESP_LOGCONFIG(TAG, "Setting up SPI ST7789V..."); @@ -19,7 +20,6 @@ void ST7789V::setup() { this->write_command_(ST7789_SLPOUT); // Sleep out delay(120); // NOLINT - this->write_command_(ST7789_SLPOUT); // this->write_command_(ST7789_NORON); // Normal display mode on @@ -206,15 +206,23 @@ void ST7789V::write_display_data() { this->dc_pin_->digital_write(true); if (this->eightbitcolor_) { + uint8_t temp_buffer[TEMP_BUFFER_SIZE]; + size_t temp_index = 0; for (int line = 0; line < this->get_buffer_length_(); line = line + this->get_width_internal()) { for (int index = 0; index < this->get_width_internal(); ++index) { auto color = display::ColorUtil::color_to_565( display::ColorUtil::to_color(this->buffer_[index + line], display::ColorOrder::COLOR_ORDER_RGB, display::ColorBitness::COLOR_BITNESS_332, true)); - this->write_byte((color >> 8) & 0xff); - this->write_byte(color & 0xff); + temp_buffer[temp_index++] = (uint8_t) (color >> 8); + temp_buffer[temp_index++] = (uint8_t) color; + if (temp_index == TEMP_BUFFER_SIZE) { + this->write_array(temp_buffer, TEMP_BUFFER_SIZE); + temp_index = 0; + } } } + if (temp_index != 0) + this->write_array(temp_buffer, temp_index); } else { this->write_array(this->buffer_, this->get_buffer_length_()); } @@ -229,9 +237,10 @@ void ST7789V::init_reset_() { delay(1); // Trigger Reset this->reset_pin_->digital_write(false); - delay(10); + delay(1); // Wake up this->reset_pin_->digital_write(true); + delay(5); } } diff --git a/esphome/components/st7789v/st7789v.h b/esphome/components/st7789v/st7789v.h index ccbe50cf85..56132e8ea2 100644 --- a/esphome/components/st7789v/st7789v.h +++ b/esphome/components/st7789v/st7789v.h @@ -117,8 +117,8 @@ static const uint8_t ST7789_MADCTL_COLOR_ORDER = ST7789_MADCTL_BGR; class ST7789V : public PollingComponent, public display::DisplayBuffer, - public spi::SPIDevice { + public spi::SPIDevice { public: void set_model(ST7789VModel model); void set_dc_pin(GPIOPin *dc_pin) { this->dc_pin_ = dc_pin; } From 3003485dc63e850c4e8cc4b67c3b87826265ea0b Mon Sep 17 00:00:00 2001 From: luka6000 Date: Fri, 1 Sep 2023 03:20:21 +0200 Subject: [PATCH 0108/2101] fix to PR # 3887 MQTT connection not using discovery: false (#5275) --- esphome/components/mqtt/mqtt_client.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/esphome/components/mqtt/mqtt_client.cpp b/esphome/components/mqtt/mqtt_client.cpp index d3f759c072..1d804170f6 100644 --- a/esphome/components/mqtt/mqtt_client.cpp +++ b/esphome/components/mqtt/mqtt_client.cpp @@ -66,25 +66,28 @@ void MQTTClientComponent::setup() { } #endif - this->subscribe( - "esphome/discover", [this](const std::string &topic, const std::string &payload) { this->send_device_info_(); }, - 2); + if (this->is_discovery_enabled()) { + this->subscribe( + "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()); - this->subscribe( - topic, [this](const std::string &topic, const std::string &payload) { this->send_device_info_(); }, 2); + std::string topic = "esphome/ping/"; + topic.append(App.get_name()); + this->subscribe( + topic, [this](const std::string &topic, const std::string &payload) { this->send_device_info_(); }, 2); + } this->last_connected_ = millis(); this->start_dnslookup_(); } void MQTTClientComponent::send_device_info_() { - if (!this->is_connected()) { + if (!this->is_connected() or !this->is_discovery_enabled()) { return; } std::string topic = "esphome/discover/"; topic.append(App.get_name()); + this->publish_json( topic, [](JsonObject root) { From f14419bab589d911d55f845b21f7ba238cd79d07 Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Fri, 1 Sep 2023 03:21:01 +0200 Subject: [PATCH 0109/2101] Bump Arduino Pico to 3.4.0 (#5321) --- esphome/components/rp2040/__init__.py | 6 +++--- platformio.ini | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/rp2040/__init__.py b/esphome/components/rp2040/__init__.py index dafafc531c..9e9db02de1 100644 --- a/esphome/components/rp2040/__init__.py +++ b/esphome/components/rp2040/__init__.py @@ -62,7 +62,7 @@ def _format_framework_arduino_version(ver: cv.Version) -> str: # 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, 3, 0) +RECOMMENDED_ARDUINO_FRAMEWORK_VERSION = cv.Version(3, 4, 0) # The platformio/raspberrypi version to use for arduino frameworks # - https://github.com/platformio/platform-raspberrypi/releases @@ -73,8 +73,8 @@ ARDUINO_PLATFORM_VERSION = cv.Version(1, 9, 0) def _arduino_check_versions(value): value = value.copy() lookups = { - "dev": (cv.Version(3, 3, 0), "https://github.com/earlephilhower/arduino-pico"), - "latest": (cv.Version(3, 3, 0), None), + "dev": (cv.Version(3, 4, 0), "https://github.com/earlephilhower/arduino-pico"), + "latest": (cv.Version(3, 4, 0), None), "recommended": (RECOMMENDED_ARDUINO_FRAMEWORK_VERSION, None), } diff --git a/platformio.ini b/platformio.ini index 6341d7bde5..64c7bec6e8 100644 --- a/platformio.ini +++ b/platformio.ini @@ -157,7 +157,7 @@ board_build.filesystem_size = 0.5m platform = https://github.com/maxgerhardt/platform-raspberrypi.git 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.3.0/rp2040-3.3.0.zip + earlephilhower/framework-arduinopico@https://github.com/earlephilhower/arduino-pico/releases/download/3.4.0/rp2040-3.4.0.zip framework = arduino lib_deps = From 19d53c6643df22823c2b20b05858f06e093c628f Mon Sep 17 00:00:00 2001 From: Daniel Dunn Date: Thu, 31 Aug 2023 20:02:26 -0600 Subject: [PATCH 0110/2101] Use gzip compression for the web server component's static resources (#5291) Co-authored-by: Daniel Dunn --- esphome/components/web_server/__init__.py | 10 ++++++++-- esphome/components/web_server/web_server.cpp | 3 +++ tests/test3.1.yaml | 4 ++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/esphome/components/web_server/__init__.py b/esphome/components/web_server/__init__.py index ab54ae8582..b1cf8a5de6 100644 --- a/esphome/components/web_server/__init__.py +++ b/esphome/components/web_server/__init__.py @@ -1,3 +1,4 @@ +import gzip import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import web_server_base @@ -109,9 +110,13 @@ def build_index_html(config) -> str: return html -def add_resource_as_progmem(resource_name: str, content: str) -> None: +def add_resource_as_progmem( + resource_name: str, content: str, compress: bool = True +) -> None: """Add a resource to progmem.""" content_encoded = content.encode("utf-8") + if compress: + 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}}}" @@ -137,7 +142,8 @@ async def to_code(config): cg.add_define("USE_WEBSERVER_PORT", config[CONF_PORT]) cg.add_define("USE_WEBSERVER_VERSION", version) if version == 2: - add_resource_as_progmem("INDEX_HTML", build_index_html(config)) + # Don't compress the index HTML as the data sizes are almost the same. + add_resource_as_progmem("INDEX_HTML", build_index_html(config), compress=False) else: cg.add(var.set_css_url(config[CONF_CSS_URL])) cg.add(var.set_js_url(config[CONF_JS_URL])) diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index 01057fead6..e350e1b140 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -328,6 +328,7 @@ void WebServer::handle_index_request(AsyncWebServerRequest *request) { void WebServer::handle_index_request(AsyncWebServerRequest *request) { AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", ESPHOME_WEBSERVER_INDEX_HTML, ESPHOME_WEBSERVER_INDEX_HTML_SIZE); + // No gzip header here because the HTML file is so small request->send(response); } #endif @@ -336,6 +337,7 @@ void WebServer::handle_index_request(AsyncWebServerRequest *request) { void WebServer::handle_css_request(AsyncWebServerRequest *request) { AsyncWebServerResponse *response = request->beginResponse_P(200, "text/css", ESPHOME_WEBSERVER_CSS_INCLUDE, ESPHOME_WEBSERVER_CSS_INCLUDE_SIZE); + response->addHeader("Content-Encoding", "gzip"); request->send(response); } #endif @@ -344,6 +346,7 @@ void WebServer::handle_css_request(AsyncWebServerRequest *request) { void WebServer::handle_js_request(AsyncWebServerRequest *request) { AsyncWebServerResponse *response = request->beginResponse_P(200, "text/javascript", ESPHOME_WEBSERVER_JS_INCLUDE, ESPHOME_WEBSERVER_JS_INCLUDE_SIZE); + response->addHeader("Content-Encoding", "gzip"); request->send(response); } #endif diff --git a/tests/test3.1.yaml b/tests/test3.1.yaml index 46bc014204..ea8dc337be 100644 --- a/tests/test3.1.yaml +++ b/tests/test3.1.yaml @@ -21,6 +21,10 @@ wifi: ssid: "MySSID" password: "password1" +web_server: + port: 80 + version: 2 + i2c: sda: 4 scl: 5 From 712634b30102026b950b416efac4b17aae249ff3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Sep 2023 14:03:10 +1200 Subject: [PATCH 0111/2101] Bump zeroconf from 0.86.0 to 0.88.0 (#5315) 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 b23964828c..715dbef4f2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,7 +11,7 @@ esptool==4.6.2 click==8.1.7 esphome-dashboard==20230711.0 aioesphomeapi==15.0.0 -zeroconf==0.86.0 +zeroconf==0.88.0 # esp-idf requires this, but doesn't bundle it by default # https://github.com/espressif/esp-idf/blob/220590d599e134d7a5e7f1e683cc4550349ffbf8/requirements.txt#L24 From f8a03be2f1fbc641131679a6be628deab277e8fb Mon Sep 17 00:00:00 2001 From: Josh Barnard Date: Thu, 31 Aug 2023 22:10:42 -0700 Subject: [PATCH 0112/2101] Adding heating coil and fan icons, enum device_class (#5325) * Adding heating cool and fan icons. * Adding Enum device_class as well. --- esphome/const.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/esphome/const.py b/esphome/const.py index 373d6bd8c9..e0642247ab 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -842,6 +842,7 @@ ICON_COUNTER = "mdi:counter" ICON_CURRENT_AC = "mdi:current-ac" ICON_DATABASE = "mdi:database" ICON_EMPTY = "" +ICON_FAN = "mdi:fan" ICON_FINGERPRINT = "mdi:fingerprint" ICON_FLASH = "mdi:flash" ICON_FLASK = "mdi:flask" @@ -850,6 +851,7 @@ ICON_FLOWER = "mdi:flower" ICON_GAS_CYLINDER = "mdi:gas-cylinder" ICON_GAUGE = "mdi:gauge" ICON_GRAIN = "mdi:grain" +ICON_HEATING_COIL = "mdi:heating-coil" ICON_KEY_PLUS = "mdi:key-plus" ICON_LIGHTBULB = "mdi:lightbulb" ICON_MAGNET = "mdi:magnet" @@ -965,6 +967,7 @@ DEVICE_CLASS_DURATION = "duration" DEVICE_CLASS_EMPTY = "" DEVICE_CLASS_ENERGY = "energy" DEVICE_CLASS_ENERGY_STORAGE = "energy_storage" +DEVICE_CLASS_ENUM = "enum" DEVICE_CLASS_FREQUENCY = "frequency" DEVICE_CLASS_GARAGE = "garage" DEVICE_CLASS_GARAGE_DOOR = "garage_door" From c3332e4a394b6fb4d1d44e321e168c1fc39fec09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Fri, 1 Sep 2023 08:17:33 +0200 Subject: [PATCH 0113/2101] Add dashboard API to get firmware binaries (#4675) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/esp32/__init__.py | 17 ++++++ esphome/components/esp8266/__init__.py | 11 ++++ esphome/components/rp2040/__init__.py | 11 ++++ esphome/dashboard/dashboard.py | 80 ++++++++++++++++++-------- 4 files changed, 94 insertions(+), 25 deletions(-) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index d158528066..ee18315518 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -84,6 +84,23 @@ def get_board(core_obj=None): return (core_obj or CORE).data[KEY_ESP32][KEY_BOARD] +def get_download_types(storage_json): + return [ + { + "title": "Modern format", + "description": "For use with ESPHome Web and other tools.", + "file": "firmware-factory.bin", + "download": f"{storage_json.name}-factory.bin", + }, + { + "title": "Legacy format", + "description": "For use with ESPHome Flasher.", + "file": "firmware.bin", + "download": f"{storage_json.name}.bin", + }, + ] + + def only_on_variant(*, supported=None, unsupported=None): """Config validator for features only available on some ESP32 variants.""" if supported is not None and not isinstance(supported, list): diff --git a/esphome/components/esp8266/__init__.py b/esphome/components/esp8266/__init__.py index 674f433d52..412c2d903f 100644 --- a/esphome/components/esp8266/__init__.py +++ b/esphome/components/esp8266/__init__.py @@ -50,6 +50,17 @@ def set_core_data(config): return config +def get_download_types(storage_json): + return [ + { + "title": "Standard format", + "description": "For flashing ESP8266.", + "file": "firmware.bin", + "download": f"{storage_json.name}.bin", + }, + ] + + def _format_framework_arduino_version(ver: cv.Version) -> str: # format the given arduino (https://github.com/esp8266/Arduino/releases) version to # a PIO platformio/framework-arduinoespressif8266 value diff --git a/esphome/components/rp2040/__init__.py b/esphome/components/rp2040/__init__.py index 9e9db02de1..b31192f73f 100644 --- a/esphome/components/rp2040/__init__.py +++ b/esphome/components/rp2040/__init__.py @@ -42,6 +42,17 @@ def set_core_data(config): return config +def get_download_types(storage_json): + return [ + { + "title": "UF2 format", + "description": "For copying to RP2040 over USB.", + "file": "firmware.uf2", + "download": f"{storage_json.name}.uf2", + }, + ] + + def _format_framework_arduino_version(ver: cv.Version) -> str: # The most recent releases have not been uploaded to platformio so grabbing them directly from # the GitHub release is one path forward for now. diff --git a/esphome/dashboard/dashboard.py b/esphome/dashboard/dashboard.py index eae004fa09..c05e1fcfcc 100644 --- a/esphome/dashboard/dashboard.py +++ b/esphome/dashboard/dashboard.py @@ -530,11 +530,43 @@ class ImportRequestHandler(BaseHandler): self.finish() +class DownloadListRequestHandler(BaseHandler): + @authenticated + @bind_config + def get(self, configuration=None): + storage_path = ext_storage_path(settings.config_dir, configuration) + storage_json = StorageJSON.load(storage_path) + if storage_json is None: + self.send_error(404) + return + + from esphome.components.esp32 import get_download_types as esp32_types + from esphome.components.esp8266 import get_download_types as esp8266_types + from esphome.components.rp2040 import get_download_types as rp2040_types + + downloads = [] + platform = storage_json.target_platform.lower() + if platform == const.PLATFORM_RP2040: + downloads = rp2040_types(storage_json) + elif platform == const.PLATFORM_ESP8266: + downloads = esp8266_types(storage_json) + elif platform == const.PLATFORM_ESP32: + downloads = esp32_types(storage_json) + else: + self.send_error(418) + return + + self.set_status(200) + self.set_header("content-type", "application/json") + self.write(json.dumps(downloads)) + self.finish() + return + + class DownloadBinaryRequestHandler(BaseHandler): @authenticated @bind_config def get(self, configuration=None): - type = self.get_argument("type", "firmware.bin") compressed = self.get_argument("compressed", "0") == "1" storage_path = ext_storage_path(settings.config_dir, configuration) @@ -543,27 +575,22 @@ class DownloadBinaryRequestHandler(BaseHandler): self.send_error(404) return - if storage_json.target_platform.lower() == const.PLATFORM_RP2040: - filename = f"{storage_json.name}.uf2" - path = storage_json.firmware_bin_path.replace( - "firmware.bin", "firmware.uf2" - ) + # 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: + 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 = os.path.dirname(storage_json.firmware_bin_path) + path = os.path.join(path, file_name) - elif storage_json.target_platform.lower() == const.PLATFORM_ESP8266: - filename = f"{storage_json.name}.bin" - path = storage_json.firmware_bin_path - - elif type == "firmware.bin": - filename = f"{storage_json.name}.bin" - path = storage_json.firmware_bin_path - - elif type == "firmware-factory.bin": - filename = f"{storage_json.name}-factory.bin" - path = storage_json.firmware_bin_path.replace( - "firmware.bin", "firmware-factory.bin" - ) - - else: + if not Path(path).is_file(): args = ["esphome", "idedata", settings.rel_path(configuration)] rc, stdout, _ = run_system_command(*args) @@ -575,9 +602,9 @@ class DownloadBinaryRequestHandler(BaseHandler): found = False for image in idedata.extra_flash_images: - if image.path.endswith(type): + if image.path.endswith(file_name): path = image.path - filename = type + download_name = file_name found = True break @@ -585,10 +612,12 @@ class DownloadBinaryRequestHandler(BaseHandler): self.send_error(404) return - filename = filename + ".gz" if compressed else filename + download_name = download_name + ".gz" if compressed else download_name self.set_header("Content-Type", "application/octet-stream") - self.set_header("Content-Disposition", f'attachment; filename="{filename}"') + self.set_header( + "Content-Disposition", f'attachment; filename="{download_name}"' + ) self.set_header("Cache-Control", "no-cache") if not Path(path).is_file(): self.send_error(404) @@ -1259,6 +1288,7 @@ def make_app(debug=get_bool_env(ENV_DEV)): (f"{rel}update-all", EsphomeUpdateAllHandler), (f"{rel}info", InfoRequestHandler), (f"{rel}edit", EditRequestHandler), + (f"{rel}downloads", DownloadListRequestHandler), (f"{rel}download.bin", DownloadBinaryRequestHandler), (f"{rel}serial-ports", SerialPortRequestHandler), (f"{rel}ping", PingRequestHandler), From bec53f97a251efa343796146796e6c4f2fb59ee1 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Sat, 2 Sep 2023 08:41:52 +1200 Subject: [PATCH 0114/2101] Attempt to fix secret blurring (#5326) --- esphome/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/__main__.py b/esphome/__main__.py index ca5fc1c008..697adc03a3 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -371,7 +371,7 @@ def command_config(args, config): # add the console decoration so the front-end can hide the secrets if not args.show_secrets: output = re.sub( - r"(password|key|psk|ssid)\:\s(.*)", r"\1: \\033[5m\2\\033[6m", output + r"(password|key|psk|ssid)\: (.+)", r"\1: \\033[5m\2\\033[6m", output ) safe_print(output) _LOGGER.info("Configuration is valid!") From 211b3eddeaa5372e7fb3128fe7fc42653fa71ce2 Mon Sep 17 00:00:00 2001 From: kahrendt Date: Fri, 1 Sep 2023 16:55:59 -0400 Subject: [PATCH 0115/2101] Bugfix: disable channels after IO if multiple tca9548a I2C multiplexers are configured (#5317) --- esphome/components/tca9548a/tca9548a.cpp | 27 ++++++++++++++---------- esphome/components/tca9548a/tca9548a.h | 4 +++- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/esphome/components/tca9548a/tca9548a.cpp b/esphome/components/tca9548a/tca9548a.cpp index caa3dd0655..770fd5e47c 100644 --- a/esphome/components/tca9548a/tca9548a.cpp +++ b/esphome/components/tca9548a/tca9548a.cpp @@ -7,23 +7,27 @@ namespace tca9548a { static const char *const TAG = "tca9548a"; i2c::ErrorCode TCA9548AChannel::readv(uint8_t address, i2c::ReadBuffer *buffers, size_t cnt) { - auto err = parent_->switch_to_channel(channel_); + auto err = this->parent_->switch_to_channel(channel_); if (err != i2c::ERROR_OK) return err; - return parent_->bus_->readv(address, buffers, cnt); + err = this->parent_->bus_->readv(address, buffers, cnt); + this->parent_->disable_all_channels(); + return err; } i2c::ErrorCode TCA9548AChannel::writev(uint8_t address, i2c::WriteBuffer *buffers, size_t cnt, bool stop) { - auto err = parent_->switch_to_channel(channel_); + auto err = this->parent_->switch_to_channel(channel_); if (err != i2c::ERROR_OK) return err; - return parent_->bus_->writev(address, buffers, cnt, stop); + err = this->parent_->bus_->writev(address, buffers, cnt, stop); + this->parent_->disable_all_channels(); + return err; } void TCA9548AComponent::setup() { ESP_LOGCONFIG(TAG, "Setting up TCA9548A..."); uint8_t status = 0; if (this->read(&status, 1) != i2c::ERROR_OK) { - ESP_LOGI(TAG, "TCA9548A failed"); + ESP_LOGE(TAG, "TCA9548A failed"); this->mark_failed(); return; } @@ -37,15 +41,16 @@ void TCA9548AComponent::dump_config() { i2c::ErrorCode TCA9548AComponent::switch_to_channel(uint8_t channel) { if (this->is_failed()) return i2c::ERROR_NOT_INITIALIZED; - if (current_channel_ == channel) - return i2c::ERROR_OK; uint8_t channel_val = 1 << channel; - auto err = this->write(&channel_val, 1); - if (err == i2c::ERROR_OK) { - current_channel_ = channel; + return this->write(&channel_val, 1); +} + +void TCA9548AComponent::disable_all_channels() { + if (this->write(&TCA9548A_DISABLE_CHANNELS_COMMAND, 1) != i2c::ERROR_OK) { + ESP_LOGE(TAG, "Failed to disable all channels."); + this->status_set_error(); // couldn't disable channels, set error status } - return err; } } // namespace tca9548a diff --git a/esphome/components/tca9548a/tca9548a.h b/esphome/components/tca9548a/tca9548a.h index 02553f8cd0..08f1674d11 100644 --- a/esphome/components/tca9548a/tca9548a.h +++ b/esphome/components/tca9548a/tca9548a.h @@ -6,6 +6,8 @@ namespace esphome { namespace tca9548a { +static const uint8_t TCA9548A_DISABLE_CHANNELS_COMMAND = 0x00; + class TCA9548AComponent; class TCA9548AChannel : public i2c::I2CBus { public: @@ -28,10 +30,10 @@ class TCA9548AComponent : public Component, public i2c::I2CDevice { void update(); i2c::ErrorCode switch_to_channel(uint8_t channel); + void disable_all_channels(); protected: friend class TCA9548AChannel; - uint8_t current_channel_ = 255; }; } // namespace tca9548a } // namespace esphome From 2bb5f53b98fbbca09755d1715a8f6d066786fa25 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Sat, 2 Sep 2023 08:10:08 +1000 Subject: [PATCH 0116/2101] Make uart error message go away (#5329) * Make error message in log go away. * Test for IDF version. --- esphome/components/logger/logger.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/esphome/components/logger/logger.cpp b/esphome/components/logger/logger.cpp index 86ebb53764..758e9c1f98 100644 --- a/esphome/components/logger/logger.cpp +++ b/esphome/components/logger/logger.cpp @@ -4,6 +4,7 @@ #ifdef USE_ESP_IDF #include #include "freertos/FreeRTOS.h" +#include "esp_idf_version.h" #endif // USE_ESP_IDF #if defined(USE_ESP32_FRAMEWORK_ARDUINO) || defined(USE_ESP_IDF) @@ -239,6 +240,9 @@ void Logger::pre_setup() { uart_config.parity = UART_PARITY_DISABLE; uart_config.stop_bits = UART_STOP_BITS_1; uart_config.flow_ctrl = UART_HW_FLOWCTRL_DISABLE; +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) + uart_config.source_clk = UART_SCLK_DEFAULT; +#endif uart_param_config(uart_num_, &uart_config); const int uart_buffer_size = tx_buffer_size_; // Install UART driver using an event queue here From 2165960ba171e9b3d775622f0bc012ffc51fb295 Mon Sep 17 00:00:00 2001 From: Christian Date: Sat, 2 Sep 2023 01:03:30 +0100 Subject: [PATCH 0117/2101] add heating functionality to SI7021 (#4828) * add heating functoinality * add test * add heat * fix * fix * fix * fix * fix * fix sensor * restore class * Update esphome/components/htu21d/sensor.py * Update esphome/components/htu21d/sensor.py Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> * Update esphome/components/htu21d/sensor.py Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --------- Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Co-authored-by: Keith Burzinski --- esphome/components/htu21d/htu21d.cpp | 58 +++++++++++++++++++++++++++- esphome/components/htu21d/htu21d.h | 30 ++++++++++++++ esphome/components/htu21d/sensor.py | 56 +++++++++++++++++++++++++++ tests/test1.yaml | 2 + 4 files changed, 145 insertions(+), 1 deletion(-) diff --git a/esphome/components/htu21d/htu21d.cpp b/esphome/components/htu21d/htu21d.cpp index a38ec73019..5030ac4d0f 100644 --- a/esphome/components/htu21d/htu21d.cpp +++ b/esphome/components/htu21d/htu21d.cpp @@ -11,7 +11,11 @@ static const uint8_t HTU21D_ADDRESS = 0x40; static const uint8_t HTU21D_REGISTER_RESET = 0xFE; static const uint8_t HTU21D_REGISTER_TEMPERATURE = 0xF3; static const uint8_t HTU21D_REGISTER_HUMIDITY = 0xF5; +static const uint8_t HTU21D_WRITERHT_REG_CMD = 0xE6; /**< Write RH/T User Register 1 */ static const uint8_t HTU21D_REGISTER_STATUS = 0xE7; +static const uint8_t HTU21D_WRITEHEATER_REG_CMD = 0x51; /**< Write Heater Control Register */ +static const uint8_t HTU21D_READHEATER_REG_CMD = 0x11; /**< Read Heater Control Register */ +static const uint8_t HTU21D_REG_HTRE_BIT = 0x02; /**< Control Register Heater Bit */ void HTU21DComponent::setup() { ESP_LOGCONFIG(TAG, "Setting up HTU21D..."); @@ -62,14 +66,66 @@ void HTU21DComponent::update() { raw_humidity = i2c::i2ctohs(raw_humidity); float humidity = (float(raw_humidity & 0xFFFC)) * 125.0f / 65536.0f - 6.0f; - ESP_LOGD(TAG, "Got Temperature=%.1f°C Humidity=%.1f%%", temperature, humidity); + + int8_t heater_level = this->get_heater_level(); + + ESP_LOGD(TAG, "Got Temperature=%.1f°C Humidity=%.1f%% Heater Level=%d", temperature, humidity, heater_level); if (this->temperature_ != nullptr) this->temperature_->publish_state(temperature); if (this->humidity_ != nullptr) this->humidity_->publish_state(humidity); + if (this->heater_ != nullptr) + this->heater_->publish_state(humidity); this->status_clear_warning(); } + +bool HTU21DComponent::is_heater_enabled() { + uint8_t raw_heater; + if (this->read_register(HTU21D_REGISTER_STATUS, reinterpret_cast(&raw_heater), 2) != i2c::ERROR_OK) { + this->status_set_warning(); + return false; + } + raw_heater = i2c::i2ctohs(raw_heater); + return (bool) (((raw_heater) >> (HTU21D_REG_HTRE_BIT)) & 0x01); +} + +void HTU21DComponent::set_heater(bool status) { + uint8_t raw_heater; + if (this->read_register(HTU21D_REGISTER_STATUS, reinterpret_cast(&raw_heater), 2) != i2c::ERROR_OK) { + this->status_set_warning(); + return; + } + raw_heater = i2c::i2ctohs(raw_heater); + if (status) { + raw_heater |= (1 << (HTU21D_REG_HTRE_BIT)); + } else { + raw_heater &= ~(1 << (HTU21D_REG_HTRE_BIT)); + } + + if (this->write_register(HTU21D_WRITERHT_REG_CMD, &raw_heater, 1) != i2c::ERROR_OK) { + this->status_set_warning(); + return; + } +} + +void HTU21DComponent::set_heater_level(uint8_t level) { + if (this->write_register(HTU21D_WRITEHEATER_REG_CMD, &level, 1) != i2c::ERROR_OK) { + this->status_set_warning(); + return; + } +} + +int8_t HTU21DComponent::get_heater_level() { + int8_t raw_heater; + if (this->read_register(HTU21D_READHEATER_REG_CMD, reinterpret_cast(&raw_heater), 2) != i2c::ERROR_OK) { + this->status_set_warning(); + return 0; + } + raw_heater = i2c::i2ctohs(raw_heater); + return raw_heater; +} + float HTU21DComponent::get_setup_priority() const { return setup_priority::DATA; } } // namespace htu21d diff --git a/esphome/components/htu21d/htu21d.h b/esphome/components/htu21d/htu21d.h index a408f06d01..a77a8e3ada 100644 --- a/esphome/components/htu21d/htu21d.h +++ b/esphome/components/htu21d/htu21d.h @@ -3,6 +3,7 @@ #include "esphome/core/component.h" #include "esphome/components/sensor/sensor.h" #include "esphome/components/i2c/i2c.h" +#include "esphome/core/automation.h" namespace esphome { namespace htu21d { @@ -11,6 +12,7 @@ class HTU21DComponent : public PollingComponent, public i2c::I2CDevice { public: void set_temperature(sensor::Sensor *temperature) { temperature_ = temperature; } void set_humidity(sensor::Sensor *humidity) { humidity_ = humidity; } + void set_heater(sensor::Sensor *heater) { heater_ = heater; } /// Setup (reset) the sensor and check connection. void setup() override; @@ -18,11 +20,39 @@ class HTU21DComponent : public PollingComponent, public i2c::I2CDevice { /// Update the sensor values (temperature+humidity). void update() override; + bool is_heater_enabled(); + void set_heater(bool status); + void set_heater_level(uint8_t level); + int8_t get_heater_level(); + float get_setup_priority() const override; protected: sensor::Sensor *temperature_{nullptr}; sensor::Sensor *humidity_{nullptr}; + sensor::Sensor *heater_{nullptr}; +}; + +template class SetHeaterLevelAction : public Action, public Parented { + public: + TEMPLATABLE_VALUE(uint8_t, level) + + void play(Ts... x) override { + auto level = this->level_.value(x...); + + this->parent_->set_heater_level(level); + } +}; + +template class SetHeaterAction : public Action, public Parented { + public: + TEMPLATABLE_VALUE(bool, status) + + void play(Ts... x) override { + auto status = this->status_.value(x...); + + this->parent_->set_heater(status); + } }; } // namespace htu21d diff --git a/esphome/components/htu21d/sensor.py b/esphome/components/htu21d/sensor.py index 2ed318f1c9..1f878230f8 100644 --- a/esphome/components/htu21d/sensor.py +++ b/esphome/components/htu21d/sensor.py @@ -1,6 +1,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import i2c, sensor +from esphome import automation from esphome.const import ( CONF_HUMIDITY, CONF_ID, @@ -10,6 +11,10 @@ from esphome.const import ( STATE_CLASS_MEASUREMENT, UNIT_CELSIUS, UNIT_PERCENT, + CONF_HEATER, + UNIT_EMPTY, + CONF_LEVEL, + CONF_STATUS, ) DEPENDENCIES = ["i2c"] @@ -19,6 +24,10 @@ HTU21DComponent = htu21d_ns.class_( "HTU21DComponent", cg.PollingComponent, i2c.I2CDevice ) +SetHeaterLevelAction = htu21d_ns.class_("SetHeaterLevelAction", automation.Action) +SetHeaterAction = htu21d_ns.class_("SetHeaterAction", automation.Action) + + CONFIG_SCHEMA = ( cv.Schema( { @@ -35,6 +44,11 @@ CONFIG_SCHEMA = ( device_class=DEVICE_CLASS_HUMIDITY, state_class=STATE_CLASS_MEASUREMENT, ), + cv.Optional(CONF_HEATER): sensor.sensor_schema( + unit_of_measurement=UNIT_EMPTY, + accuracy_decimals=1, + state_class=STATE_CLASS_MEASUREMENT, + ), } ) .extend(cv.polling_component_schema("60s")) @@ -54,3 +68,45 @@ async def to_code(config): if CONF_HUMIDITY in config: sens = await sensor.new_sensor(config[CONF_HUMIDITY]) cg.add(var.set_humidity(sens)) + + if CONF_HEATER in config: + sens = await sensor.new_sensor(config[CONF_HEATER]) + cg.add(var.set_heater(sens)) + + +@automation.register_action( + "htu21d.set_heater_level", + SetHeaterLevelAction, + cv.maybe_simple_value( + { + cv.GenerateID(): cv.use_id(HTU21DComponent), + cv.Required(CONF_LEVEL): cv.templatable(cv.int_), + }, + key=CONF_LEVEL, + ), +) +async def set_heater_level_to_code(config, action_id, template_arg, args): + var = cg.new_Pvariable(action_id, template_arg) + await cg.register_parented(var, config[CONF_ID]) + level_ = await cg.templatable(config[CONF_LEVEL], args, int) + cg.add(var.set_level(level_)) + return var + + +@automation.register_action( + "htu21d.set_heater", + SetHeaterAction, + cv.maybe_simple_value( + { + cv.GenerateID(): cv.use_id(HTU21DComponent), + cv.Required(CONF_STATUS): cv.templatable(cv.boolean), + }, + key=CONF_STATUS, + ), +) +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) + cg.add(var.set_status(status_)) + return var diff --git a/tests/test1.yaml b/tests/test1.yaml index 3a6cfa0c4b..efca34247b 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -848,6 +848,8 @@ sensor: name: Living Room Temperature 6 humidity: name: Living Room Humidity 6 + heater: + name: Living Room Heater 6 update_interval: 15s i2c_id: i2c_bus - platform: max6675 From 5fdafc00e665f846a8b3e9b4b318df6c5ddca183 Mon Sep 17 00:00:00 2001 From: Mat931 <49403702+Mat931@users.noreply.github.com> Date: Sat, 2 Sep 2023 09:54:03 +0000 Subject: [PATCH 0118/2101] Fix checksum calculation for pipsolar (#5299) --- esphome/components/pipsolar/pipsolar.cpp | 20 ++++++++++++++++---- esphome/components/pipsolar/pipsolar.h | 2 +- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/esphome/components/pipsolar/pipsolar.cpp b/esphome/components/pipsolar/pipsolar.cpp index 62e4fbd341..2cd1aeba44 100644 --- a/esphome/components/pipsolar/pipsolar.cpp +++ b/esphome/components/pipsolar/pipsolar.cpp @@ -769,7 +769,7 @@ uint8_t Pipsolar::check_incoming_length_(uint8_t length) { uint8_t Pipsolar::check_incoming_crc_() { uint16_t crc16; - crc16 = crc16be(read_buffer_, read_pos_ - 3); + crc16 = this->pipsolar_crc_(read_buffer_, read_pos_ - 3); ESP_LOGD(TAG, "checking crc on incoming message"); if (((uint8_t) ((crc16) >> 8)) == read_buffer_[read_pos_ - 3] && ((uint8_t) ((crc16) &0xff)) == read_buffer_[read_pos_ - 2]) { @@ -798,7 +798,7 @@ uint8_t Pipsolar::send_next_command_() { this->command_start_millis_ = millis(); this->empty_uart_buffer_(); this->read_pos_ = 0; - crc16 = crc16be(byte_command, length); + crc16 = this->pipsolar_crc_(byte_command, length); this->write_str(command); // checksum this->write(((uint8_t) ((crc16) >> 8))); // highbyte @@ -825,8 +825,8 @@ void Pipsolar::send_next_poll_() { this->command_start_millis_ = millis(); this->empty_uart_buffer_(); this->read_pos_ = 0; - crc16 = crc16be(this->used_polling_commands_[this->last_polling_command_].command, - this->used_polling_commands_[this->last_polling_command_].length); + crc16 = this->pipsolar_crc_(this->used_polling_commands_[this->last_polling_command_].command, + this->used_polling_commands_[this->last_polling_command_].length); this->write_array(this->used_polling_commands_[this->last_polling_command_].command, this->used_polling_commands_[this->last_polling_command_].length); // checksum @@ -893,5 +893,17 @@ void Pipsolar::add_polling_command_(const char *command, ENUMPollingCommand poll } } +uint16_t Pipsolar::pipsolar_crc_(uint8_t *msg, uint8_t len) { + uint16_t crc = crc16be(msg, len); + uint8_t crc_low = crc & 0xff; + uint8_t crc_high = crc >> 8; + if (crc_low == 0x28 || crc_low == 0x0d || crc_low == 0x0a) + crc_low++; + if (crc_high == 0x28 || crc_high == 0x0d || crc_high == 0x0a) + crc_high++; + crc = (crc_high << 8) | crc_low; + return crc; +} + } // namespace pipsolar } // namespace esphome diff --git a/esphome/components/pipsolar/pipsolar.h b/esphome/components/pipsolar/pipsolar.h index 65fd3c670d..f20f44f095 100644 --- a/esphome/components/pipsolar/pipsolar.h +++ b/esphome/components/pipsolar/pipsolar.h @@ -193,7 +193,7 @@ class Pipsolar : public uart::UARTDevice, public PollingComponent { void empty_uart_buffer_(); uint8_t check_incoming_crc_(); uint8_t check_incoming_length_(uint8_t length); - uint16_t cal_crc_half_(uint8_t *msg, uint8_t len); + uint16_t pipsolar_crc_(uint8_t *msg, uint8_t len); uint8_t send_next_command_(); void send_next_poll_(); void queue_command_(const char *command, uint8_t length); From 4ae582c3051ba06c811bdfaf89a15b00a19a571b Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 4 Sep 2023 20:43:17 +1200 Subject: [PATCH 0119/2101] Bump esphome-dashboard to 20230904.0 (#5339) --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 715dbef4f2..c52b8e1d8e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,7 +9,7 @@ pyserial==3.5 platformio==6.1.10 # When updating platformio, also update Dockerfile esptool==4.6.2 click==8.1.7 -esphome-dashboard==20230711.0 +esphome-dashboard==20230904.0 aioesphomeapi==15.0.0 zeroconf==0.88.0 From 3d9af2a67c3de1ff9761d099364c399f07a93803 Mon Sep 17 00:00:00 2001 From: croessi <87674139+croessi@users.noreply.github.com> Date: Mon, 4 Sep 2023 22:40:46 +0200 Subject: [PATCH 0120/2101] Added Handling for Nack "file not found" (#5338) --- esphome/components/dfplayer/dfplayer.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/esphome/components/dfplayer/dfplayer.cpp b/esphome/components/dfplayer/dfplayer.cpp index a6339dc988..39a30d035e 100644 --- a/esphome/components/dfplayer/dfplayer.cpp +++ b/esphome/components/dfplayer/dfplayer.cpp @@ -101,6 +101,11 @@ void DFPlayer::loop() { ESP_LOGV(TAG, "Nack"); this->ack_set_is_playing_ = false; this->ack_reset_is_playing_ = false; + if (argument == 6) { + ESP_LOGV(TAG, "File not found"); + this->is_playing_ = false; + } + break; case 0x41: ESP_LOGV(TAG, "Ack ok"); this->is_playing_ |= this->ack_set_is_playing_; From aabe0091ccf1c666e1a6771c40614e8c310aec7f Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Mon, 4 Sep 2023 22:51:04 +0200 Subject: [PATCH 0121/2101] Prepare api and time for ESP-IDF >= 5 (#5332) --- esphome/components/api/api_pb2.cpp | 184 ++++++++++---------- esphome/components/time/real_time_clock.cpp | 2 +- 2 files changed, 94 insertions(+), 92 deletions(-) diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index 3a2d980e57..6149a970ee 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -3,6 +3,8 @@ #include "api_pb2.h" #include "esphome/core/log.h" +#include + namespace esphome { namespace api { @@ -522,12 +524,12 @@ void HelloRequest::dump_to(std::string &out) const { out.append("\n"); out.append(" api_version_major: "); - sprintf(buffer, "%u", this->api_version_major); + sprintf(buffer, "%" PRIu32, this->api_version_major); out.append(buffer); out.append("\n"); out.append(" api_version_minor: "); - sprintf(buffer, "%u", this->api_version_minor); + sprintf(buffer, "%" PRIu32, this->api_version_minor); out.append(buffer); out.append("\n"); out.append("}"); @@ -572,12 +574,12 @@ void HelloResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("HelloResponse {\n"); out.append(" api_version_major: "); - sprintf(buffer, "%u", this->api_version_major); + sprintf(buffer, "%" PRIu32, this->api_version_major); out.append(buffer); out.append("\n"); out.append(" api_version_minor: "); - sprintf(buffer, "%u", this->api_version_minor); + sprintf(buffer, "%" PRIu32, this->api_version_minor); out.append(buffer); out.append("\n"); @@ -783,17 +785,17 @@ void DeviceInfoResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" webserver_port: "); - sprintf(buffer, "%u", this->webserver_port); + sprintf(buffer, "%" PRIu32, this->webserver_port); out.append(buffer); out.append("\n"); out.append(" legacy_bluetooth_proxy_version: "); - sprintf(buffer, "%u", this->legacy_bluetooth_proxy_version); + sprintf(buffer, "%" PRIu32, this->legacy_bluetooth_proxy_version); out.append(buffer); out.append("\n"); out.append(" bluetooth_proxy_feature_flags: "); - sprintf(buffer, "%u", this->bluetooth_proxy_feature_flags); + sprintf(buffer, "%" PRIu32, this->bluetooth_proxy_feature_flags); out.append(buffer); out.append("\n"); @@ -806,7 +808,7 @@ void DeviceInfoResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" voice_assistant_version: "); - sprintf(buffer, "%u", this->voice_assistant_version); + sprintf(buffer, "%" PRIu32, this->voice_assistant_version); out.append(buffer); out.append("\n"); out.append("}"); @@ -898,7 +900,7 @@ void ListEntitiesBinarySensorResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -966,7 +968,7 @@ void BinarySensorStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("BinarySensorStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -1069,7 +1071,7 @@ void ListEntitiesCoverResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -1159,7 +1161,7 @@ void CoverStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("CoverStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -1242,7 +1244,7 @@ void CoverCommandRequest::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("CoverCommandRequest {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -1362,7 +1364,7 @@ void ListEntitiesFanResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -1387,7 +1389,7 @@ void ListEntitiesFanResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" supported_speed_count: "); - sprintf(buffer, "%d", this->supported_speed_count); + sprintf(buffer, "%" PRId32, this->supported_speed_count); out.append(buffer); out.append("\n"); @@ -1454,7 +1456,7 @@ void FanStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("FanStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -1475,7 +1477,7 @@ void FanStateResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" speed_level: "); - sprintf(buffer, "%d", this->speed_level); + sprintf(buffer, "%" PRId32, this->speed_level); out.append(buffer); out.append("\n"); out.append("}"); @@ -1555,7 +1557,7 @@ void FanCommandRequest::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("FanCommandRequest {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -1596,7 +1598,7 @@ void FanCommandRequest::dump_to(std::string &out) const { out.append("\n"); out.append(" speed_level: "); - sprintf(buffer, "%d", this->speed_level); + sprintf(buffer, "%" PRId32, this->speed_level); out.append(buffer); out.append("\n"); out.append("}"); @@ -1710,7 +1712,7 @@ void ListEntitiesLightResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -1864,7 +1866,7 @@ void LightStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("LightStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -2087,7 +2089,7 @@ void LightCommandRequest::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("LightCommandRequest {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -2185,7 +2187,7 @@ void LightCommandRequest::dump_to(std::string &out) const { out.append("\n"); out.append(" transition_length: "); - sprintf(buffer, "%u", this->transition_length); + sprintf(buffer, "%" PRIu32, this->transition_length); out.append(buffer); out.append("\n"); @@ -2194,7 +2196,7 @@ void LightCommandRequest::dump_to(std::string &out) const { out.append("\n"); out.append(" flash_length: "); - sprintf(buffer, "%u", this->flash_length); + sprintf(buffer, "%" PRIu32, this->flash_length); out.append(buffer); out.append("\n"); @@ -2302,7 +2304,7 @@ void ListEntitiesSensorResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -2323,7 +2325,7 @@ void ListEntitiesSensorResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" accuracy_decimals: "); - sprintf(buffer, "%d", this->accuracy_decimals); + sprintf(buffer, "%" PRId32, this->accuracy_decimals); out.append(buffer); out.append("\n"); @@ -2387,7 +2389,7 @@ void SensorStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("SensorStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -2476,7 +2478,7 @@ void ListEntitiesSwitchResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -2539,7 +2541,7 @@ void SwitchStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("SwitchStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -2578,7 +2580,7 @@ void SwitchCommandRequest::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("SwitchCommandRequest {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -2652,7 +2654,7 @@ void ListEntitiesTextSensorResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -2718,7 +2720,7 @@ void TextSensorStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("TextSensorStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -3025,7 +3027,7 @@ void GetTimeResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("GetTimeResponse {\n"); out.append(" epoch_seconds: "); - sprintf(buffer, "%u", this->epoch_seconds); + sprintf(buffer, "%" PRIu32, this->epoch_seconds); out.append(buffer); out.append("\n"); out.append("}"); @@ -3109,7 +3111,7 @@ void ListEntitiesServicesResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -3203,7 +3205,7 @@ void ExecuteServiceArgument::dump_to(std::string &out) const { out.append("\n"); out.append(" legacy_int: "); - sprintf(buffer, "%d", this->legacy_int); + sprintf(buffer, "%" PRId32, this->legacy_int); out.append(buffer); out.append("\n"); @@ -3217,7 +3219,7 @@ void ExecuteServiceArgument::dump_to(std::string &out) const { out.append("\n"); out.append(" int_: "); - sprintf(buffer, "%d", this->int_); + sprintf(buffer, "%" PRId32, this->int_); out.append(buffer); out.append("\n"); @@ -3229,7 +3231,7 @@ void ExecuteServiceArgument::dump_to(std::string &out) const { for (const auto &it : this->int_array) { out.append(" int_array: "); - sprintf(buffer, "%d", it); + sprintf(buffer, "%" PRId32, it); out.append(buffer); out.append("\n"); } @@ -3280,7 +3282,7 @@ void ExecuteServiceRequest::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("ExecuteServiceRequest {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -3356,7 +3358,7 @@ void ListEntitiesCameraResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -3422,7 +3424,7 @@ void CameraImageResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("CameraImageResponse {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -3614,7 +3616,7 @@ void ListEntitiesClimateResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -3802,7 +3804,7 @@ void ClimateStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("ClimateStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -3990,7 +3992,7 @@ void ClimateCommandRequest::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("ClimateCommandRequest {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -4173,7 +4175,7 @@ void ListEntitiesNumberResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -4260,7 +4262,7 @@ void NumberStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("NumberStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -4298,7 +4300,7 @@ void NumberCommandRequest::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("NumberCommandRequest {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -4380,7 +4382,7 @@ void ListEntitiesSelectResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -4452,7 +4454,7 @@ void SelectStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("SelectStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -4495,7 +4497,7 @@ void SelectCommandRequest::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("SelectCommandRequest {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -4589,7 +4591,7 @@ void ListEntitiesLockResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -4660,7 +4662,7 @@ void LockStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("LockStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -4715,7 +4717,7 @@ void LockCommandRequest::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("LockCommandRequest {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -4802,7 +4804,7 @@ void ListEntitiesButtonResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -4848,7 +4850,7 @@ void ButtonCommandRequest::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("ButtonCommandRequest {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); out.append("}"); @@ -4923,7 +4925,7 @@ void ListEntitiesMediaPlayerResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -4992,7 +4994,7 @@ void MediaPlayerStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("MediaPlayerStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -5071,7 +5073,7 @@ void MediaPlayerCommandRequest::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("MediaPlayerCommandRequest {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -5120,7 +5122,7 @@ void SubscribeBluetoothLEAdvertisementsRequest::dump_to(std::string &out) const __attribute__((unused)) char buffer[64]; out.append("SubscribeBluetoothLEAdvertisementsRequest {\n"); out.append(" flags: "); - sprintf(buffer, "%u", this->flags); + sprintf(buffer, "%" PRIu32, this->flags); out.append(buffer); out.append("\n"); out.append("}"); @@ -5167,7 +5169,7 @@ void BluetoothServiceData::dump_to(std::string &out) const { for (const auto &it : this->legacy_data) { out.append(" legacy_data: "); - sprintf(buffer, "%u", it); + sprintf(buffer, "%" PRIu32, it); out.append(buffer); out.append("\n"); } @@ -5247,7 +5249,7 @@ void BluetoothLEAdvertisementResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" rssi: "); - sprintf(buffer, "%d", this->rssi); + sprintf(buffer, "%" PRId32, this->rssi); out.append(buffer); out.append("\n"); @@ -5270,7 +5272,7 @@ void BluetoothLEAdvertisementResponse::dump_to(std::string &out) const { } out.append(" address_type: "); - sprintf(buffer, "%u", this->address_type); + sprintf(buffer, "%" PRIu32, this->address_type); out.append(buffer); out.append("\n"); out.append("}"); @@ -5320,12 +5322,12 @@ void BluetoothLERawAdvertisement::dump_to(std::string &out) const { out.append("\n"); out.append(" rssi: "); - sprintf(buffer, "%d", this->rssi); + sprintf(buffer, "%" PRId32, this->rssi); out.append(buffer); out.append("\n"); out.append(" address_type: "); - sprintf(buffer, "%u", this->address_type); + sprintf(buffer, "%" PRIu32, this->address_type); out.append(buffer); out.append("\n"); @@ -5408,7 +5410,7 @@ void BluetoothDeviceRequest::dump_to(std::string &out) const { out.append("\n"); out.append(" address_type: "); - sprintf(buffer, "%u", this->address_type); + sprintf(buffer, "%" PRIu32, this->address_type); out.append(buffer); out.append("\n"); out.append("}"); @@ -5456,12 +5458,12 @@ void BluetoothDeviceConnectionResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" mtu: "); - sprintf(buffer, "%u", this->mtu); + sprintf(buffer, "%" PRIu32, this->mtu); out.append(buffer); out.append("\n"); out.append(" error: "); - sprintf(buffer, "%d", this->error); + sprintf(buffer, "%" PRId32, this->error); out.append(buffer); out.append("\n"); out.append("}"); @@ -5521,7 +5523,7 @@ void BluetoothGATTDescriptor::dump_to(std::string &out) const { } out.append(" handle: "); - sprintf(buffer, "%u", this->handle); + sprintf(buffer, "%" PRIu32, this->handle); out.append(buffer); out.append("\n"); out.append("}"); @@ -5577,12 +5579,12 @@ void BluetoothGATTCharacteristic::dump_to(std::string &out) const { } out.append(" handle: "); - sprintf(buffer, "%u", this->handle); + sprintf(buffer, "%" PRIu32, this->handle); out.append(buffer); out.append("\n"); out.append(" properties: "); - sprintf(buffer, "%u", this->properties); + sprintf(buffer, "%" PRIu32, this->properties); out.append(buffer); out.append("\n"); @@ -5639,7 +5641,7 @@ void BluetoothGATTService::dump_to(std::string &out) const { } out.append(" handle: "); - sprintf(buffer, "%u", this->handle); + sprintf(buffer, "%" PRIu32, this->handle); out.append(buffer); out.append("\n"); @@ -5746,7 +5748,7 @@ void BluetoothGATTReadRequest::dump_to(std::string &out) const { out.append("\n"); out.append(" handle: "); - sprintf(buffer, "%u", this->handle); + sprintf(buffer, "%" PRIu32, this->handle); out.append(buffer); out.append("\n"); out.append("}"); @@ -5791,7 +5793,7 @@ void BluetoothGATTReadResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" handle: "); - sprintf(buffer, "%u", this->handle); + sprintf(buffer, "%" PRIu32, this->handle); out.append(buffer); out.append("\n"); @@ -5845,7 +5847,7 @@ void BluetoothGATTWriteRequest::dump_to(std::string &out) const { out.append("\n"); out.append(" handle: "); - sprintf(buffer, "%u", this->handle); + sprintf(buffer, "%" PRIu32, this->handle); out.append(buffer); out.append("\n"); @@ -5887,7 +5889,7 @@ void BluetoothGATTReadDescriptorRequest::dump_to(std::string &out) const { out.append("\n"); out.append(" handle: "); - sprintf(buffer, "%u", this->handle); + sprintf(buffer, "%" PRIu32, this->handle); out.append(buffer); out.append("\n"); out.append("}"); @@ -5932,7 +5934,7 @@ void BluetoothGATTWriteDescriptorRequest::dump_to(std::string &out) const { out.append("\n"); out.append(" handle: "); - sprintf(buffer, "%u", this->handle); + sprintf(buffer, "%" PRIu32, this->handle); out.append(buffer); out.append("\n"); @@ -5975,7 +5977,7 @@ void BluetoothGATTNotifyRequest::dump_to(std::string &out) const { out.append("\n"); out.append(" handle: "); - sprintf(buffer, "%u", this->handle); + sprintf(buffer, "%" PRIu32, this->handle); out.append(buffer); out.append("\n"); @@ -6024,7 +6026,7 @@ void BluetoothGATTNotifyDataResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" handle: "); - sprintf(buffer, "%u", this->handle); + sprintf(buffer, "%" PRIu32, this->handle); out.append(buffer); out.append("\n"); @@ -6063,12 +6065,12 @@ void BluetoothConnectionsFreeResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("BluetoothConnectionsFreeResponse {\n"); out.append(" free: "); - sprintf(buffer, "%u", this->free); + sprintf(buffer, "%" PRIu32, this->free); out.append(buffer); out.append("\n"); out.append(" limit: "); - sprintf(buffer, "%u", this->limit); + sprintf(buffer, "%" PRIu32, this->limit); out.append(buffer); out.append("\n"); out.append("}"); @@ -6107,12 +6109,12 @@ void BluetoothGATTErrorResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" handle: "); - sprintf(buffer, "%u", this->handle); + sprintf(buffer, "%" PRIu32, this->handle); out.append(buffer); out.append("\n"); out.append(" error: "); - sprintf(buffer, "%d", this->error); + sprintf(buffer, "%" PRId32, this->error); out.append(buffer); out.append("\n"); out.append("}"); @@ -6146,7 +6148,7 @@ void BluetoothGATTWriteResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" handle: "); - sprintf(buffer, "%u", this->handle); + sprintf(buffer, "%" PRIu32, this->handle); out.append(buffer); out.append("\n"); out.append("}"); @@ -6180,7 +6182,7 @@ void BluetoothGATTNotifyResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" handle: "); - sprintf(buffer, "%u", this->handle); + sprintf(buffer, "%" PRIu32, this->handle); out.append(buffer); out.append("\n"); out.append("}"); @@ -6223,7 +6225,7 @@ void BluetoothDevicePairingResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" error: "); - sprintf(buffer, "%d", this->error); + sprintf(buffer, "%" PRId32, this->error); out.append(buffer); out.append("\n"); out.append("}"); @@ -6266,7 +6268,7 @@ void BluetoothDeviceUnpairingResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" error: "); - sprintf(buffer, "%d", this->error); + sprintf(buffer, "%" PRId32, this->error); out.append(buffer); out.append("\n"); out.append("}"); @@ -6315,7 +6317,7 @@ void BluetoothDeviceClearCacheResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" error: "); - sprintf(buffer, "%d", this->error); + sprintf(buffer, "%" PRId32, this->error); out.append(buffer); out.append("\n"); out.append("}"); @@ -6412,7 +6414,7 @@ void VoiceAssistantResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("VoiceAssistantResponse {\n"); out.append(" port: "); - sprintf(buffer, "%u", this->port); + sprintf(buffer, "%" PRIu32, this->port); out.append(buffer); out.append("\n"); @@ -6575,7 +6577,7 @@ void ListEntitiesAlarmControlPanelResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -6600,7 +6602,7 @@ void ListEntitiesAlarmControlPanelResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" supported_features: "); - sprintf(buffer, "%u", this->supported_features); + sprintf(buffer, "%" PRIu32, this->supported_features); out.append(buffer); out.append("\n"); @@ -6643,7 +6645,7 @@ void AlarmControlPanelStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("AlarmControlPanelStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -6693,7 +6695,7 @@ void AlarmControlPanelCommandRequest::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("AlarmControlPanelCommandRequest {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); diff --git a/esphome/components/time/real_time_clock.cpp b/esphome/components/time/real_time_clock.cpp index 10fa9597b9..0573c7de9d 100644 --- a/esphome/components/time/real_time_clock.cpp +++ b/esphome/components/time/real_time_clock.cpp @@ -24,7 +24,7 @@ void RealTimeClock::synchronize_epoch_(uint32_t epoch) { struct timeval timev { .tv_sec = static_cast(epoch), .tv_usec = 0, }; - ESP_LOGVV(TAG, "Got epoch %u", epoch); + ESP_LOGVV(TAG, "Got epoch %" PRIu32, epoch); timezone tz = {0, 0}; int ret = settimeofday(&timev, &tz); if (ret == EINVAL) { From 22c0b0abaa548bd00938135acecc401a7a12aecf Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Mon, 4 Sep 2023 16:47:53 -0500 Subject: [PATCH 0122/2101] Tweak Improv serial to build in IDF 5 (#5331) --- esphome/components/improv_serial/improv_serial_component.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/improv_serial/improv_serial_component.cpp b/esphome/components/improv_serial/improv_serial_component.cpp index fe19e2f085..1dd1c9cf6f 100644 --- a/esphome/components/improv_serial/improv_serial_component.cpp +++ b/esphome/components/improv_serial/improv_serial_component.cpp @@ -48,7 +48,7 @@ uint8_t ImprovSerialComponent::read_byte_() { this->hw_serial_->readBytes(&data, 1); #endif #ifdef USE_ESP_IDF - uart_read_bytes(this->uart_num_, &data, 1, 20 / portTICK_RATE_MS); + uart_read_bytes(this->uart_num_, &data, 1, 20 / portTICK_PERIOD_MS); #endif return data; } From a9630ac847a292bc6ad671356804deb809eb6dc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Tue, 5 Sep 2023 00:16:08 +0200 Subject: [PATCH 0123/2101] Support for LibreTiny platform (RTL8710, BK7231 & other modules) (#3509) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kuba Szczodrzyński Co-authored-by: Sam Neirinck Co-authored-by: David Buezas Co-authored-by: Stroe Andrei Catalin Co-authored-by: Sam Neirinck Co-authored-by: Péter Sárközi Co-authored-by: Hajo Noerenberg --- CODEOWNERS | 4 + esphome/__main__.py | 21 +- esphome/components/adc/__init__.py | 9 +- esphome/components/adc/adc_sensor.cpp | 13 +- esphome/components/api/api_connection.cpp | 4 + esphome/components/async_tcp/__init__.py | 6 +- esphome/components/bk72xx/__init__.py | 51 + esphome/components/bk72xx/boards.py | 1264 +++++++++++++++ esphome/components/captive_portal/__init__.py | 4 +- esphome/components/debug/debug_component.cpp | 31 +- esphome/components/esp8266/gpio.py | 2 +- esphome/components/i2c/__init__.py | 37 +- esphome/components/json/json_util.cpp | 4 + esphome/components/libretiny/__init__.py | 336 ++++ esphome/components/libretiny/const.py | 90 ++ esphome/components/libretiny/core.cpp | 40 + esphome/components/libretiny/core.h | 11 + .../libretiny/generate_components.py | 329 ++++ esphome/components/libretiny/gpio.py | 216 +++ esphome/components/libretiny/gpio_arduino.cpp | 105 ++ esphome/components/libretiny/gpio_arduino.h | 36 + esphome/components/libretiny/lt_component.cpp | 29 + esphome/components/libretiny/lt_component.h | 36 + esphome/components/libretiny/preferences.cpp | 182 +++ esphome/components/libretiny/preferences.h | 13 + esphome/components/libretiny/text_sensor.py | 31 + esphome/components/libretiny_pwm/__init__.py | 1 + .../libretiny_pwm/libretiny_pwm.cpp | 53 + .../components/libretiny_pwm/libretiny_pwm.h | 55 + esphome/components/libretiny_pwm/output.py | 49 + esphome/components/logger/__init__.py | 34 +- esphome/components/logger/logger.cpp | 58 +- esphome/components/logger/logger.h | 16 +- esphome/components/md5/md5.h | 5 + esphome/components/mdns/mdns_component.cpp | 3 + esphome/components/mdns/mdns_libretiny.cpp | 43 + esphome/components/ota/__init__.py | 9 +- .../ota/ota_backend_arduino_libretiny.cpp | 46 + .../ota/ota_backend_arduino_libretiny.h | 24 + esphome/components/ota/ota_component.cpp | 4 + .../components/remote_receiver/__init__.py | 6 +- .../remote_receiver/remote_receiver.h | 4 +- .../remote_receiver_libretiny.cpp | 122 ++ .../remote_transmitter/remote_transmitter.h | 2 +- .../remote_transmitter_libretiny.cpp | 104 ++ esphome/components/rp2040/gpio.py | 3 +- esphome/components/rtl87xx/__init__.py | 51 + esphome/components/rtl87xx/boards.py | 1390 +++++++++++++++++ esphome/components/sntp/sntp_component.cpp | 4 +- esphome/components/socket/__init__.py | 11 +- esphome/components/socket/headers.h | 29 + .../components/socket/lwip_sockets_impl.cpp | 115 ++ esphome/components/spi/__init__.py | 1 + esphome/components/uart/__init__.py | 5 + .../uart/uart_component_libretiny.cpp | 168 ++ .../uart/uart_component_libretiny.h | 43 + esphome/components/web_server/__init__.py | 9 +- .../components/web_server_base/__init__.py | 2 +- .../web_server_base/web_server_base.cpp | 4 +- esphome/components/wifi/__init__.py | 7 +- esphome/components/wifi/wifi_component.h | 9 + .../wifi/wifi_component_libretiny.cpp | 467 ++++++ esphome/config_validation.py | 8 + esphome/const.py | 15 +- esphome/core/__init__.py | 14 + esphome/core/config.py | 2 +- esphome/core/defines.h | 4 + esphome/core/helpers.cpp | 15 +- esphome/core/helpers.h | 5 +- esphome/core/log.h | 3 + esphome/dashboard/dashboard.py | 9 + esphome/voluptuous_schema.py | 5 + esphome/wizard.py | 80 +- platformio.ini | 41 +- script/ci-custom.py | 6 +- tests/test9.1.yaml | 28 + tests/test9.yaml | 28 + tests/unit_tests/test_wizard.py | 51 +- 78 files changed, 6085 insertions(+), 89 deletions(-) create mode 100644 esphome/components/bk72xx/__init__.py create mode 100644 esphome/components/bk72xx/boards.py create mode 100644 esphome/components/libretiny/__init__.py create mode 100644 esphome/components/libretiny/const.py create mode 100644 esphome/components/libretiny/core.cpp create mode 100644 esphome/components/libretiny/core.h create mode 100644 esphome/components/libretiny/generate_components.py create mode 100644 esphome/components/libretiny/gpio.py create mode 100644 esphome/components/libretiny/gpio_arduino.cpp create mode 100644 esphome/components/libretiny/gpio_arduino.h create mode 100644 esphome/components/libretiny/lt_component.cpp create mode 100644 esphome/components/libretiny/lt_component.h create mode 100644 esphome/components/libretiny/preferences.cpp create mode 100644 esphome/components/libretiny/preferences.h create mode 100644 esphome/components/libretiny/text_sensor.py create mode 100644 esphome/components/libretiny_pwm/__init__.py create mode 100644 esphome/components/libretiny_pwm/libretiny_pwm.cpp create mode 100644 esphome/components/libretiny_pwm/libretiny_pwm.h create mode 100644 esphome/components/libretiny_pwm/output.py create mode 100644 esphome/components/mdns/mdns_libretiny.cpp create mode 100644 esphome/components/ota/ota_backend_arduino_libretiny.cpp create mode 100644 esphome/components/ota/ota_backend_arduino_libretiny.h create mode 100644 esphome/components/remote_receiver/remote_receiver_libretiny.cpp create mode 100644 esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp create mode 100644 esphome/components/rtl87xx/__init__.py create mode 100644 esphome/components/rtl87xx/boards.py create mode 100644 esphome/components/socket/lwip_sockets_impl.cpp create mode 100644 esphome/components/uart/uart_component_libretiny.cpp create mode 100644 esphome/components/uart/uart_component_libretiny.h create mode 100644 esphome/components/wifi/wifi_component_libretiny.cpp create mode 100644 tests/test9.1.yaml create mode 100644 tests/test9.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 49746cf013..1455643550 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -42,6 +42,7 @@ esphome/components/bedjet/climate/* @jhansche esphome/components/bedjet/fan/* @jhansche esphome/components/bh1750/* @OttoWinter esphome/components/binary_sensor/* @esphome/core +esphome/components/bk72xx/* @kuba2k2 esphome/components/bl0939/* @ziceva esphome/components/bl0940/* @tobias- esphome/components/bl0942/* @dbuezas @@ -146,6 +147,8 @@ esphome/components/kuntze/* @ssieb esphome/components/lcd_menu/* @numo68 esphome/components/ld2410/* @regevbr @sebcaps esphome/components/ledc/* @OttoWinter +esphome/components/libretiny/* @kuba2k2 +esphome/components/libretiny_pwm/* @kuba2k2 esphome/components/light/* @esphome/core esphome/components/lilygo_t5_47/touchscreen/* @jesserockz esphome/components/lock/* @esphome/core @@ -234,6 +237,7 @@ esphome/components/rgbct/* @jesserockz esphome/components/rp2040/* @jesserockz esphome/components/rp2040_pio_led_strip/* @Papa-DMan esphome/components/rp2040_pwm/* @jesserockz +esphome/components/rtl87xx/* @kuba2k2 esphome/components/rtttl/* @glmnet esphome/components/safe_mode/* @jsuanet @paulmonigatti esphome/components/scd4x/* @martgras @sjtrny diff --git a/esphome/__main__.py b/esphome/__main__.py index 697adc03a3..9b208c2280 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -26,6 +26,8 @@ from esphome.const import ( CONF_ESPHOME, CONF_PLATFORMIO_OPTIONS, CONF_SUBSTITUTIONS, + PLATFORM_BK72XX, + PLATFORM_RTL87XX, PLATFORM_ESP32, PLATFORM_ESP8266, PLATFORM_RP2040, @@ -278,20 +280,25 @@ def upload_using_esptool(config, port): return run_esptool(115200) +def upload_using_platformio(config, port): + from esphome import platformio_api + + 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 upload_program(config, args, host): if get_port_type(host) == "SERIAL": if CORE.target_platform in (PLATFORM_ESP32, PLATFORM_ESP8266): return upload_using_esptool(config, host) if CORE.target_platform in (PLATFORM_RP2040): - from esphome import platformio_api + return upload_using_platformio(config, args.device) - upload_args = ["-t", "upload"] - if args.device is not None: - upload_args += ["--upload-port", args.device] - return platformio_api.run_platformio_cli_run( - config, CORE.verbose, *upload_args - ) + if CORE.target_platform in (PLATFORM_BK72XX, PLATFORM_RTL87XX): + return upload_using_platformio(config, host) return 1 # Unknown target platform diff --git a/esphome/components/adc/__init__.py b/esphome/components/adc/__init__.py index 015d6edd21..ba72951777 100644 --- a/esphome/components/adc/__init__.py +++ b/esphome/components/adc/__init__.py @@ -1,7 +1,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import pins -from esphome.const import CONF_INPUT +from esphome.const import CONF_ANALOG, CONF_INPUT from esphome.core import CORE from esphome.components.esp32 import get_esp32_variant @@ -166,8 +166,6 @@ def validate_adc_pin(value): return pins.internal_gpio_input_pin_schema(value) if CORE.is_esp8266: - from esphome.components.esp8266.gpio import CONF_ANALOG - value = pins.internal_gpio_pin_number({CONF_ANALOG: True, CONF_INPUT: True})( value ) @@ -184,4 +182,9 @@ def validate_adc_pin(value): raise cv.Invalid("RP2040: Only pins 26, 27, 28 and 29 support ADC") return pins.internal_gpio_input_pin_schema(value) + if CORE.is_libretiny: + return pins.gpio_pin_schema( + {CONF_ANALOG: True, CONF_INPUT: True}, internal=True + )(value) + raise NotImplementedError diff --git a/esphome/components/adc/adc_sensor.cpp b/esphome/components/adc/adc_sensor.cpp index 665ecfd6b5..0642cd7f3f 100644 --- a/esphome/components/adc/adc_sensor.cpp +++ b/esphome/components/adc/adc_sensor.cpp @@ -92,13 +92,13 @@ extern "C" void ADCSensor::dump_config() { LOG_SENSOR("", "ADC Sensor", this); -#ifdef USE_ESP8266 +#if defined(USE_ESP8266) || defined(USE_LIBRETINY) #ifdef USE_ADC_SENSOR_VCC ESP_LOGCONFIG(TAG, " Pin: VCC"); #else LOG_PIN(" Pin: ", pin_); #endif -#endif // USE_ESP8266 +#endif // USE_ESP8266 || USE_LIBRETINY #ifdef USE_ESP32 LOG_PIN(" Pin: ", pin_); @@ -254,6 +254,15 @@ float ADCSensor::sample() { } #endif +#ifdef USE_LIBRETINY +float ADCSensor::sample() { + if (output_raw_) { + return analogRead(this->pin_->get_pin()); // NOLINT + } + return analogReadVoltage(this->pin_->get_pin()) / 1000.0f; // NOLINT +} +#endif // USE_LIBRETINY + #ifdef USE_ESP8266 std::string ADCSensor::unique_id() { return get_mac_address() + "-adc"; } #endif diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index a46efd80e5..ceec53bb65 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1051,6 +1051,10 @@ DeviceInfoResponse APIConnection::device_info(const DeviceInfoRequest &msg) { resp.manufacturer = "Espressif"; #elif defined(USE_RP2040) resp.manufacturer = "Raspberry Pi"; +#elif defined(USE_BK72XX) + resp.manufacturer = "Beken"; +#elif defined(USE_RTL87XX) + resp.manufacturer = "Realtek"; #elif defined(USE_HOST) resp.manufacturer = "Host"; #endif diff --git a/esphome/components/async_tcp/__init__.py b/esphome/components/async_tcp/__init__.py index 1d127623f1..1677d4b9a8 100644 --- a/esphome/components/async_tcp/__init__.py +++ b/esphome/components/async_tcp/__init__.py @@ -8,15 +8,15 @@ CODEOWNERS = ["@OttoWinter"] CONFIG_SCHEMA = cv.All( cv.Schema({}), cv.only_with_arduino, - cv.only_on(["esp32", "esp8266"]), + cv.only_on(["esp32", "esp8266", "bk72xx", "rtl87xx"]), ) @coroutine_with_priority(200.0) async def to_code(config): - if CORE.is_esp32: + if CORE.is_esp32 or CORE.is_libretiny: # https://github.com/esphome/AsyncTCP/blob/master/library.json - cg.add_library("esphome/AsyncTCP-esphome", "1.2.2") + cg.add_library("esphome/AsyncTCP-esphome", "2.0.1") elif CORE.is_esp8266: # https://github.com/esphome/ESPAsyncTCP cg.add_library("esphome/ESPAsyncTCP-esphome", "1.2.3") diff --git a/esphome/components/bk72xx/__init__.py b/esphome/components/bk72xx/__init__.py new file mode 100644 index 0000000000..6737631ac7 --- /dev/null +++ b/esphome/components/bk72xx/__init__.py @@ -0,0 +1,51 @@ +# 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. + +from esphome import pins +from esphome.components import libretiny +from esphome.components.libretiny.const import ( + COMPONENT_BK72XX, + KEY_COMPONENT_DATA, + KEY_LIBRETINY, + LibreTinyComponent, +) +from esphome.core import CORE + +from .boards import BK72XX_BOARDS, BK72XX_BOARD_PINS + +CODEOWNERS = ["@kuba2k2"] +AUTO_LOAD = ["libretiny"] + +COMPONENT_DATA = LibreTinyComponent( + name=COMPONENT_BK72XX, + boards=BK72XX_BOARDS, + board_pins=BK72XX_BOARD_PINS, + pin_validation=None, + usage_validation=None, +) + + +def _set_core_data(config): + CORE.data[KEY_LIBRETINY] = {} + CORE.data[KEY_LIBRETINY][KEY_COMPONENT_DATA] = COMPONENT_DATA + return config + + +CONFIG_SCHEMA = libretiny.BASE_SCHEMA + +PIN_SCHEMA = libretiny.gpio.BASE_PIN_SCHEMA + +CONFIG_SCHEMA.prepend_extra(_set_core_data) + + +async def to_code(config): + return await libretiny.component_to_code(config) + + +@pins.PIN_SCHEMA_REGISTRY.register("bk72xx", PIN_SCHEMA) +async def pin_to_code(config): + return await libretiny.gpio.component_pin_to_code(config) diff --git a/esphome/components/bk72xx/boards.py b/esphome/components/bk72xx/boards.py new file mode 100644 index 0000000000..8e3e8a97a2 --- /dev/null +++ b/esphome/components/bk72xx/boards.py @@ -0,0 +1,1264 @@ +# This file was auto-generated by libretiny/generate_components.py +# Do not modify its contents. + +from esphome.components.libretiny.const import ( + FAMILY_BK7231N, + FAMILY_BK7231Q, + FAMILY_BK7231T, + FAMILY_BK7251, +) + +BK72XX_BOARDS = { + "cb1s": { + "name": "CB1S Wi-Fi Module", + "family": FAMILY_BK7231N, + }, + "cb2l": { + "name": "CB2L Wi-Fi Module", + "family": FAMILY_BK7231N, + }, + "cb2s": { + "name": "CB2S Wi-Fi Module", + "family": FAMILY_BK7231N, + }, + "cb3l": { + "name": "CB3L 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", + "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, + }, + "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", + "family": FAMILY_BK7231T, + }, + "wblc5": { + "name": "WBLC5 Wi-Fi Module", + "family": FAMILY_BK7231T, + }, +} + +BK72XX_BOARD_PINS = { + "cb1s": { + "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": 11, + "D1": 10, + "D2": 6, + "D3": 7, + "D4": 0, + "D5": 9, + "D6": 8, + "D7": 1, + "D8": 24, + "D9": 26, + "D10": 23, + "D11": 20, + "D12": 21, + "D13": 22, + "A0": 23, + }, + "cb2l": { + "SERIAL1_RX": 10, + "SERIAL1_TX": 11, + "SERIAL2_TX": 0, + "P0": 0, + "P6": 6, + "P7": 7, + "P8": 8, + "P10": 10, + "P11": 11, + "P21": 21, + "P24": 24, + "P26": 26, + "PWM0": 6, + "PWM1": 7, + "PWM2": 8, + "PWM4": 24, + "PWM5": 26, + "RX1": 10, + "SCL2": 0, + "SDA1": 21, + "TX1": 11, + "TX2": 0, + "D0": 8, + "D1": 7, + "D2": 6, + "D3": 26, + "D4": 24, + "D5": 10, + "D6": 0, + "D7": 11, + "D8": 21, + }, + "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, + }, + "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, + }, + "cb3s": { + "WIRE1_SCL": 20, + "WIRE1_SDA_0": 21, + "WIRE1_SDA_1": 21, + "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, + "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, + "SCK": 14, + "SCL1": 20, + "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, + "D12": 22, + "D13": 20, + "A0": 23, + }, + "cb3se": { + "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, + "P22": 22, + "P23": 23, + "P24": 24, + "P26": 26, + "PWM0": 6, + "PWM1": 7, + "PWM2": 8, + "PWM3": 9, + "PWM4": 24, + "PWM5": 26, + "RX1": 10, + "RX2": 1, + "SCK": 14, + "SCL1": 20, + "SCL2": 0, + "SDA2": 1, + "TX1": 11, + "TX2": 0, + "D0": 23, + "D1": 14, + "D2": 26, + "D3": 24, + "D4": 6, + "D5": 9, + "D6": 0, + "D7": 1, + "D8": 8, + "D9": 7, + "D10": 10, + "D11": 11, + "D12": 15, + "D13": 22, + "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, + "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-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, + "A0": 23, + }, + "generic-bk7252": { + "WIRE1_SCL": 20, + "WIRE1_SDA": 21, + "WIRE2_SCL": 0, + "WIRE2_SDA": 1, + "SERIAL1_CTS": 12, + "SERIAL1_RTS": 13, + "SERIAL1_RX": 10, + "SERIAL1_TX": 11, + "SERIAL2_RX": 1, + "SERIAL2_TX": 0, + "ADC1": 4, + "ADC2": 5, + "ADC3": 23, + "ADC4": 2, + "ADC5": 3, + "ADC6": 12, + "ADC7": 13, + "CS": 15, + "CTS1": 12, + "MISO": 17, + "MOSI": 16, + "P0": 0, + "P1": 1, + "P2": 2, + "P3": 3, + "P4": 4, + "P5": 5, + "P6": 6, + "P7": 7, + "P10": 10, + "P11": 11, + "P12": 12, + "P13": 13, + "P14": 14, + "P15": 15, + "P16": 16, + "P17": 17, + "P18": 18, + "P19": 19, + "P20": 20, + "P21": 21, + "P22": 22, + "P23": 23, + "P24": 24, + "P25": 25, + "P26": 26, + "P27": 27, + "P28": 28, + "P29": 29, + "P30": 30, + "P31": 31, + "P32": 32, + "P33": 33, + "P34": 34, + "P35": 35, + "P36": 36, + "P37": 37, + "P38": 38, + "P39": 39, + "PWM0": 6, + "PWM1": 7, + "PWM4": 24, + "PWM5": 26, + "RTS1": 13, + "RX1": 10, + "RX2": 1, + "SCK": 14, + "SCL1": 20, + "SCL2": 0, + "SDA1": 21, + "SDA2": 1, + "TX1": 11, + "TX2": 0, + "D0": 0, + "D1": 1, + "D2": 2, + "D3": 3, + "D4": 4, + "D5": 5, + "D6": 6, + "D7": 7, + "D8": 10, + "D9": 11, + "D10": 12, + "D11": 13, + "D12": 14, + "D13": 15, + "D14": 16, + "D15": 17, + "D16": 18, + "D17": 19, + "D18": 20, + "D19": 21, + "D20": 22, + "D21": 23, + "D22": 24, + "D23": 25, + "D24": 26, + "D25": 27, + "D26": 28, + "D27": 29, + "D28": 30, + "D29": 31, + "D30": 32, + "D31": 33, + "D32": 34, + "D33": 35, + "D34": 36, + "D35": 37, + "D36": 38, + "D37": 39, + "A1": 4, + "A2": 5, + "A3": 23, + "A4": 3, + "A5": 2, + "A6": 12, + "A7": 13, + }, + "lsc-lma35-t": { + "WIRE2_SCL": 0, + "WIRE2_SDA": 1, + "SERIAL1_RX": 10, + "SERIAL1_TX": 11, + "SERIAL2_RX": 1, + "SERIAL2_TX": 0, + "ADC3": 23, + "MOSI": 16, + "P0": 0, + "P1": 1, + "P6": 6, + "P7": 7, + "P8": 8, + "P9": 9, + "P10": 10, + "P11": 11, + "P14": 14, + "P16": 16, + "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, + "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, + }, + "lsc-lma35": { + "WIRE2_SCL": 0, + "WIRE2_SDA": 1, + "SERIAL1_RX": 10, + "SERIAL1_TX": 11, + "SERIAL2_RX": 1, + "SERIAL2_TX": 0, + "ADC3": 23, + "MOSI": 16, + "P0": 0, + "P1": 1, + "P6": 6, + "P7": 7, + "P8": 8, + "P9": 9, + "P10": 10, + "P11": 11, + "P14": 14, + "P16": 16, + "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, + "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, + "D2": 26, + "D3": 24, + "D4": 0, + "D5": 8, + "D6": 7, + "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, + "D13": 22, + "A0": 23, + }, + "wb3l": { + "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, + "MOSI": 16, + "P0": 0, + "P1": 1, + "P6": 6, + "P7": 7, + "P8": 8, + "P9": 9, + "P10": 10, + "P11": 11, + "P14": 14, + "P16": 16, + "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, + "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": 9, + "D6": 0, + "D7": 16, + "D8": 8, + "D9": 7, + "D10": 10, + "D11": 11, + "D12": 22, + "D13": 21, + "D14": 20, + "D15": 1, + "A0": 23, + }, + "wb3s": { + "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, + "P14": 14, + "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, + "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, + "A0": 23, + }, +} + +BOARDS = BK72XX_BOARDS diff --git a/esphome/components/captive_portal/__init__.py b/esphome/components/captive_portal/__init__.py index db4a17f6f7..6af741c6b3 100644 --- a/esphome/components/captive_portal/__init__.py +++ b/esphome/components/captive_portal/__init__.py @@ -21,7 +21,7 @@ CONFIG_SCHEMA = cv.All( ), } ).extend(cv.COMPONENT_SCHEMA), - cv.only_on(["esp32", "esp8266"]), + cv.only_on(["esp32", "esp8266", "bk72xx", "rtl87xx"]), ) @@ -39,3 +39,5 @@ async def to_code(config): cg.add_library("WiFi", None) if CORE.is_esp8266: cg.add_library("DNSServer", None) + if CORE.is_libretiny: + cg.add_library("DNSServer", None) diff --git a/esphome/components/debug/debug_component.cpp b/esphome/components/debug/debug_component.cpp index 5ee1960267..52ee4b070e 100644 --- a/esphome/components/debug/debug_component.cpp +++ b/esphome/components/debug/debug_component.cpp @@ -28,7 +28,7 @@ #ifdef USE_ARDUINO #ifdef USE_RP2040 #include -#else +#elif defined(USE_ESP32) || defined(USE_ESP8266) #include #endif #endif @@ -45,6 +45,8 @@ static uint32_t get_free_heap() { return heap_caps_get_free_size(MALLOC_CAP_INTERNAL); #elif defined(USE_RP2040) return rp2040.getFreeHeap(); +#elif defined(USE_LIBRETINY) + return lt_heap_get_free(); #endif } @@ -75,7 +77,7 @@ void DebugComponent::dump_config() { this->free_heap_ = get_free_heap(); ESP_LOGD(TAG, "Free Heap Size: %" PRIu32 " bytes", this->free_heap_); -#if defined(USE_ARDUINO) && !defined(USE_RP2040) +#if defined(USE_ARDUINO) && (defined(USE_ESP32) || defined(USE_ESP8266)) const char *flash_mode; switch (ESP.getFlashChipMode()) { // NOLINT(readability-static-accessed-through-instance) case FM_QIO: @@ -107,7 +109,7 @@ void DebugComponent::dump_config() { device_info += "|Flash: " + to_string(ESP.getFlashChipSize() / 1024) + // NOLINT "kB Speed:" + to_string(ESP.getFlashChipSpeed() / 1000000) + "MHz Mode:"; // NOLINT device_info += flash_mode; -#endif // USE_ARDUINO +#endif // USE_ARDUINO && (USE_ESP32 || USE_ESP8266) #ifdef USE_ESP32 esp_chip_info_t info; @@ -340,6 +342,27 @@ void DebugComponent::dump_config() { device_info += "CPU Frequency: " + to_string(rp2040.f_cpu()); #endif // USE_RP2040 +#ifdef USE_LIBRETINY + ESP_LOGD(TAG, "LibreTiny Version: %s", lt_get_version()); + ESP_LOGD(TAG, "Chip: %s (%04x) @ %u MHz", lt_cpu_get_model_name(), lt_cpu_get_model(), lt_cpu_get_freq_mhz()); + ESP_LOGD(TAG, "Chip ID: 0x%06X", lt_cpu_get_mac_id()); + ESP_LOGD(TAG, "Board: %s", lt_get_board_code()); + ESP_LOGD(TAG, "Flash: %u KiB / RAM: %u KiB", lt_flash_get_size() / 1024, lt_ram_get_size() / 1024); + ESP_LOGD(TAG, "Reset Reason: %s", lt_get_reboot_reason_name(lt_get_reboot_reason())); + + device_info += "|Version: "; + device_info += LT_BANNER_STR + 10; + device_info += "|Reset Reason: "; + device_info += lt_get_reboot_reason_name(lt_get_reboot_reason()); + device_info += "|Chip Name: "; + device_info += lt_cpu_get_model_name(); + device_info += "|Chip ID: 0x" + format_hex(lt_cpu_get_mac_id()); + device_info += "|Flash: " + to_string(lt_flash_get_size() / 1024) + " KiB"; + device_info += "|RAM: " + to_string(lt_ram_get_size() / 1024) + " KiB"; + + reset_reason = lt_get_reboot_reason_name(lt_get_reboot_reason()); +#endif // USE_LIBRETINY + #ifdef USE_TEXT_SENSOR if (this->device_info_ != nullptr) { if (device_info.length() > 255) @@ -384,6 +407,8 @@ void DebugComponent::update() { this->block_sensor_->publish_state(ESP.getMaxFreeBlockSize()); #elif defined(USE_ESP32) this->block_sensor_->publish_state(heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL)); +#elif defined(USE_LIBRETINY) + this->block_sensor_->publish_state(lt_heap_get_max_alloc()); #endif } diff --git a/esphome/components/esp8266/gpio.py b/esphome/components/esp8266/gpio.py index d4b2078524..e75578cc16 100644 --- a/esphome/components/esp8266/gpio.py +++ b/esphome/components/esp8266/gpio.py @@ -2,6 +2,7 @@ import logging from dataclasses import dataclass from esphome.const import ( + CONF_ANALOG, CONF_ID, CONF_INPUT, CONF_INVERTED, @@ -140,7 +141,6 @@ def validate_supports(value): return value -CONF_ANALOG = "analog" ESP8266_PIN_SCHEMA = cv.All( { cv.GenerateID(): cv.declare_id(ESP8266GPIOPin), diff --git a/esphome/components/i2c/__init__.py b/esphome/components/i2c/__init__.py index a04e63e789..e38cfd23fa 100644 --- a/esphome/components/i2c/__init__.py +++ b/esphome/components/i2c/__init__.py @@ -42,23 +42,26 @@ pin_with_input_and_output_support = cv.All( ) -CONFIG_SCHEMA = cv.Schema( - { - cv.GenerateID(): _bus_declare_type, - cv.Optional(CONF_SDA, default="SDA"): pin_with_input_and_output_support, - cv.SplitDefault(CONF_SDA_PULLUP_ENABLED, esp32_idf=True): cv.All( - cv.only_with_esp_idf, cv.boolean - ), - cv.Optional(CONF_SCL, default="SCL"): pin_with_input_and_output_support, - cv.SplitDefault(CONF_SCL_PULLUP_ENABLED, esp32_idf=True): cv.All( - cv.only_with_esp_idf, cv.boolean - ), - cv.Optional(CONF_FREQUENCY, default="50kHz"): cv.All( - cv.frequency, cv.Range(min=0, min_included=False) - ), - cv.Optional(CONF_SCAN, default=True): cv.boolean, - } -).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = cv.All( + cv.Schema( + { + cv.GenerateID(): _bus_declare_type, + cv.Optional(CONF_SDA, default="SDA"): pin_with_input_and_output_support, + cv.SplitDefault(CONF_SDA_PULLUP_ENABLED, esp32_idf=True): cv.All( + cv.only_with_esp_idf, cv.boolean + ), + cv.Optional(CONF_SCL, default="SCL"): pin_with_input_and_output_support, + cv.SplitDefault(CONF_SCL_PULLUP_ENABLED, esp32_idf=True): cv.All( + cv.only_with_esp_idf, cv.boolean + ), + cv.Optional(CONF_FREQUENCY, default="50kHz"): cv.All( + cv.frequency, cv.Range(min=0, min_included=False) + ), + cv.Optional(CONF_SCAN, default=True): cv.boolean, + } + ).extend(cv.COMPONENT_SCHEMA), + cv.only_on(["esp32", "esp8266", "rp2040"]), +) @coroutine_with_priority(1.0) diff --git a/esphome/components/json/json_util.cpp b/esphome/components/json/json_util.cpp index f27d441804..bef494b64d 100644 --- a/esphome/components/json/json_util.cpp +++ b/esphome/components/json/json_util.cpp @@ -29,6 +29,8 @@ std::string build_json(const json_build_t &f) { const size_t free_heap = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT); #elif defined(USE_RP2040) const size_t free_heap = rp2040.getFreeHeap(); +#elif defined(USE_LIBRETINY) + const size_t free_heap = lt_heap_get_free(); #endif size_t request_size = std::min(free_heap, (size_t) 512); @@ -71,6 +73,8 @@ void parse_json(const std::string &data, const json_parse_t &f) { const size_t free_heap = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT); #elif defined(USE_RP2040) const size_t free_heap = rp2040.getFreeHeap(); +#elif defined(USE_LIBRETINY) + const size_t free_heap = lt_heap_get_free(); #endif bool pass = false; size_t request_size = std::min(free_heap, (size_t) (data.size() * 1.5)); diff --git a/esphome/components/libretiny/__init__.py b/esphome/components/libretiny/__init__.py new file mode 100644 index 0000000000..c6c63b48c8 --- /dev/null +++ b/esphome/components/libretiny/__init__.py @@ -0,0 +1,336 @@ +import json +import logging +from os.path import dirname, isfile, join + +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.const import ( + CONF_BOARD, + CONF_COMPONENT_ID, + CONF_DEBUG, + CONF_FAMILY, + CONF_FRAMEWORK, + CONF_ID, + CONF_NAME, + CONF_OPTIONS, + CONF_PROJECT, + CONF_SOURCE, + CONF_VERSION, + KEY_CORE, + KEY_FRAMEWORK_VERSION, + KEY_TARGET_FRAMEWORK, + KEY_TARGET_PLATFORM, + __version__, +) +from esphome.core import CORE + +from . import gpio # noqa +from .const import ( + CONF_GPIO_RECOVER, + CONF_LOGLEVEL, + CONF_SDK_SILENT, + CONF_UART_PORT, + FAMILIES, + FAMILY_COMPONENT, + FAMILY_FRIENDLY, + KEY_BOARD, + KEY_COMPONENT, + KEY_COMPONENT_DATA, + KEY_FAMILY, + KEY_LIBRETINY, + LT_DEBUG_MODULES, + LT_LOGLEVELS, + LibreTinyComponent, + LTComponent, +) + +_LOGGER = logging.getLogger(__name__) +CODEOWNERS = ["@kuba2k2"] +AUTO_LOAD = [] + + +def _detect_variant(value): + if KEY_LIBRETINY not in CORE.data: + raise cv.Invalid("Family component didn't populate core data properly!") + component: LibreTinyComponent = CORE.data[KEY_LIBRETINY][KEY_COMPONENT_DATA] + board = value[CONF_BOARD] + # read board-default family if not specified + if CONF_FAMILY not in value: + if board not in component.boards: + raise cv.Invalid( + "This board is unknown, please set the family manually. " + "Also, make sure the chosen chip component is correct.", + path=[CONF_BOARD], + ) + value = value.copy() + value[CONF_FAMILY] = component.boards[board][KEY_FAMILY] + # read component name matching this family + value[CONF_COMPONENT_ID] = FAMILY_COMPONENT[value[CONF_FAMILY]] + # make sure the chosen component matches the family + if value[CONF_COMPONENT_ID] != component.name: + raise cv.Invalid( + f"The chosen family doesn't belong to '{component.name}' component. The correct component is '{value[CONF_COMPONENT_ID]}'", + path=[CONF_FAMILY], + ) + # warn anyway if the board wasn't found + if board not in component.boards: + _LOGGER.warning( + "This board is unknown. Make sure the chosen chip component is correct.", + ) + return value + + +def _update_core_data(config): + CORE.data[KEY_CORE][KEY_TARGET_PLATFORM] = config[CONF_COMPONENT_ID] + CORE.data[KEY_CORE][KEY_TARGET_FRAMEWORK] = "arduino" + CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] = cv.Version.parse( + config[CONF_FRAMEWORK][CONF_VERSION] + ) + CORE.data[KEY_LIBRETINY][KEY_BOARD] = config[CONF_BOARD] + CORE.data[KEY_LIBRETINY][KEY_COMPONENT] = config[CONF_COMPONENT_ID] + CORE.data[KEY_LIBRETINY][KEY_FAMILY] = config[CONF_FAMILY] + return config + + +def get_libretiny_component(core_obj=None): + return (core_obj or CORE).data[KEY_LIBRETINY][KEY_COMPONENT] + + +def get_libretiny_family(core_obj=None): + return (core_obj or CORE).data[KEY_LIBRETINY][KEY_FAMILY] + + +def only_on_family(*, supported=None, unsupported=None): + """Config validator for features only available on some LibreTiny families.""" + if supported is not None and not isinstance(supported, list): + supported = [supported] + if unsupported is not None and not isinstance(unsupported, list): + unsupported = [unsupported] + + def validator_(obj): + family = get_libretiny_family() + if supported is not None and family not in supported: + raise cv.Invalid( + f"This feature is only available on {', '.join(supported)}" + ) + if unsupported is not None and family in unsupported: + raise cv.Invalid( + f"This feature is not available on {', '.join(unsupported)}" + ) + return obj + + return validator_ + + +def get_download_types(storage_json=None): + types = [ + { + "title": "UF2 package (recommended)", + "description": "For flashing via web_server OTA or with ltchiptool (UART)", + "file": "firmware.uf2", + "download": f"{storage_json.name}.uf2", + }, + ] + + build_dir = dirname(storage_json.firmware_bin_path) + outputs = join(build_dir, "firmware.json") + if not isfile(outputs): + return types + with open(outputs, encoding="utf-8") as f: + outputs = json.load(f) + for output in outputs: + if not output["public"]: + continue + suffix = output["filename"].partition(".")[2] + suffix = f"-{suffix}" if "." in suffix else f".{suffix}" + types.append( + { + "title": output["title"], + "description": output["description"], + "file": output["filename"], + "download": storage_json.name + suffix, + } + ) + return types + + +def _notify_old_style(config): + if config: + raise cv.Invalid( + "The LibreTiny component is now split between supported chip families.\n" + "Migrate your config file to include a chip-based configuration, " + "instead of the 'libretiny:' block.\n" + "For example 'bk72xx:' or 'rtl87xx:'." + ) + return config + + +# NOTE: Keep this in mind when updating the recommended version: +# * For all constants below, update platformio.ini (in this repo) +ARDUINO_VERSIONS = { + "dev": (cv.Version(0, 0, 0), "https://github.com/kuba2k2/libretiny.git"), + "latest": (cv.Version(0, 0, 0), None), + "recommended": (cv.Version(1, 3, 0), None), +} + + +def _check_framework_version(value): + value = value.copy() + + if value[CONF_VERSION] in ARDUINO_VERSIONS: + if CONF_SOURCE in value: + raise cv.Invalid( + "Framework version needs to be explicitly specified when custom source is used." + ) + + version, source = ARDUINO_VERSIONS[value[CONF_VERSION]] + else: + version = cv.Version.parse(cv.version_number(value[CONF_VERSION])) + source = value.get(CONF_SOURCE, None) + + value[CONF_VERSION] = str(version) + value[CONF_SOURCE] = source + + return value + + +def _check_debug_order(value): + debug = value[CONF_DEBUG] + if "NONE" in debug and "NONE" in debug[1:]: + raise cv.Invalid( + "'none' has to be specified before other modules, and only once", + path=[CONF_DEBUG], + ) + return value + + +FRAMEWORK_SCHEMA = cv.All( + cv.Schema( + { + cv.Optional(CONF_VERSION, default="recommended"): cv.string_strict, + cv.Optional(CONF_SOURCE): cv.string_strict, + cv.Optional(CONF_LOGLEVEL, default="warn"): ( + cv.one_of(*LT_LOGLEVELS, upper=True) + ), + cv.Optional(CONF_DEBUG, default=[]): cv.ensure_list( + cv.one_of("NONE", *LT_DEBUG_MODULES, upper=True) + ), + cv.Optional(CONF_SDK_SILENT, default="all"): ( + cv.one_of("all", "auto", "none", lower=True) + ), + cv.Optional(CONF_UART_PORT, default=None): cv.one_of(0, 1, 2, int=True), + cv.Optional(CONF_GPIO_RECOVER, default=True): cv.boolean, + cv.Optional(CONF_OPTIONS, default={}): { + cv.string_strict: cv.string, + }, + } + ), + _check_framework_version, + _check_debug_order, +) + +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.Optional(CONF_FAMILY): cv.one_of(*FAMILIES, upper=True), + cv.Optional(CONF_FRAMEWORK, default={}): FRAMEWORK_SCHEMA, + }, +) + +BASE_SCHEMA.add_extra(_detect_variant) +BASE_SCHEMA.add_extra(_update_core_data) + + +# pylint: disable=use-dict-literal +async def component_to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + + # setup board config + cg.add_platformio_option("board", config[CONF_BOARD]) + cg.add_build_flag("-DUSE_LIBRETINY") + cg.add_build_flag(f"-DUSE_{config[CONF_COMPONENT_ID]}") + 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]]) + + # force using arduino framework + cg.add_platformio_option("framework", "arduino") + cg.add_build_flag("-DUSE_ARDUINO") + + # disable library compatibility checks + cg.add_platformio_option("lib_ldf_mode", "off") + # include in every file + cg.add_platformio_option("build_src_flags", "-include Arduino.h") + # 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) + cg.add_build_flag("-DCONFIG_ASYNC_TCP_STACK_SIZE=4096") + + # build framework version + # if platform version is a valid version constraint, prefix the default package + framework = config[CONF_FRAMEWORK] + cv.platformio_version_constraint(framework[CONF_VERSION]) + if str(framework[CONF_VERSION]) != "0.0.0": + cg.add_platformio_option("platform", f"libretiny @ {framework[CONF_VERSION]}") + elif framework[CONF_SOURCE]: + cg.add_platformio_option("platform", framework[CONF_SOURCE]) + else: + cg.add_platformio_option("platform", "libretiny") + + # apply LibreTiny options from framework: block + # setup LT logger to work nicely with ESPHome logger + lt_options = dict( + LT_LOGLEVEL="LT_LEVEL_" + framework[CONF_LOGLEVEL], + LT_LOGGER_CALLER=0, + LT_LOGGER_TASK=0, + LT_LOGGER_COLOR=1, + LT_USE_TIME=1, + ) + # enable/disable per-module debugging + for module in framework[CONF_DEBUG]: + if module == "NONE": + # disable all modules + for module in LT_DEBUG_MODULES: + lt_options[f"LT_DEBUG_{module}"] = 0 + else: + # enable one module + lt_options[f"LT_DEBUG_{module}"] = 1 + # set SDK silencing mode + if framework[CONF_SDK_SILENT] == "all": + lt_options["LT_UART_SILENT_ENABLED"] = 1 + lt_options["LT_UART_SILENT_ALL"] = 1 + elif framework[CONF_SDK_SILENT] == "auto": + lt_options["LT_UART_SILENT_ENABLED"] = 1 + lt_options["LT_UART_SILENT_ALL"] = 0 + else: + lt_options["LT_UART_SILENT_ENABLED"] = 0 + lt_options["LT_UART_SILENT_ALL"] = 0 + # set default UART port + if framework[CONF_UART_PORT] is not None: + lt_options["LT_UART_DEFAULT_PORT"] = framework[CONF_UART_PORT] + # add custom options + lt_options.update(framework[CONF_OPTIONS]) + + # apply ESPHome options from framework: block + cg.add_define("LT_GPIO_RECOVER", int(framework[CONF_GPIO_RECOVER])) + + # build PlatformIO compiler flags + for name, value in sorted(lt_options.items()): + cg.add_build_flag(f"-D{name}={value}") + + # custom output firmware name and version + if CONF_PROJECT in config: + cg.add_platformio_option( + "custom_fw_name", "esphome." + config[CONF_PROJECT][CONF_NAME] + ) + cg.add_platformio_option( + "custom_fw_version", config[CONF_PROJECT][CONF_VERSION] + ) + else: + cg.add_platformio_option("custom_fw_name", "esphome") + cg.add_platformio_option("custom_fw_version", __version__) + + await cg.register_component(var, config) diff --git a/esphome/components/libretiny/const.py b/esphome/components/libretiny/const.py new file mode 100644 index 0000000000..525d8b7786 --- /dev/null +++ b/esphome/components/libretiny/const.py @@ -0,0 +1,90 @@ +from dataclasses import dataclass +from typing import Callable + +import esphome.codegen as cg + + +@dataclass +class LibreTinyComponent: + name: str + boards: dict[str, dict[str, str]] + board_pins: dict[str, dict[str, int]] + pin_validation: Callable[[int], int] + usage_validation: Callable[[dict], dict] + + +CONF_LIBRETINY = "libretiny" +CONF_LOGLEVEL = "loglevel" +CONF_SDK_SILENT = "sdk_silent" +CONF_GPIO_RECOVER = "gpio_recover" +CONF_UART_PORT = "uart_port" + +LT_LOGLEVELS = [ + "VERBOSE", + "TRACE", + "DEBUG", + "INFO", + "WARN", + "ERROR", + "FATAL", + "NONE", +] + +LT_DEBUG_MODULES = [ + "WIFI", + "CLIENT", + "SERVER", + "SSL", + "OTA", + "FDB", + "MDNS", + "LWIP", + "LWIP_ASSERT", +] + +KEY_LIBRETINY = "libretiny" +KEY_BOARD = "board" +KEY_COMPONENT = "component" +KEY_COMPONENT_DATA = "component_data" +KEY_FAMILY = "family" + +# COMPONENTS - auto-generated! Do not modify this block. +COMPONENT_BK72XX = "bk72xx" +COMPONENT_RTL87XX = "rtl87xx" +# COMPONENTS - end + +# FAMILIES - auto-generated! Do not modify this block. +FAMILY_BK7231N = "BK7231N" +FAMILY_BK7231Q = "BK7231Q" +FAMILY_BK7231T = "BK7231T" +FAMILY_BK7251 = "BK7251" +FAMILY_RTL8710B = "RTL8710B" +FAMILY_RTL8720C = "RTL8720C" +FAMILIES = [ + FAMILY_BK7231N, + FAMILY_BK7231Q, + FAMILY_BK7231T, + FAMILY_BK7251, + FAMILY_RTL8710B, + FAMILY_RTL8720C, +] +FAMILY_FRIENDLY = { + FAMILY_BK7231N: "BK7231N", + FAMILY_BK7231Q: "BK7231Q", + FAMILY_BK7231T: "BK7231T", + FAMILY_BK7251: "BK7251", + FAMILY_RTL8710B: "RTL8710B", + FAMILY_RTL8720C: "RTL8720C", +} +FAMILY_COMPONENT = { + FAMILY_BK7231N: COMPONENT_BK72XX, + FAMILY_BK7231Q: COMPONENT_BK72XX, + FAMILY_BK7231T: COMPONENT_BK72XX, + FAMILY_BK7251: COMPONENT_BK72XX, + FAMILY_RTL8710B: COMPONENT_RTL87XX, + FAMILY_RTL8720C: COMPONENT_RTL87XX, +} +# FAMILIES - end + +libretiny_ns = cg.esphome_ns.namespace("libretiny") +LTComponent = libretiny_ns.class_("LTComponent", cg.PollingComponent) diff --git a/esphome/components/libretiny/core.cpp b/esphome/components/libretiny/core.cpp new file mode 100644 index 0000000000..b22740f02a --- /dev/null +++ b/esphome/components/libretiny/core.cpp @@ -0,0 +1,40 @@ +#ifdef USE_LIBRETINY + +#include "core.h" +#include "esphome/core/defines.h" +#include "esphome/core/hal.h" +#include "esphome/core/helpers.h" +#include "preferences.h" + +void setup(); +void loop(); + +namespace esphome { + +void IRAM_ATTR 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 IRAM_ATTR HOT delayMicroseconds(uint32_t us) { ::delayMicroseconds(us); } + +void arch_init() { + libretiny::setup_preferences(); + lt_wdt_enable(10000L); +#if LT_GPIO_RECOVER + lt_gpio_recover(); +#endif +} + +void arch_restart() { + lt_reboot(); + while (1) { + } +} +void IRAM_ATTR 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; } + +} // namespace esphome + +#endif // USE_LIBRETINY diff --git a/esphome/components/libretiny/core.h b/esphome/components/libretiny/core.h new file mode 100644 index 0000000000..9458df1f16 --- /dev/null +++ b/esphome/components/libretiny/core.h @@ -0,0 +1,11 @@ +#pragma once + +#ifdef USE_LIBRETINY + +#include + +namespace esphome { +namespace libretiny {} // namespace libretiny +} // namespace esphome + +#endif // USE_LIBRETINY diff --git a/esphome/components/libretiny/generate_components.py b/esphome/components/libretiny/generate_components.py new file mode 100644 index 0000000000..ae55fd9e40 --- /dev/null +++ b/esphome/components/libretiny/generate_components.py @@ -0,0 +1,329 @@ +# Copyright (c) Kuba Szczodrzyński 2023-06-01. + +# pylint: skip-file +# flake8: noqa + +import json +import re +from pathlib import Path + +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. + +from esphome import pins +from esphome.components import libretiny +from esphome.components.libretiny.const import ( + COMPONENT_{COMPONENT}, + KEY_COMPONENT_DATA, + KEY_LIBRETINY, + LibreTinyComponent, +) +from esphome.core import CORE + +{IMPORTS} + +CODEOWNERS = ["@kuba2k2"] +AUTO_LOAD = ["libretiny"] + +COMPONENT_DATA = LibreTinyComponent( + name=COMPONENT_{COMPONENT}, + boards={COMPONENT}_BOARDS, + board_pins={COMPONENT}_BOARD_PINS, + pin_validation={PIN_VALIDATION}, + usage_validation={USAGE_VALIDATION}, +) + + +def _set_core_data(config): + CORE.data[KEY_LIBRETINY] = {} + CORE.data[KEY_LIBRETINY][KEY_COMPONENT_DATA] = COMPONENT_DATA + return config + + +CONFIG_SCHEMA = {SCHEMA} + +PIN_SCHEMA = {PIN_SCHEMA} + +CONFIG_SCHEMA.prepend_extra(_set_core_data) + + +async def to_code(config): + return await libretiny.component_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. + +from esphome.components.libretiny.const import {FAMILIES} + +{COMPONENT}_BOARDS = {BOARDS_JSON} + +{COMPONENT}_BOARD_PINS = {PINS_JSON} + +BOARDS = {COMPONENT}_BOARDS +""" + +# variable names in component extension code +VAR_SCHEMA = "COMPONENT_SCHEMA" +VAR_PIN_SCHEMA = "COMPONENT_PIN_SCHEMA" +VAR_GPIO_PIN = "validate_pin" +VAR_GPIO_USAGE = "validate_usage" + +# lines for code snippets +SCHEMA_BASE = "libretiny.BASE_SCHEMA" +SCHEMA_EXTRA = f"libretiny.BASE_SCHEMA.extend({VAR_SCHEMA})" +PIN_SCHEMA_BASE = "libretiny.gpio.BASE_PIN_SCHEMA" +PIN_SCHEMA_EXTRA = f"libretiny.BASE_PIN_SCHEMA.extend({VAR_PIN_SCHEMA})" + +# supported root components +COMPONENT_MAP = { + "rtl87xx": "realtek-amb", + "bk72xx": "beken-72xx", +} + + +def subst(code: str, key: str, value: str) -> str: + return code.replace(f"{{{key}}}", value) + + +def subst_all(code: str, value: str) -> str: + return re.sub(r"{.+?}", value, code) + + +def subst_many(code: str, *templates: tuple[str, str]) -> str: + while True: + prev_code = code + for key, value in templates: + code = subst(code, key, value) + if code == prev_code: + break + return code + + +def check_base_code(code: str) -> None: + code = subst_all(code, "DUMMY") + formatted = format_str(code, mode=FileMode()) + if code.strip() != formatted.strip(): + print(formatted) + raise RuntimeError("Base code is not formatted properly") + + +def write_component_code( + component_dir: Path, + component: str, +) -> None: + code = BASE_CODE_INIT + gpio_py = component_dir.joinpath("gpio.py") + schema_py = component_dir.joinpath("schema.py") + init_py = component_dir.joinpath("__init__.py") + + # gather all imports + imports = { + "gpio": set(), + "schema": set(), + "boards": {"{COMPONENT}_BOARDS", "{COMPONENT}_BOARD_PINS"}, + } + # substitution values + values = dict( + COMPONENT=component.upper(), + COMPONENT_LOWER=component.lower(), + SCHEMA=SCHEMA_BASE, + PIN_SCHEMA=PIN_SCHEMA_BASE, + PIN_VALIDATION="None", + USAGE_VALIDATION="None", + ) + + # parse gpio.py file to find custom validators + if gpio_py.is_file(): + gpio_code = gpio_py.read_text() + if VAR_GPIO_PIN in gpio_code: + values["PIN_VALIDATION"] = VAR_GPIO_PIN + imports["gpio"].add(VAR_GPIO_PIN) + + # parse schema.py file to find schema extension + if schema_py.is_file(): + schema_code = schema_py.read_text() + if VAR_SCHEMA in schema_code: + values["SCHEMA"] = SCHEMA_EXTRA + imports["schema"].add(VAR_SCHEMA) + if VAR_PIN_SCHEMA in schema_code: + values["PIN_SCHEMA"] = PIN_SCHEMA_EXTRA + imports["schema"].add(VAR_PIN_SCHEMA) + + # add import lines if needed + import_lines = "\n".join( + f"from .{m} import {', '.join(sorted(v))}" for m, v in imports.items() if v + ) + code = subst_many( + code, + ("IMPORTS", import_lines), + *values.items(), + ) + # format with black + code = format_str(code, mode=FileMode()) + # write back to file + init_py.write_text(code) + + +def write_component_boards( + component_dir: Path, + component: str, + boards: list[Board], +) -> list[Family]: + code = BASE_CODE_BOARDS + variants_dir = Path(LVM.path(), "boards", "variants") + boards_py = component_dir.joinpath("boards.py") + pin_regex = r"#define PIN_(\w+)\s+(\d+)" + pin_number_regex = r"0*(\d+)$" + + # families to import + families = set() + # found root families + root_families = [] + # substitution values + values = dict( + COMPONENT=component.upper(), + ) + # resulting JSON objects + boards_json = {} + pins_json = {} + + # go through all boards found for this root family + for board in boards: + family = "FAMILY_" + board.family.short_name + boards_json[board.name] = { + "name": board.title, + "family": family, + } + families.add(family) + if board.family not in root_families: + root_families.append(board.family) + + board_h = variants_dir.joinpath(f"{board.name}.h") + board_code = board_h.read_text() + board_pins = {} + for match in re.finditer(pin_regex, board_code): + pin_name = match[1] + pin_value = match[2] + board_pins[pin_name] = int(pin_value) + # trim leading zeroes in GPIO numbers + pin_name = re.sub(pin_number_regex, r"\1", pin_name) + board_pins[pin_name] = int(pin_value) + pins_json[board.name] = board_pins + + # make the JSONs format as non-inline + boards_json = json.dumps(boards_json).replace("}", ",}") + pins_json = json.dumps(pins_json).replace("}", ",}") + # remove quotes from family constants + for family in families: + boards_json = boards_json.replace(f'"{family}"', family) + code = subst_many( + code, + ("FAMILIES", ", ".join(sorted(families))), + ("BOARDS_JSON", boards_json), + ("PINS_JSON", pins_json), + *values.items(), + ) + # format with black + code = format_str(code, mode=FileMode()) + # write back to file + boards_py.write_text(code) + return root_families + + +def write_const( + components_dir: Path, + components: set[str], + families: dict[str, str], +) -> None: + const_py = components_dir.joinpath("libretiny").joinpath("const.py") + if not const_py.is_file(): + raise FileNotFoundError(const_py) + code = const_py.read_text() + components = sorted(components) + v2f = families + families = sorted(families) + + # regex for finding the component list block + comp_regex = r"(# COMPONENTS.+?\n)(.*?)(\n# COMPONENTS)" + # build component constants + comp_str = "\n".join(f'COMPONENT_{f} = "{f.lower()}"' for f in components) + # replace the 2nd regex group only + repl = lambda m: m.group(1) + comp_str + m.group(3) + code = re.sub(comp_regex, repl, code, flags=re.DOTALL | re.MULTILINE) + + # regex for finding the family list block + fam_regex = r"(# FAMILIES.+?\n)(.*?)(\n# FAMILIES)" + # build family constants + fam_defs = "\n".join(f'FAMILY_{v} = "{v}"' for v in families) + fam_list = ", ".join(f"FAMILY_{v}" for v in families) + fam_friendly = ", ".join(f'FAMILY_{v}: "{v}"' for v in families) + fam_component = ", ".join(f"FAMILY_{v}: COMPONENT_{v2f[v]}" for v in families) + fam_lines = [ + fam_defs, + "FAMILIES = [", + fam_list, + ",]", + "FAMILY_FRIENDLY = {", + fam_friendly, + ",}", + "FAMILY_COMPONENT = {", + fam_component, + ",}", + ] + var_str = "\n".join(fam_lines) + # replace the 2nd regex group only + repl = lambda m: m.group(1) + var_str + m.group(3) + code = re.sub(fam_regex, repl, code, flags=re.DOTALL | re.MULTILINE) + + # format with black + code = format_str(code, mode=FileMode()) + # write back to file + const_py.write_text(code) + + +if __name__ == "__main__": + # safety check if code is properly formatted + check_base_code(BASE_CODE_INIT) + # list all boards from ltchiptool + components_dir = Path(__file__).parent.parent + boards = [Board(b) for b in Board.get_list()] + # keep track of all supported root- and chip-families + components = set() + families = {} + # loop through supported components + for component, family_name in COMPONENT_MAP.items(): + family = Family.get(name=family_name) + # make family component directory + component_dir = components_dir.joinpath(component) + component_dir.mkdir(exist_ok=True) + # filter boards list + family_boards = [b for b in boards if family in b.family.inheritance] + # write __init__.py + write_component_code(component_dir, component) + # write boards.py + component_families = write_component_boards( + component_dir, component, family_boards + ) + # store current root component name + components.add(component.upper()) + # add all chip families + for family in component_families: + families[family.short_name] = component.upper() + # update libretiny/const.py + write_const(components_dir, components, families) diff --git a/esphome/components/libretiny/gpio.py b/esphome/components/libretiny/gpio.py new file mode 100644 index 0000000000..ba9bfffcc9 --- /dev/null +++ b/esphome/components/libretiny/gpio.py @@ -0,0 +1,216 @@ +import logging + +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome import pins +from esphome.const import ( + CONF_ANALOG, + CONF_ID, + CONF_INPUT, + CONF_INVERTED, + CONF_MODE, + CONF_NUMBER, + CONF_OPEN_DRAIN, + CONF_OUTPUT, + CONF_PULLDOWN, + CONF_PULLUP, +) +from esphome.core import CORE + +from .const import ( + KEY_BOARD, + KEY_COMPONENT_DATA, + KEY_LIBRETINY, + LibreTinyComponent, + libretiny_ns, +) + +_LOGGER = logging.getLogger(__name__) + +ArduinoInternalGPIOPin = libretiny_ns.class_( + "ArduinoInternalGPIOPin", cg.InternalGPIOPin +) + + +def _is_name_deprecated(value): + return value[0] in "DA" and value[1:].isnumeric() + + +def _lookup_board_pins(board): + component: LibreTinyComponent = CORE.data[KEY_LIBRETINY][KEY_COMPONENT_DATA] + 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] + return board_pins + + +def _lookup_pin(value): + board: str = CORE.data[KEY_LIBRETINY][KEY_BOARD] + board_pins = _lookup_board_pins(board) + + # check numeric pin values + if isinstance(value, int): + if value in board_pins.values() or not board_pins: + # accept if pin number present in board pins + # if board is not found, just accept all numeric values + return value + raise cv.Invalid(f"Pin number '{value}' is not usable for board {board}.") + + # check textual pin names + if isinstance(value, str): + if not board_pins: + # can't remap without known pin name + raise cv.Invalid( + f"Board {board} wasn't found. " + f"Use 'GPIO#' (numeric value) instead of '{value}'." + ) + + if value in board_pins: + # pin name found, remap to numeric value + if _is_name_deprecated(value): + number = board_pins[value] + # find all alternative pin names (except the deprecated) + names = ( + k + for k, v in board_pins.items() + if v == number and not _is_name_deprecated(k) + ) + # sort by shortest + # favor P# or PA# names + names = sorted( + names, + key=lambda x: len(x) - 99 if x[0] == "P" else len(x), + ) + _LOGGER.warning( + "Using D# and A# pin numbering is deprecated. " + "Please replace '%s' with one of: %s", + value, + ", ".join(names), + ) + return board_pins[value] + + # pin name not found and not numeric + raise cv.Invalid(f"Cannot resolve pin name '{value}' for board {board}.") + + # unknown type of the value + raise cv.Invalid(f"Unrecognized pin value '{value}'.") + + +def _translate_pin(value): + if isinstance(value, dict) or value is None: + raise cv.Invalid( + "This variable only supports pin numbers, not full pin schemas " + "(with inverted and mode)." + ) + if isinstance(value, int): + return value + try: + return int(value) + except ValueError: + pass + # translate GPIO* and P* to a number, if possible + # otherwise return unchanged value (i.e. pin PA05) + try: + if value.startswith("GPIO"): + value = int(value[4:]) + elif value.startswith("P"): + value = int(value[1:]) + except ValueError: + pass + return value + + +def validate_gpio_pin(value): + value = _translate_pin(value) + value = _lookup_pin(value) + + component: LibreTinyComponent = CORE.data[KEY_LIBRETINY][KEY_COMPONENT_DATA] + if component.pin_validation: + value = component.pin_validation(value) + + return value + + +def validate_gpio_usage(value): + mode = value[CONF_MODE] + is_analog = mode[CONF_ANALOG] + is_input = mode[CONF_INPUT] + is_output = mode[CONF_OUTPUT] + is_open_drain = mode[CONF_OPEN_DRAIN] + is_pullup = mode[CONF_PULLUP] + is_pulldown = mode[CONF_PULLDOWN] + + if is_open_drain and not is_output: + raise cv.Invalid( + "Open-drain only works with output mode", [CONF_MODE, CONF_OPEN_DRAIN] + ) + if is_analog and not is_input: + raise cv.Invalid("Analog pins must be an input", [CONF_MODE, CONF_ANALOG]) + if is_analog: + # expect analog pin numbers to be available as either ADC# or A# + number = value[CONF_NUMBER] + board: str = CORE.data[KEY_LIBRETINY][KEY_BOARD] + board_pins = _lookup_board_pins(board) + analog_pins = [ + v + for k, v in board_pins.items() + if k[0] == "A" and k[1:].isnumeric() or k[0:3] == "ADC" + ] + if number not in analog_pins: + raise cv.Invalid( + f"Pin '{number}' is not an analog pin", [CONF_MODE, CONF_ANALOG] + ) + + # (input, output, open_drain, pullup, pulldown) + supported_modes = { + # INPUT + (True, False, False, False, False), + # OUTPUT + (False, True, False, False, False), + # INPUT_PULLUP + (True, False, False, True, False), + # INPUT_PULLDOWN + (True, False, False, False, True), + # OUTPUT_OPEN_DRAIN + (False, True, True, False, False), + } + key = (is_input, is_output, is_open_drain, is_pullup, is_pulldown) + if key not in supported_modes: + raise cv.Invalid("This pin mode is not supported", [CONF_MODE]) + + component: LibreTinyComponent = CORE.data[KEY_LIBRETINY][KEY_COMPONENT_DATA] + if component.usage_validation: + value = component.usage_validation(value) + + return value + + +BASE_PIN_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.declare_id(ArduinoInternalGPIOPin), + cv.Required(CONF_NUMBER): validate_gpio_pin, + cv.Optional(CONF_MODE, default={}): cv.Schema( + { + cv.Optional(CONF_ANALOG, default=False): cv.boolean, + cv.Optional(CONF_INPUT, default=False): cv.boolean, + cv.Optional(CONF_OUTPUT, default=False): cv.boolean, + cv.Optional(CONF_OPEN_DRAIN, default=False): cv.boolean, + cv.Optional(CONF_PULLUP, default=False): cv.boolean, + cv.Optional(CONF_PULLDOWN, default=False): cv.boolean, + } + ), + cv.Optional(CONF_INVERTED, default=False): cv.boolean, + }, +) + +BASE_PIN_SCHEMA.add_extra(validate_gpio_usage) + + +async def component_pin_to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + 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/libretiny/gpio_arduino.cpp b/esphome/components/libretiny/gpio_arduino.cpp new file mode 100644 index 0000000000..7a1e014ea4 --- /dev/null +++ b/esphome/components/libretiny/gpio_arduino.cpp @@ -0,0 +1,105 @@ +#ifdef USE_LIBRETINY + +#include "gpio_arduino.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace libretiny { + +static const char *const TAG = "lt.gpio"; + +static int IRAM_ATTR flags_to_mode(gpio::Flags flags) { + if (flags == gpio::FLAG_INPUT) { + return INPUT; + } else if (flags == gpio::FLAG_OUTPUT) { + return OUTPUT; + } else if (flags == (gpio::FLAG_INPUT | gpio::FLAG_PULLUP)) { + return INPUT_PULLUP; + } else if (flags == (gpio::FLAG_INPUT | gpio::FLAG_PULLDOWN)) { + return INPUT_PULLDOWN; + } else if (flags == (gpio::FLAG_OUTPUT | gpio::FLAG_OPEN_DRAIN)) { + return OUTPUT_OPEN_DRAIN; + } else { + return 0; + } +} + +struct ISRPinArg { + uint8_t pin; + bool inverted; +}; + +ISRInternalGPIOPin ArduinoInternalGPIOPin::to_isr() const { + auto *arg = new ISRPinArg{}; // NOLINT(cppcoreguidelines-owning-memory) + arg->pin = pin_; + arg->inverted = inverted_; + return ISRInternalGPIOPin((void *) arg); +} + +void ArduinoInternalGPIOPin::attach_interrupt(void (*func)(void *), void *arg, gpio::InterruptType type) const { + PinStatus arduino_mode = (PinStatus) 255; + switch (type) { + case gpio::INTERRUPT_RISING_EDGE: + arduino_mode = inverted_ ? FALLING : RISING; + break; + case gpio::INTERRUPT_FALLING_EDGE: + arduino_mode = inverted_ ? RISING : FALLING; + break; + case gpio::INTERRUPT_ANY_EDGE: + arduino_mode = CHANGE; + break; + case gpio::INTERRUPT_LOW_LEVEL: + arduino_mode = inverted_ ? HIGH : LOW; + break; + case gpio::INTERRUPT_HIGH_LEVEL: + arduino_mode = inverted_ ? LOW : HIGH; + break; + } + + attachInterruptParam(pin_, func, arduino_mode, arg); +} + +void ArduinoInternalGPIOPin::pin_mode(gpio::Flags flags) { + pinMode(pin_, flags_to_mode(flags)); // NOLINT +} + +std::string ArduinoInternalGPIOPin::dump_summary() const { + char buffer[32]; + snprintf(buffer, sizeof(buffer), "%u", pin_); + return buffer; +} + +bool ArduinoInternalGPIOPin::digital_read() { + return bool(digitalRead(pin_)) ^ inverted_; // NOLINT +} +void ArduinoInternalGPIOPin::digital_write(bool value) { + digitalWrite(pin_, value ^ inverted_); // NOLINT +} +void ArduinoInternalGPIOPin::detach_interrupt() const { + detachInterrupt(pin_); // NOLINT +} + +} // namespace libretiny + +using namespace libretiny; + +bool IRAM_ATTR ISRInternalGPIOPin::digital_read() { + auto *arg = reinterpret_cast(arg_); + return bool(digitalRead(arg->pin)) ^ arg->inverted; // NOLINT +} +void IRAM_ATTR ISRInternalGPIOPin::digital_write(bool value) { + auto *arg = reinterpret_cast(arg_); + digitalWrite(arg->pin, value ^ arg->inverted); // NOLINT +} +void IRAM_ATTR ISRInternalGPIOPin::clear_interrupt() { + auto *arg = reinterpret_cast(arg_); + detachInterrupt(arg->pin); +} +void IRAM_ATTR ISRInternalGPIOPin::pin_mode(gpio::Flags flags) { + auto *arg = reinterpret_cast(arg_); + pinMode(arg->pin, flags_to_mode(flags)); // NOLINT +} + +} // namespace esphome + +#endif // USE_LIBRETINY diff --git a/esphome/components/libretiny/gpio_arduino.h b/esphome/components/libretiny/gpio_arduino.h new file mode 100644 index 0000000000..a43ed28c5e --- /dev/null +++ b/esphome/components/libretiny/gpio_arduino.h @@ -0,0 +1,36 @@ +#pragma once + +#ifdef USE_LIBRETINY +#include "esphome/core/hal.h" + +namespace esphome { +namespace libretiny { + +class ArduinoInternalGPIOPin : public InternalGPIOPin { + public: + void set_pin(uint8_t pin) { pin_ = pin; } + void set_inverted(bool inverted) { inverted_ = inverted; } + void set_flags(gpio::Flags flags) { flags_ = flags; } + + void setup() override { pin_mode(flags_); } + void pin_mode(gpio::Flags flags) override; + bool digital_read() override; + void digital_write(bool value) override; + std::string dump_summary() const override; + void detach_interrupt() const override; + ISRInternalGPIOPin to_isr() const override; + uint8_t get_pin() const override { return pin_; } + bool is_inverted() const override { return inverted_; } + + protected: + void attach_interrupt(void (*func)(void *), void *arg, gpio::InterruptType type) const override; + + uint8_t pin_; + bool inverted_; + gpio::Flags flags_; +}; + +} // namespace libretiny +} // namespace esphome + +#endif // USE_LIBRETINY diff --git a/esphome/components/libretiny/lt_component.cpp b/esphome/components/libretiny/lt_component.cpp new file mode 100644 index 0000000000..ec4b60eaeb --- /dev/null +++ b/esphome/components/libretiny/lt_component.cpp @@ -0,0 +1,29 @@ +#include "lt_component.h" + +#ifdef USE_LIBRETINY + +#include "esphome/core/log.h" + +namespace esphome { +namespace libretiny { + +static const char *const TAG = "lt.component"; + +void LTComponent::dump_config() { + ESP_LOGCONFIG(TAG, "LibreTiny:"); + ESP_LOGCONFIG(TAG, " Version: %s", LT_BANNER_STR + 10); + ESP_LOGCONFIG(TAG, " Loglevel: %u", LT_LOGLEVEL); + +#ifdef USE_TEXT_SENSOR + if (this->version_ != nullptr) { + this->version_->publish_state(LT_BANNER_STR + 10); + } +#endif // USE_TEXT_SENSOR +} + +float LTComponent::get_setup_priority() const { return setup_priority::LATE; } + +} // namespace libretiny +} // namespace esphome + +#endif // USE_LIBRETINY diff --git a/esphome/components/libretiny/lt_component.h b/esphome/components/libretiny/lt_component.h new file mode 100644 index 0000000000..3d4483ab5d --- /dev/null +++ b/esphome/components/libretiny/lt_component.h @@ -0,0 +1,36 @@ +#pragma once + +#ifdef USE_LIBRETINY + +#include "esphome/core/component.h" +#include "esphome/core/defines.h" + +#ifdef USE_SENSOR +#include "esphome/components/sensor/sensor.h" +#endif +#ifdef USE_TEXT_SENSOR +#include "esphome/components/text_sensor/text_sensor.h" +#endif + +namespace esphome { +namespace libretiny { + +class LTComponent : public Component { + public: + float get_setup_priority() const override; + void dump_config() override; + +#ifdef USE_TEXT_SENSOR + void set_version_sensor(text_sensor::TextSensor *version) { version_ = version; } +#endif // USE_TEXT_SENSOR + + protected: +#ifdef USE_TEXT_SENSOR + text_sensor::TextSensor *version_{nullptr}; +#endif // USE_TEXT_SENSOR +}; + +} // namespace libretiny +} // namespace esphome + +#endif // USE_LIBRETINY diff --git a/esphome/components/libretiny/preferences.cpp b/esphome/components/libretiny/preferences.cpp new file mode 100644 index 0000000000..ceeb30baf5 --- /dev/null +++ b/esphome/components/libretiny/preferences.cpp @@ -0,0 +1,182 @@ +#ifdef USE_LIBRETINY + +#include "esphome/core/preferences.h" +#include "esphome/core/helpers.h" +#include "esphome/core/log.h" +#include +#include +#include +#include + +namespace esphome { +namespace libretiny { + +static const char *const TAG = "lt.preferences"; + +struct NVSData { + std::string key; + std::vector data; +}; + +static std::vector s_pending_save; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + +class LibreTinyPreferenceBackend : public ESPPreferenceBackend { + public: + std::string key; + fdb_kvdb_t db; + fdb_blob_t blob; + + 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 == key) { + obj.data.assign(data, data + len); + return true; + } + } + NVSData save{}; + save.key = key; + save.data.assign(data, data + len); + s_pending_save.emplace_back(save); + ESP_LOGVV(TAG, "s_pending_save: key: %s, len: %d", key.c_str(), 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 == key) { + if (obj.data.size() != len) { + // size mismatch + return false; + } + memcpy(data, obj.data.data(), len); + return true; + } + } + + fdb_blob_make(blob, data, len); + size_t actual_len = fdb_kv_get_blob(db, key.c_str(), blob); + if (actual_len != len) { + ESP_LOGVV(TAG, "NVS length does not match (%u!=%u)", actual_len, len); + return false; + } else { + ESP_LOGVV(TAG, "fdb_kv_get_blob: key: %s, len: %d", key.c_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 make_preference(length, type); + } + + ESPPreferenceObject make_preference(size_t length, uint32_t type) override { + auto *pref = new LibreTinyPreferenceBackend(); // NOLINT(cppcoreguidelines-owning-memory) + pref->db = &db; + pref->blob = &blob; + + uint32_t keyval = type; + pref->key = str_sprintf("%u", keyval); + + return ESPPreferenceObject(pref); + } + + bool sync() override { + if (s_pending_save.empty()) + return true; + + ESP_LOGD(TAG, "Saving %d preferences to flash...", 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; + std::string last_key{}; + + // 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]; + ESP_LOGVV(TAG, "Checking if FDB data %s has changed", save.key.c_str()); + if (is_changed(&db, save)) { + ESP_LOGV(TAG, "sync: key: %s, len: %d", save.key.c_str(), save.data.size()); + fdb_blob_make(&blob, save.data.data(), save.data.size()); + fdb_err_t err = fdb_kv_set_blob(&db, save.key.c_str(), &blob); + if (err != FDB_NO_ERR) { + ESP_LOGV(TAG, "fdb_kv_set_blob('%s', len=%u) failed: %d", save.key.c_str(), save.data.size(), err); + failed++; + last_err = err; + last_key = save.key; + continue; + } + written++; + } else { + ESP_LOGD(TAG, "FDB data not changed; skipping %s len=%u", save.key.c_str(), save.data.size()); + cached++; + } + s_pending_save.erase(s_pending_save.begin() + i); + } + ESP_LOGD(TAG, "Saving %d preferences to flash: %d cached, %d written, %d failed", cached + written + failed, cached, + written, failed); + if (failed > 0) { + ESP_LOGE(TAG, "Error saving %d preferences to flash. Last error=%d for key=%s", failed, last_err, + last_key.c_str()); + } + + return failed == 0; + } + + bool is_changed(const fdb_kvdb_t db, const NVSData &to_save) { + NVSData stored_data{}; + struct fdb_kv kv; + fdb_kv_t kvp = fdb_kv_get_obj(db, to_save.key.c_str(), &kv); + if (kvp == nullptr) { + ESP_LOGV(TAG, "fdb_kv_get_obj('%s'): nullptr - the key might not be set yet", to_save.key.c_str()); + return true; + } + stored_data.data.reserve(kv.value_len); + fdb_blob_make(&blob, stored_data.data.data(), kv.value_len); + size_t actual_len = fdb_kv_get_blob(db, to_save.key.c_str(), &blob); + if (actual_len != kv.value_len) { + ESP_LOGV(TAG, "fdb_kv_get_blob('%s') len mismatch: %u != %u", to_save.key.c_str(), actual_len, kv.value_len); + return true; + } + return to_save.data != stored_data.data; + } + + bool reset() override { + ESP_LOGD(TAG, "Cleaning up preferences in flash..."); + s_pending_save.clear(); + + fdb_kv_set_default(&db); + fdb_kvdb_deinit(&db); + return true; + } +}; + +void setup_preferences() { + auto *prefs = new LibreTinyPreferences(); // NOLINT(cppcoreguidelines-owning-memory) + prefs->open(); + global_preferences = prefs; +} + +} // namespace libretiny + +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 new file mode 100644 index 0000000000..8ec3cd31b1 --- /dev/null +++ b/esphome/components/libretiny/preferences.h @@ -0,0 +1,13 @@ +#pragma once + +#ifdef USE_LIBRETINY + +namespace esphome { +namespace libretiny { + +void setup_preferences(); + +} // namespace libretiny +} // namespace esphome + +#endif // USE_LIBRETINY diff --git a/esphome/components/libretiny/text_sensor.py b/esphome/components/libretiny/text_sensor.py new file mode 100644 index 0000000000..df10ee7229 --- /dev/null +++ b/esphome/components/libretiny/text_sensor.py @@ -0,0 +1,31 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import text_sensor +from esphome.const import ( + CONF_VERSION, + ENTITY_CATEGORY_DIAGNOSTIC, + ICON_CELLPHONE_ARROW_DOWN, +) + +from .const import CONF_LIBRETINY, LTComponent + +DEPENDENCIES = ["libretiny"] + + +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(CONF_LIBRETINY): cv.use_id(LTComponent), + cv.Optional(CONF_VERSION): text_sensor.text_sensor_schema( + icon=ICON_CELLPHONE_ARROW_DOWN, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + ), + } +) + + +async def to_code(config): + lt_component = await cg.get_variable(config[CONF_LIBRETINY]) + + if CONF_VERSION in config: + sens = await text_sensor.new_text_sensor(config[CONF_VERSION]) + cg.add(lt_component.set_version_sensor(sens)) diff --git a/esphome/components/libretiny_pwm/__init__.py b/esphome/components/libretiny_pwm/__init__.py new file mode 100644 index 0000000000..4db724f8ad --- /dev/null +++ b/esphome/components/libretiny_pwm/__init__.py @@ -0,0 +1 @@ +CODEOWNERS = ["@kuba2k2"] diff --git a/esphome/components/libretiny_pwm/libretiny_pwm.cpp b/esphome/components/libretiny_pwm/libretiny_pwm.cpp new file mode 100644 index 0000000000..92e4097c0e --- /dev/null +++ b/esphome/components/libretiny_pwm/libretiny_pwm.cpp @@ -0,0 +1,53 @@ +#include "libretiny_pwm.h" +#include "esphome/core/log.h" + +#ifdef USE_LIBRETINY + +namespace esphome { +namespace libretiny_pwm { + +static const char *const TAG = "libretiny.pwm"; + +void LibreTinyPWM::write_state(float state) { + if (!this->initialized_) { + ESP_LOGW(TAG, "LibreTinyPWM output hasn't been initialized yet!"); + return; + } + + if (this->pin_->is_inverted()) + state = 1.0f - state; + + this->duty_ = 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(duty_rounded); + + analogWrite(this->pin_->get_pin(), duty); // NOLINT +} + +void LibreTinyPWM::setup() { + this->update_frequency(this->frequency_); + this->turn_off(); +} + +void LibreTinyPWM::dump_config() { + ESP_LOGCONFIG(TAG, "PWM Output:"); + LOG_PIN(" Pin ", this->pin_); + ESP_LOGCONFIG(TAG, " Frequency: %.1f Hz", this->frequency_); +} + +void LibreTinyPWM::update_frequency(float frequency) { + this->frequency_ = frequency; + // force changing the frequency by removing PWM mode + this->pin_->pin_mode(gpio::FLAG_INPUT); + analogWriteResolution(this->bit_depth_); // NOLINT + analogWriteFrequency(frequency); // NOLINT + this->initialized_ = true; + // re-apply duty + this->write_state(this->duty_); +} + +} // namespace libretiny_pwm +} // namespace esphome + +#endif diff --git a/esphome/components/libretiny_pwm/libretiny_pwm.h b/esphome/components/libretiny_pwm/libretiny_pwm.h new file mode 100644 index 0000000000..42ce40ca39 --- /dev/null +++ b/esphome/components/libretiny_pwm/libretiny_pwm.h @@ -0,0 +1,55 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/core/hal.h" +#include "esphome/core/automation.h" +#include "esphome/components/output/float_output.h" + +#ifdef USE_LIBRETINY + +namespace esphome { +namespace libretiny_pwm { + +class LibreTinyPWM : public output::FloatOutput, public Component { + public: + explicit LibreTinyPWM(InternalGPIOPin *pin) : pin_(pin) {} + + void set_frequency(float frequency) { this->frequency_ = frequency; } + /// Dynamically change frequency at runtime + void update_frequency(float frequency) override; + + /// Setup LibreTinyPWM. + void setup() override; + void dump_config() override; + /// HARDWARE setup priority + float get_setup_priority() const override { return setup_priority::HARDWARE; } + + /// Override FloatOutput's write_state. + void write_state(float state) override; + + protected: + InternalGPIOPin *pin_; + uint8_t bit_depth_{10}; + float frequency_{}; + float duty_{0.0f}; + bool initialized_ = false; +}; + +template class SetFrequencyAction : public Action { + public: + SetFrequencyAction(LibreTinyPWM *parent) : parent_(parent) {} + TEMPLATABLE_VALUE(float, frequency); + + void play(Ts... x) { + float freq = this->frequency_.value(x...); + this->parent_->update_frequency(freq); + } + + protected: + LibreTinyPWM *parent_; +}; + +} // namespace libretiny_pwm +} // namespace esphome + +#endif diff --git a/esphome/components/libretiny_pwm/output.py b/esphome/components/libretiny_pwm/output.py new file mode 100644 index 0000000000..e74bc8f129 --- /dev/null +++ b/esphome/components/libretiny_pwm/output.py @@ -0,0 +1,49 @@ +from esphome import pins, automation +from esphome.components import output +import esphome.config_validation as cv +import esphome.codegen as cg +from esphome.const import ( + CONF_FREQUENCY, + CONF_ID, + CONF_PIN, +) + +DEPENDENCIES = ["libretiny"] + +libretinypwm_ns = cg.esphome_ns.namespace("libretiny_pwm") +LibreTinyPWM = libretinypwm_ns.class_("LibreTinyPWM", output.FloatOutput, cg.Component) +SetFrequencyAction = libretinypwm_ns.class_("SetFrequencyAction", automation.Action) + +CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend( + { + cv.Required(CONF_ID): cv.declare_id(LibreTinyPWM), + cv.Required(CONF_PIN): pins.internal_gpio_output_pin_schema, + cv.Optional(CONF_FREQUENCY, default="1kHz"): cv.frequency, + } +).extend(cv.COMPONENT_SCHEMA) + + +async def to_code(config): + gpio = await cg.gpio_pin_expression(config[CONF_PIN]) + var = cg.new_Pvariable(config[CONF_ID], gpio) + await cg.register_component(var, config) + await output.register_output(var, config) + cg.add(var.set_frequency(config[CONF_FREQUENCY])) + + +@automation.register_action( + "output.libretiny_pwm.set_frequency", + SetFrequencyAction, + cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(LibreTinyPWM), + cv.Required(CONF_FREQUENCY): cv.templatable(cv.int_), + } + ), +) +async def libretiny_pwm_set_frequency_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_FREQUENCY], args, float) + cg.add(var.set_frequency(template_)) + return var diff --git a/esphome/components/logger/__init__.py b/esphome/components/logger/__init__.py index 5c87bb9d91..5225a227ec 100644 --- a/esphome/components/logger/__init__.py +++ b/esphome/components/logger/__init__.py @@ -17,6 +17,8 @@ from esphome.const import ( CONF_TAG, CONF_TRIGGER_ID, CONF_TX_BUFFER_SIZE, + PLATFORM_BK72XX, + PLATFORM_RTL87XX, PLATFORM_ESP32, PLATFORM_ESP8266, PLATFORM_RP2040, @@ -31,6 +33,11 @@ from esphome.components.esp32.const import ( VARIANT_ESP32C2, VARIANT_ESP32C6, ) +from esphome.components.libretiny import get_libretiny_component, get_libretiny_family +from esphome.components.libretiny.const import ( + COMPONENT_BK72XX, + COMPONENT_RTL87XX, +) CODEOWNERS = ["@esphome/core"] logger_ns = cg.esphome_ns.namespace("logger") @@ -70,6 +77,7 @@ UART2 = "UART2" UART0_SWAP = "UART0_SWAP" USB_SERIAL_JTAG = "USB_SERIAL_JTAG" USB_CDC = "USB_CDC" +DEFAULT = "DEFAULT" UART_SELECTION_ESP32 = { VARIANT_ESP32: [UART0, UART1, UART2], @@ -82,6 +90,11 @@ UART_SELECTION_ESP32 = { UART_SELECTION_ESP8266 = [UART0, UART0_SWAP, UART1] +UART_SELECTION_LIBRETINY = { + COMPONENT_BK72XX: [DEFAULT, UART1, UART2], + COMPONENT_RTL87XX: [DEFAULT, UART0, UART1, UART2], +} + ESP_IDF_UARTS = [USB_CDC, USB_SERIAL_JTAG] UART_SELECTION_RP2040 = [USB_CDC, UART0, UART1] @@ -93,6 +106,7 @@ HARDWARE_UART_TO_UART_SELECTION = { UART2: logger_ns.UART_SELECTION_UART2, USB_CDC: logger_ns.UART_SELECTION_USB_CDC, USB_SERIAL_JTAG: logger_ns.UART_SELECTION_USB_SERIAL_JTAG, + DEFAULT: logger_ns.UART_SELECTION_DEFAULT, } HARDWARE_UART_TO_SERIAL = { @@ -100,6 +114,7 @@ HARDWARE_UART_TO_SERIAL = { UART0_SWAP: cg.global_ns.Serial, UART1: cg.global_ns.Serial1, UART2: cg.global_ns.Serial2, + DEFAULT: cg.global_ns.Serial, } is_log_level = cv.one_of(*LOG_LEVELS, upper=True) @@ -116,6 +131,13 @@ def uart_selection(value): return cv.one_of(*UART_SELECTION_ESP8266, upper=True)(value) if CORE.is_rp2040: return cv.one_of(*UART_SELECTION_RP2040, upper=True)(value) + if CORE.is_libretiny: + family = get_libretiny_family() + if family in UART_SELECTION_LIBRETINY: + return cv.one_of(*UART_SELECTION_LIBRETINY[family], upper=True)(value) + component = get_libretiny_component() + if component in UART_SELECTION_LIBRETINY: + return cv.one_of(*UART_SELECTION_LIBRETINY[component], upper=True)(value) raise NotImplementedError @@ -148,8 +170,18 @@ CONFIG_SCHEMA = cv.All( esp8266=UART0, esp32=UART0, rp2040=USB_CDC, + bk72xx=DEFAULT, + rtl87xx=DEFAULT, ): cv.All( - cv.only_on([PLATFORM_ESP8266, PLATFORM_ESP32, PLATFORM_RP2040]), + cv.only_on( + [ + PLATFORM_ESP8266, + PLATFORM_ESP32, + PLATFORM_RP2040, + PLATFORM_BK72XX, + PLATFORM_RTL87XX, + ] + ), uart_selection, ), cv.Optional(CONF_LEVEL, default="DEBUG"): is_log_level, diff --git a/esphome/components/logger/logger.cpp b/esphome/components/logger/logger.cpp index 758e9c1f98..df4662024f 100644 --- a/esphome/components/logger/logger.cpp +++ b/esphome/components/logger/logger.cpp @@ -158,6 +158,7 @@ Logger::Logger(uint32_t baud_rate, size_t tx_buffer_size) : baud_rate_(baud_rate this->tx_buffer_ = new char[this->tx_buffer_size_ + 1]; // NOLINT } +#ifndef USE_LIBRETINY void Logger::pre_setup() { if (this->baud_rate_ > 0) { #ifdef USE_ARDUINO @@ -266,12 +267,58 @@ void Logger::pre_setup() { ESP_LOGI(TAG, "Log initialized"); } +#else // USE_LIBRETINY +void Logger::pre_setup() { + if (this->baud_rate_ > 0) { + switch (this->uart_) { +#if LT_HW_UART0 + case UART_SELECTION_UART0: + this->hw_serial_ = &Serial0; + Serial0.begin(this->baud_rate_); + break; +#endif +#if LT_HW_UART1 + case UART_SELECTION_UART1: + this->hw_serial_ = &Serial1; + Serial1.begin(this->baud_rate_); + break; +#endif +#if LT_HW_UART2 + case UART_SELECTION_UART2: + this->hw_serial_ = &Serial2; + Serial2.begin(this->baud_rate_); + break; +#endif + default: + this->hw_serial_ = &Serial; + Serial.begin(this->baud_rate_); + if (this->uart_ != UART_SELECTION_DEFAULT) { + ESP_LOGW(TAG, " The chosen logger UART port is not available on this board." + "The default port was used instead."); + } + break; + } + + // change lt_log() port to match default Serial + if (this->uart_ == UART_SELECTION_DEFAULT) { + this->uart_ = (UARTSelection) (LT_UART_DEFAULT_SERIAL + 1); + lt_log_set_port(LT_UART_DEFAULT_SERIAL); + } else { + lt_log_set_port(this->uart_ - 1); + } + } + + global_logger = this; + ESP_LOGI(TAG, "Log initialized"); +} +#endif // USE_LIBRETINY + void Logger::set_baud_rate(uint32_t baud_rate) { this->baud_rate_ = baud_rate; } void Logger::set_log_level(const std::string &tag, int log_level) { this->log_levels_.push_back(LogLevelOverride{tag, log_level}); } -#if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) +#if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) || defined(USE_LIBRETINY) UARTSelection Logger::get_uart() const { return this->uart_; } #endif @@ -299,15 +346,18 @@ const char *const UART_SELECTIONS[] = { #endif // USE_ESP32 #ifdef USE_ESP8266 const char *const UART_SELECTIONS[] = {"UART0", "UART1", "UART0_SWAP"}; -#endif +#endif // USE_ESP8266 #ifdef USE_RP2040 const char *const UART_SELECTIONS[] = {"UART0", "UART1", "USB_CDC"}; -#endif // USE_ESP8266 +#endif // USE_RP2040 +#ifdef USE_LIBRETINY +const char *const UART_SELECTIONS[] = {"DEFAULT", "UART0", "UART1", "UART2"}; +#endif // USE_LIBRETINY void Logger::dump_config() { ESP_LOGCONFIG(TAG, "Logger:"); ESP_LOGCONFIG(TAG, " Level: %s", LOG_LEVELS[ESPHOME_LOG_LEVEL]); ESP_LOGCONFIG(TAG, " Log Baud Rate: %" PRIu32, this->baud_rate_); -#if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) +#if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) || defined(USE_LIBRETINY) ESP_LOGCONFIG(TAG, " Hardware UART: %s", UART_SELECTIONS[this->uart_]); #endif diff --git a/esphome/components/logger/logger.h b/esphome/components/logger/logger.h index 47cde45c29..4a7a43c7c2 100644 --- a/esphome/components/logger/logger.h +++ b/esphome/components/logger/logger.h @@ -25,12 +25,18 @@ namespace esphome { namespace logger { -#if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) +#if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) || defined(USE_LIBRETINY) /** Enum for logging UART selection * * Advanced configuration (pin selection, etc) is not supported. */ enum UARTSelection { +#ifdef USE_LIBRETINY + UART_SELECTION_DEFAULT = 0, + UART_SELECTION_UART0, + UART_SELECTION_UART1, + UART_SELECTION_UART2, +#else UART_SELECTION_UART0 = 0, UART_SELECTION_UART1, #if defined(USE_ESP32) @@ -53,8 +59,9 @@ enum UARTSelection { #ifdef USE_RP2040 UART_SELECTION_USB_CDC, #endif // USE_RP2040 +#endif // USE_LIBRETINY }; -#endif // USE_ESP32 || USE_ESP8266 +#endif // USE_ESP32 || USE_ESP8266 || USE_RP2040 || USE_LIBRETINY class Logger : public Component { public: @@ -69,7 +76,7 @@ class Logger : public Component { #ifdef USE_ESP_IDF uart_port_t get_uart_num() const { return uart_num_; } #endif -#if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) +#if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) || defined(USE_LIBRETINY) void set_uart_selection(UARTSelection uart_selection) { uart_ = uart_selection; } /// Get the UART used by the logger. UARTSelection get_uart() const; @@ -146,6 +153,9 @@ class Logger : public Component { #if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) UARTSelection uart_{UART_SELECTION_UART0}; #endif +#ifdef USE_LIBRETINY + UARTSelection uart_{UART_SELECTION_DEFAULT}; +#endif #ifdef USE_ARDUINO Stream *hw_serial_{nullptr}; #endif diff --git a/esphome/components/md5/md5.h b/esphome/components/md5/md5.h index 738a312267..4ec8a8a12c 100644 --- a/esphome/components/md5/md5.h +++ b/esphome/components/md5/md5.h @@ -22,6 +22,11 @@ #define MD5_CTX_TYPE br_md5_context #endif +#if defined(USE_LIBRETINY) +#include +#define MD5_CTX_TYPE LT_MD5_CTX_T +#endif + namespace esphome { namespace md5 { diff --git a/esphome/components/mdns/mdns_component.cpp b/esphome/components/mdns/mdns_component.cpp index 581758cf2d..e2e562670b 100644 --- a/esphome/components/mdns/mdns_component.cpp +++ b/esphome/components/mdns/mdns_component.cpp @@ -44,6 +44,9 @@ void MDNSComponent::compile_records_() { #endif #ifdef USE_RP2040 platform = "RP2040"; +#endif +#ifdef USE_LIBRETINY + platform = lt_cpu_get_model_name(); #endif if (platform != nullptr) { service.txt_records.push_back({"platform", platform}); diff --git a/esphome/components/mdns/mdns_libretiny.cpp b/esphome/components/mdns/mdns_libretiny.cpp new file mode 100644 index 0000000000..ccb79c88b9 --- /dev/null +++ b/esphome/components/mdns/mdns_libretiny.cpp @@ -0,0 +1,43 @@ +#ifdef USE_LIBRETINY + +#include "esphome/components/network/ip_address.h" +#include "esphome/components/network/util.h" +#include "esphome/core/log.h" +#include "mdns_component.h" + +#include + +namespace esphome { +namespace mdns { + +void MDNSComponent::setup() { + this->compile_records_(); + + MDNS.begin(this->hostname_.c_str()); + + for (const auto &service : this->services_) { + // Strip the leading underscore from the proto and service_type. While it is + // part of the wire protocol to have an underscore, and for example ESP-IDF + // expects the underscore to be there, the ESP8266 implementation always adds + // the underscore itself. + auto *proto = service.proto.c_str(); + while (*proto == '_') { + proto++; + } + auto *service_type = service.service_type.c_str(); + while (*service_type == '_') { + service_type++; + } + MDNS.addService(service_type, proto, service.port); + for (const auto &record : service.txt_records) { + MDNS.addServiceTxt(service_type, proto, record.key.c_str(), record.value.c_str()); + } + } +} + +void MDNSComponent::on_shutdown() {} + +} // namespace mdns +} // namespace esphome + +#endif diff --git a/esphome/components/ota/__init__.py b/esphome/components/ota/__init__.py index a966157ffa..eb2a83272d 100644 --- a/esphome/components/ota/__init__.py +++ b/esphome/components/ota/__init__.py @@ -41,7 +41,14 @@ CONFIG_SCHEMA = cv.Schema( { cv.GenerateID(): cv.declare_id(OTAComponent), cv.Optional(CONF_SAFE_MODE, default=True): cv.boolean, - cv.SplitDefault(CONF_PORT, esp8266=8266, esp32=3232, rp2040=2040): cv.port, + cv.SplitDefault( + CONF_PORT, + esp8266=8266, + esp32=3232, + rp2040=2040, + bk72xx=8892, + rtl87xx=8892, + ): cv.port, cv.Optional(CONF_PASSWORD): cv.string, cv.Optional( CONF_REBOOT_TIMEOUT, default="5min" diff --git a/esphome/components/ota/ota_backend_arduino_libretiny.cpp b/esphome/components/ota/ota_backend_arduino_libretiny.cpp new file mode 100644 index 0000000000..dbf6c97988 --- /dev/null +++ b/esphome/components/ota/ota_backend_arduino_libretiny.cpp @@ -0,0 +1,46 @@ +#include "esphome/core/defines.h" +#ifdef USE_LIBRETINY + +#include "ota_backend_arduino_libretiny.h" +#include "ota_component.h" +#include "ota_backend.h" + +#include + +namespace esphome { +namespace ota { + +OTAResponseTypes ArduinoLibreTinyOTABackend::begin(size_t image_size) { + bool ret = Update.begin(image_size, U_FLASH); + if (ret) { + return OTA_RESPONSE_OK; + } + + uint8_t error = Update.getError(); + if (error == UPDATE_ERROR_SIZE) + return OTA_RESPONSE_ERROR_ESP32_NOT_ENOUGH_SPACE; + return OTA_RESPONSE_ERROR_UNKNOWN; +} + +void ArduinoLibreTinyOTABackend::set_update_md5(const char *md5) { Update.setMD5(md5); } + +OTAResponseTypes ArduinoLibreTinyOTABackend::write(uint8_t *data, size_t len) { + size_t written = Update.write(data, len); + if (written != len) { + return OTA_RESPONSE_ERROR_WRITING_FLASH; + } + return OTA_RESPONSE_OK; +} + +OTAResponseTypes ArduinoLibreTinyOTABackend::end() { + if (!Update.end()) + return OTA_RESPONSE_ERROR_UPDATE_END; + return OTA_RESPONSE_OK; +} + +void ArduinoLibreTinyOTABackend::abort() { Update.abort(); } + +} // namespace ota +} // namespace esphome + +#endif // USE_LIBRETINY diff --git a/esphome/components/ota/ota_backend_arduino_libretiny.h b/esphome/components/ota/ota_backend_arduino_libretiny.h new file mode 100644 index 0000000000..79656bb353 --- /dev/null +++ b/esphome/components/ota/ota_backend_arduino_libretiny.h @@ -0,0 +1,24 @@ +#pragma once +#include "esphome/core/defines.h" +#ifdef USE_LIBRETINY + +#include "ota_component.h" +#include "ota_backend.h" + +namespace esphome { +namespace ota { + +class ArduinoLibreTinyOTABackend : public OTABackend { + 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; } +}; + +} // namespace ota +} // namespace esphome + +#endif // USE_LIBRETINY diff --git a/esphome/components/ota/ota_component.cpp b/esphome/components/ota/ota_component.cpp index acf9e923b6..41cf333be9 100644 --- a/esphome/components/ota/ota_component.cpp +++ b/esphome/components/ota/ota_component.cpp @@ -3,6 +3,7 @@ #include "ota_backend_arduino_esp32.h" #include "ota_backend_arduino_esp8266.h" #include "ota_backend_arduino_rp2040.h" +#include "ota_backend_arduino_libretiny.h" #include "ota_backend_esp_idf.h" #include "esphome/core/log.h" @@ -39,6 +40,9 @@ std::unique_ptr make_ota_backend() { #ifdef USE_RP2040 return make_unique(); #endif // USE_RP2040 +#ifdef USE_LIBRETINY + return make_unique(); +#endif } OTAComponent::OTAComponent() { global_ota_component = this; } diff --git a/esphome/components/remote_receiver/__init__.py b/esphome/components/remote_receiver/__init__.py index d59ad5c7f1..5737957adb 100644 --- a/esphome/components/remote_receiver/__init__.py +++ b/esphome/components/remote_receiver/__init__.py @@ -31,7 +31,11 @@ CONFIG_SCHEMA = remote_base.validate_triggers( cv.percentage_int, cv.Range(min=0) ), cv.SplitDefault( - CONF_BUFFER_SIZE, esp32="10000b", esp8266="1000b" + CONF_BUFFER_SIZE, + esp32="10000b", + esp8266="1000b", + bk72xx="1000b", + rtl87xx="1000b", ): cv.validate_bytes, cv.Optional(CONF_FILTER, default="50us"): cv.All( cv.positive_time_period_microseconds, diff --git a/esphome/components/remote_receiver/remote_receiver.h b/esphome/components/remote_receiver/remote_receiver.h index 50153c105d..82c66e3cd0 100644 --- a/esphome/components/remote_receiver/remote_receiver.h +++ b/esphome/components/remote_receiver/remote_receiver.h @@ -6,7 +6,7 @@ namespace esphome { namespace remote_receiver { -#ifdef USE_ESP8266 +#if defined(USE_ESP8266) || defined(USE_LIBRETINY) struct RemoteReceiverComponentStore { static void gpio_intr(RemoteReceiverComponentStore *arg); @@ -55,7 +55,7 @@ class RemoteReceiverComponent : public remote_base::RemoteReceiverBase, esp_err_t error_code_{ESP_OK}; #endif -#ifdef USE_ESP8266 +#if defined(USE_ESP8266) || defined(USE_LIBRETINY) RemoteReceiverComponentStore store_; HighFrequencyLoopRequester high_freq_; #endif diff --git a/esphome/components/remote_receiver/remote_receiver_libretiny.cpp b/esphome/components/remote_receiver/remote_receiver_libretiny.cpp new file mode 100644 index 0000000000..ac85b6b520 --- /dev/null +++ b/esphome/components/remote_receiver/remote_receiver_libretiny.cpp @@ -0,0 +1,122 @@ +#include "remote_receiver.h" +#include "esphome/core/hal.h" +#include "esphome/core/log.h" +#include "esphome/core/helpers.h" + +#ifdef USE_LIBRETINY + +namespace esphome { +namespace remote_receiver { + +static const char *const TAG = "remote_receiver.libretiny"; + +void IRAM_ATTR HOT RemoteReceiverComponentStore::gpio_intr(RemoteReceiverComponentStore *arg) { + const uint32_t now = micros(); + // If the lhs is 1 (rising edge) we should write to an uneven index and vice versa + const uint32_t next = (arg->buffer_write_at + 1) % arg->buffer_size; + const bool level = arg->pin.digital_read(); + if (level != next % 2) + return; + + // If next is buffer_read, we have hit an overflow + if (next == arg->buffer_read_at) + return; + + const uint32_t last_change = arg->buffer[arg->buffer_write_at]; + const uint32_t time_since_change = now - last_change; + if (time_since_change <= arg->filter_us) + return; + + arg->buffer[arg->buffer_write_at = next] = now; +} + +void RemoteReceiverComponent::setup() { + ESP_LOGCONFIG(TAG, "Setting up Remote Receiver..."); + this->pin_->setup(); + auto &s = this->store_; + s.filter_us = this->filter_us_; + s.pin = this->pin_->to_isr(); + s.buffer_size = this->buffer_size_; + + this->high_freq_.start(); + if (s.buffer_size % 2 != 0) { + // Make sure divisible by two. This way, we know that every 0bxxx0 index is a space and every 0bxxx1 index is a mark + s.buffer_size++; + } + + s.buffer = new uint32_t[s.buffer_size]; + void *buf = (void *) s.buffer; + memset(buf, 0, s.buffer_size * sizeof(uint32_t)); + + // First index is a space. + if (this->pin_->digital_read()) { + s.buffer_write_at = s.buffer_read_at = 1; + } else { + s.buffer_write_at = s.buffer_read_at = 0; + } + this->pin_->attach_interrupt(RemoteReceiverComponentStore::gpio_intr, &this->store_, gpio::INTERRUPT_ANY_EDGE); +} +void RemoteReceiverComponent::dump_config() { + ESP_LOGCONFIG(TAG, "Remote Receiver:"); + LOG_PIN(" Pin: ", this->pin_); + if (this->pin_->digital_read()) { + ESP_LOGW(TAG, "Remote Receiver Signal starts with a HIGH value. Usually this means you have to " + "invert the signal using 'inverted: True' in the pin schema!"); + } + ESP_LOGCONFIG(TAG, " Buffer Size: %u", this->buffer_size_); + ESP_LOGCONFIG(TAG, " Tolerance: %u%%", this->tolerance_); + ESP_LOGCONFIG(TAG, " Filter out pulses shorter than: %u us", this->filter_us_); + ESP_LOGCONFIG(TAG, " Signal is done after %u us of no changes", this->idle_us_); +} + +void RemoteReceiverComponent::loop() { + auto &s = this->store_; + + // copy write at to local variables, as it's volatile + const uint32_t write_at = s.buffer_write_at; + const uint32_t dist = (s.buffer_size + write_at - s.buffer_read_at) % s.buffer_size; + // signals must at least one rising and one leading edge + if (dist <= 1) + return; + const uint32_t now = micros(); + if (now - s.buffer[write_at] < this->idle_us_) { + // The last change was fewer than the configured idle time ago. + return; + } + + ESP_LOGVV(TAG, "read_at=%u write_at=%u dist=%u now=%u end=%u", s.buffer_read_at, write_at, dist, now, + s.buffer[write_at]); + + // Skip first value, it's from the previous idle level + s.buffer_read_at = (s.buffer_read_at + 1) % s.buffer_size; + uint32_t prev = s.buffer_read_at; + s.buffer_read_at = (s.buffer_read_at + 1) % s.buffer_size; + const uint32_t reserve_size = 1 + (s.buffer_size + write_at - s.buffer_read_at) % s.buffer_size; + this->temp_.clear(); + this->temp_.reserve(reserve_size); + int32_t multiplier = s.buffer_read_at % 2 == 0 ? 1 : -1; + + for (uint32_t i = 0; prev != write_at; i++) { + int32_t delta = s.buffer[s.buffer_read_at] - s.buffer[prev]; + if (uint32_t(delta) >= this->idle_us_) { + // already found a space longer than idle. There must have been two pulses + break; + } + + ESP_LOGVV(TAG, " i=%u buffer[%u]=%u - buffer[%u]=%u -> %d", i, s.buffer_read_at, s.buffer[s.buffer_read_at], prev, + s.buffer[prev], multiplier * delta); + this->temp_.push_back(multiplier * delta); + prev = s.buffer_read_at; + s.buffer_read_at = (s.buffer_read_at + 1) % s.buffer_size; + multiplier *= -1; + } + s.buffer_read_at = (s.buffer_size + s.buffer_read_at - 1) % s.buffer_size; + this->temp_.push_back(this->idle_us_ * multiplier); + + this->call_listeners_dumpers_(); +} + +} // namespace remote_receiver +} // namespace esphome + +#endif diff --git a/esphome/components/remote_transmitter/remote_transmitter.h b/esphome/components/remote_transmitter/remote_transmitter.h index a20df0cc62..686a6ec09b 100644 --- a/esphome/components/remote_transmitter/remote_transmitter.h +++ b/esphome/components/remote_transmitter/remote_transmitter.h @@ -28,7 +28,7 @@ class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase, protected: void send_internal(uint32_t send_times, uint32_t send_wait) override; -#ifdef USE_ESP8266 +#if defined(USE_ESP8266) || defined(USE_LIBRETINY) 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); diff --git a/esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp b/esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp new file mode 100644 index 0000000000..78bb280482 --- /dev/null +++ b/esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp @@ -0,0 +1,104 @@ +#include "remote_transmitter.h" +#include "esphome/core/log.h" +#include "esphome/core/application.h" + +#ifdef USE_LIBRETINY + +namespace esphome { +namespace remote_transmitter { + +static const char *const TAG = "remote_transmitter"; + +void RemoteTransmitterComponent::setup() { + this->pin_->setup(); + this->pin_->digital_write(false); +} + +void RemoteTransmitterComponent::dump_config() { + ESP_LOGCONFIG(TAG, "Remote Transmitter..."); + ESP_LOGCONFIG(TAG, " Carrier Duty: %u%%", this->carrier_duty_percent_); + LOG_PIN(" Pin: ", this->pin_); +} + +void RemoteTransmitterComponent::calculate_on_off_time_(uint32_t carrier_frequency, uint32_t *on_time_period, + uint32_t *off_time_period) { + if (carrier_frequency == 0) { + *on_time_period = 0; + *off_time_period = 0; + return; + } + uint32_t period = (1000000UL + carrier_frequency / 2) / carrier_frequency; // round(1000000/freq) + period = std::max(uint32_t(1), period); + *on_time_period = (period * this->carrier_duty_percent_) / 100; + *off_time_period = period - *on_time_period; +} + +void RemoteTransmitterComponent::await_target_time_() { + const uint32_t current_time = micros(); + if (this->target_time_ == 0) { + this->target_time_ = current_time; + } else { + while (this->target_time_ > micros()) { + // busy loop that ensures micros is constantly called + } + } +} + +void RemoteTransmitterComponent::mark_(uint32_t on_time, uint32_t off_time, uint32_t usec) { + this->await_target_time_(); + this->pin_->digital_write(true); + + const uint32_t target = this->target_time_ + usec; + if (this->carrier_duty_percent_ < 100 && (on_time > 0 || off_time > 0)) { + while (true) { // Modulate with carrier frequency + this->target_time_ += on_time; + if (this->target_time_ >= target) + break; + this->await_target_time_(); + this->pin_->digital_write(false); + + this->target_time_ += off_time; + if (this->target_time_ >= target) + break; + this->await_target_time_(); + this->pin_->digital_write(true); + } + } + this->target_time_ = target; +} + +void RemoteTransmitterComponent::space_(uint32_t usec) { + this->await_target_time_(); + this->pin_->digital_write(false); + this->target_time_ += usec; +} + +void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t send_wait) { + ESP_LOGD(TAG, "Sending remote code..."); + uint32_t on_time, off_time; + this->calculate_on_off_time_(this->temp_.get_carrier_frequency(), &on_time, &off_time); + this->target_time_ = 0; + for (uint32_t i = 0; i < send_times; i++) { + InterruptLock lock; + for (int32_t item : this->temp_.get_data()) { + if (item > 0) { + const auto length = uint32_t(item); + this->mark_(on_time, off_time, length); + } else { + const auto length = uint32_t(-item); + this->space_(length); + } + App.feed_wdt(); + } + this->await_target_time_(); // wait for duration of last pulse + this->pin_->digital_write(false); + + if (i + 1 < send_times) + this->target_time_ += send_wait; + } +} + +} // namespace remote_transmitter +} // namespace esphome + +#endif diff --git a/esphome/components/rp2040/gpio.py b/esphome/components/rp2040/gpio.py index 2340bed892..4823a6d22a 100644 --- a/esphome/components/rp2040/gpio.py +++ b/esphome/components/rp2040/gpio.py @@ -1,6 +1,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.const import ( + CONF_ANALOG, CONF_ID, CONF_INPUT, CONF_INVERTED, @@ -76,8 +77,6 @@ def validate_supports(value): return value -CONF_ANALOG = "analog" - RP2040_PIN_SCHEMA = cv.All( cv.Schema( { diff --git a/esphome/components/rtl87xx/__init__.py b/esphome/components/rtl87xx/__init__.py new file mode 100644 index 0000000000..9060a7c4a6 --- /dev/null +++ b/esphome/components/rtl87xx/__init__.py @@ -0,0 +1,51 @@ +# 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. + +from esphome import pins +from esphome.components import libretiny +from esphome.components.libretiny.const import ( + COMPONENT_RTL87XX, + KEY_COMPONENT_DATA, + KEY_LIBRETINY, + LibreTinyComponent, +) +from esphome.core import CORE + +from .boards import RTL87XX_BOARDS, RTL87XX_BOARD_PINS + +CODEOWNERS = ["@kuba2k2"] +AUTO_LOAD = ["libretiny"] + +COMPONENT_DATA = LibreTinyComponent( + name=COMPONENT_RTL87XX, + boards=RTL87XX_BOARDS, + board_pins=RTL87XX_BOARD_PINS, + pin_validation=None, + usage_validation=None, +) + + +def _set_core_data(config): + CORE.data[KEY_LIBRETINY] = {} + CORE.data[KEY_LIBRETINY][KEY_COMPONENT_DATA] = COMPONENT_DATA + return config + + +CONFIG_SCHEMA = libretiny.BASE_SCHEMA + +PIN_SCHEMA = libretiny.gpio.BASE_PIN_SCHEMA + +CONFIG_SCHEMA.prepend_extra(_set_core_data) + + +async def to_code(config): + return await libretiny.component_to_code(config) + + +@pins.PIN_SCHEMA_REGISTRY.register("rtl87xx", PIN_SCHEMA) +async def pin_to_code(config): + return await libretiny.gpio.component_pin_to_code(config) diff --git a/esphome/components/rtl87xx/boards.py b/esphome/components/rtl87xx/boards.py new file mode 100644 index 0000000000..6c29467f6e --- /dev/null +++ b/esphome/components/rtl87xx/boards.py @@ -0,0 +1,1390 @@ +# This file was auto-generated by libretiny/generate_components.py +# Do not modify its contents. + +from esphome.components.libretiny.const import FAMILY_RTL8710B, FAMILY_RTL8720C + +RTL87XX_BOARDS = { + "bw12": { + "name": "BW12", + "family": FAMILY_RTL8710B, + }, + "bw15": { + "name": "BW15", + "family": FAMILY_RTL8720C, + }, + "generic-rtl8710bn-2mb-468k": { + "name": "Generic - RTL8710BN (2M/468k)", + "family": FAMILY_RTL8710B, + }, + "generic-rtl8710bn-2mb-788k": { + "name": "Generic - RTL8710BN (2M/788k)", + "family": FAMILY_RTL8710B, + }, + "generic-rtl8710bx-4mb-980k": { + "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", + "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", + "family": FAMILY_RTL8710B, + }, + "wr2le": { + "name": "WR2LE Wi-Fi Module", + "family": FAMILY_RTL8710B, + }, + "wr3": { + "name": "WR3 Wi-Fi Module", + "family": FAMILY_RTL8710B, + }, + "wr3e": { + "name": "WR3E Wi-Fi Module", + "family": FAMILY_RTL8710B, + }, + "wr3l": { + "name": "WR3L Wi-Fi Module", + "family": FAMILY_RTL8710B, + }, + "wr3le": { + "name": "WR3LE Wi-Fi Module", + "family": FAMILY_RTL8710B, + }, + "wr3n": { + "name": "WR3N Wi-Fi Module", + "family": FAMILY_RTL8710B, + }, +} + +RTL87XX_BOARD_PINS = { + "bw12": { + "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": 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, + "PWM0": 23, + "PWM1": 15, + "PWM2": 0, + "PWM3": 12, + "PWM4": 30, + "PWM5": 22, + "RTS0": 22, + "RX0": 18, + "RX2": 29, + "SCK0": 18, + "SCK1": 18, + "SCL0": 22, + "SCL1": 18, + "SDA0": 30, + "SDA1": 23, + "TX0": 23, + "TX2": 30, + "D0": 5, + "D1": 29, + "D2": 0, + "D3": 19, + "D4": 22, + "D5": 30, + "D6": 14, + "D7": 12, + "D8": 15, + "D9": 18, + "D10": 23, + "A0": 19, + }, + "bw15": { + "SPI0_CS_0": 2, + "SPI0_CS_1": 15, + "SPI0_MISO": 20, + "SPI0_MOSI_0": 4, + "SPI0_MOSI_1": 19, + "SPI0_SCK_0": 16, + "SPI0_SCK_1": 3, + "WIRE0_SCL_0": 2, + "WIRE0_SCL_1": 15, + "WIRE0_SCL_2": 19, + "WIRE0_SDA_0": 20, + "WIRE0_SDA_1": 16, + "WIRE0_SDA_2": 3, + "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, + "SERIAL2_CTS": 19, + "SERIAL2_RTS": 20, + "SERIAL2_RX": 15, + "SERIAL2_TX": 16, + "CS0": 15, + "CTS1": 4, + "CTS2": 19, + "MISO0": 20, + "MOSI0": 19, + "PA00": 0, + "PA0": 0, + "PA01": 1, + "PA1": 1, + "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": 0, + "PWM1": 1, + "PWM2": 14, + "PWM3": 3, + "PWM4": 16, + "PWM5": 17, + "PWM6": 18, + "PWM7": 13, + "RTS2": 20, + "RX0": 13, + "RX1": 0, + "RX2": 15, + "SCK0": 3, + "SCL0": 19, + "SDA0": 3, + "TX0": 14, + "TX1": 1, + "TX2": 16, + "D0": 17, + "D1": 18, + "D2": 2, + "D3": 15, + "D4": 4, + "D5": 19, + "D6": 20, + "D7": 16, + "D8": 0, + "D9": 3, + "D10": 1, + "D11": 13, + "D12": 14, + }, + "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, + "PWM0": 23, + "PWM1": 15, + "PWM2": 0, + "PWM3": 12, + "PWM4": 30, + "PWM5": 22, + "RTS0": 22, + "RX0": 18, + "RX2": 29, + "SCK0": 18, + "SCK1": 18, + "SCL0": 29, + "SCL1": 18, + "SDA0": 30, + "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-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, + "PWM0": 23, + "PWM1": 15, + "PWM2": 0, + "PWM3": 12, + "PWM4": 30, + "PWM5": 22, + "RTS0": 22, + "RX0": 18, + "RX2": 29, + "SCK0": 18, + "SCK1": 18, + "SCL0": 29, + "SCL1": 18, + "SDA0": 30, + "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, + "PWM0": 23, + "PWM1": 15, + "PWM2": 0, + "PWM3": 12, + "PWM4": 30, + "PWM5": 22, + "RTS0": 22, + "RX0": 18, + "RX2": 29, + "SCK0": 18, + "SCK1": 18, + "SCL0": 29, + "SCL1": 18, + "SDA0": 30, + "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, + "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, + "MISO0": 20, + "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, + "PWM1": 12, + "PWM2": 14, + "PWM3": 15, + "PWM4": 16, + "PWM5": 17, + "PWM6": 18, + "PWM7": 23, + "RTS0": 9, + "RTS2": 20, + "RX0": 13, + "RX1": 2, + "RX2": 15, + "SCK0": 16, + "SCL0": 19, + "SDA0": 20, + "TX0": 14, + "TX1": 3, + "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, + }, + "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, + "PWM0": 14, + "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, + "PWM0": 23, + "PWM1": 15, + "PWM2": 0, + "PWM3": 12, + "PWM4": 5, + "PWM5": 22, + "RTS0": 22, + "RX0": 18, + "RX2": 29, + "SCK0": 18, + "SCK1": 18, + "SCL0": 29, + "SCL1": 18, + "SDA0": 30, + "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, + }, + "wr1": { + "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, + "PA14": 14, + "PA15": 15, + "PA18": 18, + "PA19": 19, + "PA22": 22, + "PA23": 23, + "PA29": 29, + "PA30": 30, + "PWM0": 14, + "PWM1": 15, + "PWM2": 0, + "PWM4": 29, + "PWM5": 22, + "RTS0": 22, + "RX0": 18, + "RX2": 29, + "SCK0": 18, + "SCK1": 18, + "SCL0": 22, + "SCL1": 18, + "SDA0": 19, + "SDA1": 23, + "TX0": 23, + "TX2": 30, + "D0": 23, + "D1": 18, + "D2": 14, + "D3": 15, + "D4": 30, + "D5": 0, + "D6": 5, + "D7": 29, + "D8": 19, + "D9": 22, + "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, + "PWM0": 14, + "PWM1": 15, + "PWM3": 12, + "PWM4": 29, + "PWM5": 22, + "RTS0": 22, + "RX0": 18, + "RX2": 29, + "SCK0": 18, + "SCK1": 18, + "SCL0": 22, + "SCL1": 18, + "SDA0": 19, + "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, + "PWM0": 14, + "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, + "PWM0": 14, + "PWM1": 15, + "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": 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, + "PWM0": 23, + "PWM1": 15, + "PWM2": 0, + "PWM3": 12, + "PWM4": 5, + "PWM5": 22, + "RTS0": 22, + "RX0": 18, + "RX2": 29, + "SCK0": 18, + "SCK1": 18, + "SCL0": 29, + "SCL1": 18, + "SDA0": 30, + "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, + "PWM0": 23, + "PWM1": 15, + "PWM2": 0, + "PWM3": 12, + "PWM4": 5, + "PWM5": 22, + "RTS0": 22, + "RX0": 18, + "RX2": 29, + "SCK0": 18, + "SCK1": 18, + "SCL0": 22, + "SCL1": 18, + "SDA0": 19, + "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, + "PWM0": 23, + "PWM1": 15, + "PWM2": 0, + "PWM3": 12, + "PWM4": 5, + "PWM5": 22, + "RTS0": 22, + "RX0": 18, + "RX2": 29, + "SCK0": 18, + "SCK1": 18, + "SCL0": 29, + "SCL1": 18, + "SDA0": 30, + "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, + "PWM0": 23, + "PWM1": 15, + "PWM2": 0, + "PWM3": 12, + "PWM4": 5, + "PWM5": 22, + "RTS0": 22, + "RX0": 18, + "RX2": 29, + "SCK0": 18, + "SCK1": 18, + "SCL0": 22, + "SCL1": 18, + "SDA0": 19, + "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, + "PWM0": 23, + "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/components/sntp/sntp_component.cpp b/esphome/components/sntp/sntp_component.cpp index 3af21a9b23..418eacd870 100644 --- a/esphome/components/sntp/sntp_component.cpp +++ b/esphome/components/sntp/sntp_component.cpp @@ -1,7 +1,7 @@ #include "sntp_component.h" #include "esphome/core/log.h" -#ifdef USE_ESP32 +#if defined(USE_ESP32) || defined(USE_LIBRETINY) #include "lwip/apps/sntp.h" #ifdef USE_ESP_IDF #include "esp_sntp.h" @@ -26,7 +26,7 @@ static const char *const TAG = "sntp"; void SNTPComponent::setup() { ESP_LOGCONFIG(TAG, "Setting up SNTP..."); -#ifdef USE_ESP32 +#if defined(USE_ESP32) || defined(USE_LIBRETINY) if (sntp_enabled()) { sntp_stop(); } diff --git a/esphome/components/socket/__init__.py b/esphome/components/socket/__init__.py index 1757ec4668..19952aeece 100644 --- a/esphome/components/socket/__init__.py +++ b/esphome/components/socket/__init__.py @@ -5,6 +5,7 @@ CODEOWNERS = ["@esphome/core"] CONF_IMPLEMENTATION = "implementation" IMPLEMENTATION_LWIP_TCP = "lwip_tcp" +IMPLEMENTATION_LWIP_SOCKETS = "lwip_sockets" IMPLEMENTATION_BSD_SOCKETS = "bsd_sockets" CONFIG_SCHEMA = cv.Schema( @@ -14,9 +15,15 @@ CONFIG_SCHEMA = cv.Schema( esp8266=IMPLEMENTATION_LWIP_TCP, esp32=IMPLEMENTATION_BSD_SOCKETS, rp2040=IMPLEMENTATION_LWIP_TCP, + bk72xx=IMPLEMENTATION_LWIP_SOCKETS, + rtl87xx=IMPLEMENTATION_LWIP_SOCKETS, host=IMPLEMENTATION_BSD_SOCKETS, ): cv.one_of( - IMPLEMENTATION_LWIP_TCP, IMPLEMENTATION_BSD_SOCKETS, lower=True, space="_" + IMPLEMENTATION_LWIP_TCP, + IMPLEMENTATION_LWIP_SOCKETS, + IMPLEMENTATION_BSD_SOCKETS, + lower=True, + space="_", ), } ) @@ -26,5 +33,7 @@ async def to_code(config): impl = config[CONF_IMPLEMENTATION] if impl == IMPLEMENTATION_LWIP_TCP: cg.add_define("USE_SOCKET_IMPL_LWIP_TCP") + elif impl == IMPLEMENTATION_LWIP_SOCKETS: + cg.add_define("USE_SOCKET_IMPL_LWIP_SOCKETS") elif impl == IMPLEMENTATION_BSD_SOCKETS: cg.add_define("USE_SOCKET_IMPL_BSD_SOCKETS") diff --git a/esphome/components/socket/headers.h b/esphome/components/socket/headers.h index 1922885ac0..032892072d 100644 --- a/esphome/components/socket/headers.h +++ b/esphome/components/socket/headers.h @@ -120,6 +120,35 @@ struct iovec { #endif // USE_SOCKET_IMPL_LWIP_TCP +#ifdef USE_SOCKET_IMPL_LWIP_SOCKETS + +// standard lwIP's compatibility macros will interfere +// with Socket class function names - disable the macros +// and use real function names instead +#undef LWIP_COMPAT_SOCKETS +#define LWIP_COMPAT_SOCKETS 0 + +#include "lwip/sockets.h" +#include + +#ifdef USE_ARDUINO +// arduino-esp32 declares a global var called INADDR_NONE which is replaced +// by the define +#ifdef INADDR_NONE +#undef INADDR_NONE +#endif +// not defined for ESP32 +using socklen_t = uint32_t; + +#define ESPHOME_INADDR_ANY ((uint32_t) 0x00000000UL) +#define ESPHOME_INADDR_NONE ((uint32_t) 0xFFFFFFFFUL) +#else // !USE_ESP32 +#define ESPHOME_INADDR_ANY INADDR_ANY +#define ESPHOME_INADDR_NONE INADDR_NONE +#endif + +#endif // USE_SOCKET_IMPL_LWIP_SOCKETS + #ifdef USE_SOCKET_IMPL_BSD_SOCKETS #include diff --git a/esphome/components/socket/lwip_sockets_impl.cpp b/esphome/components/socket/lwip_sockets_impl.cpp new file mode 100644 index 0000000000..eaf6ac2c6f --- /dev/null +++ b/esphome/components/socket/lwip_sockets_impl.cpp @@ -0,0 +1,115 @@ +#include "socket.h" +#include "esphome/core/defines.h" +#include "esphome/core/helpers.h" + +#ifdef USE_SOCKET_IMPL_LWIP_SOCKETS + +#include + +namespace esphome { +namespace socket { + +std::string format_sockaddr(const struct sockaddr_storage &storage) { + if (storage.ss_family == AF_INET) { + const struct sockaddr_in *addr = reinterpret_cast(&storage); + char buf[INET_ADDRSTRLEN]; + const char *ret = lwip_inet_ntop(AF_INET, &addr->sin_addr, buf, sizeof(buf)); + if (ret == nullptr) + return {}; + return std::string{buf}; + } +#if LWIP_IPV6 + else if (storage.ss_family == AF_INET6) { + const struct sockaddr_in6 *addr = reinterpret_cast(&storage); + char buf[INET6_ADDRSTRLEN]; + const char *ret = lwip_inet_ntop(AF_INET6, &addr->sin6_addr, buf, sizeof(buf)); + if (ret == nullptr) + return {}; + return std::string{buf}; + } +#endif + return {}; +} + +class LwIPSocketImpl : public Socket { + public: + LwIPSocketImpl(int fd) : fd_(fd) {} + ~LwIPSocketImpl() override { + if (!closed_) { + close(); // NOLINT(clang-analyzer-optin.cplusplus.VirtualCall) + } + } + std::unique_ptr accept(struct sockaddr *addr, socklen_t *addrlen) override { + int fd = lwip_accept(fd_, addr, addrlen); + if (fd == -1) + return {}; + return make_unique(fd); + } + int bind(const struct sockaddr *addr, socklen_t addrlen) override { return lwip_bind(fd_, addr, addrlen); } + int close() override { + int ret = lwip_close(fd_); + closed_ = true; + return ret; + } + int shutdown(int how) override { return lwip_shutdown(fd_, how); } + + int getpeername(struct sockaddr *addr, socklen_t *addrlen) override { return lwip_getpeername(fd_, addr, addrlen); } + std::string getpeername() override { + struct sockaddr_storage storage; + socklen_t len = sizeof(storage); + int err = this->getpeername((struct sockaddr *) &storage, &len); + if (err != 0) + return {}; + return format_sockaddr(storage); + } + int getsockname(struct sockaddr *addr, socklen_t *addrlen) override { return lwip_getsockname(fd_, addr, addrlen); } + std::string getsockname() override { + struct sockaddr_storage storage; + socklen_t len = sizeof(storage); + int err = this->getsockname((struct sockaddr *) &storage, &len); + if (err != 0) + return {}; + return format_sockaddr(storage); + } + int getsockopt(int level, int optname, void *optval, socklen_t *optlen) override { + return lwip_getsockopt(fd_, level, optname, optval, optlen); + } + int setsockopt(int level, int optname, const void *optval, socklen_t optlen) override { + return lwip_setsockopt(fd_, level, optname, optval, optlen); + } + int listen(int backlog) override { return lwip_listen(fd_, backlog); } + ssize_t read(void *buf, size_t len) override { return lwip_read(fd_, buf, len); } + ssize_t readv(const struct iovec *iov, int iovcnt) override { return lwip_readv(fd_, iov, iovcnt); } + ssize_t write(const void *buf, size_t len) override { return lwip_write(fd_, buf, len); } + ssize_t send(void *buf, size_t len, int flags) { return lwip_send(fd_, buf, len, flags); } + ssize_t writev(const struct iovec *iov, int iovcnt) override { return lwip_writev(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(fd_, buf, len, flags, to, tolen); + } + int setblocking(bool blocking) override { + int fl = lwip_fcntl(fd_, F_GETFL, 0); + if (blocking) { + fl &= ~O_NONBLOCK; + } else { + fl |= O_NONBLOCK; + } + lwip_fcntl(fd_, F_SETFL, fl); + return 0; + } + + protected: + int fd_; + bool closed_ = false; +}; + +std::unique_ptr socket(int domain, int type, int protocol) { + int ret = lwip_socket(domain, type, protocol); + if (ret == -1) + return nullptr; + return std::unique_ptr{new LwIPSocketImpl(ret)}; +} + +} // namespace socket +} // namespace esphome + +#endif // USE_SOCKET_IMPL_LWIP_SOCKETS diff --git a/esphome/components/spi/__init__.py b/esphome/components/spi/__init__.py index 57a4fa9f4e..a2ef956200 100644 --- a/esphome/components/spi/__init__.py +++ b/esphome/components/spi/__init__.py @@ -48,6 +48,7 @@ CONFIG_SCHEMA = cv.All( } ), cv.has_at_least_one_key(CONF_MISO_PIN, CONF_MOSI_PIN), + cv.only_on(["esp32", "esp8266", "rp2040"]), ) diff --git a/esphome/components/uart/__init__.py b/esphome/components/uart/__init__.py index aea59d9d8b..36f2bb5851 100644 --- a/esphome/components/uart/__init__.py +++ b/esphome/components/uart/__init__.py @@ -42,6 +42,9 @@ ESP8266UartComponent = uart_ns.class_( "ESP8266UartComponent", UARTComponent, cg.Component ) RP2040UartComponent = uart_ns.class_("RP2040UartComponent", UARTComponent, cg.Component) +LibreTinyUARTComponent = uart_ns.class_( + "LibreTinyUARTComponent", UARTComponent, cg.Component +) UARTDevice = uart_ns.class_("UARTDevice") UARTWriteAction = uart_ns.class_("UARTWriteAction", automation.Action) @@ -92,6 +95,8 @@ def _uart_declare_type(value): return cv.declare_id(IDFUARTComponent)(value) if CORE.is_rp2040: return cv.declare_id(RP2040UartComponent)(value) + if CORE.is_libretiny: + return cv.declare_id(LibreTinyUARTComponent)(value) raise NotImplementedError diff --git a/esphome/components/uart/uart_component_libretiny.cpp b/esphome/components/uart/uart_component_libretiny.cpp new file mode 100644 index 0000000000..c5e299e9d1 --- /dev/null +++ b/esphome/components/uart/uart_component_libretiny.cpp @@ -0,0 +1,168 @@ +#ifdef USE_LIBRETINY + +#include "esphome/core/application.h" +#include "esphome/core/defines.h" +#include "esphome/core/helpers.h" +#include "esphome/core/log.h" +#include "uart_component_libretiny.h" + +#ifdef USE_LOGGER +#include "esphome/components/logger/logger.h" +#endif + +#if LT_ARD_HAS_SOFTSERIAL +#include +#endif + +namespace esphome { +namespace uart { + +static const char *const TAG = "uart.lt"; + +static const char *UART_TYPE[] = { + "hardware", + "software", +}; + +uint16_t LibreTinyUARTComponent::get_config() { + uint16_t config = 0; + + switch (this->parity_) { + case UART_CONFIG_PARITY_NONE: + config |= SERIAL_PARITY_NONE; + break; + case UART_CONFIG_PARITY_EVEN: + config |= SERIAL_PARITY_EVEN; + break; + case UART_CONFIG_PARITY_ODD: + config |= SERIAL_PARITY_ODD; + break; + } + + config |= (this->data_bits_ - 4) << 8; + config |= 0x10 + (this->stop_bits_ - 1) * 0x20; + + return config; +} + +void LibreTinyUARTComponent::setup() { + ESP_LOGCONFIG(TAG, "Setting up UART..."); + + int8_t tx_pin = tx_pin_ == nullptr ? -1 : tx_pin_->get_pin(); + int8_t rx_pin = rx_pin_ == nullptr ? -1 : rx_pin_->get_pin(); + bool tx_inverted = tx_pin_ != nullptr && tx_pin_->is_inverted(); + bool rx_inverted = rx_pin_ != nullptr && rx_pin_->is_inverted(); + + if (false) + return; +#if LT_HW_UART0 + else if ((tx_pin == -1 || tx_pin == PIN_SERIAL0_TX) && (rx_pin == -1 || rx_pin == PIN_SERIAL0_RX)) { + this->serial_ = &Serial0; + this->hardware_idx_ = 0; + } +#endif +#if LT_HW_UART1 + else if ((tx_pin == -1 || tx_pin == PIN_SERIAL1_TX) && (rx_pin == -1 || rx_pin == PIN_SERIAL1_RX)) { + this->serial_ = &Serial1; + this->hardware_idx_ = 1; + } +#endif +#if LT_HW_UART2 + else if ((tx_pin == -1 || tx_pin == PIN_SERIAL2_TX) && (rx_pin == -1 || rx_pin == PIN_SERIAL2_RX)) { + this->serial_ = &Serial2; + this->hardware_idx_ = 2; + } +#endif + else { +#if LT_ARD_HAS_SOFTSERIAL + this->serial_ = new SoftwareSerial(rx_pin, tx_pin, rx_inverted || tx_inverted); +#else + this->serial_ = &Serial; + ESP_LOGE(TAG, " SoftwareSerial is not implemented for this chip. Only hardware pins are supported:"); +#if LT_HW_UART0 + ESP_LOGE(TAG, " TX=%u, RX=%u", PIN_SERIAL0_TX, PIN_SERIAL0_RX); +#endif +#if LT_HW_UART1 + ESP_LOGE(TAG, " TX=%u, RX=%u", PIN_SERIAL1_TX, PIN_SERIAL1_RX); +#endif +#if LT_HW_UART2 + ESP_LOGE(TAG, " TX=%u, RX=%u", PIN_SERIAL2_TX, PIN_SERIAL2_RX); +#endif + this->mark_failed(); + return; +#endif + } + + this->serial_->begin(this->baud_rate_, get_config()); +} + +void LibreTinyUARTComponent::dump_config() { + bool is_software = this->hardware_idx_ == -1; + ESP_LOGCONFIG(TAG, "UART Bus:"); + ESP_LOGCONFIG(TAG, " Type: %s", UART_TYPE[is_software]); + if (!is_software) { + ESP_LOGCONFIG(TAG, " Port number: %d", this->hardware_idx_); + } + LOG_PIN(" TX Pin: ", tx_pin_); + LOG_PIN(" RX Pin: ", rx_pin_); + if (this->rx_pin_ != nullptr) { + ESP_LOGCONFIG(TAG, " RX Buffer Size: %u", this->rx_buffer_size_); + } + ESP_LOGCONFIG(TAG, " Baud Rate: %u baud", this->baud_rate_); + ESP_LOGCONFIG(TAG, " Data Bits: %u", this->data_bits_); + ESP_LOGCONFIG(TAG, " Parity: %s", LOG_STR_ARG(parity_to_str(this->parity_))); + ESP_LOGCONFIG(TAG, " Stop bits: %u", this->stop_bits_); + this->check_logger_conflict(); +} + +void LibreTinyUARTComponent::write_array(const uint8_t *data, size_t len) { + this->serial_->write(data, len); +#ifdef USE_UART_DEBUGGER + for (size_t i = 0; i < len; i++) { + this->debug_callback_.call(UART_DIRECTION_TX, data[i]); + } +#endif +} + +bool LibreTinyUARTComponent::peek_byte(uint8_t *data) { + if (!this->check_read_timeout_()) + return false; + *data = this->serial_->peek(); + return true; +} + +bool LibreTinyUARTComponent::read_array(uint8_t *data, size_t len) { + if (!this->check_read_timeout_(len)) + return false; + this->serial_->readBytes(data, len); +#ifdef USE_UART_DEBUGGER + for (size_t i = 0; i < len; i++) { + this->debug_callback_.call(UART_DIRECTION_RX, data[i]); + } +#endif + return true; +} + +int LibreTinyUARTComponent::available() { return this->serial_->available(); } +void LibreTinyUARTComponent::flush() { + ESP_LOGVV(TAG, " Flushing..."); + this->serial_->flush(); +} + +void LibreTinyUARTComponent::check_logger_conflict() { +#ifdef USE_LOGGER + if (this->hardware_idx_ == -1 || logger::global_logger->get_baud_rate() == 0) { + return; + } + + if (this->serial_ == logger::global_logger->get_hw_serial()) { + ESP_LOGW(TAG, " You're using the same serial port for logging and the UART component. Please " + "disable logging over the serial port by setting logger->baud_rate to 0."); + } +#endif +} + +} // namespace uart +} // namespace esphome + +#endif // USE_LIBRETINY diff --git a/esphome/components/uart/uart_component_libretiny.h b/esphome/components/uart/uart_component_libretiny.h new file mode 100644 index 0000000000..00982fd297 --- /dev/null +++ b/esphome/components/uart/uart_component_libretiny.h @@ -0,0 +1,43 @@ +#pragma once + +#ifdef USE_LIBRETINY + +#include +#include "esphome/core/component.h" +#include "esphome/core/hal.h" +#include "esphome/core/log.h" +#include "uart_component.h" + +namespace esphome { +namespace uart { + +class LibreTinyUARTComponent : public UARTComponent, public Component { + public: + void setup() override; + void dump_config() override; + float get_setup_priority() const override { return setup_priority::BUS; } + + 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; + void flush() override; + + uint16_t get_config(); + + HardwareSerial *get_hw_serial() { return this->serial_; } + int8_t get_hw_serial_number() { return this->hardware_idx_; } + + protected: + void check_logger_conflict() override; + + HardwareSerial *serial_{nullptr}; + int8_t hardware_idx_{-1}; +}; + +} // namespace uart +} // namespace esphome + +#endif // USE_LIBRETINY diff --git a/esphome/components/web_server/__init__.py b/esphome/components/web_server/__init__.py index b1cf8a5de6..c6d9c31e93 100644 --- a/esphome/components/web_server/__init__.py +++ b/esphome/components/web_server/__init__.py @@ -79,13 +79,18 @@ CONFIG_SCHEMA = cv.All( ), cv.Optional(CONF_INCLUDE_INTERNAL, default=False): cv.boolean, cv.SplitDefault( - CONF_OTA, esp8266=True, esp32_arduino=True, esp32_idf=False + CONF_OTA, + esp8266=True, + esp32_arduino=True, + esp32_idf=False, + bk72xx=True, + rtl87xx=True, ): cv.boolean, cv.Optional(CONF_LOG, default=True): cv.boolean, cv.Optional(CONF_LOCAL): cv.boolean, } ).extend(cv.COMPONENT_SCHEMA), - cv.only_on(["esp32", "esp8266"]), + cv.only_on(["esp32", "esp8266", "bk72xx", "rtl87xx"]), default_url, validate_local, validate_ota, diff --git a/esphome/components/web_server_base/__init__.py b/esphome/components/web_server_base/__init__.py index 87f23a990a..6491446bcc 100644 --- a/esphome/components/web_server_base/__init__.py +++ b/esphome/components/web_server_base/__init__.py @@ -37,4 +37,4 @@ async def to_code(config): cg.add_library("FS", None) cg.add_library("Update", None) # https://github.com/esphome/ESPAsyncWebServer/blob/master/library.json - cg.add_library("esphome/ESPAsyncWebServer-esphome", "2.1.0") + cg.add_library("esphome/ESPAsyncWebServer-esphome", "3.1.0") diff --git a/esphome/components/web_server_base/web_server_base.cpp b/esphome/components/web_server_base/web_server_base.cpp index 997ce0798a..f90c7e56a3 100644 --- a/esphome/components/web_server_base/web_server_base.cpp +++ b/esphome/components/web_server_base/web_server_base.cpp @@ -5,7 +5,7 @@ #ifdef USE_ARDUINO #include -#ifdef USE_ESP32 +#if defined(USE_ESP32) || defined(USE_LIBRETINY) #include #endif #ifdef USE_ESP8266 @@ -50,7 +50,7 @@ void OTARequestHandler::handleUpload(AsyncWebServerRequest *request, const Strin // NOLINTNEXTLINE(readability-static-accessed-through-instance) success = Update.begin((ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000); #endif -#ifdef USE_ESP32_FRAMEWORK_ARDUINO +#if defined(USE_ESP32_FRAMEWORK_ARDUINO) || defined(USE_LIBRETINY) if (Update.isRunning()) { Update.abort(); } diff --git a/esphome/components/wifi/__init__.py b/esphome/components/wifi/__init__.py index 068d015732..1baffcbfcc 100644 --- a/esphome/components/wifi/__init__.py +++ b/esphome/components/wifi/__init__.py @@ -272,7 +272,12 @@ CONFIG_SCHEMA = cv.All( CONF_REBOOT_TIMEOUT, default="15min" ): cv.positive_time_period_milliseconds, cv.SplitDefault( - CONF_POWER_SAVE_MODE, esp8266="none", esp32="light", rp2040="light" + CONF_POWER_SAVE_MODE, + esp8266="none", + esp32="light", + rp2040="light", + bk72xx="none", + rtl87xx="none", ): cv.enum(WIFI_POWER_SAVE_MODES, upper=True), cv.Optional(CONF_FAST_CONNECT, default=False): cv.boolean, cv.Optional(CONF_USE_ADDRESS): cv.string_strict, diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index c17246fd00..b418a5b353 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -15,6 +15,10 @@ #include #endif +#ifdef USE_LIBRETINY +#include +#endif + #ifdef USE_ESP8266 #include #include @@ -336,6 +340,11 @@ class WiFiComponent : public Component { void wifi_scan_result(void *env, const cyw43_ev_scan_result_t *result); #endif +#ifdef USE_LIBRETINY + void wifi_event_callback_(arduino_event_id_t event, arduino_event_info_t info); + void wifi_scan_done_callback_(); +#endif + std::string use_address_; std::vector sta_; std::vector sta_priorities_; diff --git a/esphome/components/wifi/wifi_component_libretiny.cpp b/esphome/components/wifi/wifi_component_libretiny.cpp new file mode 100644 index 0000000000..abad5aca9c --- /dev/null +++ b/esphome/components/wifi/wifi_component_libretiny.cpp @@ -0,0 +1,467 @@ +#include "wifi_component.h" + +#ifdef USE_LIBRETINY + +#include +#include +#include "lwip/ip_addr.h" +#include "lwip/err.h" +#include "lwip/dns.h" + +#include "esphome/core/helpers.h" +#include "esphome/core/log.h" +#include "esphome/core/hal.h" +#include "esphome/core/application.h" +#include "esphome/core/util.h" + +namespace esphome { +namespace wifi { + +static const char *const TAG = "wifi_lt"; + +static bool s_sta_connecting = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + +bool WiFiComponent::wifi_mode_(optional sta, optional ap) { + uint8_t current_mode = WiFi.getMode(); + bool current_sta = current_mode & 0b01; + bool current_ap = current_mode & 0b10; + bool enable_sta = sta.value_or(current_sta); + bool enable_ap = ap.value_or(current_ap); + if (current_sta == enable_sta && current_ap == enable_ap) + return true; + + if (enable_sta && !current_sta) { + ESP_LOGV(TAG, "Enabling STA."); + } else if (!enable_sta && current_sta) { + ESP_LOGV(TAG, "Disabling STA."); + } + if (enable_ap && !current_ap) { + ESP_LOGV(TAG, "Enabling AP."); + } else if (!enable_ap && current_ap) { + ESP_LOGV(TAG, "Disabling AP."); + } + + uint8_t mode = 0; + if (enable_sta) + mode |= 0b01; + if (enable_ap) + mode |= 0b10; + bool ret = WiFi.mode(static_cast(mode)); + + if (!ret) { + ESP_LOGW(TAG, "Setting WiFi mode failed!"); + } + + return ret; +} +bool WiFiComponent::wifi_apply_output_power_(float output_power) { + int8_t val = static_cast(output_power * 4); + return WiFi.setTxPower(val); +} +bool WiFiComponent::wifi_sta_pre_setup_() { + if (!this->wifi_mode_(true, {})) + return false; + + WiFi.setAutoReconnect(false); + delay(10); + return true; +} +bool WiFiComponent::wifi_apply_power_save_() { return WiFi.setSleep(this->power_save_ != WIFI_POWER_SAVE_NONE); } +bool WiFiComponent::wifi_sta_ip_config_(optional manual_ip) { + // enable STA + if (!this->wifi_mode_(true, {})) + return false; + + if (!manual_ip.has_value()) { + return true; + } + + WiFi.config(static_cast(manual_ip->static_ip), static_cast(manual_ip->gateway), + static_cast(manual_ip->subnet), static_cast(manual_ip->dns1), + static_cast(manual_ip->dns2)); + + return true; +} + +network::IPAddress WiFiComponent::wifi_sta_ip() { + if (!this->has_sta()) + return {}; + return {WiFi.localIP()}; +} + +bool WiFiComponent::wifi_apply_hostname_() { + // setting is done in SYSTEM_EVENT_STA_START callback too + WiFi.setHostname(App.get_name().c_str()); + return true; +} +bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) { + // enable STA + if (!this->wifi_mode_(true, {})) + return false; + + String ssid = WiFi.SSID(); + if (ssid && strcmp(ssid.c_str(), ap.get_ssid().c_str()) != 0) { + WiFi.disconnect(); + } + + if (!this->wifi_sta_ip_config_(ap.get_manual_ip())) { + return false; + } + + this->wifi_apply_hostname_(); + + s_sta_connecting = true; + + WiFiStatus status = WiFi.begin(ap.get_ssid().c_str(), ap.get_password().empty() ? NULL : ap.get_password().c_str(), + ap.get_channel().has_value() ? *ap.get_channel() : 0, + ap.get_bssid().has_value() ? ap.get_bssid()->data() : NULL); + if (status != WL_CONNECTED) { + ESP_LOGW(TAG, "esp_wifi_connect failed! %d", status); + return false; + } + + return true; +} +const char *get_auth_mode_str(uint8_t mode) { + switch (mode) { + case WIFI_AUTH_OPEN: + return "OPEN"; + case WIFI_AUTH_WEP: + return "WEP"; + case WIFI_AUTH_WPA_PSK: + return "WPA PSK"; + case WIFI_AUTH_WPA2_PSK: + return "WPA2 PSK"; + case WIFI_AUTH_WPA_WPA2_PSK: + return "WPA/WPA2 PSK"; + default: + return "UNKNOWN"; + } +} + +using esphome_ip4_addr_t = IPAddress; + +std::string format_ip4_addr(const esphome_ip4_addr_t &ip) { + char buf[20]; + uint32_t addr = ip; + sprintf(buf, "%u.%u.%u.%u", uint8_t(addr >> 0), uint8_t(addr >> 8), uint8_t(addr >> 16), uint8_t(addr >> 24)); + return buf; +} +const char *get_op_mode_str(uint8_t mode) { + switch (mode) { + case WIFI_OFF: + return "OFF"; + case WIFI_STA: + return "STA"; + case WIFI_AP: + return "AP"; + case WIFI_AP_STA: + return "AP+STA"; + default: + return "UNKNOWN"; + } +} +const char *get_disconnect_reason_str(uint8_t reason) { + switch (reason) { + case WIFI_REASON_AUTH_EXPIRE: + return "Auth Expired"; + case WIFI_REASON_AUTH_LEAVE: + return "Auth Leave"; + case WIFI_REASON_ASSOC_EXPIRE: + return "Association Expired"; + case WIFI_REASON_ASSOC_TOOMANY: + return "Too Many Associations"; + case WIFI_REASON_NOT_AUTHED: + return "Not Authenticated"; + case WIFI_REASON_NOT_ASSOCED: + return "Not Associated"; + case WIFI_REASON_ASSOC_LEAVE: + return "Association Leave"; + case WIFI_REASON_ASSOC_NOT_AUTHED: + return "Association not Authenticated"; + case WIFI_REASON_DISASSOC_PWRCAP_BAD: + return "Disassociate Power Cap Bad"; + case WIFI_REASON_DISASSOC_SUPCHAN_BAD: + return "Disassociate Supported Channel Bad"; + case WIFI_REASON_IE_INVALID: + return "IE Invalid"; + case WIFI_REASON_MIC_FAILURE: + return "Mic Failure"; + case WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT: + return "4-Way Handshake Timeout"; + case WIFI_REASON_GROUP_KEY_UPDATE_TIMEOUT: + return "Group Key Update Timeout"; + case WIFI_REASON_IE_IN_4WAY_DIFFERS: + return "IE In 4-Way Handshake Differs"; + case WIFI_REASON_GROUP_CIPHER_INVALID: + return "Group Cipher Invalid"; + case WIFI_REASON_PAIRWISE_CIPHER_INVALID: + return "Pairwise Cipher Invalid"; + case WIFI_REASON_AKMP_INVALID: + return "AKMP Invalid"; + case WIFI_REASON_UNSUPP_RSN_IE_VERSION: + return "Unsupported RSN IE version"; + case WIFI_REASON_INVALID_RSN_IE_CAP: + return "Invalid RSN IE Cap"; + case WIFI_REASON_802_1X_AUTH_FAILED: + return "802.1x Authentication Failed"; + case WIFI_REASON_CIPHER_SUITE_REJECTED: + return "Cipher Suite Rejected"; + case WIFI_REASON_BEACON_TIMEOUT: + return "Beacon Timeout"; + case WIFI_REASON_NO_AP_FOUND: + return "AP Not Found"; + case WIFI_REASON_AUTH_FAIL: + return "Authentication Failed"; + case WIFI_REASON_ASSOC_FAIL: + return "Association Failed"; + case WIFI_REASON_HANDSHAKE_TIMEOUT: + return "Handshake Failed"; + case WIFI_REASON_CONNECTION_FAIL: + return "Connection Failed"; + case WIFI_REASON_UNSPECIFIED: + default: + return "Unspecified"; + } +} + +#define ESPHOME_EVENT_ID_WIFI_READY ARDUINO_EVENT_WIFI_READY +#define ESPHOME_EVENT_ID_WIFI_SCAN_DONE ARDUINO_EVENT_WIFI_SCAN_DONE +#define ESPHOME_EVENT_ID_WIFI_STA_START ARDUINO_EVENT_WIFI_STA_START +#define ESPHOME_EVENT_ID_WIFI_STA_STOP ARDUINO_EVENT_WIFI_STA_STOP +#define ESPHOME_EVENT_ID_WIFI_STA_CONNECTED ARDUINO_EVENT_WIFI_STA_CONNECTED +#define ESPHOME_EVENT_ID_WIFI_STA_DISCONNECTED ARDUINO_EVENT_WIFI_STA_DISCONNECTED +#define ESPHOME_EVENT_ID_WIFI_STA_AUTHMODE_CHANGE ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE +#define ESPHOME_EVENT_ID_WIFI_STA_GOT_IP ARDUINO_EVENT_WIFI_STA_GOT_IP +#define ESPHOME_EVENT_ID_WIFI_STA_GOT_IP6 ARDUINO_EVENT_WIFI_STA_GOT_IP6 +#define ESPHOME_EVENT_ID_WIFI_STA_LOST_IP ARDUINO_EVENT_WIFI_STA_LOST_IP +#define ESPHOME_EVENT_ID_WIFI_AP_START ARDUINO_EVENT_WIFI_AP_START +#define ESPHOME_EVENT_ID_WIFI_AP_STOP ARDUINO_EVENT_WIFI_AP_STOP +#define ESPHOME_EVENT_ID_WIFI_AP_STACONNECTED ARDUINO_EVENT_WIFI_AP_STACONNECTED +#define ESPHOME_EVENT_ID_WIFI_AP_STADISCONNECTED ARDUINO_EVENT_WIFI_AP_STADISCONNECTED +#define ESPHOME_EVENT_ID_WIFI_AP_STAIPASSIGNED ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED +#define ESPHOME_EVENT_ID_WIFI_AP_PROBEREQRECVED ARDUINO_EVENT_WIFI_AP_PROBEREQRECVED +#define ESPHOME_EVENT_ID_WIFI_AP_GOT_IP6 ARDUINO_EVENT_WIFI_AP_GOT_IP6 +using esphome_wifi_event_id_t = arduino_event_id_t; +using esphome_wifi_event_info_t = arduino_event_info_t; + +void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_wifi_event_info_t info) { + switch (event) { + case ESPHOME_EVENT_ID_WIFI_READY: { + ESP_LOGV(TAG, "Event: WiFi ready"); + break; + } + case ESPHOME_EVENT_ID_WIFI_SCAN_DONE: { + auto it = info.wifi_scan_done; + ESP_LOGV(TAG, "Event: WiFi Scan Done status=%u number=%u scan_id=%u", it.status, it.number, it.scan_id); + + this->wifi_scan_done_callback_(); + break; + } + case ESPHOME_EVENT_ID_WIFI_STA_START: { + ESP_LOGV(TAG, "Event: WiFi STA start"); + WiFi.setHostname(App.get_name().c_str()); + break; + } + case ESPHOME_EVENT_ID_WIFI_STA_STOP: { + ESP_LOGV(TAG, "Event: WiFi STA stop"); + break; + } + case ESPHOME_EVENT_ID_WIFI_STA_CONNECTED: { + auto it = info.wifi_sta_connected; + char buf[33]; + memcpy(buf, it.ssid, it.ssid_len); + buf[it.ssid_len] = '\0'; + ESP_LOGV(TAG, "Event: Connected ssid='%s' bssid=" LOG_SECRET("%s") " channel=%u, authmode=%s", buf, + format_mac_addr(it.bssid).c_str(), it.channel, get_auth_mode_str(it.authmode)); + + break; + } + case ESPHOME_EVENT_ID_WIFI_STA_DISCONNECTED: { + auto it = info.wifi_sta_disconnected; + char buf[33]; + memcpy(buf, it.ssid, it.ssid_len); + buf[it.ssid_len] = '\0'; + if (it.reason == WIFI_REASON_NO_AP_FOUND) { + ESP_LOGW(TAG, "Event: Disconnected ssid='%s' reason='Probe Request Unsuccessful'", buf); + } else { + ESP_LOGW(TAG, "Event: Disconnected ssid='%s' bssid=" LOG_SECRET("%s") " reason='%s'", buf, + format_mac_addr(it.bssid).c_str(), get_disconnect_reason_str(it.reason)); + } + + uint8_t reason = it.reason; + if (reason == WIFI_REASON_AUTH_EXPIRE || reason == WIFI_REASON_BEACON_TIMEOUT || + reason == WIFI_REASON_NO_AP_FOUND || reason == WIFI_REASON_ASSOC_FAIL || + reason == WIFI_REASON_HANDSHAKE_TIMEOUT) { + WiFi.disconnect(); + this->error_from_callback_ = true; + } + + s_sta_connecting = false; + break; + } + case ESPHOME_EVENT_ID_WIFI_STA_AUTHMODE_CHANGE: { + auto it = info.wifi_sta_authmode_change; + ESP_LOGV(TAG, "Event: Authmode Change old=%s new=%s", get_auth_mode_str(it.old_mode), + get_auth_mode_str(it.new_mode)); + // Mitigate CVE-2020-12638 + // https://lbsfilm.at/blog/wpa2-authenticationmode-downgrade-in-espressif-microprocessors + if (it.old_mode != WIFI_AUTH_OPEN && it.new_mode == WIFI_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.disconnect(); + this->error_from_callback_ = true; + } + break; + } + case ESPHOME_EVENT_ID_WIFI_STA_GOT_IP: { + // auto it = info.got_ip.ip_info; + ESP_LOGV(TAG, "Event: Got IP static_ip=%s gateway=%s", format_ip4_addr(WiFi.localIP()).c_str(), + format_ip4_addr(WiFi.gatewayIP()).c_str()); + s_sta_connecting = false; + break; + } + case ESPHOME_EVENT_ID_WIFI_STA_LOST_IP: { + ESP_LOGV(TAG, "Event: Lost IP"); + break; + } + case ESPHOME_EVENT_ID_WIFI_AP_START: { + ESP_LOGV(TAG, "Event: WiFi AP start"); + break; + } + case ESPHOME_EVENT_ID_WIFI_AP_STOP: { + ESP_LOGV(TAG, "Event: WiFi AP stop"); + break; + } + case ESPHOME_EVENT_ID_WIFI_AP_STACONNECTED: { + auto it = info.wifi_sta_connected; + auto &mac = it.bssid; + ESP_LOGV(TAG, "Event: AP client connected MAC=%s", format_mac_addr(mac).c_str()); + break; + } + case ESPHOME_EVENT_ID_WIFI_AP_STADISCONNECTED: { + auto it = info.wifi_sta_disconnected; + auto &mac = it.bssid; + ESP_LOGV(TAG, "Event: AP client disconnected MAC=%s", format_mac_addr(mac).c_str()); + break; + } + case ESPHOME_EVENT_ID_WIFI_AP_STAIPASSIGNED: { + ESP_LOGV(TAG, "Event: AP client assigned IP"); + break; + } + case ESPHOME_EVENT_ID_WIFI_AP_PROBEREQRECVED: { + auto it = info.wifi_ap_probereqrecved; + ESP_LOGVV(TAG, "Event: AP receive Probe Request MAC=%s RSSI=%d", format_mac_addr(it.mac).c_str(), it.rssi); + break; + } + default: + break; + } +} +void WiFiComponent::wifi_pre_setup_() { + auto f = std::bind(&WiFiComponent::wifi_event_callback_, this, std::placeholders::_1, std::placeholders::_2); + WiFi.onEvent(f); + // Make sure WiFi is in clean state before anything starts + this->wifi_mode_(false, false); +} +WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() { + auto status = WiFi.status(); + if (status == WL_CONNECTED) { + return WiFiSTAConnectStatus::CONNECTED; + } else if (status == WL_CONNECT_FAILED || status == WL_CONNECTION_LOST) { + return WiFiSTAConnectStatus::ERROR_CONNECT_FAILED; + } else if (status == WL_NO_SSID_AVAIL) { + return WiFiSTAConnectStatus::ERROR_NETWORK_NOT_FOUND; + } else if (s_sta_connecting) { + return WiFiSTAConnectStatus::CONNECTING; + } + return WiFiSTAConnectStatus::IDLE; +} +bool WiFiComponent::wifi_scan_start_(bool passive) { + // enable STA + if (!this->wifi_mode_(true, {})) + return false; + + // need to use WiFi because of WiFiScanClass allocations :( + int16_t err = WiFi.scanNetworks(true, true, passive, 200); + if (err != WIFI_SCAN_RUNNING) { + ESP_LOGV(TAG, "WiFi.scanNetworks failed! %d", err); + return false; + } + + return true; +} +void WiFiComponent::wifi_scan_done_callback_() { + this->scan_result_.clear(); + + int16_t num = WiFi.scanComplete(); + if (num < 0) + return; + + this->scan_result_.reserve(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); + + WiFiScanResult scan({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); + this->scan_result_.push_back(scan); + } + WiFi.scanDelete(); + this->scan_done_ = true; +} +bool WiFiComponent::wifi_ap_ip_config_(optional manual_ip) { + // enable AP + if (!this->wifi_mode_({}, true)) + return false; + + if (manual_ip.has_value()) { + return WiFi.softAPConfig(static_cast(manual_ip->static_ip), static_cast(manual_ip->gateway), + static_cast(manual_ip->subnet)); + } else { + return WiFi.softAPConfig(IPAddress(192, 168, 4, 1), IPAddress(192, 168, 4, 1), IPAddress(255, 255, 255, 0)); + } +} +bool WiFiComponent::wifi_start_ap_(const WiFiAP &ap) { + // enable AP + if (!this->wifi_mode_({}, true)) + return false; + + if (!this->wifi_ap_ip_config_(ap.get_manual_ip())) { + ESP_LOGV(TAG, "wifi_ap_ip_config_ failed!"); + return false; + } + + yield(); + + return WiFi.softAP(ap.get_ssid().c_str(), ap.get_password().empty() ? NULL : ap.get_password().c_str(), + ap.get_channel().value_or(1), ap.get_hidden()); +} +network::IPAddress WiFiComponent::wifi_soft_ap_ip() { return {WiFi.softAPIP()}; } +bool WiFiComponent::wifi_disconnect_() { return WiFi.disconnect(); } + +bssid_t WiFiComponent::wifi_bssid() { + bssid_t bssid{}; + uint8_t *raw_bssid = WiFi.BSSID(); + if (raw_bssid != nullptr) { + for (size_t i = 0; i < bssid.size(); i++) + bssid[i] = raw_bssid[i]; + } + return bssid; +} +std::string WiFiComponent::wifi_ssid() { return WiFi.SSID().c_str(); } +int8_t WiFiComponent::wifi_rssi() { return WiFi.RSSI(); } +int32_t WiFiComponent::wifi_channel_() { return WiFi.channel(); } +network::IPAddress WiFiComponent::wifi_subnet_mask_() { return {WiFi.subnetMask()}; } +network::IPAddress WiFiComponent::wifi_gateway_ip_() { return {WiFi.gatewayIP()}; } +network::IPAddress WiFiComponent::wifi_dns_ip_(int num) { return {WiFi.dnsIP(num)}; } +void WiFiComponent::wifi_loop_() {} + +} // namespace wifi +} // namespace esphome + +#endif // USE_LIBRETINY diff --git a/esphome/config_validation.py b/esphome/config_validation.py index ed87e98078..b3f24d9d17 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -1500,6 +1500,8 @@ class SplitDefault(Optional): esp32_arduino=vol.UNDEFINED, esp32_idf=vol.UNDEFINED, rp2040=vol.UNDEFINED, + bk72xx=vol.UNDEFINED, + rtl87xx=vol.UNDEFINED, host=vol.UNDEFINED, ): super().__init__(key) @@ -1511,6 +1513,8 @@ class SplitDefault(Optional): esp32_idf if esp32 is vol.UNDEFINED else esp32 ) self._rp2040_default = vol.default_factory(rp2040) + self._bk72xx_default = vol.default_factory(bk72xx) + self._rtl87xx_default = vol.default_factory(rtl87xx) self._host_default = vol.default_factory(host) @property @@ -1523,6 +1527,10 @@ class SplitDefault(Optional): return self._esp32_idf_default if CORE.is_rp2040: return self._rp2040_default + if CORE.is_bk72xx: + return self._bk72xx_default + if CORE.is_rtl87xx: + return self._rtl87xx_default if CORE.is_host: return self._host_default raise NotImplementedError diff --git a/esphome/const.py b/esphome/const.py index e0642247ab..d0575a6ebd 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -11,8 +11,19 @@ PLATFORM_ESP32 = "esp32" PLATFORM_ESP8266 = "esp8266" PLATFORM_RP2040 = "rp2040" PLATFORM_HOST = "host" +PLATFORM_BK72XX = "bk72xx" +PLATFORM_RTL87XX = "rtl87xx" +PLATFORM_LIBRETINY_OLDSTYLE = "libretiny" -TARGET_PLATFORMS = [PLATFORM_ESP32, PLATFORM_ESP8266, PLATFORM_RP2040, PLATFORM_HOST] +TARGET_PLATFORMS = [ + PLATFORM_ESP32, + PLATFORM_ESP8266, + PLATFORM_RP2040, + PLATFORM_HOST, + PLATFORM_BK72XX, + PLATFORM_RTL87XX, + PLATFORM_LIBRETINY_OLDSTYLE, +] SOURCE_FILE_EXTENSIONS = {".cpp", ".hpp", ".h", ".c", ".tcc", ".ino"} HEADER_FILE_EXTENSIONS = {".h", ".hpp", ".tcc"} @@ -37,6 +48,7 @@ CONF_ADVANCED = "advanced" CONF_AFTER = "after" CONF_ALPHA = "alpha" CONF_ALTITUDE = "altitude" +CONF_ANALOG = "analog" CONF_AND = "and" CONF_AP = "ap" CONF_APPARENT_POWER = "apparent_power" @@ -835,6 +847,7 @@ ICON_BRIEFCASE_DOWNLOAD = "mdi:briefcase-download" ICON_BRIGHTNESS_5 = "mdi:brightness-5" ICON_BRIGHTNESS_6 = "mdi:brightness-6" ICON_BUG = "mdi:bug" +ICON_CELLPHONE_ARROW_DOWN = "mdi:cellphone-arrow-down" ICON_CHECK_CIRCLE_OUTLINE = "mdi:check-circle-outline" ICON_CHEMICAL_WEAPON = "mdi:chemical-weapon" ICON_CHIP = "mdi:chip" diff --git a/esphome/core/__init__.py b/esphome/core/__init__.py index 891936adc3..d9b1603894 100644 --- a/esphome/core/__init__.py +++ b/esphome/core/__init__.py @@ -584,6 +584,8 @@ class EsphomeCore: @property def firmware_bin(self): + if self.is_libretiny: + return self.relative_pioenvs_path(self.name, "firmware.uf2") return self.relative_pioenvs_path(self.name, "firmware.bin") @property @@ -602,6 +604,18 @@ class EsphomeCore: def is_rp2040(self): return self.target_platform == "rp2040" + @property + def is_bk72xx(self): + return self.target_platform == "bk72xx" + + @property + def is_rtl87xx(self): + return self.target_platform == "rtl87xx" + + @property + def is_libretiny(self): + return self.is_bk72xx or self.is_rtl87xx + @property def is_host(self): return self.target_platform == "host" diff --git a/esphome/core/config.py b/esphome/core/config.py index ef6553026e..a09252e4b4 100644 --- a/esphome/core/config.py +++ b/esphome/core/config.py @@ -380,7 +380,7 @@ async def to_code(config): cg.add_build_flag("-Wno-unused-but-set-variable") cg.add_build_flag("-Wno-sign-compare") - if CORE.using_arduino: + if CORE.using_arduino and not CORE.is_bk72xx: CORE.add_job(add_arduino_global_workaround) if config[CONF_INCLUDES]: diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 8d4d7e3f22..1e0df74eec 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -95,6 +95,10 @@ #define USE_HTTP_REQUEST_ESP8266_HTTPS #define USE_SOCKET_IMPL_LWIP_TCP +#ifdef USE_LIBRETINY +#define USE_SOCKET_IMPL_LWIP_SOCKETS +#endif + // Dummy firmware payload for shelly_dimmer #define USE_SHD_FIRMWARE_MAJOR_VERSION 56 #define USE_SHD_FIRMWARE_MINOR_VERSION 5 diff --git a/esphome/core/helpers.cpp b/esphome/core/helpers.cpp index c65928556a..714a1642f8 100644 --- a/esphome/core/helpers.cpp +++ b/esphome/core/helpers.cpp @@ -43,6 +43,10 @@ #include "esp_efuse_table.h" #endif +#ifdef USE_LIBRETINY +#include // for macAddress() +#endif + namespace esphome { static const char *const TAG = "helpers"; @@ -190,6 +194,8 @@ uint32_t random_uint32() { result |= rosc_hw->randombit; } return result; +#elif defined(USE_LIBRETINY) + return rand(); #elif defined(USE_HOST) std::random_device dev; std::mt19937 rng(dev()); @@ -216,6 +222,9 @@ bool random_bytes(uint8_t *data, size_t len) { *data++ = result; } return true; +#elif defined(USE_LIBRETINY) + lt_rand_bytes(data, len); + return true; #elif defined(USE_HOST) FILE *fp = fopen("/dev/urandom", "r"); if (fp == nullptr) { @@ -503,7 +512,7 @@ Mutex::Mutex() {} void Mutex::lock() {} bool Mutex::try_lock() { return true; } void Mutex::unlock() {} -#elif defined(USE_ESP32) +#elif defined(USE_ESP32) || defined(USE_LIBRETINY) Mutex::Mutex() { handle_ = xSemaphoreCreateMutex(); } void Mutex::lock() { xSemaphoreTake(this->handle_, portMAX_DELAY); } bool Mutex::try_lock() { return xSemaphoreTake(this->handle_, 0) == pdTRUE; } @@ -513,7 +522,7 @@ void Mutex::unlock() { xSemaphoreGive(this->handle_); } #if defined(USE_ESP8266) IRAM_ATTR InterruptLock::InterruptLock() { state_ = xt_rsil(15); } IRAM_ATTR InterruptLock::~InterruptLock() { xt_wsr_ps(state_); } -#elif defined(USE_ESP32) +#elif defined(USE_ESP32) || defined(USE_LIBRETINY) // 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(); } @@ -555,6 +564,8 @@ void get_mac_address_raw(uint8_t *mac) { // NOLINT(readability-non-const-parame wifi_get_macaddr(STATION_IF, mac); #elif defined(USE_RP2040) && defined(USE_WIFI) WiFi.macAddress(mac); +#elif defined(USE_LIBRETINY) + WiFi.macAddress(mac); #endif } std::string get_mac_address() { diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 115073de80..c3ed443bf0 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -17,6 +17,9 @@ #if defined(USE_ESP32) #include #include +#elif defined(USE_LIBRETINY) +#include +#include #endif #define HOT __attribute__((hot)) @@ -543,7 +546,7 @@ class Mutex { Mutex &operator=(const Mutex &) = delete; private: -#if defined(USE_ESP32) +#if defined(USE_ESP32) || defined(USE_LIBRETINY) SemaphoreHandle_t handle_; #endif }; diff --git a/esphome/core/log.h b/esphome/core/log.h index 6775aa5ac5..86af534f98 100644 --- a/esphome/core/log.h +++ b/esphome/core/log.h @@ -17,6 +17,9 @@ #ifdef USE_ESP32_FRAMEWORK_ARDUINO #include #endif +#ifdef USE_LIBRETINY +#include +#endif namespace esphome { diff --git a/esphome/dashboard/dashboard.py b/esphome/dashboard/dashboard.py index c05e1fcfcc..0d6ec8dc13 100644 --- a/esphome/dashboard/dashboard.py +++ b/esphome/dashboard/dashboard.py @@ -543,6 +543,7 @@ class DownloadListRequestHandler(BaseHandler): from esphome.components.esp32 import get_download_types as esp32_types from esphome.components.esp8266 import get_download_types as esp8266_types from esphome.components.rp2040 import get_download_types as rp2040_types + from esphome.components.libretiny import get_download_types as libretiny_types downloads = [] platform = storage_json.target_platform.lower() @@ -552,6 +553,10 @@ class DownloadListRequestHandler(BaseHandler): downloads = esp8266_types(storage_json) elif platform == const.PLATFORM_ESP32: downloads = esp32_types(storage_json) + elif platform == const.PLATFORM_BK72XX: + downloads = libretiny_types(storage_json) + elif platform == const.PLATFORM_RTL87XX: + downloads = libretiny_types(storage_json) else: self.send_error(418) return @@ -826,11 +831,15 @@ class BoardsRequestHandler(BaseHandler): from esphome.components.esp32.boards import BOARDS as ESP32_BOARDS from esphome.components.esp8266.boards import BOARDS as ESP8266_BOARDS from esphome.components.rp2040.boards import BOARDS as RP2040_BOARDS + from esphome.components.bk72xx.boards import BOARDS as BK72XX_BOARDS + from esphome.components.rtl87xx.boards import BOARDS as RTL87XX_BOARDS platform_to_boards = { "esp32": ESP32_BOARDS, "esp8266": ESP8266_BOARDS, "rp2040": RP2040_BOARDS, + "bk72xx": BK72XX_BOARDS, + "rtl87xx": RTL87XX_BOARDS, } # filter all ESP32 variants by requested platform if platform.startswith("esp32"): diff --git a/esphome/voluptuous_schema.py b/esphome/voluptuous_schema.py index 281ef10964..e2171cabed 100644 --- a/esphome/voluptuous_schema.py +++ b/esphome/voluptuous_schema.py @@ -203,6 +203,11 @@ class _Schema(vol.Schema): self._extra_schemas.append(validator) return self + def prepend_extra(self, validator): + validator = _Schema(validator) + self._extra_schemas.insert(0, validator) + return self + @schema_extractor_extended def extend(self, *schemas, **kwargs): extra = kwargs.pop("extra", None) diff --git a/esphome/wizard.py b/esphome/wizard.py index fd661af639..17a0882e1c 100644 --- a/esphome/wizard.py +++ b/esphome/wizard.py @@ -93,12 +93,24 @@ rp2040: platform_version: https://github.com/maxgerhardt/platform-raspberrypi.git """ +BK72XX_CONFIG = """ +bk72xx: + board: {board} +""" + +RTL87XX_CONFIG = """ +rtl87xx: + board: {board} +""" + HARDWARE_BASE_CONFIGS = { "ESP8266": ESP8266_CONFIG, "ESP32": ESP32_CONFIG, "ESP32S2": ESP32S2_CONFIG, "ESP32C3": ESP32C3_CONFIG, "RP2040": RP2040_CONFIG, + "BK72XX": BK72XX_CONFIG, + "RTL87XX": RTL87XX_CONFIG, } @@ -156,7 +168,7 @@ def wizard_file(**kwargs): """ # pylint: disable=consider-using-f-string - if kwargs["platform"] in ["ESP8266", "ESP32"]: + if kwargs["platform"] in ["ESP8266", "ESP32", "BK72XX", "RTL87XX"]: config += """ # Enable fallback hotspot (captive portal) in case wifi connection fails ap: @@ -182,7 +194,10 @@ captive_portal: def wizard_write(path, **kwargs): from esphome.components.esp8266 import boards as esp8266_boards + from esphome.components.esp32 import boards as esp32_boards from esphome.components.rp2040 import boards as rp2040_boards + from esphome.components.bk72xx import boards as bk72xx_boards + from esphome.components.rtl87xx import boards as rtl87xx_boards name = kwargs["name"] board = kwargs["board"] @@ -192,12 +207,19 @@ def wizard_write(path, **kwargs): kwargs[key] = sanitize_double_quotes(kwargs[key]) if "platform" not in kwargs: - if board in esp8266_boards.ESP8266_BOARD_PINS: + if board in esp8266_boards.BOARDS: platform = "ESP8266" - elif board in rp2040_boards.RP2040_BOARD_PINS: - platform = "RP2040" - else: + elif board in esp32_boards.BOARDS: platform = "ESP32" + elif board in rp2040_boards.BOARDS: + platform = "RP2040" + elif board in bk72xx_boards.BOARDS: + platform = "BK72XX" + elif board in rtl87xx_boards.BOARDS: + platform = "RTL87XX" + else: + safe_print(color(Fore.RED, f'The board "{board}" is unknown.')) + return False kwargs["platform"] = platform hardware = kwargs["platform"] @@ -206,6 +228,8 @@ def wizard_write(path, **kwargs): storage_path = ext_storage_path(os.path.dirname(path), os.path.basename(path)) storage.save(storage_path) + return True + if get_bool_env(ENV_QUICKWIZARD): @@ -243,6 +267,8 @@ def strip_accents(value): def wizard(path): from esphome.components.esp32 import boards as esp32_boards from esphome.components.esp8266 import boards as esp8266_boards + from esphome.components.bk72xx import boards as bk72xx_boards + from esphome.components.rtl87xx import boards as rtl87xx_boards if not path.endswith(".yaml") and not path.endswith(".yml"): safe_print( @@ -262,7 +288,7 @@ def wizard(path): sleep(2.0) safe_print( "In 4 steps I'm going to guide you through creating a basic " - "configuration file for your custom ESP8266/ESP32 firmware. Yay!" + "configuration file for your custom firmware. Yay!" ) sleep(3.0) safe_print() @@ -305,16 +331,18 @@ def wizard(path): "Now I'd like to know what microcontroller you're using so that I can compile " "firmwares for it." ) + + wizard_platforms = ["ESP32", "ESP8266", "BK72XX", "RTL87XX"] safe_print( - f"Are you using an {color(Fore.GREEN, 'ESP32')} or {color(Fore.GREEN, 'ESP8266')} platform? (Choose ESP8266 for Sonoff devices)" + "Please choose one of the supported microcontrollers " + "(Use ESP8266 for Sonoff devices)." ) while True: sleep(0.5) safe_print() - safe_print("Please enter either ESP32 or ESP8266.") - platform = input(color(Fore.BOLD_WHITE, "(ESP32/ESP8266): ")) + platform = input(color(Fore.BOLD_WHITE, f"({'/'.join(wizard_platforms)}): ")) try: - platform = vol.All(vol.Upper, vol.Any("ESP32", "ESP8266"))(platform) + platform = vol.All(vol.Upper, vol.Any(*wizard_platforms))(platform.upper()) break except vol.Invalid: safe_print( @@ -328,10 +356,14 @@ def wizard(path): board_link = ( "http://docs.platformio.org/en/latest/platforms/espressif32.html#boards" ) - else: + elif platform == "ESP8266": board_link = ( "http://docs.platformio.org/en/latest/platforms/espressif8266.html#boards" ) + elif platform in ["BK72XX", "RTL87XX"]: + board_link = "https://docs.libretiny.eu/docs/status/supported/" + else: + raise NotImplementedError("Unknown platform!") safe_print(f"Next, I need to know what {color(Fore.GREEN, 'board')} you're using.") sleep(0.5) @@ -342,11 +374,24 @@ def wizard(path): # Don't sleep because user needs to copy link if platform == "ESP32": safe_print(f"For example \"{color(Fore.BOLD_WHITE, 'nodemcu-32s')}\".") - boards = list(esp32_boards.ESP32_BOARD_PINS.keys()) - else: + boards_list = esp32_boards.BOARDS.items() + elif platform == "ESP8266": safe_print(f"For example \"{color(Fore.BOLD_WHITE, 'nodemcuv2')}\".") - boards = list(esp8266_boards.ESP8266_BOARD_PINS.keys()) - safe_print(f"Options: {', '.join(sorted(boards))}") + boards_list = esp8266_boards.BOARDS.items() + elif platform == "BK72XX": + safe_print(f"For example \"{color(Fore.BOLD_WHITE, 'cb2s')}\".") + boards_list = bk72xx_boards.BOARDS.items() + elif platform == "RTL87XX": + safe_print(f"For example \"{color(Fore.BOLD_WHITE, 'wr3')}\".") + boards_list = rtl87xx_boards.BOARDS.items() + else: + raise NotImplementedError("Unknown platform!") + + boards = [] + safe_print("Options:") + for board_id, board_data in boards_list: + safe_print(f" - {board_id} - {board_data['name']}") + boards.append(board_id) while True: board = input(color(Fore.BOLD_WHITE, "(board): ")) @@ -420,7 +465,7 @@ def wizard(path): safe_print("Press ENTER for no password") password = input(color(Fore.BOLD_WHITE, "(password): ")) - wizard_write( + if not wizard_write( path=path, name=name, platform=platform, @@ -428,7 +473,8 @@ def wizard(path): ssid=ssid, psk=psk, password=password, - ) + ): + return 1 safe_print() safe_print( diff --git a/platformio.ini b/platformio.ini index 64c7bec6e8..ab9584d9b8 100644 --- a/platformio.ini +++ b/platformio.ini @@ -4,7 +4,7 @@ ; It's *not* used during runtime. [platformio] -default_envs = esp8266-arduino, esp32-arduino, esp32-idf +default_envs = esp8266-arduino, esp32-arduino, esp32-idf, bk72xx-arduino ; Ideally, we want src_dir to be the root directory of the repository, to mimic the runtime build ; environment as best as possible. Unfortunately, the ESP-IDF toolchain really doesn't like this ; being the root directory. Instead, set esphome/ as the source directory, all our sources are in @@ -167,6 +167,16 @@ build_flags = -DUSE_RP2040 -DUSE_RP2040_FRAMEWORK_ARDUINO +; This are common settings for the LibreTiny (all variants) using Arduino. +[common:libretiny-arduino] +extends = common:arduino +platform = libretiny +framework = arduino +build_flags = + ${common:arduino.build_flags} + -DUSE_LIBRETINY +build_src_flags = -include Arduino.h + ; All the actual environments are defined below. ;;;;;;;; ESP8266 ;;;;;;;; @@ -339,6 +349,35 @@ build_flags = ${common:rp2040-arduino.build_flags} ${flags:runtime.build_flags} +;;;;;;;; LibreTiny ;;;;;;;; + +[env:bk72xx-arduino] +extends = common:libretiny-arduino +board = generic-bk7231n-qfn32-tuya +build_flags = + ${common:libretiny-arduino.build_flags} + ${flags:runtime.build_flags} + -DUSE_BK72XX + -DUSE_LIBRETINY_VARIANT_BK7231N + +[env:rtl87xxb-arduino] +extends = common:libretiny-arduino +board = generic-rtl8710bn-2mb-788k +build_flags = + ${common:libretiny-arduino.build_flags} + ${flags:runtime.build_flags} + -DUSE_RTL87XX + -DUSE_LIBRETINY_VARIANT_RTL8710B + +[env:rtl87xxc-arduino] +extends = common:libretiny-arduino +board = generic-rtl8720cf-2mb-992k +build_flags = + ${common:libretiny-arduino.build_flags} + ${flags:runtime.build_flags} + -DUSE_RTL87XX + -DUSE_LIBRETINY_VARIANT_RTL8720C + [env:host] extends = common platform = platformio/native diff --git a/script/ci-custom.py b/script/ci-custom.py index a731e2e5b8..da4da50d7e 100755 --- a/script/ci-custom.py +++ b/script/ci-custom.py @@ -512,7 +512,10 @@ def relative_py_search_text(fname, content): @lint_content_find_check( relative_py_search_text, include=["esphome/components/*.py"], - exclude=["esphome/components/web_server/__init__.py"], + exclude=[ + "esphome/components/libretiny/generate_components.py", + "esphome/components/web_server/__init__.py", + ], ) def lint_relative_py_import(fname): return ( @@ -536,6 +539,7 @@ def lint_relative_py_import(fname): "esphome/components/esp32/core.cpp", "esphome/components/esp8266/core.cpp", "esphome/components/rp2040/core.cpp", + "esphome/components/libretiny/core.cpp", "esphome/components/host/core.cpp", ], ) diff --git a/tests/test9.1.yaml b/tests/test9.1.yaml new file mode 100644 index 0000000000..f7455b7668 --- /dev/null +++ b/tests/test9.1.yaml @@ -0,0 +1,28 @@ +# Tests for rtl87xx boards using LibreTiny +--- +wifi: + ssid: "ssid" + +rtl87xx: + board: generic-rtl8710bn-2mb-788k + +esphome: + name: rtl87xx-test + +logger: + +ota: + +captive_portal: + +binary_sensor: + - platform: gpio + name: Home Button + pin: GPIO11 + +sensor: + - platform: adc + id: adc_sensor + name: ADC + pin: PA19 + update_interval: 1s diff --git a/tests/test9.yaml b/tests/test9.yaml new file mode 100644 index 0000000000..ccf5f4b5b0 --- /dev/null +++ b/tests/test9.yaml @@ -0,0 +1,28 @@ +# Tests for bk7xx boards using LibreTiny +--- +wifi: + ssid: "ssid" + +bk72xx: + board: cb2s + +esphome: + name: bk72xx-test + +logger: + +ota: + +captive_portal: + +binary_sensor: + - platform: gpio + name: Home Button + pin: GPIO24 + +sensor: + - platform: adc + id: adc_sensor + name: ADC + pin: GPIO23 + update_interval: 1s diff --git a/tests/unit_tests/test_wizard.py b/tests/unit_tests/test_wizard.py index 79a5894075..d94624d1e4 100644 --- a/tests/unit_tests/test_wizard.py +++ b/tests/unit_tests/test_wizard.py @@ -3,6 +3,9 @@ import esphome.wizard as wz import pytest from esphome.components.esp8266.boards import ESP8266_BOARD_PINS +from esphome.components.esp32.boards import ESP32_BOARD_PINS +from esphome.components.bk72xx.boards import BK72XX_BOARD_PINS +from esphome.components.rtl87xx.boards import RTL87XX_BOARD_PINS from unittest.mock import MagicMock @@ -140,11 +143,11 @@ def test_wizard_write_defaults_platform_from_board_esp32( default_config, tmp_path, monkeypatch ): """ - If the platform is not explicitly set, use "ESP32" if the board is not one of the ESP8266 boards + If the platform is not explicitly set, use "ESP32" if the board is one of the ESP32 boards """ # Given del default_config["platform"] - default_config["board"] = "foo" + default_config["board"] = [*ESP32_BOARD_PINS][0] monkeypatch.setattr(wz, "write_file", MagicMock()) @@ -156,6 +159,46 @@ def test_wizard_write_defaults_platform_from_board_esp32( assert "esp32:" in generated_config +def test_wizard_write_defaults_platform_from_board_bk72xx( + default_config, tmp_path, monkeypatch +): + """ + If the platform is not explicitly set, use "BK72XX" if the board is one of BK72XX boards + """ + # Given + del default_config["platform"] + default_config["board"] = [*BK72XX_BOARD_PINS][0] + + monkeypatch.setattr(wz, "write_file", MagicMock()) + + # When + wz.wizard_write(tmp_path, **default_config) + + # Then + generated_config = wz.write_file.call_args.args[1] + assert "bk72xx:" in generated_config + + +def test_wizard_write_defaults_platform_from_board_rtl87xx( + default_config, tmp_path, monkeypatch +): + """ + If the platform is not explicitly set, use "RTL87XX" if the board is one of RTL87XX boards + """ + # Given + del default_config["platform"] + default_config["board"] = [*RTL87XX_BOARD_PINS][0] + + monkeypatch.setattr(wz, "write_file", MagicMock()) + + # When + wz.wizard_write(tmp_path, **default_config) + + # Then + generated_config = wz.write_file.call_args.args[1] + assert "rtl87xx:" in generated_config + + def test_safe_print_step_prints_step_number_and_description(monkeypatch): """ The safe_print_step function prints the step number and the passed description @@ -186,7 +229,7 @@ def test_default_input_uses_default_if_no_input_supplied(monkeypatch): """ # Given - monkeypatch.setattr("builtins.input", lambda _: "") + monkeypatch.setattr("builtins.input", lambda _=None: "") default_string = "foobar" # When @@ -203,7 +246,7 @@ def test_default_input_uses_user_supplied_value(monkeypatch): # Given user_input = "A value" - monkeypatch.setattr("builtins.input", lambda _: user_input) + monkeypatch.setattr("builtins.input", lambda _=None: user_input) default_string = "foobar" # When From d382ca2401581579c8edceca52547f1ded3e8eda Mon Sep 17 00:00:00 2001 From: mkaiser <29856783+mkaiser@users.noreply.github.com> Date: Tue, 5 Sep 2023 00:27:58 +0200 Subject: [PATCH 0124/2101] Extend ESP32 CAN bit rates /bus speed support (#5280) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Co-authored-by: mkaiser --- esphome/components/canbus/__init__.py | 6 ++- esphome/components/canbus/canbus.h | 5 +++ esphome/components/esp32_can/canbus.py | 51 +++++++++++++++++++++- esphome/components/esp32_can/esp32_can.cpp | 27 ++++++++++++ 4 files changed, 86 insertions(+), 3 deletions(-) diff --git a/esphome/components/canbus/__init__.py b/esphome/components/canbus/__init__.py index c5a9924644..f49398858c 100644 --- a/esphome/components/canbus/__init__.py +++ b/esphome/components/canbus/__init__.py @@ -45,9 +45,13 @@ CanbusTrigger = canbus_ns.class_( CanSpeed = canbus_ns.enum("CAN_SPEED") CAN_SPEEDS = { + "1KBPS": CanSpeed.CAN_1KBPS, "5KBPS": CanSpeed.CAN_5KBPS, "10KBPS": CanSpeed.CAN_10KBPS, + "12K5BPS": CanSpeed.CAN_12K5BPS, + "16KBPS": CanSpeed.CAN_16KBPS, "20KBPS": CanSpeed.CAN_20KBPS, + "25KBPS": CanSpeed.CAN_25KBPS, "31K25BPS": CanSpeed.CAN_31K25BPS, "33KBPS": CanSpeed.CAN_33KBPS, "40KBPS": CanSpeed.CAN_40KBPS, @@ -60,9 +64,9 @@ CAN_SPEEDS = { "200KBPS": CanSpeed.CAN_200KBPS, "250KBPS": CanSpeed.CAN_250KBPS, "500KBPS": CanSpeed.CAN_500KBPS, + "800KBPS": CanSpeed.CAN_800KBPS, "1000KBPS": CanSpeed.CAN_1000KBPS, } - CANBUS_SCHEMA = cv.Schema( { cv.GenerateID(): cv.declare_id(CanbusComponent), diff --git a/esphome/components/canbus/canbus.h b/esphome/components/canbus/canbus.h index 4a12742627..c0ccff4866 100644 --- a/esphome/components/canbus/canbus.h +++ b/esphome/components/canbus/canbus.h @@ -19,9 +19,13 @@ enum Error : uint8_t { }; enum CanSpeed : uint8_t { + CAN_1KBPS, CAN_5KBPS, CAN_10KBPS, + CAN_12K5BPS, + CAN_16KBPS, CAN_20KBPS, + CAN_25KBPS, CAN_31K25BPS, CAN_33KBPS, CAN_40KBPS, @@ -34,6 +38,7 @@ enum CanSpeed : uint8_t { CAN_200KBPS, CAN_250KBPS, CAN_500KBPS, + CAN_800KBPS, CAN_1000KBPS }; diff --git a/esphome/components/esp32_can/canbus.py b/esphome/components/esp32_can/canbus.py index 7761418c6a..74f331f30b 100644 --- a/esphome/components/esp32_can/canbus.py +++ b/esphome/components/esp32_can/canbus.py @@ -5,6 +5,15 @@ from esphome.components import canbus from esphome.const import CONF_ID, CONF_RX_PIN, CONF_TX_PIN from esphome.components.canbus import CanbusComponent, CanSpeed, CONF_BIT_RATE +from esphome.components.esp32 import get_esp32_variant +from esphome.components.esp32.const import ( + VARIANT_ESP32, + VARIANT_ESP32S2, + VARIANT_ESP32S3, + VARIANT_ESP32C3, + VARIANT_ESP32H2, +) + CODEOWNERS = ["@Sympatron"] DEPENDENCIES = ["esp32"] @@ -12,19 +21,57 @@ esp32_can_ns = cg.esphome_ns.namespace("esp32_can") esp32_can = esp32_can_ns.class_("ESP32Can", CanbusComponent) # Currently the driver only supports a subset of the bit rates defined in canbus -CAN_SPEEDS = { +# The supported bit rates differ between ESP32 variants. +# See ESP-IDF Programming Guide --> API Reference --> Two-Wire Automotive Interface (TWAI) + +CAN_SPEEDS_ESP32 = { + "25KBPS": CanSpeed.CAN_25KBPS, "50KBPS": CanSpeed.CAN_50KBPS, "100KBPS": CanSpeed.CAN_100KBPS, "125KBPS": CanSpeed.CAN_125KBPS, "250KBPS": CanSpeed.CAN_250KBPS, "500KBPS": CanSpeed.CAN_500KBPS, + "800KBPS": CanSpeed.CAN_800KBPS, "1000KBPS": CanSpeed.CAN_1000KBPS, } +CAN_SPEEDS_ESP32_S2 = { + "1KBPS": CanSpeed.CAN_1KBPS, + "5KBPS": CanSpeed.CAN_5KBPS, + "10KBPS": CanSpeed.CAN_10KBPS, + "12K5BPS": CanSpeed.CAN_12K5BPS, + "16KBPS": CanSpeed.CAN_16KBPS, + "20KBPS": CanSpeed.CAN_20KBPS, + **CAN_SPEEDS_ESP32, +} + +CAN_SPEEDS_ESP32_S3 = {**CAN_SPEEDS_ESP32_S2} +CAN_SPEEDS_ESP32_C3 = {**CAN_SPEEDS_ESP32_S2} +CAN_SPEEDS_ESP32_H2 = {**CAN_SPEEDS_ESP32_S2} + +CAN_SPEEDS = { + VARIANT_ESP32: CAN_SPEEDS_ESP32, + VARIANT_ESP32S2: CAN_SPEEDS_ESP32_S2, + VARIANT_ESP32S3: CAN_SPEEDS_ESP32_S3, + VARIANT_ESP32C3: CAN_SPEEDS_ESP32_C3, + VARIANT_ESP32H2: CAN_SPEEDS_ESP32_H2, +} + + +def validate_bit_rate(value): + variant = get_esp32_variant() + if variant not in CAN_SPEEDS: + raise cv.Invalid(f"{variant} is not supported by component {esp32_can_ns}") + value = value.upper() + if value not in CAN_SPEEDS[variant]: + raise cv.Invalid(f"Bit rate {value} is not supported on {variant}") + return cv.enum(CAN_SPEEDS[variant])(value) + + CONFIG_SCHEMA = canbus.CANBUS_SCHEMA.extend( { cv.GenerateID(): cv.declare_id(esp32_can), - cv.Optional(CONF_BIT_RATE, default="125KBPS"): cv.enum(CAN_SPEEDS, upper=True), + 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, } diff --git a/esphome/components/esp32_can/esp32_can.cpp b/esphome/components/esp32_can/esp32_can.cpp index 3eb2d1f035..79e4b70f97 100644 --- a/esphome/components/esp32_can/esp32_can.cpp +++ b/esphome/components/esp32_can/esp32_can.cpp @@ -16,6 +16,30 @@ static const char *const TAG = "esp32_can"; static bool get_bitrate(canbus::CanSpeed bitrate, twai_timing_config_t *t_config) { switch (bitrate) { +#if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32C3) || \ + defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32H6) + case canbus::CAN_1KBPS: + *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_1KBITS(); + return true; + case canbus::CAN_5KBPS: + *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_5KBITS(); + return true; + case canbus::CAN_10KBPS: + *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_10KBITS(); + return true; + case canbus::CAN_12K5BPS: + *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_12_5KBITS(); + return true; + case canbus::CAN_16KBPS: + *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_16KBITS(); + return true; + case canbus::CAN_20KBPS: + *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_20KBITS(); + return true; +#endif + case canbus::CAN_25KBPS: + *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_25KBITS(); + return true; case canbus::CAN_50KBPS: *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_50KBITS(); return true; @@ -31,6 +55,9 @@ static bool get_bitrate(canbus::CanSpeed bitrate, twai_timing_config_t *t_config case canbus::CAN_500KBPS: *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_500KBITS(); return true; + case canbus::CAN_800KBPS: + *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_800KBITS(); + return true; case canbus::CAN_1000KBPS: *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_1MBITS(); return true; From 562f7c8718912de531780037ddb47199340b49d0 Mon Sep 17 00:00:00 2001 From: kahrendt Date: Mon, 4 Sep 2023 22:02:59 -0400 Subject: [PATCH 0125/2101] Debug component: add free PSRAM sensor (#5334) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/debug/debug_component.cpp | 10 ++++++ esphome/components/debug/debug_component.h | 6 ++++ esphome/components/debug/sensor.py | 32 +++++++++++++++----- tests/test1.yaml | 10 +++++- tests/test5.yaml | 14 +++++++++ tests/test8.yaml | 15 +++++++++ 6 files changed, 78 insertions(+), 9 deletions(-) diff --git a/esphome/components/debug/debug_component.cpp b/esphome/components/debug/debug_component.cpp index 52ee4b070e..67b07237b7 100644 --- a/esphome/components/debug/debug_component.cpp +++ b/esphome/components/debug/debug_component.cpp @@ -145,6 +145,10 @@ void DebugComponent::dump_config() { features += "BT,"; info.features &= ~CHIP_FEATURE_BT; } + if (info.features & CHIP_FEATURE_EMB_PSRAM) { + features += "EMB_PSRAM,"; + info.features &= ~CHIP_FEATURE_EMB_PSRAM; + } if (info.features) features += "Other:" + format_hex(info.features); ESP_LOGD(TAG, "Chip: Model=%s, Features=%s Cores=%u, Revision=%u", model, features.c_str(), info.cores, @@ -423,6 +427,12 @@ void DebugComponent::update() { this->loop_time_sensor_->publish_state(this->max_loop_time_); this->max_loop_time_ = 0; } + +#ifdef USE_ESP32 + if (this->psram_sensor_ != nullptr) { + this->psram_sensor_->publish_state(heap_caps_get_free_size(MALLOC_CAP_SPIRAM)); + } +#endif // USE_ESP32 #endif // USE_SENSOR } diff --git a/esphome/components/debug/debug_component.h b/esphome/components/debug/debug_component.h index b80fda55eb..93e3ba4857 100644 --- a/esphome/components/debug/debug_component.h +++ b/esphome/components/debug/debug_component.h @@ -33,6 +33,9 @@ class DebugComponent : public PollingComponent { void set_fragmentation_sensor(sensor::Sensor *fragmentation_sensor) { fragmentation_sensor_ = fragmentation_sensor; } #endif void set_loop_time_sensor(sensor::Sensor *loop_time_sensor) { loop_time_sensor_ = loop_time_sensor; } +#ifdef USE_ESP32 + void set_psram_sensor(sensor::Sensor *psram_sensor) { this->psram_sensor_ = psram_sensor; } +#endif // USE_ESP32 #endif // USE_SENSOR protected: uint32_t free_heap_{}; @@ -47,6 +50,9 @@ class DebugComponent : public PollingComponent { sensor::Sensor *fragmentation_sensor_{nullptr}; #endif sensor::Sensor *loop_time_sensor_{nullptr}; +#ifdef USE_ESP32 + sensor::Sensor *psram_sensor_{nullptr}; +#endif // USE_ESP32 #endif // USE_SENSOR #ifdef USE_TEXT_SENSOR diff --git a/esphome/components/debug/sensor.py b/esphome/components/debug/sensor.py index f7ea07d138..061c2750e4 100644 --- a/esphome/components/debug/sensor.py +++ b/esphome/components/debug/sensor.py @@ -17,6 +17,8 @@ from . import CONF_DEBUG_ID, DebugComponent DEPENDENCIES = ["debug"] +CONF_PSRAM = "psram" + CONFIG_SCHEMA = { cv.GenerateID(CONF_DEBUG_ID): cv.use_id(DebugComponent), cv.Optional(CONF_FREE): sensor.sensor_schema( @@ -47,24 +49,38 @@ CONFIG_SCHEMA = { accuracy_decimals=0, entity_category=ENTITY_CATEGORY_DIAGNOSTIC, ), + cv.Optional(CONF_PSRAM): cv.All( + cv.only_on_esp32, + cv.requires_component("psram"), + sensor.sensor_schema( + unit_of_measurement=UNIT_BYTES, + icon=ICON_COUNTER, + accuracy_decimals=0, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + ), + ), } async def to_code(config): debug_component = await cg.get_variable(config[CONF_DEBUG_ID]) - if CONF_FREE in config: - sens = await sensor.new_sensor(config[CONF_FREE]) + if free_conf := config.get(CONF_FREE): + sens = await sensor.new_sensor(free_conf) cg.add(debug_component.set_free_sensor(sens)) - if CONF_BLOCK in config: - sens = await sensor.new_sensor(config[CONF_BLOCK]) + if block_conf := config.get(CONF_BLOCK): + sens = await sensor.new_sensor(block_conf) cg.add(debug_component.set_block_sensor(sens)) - if CONF_FRAGMENTATION in config: - sens = await sensor.new_sensor(config[CONF_FRAGMENTATION]) + if fragmentation_conf := config.get(CONF_FRAGMENTATION): + sens = await sensor.new_sensor(fragmentation_conf) cg.add(debug_component.set_fragmentation_sensor(sens)) - if CONF_LOOP_TIME in config: - sens = await sensor.new_sensor(config[CONF_LOOP_TIME]) + 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)) + + if psram_conf := config.get(CONF_PSRAM): + sens = await sensor.new_sensor(psram_conf) + cg.add(debug_component.set_psram_sensor(sens)) diff --git a/tests/test1.yaml b/tests/test1.yaml index efca34247b..b78407069d 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -1448,6 +1448,15 @@ sensor: pressure: name: "BMP581 Pressure" oversampling: 128x + - platform: debug + free: + name: "Heap Free" + block: + name: "Heap Max Block" + loop_time: + name: "Loop Time" + psram: + name: "PSRAM Free" esp32_touch: setup_mode: false @@ -3448,7 +3457,6 @@ number: still_threshold: name: g8 still threshold - select: - platform: template id: test_select diff --git a/tests/test5.yaml b/tests/test5.yaml index a2530d799a..a1cc3103d7 100644 --- a/tests/test5.yaml +++ b/tests/test5.yaml @@ -28,6 +28,10 @@ ota: logger: +debug: + +psram: + uart: - id: uart_1 tx_pin: 1 @@ -525,6 +529,16 @@ sensor: time: name: System Time + - platform: debug + free: + name: "Heap Free" + block: + name: "Heap Max Block" + loop_time: + name: "Loop Time" + psram: + name: "PSRAM Free" + - platform: vbus model: custom command: 0x100 diff --git a/tests/test8.yaml b/tests/test8.yaml index 8d031b033f..28c6e78b87 100644 --- a/tests/test8.yaml +++ b/tests/test8.yaml @@ -14,6 +14,10 @@ esphome: logger: +debug: + +psram: + light: - platform: neopixelbus type: GRB @@ -50,3 +54,14 @@ binary_sensor: - platform: tt21100 name: Home Button index: 1 + +sensor: + - platform: debug + free: + name: "Heap Free" + block: + name: "Max Block Free" + loop_time: + name: "Loop Time" + psram: + name: "PSRAM Free" From b11824b0587fd23317959bfbf02e3f1eb445cfc0 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 5 Sep 2023 14:33:42 +1200 Subject: [PATCH 0126/2101] libretiny: fix uart_port framework config (#5343) --- esphome/components/libretiny/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/libretiny/__init__.py b/esphome/components/libretiny/__init__.py index c6c63b48c8..ac294d3f65 100644 --- a/esphome/components/libretiny/__init__.py +++ b/esphome/components/libretiny/__init__.py @@ -218,7 +218,7 @@ FRAMEWORK_SCHEMA = cv.All( cv.Optional(CONF_SDK_SILENT, default="all"): ( cv.one_of("all", "auto", "none", lower=True) ), - cv.Optional(CONF_UART_PORT, default=None): cv.one_of(0, 1, 2, int=True), + cv.Optional(CONF_UART_PORT): cv.one_of(0, 1, 2, int=True), cv.Optional(CONF_GPIO_RECOVER, default=True): cv.boolean, cv.Optional(CONF_OPTIONS, default={}): { cv.string_strict: cv.string, @@ -309,8 +309,8 @@ async def component_to_code(config): lt_options["LT_UART_SILENT_ENABLED"] = 0 lt_options["LT_UART_SILENT_ALL"] = 0 # set default UART port - if framework[CONF_UART_PORT] is not None: - lt_options["LT_UART_DEFAULT_PORT"] = framework[CONF_UART_PORT] + if uart_port := framework.get(CONF_UART_PORT, None) is not None: + lt_options["LT_UART_DEFAULT_PORT"] = uart_port # add custom options lt_options.update(framework[CONF_OPTIONS]) From 343278b29108a1f4e331fda4116244dc9f5a35a9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Sep 2023 18:11:46 +1200 Subject: [PATCH 0127/2101] Bump actions/checkout from 3 to 4 (#5341) Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-docker.yml | 2 +- .github/workflows/ci.yml | 22 +++++++++++----------- .github/workflows/release.yml | 6 +++--- .github/workflows/sync-device-classes.yml | 4 ++-- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/ci-docker.yml b/.github/workflows/ci-docker.yml index eb3a5a945c..394379d675 100644 --- a/.github/workflows/ci-docker.yml +++ b/.github/workflows/ci-docker.yml @@ -40,7 +40,7 @@ jobs: arch: [amd64, armv7, aarch64] build_type: ["ha-addon", "docker", "lint"] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v4 with: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ba46936952..1de5822960 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,7 +30,7 @@ jobs: cache-key: ${{ steps.cache-key.outputs.key }} steps: - name: Check out code from GitHub - uses: actions/checkout@v3.5.2 + uses: actions/checkout@v4 - name: Generate cache-key id: cache-key run: echo key="${{ hashFiles('requirements.txt', 'requirements_optional.txt', 'requirements_test.txt') }}" >> $GITHUB_OUTPUT @@ -60,7 +60,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code from GitHub - uses: actions/checkout@v3.5.2 + uses: actions/checkout@v4 - name: Run yamllint uses: frenck/action-yamllint@v1.4.1 @@ -71,7 +71,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v3.5.2 + uses: actions/checkout@v4 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -92,7 +92,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v3.5.2 + uses: actions/checkout@v4 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -113,7 +113,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v3.5.2 + uses: actions/checkout@v4 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -134,7 +134,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v3.5.2 + uses: actions/checkout@v4 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -155,7 +155,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v3.5.2 + uses: actions/checkout@v4 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -176,7 +176,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v3.5.2 + uses: actions/checkout@v4 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -196,7 +196,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v3.5.2 + uses: actions/checkout@v4 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -235,7 +235,7 @@ jobs: file: [1, 2, 3, 3.1, 4, 5, 6, 7, 8] steps: - name: Check out code from GitHub - uses: actions/checkout@v3.5.2 + uses: actions/checkout@v4 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -291,7 +291,7 @@ jobs: steps: - name: Check out code from GitHub - uses: actions/checkout@v3.5.2 + uses: actions/checkout@v4 - name: Restore Python uses: ./.github/actions/restore-python with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 74ff4d87f4..71a0cd2c78 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,7 +19,7 @@ jobs: outputs: tag: ${{ steps.tag.outputs.tag }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Get tag id: tag # yamllint disable rule:line-length @@ -43,7 +43,7 @@ jobs: if: github.repository == 'esphome/esphome' && github.event_name == 'release' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v4 with: @@ -88,7 +88,7 @@ jobs: target: "lint" baseimg: "docker" steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v4 with: diff --git a/.github/workflows/sync-device-classes.yml b/.github/workflows/sync-device-classes.yml index 7067300826..1759db962c 100644 --- a/.github/workflows/sync-device-classes.yml +++ b/.github/workflows/sync-device-classes.yml @@ -14,10 +14,10 @@ jobs: if: github.repository == 'esphome/esphome' steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Checkout Home Assistant - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: home-assistant/core path: lib/home-assistant From 32b24726ed5bc9dfa18c8a8d3bb41c2f25d65144 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Tue, 5 Sep 2023 17:01:28 +1000 Subject: [PATCH 0128/2101] Add Lilygo T-Embed to st7789v display config. (#5337) * Add Lilygo T-Embed to st7789v display config. * Move all configuration into the Python code. Add presets for TTGO. All preset configuration can be overridden. * Add Adafruit S2 pin presets * Add test * Add funhouse pins. Co-authored-by: Keith Burzinski * Keep ordering of options consistent * Remove unused declarations --------- Co-authored-by: Keith Burzinski --- esphome/components/st7789v/display.py | 133 ++++++++++++++++++------- esphome/components/st7789v/st7789v.cpp | 62 ++---------- esphome/components/st7789v/st7789v.h | 13 +-- tests/test2.yaml | 8 ++ 4 files changed, 112 insertions(+), 104 deletions(-) diff --git a/esphome/components/st7789v/display.py b/esphome/components/st7789v/display.py index 16c1e790bd..ad152bf356 100644 --- a/esphome/components/st7789v/display.py +++ b/esphome/components/st7789v/display.py @@ -12,6 +12,8 @@ from esphome.const import ( CONF_RESET_PIN, CONF_WIDTH, CONF_POWER_SUPPLY, + CONF_ROTATION, + CONF_CS_PIN, ) from . import st7789v_ns @@ -26,48 +28,106 @@ DEPENDENCIES = ["spi"] ST7789V = st7789v_ns.class_( "ST7789V", cg.PollingComponent, spi.SPIDevice, display.DisplayBuffer ) -ST7789VRef = ST7789V.operator("ref") -ST7789VModel = st7789v_ns.enum("ST7789VModel") + +MODEL_PRESETS = "model_presets" +REQUIRE_PS = "require_ps" + + +def model_spec(require_ps=False, presets=None): + if presets is None: + presets = {} + return {MODEL_PRESETS: presets, REQUIRE_PS: require_ps} + MODELS = { - "TTGO_TDISPLAY_135X240": ST7789VModel.ST7789V_MODEL_TTGO_TDISPLAY_135_240, - "ADAFRUIT_FUNHOUSE_240X240": ST7789VModel.ST7789V_MODEL_ADAFRUIT_FUNHOUSE_240_240, - "ADAFRUIT_RR_280X240": ST7789VModel.ST7789V_MODEL_ADAFRUIT_RR_280_240, - "ADAFRUIT_S2_TFT_FEATHER_240X135": ST7789VModel.ST7789V_MODEL_ADAFRUIT_S2_TFT_FEATHER_240_135, - "CUSTOM": ST7789VModel.ST7789V_MODEL_CUSTOM, + "TTGO_TDISPLAY_135X240": model_spec( + presets={ + CONF_HEIGHT: 240, + CONF_WIDTH: 135, + CONF_OFFSET_HEIGHT: 52, + CONF_OFFSET_WIDTH: 40, + CONF_CS_PIN: "GPIO5", + CONF_DC_PIN: "GPIO16", + CONF_RESET_PIN: "GPIO23", + CONF_BACKLIGHT_PIN: "GPIO4", + } + ), + "ADAFRUIT_FUNHOUSE_240X240": model_spec( + presets={ + CONF_HEIGHT: 240, + CONF_WIDTH: 240, + CONF_OFFSET_HEIGHT: 0, + CONF_OFFSET_WIDTH: 0, + CONF_CS_PIN: "GPIO40", + CONF_DC_PIN: "GPIO39", + CONF_RESET_PIN: "GPIO41", + } + ), + "ADAFRUIT_RR_280X240": model_spec( + presets={ + CONF_HEIGHT: 280, + CONF_WIDTH: 240, + CONF_OFFSET_HEIGHT: 0, + CONF_OFFSET_WIDTH: 20, + } + ), + "ADAFRUIT_S2_TFT_FEATHER_240X135": model_spec( + require_ps=True, + presets={ + CONF_HEIGHT: 240, + CONF_WIDTH: 135, + CONF_OFFSET_HEIGHT: 52, + CONF_OFFSET_WIDTH: 40, + CONF_CS_PIN: "GPIO7", + CONF_DC_PIN: "GPIO39", + CONF_RESET_PIN: "GPIO40", + CONF_BACKLIGHT_PIN: "GPIO45", + }, + ), + "LILYGO_T-EMBED_170X320": model_spec( + presets={ + CONF_HEIGHT: 320, + CONF_WIDTH: 170, + CONF_OFFSET_HEIGHT: 35, + CONF_OFFSET_WIDTH: 0, + CONF_ROTATION: 270, + CONF_CS_PIN: "GPIO10", + CONF_DC_PIN: "GPIO13", + CONF_RESET_PIN: "GPIO9", + CONF_BACKLIGHT_PIN: "GPIO15", + } + ), + "CUSTOM": model_spec(), } -ST7789V_MODEL = cv.enum(MODELS, upper=True, space="_") - def validate_st7789v(config): - if config[CONF_MODEL].upper() == "CUSTOM" and ( - CONF_HEIGHT not in config - or CONF_WIDTH not in config - or CONF_OFFSET_HEIGHT not in config - or CONF_OFFSET_WIDTH not in config - ): - raise cv.Invalid( - f'{CONF_HEIGHT}, {CONF_WIDTH}, {CONF_OFFSET_HEIGHT} and {CONF_OFFSET_WIDTH} must be specified when {CONF_MODEL} is "CUSTOM"' - ) + model_data = MODELS[config[CONF_MODEL]] + presets = model_data[MODEL_PRESETS] + for key, value in presets.items(): + if key not in config: + if key.endswith("pin"): + # All pins are output. + value = pins.gpio_output_pin_schema(value) + config[key] = value - if config[CONF_MODEL].upper() != "CUSTOM" and ( - CONF_HEIGHT in config - or CONF_WIDTH in config - or CONF_OFFSET_HEIGHT in config - or CONF_OFFSET_WIDTH in config - ): + if model_data[REQUIRE_PS] and CONF_POWER_SUPPLY not in config: raise cv.Invalid( - f'Do not specify {CONF_HEIGHT}, {CONF_WIDTH}, {CONF_OFFSET_HEIGHT} or {CONF_OFFSET_WIDTH} when using {CONF_MODEL} that is not "CUSTOM"' + f'{CONF_POWER_SUPPLY} must be specified when {CONF_MODEL} is {config[CONF_MODEL]}"' ) if ( - config[CONF_MODEL].upper() == "ADAFRUIT_S2_TFT_FEATHER_240X135" - and CONF_POWER_SUPPLY not in config + CONF_OFFSET_WIDTH not in config + or CONF_OFFSET_HEIGHT not in config + or CONF_HEIGHT not in config + or CONF_WIDTH not in config ): raise cv.Invalid( - f'{CONF_POWER_SUPPLY} must be specified when {CONF_MODEL} is "ADAFRUIT_S2_TFT_FEATHER_240X135"' + f"{CONF_HEIGHT}, {CONF_WIDTH}, {CONF_OFFSET_HEIGHT} and {CONF_OFFSET_WIDTH} must all be specified" ) + if CONF_DC_PIN not in config or CONF_RESET_PIN not in config: + raise cv.Invalid(f"both {CONF_DC_PIN} and {CONF_RESET_PIN} must be specified") + return config @@ -75,9 +135,9 @@ CONFIG_SCHEMA = cv.All( display.FULL_DISPLAY_SCHEMA.extend( { cv.GenerateID(): cv.declare_id(ST7789V), - cv.Required(CONF_MODEL): ST7789V_MODEL, - cv.Required(CONF_RESET_PIN): pins.gpio_output_pin_schema, - cv.Required(CONF_DC_PIN): pins.gpio_output_pin_schema, + cv.Required(CONF_MODEL): cv.one_of(*MODELS.keys(), upper=True, space="_"), + cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, + cv.Optional(CONF_DC_PIN): pins.gpio_output_pin_schema, cv.Optional(CONF_BACKLIGHT_PIN): pins.gpio_output_pin_schema, cv.Optional(CONF_POWER_SUPPLY): cv.use_id(power_supply.PowerSupply), cv.Optional(CONF_EIGHTBITCOLOR, default=False): cv.boolean, @@ -99,13 +159,12 @@ async def to_code(config): await display.register_display(var, config) await spi.register_spi_device(var, config) - cg.add(var.set_model(config[CONF_MODEL])) + cg.add(var.set_model_str(config[CONF_MODEL])) - if config[CONF_MODEL].upper() == "CUSTOM": - cg.add(var.set_height(config[CONF_HEIGHT])) - cg.add(var.set_width(config[CONF_WIDTH])) - cg.add(var.set_offset_height(config[CONF_OFFSET_HEIGHT])) - cg.add(var.set_offset_width(config[CONF_OFFSET_WIDTH])) + cg.add(var.set_height(config[CONF_HEIGHT])) + cg.add(var.set_width(config[CONF_WIDTH])) + cg.add(var.set_offset_height(config[CONF_OFFSET_HEIGHT])) + cg.add(var.set_offset_width(config[CONF_OFFSET_WIDTH])) cg.add(var.set_eightbitcolor(config[CONF_EIGHTBITCOLOR])) diff --git a/esphome/components/st7789v/st7789v.cpp b/esphome/components/st7789v/st7789v.cpp index f29182e634..a181723546 100644 --- a/esphome/components/st7789v/st7789v.cpp +++ b/esphome/components/st7789v/st7789v.cpp @@ -122,11 +122,11 @@ void ST7789V::setup() { void ST7789V::dump_config() { LOG_DISPLAY("", "SPI ST7789V", this); - ESP_LOGCONFIG(TAG, " Model: %s", this->model_str_()); - if (this->model_ == ST7789V_MODEL_CUSTOM) { - ESP_LOGCONFIG(TAG, " Height Offset: %u", this->offset_height_); - ESP_LOGCONFIG(TAG, " Width Offset: %u", this->offset_width_); - } + ESP_LOGCONFIG(TAG, " Model: %s", this->model_str_); + ESP_LOGCONFIG(TAG, " Height: %u", this->height_); + ESP_LOGCONFIG(TAG, " Width: %u", this->width_); + ESP_LOGCONFIG(TAG, " Height Offset: %u", this->offset_height_); + ESP_LOGCONFIG(TAG, " Width Offset: %u", this->offset_width_); ESP_LOGCONFIG(TAG, " 8-bit color mode: %s", YESNO(this->eightbitcolor_)); LOG_PIN(" CS Pin: ", this->cs_); LOG_PIN(" DC Pin: ", this->dc_pin_); @@ -145,42 +145,7 @@ void ST7789V::update() { this->write_display_data(); } -void ST7789V::set_model(ST7789VModel model) { - this->model_ = model; - - switch (this->model_) { - case ST7789V_MODEL_TTGO_TDISPLAY_135_240: - this->height_ = 240; - this->width_ = 135; - this->offset_height_ = 52; - this->offset_width_ = 40; - break; - - case ST7789V_MODEL_ADAFRUIT_FUNHOUSE_240_240: - this->height_ = 240; - this->width_ = 240; - this->offset_height_ = 0; - this->offset_width_ = 0; - break; - - case ST7789V_MODEL_ADAFRUIT_RR_280_240: - this->height_ = 280; - this->width_ = 240; - this->offset_height_ = 0; - this->offset_width_ = 20; - break; - - case ST7789V_MODEL_ADAFRUIT_S2_TFT_FEATHER_240_135: - this->height_ = 240; - this->width_ = 135; - this->offset_height_ = 52; - this->offset_width_ = 40; - break; - - default: - break; - } -} +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_; @@ -339,20 +304,5 @@ void HOT ST7789V::draw_absolute_pixel_internal(int x, int y, Color color) { } } -const char *ST7789V::model_str_() { - switch (this->model_) { - case ST7789V_MODEL_TTGO_TDISPLAY_135_240: - return "TTGO T-Display 135x240"; - case ST7789V_MODEL_ADAFRUIT_FUNHOUSE_240_240: - return "Adafruit Funhouse 240x240"; - case ST7789V_MODEL_ADAFRUIT_RR_280_240: - return "Adafruit Round-Rectangular 280x240"; - case ST7789V_MODEL_ADAFRUIT_S2_TFT_FEATHER_240_135: - return "Adafruit ESP32-S2 TFT Feather"; - default: - return "Custom"; - } -} - } // namespace st7789v } // namespace esphome diff --git a/esphome/components/st7789v/st7789v.h b/esphome/components/st7789v/st7789v.h index 56132e8ea2..22093301e2 100644 --- a/esphome/components/st7789v/st7789v.h +++ b/esphome/components/st7789v/st7789v.h @@ -10,14 +10,6 @@ namespace esphome { namespace st7789v { -enum ST7789VModel { - ST7789V_MODEL_TTGO_TDISPLAY_135_240, - ST7789V_MODEL_ADAFRUIT_FUNHOUSE_240_240, - ST7789V_MODEL_ADAFRUIT_RR_280_240, - ST7789V_MODEL_ADAFRUIT_S2_TFT_FEATHER_240_135, - ST7789V_MODEL_CUSTOM -}; - static const uint8_t ST7789_NOP = 0x00; // No Operation static const uint8_t ST7789_SWRESET = 0x01; // Software Reset static const uint8_t ST7789_RDDID = 0x04; // Read Display ID @@ -120,7 +112,7 @@ class ST7789V : public PollingComponent, public spi::SPIDevice { public: - void set_model(ST7789VModel model); + void set_model_str(const char *model_str); void set_dc_pin(GPIOPin *dc_pin) { this->dc_pin_ = dc_pin; } void set_reset_pin(GPIOPin *reset_pin) { this->reset_pin_ = reset_pin; } void set_backlight_pin(GPIOPin *backlight_pin) { this->backlight_pin_ = backlight_pin; } @@ -146,7 +138,6 @@ class ST7789V : public PollingComponent, display::DisplayType get_display_type() override { return display::DisplayType::DISPLAY_TYPE_COLOR; } protected: - ST7789VModel model_{ST7789V_MODEL_TTGO_TDISPLAY_135_240}; GPIOPin *dc_pin_{nullptr}; GPIOPin *reset_pin_{nullptr}; GPIOPin *backlight_pin_{nullptr}; @@ -175,7 +166,7 @@ class ST7789V : public PollingComponent, void draw_absolute_pixel_internal(int x, int y, Color color) override; - const char *model_str_(); + const char *model_str_; }; } // namespace st7789v diff --git a/tests/test2.yaml b/tests/test2.yaml index d1508632b3..adc57f4f7e 100644 --- a/tests/test2.yaml +++ b/tests/test2.yaml @@ -710,6 +710,14 @@ interval: - logger.log: Interval Run display: + - platform: st7789v + model: LILYGO_T-EMBED_170X320 + height: 320 + width: 170 + offset_height: 35 + offset_width: 0 + dc_pin: GPIO13 + reset_pin: GPIO9 image: - id: binary_image From 97dcbe84da0c8ff9d6044e7d2d059c0161b5170a Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Tue, 5 Sep 2023 09:56:17 +0200 Subject: [PATCH 0129/2101] Disable IPv6 when config explicitly says false (#5310) --- .../ethernet/ethernet_component.cpp | 20 +++++++++---------- esphome/components/network/__init__.py | 1 + .../wifi/wifi_component_esp32_arduino.cpp | 8 ++++---- .../wifi/wifi_component_esp_idf.cpp | 14 ++++++------- 4 files changed, 22 insertions(+), 21 deletions(-) diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index d9004a913b..59d2e4c4d6 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -118,10 +118,10 @@ void EthernetComponent::setup() { 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 LWIP_IPV6 +#if ENABLE_IPV6 err = esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6, &EthernetComponent::got_ip6_event_handler, nullptr); ESPHL_ERROR_CHECK(err, "GOT IP6 event handler register error"); -#endif /* LWIP_IPV6 */ +#endif /* ENABLE_IPV6 */ /* start Ethernet driver state machine */ err = esp_eth_start(this->eth_handle_); @@ -164,7 +164,7 @@ void EthernetComponent::loop() { this->state_ = EthernetComponentState::CONNECTING; this->start_connect_(); } -#if LWIP_IPV6 +#if ENABLE_IPV6 else if (this->got_ipv6_) { esp_ip6_addr_t ip6_addr; if (esp_netif_get_ip6_global(this->eth_netif_, &ip6_addr) == 0 && @@ -177,7 +177,7 @@ void EthernetComponent::loop() { this->got_ipv6_ = false; } -#endif /* LWIP_IPV6 */ +#endif /* ENABLE_IPV6 */ break; } } @@ -272,14 +272,14 @@ void EthernetComponent::got_ip_event_handler(void *arg, esp_event_base_t event_b ESP_LOGV(TAG, "[Ethernet event] ETH Got IP (num=%" PRId32 ")", event_id); } -#if LWIP_IPV6 +#if ENABLE_IPV6 void EthernetComponent::got_ip6_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { ESP_LOGV(TAG, "[Ethernet event] ETH Got IP6 (num=%d)", event_id); global_eth_component->got_ipv6_ = true; global_eth_component->ipv6_count_ += 1; } -#endif /* LWIP_IPV6 */ +#endif /* ENABLE_IPV6 */ void EthernetComponent::start_connect_() { this->connect_begin_ = millis(); @@ -343,12 +343,12 @@ void EthernetComponent::start_connect_() { if (err != ESP_ERR_ESP_NETIF_DHCP_ALREADY_STARTED) { ESPHL_ERROR_CHECK(err, "DHCPC start error"); } -#if LWIP_IPV6 +#if ENABLE_IPV6 err = esp_netif_create_ip6_linklocal(this->eth_netif_); if (err != ESP_OK) { ESPHL_ERROR_CHECK(err, "IPv6 local failed"); } -#endif /* LWIP_IPV6 */ +#endif /* ENABLE_IPV6 */ } this->connect_begin_ = millis(); @@ -376,7 +376,7 @@ void EthernetComponent::dump_connect_params_() { ESP_LOGCONFIG(TAG, " DNS2: %s", network::IPAddress(dns_ip2->addr).str().c_str()); #endif -#if LWIP_IPV6 +#if ENABLE_IPV6 if (this->ipv6_count_ > 0) { esp_ip6_addr_t ip6_addr; esp_netif_get_ip6_linklocal(this->eth_netif_, &ip6_addr); @@ -387,7 +387,7 @@ void EthernetComponent::dump_connect_params_() { ESP_LOGCONFIG(TAG, "IPv6 Addr (Global): " IPV6STR, IPV62STR(ip6_addr)); } } -#endif /* LWIP_IPV6 */ +#endif /* ENABLE_IPV6 */ esp_err_t err; diff --git a/esphome/components/network/__init__.py b/esphome/components/network/__init__.py index cd29734f42..83778e0bf4 100644 --- a/esphome/components/network/__init__.py +++ b/esphome/components/network/__init__.py @@ -24,6 +24,7 @@ CONFIG_SCHEMA = cv.Schema( async def to_code(config): if CONF_ENABLE_IPV6 in config: + cg.add_define("ENABLE_IPV6", config[CONF_ENABLE_IPV6]) if CORE.using_esp_idf: add_idf_sdkconfig_option("CONFIG_LWIP_IPV6", config[CONF_ENABLE_IPV6]) add_idf_sdkconfig_option( diff --git a/esphome/components/wifi/wifi_component_esp32_arduino.cpp b/esphome/components/wifi/wifi_component_esp32_arduino.cpp index 95f4e2ce92..5b147b20c6 100644 --- a/esphome/components/wifi/wifi_component_esp32_arduino.cpp +++ b/esphome/components/wifi/wifi_component_esp32_arduino.cpp @@ -447,9 +447,9 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_ buf[it.ssid_len] = '\0'; ESP_LOGV(TAG, "Event: Connected ssid='%s' bssid=" LOG_SECRET("%s") " channel=%u, authmode=%s", buf, format_mac_addr(it.bssid).c_str(), it.channel, get_auth_mode_str(it.authmode)); -#if LWIP_IPV6 +#if ENABLE_IPV6 this->set_timeout(100, [] { WiFi.enableIpV6(); }); -#endif /* LWIP_IPV6 */ +#endif /* ENABLE_IPV6 */ break; } @@ -504,13 +504,13 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_ s_sta_connecting = false; break; } -#if LWIP_IPV6 +#if ENABLE_IPV6 case ESPHOME_EVENT_ID_WIFI_STA_GOT_IP6: { auto it = info.got_ip6.ip6_info; ESP_LOGV(TAG, "Got IPv6 address=" IPV6STR, IPV62STR(it.ip)); break; } -#endif /* LWIP_IPV6 */ +#endif /* ENABLE_IPV6 */ case ESPHOME_EVENT_ID_WIFI_STA_LOST_IP: { ESP_LOGV(TAG, "Event: Lost IP"); break; diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index 9041679ccf..0ff9e932b2 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -58,9 +58,9 @@ struct IDFWiFiEvent { wifi_event_ap_probe_req_rx_t ap_probe_req_rx; wifi_event_bss_rssi_low_t bss_rssi_low; ip_event_got_ip_t ip_got_ip; -#if LWIP_IPV6 +#if ENABLE_IPV6 ip_event_got_ip6_t ip_got_ip6; -#endif +#endif /* ENABLE_IPV6 */ ip_event_ap_staipassigned_t ip_ap_staipassigned; } data; }; @@ -84,7 +84,7 @@ void event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, voi memcpy(&event.data.sta_disconnected, event_data, sizeof(wifi_event_sta_disconnected_t)); } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { memcpy(&event.data.ip_got_ip, event_data, sizeof(ip_event_got_ip_t)); -#if LWIP_IPV6 +#if ENABLE_IPV6 } else if (event_base == IP_EVENT && event_id == IP_EVENT_GOT_IP6) { memcpy(&event.data.ip_got_ip6, event_data, sizeof(ip_event_got_ip6_t)); #endif @@ -645,18 +645,18 @@ void WiFiComponent::wifi_process_event_(IDFWiFiEvent *data) { } else if (data->event_base == IP_EVENT && data->event_id == IP_EVENT_STA_GOT_IP) { const auto &it = data->data.ip_got_ip; -#if LWIP_IPV6_AUTOCONFIG +#if ENABLE_IPV6 esp_netif_create_ip6_linklocal(s_sta_netif); -#endif +#endif /* ENABLE_IPV6 */ ESP_LOGV(TAG, "Event: Got IP static_ip=%s gateway=%s", format_ip4_addr(it.ip_info.ip).c_str(), format_ip4_addr(it.ip_info.gw).c_str()); s_sta_got_ip = true; -#if LWIP_IPV6 +#if ENABLE_IPV6 } else if (data->event_base == IP_EVENT && data->event_id == IP_EVENT_GOT_IP6) { const auto &it = data->data.ip_got_ip6; ESP_LOGV(TAG, "Event: Got IPv6 address=%s", format_ip6_addr(it.ip6_info.ip).c_str()); -#endif +#endif /* ENABLE_IPV6 */ } else if (data->event_base == IP_EVENT && data->event_id == IP_EVENT_STA_LOST_IP) { ESP_LOGV(TAG, "Event: Lost IP"); From b7a16d5a5968122c9ec9e2937da826b4eb93b274 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Tue, 5 Sep 2023 05:35:20 -0500 Subject: [PATCH 0130/2101] Add defines.h to ethernet_component.h for ENABLE_IPV6 (#5344) --- 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 1bd4786b44..11f50af966 100644 --- a/esphome/components/ethernet/ethernet_component.h +++ b/esphome/components/ethernet/ethernet_component.h @@ -1,6 +1,7 @@ #pragma once #include "esphome/core/component.h" +#include "esphome/core/defines.h" #include "esphome/core/hal.h" #include "esphome/components/network/ip_address.h" From e2d784a5b5dfbf8d6be7f09d3f38ba172272349c Mon Sep 17 00:00:00 2001 From: esphomebot Date: Wed, 6 Sep 2023 07:29:41 +1200 Subject: [PATCH 0131/2101] Synchronise Device Classes from Home Assistant (#5328) --- esphome/const.py | 1 - 1 file changed, 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index d0575a6ebd..067fd23946 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -980,7 +980,6 @@ DEVICE_CLASS_DURATION = "duration" DEVICE_CLASS_EMPTY = "" DEVICE_CLASS_ENERGY = "energy" DEVICE_CLASS_ENERGY_STORAGE = "energy_storage" -DEVICE_CLASS_ENUM = "enum" DEVICE_CLASS_FREQUENCY = "frequency" DEVICE_CLASS_GARAGE = "garage" DEVICE_CLASS_GARAGE_DOOR = "garage_door" From 35b5dadb99f1a22b9a8d3c5ff8603537cb7292e7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Sep 2023 07:32:00 +1200 Subject: [PATCH 0132/2101] Bump pytest from 7.4.0 to 7.4.1 (#5342) 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 7ab6742b02..e160c3e9e3 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -5,7 +5,7 @@ pyupgrade==3.10.1 # also change in .pre-commit-config.yaml when updating pre-commit # Unit tests -pytest==7.4.0 +pytest==7.4.1 pytest-cov==4.1.0 pytest-mock==3.11.1 pytest-asyncio==0.21.1 From 47735d1dae8d2e66eb8b755afc0de3d68d3020af Mon Sep 17 00:00:00 2001 From: Pavlo Dudnytskyi Date: Tue, 5 Sep 2023 21:37:01 +0200 Subject: [PATCH 0133/2101] Fixed default temperature step values for haier climate (#5330) --- esphome/components/haier/climate.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/esphome/components/haier/climate.py b/esphome/components/haier/climate.py index acb079c822..d796f13581 100644 --- a/esphome/components/haier/climate.py +++ b/esphome/components/haier/climate.py @@ -136,12 +136,10 @@ def validate_visual(config): f"Configured visual temperature step {temp_step} is wrong, it should be a multiple of 0.5" ) else: - config[CONF_VISUAL][CONF_TEMPERATURE_STEP] = ( - { - CONF_TARGET_TEMPERATURE: PROTOCOL_TARGET_TEMPERATURE_STEP, - CONF_CURRENT_TEMPERATURE: PROTOCOL_CURRENT_TEMPERATURE_STEP, - }, - ) + config[CONF_VISUAL][CONF_TEMPERATURE_STEP] = { + CONF_TARGET_TEMPERATURE: PROTOCOL_TARGET_TEMPERATURE_STEP, + CONF_CURRENT_TEMPERATURE: PROTOCOL_CURRENT_TEMPERATURE_STEP, + } else: config[CONF_VISUAL] = { CONF_MIN_TEMPERATURE: PROTOCOL_MIN_TEMPERATURE, From ac5c6ec2883115e68cf31d51118f36cbdf8de011 Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Tue, 5 Sep 2023 21:38:58 +0200 Subject: [PATCH 0134/2101] Add debug component to all tests (#5333) --- tests/test2.yaml | 2 ++ tests/test3.1.yaml | 2 ++ tests/test3.yaml | 2 ++ tests/test4.yaml | 2 ++ tests/test6.yaml | 2 ++ tests/test7.yaml | 2 ++ 6 files changed, 12 insertions(+) diff --git a/tests/test2.yaml b/tests/test2.yaml index adc57f4f7e..4928b8b877 100644 --- a/tests/test2.yaml +++ b/tests/test2.yaml @@ -55,6 +55,8 @@ ota: logger: level: DEBUG +debug: + deep_sleep: run_duration: default: 20s diff --git a/tests/test3.1.yaml b/tests/test3.1.yaml index ea8dc337be..16f31409d8 100644 --- a/tests/test3.1.yaml +++ b/tests/test3.1.yaml @@ -39,6 +39,8 @@ ota: logger: +debug: + sensor: - platform: apds9960 type: proximity diff --git a/tests/test3.yaml b/tests/test3.yaml index 471b7d97b6..abfd133c99 100644 --- a/tests/test3.yaml +++ b/tests/test3.yaml @@ -287,6 +287,8 @@ logger: level: DEBUG esp8266_store_log_strings_in_flash: true +debug: + improv_serial: next_url: https://esphome.io/?name={{device_name}}&version={{esphome_version}}&ip={{ip_address}} diff --git a/tests/test4.yaml b/tests/test4.yaml index 54caebf1fe..1175bb207c 100644 --- a/tests/test4.yaml +++ b/tests/test4.yaml @@ -50,6 +50,8 @@ ota: logger: level: DEBUG +debug: + web_server: ota: false auth: diff --git a/tests/test6.yaml b/tests/test6.yaml index 6224563a77..f048a4fa14 100644 --- a/tests/test6.yaml +++ b/tests/test6.yaml @@ -22,6 +22,8 @@ ota: logger: +debug: + binary_sensor: - platform: gpio pin: GPIO5 diff --git a/tests/test7.yaml b/tests/test7.yaml index 8d48c9a601..2355dd6feb 100644 --- a/tests/test7.yaml +++ b/tests/test7.yaml @@ -28,6 +28,8 @@ esphome: logger: +debug: + http_request: useragent: esphome/tagreader timeout: 10s From 82c1988a2d925f78e47036b8c002a2c78d9503ff Mon Sep 17 00:00:00 2001 From: JJ Date: Tue, 5 Sep 2023 14:59:23 -0700 Subject: [PATCH 0135/2101] Support MaxBotix XL in addition to HRXL (#4510) --- .../hrxl_maxsonar_wr/hrxl_maxsonar_wr.cpp | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/esphome/components/hrxl_maxsonar_wr/hrxl_maxsonar_wr.cpp b/esphome/components/hrxl_maxsonar_wr/hrxl_maxsonar_wr.cpp index bd1c82c96b..b56e96badc 100644 --- a/esphome/components/hrxl_maxsonar_wr/hrxl_maxsonar_wr.cpp +++ b/esphome/components/hrxl_maxsonar_wr/hrxl_maxsonar_wr.cpp @@ -1,9 +1,10 @@ // Official Datasheet: -// https://www.maxbotix.com/documents/HRXL-MaxSonar-WR_Datasheet.pdf +// HRXL: https://www.maxbotix.com/documents/HRXL-MaxSonar-WR_Datasheet.pdf +// XL: https://www.maxbotix.com/documents/XL-MaxSonar-WR_Datasheet.pdf // // This implementation is designed to work with the TTL Versions of the -// MaxBotix HRXL MaxSonar WR sensor series. The sensor's TTL Pin (5) should be -// wired to one of the ESP's input pins and configured as uart rx_pin. +// MaxBotix HRXL and XL MaxSonar WR sensor series. The sensor's TTL Pin (5) +// should be wired to one of the ESP's input pins and configured as uart rx_pin. #include "hrxl_maxsonar_wr.h" #include "esphome/core/log.h" @@ -17,8 +18,10 @@ static const uint8_t ASCII_NBSP = 0xFF; static const int MAX_DATA_LENGTH_BYTES = 6; /** - * The sensor outputs something like "R1234\r" at a fixed rate of 6 Hz. Where - * 1234 means a distance of 1,234 m. + * HRXL sensors output the format "R1234\r" at 6Hz + * The 1234 means 1234mm + * XL sensors output the format "R123\r" at 5 to 10Hz + * The 123 means 123cm */ void HrxlMaxsonarWrComponent::loop() { uint8_t data; @@ -42,9 +45,17 @@ void HrxlMaxsonarWrComponent::check_buffer_() { if (this->buffer_.back() == static_cast(ASCII_CR) || this->buffer_.length() >= MAX_DATA_LENGTH_BYTES) { ESP_LOGV(TAG, "Read from serial: %s", this->buffer_.c_str()); - if (this->buffer_.length() == MAX_DATA_LENGTH_BYTES && this->buffer_[0] == 'R' && - this->buffer_.back() == static_cast(ASCII_CR)) { - int millimeters = parse_number(this->buffer_.substr(1, MAX_DATA_LENGTH_BYTES - 2)).value_or(0); + size_t rpos = this->buffer_.find(static_cast(ASCII_CR)); + + if (this->buffer_.length() <= MAX_DATA_LENGTH_BYTES && this->buffer_[0] == 'R' && rpos != std::string::npos) { + std::string distance = this->buffer_.substr(1, rpos - 1); + int millimeters = parse_number(distance).value_or(0); + + // XL reports in cm instead of mm and reports 3 digits instead of 4 + if (distance.length() == 3) { + millimeters = millimeters * 10; + } + float meters = float(millimeters) / 1000.0; ESP_LOGV(TAG, "Distance from sensor: %d mm, %f m", millimeters, meters); this->publish_state(meters); From 74ab940aff7289b2183fe315cd5665e4ba1d36f1 Mon Sep 17 00:00:00 2001 From: JJ Date: Tue, 5 Sep 2023 15:09:22 -0700 Subject: [PATCH 0136/2101] Adding DFRobot Ozone Sensor Support (sen0321) (#4782) --- CODEOWNERS | 1 + esphome/components/sen0321/__init__.py | 1 + esphome/components/sen0321/sen0321.cpp | 36 ++++++++++++++++++++++++++ esphome/components/sen0321/sen0321.h | 35 +++++++++++++++++++++++++ esphome/components/sen0321/sensor.py | 34 ++++++++++++++++++++++++ tests/test1.yaml | 5 ++++ 6 files changed, 112 insertions(+) create mode 100644 esphome/components/sen0321/__init__.py create mode 100644 esphome/components/sen0321/sen0321.cpp create mode 100644 esphome/components/sen0321/sen0321.h create mode 100644 esphome/components/sen0321/sensor.py diff --git a/CODEOWNERS b/CODEOWNERS index 1455643550..384db8098f 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -246,6 +246,7 @@ esphome/components/sdm_meter/* @jesserockz @polyfaces esphome/components/sdp3x/* @Azimath esphome/components/selec_meter/* @sourabhjaiswal esphome/components/select/* @esphome/core +esphome/components/sen0321/* @notjj esphome/components/sen21231/* @shreyaskarnik esphome/components/sen5x/* @martgras esphome/components/sensirion_common/* @martgras diff --git a/esphome/components/sen0321/__init__.py b/esphome/components/sen0321/__init__.py new file mode 100644 index 0000000000..458ffa67f9 --- /dev/null +++ b/esphome/components/sen0321/__init__.py @@ -0,0 +1 @@ +CODEOWNERS = ["@notjj"] diff --git a/esphome/components/sen0321/sen0321.cpp b/esphome/components/sen0321/sen0321.cpp new file mode 100644 index 0000000000..7801c8c389 --- /dev/null +++ b/esphome/components/sen0321/sen0321.cpp @@ -0,0 +1,36 @@ +#include "sen0321.h" +#include "esphome/core/log.h" +#include "esphome/core/hal.h" + +namespace esphome { +namespace sen0321_sensor { + +static const char *const TAG = "sen0321_sensor.sensor"; + +void Sen0321Sensor::setup() { + ESP_LOGCONFIG(TAG, "Setting up sen0321..."); + if (!this->write_byte(SENSOR_MODE_REGISTER, SENSOR_MODE_AUTO)) { + ESP_LOGW(TAG, "Error setting measurement mode."); + this->mark_failed(); + }; +} + +void Sen0321Sensor::update() { this->read_data_(); } + +void Sen0321Sensor::dump_config() { + ESP_LOGCONFIG(TAG, "DF Robot Ozone Sensor sen0321:"); + LOG_I2C_DEVICE(this); + if (this->is_failed()) { + ESP_LOGE(TAG, "Communication with sen0321 failed!"); + } + LOG_UPDATE_INTERVAL(this); +} + +void Sen0321Sensor::read_data_() { + uint8_t result[2]; + this->read_bytes(SENSOR_AUTO_READ_REG, result, (uint8_t) 2); + this->publish_state(((uint16_t) (result[0] << 8) + result[1])); +} + +} // namespace sen0321_sensor +} // namespace esphome diff --git a/esphome/components/sen0321/sen0321.h b/esphome/components/sen0321/sen0321.h new file mode 100644 index 0000000000..3bb3d5b015 --- /dev/null +++ b/esphome/components/sen0321/sen0321.h @@ -0,0 +1,35 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/components/sensor/sensor.h" +#include "esphome/components/i2c/i2c.h" + +// ref: +// https://github.com/DFRobot/DFRobot_OzoneSensor + +namespace esphome { +namespace sen0321_sensor { +// Sensor Mode +// While passive is supposedly supported, it does not appear to work reliably. +static const uint8_t SENSOR_MODE_REGISTER = 0x03; +static const uint8_t SENSOR_MODE_AUTO = 0x00; +static const uint8_t SENSOR_MODE_PASSIVE = 0x01; +static const uint8_t SET_REGISTER = 0x04; + +// Each register is 2 wide, so 0x07-0x08 for passive, or 0x09-0x0A for auto +// First register is high bits, next low. +static const uint8_t SENSOR_PASS_READ_REG = 0x07; +static const uint8_t SENSOR_AUTO_READ_REG = 0x09; + +class Sen0321Sensor : public sensor::Sensor, public PollingComponent, public i2c::I2CDevice { + public: + void update() override; + void dump_config() override; + void setup() override; + + protected: + void read_data_(); +}; + +} // namespace sen0321_sensor +} // namespace esphome diff --git a/esphome/components/sen0321/sensor.py b/esphome/components/sen0321/sensor.py new file mode 100644 index 0000000000..ee613dc440 --- /dev/null +++ b/esphome/components/sen0321/sensor.py @@ -0,0 +1,34 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import i2c, sensor +from esphome.const import ( + ICON_CHEMICAL_WEAPON, + UNIT_PARTS_PER_BILLION, + STATE_CLASS_MEASUREMENT, +) + +CODEOWNERS = ["@notjj"] +DEPENDENCIES = ["i2c"] + +sen0321_sensor_ns = cg.esphome_ns.namespace("sen0321_sensor") +Sen0321Sensor = sen0321_sensor_ns.class_( + "Sen0321Sensor", cg.PollingComponent, i2c.I2CDevice +) + +CONFIG_SCHEMA = ( + sensor.sensor_schema( + Sen0321Sensor, + unit_of_measurement=UNIT_PARTS_PER_BILLION, + icon=ICON_CHEMICAL_WEAPON, + accuracy_decimals=1, + state_class=STATE_CLASS_MEASUREMENT, + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x73)) +) + + +async def to_code(config): + var = await sensor.new_sensor(config) + await cg.register_component(var, config) + await i2c.register_i2c_device(var, config) diff --git a/tests/test1.yaml b/tests/test1.yaml index b78407069d..33782dbf53 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -1081,6 +1081,11 @@ sensor: ambient_pressure_compensation: 961mBar temperature_offset: 4.2C i2c_id: i2c_bus + - platform: sen0321 + name: Workshop Ozone Sensor + id: sen0321_ozone + update_interval: 10s + i2c_id: i2c_bus - platform: sgp30 eco2: name: Workshop eCO2 From feba9ffdc453f978ce6530fa63dcae3ee6d82b19 Mon Sep 17 00:00:00 2001 From: Stijn Tintel Date: Wed, 6 Sep 2023 01:11:07 +0300 Subject: [PATCH 0137/2101] mdns: bump IDF mdns component to 1.2.0 (#5217) --- esphome/components/mdns/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/mdns/__init__.py b/esphome/components/mdns/__init__.py index e7d700d149..fbe1e1a719 100644 --- a/esphome/components/mdns/__init__.py +++ b/esphome/components/mdns/__init__.py @@ -88,7 +88,7 @@ async def to_code(config): add_idf_component( name="mdns", repo="https://github.com/espressif/esp-protocols.git", - ref="mdns-v1.0.9", + ref="mdns-v1.2.0", path="components/mdns", ) From 2cabe59c228d1863cf3616fb6edb429c9909aef6 Mon Sep 17 00:00:00 2001 From: Sebastian Rasor <92653912+sebastianrasor@users.noreply.github.com> Date: Tue, 22 Aug 2023 20:01:34 -0500 Subject: [PATCH 0138/2101] Introduce cv.temperature_delta and fix problematic thermostat configuration behavior (#5297) --- esphome/components/thermostat/climate.py | 14 +++++++------- esphome/config_validation.py | 21 +++++++++++++++++++++ 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/esphome/components/thermostat/climate.py b/esphome/components/thermostat/climate.py index 9a57f6a337..cca46609db 100644 --- a/esphome/components/thermostat/climate.py +++ b/esphome/components/thermostat/climate.py @@ -591,11 +591,11 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_DEFAULT_TARGET_TEMPERATURE_LOW): cv.temperature, cv.Optional( CONF_SET_POINT_MINIMUM_DIFFERENTIAL, default=0.5 - ): cv.temperature, - cv.Optional(CONF_COOL_DEADBAND, default=0.5): cv.temperature, - cv.Optional(CONF_COOL_OVERRUN, default=0.5): cv.temperature, - cv.Optional(CONF_HEAT_DEADBAND, default=0.5): cv.temperature, - cv.Optional(CONF_HEAT_OVERRUN, default=0.5): cv.temperature, + ): cv.temperature_delta, + cv.Optional(CONF_COOL_DEADBAND, default=0.5): cv.temperature_delta, + cv.Optional(CONF_COOL_OVERRUN, default=0.5): cv.temperature_delta, + cv.Optional(CONF_HEAT_DEADBAND, default=0.5): cv.temperature_delta, + cv.Optional(CONF_HEAT_OVERRUN, default=0.5): cv.temperature_delta, cv.Optional(CONF_MAX_COOLING_RUN_TIME): cv.positive_time_period_seconds, cv.Optional(CONF_MAX_HEATING_RUN_TIME): cv.positive_time_period_seconds, cv.Optional(CONF_MIN_COOLING_OFF_TIME): cv.positive_time_period_seconds, @@ -608,8 +608,8 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_MIN_HEATING_OFF_TIME): cv.positive_time_period_seconds, cv.Optional(CONF_MIN_HEATING_RUN_TIME): cv.positive_time_period_seconds, cv.Required(CONF_MIN_IDLE_TIME): cv.positive_time_period_seconds, - cv.Optional(CONF_SUPPLEMENTAL_COOLING_DELTA): cv.temperature, - cv.Optional(CONF_SUPPLEMENTAL_HEATING_DELTA): cv.temperature, + cv.Optional(CONF_SUPPLEMENTAL_COOLING_DELTA): cv.temperature_delta, + cv.Optional(CONF_SUPPLEMENTAL_HEATING_DELTA): cv.temperature_delta, cv.Optional( CONF_FAN_ONLY_ACTION_USES_FAN_MODE_TIMER, default=False ): cv.boolean, diff --git a/esphome/config_validation.py b/esphome/config_validation.py index 3720757828..ed87e98078 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -929,6 +929,27 @@ def temperature(value): raise err +def temperature_delta(value): + err = None + try: + return _temperature_c(value) + except Invalid as orig_err: + err = orig_err + + try: + return _temperature_k(value) + except Invalid: + pass + + try: + fahrenheit = _temperature_f(value) + return fahrenheit * (5 / 9) + except Invalid: + pass + + raise err + + _color_temperature_mireds = float_with_unit("Color Temperature", r"(mireds|Mireds)") _color_temperature_kelvin = float_with_unit("Color Temperature", r"(K|Kelvin)") From c146712b1644deba320195530330c2892793a90f Mon Sep 17 00:00:00 2001 From: luka6000 Date: Fri, 1 Sep 2023 03:20:21 +0200 Subject: [PATCH 0139/2101] fix to PR # 3887 MQTT connection not using discovery: false (#5275) --- esphome/components/mqtt/mqtt_client.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/esphome/components/mqtt/mqtt_client.cpp b/esphome/components/mqtt/mqtt_client.cpp index d3f759c072..1d804170f6 100644 --- a/esphome/components/mqtt/mqtt_client.cpp +++ b/esphome/components/mqtt/mqtt_client.cpp @@ -66,25 +66,28 @@ void MQTTClientComponent::setup() { } #endif - this->subscribe( - "esphome/discover", [this](const std::string &topic, const std::string &payload) { this->send_device_info_(); }, - 2); + if (this->is_discovery_enabled()) { + this->subscribe( + "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()); - this->subscribe( - topic, [this](const std::string &topic, const std::string &payload) { this->send_device_info_(); }, 2); + std::string topic = "esphome/ping/"; + topic.append(App.get_name()); + this->subscribe( + topic, [this](const std::string &topic, const std::string &payload) { this->send_device_info_(); }, 2); + } this->last_connected_ = millis(); this->start_dnslookup_(); } void MQTTClientComponent::send_device_info_() { - if (!this->is_connected()) { + if (!this->is_connected() or !this->is_discovery_enabled()) { return; } std::string topic = "esphome/discover/"; topic.append(App.get_name()); + this->publish_json( topic, [](JsonObject root) { From 3f8bad3ed1748ed1eef8c378c079466054650bbb Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Sat, 2 Sep 2023 08:41:52 +1200 Subject: [PATCH 0140/2101] Attempt to fix secret blurring (#5326) --- esphome/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/__main__.py b/esphome/__main__.py index ca5fc1c008..697adc03a3 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -371,7 +371,7 @@ def command_config(args, config): # add the console decoration so the front-end can hide the secrets if not args.show_secrets: output = re.sub( - r"(password|key|psk|ssid)\:\s(.*)", r"\1: \\033[5m\2\\033[6m", output + r"(password|key|psk|ssid)\: (.+)", r"\1: \\033[5m\2\\033[6m", output ) safe_print(output) _LOGGER.info("Configuration is valid!") From 619787e6d2f4dbf3c860d3b70657e1d62a3cf7a6 Mon Sep 17 00:00:00 2001 From: kahrendt Date: Fri, 1 Sep 2023 16:55:59 -0400 Subject: [PATCH 0141/2101] Bugfix: disable channels after IO if multiple tca9548a I2C multiplexers are configured (#5317) --- esphome/components/tca9548a/tca9548a.cpp | 27 ++++++++++++++---------- esphome/components/tca9548a/tca9548a.h | 4 +++- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/esphome/components/tca9548a/tca9548a.cpp b/esphome/components/tca9548a/tca9548a.cpp index caa3dd0655..770fd5e47c 100644 --- a/esphome/components/tca9548a/tca9548a.cpp +++ b/esphome/components/tca9548a/tca9548a.cpp @@ -7,23 +7,27 @@ namespace tca9548a { static const char *const TAG = "tca9548a"; i2c::ErrorCode TCA9548AChannel::readv(uint8_t address, i2c::ReadBuffer *buffers, size_t cnt) { - auto err = parent_->switch_to_channel(channel_); + auto err = this->parent_->switch_to_channel(channel_); if (err != i2c::ERROR_OK) return err; - return parent_->bus_->readv(address, buffers, cnt); + err = this->parent_->bus_->readv(address, buffers, cnt); + this->parent_->disable_all_channels(); + return err; } i2c::ErrorCode TCA9548AChannel::writev(uint8_t address, i2c::WriteBuffer *buffers, size_t cnt, bool stop) { - auto err = parent_->switch_to_channel(channel_); + auto err = this->parent_->switch_to_channel(channel_); if (err != i2c::ERROR_OK) return err; - return parent_->bus_->writev(address, buffers, cnt, stop); + err = this->parent_->bus_->writev(address, buffers, cnt, stop); + this->parent_->disable_all_channels(); + return err; } void TCA9548AComponent::setup() { ESP_LOGCONFIG(TAG, "Setting up TCA9548A..."); uint8_t status = 0; if (this->read(&status, 1) != i2c::ERROR_OK) { - ESP_LOGI(TAG, "TCA9548A failed"); + ESP_LOGE(TAG, "TCA9548A failed"); this->mark_failed(); return; } @@ -37,15 +41,16 @@ void TCA9548AComponent::dump_config() { i2c::ErrorCode TCA9548AComponent::switch_to_channel(uint8_t channel) { if (this->is_failed()) return i2c::ERROR_NOT_INITIALIZED; - if (current_channel_ == channel) - return i2c::ERROR_OK; uint8_t channel_val = 1 << channel; - auto err = this->write(&channel_val, 1); - if (err == i2c::ERROR_OK) { - current_channel_ = channel; + return this->write(&channel_val, 1); +} + +void TCA9548AComponent::disable_all_channels() { + if (this->write(&TCA9548A_DISABLE_CHANNELS_COMMAND, 1) != i2c::ERROR_OK) { + ESP_LOGE(TAG, "Failed to disable all channels."); + this->status_set_error(); // couldn't disable channels, set error status } - return err; } } // namespace tca9548a diff --git a/esphome/components/tca9548a/tca9548a.h b/esphome/components/tca9548a/tca9548a.h index 02553f8cd0..08f1674d11 100644 --- a/esphome/components/tca9548a/tca9548a.h +++ b/esphome/components/tca9548a/tca9548a.h @@ -6,6 +6,8 @@ namespace esphome { namespace tca9548a { +static const uint8_t TCA9548A_DISABLE_CHANNELS_COMMAND = 0x00; + class TCA9548AComponent; class TCA9548AChannel : public i2c::I2CBus { public: @@ -28,10 +30,10 @@ class TCA9548AComponent : public Component, public i2c::I2CDevice { void update(); i2c::ErrorCode switch_to_channel(uint8_t channel); + void disable_all_channels(); protected: friend class TCA9548AChannel; - uint8_t current_channel_ = 255; }; } // namespace tca9548a } // namespace esphome From 55df88d7ae14db3da6d5d3a93189314a0045c0cd Mon Sep 17 00:00:00 2001 From: Mat931 <49403702+Mat931@users.noreply.github.com> Date: Sat, 2 Sep 2023 09:54:03 +0000 Subject: [PATCH 0142/2101] Fix checksum calculation for pipsolar (#5299) --- esphome/components/pipsolar/pipsolar.cpp | 20 ++++++++++++++++---- esphome/components/pipsolar/pipsolar.h | 2 +- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/esphome/components/pipsolar/pipsolar.cpp b/esphome/components/pipsolar/pipsolar.cpp index 62e4fbd341..2cd1aeba44 100644 --- a/esphome/components/pipsolar/pipsolar.cpp +++ b/esphome/components/pipsolar/pipsolar.cpp @@ -769,7 +769,7 @@ uint8_t Pipsolar::check_incoming_length_(uint8_t length) { uint8_t Pipsolar::check_incoming_crc_() { uint16_t crc16; - crc16 = crc16be(read_buffer_, read_pos_ - 3); + crc16 = this->pipsolar_crc_(read_buffer_, read_pos_ - 3); ESP_LOGD(TAG, "checking crc on incoming message"); if (((uint8_t) ((crc16) >> 8)) == read_buffer_[read_pos_ - 3] && ((uint8_t) ((crc16) &0xff)) == read_buffer_[read_pos_ - 2]) { @@ -798,7 +798,7 @@ uint8_t Pipsolar::send_next_command_() { this->command_start_millis_ = millis(); this->empty_uart_buffer_(); this->read_pos_ = 0; - crc16 = crc16be(byte_command, length); + crc16 = this->pipsolar_crc_(byte_command, length); this->write_str(command); // checksum this->write(((uint8_t) ((crc16) >> 8))); // highbyte @@ -825,8 +825,8 @@ void Pipsolar::send_next_poll_() { this->command_start_millis_ = millis(); this->empty_uart_buffer_(); this->read_pos_ = 0; - crc16 = crc16be(this->used_polling_commands_[this->last_polling_command_].command, - this->used_polling_commands_[this->last_polling_command_].length); + crc16 = this->pipsolar_crc_(this->used_polling_commands_[this->last_polling_command_].command, + this->used_polling_commands_[this->last_polling_command_].length); this->write_array(this->used_polling_commands_[this->last_polling_command_].command, this->used_polling_commands_[this->last_polling_command_].length); // checksum @@ -893,5 +893,17 @@ void Pipsolar::add_polling_command_(const char *command, ENUMPollingCommand poll } } +uint16_t Pipsolar::pipsolar_crc_(uint8_t *msg, uint8_t len) { + uint16_t crc = crc16be(msg, len); + uint8_t crc_low = crc & 0xff; + uint8_t crc_high = crc >> 8; + if (crc_low == 0x28 || crc_low == 0x0d || crc_low == 0x0a) + crc_low++; + if (crc_high == 0x28 || crc_high == 0x0d || crc_high == 0x0a) + crc_high++; + crc = (crc_high << 8) | crc_low; + return crc; +} + } // namespace pipsolar } // namespace esphome diff --git a/esphome/components/pipsolar/pipsolar.h b/esphome/components/pipsolar/pipsolar.h index 65fd3c670d..f20f44f095 100644 --- a/esphome/components/pipsolar/pipsolar.h +++ b/esphome/components/pipsolar/pipsolar.h @@ -193,7 +193,7 @@ class Pipsolar : public uart::UARTDevice, public PollingComponent { void empty_uart_buffer_(); uint8_t check_incoming_crc_(); uint8_t check_incoming_length_(uint8_t length); - uint16_t cal_crc_half_(uint8_t *msg, uint8_t len); + uint16_t pipsolar_crc_(uint8_t *msg, uint8_t len); uint8_t send_next_command_(); void send_next_poll_(); void queue_command_(const char *command, uint8_t length); From 150c9b5fa3f43ce28391e841764828a5d8b7d7ae Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 6 Sep 2023 10:14:19 +1200 Subject: [PATCH 0143/2101] Bump version to 2023.8.3 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index c22dde6986..bd4c48a704 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2023.8.2" +__version__ = "2023.8.3" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 76ebbfefd2d6f69d58f3ceaf0f2c0cc0b3705d8b Mon Sep 17 00:00:00 2001 From: Christian Date: Tue, 5 Sep 2023 23:33:49 +0100 Subject: [PATCH 0144/2101] Integration LightwaveRF switches (#4812) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- CODEOWNERS | 1 + esphome/components/lightwaverf/LwRx.cpp | 427 ++++++++++++++++++ esphome/components/lightwaverf/LwRx.h | 142 ++++++ esphome/components/lightwaverf/LwTx.cpp | 208 +++++++++ esphome/components/lightwaverf/LwTx.h | 92 ++++ esphome/components/lightwaverf/__init__.py | 83 ++++ .../components/lightwaverf/lightwaverf.cpp | 67 +++ esphome/components/lightwaverf/lightwaverf.h | 70 +++ tests/test3.yaml | 4 + 9 files changed, 1094 insertions(+) create mode 100644 esphome/components/lightwaverf/LwRx.cpp create mode 100644 esphome/components/lightwaverf/LwRx.h create mode 100644 esphome/components/lightwaverf/LwTx.cpp create mode 100644 esphome/components/lightwaverf/LwTx.h create mode 100644 esphome/components/lightwaverf/__init__.py create mode 100644 esphome/components/lightwaverf/lightwaverf.cpp create mode 100644 esphome/components/lightwaverf/lightwaverf.h diff --git a/CODEOWNERS b/CODEOWNERS index 384db8098f..498cfcac01 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -150,6 +150,7 @@ esphome/components/ledc/* @OttoWinter esphome/components/libretiny/* @kuba2k2 esphome/components/libretiny_pwm/* @kuba2k2 esphome/components/light/* @esphome/core +esphome/components/lightwaverf/* @max246 esphome/components/lilygo_t5_47/touchscreen/* @jesserockz esphome/components/lock/* @esphome/core esphome/components/logger/* @esphome/core diff --git a/esphome/components/lightwaverf/LwRx.cpp b/esphome/components/lightwaverf/LwRx.cpp new file mode 100644 index 0000000000..2b1ad5e870 --- /dev/null +++ b/esphome/components/lightwaverf/LwRx.cpp @@ -0,0 +1,427 @@ +// LwRx.cpp +// +// LightwaveRF 434MHz receiver interface for Arduino +// +// Author: Bob Tidey (robert@tideys.net) + +#ifdef USE_ESP8266 + +#include "LwRx.h" +#include + +namespace esphome { +namespace lightwaverf { + +/** + Pin change interrupt routine that identifies 1 and 0 LightwaveRF bits + and constructs a message when a valid packet of data is received. +**/ + +void IRAM_ATTR LwRx::rx_process_bits(LwRx *args) { + uint8_t event = args->rx_pin_isr_.digital_read(); // start setting event to the current value + uint32_t curr = micros(); // the current time in microseconds + + uint16_t dur = (curr - args->rx_prev); // unsigned int + args->rx_prev = curr; + // set event based on input and duration of previous pulse + if (dur < 120) { // 120 very short + } else if (dur < 500) { // normal short pulse + event += 2; + } else if (dur < 2000) { // normal long pulse + event += 4; + } else if (dur > 5000) { // gap between messages + event += 6; + } else { // 2000 > 5000 + event = 8; // illegal gap + } + // state machine transitions + switch (args->rx_state) { + case RX_STATE_IDLE: + switch (event) { + case 7: // 1 after a message gap + args->rx_state = RX_STATE_MSGSTARTFOUND; + break; + } + break; + case RX_STATE_MSGSTARTFOUND: + switch (event) { + case 2: // 0 160->500 + // nothing to do wait for next positive edge + break; + case 3: // 1 160->500 + args->rx_num_bytes = 0; + args->rx_state = RX_STATE_BYTESTARTFOUND; + break; + default: + // not good start again + args->rx_state = RX_STATE_IDLE; + break; + } + break; + case RX_STATE_BYTESTARTFOUND: + switch (event) { + case 2: // 0 160->500 + // nothing to do wait for next positive edge + break; + case 3: // 1 160->500 + args->rx_state = RX_STATE_GETBYTE; + args->rx_num_bits = 0; + break; + case 5: // 0 500->1500 + args->rx_state = RX_STATE_GETBYTE; + // Starts with 0 so put this into uint8_t + args->rx_num_bits = 1; + args->rx_buf[args->rx_num_bytes] = 0; + break; + default: + // not good start again + args->rx_state = RX_STATE_IDLE; + break; + } + break; + case RX_STATE_GETBYTE: + switch (event) { + case 2: // 0 160->500 + // nothing to do wait for next positive edge but do stats + if (args->lwrx_stats_enable) { + args->lwrx_stats[RX_STAT_HIGH_MAX] = std::max(args->lwrx_stats[RX_STAT_HIGH_MAX], dur); + args->lwrx_stats[RX_STAT_HIGH_MIN] = std::min(args->lwrx_stats[RX_STAT_HIGH_MIN], dur); + args->lwrx_stats[RX_STAT_HIGH_AVE] = + args->lwrx_stats[RX_STAT_HIGH_AVE] - (args->lwrx_stats[RX_STAT_HIGH_AVE] >> 4) + dur; + } + break; + case 3: // 1 160->500 + // a single 1 + args->rx_buf[args->rx_num_bytes] = args->rx_buf[args->rx_num_bytes] << 1 | 1; + args->rx_num_bits++; + if (args->lwrx_stats_enable) { + args->lwrx_stats[RX_STAT_LOW1_MAX] = std::max(args->lwrx_stats[RX_STAT_LOW1_MAX], dur); + args->lwrx_stats[RX_STAT_LOW1_MIN] = std::min(args->lwrx_stats[RX_STAT_LOW1_MIN], dur); + args->lwrx_stats[RX_STAT_LOW1_AVE] = + args->lwrx_stats[RX_STAT_LOW1_AVE] - (args->lwrx_stats[RX_STAT_LOW1_AVE] >> 4) + dur; + } + break; + case 5: // 1 500->1500 + // a 1 followed by a 0 + args->rx_buf[args->rx_num_bytes] = args->rx_buf[args->rx_num_bytes] << 2 | 2; + args->rx_num_bits++; + args->rx_num_bits++; + if (args->lwrx_stats_enable) { + args->lwrx_stats[RX_STAT_LOW0_MAX] = std::max(args->lwrx_stats[RX_STAT_LOW0_MAX], dur); + args->lwrx_stats[RX_STAT_LOW0_MIN] = std::min(args->lwrx_stats[RX_STAT_LOW0_MIN], dur); + args->lwrx_stats[RX_STAT_LOW0_AVE] = + args->lwrx_stats[RX_STAT_LOW0_AVE] - (args->lwrx_stats[RX_STAT_LOW0_AVE] >> 4) + dur; + } + break; + default: + // not good start again + args->rx_state = RX_STATE_IDLE; + break; + } + if (args->rx_num_bits >= 8) { + args->rx_num_bytes++; + args->rx_num_bits = 0; + if (args->rx_num_bytes >= RX_MSGLEN) { + uint32_t curr_millis = millis(); + if (args->rx_repeats > 0) { + if ((curr_millis - args->rx_prevpkttime) / 100 > args->rx_timeout) { + args->rx_repeatcount = 1; + } else { + // Test message same as last one + int16_t i = RX_MSGLEN; // int + do { + i--; + } while ((i >= 0) && (args->rx_msg[i] == args->rx_buf[i])); + if (i < 0) { + args->rx_repeatcount++; + } else { + args->rx_repeatcount = 1; + } + } + } else { + args->rx_repeatcount = 0; + } + args->rx_prevpkttime = curr_millis; + // If last message hasn't been read it gets overwritten + memcpy(args->rx_msg, args->rx_buf, RX_MSGLEN); + if (args->rx_repeats == 0 || args->rx_repeatcount == args->rx_repeats) { + if (args->rx_pairtimeout != 0) { + if ((curr_millis - args->rx_pairstarttime) / 100 <= args->rx_pairtimeout) { + if (args->rx_msg[3] == RX_CMD_ON) { + args->rx_addpairfrommsg_(); + } else if (args->rx_msg[3] == RX_CMD_OFF) { + args->rx_remove_pair_(&args->rx_msg[2]); + } + } + } + if (args->rx_report_message_()) { + args->rx_msgcomplete = true; + } + args->rx_pairtimeout = 0; + } + // And cycle round for next one + args->rx_state = RX_STATE_IDLE; + } else { + args->rx_state = RX_STATE_BYTESTARTFOUND; + } + } + break; + } +} + +/** + Test if a message has arrived +**/ +bool LwRx::lwrx_message() { return (this->rx_msgcomplete); } + +/** + Set translate mode +**/ +void LwRx::lwrx_settranslate(bool rxtranslate) { this->rx_translate = rxtranslate; } +/** + Transfer a message to user buffer +**/ +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) { + 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]); + if (j < 0) + ret = false; + } else { + j = this->rx_msg[i]; + } + switch (len) { + case 4: + if (i == 9) + buf[2] = j; + if (i == 2) + buf[3] = j; + case 2: + if (i == 3) + buf[0] = j; + if (i == 0) + buf[1] = j << 4; + if (i == 1) + buf[1] += j; + break; + case 10: + buf[i] = j; + break; + } + } + this->rx_msgcomplete = false; + } else { + ret = false; + } + return ret; +} + +/** + Return time in milliseconds since last packet received +**/ +uint32_t LwRx::lwrx_packetinterval() { return millis() - this->rx_prevpkttime; } + +/** + Set up repeat filtering of received messages +**/ +void LwRx::lwrx_setfilter(uint8_t repeats, uint8_t timeout) { + this->rx_repeats = repeats; + this->rx_timeout = timeout; +} + +/** + Add a pair to filter received messages + pairdata is device,dummy,5*addr,room + pairdata is held in translated form to make comparisons quicker +**/ +uint8_t LwRx::lwrx_addpair(const uint8_t *pairdata) { + if (this->rx_paircount < RX_MAXPAIRS) { + for (uint8_t i = 0; i < 8; i++) { + this->rx_pairs[rx_paircount][i] = RX_NIBBLE[pairdata[i]]; + } + this->rx_paircommit_(); + } + return this->rx_paircount; +} + +/** + Make a pair from next message successfully received +**/ +void LwRx::lwrx_makepair(uint8_t timeout) { + this->rx_pairtimeout = timeout; + this->rx_pairstarttime = millis(); +} + +/** + Get pair data (translated back to nibble form +**/ +uint8_t LwRx::lwrx_getpair(uint8_t *pairdata, uint8_t pairnumber) { + if (pairnumber < this->rx_paircount) { + int16_t j; // int + for (uint8_t i = 0; i < 8; i++) { + j = this->rx_find_nibble_(this->rx_pairs[pairnumber][i]); + if (j >= 0) + pairdata[i] = j; + } + } + return this->rx_paircount; +} + +/** + Clear all pairing +**/ +void LwRx::lwrx_clearpairing_() { rx_paircount = 0; } + +/** + Return stats on high and low pulses +**/ +bool LwRx::lwrx_getstats_(uint16_t *stats) { // unsigned int + if (this->lwrx_stats_enable) { + memcpy(stats, this->lwrx_stats, 2 * RX_STAT_COUNT); + return true; + } else { + return false; + } +} + +/** + Set stats mode +**/ +void LwRx::lwrx_setstatsenable_(bool rx_stats_enable) { + this->lwrx_stats_enable = rx_stats_enable; + if (!this->lwrx_stats_enable) { + // clear down stats when disabling + memcpy(this->lwrx_stats, LWRX_STATSDFLT, sizeof(LWRX_STATSDFLT)); + } +} +/** + Set pairs behaviour +**/ +void LwRx::lwrx_set_pair_mode(bool pair_enforce, bool pair_base_only) { + this->rx_pairEnforce = pair_enforce; + this->rx_pairBaseOnly = pair_base_only; +} + +/** + Set things up to receive LightWaveRF 434Mhz messages + pin must be 2 or 3 to trigger interrupts + !!! For Spark, any pin will work +**/ +void LwRx::lwrx_setup(InternalGPIOPin *pin) { + // rx_pin = pin; + pin->setup(); + this->rx_pin_isr_ = pin->to_isr(); + pin->attach_interrupt(&LwRx::rx_process_bits, this, gpio::INTERRUPT_ANY_EDGE); + + memcpy(this->lwrx_stats, LWRX_STATSDFLT, sizeof(LWRX_STATSDFLT)); +} + +/** + Check a message to see if it should be reported under pairing / mood / all off rules + returns -1 if none found +**/ +bool LwRx::rx_report_message_() { + if (this->rx_pairEnforce && this->rx_paircount == 0) { + return false; + } else { + bool all_devices; + // True if mood to device 15 or Off cmd with Allof paramater + all_devices = ((this->rx_msg[3] == RX_CMD_MOOD && this->rx_msg[2] == RX_DEV_15) || + (this->rx_msg[3] == RX_CMD_OFF && this->rx_msg[0] == RX_PAR0_ALLOFF)); + return (rx_check_pairs_(&this->rx_msg[2], all_devices) != -1); + } +} +/** + Find nibble from byte + returns -1 if none found +**/ +int16_t LwRx::rx_find_nibble_(uint8_t data) { // int + int16_t i = 15; // int + do { + if (RX_NIBBLE[i] == data) + break; + i--; + } while (i >= 0); + return i; +} + +/** + add pair from message buffer +**/ +void LwRx::rx_addpairfrommsg_() { + if (this->rx_paircount < RX_MAXPAIRS) { + memcpy(this->rx_pairs[this->rx_paircount], &this->rx_msg[2], 8); + this->rx_paircommit_(); + } +} + +/** + check and commit pair +**/ +void LwRx::rx_paircommit_() { + if (this->rx_paircount == 0 || this->rx_check_pairs_(this->rx_pairs[this->rx_paircount], false) < 0) { + this->rx_paircount++; + } +} + +/** + Check to see if message matches one of the pairs + if mode is pairBase only then ignore device and room + if allDevices is true then ignore the device number + Returns matching pair number, -1 if not found, -2 if no pairs defined +**/ +int16_t LwRx::rx_check_pairs_(const uint8_t *buf, bool all_devices) { // int + if (this->rx_paircount == 0) { + return -2; + } else { + int16_t pair = this->rx_paircount; // int + int16_t j = -1; // int + int16_t jstart, jend; // int + if (this->rx_pairBaseOnly) { + // skip room(8) and dev/cmd (0,1) + jstart = 7; + jend = 2; + } else { + // include room in comparison + jstart = 8; + // skip device comparison if allDevices true + jend = (all_devices) ? 2 : 0; + } + while (pair > 0 && j < 0) { + pair--; + j = jstart; + while (j > jend) { + j--; + if (j != 1) { + if (this->rx_pairs[pair][j] != buf[j]) { + j = -1; + } + } + } + } + return (j >= 0) ? pair : -1; + } +} + +/** + Remove an existing pair matching the buffer +**/ +void LwRx::rx_remove_pair_(uint8_t *buf) { + int16_t pair = this->rx_check_pairs_(buf, false); // int + if (pair >= 0) { + while (pair < this->rx_paircount - 1) { + for (uint8_t j = 0; j < 8; j++) { + this->rx_pairs[pair][j] = this->rx_pairs[pair + 1][j]; + } + pair++; + } + this->rx_paircount--; + } +} + +} // namespace lightwaverf +} // namespace esphome +#endif diff --git a/esphome/components/lightwaverf/LwRx.h b/esphome/components/lightwaverf/LwRx.h new file mode 100644 index 0000000000..7200f9a51c --- /dev/null +++ b/esphome/components/lightwaverf/LwRx.h @@ -0,0 +1,142 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/core/hal.h" + +namespace esphome { +namespace lightwaverf { + +// LwRx.h +// +// LightwaveRF 434MHz receiver for Arduino +// +// Author: Bob Tidey (robert@tideys.net) + +static const uint8_t RX_STAT_HIGH_AVE = 0; +static const uint8_t RX_STAT_HIGH_MAX = 1; +static const uint8_t RX_STAT_HIGH_MIN = 2; +static const uint8_t RX_STAT_LOW0_AVE = 3; +static const uint8_t RX_STAT_LOW0_MAX = 4; +static const uint8_t RX_STAT_LOW0_MIN = 5; +static const uint8_t RX_STAT_LOW1_AVE = 6; +static const uint8_t RX_STAT_LOW1_MAX = 7; +static const uint8_t RX_STAT_LOW1_MIN = 8; +static const uint8_t RX_STAT_COUNT = 9; + +// sets maximum number of pairings which can be held +static const uint8_t RX_MAXPAIRS = 10; + +static const uint8_t RX_NIBBLE[] = {0xF6, 0xEE, 0xED, 0xEB, 0xDE, 0xDD, 0xDB, 0xBE, + 0xBD, 0xBB, 0xB7, 0x7E, 0x7D, 0x7B, 0x77, 0x6F}; +static const uint8_t RX_CMD_OFF = 0xF6; // raw 0 +static const uint8_t RX_CMD_ON = 0xEE; // raw 1 +static const uint8_t RX_CMD_MOOD = 0xED; // raw 2 +static const uint8_t RX_PAR0_ALLOFF = 0x7D; // param 192-255 all off (12 in msb) +static const uint8_t RX_DEV_15 = 0x6F; // device 15 + +static const uint8_t RX_MSGLEN = 10; // expected length of rx message + +static const uint8_t RX_STATE_IDLE = 0; +static const uint8_t RX_STATE_MSGSTARTFOUND = 1; +static const uint8_t RX_STATE_BYTESTARTFOUND = 2; +static const uint8_t RX_STATE_GETBYTE = 3; + +// Gather stats for pulse widths (ave is x 16) +static const uint16_t LWRX_STATSDFLT[RX_STAT_COUNT] = {5000, 0, 5000, 20000, 0, 2500, 4000, 0, 500}; // usigned int + +class LwRx { + public: + // Seup must be called once, set up pin used to receive data + void lwrx_setup(InternalGPIOPin *pin); + + // Set translate to determine whether translating from nibbles to bytes in message + // Translate off only applies to 10char message returns + void lwrx_settranslate(bool translate); + + // Check to see whether message available + bool lwrx_message(); + + // Get a message, len controls format (2 cmd+param, 4 cmd+param+room+device),10 full message + bool lwrx_getmessage(uint8_t *buf, uint8_t len); + + // Setup repeat filter + void lwrx_setfilter(uint8_t repeats, uint8_t timeout); + + // Add pair, if no pairing set then all messages are received, returns number of pairs + uint8_t lwrx_addpair(const uint8_t *pairdata); + + // Get pair data into buffer for the pairnumber. Returns current paircount + // Use pairnumber 255 to just get current paircount + uint8_t lwrx_getpair(uint8_t *pairdata, uint8_t pairnumber); + + // Make a pair from next message received within timeout 100mSec + // This call returns immediately whilst message checking continues + void lwrx_makepair(uint8_t timeout); + + // Set pair mode controls + void lwrx_set_pair_mode(bool pair_enforce, bool pair_base_only); + + // Returns time from last packet received in msec + // Can be used to determine if Rx may be still receiving repeats + uint32_t lwrx_packetinterval(); + + static void rx_process_bits(LwRx *arg); + + // Pairing data + uint8_t rx_paircount = 0; + uint8_t rx_pairs[RX_MAXPAIRS][8]; + // set false to responds to all messages if no pairs set up + bool rx_pairEnforce = false; + // set false to use Address, Room and Device in pairs, true just the Address part + bool rx_pairBaseOnly = false; + + uint8_t rx_pairtimeout = 0; // 100msec units + + // Repeat filters + uint8_t rx_repeats = 2; // msg must be repeated at least this number of times + uint8_t rx_repeatcount = 0; + uint8_t rx_timeout = 20; // reset repeat window after this in 100mSecs + uint32_t rx_prevpkttime = 0; // last packet time in milliseconds + uint32_t rx_pairstarttime = 0; // last msg time in milliseconds + + // Receive mode constants and variables + uint8_t rx_msg[RX_MSGLEN]; // raw message received + uint8_t rx_buf[RX_MSGLEN]; // message buffer during reception + + 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 + + uint8_t rx_state = 0; + + uint8_t rx_num_bits = 0; // number of bits in the current uint8_t + uint8_t rx_num_bytes = 0; // number of bytes received + + uint16_t lwrx_stats[RX_STAT_COUNT]; // unsigned int + + bool lwrx_stats_enable = true; + + protected: + void lwrx_clearpairing_(); + + // Return stats on pulse timings + bool lwrx_getstats_(uint16_t *stats); + + // Enable collection of stats on pulse timings + void lwrx_setstatsenable_(bool rx_stats_enable); + + // internal support functions + bool rx_report_message_(); + int16_t rx_find_nibble_(uint8_t data); // int + void rx_addpairfrommsg_(); + void rx_paircommit_(); + void rx_remove_pair_(uint8_t *buf); + int16_t rx_check_pairs_(const uint8_t *buf, bool all_devices); // int + + ISRInternalGPIOPin rx_pin_isr_; + InternalGPIOPin *rx_pin_; +}; + +} // namespace lightwaverf +} // namespace esphome diff --git a/esphome/components/lightwaverf/LwTx.cpp b/esphome/components/lightwaverf/LwTx.cpp new file mode 100644 index 0000000000..2f46b04b2d --- /dev/null +++ b/esphome/components/lightwaverf/LwTx.cpp @@ -0,0 +1,208 @@ +// LwTx.cpp +// +// LightwaveRF 434MHz tx interface for Arduino +// +// Author: Bob Tidey (robert@tideys.net) +#ifdef USE_ESP8266 + +#include "LwTx.h" +#include +#include +#include "esphome/core/log.h" +#include "esphome/core/helpers.h" + +namespace esphome { +namespace lightwaverf { + +static const uint8_t TX_NIBBLE[] = {0xF6, 0xEE, 0xED, 0xEB, 0xDE, 0xDD, 0xDB, 0xBE, + 0xBD, 0xBB, 0xB7, 0x7E, 0x7D, 0x7B, 0x77, 0x6F}; + +static const uint8_t TX_STATE_IDLE = 0; +static const uint8_t TX_STATE_MSGSTART = 1; +static const uint8_t TX_STATE_BYTESTART = 2; +static const uint8_t TX_STATE_SENDBYTE = 3; +static const uint8_t TX_STATE_MSGEND = 4; +static const uint8_t TX_STATE_GAPSTART = 5; +static const uint8_t TX_STATE_GAPEND = 6; +/** + Set translate mode +**/ +void LwTx::lwtx_settranslate(bool txtranslate) { tx_translate = txtranslate; } + +static void IRAM_ATTR isr_t_xtimer(LwTx *arg) { + // Set low after toggle count interrupts + arg->tx_toggle_count--; + if (arg->tx_toggle_count == arg->tx_trail_count) { + // ESP_LOGD("lightwaverf.sensor", "timer") + arg->tx_pin->digital_write(arg->txoff); + } else if (arg->tx_toggle_count == 0) { + arg->tx_toggle_count = arg->tx_high_count; // default high pulse duration + switch (arg->tx_state) { + case TX_STATE_IDLE: + if (arg->tx_msg_active) { + arg->tx_repeat = 0; + arg->tx_state = TX_STATE_MSGSTART; + } + break; + case TX_STATE_MSGSTART: + arg->tx_pin->digital_write(arg->txon); + arg->tx_num_bytes = 0; + arg->tx_state = TX_STATE_BYTESTART; + break; + case TX_STATE_BYTESTART: + arg->tx_pin->digital_write(arg->txon); + arg->tx_bit_mask = 0x80; + arg->tx_state = TX_STATE_SENDBYTE; + break; + case TX_STATE_SENDBYTE: + if (arg->tx_buf[arg->tx_num_bytes] & arg->tx_bit_mask) { + arg->tx_pin->digital_write(arg->txon); + } else { + // toggle count for the 0 pulse + arg->tx_toggle_count = arg->tx_low_count; + } + arg->tx_bit_mask >>= 1; + if (arg->tx_bit_mask == 0) { + arg->tx_num_bytes++; + if (arg->tx_num_bytes >= esphome::lightwaverf::LwTx::TX_MSGLEN) { + arg->tx_state = TX_STATE_MSGEND; + } else { + arg->tx_state = TX_STATE_BYTESTART; + } + } + break; + case TX_STATE_MSGEND: + arg->tx_pin->digital_write(arg->txon); + arg->tx_state = TX_STATE_GAPSTART; + arg->tx_gap_repeat = arg->tx_gap_multiplier; + break; + case TX_STATE_GAPSTART: + arg->tx_toggle_count = arg->tx_gap_count; + if (arg->tx_gap_repeat == 0) { + arg->tx_state = TX_STATE_GAPEND; + } else { + arg->tx_gap_repeat--; + } + break; + case TX_STATE_GAPEND: + arg->tx_repeat++; + if (arg->tx_repeat >= arg->tx_repeats) { + // disable timer nterrupt + arg->lw_timer_stop(); + arg->tx_msg_active = false; + arg->tx_state = TX_STATE_IDLE; + } else { + arg->tx_state = TX_STATE_MSGSTART; + } + break; + } + } +} + +/** + Check for send free +**/ +bool LwTx::lwtx_free() { return !this->tx_msg_active; } + +/** + Send a LightwaveRF message (10 nibbles in bytes) +**/ +void LwTx::lwtx_send(const std::vector &msg) { + if (this->tx_translate) { + for (uint8_t i = 0; i < TX_MSGLEN; i++) { + this->tx_buf[i] = TX_NIBBLE[msg[i] & 0xF]; + ESP_LOGD("lightwaverf.sensor", "%x ", msg[i]); + } + } else { + // memcpy(tx_buf, msg, tx_msglen); + } + this->lw_timer_start(); + this->tx_msg_active = true; +} + +/** + Set 5 char address for future messages +**/ +void LwTx::lwtx_setaddr(const uint8_t *addr) { + for (uint8_t i = 0; i < 5; i++) { + this->tx_buf[i + 4] = TX_NIBBLE[addr[i] & 0xF]; + } +} + +/** + Send a LightwaveRF message (10 nibbles in bytes) +**/ +void LwTx::lwtx_cmd(uint8_t command, uint8_t parameter, uint8_t room, uint8_t device) { + // enable timer 2 interrupts + this->tx_buf[0] = TX_NIBBLE[parameter >> 4]; + this->tx_buf[1] = TX_NIBBLE[parameter & 0xF]; + this->tx_buf[2] = TX_NIBBLE[device & 0xF]; + this->tx_buf[3] = TX_NIBBLE[command & 0xF]; + this->tx_buf[9] = TX_NIBBLE[room & 0xF]; + this->lw_timer_start(); + this->tx_msg_active = true; +} + +/** + Set things up to transmit LightWaveRF 434Mhz messages +**/ +void LwTx::lwtx_setup(InternalGPIOPin *pin, uint8_t repeats, bool inverted, int u_sec) { + pin->setup(); + tx_pin = pin; + + tx_pin->pin_mode(gpio::FLAG_OUTPUT); + tx_pin->digital_write(txoff); + + if (repeats > 0 && repeats < 40) { + this->tx_repeats = repeats; + } + if (inverted) { + this->txon = 0; + this->txoff = 1; + } else { + this->txon = 1; + this->txoff = 0; + } + + int period1 = 330; + /* + if (period > 32 && period < 1000) { + period1 = period; + } else { + // default 330 uSec + period1 = 330; + }*/ + this->espPeriod = 5 * period1; + timer1_isr_init(); +} + +void LwTx::lwtx_set_tick_counts(uint8_t low_count, uint8_t high_count, uint8_t trail_count, uint8_t gap_count) { + this->tx_low_count = low_count; + this->tx_high_count = high_count; + this->tx_trail_count = trail_count; + this->tx_gap_count = gap_count; +} + +void LwTx::lwtx_set_gap_multiplier(uint8_t gap_multiplier) { this->tx_gap_multiplier = gap_multiplier; } + +void LwTx::lw_timer_start() { + { + InterruptLock lock; + static LwTx *arg = this; // NOLINT + timer1_attachInterrupt([] { isr_t_xtimer(arg); }); + timer1_enable(TIM_DIV16, TIM_EDGE, TIM_LOOP); + timer1_write(this->espPeriod); + } +} + +void LwTx::lw_timer_stop() { + { + InterruptLock lock; + timer1_disable(); + timer1_detachInterrupt(); + } +} + +} // namespace lightwaverf +} // namespace esphome +#endif diff --git a/esphome/components/lightwaverf/LwTx.h b/esphome/components/lightwaverf/LwTx.h new file mode 100644 index 0000000000..719826640e --- /dev/null +++ b/esphome/components/lightwaverf/LwTx.h @@ -0,0 +1,92 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/core/hal.h" + +namespace esphome { +namespace lightwaverf { + +// LxTx.h +// +// LightwaveRF 434MHz tx interface for Arduino +// +// Author: Bob Tidey (robert@tideys.net) + +// Include basic library header and set default TX pin +static const uint8_t TX_PIN_DEFAULT = 13; + +class LwTx { + public: + // Sets up basic parameters must be called at least once + void lwtx_setup(InternalGPIOPin *pin, uint8_t repeats, bool inverted, int u_sec); + + // Allows changing basic tick counts from their defaults + void lwtx_set_tick_counts(uint8_t low_count, uint8_t high_count, uint8_t trail_count, uint8_t gap_count); + + // Allws multiplying the gap period for creating very large gaps + void lwtx_set_gap_multiplier(uint8_t gap_multiplier); + + // determines whether incoming data or should be translated from nibble data + void lwtx_settranslate(bool txtranslate); + + // Checks whether tx is free to accept a new message + bool lwtx_free(); + + // Basic send of new 10 char message, not normally needed if setaddr and cmd are used. + void lwtx_send(const std::vector &msg); + + // Sets up 5 char address which will be used to form messages for lwtx_cmd + void lwtx_setaddr(const uint8_t *addr); + + // Send Command + void lwtx_cmd(uint8_t command, uint8_t parameter, uint8_t room, uint8_t device); + + // Allows changing basic tick counts from their defaults + void lw_timer_start(); + + // Allws multiplying the gap period for creating very large gaps + void lw_timer_stop(); + + // These set the pulse durationlws in ticks. ESP uses 330uSec base tick, else use 140uSec + uint8_t tx_low_count = 3; // total number of ticks in a low (990 uSec) + uint8_t tx_high_count = 2; // total number of ticks in a high (660 uSec) + uint8_t tx_trail_count = 1; // tick count to set line low (330 uSec) + + uint8_t tx_toggle_count = 3; + + static const uint8_t TX_MSGLEN = 10; // the expected length of the message + + // Transmit mode constants and variables + 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 + + uint8_t tx_buf[TX_MSGLEN]; // the message buffer during reception + uint8_t tx_repeat = 0; // counter for repeats + uint8_t tx_state = 0; + uint16_t tx_gap_repeat = 0; // unsigned int + + // Use with low repeat counts + uint8_t tx_gap_count = 33; // Inter-message gap count (10.9 msec) + uint32_t espPeriod = 0; // Holds interrupt timer0 period + uint32_t espNext = 0; // Holds interrupt next count + + // Gap multiplier byte is used to multiply gap if longer periods are needed for experimentation + // If gap is 255 (35msec) then this to give a max of 9 seconds + // Used with low repeat counts to find if device times out + uint8_t tx_gap_multiplier = 0; // Gap extension byte + + uint8_t tx_bit_mask = 0; // bit mask in current byte + uint8_t tx_num_bytes = 0; // number of bytes sent + + InternalGPIOPin *tx_pin; + + protected: + uint32_t duty_on_; + uint32_t duty_off_; +}; + +} // namespace lightwaverf +} // namespace esphome diff --git a/esphome/components/lightwaverf/__init__.py b/esphome/components/lightwaverf/__init__.py new file mode 100644 index 0000000000..4e96dda663 --- /dev/null +++ b/esphome/components/lightwaverf/__init__.py @@ -0,0 +1,83 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome import pins +from esphome import automation + +from esphome.const import ( + CONF_READ_PIN, + CONF_ID, + CONF_NAME, + CONF_WRITE_PIN, + CONF_REPEAT, + CONF_INVERTED, + CONF_PULSE_LENGTH, + CONF_CODE, +) +from esphome.cpp_helpers import gpio_pin_expression + +CODEOWNERS = ["@max246"] + +lightwaverf_ns = cg.esphome_ns.namespace("lightwaverf") + + +LIGHTWAVERFComponent = lightwaverf_ns.class_( + "LightWaveRF", cg.Component, cg.PollingComponent +) +LightwaveRawAction = lightwaverf_ns.class_("SendRawAction", automation.Action) + + +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, + } +).extend(cv.polling_component_schema("1s")) + + +LIGHTWAVE_SEND_SCHEMA = cv.Any( + cv.int_range(min=1), + cv.Schema( + { + cv.GenerateID(): cv.use_id(LIGHTWAVERFComponent), + cv.Required(CONF_NAME): cv.string, + cv.Required(CONF_CODE): cv.All( + [cv.Any(cv.hex_uint8_t)], + cv.Length(min=10), + ), + cv.Optional(CONF_REPEAT, default=10): cv.int_, + cv.Optional(CONF_INVERTED, default=False): cv.boolean, + cv.Optional(CONF_PULSE_LENGTH, default=330): cv.int_, + } + ), +) + + +@automation.register_action( + "lightwaverf.send_raw", + LightwaveRawAction, + LIGHTWAVE_SEND_SCHEMA, +) +async def send_raw_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) + + repeats = await cg.templatable(config[CONF_REPEAT], args, int) + inverted = await cg.templatable(config[CONF_INVERTED], args, bool) + pulse_length = await cg.templatable(config[CONF_PULSE_LENGTH], args, int) + code = config[CONF_CODE] + + cg.add(var.set_repeats(repeats)) + cg.add(var.set_inverted(inverted)) + cg.add(var.set_pulse_length(pulse_length)) + cg.add(var.set_data(code)) + return var + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, config) + + pin_read = await gpio_pin_expression(config[CONF_READ_PIN]) + pin_write = await gpio_pin_expression(config[CONF_WRITE_PIN]) + cg.add(var.set_pin(pin_write, pin_read)) diff --git a/esphome/components/lightwaverf/lightwaverf.cpp b/esphome/components/lightwaverf/lightwaverf.cpp new file mode 100644 index 0000000000..89cbdae6e1 --- /dev/null +++ b/esphome/components/lightwaverf/lightwaverf.cpp @@ -0,0 +1,67 @@ +#include "esphome/core/log.h" + +#ifdef USE_ESP8266 + +#include "lightwaverf.h" + +namespace esphome { +namespace lightwaverf { + +static const char *const TAG = "lightwaverf.sensor"; + +static const uint8_t DEFAULT_REPEAT = 10; +static const bool DEFAULT_INVERT = false; +static const uint32_t DEFAULT_TICK = 330; + +void LightWaveRF::setup() { + ESP_LOGCONFIG(TAG, "Setting up Lightwave RF..."); + + this->lwtx_.lwtx_setup(pin_tx_, DEFAULT_REPEAT, DEFAULT_INVERT, DEFAULT_TICK); + this->lwrx_.lwrx_setup(pin_rx_); +} + +void LightWaveRF::update() { this->read_tx(); } + +void LightWaveRF::read_tx() { + if (this->lwrx_.lwrx_message()) { + this->lwrx_.lwrx_getmessage(msg_, msglen_); + print_msg_(msg_, msglen_); + } +} + +void LightWaveRF::send_rx(const std::vector &msg, uint8_t repeats, bool inverted, int u_sec) { + this->lwtx_.lwtx_setup(pin_tx_, repeats, inverted, u_sec); + + uint32_t timeout = 0; + 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)) { + delay(10); + } + timeout = millis() - timeout; + ESP_LOGD(TAG, "[%u] msg sent: %i", millis(), timeout); +} + +void LightWaveRF::print_msg_(uint8_t *msg, uint8_t len) { + char buffer[65]; + ESP_LOGD(TAG, " Received code (len:%i): ", len); + + for (int i = 0; i < len; i++) { + sprintf(&buffer[i * 6], "0x%02x, ", msg[i]); + } + ESP_LOGD(TAG, "[%s]", buffer); +} + +void LightWaveRF::dump_config() { + ESP_LOGCONFIG(TAG, "Lightwave RF:"); + LOG_PIN(" Pin TX: ", this->pin_tx_); + LOG_PIN(" Pin RX: ", this->pin_rx_); + LOG_UPDATE_INTERVAL(this); +} +} // namespace lightwaverf +} // namespace esphome + +#endif diff --git a/esphome/components/lightwaverf/lightwaverf.h b/esphome/components/lightwaverf/lightwaverf.h new file mode 100644 index 0000000000..b9f2abfcb3 --- /dev/null +++ b/esphome/components/lightwaverf/lightwaverf.h @@ -0,0 +1,70 @@ +#pragma once + +#ifdef USE_ESP8266 + +#include "esphome/core/component.h" +#include "esphome/core/hal.h" +#include "esphome/core/automation.h" + +#include + +#include "LwRx.h" +#include "LwTx.h" + +namespace esphome { +namespace lightwaverf { + +#ifdef USE_ESP8266 + +class LightWaveRF : public PollingComponent { + public: + void set_pin(InternalGPIOPin *pin_tx, InternalGPIOPin *pin_rx) { + pin_tx_ = pin_tx; + pin_rx_ = pin_rx; + } + void update() override; + void setup() override; + void dump_config() override; + void read_tx(); + void send_rx(const std::vector &msg, uint8_t repeats, bool inverted, int u_sec); + + protected: + void print_msg_(uint8_t *msg, uint8_t len); + uint8_t msg_[10]; + uint8_t msglen_ = 10; + InternalGPIOPin *pin_tx_; + InternalGPIOPin *pin_rx_; + LwRx lwrx_; + LwTx lwtx_; +}; + +template class SendRawAction : public Action { + public: + SendRawAction(LightWaveRF *parent) : parent_(parent){}; + TEMPLATABLE_VALUE(int, repeat); + TEMPLATABLE_VALUE(int, inverted); + TEMPLATABLE_VALUE(int, pulse_length); + TEMPLATABLE_VALUE(std::vector, code); + + void set_repeats(const int &data) { repeat_ = data; } + void set_inverted(const int &data) { inverted_ = data; } + void set_pulse_length(const int &data) { pulse_length_ = data; } + void set_data(const std::vector &data) { code_ = data; } + + void play(Ts... x) { + int repeats = this->repeat_.value(x...); + int inverted = this->inverted_.value(x...); + int pulse_length = this->pulse_length_.value(x...); + std::vector msg = this->code_.value(x...); + + this->parent_->send_rx(msg, repeats, inverted, pulse_length); + } + + protected: + LightWaveRF *parent_; +}; + +#endif +} // namespace lightwaverf +} // namespace esphome +#endif diff --git a/tests/test3.yaml b/tests/test3.yaml index abfd133c99..5d30e415fb 100644 --- a/tests/test3.yaml +++ b/tests/test3.yaml @@ -1188,6 +1188,10 @@ qr_code: - id: homepage_qr value: https://esphome.io/index.html +lightwaverf: + read_pin: 13 + write_pin: 14 + alarm_control_panel: - platform: template id: alarmcontrolpanel1 From eff76d578b3391c568674cd41f820634c37c7a3e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Sep 2023 10:44:47 +1200 Subject: [PATCH 0145/2101] Bump flake8 from 6.0.0 to 6.1.0 (#5171) 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 e160c3e9e3..2d46d3dccd 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,5 +1,5 @@ pylint==2.17.5 -flake8==6.0.0 # also change in .pre-commit-config.yaml when updating +flake8==6.1.0 # also change in .pre-commit-config.yaml when updating black==23.7.0 # also change in .pre-commit-config.yaml when updating pyupgrade==3.10.1 # also change in .pre-commit-config.yaml when updating pre-commit From e89c6494a6621a46685112fd658153611b9f72b2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Sep 2023 10:45:17 +1200 Subject: [PATCH 0146/2101] Bump tornado from 6.3.2 to 6.3.3 (#5236) 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 c52b8e1d8e..9ec3a9c8f9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ voluptuous==0.13.1 PyYAML==6.0.1 paho-mqtt==1.6.1 colorama==0.4.6 -tornado==6.3.2 +tornado==6.3.3 tzlocal==5.0.1 # from time tzdata>=2021.1 # from time pyserial==3.5 From 6b0fb3dd065a7b443ea17ddef095e5ac3785a62d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Sep 2023 23:31:21 +0000 Subject: [PATCH 0147/2101] Bump platformio from 6.1.10 to 6.1.11 (#5323) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- docker/Dockerfile | 2 +- requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index a590445de9..bf64897af7 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -61,7 +61,7 @@ RUN \ # Ubuntu python3-pip is missing wheel pip3 install --no-cache-dir \ wheel==0.37.1 \ - platformio==6.1.10 \ + platformio==6.1.11 \ # Change some platformio settings && platformio settings set enable_telemetry No \ && platformio settings set check_platformio_interval 1000000 \ diff --git a/requirements.txt b/requirements.txt index 9ec3a9c8f9..dcb7420d3f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,7 +6,7 @@ tornado==6.3.3 tzlocal==5.0.1 # from time tzdata>=2021.1 # from time pyserial==3.5 -platformio==6.1.10 # When updating platformio, also update Dockerfile +platformio==6.1.11 # When updating platformio, also update Dockerfile esptool==4.6.2 click==8.1.7 esphome-dashboard==20230904.0 From 8cac5ca90c59acb62283d3ae2a488c798069e2ee Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 6 Sep 2023 15:32:14 +1200 Subject: [PATCH 0148/2101] Only run ci-docker when ci-docker workflow changes (#5347) --- .github/workflows/ci-docker.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-docker.yml b/.github/workflows/ci-docker.yml index 394379d675..dbd0d573da 100644 --- a/.github/workflows/ci-docker.yml +++ b/.github/workflows/ci-docker.yml @@ -8,7 +8,7 @@ on: branches: [dev, beta, release] paths: - "docker/**" - - ".github/workflows/**" + - ".github/workflows/ci-docker.yml" - "requirements*.txt" - "platformio.ini" - "script/platformio_install_deps.py" @@ -16,7 +16,7 @@ on: pull_request: paths: - "docker/**" - - ".github/workflows/**" + - ".github/workflows/ci-docker.yml" - "requirements*.txt" - "platformio.ini" - "script/platformio_install_deps.py" From f2a6f1855376bbea403409f885dfd747d75ec6fd Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 6 Sep 2023 17:02:21 +1200 Subject: [PATCH 0149/2101] esp32: Extra build customization (#5322) --- esphome/components/esp32/__init__.py | 46 +++++++++++++++++++++++----- esphome/components/esp32/const.py | 1 + 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index ee18315518..0b067dc78f 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -22,6 +22,7 @@ from esphome.const import ( CONF_IGNORE_EFUSE_MAC_CRC, KEY_CORE, KEY_FRAMEWORK_VERSION, + KEY_NAME, KEY_TARGET_FRAMEWORK, KEY_TARGET_PLATFORM, TYPE_GIT, @@ -37,6 +38,7 @@ from .const import ( # noqa KEY_BOARD, KEY_COMPONENTS, KEY_ESP32, + KEY_EXTRA_BUILD_FILES, KEY_PATH, KEY_REF, KEY_REFRESH, @@ -73,6 +75,8 @@ def set_core_data(config): ) CORE.data[KEY_ESP32][KEY_BOARD] = config[CONF_BOARD] CORE.data[KEY_ESP32][KEY_VARIANT] = config[CONF_VARIANT] + CORE.data[KEY_ESP32][KEY_EXTRA_BUILD_FILES] = {} + return config @@ -166,6 +170,24 @@ def add_idf_component( } +def add_extra_script(stage: str, filename: str, path: str): + """Add an extra script to the project.""" + key = f"{stage}:{filename}" + if add_extra_build_file(filename, path): + cg.add_platformio_option("extra_scripts", [key]) + + +def add_extra_build_file(filename: str, path: str) -> bool: + """Add an extra build file to the project.""" + if filename not in CORE.data[KEY_ESP32][KEY_EXTRA_BUILD_FILES]: + CORE.data[KEY_ESP32][KEY_EXTRA_BUILD_FILES][filename] = { + KEY_NAME: filename, + KEY_PATH: path, + } + return True + return False + + def _format_framework_arduino_version(ver: cv.Version) -> str: # format the given arduino (https://github.com/espressif/arduino-esp32/releases) version to # a PIO platformio/framework-arduinoespressif32 value @@ -390,7 +412,11 @@ async def to_code(config): conf = config[CONF_FRAMEWORK] cg.add_platformio_option("platform", conf[CONF_PLATFORM_VERSION]) - cg.add_platformio_option("extra_scripts", ["post:post_build.py"]) + add_extra_script( + "post", + "post_build2.py", + os.path.join(os.path.dirname(__file__), "post_build.py.script"), + ) if conf[CONF_TYPE] == FRAMEWORK_ESP_IDF: cg.add_platformio_option("framework", "espidf") @@ -604,9 +630,15 @@ def copy_files(): ignore_dangling_symlinks=True, ) - dir = os.path.dirname(__file__) - post_build_file = os.path.join(dir, "post_build.py.script") - copy_file_if_changed( - post_build_file, - CORE.relative_build_path("post_build.py"), - ) + for _, file in CORE.data[KEY_ESP32][KEY_EXTRA_BUILD_FILES].items(): + if file[KEY_PATH].startswith("http"): + import requests + + mkdir_p(CORE.relative_build_path(os.path.dirname(file[KEY_NAME]))) + with open(CORE.relative_build_path(file[KEY_NAME]), "wb") as f: + f.write(requests.get(file[KEY_PATH], timeout=30).content) + else: + copy_file_if_changed( + file[KEY_PATH], + CORE.relative_build_path(file[KEY_NAME]), + ) diff --git a/esphome/components/esp32/const.py b/esphome/components/esp32/const.py index 9e997bdeb5..a86713e857 100644 --- a/esphome/components/esp32/const.py +++ b/esphome/components/esp32/const.py @@ -10,6 +10,7 @@ KEY_REF = "ref" KEY_REFRESH = "refresh" KEY_PATH = "path" KEY_SUBMODULES = "submodules" +KEY_EXTRA_BUILD_FILES = "extra_build_files" VARIANT_ESP32 = "ESP32" VARIANT_ESP32S2 = "ESP32S2" From 72f29b1283b925da3177bacd4b60ec0446291e81 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 7 Sep 2023 10:15:54 +1200 Subject: [PATCH 0150/2101] Allow upload command to flash file via serial (#5274) --- esphome/__main__.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/esphome/__main__.py b/esphome/__main__.py index 9b208c2280..9fac8cd605 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -218,14 +218,16 @@ def compile_program(args, config): return 0 if idedata is not None else 1 -def upload_using_esptool(config, port): +def upload_using_esptool(config, port, file): from esphome import platformio_api first_baudrate = config[CONF_ESPHOME][CONF_PLATFORMIO_OPTIONS].get( "upload_speed", 460800 ) - def run_esptool(baud_rate): + if file is not None: + flash_images = [platformio_api.FlashImage(path=file, offset="0x0")] + else: idedata = platformio_api.get_idedata(config) firmware_offset = "0x10000" if CORE.is_esp32 else "0x0" @@ -236,12 +238,13 @@ def upload_using_esptool(config, port): *idedata.extra_flash_images, ] - mcu = "esp8266" - if CORE.is_esp32: - from esphome.components.esp32 import get_esp32_variant + mcu = "esp8266" + if CORE.is_esp32: + from esphome.components.esp32 import get_esp32_variant - mcu = get_esp32_variant().lower() + mcu = get_esp32_variant().lower() + def run_esptool(baud_rate): cmd = [ "esptool.py", "--before", @@ -292,7 +295,8 @@ def upload_using_platformio(config, port): def upload_program(config, args, host): if get_port_type(host) == "SERIAL": if CORE.target_platform in (PLATFORM_ESP32, PLATFORM_ESP8266): - return upload_using_esptool(config, host) + file = getattr(args, "file", None) + return upload_using_esptool(config, host, file) if CORE.target_platform in (PLATFORM_RP2040): return upload_using_platformio(config, args.device) From 87395d259ee53c8e50a2bbc29525bdeff0a97493 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 7 Sep 2023 13:22:39 +1200 Subject: [PATCH 0151/2101] Allow "--device SERIAL" on cli to flash only via serial (#5351) --- esphome/__main__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/__main__.py b/esphome/__main__.py index 9fac8cd605..cf540f58ba 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -85,6 +85,8 @@ def choose_upload_log_host( options = [] for port in get_serial_ports(): options.append((f"{port.path} ({port.description})", port.path)) + if default == "SERIAL": + return choose_prompt(options, purpose=purpose) if (show_ota and "ota" in CORE.config) or (show_api and "api" in CORE.config): options.append((f"Over The Air ({CORE.address})", CORE.address)) if default == "OTA": From ab872b075a402d0180ab5087199b7e251b577f64 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Thu, 7 Sep 2023 04:48:44 -0500 Subject: [PATCH 0152/2101] Fix PN532 for IDF 5 and ultralight enhancements (#5352) --- esphome/components/nfc/nfc.cpp | 2 +- esphome/components/pn532/pn532.h | 8 +- .../pn532/pn532_mifare_ultralight.cpp | 119 ++++++++++-------- 3 files changed, 71 insertions(+), 58 deletions(-) diff --git a/esphome/components/nfc/nfc.cpp b/esphome/components/nfc/nfc.cpp index b7c7215028..7225e373b3 100644 --- a/esphome/components/nfc/nfc.cpp +++ b/esphome/components/nfc/nfc.cpp @@ -54,7 +54,7 @@ uint8_t get_mifare_classic_ndef_start_index(std::vector &data) { bool decode_mifare_classic_tlv(std::vector &data, uint32_t &message_length, uint8_t &message_start_index) { uint8_t i = get_mifare_classic_ndef_start_index(data); - if (i < 0 || data[i] != 0x03) { + if (data[i] != 0x03) { ESP_LOGE(TAG, "Error, Can't decode message length."); return false; } diff --git a/esphome/components/pn532/pn532.h b/esphome/components/pn532/pn532.h index 73b349e328..8ae215dfd9 100644 --- a/esphome/components/pn532/pn532.h +++ b/esphome/components/pn532/pn532.h @@ -7,6 +7,7 @@ #include "esphome/components/nfc/nfc.h" #include "esphome/components/nfc/automation.h" +#include #include namespace esphome { @@ -74,10 +75,11 @@ class PN532 : public PollingComponent { bool write_mifare_classic_tag_(std::vector &uid, nfc::NdefMessage *message); std::unique_ptr read_mifare_ultralight_tag_(std::vector &uid); - bool read_mifare_ultralight_page_(uint8_t page_num, std::vector &data); - bool is_mifare_ultralight_formatted_(); + 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_(uint8_t &message_length, uint8_t &message_start_index); + 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 clean_mifare_ultralight_(); diff --git a/esphome/components/pn532/pn532_mifare_ultralight.cpp b/esphome/components/pn532/pn532_mifare_ultralight.cpp index 1b91ae919e..b08a7336c7 100644 --- a/esphome/components/pn532/pn532_mifare_ultralight.cpp +++ b/esphome/components/pn532/pn532_mifare_ultralight.cpp @@ -9,93 +9,104 @@ namespace pn532 { static const char *const TAG = "pn532.mifare_ultralight"; std::unique_ptr PN532::read_mifare_ultralight_tag_(std::vector &uid) { - if (!this->is_mifare_ultralight_formatted_()) { - ESP_LOGD(TAG, "Not NDEF formatted"); + 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, + data)) { + return make_unique(uid, nfc::NFC_FORUM_TYPE_2); + } + + if (!this->is_mifare_ultralight_formatted_(data)) { + ESP_LOGW(TAG, "Not NDEF formatted"); return make_unique(uid, nfc::NFC_FORUM_TYPE_2); } uint8_t message_length; uint8_t message_start_index; - if (!this->find_mifare_ultralight_ndef_(message_length, message_start_index)) { + if (!this->find_mifare_ultralight_ndef_(data, message_length, message_start_index)) { + ESP_LOGW(TAG, "Couldn't find NDEF message"); return make_unique(uid, nfc::NFC_FORUM_TYPE_2); } - ESP_LOGVV(TAG, "message length: %d, start: %d", message_length, message_start_index); + ESP_LOGVV(TAG, "NDEF message length: %u, start: %u", message_length, message_start_index); if (message_length == 0) { return make_unique(uid, nfc::NFC_FORUM_TYPE_2); } - std::vector data; - for (uint8_t page = nfc::MIFARE_ULTRALIGHT_DATA_START_PAGE; page < nfc::MIFARE_ULTRALIGHT_MAX_PAGE; page++) { - std::vector page_data; - if (!this->read_mifare_ultralight_page_(page, page_data)) { - ESP_LOGE(TAG, "Error reading page %d", page); + // we already read pages 3-6 earlier -- pick up where we left off so we're not re-reading pages + const uint8_t read_length = message_length + message_start_index > 12 ? message_length + message_start_index - 12 : 0; + if (read_length) { + if (!read_mifare_ultralight_bytes_(nfc::MIFARE_ULTRALIGHT_DATA_START_PAGE + 3, read_length, data)) { + ESP_LOGE(TAG, "Error reading tag data"); return make_unique(uid, nfc::NFC_FORUM_TYPE_2); } - data.insert(data.end(), page_data.begin(), page_data.end()); - - if (data.size() >= (message_length + message_start_index)) - break; } - - data.erase(data.begin(), data.begin() + message_start_index); - data.erase(data.begin() + message_length, data.end()); + // we need to trim off page 3 as well as any bytes ahead of message_start_index + data.erase(data.begin(), data.begin() + message_start_index + nfc::MIFARE_ULTRALIGHT_PAGE_SIZE); return make_unique(uid, nfc::NFC_FORUM_TYPE_2, data); } -bool PN532::read_mifare_ultralight_page_(uint8_t page_num, std::vector &data) { - if (!this->write_command_({ - PN532_COMMAND_INDATAEXCHANGE, - 0x01, // One card - nfc::MIFARE_CMD_READ, - page_num, - })) { - return false; +bool PN532::read_mifare_ultralight_bytes_(uint8_t start_page, uint16_t num_bytes, std::vector &data) { + const uint8_t read_increment = nfc::MIFARE_ULTRALIGHT_READ_SIZE * nfc::MIFARE_ULTRALIGHT_PAGE_SIZE; + std::vector response; + + for (uint8_t i = 0; i * read_increment < num_bytes; i++) { + if (!this->write_command_({ + PN532_COMMAND_INDATAEXCHANGE, + 0x01, // One card + nfc::MIFARE_CMD_READ, + uint8_t(i * nfc::MIFARE_ULTRALIGHT_READ_SIZE + start_page), + })) { + return false; + } + + if (!this->read_response(PN532_COMMAND_INDATAEXCHANGE, response) || response[0] != 0x00) { + return false; + } + uint16_t bytes_offset = (i + 1) * read_increment; + auto pages_in_end_itr = bytes_offset <= num_bytes ? response.end() : response.end() - (bytes_offset - num_bytes); + + if ((pages_in_end_itr > response.begin()) && (pages_in_end_itr <= response.end())) { + data.insert(data.end(), response.begin() + 1, pages_in_end_itr); + } } - if (!this->read_response(PN532_COMMAND_INDATAEXCHANGE, data) || data[0] != 0x00) { - return false; - } - data.erase(data.begin()); - // We only want 1 page of data but the PN532 returns 4 at once. - data.erase(data.begin() + 4, data.end()); - - ESP_LOGVV(TAG, "Pages %d-%d: %s", page_num, page_num + 4, nfc::format_bytes(data).c_str()); + ESP_LOGVV(TAG, "Data read: %s", nfc::format_bytes(data).c_str()); return true; } -bool PN532::is_mifare_ultralight_formatted_() { - std::vector data; - if (this->read_mifare_ultralight_page_(4, data)) { - return !(data[0] == 0xFF && data[1] == 0xFF && data[2] == 0xFF && data[3] == 0xFF); - } - return true; +bool PN532::is_mifare_ultralight_formatted_(const std::vector &page_3_to_6) { + const uint8_t p4_offset = nfc::MIFARE_ULTRALIGHT_PAGE_SIZE; // page 4 will begin 4 bytes into the vector + + return (page_3_to_6.size() > p4_offset + 3) && + !((page_3_to_6[p4_offset + 0] == 0xFF) && (page_3_to_6[p4_offset + 1] == 0xFF) && + (page_3_to_6[p4_offset + 2] == 0xFF) && (page_3_to_6[p4_offset + 3] == 0xFF)); } uint16_t PN532::read_mifare_ultralight_capacity_() { std::vector data; - if (this->read_mifare_ultralight_page_(3, data)) { + if (this->read_mifare_ultralight_bytes_(3, nfc::MIFARE_ULTRALIGHT_PAGE_SIZE, data)) { + ESP_LOGV(TAG, "Tag capacity is %u bytes", data[2] * 8U); return data[2] * 8U; } return 0; } -bool PN532::find_mifare_ultralight_ndef_(uint8_t &message_length, uint8_t &message_start_index) { - std::vector data; - for (int page = 4; page < 6; page++) { - std::vector page_data; - if (!this->read_mifare_ultralight_page_(page, page_data)) { - return false; - } - data.insert(data.end(), page_data.begin(), page_data.end()); +bool PN532::find_mifare_ultralight_ndef_(const std::vector &page_3_to_6, uint8_t &message_length, + 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)) { + return false; } - if (data[0] == 0x03) { - message_length = data[1]; + + if (page_3_to_6[p4_offset + 0] == 0x03) { + message_length = page_3_to_6[p4_offset + 1]; message_start_index = 2; return true; - } else if (data[5] == 0x03) { - message_length = data[6]; + } else if (page_3_to_6[p4_offset + 5] == 0x03) { + message_length = page_3_to_6[p4_offset + 6]; message_start_index = 7; return true; } @@ -111,7 +122,7 @@ bool PN532::write_mifare_ultralight_tag_(std::vector &uid, nfc::NdefMes uint32_t buffer_length = nfc::get_mifare_ultralight_buffer_size(message_length); if (buffer_length > capacity) { - ESP_LOGE(TAG, "Message length exceeds tag capacity %d > %d", buffer_length, capacity); + ESP_LOGE(TAG, "Message length exceeds tag capacity %" PRIu32 " > %" PRIu32, buffer_length, capacity); return false; } @@ -164,13 +175,13 @@ bool PN532::write_mifare_ultralight_page_(uint8_t page_num, std::vector }); data.insert(data.end(), write_data.begin(), write_data.end()); if (!this->write_command_(data)) { - ESP_LOGE(TAG, "Error writing page %d", page_num); + ESP_LOGE(TAG, "Error writing page %u", page_num); return false; } std::vector response; if (!this->read_response(PN532_COMMAND_INDATAEXCHANGE, response)) { - ESP_LOGE(TAG, "Error writing page %d", page_num); + ESP_LOGE(TAG, "Error writing page %u", page_num); return false; } From ce171f5c002c229cd207c0858881d5a79fd12689 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Thu, 7 Sep 2023 04:49:12 -0500 Subject: [PATCH 0153/2101] Fix cpu_ll_get_cycle_count() deprecated warning (#5353) --- esphome/components/esp32/core.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/esphome/components/esp32/core.cpp b/esphome/components/esp32/core.cpp index 16aa93c232..48c8b2b04d 100644 --- a/esphome/components/esp32/core.cpp +++ b/esphome/components/esp32/core.cpp @@ -53,7 +53,11 @@ void arch_init() { void IRAM_ATTR HOT arch_feed_wdt() { esp_task_wdt_reset(); } uint8_t progmem_read_byte(const uint8_t *addr) { return *addr; } +#if ESP_IDF_VERSION_MAJOR >= 5 +uint32_t arch_get_cpu_cycle_count() { return esp_cpu_get_cycle_count(); } +#else uint32_t arch_get_cpu_cycle_count() { return cpu_hal_get_cycle_count(); } +#endif uint32_t arch_get_cpu_freq_hz() { return rtc_clk_apb_freq_get(); } #ifdef USE_ESP_IDF From 5c26f95a4be6948adb4fc35252f297a6b17af4a8 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Fri, 8 Sep 2023 17:27:19 +1000 Subject: [PATCH 0154/2101] Refactor SPI code; Add ESP-IDF hardware support (#5311) * Checkpoint * Checkpoint * Checkpoint * Revert hal change * Checkpoint * Checkpoint * Checkpoint * Checkpoint * ESP-IDF working * clang-format * use bus_list * Add spi_device; fix 16 bit transfer. * Enable multi_conf; Fix LSB 16 bit transactions * Formatting fixes * Clang-format, codeowners * Add test * Formatting * clang tidy * clang-format * clang-tidy * clang-format * Checkpoint * Checkpoint * Checkpoint * Revert hal change * Checkpoint * Checkpoint * Checkpoint * Checkpoint * ESP-IDF working * clang-format * use bus_list * Add spi_device; fix 16 bit transfer. * Enable multi_conf; Fix LSB 16 bit transactions * Formatting fixes * Clang-format, codeowners * Add test * Formatting * clang tidy * clang-format * clang-tidy * clang-format * Clang-tidy * Clang-format * clang-tidy * clang-tidy * Fix ESP8266 * RP2040 * RP2040 * Avoid use of spi1 as id * Refactor SPI code. Add support for ESP-IDF hardware SPI * Force SW only for RP2040 * Break up large transfers * Add interface: option for spi. validate pins in python. * Can't use match/case with Python 3.9. Check for inverted pins. * Work around target_platform issue with * Remove debug code * Optimize write_array16 * Show errors in hex * Only one spi on ESP32Cx variants * Ensure bus is claimed before asserting /CS. * Check on init/deinit * Allow maximum rate write only SPI on GPIO MUXed pins. * Clang-format * Clang-tidy * Fix issue with reads. * Finger trouble... * Make comment about missing SPI on Cx variants * Pacify CI clang-format. Did not complain locally?? * Restore 8266 to its former SPI glory * Fix per clang-format * Move validation and choice of SPI into Python code. * Add test for interface: config * Fix issues found on self-review. --------- Co-authored-by: Keith Burzinski --- CODEOWNERS | 1 + esphome/components/spi/__init__.py | 200 ++++++- esphome/components/spi/spi.cpp | 296 +++------- esphome/components/spi/spi.h | 567 +++++++++++-------- esphome/components/spi/spi_arduino.cpp | 89 +++ esphome/components/spi/spi_esp_idf.cpp | 163 ++++++ esphome/components/spi_device/__init__.py | 49 ++ esphome/components/spi_device/spi_device.cpp | 30 + esphome/components/spi_device/spi_device.h | 22 + tests/test4.yaml | 1 + tests/test8.yaml | 9 + 11 files changed, 954 insertions(+), 473 deletions(-) create mode 100644 esphome/components/spi/spi_arduino.cpp create mode 100644 esphome/components/spi/spi_esp_idf.cpp create mode 100644 esphome/components/spi_device/__init__.py create mode 100644 esphome/components/spi_device/spi_device.cpp create mode 100644 esphome/components/spi_device/spi_device.h diff --git a/CODEOWNERS b/CODEOWNERS index 498cfcac01..ab4c5011f6 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -270,6 +270,7 @@ esphome/components/socket/* @esphome/core esphome/components/sonoff_d1/* @anatoly-savchenkov esphome/components/speaker/* @jesserockz esphome/components/spi/* @esphome/core +esphome/components/spi_device/* @clydebarrow esphome/components/sprinkler/* @kbx81 esphome/components/sps30/* @martgras esphome/components/ssd1322_base/* @kbx81 diff --git a/esphome/components/spi/__init__.py b/esphome/components/spi/__init__.py index a2ef956200..79e7a5b034 100644 --- a/esphome/components/spi/__init__.py +++ b/esphome/components/spi/__init__.py @@ -1,6 +1,17 @@ +import re + import esphome.codegen as cg import esphome.config_validation as cv import esphome.final_validate as fv +from esphome.components.esp32.const import ( + KEY_ESP32, + VARIANT_ESP32S2, + VARIANT_ESP32S3, + VARIANT_ESP32C2, + VARIANT_ESP32C3, + VARIANT_ESP32C6, + VARIANT_ESP32H2, +) from esphome import pins from esphome.const import ( CONF_CLK_PIN, @@ -9,6 +20,11 @@ from esphome.const import ( CONF_MOSI_PIN, CONF_SPI_ID, CONF_CS_PIN, + CONF_NUMBER, + CONF_INVERTED, + KEY_CORE, + KEY_TARGET_PLATFORM, + KEY_VARIANT, ) from esphome.core import coroutine_with_priority, CORE @@ -34,10 +50,147 @@ SPI_DATA_RATE_OPTIONS = { } SPI_DATA_RATE_SCHEMA = cv.All(cv.frequency, cv.enum(SPI_DATA_RATE_OPTIONS)) -MULTI_CONF = True CONF_FORCE_SW = "force_sw" +CONF_INTERFACE = "interface" +CONF_INTERFACE_INDEX = "interface_index" -CONFIG_SCHEMA = cv.All( + +def get_target_platform(): + return ( + CORE.data[KEY_CORE][KEY_TARGET_PLATFORM] + if KEY_TARGET_PLATFORM in CORE.data[KEY_CORE] + else "" + ) + + +def get_target_variant(): + return ( + CORE.data[KEY_ESP32][KEY_VARIANT] if KEY_VARIANT in CORE.data[KEY_ESP32] else "" + ) + + +# Get a list of available hardware interfaces based on target and variant. +# The returned value is a list of lists of names +def get_hw_interface_list(): + target_platform = get_target_platform() + if target_platform == "esp8266": + return [["spi", "hspi"]] + if target_platform == "esp32": + if get_target_variant() in [ + VARIANT_ESP32C2, + VARIANT_ESP32C3, + VARIANT_ESP32C6, + VARIANT_ESP32H2, + ]: + return [["spi", "spi2"]] + return [["spi", "spi2"], ["spi3"]] + if target_platform == "rp2040": + return [["spi"]] + return [] + + +# Given an SPI name, return the index of it in the available list +def get_spi_index(name): + for i, ilist in enumerate(get_hw_interface_list()): + if name in ilist: + return i + # Should never get to here. + raise cv.Invalid(f"{name} is not an available SPI") + + +# Check that pins are suitable for HW spi +# TODO verify that the pins are internal +def validate_hw_pins(spi): + clk_pin = spi[CONF_CLK_PIN] + if clk_pin[CONF_INVERTED]: + return False + clk_pin_no = clk_pin[CONF_NUMBER] + sdo_pin_no = -1 + sdi_pin_no = -1 + if CONF_MOSI_PIN in spi: + sdo_pin = spi[CONF_MOSI_PIN] + if sdo_pin[CONF_INVERTED]: + return False + sdo_pin_no = sdo_pin[CONF_NUMBER] + if CONF_MISO_PIN in spi: + sdi_pin = spi[CONF_MISO_PIN] + if sdi_pin[CONF_INVERTED]: + return False + sdi_pin_no = sdi_pin[CONF_NUMBER] + + target_platform = get_target_platform() + if target_platform == "esp8266": + if clk_pin_no == 6: + return sdo_pin_no in (-1, 8) and sdi_pin_no in (-1, 7) + if clk_pin_no == 14: + return sdo_pin_no in (-1, 13) and sdi_pin_no in (-1, 12) + return False + + if target_platform == "esp32": + return clk_pin_no >= 0 + + return False + + +def validate_spi_config(config): + available = list(range(len(get_hw_interface_list()))) + for spi in config: + interface = spi[CONF_INTERFACE] + if spi[CONF_FORCE_SW]: + if interface == "any": + spi[CONF_INTERFACE] = interface = "software" + elif interface != "software": + raise cv.Invalid("force_sw is deprecated - use interface: software") + if interface == "software": + pass + elif interface == "any": + if not validate_hw_pins(spi): + spi[CONF_INTERFACE] = "software" + elif interface == "hardware": + if len(available) == 0: + raise cv.Invalid("No hardware interface available") + index = spi[CONF_INTERFACE_INDEX] = available[0] + available.remove(index) + else: + # Must be a specific name + index = spi[CONF_INTERFACE_INDEX] = get_spi_index(interface) + if index not in available: + raise cv.Invalid( + f"interface '{interface}' not available here (may be already assigned)" + ) + available.remove(index) + + # Second time around: + # Any specific names and any 'hardware' requests will have already been filled, + # so just need to assign remaining hardware to 'any' requests. + for spi in config: + if spi[CONF_INTERFACE] == "any" and len(available) != 0: + index = available[0] + spi[CONF_INTERFACE_INDEX] = index + available.remove(index) + if CONF_INTERFACE_INDEX in spi and not validate_hw_pins(spi): + raise cv.Invalid("Invalid pin selections for hardware SPI interface") + + return config + + +# Given an SPI index, convert to a string that represents the C++ object for it. +def get_spi_interface(index): + if CORE.using_esp_idf: + return ["SPI2_HOST", "SPI3_HOST"][index] + # Arduino code follows + platform = get_target_platform() + if platform == "rp2040": + return "&spi1" + if index == 0: + return "&SPI" + # Following code can't apply to C2, H2 or 8266 since they have only one SPI + if get_target_variant() in (VARIANT_ESP32S3, VARIANT_ESP32S2): + return "new SPIClass(FSPI)" + return "return new SPIClass(HSPI)" + + +SPI_SCHEMA = cv.All( cv.Schema( { cv.GenerateID(): cv.declare_id(SPIComponent), @@ -45,28 +198,47 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_MISO_PIN): pins.gpio_input_pin_schema, cv.Optional(CONF_MOSI_PIN): pins.gpio_output_pin_schema, cv.Optional(CONF_FORCE_SW, default=False): cv.boolean, + cv.Optional(CONF_INTERFACE, default="any"): cv.one_of( + *sum(get_hw_interface_list(), ["software", "hardware", "any"]), + lower=True, + ), } ), cv.has_at_least_one_key(CONF_MISO_PIN, CONF_MOSI_PIN), cv.only_on(["esp32", "esp8266", "rp2040"]), ) +CONFIG_SCHEMA = cv.All( + cv.ensure_list(SPI_SCHEMA), + validate_spi_config, +) + @coroutine_with_priority(1.0) -async def to_code(config): +async def to_code(configs): cg.add_global(spi_ns.using) - var = cg.new_Pvariable(config[CONF_ID]) - await cg.register_component(var, config) + for spi in configs: + var = cg.new_Pvariable(spi[CONF_ID]) + await cg.register_component(var, spi) - clk = await cg.gpio_pin_expression(config[CONF_CLK_PIN]) - cg.add(var.set_clk(clk)) - cg.add(var.set_force_sw(config[CONF_FORCE_SW])) - if CONF_MISO_PIN in config: - miso = await cg.gpio_pin_expression(config[CONF_MISO_PIN]) - cg.add(var.set_miso(miso)) - if CONF_MOSI_PIN in config: - mosi = await cg.gpio_pin_expression(config[CONF_MOSI_PIN]) - cg.add(var.set_mosi(mosi)) + clk = await cg.gpio_pin_expression(spi[CONF_CLK_PIN]) + cg.add(var.set_clk(clk)) + if CONF_MISO_PIN in spi: + miso = await cg.gpio_pin_expression(spi[CONF_MISO_PIN]) + cg.add(var.set_miso(miso)) + if CONF_MOSI_PIN in spi: + mosi = await cg.gpio_pin_expression(spi[CONF_MOSI_PIN]) + cg.add(var.set_mosi(mosi)) + if CONF_INTERFACE_INDEX in spi: + index = spi[CONF_INTERFACE_INDEX] + cg.add(var.set_interface(cg.RawExpression(get_spi_interface(index)))) + cg.add( + var.set_interface_name( + re.sub( + r"\W", "", get_spi_interface(index).replace("new SPIClass", "") + ) + ) + ) if CORE.using_arduino: cg.add_library("SPI", None) diff --git a/esphome/components/spi/spi.cpp b/esphome/components/spi/spi.cpp index 33630897f6..935399500f 100644 --- a/esphome/components/spi/spi.cpp +++ b/esphome/components/spi/spi.cpp @@ -1,268 +1,116 @@ #include "spi.h" #include "esphome/core/log.h" -#include "esphome/core/helpers.h" #include "esphome/core/application.h" namespace esphome { namespace spi { -static const char *const TAG = "spi"; +const char *const TAG = "spi"; -void IRAM_ATTR HOT SPIComponent::disable() { -#ifdef USE_SPI_ARDUINO_BACKEND - if (this->hw_spi_ != nullptr) { - this->hw_spi_->endTransaction(); - } -#endif // USE_SPI_ARDUINO_BACKEND - if (this->active_cs_) { - this->active_cs_->digital_write(true); - this->active_cs_ = nullptr; +SPIDelegate *const SPIDelegate::NULL_DELEGATE = // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + new SPIDelegateDummy(); +// https://bugs.llvm.org/show_bug.cgi?id=48040 + +bool SPIDelegate::is_ready() { return true; } + +GPIOPin *const NullPin::NULL_PIN = new NullPin(); // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + +SPIDelegate *SPIComponent::register_device(SPIClient *device, SPIMode mode, SPIBitOrder bit_order, uint32_t data_rate, + GPIOPin *cs_pin) { + if (this->devices_.count(device) != 0) { + ESP_LOGE(TAG, "SPI device already registered"); + return this->devices_[device]; } + SPIDelegate *delegate = this->spi_bus_->get_delegate(data_rate, bit_order, mode, cs_pin); // NOLINT + this->devices_[device] = delegate; + return delegate; } + +void SPIComponent::unregister_device(SPIClient *device) { + if (this->devices_.count(device) == 0) { + esph_log_e(TAG, "SPI device not registered"); + return; + } + delete this->devices_[device]; // NOLINT + this->devices_.erase(device); +} + void SPIComponent::setup() { - ESP_LOGCONFIG(TAG, "Setting up SPI bus..."); - this->clk_->setup(); - this->clk_->digital_write(true); + ESP_LOGD(TAG, "Setting up SPI bus..."); -#ifdef USE_SPI_ARDUINO_BACKEND - bool use_hw_spi = !this->force_sw_; - const bool has_miso = this->miso_ != nullptr; - const bool has_mosi = this->mosi_ != nullptr; - int8_t clk_pin = -1, miso_pin = -1, mosi_pin = -1; - - if (!this->clk_->is_internal()) - use_hw_spi = false; - if (has_miso && !miso_->is_internal()) - use_hw_spi = false; - if (has_mosi && !mosi_->is_internal()) - use_hw_spi = false; - if (use_hw_spi) { - auto *clk_internal = (InternalGPIOPin *) clk_; - auto *miso_internal = (InternalGPIOPin *) miso_; - auto *mosi_internal = (InternalGPIOPin *) mosi_; - - if (clk_internal->is_inverted()) - use_hw_spi = false; - if (has_miso && miso_internal->is_inverted()) - use_hw_spi = false; - if (has_mosi && mosi_internal->is_inverted()) - use_hw_spi = false; - - if (use_hw_spi) { - clk_pin = clk_internal->get_pin(); - miso_pin = has_miso ? miso_internal->get_pin() : -1; - mosi_pin = has_mosi ? mosi_internal->get_pin() : -1; - } - } -#ifdef USE_ESP8266 - if (!(clk_pin == 6 && miso_pin == 7 && mosi_pin == 8) && - !(clk_pin == 14 && (!has_miso || miso_pin == 12) && (!has_mosi || mosi_pin == 13))) - use_hw_spi = false; - - if (use_hw_spi) { - this->hw_spi_ = &SPI; - this->hw_spi_->pins(clk_pin, miso_pin, mosi_pin, 0); - this->hw_spi_->begin(); + if (this->sdo_pin_ == nullptr) + this->sdo_pin_ = NullPin::NULL_PIN; + if (this->sdi_pin_ == nullptr) + this->sdi_pin_ = NullPin::NULL_PIN; + if (this->clk_pin_ == nullptr) { + ESP_LOGE(TAG, "No clock pin for SPI"); + this->mark_failed(); return; } -#endif // USE_ESP8266 -#ifdef USE_ESP32 - static uint8_t spi_bus_num = 0; - if (spi_bus_num >= 2) { - use_hw_spi = false; - } - if (use_hw_spi) { - if (spi_bus_num == 0) { - this->hw_spi_ = &SPI; - } else { -#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) || \ - defined(USE_ESP32_VARIANT_ESP32C2) || defined(USE_ESP32_VARIANT_ESP32C6) - this->hw_spi_ = new SPIClass(FSPI); // NOLINT(cppcoreguidelines-owning-memory) -#else - this->hw_spi_ = new SPIClass(HSPI); // NOLINT(cppcoreguidelines-owning-memory) -#endif // USE_ESP32_VARIANT + if (this->using_hw_) { + this->spi_bus_ = SPIComponent::get_bus(this->interface_, this->clk_pin_, this->sdo_pin_, this->sdi_pin_); + if (this->spi_bus_ == nullptr) { + ESP_LOGE(TAG, "Unable to allocate SPI interface"); + this->mark_failed(); } - spi_bus_num++; - this->hw_spi_->begin(clk_pin, miso_pin, mosi_pin); - return; - } -#endif // USE_ESP32 -#ifdef USE_RP2040 - static uint8_t spi_bus_num = 0; - if (spi_bus_num >= 2) { - use_hw_spi = false; - } - if (use_hw_spi) { - SPIClassRP2040 *spi; - if (spi_bus_num == 0) { - spi = &SPI; - } else { - spi = &SPI1; - } - spi_bus_num++; - - if (miso_pin != -1) - spi->setRX(miso_pin); - if (mosi_pin != -1) - spi->setTX(mosi_pin); - spi->setSCK(clk_pin); - this->hw_spi_ = spi; - this->hw_spi_->begin(); - return; - } -#endif // USE_RP2040 -#endif // USE_SPI_ARDUINO_BACKEND - - if (this->miso_ != nullptr) { - this->miso_->setup(); - } - if (this->mosi_ != nullptr) { - this->mosi_->setup(); - this->mosi_->digital_write(false); + } else { + this->spi_bus_ = new SPIBus(this->clk_pin_, this->sdo_pin_, this->sdi_pin_); // NOLINT + this->clk_pin_->setup(); + this->clk_pin_->digital_write(true); + this->sdo_pin_->setup(); + this->sdi_pin_->setup(); } } + void SPIComponent::dump_config() { ESP_LOGCONFIG(TAG, "SPI bus:"); - LOG_PIN(" CLK Pin: ", this->clk_); - LOG_PIN(" MISO Pin: ", this->miso_); - LOG_PIN(" MOSI Pin: ", this->mosi_); -#ifdef USE_SPI_ARDUINO_BACKEND - ESP_LOGCONFIG(TAG, " Using HW SPI: %s", YESNO(this->hw_spi_ != nullptr)); -#endif // USE_SPI_ARDUINO_BACKEND -} -float SPIComponent::get_setup_priority() const { return setup_priority::BUS; } - -void SPIComponent::cycle_clock_(bool value) { - uint32_t start = arch_get_cpu_cycle_count(); - while (start - arch_get_cpu_cycle_count() < this->wait_cycle_) - ; - this->clk_->digital_write(value); - start += this->wait_cycle_; - while (start - arch_get_cpu_cycle_count() < this->wait_cycle_) - ; + LOG_PIN(" CLK Pin: ", this->clk_pin_) + LOG_PIN(" SDI Pin: ", this->sdi_pin_) + LOG_PIN(" SDO Pin: ", this->sdo_pin_) + if (this->spi_bus_->is_hw()) { + ESP_LOGCONFIG(TAG, " Using HW SPI: %s", this->interface_name_); + } else { + ESP_LOGCONFIG(TAG, " Using software SPI"); + } } -// NOLINTNEXTLINE -#ifndef CLANG_TIDY -#pragma GCC optimize("unroll-loops") -// NOLINTNEXTLINE -#pragma GCC optimize("O2") -#endif // CLANG_TIDY +void SPIDelegateDummy::begin_transaction() { ESP_LOGE(TAG, "SPIDevice not initialised - did you call spi_setup()?"); } -template -uint8_t HOT SPIComponent::transfer_(uint8_t data) { +uint8_t SPIDelegateBitBash::transfer(uint8_t data) { // Clock starts out at idle level - this->clk_->digital_write(CLOCK_POLARITY); + this->clk_pin_->digital_write(clock_polarity_); uint8_t out_data = 0; for (uint8_t i = 0; i < 8; i++) { uint8_t shift; - if (BIT_ORDER == BIT_ORDER_MSB_FIRST) { + if (bit_order_ == BIT_ORDER_MSB_FIRST) { shift = 7 - i; } else { shift = i; } - if (CLOCK_PHASE == CLOCK_PHASE_LEADING) { + if (clock_phase_ == CLOCK_PHASE_LEADING) { // sampling on leading edge - if (WRITE) { - this->mosi_->digital_write(data & (1 << shift)); - } - - // SAMPLE! - this->cycle_clock_(!CLOCK_POLARITY); - - if (READ) { - out_data |= uint8_t(this->miso_->digital_read()) << shift; - } - - this->cycle_clock_(CLOCK_POLARITY); + this->sdo_pin_->digital_write(data & (1 << shift)); + this->cycle_clock_(); + out_data |= uint8_t(this->sdi_pin_->digital_read()) << shift; + this->clk_pin_->digital_write(!this->clock_polarity_); + this->cycle_clock_(); + this->clk_pin_->digital_write(this->clock_polarity_); } else { // sampling on trailing edge - this->cycle_clock_(!CLOCK_POLARITY); - - if (WRITE) { - this->mosi_->digital_write(data & (1 << shift)); - } - - // SAMPLE! - this->cycle_clock_(CLOCK_POLARITY); - - if (READ) { - out_data |= uint8_t(this->miso_->digital_read()) << shift; - } + this->cycle_clock_(); + this->clk_pin_->digital_write(!this->clock_polarity_); + this->sdo_pin_->digital_write(data & (1 << shift)); + this->cycle_clock_(); + out_data |= uint8_t(this->sdi_pin_->digital_read()) << shift; + this->clk_pin_->digital_write(this->clock_polarity_); } } - App.feed_wdt(); - return out_data; } -// Generate with (py3): -// -// from itertools import product -// bit_orders = ['BIT_ORDER_LSB_FIRST', 'BIT_ORDER_MSB_FIRST'] -// clock_pols = ['CLOCK_POLARITY_LOW', 'CLOCK_POLARITY_HIGH'] -// clock_phases = ['CLOCK_PHASE_LEADING', 'CLOCK_PHASE_TRAILING'] -// reads = [False, True] -// writes = [False, True] -// cpp_bool = {False: 'false', True: 'true'} -// for b, cpol, cph, r, w in product(bit_orders, clock_pols, clock_phases, reads, writes): -// if not r and not w: -// continue -// print(f"template uint8_t SPIComponent::transfer_<{b}, {cpol}, {cph}, {cpp_bool[r]}, {cpp_bool[w]}>(uint8_t -// data);") - -template uint8_t SPIComponent::transfer_( - uint8_t data); -template uint8_t SPIComponent::transfer_( - uint8_t data); -template uint8_t SPIComponent::transfer_( - uint8_t data); -template uint8_t SPIComponent::transfer_( - uint8_t data); -template uint8_t SPIComponent::transfer_( - uint8_t data); -template uint8_t SPIComponent::transfer_( - uint8_t data); -template uint8_t SPIComponent::transfer_( - uint8_t data); -template uint8_t SPIComponent::transfer_( - uint8_t data); -template uint8_t SPIComponent::transfer_( - uint8_t data); -template uint8_t SPIComponent::transfer_( - uint8_t data); -template uint8_t SPIComponent::transfer_( - uint8_t data); -template uint8_t SPIComponent::transfer_( - uint8_t data); -template uint8_t SPIComponent::transfer_( - uint8_t data); -template uint8_t SPIComponent::transfer_( - uint8_t data); -template uint8_t SPIComponent::transfer_( - uint8_t data); -template uint8_t SPIComponent::transfer_( - uint8_t data); -template uint8_t SPIComponent::transfer_( - uint8_t data); -template uint8_t SPIComponent::transfer_( - uint8_t data); -template uint8_t SPIComponent::transfer_( - uint8_t data); -template uint8_t SPIComponent::transfer_( - uint8_t data); -template uint8_t SPIComponent::transfer_( - uint8_t data); -template uint8_t SPIComponent::transfer_( - uint8_t data); -template uint8_t SPIComponent::transfer_( - uint8_t data); -template uint8_t SPIComponent::transfer_( - uint8_t data); - } // namespace spi } // namespace esphome diff --git a/esphome/components/spi/spi.h b/esphome/components/spi/spi.h index 159d117533..2761c2d604 100644 --- a/esphome/components/spi/spi.h +++ b/esphome/components/spi/spi.h @@ -2,16 +2,34 @@ #include "esphome/core/component.h" #include "esphome/core/hal.h" +#include "esphome/core/log.h" +#include "esphome/core/application.h" #include +#include #ifdef USE_ARDUINO -#define USE_SPI_ARDUINO_BACKEND -#endif -#ifdef USE_SPI_ARDUINO_BACKEND #include + +#ifdef USE_RP2040 +using SPIInterface = SPIClassRP2040 *; +#else +using SPIInterface = SPIClass *; #endif +#endif + +#ifdef USE_ESP_IDF + +#include "driver/spi_master.h" + +using SPIInterface = spi_host_device_t; + +#endif // USE_ESP_IDF + +/** + * Implementation of SPI Controller mode. + */ namespace esphome { namespace spi { @@ -48,10 +66,19 @@ enum SPIClockPhase { /// The data is sampled on a trailing clock edge. (CPHA=1) CLOCK_PHASE_TRAILING, }; -/** The SPI clock signal data rate. This defines for what duration the clock signal is HIGH/LOW. - * So effectively the rate of bytes can be calculated using + +/** + * Modes mapping to clock phase and polarity. * - * effective_byte_rate = spi_data_rate / 16 + */ + +enum SPIMode { + MODE0 = 0, + MODE1 = 1, + MODE2 = 2, + MODE3 = 3, +}; +/** The SPI clock signal frequency, which determines the transfer bit rate/second. * * Implementations can use the pre-defined constants here, or use an integer in the template definition * to manually use a specific data rate. @@ -71,270 +98,340 @@ enum SPIDataRate : uint32_t { DATA_RATE_80MHZ = 80000000, }; -class SPIComponent : public Component { +/** + * A pin to replace those that don't exist. + */ +class NullPin : public GPIOPin { + friend class SPIComponent; + + friend class SPIDelegate; + + friend class Utility; + public: - void set_clk(GPIOPin *clk) { clk_ = clk; } - void set_miso(GPIOPin *miso) { miso_ = miso; } - void set_mosi(GPIOPin *mosi) { mosi_ = mosi; } - void set_force_sw(bool force_sw) { force_sw_ = force_sw; } + void setup() override {} - void setup() override; + void pin_mode(gpio::Flags flags) override {} - void dump_config() override; + bool digital_read() override { return false; } - template uint8_t read_byte() { -#ifdef USE_SPI_ARDUINO_BACKEND - if (this->hw_spi_ != nullptr) { - return this->hw_spi_->transfer(0x00); - } -#endif // USE_SPI_ARDUINO_BACKEND - return this->transfer_(0x00); - } + void digital_write(bool value) override {} - template - void read_array(uint8_t *data, size_t length) { -#ifdef USE_SPI_ARDUINO_BACKEND - if (this->hw_spi_ != nullptr) { - this->hw_spi_->transfer(data, length); - return; - } -#endif // USE_SPI_ARDUINO_BACKEND - for (size_t i = 0; i < length; i++) { - data[i] = this->read_byte(); - } - } - - template - void write_byte(uint8_t data) { -#ifdef USE_SPI_ARDUINO_BACKEND - if (this->hw_spi_ != nullptr) { -#ifdef USE_RP2040 - this->hw_spi_->transfer(data); -#else - this->hw_spi_->write(data); -#endif - return; - } -#endif // USE_SPI_ARDUINO_BACKEND - this->transfer_(data); - } - - template - void write_byte16(const uint16_t data) { -#ifdef USE_SPI_ARDUINO_BACKEND - if (this->hw_spi_ != nullptr) { -#ifdef USE_RP2040 - this->hw_spi_->transfer16(data); -#else - this->hw_spi_->write16(data); -#endif - return; - } -#endif // USE_SPI_ARDUINO_BACKEND - - this->write_byte(data >> 8); - this->write_byte(data); - } - - template - void write_array16(const uint16_t *data, size_t length) { -#ifdef USE_SPI_ARDUINO_BACKEND - if (this->hw_spi_ != nullptr) { - for (size_t i = 0; i < length; i++) { -#ifdef USE_RP2040 - this->hw_spi_->transfer16(data[i]); -#else - this->hw_spi_->write16(data[i]); -#endif - } - return; - } -#endif // USE_SPI_ARDUINO_BACKEND - for (size_t i = 0; i < length; i++) { - this->write_byte16(data[i]); - } - } - - template - void write_array(const uint8_t *data, size_t length) { -#ifdef USE_SPI_ARDUINO_BACKEND - if (this->hw_spi_ != nullptr) { - auto *data_c = const_cast(data); -#ifdef USE_RP2040 - this->hw_spi_->transfer(data_c, length); -#else - this->hw_spi_->writeBytes(data_c, length); -#endif - return; - } -#endif // USE_SPI_ARDUINO_BACKEND - for (size_t i = 0; i < length; i++) { - this->write_byte(data[i]); - } - } - - template - uint8_t transfer_byte(uint8_t data) { - if (this->miso_ != nullptr) { -#ifdef USE_SPI_ARDUINO_BACKEND - if (this->hw_spi_ != nullptr) { - return this->hw_spi_->transfer(data); - } else { -#endif // USE_SPI_ARDUINO_BACKEND - return this->transfer_(data); -#ifdef USE_SPI_ARDUINO_BACKEND - } -#endif // USE_SPI_ARDUINO_BACKEND - } - this->write_byte(data); - return 0; - } - - template - void transfer_array(uint8_t *data, size_t length) { -#ifdef USE_SPI_ARDUINO_BACKEND - if (this->hw_spi_ != nullptr) { - if (this->miso_ != nullptr) { - this->hw_spi_->transfer(data, length); - } else { -#ifdef USE_RP2040 - this->hw_spi_->transfer(data, length); -#else - this->hw_spi_->writeBytes(data, length); -#endif - } - return; - } -#endif // USE_SPI_ARDUINO_BACKEND - - if (this->miso_ != nullptr) { - for (size_t i = 0; i < length; i++) { - data[i] = this->transfer_byte(data[i]); - } - } else { - this->write_array(data, length); - } - } - - template - void enable(GPIOPin *cs) { -#ifdef USE_SPI_ARDUINO_BACKEND - if (this->hw_spi_ != nullptr) { - uint8_t data_mode = SPI_MODE0; - if (!CLOCK_POLARITY && CLOCK_PHASE) { - data_mode = SPI_MODE1; - } else if (CLOCK_POLARITY && !CLOCK_PHASE) { - data_mode = SPI_MODE2; - } else if (CLOCK_POLARITY && CLOCK_PHASE) { - data_mode = SPI_MODE3; - } -#ifdef USE_RP2040 - SPISettings settings(DATA_RATE, static_cast(BIT_ORDER), data_mode); -#else - SPISettings settings(DATA_RATE, BIT_ORDER, data_mode); -#endif - this->hw_spi_->beginTransaction(settings); - } else { -#endif // USE_SPI_ARDUINO_BACKEND - this->clk_->digital_write(CLOCK_POLARITY); - uint32_t cpu_freq_hz = arch_get_cpu_freq_hz(); - this->wait_cycle_ = uint32_t(cpu_freq_hz) / DATA_RATE / 2ULL; -#ifdef USE_SPI_ARDUINO_BACKEND - } -#endif // USE_SPI_ARDUINO_BACKEND - - if (cs != nullptr) { - this->active_cs_ = cs; - this->active_cs_->digital_write(false); - } - } - - void disable(); - - float get_setup_priority() const override; + std::string dump_summary() const override { return std::string(); } protected: - inline void cycle_clock_(bool value); - - template - uint8_t transfer_(uint8_t data); - - GPIOPin *clk_; - GPIOPin *miso_{nullptr}; - GPIOPin *mosi_{nullptr}; - GPIOPin *active_cs_{nullptr}; - bool force_sw_{false}; -#ifdef USE_SPI_ARDUINO_BACKEND - SPIClass *hw_spi_{nullptr}; -#endif // USE_SPI_ARDUINO_BACKEND - uint32_t wait_cycle_; + static GPIOPin *const NULL_PIN; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + // https://bugs.llvm.org/show_bug.cgi?id=48040 }; -template -class SPIDevice { +class Utility { public: - SPIDevice() = default; - SPIDevice(SPIComponent *parent, GPIOPin *cs) : parent_(parent), cs_(cs) {} + static int get_pin_no(GPIOPin *pin) { + if (pin == nullptr || !pin->is_internal()) + return -1; + if (((InternalGPIOPin *) pin)->is_inverted()) + return -1; + return ((InternalGPIOPin *) pin)->get_pin(); + } - void set_spi_parent(SPIComponent *parent) { parent_ = parent; } - void set_cs_pin(GPIOPin *cs) { cs_ = cs; } + static SPIMode get_mode(SPIClockPolarity polarity, SPIClockPhase phase) { + if (polarity == CLOCK_POLARITY_HIGH) { + return phase == CLOCK_PHASE_LEADING ? MODE2 : MODE3; + } + return phase == CLOCK_PHASE_LEADING ? MODE0 : MODE1; + } - void spi_setup() { - if (this->cs_) { - this->cs_->setup(); - this->cs_->digital_write(true); + static SPIClockPhase get_phase(SPIMode mode) { + switch (mode) { + case MODE0: + case MODE2: + return CLOCK_PHASE_LEADING; + default: + return CLOCK_PHASE_TRAILING; } } - void enable() { this->parent_->template enable(this->cs_); } + static SPIClockPolarity get_polarity(SPIMode mode) { + switch (mode) { + case MODE0: + case MODE1: + return CLOCK_POLARITY_LOW; + default: + return CLOCK_POLARITY_HIGH; + } + } +}; - void disable() { this->parent_->disable(); } +class SPIDelegateDummy; - uint8_t read_byte() { return this->parent_->template read_byte(); } +// represents a device attached to an SPI bus, with a defined clock rate, mode and bit order. On Arduino this is +// a thin wrapper over SPIClass. +class SPIDelegate { + friend class SPIClient; - void read_array(uint8_t *data, size_t length) { - return this->parent_->template read_array(data, length); + public: + SPIDelegate() = default; + + SPIDelegate(uint32_t data_rate, SPIBitOrder bit_order, SPIMode mode, GPIOPin *cs_pin) + : bit_order_(bit_order), data_rate_(data_rate), mode_(mode), cs_pin_(cs_pin) { + if (this->cs_pin_ == nullptr) + this->cs_pin_ = NullPin::NULL_PIN; + this->cs_pin_->setup(); + this->cs_pin_->digital_write(true); } - template std::array read_array() { - std::array data; - this->read_array(data.data(), N); - return data; + virtual ~SPIDelegate(){}; + + // enable CS if configured. + virtual void begin_transaction() { this->cs_pin_->digital_write(false); } + + // end the transaction + virtual void end_transaction() { this->cs_pin_->digital_write(true); } + + // transfer one byte, return the byte that was read. + virtual uint8_t transfer(uint8_t data) = 0; + + // transfer a buffer, replace the contents with read data + virtual void transfer(uint8_t *ptr, size_t length) { this->transfer(ptr, ptr, length); } + + virtual void transfer(const uint8_t *txbuf, uint8_t *rxbuf, size_t length) { + for (size_t i = 0; i != length; i++) + rxbuf[i] = this->transfer(txbuf[i]); } - void write_byte(uint8_t data) { - return this->parent_->template write_byte(data); + // write 16 bits + virtual void write16(uint16_t data) { + if (this->bit_order_ == BIT_ORDER_MSB_FIRST) { + uint16_t buffer; + buffer = (data >> 8) | (data << 8); + this->write_array(reinterpret_cast(&buffer), 2); + } else { + this->write_array(reinterpret_cast(&data), 2); + } } - void write_byte16(uint16_t data) { - return this->parent_->template write_byte16(data); + virtual void write_array16(const uint16_t *data, size_t length) { + for (size_t i = 0; i != length; i++) { + this->write16(data[i]); + } } - void write_array16(const uint16_t *data, size_t length) { - this->parent_->template write_array16(data, length); + // write the contents of a buffer, ignore read data (buffer is unchanged.) + virtual void write_array(const uint8_t *ptr, size_t length) { + for (size_t i = 0; i != length; i++) + this->transfer(ptr[i]); } - void write_array(const uint8_t *data, size_t length) { - this->parent_->template write_array(data, length); + // read into a buffer, write nulls + virtual void read_array(uint8_t *ptr, size_t length) { + for (size_t i = 0; i != length; i++) + ptr[i] = this->transfer(0); } + // check if device is ready + virtual bool is_ready(); + + protected: + SPIBitOrder bit_order_{BIT_ORDER_MSB_FIRST}; + uint32_t data_rate_{1000000}; + SPIMode mode_{MODE0}; + GPIOPin *cs_pin_{NullPin::NULL_PIN}; + static SPIDelegate *const NULL_DELEGATE; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) +}; + +/** + * A dummy SPIDelegate that complains if it's used. + */ + +class SPIDelegateDummy : public SPIDelegate { + public: + SPIDelegateDummy() = default; + + uint8_t transfer(uint8_t data) override { return 0; } + + void begin_transaction() override; +}; + +/** + * An implementation of SPI that relies only on software toggling of pins. + * + */ +class SPIDelegateBitBash : public SPIDelegate { + public: + SPIDelegateBitBash(uint32_t clock, SPIBitOrder bit_order, SPIMode mode, GPIOPin *cs_pin, GPIOPin *clk_pin, + GPIOPin *sdo_pin, GPIOPin *sdi_pin) + : SPIDelegate(clock, bit_order, mode, cs_pin), clk_pin_(clk_pin), sdo_pin_(sdo_pin), sdi_pin_(sdi_pin) { + // this calculation is pretty meaningless except at very low bit rates. + this->wait_cycle_ = uint32_t(arch_get_cpu_freq_hz()) / this->data_rate_ / 2ULL; + this->clock_polarity_ = Utility::get_polarity(this->mode_); + this->clock_phase_ = Utility::get_phase(this->mode_); + } + + uint8_t transfer(uint8_t data) override; + + protected: + GPIOPin *clk_pin_; + GPIOPin *sdo_pin_; + GPIOPin *sdi_pin_; + uint32_t last_transition_{0}; + uint32_t wait_cycle_; + SPIClockPolarity clock_polarity_; + SPIClockPhase clock_phase_; + + void HOT cycle_clock_() { + while (this->last_transition_ - arch_get_cpu_cycle_count() < this->wait_cycle_) + continue; + this->last_transition_ += this->wait_cycle_; + } +}; + +class SPIBus { + public: + SPIBus() = default; + + SPIBus(GPIOPin *clk, GPIOPin *sdo, GPIOPin *sdi) : clk_pin_(clk), sdo_pin_(sdo), sdi_pin_(sdi) {} + + virtual SPIDelegate *get_delegate(uint32_t data_rate, SPIBitOrder bit_order, SPIMode mode, GPIOPin *cs_pin) { + return new SPIDelegateBitBash(data_rate, bit_order, mode, cs_pin, this->clk_pin_, this->sdo_pin_, this->sdi_pin_); + } + + virtual bool is_hw() { return false; } + + protected: + GPIOPin *clk_pin_{}; + GPIOPin *sdo_pin_{}; + GPIOPin *sdi_pin_{}; +}; + +class SPIClient; + +class SPIComponent : public Component { + public: + SPIDelegate *register_device(SPIClient *device, SPIMode mode, SPIBitOrder bit_order, uint32_t data_rate, + GPIOPin *cs_pin); + void unregister_device(SPIClient *device); + + void set_clk(GPIOPin *clk) { this->clk_pin_ = clk; } + + void set_miso(GPIOPin *sdi) { this->sdi_pin_ = sdi; } + + void set_mosi(GPIOPin *sdo) { this->sdo_pin_ = sdo; } + + void set_interface(SPIInterface interface) { + this->interface_ = interface; + this->using_hw_ = true; + } + + void set_interface_name(const char *name) { this->interface_name_ = name; } + + float get_setup_priority() const override { return setup_priority::BUS; } + + void setup() override; + void dump_config() override; + + protected: + GPIOPin *clk_pin_{nullptr}; + GPIOPin *sdi_pin_{nullptr}; + GPIOPin *sdo_pin_{nullptr}; + SPIInterface interface_{}; + bool using_hw_{false}; + const char *interface_name_{nullptr}; + SPIBus *spi_bus_{}; + std::map devices_; + + static SPIBus *get_bus(SPIInterface interface, GPIOPin *clk, GPIOPin *sdo, GPIOPin *sdi); +}; + +/** + * Base class for SPIDevice, un-templated. + */ +class SPIClient { + public: + SPIClient(SPIBitOrder bit_order, SPIMode mode, uint32_t data_rate) + : bit_order_(bit_order), mode_(mode), data_rate_(data_rate) {} + + virtual void spi_setup() { + this->delegate_ = this->parent_->register_device(this, this->mode_, this->bit_order_, this->data_rate_, this->cs_); + } + + virtual void spi_teardown() { + this->parent_->unregister_device(this); + this->delegate_ = SPIDelegate::NULL_DELEGATE; + } + + bool spi_is_ready() { return this->delegate_->is_ready(); } + + protected: + SPIBitOrder bit_order_{BIT_ORDER_MSB_FIRST}; + SPIMode mode_{MODE0}; + uint32_t data_rate_{1000000}; + SPIComponent *parent_{nullptr}; + GPIOPin *cs_{nullptr}; + SPIDelegate *delegate_{SPIDelegate::NULL_DELEGATE}; +}; + +/** + * The SPIDevice is what components using the SPI will create. + * + * @tparam BIT_ORDER + * @tparam CLOCK_POLARITY + * @tparam CLOCK_PHASE + * @tparam DATA_RATE + */ +template +class SPIDevice : public SPIClient { + public: + SPIDevice() : SPIClient(BIT_ORDER, Utility::get_mode(CLOCK_POLARITY, CLOCK_PHASE), DATA_RATE) {} + + SPIDevice(SPIComponent *parent, GPIOPin *cs_pin) { + this->set_spi_parent(parent); + this->set_cs_pin(cs_pin); + } + + void spi_setup() override { SPIClient::spi_setup(); } + + void spi_teardown() override { SPIClient::spi_teardown(); } + + void set_spi_parent(SPIComponent *parent) { this->parent_ = parent; } + + void set_cs_pin(GPIOPin *cs) { this->cs_ = cs; } + + void set_data_rate(uint32_t data_rate) { this->data_rate_ = data_rate; } + + void set_bit_order(SPIBitOrder order) { + this->bit_order_ = order; + esph_log_d("spi.h", "bit order set to %d", order); + } + + void set_mode(SPIMode mode) { this->mode_ = mode; } + + uint8_t read_byte() { return this->delegate_->transfer(0); } + + void read_array(uint8_t *data, size_t length) { return this->delegate_->read_array(data, length); } + + void write_byte(uint8_t data) { this->delegate_->write_array(&data, 1); } + + void transfer_array(uint8_t *data, size_t length) { this->delegate_->transfer(data, length); } + + uint8_t transfer_byte(uint8_t data) { return this->delegate_->transfer(data); } + + // the driver will byte-swap if required. + void write_byte16(uint16_t data) { this->delegate_->write16(data); } + + // avoid use of this if possible. It's inefficient and ugly. + void write_array16(const uint16_t *data, size_t length) { this->delegate_->write_array16(data, length); } + + void enable() { this->delegate_->begin_transaction(); } + + void disable() { this->delegate_->end_transaction(); } + + void write_array(const uint8_t *data, size_t length) { this->delegate_->write_array(data, length); } + template void write_array(const std::array &data) { this->write_array(data.data(), N); } void write_array(const std::vector &data) { this->write_array(data.data(), data.size()); } - uint8_t transfer_byte(uint8_t data) { - return this->parent_->template transfer_byte(data); - } - - void transfer_array(uint8_t *data, size_t length) { - this->parent_->template transfer_array(data, length); - } - template void transfer_array(std::array &data) { this->transfer_array(data.data(), N); } - - protected: - SPIComponent *parent_{nullptr}; - GPIOPin *cs_{nullptr}; }; } // namespace spi diff --git a/esphome/components/spi/spi_arduino.cpp b/esphome/components/spi/spi_arduino.cpp new file mode 100644 index 0000000000..40ed9e6062 --- /dev/null +++ b/esphome/components/spi/spi_arduino.cpp @@ -0,0 +1,89 @@ +#include "spi.h" +#include + +namespace esphome { +namespace spi { + +#ifdef USE_ARDUINO + +static const char *const TAG = "spi-esp-arduino"; +class SPIDelegateHw : public SPIDelegate { + public: + SPIDelegateHw(SPIInterface channel, uint32_t data_rate, SPIBitOrder bit_order, SPIMode mode, GPIOPin *cs_pin) + : SPIDelegate(data_rate, bit_order, mode, cs_pin), channel_(channel) {} + + void begin_transaction() override { +#ifdef USE_RP2040 + SPISettings const settings(this->data_rate_, static_cast(this->bit_order_), this->mode_); +#else + SPISettings const settings(this->data_rate_, this->bit_order_, this->mode_); +#endif + this->channel_->beginTransaction(settings); + SPIDelegate::begin_transaction(); + } + + void transfer(uint8_t *ptr, size_t length) override { this->channel_->transfer(ptr, length); } + + void end_transaction() override { + this->channel_->endTransaction(); + SPIDelegate::end_transaction(); + } + + uint8_t transfer(uint8_t data) override { return this->channel_->transfer(data); } + + void write16(uint16_t data) override { this->channel_->transfer16(data); } + +#ifdef USE_RP2040 + void write_array(const uint8_t *ptr, size_t length) override { + // avoid overwriting the supplied buffer + uint8_t *rxbuf = new uint8_t[length]; // NOLINT(cppcoreguidelines-owning-memory) + memcpy(rxbuf, ptr, length); + this->channel_->transfer((void *) rxbuf, length); + delete[] rxbuf; // NOLINT(cppcoreguidelines-owning-memory) + } +#else + void write_array(const uint8_t *ptr, size_t length) override { this->channel_->writeBytes(ptr, length); } +#endif + + void read_array(uint8_t *ptr, size_t length) override { this->channel_->transfer(ptr, length); } + + protected: + SPIInterface channel_{}; +}; + +class SPIBusHw : public SPIBus { + public: + SPIBusHw(GPIOPin *clk, GPIOPin *sdo, GPIOPin *sdi, SPIInterface channel) : SPIBus(clk, sdo, sdi), channel_(channel) { +#ifdef USE_ESP8266 + channel->pins(Utility::get_pin_no(clk), Utility::get_pin_no(sdi), Utility::get_pin_no(sdo), -1); + channel->begin(); +#endif // USE_ESP8266 +#ifdef USE_ESP32 + channel->begin(Utility::get_pin_no(clk), Utility::get_pin_no(sdi), Utility::get_pin_no(sdo), -1); +#endif +#ifdef USE_RP2040 + if (Utility::get_pin_no(sdi) != -1) + channel->setRX(Utility::get_pin_no(sdi)); + if (Utility::get_pin_no(sdo) != -1) + channel->setTX(Utility::get_pin_no(sdo)); + channel->setSCK(Utility::get_pin_no(clk)); + channel->begin(); +#endif + } + + SPIDelegate *get_delegate(uint32_t data_rate, SPIBitOrder bit_order, SPIMode mode, GPIOPin *cs_pin) override { + return new SPIDelegateHw(this->channel_, data_rate, bit_order, mode, cs_pin); + } + + protected: + SPIInterface channel_{}; + bool is_hw() override { return true; } +}; + +SPIBus *SPIComponent::get_bus(SPIInterface interface, GPIOPin *clk, GPIOPin *sdo, GPIOPin *sdi) { + return new SPIBusHw(clk, sdo, sdi, interface); +} + +#endif // USE_ARDUINO +} // namespace spi +} // namespace esphome diff --git a/esphome/components/spi/spi_esp_idf.cpp b/esphome/components/spi/spi_esp_idf.cpp new file mode 100644 index 0000000000..f9e4bfcca6 --- /dev/null +++ b/esphome/components/spi/spi_esp_idf.cpp @@ -0,0 +1,163 @@ +#include "spi.h" +#include + +namespace esphome { +namespace spi { + +#ifdef USE_ESP_IDF +static const char *const TAG = "spi-esp-idf"; +static const size_t MAX_TRANSFER_SIZE = 4092; // dictated by ESP-IDF API. + +class SPIDelegateHw : public SPIDelegate { + public: + SPIDelegateHw(SPIInterface channel, uint32_t data_rate, SPIBitOrder bit_order, SPIMode mode, GPIOPin *cs_pin, + bool write_only) + : SPIDelegate(data_rate, bit_order, mode, cs_pin), channel_(channel), write_only_(write_only) { + spi_device_interface_config_t config = {}; + config.mode = static_cast(mode); + config.clock_speed_hz = static_cast(data_rate); + config.spics_io_num = -1; + config.flags = 0; + config.queue_size = 1; + config.pre_cb = nullptr; + config.post_cb = nullptr; + if (bit_order == BIT_ORDER_LSB_FIRST) + config.flags |= SPI_DEVICE_BIT_LSBFIRST; + if (write_only) + config.flags |= SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_NO_DUMMY; + esp_err_t const err = spi_bus_add_device(channel, &config, &this->handle_); + if (err != ESP_OK) + ESP_LOGE(TAG, "Add device failed - err %X", err); + } + + bool is_ready() override { return this->handle_ != nullptr; } + + void begin_transaction() override { + if (this->is_ready()) { + if (spi_device_acquire_bus(this->handle_, portMAX_DELAY) != ESP_OK) + ESP_LOGE(TAG, "Failed to acquire SPI bus"); + SPIDelegate::begin_transaction(); + } else { + ESP_LOGW(TAG, "spi_setup called before initialisation"); + } + } + + void end_transaction() override { + if (this->is_ready()) { + SPIDelegate::end_transaction(); + spi_device_release_bus(this->handle_); + } + } + + ~SPIDelegateHw() override { + esp_err_t const err = spi_bus_remove_device(this->handle_); + if (err != ESP_OK) + ESP_LOGE(TAG, "Remove device failed - err %X", err); + } + + // do a transfer. either txbuf or rxbuf (but not both) may be null. + // transfers above the maximum size will be split. + // TODO - make use of the queue for interrupt transfers to provide a (short) pipeline of blocks + // when splitting is required. + void transfer(const uint8_t *txbuf, uint8_t *rxbuf, size_t length) override { + if (rxbuf != nullptr && this->write_only_) { + ESP_LOGE(TAG, "Attempted read from write-only channel"); + return; + } + spi_transaction_t desc = {}; + desc.flags = 0; + while (length != 0) { + size_t const partial = std::min(length, MAX_TRANSFER_SIZE); + desc.length = partial * 8; + desc.rxlength = this->write_only_ ? 0 : partial * 8; + desc.tx_buffer = txbuf; + desc.rx_buffer = rxbuf; + esp_err_t const err = spi_device_transmit(this->handle_, &desc); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Transmit failed - err %X", err); + break; + } + length -= partial; + if (txbuf != nullptr) + txbuf += partial; + if (rxbuf != nullptr) + rxbuf += partial; + } + } + + void transfer(uint8_t *ptr, size_t length) override { this->transfer(ptr, ptr, length); } + + uint8_t transfer(uint8_t data) override { + uint8_t rxbuf; + this->transfer(&data, &rxbuf, 1); + return rxbuf; + } + + void write16(uint16_t data) override { + if (this->bit_order_ == BIT_ORDER_MSB_FIRST) { + uint16_t txbuf = SPI_SWAP_DATA_TX(data, 16); + this->transfer((uint8_t *) &txbuf, nullptr, 2); + } else { + this->transfer((uint8_t *) &data, nullptr, 2); + } + } + + void write_array(const uint8_t *ptr, size_t length) override { this->transfer(ptr, nullptr, length); } + + void write_array16(const uint16_t *data, size_t length) override { + if (this->bit_order_ == BIT_ORDER_LSB_FIRST) { + this->write_array((uint8_t *) data, length * 2); + } else { + uint16_t buffer[MAX_TRANSFER_SIZE / 2]; + while (length != 0) { + size_t const partial = std::min(length, MAX_TRANSFER_SIZE / 2); + for (size_t i = 0; i != partial; i++) { + buffer[i] = SPI_SWAP_DATA_TX(*data++, 16); + } + this->write_array((const uint8_t *) buffer, partial * 2); + length -= partial; + } + } + } + + void read_array(uint8_t *ptr, size_t length) override { this->transfer(nullptr, ptr, length); } + + protected: + SPIInterface channel_{}; + spi_device_handle_t handle_{}; + bool write_only_{false}; +}; + +class SPIBusHw : public SPIBus { + public: + SPIBusHw(GPIOPin *clk, GPIOPin *sdo, GPIOPin *sdi, SPIInterface channel) : SPIBus(clk, sdo, sdi), channel_(channel) { + spi_bus_config_t buscfg = {}; + buscfg.mosi_io_num = Utility::get_pin_no(sdo); + buscfg.miso_io_num = Utility::get_pin_no(sdi); + buscfg.sclk_io_num = Utility::get_pin_no(clk); + buscfg.quadwp_io_num = -1; + buscfg.quadhd_io_num = -1; + buscfg.max_transfer_sz = MAX_TRANSFER_SIZE; + auto err = spi_bus_initialize(channel, &buscfg, SPI_DMA_CH_AUTO); + if (err != ESP_OK) + ESP_LOGE(TAG, "Bus init failed - err %X", err); + } + + SPIDelegate *get_delegate(uint32_t data_rate, SPIBitOrder bit_order, SPIMode mode, GPIOPin *cs_pin) override { + return new SPIDelegateHw(this->channel_, data_rate, bit_order, mode, cs_pin, + Utility::get_pin_no(this->sdi_pin_) == -1); + } + + protected: + SPIInterface channel_{}; + + bool is_hw() override { return true; } +}; + +SPIBus *SPIComponent::get_bus(SPIInterface interface, GPIOPin *clk, GPIOPin *sdo, GPIOPin *sdi) { + return new SPIBusHw(clk, sdo, sdi, interface); +} + +#endif +} // namespace spi +} // namespace esphome diff --git a/esphome/components/spi_device/__init__.py b/esphome/components/spi_device/__init__.py new file mode 100644 index 0000000000..428b5bfbda --- /dev/null +++ b/esphome/components/spi_device/__init__.py @@ -0,0 +1,49 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import spi +from esphome.const import CONF_ID, CONF_DATA_RATE, CONF_MODE + +DEPENDENCIES = ["spi"] +CODEOWNERS = ["@clydebarrow"] + +MULTI_CONF = True +spi_device_ns = cg.esphome_ns.namespace("spi_device") + +spi_device = spi_device_ns.class_("SPIDeviceComponent", cg.Component, spi.SPIDevice) + +Mode = spi.spi_ns.enum("SPIMode") +MODES = { + "0": Mode.MODE0, + "1": Mode.MODE1, + "2": Mode.MODE2, + "3": Mode.MODE3, + "MODE0": Mode.MODE0, + "MODE1": Mode.MODE1, + "MODE2": Mode.MODE2, + "MODE3": Mode.MODE3, +} + +BitOrder = spi.spi_ns.enum("SPIBitOrder") +ORDERS = { + "msb_first": BitOrder.BIT_ORDER_MSB_FIRST, + "lsb_first": BitOrder.BIT_ORDER_LSB_FIRST, +} +CONF_BIT_ORDER = "bit_order" + +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(CONF_ID): cv.declare_id(spi_device), + cv.Optional(CONF_DATA_RATE, default="1MHz"): spi.SPI_DATA_RATE_SCHEMA, + cv.Optional(CONF_BIT_ORDER, default="msb_first"): cv.enum(ORDERS, lower=True), + cv.Optional(CONF_MODE, default="0"): cv.enum(MODES, upper=True), + } +).extend(spi.spi_device_schema(False)) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, config) + cg.add(var.set_data_rate(config[CONF_DATA_RATE])) + cg.add(var.set_mode(config[CONF_MODE])) + cg.add(var.set_bit_order(config[CONF_BIT_ORDER])) + await spi.register_spi_device(var, config) diff --git a/esphome/components/spi_device/spi_device.cpp b/esphome/components/spi_device/spi_device.cpp new file mode 100644 index 0000000000..4e0b72ae60 --- /dev/null +++ b/esphome/components/spi_device/spi_device.cpp @@ -0,0 +1,30 @@ +#include "spi_device.h" +#include "esphome/core/log.h" +#include "esphome/core/hal.h" + +namespace esphome { +namespace spi_device { + +static const char *const TAG = "spi_device"; + +void SPIDeviceComponent::setup() { + ESP_LOGD(TAG, "Setting up SPIDevice..."); + this->spi_setup(); + ESP_LOGCONFIG(TAG, "SPIDevice started!"); +} + +void SPIDeviceComponent::dump_config() { + ESP_LOGCONFIG(TAG, "SPIDevice"); + LOG_PIN(" CS pin: ", this->cs_); + ESP_LOGCONFIG(TAG, " Mode: %d", this->mode_); + if (this->data_rate_ < 1000000) { + ESP_LOGCONFIG(TAG, " Data rate: %dkHz", this->data_rate_ / 1000); + } else { + ESP_LOGCONFIG(TAG, " Data rate: %dMHz", this->data_rate_ / 1000000); + } +} + +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 new file mode 100644 index 0000000000..d8aef440a7 --- /dev/null +++ b/esphome/components/spi_device/spi_device.h @@ -0,0 +1,22 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/components/spi/spi.h" + +namespace esphome { +namespace spi_device { + +class SPIDeviceComponent : public Component, + public spi::SPIDevice { + public: + void setup() override; + void dump_config() override; + + float get_setup_priority() const override; + + protected: +}; + +} // namespace spi_device +} // namespace esphome diff --git a/tests/test4.yaml b/tests/test4.yaml index 1175bb207c..341e613785 100644 --- a/tests/test4.yaml +++ b/tests/test4.yaml @@ -32,6 +32,7 @@ spi: clk_pin: GPIO21 mosi_pin: GPIO22 miso_pin: GPIO23 + interface: hardware uart: - id: uart115200 diff --git a/tests/test8.yaml b/tests/test8.yaml index 28c6e78b87..498da94483 100644 --- a/tests/test8.yaml +++ b/tests/test8.yaml @@ -31,8 +31,17 @@ light: restore_mode: ALWAYS_OFF spi: + id: spi_id_1 clk_pin: GPIO7 mosi_pin: GPIO6 + interface: any + +spi_device: + id: spidev + data_rate: 2MHz + spi_id: spi_id_1 + mode: 3 + bit_order: lsb_first display: - platform: ili9xxx From b19a7e006efda8c40010ccd381976577b3f00c0c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 9 Sep 2023 08:57:10 +1200 Subject: [PATCH 0155/2101] Bump actions/cache from 3.3.1 to 3.3.2 (#5367) Bumps [actions/cache](https://github.com/actions/cache) from 3.3.1 to 3.3.2. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v3.3.1...v3.3.2) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1de5822960..4214bc2c5d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,7 +41,7 @@ jobs: python-version: ${{ env.DEFAULT_PYTHON }} - name: Restore Python virtual environment id: cache-venv - uses: actions/cache@v3.3.1 + uses: actions/cache@v3.3.2 with: path: venv # yamllint disable-line rule:line-length @@ -298,7 +298,7 @@ jobs: python-version: ${{ env.DEFAULT_PYTHON }} cache-key: ${{ needs.common.outputs.cache-key }} - name: Cache platformio - uses: actions/cache@v3.3.1 + uses: actions/cache@v3.3.2 with: path: ~/.platformio # yamllint disable-line rule:line-length From 2fd6942de4bef6d2bc2fa556ec942ef558201379 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 9 Sep 2023 08:57:35 +1200 Subject: [PATCH 0156/2101] Bump zeroconf from 0.88.0 to 0.102.0 (#5368) Bumps [zeroconf](https://github.com/python-zeroconf/python-zeroconf) from 0.88.0 to 0.102.0. - [Release notes](https://github.com/python-zeroconf/python-zeroconf/releases) - [Changelog](https://github.com/python-zeroconf/python-zeroconf/blob/master/CHANGELOG.md) - [Commits](https://github.com/python-zeroconf/python-zeroconf/compare/0.88.0...0.102.0) --- updated-dependencies: - dependency-name: zeroconf dependency-type: direct:production update-type: version-update:semver-minor ... 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 dcb7420d3f..9bce4a309d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,7 +11,7 @@ esptool==4.6.2 click==8.1.7 esphome-dashboard==20230904.0 aioesphomeapi==15.0.0 -zeroconf==0.88.0 +zeroconf==0.102.0 # esp-idf requires this, but doesn't bundle it by default # https://github.com/espressif/esp-idf/blob/220590d599e134d7a5e7f1e683cc4550349ffbf8/requirements.txt#L24 From d9523a0cbf556c3483d546ce42da808345af01f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20S=C3=A1rk=C3=B6zi?= Date: Fri, 8 Sep 2023 23:10:20 +0200 Subject: [PATCH 0157/2101] Fix repeat.count = 0 case (#5364) * Only play first action if count is non-zero * Add test to yaml * Update test5.yaml --- esphome/core/base_automation.h | 6 +++++- tests/test5.yaml | 7 +++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/esphome/core/base_automation.h b/esphome/core/base_automation.h index daa09b912e..a17b6a6f85 100644 --- a/esphome/core/base_automation.h +++ b/esphome/core/base_automation.h @@ -249,7 +249,11 @@ template class RepeatAction : public Action { void play_complex(Ts... x) override { this->num_running_++; this->var_ = std::make_tuple(x...); - this->then_.play(0, x...); + if (this->count_.value(x...) > 0) { + this->then_.play(0, x...); + } else { + this->play_next_tuple_(this->var_); + } } void play(Ts... x) override { /* ignore - see play_complex */ diff --git a/tests/test5.yaml b/tests/test5.yaml index a1cc3103d7..417f3bfecd 100644 --- a/tests/test5.yaml +++ b/tests/test5.yaml @@ -563,6 +563,13 @@ script: then: - logger.log: looping! + - id: zero_repeat_test + then: + - repeat: + count: !lambda "return 0;" + then: + - logger.log: shouldn't see mee! + switch: - platform: modbus_controller modbus_controller_id: modbus_controller_test From 9cf115a7526a51b8e951586f8b4488784afcf41c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Fri, 8 Sep 2023 23:20:26 +0200 Subject: [PATCH 0158/2101] Fix dashboard download for ESP32 variants (#5355) --- esphome/dashboard/dashboard.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/esphome/dashboard/dashboard.py b/esphome/dashboard/dashboard.py index 0d6ec8dc13..cacd5e2db0 100644 --- a/esphome/dashboard/dashboard.py +++ b/esphome/dashboard/dashboard.py @@ -540,7 +540,10 @@ class DownloadListRequestHandler(BaseHandler): self.send_error(404) return - from esphome.components.esp32 import get_download_types as esp32_types + from esphome.components.esp32 import ( + get_download_types as esp32_types, + VARIANTS as ESP32_VARIANTS, + ) from esphome.components.esp8266 import get_download_types as esp8266_types from esphome.components.rp2040 import get_download_types as rp2040_types from esphome.components.libretiny import get_download_types as libretiny_types @@ -551,7 +554,7 @@ class DownloadListRequestHandler(BaseHandler): downloads = rp2040_types(storage_json) elif platform == const.PLATFORM_ESP8266: downloads = esp8266_types(storage_json) - elif platform == const.PLATFORM_ESP32: + elif platform.upper() in ESP32_VARIANTS: downloads = esp32_types(storage_json) elif platform == const.PLATFORM_BK72XX: downloads = libretiny_types(storage_json) From ccc30116ba5c31af3e2e71e1338c579e66433005 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 9 Sep 2023 09:20:54 +1200 Subject: [PATCH 0159/2101] Bump pytest from 7.4.1 to 7.4.2 (#5357) Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.4.1 to 7.4.2. - [Release notes](https://github.com/pytest-dev/pytest/releases) - [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest/compare/7.4.1...7.4.2) --- updated-dependencies: - dependency-name: pytest dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] 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 2d46d3dccd..f17ccd220d 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -5,7 +5,7 @@ pyupgrade==3.10.1 # also change in .pre-commit-config.yaml when updating pre-commit # Unit tests -pytest==7.4.1 +pytest==7.4.2 pytest-cov==4.1.0 pytest-mock==3.11.1 pytest-asyncio==0.21.1 From 7bb67ae94b0399467a4f9752b5111b1c613f2643 Mon Sep 17 00:00:00 2001 From: Ilia Sotnikov Date: Sat, 9 Sep 2023 12:00:45 +0300 Subject: [PATCH 0160/2101] [ADC] Support measuring VCC on Raspberry Pico (W) (#5335) * [ADC] Support measuring VCC on Raspberry Pico (W) Added support for measuring VCC on Raspberry Pico (W) with ADC. GPIO pin is provided as `VCC`, same as with ESP8266. VSYS is the voltage being actually processed, and might have an offset from actual power supply voltage (e.g. USB on VBUS) due to voltage drop on Schottky diode between VSYS and VBUS on Rasberry Pico. The offset has experimentally been found to be ~0.25V on Pico W and ~0.1 on Pico, presumably due to different power consumption. Example usage: sensor: - platform: adc pin: VCC name: "VSYS" * + Added tests for VCC measuring on `rpipicow` board --- esphome/components/adc/__init__.py | 6 +++- esphome/components/adc/adc_sensor.cpp | 40 +++++++++++++++++++++++++-- tests/test6.yaml | 3 ++ 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/esphome/components/adc/__init__.py b/esphome/components/adc/__init__.py index ba72951777..0b6ee145f2 100644 --- a/esphome/components/adc/__init__.py +++ b/esphome/components/adc/__init__.py @@ -5,6 +5,10 @@ from esphome.const import CONF_ANALOG, CONF_INPUT from esphome.core import CORE from esphome.components.esp32 import get_esp32_variant +from esphome.const import ( + PLATFORM_ESP8266, + PLATFORM_RP2040, +) from esphome.components.esp32.const import ( VARIANT_ESP32, VARIANT_ESP32C2, @@ -143,7 +147,7 @@ ESP32_VARIANT_ADC2_PIN_TO_CHANNEL = { def validate_adc_pin(value): if str(value).upper() == "VCC": - return cv.only_on_esp8266("VCC") + return cv.only_on([PLATFORM_ESP8266, PLATFORM_RP2040])("VCC") if str(value).upper() == "TEMPERATURE": return cv.only_on_rp2040("TEMPERATURE") diff --git a/esphome/components/adc/adc_sensor.cpp b/esphome/components/adc/adc_sensor.cpp index 0642cd7f3f..e69e6b9313 100644 --- a/esphome/components/adc/adc_sensor.cpp +++ b/esphome/components/adc/adc_sensor.cpp @@ -12,6 +12,9 @@ ADC_MODE(ADC_VCC) #endif #ifdef USE_RP2040 +#ifdef CYW43_USES_VSYS_PIN +#include "pico/cyw43_arch.h" +#endif #include #endif @@ -123,13 +126,19 @@ void ADCSensor::dump_config() { } } #endif // USE_ESP32 + #ifdef USE_RP2040 if (this->is_temperature_) { ESP_LOGCONFIG(TAG, " Pin: Temperature"); } else { +#ifdef USE_ADC_SENSOR_VCC + ESP_LOGCONFIG(TAG, " Pin: VCC"); +#else LOG_PIN(" Pin: ", pin_); +#endif // USE_ADC_SENSOR_VCC } -#endif +#endif // USE_RP2040 + LOG_UPDATE_INTERVAL(this); } @@ -238,7 +247,20 @@ float ADCSensor::sample() { delay(1); adc_select_input(4); } else { - uint8_t pin = this->pin_->get_pin(); + uint8_t pin; +#ifdef USE_ADC_SENSOR_VCC +#ifdef CYW43_USES_VSYS_PIN + // Measuring VSYS on Raspberry Pico W needs to be wrapped with + // `cyw43_thread_enter()`/`cyw43_thread_exit()` as discussed in + // https://github.com/raspberrypi/pico-sdk/issues/1222, since Wifi chip and + // VSYS ADC both share GPIO29 + cyw43_thread_enter(); +#endif // CYW43_USES_VSYS_PIN + pin = PICO_VSYS_PIN; +#else + pin = this->pin_->get_pin(); +#endif // USE_ADC_SENSOR_VCC + adc_gpio_init(pin); adc_select_input(pin - 26); } @@ -246,11 +268,23 @@ float ADCSensor::sample() { int32_t raw = adc_read(); if (this->is_temperature_) { adc_set_temp_sensor_enabled(false); + } else { +#ifdef USE_ADC_SENSOR_VCC +#ifdef CYW43_USES_VSYS_PIN + cyw43_thread_exit(); +#endif // CYW43_USES_VSYS_PIN +#endif // USE_ADC_SENSOR_VCC } + if (output_raw_) { return raw; } - return raw * 3.3f / 4096.0f; + float coeff = 1.0; +#ifdef USE_ADC_SENSOR_VCC + // As per Raspberry Pico (W) datasheet (section 2.1) the VSYS/3 is measured + coeff = 3.0; +#endif // USE_ADC_SENSOR_VCC + return raw * 3.3f / 4096.0f * coeff; } #endif diff --git a/tests/test6.yaml b/tests/test6.yaml index f048a4fa14..3d6a1ceb1f 100644 --- a/tests/test6.yaml +++ b/tests/test6.yaml @@ -62,3 +62,6 @@ switch: sensor: - platform: internal_temperature name: Internal Temperature + - platform: adc + pin: VCC + name: VSYS From 0c84224ca265c483db4de784061062f7e80d3852 Mon Sep 17 00:00:00 2001 From: "Kevin P. Fleming" Date: Sat, 9 Sep 2023 19:19:54 -0400 Subject: [PATCH 0161/2101] Move CONF_PHASE_A/B/C constants to const.py. (#5304) --- esphome/components/atm90e32/sensor.py | 7 +++---- esphome/components/growatt_solar/sensor.py | 7 +++---- esphome/components/havells_solar/sensor.py | 6 +++--- esphome/const.py | 3 +++ 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/esphome/components/atm90e32/sensor.py b/esphome/components/atm90e32/sensor.py index 6cc0f6ac3e..af4d2ef412 100644 --- a/esphome/components/atm90e32/sensor.py +++ b/esphome/components/atm90e32/sensor.py @@ -6,6 +6,9 @@ from esphome.const import ( CONF_REACTIVE_POWER, CONF_VOLTAGE, CONF_CURRENT, + CONF_PHASE_A, + CONF_PHASE_B, + CONF_PHASE_C, CONF_POWER, CONF_POWER_FACTOR, CONF_FREQUENCY, @@ -31,10 +34,6 @@ from esphome.const import ( UNIT_WATT_HOURS, ) -CONF_PHASE_A = "phase_a" -CONF_PHASE_B = "phase_b" -CONF_PHASE_C = "phase_c" - CONF_LINE_FREQUENCY = "line_frequency" CONF_CHIP_TEMPERATURE = "chip_temperature" CONF_GAIN_PGA = "gain_pga" diff --git a/esphome/components/growatt_solar/sensor.py b/esphome/components/growatt_solar/sensor.py index f95d679c3e..0db15ae53e 100644 --- a/esphome/components/growatt_solar/sensor.py +++ b/esphome/components/growatt_solar/sensor.py @@ -6,6 +6,9 @@ from esphome.const import ( CONF_CURRENT, CONF_FREQUENCY, CONF_ID, + CONF_PHASE_A, + CONF_PHASE_B, + CONF_PHASE_C, CONF_VOLTAGE, DEVICE_CLASS_CURRENT, DEVICE_CLASS_ENERGY, @@ -21,10 +24,6 @@ from esphome.const import ( UNIT_WATT, ) -CONF_PHASE_A = "phase_a" -CONF_PHASE_B = "phase_b" -CONF_PHASE_C = "phase_c" - CONF_ENERGY_PRODUCTION_DAY = "energy_production_day" CONF_TOTAL_ENERGY_PRODUCTION = "total_energy_production" CONF_TOTAL_GENERATION_TIME = "total_generation_time" diff --git a/esphome/components/havells_solar/sensor.py b/esphome/components/havells_solar/sensor.py index d7c8d544f9..66b72f9e3e 100644 --- a/esphome/components/havells_solar/sensor.py +++ b/esphome/components/havells_solar/sensor.py @@ -6,6 +6,9 @@ from esphome.const import ( CONF_CURRENT, CONF_FREQUENCY, CONF_ID, + CONF_PHASE_A, + CONF_PHASE_B, + CONF_PHASE_C, CONF_REACTIVE_POWER, CONF_VOLTAGE, DEVICE_CLASS_CURRENT, @@ -24,9 +27,6 @@ from esphome.const import ( UNIT_WATT, ) -CONF_PHASE_A = "phase_a" -CONF_PHASE_B = "phase_b" -CONF_PHASE_C = "phase_c" CONF_ENERGY_PRODUCTION_DAY = "energy_production_day" CONF_TOTAL_ENERGY_PRODUCTION = "total_energy_production" CONF_TOTAL_GENERATION_TIME = "total_generation_time" diff --git a/esphome/const.py b/esphome/const.py index 067fd23946..0e4e880c19 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -538,8 +538,11 @@ CONF_PAYLOAD_AVAILABLE = "payload_available" CONF_PAYLOAD_NOT_AVAILABLE = "payload_not_available" CONF_PERIOD = "period" CONF_PH = "ph" +CONF_PHASE_A = "phase_a" CONF_PHASE_ANGLE = "phase_angle" +CONF_PHASE_B = "phase_b" CONF_PHASE_BALANCER = "phase_balancer" +CONF_PHASE_C = "phase_c" CONF_PIN = "pin" CONF_PIN_A = "pin_a" CONF_PIN_B = "pin_b" From e66047e07212aa214542949da68049c914901d6a Mon Sep 17 00:00:00 2001 From: Flaviu Tamas Date: Sat, 9 Sep 2023 22:25:09 -0400 Subject: [PATCH 0162/2101] Add BMI160 support (#5143) * Add BMI160 support * BMI160: use set_timeout for delay * Add support for old compilers Fix "warning: missing terminating ' character" * Increase power-on delay to be more conservative * Add helper for reading little-endian data over i2c * Replace configuration names with globals Note: for testing with external components, you will need to comment out the import & define your own CONF_GYROSCOPE_X, etc, in this file * Improve icons * Fix tests & lint --- CODEOWNERS | 1 + esphome/components/bmi160/__init__.py | 1 + esphome/components/bmi160/bmi160.cpp | 270 ++++++++++++++++++++++++++ esphome/components/bmi160/bmi160.h | 44 +++++ esphome/components/bmi160/sensor.py | 102 ++++++++++ esphome/const.py | 6 + tests/test1.yaml | 17 ++ 7 files changed, 441 insertions(+) create mode 100644 esphome/components/bmi160/__init__.py create mode 100644 esphome/components/bmi160/bmi160.cpp create mode 100644 esphome/components/bmi160/bmi160.h create mode 100644 esphome/components/bmi160/sensor.py diff --git a/CODEOWNERS b/CODEOWNERS index ab4c5011f6..2658aebdc7 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -49,6 +49,7 @@ esphome/components/bl0942/* @dbuezas esphome/components/ble_client/* @buxtronix esphome/components/bluetooth_proxy/* @jesserockz esphome/components/bme680_bsec/* @trvrnrth +esphome/components/bmi160/* @flaviut esphome/components/bmp3xx/* @martgras esphome/components/bmp581/* @kahrendt esphome/components/bp1658cj/* @Cossid diff --git a/esphome/components/bmi160/__init__.py b/esphome/components/bmi160/__init__.py new file mode 100644 index 0000000000..49b6d0252a --- /dev/null +++ b/esphome/components/bmi160/__init__.py @@ -0,0 +1 @@ +CODEOWNERS = ["@flaviut"] diff --git a/esphome/components/bmi160/bmi160.cpp b/esphome/components/bmi160/bmi160.cpp new file mode 100644 index 0000000000..69b4694345 --- /dev/null +++ b/esphome/components/bmi160/bmi160.cpp @@ -0,0 +1,270 @@ +#include "bmi160.h" +#include "esphome/core/hal.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace bmi160 { + +static const char *const TAG = "bmi160"; + +const uint8_t BMI160_REGISTER_CHIPID = 0x00; + +const uint8_t BMI160_REGISTER_CMD = 0x7E; +enum class Cmd : uint8_t { + START_FOC = 0x03, + ACCL_SET_PMU_MODE = 0b00010000, // last 2 bits are mode + GYRO_SET_PMU_MODE = 0b00010100, // last 2 bits are mode + MAG_SET_PMU_MODE = 0b00011000, // last 2 bits are mode + PROG_NVM = 0xA0, + FIFO_FLUSH = 0xB0, + INT_RESET = 0xB1, + SOFT_RESET = 0xB6, + STEP_CNT_CLR = 0xB2, +}; +enum class GyroPmuMode : uint8_t { + SUSPEND = 0b00, + NORMAL = 0b01, + LOW_POWER = 0b10, +}; +enum class AcclPmuMode : uint8_t { + SUSPEND = 0b00, + NORMAL = 0b01, + FAST_STARTUP = 0b11, +}; +enum class MagPmuMode : uint8_t { + SUSPEND = 0b00, + NORMAL = 0b01, + LOW_POWER = 0b10, +}; + +const uint8_t BMI160_REGISTER_ACCEL_CONFIG = 0x40; +enum class AcclFilterMode : uint8_t { + POWER_SAVING = 0b00000000, + PERF = 0b10000000, +}; +enum class AcclBandwidth : uint8_t { + OSR4_AVG1 = 0b00000000, + OSR2_AVG2 = 0b00010000, + NORMAL_AVG4 = 0b00100000, + RES_AVG8 = 0b00110000, + RES_AVG16 = 0b01000000, + RES_AVG32 = 0b01010000, + RES_AVG64 = 0b01100000, + RES_AVG128 = 0b01110000, +}; +enum class AccelOutputDataRate : uint8_t { + HZ_25_32 = 0b0001, // 25/32 Hz + HZ_25_16 = 0b0010, // 25/16 Hz + HZ_25_8 = 0b0011, // 25/8 Hz + HZ_25_4 = 0b0100, // 25/4 Hz + HZ_25_2 = 0b0101, // 25/2 Hz + HZ_25 = 0b0110, // 25 Hz + HZ_50 = 0b0111, // 50 Hz + HZ_100 = 0b1000, // 100 Hz + HZ_200 = 0b1001, // 200 Hz + HZ_400 = 0b1010, // 400 Hz + HZ_800 = 0b1011, // 800 Hz + HZ_1600 = 0b1100, // 1600 Hz +}; +const uint8_t BMI160_REGISTER_ACCEL_RANGE = 0x41; +enum class AccelRange : uint8_t { + RANGE_2G = 0b0011, + RANGE_4G = 0b0101, + RANGE_8G = 0b1000, + RANGE_16G = 0b1100, +}; + +const uint8_t BMI160_REGISTER_GYRO_CONFIG = 0x42; +enum class GyroBandwidth : uint8_t { + OSR4 = 0x00, + OSR2 = 0x10, + NORMAL = 0x20, +}; +enum class GyroOuputDataRate : uint8_t { + HZ_25 = 0x06, + HZ_50 = 0x07, + HZ_100 = 0x08, + HZ_200 = 0x09, + HZ_400 = 0x0A, + HZ_800 = 0x0B, + HZ_1600 = 0x0C, + HZ_3200 = 0x0D, +}; +const uint8_t BMI160_REGISTER_GYRO_RANGE = 0x43; +enum class GyroRange : uint8_t { + RANGE_2000_DPS = 0x0, // ±2000 °/s + RANGE_1000_DPS = 0x1, + RANGE_500_DPS = 0x2, + RANGE_250_DPS = 0x3, + RANGE_125_DPS = 0x4, +}; + +const uint8_t BMI160_REGISTER_DATA_GYRO_X_LSB = 0x0C; +const uint8_t BMI160_REGISTER_DATA_GYRO_X_MSB = 0x0D; +const uint8_t BMI160_REGISTER_DATA_GYRO_Y_LSB = 0x0E; +const uint8_t BMI160_REGISTER_DATA_GYRO_Y_MSB = 0x0F; +const uint8_t BMI160_REGISTER_DATA_GYRO_Z_LSB = 0x10; +const uint8_t BMI160_REGISTER_DATA_GYRO_Z_MSB = 0x11; +const uint8_t BMI160_REGISTER_DATA_ACCEL_X_LSB = 0x12; +const uint8_t BMI160_REGISTER_DATA_ACCEL_X_MSB = 0x13; +const uint8_t BMI160_REGISTER_DATA_ACCEL_Y_LSB = 0x14; +const uint8_t BMI160_REGISTER_DATA_ACCEL_Y_MSB = 0x15; +const uint8_t BMI160_REGISTER_DATA_ACCEL_Z_LSB = 0x16; +const uint8_t BMI160_REGISTER_DATA_ACCEL_Z_MSB = 0x17; +const uint8_t BMI160_REGISTER_DATA_TEMP_LSB = 0x20; +const uint8_t BMI160_REGISTER_DATA_TEMP_MSB = 0x21; + +const float GRAVITY_EARTH = 9.80665f; + +void BMI160Component::internal_setup_(int stage) { + switch (stage) { + case 0: + ESP_LOGCONFIG(TAG, "Setting up BMI160..."); + uint8_t chipid; + if (!this->read_byte(BMI160_REGISTER_CHIPID, &chipid) || (chipid != 0b11010001)) { + this->mark_failed(); + return; + } + + ESP_LOGV(TAG, " Bringing accelerometer out of sleep..."); + if (!this->write_byte(BMI160_REGISTER_CMD, (uint8_t) Cmd::ACCL_SET_PMU_MODE | (uint8_t) AcclPmuMode::NORMAL)) { + this->mark_failed(); + return; + } + ESP_LOGV(TAG, " Waiting for accelerometer to wake up..."); + // need to wait (max delay in datasheet) because we can't send commands while another is in progress + // min 5ms, 10ms + this->set_timeout(10, [this]() { this->internal_setup_(1); }); + break; + + case 1: + ESP_LOGV(TAG, " Bringing gyroscope out of sleep..."); + if (!this->write_byte(BMI160_REGISTER_CMD, (uint8_t) Cmd::GYRO_SET_PMU_MODE | (uint8_t) GyroPmuMode::NORMAL)) { + this->mark_failed(); + return; + } + 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); }); + break; + + case 2: + ESP_LOGV(TAG, " Setting up Gyro Config..."); + uint8_t gyro_config = (uint8_t) GyroBandwidth::OSR4 | (uint8_t) GyroOuputDataRate::HZ_25; + ESP_LOGV(TAG, " Output gyro_config: 0b" BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(gyro_config)); + if (!this->write_byte(BMI160_REGISTER_GYRO_CONFIG, gyro_config)) { + this->mark_failed(); + return; + } + ESP_LOGV(TAG, " Setting up Gyro Range..."); + uint8_t gyro_range = (uint8_t) GyroRange::RANGE_2000_DPS; + ESP_LOGV(TAG, " Output gyro_range: 0b" BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(gyro_range)); + if (!this->write_byte(BMI160_REGISTER_GYRO_RANGE, gyro_range)) { + this->mark_failed(); + return; + } + + ESP_LOGV(TAG, " Setting up Accel Config..."); + uint8_t accel_config = + (uint8_t) AcclFilterMode::PERF | (uint8_t) AcclBandwidth::RES_AVG16 | (uint8_t) AccelOutputDataRate::HZ_25; + ESP_LOGV(TAG, " Output accel_config: 0b" BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(accel_config)); + if (!this->write_byte(BMI160_REGISTER_ACCEL_CONFIG, accel_config)) { + this->mark_failed(); + return; + } + ESP_LOGV(TAG, " Setting up Accel Range..."); + uint8_t accel_range = (uint8_t) AccelRange::RANGE_16G; + ESP_LOGV(TAG, " Output accel_range: 0b" BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(accel_range)); + if (!this->write_byte(BMI160_REGISTER_ACCEL_RANGE, accel_range)) { + this->mark_failed(); + return; + } + + this->setup_complete_ = true; + } +} + +void BMI160Component::setup() { this->internal_setup_(0); } +void BMI160Component::dump_config() { + ESP_LOGCONFIG(TAG, "BMI160:"); + LOG_I2C_DEVICE(this); + if (this->is_failed()) { + ESP_LOGE(TAG, "Communication with BMI160 failed!"); + } + LOG_UPDATE_INTERVAL(this); + LOG_SENSOR(" ", "Acceleration X", this->accel_x_sensor_); + LOG_SENSOR(" ", "Acceleration Y", this->accel_y_sensor_); + LOG_SENSOR(" ", "Acceleration Z", this->accel_z_sensor_); + LOG_SENSOR(" ", "Gyro X", this->gyro_x_sensor_); + LOG_SENSOR(" ", "Gyro Y", this->gyro_y_sensor_); + LOG_SENSOR(" ", "Gyro Z", this->gyro_z_sensor_); + LOG_SENSOR(" ", "Temperature", this->temperature_sensor_); +} + +i2c::ErrorCode BMI160Component::read_le_int16_(uint8_t reg, int16_t *value, uint8_t len) { + uint8_t raw_data[len * 2]; + // read using read_register because we have little-endian data, and read_bytes_16 will swap it + i2c::ErrorCode err = this->read_register(reg, raw_data, len * 2, true); + if (err != i2c::ERROR_OK) { + return err; + } + for (int i = 0; i < len; i++) { + value[i] = (int16_t) ((uint16_t) raw_data[i * 2] | ((uint16_t) raw_data[i * 2 + 1] << 8)); + } + return err; +} + +void BMI160Component::update() { + if (!this->setup_complete_) { + return; + } + + ESP_LOGV(TAG, " Updating BMI160..."); + int16_t data[6]; + if (this->read_le_int16_(BMI160_REGISTER_DATA_GYRO_X_LSB, data, 6) != i2c::ERROR_OK) { + this->status_set_warning(); + return; + } + + float gyro_x = (float) data[0] / (float) INT16_MAX * 2000.f; + float gyro_y = (float) data[1] / (float) INT16_MAX * 2000.f; + float gyro_z = (float) data[2] / (float) INT16_MAX * 2000.f; + float accel_x = (float) data[3] / (float) INT16_MAX * 16 * GRAVITY_EARTH; + float accel_y = (float) data[4] / (float) INT16_MAX * 16 * GRAVITY_EARTH; + float accel_z = (float) data[5] / (float) INT16_MAX * 16 * GRAVITY_EARTH; + + int16_t raw_temperature; + if (this->read_le_int16_(BMI160_REGISTER_DATA_TEMP_LSB, &raw_temperature, 1) != i2c::ERROR_OK) { + this->status_set_warning(); + return; + } + float temperature = (float) raw_temperature / (float) INT16_MAX * 64.5f + 23.f; + + ESP_LOGD(TAG, + "Got accel={x=%.3f m/s², y=%.3f m/s², z=%.3f m/s²}, " + "gyro={x=%.3f °/s, y=%.3f °/s, z=%.3f °/s}, temp=%.3f°C", + accel_x, accel_y, accel_z, gyro_x, gyro_y, gyro_z, temperature); + + if (this->accel_x_sensor_ != nullptr) + this->accel_x_sensor_->publish_state(accel_x); + if (this->accel_y_sensor_ != nullptr) + this->accel_y_sensor_->publish_state(accel_y); + if (this->accel_z_sensor_ != nullptr) + this->accel_z_sensor_->publish_state(accel_z); + + if (this->temperature_sensor_ != nullptr) + this->temperature_sensor_->publish_state(temperature); + + if (this->gyro_x_sensor_ != nullptr) + this->gyro_x_sensor_->publish_state(gyro_x); + if (this->gyro_y_sensor_ != nullptr) + this->gyro_y_sensor_->publish_state(gyro_y); + if (this->gyro_z_sensor_ != nullptr) + this->gyro_z_sensor_->publish_state(gyro_z); + + 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 new file mode 100644 index 0000000000..47691a4de9 --- /dev/null +++ b/esphome/components/bmi160/bmi160.h @@ -0,0 +1,44 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/components/sensor/sensor.h" +#include "esphome/components/i2c/i2c.h" + +namespace esphome { +namespace bmi160 { + +class BMI160Component : public PollingComponent, public i2c::I2CDevice { + public: + void setup() override; + void dump_config() override; + + 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; } + void set_temperature_sensor(sensor::Sensor *temperature_sensor) { temperature_sensor_ = temperature_sensor; } + void set_gyro_x_sensor(sensor::Sensor *gyro_x_sensor) { gyro_x_sensor_ = gyro_x_sensor; } + void set_gyro_y_sensor(sensor::Sensor *gyro_y_sensor) { gyro_y_sensor_ = gyro_y_sensor; } + void set_gyro_z_sensor(sensor::Sensor *gyro_z_sensor) { gyro_z_sensor_ = gyro_z_sensor; } + + protected: + sensor::Sensor *accel_x_sensor_{nullptr}; + sensor::Sensor *accel_y_sensor_{nullptr}; + sensor::Sensor *accel_z_sensor_{nullptr}; + sensor::Sensor *temperature_sensor_{nullptr}; + sensor::Sensor *gyro_x_sensor_{nullptr}; + sensor::Sensor *gyro_y_sensor_{nullptr}; + sensor::Sensor *gyro_z_sensor_{nullptr}; + + void internal_setup_(int stage); + bool setup_complete_{false}; + + /** reads `len` 16-bit little-endian integers from the given i2c register */ + i2c::ErrorCode read_le_int16_(uint8_t reg, int16_t *value, uint8_t len); +}; + +} // namespace bmi160 +} // namespace esphome diff --git a/esphome/components/bmi160/sensor.py b/esphome/components/bmi160/sensor.py new file mode 100644 index 0000000000..baf185f95a --- /dev/null +++ b/esphome/components/bmi160/sensor.py @@ -0,0 +1,102 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import i2c, sensor +from esphome.const import ( + CONF_ID, + CONF_TEMPERATURE, + CONF_ACCELERATION_X, + CONF_ACCELERATION_Y, + CONF_ACCELERATION_Z, + CONF_GYROSCOPE_X, + CONF_GYROSCOPE_Y, + CONF_GYROSCOPE_Z, + DEVICE_CLASS_TEMPERATURE, + STATE_CLASS_MEASUREMENT, + UNIT_METER_PER_SECOND_SQUARED, + ICON_ACCELERATION_X, + ICON_ACCELERATION_Y, + ICON_ACCELERATION_Z, + ICON_GYROSCOPE_X, + ICON_GYROSCOPE_Y, + ICON_GYROSCOPE_Z, + UNIT_DEGREE_PER_SECOND, + UNIT_CELSIUS, +) + +DEPENDENCIES = ["i2c"] + +bmi160_ns = cg.esphome_ns.namespace("bmi160") +BMI160Component = bmi160_ns.class_( + "BMI160Component", cg.PollingComponent, i2c.I2CDevice +) + +accel_schema = { + "unit_of_measurement": UNIT_METER_PER_SECOND_SQUARED, + "accuracy_decimals": 2, + "state_class": STATE_CLASS_MEASUREMENT, +} +gyro_schema = { + "unit_of_measurement": UNIT_DEGREE_PER_SECOND, + "accuracy_decimals": 2, + "state_class": STATE_CLASS_MEASUREMENT, +} + +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(BMI160Component), + cv.Optional(CONF_ACCELERATION_X): sensor.sensor_schema( + icon=ICON_ACCELERATION_X, + **accel_schema, + ), + cv.Optional(CONF_ACCELERATION_Y): sensor.sensor_schema( + icon=ICON_ACCELERATION_Y, + **accel_schema, + ), + cv.Optional(CONF_ACCELERATION_Z): sensor.sensor_schema( + icon=ICON_ACCELERATION_Z, + **accel_schema, + ), + cv.Optional(CONF_GYROSCOPE_X): sensor.sensor_schema( + icon=ICON_GYROSCOPE_X, + **gyro_schema, + ), + cv.Optional(CONF_GYROSCOPE_Y): sensor.sensor_schema( + icon=ICON_GYROSCOPE_Y, + **gyro_schema, + ), + cv.Optional(CONF_GYROSCOPE_Z): sensor.sensor_schema( + icon=ICON_GYROSCOPE_Z, + **gyro_schema, + ), + cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema( + unit_of_measurement=UNIT_CELSIUS, + accuracy_decimals=0, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + ), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x68)) +) + + +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) + + for d in ["x", "y", "z"]: + accel_key = f"acceleration_{d}" + if accel_key in config: + sens = await sensor.new_sensor(config[accel_key]) + cg.add(getattr(var, f"set_accel_{d}_sensor")(sens)) + accel_key = f"gyroscope_{d}" + if accel_key in config: + sens = await sensor.new_sensor(config[accel_key]) + cg.add(getattr(var, f"set_gyro_{d}_sensor")(sens)) + + if CONF_TEMPERATURE in config: + sens = await sensor.new_sensor(config[CONF_TEMPERATURE]) + cg.add(var.set_temperature_sensor(sens)) diff --git a/esphome/const.py b/esphome/const.py index 0e4e880c19..bbc6e71885 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -298,6 +298,9 @@ CONF_GLYPHS = "glyphs" CONF_GPIO = "gpio" CONF_GREEN = "green" CONF_GROUP = "group" +CONF_GYROSCOPE_X = "gyroscope_x" +CONF_GYROSCOPE_Y = "gyroscope_y" +CONF_GYROSCOPE_Z = "gyroscope_z" CONF_HARDWARE_UART = "hardware_uart" CONF_HEAD = "head" CONF_HEARTBEAT = "heartbeat" @@ -867,6 +870,9 @@ ICON_FLOWER = "mdi:flower" ICON_GAS_CYLINDER = "mdi:gas-cylinder" ICON_GAUGE = "mdi:gauge" ICON_GRAIN = "mdi:grain" +ICON_GYROSCOPE_X = "mdi:axis-x-rotate-clockwise" +ICON_GYROSCOPE_Y = "mdi:axis-y-rotate-clockwise" +ICON_GYROSCOPE_Z = "mdi:axis-z-rotate-clockwise" ICON_HEATING_COIL = "mdi:heating-coil" ICON_KEY_PLUS = "mdi:key-plus" ICON_LIGHTBULB = "mdi:lightbulb" diff --git a/tests/test1.yaml b/tests/test1.yaml index 33782dbf53..fe983cf421 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -915,6 +915,23 @@ sensor: temperature: name: MPU6886 Temperature i2c_id: i2c_bus + - platform: bmi160 + address: 0x68 + acceleration_x: + name: BMI160 Accel X + acceleration_y: + name: BMI160 Accel Y + acceleration_z: + name: BMI160 Accel z + gyroscope_x: + name: BMI160 Gyro X + gyroscope_y: + name: BMI160 Gyro Y + gyroscope_z: + name: BMI160 Gyro z + temperature: + name: BMI160 Temperature + i2c_id: i2c_bus - platform: mmc5603 address: 0x30 field_strength_x: From 32b103eb1d67ea2275d61531ffc51b90f59870fa Mon Sep 17 00:00:00 2001 From: "Kevin P. Fleming" Date: Sun, 10 Sep 2023 15:42:42 -0400 Subject: [PATCH 0163/2101] Use black-pre-commit-mirror to speed up pre-commit runs. (#5372) --- .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 cf86d354b7..0bbb2fee61 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,7 +2,7 @@ # See https://pre-commit.com for more information # See https://pre-commit.com/hooks.html for more hooks repos: - - repo: https://github.com/psf/black + - repo: https://github.com/psf/black-pre-commit-mirror rev: 23.7.0 hooks: - id: black From d2648657fb13e9bc576c1f8436ca7ab9a9d3748e Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Mon, 11 Sep 2023 12:20:06 +1000 Subject: [PATCH 0164/2101] Native SPI RGB LED component (#5288) * Add testing branch to workflow * Add workflow * Checkpoint * Align SPI data rates in c++ code with Python code. * Checkpoint * CI fixes * Update codeowners * Workflow cleanup * Rename to spi_rgb_led * Rename header file * Clang tidy * Disable spi after transfer. * Move enable() to where it belongs * Call spi_setup before enable * Clang tidy * Add test * Rename to spi_led_strip * Include 'defines.h' * Fix CODEOWNERS * Migrate data rate to new style setting. * Remove defines.h * Fix class name * Fix name in .py * And more more name tidy up. --------- Co-authored-by: Keith Burzinski --- CODEOWNERS | 1 + esphome/components/spi_led_strip/__init__.py | 2 + esphome/components/spi_led_strip/light.py | 27 ++++++ .../components/spi_led_strip/spi_led_strip.h | 91 +++++++++++++++++++ tests/test8.yaml | 6 ++ 5 files changed, 127 insertions(+) create mode 100644 esphome/components/spi_led_strip/__init__.py create mode 100644 esphome/components/spi_led_strip/light.py create mode 100644 esphome/components/spi_led_strip/spi_led_strip.h diff --git a/CODEOWNERS b/CODEOWNERS index 2658aebdc7..8e0911f2a9 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -272,6 +272,7 @@ esphome/components/sonoff_d1/* @anatoly-savchenkov esphome/components/speaker/* @jesserockz esphome/components/spi/* @esphome/core esphome/components/spi_device/* @clydebarrow +esphome/components/spi_led_strip/* @clydebarrow esphome/components/sprinkler/* @kbx81 esphome/components/sps30/* @martgras esphome/components/ssd1322_base/* @kbx81 diff --git a/esphome/components/spi_led_strip/__init__.py b/esphome/components/spi_led_strip/__init__.py new file mode 100644 index 0000000000..850a1f6e02 --- /dev/null +++ b/esphome/components/spi_led_strip/__init__.py @@ -0,0 +1,2 @@ +CODEOWNERS = ["@clydebarrow"] +DEPENDENCIES = ["spi"] diff --git a/esphome/components/spi_led_strip/light.py b/esphome/components/spi_led_strip/light.py new file mode 100644 index 0000000000..7420b0c929 --- /dev/null +++ b/esphome/components/spi_led_strip/light.py @@ -0,0 +1,27 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import light +from esphome.components import spi +from esphome.const import CONF_OUTPUT_ID, CONF_NUM_LEDS, CONF_DATA_RATE + +spi_led_strip_ns = cg.esphome_ns.namespace("spi_led_strip") +SpiLedStrip = spi_led_strip_ns.class_( + "SpiLedStrip", light.AddressableLight, spi.SPIDevice +) + +CONFIG_SCHEMA = light.ADDRESSABLE_LIGHT_SCHEMA.extend( + { + cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(SpiLedStrip), + cv.Optional(CONF_NUM_LEDS, default=1): cv.positive_not_null_int, + cv.Optional(CONF_DATA_RATE, default="1MHz"): spi.SPI_DATA_RATE_SCHEMA, + } +).extend(spi.spi_device_schema(False)) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_OUTPUT_ID]) + cg.add(var.set_data_rate(spi.SPI_DATA_RATE_OPTIONS[config[CONF_DATA_RATE]])) + cg.add(var.set_num_leds(config[CONF_NUM_LEDS])) + await light.register_light(var, config) + await spi.register_spi_device(var, config) + await cg.register_component(var, config) diff --git a/esphome/components/spi_led_strip/spi_led_strip.h b/esphome/components/spi_led_strip/spi_led_strip.h new file mode 100644 index 0000000000..0d8c1c1e1c --- /dev/null +++ b/esphome/components/spi_led_strip/spi_led_strip.h @@ -0,0 +1,91 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/core/log.h" +#include "esphome/components/light/addressable_light.h" +#include "esphome/components/spi/spi.h" + +namespace esphome { +namespace spi_led_strip { + +static const char *const TAG = "spi_led_strip"; +class SpiLedStrip : public light::AddressableLight, + public spi::SPIDevice { + public: + void setup() { this->spi_setup(); } + + int32_t size() const override { return this->num_leds_; } + + light::LightTraits get_traits() override { + auto traits = light::LightTraits(); + traits.set_supported_color_modes({light::ColorMode::RGB}); + return traits; + } + void set_num_leds(uint16_t num_leds) { + this->num_leds_ = num_leds; + ExternalRAMAllocator allocator(ExternalRAMAllocator::ALLOW_FAILURE); + this->buffer_size_ = num_leds * 4 + 8; + this->buf_ = allocator.allocate(this->buffer_size_); + if (this->buf_ == nullptr) { + esph_log_e(TAG, "Failed to allocate buffer of size %u", this->buffer_size_); + this->mark_failed(); + return; + } + + this->effect_data_ = allocator.allocate(num_leds); + if (this->effect_data_ == nullptr) { + esph_log_e(TAG, "Failed to allocate effect data of size %u", num_leds); + this->mark_failed(); + return; + } + memset(this->buf_, 0xFF, this->buffer_size_); + memset(this->buf_, 0, 4); + } + + void dump_config() { + esph_log_config(TAG, "SPI LED Strip:"); + esph_log_config(TAG, " LEDs: %d", this->num_leds_); + if (this->data_rate_ >= spi::DATA_RATE_1MHZ) + esph_log_config(TAG, " Data rate: %uMHz", (unsigned) (this->data_rate_ / 1000000)); + else + esph_log_config(TAG, " Data rate: %ukHz", (unsigned) (this->data_rate_ / 1000)); + } + + void write_state(light::LightState *state) override { + 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]); + } + esph_log_v(TAG, "write_state: buf = %s", strbuf); + } + this->enable(); + this->write_array(this->buf_, this->buffer_size_); + this->disable(); + } + + void clear_effect_data() override { + for (int i = 0; i < this->size(); i++) + this->effect_data_[i] = 0; + } + + protected: + light::ESPColorView get_view_internal(int32_t index) const override { + size_t pos = index * 4 + 5; + return {this->buf_ + pos + 2, this->buf_ + pos + 1, this->buf_ + pos + 0, nullptr, + this->effect_data_ + index, &this->correction_}; + } + + size_t buffer_size_{}; + uint8_t *effect_data_{nullptr}; + uint8_t *buf_{nullptr}; + uint16_t num_leds_; +}; + +} // namespace spi_led_strip +} // namespace esphome diff --git a/tests/test8.yaml b/tests/test8.yaml index 498da94483..01d12ea330 100644 --- a/tests/test8.yaml +++ b/tests/test8.yaml @@ -29,6 +29,12 @@ light: name: neopixel-enable internal: false restore_mode: ALWAYS_OFF + - platform: spi_led_strip + num_leds: 4 + color_correct: [80%, 60%, 100%] + id: rgb_led + name: "RGB LED" + data_rate: 8MHz spi: id: spi_id_1 From b107948c476e0d587b41399fdc5a7bea90753c68 Mon Sep 17 00:00:00 2001 From: Lubos Horacek Date: Mon, 11 Sep 2023 21:13:24 +0200 Subject: [PATCH 0165/2101] Wireguard component (#4256) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Co-authored-by: Simone Rossetto Co-authored-by: Thomas Bernard --- .github/workflows/ci.yml | 2 +- .gitignore | 6 + CODEOWNERS | 1 + esphome/components/wireguard/__init__.py | 113 +++++++ esphome/components/wireguard/binary_sensor.py | 28 ++ esphome/components/wireguard/sensor.py | 30 ++ esphome/components/wireguard/wireguard.cpp | 296 ++++++++++++++++++ esphome/components/wireguard/wireguard.h | 122 ++++++++ platformio.ini | 2 + tests/README.md | 1 + tests/test10.yaml | 48 +++ 11 files changed, 648 insertions(+), 1 deletion(-) create mode 100644 esphome/components/wireguard/__init__.py create mode 100644 esphome/components/wireguard/binary_sensor.py create mode 100644 esphome/components/wireguard/sensor.py create mode 100644 esphome/components/wireguard/wireguard.cpp create mode 100644 esphome/components/wireguard/wireguard.h create mode 100644 tests/test10.yaml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4214bc2c5d..79ebe8782e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -232,7 +232,7 @@ jobs: fail-fast: false max-parallel: 2 matrix: - file: [1, 2, 3, 3.1, 4, 5, 6, 7, 8] + file: [1, 2, 3, 3.1, 4, 5, 6, 7, 8, 10] steps: - name: Check out code from GitHub uses: actions/checkout@v4 diff --git a/.gitignore b/.gitignore index d180b58259..0c9a878400 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,12 @@ __pycache__/ # Intellij Idea .idea +# Eclipse +.project +.cproject +.pydevproject +.settings/ + # Vim *.swp diff --git a/CODEOWNERS b/CODEOWNERS index 8e0911f2a9..22e46aa2f0 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -333,6 +333,7 @@ esphome/components/web_server_idf/* @dentra esphome/components/whirlpool/* @glmnet esphome/components/whynter/* @aeonsablaze esphome/components/wiegand/* @ssieb +esphome/components/wireguard/* @droscy @lhoracek @thomas0bernard esphome/components/wl_134/* @hobbypunk90 esphome/components/x9c/* @EtienneMD esphome/components/xiaomi_lywsd03mmc/* @ahpohl diff --git a/esphome/components/wireguard/__init__.py b/esphome/components/wireguard/__init__.py new file mode 100644 index 0000000000..717fe50d2c --- /dev/null +++ b/esphome/components/wireguard/__init__.py @@ -0,0 +1,113 @@ +import re +import ipaddress +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.const import ( + CONF_ID, + CONF_TIME_ID, + CONF_ADDRESS, + CONF_REBOOT_TIMEOUT, +) +from esphome.components import time + +CONF_NETMASK = "netmask" +CONF_PRIVATE_KEY = "private_key" +CONF_PEER_ENDPOINT = "peer_endpoint" +CONF_PEER_PUBLIC_KEY = "peer_public_key" +CONF_PEER_PORT = "peer_port" +CONF_PEER_PRESHARED_KEY = "peer_preshared_key" +CONF_PEER_ALLOWED_IPS = "peer_allowed_ips" +CONF_PEER_PERSISTENT_KEEPALIVE = "peer_persistent_keepalive" +CONF_REQUIRE_CONNECTION_TO_PROCEED = "require_connection_to_proceed" + +DEPENDENCIES = ["time", "esp32"] +CODEOWNERS = ["@lhoracek", "@droscy", "@thomas0bernard"] + +# The key validation regex has been described by Jason Donenfeld himself +# url: https://lists.zx2c4.com/pipermail/wireguard/2020-December/006222.html +_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) + + +def _wireguard_key(value): + if _WG_KEY_REGEX.match(cv.string(value)) is not None: + return value + raise cv.Invalid(f"Invalid WireGuard key: {value}") + + +def _cidr_network(value): + try: + ipaddress.ip_network(value, strict=False) + except ValueError as err: + raise cv.Invalid(f"Invalid network in CIDR notation: {err}") + return value + + +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.declare_id(Wireguard), + cv.GenerateID(CONF_TIME_ID): cv.use_id(time.RealTimeClock), + cv.Required(CONF_ADDRESS): cv.ipv4, + cv.Optional(CONF_NETMASK, default="255.255.255.255"): cv.ipv4, + cv.Required(CONF_PRIVATE_KEY): _wireguard_key, + cv.Required(CONF_PEER_ENDPOINT): cv.string, + cv.Required(CONF_PEER_PUBLIC_KEY): _wireguard_key, + cv.Optional(CONF_PEER_PORT, default=51820): cv.port, + cv.Optional(CONF_PEER_PRESHARED_KEY): _wireguard_key, + cv.Optional(CONF_PEER_ALLOWED_IPS, default=["0.0.0.0/0"]): cv.ensure_list( + _cidr_network + ), + cv.Optional(CONF_PEER_PERSISTENT_KEEPALIVE, default=0): cv.Any( + cv.positive_time_period_seconds, + cv.uint16_t, + ), + cv.Optional( + CONF_REBOOT_TIMEOUT, default="15min" + ): cv.positive_time_period_milliseconds, + cv.Optional(CONF_REQUIRE_CONNECTION_TO_PROCEED, default=False): cv.boolean, + } +).extend(cv.polling_component_schema("10s")) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + + cg.add(var.set_address(str(config[CONF_ADDRESS]))) + cg.add(var.set_netmask(str(config[CONF_NETMASK]))) + cg.add(var.set_private_key(config[CONF_PRIVATE_KEY])) + cg.add(var.set_peer_endpoint(config[CONF_PEER_ENDPOINT])) + cg.add(var.set_peer_public_key(config[CONF_PEER_PUBLIC_KEY])) + cg.add(var.set_peer_port(config[CONF_PEER_PORT])) + cg.add(var.set_keepalive(config[CONF_PEER_PERSISTENT_KEEPALIVE])) + cg.add(var.set_reboot_timeout(config[CONF_REBOOT_TIMEOUT])) + + if CONF_PEER_PRESHARED_KEY in config: + cg.add(var.set_preshared_key(config[CONF_PEER_PRESHARED_KEY])) + + allowed_ips = list( + ipaddress.collapse_addresses( + [ + ipaddress.ip_network(ip, strict=False) + for ip in config[CONF_PEER_ALLOWED_IPS] + ] + ) + ) + + for ip in allowed_ips: + cg.add(var.add_allowed_ip(str(ip.network_address), str(ip.netmask))) + + cg.add(var.set_srctime(await cg.get_variable(config[CONF_TIME_ID]))) + + if config[CONF_REQUIRE_CONNECTION_TO_PROCEED]: + cg.add(var.disable_auto_proceed()) + + # This flag is added here because the esp_wireguard library statically + # set the size of its allowed_ips list at compile time using this value; + # the '+1' modifier is relative to the device's own address that will + # 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.3.2") + + await cg.register_component(var, config) diff --git a/esphome/components/wireguard/binary_sensor.py b/esphome/components/wireguard/binary_sensor.py new file mode 100644 index 0000000000..14ff2b0159 --- /dev/null +++ b/esphome/components/wireguard/binary_sensor.py @@ -0,0 +1,28 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import binary_sensor +from esphome.const import ( + CONF_STATUS, + DEVICE_CLASS_CONNECTIVITY, +) + +from . import Wireguard + +CONF_WIREGUARD_ID = "wireguard_id" + +DEPENDENCIES = ["wireguard"] + +CONFIG_SCHEMA = { + cv.GenerateID(CONF_WIREGUARD_ID): cv.use_id(Wireguard), + cv.Optional(CONF_STATUS): binary_sensor.binary_sensor_schema( + device_class=DEVICE_CLASS_CONNECTIVITY, + ), +} + + +async def to_code(config): + parent = await cg.get_variable(config[CONF_WIREGUARD_ID]) + + if status_config := config.get(CONF_STATUS): + sens = await binary_sensor.new_binary_sensor(status_config) + cg.add(parent.set_status_sensor(sens)) diff --git a/esphome/components/wireguard/sensor.py b/esphome/components/wireguard/sensor.py new file mode 100644 index 0000000000..78cb619701 --- /dev/null +++ b/esphome/components/wireguard/sensor.py @@ -0,0 +1,30 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import sensor +from esphome.const import ( + DEVICE_CLASS_TIMESTAMP, + ENTITY_CATEGORY_DIAGNOSTIC, +) + +from . import Wireguard + +CONF_WIREGUARD_ID = "wireguard_id" +CONF_LATEST_HANDSHAKE = "latest_handshake" + +DEPENDENCIES = ["wireguard"] + +CONFIG_SCHEMA = { + cv.GenerateID(CONF_WIREGUARD_ID): cv.use_id(Wireguard), + cv.Optional(CONF_LATEST_HANDSHAKE): sensor.sensor_schema( + device_class=DEVICE_CLASS_TIMESTAMP, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + ), +} + + +async def to_code(config): + parent = await cg.get_variable(config[CONF_WIREGUARD_ID]) + + if latest_handshake_config := config.get(CONF_LATEST_HANDSHAKE): + sens = await sensor.new_sensor(latest_handshake_config) + cg.add(parent.set_handshake_sensor(sens)) diff --git a/esphome/components/wireguard/wireguard.cpp b/esphome/components/wireguard/wireguard.cpp new file mode 100644 index 0000000000..1b361cc1cc --- /dev/null +++ b/esphome/components/wireguard/wireguard.cpp @@ -0,0 +1,296 @@ +#include "wireguard.h" + +#ifdef USE_ESP32 + +#include +#include + +#include "esphome/core/application.h" +#include "esphome/core/log.h" +#include "esphome/core/time.h" +#include "esphome/components/network/util.h" + +#include + +#include + +// includes for resume/suspend wdt +#if defined(USE_ESP_IDF) +#include +#if ESP_IDF_VERSION_MAJOR >= 5 +#include +#endif +#elif defined(USE_ARDUINO) +#include +#endif + +namespace esphome { +namespace wireguard { + +static const char *const TAG = "wireguard"; + +static const char *const LOGMSG_PEER_STATUS = "WireGuard remote peer is %s (latest handshake %s)"; +static const char *const LOGMSG_ONLINE = "online"; +static const char *const LOGMSG_OFFLINE = "offline"; + +void Wireguard::setup() { + ESP_LOGD(TAG, "initializing WireGuard..."); + + 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_.port = this->peer_port_; + this->wg_config_.netmask = this->netmask_.c_str(); + this->wg_config_.persistent_keepalive = this->keepalive_; + + if (this->preshared_key_.length() > 0) + this->wg_config_.preshared_key = this->preshared_key_.c_str(); + + this->wg_initialized_ = esp_wireguard_init(&(this->wg_config_), &(this->wg_ctx_)); + + if (this->wg_initialized_ == ESP_OK) { + ESP_LOGI(TAG, "WireGuard 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 + } else { + ESP_LOGE(TAG, "cannot initialize WireGuard, error code %d", this->wg_initialized_); + this->mark_failed(); + } +} + +void Wireguard::loop() { + if ((this->wg_initialized_ == ESP_OK) && (this->wg_connected_ == ESP_OK) && (!network::is_connected())) { + ESP_LOGV(TAG, "local network connection has been lost, stopping WireGuard..."); + this->stop_connection_(); + } +} + +void Wireguard::update() { + bool peer_up = this->is_peer_up(); + time_t lhs = this->get_latest_handshake(); + bool lhs_updated = (lhs > this->latest_saved_handshake_); + + ESP_LOGV(TAG, "handshake: latest=%.0f, saved=%.0f, updated=%d", (double) lhs, (double) this->latest_saved_handshake_, + (int) lhs_updated); + + if (lhs_updated) { + this->latest_saved_handshake_ = lhs; + } + + std::string latest_handshake = + (this->latest_saved_handshake_ > 0) + ? ESPTime::from_epoch_local(this->latest_saved_handshake_).strftime("%Y-%m-%d %H:%M:%S %Z") + : "timestamp not available"; + + if (peer_up) { + if (this->wg_peer_offline_time_ != 0) { + ESP_LOGI(TAG, LOGMSG_PEER_STATUS, LOGMSG_ONLINE, latest_handshake.c_str()); + this->wg_peer_offline_time_ = 0; + } else { + ESP_LOGD(TAG, LOGMSG_PEER_STATUS, LOGMSG_ONLINE, latest_handshake.c_str()); + } + } else { + if (this->wg_peer_offline_time_ == 0) { + ESP_LOGW(TAG, LOGMSG_PEER_STATUS, LOGMSG_OFFLINE, latest_handshake.c_str()); + this->wg_peer_offline_time_ = millis(); + } else { + ESP_LOGD(TAG, LOGMSG_PEER_STATUS, LOGMSG_OFFLINE, latest_handshake.c_str()); + this->start_connection_(); + } + + // check reboot timeout every time the peer is down + if (this->reboot_timeout_ > 0) { + if (millis() - this->wg_peer_offline_time_ > this->reboot_timeout_) { + ESP_LOGE(TAG, "WireGuard remote peer is unreachable, rebooting..."); + App.reboot(); + } + } + } + +#ifdef USE_BINARY_SENSOR + if (this->status_sensor_ != nullptr) { + this->status_sensor_->publish_state(peer_up); + } +#endif + +#ifdef USE_SENSOR + if (this->handshake_sensor_ != nullptr && lhs_updated) { + this->handshake_sensor_->publish_state((double) this->latest_saved_handshake_); + } +#endif +} + +void Wireguard::dump_config() { + ESP_LOGCONFIG(TAG, "WireGuard:"); + ESP_LOGCONFIG(TAG, " Address: %s", this->address_.c_str()); + ESP_LOGCONFIG(TAG, " Netmask: %s", this->netmask_.c_str()); + ESP_LOGCONFIG(TAG, " Private Key: " LOG_SECRET("%s"), mask_key(this->private_key_).c_str()); + ESP_LOGCONFIG(TAG, " Peer Endpoint: " LOG_SECRET("%s"), this->peer_endpoint_.c_str()); + ESP_LOGCONFIG(TAG, " Peer Port: " LOG_SECRET("%d"), this->peer_port_); + ESP_LOGCONFIG(TAG, " Peer Public Key: " LOG_SECRET("%s"), this->peer_public_key_.c_str()); + ESP_LOGCONFIG(TAG, " Peer Pre-shared Key: " LOG_SECRET("%s"), + (this->preshared_key_.length() > 0 ? mask_key(this->preshared_key_).c_str() : "NOT IN USE")); + 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()); + } + ESP_LOGCONFIG(TAG, " Peer Persistent Keepalive: %d%s", this->keepalive_, + (this->keepalive_ > 0 ? "s" : " (DISABLED)")); + ESP_LOGCONFIG(TAG, " Reboot Timeout: %d%s", (this->reboot_timeout_ / 1000), + (this->reboot_timeout_ != 0 ? "s" : " (DISABLED)")); + // be careful: if proceed_allowed_ is true, require connection is false + ESP_LOGCONFIG(TAG, " Require Connection to Proceed: %s", (this->proceed_allowed_ ? "NO" : "YES")); + LOG_UPDATE_INTERVAL(this); +} + +void Wireguard::on_shutdown() { this->stop_connection_(); } + +bool Wireguard::can_proceed() { return (this->proceed_allowed_ || this->is_peer_up()); } + +bool Wireguard::is_peer_up() const { + return (this->wg_initialized_ == ESP_OK) && (this->wg_connected_ == ESP_OK) && + (esp_wireguardif_peer_is_up(&(this->wg_ctx_)) == ESP_OK); +} + +time_t Wireguard::get_latest_handshake() const { + time_t result; + if (esp_wireguard_latest_handshake(&(this->wg_ctx_), &result) != ESP_OK) { + result = 0; + } + 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; } + +#ifdef USE_BINARY_SENSOR +void Wireguard::set_status_sensor(binary_sensor::BinarySensor *sensor) { this->status_sensor_ = sensor; } +#endif + +#ifdef USE_SENSOR +void Wireguard::set_handshake_sensor(sensor::Sensor *sensor) { this->handshake_sensor_ = sensor; } +#endif + +void Wireguard::disable_auto_proceed() { this->proceed_allowed_ = false; } + +void Wireguard::start_connection_() { + if (this->wg_initialized_ != ESP_OK) { + ESP_LOGE(TAG, "cannot start WireGuard, initialization in error with code %d", this->wg_initialized_); + return; + } + + if (!network::is_connected()) { + ESP_LOGD(TAG, "WireGuard is waiting for local network connection to be available"); + return; + } + + if (!this->srctime_->now().is_valid()) { + ESP_LOGD(TAG, "WireGuard is waiting for system time to be synchronized"); + return; + } + + if (this->wg_connected_ == ESP_OK) { + ESP_LOGV(TAG, "WireGuard connection already started"); + return; + } + + ESP_LOGD(TAG, "starting WireGuard connection..."); + + /* + * The function esp_wireguard_connect() contains a DNS resolution + * that could trigger the watchdog, so before it we suspend (or + * increase the time, it depends on the platform) the wdt and + * then we resume the normal timeout. + */ + suspend_wdt(); + ESP_LOGV(TAG, "executing esp_wireguard_connect"); + this->wg_connected_ = esp_wireguard_connect(&(this->wg_ctx_)); + resume_wdt(); + + if (this->wg_connected_ == ESP_OK) { + ESP_LOGI(TAG, "WireGuard connection started"); + } else { + ESP_LOGW(TAG, "cannot start WireGuard connection, error code %d", this->wg_connected_); + return; + } + + ESP_LOGD(TAG, "configuring WireGuard 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); + } + + if (allowed_ips_ok) { + ESP_LOGD(TAG, "allowed IPs list configured correctly"); + } else { + ESP_LOGE(TAG, "cannot configure WireGuard allowed IPs list, aborting..."); + this->stop_connection_(); + this->mark_failed(); + } +} + +void Wireguard::stop_connection_() { + if (this->wg_initialized_ == ESP_OK && this->wg_connected_ == ESP_OK) { + ESP_LOGD(TAG, "stopping WireGuard connection..."); + esp_wireguard_disconnect(&(this->wg_ctx_)); + this->wg_connected_ = ESP_FAIL; + } +} + +void suspend_wdt() { +#if defined(USE_ESP_IDF) +#if ESP_IDF_VERSION_MAJOR >= 5 + ESP_LOGV(TAG, "temporarily increasing wdt timeout to 15000 ms"); + esp_task_wdt_config_t wdtc; + wdtc.timeout_ms = 15000; + wdtc.idle_core_mask = 0; + wdtc.trigger_panic = false; + esp_task_wdt_reconfigure(&wdtc); +#else + ESP_LOGV(TAG, "temporarily increasing wdt timeout to 15 seconds"); + esp_task_wdt_init(15, false); +#endif +#elif defined(USE_ARDUINO) + ESP_LOGV(TAG, "temporarily disabling the wdt"); + disableLoopWDT(); +#endif +} + +void resume_wdt() { +#if defined(USE_ESP_IDF) +#if ESP_IDF_VERSION_MAJOR >= 5 + wdtc.timeout_ms = CONFIG_ESP_TASK_WDT_TIMEOUT_S * 1000; + esp_task_wdt_reconfigure(&wdtc); + ESP_LOGV(TAG, "wdt resumed with %d ms timeout", wdtc.timeout_ms); +#else + esp_task_wdt_init(CONFIG_ESP_TASK_WDT_TIMEOUT_S, false); + ESP_LOGV(TAG, "wdt resumed with %d seconds timeout", CONFIG_ESP_TASK_WDT_TIMEOUT_S); +#endif +#elif defined(USE_ARDUINO) + enableLoopWDT(); + ESP_LOGV(TAG, "wdt resumed"); +#endif +} + +std::string mask_key(const std::string &key) { return (key.substr(0, 5) + "[...]="); } + +} // namespace wireguard +} // namespace esphome + +#endif // USE_ESP32 diff --git a/esphome/components/wireguard/wireguard.h b/esphome/components/wireguard/wireguard.h new file mode 100644 index 0000000000..cfc5fa1a27 --- /dev/null +++ b/esphome/components/wireguard/wireguard.h @@ -0,0 +1,122 @@ +#pragma once + +#ifdef USE_ESP32 + +#include +#include +#include + +#include "esphome/core/component.h" +#include "esphome/components/time/real_time_clock.h" + +#ifdef USE_BINARY_SENSOR +#include "esphome/components/binary_sensor/binary_sensor.h" +#endif + +#ifdef USE_SENSOR +#include "esphome/components/sensor/sensor.h" +#endif + +#include + +namespace esphome { +namespace wireguard { + +class Wireguard : public PollingComponent { + public: + void setup() override; + void loop() override; + void update() override; + void dump_config() override; + void on_shutdown() override; + bool can_proceed() override; + + 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 add_allowed_ip(const std::string &ip, const std::string &netmask); + + void set_keepalive(uint16_t seconds); + void set_reboot_timeout(uint32_t seconds); + void set_srctime(time::RealTimeClock *srctime); + +#ifdef USE_BINARY_SENSOR + void set_status_sensor(binary_sensor::BinarySensor *sensor); +#endif + +#ifdef USE_SENSOR + void set_handshake_sensor(sensor::Sensor *sensor); +#endif + + /// Block the setup step until peer is connected. + void disable_auto_proceed(); + + bool is_peer_up() const; + 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_; + + std::vector> allowed_ips_; + + uint16_t peer_port_; + uint16_t keepalive_; + uint32_t reboot_timeout_; + + time::RealTimeClock *srctime_; + +#ifdef USE_BINARY_SENSOR + binary_sensor::BinarySensor *status_sensor_ = nullptr; +#endif + +#ifdef USE_SENSOR + sensor::Sensor *handshake_sensor_ = nullptr; +#endif + + /// Set to false to block the setup step until peer is connected. + bool proceed_allowed_ = true; + + wireguard_config_t wg_config_ = ESP_WIREGUARD_CONFIG_DEFAULT(); + wireguard_ctx_t wg_ctx_ = ESP_WIREGUARD_CONTEXT_DEFAULT(); + + esp_err_t wg_initialized_ = ESP_FAIL; + esp_err_t wg_connected_ = ESP_FAIL; + + /// The last time the remote peer become offline. + uint32_t wg_peer_offline_time_ = 0; + + /** \brief The latest saved handshake. + * + * This is used to save (and log) the latest completed handshake even + * after a full refresh of the wireguard keys (for example after a + * stop/start connection cycle). + */ + time_t latest_saved_handshake_ = 0; + + void start_connection_(); + void stop_connection_(); +}; + +// These are used for possibly long DNS resolution to temporarily suspend the watchdog +void suspend_wdt(); +void resume_wdt(); + +/// Strip most part of the key only for secure printing +std::string mask_key(const std::string &key); + +} // namespace wireguard +} // namespace esphome + +#endif // USE_ESP32 diff --git a/platformio.ini b/platformio.ini index ab9584d9b8..aea164353d 100644 --- a/platformio.ini +++ b/platformio.ini @@ -123,6 +123,7 @@ lib_deps = DNSServer ; captive_portal (Arduino built-in) esphome/ESP32-audioI2S@2.0.7 ; i2s_audio crankyoldgit/IRremoteESP8266@2.7.12 ; heatpumpir + droscy/esp_wireguard@0.3.2 ; wireguard build_flags = ${common:arduino.build_flags} -DUSE_ESP32 @@ -141,6 +142,7 @@ framework = espidf lib_deps = ${common:idf.lib_deps} espressif/esp32-camera@1.0.0 ; esp32_camera + droscy/esp_wireguard@0.3.2 ; wireguard build_flags = ${common:idf.build_flags} -Wno-nonnull-compare diff --git a/tests/README.md b/tests/README.md index 6d83fc6886..5b312d00de 100644 --- a/tests/README.md +++ b/tests/README.md @@ -27,3 +27,4 @@ Current test_.yaml file contents. | test6.yaml | RP2040 | wifi | N/A | test7.yaml | ESP32-C3 | wifi | N/A | test8.yaml | ESP32-S3 | wifi | None +| test10.yaml | ESP32 | wifi | None diff --git a/tests/test10.yaml b/tests/test10.yaml new file mode 100644 index 0000000000..0470e37e6c --- /dev/null +++ b/tests/test10.yaml @@ -0,0 +1,48 @@ +--- +esphome: + name: test10 + build_path: build/test10 + +esp32: + board: esp32doit-devkit-v1 + framework: + type: arduino + +wifi: + ssid: "MySSID1" + password: "password1" + reboot_timeout: 3min + power_save_mode: high + +logger: + level: VERBOSE + +api: + reboot_timeout: 10min + +time: + - platform: sntp + +wireguard: + id: vpn + address: 172.16.34.100 + netmask: 255.255.255.0 + # NEVER use the following keys for your vpn, they are now public! + private_key: wPBMxtNYH3mChicrbpsRpZIasIdPq3yZuthn23FbGG8= + peer_public_key: Hs2JfikvYU03/Kv3YoAs1hrUIPPTEkpsZKSPUljE9yc= + peer_preshared_key: 20fjM5GRnSolGPC5SRj9ljgIUyQfruv0B0bvLl3Yt60= + peer_endpoint: wg.server.example + peer_persistent_keepalive: 25s + peer_allowed_ips: + - 172.16.34.0/24 + - 192.168.4.0/24 + +binary_sensor: + - platform: wireguard + status: + name: 'WireGuard Status' + +sensor: + - platform: wireguard + latest_handshake: + name: 'WireGuard Latest Handshake' From 892d2ce34fb25332c2013ca3349f2558935734dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Mon, 11 Sep 2023 21:15:24 +0200 Subject: [PATCH 0166/2101] Bump LibreTiny version to 1.4.0 (#5375) --- esphome/components/libretiny/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/libretiny/__init__.py b/esphome/components/libretiny/__init__.py index ac294d3f65..3c1c0ac3f0 100644 --- a/esphome/components/libretiny/__init__.py +++ b/esphome/components/libretiny/__init__.py @@ -168,9 +168,9 @@ def _notify_old_style(config): # NOTE: Keep this in mind when updating the recommended version: # * For all constants below, update platformio.ini (in this repo) ARDUINO_VERSIONS = { - "dev": (cv.Version(0, 0, 0), "https://github.com/kuba2k2/libretiny.git"), + "dev": (cv.Version(0, 0, 0), "https://github.com/libretiny-eu/libretiny.git"), "latest": (cv.Version(0, 0, 0), None), - "recommended": (cv.Version(1, 3, 0), None), + "recommended": (cv.Version(1, 4, 0), None), } From deb34c947314b27c9db4f49cd8771fa5c76eaf00 Mon Sep 17 00:00:00 2001 From: "Kevin P. Fleming" Date: Mon, 11 Sep 2023 16:02:07 -0400 Subject: [PATCH 0167/2101] time: Make std::string version of strftime() avoid runaway memory allocations (#5348) --- esphome/core/time.cpp | 5 +++++ esphome/core/time.h | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/esphome/core/time.cpp b/esphome/core/time.cpp index bc5bfa173e..751b2a2703 100644 --- a/esphome/core/time.cpp +++ b/esphome/core/time.cpp @@ -49,6 +49,11 @@ std::string ESPTime::strftime(const std::string &format) { struct tm c_tm = this->to_c_tm(); size_t len = ::strftime(×tr[0], timestr.size(), format.c_str(), &c_tm); while (len == 0) { + if (timestr.size() >= 128) { + // strftime has failed for reasons unrelated to the size of the buffer + // so return a formatting error + return "ERROR"; + } timestr.resize(timestr.size() * 2); len = ::strftime(×tr[0], timestr.size(), format.c_str(), &c_tm); } diff --git a/esphome/core/time.h b/esphome/core/time.h index e16e449f0b..14c36311e0 100644 --- a/esphome/core/time.h +++ b/esphome/core/time.h @@ -45,6 +45,10 @@ struct ESPTime { * * @warning This method uses dynamically allocated strings which can cause heap fragmentation with some * microcontrollers. + * + * @warning This method can return "ERROR" when the underlying strftime() call fails, e.g. when the + * format string contains unsupported specifiers or when the format string doesn't produce any + * output. */ std::string strftime(const std::string &format); From d3196e0e34584bebc63b7a3a23d6403f4ceffdea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20S=C3=A1rk=C3=B6zi?= Date: Mon, 11 Sep 2023 22:12:56 +0200 Subject: [PATCH 0168/2101] Fix disabled wifi crash on boot (#5370) --- esphome/components/wifi/wifi_component.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index ff621291f0..2cb36fe8ea 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -40,6 +40,9 @@ void WiFiComponent::setup() { if (this->enable_on_boot_) { this->start(); } else { +#ifdef USE_ESP32 + esp_netif_init(); +#endif this->state_ = WIFI_COMPONENT_STATE_DISABLED; } } From c930c86cfa80ca67be2f8d98ec9b1f010a7dd90a Mon Sep 17 00:00:00 2001 From: Stijn Tintel Date: Mon, 11 Sep 2023 23:19:26 +0300 Subject: [PATCH 0169/2101] debug: add ESP32-C6 support (#5354) --- esphome/components/debug/debug_component.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/esphome/components/debug/debug_component.cpp b/esphome/components/debug/debug_component.cpp index 67b07237b7..fe66220ead 100644 --- a/esphome/components/debug/debug_component.cpp +++ b/esphome/components/debug/debug_component.cpp @@ -17,6 +17,8 @@ #include #elif defined(USE_ESP32_VARIANT_ESP32C3) #include +#elif defined(USE_ESP32_VARIANT_ESP32C6) +#include #elif defined(USE_ESP32_VARIANT_ESP32S2) #include #elif defined(USE_ESP32_VARIANT_ESP32S3) @@ -119,6 +121,8 @@ void DebugComponent::dump_config() { model = "ESP32"; #elif defined(USE_ESP32_VARIANT_ESP32C3) model = "ESP32-C3"; +#elif defined(USE_ESP32_VARIANT_ESP32C6) + model = "ESP32-C6"; #elif defined(USE_ESP32_VARIANT_ESP32S2) model = "ESP32-S2"; #elif defined(USE_ESP32_VARIANT_ESP32S3) @@ -202,9 +206,11 @@ void DebugComponent::dump_config() { case RTCWDT_SYS_RESET: reset_reason = "RTC Watch Dog Reset Digital Core"; break; +#if !defined(USE_ESP32_VARIANT_ESP32C6) case INTRUSION_RESET: reset_reason = "Intrusion Reset CPU"; break; +#endif #if defined(USE_ESP32_VARIANT_ESP32) case TGWDT_CPU_RESET: reset_reason = "Timer Group Reset CPU"; From 10eee47b6bd4f4032226aaf009b7339ec642d0fa Mon Sep 17 00:00:00 2001 From: Daniel Dunn Date: Mon, 11 Sep 2023 15:26:00 -0600 Subject: [PATCH 0170/2101] Make string globals persist-able using fixed size allocations (#5296) Co-authored-by: Daniel Dunn --- esphome/components/globals/__init__.py | 20 ++++++- .../components/globals/globals_component.h | 59 +++++++++++++++++++ esphome/cpp_generator.py | 7 ++- tests/test2.yaml | 7 +++ 4 files changed, 89 insertions(+), 4 deletions(-) diff --git a/esphome/components/globals/__init__.py b/esphome/components/globals/__init__.py index 97a7ba3d54..8defa4ac24 100644 --- a/esphome/components/globals/__init__.py +++ b/esphome/components/globals/__init__.py @@ -15,8 +15,14 @@ CODEOWNERS = ["@esphome/core"] globals_ns = cg.esphome_ns.namespace("globals") GlobalsComponent = globals_ns.class_("GlobalsComponent", cg.Component) RestoringGlobalsComponent = globals_ns.class_("RestoringGlobalsComponent", cg.Component) +RestoringGlobalStringComponent = globals_ns.class_( + "RestoringGlobalStringComponent", cg.Component +) GlobalVarSetAction = globals_ns.class_("GlobalVarSetAction", automation.Action) +CONF_MAX_RESTORE_DATA_LENGTH = "max_restore_data_length" + + MULTI_CONF = True CONFIG_SCHEMA = cv.Schema( { @@ -24,6 +30,7 @@ CONFIG_SCHEMA = cv.Schema( cv.Required(CONF_TYPE): cv.string_strict, cv.Optional(CONF_INITIAL_VALUE): cv.string_strict, 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) @@ -32,12 +39,19 @@ CONFIG_SCHEMA = cv.Schema( @coroutine_with_priority(-100.0) async def to_code(config): type_ = cg.RawExpression(config[CONF_TYPE]) - template_args = cg.TemplateArguments(type_) restore = config[CONF_RESTORE_VALUE] - type = RestoringGlobalsComponent if restore else GlobalsComponent - res_type = type.template(template_args) + # Special casing the strings to their own class with a different save/restore mechanism + if str(type_) == "std::string" and restore: + template_args = cg.TemplateArguments( + type_, config.get(CONF_MAX_RESTORE_DATA_LENGTH, 63) + 1 + ) + type = RestoringGlobalStringComponent + else: + template_args = cg.TemplateArguments(type_) + type = RestoringGlobalsComponent if restore else GlobalsComponent + res_type = type.template(template_args) initial_value = None if CONF_INITIAL_VALUE in config: initial_value = cg.RawExpression(config[CONF_INITIAL_VALUE]) diff --git a/esphome/components/globals/globals_component.h b/esphome/components/globals/globals_component.h index 101adeb311..78808436af 100644 --- a/esphome/components/globals/globals_component.h +++ b/esphome/components/globals/globals_component.h @@ -65,6 +65,64 @@ template class RestoringGlobalsComponent : public Component { ESPPreferenceObject rtc_; }; +// Use with string or subclasses of strings +template class RestoringGlobalStringComponent : public Component { + public: + using value_type = T; + explicit RestoringGlobalStringComponent() = default; + explicit RestoringGlobalStringComponent(T initial_value) { this->value_ = initial_value; } + explicit RestoringGlobalStringComponent( + std::array::type, std::extent::value> initial_value) { + memcpy(this->value_, initial_value.data(), sizeof(T)); + } + + T &value() { return this->value_; } + + void setup() override { + char temp[SZ]; + this->rtc_ = global_preferences->make_preference(1944399030U ^ this->name_hash_); + bool hasdata = this->rtc_.load(&temp); + if (hasdata) { + this->value_.assign(temp + 1, temp[0]); + } + this->prev_value_.assign(this->value_); + } + + float get_setup_priority() const override { return setup_priority::HARDWARE; } + + void loop() override { store_value_(); } + + void on_shutdown() override { store_value_(); } + + void set_name_hash(uint32_t name_hash) { this->name_hash_ = name_hash; } + + protected: + void store_value_() { + int diff = this->value_.compare(this->prev_value_); + if (diff != 0) { + // Make it into a length prefixed thing + unsigned char temp[SZ]; + + // If string is bigger than the allocation, do not save it. + // We don't need to waste ram setting prev_value either. + int size = this->value_.size(); + // Less than, not less than or equal, SZ includes the length byte. + if (size < SZ) { + memcpy(temp + 1, this->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->rtc_.save(&temp); + this->prev_value_.assign(this->value_); + } + } + } + + T value_{}; + T prev_value_{}; + uint32_t name_hash_{}; + ESPPreferenceObject rtc_; +}; + template class GlobalVarSetAction : public Action { public: explicit GlobalVarSetAction(C *parent) : parent_(parent) {} @@ -81,6 +139,7 @@ template class GlobalVarSetAction : public Action 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 diff --git a/esphome/cpp_generator.py b/esphome/cpp_generator.py index 789bd58e5c..2841be1546 100644 --- a/esphome/cpp_generator.py +++ b/esphome/cpp_generator.py @@ -663,7 +663,11 @@ async def process_lambda( :param return_type: The return type of the lambda. :return: The generated lambda expression. """ - from esphome.components.globals import GlobalsComponent, RestoringGlobalsComponent + from esphome.components.globals import ( + GlobalsComponent, + RestoringGlobalsComponent, + RestoringGlobalStringComponent, + ) if value is None: return @@ -676,6 +680,7 @@ async def process_lambda( and ( full_id.type.inherits_from(GlobalsComponent) or full_id.type.inherits_from(RestoringGlobalsComponent) + or full_id.type.inherits_from(RestoringGlobalStringComponent) ) ): parts[i * 3 + 1] = var.value() diff --git a/tests/test2.yaml b/tests/test2.yaml index 4928b8b877..c04e6726b1 100644 --- a/tests/test2.yaml +++ b/tests/test2.yaml @@ -5,6 +5,13 @@ esphome: board: nodemcu-32s build_path: build/test2 +globals: + - id: my_global_string + type: std::string + restore_value: yes + max_restore_data_length: 70 + initial_value: '"DefaultValue"' + substitutions: devicename: test2 From fe81bcc00343ba8d99a437762087717d45a20946 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 12 Sep 2023 09:26:48 +1200 Subject: [PATCH 0171/2101] Use /data directory for .esphome folder when running as HA add-on (#5374) --- .../etc/s6-overlay/s6-rc.d/esphome/run | 7 ++++++- esphome/components/font/__init__.py | 3 +-- esphome/components/image/__init__.py | 2 +- esphome/components/shelly_dimmer/light.py | 7 +------ esphome/core/__init__.py | 12 +++++++----- esphome/core/config.py | 4 ++-- esphome/dashboard/dashboard.py | 19 +++++++++---------- esphome/git.py | 2 +- esphome/storage_json.py | 14 +++++++------- esphome/wizard.py | 19 +++++++++++-------- tests/unit_tests/test_wizard.py | 7 +++++++ 11 files changed, 53 insertions(+), 43 deletions(-) diff --git a/docker/ha-addon-rootfs/etc/s6-overlay/s6-rc.d/esphome/run b/docker/ha-addon-rootfs/etc/s6-overlay/s6-rc.d/esphome/run index 277f26ea49..775c2fa0d6 100755 --- a/docker/ha-addon-rootfs/etc/s6-overlay/s6-rc.d/esphome/run +++ b/docker/ha-addon-rootfs/etc/s6-overlay/s6-rc.d/esphome/run @@ -35,11 +35,16 @@ if bashio::config.has_value 'default_compile_process_limit'; then export ESPHOME_DEFAULT_COMPILE_PROCESS_LIMIT=$(bashio::config 'default_compile_process_limit') else if grep -q 'Raspberry Pi 3' /proc/cpuinfo; then - export ESPHOME_DEFAULT_COMPILE_PROCESS_LIMIT=1; + export ESPHOME_DEFAULT_COMPILE_PROCESS_LIMIT=1 fi fi mkdir -p "${pio_cache_base}" +if bashio::fs.directory_exists '/config/esphome/.esphome'; then + bashio::log.info "Removing old .esphome directory..." + rm -rf /config/esphome/.esphome +fi + bashio::log.info "Starting ESPHome dashboard..." exec esphome dashboard /config/esphome --socket /var/run/esphome.sock --ha-addon diff --git a/esphome/components/font/__init__.py b/esphome/components/font/__init__.py index 52f877d986..e6244d8d44 100644 --- a/esphome/components/font/__init__.py +++ b/esphome/components/font/__init__.py @@ -98,10 +98,9 @@ def validate_truetype_file(value): def _compute_local_font_dir(name) -> Path: - base_dir = Path(CORE.config_dir) / ".esphome" / DOMAIN h = hashlib.new("sha256") h.update(name.encode()) - return base_dir / h.hexdigest()[:8] + return Path(CORE.data_dir) / DOMAIN / h.hexdigest()[:8] def _compute_gfonts_local_path(value) -> Path: diff --git a/esphome/components/image/__init__.py b/esphome/components/image/__init__.py index 392efb18a2..aa402ee329 100644 --- a/esphome/components/image/__init__.py +++ b/esphome/components/image/__init__.py @@ -52,7 +52,7 @@ Image_ = image_ns.class_("Image") def _compute_local_icon_path(value) -> Path: - base_dir = Path(CORE.config_dir) / ".esphome" / DOMAIN / "mdi" + base_dir = Path(CORE.data_dir) / DOMAIN / "mdi" return base_dir / f"{value[CONF_ICON]}.svg" diff --git a/esphome/components/shelly_dimmer/light.py b/esphome/components/shelly_dimmer/light.py index c49193d135..467a3c3531 100644 --- a/esphome/components/shelly_dimmer/light.py +++ b/esphome/components/shelly_dimmer/light.py @@ -87,12 +87,7 @@ def get_firmware(value): url = value[CONF_URL] if CONF_SHA256 in value: # we have a hash, enable caching - path = ( - Path(CORE.config_dir) - / ".esphome" - / DOMAIN - / (value[CONF_SHA256] + "_fw_stm.bin") - ) + path = Path(CORE.data_dir) / DOMAIN / (value[CONF_SHA256] + "_fw_stm.bin") if not path.is_file(): firmware_data, dl_hash = dl(url) diff --git a/esphome/core/__init__.py b/esphome/core/__init__.py index d9b1603894..cca758e3c1 100644 --- a/esphome/core/__init__.py +++ b/esphome/core/__init__.py @@ -554,6 +554,12 @@ class EsphomeCore: def config_dir(self): return os.path.dirname(self.config_path) + @property + def data_dir(self): + if is_ha_addon(): + return os.path.join("/data") + return self.relative_config_path(".esphome") + @property def config_filename(self): return os.path.basename(self.config_path) @@ -563,7 +569,7 @@ class EsphomeCore: return os.path.join(self.config_dir, path_) def relative_internal_path(self, *path: str) -> str: - return self.relative_config_path(".esphome", *path) + return os.path.join(self.data_dir, *path) def relative_build_path(self, *path): path_ = os.path.expanduser(os.path.join(*path)) @@ -573,13 +579,9 @@ class EsphomeCore: return self.relative_build_path("src", *path) def relative_pioenvs_path(self, *path): - if is_ha_addon(): - return os.path.join("/data", self.name, ".pioenvs", *path) return self.relative_build_path(".pioenvs", *path) def relative_piolibdeps_path(self, *path): - if is_ha_addon(): - return os.path.join("/data", self.name, ".piolibdeps", *path) return self.relative_build_path(".piolibdeps", *path) @property diff --git a/esphome/core/config.py b/esphome/core/config.py index a09252e4b4..1625644092 100644 --- a/esphome/core/config.py +++ b/esphome/core/config.py @@ -198,8 +198,8 @@ def preload_core_config(config, result): CORE.data[KEY_CORE] = {} if CONF_BUILD_PATH not in conf: - conf[CONF_BUILD_PATH] = f".esphome/build/{CORE.name}" - CORE.build_path = CORE.relative_config_path(conf[CONF_BUILD_PATH]) + conf[CONF_BUILD_PATH] = f"build/{CORE.name}" + CORE.build_path = CORE.relative_internal_path(conf[CONF_BUILD_PATH]) has_oldstyle = CONF_PLATFORM in conf newstyle_found = [key for key in TARGET_PLATFORMS if key in config] diff --git a/esphome/dashboard/dashboard.py b/esphome/dashboard/dashboard.py index cacd5e2db0..8049fb7f4c 100644 --- a/esphome/dashboard/dashboard.py +++ b/esphome/dashboard/dashboard.py @@ -32,6 +32,7 @@ import yaml from tornado.log import access_log from esphome import const, platformio_api, util, yaml_util +from esphome.core import CORE from esphome.helpers import get_bool_env, mkdir_p, run_system_command from esphome.storage_json import ( EsphomeStorageJSON, @@ -70,6 +71,7 @@ class DashboardSettings: self.password_hash = password_hash(password) self.config_dir = args.configuration self.absolute_config_dir = Path(self.config_dir).resolve() + CORE.config_path = os.path.join(self.config_dir, ".") @property def relative_url(self): @@ -534,7 +536,7 @@ class DownloadListRequestHandler(BaseHandler): @authenticated @bind_config def get(self, configuration=None): - storage_path = ext_storage_path(settings.config_dir, configuration) + storage_path = ext_storage_path(configuration) storage_json = StorageJSON.load(storage_path) if storage_json is None: self.send_error(404) @@ -577,7 +579,7 @@ class DownloadBinaryRequestHandler(BaseHandler): def get(self, configuration=None): compressed = self.get_argument("compressed", "0") == "1" - storage_path = ext_storage_path(settings.config_dir, configuration) + storage_path = ext_storage_path(configuration) storage_json = StorageJSON.load(storage_path) if storage_json is None: self.send_error(404) @@ -666,9 +668,7 @@ class DashboardEntry: @property def storage(self) -> Optional[StorageJSON]: if not self._loaded_storage: - self._storage = StorageJSON.load( - ext_storage_path(settings.config_dir, self.filename) - ) + self._storage = StorageJSON.load(ext_storage_path(self.filename)) self._loaded_storage = True return self._storage @@ -1044,9 +1044,9 @@ class DeleteRequestHandler(BaseHandler): @bind_config def post(self, configuration=None): config_file = settings.rel_path(configuration) - storage_path = ext_storage_path(settings.config_dir, configuration) + storage_path = ext_storage_path(configuration) - trash_path = trash_storage_path(settings.config_dir) + trash_path = trash_storage_path() mkdir_p(trash_path) shutil.move(config_file, os.path.join(trash_path, configuration)) @@ -1067,7 +1067,7 @@ class UndoDeleteRequestHandler(BaseHandler): @bind_config def post(self, configuration=None): config_file = settings.rel_path(configuration) - trash_path = trash_storage_path(settings.config_dir) + trash_path = trash_storage_path() shutil.move(os.path.join(trash_path, configuration), config_file) @@ -1325,10 +1325,9 @@ def make_app(debug=get_bool_env(ENV_DEV)): def start_web_server(args): settings.parse_args(args) - mkdir_p(settings.rel_path(".esphome")) if settings.using_auth: - path = esphome_storage_path(settings.config_dir) + path = esphome_storage_path() storage = EsphomeStorageJSON.load(path) if storage is None: storage = EsphomeStorageJSON.get_default() diff --git a/esphome/git.py b/esphome/git.py index dcc3e4d0c8..4f0911233e 100644 --- a/esphome/git.py +++ b/esphome/git.py @@ -35,7 +35,7 @@ def run_git_command(cmd, cwd=None) -> str: def _compute_destination_path(key: str, domain: str) -> Path: - base_dir = Path(CORE.config_dir) / ".esphome" / domain + base_dir = Path(CORE.data_dir) / domain h = hashlib.new("sha256") h.update(key.encode()) return base_dir / h.hexdigest()[:8] diff --git a/esphome/storage_json.py b/esphome/storage_json.py index acf525203d..a2619cb536 100644 --- a/esphome/storage_json.py +++ b/esphome/storage_json.py @@ -22,19 +22,19 @@ _LOGGER = logging.getLogger(__name__) def storage_path() -> str: - return CORE.relative_internal_path(f"{CORE.config_filename}.json") + return os.path.join(CORE.data_dir, "storage", f"{CORE.config_filename}.json") -def ext_storage_path(base_path: str, config_filename: str) -> str: - return os.path.join(base_path, ".esphome", f"{config_filename}.json") +def ext_storage_path(config_filename: str) -> str: + return os.path.join(CORE.data_dir, "storage", f"{config_filename}.json") -def esphome_storage_path(base_path: str) -> str: - return os.path.join(base_path, ".esphome", "esphome.json") +def esphome_storage_path() -> str: + return os.path.join(CORE.data_dir, "esphome.json") -def trash_storage_path(base_path: str) -> str: - return os.path.join(base_path, ".esphome", "trash") +def trash_storage_path() -> str: + return CORE.relative_config_path("trash") class StorageJSON: diff --git a/esphome/wizard.py b/esphome/wizard.py index 17a0882e1c..aa05e513a7 100644 --- a/esphome/wizard.py +++ b/esphome/wizard.py @@ -6,12 +6,12 @@ import unicodedata import voluptuous as vol import esphome.config_validation as cv +from esphome.const import ALLOWED_NAME_CHARS, ENV_QUICKWIZARD +from esphome.core import CORE from esphome.helpers import get_bool_env, write_file -from esphome.log import color, Fore - +from esphome.log import Fore, color from esphome.storage_json import StorageJSON, ext_storage_path from esphome.util import safe_print -from esphome.const import ALLOWED_NAME_CHARS, ENV_QUICKWIZARD CORE_BIG = r""" _____ ____ _____ ______ / ____/ __ \| __ \| ____| @@ -193,10 +193,10 @@ captive_portal: def wizard_write(path, **kwargs): - from esphome.components.esp8266 import boards as esp8266_boards - from esphome.components.esp32 import boards as esp32_boards - from esphome.components.rp2040 import boards as rp2040_boards from esphome.components.bk72xx import boards as bk72xx_boards + from esphome.components.esp32 import boards as esp32_boards + from esphome.components.esp8266 import boards as esp8266_boards + from esphome.components.rp2040 import boards as rp2040_boards from esphome.components.rtl87xx import boards as rtl87xx_boards name = kwargs["name"] @@ -225,7 +225,7 @@ def wizard_write(path, **kwargs): write_file(path, wizard_file(**kwargs)) storage = StorageJSON.from_wizard(name, name, f"{name}.local", hardware) - storage_path = ext_storage_path(os.path.dirname(path), os.path.basename(path)) + storage_path = ext_storage_path(os.path.basename(path)) storage.save(storage_path) return True @@ -265,9 +265,9 @@ def strip_accents(value): def wizard(path): + from esphome.components.bk72xx import boards as bk72xx_boards from esphome.components.esp32 import boards as esp32_boards from esphome.components.esp8266 import boards as esp8266_boards - from esphome.components.bk72xx import boards as bk72xx_boards from esphome.components.rtl87xx import boards as rtl87xx_boards if not path.endswith(".yaml") and not path.endswith(".yml"): @@ -280,6 +280,9 @@ def wizard(path): f"Uh oh, it seems like {color(Fore.CYAN, path)} already exists, please delete that file first or chose another configuration file." ) return 2 + + CORE.config_path = path + safe_print("Hi there!") sleep(1.5) safe_print("I'm the wizard of ESPHome :)") diff --git a/tests/unit_tests/test_wizard.py b/tests/unit_tests/test_wizard.py index d94624d1e4..8bbce08ae5 100644 --- a/tests/unit_tests/test_wizard.py +++ b/tests/unit_tests/test_wizard.py @@ -1,7 +1,9 @@ """Tests for the wizard.py file.""" +import os import esphome.wizard as wz import pytest +from esphome.core import CORE from esphome.components.esp8266.boards import ESP8266_BOARD_PINS from esphome.components.esp32.boards import ESP32_BOARD_PINS from esphome.components.bk72xx.boards import BK72XX_BOARD_PINS @@ -110,6 +112,7 @@ def test_wizard_write_sets_platform(default_config, tmp_path, monkeypatch): # Given del default_config["platform"] monkeypatch.setattr(wz, "write_file", MagicMock()) + monkeypatch.setattr(CORE, "config_path", os.path.dirname(tmp_path)) # When wz.wizard_write(tmp_path, **default_config) @@ -130,6 +133,7 @@ def test_wizard_write_defaults_platform_from_board_esp8266( default_config["board"] = [*ESP8266_BOARD_PINS][0] monkeypatch.setattr(wz, "write_file", MagicMock()) + monkeypatch.setattr(CORE, "config_path", os.path.dirname(tmp_path)) # When wz.wizard_write(tmp_path, **default_config) @@ -150,6 +154,7 @@ def test_wizard_write_defaults_platform_from_board_esp32( default_config["board"] = [*ESP32_BOARD_PINS][0] monkeypatch.setattr(wz, "write_file", MagicMock()) + monkeypatch.setattr(CORE, "config_path", os.path.dirname(tmp_path)) # When wz.wizard_write(tmp_path, **default_config) @@ -170,6 +175,7 @@ def test_wizard_write_defaults_platform_from_board_bk72xx( default_config["board"] = [*BK72XX_BOARD_PINS][0] monkeypatch.setattr(wz, "write_file", MagicMock()) + monkeypatch.setattr(CORE, "config_path", os.path.dirname(tmp_path)) # When wz.wizard_write(tmp_path, **default_config) @@ -190,6 +196,7 @@ def test_wizard_write_defaults_platform_from_board_rtl87xx( default_config["board"] = [*RTL87XX_BOARD_PINS][0] monkeypatch.setattr(wz, "write_file", MagicMock()) + monkeypatch.setattr(CORE, "config_path", os.path.dirname(tmp_path)) # When wz.wizard_write(tmp_path, **default_config) From e6da2313e69a1da4d1673ea28e5441fe189862fa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Sep 2023 10:02:13 +1200 Subject: [PATCH 0172/2101] Bump zeroconf from 0.102.0 to 0.108.0 (#5376) 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 9bce4a309d..19c05bf8f7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,7 +11,7 @@ esptool==4.6.2 click==8.1.7 esphome-dashboard==20230904.0 aioesphomeapi==15.0.0 -zeroconf==0.102.0 +zeroconf==0.108.0 # esp-idf requires this, but doesn't bundle it by default # https://github.com/espressif/esp-idf/blob/220590d599e134d7a5e7f1e683cc4550349ffbf8/requirements.txt#L24 From 47b1b458284dd1d3e7bbf2a8bd196a5b2f4ac64a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Sep 2023 22:38:58 +0000 Subject: [PATCH 0173/2101] Bump black from 23.7.0 to 23.9.1 (#5377) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- .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 0bbb2fee61..6e7261ebc3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,7 +3,7 @@ # See https://pre-commit.com/hooks.html for more hooks repos: - repo: https://github.com/psf/black-pre-commit-mirror - rev: 23.7.0 + rev: 23.9.1 hooks: - id: black args: diff --git a/requirements_test.txt b/requirements_test.txt index f17ccd220d..a07815df54 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,6 +1,6 @@ pylint==2.17.5 flake8==6.1.0 # also change in .pre-commit-config.yaml when updating -black==23.7.0 # also change in .pre-commit-config.yaml when updating +black==23.9.1 # also change in .pre-commit-config.yaml when updating pyupgrade==3.10.1 # also change in .pre-commit-config.yaml when updating pre-commit From fc354eec0e6377d4faf0dcb7c160da5cc4e76228 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 12 Sep 2023 14:14:10 +1200 Subject: [PATCH 0174/2101] Attempt to fix rp2040 adc with vcc (#5378) --- esphome/components/adc/__init__.py | 9 ++--- esphome/components/adc/adc_sensor.cpp | 55 +++++++++++++-------------- 2 files changed, 30 insertions(+), 34 deletions(-) diff --git a/esphome/components/adc/__init__.py b/esphome/components/adc/__init__.py index 0b6ee145f2..bad5cf74ef 100644 --- a/esphome/components/adc/__init__.py +++ b/esphome/components/adc/__init__.py @@ -5,10 +5,7 @@ from esphome.const import CONF_ANALOG, CONF_INPUT from esphome.core import CORE from esphome.components.esp32 import get_esp32_variant -from esphome.const import ( - PLATFORM_ESP8266, - PLATFORM_RP2040, -) +from esphome.const import PLATFORM_ESP8266 from esphome.components.esp32.const import ( VARIANT_ESP32, VARIANT_ESP32C2, @@ -147,7 +144,9 @@ ESP32_VARIANT_ADC2_PIN_TO_CHANNEL = { def validate_adc_pin(value): if str(value).upper() == "VCC": - return cv.only_on([PLATFORM_ESP8266, PLATFORM_RP2040])("VCC") + if CORE.is_rp2040: + return pins.internal_gpio_input_pin_schema(29) + return cv.only_on([PLATFORM_ESP8266])("VCC") if str(value).upper() == "TEMPERATURE": return cv.only_on_rp2040("TEMPERATURE") diff --git a/esphome/components/adc/adc_sensor.cpp b/esphome/components/adc/adc_sensor.cpp index e69e6b9313..a9ac5a5cfe 100644 --- a/esphome/components/adc/adc_sensor.cpp +++ b/esphome/components/adc/adc_sensor.cpp @@ -1,6 +1,6 @@ #include "adc_sensor.h" -#include "esphome/core/log.h" #include "esphome/core/helpers.h" +#include "esphome/core/log.h" #ifdef USE_ESP8266 #ifdef USE_ADC_SENSOR_VCC @@ -246,45 +246,42 @@ float ADCSensor::sample() { adc_set_temp_sensor_enabled(true); delay(1); adc_select_input(4); + + int32_t raw = adc_read(); + adc_set_temp_sensor_enabled(false); + if (this->output_raw_) { + return raw; + } + return raw * 3.3f / 4096.0f; } else { - uint8_t pin; -#ifdef USE_ADC_SENSOR_VCC + uint8_t pin = this->pin_->get_pin(); #ifdef CYW43_USES_VSYS_PIN - // Measuring VSYS on Raspberry Pico W needs to be wrapped with - // `cyw43_thread_enter()`/`cyw43_thread_exit()` as discussed in - // https://github.com/raspberrypi/pico-sdk/issues/1222, since Wifi chip and - // VSYS ADC both share GPIO29 - cyw43_thread_enter(); + if (pin == PICO_VSYS_PIN) { + // Measuring VSYS on Raspberry Pico W needs to be wrapped with + // `cyw43_thread_enter()`/`cyw43_thread_exit()` as discussed in + // https://github.com/raspberrypi/pico-sdk/issues/1222, since Wifi chip and + // VSYS ADC both share GPIO29 + cyw43_thread_enter(); + } #endif // CYW43_USES_VSYS_PIN - pin = PICO_VSYS_PIN; -#else - pin = this->pin_->get_pin(); -#endif // USE_ADC_SENSOR_VCC adc_gpio_init(pin); adc_select_input(pin - 26); - } - int32_t raw = adc_read(); - if (this->is_temperature_) { - adc_set_temp_sensor_enabled(false); - } else { -#ifdef USE_ADC_SENSOR_VCC + int32_t raw = adc_read(); + #ifdef CYW43_USES_VSYS_PIN - cyw43_thread_exit(); + if (pin == PICO_VSYS_PIN) { + cyw43_thread_exit(); + } #endif // CYW43_USES_VSYS_PIN -#endif // USE_ADC_SENSOR_VCC - } - if (output_raw_) { - return raw; + if (output_raw_) { + return raw; + } + float coeff = pin == PICO_VSYS_PIN ? 3.0 : 1.0; + return raw * 3.3f / 4096.0f * coeff; } - float coeff = 1.0; -#ifdef USE_ADC_SENSOR_VCC - // As per Raspberry Pico (W) datasheet (section 2.1) the VSYS/3 is measured - coeff = 3.0; -#endif // USE_ADC_SENSOR_VCC - return raw * 3.3f / 4096.0f * coeff; } #endif From dadbc1aefa267d1868aa189da6a3ee16bb318674 Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Tue, 12 Sep 2023 22:05:02 +0200 Subject: [PATCH 0175/2101] Enable IPv6 for ESP8266 and Raspberry pi pico w (RP2040) (#4759) --- esphome/components/async_tcp/__init__.py | 2 +- esphome/components/mdns/mdns_esp8266.cpp | 3 +- esphome/components/mqtt/__init__.py | 4 +-- esphome/components/mqtt/mqtt_client.cpp | 10 ------- esphome/components/network/__init__.py | 29 ++++++++++--------- esphome/components/socket/socket.cpp | 2 +- .../wifi/wifi_component_esp8266.cpp | 17 +++++++++-- .../components/wifi/wifi_component_pico_w.cpp | 4 +++ platformio.ini | 4 +-- 9 files changed, 41 insertions(+), 34 deletions(-) diff --git a/esphome/components/async_tcp/__init__.py b/esphome/components/async_tcp/__init__.py index 1677d4b9a8..fa74f7103f 100644 --- a/esphome/components/async_tcp/__init__.py +++ b/esphome/components/async_tcp/__init__.py @@ -19,4 +19,4 @@ async def to_code(config): cg.add_library("esphome/AsyncTCP-esphome", "2.0.1") elif CORE.is_esp8266: # https://github.com/esphome/ESPAsyncTCP - cg.add_library("esphome/ESPAsyncTCP-esphome", "1.2.3") + cg.add_library("esphome/ESPAsyncTCP-esphome", "2.0.0") diff --git a/esphome/components/mdns/mdns_esp8266.cpp b/esphome/components/mdns/mdns_esp8266.cpp index 4ccfe42baa..5ff1b86341 100644 --- a/esphome/components/mdns/mdns_esp8266.cpp +++ b/esphome/components/mdns/mdns_esp8266.cpp @@ -13,8 +13,7 @@ namespace mdns { void MDNSComponent::setup() { this->compile_records_(); - network::IPAddress addr = network::get_ip_address(); - MDNS.begin(this->hostname_.c_str(), (uint32_t) addr); + MDNS.begin(this->hostname_.c_str()); for (const auto &service : this->services_) { // Strip the leading underscore from the proto and service_type. While it is diff --git a/esphome/components/mqtt/__init__.py b/esphome/components/mqtt/__init__.py index 102c070eb6..9df2067832 100644 --- a/esphome/components/mqtt/__init__.py +++ b/esphome/components/mqtt/__init__.py @@ -273,8 +273,8 @@ async def to_code(config): await cg.register_component(var, config) # Add required libraries for ESP8266 if CORE.is_esp8266: - # https://github.com/OttoWinter/async-mqtt-client/blob/master/library.json - cg.add_library("ottowinter/AsyncMqttClient-esphome", "0.8.6") + # https://github.com/heman/async-mqtt-client/blob/master/library.json + cg.add_library("heman/AsyncMqttClient-esphome", "1.0.0") cg.add_define("USE_MQTT") cg.add_global(mqtt_ns.using) diff --git a/esphome/components/mqtt/mqtt_client.cpp b/esphome/components/mqtt/mqtt_client.cpp index 1d804170f6..0c6da42328 100644 --- a/esphome/components/mqtt/mqtt_client.cpp +++ b/esphome/components/mqtt/mqtt_client.cpp @@ -168,15 +168,10 @@ void MQTTClientComponent::start_dnslookup_() { case ERR_OK: { // Got IP immediately this->dns_resolved_ = true; -#ifdef USE_ESP32 #if LWIP_IPV6 this->ip_ = addr.u_addr.ip4.addr; #else this->ip_ = addr.addr; -#endif -#endif -#ifdef USE_ESP8266 - this->ip_ = addr.addr; #endif this->start_connect_(); return; @@ -228,15 +223,10 @@ void MQTTClientComponent::dns_found_callback(const char *name, const ip_addr_t * if (ipaddr == nullptr) { a_this->dns_resolve_error_ = true; } else { -#ifdef USE_ESP32 #if LWIP_IPV6 a_this->ip_ = ipaddr->u_addr.ip4.addr; #else a_this->ip_ = ipaddr->addr; -#endif -#endif // USE_ESP32 -#ifdef USE_ESP8266 - a_this->ip_ = ipaddr->addr; #endif a_this->dns_resolved_ = true; } diff --git a/esphome/components/network/__init__.py b/esphome/components/network/__init__.py index 83778e0bf4..dd1353f86f 100644 --- a/esphome/components/network/__init__.py +++ b/esphome/components/network/__init__.py @@ -15,22 +15,23 @@ IPAddress = network_ns.class_("IPAddress") CONFIG_SCHEMA = cv.Schema( { - cv.SplitDefault(CONF_ENABLE_IPV6, esp32=False): cv.All( - cv.only_on_esp32, cv.boolean - ), + cv.Optional(CONF_ENABLE_IPV6, default=False): cv.boolean, } ) async def to_code(config): - if CONF_ENABLE_IPV6 in config: - cg.add_define("ENABLE_IPV6", config[CONF_ENABLE_IPV6]) - if CORE.using_esp_idf: - add_idf_sdkconfig_option("CONFIG_LWIP_IPV6", config[CONF_ENABLE_IPV6]) - add_idf_sdkconfig_option( - "CONFIG_LWIP_IPV6_AUTOCONFIG", config[CONF_ENABLE_IPV6] - ) - else: - if config[CONF_ENABLE_IPV6]: - cg.add_build_flag("-DCONFIG_LWIP_IPV6") - cg.add_build_flag("-DCONFIG_LWIP_IPV6_AUTOCONFIG") + cg.add_define("ENABLE_IPV6", config[CONF_ENABLE_IPV6]) + if CORE.using_esp_idf: + add_idf_sdkconfig_option("CONFIG_LWIP_IPV6", config[CONF_ENABLE_IPV6]) + add_idf_sdkconfig_option( + "CONFIG_LWIP_IPV6_AUTOCONFIG", config[CONF_ENABLE_IPV6] + ) + else: + if config[CONF_ENABLE_IPV6]: + cg.add_build_flag("-DCONFIG_LWIP_IPV6") + cg.add_build_flag("-DCONFIG_LWIP_IPV6_AUTOCONFIG") + if CORE.is_rp2040: + cg.add_build_flag("-DPIO_FRAMEWORK_ARDUINO_ENABLE_IPV6") + if CORE.is_esp8266: + cg.add_build_flag("-DPIO_FRAMEWORK_ARDUINO_LWIP2_IPV6_LOW_MEMORY") diff --git a/esphome/components/socket/socket.cpp b/esphome/components/socket/socket.cpp index 4c78397873..824e04150b 100644 --- a/esphome/components/socket/socket.cpp +++ b/esphome/components/socket/socket.cpp @@ -60,7 +60,7 @@ socklen_t set_sockaddr_any(struct sockaddr *addr, socklen_t addrlen, uint16_t po memset(server, 0, sizeof(sockaddr_in6)); server->sin6_family = AF_INET6; server->sin6_port = htons(port); - server->sin6_addr = in6addr_any; + server->sin6_addr = IN6ADDR_ANY_INIT; return sizeof(sockaddr_in6); #else if (addrlen < sizeof(sockaddr_in)) { diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index a28aa8b858..1afa439567 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -19,6 +19,7 @@ extern "C" { #include "lwip/apps/sntp.h" #if LWIP_IPV6 #include "lwip/netif.h" // struct netif +#include #endif #if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(3, 0, 0) #include "LwipDhcpServer.h" @@ -164,11 +165,11 @@ bool WiFiComponent::wifi_sta_ip_config_(optional manual_ip) { ip_addr_t dns; if (uint32_t(manual_ip->dns1) != 0) { - dns.addr = static_cast(manual_ip->dns1); + ip_addr_set_ip4_u32_val(dns, static_cast(manual_ip->dns1)); dns_setserver(0, &dns); } if (uint32_t(manual_ip->dns2) != 0) { - dns.addr = static_cast(manual_ip->dns2); + ip_addr_set_ip4_u32_val(dns, static_cast(manual_ip->dns2)); dns_setserver(1, &dns); } @@ -325,6 +326,18 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) { return false; } +#if ENABLE_IPV6 + for (bool configured = false; !configured;) { + for (auto addr : addrList) { + ESP_LOGV(TAG, "Address %s", addr.toString().c_str()); + if ((configured = !addr.isLocal() && addr.isV6())) { + break; + } + } + delay(500); // NOLINT + } +#endif + if (ap.get_channel().has_value()) { ret = wifi_set_channel(*ap.get_channel()); if (!ret) { diff --git a/esphome/components/wifi/wifi_component_pico_w.cpp b/esphome/components/wifi/wifi_component_pico_w.cpp index 489ebc3699..149ca61cd5 100644 --- a/esphome/components/wifi/wifi_component_pico_w.cpp +++ b/esphome/components/wifi/wifi_component_pico_w.cpp @@ -175,7 +175,11 @@ network::IPAddress WiFiComponent::wifi_subnet_mask_() { return {WiFi.subnetMask( network::IPAddress WiFiComponent::wifi_gateway_ip_() { return {WiFi.gatewayIP()}; } network::IPAddress WiFiComponent::wifi_dns_ip_(int num) { const ip_addr_t *dns_ip = dns_getserver(num); +#ifdef PIO_FRAMEWORK_ARDUINO_ENABLE_IPV6 + return {dns_ip->u_addr.ip4.addr}; +#else return {dns_ip->addr}; +#endif } void WiFiComponent::wifi_loop_() { diff --git a/platformio.ini b/platformio.ini index aea164353d..73cd7c65c8 100644 --- a/platformio.ini +++ b/platformio.ini @@ -57,6 +57,7 @@ lib_deps = ${common.lib_deps} SPI ; spi (Arduino built-in) Wire ; i2c (Arduino built-int) + heman/AsyncMqttClient-esphome@1.0.0 ; mqtt esphome/ESPAsyncWebServer-esphome@2.1.0 ; web_server_base fastled/FastLED@3.3.2 ; fastled_base mikalhart/TinyGPSPlus@1.0.2 ; gps @@ -88,8 +89,7 @@ lib_deps = ${common:arduino.lib_deps} ESP8266WiFi ; wifi (Arduino built-in) Update ; ota (Arduino built-in) - ottowinter/AsyncMqttClient-esphome@0.8.6 ; mqtt - esphome/ESPAsyncTCP-esphome@1.2.3 ; async_tcp + esphome/ESPAsyncTCP-esphome@2.0.0 ; async_tcp ESP8266HTTPClient ; http_request (Arduino built-in) ESP8266mDNS ; mdns (Arduino built-in) DNSServer ; captive_portal (Arduino built-in) From bff74af882d52e515798284b70ea4b5e3d9b16b4 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 13 Sep 2023 10:06:32 +1200 Subject: [PATCH 0176/2101] Workflow updates (#5384) --- .github/actions/restore-python/action.yml | 4 +-- .github/workflows/ci-docker.yml | 8 ++--- .github/workflows/ci.yml | 38 +++++++++-------------- .github/workflows/lock.yml | 2 +- .github/workflows/release.yml | 22 ++++++------- .github/workflows/stale.yml | 4 +-- .github/workflows/sync-device-classes.yml | 11 +++---- .github/workflows/yaml-lint.yml | 22 +++++++++++++ 8 files changed, 62 insertions(+), 49 deletions(-) create mode 100644 .github/workflows/yaml-lint.yml diff --git a/.github/actions/restore-python/action.yml b/.github/actions/restore-python/action.yml index c6e9ca4153..aa8dd6d894 100644 --- a/.github/actions/restore-python/action.yml +++ b/.github/actions/restore-python/action.yml @@ -17,12 +17,12 @@ runs: steps: - name: Set up Python ${{ inputs.python-version }} id: python - uses: actions/setup-python@v4.6.0 + uses: actions/setup-python@v4.7.0 with: python-version: ${{ inputs.python-version }} - name: Restore Python virtual environment id: cache-venv - uses: actions/cache/restore@v3.3.1 + uses: actions/cache/restore@v3.3.2 with: path: venv # yamllint disable-line rule:line-length diff --git a/.github/workflows/ci-docker.yml b/.github/workflows/ci-docker.yml index dbd0d573da..b53eaf8e1a 100644 --- a/.github/workflows/ci-docker.yml +++ b/.github/workflows/ci-docker.yml @@ -40,15 +40,15 @@ jobs: arch: [amd64, armv7, aarch64] build_type: ["ha-addon", "docker", "lint"] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v4.0.0 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v4.7.0 with: python-version: "3.9" - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v3.0.0 - name: Set up QEMU - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@v3.0.0 - name: Set TAG run: | diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 79ebe8782e..0786e1b9a2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,6 +7,10 @@ on: branches: [dev, beta, release] pull_request: + paths: + - "**" + - "!.github/workflows/*.yml" + - ".github/workflows/ci.yml" merge_group: permissions: @@ -30,13 +34,13 @@ jobs: cache-key: ${{ steps.cache-key.outputs.key }} steps: - name: Check out code from GitHub - uses: actions/checkout@v4 + uses: actions/checkout@v4.0.0 - name: Generate cache-key id: cache-key run: echo key="${{ hashFiles('requirements.txt', 'requirements_optional.txt', 'requirements_test.txt') }}" >> $GITHUB_OUTPUT - name: Set up Python ${{ env.DEFAULT_PYTHON }} id: python - uses: actions/setup-python@v4.6.0 + uses: actions/setup-python@v4.7.0 with: python-version: ${{ env.DEFAULT_PYTHON }} - name: Restore Python virtual environment @@ -55,15 +59,6 @@ jobs: pip install -r requirements.txt -r requirements_optional.txt -r requirements_test.txt pip install -e . - yamllint: - name: yamllint - runs-on: ubuntu-latest - steps: - - name: Check out code from GitHub - uses: actions/checkout@v4 - - name: Run yamllint - uses: frenck/action-yamllint@v1.4.1 - black: name: Check black runs-on: ubuntu-latest @@ -71,7 +66,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4 + uses: actions/checkout@v4.0.0 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -92,7 +87,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4 + uses: actions/checkout@v4.0.0 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -113,7 +108,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4 + uses: actions/checkout@v4.0.0 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -134,7 +129,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4 + uses: actions/checkout@v4.0.0 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -155,7 +150,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4 + uses: actions/checkout@v4.0.0 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -176,7 +171,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4 + uses: actions/checkout@v4.0.0 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -196,7 +191,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4 + uses: actions/checkout@v4.0.0 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -227,7 +222,6 @@ jobs: - pylint - pytest - pyupgrade - - yamllint strategy: fail-fast: false max-parallel: 2 @@ -235,7 +229,7 @@ jobs: file: [1, 2, 3, 3.1, 4, 5, 6, 7, 8, 10] steps: - name: Check out code from GitHub - uses: actions/checkout@v4 + uses: actions/checkout@v4.0.0 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -258,7 +252,6 @@ jobs: - pylint - pytest - pyupgrade - - yamllint strategy: fail-fast: false max-parallel: 2 @@ -291,7 +284,7 @@ jobs: steps: - name: Check out code from GitHub - uses: actions/checkout@v4 + uses: actions/checkout@v4.0.0 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -337,7 +330,6 @@ jobs: - pylint - pytest - pyupgrade - - yamllint - compile-tests - clang-tidy if: always() diff --git a/.github/workflows/lock.yml b/.github/workflows/lock.yml index e762512ff6..b455e3f4ea 100644 --- a/.github/workflows/lock.yml +++ b/.github/workflows/lock.yml @@ -18,7 +18,7 @@ jobs: lock: runs-on: ubuntu-latest steps: - - uses: dessant/lock-threads@v4 + - uses: dessant/lock-threads@v4.0.1 with: pr-inactive-days: "1" pr-lock-reason: "" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 71a0cd2c78..99d1594f03 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,7 +19,7 @@ jobs: outputs: tag: ${{ steps.tag.outputs.tag }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v4.0.0 - name: Get tag id: tag # yamllint disable rule:line-length @@ -43,9 +43,9 @@ jobs: if: github.repository == 'esphome/esphome' && github.event_name == 'release' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v4.0.0 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v4.7.0 with: python-version: "3.x" - name: Set up python environment @@ -88,24 +88,24 @@ jobs: target: "lint" baseimg: "docker" steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v4.0.0 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v4.7.0 with: python-version: "3.9" - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v3.0.0 - name: Set up QEMU - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@v3.0.0 - name: Log in to docker hub - uses: docker/login-action@v2 + uses: docker/login-action@v3.0.0 with: username: ${{ secrets.DOCKER_USER }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Log in to the GitHub container registry - uses: docker/login-action@v2 + uses: docker/login-action@v3.0.0 with: registry: ghcr.io username: ${{ github.actor }} @@ -119,7 +119,7 @@ jobs: --suffix "${{ matrix.image.suffix }}" - name: Build and push - uses: docker/build-push-action@v4 + uses: docker/build-push-action@v5.0.0 with: context: . file: ./docker/Dockerfile @@ -141,7 +141,7 @@ jobs: needs: [deploy-docker] steps: - name: Trigger Workflow - uses: actions/github-script@v6 + uses: actions/github-script@v6.4.1 with: github-token: ${{ secrets.DEPLOY_HA_ADDON_REPO_TOKEN }} script: | diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 3a3e390eef..a2d3f2f77d 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -18,7 +18,7 @@ jobs: stale: runs-on: ubuntu-latest steps: - - uses: actions/stale@v8 + - uses: actions/stale@v8.0.0 with: days-before-pr-stale: 90 days-before-pr-close: 7 @@ -38,7 +38,7 @@ jobs: close-issues: runs-on: ubuntu-latest steps: - - uses: actions/stale@v8 + - uses: actions/stale@v8.0.0 with: days-before-pr-stale: -1 days-before-pr-close: -1 diff --git a/.github/workflows/sync-device-classes.yml b/.github/workflows/sync-device-classes.yml index 1759db962c..943e93a0b7 100644 --- a/.github/workflows/sync-device-classes.yml +++ b/.github/workflows/sync-device-classes.yml @@ -4,8 +4,7 @@ name: Synchronise Device Classes from Home Assistant on: workflow_dispatch: schedule: - - cron: '45 6 * * *' - + - cron: "45 6 * * *" jobs: sync: @@ -14,16 +13,16 @@ jobs: if: github.repository == 'esphome/esphome' steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v4.0.0 - name: Checkout Home Assistant - uses: actions/checkout@v4 + uses: actions/checkout@v4.0.0 with: repository: home-assistant/core path: lib/home-assistant - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v4.7.0 with: python-version: 3.11 @@ -37,7 +36,7 @@ jobs: python ./script/sync-device_class.py - name: Commit changes - uses: peter-evans/create-pull-request@v5 + uses: peter-evans/create-pull-request@v5.0.2 with: commit-message: "Synchronise Device Classes from Home Assistant" committer: esphomebot diff --git a/.github/workflows/yaml-lint.yml b/.github/workflows/yaml-lint.yml new file mode 100644 index 0000000000..77b3c1dcb5 --- /dev/null +++ b/.github/workflows/yaml-lint.yml @@ -0,0 +1,22 @@ +name: YAML lint + +on: + push: + branches: [dev, beta, release] + paths: + - "**.yaml" + - "**.yml" + pull_request: + paths: + - "**.yaml" + - "**.yml" + +jobs: + yamllint: + name: yamllint + runs-on: ubuntu-latest + steps: + - name: Check out code from GitHub + uses: actions/checkout@v4.0.0 + - name: Run yamllint + uses: frenck/action-yamllint@v1.4.1 From bf5352b44ee84f6880935fcc011be4df7edf4863 Mon Sep 17 00:00:00 2001 From: Tercio Filho Date: Tue, 12 Sep 2023 19:15:01 -0300 Subject: [PATCH 0177/2101] Modbus Controller added some features (#5318) --- .../components/modbus_controller/__init__.py | 5 +++- esphome/components/modbus_controller/const.py | 1 + .../modbus_controller/modbus_controller.cpp | 23 +++++++++++++++++++ .../modbus_controller/modbus_controller.h | 13 ++++++++--- 4 files changed, 38 insertions(+), 4 deletions(-) diff --git a/esphome/components/modbus_controller/__init__.py b/esphome/components/modbus_controller/__init__.py index 46bb2c4233..8703771c3a 100644 --- a/esphome/components/modbus_controller/__init__.py +++ b/esphome/components/modbus_controller/__init__.py @@ -8,6 +8,7 @@ from .const import ( CONF_BITMASK, CONF_BYTE_OFFSET, CONF_COMMAND_THROTTLE, + CONF_OFFLINE_SKIP_UPDATES, CONF_CUSTOM_COMMAND, CONF_FORCE_NEW_RANGE, CONF_MODBUS_CONTROLLER_ID, @@ -104,6 +105,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional( CONF_COMMAND_THROTTLE, default="0ms" ): cv.positive_time_period_milliseconds, + cv.Optional(CONF_OFFLINE_SKIP_UPDATES, default=0): cv.positive_int, } ) .extend(cv.polling_component_schema("60s")) @@ -206,8 +208,9 @@ async def add_modbus_base_properties( async def to_code(config): - var = cg.new_Pvariable(config[CONF_ID], config[CONF_COMMAND_THROTTLE]) + var = cg.new_Pvariable(config[CONF_ID]) cg.add(var.set_command_throttle(config[CONF_COMMAND_THROTTLE])) + cg.add(var.set_offline_skip_updates(config[CONF_OFFLINE_SKIP_UPDATES])) await register_modbus_device(var, config) diff --git a/esphome/components/modbus_controller/const.py b/esphome/components/modbus_controller/const.py index baf72efb94..1a23640e17 100644 --- a/esphome/components/modbus_controller/const.py +++ b/esphome/components/modbus_controller/const.py @@ -1,6 +1,7 @@ CONF_BITMASK = "bitmask" CONF_BYTE_OFFSET = "byte_offset" CONF_COMMAND_THROTTLE = "command_throttle" +CONF_OFFLINE_SKIP_UPDATES = "offline_skip_updates" CONF_CUSTOM_COMMAND = "custom_command" CONF_FORCE_NEW_RANGE = "force_new_range" CONF_MODBUS_CONTROLLER_ID = "modbus_controller_id" diff --git a/esphome/components/modbus_controller/modbus_controller.cpp b/esphome/components/modbus_controller/modbus_controller.cpp index 79c13e3f68..7565dc5e1b 100644 --- a/esphome/components/modbus_controller/modbus_controller.cpp +++ b/esphome/components/modbus_controller/modbus_controller.cpp @@ -26,6 +26,17 @@ bool ModbusController::send_next_command_() { // remove from queue if command was sent too often if (command->send_countdown < 1) { + if (!this->module_offline_) { + ESP_LOGW(TAG, "Modbus device=%d set offline", this->address_); + + if (this->offline_skip_updates_ > 0) { + // Update skip_updates_counter to stop flooding channel with timeouts + for (auto &r : this->register_ranges_) { + r.skip_updates_counter = this->offline_skip_updates_; + } + } + } + this->module_offline_ = true; ESP_LOGD( TAG, "Modbus command to device=%d register=0x%02X countdown=%d no response received - removed from send queue", @@ -49,6 +60,18 @@ bool ModbusController::send_next_command_() { void ModbusController::on_modbus_data(const std::vector &data) { auto ¤t_command = this->command_queue_.front(); if (current_command != nullptr) { + if (this->module_offline_) { + ESP_LOGW(TAG, "Modbus device=%d back online", this->address_); + + if (this->offline_skip_updates_ > 0) { + // Restore skip_updates_counter to restore commands updates + for (auto &r : this->register_ranges_) { + r.skip_updates_counter = 0; + } + } + } + this->module_offline_ = false; + // Move the commandItem to the response queue current_command->payload = data; this->incoming_queue_.push(std::move(current_command)); diff --git a/esphome/components/modbus_controller/modbus_controller.h b/esphome/components/modbus_controller/modbus_controller.h index ccb0edf9c6..a389375523 100644 --- a/esphome/components/modbus_controller/modbus_controller.h +++ b/esphome/components/modbus_controller/modbus_controller.h @@ -409,7 +409,6 @@ class ModbusCommandItem { class ModbusController : public PollingComponent, public modbus::ModbusDevice { public: - ModbusController(uint16_t throttle = 0) : command_throttle_(throttle){}; void dump_config() override; void loop() override; void setup() override; @@ -431,6 +430,12 @@ class ModbusController : public PollingComponent, public modbus::ModbusDevice { const std::vector &data); /// called by esphome generated code to set the command_throttle period void set_command_throttle(uint16_t command_throttle) { this->command_throttle_ = command_throttle; } + /// called by esphome generated code to set the offline_skip_updates + void set_offline_skip_updates(uint16_t offline_skip_updates) { this->offline_skip_updates_ = offline_skip_updates; } + /// get the number of queued modbus commands (should be mostly empty) + size_t get_command_queue_length() { return command_queue_.size(); } + /// get if the module is offline, didn't respond the last command + bool get_module_offline() { return module_offline_; } protected: /// parse sensormap_ and create range of sequential addresses @@ -443,8 +448,6 @@ class ModbusController : public PollingComponent, public modbus::ModbusDevice { void process_modbus_data_(const ModbusCommandItem *response); /// send the next modbus command from the send queue bool send_next_command_(); - /// get the number of queued modbus commands (should be mostly empty) - size_t get_command_queue_length_() { return command_queue_.size(); } /// dump the parsed sensormap for diagnostics void dump_sensors_(); /// Collection of all sensors for this component @@ -459,6 +462,10 @@ class ModbusController : public PollingComponent, public modbus::ModbusDevice { uint32_t last_command_timestamp_; /// min time in ms between sending modbus commands uint16_t command_throttle_; + /// if module didn't respond the last command + bool module_offline_; + /// how many updates to skip if module is offline + uint16_t offline_skip_updates_; }; /** Convert vector response payload to float. From b8fa737bc956577e7b2635af7f60b43633613a58 Mon Sep 17 00:00:00 2001 From: rufuswilson Date: Wed, 13 Sep 2023 00:20:00 +0200 Subject: [PATCH 0178/2101] Force heater off on setup (#5161) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/sht3xd/sensor.py | 7 ++++++- esphome/components/sht3xd/sht3xd.cpp | 4 ++++ esphome/components/sht3xd/sht3xd.h | 2 ++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/esphome/components/sht3xd/sensor.py b/esphome/components/sht3xd/sensor.py index 8e1ef426ad..5c73a63f1a 100644 --- a/esphome/components/sht3xd/sensor.py +++ b/esphome/components/sht3xd/sensor.py @@ -12,6 +12,8 @@ from esphome.const import ( UNIT_PERCENT, ) +CONF_HEATER_ENABLED = "heater_enabled" + DEPENDENCIES = ["i2c"] AUTO_LOAD = ["sensirion_common"] @@ -36,7 +38,8 @@ CONFIG_SCHEMA = ( device_class=DEVICE_CLASS_HUMIDITY, state_class=STATE_CLASS_MEASUREMENT, ), - } + cv.Optional(CONF_HEATER_ENABLED, default=True): cv.boolean, + }, ) .extend(cv.polling_component_schema("60s")) .extend(i2c.i2c_device_schema(0x44)) @@ -48,6 +51,8 @@ async def to_code(config): await cg.register_component(var, config) await i2c.register_i2c_device(var, config) + cg.add(var.set_heater_enabled(config[CONF_HEATER_ENABLED])) + if CONF_TEMPERATURE in config: sens = await sensor.new_sensor(config[CONF_TEMPERATURE]) cg.add(var.set_temperature_sensor(sens)) diff --git a/esphome/components/sht3xd/sht3xd.cpp b/esphome/components/sht3xd/sht3xd.cpp index 4e1c9742bc..f4bd2da271 100644 --- a/esphome/components/sht3xd/sht3xd.cpp +++ b/esphome/components/sht3xd/sht3xd.cpp @@ -22,6 +22,10 @@ void SHT3XDComponent::setup() { this->mark_failed(); return; } + if (!this->write_command(heater_enabled_ ? SHT3XD_COMMAND_HEATER_ENABLE : SHT3XD_COMMAND_HEATER_DISABLE)) { + this->mark_failed(); + return; + } uint32_t serial_number = (uint32_t(raw_serial_number[0]) << 16) | uint32_t(raw_serial_number[1]); ESP_LOGV(TAG, " Serial Number: 0x%08X", serial_number); } diff --git a/esphome/components/sht3xd/sht3xd.h b/esphome/components/sht3xd/sht3xd.h index 41ca3c5d6e..04023c8a46 100644 --- a/esphome/components/sht3xd/sht3xd.h +++ b/esphome/components/sht3xd/sht3xd.h @@ -17,10 +17,12 @@ class SHT3XDComponent : public PollingComponent, public sensirion_common::Sensir void dump_config() override; float get_setup_priority() const override; void update() override; + void set_heater_enabled(bool heater_enabled) { heater_enabled_ = heater_enabled; } protected: sensor::Sensor *temperature_sensor_{nullptr}; sensor::Sensor *humidity_sensor_{nullptr}; + bool heater_enabled_{true}; }; } // namespace sht3xd From 736dbfac135e368f8c6ee0be2701597ec59ad3ef Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Tue, 12 Sep 2023 18:36:17 -0500 Subject: [PATCH 0179/2101] Add IDF 5 test yaml, add adc to IDF tests, fix adc for IDF 5 (#5379) --- .github/workflows/ci.yml | 2 +- esphome/components/adc/adc_sensor.h | 4 + tests/test11.5.yaml | 697 ++++++++++++++++++++++++++++ tests/test5.yaml | 6 + 4 files changed, 708 insertions(+), 1 deletion(-) create mode 100644 tests/test11.5.yaml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0786e1b9a2..4e4e6c0ece 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -226,7 +226,7 @@ jobs: fail-fast: false max-parallel: 2 matrix: - file: [1, 2, 3, 3.1, 4, 5, 6, 7, 8, 10] + file: [1, 2, 3, 3.1, 4, 5, 6, 7, 8, 10, 11.5] steps: - name: Check out code from GitHub uses: actions/checkout@v4.0.0 diff --git a/esphome/components/adc/adc_sensor.h b/esphome/components/adc/adc_sensor.h index 7d9c8959da..b1fdcd5d29 100644 --- a/esphome/components/adc/adc_sensor.h +++ b/esphome/components/adc/adc_sensor.h @@ -62,8 +62,12 @@ class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage adc1_channel_t channel1_{ADC1_CHANNEL_MAX}; adc2_channel_t channel2_{ADC2_CHANNEL_MAX}; bool autorange_{false}; +#if ESP_IDF_VERSION_MAJOR >= 5 + esp_adc_cal_characteristics_t cal_characteristics_[SOC_ADC_ATTEN_NUM] = {}; +#else esp_adc_cal_characteristics_t cal_characteristics_[ADC_ATTEN_MAX] = {}; #endif +#endif }; } // namespace adc diff --git a/tests/test11.5.yaml b/tests/test11.5.yaml new file mode 100644 index 0000000000..544dc10930 --- /dev/null +++ b/tests/test11.5.yaml @@ -0,0 +1,697 @@ +--- +# copy of test5.yaml configured to build on IDF 5 +esphome: + name: test11-5 + build_path: build/test11.5 + project: + name: esphome.test11_5_project + version: "1.0.0" + +esp32: + board: nodemcu-32s + framework: + type: esp-idf + version: 5.0.2 + platform_version: 6.3.2 + advanced: + ignore_efuse_mac_crc: true + +wifi: + networks: + - ssid: "MySSID" + password: "password1" + manual_ip: + static_ip: 192.168.1.23 + gateway: 192.168.1.1 + subnet: 255.255.255.0 + +api: + +ota: + +logger: + +debug: + +psram: + +uart: + - id: uart_1 + tx_pin: 1 + rx_pin: 3 + baud_rate: 9600 + - id: uart_2 + tx_pin: 17 + rx_pin: 16 + baud_rate: 19200 + +i2c: + frequency: 100khz + +modbus: + uart_id: uart_1 + flow_control_pin: 5 + id: mod_bus1 + +modbus_controller: + - id: modbus_controller_test + address: 0x2 + modbus_id: mod_bus1 + +mqtt: + broker: test.mosquitto.org + port: 1883 + discovery: true + discovery_prefix: homeassistant + idf_send_async: false + on_message: + topic: testing/sensor/testing_sensor/state + qos: 0 + then: + # yamllint disable rule:line-length + - lambda: |- + ESP_LOGD("Mqtt Test", "testing/sensor/testing_sensor/state=[%s]", x.c_str()); + # yamllint enable rule:line-length + +vbus: + - uart_id: uart_2 + +binary_sensor: + - platform: gpio + pin: GPIO0 + id: io0_button + icon: mdi:gesture-tap-button + + - platform: modbus_controller + modbus_controller_id: modbus_controller_test + id: modbus_binsensortest + register_type: read + address: 0x3200 + bitmask: 0x80 # (bit 8) + lambda: "return x;" + + - platform: tm1638 + id: Button0 + key: 0 + filters: + - delayed_on: 10ms + on_press: + then: + - switch.turn_on: Led0 + on_release: + then: + - switch.turn_off: Led0 + + - platform: tm1638 + id: Button1 + key: 1 + on_press: + then: + - switch.turn_on: Led1 + on_release: + then: + - switch.turn_off: Led1 + + - platform: tm1638 + id: Button2 + key: 2 + on_press: + then: + - switch.turn_on: Led2 + on_release: + then: + - switch.turn_off: Led2 + + - platform: tm1638 + id: Button3 + key: 3 + on_press: + then: + - switch.turn_on: Led3 + on_release: + then: + - switch.turn_off: Led3 + + - platform: tm1638 + id: Button4 + key: 4 + on_press: + then: + - output.turn_on: Led4 + on_release: + then: + - output.turn_off: Led4 + + - platform: tm1638 + id: Button5 + key: 5 + on_press: + then: + - output.turn_on: Led5 + on_release: + then: + - output.turn_off: Led5 + + - platform: tm1638 + id: Button6 + key: 6 + on_press: + then: + - output.turn_on: Led6 + on_release: + then: + - output.turn_off: Led6 + + - platform: tm1638 + id: Button7 + key: 7 + on_press: + then: + - output.turn_on: Led7 + on_release: + then: + - output.turn_off: Led7 + + - platform: gpio + id: sn74hc165_pin_0 + pin: + sn74hc165: sn74hc165_hub + number: 0 + + - platform: ezo_pmp + pump_state: + name: "Pump State" + is_paused: + name: "Is Paused" + + - platform: matrix_keypad + keypad_id: keypad + id: key4 + row: 1 + col: 1 + - platform: matrix_keypad + id: key1 + key: 1 + + - platform: vbus + model: deltasol_bs_plus + relay2: + name: Relay 2 On + sensor1_error: + name: Sensor 1 Error + + - platform: vbus + model: custom + command: 0x100 + source: 0x1234 + dest: 0x10 + binary_sensors: + - id: vcustom_b + name: VBus Custom Binary Sensor + lambda: return x[0] & 1; + +tlc5947: + data_pin: GPIO12 + clock_pin: GPIO14 + lat_pin: GPIO15 + +gp8403: + - id: gp8403_5v + voltage: 5V + - id: gp8403_10v + voltage: 10V + +output: + - platform: gpio + pin: GPIO2 + id: built_in_led + + - platform: tlc5947 + id: output_red + channel: 0 + max_power: 0.8 + + - platform: mcp47a1 + id: output_mcp47a1 + + - platform: modbus_controller + modbus_controller_id: modbus_controller_test + id: modbus_output_test + lambda: |- + return x * 1.0 ; + address: 0x9001 + value_type: U_WORD + + - platform: tm1638 + id: Led4 + led: 4 + + - platform: tm1638 + id: Led5 + led: 5 + + - platform: tm1638 + id: Led6 + led: 6 + + - platform: tm1638 + id: Led7 + led: 7 + + - platform: gp8403 + id: gp8403_output_0 + gp8403_id: gp8403_5v + channel: 0 + - platform: gp8403 + gp8403_id: gp8403_10v + id: gp8403_output_1 + channel: 1 + +demo: + +esp32_ble: + +esp32_ble_server: + manufacturer: ESPHome + model: Test11 + +esp32_improv: + authorizer: io0_button + authorized_duration: 1min + status_indicator: built_in_led + +ezo_pmp: + id: hcl_pump + update_interval: 1s + +number: + - platform: template + name: My template number + id: template_number_id + optimistic: true + max_value: 100 + min_value: 0 + step: 5 + unit_of_measurement: "%" + mode: slider + device_class: humidity + on_value: + - logger.log: + format: Number changed to %f + args: [x] + set_action: + - logger.log: + format: Template Number set to %f + args: [x] + - number.set: + id: template_number_id + value: 50 + - number.to_min: template_number_id + - number.to_min: + id: template_number_id + - number.to_max: template_number_id + - number.to_max: + id: template_number_id + - number.increment: template_number_id + - number.increment: + id: template_number_id + cycle: false + - number.decrement: template_number_id + - number.decrement: + id: template_number_id + cycle: false + - number.operation: + id: template_number_id + operation: Increment + cycle: false + - number.operation: + id: template_number_id + operation: !lambda "return NUMBER_OP_INCREMENT;" + cycle: !lambda "return false;" + + - id: modbus_numbertest + platform: modbus_controller + modbus_controller_id: modbus_controller_test + name: ModbusNumber + address: 0x9002 + value_type: U_WORD + lambda: "return x * 1.0;" + write_lambda: |- + return x * 1.0 ; + multiply: 1.0 + +select: + - platform: template + name: My template select + id: template_select_id + optimistic: true + initial_option: two + restore_value: true + on_value: + - logger.log: + format: Select changed to %s (index %d)" + args: ["x.c_str()", "i"] + set_action: + - logger.log: + format: Template Select set to %s + args: ["x.c_str()"] + - select.set: + id: template_select_id + option: two + - select.first: template_select_id + - select.last: + id: template_select_id + - select.previous: template_select_id + - select.next: + id: template_select_id + cycle: false + - select.operation: + id: template_select_id + operation: Previous + cycle: false + - select.operation: + id: template_select_id + operation: !lambda "return SELECT_OP_PREVIOUS;" + cycle: !lambda "return true;" + - select.set_index: + id: template_select_id + index: 1 + - select.set_index: + id: template_select_id + index: !lambda "return 1 + 1;" + options: + - one + - two + - three + + - platform: modbus_controller + name: Modbus Select Register 1000 + address: 1000 + value_type: U_WORD + optionsmap: + "Zero": 0 + "One": 1 + "Two": 2 + "Three": 3 + +sensor: + - platform: adc + id: adc_sensor_p32 + name: ADC pin 32 + pin: 32 + attenuation: 11db + update_interval: 1s + - platform: internal_temperature + name: Internal Temperature + - platform: selec_meter + total_active_energy: + name: SelecEM2M Total Active Energy + import_active_energy: + name: SelecEM2M Import Active Energy + export_active_energy: + name: SelecEM2M Export Active Energy + total_reactive_energy: + name: SelecEM2M Total Reactive Energy + import_reactive_energy: + name: SelecEM2M Import Reactive Energy + export_reactive_energy: + name: SelecEM2M Export Reactive Energy + apparent_energy: + name: SelecEM2M Apparent Energy + active_power: + name: SelecEM2M Active Power + reactive_power: + name: SelecEM2M Reactive Power + apparent_power: + name: SelecEM2M Apparent Power + voltage: + name: SelecEM2M Voltage + current: + name: SelecEM2M Current + power_factor: + name: SelecEM2M Power Factor + frequency: + name: SelecEM2M Frequency + maximum_demand_active_power: + name: SelecEM2M Maximum Demand Active Power + disabled_by_default: true + maximum_demand_reactive_power: + name: SelecEM2M Maximum Demand Reactive Power + disabled_by_default: true + maximum_demand_apparent_power: + name: SelecEM2M Maximum Demand Apparent Power + disabled_by_default: true + + - id: modbus_sensortest + platform: modbus_controller + modbus_controller_id: modbus_controller_test + address: 0x331A + register_type: read + value_type: U_WORD + + - platform: t6615 + uart_id: uart_2 + co2: + name: CO2 Sensor + + - platform: bmp3xx + temperature: + name: BMP Temperature + oversampling: 16x + pressure: + name: BMP Pressure + address: 0x77 + iir_filter: 2X + + - platform: sen5x + id: sen54 + 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 + algorithm_tuning: + index_offset: 100 + learning_time_offset_hours: 12 + learning_time_gain_hours: 12 + gating_max_duration_minutes: 180 + std_initial: 50 + gain_factor: 230 + temperature_compensation: + offset: 0 + normalized_offset_slope: 0 + time_constant: 0 + auto_cleaning_interval: 604800s + acceleration_mode: low + store_baseline: true + address: 0x69 + - platform: mcp9600 + thermocouple_type: K + hot_junction: + name: Thermocouple Temperature + cold_junction: + name: Ambient Temperature + + - platform: ezo_pmp + current_volume_dosed: + name: Current Volume Dosed + total_volume_dosed: + name: Total Volume Dosed + absolute_total_volume_dosed: + name: Absolute Total Volume Dosed + pump_voltage: + name: Pump Voltage + last_volume_requested: + name: Last Volume Requested + max_flow_rate: + name: Max Flow Rate + + - platform: vbus + model: deltasol c + temperature_3: + name: Temperature 3 + operating_hours_1: + name: Operating Hours 1 + heat_quantity: + name: Heat Quantity + time: + name: System Time + + - platform: debug + free: + name: "Heap Free" + block: + name: "Heap Max Block" + loop_time: + name: "Loop Time" + psram: + name: "PSRAM Free" + + - platform: vbus + model: custom + command: 0x100 + source: 0x1234 + dest: 0x10 + sensors: + - id: vcustom + name: VBus Custom Sensor + lambda: return x[0] / 10.0; + + - platform: kuntze + ph: + name: Kuntze pH + temperature: + name: Kuntze temperature + +script: + - id: automation_test + then: + - repeat: + count: 5 + then: + - logger.log: looping! + + - id: zero_repeat_test + then: + - repeat: + count: !lambda "return 0;" + then: + - logger.log: shouldn't see mee! + +switch: + - platform: modbus_controller + modbus_controller_id: modbus_controller_test + id: modbus_switch_test + register_type: coil + address: 2 + bitmask: 1 + + - platform: tm1638 + id: Led0 + led: 0 + name: TM1638Led0 + + - platform: tm1638 + id: Led1 + led: 1 + name: TM1638Led1 + + - platform: tm1638 + id: Led2 + led: 2 + name: TM1638Led2 + + - platform: tm1638 + id: Led3 + led: 3 + name: TM1638Led3 + +display: + - platform: tm1638 + id: primarydisplay + stb_pin: 5 #TM1638 STB + clk_pin: 18 #TM1638 CLK + dio_pin: 23 #TM1638 DIO + update_interval: 5s + intensity: 5 + lambda: |- + it.print("81818181"); + +time: + - platform: pcf85063 + - platform: pcf8563 + +text_sensor: + - platform: ezo_pmp + dosing_mode: + name: Dosing Mode + calibration_status: + name: Calibration Status + on_value: + - ezo_pmp.dose_volume: + id: hcl_pump + volume: 10 + - ezo_pmp.dose_volume_over_time: + id: hcl_pump + volume: 10 + duration: 2 + - ezo_pmp.dose_with_constant_flow_rate: + id: hcl_pump + volume_per_minute: 10 + duration: 2 + - ezo_pmp.set_calibration_volume: + id: hcl_pump + volume: 10 + - ezo_pmp.find: hcl_pump + - ezo_pmp.dose_continuously: hcl_pump + - ezo_pmp.clear_total_volume_dosed: hcl_pump + - ezo_pmp.clear_calibration: hcl_pump + - ezo_pmp.pause_dosing: hcl_pump + - ezo_pmp.stop_dosing: hcl_pump + - ezo_pmp.arbitrary_command: + id: hcl_pump + command: D,? + +sn74hc165: + id: sn74hc165_hub + data_pin: GPIO12 + clock_pin: GPIO14 + load_pin: GPIO27 + clock_inhibit_pin: GPIO26 + sr_count: 4 + +matrix_keypad: + id: keypad + rows: + - pin: 21 + - pin: 19 + columns: + - pin: 17 + - pin: 16 + keys: "1234" + +key_collector: + - id: reader + source_id: keypad + min_length: 4 + max_length: 4 + +light: + - platform: esp32_rmt_led_strip + id: led_strip + pin: 13 + num_leds: 60 + rmt_channel: 6 + rgb_order: GRB + chipset: ws2812 + - platform: esp32_rmt_led_strip + id: led_strip2 + pin: 15 + num_leds: 60 + rmt_channel: 2 + rgb_order: RGB + bit0_high: 100us + bit0_low: 100us + bit1_high: 100us + bit1_low: 100us diff --git a/tests/test5.yaml b/tests/test5.yaml index 417f3bfecd..274570aad6 100644 --- a/tests/test5.yaml +++ b/tests/test5.yaml @@ -392,6 +392,12 @@ select: "Three": 3 sensor: + - platform: adc + id: adc_sensor_p32 + name: ADC pin 32 + pin: 32 + attenuation: 11db + update_interval: 1s - platform: internal_temperature name: Internal Temperature - platform: selec_meter From 68a2c45edf01e426f26350693d91669696481ab1 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 13 Sep 2023 13:05:06 +1200 Subject: [PATCH 0180/2101] Bump version to 2023.9.0b1 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index bbc6e71885..cbb31e0ec6 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2023.9.0-dev" +__version__ = "2023.9.0b1" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 11433c8c178df6604788f91aceeeb99755befe0c Mon Sep 17 00:00:00 2001 From: vr6racer <12117307+vr6racer@users.noreply.github.com> Date: Wed, 13 Sep 2023 03:14:54 +0100 Subject: [PATCH 0181/2101] SX1509 component (#5385) --- esphome/components/sx1509/binary_sensor/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/sx1509/binary_sensor/__init__.py b/esphome/components/sx1509/binary_sensor/__init__.py index bbf0e5d0bc..fa620fa202 100644 --- a/esphome/components/sx1509/binary_sensor/__init__.py +++ b/esphome/components/sx1509/binary_sensor/__init__.py @@ -14,8 +14,8 @@ SX1509BinarySensor = sx1509_ns.class_("SX1509BinarySensor", binary_sensor.Binary CONFIG_SCHEMA = binary_sensor.binary_sensor_schema(SX1509BinarySensor).extend( { cv.GenerateID(CONF_SX1509_ID): cv.use_id(SX1509Component), - cv.Required(CONF_ROW): cv.int_range(min=0, max=4), - cv.Required(CONF_COL): cv.int_range(min=0, max=4), + cv.Required(CONF_ROW): cv.int_range(min=0, max=7), + cv.Required(CONF_COL): cv.int_range(min=0, max=7), } ) From 9d978075875b0fdb4fa72e07c657fa108f306296 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 13 Sep 2023 13:05:06 +1200 Subject: [PATCH 0182/2101] Bump version to 2023.10.0-dev --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index bbc6e71885..2865b369e8 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2023.9.0-dev" +__version__ = "2023.10.0-dev" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 280b090dfce2576f056ac0b04c011ee225235fad Mon Sep 17 00:00:00 2001 From: Michael Hansen Date: Wed, 13 Sep 2023 18:13:55 -0500 Subject: [PATCH 0183/2101] Add patch to apt install (#5389) --- docker/Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index bf64897af7..a0bb007641 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -29,7 +29,8 @@ RUN \ curl=7.74.0-1.3+deb11u7 \ openssh-client=1:8.4p1-5+deb11u1 \ python3-cffi=1.14.5-1 \ - libcairo2=1.16.0-5; \ + libcairo2=1.16.0-5 \ + patch=2.7.6-7; \ if [ "$TARGETARCH$TARGETVARIANT" = "armv7" ]; then \ apt-get install -y --no-install-recommends \ build-essential=12.9 \ From 55b5c0fc32210fea202e930fe2d1e7ca374cc635 Mon Sep 17 00:00:00 2001 From: phoenixswiss <52887628+phoenixswiss@users.noreply.github.com> Date: Thu, 14 Sep 2023 08:20:21 +0200 Subject: [PATCH 0184/2101] Fix Waveshare 7.5v2 epaper screens are always powered on (#5283) --- .../waveshare_epaper/waveshare_epaper.cpp | 66 ++++++++++++++++--- .../waveshare_epaper/waveshare_epaper.h | 4 ++ 2 files changed, 61 insertions(+), 9 deletions(-) diff --git a/esphome/components/waveshare_epaper/waveshare_epaper.cpp b/esphome/components/waveshare_epaper/waveshare_epaper.cpp index 73c2680add..f52808d295 100644 --- a/esphome/components/waveshare_epaper/waveshare_epaper.cpp +++ b/esphome/components/waveshare_epaper/waveshare_epaper.cpp @@ -1561,6 +1561,23 @@ void WaveshareEPaper7P5In::dump_config() { LOG_PIN(" Busy Pin: ", this->busy_pin_); LOG_UPDATE_INTERVAL(this); } +bool WaveshareEPaper7P5InV2::wait_until_idle_() { + if (this->busy_pin_ == nullptr) { + return true; + } + + const uint32_t start = millis(); + while (this->busy_pin_->digital_read()) { + this->command(0x71); + if (millis() - start > this->idle_timeout_()) { + ESP_LOGE(TAG, "Timeout while displaying image!"); + return false; + } + App.feed_wdt(); + delay(10); + } + return true; +} void WaveshareEPaper7P5InV2::initialize() { // COMMAND POWER SETTING this->command(0x01); @@ -1568,10 +1585,21 @@ void WaveshareEPaper7P5InV2::initialize() { this->data(0x07); this->data(0x3f); this->data(0x3f); - this->command(0x04); + + // We don't want the display to be powered at this point delay(100); // NOLINT this->wait_until_idle_(); + + // COMMAND VCOM AND DATA INTERVAL SETTING + this->command(0x50); + this->data(0x10); + this->data(0x07); + + // COMMAND TCON SETTING + this->command(0x60); + this->data(0x22); + // COMMAND PANEL SETTING this->command(0x00); this->data(0x1F); @@ -1582,19 +1610,30 @@ void WaveshareEPaper7P5InV2::initialize() { this->data(0x20); this->data(0x01); this->data(0xE0); - // COMMAND ...? + + // COMMAND DUAL SPI MM_EN, DUSPI_EN this->command(0x15); this->data(0x00); - // COMMAND VCOM AND DATA INTERVAL SETTING - this->command(0x50); - this->data(0x10); - this->data(0x07); - // COMMAND TCON SETTING - this->command(0x60); - this->data(0x22); + + // COMMAND POWER DRIVER HAT DOWN + // This command will turn off booster, controller, source driver, gate driver, VCOM, and + // temperature sensor, but register data will be kept until VDD turned OFF or Deep Sleep Mode. + // Source/Gate/Border/VCOM will be released to floating. + this->command(0x02); } void HOT WaveshareEPaper7P5InV2::display() { uint32_t buf_len = this->get_buffer_length_(); + + // COMMAND POWER ON + ESP_LOGI(TAG, "Power on the display and hat"); + + // This command will turn on booster, controller, regulators, and temperature sensor will be + // activated for one-time sensing before enabling booster. When all voltages are ready, the + // BUSY_N signal will return to high. + this->command(0x04); + delay(200); // NOLINT + this->wait_until_idle_(); + // COMMAND DATA START TRANSMISSION NEW DATA this->command(0x13); delay(2); @@ -1602,14 +1641,23 @@ void HOT WaveshareEPaper7P5InV2::display() { this->data(~(this->buffer_[i])); } + delay(100); // NOLINT + this->wait_until_idle_(); + // COMMAND DISPLAY REFRESH this->command(0x12); delay(100); // NOLINT this->wait_until_idle_(); + + ESP_LOGV(TAG, "Before command(0x02) (>> power off)"); + this->command(0x02); + this->wait_until_idle_(); + ESP_LOGV(TAG, "After command(0x02) (>> power off)"); } int WaveshareEPaper7P5InV2::get_width_internal() { return 800; } int WaveshareEPaper7P5InV2::get_height_internal() { return 480; } +uint32_t WaveshareEPaper7P5InV2::idle_timeout_() { return 10000; } void WaveshareEPaper7P5InV2::dump_config() { LOG_DISPLAY("", "Waveshare E-Paper", this); ESP_LOGCONFIG(TAG, " Model: 7.5inV2rev2"); diff --git a/esphome/components/waveshare_epaper/waveshare_epaper.h b/esphome/components/waveshare_epaper/waveshare_epaper.h index 315af9ea82..b3325d69eb 100644 --- a/esphome/components/waveshare_epaper/waveshare_epaper.h +++ b/esphome/components/waveshare_epaper/waveshare_epaper.h @@ -472,6 +472,8 @@ class WaveshareEPaper7P5InBC : public WaveshareEPaper { class WaveshareEPaper7P5InV2 : public WaveshareEPaper { public: + bool wait_until_idle_(); + void initialize() override; void display() override; @@ -491,6 +493,8 @@ class WaveshareEPaper7P5InV2 : public WaveshareEPaper { int get_width_internal() override; int get_height_internal() override; + + uint32_t idle_timeout_() override; }; class WaveshareEPaper7P5InV2alt : public WaveshareEPaper7P5InV2 { From b5f2d69ca529a04616262d96a066080a3b6ad847 Mon Sep 17 00:00:00 2001 From: rmmacias <46213351+rmmacias@users.noreply.github.com> Date: Sun, 17 Sep 2023 07:18:51 +0200 Subject: [PATCH 0185/2101] Update radon_eye_listener.cpp (#5401) New devices identifiers do not star by the hardcoded string. FR:RE222 is the 8-char length string of my devices bought in 2023. This proposal aims at solve the topic by making the detection track devices starting only by FR:R --- esphome/components/radon_eye_ble/radon_eye_listener.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/radon_eye_ble/radon_eye_listener.cpp b/esphome/components/radon_eye_ble/radon_eye_listener.cpp index b10986c9cb..340322c188 100644 --- a/esphome/components/radon_eye_ble/radon_eye_listener.cpp +++ b/esphome/components/radon_eye_ble/radon_eye_listener.cpp @@ -10,7 +10,7 @@ static const char *const TAG = "radon_eye_ble"; bool RadonEyeListener::parse_device(const esp32_ble_tracker::ESPBTDevice &device) { if (not device.get_name().empty()) { - if (device.get_name().rfind("FR:R20:SN", 0) == 0) { + if (device.get_name().rfind("FR:R", 0) == 0) { // This is an RD200, I think ESP_LOGD(TAG, "Found Radon Eye RD200 device Name: %s (MAC: %s)", device.get_name().c_str(), device.address_str().c_str()); From a61e3fadf66d38f5aa823be3a70b23dffa03dad5 Mon Sep 17 00:00:00 2001 From: Trevor North Date: Sun, 17 Sep 2023 06:20:31 +0100 Subject: [PATCH 0186/2101] Add shelly-dimmer-stm32 51.7 to known versions (#5400) This version removes support for no-neutral setups in favor of fixing flickering some users have experienced. --- esphome/components/shelly_dimmer/light.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/esphome/components/shelly_dimmer/light.py b/esphome/components/shelly_dimmer/light.py index 467a3c3531..5bdb54baf5 100644 --- a/esphome/components/shelly_dimmer/light.py +++ b/esphome/components/shelly_dimmer/light.py @@ -57,6 +57,10 @@ KNOWN_FIRMWARE = { "https://github.com/jamesturton/shelly-dimmer-stm32/releases/download/v51.6/shelly-dimmer-stm32_v51.6.bin", "eda483e111c914723a33f5088f1397d5c0b19333db4a88dc965636b976c16c36", ), + "51.7": ( + "https://github.com/jamesturton/shelly-dimmer-stm32/releases/download/v51.7/shelly-dimmer-stm32_v51.7.bin", + "7a20f1c967c469917368a79bc56498009045237080408cef7190743e08031889", + ), } From 164631fcec7f286c0ef6575e9c07c76c369e2b38 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 17 Sep 2023 07:24:31 +0200 Subject: [PATCH 0187/2101] Ci find YAML tests dynamically (#5399) * Find all YAML test files dynamically. * Merge error * GitHub set-ouput syntax upgrade. --------- Co-authored-by: Your Name --- .github/workflows/ci.yml | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4e4e6c0ece..792d972311 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -210,6 +210,17 @@ jobs: run: script/ci-suggest-changes if: always() + compile-tests-list: + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.set-matrix.outputs.matrix }} + steps: + - name: Check out code from GitHub + uses: actions/checkout@v4.0.0 + - name: Find all YAML test files + id: set-matrix + run: echo "matrix=$(ls tests/test*.yaml | jq -R -s -c 'split("\n")[:-1]')" >> $GITHUB_OUTPUT + compile-tests: name: Run YAML test ${{ matrix.file }} runs-on: ubuntu-latest @@ -222,11 +233,12 @@ jobs: - pylint - pytest - pyupgrade + - compile-tests-list strategy: fail-fast: false max-parallel: 2 matrix: - file: [1, 2, 3, 3.1, 4, 5, 6, 7, 8, 10, 11.5] + file: ${{ fromJson(needs.compile-tests-list.outputs.matrix) }} steps: - name: Check out code from GitHub uses: actions/checkout@v4.0.0 @@ -235,10 +247,10 @@ jobs: with: python-version: ${{ env.DEFAULT_PYTHON }} cache-key: ${{ needs.common.outputs.cache-key }} - - name: Run esphome compile tests/test${{ matrix.file }}.yaml + - name: Run esphome compile ${{ matrix.file }} run: | . venv/bin/activate - esphome compile tests/test${{ matrix.file }}.yaml + esphome compile ${{ matrix.file }} clang-tidy: name: ${{ matrix.name }} From 11f6e555f9607767991a93d9c6259ef627a39bda Mon Sep 17 00:00:00 2001 From: Philipp Helo Rehs Date: Sun, 17 Sep 2023 07:30:52 +0200 Subject: [PATCH 0188/2101] Add E-Trailer Gaslevel support to Mopeka Std Check (#5397) * Add E-Trailer Gaslevel support to Mopeka Std Check Signed-off-by: Philipp Helo Rehs * fix format --------- Signed-off-by: Philipp Helo Rehs Co-authored-by: Philipp Helo Rehs --- esphome/components/mopeka_std_check/mopeka_std_check.cpp | 3 ++- esphome/components/mopeka_std_check/mopeka_std_check.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/esphome/components/mopeka_std_check/mopeka_std_check.cpp b/esphome/components/mopeka_std_check/mopeka_std_check.cpp index 67e749c68b..9dd1718cb2 100644 --- a/esphome/components/mopeka_std_check/mopeka_std_check.cpp +++ b/esphome/components/mopeka_std_check/mopeka_std_check.cpp @@ -71,7 +71,8 @@ bool MopekaStdCheck::parse_device(const esp32_ble_tracker::ESPBTDevice &device) const auto *mopeka_data = (const mopeka_std_package *) manu_data.data.data(); const u_int8_t hardware_id = mopeka_data->data_1 & 0xCF; - if (static_cast(hardware_id) != STANDARD && static_cast(hardware_id) != XL) { + if (static_cast(hardware_id) != STANDARD && static_cast(hardware_id) != XL && + static_cast(hardware_id) != ETRAILER) { ESP_LOGE(TAG, "[%s] Unsupported Sensor Type (0x%X)", device.address_str().c_str(), hardware_id); return false; } diff --git a/esphome/components/mopeka_std_check/mopeka_std_check.h b/esphome/components/mopeka_std_check/mopeka_std_check.h index e4d81afbd7..ee588c8e5f 100644 --- a/esphome/components/mopeka_std_check/mopeka_std_check.h +++ b/esphome/components/mopeka_std_check/mopeka_std_check.h @@ -14,6 +14,7 @@ namespace mopeka_std_check { enum SensorType { STANDARD = 0x02, XL = 0x03, + ETRAILER = 0x46, }; // 4 values in one struct so it aligns to 8 byte. One `mopeka_std_values` is 40 bit long. From e3eef1cc6dbbce019fc18168e61c71e5ba3d960e Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Wed, 20 Sep 2023 14:20:54 -0700 Subject: [PATCH 0189/2101] fix disabled wifi power on 8266 (#5409) Co-authored-by: Samuel Sieb --- esphome/components/wifi/wifi_component_esp8266.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index 1afa439567..6e7c491967 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -98,6 +98,7 @@ bool WiFiComponent::wifi_apply_power_save_() { power_save = NONE_SLEEP_T; break; } + wifi_fpm_auto_sleep_set_in_null_mode(1); return wifi_set_sleep_type(power_save); } From bf253c21fac829da986e0e914bff7f1d36eba996 Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Wed, 20 Sep 2023 14:25:16 -0700 Subject: [PATCH 0190/2101] fix handling of web server version (#5405) Co-authored-by: Samuel Sieb --- esphome/components/web_server/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/web_server/__init__.py b/esphome/components/web_server/__init__.py index c6d9c31e93..966c978836 100644 --- a/esphome/components/web_server/__init__.py +++ b/esphome/components/web_server/__init__.py @@ -59,7 +59,7 @@ CONFIG_SCHEMA = cv.All( { cv.GenerateID(): cv.declare_id(WebServer), cv.Optional(CONF_PORT, default=80): cv.port, - cv.Optional(CONF_VERSION, default=2): cv.one_of(1, 2), + cv.Optional(CONF_VERSION, default=2): cv.one_of(1, 2, int=True), cv.Optional(CONF_CSS_URL): cv.string, cv.Optional(CONF_CSS_INCLUDE): cv.file_, cv.Optional(CONF_JS_URL): cv.string, From 397f57ce74e87c447508e940c2f9a44d6ed7bfe6 Mon Sep 17 00:00:00 2001 From: Joris S <100357138+Jorre05@users.noreply.github.com> Date: Wed, 20 Sep 2023 23:28:03 +0200 Subject: [PATCH 0191/2101] Climate preset fix (#5407) --- esphome/components/thermostat/thermostat_climate.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/components/thermostat/thermostat_climate.cpp b/esphome/components/thermostat/thermostat_climate.cpp index 51da663a0c..386e13dc37 100644 --- a/esphome/components/thermostat/thermostat_climate.cpp +++ b/esphome/components/thermostat/thermostat_climate.cpp @@ -986,6 +986,7 @@ void ThermostatClimate::change_preset_(climate::ClimatePreset preset) { // Fire any preset changed trigger if defined Trigger<> *trig = this->preset_change_trigger_; assert(trig != nullptr); + this->preset = preset; trig->trigger(); this->refresh(); @@ -1010,6 +1011,7 @@ void ThermostatClimate::change_custom_preset_(const std::string &custom_preset) // Fire any preset changed trigger if defined Trigger<> *trig = this->preset_change_trigger_; assert(trig != nullptr); + this->custom_preset = custom_preset; trig->trigger(); this->refresh(); From 61edf8c196613c2f38da96ca7ce311e3f24c6bb7 Mon Sep 17 00:00:00 2001 From: Anthony Date: Wed, 20 Sep 2023 16:30:22 -0500 Subject: [PATCH 0192/2101] Remove Wi-Fi dependency from Midea component (#5394) --- esphome/components/midea/climate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/midea/climate.py b/esphome/components/midea/climate.py index 80b1461576..074ab8abb2 100644 --- a/esphome/components/midea/climate.py +++ b/esphome/components/midea/climate.py @@ -35,7 +35,7 @@ from esphome.components.climate import ( ) CODEOWNERS = ["@dudanov"] -DEPENDENCIES = ["climate", "uart", "wifi"] +DEPENDENCIES = ["climate", "uart"] AUTO_LOAD = ["sensor"] CONF_OUTDOOR_TEMPERATURE = "outdoor_temperature" CONF_POWER_USAGE = "power_usage" From 157a3e53ddde620f25522d0f218e692d86d7d291 Mon Sep 17 00:00:00 2001 From: "Kevin P. Fleming" Date: Wed, 20 Sep 2023 18:02:29 -0400 Subject: [PATCH 0193/2101] http_request: Cleanups and safety improvements (#5360) --- .../components/http_request/http_request.h | 27 +++++++------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/esphome/components/http_request/http_request.h b/esphome/components/http_request/http_request.h index 0958c07683..b885de18e6 100644 --- a/esphome/components/http_request/http_request.h +++ b/esphome/components/http_request/http_request.h @@ -80,8 +80,6 @@ template class HttpRequestSendAction : public Action { TEMPLATABLE_VALUE(std::string, url) TEMPLATABLE_VALUE(const char *, method) TEMPLATABLE_VALUE(std::string, body) - TEMPLATABLE_VALUE(const char *, useragent) - TEMPLATABLE_VALUE(uint16_t, timeout) void add_header(const char *key, TemplatableValue value) { this->headers_.insert({key, value}); } @@ -105,25 +103,18 @@ template class HttpRequestSendAction : public Action { auto f = std::bind(&HttpRequestSendAction::encode_json_func_, this, x..., std::placeholders::_1); this->parent_->set_body(json::build_json(f)); } - if (this->useragent_.has_value()) { - this->parent_->set_useragent(this->useragent_.value(x...)); - } - if (this->timeout_.has_value()) { - this->parent_->set_timeout(this->timeout_.value(x...)); - } - if (!this->headers_.empty()) { - std::list
headers; - for (const auto &item : this->headers_) { - auto val = item.second; - Header header; - header.name = item.first; - header.value = val.value(x...); - headers.push_back(header); - } - this->parent_->set_headers(headers); + std::list
headers; + for (const auto &item : this->headers_) { + auto val = item.second; + Header header; + header.name = item.first; + header.value = val.value(x...); + headers.push_back(header); } + this->parent_->set_headers(headers); this->parent_->send(this->response_triggers_); this->parent_->close(); + this->parent_->set_body(""); } protected: From 2c2821cd961b51cb303996fdb62e17f323eb8908 Mon Sep 17 00:00:00 2001 From: Trent Houliston Date: Thu, 21 Sep 2023 08:04:03 +1000 Subject: [PATCH 0194/2101] Make the pulse meter timeout on startup when no pulses are received (#5388) --- .../pulse_meter/pulse_meter_sensor.cpp | 35 +++++++++++++------ .../pulse_meter/pulse_meter_sensor.h | 3 +- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/esphome/components/pulse_meter/pulse_meter_sensor.cpp b/esphome/components/pulse_meter/pulse_meter_sensor.cpp index 7eef18e5e0..be5fad6fe5 100644 --- a/esphome/components/pulse_meter/pulse_meter_sensor.cpp +++ b/esphome/components/pulse_meter/pulse_meter_sensor.cpp @@ -11,6 +11,9 @@ void PulseMeterSensor::setup() { this->pin_->setup(); this->isr_pin_ = pin_->to_isr(); + // Set the last processed edge to now for the first timeout + this->last_processed_edge_us_ = micros(); + if (this->filter_mode_ == FILTER_EDGE) { this->pin_->attach_interrupt(PulseMeterSensor::edge_intr, this, gpio::INTERRUPT_RISING_EDGE); } else if (this->filter_mode_ == FILTER_PULSE) { @@ -38,12 +41,16 @@ void PulseMeterSensor::loop() { } // We need to detect at least two edges to have a valid pulse width - if (!this->initialized_) { - this->initialized_ = true; - } else { - 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_); - this->publish_state((60.0f * 1000000.0f) / pulse_width_us); + switch (this->meter_state_) { + case MeterState::INITIAL: + case MeterState::TIMED_OUT: { + 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_); + this->publish_state((60.0f * 1000000.0f) / pulse_width_us); + } break; } this->last_processed_edge_us_ = this->get_->last_detected_edge_us_; @@ -53,10 +60,18 @@ void PulseMeterSensor::loop() { const uint32_t now = micros(); const uint32_t time_since_valid_edge_us = now - this->last_processed_edge_us_; - if (this->initialized_ && time_since_valid_edge_us > this->timeout_us_) { - ESP_LOGD(TAG, "No pulse detected for %us, assuming 0 pulses/min", time_since_valid_edge_us / 1000000); - this->initialized_ = false; - this->publish_state(0.0f); + switch (this->meter_state_) { + // Running and initial states can timeout + case MeterState::INITIAL: + case MeterState::RUNNING: { + if (time_since_valid_edge_us > this->timeout_us_) { + this->meter_state_ = MeterState::TIMED_OUT; + ESP_LOGD(TAG, "No pulse detected for %us, assuming 0 pulses/min", time_since_valid_edge_us / 1000000); + this->publish_state(0.0f); + } + } break; + default: + break; } } } diff --git a/esphome/components/pulse_meter/pulse_meter_sensor.h b/esphome/components/pulse_meter/pulse_meter_sensor.h index ddd42c2ed5..f376ea48a5 100644 --- a/esphome/components/pulse_meter/pulse_meter_sensor.h +++ b/esphome/components/pulse_meter/pulse_meter_sensor.h @@ -38,7 +38,8 @@ class PulseMeterSensor : public sensor::Sensor, public Component { InternalFilterMode filter_mode_{FILTER_EDGE}; // Variables used in the loop - bool initialized_ = false; + enum class MeterState { INITIAL, RUNNING, TIMED_OUT }; + MeterState meter_state_ = MeterState::INITIAL; uint32_t total_pulses_ = 0; uint32_t last_processed_edge_us_ = 0; From 056a28906ba9de193da4aa78f6034984654bc4a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Thu, 21 Sep 2023 00:09:23 +0200 Subject: [PATCH 0195/2101] Wizard: fix colored text in input prompts (#5313) --- esphome/util.py | 14 ++++++++++---- esphome/wizard.py | 18 ++++++++++-------- tests/unit_tests/test_wizard.py | 12 ++++++------ 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/esphome/util.py b/esphome/util.py index 0d60212f50..480618aca0 100644 --- a/esphome/util.py +++ b/esphome/util.py @@ -57,7 +57,7 @@ class SimpleRegistry(dict): return decorator -def safe_print(message=""): +def safe_print(message="", end="\n"): from esphome.core import CORE if CORE.dashboard: @@ -67,20 +67,26 @@ def safe_print(message=""): pass try: - print(message) + print(message, end=end) return except UnicodeEncodeError: pass try: - print(message.encode("utf-8", "backslashreplace")) + print(message.encode("utf-8", "backslashreplace"), end=end) except UnicodeEncodeError: try: - print(message.encode("ascii", "backslashreplace")) + print(message.encode("ascii", "backslashreplace"), end=end) except UnicodeEncodeError: print("Cannot print line because of invalid locale!") +def safe_input(prompt=""): + if prompt: + safe_print(prompt, end="") + return input() + + def shlex_quote(s): if not s: return "''" diff --git a/esphome/wizard.py b/esphome/wizard.py index aa05e513a7..1308338ad0 100644 --- a/esphome/wizard.py +++ b/esphome/wizard.py @@ -11,7 +11,7 @@ from esphome.core import CORE from esphome.helpers import get_bool_env, write_file from esphome.log import Fore, color from esphome.storage_json import StorageJSON, ext_storage_path -from esphome.util import safe_print +from esphome.util import safe_input, safe_print CORE_BIG = r""" _____ ____ _____ ______ / ____/ __ \| __ \| ____| @@ -252,7 +252,7 @@ def safe_print_step(step, big): def default_input(text, default): safe_print() safe_print(f"Press ENTER for default ({default})") - return input(text.format(default)) or default + return safe_input(text.format(default)) or default # From https://stackoverflow.com/a/518232/8924614 @@ -306,7 +306,7 @@ def wizard(path): ) safe_print() sleep(1) - name = input(color(Fore.BOLD_WHITE, "(name): ")) + name = safe_input(color(Fore.BOLD_WHITE, "(name): ")) while True: try: @@ -343,7 +343,9 @@ def wizard(path): while True: sleep(0.5) safe_print() - platform = input(color(Fore.BOLD_WHITE, f"({'/'.join(wizard_platforms)}): ")) + platform = safe_input( + color(Fore.BOLD_WHITE, f"({'/'.join(wizard_platforms)}): ") + ) try: platform = vol.All(vol.Upper, vol.Any(*wizard_platforms))(platform.upper()) break @@ -397,7 +399,7 @@ def wizard(path): boards.append(board_id) while True: - board = input(color(Fore.BOLD_WHITE, "(board): ")) + board = safe_input(color(Fore.BOLD_WHITE, "(board): ")) try: board = vol.All(vol.Lower, vol.Any(*boards))(board) break @@ -423,7 +425,7 @@ def wizard(path): sleep(1.5) safe_print(f"For example \"{color(Fore.BOLD_WHITE, 'Abraham Linksys')}\".") while True: - ssid = input(color(Fore.BOLD_WHITE, "(ssid): ")) + ssid = safe_input(color(Fore.BOLD_WHITE, "(ssid): ")) try: ssid = cv.ssid(ssid) break @@ -449,7 +451,7 @@ def wizard(path): safe_print() safe_print(f"For example \"{color(Fore.BOLD_WHITE, 'PASSWORD42')}\"") sleep(0.5) - psk = input(color(Fore.BOLD_WHITE, "(PSK): ")) + psk = safe_input(color(Fore.BOLD_WHITE, "(PSK): ")) safe_print( "Perfect! WiFi is now set up (you can create static IPs and so on later)." ) @@ -466,7 +468,7 @@ def wizard(path): safe_print() sleep(0.25) safe_print("Press ENTER for no password") - password = input(color(Fore.BOLD_WHITE, "(password): ")) + password = safe_input(color(Fore.BOLD_WHITE, "(password): ")) if not wizard_write( path=path, diff --git a/tests/unit_tests/test_wizard.py b/tests/unit_tests/test_wizard.py index 8bbce08ae5..46700a3ba8 100644 --- a/tests/unit_tests/test_wizard.py +++ b/tests/unit_tests/test_wizard.py @@ -319,7 +319,7 @@ def test_wizard_accepts_default_answers_esp8266(tmpdir, monkeypatch, wizard_answ config_file = tmpdir.join("test.yaml") input_mock = MagicMock(side_effect=wizard_answers) monkeypatch.setattr("builtins.input", input_mock) - monkeypatch.setattr(wz, "safe_print", lambda t=None: 0) + monkeypatch.setattr(wz, "safe_print", lambda t=None, end=None: 0) monkeypatch.setattr(wz, "sleep", lambda _: 0) monkeypatch.setattr(wz, "wizard_write", MagicMock()) @@ -341,7 +341,7 @@ def test_wizard_accepts_default_answers_esp32(tmpdir, monkeypatch, wizard_answer config_file = tmpdir.join("test.yaml") input_mock = MagicMock(side_effect=wizard_answers) monkeypatch.setattr("builtins.input", input_mock) - monkeypatch.setattr(wz, "safe_print", lambda t=None: 0) + monkeypatch.setattr(wz, "safe_print", lambda t=None, end=None: 0) monkeypatch.setattr(wz, "sleep", lambda _: 0) monkeypatch.setattr(wz, "wizard_write", MagicMock()) @@ -371,7 +371,7 @@ def test_wizard_offers_better_node_name(tmpdir, monkeypatch, wizard_answers): config_file = tmpdir.join("test.yaml") input_mock = MagicMock(side_effect=wizard_answers) monkeypatch.setattr("builtins.input", input_mock) - monkeypatch.setattr(wz, "safe_print", lambda t=None: 0) + monkeypatch.setattr(wz, "safe_print", lambda t=None, end=None: 0) monkeypatch.setattr(wz, "sleep", lambda _: 0) monkeypatch.setattr(wz, "wizard_write", MagicMock()) @@ -394,7 +394,7 @@ def test_wizard_requires_correct_platform(tmpdir, monkeypatch, wizard_answers): config_file = tmpdir.join("test.yaml") input_mock = MagicMock(side_effect=wizard_answers) monkeypatch.setattr("builtins.input", input_mock) - monkeypatch.setattr(wz, "safe_print", lambda t=None: 0) + monkeypatch.setattr(wz, "safe_print", lambda t=None, end=None: 0) monkeypatch.setattr(wz, "sleep", lambda _: 0) monkeypatch.setattr(wz, "wizard_write", MagicMock()) @@ -416,7 +416,7 @@ def test_wizard_requires_correct_board(tmpdir, monkeypatch, wizard_answers): config_file = tmpdir.join("test.yaml") input_mock = MagicMock(side_effect=wizard_answers) monkeypatch.setattr("builtins.input", input_mock) - monkeypatch.setattr(wz, "safe_print", lambda t=None: 0) + monkeypatch.setattr(wz, "safe_print", lambda t=None, end=None: 0) monkeypatch.setattr(wz, "sleep", lambda _: 0) monkeypatch.setattr(wz, "wizard_write", MagicMock()) @@ -438,7 +438,7 @@ def test_wizard_requires_valid_ssid(tmpdir, monkeypatch, wizard_answers): config_file = tmpdir.join("test.yaml") input_mock = MagicMock(side_effect=wizard_answers) monkeypatch.setattr("builtins.input", input_mock) - monkeypatch.setattr(wz, "safe_print", lambda t=None: 0) + monkeypatch.setattr(wz, "safe_print", lambda t=None, end=None: 0) monkeypatch.setattr(wz, "sleep", lambda _: 0) monkeypatch.setattr(wz, "wizard_write", MagicMock()) From 1100f67b66de7fa944c446335f6f1254ba78a78a Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Wed, 20 Sep 2023 15:26:36 -0700 Subject: [PATCH 0196/2101] support keypads with pulldowns (#5404) Co-authored-by: Samuel Sieb --- esphome/components/matrix_keypad/__init__.py | 4 ++++ .../components/matrix_keypad/matrix_keypad.cpp | 17 +++++++++++------ .../components/matrix_keypad/matrix_keypad.h | 2 ++ tests/test5.yaml | 1 + 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/esphome/components/matrix_keypad/__init__.py b/esphome/components/matrix_keypad/__init__.py index 1c549007b9..5250a45732 100644 --- a/esphome/components/matrix_keypad/__init__.py +++ b/esphome/components/matrix_keypad/__init__.py @@ -21,6 +21,7 @@ CONF_COLUMNS = "columns" CONF_KEYS = "keys" CONF_DEBOUNCE_TIME = "debounce_time" CONF_HAS_DIODES = "has_diodes" +CONF_HAS_PULLDOWNS = "has_pulldowns" def check_keys(obj): @@ -45,6 +46,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_KEYS): cv.string, cv.Optional(CONF_DEBOUNCE_TIME, default=1): cv.int_range(min=1, max=100), cv.Optional(CONF_HAS_DIODES): cv.boolean, + cv.Optional(CONF_HAS_PULLDOWNS): cv.boolean, } ), check_keys, @@ -69,3 +71,5 @@ async def to_code(config): cg.add(var.set_debounce_time(config[CONF_DEBOUNCE_TIME])) if CONF_HAS_DIODES in config: cg.add(var.set_has_diodes(config[CONF_HAS_DIODES])) + if CONF_HAS_PULLDOWNS in config: + cg.add(var.set_has_pulldowns(config[CONF_HAS_PULLDOWNS])) diff --git a/esphome/components/matrix_keypad/matrix_keypad.cpp b/esphome/components/matrix_keypad/matrix_keypad.cpp index 4f8962a782..902e574846 100644 --- a/esphome/components/matrix_keypad/matrix_keypad.cpp +++ b/esphome/components/matrix_keypad/matrix_keypad.cpp @@ -11,11 +11,16 @@ void MatrixKeypad::setup() { if (!has_diodes_) { pin->pin_mode(gpio::FLAG_INPUT); } else { - pin->digital_write(true); + pin->digital_write(!has_pulldowns_); + } + } + for (auto *pin : this->columns_) { + if (has_pulldowns_) { + pin->pin_mode(gpio::FLAG_INPUT); + } else { + pin->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP); } } - for (auto *pin : this->columns_) - pin->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP); } void MatrixKeypad::loop() { @@ -28,9 +33,9 @@ void MatrixKeypad::loop() { for (auto *row : this->rows_) { if (!has_diodes_) row->pin_mode(gpio::FLAG_OUTPUT); - row->digital_write(false); + row->digital_write(has_pulldowns_); for (auto *col : this->columns_) { - if (!col->digital_read()) { + if (col->digital_read() == has_pulldowns_) { if (key != -1) { error = true; } else { @@ -39,7 +44,7 @@ void MatrixKeypad::loop() { } pos++; } - row->digital_write(true); + row->digital_write(!has_pulldowns_); if (!has_diodes_) row->pin_mode(gpio::FLAG_INPUT); } diff --git a/esphome/components/matrix_keypad/matrix_keypad.h b/esphome/components/matrix_keypad/matrix_keypad.h index 9f5942be9a..d506040b7c 100644 --- a/esphome/components/matrix_keypad/matrix_keypad.h +++ b/esphome/components/matrix_keypad/matrix_keypad.h @@ -28,6 +28,7 @@ class MatrixKeypad : public key_provider::KeyProvider, public Component { void set_keys(std::string keys) { keys_ = std::move(keys); }; void set_debounce_time(int debounce_time) { debounce_time_ = debounce_time; }; void set_has_diodes(int has_diodes) { has_diodes_ = has_diodes; }; + void set_has_pulldowns(int has_pulldowns) { has_pulldowns_ = has_pulldowns; }; void register_listener(MatrixKeypadListener *listener); @@ -37,6 +38,7 @@ class MatrixKeypad : public key_provider::KeyProvider, public Component { std::string keys_; int debounce_time_ = 0; bool has_diodes_{false}; + bool has_pulldowns_{false}; int pressed_key_ = -1; std::vector listeners_{}; diff --git a/tests/test5.yaml b/tests/test5.yaml index 274570aad6..5727d30e61 100644 --- a/tests/test5.yaml +++ b/tests/test5.yaml @@ -667,6 +667,7 @@ matrix_keypad: - pin: 17 - pin: 16 keys: "1234" + has_pulldowns: true key_collector: - id: reader From b3ca71c6fb0d3f68228e522824c272d671292089 Mon Sep 17 00:00:00 2001 From: Michael Hansen Date: Wed, 13 Sep 2023 18:13:55 -0500 Subject: [PATCH 0197/2101] Add patch to apt install (#5389) --- docker/Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index bf64897af7..a0bb007641 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -29,7 +29,8 @@ RUN \ curl=7.74.0-1.3+deb11u7 \ openssh-client=1:8.4p1-5+deb11u1 \ python3-cffi=1.14.5-1 \ - libcairo2=1.16.0-5; \ + libcairo2=1.16.0-5 \ + patch=2.7.6-7; \ if [ "$TARGETARCH$TARGETVARIANT" = "armv7" ]; then \ apt-get install -y --no-install-recommends \ build-essential=12.9 \ From ec20778d83dd7bf10d8f32c49ff0dfd7102a0ade Mon Sep 17 00:00:00 2001 From: phoenixswiss <52887628+phoenixswiss@users.noreply.github.com> Date: Thu, 14 Sep 2023 08:20:21 +0200 Subject: [PATCH 0198/2101] Fix Waveshare 7.5v2 epaper screens are always powered on (#5283) --- .../waveshare_epaper/waveshare_epaper.cpp | 66 ++++++++++++++++--- .../waveshare_epaper/waveshare_epaper.h | 4 ++ 2 files changed, 61 insertions(+), 9 deletions(-) diff --git a/esphome/components/waveshare_epaper/waveshare_epaper.cpp b/esphome/components/waveshare_epaper/waveshare_epaper.cpp index 73c2680add..f52808d295 100644 --- a/esphome/components/waveshare_epaper/waveshare_epaper.cpp +++ b/esphome/components/waveshare_epaper/waveshare_epaper.cpp @@ -1561,6 +1561,23 @@ void WaveshareEPaper7P5In::dump_config() { LOG_PIN(" Busy Pin: ", this->busy_pin_); LOG_UPDATE_INTERVAL(this); } +bool WaveshareEPaper7P5InV2::wait_until_idle_() { + if (this->busy_pin_ == nullptr) { + return true; + } + + const uint32_t start = millis(); + while (this->busy_pin_->digital_read()) { + this->command(0x71); + if (millis() - start > this->idle_timeout_()) { + ESP_LOGE(TAG, "Timeout while displaying image!"); + return false; + } + App.feed_wdt(); + delay(10); + } + return true; +} void WaveshareEPaper7P5InV2::initialize() { // COMMAND POWER SETTING this->command(0x01); @@ -1568,10 +1585,21 @@ void WaveshareEPaper7P5InV2::initialize() { this->data(0x07); this->data(0x3f); this->data(0x3f); - this->command(0x04); + + // We don't want the display to be powered at this point delay(100); // NOLINT this->wait_until_idle_(); + + // COMMAND VCOM AND DATA INTERVAL SETTING + this->command(0x50); + this->data(0x10); + this->data(0x07); + + // COMMAND TCON SETTING + this->command(0x60); + this->data(0x22); + // COMMAND PANEL SETTING this->command(0x00); this->data(0x1F); @@ -1582,19 +1610,30 @@ void WaveshareEPaper7P5InV2::initialize() { this->data(0x20); this->data(0x01); this->data(0xE0); - // COMMAND ...? + + // COMMAND DUAL SPI MM_EN, DUSPI_EN this->command(0x15); this->data(0x00); - // COMMAND VCOM AND DATA INTERVAL SETTING - this->command(0x50); - this->data(0x10); - this->data(0x07); - // COMMAND TCON SETTING - this->command(0x60); - this->data(0x22); + + // COMMAND POWER DRIVER HAT DOWN + // This command will turn off booster, controller, source driver, gate driver, VCOM, and + // temperature sensor, but register data will be kept until VDD turned OFF or Deep Sleep Mode. + // Source/Gate/Border/VCOM will be released to floating. + this->command(0x02); } void HOT WaveshareEPaper7P5InV2::display() { uint32_t buf_len = this->get_buffer_length_(); + + // COMMAND POWER ON + ESP_LOGI(TAG, "Power on the display and hat"); + + // This command will turn on booster, controller, regulators, and temperature sensor will be + // activated for one-time sensing before enabling booster. When all voltages are ready, the + // BUSY_N signal will return to high. + this->command(0x04); + delay(200); // NOLINT + this->wait_until_idle_(); + // COMMAND DATA START TRANSMISSION NEW DATA this->command(0x13); delay(2); @@ -1602,14 +1641,23 @@ void HOT WaveshareEPaper7P5InV2::display() { this->data(~(this->buffer_[i])); } + delay(100); // NOLINT + this->wait_until_idle_(); + // COMMAND DISPLAY REFRESH this->command(0x12); delay(100); // NOLINT this->wait_until_idle_(); + + ESP_LOGV(TAG, "Before command(0x02) (>> power off)"); + this->command(0x02); + this->wait_until_idle_(); + ESP_LOGV(TAG, "After command(0x02) (>> power off)"); } int WaveshareEPaper7P5InV2::get_width_internal() { return 800; } int WaveshareEPaper7P5InV2::get_height_internal() { return 480; } +uint32_t WaveshareEPaper7P5InV2::idle_timeout_() { return 10000; } void WaveshareEPaper7P5InV2::dump_config() { LOG_DISPLAY("", "Waveshare E-Paper", this); ESP_LOGCONFIG(TAG, " Model: 7.5inV2rev2"); diff --git a/esphome/components/waveshare_epaper/waveshare_epaper.h b/esphome/components/waveshare_epaper/waveshare_epaper.h index 315af9ea82..b3325d69eb 100644 --- a/esphome/components/waveshare_epaper/waveshare_epaper.h +++ b/esphome/components/waveshare_epaper/waveshare_epaper.h @@ -472,6 +472,8 @@ class WaveshareEPaper7P5InBC : public WaveshareEPaper { class WaveshareEPaper7P5InV2 : public WaveshareEPaper { public: + bool wait_until_idle_(); + void initialize() override; void display() override; @@ -491,6 +493,8 @@ class WaveshareEPaper7P5InV2 : public WaveshareEPaper { int get_width_internal() override; int get_height_internal() override; + + uint32_t idle_timeout_() override; }; class WaveshareEPaper7P5InV2alt : public WaveshareEPaper7P5InV2 { From d76f18b4f24fe8cd554e2e9ed2f24bcd601e63ae Mon Sep 17 00:00:00 2001 From: rmmacias <46213351+rmmacias@users.noreply.github.com> Date: Sun, 17 Sep 2023 07:18:51 +0200 Subject: [PATCH 0199/2101] Update radon_eye_listener.cpp (#5401) New devices identifiers do not star by the hardcoded string. FR:RE222 is the 8-char length string of my devices bought in 2023. This proposal aims at solve the topic by making the detection track devices starting only by FR:R --- esphome/components/radon_eye_ble/radon_eye_listener.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/radon_eye_ble/radon_eye_listener.cpp b/esphome/components/radon_eye_ble/radon_eye_listener.cpp index b10986c9cb..340322c188 100644 --- a/esphome/components/radon_eye_ble/radon_eye_listener.cpp +++ b/esphome/components/radon_eye_ble/radon_eye_listener.cpp @@ -10,7 +10,7 @@ static const char *const TAG = "radon_eye_ble"; bool RadonEyeListener::parse_device(const esp32_ble_tracker::ESPBTDevice &device) { if (not device.get_name().empty()) { - if (device.get_name().rfind("FR:R20:SN", 0) == 0) { + if (device.get_name().rfind("FR:R", 0) == 0) { // This is an RD200, I think ESP_LOGD(TAG, "Found Radon Eye RD200 device Name: %s (MAC: %s)", device.get_name().c_str(), device.address_str().c_str()); From 4622ef770d8a62232eddc8a1315699f91ef1952c Mon Sep 17 00:00:00 2001 From: Trevor North Date: Sun, 17 Sep 2023 06:20:31 +0100 Subject: [PATCH 0200/2101] Add shelly-dimmer-stm32 51.7 to known versions (#5400) This version removes support for no-neutral setups in favor of fixing flickering some users have experienced. --- esphome/components/shelly_dimmer/light.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/esphome/components/shelly_dimmer/light.py b/esphome/components/shelly_dimmer/light.py index 467a3c3531..5bdb54baf5 100644 --- a/esphome/components/shelly_dimmer/light.py +++ b/esphome/components/shelly_dimmer/light.py @@ -57,6 +57,10 @@ KNOWN_FIRMWARE = { "https://github.com/jamesturton/shelly-dimmer-stm32/releases/download/v51.6/shelly-dimmer-stm32_v51.6.bin", "eda483e111c914723a33f5088f1397d5c0b19333db4a88dc965636b976c16c36", ), + "51.7": ( + "https://github.com/jamesturton/shelly-dimmer-stm32/releases/download/v51.7/shelly-dimmer-stm32_v51.7.bin", + "7a20f1c967c469917368a79bc56498009045237080408cef7190743e08031889", + ), } From 2fa7f8c5112333a65c1a5c2de85cc28687f0d1c7 Mon Sep 17 00:00:00 2001 From: Philipp Helo Rehs Date: Sun, 17 Sep 2023 07:30:52 +0200 Subject: [PATCH 0201/2101] Add E-Trailer Gaslevel support to Mopeka Std Check (#5397) * Add E-Trailer Gaslevel support to Mopeka Std Check Signed-off-by: Philipp Helo Rehs * fix format --------- Signed-off-by: Philipp Helo Rehs Co-authored-by: Philipp Helo Rehs --- esphome/components/mopeka_std_check/mopeka_std_check.cpp | 3 ++- esphome/components/mopeka_std_check/mopeka_std_check.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/esphome/components/mopeka_std_check/mopeka_std_check.cpp b/esphome/components/mopeka_std_check/mopeka_std_check.cpp index 67e749c68b..9dd1718cb2 100644 --- a/esphome/components/mopeka_std_check/mopeka_std_check.cpp +++ b/esphome/components/mopeka_std_check/mopeka_std_check.cpp @@ -71,7 +71,8 @@ bool MopekaStdCheck::parse_device(const esp32_ble_tracker::ESPBTDevice &device) const auto *mopeka_data = (const mopeka_std_package *) manu_data.data.data(); const u_int8_t hardware_id = mopeka_data->data_1 & 0xCF; - if (static_cast(hardware_id) != STANDARD && static_cast(hardware_id) != XL) { + if (static_cast(hardware_id) != STANDARD && static_cast(hardware_id) != XL && + static_cast(hardware_id) != ETRAILER) { ESP_LOGE(TAG, "[%s] Unsupported Sensor Type (0x%X)", device.address_str().c_str(), hardware_id); return false; } diff --git a/esphome/components/mopeka_std_check/mopeka_std_check.h b/esphome/components/mopeka_std_check/mopeka_std_check.h index e4d81afbd7..ee588c8e5f 100644 --- a/esphome/components/mopeka_std_check/mopeka_std_check.h +++ b/esphome/components/mopeka_std_check/mopeka_std_check.h @@ -14,6 +14,7 @@ namespace mopeka_std_check { enum SensorType { STANDARD = 0x02, XL = 0x03, + ETRAILER = 0x46, }; // 4 values in one struct so it aligns to 8 byte. One `mopeka_std_values` is 40 bit long. From e8862620556008834356669be14f93a2b3395d62 Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Wed, 20 Sep 2023 14:20:54 -0700 Subject: [PATCH 0202/2101] fix disabled wifi power on 8266 (#5409) Co-authored-by: Samuel Sieb --- esphome/components/wifi/wifi_component_esp8266.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index 1afa439567..6e7c491967 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -98,6 +98,7 @@ bool WiFiComponent::wifi_apply_power_save_() { power_save = NONE_SLEEP_T; break; } + wifi_fpm_auto_sleep_set_in_null_mode(1); return wifi_set_sleep_type(power_save); } From e55636ed521bc2feda4ce690c9b6eba50a8cf1cb Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Wed, 20 Sep 2023 14:25:16 -0700 Subject: [PATCH 0203/2101] fix handling of web server version (#5405) Co-authored-by: Samuel Sieb --- esphome/components/web_server/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/web_server/__init__.py b/esphome/components/web_server/__init__.py index c6d9c31e93..966c978836 100644 --- a/esphome/components/web_server/__init__.py +++ b/esphome/components/web_server/__init__.py @@ -59,7 +59,7 @@ CONFIG_SCHEMA = cv.All( { cv.GenerateID(): cv.declare_id(WebServer), cv.Optional(CONF_PORT, default=80): cv.port, - cv.Optional(CONF_VERSION, default=2): cv.one_of(1, 2), + cv.Optional(CONF_VERSION, default=2): cv.one_of(1, 2, int=True), cv.Optional(CONF_CSS_URL): cv.string, cv.Optional(CONF_CSS_INCLUDE): cv.file_, cv.Optional(CONF_JS_URL): cv.string, From 8f1ce8c7f7a6a86b0e9d98e9324f9ab6ff0e41e2 Mon Sep 17 00:00:00 2001 From: Joris S <100357138+Jorre05@users.noreply.github.com> Date: Wed, 20 Sep 2023 23:28:03 +0200 Subject: [PATCH 0204/2101] Climate preset fix (#5407) --- esphome/components/thermostat/thermostat_climate.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/components/thermostat/thermostat_climate.cpp b/esphome/components/thermostat/thermostat_climate.cpp index 51da663a0c..386e13dc37 100644 --- a/esphome/components/thermostat/thermostat_climate.cpp +++ b/esphome/components/thermostat/thermostat_climate.cpp @@ -986,6 +986,7 @@ void ThermostatClimate::change_preset_(climate::ClimatePreset preset) { // Fire any preset changed trigger if defined Trigger<> *trig = this->preset_change_trigger_; assert(trig != nullptr); + this->preset = preset; trig->trigger(); this->refresh(); @@ -1010,6 +1011,7 @@ void ThermostatClimate::change_custom_preset_(const std::string &custom_preset) // Fire any preset changed trigger if defined Trigger<> *trig = this->preset_change_trigger_; assert(trig != nullptr); + this->custom_preset = custom_preset; trig->trigger(); this->refresh(); From 41c829fa32ec2b13eab7647ed806575e0f5897a4 Mon Sep 17 00:00:00 2001 From: Anthony Date: Wed, 20 Sep 2023 16:30:22 -0500 Subject: [PATCH 0205/2101] Remove Wi-Fi dependency from Midea component (#5394) --- esphome/components/midea/climate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/midea/climate.py b/esphome/components/midea/climate.py index 80b1461576..074ab8abb2 100644 --- a/esphome/components/midea/climate.py +++ b/esphome/components/midea/climate.py @@ -35,7 +35,7 @@ from esphome.components.climate import ( ) CODEOWNERS = ["@dudanov"] -DEPENDENCIES = ["climate", "uart", "wifi"] +DEPENDENCIES = ["climate", "uart"] AUTO_LOAD = ["sensor"] CONF_OUTDOOR_TEMPERATURE = "outdoor_temperature" CONF_POWER_USAGE = "power_usage" From 7ebe6a5894da94d1dd9c4c2e711e2c0ce8a087d3 Mon Sep 17 00:00:00 2001 From: "Kevin P. Fleming" Date: Wed, 20 Sep 2023 18:02:29 -0400 Subject: [PATCH 0206/2101] http_request: Cleanups and safety improvements (#5360) --- .../components/http_request/http_request.h | 27 +++++++------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/esphome/components/http_request/http_request.h b/esphome/components/http_request/http_request.h index 0958c07683..b885de18e6 100644 --- a/esphome/components/http_request/http_request.h +++ b/esphome/components/http_request/http_request.h @@ -80,8 +80,6 @@ template class HttpRequestSendAction : public Action { TEMPLATABLE_VALUE(std::string, url) TEMPLATABLE_VALUE(const char *, method) TEMPLATABLE_VALUE(std::string, body) - TEMPLATABLE_VALUE(const char *, useragent) - TEMPLATABLE_VALUE(uint16_t, timeout) void add_header(const char *key, TemplatableValue value) { this->headers_.insert({key, value}); } @@ -105,25 +103,18 @@ template class HttpRequestSendAction : public Action { auto f = std::bind(&HttpRequestSendAction::encode_json_func_, this, x..., std::placeholders::_1); this->parent_->set_body(json::build_json(f)); } - if (this->useragent_.has_value()) { - this->parent_->set_useragent(this->useragent_.value(x...)); - } - if (this->timeout_.has_value()) { - this->parent_->set_timeout(this->timeout_.value(x...)); - } - if (!this->headers_.empty()) { - std::list
headers; - for (const auto &item : this->headers_) { - auto val = item.second; - Header header; - header.name = item.first; - header.value = val.value(x...); - headers.push_back(header); - } - this->parent_->set_headers(headers); + std::list
headers; + for (const auto &item : this->headers_) { + auto val = item.second; + Header header; + header.name = item.first; + header.value = val.value(x...); + headers.push_back(header); } + this->parent_->set_headers(headers); this->parent_->send(this->response_triggers_); this->parent_->close(); + this->parent_->set_body(""); } protected: From 807c47a076e202d681affe65414b49c40a0015d5 Mon Sep 17 00:00:00 2001 From: Trent Houliston Date: Thu, 21 Sep 2023 08:04:03 +1000 Subject: [PATCH 0207/2101] Make the pulse meter timeout on startup when no pulses are received (#5388) --- .../pulse_meter/pulse_meter_sensor.cpp | 35 +++++++++++++------ .../pulse_meter/pulse_meter_sensor.h | 3 +- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/esphome/components/pulse_meter/pulse_meter_sensor.cpp b/esphome/components/pulse_meter/pulse_meter_sensor.cpp index 7eef18e5e0..be5fad6fe5 100644 --- a/esphome/components/pulse_meter/pulse_meter_sensor.cpp +++ b/esphome/components/pulse_meter/pulse_meter_sensor.cpp @@ -11,6 +11,9 @@ void PulseMeterSensor::setup() { this->pin_->setup(); this->isr_pin_ = pin_->to_isr(); + // Set the last processed edge to now for the first timeout + this->last_processed_edge_us_ = micros(); + if (this->filter_mode_ == FILTER_EDGE) { this->pin_->attach_interrupt(PulseMeterSensor::edge_intr, this, gpio::INTERRUPT_RISING_EDGE); } else if (this->filter_mode_ == FILTER_PULSE) { @@ -38,12 +41,16 @@ void PulseMeterSensor::loop() { } // We need to detect at least two edges to have a valid pulse width - if (!this->initialized_) { - this->initialized_ = true; - } else { - 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_); - this->publish_state((60.0f * 1000000.0f) / pulse_width_us); + switch (this->meter_state_) { + case MeterState::INITIAL: + case MeterState::TIMED_OUT: { + 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_); + this->publish_state((60.0f * 1000000.0f) / pulse_width_us); + } break; } this->last_processed_edge_us_ = this->get_->last_detected_edge_us_; @@ -53,10 +60,18 @@ void PulseMeterSensor::loop() { const uint32_t now = micros(); const uint32_t time_since_valid_edge_us = now - this->last_processed_edge_us_; - if (this->initialized_ && time_since_valid_edge_us > this->timeout_us_) { - ESP_LOGD(TAG, "No pulse detected for %us, assuming 0 pulses/min", time_since_valid_edge_us / 1000000); - this->initialized_ = false; - this->publish_state(0.0f); + switch (this->meter_state_) { + // Running and initial states can timeout + case MeterState::INITIAL: + case MeterState::RUNNING: { + if (time_since_valid_edge_us > this->timeout_us_) { + this->meter_state_ = MeterState::TIMED_OUT; + ESP_LOGD(TAG, "No pulse detected for %us, assuming 0 pulses/min", time_since_valid_edge_us / 1000000); + this->publish_state(0.0f); + } + } break; + default: + break; } } } diff --git a/esphome/components/pulse_meter/pulse_meter_sensor.h b/esphome/components/pulse_meter/pulse_meter_sensor.h index ddd42c2ed5..f376ea48a5 100644 --- a/esphome/components/pulse_meter/pulse_meter_sensor.h +++ b/esphome/components/pulse_meter/pulse_meter_sensor.h @@ -38,7 +38,8 @@ class PulseMeterSensor : public sensor::Sensor, public Component { InternalFilterMode filter_mode_{FILTER_EDGE}; // Variables used in the loop - bool initialized_ = false; + enum class MeterState { INITIAL, RUNNING, TIMED_OUT }; + MeterState meter_state_ = MeterState::INITIAL; uint32_t total_pulses_ = 0; uint32_t last_processed_edge_us_ = 0; From d7e267eca53e47beec3496e9458ccce151d25ff5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Thu, 21 Sep 2023 00:09:23 +0200 Subject: [PATCH 0208/2101] Wizard: fix colored text in input prompts (#5313) --- esphome/util.py | 14 ++++++++++---- esphome/wizard.py | 18 ++++++++++-------- tests/unit_tests/test_wizard.py | 12 ++++++------ 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/esphome/util.py b/esphome/util.py index 0d60212f50..480618aca0 100644 --- a/esphome/util.py +++ b/esphome/util.py @@ -57,7 +57,7 @@ class SimpleRegistry(dict): return decorator -def safe_print(message=""): +def safe_print(message="", end="\n"): from esphome.core import CORE if CORE.dashboard: @@ -67,20 +67,26 @@ def safe_print(message=""): pass try: - print(message) + print(message, end=end) return except UnicodeEncodeError: pass try: - print(message.encode("utf-8", "backslashreplace")) + print(message.encode("utf-8", "backslashreplace"), end=end) except UnicodeEncodeError: try: - print(message.encode("ascii", "backslashreplace")) + print(message.encode("ascii", "backslashreplace"), end=end) except UnicodeEncodeError: print("Cannot print line because of invalid locale!") +def safe_input(prompt=""): + if prompt: + safe_print(prompt, end="") + return input() + + def shlex_quote(s): if not s: return "''" diff --git a/esphome/wizard.py b/esphome/wizard.py index aa05e513a7..1308338ad0 100644 --- a/esphome/wizard.py +++ b/esphome/wizard.py @@ -11,7 +11,7 @@ from esphome.core import CORE from esphome.helpers import get_bool_env, write_file from esphome.log import Fore, color from esphome.storage_json import StorageJSON, ext_storage_path -from esphome.util import safe_print +from esphome.util import safe_input, safe_print CORE_BIG = r""" _____ ____ _____ ______ / ____/ __ \| __ \| ____| @@ -252,7 +252,7 @@ def safe_print_step(step, big): def default_input(text, default): safe_print() safe_print(f"Press ENTER for default ({default})") - return input(text.format(default)) or default + return safe_input(text.format(default)) or default # From https://stackoverflow.com/a/518232/8924614 @@ -306,7 +306,7 @@ def wizard(path): ) safe_print() sleep(1) - name = input(color(Fore.BOLD_WHITE, "(name): ")) + name = safe_input(color(Fore.BOLD_WHITE, "(name): ")) while True: try: @@ -343,7 +343,9 @@ def wizard(path): while True: sleep(0.5) safe_print() - platform = input(color(Fore.BOLD_WHITE, f"({'/'.join(wizard_platforms)}): ")) + platform = safe_input( + color(Fore.BOLD_WHITE, f"({'/'.join(wizard_platforms)}): ") + ) try: platform = vol.All(vol.Upper, vol.Any(*wizard_platforms))(platform.upper()) break @@ -397,7 +399,7 @@ def wizard(path): boards.append(board_id) while True: - board = input(color(Fore.BOLD_WHITE, "(board): ")) + board = safe_input(color(Fore.BOLD_WHITE, "(board): ")) try: board = vol.All(vol.Lower, vol.Any(*boards))(board) break @@ -423,7 +425,7 @@ def wizard(path): sleep(1.5) safe_print(f"For example \"{color(Fore.BOLD_WHITE, 'Abraham Linksys')}\".") while True: - ssid = input(color(Fore.BOLD_WHITE, "(ssid): ")) + ssid = safe_input(color(Fore.BOLD_WHITE, "(ssid): ")) try: ssid = cv.ssid(ssid) break @@ -449,7 +451,7 @@ def wizard(path): safe_print() safe_print(f"For example \"{color(Fore.BOLD_WHITE, 'PASSWORD42')}\"") sleep(0.5) - psk = input(color(Fore.BOLD_WHITE, "(PSK): ")) + psk = safe_input(color(Fore.BOLD_WHITE, "(PSK): ")) safe_print( "Perfect! WiFi is now set up (you can create static IPs and so on later)." ) @@ -466,7 +468,7 @@ def wizard(path): safe_print() sleep(0.25) safe_print("Press ENTER for no password") - password = input(color(Fore.BOLD_WHITE, "(password): ")) + password = safe_input(color(Fore.BOLD_WHITE, "(password): ")) if not wizard_write( path=path, diff --git a/tests/unit_tests/test_wizard.py b/tests/unit_tests/test_wizard.py index 8bbce08ae5..46700a3ba8 100644 --- a/tests/unit_tests/test_wizard.py +++ b/tests/unit_tests/test_wizard.py @@ -319,7 +319,7 @@ def test_wizard_accepts_default_answers_esp8266(tmpdir, monkeypatch, wizard_answ config_file = tmpdir.join("test.yaml") input_mock = MagicMock(side_effect=wizard_answers) monkeypatch.setattr("builtins.input", input_mock) - monkeypatch.setattr(wz, "safe_print", lambda t=None: 0) + monkeypatch.setattr(wz, "safe_print", lambda t=None, end=None: 0) monkeypatch.setattr(wz, "sleep", lambda _: 0) monkeypatch.setattr(wz, "wizard_write", MagicMock()) @@ -341,7 +341,7 @@ def test_wizard_accepts_default_answers_esp32(tmpdir, monkeypatch, wizard_answer config_file = tmpdir.join("test.yaml") input_mock = MagicMock(side_effect=wizard_answers) monkeypatch.setattr("builtins.input", input_mock) - monkeypatch.setattr(wz, "safe_print", lambda t=None: 0) + monkeypatch.setattr(wz, "safe_print", lambda t=None, end=None: 0) monkeypatch.setattr(wz, "sleep", lambda _: 0) monkeypatch.setattr(wz, "wizard_write", MagicMock()) @@ -371,7 +371,7 @@ def test_wizard_offers_better_node_name(tmpdir, monkeypatch, wizard_answers): config_file = tmpdir.join("test.yaml") input_mock = MagicMock(side_effect=wizard_answers) monkeypatch.setattr("builtins.input", input_mock) - monkeypatch.setattr(wz, "safe_print", lambda t=None: 0) + monkeypatch.setattr(wz, "safe_print", lambda t=None, end=None: 0) monkeypatch.setattr(wz, "sleep", lambda _: 0) monkeypatch.setattr(wz, "wizard_write", MagicMock()) @@ -394,7 +394,7 @@ def test_wizard_requires_correct_platform(tmpdir, monkeypatch, wizard_answers): config_file = tmpdir.join("test.yaml") input_mock = MagicMock(side_effect=wizard_answers) monkeypatch.setattr("builtins.input", input_mock) - monkeypatch.setattr(wz, "safe_print", lambda t=None: 0) + monkeypatch.setattr(wz, "safe_print", lambda t=None, end=None: 0) monkeypatch.setattr(wz, "sleep", lambda _: 0) monkeypatch.setattr(wz, "wizard_write", MagicMock()) @@ -416,7 +416,7 @@ def test_wizard_requires_correct_board(tmpdir, monkeypatch, wizard_answers): config_file = tmpdir.join("test.yaml") input_mock = MagicMock(side_effect=wizard_answers) monkeypatch.setattr("builtins.input", input_mock) - monkeypatch.setattr(wz, "safe_print", lambda t=None: 0) + monkeypatch.setattr(wz, "safe_print", lambda t=None, end=None: 0) monkeypatch.setattr(wz, "sleep", lambda _: 0) monkeypatch.setattr(wz, "wizard_write", MagicMock()) @@ -438,7 +438,7 @@ def test_wizard_requires_valid_ssid(tmpdir, monkeypatch, wizard_answers): config_file = tmpdir.join("test.yaml") input_mock = MagicMock(side_effect=wizard_answers) monkeypatch.setattr("builtins.input", input_mock) - monkeypatch.setattr(wz, "safe_print", lambda t=None: 0) + monkeypatch.setattr(wz, "safe_print", lambda t=None, end=None: 0) monkeypatch.setattr(wz, "sleep", lambda _: 0) monkeypatch.setattr(wz, "wizard_write", MagicMock()) From 5b46088ae4089fa8f8c02f3a54a86d2f9da0bb24 Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Wed, 20 Sep 2023 15:26:36 -0700 Subject: [PATCH 0209/2101] support keypads with pulldowns (#5404) Co-authored-by: Samuel Sieb --- esphome/components/matrix_keypad/__init__.py | 4 ++++ .../components/matrix_keypad/matrix_keypad.cpp | 17 +++++++++++------ .../components/matrix_keypad/matrix_keypad.h | 2 ++ tests/test5.yaml | 1 + 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/esphome/components/matrix_keypad/__init__.py b/esphome/components/matrix_keypad/__init__.py index 1c549007b9..5250a45732 100644 --- a/esphome/components/matrix_keypad/__init__.py +++ b/esphome/components/matrix_keypad/__init__.py @@ -21,6 +21,7 @@ CONF_COLUMNS = "columns" CONF_KEYS = "keys" CONF_DEBOUNCE_TIME = "debounce_time" CONF_HAS_DIODES = "has_diodes" +CONF_HAS_PULLDOWNS = "has_pulldowns" def check_keys(obj): @@ -45,6 +46,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_KEYS): cv.string, cv.Optional(CONF_DEBOUNCE_TIME, default=1): cv.int_range(min=1, max=100), cv.Optional(CONF_HAS_DIODES): cv.boolean, + cv.Optional(CONF_HAS_PULLDOWNS): cv.boolean, } ), check_keys, @@ -69,3 +71,5 @@ async def to_code(config): cg.add(var.set_debounce_time(config[CONF_DEBOUNCE_TIME])) if CONF_HAS_DIODES in config: cg.add(var.set_has_diodes(config[CONF_HAS_DIODES])) + if CONF_HAS_PULLDOWNS in config: + cg.add(var.set_has_pulldowns(config[CONF_HAS_PULLDOWNS])) diff --git a/esphome/components/matrix_keypad/matrix_keypad.cpp b/esphome/components/matrix_keypad/matrix_keypad.cpp index 4f8962a782..902e574846 100644 --- a/esphome/components/matrix_keypad/matrix_keypad.cpp +++ b/esphome/components/matrix_keypad/matrix_keypad.cpp @@ -11,11 +11,16 @@ void MatrixKeypad::setup() { if (!has_diodes_) { pin->pin_mode(gpio::FLAG_INPUT); } else { - pin->digital_write(true); + pin->digital_write(!has_pulldowns_); + } + } + for (auto *pin : this->columns_) { + if (has_pulldowns_) { + pin->pin_mode(gpio::FLAG_INPUT); + } else { + pin->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP); } } - for (auto *pin : this->columns_) - pin->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP); } void MatrixKeypad::loop() { @@ -28,9 +33,9 @@ void MatrixKeypad::loop() { for (auto *row : this->rows_) { if (!has_diodes_) row->pin_mode(gpio::FLAG_OUTPUT); - row->digital_write(false); + row->digital_write(has_pulldowns_); for (auto *col : this->columns_) { - if (!col->digital_read()) { + if (col->digital_read() == has_pulldowns_) { if (key != -1) { error = true; } else { @@ -39,7 +44,7 @@ void MatrixKeypad::loop() { } pos++; } - row->digital_write(true); + row->digital_write(!has_pulldowns_); if (!has_diodes_) row->pin_mode(gpio::FLAG_INPUT); } diff --git a/esphome/components/matrix_keypad/matrix_keypad.h b/esphome/components/matrix_keypad/matrix_keypad.h index 9f5942be9a..d506040b7c 100644 --- a/esphome/components/matrix_keypad/matrix_keypad.h +++ b/esphome/components/matrix_keypad/matrix_keypad.h @@ -28,6 +28,7 @@ class MatrixKeypad : public key_provider::KeyProvider, public Component { void set_keys(std::string keys) { keys_ = std::move(keys); }; void set_debounce_time(int debounce_time) { debounce_time_ = debounce_time; }; void set_has_diodes(int has_diodes) { has_diodes_ = has_diodes; }; + void set_has_pulldowns(int has_pulldowns) { has_pulldowns_ = has_pulldowns; }; void register_listener(MatrixKeypadListener *listener); @@ -37,6 +38,7 @@ class MatrixKeypad : public key_provider::KeyProvider, public Component { std::string keys_; int debounce_time_ = 0; bool has_diodes_{false}; + bool has_pulldowns_{false}; int pressed_key_ = -1; std::vector listeners_{}; diff --git a/tests/test5.yaml b/tests/test5.yaml index 274570aad6..5727d30e61 100644 --- a/tests/test5.yaml +++ b/tests/test5.yaml @@ -667,6 +667,7 @@ matrix_keypad: - pin: 17 - pin: 16 keys: "1234" + has_pulldowns: true key_collector: - id: reader From 90835ab917ec52e2e9de464477f9e24988392be0 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 21 Sep 2023 10:35:38 +1200 Subject: [PATCH 0210/2101] Bump version to 2023.9.0b2 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index cbb31e0ec6..8a10776c4a 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2023.9.0b1" +__version__ = "2023.9.0b2" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 518ecb4cc4489c8a76b899bfda7576b05d84c226 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Fri, 22 Sep 2023 14:15:50 +1000 Subject: [PATCH 0211/2101] Fix SPI inverted clock on ESP8266 (#5416) --- esphome/components/spi/spi.h | 6 ++---- esphome/components/spi/spi_arduino.cpp | 5 +++++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/esphome/components/spi/spi.h b/esphome/components/spi/spi.h index 2761c2d604..56aa746fc9 100644 --- a/esphome/components/spi/spi.h +++ b/esphome/components/spi/spi.h @@ -351,6 +351,7 @@ class SPIClient { : bit_order_(bit_order), mode_(mode), data_rate_(data_rate) {} virtual void spi_setup() { + esph_log_d("spi_device", "mode %u, data_rate %ukHz", (unsigned) this->mode_, (unsigned) (this->data_rate_ / 1000)); this->delegate_ = this->parent_->register_device(this, this->mode_, this->bit_order_, this->data_rate_, this->cs_); } @@ -398,10 +399,7 @@ class SPIDevice : public SPIClient { void set_data_rate(uint32_t data_rate) { this->data_rate_ = data_rate; } - void set_bit_order(SPIBitOrder order) { - this->bit_order_ = order; - esph_log_d("spi.h", "bit order set to %d", order); - } + void set_bit_order(SPIBitOrder order) { this->bit_order_ = order; } void set_mode(SPIMode mode) { this->mode_ = mode; } diff --git a/esphome/components/spi/spi_arduino.cpp b/esphome/components/spi/spi_arduino.cpp index 40ed9e6062..2e6b2d6064 100644 --- a/esphome/components/spi/spi_arduino.cpp +++ b/esphome/components/spi/spi_arduino.cpp @@ -15,6 +15,11 @@ class SPIDelegateHw : public SPIDelegate { void begin_transaction() override { #ifdef USE_RP2040 SPISettings const settings(this->data_rate_, static_cast(this->bit_order_), this->mode_); +#elif defined(ESP8266) + // Arduino ESP8266 library has mangled values for SPI modes :-( + auto mode = (this->mode_ & 0x01) + ((this->mode_ & 0x02) << 3); + ESP_LOGV(TAG, "8266 mangled SPI mode 0x%X", mode); + SPISettings const settings(this->data_rate_, this->bit_order_, mode); #else SPISettings const settings(this->data_rate_, this->bit_order_, this->mode_); #endif From 3c7c4e1dbaf25c9fa35247328aa76c03fda53fac Mon Sep 17 00:00:00 2001 From: Andrew Garrett Date: Sun, 24 Sep 2023 19:34:37 +1000 Subject: [PATCH 0212/2101] Make ESPHome data dir configurable (#5417) --- esphome/core/__init__.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/esphome/core/__init__.py b/esphome/core/__init__.py index cca758e3c1..4897b073fa 100644 --- a/esphome/core/__init__.py +++ b/esphome/core/__init__.py @@ -21,7 +21,7 @@ from esphome.coroutine import FakeEventLoop as _FakeEventLoop # pylint: disable=unused-import from esphome.coroutine import coroutine, coroutine_with_priority # noqa -from esphome.helpers import ensure_unique_string, is_ha_addon +from esphome.helpers import ensure_unique_string, get_str_env, is_ha_addon from esphome.util import OrderedDict if TYPE_CHECKING: @@ -558,6 +558,8 @@ class EsphomeCore: def data_dir(self): if is_ha_addon(): return os.path.join("/data") + if get_str_env("ESPHOME_DATA_DIR", None) is not None: + return get_str_env("ESPHOME_DATA_DIR", None) return self.relative_config_path(".esphome") @property From 0ca8dcd08e96b431f8034acc16a7f9c2ab64eb84 Mon Sep 17 00:00:00 2001 From: Ilia Sotnikov Date: Sun, 24 Sep 2023 12:44:55 +0300 Subject: [PATCH 0213/2101] [RP2040W] Fix WiFi bootloop upon LibreTiny support (#5414) --- esphome/components/rp2040/__init__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/esphome/components/rp2040/__init__.py b/esphome/components/rp2040/__init__.py index b31192f73f..5d8608c44d 100644 --- a/esphome/components/rp2040/__init__.py +++ b/esphome/components/rp2040/__init__.py @@ -152,6 +152,9 @@ CONFIG_SCHEMA = cv.All( async def to_code(config): cg.add(rp2040_ns.setup_preferences()) + # Allow LDF to properly discover dependency including those in preprocessor + # conditionals + cg.add_platformio_option("lib_ldf_mode", "chain+") cg.add_platformio_option("board", config[CONF_BOARD]) cg.add_build_flag("-DUSE_RP2040") cg.add_define("ESPHOME_BOARD", config[CONF_BOARD]) From 727056a28c8c59351ac3be6a9ee2fa1e4343ef47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Odd=20Str=C3=A5b=C3=B8?= Date: Sun, 24 Sep 2023 23:15:28 +0200 Subject: [PATCH 0214/2101] dallas: limit addresses to 64 bits (#5413) --- esphome/components/dallas/sensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/dallas/sensor.py b/esphome/components/dallas/sensor.py index 9288f0a3a6..c6ebda62c8 100644 --- a/esphome/components/dallas/sensor.py +++ b/esphome/components/dallas/sensor.py @@ -24,7 +24,7 @@ CONFIG_SCHEMA = cv.All( ).extend( { cv.GenerateID(CONF_DALLAS_ID): cv.use_id(DallasComponent), - cv.Optional(CONF_ADDRESS): cv.hex_int, + cv.Optional(CONF_ADDRESS): cv.hex_uint64_t, cv.Optional(CONF_INDEX): cv.positive_int, cv.Optional(CONF_RESOLUTION, default=12): cv.int_range(min=9, max=12), } From c34d5111fceb3f16f147c9aeb7bd7684a39dc454 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Sep 2023 10:23:40 +1300 Subject: [PATCH 0215/2101] Bump actions/checkout from 4.0.0 to 4.1.0 (#5420) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-docker.yml | 2 +- .github/workflows/ci.yml | 22 +++++++++++----------- .github/workflows/release.yml | 6 +++--- .github/workflows/sync-device-classes.yml | 4 ++-- .github/workflows/yaml-lint.yml | 2 +- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci-docker.yml b/.github/workflows/ci-docker.yml index b53eaf8e1a..7fe51163ba 100644 --- a/.github/workflows/ci-docker.yml +++ b/.github/workflows/ci-docker.yml @@ -40,7 +40,7 @@ jobs: arch: [amd64, armv7, aarch64] build_type: ["ha-addon", "docker", "lint"] steps: - - uses: actions/checkout@v4.0.0 + - uses: actions/checkout@v4.1.0 - name: Set up Python uses: actions/setup-python@v4.7.0 with: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 792d972311..26fcbbf458 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,7 +34,7 @@ jobs: cache-key: ${{ steps.cache-key.outputs.key }} steps: - name: Check out code from GitHub - uses: actions/checkout@v4.0.0 + uses: actions/checkout@v4.1.0 - name: Generate cache-key id: cache-key run: echo key="${{ hashFiles('requirements.txt', 'requirements_optional.txt', 'requirements_test.txt') }}" >> $GITHUB_OUTPUT @@ -66,7 +66,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4.0.0 + uses: actions/checkout@v4.1.0 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -87,7 +87,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4.0.0 + uses: actions/checkout@v4.1.0 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -108,7 +108,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4.0.0 + uses: actions/checkout@v4.1.0 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -129,7 +129,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4.0.0 + uses: actions/checkout@v4.1.0 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -150,7 +150,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4.0.0 + uses: actions/checkout@v4.1.0 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -171,7 +171,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4.0.0 + uses: actions/checkout@v4.1.0 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -191,7 +191,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4.0.0 + uses: actions/checkout@v4.1.0 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -216,7 +216,7 @@ jobs: matrix: ${{ steps.set-matrix.outputs.matrix }} steps: - name: Check out code from GitHub - uses: actions/checkout@v4.0.0 + uses: actions/checkout@v4.1.0 - name: Find all YAML test files id: set-matrix run: echo "matrix=$(ls tests/test*.yaml | jq -R -s -c 'split("\n")[:-1]')" >> $GITHUB_OUTPUT @@ -241,7 +241,7 @@ jobs: file: ${{ fromJson(needs.compile-tests-list.outputs.matrix) }} steps: - name: Check out code from GitHub - uses: actions/checkout@v4.0.0 + uses: actions/checkout@v4.1.0 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -296,7 +296,7 @@ jobs: steps: - name: Check out code from GitHub - uses: actions/checkout@v4.0.0 + uses: actions/checkout@v4.1.0 - name: Restore Python uses: ./.github/actions/restore-python with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 99d1594f03..6934d36686 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,7 +19,7 @@ jobs: outputs: tag: ${{ steps.tag.outputs.tag }} steps: - - uses: actions/checkout@v4.0.0 + - uses: actions/checkout@v4.1.0 - name: Get tag id: tag # yamllint disable rule:line-length @@ -43,7 +43,7 @@ jobs: if: github.repository == 'esphome/esphome' && github.event_name == 'release' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.0.0 + - uses: actions/checkout@v4.1.0 - name: Set up Python uses: actions/setup-python@v4.7.0 with: @@ -88,7 +88,7 @@ jobs: target: "lint" baseimg: "docker" steps: - - uses: actions/checkout@v4.0.0 + - uses: actions/checkout@v4.1.0 - name: Set up Python uses: actions/setup-python@v4.7.0 with: diff --git a/.github/workflows/sync-device-classes.yml b/.github/workflows/sync-device-classes.yml index 943e93a0b7..25d36bc6d0 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@v4.0.0 + uses: actions/checkout@v4.1.0 - name: Checkout Home Assistant - uses: actions/checkout@v4.0.0 + uses: actions/checkout@v4.1.0 with: repository: home-assistant/core path: lib/home-assistant diff --git a/.github/workflows/yaml-lint.yml b/.github/workflows/yaml-lint.yml index 77b3c1dcb5..65628a22bb 100644 --- a/.github/workflows/yaml-lint.yml +++ b/.github/workflows/yaml-lint.yml @@ -17,6 +17,6 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code from GitHub - uses: actions/checkout@v4.0.0 + uses: actions/checkout@v4.1.0 - name: Run yamllint uses: frenck/action-yamllint@v1.4.1 From a031cc3b848b942119d63b6673027e39d2c26259 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Sep 2023 10:25:51 +1300 Subject: [PATCH 0216/2101] Bump zeroconf from 0.108.0 to 0.112.0 (#5392) 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 19c05bf8f7..63199680cf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,7 +11,7 @@ esptool==4.6.2 click==8.1.7 esphome-dashboard==20230904.0 aioesphomeapi==15.0.0 -zeroconf==0.108.0 +zeroconf==0.112.0 # esp-idf requires this, but doesn't bundle it by default # https://github.com/espressif/esp-idf/blob/220590d599e134d7a5e7f1e683cc4550349ffbf8/requirements.txt#L24 From 17e1d4c2455997a0a15c875950be1942c6249d0d Mon Sep 17 00:00:00 2001 From: Kapil Yedidi Date: Sun, 24 Sep 2023 16:05:56 -0700 Subject: [PATCH 0217/2101] Fix typo in documentation (#5425) --- esphome/components/pmsa003i/pmsa003i.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/esphome/components/pmsa003i/pmsa003i.h b/esphome/components/pmsa003i/pmsa003i.h index 10176218ed..1fe4139951 100644 --- a/esphome/components/pmsa003i/pmsa003i.h +++ b/esphome/components/pmsa003i/pmsa003i.h @@ -17,12 +17,12 @@ struct PM25AQIData { uint16_t pm10_env, ///< Environmental PM1.0 pm25_env, ///< Environmental PM2.5 pm100_env; ///< Environmental PM10.0 - uint16_t particles_03um, ///< 0.3um Particle Count - particles_05um, ///< 0.5um Particle Count - particles_10um, ///< 1.0um Particle Count - particles_25um, ///< 2.5um Particle Count - particles_50um, ///< 5.0um Particle Count - particles_100um; ///< 10.0um Particle Count + uint16_t particles_03um, ///> 0.3um Particle Count + particles_05um, ///> 0.5um Particle Count + particles_10um, ///> 1.0um Particle Count + particles_25um, ///> 2.5um Particle Count + particles_50um, ///> 5.0um Particle Count + particles_100um; ///> 10.0um Particle Count uint16_t unused; ///< Unused uint16_t checksum; ///< Packet checksum }; From b07a038bc8f17afe9aa6bdde6b8ec929b1120945 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Fri, 22 Sep 2023 14:15:50 +1000 Subject: [PATCH 0218/2101] Fix SPI inverted clock on ESP8266 (#5416) --- esphome/components/spi/spi.h | 6 ++---- esphome/components/spi/spi_arduino.cpp | 5 +++++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/esphome/components/spi/spi.h b/esphome/components/spi/spi.h index 2761c2d604..56aa746fc9 100644 --- a/esphome/components/spi/spi.h +++ b/esphome/components/spi/spi.h @@ -351,6 +351,7 @@ class SPIClient { : bit_order_(bit_order), mode_(mode), data_rate_(data_rate) {} virtual void spi_setup() { + esph_log_d("spi_device", "mode %u, data_rate %ukHz", (unsigned) this->mode_, (unsigned) (this->data_rate_ / 1000)); this->delegate_ = this->parent_->register_device(this, this->mode_, this->bit_order_, this->data_rate_, this->cs_); } @@ -398,10 +399,7 @@ class SPIDevice : public SPIClient { void set_data_rate(uint32_t data_rate) { this->data_rate_ = data_rate; } - void set_bit_order(SPIBitOrder order) { - this->bit_order_ = order; - esph_log_d("spi.h", "bit order set to %d", order); - } + void set_bit_order(SPIBitOrder order) { this->bit_order_ = order; } void set_mode(SPIMode mode) { this->mode_ = mode; } diff --git a/esphome/components/spi/spi_arduino.cpp b/esphome/components/spi/spi_arduino.cpp index 40ed9e6062..2e6b2d6064 100644 --- a/esphome/components/spi/spi_arduino.cpp +++ b/esphome/components/spi/spi_arduino.cpp @@ -15,6 +15,11 @@ class SPIDelegateHw : public SPIDelegate { void begin_transaction() override { #ifdef USE_RP2040 SPISettings const settings(this->data_rate_, static_cast(this->bit_order_), this->mode_); +#elif defined(ESP8266) + // Arduino ESP8266 library has mangled values for SPI modes :-( + auto mode = (this->mode_ & 0x01) + ((this->mode_ & 0x02) << 3); + ESP_LOGV(TAG, "8266 mangled SPI mode 0x%X", mode); + SPISettings const settings(this->data_rate_, this->bit_order_, mode); #else SPISettings const settings(this->data_rate_, this->bit_order_, this->mode_); #endif From a42788812e5136e8235c76df2bb0526d1436a417 Mon Sep 17 00:00:00 2001 From: Ilia Sotnikov Date: Sun, 24 Sep 2023 12:44:55 +0300 Subject: [PATCH 0219/2101] [RP2040W] Fix WiFi bootloop upon LibreTiny support (#5414) --- esphome/components/rp2040/__init__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/esphome/components/rp2040/__init__.py b/esphome/components/rp2040/__init__.py index b31192f73f..5d8608c44d 100644 --- a/esphome/components/rp2040/__init__.py +++ b/esphome/components/rp2040/__init__.py @@ -152,6 +152,9 @@ CONFIG_SCHEMA = cv.All( async def to_code(config): cg.add(rp2040_ns.setup_preferences()) + # Allow LDF to properly discover dependency including those in preprocessor + # conditionals + cg.add_platformio_option("lib_ldf_mode", "chain+") cg.add_platformio_option("board", config[CONF_BOARD]) cg.add_build_flag("-DUSE_RP2040") cg.add_define("ESPHOME_BOARD", config[CONF_BOARD]) From 33e2aa341e63a925123a27b758769a70ff012195 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Odd=20Str=C3=A5b=C3=B8?= Date: Sun, 24 Sep 2023 23:15:28 +0200 Subject: [PATCH 0220/2101] dallas: limit addresses to 64 bits (#5413) --- esphome/components/dallas/sensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/dallas/sensor.py b/esphome/components/dallas/sensor.py index 9288f0a3a6..c6ebda62c8 100644 --- a/esphome/components/dallas/sensor.py +++ b/esphome/components/dallas/sensor.py @@ -24,7 +24,7 @@ CONFIG_SCHEMA = cv.All( ).extend( { cv.GenerateID(CONF_DALLAS_ID): cv.use_id(DallasComponent), - cv.Optional(CONF_ADDRESS): cv.hex_int, + cv.Optional(CONF_ADDRESS): cv.hex_uint64_t, cv.Optional(CONF_INDEX): cv.positive_int, cv.Optional(CONF_RESOLUTION, default=12): cv.int_range(min=9, max=12), } From 0aeebdd2896cd5cf6d262fea41269c1dc21c3307 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Sep 2023 10:25:51 +1300 Subject: [PATCH 0221/2101] Bump zeroconf from 0.108.0 to 0.112.0 (#5392) 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 19c05bf8f7..63199680cf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,7 +11,7 @@ esptool==4.6.2 click==8.1.7 esphome-dashboard==20230904.0 aioesphomeapi==15.0.0 -zeroconf==0.108.0 +zeroconf==0.112.0 # esp-idf requires this, but doesn't bundle it by default # https://github.com/espressif/esp-idf/blob/220590d599e134d7a5e7f1e683cc4550349ffbf8/requirements.txt#L24 From 5f5ee9c9204bda8b38d86eac065781a87b2ea27a Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 25 Sep 2023 12:10:35 +1300 Subject: [PATCH 0222/2101] Bump version to 2023.9.0b3 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 8a10776c4a..f5319adfa7 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2023.9.0b2" +__version__ = "2023.9.0b3" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 607d0b426402ff27324f05c881c617162c2a8a7e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 Sep 2023 09:28:25 +1300 Subject: [PATCH 0223/2101] Bump pylint from 2.17.5 to 2.17.6 (#5429) 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 a07815df54..92cb8b1be2 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,4 +1,4 @@ -pylint==2.17.5 +pylint==2.17.6 flake8==6.1.0 # also change in .pre-commit-config.yaml when updating black==23.9.1 # also change in .pre-commit-config.yaml when updating pyupgrade==3.10.1 # also change in .pre-commit-config.yaml when updating From 2f7a378c7b87cd11b750b36475f6129599ffda8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Tue, 26 Sep 2023 23:23:21 +0200 Subject: [PATCH 0224/2101] LibreTiny: enable MQTT, bump to v1.4.1 (#5419) --- esphome/components/libretiny/__init__.py | 2 +- esphome/components/mqtt/__init__.py | 8 +- .../components/mqtt/mqtt_backend_libretiny.h | 74 +++++++++++++++++++ esphome/components/mqtt/mqtt_client.cpp | 5 +- esphome/components/mqtt/mqtt_client.h | 4 + 5 files changed, 87 insertions(+), 6 deletions(-) create mode 100644 esphome/components/mqtt/mqtt_backend_libretiny.h diff --git a/esphome/components/libretiny/__init__.py b/esphome/components/libretiny/__init__.py index 3c1c0ac3f0..b01d342a87 100644 --- a/esphome/components/libretiny/__init__.py +++ b/esphome/components/libretiny/__init__.py @@ -170,7 +170,7 @@ def _notify_old_style(config): ARDUINO_VERSIONS = { "dev": (cv.Version(0, 0, 0), "https://github.com/libretiny-eu/libretiny.git"), "latest": (cv.Version(0, 0, 0), None), - "recommended": (cv.Version(1, 4, 0), None), + "recommended": (cv.Version(1, 4, 1), None), } diff --git a/esphome/components/mqtt/__init__.py b/esphome/components/mqtt/__init__.py index 9df2067832..10ae8ac40d 100644 --- a/esphome/components/mqtt/__init__.py +++ b/esphome/components/mqtt/__init__.py @@ -250,7 +250,7 @@ CONFIG_SCHEMA = cv.All( } ), validate_config, - cv.only_on(["esp32", "esp8266"]), + cv.only_on(["esp32", "esp8266", "bk72xx"]), ) @@ -271,10 +271,10 @@ 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 - if CORE.is_esp8266: + # 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 - cg.add_library("heman/AsyncMqttClient-esphome", "1.0.0") + cg.add_library("heman/AsyncMqttClient-esphome", "2.0.0") cg.add_define("USE_MQTT") cg.add_global(mqtt_ns.using) diff --git a/esphome/components/mqtt/mqtt_backend_libretiny.h b/esphome/components/mqtt/mqtt_backend_libretiny.h new file mode 100644 index 0000000000..5373a1926a --- /dev/null +++ b/esphome/components/mqtt/mqtt_backend_libretiny.h @@ -0,0 +1,74 @@ +#pragma once + +#ifdef USE_LIBRETINY + +#include "mqtt_backend.h" +#include + +namespace esphome { +namespace mqtt { + +class MQTTBackendLibreTiny final : public MQTTBackend { + public: + void set_keep_alive(uint16_t keep_alive) final { mqtt_client_.setKeepAlive(keep_alive); } + void set_client_id(const char *client_id) final { mqtt_client_.setClientId(client_id); } + void set_clean_session(bool clean_session) final { mqtt_client_.setCleanSession(clean_session); } + void set_credentials(const char *username, const char *password) final { + mqtt_client_.setCredentials(username, password); + } + void set_will(const char *topic, uint8_t qos, bool retain, const char *payload) final { + mqtt_client_.setWill(topic, qos, retain, payload); + } + void set_server(network::IPAddress ip, uint16_t port) final { + mqtt_client_.setServer(IPAddress(static_cast(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 &&callback) final { + this->mqtt_client_.onConnect(std::move(callback)); + } + void set_on_disconnect(std::function &&callback) final { + auto async_callback = [callback](AsyncMqttClientDisconnectReason reason) { + // int based enum so casting isn't a problem + callback(static_cast(reason)); + }; + this->mqtt_client_.onDisconnect(std::move(async_callback)); + } + void set_on_subscribe(std::function &&callback) final { + this->mqtt_client_.onSubscribe(std::move(callback)); + } + void set_on_unsubscribe(std::function &&callback) final { + this->mqtt_client_.onUnsubscribe(std::move(callback)); + } + void set_on_message(std::function &&callback) final { + auto async_callback = [callback](const char *topic, const char *payload, + AsyncMqttClientMessageProperties async_properties, size_t len, size_t index, + size_t total) { callback(topic, payload, len, index, total); }; + mqtt_client_.onMessage(std::move(async_callback)); + } + void set_on_publish(std::function &&callback) final { + this->mqtt_client_.onPublish(std::move(callback)); + } + + bool connected() const final { return mqtt_client_.connected(); } + void connect() final { mqtt_client_.connect(); } + void disconnect() final { mqtt_client_.disconnect(true); } + bool subscribe(const char *topic, uint8_t qos) final { return mqtt_client_.subscribe(topic, qos) != 0; } + bool unsubscribe(const char *topic) final { return mqtt_client_.unsubscribe(topic) != 0; } + bool publish(const char *topic, const char *payload, size_t length, uint8_t qos, bool retain) final { + return mqtt_client_.publish(topic, qos, retain, payload, length, false, 0) != 0; + } + using MQTTBackend::publish; + + protected: + AsyncMqttClient mqtt_client_; +}; + +} // namespace mqtt +} // namespace esphome + +#endif // defined(USE_LIBRETINY) diff --git a/esphome/components/mqtt/mqtt_client.cpp b/esphome/components/mqtt/mqtt_client.cpp index 0c6da42328..fd5e13ecc7 100644 --- a/esphome/components/mqtt/mqtt_client.cpp +++ b/esphome/components/mqtt/mqtt_client.cpp @@ -106,6 +106,9 @@ void MQTTClientComponent::send_device_info_() { #ifdef USE_ESP32 root["platform"] = "ESP32"; #endif +#ifdef USE_LIBRETINY + root["platform"] = lt_cpu_get_model_name(); +#endif root["board"] = ESPHOME_BOARD; #if defined(USE_WIFI) @@ -156,7 +159,7 @@ void MQTTClientComponent::start_dnslookup_() { this->dns_resolve_error_ = false; this->dns_resolved_ = false; ip_addr_t addr; -#ifdef USE_ESP32 +#if defined(USE_ESP32) || defined(USE_LIBRETINY) err_t err = dns_gethostbyname_addrtype(this->credentials_.address.c_str(), &addr, MQTTClientComponent::dns_found_callback, this, LWIP_DNS_ADDRTYPE_IPV4); #endif diff --git a/esphome/components/mqtt/mqtt_client.h b/esphome/components/mqtt/mqtt_client.h index 00eb3fdd40..bcb44ab4c2 100644 --- a/esphome/components/mqtt/mqtt_client.h +++ b/esphome/components/mqtt/mqtt_client.h @@ -13,6 +13,8 @@ #include "mqtt_backend_esp32.h" #elif defined(USE_ESP8266) #include "mqtt_backend_esp8266.h" +#elif defined(USE_LIBRETINY) +#include "mqtt_backend_libretiny.h" #endif #include "lwip/ip_addr.h" @@ -300,6 +302,8 @@ class MQTTClientComponent : public Component { MQTTBackendESP32 mqtt_backend_; #elif defined(USE_ESP8266) MQTTBackendESP8266 mqtt_backend_; +#elif defined(USE_LIBRETINY) + MQTTBackendLibreTiny mqtt_backend_; #endif MQTTClientState state_{MQTT_CLIENT_DISCONNECTED}; From 86db559f6e8edf1f0e69cb300dedd1954ab766bd Mon Sep 17 00:00:00 2001 From: Guillermo Ruffino Date: Tue, 26 Sep 2023 20:25:00 -0300 Subject: [PATCH 0225/2101] Wireguard keepalive remove uint16 type (#5430) --- esphome/components/wireguard/__init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/esphome/components/wireguard/__init__.py b/esphome/components/wireguard/__init__.py index 717fe50d2c..acb5f690ec 100644 --- a/esphome/components/wireguard/__init__.py +++ b/esphome/components/wireguard/__init__.py @@ -9,6 +9,7 @@ from esphome.const import ( CONF_REBOOT_TIMEOUT, ) from esphome.components import time +from esphome.core import TimePeriod CONF_NETMASK = "netmask" CONF_PRIVATE_KEY = "private_key" @@ -59,9 +60,9 @@ CONFIG_SCHEMA = cv.Schema( cv.Optional(CONF_PEER_ALLOWED_IPS, default=["0.0.0.0/0"]): cv.ensure_list( _cidr_network ), - cv.Optional(CONF_PEER_PERSISTENT_KEEPALIVE, default=0): cv.Any( + cv.Optional(CONF_PEER_PERSISTENT_KEEPALIVE, default="0s"): cv.All( cv.positive_time_period_seconds, - cv.uint16_t, + cv.Range(max=TimePeriod(seconds=65535)), ), cv.Optional( CONF_REBOOT_TIMEOUT, default="15min" From 5360e14a9ce3f6e0b3e169ef0c555323a68ed81b Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Wed, 27 Sep 2023 09:25:14 +1000 Subject: [PATCH 0226/2101] Fix #4896 and #4903 (#5433) --- CODEOWNERS | 2 +- esphome/components/ili9xxx/display.py | 9 +++---- .../components/ili9xxx/ili9xxx_display.cpp | 12 ++++++++++ esphome/components/ili9xxx/ili9xxx_display.h | 6 +++++ esphome/components/ili9xxx/ili9xxx_init.h | 24 +++++++++++++++++++ tests/test1.yaml | 1 + 6 files changed, 47 insertions(+), 7 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index 22e46aa2f0..3920a9100e 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -131,7 +131,7 @@ esphome/components/i2s_audio/* @jesserockz esphome/components/i2s_audio/media_player/* @jesserockz esphome/components/i2s_audio/microphone/* @jesserockz esphome/components/i2s_audio/speaker/* @jesserockz -esphome/components/ili9xxx/* @nielsnl68 +esphome/components/ili9xxx/* @clydebarrow @nielsnl68 esphome/components/improv_base/* @esphome/core esphome/components/improv_serial/* @esphome/core esphome/components/ina260/* @mreditor97 diff --git a/esphome/components/ili9xxx/display.py b/esphome/components/ili9xxx/display.py index 0435460b6a..89a6b2d1b9 100644 --- a/esphome/components/ili9xxx/display.py +++ b/esphome/components/ili9xxx/display.py @@ -25,7 +25,7 @@ def AUTO_LOAD(): return [] -CODEOWNERS = ["@nielsnl68"] +CODEOWNERS = ["@nielsnl68", "@clydebarrow"] ili9XXX_ns = cg.esphome_ns.namespace("ili9xxx") ili9XXXSPI = ili9XXX_ns.class_( @@ -42,6 +42,7 @@ MODELS = { "ILI9341": ili9XXX_ns.class_("ILI9XXXILI9341", ili9XXXSPI), "ILI9342": ili9XXX_ns.class_("ILI9XXXILI9342", ili9XXXSPI), "ILI9481": ili9XXX_ns.class_("ILI9XXXILI9481", ili9XXXSPI), + "ILI9481-18": ili9XXX_ns.class_("ILI9XXXILI948118", ili9XXXSPI), "ILI9486": ili9XXX_ns.class_("ILI9XXXILI9486", ili9XXXSPI), "ILI9488": ili9XXX_ns.class_("ILI9XXXILI9488", ili9XXXSPI), "ILI9488_A": ili9XXX_ns.class_("ILI9XXXILI9488A", ili9XXXSPI), @@ -140,8 +141,6 @@ async def to_code(config): rhs = [] for x in range(256): rhs.extend([HexInt(x), HexInt(x), HexInt(x)]) - prog_arr = cg.progmem_array(config[CONF_RAW_DATA_ID], rhs) - cg.add(var.set_palette(prog_arr)) elif config[CONF_COLOR_PALETTE] == "IMAGE_ADAPTIVE": cg.add(var.set_buffer_color_mode(ILI9XXXColorMode.BITS_8_INDEXED)) from PIL import Image @@ -178,6 +177,4 @@ async def to_code(config): if rhs is not None: prog_arr = cg.progmem_array(config[CONF_RAW_DATA_ID], rhs) cg.add(var.set_palette(prog_arr)) - - spi_data_rate = str(spi.SPI_DATA_RATE_OPTIONS[config[CONF_DATA_RATE]]) - cg.add_define("ILI9XXXDisplay_DATA_RATE", cg.RawExpression(spi_data_rate)) + cg.add(var.set_data_rate(config[CONF_DATA_RATE])) diff --git a/esphome/components/ili9xxx/ili9xxx_display.cpp b/esphome/components/ili9xxx/ili9xxx_display.cpp index 750f629db2..abe01ea8c3 100644 --- a/esphome/components/ili9xxx/ili9xxx_display.cpp +++ b/esphome/components/ili9xxx/ili9xxx_display.cpp @@ -59,6 +59,7 @@ void ILI9XXXDisplay::dump_config() { if (this->is_18bitdisplay_) { ESP_LOGCONFIG(TAG, " 18-Bit Mode: YES"); } + ESP_LOGCONFIG(TAG, " Data rate: %dMHz", (unsigned) (this->data_rate_ / 1000000)); LOG_PIN(" Reset Pin: ", this->reset_pin_); LOG_PIN(" DC Pin: ", this->dc_pin_); @@ -387,6 +388,17 @@ void ILI9XXXILI9481::initialize() { } } +void ILI9XXXILI948118::initialize() { + this->init_lcd_(INITCMD_ILI9481_18); + if (this->width_ == 0) { + this->width_ = 320; + } + if (this->height_ == 0) { + this->height_ = 480; + } + this->is_18bitdisplay_ = true; +} + // 35_TFT display void ILI9XXXILI9486::initialize() { this->init_lcd_(INITCMD_ILI9486); diff --git a/esphome/components/ili9xxx/ili9xxx_display.h b/esphome/components/ili9xxx/ili9xxx_display.h index 15b08e6c76..4e8355b9a5 100644 --- a/esphome/components/ili9xxx/ili9xxx_display.h +++ b/esphome/components/ili9xxx/ili9xxx_display.h @@ -120,6 +120,12 @@ class ILI9XXXILI9481 : public ILI9XXXDisplay { void initialize() override; }; +//----------- ILI9481 in 18 bit mode -------------- +class ILI9XXXILI948118 : public ILI9XXXDisplay { + protected: + void initialize() override; +}; + //----------- ILI9XXX_35_TFT rotated display -------------- class ILI9XXXILI9486 : public ILI9XXXDisplay { protected: diff --git a/esphome/components/ili9xxx/ili9xxx_init.h b/esphome/components/ili9xxx/ili9xxx_init.h index 1856fb06ab..031dc25f91 100644 --- a/esphome/components/ili9xxx/ili9xxx_init.h +++ b/esphome/components/ili9xxx/ili9xxx_init.h @@ -94,12 +94,36 @@ static const uint8_t PROGMEM INITCMD_ILI9481[] = { ILI9XXX_IFCTR , 1, 0x83, ILI9XXX_GMCTR ,12, 0x00, 0x26, 0x21, 0x00, 0x00, 0x1F, 0x65, 0x23, 0x77, 0x00, 0x0F, 0x00, ILI9XXX_IFMODE , 1, 0x00, // CommandAccessProtect + ILI9XXX_PTLAR , 4, 0, 0, 1, 0xDF, 0xE4 , 1, 0xA0, + ILI9XXX_MADCTL , 1, MADCTL_MV | MADCTL_BGR, // Memory Access Control ILI9XXX_CSCON , 1, 0x01, + ILI9XXX_PIXFMT, 1, 0x55, // 16 bit mode + ILI9XXX_INVON, 0, ILI9XXX_DISPON, 0x80, // Set display on 0x00 // end }; +static const uint8_t PROGMEM INITCMD_ILI9481_18[] = { + ILI9XXX_SLPOUT , 0x80, // Exit sleep mode + ILI9XXX_PWSET , 3, 0x07, 0x41, 0x1D, + ILI9XXX_VMCTR , 3, 0x00, 0x1C, 0x1F, + ILI9XXX_PWSETN , 2, 0x01, 0x11, + ILI9XXX_PWCTR1 , 5, 0x10, 0x3B, 0x00, 0x02, 0x11, + ILI9XXX_VMCTR1 , 1, 0x03, + ILI9XXX_IFCTR , 1, 0x83, + ILI9XXX_GMCTR ,12, 0x00, 0x26, 0x21, 0x00, 0x00, 0x1F, 0x65, 0x23, 0x77, 0x00, 0x0F, 0x00, + ILI9XXX_IFMODE , 1, 0x00, // CommandAccessProtect + ILI9XXX_PTLAR , 4, 0, 0, 1, 0xDF, + 0xE4 , 1, 0xA0, + ILI9XXX_MADCTL , 1, MADCTL_MX| MADCTL_BGR, // Memory Access Control + ILI9XXX_CSCON , 1, 0x01, + ILI9XXX_PIXFMT, 1, 0x66, // 18 bit mode + ILI9XXX_INVON, 0, + ILI9XXX_DISPON, 0x80, // Set display on + 0x00 // end +}; + static const uint8_t PROGMEM INITCMD_ILI9486[] = { ILI9XXX_SLPOUT, 0x80, ILI9XXX_PIXFMT, 1, 0x55, diff --git a/tests/test1.yaml b/tests/test1.yaml index fe983cf421..350057e3cc 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -2972,6 +2972,7 @@ display: model: TFT 2.4 cs_pin: GPIO5 dc_pin: GPIO4 + color_palette: GRAYSCALE reset_pin: GPIO22 lambda: |- it.rectangle(0, 0, it.get_width(), it.get_height()); From b30bab8c1b310b5cb03bde7f86d8d8fc2e6ae3ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Tue, 26 Sep 2023 23:23:21 +0200 Subject: [PATCH 0227/2101] LibreTiny: enable MQTT, bump to v1.4.1 (#5419) --- esphome/components/libretiny/__init__.py | 2 +- esphome/components/mqtt/__init__.py | 8 +- .../components/mqtt/mqtt_backend_libretiny.h | 74 +++++++++++++++++++ esphome/components/mqtt/mqtt_client.cpp | 5 +- esphome/components/mqtt/mqtt_client.h | 4 + 5 files changed, 87 insertions(+), 6 deletions(-) create mode 100644 esphome/components/mqtt/mqtt_backend_libretiny.h diff --git a/esphome/components/libretiny/__init__.py b/esphome/components/libretiny/__init__.py index 3c1c0ac3f0..b01d342a87 100644 --- a/esphome/components/libretiny/__init__.py +++ b/esphome/components/libretiny/__init__.py @@ -170,7 +170,7 @@ def _notify_old_style(config): ARDUINO_VERSIONS = { "dev": (cv.Version(0, 0, 0), "https://github.com/libretiny-eu/libretiny.git"), "latest": (cv.Version(0, 0, 0), None), - "recommended": (cv.Version(1, 4, 0), None), + "recommended": (cv.Version(1, 4, 1), None), } diff --git a/esphome/components/mqtt/__init__.py b/esphome/components/mqtt/__init__.py index 9df2067832..10ae8ac40d 100644 --- a/esphome/components/mqtt/__init__.py +++ b/esphome/components/mqtt/__init__.py @@ -250,7 +250,7 @@ CONFIG_SCHEMA = cv.All( } ), validate_config, - cv.only_on(["esp32", "esp8266"]), + cv.only_on(["esp32", "esp8266", "bk72xx"]), ) @@ -271,10 +271,10 @@ 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 - if CORE.is_esp8266: + # 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 - cg.add_library("heman/AsyncMqttClient-esphome", "1.0.0") + cg.add_library("heman/AsyncMqttClient-esphome", "2.0.0") cg.add_define("USE_MQTT") cg.add_global(mqtt_ns.using) diff --git a/esphome/components/mqtt/mqtt_backend_libretiny.h b/esphome/components/mqtt/mqtt_backend_libretiny.h new file mode 100644 index 0000000000..5373a1926a --- /dev/null +++ b/esphome/components/mqtt/mqtt_backend_libretiny.h @@ -0,0 +1,74 @@ +#pragma once + +#ifdef USE_LIBRETINY + +#include "mqtt_backend.h" +#include + +namespace esphome { +namespace mqtt { + +class MQTTBackendLibreTiny final : public MQTTBackend { + public: + void set_keep_alive(uint16_t keep_alive) final { mqtt_client_.setKeepAlive(keep_alive); } + void set_client_id(const char *client_id) final { mqtt_client_.setClientId(client_id); } + void set_clean_session(bool clean_session) final { mqtt_client_.setCleanSession(clean_session); } + void set_credentials(const char *username, const char *password) final { + mqtt_client_.setCredentials(username, password); + } + void set_will(const char *topic, uint8_t qos, bool retain, const char *payload) final { + mqtt_client_.setWill(topic, qos, retain, payload); + } + void set_server(network::IPAddress ip, uint16_t port) final { + mqtt_client_.setServer(IPAddress(static_cast(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 &&callback) final { + this->mqtt_client_.onConnect(std::move(callback)); + } + void set_on_disconnect(std::function &&callback) final { + auto async_callback = [callback](AsyncMqttClientDisconnectReason reason) { + // int based enum so casting isn't a problem + callback(static_cast(reason)); + }; + this->mqtt_client_.onDisconnect(std::move(async_callback)); + } + void set_on_subscribe(std::function &&callback) final { + this->mqtt_client_.onSubscribe(std::move(callback)); + } + void set_on_unsubscribe(std::function &&callback) final { + this->mqtt_client_.onUnsubscribe(std::move(callback)); + } + void set_on_message(std::function &&callback) final { + auto async_callback = [callback](const char *topic, const char *payload, + AsyncMqttClientMessageProperties async_properties, size_t len, size_t index, + size_t total) { callback(topic, payload, len, index, total); }; + mqtt_client_.onMessage(std::move(async_callback)); + } + void set_on_publish(std::function &&callback) final { + this->mqtt_client_.onPublish(std::move(callback)); + } + + bool connected() const final { return mqtt_client_.connected(); } + void connect() final { mqtt_client_.connect(); } + void disconnect() final { mqtt_client_.disconnect(true); } + bool subscribe(const char *topic, uint8_t qos) final { return mqtt_client_.subscribe(topic, qos) != 0; } + bool unsubscribe(const char *topic) final { return mqtt_client_.unsubscribe(topic) != 0; } + bool publish(const char *topic, const char *payload, size_t length, uint8_t qos, bool retain) final { + return mqtt_client_.publish(topic, qos, retain, payload, length, false, 0) != 0; + } + using MQTTBackend::publish; + + protected: + AsyncMqttClient mqtt_client_; +}; + +} // namespace mqtt +} // namespace esphome + +#endif // defined(USE_LIBRETINY) diff --git a/esphome/components/mqtt/mqtt_client.cpp b/esphome/components/mqtt/mqtt_client.cpp index 0c6da42328..fd5e13ecc7 100644 --- a/esphome/components/mqtt/mqtt_client.cpp +++ b/esphome/components/mqtt/mqtt_client.cpp @@ -106,6 +106,9 @@ void MQTTClientComponent::send_device_info_() { #ifdef USE_ESP32 root["platform"] = "ESP32"; #endif +#ifdef USE_LIBRETINY + root["platform"] = lt_cpu_get_model_name(); +#endif root["board"] = ESPHOME_BOARD; #if defined(USE_WIFI) @@ -156,7 +159,7 @@ void MQTTClientComponent::start_dnslookup_() { this->dns_resolve_error_ = false; this->dns_resolved_ = false; ip_addr_t addr; -#ifdef USE_ESP32 +#if defined(USE_ESP32) || defined(USE_LIBRETINY) err_t err = dns_gethostbyname_addrtype(this->credentials_.address.c_str(), &addr, MQTTClientComponent::dns_found_callback, this, LWIP_DNS_ADDRTYPE_IPV4); #endif diff --git a/esphome/components/mqtt/mqtt_client.h b/esphome/components/mqtt/mqtt_client.h index 00eb3fdd40..bcb44ab4c2 100644 --- a/esphome/components/mqtt/mqtt_client.h +++ b/esphome/components/mqtt/mqtt_client.h @@ -13,6 +13,8 @@ #include "mqtt_backend_esp32.h" #elif defined(USE_ESP8266) #include "mqtt_backend_esp8266.h" +#elif defined(USE_LIBRETINY) +#include "mqtt_backend_libretiny.h" #endif #include "lwip/ip_addr.h" @@ -300,6 +302,8 @@ class MQTTClientComponent : public Component { MQTTBackendESP32 mqtt_backend_; #elif defined(USE_ESP8266) MQTTBackendESP8266 mqtt_backend_; +#elif defined(USE_LIBRETINY) + MQTTBackendLibreTiny mqtt_backend_; #endif MQTTClientState state_{MQTT_CLIENT_DISCONNECTED}; From 7dabbb65d081dbea8c266d7fbc9ac8bfb42dc461 Mon Sep 17 00:00:00 2001 From: Guillermo Ruffino Date: Tue, 26 Sep 2023 20:25:00 -0300 Subject: [PATCH 0228/2101] Wireguard keepalive remove uint16 type (#5430) --- esphome/components/wireguard/__init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/esphome/components/wireguard/__init__.py b/esphome/components/wireguard/__init__.py index 717fe50d2c..acb5f690ec 100644 --- a/esphome/components/wireguard/__init__.py +++ b/esphome/components/wireguard/__init__.py @@ -9,6 +9,7 @@ from esphome.const import ( CONF_REBOOT_TIMEOUT, ) from esphome.components import time +from esphome.core import TimePeriod CONF_NETMASK = "netmask" CONF_PRIVATE_KEY = "private_key" @@ -59,9 +60,9 @@ CONFIG_SCHEMA = cv.Schema( cv.Optional(CONF_PEER_ALLOWED_IPS, default=["0.0.0.0/0"]): cv.ensure_list( _cidr_network ), - cv.Optional(CONF_PEER_PERSISTENT_KEEPALIVE, default=0): cv.Any( + cv.Optional(CONF_PEER_PERSISTENT_KEEPALIVE, default="0s"): cv.All( cv.positive_time_period_seconds, - cv.uint16_t, + cv.Range(max=TimePeriod(seconds=65535)), ), cv.Optional( CONF_REBOOT_TIMEOUT, default="15min" From 69adebfefa13e5f50512a114fed10b54b0ce20b6 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Wed, 27 Sep 2023 09:25:14 +1000 Subject: [PATCH 0229/2101] Fix #4896 and #4903 (#5433) --- CODEOWNERS | 2 +- esphome/components/ili9xxx/display.py | 9 +++---- .../components/ili9xxx/ili9xxx_display.cpp | 12 ++++++++++ esphome/components/ili9xxx/ili9xxx_display.h | 6 +++++ esphome/components/ili9xxx/ili9xxx_init.h | 24 +++++++++++++++++++ tests/test1.yaml | 1 + 6 files changed, 47 insertions(+), 7 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index 22e46aa2f0..3920a9100e 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -131,7 +131,7 @@ esphome/components/i2s_audio/* @jesserockz esphome/components/i2s_audio/media_player/* @jesserockz esphome/components/i2s_audio/microphone/* @jesserockz esphome/components/i2s_audio/speaker/* @jesserockz -esphome/components/ili9xxx/* @nielsnl68 +esphome/components/ili9xxx/* @clydebarrow @nielsnl68 esphome/components/improv_base/* @esphome/core esphome/components/improv_serial/* @esphome/core esphome/components/ina260/* @mreditor97 diff --git a/esphome/components/ili9xxx/display.py b/esphome/components/ili9xxx/display.py index 0435460b6a..89a6b2d1b9 100644 --- a/esphome/components/ili9xxx/display.py +++ b/esphome/components/ili9xxx/display.py @@ -25,7 +25,7 @@ def AUTO_LOAD(): return [] -CODEOWNERS = ["@nielsnl68"] +CODEOWNERS = ["@nielsnl68", "@clydebarrow"] ili9XXX_ns = cg.esphome_ns.namespace("ili9xxx") ili9XXXSPI = ili9XXX_ns.class_( @@ -42,6 +42,7 @@ MODELS = { "ILI9341": ili9XXX_ns.class_("ILI9XXXILI9341", ili9XXXSPI), "ILI9342": ili9XXX_ns.class_("ILI9XXXILI9342", ili9XXXSPI), "ILI9481": ili9XXX_ns.class_("ILI9XXXILI9481", ili9XXXSPI), + "ILI9481-18": ili9XXX_ns.class_("ILI9XXXILI948118", ili9XXXSPI), "ILI9486": ili9XXX_ns.class_("ILI9XXXILI9486", ili9XXXSPI), "ILI9488": ili9XXX_ns.class_("ILI9XXXILI9488", ili9XXXSPI), "ILI9488_A": ili9XXX_ns.class_("ILI9XXXILI9488A", ili9XXXSPI), @@ -140,8 +141,6 @@ async def to_code(config): rhs = [] for x in range(256): rhs.extend([HexInt(x), HexInt(x), HexInt(x)]) - prog_arr = cg.progmem_array(config[CONF_RAW_DATA_ID], rhs) - cg.add(var.set_palette(prog_arr)) elif config[CONF_COLOR_PALETTE] == "IMAGE_ADAPTIVE": cg.add(var.set_buffer_color_mode(ILI9XXXColorMode.BITS_8_INDEXED)) from PIL import Image @@ -178,6 +177,4 @@ async def to_code(config): if rhs is not None: prog_arr = cg.progmem_array(config[CONF_RAW_DATA_ID], rhs) cg.add(var.set_palette(prog_arr)) - - spi_data_rate = str(spi.SPI_DATA_RATE_OPTIONS[config[CONF_DATA_RATE]]) - cg.add_define("ILI9XXXDisplay_DATA_RATE", cg.RawExpression(spi_data_rate)) + cg.add(var.set_data_rate(config[CONF_DATA_RATE])) diff --git a/esphome/components/ili9xxx/ili9xxx_display.cpp b/esphome/components/ili9xxx/ili9xxx_display.cpp index 750f629db2..abe01ea8c3 100644 --- a/esphome/components/ili9xxx/ili9xxx_display.cpp +++ b/esphome/components/ili9xxx/ili9xxx_display.cpp @@ -59,6 +59,7 @@ void ILI9XXXDisplay::dump_config() { if (this->is_18bitdisplay_) { ESP_LOGCONFIG(TAG, " 18-Bit Mode: YES"); } + ESP_LOGCONFIG(TAG, " Data rate: %dMHz", (unsigned) (this->data_rate_ / 1000000)); LOG_PIN(" Reset Pin: ", this->reset_pin_); LOG_PIN(" DC Pin: ", this->dc_pin_); @@ -387,6 +388,17 @@ void ILI9XXXILI9481::initialize() { } } +void ILI9XXXILI948118::initialize() { + this->init_lcd_(INITCMD_ILI9481_18); + if (this->width_ == 0) { + this->width_ = 320; + } + if (this->height_ == 0) { + this->height_ = 480; + } + this->is_18bitdisplay_ = true; +} + // 35_TFT display void ILI9XXXILI9486::initialize() { this->init_lcd_(INITCMD_ILI9486); diff --git a/esphome/components/ili9xxx/ili9xxx_display.h b/esphome/components/ili9xxx/ili9xxx_display.h index 15b08e6c76..4e8355b9a5 100644 --- a/esphome/components/ili9xxx/ili9xxx_display.h +++ b/esphome/components/ili9xxx/ili9xxx_display.h @@ -120,6 +120,12 @@ class ILI9XXXILI9481 : public ILI9XXXDisplay { void initialize() override; }; +//----------- ILI9481 in 18 bit mode -------------- +class ILI9XXXILI948118 : public ILI9XXXDisplay { + protected: + void initialize() override; +}; + //----------- ILI9XXX_35_TFT rotated display -------------- class ILI9XXXILI9486 : public ILI9XXXDisplay { protected: diff --git a/esphome/components/ili9xxx/ili9xxx_init.h b/esphome/components/ili9xxx/ili9xxx_init.h index 1856fb06ab..031dc25f91 100644 --- a/esphome/components/ili9xxx/ili9xxx_init.h +++ b/esphome/components/ili9xxx/ili9xxx_init.h @@ -94,12 +94,36 @@ static const uint8_t PROGMEM INITCMD_ILI9481[] = { ILI9XXX_IFCTR , 1, 0x83, ILI9XXX_GMCTR ,12, 0x00, 0x26, 0x21, 0x00, 0x00, 0x1F, 0x65, 0x23, 0x77, 0x00, 0x0F, 0x00, ILI9XXX_IFMODE , 1, 0x00, // CommandAccessProtect + ILI9XXX_PTLAR , 4, 0, 0, 1, 0xDF, 0xE4 , 1, 0xA0, + ILI9XXX_MADCTL , 1, MADCTL_MV | MADCTL_BGR, // Memory Access Control ILI9XXX_CSCON , 1, 0x01, + ILI9XXX_PIXFMT, 1, 0x55, // 16 bit mode + ILI9XXX_INVON, 0, ILI9XXX_DISPON, 0x80, // Set display on 0x00 // end }; +static const uint8_t PROGMEM INITCMD_ILI9481_18[] = { + ILI9XXX_SLPOUT , 0x80, // Exit sleep mode + ILI9XXX_PWSET , 3, 0x07, 0x41, 0x1D, + ILI9XXX_VMCTR , 3, 0x00, 0x1C, 0x1F, + ILI9XXX_PWSETN , 2, 0x01, 0x11, + ILI9XXX_PWCTR1 , 5, 0x10, 0x3B, 0x00, 0x02, 0x11, + ILI9XXX_VMCTR1 , 1, 0x03, + ILI9XXX_IFCTR , 1, 0x83, + ILI9XXX_GMCTR ,12, 0x00, 0x26, 0x21, 0x00, 0x00, 0x1F, 0x65, 0x23, 0x77, 0x00, 0x0F, 0x00, + ILI9XXX_IFMODE , 1, 0x00, // CommandAccessProtect + ILI9XXX_PTLAR , 4, 0, 0, 1, 0xDF, + 0xE4 , 1, 0xA0, + ILI9XXX_MADCTL , 1, MADCTL_MX| MADCTL_BGR, // Memory Access Control + ILI9XXX_CSCON , 1, 0x01, + ILI9XXX_PIXFMT, 1, 0x66, // 18 bit mode + ILI9XXX_INVON, 0, + ILI9XXX_DISPON, 0x80, // Set display on + 0x00 // end +}; + static const uint8_t PROGMEM INITCMD_ILI9486[] = { ILI9XXX_SLPOUT, 0x80, ILI9XXX_PIXFMT, 1, 0x55, diff --git a/tests/test1.yaml b/tests/test1.yaml index fe983cf421..350057e3cc 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -2972,6 +2972,7 @@ display: model: TFT 2.4 cs_pin: GPIO5 dc_pin: GPIO4 + color_palette: GRAYSCALE reset_pin: GPIO22 lambda: |- it.rectangle(0, 0, it.get_width(), it.get_height()); From e5bae8187f0886360a0807eaec6a83acf591a5db Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 27 Sep 2023 12:28:12 +1300 Subject: [PATCH 0230/2101] Bump version to 2023.9.0b4 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index f5319adfa7..c5cc7010a9 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2023.9.0b3" +__version__ = "2023.9.0b4" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From cc1b7a7a569e89c509d7810b87b56690cc23ee36 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 27 Sep 2023 16:21:35 +1300 Subject: [PATCH 0231/2101] Bump version to 2023.9.0 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index c5cc7010a9..bf703d9595 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2023.9.0b4" +__version__ = "2023.9.0" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 9d4f471855fcf3cab19368d0558f17a25629f0dc Mon Sep 17 00:00:00 2001 From: Marc J Date: Wed, 27 Sep 2023 00:45:21 -0700 Subject: [PATCH 0232/2101] Tuya Number Scaling by step value (#5108) --- esphome/components/tuya/number/tuya_number.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/esphome/components/tuya/number/tuya_number.cpp b/esphome/components/tuya/number/tuya_number.cpp index 5c7cafbf7a..30ef8b8f72 100644 --- a/esphome/components/tuya/number/tuya_number.cpp +++ b/esphome/components/tuya/number/tuya_number.cpp @@ -10,7 +10,7 @@ void TuyaNumber::setup() { this->parent_->register_listener(this->number_id_, [this](const TuyaDatapoint &datapoint) { if (datapoint.type == TuyaDatapointType::INTEGER) { ESP_LOGV(TAG, "MCU reported number %u is: %d", datapoint.id, datapoint.value_int); - this->publish_state(datapoint.value_int); + this->publish_state(datapoint.value_int * this->traits.get_step()); } else if (datapoint.type == TuyaDatapointType::ENUM) { ESP_LOGV(TAG, "MCU reported number %u is: %u", datapoint.id, datapoint.value_enum); this->publish_state(datapoint.value_enum); @@ -22,7 +22,8 @@ void TuyaNumber::setup() { void TuyaNumber::control(float value) { ESP_LOGV(TAG, "Setting number %u: %f", this->number_id_, value); if (this->type_ == TuyaDatapointType::INTEGER) { - this->parent_->set_integer_datapoint_value(this->number_id_, value); + int integer_value = lround(value / this->traits.get_step()); + this->parent_->set_integer_datapoint_value(this->number_id_, integer_value); } else if (this->type_ == TuyaDatapointType::ENUM) { this->parent_->set_enum_datapoint_value(this->number_id_, value); } From 57b7dd0fa24d749420747729be854eb381a3238e Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Wed, 27 Sep 2023 10:38:43 +0200 Subject: [PATCH 0233/2101] Refactor ip address representation (#5252) --- .../captive_portal/captive_portal.cpp | 2 +- esphome/components/e131/e131_packet.cpp | 7 +- .../ethernet/ethernet_component.cpp | 41 +++---- esphome/components/mdns/mdns_rp2040.cpp | 3 +- .../components/mqtt/mqtt_backend_esp8266.h | 4 +- esphome/components/mqtt/mqtt_client.cpp | 12 +- esphome/components/network/ip_address.h | 110 ++++++++++++++---- .../components/wake_on_lan/wake_on_lan.cpp | 5 +- .../wifi/wifi_component_esp32_arduino.cpp | 55 ++++----- .../wifi/wifi_component_esp8266.cpp | 46 ++++---- .../wifi/wifi_component_esp_idf.cpp | 53 ++++----- .../wifi/wifi_component_libretiny.cpp | 7 +- .../components/wifi/wifi_component_pico_w.cpp | 22 ++-- tests/test1.yaml | 3 + tests/test10.yaml | 3 + tests/test11.5.yaml | 3 + tests/test2.yaml | 3 + tests/test3.1.yaml | 3 + tests/test3.yaml | 3 + tests/test4.yaml | 3 + tests/test5.yaml | 3 + tests/test6.yaml | 3 + tests/test7.yaml | 3 + tests/test8.yaml | 3 + 24 files changed, 225 insertions(+), 175 deletions(-) diff --git a/esphome/components/captive_portal/captive_portal.cpp b/esphome/components/captive_portal/captive_portal.cpp index 74c6606fc0..cc78528e46 100644 --- a/esphome/components/captive_portal/captive_portal.cpp +++ b/esphome/components/captive_portal/captive_portal.cpp @@ -48,7 +48,7 @@ void CaptivePortal::start() { this->dns_server_ = make_unique(); this->dns_server_->setErrorReplyCode(DNSReplyCode::NoError); network::IPAddress ip = wifi::global_wifi_component->wifi_soft_ap_ip(); - this->dns_server_->start(53, "*", (uint32_t) ip); + this->dns_server_->start(53, "*", IPAddress(ip)); #endif this->base_->get_server()->onNotFound([this](AsyncWebServerRequest *req) { diff --git a/esphome/components/e131/e131_packet.cpp b/esphome/components/e131/e131_packet.cpp index ac8b72f6e7..e1ae41cbaf 100644 --- a/esphome/components/e131/e131_packet.cpp +++ b/esphome/components/e131/e131_packet.cpp @@ -67,8 +67,8 @@ bool E131Component::join_igmp_groups_() { if (!universe.second) continue; - ip4_addr_t multicast_addr = {static_cast( - network::IPAddress(239, 255, ((universe.first >> 8) & 0xff), ((universe.first >> 0) & 0xff)))}; + ip4_addr_t multicast_addr = + network::IPAddress(239, 255, ((universe.first >> 8) & 0xff), ((universe.first >> 0) & 0xff)); auto err = igmp_joingroup(IP4_ADDR_ANY4, &multicast_addr); @@ -101,8 +101,7 @@ void E131Component::leave_(int universe) { } if (listen_method_ == E131_MULTICAST) { - ip4_addr_t multicast_addr = { - static_cast(network::IPAddress(239, 255, ((universe >> 8) & 0xff), ((universe >> 0) & 0xff)))}; + ip4_addr_t multicast_addr = network::IPAddress(239, 255, ((universe >> 8) & 0xff), ((universe >> 0) & 0xff)); igmp_leavegroup(IP4_ADDR_ANY4, &multicast_addr); } diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index 59d2e4c4d6..03fdc49338 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -236,7 +236,7 @@ bool EthernetComponent::can_proceed() { return this->is_connected(); } network::IPAddress EthernetComponent::get_ip_address() { esp_netif_ip_info_t ip; esp_netif_get_ip_info(this->eth_netif_, &ip); - return {ip.ip.addr}; + return network::IPAddress(&ip.ip); } void EthernetComponent::eth_event_handler(void *arg, esp_event_base_t event_base, int32_t event, void *event_data) { @@ -293,9 +293,9 @@ void EthernetComponent::start_connect_() { esp_netif_ip_info_t info; if (this->manual_ip_.has_value()) { - info.ip.addr = static_cast(this->manual_ip_->static_ip); - info.gw.addr = static_cast(this->manual_ip_->gateway); - info.netmask.addr = static_cast(this->manual_ip_->subnet); + info.ip = this->manual_ip_->static_ip; + info.gw = this->manual_ip_->gateway; + info.netmask = this->manual_ip_->subnet; } else { info.ip.addr = 0; info.gw.addr = 0; @@ -318,24 +318,14 @@ void EthernetComponent::start_connect_() { ESPHL_ERROR_CHECK(err, "DHCPC set IP info error"); if (this->manual_ip_.has_value()) { - if (uint32_t(this->manual_ip_->dns1) != 0) { + if (this->manual_ip_->dns1.is_set()) { ip_addr_t d; -#if LWIP_IPV6 - d.type = IPADDR_TYPE_V4; - d.u_addr.ip4.addr = static_cast(this->manual_ip_->dns1); -#else - d.addr = static_cast(this->manual_ip_->dns1); -#endif + d = this->manual_ip_->dns1; dns_setserver(0, &d); } - if (uint32_t(this->manual_ip_->dns2) != 0) { + if (this->manual_ip_->dns2.is_set()) { ip_addr_t d; -#if LWIP_IPV6 - d.type = IPADDR_TYPE_V4; - d.u_addr.ip4.addr = static_cast(this->manual_ip_->dns2); -#else - d.addr = static_cast(this->manual_ip_->dns2); -#endif + d = this->manual_ip_->dns2; dns_setserver(1, &d); } } else { @@ -360,21 +350,16 @@ bool EthernetComponent::is_connected() { return this->state_ == EthernetComponen void EthernetComponent::dump_connect_params_() { esp_netif_ip_info_t ip; esp_netif_get_ip_info(this->eth_netif_, &ip); - ESP_LOGCONFIG(TAG, " IP Address: %s", network::IPAddress(ip.ip.addr).str().c_str()); + ESP_LOGCONFIG(TAG, " IP Address: %s", network::IPAddress(&ip.ip).str().c_str()); ESP_LOGCONFIG(TAG, " Hostname: '%s'", App.get_name().c_str()); - ESP_LOGCONFIG(TAG, " Subnet: %s", network::IPAddress(ip.netmask.addr).str().c_str()); - ESP_LOGCONFIG(TAG, " Gateway: %s", network::IPAddress(ip.gw.addr).str().c_str()); + ESP_LOGCONFIG(TAG, " Subnet: %s", network::IPAddress(&ip.netmask).str().c_str()); + ESP_LOGCONFIG(TAG, " Gateway: %s", network::IPAddress(&ip.gw).str().c_str()); const ip_addr_t *dns_ip1 = dns_getserver(0); const ip_addr_t *dns_ip2 = dns_getserver(1); -#if LWIP_IPV6 - ESP_LOGCONFIG(TAG, " DNS1: %s", network::IPAddress(dns_ip1->u_addr.ip4.addr).str().c_str()); - ESP_LOGCONFIG(TAG, " DNS2: %s", network::IPAddress(dns_ip2->u_addr.ip4.addr).str().c_str()); -#else - ESP_LOGCONFIG(TAG, " DNS1: %s", network::IPAddress(dns_ip1->addr).str().c_str()); - ESP_LOGCONFIG(TAG, " DNS2: %s", network::IPAddress(dns_ip2->addr).str().c_str()); -#endif + ESP_LOGCONFIG(TAG, " DNS1: %s", network::IPAddress(dns_ip1).str().c_str()); + ESP_LOGCONFIG(TAG, " DNS2: %s", network::IPAddress(dns_ip2).str().c_str()); #if ENABLE_IPV6 if (this->ipv6_count_ > 0) { diff --git a/esphome/components/mdns/mdns_rp2040.cpp b/esphome/components/mdns/mdns_rp2040.cpp index b30a3a4ee7..56afd6f5e1 100644 --- a/esphome/components/mdns/mdns_rp2040.cpp +++ b/esphome/components/mdns/mdns_rp2040.cpp @@ -13,8 +13,7 @@ namespace mdns { void MDNSComponent::setup() { this->compile_records_(); - network::IPAddress addr = network::get_ip_address(); - MDNS.begin(this->hostname_.c_str(), (uint32_t) addr); + MDNS.begin(this->hostname_.c_str()); for (const auto &service : this->services_) { // Strip the leading underscore from the proto and service_type. While it is diff --git a/esphome/components/mqtt/mqtt_backend_esp8266.h b/esphome/components/mqtt/mqtt_backend_esp8266.h index 2d91877e9d..981d27693f 100644 --- a/esphome/components/mqtt/mqtt_backend_esp8266.h +++ b/esphome/components/mqtt/mqtt_backend_esp8266.h @@ -19,9 +19,7 @@ class MQTTBackendESP8266 final : public MQTTBackend { void set_will(const char *topic, uint8_t qos, bool retain, const char *payload) final { mqtt_client_.setWill(topic, qos, retain, payload); } - void set_server(network::IPAddress ip, uint16_t port) final { - mqtt_client_.setServer(IPAddress(static_cast(ip)), port); - } + 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); } diff --git a/esphome/components/mqtt/mqtt_client.cpp b/esphome/components/mqtt/mqtt_client.cpp index fd5e13ecc7..6f63935e6e 100644 --- a/esphome/components/mqtt/mqtt_client.cpp +++ b/esphome/components/mqtt/mqtt_client.cpp @@ -171,11 +171,7 @@ void MQTTClientComponent::start_dnslookup_() { case ERR_OK: { // Got IP immediately this->dns_resolved_ = true; -#if LWIP_IPV6 - this->ip_ = addr.u_addr.ip4.addr; -#else - this->ip_ = addr.addr; -#endif + this->ip_ = network::IPAddress(&addr); this->start_connect_(); return; } @@ -226,11 +222,7 @@ void MQTTClientComponent::dns_found_callback(const char *name, const ip_addr_t * if (ipaddr == nullptr) { a_this->dns_resolve_error_ = true; } else { -#if LWIP_IPV6 - a_this->ip_ = ipaddr->u_addr.ip4.addr; -#else - a_this->ip_ = ipaddr->addr; -#endif + a_this->ip_ = network::IPAddress(ipaddr); a_this->dns_resolved_ = true; } } diff --git a/esphome/components/network/ip_address.h b/esphome/components/network/ip_address.h index af198179ba..8b05237c05 100644 --- a/esphome/components/network/ip_address.h +++ b/esphome/components/network/ip_address.h @@ -3,42 +3,104 @@ #include #include #include +#include + +#if USE_ARDUINO +#include +#include +#endif /* USE_ADRDUINO */ + +#if USE_ESP32_FRAMEWORK_ARDUINO +#define arduino_ns Arduino_h +#elif USE_LIBRETINY +#define arduino_ns arduino +#elif USE_ARDUINO +#define arduino_ns +#endif + +#ifdef USE_ESP32 +#include +#include +#endif namespace esphome { namespace network { struct IPAddress { public: - IPAddress() : addr_({0, 0, 0, 0}) {} - IPAddress(uint8_t first, uint8_t second, uint8_t third, uint8_t fourth) : addr_({first, second, third, fourth}) {} - IPAddress(uint32_t raw) { - addr_[0] = (uint8_t) (raw >> 0); - addr_[1] = (uint8_t) (raw >> 8); - addr_[2] = (uint8_t) (raw >> 16); - addr_[3] = (uint8_t) (raw >> 24); + IPAddress() { ip_addr_set_zero(&ip_addr_); } + IPAddress(uint8_t first, uint8_t second, uint8_t third, uint8_t fourth) { + IP_ADDR4(&ip_addr_, first, second, third, fourth); } - operator uint32_t() const { - uint32_t res = 0; - res |= ((uint32_t) addr_[0]) << 0; - res |= ((uint32_t) addr_[1]) << 8; - res |= ((uint32_t) addr_[2]) << 16; - res |= ((uint32_t) addr_[3]) << 24; - return res; + IPAddress(const ip_addr_t *other_ip) { ip_addr_copy(ip_addr_, *other_ip); } + IPAddress(const std::string &in_address) { ipaddr_aton(in_address.c_str(), &ip_addr_); } + IPAddress(ip4_addr_t *other_ip) { memcpy((void *) &ip_addr_, (void *) other_ip, sizeof(ip4_addr_t)); } +#if USE_ARDUINO + IPAddress(const arduino_ns::IPAddress &other_ip) { ip_addr_set_ip4_u32(&ip_addr_, other_ip); } +#endif +#if LWIP_IPV6 + IPAddress(ip6_addr_t *other_ip) { + memcpy((void *) &ip_addr_, (void *) other_ip, sizeof(ip6_addr_t)); + ip_addr_.type = IPADDR_TYPE_V6; } - std::string str() const { - char buffer[24]; - snprintf(buffer, sizeof(buffer), "%d.%d.%d.%d", addr_[0], addr_[1], addr_[2], addr_[3]); - return buffer; +#endif /* LWIP_IPV6 */ + +#ifdef USE_ESP32 +#if LWIP_IPV6 + IPAddress(esp_ip6_addr_t *other_ip) { + memcpy((void *) &ip_addr_.u_addr.ip6, (void *) other_ip, sizeof(esp_ip6_addr_t)); + ip_addr_.type = IPADDR_TYPE_V6; } - bool operator==(const IPAddress &other) const { - return addr_[0] == other.addr_[0] && addr_[1] == other.addr_[1] && addr_[2] == other.addr_[2] && - addr_[3] == other.addr_[3]; +#endif /* LWIP_IPV6 */ + IPAddress(esp_ip4_addr_t *other_ip) { memcpy((void *) &ip_addr_, (void *) other_ip, sizeof(esp_ip4_addr_t)); } + operator esp_ip_addr_t() const { + esp_ip_addr_t tmp; +#if LWIP_IPV6 + memcpy((void *) &tmp, (void *) &ip_addr_, sizeof(ip_addr_)); +#else + memcpy((void *) &tmp.u_addr.ip4, (void *) &ip_addr_, sizeof(ip_addr_)); +#endif /* LWIP_IPV6 */ + return tmp; + } + operator esp_ip4_addr_t() const { + esp_ip4_addr_t tmp; +#if LWIP_IPV6 + memcpy((void *) &tmp, (void *) &ip_addr_.u_addr.ip4, sizeof(esp_ip4_addr_t)); +#else + memcpy((void *) &tmp, (void *) &ip_addr_, sizeof(ip_addr_)); +#endif /* LWIP_IPV6 */ + return tmp; + } +#endif /* USE_ESP32 */ + + operator ip_addr_t() const { return ip_addr_; } +#if LWIP_IPV6 + operator ip4_addr_t() const { return *ip_2_ip4(&ip_addr_); } +#endif /* LWIP_IPV6 */ + +#if USE_ARDUINO + operator arduino_ns::IPAddress() const { return ip_addr_get_ip4_u32(&ip_addr_); } +#endif + + bool is_set() { return !ip_addr_isany(&ip_addr_); } + bool is_ip4() { return IP_IS_V4(&ip_addr_); } + bool is_ip6() { return IP_IS_V6(&ip_addr_); } + std::string str() const { return ipaddr_ntoa(&ip_addr_); } + bool operator==(const IPAddress &other) const { return ip_addr_cmp(&ip_addr_, &other.ip_addr_); } + bool operator!=(const IPAddress &other) const { return !(&ip_addr_ == &other.ip_addr_); } + IPAddress &operator+=(uint8_t increase) { + if (IP_IS_V4(&ip_addr_)) { +#if LWIP_IPV6 + (((u8_t *) (&ip_addr_.u_addr.ip4))[3]) += increase; +#else + (((u8_t *) (&ip_addr_.addr))[3]) += increase; +#endif /* LWIP_IPV6 */ + } + return *this; } - uint8_t operator[](int index) const { return addr_[index]; } - uint8_t &operator[](int index) { return addr_[index]; } protected: - std::array addr_; + ip_addr_t ip_addr_; }; } // namespace network diff --git a/esphome/components/wake_on_lan/wake_on_lan.cpp b/esphome/components/wake_on_lan/wake_on_lan.cpp index 893aa75895..a4dd0f3b6f 100644 --- a/esphome/components/wake_on_lan/wake_on_lan.cpp +++ b/esphome/components/wake_on_lan/wake_on_lan.cpp @@ -30,11 +30,10 @@ void WakeOnLanButton::press_action() { ESP_LOGI(TAG, "Sending Wake-on-LAN Packet..."); bool begin_status = false; bool end_status = false; - uint32_t interface = esphome::network::get_ip_address(); - IPAddress interface_ip = IPAddress(interface); IPAddress broadcast = IPAddress(255, 255, 255, 255); #ifdef USE_ESP8266 - begin_status = this->udp_client_.beginPacketMulticast(broadcast, 9, interface_ip, 128); + begin_status = this->udp_client_.beginPacketMulticast(broadcast, 9, + IPAddress((ip_addr_t) esphome::network::get_ip_address()), 128); #endif #ifdef USE_ESP32 begin_status = this->udp_client_.beginPacket(broadcast, 9); diff --git a/esphome/components/wifi/wifi_component_esp32_arduino.cpp b/esphome/components/wifi/wifi_component_esp32_arduino.cpp index 5b147b20c6..17b15757ef 100644 --- a/esphome/components/wifi/wifi_component_esp32_arduino.cpp +++ b/esphome/components/wifi/wifi_component_esp32_arduino.cpp @@ -113,9 +113,9 @@ bool WiFiComponent::wifi_sta_ip_config_(optional manual_ip) { tcpip_adapter_ip_info_t info; memset(&info, 0, sizeof(info)); - info.ip.addr = static_cast(manual_ip->static_ip); - info.gw.addr = static_cast(manual_ip->gateway); - info.netmask.addr = static_cast(manual_ip->subnet); + info.ip = manual_ip->static_ip; + info.gw = manual_ip->gateway; + info.netmask = manual_ip->subnet; esp_err_t dhcp_stop_ret = tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA); if (dhcp_stop_ret != ESP_OK && dhcp_stop_ret != ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED) { @@ -128,23 +128,16 @@ bool WiFiComponent::wifi_sta_ip_config_(optional manual_ip) { } ip_addr_t dns; +// TODO: is this needed? #if LWIP_IPV6 dns.type = IPADDR_TYPE_V4; #endif - if (uint32_t(manual_ip->dns1) != 0) { -#if LWIP_IPV6 - dns.u_addr.ip4.addr = static_cast(manual_ip->dns1); -#else - dns.addr = static_cast(manual_ip->dns1); -#endif + if (manual_ip->dns1.is_set()) { + dns = manual_ip->dns1; dns_setserver(0, &dns); } - if (uint32_t(manual_ip->dns2) != 0) { -#if LWIP_IPV6 - dns.u_addr.ip4.addr = static_cast(manual_ip->dns2); -#else - dns.addr = static_cast(manual_ip->dns2); -#endif + if (manual_ip->dns2.is_set()) { + dns = manual_ip->dns2; dns_setserver(1, &dns); } @@ -156,7 +149,7 @@ network::IPAddress WiFiComponent::wifi_sta_ip() { return {}; tcpip_adapter_ip_info_t ip; tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip); - return {ip.ip.addr}; + return network::IPAddress(&ip.ip); } bool WiFiComponent::wifi_apply_hostname_() { @@ -614,13 +607,13 @@ bool WiFiComponent::wifi_ap_ip_config_(optional manual_ip) { tcpip_adapter_ip_info_t info; memset(&info, 0, sizeof(info)); if (manual_ip.has_value()) { - info.ip.addr = static_cast(manual_ip->static_ip); - info.gw.addr = static_cast(manual_ip->gateway); - info.netmask.addr = static_cast(manual_ip->subnet); + info.ip = manual_ip->static_ip; + info.gw = manual_ip->gateway; + info.netmask = manual_ip->subnet; } else { - info.ip.addr = static_cast(network::IPAddress(192, 168, 4, 1)); - info.gw.addr = static_cast(network::IPAddress(192, 168, 4, 1)); - info.netmask.addr = static_cast(network::IPAddress(255, 255, 255, 0)); + info.ip = network::IPAddress(192, 168, 4, 1); + info.gw = network::IPAddress(192, 168, 4, 1); + info.netmask = network::IPAddress(255, 255, 255, 0); } tcpip_adapter_dhcp_status_t dhcp_status; tcpip_adapter_dhcps_get_status(TCPIP_ADAPTER_IF_AP, &dhcp_status); @@ -638,12 +631,12 @@ bool WiFiComponent::wifi_ap_ip_config_(optional manual_ip) { dhcps_lease_t lease; lease.enable = true; - network::IPAddress start_address = info.ip.addr; - start_address[3] += 99; - lease.start_ip.addr = static_cast(start_address); + network::IPAddress start_address = network::IPAddress(&info.ip); + start_address += 99; + lease.start_ip = start_address; ESP_LOGV(TAG, "DHCP server IP lease start: %s", start_address.str().c_str()); - start_address[3] += 100; - lease.end_ip.addr = static_cast(start_address); + start_address += 100; + lease.end_ip = start_address; ESP_LOGV(TAG, "DHCP server IP lease end: %s", start_address.str().c_str()); err = tcpip_adapter_dhcps_option(TCPIP_ADAPTER_OP_SET, TCPIP_ADAPTER_REQUESTED_IP_ADDRESS, &lease, sizeof(lease)); @@ -702,7 +695,7 @@ bool WiFiComponent::wifi_start_ap_(const WiFiAP &ap) { network::IPAddress WiFiComponent::wifi_soft_ap_ip() { tcpip_adapter_ip_info_t ip; tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, &ip); - return {ip.ip.addr}; + return network::IPAddress(&ip.ip); } bool WiFiComponent::wifi_disconnect_() { return esp_wifi_disconnect(); } @@ -718,9 +711,9 @@ bssid_t WiFiComponent::wifi_bssid() { std::string WiFiComponent::wifi_ssid() { return WiFi.SSID().c_str(); } int8_t WiFiComponent::wifi_rssi() { return WiFi.RSSI(); } int32_t WiFiComponent::wifi_channel_() { return WiFi.channel(); } -network::IPAddress WiFiComponent::wifi_subnet_mask_() { return {WiFi.subnetMask()}; } -network::IPAddress WiFiComponent::wifi_gateway_ip_() { return {WiFi.gatewayIP()}; } -network::IPAddress WiFiComponent::wifi_dns_ip_(int num) { return {WiFi.dnsIP(num)}; } +network::IPAddress WiFiComponent::wifi_subnet_mask_() { return network::IPAddress(WiFi.subnetMask()); } +network::IPAddress WiFiComponent::wifi_gateway_ip_() { return network::IPAddress(WiFi.gatewayIP()); } +network::IPAddress WiFiComponent::wifi_dns_ip_(int num) { return network::IPAddress(WiFi.dnsIP(num)); } void WiFiComponent::wifi_loop_() {} } // namespace wifi diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index 6e7c491967..a48c6c711d 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -147,9 +147,9 @@ bool WiFiComponent::wifi_sta_ip_config_(optional manual_ip) { #endif struct ip_info info {}; - info.ip.addr = static_cast(manual_ip->static_ip); - info.gw.addr = static_cast(manual_ip->gateway); - info.netmask.addr = static_cast(manual_ip->subnet); + info.ip = manual_ip->static_ip; + info.gw = manual_ip->gateway; + info.netmask = manual_ip->subnet; if (dhcp_status == DHCP_STARTED) { bool dhcp_stop_ret = wifi_station_dhcpc_stop(); @@ -165,12 +165,12 @@ bool WiFiComponent::wifi_sta_ip_config_(optional manual_ip) { } ip_addr_t dns; - if (uint32_t(manual_ip->dns1) != 0) { - ip_addr_set_ip4_u32_val(dns, static_cast(manual_ip->dns1)); + if (manual_ip->dns1.is_set()) { + dns = manual_ip->dns1; dns_setserver(0, &dns); } - if (uint32_t(manual_ip->dns2) != 0) { - ip_addr_set_ip4_u32_val(dns, static_cast(manual_ip->dns2)); + if (manual_ip->dns2.is_set()) { + dns = manual_ip->dns2; dns_setserver(1, &dns); } @@ -190,7 +190,7 @@ network::IPAddress WiFiComponent::wifi_sta_ip() { return {}; struct ip_info ip {}; wifi_get_ip_info(STATION_IF, &ip); - return {ip.ip.addr}; + return network::IPAddress(&ip.ip); } bool WiFiComponent::wifi_apply_hostname_() { const std::string &hostname = App.get_name(); @@ -695,13 +695,13 @@ bool WiFiComponent::wifi_ap_ip_config_(optional manual_ip) { struct ip_info info {}; if (manual_ip.has_value()) { - info.ip.addr = static_cast(manual_ip->static_ip); - info.gw.addr = static_cast(manual_ip->gateway); - info.netmask.addr = static_cast(manual_ip->subnet); + info.ip = manual_ip->static_ip; + info.gw = manual_ip->gateway; + info.netmask = manual_ip->subnet; } else { - info.ip.addr = static_cast(network::IPAddress(192, 168, 4, 1)); - info.gw.addr = static_cast(network::IPAddress(192, 168, 4, 1)); - info.netmask.addr = static_cast(network::IPAddress(255, 255, 255, 0)); + info.ip = network::IPAddress(192, 168, 4, 1); + info.gw = network::IPAddress(192, 168, 4, 1); + info.netmask = network::IPAddress(255, 255, 255, 0); } if (wifi_softap_dhcps_status() == DHCP_STARTED) { @@ -721,12 +721,12 @@ bool WiFiComponent::wifi_ap_ip_config_(optional manual_ip) { struct dhcps_lease lease {}; lease.enable = true; - network::IPAddress start_address = info.ip.addr; - start_address[3] += 99; - lease.start_ip.addr = static_cast(start_address); + network::IPAddress start_address = network::IPAddress(&info.ip); + start_address += 99; + lease.start_ip = start_address; ESP_LOGV(TAG, "DHCP server IP lease start: %s", start_address.str().c_str()); - start_address[3] += 100; - lease.end_ip.addr = static_cast(start_address); + start_address += 100; + lease.end_ip = start_address; ESP_LOGV(TAG, "DHCP server IP lease end: %s", start_address.str().c_str()); if (!wifi_softap_set_dhcps_lease(&lease)) { ESP_LOGV(TAG, "Setting SoftAP DHCP lease failed!"); @@ -793,7 +793,7 @@ bool WiFiComponent::wifi_start_ap_(const WiFiAP &ap) { network::IPAddress WiFiComponent::wifi_soft_ap_ip() { struct ip_info ip {}; wifi_get_ip_info(SOFTAP_IF, &ip); - return {ip.ip.addr}; + return network::IPAddress(&ip.ip); } bssid_t WiFiComponent::wifi_bssid() { bssid_t bssid{}; @@ -807,9 +807,9 @@ bssid_t WiFiComponent::wifi_bssid() { std::string WiFiComponent::wifi_ssid() { return WiFi.SSID().c_str(); } int8_t WiFiComponent::wifi_rssi() { return WiFi.RSSI(); } int32_t WiFiComponent::wifi_channel_() { return WiFi.channel(); } -network::IPAddress WiFiComponent::wifi_subnet_mask_() { return {WiFi.subnetMask()}; } -network::IPAddress WiFiComponent::wifi_gateway_ip_() { return {WiFi.gatewayIP()}; } -network::IPAddress WiFiComponent::wifi_dns_ip_(int num) { return {WiFi.dnsIP(num)}; } +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)}; } void WiFiComponent::wifi_loop_() {} } // namespace wifi diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index 0ff9e932b2..34ecaf887d 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -437,9 +437,9 @@ bool WiFiComponent::wifi_sta_ip_config_(optional manual_ip) { } esp_netif_ip_info_t info; // struct of ip4_addr_t with ip, netmask, gw - info.ip.addr = static_cast(manual_ip->static_ip); - info.gw.addr = static_cast(manual_ip->gateway); - info.netmask.addr = static_cast(manual_ip->subnet); + info.ip = manual_ip->static_ip; + info.gw = manual_ip->gateway; + info.netmask = manual_ip->subnet; err = esp_netif_dhcpc_stop(s_sta_netif); if (err != ESP_OK && err != ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED) { ESP_LOGV(TAG, "esp_netif_dhcpc_stop failed: %s", esp_err_to_name(err)); @@ -452,12 +452,12 @@ bool WiFiComponent::wifi_sta_ip_config_(optional manual_ip) { } esp_netif_dns_info_t dns; - if (uint32_t(manual_ip->dns1) != 0) { - dns.ip.u_addr.ip4.addr = static_cast(manual_ip->dns1); + if (manual_ip->dns1.is_set()) { + dns.ip = manual_ip->dns1; esp_netif_set_dns_info(s_sta_netif, ESP_NETIF_DNS_MAIN, &dns); } - if (uint32_t(manual_ip->dns2) != 0) { - dns.ip.u_addr.ip4.addr = static_cast(manual_ip->dns2); + if (manual_ip->dns2.is_set()) { + dns.ip = manual_ip->dns2; esp_netif_set_dns_info(s_sta_netif, ESP_NETIF_DNS_BACKUP, &dns); } @@ -471,9 +471,10 @@ network::IPAddress WiFiComponent::wifi_sta_ip() { esp_err_t err = esp_netif_get_ip_info(s_sta_netif, &ip); if (err != ESP_OK) { ESP_LOGV(TAG, "esp_netif_get_ip_info failed: %s", esp_err_to_name(err)); - return false; + // TODO: do something smarter + // return false; } - return {ip.ip.addr}; + return network::IPAddress(&ip.ip); } bool WiFiComponent::wifi_apply_hostname_() { @@ -769,13 +770,13 @@ bool WiFiComponent::wifi_ap_ip_config_(optional manual_ip) { esp_netif_ip_info_t info; if (manual_ip.has_value()) { - info.ip.addr = static_cast(manual_ip->static_ip); - info.gw.addr = static_cast(manual_ip->gateway); - info.netmask.addr = static_cast(manual_ip->subnet); + info.ip = manual_ip->static_ip; + info.gw = manual_ip->gateway; + info.netmask = manual_ip->subnet; } else { - info.ip.addr = static_cast(network::IPAddress(192, 168, 4, 1)); - info.gw.addr = static_cast(network::IPAddress(192, 168, 4, 1)); - info.netmask.addr = static_cast(network::IPAddress(255, 255, 255, 0)); + info.ip = network::IPAddress(192, 168, 4, 1); + info.gw = network::IPAddress(192, 168, 4, 1); + info.netmask = network::IPAddress(255, 255, 255, 0); } err = esp_netif_dhcpc_stop(s_sta_netif); @@ -792,12 +793,12 @@ bool WiFiComponent::wifi_ap_ip_config_(optional manual_ip) { dhcps_lease_t lease; lease.enable = true; - network::IPAddress start_address = info.ip.addr; - start_address[3] += 99; - lease.start_ip.addr = static_cast(start_address); + network::IPAddress start_address = network::IPAddress(&info.ip); + start_address += 99; + lease.start_ip = start_address; ESP_LOGV(TAG, "DHCP server IP lease start: %s", start_address.str().c_str()); - start_address[3] += 100; - lease.end_ip.addr = static_cast(start_address); + start_address += 100; + lease.end_ip = start_address; ESP_LOGV(TAG, "DHCP server IP lease end: %s", start_address.str().c_str()); err = esp_netif_dhcps_option(s_sta_netif, ESP_NETIF_OP_SET, ESP_NETIF_REQUESTED_IP_ADDRESS, &lease, sizeof(lease)); @@ -855,7 +856,7 @@ bool WiFiComponent::wifi_start_ap_(const WiFiAP &ap) { network::IPAddress WiFiComponent::wifi_soft_ap_ip() { esp_netif_ip_info_t ip; esp_netif_get_ip_info(s_sta_netif, &ip); - return {ip.ip.addr}; + return network::IPAddress(&ip.ip); } bool WiFiComponent::wifi_disconnect_() { return esp_wifi_disconnect(); } @@ -907,7 +908,7 @@ network::IPAddress WiFiComponent::wifi_subnet_mask_() { ESP_LOGW(TAG, "esp_netif_get_ip_info failed: %s", esp_err_to_name(err)); return {}; } - return {ip.netmask.addr}; + return network::IPAddress(&ip.netmask); } network::IPAddress WiFiComponent::wifi_gateway_ip_() { esp_netif_ip_info_t ip; @@ -916,15 +917,11 @@ network::IPAddress WiFiComponent::wifi_gateway_ip_() { ESP_LOGW(TAG, "esp_netif_get_ip_info failed: %s", esp_err_to_name(err)); return {}; } - return {ip.gw.addr}; + return network::IPAddress(&ip.gw); } network::IPAddress WiFiComponent::wifi_dns_ip_(int num) { const ip_addr_t *dns_ip = dns_getserver(num); -#if LWIP_IPV6 - return {dns_ip->u_addr.ip4.addr}; -#else - return {dns_ip->addr}; -#endif + return network::IPAddress(dns_ip); } } // namespace wifi diff --git a/esphome/components/wifi/wifi_component_libretiny.cpp b/esphome/components/wifi/wifi_component_libretiny.cpp index abad5aca9c..d7f4406540 100644 --- a/esphome/components/wifi/wifi_component_libretiny.cpp +++ b/esphome/components/wifi/wifi_component_libretiny.cpp @@ -76,9 +76,7 @@ bool WiFiComponent::wifi_sta_ip_config_(optional manual_ip) { return true; } - WiFi.config(static_cast(manual_ip->static_ip), static_cast(manual_ip->gateway), - static_cast(manual_ip->subnet), static_cast(manual_ip->dns1), - static_cast(manual_ip->dns2)); + WiFi.config(manual_ip->static_ip, manual_ip->gateway, manual_ip->subnet, manual_ip->dns1, manual_ip->dns2); return true; } @@ -420,8 +418,7 @@ bool WiFiComponent::wifi_ap_ip_config_(optional manual_ip) { return false; if (manual_ip.has_value()) { - return WiFi.softAPConfig(static_cast(manual_ip->static_ip), static_cast(manual_ip->gateway), - static_cast(manual_ip->subnet)); + return WiFi.softAPConfig(manual_ip->static_ip, manual_ip->gateway, manual_ip->subnet); } else { return WiFi.softAPConfig(IPAddress(192, 168, 4, 1), IPAddress(192, 168, 4, 1), IPAddress(255, 255, 255, 0)); } diff --git a/esphome/components/wifi/wifi_component_pico_w.cpp b/esphome/components/wifi/wifi_component_pico_w.cpp index 149ca61cd5..d67b466d6c 100644 --- a/esphome/components/wifi/wifi_component_pico_w.cpp +++ b/esphome/components/wifi/wifi_component_pico_w.cpp @@ -70,11 +70,11 @@ bool WiFiComponent::wifi_sta_ip_config_(optional manual_ip) { return true; } - IPAddress ip_address = IPAddress(manual_ip->static_ip); - IPAddress gateway = IPAddress(manual_ip->gateway); - IPAddress subnet = IPAddress(manual_ip->subnet); + IPAddress ip_address = manual_ip->static_ip; + IPAddress gateway = manual_ip->gateway; + IPAddress subnet = manual_ip->subnet; - IPAddress dns = IPAddress(manual_ip->dns1); + IPAddress dns = manual_ip->dns1; WiFi.config(ip_address, dns, gateway, subnet); return true; @@ -151,7 +151,7 @@ bool WiFiComponent::wifi_start_ap_(const WiFiAP &ap) { return true; } -network::IPAddress WiFiComponent::wifi_soft_ap_ip() { return {WiFi.localIP()}; } +network::IPAddress WiFiComponent::wifi_soft_ap_ip() { return {(const ip_addr_t *) WiFi.localIP()}; } bool WiFiComponent::wifi_disconnect_() { int err = cyw43_wifi_leave(&cyw43_state, CYW43_ITF_STA); @@ -170,16 +170,12 @@ std::string WiFiComponent::wifi_ssid() { return WiFi.SSID().c_str(); } int8_t WiFiComponent::wifi_rssi() { return WiFi.RSSI(); } int32_t WiFiComponent::wifi_channel_() { return WiFi.channel(); } -network::IPAddress WiFiComponent::wifi_sta_ip() { return {WiFi.localIP()}; } -network::IPAddress WiFiComponent::wifi_subnet_mask_() { return {WiFi.subnetMask()}; } -network::IPAddress WiFiComponent::wifi_gateway_ip_() { return {WiFi.gatewayIP()}; } +network::IPAddress WiFiComponent::wifi_sta_ip() { return {(const ip_addr_t *) WiFi.localIP()}; } +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) { const ip_addr_t *dns_ip = dns_getserver(num); -#ifdef PIO_FRAMEWORK_ARDUINO_ENABLE_IPV6 - return {dns_ip->u_addr.ip4.addr}; -#else - return {dns_ip->addr}; -#endif + return network::IPAddress(dns_ip); } void WiFiComponent::wifi_loop_() { diff --git a/tests/test1.yaml b/tests/test1.yaml index 350057e3cc..96dda707b6 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -82,6 +82,9 @@ wifi: reboot_timeout: 120s power_save_mode: light +network: + enable_ipv6: true + mdns: disabled: false diff --git a/tests/test10.yaml b/tests/test10.yaml index 0470e37e6c..fc74d95d84 100644 --- a/tests/test10.yaml +++ b/tests/test10.yaml @@ -14,6 +14,9 @@ wifi: reboot_timeout: 3min power_save_mode: high +network: + enable_ipv6: true + logger: level: VERBOSE diff --git a/tests/test11.5.yaml b/tests/test11.5.yaml index 544dc10930..06985611e7 100644 --- a/tests/test11.5.yaml +++ b/tests/test11.5.yaml @@ -25,6 +25,9 @@ wifi: gateway: 192.168.1.1 subnet: 255.255.255.0 +network: + enable_ipv6: true + api: ota: diff --git a/tests/test2.yaml b/tests/test2.yaml index c04e6726b1..5485711c2e 100644 --- a/tests/test2.yaml +++ b/tests/test2.yaml @@ -28,6 +28,9 @@ ethernet: subnet: 255.255.255.0 domain: .local +network: + enable_ipv6: true + mdns: disabled: true diff --git a/tests/test3.1.yaml b/tests/test3.1.yaml index 16f31409d8..8884479f61 100644 --- a/tests/test3.1.yaml +++ b/tests/test3.1.yaml @@ -21,6 +21,9 @@ wifi: ssid: "MySSID" password: "password1" +network: + enable_ipv6: true + web_server: port: 80 version: 2 diff --git a/tests/test3.yaml b/tests/test3.yaml index 5d30e415fb..e7cf24a95a 100644 --- a/tests/test3.yaml +++ b/tests/test3.yaml @@ -215,6 +215,9 @@ wifi: ssid: "MySSID" password: "password1" +network: + enable_ipv6: true + uart: - id: uart_1 tx_pin: diff --git a/tests/test4.yaml b/tests/test4.yaml index 341e613785..1b809256e7 100644 --- a/tests/test4.yaml +++ b/tests/test4.yaml @@ -21,6 +21,9 @@ ethernet: subnet: 255.255.255.0 domain: .local +network: + enable_ipv6: true + api: i2c: diff --git a/tests/test5.yaml b/tests/test5.yaml index 5727d30e61..d87a7f50d4 100644 --- a/tests/test5.yaml +++ b/tests/test5.yaml @@ -22,6 +22,9 @@ wifi: gateway: 192.168.1.1 subnet: 255.255.255.0 +network: + enable_ipv6: true + api: ota: diff --git a/tests/test6.yaml b/tests/test6.yaml index 3d6a1ceb1f..7c72151860 100644 --- a/tests/test6.yaml +++ b/tests/test6.yaml @@ -16,6 +16,9 @@ wifi: - ssid: "MySSID" password: "password1" +network: + enable_ipv6: true + api: ota: diff --git a/tests/test7.yaml b/tests/test7.yaml index 2355dd6feb..b22fbfbcb4 100644 --- a/tests/test7.yaml +++ b/tests/test7.yaml @@ -3,6 +3,9 @@ wifi: ssid: 'ssid' +network: + enable_ipv6: true + esp32: board: lolin_c3_mini framework: diff --git a/tests/test8.yaml b/tests/test8.yaml index 01d12ea330..3ba8aa19ef 100644 --- a/tests/test8.yaml +++ b/tests/test8.yaml @@ -3,6 +3,9 @@ wifi: ssid: "ssid" +network: + enable_ipv6: true + esp32: board: esp32s3box variant: ESP32S3 From 4ac4492241deaecfdf1dd2597650a009659eb94d Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 28 Sep 2023 11:20:44 +1300 Subject: [PATCH 0234/2101] Fix .esphome path when not using envvar (#5440) --- esphome/core/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/core/__init__.py b/esphome/core/__init__.py index 4897b073fa..4c99aff011 100644 --- a/esphome/core/__init__.py +++ b/esphome/core/__init__.py @@ -558,7 +558,7 @@ class EsphomeCore: def data_dir(self): if is_ha_addon(): return os.path.join("/data") - if get_str_env("ESPHOME_DATA_DIR", None) is not None: + if "ESPHOME_DATA_DIR" in os.environ: return get_str_env("ESPHOME_DATA_DIR", None) return self.relative_config_path(".esphome") From 12365976c4dda765c22e0b51075196931da8e3ed Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 28 Sep 2023 11:40:36 +1300 Subject: [PATCH 0235/2101] Migrate dashboard json files to /data folder instead of wiping out (#5441) --- docker/ha-addon-rootfs/etc/s6-overlay/s6-rc.d/esphome/run | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docker/ha-addon-rootfs/etc/s6-overlay/s6-rc.d/esphome/run b/docker/ha-addon-rootfs/etc/s6-overlay/s6-rc.d/esphome/run index 775c2fa0d6..edb98a8d9b 100755 --- a/docker/ha-addon-rootfs/etc/s6-overlay/s6-rc.d/esphome/run +++ b/docker/ha-addon-rootfs/etc/s6-overlay/s6-rc.d/esphome/run @@ -42,7 +42,12 @@ fi mkdir -p "${pio_cache_base}" if bashio::fs.directory_exists '/config/esphome/.esphome'; then - bashio::log.info "Removing old .esphome directory..." + bashio::log.info "Migrating old .esphome directory..." + if bashio::fs.file_exists '/config/esphome/.esphome/esphome.json'; then + mv /config/esphome/.esphome/esphome.json /data/esphome.json + fi + mkdir -p "/data/storage" + mv /config/esphome/.esphome/*.json /data/storage/ || true rm -rf /config/esphome/.esphome fi From dae8ab563c92288bc017be8567fe41f9f93ec159 Mon Sep 17 00:00:00 2001 From: Marc J Date: Wed, 27 Sep 2023 00:45:21 -0700 Subject: [PATCH 0236/2101] Tuya Number Scaling by step value (#5108) --- esphome/components/tuya/number/tuya_number.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/esphome/components/tuya/number/tuya_number.cpp b/esphome/components/tuya/number/tuya_number.cpp index 5c7cafbf7a..30ef8b8f72 100644 --- a/esphome/components/tuya/number/tuya_number.cpp +++ b/esphome/components/tuya/number/tuya_number.cpp @@ -10,7 +10,7 @@ void TuyaNumber::setup() { this->parent_->register_listener(this->number_id_, [this](const TuyaDatapoint &datapoint) { if (datapoint.type == TuyaDatapointType::INTEGER) { ESP_LOGV(TAG, "MCU reported number %u is: %d", datapoint.id, datapoint.value_int); - this->publish_state(datapoint.value_int); + this->publish_state(datapoint.value_int * this->traits.get_step()); } else if (datapoint.type == TuyaDatapointType::ENUM) { ESP_LOGV(TAG, "MCU reported number %u is: %u", datapoint.id, datapoint.value_enum); this->publish_state(datapoint.value_enum); @@ -22,7 +22,8 @@ void TuyaNumber::setup() { void TuyaNumber::control(float value) { ESP_LOGV(TAG, "Setting number %u: %f", this->number_id_, value); if (this->type_ == TuyaDatapointType::INTEGER) { - this->parent_->set_integer_datapoint_value(this->number_id_, value); + int integer_value = lround(value / this->traits.get_step()); + this->parent_->set_integer_datapoint_value(this->number_id_, integer_value); } else if (this->type_ == TuyaDatapointType::ENUM) { this->parent_->set_enum_datapoint_value(this->number_id_, value); } From b5b654e0546f3fdfd835de3930b91f7e6760be69 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 28 Sep 2023 11:40:36 +1300 Subject: [PATCH 0237/2101] Migrate dashboard json files to /data folder instead of wiping out (#5441) --- docker/ha-addon-rootfs/etc/s6-overlay/s6-rc.d/esphome/run | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docker/ha-addon-rootfs/etc/s6-overlay/s6-rc.d/esphome/run b/docker/ha-addon-rootfs/etc/s6-overlay/s6-rc.d/esphome/run index 775c2fa0d6..edb98a8d9b 100755 --- a/docker/ha-addon-rootfs/etc/s6-overlay/s6-rc.d/esphome/run +++ b/docker/ha-addon-rootfs/etc/s6-overlay/s6-rc.d/esphome/run @@ -42,7 +42,12 @@ fi mkdir -p "${pio_cache_base}" if bashio::fs.directory_exists '/config/esphome/.esphome'; then - bashio::log.info "Removing old .esphome directory..." + bashio::log.info "Migrating old .esphome directory..." + if bashio::fs.file_exists '/config/esphome/.esphome/esphome.json'; then + mv /config/esphome/.esphome/esphome.json /data/esphome.json + fi + mkdir -p "/data/storage" + mv /config/esphome/.esphome/*.json /data/storage/ || true rm -rf /config/esphome/.esphome fi From d262548d2e00bf7e9b3354430f1deca4ea79edf4 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 28 Sep 2023 11:52:35 +1300 Subject: [PATCH 0238/2101] Bump version to 2023.9.1 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index bf703d9595..65757da130 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2023.9.0" +__version__ = "2023.9.1" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 43355435756afee62d68368ee5985a4c420da875 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 29 Sep 2023 10:58:51 +1300 Subject: [PATCH 0239/2101] Bump zeroconf from 0.112.0 to 0.115.0 (#5432) 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 63199680cf..821e7c5786 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,7 +11,7 @@ esptool==4.6.2 click==8.1.7 esphome-dashboard==20230904.0 aioesphomeapi==15.0.0 -zeroconf==0.112.0 +zeroconf==0.115.0 # esp-idf requires this, but doesn't bundle it by default # https://github.com/espressif/esp-idf/blob/220590d599e134d7a5e7f1e683cc4550349ffbf8/requirements.txt#L24 From 507dc5f4961751cdf651327ac76ca1c70561b4f2 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Fri, 29 Sep 2023 10:36:31 +1000 Subject: [PATCH 0240/2101] SPI fixes for buggy components (#5446) --- CODEOWNERS | 2 +- esphome/components/max7219/max7219.cpp | 5 +---- esphome/components/spi/__init__.py | 2 +- esphome/components/spi/spi.h | 1 + 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index 3920a9100e..ce19f14c05 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -270,7 +270,7 @@ esphome/components/sn74hc165/* @jesserockz esphome/components/socket/* @esphome/core esphome/components/sonoff_d1/* @anatoly-savchenkov esphome/components/speaker/* @jesserockz -esphome/components/spi/* @esphome/core +esphome/components/spi/* @clydebarrow @esphome/core esphome/components/spi_device/* @clydebarrow esphome/components/spi_led_strip/* @clydebarrow esphome/components/sprinkler/* @kbx81 diff --git a/esphome/components/max7219/max7219.cpp b/esphome/components/max7219/max7219.cpp index 38b4a165cb..b08723f1d4 100644 --- a/esphome/components/max7219/max7219.cpp +++ b/esphome/components/max7219/max7219.cpp @@ -217,10 +217,7 @@ uint8_t MAX7219Component::printf(const char *format, ...) { return 0; } void MAX7219Component::set_writer(max7219_writer_t &&writer) { this->writer_ = writer; } -void MAX7219Component::set_intensity(uint8_t intensity) { - this->intensity_ = intensity; - this->send_to_all_(MAX7219_REGISTER_INTENSITY, this->intensity_); -} +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) { diff --git a/esphome/components/spi/__init__.py b/esphome/components/spi/__init__.py index 79e7a5b034..a5aa610462 100644 --- a/esphome/components/spi/__init__.py +++ b/esphome/components/spi/__init__.py @@ -28,7 +28,7 @@ from esphome.const import ( ) from esphome.core import coroutine_with_priority, CORE -CODEOWNERS = ["@esphome/core"] +CODEOWNERS = ["@esphome/core", "@clydebarrow"] spi_ns = cg.esphome_ns.namespace("spi") SPIComponent = spi_ns.class_("SPIComponent", cg.Component) SPIDevice = spi_ns.class_("SPIDevice") diff --git a/esphome/components/spi/spi.h b/esphome/components/spi/spi.h index 56aa746fc9..107ffb7cb5 100644 --- a/esphome/components/spi/spi.h +++ b/esphome/components/spi/spi.h @@ -248,6 +248,7 @@ class SPIDelegateDummy : public SPIDelegate { SPIDelegateDummy() = default; uint8_t transfer(uint8_t data) override { return 0; } + void end_transaction() override{}; void begin_transaction() override; }; From 4d81153150a1bfd5f970bb930976d1e4c7a1077f Mon Sep 17 00:00:00 2001 From: Avri Chen-Roth Date: Fri, 29 Sep 2023 04:17:32 +0300 Subject: [PATCH 0241/2101] Fix an Issue with IR Remote Climate and Whirlpool protocol toggle (#5447) Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/whirlpool/whirlpool.cpp | 7 +++++++ esphome/components/whirlpool/whirlpool.h | 2 ++ 2 files changed, 9 insertions(+) diff --git a/esphome/components/whirlpool/whirlpool.cpp b/esphome/components/whirlpool/whirlpool.cpp index 225423b4db..1ac32f30da 100644 --- a/esphome/components/whirlpool/whirlpool.cpp +++ b/esphome/components/whirlpool/whirlpool.cpp @@ -33,6 +33,7 @@ const uint8_t WHIRLPOOL_SWING_MASK = 128; const uint8_t WHIRLPOOL_POWER = 0x04; void WhirlpoolClimate::transmit_state() { + this->last_transmit_time_ = millis(); // setting the time of the last transmission. uint8_t remote_state[WHIRLPOOL_STATE_LENGTH] = {0}; remote_state[0] = 0x83; remote_state[1] = 0x06; @@ -149,6 +150,12 @@ void WhirlpoolClimate::transmit_state() { } bool WhirlpoolClimate::on_receive(remote_base::RemoteReceiveData data) { + // Check if the esp isn't currently transmitting. + if (millis() - this->last_transmit_time_ < 500) { + ESP_LOGV(TAG, "Blocked receive because of current trasmittion"); + return false; + } + // Validate header if (!data.expect_item(WHIRLPOOL_HEADER_MARK, WHIRLPOOL_HEADER_SPACE)) { ESP_LOGV(TAG, "Header fail"); diff --git a/esphome/components/whirlpool/whirlpool.h b/esphome/components/whirlpool/whirlpool.h index 7f31894df9..907a21225c 100644 --- a/esphome/components/whirlpool/whirlpool.h +++ b/esphome/components/whirlpool/whirlpool.h @@ -47,6 +47,8 @@ class WhirlpoolClimate : public climate_ir::ClimateIR { void transmit_state() override; /// Handle received IR Buffer bool on_receive(remote_base::RemoteReceiveData data) override; + /// Set the time of the last transmission. + int32_t last_transmit_time_{}; bool send_swing_cmd_{false}; Model model_; From 2c94c3d96f932056a1b8099906b3fabc57e6c79b Mon Sep 17 00:00:00 2001 From: leoshusar Date: Fri, 29 Sep 2023 05:40:56 +0200 Subject: [PATCH 0242/2101] [BP1658CJ] Missing clock line delays and ack bit (#5448) * fix: missing clock line delays and ack bit * chore: remove esphome namespace from delay methods * style: removed trailing whitespace --- esphome/components/bp1658cj/bp1658cj.cpp | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/esphome/components/bp1658cj/bp1658cj.cpp b/esphome/components/bp1658cj/bp1658cj.cpp index 5b9e4a5a2c..d3f3e71fed 100644 --- a/esphome/components/bp1658cj/bp1658cj.cpp +++ b/esphome/components/bp1658cj/bp1658cj.cpp @@ -12,6 +12,8 @@ static const uint8_t BP1658CJ_ADDR_START_3CH = 0x10; static const uint8_t BP1658CJ_ADDR_START_2CH = 0x20; static const uint8_t BP1658CJ_ADDR_START_5CH = 0x30; +static const uint8_t BP1658CJ_DELAY = 2; + void BP1658CJ::setup() { ESP_LOGCONFIG(TAG, "Setting up BP1658CJ Output Component..."); this->data_pin_->setup(); @@ -81,27 +83,41 @@ void BP1658CJ::set_channel_value_(uint8_t channel, uint16_t value) { } this->pwm_amounts_[channel] = value; } + void BP1658CJ::write_bit_(bool value) { - this->clock_pin_->digital_write(false); this->data_pin_->digital_write(value); this->clock_pin_->digital_write(true); + + delayMicroseconds(BP1658CJ_DELAY); + + this->clock_pin_->digital_write(false); } void BP1658CJ::write_byte_(uint8_t data) { for (uint8_t mask = 0x80; mask; mask >>= 1) { this->write_bit_(data & mask); + delayMicroseconds(BP1658CJ_DELAY); } - this->clock_pin_->digital_write(false); - this->data_pin_->digital_write(true); + + // ack bit + this->data_pin_->pin_mode(gpio::FLAG_INPUT); this->clock_pin_->digital_write(true); + + delayMicroseconds(BP1658CJ_DELAY); + + this->clock_pin_->digital_write(false); + this->data_pin_->pin_mode(gpio::FLAG_OUTPUT); } void BP1658CJ::write_buffer_(uint8_t *buffer, uint8_t size) { this->data_pin_->digital_write(false); + this->clock_pin_->digital_write(false); + for (uint32_t i = 0; i < size; i++) { this->write_byte_(buffer[i]); + delayMicroseconds(BP1658CJ_DELAY); } - this->clock_pin_->digital_write(false); + this->clock_pin_->digital_write(true); this->data_pin_->digital_write(true); } From d3913be7e531e07f90941eeba4f85c5272d79e90 Mon Sep 17 00:00:00 2001 From: De Cock Xavier Date: Sat, 30 Sep 2023 00:08:56 +0200 Subject: [PATCH 0243/2101] =?UTF-8?q?[ssd1351]=20fix:=20wait=20for=20the?= =?UTF-8?q?=20component=20to=20be=20at=20least=20in=20setup=20phase=20b?= =?UTF-8?q?=E2=80=A6=20(#5454)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- esphome/components/ssd1351_base/ssd1351_base.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/esphome/components/ssd1351_base/ssd1351_base.cpp b/esphome/components/ssd1351_base/ssd1351_base.cpp index 036a6a0e82..38ea05a0b8 100644 --- a/esphome/components/ssd1351_base/ssd1351_base.cpp +++ b/esphome/components/ssd1351_base/ssd1351_base.cpp @@ -112,6 +112,9 @@ void SSD1351::set_brightness(float brightness) { } else { this->brightness_ = brightness; } + if (!this->is_ready()) { + return; // Component is not yet setup skip the command + } // now write the new brightness level to the display this->command(SSD1351_CONTRASTMASTER); this->data(int(SSD1351_MAX_CONTRAST * (this->brightness_))); From b3dc2d43a52b181b700477db78a762a228ec2747 Mon Sep 17 00:00:00 2001 From: "John K. Luebs" Date: Fri, 29 Sep 2023 18:27:40 -0500 Subject: [PATCH 0244/2101] Do not enable SHT3x heater by default. Fixes #4886. (#5445) --- esphome/components/sht3xd/sensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/sht3xd/sensor.py b/esphome/components/sht3xd/sensor.py index 5c73a63f1a..80e15a1ab9 100644 --- a/esphome/components/sht3xd/sensor.py +++ b/esphome/components/sht3xd/sensor.py @@ -38,7 +38,7 @@ CONFIG_SCHEMA = ( device_class=DEVICE_CLASS_HUMIDITY, state_class=STATE_CLASS_MEASUREMENT, ), - cv.Optional(CONF_HEATER_ENABLED, default=True): cv.boolean, + cv.Optional(CONF_HEATER_ENABLED, default=False): cv.boolean, }, ) .extend(cv.polling_component_schema("60s")) From 0b5a57ead403103050288dfe959201b8ead08965 Mon Sep 17 00:00:00 2001 From: Angel Nunez Mencias Date: Sat, 30 Sep 2023 01:34:56 +0200 Subject: [PATCH 0245/2101] Fix SPI support for second bus on 2023.9.1 (#5456) --- esphome/components/spi/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/spi/__init__.py b/esphome/components/spi/__init__.py index a5aa610462..fb30755511 100644 --- a/esphome/components/spi/__init__.py +++ b/esphome/components/spi/__init__.py @@ -187,7 +187,7 @@ def get_spi_interface(index): # Following code can't apply to C2, H2 or 8266 since they have only one SPI if get_target_variant() in (VARIANT_ESP32S3, VARIANT_ESP32S2): return "new SPIClass(FSPI)" - return "return new SPIClass(HSPI)" + return "new SPIClass(HSPI)" SPI_SCHEMA = cv.All( From 2513ede3ec2afc8a6d2f0561c1a5425dc0830589 Mon Sep 17 00:00:00 2001 From: Angel Nunez Mencias Date: Sat, 30 Sep 2023 03:48:51 +0200 Subject: [PATCH 0246/2101] Add testcases for multiple SPI buses on ESP32 Arduino (#5457) --- tests/test4.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/test4.yaml b/tests/test4.yaml index 1b809256e7..bb4357e28d 100644 --- a/tests/test4.yaml +++ b/tests/test4.yaml @@ -32,10 +32,15 @@ i2c: scan: false spi: +- id: spi_id_1 clk_pin: GPIO21 mosi_pin: GPIO22 miso_pin: GPIO23 interface: hardware +- id: spi_id_2 + clk_pin: GPIO32 + mosi_pin: GPIO33 + interface: hardware uart: - id: uart115200 @@ -92,6 +97,7 @@ sx1509: address: 0x3E mcp3204: + spi_id: spi_id_1 cs_pin: GPIO23 dac7678: @@ -495,6 +501,7 @@ display: update_interval: 16ms - platform: waveshare_epaper + spi_id: spi_id_1 cs_pin: GPIO23 dc_pin: GPIO23 busy_pin: GPIO23 @@ -504,6 +511,7 @@ display: lambda: |- it.rectangle(0, 0, it.get_width(), it.get_height()); - platform: waveshare_epaper + spi_id: spi_id_1 cs_pin: GPIO23 dc_pin: GPIO23 busy_pin: GPIO23 @@ -514,6 +522,7 @@ display: lambda: |- it.rectangle(0, 0, it.get_width(), it.get_height()); - platform: waveshare_epaper + spi_id: spi_id_1 cs_pin: GPIO23 dc_pin: GPIO23 busy_pin: GPIO23 @@ -523,6 +532,7 @@ display: lambda: |- it.rectangle(0, 0, it.get_width(), it.get_height()); - platform: waveshare_epaper + spi_id: spi_id_1 cs_pin: GPIO23 dc_pin: GPIO23 busy_pin: GPIO23 @@ -673,6 +683,7 @@ touchscreen: - platform: xpt2046 id: xpt_touchscreen + spi_id: spi_id_2 cs_pin: 17 interrupt_pin: 16 display: inkplate_display From 589b9e10b2c877909083c6551c9d510d02d23ca5 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 2 Oct 2023 13:45:24 +1300 Subject: [PATCH 0247/2101] Ensure esphome directory exists on addon startup (#5464) --- docker/ha-addon-rootfs/etc/s6-overlay/s6-rc.d/esphome/run | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docker/ha-addon-rootfs/etc/s6-overlay/s6-rc.d/esphome/run b/docker/ha-addon-rootfs/etc/s6-overlay/s6-rc.d/esphome/run index edb98a8d9b..f973dfcaf8 100755 --- a/docker/ha-addon-rootfs/etc/s6-overlay/s6-rc.d/esphome/run +++ b/docker/ha-addon-rootfs/etc/s6-overlay/s6-rc.d/esphome/run @@ -41,6 +41,8 @@ fi mkdir -p "${pio_cache_base}" +mkdir -p /config/esphome + if bashio::fs.directory_exists '/config/esphome/.esphome'; then bashio::log.info "Migrating old .esphome directory..." if bashio::fs.file_exists '/config/esphome/.esphome/esphome.json'; then From ec4777b8d03845d01e5ed87f72a19093f205d277 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Fri, 29 Sep 2023 10:36:31 +1000 Subject: [PATCH 0248/2101] SPI fixes for buggy components (#5446) --- CODEOWNERS | 2 +- esphome/components/max7219/max7219.cpp | 5 +---- esphome/components/spi/__init__.py | 2 +- esphome/components/spi/spi.h | 1 + 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index 3920a9100e..ce19f14c05 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -270,7 +270,7 @@ esphome/components/sn74hc165/* @jesserockz esphome/components/socket/* @esphome/core esphome/components/sonoff_d1/* @anatoly-savchenkov esphome/components/speaker/* @jesserockz -esphome/components/spi/* @esphome/core +esphome/components/spi/* @clydebarrow @esphome/core esphome/components/spi_device/* @clydebarrow esphome/components/spi_led_strip/* @clydebarrow esphome/components/sprinkler/* @kbx81 diff --git a/esphome/components/max7219/max7219.cpp b/esphome/components/max7219/max7219.cpp index 38b4a165cb..b08723f1d4 100644 --- a/esphome/components/max7219/max7219.cpp +++ b/esphome/components/max7219/max7219.cpp @@ -217,10 +217,7 @@ uint8_t MAX7219Component::printf(const char *format, ...) { return 0; } void MAX7219Component::set_writer(max7219_writer_t &&writer) { this->writer_ = writer; } -void MAX7219Component::set_intensity(uint8_t intensity) { - this->intensity_ = intensity; - this->send_to_all_(MAX7219_REGISTER_INTENSITY, this->intensity_); -} +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) { diff --git a/esphome/components/spi/__init__.py b/esphome/components/spi/__init__.py index 79e7a5b034..a5aa610462 100644 --- a/esphome/components/spi/__init__.py +++ b/esphome/components/spi/__init__.py @@ -28,7 +28,7 @@ from esphome.const import ( ) from esphome.core import coroutine_with_priority, CORE -CODEOWNERS = ["@esphome/core"] +CODEOWNERS = ["@esphome/core", "@clydebarrow"] spi_ns = cg.esphome_ns.namespace("spi") SPIComponent = spi_ns.class_("SPIComponent", cg.Component) SPIDevice = spi_ns.class_("SPIDevice") diff --git a/esphome/components/spi/spi.h b/esphome/components/spi/spi.h index 56aa746fc9..107ffb7cb5 100644 --- a/esphome/components/spi/spi.h +++ b/esphome/components/spi/spi.h @@ -248,6 +248,7 @@ class SPIDelegateDummy : public SPIDelegate { SPIDelegateDummy() = default; uint8_t transfer(uint8_t data) override { return 0; } + void end_transaction() override{}; void begin_transaction() override; }; From e9bda2810f5b9aaf867ced8c465d89401a0e1e00 Mon Sep 17 00:00:00 2001 From: Avri Chen-Roth Date: Fri, 29 Sep 2023 04:17:32 +0300 Subject: [PATCH 0249/2101] Fix an Issue with IR Remote Climate and Whirlpool protocol toggle (#5447) Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/whirlpool/whirlpool.cpp | 7 +++++++ esphome/components/whirlpool/whirlpool.h | 2 ++ 2 files changed, 9 insertions(+) diff --git a/esphome/components/whirlpool/whirlpool.cpp b/esphome/components/whirlpool/whirlpool.cpp index 225423b4db..1ac32f30da 100644 --- a/esphome/components/whirlpool/whirlpool.cpp +++ b/esphome/components/whirlpool/whirlpool.cpp @@ -33,6 +33,7 @@ const uint8_t WHIRLPOOL_SWING_MASK = 128; const uint8_t WHIRLPOOL_POWER = 0x04; void WhirlpoolClimate::transmit_state() { + this->last_transmit_time_ = millis(); // setting the time of the last transmission. uint8_t remote_state[WHIRLPOOL_STATE_LENGTH] = {0}; remote_state[0] = 0x83; remote_state[1] = 0x06; @@ -149,6 +150,12 @@ void WhirlpoolClimate::transmit_state() { } bool WhirlpoolClimate::on_receive(remote_base::RemoteReceiveData data) { + // Check if the esp isn't currently transmitting. + if (millis() - this->last_transmit_time_ < 500) { + ESP_LOGV(TAG, "Blocked receive because of current trasmittion"); + return false; + } + // Validate header if (!data.expect_item(WHIRLPOOL_HEADER_MARK, WHIRLPOOL_HEADER_SPACE)) { ESP_LOGV(TAG, "Header fail"); diff --git a/esphome/components/whirlpool/whirlpool.h b/esphome/components/whirlpool/whirlpool.h index 7f31894df9..907a21225c 100644 --- a/esphome/components/whirlpool/whirlpool.h +++ b/esphome/components/whirlpool/whirlpool.h @@ -47,6 +47,8 @@ class WhirlpoolClimate : public climate_ir::ClimateIR { void transmit_state() override; /// Handle received IR Buffer bool on_receive(remote_base::RemoteReceiveData data) override; + /// Set the time of the last transmission. + int32_t last_transmit_time_{}; bool send_swing_cmd_{false}; Model model_; From efd31be21cd347950fe3ef4089e23109c1d81353 Mon Sep 17 00:00:00 2001 From: Angel Nunez Mencias Date: Sat, 30 Sep 2023 01:34:56 +0200 Subject: [PATCH 0250/2101] Fix SPI support for second bus on 2023.9.1 (#5456) --- esphome/components/spi/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/spi/__init__.py b/esphome/components/spi/__init__.py index a5aa610462..fb30755511 100644 --- a/esphome/components/spi/__init__.py +++ b/esphome/components/spi/__init__.py @@ -187,7 +187,7 @@ def get_spi_interface(index): # Following code can't apply to C2, H2 or 8266 since they have only one SPI if get_target_variant() in (VARIANT_ESP32S3, VARIANT_ESP32S2): return "new SPIClass(FSPI)" - return "return new SPIClass(HSPI)" + return "new SPIClass(HSPI)" SPI_SCHEMA = cv.All( From af005a6554265cb0f5f2f14fb3302880dfc89429 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 2 Oct 2023 13:45:24 +1300 Subject: [PATCH 0251/2101] Ensure esphome directory exists on addon startup (#5464) --- docker/ha-addon-rootfs/etc/s6-overlay/s6-rc.d/esphome/run | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docker/ha-addon-rootfs/etc/s6-overlay/s6-rc.d/esphome/run b/docker/ha-addon-rootfs/etc/s6-overlay/s6-rc.d/esphome/run index edb98a8d9b..f973dfcaf8 100755 --- a/docker/ha-addon-rootfs/etc/s6-overlay/s6-rc.d/esphome/run +++ b/docker/ha-addon-rootfs/etc/s6-overlay/s6-rc.d/esphome/run @@ -41,6 +41,8 @@ fi mkdir -p "${pio_cache_base}" +mkdir -p /config/esphome + if bashio::fs.directory_exists '/config/esphome/.esphome'; then bashio::log.info "Migrating old .esphome directory..." if bashio::fs.file_exists '/config/esphome/.esphome/esphome.json'; then From 5e1472185cb478cdd8e60dbc1bb01d1902c921cb Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 2 Oct 2023 17:01:22 +1300 Subject: [PATCH 0252/2101] Bump version to 2023.9.2 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 65757da130..496880ac88 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2023.9.1" +__version__ = "2023.9.2" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From a33b8abce8ab0ec7b3bb81e62c58ab213c44193c Mon Sep 17 00:00:00 2001 From: De Cock Xavier Date: Mon, 2 Oct 2023 22:25:13 +0200 Subject: [PATCH 0253/2101] Feat/component poller suspend (#5423) --- esphome/automation.py | 38 ++++++++++++++++++++++++++++++++++ esphome/core/base_automation.h | 34 ++++++++++++++++++++++++++++++ esphome/core/component.cpp | 10 +++++++++ esphome/core/component.h | 6 ++++++ tests/test1.yaml | 16 ++++++++++++++ 5 files changed, 104 insertions(+) diff --git a/esphome/automation.py b/esphome/automation.py index 0c4bda09d1..d90a9cb99a 100644 --- a/esphome/automation.py +++ b/esphome/automation.py @@ -11,6 +11,7 @@ from esphome.const import ( CONF_TRIGGER_ID, CONF_TYPE_ID, CONF_TIME, + CONF_UPDATE_INTERVAL, ) from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor from esphome.util import Registry @@ -69,6 +70,8 @@ WhileAction = cg.esphome_ns.class_("WhileAction", Action) RepeatAction = cg.esphome_ns.class_("RepeatAction", Action) WaitUntilAction = cg.esphome_ns.class_("WaitUntilAction", Action, cg.Component) 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") LambdaCondition = cg.esphome_ns.class_("LambdaCondition", Condition) @@ -303,6 +306,41 @@ async def component_update_action_to_code(config, action_id, template_arg, args) return cg.new_Pvariable(action_id, template_arg, comp) +@register_action( + "component.suspend", + SuspendComponentAction, + maybe_simple_id( + { + cv.Required(CONF_ID): cv.use_id(cg.PollingComponent), + } + ), +) +async def component_suspend_action_to_code(config, action_id, template_arg, args): + comp = await cg.get_variable(config[CONF_ID]) + return cg.new_Pvariable(action_id, template_arg, comp) + + +@register_action( + "component.resume", + ResumeComponentAction, + maybe_simple_id( + { + cv.Required(CONF_ID): cv.use_id(cg.PollingComponent), + cv.Optional(CONF_UPDATE_INTERVAL): cv.templatable( + cv.positive_time_period_milliseconds + ), + } + ), +) +async def component_resume_action_to_code(config, action_id, template_arg, args): + comp = await cg.get_variable(config[CONF_ID]) + var = cg.new_Pvariable(action_id, template_arg, comp) + if CONF_UPDATE_INTERVAL in config: + template_ = await cg.templatable(config[CONF_UPDATE_INTERVAL], args, int) + cg.add(var.set_update_interval(template_)) + return var + + async def build_action(full_config, template_arg, args): registry_entry, config = cg.extract_registry_entry_config( ACTION_REGISTRY, full_config diff --git a/esphome/core/base_automation.h b/esphome/core/base_automation.h index a17b6a6f85..af618af99a 100644 --- a/esphome/core/base_automation.h +++ b/esphome/core/base_automation.h @@ -330,4 +330,38 @@ template class UpdateComponentAction : public Action { PollingComponent *component_; }; +template class SuspendComponentAction : public Action { + public: + SuspendComponentAction(PollingComponent *component) : component_(component) {} + + void play(Ts... x) override { + if (!this->component_->is_ready()) + return; + this->component_->stop_poller(); + } + + protected: + PollingComponent *component_; +}; + +template class ResumeComponentAction : public Action { + public: + ResumeComponentAction(PollingComponent *component) : component_(component) {} + TEMPLATABLE_VALUE(uint32_t, update_interval) + + void play(Ts... x) override { + if (!this->component_->is_ready()) { + return; + } + optional update_interval = this->update_interval_.optional_value(x...); + if (update_interval.has_value()) { + this->component_->set_update_interval(update_interval.value()); + } + this->component_->start_poller(); + } + + protected: + PollingComponent *component_; +}; + } // namespace esphome diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index ae85d55498..e2f27f9828 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -188,10 +188,20 @@ void PollingComponent::call_setup() { // Let the polling component subclass setup their HW. this->setup(); + // init the poller + this->start_poller(); +} + +void PollingComponent::start_poller() { // Register interval. this->set_interval("update", this->get_update_interval(), [this]() { this->update(); }); } +void PollingComponent::stop_poller() { + // Clear the interval to suspend component + this->cancel_interval("update"); +} + 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; } diff --git a/esphome/core/component.h b/esphome/core/component.h index 7382f1c617..51a6296811 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -308,6 +308,12 @@ class PollingComponent : public Component { /// Get the update interval in ms of this sensor virtual uint32_t get_update_interval() const; + // Start the poller, used for component.suspend + void start_poller(); + + // Stop the poller, used for component.suspend + void stop_poller(); + protected: uint32_t update_interval_; }; diff --git a/tests/test1.yaml b/tests/test1.yaml index 96dda707b6..b84aa21439 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -3566,6 +3566,22 @@ button: name: Midea Power Inverse on_press: midea_ac.power_toggle: + - platform: template + name: Poller component suspend test + on_press: + - component.suspend: myteleinfo + - delay: 20s + - component.update: myteleinfo + - delay: 20s + - component.resume: myteleinfo + - delay: 20s + - component.resume: + id: myteleinfo + update_interval: 2s + - delay: 20s + - component.resume: + id: myteleinfo + update_interval: !lambda return 2500; - platform: ld2410 factory_reset: name: "factory reset" From e87c8d550bbc9cdf30a18b6ba1cf2f2792cc53e4 Mon Sep 17 00:00:00 2001 From: Maxime Gauduin Date: Mon, 2 Oct 2023 23:15:29 +0200 Subject: [PATCH 0254/2101] add pin config for denky_d4 (#5471) --- esphome/components/esp32/boards.py | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/esp32/boards.py b/esphome/components/esp32/boards.py index 61cb8cdc3f..e6c23c4d96 100644 --- a/esphome/components/esp32/boards.py +++ b/esphome/components/esp32/boards.py @@ -235,6 +235,7 @@ ESP32_BOARD_PINS = { "SDA": 5, "SS": 15, }, + "denky_d4": {"RX": 8, "LED": 14}, "esp-wrover-kit": {}, "esp32-devkitlipo": {}, "esp32-evb": { From 205f41509b06fa243971690d54f39e46a02a9439 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Tue, 3 Oct 2023 08:24:20 +1100 Subject: [PATCH 0255/2101] Support RP2040 hardware SPI (#5466) --- esphome/components/spi/__init__.py | 64 +++++++++++++++++++++++++----- tests/test6.yaml | 8 ++++ 2 files changed, 61 insertions(+), 11 deletions(-) diff --git a/esphome/components/spi/__init__.py b/esphome/components/spi/__init__.py index fb30755511..07e8982f6e 100644 --- a/esphome/components/spi/__init__.py +++ b/esphome/components/spi/__init__.py @@ -54,6 +54,21 @@ CONF_FORCE_SW = "force_sw" CONF_INTERFACE = "interface" CONF_INTERFACE_INDEX = "interface_index" +# RP2040 SPI pin assignments are complicated. Refer to https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf + +RP_SPI_PINSETS = [ + { + CONF_MISO_PIN: [0, 4, 16, 20, -1], + CONF_CLK_PIN: [2, 6, 18, 22], + CONF_MOSI_PIN: [3, 7, 19, 23, -1], + }, + { + CONF_MISO_PIN: [8, 12, 24, 28, -1], + CONF_CLK_PIN: [10, 14, 26], + CONF_MOSI_PIN: [11, 23, 27, -1], + }, +] + def get_target_platform(): return ( @@ -85,7 +100,7 @@ def get_hw_interface_list(): return [["spi", "spi2"]] return [["spi", "spi2"], ["spi3"]] if target_platform == "rp2040": - return [["spi"]] + return [["spi"], ["spi1"]] return [] @@ -99,8 +114,10 @@ def get_spi_index(name): # Check that pins are suitable for HW spi +# \param spi the config data for the spi instance +# \param index the selected hw interface number, -1 if not yet known # TODO verify that the pins are internal -def validate_hw_pins(spi): +def validate_hw_pins(spi, index=-1): clk_pin = spi[CONF_CLK_PIN] if clk_pin[CONF_INVERTED]: return False @@ -129,9 +146,30 @@ def validate_hw_pins(spi): if target_platform == "esp32": return clk_pin_no >= 0 + if target_platform == "rp2040": + pin_set = ( + list(filter(lambda s: clk_pin_no in s[CONF_CLK_PIN], RP_SPI_PINSETS))[0] + if index == -1 + else RP_SPI_PINSETS[index] + ) + if pin_set is None: + return False + if sdo_pin_no not in pin_set[CONF_MOSI_PIN]: + return False + if sdi_pin_no not in pin_set[CONF_MISO_PIN]: + return False + return True return False +def get_hw_spi(config, available): + """Get an available hardware spi interface suitable for this config""" + matching = list(filter(lambda idx: validate_hw_pins(config, idx), available)) + if len(matching) != 0: + return matching[0] + return None + + def validate_spi_config(config): available = list(range(len(get_hw_interface_list()))) for spi in config: @@ -147,9 +185,10 @@ def validate_spi_config(config): if not validate_hw_pins(spi): spi[CONF_INTERFACE] = "software" elif interface == "hardware": - if len(available) == 0: - raise cv.Invalid("No hardware interface available") - index = spi[CONF_INTERFACE_INDEX] = available[0] + index = get_hw_spi(spi, available) + if index is None: + raise cv.Invalid("No suitable hardware interface available") + spi[CONF_INTERFACE_INDEX] = index available.remove(index) else: # Must be a specific name @@ -164,11 +203,14 @@ def validate_spi_config(config): # Any specific names and any 'hardware' requests will have already been filled, # so just need to assign remaining hardware to 'any' requests. for spi in config: - if spi[CONF_INTERFACE] == "any" and len(available) != 0: - index = available[0] - spi[CONF_INTERFACE_INDEX] = index - available.remove(index) - if CONF_INTERFACE_INDEX in spi and not validate_hw_pins(spi): + if spi[CONF_INTERFACE] == "any": + index = get_hw_spi(spi, available) + if index is not None: + spi[CONF_INTERFACE_INDEX] = index + available.remove(index) + if CONF_INTERFACE_INDEX in spi and not validate_hw_pins( + spi, spi[CONF_INTERFACE_INDEX] + ): raise cv.Invalid("Invalid pin selections for hardware SPI interface") return config @@ -181,7 +223,7 @@ def get_spi_interface(index): # Arduino code follows platform = get_target_platform() if platform == "rp2040": - return "&spi1" + return ["&SPI", "&SPI1"][index] if index == 0: return "&SPI" # Following code can't apply to C2, H2 or 8266 since they have only one SPI diff --git a/tests/test6.yaml b/tests/test6.yaml index 7c72151860..b0ec04eb6a 100644 --- a/tests/test6.yaml +++ b/tests/test6.yaml @@ -42,6 +42,14 @@ switch: output: pin_4 id: pin_4_switch + +spi: # Pins are for SPI1 on the RP2040 Pico-W + miso_pin: 8 + clk_pin: 10 + mosi_pin: 11 + id: spi_0 + interface: hardware + #light: # - platform: rp2040_pio_led_strip # id: led_strip From 401a3862194b8b7711be607aec027b02fe4aa418 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Oct 2023 10:25:15 +1300 Subject: [PATCH 0256/2101] Bump actions/setup-python from 4.7.0 to 4.7.1 (#5467) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-docker.yml | 2 +- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 4 ++-- .github/workflows/sync-device-classes.yml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-docker.yml b/.github/workflows/ci-docker.yml index 7fe51163ba..897d01398e 100644 --- a/.github/workflows/ci-docker.yml +++ b/.github/workflows/ci-docker.yml @@ -42,7 +42,7 @@ jobs: steps: - uses: actions/checkout@v4.1.0 - name: Set up Python - uses: actions/setup-python@v4.7.0 + uses: actions/setup-python@v4.7.1 with: python-version: "3.9" - name: Set up Docker Buildx diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 26fcbbf458..435a2fdbec 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,7 +40,7 @@ jobs: run: echo key="${{ hashFiles('requirements.txt', 'requirements_optional.txt', 'requirements_test.txt') }}" >> $GITHUB_OUTPUT - name: Set up Python ${{ env.DEFAULT_PYTHON }} id: python - uses: actions/setup-python@v4.7.0 + uses: actions/setup-python@v4.7.1 with: python-version: ${{ env.DEFAULT_PYTHON }} - name: Restore Python virtual environment diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6934d36686..f7652bf478 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -45,7 +45,7 @@ jobs: steps: - uses: actions/checkout@v4.1.0 - name: Set up Python - uses: actions/setup-python@v4.7.0 + uses: actions/setup-python@v4.7.1 with: python-version: "3.x" - name: Set up python environment @@ -90,7 +90,7 @@ jobs: steps: - uses: actions/checkout@v4.1.0 - name: Set up Python - uses: actions/setup-python@v4.7.0 + uses: actions/setup-python@v4.7.1 with: python-version: "3.9" diff --git a/.github/workflows/sync-device-classes.yml b/.github/workflows/sync-device-classes.yml index 25d36bc6d0..082c63ae41 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@v4.7.0 + uses: actions/setup-python@v4.7.1 with: python-version: 3.11 From 49132565979f2e0bab96a135b3a68cf1484f88c7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Oct 2023 10:51:29 +1300 Subject: [PATCH 0257/2101] Bump zeroconf from 0.115.0 to 0.115.1 (#5470) 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 821e7c5786..97e42663d7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,7 +11,7 @@ esptool==4.6.2 click==8.1.7 esphome-dashboard==20230904.0 aioesphomeapi==15.0.0 -zeroconf==0.115.0 +zeroconf==0.115.1 # esp-idf requires this, but doesn't bundle it by default # https://github.com/espressif/esp-idf/blob/220590d599e134d7a5e7f1e683cc4550349ffbf8/requirements.txt#L24 From e95ba57a6150ba83108435e3454adb04749d04fa Mon Sep 17 00:00:00 2001 From: dwildstr <65917913+dwildstr@users.noreply.github.com> Date: Mon, 2 Oct 2023 19:06:54 -0400 Subject: [PATCH 0258/2101] Sleep mode fix for BP5758D driver (#5461) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/bp5758d/bp5758d.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/esphome/components/bp5758d/bp5758d.cpp b/esphome/components/bp5758d/bp5758d.cpp index 111fd6b68e..71a81f7e6c 100644 --- a/esphome/components/bp5758d/bp5758d.cpp +++ b/esphome/components/bp5758d/bp5758d.cpp @@ -39,10 +39,14 @@ void BP5758D::loop() { uint8_t data[17]; if (this->pwm_amounts_[0] == 0 && this->pwm_amounts_[1] == 0 && this->pwm_amounts_[2] == 0 && this->pwm_amounts_[3] == 0 && this->pwm_amounts_[4] == 0) { - // Off / Sleep - data[0] = BP5758D_MODEL_ID + BP5758D_ADDR_STANDBY; for (int i = 1; i < 16; i++) data[i] = 0; + + // First turn all channels off + data[0] = BP5758D_MODEL_ID + BP5758D_ADDR_START_3CH; + this->write_buffer_(data, 17); + // Then sleep + data[0] = BP5758D_MODEL_ID + BP5758D_ADDR_STANDBY; this->write_buffer_(data, 17); } else if (this->pwm_amounts_[0] == 0 && this->pwm_amounts_[1] == 0 && this->pwm_amounts_[2] == 0 && (this->pwm_amounts_[3] > 0 || this->pwm_amounts_[4] > 0)) { From f38849828d8d7f069527b6cf1543af6a84c1d924 Mon Sep 17 00:00:00 2001 From: Faidon Liambotis Date: Tue, 3 Oct 2023 03:23:18 +0300 Subject: [PATCH 0259/2101] Tuya Number: split "multiply" to a separate option (#5458) --- esphome/components/tuya/number/__init__.py | 7 +++++-- esphome/components/tuya/number/tuya_number.cpp | 4 ++-- esphome/components/tuya/number/tuya_number.h | 2 ++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/esphome/components/tuya/number/__init__.py b/esphome/components/tuya/number/__init__.py index 42ac9fcfbe..4dae6d8d60 100644 --- a/esphome/components/tuya/number/__init__.py +++ b/esphome/components/tuya/number/__init__.py @@ -6,6 +6,7 @@ from esphome.const import ( CONF_NUMBER_DATAPOINT, CONF_MAX_VALUE, CONF_MIN_VALUE, + CONF_MULTIPLY, CONF_STEP, ) from .. import tuya_ns, CONF_TUYA_ID, Tuya @@ -31,6 +32,7 @@ CONFIG_SCHEMA = cv.All( cv.Required(CONF_MAX_VALUE): cv.float_, cv.Required(CONF_MIN_VALUE): cv.float_, cv.Required(CONF_STEP): cv.positive_float, + cv.Optional(CONF_MULTIPLY, default=1.0): cv.float_, } ) .extend(cv.COMPONENT_SCHEMA), @@ -49,7 +51,8 @@ async def to_code(config): step=config[CONF_STEP], ) - paren = await cg.get_variable(config[CONF_TUYA_ID]) - cg.add(var.set_tuya_parent(paren)) + cg.add(var.set_write_multiply(config[CONF_MULTIPLY])) + parent = await cg.get_variable(config[CONF_TUYA_ID]) + cg.add(var.set_tuya_parent(parent)) cg.add(var.set_number_id(config[CONF_NUMBER_DATAPOINT])) diff --git a/esphome/components/tuya/number/tuya_number.cpp b/esphome/components/tuya/number/tuya_number.cpp index 30ef8b8f72..e883c72d3d 100644 --- a/esphome/components/tuya/number/tuya_number.cpp +++ b/esphome/components/tuya/number/tuya_number.cpp @@ -10,7 +10,7 @@ void TuyaNumber::setup() { this->parent_->register_listener(this->number_id_, [this](const TuyaDatapoint &datapoint) { if (datapoint.type == TuyaDatapointType::INTEGER) { ESP_LOGV(TAG, "MCU reported number %u is: %d", datapoint.id, datapoint.value_int); - this->publish_state(datapoint.value_int * this->traits.get_step()); + this->publish_state(datapoint.value_int / multiply_by_); } else if (datapoint.type == TuyaDatapointType::ENUM) { ESP_LOGV(TAG, "MCU reported number %u is: %u", datapoint.id, datapoint.value_enum); this->publish_state(datapoint.value_enum); @@ -22,7 +22,7 @@ void TuyaNumber::setup() { void TuyaNumber::control(float value) { ESP_LOGV(TAG, "Setting number %u: %f", this->number_id_, value); if (this->type_ == TuyaDatapointType::INTEGER) { - int integer_value = lround(value / this->traits.get_step()); + int integer_value = lround(value * multiply_by_); this->parent_->set_integer_datapoint_value(this->number_id_, integer_value); } else if (this->type_ == TuyaDatapointType::ENUM) { this->parent_->set_enum_datapoint_value(this->number_id_, value); diff --git a/esphome/components/tuya/number/tuya_number.h b/esphome/components/tuya/number/tuya_number.h index 7cca9fc646..f64dac8957 100644 --- a/esphome/components/tuya/number/tuya_number.h +++ b/esphome/components/tuya/number/tuya_number.h @@ -12,6 +12,7 @@ class TuyaNumber : public number::Number, public Component { void setup() override; void dump_config() override; void set_number_id(uint8_t number_id) { this->number_id_ = number_id; } + void set_write_multiply(float factor) { multiply_by_ = factor; } void set_tuya_parent(Tuya *parent) { this->parent_ = parent; } @@ -20,6 +21,7 @@ class TuyaNumber : public number::Number, public Component { Tuya *parent_; uint8_t number_id_{0}; + float multiply_by_{1.0}; TuyaDatapointType type_{}; }; From f73fd975250364ae783593ef927393015fbe8577 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 29 Sep 2023 10:58:51 +1300 Subject: [PATCH 0260/2101] Bump zeroconf from 0.112.0 to 0.115.0 (#5432) 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 63199680cf..821e7c5786 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,7 +11,7 @@ esptool==4.6.2 click==8.1.7 esphome-dashboard==20230904.0 aioesphomeapi==15.0.0 -zeroconf==0.112.0 +zeroconf==0.115.0 # esp-idf requires this, but doesn't bundle it by default # https://github.com/espressif/esp-idf/blob/220590d599e134d7a5e7f1e683cc4550349ffbf8/requirements.txt#L24 From 689c2f11a39f7b1c0411160714802c15ffaef74b Mon Sep 17 00:00:00 2001 From: Maxime Gauduin Date: Mon, 2 Oct 2023 23:15:29 +0200 Subject: [PATCH 0261/2101] add pin config for denky_d4 (#5471) --- esphome/components/esp32/boards.py | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/esp32/boards.py b/esphome/components/esp32/boards.py index 61cb8cdc3f..e6c23c4d96 100644 --- a/esphome/components/esp32/boards.py +++ b/esphome/components/esp32/boards.py @@ -235,6 +235,7 @@ ESP32_BOARD_PINS = { "SDA": 5, "SS": 15, }, + "denky_d4": {"RX": 8, "LED": 14}, "esp-wrover-kit": {}, "esp32-devkitlipo": {}, "esp32-evb": { From f5dfbaff4b2938e2015434dc05e4213dfd43077d Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Tue, 3 Oct 2023 08:24:20 +1100 Subject: [PATCH 0262/2101] Support RP2040 hardware SPI (#5466) --- esphome/components/spi/__init__.py | 64 +++++++++++++++++++++++++----- tests/test6.yaml | 8 ++++ 2 files changed, 61 insertions(+), 11 deletions(-) diff --git a/esphome/components/spi/__init__.py b/esphome/components/spi/__init__.py index fb30755511..07e8982f6e 100644 --- a/esphome/components/spi/__init__.py +++ b/esphome/components/spi/__init__.py @@ -54,6 +54,21 @@ CONF_FORCE_SW = "force_sw" CONF_INTERFACE = "interface" CONF_INTERFACE_INDEX = "interface_index" +# RP2040 SPI pin assignments are complicated. Refer to https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf + +RP_SPI_PINSETS = [ + { + CONF_MISO_PIN: [0, 4, 16, 20, -1], + CONF_CLK_PIN: [2, 6, 18, 22], + CONF_MOSI_PIN: [3, 7, 19, 23, -1], + }, + { + CONF_MISO_PIN: [8, 12, 24, 28, -1], + CONF_CLK_PIN: [10, 14, 26], + CONF_MOSI_PIN: [11, 23, 27, -1], + }, +] + def get_target_platform(): return ( @@ -85,7 +100,7 @@ def get_hw_interface_list(): return [["spi", "spi2"]] return [["spi", "spi2"], ["spi3"]] if target_platform == "rp2040": - return [["spi"]] + return [["spi"], ["spi1"]] return [] @@ -99,8 +114,10 @@ def get_spi_index(name): # Check that pins are suitable for HW spi +# \param spi the config data for the spi instance +# \param index the selected hw interface number, -1 if not yet known # TODO verify that the pins are internal -def validate_hw_pins(spi): +def validate_hw_pins(spi, index=-1): clk_pin = spi[CONF_CLK_PIN] if clk_pin[CONF_INVERTED]: return False @@ -129,9 +146,30 @@ def validate_hw_pins(spi): if target_platform == "esp32": return clk_pin_no >= 0 + if target_platform == "rp2040": + pin_set = ( + list(filter(lambda s: clk_pin_no in s[CONF_CLK_PIN], RP_SPI_PINSETS))[0] + if index == -1 + else RP_SPI_PINSETS[index] + ) + if pin_set is None: + return False + if sdo_pin_no not in pin_set[CONF_MOSI_PIN]: + return False + if sdi_pin_no not in pin_set[CONF_MISO_PIN]: + return False + return True return False +def get_hw_spi(config, available): + """Get an available hardware spi interface suitable for this config""" + matching = list(filter(lambda idx: validate_hw_pins(config, idx), available)) + if len(matching) != 0: + return matching[0] + return None + + def validate_spi_config(config): available = list(range(len(get_hw_interface_list()))) for spi in config: @@ -147,9 +185,10 @@ def validate_spi_config(config): if not validate_hw_pins(spi): spi[CONF_INTERFACE] = "software" elif interface == "hardware": - if len(available) == 0: - raise cv.Invalid("No hardware interface available") - index = spi[CONF_INTERFACE_INDEX] = available[0] + index = get_hw_spi(spi, available) + if index is None: + raise cv.Invalid("No suitable hardware interface available") + spi[CONF_INTERFACE_INDEX] = index available.remove(index) else: # Must be a specific name @@ -164,11 +203,14 @@ def validate_spi_config(config): # Any specific names and any 'hardware' requests will have already been filled, # so just need to assign remaining hardware to 'any' requests. for spi in config: - if spi[CONF_INTERFACE] == "any" and len(available) != 0: - index = available[0] - spi[CONF_INTERFACE_INDEX] = index - available.remove(index) - if CONF_INTERFACE_INDEX in spi and not validate_hw_pins(spi): + if spi[CONF_INTERFACE] == "any": + index = get_hw_spi(spi, available) + if index is not None: + spi[CONF_INTERFACE_INDEX] = index + available.remove(index) + if CONF_INTERFACE_INDEX in spi and not validate_hw_pins( + spi, spi[CONF_INTERFACE_INDEX] + ): raise cv.Invalid("Invalid pin selections for hardware SPI interface") return config @@ -181,7 +223,7 @@ def get_spi_interface(index): # Arduino code follows platform = get_target_platform() if platform == "rp2040": - return "&spi1" + return ["&SPI", "&SPI1"][index] if index == 0: return "&SPI" # Following code can't apply to C2, H2 or 8266 since they have only one SPI diff --git a/tests/test6.yaml b/tests/test6.yaml index 3d6a1ceb1f..c6d9c6feba 100644 --- a/tests/test6.yaml +++ b/tests/test6.yaml @@ -39,6 +39,14 @@ switch: output: pin_4 id: pin_4_switch + +spi: # Pins are for SPI1 on the RP2040 Pico-W + miso_pin: 8 + clk_pin: 10 + mosi_pin: 11 + id: spi_0 + interface: hardware + #light: # - platform: rp2040_pio_led_strip # id: led_strip From 85c5928baa6bddc3668f20af3b32ac6052e77f9f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Oct 2023 10:51:29 +1300 Subject: [PATCH 0263/2101] Bump zeroconf from 0.115.0 to 0.115.1 (#5470) 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 821e7c5786..97e42663d7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,7 +11,7 @@ esptool==4.6.2 click==8.1.7 esphome-dashboard==20230904.0 aioesphomeapi==15.0.0 -zeroconf==0.115.0 +zeroconf==0.115.1 # esp-idf requires this, but doesn't bundle it by default # https://github.com/espressif/esp-idf/blob/220590d599e134d7a5e7f1e683cc4550349ffbf8/requirements.txt#L24 From f709350b04ebb52320492fb450fbeded051b6c8e Mon Sep 17 00:00:00 2001 From: dwildstr <65917913+dwildstr@users.noreply.github.com> Date: Mon, 2 Oct 2023 19:06:54 -0400 Subject: [PATCH 0264/2101] Sleep mode fix for BP5758D driver (#5461) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/bp5758d/bp5758d.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/esphome/components/bp5758d/bp5758d.cpp b/esphome/components/bp5758d/bp5758d.cpp index 111fd6b68e..71a81f7e6c 100644 --- a/esphome/components/bp5758d/bp5758d.cpp +++ b/esphome/components/bp5758d/bp5758d.cpp @@ -39,10 +39,14 @@ void BP5758D::loop() { uint8_t data[17]; if (this->pwm_amounts_[0] == 0 && this->pwm_amounts_[1] == 0 && this->pwm_amounts_[2] == 0 && this->pwm_amounts_[3] == 0 && this->pwm_amounts_[4] == 0) { - // Off / Sleep - data[0] = BP5758D_MODEL_ID + BP5758D_ADDR_STANDBY; for (int i = 1; i < 16; i++) data[i] = 0; + + // First turn all channels off + data[0] = BP5758D_MODEL_ID + BP5758D_ADDR_START_3CH; + this->write_buffer_(data, 17); + // Then sleep + data[0] = BP5758D_MODEL_ID + BP5758D_ADDR_STANDBY; this->write_buffer_(data, 17); } else if (this->pwm_amounts_[0] == 0 && this->pwm_amounts_[1] == 0 && this->pwm_amounts_[2] == 0 && (this->pwm_amounts_[3] > 0 || this->pwm_amounts_[4] > 0)) { From 7dfc4c74da6d20de03ee01254e81bf7c5a36509e Mon Sep 17 00:00:00 2001 From: Faidon Liambotis Date: Tue, 3 Oct 2023 03:23:18 +0300 Subject: [PATCH 0265/2101] Tuya Number: split "multiply" to a separate option (#5458) --- esphome/components/tuya/number/__init__.py | 7 +++++-- esphome/components/tuya/number/tuya_number.cpp | 4 ++-- esphome/components/tuya/number/tuya_number.h | 2 ++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/esphome/components/tuya/number/__init__.py b/esphome/components/tuya/number/__init__.py index 42ac9fcfbe..4dae6d8d60 100644 --- a/esphome/components/tuya/number/__init__.py +++ b/esphome/components/tuya/number/__init__.py @@ -6,6 +6,7 @@ from esphome.const import ( CONF_NUMBER_DATAPOINT, CONF_MAX_VALUE, CONF_MIN_VALUE, + CONF_MULTIPLY, CONF_STEP, ) from .. import tuya_ns, CONF_TUYA_ID, Tuya @@ -31,6 +32,7 @@ CONFIG_SCHEMA = cv.All( cv.Required(CONF_MAX_VALUE): cv.float_, cv.Required(CONF_MIN_VALUE): cv.float_, cv.Required(CONF_STEP): cv.positive_float, + cv.Optional(CONF_MULTIPLY, default=1.0): cv.float_, } ) .extend(cv.COMPONENT_SCHEMA), @@ -49,7 +51,8 @@ async def to_code(config): step=config[CONF_STEP], ) - paren = await cg.get_variable(config[CONF_TUYA_ID]) - cg.add(var.set_tuya_parent(paren)) + cg.add(var.set_write_multiply(config[CONF_MULTIPLY])) + parent = await cg.get_variable(config[CONF_TUYA_ID]) + cg.add(var.set_tuya_parent(parent)) cg.add(var.set_number_id(config[CONF_NUMBER_DATAPOINT])) diff --git a/esphome/components/tuya/number/tuya_number.cpp b/esphome/components/tuya/number/tuya_number.cpp index 30ef8b8f72..e883c72d3d 100644 --- a/esphome/components/tuya/number/tuya_number.cpp +++ b/esphome/components/tuya/number/tuya_number.cpp @@ -10,7 +10,7 @@ void TuyaNumber::setup() { this->parent_->register_listener(this->number_id_, [this](const TuyaDatapoint &datapoint) { if (datapoint.type == TuyaDatapointType::INTEGER) { ESP_LOGV(TAG, "MCU reported number %u is: %d", datapoint.id, datapoint.value_int); - this->publish_state(datapoint.value_int * this->traits.get_step()); + this->publish_state(datapoint.value_int / multiply_by_); } else if (datapoint.type == TuyaDatapointType::ENUM) { ESP_LOGV(TAG, "MCU reported number %u is: %u", datapoint.id, datapoint.value_enum); this->publish_state(datapoint.value_enum); @@ -22,7 +22,7 @@ void TuyaNumber::setup() { void TuyaNumber::control(float value) { ESP_LOGV(TAG, "Setting number %u: %f", this->number_id_, value); if (this->type_ == TuyaDatapointType::INTEGER) { - int integer_value = lround(value / this->traits.get_step()); + int integer_value = lround(value * multiply_by_); this->parent_->set_integer_datapoint_value(this->number_id_, integer_value); } else if (this->type_ == TuyaDatapointType::ENUM) { this->parent_->set_enum_datapoint_value(this->number_id_, value); diff --git a/esphome/components/tuya/number/tuya_number.h b/esphome/components/tuya/number/tuya_number.h index 7cca9fc646..f64dac8957 100644 --- a/esphome/components/tuya/number/tuya_number.h +++ b/esphome/components/tuya/number/tuya_number.h @@ -12,6 +12,7 @@ class TuyaNumber : public number::Number, public Component { void setup() override; void dump_config() override; void set_number_id(uint8_t number_id) { this->number_id_ = number_id; } + void set_write_multiply(float factor) { multiply_by_ = factor; } void set_tuya_parent(Tuya *parent) { this->parent_ = parent; } @@ -20,6 +21,7 @@ class TuyaNumber : public number::Number, public Component { Tuya *parent_; uint8_t number_id_{0}; + float multiply_by_{1.0}; TuyaDatapointType type_{}; }; From 471533d0418290814216f84ab500ba2582ad99b2 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 3 Oct 2023 13:35:19 +1300 Subject: [PATCH 0266/2101] Bump version to 2023.9.3 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 496880ac88..15558da081 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2023.9.2" +__version__ = "2023.9.3" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 88bb051f376eb600f6169b907e7490dda6acba13 Mon Sep 17 00:00:00 2001 From: kahrendt Date: Tue, 3 Oct 2023 05:58:11 -0400 Subject: [PATCH 0267/2101] Add xor automation condition (#5453) --- esphome/automation.py | 7 +++++++ esphome/core/base_automation.h | 16 +++++++++++++++ tests/test1.yaml | 36 ++++++++++++++++++++++++++++++---- 3 files changed, 55 insertions(+), 4 deletions(-) diff --git a/esphome/automation.py b/esphome/automation.py index d90a9cb99a..8475858a9c 100644 --- a/esphome/automation.py +++ b/esphome/automation.py @@ -141,6 +141,7 @@ AUTOMATION_SCHEMA = cv.Schema( AndCondition = cg.esphome_ns.class_("AndCondition", Condition) OrCondition = cg.esphome_ns.class_("OrCondition", Condition) NotCondition = cg.esphome_ns.class_("NotCondition", Condition) +XorCondition = cg.esphome_ns.class_("XorCondition", Condition) @register_condition("and", AndCondition, validate_condition_list) @@ -161,6 +162,12 @@ async def not_condition_to_code(config, condition_id, template_arg, args): return cg.new_Pvariable(condition_id, template_arg, condition) +@register_condition("xor", XorCondition, validate_condition_list) +async def xor_condition_to_code(config, condition_id, template_arg, args): + conditions = await build_condition_list(config, template_arg, args) + return cg.new_Pvariable(condition_id, template_arg, conditions) + + @register_condition("lambda", LambdaCondition, cv.returning_lambda) async def lambda_condition_to_code(config, condition_id, template_arg, args): lambda_ = await cg.process_lambda(config, args, return_type=bool) diff --git a/esphome/core/base_automation.h b/esphome/core/base_automation.h index af618af99a..9b3377f694 100644 --- a/esphome/core/base_automation.h +++ b/esphome/core/base_automation.h @@ -48,6 +48,22 @@ template class NotCondition : public Condition { Condition *condition_; }; +template class XorCondition : public Condition { + public: + explicit XorCondition(const std::vector *> &conditions) : conditions_(conditions) {} + bool check(Ts... x) override { + bool xor_state = false; + for (auto *condition : this->conditions_) { + xor_state = xor_state ^ condition->check(x...); + } + + return xor_state; + } + + protected: + std::vector *> conditions_; +}; + template class LambdaCondition : public Condition { public: explicit LambdaCondition(std::function &&f) : f_(std::move(f)) {} diff --git a/tests/test1.yaml b/tests/test1.yaml index b84aa21439..11ce86c5f3 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -3104,11 +3104,39 @@ time: - platform: ds1307 id: ds1307_time update_interval: never - on_time: - seconds: 0 - then: ds1307.read_time i2c_id: i2c_bus - + on_time: + - seconds: 0 + then: ds1307.read_time + - at: "16:00:00" + then: + - if: + condition: + or: + - binary_sensor.is_on: close_sensor + - binary_sensor.is_on: open_sensor + then: + logger.log: "close_sensor or open_sensor is on" + - if: + condition: + and: + - binary_sensor.is_on: close_sensor + - binary_sensor.is_on: open_sensor + then: + logger.log: "close_sensor and open_sensor are both on" + - if: + condition: + xor: + - binary_sensor.is_on: close_sensor + - binary_sensor.is_on: open_sensor + then: + logger.log: "close_sensor or open_sensor is exclusively on" + - if: + condition: + not: + - binary_sensor.is_on: close_sensor + then: + logger.log: "close_sensor is not on" cover: - platform: template name: Template Cover From 050fa0d4c17ac240abf2ebafdc27fdab1d53135d Mon Sep 17 00:00:00 2001 From: kahrendt Date: Tue, 3 Oct 2023 06:01:57 -0400 Subject: [PATCH 0268/2101] Fix units for SPS30 number concentration sensors (#5452) --- esphome/components/sps30/sensor.py | 12 ++++++------ esphome/const.py | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/esphome/components/sps30/sensor.py b/esphome/components/sps30/sensor.py index ff8d5a3594..0f01bab514 100644 --- a/esphome/components/sps30/sensor.py +++ b/esphome/components/sps30/sensor.py @@ -20,7 +20,7 @@ from esphome.const import ( DEVICE_CLASS_PM25, STATE_CLASS_MEASUREMENT, UNIT_MICROGRAMS_PER_CUBIC_METER, - UNIT_COUNTS_PER_CUBIC_METER, + UNIT_COUNTS_PER_CUBIC_CENTIMETER, UNIT_MICROMETER, ICON_CHEMICAL_WEAPON, ICON_COUNTER, @@ -73,31 +73,31 @@ CONFIG_SCHEMA = ( state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_PMC_0_5): sensor.sensor_schema( - unit_of_measurement=UNIT_COUNTS_PER_CUBIC_METER, + unit_of_measurement=UNIT_COUNTS_PER_CUBIC_CENTIMETER, icon=ICON_COUNTER, accuracy_decimals=2, state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_PMC_1_0): sensor.sensor_schema( - unit_of_measurement=UNIT_COUNTS_PER_CUBIC_METER, + unit_of_measurement=UNIT_COUNTS_PER_CUBIC_CENTIMETER, icon=ICON_COUNTER, accuracy_decimals=2, state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_PMC_2_5): sensor.sensor_schema( - unit_of_measurement=UNIT_COUNTS_PER_CUBIC_METER, + unit_of_measurement=UNIT_COUNTS_PER_CUBIC_CENTIMETER, icon=ICON_COUNTER, accuracy_decimals=2, state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_PMC_4_0): sensor.sensor_schema( - unit_of_measurement=UNIT_COUNTS_PER_CUBIC_METER, + unit_of_measurement=UNIT_COUNTS_PER_CUBIC_CENTIMETER, icon=ICON_COUNTER, accuracy_decimals=2, state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_PMC_10_0): sensor.sensor_schema( - unit_of_measurement=UNIT_COUNTS_PER_CUBIC_METER, + unit_of_measurement=UNIT_COUNTS_PER_CUBIC_CENTIMETER, icon=ICON_COUNTER, accuracy_decimals=2, state_class=STATE_CLASS_MEASUREMENT, diff --git a/esphome/const.py b/esphome/const.py index 2865b369e8..e188ba478e 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -915,7 +915,7 @@ UNIT_BYTES = "B" UNIT_CELSIUS = "°C" UNIT_CENTIMETER = "cm" UNIT_COUNT_DECILITRE = "/dL" -UNIT_COUNTS_PER_CUBIC_METER = "#/m³" +UNIT_COUNTS_PER_CUBIC_CENTIMETER = "#/cm³" UNIT_CUBIC_METER = "m³" UNIT_CUBIC_METER_PER_HOUR = "m³/h" UNIT_DECIBEL = "dB" From 506c2ba6c7064692a11bf18b0a9ed935a6055ffc Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Wed, 4 Oct 2023 12:10:26 +1100 Subject: [PATCH 0269/2101] ST7789v - Allow predefined backlight pin to be disabled. (#5476) * Allow predefined backlight pin to be disabled. * Add test * Update esphome/components/st7789v/display.py --- esphome/components/st7789v/display.py | 7 +++++-- tests/test1.yaml | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/esphome/components/st7789v/display.py b/esphome/components/st7789v/display.py index ad152bf356..a4c08974c6 100644 --- a/esphome/components/st7789v/display.py +++ b/esphome/components/st7789v/display.py @@ -138,7 +138,10 @@ CONFIG_SCHEMA = cv.All( cv.Required(CONF_MODEL): cv.one_of(*MODELS.keys(), upper=True, space="_"), cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, cv.Optional(CONF_DC_PIN): pins.gpio_output_pin_schema, - cv.Optional(CONF_BACKLIGHT_PIN): pins.gpio_output_pin_schema, + cv.Optional(CONF_BACKLIGHT_PIN): cv.Any( + cv.boolean, + pins.gpio_output_pin_schema, + ), cv.Optional(CONF_POWER_SUPPLY): cv.use_id(power_supply.PowerSupply), cv.Optional(CONF_EIGHTBITCOLOR, default=False): cv.boolean, cv.Optional(CONF_HEIGHT): cv.int_, @@ -174,7 +177,7 @@ async def to_code(config): reset = await cg.gpio_pin_expression(config[CONF_RESET_PIN]) cg.add(var.set_reset_pin(reset)) - if CONF_BACKLIGHT_PIN in config: + if CONF_BACKLIGHT_PIN in config and config[CONF_BACKLIGHT_PIN]: bl = await cg.gpio_pin_expression(config[CONF_BACKLIGHT_PIN]) cg.add(var.set_backlight_pin(bl)) diff --git a/tests/test1.yaml b/tests/test1.yaml index 11ce86c5f3..ea69343dbf 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -2948,7 +2948,7 @@ display: cs_pin: GPIO5 dc_pin: GPIO16 reset_pin: GPIO23 - backlight_pin: GPIO4 + backlight_pin: no lambda: |- it.rectangle(0, 0, it.get_width(), it.get_height()); - platform: st7920 From 4e8cba49f1240c76388a9db49b1cb903e702a1af Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Wed, 4 Oct 2023 12:15:44 +1100 Subject: [PATCH 0270/2101] MAX7219 - Update intensity (#5477) --- esphome/components/max7219/max7219.cpp | 12 +++++++++++- esphome/components/max7219/max7219.h | 3 ++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/esphome/components/max7219/max7219.cpp b/esphome/components/max7219/max7219.cpp index b08723f1d4..d3cf6f5c48 100644 --- a/esphome/components/max7219/max7219.cpp +++ b/esphome/components/max7219/max7219.cpp @@ -164,6 +164,10 @@ void MAX7219Component::send_to_all_(uint8_t a_register, uint8_t data) { this->disable(); } void MAX7219Component::update() { + if (this->intensity_changed_) { + this->send_to_all_(MAX7219_REGISTER_INTENSITY, this->intensity_); + this->intensity_changed_ = false; + } for (uint8_t i = 0; i < this->num_chips_ * 8; i++) this->buffer_[i] = 0; if (this->writer_.has_value()) @@ -217,7 +221,13 @@ uint8_t MAX7219Component::printf(const char *format, ...) { return 0; } void MAX7219Component::set_writer(max7219_writer_t &&writer) { this->writer_ = writer; } -void MAX7219Component::set_intensity(uint8_t intensity) { this->intensity_ = intensity; } +void MAX7219Component::set_intensity(uint8_t intensity) { + intensity &= 0xF; + if (intensity != this->intensity_) { + this->intensity_changed_ = true; + 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) { diff --git a/esphome/components/max7219/max7219.h b/esphome/components/max7219/max7219.h index 1b724cef69..270edf3282 100644 --- a/esphome/components/max7219/max7219.h +++ b/esphome/components/max7219/max7219.h @@ -52,7 +52,8 @@ class MAX7219Component : public PollingComponent, void send_byte_(uint8_t a_register, uint8_t data); void send_to_all_(uint8_t a_register, uint8_t data); - uint8_t intensity_{15}; /// Intensity of the display from 0 to 15 (most) + 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_; bool reverse_{false}; From b6d5cb4142c42de8c6b6a12af4caf4c87546b673 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Thu, 5 Oct 2023 07:18:33 +1100 Subject: [PATCH 0271/2101] St7789v and SPI data rate (#5472) --- esphome/components/ili9xxx/display.py | 5 +---- esphome/components/max6675/max6675.h | 2 +- esphome/components/spi/__init__.py | 27 ++++++++++++++++++++++- esphome/components/spi_device/__init__.py | 6 ++--- esphome/components/spi_led_strip/light.py | 6 ++--- esphome/components/st7789v/st7789v.cpp | 1 + tests/test2.yaml | 1 + 7 files changed, 34 insertions(+), 14 deletions(-) diff --git a/esphome/components/ili9xxx/display.py b/esphome/components/ili9xxx/display.py index 89a6b2d1b9..1a18978d94 100644 --- a/esphome/components/ili9xxx/display.py +++ b/esphome/components/ili9xxx/display.py @@ -13,7 +13,6 @@ from esphome.const import ( CONF_PAGES, CONF_RESET_PIN, CONF_DIMENSIONS, - CONF_DATA_RATE, ) DEPENDENCIES = ["spi"] @@ -100,11 +99,10 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_COLOR_PALETTE_IMAGES, default=[]): cv.ensure_list( cv.file_ ), - cv.Optional(CONF_DATA_RATE, default="40MHz"): spi.SPI_DATA_RATE_SCHEMA, } ) .extend(cv.polling_component_schema("1s")) - .extend(spi.spi_device_schema(False)), + .extend(spi.spi_device_schema(False, "40MHz")), cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA), _validate, ) @@ -177,4 +175,3 @@ async def to_code(config): if rhs is not None: prog_arr = cg.progmem_array(config[CONF_RAW_DATA_ID], rhs) cg.add(var.set_palette(prog_arr)) - cg.add(var.set_data_rate(config[CONF_DATA_RATE])) diff --git a/esphome/components/max6675/max6675.h b/esphome/components/max6675/max6675.h index 09bd9df3b8..ab0f06b041 100644 --- a/esphome/components/max6675/max6675.h +++ b/esphome/components/max6675/max6675.h @@ -10,7 +10,7 @@ namespace max6675 { class MAX6675Sensor : public sensor::Sensor, public PollingComponent, public spi::SPIDevice { + spi::DATA_RATE_1MHZ> { public: void setup() override; void dump_config() override; diff --git a/esphome/components/spi/__init__.py b/esphome/components/spi/__init__.py index 07e8982f6e..dc9d560874 100644 --- a/esphome/components/spi/__init__.py +++ b/esphome/components/spi/__init__.py @@ -25,6 +25,7 @@ from esphome.const import ( KEY_CORE, KEY_TARGET_PLATFORM, KEY_VARIANT, + CONF_DATA_RATE, ) from esphome.core import coroutine_with_priority, CORE @@ -33,6 +34,7 @@ spi_ns = cg.esphome_ns.namespace("spi") SPIComponent = spi_ns.class_("SPIComponent", cg.Component) SPIDevice = spi_ns.class_("SPIDevice") SPIDataRate = spi_ns.enum("SPIDataRate") +SPIMode = spi_ns.enum("SPIMode") SPI_DATA_RATE_OPTIONS = { 80e6: SPIDataRate.DATA_RATE_80MHZ, @@ -50,6 +52,18 @@ SPI_DATA_RATE_OPTIONS = { } SPI_DATA_RATE_SCHEMA = cv.All(cv.frequency, cv.enum(SPI_DATA_RATE_OPTIONS)) +SPI_MODE_OPTIONS = { + "MODE0": SPIMode.MODE0, + "MODE1": SPIMode.MODE1, + "MODE2": SPIMode.MODE2, + "MODE3": SPIMode.MODE3, + 0: SPIMode.MODE0, + 1: SPIMode.MODE1, + 2: SPIMode.MODE2, + 3: SPIMode.MODE3, +} + +CONF_SPI_MODE = "spi_mode" CONF_FORCE_SW = "force_sw" CONF_INTERFACE = "interface" CONF_INTERFACE_INDEX = "interface_index" @@ -286,13 +300,20 @@ async def to_code(configs): cg.add_library("SPI", None) -def spi_device_schema(cs_pin_required=True): +def spi_device_schema( + cs_pin_required=True, default_data_rate=cv.UNDEFINED, default_mode=cv.UNDEFINED +): """Create a schema for an SPI device. :param cs_pin_required: If true, make the CS_PIN required in the config. + :param default_data_rate: Optional data_rate to use as default :return: The SPI device schema, `extend` this in your config schema. """ schema = { cv.GenerateID(CONF_SPI_ID): cv.use_id(SPIComponent), + cv.Optional(CONF_DATA_RATE, default=default_data_rate): SPI_DATA_RATE_SCHEMA, + cv.Optional(CONF_SPI_MODE, default=default_mode): cv.enum( + SPI_MODE_OPTIONS, upper=True + ), } if cs_pin_required: schema[cv.Required(CONF_CS_PIN)] = pins.gpio_output_pin_schema @@ -307,6 +328,10 @@ async def register_spi_device(var, config): if CONF_CS_PIN in config: pin = await cg.gpio_pin_expression(config[CONF_CS_PIN]) cg.add(var.set_cs_pin(pin)) + if CONF_DATA_RATE in config: + cg.add(var.set_data_rate(config[CONF_DATA_RATE])) + if CONF_SPI_MODE in config: + cg.add(var.set_mode(config[CONF_SPI_MODE])) def final_validate_device_schema(name: str, *, require_mosi: bool, require_miso: bool): diff --git a/esphome/components/spi_device/__init__.py b/esphome/components/spi_device/__init__.py index 428b5bfbda..65e7ee6fc6 100644 --- a/esphome/components/spi_device/__init__.py +++ b/esphome/components/spi_device/__init__.py @@ -1,7 +1,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import spi -from esphome.const import CONF_ID, CONF_DATA_RATE, CONF_MODE +from esphome.const import CONF_ID, CONF_MODE DEPENDENCIES = ["spi"] CODEOWNERS = ["@clydebarrow"] @@ -33,17 +33,15 @@ CONF_BIT_ORDER = "bit_order" CONFIG_SCHEMA = cv.Schema( { cv.GenerateID(CONF_ID): cv.declare_id(spi_device), - cv.Optional(CONF_DATA_RATE, default="1MHz"): spi.SPI_DATA_RATE_SCHEMA, cv.Optional(CONF_BIT_ORDER, default="msb_first"): cv.enum(ORDERS, lower=True), cv.Optional(CONF_MODE, default="0"): cv.enum(MODES, upper=True), } -).extend(spi.spi_device_schema(False)) +).extend(spi.spi_device_schema(False, "1MHz")) async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) - cg.add(var.set_data_rate(config[CONF_DATA_RATE])) cg.add(var.set_mode(config[CONF_MODE])) cg.add(var.set_bit_order(config[CONF_BIT_ORDER])) await spi.register_spi_device(var, config) diff --git a/esphome/components/spi_led_strip/light.py b/esphome/components/spi_led_strip/light.py index 7420b0c929..78642935de 100644 --- a/esphome/components/spi_led_strip/light.py +++ b/esphome/components/spi_led_strip/light.py @@ -2,7 +2,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import light from esphome.components import spi -from esphome.const import CONF_OUTPUT_ID, CONF_NUM_LEDS, CONF_DATA_RATE +from esphome.const import CONF_OUTPUT_ID, CONF_NUM_LEDS spi_led_strip_ns = cg.esphome_ns.namespace("spi_led_strip") SpiLedStrip = spi_led_strip_ns.class_( @@ -13,14 +13,12 @@ CONFIG_SCHEMA = light.ADDRESSABLE_LIGHT_SCHEMA.extend( { cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(SpiLedStrip), cv.Optional(CONF_NUM_LEDS, default=1): cv.positive_not_null_int, - cv.Optional(CONF_DATA_RATE, default="1MHz"): spi.SPI_DATA_RATE_SCHEMA, } -).extend(spi.spi_device_schema(False)) +).extend(spi.spi_device_schema(False, "1MHz")) async def to_code(config): var = cg.new_Pvariable(config[CONF_OUTPUT_ID]) - cg.add(var.set_data_rate(spi.SPI_DATA_RATE_OPTIONS[config[CONF_DATA_RATE]])) cg.add(var.set_num_leds(config[CONF_NUM_LEDS])) await light.register_light(var, config) await spi.register_spi_device(var, config) diff --git a/esphome/components/st7789v/st7789v.cpp b/esphome/components/st7789v/st7789v.cpp index a181723546..74c7a4e9e3 100644 --- a/esphome/components/st7789v/st7789v.cpp +++ b/esphome/components/st7789v/st7789v.cpp @@ -133,6 +133,7 @@ void ST7789V::dump_config() { LOG_PIN(" Reset Pin: ", this->reset_pin_); LOG_PIN(" B/L Pin: ", this->backlight_pin_); LOG_UPDATE_INTERVAL(this); + ESP_LOGCONFIG(TAG, " Data rate: %dMHz", (unsigned) (this->data_rate_ / 1000000)); #ifdef USE_POWER_SUPPLY ESP_LOGCONFIG(TAG, " Power Supply Configured: yes"); #endif diff --git a/tests/test2.yaml b/tests/test2.yaml index 5485711c2e..fe577c2188 100644 --- a/tests/test2.yaml +++ b/tests/test2.yaml @@ -724,6 +724,7 @@ interval: display: - platform: st7789v model: LILYGO_T-EMBED_170X320 + spi_mode: mode0 height: 320 width: 170 offset_height: 35 From 44e5b0c74540bdabfd55c0f68ed84e77277477d0 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Fri, 6 Oct 2023 00:28:51 -0500 Subject: [PATCH 0272/2101] Move CONF_IRQ_PIN into const.py (#5488) --- esphome/components/ade7953/sensor.py | 4 ++-- esphome/components/as3935/__init__.py | 12 ++++++------ esphome/components/xpt2046/touchscreen.py | 3 +-- esphome/const.py | 1 + 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/esphome/components/ade7953/sensor.py b/esphome/components/ade7953/sensor.py index 878f2f8e2d..8a43baf475 100644 --- a/esphome/components/ade7953/sensor.py +++ b/esphome/components/ade7953/sensor.py @@ -4,13 +4,14 @@ from esphome.components import sensor, i2c from esphome import pins from esphome.const import ( CONF_ID, + CONF_IRQ_PIN, CONF_VOLTAGE, DEVICE_CLASS_CURRENT, DEVICE_CLASS_POWER, DEVICE_CLASS_VOLTAGE, STATE_CLASS_MEASUREMENT, - UNIT_VOLT, UNIT_AMPERE, + UNIT_VOLT, UNIT_WATT, ) @@ -19,7 +20,6 @@ DEPENDENCIES = ["i2c"] ade7953_ns = cg.esphome_ns.namespace("ade7953") ADE7953 = ade7953_ns.class_("ADE7953", cg.PollingComponent, i2c.I2CDevice) -CONF_IRQ_PIN = "irq_pin" CONF_CURRENT_A = "current_a" CONF_CURRENT_B = "current_b" CONF_ACTIVE_POWER_A = "active_power_a" diff --git a/esphome/components/as3935/__init__.py b/esphome/components/as3935/__init__.py index cf0580ca62..5cec1bfaba 100644 --- a/esphome/components/as3935/__init__.py +++ b/esphome/components/as3935/__init__.py @@ -2,14 +2,15 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import pins from esphome.const import ( + CONF_CAPACITANCE, + CONF_DIV_RATIO, CONF_INDOOR, - CONF_WATCHDOG_THRESHOLD, - CONF_NOISE_LEVEL, - CONF_SPIKE_REJECTION, + CONF_IRQ_PIN, CONF_LIGHTNING_THRESHOLD, CONF_MASK_DISTURBER, - CONF_DIV_RATIO, - CONF_CAPACITANCE, + CONF_NOISE_LEVEL, + CONF_SPIKE_REJECTION, + CONF_WATCHDOG_THRESHOLD, ) MULTI_CONF = True @@ -19,7 +20,6 @@ CONF_AS3935_ID = "as3935_id" as3935_ns = cg.esphome_ns.namespace("as3935") AS3935 = as3935_ns.class_("AS3935Component", cg.Component) -CONF_IRQ_PIN = "irq_pin" AS3935_SCHEMA = cv.Schema( { cv.GenerateID(): cv.declare_id(AS3935), diff --git a/esphome/components/xpt2046/touchscreen.py b/esphome/components/xpt2046/touchscreen.py index e45b723179..150d1cf396 100644 --- a/esphome/components/xpt2046/touchscreen.py +++ b/esphome/components/xpt2046/touchscreen.py @@ -3,7 +3,7 @@ import esphome.config_validation as cv from esphome import pins from esphome.components import spi, touchscreen -from esphome.const import CONF_ID, CONF_THRESHOLD, CONF_INTERRUPT_PIN +from esphome.const import CONF_ID, CONF_INTERRUPT_PIN, CONF_IRQ_PIN, CONF_THRESHOLD CODEOWNERS = ["@numo68", "@nielsnl68"] DEPENDENCIES = ["spi"] @@ -26,7 +26,6 @@ CONF_SWAP_X_Y = "swap_x_y" # obsolete Keys CONF_DIMENSION_X = "dimension_x" CONF_DIMENSION_Y = "dimension_y" -CONF_IRQ_PIN = "irq_pin" def validate_xpt2046(config): diff --git a/esphome/const.py b/esphome/const.py index e188ba478e..75ed874cfd 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -360,6 +360,7 @@ CONF_INVALID_COOLDOWN = "invalid_cooldown" CONF_INVERT = "invert" CONF_INVERTED = "inverted" CONF_IP_ADDRESS = "ip_address" +CONF_IRQ_PIN = "irq_pin" CONF_JS_INCLUDE = "js_include" CONF_JS_URL = "js_url" CONF_JVC = "jvc" From fa0dcac2c75d81f9b2a1b287c9792f1bc281bed4 Mon Sep 17 00:00:00 2001 From: Austin Date: Sun, 8 Oct 2023 14:34:12 -0400 Subject: [PATCH 0273/2101] Initial ESP32-H2 Support (#5498) --- esphome/components/deep_sleep/__init__.py | 2 + esphome/components/esp32/gpio_esp32_h2.py | 50 +++++++++++++++++-- .../components/esp32_rmt_led_strip/light.py | 1 + esphome/components/logger/__init__.py | 2 + esphome/components/logger/logger.cpp | 18 ++++--- esphome/components/logger/logger.h | 11 ++-- esphome/components/wifi/__init__.py | 12 ++++- 7 files changed, 80 insertions(+), 16 deletions(-) diff --git a/esphome/components/deep_sleep/__init__.py b/esphome/components/deep_sleep/__init__.py index 6e71f7bbf6..bb7084282c 100644 --- a/esphome/components/deep_sleep/__init__.py +++ b/esphome/components/deep_sleep/__init__.py @@ -24,6 +24,7 @@ from esphome.components.esp32.const import ( VARIANT_ESP32S3, VARIANT_ESP32C2, VARIANT_ESP32C6, + VARIANT_ESP32H2, ) WAKEUP_PINS = { @@ -98,6 +99,7 @@ WAKEUP_PINS = { ], VARIANT_ESP32C2: [0, 1, 2, 3, 4, 5], VARIANT_ESP32C6: [0, 1, 2, 3, 4, 5, 6, 7], + VARIANT_ESP32H2: [7, 8, 9, 10, 11, 12, 13, 14], } diff --git a/esphome/components/esp32/gpio_esp32_h2.py b/esphome/components/esp32/gpio_esp32_h2.py index 5196ef0c09..d18ee8a2a6 100644 --- a/esphome/components/esp32/gpio_esp32_h2.py +++ b/esphome/components/esp32/gpio_esp32_h2.py @@ -1,11 +1,53 @@ +import logging + +from esphome.const import CONF_INPUT, CONF_MODE, CONF_NUMBER + import esphome.config_validation as cv +_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} + +_LOGGER = logging.getLogger(__name__) + def esp32_h2_validate_gpio_pin(value): - # ESP32-H2 not yet supported - raise cv.Invalid("ESP32-H2 isn't supported yet") + if value < 0 or value > 27: + raise cv.Invalid(f"Invalid pin number: {value} (must be 0-27)") + if value in _ESP32H2_STRAPPING_PINS: + _LOGGER.warning( + "GPIO%d is a Strapping PIN and should be avoided.\n" + "Attaching external pullup/down resistors to strapping pins can cause unexpected failures.\n" + "See https://esphome.io/guides/faq.html#why-am-i-getting-a-warning-about-strapping-pins", + value, + ) + if value in _ESP32H2_SPI_FLASH_PINS: + _LOGGER.warning( + "GPIO%d is reserved for SPI Flash communication on some ESP32-H2 chip variants.\n" + "Utilizing SPI-reserved pins could cause unexpected failures.\n" + "See https://docs.espressif.com/projects/esp-idf/en/latest/esp32h2/api-reference/peripherals/gpio.html", + value, + ) + 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.", + value, + ) + + return value def esp32_h2_validate_supports(value): - # ESP32-H2 not yet supported - raise cv.Invalid("ESP32-H2 isn't supported yet") + num = value[CONF_NUMBER] + mode = value[CONF_MODE] + is_input = mode[CONF_INPUT] + + if num < 0 or num > 27: + raise cv.Invalid(f"Invalid pin number: {value} (must be 0-27)") + if is_input: + # All ESP32 pins support input mode + pass + return value diff --git a/esphome/components/esp32_rmt_led_strip/light.py b/esphome/components/esp32_rmt_led_strip/light.py index 5b65ecdabf..43629bec51 100644 --- a/esphome/components/esp32_rmt_led_strip/light.py +++ b/esphome/components/esp32_rmt_led_strip/light.py @@ -64,6 +64,7 @@ RMT_CHANNELS = { esp32.const.VARIANT_ESP32S3: [0, 1, 2, 3], esp32.const.VARIANT_ESP32C3: [0, 1], esp32.const.VARIANT_ESP32C6: [0, 1], + esp32.const.VARIANT_ESP32H2: [0, 1], } diff --git a/esphome/components/logger/__init__.py b/esphome/components/logger/__init__.py index 5225a227ec..e431997276 100644 --- a/esphome/components/logger/__init__.py +++ b/esphome/components/logger/__init__.py @@ -32,6 +32,7 @@ from esphome.components.esp32.const import ( VARIANT_ESP32S3, VARIANT_ESP32C2, VARIANT_ESP32C6, + VARIANT_ESP32H2, ) from esphome.components.libretiny import get_libretiny_component, get_libretiny_family from esphome.components.libretiny.const import ( @@ -86,6 +87,7 @@ UART_SELECTION_ESP32 = { VARIANT_ESP32C3: [UART0, UART1, USB_SERIAL_JTAG], VARIANT_ESP32C2: [UART0, UART1], VARIANT_ESP32C6: [UART0, UART1, USB_CDC, USB_SERIAL_JTAG], + VARIANT_ESP32H2: [UART0, UART1, USB_CDC, USB_SERIAL_JTAG], } UART_SELECTION_ESP8266 = [UART0, UART0_SWAP, UART1] diff --git a/esphome/components/logger/logger.cpp b/esphome/components/logger/logger.cpp index df4662024f..d1f3149d84 100644 --- a/esphome/components/logger/logger.cpp +++ b/esphome/components/logger/logger.cpp @@ -121,7 +121,7 @@ void HOT Logger::log_message_(int level, const char *tag, int offset) { if ( #if defined(USE_ESP32_VARIANT_ESP32S2) uart_ == UART_SELECTION_USB_CDC -#elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) +#elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32H2) uart_ == UART_SELECTION_USB_SERIAL_JTAG #elif defined(USE_ESP32_VARIANT_ESP32S3) uart_ == UART_SELECTION_USB_CDC || uart_ == UART_SELECTION_USB_SERIAL_JTAG @@ -218,21 +218,24 @@ void Logger::pre_setup() { uart_num_ = UART_NUM_1; break; #if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32C6) && \ - !defined(USE_ESP32_VARIANT_ESP32S2) && !defined(USE_ESP32_VARIANT_ESP32S3) + !defined(USE_ESP32_VARIANT_ESP32S2) && !defined(USE_ESP32_VARIANT_ESP32S3) && !defined(USE_ESP32_VARIANT_ESP32H2) case UART_SELECTION_UART2: uart_num_ = UART_NUM_2; break; -#endif // !USE_ESP32_VARIANT_ESP32C3 && !USE_ESP32_VARIANT_ESP32S2 && !USE_ESP32_VARIANT_ESP32S3 +#endif // !USE_ESP32_VARIANT_ESP32C3 && !USE_ESP32_VARIANT_ESP32S2 && !USE_ESP32_VARIANT_ESP32S3 && + // !USE_ESP32_VARIANT_ESP32H2 #if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) case UART_SELECTION_USB_CDC: uart_num_ = -1; break; #endif // USE_ESP32_VARIANT_ESP32S2 || USE_ESP32_VARIANT_ESP32S3 -#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S3) +#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S3) || \ + defined(USE_ESP32_VARIANT_ESP32H2) case UART_SELECTION_USB_SERIAL_JTAG: uart_num_ = -1; break; -#endif // USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C6 || USE_ESP32_VARIANT_ESP32S3 +#endif // USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C6 || USE_ESP32_VARIANT_ESP32S3 || + // USE_ESP32_VARIANT_ESP32H2 } if (uart_num_ >= 0) { uart_config_t uart_config{}; @@ -331,9 +334,10 @@ const char *const LOG_LEVELS[] = {"NONE", "ERROR", "WARN", "INFO", "CONFIG", "DE const char *const UART_SELECTIONS[] = { "UART0", "UART1", #if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32C6) && \ - !defined(USE_ESP32_VARIANT_ESP32S2) && !defined(USE_ESP32_VARIANT_ESP32S3) + !defined(USE_ESP32_VARIANT_ESP32S2) && !defined(USE_ESP32_VARIANT_ESP32S3) && !defined(USE_ESP32_VARIANT_ESP32H2) "UART2", -#endif // !USE_ESP32_VARIANT_ESP32C3 && !USE_ESP32_VARIANT_ESP32S2 && !USE_ESP32_VARIANT_ESP32S3 +#endif // !USE_ESP32_VARIANT_ESP32C3 && !USE_ESP32_VARINT_ESP32C6 && !USE_ESP32_VARIANT_ESP32S2 && + // !USE_ESP32_VARIANT_ESP32S3 && !USE_ESP32_VARIANT_ESP32H2 #if defined(USE_ESP_IDF) #if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) "USB_CDC", diff --git a/esphome/components/logger/logger.h b/esphome/components/logger/logger.h index 4a7a43c7c2..de272934bf 100644 --- a/esphome/components/logger/logger.h +++ b/esphome/components/logger/logger.h @@ -41,16 +41,19 @@ enum UARTSelection { UART_SELECTION_UART1, #if defined(USE_ESP32) #if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32C6) && \ - !defined(USE_ESP32_VARIANT_ESP32S2) && !defined(USE_ESP32_VARIANT_ESP32S3) + !defined(USE_ESP32_VARIANT_ESP32S2) && !defined(USE_ESP32_VARIANT_ESP32S3) && !defined(USE_ESP32_VARIANT_ESP32H2) UART_SELECTION_UART2, -#endif // !USE_ESP32_VARIANT_ESP32C3 && !USE_ESP32_VARIANT_ESP32S2 && !USE_ESP32_VARIANT_ESP32S3 +#endif // !USE_ESP32_VARIANT_ESP32C3 && !USE_ESP32_VARIANT_ESP32C6 && !USE_ESP32_VARIANT_ESP32S2 && + // !USE_ESP32_VARIANT_ESP32S3 && !USE_ESP32_VARIANT_ESP32H2 #ifdef USE_ESP_IDF #if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) UART_SELECTION_USB_CDC, #endif // USE_ESP32_VARIANT_ESP32S2 || USE_ESP32_VARIANT_ESP32S3 -#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S3) +#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S3) || \ + defined(USE_ESP32_VARIANT_ESP32H2) UART_SELECTION_USB_SERIAL_JTAG, -#endif // USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32S3 +#endif // USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C6 || USE_ESP32_VARIANT_ESP32S3 || + // USE_ESP32_VARIANT_ESP32H2 #endif // USE_ESP_IDF #endif // USE_ESP32 #ifdef USE_ESP8266 diff --git a/esphome/components/wifi/__init__.py b/esphome/components/wifi/__init__.py index 1baffcbfcc..86ce53b804 100644 --- a/esphome/components/wifi/__init__.py +++ b/esphome/components/wifi/__init__.py @@ -34,12 +34,14 @@ from esphome.const import ( CONF_EAP, ) from esphome.core import CORE, HexInt, coroutine_with_priority -from esphome.components.esp32 import add_idf_sdkconfig_option +from esphome.components.esp32 import add_idf_sdkconfig_option, get_esp32_variant, const from esphome.components.network import IPAddress from . import wpa2_eap AUTO_LOAD = ["network"] +NO_WIFI_VARIANTS = [const.VARIANT_ESP32H2] + wifi_ns = cg.esphome_ns.namespace("wifi") EAPAuth = wifi_ns.struct("EAPAuth") ManualIP = wifi_ns.struct("ManualIP") @@ -148,6 +150,13 @@ WIFI_NETWORK_STA = WIFI_NETWORK_BASE.extend( ) +def validate_variant(_): + if CORE.is_esp32: + variant = get_esp32_variant() + if variant in NO_WIFI_VARIANTS: + raise cv.Invalid(f"{variant} does not support WiFi") + + def final_validate(config): has_sta = bool(config.get(CONF_NETWORKS, True)) has_ap = CONF_AP in config @@ -199,6 +208,7 @@ FINAL_VALIDATE_SCHEMA = cv.All( extra=cv.ALLOW_EXTRA, ), final_validate, + validate_variant, ) From ee4ccf2762a565ecc8f8d58646127626b7978601 Mon Sep 17 00:00:00 2001 From: Luke Ansell <33194087+lukeansell@users.noreply.github.com> Date: Sun, 8 Oct 2023 22:20:43 +0200 Subject: [PATCH 0274/2101] Increased debug message precision (#5496) --- esphome/components/ultrasonic/ultrasonic_sensor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/ultrasonic/ultrasonic_sensor.cpp b/esphome/components/ultrasonic/ultrasonic_sensor.cpp index 9f47f9f6b9..dc828aed6b 100644 --- a/esphome/components/ultrasonic/ultrasonic_sensor.cpp +++ b/esphome/components/ultrasonic/ultrasonic_sensor.cpp @@ -37,7 +37,7 @@ void UltrasonicSensorComponent::update() { this->publish_state(NAN); } else { float result = UltrasonicSensorComponent::us_to_m(pulse_end - pulse_start); - ESP_LOGD(TAG, "'%s' - Got distance: %.2f m", this->name_.c_str(), result); + ESP_LOGD(TAG, "'%s' - Got distance: %.3f m", this->name_.c_str(), result); this->publish_state(result); } } From 7e7c83b3ca87a7eda8d76b20b994abb8170aa252 Mon Sep 17 00:00:00 2001 From: Pavlo Dudnytskyi Date: Sun, 8 Oct 2023 22:49:55 +0200 Subject: [PATCH 0275/2101] Support for Haier IR protocol added (#5403) --- esphome/components/remote_base/__init__.py | 34 ++++++++ .../components/remote_base/haier_protocol.cpp | 84 +++++++++++++++++++ .../components/remote_base/haier_protocol.h | 40 +++++++++ tests/test1.yaml | 5 ++ 4 files changed, 163 insertions(+) create mode 100644 esphome/components/remote_base/haier_protocol.cpp create mode 100644 esphome/components/remote_base/haier_protocol.h diff --git a/esphome/components/remote_base/__init__.py b/esphome/components/remote_base/__init__.py index e2d96c9472..5a703066a1 100644 --- a/esphome/components/remote_base/__init__.py +++ b/esphome/components/remote_base/__init__.py @@ -1558,3 +1558,37 @@ async def aeha_action(var, config, args): config[CONF_DATA], args, cg.std_vector.template(cg.uint8) ) cg.add(var.set_data(template_)) + + +# Haier +HaierData, HaierBinarySensor, HaierTrigger, HaierAction, HaierDumper = declare_protocol( + "Haier" +) +HaierAction = ns.class_("HaierAction", RemoteTransmitterActionBase) +HAIER_SCHEMA = cv.Schema( + { + cv.Required(CONF_CODE): cv.All([cv.hex_uint8_t], cv.Length(min=13, max=13)), + } +) + + +@register_binary_sensor("haier", HaierBinarySensor, HAIER_SCHEMA) +def haier_binary_sensor(var, config): + cg.add(var.set_code(config[CONF_CODE])) + + +@register_trigger("haier", HaierTrigger, HaierData) +def haier_trigger(var, config): + pass + + +@register_dumper("haier", HaierDumper) +def haier_dumper(var, config): + pass + + +@register_action("haier", HaierAction, HAIER_SCHEMA) +async def haier_action(var, config, args): + vec_ = cg.std_vector.template(cg.uint8) + template_ = await cg.templatable(config[CONF_CODE], args, vec_, vec_) + cg.add(var.set_code(template_)) diff --git a/esphome/components/remote_base/haier_protocol.cpp b/esphome/components/remote_base/haier_protocol.cpp new file mode 100644 index 0000000000..ec5cb5775c --- /dev/null +++ b/esphome/components/remote_base/haier_protocol.cpp @@ -0,0 +1,84 @@ +#include "haier_protocol.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace remote_base { + +static const char *const TAG = "remote.haier"; + +constexpr uint32_t HEADER_LOW_US = 3100; +constexpr uint32_t HEADER_HIGH_US = 4400; +constexpr uint32_t BIT_MARK_US = 540; +constexpr uint32_t BIT_ONE_SPACE_US = 1650; +constexpr uint32_t BIT_ZERO_SPACE_US = 580; +constexpr unsigned int HAIER_IR_PACKET_BIT_SIZE = 112; + +void HaierProtocol::encode_byte_(RemoteTransmitData *dst, uint8_t item) { + for (uint8_t mask = 1 << 7; mask != 0; mask >>= 1) { + if (item & mask) { + dst->space(BIT_ONE_SPACE_US); + } else { + dst->space(BIT_ZERO_SPACE_US); + } + dst->mark(BIT_MARK_US); + } +} + +void HaierProtocol::encode(RemoteTransmitData *dst, const HaierData &data) { + dst->set_carrier_frequency(38000); + dst->reserve(5 + ((data.data.size() + 1) * 2)); + dst->mark(HEADER_LOW_US); + dst->space(HEADER_LOW_US); + dst->mark(HEADER_LOW_US); + dst->space(HEADER_HIGH_US); + dst->mark(BIT_MARK_US); + uint8_t checksum = 0; + for (uint8_t item : data.data) { + this->encode_byte_(dst, item); + checksum += item; + } + this->encode_byte_(dst, checksum); +} + +optional HaierProtocol::decode(RemoteReceiveData src) { + if (!src.expect_item(HEADER_LOW_US, HEADER_LOW_US) || !src.expect_item(HEADER_LOW_US, HEADER_HIGH_US)) { + return {}; + } + if (!src.expect_mark(BIT_MARK_US)) { + return {}; + } + size_t size = src.size() - src.get_index() - 1; + if (size < HAIER_IR_PACKET_BIT_SIZE * 2) + return {}; + size = HAIER_IR_PACKET_BIT_SIZE * 2; + uint8_t checksum = 0; + HaierData out; + while (size > 0) { + uint8_t data = 0; + for (uint8_t mask = 0x80; mask != 0; mask >>= 1) { + if (src.expect_space(BIT_ONE_SPACE_US)) { + data |= mask; + } else if (!src.expect_space(BIT_ZERO_SPACE_US)) { + return {}; + } + if (!src.expect_mark(BIT_MARK_US)) { + return {}; + } + size -= 2; + } + if (size > 0) { + checksum += data; + out.data.push_back(data); + } else if (checksum != data) { + return {}; + } + } + return out; +} + +void HaierProtocol::dump(const HaierData &data) { + ESP_LOGI(TAG, "Received Haier: %s", format_hex_pretty(data.data).c_str()); +} + +} // namespace remote_base +} // namespace esphome diff --git a/esphome/components/remote_base/haier_protocol.h b/esphome/components/remote_base/haier_protocol.h new file mode 100644 index 0000000000..6a1c4bea72 --- /dev/null +++ b/esphome/components/remote_base/haier_protocol.h @@ -0,0 +1,40 @@ +#pragma once + +#include "remote_base.h" +#include + +namespace esphome { +namespace remote_base { + +struct HaierData { + std::vector data; + + bool operator==(const HaierData &rhs) const { return data == rhs.data; } +}; + +class HaierProtocol : public RemoteProtocol { + public: + void encode(RemoteTransmitData *dst, const HaierData &data) override; + optional decode(RemoteReceiveData src) override; + void dump(const HaierData &data) override; + + protected: + void encode_byte_(RemoteTransmitData *dst, uint8_t item); +}; + +DECLARE_REMOTE_PROTOCOL(Haier) + +template class HaierAction : public RemoteTransmitterActionBase { + public: + TEMPLATABLE_VALUE(std::vector, data) + + void set_code(const std::vector &code) { data_ = code; } + void encode(RemoteTransmitData *dst, Ts... x) override { + HaierData data{}; + data.data = this->data_.value(x...); + HaierProtocol().encode(dst, data); + } +}; + +} // namespace remote_base +} // namespace esphome diff --git a/tests/test1.yaml b/tests/test1.yaml index ea69343dbf..5110500e26 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -2622,6 +2622,11 @@ switch: 0x00, 0xFF, ] + - platform: template + name: Haier + turn_on_action: + remote_transmitter.transmit_haier: + code: [0xA6, 0xDA, 0x00, 0x00, 0x40, 0x40, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x05] - platform: template name: Living Room Lights id: livingroom_lights From aba3cd557abe4fd48531a7dc0c90aa3dfcb75722 Mon Sep 17 00:00:00 2001 From: Angel Nunez Mencias Date: Sun, 8 Oct 2023 23:01:26 +0200 Subject: [PATCH 0276/2101] add USE_SPI define (#5500) --- esphome/components/spi/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/spi/__init__.py b/esphome/components/spi/__init__.py index dc9d560874..00b23747d4 100644 --- a/esphome/components/spi/__init__.py +++ b/esphome/components/spi/__init__.py @@ -272,6 +272,7 @@ CONFIG_SCHEMA = cv.All( @coroutine_with_priority(1.0) async def to_code(configs): + cg.add_define("USE_SPI") cg.add_global(spi_ns.using) for spi in configs: var = cg.new_Pvariable(spi[CONF_ID]) From af62c2d9cf20c5d4fc68402e62ebf20884aa8519 Mon Sep 17 00:00:00 2001 From: Adam Goode Date: Sun, 8 Oct 2023 17:26:58 -0400 Subject: [PATCH 0277/2101] Implement sensor component for MMC5983 (#5361) --- CODEOWNERS | 1 + esphome/components/hmc5883l/sensor.py | 6 +- esphome/components/mmc5603/sensor.py | 6 +- esphome/components/mmc5983/__init__.py | 1 + esphome/components/mmc5983/mmc5983.cpp | 141 +++++++++++++++++++++++++ esphome/components/mmc5983/mmc5983.h | 28 +++++ esphome/components/mmc5983/sensor.py | 55 ++++++++++ esphome/components/qmc5883l/sensor.py | 6 +- esphome/const.py | 3 + tests/test1.yaml | 11 ++ 10 files changed, 249 insertions(+), 9 deletions(-) create mode 100644 esphome/components/mmc5983/__init__.py create mode 100644 esphome/components/mmc5983/mmc5983.cpp create mode 100644 esphome/components/mmc5983/mmc5983.h create mode 100644 esphome/components/mmc5983/sensor.py diff --git a/CODEOWNERS b/CODEOWNERS index ce19f14c05..d7cf7269ab 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -186,6 +186,7 @@ esphome/components/mitsubishi/* @RubyBailey esphome/components/mlx90393/* @functionpointer esphome/components/mlx90614/* @jesserockz esphome/components/mmc5603/* @benhoff +esphome/components/mmc5983/* @agoode esphome/components/modbus_controller/* @martgras esphome/components/modbus_controller/binary_sensor/* @martgras esphome/components/modbus_controller/number/* @martgras diff --git a/esphome/components/hmc5883l/sensor.py b/esphome/components/hmc5883l/sensor.py index 26e8e2b60c..7edd13965e 100644 --- a/esphome/components/hmc5883l/sensor.py +++ b/esphome/components/hmc5883l/sensor.py @@ -3,6 +3,9 @@ import esphome.config_validation as cv from esphome.components import i2c, sensor from esphome.const import ( CONF_ADDRESS, + CONF_FIELD_STRENGTH_X, + CONF_FIELD_STRENGTH_Y, + CONF_FIELD_STRENGTH_Z, CONF_ID, CONF_OVERSAMPLING, CONF_RANGE, @@ -18,9 +21,6 @@ DEPENDENCIES = ["i2c"] hmc5883l_ns = cg.esphome_ns.namespace("hmc5883l") -CONF_FIELD_STRENGTH_X = "field_strength_x" -CONF_FIELD_STRENGTH_Y = "field_strength_y" -CONF_FIELD_STRENGTH_Z = "field_strength_z" CONF_HEADING = "heading" HMC5883LComponent = hmc5883l_ns.class_( diff --git a/esphome/components/mmc5603/sensor.py b/esphome/components/mmc5603/sensor.py index 348a0e7dcc..db4e5cbf26 100644 --- a/esphome/components/mmc5603/sensor.py +++ b/esphome/components/mmc5603/sensor.py @@ -3,6 +3,9 @@ import esphome.config_validation as cv from esphome.components import i2c, sensor from esphome.const import ( CONF_ADDRESS, + CONF_FIELD_STRENGTH_X, + CONF_FIELD_STRENGTH_Y, + CONF_FIELD_STRENGTH_Z, CONF_ID, ICON_MAGNET, STATE_CLASS_MEASUREMENT, @@ -16,9 +19,6 @@ DEPENDENCIES = ["i2c"] mmc5603_ns = cg.esphome_ns.namespace("mmc5603") -CONF_FIELD_STRENGTH_X = "field_strength_x" -CONF_FIELD_STRENGTH_Y = "field_strength_y" -CONF_FIELD_STRENGTH_Z = "field_strength_z" CONF_HEADING = "heading" MMC5603Component = mmc5603_ns.class_( diff --git a/esphome/components/mmc5983/__init__.py b/esphome/components/mmc5983/__init__.py new file mode 100644 index 0000000000..c8db8c4300 --- /dev/null +++ b/esphome/components/mmc5983/__init__.py @@ -0,0 +1 @@ +CODEOWNERS = ["@agoode"] diff --git a/esphome/components/mmc5983/mmc5983.cpp b/esphome/components/mmc5983/mmc5983.cpp new file mode 100644 index 0000000000..5b045ae38b --- /dev/null +++ b/esphome/components/mmc5983/mmc5983.cpp @@ -0,0 +1,141 @@ +// See https://github.com/sparkfun/SparkFun_MMC5983MA_Magnetometer_Arduino_Library/tree/main +// for datasheets and an Arduino implementation. + +#include "mmc5983.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace mmc5983 { + +static const char *const TAG = "mmc5983"; + +namespace { +constexpr uint8_t IC0_ADDR = 0x09; +constexpr uint8_t IC1_ADDR = 0x0a; +constexpr uint8_t IC2_ADDR = 0x0b; +constexpr uint8_t IC3_ADDR = 0x0c; +constexpr uint8_t PRODUCT_ID_ADDR = 0x2f; + +float convert_data_to_millitesla(uint8_t data_17_10, uint8_t data_9_2, uint8_t data_1_0) { + int32_t counts = (data_17_10 << 10) | (data_9_2 << 2) | data_1_0; + counts -= 131072; // "Null Field Output" from datasheet. + + // Sensitivity is 16384 counts/gauss, which is 163840 counts/mT. + return counts / 163840.0f; +} +} // namespace + +void MMC5983Component::update() { + // Schedule a SET/RESET. This will recalibrate the sensor. + // We are supposed to be able to set this once, and have it automatically continue every reading, but + // this does not appear to work in continuous mode, even with En_prd_set turned on in Internal Control 2. + // Bit 5 = Auto_SR_en (automatic SET/RESET enable). + const uint8_t ic0_value = 0b10000; + i2c::ErrorCode err = this->write_register(IC0_ADDR, &ic0_value, 1); + if (err != i2c::ErrorCode::ERROR_OK) { + ESP_LOGW(TAG, "Writing Internal Control 0 failed with i2c error %d", err); + this->status_set_warning(); + } + + // Read out the data, 7 bytes starting from 0x00. + uint8_t data[7]; + err = this->read_register(0x00, data, sizeof(data)); + if (err != i2c::ErrorCode::ERROR_OK) { + ESP_LOGW(TAG, "Reading data failed with i2c error %d", err); + this->status_set_warning(); + return; + } + + // Unpack the data and publish to sensors. + // Data is in this format: + // data[0]: Xout[17:10] + // data[1]: Xout[9:2] + // data[2]: Yout[17:10] + // data[3]: Yout[9:2] + // data[4]: Zout[17:10] + // data[5]: Zout[9:2] + // data[6]: { Xout[1], Xout[0], Yout[1], Yout[0], Zout[1], Zout[0], 0, 0 } + if (this->x_sensor_) { + this->x_sensor_->publish_state(convert_data_to_millitesla(data[0], data[1], (data[6] & 0b11000000) >> 6)); + } + if (this->y_sensor_) { + this->y_sensor_->publish_state(convert_data_to_millitesla(data[2], data[3], (data[6] & 0b00110000) >> 4)); + } + if (this->z_sensor_) { + this->z_sensor_->publish_state(convert_data_to_millitesla(data[4], data[5], (data[6] & 0b00001100) >> 2)); + } +} + +void MMC5983Component::setup() { + ESP_LOGCONFIG(TAG, "Setting up MMC5983..."); + + // Verify product id. + const uint8_t mmc5983_product_id = 0x30; + uint8_t id; + i2c::ErrorCode err = this->read_register(PRODUCT_ID_ADDR, &id, 1); + if (err != i2c::ErrorCode::ERROR_OK) { + ESP_LOGE(TAG, "Reading product id failed with i2c error %d", err); + this->mark_failed(); + return; + } + if (id != mmc5983_product_id) { + ESP_LOGE(TAG, "Product id 0x%02x does not match expected value 0x%02x", id, mmc5983_product_id); + this->mark_failed(); + return; + } + + // Initialize Internal Control registers to 0. + // Internal Control 0. + const uint8_t zero = 0; + err = this->write_register(IC0_ADDR, &zero, 1); + if (err != i2c::ErrorCode::ERROR_OK) { + ESP_LOGE(TAG, "Initializing Internal Control 0 failed with i2c error %d", err); + this->mark_failed(); + return; + } + // Internal Control 1. + err = this->write_register(IC1_ADDR, &zero, 1); + if (err != i2c::ErrorCode::ERROR_OK) { + ESP_LOGE(TAG, "Initializing Internal Control 1 failed with i2c error %d", err); + this->mark_failed(); + return; + } + // Internal Control 2. + err = this->write_register(IC2_ADDR, &zero, 1); + if (err != i2c::ErrorCode::ERROR_OK) { + ESP_LOGE(TAG, "Initializing Internal Control 2 failed with i2c error %d", err); + this->mark_failed(); + return; + } + // Internal Control 3. + err = this->write_register(IC3_ADDR, &zero, 1); + if (err != i2c::ErrorCode::ERROR_OK) { + ESP_LOGE(TAG, "Initializing Internal Control 3 failed with i2c error %d", err); + this->mark_failed(); + return; + } + + // Enable continuous mode at 100 Hz, using Internal Control 2. + // Bit 3 = Cmm_en (continuous mode enable). + // Bit [2:0] = Cm_freq. 0b101 = 100 Hz, the fastest reading speed at Bandwidth=100 Hz. + const uint8_t ic2_value = 0b00001101; + err = this->write_register(IC2_ADDR, &ic2_value, 1); + if (err != i2c::ErrorCode::ERROR_OK) { + ESP_LOGE(TAG, "Writing Internal Control 2 failed with i2c error %d", err); + this->mark_failed(); + return; + } +} + +void MMC5983Component::dump_config() { + ESP_LOGD(TAG, "MMC5983:"); + LOG_I2C_DEVICE(this); + LOG_SENSOR(" ", "X", this->x_sensor_); + LOG_SENSOR(" ", "Y", this->y_sensor_); + 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 new file mode 100644 index 0000000000..d425418904 --- /dev/null +++ b/esphome/components/mmc5983/mmc5983.h @@ -0,0 +1,28 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/components/sensor/sensor.h" +#include "esphome/components/i2c/i2c.h" + +namespace esphome { +namespace mmc5983 { + +class MMC5983Component : public PollingComponent, public i2c::I2CDevice { + public: + 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; } + void set_z_sensor(sensor::Sensor *z_sensor) { z_sensor_ = z_sensor; } + + protected: + sensor::Sensor *x_sensor_{nullptr}; + sensor::Sensor *y_sensor_{nullptr}; + sensor::Sensor *z_sensor_{nullptr}; +}; + +} // namespace mmc5983 +} // namespace esphome diff --git a/esphome/components/mmc5983/sensor.py b/esphome/components/mmc5983/sensor.py new file mode 100644 index 0000000000..e3f4209cf9 --- /dev/null +++ b/esphome/components/mmc5983/sensor.py @@ -0,0 +1,55 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import i2c, sensor +from esphome.const import ( + CONF_FIELD_STRENGTH_X, + CONF_FIELD_STRENGTH_Y, + CONF_FIELD_STRENGTH_Z, + CONF_ID, + ICON_MAGNET, + STATE_CLASS_MEASUREMENT, + UNIT_MICROTESLA, +) + +DEPENDENCIES = ["i2c"] + +mmc5983_ns = cg.esphome_ns.namespace("mmc5983") +MMC5983Component = mmc5983_ns.class_( + "MMC5983Component", cg.PollingComponent, i2c.I2CDevice +) + +field_strength_schema = sensor.sensor_schema( + unit_of_measurement=UNIT_MICROTESLA, + icon=ICON_MAGNET, + accuracy_decimals=4, + state_class=STATE_CLASS_MEASUREMENT, +) + +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(MMC5983Component), + cv.Optional(CONF_FIELD_STRENGTH_X): field_strength_schema, + cv.Optional(CONF_FIELD_STRENGTH_Y): field_strength_schema, + cv.Optional(CONF_FIELD_STRENGTH_Z): field_strength_schema, + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x30)) +) + + +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 x_config := config.get(CONF_FIELD_STRENGTH_X): + sens = await sensor.new_sensor(x_config) + cg.add(var.set_x_sensor(sens)) + if y_config := config.get(CONF_FIELD_STRENGTH_Y): + sens = await sensor.new_sensor(y_config) + cg.add(var.set_y_sensor(sens)) + if z_config := config.get(CONF_FIELD_STRENGTH_Z): + sens = await sensor.new_sensor(z_config) + cg.add(var.set_z_sensor(sens)) diff --git a/esphome/components/qmc5883l/sensor.py b/esphome/components/qmc5883l/sensor.py index cce4d93843..b819fecfe1 100644 --- a/esphome/components/qmc5883l/sensor.py +++ b/esphome/components/qmc5883l/sensor.py @@ -3,6 +3,9 @@ import esphome.config_validation as cv from esphome.components import i2c, sensor from esphome.const import ( CONF_ADDRESS, + CONF_FIELD_STRENGTH_X, + CONF_FIELD_STRENGTH_Y, + CONF_FIELD_STRENGTH_Z, CONF_ID, CONF_OVERSAMPLING, CONF_RANGE, @@ -18,9 +21,6 @@ DEPENDENCIES = ["i2c"] qmc5883l_ns = cg.esphome_ns.namespace("qmc5883l") -CONF_FIELD_STRENGTH_X = "field_strength_x" -CONF_FIELD_STRENGTH_Y = "field_strength_y" -CONF_FIELD_STRENGTH_Z = "field_strength_z" CONF_HEADING = "heading" QMC5883LComponent = qmc5883l_ns.class_( diff --git a/esphome/const.py b/esphome/const.py index 75ed874cfd..01555c35ec 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -265,6 +265,9 @@ CONF_FAN_ONLY_MODE = "fan_only_mode" CONF_FAN_WITH_COOLING = "fan_with_cooling" CONF_FAN_WITH_HEATING = "fan_with_heating" CONF_FAST_CONNECT = "fast_connect" +CONF_FIELD_STRENGTH_X = "field_strength_x" +CONF_FIELD_STRENGTH_Y = "field_strength_y" +CONF_FIELD_STRENGTH_Z = "field_strength_z" CONF_FILE = "file" CONF_FILES = "files" CONF_FILTER = "filter" diff --git a/tests/test1.yaml b/tests/test1.yaml index 5110500e26..c504012481 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -1482,6 +1482,17 @@ sensor: name: "Loop Time" psram: name: "PSRAM Free" + - platform: mmc5983 + i2c_id: i2c_bus + field_strength_x: + name: "Magnet X" + id: magnet_x + field_strength_y: + name: "Magnet Y" + id: magnet_y + field_strength_z: + name: "Magnet Z" + id: magnet_z esp32_touch: setup_mode: false From e09c217fdeb533015d55b22bbb9b4065581f97e3 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 9 Oct 2023 11:13:12 +1300 Subject: [PATCH 0278/2101] Bump docker dependencies (#5501) --- docker/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index a0bb007641..99f15d64b2 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -26,8 +26,8 @@ RUN \ python3-venv=3.9.2-3 \ iputils-ping=3:20210202-1 \ git=1:2.30.2-1+deb11u2 \ - curl=7.74.0-1.3+deb11u7 \ - openssh-client=1:8.4p1-5+deb11u1 \ + curl=7.74.0-1.3+deb11u9 \ + openssh-client=1:8.4p1-5+deb11u2 \ python3-cffi=1.14.5-1 \ libcairo2=1.16.0-5 \ patch=2.7.6-7; \ From 412a866de8ccdeb19cfe38d8056fc41ac16afd04 Mon Sep 17 00:00:00 2001 From: Ilia Sotnikov Date: Mon, 9 Oct 2023 03:47:52 +0300 Subject: [PATCH 0279/2101] Move to Pillow 10.x (#5489) Co-authored-by: Franck Nijhof Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/animation/__init__.py | 4 ++-- esphome/components/font/__init__.py | 13 ++++--------- esphome/components/ili9xxx/display.py | 5 +++-- esphome/components/image/__init__.py | 6 +++++- requirements_optional.txt | 2 +- tests/test2.yaml | 5 +++++ 6 files changed, 20 insertions(+), 15 deletions(-) diff --git a/esphome/components/animation/__init__.py b/esphome/components/animation/__init__.py index 52e14f0a43..9151d6e56d 100644 --- a/esphome/components/animation/__init__.py +++ b/esphome/components/animation/__init__.py @@ -151,7 +151,7 @@ async def to_code(config): pos = 0 for frameIndex in range(frames): image.seek(frameIndex) - frame = image.convert("LA", dither=Image.NONE) + frame = image.convert("LA", dither=Image.Dither.NONE) if CONF_RESIZE in config: frame = frame.resize([width, height]) pixels = list(frame.getdata()) @@ -259,7 +259,7 @@ async def to_code(config): if transparent: alpha = image.split()[-1] has_alpha = alpha.getextrema()[0] < 0xFF - frame = image.convert("1", dither=Image.NONE) + frame = image.convert("1", dither=Image.Dither.NONE) if CONF_RESIZE in config: frame = frame.resize([width, height]) if transparent: diff --git a/esphome/components/font/__init__.py b/esphome/components/font/__init__.py index e6244d8d44..2bd6beeaeb 100644 --- a/esphome/components/font/__init__.py +++ b/esphome/components/font/__init__.py @@ -67,18 +67,13 @@ def validate_pillow_installed(value): except ImportError as err: raise cv.Invalid( "Please install the pillow python package to use this feature. " - '(pip install pillow">4.0.0,<10.0.0")' + '(pip install "pillow==10.0.1")' ) from err - if version.parse(PIL.__version__) < version.parse("4.0.0"): + if version.parse(PIL.__version__) != version.parse("10.0.1"): raise cv.Invalid( - "Please update your pillow installation to at least 4.0.x. " - '(pip install pillow">4.0.0,<10.0.0")' - ) - if version.parse(PIL.__version__) >= version.parse("10.0.0"): - raise cv.Invalid( - "Please downgrade your pillow installation to below 10.0.0. " - '(pip install pillow">4.0.0,<10.0.0")' + "Please update your pillow installation to 10.0.1. " + '(pip install "pillow==10.0.1")' ) return value diff --git a/esphome/components/ili9xxx/display.py b/esphome/components/ili9xxx/display.py index 1a18978d94..241f56e018 100644 --- a/esphome/components/ili9xxx/display.py +++ b/esphome/components/ili9xxx/display.py @@ -1,7 +1,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import core, pins -from esphome.components import display, spi +from esphome.components import display, spi, font from esphome.core import CORE, HexInt from esphome.const import ( CONF_COLOR_PALETTE, @@ -84,6 +84,7 @@ def _validate(config): CONFIG_SCHEMA = cv.All( + font.validate_pillow_installed, display.FULL_DISPLAY_SCHEMA.extend( { cv.GenerateID(): cv.declare_id(ili9XXXSPI), @@ -162,7 +163,7 @@ async def to_code(config): x = x + i.width # reduce the colors on combined image to 256. - converted = ref_image.convert("P", palette=Image.ADAPTIVE, colors=256) + converted = ref_image.convert("P", palette=Image.Palette.ADAPTIVE, colors=256) # if you want to verify how the images look use # ref_image.save("ref_in.png") # converted.save("ref_out.png") diff --git a/esphome/components/image/__init__.py b/esphome/components/image/__init__.py index aa402ee329..1b7c654b0b 100644 --- a/esphome/components/image/__init__.py +++ b/esphome/components/image/__init__.py @@ -255,7 +255,11 @@ async def to_code(config): transparent = config[CONF_USE_TRANSPARENCY] - dither = Image.NONE if config[CONF_DITHER] == "NONE" else Image.FLOYDSTEINBERG + dither = ( + Image.Dither.NONE + if config[CONF_DITHER] == "NONE" + else Image.Dither.FLOYDSTEINBERG + ) if config[CONF_TYPE] == "GRAYSCALE": image = image.convert("LA", dither=dither) pixels = list(image.getdata()) diff --git a/requirements_optional.txt b/requirements_optional.txt index 8bbf0a6809..236f5e3f13 100644 --- a/requirements_optional.txt +++ b/requirements_optional.txt @@ -1,3 +1,3 @@ -pillow>4.0.0,<10.0.0 +pillow==10.0.1 cairosvg>=2.2.0 cryptography>=2.0.0,<4 diff --git a/tests/test2.yaml b/tests/test2.yaml index fe577c2188..fe1ad91f8d 100644 --- a/tests/test2.yaml +++ b/tests/test2.yaml @@ -760,6 +760,11 @@ image: file: mdi:alert-outline type: BINARY +font: + - file: "gfonts://Roboto" + id: roboto + size: 20 + graph: - id: my_graph sensor: ha_hello_world_temperature From c65d78f568fcb9bdd7bea001e05601df941714ec Mon Sep 17 00:00:00 2001 From: Ilia Sotnikov Date: Mon, 9 Oct 2023 06:37:48 +0300 Subject: [PATCH 0280/2101] [Sprinkler] Initialize timers early to avoid crash (#5499) --- esphome/components/sprinkler/__init__.py | 16 +++++----------- esphome/components/sprinkler/sprinkler.cpp | 9 +++++++-- esphome/components/sprinkler/sprinkler.h | 4 ++-- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/esphome/components/sprinkler/__init__.py b/esphome/components/sprinkler/__init__.py index e1d855778a..02c80ad5a0 100644 --- a/esphome/components/sprinkler/__init__.py +++ b/esphome/components/sprinkler/__init__.py @@ -571,18 +571,12 @@ async def sprinkler_simple_action_to_code(config, action_id, template_arg, args) async def to_code(config): for sprinkler_controller in config: - var = cg.new_Pvariable(sprinkler_controller[CONF_ID]) - - if CONF_NAME in sprinkler_controller: - cg.add(var.set_name(sprinkler_controller[CONF_NAME])) + if len(sprinkler_controller[CONF_VALVES]) > 1: + name = sprinkler_controller[CONF_MAIN_SWITCH][CONF_NAME] else: - if len(sprinkler_controller[CONF_VALVES]) > 1: - name = sprinkler_controller[CONF_MAIN_SWITCH][CONF_NAME] - else: - name = sprinkler_controller[CONF_VALVES][0][CONF_VALVE_SWITCH][ - CONF_NAME - ] - cg.add(var.set_name(name)) + name = sprinkler_controller[CONF_VALVES][0][CONF_VALVE_SWITCH][CONF_NAME] + name = sprinkler_controller.get(CONF_NAME, name) + var = cg.new_Pvariable(sprinkler_controller[CONF_ID], name) await cg.register_component(var, sprinkler_controller) diff --git a/esphome/components/sprinkler/sprinkler.cpp b/esphome/components/sprinkler/sprinkler.cpp index 8afafcb5ce..6900c9461b 100644 --- a/esphome/components/sprinkler/sprinkler.cpp +++ b/esphome/components/sprinkler/sprinkler.cpp @@ -386,12 +386,17 @@ SprinklerValveOperator *SprinklerValveRunRequest::valve_operator() { return this SprinklerValveRunRequestOrigin SprinklerValveRunRequest::request_is_from() { return this->origin_; } -void Sprinkler::setup() { +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; 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)}); - this->all_valves_off_(true); } +void Sprinkler::setup() { this->all_valves_off_(true); } + void Sprinkler::loop() { for (auto &p : this->pump_) { p.loop(); diff --git a/esphome/components/sprinkler/sprinkler.h b/esphome/components/sprinkler/sprinkler.h index ae7554d3af..5311ae4c05 100644 --- a/esphome/components/sprinkler/sprinkler.h +++ b/esphome/components/sprinkler/sprinkler.h @@ -204,12 +204,12 @@ class SprinklerValveRunRequest { class Sprinkler : public Component { public: + Sprinkler(); + Sprinkler(const std::string &name); void setup() override; void loop() override; void dump_config() override; - void set_name(const std::string &name) { this->name_ = name; } - /// add a valve to the controller void add_valve(SprinklerControllerSwitch *valve_sw, SprinklerControllerSwitch *enable_sw = nullptr); From be7e167c638d301b6c6f244fb463e94fc95f736a Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 10 Oct 2023 09:41:28 +1300 Subject: [PATCH 0281/2101] Deep sleep is only available on esp32 and esp8266 (#5507) --- esphome/components/deep_sleep/__init__.py | 61 +++++++++++++---------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/esphome/components/deep_sleep/__init__.py b/esphome/components/deep_sleep/__init__.py index bb7084282c..fd7ef6fcce 100644 --- a/esphome/components/deep_sleep/__init__.py +++ b/esphome/components/deep_sleep/__init__.py @@ -14,6 +14,8 @@ from esphome.const import ( CONF_SLEEP_DURATION, CONF_TIME_ID, CONF_WAKEUP_PIN, + PLATFORM_ESP32, + PLATFORM_ESP8266, ) from esphome.components.esp32 import get_esp32_variant @@ -165,34 +167,39 @@ WAKEUP_CAUSES_SCHEMA = cv.Schema( } ) -CONFIG_SCHEMA = cv.Schema( - { - cv.GenerateID(): cv.declare_id(DeepSleepComponent), - cv.Optional(CONF_RUN_DURATION): cv.Any( - cv.All(cv.only_on_esp32, WAKEUP_CAUSES_SCHEMA), - cv.positive_time_period_milliseconds, - ), - cv.Optional(CONF_SLEEP_DURATION): cv.positive_time_period_milliseconds, - cv.Optional(CONF_WAKEUP_PIN): cv.All( - cv.only_on_esp32, pins.internal_gpio_input_pin_schema, validate_pin_number - ), - cv.Optional(CONF_WAKEUP_PIN_MODE): cv.All( - cv.only_on_esp32, cv.enum(WAKEUP_PIN_MODES), upper=True - ), - cv.Optional(CONF_ESP32_EXT1_WAKEUP): cv.All( - cv.only_on_esp32, - cv.Schema( - { - cv.Required(CONF_PINS): cv.ensure_list( - pins.internal_gpio_input_pin_schema, validate_pin_number - ), - cv.Required(CONF_MODE): cv.enum(EXT1_WAKEUP_MODES, upper=True), - } +CONFIG_SCHEMA = cv.All( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(DeepSleepComponent), + cv.Optional(CONF_RUN_DURATION): cv.Any( + cv.All(cv.only_on_esp32, WAKEUP_CAUSES_SCHEMA), + cv.positive_time_period_milliseconds, ), - ), - cv.Optional(CONF_TOUCH_WAKEUP): cv.All(cv.only_on_esp32, cv.boolean), - } -).extend(cv.COMPONENT_SCHEMA) + cv.Optional(CONF_SLEEP_DURATION): cv.positive_time_period_milliseconds, + cv.Optional(CONF_WAKEUP_PIN): cv.All( + cv.only_on_esp32, + pins.internal_gpio_input_pin_schema, + validate_pin_number, + ), + cv.Optional(CONF_WAKEUP_PIN_MODE): cv.All( + cv.only_on_esp32, cv.enum(WAKEUP_PIN_MODES), upper=True + ), + cv.Optional(CONF_ESP32_EXT1_WAKEUP): cv.All( + cv.only_on_esp32, + cv.Schema( + { + cv.Required(CONF_PINS): cv.ensure_list( + pins.internal_gpio_input_pin_schema, validate_pin_number + ), + cv.Required(CONF_MODE): cv.enum(EXT1_WAKEUP_MODES, upper=True), + } + ), + ), + cv.Optional(CONF_TOUCH_WAKEUP): cv.All(cv.only_on_esp32, cv.boolean), + } + ).extend(cv.COMPONENT_SCHEMA), + cv.only_on([PLATFORM_ESP32, PLATFORM_ESP8266]), +) async def to_code(config): From 46be886ca69c59d074dcbfdbaa07f64b5b7311d6 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 10 Oct 2023 10:54:15 +1300 Subject: [PATCH 0282/2101] Use platform consts (#5508) --- esphome/components/async_tcp/__init__.py | 8 +++++++- esphome/components/captive_portal/__init__.py | 10 ++++++++-- esphome/components/esp32/__init__.py | 3 ++- esphome/components/esp8266/__init__.py | 3 ++- esphome/components/host/__init__.py | 3 ++- esphome/components/i2c/__init__.py | 5 ++++- .../components/internal_temperature/sensor.py | 4 +++- esphome/components/mqtt/__init__.py | 5 ++++- esphome/components/rp2040/__init__.py | 3 ++- esphome/components/spi/__init__.py | 19 +++++++++++-------- esphome/components/web_server/__init__.py | 6 +++++- esphome/config_validation.py | 9 ++++++--- esphome/core/__init__.py | 18 ++++++++++++------ esphome/dashboard/dashboard.py | 12 ++++++------ 14 files changed, 74 insertions(+), 34 deletions(-) diff --git a/esphome/components/async_tcp/__init__.py b/esphome/components/async_tcp/__init__.py index fa74f7103f..0a69943a25 100644 --- a/esphome/components/async_tcp/__init__.py +++ b/esphome/components/async_tcp/__init__.py @@ -2,13 +2,19 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.core import CORE, coroutine_with_priority +from esphome.const import ( + PLATFORM_ESP32, + PLATFORM_ESP8266, + PLATFORM_BK72XX, + PLATFORM_RTL87XX, +) CODEOWNERS = ["@OttoWinter"] CONFIG_SCHEMA = cv.All( cv.Schema({}), cv.only_with_arduino, - cv.only_on(["esp32", "esp8266", "bk72xx", "rtl87xx"]), + cv.only_on([PLATFORM_ESP32, PLATFORM_ESP8266, PLATFORM_BK72XX, PLATFORM_RTL87XX]), ) diff --git a/esphome/components/captive_portal/__init__.py b/esphome/components/captive_portal/__init__.py index 6af741c6b3..a90ea14c4e 100644 --- a/esphome/components/captive_portal/__init__.py +++ b/esphome/components/captive_portal/__init__.py @@ -2,7 +2,13 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import web_server_base from esphome.components.web_server_base import CONF_WEB_SERVER_BASE_ID -from esphome.const import CONF_ID +from esphome.const import ( + CONF_ID, + PLATFORM_ESP32, + PLATFORM_ESP8266, + PLATFORM_BK72XX, + PLATFORM_RTL87XX, +) from esphome.core import coroutine_with_priority, CORE AUTO_LOAD = ["web_server_base"] @@ -21,7 +27,7 @@ CONFIG_SCHEMA = cv.All( ), } ).extend(cv.COMPONENT_SCHEMA), - cv.only_on(["esp32", "esp8266", "bk72xx", "rtl87xx"]), + cv.only_on([PLATFORM_ESP32, PLATFORM_ESP8266, PLATFORM_BK72XX, PLATFORM_RTL87XX]), ) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 0b067dc78f..cda02f80c2 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -25,6 +25,7 @@ from esphome.const import ( KEY_NAME, KEY_TARGET_FRAMEWORK, KEY_TARGET_PLATFORM, + PLATFORM_ESP32, TYPE_GIT, TYPE_LOCAL, __version__, @@ -62,7 +63,7 @@ AUTO_LOAD = ["preferences"] def set_core_data(config): CORE.data[KEY_ESP32] = {} - CORE.data[KEY_CORE][KEY_TARGET_PLATFORM] = "esp32" + CORE.data[KEY_CORE][KEY_TARGET_PLATFORM] = PLATFORM_ESP32 conf = config[CONF_FRAMEWORK] if conf[CONF_TYPE] == FRAMEWORK_ESP_IDF: CORE.data[KEY_CORE][KEY_TARGET_FRAMEWORK] = "esp-idf" diff --git a/esphome/components/esp8266/__init__.py b/esphome/components/esp8266/__init__.py index 412c2d903f..5336842b9d 100644 --- a/esphome/components/esp8266/__init__.py +++ b/esphome/components/esp8266/__init__.py @@ -11,6 +11,7 @@ from esphome.const import ( KEY_FRAMEWORK_VERSION, KEY_TARGET_FRAMEWORK, KEY_TARGET_PLATFORM, + PLATFORM_ESP8266, ) from esphome.core import CORE, coroutine_with_priority import esphome.config_validation as cv @@ -38,7 +39,7 @@ AUTO_LOAD = ["preferences"] def set_core_data(config): CORE.data[KEY_ESP8266] = {} - CORE.data[KEY_CORE][KEY_TARGET_PLATFORM] = "esp8266" + CORE.data[KEY_CORE][KEY_TARGET_PLATFORM] = PLATFORM_ESP8266 CORE.data[KEY_CORE][KEY_TARGET_FRAMEWORK] = "arduino" CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] = cv.Version.parse( config[CONF_FRAMEWORK][CONF_VERSION] diff --git a/esphome/components/host/__init__.py b/esphome/components/host/__init__.py index 46f763d255..14d2597866 100644 --- a/esphome/components/host/__init__.py +++ b/esphome/components/host/__init__.py @@ -3,6 +3,7 @@ from esphome.const import ( KEY_FRAMEWORK_VERSION, KEY_TARGET_FRAMEWORK, KEY_TARGET_PLATFORM, + PLATFORM_HOST, ) from esphome.core import CORE import esphome.config_validation as cv @@ -20,7 +21,7 @@ AUTO_LOAD = ["network"] def set_core_data(config): CORE.data[KEY_HOST] = {} - CORE.data[KEY_CORE][KEY_TARGET_PLATFORM] = "host" + CORE.data[KEY_CORE][KEY_TARGET_PLATFORM] = PLATFORM_HOST CORE.data[KEY_CORE][KEY_TARGET_FRAMEWORK] = "host" CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] = cv.Version(1, 0, 0) return config diff --git a/esphome/components/i2c/__init__.py b/esphome/components/i2c/__init__.py index e38cfd23fa..676190b0e5 100644 --- a/esphome/components/i2c/__init__.py +++ b/esphome/components/i2c/__init__.py @@ -12,6 +12,9 @@ from esphome.const import ( CONF_SDA, CONF_ADDRESS, CONF_I2C_ID, + PLATFORM_ESP32, + PLATFORM_ESP8266, + PLATFORM_RP2040, ) from esphome.core import coroutine_with_priority, CORE @@ -60,7 +63,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_SCAN, default=True): cv.boolean, } ).extend(cv.COMPONENT_SCHEMA), - cv.only_on(["esp32", "esp8266", "rp2040"]), + cv.only_on([PLATFORM_ESP32, PLATFORM_ESP8266, PLATFORM_RP2040]), ) diff --git a/esphome/components/internal_temperature/sensor.py b/esphome/components/internal_temperature/sensor.py index 8d462bd801..2daf816538 100644 --- a/esphome/components/internal_temperature/sensor.py +++ b/esphome/components/internal_temperature/sensor.py @@ -12,6 +12,8 @@ from esphome.const import ( ENTITY_CATEGORY_DIAGNOSTIC, KEY_CORE, KEY_FRAMEWORK_VERSION, + PLATFORM_ESP32, + PLATFORM_RP2040, ) from esphome.core import CORE @@ -49,7 +51,7 @@ CONFIG_SCHEMA = cv.All( state_class=STATE_CLASS_MEASUREMENT, entity_category=ENTITY_CATEGORY_DIAGNOSTIC, ).extend(cv.polling_component_schema("60s")), - cv.only_on(["esp32", "rp2040"]), + cv.only_on([PLATFORM_ESP32, PLATFORM_RP2040]), validate_config, ) diff --git a/esphome/components/mqtt/__init__.py b/esphome/components/mqtt/__init__.py index 10ae8ac40d..2d1a3dc5fd 100644 --- a/esphome/components/mqtt/__init__.py +++ b/esphome/components/mqtt/__init__.py @@ -43,6 +43,9 @@ from esphome.const import ( CONF_USE_ABBREVIATIONS, CONF_USERNAME, CONF_WILL_MESSAGE, + PLATFORM_ESP32, + PLATFORM_ESP8266, + PLATFORM_BK72XX, ) from esphome.core import coroutine_with_priority, CORE from esphome.components.esp32 import add_idf_sdkconfig_option @@ -250,7 +253,7 @@ CONFIG_SCHEMA = cv.All( } ), validate_config, - cv.only_on(["esp32", "esp8266", "bk72xx"]), + cv.only_on([PLATFORM_ESP32, PLATFORM_ESP8266, PLATFORM_BK72XX]), ) diff --git a/esphome/components/rp2040/__init__.py b/esphome/components/rp2040/__init__.py index 5d8608c44d..62f199b040 100644 --- a/esphome/components/rp2040/__init__.py +++ b/esphome/components/rp2040/__init__.py @@ -14,6 +14,7 @@ from esphome.const import ( KEY_FRAMEWORK_VERSION, KEY_TARGET_FRAMEWORK, KEY_TARGET_PLATFORM, + PLATFORM_RP2040, ) from esphome.core import CORE, coroutine_with_priority, EsphomeError from esphome.helpers import mkdir_p, write_file, copy_file_if_changed @@ -30,7 +31,7 @@ AUTO_LOAD = [] def set_core_data(config): CORE.data[KEY_RP2040] = {} - CORE.data[KEY_CORE][KEY_TARGET_PLATFORM] = "rp2040" + CORE.data[KEY_CORE][KEY_TARGET_PLATFORM] = PLATFORM_RP2040 CORE.data[KEY_CORE][KEY_TARGET_FRAMEWORK] = "arduino" CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] = cv.Version.parse( config[CONF_FRAMEWORK][CONF_VERSION] diff --git a/esphome/components/spi/__init__.py b/esphome/components/spi/__init__.py index 00b23747d4..d116641373 100644 --- a/esphome/components/spi/__init__.py +++ b/esphome/components/spi/__init__.py @@ -26,6 +26,9 @@ from esphome.const import ( KEY_TARGET_PLATFORM, KEY_VARIANT, CONF_DATA_RATE, + PLATFORM_ESP32, + PLATFORM_ESP8266, + PLATFORM_RP2040, ) from esphome.core import coroutine_with_priority, CORE @@ -102,9 +105,9 @@ def get_target_variant(): # The returned value is a list of lists of names def get_hw_interface_list(): target_platform = get_target_platform() - if target_platform == "esp8266": + if target_platform == PLATFORM_ESP8266: return [["spi", "hspi"]] - if target_platform == "esp32": + if target_platform == PLATFORM_ESP32: if get_target_variant() in [ VARIANT_ESP32C2, VARIANT_ESP32C3, @@ -113,7 +116,7 @@ def get_hw_interface_list(): ]: return [["spi", "spi2"]] return [["spi", "spi2"], ["spi3"]] - if target_platform == "rp2040": + if target_platform == PLATFORM_RP2040: return [["spi"], ["spi1"]] return [] @@ -150,17 +153,17 @@ def validate_hw_pins(spi, index=-1): sdi_pin_no = sdi_pin[CONF_NUMBER] target_platform = get_target_platform() - if target_platform == "esp8266": + if target_platform == PLATFORM_ESP8266: if clk_pin_no == 6: return sdo_pin_no in (-1, 8) and sdi_pin_no in (-1, 7) if clk_pin_no == 14: return sdo_pin_no in (-1, 13) and sdi_pin_no in (-1, 12) return False - if target_platform == "esp32": + if target_platform == PLATFORM_ESP32: return clk_pin_no >= 0 - if target_platform == "rp2040": + if target_platform == PLATFORM_RP2040: pin_set = ( list(filter(lambda s: clk_pin_no in s[CONF_CLK_PIN], RP_SPI_PINSETS))[0] if index == -1 @@ -236,7 +239,7 @@ def get_spi_interface(index): return ["SPI2_HOST", "SPI3_HOST"][index] # Arduino code follows platform = get_target_platform() - if platform == "rp2040": + if platform == PLATFORM_RP2040: return ["&SPI", "&SPI1"][index] if index == 0: return "&SPI" @@ -261,7 +264,7 @@ SPI_SCHEMA = cv.All( } ), cv.has_at_least_one_key(CONF_MISO_PIN, CONF_MOSI_PIN), - cv.only_on(["esp32", "esp8266", "rp2040"]), + cv.only_on([PLATFORM_ESP32, PLATFORM_ESP8266, PLATFORM_RP2040]), ) CONFIG_SCHEMA = cv.All( diff --git a/esphome/components/web_server/__init__.py b/esphome/components/web_server/__init__.py index 966c978836..b8698438e2 100644 --- a/esphome/components/web_server/__init__.py +++ b/esphome/components/web_server/__init__.py @@ -18,6 +18,10 @@ from esphome.const import ( CONF_LOG, CONF_VERSION, CONF_LOCAL, + PLATFORM_ESP32, + PLATFORM_ESP8266, + PLATFORM_BK72XX, + PLATFORM_RTL87XX, ) from esphome.core import CORE, coroutine_with_priority @@ -90,7 +94,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_LOCAL): cv.boolean, } ).extend(cv.COMPONENT_SCHEMA), - cv.only_on(["esp32", "esp8266", "bk72xx", "rtl87xx"]), + cv.only_on([PLATFORM_ESP32, PLATFORM_ESP8266, PLATFORM_BK72XX, PLATFORM_RTL87XX]), default_url, validate_local, validate_ota, diff --git a/esphome/config_validation.py b/esphome/config_validation.py index b3f24d9d17..46f3f6a7bd 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -51,6 +51,9 @@ from esphome.const import ( KEY_FRAMEWORK_VERSION, KEY_TARGET_FRAMEWORK, KEY_TARGET_PLATFORM, + PLATFORM_ESP32, + PLATFORM_ESP8266, + PLATFORM_RP2040, TYPE_GIT, TYPE_LOCAL, VALID_SUBSTITUTIONS_CHARACTERS, @@ -583,9 +586,9 @@ def only_with_framework(frameworks): return validator_ -only_on_esp32 = only_on("esp32") -only_on_esp8266 = only_on("esp8266") -only_on_rp2040 = only_on("rp2040") +only_on_esp32 = only_on(PLATFORM_ESP32) +only_on_esp8266 = only_on(PLATFORM_ESP8266) +only_on_rp2040 = only_on(PLATFORM_RP2040) only_with_arduino = only_with_framework("arduino") only_with_esp_idf = only_with_framework("esp-idf") diff --git a/esphome/core/__init__.py b/esphome/core/__init__.py index 4c99aff011..52c58cb54a 100644 --- a/esphome/core/__init__.py +++ b/esphome/core/__init__.py @@ -15,6 +15,12 @@ from esphome.const import ( KEY_CORE, KEY_TARGET_FRAMEWORK, KEY_TARGET_PLATFORM, + PLATFORM_ESP32, + PLATFORM_ESP8266, + PLATFORM_BK72XX, + PLATFORM_RTL87XX, + PLATFORM_RP2040, + PLATFORM_HOST, ) from esphome.coroutine import FakeAwaitable as _FakeAwaitable from esphome.coroutine import FakeEventLoop as _FakeEventLoop @@ -598,23 +604,23 @@ class EsphomeCore: @property def is_esp8266(self): - return self.target_platform == "esp8266" + return self.target_platform == PLATFORM_ESP8266 @property def is_esp32(self): - return self.target_platform == "esp32" + return self.target_platform == PLATFORM_ESP32 @property def is_rp2040(self): - return self.target_platform == "rp2040" + return self.target_platform == PLATFORM_RP2040 @property def is_bk72xx(self): - return self.target_platform == "bk72xx" + return self.target_platform == PLATFORM_BK72XX @property def is_rtl87xx(self): - return self.target_platform == "rtl87xx" + return self.target_platform == PLATFORM_RTL87XX @property def is_libretiny(self): @@ -622,7 +628,7 @@ class EsphomeCore: @property def is_host(self): - return self.target_platform == "host" + return self.target_platform == PLATFORM_HOST @property def target_framework(self): diff --git a/esphome/dashboard/dashboard.py b/esphome/dashboard/dashboard.py index 8049fb7f4c..ce8976cb0f 100644 --- a/esphome/dashboard/dashboard.py +++ b/esphome/dashboard/dashboard.py @@ -838,17 +838,17 @@ class BoardsRequestHandler(BaseHandler): from esphome.components.rtl87xx.boards import BOARDS as RTL87XX_BOARDS platform_to_boards = { - "esp32": ESP32_BOARDS, - "esp8266": ESP8266_BOARDS, - "rp2040": RP2040_BOARDS, - "bk72xx": BK72XX_BOARDS, - "rtl87xx": RTL87XX_BOARDS, + const.PLATFORM_ESP32: ESP32_BOARDS, + const.PLATFORM_ESP8266: ESP8266_BOARDS, + const.PLATFORM_RP2040: RP2040_BOARDS, + const.PLATFORM_BK72XX: BK72XX_BOARDS, + const.PLATFORM_RTL87XX: RTL87XX_BOARDS, } # filter all ESP32 variants by requested platform if platform.startswith("esp32"): boards = { k: v - for k, v in platform_to_boards["esp32"].items() + for k, v in platform_to_boards[const.PLATFORM_ESP32].items() if v[const.KEY_VARIANT] == platform.upper() } else: From 6b96089f024c44716b594dfe03007c634414df84 Mon Sep 17 00:00:00 2001 From: Oleg Tarasov Date: Tue, 10 Oct 2023 03:16:12 +0300 Subject: [PATCH 0283/2101] Fixed precision for Nextion sensor with float values (#5497) --- esphome/components/nextion/sensor/nextion_sensor.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/esphome/components/nextion/sensor/nextion_sensor.cpp b/esphome/components/nextion/sensor/nextion_sensor.cpp index 32bfccf9f8..566dd30acf 100644 --- a/esphome/components/nextion/sensor/nextion_sensor.cpp +++ b/esphome/components/nextion/sensor/nextion_sensor.cpp @@ -76,9 +76,15 @@ void NextionSensor::set_state(float state, bool publish, bool send_to_nextion) { } } + float published_state = state; if (this->wave_chan_id_ == UINT8_MAX) { if (publish) { - this->publish_state(state); + if (this->precision_ > 0) { + double to_multiply = pow(10, -this->precision_); + published_state = (float) (state * to_multiply); + } + + this->publish_state(published_state); } else { this->raw_state = state; this->state = state; @@ -87,7 +93,7 @@ void NextionSensor::set_state(float state, bool publish, bool send_to_nextion) { } this->update_component_settings(); - ESP_LOGN(TAG, "Wrote state for sensor \"%s\" state %lf", this->variable_name_.c_str(), state); + ESP_LOGN(TAG, "Wrote state for sensor \"%s\" state %lf", this->variable_name_.c_str(), published_state); } void NextionSensor::wave_update_() { From 511af5845ecb54c36c8b575013cbbd7e145fa3af Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 10 Oct 2023 19:52:42 +1300 Subject: [PATCH 0284/2101] Remote wake word support for voice assistant (#5229) --- esphome/components/api/api.proto | 19 +- esphome/components/api/api_connection.cpp | 13 +- esphome/components/api/api_connection.h | 2 +- esphome/components/api/api_pb2.cpp | 274 +++++++----- esphome/components/api/api_pb2.h | 26 +- esphome/components/api/api_server.cpp | 20 +- esphome/components/api/api_server.h | 11 +- .../microphone/i2s_audio_microphone.cpp | 9 +- .../i2s_audio/speaker/i2s_audio_speaker.cpp | 4 +- .../components/voice_assistant/__init__.py | 86 +++- .../voice_assistant/voice_assistant.cpp | 391 +++++++++++++++--- .../voice_assistant/voice_assistant.h | 97 ++++- tests/test4.yaml | 3 + 13 files changed, 744 insertions(+), 211 deletions(-) diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index 86685aa5e6..ec4a0f7cc9 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -1413,6 +1413,18 @@ message SubscribeVoiceAssistantRequest { bool subscribe = 1; } +enum VoiceAssistantRequestFlag { + VOICE_ASSISTANT_REQUEST_NONE = 0; + VOICE_ASSISTANT_REQUEST_USE_VAD = 1; + VOICE_ASSISTANT_REQUEST_USE_WAKE_WORD = 2; +} + +message VoiceAssistantAudioSettings { + uint32 noise_suppression_level = 1; + uint32 auto_gain = 2; + float volume_multiplier = 3; +} + message VoiceAssistantRequest { option (id) = 90; option (source) = SOURCE_SERVER; @@ -1420,7 +1432,8 @@ message VoiceAssistantRequest { bool start = 1; string conversation_id = 2; - bool use_vad = 3; + uint32 flags = 3; + VoiceAssistantAudioSettings audio_settings = 4; } message VoiceAssistantResponse { @@ -1442,6 +1455,10 @@ enum VoiceAssistantEvent { VOICE_ASSISTANT_INTENT_END = 6; VOICE_ASSISTANT_TTS_START = 7; VOICE_ASSISTANT_TTS_END = 8; + VOICE_ASSISTANT_WAKE_WORD_START = 9; + VOICE_ASSISTANT_WAKE_WORD_END = 10; + VOICE_ASSISTANT_STT_VAD_START = 11; + VOICE_ASSISTANT_STT_VAD_END = 12; } message VoiceAssistantEventData { diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index ceec53bb65..3172b71fa2 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -907,21 +907,22 @@ BluetoothConnectionsFreeResponse APIConnection::subscribe_bluetooth_connections_ #endif #ifdef USE_VOICE_ASSISTANT -bool APIConnection::request_voice_assistant(bool start, const std::string &conversation_id, bool use_vad) { +bool APIConnection::request_voice_assistant(const VoiceAssistantRequest &msg) { if (!this->voice_assistant_subscription_) return false; - VoiceAssistantRequest msg; - msg.start = start; - msg.conversation_id = conversation_id; - msg.use_vad = use_vad; + return this->send_voice_assistant_request(msg); } void APIConnection::on_voice_assistant_response(const VoiceAssistantResponse &msg) { if (voice_assistant::global_voice_assistant != nullptr) { + if (msg.error) { + voice_assistant::global_voice_assistant->failed_to_start(); + return; + } struct sockaddr_storage storage; socklen_t len = sizeof(storage); this->helper_->getpeername((struct sockaddr *) &storage, &len); - voice_assistant::global_voice_assistant->start(&storage, msg.port); + voice_assistant::global_voice_assistant->start_streaming(&storage, msg.port); } }; void APIConnection::on_voice_assistant_event_response(const VoiceAssistantEventResponse &msg) { diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index acc4578661..2a62c2faff 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -124,7 +124,7 @@ class APIConnection : public APIServerConnection { void subscribe_voice_assistant(const SubscribeVoiceAssistantRequest &msg) override { this->voice_assistant_subscription_ = msg.subscribe; } - bool request_voice_assistant(bool start, const std::string &conversation_id, bool use_vad); + bool request_voice_assistant(const VoiceAssistantRequest &msg); void on_voice_assistant_response(const VoiceAssistantResponse &msg) override; void on_voice_assistant_event_response(const VoiceAssistantEventResponse &msg) override; #endif diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index 6149a970ee..d0711aba7b 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -3,8 +3,6 @@ #include "api_pb2.h" #include "esphome/core/log.h" -#include - namespace esphome { namespace api { @@ -410,6 +408,20 @@ const char *proto_enum_to_string(enums::Bluet } #endif #ifdef HAS_PROTO_MESSAGE_DUMP +template<> const char *proto_enum_to_string(enums::VoiceAssistantRequestFlag value) { + switch (value) { + case enums::VOICE_ASSISTANT_REQUEST_NONE: + return "VOICE_ASSISTANT_REQUEST_NONE"; + case enums::VOICE_ASSISTANT_REQUEST_USE_VAD: + return "VOICE_ASSISTANT_REQUEST_USE_VAD"; + case enums::VOICE_ASSISTANT_REQUEST_USE_WAKE_WORD: + return "VOICE_ASSISTANT_REQUEST_USE_WAKE_WORD"; + default: + return "UNKNOWN"; + } +} +#endif +#ifdef HAS_PROTO_MESSAGE_DUMP template<> const char *proto_enum_to_string(enums::VoiceAssistantEvent value) { switch (value) { case enums::VOICE_ASSISTANT_ERROR: @@ -430,6 +442,14 @@ template<> const char *proto_enum_to_string(enums::V return "VOICE_ASSISTANT_TTS_START"; case enums::VOICE_ASSISTANT_TTS_END: return "VOICE_ASSISTANT_TTS_END"; + case enums::VOICE_ASSISTANT_WAKE_WORD_START: + return "VOICE_ASSISTANT_WAKE_WORD_START"; + case enums::VOICE_ASSISTANT_WAKE_WORD_END: + return "VOICE_ASSISTANT_WAKE_WORD_END"; + case enums::VOICE_ASSISTANT_STT_VAD_START: + return "VOICE_ASSISTANT_STT_VAD_START"; + case enums::VOICE_ASSISTANT_STT_VAD_END: + return "VOICE_ASSISTANT_STT_VAD_END"; default: return "UNKNOWN"; } @@ -524,12 +544,12 @@ void HelloRequest::dump_to(std::string &out) const { out.append("\n"); out.append(" api_version_major: "); - sprintf(buffer, "%" PRIu32, this->api_version_major); + sprintf(buffer, "%u", this->api_version_major); out.append(buffer); out.append("\n"); out.append(" api_version_minor: "); - sprintf(buffer, "%" PRIu32, this->api_version_minor); + sprintf(buffer, "%u", this->api_version_minor); out.append(buffer); out.append("\n"); out.append("}"); @@ -574,12 +594,12 @@ void HelloResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("HelloResponse {\n"); out.append(" api_version_major: "); - sprintf(buffer, "%" PRIu32, this->api_version_major); + sprintf(buffer, "%u", this->api_version_major); out.append(buffer); out.append("\n"); out.append(" api_version_minor: "); - sprintf(buffer, "%" PRIu32, this->api_version_minor); + sprintf(buffer, "%u", this->api_version_minor); out.append(buffer); out.append("\n"); @@ -785,17 +805,17 @@ void DeviceInfoResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" webserver_port: "); - sprintf(buffer, "%" PRIu32, this->webserver_port); + sprintf(buffer, "%u", this->webserver_port); out.append(buffer); out.append("\n"); out.append(" legacy_bluetooth_proxy_version: "); - sprintf(buffer, "%" PRIu32, this->legacy_bluetooth_proxy_version); + sprintf(buffer, "%u", this->legacy_bluetooth_proxy_version); out.append(buffer); out.append("\n"); out.append(" bluetooth_proxy_feature_flags: "); - sprintf(buffer, "%" PRIu32, this->bluetooth_proxy_feature_flags); + sprintf(buffer, "%u", this->bluetooth_proxy_feature_flags); out.append(buffer); out.append("\n"); @@ -808,7 +828,7 @@ void DeviceInfoResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" voice_assistant_version: "); - sprintf(buffer, "%" PRIu32, this->voice_assistant_version); + sprintf(buffer, "%u", this->voice_assistant_version); out.append(buffer); out.append("\n"); out.append("}"); @@ -900,7 +920,7 @@ void ListEntitiesBinarySensorResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -968,7 +988,7 @@ void BinarySensorStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("BinarySensorStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -1071,7 +1091,7 @@ void ListEntitiesCoverResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -1161,7 +1181,7 @@ void CoverStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("CoverStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -1244,7 +1264,7 @@ void CoverCommandRequest::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("CoverCommandRequest {\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -1364,7 +1384,7 @@ void ListEntitiesFanResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -1389,7 +1409,7 @@ void ListEntitiesFanResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" supported_speed_count: "); - sprintf(buffer, "%" PRId32, this->supported_speed_count); + sprintf(buffer, "%d", this->supported_speed_count); out.append(buffer); out.append("\n"); @@ -1456,7 +1476,7 @@ void FanStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("FanStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -1477,7 +1497,7 @@ void FanStateResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" speed_level: "); - sprintf(buffer, "%" PRId32, this->speed_level); + sprintf(buffer, "%d", this->speed_level); out.append(buffer); out.append("\n"); out.append("}"); @@ -1557,7 +1577,7 @@ void FanCommandRequest::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("FanCommandRequest {\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -1598,7 +1618,7 @@ void FanCommandRequest::dump_to(std::string &out) const { out.append("\n"); out.append(" speed_level: "); - sprintf(buffer, "%" PRId32, this->speed_level); + sprintf(buffer, "%d", this->speed_level); out.append(buffer); out.append("\n"); out.append("}"); @@ -1712,7 +1732,7 @@ void ListEntitiesLightResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -1866,7 +1886,7 @@ void LightStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("LightStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -2089,7 +2109,7 @@ void LightCommandRequest::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("LightCommandRequest {\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -2187,7 +2207,7 @@ void LightCommandRequest::dump_to(std::string &out) const { out.append("\n"); out.append(" transition_length: "); - sprintf(buffer, "%" PRIu32, this->transition_length); + sprintf(buffer, "%u", this->transition_length); out.append(buffer); out.append("\n"); @@ -2196,7 +2216,7 @@ void LightCommandRequest::dump_to(std::string &out) const { out.append("\n"); out.append(" flash_length: "); - sprintf(buffer, "%" PRIu32, this->flash_length); + sprintf(buffer, "%u", this->flash_length); out.append(buffer); out.append("\n"); @@ -2304,7 +2324,7 @@ void ListEntitiesSensorResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -2325,7 +2345,7 @@ void ListEntitiesSensorResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" accuracy_decimals: "); - sprintf(buffer, "%" PRId32, this->accuracy_decimals); + sprintf(buffer, "%d", this->accuracy_decimals); out.append(buffer); out.append("\n"); @@ -2389,7 +2409,7 @@ void SensorStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("SensorStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -2478,7 +2498,7 @@ void ListEntitiesSwitchResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -2541,7 +2561,7 @@ void SwitchStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("SwitchStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -2580,7 +2600,7 @@ void SwitchCommandRequest::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("SwitchCommandRequest {\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -2654,7 +2674,7 @@ void ListEntitiesTextSensorResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -2720,7 +2740,7 @@ void TextSensorStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("TextSensorStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -3027,7 +3047,7 @@ void GetTimeResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("GetTimeResponse {\n"); out.append(" epoch_seconds: "); - sprintf(buffer, "%" PRIu32, this->epoch_seconds); + sprintf(buffer, "%u", this->epoch_seconds); out.append(buffer); out.append("\n"); out.append("}"); @@ -3111,7 +3131,7 @@ void ListEntitiesServicesResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -3205,7 +3225,7 @@ void ExecuteServiceArgument::dump_to(std::string &out) const { out.append("\n"); out.append(" legacy_int: "); - sprintf(buffer, "%" PRId32, this->legacy_int); + sprintf(buffer, "%d", this->legacy_int); out.append(buffer); out.append("\n"); @@ -3219,7 +3239,7 @@ void ExecuteServiceArgument::dump_to(std::string &out) const { out.append("\n"); out.append(" int_: "); - sprintf(buffer, "%" PRId32, this->int_); + sprintf(buffer, "%d", this->int_); out.append(buffer); out.append("\n"); @@ -3231,7 +3251,7 @@ void ExecuteServiceArgument::dump_to(std::string &out) const { for (const auto &it : this->int_array) { out.append(" int_array: "); - sprintf(buffer, "%" PRId32, it); + sprintf(buffer, "%d", it); out.append(buffer); out.append("\n"); } @@ -3282,7 +3302,7 @@ void ExecuteServiceRequest::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("ExecuteServiceRequest {\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -3358,7 +3378,7 @@ void ListEntitiesCameraResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -3424,7 +3444,7 @@ void CameraImageResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("CameraImageResponse {\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -3616,7 +3636,7 @@ void ListEntitiesClimateResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -3804,7 +3824,7 @@ void ClimateStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("ClimateStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -3992,7 +4012,7 @@ void ClimateCommandRequest::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("ClimateCommandRequest {\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -4175,7 +4195,7 @@ void ListEntitiesNumberResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -4262,7 +4282,7 @@ void NumberStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("NumberStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -4300,7 +4320,7 @@ void NumberCommandRequest::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("NumberCommandRequest {\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -4382,7 +4402,7 @@ void ListEntitiesSelectResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -4454,7 +4474,7 @@ void SelectStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("SelectStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -4497,7 +4517,7 @@ void SelectCommandRequest::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("SelectCommandRequest {\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -4591,7 +4611,7 @@ void ListEntitiesLockResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -4662,7 +4682,7 @@ void LockStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("LockStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -4717,7 +4737,7 @@ void LockCommandRequest::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("LockCommandRequest {\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -4804,7 +4824,7 @@ void ListEntitiesButtonResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -4850,7 +4870,7 @@ void ButtonCommandRequest::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("ButtonCommandRequest {\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); out.append("}"); @@ -4925,7 +4945,7 @@ void ListEntitiesMediaPlayerResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -4994,7 +5014,7 @@ void MediaPlayerStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("MediaPlayerStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -5073,7 +5093,7 @@ void MediaPlayerCommandRequest::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("MediaPlayerCommandRequest {\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -5122,7 +5142,7 @@ void SubscribeBluetoothLEAdvertisementsRequest::dump_to(std::string &out) const __attribute__((unused)) char buffer[64]; out.append("SubscribeBluetoothLEAdvertisementsRequest {\n"); out.append(" flags: "); - sprintf(buffer, "%" PRIu32, this->flags); + sprintf(buffer, "%u", this->flags); out.append(buffer); out.append("\n"); out.append("}"); @@ -5169,7 +5189,7 @@ void BluetoothServiceData::dump_to(std::string &out) const { for (const auto &it : this->legacy_data) { out.append(" legacy_data: "); - sprintf(buffer, "%" PRIu32, it); + sprintf(buffer, "%u", it); out.append(buffer); out.append("\n"); } @@ -5249,7 +5269,7 @@ void BluetoothLEAdvertisementResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" rssi: "); - sprintf(buffer, "%" PRId32, this->rssi); + sprintf(buffer, "%d", this->rssi); out.append(buffer); out.append("\n"); @@ -5272,7 +5292,7 @@ void BluetoothLEAdvertisementResponse::dump_to(std::string &out) const { } out.append(" address_type: "); - sprintf(buffer, "%" PRIu32, this->address_type); + sprintf(buffer, "%u", this->address_type); out.append(buffer); out.append("\n"); out.append("}"); @@ -5322,12 +5342,12 @@ void BluetoothLERawAdvertisement::dump_to(std::string &out) const { out.append("\n"); out.append(" rssi: "); - sprintf(buffer, "%" PRId32, this->rssi); + sprintf(buffer, "%d", this->rssi); out.append(buffer); out.append("\n"); out.append(" address_type: "); - sprintf(buffer, "%" PRIu32, this->address_type); + sprintf(buffer, "%u", this->address_type); out.append(buffer); out.append("\n"); @@ -5410,7 +5430,7 @@ void BluetoothDeviceRequest::dump_to(std::string &out) const { out.append("\n"); out.append(" address_type: "); - sprintf(buffer, "%" PRIu32, this->address_type); + sprintf(buffer, "%u", this->address_type); out.append(buffer); out.append("\n"); out.append("}"); @@ -5458,12 +5478,12 @@ void BluetoothDeviceConnectionResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" mtu: "); - sprintf(buffer, "%" PRIu32, this->mtu); + sprintf(buffer, "%u", this->mtu); out.append(buffer); out.append("\n"); out.append(" error: "); - sprintf(buffer, "%" PRId32, this->error); + sprintf(buffer, "%d", this->error); out.append(buffer); out.append("\n"); out.append("}"); @@ -5523,7 +5543,7 @@ void BluetoothGATTDescriptor::dump_to(std::string &out) const { } out.append(" handle: "); - sprintf(buffer, "%" PRIu32, this->handle); + sprintf(buffer, "%u", this->handle); out.append(buffer); out.append("\n"); out.append("}"); @@ -5579,12 +5599,12 @@ void BluetoothGATTCharacteristic::dump_to(std::string &out) const { } out.append(" handle: "); - sprintf(buffer, "%" PRIu32, this->handle); + sprintf(buffer, "%u", this->handle); out.append(buffer); out.append("\n"); out.append(" properties: "); - sprintf(buffer, "%" PRIu32, this->properties); + sprintf(buffer, "%u", this->properties); out.append(buffer); out.append("\n"); @@ -5641,7 +5661,7 @@ void BluetoothGATTService::dump_to(std::string &out) const { } out.append(" handle: "); - sprintf(buffer, "%" PRIu32, this->handle); + sprintf(buffer, "%u", this->handle); out.append(buffer); out.append("\n"); @@ -5748,7 +5768,7 @@ void BluetoothGATTReadRequest::dump_to(std::string &out) const { out.append("\n"); out.append(" handle: "); - sprintf(buffer, "%" PRIu32, this->handle); + sprintf(buffer, "%u", this->handle); out.append(buffer); out.append("\n"); out.append("}"); @@ -5793,7 +5813,7 @@ void BluetoothGATTReadResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" handle: "); - sprintf(buffer, "%" PRIu32, this->handle); + sprintf(buffer, "%u", this->handle); out.append(buffer); out.append("\n"); @@ -5847,7 +5867,7 @@ void BluetoothGATTWriteRequest::dump_to(std::string &out) const { out.append("\n"); out.append(" handle: "); - sprintf(buffer, "%" PRIu32, this->handle); + sprintf(buffer, "%u", this->handle); out.append(buffer); out.append("\n"); @@ -5889,7 +5909,7 @@ void BluetoothGATTReadDescriptorRequest::dump_to(std::string &out) const { out.append("\n"); out.append(" handle: "); - sprintf(buffer, "%" PRIu32, this->handle); + sprintf(buffer, "%u", this->handle); out.append(buffer); out.append("\n"); out.append("}"); @@ -5934,7 +5954,7 @@ void BluetoothGATTWriteDescriptorRequest::dump_to(std::string &out) const { out.append("\n"); out.append(" handle: "); - sprintf(buffer, "%" PRIu32, this->handle); + sprintf(buffer, "%u", this->handle); out.append(buffer); out.append("\n"); @@ -5977,7 +5997,7 @@ void BluetoothGATTNotifyRequest::dump_to(std::string &out) const { out.append("\n"); out.append(" handle: "); - sprintf(buffer, "%" PRIu32, this->handle); + sprintf(buffer, "%u", this->handle); out.append(buffer); out.append("\n"); @@ -6026,7 +6046,7 @@ void BluetoothGATTNotifyDataResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" handle: "); - sprintf(buffer, "%" PRIu32, this->handle); + sprintf(buffer, "%u", this->handle); out.append(buffer); out.append("\n"); @@ -6065,12 +6085,12 @@ void BluetoothConnectionsFreeResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("BluetoothConnectionsFreeResponse {\n"); out.append(" free: "); - sprintf(buffer, "%" PRIu32, this->free); + sprintf(buffer, "%u", this->free); out.append(buffer); out.append("\n"); out.append(" limit: "); - sprintf(buffer, "%" PRIu32, this->limit); + sprintf(buffer, "%u", this->limit); out.append(buffer); out.append("\n"); out.append("}"); @@ -6109,12 +6129,12 @@ void BluetoothGATTErrorResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" handle: "); - sprintf(buffer, "%" PRIu32, this->handle); + sprintf(buffer, "%u", this->handle); out.append(buffer); out.append("\n"); out.append(" error: "); - sprintf(buffer, "%" PRId32, this->error); + sprintf(buffer, "%d", this->error); out.append(buffer); out.append("\n"); out.append("}"); @@ -6148,7 +6168,7 @@ void BluetoothGATTWriteResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" handle: "); - sprintf(buffer, "%" PRIu32, this->handle); + sprintf(buffer, "%u", this->handle); out.append(buffer); out.append("\n"); out.append("}"); @@ -6182,7 +6202,7 @@ void BluetoothGATTNotifyResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" handle: "); - sprintf(buffer, "%" PRIu32, this->handle); + sprintf(buffer, "%u", this->handle); out.append(buffer); out.append("\n"); out.append("}"); @@ -6225,7 +6245,7 @@ void BluetoothDevicePairingResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" error: "); - sprintf(buffer, "%" PRId32, this->error); + sprintf(buffer, "%d", this->error); out.append(buffer); out.append("\n"); out.append("}"); @@ -6268,7 +6288,7 @@ void BluetoothDeviceUnpairingResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" error: "); - sprintf(buffer, "%" PRId32, this->error); + sprintf(buffer, "%d", this->error); out.append(buffer); out.append("\n"); out.append("}"); @@ -6317,7 +6337,7 @@ void BluetoothDeviceClearCacheResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" error: "); - sprintf(buffer, "%" PRId32, this->error); + sprintf(buffer, "%d", this->error); out.append(buffer); out.append("\n"); out.append("}"); @@ -6344,6 +6364,56 @@ void SubscribeVoiceAssistantRequest::dump_to(std::string &out) const { out.append("}"); } #endif +bool VoiceAssistantAudioSettings::decode_varint(uint32_t field_id, ProtoVarInt value) { + switch (field_id) { + case 1: { + this->noise_suppression_level = value.as_uint32(); + return true; + } + case 2: { + this->auto_gain = value.as_uint32(); + return true; + } + default: + return false; + } +} +bool VoiceAssistantAudioSettings::decode_32bit(uint32_t field_id, Proto32Bit value) { + switch (field_id) { + case 3: { + this->volume_multiplier = value.as_float(); + return true; + } + default: + return false; + } +} +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); +} +#ifdef HAS_PROTO_MESSAGE_DUMP +void VoiceAssistantAudioSettings::dump_to(std::string &out) const { + __attribute__((unused)) char buffer[64]; + out.append("VoiceAssistantAudioSettings {\n"); + out.append(" noise_suppression_level: "); + sprintf(buffer, "%u", this->noise_suppression_level); + out.append(buffer); + out.append("\n"); + + out.append(" auto_gain: "); + sprintf(buffer, "%u", this->auto_gain); + out.append(buffer); + out.append("\n"); + + out.append(" volume_multiplier: "); + sprintf(buffer, "%g", this->volume_multiplier); + out.append(buffer); + out.append("\n"); + out.append("}"); +} +#endif bool VoiceAssistantRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { case 1: { @@ -6351,7 +6421,7 @@ bool VoiceAssistantRequest::decode_varint(uint32_t field_id, ProtoVarInt value) return true; } case 3: { - this->use_vad = value.as_bool(); + this->flags = value.as_uint32(); return true; } default: @@ -6364,6 +6434,10 @@ bool VoiceAssistantRequest::decode_length(uint32_t field_id, ProtoLengthDelimite this->conversation_id = value.as_string(); return true; } + case 4: { + this->audio_settings = value.as_message(); + return true; + } default: return false; } @@ -6371,7 +6445,8 @@ bool VoiceAssistantRequest::decode_length(uint32_t field_id, ProtoLengthDelimite void VoiceAssistantRequest::encode(ProtoWriteBuffer buffer) const { buffer.encode_bool(1, this->start); buffer.encode_string(2, this->conversation_id); - buffer.encode_bool(3, this->use_vad); + buffer.encode_uint32(3, this->flags); + buffer.encode_message(4, this->audio_settings); } #ifdef HAS_PROTO_MESSAGE_DUMP void VoiceAssistantRequest::dump_to(std::string &out) const { @@ -6385,8 +6460,13 @@ void VoiceAssistantRequest::dump_to(std::string &out) const { out.append("'").append(this->conversation_id).append("'"); out.append("\n"); - out.append(" use_vad: "); - out.append(YESNO(this->use_vad)); + out.append(" flags: "); + sprintf(buffer, "%u", this->flags); + out.append(buffer); + out.append("\n"); + + out.append(" audio_settings: "); + this->audio_settings.dump_to(out); out.append("\n"); out.append("}"); } @@ -6414,7 +6494,7 @@ void VoiceAssistantResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("VoiceAssistantResponse {\n"); out.append(" port: "); - sprintf(buffer, "%" PRIu32, this->port); + sprintf(buffer, "%u", this->port); out.append(buffer); out.append("\n"); @@ -6577,7 +6657,7 @@ void ListEntitiesAlarmControlPanelResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -6602,7 +6682,7 @@ void ListEntitiesAlarmControlPanelResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" supported_features: "); - sprintf(buffer, "%" PRIu32, this->supported_features); + sprintf(buffer, "%u", this->supported_features); out.append(buffer); out.append("\n"); @@ -6645,7 +6725,7 @@ void AlarmControlPanelStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("AlarmControlPanelStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); @@ -6695,7 +6775,7 @@ void AlarmControlPanelCommandRequest::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("AlarmControlPanelCommandRequest {\n"); out.append(" key: "); - sprintf(buffer, "%" PRIu32, this->key); + sprintf(buffer, "%u", this->key); out.append(buffer); out.append("\n"); diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index 627165953d..a4826f09d2 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -165,6 +165,11 @@ enum BluetoothDeviceRequestType : uint32_t { BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITHOUT_CACHE = 5, BLUETOOTH_DEVICE_REQUEST_TYPE_CLEAR_CACHE = 6, }; +enum VoiceAssistantRequestFlag : uint32_t { + VOICE_ASSISTANT_REQUEST_NONE = 0, + VOICE_ASSISTANT_REQUEST_USE_VAD = 1, + VOICE_ASSISTANT_REQUEST_USE_WAKE_WORD = 2, +}; enum VoiceAssistantEvent : uint32_t { VOICE_ASSISTANT_ERROR = 0, VOICE_ASSISTANT_RUN_START = 1, @@ -175,6 +180,10 @@ enum VoiceAssistantEvent : uint32_t { VOICE_ASSISTANT_INTENT_END = 6, VOICE_ASSISTANT_TTS_START = 7, VOICE_ASSISTANT_TTS_END = 8, + VOICE_ASSISTANT_WAKE_WORD_START = 9, + VOICE_ASSISTANT_WAKE_WORD_END = 10, + VOICE_ASSISTANT_STT_VAD_START = 11, + VOICE_ASSISTANT_STT_VAD_END = 12, }; enum AlarmControlPanelState : uint32_t { ALARM_STATE_DISARMED = 0, @@ -1651,11 +1660,26 @@ class SubscribeVoiceAssistantRequest : public ProtoMessage { protected: bool decode_varint(uint32_t field_id, ProtoVarInt value) override; }; +class VoiceAssistantAudioSettings : public ProtoMessage { + public: + uint32_t noise_suppression_level{0}; + uint32_t auto_gain{0}; + float volume_multiplier{0.0f}; + void encode(ProtoWriteBuffer buffer) const override; +#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_varint(uint32_t field_id, ProtoVarInt value) override; +}; class VoiceAssistantRequest : public ProtoMessage { public: bool start{false}; std::string conversation_id{}; - bool use_vad{false}; + uint32_t flags{0}; + VoiceAssistantAudioSettings audio_settings{}; void encode(ProtoWriteBuffer buffer) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; diff --git a/esphome/components/api/api_server.cpp b/esphome/components/api/api_server.cpp index f70d45ecd0..54266ff0f0 100644 --- a/esphome/components/api/api_server.cpp +++ b/esphome/components/api/api_server.cpp @@ -1,13 +1,13 @@ #include "api_server.h" +#include #include "api_connection.h" +#include "esphome/components/network/util.h" #include "esphome/core/application.h" #include "esphome/core/defines.h" +#include "esphome/core/hal.h" #include "esphome/core/log.h" #include "esphome/core/util.h" #include "esphome/core/version.h" -#include "esphome/core/hal.h" -#include "esphome/components/network/util.h" -#include #ifdef USE_LOGGER #include "esphome/components/logger/logger.h" @@ -323,16 +323,24 @@ void APIServer::on_shutdown() { } #ifdef USE_VOICE_ASSISTANT -bool APIServer::start_voice_assistant(const std::string &conversation_id, bool use_vad) { +bool APIServer::start_voice_assistant(const std::string &conversation_id, uint32_t flags, + const api::VoiceAssistantAudioSettings &audio_settings) { + VoiceAssistantRequest msg; + msg.start = true; + msg.conversation_id = conversation_id; + msg.flags = flags; + msg.audio_settings = audio_settings; for (auto &c : this->clients_) { - if (c->request_voice_assistant(true, conversation_id, use_vad)) + if (c->request_voice_assistant(msg)) return true; } return false; } void APIServer::stop_voice_assistant() { + VoiceAssistantRequest msg; + msg.start = false; for (auto &c : this->clients_) { - if (c->request_voice_assistant(false, "", false)) + if (c->request_voice_assistant(msg)) return; } } diff --git a/esphome/components/api/api_server.h b/esphome/components/api/api_server.h index 9b40a5ef02..a4454d4b84 100644 --- a/esphome/components/api/api_server.h +++ b/esphome/components/api/api_server.h @@ -1,16 +1,16 @@ #pragma once +#include "api_noise_context.h" +#include "api_pb2.h" +#include "api_pb2_service.h" +#include "esphome/components/socket/socket.h" #include "esphome/core/component.h" #include "esphome/core/controller.h" #include "esphome/core/defines.h" #include "esphome/core/log.h" -#include "esphome/components/socket/socket.h" -#include "api_pb2.h" -#include "api_pb2_service.h" #include "list_entities.h" #include "subscribe_state.h" #include "user_services.h" -#include "api_noise_context.h" #include @@ -81,7 +81,8 @@ class APIServer : public Component, public Controller { #endif #ifdef USE_VOICE_ASSISTANT - bool start_voice_assistant(const std::string &conversation_id, bool use_vad); + bool start_voice_assistant(const std::string &conversation_id, uint32_t flags, + const api::VoiceAssistantAudioSettings &audio_settings); void stop_voice_assistant(); #endif diff --git a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp index cf0628d638..44c73eb8fd 100644 --- a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +++ b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp @@ -66,8 +66,9 @@ void I2SAudioMicrophone::start_() { i2s_set_adc_mode(ADC_UNIT_1, this->adc_channel_); i2s_adc_enable(this->parent_->get_port()); - } else { + } else #endif + { if (this->pdm_) config.mode = (i2s_mode_t) (config.mode | I2S_MODE_PDM); @@ -77,9 +78,7 @@ void I2SAudioMicrophone::start_() { pin_config.data_in_num = this->din_pin_; i2s_set_pin(this->parent_->get_port(), &pin_config); -#if SOC_I2S_SUPPORTS_ADC } -#endif this->state_ = microphone::STATE_RUNNING; this->high_freq_.start(); } @@ -110,6 +109,10 @@ size_t I2SAudioMicrophone::read(int16_t *buf, size_t len) { this->status_set_warning(); return 0; } + if (bytes_read == 0) { + this->status_set_warning(); + return 0; + } this->status_clear_warning(); if (this->bits_per_sample_ == I2S_BITS_PER_SAMPLE_16BIT) { return bytes_read; diff --git a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp index 43bc005136..a0934e3844 100644 --- a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +++ b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp @@ -158,10 +158,10 @@ void I2SAudioSpeaker::watch_() { this->status_clear_warning(); break; case TaskEventType::STOPPED: - this->parent_->unlock(); this->state_ = speaker::STATE_STOPPED; vTaskDelete(this->player_task_handle_); this->player_task_handle_ = nullptr; + this->parent_->unlock(); break; case TaskEventType::WARNING: ESP_LOGW(TAG, "Error writing to I2S: %s", esp_err_to_name(event.err)); @@ -177,9 +177,9 @@ void I2SAudioSpeaker::loop() { this->start_(); break; case speaker::STATE_RUNNING: + case speaker::STATE_STOPPING: this->watch_(); break; - case speaker::STATE_STOPPING: case speaker::STATE_STOPPED: break; } diff --git a/esphome/components/voice_assistant/__init__.py b/esphome/components/voice_assistant/__init__.py index 55d995be88..14176ad7cf 100644 --- a/esphome/components/voice_assistant/__init__.py +++ b/esphome/components/voice_assistant/__init__.py @@ -19,11 +19,18 @@ CODEOWNERS = ["@jesserockz"] CONF_SILENCE_DETECTION = "silence_detection" CONF_ON_LISTENING = "on_listening" CONF_ON_START = "on_start" +CONF_ON_WAKE_WORD_DETECTED = "on_wake_word_detected" CONF_ON_STT_END = "on_stt_end" CONF_ON_TTS_START = "on_tts_start" CONF_ON_TTS_END = "on_tts_end" CONF_ON_END = "on_end" CONF_ON_ERROR = "on_error" +CONF_USE_WAKE_WORD = "use_wake_word" +CONF_VAD_THRESHOLD = "vad_threshold" + +CONF_NOISE_SUPPRESSION_LEVEL = "noise_suppression_level" +CONF_AUTO_GAIN = "auto_gain" +CONF_VOLUME_MULTIPLIER = "volume_multiplier" voice_assistant_ns = cg.esphome_ns.namespace("voice_assistant") @@ -42,23 +49,40 @@ IsRunningCondition = voice_assistant_ns.class_( "IsRunningCondition", automation.Condition, cg.Parented.template(VoiceAssistant) ) - -CONFIG_SCHEMA = cv.Schema( - { - cv.GenerateID(): cv.declare_id(VoiceAssistant), - cv.GenerateID(CONF_MICROPHONE): cv.use_id(microphone.Microphone), - cv.Exclusive(CONF_SPEAKER, "output"): cv.use_id(speaker.Speaker), - cv.Exclusive(CONF_MEDIA_PLAYER, "output"): cv.use_id(media_player.MediaPlayer), - cv.Optional(CONF_SILENCE_DETECTION, default=True): cv.boolean, - cv.Optional(CONF_ON_LISTENING): automation.validate_automation(single=True), - cv.Optional(CONF_ON_START): automation.validate_automation(single=True), - cv.Optional(CONF_ON_STT_END): automation.validate_automation(single=True), - cv.Optional(CONF_ON_TTS_START): automation.validate_automation(single=True), - cv.Optional(CONF_ON_TTS_END): automation.validate_automation(single=True), - cv.Optional(CONF_ON_END): automation.validate_automation(single=True), - cv.Optional(CONF_ON_ERROR): automation.validate_automation(single=True), - } -).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = cv.All( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(VoiceAssistant), + cv.GenerateID(CONF_MICROPHONE): cv.use_id(microphone.Microphone), + cv.Exclusive(CONF_SPEAKER, "output"): cv.use_id(speaker.Speaker), + cv.Exclusive(CONF_MEDIA_PLAYER, "output"): cv.use_id( + media_player.MediaPlayer + ), + cv.Optional(CONF_USE_WAKE_WORD, default=False): cv.boolean, + cv.Optional(CONF_VAD_THRESHOLD): cv.All( + cv.requires_component("esp_adf"), cv.only_with_esp_idf, cv.uint8_t + ), + cv.Optional(CONF_NOISE_SUPPRESSION_LEVEL, default=0): cv.int_range(0, 4), + cv.Optional(CONF_AUTO_GAIN, default="0dBFS"): cv.All( + cv.float_with_unit("decibel full scale", "(dBFS|dbfs|DBFS)"), + cv.int_range(0, 31), + ), + cv.Optional(CONF_VOLUME_MULTIPLIER, default=1.0): cv.float_range( + min=0.0, min_included=False + ), + cv.Optional(CONF_ON_LISTENING): automation.validate_automation(single=True), + cv.Optional(CONF_ON_START): automation.validate_automation(single=True), + cv.Optional(CONF_ON_WAKE_WORD_DETECTED): automation.validate_automation( + single=True + ), + cv.Optional(CONF_ON_STT_END): automation.validate_automation(single=True), + cv.Optional(CONF_ON_TTS_START): automation.validate_automation(single=True), + cv.Optional(CONF_ON_TTS_END): automation.validate_automation(single=True), + cv.Optional(CONF_ON_END): automation.validate_automation(single=True), + cv.Optional(CONF_ON_ERROR): automation.validate_automation(single=True), + } + ).extend(cv.COMPONENT_SCHEMA), +) async def to_code(config): @@ -76,7 +100,14 @@ async def to_code(config): mp = await cg.get_variable(config[CONF_MEDIA_PLAYER]) cg.add(var.set_media_player(mp)) - cg.add(var.set_silence_detection(config[CONF_SILENCE_DETECTION])) + cg.add(var.set_use_wake_word(config[CONF_USE_WAKE_WORD])) + + if (vad_threshold := config.get(CONF_VAD_THRESHOLD)) is not None: + cg.add(var.set_vad_threshold(vad_threshold)) + + cg.add(var.set_noise_suppression_level(config[CONF_NOISE_SUPPRESSION_LEVEL])) + cg.add(var.set_auto_gain(config[CONF_AUTO_GAIN])) + cg.add(var.set_volume_multiplier(config[CONF_VOLUME_MULTIPLIER])) if CONF_ON_LISTENING in config: await automation.build_automation( @@ -88,6 +119,13 @@ async def to_code(config): var.get_start_trigger(), [], config[CONF_ON_START] ) + if CONF_ON_WAKE_WORD_DETECTED in config: + await automation.build_automation( + var.get_wake_word_detected_trigger(), + [], + config[CONF_ON_WAKE_WORD_DETECTED], + ) + if CONF_ON_STT_END in config: await automation.build_automation( var.get_stt_end_trigger(), [(cg.std_string, "x")], config[CONF_ON_STT_END] @@ -128,10 +166,20 @@ VOICE_ASSISTANT_ACTION_SCHEMA = cv.Schema({cv.GenerateID(): cv.use_id(VoiceAssis StartContinuousAction, VOICE_ASSISTANT_ACTION_SCHEMA, ) -@register_action("voice_assistant.start", StartAction, VOICE_ASSISTANT_ACTION_SCHEMA) +@register_action( + "voice_assistant.start", + StartAction, + VOICE_ASSISTANT_ACTION_SCHEMA.extend( + { + cv.Optional(CONF_SILENCE_DETECTION, default=True): cv.boolean, + } + ), +) async def voice_assistant_listen_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) await cg.register_parented(var, config[CONF_ID]) + if CONF_SILENCE_DETECTION in config: + cg.add(var.set_silence_detection(config[CONF_SILENCE_DETECTION])) return var diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index 217ddb6354..802ae508ff 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -11,6 +11,17 @@ namespace voice_assistant { static const char *const TAG = "voice_assistant"; +#ifdef SAMPLE_RATE_HZ +#undef SAMPLE_RATE_HZ +#endif + +static const size_t SAMPLE_RATE_HZ = 16000; +static const size_t INPUT_BUFFER_SIZE = 32 * SAMPLE_RATE_HZ / 1000; // 32ms * 16kHz / 1000ms +static const size_t BUFFER_SIZE = 1000 * SAMPLE_RATE_HZ / 1000; // 1s +static const size_t SEND_BUFFER_SIZE = INPUT_BUFFER_SIZE * sizeof(int16_t); +static const size_t RECEIVE_SIZE = 1024; +static const size_t SPEAKER_BUFFER_SIZE = 16 * RECEIVE_SIZE; + float VoiceAssistant::get_setup_priority() const { return setup_priority::AFTER_CONNECTION; } void VoiceAssistant::setup() { @@ -47,7 +58,6 @@ void VoiceAssistant::setup() { this->mark_failed(); return; } - server.ss_family = AF_INET; err = socket_->bind((struct sockaddr *) &server, sizeof(server)); if (err != 0) { @@ -55,60 +65,262 @@ void VoiceAssistant::setup() { this->mark_failed(); return; } + + ExternalRAMAllocator speaker_allocator(ExternalRAMAllocator::ALLOW_FAILURE); + this->speaker_buffer_ = speaker_allocator.allocate(SPEAKER_BUFFER_SIZE); + if (this->speaker_buffer_ == nullptr) { + ESP_LOGW(TAG, "Could not allocate speaker buffer."); + this->mark_failed(); + return; + } } #endif - this->mic_->add_data_callback([this](const std::vector &data) { - if (!this->running_) { - return; + ExternalRAMAllocator allocator(ExternalRAMAllocator::ALLOW_FAILURE); + this->input_buffer_ = allocator.allocate(INPUT_BUFFER_SIZE); + if (this->input_buffer_ == nullptr) { + ESP_LOGW(TAG, "Could not allocate input buffer."); + this->mark_failed(); + return; + } + +#ifdef USE_ESP_ADF + this->vad_instance_ = vad_create(VAD_MODE_4); + + this->ring_buffer_ = rb_create(BUFFER_SIZE, sizeof(int16_t)); + if (this->ring_buffer_ == nullptr) { + ESP_LOGW(TAG, "Could not allocate ring buffer."); + this->mark_failed(); + return; + } +#endif + + ExternalRAMAllocator send_allocator(ExternalRAMAllocator::ALLOW_FAILURE); + this->send_buffer_ = send_allocator.allocate(SEND_BUFFER_SIZE); + if (send_buffer_ == nullptr) { + ESP_LOGW(TAG, "Could not allocate send buffer."); + this->mark_failed(); + return; + } +} + +int VoiceAssistant::read_microphone_() { + size_t bytes_read = 0; + if (this->mic_->is_running()) { // Read audio into input buffer + bytes_read = this->mic_->read(this->input_buffer_, INPUT_BUFFER_SIZE * sizeof(int16_t)); + if (bytes_read == 0) { + memset(this->input_buffer_, 0, INPUT_BUFFER_SIZE * sizeof(int16_t)); + return 0; } - this->socket_->sendto(data.data(), data.size() * sizeof(int16_t), 0, (struct sockaddr *) &this->dest_addr_, - sizeof(this->dest_addr_)); - }); +#ifdef USE_ESP_ADF + // Write audio into ring buffer + int available = rb_bytes_available(this->ring_buffer_); + if (available < bytes_read) { + rb_read(this->ring_buffer_, nullptr, bytes_read - available, 0); + } + rb_write(this->ring_buffer_, (char *) this->input_buffer_, bytes_read, 0); +#endif + } else { + ESP_LOGD(TAG, "microphone not running"); + } + return bytes_read; } void VoiceAssistant::loop() { -#ifdef USE_SPEAKER - if (this->speaker_ != nullptr) { - uint8_t buf[1024]; - auto len = this->socket_->read(buf, sizeof(buf)); - if (len == -1) { - return; + if (this->state_ != State::IDLE && this->state_ != State::STOP_MICROPHONE && + this->state_ != State::STOPPING_MICROPHONE && !api::global_api_server->is_connected()) { + if (this->mic_->is_running() || this->state_ == State::STARTING_MICROPHONE) { + this->set_state_(State::STOP_MICROPHONE, State::IDLE); + } else { + this->set_state_(State::IDLE, State::IDLE); } - this->speaker_->play(buf, len); - this->set_timeout("data-incoming", 200, [this]() { - if (this->continuous_) { - this->request_start(true); - } - }); + this->continuous_ = false; + this->signal_stop_(); return; } + switch (this->state_) { + case State::IDLE: { + if (this->continuous_ && this->desired_state_ == State::IDLE) { +#ifdef USE_ESP_ADF + if (this->use_wake_word_) { + rb_reset(this->ring_buffer_); + this->set_state_(State::START_MICROPHONE, State::WAIT_FOR_VAD); + } else +#endif + { + this->set_state_(State::START_PIPELINE, State::START_MICROPHONE); + } + } else { + this->high_freq_.stop(); + } + break; + } + case State::START_MICROPHONE: { + ESP_LOGD(TAG, "Starting Microphone"); + memset(this->send_buffer_, 0, SEND_BUFFER_SIZE); + memset(this->input_buffer_, 0, INPUT_BUFFER_SIZE * sizeof(int16_t)); + this->mic_->start(); + this->high_freq_.start(); + this->set_state_(State::STARTING_MICROPHONE); + break; + } + case State::STARTING_MICROPHONE: { + if (this->mic_->is_running()) { + this->set_state_(this->desired_state_); + } + break; + } +#ifdef USE_ESP_ADF + case State::WAIT_FOR_VAD: { + this->read_microphone_(); + ESP_LOGD(TAG, "Waiting for speech..."); + this->set_state_(State::WAITING_FOR_VAD); + break; + } + case State::WAITING_FOR_VAD: { + size_t bytes_read = this->read_microphone_(); + if (bytes_read > 0) { + vad_state_t vad_state = + vad_process(this->vad_instance_, this->input_buffer_, SAMPLE_RATE_HZ, VAD_FRAME_LENGTH_MS); + if (vad_state == VAD_SPEECH) { + if (this->vad_counter_ < this->vad_threshold_) { + this->vad_counter_++; + } else { + ESP_LOGD(TAG, "VAD detected speech"); + this->set_state_(State::START_PIPELINE, State::STREAMING_MICROPHONE); + } + } else { + if (this->vad_counter_ > 0) { + this->vad_counter_--; + } + } + } + break; + } +#endif + case State::START_PIPELINE: { + this->read_microphone_(); + ESP_LOGD(TAG, "Requesting start..."); + uint32_t flags = 0; + if (this->use_wake_word_) + flags |= api::enums::VOICE_ASSISTANT_REQUEST_USE_WAKE_WORD; + if (this->silence_detection_) + flags |= api::enums::VOICE_ASSISTANT_REQUEST_USE_VAD; + api::VoiceAssistantAudioSettings audio_settings; + audio_settings.noise_suppression_level = this->noise_suppression_level_; + audio_settings.auto_gain = this->auto_gain_; + audio_settings.volume_multiplier = this->volume_multiplier_; + if (!api::global_api_server->start_voice_assistant(this->conversation_id_, flags, audio_settings)) { + ESP_LOGW(TAG, "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; + } + this->set_state_(State::STARTING_PIPELINE); + this->set_timeout("reset-conversation_id", 5 * 60 * 1000, [this]() { this->conversation_id_ = ""; }); + break; + } + case State::STARTING_PIPELINE: { + this->read_microphone_(); + break; // State changed when udp server port received + } + case State::STREAMING_MICROPHONE: { + size_t bytes_read = this->read_microphone_(); +#ifdef USE_ESP_ADF + if (rb_bytes_filled(this->ring_buffer_) >= SEND_BUFFER_SIZE) { + rb_read(this->ring_buffer_, (char *) this->send_buffer_, SEND_BUFFER_SIZE, 0); + this->socket_->sendto(this->send_buffer_, SEND_BUFFER_SIZE, 0, (struct sockaddr *) &this->dest_addr_, + sizeof(this->dest_addr_)); + } +#else + if (bytes_read > 0) { + this->socket_->sendto(this->input_buffer_, bytes_read, 0, (struct sockaddr *) &this->dest_addr_, + sizeof(this->dest_addr_)); + } +#endif + break; + } + case State::STOP_MICROPHONE: { + if (this->mic_->is_running()) { + this->mic_->stop(); + this->set_state_(State::STOPPING_MICROPHONE); + } else { + this->set_state_(this->desired_state_); + } + break; + } + case State::STOPPING_MICROPHONE: { + if (this->mic_->is_stopped()) { + this->set_state_(this->desired_state_); + } + break; + } + case State::AWAITING_RESPONSE: { + break; // State changed by events + } + case State::STREAMING_RESPONSE: { + bool playing = false; +#ifdef USE_SPEAKER + if (this->speaker_ != nullptr) { + if (this->speaker_buffer_index_ + RECEIVE_SIZE < SPEAKER_BUFFER_SIZE) { + auto len = this->socket_->read(this->speaker_buffer_ + this->speaker_buffer_index_, RECEIVE_SIZE); + if (len > 0) { + this->speaker_buffer_index_ += len; + this->speaker_buffer_size_ += len; + } + } else { + ESP_LOGW(TAG, "Speaker buffer full."); + } + if (this->speaker_buffer_size_ > 0) { + size_t written = this->speaker_->play(this->speaker_buffer_, this->speaker_buffer_size_); + memmove(this->speaker_buffer_, this->speaker_buffer_ + written, this->speaker_buffer_size_ - written); + this->speaker_buffer_size_ -= written; + this->speaker_buffer_index_ -= written; + } + playing = this->speaker_->is_running(); + } #endif #ifdef USE_MEDIA_PLAYER - if (this->media_player_ != nullptr) { - if (!this->playing_tts_ || - this->media_player_->state == media_player::MediaPlayerState::MEDIA_PLAYER_STATE_PLAYING) { - return; - } - this->set_timeout("playing-media", 1000, [this]() { - this->playing_tts_ = false; - if (this->continuous_) { - this->request_start(true); + if (this->media_player_ != nullptr) { + playing = (this->media_player_->state == media_player::MediaPlayerState::MEDIA_PLAYER_STATE_PLAYING); } - }); - return; - } #endif - // Set a 1 second timeout to start the voice assistant again. - this->set_timeout("continuous-no-sound", 1000, [this]() { - if (this->continuous_) { - this->request_start(true); + if (playing) { + this->set_timeout("playing", 100, [this]() { this->set_state_(State::IDLE, State::IDLE); }); + } + break; } - }); + default: + break; + } } -void VoiceAssistant::start(struct sockaddr_storage *addr, uint16_t port) { - ESP_LOGD(TAG, "Starting..."); +void VoiceAssistant::set_state_(State state) { + State old_state = this->state_; + this->state_ = state; + ESP_LOGD(TAG, "State changed from %d to %d", static_cast(old_state), static_cast(state)); +} + +void VoiceAssistant::set_state_(State state, State desired_state) { + this->set_state_(state); + this->desired_state_ = desired_state; + ESP_LOGD(TAG, "Desired state set to %d", static_cast(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->set_state_(State::STOP_MICROPHONE, State::IDLE); +} + +void VoiceAssistant::start_streaming(struct sockaddr_storage *addr, uint16_t port) { + if (this->state_ != State::STARTING_PIPELINE) { + this->signal_stop_(); + return; + } + + ESP_LOGD(TAG, "Client started, streaming microphone"); memcpy(&this->dest_addr_, addr, sizeof(this->dest_addr_)); if (this->dest_addr_.ss_family == AF_INET) { @@ -123,38 +335,90 @@ void VoiceAssistant::start(struct sockaddr_storage *addr, uint16_t port) { ESP_LOGW(TAG, "Unknown address family: %d", this->dest_addr_.ss_family); return; } - this->running_ = true; - this->mic_->start(); - this->listening_trigger_->trigger(); + + if (this->mic_->is_running()) { + this->set_state_(State::STREAMING_MICROPHONE, State::STREAMING_MICROPHONE); + } else { + this->set_state_(State::START_MICROPHONE, State::STREAMING_MICROPHONE); + } } -void VoiceAssistant::request_start(bool continuous) { - ESP_LOGD(TAG, "Requesting start..."); - if (!api::global_api_server->start_voice_assistant(this->conversation_id_, this->silence_detection_)) { - ESP_LOGW(TAG, "Could not request start."); - this->error_trigger_->trigger("not-connected", "Could not request start."); +void VoiceAssistant::request_start(bool continuous, bool silence_detection) { + if (!api::global_api_server->is_connected()) { + ESP_LOGE(TAG, "No API client connected"); + this->set_state_(State::IDLE, State::IDLE); this->continuous_ = false; return; } - this->continuous_ = continuous; - this->set_timeout("reset-conversation_id", 5 * 60 * 1000, [this]() { this->conversation_id_ = ""; }); + if (this->state_ == State::IDLE) { + this->continuous_ = continuous; + this->silence_detection_ = silence_detection; +#ifdef USE_ESP_ADF + if (this->use_wake_word_) { + rb_reset(this->ring_buffer_); + this->set_state_(State::START_MICROPHONE, State::WAIT_FOR_VAD); + } else +#endif + { + this->set_state_(State::START_PIPELINE, State::START_MICROPHONE); + } + } } -void VoiceAssistant::signal_stop() { +void VoiceAssistant::request_stop() { + this->continuous_ = false; + + switch (this->state_) { + case State::IDLE: + break; + case State::START_MICROPHONE: + case State::STARTING_MICROPHONE: + case State::WAIT_FOR_VAD: + case State::WAITING_FOR_VAD: + case State::START_PIPELINE: + this->set_state_(State::STOP_MICROPHONE, State::IDLE); + break; + case State::STARTING_PIPELINE: + case State::STREAMING_MICROPHONE: + this->signal_stop_(); + this->set_state_(State::STOP_MICROPHONE, State::IDLE); + break; + case State::STOP_MICROPHONE: + case State::STOPPING_MICROPHONE: + this->desired_state_ = State::IDLE; + break; + case State::AWAITING_RESPONSE: + case State::STREAMING_RESPONSE: + break; // Let the incoming audio stream finish then it will go to idle. + } +} + +void VoiceAssistant::signal_stop_() { ESP_LOGD(TAG, "Signaling stop..."); - this->mic_->stop(); - this->running_ = false; api::global_api_server->stop_voice_assistant(); memset(&this->dest_addr_, 0, sizeof(this->dest_addr_)); } void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { + ESP_LOGD(TAG, "Event Type: %d", msg.event_type); switch (msg.event_type) { case api::enums::VOICE_ASSISTANT_RUN_START: ESP_LOGD(TAG, "Assist Pipeline running"); 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->wake_word_detected_trigger_->trigger(); + break; + } + case api::enums::VOICE_ASSISTANT_STT_START: + ESP_LOGD(TAG, "STT Started"); + this->listening_trigger_->trigger(); + break; case api::enums::VOICE_ASSISTANT_STT_END: { + this->set_state_(State::STOP_MICROPHONE, State::AWAITING_RESPONSE); std::string text; for (auto arg : msg.data) { if (arg.name == "text") { @@ -166,7 +430,6 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { return; } ESP_LOGD(TAG, "Speech recognised as: \"%s\"", text.c_str()); - this->signal_stop(); this->stt_end_trigger_->trigger(text); break; } @@ -191,6 +454,9 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { } ESP_LOGD(TAG, "Response: \"%s\"", text.c_str()); this->tts_start_trigger_->trigger(text); +#ifdef USE_SPEAKER + this->speaker_->start(); +#endif break; } case api::enums::VOICE_ASSISTANT_TTS_END: { @@ -207,17 +473,22 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { ESP_LOGD(TAG, "Response URL: \"%s\"", url.c_str()); #ifdef USE_MEDIA_PLAYER if (this->media_player_ != nullptr) { - this->playing_tts_ = true; this->media_player_->make_call().set_media_url(url).perform(); } #endif + State new_state = this->local_output_ ? State::STREAMING_RESPONSE : State::IDLE; + this->set_state_(new_state, new_state); this->tts_end_trigger_->trigger(url); break; } - case api::enums::VOICE_ASSISTANT_RUN_END: + case api::enums::VOICE_ASSISTANT_RUN_END: { ESP_LOGD(TAG, "Assist Pipeline ended"); + if (this->state_ != State::STREAMING_RESPONSE && this->state_ != State::IDLE) { + this->set_state_(State::IDLE, State::IDLE); + } this->end_trigger_->trigger(); break; + } case api::enums::VOICE_ASSISTANT_ERROR: { std::string code = ""; std::string message = ""; @@ -228,12 +499,20 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { message = std::move(arg.value); } } + if (code == "wake-word-timeout" || code == "wake_word_detection_aborted") { + this->set_state_(State::STOP_MICROPHONE, State::IDLE); + return; + } ESP_LOGE(TAG, "Error: %s - %s", code.c_str(), message.c_str()); - this->continuous_ = false; - this->signal_stop(); + if (this->state_ != State::IDLE) { + this->signal_stop_(); + this->set_state_(State::STOP_MICROPHONE, State::IDLE); + } this->error_trigger_->trigger(code, message); + break; } default: + ESP_LOGD(TAG, "Unhandled event type: %d", msg.event_type); break; } } diff --git a/esphome/components/voice_assistant/voice_assistant.h b/esphome/components/voice_assistant/voice_assistant.h index 75c17965bc..ce22538a85 100644 --- a/esphome/components/voice_assistant/voice_assistant.h +++ b/esphome/components/voice_assistant/voice_assistant.h @@ -19,6 +19,11 @@ #endif #include "esphome/components/socket/socket.h" +#ifdef USE_ESP_ADF +#include +#include +#endif + namespace esphome { namespace voice_assistant { @@ -28,19 +33,41 @@ namespace voice_assistant { static const uint32_t INITIAL_VERSION = 1; static const uint32_t SPEAKER_SUPPORT = 2; +enum class State { + IDLE, + START_MICROPHONE, + STARTING_MICROPHONE, + WAIT_FOR_VAD, + WAITING_FOR_VAD, + START_PIPELINE, + STARTING_PIPELINE, + STREAMING_MICROPHONE, + STOP_MICROPHONE, + STOPPING_MICROPHONE, + AWAITING_RESPONSE, + STREAMING_RESPONSE, +}; + class VoiceAssistant : public Component { public: void setup() override; void loop() override; float get_setup_priority() const override; - void start(struct sockaddr_storage *addr, uint16_t port); + void start_streaming(struct sockaddr_storage *addr, uint16_t port); + void failed_to_start(); void set_microphone(microphone::Microphone *mic) { this->mic_ = mic; } #ifdef USE_SPEAKER - void set_speaker(speaker::Speaker *speaker) { this->speaker_ = speaker; } + void set_speaker(speaker::Speaker *speaker) { + this->speaker_ = speaker; + this->local_output_ = true; + } #endif #ifdef USE_MEDIA_PLAYER - void set_media_player(media_player::MediaPlayer *media_player) { this->media_player_ = media_player; } + void set_media_player(media_player::MediaPlayer *media_player) { + this->media_player_ = media_player; + this->local_output_ = true; + } #endif uint32_t get_version() const { @@ -52,19 +79,29 @@ class VoiceAssistant : public Component { return INITIAL_VERSION; } - void request_start(bool continuous = false); - void signal_stop(); + void request_start(bool continuous, bool silence_detection); + void request_stop(); void on_event(const api::VoiceAssistantEventResponse &msg); - bool is_running() const { return this->running_; } + bool is_running() const { return this->state_ != State::IDLE; } void set_continuous(bool continuous) { this->continuous_ = continuous; } bool is_continuous() const { return this->continuous_; } - void set_silence_detection(bool silence_detection) { this->silence_detection_ = silence_detection; } + void set_use_wake_word(bool use_wake_word) { this->use_wake_word_ = use_wake_word; } +#ifdef USE_ESP_ADF + void set_vad_threshold(uint8_t vad_threshold) { this->vad_threshold_ = vad_threshold; } +#endif + + void set_noise_suppression_level(uint8_t noise_suppression_level) { + this->noise_suppression_level_ = noise_suppression_level; + } + void set_auto_gain(uint8_t auto_gain) { this->auto_gain_ = auto_gain; } + void set_volume_multiplier(float volume_multiplier) { this->volume_multiplier_ = volume_multiplier; } Trigger<> *get_listening_trigger() const { return this->listening_trigger_; } Trigger<> *get_start_trigger() const { return this->start_trigger_; } + 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_start_trigger() const { return this->tts_start_trigger_; } Trigger *get_tts_end_trigger() const { return this->tts_end_trigger_; } @@ -72,11 +109,17 @@ class VoiceAssistant : public Component { Trigger *get_error_trigger() const { return this->error_trigger_; } protected: + int read_microphone_(); + void set_state_(State state); + void set_state_(State state, State desired_state); + void signal_stop_(); + std::unique_ptr socket_ = nullptr; struct sockaddr_storage dest_addr_; Trigger<> *listening_trigger_ = new Trigger<>(); Trigger<> *start_trigger_ = new Trigger<>(); + Trigger<> *wake_word_detected_trigger_ = new Trigger<>(); Trigger *stt_end_trigger_ = new Trigger(); Trigger *tts_start_trigger_ = new Trigger(); Trigger *tts_end_trigger_ = new Trigger(); @@ -86,35 +129,61 @@ class VoiceAssistant : public Component { microphone::Microphone *mic_{nullptr}; #ifdef USE_SPEAKER speaker::Speaker *speaker_{nullptr}; + uint8_t *speaker_buffer_; + size_t speaker_buffer_index_{0}; + size_t speaker_buffer_size_{0}; #endif #ifdef USE_MEDIA_PLAYER media_player::MediaPlayer *media_player_{nullptr}; bool playing_tts_{false}; #endif + bool local_output_{false}; + std::string conversation_id_{""}; - bool running_{false}; + HighFrequencyLoopRequester high_freq_; + +#ifdef USE_ESP_ADF + vad_handle_t vad_instance_; + ringbuf_handle_t ring_buffer_; + uint8_t vad_threshold_{5}; + uint8_t vad_counter_{0}; +#endif + + bool use_wake_word_; + uint8_t noise_suppression_level_; + uint8_t auto_gain_; + float volume_multiplier_; + + uint8_t *send_buffer_; + int16_t *input_buffer_; + bool continuous_{false}; bool silence_detection_; + + State state_{State::IDLE}; + State desired_state_{State::IDLE}; }; template class StartAction : public Action, public Parented { public: - void play(Ts... x) override { this->parent_->request_start(); } + void play(Ts... x) override { this->parent_->request_start(false, this->silence_detection_); } + + void set_silence_detection(bool silence_detection) { this->silence_detection_ = silence_detection; } + + protected: + bool silence_detection_; }; template class StartContinuousAction : public Action, public Parented { public: - void play(Ts... x) override { this->parent_->request_start(true); } + void play(Ts... x) override { this->parent_->request_start(true, true); } }; template class StopAction : public Action, public Parented { public: - void play(Ts... x) override { - this->parent_->set_continuous(false); - this->parent_->signal_stop(); - } + void play(Ts... x) override { this->parent_->request_stop(); } }; template class IsRunningCondition : public Condition, public Parented { diff --git a/tests/test4.yaml b/tests/test4.yaml index bb4357e28d..3d0ed2f658 100644 --- a/tests/test4.yaml +++ b/tests/test4.yaml @@ -767,6 +767,9 @@ speaker: voice_assistant: microphone: mic_id_external + speaker: speaker_id + on_listening: + - logger.log: "Voice assistant microphone listening" on_start: - logger.log: "Voice assistant started" on_stt_end: From c77a9ad3630802376ab65d79d73d5663c79bf6a4 Mon Sep 17 00:00:00 2001 From: Robert Resch Date: Tue, 10 Oct 2023 09:00:05 +0200 Subject: [PATCH 0285/2101] Don't allow entity category "CONFIG" for sensors (#5505) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/sensor/__init__.py | 13 ++++++++++++- esphome/config_validation.py | 4 ++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index 8f7d581b2d..ee42011038 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -85,6 +85,7 @@ from esphome.const import ( DEVICE_CLASS_WATER, DEVICE_CLASS_WEIGHT, DEVICE_CLASS_WIND_SPEED, + ENTITY_CATEGORY_CONFIG, ) from esphome.core import CORE, coroutine_with_priority from esphome.cpp_generator import MockObjClass @@ -188,6 +189,15 @@ def validate_datapoint(value): return validate_datapoint({CONF_FROM: cv.float_(a), CONF_TO: cv.float_(b)}) +_SENSOR_ENTITY_CATEGORIES = { + k: v for k, v in cv.ENTITY_CATEGORIES.items() if k != ENTITY_CATEGORY_CONFIG +} + + +def sensor_entity_category(value): + return cv.enum(_SENSOR_ENTITY_CATEGORIES, lower=True)(value) + + # Base Sensor = sensor_ns.class_("Sensor", cg.EntityBase) SensorPtr = Sensor.operator("ptr") @@ -246,6 +256,7 @@ SENSOR_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMPONENT_SCHEMA).extend( cv.Optional(CONF_ACCURACY_DECIMALS): validate_accuracy_decimals, cv.Optional(CONF_DEVICE_CLASS): validate_device_class, cv.Optional(CONF_STATE_CLASS): validate_state_class, + cv.Optional(CONF_ENTITY_CATEGORY): sensor_entity_category, cv.Optional("last_reset_type"): cv.invalid( "last_reset_type has been removed since 2021.9.0. state_class: total_increasing should be used for total values." ), @@ -301,7 +312,7 @@ def sensor_schema( (CONF_ACCURACY_DECIMALS, accuracy_decimals, validate_accuracy_decimals), (CONF_DEVICE_CLASS, device_class, validate_device_class), (CONF_STATE_CLASS, state_class, validate_state_class), - (CONF_ENTITY_CATEGORY, entity_category, cv.entity_category), + (CONF_ENTITY_CATEGORY, entity_category, sensor_entity_category), ]: if default is not _UNDEF: schema[cv.Optional(key, default=default)] = validator diff --git a/esphome/config_validation.py b/esphome/config_validation.py index 46f3f6a7bd..d699a2647b 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -1672,7 +1672,7 @@ def maybe_simple_value(*validators, **kwargs): return validate -_ENTITY_CATEGORIES = { +ENTITY_CATEGORIES = { ENTITY_CATEGORY_NONE: cg.EntityCategory.ENTITY_CATEGORY_NONE, ENTITY_CATEGORY_CONFIG: cg.EntityCategory.ENTITY_CATEGORY_CONFIG, ENTITY_CATEGORY_DIAGNOSTIC: cg.EntityCategory.ENTITY_CATEGORY_DIAGNOSTIC, @@ -1680,7 +1680,7 @@ _ENTITY_CATEGORIES = { def entity_category(value): - return enum(_ENTITY_CATEGORIES, lower=True)(value) + return enum(ENTITY_CATEGORIES, lower=True)(value) MQTT_COMPONENT_AVAILABILITY_SCHEMA = Schema( From c9a8911029698c239cff21a0a67bd952c526da14 Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Wed, 11 Oct 2023 00:51:53 +0200 Subject: [PATCH 0286/2101] Prepare protobuf for ESP-IDF >= 5 (#5510) --- esphome/components/api/api_pb2.cpp | 190 ++++++++++++++-------------- script/api_protobuf/api_protobuf.py | 12 +- 2 files changed, 103 insertions(+), 99 deletions(-) diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index d0711aba7b..225b213a67 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -3,6 +3,8 @@ #include "api_pb2.h" #include "esphome/core/log.h" +#include + namespace esphome { namespace api { @@ -544,12 +546,12 @@ void HelloRequest::dump_to(std::string &out) const { out.append("\n"); out.append(" api_version_major: "); - sprintf(buffer, "%u", this->api_version_major); + sprintf(buffer, "%" PRIu32, this->api_version_major); out.append(buffer); out.append("\n"); out.append(" api_version_minor: "); - sprintf(buffer, "%u", this->api_version_minor); + sprintf(buffer, "%" PRIu32, this->api_version_minor); out.append(buffer); out.append("\n"); out.append("}"); @@ -594,12 +596,12 @@ void HelloResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("HelloResponse {\n"); out.append(" api_version_major: "); - sprintf(buffer, "%u", this->api_version_major); + sprintf(buffer, "%" PRIu32, this->api_version_major); out.append(buffer); out.append("\n"); out.append(" api_version_minor: "); - sprintf(buffer, "%u", this->api_version_minor); + sprintf(buffer, "%" PRIu32, this->api_version_minor); out.append(buffer); out.append("\n"); @@ -805,17 +807,17 @@ void DeviceInfoResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" webserver_port: "); - sprintf(buffer, "%u", this->webserver_port); + sprintf(buffer, "%" PRIu32, this->webserver_port); out.append(buffer); out.append("\n"); out.append(" legacy_bluetooth_proxy_version: "); - sprintf(buffer, "%u", this->legacy_bluetooth_proxy_version); + sprintf(buffer, "%" PRIu32, this->legacy_bluetooth_proxy_version); out.append(buffer); out.append("\n"); out.append(" bluetooth_proxy_feature_flags: "); - sprintf(buffer, "%u", this->bluetooth_proxy_feature_flags); + sprintf(buffer, "%" PRIu32, this->bluetooth_proxy_feature_flags); out.append(buffer); out.append("\n"); @@ -828,7 +830,7 @@ void DeviceInfoResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" voice_assistant_version: "); - sprintf(buffer, "%u", this->voice_assistant_version); + sprintf(buffer, "%" PRIu32, this->voice_assistant_version); out.append(buffer); out.append("\n"); out.append("}"); @@ -920,7 +922,7 @@ void ListEntitiesBinarySensorResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -988,7 +990,7 @@ void BinarySensorStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("BinarySensorStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -1091,7 +1093,7 @@ void ListEntitiesCoverResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -1181,7 +1183,7 @@ void CoverStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("CoverStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -1264,7 +1266,7 @@ void CoverCommandRequest::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("CoverCommandRequest {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -1384,7 +1386,7 @@ void ListEntitiesFanResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -1409,7 +1411,7 @@ void ListEntitiesFanResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" supported_speed_count: "); - sprintf(buffer, "%d", this->supported_speed_count); + sprintf(buffer, "%" PRId32, this->supported_speed_count); out.append(buffer); out.append("\n"); @@ -1476,7 +1478,7 @@ void FanStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("FanStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -1497,7 +1499,7 @@ void FanStateResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" speed_level: "); - sprintf(buffer, "%d", this->speed_level); + sprintf(buffer, "%" PRId32, this->speed_level); out.append(buffer); out.append("\n"); out.append("}"); @@ -1577,7 +1579,7 @@ void FanCommandRequest::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("FanCommandRequest {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -1618,7 +1620,7 @@ void FanCommandRequest::dump_to(std::string &out) const { out.append("\n"); out.append(" speed_level: "); - sprintf(buffer, "%d", this->speed_level); + sprintf(buffer, "%" PRId32, this->speed_level); out.append(buffer); out.append("\n"); out.append("}"); @@ -1732,7 +1734,7 @@ void ListEntitiesLightResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -1886,7 +1888,7 @@ void LightStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("LightStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -2109,7 +2111,7 @@ void LightCommandRequest::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("LightCommandRequest {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -2207,7 +2209,7 @@ void LightCommandRequest::dump_to(std::string &out) const { out.append("\n"); out.append(" transition_length: "); - sprintf(buffer, "%u", this->transition_length); + sprintf(buffer, "%" PRIu32, this->transition_length); out.append(buffer); out.append("\n"); @@ -2216,7 +2218,7 @@ void LightCommandRequest::dump_to(std::string &out) const { out.append("\n"); out.append(" flash_length: "); - sprintf(buffer, "%u", this->flash_length); + sprintf(buffer, "%" PRIu32, this->flash_length); out.append(buffer); out.append("\n"); @@ -2324,7 +2326,7 @@ void ListEntitiesSensorResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -2345,7 +2347,7 @@ void ListEntitiesSensorResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" accuracy_decimals: "); - sprintf(buffer, "%d", this->accuracy_decimals); + sprintf(buffer, "%" PRId32, this->accuracy_decimals); out.append(buffer); out.append("\n"); @@ -2409,7 +2411,7 @@ void SensorStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("SensorStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -2498,7 +2500,7 @@ void ListEntitiesSwitchResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -2561,7 +2563,7 @@ void SwitchStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("SwitchStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -2600,7 +2602,7 @@ void SwitchCommandRequest::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("SwitchCommandRequest {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -2674,7 +2676,7 @@ void ListEntitiesTextSensorResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -2740,7 +2742,7 @@ void TextSensorStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("TextSensorStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -3047,7 +3049,7 @@ void GetTimeResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("GetTimeResponse {\n"); out.append(" epoch_seconds: "); - sprintf(buffer, "%u", this->epoch_seconds); + sprintf(buffer, "%" PRIu32, this->epoch_seconds); out.append(buffer); out.append("\n"); out.append("}"); @@ -3131,7 +3133,7 @@ void ListEntitiesServicesResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -3225,7 +3227,7 @@ void ExecuteServiceArgument::dump_to(std::string &out) const { out.append("\n"); out.append(" legacy_int: "); - sprintf(buffer, "%d", this->legacy_int); + sprintf(buffer, "%" PRId32, this->legacy_int); out.append(buffer); out.append("\n"); @@ -3239,7 +3241,7 @@ void ExecuteServiceArgument::dump_to(std::string &out) const { out.append("\n"); out.append(" int_: "); - sprintf(buffer, "%d", this->int_); + sprintf(buffer, "%" PRId32, this->int_); out.append(buffer); out.append("\n"); @@ -3251,7 +3253,7 @@ void ExecuteServiceArgument::dump_to(std::string &out) const { for (const auto &it : this->int_array) { out.append(" int_array: "); - sprintf(buffer, "%d", it); + sprintf(buffer, "%" PRId32, it); out.append(buffer); out.append("\n"); } @@ -3302,7 +3304,7 @@ void ExecuteServiceRequest::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("ExecuteServiceRequest {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -3378,7 +3380,7 @@ void ListEntitiesCameraResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -3444,7 +3446,7 @@ void CameraImageResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("CameraImageResponse {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -3636,7 +3638,7 @@ void ListEntitiesClimateResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -3824,7 +3826,7 @@ void ClimateStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("ClimateStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -4012,7 +4014,7 @@ void ClimateCommandRequest::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("ClimateCommandRequest {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -4195,7 +4197,7 @@ void ListEntitiesNumberResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -4282,7 +4284,7 @@ void NumberStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("NumberStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -4320,7 +4322,7 @@ void NumberCommandRequest::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("NumberCommandRequest {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -4402,7 +4404,7 @@ void ListEntitiesSelectResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -4474,7 +4476,7 @@ void SelectStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("SelectStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -4517,7 +4519,7 @@ void SelectCommandRequest::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("SelectCommandRequest {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -4611,7 +4613,7 @@ void ListEntitiesLockResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -4682,7 +4684,7 @@ void LockStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("LockStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -4737,7 +4739,7 @@ void LockCommandRequest::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("LockCommandRequest {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -4824,7 +4826,7 @@ void ListEntitiesButtonResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -4870,7 +4872,7 @@ void ButtonCommandRequest::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("ButtonCommandRequest {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); out.append("}"); @@ -4945,7 +4947,7 @@ void ListEntitiesMediaPlayerResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -5014,7 +5016,7 @@ void MediaPlayerStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("MediaPlayerStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -5093,7 +5095,7 @@ void MediaPlayerCommandRequest::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("MediaPlayerCommandRequest {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -5142,7 +5144,7 @@ void SubscribeBluetoothLEAdvertisementsRequest::dump_to(std::string &out) const __attribute__((unused)) char buffer[64]; out.append("SubscribeBluetoothLEAdvertisementsRequest {\n"); out.append(" flags: "); - sprintf(buffer, "%u", this->flags); + sprintf(buffer, "%" PRIu32, this->flags); out.append(buffer); out.append("\n"); out.append("}"); @@ -5189,7 +5191,7 @@ void BluetoothServiceData::dump_to(std::string &out) const { for (const auto &it : this->legacy_data) { out.append(" legacy_data: "); - sprintf(buffer, "%u", it); + sprintf(buffer, "%" PRIu32, it); out.append(buffer); out.append("\n"); } @@ -5269,7 +5271,7 @@ void BluetoothLEAdvertisementResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" rssi: "); - sprintf(buffer, "%d", this->rssi); + sprintf(buffer, "%" PRId32, this->rssi); out.append(buffer); out.append("\n"); @@ -5292,7 +5294,7 @@ void BluetoothLEAdvertisementResponse::dump_to(std::string &out) const { } out.append(" address_type: "); - sprintf(buffer, "%u", this->address_type); + sprintf(buffer, "%" PRIu32, this->address_type); out.append(buffer); out.append("\n"); out.append("}"); @@ -5342,12 +5344,12 @@ void BluetoothLERawAdvertisement::dump_to(std::string &out) const { out.append("\n"); out.append(" rssi: "); - sprintf(buffer, "%d", this->rssi); + sprintf(buffer, "%" PRId32, this->rssi); out.append(buffer); out.append("\n"); out.append(" address_type: "); - sprintf(buffer, "%u", this->address_type); + sprintf(buffer, "%" PRIu32, this->address_type); out.append(buffer); out.append("\n"); @@ -5430,7 +5432,7 @@ void BluetoothDeviceRequest::dump_to(std::string &out) const { out.append("\n"); out.append(" address_type: "); - sprintf(buffer, "%u", this->address_type); + sprintf(buffer, "%" PRIu32, this->address_type); out.append(buffer); out.append("\n"); out.append("}"); @@ -5478,12 +5480,12 @@ void BluetoothDeviceConnectionResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" mtu: "); - sprintf(buffer, "%u", this->mtu); + sprintf(buffer, "%" PRIu32, this->mtu); out.append(buffer); out.append("\n"); out.append(" error: "); - sprintf(buffer, "%d", this->error); + sprintf(buffer, "%" PRId32, this->error); out.append(buffer); out.append("\n"); out.append("}"); @@ -5543,7 +5545,7 @@ void BluetoothGATTDescriptor::dump_to(std::string &out) const { } out.append(" handle: "); - sprintf(buffer, "%u", this->handle); + sprintf(buffer, "%" PRIu32, this->handle); out.append(buffer); out.append("\n"); out.append("}"); @@ -5599,12 +5601,12 @@ void BluetoothGATTCharacteristic::dump_to(std::string &out) const { } out.append(" handle: "); - sprintf(buffer, "%u", this->handle); + sprintf(buffer, "%" PRIu32, this->handle); out.append(buffer); out.append("\n"); out.append(" properties: "); - sprintf(buffer, "%u", this->properties); + sprintf(buffer, "%" PRIu32, this->properties); out.append(buffer); out.append("\n"); @@ -5661,7 +5663,7 @@ void BluetoothGATTService::dump_to(std::string &out) const { } out.append(" handle: "); - sprintf(buffer, "%u", this->handle); + sprintf(buffer, "%" PRIu32, this->handle); out.append(buffer); out.append("\n"); @@ -5768,7 +5770,7 @@ void BluetoothGATTReadRequest::dump_to(std::string &out) const { out.append("\n"); out.append(" handle: "); - sprintf(buffer, "%u", this->handle); + sprintf(buffer, "%" PRIu32, this->handle); out.append(buffer); out.append("\n"); out.append("}"); @@ -5813,7 +5815,7 @@ void BluetoothGATTReadResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" handle: "); - sprintf(buffer, "%u", this->handle); + sprintf(buffer, "%" PRIu32, this->handle); out.append(buffer); out.append("\n"); @@ -5867,7 +5869,7 @@ void BluetoothGATTWriteRequest::dump_to(std::string &out) const { out.append("\n"); out.append(" handle: "); - sprintf(buffer, "%u", this->handle); + sprintf(buffer, "%" PRIu32, this->handle); out.append(buffer); out.append("\n"); @@ -5909,7 +5911,7 @@ void BluetoothGATTReadDescriptorRequest::dump_to(std::string &out) const { out.append("\n"); out.append(" handle: "); - sprintf(buffer, "%u", this->handle); + sprintf(buffer, "%" PRIu32, this->handle); out.append(buffer); out.append("\n"); out.append("}"); @@ -5954,7 +5956,7 @@ void BluetoothGATTWriteDescriptorRequest::dump_to(std::string &out) const { out.append("\n"); out.append(" handle: "); - sprintf(buffer, "%u", this->handle); + sprintf(buffer, "%" PRIu32, this->handle); out.append(buffer); out.append("\n"); @@ -5997,7 +5999,7 @@ void BluetoothGATTNotifyRequest::dump_to(std::string &out) const { out.append("\n"); out.append(" handle: "); - sprintf(buffer, "%u", this->handle); + sprintf(buffer, "%" PRIu32, this->handle); out.append(buffer); out.append("\n"); @@ -6046,7 +6048,7 @@ void BluetoothGATTNotifyDataResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" handle: "); - sprintf(buffer, "%u", this->handle); + sprintf(buffer, "%" PRIu32, this->handle); out.append(buffer); out.append("\n"); @@ -6085,12 +6087,12 @@ void BluetoothConnectionsFreeResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("BluetoothConnectionsFreeResponse {\n"); out.append(" free: "); - sprintf(buffer, "%u", this->free); + sprintf(buffer, "%" PRIu32, this->free); out.append(buffer); out.append("\n"); out.append(" limit: "); - sprintf(buffer, "%u", this->limit); + sprintf(buffer, "%" PRIu32, this->limit); out.append(buffer); out.append("\n"); out.append("}"); @@ -6129,12 +6131,12 @@ void BluetoothGATTErrorResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" handle: "); - sprintf(buffer, "%u", this->handle); + sprintf(buffer, "%" PRIu32, this->handle); out.append(buffer); out.append("\n"); out.append(" error: "); - sprintf(buffer, "%d", this->error); + sprintf(buffer, "%" PRId32, this->error); out.append(buffer); out.append("\n"); out.append("}"); @@ -6168,7 +6170,7 @@ void BluetoothGATTWriteResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" handle: "); - sprintf(buffer, "%u", this->handle); + sprintf(buffer, "%" PRIu32, this->handle); out.append(buffer); out.append("\n"); out.append("}"); @@ -6202,7 +6204,7 @@ void BluetoothGATTNotifyResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" handle: "); - sprintf(buffer, "%u", this->handle); + sprintf(buffer, "%" PRIu32, this->handle); out.append(buffer); out.append("\n"); out.append("}"); @@ -6245,7 +6247,7 @@ void BluetoothDevicePairingResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" error: "); - sprintf(buffer, "%d", this->error); + sprintf(buffer, "%" PRId32, this->error); out.append(buffer); out.append("\n"); out.append("}"); @@ -6288,7 +6290,7 @@ void BluetoothDeviceUnpairingResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" error: "); - sprintf(buffer, "%d", this->error); + sprintf(buffer, "%" PRId32, this->error); out.append(buffer); out.append("\n"); out.append("}"); @@ -6337,7 +6339,7 @@ void BluetoothDeviceClearCacheResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" error: "); - sprintf(buffer, "%d", this->error); + sprintf(buffer, "%" PRId32, this->error); out.append(buffer); out.append("\n"); out.append("}"); @@ -6398,12 +6400,12 @@ void VoiceAssistantAudioSettings::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("VoiceAssistantAudioSettings {\n"); out.append(" noise_suppression_level: "); - sprintf(buffer, "%u", this->noise_suppression_level); + sprintf(buffer, "%" PRIu32, this->noise_suppression_level); out.append(buffer); out.append("\n"); out.append(" auto_gain: "); - sprintf(buffer, "%u", this->auto_gain); + sprintf(buffer, "%" PRIu32, this->auto_gain); out.append(buffer); out.append("\n"); @@ -6461,7 +6463,7 @@ void VoiceAssistantRequest::dump_to(std::string &out) const { out.append("\n"); out.append(" flags: "); - sprintf(buffer, "%u", this->flags); + sprintf(buffer, "%" PRIu32, this->flags); out.append(buffer); out.append("\n"); @@ -6494,7 +6496,7 @@ void VoiceAssistantResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("VoiceAssistantResponse {\n"); out.append(" port: "); - sprintf(buffer, "%u", this->port); + sprintf(buffer, "%" PRIu32, this->port); out.append(buffer); out.append("\n"); @@ -6657,7 +6659,7 @@ void ListEntitiesAlarmControlPanelResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -6682,7 +6684,7 @@ void ListEntitiesAlarmControlPanelResponse::dump_to(std::string &out) const { out.append("\n"); out.append(" supported_features: "); - sprintf(buffer, "%u", this->supported_features); + sprintf(buffer, "%" PRIu32, this->supported_features); out.append(buffer); out.append("\n"); @@ -6725,7 +6727,7 @@ void AlarmControlPanelStateResponse::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("AlarmControlPanelStateResponse {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); @@ -6775,7 +6777,7 @@ void AlarmControlPanelCommandRequest::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; out.append("AlarmControlPanelCommandRequest {\n"); out.append(" key: "); - sprintf(buffer, "%u", this->key); + sprintf(buffer, "%" PRIu32, this->key); out.append(buffer); out.append("\n"); diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index 5a0c92350d..3c19034e96 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -263,7 +263,7 @@ class Int32Type(TypeInfo): encode_func = "encode_int32" def dump(self, name): - o = f'sprintf(buffer, "%d", {name});\n' + o = f'sprintf(buffer, "%" PRId32, {name});\n' o += f"out.append(buffer);" return o @@ -289,7 +289,7 @@ class Fixed32Type(TypeInfo): encode_func = "encode_fixed32" def dump(self, name): - o = f'sprintf(buffer, "%u", {name});\n' + o = f'sprintf(buffer, "%" PRIu32, {name});\n' o += f"out.append(buffer);" return o @@ -371,7 +371,7 @@ class UInt32Type(TypeInfo): encode_func = "encode_uint32" def dump(self, name): - o = f'sprintf(buffer, "%u", {name});\n' + o = f'sprintf(buffer, "%" PRIu32, {name});\n' o += f"out.append(buffer);" return o @@ -405,7 +405,7 @@ class SFixed32Type(TypeInfo): encode_func = "encode_sfixed32" def dump(self, name): - o = f'sprintf(buffer, "%d", {name});\n' + o = f'sprintf(buffer, "%" PRId32, {name});\n' o += f"out.append(buffer);" return o @@ -431,7 +431,7 @@ class SInt32Type(TypeInfo): encode_func = "encode_sint32" def dump(self, name): - o = f'sprintf(buffer, "%d", {name});\n' + o = f'sprintf(buffer, "%" PRId32, {name});\n' o += f"out.append(buffer);" return o @@ -701,6 +701,8 @@ cpp += """\ #include "api_pb2.h" #include "esphome/core/log.h" +#include + namespace esphome { namespace api { From 5d5cc960170ae0a4f68fbc3c37bf1ced820120a4 Mon Sep 17 00:00:00 2001 From: Guillermo Ruffino Date: Tue, 10 Oct 2023 19:52:40 -0300 Subject: [PATCH 0287/2101] fix build lang schema for spi and i2c (#5509) --- script/build_language_schema.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/script/build_language_schema.py b/script/build_language_schema.py index c6fcf5eb64..fb2010fe3e 100644 --- a/script/build_language_schema.py +++ b/script/build_language_schema.py @@ -82,6 +82,10 @@ def load_components(): components[domain] = get_component(domain) +from esphome.const import CONF_TYPE, KEY_CORE +from esphome.core import CORE + +CORE.data[KEY_CORE] = {} load_components() # Import esphome after loading components (so schema is tracked) @@ -91,7 +95,6 @@ import esphome.config_validation as cv from esphome import automation from esphome import pins from esphome.components import remote_base -from esphome.const import CONF_TYPE from esphome.loader import get_platform, CORE_COMPONENTS_PATH from esphome.helpers import write_file_if_changed from esphome.util import Registry @@ -868,8 +871,11 @@ def convert(schema, config_var, path): else: raise Exception("Unknown extracted schema type") elif config_var.get("key") == "GeneratedID": - if path == "i2c/CONFIG_SCHEMA/extL/all/id": - config_var["id_type"] = {"class": "i2c::I2CBus", "parents": ["Component"]} + 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/extL/all/id": config_var["id_type"] = { "class": "uart::UARTComponent", From 9d95f5c1daece493abd61f37feb1a2d47ceef15c Mon Sep 17 00:00:00 2001 From: Oleg Tarasov Date: Wed, 11 Oct 2023 01:56:53 +0300 Subject: [PATCH 0288/2101] Added Nextion display error handling during setup (#5493) --- esphome/components/nextion/nextion.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/esphome/components/nextion/nextion.cpp b/esphome/components/nextion/nextion.cpp index f8beaeab78..6133ad1d7e 100644 --- a/esphome/components/nextion/nextion.cpp +++ b/esphome/components/nextion/nextion.cpp @@ -61,6 +61,11 @@ bool Nextion::check_connect_() { std::string response; this->recv_ret_string_(response, 0, false); + if (!response.empty() && response[0] == 0x1A) { + // Swallow invalid variable name responses that may be caused by the above commands + ESP_LOGD(TAG, "0x1A error ignored during setup"); + return false; + } if (response.empty() || response.find("comok") == std::string::npos) { #ifdef NEXTION_PROTOCOL_LOG ESP_LOGN(TAG, "Bad connect request %s", response.c_str()); From 41f29c46d024138ae8b3a1dd19d94f1c4ed96816 Mon Sep 17 00:00:00 2001 From: justdaniel-gh <68163487+justdaniel-gh@users.noreply.github.com> Date: Tue, 10 Oct 2023 18:42:38 -0500 Subject: [PATCH 0289/2101] Fix e131 and voice_assistant sockets (#5502) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/e131/e131.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/esphome/components/e131/e131.cpp b/esphome/components/e131/e131.cpp index 818006ced7..c3ff21c1a0 100644 --- a/esphome/components/e131/e131.cpp +++ b/esphome/components/e131/e131.cpp @@ -40,7 +40,6 @@ void E131Component::setup() { this->mark_failed(); return; } - server.ss_family = AF_INET; err = this->socket_->bind((struct sockaddr *) &server, sizeof(server)); if (err != 0) { From e35de626a46d595609556d83c1c18a9afe4d8183 Mon Sep 17 00:00:00 2001 From: NP v/d Spek Date: Thu, 12 Oct 2023 03:26:07 +0200 Subject: [PATCH 0290/2101] Allow manual set "Invert_display" (#5494) --- esphome/components/ili9xxx/display.py | 5 +++++ esphome/components/ili9xxx/ili9xxx_display.cpp | 15 +++++++++++---- esphome/components/ili9xxx/ili9xxx_display.h | 4 +++- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/esphome/components/ili9xxx/display.py b/esphome/components/ili9xxx/display.py index 241f56e018..ec96d38cf8 100644 --- a/esphome/components/ili9xxx/display.py +++ b/esphome/components/ili9xxx/display.py @@ -54,6 +54,7 @@ COLOR_PALETTE = cv.one_of("NONE", "GRAYSCALE", "IMAGE_ADAPTIVE") CONF_LED_PIN = "led_pin" CONF_COLOR_PALETTE_IMAGES = "color_palette_images" +CONF_INVERT_DISPLAY = "invert_display" def _validate(config): @@ -100,6 +101,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_COLOR_PALETTE_IMAGES, default=[]): cv.ensure_list( cv.file_ ), + cv.Optional(CONF_INVERT_DISPLAY): cv.boolean, } ) .extend(cv.polling_component_schema("1s")) @@ -176,3 +178,6 @@ async def to_code(config): if rhs is not None: prog_arr = cg.progmem_array(config[CONF_RAW_DATA_ID], rhs) cg.add(var.set_palette(prog_arr)) + + if CONF_INVERT_DISPLAY in config: + cg.add(var.invert_display(config[CONF_INVERT_DISPLAY])) diff --git a/esphome/components/ili9xxx/ili9xxx_display.cpp b/esphome/components/ili9xxx/ili9xxx_display.cpp index abe01ea8c3..fdbf3e3760 100644 --- a/esphome/components/ili9xxx/ili9xxx_display.cpp +++ b/esphome/components/ili9xxx/ili9xxx_display.cpp @@ -12,11 +12,13 @@ static const char *const TAG = "ili9xxx"; void ILI9XXXDisplay::setup() { this->setup_pins_(); this->initialize(); + this->command(this->pre_invertdisplay_ ? ILI9XXX_INVON : ILI9XXX_INVOFF); this->x_low_ = this->width_; this->y_low_ = this->height_; this->x_high_ = 0; this->y_high_ = 0; + if (this->buffer_color_mode_ == BITS_16) { this->init_internal_(this->get_buffer_length_() * 2); if (this->buffer_ != nullptr) { @@ -333,7 +335,12 @@ void ILI9XXXDisplay::set_addr_window_(uint16_t x1, uint16_t y1, uint16_t w, uint this->command(ILI9XXX_RAMWR); // Write to RAM } -void ILI9XXXDisplay::invert_display_(bool invert) { this->command(invert ? ILI9XXX_INVON : ILI9XXX_INVOFF); } +void ILI9XXXDisplay::invert_display(bool invert) { + this->pre_invertdisplay_ = invert; + if (is_ready()) { + this->command(invert ? ILI9XXX_INVON : ILI9XXX_INVOFF); + } +} int ILI9XXXDisplay::get_width_internal() { return this->width_; } int ILI9XXXDisplay::get_height_internal() { return this->height_; } @@ -345,7 +352,7 @@ void ILI9XXXM5Stack::initialize() { this->width_ = 320; if (this->height_ == 0) this->height_ = 240; - this->invert_display_(true); + this->pre_invertdisplay_ = true; } // M5CORE display // Based on the configuration settings of M5stact's M5GFX code. @@ -355,7 +362,7 @@ void ILI9XXXM5CORE::initialize() { this->width_ = 320; if (this->height_ == 0) this->height_ = 240; - this->invert_display_(true); + this->pre_invertdisplay_ = true; } // 24_TFT display @@ -462,7 +469,7 @@ void ILI9XXXS3BoxLite::initialize() { if (this->height_ == 0) { this->height_ = 240; } - this->invert_display_(true); + this->pre_invertdisplay_ = true; } } // namespace ili9xxx diff --git a/esphome/components/ili9xxx/ili9xxx_display.h b/esphome/components/ili9xxx/ili9xxx_display.h index 4e8355b9a5..e43585afeb 100644 --- a/esphome/components/ili9xxx/ili9xxx_display.h +++ b/esphome/components/ili9xxx/ili9xxx_display.h @@ -33,6 +33,7 @@ class ILI9XXXDisplay : public PollingComponent, this->height_ = height; this->width_ = width; } + void invert_display(bool invert); void command(uint8_t value); void data(uint8_t value); void send_command(uint8_t command_byte, const uint8_t *data_bytes, uint8_t num_data_bytes); @@ -55,7 +56,7 @@ class ILI9XXXDisplay : public PollingComponent, void display_(); void init_lcd_(const uint8_t *init_cmd); void set_addr_window_(uint16_t x, uint16_t y, uint16_t w, uint16_t h); - void invert_display_(bool invert); + void reset_(); int16_t width_{0}; ///< Display width as modified by current rotation @@ -88,6 +89,7 @@ class ILI9XXXDisplay : public PollingComponent, bool prossing_update_ = false; bool need_update_ = false; bool is_18bitdisplay_ = false; + bool pre_invertdisplay_ = false; }; //----------- M5Stack display -------------- From 853d81c6ddb7d9d11e04156707a83451214c7356 Mon Sep 17 00:00:00 2001 From: Mark Veinot Date: Wed, 11 Oct 2023 22:27:36 -0300 Subject: [PATCH 0291/2101] As3935 calibration (#5366) --- esphome/components/as3935/__init__.py | 6 ++ esphome/components/as3935/as3935.cpp | 89 +++++++++++++++++++++++++++ esphome/components/as3935/as3935.h | 14 +++++ esphome/const.py | 1 + 4 files changed, 110 insertions(+) diff --git a/esphome/components/as3935/__init__.py b/esphome/components/as3935/__init__.py index 5cec1bfaba..2ec7c50859 100644 --- a/esphome/components/as3935/__init__.py +++ b/esphome/components/as3935/__init__.py @@ -8,6 +8,8 @@ from esphome.const import ( CONF_IRQ_PIN, CONF_LIGHTNING_THRESHOLD, CONF_MASK_DISTURBER, + CONF_CALIBRATION, + CONF_TUNE_ANTENNA, CONF_NOISE_LEVEL, CONF_SPIKE_REJECTION, CONF_WATCHDOG_THRESHOLD, @@ -34,6 +36,8 @@ AS3935_SCHEMA = cv.Schema( cv.Optional(CONF_MASK_DISTURBER, default=False): cv.boolean, cv.Optional(CONF_DIV_RATIO, default=0): cv.one_of(0, 16, 32, 64, 128, int=True), cv.Optional(CONF_CAPACITANCE, default=0): cv.int_range(min=0, max=15), + cv.Optional(CONF_TUNE_ANTENNA, default=False): cv.boolean, + cv.Optional(CONF_CALIBRATION, default=True): cv.boolean, } ) @@ -51,3 +55,5 @@ async def setup_as3935(var, config): cg.add(var.set_mask_disturber(config[CONF_MASK_DISTURBER])) cg.add(var.set_div_ratio(config[CONF_DIV_RATIO])) cg.add(var.set_capacitance(config[CONF_CAPACITANCE])) + cg.add(var.set_tune_antenna(config[CONF_TUNE_ANTENNA])) + cg.add(var.set_calibration(config[CONF_CALIBRATION])) diff --git a/esphome/components/as3935/as3935.cpp b/esphome/components/as3935/as3935.cpp index c5651caee3..29fc6ee685 100644 --- a/esphome/components/as3935/as3935.cpp +++ b/esphome/components/as3935/as3935.cpp @@ -21,6 +21,14 @@ void AS3935Component::setup() { this->write_mask_disturber(this->mask_disturber_); this->write_div_ratio(this->div_ratio_); this->write_capacitance(this->capacitance_); + + // Handle setting up tuning or auto-calibration + if (this->tune_antenna_) { + ESP_LOGCONFIG(TAG, " Antenna tuning: ENABLED - lightning detection will not function in this mode"); + this->tune_antenna(); + } else if (this->calibration_) { + this->calibrate_oscillator(); + } } void AS3935Component::dump_config() { @@ -227,6 +235,87 @@ uint32_t AS3935Component::get_lightning_energy_() { return pure_light; } +// REG0x03, bit [7:6], manufacturer default: 0 (16 division ratio). +// This function returns the current division ratio of the resonance frequency. +// The antenna resonance frequency should be within 3.5 percent of 500kHz, and +// so when modifying the resonance frequency with the internal capacitors +// (tuneCap()) it's important to keep in mind that the displayed frequency on +// the IRQ pin is divided by this number. +uint8_t AS3935Component::read_div_ratio() { + ESP_LOGV(TAG, "Calling read_div_ratio"); + uint8_t reg_val = this->read_register_(INT_MASK_ANT, DIV_MASK); + reg_val >>= 6; // Front of the line. + + if (reg_val == 0) { + return 16; + } else if (reg_val == 1) { + return 32; + } else if (reg_val == 2) { + return 64; + } else if (reg_val == 3) { + return 128; + } + ESP_LOGW(TAG, "Unknown response received for div_ratio"); + return 0; +} + +uint8_t AS3935Component::read_capacitance() { + ESP_LOGV(TAG, "Calling read_capacitance"); + uint8_t reg_val = this->read_register_(FREQ_DISP_IRQ, CAP_MASK) * 8; + return (reg_val); +} + +// REG0x08, bits [5,6,7], manufacturer default: 0. +// This will send the frequency of the oscillators to the IRQ pin. +// _osc 1, bit[5] = TRCO - System RCO at 32.768kHz +// _osc 2, bit[6] = SRCO - Timer RCO Oscillators 1.1MHz +// _osc 3, bit[7] = LCO - Frequency of the Antenna +void AS3935Component::display_oscillator(bool state, uint8_t osc) { + if ((osc < 1) || (osc > 3)) + return; + + this->write_register(FREQ_DISP_IRQ, OSC_MASK, state, 4 + osc); +} + +// REG0x3D, bits[7:0] +// This function calibrates both internal oscillators The oscillators are tuned +// based on the resonance frequency of the antenna and so it should be trimmed +// before the calibration is done. +bool AS3935Component::calibrate_oscillator() { + ESP_LOGI(TAG, "Starting oscillators calibration..."); + this->write_register(CALIB_RCO, WIPE_ALL, DIRECT_COMMAND, 0); // Send command to calibrate the oscillators + + this->display_oscillator(true, 2); + delay(2); // Give time for the internal oscillators to start up. + this->display_oscillator(false, 2); + + // Check it they were calibrated successfully. + uint8_t reg_val_srco = this->read_register_(CALIB_SRCO, CALIB_MASK_NOK); + uint8_t reg_val_trco = this->read_register_(CALIB_TRCO, CALIB_MASK_NOK); + + // reg_val_srco &= CALIB_MASK; + // reg_val_srco >>= 6; + // reg_val_trco &= CALIB_MASK; + // reg_val_trco >>= 6; + if (!reg_val_srco && !reg_val_trco) { // Zero upon success + ESP_LOGI(TAG, "Calibration was succesful"); + return true; + } else { + ESP_LOGW(TAG, "Calibration was NOT succesful"); + return false; + } +} + +void AS3935Component::tune_antenna() { + ESP_LOGI(TAG, "Starting antenna tuning..."); + uint8_t div_ratio = this->read_div_ratio(); + uint8_t tune_val = this->read_capacitance(); + ESP_LOGI(TAG, "Division Ratio is set to: %d", div_ratio); + ESP_LOGI(TAG, "Internal Capacitor is set to: %d", tune_val); + ESP_LOGI(TAG, "Displaying oscillator on INT pin. Measure its frequency - multiply value by Division Ratio"); + this->display_oscillator(true, ANTFREQ); +} + uint8_t AS3935Component::read_register_(uint8_t reg, uint8_t mask) { uint8_t value = this->read_register(reg); value &= (~mask); diff --git a/esphome/components/as3935/as3935.h b/esphome/components/as3935/as3935.h index a8af703a59..dc590c268e 100644 --- a/esphome/components/as3935/as3935.h +++ b/esphome/components/as3935/as3935.h @@ -13,6 +13,9 @@ namespace esphome { namespace as3935 { +static const uint8_t DIRECT_COMMAND = 0x96; +static const uint8_t ANTFREQ = 3; + enum AS3935RegisterNames { AFE_GAIN = 0x00, THRESHOLD, @@ -30,6 +33,7 @@ enum AS3935RegisterNames { }; enum AS3935RegisterMasks { + WIPE_ALL = 0x0, GAIN_MASK = 0x3E, SPIKE_MASK = 0xF, IO_MASK = 0xC1, @@ -44,6 +48,7 @@ enum AS3935RegisterMasks { NOISE_FLOOR_MASK = 0x70, OSC_MASK = 0xE0, CALIB_MASK = 0x7F, + CALIB_MASK_NOK = 0xBF, DIV_MASK = 0x3F }; @@ -90,6 +95,13 @@ class AS3935Component : public Component { void write_div_ratio(uint8_t div_ratio); void set_capacitance(uint8_t capacitance) { capacitance_ = capacitance; } void write_capacitance(uint8_t capacitance); + uint8_t read_div_ratio(); + uint8_t read_capacitance(); + bool calibrate_oscillator(); + void display_oscillator(bool state, uint8_t osc); + void tune_antenna(); + void set_tune_antenna(bool tune_antenna) { tune_antenna_ = tune_antenna; } + void set_calibration(bool calibration) { calibration_ = calibration; } protected: uint8_t read_interrupt_register_(); @@ -112,6 +124,8 @@ class AS3935Component : public Component { bool mask_disturber_; uint8_t div_ratio_; uint8_t capacitance_; + bool tune_antenna_; + bool calibration_; }; } // namespace as3935 diff --git a/esphome/const.py b/esphome/const.py index 01555c35ec..fc67651193 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -783,6 +783,7 @@ CONF_TRACES = "traces" CONF_TRANSITION_LENGTH = "transition_length" CONF_TRIGGER_ID = "trigger_id" CONF_TRIGGER_PIN = "trigger_pin" +CONF_TUNE_ANTENNA = "tune_antenna" CONF_TURN_OFF_ACTION = "turn_off_action" CONF_TURN_ON_ACTION = "turn_on_action" CONF_TVOC = "tvoc" From 2fc4e8827131f3199a2e15c64201eed1312d0688 Mon Sep 17 00:00:00 2001 From: Michael Hansen Date: Wed, 11 Oct 2023 20:51:29 -0500 Subject: [PATCH 0292/2101] Small fixes for voice assistant (#5513) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- .../i2s_audio/speaker/i2s_audio_speaker.cpp | 26 +++++++++----- .../voice_assistant/voice_assistant.cpp | 36 ++++++++++++++----- 2 files changed, 45 insertions(+), 17 deletions(-) diff --git a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp index a0934e3844..592a27b739 100644 --- a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +++ b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp @@ -11,7 +11,7 @@ namespace esphome { namespace i2s_audio { -static const size_t BUFFER_COUNT = 10; +static const size_t BUFFER_COUNT = 20; static const char *const TAG = "i2s_audio.speaker"; @@ -19,7 +19,7 @@ void I2SAudioSpeaker::setup() { ESP_LOGCONFIG(TAG, "Setting up I2S Audio Speaker..."); this->buffer_queue_ = xQueueCreate(BUFFER_COUNT, sizeof(DataEvent)); - this->event_queue_ = xQueueCreate(20, sizeof(TaskEvent)); + this->event_queue_ = xQueueCreate(BUFFER_COUNT, sizeof(TaskEvent)); } void I2SAudioSpeaker::start() { this->state_ = speaker::STATE_STARTING; } @@ -47,7 +47,7 @@ void I2SAudioSpeaker::player_task(void *params) { .communication_format = I2S_COMM_FORMAT_STAND_I2S, .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, .dma_buf_count = 8, - .dma_buf_len = 1024, + .dma_buf_len = 128, .use_apll = false, .tx_desc_auto_clear = true, .fixed_mclk = I2S_PIN_NO_CHANGE, @@ -60,7 +60,17 @@ void I2SAudioSpeaker::player_task(void *params) { } #endif - i2s_driver_install(this_speaker->parent_->get_port(), &config, 0, nullptr); + esp_err_t err = i2s_driver_install(this_speaker->parent_->get_port(), &config, 0, nullptr); + if (err != ESP_OK) { + event.type = TaskEventType::WARNING; + event.err = err; + xQueueSend(this_speaker->event_queue_, &event, 0); + event.type = TaskEventType::STOPPED; + xQueueSend(this_speaker->event_queue_, &event, 0); + while (true) { + delay(10); + } + } #if SOC_I2S_SUPPORTS_DAC if (this_speaker->internal_dac_mode_ == I2S_DAC_CHANNEL_DISABLE) { @@ -88,9 +98,7 @@ void I2SAudioSpeaker::player_task(void *params) { } if (data_event.stop) { // Stop signal from main thread - while (xQueueReceive(this_speaker->buffer_queue_, &data_event, 0) == pdTRUE) { - // Flush queue - } + xQueueReset(this_speaker->buffer_queue_); // Flush queue break; } size_t bytes_written; @@ -103,7 +111,7 @@ void I2SAudioSpeaker::player_task(void *params) { uint32_t sample = (buffer[current] << 16) | (buffer[current] & 0xFFFF); esp_err_t err = i2s_write(this_speaker->parent_->get_port(), &sample, sizeof(sample), &bytes_written, - (100 / portTICK_PERIOD_MS)); + (10 / portTICK_PERIOD_MS)); if (err != ESP_OK) { event = {.type = TaskEventType::WARNING, .err = err}; xQueueSend(this_speaker->event_queue_, &event, portMAX_DELAY); @@ -122,7 +130,6 @@ void I2SAudioSpeaker::player_task(void *params) { event.type = TaskEventType::STOPPING; xQueueSend(this_speaker->event_queue_, &event, portMAX_DELAY); - i2s_stop(this_speaker->parent_->get_port()); i2s_driver_uninstall(this_speaker->parent_->get_port()); event.type = TaskEventType::STOPPED; @@ -162,6 +169,7 @@ void I2SAudioSpeaker::watch_() { vTaskDelete(this->player_task_handle_); this->player_task_handle_ = nullptr; this->parent_->unlock(); + xQueueReset(this->buffer_queue_); break; case TaskEventType::WARNING: ESP_LOGW(TAG, "Error writing to I2S: %s", esp_err_to_name(event.err)); diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index 802ae508ff..448df61d80 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -188,6 +188,9 @@ void VoiceAssistant::loop() { } else { ESP_LOGD(TAG, "VAD detected speech"); this->set_state_(State::START_PIPELINE, State::STREAMING_MICROPHONE); + + // Reset for next time + this->vad_counter_ = 0; } } else { if (this->vad_counter_ > 0) { @@ -270,13 +273,18 @@ void VoiceAssistant::loop() { this->speaker_buffer_size_ += len; } } else { - ESP_LOGW(TAG, "Speaker buffer full."); + ESP_LOGW(TAG, "Receive buffer full."); } if (this->speaker_buffer_size_ > 0) { size_t written = this->speaker_->play(this->speaker_buffer_, this->speaker_buffer_size_); - memmove(this->speaker_buffer_, this->speaker_buffer_ + written, this->speaker_buffer_size_ - written); - this->speaker_buffer_size_ -= written; - this->speaker_buffer_index_ -= written; + if (written > 0) { + memmove(this->speaker_buffer_, this->speaker_buffer_ + written, this->speaker_buffer_size_ - written); + this->speaker_buffer_size_ -= written; + this->speaker_buffer_index_ -= written; + this->set_timeout("speaker-timeout", 1000, [this]() { this->speaker_->stop(); }); + } else { + ESP_LOGW(TAG, "Speaker buffer full."); + } } playing = this->speaker_->is_running(); } @@ -287,7 +295,10 @@ void VoiceAssistant::loop() { } #endif if (playing) { - this->set_timeout("playing", 100, [this]() { this->set_state_(State::IDLE, State::IDLE); }); + this->set_timeout("playing", 100, [this]() { + this->cancel_timeout("speaker-timeout"); + this->set_state_(State::IDLE, State::IDLE); + }); } break; } @@ -483,8 +494,17 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { } case api::enums::VOICE_ASSISTANT_RUN_END: { ESP_LOGD(TAG, "Assist Pipeline ended"); - if (this->state_ != State::STREAMING_RESPONSE && this->state_ != State::IDLE) { - this->set_state_(State::IDLE, State::IDLE); + if (this->state_ == State::STREAMING_MICROPHONE) { +#ifdef USE_ESP_ADF + if (this->use_wake_word_) { + rb_reset(this->ring_buffer_); + // No need to stop the microphone since we didn't use the speaker + this->set_state_(State::WAIT_FOR_VAD, State::WAITING_FOR_VAD); + } else +#endif + { + this->set_state_(State::IDLE, State::IDLE); + } } this->end_trigger_->trigger(); break; @@ -500,7 +520,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { } } if (code == "wake-word-timeout" || code == "wake_word_detection_aborted") { - this->set_state_(State::STOP_MICROPHONE, State::IDLE); + // Don't change state here since either the "tts-end" or "run-end" events will do it. return; } ESP_LOGE(TAG, "Error: %s - %s", code.c_str(), message.c_str()); From 689dcd1e2459f70f092222e3826367061b64d3e5 Mon Sep 17 00:00:00 2001 From: Daniel Baulig Date: Wed, 11 Oct 2023 18:55:01 -0700 Subject: [PATCH 0293/2101] Add detail param to allow listing of select options in WebServer REST API (#5503) --- esphome/components/web_server/web_server.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index e350e1b140..dec8fb8e21 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -805,7 +805,12 @@ void WebServer::handle_select_request(AsyncWebServerRequest *request, const UrlM continue; if (request->method() == HTTP_GET) { - std::string data = this->select_json(obj, obj->state, DETAIL_STATE); + auto detail = DETAIL_STATE; + auto *param = request->getParam("detail"); + if (param && param->value() == "all") { + detail = DETAIL_ALL; + } + std::string data = this->select_json(obj, obj->state, detail); request->send(200, "application/json", data.c_str()); return; } From 11727391ad0b5d029eef2f54b4113b1b049a03ce Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 12 Oct 2023 15:14:43 +1300 Subject: [PATCH 0294/2101] Bump version to 2023.11.0-dev --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index fc67651193..eb7a5dab09 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2023.10.0-dev" +__version__ = "2023.11.0-dev" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 54363f1246eeab37375b0c37748b18e8c7570d80 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 12 Oct 2023 15:14:43 +1300 Subject: [PATCH 0295/2101] Bump version to 2023.10.0b1 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index fc67651193..5a5b683c2d 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2023.10.0-dev" +__version__ = "2023.10.0b1" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From f4ce8b8b6c6ea414f9d05fa7dc0048e1582d4b40 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 12 Oct 2023 15:52:57 +1300 Subject: [PATCH 0296/2101] Bump curl to 7.74.0-1.3+deb11u10 (#5517) --- docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 99f15d64b2..5ca36d1c13 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -26,7 +26,7 @@ RUN \ python3-venv=3.9.2-3 \ iputils-ping=3:20210202-1 \ git=1:2.30.2-1+deb11u2 \ - curl=7.74.0-1.3+deb11u9 \ + curl=7.74.0-1.3+deb11u10 \ openssh-client=1:8.4p1-5+deb11u2 \ python3-cffi=1.14.5-1 \ libcairo2=1.16.0-5 \ From 2910eb2ef70272719a0d2532e7e426d3d59aceb6 Mon Sep 17 00:00:00 2001 From: Nippey Date: Thu, 12 Oct 2023 19:56:30 +0200 Subject: [PATCH 0297/2101] Update htu21d.cpp, fix publishing of heater level (#5520) --- esphome/components/htu21d/htu21d.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/htu21d/htu21d.cpp b/esphome/components/htu21d/htu21d.cpp index 5030ac4d0f..a8133ae32e 100644 --- a/esphome/components/htu21d/htu21d.cpp +++ b/esphome/components/htu21d/htu21d.cpp @@ -76,7 +76,7 @@ void HTU21DComponent::update() { if (this->humidity_ != nullptr) this->humidity_->publish_state(humidity); if (this->heater_ != nullptr) - this->heater_->publish_state(humidity); + this->heater_->publish_state(heater_level); this->status_clear_warning(); } From 04b708c336ff93c907fcbbc3a7ab7a812293f8e7 Mon Sep 17 00:00:00 2001 From: NP v/d Spek Date: Thu, 12 Oct 2023 20:20:31 +0200 Subject: [PATCH 0298/2101] Splits FastLed test scripts out of test1.yaml (#5522) --- tests/test1.1.yaml | 205 +++++++++++++++++++++++++++++++++++++++++++++ tests/test1.yaml | 139 ------------------------------ 2 files changed, 205 insertions(+), 139 deletions(-) create mode 100644 tests/test1.1.yaml diff --git a/tests/test1.1.yaml b/tests/test1.1.yaml new file mode 100644 index 0000000000..3bad4e0492 --- /dev/null +++ b/tests/test1.1.yaml @@ -0,0 +1,205 @@ +--- +substitutions: + devicename: test1_1 + sensorname: my + textname: template + roomname: fastled_room + +esphome: + name: test1-1 + name_add_mac_suffix: true + platform: ESP32 + board: nodemcu-32s + platformio_options: + board_build.partitions: huge_app.csv + on_loop: + then: + - light.addressable_set: + id: addr1 + range_from: 0 + range_to: 100 + red: 100% + green: !lambda "return 255;" + blue: 0% + white: 100% + +wled: + +wifi: + networks: + - ssid: "MySSID" + password: "password1" + +uart: + - id: adalight_uart + tx_pin: GPIO25 + rx_pin: GPIO26 + baud_rate: 115200 + rx_buffer_size: 1024 + +adalight: + +network: + +e131: + +power_supply: + id: atx_power_supply + enable_time: 20ms + keep_on_time: 10s + pin: + number: 13 + inverted: true + +i2c: + sda: 21 + scl: 22 + scan: true + frequency: 100kHz + setup_priority: -100 + id: i2c_bus + +pca9685: + frequency: 500 + address: 0x0 + i2c_id: i2c_bus + +output: + - platform: pca9685 + id: pca_0 + channel: 0 + - platform: pca9685 + id: pca_1 + channel: 1 + - platform: pca9685 + id: pca_2 + channel: 2 + +light: + - platform: rgb + name: Living Room Lights + id: ${roomname}_lights + red: pca_0 + green: pca_1 + blue: pca_2 + - platform: fastled_clockless + id: addr1 + chipset: WS2811 + pin: GPIO23 + num_leds: 60 + rgb_order: BRG + max_refresh_rate: 20ms + power_supply: atx_power_supply + color_correct: [75%, 100%, 50%] + name: FastLED WS2811 Light + effects: + - addressable_color_wipe: + - addressable_color_wipe: + name: Color Wipe Effect With Custom Values + colors: + - red: 100% + green: 100% + blue: 100% + num_leds: 1 + - red: 0% + green: 0% + blue: 0% + num_leds: 1 + add_led_interval: 100ms + reverse: false + - addressable_scan: + - addressable_scan: + name: Scan Effect With Custom Values + move_interval: 100ms + - addressable_twinkle: + - addressable_twinkle: + name: Twinkle Effect With Custom Values + twinkle_probability: 5% + progress_interval: 4ms + - addressable_random_twinkle: + - addressable_random_twinkle: + name: Random Twinkle Effect With Custom Values + twinkle_probability: 5% + progress_interval: 32ms + - addressable_fireworks: + - addressable_fireworks: + name: Fireworks Effect With Custom Values + update_interval: 32ms + spark_probability: 10% + use_random_color: false + fade_out_rate: 120 + - addressable_flicker: + - addressable_flicker: + name: Flicker Effect With Custom Values + update_interval: 16ms + intensity: 5% + - addressable_lambda: + name: Test For Custom Lambda Effect + lambda: |- + if (initial_run) { + it[0] = current_color; + } + + - wled: + port: 11111 + + - adalight: + uart_id: adalight_uart + + - e131: + universe: 1 + + - automation: + name: Custom Effect + sequence: + - light.addressable_set: + id: addr1 + red: 100% + green: 100% + blue: 0% + - delay: 100ms + - light.addressable_set: + id: addr1 + red: 0% + green: 100% + blue: 0% + + - platform: fastled_spi + id: addr2 + chipset: WS2801 + data_pin: GPIO23 + clock_pin: GPIO22 + data_rate: 2MHz + num_leds: 60 + rgb_order: BRG + name: FastLED SPI Light + - platform: neopixelbus + id: addr3 + name: Neopixelbus Light + gamma_correct: 2.8 + color_correct: [0.0, 0.0, 0.0, 0.0] + default_transition_length: 10s + power_supply: atx_power_supply + effects: + - addressable_flicker: + name: Flicker Effect With Custom Values + update_interval: 16ms + intensity: 5% + type: GRBW + variant: SK6812 + method: ESP32_I2S_0 + num_leds: 60 + pin: GPIO23 + - platform: partition + name: Partition Light + segments: + - id: addr1 + from: 0 + to: 0 + - id: addr2 + from: 1 + to: 10 + - id: addr2 + from: 20 + to: 25 + - single_light_id: ${roomname}_lights diff --git a/tests/test1.yaml b/tests/test1.yaml index c504012481..6d42e325d8 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -25,14 +25,6 @@ esphome: then: - lambda: >- ESP_LOGV("main", "ON LOOP!"); - - light.addressable_set: - id: addr1 - range_from: 0 - range_to: 100 - red: 100% - green: !lambda "return 255;" - blue: 0% - white: 100% - http_request.get: url: https://esphome.io headers: @@ -222,12 +214,6 @@ uart: - lambda: UARTDebug::log_string(direction, bytes); - lambda: UARTDebug::log_int(direction, bytes, ','); - lambda: UARTDebug::log_binary(direction, bytes, ';'); - - - id: adalight_uart - tx_pin: GPIO25 - rx_pin: GPIO26 - baud_rate: 115200 - rx_buffer_size: 1024 - id: ld2410_uart tx_pin: 18 rx_pin: 23 @@ -300,10 +286,6 @@ as3935_spi: cs_pin: GPIO12 irq_pin: GPIO13 -wled: - -adalight: - esp32_ble: io_capability: keyboard_only @@ -2073,8 +2055,6 @@ output: ud_pin: GPIO27 initial_value: 0.5 -e131: - light: - platform: binary name: Desk Lamp @@ -2163,125 +2143,6 @@ light: brightness: pca_6 cold_white_color_temperature: 153 mireds warm_white_color_temperature: 500 mireds - - platform: fastled_clockless - id: addr1 - chipset: WS2811 - pin: GPIO23 - num_leds: 60 - rgb_order: BRG - max_refresh_rate: 20ms - power_supply: atx_power_supply - color_correct: [75%, 100%, 50%] - name: FastLED WS2811 Light - effects: - - addressable_color_wipe: - - addressable_color_wipe: - name: Color Wipe Effect With Custom Values - colors: - - red: 100% - green: 100% - blue: 100% - num_leds: 1 - - red: 0% - green: 0% - blue: 0% - num_leds: 1 - add_led_interval: 100ms - reverse: false - - addressable_scan: - - addressable_scan: - name: Scan Effect With Custom Values - move_interval: 100ms - - addressable_twinkle: - - addressable_twinkle: - name: Twinkle Effect With Custom Values - twinkle_probability: 5% - progress_interval: 4ms - - addressable_random_twinkle: - - addressable_random_twinkle: - name: Random Twinkle Effect With Custom Values - twinkle_probability: 5% - progress_interval: 32ms - - addressable_fireworks: - - addressable_fireworks: - name: Fireworks Effect With Custom Values - update_interval: 32ms - spark_probability: 10% - use_random_color: false - fade_out_rate: 120 - - addressable_flicker: - - addressable_flicker: - name: Flicker Effect With Custom Values - update_interval: 16ms - intensity: 5% - - addressable_lambda: - name: Test For Custom Lambda Effect - lambda: |- - if (initial_run) { - it[0] = current_color; - } - - - wled: - port: 11111 - - - adalight: - uart_id: adalight_uart - - - automation: - name: Custom Effect - sequence: - - light.addressable_set: - id: addr1 - red: 100% - green: 100% - blue: 0% - - delay: 100ms - - light.addressable_set: - id: addr1 - red: 0% - green: 100% - blue: 0% - - e131: - universe: 1 - - platform: fastled_spi - id: addr2 - chipset: WS2801 - data_pin: GPIO23 - clock_pin: GPIO22 - data_rate: 2MHz - num_leds: 60 - rgb_order: BRG - name: FastLED SPI Light - - platform: neopixelbus - id: addr3 - name: Neopixelbus Light - gamma_correct: 2.8 - color_correct: [0.0, 0.0, 0.0, 0.0] - default_transition_length: 10s - power_supply: atx_power_supply - effects: - - addressable_flicker: - name: Flicker Effect With Custom Values - update_interval: 16ms - intensity: 5% - type: GRBW - variant: SK6812 - method: ESP32_I2S_0 - num_leds: 60 - pin: GPIO23 - - platform: partition - name: Partition Light - segments: - - id: addr1 - from: 0 - to: 0 - - id: addr2 - from: 1 - to: 10 - - id: addr2 - from: 20 - to: 25 - - single_light_id: ${roomname}_lights remote_transmitter: - pin: 32 From 7c890d8ebc2daf91268d1758548076880d0b7c64 Mon Sep 17 00:00:00 2001 From: Cossid <83468485+Cossid@users.noreply.github.com> Date: Thu, 12 Oct 2023 14:09:07 -0500 Subject: [PATCH 0299/2101] BD5758D - Add delays and ACKs (#5524) --- esphome/components/bp5758d/bp5758d.cpp | 30 ++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/esphome/components/bp5758d/bp5758d.cpp b/esphome/components/bp5758d/bp5758d.cpp index 71a81f7e6c..87c4165275 100644 --- a/esphome/components/bp5758d/bp5758d.cpp +++ b/esphome/components/bp5758d/bp5758d.cpp @@ -17,12 +17,16 @@ static const uint8_t BP5758D_ADDR_START_2CH = 0b00100000; static const uint8_t BP5758D_ADDR_START_5CH = 0b00110000; static const uint8_t BP5758D_ALL_DATA_CHANNEL_ENABLEMENT = 0b00011111; +static const uint8_t BP5758D_DELAY = 2; + void BP5758D::setup() { ESP_LOGCONFIG(TAG, "Setting up BP5758D Output Component..."); this->data_pin_->setup(); this->data_pin_->digital_write(false); + delayMicroseconds(BP5758D_DELAY); this->clock_pin_->setup(); this->clock_pin_->digital_write(false); + delayMicroseconds(BP5758D_DELAY); this->channel_current_.resize(5, 0); this->pwm_amounts_.resize(5, 0); } @@ -39,11 +43,11 @@ void BP5758D::loop() { uint8_t data[17]; if (this->pwm_amounts_[0] == 0 && this->pwm_amounts_[1] == 0 && this->pwm_amounts_[2] == 0 && this->pwm_amounts_[3] == 0 && this->pwm_amounts_[4] == 0) { - for (int i = 1; i < 16; i++) + for (int i = 1; i < 17; i++) data[i] = 0; // First turn all channels off - data[0] = BP5758D_MODEL_ID + BP5758D_ADDR_START_3CH; + data[0] = BP5758D_MODEL_ID + BP5758D_ADDR_START_5CH; this->write_buffer_(data, 17); // Then sleep data[0] = BP5758D_MODEL_ID + BP5758D_ADDR_STANDBY; @@ -123,28 +127,42 @@ void BP5758D::set_channel_value_(uint8_t channel, uint16_t value) { void BP5758D::set_channel_current_(uint8_t channel, uint8_t current) { this->channel_current_[channel] = current; } void BP5758D::write_bit_(bool value) { - this->clock_pin_->digital_write(false); this->data_pin_->digital_write(value); + delayMicroseconds(BP5758D_DELAY); this->clock_pin_->digital_write(true); + delayMicroseconds(BP5758D_DELAY); + this->clock_pin_->digital_write(false); + delayMicroseconds(BP5758D_DELAY); } void BP5758D::write_byte_(uint8_t data) { for (uint8_t mask = 0x80; mask; mask >>= 1) { this->write_bit_(data & mask); } - this->clock_pin_->digital_write(false); - this->data_pin_->digital_write(true); + + // ack bit + this->data_pin_->pin_mode(gpio::FLAG_INPUT); this->clock_pin_->digital_write(true); + delayMicroseconds(BP5758D_DELAY); + this->clock_pin_->digital_write(false); + delayMicroseconds(BP5758D_DELAY); + this->data_pin_->pin_mode(gpio::FLAG_OUTPUT); } void BP5758D::write_buffer_(uint8_t *buffer, uint8_t size) { this->data_pin_->digital_write(false); + delayMicroseconds(BP5758D_DELAY); + this->clock_pin_->digital_write(false); + delayMicroseconds(BP5758D_DELAY); + for (uint32_t i = 0; i < size; i++) { this->write_byte_(buffer[i]); } - this->clock_pin_->digital_write(false); + this->clock_pin_->digital_write(true); + delayMicroseconds(BP5758D_DELAY); this->data_pin_->digital_write(true); + delayMicroseconds(BP5758D_DELAY); } } // namespace bp5758d From 33ebfd221ea5c0000a67da326eff16dcbe71581f Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 13 Oct 2023 12:46:46 +1300 Subject: [PATCH 0300/2101] Update Improv BLE component (#5518) --- .../esp32_ble_server/ble_service.cpp | 2 + .../components/esp32_ble_server/ble_service.h | 2 +- esphome/components/esp32_improv/__init__.py | 2 +- .../esp32_improv/esp32_improv_component.cpp | 79 +++++++++++-------- .../esp32_improv/esp32_improv_component.h | 29 +++++-- esphome/components/output/__init__.py | 1 + esphome/core/defines.h | 3 +- 7 files changed, 79 insertions(+), 39 deletions(-) diff --git a/esphome/components/esp32_ble_server/ble_service.cpp b/esphome/components/esp32_ble_server/ble_service.cpp index 4fcd2e3e79..e5aaebc137 100644 --- a/esphome/components/esp32_ble_server/ble_service.cpp +++ b/esphome/components/esp32_ble_server/ble_service.cpp @@ -90,6 +90,8 @@ void BLEService::stop() { ESP_LOGE(TAG, "esp_ble_gatts_stop_service failed: %d", err); return; } + esp32_ble::global_ble->get_advertising()->remove_service_uuid(this->uuid_); + esp32_ble::global_ble->get_advertising()->start(); this->running_state_ = STOPPING; } diff --git a/esphome/components/esp32_ble_server/ble_service.h b/esphome/components/esp32_ble_server/ble_service.h index 2766c931a7..93b4217517 100644 --- a/esphome/components/esp32_ble_server/ble_service.h +++ b/esphome/components/esp32_ble_server/ble_service.h @@ -7,11 +7,11 @@ #ifdef USE_ESP32 +#include #include #include #include #include -#include namespace esphome { namespace esp32_ble_server { diff --git a/esphome/components/esp32_improv/__init__.py b/esphome/components/esp32_improv/__init__.py index ae7f0b6427..fba2e55ae8 100644 --- a/esphome/components/esp32_improv/__init__.py +++ b/esphome/components/esp32_improv/__init__.py @@ -4,7 +4,7 @@ from esphome.components import binary_sensor, output, esp32_ble_server from esphome.const import CONF_ID -AUTO_LOAD = ["binary_sensor", "output", "esp32_ble_server"] +AUTO_LOAD = ["esp32_ble_server"] CODEOWNERS = ["@jesserockz"] CONFLICTS_WITH = ["esp32_ble_beacon"] DEPENDENCIES = ["wifi", "esp32"] diff --git a/esphome/components/esp32_improv/esp32_improv_component.cpp b/esphome/components/esp32_improv/esp32_improv_component.cpp index 85013c006b..5bdf7d19fe 100644 --- a/esphome/components/esp32_improv/esp32_improv_component.cpp +++ b/esphome/components/esp32_improv/esp32_improv_component.cpp @@ -18,6 +18,17 @@ ESP32ImprovComponent::ESP32ImprovComponent() { global_improv_component = this; } void ESP32ImprovComponent::setup() { this->service_ = global_ble_server->create_service(improv::SERVICE_UUID, true); this->setup_characteristics(); + +#ifdef USE_BINARY_SENSOR + if (this->authorizer_ != nullptr) { + this->authorizer_->add_on_state_callback([this](bool state) { + if (state) { + this->authorized_start_ = millis(); + this->identify_start_ = 0; + } + }); + } +#endif } void ESP32ImprovComponent::setup_characteristics() { @@ -50,8 +61,10 @@ void ESP32ImprovComponent::setup_characteristics() { BLEDescriptor *capabilities_descriptor = new BLE2902(); this->capabilities_->add_descriptor(capabilities_descriptor); uint8_t capabilities = 0x00; +#ifdef USE_OUTPUT if (this->status_indicator_ != nullptr) capabilities |= improv::CAPABILITY_IDENTIFY; +#endif this->capabilities_->set_value(capabilities); this->setup_complete_ = true; } @@ -63,8 +76,7 @@ void ESP32ImprovComponent::loop() { switch (this->state_) { case improv::STATE_STOPPED: - if (this->status_indicator_ != nullptr) - this->status_indicator_->turn_off(); + this->set_status_indicator_state_(false); if (this->service_->is_created() && this->should_start_ && this->setup_complete_) { if (this->service_->is_running()) { @@ -80,14 +92,17 @@ void ESP32ImprovComponent::loop() { } break; case improv::STATE_AWAITING_AUTHORIZATION: { - if (this->authorizer_ == nullptr || this->authorizer_->state) { +#ifdef USE_BINARY_SENSOR + if (this->authorizer_ == nullptr || + (this->authorized_start_ != 0 && ((now - this->authorized_start_) < this->authorized_duration_))) { this->set_state_(improv::STATE_AUTHORIZED); - this->authorized_start_ = now; - } else { - if (this->status_indicator_ != nullptr) { - if (!this->check_identify_()) - this->status_indicator_->turn_on(); - } + } else +#else + this->set_state_(improv::STATE_AUTHORIZED); +#endif + { + if (!this->check_identify_()) + this->set_status_indicator_state_(true); } break; } @@ -99,25 +114,13 @@ void ESP32ImprovComponent::loop() { return; } } - if (this->status_indicator_ != nullptr) { - if (!this->check_identify_()) { - if ((now % 1000) < 500) { - this->status_indicator_->turn_on(); - } else { - this->status_indicator_->turn_off(); - } - } + if (!this->check_identify_()) { + this->set_status_indicator_state_((now % 1000) < 500); } break; } case improv::STATE_PROVISIONING: { - if (this->status_indicator_ != nullptr) { - if ((now % 200) < 100) { - this->status_indicator_->turn_on(); - } else { - this->status_indicator_->turn_off(); - } - } + this->set_status_indicator_state_((now % 200) < 100); if (wifi::global_wifi_component->is_connected()) { wifi::global_wifi_component->save_wifi_sta(this->connecting_sta_.get_ssid(), this->connecting_sta_.get_password()); @@ -142,13 +145,27 @@ void ESP32ImprovComponent::loop() { } case improv::STATE_PROVISIONED: { this->incoming_data_.clear(); - if (this->status_indicator_ != nullptr) - this->status_indicator_->turn_off(); + this->set_status_indicator_state_(false); break; } } } +void ESP32ImprovComponent::set_status_indicator_state_(bool state) { +#ifdef USE_OUTPUT + if (this->status_indicator_ == nullptr) + return; + if (this->status_indicator_state_ == state) + return; + this->status_indicator_state_ = state; + if (state) { + this->status_indicator_->turn_on(); + } else { + this->status_indicator_->turn_off(); + } +#endif +} + bool ESP32ImprovComponent::check_identify_() { uint32_t now = millis(); @@ -156,11 +173,7 @@ bool ESP32ImprovComponent::check_identify_() { if (identify) { uint32_t time = now % 1000; - if (time < 600 && time % 200 < 100) { - this->status_indicator_->turn_on(); - } else { - this->status_indicator_->turn_off(); - } + this->set_status_indicator_state_(time < 600 && time % 200 < 100); } return identify; } @@ -213,8 +226,12 @@ float ESP32ImprovComponent::get_setup_priority() const { return setup_priority:: void ESP32ImprovComponent::dump_config() { ESP_LOGCONFIG(TAG, "ESP32 Improv:"); +#ifdef USE_BINARY_SENSOR LOG_BINARY_SENSOR(" ", "Authorizer", this->authorizer_); +#endif +#ifdef USE_OUTPUT ESP_LOGCONFIG(TAG, " Status Indicator: '%s'", YESNO(this->status_indicator_ != nullptr)); +#endif } void ESP32ImprovComponent::process_incoming_data_() { diff --git a/esphome/components/esp32_improv/esp32_improv_component.h b/esphome/components/esp32_improv/esp32_improv_component.h index 1a142c94b6..ba9892d6a5 100644 --- a/esphome/components/esp32_improv/esp32_improv_component.h +++ b/esphome/components/esp32_improv/esp32_improv_component.h @@ -1,14 +1,22 @@ #pragma once -#include "esphome/components/binary_sensor/binary_sensor.h" -#include "esphome/components/esp32_ble_server/ble_characteristic.h" -#include "esphome/components/esp32_ble_server/ble_server.h" -#include "esphome/components/output/binary_output.h" -#include "esphome/components/wifi/wifi_component.h" #include "esphome/core/component.h" +#include "esphome/core/defines.h" #include "esphome/core/helpers.h" #include "esphome/core/preferences.h" +#include "esphome/components/esp32_ble_server/ble_characteristic.h" +#include "esphome/components/esp32_ble_server/ble_server.h" +#include "esphome/components/wifi/wifi_component.h" + +#ifdef USE_BINARY_SENSOR +#include "esphome/components/binary_sensor/binary_sensor.h" +#endif + +#ifdef USE_OUTPUT +#include "esphome/components/output/binary_output.h" +#endif + #include #ifdef USE_ESP32 @@ -34,8 +42,12 @@ class ESP32ImprovComponent : public Component, public BLEServiceComponent { void stop() override; bool is_active() const { return this->state_ != improv::STATE_STOPPED; } +#ifdef USE_BINARY_SENSOR void set_authorizer(binary_sensor::BinarySensor *authorizer) { this->authorizer_ = authorizer; } +#endif +#ifdef USE_OUTPUT void set_status_indicator(output::BinaryOutput *status_indicator) { this->status_indicator_ = status_indicator; } +#endif void set_identify_duration(uint32_t identify_duration) { this->identify_duration_ = identify_duration; } void set_authorized_duration(uint32_t authorized_duration) { this->authorized_duration_ = authorized_duration; } @@ -58,12 +70,19 @@ class ESP32ImprovComponent : public Component, public BLEServiceComponent { BLECharacteristic *rpc_response_; BLECharacteristic *capabilities_; +#ifdef USE_BINARY_SENSOR binary_sensor::BinarySensor *authorizer_{nullptr}; +#endif +#ifdef USE_OUTPUT output::BinaryOutput *status_indicator_{nullptr}; +#endif improv::State state_{improv::STATE_STOPPED}; improv::Error error_state_{improv::ERROR_NONE}; + bool status_indicator_state_{false}; + void set_status_indicator_state_(bool state); + void set_state_(improv::State state); void set_error_(improv::Error error); void send_response_(std::vector &response); diff --git a/esphome/components/output/__init__.py b/esphome/components/output/__init__.py index 4f1fb33fe7..726d1ac084 100644 --- a/esphome/components/output/__init__.py +++ b/esphome/components/output/__init__.py @@ -106,4 +106,5 @@ async def output_set_level_to_code(config, action_id, template_arg, args): async def to_code(config): + cg.add_define("USE_OUTPUT") cg.add_global(output_ns.using) diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 1e0df74eec..71493119c0 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -37,6 +37,7 @@ #define USE_OTA #define USE_OTA_PASSWORD #define USE_OTA_STATE_CALLBACK +#define USE_OUTPUT #define USE_POWER_SUPPLY #define USE_QR_CODE #define USE_SELECT @@ -117,6 +118,6 @@ #endif // Disabled feature flags -//#define USE_BSEC // Requires a library with proprietary license. +// #define USE_BSEC // Requires a library with proprietary license. #define USE_DASHBOARD_IMPORT From f5c12b50cea418ca0b8315c294575089f529d120 Mon Sep 17 00:00:00 2001 From: Cossid <83468485+Cossid@users.noreply.github.com> Date: Thu, 12 Oct 2023 18:51:19 -0500 Subject: [PATCH 0301/2101] SM10BIT_BASE - Add delays and ACKs, clear all channels before sleeping. (#5526) --- .../components/sm10bit_base/sm10bit_base.cpp | 31 +++++++++++++++---- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/esphome/components/sm10bit_base/sm10bit_base.cpp b/esphome/components/sm10bit_base/sm10bit_base.cpp index 9c7abb48e2..d380f31c6f 100644 --- a/esphome/components/sm10bit_base/sm10bit_base.cpp +++ b/esphome/components/sm10bit_base/sm10bit_base.cpp @@ -11,6 +11,8 @@ static const uint8_t SM10BIT_ADDR_START_3CH = 0x8; static const uint8_t SM10BIT_ADDR_START_2CH = 0x10; static const uint8_t SM10BIT_ADDR_START_5CH = 0x18; +static const uint8_t SM10BIT_DELAY = 2; + // Power current values // HEX | Binary | RGB level | White level | Config value // 0x0 | 0000 | RGB 10mA | CW 5mA | 0 @@ -37,10 +39,13 @@ void Sm10BitBase::loop() { uint8_t data[12]; if (this->pwm_amounts_[0] == 0 && this->pwm_amounts_[1] == 0 && this->pwm_amounts_[2] == 0 && this->pwm_amounts_[3] == 0 && this->pwm_amounts_[4] == 0) { - // Off / Sleep - data[0] = this->model_id_ + SM10BIT_ADDR_STANDBY; for (int i = 1; i < 12; i++) data[i] = 0; + // First turn all channels off + data[0] = this->model_id_ + SM10BIT_ADDR_START_5CH; + this->write_buffer_(data, 12); + // Then sleep + data[0] = this->model_id_ + SM10BIT_ADDR_STANDBY; this->write_buffer_(data, 12); } else if (this->pwm_amounts_[0] == 0 && this->pwm_amounts_[1] == 0 && this->pwm_amounts_[2] == 0 && (this->pwm_amounts_[3] > 0 || this->pwm_amounts_[4] > 0)) { @@ -84,28 +89,42 @@ void Sm10BitBase::set_channel_value_(uint8_t channel, uint16_t value) { this->pwm_amounts_[channel] = value; } void Sm10BitBase::write_bit_(bool value) { - this->clock_pin_->digital_write(false); this->data_pin_->digital_write(value); + delayMicroseconds(SM10BIT_DELAY); this->clock_pin_->digital_write(true); + delayMicroseconds(SM10BIT_DELAY); + this->clock_pin_->digital_write(false); + delayMicroseconds(SM10BIT_DELAY); } void Sm10BitBase::write_byte_(uint8_t data) { for (uint8_t mask = 0x80; mask; mask >>= 1) { this->write_bit_(data & mask); } - this->clock_pin_->digital_write(false); - this->data_pin_->digital_write(true); + + // ack bit + this->data_pin_->pin_mode(gpio::FLAG_INPUT); this->clock_pin_->digital_write(true); + delayMicroseconds(SM10BIT_DELAY); + this->clock_pin_->digital_write(false); + delayMicroseconds(SM10BIT_DELAY); + this->data_pin_->pin_mode(gpio::FLAG_OUTPUT); } void Sm10BitBase::write_buffer_(uint8_t *buffer, uint8_t size) { this->data_pin_->digital_write(false); + delayMicroseconds(SM10BIT_DELAY); + this->clock_pin_->digital_write(false); + delayMicroseconds(SM10BIT_DELAY); + for (uint32_t i = 0; i < size; i++) { this->write_byte_(buffer[i]); } - this->clock_pin_->digital_write(false); + this->clock_pin_->digital_write(true); + delayMicroseconds(SM10BIT_DELAY); this->data_pin_->digital_write(true); + delayMicroseconds(SM10BIT_DELAY); } } // namespace sm10bit_base From da3e3903ddb36f5a5c3161bf6e23c8eadfdcfbbe Mon Sep 17 00:00:00 2001 From: Cossid <83468485+Cossid@users.noreply.github.com> Date: Thu, 12 Oct 2023 18:51:28 -0500 Subject: [PATCH 0302/2101] BP1658CJ - Clear all channels before sleeping. (#5525) --- esphome/components/bp1658cj/bp1658cj.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/esphome/components/bp1658cj/bp1658cj.cpp b/esphome/components/bp1658cj/bp1658cj.cpp index d3f3e71fed..05c3f790c2 100644 --- a/esphome/components/bp1658cj/bp1658cj.cpp +++ b/esphome/components/bp1658cj/bp1658cj.cpp @@ -37,10 +37,14 @@ void BP1658CJ::loop() { uint8_t data[12]; if (this->pwm_amounts_[0] == 0 && this->pwm_amounts_[1] == 0 && this->pwm_amounts_[2] == 0 && this->pwm_amounts_[3] == 0 && this->pwm_amounts_[4] == 0) { - // Off / Sleep - data[0] = BP1658CJ_MODEL_ID + BP1658CJ_ADDR_STANDBY; for (int i = 1; i < 12; i++) data[i] = 0; + + // First turn all channels off + data[0] = BP1658CJ_MODEL_ID + BP1658CJ_ADDR_START_5CH; + this->write_buffer_(data, 12); + // Then sleep + data[0] = BP1658CJ_MODEL_ID + BP1658CJ_ADDR_STANDBY; this->write_buffer_(data, 12); } else if (this->pwm_amounts_[0] == 0 && this->pwm_amounts_[1] == 0 && this->pwm_amounts_[2] == 0 && (this->pwm_amounts_[3] > 0 || this->pwm_amounts_[4] > 0)) { From d27e5e9c97ccb1035c3ef738f0fd22cb36227c7a Mon Sep 17 00:00:00 2001 From: Nippey Date: Thu, 12 Oct 2023 19:56:30 +0200 Subject: [PATCH 0303/2101] Update htu21d.cpp, fix publishing of heater level (#5520) --- esphome/components/htu21d/htu21d.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/htu21d/htu21d.cpp b/esphome/components/htu21d/htu21d.cpp index 5030ac4d0f..a8133ae32e 100644 --- a/esphome/components/htu21d/htu21d.cpp +++ b/esphome/components/htu21d/htu21d.cpp @@ -76,7 +76,7 @@ void HTU21DComponent::update() { if (this->humidity_ != nullptr) this->humidity_->publish_state(humidity); if (this->heater_ != nullptr) - this->heater_->publish_state(humidity); + this->heater_->publish_state(heater_level); this->status_clear_warning(); } From 6cce6d4c364104082b77a6ec12ede5243cbe11bb Mon Sep 17 00:00:00 2001 From: Cossid <83468485+Cossid@users.noreply.github.com> Date: Thu, 12 Oct 2023 14:09:07 -0500 Subject: [PATCH 0304/2101] BD5758D - Add delays and ACKs (#5524) --- esphome/components/bp5758d/bp5758d.cpp | 30 ++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/esphome/components/bp5758d/bp5758d.cpp b/esphome/components/bp5758d/bp5758d.cpp index 71a81f7e6c..87c4165275 100644 --- a/esphome/components/bp5758d/bp5758d.cpp +++ b/esphome/components/bp5758d/bp5758d.cpp @@ -17,12 +17,16 @@ static const uint8_t BP5758D_ADDR_START_2CH = 0b00100000; static const uint8_t BP5758D_ADDR_START_5CH = 0b00110000; static const uint8_t BP5758D_ALL_DATA_CHANNEL_ENABLEMENT = 0b00011111; +static const uint8_t BP5758D_DELAY = 2; + void BP5758D::setup() { ESP_LOGCONFIG(TAG, "Setting up BP5758D Output Component..."); this->data_pin_->setup(); this->data_pin_->digital_write(false); + delayMicroseconds(BP5758D_DELAY); this->clock_pin_->setup(); this->clock_pin_->digital_write(false); + delayMicroseconds(BP5758D_DELAY); this->channel_current_.resize(5, 0); this->pwm_amounts_.resize(5, 0); } @@ -39,11 +43,11 @@ void BP5758D::loop() { uint8_t data[17]; if (this->pwm_amounts_[0] == 0 && this->pwm_amounts_[1] == 0 && this->pwm_amounts_[2] == 0 && this->pwm_amounts_[3] == 0 && this->pwm_amounts_[4] == 0) { - for (int i = 1; i < 16; i++) + for (int i = 1; i < 17; i++) data[i] = 0; // First turn all channels off - data[0] = BP5758D_MODEL_ID + BP5758D_ADDR_START_3CH; + data[0] = BP5758D_MODEL_ID + BP5758D_ADDR_START_5CH; this->write_buffer_(data, 17); // Then sleep data[0] = BP5758D_MODEL_ID + BP5758D_ADDR_STANDBY; @@ -123,28 +127,42 @@ void BP5758D::set_channel_value_(uint8_t channel, uint16_t value) { void BP5758D::set_channel_current_(uint8_t channel, uint8_t current) { this->channel_current_[channel] = current; } void BP5758D::write_bit_(bool value) { - this->clock_pin_->digital_write(false); this->data_pin_->digital_write(value); + delayMicroseconds(BP5758D_DELAY); this->clock_pin_->digital_write(true); + delayMicroseconds(BP5758D_DELAY); + this->clock_pin_->digital_write(false); + delayMicroseconds(BP5758D_DELAY); } void BP5758D::write_byte_(uint8_t data) { for (uint8_t mask = 0x80; mask; mask >>= 1) { this->write_bit_(data & mask); } - this->clock_pin_->digital_write(false); - this->data_pin_->digital_write(true); + + // ack bit + this->data_pin_->pin_mode(gpio::FLAG_INPUT); this->clock_pin_->digital_write(true); + delayMicroseconds(BP5758D_DELAY); + this->clock_pin_->digital_write(false); + delayMicroseconds(BP5758D_DELAY); + this->data_pin_->pin_mode(gpio::FLAG_OUTPUT); } void BP5758D::write_buffer_(uint8_t *buffer, uint8_t size) { this->data_pin_->digital_write(false); + delayMicroseconds(BP5758D_DELAY); + this->clock_pin_->digital_write(false); + delayMicroseconds(BP5758D_DELAY); + for (uint32_t i = 0; i < size; i++) { this->write_byte_(buffer[i]); } - this->clock_pin_->digital_write(false); + this->clock_pin_->digital_write(true); + delayMicroseconds(BP5758D_DELAY); this->data_pin_->digital_write(true); + delayMicroseconds(BP5758D_DELAY); } } // namespace bp5758d From 969f6dbe131824ce0c9e6c23fe9a8b207887f991 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 13 Oct 2023 12:46:46 +1300 Subject: [PATCH 0305/2101] Update Improv BLE component (#5518) --- .../esp32_ble_server/ble_service.cpp | 2 + .../components/esp32_ble_server/ble_service.h | 2 +- esphome/components/esp32_improv/__init__.py | 2 +- .../esp32_improv/esp32_improv_component.cpp | 79 +++++++++++-------- .../esp32_improv/esp32_improv_component.h | 29 +++++-- esphome/components/output/__init__.py | 1 + esphome/core/defines.h | 3 +- 7 files changed, 79 insertions(+), 39 deletions(-) diff --git a/esphome/components/esp32_ble_server/ble_service.cpp b/esphome/components/esp32_ble_server/ble_service.cpp index 4fcd2e3e79..e5aaebc137 100644 --- a/esphome/components/esp32_ble_server/ble_service.cpp +++ b/esphome/components/esp32_ble_server/ble_service.cpp @@ -90,6 +90,8 @@ void BLEService::stop() { ESP_LOGE(TAG, "esp_ble_gatts_stop_service failed: %d", err); return; } + esp32_ble::global_ble->get_advertising()->remove_service_uuid(this->uuid_); + esp32_ble::global_ble->get_advertising()->start(); this->running_state_ = STOPPING; } diff --git a/esphome/components/esp32_ble_server/ble_service.h b/esphome/components/esp32_ble_server/ble_service.h index 2766c931a7..93b4217517 100644 --- a/esphome/components/esp32_ble_server/ble_service.h +++ b/esphome/components/esp32_ble_server/ble_service.h @@ -7,11 +7,11 @@ #ifdef USE_ESP32 +#include #include #include #include #include -#include namespace esphome { namespace esp32_ble_server { diff --git a/esphome/components/esp32_improv/__init__.py b/esphome/components/esp32_improv/__init__.py index ae7f0b6427..fba2e55ae8 100644 --- a/esphome/components/esp32_improv/__init__.py +++ b/esphome/components/esp32_improv/__init__.py @@ -4,7 +4,7 @@ from esphome.components import binary_sensor, output, esp32_ble_server from esphome.const import CONF_ID -AUTO_LOAD = ["binary_sensor", "output", "esp32_ble_server"] +AUTO_LOAD = ["esp32_ble_server"] CODEOWNERS = ["@jesserockz"] CONFLICTS_WITH = ["esp32_ble_beacon"] DEPENDENCIES = ["wifi", "esp32"] diff --git a/esphome/components/esp32_improv/esp32_improv_component.cpp b/esphome/components/esp32_improv/esp32_improv_component.cpp index 85013c006b..5bdf7d19fe 100644 --- a/esphome/components/esp32_improv/esp32_improv_component.cpp +++ b/esphome/components/esp32_improv/esp32_improv_component.cpp @@ -18,6 +18,17 @@ ESP32ImprovComponent::ESP32ImprovComponent() { global_improv_component = this; } void ESP32ImprovComponent::setup() { this->service_ = global_ble_server->create_service(improv::SERVICE_UUID, true); this->setup_characteristics(); + +#ifdef USE_BINARY_SENSOR + if (this->authorizer_ != nullptr) { + this->authorizer_->add_on_state_callback([this](bool state) { + if (state) { + this->authorized_start_ = millis(); + this->identify_start_ = 0; + } + }); + } +#endif } void ESP32ImprovComponent::setup_characteristics() { @@ -50,8 +61,10 @@ void ESP32ImprovComponent::setup_characteristics() { BLEDescriptor *capabilities_descriptor = new BLE2902(); this->capabilities_->add_descriptor(capabilities_descriptor); uint8_t capabilities = 0x00; +#ifdef USE_OUTPUT if (this->status_indicator_ != nullptr) capabilities |= improv::CAPABILITY_IDENTIFY; +#endif this->capabilities_->set_value(capabilities); this->setup_complete_ = true; } @@ -63,8 +76,7 @@ void ESP32ImprovComponent::loop() { switch (this->state_) { case improv::STATE_STOPPED: - if (this->status_indicator_ != nullptr) - this->status_indicator_->turn_off(); + this->set_status_indicator_state_(false); if (this->service_->is_created() && this->should_start_ && this->setup_complete_) { if (this->service_->is_running()) { @@ -80,14 +92,17 @@ void ESP32ImprovComponent::loop() { } break; case improv::STATE_AWAITING_AUTHORIZATION: { - if (this->authorizer_ == nullptr || this->authorizer_->state) { +#ifdef USE_BINARY_SENSOR + if (this->authorizer_ == nullptr || + (this->authorized_start_ != 0 && ((now - this->authorized_start_) < this->authorized_duration_))) { this->set_state_(improv::STATE_AUTHORIZED); - this->authorized_start_ = now; - } else { - if (this->status_indicator_ != nullptr) { - if (!this->check_identify_()) - this->status_indicator_->turn_on(); - } + } else +#else + this->set_state_(improv::STATE_AUTHORIZED); +#endif + { + if (!this->check_identify_()) + this->set_status_indicator_state_(true); } break; } @@ -99,25 +114,13 @@ void ESP32ImprovComponent::loop() { return; } } - if (this->status_indicator_ != nullptr) { - if (!this->check_identify_()) { - if ((now % 1000) < 500) { - this->status_indicator_->turn_on(); - } else { - this->status_indicator_->turn_off(); - } - } + if (!this->check_identify_()) { + this->set_status_indicator_state_((now % 1000) < 500); } break; } case improv::STATE_PROVISIONING: { - if (this->status_indicator_ != nullptr) { - if ((now % 200) < 100) { - this->status_indicator_->turn_on(); - } else { - this->status_indicator_->turn_off(); - } - } + this->set_status_indicator_state_((now % 200) < 100); if (wifi::global_wifi_component->is_connected()) { wifi::global_wifi_component->save_wifi_sta(this->connecting_sta_.get_ssid(), this->connecting_sta_.get_password()); @@ -142,13 +145,27 @@ void ESP32ImprovComponent::loop() { } case improv::STATE_PROVISIONED: { this->incoming_data_.clear(); - if (this->status_indicator_ != nullptr) - this->status_indicator_->turn_off(); + this->set_status_indicator_state_(false); break; } } } +void ESP32ImprovComponent::set_status_indicator_state_(bool state) { +#ifdef USE_OUTPUT + if (this->status_indicator_ == nullptr) + return; + if (this->status_indicator_state_ == state) + return; + this->status_indicator_state_ = state; + if (state) { + this->status_indicator_->turn_on(); + } else { + this->status_indicator_->turn_off(); + } +#endif +} + bool ESP32ImprovComponent::check_identify_() { uint32_t now = millis(); @@ -156,11 +173,7 @@ bool ESP32ImprovComponent::check_identify_() { if (identify) { uint32_t time = now % 1000; - if (time < 600 && time % 200 < 100) { - this->status_indicator_->turn_on(); - } else { - this->status_indicator_->turn_off(); - } + this->set_status_indicator_state_(time < 600 && time % 200 < 100); } return identify; } @@ -213,8 +226,12 @@ float ESP32ImprovComponent::get_setup_priority() const { return setup_priority:: void ESP32ImprovComponent::dump_config() { ESP_LOGCONFIG(TAG, "ESP32 Improv:"); +#ifdef USE_BINARY_SENSOR LOG_BINARY_SENSOR(" ", "Authorizer", this->authorizer_); +#endif +#ifdef USE_OUTPUT ESP_LOGCONFIG(TAG, " Status Indicator: '%s'", YESNO(this->status_indicator_ != nullptr)); +#endif } void ESP32ImprovComponent::process_incoming_data_() { diff --git a/esphome/components/esp32_improv/esp32_improv_component.h b/esphome/components/esp32_improv/esp32_improv_component.h index 1a142c94b6..ba9892d6a5 100644 --- a/esphome/components/esp32_improv/esp32_improv_component.h +++ b/esphome/components/esp32_improv/esp32_improv_component.h @@ -1,14 +1,22 @@ #pragma once -#include "esphome/components/binary_sensor/binary_sensor.h" -#include "esphome/components/esp32_ble_server/ble_characteristic.h" -#include "esphome/components/esp32_ble_server/ble_server.h" -#include "esphome/components/output/binary_output.h" -#include "esphome/components/wifi/wifi_component.h" #include "esphome/core/component.h" +#include "esphome/core/defines.h" #include "esphome/core/helpers.h" #include "esphome/core/preferences.h" +#include "esphome/components/esp32_ble_server/ble_characteristic.h" +#include "esphome/components/esp32_ble_server/ble_server.h" +#include "esphome/components/wifi/wifi_component.h" + +#ifdef USE_BINARY_SENSOR +#include "esphome/components/binary_sensor/binary_sensor.h" +#endif + +#ifdef USE_OUTPUT +#include "esphome/components/output/binary_output.h" +#endif + #include #ifdef USE_ESP32 @@ -34,8 +42,12 @@ class ESP32ImprovComponent : public Component, public BLEServiceComponent { void stop() override; bool is_active() const { return this->state_ != improv::STATE_STOPPED; } +#ifdef USE_BINARY_SENSOR void set_authorizer(binary_sensor::BinarySensor *authorizer) { this->authorizer_ = authorizer; } +#endif +#ifdef USE_OUTPUT void set_status_indicator(output::BinaryOutput *status_indicator) { this->status_indicator_ = status_indicator; } +#endif void set_identify_duration(uint32_t identify_duration) { this->identify_duration_ = identify_duration; } void set_authorized_duration(uint32_t authorized_duration) { this->authorized_duration_ = authorized_duration; } @@ -58,12 +70,19 @@ class ESP32ImprovComponent : public Component, public BLEServiceComponent { BLECharacteristic *rpc_response_; BLECharacteristic *capabilities_; +#ifdef USE_BINARY_SENSOR binary_sensor::BinarySensor *authorizer_{nullptr}; +#endif +#ifdef USE_OUTPUT output::BinaryOutput *status_indicator_{nullptr}; +#endif improv::State state_{improv::STATE_STOPPED}; improv::Error error_state_{improv::ERROR_NONE}; + bool status_indicator_state_{false}; + void set_status_indicator_state_(bool state); + void set_state_(improv::State state); void set_error_(improv::Error error); void send_response_(std::vector &response); diff --git a/esphome/components/output/__init__.py b/esphome/components/output/__init__.py index 4f1fb33fe7..726d1ac084 100644 --- a/esphome/components/output/__init__.py +++ b/esphome/components/output/__init__.py @@ -106,4 +106,5 @@ async def output_set_level_to_code(config, action_id, template_arg, args): async def to_code(config): + cg.add_define("USE_OUTPUT") cg.add_global(output_ns.using) diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 1e0df74eec..71493119c0 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -37,6 +37,7 @@ #define USE_OTA #define USE_OTA_PASSWORD #define USE_OTA_STATE_CALLBACK +#define USE_OUTPUT #define USE_POWER_SUPPLY #define USE_QR_CODE #define USE_SELECT @@ -117,6 +118,6 @@ #endif // Disabled feature flags -//#define USE_BSEC // Requires a library with proprietary license. +// #define USE_BSEC // Requires a library with proprietary license. #define USE_DASHBOARD_IMPORT From 8c1ad1e9a6816d2d59cb768d8d9638359625a195 Mon Sep 17 00:00:00 2001 From: Cossid <83468485+Cossid@users.noreply.github.com> Date: Thu, 12 Oct 2023 18:51:19 -0500 Subject: [PATCH 0306/2101] SM10BIT_BASE - Add delays and ACKs, clear all channels before sleeping. (#5526) --- .../components/sm10bit_base/sm10bit_base.cpp | 31 +++++++++++++++---- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/esphome/components/sm10bit_base/sm10bit_base.cpp b/esphome/components/sm10bit_base/sm10bit_base.cpp index 9c7abb48e2..d380f31c6f 100644 --- a/esphome/components/sm10bit_base/sm10bit_base.cpp +++ b/esphome/components/sm10bit_base/sm10bit_base.cpp @@ -11,6 +11,8 @@ static const uint8_t SM10BIT_ADDR_START_3CH = 0x8; static const uint8_t SM10BIT_ADDR_START_2CH = 0x10; static const uint8_t SM10BIT_ADDR_START_5CH = 0x18; +static const uint8_t SM10BIT_DELAY = 2; + // Power current values // HEX | Binary | RGB level | White level | Config value // 0x0 | 0000 | RGB 10mA | CW 5mA | 0 @@ -37,10 +39,13 @@ void Sm10BitBase::loop() { uint8_t data[12]; if (this->pwm_amounts_[0] == 0 && this->pwm_amounts_[1] == 0 && this->pwm_amounts_[2] == 0 && this->pwm_amounts_[3] == 0 && this->pwm_amounts_[4] == 0) { - // Off / Sleep - data[0] = this->model_id_ + SM10BIT_ADDR_STANDBY; for (int i = 1; i < 12; i++) data[i] = 0; + // First turn all channels off + data[0] = this->model_id_ + SM10BIT_ADDR_START_5CH; + this->write_buffer_(data, 12); + // Then sleep + data[0] = this->model_id_ + SM10BIT_ADDR_STANDBY; this->write_buffer_(data, 12); } else if (this->pwm_amounts_[0] == 0 && this->pwm_amounts_[1] == 0 && this->pwm_amounts_[2] == 0 && (this->pwm_amounts_[3] > 0 || this->pwm_amounts_[4] > 0)) { @@ -84,28 +89,42 @@ void Sm10BitBase::set_channel_value_(uint8_t channel, uint16_t value) { this->pwm_amounts_[channel] = value; } void Sm10BitBase::write_bit_(bool value) { - this->clock_pin_->digital_write(false); this->data_pin_->digital_write(value); + delayMicroseconds(SM10BIT_DELAY); this->clock_pin_->digital_write(true); + delayMicroseconds(SM10BIT_DELAY); + this->clock_pin_->digital_write(false); + delayMicroseconds(SM10BIT_DELAY); } void Sm10BitBase::write_byte_(uint8_t data) { for (uint8_t mask = 0x80; mask; mask >>= 1) { this->write_bit_(data & mask); } - this->clock_pin_->digital_write(false); - this->data_pin_->digital_write(true); + + // ack bit + this->data_pin_->pin_mode(gpio::FLAG_INPUT); this->clock_pin_->digital_write(true); + delayMicroseconds(SM10BIT_DELAY); + this->clock_pin_->digital_write(false); + delayMicroseconds(SM10BIT_DELAY); + this->data_pin_->pin_mode(gpio::FLAG_OUTPUT); } void Sm10BitBase::write_buffer_(uint8_t *buffer, uint8_t size) { this->data_pin_->digital_write(false); + delayMicroseconds(SM10BIT_DELAY); + this->clock_pin_->digital_write(false); + delayMicroseconds(SM10BIT_DELAY); + for (uint32_t i = 0; i < size; i++) { this->write_byte_(buffer[i]); } - this->clock_pin_->digital_write(false); + this->clock_pin_->digital_write(true); + delayMicroseconds(SM10BIT_DELAY); this->data_pin_->digital_write(true); + delayMicroseconds(SM10BIT_DELAY); } } // namespace sm10bit_base From 5d7c3d16224ff4ce8b7afaa91907b95b9c29b7c2 Mon Sep 17 00:00:00 2001 From: Cossid <83468485+Cossid@users.noreply.github.com> Date: Thu, 12 Oct 2023 18:51:28 -0500 Subject: [PATCH 0307/2101] BP1658CJ - Clear all channels before sleeping. (#5525) --- esphome/components/bp1658cj/bp1658cj.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/esphome/components/bp1658cj/bp1658cj.cpp b/esphome/components/bp1658cj/bp1658cj.cpp index d3f3e71fed..05c3f790c2 100644 --- a/esphome/components/bp1658cj/bp1658cj.cpp +++ b/esphome/components/bp1658cj/bp1658cj.cpp @@ -37,10 +37,14 @@ void BP1658CJ::loop() { uint8_t data[12]; if (this->pwm_amounts_[0] == 0 && this->pwm_amounts_[1] == 0 && this->pwm_amounts_[2] == 0 && this->pwm_amounts_[3] == 0 && this->pwm_amounts_[4] == 0) { - // Off / Sleep - data[0] = BP1658CJ_MODEL_ID + BP1658CJ_ADDR_STANDBY; for (int i = 1; i < 12; i++) data[i] = 0; + + // First turn all channels off + data[0] = BP1658CJ_MODEL_ID + BP1658CJ_ADDR_START_5CH; + this->write_buffer_(data, 12); + // Then sleep + data[0] = BP1658CJ_MODEL_ID + BP1658CJ_ADDR_STANDBY; this->write_buffer_(data, 12); } else if (this->pwm_amounts_[0] == 0 && this->pwm_amounts_[1] == 0 && this->pwm_amounts_[2] == 0 && (this->pwm_amounts_[3] > 0 || this->pwm_amounts_[4] > 0)) { From 90315b3c401f608ae3dbe6f3cf89d6ef000c7510 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 13 Oct 2023 14:16:22 +1300 Subject: [PATCH 0308/2101] Bump version to 2023.10.0b2 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 5a5b683c2d..cef733b2f9 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2023.10.0b1" +__version__ = "2023.10.0b2" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 7ddcdab35130ab54ba4735623df2aab95dcf3ce6 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Sat, 14 Oct 2023 13:07:23 +1300 Subject: [PATCH 0309/2101] Add round sensor filter (#5532) --- esphome/components/sensor/__init__.py | 18 ++++++++++++++++++ esphome/components/sensor/filter.cpp | 9 +++++++++ esphome/components/sensor/filter.h | 9 +++++++++ 3 files changed, 36 insertions(+) diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index ee42011038..bd7306ac28 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -242,6 +242,7 @@ CalibrateLinearFilter = sensor_ns.class_("CalibrateLinearFilter", Filter) CalibratePolynomialFilter = sensor_ns.class_("CalibratePolynomialFilter", Filter) SensorInRangeCondition = sensor_ns.class_("SensorInRangeCondition", Filter) ClampFilter = sensor_ns.class_("ClampFilter", Filter) +RoundFilter = sensor_ns.class_("RoundFilter", Filter) validate_unit_of_measurement = cv.string_strict validate_accuracy_decimals = cv.int_ @@ -702,6 +703,23 @@ async def clamp_filter_to_code(config, filter_id): ) +@FILTER_REGISTRY.register( + "round", + RoundFilter, + cv.maybe_simple_value( + { + cv.Required(CONF_ACCURACY_DECIMALS): cv.uint8_t, + }, + key=CONF_ACCURACY_DECIMALS, + ), +) +async def round_filter_to_code(config, filter_id): + return cg.new_Pvariable( + filter_id, + config[CONF_ACCURACY_DECIMALS], + ) + + async def build_filters(config): return await cg.build_registry_list(FILTER_REGISTRY, config) diff --git a/esphome/components/sensor/filter.cpp b/esphome/components/sensor/filter.cpp index 6323023d50..af67a60754 100644 --- a/esphome/components/sensor/filter.cpp +++ b/esphome/components/sensor/filter.cpp @@ -445,5 +445,14 @@ optional ClampFilter::new_value(float value) { return value; } +RoundFilter::RoundFilter(uint8_t precision) : precision_(precision) {} +optional RoundFilter::new_value(float value) { + if (std::isfinite(value)) { + float accuracy_mult = powf(10.0f, this->precision_); + return roundf(accuracy_mult * value) / accuracy_mult; + } + return value; +} + } // namespace sensor } // namespace esphome diff --git a/esphome/components/sensor/filter.h b/esphome/components/sensor/filter.h index 46aeefac56..d4239837b6 100644 --- a/esphome/components/sensor/filter.h +++ b/esphome/components/sensor/filter.h @@ -419,5 +419,14 @@ class ClampFilter : public Filter { float max_{NAN}; }; +class RoundFilter : public Filter { + public: + explicit RoundFilter(uint8_t precision); + optional new_value(float value) override; + + protected: + uint8_t precision_; +}; + } // namespace sensor } // namespace esphome From 6143099f60d1c76e3faa0da3e75cb3fd25e5ebf1 Mon Sep 17 00:00:00 2001 From: ghsensdev <145111396+ghsensdev@users.noreply.github.com> Date: Sun, 15 Oct 2023 20:49:57 +0200 Subject: [PATCH 0310/2101] Add Support for Sensirion SFA30 sensor (#5519) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- CODEOWNERS | 1 + esphome/components/sfa30/__init__.py | 1 + esphome/components/sfa30/sensor.py | 78 ++++++++++++++++++++++ esphome/components/sfa30/sfa30.cpp | 99 ++++++++++++++++++++++++++++ esphome/components/sfa30/sfa30.h | 34 ++++++++++ tests/test1.yaml | 10 +++ 6 files changed, 223 insertions(+) create mode 100644 esphome/components/sfa30/__init__.py create mode 100644 esphome/components/sfa30/sensor.py create mode 100644 esphome/components/sfa30/sfa30.cpp create mode 100644 esphome/components/sfa30/sfa30.h diff --git a/CODEOWNERS b/CODEOWNERS index d7cf7269ab..326642e12c 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -254,6 +254,7 @@ esphome/components/sen21231/* @shreyaskarnik esphome/components/sen5x/* @martgras esphome/components/sensirion_common/* @martgras esphome/components/sensor/* @esphome/core +esphome/components/sfa30/* @ghsensdev esphome/components/sgp40/* @SenexCrenshaw esphome/components/sgp4x/* @SenexCrenshaw @martgras esphome/components/shelly_dimmer/* @edge90 @rnauber diff --git a/esphome/components/sfa30/__init__.py b/esphome/components/sfa30/__init__.py new file mode 100644 index 0000000000..28b665906f --- /dev/null +++ b/esphome/components/sfa30/__init__.py @@ -0,0 +1 @@ +CODEOWNERS = ["@ghsensdev"] diff --git a/esphome/components/sfa30/sensor.py b/esphome/components/sfa30/sensor.py new file mode 100644 index 0000000000..428f6b874b --- /dev/null +++ b/esphome/components/sfa30/sensor.py @@ -0,0 +1,78 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import i2c, sensor, sensirion_common + +from esphome.const import ( + CONF_ID, + CONF_FORMALDEHYDE, + CONF_HUMIDITY, + CONF_TEMPERATURE, + DEVICE_CLASS_GAS, + DEVICE_CLASS_HUMIDITY, + DEVICE_CLASS_TEMPERATURE, + ICON_RADIATOR, + ICON_WATER_PERCENT, + ICON_THERMOMETER, + STATE_CLASS_MEASUREMENT, + UNIT_PARTS_PER_BILLION, + UNIT_PERCENT, + UNIT_CELSIUS, +) + +CODEOWNERS = ["@ghsensdev"] +DEPENDENCIES = ["i2c"] +AUTO_LOAD = ["sensirion_common"] + +sfa30_ns = cg.esphome_ns.namespace("sfa30") + +SFA30Component = sfa30_ns.class_( + "SFA30Component", cg.PollingComponent, sensirion_common.SensirionI2CDevice +) + +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(SFA30Component), + cv.Optional(CONF_FORMALDEHYDE): sensor.sensor_schema( + unit_of_measurement=UNIT_PARTS_PER_BILLION, + icon=ICON_RADIATOR, + accuracy_decimals=1, + device_class=DEVICE_CLASS_GAS, + 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_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, + ), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x5D)) +) + +SENSOR_MAP = { + CONF_FORMALDEHYDE: "set_formaldehyde_sensor", + CONF_HUMIDITY: "set_humidity_sensor", + CONF_TEMPERATURE: "set_temperature_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) + + for key, funcName in SENSOR_MAP.items(): + if sensor_config := config.get(key): + sens = await sensor.new_sensor(sensor_config) + cg.add(getattr(var, funcName)(sens)) diff --git a/esphome/components/sfa30/sfa30.cpp b/esphome/components/sfa30/sfa30.cpp new file mode 100644 index 0000000000..20d5ddad5e --- /dev/null +++ b/esphome/components/sfa30/sfa30.cpp @@ -0,0 +1,99 @@ +#include "sfa30.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace sfa30 { + +static const char *const TAG = "sfa30"; + +static const uint16_t SFA30_CMD_GET_DEVICE_MARKING = 0xD060; +static const uint16_t SFA30_CMD_START_CONTINUOUS_MEASUREMENTS = 0x0006; +static const uint16_t SFA30_CMD_READ_MEASUREMENT = 0x0327; + +void SFA30Component::setup() { + ESP_LOGCONFIG(TAG, "Setting up sfa30..."); + + // Serial Number identification + uint16_t raw_device_marking[16]; + if (!this->get_register(SFA30_CMD_GET_DEVICE_MARKING, raw_device_marking, 16, 5)) { + ESP_LOGE(TAG, "Failed to read device marking"); + this->error_code_ = DEVICE_MARKING_READ_FAILED; + this->mark_failed(); + return; + } + + for (size_t i = 0; i < 16; i++) { + this->device_marking_[i * 2] = static_cast(raw_device_marking[i] >> 8); + this->device_marking_[i * 2 + 1] = static_cast(raw_device_marking[i] & 0xFF); + } + ESP_LOGD(TAG, "Device Marking: '%s'", this->device_marking_); + + if (!this->write_command(SFA30_CMD_START_CONTINUOUS_MEASUREMENTS)) { + ESP_LOGE(TAG, "Error starting measurements."); + this->error_code_ = MEASUREMENT_INIT_FAILED; + this->mark_failed(); + return; + } + + ESP_LOGD(TAG, "Sensor initialized"); +} + +void SFA30Component::dump_config() { + ESP_LOGCONFIG(TAG, "sfa30:"); + LOG_I2C_DEVICE(this); + if (this->is_failed()) { + switch (this->error_code_) { + case DEVICE_MARKING_READ_FAILED: + ESP_LOGW(TAG, "Unable to read device marking!"); + break; + case MEASUREMENT_INIT_FAILED: + ESP_LOGW(TAG, "Measurement initialization failed!"); + break; + default: + ESP_LOGW(TAG, "Unknown setup error!"); + break; + } + } + LOG_UPDATE_INTERVAL(this); + ESP_LOGCONFIG(TAG, " Device Marking: '%s'", this->device_marking_); + LOG_SENSOR(" ", "Formaldehyde", this->formaldehyde_sensor_); + LOG_SENSOR(" ", "Humidity", this->humidity_sensor_); + LOG_SENSOR(" ", "Temperature", this->temperature_sensor_); +} + +void SFA30Component::update() { + if (!this->write_command(SFA30_CMD_READ_MEASUREMENT)) { + ESP_LOGW(TAG, "Error reading measurement!"); + this->status_set_warning(); + return; + } + + this->set_timeout(5, [this]() { + uint16_t raw_data[3]; + if (!this->read_data(raw_data, 3)) { + ESP_LOGW(TAG, "Error reading measurement data!"); + this->status_set_warning(); + return; + } + + if (this->formaldehyde_sensor_ != nullptr) { + const float formaldehyde = raw_data[0] / 5.0f; + this->formaldehyde_sensor_->publish_state(formaldehyde); + } + + if (this->humidity_sensor_ != nullptr) { + const float humidity = raw_data[1] / 100.0f; + this->humidity_sensor_->publish_state(humidity); + } + + if (this->temperature_sensor_ != nullptr) { + const float temperature = raw_data[2] / 200.0f; + this->temperature_sensor_->publish_state(temperature); + } + + this->status_clear_warning(); + }); +} + +} // namespace sfa30 +} // namespace esphome diff --git a/esphome/components/sfa30/sfa30.h b/esphome/components/sfa30/sfa30.h new file mode 100644 index 0000000000..fa2c59f624 --- /dev/null +++ b/esphome/components/sfa30/sfa30.h @@ -0,0 +1,34 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/components/sensor/sensor.h" +#include "esphome/components/sensirion_common/i2c_sensirion.h" + +namespace esphome { +namespace sfa30 { + +class SFA30Component : public PollingComponent, public sensirion_common::SensirionI2CDevice { + enum ErrorCode { DEVICE_MARKING_READ_FAILED, MEASUREMENT_INIT_FAILED, UNKNOWN }; + + public: + float get_setup_priority() const override { return setup_priority::DATA; } + void setup() override; + void dump_config() override; + void update() override; + + void set_formaldehyde_sensor(sensor::Sensor *formaldehyde) { this->formaldehyde_sensor_ = formaldehyde; } + void set_humidity_sensor(sensor::Sensor *humidity) { this->humidity_sensor_ = humidity; } + void set_temperature_sensor(sensor::Sensor *temperature) { this->temperature_sensor_ = temperature; } + + protected: + char device_marking_[32] = {0}; + + ErrorCode error_code_{UNKNOWN}; + + sensor::Sensor *formaldehyde_sensor_{nullptr}; + sensor::Sensor *humidity_sensor_{nullptr}; + sensor::Sensor *temperature_sensor_{nullptr}; +}; + +} // namespace sfa30 +} // namespace esphome diff --git a/tests/test1.yaml b/tests/test1.yaml index 6d42e325d8..b9b4beb5ad 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -1083,6 +1083,16 @@ sensor: ambient_pressure_compensation: 961mBar temperature_offset: 4.2C i2c_id: i2c_bus + - platform: sfa30 + formaldehyde: + name: "SFA30 formaldehyde" + temperature: + name: "SFA30 temperature" + humidity: + name: "SFA30 humidity" + i2c_id: i2c_bus + address: 0x5D + update_interval: 30s - platform: sen0321 name: Workshop Ozone Sensor id: sen0321_ozone From 357ba1ab0f08ee0a0653a3cde8db246f5c10447f Mon Sep 17 00:00:00 2001 From: leoshusar Date: Mon, 16 Oct 2023 00:29:13 +0200 Subject: [PATCH 0311/2101] Change UART source clock to `UART_SCLK_DEFAULT` when IDF >=v5 (#5533) --- esphome/components/uart/uart_component_esp_idf.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/esphome/components/uart/uart_component_esp_idf.cpp b/esphome/components/uart/uart_component_esp_idf.cpp index ae772fa8f8..9b519c4568 100644 --- a/esphome/components/uart/uart_component_esp_idf.cpp +++ b/esphome/components/uart/uart_component_esp_idf.cpp @@ -48,7 +48,11 @@ uart_config_t IDFUARTComponent::get_config_() { uart_config.parity = parity; uart_config.stop_bits = this->stop_bits_ == 1 ? UART_STOP_BITS_1 : UART_STOP_BITS_2; uart_config.flow_ctrl = UART_HW_FLOWCTRL_DISABLE; +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) + uart_config.source_clk = UART_SCLK_DEFAULT; +#else uart_config.source_clk = UART_SCLK_APB; +#endif uart_config.rx_flow_ctrl_thresh = 122; return uart_config; From 06eff72065c1510a4d4e7a5707adff70f243911f Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 16 Oct 2023 19:41:59 +1300 Subject: [PATCH 0312/2101] Prometheus fix for esp-idf and fix newlines (#5536) --- .../prometheus/prometheus_handler.cpp | 22 ++++++++----------- .../prometheus/prometheus_handler.h | 8 ++----- 2 files changed, 11 insertions(+), 19 deletions(-) diff --git a/esphome/components/prometheus/prometheus_handler.cpp b/esphome/components/prometheus/prometheus_handler.cpp index abb5111aaf..68bca95a21 100644 --- a/esphome/components/prometheus/prometheus_handler.cpp +++ b/esphome/components/prometheus/prometheus_handler.cpp @@ -1,5 +1,3 @@ -#ifdef USE_ARDUINO - #include "prometheus_handler.h" #include "esphome/core/application.h" @@ -89,7 +87,7 @@ void PrometheusHandler::sensor_row_(AsyncResponseStream *stream, sensor::Sensor stream->print(obj->get_unit_of_measurement().c_str()); stream->print(F("\"} ")); stream->print(value_accuracy_to_string(obj->state, obj->get_accuracy_decimals()).c_str()); - stream->print('\n'); + stream->print(F("\n")); } else { // Invalid state stream->print(F("esphome_sensor_failed{id=\"")); @@ -124,7 +122,7 @@ void PrometheusHandler::binary_sensor_row_(AsyncResponseStream *stream, binary_s stream->print(relabel_name_(obj).c_str()); stream->print(F("\"} ")); stream->print(obj->state); - stream->print('\n'); + stream->print(F("\n")); } else { // Invalid state stream->print(F("esphome_binary_sensor_failed{id=\"")); @@ -158,7 +156,7 @@ void PrometheusHandler::fan_row_(AsyncResponseStream *stream, fan::Fan *obj) { stream->print(relabel_name_(obj).c_str()); stream->print(F("\"} ")); stream->print(obj->state); - stream->print('\n'); + stream->print(F("\n")); // Speed if available if (obj->get_traits().supports_speed()) { stream->print(F("esphome_fan_speed{id=\"")); @@ -167,7 +165,7 @@ void PrometheusHandler::fan_row_(AsyncResponseStream *stream, fan::Fan *obj) { stream->print(relabel_name_(obj).c_str()); stream->print(F("\"} ")); stream->print(obj->speed); - stream->print('\n'); + stream->print(F("\n")); } // Oscillation if available if (obj->get_traits().supports_oscillation()) { @@ -177,7 +175,7 @@ void PrometheusHandler::fan_row_(AsyncResponseStream *stream, fan::Fan *obj) { stream->print(relabel_name_(obj).c_str()); stream->print(F("\"} ")); stream->print(obj->oscillating); - stream->print('\n'); + stream->print(F("\n")); } } #endif @@ -281,7 +279,7 @@ void PrometheusHandler::cover_row_(AsyncResponseStream *stream, cover::Cover *ob stream->print(relabel_name_(obj).c_str()); stream->print(F("\"} ")); stream->print(obj->position); - stream->print('\n'); + stream->print(F("\n")); if (obj->get_traits().get_supports_tilt()) { stream->print(F("esphome_cover_tilt{id=\"")); stream->print(relabel_id_(obj).c_str()); @@ -289,7 +287,7 @@ void PrometheusHandler::cover_row_(AsyncResponseStream *stream, cover::Cover *ob stream->print(relabel_name_(obj).c_str()); stream->print(F("\"} ")); stream->print(obj->tilt); - stream->print('\n'); + stream->print(F("\n")); } } else { // Invalid state @@ -322,7 +320,7 @@ void PrometheusHandler::switch_row_(AsyncResponseStream *stream, switch_::Switch stream->print(relabel_name_(obj).c_str()); stream->print(F("\"} ")); stream->print(obj->state); - stream->print('\n'); + stream->print(F("\n")); } #endif @@ -346,11 +344,9 @@ void PrometheusHandler::lock_row_(AsyncResponseStream *stream, lock::Lock *obj) stream->print(relabel_name_(obj).c_str()); stream->print(F("\"} ")); stream->print(obj->state); - stream->print('\n'); + stream->print(F("\n")); } #endif } // namespace prometheus } // namespace esphome - -#endif // USE_ARDUINO diff --git a/esphome/components/prometheus/prometheus_handler.h b/esphome/components/prometheus/prometheus_handler.h index 0ae2856ce4..a9505a3572 100644 --- a/esphome/components/prometheus/prometheus_handler.h +++ b/esphome/components/prometheus/prometheus_handler.h @@ -1,14 +1,12 @@ #pragma once -#ifdef USE_ARDUINO - #include #include -#include "esphome/core/entity_base.h" #include "esphome/components/web_server_base/web_server_base.h" -#include "esphome/core/controller.h" #include "esphome/core/component.h" +#include "esphome/core/controller.h" +#include "esphome/core/entity_base.h" namespace esphome { namespace prometheus { @@ -119,5 +117,3 @@ class PrometheusHandler : public AsyncWebHandler, public Component { } // namespace prometheus } // namespace esphome - -#endif // USE_ARDUINO From 26f12cd3bbed34df0a4829e999f378e37afc8902 Mon Sep 17 00:00:00 2001 From: raineth Date: Mon, 16 Oct 2023 02:42:18 -0400 Subject: [PATCH 0313/2101] Make IPAddress's operator!= compare values, not memory addresses. (#5537) Co-authored-by: Ben Winslow --- esphome/components/network/ip_address.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/network/ip_address.h b/esphome/components/network/ip_address.h index 8b05237c05..7a4d394805 100644 --- a/esphome/components/network/ip_address.h +++ b/esphome/components/network/ip_address.h @@ -87,7 +87,7 @@ struct IPAddress { bool is_ip6() { return IP_IS_V6(&ip_addr_); } std::string str() const { return ipaddr_ntoa(&ip_addr_); } bool operator==(const IPAddress &other) const { return ip_addr_cmp(&ip_addr_, &other.ip_addr_); } - bool operator!=(const IPAddress &other) const { return !(&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) { if (IP_IS_V4(&ip_addr_)) { #if LWIP_IPV6 From e42c51a222abb817d5dfba00cc7cd34d8b7c8fca Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 16 Oct 2023 20:47:35 +0100 Subject: [PATCH 0314/2101] Add change i2c address and allow multi conf for TB6612FNG (#5492) --- .../components/grove_tb6612fng/__init__.py | 25 +++++++++++++++++++ .../grove_tb6612fng/grove_tb6612fng.h | 11 ++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/esphome/components/grove_tb6612fng/__init__.py b/esphome/components/grove_tb6612fng/__init__.py index 75610ce9d3..7db0198a89 100644 --- a/esphome/components/grove_tb6612fng/__init__.py +++ b/esphome/components/grove_tb6612fng/__init__.py @@ -8,12 +8,15 @@ from esphome.const import ( CONF_CHANNEL, CONF_SPEED, CONF_DIRECTION, + CONF_ADDRESS, ) DEPENDENCIES = ["i2c"] CODEOWNERS = ["@max246"] +MULTI_CONF = True + grove_tb6612fng_ns = cg.esphome_ns.namespace("grove_tb6612fng") GROVE_TB6612FNG = grove_tb6612fng_ns.class_( "GroveMotorDriveTB6612FNG", cg.Component, i2c.I2CDevice @@ -33,6 +36,9 @@ GROVETB6612FNGMotorStandbyAction = grove_tb6612fng_ns.class_( GROVETB6612FNGMotorNoStandbyAction = grove_tb6612fng_ns.class_( "GROVETB6612FNGMotorNoStandbyAction", automation.Action ) +GROVETB6612FNGMotorChangeAddressAction = grove_tb6612fng_ns.class_( + "GROVETB6612FNGMotorChangeAddressAction", automation.Action +) DIRECTION_TYPE = { "FORWARD": 1, @@ -150,3 +156,22 @@ async def grove_tb6612fng_no_standby_to_code(config, action_id, template_arg, ar await cg.register_parented(var, config[CONF_ID]) return var + + +@automation.register_action( + "grove_tb6612fng.change_address", + GROVETB6612FNGMotorChangeAddressAction, + cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(GROVE_TB6612FNG), + cv.Required(CONF_ADDRESS): cv.i2c_address, + } + ), +) +async def grove_tb6612fng_change_address_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_channel = await cg.templatable(config[CONF_ADDRESS], args, int) + cg.add(var.set_address(template_channel)) + return var diff --git a/esphome/components/grove_tb6612fng/grove_tb6612fng.h b/esphome/components/grove_tb6612fng/grove_tb6612fng.h index ccdab6472a..2743ef4ed7 100644 --- a/esphome/components/grove_tb6612fng/grove_tb6612fng.h +++ b/esphome/components/grove_tb6612fng/grove_tb6612fng.h @@ -84,8 +84,7 @@ class GroveMotorDriveTB6612FNG : public Component, public i2c::I2CDevice { *************************************************************/ void set_i2c_addr(uint8_t addr); - /************************************************************* - Description + /***********************************change_address Drive a motor. Parameter chl: MOTOR_CHA or MOTOR_CHB @@ -204,5 +203,13 @@ class GROVETB6612FNGMotorNoStandbyAction : public Action, public Parented void play(Ts... x) override { this->parent_->not_standby(); } }; +template +class GROVETB6612FNGMotorChangeAddressAction : public Action, public Parented { + public: + TEMPLATABLE_VALUE(uint8_t, address) + + void play(Ts... x) override { this->parent_->set_i2c_addr(this->address_.value(x...)); } +}; + } // namespace grove_tb6612fng } // namespace esphome From 4913b3cc356a996a548ea9ed8d61d11d172b5e8f Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 17 Oct 2023 17:18:05 +1300 Subject: [PATCH 0315/2101] Add stream start and end events (#5545) --- esphome/components/api/api.proto | 2 + esphome/components/api/api_pb2.cpp | 4 ++ esphome/components/api/api_pb2.h | 2 + .../i2s_audio/speaker/i2s_audio_speaker.cpp | 6 ++ .../voice_assistant/voice_assistant.cpp | 69 +++++++++++++++++-- .../voice_assistant/voice_assistant.h | 3 +- 6 files changed, 81 insertions(+), 5 deletions(-) diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index ec4a0f7cc9..69765c7a94 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -1459,6 +1459,8 @@ enum VoiceAssistantEvent { VOICE_ASSISTANT_WAKE_WORD_END = 10; VOICE_ASSISTANT_STT_VAD_START = 11; VOICE_ASSISTANT_STT_VAD_END = 12; + VOICE_ASSISTANT_TTS_STREAM_START = 98; + VOICE_ASSISTANT_TTS_STREAM_END = 99; } message VoiceAssistantEventData { diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index 225b213a67..65df2312e1 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -452,6 +452,10 @@ template<> const char *proto_enum_to_string(enums::V return "VOICE_ASSISTANT_STT_VAD_START"; case enums::VOICE_ASSISTANT_STT_VAD_END: return "VOICE_ASSISTANT_STT_VAD_END"; + case enums::VOICE_ASSISTANT_TTS_STREAM_START: + return "VOICE_ASSISTANT_TTS_STREAM_START"; + case enums::VOICE_ASSISTANT_TTS_STREAM_END: + return "VOICE_ASSISTANT_TTS_STREAM_END"; default: return "UNKNOWN"; } diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index a4826f09d2..4c70facf3d 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -184,6 +184,8 @@ enum VoiceAssistantEvent : uint32_t { VOICE_ASSISTANT_WAKE_WORD_END = 10, VOICE_ASSISTANT_STT_VAD_START = 11, VOICE_ASSISTANT_STT_VAD_END = 12, + VOICE_ASSISTANT_TTS_STREAM_START = 98, + VOICE_ASSISTANT_TTS_STREAM_END = 99, }; enum AlarmControlPanelState : uint32_t { ALARM_STATE_DISARMED = 0, diff --git a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp index 592a27b739..ed13e6b458 100644 --- a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +++ b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp @@ -158,8 +158,13 @@ void I2SAudioSpeaker::watch_() { if (xQueueReceive(this->event_queue_, &event, 0) == pdTRUE) { switch (event.type) { case TaskEventType::STARTING: + ESP_LOGD(TAG, "Starting I2S Audio Speaker"); + break; case TaskEventType::STARTED: + ESP_LOGD(TAG, "Started I2S Audio Speaker"); + break; case TaskEventType::STOPPING: + ESP_LOGD(TAG, "Stopping I2S Audio Speaker"); break; case TaskEventType::PLAYING: this->status_clear_warning(); @@ -170,6 +175,7 @@ void I2SAudioSpeaker::watch_() { this->player_task_handle_ = nullptr; this->parent_->unlock(); xQueueReset(this->buffer_queue_); + ESP_LOGD(TAG, "Stopped I2S Audio Speaker"); break; case TaskEventType::WARNING: ESP_LOGW(TAG, "Error writing to I2S: %s", esp_err_to_name(event.err)); diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index 448df61d80..12fbdc97b4 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -281,11 +281,14 @@ void VoiceAssistant::loop() { memmove(this->speaker_buffer_, this->speaker_buffer_ + written, this->speaker_buffer_size_ - written); this->speaker_buffer_size_ -= written; this->speaker_buffer_index_ -= written; - this->set_timeout("speaker-timeout", 1000, [this]() { this->speaker_->stop(); }); + this->set_timeout("speaker-timeout", 2000, [this]() { this->speaker_->stop(); }); } else { ESP_LOGW(TAG, "Speaker buffer full."); } } + if (this->wait_for_stream_end_) { + break; // We dont want to timeout here as the STREAM_END event will take care of that. + } playing = this->speaker_->is_running(); } #endif @@ -295,28 +298,77 @@ void VoiceAssistant::loop() { } #endif if (playing) { - this->set_timeout("playing", 100, [this]() { + this->set_timeout("playing", 2000, [this]() { this->cancel_timeout("speaker-timeout"); this->set_state_(State::IDLE, State::IDLE); }); } break; } + case State::RESPONSE_FINISHED: { +#ifdef USE_SPEAKER + if (this->speaker_ != nullptr) { + this->speaker_->stop(); + this->cancel_timeout("speaker-timeout"); + this->cancel_timeout("playing"); + this->speaker_buffer_size_ = 0; + this->speaker_buffer_index_ = 0; + memset(this->speaker_buffer_, 0, SPEAKER_BUFFER_SIZE); + } +#endif + this->wait_for_stream_end_ = false; + this->set_state_(State::IDLE, State::IDLE); + break; + } default: break; } } +static const LogString *voice_assistant_state_to_string(State state) { + switch (state) { + case State::IDLE: + return LOG_STR("IDLE"); + case State::START_MICROPHONE: + return LOG_STR("START_MICROPHONE"); + case State::STARTING_MICROPHONE: + return LOG_STR("STARTING_MICROPHONE"); + case State::WAIT_FOR_VAD: + return LOG_STR("WAIT_FOR_VAD"); + case State::WAITING_FOR_VAD: + return LOG_STR("WAITING_FOR_VAD"); + case State::START_PIPELINE: + return LOG_STR("START_PIPELINE"); + case State::STARTING_PIPELINE: + return LOG_STR("STARTING_PIPELINE"); + case State::STREAMING_MICROPHONE: + return LOG_STR("STREAMING_MICROPHONE"); + case State::STOP_MICROPHONE: + return LOG_STR("STOP_MICROPHONE"); + case State::STOPPING_MICROPHONE: + return LOG_STR("STOPPING_MICROPHONE"); + case State::AWAITING_RESPONSE: + return LOG_STR("AWAITING_RESPONSE"); + case State::STREAMING_RESPONSE: + return LOG_STR("STREAMING_RESPONSE"); + case State::RESPONSE_FINISHED: + return LOG_STR("RESPONSE_FINISHED"); + default: + return LOG_STR("UNKNOWN"); + } +}; + void VoiceAssistant::set_state_(State state) { State old_state = this->state_; this->state_ = state; - ESP_LOGD(TAG, "State changed from %d to %d", static_cast(old_state), static_cast(state)); + ESP_LOGD(TAG, "State changed from %s to %s", LOG_STR_ARG(voice_assistant_state_to_string(old_state)), + LOG_STR_ARG(voice_assistant_state_to_string(state))); } void VoiceAssistant::set_state_(State state, State desired_state) { this->set_state_(state); this->desired_state_ = desired_state; - ESP_LOGD(TAG, "Desired state set to %d", static_cast(desired_state)); + ESP_LOGD(TAG, "Desired state set to %s", LOG_STR_ARG(voice_assistant_state_to_string(desired_state))); } void VoiceAssistant::failed_to_start() { @@ -400,6 +452,7 @@ void VoiceAssistant::request_stop() { break; case State::AWAITING_RESPONSE: case State::STREAMING_RESPONSE: + case State::RESPONSE_FINISHED: break; // Let the incoming audio stream finish then it will go to idle. } } @@ -531,6 +584,14 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { this->error_trigger_->trigger(code, message); break; } + case api::enums::VOICE_ASSISTANT_TTS_STREAM_START: { + this->wait_for_stream_end_ = true; + break; + } + case api::enums::VOICE_ASSISTANT_TTS_STREAM_END: { + this->set_state_(State::RESPONSE_FINISHED, State::IDLE); + break; + } default: ESP_LOGD(TAG, "Unhandled event type: %d", msg.event_type); break; diff --git a/esphome/components/voice_assistant/voice_assistant.h b/esphome/components/voice_assistant/voice_assistant.h index ce22538a85..cd448293db 100644 --- a/esphome/components/voice_assistant/voice_assistant.h +++ b/esphome/components/voice_assistant/voice_assistant.h @@ -46,6 +46,7 @@ enum class State { STOPPING_MICROPHONE, AWAITING_RESPONSE, STREAMING_RESPONSE, + RESPONSE_FINISHED, }; class VoiceAssistant : public Component { @@ -132,10 +133,10 @@ class VoiceAssistant : public Component { uint8_t *speaker_buffer_; size_t speaker_buffer_index_{0}; size_t speaker_buffer_size_{0}; + bool wait_for_stream_end_{false}; #endif #ifdef USE_MEDIA_PLAYER media_player::MediaPlayer *media_player_{nullptr}; - bool playing_tts_{false}; #endif bool local_output_{false}; From fb90e197132a1dc8c23fe7cbbef83fcb18fbfab8 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 17 Oct 2023 20:03:39 +1300 Subject: [PATCH 0316/2101] Fix esp32_improv authorizer with no binary sensors in config (#5546) --- esphome/components/esp32_improv/esp32_improv_component.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/esphome/components/esp32_improv/esp32_improv_component.cpp b/esphome/components/esp32_improv/esp32_improv_component.cpp index 5bdf7d19fe..8a901a79e5 100644 --- a/esphome/components/esp32_improv/esp32_improv_component.cpp +++ b/esphome/components/esp32_improv/esp32_improv_component.cpp @@ -107,6 +107,7 @@ void ESP32ImprovComponent::loop() { break; } case improv::STATE_AUTHORIZED: { +#ifdef USE_BINARY_SENSOR if (this->authorizer_ != nullptr) { if (now - this->authorized_start_ > this->authorized_duration_) { ESP_LOGD(TAG, "Authorization timeout"); @@ -114,6 +115,7 @@ void ESP32ImprovComponent::loop() { return; } } +#endif if (!this->check_identify_()) { this->set_status_indicator_state_((now % 1000) < 500); } @@ -290,8 +292,10 @@ void ESP32ImprovComponent::process_incoming_data_() { void ESP32ImprovComponent::on_wifi_connect_timeout_() { this->set_error_(improv::ERROR_UNABLE_TO_CONNECT); this->set_state_(improv::STATE_AUTHORIZED); +#ifdef USE_BINARY_SENSOR if (this->authorizer_ != nullptr) this->authorized_start_ = millis(); +#endif ESP_LOGW(TAG, "Timed out trying to connect to given WiFi network"); wifi::global_wifi_component->clear_sta(); } From a960c8008ea3f15888b2388a08bf6308995ac278 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 17 Oct 2023 20:11:37 +1300 Subject: [PATCH 0317/2101] More voice assistant fixes (#5547) --- .../components/i2s_audio/microphone/i2s_audio_microphone.cpp | 2 ++ esphome/components/voice_assistant/voice_assistant.cpp | 1 + 2 files changed, 3 insertions(+) diff --git a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp index 44c73eb8fd..ec2fe258c9 100644 --- a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +++ b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp @@ -37,6 +37,8 @@ void I2SAudioMicrophone::setup() { void I2SAudioMicrophone::start() { if (this->is_failed()) return; + if (this->state_ == microphone::STATE_RUNNING) + return; // Already running this->state_ = microphone::STATE_STARTING; } void I2SAudioMicrophone::start_() { diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index 12fbdc97b4..27dc201073 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -287,6 +287,7 @@ void VoiceAssistant::loop() { } } if (this->wait_for_stream_end_) { + this->cancel_timeout("playing"); break; // We dont want to timeout here as the STREAM_END event will take care of that. } playing = this->speaker_->is_running(); From 261c271d60caa35a496cca256f667157c3ee2a4f Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 16 Oct 2023 19:41:59 +1300 Subject: [PATCH 0318/2101] Prometheus fix for esp-idf and fix newlines (#5536) --- .../prometheus/prometheus_handler.cpp | 22 ++++++++----------- .../prometheus/prometheus_handler.h | 8 ++----- 2 files changed, 11 insertions(+), 19 deletions(-) diff --git a/esphome/components/prometheus/prometheus_handler.cpp b/esphome/components/prometheus/prometheus_handler.cpp index abb5111aaf..68bca95a21 100644 --- a/esphome/components/prometheus/prometheus_handler.cpp +++ b/esphome/components/prometheus/prometheus_handler.cpp @@ -1,5 +1,3 @@ -#ifdef USE_ARDUINO - #include "prometheus_handler.h" #include "esphome/core/application.h" @@ -89,7 +87,7 @@ void PrometheusHandler::sensor_row_(AsyncResponseStream *stream, sensor::Sensor stream->print(obj->get_unit_of_measurement().c_str()); stream->print(F("\"} ")); stream->print(value_accuracy_to_string(obj->state, obj->get_accuracy_decimals()).c_str()); - stream->print('\n'); + stream->print(F("\n")); } else { // Invalid state stream->print(F("esphome_sensor_failed{id=\"")); @@ -124,7 +122,7 @@ void PrometheusHandler::binary_sensor_row_(AsyncResponseStream *stream, binary_s stream->print(relabel_name_(obj).c_str()); stream->print(F("\"} ")); stream->print(obj->state); - stream->print('\n'); + stream->print(F("\n")); } else { // Invalid state stream->print(F("esphome_binary_sensor_failed{id=\"")); @@ -158,7 +156,7 @@ void PrometheusHandler::fan_row_(AsyncResponseStream *stream, fan::Fan *obj) { stream->print(relabel_name_(obj).c_str()); stream->print(F("\"} ")); stream->print(obj->state); - stream->print('\n'); + stream->print(F("\n")); // Speed if available if (obj->get_traits().supports_speed()) { stream->print(F("esphome_fan_speed{id=\"")); @@ -167,7 +165,7 @@ void PrometheusHandler::fan_row_(AsyncResponseStream *stream, fan::Fan *obj) { stream->print(relabel_name_(obj).c_str()); stream->print(F("\"} ")); stream->print(obj->speed); - stream->print('\n'); + stream->print(F("\n")); } // Oscillation if available if (obj->get_traits().supports_oscillation()) { @@ -177,7 +175,7 @@ void PrometheusHandler::fan_row_(AsyncResponseStream *stream, fan::Fan *obj) { stream->print(relabel_name_(obj).c_str()); stream->print(F("\"} ")); stream->print(obj->oscillating); - stream->print('\n'); + stream->print(F("\n")); } } #endif @@ -281,7 +279,7 @@ void PrometheusHandler::cover_row_(AsyncResponseStream *stream, cover::Cover *ob stream->print(relabel_name_(obj).c_str()); stream->print(F("\"} ")); stream->print(obj->position); - stream->print('\n'); + stream->print(F("\n")); if (obj->get_traits().get_supports_tilt()) { stream->print(F("esphome_cover_tilt{id=\"")); stream->print(relabel_id_(obj).c_str()); @@ -289,7 +287,7 @@ void PrometheusHandler::cover_row_(AsyncResponseStream *stream, cover::Cover *ob stream->print(relabel_name_(obj).c_str()); stream->print(F("\"} ")); stream->print(obj->tilt); - stream->print('\n'); + stream->print(F("\n")); } } else { // Invalid state @@ -322,7 +320,7 @@ void PrometheusHandler::switch_row_(AsyncResponseStream *stream, switch_::Switch stream->print(relabel_name_(obj).c_str()); stream->print(F("\"} ")); stream->print(obj->state); - stream->print('\n'); + stream->print(F("\n")); } #endif @@ -346,11 +344,9 @@ void PrometheusHandler::lock_row_(AsyncResponseStream *stream, lock::Lock *obj) stream->print(relabel_name_(obj).c_str()); stream->print(F("\"} ")); stream->print(obj->state); - stream->print('\n'); + stream->print(F("\n")); } #endif } // namespace prometheus } // namespace esphome - -#endif // USE_ARDUINO diff --git a/esphome/components/prometheus/prometheus_handler.h b/esphome/components/prometheus/prometheus_handler.h index 0ae2856ce4..a9505a3572 100644 --- a/esphome/components/prometheus/prometheus_handler.h +++ b/esphome/components/prometheus/prometheus_handler.h @@ -1,14 +1,12 @@ #pragma once -#ifdef USE_ARDUINO - #include #include -#include "esphome/core/entity_base.h" #include "esphome/components/web_server_base/web_server_base.h" -#include "esphome/core/controller.h" #include "esphome/core/component.h" +#include "esphome/core/controller.h" +#include "esphome/core/entity_base.h" namespace esphome { namespace prometheus { @@ -119,5 +117,3 @@ class PrometheusHandler : public AsyncWebHandler, public Component { } // namespace prometheus } // namespace esphome - -#endif // USE_ARDUINO From 52e8a2e9e4ec73620c3a31dc8925eb9cae19e3c5 Mon Sep 17 00:00:00 2001 From: raineth Date: Mon, 16 Oct 2023 02:42:18 -0400 Subject: [PATCH 0319/2101] Make IPAddress's operator!= compare values, not memory addresses. (#5537) Co-authored-by: Ben Winslow --- esphome/components/network/ip_address.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/network/ip_address.h b/esphome/components/network/ip_address.h index 8b05237c05..7a4d394805 100644 --- a/esphome/components/network/ip_address.h +++ b/esphome/components/network/ip_address.h @@ -87,7 +87,7 @@ struct IPAddress { bool is_ip6() { return IP_IS_V6(&ip_addr_); } std::string str() const { return ipaddr_ntoa(&ip_addr_); } bool operator==(const IPAddress &other) const { return ip_addr_cmp(&ip_addr_, &other.ip_addr_); } - bool operator!=(const IPAddress &other) const { return !(&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) { if (IP_IS_V4(&ip_addr_)) { #if LWIP_IPV6 From 97d624114d8722e84fd4ac62f841cccba5e7f725 Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 16 Oct 2023 20:47:35 +0100 Subject: [PATCH 0320/2101] Add change i2c address and allow multi conf for TB6612FNG (#5492) --- .../components/grove_tb6612fng/__init__.py | 25 +++++++++++++++++++ .../grove_tb6612fng/grove_tb6612fng.h | 11 ++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/esphome/components/grove_tb6612fng/__init__.py b/esphome/components/grove_tb6612fng/__init__.py index 75610ce9d3..7db0198a89 100644 --- a/esphome/components/grove_tb6612fng/__init__.py +++ b/esphome/components/grove_tb6612fng/__init__.py @@ -8,12 +8,15 @@ from esphome.const import ( CONF_CHANNEL, CONF_SPEED, CONF_DIRECTION, + CONF_ADDRESS, ) DEPENDENCIES = ["i2c"] CODEOWNERS = ["@max246"] +MULTI_CONF = True + grove_tb6612fng_ns = cg.esphome_ns.namespace("grove_tb6612fng") GROVE_TB6612FNG = grove_tb6612fng_ns.class_( "GroveMotorDriveTB6612FNG", cg.Component, i2c.I2CDevice @@ -33,6 +36,9 @@ GROVETB6612FNGMotorStandbyAction = grove_tb6612fng_ns.class_( GROVETB6612FNGMotorNoStandbyAction = grove_tb6612fng_ns.class_( "GROVETB6612FNGMotorNoStandbyAction", automation.Action ) +GROVETB6612FNGMotorChangeAddressAction = grove_tb6612fng_ns.class_( + "GROVETB6612FNGMotorChangeAddressAction", automation.Action +) DIRECTION_TYPE = { "FORWARD": 1, @@ -150,3 +156,22 @@ async def grove_tb6612fng_no_standby_to_code(config, action_id, template_arg, ar await cg.register_parented(var, config[CONF_ID]) return var + + +@automation.register_action( + "grove_tb6612fng.change_address", + GROVETB6612FNGMotorChangeAddressAction, + cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(GROVE_TB6612FNG), + cv.Required(CONF_ADDRESS): cv.i2c_address, + } + ), +) +async def grove_tb6612fng_change_address_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_channel = await cg.templatable(config[CONF_ADDRESS], args, int) + cg.add(var.set_address(template_channel)) + return var diff --git a/esphome/components/grove_tb6612fng/grove_tb6612fng.h b/esphome/components/grove_tb6612fng/grove_tb6612fng.h index ccdab6472a..2743ef4ed7 100644 --- a/esphome/components/grove_tb6612fng/grove_tb6612fng.h +++ b/esphome/components/grove_tb6612fng/grove_tb6612fng.h @@ -84,8 +84,7 @@ class GroveMotorDriveTB6612FNG : public Component, public i2c::I2CDevice { *************************************************************/ void set_i2c_addr(uint8_t addr); - /************************************************************* - Description + /***********************************change_address Drive a motor. Parameter chl: MOTOR_CHA or MOTOR_CHB @@ -204,5 +203,13 @@ class GROVETB6612FNGMotorNoStandbyAction : public Action, public Parented void play(Ts... x) override { this->parent_->not_standby(); } }; +template +class GROVETB6612FNGMotorChangeAddressAction : public Action, public Parented { + public: + TEMPLATABLE_VALUE(uint8_t, address) + + void play(Ts... x) override { this->parent_->set_i2c_addr(this->address_.value(x...)); } +}; + } // namespace grove_tb6612fng } // namespace esphome From 61cf566560539ba0549843d8e645242833879ddd Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 17 Oct 2023 17:18:05 +1300 Subject: [PATCH 0321/2101] Add stream start and end events (#5545) --- esphome/components/api/api.proto | 2 + esphome/components/api/api_pb2.cpp | 4 ++ esphome/components/api/api_pb2.h | 2 + .../i2s_audio/speaker/i2s_audio_speaker.cpp | 6 ++ .../voice_assistant/voice_assistant.cpp | 69 +++++++++++++++++-- .../voice_assistant/voice_assistant.h | 3 +- 6 files changed, 81 insertions(+), 5 deletions(-) diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index ec4a0f7cc9..69765c7a94 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -1459,6 +1459,8 @@ enum VoiceAssistantEvent { VOICE_ASSISTANT_WAKE_WORD_END = 10; VOICE_ASSISTANT_STT_VAD_START = 11; VOICE_ASSISTANT_STT_VAD_END = 12; + VOICE_ASSISTANT_TTS_STREAM_START = 98; + VOICE_ASSISTANT_TTS_STREAM_END = 99; } message VoiceAssistantEventData { diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index 225b213a67..65df2312e1 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -452,6 +452,10 @@ template<> const char *proto_enum_to_string(enums::V return "VOICE_ASSISTANT_STT_VAD_START"; case enums::VOICE_ASSISTANT_STT_VAD_END: return "VOICE_ASSISTANT_STT_VAD_END"; + case enums::VOICE_ASSISTANT_TTS_STREAM_START: + return "VOICE_ASSISTANT_TTS_STREAM_START"; + case enums::VOICE_ASSISTANT_TTS_STREAM_END: + return "VOICE_ASSISTANT_TTS_STREAM_END"; default: return "UNKNOWN"; } diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index a4826f09d2..4c70facf3d 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -184,6 +184,8 @@ enum VoiceAssistantEvent : uint32_t { VOICE_ASSISTANT_WAKE_WORD_END = 10, VOICE_ASSISTANT_STT_VAD_START = 11, VOICE_ASSISTANT_STT_VAD_END = 12, + VOICE_ASSISTANT_TTS_STREAM_START = 98, + VOICE_ASSISTANT_TTS_STREAM_END = 99, }; enum AlarmControlPanelState : uint32_t { ALARM_STATE_DISARMED = 0, diff --git a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp index 592a27b739..ed13e6b458 100644 --- a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +++ b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp @@ -158,8 +158,13 @@ void I2SAudioSpeaker::watch_() { if (xQueueReceive(this->event_queue_, &event, 0) == pdTRUE) { switch (event.type) { case TaskEventType::STARTING: + ESP_LOGD(TAG, "Starting I2S Audio Speaker"); + break; case TaskEventType::STARTED: + ESP_LOGD(TAG, "Started I2S Audio Speaker"); + break; case TaskEventType::STOPPING: + ESP_LOGD(TAG, "Stopping I2S Audio Speaker"); break; case TaskEventType::PLAYING: this->status_clear_warning(); @@ -170,6 +175,7 @@ void I2SAudioSpeaker::watch_() { this->player_task_handle_ = nullptr; this->parent_->unlock(); xQueueReset(this->buffer_queue_); + ESP_LOGD(TAG, "Stopped I2S Audio Speaker"); break; case TaskEventType::WARNING: ESP_LOGW(TAG, "Error writing to I2S: %s", esp_err_to_name(event.err)); diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index 448df61d80..12fbdc97b4 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -281,11 +281,14 @@ void VoiceAssistant::loop() { memmove(this->speaker_buffer_, this->speaker_buffer_ + written, this->speaker_buffer_size_ - written); this->speaker_buffer_size_ -= written; this->speaker_buffer_index_ -= written; - this->set_timeout("speaker-timeout", 1000, [this]() { this->speaker_->stop(); }); + this->set_timeout("speaker-timeout", 2000, [this]() { this->speaker_->stop(); }); } else { ESP_LOGW(TAG, "Speaker buffer full."); } } + if (this->wait_for_stream_end_) { + break; // We dont want to timeout here as the STREAM_END event will take care of that. + } playing = this->speaker_->is_running(); } #endif @@ -295,28 +298,77 @@ void VoiceAssistant::loop() { } #endif if (playing) { - this->set_timeout("playing", 100, [this]() { + this->set_timeout("playing", 2000, [this]() { this->cancel_timeout("speaker-timeout"); this->set_state_(State::IDLE, State::IDLE); }); } break; } + case State::RESPONSE_FINISHED: { +#ifdef USE_SPEAKER + if (this->speaker_ != nullptr) { + this->speaker_->stop(); + this->cancel_timeout("speaker-timeout"); + this->cancel_timeout("playing"); + this->speaker_buffer_size_ = 0; + this->speaker_buffer_index_ = 0; + memset(this->speaker_buffer_, 0, SPEAKER_BUFFER_SIZE); + } +#endif + this->wait_for_stream_end_ = false; + this->set_state_(State::IDLE, State::IDLE); + break; + } default: break; } } +static const LogString *voice_assistant_state_to_string(State state) { + switch (state) { + case State::IDLE: + return LOG_STR("IDLE"); + case State::START_MICROPHONE: + return LOG_STR("START_MICROPHONE"); + case State::STARTING_MICROPHONE: + return LOG_STR("STARTING_MICROPHONE"); + case State::WAIT_FOR_VAD: + return LOG_STR("WAIT_FOR_VAD"); + case State::WAITING_FOR_VAD: + return LOG_STR("WAITING_FOR_VAD"); + case State::START_PIPELINE: + return LOG_STR("START_PIPELINE"); + case State::STARTING_PIPELINE: + return LOG_STR("STARTING_PIPELINE"); + case State::STREAMING_MICROPHONE: + return LOG_STR("STREAMING_MICROPHONE"); + case State::STOP_MICROPHONE: + return LOG_STR("STOP_MICROPHONE"); + case State::STOPPING_MICROPHONE: + return LOG_STR("STOPPING_MICROPHONE"); + case State::AWAITING_RESPONSE: + return LOG_STR("AWAITING_RESPONSE"); + case State::STREAMING_RESPONSE: + return LOG_STR("STREAMING_RESPONSE"); + case State::RESPONSE_FINISHED: + return LOG_STR("RESPONSE_FINISHED"); + default: + return LOG_STR("UNKNOWN"); + } +}; + void VoiceAssistant::set_state_(State state) { State old_state = this->state_; this->state_ = state; - ESP_LOGD(TAG, "State changed from %d to %d", static_cast(old_state), static_cast(state)); + ESP_LOGD(TAG, "State changed from %s to %s", LOG_STR_ARG(voice_assistant_state_to_string(old_state)), + LOG_STR_ARG(voice_assistant_state_to_string(state))); } void VoiceAssistant::set_state_(State state, State desired_state) { this->set_state_(state); this->desired_state_ = desired_state; - ESP_LOGD(TAG, "Desired state set to %d", static_cast(desired_state)); + ESP_LOGD(TAG, "Desired state set to %s", LOG_STR_ARG(voice_assistant_state_to_string(desired_state))); } void VoiceAssistant::failed_to_start() { @@ -400,6 +452,7 @@ void VoiceAssistant::request_stop() { break; case State::AWAITING_RESPONSE: case State::STREAMING_RESPONSE: + case State::RESPONSE_FINISHED: break; // Let the incoming audio stream finish then it will go to idle. } } @@ -531,6 +584,14 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { this->error_trigger_->trigger(code, message); break; } + case api::enums::VOICE_ASSISTANT_TTS_STREAM_START: { + this->wait_for_stream_end_ = true; + break; + } + case api::enums::VOICE_ASSISTANT_TTS_STREAM_END: { + this->set_state_(State::RESPONSE_FINISHED, State::IDLE); + break; + } default: ESP_LOGD(TAG, "Unhandled event type: %d", msg.event_type); break; diff --git a/esphome/components/voice_assistant/voice_assistant.h b/esphome/components/voice_assistant/voice_assistant.h index ce22538a85..cd448293db 100644 --- a/esphome/components/voice_assistant/voice_assistant.h +++ b/esphome/components/voice_assistant/voice_assistant.h @@ -46,6 +46,7 @@ enum class State { STOPPING_MICROPHONE, AWAITING_RESPONSE, STREAMING_RESPONSE, + RESPONSE_FINISHED, }; class VoiceAssistant : public Component { @@ -132,10 +133,10 @@ class VoiceAssistant : public Component { uint8_t *speaker_buffer_; size_t speaker_buffer_index_{0}; size_t speaker_buffer_size_{0}; + bool wait_for_stream_end_{false}; #endif #ifdef USE_MEDIA_PLAYER media_player::MediaPlayer *media_player_{nullptr}; - bool playing_tts_{false}; #endif bool local_output_{false}; From fd7d3c4332537f58a2a52518c1bfefdca5513551 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 17 Oct 2023 20:03:39 +1300 Subject: [PATCH 0322/2101] Fix esp32_improv authorizer with no binary sensors in config (#5546) --- esphome/components/esp32_improv/esp32_improv_component.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/esphome/components/esp32_improv/esp32_improv_component.cpp b/esphome/components/esp32_improv/esp32_improv_component.cpp index 5bdf7d19fe..8a901a79e5 100644 --- a/esphome/components/esp32_improv/esp32_improv_component.cpp +++ b/esphome/components/esp32_improv/esp32_improv_component.cpp @@ -107,6 +107,7 @@ void ESP32ImprovComponent::loop() { break; } case improv::STATE_AUTHORIZED: { +#ifdef USE_BINARY_SENSOR if (this->authorizer_ != nullptr) { if (now - this->authorized_start_ > this->authorized_duration_) { ESP_LOGD(TAG, "Authorization timeout"); @@ -114,6 +115,7 @@ void ESP32ImprovComponent::loop() { return; } } +#endif if (!this->check_identify_()) { this->set_status_indicator_state_((now % 1000) < 500); } @@ -290,8 +292,10 @@ void ESP32ImprovComponent::process_incoming_data_() { void ESP32ImprovComponent::on_wifi_connect_timeout_() { this->set_error_(improv::ERROR_UNABLE_TO_CONNECT); this->set_state_(improv::STATE_AUTHORIZED); +#ifdef USE_BINARY_SENSOR if (this->authorizer_ != nullptr) this->authorized_start_ = millis(); +#endif ESP_LOGW(TAG, "Timed out trying to connect to given WiFi network"); wifi::global_wifi_component->clear_sta(); } From 1f02096edb29095c8ee5462c4a46a705bba163eb Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 17 Oct 2023 20:11:37 +1300 Subject: [PATCH 0323/2101] More voice assistant fixes (#5547) --- .../components/i2s_audio/microphone/i2s_audio_microphone.cpp | 2 ++ esphome/components/voice_assistant/voice_assistant.cpp | 1 + 2 files changed, 3 insertions(+) diff --git a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp index 44c73eb8fd..ec2fe258c9 100644 --- a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +++ b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp @@ -37,6 +37,8 @@ void I2SAudioMicrophone::setup() { void I2SAudioMicrophone::start() { if (this->is_failed()) return; + if (this->state_ == microphone::STATE_RUNNING) + return; // Already running this->state_ = microphone::STATE_STARTING; } void I2SAudioMicrophone::start_() { diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index 12fbdc97b4..27dc201073 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -287,6 +287,7 @@ void VoiceAssistant::loop() { } } if (this->wait_for_stream_end_) { + this->cancel_timeout("playing"); break; // We dont want to timeout here as the STREAM_END event will take care of that. } playing = this->speaker_->is_running(); From 5e7ce610a030307ca4cbe9347c42c6dc6fbec7d9 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 17 Oct 2023 20:15:14 +1300 Subject: [PATCH 0324/2101] Bump version to 2023.10.0b3 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index cef733b2f9..cf267a2424 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2023.10.0b2" +__version__ = "2023.10.0b3" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From b12dc98150d68e9a356c597cc16f1dfc4addf17e Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 18 Oct 2023 07:23:34 +1300 Subject: [PATCH 0325/2101] Fix default libretiny manufacturer reported to HA (#5549) --- esphome/components/libretiny/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/libretiny/__init__.py b/esphome/components/libretiny/__init__.py index b01d342a87..e36c08d522 100644 --- a/esphome/components/libretiny/__init__.py +++ b/esphome/components/libretiny/__init__.py @@ -251,7 +251,7 @@ async def component_to_code(config): # setup board config cg.add_platformio_option("board", config[CONF_BOARD]) cg.add_build_flag("-DUSE_LIBRETINY") - cg.add_build_flag(f"-DUSE_{config[CONF_COMPONENT_ID]}") + cg.add_build_flag(f"-DUSE_{config[CONF_COMPONENT_ID].upper()}") 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]]) From 6839de69c1730611ad8db6723996aea491a27581 Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Tue, 17 Oct 2023 11:30:32 -0700 Subject: [PATCH 0326/2101] add uart button (#5540) Co-authored-by: Samuel Sieb --- CODEOWNERS | 1 + esphome/components/uart/button/__init__.py | 35 +++++++++++++++++++ .../components/uart/button/uart_button.cpp | 17 +++++++++ esphome/components/uart/button/uart_button.h | 24 +++++++++++++ tests/test1.yaml | 4 +++ 5 files changed, 81 insertions(+) create mode 100644 esphome/components/uart/button/__init__.py create mode 100644 esphome/components/uart/button/uart_button.cpp create mode 100644 esphome/components/uart/button/uart_button.h diff --git a/CODEOWNERS b/CODEOWNERS index 326642e12c..b66da4fc26 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -323,6 +323,7 @@ esphome/components/tuya/sensor/* @jesserockz esphome/components/tuya/switch/* @jesserockz esphome/components/tuya/text_sensor/* @dentra esphome/components/uart/* @esphome/core +esphome/components/uart/button/* @ssieb esphome/components/ufire_ec/* @pvizeli esphome/components/ufire_ise/* @pvizeli esphome/components/ultrasonic/* @OttoWinter diff --git a/esphome/components/uart/button/__init__.py b/esphome/components/uart/button/__init__.py new file mode 100644 index 0000000000..05909516a0 --- /dev/null +++ b/esphome/components/uart/button/__init__.py @@ -0,0 +1,35 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import button, uart +from esphome.const import CONF_DATA +from esphome.core import HexInt +from .. import uart_ns, validate_raw_data + +CODEOWNERS = ["@ssieb"] + +DEPENDENCIES = ["uart"] + +UARTButton = uart_ns.class_("UARTButton", button.Button, uart.UARTDevice, cg.Component) + + +CONFIG_SCHEMA = ( + button.button_schema(UARTButton) + .extend( + { + cv.Required(CONF_DATA): validate_raw_data, + } + ) + .extend(uart.UART_DEVICE_SCHEMA) + .extend(cv.COMPONENT_SCHEMA) +) + + +async def to_code(config): + var = await button.new_button(config) + await cg.register_component(var, config) + await uart.register_uart_device(var, config) + + data = config[CONF_DATA] + if isinstance(data, bytes): + data = [HexInt(x) for x in data] + cg.add(var.set_data(data)) diff --git a/esphome/components/uart/button/uart_button.cpp b/esphome/components/uart/button/uart_button.cpp new file mode 100644 index 0000000000..4db164c400 --- /dev/null +++ b/esphome/components/uart/button/uart_button.cpp @@ -0,0 +1,17 @@ +#include "uart_button.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace uart { + +static const char *const TAG = "uart.button"; + +void UARTButton::press_action() { + ESP_LOGD(TAG, "'%s': Sending data...", this->get_name().c_str()); + this->write_array(this->data_.data(), this->data_.size()); +} + +void UARTButton::dump_config() { LOG_BUTTON("", "UART Button", this); } + +} // namespace uart +} // namespace esphome diff --git a/esphome/components/uart/button/uart_button.h b/esphome/components/uart/button/uart_button.h new file mode 100644 index 0000000000..2d600b199a --- /dev/null +++ b/esphome/components/uart/button/uart_button.h @@ -0,0 +1,24 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/components/uart/uart.h" +#include "esphome/components/button/button.h" + +#include + +namespace esphome { +namespace uart { + +class UARTButton : public button::Button, public UARTDevice, public Component { + public: + void set_data(const std::vector &data) { this->data_ = data; } + + void dump_config() override; + + protected: + void press_action() override; + std::vector data_; +}; + +} // namespace uart +} // namespace esphome diff --git a/tests/test1.yaml b/tests/test1.yaml index b9b4beb5ad..66471377f9 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -3504,6 +3504,10 @@ button: name: "restart" query_params: name: query params + - platform: uart + uart_id: uart_0 + name: UART button + data: "Pressed\r\n" ld2410: id: my_ld2410 From b0ac729a8ed17f5d5626f7911a8ca816d826acdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Bl=C3=A4se?= Date: Tue, 17 Oct 2023 20:39:05 +0200 Subject: [PATCH 0327/2101] SML: fix incomplete sign extension for abbreviated transmissions (#5544) --- esphome/components/sml/sml_parser.cpp | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/esphome/components/sml/sml_parser.cpp b/esphome/components/sml/sml_parser.cpp index 91b320a30e..3b23522b21 100644 --- a/esphome/components/sml/sml_parser.cpp +++ b/esphome/components/sml/sml_parser.cpp @@ -88,11 +88,6 @@ uint64_t bytes_to_uint(const bytes &buffer) { for (auto const value : buffer) { val = (val << 8) + value; } - // Some smart meters send 24 bit signed integers. Sign extend to 64 bit if the - // 24 bit value is negative. - if (buffer.size() == 3 && buffer[0] & 0x80) { - val |= 0xFFFFFFFFFF000000; - } return val; } @@ -100,19 +95,15 @@ int64_t bytes_to_int(const bytes &buffer) { uint64_t tmp = bytes_to_uint(buffer); int64_t val; - switch (buffer.size()) { - case 1: // int8 - val = (int8_t) tmp; - break; - case 2: // int16 - val = (int16_t) tmp; - break; - case 4: // int32 - val = (int32_t) tmp; - break; - default: // int64 - val = (int64_t) tmp; + // sign extension for abbreviations of leading ones (e.g. 3 byte transmissions, see 6.2.2 of SML protocol definition) + // see https://stackoverflow.com/questions/42534749/signed-extension-from-24-bit-to-32-bit-in-c + if (buffer.size() < 8) { + const int bits = buffer.size() * 8; + const uint64_t m = 1u << (bits - 1); + tmp = (tmp ^ m) - m; } + + val = (int64_t) tmp; return val; } From c19dbdb02dab3a328c6601971beb70b50fa874b5 Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Tue, 17 Oct 2023 12:07:29 -0700 Subject: [PATCH 0328/2101] add on/off options for uart switch (#5539) Co-authored-by: Samuel Sieb --- esphome/components/uart/switch/__init__.py | 33 +++++++++++++++---- .../components/uart/switch/uart_switch.cpp | 26 +++++++++++---- esphome/components/uart/switch/uart_switch.h | 10 ++++-- tests/test1.yaml | 6 ++++ 4 files changed, 60 insertions(+), 15 deletions(-) diff --git a/esphome/components/uart/switch/__init__.py b/esphome/components/uart/switch/__init__.py index 60f5ddaf0d..8853a61ae3 100644 --- a/esphome/components/uart/switch/__init__.py +++ b/esphome/components/uart/switch/__init__.py @@ -9,14 +9,24 @@ DEPENDENCIES = ["uart"] UARTSwitch = uart_ns.class_("UARTSwitch", switch.Switch, uart.UARTDevice, cg.Component) +CONF_TURN_OFF = "turn_off" +CONF_TURN_ON = "turn_on" CONFIG_SCHEMA = ( switch.switch_schema(UARTSwitch, block_inverted=True) .extend( { - cv.Required(CONF_DATA): validate_raw_data, + cv.Required(CONF_DATA): cv.Any( + validate_raw_data, + cv.Schema( + { + cv.Optional(CONF_TURN_OFF): validate_raw_data, + cv.Optional(CONF_TURN_ON): validate_raw_data, + } + ), + ), cv.Optional(CONF_SEND_EVERY): cv.positive_time_period_milliseconds, - } + }, ) .extend(uart.UART_DEVICE_SCHEMA) .extend(cv.COMPONENT_SCHEMA) @@ -29,9 +39,20 @@ async def to_code(config): await uart.register_uart_device(var, config) data = config[CONF_DATA] - if isinstance(data, bytes): - data = [HexInt(x) for x in data] - cg.add(var.set_data(data)) - + if isinstance(data, dict): + if data_on := data.get(CONF_TURN_ON): + if isinstance(data_on, bytes): + data_on = [HexInt(x) for x in data_on] + cg.add(var.set_data_on(data_on)) + if data_off := data.get(CONF_TURN_OFF): + if isinstance(data_off, bytes): + data_off = [HexInt(x) for x in data_off] + cg.add(var.set_data_off(data_off)) + else: + data = config[CONF_DATA] + if isinstance(data, bytes): + data = [HexInt(x) for x in data] + cg.add(var.set_data_on(data)) + cg.add(var.set_single_state(True)) if CONF_SEND_EVERY in config: cg.add(var.set_send_every(config[CONF_SEND_EVERY])) diff --git a/esphome/components/uart/switch/uart_switch.cpp b/esphome/components/uart/switch/uart_switch.cpp index ffed08c731..b995aca98c 100644 --- a/esphome/components/uart/switch/uart_switch.cpp +++ b/esphome/components/uart/switch/uart_switch.cpp @@ -7,28 +7,41 @@ namespace uart { static const char *const TAG = "uart.switch"; void UARTSwitch::loop() { - if (this->state && this->send_every_) { + if (this->send_every_) { const uint32_t now = millis(); if (now - this->last_transmission_ > this->send_every_) { - this->write_command_(); + this->write_command_(this->state); this->last_transmission_ = now; } } } -void UARTSwitch::write_command_() { - ESP_LOGD(TAG, "'%s': Sending data...", this->get_name().c_str()); - this->write_array(this->data_.data(), this->data_.size()); +void UARTSwitch::write_command_(bool state) { + if (state && !this->data_on_.empty()) { + ESP_LOGD(TAG, "'%s': Sending on data...", this->get_name().c_str()); + this->write_array(this->data_on_.data(), this->data_on_.size()); + } + if (!state && !this->data_off_.empty()) { + ESP_LOGD(TAG, "'%s': Sending off data...", this->get_name().c_str()); + this->write_array(this->data_off_.data(), this->data_off_.size()); + } } void UARTSwitch::write_state(bool state) { + if (!this->single_state_) { + this->publish_state(state); + this->write_command_(state); + this->last_transmission_ = millis(); + return; + } + if (!state) { this->publish_state(false); return; } this->publish_state(true); - this->write_command_(); + this->write_command_(true); if (this->send_every_ == 0) { this->publish_state(false); @@ -36,6 +49,7 @@ void UARTSwitch::write_state(bool state) { this->last_transmission_ = millis(); } } + void UARTSwitch::dump_config() { LOG_SWITCH("", "UART Switch", this); if (this->send_every_) { diff --git a/esphome/components/uart/switch/uart_switch.h b/esphome/components/uart/switch/uart_switch.h index 4f24d76d0c..eb3d697a58 100644 --- a/esphome/components/uart/switch/uart_switch.h +++ b/esphome/components/uart/switch/uart_switch.h @@ -13,15 +13,19 @@ class UARTSwitch : public switch_::Switch, public UARTDevice, public Component { public: void loop() override; - void set_data(const std::vector &data) { data_ = data; } + void set_data_on(const std::vector &data) { this->data_on_ = data; } + void set_data_off(const std::vector &data) { this->data_off_ = data; } void set_send_every(uint32_t send_every) { this->send_every_ = send_every; } + void set_single_state(bool single) { this->single_state_ = single; } void dump_config() override; protected: - void write_command_(); + void write_command_(bool state); void write_state(bool state) override; - std::vector data_; + std::vector data_on_; + std::vector data_off_; + bool single_state_{false}; uint32_t send_every_; uint32_t last_transmission_; }; diff --git a/tests/test1.yaml b/tests/test1.yaml index 66471377f9..9bf9a32e17 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -2588,6 +2588,12 @@ switch: name: UART Recurring Output data: [0xDE, 0xAD, 0xBE, 0xEF] send_every: 1s + - platform: uart + uart_id: uart_0 + name: "UART On/Off" + data: + turn_on: "TurnOn\r\n" + turn_off: "TurnOff\r\n" - platform: template assumed_state: true name: Stepper Switch From 14aa27f5e2df02dbe251f72ef0869e87405c15a0 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 18 Oct 2023 14:26:47 +1300 Subject: [PATCH 0329/2101] esp32_improv advertise capabilities and state in ble service data (#5553) --- .../components/esp32_ble/ble_advertising.cpp | 21 +++++++++++++------ .../components/esp32_ble/ble_advertising.h | 1 + .../esp32_improv/esp32_improv_component.cpp | 19 +++++++++++++++++ 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/esphome/components/esp32_ble/ble_advertising.cpp b/esphome/components/esp32_ble/ble_advertising.cpp index 072bb38c07..59d2398829 100644 --- a/esphome/components/esp32_ble/ble_advertising.cpp +++ b/esphome/components/esp32_ble/ble_advertising.cpp @@ -2,9 +2,9 @@ #ifdef USE_ESP32 -#include "ble_uuid.h" -#include #include +#include +#include "ble_uuid.h" #include "esphome/core/log.h" namespace esphome { @@ -16,8 +16,8 @@ BLEAdvertising::BLEAdvertising() { this->advertising_data_.set_scan_rsp = false; this->advertising_data_.include_name = true; this->advertising_data_.include_txpower = true; - this->advertising_data_.min_interval = 0x20; - this->advertising_data_.max_interval = 0x40; + this->advertising_data_.min_interval = 0; + this->advertising_data_.max_interval = 0; this->advertising_data_.appearance = 0x00; this->advertising_data_.manufacturer_len = 0; this->advertising_data_.p_manufacturer_data = nullptr; @@ -42,6 +42,17 @@ void BLEAdvertising::remove_service_uuid(ESPBTUUID uuid) { this->advertising_uuids_.end()); } +void BLEAdvertising::set_service_data(const std::vector &data) { + delete[] this->advertising_data_.p_service_data; + this->advertising_data_.p_service_data = nullptr; + this->advertising_data_.service_data_len = data.size(); + if (!data.empty()) { + // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) + this->advertising_data_.p_service_data = new uint8_t[data.size()]; + memcpy(this->advertising_data_.p_service_data, data.data(), data.size()); + } +} + void BLEAdvertising::set_manufacturer_data(const std::vector &data) { delete[] this->advertising_data_.p_manufacturer_data; this->advertising_data_.p_manufacturer_data = nullptr; @@ -85,8 +96,6 @@ void BLEAdvertising::start() { this->scan_response_data_.set_scan_rsp = true; this->scan_response_data_.include_name = true; this->scan_response_data_.include_txpower = true; - this->scan_response_data_.min_interval = 0; - this->scan_response_data_.max_interval = 0; this->scan_response_data_.manufacturer_len = 0; this->scan_response_data_.appearance = 0; this->scan_response_data_.flag = 0; diff --git a/esphome/components/esp32_ble/ble_advertising.h b/esphome/components/esp32_ble/ble_advertising.h index 9e4e2b7701..16a7dd1d8e 100644 --- a/esphome/components/esp32_ble/ble_advertising.h +++ b/esphome/components/esp32_ble/ble_advertising.h @@ -21,6 +21,7 @@ class BLEAdvertising { void set_scan_response(bool scan_response) { this->scan_response_ = scan_response; } void set_min_preferred_interval(uint16_t interval) { this->advertising_data_.min_interval = interval; } void set_manufacturer_data(const std::vector &data); + void set_service_data(const std::vector &data); void start(); void stop(); diff --git a/esphome/components/esp32_improv/esp32_improv_component.cpp b/esphome/components/esp32_improv/esp32_improv_component.cpp index 8a901a79e5..19340c3dd8 100644 --- a/esphome/components/esp32_improv/esp32_improv_component.cpp +++ b/esphome/components/esp32_improv/esp32_improv_component.cpp @@ -189,6 +189,25 @@ void ESP32ImprovComponent::set_state_(improv::State state) { if (state != improv::STATE_STOPPED) this->status_->notify(); } + std::vector service_data(8, 0); + service_data[0] = 0x77; // PR + service_data[1] = 0x46; // IM + service_data[2] = static_cast(state); + + uint8_t capabilities = 0x00; +#ifdef USE_OUTPUT + if (this->status_indicator_ != nullptr) + capabilities |= improv::CAPABILITY_IDENTIFY; +#endif + + service_data[3] = capabilities; + service_data[4] = 0x00; // Reserved + service_data[5] = 0x00; // Reserved + service_data[6] = 0x00; // Reserved + service_data[7] = 0x00; // Reserved + + esp32_ble::global_ble->get_advertising()->set_service_data(service_data); + esp32_ble::global_ble->get_advertising()->start(); } void ESP32ImprovComponent::set_error_(improv::Error error) { From cc4c0e3e0bee6a88aa898e86bba48755b4c71d80 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 18 Oct 2023 07:23:34 +1300 Subject: [PATCH 0330/2101] Fix default libretiny manufacturer reported to HA (#5549) --- esphome/components/libretiny/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/libretiny/__init__.py b/esphome/components/libretiny/__init__.py index b01d342a87..e36c08d522 100644 --- a/esphome/components/libretiny/__init__.py +++ b/esphome/components/libretiny/__init__.py @@ -251,7 +251,7 @@ async def component_to_code(config): # setup board config cg.add_platformio_option("board", config[CONF_BOARD]) cg.add_build_flag("-DUSE_LIBRETINY") - cg.add_build_flag(f"-DUSE_{config[CONF_COMPONENT_ID]}") + cg.add_build_flag(f"-DUSE_{config[CONF_COMPONENT_ID].upper()}") 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]]) From 51688d40780f2ef203e701b4d224c3abee283c23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Bl=C3=A4se?= Date: Tue, 17 Oct 2023 20:39:05 +0200 Subject: [PATCH 0331/2101] SML: fix incomplete sign extension for abbreviated transmissions (#5544) --- esphome/components/sml/sml_parser.cpp | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/esphome/components/sml/sml_parser.cpp b/esphome/components/sml/sml_parser.cpp index 91b320a30e..3b23522b21 100644 --- a/esphome/components/sml/sml_parser.cpp +++ b/esphome/components/sml/sml_parser.cpp @@ -88,11 +88,6 @@ uint64_t bytes_to_uint(const bytes &buffer) { for (auto const value : buffer) { val = (val << 8) + value; } - // Some smart meters send 24 bit signed integers. Sign extend to 64 bit if the - // 24 bit value is negative. - if (buffer.size() == 3 && buffer[0] & 0x80) { - val |= 0xFFFFFFFFFF000000; - } return val; } @@ -100,19 +95,15 @@ int64_t bytes_to_int(const bytes &buffer) { uint64_t tmp = bytes_to_uint(buffer); int64_t val; - switch (buffer.size()) { - case 1: // int8 - val = (int8_t) tmp; - break; - case 2: // int16 - val = (int16_t) tmp; - break; - case 4: // int32 - val = (int32_t) tmp; - break; - default: // int64 - val = (int64_t) tmp; + // sign extension for abbreviations of leading ones (e.g. 3 byte transmissions, see 6.2.2 of SML protocol definition) + // see https://stackoverflow.com/questions/42534749/signed-extension-from-24-bit-to-32-bit-in-c + if (buffer.size() < 8) { + const int bits = buffer.size() * 8; + const uint64_t m = 1u << (bits - 1); + tmp = (tmp ^ m) - m; } + + val = (int64_t) tmp; return val; } From 2189a40a39951f931b692a5f9aa8326ec41e3726 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 18 Oct 2023 14:26:47 +1300 Subject: [PATCH 0332/2101] esp32_improv advertise capabilities and state in ble service data (#5553) --- .../components/esp32_ble/ble_advertising.cpp | 21 +++++++++++++------ .../components/esp32_ble/ble_advertising.h | 1 + .../esp32_improv/esp32_improv_component.cpp | 19 +++++++++++++++++ 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/esphome/components/esp32_ble/ble_advertising.cpp b/esphome/components/esp32_ble/ble_advertising.cpp index 072bb38c07..59d2398829 100644 --- a/esphome/components/esp32_ble/ble_advertising.cpp +++ b/esphome/components/esp32_ble/ble_advertising.cpp @@ -2,9 +2,9 @@ #ifdef USE_ESP32 -#include "ble_uuid.h" -#include #include +#include +#include "ble_uuid.h" #include "esphome/core/log.h" namespace esphome { @@ -16,8 +16,8 @@ BLEAdvertising::BLEAdvertising() { this->advertising_data_.set_scan_rsp = false; this->advertising_data_.include_name = true; this->advertising_data_.include_txpower = true; - this->advertising_data_.min_interval = 0x20; - this->advertising_data_.max_interval = 0x40; + this->advertising_data_.min_interval = 0; + this->advertising_data_.max_interval = 0; this->advertising_data_.appearance = 0x00; this->advertising_data_.manufacturer_len = 0; this->advertising_data_.p_manufacturer_data = nullptr; @@ -42,6 +42,17 @@ void BLEAdvertising::remove_service_uuid(ESPBTUUID uuid) { this->advertising_uuids_.end()); } +void BLEAdvertising::set_service_data(const std::vector &data) { + delete[] this->advertising_data_.p_service_data; + this->advertising_data_.p_service_data = nullptr; + this->advertising_data_.service_data_len = data.size(); + if (!data.empty()) { + // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) + this->advertising_data_.p_service_data = new uint8_t[data.size()]; + memcpy(this->advertising_data_.p_service_data, data.data(), data.size()); + } +} + void BLEAdvertising::set_manufacturer_data(const std::vector &data) { delete[] this->advertising_data_.p_manufacturer_data; this->advertising_data_.p_manufacturer_data = nullptr; @@ -85,8 +96,6 @@ void BLEAdvertising::start() { this->scan_response_data_.set_scan_rsp = true; this->scan_response_data_.include_name = true; this->scan_response_data_.include_txpower = true; - this->scan_response_data_.min_interval = 0; - this->scan_response_data_.max_interval = 0; this->scan_response_data_.manufacturer_len = 0; this->scan_response_data_.appearance = 0; this->scan_response_data_.flag = 0; diff --git a/esphome/components/esp32_ble/ble_advertising.h b/esphome/components/esp32_ble/ble_advertising.h index 9e4e2b7701..16a7dd1d8e 100644 --- a/esphome/components/esp32_ble/ble_advertising.h +++ b/esphome/components/esp32_ble/ble_advertising.h @@ -21,6 +21,7 @@ class BLEAdvertising { void set_scan_response(bool scan_response) { this->scan_response_ = scan_response; } void set_min_preferred_interval(uint16_t interval) { this->advertising_data_.min_interval = interval; } void set_manufacturer_data(const std::vector &data); + void set_service_data(const std::vector &data); void start(); void stop(); diff --git a/esphome/components/esp32_improv/esp32_improv_component.cpp b/esphome/components/esp32_improv/esp32_improv_component.cpp index 8a901a79e5..19340c3dd8 100644 --- a/esphome/components/esp32_improv/esp32_improv_component.cpp +++ b/esphome/components/esp32_improv/esp32_improv_component.cpp @@ -189,6 +189,25 @@ void ESP32ImprovComponent::set_state_(improv::State state) { if (state != improv::STATE_STOPPED) this->status_->notify(); } + std::vector service_data(8, 0); + service_data[0] = 0x77; // PR + service_data[1] = 0x46; // IM + service_data[2] = static_cast(state); + + uint8_t capabilities = 0x00; +#ifdef USE_OUTPUT + if (this->status_indicator_ != nullptr) + capabilities |= improv::CAPABILITY_IDENTIFY; +#endif + + service_data[3] = capabilities; + service_data[4] = 0x00; // Reserved + service_data[5] = 0x00; // Reserved + service_data[6] = 0x00; // Reserved + service_data[7] = 0x00; // Reserved + + esp32_ble::global_ble->get_advertising()->set_service_data(service_data); + esp32_ble::global_ble->get_advertising()->start(); } void ESP32ImprovComponent::set_error_(improv::Error error) { From 2aa787f5f0546fbb550ececaffe9d43f019b3053 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 18 Oct 2023 14:28:03 +1300 Subject: [PATCH 0333/2101] Bump version to 2023.10.0b4 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index cf267a2424..fead0a5f1f 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2023.10.0b3" +__version__ = "2023.10.0b4" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 582b8383d248cd1a8cfd17c3bba39b6341868c52 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 18 Oct 2023 16:47:03 +1300 Subject: [PATCH 0334/2101] Bump version to 2023.10.0 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index fead0a5f1f..30e7fd7b8e 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2023.10.0b4" +__version__ = "2023.10.0" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 8ef743f25e3387ef69fb6f9cb000a492b6bbb2b2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 17 Oct 2023 20:33:19 -1000 Subject: [PATCH 0335/2101] Update docker base and packages + docker python 3.11 (#5473) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- docker/Dockerfile | 73 ++++++++++++++++++++++----------------- requirements_optional.txt | 4 +-- 2 files changed, 44 insertions(+), 33 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 5ca36d1c13..f076173519 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -6,38 +6,47 @@ ARG BASEIMGTYPE=docker # https://github.com/hassio-addons/addon-debian-base/releases -FROM ghcr.io/hassio-addons/debian-base:6.2.3 AS base-hassio -# https://hub.docker.com/_/debian?tab=tags&page=1&name=bullseye -FROM debian:bullseye-20230208-slim AS base-docker +FROM ghcr.io/hassio-addons/debian-base:7.2.0 AS base-hassio +# https://hub.docker.com/_/debian?tab=tags&page=1&name=bookworm +FROM debian:12.2-slim AS base-docker FROM base-${BASEIMGTYPE} AS base ARG TARGETARCH ARG TARGETVARIANT +# Note that --break-system-packages is used below because +# https://peps.python.org/pep-0668/ added a safety check that prevents +# installing packages with the same name as a system package. This is +# not a problem for us because we are not concerned about overwriting +# system packages because we are running in an isolated container. + RUN \ apt-get update \ # Use pinned versions so that we get updates with build caching && apt-get install -y --no-install-recommends \ - python3=3.9.2-3 \ - python3-pip=20.3.4-4+deb11u1 \ - python3-setuptools=52.0.0-4 \ - python3-cryptography=3.3.2-1 \ - python3-venv=3.9.2-3 \ - iputils-ping=3:20210202-1 \ - git=1:2.30.2-1+deb11u2 \ - curl=7.74.0-1.3+deb11u10 \ - openssh-client=1:8.4p1-5+deb11u2 \ - python3-cffi=1.14.5-1 \ - libcairo2=1.16.0-5 \ + python3-pip=23.0.1+dfsg-1 \ + python3-setuptools=66.1.1-1 \ + python3-venv=3.11.2-1+b1 \ + python3-wheel=0.38.4-2 \ + iputils-ping=3:20221126-1 \ + git=1:2.39.2-1.1 \ + curl=7.88.1-10+deb12u4 \ + openssh-client=1:9.2p1-2+deb12u1 \ + python3-cffi=1.15.1-5 \ + libcairo2=1.16.0-7 \ patch=2.7.6-7; \ if [ "$TARGETARCH$TARGETVARIANT" = "armv7" ]; then \ apt-get install -y --no-install-recommends \ build-essential=12.9 \ - python3-dev=3.9.2-3 \ - zlib1g-dev=1:1.2.11.dfsg-2+deb11u2 \ - libjpeg-dev=1:2.0.6-4 \ - libfreetype-dev=2.10.4+dfsg-1+deb11u1; \ + python3-dev=3.11.2-1+b1 \ + zlib1g-dev=1:1.2.13.dfsg-1 \ + libjpeg-dev=1:2.1.5-2 \ + libfreetype-dev=2.12.1+dfsg-5 \ + libssl-dev=3.0.11-1~deb12u1 \ + libffi-dev=3.4.4-1 \ + cargo=0.66.0+ds1-1 \ + pkg-config=1.8.1-1; \ fi; \ rm -rf \ /tmp/* \ @@ -50,6 +59,7 @@ ENV \ # Store globally installed pio libs in /piolibs PLATFORMIO_GLOBALLIB_DIR=/piolibs + # Support legacy binaries on Debian multiarch system. There is no "correct" way # to do this, other than using properly built toolchains... # See: https://unix.stackexchange.com/questions/553743/correct-way-to-add-lib-ld-linux-so-3-in-debian @@ -60,8 +70,7 @@ RUN \ RUN \ # Ubuntu python3-pip is missing wheel - pip3 install --no-cache-dir \ - wheel==0.37.1 \ + pip3 install --break-system-packages --no-cache-dir \ platformio==6.1.11 \ # Change some platformio settings && platformio settings set enable_telemetry No \ @@ -70,9 +79,11 @@ RUN \ # First install requirements to leverage caching when requirements don't change +# tmpfs is for https://github.com/rust-lang/cargo/issues/8719 + COPY requirements.txt requirements_optional.txt script/platformio_install_deps.py platformio.ini / -RUN \ - pip3 install --no-cache-dir -r /requirements.txt -r /requirements_optional.txt \ +RUN --mount=type=tmpfs,target=/root/.cargo CARGO_REGISTRIES_CRATES_IO_PROTOCOL=sparse CARGO_HOME=/root/.cargo \ + pip3 install --break-system-packages --no-cache-dir -r /requirements.txt -r /requirements_optional.txt \ && /platformio_install_deps.py /platformio.ini --libraries @@ -81,7 +92,7 @@ FROM base AS docker # Copy esphome and install COPY . /esphome -RUN pip3 install --no-cache-dir --no-use-pep517 -e /esphome +RUN pip3 install --break-system-packages --no-cache-dir --no-use-pep517 -e /esphome # Settings for dashboard ENV USERNAME="" PASSWORD="" @@ -110,7 +121,7 @@ RUN \ apt-get update \ # Use pinned versions so that we get updates with build caching && apt-get install -y --no-install-recommends \ - nginx-light=1.18.0-6.1+deb11u3 \ + nginx-light=1.22.1-9 \ && rm -rf \ /tmp/* \ /var/{cache,log}/* \ @@ -123,7 +134,7 @@ COPY docker/ha-addon-rootfs/ / # Copy esphome and install COPY . /esphome -RUN pip3 install --no-cache-dir --no-use-pep517 -e /esphome +RUN pip3 install --break-system-packages --no-cache-dir --no-use-pep517 -e /esphome # Labels LABEL \ @@ -146,20 +157,20 @@ RUN \ apt-get update \ # Use pinned versions so that we get updates with build caching && apt-get install -y --no-install-recommends \ - clang-format-13=1:13.0.1-6~deb11u1 \ - clang-tidy-11=1:11.0.1-2 \ + clang-format-13=1:13.0.1-11+b2 \ + clang-tidy-14=1:14.0.6-12 \ patch=2.7.6-7 \ - software-properties-common=0.96.20.2-2.1 \ - nano=5.4-2+deb11u2 \ + software-properties-common=0.99.30-4 \ + nano=7.2-1 \ build-essential=12.9 \ - python3-dev=3.9.2-3 \ + python3-dev=3.11.2-1+b1 \ && rm -rf \ /tmp/* \ /var/{cache,log}/* \ /var/lib/apt/lists/* COPY requirements_test.txt / -RUN pip3 install --no-cache-dir -r /requirements_test.txt +RUN pip3 install --break-system-packages --no-cache-dir -r /requirements_test.txt VOLUME ["/esphome"] WORKDIR /esphome diff --git a/requirements_optional.txt b/requirements_optional.txt index 236f5e3f13..40c27f8547 100644 --- a/requirements_optional.txt +++ b/requirements_optional.txt @@ -1,3 +1,3 @@ pillow==10.0.1 -cairosvg>=2.2.0 -cryptography>=2.0.0,<4 +cairosvg==2.7.1 +cryptography==41.0.4 From cdc4f7f59b53d185bf1a252dd57a24c648ba47ff Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Wed, 18 Oct 2023 01:33:36 -0500 Subject: [PATCH 0336/2101] IDF 5 fixes for various components from test1.yaml (#5451) --- esphome/components/binary_sensor/automation.cpp | 11 ++++++----- esphome/components/binary_sensor/automation.h | 1 + esphome/components/canbus/canbus.cpp | 16 +++++++++------- esphome/components/canbus/canbus.h | 1 + .../components/climate_ir_lg/climate_ir_lg.cpp | 4 ++-- esphome/components/climate_ir_lg/climate_ir_lg.h | 2 ++ esphome/components/coolix/coolix.cpp | 4 ++-- esphome/components/coolix/coolix.h | 2 ++ esphome/components/cs5460a/cs5460a.cpp | 4 ++-- esphome/components/cs5460a/cs5460a.h | 2 ++ .../deep_sleep/deep_sleep_component.cpp | 13 +++++++------ .../components/deep_sleep/deep_sleep_component.h | 2 ++ esphome/components/e131/e131.h | 1 + .../e131/e131_addressable_light_effect.cpp | 4 ++-- esphome/components/hlw8012/hlw8012.cpp | 2 +- esphome/components/hlw8012/hlw8012.h | 2 ++ esphome/components/hx711/hx711.cpp | 2 +- esphome/components/hx711/hx711.h | 2 ++ esphome/components/hyt271/hyt271.cpp | 2 +- esphome/components/ili9xxx/ili9xxx_display.cpp | 2 +- esphome/components/ili9xxx/ili9xxx_init.h | 2 ++ esphome/components/ina219/ina219.cpp | 2 +- esphome/components/ina219/ina219.h | 2 ++ esphome/components/max31855/max31855.cpp | 10 +++++----- esphome/components/max31855/max31855.h | 2 ++ esphome/components/max31856/max31856.cpp | 2 +- esphome/components/max31856/max31856.h | 2 ++ esphome/components/mitsubishi/mitsubishi.cpp | 4 ++-- esphome/components/mitsubishi/mitsubishi.h | 2 ++ esphome/components/ota/__init__.py | 2 +- esphome/components/ota/automation.h | 2 +- esphome/components/power_supply/power_supply.cpp | 2 +- esphome/components/power_supply/power_supply.h | 2 ++ .../pulse_counter/pulse_counter_sensor.cpp | 6 +++--- .../pulse_counter/pulse_counter_sensor.h | 2 ++ .../pulse_meter/pulse_meter_sensor.cpp | 12 +++++++----- .../components/pulse_meter/pulse_meter_sensor.h | 2 ++ .../pvvx_mithermometer/display/pvvx_display.cpp | 6 +++++- .../pvvx_mithermometer/display/pvvx_display.h | 2 ++ esphome/components/rdm6300/rdm6300.cpp | 2 +- esphome/components/rdm6300/rdm6300.h | 1 + esphome/components/remote_base/__init__.py | 13 ++++--------- .../components/remote_base/coolix_protocol.cpp | 6 +++--- esphome/components/remote_base/coolix_protocol.h | 2 ++ .../components/remote_base/drayton_protocol.cpp | 6 +++--- .../components/remote_base/drayton_protocol.h | 2 ++ esphome/components/remote_base/jvc_protocol.cpp | 2 +- esphome/components/remote_base/jvc_protocol.h | 2 ++ esphome/components/remote_base/lg_protocol.cpp | 2 +- esphome/components/remote_base/lg_protocol.h | 2 ++ .../remote_base/magiquest_protocol.cpp | 2 +- .../components/remote_base/magiquest_protocol.h | 2 ++ esphome/components/remote_base/nexa_protocol.cpp | 2 +- esphome/components/remote_base/nexa_protocol.h | 2 ++ .../remote_base/panasonic_protocol.cpp | 2 +- .../components/remote_base/panasonic_protocol.h | 2 ++ esphome/components/remote_base/raw_protocol.cpp | 8 ++++---- esphome/components/remote_base/raw_protocol.h | 1 + .../remote_base/samsung36_protocol.cpp | 2 +- .../components/remote_base/samsung36_protocol.h | 2 ++ esphome/components/remote_base/sony_protocol.cpp | 2 +- esphome/components/remote_base/sony_protocol.h | 2 ++ .../components/remote_receiver/remote_receiver.h | 2 ++ .../remote_receiver/remote_receiver_esp32.cpp | 2 +- esphome/components/sgp30/sgp30.cpp | 2 +- esphome/components/sgp30/sgp30.h | 2 ++ esphome/components/sht3xd/sht3xd.cpp | 2 +- esphome/components/sht3xd/sht3xd.h | 2 ++ esphome/components/sht4x/sht4x.cpp | 2 +- esphome/components/sht4x/sht4x.h | 2 ++ esphome/components/sts3x/sts3x.cpp | 2 +- esphome/components/sts3x/sts3x.h | 2 ++ .../template_alarm_control_panel.cpp | 12 ++++++------ .../template_alarm_control_panel.h | 1 + esphome/components/tsl2591/tsl2591.cpp | 4 ++-- esphome/components/tsl2591/tsl2591.h | 2 ++ esphome/components/uart/switch/uart_switch.cpp | 2 +- esphome/components/uart/switch/uart_switch.h | 1 + .../components/ultrasonic/ultrasonic_sensor.cpp | 6 +++--- .../components/ultrasonic/ultrasonic_sensor.h | 2 ++ esphome/components/whynter/whynter.cpp | 4 ++-- esphome/components/whynter/whynter.h | 2 ++ 82 files changed, 173 insertions(+), 97 deletions(-) diff --git a/esphome/components/binary_sensor/automation.cpp b/esphome/components/binary_sensor/automation.cpp index ce082aafb3..bfec882e07 100644 --- a/esphome/components/binary_sensor/automation.cpp +++ b/esphome/components/binary_sensor/automation.cpp @@ -22,7 +22,7 @@ void binary_sensor::MultiClickTrigger::on_state_(bool state) { // Start matching MultiClickTriggerEvent evt = this->timing_[0]; if (evt.state == state) { - ESP_LOGV(TAG, "START min=%u max=%u", 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) { @@ -51,15 +51,15 @@ void binary_sensor::MultiClickTrigger::on_state_(bool state) { MultiClickTriggerEvent evt = this->timing_[*this->at_index_]; if (evt.max_length != 4294967294UL) { - ESP_LOGV(TAG, "A i=%u min=%u max=%u", *this->at_index_, evt.min_length, evt.max_length); // NOLINT + ESP_LOGV(TAG, "A i=%u 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()) { - ESP_LOGV(TAG, "B i=%u min=%u", *this->at_index_, evt.min_length); // NOLINT + ESP_LOGV(TAG, "B i=%u min=%" PRIu32, *this->at_index_, evt.min_length); // NOLINT this->cancel_timeout("is_not_valid"); this->schedule_is_valid_(evt.min_length); } else { - ESP_LOGV(TAG, "C i=%u min=%u", *this->at_index_, evt.min_length); // NOLINT + ESP_LOGV(TAG, "C i=%u 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_(); }); @@ -68,7 +68,8 @@ void binary_sensor::MultiClickTrigger::on_state_(bool state) { *this->at_index_ = *this->at_index_ + 1; } void binary_sensor::MultiClickTrigger::schedule_cooldown_() { - ESP_LOGV(TAG, "Multi Click: Invalid length of press, starting cooldown of %u ms...", this->invalid_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]() { ESP_LOGV(TAG, "Multi Click: Cooldown ended, matching is now enabled again."); diff --git a/esphome/components/binary_sensor/automation.h b/esphome/components/binary_sensor/automation.h index de527d1070..a5e9d208a1 100644 --- a/esphome/components/binary_sensor/automation.h +++ b/esphome/components/binary_sensor/automation.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include diff --git a/esphome/components/canbus/canbus.cpp b/esphome/components/canbus/canbus.cpp index 6316c77ff4..8cffebdaa0 100644 --- a/esphome/components/canbus/canbus.cpp +++ b/esphome/components/canbus/canbus.cpp @@ -16,9 +16,9 @@ void Canbus::setup() { void Canbus::dump_config() { if (this->use_extended_id_) { - ESP_LOGCONFIG(TAG, "config extended id=0x%08x", this->can_id_); + ESP_LOGCONFIG(TAG, "config extended id=0x%08" PRIx32, this->can_id_); } else { - ESP_LOGCONFIG(TAG, "config standard id=0x%03x", this->can_id_); + ESP_LOGCONFIG(TAG, "config standard id=0x%03" PRIx32, this->can_id_); } } @@ -28,9 +28,11 @@ void Canbus::send_data(uint32_t can_id, bool use_extended_id, bool remote_transm uint8_t size = static_cast(data.size()); if (use_extended_id) { - ESP_LOGD(TAG, "send extended id=0x%08x rtr=%s size=%d", can_id, TRUEFALSE(remote_transmission_request), size); + ESP_LOGD(TAG, "send extended id=0x%08" PRIx32 " rtr=%s size=%d", can_id, TRUEFALSE(remote_transmission_request), + size); } else { - ESP_LOGD(TAG, "send standard id=0x%03x rtr=%s size=%d", can_id, TRUEFALSE(remote_transmission_request), size); + ESP_LOGD(TAG, "send standard id=0x%03" PRIx32 " rtr=%s size=%d", can_id, TRUEFALSE(remote_transmission_request), + size); } if (size > CAN_MAX_DATA_LENGTH) size = CAN_MAX_DATA_LENGTH; @@ -63,10 +65,10 @@ void Canbus::loop() { while (this->read_message(&can_message) == canbus::ERROR_OK) { message_counter++; if (can_message.use_extended_id) { - ESP_LOGD(TAG, "received can message (#%d) extended can_id=0x%x size=%d", message_counter, can_message.can_id, - can_message.can_data_length_code); + ESP_LOGD(TAG, "received can message (#%d) extended can_id=0x%" PRIx32 " size=%d", message_counter, + can_message.can_id, can_message.can_data_length_code); } else { - ESP_LOGD(TAG, "received can message (#%d) std can_id=0x%x size=%d", message_counter, can_message.can_id, + ESP_LOGD(TAG, "received can message (#%d) std can_id=0x%" PRIx32 " size=%d", message_counter, can_message.can_id, can_message.can_data_length_code); } diff --git a/esphome/components/canbus/canbus.h b/esphome/components/canbus/canbus.h index c0ccff4866..1e5214fef4 100644 --- a/esphome/components/canbus/canbus.h +++ b/esphome/components/canbus/canbus.h @@ -4,6 +4,7 @@ #include "esphome/core/component.h" #include "esphome/core/optional.h" +#include #include namespace esphome { diff --git a/esphome/components/climate_ir_lg/climate_ir_lg.cpp b/esphome/components/climate_ir_lg/climate_ir_lg.cpp index a41aad1bd0..d2199c1cbe 100644 --- a/esphome/components/climate_ir_lg/climate_ir_lg.cpp +++ b/esphome/components/climate_ir_lg/climate_ir_lg.cpp @@ -121,7 +121,7 @@ bool LgIrClimate::on_receive(remote_base::RemoteReceiveData data) { } } - ESP_LOGD(TAG, "Decoded 0x%02X", remote_state); + ESP_LOGD(TAG, "Decoded 0x%02" PRIX32, remote_state); if ((remote_state & 0xFF00000) != 0x8800000) return false; @@ -173,7 +173,7 @@ bool LgIrClimate::on_receive(remote_base::RemoteReceiveData data) { } void LgIrClimate::transmit_(uint32_t value) { calc_checksum_(value); - ESP_LOGD(TAG, "Sending climate_lg_ir code: 0x%02X", value); + ESP_LOGD(TAG, "Sending climate_lg_ir code: 0x%02" PRIX32, value); auto transmit = this->transmitter_->transmit(); auto *data = transmit.get_data(); diff --git a/esphome/components/climate_ir_lg/climate_ir_lg.h b/esphome/components/climate_ir_lg/climate_ir_lg.h index 6b38b3247b..34f50744ef 100644 --- a/esphome/components/climate_ir_lg/climate_ir_lg.h +++ b/esphome/components/climate_ir_lg/climate_ir_lg.h @@ -2,6 +2,8 @@ #include "esphome/components/climate_ir/climate_ir.h" +#include + namespace esphome { namespace climate_ir_lg { diff --git a/esphome/components/coolix/coolix.cpp b/esphome/components/coolix/coolix.cpp index 6233014a96..f4309419a4 100644 --- a/esphome/components/coolix/coolix.cpp +++ b/esphome/components/coolix/coolix.cpp @@ -101,7 +101,7 @@ void CoolixClimate::transmit_state() { } } } - ESP_LOGV(TAG, "Sending coolix code: 0x%06X", remote_state); + ESP_LOGV(TAG, "Sending coolix code: 0x%06" PRIX32, remote_state); auto transmit = this->transmitter_->transmit(); auto *data = transmit.get_data(); @@ -115,7 +115,7 @@ bool CoolixClimate::on_coolix(climate::Climate *parent, remote_base::RemoteRecei return false; // Decoded remote state y 3 bytes long code. uint32_t remote_state = (*decoded).second; - ESP_LOGV(TAG, "Decoded 0x%06X", remote_state); + ESP_LOGV(TAG, "Decoded 0x%06" PRIX32, remote_state); if ((remote_state & 0xFF0000) != 0xB20000) return false; diff --git a/esphome/components/coolix/coolix.h b/esphome/components/coolix/coolix.h index 3419795875..f4b4ff8e0e 100644 --- a/esphome/components/coolix/coolix.h +++ b/esphome/components/coolix/coolix.h @@ -2,6 +2,8 @@ #include "esphome/components/climate_ir/climate_ir.h" +#include + namespace esphome { namespace coolix { diff --git a/esphome/components/cs5460a/cs5460a.cpp b/esphome/components/cs5460a/cs5460a.cpp index fb8e50b87a..0d347ae0c1 100644 --- a/esphome/components/cs5460a/cs5460a.cpp +++ b/esphome/components/cs5460a/cs5460a.cpp @@ -86,7 +86,7 @@ void CS5460AComponent::hw_init_() { } uint32_t status = this->read_register_(REG_STATUS); - ESP_LOGCONFIG(TAG, " Version: %x", (status >> 6) & 7); + ESP_LOGCONFIG(TAG, " Version: %" PRIx32, (status >> 6) & 7); this->write_register_(REG_CYCLE_COUNT, samples_); this->write_register_(REG_PULSE_RATE, lroundf(pulse_freq_ * 32.0f)); @@ -323,7 +323,7 @@ void CS5460AComponent::dump_config() { ESP_LOGCONFIG(TAG, " Init status: %s", state == COMPONENT_STATE_LOOP ? "OK" : (state == COMPONENT_STATE_FAILED ? "failed" : "other")); LOG_PIN(" CS Pin: ", cs_); - ESP_LOGCONFIG(TAG, " Samples / cycle: %u", samples_); + ESP_LOGCONFIG(TAG, " Samples / cycle: %" PRIu32, samples_); ESP_LOGCONFIG(TAG, " Phase offset: %i", phase_offset_); ESP_LOGCONFIG(TAG, " PGA Gain: %s", pga_gain_ == CS5460A_PGA_GAIN_50X ? "50x" : "10x"); ESP_LOGCONFIG(TAG, " Current gain: %.5f", current_gain_); diff --git a/esphome/components/cs5460a/cs5460a.h b/esphome/components/cs5460a/cs5460a.h index 699049757c..763ddc14fa 100644 --- a/esphome/components/cs5460a/cs5460a.h +++ b/esphome/components/cs5460a/cs5460a.h @@ -5,6 +5,8 @@ #include "esphome/components/sensor/sensor.h" #include "esphome/components/spi/spi.h" +#include + namespace esphome { namespace cs5460a { diff --git a/esphome/components/deep_sleep/deep_sleep_component.cpp b/esphome/components/deep_sleep/deep_sleep_component.cpp index f6472a123c..328e972e6b 100644 --- a/esphome/components/deep_sleep/deep_sleep_component.cpp +++ b/esphome/components/deep_sleep/deep_sleep_component.cpp @@ -39,7 +39,7 @@ void DeepSleepComponent::setup() { const optional run_duration = get_run_duration_(); if (run_duration.has_value()) { - ESP_LOGI(TAG, "Scheduling Deep Sleep to start in %u ms", *run_duration); + ESP_LOGI(TAG, "Scheduling Deep Sleep to start in %" PRIu32 " ms", *run_duration); this->set_timeout(*run_duration, [this]() { this->begin_sleep(); }); } else { ESP_LOGD(TAG, "Not scheduling Deep Sleep, as no run duration is configured."); @@ -49,19 +49,20 @@ void DeepSleepComponent::dump_config() { ESP_LOGCONFIG(TAG, "Setting up Deep Sleep..."); if (this->sleep_duration_.has_value()) { uint32_t duration = *this->sleep_duration_ / 1000; - ESP_LOGCONFIG(TAG, " Sleep Duration: %u ms", duration); + ESP_LOGCONFIG(TAG, " Sleep Duration: %" PRIu32 " ms", duration); } if (this->run_duration_.has_value()) { - ESP_LOGCONFIG(TAG, " Run Duration: %u ms", *this->run_duration_); + ESP_LOGCONFIG(TAG, " Run Duration: %" PRIu32 " ms", *this->run_duration_); } #ifdef USE_ESP32 if (wakeup_pin_ != nullptr) { LOG_PIN(" Wakeup Pin: ", this->wakeup_pin_); } if (this->wakeup_cause_to_run_duration_.has_value()) { - ESP_LOGCONFIG(TAG, " Default Wakeup Run Duration: %u ms", this->wakeup_cause_to_run_duration_->default_cause); - ESP_LOGCONFIG(TAG, " Touch Wakeup Run Duration: %u ms", this->wakeup_cause_to_run_duration_->touch_cause); - ESP_LOGCONFIG(TAG, " GPIO Wakeup Run Duration: %u ms", this->wakeup_cause_to_run_duration_->gpio_cause); + ESP_LOGCONFIG(TAG, " Default Wakeup Run Duration: %" PRIu32 " ms", + this->wakeup_cause_to_run_duration_->default_cause); + ESP_LOGCONFIG(TAG, " Touch Wakeup Run Duration: %" PRIu32 " ms", this->wakeup_cause_to_run_duration_->touch_cause); + ESP_LOGCONFIG(TAG, " GPIO Wakeup Run Duration: %" PRIu32 " ms", this->wakeup_cause_to_run_duration_->gpio_cause); } #endif } diff --git a/esphome/components/deep_sleep/deep_sleep_component.h b/esphome/components/deep_sleep/deep_sleep_component.h index 2e54e53c56..e97d8300c4 100644 --- a/esphome/components/deep_sleep/deep_sleep_component.h +++ b/esphome/components/deep_sleep/deep_sleep_component.h @@ -14,6 +14,8 @@ #include "esphome/core/time.h" #endif +#include + namespace esphome { namespace deep_sleep { diff --git a/esphome/components/e131/e131.h b/esphome/components/e131/e131.h index 364a05af75..91b67f62eb 100644 --- a/esphome/components/e131/e131.h +++ b/esphome/components/e131/e131.h @@ -3,6 +3,7 @@ #include "esphome/components/socket/socket.h" #include "esphome/core/component.h" +#include #include #include #include diff --git a/esphome/components/e131/e131_addressable_light_effect.cpp b/esphome/components/e131/e131_addressable_light_effect.cpp index 6b6a726ef3..be3144f590 100644 --- a/esphome/components/e131/e131_addressable_light_effect.cpp +++ b/esphome/components/e131/e131_addressable_light_effect.cpp @@ -57,8 +57,8 @@ 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 %d-%d.", get_name().c_str(), universe, output_offset, - output_end); + ESP_LOGV(TAG, "Applying data for '%s' on %d universe, for %" PRId32 "-%d.", get_name().c_str(), universe, + output_offset, output_end); switch (channels_) { case E131_MONO: diff --git a/esphome/components/hlw8012/hlw8012.cpp b/esphome/components/hlw8012/hlw8012.cpp index ecdaa07ab2..1a9f47faaf 100644 --- a/esphome/components/hlw8012/hlw8012.cpp +++ b/esphome/components/hlw8012/hlw8012.cpp @@ -38,7 +38,7 @@ void HLW8012Component::dump_config() { LOG_PIN(" SEL Pin: ", this->sel_pin_) LOG_PIN(" CF Pin: ", this->cf_pin_) LOG_PIN(" CF1 Pin: ", this->cf1_pin_) - ESP_LOGCONFIG(TAG, " Change measurement mode every %u", this->change_mode_every_); + ESP_LOGCONFIG(TAG, " Change measurement mode every %" PRIu32, this->change_mode_every_); ESP_LOGCONFIG(TAG, " Current resistor: %.1f mΩ", this->current_resistor_ * 1000.0f); ESP_LOGCONFIG(TAG, " Voltage Divider: %.1f", this->voltage_divider_); LOG_UPDATE_INTERVAL(this) diff --git a/esphome/components/hlw8012/hlw8012.h b/esphome/components/hlw8012/hlw8012.h index adb49ffb66..312391f533 100644 --- a/esphome/components/hlw8012/hlw8012.h +++ b/esphome/components/hlw8012/hlw8012.h @@ -5,6 +5,8 @@ #include "esphome/components/sensor/sensor.h" #include "esphome/components/pulse_counter/pulse_counter_sensor.h" +#include + namespace esphome { namespace hlw8012 { diff --git a/esphome/components/hx711/hx711.cpp b/esphome/components/hx711/hx711.cpp index 62adc4ae86..dbbf4c91f4 100644 --- a/esphome/components/hx711/hx711.cpp +++ b/esphome/components/hx711/hx711.cpp @@ -28,7 +28,7 @@ void HX711Sensor::update() { uint32_t result; if (this->read_sensor_(&result)) { int32_t value = static_cast(result); - ESP_LOGD(TAG, "'%s': Got value %d", this->name_.c_str(), value); + ESP_LOGD(TAG, "'%s': Got value %" PRId32, this->name_.c_str(), value); this->publish_state(value); } } diff --git a/esphome/components/hx711/hx711.h b/esphome/components/hx711/hx711.h index 9fef649b03..0cb6868ab5 100644 --- a/esphome/components/hx711/hx711.h +++ b/esphome/components/hx711/hx711.h @@ -4,6 +4,8 @@ #include "esphome/core/hal.h" #include "esphome/components/sensor/sensor.h" +#include + namespace esphome { namespace hx711 { diff --git a/esphome/components/hyt271/hyt271.cpp b/esphome/components/hyt271/hyt271.cpp index 94558fff04..3b81294cfc 100644 --- a/esphome/components/hyt271/hyt271.cpp +++ b/esphome/components/hyt271/hyt271.cpp @@ -17,7 +17,7 @@ void HYT271Component::dump_config() { LOG_SENSOR(" ", "Humidity", this->humidity_); } void HYT271Component::update() { - uint8_t raw_data[4]; + uint8_t raw_data[4] = {0, 0, 0, 0}; if (this->write(&raw_data[0], 0) != i2c::ERROR_OK) { this->status_set_warning(); diff --git a/esphome/components/ili9xxx/ili9xxx_display.cpp b/esphome/components/ili9xxx/ili9xxx_display.cpp index fdbf3e3760..902a9e6245 100644 --- a/esphome/components/ili9xxx/ili9xxx_display.cpp +++ b/esphome/components/ili9xxx/ili9xxx_display.cpp @@ -180,7 +180,7 @@ void ILI9XXXDisplay::display_() { ESP_LOGV(TAG, "Start display(xlow:%d, ylow:%d, xhigh:%d, yhigh:%d, width:%d, " - "heigth:%d, start_pos:%d)", + "heigth:%d, start_pos:%" PRId32 ")", this->x_low_, this->y_low_, this->x_high_, this->y_high_, w, h, start_pos); this->start_data_(); diff --git a/esphome/components/ili9xxx/ili9xxx_init.h b/esphome/components/ili9xxx/ili9xxx_init.h index 031dc25f91..e3be9389b7 100644 --- a/esphome/components/ili9xxx/ili9xxx_init.h +++ b/esphome/components/ili9xxx/ili9xxx_init.h @@ -1,6 +1,8 @@ #pragma once #include "esphome/core/helpers.h" +#include + namespace esphome { namespace ili9xxx { diff --git a/esphome/components/ina219/ina219.cpp b/esphome/components/ina219/ina219.cpp index 609f3d0f08..2fb3bea356 100644 --- a/esphome/components/ina219/ina219.cpp +++ b/esphome/components/ina219/ina219.cpp @@ -122,7 +122,7 @@ void INA219Component::setup() { this->calibration_lsb_ = lsb; auto calibration = uint32_t(0.04096f / (0.000001 * lsb * this->shunt_resistance_ohm_)); - ESP_LOGV(TAG, " Using LSB=%u calibration=%u", lsb, calibration); + ESP_LOGV(TAG, " Using LSB=%" PRIu32 " calibration=%" PRIu32, lsb, calibration); if (!this->write_byte_16(INA219_REGISTER_CALIBRATION, calibration)) { this->mark_failed(); return; diff --git a/esphome/components/ina219/ina219.h b/esphome/components/ina219/ina219.h index 31cd22375e..a6c0f2bc4c 100644 --- a/esphome/components/ina219/ina219.h +++ b/esphome/components/ina219/ina219.h @@ -4,6 +4,8 @@ #include "esphome/components/sensor/sensor.h" #include "esphome/components/i2c/i2c.h" +#include + namespace esphome { namespace ina219 { diff --git a/esphome/components/max31855/max31855.cpp b/esphome/components/max31855/max31855.cpp index 2578c4742d..445e086ef6 100644 --- a/esphome/components/max31855/max31855.cpp +++ b/esphome/components/max31855/max31855.cpp @@ -47,7 +47,7 @@ void MAX31855Sensor::read_data_() { if (mem != 0xFFFFFFFF) { this->status_clear_error(); } else { - ESP_LOGE(TAG, "No data received from MAX31855 (0x%08X). Check wiring!", mem); + ESP_LOGE(TAG, "No data received from MAX31855 (0x%08" PRIX32 "). Check wiring!", mem); this->publish_state(NAN); if (this->temperature_reference_) { this->temperature_reference_->publish_state(NAN); @@ -69,25 +69,25 @@ void MAX31855Sensor::read_data_() { // Check thermocouple faults if (mem & 0x00000001) { - ESP_LOGW(TAG, "Thermocouple open circuit (not connected) fault from MAX31855 (0x%08X)", mem); + ESP_LOGW(TAG, "Thermocouple open circuit (not connected) fault from MAX31855 (0x%08" PRIX32 ")", mem); this->publish_state(NAN); this->status_set_warning(); return; } if (mem & 0x00000002) { - ESP_LOGW(TAG, "Thermocouple short circuit to ground fault from MAX31855 (0x%08X)", mem); + ESP_LOGW(TAG, "Thermocouple short circuit to ground fault from MAX31855 (0x%08" PRIX32 ")", mem); this->publish_state(NAN); this->status_set_warning(); return; } if (mem & 0x00000004) { - ESP_LOGW(TAG, "Thermocouple short circuit to VCC fault from MAX31855 (0x%08X)", mem); + ESP_LOGW(TAG, "Thermocouple short circuit to VCC fault from MAX31855 (0x%08" PRIX32 ")", mem); this->publish_state(NAN); this->status_set_warning(); return; } if (mem & 0x00010000) { - ESP_LOGW(TAG, "Got faulty reading from MAX31855 (0x%08X)", mem); + ESP_LOGW(TAG, "Got faulty reading from MAX31855 (0x%08" PRIX32 ")", mem); this->publish_state(NAN); this->status_set_warning(); return; diff --git a/esphome/components/max31855/max31855.h b/esphome/components/max31855/max31855.h index c0ed8a467d..822e256587 100644 --- a/esphome/components/max31855/max31855.h +++ b/esphome/components/max31855/max31855.h @@ -4,6 +4,8 @@ #include "esphome/components/sensor/sensor.h" #include "esphome/components/spi/spi.h" +#include + namespace esphome { namespace max31855 { diff --git a/esphome/components/max31856/max31856.cpp b/esphome/components/max31856/max31856.cpp index 9300916fdc..8ae4be6657 100644 --- a/esphome/components/max31856/max31856.cpp +++ b/esphome/components/max31856/max31856.cpp @@ -188,7 +188,7 @@ uint32_t MAX31856Sensor::read_register24_(uint8_t reg) { ESP_LOGVV(TAG, "read_byte lsb=0x%02X", lsb); this->disable(); const uint32_t value((msb << 16) | (mid << 8) | lsb); - ESP_LOGV(TAG, "read_register_24_ reg=0x%02X: value=0x%06X", reg, value); + ESP_LOGV(TAG, "read_register_24_ reg=0x%02X: value=0x%06" PRIX32, reg, value); return value; } diff --git a/esphome/components/max31856/max31856.h b/esphome/components/max31856/max31856.h index 157aad433c..4deb6bc855 100644 --- a/esphome/components/max31856/max31856.h +++ b/esphome/components/max31856/max31856.h @@ -4,6 +4,8 @@ #include "esphome/components/spi/spi.h" #include "esphome/core/component.h" +#include + namespace esphome { namespace max31856 { diff --git a/esphome/components/mitsubishi/mitsubishi.cpp b/esphome/components/mitsubishi/mitsubishi.cpp index 99ca6d1cc5..87b78128e4 100644 --- a/esphome/components/mitsubishi/mitsubishi.cpp +++ b/esphome/components/mitsubishi/mitsubishi.cpp @@ -45,8 +45,8 @@ void MitsubishiClimate::transmit_state() { remote_state[7] = (uint8_t) roundf(clamp(this->target_temperature, MITSUBISHI_TEMP_MIN, MITSUBISHI_TEMP_MAX) - MITSUBISHI_TEMP_MIN); - ESP_LOGV(TAG, "Sending Mitsubishi target temp: %.1f state: %02X mode: %02X temp: %02X", this->target_temperature, - remote_state[5], remote_state[6], remote_state[7]); + ESP_LOGV(TAG, "Sending Mitsubishi target temp: %.1f state: %02" PRIX32 " mode: %02" PRIX32 " temp: %02" PRIX32, + this->target_temperature, remote_state[5], remote_state[6], remote_state[7]); // Checksum for (int i = 0; i < 17; i++) { diff --git a/esphome/components/mitsubishi/mitsubishi.h b/esphome/components/mitsubishi/mitsubishi.h index e6bd7b8ebe..9a88040d3f 100644 --- a/esphome/components/mitsubishi/mitsubishi.h +++ b/esphome/components/mitsubishi/mitsubishi.h @@ -2,6 +2,8 @@ #include "esphome/components/climate_ir/climate_ir.h" +#include + namespace esphome { namespace mitsubishi { diff --git a/esphome/components/ota/__init__.py b/esphome/components/ota/__init__.py index eb2a83272d..039596d897 100644 --- a/esphome/components/ota/__init__.py +++ b/esphome/components/ota/__init__.py @@ -128,7 +128,7 @@ async def to_code(config): use_state_callback = True for conf in config.get(CONF_ON_ERROR, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [(int, "x")], conf) + await automation.build_automation(trigger, [(cg.uint8, "x")], conf) use_state_callback = True if use_state_callback: cg.add_define("USE_OTA_STATE_CALLBACK") diff --git a/esphome/components/ota/automation.h b/esphome/components/ota/automation.h index 6c8aca3705..0c77a18ce1 100644 --- a/esphome/components/ota/automation.h +++ b/esphome/components/ota/automation.h @@ -54,7 +54,7 @@ class OTAEndTrigger : public Trigger<> { } }; -class OTAErrorTrigger : public Trigger { +class OTAErrorTrigger : public Trigger { public: explicit OTAErrorTrigger(OTAComponent *parent) { parent->add_on_state_callback([this, parent](OTAState state, float progress, uint8_t error) { diff --git a/esphome/components/power_supply/power_supply.cpp b/esphome/components/power_supply/power_supply.cpp index a492919202..c4d157615a 100644 --- a/esphome/components/power_supply/power_supply.cpp +++ b/esphome/components/power_supply/power_supply.cpp @@ -16,7 +16,7 @@ void PowerSupply::setup() { void PowerSupply::dump_config() { ESP_LOGCONFIG(TAG, "Power Supply:"); LOG_PIN(" Pin: ", this->pin_); - ESP_LOGCONFIG(TAG, " Time to enable: %u ms", this->enable_time_); + ESP_LOGCONFIG(TAG, " Time to enable: %" PRIu32 " ms", this->enable_time_); ESP_LOGCONFIG(TAG, " Keep on time: %.1f s", this->keep_on_time_ / 1000.0f); } diff --git a/esphome/components/power_supply/power_supply.h b/esphome/components/power_supply/power_supply.h index 66e4a7565a..49d905ba3a 100644 --- a/esphome/components/power_supply/power_supply.h +++ b/esphome/components/power_supply/power_supply.h @@ -3,6 +3,8 @@ #include "esphome/core/component.h" #include "esphome/core/hal.h" +#include + namespace esphome { namespace power_supply { diff --git a/esphome/components/pulse_counter/pulse_counter_sensor.cpp b/esphome/components/pulse_counter/pulse_counter_sensor.cpp index 1f50360fed..281a61a66a 100644 --- a/esphome/components/pulse_counter/pulse_counter_sensor.cpp +++ b/esphome/components/pulse_counter/pulse_counter_sensor.cpp @@ -104,7 +104,7 @@ bool HwPulseCounterStorage::pulse_counter_setup(InternalGPIOPin *pin) { if (this->filter_us != 0) { uint16_t filter_val = std::min(static_cast(this->filter_us * 80u), 1023u); - ESP_LOGCONFIG(TAG, " Filter Value: %uus (val=%u)", this->filter_us, filter_val); + ESP_LOGCONFIG(TAG, " Filter Value: %" PRIu32 "us (val=%u)", this->filter_us, filter_val); error = pcnt_set_filter_value(this->pcnt_unit, filter_val); if (error != ESP_OK) { ESP_LOGE(TAG, "Setting filter value failed: %s", esp_err_to_name(error)); @@ -161,7 +161,7 @@ void PulseCounterSensor::dump_config() { LOG_PIN(" Pin: ", this->pin_); ESP_LOGCONFIG(TAG, " Rising Edge: %s", EDGE_MODE_TO_STRING[this->storage_.rising_edge_mode]); ESP_LOGCONFIG(TAG, " Falling Edge: %s", EDGE_MODE_TO_STRING[this->storage_.falling_edge_mode]); - ESP_LOGCONFIG(TAG, " Filtering pulses shorter than %u µs", this->storage_.filter_us); + ESP_LOGCONFIG(TAG, " Filtering pulses shorter than %" PRIu32 " µs", this->storage_.filter_us); LOG_UPDATE_INTERVAL(this); } @@ -177,7 +177,7 @@ void PulseCounterSensor::update() { if (this->total_sensor_ != nullptr) { current_total_ += raw; - ESP_LOGD(TAG, "'%s': Total : %i pulses", this->get_name().c_str(), current_total_); + ESP_LOGD(TAG, "'%s': Total : %" PRIu32 " pulses", this->get_name().c_str(), current_total_); this->total_sensor_->publish_state(current_total_); } this->last_time_ = now; diff --git a/esphome/components/pulse_counter/pulse_counter_sensor.h b/esphome/components/pulse_counter/pulse_counter_sensor.h index ef944f106f..ef9f73f95c 100644 --- a/esphome/components/pulse_counter/pulse_counter_sensor.h +++ b/esphome/components/pulse_counter/pulse_counter_sensor.h @@ -4,6 +4,8 @@ #include "esphome/core/hal.h" #include "esphome/components/sensor/sensor.h" +#include + #if defined(USE_ESP32) && !defined(USE_ESP32_VARIANT_ESP32C3) #include #define HAS_PCNT diff --git a/esphome/components/pulse_meter/pulse_meter_sensor.cpp b/esphome/components/pulse_meter/pulse_meter_sensor.cpp index be5fad6fe5..6c4ebe002e 100644 --- a/esphome/components/pulse_meter/pulse_meter_sensor.cpp +++ b/esphome/components/pulse_meter/pulse_meter_sensor.cpp @@ -61,12 +61,13 @@ void PulseMeterSensor::loop() { const uint32_t time_since_valid_edge_us = now - this->last_processed_edge_us_; switch (this->meter_state_) { - // Running and initial states can timeout + // Running and initial states can timeout case MeterState::INITIAL: case MeterState::RUNNING: { if (time_since_valid_edge_us > this->timeout_us_) { this->meter_state_ = MeterState::TIMED_OUT; - ESP_LOGD(TAG, "No pulse detected for %us, assuming 0 pulses/min", time_since_valid_edge_us / 1000000); + ESP_LOGD(TAG, "No pulse detected for %" PRIu32 "s, assuming 0 pulses/min", + time_since_valid_edge_us / 1000000); this->publish_state(0.0f); } } break; @@ -82,11 +83,12 @@ void PulseMeterSensor::dump_config() { LOG_SENSOR("", "Pulse Meter", this); LOG_PIN(" Pin: ", this->pin_); if (this->filter_mode_ == FILTER_EDGE) { - ESP_LOGCONFIG(TAG, " Filtering rising edges less than %u µs apart", this->filter_us_); + ESP_LOGCONFIG(TAG, " Filtering rising edges less than %" PRIu32 " µs apart", this->filter_us_); } else { - ESP_LOGCONFIG(TAG, " Filtering pulses shorter than %u µs", this->filter_us_); + ESP_LOGCONFIG(TAG, " Filtering pulses shorter than %" PRIu32 " µs", this->filter_us_); } - ESP_LOGCONFIG(TAG, " Assuming 0 pulses/min after not receiving a pulse for %us", this->timeout_us_ / 1000000); + ESP_LOGCONFIG(TAG, " Assuming 0 pulses/min after not receiving a pulse for %" PRIu32 "s", + this->timeout_us_ / 1000000); } void IRAM_ATTR PulseMeterSensor::edge_intr(PulseMeterSensor *sensor) { diff --git a/esphome/components/pulse_meter/pulse_meter_sensor.h b/esphome/components/pulse_meter/pulse_meter_sensor.h index f376ea48a5..fc8d47538f 100644 --- a/esphome/components/pulse_meter/pulse_meter_sensor.h +++ b/esphome/components/pulse_meter/pulse_meter_sensor.h @@ -5,6 +5,8 @@ #include "esphome/core/hal.h" #include "esphome/core/helpers.h" +#include + namespace esphome { namespace pulse_meter { diff --git a/esphome/components/pvvx_mithermometer/display/pvvx_display.cpp b/esphome/components/pvvx_mithermometer/display/pvvx_display.cpp index 384537e5d7..fc200f7d71 100644 --- a/esphome/components/pvvx_mithermometer/display/pvvx_display.cpp +++ b/esphome/components/pvvx_mithermometer/display/pvvx_display.cpp @@ -14,7 +14,7 @@ void PVVXDisplay::dump_config() { ESP_LOGCONFIG(TAG, " Characteristic UUID : %s", this->char_uuid_.to_string().c_str()); ESP_LOGCONFIG(TAG, " Auto clear : %s", YESNO(this->auto_clear_enabled_)); ESP_LOGCONFIG(TAG, " Set time on connection: %s", YESNO(this->time_ != nullptr)); - ESP_LOGCONFIG(TAG, " Disconnect delay : %dms", this->disconnect_delay_ms_); + ESP_LOGCONFIG(TAG, " Disconnect delay : %" PRIu32 "ms", this->disconnect_delay_ms_); LOG_UPDATE_INTERVAL(this); } @@ -139,7 +139,11 @@ void PVVXDisplay::sync_time_() { } time.recalc_timestamp_utc(true); // calculate timestamp of local time uint8_t blk[5] = {}; +#if ESP_IDF_VERSION_MAJOR >= 5 + ESP_LOGD(TAG, "[%s] Sync time with timestamp %" PRIu64 ".", this->parent_->address_str().c_str(), time.timestamp); +#else ESP_LOGD(TAG, "[%s] Sync time with timestamp %lu.", this->parent_->address_str().c_str(), time.timestamp); +#endif blk[0] = 0x23; blk[1] = time.timestamp & 0xff; blk[2] = (time.timestamp >> 8) & 0xff; diff --git a/esphome/components/pvvx_mithermometer/display/pvvx_display.h b/esphome/components/pvvx_mithermometer/display/pvvx_display.h index c7e7cc04fb..dfeb49c49d 100644 --- a/esphome/components/pvvx_mithermometer/display/pvvx_display.h +++ b/esphome/components/pvvx_mithermometer/display/pvvx_display.h @@ -4,6 +4,8 @@ #include "esphome/core/defines.h" #include "esphome/components/ble_client/ble_client.h" +#include + #ifdef USE_ESP32 #include #ifdef USE_TIME diff --git a/esphome/components/rdm6300/rdm6300.cpp b/esphome/components/rdm6300/rdm6300.cpp index 434b9f5720..bfdd880079 100644 --- a/esphome/components/rdm6300/rdm6300.cpp +++ b/esphome/components/rdm6300/rdm6300.cpp @@ -57,7 +57,7 @@ void rdm6300::RDM6300Component::loop() { trig->process(result); if (report) { - ESP_LOGD(TAG, "Found new tag with ID %u", result); + ESP_LOGD(TAG, "Found new tag with ID %" PRIu32, result); } } } diff --git a/esphome/components/rdm6300/rdm6300.h b/esphome/components/rdm6300/rdm6300.h index 0aeabef2bc..1a1a0c0cd6 100644 --- a/esphome/components/rdm6300/rdm6300.h +++ b/esphome/components/rdm6300/rdm6300.h @@ -5,6 +5,7 @@ #include "esphome/components/binary_sensor/binary_sensor.h" #include "esphome/components/uart/uart.h" +#include #include namespace esphome { diff --git a/esphome/components/remote_base/__init__.py b/esphome/components/remote_base/__init__.py index 5a703066a1..cf2ae89b6a 100644 --- a/esphome/components/remote_base/__init__.py +++ b/esphome/components/remote_base/__init__.py @@ -372,19 +372,14 @@ def coolix_binary_sensor(var, config): if isinstance(config, dict): cg.add( var.set_data( - cg.StructInitializer( - CoolixData, - ("first", config[CONF_FIRST]), - ("second", config[CONF_SECOND]), + cg.ArrayInitializer( + config[CONF_FIRST], + config[CONF_SECOND], ) ) ) else: - cg.add( - var.set_data( - cg.StructInitializer(CoolixData, ("first", 0), ("second", config)) - ) - ) + cg.add(var.set_data(cg.ArrayInitializer(0, config))) @register_action("coolix", CoolixAction, COOLIX_BASE_SCHEMA) diff --git a/esphome/components/remote_base/coolix_protocol.cpp b/esphome/components/remote_base/coolix_protocol.cpp index 295fccb762..21a9f598b7 100644 --- a/esphome/components/remote_base/coolix_protocol.cpp +++ b/esphome/components/remote_base/coolix_protocol.cpp @@ -101,11 +101,11 @@ optional CoolixProtocol::decode(RemoteReceiveData data) { void CoolixProtocol::dump(const CoolixData &data) { if (data.is_strict()) { - ESP_LOGI(TAG, "Received Coolix: 0x%06X", data.first); + ESP_LOGI(TAG, "Received Coolix: 0x%06" PRIX32, data.first); } else if (data.has_second()) { - ESP_LOGI(TAG, "Received unstrict Coolix: [0x%06X, 0x%06X]", data.first, data.second); + ESP_LOGI(TAG, "Received unstrict Coolix: [0x%06" PRIX32 ", 0x%06" PRIX32 "]", data.first, data.second); } else { - ESP_LOGI(TAG, "Received unstrict Coolix: [0x%06X]", data.first); + ESP_LOGI(TAG, "Received unstrict Coolix: [0x%06" PRIX32 "]", data.first); } } diff --git a/esphome/components/remote_base/coolix_protocol.h b/esphome/components/remote_base/coolix_protocol.h index 50ac839200..b66415ff70 100644 --- a/esphome/components/remote_base/coolix_protocol.h +++ b/esphome/components/remote_base/coolix_protocol.h @@ -4,6 +4,8 @@ #include "esphome/core/helpers.h" #include "remote_base.h" +#include + namespace esphome { namespace remote_base { diff --git a/esphome/components/remote_base/drayton_protocol.cpp b/esphome/components/remote_base/drayton_protocol.cpp index 56a3dec1e0..12a553455f 100644 --- a/esphome/components/remote_base/drayton_protocol.cpp +++ b/esphome/components/remote_base/drayton_protocol.cpp @@ -114,7 +114,7 @@ void DraytonProtocol::encode(RemoteTransmitData *dst, const DraytonData &data) { out_data <<= NBITS_CHANNEL; out_data |= data.channel; - ESP_LOGV(TAG, "Send Drayton: out_data %08x", out_data); + ESP_LOGV(TAG, "Send Drayton: out_data %08" PRIx32, out_data); for (uint32_t mask = 1UL << (NBITS - 1); mask != 0; mask >>= 1) { if (out_data & mask) { @@ -169,7 +169,7 @@ optional DraytonProtocol::decode(RemoteReceiveData src) { (src.expect_space(BIT_TIME_US) || src.peek_space(2 * BIT_TIME_US))) { out_data |= 1 << bit; } else { - ESP_LOGV(TAG, "Decode Drayton: Fail 1, - %d", src.get_index()); + ESP_LOGV(TAG, "Decode Drayton: Fail 1, - %" PRIu32, src.get_index()); return {}; } @@ -194,7 +194,7 @@ optional DraytonProtocol::decode(RemoteReceiveData src) { } else if (src.expect_mark(BIT_TIME_US) || src.expect_mark(2 * BIT_TIME_US)) { out_data |= 1; } - ESP_LOGV(TAG, "Decode Drayton: Data, %2d %08x", bit, out_data); + ESP_LOGV(TAG, "Decode Drayton: Data, %2d %08" PRIx32, bit, out_data); out.channel = (uint8_t) (out_data & 0x1F); out_data >>= NBITS_CHANNEL; diff --git a/esphome/components/remote_base/drayton_protocol.h b/esphome/components/remote_base/drayton_protocol.h index f468e7b57e..75213b9186 100644 --- a/esphome/components/remote_base/drayton_protocol.h +++ b/esphome/components/remote_base/drayton_protocol.h @@ -3,6 +3,8 @@ #include "esphome/core/component.h" #include "remote_base.h" +#include + namespace esphome { namespace remote_base { diff --git a/esphome/components/remote_base/jvc_protocol.cpp b/esphome/components/remote_base/jvc_protocol.cpp index 3d34cc614e..ca423b61e6 100644 --- a/esphome/components/remote_base/jvc_protocol.cpp +++ b/esphome/components/remote_base/jvc_protocol.cpp @@ -46,7 +46,7 @@ optional JVCProtocol::decode(RemoteReceiveData src) { } return out; } -void JVCProtocol::dump(const JVCData &data) { ESP_LOGI(TAG, "Received JVC: data=0x%04X", data.data); } +void JVCProtocol::dump(const JVCData &data) { ESP_LOGI(TAG, "Received JVC: data=0x%04" PRIX32, data.data); } } // namespace remote_base } // namespace esphome diff --git a/esphome/components/remote_base/jvc_protocol.h b/esphome/components/remote_base/jvc_protocol.h index fc40a6a874..a17e593ad2 100644 --- a/esphome/components/remote_base/jvc_protocol.h +++ b/esphome/components/remote_base/jvc_protocol.h @@ -2,6 +2,8 @@ #include "remote_base.h" +#include + namespace esphome { namespace remote_base { diff --git a/esphome/components/remote_base/lg_protocol.cpp b/esphome/components/remote_base/lg_protocol.cpp index d7d3a5ac7d..d25c59d2b1 100644 --- a/esphome/components/remote_base/lg_protocol.cpp +++ b/esphome/components/remote_base/lg_protocol.cpp @@ -51,7 +51,7 @@ optional LGProtocol::decode(RemoteReceiveData src) { return out; } void LGProtocol::dump(const LGData &data) { - ESP_LOGI(TAG, "Received LG: data=0x%08X, nbits=%d", data.data, data.nbits); + ESP_LOGI(TAG, "Received LG: data=0x%08" PRIX32 ", nbits=%d", data.data, data.nbits); } } // namespace remote_base diff --git a/esphome/components/remote_base/lg_protocol.h b/esphome/components/remote_base/lg_protocol.h index 6267560443..e0039d033d 100644 --- a/esphome/components/remote_base/lg_protocol.h +++ b/esphome/components/remote_base/lg_protocol.h @@ -3,6 +3,8 @@ #include "esphome/core/component.h" #include "remote_base.h" +#include + namespace esphome { namespace remote_base { diff --git a/esphome/components/remote_base/magiquest_protocol.cpp b/esphome/components/remote_base/magiquest_protocol.cpp index 76024b1eaf..1cec58a55f 100644 --- a/esphome/components/remote_base/magiquest_protocol.cpp +++ b/esphome/components/remote_base/magiquest_protocol.cpp @@ -76,7 +76,7 @@ optional MagiQuestProtocol::decode(RemoteReceiveData src) { return data; } void MagiQuestProtocol::dump(const MagiQuestData &data) { - ESP_LOGI(TAG, "Received MagiQuest: wand_id=0x%08X, magnitude=0x%04X", data.wand_id, data.magnitude); + ESP_LOGI(TAG, "Received MagiQuest: wand_id=0x%08" PRIX32 ", magnitude=0x%04X", data.wand_id, data.magnitude); } } // namespace remote_base diff --git a/esphome/components/remote_base/magiquest_protocol.h b/esphome/components/remote_base/magiquest_protocol.h index 909be346d0..a531a9aee1 100644 --- a/esphome/components/remote_base/magiquest_protocol.h +++ b/esphome/components/remote_base/magiquest_protocol.h @@ -2,6 +2,8 @@ #include "remote_base.h" +#include + /* Based on protocol analysis from * https://arduino-irremote.github.io/Arduino-IRremote/ir__MagiQuest_8cpp_source.html */ diff --git a/esphome/components/remote_base/nexa_protocol.cpp b/esphome/components/remote_base/nexa_protocol.cpp index f4e7d14187..862165714e 100644 --- a/esphome/components/remote_base/nexa_protocol.cpp +++ b/esphome/components/remote_base/nexa_protocol.cpp @@ -232,7 +232,7 @@ optional NexaProtocol::decode(RemoteReceiveData src) { } void NexaProtocol::dump(const NexaData &data) { - ESP_LOGI(TAG, "Received NEXA: device=0x%04X group=%d state=%d channel=%d level=%d", data.device, data.group, + ESP_LOGI(TAG, "Received NEXA: device=0x%04" PRIX32 " group=%d state=%d channel=%d level=%d", data.device, data.group, data.state, data.channel, data.level); } diff --git a/esphome/components/remote_base/nexa_protocol.h b/esphome/components/remote_base/nexa_protocol.h index f1ce380780..4d9443ce0e 100644 --- a/esphome/components/remote_base/nexa_protocol.h +++ b/esphome/components/remote_base/nexa_protocol.h @@ -2,6 +2,8 @@ #include "remote_base.h" +#include + namespace esphome { namespace remote_base { diff --git a/esphome/components/remote_base/panasonic_protocol.cpp b/esphome/components/remote_base/panasonic_protocol.cpp index 460ca3b164..d6cf1a160d 100644 --- a/esphome/components/remote_base/panasonic_protocol.cpp +++ b/esphome/components/remote_base/panasonic_protocol.cpp @@ -67,7 +67,7 @@ optional PanasonicProtocol::decode(RemoteReceiveData src) { return out; } void PanasonicProtocol::dump(const PanasonicData &data) { - ESP_LOGI(TAG, "Received Panasonic: address=0x%04X, command=0x%08X", data.address, data.command); + ESP_LOGI(TAG, "Received Panasonic: address=0x%04X, command=0x%08" PRIX32, data.address, data.command); } } // namespace remote_base diff --git a/esphome/components/remote_base/panasonic_protocol.h b/esphome/components/remote_base/panasonic_protocol.h index eae97a8a14..c81366138a 100644 --- a/esphome/components/remote_base/panasonic_protocol.h +++ b/esphome/components/remote_base/panasonic_protocol.h @@ -3,6 +3,8 @@ #include "esphome/core/component.h" #include "remote_base.h" +#include + namespace esphome { namespace remote_base { diff --git a/esphome/components/remote_base/raw_protocol.cpp b/esphome/components/remote_base/raw_protocol.cpp index 9304aa3e3d..bdeb935dc4 100644 --- a/esphome/components/remote_base/raw_protocol.cpp +++ b/esphome/components/remote_base/raw_protocol.cpp @@ -17,9 +17,9 @@ bool RawDumper::dump(RemoteReceiveData src) { int written; if (i + 1 < src.size() - 1) { - written = snprintf(buffer + buffer_offset, remaining_length, "%d, ", value); + written = snprintf(buffer + buffer_offset, remaining_length, "%" PRId32 ", ", value); } else { - written = snprintf(buffer + buffer_offset, remaining_length, "%d", value); + written = snprintf(buffer + buffer_offset, remaining_length, "%" PRId32, value); } if (written < 0 || written >= int(remaining_length)) { @@ -29,9 +29,9 @@ bool RawDumper::dump(RemoteReceiveData src) { buffer_offset = 0; written = sprintf(buffer, " "); if (i + 1 < src.size()) { - written += sprintf(buffer + written, "%d, ", value); + written += sprintf(buffer + written, "%" PRId32 ", ", value); } else { - written += sprintf(buffer + written, "%d", value); + written += sprintf(buffer + written, "%" PRId32, value); } } diff --git a/esphome/components/remote_base/raw_protocol.h b/esphome/components/remote_base/raw_protocol.h index 494903daa8..9b671e611f 100644 --- a/esphome/components/remote_base/raw_protocol.h +++ b/esphome/components/remote_base/raw_protocol.h @@ -3,6 +3,7 @@ #include "esphome/core/component.h" #include "remote_base.h" +#include #include namespace esphome { diff --git a/esphome/components/remote_base/samsung36_protocol.cpp b/esphome/components/remote_base/samsung36_protocol.cpp index 2396986670..bd3eee5849 100644 --- a/esphome/components/remote_base/samsung36_protocol.cpp +++ b/esphome/components/remote_base/samsung36_protocol.cpp @@ -96,7 +96,7 @@ optional Samsung36Protocol::decode(RemoteReceiveData src) { return out; } void Samsung36Protocol::dump(const Samsung36Data &data) { - ESP_LOGI(TAG, "Received Samsung36: address=0x%04X, command=0x%08X", data.address, data.command); + ESP_LOGI(TAG, "Received Samsung36: address=0x%04X, command=0x%08" PRIX32, data.address, data.command); } } // namespace remote_base diff --git a/esphome/components/remote_base/samsung36_protocol.h b/esphome/components/remote_base/samsung36_protocol.h index 4ba6226edd..aa7fd21609 100644 --- a/esphome/components/remote_base/samsung36_protocol.h +++ b/esphome/components/remote_base/samsung36_protocol.h @@ -3,6 +3,8 @@ #include "esphome/core/component.h" #include "remote_base.h" +#include + namespace esphome { namespace remote_base { diff --git a/esphome/components/remote_base/sony_protocol.cpp b/esphome/components/remote_base/sony_protocol.cpp index bcd8e4c8cf..69f2b49c42 100644 --- a/esphome/components/remote_base/sony_protocol.cpp +++ b/esphome/components/remote_base/sony_protocol.cpp @@ -62,7 +62,7 @@ optional SonyProtocol::decode(RemoteReceiveData src) { return out; } void SonyProtocol::dump(const SonyData &data) { - ESP_LOGI(TAG, "Received Sony: data=0x%08X, nbits=%d", data.data, data.nbits); + ESP_LOGI(TAG, "Received Sony: data=0x%08" PRIX32 ", nbits=%d", data.data, data.nbits); } } // namespace remote_base diff --git a/esphome/components/remote_base/sony_protocol.h b/esphome/components/remote_base/sony_protocol.h index aecc8ab91c..d9e4f37d53 100644 --- a/esphome/components/remote_base/sony_protocol.h +++ b/esphome/components/remote_base/sony_protocol.h @@ -3,6 +3,8 @@ #include "esphome/core/component.h" #include "remote_base.h" +#include + namespace esphome { namespace remote_base { diff --git a/esphome/components/remote_receiver/remote_receiver.h b/esphome/components/remote_receiver/remote_receiver.h index 82c66e3cd0..c1343a8603 100644 --- a/esphome/components/remote_receiver/remote_receiver.h +++ b/esphome/components/remote_receiver/remote_receiver.h @@ -3,6 +3,8 @@ #include "esphome/core/component.h" #include "esphome/components/remote_base/remote_base.h" +#include + namespace esphome { namespace remote_receiver { diff --git a/esphome/components/remote_receiver/remote_receiver_esp32.cpp b/esphome/components/remote_receiver/remote_receiver_esp32.cpp index 5a7fb3c985..1ebb5a5955 100644 --- a/esphome/components/remote_receiver/remote_receiver_esp32.cpp +++ b/esphome/components/remote_receiver/remote_receiver_esp32.cpp @@ -62,7 +62,7 @@ void RemoteReceiverComponent::dump_config() { ESP_LOGCONFIG(TAG, " Clock divider: %u", this->clock_divider_); ESP_LOGCONFIG(TAG, " Tolerance: %u%%", this->tolerance_); ESP_LOGCONFIG(TAG, " Filter out pulses shorter than: %u us", this->filter_us_); - ESP_LOGCONFIG(TAG, " Signal is done after %u us of no changes", this->idle_us_); + ESP_LOGCONFIG(TAG, " Signal is done after %" PRIu32 " us of no changes", this->idle_us_); if (this->is_failed()) { ESP_LOGE(TAG, "Configuring RMT driver failed: %s", esp_err_to_name(this->error_code_)); } diff --git a/esphome/components/sgp30/sgp30.cpp b/esphome/components/sgp30/sgp30.cpp index 25a3c1ab8f..0910a32a35 100644 --- a/esphome/components/sgp30/sgp30.cpp +++ b/esphome/components/sgp30/sgp30.cpp @@ -255,7 +255,7 @@ void SGP30Component::dump_config() { } else { ESP_LOGCONFIG(TAG, " Baseline: No baseline configured"); } - ESP_LOGCONFIG(TAG, " Warm up time: %us", this->required_warm_up_time_); + ESP_LOGCONFIG(TAG, " Warm up time: %" PRIu32 "s", this->required_warm_up_time_); } LOG_UPDATE_INTERVAL(this); LOG_SENSOR(" ", "eCO2 sensor", this->eco2_sensor_); diff --git a/esphome/components/sgp30/sgp30.h b/esphome/components/sgp30/sgp30.h index d61eee00db..9e882e6b05 100644 --- a/esphome/components/sgp30/sgp30.h +++ b/esphome/components/sgp30/sgp30.h @@ -4,6 +4,8 @@ #include "esphome/components/sensor/sensor.h" #include "esphome/components/sensirion_common/i2c_sensirion.h" #include "esphome/core/preferences.h" + +#include #include namespace esphome { diff --git a/esphome/components/sht3xd/sht3xd.cpp b/esphome/components/sht3xd/sht3xd.cpp index f4bd2da271..25332165c0 100644 --- a/esphome/components/sht3xd/sht3xd.cpp +++ b/esphome/components/sht3xd/sht3xd.cpp @@ -27,7 +27,7 @@ void SHT3XDComponent::setup() { return; } uint32_t serial_number = (uint32_t(raw_serial_number[0]) << 16) | uint32_t(raw_serial_number[1]); - ESP_LOGV(TAG, " Serial Number: 0x%08X", serial_number); + ESP_LOGV(TAG, " Serial Number: 0x%08" PRIX32, serial_number); } void SHT3XDComponent::dump_config() { ESP_LOGCONFIG(TAG, "SHT3xD:"); diff --git a/esphome/components/sht3xd/sht3xd.h b/esphome/components/sht3xd/sht3xd.h index 04023c8a46..4133bf7b93 100644 --- a/esphome/components/sht3xd/sht3xd.h +++ b/esphome/components/sht3xd/sht3xd.h @@ -4,6 +4,8 @@ #include "esphome/components/sensor/sensor.h" #include "esphome/components/sensirion_common/i2c_sensirion.h" +#include + namespace esphome { namespace sht3xd { diff --git a/esphome/components/sht4x/sht4x.cpp b/esphome/components/sht4x/sht4x.cpp index 0f9123434d..dea542ea9e 100644 --- a/esphome/components/sht4x/sht4x.cpp +++ b/esphome/components/sht4x/sht4x.cpp @@ -20,7 +20,7 @@ void SHT4XComponent::setup() { if (this->duty_cycle_ > 0.0) { uint32_t heater_interval = (uint32_t) (this->heater_time_ / this->duty_cycle_); - ESP_LOGD(TAG, "Heater interval: %i", heater_interval); + ESP_LOGD(TAG, "Heater interval: %" PRIu32, heater_interval); if (this->heater_power_ == SHT4X_HEATERPOWER_HIGH) { if (this->heater_time_ == SHT4X_HEATERTIME_LONG) { diff --git a/esphome/components/sht4x/sht4x.h b/esphome/components/sht4x/sht4x.h index 01553d5c15..46037bb0e8 100644 --- a/esphome/components/sht4x/sht4x.h +++ b/esphome/components/sht4x/sht4x.h @@ -4,6 +4,8 @@ #include "esphome/components/sensor/sensor.h" #include "esphome/components/sensirion_common/i2c_sensirion.h" +#include + namespace esphome { namespace sht4x { diff --git a/esphome/components/sts3x/sts3x.cpp b/esphome/components/sts3x/sts3x.cpp index 5af808b6e7..a533bc1d87 100644 --- a/esphome/components/sts3x/sts3x.cpp +++ b/esphome/components/sts3x/sts3x.cpp @@ -30,7 +30,7 @@ void STS3XComponent::setup() { return; } uint32_t serial_number = (uint32_t(raw_serial_number[0]) << 16); - ESP_LOGV(TAG, " Serial Number: 0x%08X", serial_number); + ESP_LOGV(TAG, " Serial Number: 0x%08" PRIX32, serial_number); } void STS3XComponent::dump_config() { ESP_LOGCONFIG(TAG, "STS3x:"); diff --git a/esphome/components/sts3x/sts3x.h b/esphome/components/sts3x/sts3x.h index 261033efad..8f806a3471 100644 --- a/esphome/components/sts3x/sts3x.h +++ b/esphome/components/sts3x/sts3x.h @@ -4,6 +4,8 @@ #include "esphome/components/sensor/sensor.h" #include "esphome/components/sensirion_common/i2c_sensirion.h" +#include + namespace esphome { namespace sts3x { 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 da56976b56..b39b587811 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 @@ -26,14 +26,14 @@ void TemplateAlarmControlPanel::dump_config() { ESP_LOGCONFIG(TAG, " Number of Codes: %u", this->codes_.size()); if (!this->codes_.empty()) ESP_LOGCONFIG(TAG, " Requires Code To Arm: %s", YESNO(this->requires_code_to_arm_)); - ESP_LOGCONFIG(TAG, " Arming Away Time: %us", (this->arming_away_time_ / 1000)); + ESP_LOGCONFIG(TAG, " Arming Away Time: %" PRIu32 "s", (this->arming_away_time_ / 1000)); if (this->arming_home_time_ != 0) - ESP_LOGCONFIG(TAG, " Arming Home Time: %us", (this->arming_home_time_ / 1000)); + ESP_LOGCONFIG(TAG, " Arming Home Time: %" PRIu32 "s", (this->arming_home_time_ / 1000)); if (this->arming_night_time_ != 0) - ESP_LOGCONFIG(TAG, " Arming Night Time: %us", (this->arming_night_time_ / 1000)); - ESP_LOGCONFIG(TAG, " Pending Time: %us", (this->pending_time_ / 1000)); - ESP_LOGCONFIG(TAG, " Trigger Time: %us", (this->trigger_time_ / 1000)); - ESP_LOGCONFIG(TAG, " Supported Features: %u", this->get_supported_features()); + ESP_LOGCONFIG(TAG, " Arming Night Time: %" PRIu32 "s", (this->arming_night_time_ / 1000)); + ESP_LOGCONFIG(TAG, " Pending Time: %" PRIu32 "s", (this->pending_time_ / 1000)); + ESP_LOGCONFIG(TAG, " Trigger Time: %" PRIu32 "s", (this->trigger_time_ / 1000)); + ESP_LOGCONFIG(TAG, " Supported Features: %" PRIu32, this->get_supported_features()); #ifdef USE_BINARY_SENSOR for (auto sensor_pair : this->sensor_map_) { ESP_LOGCONFIG(TAG, " Binary Sesnsor:"); 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 ebd8696692..9582ed157c 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,5 +1,6 @@ #pragma once +#include #include #include "esphome/core/automation.h" diff --git a/esphome/components/tsl2591/tsl2591.cpp b/esphome/components/tsl2591/tsl2591.cpp index 5086a38408..977048364c 100644 --- a/esphome/components/tsl2591/tsl2591.cpp +++ b/esphome/components/tsl2591/tsl2591.cpp @@ -142,8 +142,8 @@ void TSL2591Component::process_update_() { uint16_t full = this->get_illuminance(TSL2591_SENSOR_CHANNEL_FULL_SPECTRUM, combined); float lux = this->get_calculated_lux(full, infrared); uint16_t actual_gain = this->get_actual_gain(); - ESP_LOGD(TAG, "Got illuminance: combined 0x%X, full %d, IR %d, vis %d. Calc lux: %f. Actual gain: %d.", combined, - full, infrared, visible, lux, actual_gain); + ESP_LOGD(TAG, "Got illuminance: combined 0x%" PRIX32 ", full %d, IR %d, vis %d. Calc lux: %f. Actual gain: %d.", + combined, full, infrared, visible, lux, actual_gain); if (this->full_spectrum_sensor_ != nullptr) { this->full_spectrum_sensor_->publish_state(full); } diff --git a/esphome/components/tsl2591/tsl2591.h b/esphome/components/tsl2591/tsl2591.h index d7c5230276..fa302b14b0 100644 --- a/esphome/components/tsl2591/tsl2591.h +++ b/esphome/components/tsl2591/tsl2591.h @@ -4,6 +4,8 @@ #include "esphome/components/sensor/sensor.h" #include "esphome/components/i2c/i2c.h" +#include + namespace esphome { namespace tsl2591 { diff --git a/esphome/components/uart/switch/uart_switch.cpp b/esphome/components/uart/switch/uart_switch.cpp index b995aca98c..1edb54641b 100644 --- a/esphome/components/uart/switch/uart_switch.cpp +++ b/esphome/components/uart/switch/uart_switch.cpp @@ -53,7 +53,7 @@ void UARTSwitch::write_state(bool state) { void UARTSwitch::dump_config() { LOG_SWITCH("", "UART Switch", this); if (this->send_every_) { - ESP_LOGCONFIG(TAG, " Send Every: %u", this->send_every_); + ESP_LOGCONFIG(TAG, " Send Every: %" PRIu32, this->send_every_); } } diff --git a/esphome/components/uart/switch/uart_switch.h b/esphome/components/uart/switch/uart_switch.h index eb3d697a58..4ef5b6da4b 100644 --- a/esphome/components/uart/switch/uart_switch.h +++ b/esphome/components/uart/switch/uart_switch.h @@ -4,6 +4,7 @@ #include "esphome/components/uart/uart.h" #include "esphome/components/switch/switch.h" +#include #include namespace esphome { diff --git a/esphome/components/ultrasonic/ultrasonic_sensor.cpp b/esphome/components/ultrasonic/ultrasonic_sensor.cpp index dc828aed6b..604e78d6f8 100644 --- a/esphome/components/ultrasonic/ultrasonic_sensor.cpp +++ b/esphome/components/ultrasonic/ultrasonic_sensor.cpp @@ -30,7 +30,7 @@ void UltrasonicSensorComponent::update() { ; const uint32_t pulse_end = micros(); - ESP_LOGV(TAG, "Echo took %uµs", pulse_end - pulse_start); + ESP_LOGV(TAG, "Echo took %" PRIu32 "µs", pulse_end - pulse_start); if (pulse_end - start >= timeout_us_) { ESP_LOGD(TAG, "'%s' - Distance measurement timed out!", this->name_.c_str()); @@ -45,8 +45,8 @@ 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: %u µs", this->pulse_time_us_); - ESP_LOGCONFIG(TAG, " Timeout: %u µs", this->timeout_us_); + ESP_LOGCONFIG(TAG, " Pulse time: %" PRIu32 " µs", this->pulse_time_us_); + ESP_LOGCONFIG(TAG, " Timeout: %" PRIu32 " µs", this->timeout_us_); LOG_UPDATE_INTERVAL(this); } float UltrasonicSensorComponent::us_to_m(uint32_t us) { diff --git a/esphome/components/ultrasonic/ultrasonic_sensor.h b/esphome/components/ultrasonic/ultrasonic_sensor.h index e0d71b99ef..1a255d6122 100644 --- a/esphome/components/ultrasonic/ultrasonic_sensor.h +++ b/esphome/components/ultrasonic/ultrasonic_sensor.h @@ -4,6 +4,8 @@ #include "esphome/core/gpio.h" #include "esphome/components/sensor/sensor.h" +#include + namespace esphome { namespace ultrasonic { diff --git a/esphome/components/whynter/whynter.cpp b/esphome/components/whynter/whynter.cpp index 190bf70acc..9f57fdb843 100644 --- a/esphome/components/whynter/whynter.cpp +++ b/esphome/components/whynter/whynter.cpp @@ -118,7 +118,7 @@ bool Whynter::on_receive(remote_base::RemoteReceiveData data) { } } - ESP_LOGD(TAG, "Decoded 0x%02X", remote_state); + ESP_LOGD(TAG, "Decoded 0x%02" PRIX32, remote_state); if ((remote_state & COMMAND_MASK) != COMMAND_CODE) return false; if ((remote_state & POWER_MASK) != POWER_MASK) { @@ -156,7 +156,7 @@ bool Whynter::on_receive(remote_base::RemoteReceiveData data) { } void Whynter::transmit_(uint32_t value) { - ESP_LOGD(TAG, "Sending whynter code: 0x%02X", value); + ESP_LOGD(TAG, "Sending Whynter code: 0x%02" PRIX32, value); auto transmit = this->transmitter_->transmit(); auto *data = transmit.get_data(); diff --git a/esphome/components/whynter/whynter.h b/esphome/components/whynter/whynter.h index 939583ebfb..8273c21e4b 100644 --- a/esphome/components/whynter/whynter.h +++ b/esphome/components/whynter/whynter.h @@ -2,6 +2,8 @@ #include "esphome/components/climate_ir/climate_ir.h" +#include + namespace esphome { namespace whynter { From 19736f6e537269fff2ec42b0348b43b277dc8fb2 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 18 Oct 2023 22:12:35 +1300 Subject: [PATCH 0337/2101] Fix voice_assistant without a speaker (#5558) --- esphome/components/voice_assistant/voice_assistant.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index 27dc201073..df7853156d 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -316,8 +316,8 @@ void VoiceAssistant::loop() { this->speaker_buffer_index_ = 0; memset(this->speaker_buffer_, 0, SPEAKER_BUFFER_SIZE); } -#endif this->wait_for_stream_end_ = false; +#endif this->set_state_(State::IDLE, State::IDLE); break; } @@ -586,7 +586,9 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { break; } case api::enums::VOICE_ASSISTANT_TTS_STREAM_START: { +#ifdef USE_SPEAKER this->wait_for_stream_end_ = true; +#endif break; } case api::enums::VOICE_ASSISTANT_TTS_STREAM_END: { From b735fc475e65799a5d95fb7a4bf4f51b82efdfc9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Oct 2023 08:28:52 -1000 Subject: [PATCH 0338/2101] Bump aioesphomeapi from 15.0.0 to 18.0.6 (#5557) 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 97e42663d7..44a9dc4916 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,7 +10,7 @@ platformio==6.1.11 # When updating platformio, also update Dockerfile esptool==4.6.2 click==8.1.7 esphome-dashboard==20230904.0 -aioesphomeapi==15.0.0 +aioesphomeapi==18.0.6 zeroconf==0.115.1 # esp-idf requires this, but doesn't bundle it by default From 10c89771e35776c3f90fbcac95fdcabb2e479812 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Oct 2023 10:21:19 -1000 Subject: [PATCH 0339/2101] Bump zeroconf from 0.115.1 to 0.119.0 (#5560) --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 44a9dc4916..23d133a6ed 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,7 +11,7 @@ esptool==4.6.2 click==8.1.7 esphome-dashboard==20230904.0 aioesphomeapi==18.0.6 -zeroconf==0.115.1 +zeroconf==0.119.0 # esp-idf requires this, but doesn't bundle it by default # https://github.com/espressif/esp-idf/blob/220590d599e134d7a5e7f1e683cc4550349ffbf8/requirements.txt#L24 From a8667b680ec76907f2b5da8f06b557e44ea097ca Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 19 Oct 2023 11:42:52 +1300 Subject: [PATCH 0340/2101] esp32_improv add timeout (#5556) --- esphome/components/esp32_improv/__init__.py | 5 +++++ .../esp32_improv/esp32_improv_component.h | 5 +++++ esphome/components/wifi/wifi_component.cpp | 14 +++++++------- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/esphome/components/esp32_improv/__init__.py b/esphome/components/esp32_improv/__init__.py index fba2e55ae8..49d95d89e5 100644 --- a/esphome/components/esp32_improv/__init__.py +++ b/esphome/components/esp32_improv/__init__.py @@ -36,6 +36,9 @@ CONFIG_SCHEMA = cv.Schema( cv.Optional( CONF_AUTHORIZED_DURATION, default="1min" ): cv.positive_time_period_milliseconds, + cv.Optional( + CONF_WIFI_TIMEOUT, default="1min" + ): cv.positive_time_period_milliseconds, } ).extend(cv.COMPONENT_SCHEMA) @@ -53,6 +56,8 @@ async def to_code(config): cg.add(var.set_identify_duration(config[CONF_IDENTIFY_DURATION])) cg.add(var.set_authorized_duration(config[CONF_AUTHORIZED_DURATION])) + cg.add(var.set_wifi_timeout(config[CONF_WIFI_TIMEOUT])) + if CONF_AUTHORIZER in config and config[CONF_AUTHORIZER] is not None: activator = await cg.get_variable(config[CONF_AUTHORIZER]) cg.add(var.set_authorizer(activator)) diff --git a/esphome/components/esp32_improv/esp32_improv_component.h b/esphome/components/esp32_improv/esp32_improv_component.h index ba9892d6a5..00c6cf885a 100644 --- a/esphome/components/esp32_improv/esp32_improv_component.h +++ b/esphome/components/esp32_improv/esp32_improv_component.h @@ -51,6 +51,9 @@ class ESP32ImprovComponent : public Component, public BLEServiceComponent { void set_identify_duration(uint32_t identify_duration) { this->identify_duration_ = identify_duration; } void set_authorized_duration(uint32_t authorized_duration) { this->authorized_duration_ = authorized_duration; } + void set_wifi_timeout(uint32_t wifi_timeout) { this->wifi_timeout_ = wifi_timeout; } + uint32_t get_wifi_timeout() const { return this->wifi_timeout_; } + protected: bool should_start_{false}; bool setup_complete_{false}; @@ -60,6 +63,8 @@ class ESP32ImprovComponent : public Component, public BLEServiceComponent { uint32_t authorized_start_{0}; uint32_t authorized_duration_; + uint32_t wifi_timeout_{}; + std::vector incoming_data_; wifi::WiFiAP connecting_sta_; diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 2cb36fe8ea..b08f20de21 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -8,16 +8,16 @@ #include #endif -#include #include -#include "lwip/err.h" +#include #include "lwip/dns.h" +#include "lwip/err.h" +#include "esphome/core/application.h" +#include "esphome/core/hal.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" -#include "esphome/core/hal.h" #include "esphome/core/util.h" -#include "esphome/core/application.h" #ifdef USE_CAPTIVE_PORTAL #include "esphome/components/captive_portal/captive_portal.h" @@ -96,7 +96,7 @@ void WiFiComponent::start() { #endif } #ifdef USE_IMPROV - if (esp32_improv::global_improv_component != nullptr) { + if (!this->has_sta() && esp32_improv::global_improv_component != nullptr) { if (this->wifi_mode_(true, {})) esp32_improv::global_improv_component->start(); } @@ -163,8 +163,8 @@ void WiFiComponent::loop() { } #ifdef USE_IMPROV - if (esp32_improv::global_improv_component != nullptr) { - if (!this->is_connected()) { + if (esp32_improv::global_improv_component != nullptr && !esp32_improv::global_improv_component->is_active()) { + if (now - this->last_connected_ > esp32_improv::global_improv_component->get_wifi_timeout()) { if (this->wifi_mode_(true, {})) esp32_improv::global_improv_component->start(); } From b7402ee6ffb99b1b0433ea2e00e665f9dde82dd3 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 19 Oct 2023 12:25:43 +1300 Subject: [PATCH 0341/2101] Create IPv4 sockets if ipv6 is not enabled (#5565) --- esphome/components/socket/socket.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/socket/socket.cpp b/esphome/components/socket/socket.cpp index 824e04150b..d0fce9198f 100644 --- a/esphome/components/socket/socket.cpp +++ b/esphome/components/socket/socket.cpp @@ -10,7 +10,7 @@ namespace socket { Socket::~Socket() {} std::unique_ptr socket_ip(int type, int protocol) { -#if LWIP_IPV6 +#if ENABLE_IPV6 return socket(AF_INET6, type, protocol); #else return socket(AF_INET, type, protocol); @@ -18,7 +18,7 @@ std::unique_ptr socket_ip(int type, int protocol) { } socklen_t set_sockaddr(struct sockaddr *addr, socklen_t addrlen, const std::string &ip_address, uint16_t port) { -#if LWIP_IPV6 +#if ENABLE_IPV6 if (addrlen < sizeof(sockaddr_in6)) { errno = EINVAL; return 0; @@ -51,7 +51,7 @@ socklen_t set_sockaddr(struct sockaddr *addr, socklen_t addrlen, const std::stri } socklen_t set_sockaddr_any(struct sockaddr *addr, socklen_t addrlen, uint16_t port) { -#if LWIP_IPV6 +#if ENABLE_IPV6 if (addrlen < sizeof(sockaddr_in6)) { errno = EINVAL; return 0; From 799c3cf439b4f2a72c0c37c42955d6e38eb334ff Mon Sep 17 00:00:00 2001 From: Mike La Spina Date: Wed, 18 Oct 2023 19:00:15 -0500 Subject: [PATCH 0342/2101] Incorrect ESP32 Strapping PIN Defined (#5563) Co-authored-by: descipher <120155735+GelidusResearch@users.noreply.github.com> --- esphome/components/esp32/gpio_esp32.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/esp32/gpio_esp32.py b/esphome/components/esp32/gpio_esp32.py index 66ba2ffa62..91f006444c 100644 --- a/esphome/components/esp32/gpio_esp32.py +++ b/esphome/components/esp32/gpio_esp32.py @@ -18,7 +18,7 @@ _ESP_SDIO_PINS = { 11: "Flash Command", } -_ESP32_STRAPPING_PINS = {0, 2, 4, 12, 15} +_ESP32_STRAPPING_PINS = {0, 2, 5, 12, 15} _LOGGER = logging.getLogger(__name__) From a794836ebe9c50feb2213b71d30d13e55a778ca2 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Thu, 19 Oct 2023 09:04:53 +0900 Subject: [PATCH 0343/2101] Add config to allow suppression of warnings about use of strapping pins (#5287) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/esp32/gpio.py | 2 ++ esphome/components/esp32/gpio_esp32.py | 9 ++------- esphome/components/esp32/gpio_esp32_c2.py | 10 +++------- esphome/components/esp32/gpio_esp32_c3.py | 10 +++------- esphome/components/esp32/gpio_esp32_c6.py | 10 +++------- esphome/components/esp32/gpio_esp32_s2.py | 9 ++------- esphome/components/esp32/gpio_esp32_s3.py | 11 +++-------- esphome/const.py | 1 + esphome/pins.py | 17 ++++++++++++++++- tests/test8.yaml | 4 +++- 10 files changed, 38 insertions(+), 45 deletions(-) diff --git a/esphome/components/esp32/gpio.py b/esphome/components/esp32/gpio.py index 6950cd58a0..a53649e3e4 100644 --- a/esphome/components/esp32/gpio.py +++ b/esphome/components/esp32/gpio.py @@ -11,6 +11,7 @@ from esphome.const import ( CONF_OUTPUT, CONF_PULLDOWN, CONF_PULLUP, + CONF_IGNORE_STRAPPING_WARNING, ) from esphome import pins from esphome.core import CORE @@ -176,6 +177,7 @@ ESP32_PIN_SCHEMA = cv.All( } ), cv.Optional(CONF_INVERTED, default=False): cv.boolean, + cv.Optional(CONF_IGNORE_STRAPPING_WARNING, default=False): cv.boolean, cv.Optional(CONF_DRIVE_STRENGTH, default="20mA"): cv.All( cv.float_with_unit("current", "mA", optional_unit=True), cv.enum(DRIVE_STRENGTHS), diff --git a/esphome/components/esp32/gpio_esp32.py b/esphome/components/esp32/gpio_esp32.py index 91f006444c..d10b266c7a 100644 --- a/esphome/components/esp32/gpio_esp32.py +++ b/esphome/components/esp32/gpio_esp32.py @@ -9,6 +9,7 @@ from esphome.const import ( CONF_PULLUP, ) import esphome.config_validation as cv +from esphome.pins import check_strapping_pin _ESP_SDIO_PINS = { @@ -35,13 +36,6 @@ def esp32_validate_gpio_pin(value): "flash interface in QUAD IO flash mode.", value, ) - if value in _ESP32_STRAPPING_PINS: - _LOGGER.warning( - "GPIO%d is a Strapping PIN and should be avoided.\n" - "Attaching external pullup/down resistors to strapping pins can cause unexpected failures.\n" - "See https://esphome.io/guides/faq.html#why-am-i-getting-a-warning-about-strapping-pins", - value, - ) if value in (24, 28, 29, 30, 31): # These pins are not exposed in GPIO mux (reason unknown) # but they're missing from IO_MUX list in datasheet @@ -74,4 +68,5 @@ def esp32_validate_supports(value): f"GPIO{num} (34-39) does not support pulldowns.", [CONF_MODE, CONF_PULLDOWN] ) + check_strapping_pin(value, _ESP32_STRAPPING_PINS, _LOGGER) return value diff --git a/esphome/components/esp32/gpio_esp32_c2.py b/esphome/components/esp32/gpio_esp32_c2.py index c444f804a3..0bee7d82bf 100644 --- a/esphome/components/esp32/gpio_esp32_c2.py +++ b/esphome/components/esp32/gpio_esp32_c2.py @@ -1,6 +1,7 @@ import logging from esphome.const import CONF_INPUT, CONF_MODE, CONF_NUMBER +from esphome.pins import check_strapping_pin import esphome.config_validation as cv @@ -12,13 +13,6 @@ _LOGGER = logging.getLogger(__name__) def esp32_c2_validate_gpio_pin(value): if value < 0 or value > 20: raise cv.Invalid(f"Invalid pin number: {value} (must be 0-20)") - if value in _ESP32C2_STRAPPING_PINS: - _LOGGER.warning( - "GPIO%d is a Strapping PIN and should be avoided.\n" - "Attaching external pullup/down resistors to strapping pins can cause unexpected failures.\n" - "See https://esphome.io/guides/faq.html#why-am-i-getting-a-warning-about-strapping-pins", - value, - ) return value @@ -34,4 +28,6 @@ def esp32_c2_validate_supports(value): if is_input: # All ESP32 pins support input mode pass + + check_strapping_pin(value, _ESP32C2_STRAPPING_PINS, _LOGGER) return value diff --git a/esphome/components/esp32/gpio_esp32_c3.py b/esphome/components/esp32/gpio_esp32_c3.py index fc1cef29e5..6c70c09f9e 100644 --- a/esphome/components/esp32/gpio_esp32_c3.py +++ b/esphome/components/esp32/gpio_esp32_c3.py @@ -6,6 +6,7 @@ from esphome.const import ( CONF_NUMBER, ) import esphome.config_validation as cv +from esphome.pins import check_strapping_pin _ESP32C3_SPI_PSRAM_PINS = { 12: "SPIHD", @@ -28,13 +29,6 @@ def esp32_c3_validate_gpio_pin(value): 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_STRAPPING_PINS: - _LOGGER.warning( - "GPIO%d is a Strapping PIN and should be avoided.\n" - "Attaching external pullup/down resistors to strapping pins can cause unexpected failures.\n" - "See https://esphome.io/guides/faq.html#why-am-i-getting-a-warning-about-strapping-pins", - value, - ) return value @@ -50,4 +44,6 @@ def esp32_c3_validate_supports(value): if is_input: # All ESP32 pins support input mode pass + + check_strapping_pin(value, _ESP32C3_STRAPPING_PINS, _LOGGER) return value diff --git a/esphome/components/esp32/gpio_esp32_c6.py b/esphome/components/esp32/gpio_esp32_c6.py index b26b6bc6b4..a1f777c625 100644 --- a/esphome/components/esp32/gpio_esp32_c6.py +++ b/esphome/components/esp32/gpio_esp32_c6.py @@ -3,6 +3,7 @@ import logging from esphome.const import CONF_INPUT, CONF_MODE, CONF_NUMBER import esphome.config_validation as cv +from esphome.pins import check_strapping_pin _ESP32C6_SPI_PSRAM_PINS = { 24: "SPICS0", @@ -26,13 +27,6 @@ def esp32_c6_validate_gpio_pin(value): 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_STRAPPING_PINS: - _LOGGER.warning( - "GPIO%d is a Strapping PIN and should be avoided.\n" - "Attaching external pullup/down resistors to strapping pins can cause unexpected failures.\n" - "See https://esphome.io/guides/faq.html#why-am-i-getting-a-warning-about-strapping-pins", - value, - ) return value @@ -47,4 +41,6 @@ def esp32_c6_validate_supports(value): if is_input: # All ESP32 pins support input mode pass + + check_strapping_pin(value, _ESP32C6_STRAPPING_PINS, _LOGGER) return value diff --git a/esphome/components/esp32/gpio_esp32_s2.py b/esphome/components/esp32/gpio_esp32_s2.py index db244b6259..82449532ec 100644 --- a/esphome/components/esp32/gpio_esp32_s2.py +++ b/esphome/components/esp32/gpio_esp32_s2.py @@ -10,6 +10,7 @@ from esphome.const import ( ) import esphome.config_validation as cv +from esphome.pins import check_strapping_pin _ESP32S2_SPI_PSRAM_PINS = { 26: "SPICS1", @@ -34,13 +35,6 @@ def esp32_s2_validate_gpio_pin(value): raise cv.Invalid( f"This pin cannot be used on ESP32-S2s and is already used by the SPI/PSRAM interface (function: {_ESP32S2_SPI_PSRAM_PINS[value]})" ) - if value in _ESP32S2_STRAPPING_PINS: - _LOGGER.warning( - "GPIO%d is a Strapping PIN and should be avoided.\n" - "Attaching external pullup/down resistors to strapping pins can cause unexpected failures.\n" - "See https://esphome.io/guides/faq.html#why-am-i-getting-a-warning-about-strapping-pins", - value, - ) if value in (22, 23, 24, 25): # These pins are not exposed in GPIO mux (reason unknown) @@ -77,4 +71,5 @@ def esp32_s2_validate_supports(value): f"GPIO{num} does not support pulldowns.", [CONF_MODE, CONF_PULLDOWN] ) + check_strapping_pin(value, _ESP32S2_STRAPPING_PINS, _LOGGER) return value diff --git a/esphome/components/esp32/gpio_esp32_s3.py b/esphome/components/esp32/gpio_esp32_s3.py index f729a757c2..8dcbf8c7bb 100644 --- a/esphome/components/esp32/gpio_esp32_s3.py +++ b/esphome/components/esp32/gpio_esp32_s3.py @@ -7,6 +7,7 @@ from esphome.const import ( ) import esphome.config_validation as cv +from esphome.pins import check_strapping_pin _ESP_32S3_SPI_PSRAM_PINS = { 26: "SPICS1", @@ -45,14 +46,6 @@ def esp32_s3_validate_gpio_pin(value): value, ) - if value in _ESP_32S3_STRAPPING_PINS: - _LOGGER.warning( - "GPIO%d is a Strapping PIN and should be avoided.\n" - "Attaching external pullup/down resistors to strapping pins can cause unexpected failures.\n" - "See https://esphome.io/guides/faq.html#why-am-i-getting-a-warning-about-strapping-pins", - value, - ) - if value in (22, 23, 24, 25): # These pins are not exposed in GPIO mux (reason unknown) # but they're missing from IO_MUX list in datasheet @@ -71,4 +64,6 @@ def esp32_s3_validate_supports(value): if is_input: # All ESP32 pins support input mode pass + + check_strapping_pin(value, _ESP_32S3_STRAPPING_PINS, _LOGGER) return value diff --git a/esphome/const.py b/esphome/const.py index eb7a5dab09..be561c2880 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -335,6 +335,7 @@ CONF_IDLE_LEVEL = "idle_level" CONF_IDLE_TIME = "idle_time" CONF_IF = "if" CONF_IGNORE_EFUSE_MAC_CRC = "ignore_efuse_mac_crc" +CONF_IGNORE_STRAPPING_WARNING = "ignore_strapping_warning" CONF_IIR_FILTER = "iir_filter" CONF_ILLUMINANCE = "illuminance" CONF_IMPEDANCE = "impedance" diff --git a/esphome/pins.py b/esphome/pins.py index 2ac4cd4b54..cec715b922 100644 --- a/esphome/pins.py +++ b/esphome/pins.py @@ -9,11 +9,11 @@ from esphome.const import ( CONF_OUTPUT, CONF_PULLDOWN, CONF_PULLUP, + CONF_IGNORE_STRAPPING_WARNING, ) from esphome.util import SimpleRegistry from esphome.core import CORE - PIN_SCHEMA_REGISTRY = SimpleRegistry() @@ -146,3 +146,18 @@ internal_gpio_input_pullup_pin_number = _internal_number_creator( CONF_PULLUP: True, } ) + + +def check_strapping_pin(conf, strapping_pin_list, logger): + import esphome.config_validation as cv + + num = conf[CONF_NUMBER] + if num in strapping_pin_list and not conf.get(CONF_IGNORE_STRAPPING_WARNING): + logger.warning( + f"GPIO{num} is a strapping PIN and should only be used for I/O with care.\n" + "Attaching external pullup/down resistors to strapping pins can cause unexpected failures.\n" + "See https://esphome.io/guides/faq.html#why-am-i-getting-a-warning-about-strapping-pins", + ) + # mitigate undisciplined use of strapping: + if num not in strapping_pin_list and conf.get(CONF_IGNORE_STRAPPING_WARNING): + raise cv.Invalid(f"GPIO{num} is not a strapping pin") diff --git a/tests/test8.yaml b/tests/test8.yaml index 3ba8aa19ef..cbac2cb833 100644 --- a/tests/test8.yaml +++ b/tests/test8.yaml @@ -65,7 +65,9 @@ i2c: touchscreen: - platform: tt21100 - interrupt_pin: GPIO3 + interrupt_pin: + number: GPIO3 + ignore_strapping_warning: true reset_pin: GPIO48 binary_sensor: From a7d817656e0546b99d629065479b80b25027ee06 Mon Sep 17 00:00:00 2001 From: jj-uk <10943625+jj-uk@users.noreply.github.com> Date: Thu, 19 Oct 2023 01:06:28 +0100 Subject: [PATCH 0344/2101] Hydreon updates (#5424) --- .../components/hydreon_rgxx/hydreon_rgxx.cpp | 36 +++++++++++++++++-- .../components/hydreon_rgxx/hydreon_rgxx.h | 3 ++ esphome/components/hydreon_rgxx/sensor.py | 16 +++++++-- tests/test3.yaml | 6 ++++ 4 files changed, 56 insertions(+), 5 deletions(-) diff --git a/esphome/components/hydreon_rgxx/hydreon_rgxx.cpp b/esphome/components/hydreon_rgxx/hydreon_rgxx.cpp index da4345e136..58e00ba7a5 100644 --- a/esphome/components/hydreon_rgxx/hydreon_rgxx.cpp +++ b/esphome/components/hydreon_rgxx/hydreon_rgxx.cpp @@ -25,6 +25,10 @@ void HydreonRGxxComponent::dump_config() { LOG_SENSOR(" ", #s, this->sensors_[i - 1]); \ } HYDREON_RGXX_PROTOCOL_LIST(HYDREON_RGXX_LOG_SENSOR, ); + + if (this->model_ == RG9) { + ESP_LOGCONFIG(TAG, "disable_led: %s", TRUEFALSE(this->disable_led_)); + } } void HydreonRGxxComponent::setup() { @@ -187,7 +191,20 @@ void HydreonRGxxComponent::process_line_() { this->cancel_interval("reboot"); this->no_response_count_ = 0; ESP_LOGI(TAG, "Boot detected: %s", this->buffer_.substr(0, this->buffer_.size() - 2).c_str()); - this->write_str("P\nH\nM\n"); // set sensor to polling mode, high res mode, metric mode + + if (this->model_ == RG15) { + this->write_str("P\nH\nM\n"); // set sensor to (P)polling mode, (H)high res mode, (M)metric mode + } + + if (this->model_ == RG9) { + this->write_str("P\n"); // set sensor to (P)polling mode + + if (this->disable_led_) { + this->write_str("D 1\n"); // set sensor (D 1)rain detection LED disabled + } else { + this->write_str("D 0\n"); // set sensor (D 0)rain detection LED enabled + } + } return; } if (this->buffer_starts_with_("SW")) { @@ -227,7 +244,22 @@ void HydreonRGxxComponent::process_line_() { if (n == std::string::npos) { continue; } - float data = strtof(this->buffer_.substr(n + strlen(PROTOCOL_NAMES[i])).c_str(), nullptr); + + if (n == this->buffer_.find('t', n)) { + // The device temperature ('t') response contains both °C and °F values: + // "t 72F 22C". + // ESPHome uses only °C, only parse °C value (move past 'F'). + n = this->buffer_.find('F', n); + if (n == std::string::npos) { + continue; + } + n += 1; // move past 'F' + } else { + n += strlen(PROTOCOL_NAMES[i]); // move past protocol name + } + + // parse value, starting at str position n + float data = strtof(this->buffer_.substr(n).c_str(), nullptr); this->sensors_[i]->publish_state(data); ESP_LOGD(TAG, "Received %s: %f", PROTOCOL_NAMES[i], this->sensors_[i]->get_raw_state()); this->sensors_received_ |= (1 << i); diff --git a/esphome/components/hydreon_rgxx/hydreon_rgxx.h b/esphome/components/hydreon_rgxx/hydreon_rgxx.h index 34b9bd8d5e..1edda59800 100644 --- a/esphome/components/hydreon_rgxx/hydreon_rgxx.h +++ b/esphome/components/hydreon_rgxx/hydreon_rgxx.h @@ -49,6 +49,8 @@ class HydreonRGxxComponent : public PollingComponent, public uart::UARTDevice { float get_setup_priority() const override; + void set_disable_led(bool disable_led) { this->disable_led_ = disable_led; } + protected: void process_line_(); void schedule_reboot_(); @@ -72,6 +74,7 @@ class HydreonRGxxComponent : public PollingComponent, public uart::UARTDevice { bool lens_bad_ = false; bool em_sat_ = false; bool request_temperature_ = false; + bool disable_led_ = false; // bit field showing which sensors we have received data for int sensors_received_ = -1; diff --git a/esphome/components/hydreon_rgxx/sensor.py b/esphome/components/hydreon_rgxx/sensor.py index c2dbbd6737..0fc380f959 100644 --- a/esphome/components/hydreon_rgxx/sensor.py +++ b/esphome/components/hydreon_rgxx/sensor.py @@ -25,12 +25,17 @@ CONF_EVENT_ACC = "event_acc" CONF_TOTAL_ACC = "total_acc" CONF_R_INT = "r_int" +CONF_DISABLE_LED = "disable_led" + RG_MODELS = { "RG_9": RGModel.RG9, "RG_15": RGModel.RG15, - # https://rainsensors.com/wp-content/uploads/sites/3/2020/07/rg-15_instructions_sw_1.000.pdf - # https://rainsensors.com/wp-content/uploads/sites/3/2021/03/2020.08.25-rg-9_instructions.pdf - # https://rainsensors.com/wp-content/uploads/sites/3/2021/03/2021.03.11-rg-9_instructions.pdf + # RG-15 + # 1.000 - https://rainsensors.com/wp-content/uploads/sites/3/2020/07/rg-15_instructions_sw_1.000.pdf + # RG-9 + # 1.000 - https://rainsensors.com/wp-content/uploads/sites/3/2021/03/2020.08.25-rg-9_instructions.pdf + # 1.100 - https://rainsensors.com/wp-content/uploads/sites/3/2021/03/2021.03.11-rg-9_instructions.pdf + # 1.200 - https://rainsensors.com/wp-content/uploads/sites/3/2022/03/2022.02.17-rev-1.200-rg-9_instructions.pdf } SUPPORTED_SENSORS = { CONF_ACC: ["RG_15"], @@ -39,6 +44,7 @@ SUPPORTED_SENSORS = { CONF_R_INT: ["RG_15"], CONF_MOISTURE: ["RG_9"], CONF_TEMPERATURE: ["RG_9"], + CONF_DISABLE_LED: ["RG_9"], } PROTOCOL_NAMES = { CONF_MOISTURE: "R", @@ -105,6 +111,7 @@ CONFIG_SCHEMA = cv.All( icon=ICON_THERMOMETER, state_class=STATE_CLASS_MEASUREMENT, ), + cv.Optional(CONF_DISABLE_LED): cv.boolean, } ) .extend(cv.polling_component_schema("60s")) @@ -132,3 +139,6 @@ async def to_code(config): cg.add(var.set_sensor(sens, i)) cg.add(var.set_request_temperature(CONF_TEMPERATURE in config)) + + if CONF_DISABLE_LED in config: + cg.add(var.set_disable_led(config[CONF_DISABLE_LED])) diff --git a/tests/test3.yaml b/tests/test3.yaml index e7cf24a95a..41ded7ee39 100644 --- a/tests/test3.yaml +++ b/tests/test3.yaml @@ -347,6 +347,10 @@ sensor: moisture: name: hydreon_rain id: hydreon_rain + temperature: + name: hydreon_temperature + disable_led: true + - platform: hydreon_rgxx model: RG_15 uart_id: uart_6 @@ -358,6 +362,7 @@ sensor: name: hydreon_total_acc r_int: name: hydreon_r_int + - platform: adc pin: VCC id: my_sensor @@ -725,6 +730,7 @@ binary_sensor: name: rg9_emsat lens_bad: name: rg9_lens_bad + - platform: template id: pzemac_reset_energy on_press: From 9a087c07678f22286edced4b4f9a4d283b53e725 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Oct 2023 13:08:15 +1300 Subject: [PATCH 0345/2101] Bump actions/checkout from 4.1.0 to 4.1.1 (#5551) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-docker.yml | 2 +- .github/workflows/ci.yml | 22 +++++++++++----------- .github/workflows/release.yml | 6 +++--- .github/workflows/sync-device-classes.yml | 4 ++-- .github/workflows/yaml-lint.yml | 2 +- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci-docker.yml b/.github/workflows/ci-docker.yml index 897d01398e..51f47d39aa 100644 --- a/.github/workflows/ci-docker.yml +++ b/.github/workflows/ci-docker.yml @@ -40,7 +40,7 @@ jobs: arch: [amd64, armv7, aarch64] build_type: ["ha-addon", "docker", "lint"] steps: - - uses: actions/checkout@v4.1.0 + - uses: actions/checkout@v4.1.1 - name: Set up Python uses: actions/setup-python@v4.7.1 with: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 435a2fdbec..70da22e57a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,7 +34,7 @@ jobs: cache-key: ${{ steps.cache-key.outputs.key }} steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.0 + uses: actions/checkout@v4.1.1 - name: Generate cache-key id: cache-key run: echo key="${{ hashFiles('requirements.txt', 'requirements_optional.txt', 'requirements_test.txt') }}" >> $GITHUB_OUTPUT @@ -66,7 +66,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.0 + uses: actions/checkout@v4.1.1 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -87,7 +87,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.0 + uses: actions/checkout@v4.1.1 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -108,7 +108,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.0 + uses: actions/checkout@v4.1.1 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -129,7 +129,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.0 + uses: actions/checkout@v4.1.1 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -150,7 +150,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.0 + uses: actions/checkout@v4.1.1 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -171,7 +171,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.0 + uses: actions/checkout@v4.1.1 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -191,7 +191,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.0 + uses: actions/checkout@v4.1.1 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -216,7 +216,7 @@ jobs: matrix: ${{ steps.set-matrix.outputs.matrix }} steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.0 + uses: actions/checkout@v4.1.1 - name: Find all YAML test files id: set-matrix run: echo "matrix=$(ls tests/test*.yaml | jq -R -s -c 'split("\n")[:-1]')" >> $GITHUB_OUTPUT @@ -241,7 +241,7 @@ jobs: file: ${{ fromJson(needs.compile-tests-list.outputs.matrix) }} steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.0 + uses: actions/checkout@v4.1.1 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -296,7 +296,7 @@ jobs: steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.0 + uses: actions/checkout@v4.1.1 - name: Restore Python uses: ./.github/actions/restore-python with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f7652bf478..14dbeee7b7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,7 +19,7 @@ jobs: outputs: tag: ${{ steps.tag.outputs.tag }} steps: - - uses: actions/checkout@v4.1.0 + - uses: actions/checkout@v4.1.1 - name: Get tag id: tag # yamllint disable rule:line-length @@ -43,7 +43,7 @@ jobs: if: github.repository == 'esphome/esphome' && github.event_name == 'release' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.0 + - uses: actions/checkout@v4.1.1 - name: Set up Python uses: actions/setup-python@v4.7.1 with: @@ -88,7 +88,7 @@ jobs: target: "lint" baseimg: "docker" steps: - - uses: actions/checkout@v4.1.0 + - uses: actions/checkout@v4.1.1 - name: Set up Python uses: actions/setup-python@v4.7.1 with: diff --git a/.github/workflows/sync-device-classes.yml b/.github/workflows/sync-device-classes.yml index 082c63ae41..88edb63546 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@v4.1.0 + uses: actions/checkout@v4.1.1 - name: Checkout Home Assistant - uses: actions/checkout@v4.1.0 + uses: actions/checkout@v4.1.1 with: repository: home-assistant/core path: lib/home-assistant diff --git a/.github/workflows/yaml-lint.yml b/.github/workflows/yaml-lint.yml index 65628a22bb..a77bd2c078 100644 --- a/.github/workflows/yaml-lint.yml +++ b/.github/workflows/yaml-lint.yml @@ -17,6 +17,6 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.0 + uses: actions/checkout@v4.1.1 - name: Run yamllint uses: frenck/action-yamllint@v1.4.1 From 53572dcb8a22e78666103f9d3ec9a1031bee7895 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Oct 2023 13:08:44 +1300 Subject: [PATCH 0346/2101] Bump pyupgrade from 3.10.1 to 3.13.0 (#5428) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- esphome/components/remote_base/__init__.py | 4 ++-- requirements_test.txt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6e7261ebc3..eba6834cb6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -27,7 +27,7 @@ repos: - --branch=release - --branch=beta - repo: https://github.com/asottile/pyupgrade - rev: v3.10.1 + rev: v3.13.0 hooks: - id: pyupgrade args: [--py39-plus] diff --git a/esphome/components/remote_base/__init__.py b/esphome/components/remote_base/__init__.py index cf2ae89b6a..fb9d5e56a6 100644 --- a/esphome/components/remote_base/__init__.py +++ b/esphome/components/remote_base/__init__.py @@ -964,7 +964,7 @@ RC_SWITCH_PROTOCOL_SCHEMA = cv.Any( def validate_rc_switch_code(value): - if not isinstance(value, (str, str)): + if not isinstance(value, str): raise cv.Invalid("All RCSwitch codes must be in quotes ('')") for c in value: if c not in ("0", "1"): @@ -981,7 +981,7 @@ def validate_rc_switch_code(value): def validate_rc_switch_raw_code(value): - if not isinstance(value, (str, str)): + if not isinstance(value, str): raise cv.Invalid("All RCSwitch raw codes must be in quotes ('')") for c in value: if c not in ("0", "1", "x"): diff --git a/requirements_test.txt b/requirements_test.txt index 92cb8b1be2..5178c5c11f 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,7 +1,7 @@ pylint==2.17.6 flake8==6.1.0 # also change in .pre-commit-config.yaml when updating black==23.9.1 # also change in .pre-commit-config.yaml when updating -pyupgrade==3.10.1 # also change in .pre-commit-config.yaml when updating +pyupgrade==3.13.0 # also change in .pre-commit-config.yaml when updating pre-commit # Unit tests From 960d6a143134dacab67a57cf74d5a0ae037281d1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Oct 2023 13:09:04 +1300 Subject: [PATCH 0347/2101] Bump tzlocal from 5.0.1 to 5.1 (#5480) 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 23d133a6ed..4be7279f33 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,7 @@ PyYAML==6.0.1 paho-mqtt==1.6.1 colorama==0.4.6 tornado==6.3.3 -tzlocal==5.0.1 # from time +tzlocal==5.1 # from time tzdata>=2021.1 # from time pyserial==3.5 platformio==6.1.11 # When updating platformio, also update Dockerfile From 02449f24c9718aa959dbd5401a815685215acd59 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 18 Oct 2023 22:12:35 +1300 Subject: [PATCH 0348/2101] Fix voice_assistant without a speaker (#5558) --- esphome/components/voice_assistant/voice_assistant.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index 27dc201073..df7853156d 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -316,8 +316,8 @@ void VoiceAssistant::loop() { this->speaker_buffer_index_ = 0; memset(this->speaker_buffer_, 0, SPEAKER_BUFFER_SIZE); } -#endif this->wait_for_stream_end_ = false; +#endif this->set_state_(State::IDLE, State::IDLE); break; } @@ -586,7 +586,9 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { break; } case api::enums::VOICE_ASSISTANT_TTS_STREAM_START: { +#ifdef USE_SPEAKER this->wait_for_stream_end_ = true; +#endif break; } case api::enums::VOICE_ASSISTANT_TTS_STREAM_END: { From 9579423b24545c2921e83897a96ca2370dff44d7 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 19 Oct 2023 11:42:52 +1300 Subject: [PATCH 0349/2101] esp32_improv add timeout (#5556) --- esphome/components/esp32_improv/__init__.py | 5 +++++ .../esp32_improv/esp32_improv_component.h | 5 +++++ esphome/components/wifi/wifi_component.cpp | 14 +++++++------- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/esphome/components/esp32_improv/__init__.py b/esphome/components/esp32_improv/__init__.py index fba2e55ae8..49d95d89e5 100644 --- a/esphome/components/esp32_improv/__init__.py +++ b/esphome/components/esp32_improv/__init__.py @@ -36,6 +36,9 @@ CONFIG_SCHEMA = cv.Schema( cv.Optional( CONF_AUTHORIZED_DURATION, default="1min" ): cv.positive_time_period_milliseconds, + cv.Optional( + CONF_WIFI_TIMEOUT, default="1min" + ): cv.positive_time_period_milliseconds, } ).extend(cv.COMPONENT_SCHEMA) @@ -53,6 +56,8 @@ async def to_code(config): cg.add(var.set_identify_duration(config[CONF_IDENTIFY_DURATION])) cg.add(var.set_authorized_duration(config[CONF_AUTHORIZED_DURATION])) + cg.add(var.set_wifi_timeout(config[CONF_WIFI_TIMEOUT])) + if CONF_AUTHORIZER in config and config[CONF_AUTHORIZER] is not None: activator = await cg.get_variable(config[CONF_AUTHORIZER]) cg.add(var.set_authorizer(activator)) diff --git a/esphome/components/esp32_improv/esp32_improv_component.h b/esphome/components/esp32_improv/esp32_improv_component.h index ba9892d6a5..00c6cf885a 100644 --- a/esphome/components/esp32_improv/esp32_improv_component.h +++ b/esphome/components/esp32_improv/esp32_improv_component.h @@ -51,6 +51,9 @@ class ESP32ImprovComponent : public Component, public BLEServiceComponent { void set_identify_duration(uint32_t identify_duration) { this->identify_duration_ = identify_duration; } void set_authorized_duration(uint32_t authorized_duration) { this->authorized_duration_ = authorized_duration; } + void set_wifi_timeout(uint32_t wifi_timeout) { this->wifi_timeout_ = wifi_timeout; } + uint32_t get_wifi_timeout() const { return this->wifi_timeout_; } + protected: bool should_start_{false}; bool setup_complete_{false}; @@ -60,6 +63,8 @@ class ESP32ImprovComponent : public Component, public BLEServiceComponent { uint32_t authorized_start_{0}; uint32_t authorized_duration_; + uint32_t wifi_timeout_{}; + std::vector incoming_data_; wifi::WiFiAP connecting_sta_; diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 2cb36fe8ea..b08f20de21 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -8,16 +8,16 @@ #include #endif -#include #include -#include "lwip/err.h" +#include #include "lwip/dns.h" +#include "lwip/err.h" +#include "esphome/core/application.h" +#include "esphome/core/hal.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" -#include "esphome/core/hal.h" #include "esphome/core/util.h" -#include "esphome/core/application.h" #ifdef USE_CAPTIVE_PORTAL #include "esphome/components/captive_portal/captive_portal.h" @@ -96,7 +96,7 @@ void WiFiComponent::start() { #endif } #ifdef USE_IMPROV - if (esp32_improv::global_improv_component != nullptr) { + if (!this->has_sta() && esp32_improv::global_improv_component != nullptr) { if (this->wifi_mode_(true, {})) esp32_improv::global_improv_component->start(); } @@ -163,8 +163,8 @@ void WiFiComponent::loop() { } #ifdef USE_IMPROV - if (esp32_improv::global_improv_component != nullptr) { - if (!this->is_connected()) { + if (esp32_improv::global_improv_component != nullptr && !esp32_improv::global_improv_component->is_active()) { + if (now - this->last_connected_ > esp32_improv::global_improv_component->get_wifi_timeout()) { if (this->wifi_mode_(true, {})) esp32_improv::global_improv_component->start(); } From fa4ba43eb95b22223863916b2b2f19713d00a35b Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 19 Oct 2023 12:25:43 +1300 Subject: [PATCH 0350/2101] Create IPv4 sockets if ipv6 is not enabled (#5565) --- esphome/components/socket/socket.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/socket/socket.cpp b/esphome/components/socket/socket.cpp index 824e04150b..d0fce9198f 100644 --- a/esphome/components/socket/socket.cpp +++ b/esphome/components/socket/socket.cpp @@ -10,7 +10,7 @@ namespace socket { Socket::~Socket() {} std::unique_ptr socket_ip(int type, int protocol) { -#if LWIP_IPV6 +#if ENABLE_IPV6 return socket(AF_INET6, type, protocol); #else return socket(AF_INET, type, protocol); @@ -18,7 +18,7 @@ std::unique_ptr socket_ip(int type, int protocol) { } socklen_t set_sockaddr(struct sockaddr *addr, socklen_t addrlen, const std::string &ip_address, uint16_t port) { -#if LWIP_IPV6 +#if ENABLE_IPV6 if (addrlen < sizeof(sockaddr_in6)) { errno = EINVAL; return 0; @@ -51,7 +51,7 @@ socklen_t set_sockaddr(struct sockaddr *addr, socklen_t addrlen, const std::stri } socklen_t set_sockaddr_any(struct sockaddr *addr, socklen_t addrlen, uint16_t port) { -#if LWIP_IPV6 +#if ENABLE_IPV6 if (addrlen < sizeof(sockaddr_in6)) { errno = EINVAL; return 0; From f077a5962d6f452bf0ba54cc93904e03784fbc0c Mon Sep 17 00:00:00 2001 From: Mike La Spina Date: Wed, 18 Oct 2023 19:00:15 -0500 Subject: [PATCH 0351/2101] Incorrect ESP32 Strapping PIN Defined (#5563) Co-authored-by: descipher <120155735+GelidusResearch@users.noreply.github.com> --- esphome/components/esp32/gpio_esp32.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/esp32/gpio_esp32.py b/esphome/components/esp32/gpio_esp32.py index 66ba2ffa62..91f006444c 100644 --- a/esphome/components/esp32/gpio_esp32.py +++ b/esphome/components/esp32/gpio_esp32.py @@ -18,7 +18,7 @@ _ESP_SDIO_PINS = { 11: "Flash Command", } -_ESP32_STRAPPING_PINS = {0, 2, 4, 12, 15} +_ESP32_STRAPPING_PINS = {0, 2, 5, 12, 15} _LOGGER = logging.getLogger(__name__) From db02c4ea21f034d902872f90b58e8e4eb3ab1f57 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 19 Oct 2023 13:30:13 +1300 Subject: [PATCH 0352/2101] Bump version to 2023.10.1 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 30e7fd7b8e..bb77fa578d 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2023.10.0" +__version__ = "2023.10.1" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From e99b8aaf96a965c02530694a4b7c1f25d7547b6f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Oct 2023 00:50:09 +0000 Subject: [PATCH 0353/2101] Bump black from 23.9.1 to 23.10.0 (#5561) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- .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 eba6834cb6..578e8982da 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,7 +3,7 @@ # See https://pre-commit.com/hooks.html for more hooks repos: - repo: https://github.com/psf/black-pre-commit-mirror - rev: 23.9.1 + rev: 23.10.0 hooks: - id: black args: diff --git a/requirements_test.txt b/requirements_test.txt index 5178c5c11f..ee3b5e89c8 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,6 +1,6 @@ pylint==2.17.6 flake8==6.1.0 # also change in .pre-commit-config.yaml when updating -black==23.9.1 # also change in .pre-commit-config.yaml when updating +black==23.10.0 # also change in .pre-commit-config.yaml when updating pyupgrade==3.13.0 # also change in .pre-commit-config.yaml when updating pre-commit From b9d72231b0f444889c53c4a44afcf5e4fa0c5a8d Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 19 Oct 2023 15:36:01 +1300 Subject: [PATCH 0354/2101] Fix XOR condition (#5567) --- 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 9b3377f694..50087f3efd 100644 --- a/esphome/core/base_automation.h +++ b/esphome/core/base_automation.h @@ -52,12 +52,12 @@ template class XorCondition : public Condition { public: explicit XorCondition(const std::vector *> &conditions) : conditions_(conditions) {} bool check(Ts... x) override { - bool xor_state = false; + size_t result = 0; for (auto *condition : this->conditions_) { - xor_state = xor_state ^ condition->check(x...); + result += condition->check(x...); } - return xor_state; + return result == 1; } protected: From b632ae49d4804a0527cd5162870de6ad2b43b450 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Thu, 19 Oct 2023 01:53:09 -0500 Subject: [PATCH 0355/2101] Improv Serial support via USB CDC and JTAG (#5559) --- esphome/components/improv_serial/__init__.py | 13 ++- .../improv_serial/improv_serial_component.cpp | 102 +++++++++++++---- .../improv_serial/improv_serial_component.h | 11 +- esphome/components/logger/logger.cpp | 107 +++++++++++++----- esphome/components/logger/logger.h | 10 ++ 5 files changed, 189 insertions(+), 54 deletions(-) diff --git a/esphome/components/improv_serial/__init__.py b/esphome/components/improv_serial/__init__.py index 311256804b..2b377d77b8 100644 --- a/esphome/components/improv_serial/__init__.py +++ b/esphome/components/improv_serial/__init__.py @@ -1,10 +1,14 @@ -from esphome.components.logger import USB_CDC, USB_SERIAL_JTAG +from esphome.components import improv_base +from esphome.components.esp32 import get_esp32_variant +from esphome.components.esp32.const import ( + VARIANT_ESP32S3, +) +from esphome.components.logger import USB_CDC from esphome.const import CONF_BAUD_RATE, CONF_HARDWARE_UART, CONF_ID, CONF_LOGGER import esphome.codegen as cg import esphome.config_validation as cv from esphome.core import CORE import esphome.final_validate as fv -from esphome.components import improv_base AUTO_LOAD = ["improv_base"] CODEOWNERS = ["@esphome/core"] @@ -30,7 +34,10 @@ def validate_logger(config): if logger_conf[CONF_BAUD_RATE] == 0: raise cv.Invalid("improv_serial requires the logger baud_rate to be not 0") if CORE.using_esp_idf: - if logger_conf[CONF_HARDWARE_UART] in [USB_SERIAL_JTAG, USB_CDC]: + if ( + logger_conf[CONF_HARDWARE_UART] == USB_CDC + and get_esp32_variant() == VARIANT_ESP32S3 + ): raise cv.Invalid( "improv_serial does not support the selected logger hardware_uart" ) diff --git a/esphome/components/improv_serial/improv_serial_component.cpp b/esphome/components/improv_serial/improv_serial_component.cpp index 1dd1c9cf6f..600069b781 100644 --- a/esphome/components/improv_serial/improv_serial_component.cpp +++ b/esphome/components/improv_serial/improv_serial_component.cpp @@ -31,26 +31,57 @@ void ImprovSerialComponent::setup() { void ImprovSerialComponent::dump_config() { ESP_LOGCONFIG(TAG, "Improv Serial:"); } -int ImprovSerialComponent::available_() { +optional ImprovSerialComponent::read_byte_() { + optional byte; + uint8_t data = 0; #ifdef USE_ARDUINO - return this->hw_serial_->available(); + if (this->hw_serial_->available()) { + this->hw_serial_->readBytes(&data, 1); + byte = data; + } #endif #ifdef USE_ESP_IDF - size_t available; - uart_get_buffered_data_len(this->uart_num_, &available); - return available; + switch (logger::global_logger->get_uart()) { + case logger::UART_SELECTION_UART0: + case logger::UART_SELECTION_UART1: +#if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32C6) && \ + !defined(USE_ESP32_VARIANT_ESP32S2) && !defined(USE_ESP32_VARIANT_ESP32S3) + case logger::UART_SELECTION_UART2: +#endif // !USE_ESP32_VARIANT_ESP32C3 && !USE_ESP32_VARIANT_ESP32S2 && !USE_ESP32_VARIANT_ESP32S3 + if (this->uart_num_ >= 0) { + size_t available; + uart_get_buffered_data_len(this->uart_num_, &available); + if (available) { + uart_read_bytes(this->uart_num_, &data, 1, 20 / portTICK_PERIOD_MS); + byte = data; + } + } + break; +#if defined(CONFIG_ESP_CONSOLE_USB_CDC) && (defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3)) + case logger::UART_SELECTION_USB_CDC: +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) + if (esp_usb_console_available_for_read()) { +#else + if (esp_usb_console_read_available()) { #endif -} - -uint8_t ImprovSerialComponent::read_byte_() { - uint8_t data; -#ifdef USE_ARDUINO - this->hw_serial_->readBytes(&data, 1); + esp_usb_console_read_buf((char *) &data, 1); + byte = data; + } + break; +#endif // USE_ESP32_VARIANT_ESP32S2 || USE_ESP32_VARIANT_ESP32S3 +#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S3) + case logger::UART_SELECTION_USB_SERIAL_JTAG: { + if (usb_serial_jtag_read_bytes((char *) &data, 1, 20 / portTICK_PERIOD_MS)) { + byte = data; + } + break; + } +#endif // USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C6 || USE_ESP32_VARIANT_ESP32S3 + default: + break; + } #endif -#ifdef USE_ESP_IDF - uart_read_bytes(this->uart_num_, &data, 1, 20 / portTICK_PERIOD_MS); -#endif - return data; + return byte; } void ImprovSerialComponent::write_data_(std::vector &data) { @@ -59,24 +90,49 @@ void ImprovSerialComponent::write_data_(std::vector &data) { this->hw_serial_->write(data.data(), data.size()); #endif #ifdef USE_ESP_IDF - uart_write_bytes(this->uart_num_, data.data(), data.size()); + switch (logger::global_logger->get_uart()) { + case logger::UART_SELECTION_UART0: + case logger::UART_SELECTION_UART1: +#if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32C6) && \ + !defined(USE_ESP32_VARIANT_ESP32S2) && !defined(USE_ESP32_VARIANT_ESP32S3) + case logger::UART_SELECTION_UART2: +#endif // !USE_ESP32_VARIANT_ESP32C3 && !USE_ESP32_VARIANT_ESP32S2 && !USE_ESP32_VARIANT_ESP32S3 + uart_write_bytes(this->uart_num_, data.data(), data.size()); + break; +#if defined(CONFIG_ESP_CONSOLE_USB_CDC) && (defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3)) + case logger::UART_SELECTION_USB_CDC: { + const char *msg = (char *) data.data(); + esp_usb_console_write_buf(msg, data.size()); + break; + } +#endif // USE_ESP32_VARIANT_ESP32S2 || USE_ESP32_VARIANT_ESP32S3 +#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S3) + case logger::UART_SELECTION_USB_SERIAL_JTAG: + usb_serial_jtag_write_bytes((char *) data.data(), data.size(), 20 / portTICK_PERIOD_MS); + break; +#endif // USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32S3 + default: + break; + } #endif } void ImprovSerialComponent::loop() { - const uint32_t now = millis(); - if (now - this->last_read_byte_ > 50) { + if (this->last_read_byte_ && (millis() - this->last_read_byte_ > IMPROV_SERIAL_TIMEOUT)) { + this->last_read_byte_ = 0; this->rx_buffer_.clear(); - this->last_read_byte_ = now; + ESP_LOGV(TAG, "Improv Serial timeout"); } - while (this->available_()) { - uint8_t byte = this->read_byte_(); - if (this->parse_improv_serial_byte_(byte)) { - this->last_read_byte_ = now; + auto byte = this->read_byte_(); + while (byte.has_value()) { + if (this->parse_improv_serial_byte_(byte.value())) { + this->last_read_byte_ = millis(); } else { + this->last_read_byte_ = 0; this->rx_buffer_.clear(); } + byte = this->read_byte_(); } if (this->state_ == improv::STATE_PROVISIONING) { diff --git a/esphome/components/improv_serial/improv_serial_component.h b/esphome/components/improv_serial/improv_serial_component.h index 731f9f9984..8583d0762b 100644 --- a/esphome/components/improv_serial/improv_serial_component.h +++ b/esphome/components/improv_serial/improv_serial_component.h @@ -14,6 +14,13 @@ #endif #ifdef USE_ESP_IDF #include +#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S3) || \ + defined(USE_ESP32_VARIANT_ESP32H2) +#include +#endif +#if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) +#include +#endif #endif namespace esphome { @@ -26,6 +33,7 @@ enum ImprovSerialType : uint8_t { TYPE_RPC_RESPONSE = 0x04 }; +static const uint16_t IMPROV_SERIAL_TIMEOUT = 100; static const uint8_t IMPROV_SERIAL_VERSION = 1; class ImprovSerialComponent : public Component, public improv_base::ImprovBase { @@ -48,8 +56,7 @@ class ImprovSerialComponent : public Component, public improv_base::ImprovBase { std::vector build_rpc_settings_response_(improv::Command command); std::vector build_version_info_(); - int available_(); - uint8_t read_byte_(); + optional read_byte_(); void write_data_(std::vector &data); #ifdef USE_ARDUINO diff --git a/esphome/components/logger/logger.cpp b/esphome/components/logger/logger.cpp index d1f3149d84..2d2524b5f4 100644 --- a/esphome/components/logger/logger.cpp +++ b/esphome/components/logger/logger.cpp @@ -3,8 +3,21 @@ #ifdef USE_ESP_IDF #include + +#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S3) || \ + defined(USE_ESP32_VARIANT_ESP32H2) +#include +#include +#include +#endif + #include "freertos/FreeRTOS.h" #include "esp_idf_version.h" + +#include +#include +#include + #endif // USE_ESP_IDF #if defined(USE_ESP32_FRAMEWORK_ARDUINO) || defined(USE_ESP_IDF) @@ -93,6 +106,58 @@ void Logger::log_vprintf_(int level, const char *tag, int line, const __FlashStr } #endif +#ifdef USE_ESP_IDF +void Logger::init_uart_() { + uart_config_t uart_config{}; + uart_config.baud_rate = (int) baud_rate_; + uart_config.data_bits = UART_DATA_8_BITS; + uart_config.parity = UART_PARITY_DISABLE; + uart_config.stop_bits = UART_STOP_BITS_1; + uart_config.flow_ctrl = UART_HW_FLOWCTRL_DISABLE; +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) + uart_config.source_clk = UART_SCLK_DEFAULT; +#endif + uart_param_config(this->uart_num_, &uart_config); + const int uart_buffer_size = tx_buffer_size_; + // Install UART driver using an event queue here + uart_driver_install(this->uart_num_, uart_buffer_size, uart_buffer_size, 10, nullptr, 0); +} + +#if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) +void Logger::init_usb_cdc_() {} +#endif + +#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S3) || \ + defined(USE_ESP32_VARIANT_ESP32H2) +void Logger::init_usb_serial_jtag_() { + setvbuf(stdin, NULL, _IONBF, 0); // Disable buffering on stdin + + // Minicom, screen, idf_monitor send CR when ENTER key is pressed + esp_vfs_dev_usb_serial_jtag_set_rx_line_endings(ESP_LINE_ENDINGS_CR); + // Move the caret to the beginning of the next line on '\n' + esp_vfs_dev_usb_serial_jtag_set_tx_line_endings(ESP_LINE_ENDINGS_CRLF); + + // Enable non-blocking mode on stdin and stdout + fcntl(fileno(stdout), F_SETFL, 0); + fcntl(fileno(stdin), F_SETFL, 0); + + usb_serial_jtag_driver_config_t usb_serial_jtag_config{}; + usb_serial_jtag_config.rx_buffer_size = 512; + usb_serial_jtag_config.tx_buffer_size = 512; + + esp_err_t ret = ESP_OK; + // Install USB-SERIAL-JTAG driver for interrupt-driven reads and writes + ret = usb_serial_jtag_driver_install(&usb_serial_jtag_config); + if (ret != ESP_OK) { + return; + } + + // Tell vfs to use usb-serial-jtag driver + esp_vfs_usb_serial_jtag_use_driver(); +} +#endif +#endif + int HOT Logger::level_for(const char *tag) { // Uses std::vector<> for low memory footprint, though the vector // could be sorted to minimize lookup times. This feature isn't used that @@ -120,19 +185,19 @@ void HOT Logger::log_message_(int level, const char *tag, int offset) { #ifdef USE_ESP_IDF if ( #if defined(USE_ESP32_VARIANT_ESP32S2) - uart_ == UART_SELECTION_USB_CDC + this->uart_ == UART_SELECTION_USB_CDC #elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32H2) - uart_ == UART_SELECTION_USB_SERIAL_JTAG + this->uart_ == UART_SELECTION_USB_SERIAL_JTAG #elif defined(USE_ESP32_VARIANT_ESP32S3) - uart_ == UART_SELECTION_USB_CDC || uart_ == UART_SELECTION_USB_SERIAL_JTAG + this->uart_ == UART_SELECTION_USB_CDC || this->uart_ == UART_SELECTION_USB_SERIAL_JTAG #else /* DISABLES CODE */ (false) // NOLINT #endif ) { puts(msg); } else { - uart_write_bytes(uart_num_, msg, strlen(msg)); - uart_write_bytes(uart_num_, "\n", 1); + uart_write_bytes(this->uart_num_, msg, strlen(msg)); + uart_write_bytes(this->uart_num_, "\n", 1); } #endif } @@ -209,48 +274,38 @@ void Logger::pre_setup() { } #endif // USE_ARDUINO #ifdef USE_ESP_IDF - uart_num_ = UART_NUM_0; - switch (uart_) { + this->uart_num_ = UART_NUM_0; + switch (this->uart_) { case UART_SELECTION_UART0: - uart_num_ = UART_NUM_0; + this->uart_num_ = UART_NUM_0; break; case UART_SELECTION_UART1: - uart_num_ = UART_NUM_1; + this->uart_num_ = UART_NUM_1; break; #if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32C6) && \ !defined(USE_ESP32_VARIANT_ESP32S2) && !defined(USE_ESP32_VARIANT_ESP32S3) && !defined(USE_ESP32_VARIANT_ESP32H2) case UART_SELECTION_UART2: - uart_num_ = UART_NUM_2; + this->uart_num_ = UART_NUM_2; break; #endif // !USE_ESP32_VARIANT_ESP32C3 && !USE_ESP32_VARIANT_ESP32S2 && !USE_ESP32_VARIANT_ESP32S3 && // !USE_ESP32_VARIANT_ESP32H2 #if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) case UART_SELECTION_USB_CDC: - uart_num_ = -1; + this->uart_num_ = -1; + this->init_usb_cdc_(); break; #endif // USE_ESP32_VARIANT_ESP32S2 || USE_ESP32_VARIANT_ESP32S3 #if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S3) || \ defined(USE_ESP32_VARIANT_ESP32H2) case UART_SELECTION_USB_SERIAL_JTAG: - uart_num_ = -1; + this->uart_num_ = -1; + this->init_usb_serial_jtag_(); break; #endif // USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C6 || USE_ESP32_VARIANT_ESP32S3 || // USE_ESP32_VARIANT_ESP32H2 } - if (uart_num_ >= 0) { - uart_config_t uart_config{}; - uart_config.baud_rate = (int) baud_rate_; - uart_config.data_bits = UART_DATA_8_BITS; - uart_config.parity = UART_PARITY_DISABLE; - uart_config.stop_bits = UART_STOP_BITS_1; - uart_config.flow_ctrl = UART_HW_FLOWCTRL_DISABLE; -#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) - uart_config.source_clk = UART_SCLK_DEFAULT; -#endif - 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); + if (this->uart_num_ >= 0) { + this->init_uart_(); } #endif // USE_ESP_IDF } diff --git a/esphome/components/logger/logger.h b/esphome/components/logger/logger.h index de272934bf..3816b1dd14 100644 --- a/esphome/components/logger/logger.h +++ b/esphome/components/logger/logger.h @@ -107,6 +107,16 @@ class Logger : public Component { #endif protected: +#ifdef USE_ESP_IDF + void init_uart_(); +#if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) + void init_usb_cdc_(); +#endif +#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S3) || \ + defined(USE_ESP32_VARIANT_ESP32H2) + void init_usb_serial_jtag_(); +#endif +#endif void write_header_(int level, const char *tag, int line); void write_footer_(); void log_message_(int level, const char *tag, int offset = 0); From 9f033bce3b0c2c985c4328295c5e1d111168d157 Mon Sep 17 00:00:00 2001 From: "Jordan W. Cobb" Date: Thu, 19 Oct 2023 03:02:27 -0400 Subject: [PATCH 0356/2101] Fan no off cycle action (#5564) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/fan/__init__.py | 17 +++++++++++++++-- esphome/components/fan/automation.h | 12 ++++++++++-- esphome/const.py | 1 + tests/test1.yaml | 13 ++++++++++++- 4 files changed, 38 insertions(+), 5 deletions(-) diff --git a/esphome/components/fan/__init__.py b/esphome/components/fan/__init__.py index 9a05bff3a0..23df3c2214 100644 --- a/esphome/components/fan/__init__.py +++ b/esphome/components/fan/__init__.py @@ -14,6 +14,7 @@ from esphome.const import ( CONF_SPEED_LEVEL_STATE_TOPIC, CONF_SPEED_COMMAND_TOPIC, CONF_SPEED_STATE_TOPIC, + CONF_OFF_SPEED_CYCLE, CONF_ON_SPEED_SET, CONF_ON_TURN_OFF, CONF_ON_TURN_ON, @@ -217,10 +218,22 @@ async def fan_turn_on_to_code(config, action_id, template_arg, args): return var -@automation.register_action("fan.cycle_speed", CycleSpeedAction, FAN_ACTION_SCHEMA) +@automation.register_action( + "fan.cycle_speed", + CycleSpeedAction, + maybe_simple_id( + { + cv.Required(CONF_ID): cv.use_id(Fan), + cv.Optional(CONF_OFF_SPEED_CYCLE, default=True): cv.boolean, + } + ), +) async def fan_cycle_speed_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, paren) + template_ = await cg.templatable(config[CONF_OFF_SPEED_CYCLE], args, bool) + cg.add(var.set_no_off_cycle(template_)) + return var @automation.register_condition( diff --git a/esphome/components/fan/automation.h b/esphome/components/fan/automation.h index 23fb70a95b..511acf5682 100644 --- a/esphome/components/fan/automation.h +++ b/esphome/components/fan/automation.h @@ -54,18 +54,26 @@ template class CycleSpeedAction : public Action { public: explicit CycleSpeedAction(Fan *state) : state_(state) {} + TEMPLATABLE_VALUE(bool, no_off_cycle) + void play(Ts... x) override { // check to see if fan supports speeds and is on if (this->state_->get_traits().supported_speed_count()) { if (this->state_->state) { int speed = this->state_->speed + 1; int supported_speed_count = this->state_->get_traits().supported_speed_count(); - if (speed > supported_speed_count) { - // was running at max speed, so turn off + bool off_speed_cycle = no_off_cycle_.value(x...); + if (speed > supported_speed_count && off_speed_cycle) { + // was running at max speed, off speed cycle enabled, so turn off speed = 1; auto call = this->state_->turn_off(); call.set_speed(speed); call.perform(); + } else if (speed > supported_speed_count && !off_speed_cycle) { + // was running at max speed, off speed cycle disabled, so set to lowest speed + auto call = this->state_->turn_on(); + call.set_speed(1); + call.perform(); } else { auto call = this->state_->turn_on(); call.set_speed(speed); diff --git a/esphome/const.py b/esphome/const.py index be561c2880..a06c75ae44 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -475,6 +475,7 @@ CONF_NUM_SCANS = "num_scans" CONF_NUMBER = "number" CONF_NUMBER_DATAPOINT = "number_datapoint" CONF_OFF_MODE = "off_mode" +CONF_OFF_SPEED_CYCLE = "off_speed_cycle" CONF_OFFSET = "offset" CONF_ON = "on" CONF_ON_BLE_ADVERTISE = "on_ble_advertise" diff --git a/tests/test1.yaml b/tests/test1.yaml index 9bf9a32e17..acd119d8a5 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -1693,7 +1693,18 @@ binary_sensor: number: 7 mode: INPUT inverted: false - + - platform: gpio + name: Speed Fan Cycle binary sensor" + pin: + number: 18 + mode: + input: true + pulldown: true + on_press: + - fan.cycle_speed: + id: fan_speed + off_speed_cycle: False + - logger.log: "Cycle speed clicked" - platform: remote_receiver name: Raw Remote Receiver Test raw: From d82471942f91a85fe5e4812edfd954f47af74c2b Mon Sep 17 00:00:00 2001 From: Trent Houliston Date: Fri, 20 Oct 2023 08:28:05 +1100 Subject: [PATCH 0357/2101] Publish the `pulse_meter` total when setting the total (#5475) --- CODEOWNERS | 2 +- esphome/components/pulse_meter/pulse_meter_sensor.cpp | 7 +++++++ esphome/components/pulse_meter/pulse_meter_sensor.h | 3 ++- esphome/components/pulse_meter/sensor.py | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index b66da4fc26..0c371d6ee6 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -225,7 +225,7 @@ esphome/components/pn532_spi/* @OttoWinter @jesserockz esphome/components/power_supply/* @esphome/core esphome/components/preferences/* @esphome/core esphome/components/psram/* @esphome/core -esphome/components/pulse_meter/* @cstaahl @stevebaxter +esphome/components/pulse_meter/* @TrentHouliston @cstaahl @stevebaxter esphome/components/pvvx_mithermometer/* @pasiz esphome/components/qmp6988/* @andrewpc esphome/components/qr_code/* @wjtje diff --git a/esphome/components/pulse_meter/pulse_meter_sensor.cpp b/esphome/components/pulse_meter/pulse_meter_sensor.cpp index 6c4ebe002e..14f8e508b5 100644 --- a/esphome/components/pulse_meter/pulse_meter_sensor.cpp +++ b/esphome/components/pulse_meter/pulse_meter_sensor.cpp @@ -7,6 +7,13 @@ namespace pulse_meter { static const char *const TAG = "pulse_meter"; +void PulseMeterSensor::set_total_pulses(uint32_t pulses) { + this->total_pulses_ = pulses; + if (this->total_sensor_ != nullptr) { + this->total_sensor_->publish_state(this->total_pulses_); + } +} + void PulseMeterSensor::setup() { this->pin_->setup(); this->isr_pin_ = pin_->to_isr(); diff --git a/esphome/components/pulse_meter/pulse_meter_sensor.h b/esphome/components/pulse_meter/pulse_meter_sensor.h index fc8d47538f..1cd02e3ca2 100644 --- a/esphome/components/pulse_meter/pulse_meter_sensor.h +++ b/esphome/components/pulse_meter/pulse_meter_sensor.h @@ -22,7 +22,8 @@ class PulseMeterSensor : public sensor::Sensor, public Component { void set_timeout_us(uint32_t timeout) { this->timeout_us_ = timeout; } void set_total_sensor(sensor::Sensor *sensor) { this->total_sensor_ = sensor; } void set_filter_mode(InternalFilterMode mode) { this->filter_mode_ = mode; } - void set_total_pulses(uint32_t pulses) { this->total_pulses_ = pulses; } + + void set_total_pulses(uint32_t pulses); void setup() override; void loop() override; diff --git a/esphome/components/pulse_meter/sensor.py b/esphome/components/pulse_meter/sensor.py index 26bc6b189b..59ffa58c21 100644 --- a/esphome/components/pulse_meter/sensor.py +++ b/esphome/components/pulse_meter/sensor.py @@ -19,7 +19,7 @@ from esphome.const import ( ) from esphome.core import CORE -CODEOWNERS = ["@stevebaxter", "@cstaahl"] +CODEOWNERS = ["@stevebaxter", "@cstaahl", "@TrentHouliston"] pulse_meter_ns = cg.esphome_ns.namespace("pulse_meter") From 76417103c7559cba9cfc7d965133fe0488548193 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Oct 2023 16:48:56 -1000 Subject: [PATCH 0358/2101] Bump aioesphomeapi from 18.0.6 to 18.0.7 (#5573) 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 4be7279f33..bfab8e0faf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,7 +10,7 @@ platformio==6.1.11 # When updating platformio, also update Dockerfile esptool==4.6.2 click==8.1.7 esphome-dashboard==20230904.0 -aioesphomeapi==18.0.6 +aioesphomeapi==18.0.7 zeroconf==0.119.0 # esp-idf requires this, but doesn't bundle it by default From 05a95f8ee9f390deab5fca5e4c136fb820b25c6a Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Sat, 21 Oct 2023 06:04:07 +0200 Subject: [PATCH 0359/2101] Remove explicit cast for IPAddress (#5574) * Remove explicit cast for IPAddress * Make linter happy --- esphome/components/mqtt/mqtt_backend_libretiny.h | 4 +--- tests/test9.yaml | 6 ++++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/esphome/components/mqtt/mqtt_backend_libretiny.h b/esphome/components/mqtt/mqtt_backend_libretiny.h index 5373a1926a..ac4d4298fc 100644 --- a/esphome/components/mqtt/mqtt_backend_libretiny.h +++ b/esphome/components/mqtt/mqtt_backend_libretiny.h @@ -19,9 +19,7 @@ class MQTTBackendLibreTiny final : public MQTTBackend { void set_will(const char *topic, uint8_t qos, bool retain, const char *payload) final { mqtt_client_.setWill(topic, qos, retain, payload); } - void set_server(network::IPAddress ip, uint16_t port) final { - mqtt_client_.setServer(IPAddress(static_cast(ip)), port); - } + 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); } diff --git a/tests/test9.yaml b/tests/test9.yaml index ccf5f4b5b0..d660b4f24a 100644 --- a/tests/test9.yaml +++ b/tests/test9.yaml @@ -26,3 +26,9 @@ sensor: name: ADC pin: GPIO23 update_interval: 1s + +mqtt: + broker: test.mosquitto.org + port: 1883 + discovery: true + discovery_prefix: homeassistant From 3d7d0d4f73bc17a86ad25e1cdb725d4d4c1bde55 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Sat, 21 Oct 2023 21:38:22 +0200 Subject: [PATCH 0360/2101] Remove unnecessary checks in Nextion component (#5578) --- esphome/components/nextion/nextion_commands.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/esphome/components/nextion/nextion_commands.cpp b/esphome/components/nextion/nextion_commands.cpp index 0409e5ea6c..806e03850f 100644 --- a/esphome/components/nextion/nextion_commands.cpp +++ b/esphome/components/nextion/nextion_commands.cpp @@ -10,15 +10,11 @@ static const char *const TAG = "nextion"; void Nextion::soft_reset() { this->send_command_("rest"); } void Nextion::set_wake_up_page(uint8_t page_id) { - if (page_id > 255) { - ESP_LOGD(TAG, "Wake up page of bounds, range 0-255"); - return; - } this->add_no_result_to_queue_with_set_internal_("wake_up_page", "wup", page_id, true); } void Nextion::set_touch_sleep_timeout(uint16_t timeout) { - if (timeout < 3 || timeout > 65535) { + if (timeout < 3) { ESP_LOGD(TAG, "Sleep timeout out of bounds, range 3-65535"); return; } From e3fbf54a1aafad77ab3125855f21607ed35be74d Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Mon, 23 Oct 2023 08:41:16 +0200 Subject: [PATCH 0361/2101] Set addr type when copy from ip4_addr_t (#5583) --- esphome/components/network/ip_address.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/esphome/components/network/ip_address.h b/esphome/components/network/ip_address.h index 7a4d394805..03ba6e85d5 100644 --- a/esphome/components/network/ip_address.h +++ b/esphome/components/network/ip_address.h @@ -34,7 +34,12 @@ struct IPAddress { } IPAddress(const ip_addr_t *other_ip) { ip_addr_copy(ip_addr_, *other_ip); } IPAddress(const std::string &in_address) { ipaddr_aton(in_address.c_str(), &ip_addr_); } - IPAddress(ip4_addr_t *other_ip) { memcpy((void *) &ip_addr_, (void *) other_ip, sizeof(ip4_addr_t)); } + IPAddress(ip4_addr_t *other_ip) { + memcpy((void *) &ip_addr_, (void *) other_ip, sizeof(ip4_addr_t)); +#if USE_ESP32 + ip_addr_.type = IPADDR_TYPE_V4; +#endif + } #if USE_ARDUINO IPAddress(const arduino_ns::IPAddress &other_ip) { ip_addr_set_ip4_u32(&ip_addr_, other_ip); } #endif From 84c00a58675a63f7ef587119494d49fb81dbe671 Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Mon, 23 Oct 2023 11:26:23 -0700 Subject: [PATCH 0362/2101] fix canbus send config (#5585) Co-authored-by: Samuel Sieb --- esphome/components/canbus/__init__.py | 25 +++++++++++-------------- tests/test1.1.yaml | 16 ++++++++++++++++ tests/test1.yaml | 4 ++++ 3 files changed, 31 insertions(+), 14 deletions(-) diff --git a/esphome/components/canbus/__init__.py b/esphome/components/canbus/__init__.py index f49398858c..76e77021ad 100644 --- a/esphome/components/canbus/__init__.py +++ b/esphome/components/canbus/__init__.py @@ -17,11 +17,12 @@ CONF_ON_FRAME = "on_frame" def validate_id(config): - can_id = config[CONF_CAN_ID] - id_ext = config[CONF_USE_EXTENDED_ID] - if not id_ext: - if can_id > 0x7FF: - raise cv.Invalid("Standard IDs must be 11 Bit (0x000-0x7ff / 0-2047)") + if CONF_CAN_ID in config: + can_id = config[CONF_CAN_ID] + id_ext = config[CONF_USE_EXTENDED_ID] + if not id_ext: + if can_id > 0x7FF: + raise cv.Invalid("Standard IDs must be 11 Bit (0x000-0x7ff / 0-2047)") return config @@ -151,22 +152,18 @@ async def canbus_action_to_code(config, action_id, template_arg, args): if can_id := config.get(CONF_CAN_ID): can_id = await cg.templatable(can_id, args, cg.uint32) cg.add(var.set_can_id(can_id)) - use_extended_id = await cg.templatable( - config[CONF_USE_EXTENDED_ID], args, cg.uint32 - ) - cg.add(var.set_use_extended_id(use_extended_id)) + cg.add(var.set_use_extended_id(config[CONF_USE_EXTENDED_ID])) - remote_transmission_request = await cg.templatable( - config[CONF_REMOTE_TRANSMISSION_REQUEST], args, bool + cg.add( + var.set_remote_transmission_request(config[CONF_REMOTE_TRANSMISSION_REQUEST]) ) - cg.add(var.set_remote_transmission_request(remote_transmission_request)) data = config[CONF_DATA] - if isinstance(data, bytes): - data = [int(x) for x in 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: + if isinstance(data, bytes): + data = [int(x) for x in data] cg.add(var.set_data_static(data)) return var diff --git a/tests/test1.1.yaml b/tests/test1.1.yaml index 3bad4e0492..f4ad89897b 100644 --- a/tests/test1.1.yaml +++ b/tests/test1.1.yaml @@ -203,3 +203,19 @@ light: from: 20 to: 25 - single_light_id: ${roomname}_lights + +canbus: + - platform: esp32_can + id: esp32_internal_can + rx_pin: GPIO04 + tx_pin: GPIO05 + can_id: 4 + bit_rate: 50kbps + +button: + - platform: template + name: Canbus Actions + on_press: + - canbus.send: "abc" + - canbus.send: [0, 1, 2] + - canbus.send: !lambda return {0, 1, 2}; diff --git a/tests/test1.yaml b/tests/test1.yaml index acd119d8a5..f40dc35934 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -3214,6 +3214,10 @@ text_sensor: canbus_id: mcp2515_can can_id: 23 data: [0x10, 0x20, 0x30] + - canbus.send: + canbus_id: mcp2515_can + can_id: 23 + data: !lambda return {0x10, 0x20, 0x30}; - canbus.send: canbus_id: esp32_internal_can can_id: 23 From b898f75631d9d2ec4cc2fa7a46c5ebc6a9601b69 Mon Sep 17 00:00:00 2001 From: dentra Date: Mon, 23 Oct 2023 21:29:32 +0300 Subject: [PATCH 0363/2101] Allow set climate preset to NONE (#5588) --- esphome/components/climate/climate.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/components/climate/climate.cpp b/esphome/components/climate/climate.cpp index 1680601279..ea24cab954 100644 --- a/esphome/components/climate/climate.cpp +++ b/esphome/components/climate/climate.cpp @@ -213,6 +213,8 @@ ClimateCall &ClimateCall::set_preset(const std::string &preset) { this->set_preset(CLIMATE_PRESET_SLEEP); } else if (str_equals_case_insensitive(preset, "ACTIVITY")) { this->set_preset(CLIMATE_PRESET_ACTIVITY); + } else if (str_equals_case_insensitive(preset, "NONE")) { + this->set_preset(CLIMATE_PRESET_NONE); } else { if (this->parent_->get_traits().supports_custom_preset(preset)) { this->custom_preset_ = preset; From eead33b6f2df61d77258aaac4a168b9a652081ee Mon Sep 17 00:00:00 2001 From: Guillermo Ruffino Date: Mon, 23 Oct 2023 16:02:29 -0300 Subject: [PATCH 0364/2101] update storage version from mdns (#5584) --- esphome/zeroconf.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/esphome/zeroconf.py b/esphome/zeroconf.py index 924d7253df..14dd740a96 100644 --- a/esphome/zeroconf.py +++ b/esphome/zeroconf.py @@ -17,6 +17,8 @@ from zeroconf import ( current_time_millis, ) +from esphome.storage_json import StorageJSON, ext_storage_path + _CLASS_IN = 1 _FLAGS_QR_QUERY = 0x0000 # query _TYPE_A = 1 @@ -131,6 +133,7 @@ TXT_RECORD_PROJECT_NAME = b"project_name" TXT_RECORD_PROJECT_VERSION = b"project_version" TXT_RECORD_NETWORK = b"network" TXT_RECORD_FRIENDLY_NAME = b"friendly_name" +TXT_RECORD_VERSION = b"version" @dataclass @@ -186,6 +189,10 @@ class DashboardImportDiscovery: ] if any(key not in info.properties for key in required_keys): # Not a dashboard import device + version = info.properties.get(TXT_RECORD_VERSION) + if version is not None: + version = version.decode() + self.update_device_mdns(node_name, version) return import_url = info.properties[TXT_RECORD_PACKAGE_IMPORT_URL].decode() @@ -208,6 +215,22 @@ class DashboardImportDiscovery: def cancel(self) -> None: self.service_browser.cancel() + def update_device_mdns(self, node_name: str, version: str): + storage_path = ext_storage_path(node_name + ".yaml") + storage_json = StorageJSON.load(storage_path) + + if storage_json is not None: + storage_version = storage_json.esphome_version + if version != storage_version: + storage_json.esphome_version = version + storage_json.save(storage_path) + _LOGGER.info( + "Updated %s with mdns version %s (was %s)", + node_name, + version, + storage_version, + ) + class EsphomeZeroconf(Zeroconf): def resolve_host(self, host: str, timeout=3.0): From 7e27e98bff376a237b8911e87d0d44d5cd6648be Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Mon, 23 Oct 2023 21:02:57 +0200 Subject: [PATCH 0365/2101] set Nextion protocol reparse mode (#5484) --- esphome/components/nextion/nextion.h | 7 +++++++ .../components/nextion/nextion_commands.cpp | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/esphome/components/nextion/nextion.h b/esphome/components/nextion/nextion.h index 28663138d7..7518d7f4cb 100644 --- a/esphome/components/nextion/nextion.h +++ b/esphome/components/nextion/nextion.h @@ -623,6 +623,13 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * @param True or false. Sleep=true to enter sleep mode or sleep=false to exit sleep mode. */ void sleep(bool sleep); + /** + * Sets Nextion Protocol Reparse mode between active or passive + * @param True or false. + * active_mode=true to enter active protocol reparse mode + * active_mode=false to enter passive protocol reparse mode. + */ + void set_protocol_reparse_mode(bool active_mode); // ========== INTERNAL METHODS ========== // (In most use cases you won't need these) diff --git a/esphome/components/nextion/nextion_commands.cpp b/esphome/components/nextion/nextion_commands.cpp index 806e03850f..c4caf29287 100644 --- a/esphome/components/nextion/nextion_commands.cpp +++ b/esphome/components/nextion/nextion_commands.cpp @@ -32,6 +32,25 @@ void Nextion::sleep(bool sleep) { } // End sleep safe commands +// Protocol reparse mode +void Nextion::set_protocol_reparse_mode(bool active_mode) { + const uint8_t to_send[3] = {0xFF, 0xFF, 0xFF}; + if (active_mode) { // Sets active protocol reparse mode + this->write_str( + "recmod=1"); // send_command_ cannot be used as Nextion might not be setup if incorrect reparse mode + this->write_array(to_send, sizeof(to_send)); + } else { // Sets passive protocol reparse mode + this->write_str("DRAKJHSUYDGBNCJHGJKSHBDN"); // To exit active reparse mode this sequence must be sent + this->write_array(to_send, sizeof(to_send)); + this->write_str("recmod=0"); // Sending recmode=0 twice is recommended + this->write_array(to_send, sizeof(to_send)); + this->write_str("recmod=0"); + this->write_array(to_send, sizeof(to_send)); + } + this->write_str("connect"); + this->write_array(to_send, sizeof(to_send)); +} + // Set Colors void Nextion::set_component_background_color(const char *component, uint32_t color) { this->add_no_result_to_queue_with_printf_("set_component_background_color", "%s.bco=%d", component, color); From e7d51f9c16a08d1d814e4f5fe52c9ba93dc53521 Mon Sep 17 00:00:00 2001 From: Simone Rossetto Date: Mon, 23 Oct 2023 21:05:57 +0200 Subject: [PATCH 0366/2101] Add address text sensor to WireGuard (#5576) --- esphome/components/wireguard/text_sensor.py | 28 +++++++++++++++++++++ esphome/components/wireguard/wireguard.cpp | 10 ++++++++ esphome/components/wireguard/wireguard.h | 12 +++++++++ tests/test10.yaml | 5 ++++ 4 files changed, 55 insertions(+) create mode 100644 esphome/components/wireguard/text_sensor.py diff --git a/esphome/components/wireguard/text_sensor.py b/esphome/components/wireguard/text_sensor.py new file mode 100644 index 0000000000..3b05f6173e --- /dev/null +++ b/esphome/components/wireguard/text_sensor.py @@ -0,0 +1,28 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import text_sensor +from esphome.const import ( + CONF_ADDRESS, + ENTITY_CATEGORY_DIAGNOSTIC, +) + +from . import Wireguard + +CONF_WIREGUARD_ID = "wireguard_id" + +DEPENDENCIES = ["wireguard"] + +CONFIG_SCHEMA = { + cv.GenerateID(CONF_WIREGUARD_ID): cv.use_id(Wireguard), + cv.Optional(CONF_ADDRESS): text_sensor.text_sensor_schema( + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + ), +} + + +async def to_code(config): + parent = await cg.get_variable(config[CONF_WIREGUARD_ID]) + + if address_config := config.get(CONF_ADDRESS): + sens = await text_sensor.new_text_sensor(address_config) + cg.add(parent.set_address_sensor(sens)) diff --git a/esphome/components/wireguard/wireguard.cpp b/esphome/components/wireguard/wireguard.cpp index 1b361cc1cc..3cd4409dda 100644 --- a/esphome/components/wireguard/wireguard.cpp +++ b/esphome/components/wireguard/wireguard.cpp @@ -54,6 +54,12 @@ void Wireguard::setup() { 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 + +#ifdef USE_TEXT_SENSOR + if (this->address_sensor_ != nullptr) { + this->address_sensor_->publish_state(this->address_); + } +#endif } else { ESP_LOGE(TAG, "cannot initialize WireGuard, error code %d", this->wg_initialized_); this->mark_failed(); @@ -186,6 +192,10 @@ void Wireguard::set_status_sensor(binary_sensor::BinarySensor *sensor) { this->s void Wireguard::set_handshake_sensor(sensor::Sensor *sensor) { this->handshake_sensor_ = sensor; } #endif +#ifdef USE_TEXT_SENSOR +void Wireguard::set_address_sensor(text_sensor::TextSensor *sensor) { this->address_sensor_ = sensor; } +#endif + void Wireguard::disable_auto_proceed() { this->proceed_allowed_ = false; } void Wireguard::start_connection_() { diff --git a/esphome/components/wireguard/wireguard.h b/esphome/components/wireguard/wireguard.h index cfc5fa1a27..c47d9e6603 100644 --- a/esphome/components/wireguard/wireguard.h +++ b/esphome/components/wireguard/wireguard.h @@ -17,6 +17,10 @@ #include "esphome/components/sensor/sensor.h" #endif +#ifdef USE_TEXT_SENSOR +#include "esphome/components/text_sensor/text_sensor.h" +#endif + #include namespace esphome { @@ -55,6 +59,10 @@ class Wireguard : public PollingComponent { void set_handshake_sensor(sensor::Sensor *sensor); #endif +#ifdef USE_TEXT_SENSOR + void set_address_sensor(text_sensor::TextSensor *sensor); +#endif + /// Block the setup step until peer is connected. void disable_auto_proceed(); @@ -85,6 +93,10 @@ class Wireguard : public PollingComponent { sensor::Sensor *handshake_sensor_ = nullptr; #endif +#ifdef USE_TEXT_SENSOR + text_sensor::TextSensor *address_sensor_ = nullptr; +#endif + /// Set to false to block the setup step until peer is connected. bool proceed_allowed_ = true; diff --git a/tests/test10.yaml b/tests/test10.yaml index fc74d95d84..dda7601048 100644 --- a/tests/test10.yaml +++ b/tests/test10.yaml @@ -49,3 +49,8 @@ sensor: - platform: wireguard latest_handshake: name: 'WireGuard Latest Handshake' + +text_sensor: + - platform: wireguard + address: + name: 'WireGuard Address' From 5347c9aafeb7c15f2f0a0dd664345563e5cdd902 Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Mon, 23 Oct 2023 21:06:23 +0200 Subject: [PATCH 0367/2101] Add LibreTiny hardwares to PR Template (#5575) --- .github/PULL_REQUEST_TEMPLATE.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 3221b8ac5c..3bf9c4e1f6 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -19,6 +19,8 @@ - [ ] ESP32 IDF - [ ] ESP8266 - [ ] RP2040 +- [ ] BK72xx +- [ ] RTL87xx ## Example entry for `config.yaml`: horizontal default position + break; + } + + ESP_LOGD(TAG, "default_horizontal_direction_: %02X", this->default_horizontal_direction_); + + // Fan Speed & Vertical Vane + // Map of Climate fan mode to this device expected value + // For 3Level: Low = 1, Medium = 2, High = 3 + // For 4Level: Low = 1, Middle = 2, Medium = 3, High = 4 + // 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()) { + case climate::CLIMATE_FAN_LOW: + remote_state[9] = 1; + break; + case climate::CLIMATE_FAN_MEDIUM: + if (this->fan_mode_ == MITSUBISHI_FAN_3L) { + remote_state[9] = 2; + } else { + remote_state[9] = 3; + } + break; + case climate::CLIMATE_FAN_HIGH: + if (this->fan_mode_ == MITSUBISHI_FAN_3L) { + remote_state[9] = 3; + } else { + remote_state[9] = 4; + } + break; + case climate::CLIMATE_FAN_MIDDLE: + remote_state[9] = 2; + break; + case climate::CLIMATE_FAN_QUIET: + remote_state[9] = 5; + break; + default: + remote_state[9] = MITSUBISHI_FAN_AUTO; + break; + } + + ESP_LOGD(TAG, "fan: %02x state: %02x", this->fan_mode.value(), remote_state[9]); + + // Vertical Vane + switch (this->swing_mode) { + case climate::CLIMATE_SWING_VERTICAL: + case climate::CLIMATE_SWING_BOTH: + remote_state[9] = remote_state[9] | MITSUBISHI_VERTICAL_VANE_SWING | MITSUBISHI_OTHERWISE; // Vane Swing + break; + case climate::CLIMATE_SWING_OFF: + default: + remote_state[9] = remote_state[9] | this->default_vertical_direction_ | + MITSUBISHI_OTHERWISE; // Off--> vertical default position + break; + } + + ESP_LOGD(TAG, "default_vertical_direction_: %02X", this->default_vertical_direction_); + + // Special modes + switch (this->preset.value()) { + case climate::CLIMATE_PRESET_ECO: + remote_state[6] = MITSUBISHI_MODE_COOL | MITSUBISHI_OTHERWISE; + remote_state[8] = (remote_state[8] & ~7) | MITSUBISHI_MODE_A_COOL; + remote_state[14] = MITSUBISHI_ECONOCOOL; + break; + case climate::CLIMATE_PRESET_SLEEP: + remote_state[9] = MITSUBISHI_FAN_AUTO; + remote_state[14] = MITSUBISHI_NIGHTMODE; + break; + case climate::CLIMATE_PRESET_BOOST: + remote_state[6] |= MITSUBISHI_OTHERWISE; + remote_state[15] = MITSUBISHI_POWERFUL; + break; + case climate::CLIMATE_PRESET_NONE: + default: + break; + } // Checksum for (int i = 0; i < 17; i++) { remote_state[17] += remote_state[i]; } + ESP_LOGD(TAG, "sending: %02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%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], remote_state[8], remote_state[9], remote_state[10], remote_state[11], + remote_state[12], remote_state[13], remote_state[14], remote_state[15], remote_state[16], remote_state[17]); + auto transmit = this->transmitter_->transmit(); auto *data = transmit.get_data(); @@ -81,5 +272,119 @@ void MitsubishiClimate::transmit_state() { transmit.perform(); } +bool MitsubishiClimate::parse_state_frame_(const uint8_t frame[]) { return false; } + +bool MitsubishiClimate::on_receive(remote_base::RemoteReceiveData data) { + uint8_t state_frame[18] = {}; + + if (!data.expect_item(MITSUBISHI_HEADER_MARK, MITSUBISHI_HEADER_SPACE)) { + ESP_LOGV(TAG, "Header fail"); + return false; + } + + for (uint8_t pos = 0; pos < 18; pos++) { + uint8_t byte = 0; + for (int8_t bit = 0; bit < 8; bit++) { + if (data.expect_item(MITSUBISHI_BIT_MARK, MITSUBISHI_ONE_SPACE)) { + byte |= 1 << bit; + } else if (!data.expect_item(MITSUBISHI_BIT_MARK, MITSUBISHI_ZERO_SPACE)) { + ESP_LOGV(TAG, "Byte %d bit %d fail", pos, bit); + return false; + } + } + state_frame[pos] = byte; + + // Check Header && Footer + if ((pos == 0 && byte != MITSUBISHI_BYTE00) || (pos == 1 && byte != MITSUBISHI_BYTE01) || + (pos == 2 && byte != MITSUBISHI_BYTE02) || (pos == 3 && byte != MITSUBISHI_BYTE03) || + (pos == 4 && byte != MITSUBISHI_BYTE04) || (pos == 13 && byte != MITSUBISHI_BYTE13) || + (pos == 16 && byte != MITSUBISHI_BYTE16)) { + ESP_LOGV(TAG, "Bytes 0,1,2,3,4,13 or 16 fail - invalid value"); + return false; + } + } + + // On/Off and Mode + if (state_frame[5] == MITSUBISHI_OFF) { + this->mode = climate::CLIMATE_MODE_OFF; + } else { + switch (state_frame[6]) { + case MITSUBISHI_MODE_HEAT: + this->mode = climate::CLIMATE_MODE_HEAT; + break; + case MITSUBISHI_MODE_DRY: + this->mode = climate::CLIMATE_MODE_DRY; + break; + case MITSUBISHI_MODE_COOL: + this->mode = climate::CLIMATE_MODE_COOL; + break; + case MITSUBISHI_MODE_FAN_ONLY: + this->mode = climate::CLIMATE_MODE_FAN_ONLY; + break; + case MITSUBISHI_MODE_AUTO: + this->mode = climate::CLIMATE_MODE_HEAT_COOL; + break; + } + } + + // Temp + this->target_temperature = state_frame[7] + MITSUBISHI_TEMP_MIN; + + // Fan + uint8_t fan = state_frame[9] & 0x07; //(Bit 0,1,2 = Speed) + // Map of Climate fan mode to this device expected value + // For 3Level: Low = 1, Medium = 2, High = 3 + // For 4Level: Low = 1, Middle = 2, Medium = 3, High = 4 + // For 5Level: Low = 1, Middle = 2, Medium = 3, High = 4 + // For 4Level + Quiet: Low = 1, Middle = 2, Medium = 3, High = 4, Quiet = 5 + climate::ClimateFanMode modes_mapping[8] = { + climate::CLIMATE_FAN_AUTO, + climate::CLIMATE_FAN_LOW, + this->fan_mode_ == MITSUBISHI_FAN_3L ? climate::CLIMATE_FAN_MEDIUM : climate::CLIMATE_FAN_MIDDLE, + this->fan_mode_ == MITSUBISHI_FAN_3L ? climate::CLIMATE_FAN_HIGH : climate::CLIMATE_FAN_MEDIUM, + climate::CLIMATE_FAN_HIGH, + climate::CLIMATE_FAN_QUIET, + climate::CLIMATE_FAN_AUTO, + climate::CLIMATE_FAN_AUTO}; + this->fan_mode = modes_mapping[fan]; + + // Wide Vane + uint8_t wide_vane = state_frame[8] & 0xF0; // Bits 4,5,6,7 + switch (wide_vane) { + case MITSUBISHI_WIDE_VANE_SWING: + this->swing_mode = climate::CLIMATE_SWING_HORIZONTAL; + break; + default: + this->swing_mode = climate::CLIMATE_SWING_OFF; + break; + } + + // Vertical Vane + uint8_t vertical_vane = state_frame[9] & 0x38; // Bits 3,4,5 + switch (vertical_vane) { + case MITSUBISHI_VERTICAL_VANE_SWING: + if (this->swing_mode == climate::CLIMATE_SWING_HORIZONTAL) { + this->swing_mode = climate::CLIMATE_SWING_BOTH; + } else { + this->swing_mode = climate::CLIMATE_SWING_VERTICAL; + } + break; + } + + switch (state_frame[14]) { + case MITSUBISHI_ECONOCOOL: + this->preset = climate::CLIMATE_PRESET_ECO; + break; + case MITSUBISHI_NIGHTMODE: + this->preset = climate::CLIMATE_PRESET_SLEEP; + break; + } + + ESP_LOGV(TAG, "Receiving: %s", format_hex_pretty(state_frame, 18).c_str()); + + this->publish_state(); + return true; +} + } // namespace mitsubishi } // namespace esphome diff --git a/esphome/components/mitsubishi/mitsubishi.h b/esphome/components/mitsubishi/mitsubishi.h index 9a88040d3f..cfe12428da 100644 --- a/esphome/components/mitsubishi/mitsubishi.h +++ b/esphome/components/mitsubishi/mitsubishi.h @@ -11,13 +11,72 @@ namespace mitsubishi { const uint8_t MITSUBISHI_TEMP_MIN = 16; // Celsius const uint8_t MITSUBISHI_TEMP_MAX = 31; // Celsius +// Fan mode +enum SetFanMode { + MITSUBISHI_FAN_3L = 0, // 3 levels + auto + MITSUBISHI_FAN_4L, // 4 levels + auto + MITSUBISHI_FAN_Q4L, // Quiet + 4 levels + auto + // MITSUBISHI_FAN_5L, // 5 levels + auto +}; + +// Enum to represent horizontal directios +enum HorizontalDirection { + HORIZONTAL_DIRECTION_LEFT = 0x10, + HORIZONTAL_DIRECTION_MIDDLE_LEFT = 0x20, + HORIZONTAL_DIRECTION_MIDDLE = 0x30, + HORIZONTAL_DIRECTION_MIDDLE_RIGHT = 0x40, + HORIZONTAL_DIRECTION_RIGHT = 0x50, + HORIZONTAL_DIRECTION_SPLIT = 0x80, +}; + +// Enum to represent vertical directions +enum VerticalDirection { + VERTICAL_DIRECTION_AUTO = 0x00, + VERTICAL_DIRECTION_UP = 0x08, + VERTICAL_DIRECTION_MIDDLE_UP = 0x10, + VERTICAL_DIRECTION_MIDDLE = 0x18, + VERTICAL_DIRECTION_MIDDLE_DOWN = 0x20, + VERTICAL_DIRECTION_DOWN = 0x28, +}; + class MitsubishiClimate : public climate_ir::ClimateIR { public: - MitsubishiClimate() : climate_ir::ClimateIR(MITSUBISHI_TEMP_MIN, MITSUBISHI_TEMP_MAX) {} + MitsubishiClimate() + : climate_ir::ClimateIR(MITSUBISHI_TEMP_MIN, MITSUBISHI_TEMP_MAX, 1.0f, true, true, + {climate::CLIMATE_FAN_AUTO, climate::CLIMATE_FAN_LOW, climate::CLIMATE_FAN_MIDDLE, + climate::CLIMATE_FAN_MEDIUM, climate::CLIMATE_FAN_HIGH, climate::CLIMATE_FAN_QUIET}, + {climate::CLIMATE_SWING_OFF, climate::CLIMATE_SWING_BOTH, climate::CLIMATE_SWING_VERTICAL, + climate::CLIMATE_SWING_HORIZONTAL}, + {climate::CLIMATE_PRESET_NONE, climate::CLIMATE_PRESET_ECO, climate::CLIMATE_PRESET_BOOST, + climate::CLIMATE_PRESET_SLEEP}) {} + + void set_supports_cool(bool supports_cool) { this->supports_cool_ = supports_cool; } + void set_supports_dry(bool supports_dry) { this->supports_dry_ = supports_dry; } + void set_supports_fan_only(bool supports_fan_only) { this->supports_fan_only_ = supports_fan_only; } + void set_supports_heat(bool supports_heat) { this->supports_heat_ = supports_heat; } + + void set_fan_mode(SetFanMode fan_mode) { this->fan_mode_ = fan_mode; } + + void set_horizontal_default(HorizontalDirection horizontal_direction) { + this->default_horizontal_direction_ = horizontal_direction; + } + void set_vertical_default(VerticalDirection vertical_direction) { + this->default_vertical_direction_ = vertical_direction; + } protected: - /// Transmit via IR the state of this climate controller. + // Transmit via IR the state of this climate controller. void transmit_state() override; + // Handle received IR Buffer + bool on_receive(remote_base::RemoteReceiveData data) override; + bool parse_state_frame_(const uint8_t frame[]); + + SetFanMode fan_mode_; + + HorizontalDirection default_horizontal_direction_; + VerticalDirection default_vertical_direction_; + + climate::ClimateTraits traits() override; }; } // namespace mitsubishi diff --git a/tests/test1.yaml b/tests/test1.yaml index 505e839f5b..c8ae9691c2 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -2652,6 +2652,10 @@ climate: name: Yashima Climate - platform: mitsubishi name: Mitsubishi + supports_dry: "true" + supports_fan_only: "true" + horizontal_default: "left" + vertical_default: "down" - platform: whirlpool name: Whirlpool Climate - platform: climate_ir_lg From 1dd14254b3eddcf84903d36508cbd1649223a027 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Tue, 12 Mar 2024 09:55:23 +1100 Subject: [PATCH 1055/2101] Drivers for RGB 16 bit parallel displays (#5872) Co-authored-by: clydebarrow <366188+clydebarrow@users.noreply.github.com> --- CODEOWNERS | 2 + esphome/components/rpi_dpi_rgb/__init__.py | 1 + esphome/components/rpi_dpi_rgb/display.py | 197 ++++++++++ .../components/rpi_dpi_rgb/rpi_dpi_rgb.cpp | 116 ++++++ esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.h | 92 +++++ esphome/components/st7701s/__init__.py | 1 + esphome/components/st7701s/display.py | 253 ++++++++++++ esphome/components/st7701s/init_sequences.py | 363 ++++++++++++++++++ esphome/components/st7701s/st7701s.cpp | 180 +++++++++ esphome/components/st7701s/st7701s.h | 115 ++++++ .../rpi_dpi_rgb/test.esp32-s3-idf.yaml | 40 ++ .../components/st7701s/test.esp32-s3-idf.yaml | 60 +++ 12 files changed, 1420 insertions(+) create mode 100644 esphome/components/rpi_dpi_rgb/__init__.py create mode 100644 esphome/components/rpi_dpi_rgb/display.py create mode 100644 esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp create mode 100644 esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.h create mode 100644 esphome/components/st7701s/__init__.py create mode 100644 esphome/components/st7701s/display.py create mode 100644 esphome/components/st7701s/init_sequences.py create mode 100644 esphome/components/st7701s/st7701s.cpp create mode 100644 esphome/components/st7701s/st7701s.h create mode 100644 tests/components/rpi_dpi_rgb/test.esp32-s3-idf.yaml create mode 100644 tests/components/st7701s/test.esp32-s3-idf.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 3b2d1eeeed..320c2d5e7e 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -282,6 +282,7 @@ esphome/components/rgbct/* @jesserockz esphome/components/rp2040/* @jesserockz 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/safe_mode/* @jsuanet @paulmonigatti @@ -333,6 +334,7 @@ esphome/components/ssd1351_spi/* @kbx81 esphome/components/st7567_base/* @latonita esphome/components/st7567_i2c/* @latonita esphome/components/st7567_spi/* @latonita +esphome/components/st7701s/* @clydebarrow esphome/components/st7735/* @SenexCrenshaw esphome/components/st7789v/* @kbx81 esphome/components/st7920/* @marsjan155 diff --git a/esphome/components/rpi_dpi_rgb/__init__.py b/esphome/components/rpi_dpi_rgb/__init__.py new file mode 100644 index 0000000000..c58ce8a01e --- /dev/null +++ b/esphome/components/rpi_dpi_rgb/__init__.py @@ -0,0 +1 @@ +CODEOWNERS = ["@clydebarrow"] diff --git a/esphome/components/rpi_dpi_rgb/display.py b/esphome/components/rpi_dpi_rgb/display.py new file mode 100644 index 0000000000..0cde16e0fb --- /dev/null +++ b/esphome/components/rpi_dpi_rgb/display.py @@ -0,0 +1,197 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome import pins +from esphome.components import display +from esphome.const import ( + CONF_RESET_PIN, + CONF_DATA_PINS, + CONF_ID, + CONF_IGNORE_STRAPPING_WARNING, + CONF_DIMENSIONS, + CONF_WIDTH, + CONF_HEIGHT, + CONF_LAMBDA, + CONF_COLOR_ORDER, + CONF_RED, + CONF_GREEN, + CONF_BLUE, + CONF_NUMBER, + CONF_OFFSET_HEIGHT, + CONF_OFFSET_WIDTH, + CONF_INVERT_COLORS, +) +from esphome.components.esp32 import ( + only_on_variant, + const, +) + +DEPENDENCIES = ["esp32"] + +CONF_DE_PIN = "de_pin" +CONF_PCLK_PIN = "pclk_pin" +CONF_HSYNC_PIN = "hsync_pin" +CONF_VSYNC_PIN = "vsync_pin" + +CONF_HSYNC_FRONT_PORCH = "hsync_front_porch" +CONF_HSYNC_PULSE_WIDTH = "hsync_pulse_width" +CONF_HSYNC_BACK_PORCH = "hsync_back_porch" +CONF_VSYNC_FRONT_PORCH = "vsync_front_porch" +CONF_VSYNC_PULSE_WIDTH = "vsync_pulse_width" +CONF_VSYNC_BACK_PORCH = "vsync_back_porch" +CONF_PCLK_FREQUENCY = "pclk_frequency" +CONF_PCLK_INVERTED = "pclk_inverted" + +rpi_dpi_rgb_ns = cg.esphome_ns.namespace("rpi_dpi_rgb") +RPI_DPI_RGB = rpi_dpi_rgb_ns.class_("RpiDpiRgb", display.Display, cg.Component) +ColorOrder = display.display_ns.enum("ColorMode") + +COLOR_ORDERS = { + "RGB": ColorOrder.COLOR_ORDER_RGB, + "BGR": ColorOrder.COLOR_ORDER_BGR, +} +DATA_PIN_SCHEMA = pins.internal_gpio_output_pin_schema + + +def data_pin_validate(value): + """ + It is safe to use strapping pins as RGB output data bits, as they are outputs only, + and not initialised until after boot. + """ + if not isinstance(value, dict): + try: + return DATA_PIN_SCHEMA( + {CONF_NUMBER: value, CONF_IGNORE_STRAPPING_WARNING: True} + ) + except cv.Invalid: + pass + return DATA_PIN_SCHEMA(value) + + +def data_pin_set(length): + return cv.All( + [data_pin_validate], + cv.Length(min=length, max=length, msg=f"Exactly {length} data pins required"), + ) + + +CONFIG_SCHEMA = cv.All( + display.FULL_DISPLAY_SCHEMA.extend( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(RPI_DPI_RGB), + cv.Required(CONF_DIMENSIONS): cv.Any( + cv.dimensions, + cv.Schema( + { + cv.Required(CONF_WIDTH): cv.int_, + cv.Required(CONF_HEIGHT): cv.int_, + cv.Optional(CONF_OFFSET_HEIGHT, default=0): cv.int_, + cv.Optional(CONF_OFFSET_WIDTH, default=0): cv.int_, + } + ), + ), + cv.Optional(CONF_PCLK_FREQUENCY, default="16MHz"): cv.All( + cv.frequency, cv.Range(min=4e6, max=30e6) + ), + cv.Optional(CONF_PCLK_INVERTED, default=True): cv.boolean, + cv.Required(CONF_DATA_PINS): cv.Any( + data_pin_set(16), + cv.Schema( + { + cv.Required(CONF_RED): data_pin_set(5), + cv.Required(CONF_GREEN): data_pin_set(6), + cv.Required(CONF_BLUE): data_pin_set(5), + } + ), + ), + cv.Optional(CONF_COLOR_ORDER): cv.one_of( + *COLOR_ORDERS.keys(), upper=True + ), + cv.Optional(CONF_INVERT_COLORS, default=False): cv.boolean, + cv.Required(CONF_DE_PIN): pins.internal_gpio_output_pin_schema, + cv.Required(CONF_PCLK_PIN): pins.internal_gpio_output_pin_schema, + cv.Required(CONF_HSYNC_PIN): pins.internal_gpio_output_pin_schema, + cv.Required(CONF_VSYNC_PIN): pins.internal_gpio_output_pin_schema, + cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, + cv.Optional(CONF_HSYNC_PULSE_WIDTH, default=10): cv.int_, + cv.Optional(CONF_HSYNC_BACK_PORCH, default=10): cv.int_, + cv.Optional(CONF_HSYNC_FRONT_PORCH, default=20): cv.int_, + cv.Optional(CONF_VSYNC_PULSE_WIDTH, default=10): cv.int_, + cv.Optional(CONF_VSYNC_BACK_PORCH, default=10): cv.int_, + cv.Optional(CONF_VSYNC_FRONT_PORCH, default=10): cv.int_, + } + ) + ), + only_on_variant(supported=[const.VARIANT_ESP32S3]), + cv.only_with_esp_idf, +) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + await display.register_display(var, config) + + cg.add(var.set_color_mode(COLOR_ORDERS[config[CONF_COLOR_ORDER]])) + 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])) + cg.add(var.set_hsync_front_porch(config[CONF_HSYNC_FRONT_PORCH])) + 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_inverted(config[CONF_PCLK_INVERTED])) + cg.add(var.set_pclk_frequency(config[CONF_PCLK_FREQUENCY])) + index = 0 + dpins = [] + if CONF_RED in config[CONF_DATA_PINS]: + red_pins = config[CONF_DATA_PINS][CONF_RED] + green_pins = config[CONF_DATA_PINS][CONF_GREEN] + blue_pins = config[CONF_DATA_PINS][CONF_BLUE] + if config[CONF_COLOR_ORDER] == "BGR": + dpins.extend(red_pins) + dpins.extend(green_pins) + dpins.extend(blue_pins) + else: + dpins.extend(blue_pins) + dpins.extend(green_pins) + dpins.extend(red_pins) + # swap bytes to match big-endian format + dpins = dpins[8:16] + dpins[0:8] + else: + dpins = config[CONF_DATA_PINS] + for pin in dpins: + data_pin = await cg.gpio_pin_expression(pin) + cg.add(var.add_data_pin(data_pin, index)) + index += 1 + + if reset_pin := config.get(CONF_RESET_PIN): + reset = await cg.gpio_pin_expression(reset_pin) + cg.add(var.set_reset_pin(reset)) + + if CONF_DIMENSIONS in config: + dimensions = config[CONF_DIMENSIONS] + if isinstance(dimensions, dict): + cg.add(var.set_dimensions(dimensions[CONF_WIDTH], dimensions[CONF_HEIGHT])) + cg.add( + var.set_offsets( + dimensions[CONF_OFFSET_WIDTH], dimensions[CONF_OFFSET_HEIGHT] + ) + ) + else: + (width, height) = dimensions + cg.add(var.set_dimensions(width, height)) + + if lamb := config.get(CONF_LAMBDA): + lambda_ = await cg.process_lambda( + lamb, [(display.DisplayRef, "it")], return_type=cg.void + ) + cg.add(var.set_writer(lambda_)) + + pin = await cg.gpio_pin_expression(config[CONF_DE_PIN]) + 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)) diff --git a/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp b/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp new file mode 100644 index 0000000000..2ffdb3272a --- /dev/null +++ b/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp @@ -0,0 +1,116 @@ +#ifdef USE_ESP32_VARIANT_ESP32S3 +#include "rpi_dpi_rgb.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace rpi_dpi_rgb { + +void RpiDpiRgb::setup() { + esph_log_config(TAG, "Setting up RPI_DPI_RGB"); + esp_lcd_rgb_panel_config_t config{}; + config.flags.fb_in_psram = 1; + config.timings.h_res = this->width_; + config.timings.v_res = this->height_; + config.timings.hsync_pulse_width = this->hsync_pulse_width_; + config.timings.hsync_back_porch = this->hsync_back_porch_; + config.timings.hsync_front_porch = this->hsync_front_porch_; + config.timings.vsync_pulse_width = this->vsync_pulse_width_; + config.timings.vsync_back_porch = this->vsync_back_porch_; + config.timings.vsync_front_porch = this->vsync_front_porch_; + config.timings.flags.pclk_active_neg = this->pclk_inverted_; + config.timings.pclk_hz = this->pclk_frequency_; + config.clk_src = LCD_CLK_SRC_PLL160M; + config.sram_trans_align = 64; + config.psram_trans_align = 64; + 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_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(); + 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)); + } + ESP_ERROR_CHECK(esp_lcd_panel_reset(this->handle_)); + ESP_ERROR_CHECK(esp_lcd_panel_init(this->handle_)); + esph_log_config(TAG, "RPI_DPI_RGB setup complete"); +} + +void RpiDpiRgb::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) { + if (w <= 0 || h <= 0) + return; + // if color mapping is required, pass the buck. + // note that endianness is not considered here - it is assumed to match! + if (bitness != display::COLOR_BITNESS_565) { + return display::Display::draw_pixels_at(x_start, y_start, w, h, ptr, order, bitness, big_endian, x_offset, y_offset, + x_pad); + } + x_start += this->offset_x_; + y_start += this->offset_y_; + esp_err_t err; + // x_ and y_offset are offsets into the source buffer, unrelated to our own offsets into the display. + if (x_offset == 0 && x_pad == 0 && y_offset == 0) { + // we could deal here with a non-zero y_offset, but if x_offset is zero, y_offset probably will be so don't bother + err = esp_lcd_panel_draw_bitmap(this->handle_, x_start, y_start, x_start + w, y_start + h, ptr); + } else { + // draw line by line + auto stride = x_offset + w + x_pad; + for (int y = 0; y != h; y++) { + err = esp_lcd_panel_draw_bitmap(this->handle_, x_start, y + y_start, x_start + w, y + y_start + 1, + ptr + ((y + y_offset) * stride + x_offset) * 2); + if (err != ESP_OK) + break; + } + } + if (err != ESP_OK) + esph_log_e(TAG, "lcd_lcd_panel_draw_bitmap failed: %s", esp_err_to_name(err)); +} + +void RpiDpiRgb::draw_pixel_at(int x, int y, Color color) { + if (!this->get_clipping().inside(x, y)) + return; // NOLINT + + switch (this->rotation_) { + case display::DISPLAY_ROTATION_0_DEGREES: + break; + case display::DISPLAY_ROTATION_90_DEGREES: + std::swap(x, y); + x = this->width_ - x - 1; + break; + case display::DISPLAY_ROTATION_180_DEGREES: + x = this->width_ - x - 1; + y = this->height_ - y - 1; + break; + case display::DISPLAY_ROTATION_270_DEGREES: + std::swap(x, y); + y = this->height_ - y - 1; + break; + } + auto pixel = convert_big_endian(display::ColorUtil::color_to_565(color)); + + this->draw_pixels_at(x, y, 1, 1, (const uint8_t *) &pixel, display::COLOR_ORDER_RGB, display::COLOR_BITNESS_565, true, + 0, 0, 0); + App.feed_wdt(); +} + +void RpiDpiRgb::dump_config() { + ESP_LOGCONFIG("", "RPI_DPI_RGB LCD"); + ESP_LOGCONFIG(TAG, " Height: %u", this->height_); + ESP_LOGCONFIG(TAG, " Width: %u", this->width_); + 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()); +} + +} // namespace rpi_dpi_rgb +} // namespace esphome + +#endif // USE_ESP32_VARIANT_ESP32S3 diff --git a/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.h b/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.h new file mode 100644 index 0000000000..0319b46391 --- /dev/null +++ b/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.h @@ -0,0 +1,92 @@ +// +// Created by Clyde Stubbs on 29/10/2023. +// +#pragma once + +// only applicable on ESP32-S3 +#ifdef USE_ESP32_VARIANT_ESP32S3 +#include "esphome/core/component.h" +#include "esphome/core/gpio.h" +#include "esphome/core/log.h" +#include "esphome/core/application.h" +#include "esphome/components/display/display.h" +#include "esp_lcd_panel_ops.h" + +#include "esp_lcd_panel_rgb.h" + +namespace esphome { +namespace rpi_dpi_rgb { + +constexpr static const char *const TAG = "rpi_dpi_rgb"; + +class RpiDpiRgb : public display::Display { + public: + void update() override { this->do_update_(); } + void setup() 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 draw_pixel_at(int x, int y, Color color) override; + + 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 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; } + void set_pclk_pin(InternalGPIOPin *pclk_pin) { this->pclk_pin_ = pclk_pin; } + void set_vsync_pin(InternalGPIOPin *vsync_pin) { this->vsync_pin_ = vsync_pin; } + void set_hsync_pin(InternalGPIOPin *hsync_pin) { this->hsync_pin_ = hsync_pin; } + void set_reset_pin(GPIOPin *reset_pin) { this->reset_pin_ = reset_pin; } + void set_width(uint16_t width) { this->width_ = width; } + void set_dimensions(uint16_t width, uint16_t height) { + this->width_ = width; + this->height_ = height; + } + int get_width() override { return this->width_; } + int get_height() override { return this->height_; } + void set_hsync_back_porch(uint16_t hsync_back_porch) { this->hsync_back_porch_ = hsync_back_porch; } + void set_hsync_front_porch(uint16_t hsync_front_porch) { this->hsync_front_porch_ = hsync_front_porch; } + void set_hsync_pulse_width(uint16_t hsync_pulse_width) { this->hsync_pulse_width_ = hsync_pulse_width; } + void set_vsync_pulse_width(uint16_t vsync_pulse_width) { this->vsync_pulse_width_ = vsync_pulse_width; } + void set_vsync_back_porch(uint16_t vsync_back_porch) { this->vsync_back_porch_ = vsync_back_porch; } + void set_vsync_front_porch(uint16_t vsync_front_porch) { this->vsync_front_porch_ = vsync_front_porch; } + void set_pclk_frequency(uint32_t pclk_frequency) { this->pclk_frequency_ = pclk_frequency; } + void set_pclk_inverted(bool inverted) { this->pclk_inverted_ = inverted; } + void set_offsets(int16_t offset_x, int16_t offset_y) { + this->offset_x_ = offset_x; + this->offset_y_ = offset_y; + } + display::DisplayType get_display_type() override { return display::DisplayType::DISPLAY_TYPE_COLOR; } + void dump_config() override; + + protected: + int get_width_internal() override { return this->width_; } + int get_height_internal() override { return this->height_; } + InternalGPIOPin *de_pin_{nullptr}; + InternalGPIOPin *pclk_pin_{nullptr}; + InternalGPIOPin *hsync_pin_{nullptr}; + InternalGPIOPin *vsync_pin_{nullptr}; + GPIOPin *reset_pin_{nullptr}; + InternalGPIOPin *data_pins_[16] = {}; + uint16_t hsync_front_porch_ = 8; + uint16_t hsync_pulse_width_ = 4; + uint16_t hsync_back_porch_ = 8; + uint16_t vsync_front_porch_ = 8; + uint16_t vsync_pulse_width_ = 4; + uint16_t vsync_back_porch_ = 8; + uint32_t pclk_frequency_ = 16 * 1000 * 1000; + bool pclk_inverted_{true}; + + bool invert_colors_{}; + display::ColorOrder color_mode_{display::COLOR_ORDER_BGR}; + size_t width_{}; + size_t height_{}; + int16_t offset_x_{0}; + int16_t offset_y_{0}; + + esp_lcd_panel_handle_t handle_{}; +}; + +} // namespace rpi_dpi_rgb +} // namespace esphome +#endif // USE_ESP32_VARIANT_ESP32S3 diff --git a/esphome/components/st7701s/__init__.py b/esphome/components/st7701s/__init__.py new file mode 100644 index 0000000000..c58ce8a01e --- /dev/null +++ b/esphome/components/st7701s/__init__.py @@ -0,0 +1 @@ +CODEOWNERS = ["@clydebarrow"] diff --git a/esphome/components/st7701s/display.py b/esphome/components/st7701s/display.py new file mode 100644 index 0000000000..e33eeb89ae --- /dev/null +++ b/esphome/components/st7701s/display.py @@ -0,0 +1,253 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome import pins +from esphome.components import ( + spi, + display, +) +from esphome.const import ( + CONF_DC_PIN, + CONF_RESET_PIN, + CONF_DATA_PINS, + CONF_ID, + CONF_DIMENSIONS, + CONF_WIDTH, + CONF_HEIGHT, + CONF_LAMBDA, + CONF_MIRROR_X, + CONF_MIRROR_Y, + CONF_COLOR_ORDER, + CONF_TRANSFORM, + CONF_OFFSET_HEIGHT, + CONF_OFFSET_WIDTH, + CONF_INVERT_COLORS, + CONF_RED, + CONF_GREEN, + CONF_BLUE, + CONF_NUMBER, + CONF_IGNORE_STRAPPING_WARNING, +) + +from esphome.components.esp32 import ( + only_on_variant, + const, +) +from esphome.components.rpi_dpi_rgb.display import ( + CONF_PCLK_FREQUENCY, + CONF_PCLK_INVERTED, +) +from .init_sequences import ( + ST7701S_INITS, + cmd, +) + +CONF_INIT_SEQUENCE = "init_sequence" +CONF_DE_PIN = "de_pin" +CONF_PCLK_PIN = "pclk_pin" +CONF_HSYNC_PIN = "hsync_pin" +CONF_VSYNC_PIN = "vsync_pin" + +CONF_HSYNC_PULSE_WIDTH = "hsync_pulse_width" +CONF_HSYNC_BACK_PORCH = "hsync_back_porch" +CONF_HSYNC_FRONT_PORCH = "hsync_front_porch" +CONF_VSYNC_PULSE_WIDTH = "vsync_pulse_width" +CONF_VSYNC_BACK_PORCH = "vsync_back_porch" +CONF_VSYNC_FRONT_PORCH = "vsync_front_porch" + +DEPENDENCIES = ["spi", "esp32"] + +st7701s_ns = cg.esphome_ns.namespace("st7701s") +ST7701S = st7701s_ns.class_("ST7701S", display.Display, cg.Component, spi.SPIDevice) +ColorOrder = display.display_ns.enum("ColorMode") + +COLOR_ORDERS = { + "RGB": ColorOrder.COLOR_ORDER_RGB, + "BGR": ColorOrder.COLOR_ORDER_BGR, +} +DATA_PIN_SCHEMA = pins.internal_gpio_output_pin_schema + + +def data_pin_validate(value): + """ + It is safe to use strapping pins as RGB output data bits, as they are outputs only, + and not initialised until after boot. + """ + if not isinstance(value, dict): + try: + return DATA_PIN_SCHEMA( + {CONF_NUMBER: value, CONF_IGNORE_STRAPPING_WARNING: True} + ) + except cv.Invalid: + pass + return DATA_PIN_SCHEMA(value) + + +def data_pin_set(length): + return cv.All( + [data_pin_validate], + cv.Length(min=length, max=length, msg=f"Exactly {length} data pins required"), + ) + + +def map_sequence(value): + """ + An initialisation sequence can be selected from one of the pre-defined sequences in init_sequences.py, + or can be a literal array of data bytes. + The format is a repeated sequence of [CMD, LEN, ] where is LEN bytes. + """ + if not isinstance(value, list): + value = cv.int_(value) + value = cv.one_of(*ST7701S_INITS)(value) + return ST7701S_INITS[value] + # value = cv.ensure_list(cv.uint8_t)(value) + data_length = len(value) + if data_length == 0: + raise cv.Invalid("Empty sequence") + value = cmd(*value) + return value + + +CONFIG_SCHEMA = cv.All( + display.FULL_DISPLAY_SCHEMA.extend( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(ST7701S), + cv.Required(CONF_DIMENSIONS): cv.Any( + cv.dimensions, + cv.Schema( + { + cv.Required(CONF_WIDTH): cv.int_, + cv.Required(CONF_HEIGHT): cv.int_, + cv.Optional(CONF_OFFSET_HEIGHT, default=0): cv.int_, + cv.Optional(CONF_OFFSET_WIDTH, default=0): cv.int_, + } + ), + ), + cv.Optional(CONF_TRANSFORM): cv.Schema( + { + cv.Optional(CONF_MIRROR_X, default=False): cv.boolean, + cv.Optional(CONF_MIRROR_Y, default=False): cv.boolean, + } + ), + cv.Required(CONF_DATA_PINS): cv.Any( + data_pin_set(16), + cv.Schema( + { + cv.Required(CONF_RED): data_pin_set(5), + cv.Required(CONF_GREEN): data_pin_set(6), + cv.Required(CONF_BLUE): data_pin_set(5), + } + ), + ), + cv.Optional(CONF_INIT_SEQUENCE, default=1): cv.ensure_list( + map_sequence + ), + cv.Optional(CONF_COLOR_ORDER): cv.one_of( + *COLOR_ORDERS.keys(), upper=True + ), + cv.Optional(CONF_PCLK_FREQUENCY, default="16MHz"): cv.All( + cv.frequency, cv.Range(min=4e6, max=30e6) + ), + cv.Optional(CONF_PCLK_INVERTED, default=True): cv.boolean, + cv.Optional(CONF_INVERT_COLORS, default=False): cv.boolean, + cv.Required(CONF_DE_PIN): pins.internal_gpio_output_pin_schema, + cv.Required(CONF_PCLK_PIN): pins.internal_gpio_output_pin_schema, + cv.Required(CONF_HSYNC_PIN): pins.internal_gpio_output_pin_schema, + cv.Required(CONF_VSYNC_PIN): pins.internal_gpio_output_pin_schema, + cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, + cv.Optional(CONF_DC_PIN): pins.gpio_output_pin_schema, + cv.Optional(CONF_HSYNC_PULSE_WIDTH, default=10): cv.int_, + cv.Optional(CONF_HSYNC_BACK_PORCH, default=10): cv.int_, + cv.Optional(CONF_HSYNC_FRONT_PORCH, default=20): cv.int_, + cv.Optional(CONF_VSYNC_PULSE_WIDTH, default=10): cv.int_, + cv.Optional(CONF_VSYNC_BACK_PORCH, default=10): cv.int_, + cv.Optional(CONF_VSYNC_FRONT_PORCH, default=10): cv.int_, + } + ).extend(spi.spi_device_schema(cs_pin_required=False, default_data_rate=1e6)) + ), + only_on_variant(supported=[const.VARIANT_ESP32S3]), + cv.only_with_esp_idf, +) + + +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) + + sequence = [] + for seq in config[CONF_INIT_SEQUENCE]: + sequence.extend(seq) + cg.add(var.set_init_sequence(sequence)) + cg.add(var.set_color_mode(COLOR_ORDERS[config[CONF_COLOR_ORDER]])) + 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])) + cg.add(var.set_hsync_front_porch(config[CONF_HSYNC_FRONT_PORCH])) + 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_inverted(config[CONF_PCLK_INVERTED])) + cg.add(var.set_pclk_frequency(config[CONF_PCLK_FREQUENCY])) + index = 0 + dpins = [] + if CONF_RED in config[CONF_DATA_PINS]: + red_pins = config[CONF_DATA_PINS][CONF_RED] + green_pins = config[CONF_DATA_PINS][CONF_GREEN] + blue_pins = config[CONF_DATA_PINS][CONF_BLUE] + if config[CONF_COLOR_ORDER] == "BGR": + dpins.extend(red_pins) + dpins.extend(green_pins) + dpins.extend(blue_pins) + else: + dpins.extend(blue_pins) + dpins.extend(green_pins) + dpins.extend(red_pins) + # swap bytes to match big-endian format + dpins = dpins[8:16] + dpins[0:8] + else: + dpins = config[CONF_DATA_PINS] + for pin in dpins: + data_pin = await cg.gpio_pin_expression(pin) + cg.add(var.add_data_pin(data_pin, index)) + index += 1 + + if dc_pin := config.get(CONF_DC_PIN): + dc = await cg.gpio_pin_expression(dc_pin) + cg.add(var.set_dc_pin(dc)) + + if reset_pin := config.get(CONF_RESET_PIN): + reset = await cg.gpio_pin_expression(reset_pin) + cg.add(var.set_reset_pin(reset)) + + if transform := config.get(CONF_TRANSFORM): + cg.add(var.set_mirror_x(transform[CONF_MIRROR_X])) + cg.add(var.set_mirror_y(transform[CONF_MIRROR_Y])) + + if CONF_DIMENSIONS in config: + dimensions = config[CONF_DIMENSIONS] + if isinstance(dimensions, dict): + cg.add(var.set_dimensions(dimensions[CONF_WIDTH], dimensions[CONF_HEIGHT])) + cg.add( + var.set_offsets( + dimensions[CONF_OFFSET_WIDTH], dimensions[CONF_OFFSET_HEIGHT] + ) + ) + else: + (width, height) = dimensions + cg.add(var.set_dimensions(width, height)) + + if lamb := config.get(CONF_LAMBDA): + lambda_ = await cg.process_lambda( + lamb, [(display.DisplayRef, "it")], return_type=cg.void + ) + cg.add(var.set_writer(lambda_)) + + pin = await cg.gpio_pin_expression(config[CONF_DE_PIN]) + 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)) diff --git a/esphome/components/st7701s/init_sequences.py b/esphome/components/st7701s/init_sequences.py new file mode 100644 index 0000000000..4786731c78 --- /dev/null +++ b/esphome/components/st7701s/init_sequences.py @@ -0,0 +1,363 @@ +# These are initialisation sequences for ST7701S displays. The contents are somewhat arcane. + + +def cmd(c, *args): + """ + Create a command sequence + :param c: The command (8 bit) + :param args: zero or more arguments (8 bit values) + :return: a list with the command, the argument count and the arguments + """ + return [c, len(args)] + list(args) + + +ST7701S_1_INIT = ( + cmd(0x01) + + cmd(0xFF, 0x77, 0x01, 0x00, 0x00, 0x10) + + cmd(0xC0, 0x3B, 0x00) + + cmd(0xC1, 0x0D, 0x02) + + cmd(0xC2, 0x31, 0x05) + + cmd(0xCD, 0x08) + + cmd( + 0xB0, + 0x00, + 0x11, + 0x18, + 0x0E, + 0x11, + 0x06, + 0x07, + 0x08, + 0x07, + 0x22, + 0x04, + 0x12, + 0x0F, + 0xAA, + 0x31, + 0x18, + ) + + cmd( + 0xB1, + 0x00, + 0x11, + 0x19, + 0x0E, + 0x12, + 0x07, + 0x08, + 0x08, + 0x08, + 0x22, + 0x04, + 0x11, + 0x11, + 0xA9, + 0x32, + 0x18, + ) + + cmd(0xFF, 0x77, 0x01, 0x00, 0x00, 0x11) + + cmd(0xB0, 0x60) + + cmd(0xB1, 0x32) + + cmd(0xB2, 0x07) + + cmd(0xB3, 0x80) + + cmd(0xB5, 0x49) + + cmd(0xB7, 0x85) + + cmd(0xB8, 0x21) + + cmd(0xC1, 0x78) + + cmd(0xC2, 0x78) + + cmd(0xE0, 0x00, 0x1B, 0x02) + + cmd(0xE1, 0x08, 0xA0, 0x00, 0x00, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x44, 0x44) + + cmd(0xE2, 0x11, 0x11, 0x44, 0x44, 0xED, 0xA0, 0x00, 0x00, 0xEC, 0xA0, 0x00, 0x00) + + cmd(0xE3, 0x00, 0x00, 0x11, 0x11) + + cmd(0xE4, 0x44, 0x44) + + cmd( + 0xE5, + 0x0A, + 0xE9, + 0xD8, + 0xA0, + 0x0C, + 0xEB, + 0xD8, + 0xA0, + 0x0E, + 0xED, + 0xD8, + 0xA0, + 0x10, + 0xEF, + 0xD8, + 0xA0, + ) + + cmd(0xE6, 0x00, 0x00, 0x11, 0x11) + + cmd(0xE7, 0x44, 0x44) + + cmd( + 0xE8, + 0x09, + 0xE8, + 0xD8, + 0xA0, + 0x0B, + 0xEA, + 0xD8, + 0xA0, + 0x0D, + 0xEC, + 0xD8, + 0xA0, + 0x0F, + 0xEE, + 0xD8, + 0xA0, + ) + + cmd(0xEB, 0x02, 0x00, 0xE4, 0xE4, 0x88, 0x00, 0x40) + + cmd(0xEC, 0x3C, 0x00) + + cmd( + 0xED, + 0xAB, + 0x89, + 0x76, + 0x54, + 0x02, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0x20, + 0x45, + 0x67, + 0x98, + 0xBA, + ) + + cmd(0xFF, 0x77, 0x01, 0x00, 0x00, 0x13) + + cmd(0xE5, 0xE4) + + cmd(0x3A, 0x60) +) + +# This is untested +ST7701S_7_INIT = ( + cmd( + 0xFF, + 0x77, + 0x01, + 0x00, + 0x00, + 0x10, + ) + + cmd(0xC0, 0x3B, 0x00) + + cmd(0xC1, 0x0B, 0x02) + + cmd(0xC2, 0x07, 0x02) + + cmd(0xCC, 0x10) + + cmd(0xCD, 0x08) + + cmd( + 0xB0, + 0x00, + 0x11, + 0x16, + 0x0E, + 0x11, + 0x06, + 0x05, + 0x09, + 0x08, + 0x21, + 0x06, + 0x13, + 0x10, + 0x29, + 0x31, + 0x18, + ) + + cmd( + 0xB1, + 0x00, + 0x11, + 0x16, + 0x0E, + 0x11, + 0x07, + 0x05, + 0x09, + 0x09, + 0x21, + 0x05, + 0x13, + 0x11, + 0x2A, + 0x31, + 0x18, + ) + + cmd( + 0xFF, + 0x77, + 0x01, + 0x00, + 0x00, + 0x11, + ) + + cmd(0xB0, 0x6D) + + cmd(0xB1, 0x37) + + cmd(0xB2, 0x81) + + cmd(0xB3, 0x80) + + cmd(0xB5, 0x43) + + cmd(0xB7, 0x85) + + cmd(0xB8, 0x20) + + cmd(0xC1, 0x78) + + cmd(0xC2, 0x78) + + cmd(0xD0, 0x88) + + cmd( + 0xE0, + 3, + 0x00, + 0x00, + 0x02, + ) + + cmd( + 0xE1, + 0x03, + 0xA0, + 0x00, + 0x00, + 0x04, + 0xA0, + 0x00, + 0x00, + 0x00, + 0x20, + 0x20, + ) + + cmd( + 0xE2, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + ) + + cmd( + 0xE3, + 0x00, + 0x00, + 0x11, + 0x00, + ) + + cmd(0xE4, 0x22, 0x00) + + cmd( + 0xE5, + 0x05, + 0xEC, + 0xA0, + 0xA0, + 0x07, + 0xEE, + 0xA0, + 0xA0, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + ) + + cmd( + 0xE6, + 0x00, + 0x00, + 0x11, + 0x00, + ) + + cmd(0xE7, 0x22, 0x00) + + cmd( + 0xE8, + 0x06, + 0xED, + 0xA0, + 0xA0, + 0x08, + 0xEF, + 0xA0, + 0xA0, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + ) + + cmd( + 0xEB, + 0x00, + 0x00, + 0x40, + 0x40, + 0x00, + 0x00, + 0x00, + ) + + cmd( + 0xED, + 0xFF, + 0xFF, + 0xFF, + 0xBA, + 0x0A, + 0xBF, + 0x45, + 0xFF, + 0xFF, + 0x54, + 0xFB, + 0xA0, + 0xAB, + 0xFF, + 0xFF, + 0xFF, + ) + + cmd( + 0xEF, + 0x10, + 0x0D, + 0x04, + 0x08, + 0x3F, + 0x1F, + ) + + cmd( + 0xFF, + 0x77, + 0x01, + 0x00, + 0x00, + 0x13, + ) + + cmd(0xEF, 0x08) + + cmd( + 0xFF, + 0x77, + 0x01, + 0x00, + 0x00, + 0x00, + ) + + cmd(0x3A, 0x66) +) + +ST7701S_INITS = { + 1: ST7701S_1_INIT, + # 7: ST7701S_7_INIT, +} diff --git a/esphome/components/st7701s/st7701s.cpp b/esphome/components/st7701s/st7701s.cpp new file mode 100644 index 0000000000..43d8653709 --- /dev/null +++ b/esphome/components/st7701s/st7701s.cpp @@ -0,0 +1,180 @@ +#ifdef USE_ESP32_VARIANT_ESP32S3 +#include "st7701s.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace st7701s { + +void ST7701S::setup() { + esph_log_config(TAG, "Setting up ST7701S"); + this->spi_setup(); + esp_lcd_rgb_panel_config_t config{}; + config.flags.fb_in_psram = 1; + config.timings.h_res = this->width_; + config.timings.v_res = this->height_; + config.timings.hsync_pulse_width = this->hsync_pulse_width_; + config.timings.hsync_back_porch = this->hsync_back_porch_; + config.timings.hsync_front_porch = this->hsync_front_porch_; + config.timings.vsync_pulse_width = this->vsync_pulse_width_; + config.timings.vsync_back_porch = this->vsync_back_porch_; + config.timings.vsync_front_porch = this->vsync_front_porch_; + config.timings.flags.pclk_active_neg = this->pclk_inverted_; + config.timings.pclk_hz = this->pclk_frequency_; + config.clk_src = LCD_CLK_SRC_PLL160M; + config.sram_trans_align = 64; + config.psram_trans_align = 64; + 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_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(); + 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)); + } + ESP_ERROR_CHECK(esp_lcd_panel_reset(this->handle_)); + ESP_ERROR_CHECK(esp_lcd_panel_init(this->handle_)); + this->write_init_sequence_(); + esph_log_config(TAG, "ST7701S setup complete"); +} + +void ST7701S::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) { + if (w <= 0 || h <= 0) + return; + // if color mapping is required, pass the buck. + // note that endianness is not considered here - it is assumed to match! + if (bitness != display::COLOR_BITNESS_565) { + return display::Display::draw_pixels_at(x_start, y_start, w, h, ptr, order, bitness, big_endian, x_offset, y_offset, + x_pad); + } + x_start += this->offset_x_; + y_start += this->offset_y_; + esp_err_t err; + // x_ and y_offset are offsets into the source buffer, unrelated to our own offsets into the display. + if (x_offset == 0 && x_pad == 0 && y_offset == 0) { + // we could deal here with a non-zero y_offset, but if x_offset is zero, y_offset probably will be so don't bother + err = esp_lcd_panel_draw_bitmap(this->handle_, x_start, y_start, x_start + w, y_start + h, ptr); + } else { + // draw line by line + auto stride = x_offset + w + x_pad; + for (int y = 0; y != h; y++) { + err = esp_lcd_panel_draw_bitmap(this->handle_, x_start, y + y_start, x_start + w, y + y_start + 1, + ptr + ((y + y_offset) * stride + x_offset) * 2); + if (err != ESP_OK) + break; + } + } + if (err != ESP_OK) + esph_log_e(TAG, "lcd_lcd_panel_draw_bitmap failed: %s", esp_err_to_name(err)); +} + +void ST7701S::draw_pixel_at(int x, int y, Color color) { + if (!this->get_clipping().inside(x, y)) + return; // NOLINT + + switch (this->rotation_) { + case display::DISPLAY_ROTATION_0_DEGREES: + break; + case display::DISPLAY_ROTATION_90_DEGREES: + std::swap(x, y); + x = this->width_ - x - 1; + break; + case display::DISPLAY_ROTATION_180_DEGREES: + x = this->width_ - x - 1; + y = this->height_ - y - 1; + break; + case display::DISPLAY_ROTATION_270_DEGREES: + std::swap(x, y); + y = this->height_ - y - 1; + break; + } + auto pixel = convert_big_endian(display::ColorUtil::color_to_565(color)); + + this->draw_pixels_at(x, y, 1, 1, (const uint8_t *) &pixel, display::COLOR_ORDER_RGB, display::COLOR_BITNESS_565, true, + 0, 0, 0); + App.feed_wdt(); +} + +void ST7701S::write_command_(uint8_t value) { + this->enable(); + if (this->dc_pin_ == nullptr) { + this->write(value, 9); + } else { + this->dc_pin_->digital_write(false); + this->write_byte(value); + this->dc_pin_->digital_write(true); + } + this->disable(); +} + +void ST7701S::write_data_(uint8_t value) { + this->enable(); + if (this->dc_pin_ == nullptr) { + this->write(value | 0x100, 9); + } else { + this->dc_pin_->digital_write(true); + this->write_byte(value); + } + this->disable(); +} + +/** + * this relies upon the init sequence being well-formed, which is guaranteed by the Python init code. + */ + +void ST7701S::write_sequence_(uint8_t cmd, size_t len, const uint8_t *bytes) { + this->write_command_(cmd); + while (len-- != 0) + this->write_data_(*bytes++); +} + +void ST7701S::write_init_sequence_() { + for (size_t i = 0; i != this->init_sequence_.size();) { + uint8_t cmd = this->init_sequence_[i++]; + size_t len = this->init_sequence_[i++]; + this->write_sequence_(cmd, len, &this->init_sequence_[i]); + i += len; + esph_log_v(TAG, "Command %X, %d bytes", cmd, len); + if (cmd == SW_RESET_CMD) + delay(6); + } + // st7701 does not appear to support axis swapping + this->write_sequence_(CMD2_BKSEL, sizeof(CMD2_BK0), CMD2_BK0); + this->write_command_(SDIR_CMD); // this is in the BK0 command set + this->write_data_(this->mirror_x_ ? 0x04 : 0x00); + uint8_t val = this->color_mode_ == display::COLOR_ORDER_BGR ? 0x08 : 0x00; + if (this->mirror_y_) + val |= 0x10; + this->write_command_(MADCTL_CMD); + this->write_data_(val); + esph_log_d(TAG, "write MADCTL %X", val); + this->write_command_(this->invert_colors_ ? INVERT_ON : INVERT_OFF); + this->set_timeout(120, [this] { + this->write_command_(SLEEP_OUT); + this->write_command_(DISPLAY_ON); + }); +} + +void ST7701S::dump_config() { + ESP_LOGCONFIG("", "ST7701S RGB LCD"); + ESP_LOGCONFIG(TAG, " Height: %u", this->height_); + ESP_LOGCONFIG(TAG, " Width: %u", this->width_); + LOG_PIN(" CS Pin: ", this->cs_); + LOG_PIN(" DC Pin: ", this->dc_pin_); + 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()); + ESP_LOGCONFIG(TAG, " SPI Data rate: %dMHz", (unsigned) (this->data_rate_ / 1000000)); +} + +} // namespace st7701s +} // namespace esphome +#endif // USE_ESP32_VARIANT_ESP32S3 diff --git a/esphome/components/st7701s/st7701s.h b/esphome/components/st7701s/st7701s.h new file mode 100644 index 0000000000..2328bca965 --- /dev/null +++ b/esphome/components/st7701s/st7701s.h @@ -0,0 +1,115 @@ +// +// Created by Clyde Stubbs on 29/10/2023. +// +#pragma once + +// only applicable on ESP32-S3 +#ifdef USE_ESP32_VARIANT_ESP32S3 +#include "esphome/core/component.h" +#include "esphome/components/spi/spi.h" +#include "esphome/components/display/display.h" +#include "esp_lcd_panel_ops.h" + +#include "esp_lcd_panel_rgb.h" + +namespace esphome { +namespace st7701s { + +constexpr static const char *const TAG = "display.st7701s"; +const uint8_t SW_RESET_CMD = 0x01; +const uint8_t SLEEP_OUT = 0x11; +const uint8_t SDIR_CMD = 0xC7; +const uint8_t MADCTL_CMD = 0x36; +const uint8_t INVERT_OFF = 0x20; +const uint8_t INVERT_ON = 0x21; +const uint8_t DISPLAY_ON = 0x29; +const uint8_t CMD2_BKSEL = 0xFF; +const uint8_t CMD2_BK0[5] = {0x77, 0x01, 0x00, 0x00, 0x10}; + +class ST7701S : public display::Display, + public spi::SPIDevice { + public: + void update() override { this->do_update_(); } + void setup() 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; + + 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 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; } + void set_pclk_pin(InternalGPIOPin *pclk_pin) { this->pclk_pin_ = pclk_pin; } + void set_vsync_pin(InternalGPIOPin *vsync_pin) { this->vsync_pin_ = vsync_pin; } + void set_hsync_pin(InternalGPIOPin *hsync_pin) { this->hsync_pin_ = hsync_pin; } + void set_dc_pin(GPIOPin *dc_pin) { this->dc_pin_ = dc_pin; } + void set_reset_pin(GPIOPin *reset_pin) { this->reset_pin_ = reset_pin; } + void set_width(uint16_t width) { this->width_ = width; } + void set_pclk_frequency(uint32_t pclk_frequency) { this->pclk_frequency_ = pclk_frequency; } + void set_pclk_inverted(bool inverted) { this->pclk_inverted_ = inverted; } + void set_dimensions(uint16_t width, uint16_t height) { + this->width_ = width; + this->height_ = height; + } + int get_width() override { return this->width_; } + int get_height() override { return this->height_; } + void set_hsync_back_porch(uint16_t hsync_back_porch) { this->hsync_back_porch_ = hsync_back_porch; } + void set_hsync_front_porch(uint16_t hsync_front_porch) { this->hsync_front_porch_ = hsync_front_porch; } + void set_hsync_pulse_width(uint16_t hsync_pulse_width) { this->hsync_pulse_width_ = hsync_pulse_width; } + void set_vsync_pulse_width(uint16_t vsync_pulse_width) { this->vsync_pulse_width_ = vsync_pulse_width; } + void set_vsync_back_porch(uint16_t vsync_back_porch) { this->vsync_back_porch_ = vsync_back_porch; } + void set_vsync_front_porch(uint16_t vsync_front_porch) { this->vsync_front_porch_ = vsync_front_porch; } + void set_init_sequence(const std::vector &init_sequence) { this->init_sequence_ = init_sequence; } + void set_mirror_x(bool mirror_x) { this->mirror_x_ = mirror_x; } + void set_mirror_y(bool mirror_y) { this->mirror_y_ = mirror_y; } + void set_offsets(int16_t offset_x, int16_t offset_y) { + this->offset_x_ = offset_x; + this->offset_y_ = offset_y; + } + display::DisplayType get_display_type() override { return display::DisplayType::DISPLAY_TYPE_COLOR; } + int get_width_internal() override { return this->width_; } + int get_height_internal() override { return this->height_; } + void dump_config() override; + void draw_pixel_at(int x, int y, Color color) override; + + // this will be horribly slow. + protected: + void write_command_(uint8_t value); + void write_data_(uint8_t value); + void write_sequence_(uint8_t cmd, size_t len, const uint8_t *bytes); + void write_init_sequence_(); + + InternalGPIOPin *de_pin_{nullptr}; + InternalGPIOPin *pclk_pin_{nullptr}; + InternalGPIOPin *hsync_pin_{nullptr}; + InternalGPIOPin *vsync_pin_{nullptr}; + GPIOPin *reset_pin_{nullptr}; + GPIOPin *dc_pin_{nullptr}; + InternalGPIOPin *data_pins_[16] = {}; + uint16_t hsync_pulse_width_ = 10; + uint16_t hsync_back_porch_ = 10; + uint16_t hsync_front_porch_ = 20; + uint16_t vsync_pulse_width_ = 10; + uint16_t vsync_back_porch_ = 10; + uint16_t vsync_front_porch_ = 10; + std::vector init_sequence_; + uint32_t pclk_frequency_ = 16 * 1000 * 1000; + bool pclk_inverted_{true}; + + bool invert_colors_{}; + display::ColorOrder color_mode_{display::COLOR_ORDER_BGR}; + size_t width_{}; + size_t height_{}; + int16_t offset_x_{0}; + int16_t offset_y_{0}; + bool mirror_x_{}; + bool mirror_y_{}; + + esp_lcd_panel_handle_t handle_{}; +}; + +} // namespace st7701s +} // namespace esphome +#endif diff --git a/tests/components/rpi_dpi_rgb/test.esp32-s3-idf.yaml b/tests/components/rpi_dpi_rgb/test.esp32-s3-idf.yaml new file mode 100644 index 0000000000..9ce2d9b9fd --- /dev/null +++ b/tests/components/rpi_dpi_rgb/test.esp32-s3-idf.yaml @@ -0,0 +1,40 @@ +psram: + mode: octal + speed: 80MHz +display: + - platform: rpi_dpi_rgb + update_interval: never + auto_clear_enabled: false + id: rpi_display + color_order: RGB + rotation: 90 + dimensions: + width: 800 + height: 480 + de_pin: + number: 40 + hsync_pin: 39 + vsync_pin: 41 + pclk_pin: 42 + data_pins: + red: + - number: 45 # r1 + ignore_strapping_warning: true + - 48 # r2 + - 47 # r3 + - 21 # r4 + - number: 14 # r5 + ignore_strapping_warning: false + green: + - 5 # g0 + - 6 # g1 + - 7 # g2 + - 15 # g3 + - 16 # g4 + - 4 # g5 + blue: + - 8 # b1 + - 3 # b2 + - 46 # b3 + - 9 # b4 + - 1 # b5 diff --git a/tests/components/st7701s/test.esp32-s3-idf.yaml b/tests/components/st7701s/test.esp32-s3-idf.yaml new file mode 100644 index 0000000000..497df8c8ce --- /dev/null +++ b/tests/components/st7701s/test.esp32-s3-idf.yaml @@ -0,0 +1,60 @@ +psram: + mode: octal + speed: 80MHz +spi: + - id: lcd_spi + clk_pin: 41 + mosi_pin: 48 + +i2c: + sda: 39 + scl: 40 + scan: false + id: bus_a + +pca9554: + - id: p_c_a + pin_count: 16 + address: 0x20 + +display: + - platform: st7701s + spi_mode: MODE3 + color_order: RGB + dimensions: + width: 480 + height: 480 + invert_colors: true + transform: + mirror_x: true + mirror_y: true + cs_pin: + pca9554: p_c_a + number: 4 + reset_pin: + pca9554: p_c_a + number: 5 + de_pin: 18 + hsync_pin: 16 + vsync_pin: 17 + pclk_pin: 21 + init_sequence: 1 + data_pins: + - number: 0 + ignore_strapping_warning: true + - 1 + - 2 + - 3 + - number: 4 + ignore_strapping_warning: false + - 5 + - 6 + - 7 + - 8 + - 9 + - 10 + - 11 + - 12 + - 13 + - 14 + - 15 From 51ab15c40e6f81ac78fc884946ff3ecd999a14d0 Mon Sep 17 00:00:00 2001 From: mrtoy-me <118446898+mrtoy-me@users.noreply.github.com> Date: Tue, 12 Mar 2024 12:31:58 +1000 Subject: [PATCH 1056/2101] hydreon_rgxx - add resolution option (#6077) Co-authored-by: functionpointer --- esphome/components/hydreon_rgxx/__init__.py | 1 + .../components/hydreon_rgxx/hydreon_rgxx.cpp | 11 ++++++++++- esphome/components/hydreon_rgxx/hydreon_rgxx.h | 9 +++++++++ esphome/components/hydreon_rgxx/sensor.py | 18 +++++++++++++++--- tests/test3.yaml | 1 + 5 files changed, 36 insertions(+), 4 deletions(-) diff --git a/esphome/components/hydreon_rgxx/__init__.py b/esphome/components/hydreon_rgxx/__init__.py index 5fe050edf2..b488bfc1b4 100644 --- a/esphome/components/hydreon_rgxx/__init__.py +++ b/esphome/components/hydreon_rgxx/__init__.py @@ -6,6 +6,7 @@ DEPENDENCIES = ["uart"] hydreon_rgxx_ns = cg.esphome_ns.namespace("hydreon_rgxx") RGModel = hydreon_rgxx_ns.enum("RGModel") +RG15Resolution = hydreon_rgxx_ns.enum("RG15Resolution") HydreonRGxxComponent = hydreon_rgxx_ns.class_( "HydreonRGxxComponent", cg.PollingComponent, uart.UARTDevice ) diff --git a/esphome/components/hydreon_rgxx/hydreon_rgxx.cpp b/esphome/components/hydreon_rgxx/hydreon_rgxx.cpp index c026d7cce6..95702fe9e8 100644 --- a/esphome/components/hydreon_rgxx/hydreon_rgxx.cpp +++ b/esphome/components/hydreon_rgxx/hydreon_rgxx.cpp @@ -22,6 +22,11 @@ void HydreonRGxxComponent::dump_config() { ESP_LOGCONFIG(TAG, " Disable Led: %s", TRUEFALSE(this->disable_led_)); } else { ESP_LOGCONFIG(TAG, " Model: RG15"); + if (this->resolution_ == FORCE_HIGH) { + ESP_LOGCONFIG(TAG, " Resolution: high"); + } else { + ESP_LOGCONFIG(TAG, " Resolution: low"); + } } LOG_UPDATE_INTERVAL(this); @@ -195,7 +200,11 @@ void HydreonRGxxComponent::process_line_() { ESP_LOGI(TAG, "Boot detected: %s", this->buffer_.substr(0, this->buffer_.size() - 2).c_str()); if (this->model_ == RG15) { - this->write_str("P\nH\nM\n"); // set sensor to (P)polling mode, (H)high res mode, (M)metric mode + if (this->resolution_ == FORCE_HIGH) { + this->write_str("P\nH\nM\n"); // set sensor to (P)polling mode, (H)high res mode, (M)metric mode + } else { + this->write_str("P\nL\nM\n"); // set sensor to (P)polling mode, (L)low res mode, (M)metric mode + } } if (this->model_ == RG9) { diff --git a/esphome/components/hydreon_rgxx/hydreon_rgxx.h b/esphome/components/hydreon_rgxx/hydreon_rgxx.h index 1edda59800..76b0985a24 100644 --- a/esphome/components/hydreon_rgxx/hydreon_rgxx.h +++ b/esphome/components/hydreon_rgxx/hydreon_rgxx.h @@ -16,6 +16,11 @@ enum RGModel { RG15 = 2, }; +enum RG15Resolution { + FORCE_LOW = 1, + FORCE_HIGH = 2, +}; + #ifdef HYDREON_RGXX_NUM_SENSORS static const uint8_t NUM_SENSORS = HYDREON_RGXX_NUM_SENSORS; #else @@ -37,6 +42,7 @@ class HydreonRGxxComponent : public PollingComponent, public uart::UARTDevice { void set_em_sat_sensor(binary_sensor::BinarySensor *sensor) { this->em_sat_sensor_ = sensor; } #endif void set_model(RGModel model) { model_ = model; } + void set_resolution(RG15Resolution resolution) { resolution_ = resolution; } void set_request_temperature(bool b) { request_temperature_ = b; } /// Schedule data readings. @@ -68,7 +74,10 @@ class HydreonRGxxComponent : public PollingComponent, public uart::UARTDevice { int16_t boot_count_ = 0; int16_t no_response_count_ = 0; std::string buffer_; + RGModel model_ = RG9; + RG15Resolution resolution_ = FORCE_HIGH; + int sw_version_ = 0; bool too_cold_ = false; bool lens_bad_ = false; diff --git a/esphome/components/hydreon_rgxx/sensor.py b/esphome/components/hydreon_rgxx/sensor.py index f9cb316c24..72b74bf624 100644 --- a/esphome/components/hydreon_rgxx/sensor.py +++ b/esphome/components/hydreon_rgxx/sensor.py @@ -5,6 +5,7 @@ from esphome.const import ( CONF_ID, CONF_MODEL, CONF_MOISTURE, + CONF_RESOLUTION, CONF_TEMPERATURE, DEVICE_CLASS_PRECIPITATION_INTENSITY, DEVICE_CLASS_PRECIPITATION, @@ -14,7 +15,7 @@ from esphome.const import ( ICON_THERMOMETER, ) -from . import RGModel, HydreonRGxxComponent +from . import RGModel, RG15Resolution, HydreonRGxxComponent UNIT_INTENSITY = "intensity" UNIT_MILLIMETERS = "mm" @@ -37,11 +38,18 @@ RG_MODELS = { # 1.100 - https://rainsensors.com/wp-content/uploads/sites/3/2021/03/2021.03.11-rg-9_instructions.pdf # 1.200 - https://rainsensors.com/wp-content/uploads/sites/3/2022/03/2022.02.17-rev-1.200-rg-9_instructions.pdf } -SUPPORTED_SENSORS = { + +RG15_RESOLUTION = { + "low": RG15Resolution.FORCE_LOW, + "high": RG15Resolution.FORCE_HIGH, +} + +SUPPORTED_OPTIONS = { CONF_ACC: ["RG_15"], CONF_EVENT_ACC: ["RG_15"], CONF_TOTAL_ACC: ["RG_15"], CONF_R_INT: ["RG_15"], + CONF_RESOLUTION: ["RG_15"], CONF_MOISTURE: ["RG_9"], CONF_TEMPERATURE: ["RG_9"], CONF_DISABLE_LED: ["RG_9"], @@ -57,7 +65,7 @@ PROTOCOL_NAMES = { def _validate(config): - for conf, models in SUPPORTED_SENSORS.items(): + for conf, models in SUPPORTED_OPTIONS.items(): if conf in config: if config[CONF_MODEL] not in models: raise cv.Invalid( @@ -75,6 +83,7 @@ CONFIG_SCHEMA = cv.All( upper=True, space="_", ), + cv.Optional(CONF_RESOLUTION): cv.enum(RG15_RESOLUTION, upper=False), cv.Optional(CONF_ACC): sensor.sensor_schema( unit_of_measurement=UNIT_MILLIMETERS, accuracy_decimals=2, @@ -139,6 +148,9 @@ async def to_code(config): cg.add(var.set_sensor(sens, i)) cg.add(var.set_model(config[CONF_MODEL])) + if CONF_RESOLUTION in config: + cg.add(var.set_resolution(config[CONF_RESOLUTION])) + cg.add(var.set_request_temperature(CONF_TEMPERATURE in config)) if CONF_DISABLE_LED in config: diff --git a/tests/test3.yaml b/tests/test3.yaml index 29ed40c52a..61d814385b 100644 --- a/tests/test3.yaml +++ b/tests/test3.yaml @@ -409,6 +409,7 @@ sensor: name: hydreon_total_acc r_int: name: hydreon_r_int + resolution: low - platform: adc pin: VCC From 782d662c2029e21fbb6ddb3a434cbe20dc310208 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Tue, 12 Mar 2024 13:50:24 +1100 Subject: [PATCH 1057/2101] SPI schema now uses typed_schema with `type` key (#6353) --- esphome/components/spi/__init__.py | 22 +++++++++++++------- tests/components/spi/test.esp32-s3-idf.yaml | 23 +++++++++++++++++++++ tests/test8.1.yaml | 12 ++--------- 3 files changed, 39 insertions(+), 18 deletions(-) create mode 100644 tests/components/spi/test.esp32-s3-idf.yaml diff --git a/esphome/components/spi/__init__.py b/esphome/components/spi/__init__.py index d45362435e..c2335bd92a 100644 --- a/esphome/components/spi/__init__.py +++ b/esphome/components/spi/__init__.py @@ -32,7 +32,10 @@ from esphome.const import ( CONF_ALLOW_OTHER_USES, CONF_DATA_PINS, ) -from esphome.core import coroutine_with_priority, CORE +from esphome.core import ( + coroutine_with_priority, + CORE, +) CODEOWNERS = ["@esphome/core", "@clydebarrow"] spi_ns = cg.esphome_ns.namespace("spi") @@ -73,6 +76,8 @@ CONF_SPI_MODE = "spi_mode" CONF_FORCE_SW = "force_sw" CONF_INTERFACE = "interface" CONF_INTERFACE_INDEX = "interface_index" +TYPE_SINGLE = "single" +TYPE_QUAD = "quad" # RP2040 SPI pin assignments are complicated; # refer to GPIO function select table in https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf @@ -297,18 +302,19 @@ SPI_QUAD_SCHEMA = cv.All( ), } ), + cv.only_on([PLATFORM_ESP32]), cv.only_with_esp_idf, ) CONFIG_SCHEMA = cv.All( - # Order is important. SPI_SCHEMA is the default. cv.ensure_list( - cv.Any( - SPI_SCHEMA, - SPI_QUAD_SCHEMA, - msg="Standard SPI requires mosi_pin and/or miso_pin; quad SPI requires data_pins only." - + " A clock pin is always required", - ), + cv.typed_schema( + { + TYPE_SINGLE: SPI_SCHEMA, + TYPE_QUAD: SPI_QUAD_SCHEMA, + }, + default_type=TYPE_SINGLE, + ) ), validate_spi_config, ) diff --git a/tests/components/spi/test.esp32-s3-idf.yaml b/tests/components/spi/test.esp32-s3-idf.yaml new file mode 100644 index 0000000000..3aae21cbeb --- /dev/null +++ b/tests/components/spi/test.esp32-s3-idf.yaml @@ -0,0 +1,23 @@ +spi: + - id: spi_id_1 + type: single + clk_pin: + number: GPIO7 + allow_other_uses: false + mosi_pin: GPIO6 + interface: hardware + - id: quad_spi + type: quad + clk_pin: 47 + interface: spi3 + data_pins: + - number: 40 + allow_other_uses: false + - 41 + - 42 + - 43 + - id: spi_id_3 + clk_pin: 8 + mosi_pin: 9 + interface: any + diff --git a/tests/test8.1.yaml b/tests/test8.1.yaml index fdfa8bc786..ab3d0d44aa 100644 --- a/tests/test8.1.yaml +++ b/tests/test8.1.yaml @@ -23,20 +23,12 @@ psram: spi: - id: spi_id_1 + type: single clk_pin: number: GPIO7 allow_other_uses: false mosi_pin: GPIO6 - interface: any - - id: quad_spi - clk_pin: 47 - data_pins: - - number: 40 - allow_other_uses: false - - 41 - - 42 - - 43 - + interface: hardware spi_device: id: spidev data_rate: 2MHz From 5b28bd3d97733c44a7f79f9f6d2f143b0264fe34 Mon Sep 17 00:00:00 2001 From: Anton Viktorov Date: Tue, 12 Mar 2024 03:51:01 +0100 Subject: [PATCH 1058/2101] VEML7700 and VEML6030 light sensors (#6067) * VEML7700 and VEML6030 light sensors * VEML7700 and VEML6030 light sensors - CODEOWNERS * VEML7700 and VEML6030 light sensors - tidy up * VEML7700 and VEML6030 light sensors - tidy up * VEML7700 tidy up * VEML7700 tidy up 4 * VEML7700 tidying up more * VEML7700 after review. non-blocking approach * VEML7700 CONSTANT_CASE * VEML7700 merge fix * VEML7700 pragma pack changed to attribute * VEML7700 pragma pack -> attribute * Minor publish split * minor * LOGD->LOGV * new school tests added * Discard changes to tests/test1.yaml --------- Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Co-authored-by: Keith Burzinski --- CODEOWNERS | 1 + esphome/components/veml7700/__init__.py | 1 + esphome/components/veml7700/sensor.py | 190 ++++++++ esphome/components/veml7700/veml7700.cpp | 437 ++++++++++++++++++ esphome/components/veml7700/veml7700.h | 202 ++++++++ tests/components/veml7700/common.yaml | 10 + .../veml7700/test.esp32-c3-idf.yaml | 6 + tests/components/veml7700/test.esp32-c3.yaml | 6 + tests/components/veml7700/test.esp32-idf.yaml | 6 + tests/components/veml7700/test.esp32.yaml | 6 + tests/components/veml7700/test.esp8266.yaml | 6 + tests/components/veml7700/test.rp2040.yaml | 6 + 12 files changed, 877 insertions(+) create mode 100644 esphome/components/veml7700/__init__.py create mode 100644 esphome/components/veml7700/sensor.py create mode 100644 esphome/components/veml7700/veml7700.cpp create mode 100644 esphome/components/veml7700/veml7700.h create mode 100644 tests/components/veml7700/common.yaml create mode 100644 tests/components/veml7700/test.esp32-c3-idf.yaml create mode 100644 tests/components/veml7700/test.esp32-c3.yaml create mode 100644 tests/components/veml7700/test.esp32-idf.yaml create mode 100644 tests/components/veml7700/test.esp32.yaml create mode 100644 tests/components/veml7700/test.esp8266.yaml create mode 100644 tests/components/veml7700/test.rp2040.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 320c2d5e7e..e31dd16077 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -380,6 +380,7 @@ esphome/components/ultrasonic/* @OttoWinter esphome/components/uponor_smatrix/* @kroimon esphome/components/vbus/* @ssieb esphome/components/veml3235/* @kbx81 +esphome/components/veml7700/* @latonita esphome/components/version/* @esphome/core esphome/components/voice_assistant/* @jesserockz esphome/components/wake_on_lan/* @willwill2will54 diff --git a/esphome/components/veml7700/__init__.py b/esphome/components/veml7700/__init__.py new file mode 100644 index 0000000000..dd06cfffea --- /dev/null +++ b/esphome/components/veml7700/__init__.py @@ -0,0 +1 @@ +CODEOWNERS = ["@latonita"] diff --git a/esphome/components/veml7700/sensor.py b/esphome/components/veml7700/sensor.py new file mode 100644 index 0000000000..7ce05b47e4 --- /dev/null +++ b/esphome/components/veml7700/sensor.py @@ -0,0 +1,190 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import i2c, sensor +from esphome.const import ( + CONF_ACTUAL_GAIN, + CONF_AUTO_MODE, + CONF_FULL_SPECTRUM, + CONF_GAIN, + CONF_GLASS_ATTENUATION_FACTOR, + CONF_ID, + CONF_INFRARED, + CONF_INTEGRATION_TIME, + CONF_NAME, + UNIT_LUX, + UNIT_MILLISECOND, + ICON_BRIGHTNESS_5, + ICON_BRIGHTNESS_6, + ICON_TIMER, + DEVICE_CLASS_ILLUMINANCE, + STATE_CLASS_MEASUREMENT, +) + +CODEOWNERS = ["@latonita"] +DEPENDENCIES = ["i2c"] + +UNIT_COUNTS = "#" +ICON_MULTIPLICATION = "mdi:multiplication" +ICON_BRIGHTNESS_7 = "mdi:brightness-7" + +CONF_ACTUAL_INTEGRATION_TIME = "actual_integration_time" +CONF_AMBIENT_LIGHT = "ambient_light" +CONF_AMBIENT_LIGHT_COUNTS = "ambient_light_counts" +CONF_FULL_SPECTRUM_COUNTS = "full_spectrum_counts" +CONF_LUX_COMPENSATION = "lux_compensation" + +veml7700_ns = cg.esphome_ns.namespace("veml7700") + +VEML7700Component = veml7700_ns.class_( + "VEML7700Component", cg.PollingComponent, i2c.I2CDevice +) + +Gain = veml7700_ns.enum("Gain") +GAINS = { + "1/8X": Gain.X_1_8, + "1/4X": Gain.X_1_4, + "1X": Gain.X_1, + "2X": Gain.X_2, +} + +IntegrationTime = veml7700_ns.enum("IntegrationTime") +INTEGRATION_TIMES = { + 25: IntegrationTime.INTEGRATION_TIME_25MS, + 50: IntegrationTime.INTEGRATION_TIME_50MS, + 100: IntegrationTime.INTEGRATION_TIME_100MS, + 200: IntegrationTime.INTEGRATION_TIME_200MS, + 400: IntegrationTime.INTEGRATION_TIME_400MS, + 800: IntegrationTime.INTEGRATION_TIME_800MS, +} + + +def validate_integration_time(value): + value = cv.positive_time_period_milliseconds(value).total_milliseconds + return cv.enum(INTEGRATION_TIMES, int=True)(value) + + +CONFIG_SCHEMA = cv.All( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(VEML7700Component), + cv.Optional(CONF_AUTO_MODE, default=True): cv.boolean, + cv.Optional(CONF_GAIN, default="1/8X"): cv.enum(GAINS, upper=True), + cv.Optional( + CONF_INTEGRATION_TIME, default="100ms" + ): validate_integration_time, + cv.Optional(CONF_LUX_COMPENSATION, default=True): cv.boolean, + cv.Optional(CONF_GLASS_ATTENUATION_FACTOR, default=1.0): cv.float_range( + min=1.0 + ), + cv.Optional(CONF_AMBIENT_LIGHT): cv.maybe_simple_value( + sensor.sensor_schema( + unit_of_measurement=UNIT_LUX, + icon=ICON_BRIGHTNESS_6, + accuracy_decimals=1, + device_class=DEVICE_CLASS_ILLUMINANCE, + state_class=STATE_CLASS_MEASUREMENT, + ), + key=CONF_NAME, + ), + cv.Optional(CONF_AMBIENT_LIGHT_COUNTS): cv.maybe_simple_value( + sensor.sensor_schema( + unit_of_measurement=UNIT_COUNTS, + icon=ICON_BRIGHTNESS_6, + accuracy_decimals=0, + device_class=DEVICE_CLASS_ILLUMINANCE, + state_class=STATE_CLASS_MEASUREMENT, + ), + key=CONF_NAME, + ), + cv.Optional(CONF_FULL_SPECTRUM): cv.maybe_simple_value( + sensor.sensor_schema( + unit_of_measurement=UNIT_LUX, + icon=ICON_BRIGHTNESS_7, + accuracy_decimals=1, + device_class=DEVICE_CLASS_ILLUMINANCE, + state_class=STATE_CLASS_MEASUREMENT, + ), + key=CONF_NAME, + ), + cv.Optional(CONF_FULL_SPECTRUM_COUNTS): cv.maybe_simple_value( + sensor.sensor_schema( + 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, + ), + cv.Optional(CONF_INFRARED): cv.maybe_simple_value( + sensor.sensor_schema( + unit_of_measurement=UNIT_LUX, + icon=ICON_BRIGHTNESS_5, + accuracy_decimals=1, + device_class=DEVICE_CLASS_ILLUMINANCE, + state_class=STATE_CLASS_MEASUREMENT, + ), + key=CONF_NAME, + ), + cv.Optional(CONF_ACTUAL_GAIN): cv.maybe_simple_value( + sensor.sensor_schema( + icon=ICON_MULTIPLICATION, + accuracy_decimals=3, + state_class=STATE_CLASS_MEASUREMENT, + ), + key=CONF_NAME, + ), + cv.Optional(CONF_ACTUAL_INTEGRATION_TIME): cv.maybe_simple_value( + sensor.sensor_schema( + unit_of_measurement=UNIT_MILLISECOND, + icon=ICON_TIMER, + accuracy_decimals=0, + state_class=STATE_CLASS_MEASUREMENT, + ), + key=CONF_NAME, + ), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x10)), +) + + +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 als_config := config.get(CONF_AMBIENT_LIGHT): + sens = await sensor.new_sensor(als_config) + cg.add(var.set_ambient_light_sensor(sens)) + + if als_cnt_config := config.get(CONF_AMBIENT_LIGHT_COUNTS): + sens = await sensor.new_sensor(als_cnt_config) + cg.add(var.set_ambient_light_counts_sensor(sens)) + + if full_spect_config := config.get(CONF_FULL_SPECTRUM): + sens = await sensor.new_sensor(full_spect_config) + cg.add(var.set_white_sensor(sens)) + + if full_spect_cnt_config := config.get(CONF_FULL_SPECTRUM_COUNTS): + sens = await sensor.new_sensor(full_spect_cnt_config) + cg.add(var.set_white_counts_sensor(sens)) + + if infrared_config := config.get(CONF_INFRARED): + sens = await sensor.new_sensor(infrared_config) + cg.add(var.set_infrared_sensor(sens)) + + if act_gain_config := config.get(CONF_ACTUAL_GAIN): + sens = await sensor.new_sensor(act_gain_config) + cg.add(var.set_actual_gain_sensor(sens)) + + if act_itime_config := config.get(CONF_ACTUAL_INTEGRATION_TIME): + sens = await sensor.new_sensor(act_itime_config) + cg.add(var.set_actual_integration_time_sensor(sens)) + + cg.add(var.set_enable_automatic_mode(config[CONF_AUTO_MODE])) + cg.add(var.set_enable_lux_compensation(config[CONF_LUX_COMPENSATION])) + cg.add(var.set_gain(config[CONF_GAIN])) + cg.add(var.set_integration_time(config[CONF_INTEGRATION_TIME])) + cg.add(var.set_glass_attenuation_factor(config[CONF_GLASS_ATTENUATION_FACTOR])) diff --git a/esphome/components/veml7700/veml7700.cpp b/esphome/components/veml7700/veml7700.cpp new file mode 100644 index 0000000000..68550811a1 --- /dev/null +++ b/esphome/components/veml7700/veml7700.cpp @@ -0,0 +1,437 @@ +#include "veml7700.h" +#include "esphome/core/application.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace veml7700 { + +static const char *const TAG = "veml7700"; +static const size_t VEML_REG_SIZE = 2; + +static float reduce_to_zero(float a, float b) { return (a > b) ? (a - b) : 0; } + +template T get_next(const T (&array)[size], const T val) { + size_t i = 0; + size_t idx = -1; + while (idx == -1 && i < size) { + if (array[i] == val) { + idx = i; + break; + } + i++; + } + if (idx == -1 || i + 1 >= size) + return val; + return array[i + 1]; +} + +template T get_prev(const T (&array)[size], const T val) { + size_t i = size - 1; + size_t idx = -1; + while (idx == -1 && i > 0) { + if (array[i] == val) { + idx = i; + break; + } + i--; + } + if (idx == -1 || i == 0) + return val; + return array[i - 1]; +} + +static uint16_t get_itime_ms(IntegrationTime time) { + uint16_t ms = 0; + switch (time) { + case INTEGRATION_TIME_100MS: + ms = 100; + break; + case INTEGRATION_TIME_200MS: + ms = 200; + break; + case INTEGRATION_TIME_400MS: + ms = 400; + break; + case INTEGRATION_TIME_800MS: + ms = 800; + break; + case INTEGRATION_TIME_50MS: + ms = 50; + break; + case INTEGRATION_TIME_25MS: + ms = 25; + break; + default: + ms = 100; + } + return ms; +} + +static float get_gain_coeff(Gain gain) { + static const float GAIN_FLOAT[GAINS_COUNT] = {1.0f, 2.0f, 0.125f, 0.25f}; + return GAIN_FLOAT[gain & 0b11]; +} + +static const char *get_gain_str(Gain gain) { + static const char *gain_str[GAINS_COUNT] = {"1x", "2x", "1/8x", "1/4x"}; + return gain_str[gain & 0b11]; +} + +void VEML7700Component::setup() { + ESP_LOGCONFIG(TAG, "Setting up VEML7700/6030..."); + + auto err = this->configure_(); + if (err != i2c::ERROR_OK) { + ESP_LOGW(TAG, "Sensor configuration failed"); + this->mark_failed(); + } else { + this->state_ = State::INITIAL_SETUP_COMPLETED; + } +} + +void VEML7700Component::dump_config() { + LOG_I2C_DEVICE(this); + ESP_LOGCONFIG(TAG, " Automatic gain/time: %s", YESNO(this->automatic_mode_enabled_)); + if (!this->automatic_mode_enabled_) { + ESP_LOGCONFIG(TAG, " Gain: %s", get_gain_str(this->gain_)); + ESP_LOGCONFIG(TAG, " Integration time: %d ms", get_itime_ms(this->integration_time_)); + } + ESP_LOGCONFIG(TAG, " Lux compensation: %s", YESNO(this->lux_compensation_enabled_)); + ESP_LOGCONFIG(TAG, " Glass attenuation factor: %f", this->glass_attenuation_factor_); + LOG_UPDATE_INTERVAL(this); + + LOG_SENSOR(" ", "ALS channel lux", this->ambient_light_sensor_); + LOG_SENSOR(" ", "ALS channel counts", this->ambient_light_counts_sensor_); + LOG_SENSOR(" ", "WHITE channel lux", this->white_sensor_); + LOG_SENSOR(" ", "WHITE channel counts", this->white_counts_sensor_); + LOG_SENSOR(" ", "FAKE_IR channel lux", this->fake_infrared_sensor_); + LOG_SENSOR(" ", "Actual gain", this->actual_gain_sensor_); + LOG_SENSOR(" ", "Actual integration time", this->actual_integration_time_sensor_); + + if (this->is_failed()) { + ESP_LOGE(TAG, "Communication with I2C VEML7700/6030 failed!"); + } +} + +void VEML7700Component::update() { + if (this->is_ready() && this->state_ == State::IDLE) { + ESP_LOGV(TAG, "Update: Initiating new data collection"); + + this->state_ = this->automatic_mode_enabled_ ? State::COLLECTING_DATA_AUTO : State::COLLECTING_DATA; + + this->readings_.als_counts = 0; + this->readings_.white_counts = 0; + this->readings_.actual_time = this->integration_time_; + this->readings_.actual_gain = this->gain_; + this->readings_.als_lux = 0; + this->readings_.white_lux = 0; + this->readings_.fake_infrared_lux = 0; + } else { + ESP_LOGV(TAG, "Update: Component not ready yet"); + } +} + +void VEML7700Component::loop() { + ErrorCode err = i2c::ERROR_OK; + + if (this->state_ == State::INITIAL_SETUP_COMPLETED) { + // 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; }); + } + + if (this->is_ready()) { + switch (this->state_) { + case State::IDLE: + // doing nothing, having best time + break; + + case State::COLLECTING_DATA: + err = this->read_sensor_output_(this->readings_); + this->state_ = (err == i2c::ERROR_OK) ? State::DATA_COLLECTED : State::IDLE; + break; + + case State::COLLECTING_DATA_AUTO: // Automatic mode - we start here to reconfigure device first + case State::DATA_COLLECTED: + if (!this->are_adjustments_required_(this->readings_)) { + this->state_ = State::READY_TO_PUBLISH_PART_1; + } else { + // if sensitivity adjustment needed - + // shutdown device to change config and wait one integration time period + this->state_ = State::ADJUSTMENT_IN_PROGRESS; + err = this->reconfigure_time_and_gain_(this->readings_.actual_time, this->readings_.actual_gain, true); + if (err == i2c::ERROR_OK) { + this->set_timeout(1 * get_itime_ms(this->readings_.actual_time), + [this]() { this->state_ = State::READY_TO_APPLY_ADJUSTMENTS; }); + } else { + this->state_ = State::IDLE; + } + } + break; + + case State::ADJUSTMENT_IN_PROGRESS: + // nothing to be done, just waiting for the timeout + break; + + case State::READY_TO_APPLY_ADJUSTMENTS: + // second stage of sensitivity adjustment - turn device back on + // and wait 2-3 integration time periods to get good data samples + this->state_ = State::ADJUSTMENT_IN_PROGRESS; + err = this->reconfigure_time_and_gain_(this->readings_.actual_time, this->readings_.actual_gain, false); + if (err == i2c::ERROR_OK) { + this->set_timeout(3 * get_itime_ms(this->readings_.actual_time), + [this]() { this->state_ = State::COLLECTING_DATA; }); + } else { + this->state_ = State::IDLE; + } + break; + + case State::READY_TO_PUBLISH_PART_1: + this->status_clear_warning(); + + this->apply_lux_calculation_(this->readings_); + this->apply_lux_compensation_(this->readings_); + this->apply_glass_attenuation_(this->readings_); + + this->publish_data_part_1_(this->readings_); + this->state_ = State::READY_TO_PUBLISH_PART_2; + break; + + case State::READY_TO_PUBLISH_PART_2: + this->publish_data_part_2_(this->readings_); + this->state_ = State::READY_TO_PUBLISH_PART_3; + break; + + case State::READY_TO_PUBLISH_PART_3: + this->publish_data_part_3_(this->readings_); + this->state_ = State::IDLE; + break; + + default: + break; + } + if (err != i2c::ERROR_OK) + this->status_set_warning(); + } +} + +ErrorCode VEML7700Component::configure_() { + ESP_LOGV(TAG, "Configure"); + + ConfigurationRegister als_conf{0}; + als_conf.ALS_INT_EN = false; + als_conf.ALS_PERS = Persistence::PERSISTENCE_1; + als_conf.ALS_IT = this->integration_time_; + als_conf.ALS_GAIN = this->gain_; + + als_conf.ALS_SD = true; + ESP_LOGV(TAG, "Shutdown before config. ALS_CONF_0 to 0x%04X", als_conf.raw); + auto err = this->write_register((uint8_t) CommandRegisters::ALS_CONF_0, als_conf.raw_bytes, VEML_REG_SIZE); + if (err != i2c::ERROR_OK) { + ESP_LOGW(TAG, "Failed to shutdown, I2C error %d", err); + return err; + } + delay(3); + + als_conf.ALS_SD = false; + ESP_LOGV(TAG, "Turning on. Setting ALS_CONF_0 to 0x%04X", als_conf.raw); + err = this->write_register((uint8_t) CommandRegisters::ALS_CONF_0, als_conf.raw_bytes, VEML_REG_SIZE); + if (err != i2c::ERROR_OK) { + ESP_LOGW(TAG, "Failed to turn on, I2C error %d", err); + return err; + } + + PSMRegister psm{0}; + psm.PSM = PSM::PSM_MODE_1; + psm.PSM_EN = false; + ESP_LOGV(TAG, "Setting PSM to 0x%04X", psm.raw); + err = this->write_register((uint8_t) CommandRegisters::PWR_SAVING, psm.raw_bytes, VEML_REG_SIZE); + if (err != i2c::ERROR_OK) { + ESP_LOGW(TAG, "Failed to set PSM, I2C error %d", err); + return err; + } + + return err; +} + +ErrorCode VEML7700Component::reconfigure_time_and_gain_(IntegrationTime time, Gain gain, bool shutdown) { + ESP_LOGV(TAG, "Reconfigure time and gain (%d ms, %s) %s", get_itime_ms(time), get_gain_str(gain), + shutdown ? "Shutting down" : "Turning back on"); + + ConfigurationRegister als_conf{0}; + als_conf.raw = 0; + + // We have to before changing parameters + als_conf.ALS_SD = shutdown; + als_conf.ALS_INT_EN = false; + als_conf.ALS_PERS = Persistence::PERSISTENCE_1; + als_conf.ALS_IT = time; + als_conf.ALS_GAIN = gain; + auto err = this->write_register((uint8_t) CommandRegisters::ALS_CONF_0, als_conf.raw_bytes, VEML_REG_SIZE); + if (err != i2c::ERROR_OK) { + ESP_LOGW(TAG, "%s failed", shutdown ? "Shutdown" : "Turn on"); + } + + return err; +} + +ErrorCode VEML7700Component::read_sensor_output_(Readings &data) { + auto als_err = + this->read_register((uint8_t) CommandRegisters::ALS, (uint8_t *) &data.als_counts, VEML_REG_SIZE, false); + if (als_err != i2c::ERROR_OK) { + ESP_LOGW(TAG, "Error reading ALS register, err = %d", als_err); + } + auto white_err = + this->read_register((uint8_t) CommandRegisters::WHITE, (uint8_t *) &data.white_counts, VEML_REG_SIZE, false); + if (white_err != i2c::ERROR_OK) { + ESP_LOGW(TAG, "Error reading WHITE register, err = %d", white_err); + } + + ConfigurationRegister conf{0}; + auto err = + this->read_register((uint8_t) CommandRegisters::ALS_CONF_0, (uint8_t *) conf.raw_bytes, VEML_REG_SIZE, false); + if (err != i2c::ERROR_OK) { + ESP_LOGW(TAG, "Error reading ALS_CONF_0 register, err = %d", white_err); + } + data.actual_time = conf.ALS_IT; + data.actual_gain = conf.ALS_GAIN; + + ESP_LOGV(TAG, "Data from sensors: ALS = %d, WHITE = %d, Gain = %s, Time = %d ms", data.als_counts, data.white_counts, + get_gain_str(data.actual_gain), get_itime_ms(data.actual_time)); + return std::max(als_err, white_err); +} + +bool VEML7700Component::are_adjustments_required_(Readings &data) { + // skip first sample in auto mode - + // we need to reconfigure device after last measurement + if (this->state_ == State::COLLECTING_DATA_AUTO) + return true; + + if (!this->automatic_mode_enabled_) + return false; + + // Recommended thresholds as per datasheet + static constexpr uint16_t LOW_INTENSITY_THRESHOLD = 100; + static constexpr uint16_t HIGH_INTENSITY_THRESHOLD = 10000; + + static const IntegrationTime TIMES[INTEGRATION_TIMES_COUNT] = {INTEGRATION_TIME_25MS, INTEGRATION_TIME_50MS, + INTEGRATION_TIME_100MS, INTEGRATION_TIME_200MS, + INTEGRATION_TIME_400MS, INTEGRATION_TIME_800MS}; + static const Gain GAINS[GAINS_COUNT] = {X_1_8, X_1_4, X_1, X_2}; + + if (data.als_counts <= LOW_INTENSITY_THRESHOLD) { + Gain next_gain = get_next(GAINS, data.actual_gain); + if (next_gain != data.actual_gain) { + data.actual_gain = next_gain; + return true; + } + IntegrationTime next_time = get_next(TIMES, data.actual_time); + if (next_time != data.actual_time) { + data.actual_time = next_time; + return true; + } + } else if (data.als_counts >= HIGH_INTENSITY_THRESHOLD) { + Gain prev_gain = get_prev(GAINS, data.actual_gain); + if (prev_gain != data.actual_gain) { + data.actual_gain = prev_gain; + return true; + } + IntegrationTime prev_time = get_prev(TIMES, data.actual_time); + if (prev_time != data.actual_time) { + data.actual_time = prev_time; + return true; + } + } + + // Counts are either good (between thresholds) + // or there is no room to change sensitivity anymore + return false; +} + +void VEML7700Component::apply_lux_calculation_(Readings &data) { + static const float MAX_GAIN = 2.0f; + static const float MAX_ITIME_MS = 800.0f; + static const float MAX_LX_RESOLUTION = 0.0036f; + float lux_resolution = (MAX_ITIME_MS / (float) get_itime_ms(data.actual_time)) * + (MAX_GAIN / get_gain_coeff(data.actual_gain)) * MAX_LX_RESOLUTION; + ESP_LOGV(TAG, "Lux resolution for (%d, %s) = %.4f ", get_itime_ms(data.actual_time), get_gain_str(data.actual_gain), + lux_resolution); + + data.als_lux = lux_resolution * (float) data.als_counts; + data.white_lux = lux_resolution * (float) data.white_counts; + data.fake_infrared_lux = reduce_to_zero(data.white_lux, data.als_lux); + + ESP_LOGV(TAG, "%s mode - ALS = %.1f lx, WHITE = %.1f lx, FAKE_IR = %.1f lx", + this->automatic_mode_enabled_ ? "Automatic" : "Manual", data.als_lux, data.white_lux, + data.fake_infrared_lux); +} + +void VEML7700Component::apply_lux_compensation_(Readings &data) { + if (!this->lux_compensation_enabled_) + return; + auto &local_data = data; + // Always apply correction for G1/4 and G1/8 + // Other Gains G1 and G2 are not supposed to be used for lux > 1000, + // corrections may help, but not a lot. + // + // "Illumination values higher than 1000 lx show non-linearity. + // This non-linearity is the same for all sensors, so a compensation formula can be applied + // if this light level is exceeded" + auto compensate = [&local_data](float &lux) { + auto calculate_high_lux_compensation = [](float lux_veml) -> float { + return (((6.0135e-13 * lux_veml - 9.3924e-9) * lux_veml + 8.1488e-5) * lux_veml + 1.0023) * lux_veml; + }; + + if (lux > 1000.0f || local_data.actual_gain == Gain::X_1_8 || local_data.actual_gain == Gain::X_1_4) { + lux = calculate_high_lux_compensation(lux); + } + }; + + compensate(data.als_lux); + compensate(data.white_lux); + data.fake_infrared_lux = reduce_to_zero(data.white_lux, data.als_lux); + + ESP_LOGV(TAG, "Lux compensation - ALS = %.1f lx, WHITE = %.1f lx, FAKE_IR = %.1f lx", data.als_lux, data.white_lux, + data.fake_infrared_lux); +} + +void VEML7700Component::apply_glass_attenuation_(Readings &data) { + data.als_lux *= this->glass_attenuation_factor_; + data.white_lux *= this->glass_attenuation_factor_; + data.fake_infrared_lux = reduce_to_zero(data.white_lux, data.als_lux); + ESP_LOGV(TAG, "Glass attenuation - ALS = %.1f lx, WHITE = %.1f lx, FAKE_IR = %.1f lx", data.als_lux, data.white_lux, + data.fake_infrared_lux); +} + +void VEML7700Component::publish_data_part_1_(Readings &data) { + if (this->ambient_light_sensor_ != nullptr) { + this->ambient_light_sensor_->publish_state(data.als_lux); + } + if (this->white_sensor_ != nullptr) { + this->white_sensor_->publish_state(data.white_lux); + } +} + +void VEML7700Component::publish_data_part_2_(Readings &data) { + if (this->fake_infrared_sensor_ != nullptr) { + this->fake_infrared_sensor_->publish_state(data.fake_infrared_lux); + } + if (this->ambient_light_counts_sensor_ != nullptr) { + this->ambient_light_counts_sensor_->publish_state(data.als_counts); + } + if (this->white_counts_sensor_ != nullptr) { + this->white_counts_sensor_->publish_state(data.white_counts); + } +} + +void VEML7700Component::publish_data_part_3_(Readings &data) { + if (this->actual_gain_sensor_ != nullptr) { + this->actual_gain_sensor_->publish_state(get_gain_coeff(data.actual_gain)); + } + if (this->actual_integration_time_sensor_ != nullptr) { + this->actual_integration_time_sensor_->publish_state(get_itime_ms(data.actual_time)); + } +} +} // namespace veml7700 +} // namespace esphome diff --git a/esphome/components/veml7700/veml7700.h b/esphome/components/veml7700/veml7700.h new file mode 100644 index 0000000000..fe5e1158e3 --- /dev/null +++ b/esphome/components/veml7700/veml7700.h @@ -0,0 +1,202 @@ +#pragma once + +#include "esphome/components/i2c/i2c.h" +#include "esphome/components/sensor/sensor.h" +#include "esphome/core/component.h" +#include "esphome/core/optional.h" + +namespace esphome { +namespace veml7700 { + +using esphome::i2c::ErrorCode; + +// +// Datasheet: https://www.vishay.com/docs/84286/veml7700.pdf +// + +enum class CommandRegisters : uint8_t { + ALS_CONF_0 = 0x00, // W: ALS gain, integration time, interrupt, and shutdown + ALS_WH = 0x01, // W: ALS high threshold window setting + ALS_WL = 0x02, // W: ALS low threshold window setting + PWR_SAVING = 0x03, // W: Set (15 : 3) 0000 0000 0000 0b + ALS = 0x04, // R: MSB, LSB data of whole ALS 16 bits + WHITE = 0x05, // R: MSB, LSB data of whole WHITE 16 bits + ALS_INT = 0x06 // R: ALS INT trigger event +}; + +enum Gain : uint8_t { + X_1 = 0, + X_2 = 1, + X_1_8 = 2, + X_1_4 = 3, +}; +const uint8_t GAINS_COUNT = 4; + +enum IntegrationTime : uint8_t { + INTEGRATION_TIME_25MS = 0b1100, + INTEGRATION_TIME_50MS = 0b1000, + INTEGRATION_TIME_100MS = 0b0000, + INTEGRATION_TIME_200MS = 0b0001, + INTEGRATION_TIME_400MS = 0b0010, + INTEGRATION_TIME_800MS = 0b0011, +}; +const uint8_t INTEGRATION_TIMES_COUNT = 6; + +enum Persistence : uint8_t { + PERSISTENCE_1 = 0, + PERSISTENCE_2 = 1, + PERSISTENCE_4 = 2, + PERSISTENCE_8 = 3, +}; + +enum PSM : uint8_t { + PSM_MODE_1 = 0, + PSM_MODE_2 = 1, + PSM_MODE_3 = 2, + PSM_MODE_4 = 3, +}; + +// The following section with bit-fields brings GCC compilation 'notes' about padding bytes due to bug in older GCC back +// in 2009 "Packed bit-fields of type char were not properly bit-packed on many targets prior to GCC 4.4" Even more to +// this - this message can't be disabled with "#pragma GCC diagnostic ignored" due to another bug which was only fixed +// in GCC 13 in 2022 :) No actions required, it is just a note. The code is correct. + +// +// VEML7700_CR_ALS_CONF_0 Register (0x00) +// +union ConfigurationRegister { + uint16_t raw; + uint8_t raw_bytes[2]; + struct { + bool ALS_SD : 1; // ALS shut down setting: 0 = ALS power on, 1 = ALS shut + // down + bool ALS_INT_EN : 1; // ALS interrupt enable setting: 0 = ALS INT disable, 1 + // = ALS INT enable + bool reserved_2 : 1; // 0 + bool reserved_3 : 1; // 0 + Persistence ALS_PERS : 2; // 00 - 1, 01- 2, 10 - 4, 11 - 8 + IntegrationTime ALS_IT : 4; // ALS integration time setting + bool reserved_10 : 1; // 0 + Gain ALS_GAIN : 2; // Gain selection + bool reserved_13 : 1; // 0 + bool reserved_14 : 1; // 0 + bool reserved_15 : 1; // 0 + } __attribute__((packed)); +}; + +// +// Power Saving Mode: PSM Register (0x03) +// +union PSMRegister { + uint16_t raw; + uint8_t raw_bytes[2]; + struct { + bool PSM_EN : 1; + uint8_t PSM : 2; + uint16_t reserved : 13; + } __attribute__((packed)); +}; + +class VEML7700Component : public PollingComponent, public i2c::I2CDevice { + public: + // + // EspHome framework functions + // + float get_setup_priority() const override { return setup_priority::DATA; } + void setup() override; + void dump_config() override; + void update() override; + void loop() override; + + // + // Configuration setters + // + void set_gain(Gain gain) { this->gain_ = gain; } + void set_integration_time(IntegrationTime time) { this->integration_time_ = time; } + void set_enable_automatic_mode(bool enable) { this->automatic_mode_enabled_ = enable; } + void set_enable_lux_compensation(bool enable) { this->lux_compensation_enabled_ = enable; } + void set_glass_attenuation_factor(float factor) { this->glass_attenuation_factor_ = factor; } + + void set_ambient_light_sensor(sensor::Sensor *sensor) { this->ambient_light_sensor_ = sensor; } + void set_ambient_light_counts_sensor(sensor::Sensor *sensor) { this->ambient_light_counts_sensor_ = sensor; } + void set_white_sensor(sensor::Sensor *sensor) { this->white_sensor_ = sensor; } + void set_white_counts_sensor(sensor::Sensor *sensor) { this->white_counts_sensor_ = sensor; } + void set_infrared_sensor(sensor::Sensor *sensor) { this->fake_infrared_sensor_ = sensor; } + void set_actual_gain_sensor(sensor::Sensor *sensor) { this->actual_gain_sensor_ = sensor; } + void set_actual_integration_time_sensor(sensor::Sensor *sensor) { this->actual_integration_time_sensor_ = sensor; } + + protected: + // + // Internal state machine, used to split all the actions into + // small steps in loop() to make sure we are not blocking execution + // + enum class State : uint8_t { + NOT_INITIALIZED, + INITIAL_SETUP_COMPLETED, + IDLE, + COLLECTING_DATA, + COLLECTING_DATA_AUTO, + DATA_COLLECTED, + ADJUSTMENT_NEEDED, + ADJUSTMENT_IN_PROGRESS, + READY_TO_APPLY_ADJUSTMENTS, + READY_TO_PUBLISH_PART_1, + READY_TO_PUBLISH_PART_2, + READY_TO_PUBLISH_PART_3 + } state_{State::NOT_INITIALIZED}; + + // + // Current measurements data + // + struct Readings { + uint16_t als_counts{0}; + uint16_t white_counts{0}; + IntegrationTime actual_time{INTEGRATION_TIME_100MS}; + Gain actual_gain{X_1_8}; + float als_lux{0}; + float white_lux{0}; + float fake_infrared_lux{0}; + ErrorCode err{i2c::ERROR_OK}; + } readings_; + + // + // Device interaction + // + ErrorCode configure_(); + ErrorCode reconfigure_time_and_gain_(IntegrationTime time, Gain gain, bool shutdown); + ErrorCode read_sensor_output_(Readings &data); + + // + // Working with the data + // + bool are_adjustments_required_(Readings &data); + void apply_lux_calculation_(Readings &data); + void apply_lux_compensation_(Readings &data); + void apply_glass_attenuation_(Readings &data); + void publish_data_part_1_(Readings &data); + void publish_data_part_2_(Readings &data); + void publish_data_part_3_(Readings &data); + + // + // Component configuration + // + bool automatic_mode_enabled_{true}; + bool lux_compensation_enabled_{true}; + float glass_attenuation_factor_{1.0}; + IntegrationTime integration_time_{INTEGRATION_TIME_100MS}; + Gain gain_{X_1}; + + // + // Sensors for publishing data + // + sensor::Sensor *ambient_light_sensor_{nullptr}; // Human eye range 500-600 nm, lx + sensor::Sensor *ambient_light_counts_sensor_{nullptr}; // Raw counts + sensor::Sensor *white_sensor_{nullptr}; // Wide range 450-950 nm, lx + sensor::Sensor *white_counts_sensor_{nullptr}; // Raw counts + sensor::Sensor *fake_infrared_sensor_{nullptr}; // Artificial. = WHITE lx - ALS lx. + sensor::Sensor *actual_gain_sensor_{nullptr}; // Actual gain multiplier for the measurement + sensor::Sensor *actual_integration_time_sensor_{nullptr}; // Actual integration time for the measurement +}; + +} // namespace veml7700 +} // namespace esphome diff --git a/tests/components/veml7700/common.yaml b/tests/components/veml7700/common.yaml new file mode 100644 index 0000000000..6620c8d7e1 --- /dev/null +++ b/tests/components/veml7700/common.yaml @@ -0,0 +1,10 @@ +sensor: + - platform: veml7700 + address: 0x10 + i2c_id: i2c_veml7700 + ambient_light: Ambient light + ambient_light_counts: Ambient light counts + full_spectrum: Full spectrum + full_spectrum_counts: Full spectrum counts + actual_integration_time: Actual integration time + actual_gain: Actual gain diff --git a/tests/components/veml7700/test.esp32-c3-idf.yaml b/tests/components/veml7700/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..ce0fa0125b --- /dev/null +++ b/tests/components/veml7700/test.esp32-c3-idf.yaml @@ -0,0 +1,6 @@ +i2c: + - id: i2c_veml7700 + scl: 5 + sda: 4 + +<<: !include common.yaml diff --git a/tests/components/veml7700/test.esp32-c3.yaml b/tests/components/veml7700/test.esp32-c3.yaml new file mode 100644 index 0000000000..ce0fa0125b --- /dev/null +++ b/tests/components/veml7700/test.esp32-c3.yaml @@ -0,0 +1,6 @@ +i2c: + - id: i2c_veml7700 + scl: 5 + sda: 4 + +<<: !include common.yaml diff --git a/tests/components/veml7700/test.esp32-idf.yaml b/tests/components/veml7700/test.esp32-idf.yaml new file mode 100644 index 0000000000..4b812a1392 --- /dev/null +++ b/tests/components/veml7700/test.esp32-idf.yaml @@ -0,0 +1,6 @@ +i2c: + - id: i2c_veml7700 + scl: 16 + sda: 17 + +<<: !include common.yaml diff --git a/tests/components/veml7700/test.esp32.yaml b/tests/components/veml7700/test.esp32.yaml new file mode 100644 index 0000000000..4b812a1392 --- /dev/null +++ b/tests/components/veml7700/test.esp32.yaml @@ -0,0 +1,6 @@ +i2c: + - id: i2c_veml7700 + scl: 16 + sda: 17 + +<<: !include common.yaml diff --git a/tests/components/veml7700/test.esp8266.yaml b/tests/components/veml7700/test.esp8266.yaml new file mode 100644 index 0000000000..ce0fa0125b --- /dev/null +++ b/tests/components/veml7700/test.esp8266.yaml @@ -0,0 +1,6 @@ +i2c: + - id: i2c_veml7700 + scl: 5 + sda: 4 + +<<: !include common.yaml diff --git a/tests/components/veml7700/test.rp2040.yaml b/tests/components/veml7700/test.rp2040.yaml new file mode 100644 index 0000000000..ce0fa0125b --- /dev/null +++ b/tests/components/veml7700/test.rp2040.yaml @@ -0,0 +1,6 @@ +i2c: + - id: i2c_veml7700 + scl: 5 + sda: 4 + +<<: !include common.yaml From 4bbde8357a65c0b2060f459b3b1f6e7bc228e4e2 Mon Sep 17 00:00:00 2001 From: Citric Lee <37475446+limengdu@users.noreply.github.com> Date: Tue, 12 Mar 2024 11:33:40 +0800 Subject: [PATCH 1059/2101] Add Seeed Studio mmWave Kit MR24HPC1 (#5761) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Co-authored-by: Peter Pan --- CODEOWNERS | 1 + esphome/components/seeed_mr24hpc1/__init__.py | 51 + .../seeed_mr24hpc1/binary_sensor.py | 23 + .../seeed_mr24hpc1/button/__init__.py | 42 + .../button/custom_mode_end_button.cpp | 9 + .../button/custom_mode_end_button.h | 18 + .../seeed_mr24hpc1/button/restart_button.cpp | 9 + .../seeed_mr24hpc1/button/restart_button.h | 18 + .../seeed_mr24hpc1/number/__init__.py | 132 +++ .../number/custom_mode_number.cpp | 12 + .../number/custom_mode_number.h | 18 + .../number/custom_unman_time_number.cpp | 9 + .../number/custom_unman_time_number.h | 18 + .../number/existence_threshold_number.cpp | 9 + .../number/existence_threshold_number.h | 18 + .../number/motion_threshold_number.cpp | 9 + .../number/motion_threshold_number.h | 18 + .../number/motion_trigger_time_number.cpp | 9 + .../number/motion_trigger_time_number.h | 18 + .../number/motiontorest_time_number.cpp | 9 + .../number/motiontorest_time_number.h | 18 + .../number/sensitivity_number.cpp | 9 + .../number/sensitivity_number.h | 18 + .../seeed_mr24hpc1/seeed_mr24hpc1.cpp | 890 ++++++++++++++++++ .../seeed_mr24hpc1/seeed_mr24hpc1.h | 217 +++++ .../seeed_mr24hpc1/seeed_mr24hpc1_constants.h | 173 ++++ .../seeed_mr24hpc1/select/__init__.py | 103 ++ .../select/existence_boundary_select.cpp | 15 + .../select/existence_boundary_select.h | 18 + .../select/motion_boundary_select.cpp | 15 + .../select/motion_boundary_select.h | 18 + .../select/scene_mode_select.cpp | 15 + .../seeed_mr24hpc1/select/scene_mode_select.h | 18 + .../select/unman_time_select.cpp | 15 + .../seeed_mr24hpc1/select/unman_time_select.h | 18 + esphome/components/seeed_mr24hpc1/sensor.py | 82 ++ .../seeed_mr24hpc1/switch/__init__.py | 32 + .../switch/underlyFuc_switch.cpp | 12 + .../seeed_mr24hpc1/switch/underlyFuc_switch.h | 18 + .../components/seeed_mr24hpc1/text_sensor.py | 74 ++ tests/components/seeed_mr24hpc1/common.yaml | 92 ++ .../seeed_mr24hpc1/test.esp32-c3-idf.yaml | 5 + .../seeed_mr24hpc1/test.esp32-c3.yaml | 5 + 43 files changed, 2330 insertions(+) create mode 100644 esphome/components/seeed_mr24hpc1/__init__.py create mode 100644 esphome/components/seeed_mr24hpc1/binary_sensor.py create mode 100644 esphome/components/seeed_mr24hpc1/button/__init__.py create mode 100644 esphome/components/seeed_mr24hpc1/button/custom_mode_end_button.cpp create mode 100644 esphome/components/seeed_mr24hpc1/button/custom_mode_end_button.h create mode 100644 esphome/components/seeed_mr24hpc1/button/restart_button.cpp create mode 100644 esphome/components/seeed_mr24hpc1/button/restart_button.h create mode 100644 esphome/components/seeed_mr24hpc1/number/__init__.py create mode 100644 esphome/components/seeed_mr24hpc1/number/custom_mode_number.cpp create mode 100644 esphome/components/seeed_mr24hpc1/number/custom_mode_number.h create mode 100644 esphome/components/seeed_mr24hpc1/number/custom_unman_time_number.cpp create mode 100644 esphome/components/seeed_mr24hpc1/number/custom_unman_time_number.h create mode 100644 esphome/components/seeed_mr24hpc1/number/existence_threshold_number.cpp create mode 100644 esphome/components/seeed_mr24hpc1/number/existence_threshold_number.h create mode 100644 esphome/components/seeed_mr24hpc1/number/motion_threshold_number.cpp create mode 100644 esphome/components/seeed_mr24hpc1/number/motion_threshold_number.h create mode 100644 esphome/components/seeed_mr24hpc1/number/motion_trigger_time_number.cpp create mode 100644 esphome/components/seeed_mr24hpc1/number/motion_trigger_time_number.h create mode 100644 esphome/components/seeed_mr24hpc1/number/motiontorest_time_number.cpp create mode 100644 esphome/components/seeed_mr24hpc1/number/motiontorest_time_number.h create mode 100644 esphome/components/seeed_mr24hpc1/number/sensitivity_number.cpp create mode 100644 esphome/components/seeed_mr24hpc1/number/sensitivity_number.h create mode 100644 esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp create mode 100644 esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.h create mode 100644 esphome/components/seeed_mr24hpc1/seeed_mr24hpc1_constants.h create mode 100644 esphome/components/seeed_mr24hpc1/select/__init__.py create mode 100644 esphome/components/seeed_mr24hpc1/select/existence_boundary_select.cpp create mode 100644 esphome/components/seeed_mr24hpc1/select/existence_boundary_select.h create mode 100644 esphome/components/seeed_mr24hpc1/select/motion_boundary_select.cpp create mode 100644 esphome/components/seeed_mr24hpc1/select/motion_boundary_select.h create mode 100644 esphome/components/seeed_mr24hpc1/select/scene_mode_select.cpp create mode 100644 esphome/components/seeed_mr24hpc1/select/scene_mode_select.h create mode 100644 esphome/components/seeed_mr24hpc1/select/unman_time_select.cpp create mode 100644 esphome/components/seeed_mr24hpc1/select/unman_time_select.h create mode 100644 esphome/components/seeed_mr24hpc1/sensor.py create mode 100644 esphome/components/seeed_mr24hpc1/switch/__init__.py create mode 100644 esphome/components/seeed_mr24hpc1/switch/underlyFuc_switch.cpp create mode 100644 esphome/components/seeed_mr24hpc1/switch/underlyFuc_switch.h create mode 100644 esphome/components/seeed_mr24hpc1/text_sensor.py create mode 100644 tests/components/seeed_mr24hpc1/common.yaml create mode 100644 tests/components/seeed_mr24hpc1/test.esp32-c3-idf.yaml create mode 100644 tests/components/seeed_mr24hpc1/test.esp32-c3.yaml diff --git a/CODEOWNERS b/CODEOWNERS index e31dd16077..64005b1a81 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -290,6 +290,7 @@ esphome/components/scd4x/* @martgras @sjtrny esphome/components/script/* @esphome/core esphome/components/sdm_meter/* @jesserockz @polyfaces esphome/components/sdp3x/* @Azimath +esphome/components/seeed_mr24hpc1/* @limengdu esphome/components/selec_meter/* @sourabhjaiswal esphome/components/select/* @esphome/core esphome/components/sen0321/* @notjj diff --git a/esphome/components/seeed_mr24hpc1/__init__.py b/esphome/components/seeed_mr24hpc1/__init__.py new file mode 100644 index 0000000000..52b971e7e4 --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/__init__.py @@ -0,0 +1,51 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import uart +from esphome.const import CONF_ID + +DEPENDENCIES = ["uart"] +# is the code owner of the relevant code base +CODEOWNERS = ["@limengdu"] +# The current component or platform can be configured or defined multiple times in the same configuration file. +MULTI_CONF = True + +# This line of code creates a new namespace called mr24hpc1_ns. +# This namespace will be used as a prefix for all classes, functions and variables associated with the mr24hpc1_ns component, ensuring that they do not conflict with the names of other components. +mr24hpc1_ns = cg.esphome_ns.namespace("seeed_mr24hpc1") +# This MR24HPC1Component class will be a periodically polled UART device +MR24HPC1Component = mr24hpc1_ns.class_( + "MR24HPC1Component", cg.Component, uart.UARTDevice +) + +CONF_MR24HPC1_ID = "mr24hpc1_id" + +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(MR24HPC1Component), + } + ) + .extend(uart.UART_DEVICE_SCHEMA) + .extend(cv.COMPONENT_SCHEMA) +) + +# A verification mode was created to verify the configuration parameters of a UART device named "seeed_mr24hpc1". +# 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", + require_tx=True, + require_rx=True, + parity="NONE", + stop_bits=1, +) + + +# The async def keyword is used to define a concurrent function. +# Concurrent functions are special functions designed to work with Python's asyncio library to support asynchronous I/O operations. +async def to_code(config): + # This line of code creates a new Pvariable (a Python object representing a C++ variable) with the variable's ID taken from the configuration. + var = cg.new_Pvariable(config[CONF_ID]) + # This line of code registers the newly created Pvariable as a component so that ESPHome can manage it at runtime. + await cg.register_component(var, config) + # This line of code registers the newly created Pvariable as a device. + await uart.register_uart_device(var, config) diff --git a/esphome/components/seeed_mr24hpc1/binary_sensor.py b/esphome/components/seeed_mr24hpc1/binary_sensor.py new file mode 100644 index 0000000000..e3e54d03f9 --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/binary_sensor.py @@ -0,0 +1,23 @@ +import esphome.codegen as cg +from esphome.components import binary_sensor +import esphome.config_validation as cv +from esphome.const import ( + DEVICE_CLASS_OCCUPANCY, +) +from . import CONF_MR24HPC1_ID, MR24HPC1Component + +CONF_HAS_TARGET = "has_target" + +CONFIG_SCHEMA = { + cv.GenerateID(CONF_MR24HPC1_ID): cv.use_id(MR24HPC1Component), + cv.Optional(CONF_HAS_TARGET): binary_sensor.binary_sensor_schema( + device_class=DEVICE_CLASS_OCCUPANCY, icon="mdi:motion-sensor" + ), +} + + +async def to_code(config): + mr24hpc1_component = await cg.get_variable(config[CONF_MR24HPC1_ID]) + if has_target_config := config.get(CONF_HAS_TARGET): + sens = await binary_sensor.new_binary_sensor(has_target_config) + cg.add(mr24hpc1_component.set_has_target_binary_sensor(sens)) diff --git a/esphome/components/seeed_mr24hpc1/button/__init__.py b/esphome/components/seeed_mr24hpc1/button/__init__.py new file mode 100644 index 0000000000..0a0e7a1865 --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/button/__init__.py @@ -0,0 +1,42 @@ +import esphome.codegen as cg +from esphome.components import button +import esphome.config_validation as cv +from esphome.const import ( + DEVICE_CLASS_RESTART, + ENTITY_CATEGORY_CONFIG, + ICON_RESTART_ALERT, +) +from .. import CONF_MR24HPC1_ID, MR24HPC1Component, mr24hpc1_ns + +RestartButton = mr24hpc1_ns.class_("RestartButton", button.Button) +CustomSetEndButton = mr24hpc1_ns.class_("CustomSetEndButton", button.Button) + +CONF_RESTART = "restart" +CONF_CUSTOM_SET_END = "custom_set_end" + +CONFIG_SCHEMA = { + cv.GenerateID(CONF_MR24HPC1_ID): cv.use_id(MR24HPC1Component), + cv.Optional(CONF_RESTART): button.button_schema( + RestartButton, + device_class=DEVICE_CLASS_RESTART, + entity_category=ENTITY_CATEGORY_CONFIG, + icon=ICON_RESTART_ALERT, + ), + cv.Optional(CONF_CUSTOM_SET_END): button.button_schema( + CustomSetEndButton, + entity_category=ENTITY_CATEGORY_CONFIG, + icon="mdi:cog", + ), +} + + +async def to_code(config): + mr24hpc1_component = await cg.get_variable(config[CONF_MR24HPC1_ID]) + if restart_config := config.get(CONF_RESTART): + b = await button.new_button(restart_config) + await cg.register_parented(b, config[CONF_MR24HPC1_ID]) + cg.add(mr24hpc1_component.set_restart_button(b)) + if custom_set_end_config := config.get(CONF_CUSTOM_SET_END): + b = await button.new_button(custom_set_end_config) + await cg.register_parented(b, config[CONF_MR24HPC1_ID]) + cg.add(mr24hpc1_component.set_custom_set_end_button(b)) diff --git a/esphome/components/seeed_mr24hpc1/button/custom_mode_end_button.cpp b/esphome/components/seeed_mr24hpc1/button/custom_mode_end_button.cpp new file mode 100644 index 0000000000..0ae8889247 --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/button/custom_mode_end_button.cpp @@ -0,0 +1,9 @@ +#include "custom_mode_end_button.h" + +namespace esphome { +namespace seeed_mr24hpc1 { + +void CustomSetEndButton::press_action() { this->parent_->set_custom_end_mode(); } + +} // namespace seeed_mr24hpc1 +} // namespace esphome diff --git a/esphome/components/seeed_mr24hpc1/button/custom_mode_end_button.h b/esphome/components/seeed_mr24hpc1/button/custom_mode_end_button.h new file mode 100644 index 0000000000..a1701d8581 --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/button/custom_mode_end_button.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/button/button.h" +#include "../seeed_mr24hpc1.h" + +namespace esphome { +namespace seeed_mr24hpc1 { + +class CustomSetEndButton : public button::Button, public Parented { + public: + CustomSetEndButton() = default; + + protected: + void press_action() override; +}; + +} // namespace seeed_mr24hpc1 +} // namespace esphome diff --git a/esphome/components/seeed_mr24hpc1/button/restart_button.cpp b/esphome/components/seeed_mr24hpc1/button/restart_button.cpp new file mode 100644 index 0000000000..6c4a070d1c --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/button/restart_button.cpp @@ -0,0 +1,9 @@ +#include "restart_button.h" + +namespace esphome { +namespace seeed_mr24hpc1 { + +void RestartButton::press_action() { this->parent_->set_restart(); } + +} // namespace seeed_mr24hpc1 +} // namespace esphome diff --git a/esphome/components/seeed_mr24hpc1/button/restart_button.h b/esphome/components/seeed_mr24hpc1/button/restart_button.h new file mode 100644 index 0000000000..8a2ec2087c --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/button/restart_button.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/button/button.h" +#include "../seeed_mr24hpc1.h" + +namespace esphome { +namespace seeed_mr24hpc1 { + +class RestartButton : public button::Button, public Parented { + public: + RestartButton() = default; + + protected: + void press_action() override; +}; + +} // namespace seeed_mr24hpc1 +} // namespace esphome diff --git a/esphome/components/seeed_mr24hpc1/number/__init__.py b/esphome/components/seeed_mr24hpc1/number/__init__.py new file mode 100644 index 0000000000..d9dfcb19a5 --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/number/__init__.py @@ -0,0 +1,132 @@ +import esphome.codegen as cg +from esphome.components import number +import esphome.config_validation as cv +from esphome.const import ( + ENTITY_CATEGORY_CONFIG, +) +from .. import CONF_MR24HPC1_ID, MR24HPC1Component, mr24hpc1_ns + +SensitivityNumber = mr24hpc1_ns.class_("SensitivityNumber", number.Number) +CustomModeNumber = mr24hpc1_ns.class_("CustomModeNumber", number.Number) +ExistenceThresholdNumber = mr24hpc1_ns.class_("ExistenceThresholdNumber", number.Number) +MotionThresholdNumber = mr24hpc1_ns.class_("MotionThresholdNumber", number.Number) +MotionTriggerTimeNumber = mr24hpc1_ns.class_("MotionTriggerTimeNumber", number.Number) +MotionToRestTimeNumber = mr24hpc1_ns.class_("MotionToRestTimeNumber", number.Number) +CustomUnmanTimeNumber = mr24hpc1_ns.class_("CustomUnmanTimeNumber", number.Number) + +CONF_SENSITIVITY = "sensitivity" +CONF_CUSTOM_MODE = "custom_mode" +CONF_EXISTENCE_THRESHOLD = "existence_threshold" +CONF_MOTION_THRESHOLD = "motion_threshold" +CONF_MOTION_TRIGGER = "motion_trigger" +CONF_MOTION_TO_REST = "motion_to_rest" +CONF_CUSTOM_UNMAN_TIME = "custom_unman_time" + +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(CONF_MR24HPC1_ID): cv.use_id(MR24HPC1Component), + cv.Optional(CONF_SENSITIVITY): number.number_schema( + SensitivityNumber, + entity_category=ENTITY_CATEGORY_CONFIG, + icon="mdi:archive-check-outline", + ), + cv.Optional(CONF_CUSTOM_MODE): number.number_schema( + CustomModeNumber, + entity_category=ENTITY_CATEGORY_CONFIG, + icon="mdi:cog", + ), + cv.Optional(CONF_EXISTENCE_THRESHOLD): number.number_schema( + ExistenceThresholdNumber, + entity_category=ENTITY_CATEGORY_CONFIG, + ), + cv.Optional(CONF_MOTION_THRESHOLD): number.number_schema( + MotionThresholdNumber, + entity_category=ENTITY_CATEGORY_CONFIG, + ), + cv.Optional(CONF_MOTION_TRIGGER): number.number_schema( + MotionTriggerTimeNumber, + entity_category=ENTITY_CATEGORY_CONFIG, + icon="mdi:camera-timer", + unit_of_measurement="ms", + ), + cv.Optional(CONF_MOTION_TO_REST): number.number_schema( + MotionToRestTimeNumber, + entity_category=ENTITY_CATEGORY_CONFIG, + icon="mdi:camera-timer", + unit_of_measurement="ms", + ), + cv.Optional(CONF_CUSTOM_UNMAN_TIME): number.number_schema( + CustomUnmanTimeNumber, + entity_category=ENTITY_CATEGORY_CONFIG, + icon="mdi:camera-timer", + unit_of_measurement="s", + ), + } +) + + +async def to_code(config): + mr24hpc1_component = await cg.get_variable(config[CONF_MR24HPC1_ID]) + if sensitivity_config := config.get(CONF_SENSITIVITY): + n = await number.new_number( + sensitivity_config, + min_value=0, + max_value=3, + step=1, + ) + await cg.register_parented(n, mr24hpc1_component) + cg.add(mr24hpc1_component.set_sensitivity_number(n)) + if custom_mode_config := config.get(CONF_CUSTOM_MODE): + n = await number.new_number( + custom_mode_config, + min_value=0, + max_value=4, + step=1, + ) + await cg.register_parented(n, mr24hpc1_component) + cg.add(mr24hpc1_component.set_custom_mode_number(n)) + if existence_threshold_config := config.get(CONF_EXISTENCE_THRESHOLD): + n = await number.new_number( + existence_threshold_config, + min_value=0, + max_value=250, + step=1, + ) + await cg.register_parented(n, mr24hpc1_component) + cg.add(mr24hpc1_component.set_existence_threshold_number(n)) + if motion_threshold_config := config.get(CONF_MOTION_THRESHOLD): + n = await number.new_number( + motion_threshold_config, + min_value=0, + max_value=250, + step=1, + ) + await cg.register_parented(n, mr24hpc1_component) + cg.add(mr24hpc1_component.set_motion_threshold_number(n)) + if motion_trigger_config := config.get(CONF_MOTION_TRIGGER): + n = await number.new_number( + motion_trigger_config, + min_value=0, + max_value=150, + step=1, + ) + await cg.register_parented(n, mr24hpc1_component) + cg.add(mr24hpc1_component.set_motion_trigger_number(n)) + if motion_to_rest_config := config.get(CONF_MOTION_TO_REST): + n = await number.new_number( + motion_to_rest_config, + min_value=0, + max_value=3000, + step=1, + ) + await cg.register_parented(n, mr24hpc1_component) + cg.add(mr24hpc1_component.set_motion_to_rest_number(n)) + if custom_unman_time_config := config.get(CONF_CUSTOM_UNMAN_TIME): + n = await number.new_number( + custom_unman_time_config, + min_value=0, + max_value=3600, + step=1, + ) + await cg.register_parented(n, mr24hpc1_component) + cg.add(mr24hpc1_component.set_custom_unman_time_number(n)) diff --git a/esphome/components/seeed_mr24hpc1/number/custom_mode_number.cpp b/esphome/components/seeed_mr24hpc1/number/custom_mode_number.cpp new file mode 100644 index 0000000000..0aebd8fb9f --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/number/custom_mode_number.cpp @@ -0,0 +1,12 @@ +#include "custom_mode_number.h" + +namespace esphome { +namespace seeed_mr24hpc1 { + +void CustomModeNumber::control(float value) { + this->publish_state(value); + this->parent_->set_custom_mode(value); +} + +} // namespace seeed_mr24hpc1 +} // namespace esphome diff --git a/esphome/components/seeed_mr24hpc1/number/custom_mode_number.h b/esphome/components/seeed_mr24hpc1/number/custom_mode_number.h new file mode 100644 index 0000000000..40ff3f201a --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/number/custom_mode_number.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/number/number.h" +#include "../seeed_mr24hpc1.h" + +namespace esphome { +namespace seeed_mr24hpc1 { + +class CustomModeNumber : public number::Number, public Parented { + public: + CustomModeNumber() = default; + + protected: + void control(float value) override; +}; + +} // namespace seeed_mr24hpc1 +} // namespace esphome diff --git a/esphome/components/seeed_mr24hpc1/number/custom_unman_time_number.cpp b/esphome/components/seeed_mr24hpc1/number/custom_unman_time_number.cpp new file mode 100644 index 0000000000..12a8ff69fa --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/number/custom_unman_time_number.cpp @@ -0,0 +1,9 @@ +#include "custom_unman_time_number.h" + +namespace esphome { +namespace seeed_mr24hpc1 { + +void CustomUnmanTimeNumber::control(float value) { this->parent_->set_custom_unman_time(value); } + +} // namespace seeed_mr24hpc1 +} // namespace esphome diff --git a/esphome/components/seeed_mr24hpc1/number/custom_unman_time_number.h b/esphome/components/seeed_mr24hpc1/number/custom_unman_time_number.h new file mode 100644 index 0000000000..6b871c4c13 --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/number/custom_unman_time_number.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/number/number.h" +#include "../seeed_mr24hpc1.h" + +namespace esphome { +namespace seeed_mr24hpc1 { + +class CustomUnmanTimeNumber : public number::Number, public Parented { + public: + CustomUnmanTimeNumber() = default; + + protected: + void control(float value) override; +}; + +} // namespace seeed_mr24hpc1 +} // namespace esphome diff --git a/esphome/components/seeed_mr24hpc1/number/existence_threshold_number.cpp b/esphome/components/seeed_mr24hpc1/number/existence_threshold_number.cpp new file mode 100644 index 0000000000..58ef56509e --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/number/existence_threshold_number.cpp @@ -0,0 +1,9 @@ +#include "existence_threshold_number.h" + +namespace esphome { +namespace seeed_mr24hpc1 { + +void ExistenceThresholdNumber::control(float value) { this->parent_->set_existence_threshold(value); } + +} // namespace seeed_mr24hpc1 +} // namespace esphome diff --git a/esphome/components/seeed_mr24hpc1/number/existence_threshold_number.h b/esphome/components/seeed_mr24hpc1/number/existence_threshold_number.h new file mode 100644 index 0000000000..656bad17de --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/number/existence_threshold_number.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/number/number.h" +#include "../seeed_mr24hpc1.h" + +namespace esphome { +namespace seeed_mr24hpc1 { + +class ExistenceThresholdNumber : public number::Number, public Parented { + public: + ExistenceThresholdNumber() = default; + + protected: + void control(float value) override; +}; + +} // namespace seeed_mr24hpc1 +} // namespace esphome diff --git a/esphome/components/seeed_mr24hpc1/number/motion_threshold_number.cpp b/esphome/components/seeed_mr24hpc1/number/motion_threshold_number.cpp new file mode 100644 index 0000000000..d252b4f01d --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/number/motion_threshold_number.cpp @@ -0,0 +1,9 @@ +#include "motion_threshold_number.h" + +namespace esphome { +namespace seeed_mr24hpc1 { + +void MotionThresholdNumber::control(float value) { this->parent_->set_motion_threshold(value); } + +} // namespace seeed_mr24hpc1 +} // namespace esphome diff --git a/esphome/components/seeed_mr24hpc1/number/motion_threshold_number.h b/esphome/components/seeed_mr24hpc1/number/motion_threshold_number.h new file mode 100644 index 0000000000..e8ae37b96f --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/number/motion_threshold_number.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/number/number.h" +#include "../seeed_mr24hpc1.h" + +namespace esphome { +namespace seeed_mr24hpc1 { + +class MotionThresholdNumber : public number::Number, public Parented { + public: + MotionThresholdNumber() = default; + + protected: + void control(float value) override; +}; + +} // namespace seeed_mr24hpc1 +} // namespace esphome diff --git a/esphome/components/seeed_mr24hpc1/number/motion_trigger_time_number.cpp b/esphome/components/seeed_mr24hpc1/number/motion_trigger_time_number.cpp new file mode 100644 index 0000000000..fc7659dc54 --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/number/motion_trigger_time_number.cpp @@ -0,0 +1,9 @@ +#include "motion_trigger_time_number.h" + +namespace esphome { +namespace seeed_mr24hpc1 { + +void MotionTriggerTimeNumber::control(float value) { this->parent_->set_motion_trigger_time(value); } + +} // namespace seeed_mr24hpc1 +} // namespace esphome diff --git a/esphome/components/seeed_mr24hpc1/number/motion_trigger_time_number.h b/esphome/components/seeed_mr24hpc1/number/motion_trigger_time_number.h new file mode 100644 index 0000000000..996356e237 --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/number/motion_trigger_time_number.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/number/number.h" +#include "../seeed_mr24hpc1.h" + +namespace esphome { +namespace seeed_mr24hpc1 { + +class MotionTriggerTimeNumber : public number::Number, public Parented { + public: + MotionTriggerTimeNumber() = default; + + protected: + void control(float value) override; +}; + +} // namespace seeed_mr24hpc1 +} // namespace esphome diff --git a/esphome/components/seeed_mr24hpc1/number/motiontorest_time_number.cpp b/esphome/components/seeed_mr24hpc1/number/motiontorest_time_number.cpp new file mode 100644 index 0000000000..f598e6686c --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/number/motiontorest_time_number.cpp @@ -0,0 +1,9 @@ +#include "motiontorest_time_number.h" + +namespace esphome { +namespace seeed_mr24hpc1 { + +void MotionToRestTimeNumber::control(float value) { this->parent_->set_motion_to_rest_time(value); } + +} // namespace seeed_mr24hpc1 +} // namespace esphome diff --git a/esphome/components/seeed_mr24hpc1/number/motiontorest_time_number.h b/esphome/components/seeed_mr24hpc1/number/motiontorest_time_number.h new file mode 100644 index 0000000000..559d23fdeb --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/number/motiontorest_time_number.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/number/number.h" +#include "../seeed_mr24hpc1.h" + +namespace esphome { +namespace seeed_mr24hpc1 { + +class MotionToRestTimeNumber : public number::Number, public Parented { + public: + MotionToRestTimeNumber() = default; + + protected: + void control(float value) override; +}; + +} // namespace seeed_mr24hpc1 +} // namespace esphome diff --git a/esphome/components/seeed_mr24hpc1/number/sensitivity_number.cpp b/esphome/components/seeed_mr24hpc1/number/sensitivity_number.cpp new file mode 100644 index 0000000000..d903dfd818 --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/number/sensitivity_number.cpp @@ -0,0 +1,9 @@ +#include "sensitivity_number.h" + +namespace esphome { +namespace seeed_mr24hpc1 { + +void SensitivityNumber::control(float value) { this->parent_->set_sensitivity(value); } + +} // namespace seeed_mr24hpc1 +} // namespace esphome diff --git a/esphome/components/seeed_mr24hpc1/number/sensitivity_number.h b/esphome/components/seeed_mr24hpc1/number/sensitivity_number.h new file mode 100644 index 0000000000..fee33521d0 --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/number/sensitivity_number.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/number/number.h" +#include "../seeed_mr24hpc1.h" + +namespace esphome { +namespace seeed_mr24hpc1 { + +class SensitivityNumber : public number::Number, public Parented { + public: + SensitivityNumber() = default; + + protected: + void control(float value) override; +}; + +} // namespace seeed_mr24hpc1 +} // namespace esphome diff --git a/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp b/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp new file mode 100644 index 0000000000..1cf9bd300a --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp @@ -0,0 +1,890 @@ +#include "seeed_mr24hpc1.h" + +#include "esphome/core/log.h" + +#include + +namespace esphome { +namespace seeed_mr24hpc1 { + +static const char *const TAG = "seeed_mr24hpc1"; + +// Prints the component's configuration data. dump_config() prints all of the component's configuration +// items in an easy-to-read format, including the configuration key-value pairs. +void MR24HPC1Component::dump_config() { + ESP_LOGCONFIG(TAG, "MR24HPC1:"); +#ifdef USE_TEXT_SENSOR + LOG_TEXT_SENSOR(" ", "Heartbeat Text Sensor", this->heartbeat_state_text_sensor_); + LOG_TEXT_SENSOR(" ", "Product Model Text Sensor", this->product_model_text_sensor_); + LOG_TEXT_SENSOR(" ", "Product ID Text Sensor", this->product_id_text_sensor_); + LOG_TEXT_SENSOR(" ", "Hardware Model Text Sensor", this->hardware_model_text_sensor_); + LOG_TEXT_SENSOR(" ", "Firware Verison Text Sensor", this->firware_version_text_sensor_); + LOG_TEXT_SENSOR(" ", "Keep Away Text Sensor", this->keep_away_text_sensor_); + LOG_TEXT_SENSOR(" ", "Motion Status Text Sensor", this->motion_status_text_sensor_); + LOG_TEXT_SENSOR(" ", "Custom Mode End Text Sensor", this->custom_mode_end_text_sensor_); +#endif +#ifdef USE_BINARY_SENSOR + LOG_BINARY_SENSOR(" ", "Has Target Binary Sensor", this->has_target_binary_sensor_); +#endif +#ifdef USE_SENSOR + LOG_SENSOR(" ", "Custom Presence Of Detection Sensor", this->custom_presence_of_detection_sensor_); + LOG_SENSOR(" ", "Movement Signs Sensor", this->movement_signs_sensor_); + LOG_SENSOR(" ", "Custom Motion Distance Sensor", this->custom_motion_distance_sensor_); + LOG_SENSOR(" ", "Custom Spatial Static Sensor", this->custom_spatial_static_value_sensor_); + LOG_SENSOR(" ", "Custom Spatial Motion Sensor", this->custom_spatial_motion_value_sensor_); + LOG_SENSOR(" ", "Custom Motion Speed Sensor", this->custom_motion_speed_sensor_); + LOG_SENSOR(" ", "Custom Mode Num Sensor", this->custom_mode_num_sensor_); +#endif +#ifdef USE_SWITCH + LOG_SWITCH(" ", "Underly Open Function Switch", this->underlying_open_function_switch_); +#endif +#ifdef USE_BUTTON + LOG_BUTTON(" ", "Restart Button", this->restart_button_); + LOG_BUTTON(" ", "Custom Set End Button", this->custom_set_end_button_); +#endif +#ifdef USE_SELECT + LOG_SELECT(" ", "Scene Mode Select", this->scene_mode_select_); + LOG_SELECT(" ", "Unman Time Select", this->unman_time_select_); + LOG_SELECT(" ", "Existence Boundary Select", this->existence_boundary_select_); + LOG_SELECT(" ", "Motion Boundary Select", this->motion_boundary_select_); +#endif +#ifdef USE_NUMBER + LOG_NUMBER(" ", "Sensitivity Number", this->sensitivity_number_); + LOG_NUMBER(" ", "Custom Mode Number", this->custom_mode_number_); + LOG_NUMBER(" ", "Existence Threshold Number", this->existence_threshold_number_); + LOG_NUMBER(" ", "Motion Threshold Number", this->motion_threshold_number_); + LOG_NUMBER(" ", "Motion Trigger Time Number", this->motion_trigger_number_); + LOG_NUMBER(" ", "Motion To Rest Time Number", this->motion_to_rest_number_); + LOG_NUMBER(" ", "Custom Unman Time Number", this->custom_unman_time_number_); +#endif +} + +// Initialisation functions +void MR24HPC1Component::setup() { + ESP_LOGCONFIG(TAG, "Setting up MR24HPC1..."); + this->check_uart_settings(115200); + + if (this->custom_mode_number_ != nullptr) { + this->custom_mode_number_->publish_state(0); // Zero out the custom mode + } + if (this->custom_mode_num_sensor_ != nullptr) { + this->custom_mode_num_sensor_->publish_state(0); + } + if (this->custom_mode_end_text_sensor_ != nullptr) { + this->custom_mode_end_text_sensor_->publish_state("Not in custom mode"); + } + this->set_custom_end_mode(); + this->poll_time_base_func_check_ = true; + this->check_dev_inf_sign_ = true; + this->sg_start_query_data_ = STANDARD_FUNCTION_QUERY_PRODUCT_MODE; + this->sg_data_len_ = 0; + this->sg_frame_len_ = 0; + this->sg_recv_data_state_ = FRAME_IDLE; + this->s_output_info_switch_flag_ = OUTPUT_SWITCH_INIT; + + memset(this->c_product_mode_, 0, PRODUCT_BUF_MAX_SIZE); + memset(this->c_product_id_, 0, PRODUCT_BUF_MAX_SIZE); + memset(this->c_firmware_version_, 0, PRODUCT_BUF_MAX_SIZE); + memset(this->c_hardware_model_, 0, PRODUCT_BUF_MAX_SIZE); + memset(this->sg_frame_prase_buf_, 0, FRAME_BUF_MAX_SIZE); + memset(this->sg_frame_buf_, 0, FRAME_BUF_MAX_SIZE); + + this->set_interval(8000, [this]() { this->update_(); }); + ESP_LOGCONFIG(TAG, "Set up MR24HPC1 complete"); +} + +// Timed polling of radar data +void MR24HPC1Component::update_() { + this->get_radar_output_information_switch(); // Query the key status every so often + this->poll_time_base_func_check_ = true; // Query the base functionality information at regular intervals +} + +// main loop +void MR24HPC1Component::loop() { + uint8_t byte; + + // Is there data on the serial port + while (this->available()) { + this->read_byte(&byte); + this->r24_split_data_frame_(byte); // split data frame + } + + if ((this->s_output_info_switch_flag_ == OUTPUT_SWTICH_OFF) && + (this->sg_start_query_data_ > CUSTOM_FUNCTION_QUERY_TIME_OF_ENTER_UNMANNED) && (!this->check_dev_inf_sign_)) { + this->sg_start_query_data_ = STANDARD_FUNCTION_QUERY_SCENE_MODE; + } else if ((this->s_output_info_switch_flag_ == OUTPUT_SWITCH_ON) && + (this->sg_start_query_data_ < CUSTOM_FUNCTION_QUERY_EXISTENCE_BOUNDARY) && (!this->check_dev_inf_sign_)) { + this->sg_start_query_data_ = CUSTOM_FUNCTION_QUERY_EXISTENCE_BOUNDARY; + } else if (this->check_dev_inf_sign_ && (this->sg_start_query_data_ > STANDARD_FUNCTION_QUERY_HARDWARE_MODE)) { + // First time power up information polling + this->sg_start_query_data_ = STANDARD_FUNCTION_QUERY_PRODUCT_MODE; + } + + // Polling Functions + if (this->poll_time_base_func_check_) { + switch (this->sg_start_query_data_) { + case STANDARD_FUNCTION_QUERY_PRODUCT_MODE: + this->get_product_mode(); + this->sg_start_query_data_++; + break; + case STANDARD_FUNCTION_QUERY_PRODUCT_ID: + this->get_product_id(); + this->sg_start_query_data_++; + break; + case STANDARD_FUNCTION_QUERY_FIRMWARE_VERSION: + this->get_product_mode(); + this->get_product_id(); + this->get_firmware_version(); + this->sg_start_query_data_++; + break; + case STANDARD_FUNCTION_QUERY_HARDWARE_MODE: // Above is the equipment information + this->get_product_mode(); + this->get_product_id(); + this->get_hardware_model(); + this->sg_start_query_data_++; + this->check_dev_inf_sign_ = false; + break; + case STANDARD_FUNCTION_QUERY_SCENE_MODE: + this->get_scene_mode(); + this->sg_start_query_data_++; + break; + case STANDARD_FUNCTION_QUERY_SENSITIVITY: + this->get_sensitivity(); + this->sg_start_query_data_++; + break; + case STANDARD_FUNCTION_QUERY_UNMANNED_TIME: + this->get_unmanned_time(); + this->sg_start_query_data_++; + break; + case STANDARD_FUNCTION_QUERY_HUMAN_STATUS: + this->get_human_status(); + this->sg_start_query_data_++; + break; + case STANDARD_FUNCTION_QUERY_HUMAN_MOTION_INF: + this->get_human_motion_info(); + this->sg_start_query_data_++; + break; + case STANDARD_FUNCTION_QUERY_BODY_MOVE_PARAMETER: + this->get_body_motion_params(); + this->sg_start_query_data_++; + break; + case STANDARD_FUNCTION_QUERY_KEEPAWAY_STATUS: // The above is the basic functional information + this->get_keep_away(); + this->sg_start_query_data_++; + break; + case STANDARD_QUERY_CUSTOM_MODE: + this->get_custom_mode(); + this->sg_start_query_data_++; + break; + case STANDARD_FUNCTION_QUERY_HEARTBEAT_STATE: + this->get_heartbeat_packet(); + this->sg_start_query_data_++; + break; + case CUSTOM_FUNCTION_QUERY_EXISTENCE_BOUNDARY: + this->get_existence_boundary(); + this->sg_start_query_data_++; + break; + case CUSTOM_FUNCTION_QUERY_MOTION_BOUNDARY: + this->get_motion_boundary(); + this->sg_start_query_data_++; + break; + case CUSTOM_FUNCTION_QUERY_EXISTENCE_THRESHOLD: + this->get_existence_threshold(); + this->sg_start_query_data_++; + break; + case CUSTOM_FUNCTION_QUERY_MOTION_THRESHOLD: + this->get_motion_threshold(); + this->sg_start_query_data_++; + break; + case CUSTOM_FUNCTION_QUERY_MOTION_TRIGGER_TIME: + this->get_motion_trigger_time(); + this->sg_start_query_data_++; + break; + case CUSTOM_FUNCTION_QUERY_MOTION_TO_REST_TIME: + this->get_motion_to_rest_time(); + this->sg_start_query_data_++; + break; + case CUSTOM_FUNCTION_QUERY_TIME_OF_ENTER_UNMANNED: + this->get_custom_unman_time(); + this->sg_start_query_data_++; + if (this->s_output_info_switch_flag_ == OUTPUT_SWTICH_OFF) { + this->poll_time_base_func_check_ = false; // Avoiding high-speed polling that can cause the device to jam + } + break; + case UNDERLY_FUNCTION_QUERY_HUMAN_STATUS: + this->get_human_status(); + this->sg_start_query_data_++; + break; + case UNDERLY_FUNCTION_QUERY_SPATIAL_STATIC_VALUE: + this->get_spatial_static_value(); + this->sg_start_query_data_++; + break; + case UNDERLY_FUNCTION_QUERY_SPATIAL_MOTION_VALUE: + this->get_spatial_motion_value(); + this->sg_start_query_data_++; + break; + case UNDERLY_FUNCTION_QUERY_DISTANCE_OF_STATIC_OBJECT: + this->get_distance_of_static_object(); + this->sg_start_query_data_++; + break; + case UNDERLY_FUNCTION_QUERY_DISTANCE_OF_MOVING_OBJECT: + this->get_distance_of_moving_object(); + this->sg_start_query_data_++; + break; + case UNDERLY_FUNCTION_QUERY_TARGET_MOVEMENT_SPEED: + this->get_target_movement_speed(); + this->sg_start_query_data_++; + this->poll_time_base_func_check_ = false; // Avoiding high-speed polling that can cause the device to jam + break; + default: + break; + } + } +} + +// Calculate CRC check digit +static uint8_t get_frame_crc_sum(const uint8_t *data, int len) { + unsigned int crc_sum = 0; + for (int i = 0; i < len - 3; i++) { + crc_sum += data[i]; + } + return crc_sum & 0xff; +} + +// Check that the check digit is correct +static int get_frame_check_status(uint8_t *data, int len) { + uint8_t crc_sum = get_frame_crc_sum(data, len); + uint8_t verified = data[len - 3]; + return (verified == crc_sum) ? 1 : 0; +} + +// split data frame +void MR24HPC1Component::r24_split_data_frame_(uint8_t value) { + switch (this->sg_recv_data_state_) { + case FRAME_IDLE: // starting value + if (FRAME_HEADER1_VALUE == value) { + this->sg_recv_data_state_ = FRAME_HEADER2; + } + break; + case FRAME_HEADER2: + if (FRAME_HEADER2_VALUE == value) { + this->sg_frame_buf_[0] = FRAME_HEADER1_VALUE; + this->sg_frame_buf_[1] = FRAME_HEADER2_VALUE; + this->sg_recv_data_state_ = FRAME_CTL_WORD; + } else { + this->sg_recv_data_state_ = FRAME_IDLE; + ESP_LOGD(TAG, "FRAME_IDLE ERROR value:%x", value); + } + break; + case FRAME_CTL_WORD: + this->sg_frame_buf_[2] = value; + this->sg_recv_data_state_ = FRAME_CMD_WORD; + break; + case FRAME_CMD_WORD: + this->sg_frame_buf_[3] = 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; + 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) { + 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; + } else { + this->sg_frame_buf_[5] = value; + this->sg_frame_len_ = 6; + this->sg_recv_data_state_ = FRAME_DATA_BYTES; + } + 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) { + this->sg_recv_data_state_ = FRAME_DATA_CRC; + } + break; + case FRAME_DATA_CRC: + this->sg_frame_buf_[this->sg_frame_len_++] = value; + this->sg_recv_data_state_ = FRAME_TAIL1; + break; + case FRAME_TAIL1: + if (FRAME_TAIL1_VALUE == value) { + this->sg_recv_data_state_ = FRAME_TAIL2; + } else { + this->sg_recv_data_state_ = FRAME_IDLE; + this->sg_frame_len_ = 0; + this->sg_data_len_ = 0; + ESP_LOGD(TAG, "FRAME_TAIL1 ERROR value:%x", value); + } + break; + case FRAME_TAIL2: + if (FRAME_TAIL2_VALUE == value) { + this->sg_frame_buf_[this->sg_frame_len_++] = FRAME_TAIL1_VALUE; + this->sg_frame_buf_[this->sg_frame_len_++] = FRAME_TAIL2_VALUE; + memcpy(this->sg_frame_prase_buf_, this->sg_frame_buf_, this->sg_frame_len_); + if (get_frame_check_status(this->sg_frame_prase_buf_, this->sg_frame_len_)) { + this->r24_parse_data_frame_(this->sg_frame_prase_buf_, this->sg_frame_len_); + } else { + ESP_LOGD(TAG, "frame check failer!"); + } + } else { + ESP_LOGD(TAG, "FRAME_TAIL2 ERROR value:%x", value); + } + memset(this->sg_frame_prase_buf_, 0, FRAME_BUF_MAX_SIZE); + memset(this->sg_frame_buf_, 0, FRAME_BUF_MAX_SIZE); + this->sg_frame_len_ = 0; + this->sg_data_len_ = 0; + this->sg_recv_data_state_ = FRAME_IDLE; + break; + default: + this->sg_recv_data_state_ = FRAME_IDLE; + } +} + +// Parses data frames related to product information +void MR24HPC1Component::r24_frame_parse_product_information_(uint8_t *data) { + 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)) { + memset(this->c_product_mode_, 0, PRODUCT_BUF_MAX_SIZE); + memcpy(this->c_product_mode_, &data[FRAME_DATA_INDEX], product_len); + this->product_model_text_sensor_->publish_state(this->c_product_mode_); + } else { + ESP_LOGD(TAG, "Reply: get product_mode error!"); + } + } else if (data[FRAME_COMMAND_WORD_INDEX] == COMMAND_PRODUCT_ID) { + if ((this->product_id_text_sensor_ != nullptr) && (product_len < PRODUCT_BUF_MAX_SIZE)) { + memset(this->c_product_id_, 0, PRODUCT_BUF_MAX_SIZE); + memcpy(this->c_product_id_, &data[FRAME_DATA_INDEX], product_len); + this->product_id_text_sensor_->publish_state(this->c_product_id_); + } else { + ESP_LOGD(TAG, "Reply: get productId error!"); + } + } else if (data[FRAME_COMMAND_WORD_INDEX] == COMMAND_HARDWARE_MODEL) { + if ((this->hardware_model_text_sensor_ != nullptr) && (product_len < PRODUCT_BUF_MAX_SIZE)) { + memset(this->c_hardware_model_, 0, PRODUCT_BUF_MAX_SIZE); + memcpy(this->c_hardware_model_, &data[FRAME_DATA_INDEX], product_len); + this->hardware_model_text_sensor_->publish_state(this->c_hardware_model_); + ESP_LOGD(TAG, "Reply: get hardware_model :%s", this->c_hardware_model_); + } else { + ESP_LOGD(TAG, "Reply: get hardwareModel error!"); + } + } else if (data[FRAME_COMMAND_WORD_INDEX] == COMMAND_FIRMWARE_VERSION) { + if ((this->firware_version_text_sensor_ != nullptr) && (product_len < PRODUCT_BUF_MAX_SIZE)) { + memset(this->c_firmware_version_, 0, PRODUCT_BUF_MAX_SIZE); + memcpy(this->c_firmware_version_, &data[FRAME_DATA_INDEX], product_len); + this->firware_version_text_sensor_->publish_state(this->c_firmware_version_); + } else { + ESP_LOGD(TAG, "Reply: get firmwareVersion error!"); + } + } +} + +// 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(S_BOUNDARY_STR[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(S_BOUNDARY_STR[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); + } +} + +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) { + 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; + case 0x02: { + this->r24_frame_parse_product_information_(data); + } break; + case 0x05: { + this->r24_frame_parse_work_status_(data); + } break; + case 0x08: { + this->r24_frame_parse_open_underlying_information_(data); + } break; + case 0x80: { + this->r24_frame_parse_human_information_(data); + } break; + default: + ESP_LOGD(TAG, "control word:0x%02X not found", data[FRAME_CONTROL_WORD_INDEX]); + break; + } +} + +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(S_SCENE_STR[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(S_SCENE_STR[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"); + } + if (this->custom_mode_number_ != nullptr) { + this->custom_mode_number_->publish_state(0); + } + 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]); + } + } + } else { + ESP_LOGD(TAG, "[%s] No found COMMAND_WORD(%02X) in Frame", __FUNCTION__, data[FRAME_COMMAND_WORD_INDEX]); + } +} + +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(S_UNMANNED_TIME_STR[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]); + } +} + +// Sending data frames +void MR24HPC1Component::send_query_(const uint8_t *query, size_t string_length) { + this->write_array(query, string_length); +} + +// Send Heartbeat Packet Command +void MR24HPC1Component::get_heartbeat_packet() { this->send_query_(GET_HEARTBEAT, sizeof(GET_HEARTBEAT)); } + +// Issuance of the underlying open parameter query command +void MR24HPC1Component::get_radar_output_information_switch() { + this->send_query_(GET_RADAR_OUTPUT_INFORMATION_SWITCH, sizeof(GET_RADAR_OUTPUT_INFORMATION_SWITCH)); +} + +// Issuance of product model orders +void MR24HPC1Component::get_product_mode() { this->send_query_(GET_PRODUCT_MODE, sizeof(GET_PRODUCT_MODE)); } + +// Issuing the Get Product ID command +void MR24HPC1Component::get_product_id() { this->send_query_(GET_PRODUCT_ID, sizeof(GET_PRODUCT_ID)); } + +// Issuing hardware model commands +void MR24HPC1Component::get_hardware_model() { this->send_query_(GET_HARDWARE_MODEL, sizeof(GET_HARDWARE_MODEL)); } + +// Issuing software version commands +void MR24HPC1Component::get_firmware_version() { + this->send_query_(GET_FIRMWARE_VERSION, sizeof(GET_FIRMWARE_VERSION)); +} + +void MR24HPC1Component::get_human_status() { this->send_query_(GET_HUMAN_STATUS, sizeof(GET_HUMAN_STATUS)); } + +void MR24HPC1Component::get_human_motion_info() { + this->send_query_(GET_HUMAN_MOTION_INFORMATION, sizeof(GET_HUMAN_MOTION_INFORMATION)); +} + +void MR24HPC1Component::get_body_motion_params() { + this->send_query_(GET_BODY_MOTION_PARAMETERS, sizeof(GET_BODY_MOTION_PARAMETERS)); +} + +void MR24HPC1Component::get_keep_away() { this->send_query_(GET_KEEP_AWAY, sizeof(GET_KEEP_AWAY)); } + +void MR24HPC1Component::get_scene_mode() { this->send_query_(GET_SCENE_MODE, sizeof(GET_SCENE_MODE)); } + +void MR24HPC1Component::get_sensitivity() { this->send_query_(GET_SENSITIVITY, sizeof(GET_SENSITIVITY)); } + +void MR24HPC1Component::get_unmanned_time() { this->send_query_(GET_UNMANNED_TIME, sizeof(GET_UNMANNED_TIME)); } + +void MR24HPC1Component::get_custom_mode() { this->send_query_(GET_CUSTOM_MODE, sizeof(GET_CUSTOM_MODE)); } + +void MR24HPC1Component::get_existence_boundary() { + this->send_query_(GET_EXISTENCE_BOUNDARY, sizeof(GET_EXISTENCE_BOUNDARY)); +} + +void MR24HPC1Component::get_motion_boundary() { this->send_query_(GET_MOTION_BOUNDARY, sizeof(GET_MOTION_BOUNDARY)); } + +void MR24HPC1Component::get_spatial_static_value() { + this->send_query_(GET_SPATIAL_STATIC_VALUE, sizeof(GET_SPATIAL_STATIC_VALUE)); +} + +void MR24HPC1Component::get_spatial_motion_value() { + this->send_query_(GET_SPATIAL_MOTION_VALUE, sizeof(GET_SPATIAL_MOTION_VALUE)); +} + +void MR24HPC1Component::get_distance_of_static_object() { + this->send_query_(GET_DISTANCE_OF_STATIC_OBJECT, sizeof(GET_DISTANCE_OF_STATIC_OBJECT)); +} + +void MR24HPC1Component::get_distance_of_moving_object() { + this->send_query_(GET_DISTANCE_OF_MOVING_OBJECT, sizeof(GET_DISTANCE_OF_MOVING_OBJECT)); +} + +void MR24HPC1Component::get_target_movement_speed() { + this->send_query_(GET_TARGET_MOVEMENT_SPEED, sizeof(GET_TARGET_MOVEMENT_SPEED)); +} + +void MR24HPC1Component::get_existence_threshold() { + this->send_query_(GET_EXISTENCE_THRESHOLD, sizeof(GET_EXISTENCE_THRESHOLD)); +} + +void MR24HPC1Component::get_motion_threshold() { + this->send_query_(GET_MOTION_THRESHOLD, sizeof(GET_MOTION_THRESHOLD)); +} + +void MR24HPC1Component::get_motion_trigger_time() { + this->send_query_(GET_MOTION_TRIGGER_TIME, sizeof(GET_MOTION_TRIGGER_TIME)); +} + +void MR24HPC1Component::get_motion_to_rest_time() { + this->send_query_(GET_MOTION_TO_REST_TIME, sizeof(GET_MOTION_TO_REST_TIME)); +} + +void MR24HPC1Component::get_custom_unman_time() { + this->send_query_(GET_CUSTOM_UNMAN_TIME, sizeof(GET_CUSTOM_UNMAN_TIME)); +} + +// Logic of setting: After setting, query whether the setting is successful or not! + +void MR24HPC1Component::set_underlying_open_function(bool enable) { + if (enable) { + this->send_query_(UNDERLYING_SWITCH_ON, sizeof(UNDERLYING_SWITCH_ON)); + } else { + this->send_query_(UNDERLYING_SWITCH_OFF, sizeof(UNDERLYING_SWITCH_OFF)); + } + 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(""); + } + if (this->custom_spatial_static_value_sensor_ != nullptr) { + this->custom_spatial_static_value_sensor_->publish_state(NAN); + } + if (this->custom_spatial_motion_value_sensor_ != nullptr) { + this->custom_spatial_motion_value_sensor_->publish_state(NAN); + } + if (this->custom_motion_distance_sensor_ != nullptr) { + this->custom_motion_distance_sensor_->publish_state(NAN); + } + if (this->custom_presence_of_detection_sensor_ != nullptr) { + this->custom_presence_of_detection_sensor_->publish_state(NAN); + } + if (this->custom_motion_speed_sensor_ != nullptr) { + this->custom_motion_speed_sensor_->publish_state(NAN); + } +} + +void MR24HPC1Component::set_scene_mode(uint8_t value) { + uint8_t send_data_len = 10; + 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); + if (this->custom_mode_number_ != nullptr) { + this->custom_mode_number_->publish_state(0); + } + if (this->custom_mode_num_sensor_ != nullptr) { + this->custom_mode_num_sensor_->publish_state(0); + } + this->get_scene_mode(); + this->get_sensitivity(); + this->get_custom_mode(); + this->get_existence_boundary(); + this->get_motion_boundary(); + this->get_existence_threshold(); + this->get_motion_threshold(); + this->get_motion_trigger_time(); + this->get_motion_to_rest_time(); + this->get_custom_unman_time(); +} + +void MR24HPC1Component::set_sensitivity(uint8_t value) { + if (value == 0x00) + return; + uint8_t send_data_len = 10; + uint8_t send_data[10] = {0x53, 0x59, 0x05, 0x08, 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); + this->get_scene_mode(); + this->get_sensitivity(); +} + +void MR24HPC1Component::set_restart() { + this->send_query_(SET_RESTART, sizeof(SET_RESTART)); + this->check_dev_inf_sign_ = true; +} + +void MR24HPC1Component::set_unman_time(uint8_t value) { + uint8_t send_data_len = 10; + uint8_t send_data[10] = {0x53, 0x59, 0x80, 0x0a, 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); + this->get_unmanned_time(); +} + +void MR24HPC1Component::set_custom_mode(uint8_t mode) { + if (mode == 0) { + this->set_custom_end_mode(); // Equivalent to end setting + if (this->custom_mode_number_ != nullptr) { + this->custom_mode_number_->publish_state(0); + } + return; + } + uint8_t send_data_len = 10; + uint8_t send_data[10] = {0x53, 0x59, 0x05, 0x09, 0x00, 0x01, mode, 0x00, 0x54, 0x43}; + send_data[7] = get_frame_crc_sum(send_data, send_data_len); + this->send_query_(send_data, send_data_len); + this->get_existence_boundary(); + this->get_motion_boundary(); + this->get_existence_threshold(); + this->get_motion_threshold(); + this->get_motion_trigger_time(); + this->get_motion_to_rest_time(); + this->get_custom_unman_time(); + this->get_custom_mode(); + this->get_scene_mode(); + this->get_sensitivity(); +} + +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); + if (this->custom_mode_number_ != nullptr) { + this->custom_mode_number_->publish_state(0); // Clear setpoints + } + this->get_existence_boundary(); + this->get_motion_boundary(); + this->get_existence_threshold(); + this->get_motion_threshold(); + this->get_motion_trigger_time(); + this->get_motion_to_rest_time(); + this->get_custom_unman_time(); + this->get_custom_mode(); + this->get_scene_mode(); + this->get_sensitivity(); +} + +void MR24HPC1Component::set_existence_boundary(uint8_t value) { + 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 + 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); + this->send_query_(send_data, send_data_len); + this->get_existence_boundary(); +} + +void MR24HPC1Component::set_motion_boundary(uint8_t value) { + 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 + 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); + this->send_query_(send_data, send_data_len); + this->get_motion_boundary(); +} + +void MR24HPC1Component::set_existence_threshold(uint8_t value) { + 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 + 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); + this->send_query_(send_data, send_data_len); + this->get_existence_threshold(); +} + +void MR24HPC1Component::set_motion_threshold(uint8_t value) { + 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 + 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); + this->send_query_(send_data, send_data_len); + this->get_motion_threshold(); +} + +void MR24HPC1Component::set_motion_trigger_time(uint8_t value) { + 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 + 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); + this->send_query_(send_data, send_data_len); + this->get_motion_trigger_time(); +} + +void MR24HPC1Component::set_motion_to_rest_time(uint16_t value) { + 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 + uint8_t h8_num = (value >> 8) & 0xff; + uint8_t l8_num = value & 0xff; + uint8_t send_data_len = 13; + uint8_t send_data[13] = {0x53, 0x59, 0x08, 0x0D, 0x00, 0x04, 0x00, 0x00, h8_num, l8_num, 0x00, 0x54, 0x43}; + send_data[10] = get_frame_crc_sum(send_data, send_data_len); + this->send_query_(send_data, send_data_len); + this->get_motion_to_rest_time(); +} + +void MR24HPC1Component::set_custom_unman_time(uint16_t value) { + 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 + uint32_t value_ms = value * 1000; + uint8_t h24_num = (value_ms >> 24) & 0xff; + uint8_t h16_num = (value_ms >> 16) & 0xff; + uint8_t h8_num = (value_ms >> 8) & 0xff; + uint8_t l8_num = value_ms & 0xff; + uint8_t send_data_len = 13; + uint8_t send_data[13] = {0x53, 0x59, 0x08, 0x0E, 0x00, 0x04, h24_num, h16_num, h8_num, l8_num, 0x00, 0x54, 0x43}; + send_data[10] = get_frame_crc_sum(send_data, send_data_len); + this->send_query_(send_data, send_data_len); + this->get_custom_unman_time(); +} + +} // namespace seeed_mr24hpc1 +} // namespace esphome diff --git a/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.h b/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.h new file mode 100644 index 0000000000..8fc61ad37c --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.h @@ -0,0 +1,217 @@ +#pragma once +#include "esphome/core/component.h" +#include "esphome/core/defines.h" +#ifdef USE_BINARY_SENSOR +#include "esphome/components/binary_sensor/binary_sensor.h" +#endif +#ifdef USE_SENSOR +#include "esphome/components/sensor/sensor.h" +#endif +#ifdef USE_NUMBER +#include "esphome/components/number/number.h" +#endif +#ifdef USE_SWITCH +#include "esphome/components/switch/switch.h" +#endif +#ifdef USE_BUTTON +#include "esphome/components/button/button.h" +#endif +#ifdef USE_SELECT +#include "esphome/components/select/select.h" +#endif +#ifdef USE_TEXT_SENSOR +#include "esphome/components/text_sensor/text_sensor.h" +#endif +#include "esphome/components/uart/uart.h" +#include "esphome/core/automation.h" +#include "esphome/core/helpers.h" + +#include "seeed_mr24hpc1_constants.h" + +#include + +namespace esphome { +namespace seeed_mr24hpc1 { + +enum FrameState { + FRAME_IDLE, + FRAME_HEADER2, + FRAME_CTL_WORD, + FRAME_CMD_WORD, + FRAME_DATA_LEN_H, + FRAME_DATA_LEN_L, + FRAME_DATA_BYTES, + FRAME_DATA_CRC, + FRAME_TAIL1, + FRAME_TAIL2, +}; + +enum PollingState { + STANDARD_FUNCTION_QUERY_PRODUCT_MODE = 0, + STANDARD_FUNCTION_QUERY_PRODUCT_ID, + STANDARD_FUNCTION_QUERY_FIRMWARE_VERSION, + STANDARD_FUNCTION_QUERY_HARDWARE_MODE, // Above is the equipment information + STANDARD_FUNCTION_QUERY_SCENE_MODE, + STANDARD_FUNCTION_QUERY_SENSITIVITY, + STANDARD_FUNCTION_QUERY_UNMANNED_TIME, + STANDARD_FUNCTION_QUERY_HUMAN_STATUS, + STANDARD_FUNCTION_QUERY_HUMAN_MOTION_INF, + STANDARD_FUNCTION_QUERY_BODY_MOVE_PARAMETER, + STANDARD_FUNCTION_QUERY_KEEPAWAY_STATUS, + STANDARD_QUERY_CUSTOM_MODE, + STANDARD_FUNCTION_QUERY_HEARTBEAT_STATE, // Above is the basic function + + CUSTOM_FUNCTION_QUERY_EXISTENCE_BOUNDARY, + CUSTOM_FUNCTION_QUERY_MOTION_BOUNDARY, + CUSTOM_FUNCTION_QUERY_EXISTENCE_THRESHOLD, + CUSTOM_FUNCTION_QUERY_MOTION_THRESHOLD, + CUSTOM_FUNCTION_QUERY_MOTION_TRIGGER_TIME, + CUSTOM_FUNCTION_QUERY_MOTION_TO_REST_TIME, + CUSTOM_FUNCTION_QUERY_TIME_OF_ENTER_UNMANNED, + + UNDERLY_FUNCTION_QUERY_HUMAN_STATUS, + UNDERLY_FUNCTION_QUERY_SPATIAL_STATIC_VALUE, + UNDERLY_FUNCTION_QUERY_SPATIAL_MOTION_VALUE, + UNDERLY_FUNCTION_QUERY_DISTANCE_OF_STATIC_OBJECT, + UNDERLY_FUNCTION_QUERY_DISTANCE_OF_MOVING_OBJECT, + UNDERLY_FUNCTION_QUERY_TARGET_MOVEMENT_SPEED, +}; + +enum OutputSwitch { + OUTPUT_SWITCH_INIT, + OUTPUT_SWITCH_ON, + OUTPUT_SWTICH_OFF, +}; + +static const char *const S_SCENE_STR[5] = {"None", "Living Room", "Bedroom", "Washroom", "Area Detection"}; +static const bool S_SOMEONE_EXISTS_STR[2] = {false, true}; +static const char *const S_MOTION_STATUS_STR[3] = {"None", "Motionless", "Active"}; +static const char *const S_KEEP_AWAY_STR[3] = {"None", "Close", "Away"}; +static const char *const S_UNMANNED_TIME_STR[9] = {"None", "10s", "30s", "1min", "2min", + "5min", "10min", "30min", "60min"}; +static const char *const S_BOUNDARY_STR[10] = {"0.5m", "1.0m", "1.5m", "2.0m", "2.5m", + "3.0m", "3.5m", "4.0m", "4.5m", "5.0m"}; // uint: m +static const float S_PRESENCE_OF_DETECTION_RANGE_STR[7] = {0.0f, 0.5f, 1.0f, 1.5f, 2.0f, 2.5f, 3.0f}; // uint: m + +class MR24HPC1Component : public Component, + public uart::UARTDevice { // The class name must be the name defined by text_sensor.py +#ifdef USE_TEXT_SENSOR + SUB_TEXT_SENSOR(heartbeat_state) + SUB_TEXT_SENSOR(product_model) + SUB_TEXT_SENSOR(product_id) + SUB_TEXT_SENSOR(hardware_model) + SUB_TEXT_SENSOR(firware_version) + SUB_TEXT_SENSOR(keep_away) + SUB_TEXT_SENSOR(motion_status) + SUB_TEXT_SENSOR(custom_mode_end) +#endif +#ifdef USE_BINARY_SENSOR + SUB_BINARY_SENSOR(has_target) +#endif +#ifdef USE_SENSOR + SUB_SENSOR(custom_presence_of_detection) + SUB_SENSOR(movement_signs) + SUB_SENSOR(custom_motion_distance) + SUB_SENSOR(custom_spatial_static_value) + SUB_SENSOR(custom_spatial_motion_value) + SUB_SENSOR(custom_motion_speed) + SUB_SENSOR(custom_mode_num) +#endif +#ifdef USE_SWITCH + SUB_SWITCH(underlying_open_function) +#endif +#ifdef USE_BUTTON + SUB_BUTTON(restart) + SUB_BUTTON(custom_set_end) +#endif +#ifdef USE_SELECT + SUB_SELECT(scene_mode) + SUB_SELECT(unman_time) + SUB_SELECT(existence_boundary) + SUB_SELECT(motion_boundary) +#endif +#ifdef USE_NUMBER + SUB_NUMBER(sensitivity) + SUB_NUMBER(custom_mode) + SUB_NUMBER(existence_threshold) + SUB_NUMBER(motion_threshold) + SUB_NUMBER(motion_trigger) + SUB_NUMBER(motion_to_rest) + SUB_NUMBER(custom_unman_time) +#endif + + protected: + char c_product_mode_[PRODUCT_BUF_MAX_SIZE + 1]; + char c_product_id_[PRODUCT_BUF_MAX_SIZE + 1]; + char c_hardware_model_[PRODUCT_BUF_MAX_SIZE + 1]; + char c_firmware_version_[PRODUCT_BUF_MAX_SIZE + 1]; + uint8_t s_output_info_switch_flag_; + uint8_t sg_recv_data_state_; + uint8_t sg_frame_len_; + uint8_t sg_data_len_; + uint8_t sg_frame_buf_[FRAME_BUF_MAX_SIZE]; + uint8_t sg_frame_prase_buf_[FRAME_BUF_MAX_SIZE]; + int sg_start_query_data_; + bool check_dev_inf_sign_; + bool poll_time_base_func_check_; + + void update_(); + void r24_split_data_frame_(uint8_t value); + void r24_parse_data_frame_(uint8_t *data, uint8_t len); + void r24_frame_parse_open_underlying_information_(uint8_t *data); + void r24_frame_parse_work_status_(uint8_t *data); + void r24_frame_parse_product_information_(uint8_t *data); + void r24_frame_parse_human_information_(uint8_t *data); + void send_query_(const uint8_t *query, size_t string_length); + + public: + float get_setup_priority() const override { return esphome::setup_priority::LATE; } + void setup() override; + void dump_config() override; + void loop() override; + + void get_heartbeat_packet(); + void get_radar_output_information_switch(); + void get_product_mode(); + void get_product_id(); + void get_hardware_model(); + void get_firmware_version(); + void get_human_status(); + void get_human_motion_info(); + void get_body_motion_params(); + void get_keep_away(); + void get_scene_mode(); + void get_sensitivity(); + void get_unmanned_time(); + void get_custom_mode(); + void get_existence_boundary(); + void get_motion_boundary(); + void get_spatial_static_value(); + void get_spatial_motion_value(); + void get_distance_of_static_object(); + void get_distance_of_moving_object(); + void get_target_movement_speed(); + void get_existence_threshold(); + void get_motion_threshold(); + void get_motion_trigger_time(); + void get_motion_to_rest_time(); + void get_custom_unman_time(); + + void set_scene_mode(uint8_t value); + void set_underlying_open_function(bool enable); + void set_sensitivity(uint8_t value); + void set_restart(); + void set_unman_time(uint8_t value); + void set_custom_mode(uint8_t mode); + void set_custom_end_mode(); + void set_existence_boundary(uint8_t value); + void set_motion_boundary(uint8_t value); + void set_existence_threshold(uint8_t value); + void set_motion_threshold(uint8_t value); + void set_motion_trigger_time(uint8_t value); + void set_motion_to_rest_time(uint16_t value); + void set_custom_unman_time(uint16_t value); +}; + +} // namespace seeed_mr24hpc1 +} // namespace esphome diff --git a/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1_constants.h b/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1_constants.h new file mode 100644 index 0000000000..dafc6c0368 --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1_constants.h @@ -0,0 +1,173 @@ +#pragma once + +#include + +namespace esphome { +namespace seeed_mr24hpc1 { + +static const uint8_t FRAME_BUF_MAX_SIZE = 128; +static const uint8_t PRODUCT_BUF_MAX_SIZE = 32; + +static const uint8_t FRAME_CONTROL_WORD_INDEX = 2; +static const uint8_t FRAME_COMMAND_WORD_INDEX = 3; +static const uint8_t FRAME_DATA_INDEX = 6; + +static const uint8_t FRAME_HEADER1_VALUE = 0x53; +static const uint8_t FRAME_HEADER2_VALUE = 0x59; +static const uint8_t FRAME_TAIL1_VALUE = 0x54; +static const uint8_t FRAME_TAIL2_VALUE = 0x43; + +static const uint8_t CONTROL_MAIN = 0x01; +static const uint8_t CONTROL_PRODUCT_INFORMATION = 0x02; +static const uint8_t CONTROL_WORK = 0x05; +static const uint8_t CONTROL_UNDERLYING_FUNCTION = 0x08; +static const uint8_t CONTROL_HUMAN_INFORMATION = 0x80; + +static const uint8_t COMMAND_HEARTBEAT = 0x01; +static const uint8_t COMMAND_RESTART = 0x02; + +static const uint8_t COMMAND_PRODUCT_MODE = 0xA1; +static const uint8_t COMMAND_PRODUCT_ID = 0xA2; +static const uint8_t COMMAND_HARDWARE_MODEL = 0xA3; +static const uint8_t COMMAND_FIRMWARE_VERSION = 0xA4; + +static const uint8_t GET_HEARTBEAT[] = { + FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_MAIN, COMMAND_HEARTBEAT, 0x00, 0x01, 0x0F, 0xBE, + FRAME_TAIL1_VALUE, FRAME_TAIL2_VALUE, +}; +static const uint8_t SET_RESTART[] = { + FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_MAIN, COMMAND_RESTART, 0x00, 0x01, 0x0F, 0xBF, + FRAME_TAIL1_VALUE, FRAME_TAIL2_VALUE, +}; + +static const uint8_t GET_PRODUCT_MODE[] = { + FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_PRODUCT_INFORMATION, COMMAND_PRODUCT_MODE, 0x00, 0x01, 0x0F, 0x5F, + FRAME_TAIL1_VALUE, FRAME_TAIL2_VALUE, +}; +static const uint8_t GET_PRODUCT_ID[] = { + FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_PRODUCT_INFORMATION, COMMAND_PRODUCT_ID, 0x00, 0x01, 0x0F, 0x60, + FRAME_TAIL1_VALUE, FRAME_TAIL2_VALUE, +}; +static const uint8_t GET_HARDWARE_MODEL[] = { + FRAME_HEADER1_VALUE, + FRAME_HEADER2_VALUE, + CONTROL_PRODUCT_INFORMATION, + COMMAND_HARDWARE_MODEL, + 0x00, + 0x01, + 0x0F, + 0x61, + FRAME_TAIL1_VALUE, + FRAME_TAIL2_VALUE, +}; +static const uint8_t GET_FIRMWARE_VERSION[] = { + FRAME_HEADER1_VALUE, + FRAME_HEADER2_VALUE, + CONTROL_PRODUCT_INFORMATION, + COMMAND_FIRMWARE_VERSION, + 0x00, + 0x01, + 0x0F, + 0x62, + FRAME_TAIL1_VALUE, + FRAME_TAIL2_VALUE, +}; + +static const uint8_t GET_SCENE_MODE[] = { + FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_WORK, 0x87, 0x00, 0x01, 0x0F, 0x48, + FRAME_TAIL1_VALUE, FRAME_TAIL2_VALUE, +}; +static const uint8_t GET_SENSITIVITY[] = { + FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_WORK, 0x88, 0x00, 0x01, 0x0F, 0x49, + FRAME_TAIL1_VALUE, FRAME_TAIL2_VALUE, +}; +static const uint8_t GET_CUSTOM_MODE[] = { + FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_WORK, 0x89, 0x00, 0x01, 0x0F, 0x4A, + FRAME_TAIL1_VALUE, FRAME_TAIL2_VALUE, +}; + +static const uint8_t UNDERLYING_SWITCH_ON[] = { + FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_UNDERLYING_FUNCTION, 0x00, 0x00, 0x01, 0x01, 0xB6, + FRAME_TAIL1_VALUE, FRAME_TAIL2_VALUE, +}; +static const uint8_t UNDERLYING_SWITCH_OFF[] = { + FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_UNDERLYING_FUNCTION, 0x00, 0x00, 0x01, 0x00, 0xB5, + FRAME_TAIL1_VALUE, FRAME_TAIL2_VALUE, +}; + +static const uint8_t GET_RADAR_OUTPUT_INFORMATION_SWITCH[] = { + FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_UNDERLYING_FUNCTION, 0x80, 0x00, 0x01, 0x0F, 0x44, + FRAME_TAIL1_VALUE, FRAME_TAIL2_VALUE, +}; +static const uint8_t GET_SPATIAL_STATIC_VALUE[] = { + FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_UNDERLYING_FUNCTION, 0x81, 0x00, 0x01, 0x0F, 0x45, + FRAME_TAIL1_VALUE, FRAME_TAIL2_VALUE, +}; +static const uint8_t GET_SPATIAL_MOTION_VALUE[] = { + FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_UNDERLYING_FUNCTION, 0x82, 0x00, 0x01, 0x0F, 0x46, + FRAME_TAIL1_VALUE, FRAME_TAIL2_VALUE, +}; +static const uint8_t GET_DISTANCE_OF_STATIC_OBJECT[] = { + FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_UNDERLYING_FUNCTION, 0x83, 0x00, 0x01, 0x0F, 0x47, + FRAME_TAIL1_VALUE, FRAME_TAIL2_VALUE, +}; +static const uint8_t GET_DISTANCE_OF_MOVING_OBJECT[] = { + FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_UNDERLYING_FUNCTION, 0x84, 0x00, 0x01, 0x0F, 0x48, + FRAME_TAIL1_VALUE, FRAME_TAIL2_VALUE, +}; +static const uint8_t GET_TARGET_MOVEMENT_SPEED[] = { + FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_UNDERLYING_FUNCTION, 0x85, 0x00, 0x01, 0x0F, 0x49, + FRAME_TAIL1_VALUE, FRAME_TAIL2_VALUE, +}; +static const uint8_t GET_EXISTENCE_THRESHOLD[] = { + FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_UNDERLYING_FUNCTION, 0x88, 0x00, 0x01, 0x0F, 0x4C, + FRAME_TAIL1_VALUE, FRAME_TAIL2_VALUE, +}; +static const uint8_t GET_MOTION_THRESHOLD[] = { + FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_UNDERLYING_FUNCTION, 0x89, 0x00, 0x01, 0x0F, 0x4D, + FRAME_TAIL1_VALUE, FRAME_TAIL2_VALUE, +}; +static const uint8_t GET_EXISTENCE_BOUNDARY[] = { + FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_UNDERLYING_FUNCTION, 0x8A, 0x00, 0x01, 0x0F, 0x4E, + FRAME_TAIL1_VALUE, FRAME_TAIL2_VALUE, +}; +static const uint8_t GET_MOTION_BOUNDARY[] = { + FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_UNDERLYING_FUNCTION, 0x8B, 0x00, 0x01, 0x0F, 0x4F, + FRAME_TAIL1_VALUE, FRAME_TAIL2_VALUE, +}; +static const uint8_t GET_MOTION_TRIGGER_TIME[] = { + FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_UNDERLYING_FUNCTION, 0x8C, 0x00, 0x01, 0x0F, 0x50, + FRAME_TAIL1_VALUE, FRAME_TAIL2_VALUE, +}; +static const uint8_t GET_MOTION_TO_REST_TIME[] = { + FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_UNDERLYING_FUNCTION, 0x8D, 0x00, 0x01, 0x0F, 0x51, + FRAME_TAIL1_VALUE, FRAME_TAIL2_VALUE, +}; +static const uint8_t GET_CUSTOM_UNMAN_TIME[] = { + FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_UNDERLYING_FUNCTION, 0x8E, 0x00, 0x01, 0x0F, 0x52, + FRAME_TAIL1_VALUE, FRAME_TAIL2_VALUE, +}; + +static const uint8_t GET_HUMAN_STATUS[] = { + FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_HUMAN_INFORMATION, 0x81, 0x00, 0x01, 0x0F, 0xBD, + FRAME_TAIL1_VALUE, FRAME_TAIL2_VALUE, +}; +static const uint8_t GET_HUMAN_MOTION_INFORMATION[] = { + FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_HUMAN_INFORMATION, 0x82, 0x00, 0x01, 0x0F, 0xBE, + FRAME_TAIL1_VALUE, FRAME_TAIL2_VALUE, +}; +static const uint8_t GET_BODY_MOTION_PARAMETERS[] = { + FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_HUMAN_INFORMATION, 0x83, 0x00, 0x01, 0x0F, 0xBF, + FRAME_TAIL1_VALUE, FRAME_TAIL2_VALUE, +}; +static const uint8_t GET_UNMANNED_TIME[] = { + FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_HUMAN_INFORMATION, 0x8A, 0x00, 0x01, 0x0F, 0xC6, + FRAME_TAIL1_VALUE, FRAME_TAIL2_VALUE, +}; +static const uint8_t GET_KEEP_AWAY[] = { + FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_HUMAN_INFORMATION, 0x8B, 0x00, 0x01, 0x0F, 0xC7, + FRAME_TAIL1_VALUE, FRAME_TAIL2_VALUE, +}; + +} // namespace seeed_mr24hpc1 +} // namespace esphome diff --git a/esphome/components/seeed_mr24hpc1/select/__init__.py b/esphome/components/seeed_mr24hpc1/select/__init__.py new file mode 100644 index 0000000000..7da83627b9 --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/select/__init__.py @@ -0,0 +1,103 @@ +import esphome.codegen as cg +from esphome.components import select +import esphome.config_validation as cv +from esphome.const import ( + ENTITY_CATEGORY_CONFIG, +) +from .. import CONF_MR24HPC1_ID, MR24HPC1Component, mr24hpc1_ns + +SceneModeSelect = mr24hpc1_ns.class_("SceneModeSelect", select.Select) +UnmanTimeSelect = mr24hpc1_ns.class_("UnmanTimeSelect", select.Select) +ExistenceBoundarySelect = mr24hpc1_ns.class_("ExistenceBoundarySelect", select.Select) +MotionBoundarySelect = mr24hpc1_ns.class_("MotionBoundarySelect", select.Select) + +CONF_SCENE_MODE = "scene_mode" +CONF_UNMAN_TIME = "unman_time" +CONF_EXISTENCE_BOUNDARY = "existence_boundary" +CONF_MOTION_BOUNDARY = "motion_boundary" + +CONFIG_SCHEMA = { + cv.GenerateID(CONF_MR24HPC1_ID): cv.use_id(MR24HPC1Component), + cv.Optional(CONF_SCENE_MODE): select.select_schema( + SceneModeSelect, + entity_category=ENTITY_CATEGORY_CONFIG, + icon="mdi:hoop-house", + ), + cv.Optional(CONF_UNMAN_TIME): select.select_schema( + UnmanTimeSelect, + entity_category=ENTITY_CATEGORY_CONFIG, + icon="mdi:timeline-clock", + ), + cv.Optional(CONF_EXISTENCE_BOUNDARY): select.select_schema( + ExistenceBoundarySelect, + entity_category=ENTITY_CATEGORY_CONFIG, + ), + cv.Optional(CONF_MOTION_BOUNDARY): select.select_schema( + MotionBoundarySelect, + entity_category=ENTITY_CATEGORY_CONFIG, + ), +} + + +async def to_code(config): + mr24hpc1_component = await cg.get_variable(config[CONF_MR24HPC1_ID]) + if scenemode_config := config.get(CONF_SCENE_MODE): + s = await select.new_select( + scenemode_config, + options=["None", "Living Room", "Bedroom", "Washroom", "Area Detection"], + ) + await cg.register_parented(s, config[CONF_MR24HPC1_ID]) + cg.add(mr24hpc1_component.set_scene_mode_select(s)) + if unmantime_config := config.get(CONF_UNMAN_TIME): + s = await select.new_select( + unmantime_config, + options=[ + "None", + "10s", + "30s", + "1min", + "2min", + "5min", + "10min", + "30min", + "60min", + ], + ) + await cg.register_parented(s, config[CONF_MR24HPC1_ID]) + cg.add(mr24hpc1_component.set_unman_time_select(s)) + if existence_boundary_config := config.get(CONF_EXISTENCE_BOUNDARY): + s = await select.new_select( + existence_boundary_config, + options=[ + "0.5m", + "1.0m", + "1.5m", + "2.0m", + "2.5m", + "3.0m", + "3.5m", + "4.0m", + "4.5m", + "5.0m", + ], + ) + await cg.register_parented(s, config[CONF_MR24HPC1_ID]) + cg.add(mr24hpc1_component.set_existence_boundary_select(s)) + if motion_boundary_config := config.get(CONF_MOTION_BOUNDARY): + s = await select.new_select( + motion_boundary_config, + options=[ + "0.5m", + "1.0m", + "1.5m", + "2.0m", + "2.5m", + "3.0m", + "3.5m", + "4.0m", + "4.5m", + "5.0m", + ], + ) + await cg.register_parented(s, config[CONF_MR24HPC1_ID]) + cg.add(mr24hpc1_component.set_motion_boundary_select(s)) diff --git a/esphome/components/seeed_mr24hpc1/select/existence_boundary_select.cpp b/esphome/components/seeed_mr24hpc1/select/existence_boundary_select.cpp new file mode 100644 index 0000000000..03c2ec4745 --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/select/existence_boundary_select.cpp @@ -0,0 +1,15 @@ +#include "existence_boundary_select.h" + +namespace esphome { +namespace seeed_mr24hpc1 { + +void ExistenceBoundarySelect::control(const std::string &value) { + this->publish_state(value); + auto index = this->index_of(value); + if (index.has_value()) { + this->parent_->set_existence_boundary(index.value()); + } +} + +} // namespace seeed_mr24hpc1 +} // namespace esphome diff --git a/esphome/components/seeed_mr24hpc1/select/existence_boundary_select.h b/esphome/components/seeed_mr24hpc1/select/existence_boundary_select.h new file mode 100644 index 0000000000..ad770a7296 --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/select/existence_boundary_select.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/select/select.h" +#include "../seeed_mr24hpc1.h" + +namespace esphome { +namespace seeed_mr24hpc1 { + +class ExistenceBoundarySelect : public select::Select, public Parented { + public: + ExistenceBoundarySelect() = default; + + protected: + void control(const std::string &value) override; +}; + +} // namespace seeed_mr24hpc1 +} // namespace esphome diff --git a/esphome/components/seeed_mr24hpc1/select/motion_boundary_select.cpp b/esphome/components/seeed_mr24hpc1/select/motion_boundary_select.cpp new file mode 100644 index 0000000000..619a4f0935 --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/select/motion_boundary_select.cpp @@ -0,0 +1,15 @@ +#include "motion_boundary_select.h" + +namespace esphome { +namespace seeed_mr24hpc1 { + +void MotionBoundarySelect::control(const std::string &value) { + this->publish_state(value); + auto index = this->index_of(value); + if (index.has_value()) { + this->parent_->set_motion_boundary(index.value()); + } +} + +} // namespace seeed_mr24hpc1 +} // namespace esphome diff --git a/esphome/components/seeed_mr24hpc1/select/motion_boundary_select.h b/esphome/components/seeed_mr24hpc1/select/motion_boundary_select.h new file mode 100644 index 0000000000..9058e3130b --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/select/motion_boundary_select.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/select/select.h" +#include "../seeed_mr24hpc1.h" + +namespace esphome { +namespace seeed_mr24hpc1 { + +class MotionBoundarySelect : public select::Select, public Parented { + public: + MotionBoundarySelect() = default; + + protected: + void control(const std::string &value) override; +}; + +} // namespace seeed_mr24hpc1 +} // namespace esphome diff --git a/esphome/components/seeed_mr24hpc1/select/scene_mode_select.cpp b/esphome/components/seeed_mr24hpc1/select/scene_mode_select.cpp new file mode 100644 index 0000000000..153ae603cf --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/select/scene_mode_select.cpp @@ -0,0 +1,15 @@ +#include "scene_mode_select.h" + +namespace esphome { +namespace seeed_mr24hpc1 { + +void SceneModeSelect::control(const std::string &value) { + this->publish_state(value); + auto index = this->index_of(value); + if (index.has_value()) { + this->parent_->set_scene_mode(index.value()); + } +} + +} // namespace seeed_mr24hpc1 +} // namespace esphome diff --git a/esphome/components/seeed_mr24hpc1/select/scene_mode_select.h b/esphome/components/seeed_mr24hpc1/select/scene_mode_select.h new file mode 100644 index 0000000000..95508d49b0 --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/select/scene_mode_select.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/select/select.h" +#include "../seeed_mr24hpc1.h" + +namespace esphome { +namespace seeed_mr24hpc1 { + +class SceneModeSelect : public select::Select, public Parented { + public: + SceneModeSelect() = default; + + protected: + void control(const std::string &value) override; +}; + +} // namespace seeed_mr24hpc1 +} // namespace esphome diff --git a/esphome/components/seeed_mr24hpc1/select/unman_time_select.cpp b/esphome/components/seeed_mr24hpc1/select/unman_time_select.cpp new file mode 100644 index 0000000000..a9d96c8f67 --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/select/unman_time_select.cpp @@ -0,0 +1,15 @@ +#include "unman_time_select.h" + +namespace esphome { +namespace seeed_mr24hpc1 { + +void UnmanTimeSelect::control(const std::string &value) { + this->publish_state(value); + auto index = this->index_of(value); + if (index.has_value()) { + this->parent_->set_unman_time(index.value()); + } +} + +} // namespace seeed_mr24hpc1 +} // namespace esphome diff --git a/esphome/components/seeed_mr24hpc1/select/unman_time_select.h b/esphome/components/seeed_mr24hpc1/select/unman_time_select.h new file mode 100644 index 0000000000..7131988cda --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/select/unman_time_select.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/select/select.h" +#include "../seeed_mr24hpc1.h" + +namespace esphome { +namespace seeed_mr24hpc1 { + +class UnmanTimeSelect : public select::Select, public Parented { + public: + UnmanTimeSelect() = default; + + protected: + void control(const std::string &value) override; +}; + +} // namespace seeed_mr24hpc1 +} // namespace esphome diff --git a/esphome/components/seeed_mr24hpc1/sensor.py b/esphome/components/seeed_mr24hpc1/sensor.py new file mode 100644 index 0000000000..d5eb09e265 --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/sensor.py @@ -0,0 +1,82 @@ +import esphome.codegen as cg +from esphome.components import sensor +import esphome.config_validation as cv +from esphome.const import ( + DEVICE_CLASS_DISTANCE, + DEVICE_CLASS_ENERGY, + DEVICE_CLASS_SPEED, + UNIT_METER, +) +from . import CONF_MR24HPC1_ID, MR24HPC1Component + +CONF_CUSTOM_PRESENCE_OF_DETECTION = "custom_presence_of_detection" +CONF_MOVEMENT_SIGNS = "movement_signs" +CONF_CUSTOM_MOTION_DISTANCE = "custom_motion_distance" +CONF_CUSTOM_SPATIAL_STATIC_VALUE = "custom_spatial_static_value" +CONF_CUSTOM_SPATIAL_MOTION_VALUE = "custom_spatial_motion_value" +CONF_CUSTOM_MOTION_SPEED = "custom_motion_speed" +CONF_CUSTOM_MODE_NUM = "custom_mode_num" + +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(CONF_MR24HPC1_ID): cv.use_id(MR24HPC1Component), + cv.Optional(CONF_CUSTOM_PRESENCE_OF_DETECTION): sensor.sensor_schema( + device_class=DEVICE_CLASS_DISTANCE, + unit_of_measurement=UNIT_METER, + accuracy_decimals=2, # Specify the number of decimal places + icon="mdi:signal-distance-variant", + ), + cv.Optional(CONF_MOVEMENT_SIGNS): sensor.sensor_schema( + icon="mdi:human-greeting-variant", + ), + cv.Optional(CONF_CUSTOM_MOTION_DISTANCE): sensor.sensor_schema( + unit_of_measurement=UNIT_METER, + accuracy_decimals=2, + icon="mdi:signal-distance-variant", + ), + cv.Optional(CONF_CUSTOM_SPATIAL_STATIC_VALUE): sensor.sensor_schema( + device_class=DEVICE_CLASS_ENERGY, + icon="mdi:counter", + ), + cv.Optional(CONF_CUSTOM_SPATIAL_MOTION_VALUE): sensor.sensor_schema( + device_class=DEVICE_CLASS_ENERGY, + icon="mdi:counter", + ), + cv.Optional(CONF_CUSTOM_MOTION_SPEED): sensor.sensor_schema( + unit_of_measurement="m/s", + device_class=DEVICE_CLASS_SPEED, + accuracy_decimals=2, + icon="mdi:run-fast", + ), + cv.Optional(CONF_CUSTOM_MODE_NUM): sensor.sensor_schema( + icon="mdi:counter", + ), + } +) + + +async def to_code(config): + mr24hpc1_component = await cg.get_variable(config[CONF_MR24HPC1_ID]) + if custompresenceofdetection_config := config.get( + CONF_CUSTOM_PRESENCE_OF_DETECTION + ): + sens = await sensor.new_sensor(custompresenceofdetection_config) + cg.add(mr24hpc1_component.set_custom_presence_of_detection_sensor(sens)) + if movementsigns_config := config.get(CONF_MOVEMENT_SIGNS): + sens = await sensor.new_sensor(movementsigns_config) + cg.add(mr24hpc1_component.set_movement_signs_sensor(sens)) + if custommotiondistance_config := config.get(CONF_CUSTOM_MOTION_DISTANCE): + sens = await sensor.new_sensor(custommotiondistance_config) + cg.add(mr24hpc1_component.set_custom_motion_distance_sensor(sens)) + if customspatialstaticvalue_config := config.get(CONF_CUSTOM_SPATIAL_STATIC_VALUE): + sens = await sensor.new_sensor(customspatialstaticvalue_config) + cg.add(mr24hpc1_component.set_custom_spatial_static_value_sensor(sens)) + if customspatialmotionvalue_config := config.get(CONF_CUSTOM_SPATIAL_MOTION_VALUE): + sens = await sensor.new_sensor(customspatialmotionvalue_config) + cg.add(mr24hpc1_component.set_custom_spatial_motion_value_sensor(sens)) + if custommotionspeed_config := config.get(CONF_CUSTOM_MOTION_SPEED): + sens = await sensor.new_sensor(custommotionspeed_config) + cg.add(mr24hpc1_component.set_custom_motion_speed_sensor(sens)) + if custommodenum_config := config.get(CONF_CUSTOM_MODE_NUM): + sens = await sensor.new_sensor(custommodenum_config) + cg.add(mr24hpc1_component.set_custom_mode_num_sensor(sens)) diff --git a/esphome/components/seeed_mr24hpc1/switch/__init__.py b/esphome/components/seeed_mr24hpc1/switch/__init__.py new file mode 100644 index 0000000000..bbf5391a57 --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/switch/__init__.py @@ -0,0 +1,32 @@ +import esphome.codegen as cg +from esphome.components import switch +import esphome.config_validation as cv +from esphome.const import ( + DEVICE_CLASS_SWITCH, + ENTITY_CATEGORY_CONFIG, +) +from .. import CONF_MR24HPC1_ID, MR24HPC1Component, mr24hpc1_ns + +UnderlyingOpenFuncSwitch = mr24hpc1_ns.class_( + "UnderlyOpenFunctionSwitch", switch.Switch +) + +CONF_UNDERLYING_OPEN_FUNCTION = "underlying_open_function" + +CONFIG_SCHEMA = { + cv.GenerateID(CONF_MR24HPC1_ID): cv.use_id(MR24HPC1Component), + cv.Optional(CONF_UNDERLYING_OPEN_FUNCTION): switch.switch_schema( + UnderlyingOpenFuncSwitch, + device_class=DEVICE_CLASS_SWITCH, + entity_category=ENTITY_CATEGORY_CONFIG, + icon="mdi:electric-switch", + ), +} + + +async def to_code(config): + mr24hpc1_component = await cg.get_variable(config[CONF_MR24HPC1_ID]) + if underlying_open_function_config := config.get(CONF_UNDERLYING_OPEN_FUNCTION): + s = await switch.new_switch(underlying_open_function_config) + await cg.register_parented(s, config[CONF_MR24HPC1_ID]) + cg.add(mr24hpc1_component.set_underlying_open_function_switch(s)) diff --git a/esphome/components/seeed_mr24hpc1/switch/underlyFuc_switch.cpp b/esphome/components/seeed_mr24hpc1/switch/underlyFuc_switch.cpp new file mode 100644 index 0000000000..0fcc49bc4c --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/switch/underlyFuc_switch.cpp @@ -0,0 +1,12 @@ +#include "underlyFuc_switch.h" + +namespace esphome { +namespace seeed_mr24hpc1 { + +void UnderlyOpenFunctionSwitch::write_state(bool state) { + this->publish_state(state); + this->parent_->set_underlying_open_function(state); +} + +} // namespace seeed_mr24hpc1 +} // namespace esphome diff --git a/esphome/components/seeed_mr24hpc1/switch/underlyFuc_switch.h b/esphome/components/seeed_mr24hpc1/switch/underlyFuc_switch.h new file mode 100644 index 0000000000..1baabb25ce --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/switch/underlyFuc_switch.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/switch/switch.h" +#include "../seeed_mr24hpc1.h" + +namespace esphome { +namespace seeed_mr24hpc1 { + +class UnderlyOpenFunctionSwitch : public switch_::Switch, public Parented { + public: + UnderlyOpenFunctionSwitch() = default; + + protected: + void write_state(bool state) override; +}; + +} // namespace seeed_mr24hpc1 +} // namespace esphome diff --git a/esphome/components/seeed_mr24hpc1/text_sensor.py b/esphome/components/seeed_mr24hpc1/text_sensor.py new file mode 100644 index 0000000000..aa50f577d4 --- /dev/null +++ b/esphome/components/seeed_mr24hpc1/text_sensor.py @@ -0,0 +1,74 @@ +import esphome.codegen as cg +from esphome.components import text_sensor +import esphome.config_validation as cv +from esphome.const import ENTITY_CATEGORY_DIAGNOSTIC +from . import CONF_MR24HPC1_ID, MR24HPC1Component + +CONF_HEART_BEAT = "heart_beat" +CONF_PRODUCT_MODEL = "product_model" +CONF_PRODUCT_ID = "product_id" +CONF_HARDWARE_MODEL = "hardware_model" +CONF_HARDWARE_VERSION = "hardware_version" + +CONF_KEEP_AWAY = "keep_away" +CONF_MOTION_STATUS = "motion_status" + +CONF_CUSTOM_MODE_END = "custom_mode_end" + + +# The entity category for read only diagnostic values, for example RSSI, uptime or MAC Address +CONFIG_SCHEMA = { + cv.GenerateID(CONF_MR24HPC1_ID): cv.use_id(MR24HPC1Component), + cv.Optional(CONF_HEART_BEAT): text_sensor.text_sensor_schema( + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, icon="mdi:connection" + ), + cv.Optional(CONF_PRODUCT_MODEL): text_sensor.text_sensor_schema( + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, icon="mdi:information-outline" + ), + cv.Optional(CONF_PRODUCT_ID): text_sensor.text_sensor_schema( + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, icon="mdi:information-outline" + ), + cv.Optional(CONF_HARDWARE_MODEL): text_sensor.text_sensor_schema( + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, icon="mdi:information-outline" + ), + cv.Optional(CONF_HARDWARE_VERSION): text_sensor.text_sensor_schema( + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, icon="mdi:information-outline" + ), + cv.Optional(CONF_KEEP_AWAY): text_sensor.text_sensor_schema( + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, icon="mdi:walk" + ), + cv.Optional(CONF_MOTION_STATUS): text_sensor.text_sensor_schema( + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, icon="mdi:human-greeting" + ), + cv.Optional(CONF_CUSTOM_MODE_END): text_sensor.text_sensor_schema( + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, icon="mdi:account-check" + ), +} + + +async def to_code(config): + mr24hpc1_component = await cg.get_variable(config[CONF_MR24HPC1_ID]) + if heartbeat_config := config.get(CONF_HEART_BEAT): + sens = await text_sensor.new_text_sensor(heartbeat_config) + cg.add(mr24hpc1_component.set_heartbeat_state_text_sensor(sens)) + if productmodel_config := config.get(CONF_PRODUCT_MODEL): + sens = await text_sensor.new_text_sensor(productmodel_config) + cg.add(mr24hpc1_component.set_product_model_text_sensor(sens)) + if productid_config := config.get(CONF_PRODUCT_ID): + sens = await text_sensor.new_text_sensor(productid_config) + cg.add(mr24hpc1_component.set_product_id_text_sensor(sens)) + if hardwaremodel_config := config.get(CONF_HARDWARE_MODEL): + sens = await text_sensor.new_text_sensor(hardwaremodel_config) + cg.add(mr24hpc1_component.set_hardware_model_text_sensor(sens)) + if firwareversion_config := config.get(CONF_HARDWARE_VERSION): + sens = await text_sensor.new_text_sensor(firwareversion_config) + cg.add(mr24hpc1_component.set_firware_version_text_sensor(sens)) + if keepaway_config := config.get(CONF_KEEP_AWAY): + sens = await text_sensor.new_text_sensor(keepaway_config) + cg.add(mr24hpc1_component.set_keep_away_text_sensor(sens)) + if motionstatus_config := config.get(CONF_MOTION_STATUS): + sens = await text_sensor.new_text_sensor(motionstatus_config) + cg.add(mr24hpc1_component.set_motion_status_text_sensor(sens)) + if custommodeend_config := config.get(CONF_CUSTOM_MODE_END): + sens = await text_sensor.new_text_sensor(custommodeend_config) + cg.add(mr24hpc1_component.set_custom_mode_end_text_sensor(sens)) diff --git a/tests/components/seeed_mr24hpc1/common.yaml b/tests/components/seeed_mr24hpc1/common.yaml new file mode 100644 index 0000000000..38692b3e5e --- /dev/null +++ b/tests/components/seeed_mr24hpc1/common.yaml @@ -0,0 +1,92 @@ +uart: + - id: seeed_mr24hpc1_uart + tx_pin: ${uart_tx_pin} + rx_pin: ${uart_rx_pin} + baud_rate: 115200 + parity: NONE + stop_bits: 1 + +seeed_mr24hpc1: + id: my_seeed_mr24hpc1 + uart_id: seeed_mr24hpc1_uart + +sensor: + - platform: seeed_mr24hpc1 + custom_presence_of_detection: + name: "Static Distance" + movement_signs: + name: "Body Movement Parameter" + custom_motion_distance: + name: "Motion Distance" + custom_spatial_static_value: + name: "Existence Energy" + custom_spatial_motion_value: + name: "Motion Energy" + custom_motion_speed: + name: "Motion Speed" + custom_mode_num: + name: "Current Custom Mode" + +binary_sensor: + - platform: seeed_mr24hpc1 + has_target: + name: "Presence Information" + +switch: + - platform: seeed_mr24hpc1 + underlying_open_function: + name: Underlying Open Function Info Output Switch + +text_sensor: + - platform: seeed_mr24hpc1 + heart_beat: + name: "Heartbeat" + product_model: + name: "Product Model" + product_id: + name: "Product ID" + hardware_model: + name: "Hardware Model" + hardware_version: + name: "Hardware Version" + keep_away: + name: "Active Reporting Of Proximity" + motion_status: + name: "Motion Information" + custom_mode_end: + name: "Custom Mode Status" + +number: + - platform: seeed_mr24hpc1 + sensitivity: + name: "Sensitivity" + custom_mode: + name: "Custom Mode" + existence_threshold: + name: "Existence Energy Threshold" + motion_threshold: + name: "Motion Energy Threshold" + motion_trigger: + name: "Motion Trigger Time" + motion_to_rest: + name: "Motion To Rest Time" + custom_unman_time: + name: "Time For Entering No Person State (Underlying Open Function)" + +select: + - platform: seeed_mr24hpc1 + scene_mode: + name: "Scene" + unman_time: + name: "Time For Entering No Person State (Standard Function)" + existence_boundary: + name: "Existence Boundary" + motion_boundary: + name: "Motion Boundary" + +button: + - platform: seeed_mr24hpc1 + restart: + name: "Module Restart" + custom_set_end: + name: "End Of Custom Mode Settings" diff --git a/tests/components/seeed_mr24hpc1/test.esp32-c3-idf.yaml b/tests/components/seeed_mr24hpc1/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..4fb884abf4 --- /dev/null +++ b/tests/components/seeed_mr24hpc1/test.esp32-c3-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + uart_tx_pin: GPIO5 + uart_rx_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/seeed_mr24hpc1/test.esp32-c3.yaml b/tests/components/seeed_mr24hpc1/test.esp32-c3.yaml new file mode 100644 index 0000000000..4fb884abf4 --- /dev/null +++ b/tests/components/seeed_mr24hpc1/test.esp32-c3.yaml @@ -0,0 +1,5 @@ +substitutions: + uart_tx_pin: GPIO5 + uart_rx_pin: GPIO4 + +<<: !include common.yaml From b0a192d6a5ae8d79b70dfa1ccc7edf2bd2706b2c Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Tue, 12 Mar 2024 15:26:31 +1100 Subject: [PATCH 1060/2101] Add getter for font glyph data (#6355) --- esphome/components/font/font.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/components/font/font.h b/esphome/components/font/font.h index 91bcd399ba..57002cf510 100644 --- a/esphome/components/font/font.h +++ b/esphome/components/font/font.h @@ -30,6 +30,8 @@ class Glyph { void scan_area(int *x1, int *y1, int *width, int *height) const; + const GlyphData *get_glyph_data() const { return this->glyph_data_; } + protected: friend Font; From f5b02056b95a4d3af6b854e714d0657ce65f93cd Mon Sep 17 00:00:00 2001 From: Manuel Kasper Date: Tue, 12 Mar 2024 11:35:29 +0100 Subject: [PATCH 1061/2101] Require reset_pin for certain waveshare_epaper models in YAML validation (#6357) --- esphome/components/waveshare_epaper/display.py | 11 +++++++++++ .../waveshare_epaper/test.esp32.yaml | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/esphome/components/waveshare_epaper/display.py b/esphome/components/waveshare_epaper/display.py index 744ae8848f..dc43cbf5a7 100644 --- a/esphome/components/waveshare_epaper/display.py +++ b/esphome/components/waveshare_epaper/display.py @@ -131,6 +131,8 @@ MODELS = { "1.54in-m5coreink-m09": ("c", GDEW0154M09), } +RESET_PIN_REQUIRED_MODELS = ("2.13inv2", "2.13in-ttgo-b74") + def validate_full_update_every_only_types_ac(value): if CONF_FULL_UPDATE_EVERY not in value: @@ -147,6 +149,14 @@ def validate_full_update_every_only_types_ac(value): return value +def validate_reset_pin_required(config): + if config[CONF_MODEL] in RESET_PIN_REQUIRED_MODELS and CONF_RESET_PIN not in config: + raise cv.Invalid( + f"'{CONF_RESET_PIN}' is required for model {config[CONF_MODEL]}" + ) + return config + + CONFIG_SCHEMA = cv.All( display.FULL_DISPLAY_SCHEMA.extend( { @@ -165,6 +175,7 @@ CONFIG_SCHEMA = cv.All( .extend(cv.polling_component_schema("1s")) .extend(spi.spi_device_schema()), validate_full_update_every_only_types_ac, + validate_reset_pin_required, cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA), ) diff --git a/tests/components/waveshare_epaper/test.esp32.yaml b/tests/components/waveshare_epaper/test.esp32.yaml index 616698f902..cc6c665e7d 100644 --- a/tests/components/waveshare_epaper/test.esp32.yaml +++ b/tests/components/waveshare_epaper/test.esp32.yaml @@ -28,6 +28,24 @@ display: full_update_every: 30 lambda: |- it.rectangle(0, 0, it.get_width(), it.get_height()); + - platform: waveshare_epaper + model: 2.13in-ttgo-b74 + spi_id: spi_id_1 + cs_pin: + allow_other_uses: true + number: GPIO25 + dc_pin: + allow_other_uses: true + number: GPIO26 + busy_pin: + allow_other_uses: true + number: GPIO27 + reset_pin: + allow_other_uses: true + number: GPIO32 + full_update_every: 30 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); - platform: waveshare_epaper model: 2.90in spi_id: spi_id_1 From f264151537729625b86a62d2b34a85781abc8443 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Wed, 13 Mar 2024 05:20:16 +1100 Subject: [PATCH 1062/2101] touchscreen driver fixes (#6356) --- .../ft5x06/touchscreen/ft5x06_touchscreen.h | 2 +- esphome/components/touchscreen/touchscreen.cpp | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/esphome/components/ft5x06/touchscreen/ft5x06_touchscreen.h b/esphome/components/ft5x06/touchscreen/ft5x06_touchscreen.h index 0a1e51227d..7ddd2e44d7 100644 --- a/esphome/components/ft5x06/touchscreen/ft5x06_touchscreen.h +++ b/esphome/components/ft5x06/touchscreen/ft5x06_touchscreen.h @@ -71,7 +71,7 @@ class FT5x06Touchscreen : public touchscreen::Touchscreen, public i2c::I2CDevice 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(); } } esph_log_config(TAG, "FT5x06 Touchscreen setup complete"); diff --git a/esphome/components/touchscreen/touchscreen.cpp b/esphome/components/touchscreen/touchscreen.cpp index 83783a634f..b9498de152 100644 --- a/esphome/components/touchscreen/touchscreen.cpp +++ b/esphome/components/touchscreen/touchscreen.cpp @@ -39,7 +39,6 @@ void Touchscreen::loop() { ESP_LOGVV(TAG, "<< Do Touch loop >>"); this->first_touch_ = this->touches_.empty(); this->need_update_ = false; - this->was_touched_ = this->is_touched_; this->is_touched_ = false; this->skip_update_ = false; for (auto &tp : this->touches_) { @@ -62,7 +61,11 @@ void Touchscreen::loop() { if (this->touch_timeout_ > 0) { // Simulate a touch after touch_timeout_> ms. This will reset any existing timeout operation. // This is to detect touch release. - this->set_timeout(TAG, this->touch_timeout_, [this]() { this->store_.touched = true; }); + if (this->is_touched_) { + this->set_timeout(TAG, this->touch_timeout_, [this]() { this->store_.touched = true; }); + } else { + this->cancel_timeout(TAG); + } } } } @@ -111,6 +114,7 @@ void Touchscreen::add_raw_touch_position_(uint8_t id, int16_t x_raw, int16_t y_r void Touchscreen::send_touches_() { TouchPoints_t touches; + ESP_LOGV(TAG, "Touch status: is_touched=%d, was_touched=%d", this->is_touched_, this->was_touched_); for (auto tp : this->touches_) { ESP_LOGV(TAG, "Touch status: %d/%d: raw:(%4d,%4d,%4d) calc:(%3d,%4d)", tp.second.id, tp.second.state, tp.second.x_raw, tp.second.y_raw, tp.second.z_raw, tp.second.x, tp.second.y); @@ -124,14 +128,10 @@ void Touchscreen::send_touches_() { } if (!this->is_touched_) { if (this->was_touched_) { - if (this->touch_timeout_ > 0) { - this->cancel_timeout(TAG); - } this->release_trigger_.trigger(); for (auto *listener : this->touch_listeners_) listener->release(); this->touches_.clear(); - this->was_touched_ = false; } } else { if (this->first_touch_) { @@ -142,6 +142,7 @@ void Touchscreen::send_touches_() { } } } + this->was_touched_ = this->is_touched_; } int16_t Touchscreen::normalize_(int16_t val, int16_t min_val, int16_t max_val, bool inverted) { From d3a028f7fa4174ab6d2e5fbb10e4374454480124 Mon Sep 17 00:00:00 2001 From: M-A Date: Tue, 12 Mar 2024 16:22:28 -0400 Subject: [PATCH 1063/2101] Make USE_HOST compilable on msys2 (#6359) --- esphome/core/helpers.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/core/helpers.cpp b/esphome/core/helpers.cpp index cec8a82d04..0f7afc6a4e 100644 --- a/esphome/core/helpers.cpp +++ b/esphome/core/helpers.cpp @@ -12,9 +12,11 @@ #include #ifdef USE_HOST +#ifndef _WIN32 #include #include #include +#endif #include #endif #if defined(USE_ESP8266) From 2df9c30446f471e8754beeb89b2e45ca57e1c786 Mon Sep 17 00:00:00 2001 From: Landon Rohatensky Date: Tue, 12 Mar 2024 16:07:40 -0700 Subject: [PATCH 1064/2101] download font from url on build (#5254) Co-authored-by: guillempages Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Co-authored-by: clydebarrow <2366188+clydebarrow@users.noreply.github.com> --- esphome/components/font/__init__.py | 145 +++++++++++++++++++------- esphome/external_files.py | 4 +- tests/components/font/test.esp32.yaml | 11 ++ tests/test2.yaml | 5 - 4 files changed, 122 insertions(+), 43 deletions(-) diff --git a/esphome/components/font/__init__.py b/esphome/components/font/__init__.py index 6473ef53dc..76eb05e6ad 100644 --- a/esphome/components/font/__init__.py +++ b/esphome/components/font/__init__.py @@ -1,13 +1,15 @@ +import hashlib +import logging + import functools from pathlib import Path -import hashlib import os import re from packaging import version - import requests from esphome import core +from esphome import external_files import esphome.config_validation as cv import esphome.codegen as cg from esphome.helpers import ( @@ -15,21 +17,26 @@ from esphome.helpers import ( cpp_string_escape, ) from esphome.const import ( + __version__, CONF_FAMILY, CONF_FILE, CONF_GLYPHS, CONF_ID, CONF_RAW_DATA_ID, CONF_TYPE, + CONF_REFRESH, CONF_SIZE, CONF_PATH, CONF_WEIGHT, + CONF_URL, ) from esphome.core import ( CORE, HexInt, ) +_LOGGER = logging.getLogger(__name__) + DOMAIN = "font" DEPENDENCIES = ["display"] MULTI_CONF = True @@ -125,20 +132,10 @@ def validate_truetype_file(value): return cv.file_(value) -def _compute_local_font_dir(name) -> Path: - h = hashlib.new("sha256") - h.update(name.encode()) - return Path(CORE.data_dir) / DOMAIN / h.hexdigest()[:8] - - -def _compute_gfonts_local_path(value) -> Path: - name = f"{value[CONF_FAMILY]}@{value[CONF_WEIGHT]}@{value[CONF_ITALIC]}@v1" - return _compute_local_font_dir(name) / "font.ttf" - - TYPE_LOCAL = "local" TYPE_LOCAL_BITMAP = "local_bitmap" TYPE_GFONTS = "gfonts" +TYPE_WEB = "web" LOCAL_SCHEMA = cv.Schema( { cv.Required(CONF_PATH): validate_truetype_file, @@ -169,21 +166,64 @@ def validate_weight_name(value): return FONT_WEIGHTS[cv.one_of(*FONT_WEIGHTS, lower=True, space="-")(value)] -def download_gfonts(value): +def _compute_local_font_path(value: dict) -> 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_font_path: base_dir=%s", base_dir / key) + return base_dir / key + + +def get_font_path(value, type) -> Path: + if type == TYPE_GFONTS: + name = f"{value[CONF_FAMILY]}@{value[CONF_WEIGHT]}@{value[CONF_ITALIC]}@v1" + return external_files.compute_local_file_dir(DOMAIN) / f"{name}.ttf" + if type == TYPE_WEB: + return _compute_local_font_path(value) / "font.ttf" + return None + + +def download_content(url: str, path: Path) -> None: + if not external_files.has_remote_file_changed(url, path): + _LOGGER.debug("Remote file has not changed %s", url) + return + + _LOGGER.debug( + "Remote file has changed, downloading from %s to %s", + url, + path, + ) + + try: + req = requests.get( + url, + timeout=external_files.NETWORK_TIMEOUT, + headers={"User-agent": f"ESPHome/{__version__} (https://esphome.io)"}, + ) + req.raise_for_status() + except requests.exceptions.RequestException as e: + raise cv.Invalid(f"Could not download from {url}: {e}") + + path.parent.mkdir(parents=True, exist_ok=True) + path.write_bytes(req.content) + + +def download_gfont(value): name = ( f"{value[CONF_FAMILY]}:ital,wght@{int(value[CONF_ITALIC])},{value[CONF_WEIGHT]}" ) url = f"https://fonts.googleapis.com/css2?family={name}" + path = get_font_path(value, TYPE_GFONTS) + _LOGGER.debug("download_gfont: path=%s", path) - path = _compute_gfonts_local_path(value) - if path.is_file(): - return value try: - req = requests.get(url, timeout=30) + req = requests.get(url, timeout=external_files.NETWORK_TIMEOUT) req.raise_for_status() except requests.exceptions.RequestException as e: raise cv.Invalid( - f"Could not download font for {name}, please check the fonts exists " + f"Could not download font at {url}, please check the fonts exists " f"at google fonts ({e})" ) match = re.search(r"src:\s+url\((.+)\)\s+format\('truetype'\);", req.text) @@ -194,26 +234,48 @@ def download_gfonts(value): ) ttf_url = match.group(1) - try: - req = requests.get(ttf_url, timeout=30) - req.raise_for_status() - except requests.exceptions.RequestException as e: - raise cv.Invalid(f"Could not download ttf file for {name} ({ttf_url}): {e}") + _LOGGER.debug("download_gfont: ttf_url=%s", ttf_url) - path.parent.mkdir(exist_ok=True, parents=True) - path.write_bytes(req.content) + download_content(ttf_url, path) return value -GFONTS_SCHEMA = cv.All( +def download_web_font(value): + url = value[CONF_URL] + path = get_font_path(value, TYPE_WEB) + + download_content(url, path) + _LOGGER.debug("download_web_font: path=%s", path) + return value + + +EXTERNAL_FONT_SCHEMA = cv.Schema( { - cv.Required(CONF_FAMILY): cv.string_strict, cv.Optional(CONF_WEIGHT, default="regular"): cv.Any( cv.int_, validate_weight_name ), cv.Optional(CONF_ITALIC, default=False): cv.boolean, - }, - download_gfonts, + cv.Optional(CONF_REFRESH, default="1d"): cv.All(cv.string, cv.source_refresh), + } +) + + +GFONTS_SCHEMA = cv.All( + EXTERNAL_FONT_SCHEMA.extend( + { + cv.Required(CONF_FAMILY): cv.string_strict, + } + ), + download_gfont, +) + +WEB_FONT_SCHEMA = cv.All( + EXTERNAL_FONT_SCHEMA.extend( + { + cv.Required(CONF_URL): cv.string_strict, + } + ), + download_web_font, ) @@ -233,6 +295,14 @@ def validate_file_shorthand(value): data[CONF_WEIGHT] = weight[1:] return FILE_SCHEMA(data) + if value.startswith("http://") or value.startswith("https://"): + return FILE_SCHEMA( + { + CONF_TYPE: TYPE_WEB, + CONF_URL: value, + } + ) + if value.endswith(".pcf") or value.endswith(".bdf"): return FILE_SCHEMA( { @@ -254,6 +324,7 @@ TYPED_FILE_SCHEMA = cv.typed_schema( TYPE_LOCAL: LOCAL_SCHEMA, TYPE_GFONTS: GFONTS_SCHEMA, TYPE_LOCAL_BITMAP: LOCAL_BITMAP_SCHEMA, + TYPE_WEB: WEB_FONT_SCHEMA, } ) @@ -264,7 +335,7 @@ def _file_schema(value): return TYPED_FILE_SCHEMA(value) -FILE_SCHEMA = cv.Schema(_file_schema) +FILE_SCHEMA = cv.All(_file_schema) DEFAULT_GLYPHS = ( ' !"%()+=,-.:/?0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz°' @@ -288,7 +359,7 @@ FONT_SCHEMA = cv.Schema( ), cv.GenerateID(CONF_RAW_DATA_ID): cv.declare_id(cg.uint8), cv.GenerateID(CONF_RAW_GLYPH_ID): cv.declare_id(GlyphData), - } + }, ) CONFIG_SCHEMA = cv.All(validate_pillow_installed, FONT_SCHEMA, merge_glyphs) @@ -343,8 +414,8 @@ class EFont: elif ftype == TYPE_LOCAL: path = CORE.relative_config_path(file[CONF_PATH]) font = load_ttf_font(path, size) - elif ftype == TYPE_GFONTS: - path = _compute_gfonts_local_path(file) + elif ftype in (TYPE_GFONTS, TYPE_WEB): + path = get_font_path(file, ftype) font = load_ttf_font(path, size) else: raise cv.Invalid(f"Could not load font: unknown type: {ftype}") @@ -361,9 +432,9 @@ def convert_bitmap_to_pillow_font(filepath): BdfFontFile, ) - local_bitmap_font_file = _compute_local_font_dir(filepath) / os.path.basename( - filepath - ) + local_bitmap_font_file = external_files.compute_local_file_dir( + DOMAIN, + ) / os.path.basename(filepath) copy_file_if_changed(filepath, local_bitmap_font_file) diff --git a/esphome/external_files.py b/esphome/external_files.py index 5b476286f3..a1422d02b1 100644 --- a/esphome/external_files.py +++ b/esphome/external_files.py @@ -33,7 +33,9 @@ def has_remote_file_changed(url, local_file_path): IF_MODIFIED_SINCE: local_modification_time_str, CACHE_CONTROL: CACHE_CONTROL_MAX_AGE + "3600", } - response = requests.head(url, headers=headers, timeout=NETWORK_TIMEOUT) + response = requests.head( + url, headers=headers, timeout=NETWORK_TIMEOUT, allow_redirects=True + ) _LOGGER.debug( "has_remote_file_changed: File %s, Local modified %s, response code %d", diff --git a/tests/components/font/test.esp32.yaml b/tests/components/font/test.esp32.yaml index 9d699a1752..d142463893 100644 --- a/tests/components/font/test.esp32.yaml +++ b/tests/components/font/test.esp32.yaml @@ -6,6 +6,17 @@ font: extras: - file: "gfonts://Roboto" glyphs: ["\u00C4", "\u00C5", "\U000000C7"] + - file: "gfonts://Roboto" + id: roboto_web + size: 20 + - file: "https://github.com/IdreesInc/Monocraft/releases/download/v3.0/Monocraft.ttf" + id: monocraft + size: 20 + - file: + type: web + url: "https://github.com/IdreesInc/Monocraft/releases/download/v3.0/Monocraft.ttf" + id: monocraft2 + size: 24 spi: clk_pin: 14 diff --git a/tests/test2.yaml b/tests/test2.yaml index 217a4c8feb..a1e310be9c 100644 --- a/tests/test2.yaml +++ b/tests/test2.yaml @@ -812,11 +812,6 @@ image: file: mdi:alert-outline type: BINARY -font: - - file: "gfonts://Roboto" - id: roboto - size: 20 - graph: - id: my_graph sensor: ha_hello_world_temperature From c7305e15a7a5181cce3db77ba9842afcceb7cfa5 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Wed, 13 Mar 2024 10:14:57 +1100 Subject: [PATCH 1065/2101] Add driver for quad SPI AMOLED displays (#6354) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- CODEOWNERS | 1 + esphome/components/qspi_amoled/__init__.py | 1 + esphome/components/qspi_amoled/display.py | 131 ++++++++++++++ .../components/qspi_amoled/qspi_amoled.cpp | 165 ++++++++++++++++++ esphome/components/qspi_amoled/qspi_amoled.h | 165 ++++++++++++++++++ .../qspi_amoled/test.esp32-s3-idf.yaml | 36 ++++ 6 files changed, 499 insertions(+) create mode 100644 esphome/components/qspi_amoled/__init__.py create mode 100644 esphome/components/qspi_amoled/display.py create mode 100644 esphome/components/qspi_amoled/qspi_amoled.cpp create mode 100644 esphome/components/qspi_amoled/qspi_amoled.h create mode 100644 tests/components/qspi_amoled/test.esp32-s3-idf.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 64005b1a81..483672bf54 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -269,6 +269,7 @@ esphome/components/pvvx_mithermometer/* @pasiz esphome/components/pylontech/* @functionpointer esphome/components/qmp6988/* @andrewpc esphome/components/qr_code/* @wjtje +esphome/components/qspi_amoled/* @clydebarrow esphome/components/qwiic_pir/* @kahrendt esphome/components/radon_eye_ble/* @jeffeb3 esphome/components/radon_eye_rd200/* @jeffeb3 diff --git a/esphome/components/qspi_amoled/__init__.py b/esphome/components/qspi_amoled/__init__.py new file mode 100644 index 0000000000..c58ce8a01e --- /dev/null +++ b/esphome/components/qspi_amoled/__init__.py @@ -0,0 +1 @@ +CODEOWNERS = ["@clydebarrow"] diff --git a/esphome/components/qspi_amoled/display.py b/esphome/components/qspi_amoled/display.py new file mode 100644 index 0000000000..84bf9553cb --- /dev/null +++ b/esphome/components/qspi_amoled/display.py @@ -0,0 +1,131 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome import pins +from esphome.components import ( + spi, + display, +) +from esphome.const import ( + CONF_RESET_PIN, + CONF_ID, + CONF_DIMENSIONS, + CONF_WIDTH, + CONF_HEIGHT, + CONF_LAMBDA, + CONF_BRIGHTNESS, + CONF_ENABLE_PIN, + CONF_MODEL, + CONF_OFFSET_HEIGHT, + CONF_OFFSET_WIDTH, + CONF_INVERT_COLORS, + CONF_MIRROR_X, + CONF_MIRROR_Y, + CONF_SWAP_XY, + CONF_COLOR_ORDER, + CONF_TRANSFORM, +) + +DEPENDENCIES = ["spi"] + +qspi_amoled_ns = cg.esphome_ns.namespace("qspi_amoled") +QSPI_AMOLED = qspi_amoled_ns.class_( + "QspiAmoLed", display.Display, display.DisplayBuffer, cg.Component, spi.SPIDevice +) +ColorOrder = display.display_ns.enum("ColorMode") +Model = qspi_amoled_ns.enum("Model") + +MODELS = {"RM690B0": Model.RM690B0, "RM67162": Model.RM67162} + +COLOR_ORDERS = { + "RGB": ColorOrder.COLOR_ORDER_RGB, + "BGR": ColorOrder.COLOR_ORDER_BGR, +} +DATA_PIN_SCHEMA = pins.internal_gpio_output_pin_schema + +CONFIG_SCHEMA = cv.All( + display.FULL_DISPLAY_SCHEMA.extend( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(QSPI_AMOLED), + cv.Required(CONF_MODEL): cv.enum(MODELS, upper=True), + cv.Required(CONF_DIMENSIONS): cv.Any( + cv.dimensions, + cv.Schema( + { + cv.Required(CONF_WIDTH): cv.int_, + cv.Required(CONF_HEIGHT): cv.int_, + cv.Optional(CONF_OFFSET_HEIGHT, default=0): cv.int_, + cv.Optional(CONF_OFFSET_WIDTH, default=0): cv.int_, + } + ), + ), + cv.Optional(CONF_TRANSFORM): cv.Schema( + { + cv.Optional(CONF_MIRROR_X, default=False): cv.boolean, + cv.Optional(CONF_MIRROR_Y, default=False): cv.boolean, + cv.Optional(CONF_SWAP_XY, default=False): cv.boolean, + } + ), + cv.Optional(CONF_COLOR_ORDER, default="RGB"): cv.enum( + COLOR_ORDERS, upper=True + ), + cv.Optional(CONF_INVERT_COLORS, default=False): cv.boolean, + cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, + cv.Optional(CONF_ENABLE_PIN): pins.gpio_output_pin_schema, + cv.Optional(CONF_BRIGHTNESS, default=0xD0): cv.int_range( + 0, 0xFF, min_included=True, max_included=True + ), + } + ).extend( + spi.spi_device_schema( + cs_pin_required=False, + default_mode="MODE0", + default_data_rate=10e6, + quad=True, + ) + ) + ), + cv.only_with_esp_idf, +) + + +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) + + cg.add(var.set_color_mode(config[CONF_COLOR_ORDER])) + cg.add(var.set_invert_colors(config[CONF_INVERT_COLORS])) + cg.add(var.set_brightness(config[CONF_BRIGHTNESS])) + cg.add(var.set_model(config[CONF_MODEL])) + if enable_pin := config.get(CONF_ENABLE_PIN): + enable = await cg.gpio_pin_expression(enable_pin) + cg.add(var.set_enable_pin(enable)) + + if reset_pin := config.get(CONF_RESET_PIN): + reset = await cg.gpio_pin_expression(reset_pin) + cg.add(var.set_reset_pin(reset)) + + if transform := config.get(CONF_TRANSFORM): + cg.add(var.set_mirror_x(transform[CONF_MIRROR_X])) + cg.add(var.set_mirror_y(transform[CONF_MIRROR_Y])) + cg.add(var.set_swap_xy(transform[CONF_SWAP_XY])) + + if CONF_DIMENSIONS in config: + dimensions = config[CONF_DIMENSIONS] + if isinstance(dimensions, dict): + cg.add(var.set_dimensions(dimensions[CONF_WIDTH], dimensions[CONF_HEIGHT])) + cg.add( + var.set_offsets( + dimensions[CONF_OFFSET_WIDTH], dimensions[CONF_OFFSET_HEIGHT] + ) + ) + else: + (width, height) = dimensions + cg.add(var.set_dimensions(width, height)) + + if lamb := config.get(CONF_LAMBDA): + lambda_ = await cg.process_lambda( + lamb, [(display.DisplayRef, "it")], return_type=cg.void + ) + cg.add(var.set_writer(lambda_)) diff --git a/esphome/components/qspi_amoled/qspi_amoled.cpp b/esphome/components/qspi_amoled/qspi_amoled.cpp new file mode 100644 index 0000000000..697989e861 --- /dev/null +++ b/esphome/components/qspi_amoled/qspi_amoled.cpp @@ -0,0 +1,165 @@ +#ifdef USE_ESP_IDF +#include "qspi_amoled.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace qspi_amoled { + +void QspiAmoLed::setup() { + esph_log_config(TAG, "Setting up QSPI_AMOLED"); + this->spi_setup(); + if (this->enable_pin_ != nullptr) { + this->enable_pin_->setup(); + this->enable_pin_->digital_write(true); + } + if (this->reset_pin_ != nullptr) { + this->reset_pin_->setup(); + this->reset_pin_->digital_write(true); + delay(5); + this->reset_pin_->digital_write(false); + delay(5); + this->reset_pin_->digital_write(true); + } + this->set_timeout(120, [this] { this->write_command_(SLEEP_OUT); }); + this->set_timeout(240, [this] { this->write_init_sequence_(); }); +} + +void QspiAmoLed::update() { + this->do_update_(); + int w = this->x_high_ - this->x_low_ + 1; + int h = this->y_high_ - this->y_low_ + 1; + this->draw_pixels_at(this->x_low_, this->y_low_, w, h, this->buffer_, this->color_mode_, display::COLOR_BITNESS_565, + true, this->x_low_, this->y_low_, this->get_width_internal() - w - this->x_low_); + // invalidate watermarks + this->x_low_ = this->width_; + this->y_low_ = this->height_; + this->x_high_ = 0; + this->y_high_ = 0; +} + +void QspiAmoLed::draw_absolute_pixel_internal(int x, int y, Color color) { + if (x >= this->get_width_internal() || x < 0 || y >= this->get_height_internal() || y < 0) { + return; + } + if (this->buffer_ == nullptr) + this->init_internal_(this->width_ * this->height_ * 2); + if (this->is_failed()) + return; + uint32_t pos = (y * this->width_) + x; + uint16_t new_color; + bool updated = false; + pos = pos * 2; + new_color = display::ColorUtil::color_to_565(color, display::ColorOrder::COLOR_ORDER_RGB); + if (this->buffer_[pos] != (uint8_t) (new_color >> 8)) { + this->buffer_[pos] = (uint8_t) (new_color >> 8); + updated = true; + } + pos = pos + 1; + new_color = new_color & 0xFF; + + if (this->buffer_[pos] != new_color) { + this->buffer_[pos] = new_color; + updated = true; + } + if (updated) { + // low and high watermark may speed up drawing from buffer + if (x < this->x_low_) + this->x_low_ = x; + if (y < this->y_low_) + this->y_low_ = y; + if (x > this->x_high_) + this->x_high_ = x; + if (y > this->y_high_) + this->y_high_ = y; + } +} + +void QspiAmoLed::reset_params_(bool ready) { + if (!ready && !this->is_ready()) + return; + this->write_command_(this->invert_colors_ ? INVERT_ON : INVERT_OFF); + // custom x/y transform and color order + uint8_t mad = this->color_mode_ == display::COLOR_ORDER_BGR ? MADCTL_BGR : MADCTL_RGB; + if (this->swap_xy_) + mad |= MADCTL_MV; + if (this->mirror_x_) + mad |= MADCTL_MX; + if (this->mirror_y_) + mad |= MADCTL_MY; + this->write_command_(MADCTL_CMD, &mad, 1); + this->write_command_(BRIGHTNESS, &this->brightness_, 1); +} + +void QspiAmoLed::write_init_sequence_() { + if (this->model_ == RM690B0) { + this->write_command_(PAGESEL, 0x20); + this->write_command_(MIPI, 0x0A); + this->write_command_(WRAM, 0x80); + this->write_command_(SWIRE1, 0x51); + this->write_command_(SWIRE2, 0x2E); + this->write_command_(PAGESEL, 0x00); + this->write_command_(0xC2, 0x00); + delay(10); + this->write_command_(TEON, 0x00); + } + this->write_command_(PIXFMT, 0x55); + this->write_command_(BRIGHTNESS, 0); + this->write_command_(DISPLAY_ON); + this->reset_params_(true); + this->setup_complete_ = true; + esph_log_config(TAG, "QSPI_AMOLED setup complete"); +} + +void QspiAmoLed::set_addr_window_(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) { + uint8_t buf[4]; + x1 += this->offset_x_; + x2 += this->offset_x_; + y1 += this->offset_y_; + y2 += this->offset_y_; + put16_be(buf, x1); + put16_be(buf + 2, x2); + this->write_command_(CASET, buf, sizeof buf); + put16_be(buf, y1); + put16_be(buf + 2, y2); + this->write_command_(RASET, buf, sizeof buf); +} + +void QspiAmoLed::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) { + if (!this->setup_complete_ || this->is_failed()) + return; + if (w <= 0 || h <= 0) + return; + if (bitness != display::COLOR_BITNESS_565 || order != this->color_mode_ || + big_endian != (this->bit_order_ == spi::BIT_ORDER_MSB_FIRST)) { + return display::Display::draw_pixels_at(x_start, y_start, w, h, ptr, order, bitness, big_endian, x_offset, y_offset, + x_pad); + } + this->set_addr_window_(x_start, y_start, x_start + w - 1, y_start + h - 1); + this->enable(); + // x_ and y_offset are offsets into the source buffer, unrelated to our own offsets into the display. + if (x_offset == 0 && x_pad == 0 && y_offset == 0) { + // we could deal here with a non-zero y_offset, but if x_offset is zero, y_offset probably will be so don't bother + this->write_cmd_addr_data(8, 0x32, 24, 0x2C00, ptr, w * h * 2, 4); + } else { + this->write_cmd_addr_data(8, 0x32, 24, 0x2C00, nullptr, 0, 4); + auto stride = x_offset + w + x_pad; + for (int y = 0; y != h; y++) { + this->write_cmd_addr_data(0, 0, 0, 0, ptr + ((y + y_offset) * stride + x_offset) * 2, w * 2, 4); + } + } + this->disable(); +} + +void QspiAmoLed::dump_config() { + ESP_LOGCONFIG("", "QSPI AMOLED"); + ESP_LOGCONFIG(TAG, " Height: %u", this->height_); + ESP_LOGCONFIG(TAG, " Width: %u", this->width_); + LOG_PIN(" CS Pin: ", this->cs_); + LOG_PIN(" Reset Pin: ", this->reset_pin_); + ESP_LOGCONFIG(TAG, " SPI Data rate: %dMHz", (unsigned) (this->data_rate_ / 1000000)); +} + +} // namespace qspi_amoled +} // namespace esphome +#endif diff --git a/esphome/components/qspi_amoled/qspi_amoled.h b/esphome/components/qspi_amoled/qspi_amoled.h new file mode 100644 index 0000000000..28d243f548 --- /dev/null +++ b/esphome/components/qspi_amoled/qspi_amoled.h @@ -0,0 +1,165 @@ +// +// Created by Clyde Stubbs on 29/10/2023. +// +#pragma once + +#ifdef USE_ESP_IDF +#include "esphome/core/component.h" +#include "esphome/components/spi/spi.h" +#include "esphome/components/display/display.h" +#include "esphome/components/display/display_buffer.h" +#include "esphome/components/display/display_color_utils.h" +#include "esp_lcd_panel_ops.h" + +#include "esp_lcd_panel_rgb.h" + +namespace esphome { +namespace qspi_amoled { + +constexpr static const char *const TAG = "display.qspi_amoled"; +static const uint8_t SW_RESET_CMD = 0x01; +static const uint8_t SLEEP_OUT = 0x11; +static const uint8_t INVERT_OFF = 0x20; +static const uint8_t INVERT_ON = 0x21; +static const uint8_t ALL_ON = 0x23; +static const uint8_t WRAM = 0x24; +static const uint8_t MIPI = 0x26; +static const uint8_t DISPLAY_ON = 0x29; +static const uint8_t RASET = 0x2B; +static const uint8_t CASET = 0x2A; +static const uint8_t WDATA = 0x2C; +static const uint8_t TEON = 0x35; +static const uint8_t MADCTL_CMD = 0x36; +static const uint8_t PIXFMT = 0x3A; +static const uint8_t BRIGHTNESS = 0x51; +static const uint8_t SWIRE1 = 0x5A; +static const uint8_t SWIRE2 = 0x5B; +static const uint8_t PAGESEL = 0xFE; + +static const uint8_t MADCTL_MY = 0x80; ///< Bit 7 Bottom to top +static const uint8_t MADCTL_MX = 0x40; ///< Bit 6 Right to left +static const uint8_t MADCTL_MV = 0x20; ///< Bit 5 Reverse Mode +static const uint8_t MADCTL_RGB = 0x00; ///< Bit 3 Red-Green-Blue pixel order +static const uint8_t MADCTL_BGR = 0x08; ///< Bit 3 Blue-Green-Red pixel order + +// store a 16 bit value in a buffer, big endian. +static inline void put16_be(uint8_t *buf, uint16_t value) { + buf[0] = value >> 8; + buf[1] = value; +} + +enum Model { + RM690B0, + RM67162, +}; + +class QspiAmoLed : public display::DisplayBuffer, + public spi::SPIDevice { + public: + void set_model(Model model) { this->model_ = model; } + void update() override; + void setup() override; + display::ColorOrder get_color_mode() { return this->color_mode_; } + void set_color_mode(display::ColorOrder color_mode) { this->color_mode_ = color_mode; } + + void set_reset_pin(GPIOPin *reset_pin) { this->reset_pin_ = reset_pin; } + void set_enable_pin(GPIOPin *enable_pin) { this->enable_pin_ = enable_pin; } + void set_width(uint16_t width) { this->width_ = width; } + void set_dimensions(uint16_t width, uint16_t height) { + this->width_ = width; + this->height_ = height; + } + int get_width() override { return this->width_; } + int get_height() override { return this->height_; } + void set_invert_colors(bool invert_colors) { + this->invert_colors_ = invert_colors; + this->reset_params_(); + } + void set_mirror_x(bool mirror_x) { + this->mirror_x_ = mirror_x; + this->reset_params_(); + } + void set_mirror_y(bool mirror_y) { + this->mirror_y_ = mirror_y; + this->reset_params_(); + } + void set_swap_xy(bool swap_xy) { + this->swap_xy_ = swap_xy; + this->reset_params_(); + } + void set_brightness(uint8_t brightness) { + this->brightness_ = brightness; + this->reset_params_(); + } + void set_offsets(int16_t offset_x, int16_t offset_y) { + this->offset_x_ = offset_x; + this->offset_y_ = offset_y; + } + display::DisplayType get_display_type() override { return display::DisplayType::DISPLAY_TYPE_COLOR; } + void dump_config() override; + + int get_width_internal() override { return this->width_; } + int get_height_internal() override { return this->height_; } + bool can_proceed() override { return this->setup_complete_; } + + protected: + void draw_absolute_pixel_internal(int x, int y, 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; + /** + * the RM67162 in quad SPI mode seems to work like this (not in the datasheet, this is deduced from the + * sample code.) + * + * Immediately after enabling /CS send 4 bytes in single-dataline SPI mode: + * 0: either 0x2 or 0x32. The first indicates that any subsequent data bytes after the initial 4 will be + * sent in 1-dataline SPI. The second indicates quad mode. + * 1: 0x00 + * 2: The command (register address) byte. + * 3: 0x00 + * + * This is followed by zero or more data bytes in either 1-wire or 4-wire mode, depending on the first byte. + * At the conclusion of the write, de-assert /CS. + * + * @param cmd + * @param bytes + * @param len + */ + void write_command_(uint8_t cmd, const uint8_t *bytes, size_t len) { + this->enable(); + this->write_cmd_addr_data(8, 0x02, 24, cmd << 8, bytes, len); + this->disable(); + } + + void write_command_(uint8_t cmd, uint8_t data) { this->write_command_(cmd, &data, 1); } + void write_command_(uint8_t cmd) { this->write_command_(cmd, &cmd, 0); } + void reset_params_(bool ready = false); + void write_init_sequence_(); + void set_addr_window_(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2); + + GPIOPin *reset_pin_{nullptr}; + GPIOPin *enable_pin_{nullptr}; + uint16_t x_low_{0}; + uint16_t y_low_{0}; + uint16_t x_high_{0}; + uint16_t y_high_{0}; + bool setup_complete_{}; + + bool invert_colors_{}; + display::ColorOrder color_mode_{display::COLOR_ORDER_BGR}; + size_t width_{}; + size_t height_{}; + int16_t offset_x_{0}; + int16_t offset_y_{0}; + bool swap_xy_{}; + bool mirror_x_{}; + bool mirror_y_{}; + uint8_t brightness_{0xD0}; + Model model_{RM690B0}; + + esp_lcd_panel_handle_t handle_{}; +}; + +} // namespace qspi_amoled +} // namespace esphome +#endif diff --git a/tests/components/qspi_amoled/test.esp32-s3-idf.yaml b/tests/components/qspi_amoled/test.esp32-s3-idf.yaml new file mode 100644 index 0000000000..01d1a63bcb --- /dev/null +++ b/tests/components/qspi_amoled/test.esp32-s3-idf.yaml @@ -0,0 +1,36 @@ +spi: + id: quad_spi + clk_pin: 15 + type: quad + data_pins: [14, 10, 16, 12] + +display: + - platform: qspi_amoled + model: RM690B0 + data_rate: 80MHz + spi_mode: mode0 + dimensions: + width: 450 + height: 600 + offset_width: 16 + color_order: rgb + invert_colors: false + brightness: 255 + cs_pin: 11 + reset_pin: 13 + enable_pin: 9 + + - platform: qspi_amoled + model: RM67162 + id: main_lcd + dimensions: + height: 240 + width: 536 + transform: + mirror_x: true + swap_xy: true + color_order: rgb + brightness: 255 + cs_pin: 6 + reset_pin: 17 + enable_pin: 38 From 77214a677b85266e319f81f30573bc3546f032d7 Mon Sep 17 00:00:00 2001 From: Sorin Iordachescu Date: Tue, 12 Mar 2024 23:17:06 +0000 Subject: [PATCH 1066/2101] ADE7953: Add the ability to use accumulating energy registers, more precise power reporting (#6311) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/ade7953_base/__init__.py | 5 +++ .../components/ade7953_base/ade7953_base.cpp | 43 +++++++++++++------ .../components/ade7953_base/ade7953_base.h | 4 ++ 3 files changed, 40 insertions(+), 12 deletions(-) diff --git a/esphome/components/ade7953_base/__init__.py b/esphome/components/ade7953_base/__init__.py index d4c18f8ffd..28014ef142 100644 --- a/esphome/components/ade7953_base/__init__.py +++ b/esphome/components/ade7953_base/__init__.py @@ -41,6 +41,7 @@ CONF_CURRENT_GAIN_A = "current_gain_a" CONF_CURRENT_GAIN_B = "current_gain_b" CONF_ACTIVE_POWER_GAIN_A = "active_power_gain_a" CONF_ACTIVE_POWER_GAIN_B = "active_power_gain_b" +CONF_USE_ACCUMULATED_ENERGY_REGISTERS = "use_accumulated_energy_registers" PGA_GAINS = { "1x": 0b000, "2x": 0b001, @@ -155,6 +156,7 @@ ADE7953_CONFIG_SCHEMA = cv.Schema( cv.Optional(CONF_ACTIVE_POWER_GAIN_B, default=0x400000): cv.hex_int_range( min=0x100000, max=0x800000 ), + cv.Optional(CONF_USE_ACCUMULATED_ENERGY_REGISTERS, default=False): cv.boolean, } ).extend(cv.polling_component_schema("60s")) @@ -174,6 +176,9 @@ async def register_ade7953(var, config): cg.add(var.set_bigain(config.get(CONF_CURRENT_GAIN_B))) cg.add(var.set_awgain(config.get(CONF_ACTIVE_POWER_GAIN_A))) cg.add(var.set_bwgain(config.get(CONF_ACTIVE_POWER_GAIN_B))) + cg.add( + var.set_use_acc_energy_regs(config.get(CONF_USE_ACCUMULATED_ENERGY_REGISTERS)) + ) for key in [ CONF_VOLTAGE, diff --git a/esphome/components/ade7953_base/ade7953_base.cpp b/esphome/components/ade7953_base/ade7953_base.cpp index af6fe0a5df..862f5567a8 100644 --- a/esphome/components/ade7953_base/ade7953_base.cpp +++ b/esphome/components/ade7953_base/ade7953_base.cpp @@ -6,6 +6,9 @@ namespace ade7953_base { static const char *const TAG = "ade7953"; +static const float ADE_POWER_FACTOR = 154.0f; +static const float ADE_WATTSEC_POWER_FACTOR = ADE_POWER_FACTOR * ADE_POWER_FACTOR / 3600; + void ADE7953::setup() { if (this->irq_pin_ != nullptr) { this->irq_pin_->setup(); @@ -34,6 +37,7 @@ void ADE7953::setup() { this->ade_read_32(BIGAIN_32, &bigain_); this->ade_read_32(AWGAIN_32, &awgain_); this->ade_read_32(BWGAIN_32, &bwgain_); + this->last_update_ = millis(); this->is_setup_ = true; }); } @@ -52,6 +56,7 @@ void ADE7953::dump_config() { LOG_SENSOR(" ", "Active Power B Sensor", this->active_power_b_sensor_); LOG_SENSOR(" ", "Rective Power A Sensor", this->reactive_power_a_sensor_); LOG_SENSOR(" ", "Reactive Power B Sensor", this->reactive_power_b_sensor_); + ESP_LOGCONFIG(TAG, " USE_ACC_ENERGY_REGS: %d", this->use_acc_energy_regs_); ESP_LOGCONFIG(TAG, " PGA_V_8: 0x%X", pga_v_); ESP_LOGCONFIG(TAG, " PGA_IA_8: 0x%X", pga_ia_); ESP_LOGCONFIG(TAG, " PGA_IB_8: 0x%X", pga_ib_); @@ -85,6 +90,7 @@ void ADE7953::update() { uint32_t val; uint16_t val_16; + uint16_t reg; // Power factor err = this->ade_read_16(0x010A, &val_16); @@ -92,23 +98,36 @@ void ADE7953::update() { err = this->ade_read_16(0x010B, &val_16); ADE_PUBLISH(power_factor_b, (int16_t) val_16, (0x7FFF / 100.0f)); + float pf = ADE_POWER_FACTOR; + if (this->use_acc_energy_regs_) { + const uint32_t now = millis(); + const auto diff = now - this->last_update_; + this->last_update_ = now; + // prevent DIV/0 + pf = ADE_WATTSEC_POWER_FACTOR * (diff < 10 ? 10 : diff) / 1000; + ESP_LOGVV(TAG, "ADE7953::update() diff=%d pf=%f", diff, pf); + } + // Apparent power - err = this->ade_read_32(0x0310, &val); - ADE_PUBLISH(apparent_power_a, (int32_t) val, 154.0f); - err = this->ade_read_32(0x0311, &val); - ADE_PUBLISH(apparent_power_b, (int32_t) val, 154.0f); + reg = this->use_acc_energy_regs_ ? 0x0322 : 0x0310; + err = this->ade_read_32(reg, &val); + ADE_PUBLISH(apparent_power_a, (int32_t) val, pf); + err = this->ade_read_32(reg + 1, &val); + ADE_PUBLISH(apparent_power_b, (int32_t) val, pf); // Active power - err = this->ade_read_32(0x0312, &val); - ADE_PUBLISH(active_power_a, (int32_t) val, 154.0f); - err = this->ade_read_32(0x0313, &val); - ADE_PUBLISH(active_power_b, (int32_t) val, 154.0f); + reg = this->use_acc_energy_regs_ ? 0x031E : 0x0312; + err = this->ade_read_32(reg, &val); + ADE_PUBLISH(active_power_a, (int32_t) val, pf); + err = this->ade_read_32(reg + 1, &val); + ADE_PUBLISH(active_power_b, (int32_t) val, pf); // Reactive power - err = this->ade_read_32(0x0314, &val); - ADE_PUBLISH(reactive_power_a, (int32_t) val, 154.0f); - err = this->ade_read_32(0x0315, &val); - ADE_PUBLISH(reactive_power_b, (int32_t) val, 154.0f); + reg = this->use_acc_energy_regs_ ? 0x0320 : 0x0314; + err = this->ade_read_32(reg, &val); + ADE_PUBLISH(reactive_power_a, (int32_t) val, pf); + err = this->ade_read_32(reg + 1, &val); + ADE_PUBLISH(reactive_power_b, (int32_t) val, pf); // Current err = this->ade_read_32(0x031A, &val); diff --git a/esphome/components/ade7953_base/ade7953_base.h b/esphome/components/ade7953_base/ade7953_base.h index f57a8aa1df..d711a5c6be 100644 --- a/esphome/components/ade7953_base/ade7953_base.h +++ b/esphome/components/ade7953_base/ade7953_base.h @@ -52,6 +52,8 @@ class ADE7953 : public PollingComponent, public sensor::Sensor { void set_awgain(uint32_t awgain) { awgain_ = awgain; } void set_bwgain(uint32_t bwgain) { bwgain_ = bwgain; } + void set_use_acc_energy_regs(bool use_acc_energy_regs) { use_acc_energy_regs_ = use_acc_energy_regs; } + void set_voltage_sensor(sensor::Sensor *voltage_sensor) { voltage_sensor_ = voltage_sensor; } void set_frequency_sensor(sensor::Sensor *frequency_sensor) { frequency_sensor_ = frequency_sensor; } @@ -103,6 +105,8 @@ class ADE7953 : public PollingComponent, public sensor::Sensor { uint32_t bigain_; uint32_t awgain_; uint32_t bwgain_; + bool use_acc_energy_regs_{false}; + uint32_t last_update_; virtual bool ade_write_8(uint16_t reg, uint8_t value) = 0; From 3abf2f1d1489608f9304ea7ccbd49f28fa8e208d Mon Sep 17 00:00:00 2001 From: Mark Spicer Date: Tue, 12 Mar 2024 21:04:59 -0400 Subject: [PATCH 1067/2101] feat: Add HTU31D Support (#5805) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- CODEOWNERS | 1 + esphome/components/htu31d/__init__.py | 1 + esphome/components/htu31d/htu31d.cpp | 269 ++++++++++++++++++++ esphome/components/htu31d/htu31d.h | 33 +++ esphome/components/htu31d/sensor.py | 56 ++++ tests/components/htu31d/common.yaml | 9 + tests/components/htu31d/test.esp32-idf.yaml | 1 + tests/components/htu31d/test.esp32.yaml | 1 + tests/components/htu31d/test.esp8266.yaml | 1 + 9 files changed, 372 insertions(+) create mode 100644 esphome/components/htu31d/__init__.py create mode 100644 esphome/components/htu31d/htu31d.cpp create mode 100644 esphome/components/htu31d/htu31d.h create mode 100644 esphome/components/htu31d/sensor.py create mode 100644 tests/components/htu31d/common.yaml create mode 100644 tests/components/htu31d/test.esp32-idf.yaml create mode 100644 tests/components/htu31d/test.esp32.yaml create mode 100644 tests/components/htu31d/test.esp8266.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 483672bf54..c8d2a579d1 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -152,6 +152,7 @@ esphome/components/honeywellabp2_i2c/* @jpfaff esphome/components/host/* @esphome/core esphome/components/hrxl_maxsonar_wr/* @netmikey esphome/components/hte501/* @Stock-M +esphome/components/htu31d/* @betterengineering esphome/components/hydreon_rgxx/* @functionpointer esphome/components/hyt271/* @Philippe12 esphome/components/i2c/* @esphome/core diff --git a/esphome/components/htu31d/__init__.py b/esphome/components/htu31d/__init__.py new file mode 100644 index 0000000000..039693cb30 --- /dev/null +++ b/esphome/components/htu31d/__init__.py @@ -0,0 +1 @@ +CODEOWNERS = ["@betterengineering"] diff --git a/esphome/components/htu31d/htu31d.cpp b/esphome/components/htu31d/htu31d.cpp new file mode 100644 index 0000000000..928250a5b2 --- /dev/null +++ b/esphome/components/htu31d/htu31d.cpp @@ -0,0 +1,269 @@ +/* + * This file contains source code derived from Adafruit_HTU31D which is under + * the BSD license: + * Written by Limor Fried/Ladyada for Adafruit Industries. + * BSD license, all text above must be included in any redistribution. + * + * Modifications made by Mark Spicer. + */ + +#include "htu31d.h" +#include "esphome/core/hal.h" +#include "esphome/core/helpers.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace htu31d { + +/** Logging prefix */ +static const char *const TAG = "htu31d"; + +/** Default I2C address for the HTU31D. */ +static const uint8_t HTU31D_DEFAULT_I2CADDR = 0x40; + +/** Read temperature and humidity. */ +static const uint8_t HTU31D_READTEMPHUM = 0x00; + +/** Start a conversion! */ +static const uint8_t HTU31D_CONVERSION = 0x40; + +/** Read serial number command. */ +static const uint8_t HTU31D_READSERIAL = 0x0A; + +/** Enable heater */ +static const uint8_t HTU31D_HEATERON = 0x04; + +/** Disable heater */ +static const uint8_t HTU31D_HEATEROFF = 0x02; + +/** Reset command. */ +static const uint8_t HTU31D_RESET = 0x1E; + +/** Diagnostics command. */ +static const uint8_t HTU31D_DIAGNOSTICS = 0x08; + +/** + * Computes a CRC result for the provided input. + * + * @returns the computed CRC result for the provided input + */ +uint8_t compute_crc(uint32_t value) { + uint32_t polynom = 0x98800000; // x^8 + x^5 + x^4 + 1 + uint32_t msb = 0x80000000; + uint32_t mask = 0xFF800000; + uint32_t threshold = 0x00000080; + uint32_t result = value; + + while (msb != threshold) { + // Check if msb of current value is 1 and apply XOR mask + if (result & msb) + result = ((result ^ polynom) & mask) | (result & ~mask); + + // Shift by one + msb >>= 1; + mask >>= 1; + polynom >>= 1; + } + + return result; +} + +/** + * Resets the sensor and ensures that the devices serial number can be read over + * I2C. + */ +void HTU31DComponent::setup() { + ESP_LOGCONFIG(TAG, "Setting up esphome/components/htu31d HTU31D..."); + + if (!this->reset_()) { + this->mark_failed(); + return; + } + + if (this->read_serial_num_() == 0) { + this->mark_failed(); + return; + } +} + +/** + * Called once every update interval (user configured, defaults to 60s) and sets + * the current temperature and humidity. + */ +void HTU31DComponent::update() { + ESP_LOGD(TAG, "Checking temperature and humidty values"); + + // Trigger a conversion. From the spec sheet: The conversion command triggers + // a single temperature and humidity conversion. + if (this->write_register(HTU31D_CONVERSION, nullptr, 0) != i2c::ERROR_OK) { + this->status_set_warning(); + ESP_LOGE(TAG, "Received errror writing conversion register"); + return; + } + + // Wait conversion time. + this->set_timeout(20, [this]() { + uint8_t thdata[6]; + if (this->read_register(HTU31D_READTEMPHUM, thdata, 6) != i2c::ERROR_OK) { + this->status_set_warning(); + ESP_LOGE(TAG, "Error reading temperature/humidty register"); + return; + } + + // Calculate temperature value. + uint16_t raw_temp = encode_uint16(thdata[0], thdata[1]); + + uint8_t crc = compute_crc((uint32_t) raw_temp << 8); + if (crc != thdata[2]) { + this->status_set_warning(); + ESP_LOGE(TAG, "Error validating temperature CRC"); + return; + } + + float temperature = raw_temp; + temperature /= 65535.0f; + temperature *= 165; + temperature -= 40; + + if (this->temperature_ != nullptr) { + this->temperature_->publish_state(temperature); + } + + // Calculate humidty value. + uint16_t raw_hum = encode_uint16(thdata[3], thdata[4]); + + crc = compute_crc((uint32_t) raw_hum << 8); + if (crc != thdata[5]) { + this->status_set_warning(); + ESP_LOGE(TAG, "Error validating humidty CRC"); + return; + } + + float humidity = raw_hum; + humidity /= 65535.0f; + humidity *= 100; + + if (this->humidity_ != nullptr) { + this->humidity_->publish_state(humidity); + } + + ESP_LOGD(TAG, "Got Temperature=%.1f°C Humidity=%.1f%%", temperature, humidity); + this->status_clear_warning(); + }); +} + +/** + * Logs the current compoenent config. + */ +void HTU31DComponent::dump_config() { + ESP_LOGCONFIG(TAG, "HTU31D:"); + LOG_I2C_DEVICE(this); + if (this->is_failed()) { + ESP_LOGE(TAG, "Communication with HTU31D failed!"); + } + LOG_UPDATE_INTERVAL(this); + LOG_SENSOR(" ", "Temperature", this->temperature_); + LOG_SENSOR(" ", "Humidity", this->humidity_); +} + +/** + * Sends a 'reset' request to the HTU31D, followed by a 15ms delay. + * + * @returns True if was able to write the command successfully + */ +bool HTU31DComponent::reset_() { + if (this->write_register(HTU31D_RESET, nullptr, 0) != i2c::ERROR_OK) { + return false; + } + + delay(15); + return true; +} + +/** + * Reads the serial number from the device and checks the CRC. + * + * @returns the 24bit serial number from the device + */ +uint32_t HTU31DComponent::read_serial_num_() { + uint8_t reply[4]; + uint32_t serial = 0; + uint8_t padding = 0; + + // Verify we can read the device serial. + if (this->read_register(HTU31D_READSERIAL, reply, 4) != i2c::ERROR_OK) { + ESP_LOGE(TAG, "Error reading device serial"); + return 0; + } + + serial = encode_uint32(reply[0], reply[1], reply[2], padding); + + uint8_t crc = compute_crc(serial); + if (crc != reply[3]) { + ESP_LOGE(TAG, "Error validating serial CRC"); + return 0; + } + + ESP_LOGD(TAG, "Found serial: 0x%X", serial); + + return serial; +} + +/** + * Checks the diagnostics register to determine if the heater is currently + * enabled. + * + * @returns True if the heater is currently enabled, False otherwise + */ +bool HTU31DComponent::is_heater_enabled() { + uint8_t reply[1]; + uint8_t heater_enabled_position = 0; + uint8_t mask = 1 << heater_enabled_position; + uint8_t diagnostics = 0; + + if (this->read_register(HTU31D_DIAGNOSTICS, reply, 1) != i2c::ERROR_OK) { + ESP_LOGE(TAG, "Error reading device serial"); + return false; + } + + diagnostics = reply[0]; + return (diagnostics & mask) != 0; +} + +/** + * Sets the heater state on or off. + * + * @param desired True for on, and False for off. + */ +void HTU31DComponent::set_heater_state(bool desired) { + bool current = this->is_heater_enabled(); + + // If the current state matches the desired state, there is nothing to do. + if (current == desired) { + return; + } + + // Update heater state. + esphome::i2c::ErrorCode err; + if (desired) { + err = this->write_register(HTU31D_HEATERON, nullptr, 0); + } else { + err = this->write_register(HTU31D_HEATEROFF, nullptr, 0); + } + + // Record any error. + if (err != i2c::ERROR_OK) { + this->status_set_warning(); + ESP_LOGE(TAG, "Received error updating heater state"); + return; + } +} + +/** + * 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 new file mode 100644 index 0000000000..9462133ced --- /dev/null +++ b/esphome/components/htu31d/htu31d.h @@ -0,0 +1,33 @@ +#pragma once + +#include "esphome/components/i2c/i2c.h" +#include "esphome/components/sensor/sensor.h" +#include "esphome/core/automation.h" +#include "esphome/core/component.h" + +namespace esphome { +namespace htu31d { + +class HTU31DComponent : public PollingComponent, public i2c::I2CDevice { + public: + void setup() override; /// Setup (reset) the sensor and check connection. + void update() override; /// Update the sensor values (temperature+humidity). + void dump_config() override; /// Dumps the configuration values. + + void set_temperature(sensor::Sensor *temperature) { this->temperature_ = temperature; } + void set_humidity(sensor::Sensor *humidity) { this->humidity_ = humidity; } + + void set_heater_state(bool desired); + bool is_heater_enabled(); + + float get_setup_priority() const override; + + protected: + bool reset_(); + uint32_t read_serial_num_(); + + sensor::Sensor *temperature_{nullptr}; + sensor::Sensor *humidity_{nullptr}; +}; +} // namespace htu31d +} // namespace esphome diff --git a/esphome/components/htu31d/sensor.py b/esphome/components/htu31d/sensor.py new file mode 100644 index 0000000000..fe53aa376e --- /dev/null +++ b/esphome/components/htu31d/sensor.py @@ -0,0 +1,56 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import i2c, sensor +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"] + +htu31d_ns = cg.esphome_ns.namespace("htu31d") +HTU31DComponent = htu31d_ns.class_( + "HTU31DComponent", cg.PollingComponent, i2c.I2CDevice +) + +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(HTU31DComponent), + 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=1, + device_class=DEVICE_CLASS_HUMIDITY, + state_class=STATE_CLASS_MEASUREMENT, + ), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x40)) +) + + +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/htu31d/common.yaml b/tests/components/htu31d/common.yaml new file mode 100644 index 0000000000..c8ef2fede9 --- /dev/null +++ b/tests/components/htu31d/common.yaml @@ -0,0 +1,9 @@ +i2c: + +sensor: + - platform: htu31d + temperature: + name: Living Room Temperature 7 + humidity: + name: Living Room Humidity 7 + update_interval: 15s diff --git a/tests/components/htu31d/test.esp32-idf.yaml b/tests/components/htu31d/test.esp32-idf.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/htu31d/test.esp32-idf.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/htu31d/test.esp32.yaml b/tests/components/htu31d/test.esp32.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/htu31d/test.esp32.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/htu31d/test.esp8266.yaml b/tests/components/htu31d/test.esp8266.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/htu31d/test.esp8266.yaml @@ -0,0 +1 @@ +<<: !include common.yaml From b34b10888bf89777dbc887e6b17601737ab35859 Mon Sep 17 00:00:00 2001 From: Ettore Beltrame <42470585+E440QF@users.noreply.github.com> Date: Wed, 13 Mar 2024 02:16:02 +0100 Subject: [PATCH 1068/2101] Emmeti infrared climate support (#5197) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- CODEOWNERS | 1 + esphome/components/emmeti/__init__.py | 0 esphome/components/emmeti/climate.py | 21 ++ esphome/components/emmeti/emmeti.cpp | 316 ++++++++++++++++++++ esphome/components/emmeti/emmeti.h | 109 +++++++ tests/components/emmeti/common.yaml | 14 + tests/components/emmeti/test.esp32-idf.yaml | 5 + tests/components/emmeti/test.esp32.yaml | 5 + tests/components/emmeti/test.esp8266.yaml | 5 + 9 files changed, 476 insertions(+) create mode 100644 esphome/components/emmeti/__init__.py create mode 100644 esphome/components/emmeti/climate.py create mode 100644 esphome/components/emmeti/emmeti.cpp create mode 100644 esphome/components/emmeti/emmeti.h create mode 100644 tests/components/emmeti/common.yaml create mode 100644 tests/components/emmeti/test.esp32-idf.yaml create mode 100644 tests/components/emmeti/test.esp32.yaml create mode 100644 tests/components/emmeti/test.esp8266.yaml diff --git a/CODEOWNERS b/CODEOWNERS index c8d2a579d1..0a94c254d2 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -103,6 +103,7 @@ esphome/components/duty_time/* @dudanov esphome/components/ee895/* @Stock-M esphome/components/ektf2232/touchscreen/* @jesserockz esphome/components/emc2101/* @ellull +esphome/components/emmeti/* @E440QF esphome/components/ens160/* @vincentscode esphome/components/ens210/* @itn3rd77 esphome/components/esp32/* @esphome/core diff --git a/esphome/components/emmeti/__init__.py b/esphome/components/emmeti/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/emmeti/climate.py b/esphome/components/emmeti/climate.py new file mode 100644 index 0000000000..36585061e6 --- /dev/null +++ b/esphome/components/emmeti/climate.py @@ -0,0 +1,21 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import climate_ir +from esphome.const import CONF_ID + +CODEOWNERS = ["@E440QF"] +AUTO_LOAD = ["climate_ir"] + +emmeti_ns = cg.esphome_ns.namespace("emmeti") +EmmetiClimate = emmeti_ns.class_("EmmetiClimate", climate_ir.ClimateIR) + +CONFIG_SCHEMA = climate_ir.CLIMATE_IR_WITH_RECEIVER_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(EmmetiClimate), + } +) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + await climate_ir.register_climate_ir(var, config) diff --git a/esphome/components/emmeti/emmeti.cpp b/esphome/components/emmeti/emmeti.cpp new file mode 100644 index 0000000000..3cb184f868 --- /dev/null +++ b/esphome/components/emmeti/emmeti.cpp @@ -0,0 +1,316 @@ +#include "emmeti.h" +#include "esphome/components/remote_base/remote_base.h" + +namespace esphome { +namespace emmeti { + +static const char *const TAG = "emmeti.climate"; + +// setters +uint8_t EmmetiClimate::set_temp_() { + return (uint8_t) roundf(clamp(this->target_temperature, EMMETI_TEMP_MIN, EMMETI_TEMP_MAX) - EMMETI_TEMP_MIN); +} + +uint8_t EmmetiClimate::set_mode_() { + switch (this->mode) { + case climate::CLIMATE_MODE_COOL: + return EMMETI_MODE_COOL; + case climate::CLIMATE_MODE_DRY: + return EMMETI_MODE_DRY; + case climate::CLIMATE_MODE_HEAT: + return EMMETI_MODE_HEAT; + case climate::CLIMATE_MODE_FAN_ONLY: + return EMMETI_MODE_FAN; + case climate::CLIMATE_MODE_HEAT_COOL: + default: + return EMMETI_MODE_HEAT_COOL; + } +} + +uint8_t EmmetiClimate::set_fan_speed_() { + switch (this->fan_mode.value()) { + case climate::CLIMATE_FAN_LOW: + return EMMETI_FAN_1; + case climate::CLIMATE_FAN_MEDIUM: + return EMMETI_FAN_2; + case climate::CLIMATE_FAN_HIGH: + return EMMETI_FAN_3; + case climate::CLIMATE_FAN_AUTO: + default: + return EMMETI_FAN_AUTO; + } +} + +uint8_t EmmetiClimate::set_blades_() { + if (this->swing_mode == climate::CLIMATE_SWING_VERTICAL) { + switch (this->blades_) { + case EMMETI_BLADES_1: + case EMMETI_BLADES_2: + case EMMETI_BLADES_HIGH: + this->blades_ = EMMETI_BLADES_HIGH; + break; + case EMMETI_BLADES_3: + case EMMETI_BLADES_MID: + this->blades_ = EMMETI_BLADES_MID; + break; + case EMMETI_BLADES_4: + case EMMETI_BLADES_5: + case EMMETI_BLADES_LOW: + this->blades_ = EMMETI_BLADES_LOW; + break; + default: + this->blades_ = EMMETI_BLADES_FULL; + break; + } + } else { + switch (this->blades_) { + case EMMETI_BLADES_1: + case EMMETI_BLADES_2: + case EMMETI_BLADES_HIGH: + this->blades_ = EMMETI_BLADES_1; + break; + case EMMETI_BLADES_3: + case EMMETI_BLADES_MID: + this->blades_ = EMMETI_BLADES_3; + break; + case EMMETI_BLADES_4: + case EMMETI_BLADES_5: + case EMMETI_BLADES_LOW: + this->blades_ = EMMETI_BLADES_5; + break; + default: + this->blades_ = EMMETI_BLADES_STOP; + break; + } + } + return this->blades_; +} + +uint8_t EmmetiClimate::gen_checksum_() { return (this->set_temp_() + this->set_mode_() + 2) % 16; } + +// getters +float EmmetiClimate::get_temp_(uint8_t temp) { return (float) (temp + EMMETI_TEMP_MIN); } + +climate::ClimateMode EmmetiClimate::get_mode_(uint8_t mode) { + switch (mode) { + case EMMETI_MODE_COOL: + return climate::CLIMATE_MODE_COOL; + case EMMETI_MODE_DRY: + return climate::CLIMATE_MODE_DRY; + case EMMETI_MODE_HEAT: + return climate::CLIMATE_MODE_HEAT; + case EMMETI_MODE_HEAT_COOL: + return climate::CLIMATE_MODE_HEAT_COOL; + case EMMETI_MODE_FAN: + return climate::CLIMATE_MODE_FAN_ONLY; + default: + return climate::CLIMATE_MODE_HEAT_COOL; + } +} + +climate::ClimateFanMode EmmetiClimate::get_fan_speed_(uint8_t fan_speed) { + switch (fan_speed) { + case EMMETI_FAN_1: + return climate::CLIMATE_FAN_LOW; + case EMMETI_FAN_2: + return climate::CLIMATE_FAN_MEDIUM; + case EMMETI_FAN_3: + return climate::CLIMATE_FAN_HIGH; + case EMMETI_FAN_AUTO: + default: + return climate::CLIMATE_FAN_AUTO; + } +} + +climate::ClimateSwingMode EmmetiClimate::get_swing_(uint8_t bitmap) { + return (bitmap >> 1) & 0x01 ? climate::CLIMATE_SWING_VERTICAL : climate::CLIMATE_SWING_OFF; +} + +template T EmmetiClimate::reverse_(T val, size_t len) { + T result = 0; + for (size_t i = 0; i < len; i++) { + result |= ((val & 1 << i) != 0) << (len - 1 - i); + } + return result; +} + +template void EmmetiClimate::add_(T val, size_t len, esphome::remote_base::RemoteTransmitData *data) { + for (size_t i = len; i > 0; i--) { + data->mark(EMMETI_BIT_MARK); + data->space((val & (1 << (i - 1))) ? EMMETI_ONE_SPACE : EMMETI_ZERO_SPACE); + } +} + +template void EmmetiClimate::add_(T val, esphome::remote_base::RemoteTransmitData *data) { + data->mark(EMMETI_BIT_MARK); + data->space((val & 1) ? EMMETI_ONE_SPACE : EMMETI_ZERO_SPACE); +} + +template +void EmmetiClimate::reverse_add_(T val, size_t len, esphome::remote_base::RemoteTransmitData *data) { + this->add_(this->reverse_(val, len), len, data); +} + +bool EmmetiClimate::check_checksum_(uint8_t checksum) { + uint8_t expected = this->gen_checksum_(); + ESP_LOGV(TAG, "Expected checksum: %X", expected); + ESP_LOGV(TAG, "Checksum received: %X", checksum); + + return checksum == expected; +} + +void EmmetiClimate::transmit_state() { + auto transmit = this->transmitter_->transmit(); + auto *data = transmit.get_data(); + data->set_carrier_frequency(EMMETI_IR_FREQUENCY); + + data->mark(EMMETI_HEADER_MARK); + data->space(EMMETI_HEADER_SPACE); + + if (this->mode != climate::CLIMATE_MODE_OFF) { + this->reverse_add_(this->set_mode_(), 3, data); + this->add_(1, data); + this->reverse_add_(this->set_fan_speed_(), 2, data); + this->add_(this->swing_mode != climate::CLIMATE_SWING_OFF, data); + this->add_(0, data); // sleep mode + this->reverse_add_(this->set_temp_(), 4, data); + this->add_(0, 8, data); // zeros + this->add_(0, data); // turbo mode + this->add_(1, data); // light + this->add_(1, data); // tree icon thingy + this->add_(0, data); // blow mode + this->add_(0x52, 11, data); // idk + + data->mark(EMMETI_BIT_MARK); + data->space(EMMETI_MESSAGE_SPACE); + + this->reverse_add_(this->set_blades_(), 4, data); + this->add_(0, 4, data); // zeros + this->reverse_add_(2, 2, data); // thermometer + this->add_(0, 18, data); // zeros + this->reverse_add_(this->gen_checksum_(), 4, data); + } else { + this->add_(9, 12, data); + this->add_(0, 8, data); + this->add_(0x2052, 15, data); + data->mark(EMMETI_BIT_MARK); + data->space(EMMETI_MESSAGE_SPACE); + this->add_(0, 8, data); + this->add_(1, 2, data); + this->add_(0, 18, data); + this->add_(0x0C, 4, data); + } + data->mark(EMMETI_BIT_MARK); + data->space(0); + + transmit.perform(); +} + +bool EmmetiClimate::parse_state_frame_(EmmetiState curr_state) { + this->mode = this->get_mode_(curr_state.mode); + this->fan_mode = this->get_fan_speed_(curr_state.fan_speed); + this->target_temperature = this->get_temp_(curr_state.temp); + this->swing_mode = this->get_swing_(curr_state.bitmap); + // this->blades_ = curr_state.fan_pos; + if (!(curr_state.bitmap & 0x01)) { + this->mode = climate::CLIMATE_MODE_OFF; + } + + this->publish_state(); + return true; +} + +bool EmmetiClimate::on_receive(remote_base::RemoteReceiveData data) { + if (!data.expect_item(EMMETI_HEADER_MARK, EMMETI_HEADER_SPACE)) { + return false; + } + ESP_LOGD(TAG, "Received emmeti frame"); + + EmmetiState curr_state; + + for (size_t pos = 0; pos < 3; pos++) { + if (data.expect_item(EMMETI_BIT_MARK, EMMETI_ONE_SPACE)) { + curr_state.mode |= 1 << pos; + } else if (!data.expect_item(EMMETI_BIT_MARK, EMMETI_ZERO_SPACE)) { + return false; + } + } + + ESP_LOGD(TAG, "Mode: %d", curr_state.mode); + + if (data.expect_item(EMMETI_BIT_MARK, EMMETI_ONE_SPACE)) { + curr_state.bitmap |= 1 << 0; + } else if (!data.expect_item(EMMETI_BIT_MARK, EMMETI_ZERO_SPACE)) { + return false; + } + + ESP_LOGD(TAG, "On: %d", curr_state.bitmap & 0x01); + + for (size_t pos = 0; pos < 2; pos++) { + if (data.expect_item(EMMETI_BIT_MARK, EMMETI_ONE_SPACE)) { + curr_state.fan_speed |= 1 << pos; + } else if (!data.expect_item(EMMETI_BIT_MARK, EMMETI_ZERO_SPACE)) { + return false; + } + } + + ESP_LOGD(TAG, "Fan speed: %d", curr_state.fan_speed); + + for (size_t pos = 0; pos < 2; pos++) { + if (data.expect_item(EMMETI_BIT_MARK, EMMETI_ONE_SPACE)) { + curr_state.bitmap |= 1 << (pos + 1); + } else if (!data.expect_item(EMMETI_BIT_MARK, EMMETI_ZERO_SPACE)) { + return false; + } + } + + ESP_LOGD(TAG, "Swing: %d", (curr_state.bitmap >> 1) & 0x01); + ESP_LOGD(TAG, "Sleep: %d", (curr_state.bitmap >> 2) & 0x01); + + for (size_t pos = 0; pos < 4; pos++) { + if (data.expect_item(EMMETI_BIT_MARK, EMMETI_ONE_SPACE)) { + curr_state.temp |= 1 << pos; + } else if (!data.expect_item(EMMETI_BIT_MARK, EMMETI_ZERO_SPACE)) { + return false; + } + } + + ESP_LOGD(TAG, "Temp: %d", curr_state.temp); + + for (size_t pos = 0; pos < 8; pos++) { + if (!data.expect_item(EMMETI_BIT_MARK, EMMETI_ZERO_SPACE)) { + return false; + } + } + + for (size_t pos = 0; pos < 4; pos++) { + if (data.expect_item(EMMETI_BIT_MARK, EMMETI_ONE_SPACE)) { + curr_state.bitmap |= 1 << (pos + 3); + } else if (!data.expect_item(EMMETI_BIT_MARK, EMMETI_ZERO_SPACE)) { + return false; + } + } + + ESP_LOGD(TAG, "Turbo: %d", (curr_state.bitmap >> 3) & 0x01); + ESP_LOGD(TAG, "Light: %d", (curr_state.bitmap >> 4) & 0x01); + ESP_LOGD(TAG, "Tree: %d", (curr_state.bitmap >> 5) & 0x01); + ESP_LOGD(TAG, "Blow: %d", (curr_state.bitmap >> 6) & 0x01); + + uint16_t control_data = 0; + for (size_t pos = 0; pos < 11; pos++) { + if (data.expect_item(EMMETI_BIT_MARK, EMMETI_ONE_SPACE)) { + control_data |= 1 << pos; + } else if (!data.expect_item(EMMETI_BIT_MARK, EMMETI_ZERO_SPACE)) { + return false; + } + } + + if (control_data != 0x250) { + return false; + } + + return this->parse_state_frame_(curr_state); +} + +} // namespace emmeti +} // namespace esphome diff --git a/esphome/components/emmeti/emmeti.h b/esphome/components/emmeti/emmeti.h new file mode 100644 index 0000000000..9bfb7a7a98 --- /dev/null +++ b/esphome/components/emmeti/emmeti.h @@ -0,0 +1,109 @@ +#pragma once + +#include "esphome/components/climate_ir/climate_ir.h" + +namespace esphome { +namespace emmeti { + +const uint8_t EMMETI_TEMP_MIN = 16; // Celsius +const uint8_t EMMETI_TEMP_MAX = 30; // Celsius + +// Modes + +enum EmmetiMode : uint8_t { + EMMETI_MODE_HEAT_COOL = 0x00, + EMMETI_MODE_COOL = 0x01, + EMMETI_MODE_DRY = 0x02, + EMMETI_MODE_FAN = 0x03, + EMMETI_MODE_HEAT = 0x04, +}; + +// Fan Speed + +enum EmmetiFanMode : uint8_t { + EMMETI_FAN_AUTO = 0x00, + EMMETI_FAN_1 = 0x01, + EMMETI_FAN_2 = 0x02, + EMMETI_FAN_3 = 0x03, +}; + +// Fan Position + +enum EmmetiBlades : uint8_t { + EMMETI_BLADES_STOP = 0x00, + EMMETI_BLADES_FULL = 0x01, + EMMETI_BLADES_1 = 0x02, + EMMETI_BLADES_2 = 0x03, + EMMETI_BLADES_3 = 0x04, + EMMETI_BLADES_4 = 0x05, + EMMETI_BLADES_5 = 0x06, + EMMETI_BLADES_LOW = 0x07, + EMMETI_BLADES_MID = 0x09, + EMMETI_BLADES_HIGH = 0x11, +}; + +// IR Transmission +const uint32_t EMMETI_IR_FREQUENCY = 38000; +const uint32_t EMMETI_HEADER_MARK = 9076; +const uint32_t EMMETI_HEADER_SPACE = 4408; +const uint32_t EMMETI_BIT_MARK = 660; +const uint32_t EMMETI_ONE_SPACE = 1630; +const uint32_t EMMETI_ZERO_SPACE = 530; +const uint32_t EMMETI_MESSAGE_SPACE = 20000; + +struct EmmetiState { + uint8_t mode = 0; + uint8_t bitmap = 0; + uint8_t fan_speed = 0; + uint8_t temp = 0; + uint8_t fan_pos = 0; + uint8_t th = 0; + uint8_t checksum = 0; +}; + +class EmmetiClimate : public climate_ir::ClimateIR { + public: + EmmetiClimate() + : climate_ir::ClimateIR(EMMETI_TEMP_MIN, EMMETI_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}) {} + + protected: + // Transmit via IR the state of this climate controller + void transmit_state() override; + // Handle received IR Buffer + bool on_receive(remote_base::RemoteReceiveData data) override; + bool parse_state_frame_(EmmetiState curr_state); + + // setters + uint8_t set_mode_(); + uint8_t set_temp_(); + uint8_t set_fan_speed_(); + uint8_t gen_checksum_(); + uint8_t set_blades_(); + + // getters + climate::ClimateMode get_mode_(uint8_t mode); + climate::ClimateFanMode get_fan_speed_(uint8_t fan); + void get_blades_(uint8_t fanpos); + // get swing + climate::ClimateSwingMode get_swing_(uint8_t bitmap); + float get_temp_(uint8_t temp); + + // check if the received frame is valid + bool check_checksum_(uint8_t checksum); + + template T reverse_(T val, size_t len); + + template void add_(T val, size_t len, esphome::remote_base::RemoteTransmitData *ata); + + template void add_(T val, esphome::remote_base::RemoteTransmitData *data); + + template void reverse_add_(T val, size_t len, esphome::remote_base::RemoteTransmitData *data); + + uint8_t blades_ = EMMETI_BLADES_STOP; +}; + +} // namespace emmeti +} // namespace esphome diff --git a/tests/components/emmeti/common.yaml b/tests/components/emmeti/common.yaml new file mode 100644 index 0000000000..ac4201e19b --- /dev/null +++ b/tests/components/emmeti/common.yaml @@ -0,0 +1,14 @@ +remote_transmitter: + id: tx + pin: ${remote_transmitter_pin} + carrier_duty_percent: 100% + +remote_receiver: + id: rcvr + pin: ${remote_receiver_pin} + +climate: + - platform: emmeti + name: Emmeti + receiver_id: rcvr + transmitter_id: tx diff --git a/tests/components/emmeti/test.esp32-idf.yaml b/tests/components/emmeti/test.esp32-idf.yaml new file mode 100644 index 0000000000..2689ff279e --- /dev/null +++ b/tests/components/emmeti/test.esp32-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + remote_transmitter_pin: GPIO33 + remote_receiver_pin: GPIO32 + +<<: !include common.yaml diff --git a/tests/components/emmeti/test.esp32.yaml b/tests/components/emmeti/test.esp32.yaml new file mode 100644 index 0000000000..2689ff279e --- /dev/null +++ b/tests/components/emmeti/test.esp32.yaml @@ -0,0 +1,5 @@ +substitutions: + remote_transmitter_pin: GPIO33 + remote_receiver_pin: GPIO32 + +<<: !include common.yaml diff --git a/tests/components/emmeti/test.esp8266.yaml b/tests/components/emmeti/test.esp8266.yaml new file mode 100644 index 0000000000..2fb00aea61 --- /dev/null +++ b/tests/components/emmeti/test.esp8266.yaml @@ -0,0 +1,5 @@ +substitutions: + remote_transmitter_pin: GPIO4 + remote_receiver_pin: GPIO5 + +<<: !include common.yaml From 64a47f840eecc10e463ac678e51788ecba827546 Mon Sep 17 00:00:00 2001 From: Chris Feenstra <73584137+cfeenstra1024@users.noreply.github.com> Date: Wed, 13 Mar 2024 04:01:22 +0100 Subject: [PATCH 1069/2101] Added Kamstrup Multical 40x component (#4200) Co-authored-by: Chris Feenstra Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Co-authored-by: cfeenstra1024 --- CODEOWNERS | 1 + esphome/components/dfplayer/__init__.py | 3 +- esphome/components/ezo_pmp/__init__.py | 9 +- esphome/components/kamstrup_kmp/__init__.py | 0 .../components/kamstrup_kmp/kamstrup_kmp.cpp | 301 ++++++++++++++++++ .../components/kamstrup_kmp/kamstrup_kmp.h | 131 ++++++++ esphome/components/kamstrup_kmp/sensor.py | 132 ++++++++ esphome/components/media_player/__init__.py | 3 +- esphome/const.py | 1 + tests/components/kamstrup_kmp/common.yaml | 25 ++ .../kamstrup_kmp/test.esp32-idf.yaml | 5 + tests/components/kamstrup_kmp/test.esp32.yaml | 5 + .../components/kamstrup_kmp/test.esp8266.yaml | 5 + 13 files changed, 615 insertions(+), 6 deletions(-) create mode 100644 esphome/components/kamstrup_kmp/__init__.py create mode 100644 esphome/components/kamstrup_kmp/kamstrup_kmp.cpp create mode 100644 esphome/components/kamstrup_kmp/kamstrup_kmp.h create mode 100644 esphome/components/kamstrup_kmp/sensor.py create mode 100644 tests/components/kamstrup_kmp/common.yaml create mode 100644 tests/components/kamstrup_kmp/test.esp32-idf.yaml create mode 100644 tests/components/kamstrup_kmp/test.esp32.yaml create mode 100644 tests/components/kamstrup_kmp/test.esp8266.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 0a94c254d2..4c24096faa 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -173,6 +173,7 @@ esphome/components/integration/* @OttoWinter esphome/components/internal_temperature/* @Mat931 esphome/components/interval/* @esphome/core esphome/components/json/* @OttoWinter +esphome/components/kamstrup_kmp/* @cfeenstra1024 esphome/components/key_collector/* @ssieb esphome/components/key_provider/* @ssieb esphome/components/kuntze/* @ssieb diff --git a/esphome/components/dfplayer/__init__.py b/esphome/components/dfplayer/__init__.py index 5ea04b4804..c37c9999aa 100644 --- a/esphome/components/dfplayer/__init__.py +++ b/esphome/components/dfplayer/__init__.py @@ -1,7 +1,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation -from esphome.const import CONF_ID, CONF_TRIGGER_ID, CONF_FILE, CONF_DEVICE +from esphome.const import CONF_ID, CONF_TRIGGER_ID, CONF_FILE, CONF_DEVICE, CONF_VOLUME from esphome.components import uart DEPENDENCIES = ["uart"] @@ -19,7 +19,6 @@ DFPlayerIsPlayingCondition = dfplayer_ns.class_( MULTI_CONF = True CONF_FOLDER = "folder" CONF_LOOP = "loop" -CONF_VOLUME = "volume" CONF_EQ_PRESET = "eq_preset" CONF_ON_FINISHED_PLAYBACK = "on_finished_playback" diff --git a/esphome/components/ezo_pmp/__init__.py b/esphome/components/ezo_pmp/__init__.py index e65fcf74ca..87cda41f89 100644 --- a/esphome/components/ezo_pmp/__init__.py +++ b/esphome/components/ezo_pmp/__init__.py @@ -1,7 +1,13 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import i2c -from esphome.const import CONF_ADDRESS, CONF_COMMAND, CONF_ID, CONF_DURATION +from esphome.const import ( + CONF_ADDRESS, + CONF_COMMAND, + CONF_ID, + CONF_DURATION, + CONF_VOLUME, +) from esphome import automation from esphome.automation import maybe_simple_id @@ -9,7 +15,6 @@ CODEOWNERS = ["@carlos-sarmiento"] DEPENDENCIES = ["i2c"] MULTI_CONF = True -CONF_VOLUME = "volume" CONF_VOLUME_PER_MINUTE = "volume_per_minute" ezo_pmp_ns = cg.esphome_ns.namespace("ezo_pmp") diff --git a/esphome/components/kamstrup_kmp/__init__.py b/esphome/components/kamstrup_kmp/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/kamstrup_kmp/kamstrup_kmp.cpp b/esphome/components/kamstrup_kmp/kamstrup_kmp.cpp new file mode 100644 index 0000000000..b870d1b56d --- /dev/null +++ b/esphome/components/kamstrup_kmp/kamstrup_kmp.cpp @@ -0,0 +1,301 @@ +#include "kamstrup_kmp.h" + +#include "esphome/core/log.h" + +namespace esphome { +namespace kamstrup_kmp { + +static const char *const TAG = "kamstrup_kmp"; + +void KamstrupKMPComponent::dump_config() { + ESP_LOGCONFIG(TAG, "kamstrup_kmp:"); + if (this->is_failed()) { + ESP_LOGE(TAG, "Communication with Kamstrup meter failed!"); + } + LOG_UPDATE_INTERVAL(this); + + LOG_SENSOR(" ", "Heat Energy", this->heat_energy_sensor_); + LOG_SENSOR(" ", "Power", this->power_sensor_); + LOG_SENSOR(" ", "Temperature 1", this->temp1_sensor_); + LOG_SENSOR(" ", "Temperature 2", this->temp2_sensor_); + LOG_SENSOR(" ", "Temperature Difference", this->temp_diff_sensor_); + LOG_SENSOR(" ", "Flow", this->flow_sensor_); + LOG_SENSOR(" ", "Volume", this->volume_sensor_); + + for (int i = 0; i < this->custom_sensors_.size(); i++) { + LOG_SENSOR(" ", "Custom Sensor", this->custom_sensors_[i]); + ESP_LOGCONFIG(TAG, " Command: 0x%04X", this->custom_commands_[i]); + } + + 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); + } + + if (this->power_sensor_ != nullptr) { + this->command_queue_.push(CMD_POWER); + } + + if (this->temp1_sensor_ != nullptr) { + this->command_queue_.push(CMD_TEMP1); + } + + if (this->temp2_sensor_ != nullptr) { + this->command_queue_.push(CMD_TEMP2); + } + + if (this->temp_diff_sensor_ != nullptr) { + this->command_queue_.push(CMD_TEMP_DIFF); + } + + if (this->flow_sensor_ != nullptr) { + this->command_queue_.push(CMD_FLOW); + } + + if (this->volume_sensor_ != nullptr) { + this->command_queue_.push(CMD_VOLUME); + } + + for (uint16_t custom_command : this->custom_commands_) { + this->command_queue_.push(custom_command); + } +} + +void KamstrupKMPComponent::loop() { + if (!this->command_queue_.empty()) { + uint16_t command = this->command_queue_.front(); + this->send_command_(command); + this->command_queue_.pop(); + } +} + +void KamstrupKMPComponent::send_command_(uint16_t command) { + uint32_t msg_len = 5; + uint8_t msg[msg_len]; + + msg[0] = 0x3F; + msg[1] = 0x10; + msg[2] = 0x01; + msg[3] = command >> 8; + msg[4] = command & 0xFF; + + this->clear_uart_rx_buffer_(); + this->send_message_(msg, msg_len); + this->read_command_(command); +} + +void KamstrupKMPComponent::send_message_(const uint8_t *msg, int msg_len) { + int buffer_len = msg_len + 2; + uint8_t buffer[buffer_len]; + + // Prepare the basic message and appand CRC + for (int i = 0; i < msg_len; i++) { + buffer[i] = msg[i]; + } + + buffer[buffer_len - 2] = 0; + buffer[buffer_len - 1] = 0; + + uint16_t crc = crc16_ccitt(buffer, buffer_len); + buffer[buffer_len - 2] = crc >> 8; + buffer[buffer_len - 1] = crc & 0xFF; + + // Prepare actual TX message + uint8_t tx_msg[20]; + int tx_msg_len = 1; + tx_msg[0] = 0x80; // prefix + + for (int i = 0; i < buffer_len; i++) { + if (buffer[i] == 0x06 || buffer[i] == 0x0d || buffer[i] == 0x1b || buffer[i] == 0x40 || buffer[i] == 0x80) { + tx_msg[tx_msg_len++] = 0x1b; + tx_msg[tx_msg_len++] = buffer[i] ^ 0xff; + } else { + tx_msg[tx_msg_len++] = buffer[i]; + } + } + + tx_msg[tx_msg_len++] = 0x0D; // EOM + + this->write_array(tx_msg, tx_msg_len); +} + +void KamstrupKMPComponent::clear_uart_rx_buffer_() { + uint8_t tmp; + while (this->available()) { + this->read_byte(&tmp); + } +} + +void KamstrupKMPComponent::read_command_(uint16_t command) { + uint8_t buffer[20] = {0}; + int buffer_len = 0; + int data; + int timeout = 250; // ms + + // Read the data from the UART + while (timeout > 0) { + if (this->available()) { + data = this->read(); + if (data > -1) { + if (data == 0x40) { // start of message + buffer_len = 0; + } + buffer[buffer_len++] = (uint8_t) data; + if (data == 0x0D) { + break; + } + } else { + ESP_LOGE(TAG, "Error while reading from UART"); + } + } else { + delay(1); + timeout--; + } + } + + if (timeout == 0 || buffer_len == 0) { + ESP_LOGE(TAG, "Request timed out"); + return; + } + + // Validate message (prefix and suffix) + if (buffer[0] != 0x40) { + ESP_LOGE(TAG, "Received invalid message (prefix mismatch received 0x%02X, expected 0x40)", buffer[0]); + return; + } + + if (buffer[buffer_len - 1] != 0x0D) { + ESP_LOGE(TAG, "Received invalid message (EOM mismatch received 0x%02X, expected 0x0D)", buffer[buffer_len - 1]); + return; + } + + // Decode + uint8_t msg[20] = {0}; + int msg_len = 0; + for (int i = 1; i < buffer_len - 1; i++) { + if (buffer[i] == 0x1B) { + msg[msg_len++] = buffer[i + 1] ^ 0xFF; + i++; + } else { + msg[msg_len++] = buffer[i]; + } + } + + // Validate CRC + if (crc16_ccitt(msg, msg_len)) { + ESP_LOGE(TAG, "Received invalid message (CRC mismatch)"); + return; + } + + // All seems good. Now parse the message + this->parse_command_message_(command, msg, msg_len); +} + +void KamstrupKMPComponent::parse_command_message_(uint16_t command, const uint8_t *msg, int msg_len) { + // Validate the message + if (msg_len < 8) { + ESP_LOGE(TAG, "Received invalid message (message too small)"); + return; + } + + if (msg[0] != 0x3F || msg[1] != 0x10) { + ESP_LOGE(TAG, "Received invalid message (invalid header received 0x%02X%02X, expected 0x3F10)", msg[0], msg[1]); + return; + } + + uint16_t recv_command = msg[2] << 8 | msg[3]; + if (recv_command != command) { + ESP_LOGE(TAG, "Received invalid message (invalid unexpected command received 0x%04X, expected 0x%04X)", + recv_command, command); + return; + } + + 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); + return; + } + + // Calculate exponent + float exponent = msg[6] & 0x3F; + if (msg[6] & 0x40) { + exponent = -exponent; + } + exponent = powf(10, exponent); + if (msg[6] & 0x80) { + exponent = -exponent; + } + + // Calculate mantissa + uint32_t mantissa = 0; + for (int i = 0; i < mantissa_range; i++) { + mantissa <<= 8; + mantissa |= msg[i + 7]; + } + + // Calculate the actual value + float value = mantissa * exponent; + + // Set sensor value + this->set_sensor_value_(command, value, unit_idx); +} + +void KamstrupKMPComponent::set_sensor_value_(uint16_t command, float value, uint8_t unit_idx) { + const char *unit = UNITS[unit_idx]; + + // Standard sensors + if (command == CMD_HEAT_ENERGY && this->heat_energy_sensor_ != nullptr) { + this->heat_energy_sensor_->publish_state(value); + } else if (command == CMD_POWER && this->power_sensor_ != nullptr) { + this->power_sensor_->publish_state(value); + } else if (command == CMD_TEMP1 && this->temp1_sensor_ != nullptr) { + this->temp1_sensor_->publish_state(value); + } else if (command == CMD_TEMP2 && this->temp2_sensor_ != nullptr) { + this->temp2_sensor_->publish_state(value); + } else if (command == CMD_TEMP_DIFF && this->temp_diff_sensor_ != nullptr) { + this->temp_diff_sensor_->publish_state(value); + } else if (command == CMD_FLOW && this->flow_sensor_ != nullptr) { + this->flow_sensor_->publish_state(value); + } else if (command == CMD_VOLUME && this->volume_sensor_ != nullptr) { + this->volume_sensor_->publish_state(value); + } + + // Custom sensors + for (int i = 0; i < this->custom_commands_.size(); i++) { + if (command == this->custom_commands_[i]) { + this->custom_sensors_[i]->publish_state(value); + } + } + + ESP_LOGD(TAG, "Received value for command 0x%04X: %.3f [%s]", command, value, unit); +} + +uint16_t crc16_ccitt(const uint8_t *buffer, int len) { + uint32_t poly = 0x1021; + uint32_t reg = 0x00; + for (int i = 0; i < len; i++) { + int mask = 0x80; + while (mask > 0) { + reg <<= 1; + if (buffer[i] & mask) { + reg |= 1; + } + mask >>= 1; + if (reg & 0x10000) { + reg &= 0xffff; + reg ^= poly; + } + } + } + return (uint16_t) reg; +} + +} // namespace kamstrup_kmp +} // namespace esphome diff --git a/esphome/components/kamstrup_kmp/kamstrup_kmp.h b/esphome/components/kamstrup_kmp/kamstrup_kmp.h new file mode 100644 index 0000000000..c9cc9c5a39 --- /dev/null +++ b/esphome/components/kamstrup_kmp/kamstrup_kmp.h @@ -0,0 +1,131 @@ +#pragma once + +#include "esphome/components/sensor/sensor.h" +#include "esphome/components/uart/uart.h" +#include "esphome/core/component.h" + +namespace esphome { +namespace kamstrup_kmp { + +/* + =========================================================================== + === KAMSTRUP KMP === + =========================================================================== + + Kamstrup Meter Protocol (KMP) is a protocol used with Kamstrup district + heating meters, e.g. Kamstrup MULTICAL 403. + These devices register consumed heat from a district heating system. + It does this by measuring the incoming and outgoing water temperature + and by measuring the water flow. The temperature difference (delta T) + together with the water flow results in consumed energy, typically + in giga joule (GJ). + + The Kamstrup Multical has an optical interface just above the display. + This interface is essentially an RS-232 interface using a proprietary + protocol (Kamstrup Meter Protocol [KMP]). + + The integration uses this optical interface to periodically read the + configured values (sensors) from the meter. Supported sensors are: + - Heat Energy [GJ] + - Current Power Consumption [kW] + - Temperature 1 [°C] + - Temperature 2 [°C] + - Temperature Difference [°K] + - Water Flow [l/h] + - Volume [m3] + + Apart from these supported 'fixed' sensors, the user can configure up to + five custom sensors. The KMP command (16 bit unsigned int) has to be + provided in that case. + + Note: + The optical interface is enabled as soon as a button on the meter is pushed. + The interface stays active for a few minutes. To keep the interface 'alive' + magnets must be placed around the optical sensor. + + Units: + Units are set using the regular Sensor config in the user yaml. However, + KMP does also send the correct unit with every value. When DEBUG logging + is enabled, the received value with the received unit are logged. + + Acknowledgement: + This interface was inspired by: + - https://atomstar.tweakblogs.net/blog/19110/reading-out-kamstrup-multical-402-403-with-home-built-optical-head + - https://wiki.hal9k.dk/projects/kamstrup +*/ + +// KMP Commands +static const uint16_t CMD_HEAT_ENERGY = 0x003C; +static const uint16_t CMD_POWER = 0x0050; +static const uint16_t CMD_TEMP1 = 0x0056; +static const uint16_t CMD_TEMP2 = 0x0057; +static const uint16_t CMD_TEMP_DIFF = 0x0059; +static const uint16_t CMD_FLOW = 0x004A; +static const uint16_t CMD_VOLUME = 0x0044; + +// KMP units +static const char *const UNITS[] = { + "", "Wh", "kWh", "MWh", "GWh", "J", "kJ", "MJ", "GJ", "Cal", + "kCal", "Mcal", "Gcal", "varh", "kvarh", "Mvarh", "Gvarh", "VAh", "kVAh", "MVAh", + "GVAh", "kW", "kW", "MW", "GW", "kvar", "kvar", "Mvar", "Gvar", "VA", + "kVA", "MVA", "GVA", "V", "A", "kV", "kA", "C", "K", "l", + "m3", "l/h", "m3/h", "m3xC", "ton", "ton/h", "h", "hh:mm:ss", "yy:mm:dd", "yyyy:mm:dd", + "mm:dd", "", "bar", "RTC", "ASCII", "m3 x 10", "ton x 10", "GJ x 10", "minutes", "Bitfield", + "s", "ms", "days", "RTC-Q", "Datetime"}; + +class KamstrupKMPComponent : public PollingComponent, public uart::UARTDevice { + public: + void set_heat_energy_sensor(sensor::Sensor *sensor) { this->heat_energy_sensor_ = sensor; } + void set_power_sensor(sensor::Sensor *sensor) { this->power_sensor_ = sensor; } + void set_temp1_sensor(sensor::Sensor *sensor) { this->temp1_sensor_ = sensor; } + void set_temp2_sensor(sensor::Sensor *sensor) { this->temp2_sensor_ = sensor; } + void set_temp_diff_sensor(sensor::Sensor *sensor) { this->temp_diff_sensor_ = sensor; } + 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) { + this->custom_sensors_.push_back(sensor); + this->custom_commands_.push_back(command); + } + + protected: + // Sensors + sensor::Sensor *heat_energy_sensor_{nullptr}; + sensor::Sensor *power_sensor_{nullptr}; + sensor::Sensor *temp1_sensor_{nullptr}; + sensor::Sensor *temp2_sensor_{nullptr}; + sensor::Sensor *temp_diff_sensor_{nullptr}; + sensor::Sensor *flow_sensor_{nullptr}; + sensor::Sensor *volume_sensor_{nullptr}; + + // Custom sensors and commands + std::vector custom_sensors_; + std::vector custom_commands_; + + // Command queue + std::queue command_queue_; + + // Methods + + // Sends a command to the meter and receives its response + void send_command_(uint16_t command); + // Sends a message to the meter. A prefix/suffix and CRC are added + void send_message_(const uint8_t *msg, int msg_len); + // Clears and data that might be in the UART Rx buffer + void clear_uart_rx_buffer_(); + // Reads and validates the response to a send command + void read_command_(uint16_t command); + // Parses a received message + void parse_command_message_(uint16_t command, const uint8_t *msg, int msg_len); + // Sets the received value to the correct sensor + void set_sensor_value_(uint16_t command, float value, uint8_t unit_idx); +}; + +// "true" CCITT CRC-16 +uint16_t crc16_ccitt(const uint8_t *buffer, int len); + +} // namespace kamstrup_kmp +} // namespace esphome diff --git a/esphome/components/kamstrup_kmp/sensor.py b/esphome/components/kamstrup_kmp/sensor.py new file mode 100644 index 0000000000..c9024e4a2b --- /dev/null +++ b/esphome/components/kamstrup_kmp/sensor.py @@ -0,0 +1,132 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import sensor, uart +from esphome.const import ( + CONF_COMMAND, + CONF_CUSTOM, + CONF_FLOW, + CONF_ID, + CONF_POWER, + CONF_VOLUME, + DEVICE_CLASS_EMPTY, + DEVICE_CLASS_ENERGY, + DEVICE_CLASS_POWER, + DEVICE_CLASS_TEMPERATURE, + DEVICE_CLASS_VOLUME, + STATE_CLASS_MEASUREMENT, + STATE_CLASS_TOTAL_INCREASING, + UNIT_CELSIUS, + UNIT_CUBIC_METER, + UNIT_EMPTY, + UNIT_KELVIN, + UNIT_KILOWATT, +) + +CODEOWNERS = ["@cfeenstra1024"] +DEPENDENCIES = ["uart"] + +kamstrup_kmp_ns = cg.esphome_ns.namespace("kamstrup_kmp") +KamstrupKMPComponent = kamstrup_kmp_ns.class_( + "KamstrupKMPComponent", cg.PollingComponent, uart.UARTDevice +) + +CONF_HEAT_ENERGY = "heat_energy" +CONF_TEMP1 = "temp1" +CONF_TEMP2 = "temp2" +CONF_TEMP_DIFF = "temp_diff" + +UNIT_GIGA_JOULE = "GJ" +UNIT_LITRE_PER_HOUR = "l/h" + +# Note: The sensor units are set automatically based un the received data from the meter +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(KamstrupKMPComponent), + cv.Optional(CONF_HEAT_ENERGY): sensor.sensor_schema( + accuracy_decimals=3, + device_class=DEVICE_CLASS_ENERGY, + state_class=STATE_CLASS_TOTAL_INCREASING, + unit_of_measurement=UNIT_GIGA_JOULE, + ), + cv.Optional(CONF_POWER): sensor.sensor_schema( + accuracy_decimals=3, + device_class=DEVICE_CLASS_POWER, + state_class=STATE_CLASS_MEASUREMENT, + unit_of_measurement=UNIT_KILOWATT, + ), + cv.Optional(CONF_TEMP1): sensor.sensor_schema( + accuracy_decimals=1, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + unit_of_measurement=UNIT_CELSIUS, + ), + cv.Optional(CONF_TEMP2): sensor.sensor_schema( + accuracy_decimals=1, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + unit_of_measurement=UNIT_CELSIUS, + ), + cv.Optional(CONF_TEMP_DIFF): sensor.sensor_schema( + accuracy_decimals=1, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + unit_of_measurement=UNIT_KELVIN, + ), + cv.Optional(CONF_FLOW): sensor.sensor_schema( + accuracy_decimals=1, + device_class=DEVICE_CLASS_VOLUME, + state_class=STATE_CLASS_MEASUREMENT, + unit_of_measurement=UNIT_LITRE_PER_HOUR, + ), + cv.Optional(CONF_VOLUME): sensor.sensor_schema( + accuracy_decimals=1, + device_class=DEVICE_CLASS_VOLUME, + state_class=STATE_CLASS_TOTAL_INCREASING, + unit_of_measurement=UNIT_CUBIC_METER, + ), + cv.Optional(CONF_CUSTOM): cv.ensure_list( + sensor.sensor_schema( + accuracy_decimals=1, + device_class=DEVICE_CLASS_EMPTY, + state_class=STATE_CLASS_MEASUREMENT, + unit_of_measurement=UNIT_EMPTY, + ).extend({cv.Required(CONF_COMMAND): cv.hex_uint16_t}) + ), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(uart.UART_DEVICE_SCHEMA) +) + +FINAL_VALIDATE_SCHEMA = uart.final_validate_device_schema( + "kamstrup_kmp", baud_rate=1200, require_rx=True, require_tx=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) + + # Standard sensors + for key in [ + CONF_HEAT_ENERGY, + CONF_POWER, + CONF_TEMP1, + CONF_TEMP2, + CONF_TEMP_DIFF, + CONF_FLOW, + CONF_VOLUME, + ]: + if key not in config: + continue + conf = config[key] + sens = await sensor.new_sensor(conf) + cg.add(getattr(var, f"set_{key}_sensor")(sens)) + + # Custom sensors + if CONF_CUSTOM in config: + for conf in config[CONF_CUSTOM]: + sens = await sensor.new_sensor(conf) + cg.add(var.add_custom_sensor(sens, conf[CONF_COMMAND])) diff --git a/esphome/components/media_player/__init__.py b/esphome/components/media_player/__init__.py index 80f5fc558a..86e038d76d 100644 --- a/esphome/components/media_player/__init__.py +++ b/esphome/components/media_player/__init__.py @@ -3,7 +3,7 @@ import esphome.config_validation as cv import esphome.codegen as cg from esphome.automation import maybe_simple_id -from esphome.const import CONF_ID, CONF_ON_STATE, CONF_TRIGGER_ID +from esphome.const import CONF_ID, CONF_ON_STATE, CONF_TRIGGER_ID, CONF_VOLUME from esphome.core import CORE from esphome.coroutine import coroutine_with_priority from esphome.cpp_helpers import setup_entity @@ -43,7 +43,6 @@ VolumeSetAction = media_player_ns.class_( ) -CONF_VOLUME = "volume" CONF_ON_IDLE = "on_idle" CONF_ON_PLAY = "on_play" CONF_ON_PAUSE = "on_pause" diff --git a/esphome/const.py b/esphome/const.py index 4e53970cdf..918cf94ed3 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -856,6 +856,7 @@ CONF_VISUAL = "visual" CONF_VOLTAGE = "voltage" CONF_VOLTAGE_ATTENUATION = "voltage_attenuation" CONF_VOLTAGE_DIVIDER = "voltage_divider" +CONF_VOLUME = "volume" CONF_WAIT_TIME = "wait_time" CONF_WAIT_UNTIL = "wait_until" CONF_WAKEUP_PIN = "wakeup_pin" diff --git a/tests/components/kamstrup_kmp/common.yaml b/tests/components/kamstrup_kmp/common.yaml new file mode 100644 index 0000000000..b348d03c72 --- /dev/null +++ b/tests/components/kamstrup_kmp/common.yaml @@ -0,0 +1,25 @@ +uart: + tx_pin: ${uart_tx_pin} + rx_pin: ${uart_rx_pin} + baud_rate: 1200 + stop_bits: 2 + +sensor: + - platform: kamstrup_kmp + heat_energy: + name: Heat Energy + power: + name: Power + temp1: + name: Temperature 1 + temp2: + name: Temperature 2 + temp_diff: + name: Temperature Difference + flow: + name: Flow + volume: + name: Volume + custom: + - name: Custom 1 + command: 0x1234 diff --git a/tests/components/kamstrup_kmp/test.esp32-idf.yaml b/tests/components/kamstrup_kmp/test.esp32-idf.yaml new file mode 100644 index 0000000000..adc2c4d24a --- /dev/null +++ b/tests/components/kamstrup_kmp/test.esp32-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + uart_tx_pin: GPIO1 + uart_rx_pin: GPIO3 + +<<: !include common.yaml diff --git a/tests/components/kamstrup_kmp/test.esp32.yaml b/tests/components/kamstrup_kmp/test.esp32.yaml new file mode 100644 index 0000000000..adc2c4d24a --- /dev/null +++ b/tests/components/kamstrup_kmp/test.esp32.yaml @@ -0,0 +1,5 @@ +substitutions: + uart_tx_pin: GPIO1 + uart_rx_pin: GPIO3 + +<<: !include common.yaml diff --git a/tests/components/kamstrup_kmp/test.esp8266.yaml b/tests/components/kamstrup_kmp/test.esp8266.yaml new file mode 100644 index 0000000000..adc2c4d24a --- /dev/null +++ b/tests/components/kamstrup_kmp/test.esp8266.yaml @@ -0,0 +1,5 @@ +substitutions: + uart_tx_pin: GPIO1 + uart_rx_pin: GPIO3 + +<<: !include common.yaml From de436785254006cd84b490cefe2c55023ba75fc0 Mon Sep 17 00:00:00 2001 From: kev300 Date: Wed, 13 Mar 2024 04:25:38 +0100 Subject: [PATCH 1070/2101] =?UTF-8?q?add=20possibility=20to=20provide=20di?= =?UTF-8?q?fferent=20conversion=20times=20for=20Bus=20Voltage=E2=80=A6=20(?= =?UTF-8?q?#6327)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kevin Hübner --- esphome/components/ina226/ina226.cpp | 7 ++++--- esphome/components/ina226/ina226.h | 6 ++++-- esphome/components/ina226/sensor.py | 21 +++++++++++++++++++-- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/esphome/components/ina226/ina226.cpp b/esphome/components/ina226/ina226.cpp index 94016ad302..7a57c118af 100644 --- a/esphome/components/ina226/ina226.cpp +++ b/esphome/components/ina226/ina226.cpp @@ -55,10 +55,10 @@ void INA226Component::setup() { config.avg_samples = this->adc_avg_samples_; // Bus Voltage Conversion Time VBUSCT Bit Settings [8:6] (100 -> 1.1ms, 111 -> 8.244 ms) - config.bus_voltage_conversion_time = this->adc_time_; + config.bus_voltage_conversion_time = this->adc_time_voltage_; // Shunt Voltage Conversion Time VSHCT Bit Settings [5:3] (100 -> 1.1ms, 111 -> 8.244 ms) - config.shunt_voltage_conversion_time = this->adc_time_; + config.shunt_voltage_conversion_time = this->adc_time_current_; // Mode Settings [2:0] Combinations (111 -> Shunt and Bus, Continuous) config.mode = 0b111; @@ -93,7 +93,8 @@ void INA226Component::dump_config() { } LOG_UPDATE_INTERVAL(this); - ESP_LOGCONFIG(TAG, " ADC Conversion Time: %d", INA226_ADC_TIMES[this->adc_time_ & 0b111]); + ESP_LOGCONFIG(TAG, " ADC Conversion Time Bus Voltage: %d", INA226_ADC_TIMES[this->adc_time_voltage_ & 0b111]); + ESP_LOGCONFIG(TAG, " ADC Conversion Time Shunt Voltage: %d", INA226_ADC_TIMES[this->adc_time_current_ & 0b111]); ESP_LOGCONFIG(TAG, " ADC Averaging Samples: %d", INA226_ADC_AVG_SAMPLES[this->adc_avg_samples_ & 0b111]); LOG_SENSOR(" ", "Bus Voltage", this->bus_voltage_sensor_); diff --git a/esphome/components/ina226/ina226.h b/esphome/components/ina226/ina226.h index 2af9c8c195..61214fea0e 100644 --- a/esphome/components/ina226/ina226.h +++ b/esphome/components/ina226/ina226.h @@ -50,7 +50,8 @@ class INA226Component : public PollingComponent, public i2c::I2CDevice { void set_shunt_resistance_ohm(float shunt_resistance_ohm) { shunt_resistance_ohm_ = shunt_resistance_ohm; } void set_max_current_a(float max_current_a) { max_current_a_ = max_current_a; } - void set_adc_time(AdcTime time) { adc_time_ = time; } + void set_adc_time_voltage(AdcTime time) { adc_time_voltage_ = time; } + void set_adc_time_current(AdcTime time) { adc_time_current_ = time; } void set_adc_avg_samples(AdcAvgSamples samples) { adc_avg_samples_ = samples; } void set_bus_voltage_sensor(sensor::Sensor *bus_voltage_sensor) { bus_voltage_sensor_ = bus_voltage_sensor; } @@ -61,7 +62,8 @@ class INA226Component : public PollingComponent, public i2c::I2CDevice { protected: float shunt_resistance_ohm_; float max_current_a_; - AdcTime adc_time_{AdcTime::ADC_TIME_1100US}; + AdcTime adc_time_voltage_{AdcTime::ADC_TIME_1100US}; + AdcTime adc_time_current_{AdcTime::ADC_TIME_1100US}; AdcAvgSamples adc_avg_samples_{AdcAvgSamples::ADC_AVG_SAMPLES_4}; uint32_t calibration_lsb_; sensor::Sensor *bus_voltage_sensor_{nullptr}; diff --git a/esphome/components/ina226/sensor.py b/esphome/components/ina226/sensor.py index 32fca504a9..0accc58c00 100644 --- a/esphome/components/ina226/sensor.py +++ b/esphome/components/ina226/sensor.py @@ -16,6 +16,7 @@ from esphome.const import ( UNIT_VOLT, UNIT_AMPERE, UNIT_WATT, + CONF_VOLTAGE, ) DEPENDENCIES = ["i2c"] @@ -92,7 +93,15 @@ CONFIG_SCHEMA = ( cv.Optional(CONF_MAX_CURRENT, default=3.2): cv.All( cv.current, cv.Range(min=0.0) ), - cv.Optional(CONF_ADC_TIME, default="1100 us"): validate_adc_time, + cv.Optional(CONF_ADC_TIME, default="1100 us"): cv.Any( + validate_adc_time, + cv.Schema( + { + cv.Required(CONF_VOLTAGE): validate_adc_time, + cv.Required(CONF_CURRENT): validate_adc_time, + } + ), + ), cv.Optional(CONF_ADC_AVERAGING, default=4): cv.enum( ADC_AVG_SAMPLES, int=True ), @@ -110,7 +119,15 @@ async def to_code(config): cg.add(var.set_shunt_resistance_ohm(config[CONF_SHUNT_RESISTANCE])) cg.add(var.set_max_current_a(config[CONF_MAX_CURRENT])) - cg.add(var.set_adc_time(config[CONF_ADC_TIME])) + + adc_time_config = config[CONF_ADC_TIME] + if isinstance(adc_time_config, dict): + cg.add(var.set_adc_time_voltage(adc_time_config[CONF_VOLTAGE])) + cg.add(var.set_adc_time_current(adc_time_config[CONF_CURRENT])) + else: + cg.add(var.set_adc_time_voltage(adc_time_config)) + cg.add(var.set_adc_time_current(adc_time_config)) + cg.add(var.set_adc_avg_samples(config[CONF_ADC_AVERAGING])) if CONF_BUS_VOLTAGE in config: From 0ebb6efee691a4330050073ce74d60a8d63d65a4 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 13 Mar 2024 16:33:42 +1300 Subject: [PATCH 1071/2101] Bump version to 2024.3.0b1 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 918cf94ed3..c5e86444ab 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.3.0-dev" +__version__ = "2024.3.0b1" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From bbf7e2be28ba0c01fd82f5ce02cf01b3e15f2a2c Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 13 Mar 2024 16:33:43 +1300 Subject: [PATCH 1072/2101] Bump version to 2024.4.0-dev --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 918cf94ed3..8e3fd59ff0 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.3.0-dev" +__version__ = "2024.4.0-dev" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From dbf50381f1ddbf9ab6a92ca78301f2edced55d03 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Thu, 14 Mar 2024 13:42:54 +1100 Subject: [PATCH 1073/2101] SPI: Revert clk_pin to standard output pin schema (#6368) --- esphome/components/spi/__init__.py | 17 ++--------------- tests/components/spi/test.esp32-s3-idf.yaml | 3 ++- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/esphome/components/spi/__init__.py b/esphome/components/spi/__init__.py index c2335bd92a..2847c5bfa1 100644 --- a/esphome/components/spi/__init__.py +++ b/esphome/components/spi/__init__.py @@ -29,7 +29,6 @@ from esphome.const import ( PLATFORM_ESP32, PLATFORM_ESP8266, PLATFORM_RP2040, - CONF_ALLOW_OTHER_USES, CONF_DATA_PINS, ) from esphome.core import ( @@ -199,8 +198,6 @@ def get_hw_spi(config, available): def validate_spi_config(config): available = list(range(len(get_hw_interface_list()))) for spi in config: - # map pin number to schema - spi[CONF_CLK_PIN] = pins.gpio_output_pin_schema(spi[CONF_CLK_PIN]) interface = spi[CONF_INTERFACE] if interface == "software": pass @@ -257,21 +254,11 @@ def get_spi_interface(index): return "new SPIClass(HSPI)" -# Do not use a pin schema for the number, as that will trigger a pin reuse error due to duplication of the -# clock pin in the standard and quad schemas. -clk_pin_validator = cv.maybe_simple_value( - { - cv.Required(CONF_NUMBER): cv.Any(cv.int_, cv.string), - cv.Optional(CONF_ALLOW_OTHER_USES): cv.boolean, - }, - key=CONF_NUMBER, -) - SPI_SCHEMA = cv.All( cv.Schema( { cv.GenerateID(): cv.declare_id(SPIComponent), - cv.Required(CONF_CLK_PIN): clk_pin_validator, + cv.Required(CONF_CLK_PIN): pins.gpio_output_pin_schema, cv.Optional(CONF_MISO_PIN): pins.gpio_input_pin_schema, cv.Optional(CONF_MOSI_PIN): pins.gpio_output_pin_schema, cv.Optional(CONF_FORCE_SW): cv.invalid( @@ -291,7 +278,7 @@ SPI_QUAD_SCHEMA = cv.All( cv.Schema( { cv.GenerateID(): cv.declare_id(QuadSPIComponent), - cv.Required(CONF_CLK_PIN): clk_pin_validator, + cv.Required(CONF_CLK_PIN): pins.gpio_output_pin_schema, cv.Required(CONF_DATA_PINS): cv.All( cv.ensure_list(pins.internal_gpio_output_pin_number), cv.Length(min=4, max=4), diff --git a/tests/components/spi/test.esp32-s3-idf.yaml b/tests/components/spi/test.esp32-s3-idf.yaml index 3aae21cbeb..8db934023a 100644 --- a/tests/components/spi/test.esp32-s3-idf.yaml +++ b/tests/components/spi/test.esp32-s3-idf.yaml @@ -2,7 +2,8 @@ spi: - id: spi_id_1 type: single clk_pin: - number: GPIO7 + number: GPIO0 + ignore_strapping_warning: true allow_other_uses: false mosi_pin: GPIO6 interface: hardware From df5dfb8087ebb78d85e8789ab88e543f3e683b39 Mon Sep 17 00:00:00 2001 From: Attila Farago Date: Thu, 14 Mar 2024 03:56:17 +0100 Subject: [PATCH 1074/2101] Allow button press action in web_server to be executed via GET method (#5938) --- esphome/components/web_server/web_server.cpp | 24 ++++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index ba787239da..69d601ed49 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -486,7 +486,7 @@ void WebServer::handle_switch_request(AsyncWebServerRequest *request, const UrlM if (obj->get_object_id() != match.id) continue; - if (request->method() == HTTP_GET) { + if (request->method() == HTTP_GET && match.method.empty()) { std::string data = this->switch_json(obj, obj->state, DETAIL_STATE); request->send(200, "application/json", data.c_str()); } else if (match.method == "toggle") { @@ -517,7 +517,7 @@ void WebServer::handle_button_request(AsyncWebServerRequest *request, const UrlM for (button::Button *obj : App.get_buttons()) { if (obj->get_object_id() != match.id) continue; - if (request->method() == HTTP_POST && match.method == "press") { + if (match.method == "press") { this->schedule_([obj]() { obj->press(); }); request->send(200); return; @@ -572,7 +572,7 @@ void WebServer::handle_fan_request(AsyncWebServerRequest *request, const UrlMatc if (obj->get_object_id() != match.id) continue; - if (request->method() == HTTP_GET) { + if (request->method() == HTTP_GET && match.method.empty()) { std::string data = this->fan_json(obj, DETAIL_STATE); request->send(200, "application/json", data.c_str()); } else if (match.method == "toggle") { @@ -630,7 +630,7 @@ void WebServer::handle_light_request(AsyncWebServerRequest *request, const UrlMa if (obj->get_object_id() != match.id) continue; - if (request->method() == HTTP_GET) { + if (request->method() == HTTP_GET && match.method.empty()) { std::string data = this->light_json(obj, DETAIL_STATE); request->send(200, "application/json", data.c_str()); } else if (match.method == "toggle") { @@ -736,7 +736,7 @@ void WebServer::handle_cover_request(AsyncWebServerRequest *request, const UrlMa if (obj->get_object_id() != match.id) continue; - if (request->method() == HTTP_GET) { + if (request->method() == HTTP_GET && match.method.empty()) { std::string data = this->cover_json(obj, DETAIL_STATE); request->send(200, "application/json", data.c_str()); continue; @@ -805,7 +805,7 @@ void WebServer::handle_number_request(AsyncWebServerRequest *request, const UrlM if (obj->get_object_id() != match.id) continue; - if (request->method() == HTTP_GET) { + if (request->method() == HTTP_GET && match.method.empty()) { std::string data = this->number_json(obj, obj->state, DETAIL_STATE); request->send(200, "application/json", data.c_str()); return; @@ -910,7 +910,7 @@ void WebServer::handle_text_request(AsyncWebServerRequest *request, const UrlMat if (obj->get_object_id() != match.id) continue; - if (request->method() == HTTP_GET) { + if (request->method() == HTTP_GET && match.method.empty()) { std::string data = this->text_json(obj, obj->state, DETAIL_STATE); request->send(200, "text/json", data.c_str()); return; @@ -961,7 +961,7 @@ void WebServer::handle_select_request(AsyncWebServerRequest *request, const UrlM if (obj->get_object_id() != match.id) continue; - if (request->method() == HTTP_GET) { + if (request->method() == HTTP_GET && match.method.empty()) { auto detail = DETAIL_STATE; auto *param = request->getParam("detail"); if (param && param->value() == "all") { @@ -1016,7 +1016,7 @@ void WebServer::handle_climate_request(AsyncWebServerRequest *request, const Url if (obj->get_object_id() != match.id) continue; - if (request->method() == HTTP_GET) { + if (request->method() == HTTP_GET && match.method.empty()) { std::string data = this->climate_json(obj, DETAIL_STATE); request->send(200, "application/json", data.c_str()); return; @@ -1162,7 +1162,7 @@ void WebServer::handle_lock_request(AsyncWebServerRequest *request, const UrlMat if (obj->get_object_id() != match.id) continue; - if (request->method() == HTTP_GET) { + if (request->method() == HTTP_GET && match.method.empty()) { std::string data = this->lock_json(obj, obj->state, DETAIL_STATE); request->send(200, "application/json", data.c_str()); } else if (match.method == "lock") { @@ -1201,7 +1201,7 @@ void WebServer::handle_alarm_control_panel_request(AsyncWebServerRequest *reques if (obj->get_object_id() != match.id) continue; - if (request->method() == HTTP_GET) { + if (request->method() == HTTP_GET && match.method.empty()) { std::string data = this->alarm_control_panel_json(obj, obj->get_state(), DETAIL_STATE); request->send(200, "application/json", data.c_str()); return; @@ -1251,7 +1251,7 @@ bool WebServer::canHandle(AsyncWebServerRequest *request) { #endif #ifdef USE_BUTTON - if (request->method() == HTTP_POST && match.domain == "button") + if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain == "button") return true; #endif From 72d1fa67fa212558696398d685f3af84fe2dc7fc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Mar 2024 17:26:10 +1300 Subject: [PATCH 1075/2101] Bump docker/login-action from 3.0.0 to 3.1.0 (#6367) 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 61f5ba4b23..0771aa0f20 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -91,12 +91,12 @@ jobs: uses: docker/setup-qemu-action@v3.0.0 - name: Log in to docker hub - uses: docker/login-action@v3.0.0 + uses: docker/login-action@v3.1.0 with: username: ${{ secrets.DOCKER_USER }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Log in to the GitHub container registry - uses: docker/login-action@v3.0.0 + uses: docker/login-action@v3.1.0 with: registry: ghcr.io username: ${{ github.actor }} @@ -167,13 +167,13 @@ jobs: - name: Log in to docker hub if: matrix.registry == 'dockerhub' - uses: docker/login-action@v3.0.0 + uses: docker/login-action@v3.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@v3.0.0 + uses: docker/login-action@v3.1.0 with: registry: ghcr.io username: ${{ github.actor }} From fa4adb61f4a29347cd585b97c591b4a490f8034f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Mar 2024 17:28:05 +1300 Subject: [PATCH 1076/2101] Bump peter-evans/create-pull-request from 6.0.1 to 6.0.2 (#6361) 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 ef3c04b595..36fce2bbcf 100644 --- a/.github/workflows/sync-device-classes.yml +++ b/.github/workflows/sync-device-classes.yml @@ -37,7 +37,7 @@ jobs: python ./script/sync-device_class.py - name: Commit changes - uses: peter-evans/create-pull-request@v6.0.1 + uses: peter-evans/create-pull-request@v6.0.2 with: commit-message: "Synchronise Device Classes from Home Assistant" committer: esphomebot From d3842a7ab49c32813185d00e4b6d8399c2b1dad7 Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Wed, 13 Mar 2024 22:08:57 -0700 Subject: [PATCH 1077/2101] fix servo restore (#6370) --- esphome/components/servo/servo.cpp | 35 +++++++++++++++++++++++++----- esphome/components/servo/servo.h | 22 +++++-------------- 2 files changed, 35 insertions(+), 22 deletions(-) diff --git a/esphome/components/servo/servo.cpp b/esphome/components/servo/servo.cpp index 666c017dea..18e8c8087e 100644 --- a/esphome/components/servo/servo.cpp +++ b/esphome/components/servo/servo.cpp @@ -19,13 +19,28 @@ void Servo::dump_config() { ESP_LOGCONFIG(TAG, " run duration: %" PRIu32 " ms", this->transition_length_); } +void Servo::setup() { + float v; + if (this->restore_) { + this->rtc_ = global_preferences->make_preference(global_servo_id); + global_servo_id++; + if (this->rtc_.load(&v)) { + this->target_value_ = v; + this->internal_write(v); + this->state_ = STATE_ATTACHED; + this->start_millis_ = millis(); + return; + } + } + this->detach(); +} + void Servo::loop() { // check if auto_detach_time_ is set and servo reached target if (this->auto_detach_time_ && this->state_ == STATE_TARGET_REACHED) { if (millis() - this->start_millis_ > this->auto_detach_time_) { this->detach(); this->start_millis_ = 0; - this->state_ = STATE_DETACHED; ESP_LOGD(TAG, "Servo detached on auto_detach_time"); } } @@ -54,8 +69,11 @@ void Servo::loop() { void Servo::write(float value) { value = clamp(value, -1.0f, 1.0f); - if (this->target_value_ == value) + if ((this->state_ == STATE_DETACHED) && (this->target_value_ == value)) { this->internal_write(value); + } else { + this->save_level_(value); + } this->target_value_ = value; this->source_value_ = this->current_value_; this->state_ = STATE_ATTACHED; @@ -72,11 +90,18 @@ void Servo::internal_write(float value) { level = lerp(value, this->idle_level_, this->max_level_); } this->output_->set_level(level); - if (this->target_value_ == this->current_value_) { - this->save_level_(level); - } this->current_value_ = value; } +void Servo::detach() { + this->state_ = STATE_DETACHED; + this->output_->set_level(0.0f); +} + +void Servo::save_level_(float v) { + if (this->restore_) + this->rtc_.save(&v); +} + } // namespace servo } // namespace esphome diff --git a/esphome/components/servo/servo.h b/esphome/components/servo/servo.h index e2e3823158..13a7472ae5 100644 --- a/esphome/components/servo/servo.h +++ b/esphome/components/servo/servo.h @@ -17,22 +17,8 @@ class Servo : public Component { void loop() override; void write(float value); void internal_write(float value); - void detach() { - this->output_->set_level(0.0f); - this->save_level_(0.0f); - } - void setup() override { - float v; - if (this->restore_) { - this->rtc_ = global_preferences->make_preference(global_servo_id); - global_servo_id++; - if (this->rtc_.load(&v)) { - this->output_->set_level(v); - return; - } - } - this->detach(); - } + void detach(); + void setup() override; void dump_config() override; float get_setup_priority() const override { return setup_priority::DATA; } void set_min_level(float min_level) { min_level_ = min_level; } @@ -42,8 +28,10 @@ class Servo : public Component { void set_auto_detach_time(uint32_t auto_detach_time) { auto_detach_time_ = auto_detach_time; } void set_transition_length(uint32_t transition_length) { transition_length_ = transition_length; } + bool has_reached_target() { return this->current_value_ == this->target_value_; } + protected: - void save_level_(float v) { this->rtc_.save(&v); } + void save_level_(float v); output::FloatOutput *output_; float min_level_ = 0.0300f; From 4e850c3f325d8083a586020a5aa64cc1fe08f006 Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Thu, 14 Mar 2024 21:26:29 +0100 Subject: [PATCH 1078/2101] Don't try to get IPv6 addresses when disabled (#6366) --- esphome/components/wifi/wifi_component_esp32_arduino.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/wifi/wifi_component_esp32_arduino.cpp b/esphome/components/wifi/wifi_component_esp32_arduino.cpp index d7241fb66c..35e6c57e62 100644 --- a/esphome/components/wifi/wifi_component_esp32_arduino.cpp +++ b/esphome/components/wifi/wifi_component_esp32_arduino.cpp @@ -157,7 +157,7 @@ network::IPAddresses WiFiComponent::wifi_sta_ip_addresses() { } else { addresses[0] = network::IPAddress(&ip.ip); } -#if LWIP_IPV6 +#if USE_NETWORK_IPV6 ip6_addr_t ipv6; err = tcpip_adapter_get_ip6_global(TCPIP_ADAPTER_IF_STA, &ipv6); if (err != ESP_OK) { @@ -171,7 +171,7 @@ network::IPAddresses WiFiComponent::wifi_sta_ip_addresses() { } else { addresses[2] = network::IPAddress(&ipv6); } -#endif /* LWIP_IPV6 */ +#endif /* USE_NETWORK_IPV6 */ return addresses; } From b7af94c76fde3f92a403755117bd8faeae9acf43 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Mar 2024 12:39:32 +1300 Subject: [PATCH 1079/2101] Bump docker/build-push-action from 5.2.0 to 5.3.0 in /.github/actions/build-image (#6373) 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 f93cf61abb..838bc362a1 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -36,7 +36,7 @@ runs: - name: Build and push to ghcr by digest id: build-ghcr - uses: docker/build-push-action@v5.2.0 + uses: docker/build-push-action@v5.3.0 with: context: . file: ./docker/Dockerfile @@ -67,7 +67,7 @@ runs: - name: Build and push to dockerhub by digest id: build-dockerhub - uses: docker/build-push-action@v5.2.0 + uses: docker/build-push-action@v5.3.0 with: context: . file: ./docker/Dockerfile From e42ab710291e50b9a1cdd81355cea086a8cd38e0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Mar 2024 12:42:38 +1300 Subject: [PATCH 1080/2101] Bump docker/setup-buildx-action from 3.1.0 to 3.2.0 (#6372) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-docker.yml | 2 +- .github/workflows/release.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-docker.yml b/.github/workflows/ci-docker.yml index 1637f69954..8a7b35fe33 100644 --- a/.github/workflows/ci-docker.yml +++ b/.github/workflows/ci-docker.yml @@ -46,7 +46,7 @@ jobs: with: python-version: "3.9" - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3.1.0 + uses: docker/setup-buildx-action@v3.2.0 - name: Set up QEMU uses: docker/setup-qemu-action@v3.0.0 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0771aa0f20..6b567b5b6f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -85,7 +85,7 @@ jobs: python-version: "3.9" - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3.1.0 + uses: docker/setup-buildx-action@v3.2.0 - name: Set up QEMU if: matrix.platform != 'linux/amd64' uses: docker/setup-qemu-action@v3.0.0 @@ -163,7 +163,7 @@ jobs: name: digests-${{ matrix.image.target }}-${{ matrix.registry }} path: /tmp/digests - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3.1.0 + uses: docker/setup-buildx-action@v3.2.0 - name: Log in to docker hub if: matrix.registry == 'dockerhub' From e33e09a6859a7bc1bd11d163e8139b1019140e9f Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Thu, 14 Mar 2024 13:42:54 +1100 Subject: [PATCH 1081/2101] SPI: Revert clk_pin to standard output pin schema (#6368) --- esphome/components/spi/__init__.py | 17 ++--------------- tests/components/spi/test.esp32-s3-idf.yaml | 3 ++- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/esphome/components/spi/__init__.py b/esphome/components/spi/__init__.py index c2335bd92a..2847c5bfa1 100644 --- a/esphome/components/spi/__init__.py +++ b/esphome/components/spi/__init__.py @@ -29,7 +29,6 @@ from esphome.const import ( PLATFORM_ESP32, PLATFORM_ESP8266, PLATFORM_RP2040, - CONF_ALLOW_OTHER_USES, CONF_DATA_PINS, ) from esphome.core import ( @@ -199,8 +198,6 @@ def get_hw_spi(config, available): def validate_spi_config(config): available = list(range(len(get_hw_interface_list()))) for spi in config: - # map pin number to schema - spi[CONF_CLK_PIN] = pins.gpio_output_pin_schema(spi[CONF_CLK_PIN]) interface = spi[CONF_INTERFACE] if interface == "software": pass @@ -257,21 +254,11 @@ def get_spi_interface(index): return "new SPIClass(HSPI)" -# Do not use a pin schema for the number, as that will trigger a pin reuse error due to duplication of the -# clock pin in the standard and quad schemas. -clk_pin_validator = cv.maybe_simple_value( - { - cv.Required(CONF_NUMBER): cv.Any(cv.int_, cv.string), - cv.Optional(CONF_ALLOW_OTHER_USES): cv.boolean, - }, - key=CONF_NUMBER, -) - SPI_SCHEMA = cv.All( cv.Schema( { cv.GenerateID(): cv.declare_id(SPIComponent), - cv.Required(CONF_CLK_PIN): clk_pin_validator, + cv.Required(CONF_CLK_PIN): pins.gpio_output_pin_schema, cv.Optional(CONF_MISO_PIN): pins.gpio_input_pin_schema, cv.Optional(CONF_MOSI_PIN): pins.gpio_output_pin_schema, cv.Optional(CONF_FORCE_SW): cv.invalid( @@ -291,7 +278,7 @@ SPI_QUAD_SCHEMA = cv.All( cv.Schema( { cv.GenerateID(): cv.declare_id(QuadSPIComponent), - cv.Required(CONF_CLK_PIN): clk_pin_validator, + cv.Required(CONF_CLK_PIN): pins.gpio_output_pin_schema, cv.Required(CONF_DATA_PINS): cv.All( cv.ensure_list(pins.internal_gpio_output_pin_number), cv.Length(min=4, max=4), diff --git a/tests/components/spi/test.esp32-s3-idf.yaml b/tests/components/spi/test.esp32-s3-idf.yaml index 3aae21cbeb..8db934023a 100644 --- a/tests/components/spi/test.esp32-s3-idf.yaml +++ b/tests/components/spi/test.esp32-s3-idf.yaml @@ -2,7 +2,8 @@ spi: - id: spi_id_1 type: single clk_pin: - number: GPIO7 + number: GPIO0 + ignore_strapping_warning: true allow_other_uses: false mosi_pin: GPIO6 interface: hardware From 76c4bfbed368850a63048c1ddfce4e631d3cef2e Mon Sep 17 00:00:00 2001 From: Attila Farago Date: Thu, 14 Mar 2024 03:56:17 +0100 Subject: [PATCH 1082/2101] Allow button press action in web_server to be executed via GET method (#5938) --- esphome/components/web_server/web_server.cpp | 24 ++++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index ba787239da..69d601ed49 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -486,7 +486,7 @@ void WebServer::handle_switch_request(AsyncWebServerRequest *request, const UrlM if (obj->get_object_id() != match.id) continue; - if (request->method() == HTTP_GET) { + if (request->method() == HTTP_GET && match.method.empty()) { std::string data = this->switch_json(obj, obj->state, DETAIL_STATE); request->send(200, "application/json", data.c_str()); } else if (match.method == "toggle") { @@ -517,7 +517,7 @@ void WebServer::handle_button_request(AsyncWebServerRequest *request, const UrlM for (button::Button *obj : App.get_buttons()) { if (obj->get_object_id() != match.id) continue; - if (request->method() == HTTP_POST && match.method == "press") { + if (match.method == "press") { this->schedule_([obj]() { obj->press(); }); request->send(200); return; @@ -572,7 +572,7 @@ void WebServer::handle_fan_request(AsyncWebServerRequest *request, const UrlMatc if (obj->get_object_id() != match.id) continue; - if (request->method() == HTTP_GET) { + if (request->method() == HTTP_GET && match.method.empty()) { std::string data = this->fan_json(obj, DETAIL_STATE); request->send(200, "application/json", data.c_str()); } else if (match.method == "toggle") { @@ -630,7 +630,7 @@ void WebServer::handle_light_request(AsyncWebServerRequest *request, const UrlMa if (obj->get_object_id() != match.id) continue; - if (request->method() == HTTP_GET) { + if (request->method() == HTTP_GET && match.method.empty()) { std::string data = this->light_json(obj, DETAIL_STATE); request->send(200, "application/json", data.c_str()); } else if (match.method == "toggle") { @@ -736,7 +736,7 @@ void WebServer::handle_cover_request(AsyncWebServerRequest *request, const UrlMa if (obj->get_object_id() != match.id) continue; - if (request->method() == HTTP_GET) { + if (request->method() == HTTP_GET && match.method.empty()) { std::string data = this->cover_json(obj, DETAIL_STATE); request->send(200, "application/json", data.c_str()); continue; @@ -805,7 +805,7 @@ void WebServer::handle_number_request(AsyncWebServerRequest *request, const UrlM if (obj->get_object_id() != match.id) continue; - if (request->method() == HTTP_GET) { + if (request->method() == HTTP_GET && match.method.empty()) { std::string data = this->number_json(obj, obj->state, DETAIL_STATE); request->send(200, "application/json", data.c_str()); return; @@ -910,7 +910,7 @@ void WebServer::handle_text_request(AsyncWebServerRequest *request, const UrlMat if (obj->get_object_id() != match.id) continue; - if (request->method() == HTTP_GET) { + if (request->method() == HTTP_GET && match.method.empty()) { std::string data = this->text_json(obj, obj->state, DETAIL_STATE); request->send(200, "text/json", data.c_str()); return; @@ -961,7 +961,7 @@ void WebServer::handle_select_request(AsyncWebServerRequest *request, const UrlM if (obj->get_object_id() != match.id) continue; - if (request->method() == HTTP_GET) { + if (request->method() == HTTP_GET && match.method.empty()) { auto detail = DETAIL_STATE; auto *param = request->getParam("detail"); if (param && param->value() == "all") { @@ -1016,7 +1016,7 @@ void WebServer::handle_climate_request(AsyncWebServerRequest *request, const Url if (obj->get_object_id() != match.id) continue; - if (request->method() == HTTP_GET) { + if (request->method() == HTTP_GET && match.method.empty()) { std::string data = this->climate_json(obj, DETAIL_STATE); request->send(200, "application/json", data.c_str()); return; @@ -1162,7 +1162,7 @@ void WebServer::handle_lock_request(AsyncWebServerRequest *request, const UrlMat if (obj->get_object_id() != match.id) continue; - if (request->method() == HTTP_GET) { + if (request->method() == HTTP_GET && match.method.empty()) { std::string data = this->lock_json(obj, obj->state, DETAIL_STATE); request->send(200, "application/json", data.c_str()); } else if (match.method == "lock") { @@ -1201,7 +1201,7 @@ void WebServer::handle_alarm_control_panel_request(AsyncWebServerRequest *reques if (obj->get_object_id() != match.id) continue; - if (request->method() == HTTP_GET) { + if (request->method() == HTTP_GET && match.method.empty()) { std::string data = this->alarm_control_panel_json(obj, obj->get_state(), DETAIL_STATE); request->send(200, "application/json", data.c_str()); return; @@ -1251,7 +1251,7 @@ bool WebServer::canHandle(AsyncWebServerRequest *request) { #endif #ifdef USE_BUTTON - if (request->method() == HTTP_POST && match.domain == "button") + if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain == "button") return true; #endif From 92fbc61c46d4229e00bb5fbc42b0f22b55126330 Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Wed, 13 Mar 2024 22:08:57 -0700 Subject: [PATCH 1083/2101] fix servo restore (#6370) --- esphome/components/servo/servo.cpp | 35 +++++++++++++++++++++++++----- esphome/components/servo/servo.h | 22 +++++-------------- 2 files changed, 35 insertions(+), 22 deletions(-) diff --git a/esphome/components/servo/servo.cpp b/esphome/components/servo/servo.cpp index 666c017dea..18e8c8087e 100644 --- a/esphome/components/servo/servo.cpp +++ b/esphome/components/servo/servo.cpp @@ -19,13 +19,28 @@ void Servo::dump_config() { ESP_LOGCONFIG(TAG, " run duration: %" PRIu32 " ms", this->transition_length_); } +void Servo::setup() { + float v; + if (this->restore_) { + this->rtc_ = global_preferences->make_preference(global_servo_id); + global_servo_id++; + if (this->rtc_.load(&v)) { + this->target_value_ = v; + this->internal_write(v); + this->state_ = STATE_ATTACHED; + this->start_millis_ = millis(); + return; + } + } + this->detach(); +} + void Servo::loop() { // check if auto_detach_time_ is set and servo reached target if (this->auto_detach_time_ && this->state_ == STATE_TARGET_REACHED) { if (millis() - this->start_millis_ > this->auto_detach_time_) { this->detach(); this->start_millis_ = 0; - this->state_ = STATE_DETACHED; ESP_LOGD(TAG, "Servo detached on auto_detach_time"); } } @@ -54,8 +69,11 @@ void Servo::loop() { void Servo::write(float value) { value = clamp(value, -1.0f, 1.0f); - if (this->target_value_ == value) + if ((this->state_ == STATE_DETACHED) && (this->target_value_ == value)) { this->internal_write(value); + } else { + this->save_level_(value); + } this->target_value_ = value; this->source_value_ = this->current_value_; this->state_ = STATE_ATTACHED; @@ -72,11 +90,18 @@ void Servo::internal_write(float value) { level = lerp(value, this->idle_level_, this->max_level_); } this->output_->set_level(level); - if (this->target_value_ == this->current_value_) { - this->save_level_(level); - } this->current_value_ = value; } +void Servo::detach() { + this->state_ = STATE_DETACHED; + this->output_->set_level(0.0f); +} + +void Servo::save_level_(float v) { + if (this->restore_) + this->rtc_.save(&v); +} + } // namespace servo } // namespace esphome diff --git a/esphome/components/servo/servo.h b/esphome/components/servo/servo.h index e2e3823158..13a7472ae5 100644 --- a/esphome/components/servo/servo.h +++ b/esphome/components/servo/servo.h @@ -17,22 +17,8 @@ class Servo : public Component { void loop() override; void write(float value); void internal_write(float value); - void detach() { - this->output_->set_level(0.0f); - this->save_level_(0.0f); - } - void setup() override { - float v; - if (this->restore_) { - this->rtc_ = global_preferences->make_preference(global_servo_id); - global_servo_id++; - if (this->rtc_.load(&v)) { - this->output_->set_level(v); - return; - } - } - this->detach(); - } + void detach(); + void setup() override; void dump_config() override; float get_setup_priority() const override { return setup_priority::DATA; } void set_min_level(float min_level) { min_level_ = min_level; } @@ -42,8 +28,10 @@ class Servo : public Component { void set_auto_detach_time(uint32_t auto_detach_time) { auto_detach_time_ = auto_detach_time; } void set_transition_length(uint32_t transition_length) { transition_length_ = transition_length; } + bool has_reached_target() { return this->current_value_ == this->target_value_; } + protected: - void save_level_(float v) { this->rtc_.save(&v); } + void save_level_(float v); output::FloatOutput *output_; float min_level_ = 0.0300f; From ca85a41a724db49582e82b31d4e4a813dd272250 Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Thu, 14 Mar 2024 21:26:29 +0100 Subject: [PATCH 1084/2101] Don't try to get IPv6 addresses when disabled (#6366) --- esphome/components/wifi/wifi_component_esp32_arduino.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/wifi/wifi_component_esp32_arduino.cpp b/esphome/components/wifi/wifi_component_esp32_arduino.cpp index d7241fb66c..35e6c57e62 100644 --- a/esphome/components/wifi/wifi_component_esp32_arduino.cpp +++ b/esphome/components/wifi/wifi_component_esp32_arduino.cpp @@ -157,7 +157,7 @@ network::IPAddresses WiFiComponent::wifi_sta_ip_addresses() { } else { addresses[0] = network::IPAddress(&ip.ip); } -#if LWIP_IPV6 +#if USE_NETWORK_IPV6 ip6_addr_t ipv6; err = tcpip_adapter_get_ip6_global(TCPIP_ADAPTER_IF_STA, &ipv6); if (err != ESP_OK) { @@ -171,7 +171,7 @@ network::IPAddresses WiFiComponent::wifi_sta_ip_addresses() { } else { addresses[2] = network::IPAddress(&ipv6); } -#endif /* LWIP_IPV6 */ +#endif /* USE_NETWORK_IPV6 */ return addresses; } From 83cc7b9d48815d7da0c606ef26450344e575386f Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 15 Mar 2024 14:23:12 +1300 Subject: [PATCH 1085/2101] Bump version to 2024.3.0b2 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index c5e86444ab..4259c82ad7 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.3.0b1" +__version__ = "2024.3.0b2" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 6e8760eba0dd1b183a38cc3105a6e9b563885e99 Mon Sep 17 00:00:00 2001 From: Federico Ferretti Date: Sat, 16 Mar 2024 02:17:01 +0100 Subject: [PATCH 1086/2101] Fix deep_sleep for ESP32-C6 (#6377) --- esphome/components/deep_sleep/deep_sleep_component.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/deep_sleep/deep_sleep_component.cpp b/esphome/components/deep_sleep/deep_sleep_component.cpp index 328e972e6b..97fdf11366 100644 --- a/esphome/components/deep_sleep/deep_sleep_component.cpp +++ b/esphome/components/deep_sleep/deep_sleep_component.cpp @@ -81,7 +81,7 @@ void DeepSleepComponent::set_wakeup_pin_mode(WakeupPinMode wakeup_pin_mode) { #endif #if defined(USE_ESP32) -#if !defined(USE_ESP32_VARIANT_ESP32C3) +#if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32C6) void DeepSleepComponent::set_ext1_wakeup(Ext1Wakeup ext1_wakeup) { this->ext1_wakeup_ = ext1_wakeup; } @@ -121,7 +121,7 @@ void DeepSleepComponent::begin_sleep(bool manual) { App.run_safe_shutdown_hooks(); #if defined(USE_ESP32) -#if !defined(USE_ESP32_VARIANT_ESP32C3) +#if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32C6) if (this->sleep_duration_.has_value()) esp_sleep_enable_timer_wakeup(*this->sleep_duration_); if (this->wakeup_pin_ != nullptr) { @@ -140,7 +140,7 @@ void DeepSleepComponent::begin_sleep(bool manual) { esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON); } #endif -#ifdef USE_ESP32_VARIANT_ESP32C3 +#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) if (this->sleep_duration_.has_value()) esp_sleep_enable_timer_wakeup(*this->sleep_duration_); if (this->wakeup_pin_ != nullptr) { From 5d96b5c52befc30e8649a929c3d6f0fd29229e72 Mon Sep 17 00:00:00 2001 From: "Federico G. Schwindt" Date: Sat, 16 Mar 2024 01:21:44 +0000 Subject: [PATCH 1087/2101] Use AQI device class (#6376) --- esphome/components/sen5x/sensor.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/esphome/components/sen5x/sensor.py b/esphome/components/sen5x/sensor.py index 4bc4a138a3..67bd627f7f 100644 --- a/esphome/components/sen5x/sensor.py +++ b/esphome/components/sen5x/sensor.py @@ -14,13 +14,12 @@ from esphome.const import ( CONF_PM_4_0, CONF_STORE_BASELINE, CONF_TEMPERATURE, + DEVICE_CLASS_AQI, DEVICE_CLASS_HUMIDITY, - DEVICE_CLASS_NITROUS_OXIDE, DEVICE_CLASS_PM1, DEVICE_CLASS_PM10, DEVICE_CLASS_PM25, DEVICE_CLASS_TEMPERATURE, - DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS, ICON_CHEMICAL_WEAPON, ICON_RADIATOR, ICON_THERMOMETER, @@ -132,13 +131,13 @@ CONFIG_SCHEMA = ( cv.Optional(CONF_VOC): sensor.sensor_schema( icon=ICON_RADIATOR, accuracy_decimals=0, - device_class=DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS, + device_class=DEVICE_CLASS_AQI, state_class=STATE_CLASS_MEASUREMENT, ).extend(GAS_SENSOR), cv.Optional(CONF_NOX): sensor.sensor_schema( icon=ICON_RADIATOR, accuracy_decimals=0, - device_class=DEVICE_CLASS_NITROUS_OXIDE, + device_class=DEVICE_CLASS_AQI, state_class=STATE_CLASS_MEASUREMENT, ).extend(GAS_SENSOR), cv.Optional(CONF_STORE_BASELINE, default=True): cv.boolean, From 1148d41a66f37dcb3b37bb10feb9ba8d52348824 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Sat, 16 Mar 2024 14:22:34 +1300 Subject: [PATCH 1088/2101] Fix list-components when PR is not targeting dev (#6375) --- .github/workflows/ci.yml | 15 ++++++++++----- script/helpers.py | 4 ++-- script/list-components.py | 11 ++++++++++- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c3de879176..47709739dc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -398,6 +398,7 @@ jobs: runs-on: ubuntu-latest needs: - common + if: github.event_name == 'pull_request' outputs: matrix: ${{ steps.set-matrix.outputs.matrix }} steps: @@ -406,10 +407,14 @@ jobs: with: # Fetch enough history so `git merge-base refs/remotes/origin/dev HEAD` works. fetch-depth: 500 - - name: Fetch dev branch + - name: Get target branch + id: target-branch run: | - git -c protocol.version=2 fetch --no-tags --prune --no-recurse-submodules --depth=1 origin +refs/heads/dev*:refs/remotes/origin/dev* +refs/tags/dev*:refs/tags/dev* - git merge-base refs/remotes/origin/dev HEAD + echo "branch=${{ github.event.pull_request.base.ref }}" >> $GITHUB_OUTPUT + - name: Fetch ${{ steps.target-branch.outputs.branch }} branch + run: | + git -c protocol.version=2 fetch --no-tags --prune --no-recurse-submodules --depth=1 origin +refs/heads/${{ steps.target-branch.outputs.branch }}:refs/remotes/origin/${{ steps.target-branch.outputs.branch }} + git merge-base refs/remotes/origin/${{ steps.target-branch.outputs.branch }} HEAD - name: Restore Python uses: ./.github/actions/restore-python with: @@ -419,7 +424,7 @@ jobs: id: set-matrix run: | . venv/bin/activate - echo "matrix=$(script/list-components.py --changed | jq -R -s -c 'split("\n")[:-1]')" >> $GITHUB_OUTPUT + echo "matrix=$(script/list-components.py --changed --branch ${{ steps.target-branch.outputs.branch }} | jq -R -s -c 'split("\n")[:-1]')" >> $GITHUB_OUTPUT test-build-components: name: Component test ${{ matrix.file }} @@ -427,7 +432,7 @@ jobs: needs: - common - list-components - if: ${{ needs.list-components.outputs.matrix != '[]' && needs.list-components.outputs.matrix != '' }} + if: ${{ github.event_name == 'pull_request' && needs.list-components.outputs.matrix != '[]' && needs.list-components.outputs.matrix != '' }} strategy: fail-fast: false max-parallel: 2 diff --git a/script/helpers.py b/script/helpers.py index a971fdf475..52b0658fb6 100644 --- a/script/helpers.py +++ b/script/helpers.py @@ -70,11 +70,11 @@ def splitlines_no_ends(string): return [s.strip() for s in string.splitlines()] -def changed_files(): +def changed_files(branch="dev"): check_remotes = ["upstream", "origin"] check_remotes.extend(splitlines_no_ends(get_output("git", "remote"))) for remote in check_remotes: - command = ["git", "merge-base", f"refs/remotes/{remote}/dev", "HEAD"] + command = ["git", "merge-base", f"refs/remotes/{remote}/{branch}", "HEAD"] try: merge_base = splitlines_no_ends(get_output(*command))[0] break diff --git a/script/list-components.py b/script/list-components.py index 3e55c0e5f7..8e2d47c6b3 100755 --- a/script/list-components.py +++ b/script/list-components.py @@ -120,13 +120,22 @@ def main(): parser.add_argument( "-c", "--changed", action="store_true", help="Only run on changed files" ) + parser.add_argument( + "-b", "--branch", help="Branch to compare changed files against" + ) args = parser.parse_args() + if args.branch and not args.changed: + parser.error("--branch requires --changed") + files = git_ls_files() files = filter(filter_component_files, files) if args.changed: - changed = changed_files() + if args.branch: + changed = changed_files(args.branch) + else: + changed = changed_files() files = [f for f in files if f in changed] components = extract_component_names_array_from_files_array(files) From 4f59b14ab09f1581cb15b475f6d4f47d3a5fa93b Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Sat, 16 Mar 2024 00:18:51 -0500 Subject: [PATCH 1089/2101] Fix keeloq for IDF 5+ (#6382) --- esphome/components/remote_base/keeloq_protocol.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/esphome/components/remote_base/keeloq_protocol.cpp b/esphome/components/remote_base/keeloq_protocol.cpp index 77a2f9be6c..09d9ea4f53 100644 --- a/esphome/components/remote_base/keeloq_protocol.cpp +++ b/esphome/components/remote_base/keeloq_protocol.cpp @@ -1,6 +1,8 @@ #include "keeloq_protocol.h" #include "esphome/core/log.h" +#include + namespace esphome { namespace remote_base { @@ -34,7 +36,8 @@ transmitter and nutton command is decoded. void KeeloqProtocol::encode(RemoteTransmitData *dst, const KeeloqData &data) { uint32_t out_data = 0x0; - ESP_LOGD(TAG, "Send Keeloq: address=%07x command=%03x encrypted=%08x", data.address, data.command, data.encrypted); + ESP_LOGD(TAG, "Send Keeloq: address=%07" PRIx32 " command=%03x encrypted=%08" PRIx32, data.address, data.command, + data.encrypted); ESP_LOGV(TAG, "Send Keeloq: data bits (%d + %d)", NBITS_ENCRYPTED_DATA, NBITS_FIXED_DATA); // Preamble = '01' x 12 @@ -181,7 +184,7 @@ optional KeeloqProtocol::decode(RemoteReceiveData src) { } void KeeloqProtocol::dump(const KeeloqData &data) { - ESP_LOGD(TAG, "Received Keeloq: address=0x%08X, command=0x%02x", data.address, data.command); + ESP_LOGD(TAG, "Received Keeloq: address=0x%08" PRIx32 ", command=0x%02x", data.address, data.command); } } // namespace remote_base From e753ac3a97aa0d51695a880137f7d4078d57f088 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Sat, 16 Mar 2024 06:19:25 +0100 Subject: [PATCH 1090/2101] Fix Nextion set_component_picture call (#6378) This fixes the call to the Nextion display to change the pic id from a component. It was previously changing the attribute `val`, which is related to something else. In addition, I've changed the parameter for picture_id to be uint_8, as Nextion requires an integer from 0 to 255 on this attribute. --- esphome/components/nextion/nextion.h | 6 +++--- esphome/components/nextion/nextion_commands.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/esphome/components/nextion/nextion.h b/esphome/components/nextion/nextion.h index eef2c61638..f9f01de72c 100644 --- a/esphome/components/nextion/nextion.h +++ b/esphome/components/nextion/nextion.h @@ -82,16 +82,16 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe /** * Set the picture of an image component. * @param component The component name. - * @param value The picture name. + * @param value The picture id. * * Example: * ```cpp - * it.set_component_picture("pic", "4"); + * it.set_component_picture("pic", 4); * ``` * * This will change the image of the component `pic` to the image with ID `4`. */ - void set_component_picture(const char *component, const char *picture); + void set_component_picture(const char *component, uint8_t picture_id); /** * Set the background color of a component. * @param component The component name. diff --git a/esphome/components/nextion/nextion_commands.cpp b/esphome/components/nextion/nextion_commands.cpp index c4849d6050..e378111376 100644 --- a/esphome/components/nextion/nextion_commands.cpp +++ b/esphome/components/nextion/nextion_commands.cpp @@ -197,8 +197,8 @@ void Nextion::disable_component_touch(const char *component) { this->add_no_result_to_queue_with_printf_("disable_component_touch", "tsw %s,0", component); } -void Nextion::set_component_picture(const char *component, const char *picture) { - this->add_no_result_to_queue_with_printf_("set_component_picture", "%s.val=%s", component, picture); +void Nextion::set_component_picture(const char *component, uint8_t picture_id) { + this->add_no_result_to_queue_with_printf_("set_component_picture", "%s.pic=%d", component, picture_id); } void Nextion::set_component_text(const char *component, const char *text) { From 23f8498ff972b0c67d0cd4f708e728c11d5a0630 Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Sun, 17 Mar 2024 12:10:47 -0700 Subject: [PATCH 1091/2101] allow negative ppm for sensair (#6385) --- esphome/components/senseair/senseair.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/senseair/senseair.cpp b/esphome/components/senseair/senseair.cpp index e0504eb2b9..e58ee157f7 100644 --- a/esphome/components/senseair/senseair.cpp +++ b/esphome/components/senseair/senseair.cpp @@ -54,9 +54,9 @@ void SenseAirComponent::update() { this->status_clear_warning(); const uint8_t length = response[2]; const uint16_t status = (uint16_t(response[3]) << 8) | response[4]; - const uint16_t ppm = (uint16_t(response[length + 1]) << 8) | response[length + 2]; + const int16_t ppm = int16_t((response[length + 1] << 8) | response[length + 2]); - ESP_LOGD(TAG, "SenseAir Received CO₂=%uppm Status=0x%02X", ppm, status); + ESP_LOGD(TAG, "SenseAir Received CO₂=%dppm Status=0x%02X", ppm, status); if (this->co2_sensor_ != nullptr) this->co2_sensor_->publish_state(ppm); } From 9f121e6016921591d26d08dbe5340d6e5e3766be Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt Date: Sun, 17 Mar 2024 15:13:55 -0400 Subject: [PATCH 1092/2101] microWakeWord - add new ops and small improvements (#6360) --- .../micro_wake_word/micro_wake_word.cpp | 66 ++++++++----------- .../micro_wake_word/micro_wake_word.h | 3 +- 2 files changed, 27 insertions(+), 42 deletions(-) diff --git a/esphome/components/micro_wake_word/micro_wake_word.cpp b/esphome/components/micro_wake_word/micro_wake_word.cpp index 7321e5b05b..f637f8b2bb 100644 --- a/esphome/components/micro_wake_word/micro_wake_word.cpp +++ b/esphome/components/micro_wake_word/micro_wake_word.cpp @@ -93,11 +93,18 @@ int MicroWakeWord::read_microphone_() { return 0; } - size_t bytes_written = this->ring_buffer_->write((void *) this->input_buffer_, bytes_read); - if (bytes_written != bytes_read) { - ESP_LOGW(TAG, "Failed to write some data to ring buffer (written=%d, expected=%d)", bytes_written, bytes_read); + size_t bytes_free = this->ring_buffer_->free(); + + if (bytes_free < bytes_read) { + ESP_LOGW(TAG, + "Not enough free bytes in ring buffer to store incoming audio data (free bytes=%d, incoming bytes=%d). " + "Resetting the ring buffer. Wake word detection accuracy will be reduced.", + bytes_free, bytes_read); + + this->ring_buffer_->reset(); } - return bytes_written; + + return this->ring_buffer_->write((void *) this->input_buffer_, bytes_read); } void MicroWakeWord::loop() { @@ -206,12 +213,6 @@ bool MicroWakeWord::initialize_models() { return false; } - this->preprocessor_stride_buffer_ = audio_samples_allocator.allocate(HISTORY_SAMPLES_TO_KEEP); - if (this->preprocessor_stride_buffer_ == nullptr) { - ESP_LOGE(TAG, "Could not allocate the audio preprocessor's stride buffer."); - return false; - } - this->preprocessor_model_ = tflite::GetModel(G_AUDIO_PREPROCESSOR_INT8_TFLITE); if (this->preprocessor_model_->version() != TFLITE_SCHEMA_VERSION) { ESP_LOGE(TAG, "Wake word's audio preprocessor model's schema is not supported"); @@ -225,7 +226,7 @@ bool MicroWakeWord::initialize_models() { } static tflite::MicroMutableOpResolver<18> preprocessor_op_resolver; - static tflite::MicroMutableOpResolver<14> streaming_op_resolver; + static tflite::MicroMutableOpResolver<17> streaming_op_resolver; if (!this->register_preprocessor_ops_(preprocessor_op_resolver)) return false; @@ -329,7 +330,6 @@ bool MicroWakeWord::detect_wake_word_() { } // Perform inference - uint32_t streaming_size = micros(); float streaming_prob = this->perform_streaming_inference_(); // Add the most recent probability to the sliding window @@ -357,6 +357,9 @@ bool MicroWakeWord::detect_wake_word_() { for (auto &prob : this->recent_streaming_probabilities_) { prob = 0; } + + ESP_LOGD(TAG, "Wake word sliding average probability is %.3f and most recent probability is %.3f", + sliding_window_average, streaming_prob); return true; } @@ -371,23 +374,6 @@ void MicroWakeWord::set_sliding_window_average_size(size_t size) { bool MicroWakeWord::slice_available_() { size_t available = this->ring_buffer_->available(); - size_t free = this->ring_buffer_->free(); - - if (free < NEW_SAMPLES_TO_GET * sizeof(int16_t)) { - // If the ring buffer is within one audio slice of being full, then wake word detection will have issues. - // If this is constantly occuring, then some possibilities why are - // 1) there are too many other slow components configured - // 2) the ESP32 isn't fast enough; e.g., an ESP32 is much slower than an ESP32-S3 at inferences. - // 3) the model is too large - // 4) the model uses operations that are not optimized - ESP_LOGW(TAG, - "Audio buffer is nearly full. Wake word detection may be less accurate and have slower reponse times. " -#if !defined(USE_ESP32_VARIANT_ESP32S3) - "microWakeWord is designed for the ESP32-S3. The current platform is too slow for this model." -#endif - ); - } - return available > (NEW_SAMPLES_TO_GET * sizeof(int16_t)); } @@ -396,13 +382,12 @@ bool MicroWakeWord::stride_audio_samples_(int16_t **audio_samples) { return false; } - // Copy 320 bytes (160 samples over 10 ms) into preprocessor_audio_buffer_ from history in - // preprocessor_stride_buffer_ - memcpy((void *) (this->preprocessor_audio_buffer_), (void *) (this->preprocessor_stride_buffer_), + // Copy the last 320 bytes (160 samples over 10 ms) from the audio buffer to the start of the audio buffer + memcpy((void *) (this->preprocessor_audio_buffer_), (void *) (this->preprocessor_audio_buffer_ + NEW_SAMPLES_TO_GET), HISTORY_SAMPLES_TO_KEEP * sizeof(int16_t)); - // Copy 640 bytes (320 samples over 20 ms) from the ring buffer - // The first 320 bytes (160 samples over 10 ms) will be from history + // Copy 640 bytes (320 samples over 20 ms) from the ring buffer into the audio buffer offset 320 bytes (160 samples + // over 10 ms) size_t bytes_read = this->ring_buffer_->read((void *) (this->preprocessor_audio_buffer_ + HISTORY_SAMPLES_TO_KEEP), NEW_SAMPLES_TO_GET * sizeof(int16_t), pdMS_TO_TICKS(200)); @@ -415,11 +400,6 @@ bool MicroWakeWord::stride_audio_samples_(int16_t **audio_samples) { return false; } - // Copy the last 320 bytes (160 samples over 10 ms) from the audio buffer into history stride buffer for the next - // iteration - memcpy((void *) (this->preprocessor_stride_buffer_), (void *) (this->preprocessor_audio_buffer_ + NEW_SAMPLES_TO_GET), - HISTORY_SAMPLES_TO_KEEP * sizeof(int16_t)); - *audio_samples = this->preprocessor_audio_buffer_; return true; } @@ -480,7 +460,7 @@ bool MicroWakeWord::register_preprocessor_ops_(tflite::MicroMutableOpResolver<18 return true; } -bool MicroWakeWord::register_streaming_ops_(tflite::MicroMutableOpResolver<14> &op_resolver) { +bool MicroWakeWord::register_streaming_ops_(tflite::MicroMutableOpResolver<17> &op_resolver) { if (op_resolver.AddCallOnce() != kTfLiteOk) return false; if (op_resolver.AddVarHandle() != kTfLiteOk) @@ -509,6 +489,12 @@ bool MicroWakeWord::register_streaming_ops_(tflite::MicroMutableOpResolver<14> & return false; if (op_resolver.AddQuantize() != kTfLiteOk) return false; + if (op_resolver.AddDepthwiseConv2D() != kTfLiteOk) + return false; + if (op_resolver.AddAveragePool2D() != kTfLiteOk) + return false; + if (op_resolver.AddMaxPool2D() != kTfLiteOk) + return false; return true; } diff --git a/esphome/components/micro_wake_word/micro_wake_word.h b/esphome/components/micro_wake_word/micro_wake_word.h index 27d05c3e09..1d7c18d686 100644 --- a/esphome/components/micro_wake_word/micro_wake_word.h +++ b/esphome/components/micro_wake_word/micro_wake_word.h @@ -128,7 +128,6 @@ class MicroWakeWord : public Component { // Stores audio fed into feature generator preprocessor int16_t *preprocessor_audio_buffer_; - int16_t *preprocessor_stride_buffer_; bool detected_{false}; @@ -181,7 +180,7 @@ class MicroWakeWord : public Component { bool register_preprocessor_ops_(tflite::MicroMutableOpResolver<18> &op_resolver); /// @brief Returns true if successfully registered the streaming model's TensorFlow operations - bool register_streaming_ops_(tflite::MicroMutableOpResolver<14> &op_resolver); + bool register_streaming_ops_(tflite::MicroMutableOpResolver<17> &op_resolver); }; template class StartAction : public Action, public Parented { From c24946e09ff964d76ae44011638ef2c35280f525 Mon Sep 17 00:00:00 2001 From: Stefan Rado <628587+kroimon@users.noreply.github.com> Date: Sun, 17 Mar 2024 22:00:07 +0100 Subject: [PATCH 1093/2101] Fix compilation for uponor_smatrix without time component (#6389) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/uponor_smatrix/uponor_smatrix.cpp | 2 ++ esphome/components/uponor_smatrix/uponor_smatrix.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/esphome/components/uponor_smatrix/uponor_smatrix.cpp b/esphome/components/uponor_smatrix/uponor_smatrix.cpp index 10cd787c7f..df81691fb1 100644 --- a/esphome/components/uponor_smatrix/uponor_smatrix.cpp +++ b/esphome/components/uponor_smatrix/uponor_smatrix.cpp @@ -61,9 +61,11 @@ void UponorSmatrixComponent::loop() { // Send packets during bus silence if ((now - this->last_rx_ > 300) && (now - this->last_poll_start_ < 9500) && (now - this->last_tx_ > 200)) { +#ifdef USE_TIME // Only build time packet when bus is silent and queue is empty to make sure we can send it right away if (this->send_time_requested_ && this->tx_queue_.empty() && this->do_send_time_()) this->send_time_requested_ = false; +#endif // Send the next packet in the queue if (!this->tx_queue_.empty()) { auto packet = std::move(this->tx_queue_.front()); diff --git a/esphome/components/uponor_smatrix/uponor_smatrix.h b/esphome/components/uponor_smatrix/uponor_smatrix.h index b6675199b5..b7667b5b87 100644 --- a/esphome/components/uponor_smatrix/uponor_smatrix.h +++ b/esphome/components/uponor_smatrix/uponor_smatrix.h @@ -4,6 +4,8 @@ #include "esphome/core/component.h" #include "esphome/core/helpers.h" +#include "esphome/core/defines.h" + #ifdef USE_TIME #include "esphome/components/time/real_time_clock.h" #include "esphome/core/time.h" From 0b9a022ef6c430671ec6d906968634c4af8343fb Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Sun, 17 Mar 2024 22:01:25 +0100 Subject: [PATCH 1094/2101] Shows component operation time in `ms` (#6388) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/core/component.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index b0406e6502..d737ec0ae3 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -5,6 +5,7 @@ #include "esphome/core/helpers.h" #include "esphome/core/log.h" #include +#include namespace esphome { @@ -211,8 +212,8 @@ WarnIfComponentBlockingGuard::~WarnIfComponentBlockingGuard() { uint32_t now = millis(); if (now - started_ > 50) { const char *src = component_ == nullptr ? "" : component_->get_component_source(); - ESP_LOGW(TAG, "Component %s took a long time for an operation (%.2f s).", src, (now - started_) / 1e3f); - ESP_LOGW(TAG, "Components should block for at most 20-30ms."); + ESP_LOGW(TAG, "Component %s took a long time for an operation (%" PRIu32 " ms).", src, (now - started_)); + ESP_LOGW(TAG, "Components should block for at most 30 ms."); ; } } From 72c6563a3b4fafffa08f82765e3b8853bc88ccc9 Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Sun, 17 Mar 2024 22:06:02 +0100 Subject: [PATCH 1095/2101] IPv6 can't be enabled for libretiny (#6387) --- esphome/components/network/__init__.py | 38 ++++++++++++++++---------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/esphome/components/network/__init__.py b/esphome/components/network/__init__.py index 4e87ff1c12..36144ff0a4 100644 --- a/esphome/components/network/__init__.py +++ b/esphome/components/network/__init__.py @@ -6,6 +6,9 @@ from esphome.components.esp32 import add_idf_sdkconfig_option from esphome.const import ( CONF_ENABLE_IPV6, CONF_MIN_IPV6_ADDR_COUNT, + PLATFORM_ESP32, + PLATFORM_ESP8266, + PLATFORM_RP2040, ) CODEOWNERS = ["@esphome/core"] @@ -16,25 +19,30 @@ IPAddress = network_ns.class_("IPAddress") CONFIG_SCHEMA = cv.Schema( { - cv.Optional(CONF_ENABLE_IPV6, default=False): cv.boolean, + cv.SplitDefault(CONF_ENABLE_IPV6): cv.All( + cv.boolean, cv.only_on([PLATFORM_ESP32, PLATFORM_ESP8266, PLATFORM_RP2040]) + ), cv.Optional(CONF_MIN_IPV6_ADDR_COUNT, default=0): cv.positive_int, } ) async def to_code(config): - cg.add_define("USE_NETWORK_IPV6", config[CONF_ENABLE_IPV6]) - cg.add_define("USE_NETWORK_MIN_IPV6_ADDR_COUNT", config[CONF_MIN_IPV6_ADDR_COUNT]) - if CORE.using_esp_idf: - add_idf_sdkconfig_option("CONFIG_LWIP_IPV6", config[CONF_ENABLE_IPV6]) - add_idf_sdkconfig_option( - "CONFIG_LWIP_IPV6_AUTOCONFIG", config[CONF_ENABLE_IPV6] + if CONF_ENABLE_IPV6 in config: + cg.add_define("USE_NETWORK_IPV6", config[CONF_ENABLE_IPV6]) + cg.add_define( + "USE_NETWORK_MIN_IPV6_ADDR_COUNT", config[CONF_MIN_IPV6_ADDR_COUNT] ) - else: - if config[CONF_ENABLE_IPV6]: - cg.add_build_flag("-DCONFIG_LWIP_IPV6") - cg.add_build_flag("-DCONFIG_LWIP_IPV6_AUTOCONFIG") - if CORE.is_rp2040: - cg.add_build_flag("-DPIO_FRAMEWORK_ARDUINO_ENABLE_IPV6") - if CORE.is_esp8266: - cg.add_build_flag("-DPIO_FRAMEWORK_ARDUINO_LWIP2_IPV6_LOW_MEMORY") + if CORE.using_esp_idf: + add_idf_sdkconfig_option("CONFIG_LWIP_IPV6", config[CONF_ENABLE_IPV6]) + add_idf_sdkconfig_option( + "CONFIG_LWIP_IPV6_AUTOCONFIG", config[CONF_ENABLE_IPV6] + ) + else: + if config[CONF_ENABLE_IPV6]: + cg.add_build_flag("-DCONFIG_LWIP_IPV6") + cg.add_build_flag("-DCONFIG_LWIP_IPV6_AUTOCONFIG") + if CORE.is_rp2040: + cg.add_build_flag("-DPIO_FRAMEWORK_ARDUINO_ENABLE_IPV6") + if CORE.is_esp8266: + cg.add_build_flag("-DPIO_FRAMEWORK_ARDUINO_LWIP2_IPV6_LOW_MEMORY") From 8fd10d6859ca3013c72820a64f3853a2fed89622 Mon Sep 17 00:00:00 2001 From: Daniel Eisterhold Date: Sun, 17 Mar 2024 18:51:46 -0500 Subject: [PATCH 1096/2101] Add line_at_angle method to Display component (#6381) --- esphome/components/display/display.cpp | 15 ++++++++++ esphome/components/display/display.h | 7 +++++ tests/components/display/test.esp32.yaml | 35 ++++++++++++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 tests/components/display/test.esp32.yaml diff --git a/esphome/components/display/display.cpp b/esphome/components/display/display.cpp index 8ae1ee46aa..010e6eca0b 100644 --- a/esphome/components/display/display.cpp +++ b/esphome/components/display/display.cpp @@ -36,6 +36,21 @@ void HOT Display::line(int x1, int y1, int x2, int y2, Color color) { } } +void Display::line_at_angle(int x, int y, int angle, int length, Color color) { + this->line_at_angle(x, y, angle, 0, length, color); +} + +void Display::line_at_angle(int x, int y, int angle, int start_radius, int stop_radius, Color color) { + // Calculate start and end points + int x1 = (start_radius * cos(angle * M_PI / 180)) + x; + int y1 = (start_radius * sin(angle * M_PI / 180)) + y; + int x2 = (stop_radius * cos(angle * M_PI / 180)) + x; + int y2 = (stop_radius * sin(angle * M_PI / 180)) + y; + + // Draw line + this->line(x1, y1, x2, y2, color); +} + void Display::draw_pixels_at(int x_start, int y_start, int w, int h, const uint8_t *ptr, ColorOrder order, ColorBitness bitness, bool big_endian, int x_offset, int y_offset, int x_pad) { size_t line_stride = x_offset + w + x_pad; // length of each source line in pixels diff --git a/esphome/components/display/display.h b/esphome/components/display/display.h index 21954ebb71..a30ba976b4 100644 --- a/esphome/components/display/display.h +++ b/esphome/components/display/display.h @@ -258,6 +258,13 @@ class Display : public PollingComponent { /// Draw a straight line from the point [x1,y1] to [x2,y2] with the given color. void line(int x1, int y1, int x2, int y2, Color color = COLOR_ON); + /// Draw a straight line at the given angle based on the origin [x, y] for a specified length with the given color. + void line_at_angle(int x, int y, int angle, int length, Color color = COLOR_ON); + + /// Draw a straight line at the given angle based on the origin [x, y] from a specified start and stop radius with the + /// given color. + void line_at_angle(int x, int y, int angle, int start_radius, int stop_radius, Color color = COLOR_ON); + /// Draw a horizontal line from the point [x,y] to [x+width,y] with the given color. void horizontal_line(int x, int y, int width, Color color = COLOR_ON); diff --git a/tests/components/display/test.esp32.yaml b/tests/components/display/test.esp32.yaml new file mode 100644 index 0000000000..a22aa76780 --- /dev/null +++ b/tests/components/display/test.esp32.yaml @@ -0,0 +1,35 @@ +spi: + - id: spi_main_lcd + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +display: + - platform: ili9xxx + id: main_lcd + model: ili9342 + cs_pin: 12 + dc_pin: 13 + reset_pin: 21 + lambda: |- + // Draw an analog clock in the center of the screen + int centerX = it.get_width() / 2; + int centerY = it.get_height() / 2; + int radius = min(it.get_width(), it.get_height()) / 4; + + // Draw border + it.circle(centerX, centerY, radius); + + // Draw hour ticks + for(int h = 0; h < 12; h++) { + int hourAngle = (h * 30) - 90; + + it.line_at_angle(centerX, centerY, hourAngle, radius - 10, radius); + } + + // Draw minute ticks + for(int m = 0; m < 60; m++) { + int minuteAngle = (m * 6) - 90; + + it.line_at_angle(centerX, centerY, minuteAngle, radius - 5, radius); + } From 687553a285fc13d4b17a75a84050e5c0e6ba2cb1 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 18 Mar 2024 13:00:59 +1300 Subject: [PATCH 1097/2101] Replace name and friendly name in full adopted configs (#4456) --- .../components/dashboard_import/__init__.py | 130 +++++++++--------- esphome/dashboard/web_server.py | 3 +- requirements.txt | 1 + 3 files changed, 68 insertions(+), 66 deletions(-) diff --git a/esphome/components/dashboard_import/__init__.py b/esphome/components/dashboard_import/__init__.py index e0994be6a0..b1b22b816b 100644 --- a/esphome/components/dashboard_import/__init__.py +++ b/esphome/components/dashboard_import/__init__.py @@ -2,8 +2,10 @@ import base64 import secrets from pathlib import Path from typing import Optional +import re import requests +from ruamel.yaml import YAML import esphome.codegen as cg import esphome.config_validation as cv @@ -11,7 +13,6 @@ import esphome.final_validate as fv from esphome import git from esphome.components.packages import validate_source_shorthand from esphome.const import CONF_REF, CONF_WIFI, CONF_ESPHOME, CONF_PROJECT -from esphome.wizard import wizard_file from esphome.yaml_util import dump dashboard_import_ns = cg.esphome_ns.namespace("dashboard_import") @@ -94,75 +95,74 @@ def import_config( if p.exists(): raise FileExistsError - if project_name == "esphome.web": - if "esp32c3" in import_url: - board = "esp32-c3-devkitm-1" - platform = "ESP32" - elif "esp32s2" in import_url: - board = "esp32-s2-saola-1" - platform = "ESP32" - elif "esp32s3" in import_url: - board = "esp32-s3-devkitc-1" - platform = "ESP32" - elif "esp32" in import_url: - board = "esp32dev" - platform = "ESP32" - elif "esp8266" in import_url: - board = "esp01_1m" - platform = "ESP8266" - elif "pico-w" in import_url: - board = "pico-w" - platform = "RP2040" + git_file = git.GitFile.from_shorthand(import_url) - kwargs = { - "name": name, - "friendly_name": friendly_name, - "platform": platform, - "board": board, - "ssid": "!secret wifi_ssid", - "psk": "!secret wifi_password", + if git_file.query and "full_config" in git_file.query: + url = git_file.raw_url + try: + req = requests.get(url, timeout=30) + req.raise_for_status() + except requests.exceptions.RequestException as e: + raise ValueError(f"Error while fetching {url}: {e}") from e + + contents = req.text + yaml = YAML() + loaded_yaml = yaml.load(contents) + if ( + "name_add_mac_suffix" in loaded_yaml["esphome"] + and loaded_yaml["esphome"]["name_add_mac_suffix"] + ): + loaded_yaml["esphome"]["name_add_mac_suffix"] = False + name_val = loaded_yaml["esphome"]["name"] + sub_pattern = re.compile(r"\$\{?([a-zA-Z-_]+)\}?") + if match := sub_pattern.match(name_val): + name_sub = match.group(1) + if name_sub in loaded_yaml["substitutions"]: + loaded_yaml["substitutions"][name_sub] = name + else: + raise ValueError( + f"Name substitution {name_sub} not found in substitutions" + ) + else: + loaded_yaml["esphome"]["name"] = name + if friendly_name is not None: + friendly_name_val = loaded_yaml["esphome"]["friendly_name"] + if match := sub_pattern.match(friendly_name_val): + friendly_name_sub = match.group(1) + if friendly_name_sub in loaded_yaml["substitutions"]: + loaded_yaml["substitutions"][friendly_name_sub] = friendly_name + else: + raise ValueError( + f"Friendly name substitution {friendly_name_sub} not found in substitutions" + ) + else: + loaded_yaml["esphome"]["friendly_name"] = friendly_name + + with p.open("w", encoding="utf8") as f: + yaml.dump(loaded_yaml, f) + else: + with p.open("w", encoding="utf8") as f: + f.write(contents) + + else: + substitutions = {"name": name} + esphome_core = {"name": "${name}", "name_add_mac_suffix": False} + if friendly_name: + substitutions["friendly_name"] = friendly_name + esphome_core["friendly_name"] = "${friendly_name}" + config = { + "substitutions": substitutions, + "packages": {project_name: import_url}, + "esphome": esphome_core, } if encryption: noise_psk = secrets.token_bytes(32) key = base64.b64encode(noise_psk).decode() - kwargs["api_encryption_key"] = key + config["api"] = {"encryption": {"key": key}} - p.write_text( - wizard_file(**kwargs), - encoding="utf8", - ) - else: - git_file = git.GitFile.from_shorthand(import_url) + output = dump(config) - if git_file.query and "full_config" in git_file.query: - url = git_file.raw_url - try: - req = requests.get(url, timeout=30) - req.raise_for_status() - except requests.exceptions.RequestException as e: - raise ValueError(f"Error while fetching {url}: {e}") from e + if network == CONF_WIFI: + output += WIFI_CONFIG - p.write_text(req.text, encoding="utf8") - - else: - substitutions = {"name": name} - esphome_core = {"name": "${name}", "name_add_mac_suffix": False} - if friendly_name: - substitutions["friendly_name"] = friendly_name - esphome_core["friendly_name"] = "${friendly_name}" - config = { - "substitutions": substitutions, - "packages": {project_name: import_url}, - "esphome": esphome_core, - } - if encryption: - noise_psk = secrets.token_bytes(32) - key = base64.b64encode(noise_psk).decode() - config["api"] = {"encryption": {"key": key}} - - output = dump(config) - - if network == CONF_WIFI: - output += WIFI_CONFIG - - p.write_text(output, encoding="utf8") + p.write_text(output, encoding="utf8") diff --git a/esphome/dashboard/web_server.py b/esphome/dashboard/web_server.py index de3fe6e8ae..3de1d69115 100644 --- a/esphome/dashboard/web_server.py +++ b/esphome/dashboard/web_server.py @@ -516,7 +516,8 @@ class ImportRequestHandler(BaseHandler): self.set_status(500) self.write("File already exists") return - except ValueError: + except ValueError as e: + _LOGGER.error(e) self.set_status(422) self.write("Invalid package url") return diff --git a/requirements.txt b/requirements.txt index 32955bf6e7..9b5e06fc59 100644 --- a/requirements.txt +++ b/requirements.txt @@ -16,6 +16,7 @@ esphome-dashboard==20231107.0 aioesphomeapi==23.1.1 zeroconf==0.131.0 python-magic==0.4.27 +ruamel.yaml==0.18.6 # dashboard_import # esp-idf requires this, but doesn't bundle it by default # https://github.com/espressif/esp-idf/blob/220590d599e134d7a5e7f1e683cc4550349ffbf8/requirements.txt#L24 From a5553827f1262742abb9921f68d849c321e57d43 Mon Sep 17 00:00:00 2001 From: "Federico G. Schwindt" Date: Sat, 16 Mar 2024 01:21:44 +0000 Subject: [PATCH 1098/2101] Use AQI device class (#6376) --- esphome/components/sen5x/sensor.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/esphome/components/sen5x/sensor.py b/esphome/components/sen5x/sensor.py index 4bc4a138a3..67bd627f7f 100644 --- a/esphome/components/sen5x/sensor.py +++ b/esphome/components/sen5x/sensor.py @@ -14,13 +14,12 @@ from esphome.const import ( CONF_PM_4_0, CONF_STORE_BASELINE, CONF_TEMPERATURE, + DEVICE_CLASS_AQI, DEVICE_CLASS_HUMIDITY, - DEVICE_CLASS_NITROUS_OXIDE, DEVICE_CLASS_PM1, DEVICE_CLASS_PM10, DEVICE_CLASS_PM25, DEVICE_CLASS_TEMPERATURE, - DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS, ICON_CHEMICAL_WEAPON, ICON_RADIATOR, ICON_THERMOMETER, @@ -132,13 +131,13 @@ CONFIG_SCHEMA = ( cv.Optional(CONF_VOC): sensor.sensor_schema( icon=ICON_RADIATOR, accuracy_decimals=0, - device_class=DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS, + device_class=DEVICE_CLASS_AQI, state_class=STATE_CLASS_MEASUREMENT, ).extend(GAS_SENSOR), cv.Optional(CONF_NOX): sensor.sensor_schema( icon=ICON_RADIATOR, accuracy_decimals=0, - device_class=DEVICE_CLASS_NITROUS_OXIDE, + device_class=DEVICE_CLASS_AQI, state_class=STATE_CLASS_MEASUREMENT, ).extend(GAS_SENSOR), cv.Optional(CONF_STORE_BASELINE, default=True): cv.boolean, From 4de58559c6bad70a61efb3a32e1b04f6e98f1474 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Sat, 16 Mar 2024 14:22:34 +1300 Subject: [PATCH 1099/2101] Fix list-components when PR is not targeting dev (#6375) --- .github/workflows/ci.yml | 15 ++++++++++----- script/helpers.py | 4 ++-- script/list-components.py | 11 ++++++++++- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c3de879176..47709739dc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -398,6 +398,7 @@ jobs: runs-on: ubuntu-latest needs: - common + if: github.event_name == 'pull_request' outputs: matrix: ${{ steps.set-matrix.outputs.matrix }} steps: @@ -406,10 +407,14 @@ jobs: with: # Fetch enough history so `git merge-base refs/remotes/origin/dev HEAD` works. fetch-depth: 500 - - name: Fetch dev branch + - name: Get target branch + id: target-branch run: | - git -c protocol.version=2 fetch --no-tags --prune --no-recurse-submodules --depth=1 origin +refs/heads/dev*:refs/remotes/origin/dev* +refs/tags/dev*:refs/tags/dev* - git merge-base refs/remotes/origin/dev HEAD + echo "branch=${{ github.event.pull_request.base.ref }}" >> $GITHUB_OUTPUT + - name: Fetch ${{ steps.target-branch.outputs.branch }} branch + run: | + git -c protocol.version=2 fetch --no-tags --prune --no-recurse-submodules --depth=1 origin +refs/heads/${{ steps.target-branch.outputs.branch }}:refs/remotes/origin/${{ steps.target-branch.outputs.branch }} + git merge-base refs/remotes/origin/${{ steps.target-branch.outputs.branch }} HEAD - name: Restore Python uses: ./.github/actions/restore-python with: @@ -419,7 +424,7 @@ jobs: id: set-matrix run: | . venv/bin/activate - echo "matrix=$(script/list-components.py --changed | jq -R -s -c 'split("\n")[:-1]')" >> $GITHUB_OUTPUT + echo "matrix=$(script/list-components.py --changed --branch ${{ steps.target-branch.outputs.branch }} | jq -R -s -c 'split("\n")[:-1]')" >> $GITHUB_OUTPUT test-build-components: name: Component test ${{ matrix.file }} @@ -427,7 +432,7 @@ jobs: needs: - common - list-components - if: ${{ needs.list-components.outputs.matrix != '[]' && needs.list-components.outputs.matrix != '' }} + if: ${{ github.event_name == 'pull_request' && needs.list-components.outputs.matrix != '[]' && needs.list-components.outputs.matrix != '' }} strategy: fail-fast: false max-parallel: 2 diff --git a/script/helpers.py b/script/helpers.py index a971fdf475..52b0658fb6 100644 --- a/script/helpers.py +++ b/script/helpers.py @@ -70,11 +70,11 @@ def splitlines_no_ends(string): return [s.strip() for s in string.splitlines()] -def changed_files(): +def changed_files(branch="dev"): check_remotes = ["upstream", "origin"] check_remotes.extend(splitlines_no_ends(get_output("git", "remote"))) for remote in check_remotes: - command = ["git", "merge-base", f"refs/remotes/{remote}/dev", "HEAD"] + command = ["git", "merge-base", f"refs/remotes/{remote}/{branch}", "HEAD"] try: merge_base = splitlines_no_ends(get_output(*command))[0] break diff --git a/script/list-components.py b/script/list-components.py index 3e55c0e5f7..8e2d47c6b3 100755 --- a/script/list-components.py +++ b/script/list-components.py @@ -120,13 +120,22 @@ def main(): parser.add_argument( "-c", "--changed", action="store_true", help="Only run on changed files" ) + parser.add_argument( + "-b", "--branch", help="Branch to compare changed files against" + ) args = parser.parse_args() + if args.branch and not args.changed: + parser.error("--branch requires --changed") + files = git_ls_files() files = filter(filter_component_files, files) if args.changed: - changed = changed_files() + if args.branch: + changed = changed_files(args.branch) + else: + changed = changed_files() files = [f for f in files if f in changed] components = extract_component_names_array_from_files_array(files) From d121fa5d05604df28ab470a4fb79946eb3d8858b Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Sun, 17 Mar 2024 12:10:47 -0700 Subject: [PATCH 1100/2101] allow negative ppm for sensair (#6385) --- esphome/components/senseair/senseair.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/senseair/senseair.cpp b/esphome/components/senseair/senseair.cpp index e0504eb2b9..e58ee157f7 100644 --- a/esphome/components/senseair/senseair.cpp +++ b/esphome/components/senseair/senseair.cpp @@ -54,9 +54,9 @@ void SenseAirComponent::update() { this->status_clear_warning(); const uint8_t length = response[2]; const uint16_t status = (uint16_t(response[3]) << 8) | response[4]; - const uint16_t ppm = (uint16_t(response[length + 1]) << 8) | response[length + 2]; + const int16_t ppm = int16_t((response[length + 1] << 8) | response[length + 2]); - ESP_LOGD(TAG, "SenseAir Received CO₂=%uppm Status=0x%02X", ppm, status); + ESP_LOGD(TAG, "SenseAir Received CO₂=%dppm Status=0x%02X", ppm, status); if (this->co2_sensor_ != nullptr) this->co2_sensor_->publish_state(ppm); } From 9e378189c3157a548a6dc8ef335a6dfacf546fc6 Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt Date: Sun, 17 Mar 2024 15:13:55 -0400 Subject: [PATCH 1101/2101] microWakeWord - add new ops and small improvements (#6360) --- .../micro_wake_word/micro_wake_word.cpp | 66 ++++++++----------- .../micro_wake_word/micro_wake_word.h | 3 +- 2 files changed, 27 insertions(+), 42 deletions(-) diff --git a/esphome/components/micro_wake_word/micro_wake_word.cpp b/esphome/components/micro_wake_word/micro_wake_word.cpp index 7321e5b05b..f637f8b2bb 100644 --- a/esphome/components/micro_wake_word/micro_wake_word.cpp +++ b/esphome/components/micro_wake_word/micro_wake_word.cpp @@ -93,11 +93,18 @@ int MicroWakeWord::read_microphone_() { return 0; } - size_t bytes_written = this->ring_buffer_->write((void *) this->input_buffer_, bytes_read); - if (bytes_written != bytes_read) { - ESP_LOGW(TAG, "Failed to write some data to ring buffer (written=%d, expected=%d)", bytes_written, bytes_read); + size_t bytes_free = this->ring_buffer_->free(); + + if (bytes_free < bytes_read) { + ESP_LOGW(TAG, + "Not enough free bytes in ring buffer to store incoming audio data (free bytes=%d, incoming bytes=%d). " + "Resetting the ring buffer. Wake word detection accuracy will be reduced.", + bytes_free, bytes_read); + + this->ring_buffer_->reset(); } - return bytes_written; + + return this->ring_buffer_->write((void *) this->input_buffer_, bytes_read); } void MicroWakeWord::loop() { @@ -206,12 +213,6 @@ bool MicroWakeWord::initialize_models() { return false; } - this->preprocessor_stride_buffer_ = audio_samples_allocator.allocate(HISTORY_SAMPLES_TO_KEEP); - if (this->preprocessor_stride_buffer_ == nullptr) { - ESP_LOGE(TAG, "Could not allocate the audio preprocessor's stride buffer."); - return false; - } - this->preprocessor_model_ = tflite::GetModel(G_AUDIO_PREPROCESSOR_INT8_TFLITE); if (this->preprocessor_model_->version() != TFLITE_SCHEMA_VERSION) { ESP_LOGE(TAG, "Wake word's audio preprocessor model's schema is not supported"); @@ -225,7 +226,7 @@ bool MicroWakeWord::initialize_models() { } static tflite::MicroMutableOpResolver<18> preprocessor_op_resolver; - static tflite::MicroMutableOpResolver<14> streaming_op_resolver; + static tflite::MicroMutableOpResolver<17> streaming_op_resolver; if (!this->register_preprocessor_ops_(preprocessor_op_resolver)) return false; @@ -329,7 +330,6 @@ bool MicroWakeWord::detect_wake_word_() { } // Perform inference - uint32_t streaming_size = micros(); float streaming_prob = this->perform_streaming_inference_(); // Add the most recent probability to the sliding window @@ -357,6 +357,9 @@ bool MicroWakeWord::detect_wake_word_() { for (auto &prob : this->recent_streaming_probabilities_) { prob = 0; } + + ESP_LOGD(TAG, "Wake word sliding average probability is %.3f and most recent probability is %.3f", + sliding_window_average, streaming_prob); return true; } @@ -371,23 +374,6 @@ void MicroWakeWord::set_sliding_window_average_size(size_t size) { bool MicroWakeWord::slice_available_() { size_t available = this->ring_buffer_->available(); - size_t free = this->ring_buffer_->free(); - - if (free < NEW_SAMPLES_TO_GET * sizeof(int16_t)) { - // If the ring buffer is within one audio slice of being full, then wake word detection will have issues. - // If this is constantly occuring, then some possibilities why are - // 1) there are too many other slow components configured - // 2) the ESP32 isn't fast enough; e.g., an ESP32 is much slower than an ESP32-S3 at inferences. - // 3) the model is too large - // 4) the model uses operations that are not optimized - ESP_LOGW(TAG, - "Audio buffer is nearly full. Wake word detection may be less accurate and have slower reponse times. " -#if !defined(USE_ESP32_VARIANT_ESP32S3) - "microWakeWord is designed for the ESP32-S3. The current platform is too slow for this model." -#endif - ); - } - return available > (NEW_SAMPLES_TO_GET * sizeof(int16_t)); } @@ -396,13 +382,12 @@ bool MicroWakeWord::stride_audio_samples_(int16_t **audio_samples) { return false; } - // Copy 320 bytes (160 samples over 10 ms) into preprocessor_audio_buffer_ from history in - // preprocessor_stride_buffer_ - memcpy((void *) (this->preprocessor_audio_buffer_), (void *) (this->preprocessor_stride_buffer_), + // Copy the last 320 bytes (160 samples over 10 ms) from the audio buffer to the start of the audio buffer + memcpy((void *) (this->preprocessor_audio_buffer_), (void *) (this->preprocessor_audio_buffer_ + NEW_SAMPLES_TO_GET), HISTORY_SAMPLES_TO_KEEP * sizeof(int16_t)); - // Copy 640 bytes (320 samples over 20 ms) from the ring buffer - // The first 320 bytes (160 samples over 10 ms) will be from history + // Copy 640 bytes (320 samples over 20 ms) from the ring buffer into the audio buffer offset 320 bytes (160 samples + // over 10 ms) size_t bytes_read = this->ring_buffer_->read((void *) (this->preprocessor_audio_buffer_ + HISTORY_SAMPLES_TO_KEEP), NEW_SAMPLES_TO_GET * sizeof(int16_t), pdMS_TO_TICKS(200)); @@ -415,11 +400,6 @@ bool MicroWakeWord::stride_audio_samples_(int16_t **audio_samples) { return false; } - // Copy the last 320 bytes (160 samples over 10 ms) from the audio buffer into history stride buffer for the next - // iteration - memcpy((void *) (this->preprocessor_stride_buffer_), (void *) (this->preprocessor_audio_buffer_ + NEW_SAMPLES_TO_GET), - HISTORY_SAMPLES_TO_KEEP * sizeof(int16_t)); - *audio_samples = this->preprocessor_audio_buffer_; return true; } @@ -480,7 +460,7 @@ bool MicroWakeWord::register_preprocessor_ops_(tflite::MicroMutableOpResolver<18 return true; } -bool MicroWakeWord::register_streaming_ops_(tflite::MicroMutableOpResolver<14> &op_resolver) { +bool MicroWakeWord::register_streaming_ops_(tflite::MicroMutableOpResolver<17> &op_resolver) { if (op_resolver.AddCallOnce() != kTfLiteOk) return false; if (op_resolver.AddVarHandle() != kTfLiteOk) @@ -509,6 +489,12 @@ bool MicroWakeWord::register_streaming_ops_(tflite::MicroMutableOpResolver<14> & return false; if (op_resolver.AddQuantize() != kTfLiteOk) return false; + if (op_resolver.AddDepthwiseConv2D() != kTfLiteOk) + return false; + if (op_resolver.AddAveragePool2D() != kTfLiteOk) + return false; + if (op_resolver.AddMaxPool2D() != kTfLiteOk) + return false; return true; } diff --git a/esphome/components/micro_wake_word/micro_wake_word.h b/esphome/components/micro_wake_word/micro_wake_word.h index 27d05c3e09..1d7c18d686 100644 --- a/esphome/components/micro_wake_word/micro_wake_word.h +++ b/esphome/components/micro_wake_word/micro_wake_word.h @@ -128,7 +128,6 @@ class MicroWakeWord : public Component { // Stores audio fed into feature generator preprocessor int16_t *preprocessor_audio_buffer_; - int16_t *preprocessor_stride_buffer_; bool detected_{false}; @@ -181,7 +180,7 @@ class MicroWakeWord : public Component { bool register_preprocessor_ops_(tflite::MicroMutableOpResolver<18> &op_resolver); /// @brief Returns true if successfully registered the streaming model's TensorFlow operations - bool register_streaming_ops_(tflite::MicroMutableOpResolver<14> &op_resolver); + bool register_streaming_ops_(tflite::MicroMutableOpResolver<17> &op_resolver); }; template class StartAction : public Action, public Parented { From 3908a9ce9da17572d2176d85874ebd52406ad567 Mon Sep 17 00:00:00 2001 From: Stefan Rado <628587+kroimon@users.noreply.github.com> Date: Sun, 17 Mar 2024 22:00:07 +0100 Subject: [PATCH 1102/2101] Fix compilation for uponor_smatrix without time component (#6389) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/uponor_smatrix/uponor_smatrix.cpp | 2 ++ esphome/components/uponor_smatrix/uponor_smatrix.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/esphome/components/uponor_smatrix/uponor_smatrix.cpp b/esphome/components/uponor_smatrix/uponor_smatrix.cpp index 10cd787c7f..df81691fb1 100644 --- a/esphome/components/uponor_smatrix/uponor_smatrix.cpp +++ b/esphome/components/uponor_smatrix/uponor_smatrix.cpp @@ -61,9 +61,11 @@ void UponorSmatrixComponent::loop() { // Send packets during bus silence if ((now - this->last_rx_ > 300) && (now - this->last_poll_start_ < 9500) && (now - this->last_tx_ > 200)) { +#ifdef USE_TIME // Only build time packet when bus is silent and queue is empty to make sure we can send it right away if (this->send_time_requested_ && this->tx_queue_.empty() && this->do_send_time_()) this->send_time_requested_ = false; +#endif // Send the next packet in the queue if (!this->tx_queue_.empty()) { auto packet = std::move(this->tx_queue_.front()); diff --git a/esphome/components/uponor_smatrix/uponor_smatrix.h b/esphome/components/uponor_smatrix/uponor_smatrix.h index b6675199b5..b7667b5b87 100644 --- a/esphome/components/uponor_smatrix/uponor_smatrix.h +++ b/esphome/components/uponor_smatrix/uponor_smatrix.h @@ -4,6 +4,8 @@ #include "esphome/core/component.h" #include "esphome/core/helpers.h" +#include "esphome/core/defines.h" + #ifdef USE_TIME #include "esphome/components/time/real_time_clock.h" #include "esphome/core/time.h" From 22f427165fa8fc0e9407c66db682d3b005f54d43 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Sun, 17 Mar 2024 22:01:25 +0100 Subject: [PATCH 1103/2101] Shows component operation time in `ms` (#6388) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/core/component.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index b0406e6502..d737ec0ae3 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -5,6 +5,7 @@ #include "esphome/core/helpers.h" #include "esphome/core/log.h" #include +#include namespace esphome { @@ -211,8 +212,8 @@ WarnIfComponentBlockingGuard::~WarnIfComponentBlockingGuard() { uint32_t now = millis(); if (now - started_ > 50) { const char *src = component_ == nullptr ? "" : component_->get_component_source(); - ESP_LOGW(TAG, "Component %s took a long time for an operation (%.2f s).", src, (now - started_) / 1e3f); - ESP_LOGW(TAG, "Components should block for at most 20-30ms."); + ESP_LOGW(TAG, "Component %s took a long time for an operation (%" PRIu32 " ms).", src, (now - started_)); + ESP_LOGW(TAG, "Components should block for at most 30 ms."); ; } } From 4429e5ae5612d3e0b5acf459ea213f4762ab106d Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Sun, 17 Mar 2024 22:06:02 +0100 Subject: [PATCH 1104/2101] IPv6 can't be enabled for libretiny (#6387) --- esphome/components/network/__init__.py | 38 ++++++++++++++++---------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/esphome/components/network/__init__.py b/esphome/components/network/__init__.py index 4e87ff1c12..36144ff0a4 100644 --- a/esphome/components/network/__init__.py +++ b/esphome/components/network/__init__.py @@ -6,6 +6,9 @@ from esphome.components.esp32 import add_idf_sdkconfig_option from esphome.const import ( CONF_ENABLE_IPV6, CONF_MIN_IPV6_ADDR_COUNT, + PLATFORM_ESP32, + PLATFORM_ESP8266, + PLATFORM_RP2040, ) CODEOWNERS = ["@esphome/core"] @@ -16,25 +19,30 @@ IPAddress = network_ns.class_("IPAddress") CONFIG_SCHEMA = cv.Schema( { - cv.Optional(CONF_ENABLE_IPV6, default=False): cv.boolean, + cv.SplitDefault(CONF_ENABLE_IPV6): cv.All( + cv.boolean, cv.only_on([PLATFORM_ESP32, PLATFORM_ESP8266, PLATFORM_RP2040]) + ), cv.Optional(CONF_MIN_IPV6_ADDR_COUNT, default=0): cv.positive_int, } ) async def to_code(config): - cg.add_define("USE_NETWORK_IPV6", config[CONF_ENABLE_IPV6]) - cg.add_define("USE_NETWORK_MIN_IPV6_ADDR_COUNT", config[CONF_MIN_IPV6_ADDR_COUNT]) - if CORE.using_esp_idf: - add_idf_sdkconfig_option("CONFIG_LWIP_IPV6", config[CONF_ENABLE_IPV6]) - add_idf_sdkconfig_option( - "CONFIG_LWIP_IPV6_AUTOCONFIG", config[CONF_ENABLE_IPV6] + if CONF_ENABLE_IPV6 in config: + cg.add_define("USE_NETWORK_IPV6", config[CONF_ENABLE_IPV6]) + cg.add_define( + "USE_NETWORK_MIN_IPV6_ADDR_COUNT", config[CONF_MIN_IPV6_ADDR_COUNT] ) - else: - if config[CONF_ENABLE_IPV6]: - cg.add_build_flag("-DCONFIG_LWIP_IPV6") - cg.add_build_flag("-DCONFIG_LWIP_IPV6_AUTOCONFIG") - if CORE.is_rp2040: - cg.add_build_flag("-DPIO_FRAMEWORK_ARDUINO_ENABLE_IPV6") - if CORE.is_esp8266: - cg.add_build_flag("-DPIO_FRAMEWORK_ARDUINO_LWIP2_IPV6_LOW_MEMORY") + if CORE.using_esp_idf: + add_idf_sdkconfig_option("CONFIG_LWIP_IPV6", config[CONF_ENABLE_IPV6]) + add_idf_sdkconfig_option( + "CONFIG_LWIP_IPV6_AUTOCONFIG", config[CONF_ENABLE_IPV6] + ) + else: + if config[CONF_ENABLE_IPV6]: + cg.add_build_flag("-DCONFIG_LWIP_IPV6") + cg.add_build_flag("-DCONFIG_LWIP_IPV6_AUTOCONFIG") + if CORE.is_rp2040: + cg.add_build_flag("-DPIO_FRAMEWORK_ARDUINO_ENABLE_IPV6") + if CORE.is_esp8266: + cg.add_build_flag("-DPIO_FRAMEWORK_ARDUINO_LWIP2_IPV6_LOW_MEMORY") From 690a7d46cebec6d02df9d75277b492a9360b5c08 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 18 Mar 2024 13:00:59 +1300 Subject: [PATCH 1105/2101] Replace name and friendly name in full adopted configs (#4456) --- .../components/dashboard_import/__init__.py | 130 +++++++++--------- esphome/dashboard/web_server.py | 3 +- requirements.txt | 1 + 3 files changed, 68 insertions(+), 66 deletions(-) diff --git a/esphome/components/dashboard_import/__init__.py b/esphome/components/dashboard_import/__init__.py index e0994be6a0..b1b22b816b 100644 --- a/esphome/components/dashboard_import/__init__.py +++ b/esphome/components/dashboard_import/__init__.py @@ -2,8 +2,10 @@ import base64 import secrets from pathlib import Path from typing import Optional +import re import requests +from ruamel.yaml import YAML import esphome.codegen as cg import esphome.config_validation as cv @@ -11,7 +13,6 @@ import esphome.final_validate as fv from esphome import git from esphome.components.packages import validate_source_shorthand from esphome.const import CONF_REF, CONF_WIFI, CONF_ESPHOME, CONF_PROJECT -from esphome.wizard import wizard_file from esphome.yaml_util import dump dashboard_import_ns = cg.esphome_ns.namespace("dashboard_import") @@ -94,75 +95,74 @@ def import_config( if p.exists(): raise FileExistsError - if project_name == "esphome.web": - if "esp32c3" in import_url: - board = "esp32-c3-devkitm-1" - platform = "ESP32" - elif "esp32s2" in import_url: - board = "esp32-s2-saola-1" - platform = "ESP32" - elif "esp32s3" in import_url: - board = "esp32-s3-devkitc-1" - platform = "ESP32" - elif "esp32" in import_url: - board = "esp32dev" - platform = "ESP32" - elif "esp8266" in import_url: - board = "esp01_1m" - platform = "ESP8266" - elif "pico-w" in import_url: - board = "pico-w" - platform = "RP2040" + git_file = git.GitFile.from_shorthand(import_url) - kwargs = { - "name": name, - "friendly_name": friendly_name, - "platform": platform, - "board": board, - "ssid": "!secret wifi_ssid", - "psk": "!secret wifi_password", + if git_file.query and "full_config" in git_file.query: + url = git_file.raw_url + try: + req = requests.get(url, timeout=30) + req.raise_for_status() + except requests.exceptions.RequestException as e: + raise ValueError(f"Error while fetching {url}: {e}") from e + + contents = req.text + yaml = YAML() + loaded_yaml = yaml.load(contents) + if ( + "name_add_mac_suffix" in loaded_yaml["esphome"] + and loaded_yaml["esphome"]["name_add_mac_suffix"] + ): + loaded_yaml["esphome"]["name_add_mac_suffix"] = False + name_val = loaded_yaml["esphome"]["name"] + sub_pattern = re.compile(r"\$\{?([a-zA-Z-_]+)\}?") + if match := sub_pattern.match(name_val): + name_sub = match.group(1) + if name_sub in loaded_yaml["substitutions"]: + loaded_yaml["substitutions"][name_sub] = name + else: + raise ValueError( + f"Name substitution {name_sub} not found in substitutions" + ) + else: + loaded_yaml["esphome"]["name"] = name + if friendly_name is not None: + friendly_name_val = loaded_yaml["esphome"]["friendly_name"] + if match := sub_pattern.match(friendly_name_val): + friendly_name_sub = match.group(1) + if friendly_name_sub in loaded_yaml["substitutions"]: + loaded_yaml["substitutions"][friendly_name_sub] = friendly_name + else: + raise ValueError( + f"Friendly name substitution {friendly_name_sub} not found in substitutions" + ) + else: + loaded_yaml["esphome"]["friendly_name"] = friendly_name + + with p.open("w", encoding="utf8") as f: + yaml.dump(loaded_yaml, f) + else: + with p.open("w", encoding="utf8") as f: + f.write(contents) + + else: + substitutions = {"name": name} + esphome_core = {"name": "${name}", "name_add_mac_suffix": False} + if friendly_name: + substitutions["friendly_name"] = friendly_name + esphome_core["friendly_name"] = "${friendly_name}" + config = { + "substitutions": substitutions, + "packages": {project_name: import_url}, + "esphome": esphome_core, } if encryption: noise_psk = secrets.token_bytes(32) key = base64.b64encode(noise_psk).decode() - kwargs["api_encryption_key"] = key + config["api"] = {"encryption": {"key": key}} - p.write_text( - wizard_file(**kwargs), - encoding="utf8", - ) - else: - git_file = git.GitFile.from_shorthand(import_url) + output = dump(config) - if git_file.query and "full_config" in git_file.query: - url = git_file.raw_url - try: - req = requests.get(url, timeout=30) - req.raise_for_status() - except requests.exceptions.RequestException as e: - raise ValueError(f"Error while fetching {url}: {e}") from e + if network == CONF_WIFI: + output += WIFI_CONFIG - p.write_text(req.text, encoding="utf8") - - else: - substitutions = {"name": name} - esphome_core = {"name": "${name}", "name_add_mac_suffix": False} - if friendly_name: - substitutions["friendly_name"] = friendly_name - esphome_core["friendly_name"] = "${friendly_name}" - config = { - "substitutions": substitutions, - "packages": {project_name: import_url}, - "esphome": esphome_core, - } - if encryption: - noise_psk = secrets.token_bytes(32) - key = base64.b64encode(noise_psk).decode() - config["api"] = {"encryption": {"key": key}} - - output = dump(config) - - if network == CONF_WIFI: - output += WIFI_CONFIG - - p.write_text(output, encoding="utf8") + p.write_text(output, encoding="utf8") diff --git a/esphome/dashboard/web_server.py b/esphome/dashboard/web_server.py index de3fe6e8ae..3de1d69115 100644 --- a/esphome/dashboard/web_server.py +++ b/esphome/dashboard/web_server.py @@ -516,7 +516,8 @@ class ImportRequestHandler(BaseHandler): self.set_status(500) self.write("File already exists") return - except ValueError: + except ValueError as e: + _LOGGER.error(e) self.set_status(422) self.write("Invalid package url") return diff --git a/requirements.txt b/requirements.txt index 32955bf6e7..9b5e06fc59 100644 --- a/requirements.txt +++ b/requirements.txt @@ -16,6 +16,7 @@ esphome-dashboard==20231107.0 aioesphomeapi==23.1.1 zeroconf==0.131.0 python-magic==0.4.27 +ruamel.yaml==0.18.6 # dashboard_import # esp-idf requires this, but doesn't bundle it by default # https://github.com/espressif/esp-idf/blob/220590d599e134d7a5e7f1e683cc4550349ffbf8/requirements.txt#L24 From 8a8bfe01c7e16295de9a8256b811b1c6f1a500ee Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 18 Mar 2024 15:54:39 +1300 Subject: [PATCH 1106/2101] Bump version to 2024.3.0b3 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 4259c82ad7..60ea6f0423 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.3.0b2" +__version__ = "2024.3.0b3" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From f3f7bdc4e11a006b6305a48740b85a68b9d31be5 Mon Sep 17 00:00:00 2001 From: swoboda1337 <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 18 Mar 2024 02:35:06 -0400 Subject: [PATCH 1107/2101] Fix bug in `remote_base` conditional (#6281) Co-authored-by: Jonathan Swoboda --- esphome/components/remote_base/remote_base.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/remote_base/remote_base.cpp b/esphome/components/remote_base/remote_base.cpp index 095f95053f..f3e86aaab6 100644 --- a/esphome/components/remote_base/remote_base.cpp +++ b/esphome/components/remote_base/remote_base.cpp @@ -16,7 +16,7 @@ RemoteRMTChannel::RemoteRMTChannel(uint8_t mem_block_num) : mem_block_num_(mem_b } void RemoteRMTChannel::config_rmt(rmt_config_t &rmt) { - if (rmt_channel_t(int(this->channel_) + this->mem_block_num_) >= RMT_CHANNEL_MAX) { + if (rmt_channel_t(int(this->channel_) + this->mem_block_num_) > RMT_CHANNEL_MAX) { this->mem_block_num_ = int(RMT_CHANNEL_MAX) - int(this->channel_); ESP_LOGW(TAG, "Not enough RMT memory blocks available, reduced to %i blocks.", this->mem_block_num_); } From 1e5dc159724a330b4f28616a310e026d76c80281 Mon Sep 17 00:00:00 2001 From: Stefan Rado <628587+kroimon@users.noreply.github.com> Date: Mon, 18 Mar 2024 19:04:53 +0100 Subject: [PATCH 1108/2101] Fix sending packets to uponor_smatrix devices (#6392) --- esphome/components/uponor_smatrix/uponor_smatrix.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/esphome/components/uponor_smatrix/uponor_smatrix.cpp b/esphome/components/uponor_smatrix/uponor_smatrix.cpp index df81691fb1..a7014dc96c 100644 --- a/esphome/components/uponor_smatrix/uponor_smatrix.cpp +++ b/esphome/components/uponor_smatrix/uponor_smatrix.cpp @@ -173,7 +173,9 @@ bool UponorSmatrixComponent::send(uint16_t device_address, const UponorSmatrixDa return false; // Assemble packet for send queue. All fields are big-endian except for the little-endian checksum. - std::vector packet(6 + 3 * data_len); + std::vector packet; + packet.reserve(6 + 3 * data_len); + packet.push_back(this->address_ >> 8); packet.push_back(this->address_ >> 0); packet.push_back(device_address >> 8); From 55677bb68e285aa2b076c1ff0e54d5fd83ff7814 Mon Sep 17 00:00:00 2001 From: Stefan Rado <628587+kroimon@users.noreply.github.com> Date: Mon, 18 Mar 2024 19:06:17 +0100 Subject: [PATCH 1109/2101] Fix wrong initialization of vectors in ade7953_i2c (#6393) --- .../components/ade7953_i2c/ade7953_i2c.cpp | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/esphome/components/ade7953_i2c/ade7953_i2c.cpp b/esphome/components/ade7953_i2c/ade7953_i2c.cpp index 572337428a..ae381824db 100644 --- a/esphome/components/ade7953_i2c/ade7953_i2c.cpp +++ b/esphome/components/ade7953_i2c/ade7953_i2c.cpp @@ -13,29 +13,29 @@ void AdE7953I2c::dump_config() { ade7953_base::ADE7953::dump_config(); } bool AdE7953I2c::ade_write_8(uint16_t reg, uint8_t value) { - std::vector data(3); - data.push_back(reg >> 8); - data.push_back(reg >> 0); - data.push_back(value); - return this->write(data.data(), data.size()) != i2c::ERROR_OK; + uint8_t data[3]; + data[0] = reg >> 8; + data[1] = reg >> 0; + data[2] = value; + return this->write(data, 3) != i2c::ERROR_OK; } bool AdE7953I2c::ade_write_16(uint16_t reg, uint16_t value) { - std::vector data(4); - data.push_back(reg >> 8); - data.push_back(reg >> 0); - data.push_back(value >> 8); - data.push_back(value >> 0); - return this->write(data.data(), data.size()) != i2c::ERROR_OK; + uint8_t data[4]; + data[0] = reg >> 8; + data[1] = reg >> 0; + data[2] = value >> 8; + data[3] = value >> 0; + return this->write(data, 4) != i2c::ERROR_OK; } bool AdE7953I2c::ade_write_32(uint16_t reg, uint32_t value) { - std::vector data(6); - data.push_back(reg >> 8); - data.push_back(reg >> 0); - data.push_back(value >> 24); - data.push_back(value >> 16); - data.push_back(value >> 8); - data.push_back(value >> 0); - return this->write(data.data(), data.size()) != i2c::ERROR_OK; + uint8_t data[6]; + data[0] = reg >> 8; + data[1] = reg >> 0; + data[2] = value >> 24; + data[3] = value >> 16; + data[4] = value >> 8; + data[5] = value >> 0; + return this->write(data, 6) != i2c::ERROR_OK; } bool AdE7953I2c::ade_read_8(uint16_t reg, uint8_t *value) { uint8_t reg_data[2]; From e7fe2a2816f6bc45ae46f8d17efc1cb20222bd74 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 19 Mar 2024 07:15:52 +1300 Subject: [PATCH 1110/2101] Check generated proto files are as expected if any are modified in PRs (#6254) --- .github/workflows/ci-api-proto.yml | 81 ++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 .github/workflows/ci-api-proto.yml diff --git a/.github/workflows/ci-api-proto.yml b/.github/workflows/ci-api-proto.yml new file mode 100644 index 0000000000..038ef3a587 --- /dev/null +++ b/.github/workflows/ci-api-proto.yml @@ -0,0 +1,81 @@ +name: API Proto CI + +# yamllint disable-line rule:truthy +on: + pull_request: + paths: + - "esphome/components/api/api.proto" + - "esphome/components/api/api_pb2.cpp" + - "esphome/components/api/api_pb2.h" + - "esphome/components/api/api_pb2_service.cpp" + - "esphome/components/api/api_pb2_service.h" + - "script/api_protobuf/api_protobuf.py" + - ".github/workflows/ci-api-proto.yml" + +permissions: + contents: read + pull-requests: write + +jobs: + check: + name: Check generated files + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4.1.1 + - name: Set up Python + uses: actions/setup-python@v5.0.0 + with: + python-version: "3.11" + + - name: Install apt dependencies + run: | + sudo apt update + sudo apt-cache show protobuf-compiler + sudo apt install -y protobuf-compiler + protoc --version + - name: Install python dependencies + run: pip install aioesphomeapi -c requirements.txt -r requirements_dev.txt + - name: Generate files + run: script/api_protobuf/api_protobuf.py + - name: Check for changes + run: | + if ! git diff --quiet; then + echo "## Job Failed" | tee -a $GITHUB_STEP_SUMMARY + echo "You have altered the generated proto files but they do not match what is expected." | tee -a $GITHUB_STEP_SUMMARY + echo "Please run 'script/api_protobuf/api_protobuf.py' and commit the changes." | tee -a $GITHUB_STEP_SUMMARY + exit 1 + fi + - if: failure() + name: Review PR + uses: actions/github-script@v7.0.1 + with: + script: | + await github.rest.pulls.createReview({ + pull_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + event: 'REQUEST_CHANGES', + body: 'You have altered the generated proto files but they do not match what is expected.\nPlease run "script/api_protobuf/api_protobuf.py" and commit the changes.' + }) + - if: success() + name: Dismiss review + uses: actions/github-script@v7.0.1 + with: + script: | + let reviews = await github.rest.pulls.listReviews({ + pull_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo + }); + for (let review of reviews.data) { + if (review.user.login === 'github-actions[bot]' && review.state === 'CHANGES_REQUESTED') { + await github.rest.pulls.dismissReview({ + pull_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + review_id: review.id, + message: 'Files now match the expected proto files.' + }); + } + } From d692b5404cc40af1bf6394bcc26574847e1727bc Mon Sep 17 00:00:00 2001 From: Mike La Spina Date: Mon, 18 Mar 2024 13:26:39 -0500 Subject: [PATCH 1111/2101] ld2420: Firmware v1.5.4+ bug workaround (#6168) --- esphome/components/ld2420/ld2420.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/esphome/components/ld2420/ld2420.cpp b/esphome/components/ld2420/ld2420.cpp index bda1764cfc..bf1412ee9f 100644 --- a/esphome/components/ld2420/ld2420.cpp +++ b/esphome/components/ld2420/ld2420.cpp @@ -211,10 +211,11 @@ void LD2420Component::factory_reset_action() { void LD2420Component::restart_module_action() { ESP_LOGCONFIG(TAG, "Restarting LD2420 module..."); this->send_module_restart(); - delay_microseconds_safe(45000); - this->set_config_mode(true); - this->set_system_mode(system_mode_); - this->set_config_mode(false); + this->set_timeout(250, [this]() { + this->set_config_mode(true); + this->set_system_mode(system_mode_); + this->set_config_mode(false); + }); ESP_LOGCONFIG(TAG, "LD2420 Restarted."); } @@ -527,18 +528,16 @@ int LD2420Component::send_cmd_from_array(CmdFrameT frame) { this->write_byte(cmd_buffer[index]); } - delay_microseconds_safe(500); // give the module a moment to process it error = 0; if (frame.command == CMD_RESTART) { - delay_microseconds_safe(25000); // Wait for the restart - return 0; // restart does not reply exit now + return 0; // restart does not reply exit now } while (!this->cmd_reply_.ack) { while (available()) { this->readline_(read(), ack_buffer, sizeof(ack_buffer)); } - delay_microseconds_safe(250); + delay_microseconds_safe(1450); if (loop_count <= 0) { error = LD2420_ERROR_TIMEOUT; retry--; From f5695733bc615fa3e6c1ab3c4c5b3d95ce25461c Mon Sep 17 00:00:00 2001 From: Andres Vahter Date: Mon, 18 Mar 2024 20:28:15 +0200 Subject: [PATCH 1112/2101] ld2420: fix energy mode documentation (#6225) --- 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 bf1412ee9f..58c9a289a3 100644 --- a/esphome/components/ld2420/ld2420.cpp +++ b/esphome/components/ld2420/ld2420.cpp @@ -40,9 +40,9 @@ There are three documented parameters for modes: 00 04 = Energy output mode This mode outputs detailed signal energy values for each gate and the target distance. The data format consist of the following. - Header HH, Length LL, Persence PP, Distance DD, Range Gate GG, 16 Gate Energies EE, Footer FF - HH HH HH HH LL LL PP DD DD GG GG EE EE .. 16x .. FF FF FF FF - F4 F3 F2 F1 00 23 00 00 00 00 01 00 00 .. .. .. .. F8 F7 F6 F5 + Header HH, Length LL, Persence PP, Distance DD, 16 Gate Energies EE, Footer FF + HH HH HH HH LL LL PP DD DD EE EE .. 16x .. FF FF FF FF + F4 F3 F2 F1 23 00 00 00 00 00 00 .. .. .. .. F8 F7 F6 F5 00 00 = debug output mode This mode outputs detailed values consisting of 20 Dopplers, 16 Ranges for a total 20 * 16 * 4 bytes The data format consist of the following. From cb731926be637a6b6c1344df877f49fe2c35bc30 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Mon, 18 Mar 2024 16:00:06 -0500 Subject: [PATCH 1113/2101] Add actions for component tests A, B and C (#6256) --- tests/components/api/test.esp32-c3-idf.yaml | 13 +++++++++++++ tests/components/api/test.esp32-c3.yaml | 13 +++++++++++++ tests/components/api/test.esp32-idf.yaml | 13 +++++++++++++ tests/components/api/test.esp32.yaml | 13 +++++++++++++ tests/components/api/test.esp8266.yaml | 13 +++++++++++++ tests/components/api/test.rp2040.yaml | 13 +++++++++++++ 6 files changed, 78 insertions(+) diff --git a/tests/components/api/test.esp32-c3-idf.yaml b/tests/components/api/test.esp32-c3-idf.yaml index 8e7ca0fb06..3c56811b95 100644 --- a/tests/components/api/test.esp32-c3-idf.yaml +++ b/tests/components/api/test.esp32-c3-idf.yaml @@ -1,3 +1,16 @@ +esphome: + on_boot: + then: + - homeassistant.event: + event: esphome.button_pressed + data: + message: Button was pressed + - homeassistant.service: + service: notify.html5 + data: + message: Button was pressed + - homeassistant.tag_scanned: pulse + wifi: ssid: MySSID password: password1 diff --git a/tests/components/api/test.esp32-c3.yaml b/tests/components/api/test.esp32-c3.yaml index 8e7ca0fb06..3c56811b95 100644 --- a/tests/components/api/test.esp32-c3.yaml +++ b/tests/components/api/test.esp32-c3.yaml @@ -1,3 +1,16 @@ +esphome: + on_boot: + then: + - homeassistant.event: + event: esphome.button_pressed + data: + message: Button was pressed + - homeassistant.service: + service: notify.html5 + data: + message: Button was pressed + - homeassistant.tag_scanned: pulse + wifi: ssid: MySSID password: password1 diff --git a/tests/components/api/test.esp32-idf.yaml b/tests/components/api/test.esp32-idf.yaml index 8e7ca0fb06..3c56811b95 100644 --- a/tests/components/api/test.esp32-idf.yaml +++ b/tests/components/api/test.esp32-idf.yaml @@ -1,3 +1,16 @@ +esphome: + on_boot: + then: + - homeassistant.event: + event: esphome.button_pressed + data: + message: Button was pressed + - homeassistant.service: + service: notify.html5 + data: + message: Button was pressed + - homeassistant.tag_scanned: pulse + wifi: ssid: MySSID password: password1 diff --git a/tests/components/api/test.esp32.yaml b/tests/components/api/test.esp32.yaml index 8e7ca0fb06..3c56811b95 100644 --- a/tests/components/api/test.esp32.yaml +++ b/tests/components/api/test.esp32.yaml @@ -1,3 +1,16 @@ +esphome: + on_boot: + then: + - homeassistant.event: + event: esphome.button_pressed + data: + message: Button was pressed + - homeassistant.service: + service: notify.html5 + data: + message: Button was pressed + - homeassistant.tag_scanned: pulse + wifi: ssid: MySSID password: password1 diff --git a/tests/components/api/test.esp8266.yaml b/tests/components/api/test.esp8266.yaml index 8e7ca0fb06..3c56811b95 100644 --- a/tests/components/api/test.esp8266.yaml +++ b/tests/components/api/test.esp8266.yaml @@ -1,3 +1,16 @@ +esphome: + on_boot: + then: + - homeassistant.event: + event: esphome.button_pressed + data: + message: Button was pressed + - homeassistant.service: + service: notify.html5 + data: + message: Button was pressed + - homeassistant.tag_scanned: pulse + wifi: ssid: MySSID password: password1 diff --git a/tests/components/api/test.rp2040.yaml b/tests/components/api/test.rp2040.yaml index 8e7ca0fb06..3c56811b95 100644 --- a/tests/components/api/test.rp2040.yaml +++ b/tests/components/api/test.rp2040.yaml @@ -1,3 +1,16 @@ +esphome: + on_boot: + then: + - homeassistant.event: + event: esphome.button_pressed + data: + message: Button was pressed + - homeassistant.service: + service: notify.html5 + data: + message: Button was pressed + - homeassistant.tag_scanned: pulse + wifi: ssid: MySSID password: password1 From d5a8bea8e94a6ea4114ecf3e9cf79946b10f198e Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Mon, 18 Mar 2024 16:42:03 -0500 Subject: [PATCH 1114/2101] Add some components to the new testing framework (V) (#6231) --- tests/components/vbus/test.esp32-c3-idf.yaml | 42 ++++++++++++++ tests/components/vbus/test.esp32-c3.yaml | 42 ++++++++++++++ tests/components/vbus/test.esp32-idf.yaml | 42 ++++++++++++++ tests/components/vbus/test.esp32.yaml | 42 ++++++++++++++ tests/components/vbus/test.esp8266.yaml | 42 ++++++++++++++ tests/components/vbus/test.rp2040.yaml | 42 ++++++++++++++ .../veml3235/test.esp32-c3-idf.yaml | 15 +++++ tests/components/veml3235/test.esp32-c3.yaml | 15 +++++ tests/components/veml3235/test.esp32-idf.yaml | 15 +++++ tests/components/veml3235/test.esp32.yaml | 15 +++++ tests/components/veml3235/test.esp8266.yaml | 15 +++++ tests/components/veml3235/test.rp2040.yaml | 15 +++++ .../components/version/test.esp32-c3-idf.yaml | 3 + tests/components/version/test.esp32-c3.yaml | 3 + tests/components/version/test.esp32-idf.yaml | 3 + tests/components/version/test.esp32.yaml | 3 + tests/components/version/test.esp8266.yaml | 3 + tests/components/version/test.rp2040.yaml | 3 + .../components/vl53l0x/test.esp32-c3-idf.yaml | 12 ++++ tests/components/vl53l0x/test.esp32-c3.yaml | 12 ++++ tests/components/vl53l0x/test.esp32-idf.yaml | 12 ++++ tests/components/vl53l0x/test.esp32.yaml | 12 ++++ tests/components/vl53l0x/test.esp8266.yaml | 12 ++++ tests/components/vl53l0x/test.rp2040.yaml | 12 ++++ .../voice_assistant/test.esp32-c3-idf.yaml | 57 +++++++++++++++++++ .../voice_assistant/test.esp32-c3.yaml | 57 +++++++++++++++++++ .../voice_assistant/test.esp32-idf.yaml | 57 +++++++++++++++++++ .../voice_assistant/test.esp32.yaml | 57 +++++++++++++++++++ 28 files changed, 660 insertions(+) create mode 100644 tests/components/vbus/test.esp32-c3-idf.yaml create mode 100644 tests/components/vbus/test.esp32-c3.yaml create mode 100644 tests/components/vbus/test.esp32-idf.yaml create mode 100644 tests/components/vbus/test.esp32.yaml create mode 100644 tests/components/vbus/test.esp8266.yaml create mode 100644 tests/components/vbus/test.rp2040.yaml create mode 100644 tests/components/veml3235/test.esp32-c3-idf.yaml create mode 100644 tests/components/veml3235/test.esp32-c3.yaml create mode 100644 tests/components/veml3235/test.esp32-idf.yaml create mode 100644 tests/components/veml3235/test.esp32.yaml create mode 100644 tests/components/veml3235/test.esp8266.yaml create mode 100644 tests/components/veml3235/test.rp2040.yaml create mode 100644 tests/components/version/test.esp32-c3-idf.yaml create mode 100644 tests/components/version/test.esp32-c3.yaml create mode 100644 tests/components/version/test.esp32-idf.yaml create mode 100644 tests/components/version/test.esp32.yaml create mode 100644 tests/components/version/test.esp8266.yaml create mode 100644 tests/components/version/test.rp2040.yaml create mode 100644 tests/components/vl53l0x/test.esp32-c3-idf.yaml create mode 100644 tests/components/vl53l0x/test.esp32-c3.yaml create mode 100644 tests/components/vl53l0x/test.esp32-idf.yaml create mode 100644 tests/components/vl53l0x/test.esp32.yaml create mode 100644 tests/components/vl53l0x/test.esp8266.yaml create mode 100644 tests/components/vl53l0x/test.rp2040.yaml create mode 100644 tests/components/voice_assistant/test.esp32-c3-idf.yaml create mode 100644 tests/components/voice_assistant/test.esp32-c3.yaml create mode 100644 tests/components/voice_assistant/test.esp32-idf.yaml create mode 100644 tests/components/voice_assistant/test.esp32.yaml diff --git a/tests/components/vbus/test.esp32-c3-idf.yaml b/tests/components/vbus/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..67ee542031 --- /dev/null +++ b/tests/components/vbus/test.esp32-c3-idf.yaml @@ -0,0 +1,42 @@ +uart: + - id: uart_vbus + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +vbus: + +binary_sensor: + - platform: vbus + model: deltasol_bs_plus + relay1: + name: Relay 1 On + relay2: + name: Relay 2 On + sensor1_error: + name: Sensor 1 Error + - platform: vbus + model: custom + command: 0x100 + source: 0x1234 + dest: 0x10 + binary_sensors: + - id: vcustom_b + name: VBus Custom Binary Sensor + lambda: return x[0] & 1; + +sensor: + - platform: vbus + model: deltasol c + temperature_1: + name: Temperature 1 + temperature_2: + name: Temperature 2 + temperature_3: + name: Temperature 3 + operating_hours_1: + name: Operating Hours 1 + heat_quantity: + name: Heat Quantity + time: + name: System Time diff --git a/tests/components/vbus/test.esp32-c3.yaml b/tests/components/vbus/test.esp32-c3.yaml new file mode 100644 index 0000000000..67ee542031 --- /dev/null +++ b/tests/components/vbus/test.esp32-c3.yaml @@ -0,0 +1,42 @@ +uart: + - id: uart_vbus + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +vbus: + +binary_sensor: + - platform: vbus + model: deltasol_bs_plus + relay1: + name: Relay 1 On + relay2: + name: Relay 2 On + sensor1_error: + name: Sensor 1 Error + - platform: vbus + model: custom + command: 0x100 + source: 0x1234 + dest: 0x10 + binary_sensors: + - id: vcustom_b + name: VBus Custom Binary Sensor + lambda: return x[0] & 1; + +sensor: + - platform: vbus + model: deltasol c + temperature_1: + name: Temperature 1 + temperature_2: + name: Temperature 2 + temperature_3: + name: Temperature 3 + operating_hours_1: + name: Operating Hours 1 + heat_quantity: + name: Heat Quantity + time: + name: System Time diff --git a/tests/components/vbus/test.esp32-idf.yaml b/tests/components/vbus/test.esp32-idf.yaml new file mode 100644 index 0000000000..a0e5ca42cc --- /dev/null +++ b/tests/components/vbus/test.esp32-idf.yaml @@ -0,0 +1,42 @@ +uart: + - id: uart_vbus + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +vbus: + +binary_sensor: + - platform: vbus + model: deltasol_bs_plus + relay1: + name: Relay 1 On + relay2: + name: Relay 2 On + sensor1_error: + name: Sensor 1 Error + - platform: vbus + model: custom + command: 0x100 + source: 0x1234 + dest: 0x10 + binary_sensors: + - id: vcustom_b + name: VBus Custom Binary Sensor + lambda: return x[0] & 1; + +sensor: + - platform: vbus + model: deltasol c + temperature_1: + name: Temperature 1 + temperature_2: + name: Temperature 2 + temperature_3: + name: Temperature 3 + operating_hours_1: + name: Operating Hours 1 + heat_quantity: + name: Heat Quantity + time: + name: System Time diff --git a/tests/components/vbus/test.esp32.yaml b/tests/components/vbus/test.esp32.yaml new file mode 100644 index 0000000000..a0e5ca42cc --- /dev/null +++ b/tests/components/vbus/test.esp32.yaml @@ -0,0 +1,42 @@ +uart: + - id: uart_vbus + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +vbus: + +binary_sensor: + - platform: vbus + model: deltasol_bs_plus + relay1: + name: Relay 1 On + relay2: + name: Relay 2 On + sensor1_error: + name: Sensor 1 Error + - platform: vbus + model: custom + command: 0x100 + source: 0x1234 + dest: 0x10 + binary_sensors: + - id: vcustom_b + name: VBus Custom Binary Sensor + lambda: return x[0] & 1; + +sensor: + - platform: vbus + model: deltasol c + temperature_1: + name: Temperature 1 + temperature_2: + name: Temperature 2 + temperature_3: + name: Temperature 3 + operating_hours_1: + name: Operating Hours 1 + heat_quantity: + name: Heat Quantity + time: + name: System Time diff --git a/tests/components/vbus/test.esp8266.yaml b/tests/components/vbus/test.esp8266.yaml new file mode 100644 index 0000000000..67ee542031 --- /dev/null +++ b/tests/components/vbus/test.esp8266.yaml @@ -0,0 +1,42 @@ +uart: + - id: uart_vbus + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +vbus: + +binary_sensor: + - platform: vbus + model: deltasol_bs_plus + relay1: + name: Relay 1 On + relay2: + name: Relay 2 On + sensor1_error: + name: Sensor 1 Error + - platform: vbus + model: custom + command: 0x100 + source: 0x1234 + dest: 0x10 + binary_sensors: + - id: vcustom_b + name: VBus Custom Binary Sensor + lambda: return x[0] & 1; + +sensor: + - platform: vbus + model: deltasol c + temperature_1: + name: Temperature 1 + temperature_2: + name: Temperature 2 + temperature_3: + name: Temperature 3 + operating_hours_1: + name: Operating Hours 1 + heat_quantity: + name: Heat Quantity + time: + name: System Time diff --git a/tests/components/vbus/test.rp2040.yaml b/tests/components/vbus/test.rp2040.yaml new file mode 100644 index 0000000000..67ee542031 --- /dev/null +++ b/tests/components/vbus/test.rp2040.yaml @@ -0,0 +1,42 @@ +uart: + - id: uart_vbus + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +vbus: + +binary_sensor: + - platform: vbus + model: deltasol_bs_plus + relay1: + name: Relay 1 On + relay2: + name: Relay 2 On + sensor1_error: + name: Sensor 1 Error + - platform: vbus + model: custom + command: 0x100 + source: 0x1234 + dest: 0x10 + binary_sensors: + - id: vcustom_b + name: VBus Custom Binary Sensor + lambda: return x[0] & 1; + +sensor: + - platform: vbus + model: deltasol c + temperature_1: + name: Temperature 1 + temperature_2: + name: Temperature 2 + temperature_3: + name: Temperature 3 + operating_hours_1: + name: Operating Hours 1 + heat_quantity: + name: Heat Quantity + time: + name: System Time diff --git a/tests/components/veml3235/test.esp32-c3-idf.yaml b/tests/components/veml3235/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..1f79c5f50c --- /dev/null +++ b/tests/components/veml3235/test.esp32-c3-idf.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_veml3235 + scl: 5 + sda: 4 + +sensor: + - platform: veml3235 + id: veml3235_sensor + name: VEML3235 Light Sensor + auto_gain: true + auto_gain_threshold_high: 90% + auto_gain_threshold_low: 15% + digital_gain: 1X + gain: 1X + integration_time: 50ms diff --git a/tests/components/veml3235/test.esp32-c3.yaml b/tests/components/veml3235/test.esp32-c3.yaml new file mode 100644 index 0000000000..1f79c5f50c --- /dev/null +++ b/tests/components/veml3235/test.esp32-c3.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_veml3235 + scl: 5 + sda: 4 + +sensor: + - platform: veml3235 + id: veml3235_sensor + name: VEML3235 Light Sensor + auto_gain: true + auto_gain_threshold_high: 90% + auto_gain_threshold_low: 15% + digital_gain: 1X + gain: 1X + integration_time: 50ms diff --git a/tests/components/veml3235/test.esp32-idf.yaml b/tests/components/veml3235/test.esp32-idf.yaml new file mode 100644 index 0000000000..3442fa4317 --- /dev/null +++ b/tests/components/veml3235/test.esp32-idf.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_veml3235 + scl: 16 + sda: 17 + +sensor: + - platform: veml3235 + id: veml3235_sensor + name: VEML3235 Light Sensor + auto_gain: true + auto_gain_threshold_high: 90% + auto_gain_threshold_low: 15% + digital_gain: 1X + gain: 1X + integration_time: 50ms diff --git a/tests/components/veml3235/test.esp32.yaml b/tests/components/veml3235/test.esp32.yaml new file mode 100644 index 0000000000..3442fa4317 --- /dev/null +++ b/tests/components/veml3235/test.esp32.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_veml3235 + scl: 16 + sda: 17 + +sensor: + - platform: veml3235 + id: veml3235_sensor + name: VEML3235 Light Sensor + auto_gain: true + auto_gain_threshold_high: 90% + auto_gain_threshold_low: 15% + digital_gain: 1X + gain: 1X + integration_time: 50ms diff --git a/tests/components/veml3235/test.esp8266.yaml b/tests/components/veml3235/test.esp8266.yaml new file mode 100644 index 0000000000..1f79c5f50c --- /dev/null +++ b/tests/components/veml3235/test.esp8266.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_veml3235 + scl: 5 + sda: 4 + +sensor: + - platform: veml3235 + id: veml3235_sensor + name: VEML3235 Light Sensor + auto_gain: true + auto_gain_threshold_high: 90% + auto_gain_threshold_low: 15% + digital_gain: 1X + gain: 1X + integration_time: 50ms diff --git a/tests/components/veml3235/test.rp2040.yaml b/tests/components/veml3235/test.rp2040.yaml new file mode 100644 index 0000000000..1f79c5f50c --- /dev/null +++ b/tests/components/veml3235/test.rp2040.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_veml3235 + scl: 5 + sda: 4 + +sensor: + - platform: veml3235 + id: veml3235_sensor + name: VEML3235 Light Sensor + auto_gain: true + auto_gain_threshold_high: 90% + auto_gain_threshold_low: 15% + digital_gain: 1X + gain: 1X + integration_time: 50ms diff --git a/tests/components/version/test.esp32-c3-idf.yaml b/tests/components/version/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..7713afc37c --- /dev/null +++ b/tests/components/version/test.esp32-c3-idf.yaml @@ -0,0 +1,3 @@ +text_sensor: + - platform: version + name: "ESPHome Version" diff --git a/tests/components/version/test.esp32-c3.yaml b/tests/components/version/test.esp32-c3.yaml new file mode 100644 index 0000000000..7713afc37c --- /dev/null +++ b/tests/components/version/test.esp32-c3.yaml @@ -0,0 +1,3 @@ +text_sensor: + - platform: version + name: "ESPHome Version" diff --git a/tests/components/version/test.esp32-idf.yaml b/tests/components/version/test.esp32-idf.yaml new file mode 100644 index 0000000000..7713afc37c --- /dev/null +++ b/tests/components/version/test.esp32-idf.yaml @@ -0,0 +1,3 @@ +text_sensor: + - platform: version + name: "ESPHome Version" diff --git a/tests/components/version/test.esp32.yaml b/tests/components/version/test.esp32.yaml new file mode 100644 index 0000000000..7713afc37c --- /dev/null +++ b/tests/components/version/test.esp32.yaml @@ -0,0 +1,3 @@ +text_sensor: + - platform: version + name: "ESPHome Version" diff --git a/tests/components/version/test.esp8266.yaml b/tests/components/version/test.esp8266.yaml new file mode 100644 index 0000000000..7713afc37c --- /dev/null +++ b/tests/components/version/test.esp8266.yaml @@ -0,0 +1,3 @@ +text_sensor: + - platform: version + name: "ESPHome Version" diff --git a/tests/components/version/test.rp2040.yaml b/tests/components/version/test.rp2040.yaml new file mode 100644 index 0000000000..7713afc37c --- /dev/null +++ b/tests/components/version/test.rp2040.yaml @@ -0,0 +1,3 @@ +text_sensor: + - platform: version + name: "ESPHome Version" diff --git a/tests/components/vl53l0x/test.esp32-c3-idf.yaml b/tests/components/vl53l0x/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..832f7dcfbc --- /dev/null +++ b/tests/components/vl53l0x/test.esp32-c3-idf.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_vl53l0x + scl: 5 + sda: 4 + +sensor: + - platform: vl53l0x + name: VL53L0x Distance + address: 0x29 + enable_pin: 3 + timeout: 200us + update_interval: 60s diff --git a/tests/components/vl53l0x/test.esp32-c3.yaml b/tests/components/vl53l0x/test.esp32-c3.yaml new file mode 100644 index 0000000000..832f7dcfbc --- /dev/null +++ b/tests/components/vl53l0x/test.esp32-c3.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_vl53l0x + scl: 5 + sda: 4 + +sensor: + - platform: vl53l0x + name: VL53L0x Distance + address: 0x29 + enable_pin: 3 + timeout: 200us + update_interval: 60s diff --git a/tests/components/vl53l0x/test.esp32-idf.yaml b/tests/components/vl53l0x/test.esp32-idf.yaml new file mode 100644 index 0000000000..8f35de0e72 --- /dev/null +++ b/tests/components/vl53l0x/test.esp32-idf.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_vl53l0x + scl: 16 + sda: 17 + +sensor: + - platform: vl53l0x + name: VL53L0x Distance + address: 0x29 + enable_pin: 3 + timeout: 200us + update_interval: 60s diff --git a/tests/components/vl53l0x/test.esp32.yaml b/tests/components/vl53l0x/test.esp32.yaml new file mode 100644 index 0000000000..8f35de0e72 --- /dev/null +++ b/tests/components/vl53l0x/test.esp32.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_vl53l0x + scl: 16 + sda: 17 + +sensor: + - platform: vl53l0x + name: VL53L0x Distance + address: 0x29 + enable_pin: 3 + timeout: 200us + update_interval: 60s diff --git a/tests/components/vl53l0x/test.esp8266.yaml b/tests/components/vl53l0x/test.esp8266.yaml new file mode 100644 index 0000000000..832f7dcfbc --- /dev/null +++ b/tests/components/vl53l0x/test.esp8266.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_vl53l0x + scl: 5 + sda: 4 + +sensor: + - platform: vl53l0x + name: VL53L0x Distance + address: 0x29 + enable_pin: 3 + timeout: 200us + update_interval: 60s diff --git a/tests/components/vl53l0x/test.rp2040.yaml b/tests/components/vl53l0x/test.rp2040.yaml new file mode 100644 index 0000000000..832f7dcfbc --- /dev/null +++ b/tests/components/vl53l0x/test.rp2040.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_vl53l0x + scl: 5 + sda: 4 + +sensor: + - platform: vl53l0x + name: VL53L0x Distance + address: 0x29 + enable_pin: 3 + timeout: 200us + update_interval: 60s diff --git a/tests/components/voice_assistant/test.esp32-c3-idf.yaml b/tests/components/voice_assistant/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..248ae4d0dc --- /dev/null +++ b/tests/components/voice_assistant/test.esp32-c3-idf.yaml @@ -0,0 +1,57 @@ +esphome: + on_boot: + then: + - voice_assistant.start + - voice_assistant.start_continuous + - voice_assistant.stop + +wifi: + ssid: MySSID + password: password1 + +api: + +i2s_audio: + i2s_lrclk_pin: 6 + i2s_bclk_pin: 7 + i2s_mclk_pin: 5 + +microphone: + - platform: i2s_audio + id: mic_id_external + i2s_din_pin: 3 + adc_type: external + pdm: false + +speaker: + - platform: i2s_audio + id: speaker_id + dac_type: external + i2s_dout_pin: 2 + mode: mono + +voice_assistant: + microphone: mic_id_external + speaker: speaker_id + on_listening: + - logger.log: "Voice assistant microphone listening" + on_start: + - logger.log: "Voice assistant started" + on_stt_end: + - logger.log: + format: "Voice assistant STT ended with result %s" + args: [x.c_str()] + on_tts_start: + - logger.log: + format: "Voice assistant TTS started with text %s" + args: [x.c_str()] + on_tts_end: + - logger.log: + format: "Voice assistant TTS ended with url %s" + args: [x.c_str()] + on_end: + - logger.log: "Voice assistant ended" + on_error: + - logger.log: + format: "Voice assistant error - code %s, message: %s" + args: [code.c_str(), message.c_str()] diff --git a/tests/components/voice_assistant/test.esp32-c3.yaml b/tests/components/voice_assistant/test.esp32-c3.yaml new file mode 100644 index 0000000000..248ae4d0dc --- /dev/null +++ b/tests/components/voice_assistant/test.esp32-c3.yaml @@ -0,0 +1,57 @@ +esphome: + on_boot: + then: + - voice_assistant.start + - voice_assistant.start_continuous + - voice_assistant.stop + +wifi: + ssid: MySSID + password: password1 + +api: + +i2s_audio: + i2s_lrclk_pin: 6 + i2s_bclk_pin: 7 + i2s_mclk_pin: 5 + +microphone: + - platform: i2s_audio + id: mic_id_external + i2s_din_pin: 3 + adc_type: external + pdm: false + +speaker: + - platform: i2s_audio + id: speaker_id + dac_type: external + i2s_dout_pin: 2 + mode: mono + +voice_assistant: + microphone: mic_id_external + speaker: speaker_id + on_listening: + - logger.log: "Voice assistant microphone listening" + on_start: + - logger.log: "Voice assistant started" + on_stt_end: + - logger.log: + format: "Voice assistant STT ended with result %s" + args: [x.c_str()] + on_tts_start: + - logger.log: + format: "Voice assistant TTS started with text %s" + args: [x.c_str()] + on_tts_end: + - logger.log: + format: "Voice assistant TTS ended with url %s" + args: [x.c_str()] + on_end: + - logger.log: "Voice assistant ended" + on_error: + - logger.log: + format: "Voice assistant error - code %s, message: %s" + args: [code.c_str(), message.c_str()] diff --git a/tests/components/voice_assistant/test.esp32-idf.yaml b/tests/components/voice_assistant/test.esp32-idf.yaml new file mode 100644 index 0000000000..2e0209311d --- /dev/null +++ b/tests/components/voice_assistant/test.esp32-idf.yaml @@ -0,0 +1,57 @@ +esphome: + on_boot: + then: + - voice_assistant.start + - voice_assistant.start_continuous + - voice_assistant.stop + +wifi: + ssid: MySSID + password: password1 + +api: + +i2s_audio: + i2s_lrclk_pin: 16 + i2s_bclk_pin: 17 + i2s_mclk_pin: 15 + +microphone: + - platform: i2s_audio + id: mic_id_external + i2s_din_pin: 13 + adc_type: external + pdm: false + +speaker: + - platform: i2s_audio + id: speaker_id + dac_type: external + i2s_dout_pin: 12 + mode: mono + +voice_assistant: + microphone: mic_id_external + speaker: speaker_id + on_listening: + - logger.log: "Voice assistant microphone listening" + on_start: + - logger.log: "Voice assistant started" + on_stt_end: + - logger.log: + format: "Voice assistant STT ended with result %s" + args: [x.c_str()] + on_tts_start: + - logger.log: + format: "Voice assistant TTS started with text %s" + args: [x.c_str()] + on_tts_end: + - logger.log: + format: "Voice assistant TTS ended with url %s" + args: [x.c_str()] + on_end: + - logger.log: "Voice assistant ended" + on_error: + - logger.log: + format: "Voice assistant error - code %s, message: %s" + args: [code.c_str(), message.c_str()] diff --git a/tests/components/voice_assistant/test.esp32.yaml b/tests/components/voice_assistant/test.esp32.yaml new file mode 100644 index 0000000000..2e0209311d --- /dev/null +++ b/tests/components/voice_assistant/test.esp32.yaml @@ -0,0 +1,57 @@ +esphome: + on_boot: + then: + - voice_assistant.start + - voice_assistant.start_continuous + - voice_assistant.stop + +wifi: + ssid: MySSID + password: password1 + +api: + +i2s_audio: + i2s_lrclk_pin: 16 + i2s_bclk_pin: 17 + i2s_mclk_pin: 15 + +microphone: + - platform: i2s_audio + id: mic_id_external + i2s_din_pin: 13 + adc_type: external + pdm: false + +speaker: + - platform: i2s_audio + id: speaker_id + dac_type: external + i2s_dout_pin: 12 + mode: mono + +voice_assistant: + microphone: mic_id_external + speaker: speaker_id + on_listening: + - logger.log: "Voice assistant microphone listening" + on_start: + - logger.log: "Voice assistant started" + on_stt_end: + - logger.log: + format: "Voice assistant STT ended with result %s" + args: [x.c_str()] + on_tts_start: + - logger.log: + format: "Voice assistant TTS started with text %s" + args: [x.c_str()] + on_tts_end: + - logger.log: + format: "Voice assistant TTS ended with url %s" + args: [x.c_str()] + on_end: + - logger.log: "Voice assistant ended" + on_error: + - logger.log: + format: "Voice assistant error - code %s, message: %s" + args: [code.c_str(), message.c_str()] From 95443a43540306ef68cf8ec3fe09cf8d83c92e8c Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Mon, 18 Mar 2024 18:49:00 -0500 Subject: [PATCH 1115/2101] Add some components to the new testing framework (X,Y,Z) (#6233) --- tests/components/x9c/test.esp32-c3-idf.yaml | 7 ++++ tests/components/x9c/test.esp32-c3.yaml | 7 ++++ tests/components/x9c/test.esp32-idf.yaml | 7 ++++ tests/components/x9c/test.esp32.yaml | 7 ++++ tests/components/x9c/test.esp8266.yaml | 7 ++++ tests/components/x9c/test.rp2040.yaml | 7 ++++ .../xgzp68xx/test.esp32-c3-idf.yaml | 12 +++++++ tests/components/xgzp68xx/test.esp32-c3.yaml | 12 +++++++ tests/components/xgzp68xx/test.esp32-idf.yaml | 12 +++++++ tests/components/xgzp68xx/test.esp32.yaml | 12 +++++++ tests/components/xgzp68xx/test.esp8266.yaml | 12 +++++++ tests/components/xgzp68xx/test.rp2040.yaml | 12 +++++++ .../xiaomi_ble/test.esp32-c3-idf.yaml | 3 ++ .../components/xiaomi_ble/test.esp32-c3.yaml | 3 ++ .../components/xiaomi_ble/test.esp32-idf.yaml | 3 ++ tests/components/xiaomi_ble/test.esp32.yaml | 3 ++ .../xiaomi_cgd1/test.esp32-c3-idf.yaml | 12 +++++++ .../components/xiaomi_cgd1/test.esp32-c3.yaml | 12 +++++++ .../xiaomi_cgd1/test.esp32-idf.yaml | 12 +++++++ tests/components/xiaomi_cgd1/test.esp32.yaml | 12 +++++++ .../xiaomi_cgdk2/test.esp32-c3-idf.yaml | 12 +++++++ .../xiaomi_cgdk2/test.esp32-c3.yaml | 12 +++++++ .../xiaomi_cgdk2/test.esp32-idf.yaml | 12 +++++++ tests/components/xiaomi_cgdk2/test.esp32.yaml | 12 +++++++ .../xiaomi_cgg1/test.esp32-c3-idf.yaml | 12 +++++++ .../components/xiaomi_cgg1/test.esp32-c3.yaml | 12 +++++++ .../xiaomi_cgg1/test.esp32-idf.yaml | 12 +++++++ tests/components/xiaomi_cgg1/test.esp32.yaml | 12 +++++++ .../xiaomi_cgpr1/test.esp32-c3-idf.yaml | 13 ++++++++ .../xiaomi_cgpr1/test.esp32-c3.yaml | 13 ++++++++ .../xiaomi_cgpr1/test.esp32-idf.yaml | 13 ++++++++ tests/components/xiaomi_cgpr1/test.esp32.yaml | 13 ++++++++ .../xiaomi_gcls002/test.esp32-c3-idf.yaml | 13 ++++++++ .../xiaomi_gcls002/test.esp32-c3.yaml | 13 ++++++++ .../xiaomi_gcls002/test.esp32-idf.yaml | 13 ++++++++ .../components/xiaomi_gcls002/test.esp32.yaml | 13 ++++++++ .../xiaomi_hhccjcy01/test.esp32-c3-idf.yaml | 15 +++++++++ .../xiaomi_hhccjcy01/test.esp32-c3.yaml | 15 +++++++++ .../xiaomi_hhccjcy01/test.esp32-idf.yaml | 15 +++++++++ .../xiaomi_hhccjcy01/test.esp32.yaml | 15 +++++++++ .../xiaomi_hhccpot002/test.esp32-c3-idf.yaml | 9 +++++ .../xiaomi_hhccpot002/test.esp32-c3.yaml | 9 +++++ .../xiaomi_hhccpot002/test.esp32-idf.yaml | 9 +++++ .../xiaomi_hhccpot002/test.esp32.yaml | 9 +++++ .../xiaomi_jqjcy01ym/test.esp32-c3-idf.yaml | 13 ++++++++ .../xiaomi_jqjcy01ym/test.esp32-c3.yaml | 13 ++++++++ .../xiaomi_jqjcy01ym/test.esp32-idf.yaml | 13 ++++++++ .../xiaomi_jqjcy01ym/test.esp32.yaml | 13 ++++++++ .../xiaomi_lywsd02/test.esp32-c3-idf.yaml | 11 +++++++ .../xiaomi_lywsd02/test.esp32-c3.yaml | 11 +++++++ .../xiaomi_lywsd02/test.esp32-idf.yaml | 11 +++++++ .../components/xiaomi_lywsd02/test.esp32.yaml | 11 +++++++ .../xiaomi_lywsd03mmc/test.esp32-c3-idf.yaml | 12 +++++++ .../xiaomi_lywsd03mmc/test.esp32-c3.yaml | 12 +++++++ .../xiaomi_lywsd03mmc/test.esp32-idf.yaml | 12 +++++++ .../xiaomi_lywsd03mmc/test.esp32.yaml | 12 +++++++ .../xiaomi_lywsdcgq/test.esp32-c3-idf.yaml | 11 +++++++ .../xiaomi_lywsdcgq/test.esp32-c3.yaml | 11 +++++++ .../xiaomi_lywsdcgq/test.esp32-idf.yaml | 11 +++++++ .../xiaomi_lywsdcgq/test.esp32.yaml | 11 +++++++ .../xiaomi_mhoc303/test.esp32-c3-idf.yaml | 11 +++++++ .../xiaomi_mhoc303/test.esp32-c3.yaml | 11 +++++++ .../xiaomi_mhoc303/test.esp32-idf.yaml | 11 +++++++ .../components/xiaomi_mhoc303/test.esp32.yaml | 11 +++++++ .../xiaomi_mhoc401/test.esp32-c3-idf.yaml | 12 +++++++ .../xiaomi_mhoc401/test.esp32-c3.yaml | 12 +++++++ .../xiaomi_mhoc401/test.esp32-idf.yaml | 12 +++++++ .../components/xiaomi_mhoc401/test.esp32.yaml | 12 +++++++ .../test.esp32-c3-idf.yaml | 9 +++++ .../xiaomi_miscale copy/test.esp32-c3.yaml | 9 +++++ .../xiaomi_miscale copy/test.esp32-idf.yaml | 9 +++++ .../xiaomi_miscale copy/test.esp32.yaml | 9 +++++ .../xiaomi_miscale/test.esp32-c3-idf.yaml | 9 +++++ .../xiaomi_miscale/test.esp32-c3.yaml | 9 +++++ .../xiaomi_miscale/test.esp32-idf.yaml | 9 +++++ .../components/xiaomi_miscale/test.esp32.yaml | 9 +++++ .../xiaomi_mjyd02yla/test.esp32-c3-idf.yaml | 13 ++++++++ .../xiaomi_mjyd02yla/test.esp32-c3.yaml | 13 ++++++++ .../xiaomi_mjyd02yla/test.esp32-idf.yaml | 13 ++++++++ .../xiaomi_mjyd02yla/test.esp32.yaml | 13 ++++++++ .../xiaomi_mue4094rt/test.esp32-c3-idf.yaml | 7 ++++ .../xiaomi_mue4094rt/test.esp32-c3.yaml | 7 ++++ .../xiaomi_mue4094rt/test.esp32-idf.yaml | 7 ++++ .../xiaomi_mue4094rt/test.esp32.yaml | 7 ++++ .../xiaomi_rtcgq02lm/test.esp32-c3-idf.yaml | 22 +++++++++++++ .../xiaomi_rtcgq02lm/test.esp32-c3.yaml | 22 +++++++++++++ .../xiaomi_rtcgq02lm/test.esp32-idf.yaml | 22 +++++++++++++ .../xiaomi_rtcgq02lm/test.esp32.yaml | 22 +++++++++++++ .../xiaomi_wx08zm/test.esp32-c3-idf.yaml | 10 ++++++ .../xiaomi_wx08zm/test.esp32-c3.yaml | 10 ++++++ .../xiaomi_wx08zm/test.esp32-idf.yaml | 10 ++++++ .../components/xiaomi_wx08zm/test.esp32.yaml | 10 ++++++ .../components/xl9535/test.esp32-c3-idf.yaml | 26 +++++++++++++++ tests/components/xl9535/test.esp32-c3.yaml | 26 +++++++++++++++ tests/components/xl9535/test.esp32-idf.yaml | 26 +++++++++++++++ tests/components/xl9535/test.esp32.yaml | 26 +++++++++++++++ tests/components/xl9535/test.esp8266.yaml | 26 +++++++++++++++ tests/components/xl9535/test.rp2040.yaml | 26 +++++++++++++++ .../components/xpt2046/test.esp32-c3-idf.yaml | 33 +++++++++++++++++++ tests/components/xpt2046/test.esp32-c3.yaml | 33 +++++++++++++++++++ tests/components/xpt2046/test.esp32-idf.yaml | 33 +++++++++++++++++++ tests/components/xpt2046/test.esp32.yaml | 33 +++++++++++++++++++ tests/components/xpt2046/test.esp8266.yaml | 33 +++++++++++++++++++ tests/components/xpt2046/test.rp2040.yaml | 33 +++++++++++++++++++ .../components/yashima/test.esp32-c3-idf.yaml | 7 ++++ tests/components/yashima/test.esp32-c3.yaml | 7 ++++ tests/components/yashima/test.esp32-idf.yaml | 7 ++++ tests/components/yashima/test.esp32.yaml | 7 ++++ tests/components/yashima/test.esp8266.yaml | 7 ++++ .../components/zhlt01/test.esp32-c3-idf.yaml | 7 ++++ tests/components/zhlt01/test.esp32-c3.yaml | 7 ++++ tests/components/zhlt01/test.esp32-idf.yaml | 7 ++++ tests/components/zhlt01/test.esp32.yaml | 7 ++++ tests/components/zhlt01/test.esp8266.yaml | 7 ++++ .../zio_ultrasonic/test.esp32-c3-idf.yaml | 9 +++++ .../zio_ultrasonic/test.esp32-c3.yaml | 9 +++++ .../zio_ultrasonic/test.esp32-idf.yaml | 9 +++++ .../components/zio_ultrasonic/test.esp32.yaml | 9 +++++ .../zio_ultrasonic/test.esp8266.yaml | 9 +++++ .../zio_ultrasonic/test.rp2040.yaml | 9 +++++ .../components/zyaura/test.esp32-c3-idf.yaml | 10 ++++++ tests/components/zyaura/test.esp32-c3.yaml | 10 ++++++ tests/components/zyaura/test.esp32-idf.yaml | 10 ++++++ tests/components/zyaura/test.esp32.yaml | 10 ++++++ tests/components/zyaura/test.esp8266.yaml | 10 ++++++ tests/components/zyaura/test.rp2040.yaml | 10 ++++++ 126 files changed, 1568 insertions(+) create mode 100644 tests/components/x9c/test.esp32-c3-idf.yaml create mode 100644 tests/components/x9c/test.esp32-c3.yaml create mode 100644 tests/components/x9c/test.esp32-idf.yaml create mode 100644 tests/components/x9c/test.esp32.yaml create mode 100644 tests/components/x9c/test.esp8266.yaml create mode 100644 tests/components/x9c/test.rp2040.yaml create mode 100644 tests/components/xgzp68xx/test.esp32-c3-idf.yaml create mode 100644 tests/components/xgzp68xx/test.esp32-c3.yaml create mode 100644 tests/components/xgzp68xx/test.esp32-idf.yaml create mode 100644 tests/components/xgzp68xx/test.esp32.yaml create mode 100644 tests/components/xgzp68xx/test.esp8266.yaml create mode 100644 tests/components/xgzp68xx/test.rp2040.yaml create mode 100644 tests/components/xiaomi_ble/test.esp32-c3-idf.yaml create mode 100644 tests/components/xiaomi_ble/test.esp32-c3.yaml create mode 100644 tests/components/xiaomi_ble/test.esp32-idf.yaml create mode 100644 tests/components/xiaomi_ble/test.esp32.yaml create mode 100644 tests/components/xiaomi_cgd1/test.esp32-c3-idf.yaml create mode 100644 tests/components/xiaomi_cgd1/test.esp32-c3.yaml create mode 100644 tests/components/xiaomi_cgd1/test.esp32-idf.yaml create mode 100644 tests/components/xiaomi_cgd1/test.esp32.yaml create mode 100644 tests/components/xiaomi_cgdk2/test.esp32-c3-idf.yaml create mode 100644 tests/components/xiaomi_cgdk2/test.esp32-c3.yaml create mode 100644 tests/components/xiaomi_cgdk2/test.esp32-idf.yaml create mode 100644 tests/components/xiaomi_cgdk2/test.esp32.yaml create mode 100644 tests/components/xiaomi_cgg1/test.esp32-c3-idf.yaml create mode 100644 tests/components/xiaomi_cgg1/test.esp32-c3.yaml create mode 100644 tests/components/xiaomi_cgg1/test.esp32-idf.yaml create mode 100644 tests/components/xiaomi_cgg1/test.esp32.yaml create mode 100644 tests/components/xiaomi_cgpr1/test.esp32-c3-idf.yaml create mode 100644 tests/components/xiaomi_cgpr1/test.esp32-c3.yaml create mode 100644 tests/components/xiaomi_cgpr1/test.esp32-idf.yaml create mode 100644 tests/components/xiaomi_cgpr1/test.esp32.yaml create mode 100644 tests/components/xiaomi_gcls002/test.esp32-c3-idf.yaml create mode 100644 tests/components/xiaomi_gcls002/test.esp32-c3.yaml create mode 100644 tests/components/xiaomi_gcls002/test.esp32-idf.yaml create mode 100644 tests/components/xiaomi_gcls002/test.esp32.yaml create mode 100644 tests/components/xiaomi_hhccjcy01/test.esp32-c3-idf.yaml create mode 100644 tests/components/xiaomi_hhccjcy01/test.esp32-c3.yaml create mode 100644 tests/components/xiaomi_hhccjcy01/test.esp32-idf.yaml create mode 100644 tests/components/xiaomi_hhccjcy01/test.esp32.yaml create mode 100644 tests/components/xiaomi_hhccpot002/test.esp32-c3-idf.yaml create mode 100644 tests/components/xiaomi_hhccpot002/test.esp32-c3.yaml create mode 100644 tests/components/xiaomi_hhccpot002/test.esp32-idf.yaml create mode 100644 tests/components/xiaomi_hhccpot002/test.esp32.yaml create mode 100644 tests/components/xiaomi_jqjcy01ym/test.esp32-c3-idf.yaml create mode 100644 tests/components/xiaomi_jqjcy01ym/test.esp32-c3.yaml create mode 100644 tests/components/xiaomi_jqjcy01ym/test.esp32-idf.yaml create mode 100644 tests/components/xiaomi_jqjcy01ym/test.esp32.yaml create mode 100644 tests/components/xiaomi_lywsd02/test.esp32-c3-idf.yaml create mode 100644 tests/components/xiaomi_lywsd02/test.esp32-c3.yaml create mode 100644 tests/components/xiaomi_lywsd02/test.esp32-idf.yaml create mode 100644 tests/components/xiaomi_lywsd02/test.esp32.yaml create mode 100644 tests/components/xiaomi_lywsd03mmc/test.esp32-c3-idf.yaml create mode 100644 tests/components/xiaomi_lywsd03mmc/test.esp32-c3.yaml create mode 100644 tests/components/xiaomi_lywsd03mmc/test.esp32-idf.yaml create mode 100644 tests/components/xiaomi_lywsd03mmc/test.esp32.yaml create mode 100644 tests/components/xiaomi_lywsdcgq/test.esp32-c3-idf.yaml create mode 100644 tests/components/xiaomi_lywsdcgq/test.esp32-c3.yaml create mode 100644 tests/components/xiaomi_lywsdcgq/test.esp32-idf.yaml create mode 100644 tests/components/xiaomi_lywsdcgq/test.esp32.yaml create mode 100644 tests/components/xiaomi_mhoc303/test.esp32-c3-idf.yaml create mode 100644 tests/components/xiaomi_mhoc303/test.esp32-c3.yaml create mode 100644 tests/components/xiaomi_mhoc303/test.esp32-idf.yaml create mode 100644 tests/components/xiaomi_mhoc303/test.esp32.yaml create mode 100644 tests/components/xiaomi_mhoc401/test.esp32-c3-idf.yaml create mode 100644 tests/components/xiaomi_mhoc401/test.esp32-c3.yaml create mode 100644 tests/components/xiaomi_mhoc401/test.esp32-idf.yaml create mode 100644 tests/components/xiaomi_mhoc401/test.esp32.yaml create mode 100644 tests/components/xiaomi_miscale copy/test.esp32-c3-idf.yaml create mode 100644 tests/components/xiaomi_miscale copy/test.esp32-c3.yaml create mode 100644 tests/components/xiaomi_miscale copy/test.esp32-idf.yaml create mode 100644 tests/components/xiaomi_miscale copy/test.esp32.yaml create mode 100644 tests/components/xiaomi_miscale/test.esp32-c3-idf.yaml create mode 100644 tests/components/xiaomi_miscale/test.esp32-c3.yaml create mode 100644 tests/components/xiaomi_miscale/test.esp32-idf.yaml create mode 100644 tests/components/xiaomi_miscale/test.esp32.yaml create mode 100644 tests/components/xiaomi_mjyd02yla/test.esp32-c3-idf.yaml create mode 100644 tests/components/xiaomi_mjyd02yla/test.esp32-c3.yaml create mode 100644 tests/components/xiaomi_mjyd02yla/test.esp32-idf.yaml create mode 100644 tests/components/xiaomi_mjyd02yla/test.esp32.yaml create mode 100644 tests/components/xiaomi_mue4094rt/test.esp32-c3-idf.yaml create mode 100644 tests/components/xiaomi_mue4094rt/test.esp32-c3.yaml create mode 100644 tests/components/xiaomi_mue4094rt/test.esp32-idf.yaml create mode 100644 tests/components/xiaomi_mue4094rt/test.esp32.yaml create mode 100644 tests/components/xiaomi_rtcgq02lm/test.esp32-c3-idf.yaml create mode 100644 tests/components/xiaomi_rtcgq02lm/test.esp32-c3.yaml create mode 100644 tests/components/xiaomi_rtcgq02lm/test.esp32-idf.yaml create mode 100644 tests/components/xiaomi_rtcgq02lm/test.esp32.yaml create mode 100644 tests/components/xiaomi_wx08zm/test.esp32-c3-idf.yaml create mode 100644 tests/components/xiaomi_wx08zm/test.esp32-c3.yaml create mode 100644 tests/components/xiaomi_wx08zm/test.esp32-idf.yaml create mode 100644 tests/components/xiaomi_wx08zm/test.esp32.yaml create mode 100644 tests/components/xl9535/test.esp32-c3-idf.yaml create mode 100644 tests/components/xl9535/test.esp32-c3.yaml create mode 100644 tests/components/xl9535/test.esp32-idf.yaml create mode 100644 tests/components/xl9535/test.esp32.yaml create mode 100644 tests/components/xl9535/test.esp8266.yaml create mode 100644 tests/components/xl9535/test.rp2040.yaml create mode 100644 tests/components/xpt2046/test.esp32-c3-idf.yaml create mode 100644 tests/components/xpt2046/test.esp32-c3.yaml create mode 100644 tests/components/xpt2046/test.esp32-idf.yaml create mode 100644 tests/components/xpt2046/test.esp32.yaml create mode 100644 tests/components/xpt2046/test.esp8266.yaml create mode 100644 tests/components/xpt2046/test.rp2040.yaml create mode 100644 tests/components/yashima/test.esp32-c3-idf.yaml create mode 100644 tests/components/yashima/test.esp32-c3.yaml create mode 100644 tests/components/yashima/test.esp32-idf.yaml create mode 100644 tests/components/yashima/test.esp32.yaml create mode 100644 tests/components/yashima/test.esp8266.yaml create mode 100644 tests/components/zhlt01/test.esp32-c3-idf.yaml create mode 100644 tests/components/zhlt01/test.esp32-c3.yaml create mode 100644 tests/components/zhlt01/test.esp32-idf.yaml create mode 100644 tests/components/zhlt01/test.esp32.yaml create mode 100644 tests/components/zhlt01/test.esp8266.yaml create mode 100644 tests/components/zio_ultrasonic/test.esp32-c3-idf.yaml create mode 100644 tests/components/zio_ultrasonic/test.esp32-c3.yaml create mode 100644 tests/components/zio_ultrasonic/test.esp32-idf.yaml create mode 100644 tests/components/zio_ultrasonic/test.esp32.yaml create mode 100644 tests/components/zio_ultrasonic/test.esp8266.yaml create mode 100644 tests/components/zio_ultrasonic/test.rp2040.yaml create mode 100644 tests/components/zyaura/test.esp32-c3-idf.yaml create mode 100644 tests/components/zyaura/test.esp32-c3.yaml create mode 100644 tests/components/zyaura/test.esp32-idf.yaml create mode 100644 tests/components/zyaura/test.esp32.yaml create mode 100644 tests/components/zyaura/test.esp8266.yaml create mode 100644 tests/components/zyaura/test.rp2040.yaml diff --git a/tests/components/x9c/test.esp32-c3-idf.yaml b/tests/components/x9c/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..a0480aa68f --- /dev/null +++ b/tests/components/x9c/test.esp32-c3-idf.yaml @@ -0,0 +1,7 @@ +output: + - platform: x9c + id: test_x9c + cs_pin: 3 + inc_pin: 4 + ud_pin: 5 + initial_value: 0.5 diff --git a/tests/components/x9c/test.esp32-c3.yaml b/tests/components/x9c/test.esp32-c3.yaml new file mode 100644 index 0000000000..a0480aa68f --- /dev/null +++ b/tests/components/x9c/test.esp32-c3.yaml @@ -0,0 +1,7 @@ +output: + - platform: x9c + id: test_x9c + cs_pin: 3 + inc_pin: 4 + ud_pin: 5 + initial_value: 0.5 diff --git a/tests/components/x9c/test.esp32-idf.yaml b/tests/components/x9c/test.esp32-idf.yaml new file mode 100644 index 0000000000..28b18f7a92 --- /dev/null +++ b/tests/components/x9c/test.esp32-idf.yaml @@ -0,0 +1,7 @@ +output: + - platform: x9c + id: test_x9c + cs_pin: 13 + inc_pin: 14 + ud_pin: 15 + initial_value: 0.5 diff --git a/tests/components/x9c/test.esp32.yaml b/tests/components/x9c/test.esp32.yaml new file mode 100644 index 0000000000..28b18f7a92 --- /dev/null +++ b/tests/components/x9c/test.esp32.yaml @@ -0,0 +1,7 @@ +output: + - platform: x9c + id: test_x9c + cs_pin: 13 + inc_pin: 14 + ud_pin: 15 + initial_value: 0.5 diff --git a/tests/components/x9c/test.esp8266.yaml b/tests/components/x9c/test.esp8266.yaml new file mode 100644 index 0000000000..28b18f7a92 --- /dev/null +++ b/tests/components/x9c/test.esp8266.yaml @@ -0,0 +1,7 @@ +output: + - platform: x9c + id: test_x9c + cs_pin: 13 + inc_pin: 14 + ud_pin: 15 + initial_value: 0.5 diff --git a/tests/components/x9c/test.rp2040.yaml b/tests/components/x9c/test.rp2040.yaml new file mode 100644 index 0000000000..a0480aa68f --- /dev/null +++ b/tests/components/x9c/test.rp2040.yaml @@ -0,0 +1,7 @@ +output: + - platform: x9c + id: test_x9c + cs_pin: 3 + inc_pin: 4 + ud_pin: 5 + initial_value: 0.5 diff --git a/tests/components/xgzp68xx/test.esp32-c3-idf.yaml b/tests/components/xgzp68xx/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..25df8cc225 --- /dev/null +++ b/tests/components/xgzp68xx/test.esp32-c3-idf.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_xgzp68xx + scl: 5 + sda: 4 + +sensor: + - platform: xgzp68xx + k_value: 4096 + temperature: + name: Pressure Temperature + pressure: + name: Differential pressure diff --git a/tests/components/xgzp68xx/test.esp32-c3.yaml b/tests/components/xgzp68xx/test.esp32-c3.yaml new file mode 100644 index 0000000000..25df8cc225 --- /dev/null +++ b/tests/components/xgzp68xx/test.esp32-c3.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_xgzp68xx + scl: 5 + sda: 4 + +sensor: + - platform: xgzp68xx + k_value: 4096 + temperature: + name: Pressure Temperature + pressure: + name: Differential pressure diff --git a/tests/components/xgzp68xx/test.esp32-idf.yaml b/tests/components/xgzp68xx/test.esp32-idf.yaml new file mode 100644 index 0000000000..fb55421123 --- /dev/null +++ b/tests/components/xgzp68xx/test.esp32-idf.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_xgzp68xx + scl: 16 + sda: 17 + +sensor: + - platform: xgzp68xx + k_value: 4096 + temperature: + name: Pressure Temperature + pressure: + name: Differential pressure diff --git a/tests/components/xgzp68xx/test.esp32.yaml b/tests/components/xgzp68xx/test.esp32.yaml new file mode 100644 index 0000000000..fb55421123 --- /dev/null +++ b/tests/components/xgzp68xx/test.esp32.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_xgzp68xx + scl: 16 + sda: 17 + +sensor: + - platform: xgzp68xx + k_value: 4096 + temperature: + name: Pressure Temperature + pressure: + name: Differential pressure diff --git a/tests/components/xgzp68xx/test.esp8266.yaml b/tests/components/xgzp68xx/test.esp8266.yaml new file mode 100644 index 0000000000..25df8cc225 --- /dev/null +++ b/tests/components/xgzp68xx/test.esp8266.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_xgzp68xx + scl: 5 + sda: 4 + +sensor: + - platform: xgzp68xx + k_value: 4096 + temperature: + name: Pressure Temperature + pressure: + name: Differential pressure diff --git a/tests/components/xgzp68xx/test.rp2040.yaml b/tests/components/xgzp68xx/test.rp2040.yaml new file mode 100644 index 0000000000..25df8cc225 --- /dev/null +++ b/tests/components/xgzp68xx/test.rp2040.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_xgzp68xx + scl: 5 + sda: 4 + +sensor: + - platform: xgzp68xx + k_value: 4096 + temperature: + name: Pressure Temperature + pressure: + name: Differential pressure diff --git a/tests/components/xiaomi_ble/test.esp32-c3-idf.yaml b/tests/components/xiaomi_ble/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..9d10393177 --- /dev/null +++ b/tests/components/xiaomi_ble/test.esp32-c3-idf.yaml @@ -0,0 +1,3 @@ +esp32_ble_tracker: + +xiaomi_ble: diff --git a/tests/components/xiaomi_ble/test.esp32-c3.yaml b/tests/components/xiaomi_ble/test.esp32-c3.yaml new file mode 100644 index 0000000000..9d10393177 --- /dev/null +++ b/tests/components/xiaomi_ble/test.esp32-c3.yaml @@ -0,0 +1,3 @@ +esp32_ble_tracker: + +xiaomi_ble: diff --git a/tests/components/xiaomi_ble/test.esp32-idf.yaml b/tests/components/xiaomi_ble/test.esp32-idf.yaml new file mode 100644 index 0000000000..9d10393177 --- /dev/null +++ b/tests/components/xiaomi_ble/test.esp32-idf.yaml @@ -0,0 +1,3 @@ +esp32_ble_tracker: + +xiaomi_ble: diff --git a/tests/components/xiaomi_ble/test.esp32.yaml b/tests/components/xiaomi_ble/test.esp32.yaml new file mode 100644 index 0000000000..9d10393177 --- /dev/null +++ b/tests/components/xiaomi_ble/test.esp32.yaml @@ -0,0 +1,3 @@ +esp32_ble_tracker: + +xiaomi_ble: diff --git a/tests/components/xiaomi_cgd1/test.esp32-c3-idf.yaml b/tests/components/xiaomi_cgd1/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..94ed09e8f2 --- /dev/null +++ b/tests/components/xiaomi_cgd1/test.esp32-c3-idf.yaml @@ -0,0 +1,12 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_cgd1 + mac_address: A4:C1:38:D1:61:7D + bindkey: c99d2313182473b38001086febf781bd + temperature: + name: Xiaomi CGD1 Temperature + humidity: + name: Xiaomi CGD1 Humidity + battery_level: + name: Xiaomi CGD1 Battery Level diff --git a/tests/components/xiaomi_cgd1/test.esp32-c3.yaml b/tests/components/xiaomi_cgd1/test.esp32-c3.yaml new file mode 100644 index 0000000000..94ed09e8f2 --- /dev/null +++ b/tests/components/xiaomi_cgd1/test.esp32-c3.yaml @@ -0,0 +1,12 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_cgd1 + mac_address: A4:C1:38:D1:61:7D + bindkey: c99d2313182473b38001086febf781bd + temperature: + name: Xiaomi CGD1 Temperature + humidity: + name: Xiaomi CGD1 Humidity + battery_level: + name: Xiaomi CGD1 Battery Level diff --git a/tests/components/xiaomi_cgd1/test.esp32-idf.yaml b/tests/components/xiaomi_cgd1/test.esp32-idf.yaml new file mode 100644 index 0000000000..94ed09e8f2 --- /dev/null +++ b/tests/components/xiaomi_cgd1/test.esp32-idf.yaml @@ -0,0 +1,12 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_cgd1 + mac_address: A4:C1:38:D1:61:7D + bindkey: c99d2313182473b38001086febf781bd + temperature: + name: Xiaomi CGD1 Temperature + humidity: + name: Xiaomi CGD1 Humidity + battery_level: + name: Xiaomi CGD1 Battery Level diff --git a/tests/components/xiaomi_cgd1/test.esp32.yaml b/tests/components/xiaomi_cgd1/test.esp32.yaml new file mode 100644 index 0000000000..94ed09e8f2 --- /dev/null +++ b/tests/components/xiaomi_cgd1/test.esp32.yaml @@ -0,0 +1,12 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_cgd1 + mac_address: A4:C1:38:D1:61:7D + bindkey: c99d2313182473b38001086febf781bd + temperature: + name: Xiaomi CGD1 Temperature + humidity: + name: Xiaomi CGD1 Humidity + battery_level: + name: Xiaomi CGD1 Battery Level diff --git a/tests/components/xiaomi_cgdk2/test.esp32-c3-idf.yaml b/tests/components/xiaomi_cgdk2/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..dddca56222 --- /dev/null +++ b/tests/components/xiaomi_cgdk2/test.esp32-c3-idf.yaml @@ -0,0 +1,12 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_cgdk2 + mac_address: A4:C1:38:D1:61:7D + bindkey: c99d2313182473b38001086febf781bd + temperature: + name: Xiaomi CGD1 Temperature + humidity: + name: Xiaomi CGD1 Humidity + battery_level: + name: Xiaomi CGD1 Battery Level diff --git a/tests/components/xiaomi_cgdk2/test.esp32-c3.yaml b/tests/components/xiaomi_cgdk2/test.esp32-c3.yaml new file mode 100644 index 0000000000..dddca56222 --- /dev/null +++ b/tests/components/xiaomi_cgdk2/test.esp32-c3.yaml @@ -0,0 +1,12 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_cgdk2 + mac_address: A4:C1:38:D1:61:7D + bindkey: c99d2313182473b38001086febf781bd + temperature: + name: Xiaomi CGD1 Temperature + humidity: + name: Xiaomi CGD1 Humidity + battery_level: + name: Xiaomi CGD1 Battery Level diff --git a/tests/components/xiaomi_cgdk2/test.esp32-idf.yaml b/tests/components/xiaomi_cgdk2/test.esp32-idf.yaml new file mode 100644 index 0000000000..dddca56222 --- /dev/null +++ b/tests/components/xiaomi_cgdk2/test.esp32-idf.yaml @@ -0,0 +1,12 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_cgdk2 + mac_address: A4:C1:38:D1:61:7D + bindkey: c99d2313182473b38001086febf781bd + temperature: + name: Xiaomi CGD1 Temperature + humidity: + name: Xiaomi CGD1 Humidity + battery_level: + name: Xiaomi CGD1 Battery Level diff --git a/tests/components/xiaomi_cgdk2/test.esp32.yaml b/tests/components/xiaomi_cgdk2/test.esp32.yaml new file mode 100644 index 0000000000..dddca56222 --- /dev/null +++ b/tests/components/xiaomi_cgdk2/test.esp32.yaml @@ -0,0 +1,12 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_cgdk2 + mac_address: A4:C1:38:D1:61:7D + bindkey: c99d2313182473b38001086febf781bd + temperature: + name: Xiaomi CGD1 Temperature + humidity: + name: Xiaomi CGD1 Humidity + battery_level: + name: Xiaomi CGD1 Battery Level diff --git a/tests/components/xiaomi_cgg1/test.esp32-c3-idf.yaml b/tests/components/xiaomi_cgg1/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..170aebfbde --- /dev/null +++ b/tests/components/xiaomi_cgg1/test.esp32-c3-idf.yaml @@ -0,0 +1,12 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_cgg1 + mac_address: A4:C1:38:D1:61:7D + bindkey: c99d2313182473b38001086febf781bd + temperature: + name: Xiaomi CGD1 Temperature + humidity: + name: Xiaomi CGD1 Humidity + battery_level: + name: Xiaomi CGD1 Battery Level diff --git a/tests/components/xiaomi_cgg1/test.esp32-c3.yaml b/tests/components/xiaomi_cgg1/test.esp32-c3.yaml new file mode 100644 index 0000000000..170aebfbde --- /dev/null +++ b/tests/components/xiaomi_cgg1/test.esp32-c3.yaml @@ -0,0 +1,12 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_cgg1 + mac_address: A4:C1:38:D1:61:7D + bindkey: c99d2313182473b38001086febf781bd + temperature: + name: Xiaomi CGD1 Temperature + humidity: + name: Xiaomi CGD1 Humidity + battery_level: + name: Xiaomi CGD1 Battery Level diff --git a/tests/components/xiaomi_cgg1/test.esp32-idf.yaml b/tests/components/xiaomi_cgg1/test.esp32-idf.yaml new file mode 100644 index 0000000000..170aebfbde --- /dev/null +++ b/tests/components/xiaomi_cgg1/test.esp32-idf.yaml @@ -0,0 +1,12 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_cgg1 + mac_address: A4:C1:38:D1:61:7D + bindkey: c99d2313182473b38001086febf781bd + temperature: + name: Xiaomi CGD1 Temperature + humidity: + name: Xiaomi CGD1 Humidity + battery_level: + name: Xiaomi CGD1 Battery Level diff --git a/tests/components/xiaomi_cgg1/test.esp32.yaml b/tests/components/xiaomi_cgg1/test.esp32.yaml new file mode 100644 index 0000000000..170aebfbde --- /dev/null +++ b/tests/components/xiaomi_cgg1/test.esp32.yaml @@ -0,0 +1,12 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_cgg1 + mac_address: A4:C1:38:D1:61:7D + bindkey: c99d2313182473b38001086febf781bd + temperature: + name: Xiaomi CGD1 Temperature + humidity: + name: Xiaomi CGD1 Humidity + battery_level: + name: Xiaomi CGD1 Battery Level diff --git a/tests/components/xiaomi_cgpr1/test.esp32-c3-idf.yaml b/tests/components/xiaomi_cgpr1/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..48082a886c --- /dev/null +++ b/tests/components/xiaomi_cgpr1/test.esp32-c3-idf.yaml @@ -0,0 +1,13 @@ +esp32_ble_tracker: + +binary_sensor: + - platform: xiaomi_cgpr1 + name: CGPR1 Motion + mac_address: "12:34:56:12:34:56" + bindkey: 48403ebe2d385db8d0c187f81e62cb64 + battery_level: + name: CGPR1 battery Level + idle_time: + name: CGPR1 Idle Time + illuminance: + name: CGPR1 Illuminance diff --git a/tests/components/xiaomi_cgpr1/test.esp32-c3.yaml b/tests/components/xiaomi_cgpr1/test.esp32-c3.yaml new file mode 100644 index 0000000000..48082a886c --- /dev/null +++ b/tests/components/xiaomi_cgpr1/test.esp32-c3.yaml @@ -0,0 +1,13 @@ +esp32_ble_tracker: + +binary_sensor: + - platform: xiaomi_cgpr1 + name: CGPR1 Motion + mac_address: "12:34:56:12:34:56" + bindkey: 48403ebe2d385db8d0c187f81e62cb64 + battery_level: + name: CGPR1 battery Level + idle_time: + name: CGPR1 Idle Time + illuminance: + name: CGPR1 Illuminance diff --git a/tests/components/xiaomi_cgpr1/test.esp32-idf.yaml b/tests/components/xiaomi_cgpr1/test.esp32-idf.yaml new file mode 100644 index 0000000000..48082a886c --- /dev/null +++ b/tests/components/xiaomi_cgpr1/test.esp32-idf.yaml @@ -0,0 +1,13 @@ +esp32_ble_tracker: + +binary_sensor: + - platform: xiaomi_cgpr1 + name: CGPR1 Motion + mac_address: "12:34:56:12:34:56" + bindkey: 48403ebe2d385db8d0c187f81e62cb64 + battery_level: + name: CGPR1 battery Level + idle_time: + name: CGPR1 Idle Time + illuminance: + name: CGPR1 Illuminance diff --git a/tests/components/xiaomi_cgpr1/test.esp32.yaml b/tests/components/xiaomi_cgpr1/test.esp32.yaml new file mode 100644 index 0000000000..48082a886c --- /dev/null +++ b/tests/components/xiaomi_cgpr1/test.esp32.yaml @@ -0,0 +1,13 @@ +esp32_ble_tracker: + +binary_sensor: + - platform: xiaomi_cgpr1 + name: CGPR1 Motion + mac_address: "12:34:56:12:34:56" + bindkey: 48403ebe2d385db8d0c187f81e62cb64 + battery_level: + name: CGPR1 battery Level + idle_time: + name: CGPR1 Idle Time + illuminance: + name: CGPR1 Illuminance diff --git a/tests/components/xiaomi_gcls002/test.esp32-c3-idf.yaml b/tests/components/xiaomi_gcls002/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..32990708cc --- /dev/null +++ b/tests/components/xiaomi_gcls002/test.esp32-c3-idf.yaml @@ -0,0 +1,13 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_gcls002 + mac_address: 94:2B:FF:5C:91:61 + temperature: + name: GCLS02 Temperature + moisture: + name: GCLS02 Moisture + conductivity: + name: GCLS02 Soil Conductivity + illuminance: + name: GCLS02 Illuminance diff --git a/tests/components/xiaomi_gcls002/test.esp32-c3.yaml b/tests/components/xiaomi_gcls002/test.esp32-c3.yaml new file mode 100644 index 0000000000..32990708cc --- /dev/null +++ b/tests/components/xiaomi_gcls002/test.esp32-c3.yaml @@ -0,0 +1,13 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_gcls002 + mac_address: 94:2B:FF:5C:91:61 + temperature: + name: GCLS02 Temperature + moisture: + name: GCLS02 Moisture + conductivity: + name: GCLS02 Soil Conductivity + illuminance: + name: GCLS02 Illuminance diff --git a/tests/components/xiaomi_gcls002/test.esp32-idf.yaml b/tests/components/xiaomi_gcls002/test.esp32-idf.yaml new file mode 100644 index 0000000000..32990708cc --- /dev/null +++ b/tests/components/xiaomi_gcls002/test.esp32-idf.yaml @@ -0,0 +1,13 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_gcls002 + mac_address: 94:2B:FF:5C:91:61 + temperature: + name: GCLS02 Temperature + moisture: + name: GCLS02 Moisture + conductivity: + name: GCLS02 Soil Conductivity + illuminance: + name: GCLS02 Illuminance diff --git a/tests/components/xiaomi_gcls002/test.esp32.yaml b/tests/components/xiaomi_gcls002/test.esp32.yaml new file mode 100644 index 0000000000..32990708cc --- /dev/null +++ b/tests/components/xiaomi_gcls002/test.esp32.yaml @@ -0,0 +1,13 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_gcls002 + mac_address: 94:2B:FF:5C:91:61 + temperature: + name: GCLS02 Temperature + moisture: + name: GCLS02 Moisture + conductivity: + name: GCLS02 Soil Conductivity + illuminance: + name: GCLS02 Illuminance diff --git a/tests/components/xiaomi_hhccjcy01/test.esp32-c3-idf.yaml b/tests/components/xiaomi_hhccjcy01/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..0def909488 --- /dev/null +++ b/tests/components/xiaomi_hhccjcy01/test.esp32-c3-idf.yaml @@ -0,0 +1,15 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_hhccjcy01 + mac_address: 94:2B:FF:5C:91:61 + temperature: + name: Xiaomi HHCCJCY01 Temperature + moisture: + name: Xiaomi HHCCJCY01 Moisture + illuminance: + name: Xiaomi HHCCJCY01 Illuminance + conductivity: + name: Xiaomi HHCCJCY01 Soil Conductivity + battery_level: + name: Xiaomi HHCCJCY01 Battery Level diff --git a/tests/components/xiaomi_hhccjcy01/test.esp32-c3.yaml b/tests/components/xiaomi_hhccjcy01/test.esp32-c3.yaml new file mode 100644 index 0000000000..0def909488 --- /dev/null +++ b/tests/components/xiaomi_hhccjcy01/test.esp32-c3.yaml @@ -0,0 +1,15 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_hhccjcy01 + mac_address: 94:2B:FF:5C:91:61 + temperature: + name: Xiaomi HHCCJCY01 Temperature + moisture: + name: Xiaomi HHCCJCY01 Moisture + illuminance: + name: Xiaomi HHCCJCY01 Illuminance + conductivity: + name: Xiaomi HHCCJCY01 Soil Conductivity + battery_level: + name: Xiaomi HHCCJCY01 Battery Level diff --git a/tests/components/xiaomi_hhccjcy01/test.esp32-idf.yaml b/tests/components/xiaomi_hhccjcy01/test.esp32-idf.yaml new file mode 100644 index 0000000000..0def909488 --- /dev/null +++ b/tests/components/xiaomi_hhccjcy01/test.esp32-idf.yaml @@ -0,0 +1,15 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_hhccjcy01 + mac_address: 94:2B:FF:5C:91:61 + temperature: + name: Xiaomi HHCCJCY01 Temperature + moisture: + name: Xiaomi HHCCJCY01 Moisture + illuminance: + name: Xiaomi HHCCJCY01 Illuminance + conductivity: + name: Xiaomi HHCCJCY01 Soil Conductivity + battery_level: + name: Xiaomi HHCCJCY01 Battery Level diff --git a/tests/components/xiaomi_hhccjcy01/test.esp32.yaml b/tests/components/xiaomi_hhccjcy01/test.esp32.yaml new file mode 100644 index 0000000000..0def909488 --- /dev/null +++ b/tests/components/xiaomi_hhccjcy01/test.esp32.yaml @@ -0,0 +1,15 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_hhccjcy01 + mac_address: 94:2B:FF:5C:91:61 + temperature: + name: Xiaomi HHCCJCY01 Temperature + moisture: + name: Xiaomi HHCCJCY01 Moisture + illuminance: + name: Xiaomi HHCCJCY01 Illuminance + conductivity: + name: Xiaomi HHCCJCY01 Soil Conductivity + battery_level: + name: Xiaomi HHCCJCY01 Battery Level diff --git a/tests/components/xiaomi_hhccpot002/test.esp32-c3-idf.yaml b/tests/components/xiaomi_hhccpot002/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..2e5fa14620 --- /dev/null +++ b/tests/components/xiaomi_hhccpot002/test.esp32-c3-idf.yaml @@ -0,0 +1,9 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_hhccpot002 + mac_address: 94:2B:FF:5C:91:61 + moisture: + name: HHCCPOT002 Moisture + conductivity: + name: HHCCPOT002 Soil Conductivity diff --git a/tests/components/xiaomi_hhccpot002/test.esp32-c3.yaml b/tests/components/xiaomi_hhccpot002/test.esp32-c3.yaml new file mode 100644 index 0000000000..2e5fa14620 --- /dev/null +++ b/tests/components/xiaomi_hhccpot002/test.esp32-c3.yaml @@ -0,0 +1,9 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_hhccpot002 + mac_address: 94:2B:FF:5C:91:61 + moisture: + name: HHCCPOT002 Moisture + conductivity: + name: HHCCPOT002 Soil Conductivity diff --git a/tests/components/xiaomi_hhccpot002/test.esp32-idf.yaml b/tests/components/xiaomi_hhccpot002/test.esp32-idf.yaml new file mode 100644 index 0000000000..2e5fa14620 --- /dev/null +++ b/tests/components/xiaomi_hhccpot002/test.esp32-idf.yaml @@ -0,0 +1,9 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_hhccpot002 + mac_address: 94:2B:FF:5C:91:61 + moisture: + name: HHCCPOT002 Moisture + conductivity: + name: HHCCPOT002 Soil Conductivity diff --git a/tests/components/xiaomi_hhccpot002/test.esp32.yaml b/tests/components/xiaomi_hhccpot002/test.esp32.yaml new file mode 100644 index 0000000000..2e5fa14620 --- /dev/null +++ b/tests/components/xiaomi_hhccpot002/test.esp32.yaml @@ -0,0 +1,9 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_hhccpot002 + mac_address: 94:2B:FF:5C:91:61 + moisture: + name: HHCCPOT002 Moisture + conductivity: + name: HHCCPOT002 Soil Conductivity diff --git a/tests/components/xiaomi_jqjcy01ym/test.esp32-c3-idf.yaml b/tests/components/xiaomi_jqjcy01ym/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..54c4b33dcd --- /dev/null +++ b/tests/components/xiaomi_jqjcy01ym/test.esp32-c3-idf.yaml @@ -0,0 +1,13 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_jqjcy01ym + mac_address: 7A:80:8E:19:36:BA + temperature: + name: JQJCY01YM Temperature + humidity: + name: JQJCY01YM Humidity + formaldehyde: + name: JQJCY01YM Formaldehyde + battery_level: + name: JQJCY01YM Battery Level diff --git a/tests/components/xiaomi_jqjcy01ym/test.esp32-c3.yaml b/tests/components/xiaomi_jqjcy01ym/test.esp32-c3.yaml new file mode 100644 index 0000000000..54c4b33dcd --- /dev/null +++ b/tests/components/xiaomi_jqjcy01ym/test.esp32-c3.yaml @@ -0,0 +1,13 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_jqjcy01ym + mac_address: 7A:80:8E:19:36:BA + temperature: + name: JQJCY01YM Temperature + humidity: + name: JQJCY01YM Humidity + formaldehyde: + name: JQJCY01YM Formaldehyde + battery_level: + name: JQJCY01YM Battery Level diff --git a/tests/components/xiaomi_jqjcy01ym/test.esp32-idf.yaml b/tests/components/xiaomi_jqjcy01ym/test.esp32-idf.yaml new file mode 100644 index 0000000000..54c4b33dcd --- /dev/null +++ b/tests/components/xiaomi_jqjcy01ym/test.esp32-idf.yaml @@ -0,0 +1,13 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_jqjcy01ym + mac_address: 7A:80:8E:19:36:BA + temperature: + name: JQJCY01YM Temperature + humidity: + name: JQJCY01YM Humidity + formaldehyde: + name: JQJCY01YM Formaldehyde + battery_level: + name: JQJCY01YM Battery Level diff --git a/tests/components/xiaomi_jqjcy01ym/test.esp32.yaml b/tests/components/xiaomi_jqjcy01ym/test.esp32.yaml new file mode 100644 index 0000000000..54c4b33dcd --- /dev/null +++ b/tests/components/xiaomi_jqjcy01ym/test.esp32.yaml @@ -0,0 +1,13 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_jqjcy01ym + mac_address: 7A:80:8E:19:36:BA + temperature: + name: JQJCY01YM Temperature + humidity: + name: JQJCY01YM Humidity + formaldehyde: + name: JQJCY01YM Formaldehyde + battery_level: + name: JQJCY01YM Battery Level diff --git a/tests/components/xiaomi_lywsd02/test.esp32-c3-idf.yaml b/tests/components/xiaomi_lywsd02/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..3e40ab8d70 --- /dev/null +++ b/tests/components/xiaomi_lywsd02/test.esp32-c3-idf.yaml @@ -0,0 +1,11 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_lywsd02 + mac_address: 3F:5B:7D:82:58:4E + temperature: + name: Xiaomi LYWSD02 Temperature + humidity: + name: Xiaomi LYWSD02 Humidity + battery_level: + name: Xiaomi LYWSD02 Battery Level diff --git a/tests/components/xiaomi_lywsd02/test.esp32-c3.yaml b/tests/components/xiaomi_lywsd02/test.esp32-c3.yaml new file mode 100644 index 0000000000..3e40ab8d70 --- /dev/null +++ b/tests/components/xiaomi_lywsd02/test.esp32-c3.yaml @@ -0,0 +1,11 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_lywsd02 + mac_address: 3F:5B:7D:82:58:4E + temperature: + name: Xiaomi LYWSD02 Temperature + humidity: + name: Xiaomi LYWSD02 Humidity + battery_level: + name: Xiaomi LYWSD02 Battery Level diff --git a/tests/components/xiaomi_lywsd02/test.esp32-idf.yaml b/tests/components/xiaomi_lywsd02/test.esp32-idf.yaml new file mode 100644 index 0000000000..3e40ab8d70 --- /dev/null +++ b/tests/components/xiaomi_lywsd02/test.esp32-idf.yaml @@ -0,0 +1,11 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_lywsd02 + mac_address: 3F:5B:7D:82:58:4E + temperature: + name: Xiaomi LYWSD02 Temperature + humidity: + name: Xiaomi LYWSD02 Humidity + battery_level: + name: Xiaomi LYWSD02 Battery Level diff --git a/tests/components/xiaomi_lywsd02/test.esp32.yaml b/tests/components/xiaomi_lywsd02/test.esp32.yaml new file mode 100644 index 0000000000..3e40ab8d70 --- /dev/null +++ b/tests/components/xiaomi_lywsd02/test.esp32.yaml @@ -0,0 +1,11 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_lywsd02 + mac_address: 3F:5B:7D:82:58:4E + temperature: + name: Xiaomi LYWSD02 Temperature + humidity: + name: Xiaomi LYWSD02 Humidity + battery_level: + name: Xiaomi LYWSD02 Battery Level diff --git a/tests/components/xiaomi_lywsd03mmc/test.esp32-c3-idf.yaml b/tests/components/xiaomi_lywsd03mmc/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..d10a859c56 --- /dev/null +++ b/tests/components/xiaomi_lywsd03mmc/test.esp32-c3-idf.yaml @@ -0,0 +1,12 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_lywsd03mmc + mac_address: A4:C1:38:4E:16:78 + bindkey: e9efaa6873f9f9c87a5e75a5f814801c + temperature: + name: Xiaomi LYWSD03MMC Temperature + humidity: + name: Xiaomi LYWSD03MMC Humidity + battery_level: + name: Xiaomi LYWSD03MMC Battery Level diff --git a/tests/components/xiaomi_lywsd03mmc/test.esp32-c3.yaml b/tests/components/xiaomi_lywsd03mmc/test.esp32-c3.yaml new file mode 100644 index 0000000000..d10a859c56 --- /dev/null +++ b/tests/components/xiaomi_lywsd03mmc/test.esp32-c3.yaml @@ -0,0 +1,12 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_lywsd03mmc + mac_address: A4:C1:38:4E:16:78 + bindkey: e9efaa6873f9f9c87a5e75a5f814801c + temperature: + name: Xiaomi LYWSD03MMC Temperature + humidity: + name: Xiaomi LYWSD03MMC Humidity + battery_level: + name: Xiaomi LYWSD03MMC Battery Level diff --git a/tests/components/xiaomi_lywsd03mmc/test.esp32-idf.yaml b/tests/components/xiaomi_lywsd03mmc/test.esp32-idf.yaml new file mode 100644 index 0000000000..d10a859c56 --- /dev/null +++ b/tests/components/xiaomi_lywsd03mmc/test.esp32-idf.yaml @@ -0,0 +1,12 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_lywsd03mmc + mac_address: A4:C1:38:4E:16:78 + bindkey: e9efaa6873f9f9c87a5e75a5f814801c + temperature: + name: Xiaomi LYWSD03MMC Temperature + humidity: + name: Xiaomi LYWSD03MMC Humidity + battery_level: + name: Xiaomi LYWSD03MMC Battery Level diff --git a/tests/components/xiaomi_lywsd03mmc/test.esp32.yaml b/tests/components/xiaomi_lywsd03mmc/test.esp32.yaml new file mode 100644 index 0000000000..d10a859c56 --- /dev/null +++ b/tests/components/xiaomi_lywsd03mmc/test.esp32.yaml @@ -0,0 +1,12 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_lywsd03mmc + mac_address: A4:C1:38:4E:16:78 + bindkey: e9efaa6873f9f9c87a5e75a5f814801c + temperature: + name: Xiaomi LYWSD03MMC Temperature + humidity: + name: Xiaomi LYWSD03MMC Humidity + battery_level: + name: Xiaomi LYWSD03MMC Battery Level diff --git a/tests/components/xiaomi_lywsdcgq/test.esp32-c3-idf.yaml b/tests/components/xiaomi_lywsdcgq/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..d8422b4c0c --- /dev/null +++ b/tests/components/xiaomi_lywsdcgq/test.esp32-c3-idf.yaml @@ -0,0 +1,11 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_lywsdcgq + mac_address: 7A:80:8E:19:36:BA + temperature: + name: Xiaomi LYWSDCGQ Temperature + humidity: + name: Xiaomi LYWSDCGQ Humidity + battery_level: + name: Xiaomi LYWSDCGQ Battery Level diff --git a/tests/components/xiaomi_lywsdcgq/test.esp32-c3.yaml b/tests/components/xiaomi_lywsdcgq/test.esp32-c3.yaml new file mode 100644 index 0000000000..d8422b4c0c --- /dev/null +++ b/tests/components/xiaomi_lywsdcgq/test.esp32-c3.yaml @@ -0,0 +1,11 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_lywsdcgq + mac_address: 7A:80:8E:19:36:BA + temperature: + name: Xiaomi LYWSDCGQ Temperature + humidity: + name: Xiaomi LYWSDCGQ Humidity + battery_level: + name: Xiaomi LYWSDCGQ Battery Level diff --git a/tests/components/xiaomi_lywsdcgq/test.esp32-idf.yaml b/tests/components/xiaomi_lywsdcgq/test.esp32-idf.yaml new file mode 100644 index 0000000000..d8422b4c0c --- /dev/null +++ b/tests/components/xiaomi_lywsdcgq/test.esp32-idf.yaml @@ -0,0 +1,11 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_lywsdcgq + mac_address: 7A:80:8E:19:36:BA + temperature: + name: Xiaomi LYWSDCGQ Temperature + humidity: + name: Xiaomi LYWSDCGQ Humidity + battery_level: + name: Xiaomi LYWSDCGQ Battery Level diff --git a/tests/components/xiaomi_lywsdcgq/test.esp32.yaml b/tests/components/xiaomi_lywsdcgq/test.esp32.yaml new file mode 100644 index 0000000000..d8422b4c0c --- /dev/null +++ b/tests/components/xiaomi_lywsdcgq/test.esp32.yaml @@ -0,0 +1,11 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_lywsdcgq + mac_address: 7A:80:8E:19:36:BA + temperature: + name: Xiaomi LYWSDCGQ Temperature + humidity: + name: Xiaomi LYWSDCGQ Humidity + battery_level: + name: Xiaomi LYWSDCGQ Battery Level diff --git a/tests/components/xiaomi_mhoc303/test.esp32-c3-idf.yaml b/tests/components/xiaomi_mhoc303/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..e4353d3c6a --- /dev/null +++ b/tests/components/xiaomi_mhoc303/test.esp32-c3-idf.yaml @@ -0,0 +1,11 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_mhoc303 + mac_address: E7:50:59:32:A0:1C + temperature: + name: MHO-C303 Temperature + humidity: + name: MHO-C303 Humidity + battery_level: + name: MHO-C303 Battery Level diff --git a/tests/components/xiaomi_mhoc303/test.esp32-c3.yaml b/tests/components/xiaomi_mhoc303/test.esp32-c3.yaml new file mode 100644 index 0000000000..e4353d3c6a --- /dev/null +++ b/tests/components/xiaomi_mhoc303/test.esp32-c3.yaml @@ -0,0 +1,11 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_mhoc303 + mac_address: E7:50:59:32:A0:1C + temperature: + name: MHO-C303 Temperature + humidity: + name: MHO-C303 Humidity + battery_level: + name: MHO-C303 Battery Level diff --git a/tests/components/xiaomi_mhoc303/test.esp32-idf.yaml b/tests/components/xiaomi_mhoc303/test.esp32-idf.yaml new file mode 100644 index 0000000000..e4353d3c6a --- /dev/null +++ b/tests/components/xiaomi_mhoc303/test.esp32-idf.yaml @@ -0,0 +1,11 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_mhoc303 + mac_address: E7:50:59:32:A0:1C + temperature: + name: MHO-C303 Temperature + humidity: + name: MHO-C303 Humidity + battery_level: + name: MHO-C303 Battery Level diff --git a/tests/components/xiaomi_mhoc303/test.esp32.yaml b/tests/components/xiaomi_mhoc303/test.esp32.yaml new file mode 100644 index 0000000000..e4353d3c6a --- /dev/null +++ b/tests/components/xiaomi_mhoc303/test.esp32.yaml @@ -0,0 +1,11 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_mhoc303 + mac_address: E7:50:59:32:A0:1C + temperature: + name: MHO-C303 Temperature + humidity: + name: MHO-C303 Humidity + battery_level: + name: MHO-C303 Battery Level diff --git a/tests/components/xiaomi_mhoc401/test.esp32-c3-idf.yaml b/tests/components/xiaomi_mhoc401/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..ae378f5604 --- /dev/null +++ b/tests/components/xiaomi_mhoc401/test.esp32-c3-idf.yaml @@ -0,0 +1,12 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_mhoc401 + mac_address: E7:50:59:32:A0:1C + bindkey: "eef418daf699a0c188f3bfd17e4565d9" + temperature: + name: MHO-C303 Temperature + humidity: + name: MHO-C303 Humidity + battery_level: + name: MHO-C303 Battery Level diff --git a/tests/components/xiaomi_mhoc401/test.esp32-c3.yaml b/tests/components/xiaomi_mhoc401/test.esp32-c3.yaml new file mode 100644 index 0000000000..ae378f5604 --- /dev/null +++ b/tests/components/xiaomi_mhoc401/test.esp32-c3.yaml @@ -0,0 +1,12 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_mhoc401 + mac_address: E7:50:59:32:A0:1C + bindkey: "eef418daf699a0c188f3bfd17e4565d9" + temperature: + name: MHO-C303 Temperature + humidity: + name: MHO-C303 Humidity + battery_level: + name: MHO-C303 Battery Level diff --git a/tests/components/xiaomi_mhoc401/test.esp32-idf.yaml b/tests/components/xiaomi_mhoc401/test.esp32-idf.yaml new file mode 100644 index 0000000000..ae378f5604 --- /dev/null +++ b/tests/components/xiaomi_mhoc401/test.esp32-idf.yaml @@ -0,0 +1,12 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_mhoc401 + mac_address: E7:50:59:32:A0:1C + bindkey: "eef418daf699a0c188f3bfd17e4565d9" + temperature: + name: MHO-C303 Temperature + humidity: + name: MHO-C303 Humidity + battery_level: + name: MHO-C303 Battery Level diff --git a/tests/components/xiaomi_mhoc401/test.esp32.yaml b/tests/components/xiaomi_mhoc401/test.esp32.yaml new file mode 100644 index 0000000000..ae378f5604 --- /dev/null +++ b/tests/components/xiaomi_mhoc401/test.esp32.yaml @@ -0,0 +1,12 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_mhoc401 + mac_address: E7:50:59:32:A0:1C + bindkey: "eef418daf699a0c188f3bfd17e4565d9" + temperature: + name: MHO-C303 Temperature + humidity: + name: MHO-C303 Humidity + battery_level: + name: MHO-C303 Battery Level diff --git a/tests/components/xiaomi_miscale copy/test.esp32-c3-idf.yaml b/tests/components/xiaomi_miscale copy/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..89f32ad199 --- /dev/null +++ b/tests/components/xiaomi_miscale copy/test.esp32-c3-idf.yaml @@ -0,0 +1,9 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_miscale + mac_address: '5C:CA:D3:70:D4:A2' + weight: + name: "Xiaomi Mi Scale Weight" + impedance: + name: "Xiaomi Mi Scale Impedance" diff --git a/tests/components/xiaomi_miscale copy/test.esp32-c3.yaml b/tests/components/xiaomi_miscale copy/test.esp32-c3.yaml new file mode 100644 index 0000000000..89f32ad199 --- /dev/null +++ b/tests/components/xiaomi_miscale copy/test.esp32-c3.yaml @@ -0,0 +1,9 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_miscale + mac_address: '5C:CA:D3:70:D4:A2' + weight: + name: "Xiaomi Mi Scale Weight" + impedance: + name: "Xiaomi Mi Scale Impedance" diff --git a/tests/components/xiaomi_miscale copy/test.esp32-idf.yaml b/tests/components/xiaomi_miscale copy/test.esp32-idf.yaml new file mode 100644 index 0000000000..89f32ad199 --- /dev/null +++ b/tests/components/xiaomi_miscale copy/test.esp32-idf.yaml @@ -0,0 +1,9 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_miscale + mac_address: '5C:CA:D3:70:D4:A2' + weight: + name: "Xiaomi Mi Scale Weight" + impedance: + name: "Xiaomi Mi Scale Impedance" diff --git a/tests/components/xiaomi_miscale copy/test.esp32.yaml b/tests/components/xiaomi_miscale copy/test.esp32.yaml new file mode 100644 index 0000000000..89f32ad199 --- /dev/null +++ b/tests/components/xiaomi_miscale copy/test.esp32.yaml @@ -0,0 +1,9 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_miscale + mac_address: '5C:CA:D3:70:D4:A2' + weight: + name: "Xiaomi Mi Scale Weight" + impedance: + name: "Xiaomi Mi Scale Impedance" diff --git a/tests/components/xiaomi_miscale/test.esp32-c3-idf.yaml b/tests/components/xiaomi_miscale/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..89f32ad199 --- /dev/null +++ b/tests/components/xiaomi_miscale/test.esp32-c3-idf.yaml @@ -0,0 +1,9 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_miscale + mac_address: '5C:CA:D3:70:D4:A2' + weight: + name: "Xiaomi Mi Scale Weight" + impedance: + name: "Xiaomi Mi Scale Impedance" diff --git a/tests/components/xiaomi_miscale/test.esp32-c3.yaml b/tests/components/xiaomi_miscale/test.esp32-c3.yaml new file mode 100644 index 0000000000..89f32ad199 --- /dev/null +++ b/tests/components/xiaomi_miscale/test.esp32-c3.yaml @@ -0,0 +1,9 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_miscale + mac_address: '5C:CA:D3:70:D4:A2' + weight: + name: "Xiaomi Mi Scale Weight" + impedance: + name: "Xiaomi Mi Scale Impedance" diff --git a/tests/components/xiaomi_miscale/test.esp32-idf.yaml b/tests/components/xiaomi_miscale/test.esp32-idf.yaml new file mode 100644 index 0000000000..89f32ad199 --- /dev/null +++ b/tests/components/xiaomi_miscale/test.esp32-idf.yaml @@ -0,0 +1,9 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_miscale + mac_address: '5C:CA:D3:70:D4:A2' + weight: + name: "Xiaomi Mi Scale Weight" + impedance: + name: "Xiaomi Mi Scale Impedance" diff --git a/tests/components/xiaomi_miscale/test.esp32.yaml b/tests/components/xiaomi_miscale/test.esp32.yaml new file mode 100644 index 0000000000..89f32ad199 --- /dev/null +++ b/tests/components/xiaomi_miscale/test.esp32.yaml @@ -0,0 +1,9 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_miscale + mac_address: '5C:CA:D3:70:D4:A2' + weight: + name: "Xiaomi Mi Scale Weight" + impedance: + name: "Xiaomi Mi Scale Impedance" diff --git a/tests/components/xiaomi_mjyd02yla/test.esp32-c3-idf.yaml b/tests/components/xiaomi_mjyd02yla/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..dffcef84c4 --- /dev/null +++ b/tests/components/xiaomi_mjyd02yla/test.esp32-c3-idf.yaml @@ -0,0 +1,13 @@ +esp32_ble_tracker: + +binary_sensor: + - platform: xiaomi_mjyd02yla + name: MJYD02YL-A Motion + mac_address: 50:EC:50:CD:32:02 + bindkey: 48403ebe2d385db8d0c187f81e62cb64 + idle_time: + name: MJYD02YL-A Idle Time + light: + name: MJYD02YL-A Light Status + battery_level: + name: MJYD02YL-A Battery Level diff --git a/tests/components/xiaomi_mjyd02yla/test.esp32-c3.yaml b/tests/components/xiaomi_mjyd02yla/test.esp32-c3.yaml new file mode 100644 index 0000000000..dffcef84c4 --- /dev/null +++ b/tests/components/xiaomi_mjyd02yla/test.esp32-c3.yaml @@ -0,0 +1,13 @@ +esp32_ble_tracker: + +binary_sensor: + - platform: xiaomi_mjyd02yla + name: MJYD02YL-A Motion + mac_address: 50:EC:50:CD:32:02 + bindkey: 48403ebe2d385db8d0c187f81e62cb64 + idle_time: + name: MJYD02YL-A Idle Time + light: + name: MJYD02YL-A Light Status + battery_level: + name: MJYD02YL-A Battery Level diff --git a/tests/components/xiaomi_mjyd02yla/test.esp32-idf.yaml b/tests/components/xiaomi_mjyd02yla/test.esp32-idf.yaml new file mode 100644 index 0000000000..dffcef84c4 --- /dev/null +++ b/tests/components/xiaomi_mjyd02yla/test.esp32-idf.yaml @@ -0,0 +1,13 @@ +esp32_ble_tracker: + +binary_sensor: + - platform: xiaomi_mjyd02yla + name: MJYD02YL-A Motion + mac_address: 50:EC:50:CD:32:02 + bindkey: 48403ebe2d385db8d0c187f81e62cb64 + idle_time: + name: MJYD02YL-A Idle Time + light: + name: MJYD02YL-A Light Status + battery_level: + name: MJYD02YL-A Battery Level diff --git a/tests/components/xiaomi_mjyd02yla/test.esp32.yaml b/tests/components/xiaomi_mjyd02yla/test.esp32.yaml new file mode 100644 index 0000000000..dffcef84c4 --- /dev/null +++ b/tests/components/xiaomi_mjyd02yla/test.esp32.yaml @@ -0,0 +1,13 @@ +esp32_ble_tracker: + +binary_sensor: + - platform: xiaomi_mjyd02yla + name: MJYD02YL-A Motion + mac_address: 50:EC:50:CD:32:02 + bindkey: 48403ebe2d385db8d0c187f81e62cb64 + idle_time: + name: MJYD02YL-A Idle Time + light: + name: MJYD02YL-A Light Status + battery_level: + name: MJYD02YL-A Battery Level diff --git a/tests/components/xiaomi_mue4094rt/test.esp32-c3-idf.yaml b/tests/components/xiaomi_mue4094rt/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..4f0e5ccbae --- /dev/null +++ b/tests/components/xiaomi_mue4094rt/test.esp32-c3-idf.yaml @@ -0,0 +1,7 @@ +esp32_ble_tracker: + +binary_sensor: + - platform: xiaomi_mue4094rt + name: MUE4094RT Motion + mac_address: 7A:80:8E:19:36:BA + timeout: 5s diff --git a/tests/components/xiaomi_mue4094rt/test.esp32-c3.yaml b/tests/components/xiaomi_mue4094rt/test.esp32-c3.yaml new file mode 100644 index 0000000000..4f0e5ccbae --- /dev/null +++ b/tests/components/xiaomi_mue4094rt/test.esp32-c3.yaml @@ -0,0 +1,7 @@ +esp32_ble_tracker: + +binary_sensor: + - platform: xiaomi_mue4094rt + name: MUE4094RT Motion + mac_address: 7A:80:8E:19:36:BA + timeout: 5s diff --git a/tests/components/xiaomi_mue4094rt/test.esp32-idf.yaml b/tests/components/xiaomi_mue4094rt/test.esp32-idf.yaml new file mode 100644 index 0000000000..4f0e5ccbae --- /dev/null +++ b/tests/components/xiaomi_mue4094rt/test.esp32-idf.yaml @@ -0,0 +1,7 @@ +esp32_ble_tracker: + +binary_sensor: + - platform: xiaomi_mue4094rt + name: MUE4094RT Motion + mac_address: 7A:80:8E:19:36:BA + timeout: 5s diff --git a/tests/components/xiaomi_mue4094rt/test.esp32.yaml b/tests/components/xiaomi_mue4094rt/test.esp32.yaml new file mode 100644 index 0000000000..4f0e5ccbae --- /dev/null +++ b/tests/components/xiaomi_mue4094rt/test.esp32.yaml @@ -0,0 +1,7 @@ +esp32_ble_tracker: + +binary_sensor: + - platform: xiaomi_mue4094rt + name: MUE4094RT Motion + mac_address: 7A:80:8E:19:36:BA + timeout: 5s diff --git a/tests/components/xiaomi_rtcgq02lm/test.esp32-c3-idf.yaml b/tests/components/xiaomi_rtcgq02lm/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..a2e0c66ba5 --- /dev/null +++ b/tests/components/xiaomi_rtcgq02lm/test.esp32-c3-idf.yaml @@ -0,0 +1,22 @@ +esp32_ble_tracker: + +xiaomi_rtcgq02lm: + - id: motion_rtcgq02lm + mac_address: 01:02:03:04:05:06 + bindkey: "48403ebe2d385db8d0c187f81e62cb64" + +binary_sensor: + - platform: xiaomi_rtcgq02lm + id: motion_rtcgq02lm + motion: + name: Mi Motion Sensor 2 + light: + name: Mi Motion Sensor 2 Light + button: + name: Mi Motion Sensor 2 Button + +sensor: + - platform: xiaomi_rtcgq02lm + id: motion_rtcgq02lm + battery_level: + name: Mi Motion Sensor 2 Battery level diff --git a/tests/components/xiaomi_rtcgq02lm/test.esp32-c3.yaml b/tests/components/xiaomi_rtcgq02lm/test.esp32-c3.yaml new file mode 100644 index 0000000000..a2e0c66ba5 --- /dev/null +++ b/tests/components/xiaomi_rtcgq02lm/test.esp32-c3.yaml @@ -0,0 +1,22 @@ +esp32_ble_tracker: + +xiaomi_rtcgq02lm: + - id: motion_rtcgq02lm + mac_address: 01:02:03:04:05:06 + bindkey: "48403ebe2d385db8d0c187f81e62cb64" + +binary_sensor: + - platform: xiaomi_rtcgq02lm + id: motion_rtcgq02lm + motion: + name: Mi Motion Sensor 2 + light: + name: Mi Motion Sensor 2 Light + button: + name: Mi Motion Sensor 2 Button + +sensor: + - platform: xiaomi_rtcgq02lm + id: motion_rtcgq02lm + battery_level: + name: Mi Motion Sensor 2 Battery level diff --git a/tests/components/xiaomi_rtcgq02lm/test.esp32-idf.yaml b/tests/components/xiaomi_rtcgq02lm/test.esp32-idf.yaml new file mode 100644 index 0000000000..a2e0c66ba5 --- /dev/null +++ b/tests/components/xiaomi_rtcgq02lm/test.esp32-idf.yaml @@ -0,0 +1,22 @@ +esp32_ble_tracker: + +xiaomi_rtcgq02lm: + - id: motion_rtcgq02lm + mac_address: 01:02:03:04:05:06 + bindkey: "48403ebe2d385db8d0c187f81e62cb64" + +binary_sensor: + - platform: xiaomi_rtcgq02lm + id: motion_rtcgq02lm + motion: + name: Mi Motion Sensor 2 + light: + name: Mi Motion Sensor 2 Light + button: + name: Mi Motion Sensor 2 Button + +sensor: + - platform: xiaomi_rtcgq02lm + id: motion_rtcgq02lm + battery_level: + name: Mi Motion Sensor 2 Battery level diff --git a/tests/components/xiaomi_rtcgq02lm/test.esp32.yaml b/tests/components/xiaomi_rtcgq02lm/test.esp32.yaml new file mode 100644 index 0000000000..a2e0c66ba5 --- /dev/null +++ b/tests/components/xiaomi_rtcgq02lm/test.esp32.yaml @@ -0,0 +1,22 @@ +esp32_ble_tracker: + +xiaomi_rtcgq02lm: + - id: motion_rtcgq02lm + mac_address: 01:02:03:04:05:06 + bindkey: "48403ebe2d385db8d0c187f81e62cb64" + +binary_sensor: + - platform: xiaomi_rtcgq02lm + id: motion_rtcgq02lm + motion: + name: Mi Motion Sensor 2 + light: + name: Mi Motion Sensor 2 Light + button: + name: Mi Motion Sensor 2 Button + +sensor: + - platform: xiaomi_rtcgq02lm + id: motion_rtcgq02lm + battery_level: + name: Mi Motion Sensor 2 Battery level diff --git a/tests/components/xiaomi_wx08zm/test.esp32-c3-idf.yaml b/tests/components/xiaomi_wx08zm/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..3e83ad3e95 --- /dev/null +++ b/tests/components/xiaomi_wx08zm/test.esp32-c3-idf.yaml @@ -0,0 +1,10 @@ +esp32_ble_tracker: + +binary_sensor: + - platform: xiaomi_wx08zm + name: WX08ZM Activation State + mac_address: 74:a3:4a:b5:07:34 + tablet: + name: WX08ZM Tablet Resource + battery_level: + name: WX08ZM Battery Level diff --git a/tests/components/xiaomi_wx08zm/test.esp32-c3.yaml b/tests/components/xiaomi_wx08zm/test.esp32-c3.yaml new file mode 100644 index 0000000000..3e83ad3e95 --- /dev/null +++ b/tests/components/xiaomi_wx08zm/test.esp32-c3.yaml @@ -0,0 +1,10 @@ +esp32_ble_tracker: + +binary_sensor: + - platform: xiaomi_wx08zm + name: WX08ZM Activation State + mac_address: 74:a3:4a:b5:07:34 + tablet: + name: WX08ZM Tablet Resource + battery_level: + name: WX08ZM Battery Level diff --git a/tests/components/xiaomi_wx08zm/test.esp32-idf.yaml b/tests/components/xiaomi_wx08zm/test.esp32-idf.yaml new file mode 100644 index 0000000000..3e83ad3e95 --- /dev/null +++ b/tests/components/xiaomi_wx08zm/test.esp32-idf.yaml @@ -0,0 +1,10 @@ +esp32_ble_tracker: + +binary_sensor: + - platform: xiaomi_wx08zm + name: WX08ZM Activation State + mac_address: 74:a3:4a:b5:07:34 + tablet: + name: WX08ZM Tablet Resource + battery_level: + name: WX08ZM Battery Level diff --git a/tests/components/xiaomi_wx08zm/test.esp32.yaml b/tests/components/xiaomi_wx08zm/test.esp32.yaml new file mode 100644 index 0000000000..3e83ad3e95 --- /dev/null +++ b/tests/components/xiaomi_wx08zm/test.esp32.yaml @@ -0,0 +1,10 @@ +esp32_ble_tracker: + +binary_sensor: + - platform: xiaomi_wx08zm + name: WX08ZM Activation State + mac_address: 74:a3:4a:b5:07:34 + tablet: + name: WX08ZM Tablet Resource + battery_level: + name: WX08ZM Battery Level diff --git a/tests/components/xl9535/test.esp32-c3-idf.yaml b/tests/components/xl9535/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..178adf870e --- /dev/null +++ b/tests/components/xl9535/test.esp32-c3-idf.yaml @@ -0,0 +1,26 @@ +i2c: + - id: i2c_xl9535 + scl: 5 + sda: 4 + +xl9535: + - id: xl9535_hub + address: 0x20 + +binary_sensor: + - platform: gpio + name: XL9535 Pin 0 + pin: + xl9535: xl9535_hub + number: 0 + mode: + input: true + inverted: false + - platform: gpio + name: XL9535 Pin 17 + pin: + xl9535: xl9535_hub + number: 17 + mode: + input: true + inverted: false diff --git a/tests/components/xl9535/test.esp32-c3.yaml b/tests/components/xl9535/test.esp32-c3.yaml new file mode 100644 index 0000000000..178adf870e --- /dev/null +++ b/tests/components/xl9535/test.esp32-c3.yaml @@ -0,0 +1,26 @@ +i2c: + - id: i2c_xl9535 + scl: 5 + sda: 4 + +xl9535: + - id: xl9535_hub + address: 0x20 + +binary_sensor: + - platform: gpio + name: XL9535 Pin 0 + pin: + xl9535: xl9535_hub + number: 0 + mode: + input: true + inverted: false + - platform: gpio + name: XL9535 Pin 17 + pin: + xl9535: xl9535_hub + number: 17 + mode: + input: true + inverted: false diff --git a/tests/components/xl9535/test.esp32-idf.yaml b/tests/components/xl9535/test.esp32-idf.yaml new file mode 100644 index 0000000000..a65aae890e --- /dev/null +++ b/tests/components/xl9535/test.esp32-idf.yaml @@ -0,0 +1,26 @@ +i2c: + - id: i2c_xl9535 + scl: 16 + sda: 17 + +xl9535: + - id: xl9535_hub + address: 0x20 + +binary_sensor: + - platform: gpio + name: XL9535 Pin 0 + pin: + xl9535: xl9535_hub + number: 0 + mode: + input: true + inverted: false + - platform: gpio + name: XL9535 Pin 17 + pin: + xl9535: xl9535_hub + number: 17 + mode: + input: true + inverted: false diff --git a/tests/components/xl9535/test.esp32.yaml b/tests/components/xl9535/test.esp32.yaml new file mode 100644 index 0000000000..a65aae890e --- /dev/null +++ b/tests/components/xl9535/test.esp32.yaml @@ -0,0 +1,26 @@ +i2c: + - id: i2c_xl9535 + scl: 16 + sda: 17 + +xl9535: + - id: xl9535_hub + address: 0x20 + +binary_sensor: + - platform: gpio + name: XL9535 Pin 0 + pin: + xl9535: xl9535_hub + number: 0 + mode: + input: true + inverted: false + - platform: gpio + name: XL9535 Pin 17 + pin: + xl9535: xl9535_hub + number: 17 + mode: + input: true + inverted: false diff --git a/tests/components/xl9535/test.esp8266.yaml b/tests/components/xl9535/test.esp8266.yaml new file mode 100644 index 0000000000..178adf870e --- /dev/null +++ b/tests/components/xl9535/test.esp8266.yaml @@ -0,0 +1,26 @@ +i2c: + - id: i2c_xl9535 + scl: 5 + sda: 4 + +xl9535: + - id: xl9535_hub + address: 0x20 + +binary_sensor: + - platform: gpio + name: XL9535 Pin 0 + pin: + xl9535: xl9535_hub + number: 0 + mode: + input: true + inverted: false + - platform: gpio + name: XL9535 Pin 17 + pin: + xl9535: xl9535_hub + number: 17 + mode: + input: true + inverted: false diff --git a/tests/components/xl9535/test.rp2040.yaml b/tests/components/xl9535/test.rp2040.yaml new file mode 100644 index 0000000000..178adf870e --- /dev/null +++ b/tests/components/xl9535/test.rp2040.yaml @@ -0,0 +1,26 @@ +i2c: + - id: i2c_xl9535 + scl: 5 + sda: 4 + +xl9535: + - id: xl9535_hub + address: 0x20 + +binary_sensor: + - platform: gpio + name: XL9535 Pin 0 + pin: + xl9535: xl9535_hub + number: 0 + mode: + input: true + inverted: false + - platform: gpio + name: XL9535 Pin 17 + pin: + xl9535: xl9535_hub + number: 17 + mode: + input: true + inverted: false diff --git a/tests/components/xpt2046/test.esp32-c3-idf.yaml b/tests/components/xpt2046/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..38a1da74ae --- /dev/null +++ b/tests/components/xpt2046/test.esp32-c3-idf.yaml @@ -0,0 +1,33 @@ +spi: + - id: spi_xpt2046 + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +display: + - platform: ili9xxx + id: xpt_display + dimensions: 320x240 + model: TFT 2.4 + cs_pin: 8 + dc_pin: 9 + reset_pin: 10 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: xpt2046 + id: xpt_touchscreen + cs_pin: 4 + interrupt_pin: 3 + display: xpt_display + update_interval: 50ms + threshold: 400 + calibration_x_min: 3860 + calibration_x_max: 280 + calibration_y_min: 340 + calibration_y_max: 3860 + on_touch: + - logger.log: + format: Touch at (%d, %d) + args: [touch.x, touch.y] diff --git a/tests/components/xpt2046/test.esp32-c3.yaml b/tests/components/xpt2046/test.esp32-c3.yaml new file mode 100644 index 0000000000..38a1da74ae --- /dev/null +++ b/tests/components/xpt2046/test.esp32-c3.yaml @@ -0,0 +1,33 @@ +spi: + - id: spi_xpt2046 + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +display: + - platform: ili9xxx + id: xpt_display + dimensions: 320x240 + model: TFT 2.4 + cs_pin: 8 + dc_pin: 9 + reset_pin: 10 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: xpt2046 + id: xpt_touchscreen + cs_pin: 4 + interrupt_pin: 3 + display: xpt_display + update_interval: 50ms + threshold: 400 + calibration_x_min: 3860 + calibration_x_max: 280 + calibration_y_min: 340 + calibration_y_max: 3860 + on_touch: + - logger.log: + format: Touch at (%d, %d) + args: [touch.x, touch.y] diff --git a/tests/components/xpt2046/test.esp32-idf.yaml b/tests/components/xpt2046/test.esp32-idf.yaml new file mode 100644 index 0000000000..7f8617d176 --- /dev/null +++ b/tests/components/xpt2046/test.esp32-idf.yaml @@ -0,0 +1,33 @@ +spi: + - id: spi_xpt2046 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +display: + - platform: ili9xxx + id: xpt_display + dimensions: 320x240 + model: TFT 2.4 + cs_pin: 13 + dc_pin: 14 + reset_pin: 21 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: xpt2046 + id: xpt_touchscreen + cs_pin: 18 + interrupt_pin: 19 + display: xpt_display + update_interval: 50ms + threshold: 400 + calibration_x_min: 3860 + calibration_x_max: 280 + calibration_y_min: 340 + calibration_y_max: 3860 + on_touch: + - logger.log: + format: Touch at (%d, %d) + args: [touch.x, touch.y] diff --git a/tests/components/xpt2046/test.esp32.yaml b/tests/components/xpt2046/test.esp32.yaml new file mode 100644 index 0000000000..7f8617d176 --- /dev/null +++ b/tests/components/xpt2046/test.esp32.yaml @@ -0,0 +1,33 @@ +spi: + - id: spi_xpt2046 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +display: + - platform: ili9xxx + id: xpt_display + dimensions: 320x240 + model: TFT 2.4 + cs_pin: 13 + dc_pin: 14 + reset_pin: 21 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: xpt2046 + id: xpt_touchscreen + cs_pin: 18 + interrupt_pin: 19 + display: xpt_display + update_interval: 50ms + threshold: 400 + calibration_x_min: 3860 + calibration_x_max: 280 + calibration_y_min: 340 + calibration_y_max: 3860 + on_touch: + - logger.log: + format: Touch at (%d, %d) + args: [touch.x, touch.y] diff --git a/tests/components/xpt2046/test.esp8266.yaml b/tests/components/xpt2046/test.esp8266.yaml new file mode 100644 index 0000000000..a998d2df14 --- /dev/null +++ b/tests/components/xpt2046/test.esp8266.yaml @@ -0,0 +1,33 @@ +spi: + - id: spi_xpt2046 + clk_pin: 14 + mosi_pin: 13 + miso_pin: 12 + +display: + - platform: ili9xxx + id: xpt_display + dimensions: 320x240 + model: TFT 2.4 + cs_pin: 15 + dc_pin: 4 + reset_pin: 5 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: xpt2046 + id: xpt_touchscreen + cs_pin: 0 + interrupt_pin: 16 + display: xpt_display + update_interval: 50ms + threshold: 400 + calibration_x_min: 3860 + calibration_x_max: 280 + calibration_y_min: 340 + calibration_y_max: 3860 + on_touch: + - logger.log: + format: Touch at (%d, %d) + args: [touch.x, touch.y] diff --git a/tests/components/xpt2046/test.rp2040.yaml b/tests/components/xpt2046/test.rp2040.yaml new file mode 100644 index 0000000000..3e5d602247 --- /dev/null +++ b/tests/components/xpt2046/test.rp2040.yaml @@ -0,0 +1,33 @@ +spi: + - id: spi_xpt2046 + clk_pin: 2 + mosi_pin: 3 + miso_pin: 4 + +display: + - platform: ili9xxx + id: xpt_display + dimensions: 320x240 + model: TFT 2.4 + cs_pin: 8 + dc_pin: 9 + reset_pin: 10 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: xpt2046 + id: xpt_touchscreen + cs_pin: 5 + interrupt_pin: 6 + display: xpt_display + update_interval: 50ms + threshold: 400 + calibration_x_min: 3860 + calibration_x_max: 280 + calibration_y_min: 340 + calibration_y_max: 3860 + on_touch: + - logger.log: + format: Touch at (%d, %d) + args: [touch.x, touch.y] diff --git a/tests/components/yashima/test.esp32-c3-idf.yaml b/tests/components/yashima/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..4b6d6daee4 --- /dev/null +++ b/tests/components/yashima/test.esp32-c3-idf.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +climate: + - platform: yashima + name: Yashima Climate diff --git a/tests/components/yashima/test.esp32-c3.yaml b/tests/components/yashima/test.esp32-c3.yaml new file mode 100644 index 0000000000..4b6d6daee4 --- /dev/null +++ b/tests/components/yashima/test.esp32-c3.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +climate: + - platform: yashima + name: Yashima Climate diff --git a/tests/components/yashima/test.esp32-idf.yaml b/tests/components/yashima/test.esp32-idf.yaml new file mode 100644 index 0000000000..4b6d6daee4 --- /dev/null +++ b/tests/components/yashima/test.esp32-idf.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +climate: + - platform: yashima + name: Yashima Climate diff --git a/tests/components/yashima/test.esp32.yaml b/tests/components/yashima/test.esp32.yaml new file mode 100644 index 0000000000..4b6d6daee4 --- /dev/null +++ b/tests/components/yashima/test.esp32.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +climate: + - platform: yashima + name: Yashima Climate diff --git a/tests/components/yashima/test.esp8266.yaml b/tests/components/yashima/test.esp8266.yaml new file mode 100644 index 0000000000..296a7ede25 --- /dev/null +++ b/tests/components/yashima/test.esp8266.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 5 + carrier_duty_percent: 50% + +climate: + - platform: yashima + name: Yashima Climate diff --git a/tests/components/zhlt01/test.esp32-c3-idf.yaml b/tests/components/zhlt01/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..d1dc3b4926 --- /dev/null +++ b/tests/components/zhlt01/test.esp32-c3-idf.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +climate: + - platform: zhlt01 + name: ZH/LT-01 Climate diff --git a/tests/components/zhlt01/test.esp32-c3.yaml b/tests/components/zhlt01/test.esp32-c3.yaml new file mode 100644 index 0000000000..d1dc3b4926 --- /dev/null +++ b/tests/components/zhlt01/test.esp32-c3.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +climate: + - platform: zhlt01 + name: ZH/LT-01 Climate diff --git a/tests/components/zhlt01/test.esp32-idf.yaml b/tests/components/zhlt01/test.esp32-idf.yaml new file mode 100644 index 0000000000..d1dc3b4926 --- /dev/null +++ b/tests/components/zhlt01/test.esp32-idf.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +climate: + - platform: zhlt01 + name: ZH/LT-01 Climate diff --git a/tests/components/zhlt01/test.esp32.yaml b/tests/components/zhlt01/test.esp32.yaml new file mode 100644 index 0000000000..d1dc3b4926 --- /dev/null +++ b/tests/components/zhlt01/test.esp32.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +climate: + - platform: zhlt01 + name: ZH/LT-01 Climate diff --git a/tests/components/zhlt01/test.esp8266.yaml b/tests/components/zhlt01/test.esp8266.yaml new file mode 100644 index 0000000000..40a00bc458 --- /dev/null +++ b/tests/components/zhlt01/test.esp8266.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 5 + carrier_duty_percent: 50% + +climate: + - platform: zhlt01 + name: ZH/LT-01 Climate diff --git a/tests/components/zio_ultrasonic/test.esp32-c3-idf.yaml b/tests/components/zio_ultrasonic/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..36e1697a38 --- /dev/null +++ b/tests/components/zio_ultrasonic/test.esp32-c3-idf.yaml @@ -0,0 +1,9 @@ +i2c: + - id: i2c_zio_ultrasonic + scl: 5 + sda: 4 + +sensor: + - platform: zio_ultrasonic + name: "Distance" + update_interval: 60s diff --git a/tests/components/zio_ultrasonic/test.esp32-c3.yaml b/tests/components/zio_ultrasonic/test.esp32-c3.yaml new file mode 100644 index 0000000000..36e1697a38 --- /dev/null +++ b/tests/components/zio_ultrasonic/test.esp32-c3.yaml @@ -0,0 +1,9 @@ +i2c: + - id: i2c_zio_ultrasonic + scl: 5 + sda: 4 + +sensor: + - platform: zio_ultrasonic + name: "Distance" + update_interval: 60s diff --git a/tests/components/zio_ultrasonic/test.esp32-idf.yaml b/tests/components/zio_ultrasonic/test.esp32-idf.yaml new file mode 100644 index 0000000000..ad4050307e --- /dev/null +++ b/tests/components/zio_ultrasonic/test.esp32-idf.yaml @@ -0,0 +1,9 @@ +i2c: + - id: i2c_zio_ultrasonic + scl: 16 + sda: 17 + +sensor: + - platform: zio_ultrasonic + name: "Distance" + update_interval: 60s diff --git a/tests/components/zio_ultrasonic/test.esp32.yaml b/tests/components/zio_ultrasonic/test.esp32.yaml new file mode 100644 index 0000000000..ad4050307e --- /dev/null +++ b/tests/components/zio_ultrasonic/test.esp32.yaml @@ -0,0 +1,9 @@ +i2c: + - id: i2c_zio_ultrasonic + scl: 16 + sda: 17 + +sensor: + - platform: zio_ultrasonic + name: "Distance" + update_interval: 60s diff --git a/tests/components/zio_ultrasonic/test.esp8266.yaml b/tests/components/zio_ultrasonic/test.esp8266.yaml new file mode 100644 index 0000000000..36e1697a38 --- /dev/null +++ b/tests/components/zio_ultrasonic/test.esp8266.yaml @@ -0,0 +1,9 @@ +i2c: + - id: i2c_zio_ultrasonic + scl: 5 + sda: 4 + +sensor: + - platform: zio_ultrasonic + name: "Distance" + update_interval: 60s diff --git a/tests/components/zio_ultrasonic/test.rp2040.yaml b/tests/components/zio_ultrasonic/test.rp2040.yaml new file mode 100644 index 0000000000..36e1697a38 --- /dev/null +++ b/tests/components/zio_ultrasonic/test.rp2040.yaml @@ -0,0 +1,9 @@ +i2c: + - id: i2c_zio_ultrasonic + scl: 5 + sda: 4 + +sensor: + - platform: zio_ultrasonic + name: "Distance" + update_interval: 60s diff --git a/tests/components/zyaura/test.esp32-c3-idf.yaml b/tests/components/zyaura/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..90205c468c --- /dev/null +++ b/tests/components/zyaura/test.esp32-c3-idf.yaml @@ -0,0 +1,10 @@ +sensor: + - platform: zyaura + clock_pin: 5 + data_pin: 4 + co2: + name: ZyAura CO2 + temperature: + name: ZyAura Temperature + humidity: + name: ZyAura Humidity diff --git a/tests/components/zyaura/test.esp32-c3.yaml b/tests/components/zyaura/test.esp32-c3.yaml new file mode 100644 index 0000000000..90205c468c --- /dev/null +++ b/tests/components/zyaura/test.esp32-c3.yaml @@ -0,0 +1,10 @@ +sensor: + - platform: zyaura + clock_pin: 5 + data_pin: 4 + co2: + name: ZyAura CO2 + temperature: + name: ZyAura Temperature + humidity: + name: ZyAura Humidity diff --git a/tests/components/zyaura/test.esp32-idf.yaml b/tests/components/zyaura/test.esp32-idf.yaml new file mode 100644 index 0000000000..29116a978b --- /dev/null +++ b/tests/components/zyaura/test.esp32-idf.yaml @@ -0,0 +1,10 @@ +sensor: + - platform: zyaura + clock_pin: 16 + data_pin: 17 + co2: + name: ZyAura CO2 + temperature: + name: ZyAura Temperature + humidity: + name: ZyAura Humidity diff --git a/tests/components/zyaura/test.esp32.yaml b/tests/components/zyaura/test.esp32.yaml new file mode 100644 index 0000000000..29116a978b --- /dev/null +++ b/tests/components/zyaura/test.esp32.yaml @@ -0,0 +1,10 @@ +sensor: + - platform: zyaura + clock_pin: 16 + data_pin: 17 + co2: + name: ZyAura CO2 + temperature: + name: ZyAura Temperature + humidity: + name: ZyAura Humidity diff --git a/tests/components/zyaura/test.esp8266.yaml b/tests/components/zyaura/test.esp8266.yaml new file mode 100644 index 0000000000..90205c468c --- /dev/null +++ b/tests/components/zyaura/test.esp8266.yaml @@ -0,0 +1,10 @@ +sensor: + - platform: zyaura + clock_pin: 5 + data_pin: 4 + co2: + name: ZyAura CO2 + temperature: + name: ZyAura Temperature + humidity: + name: ZyAura Humidity diff --git a/tests/components/zyaura/test.rp2040.yaml b/tests/components/zyaura/test.rp2040.yaml new file mode 100644 index 0000000000..90205c468c --- /dev/null +++ b/tests/components/zyaura/test.rp2040.yaml @@ -0,0 +1,10 @@ +sensor: + - platform: zyaura + clock_pin: 5 + data_pin: 4 + co2: + name: ZyAura CO2 + temperature: + name: ZyAura Temperature + humidity: + name: ZyAura Humidity From 61f11386a94424f892e70fbc7bf86afc60f38c9f Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Mon, 18 Mar 2024 18:52:40 -0500 Subject: [PATCH 1116/2101] Add some components to the new testing framework (E) (#6176) --- tests/components/e131/test.esp32-c3-idf.yaml | 18 ++++++ tests/components/e131/test.esp32-c3.yaml | 18 ++++++ tests/components/e131/test.esp32-idf.yaml | 18 ++++++ tests/components/e131/test.esp32.yaml | 18 ++++++ tests/components/e131/test.esp8266.yaml | 17 ++++++ tests/components/e131/test.rp2040.yaml | 17 ++++++ tests/components/ee895/test.esp32-c3-idf.yaml | 14 +++++ tests/components/ee895/test.esp32-c3.yaml | 14 +++++ tests/components/ee895/test.esp32-idf.yaml | 14 +++++ tests/components/ee895/test.esp32.yaml | 14 +++++ tests/components/ee895/test.esp8266.yaml | 14 +++++ tests/components/ee895/test.rp2040.yaml | 14 +++++ .../ektf2232/test.esp32-c3-idf.yaml | 24 ++++++++ tests/components/ektf2232/test.esp32-c3.yaml | 24 ++++++++ tests/components/ektf2232/test.esp32-idf.yaml | 24 ++++++++ tests/components/ektf2232/test.esp32.yaml | 24 ++++++++ tests/components/ektf2232/test.esp8266.yaml | 24 ++++++++ tests/components/ektf2232/test.rp2040.yaml | 24 ++++++++ .../components/emc2101/test.esp32-c3-idf.yaml | 25 ++++++++ tests/components/emc2101/test.esp32-c3.yaml | 25 ++++++++ tests/components/emc2101/test.esp32-idf.yaml | 25 ++++++++ tests/components/emc2101/test.esp32.yaml | 25 ++++++++ tests/components/emc2101/test.esp8266.yaml | 25 ++++++++ tests/components/emc2101/test.rp2040.yaml | 25 ++++++++ .../components/endstop/test.esp32-c3-idf.yaml | 33 ++++++++++ tests/components/endstop/test.esp32-c3.yaml | 33 ++++++++++ tests/components/endstop/test.esp32-idf.yaml | 33 ++++++++++ tests/components/endstop/test.esp32.yaml | 33 ++++++++++ tests/components/endstop/test.esp8266.yaml | 33 ++++++++++ tests/components/endstop/test.rp2040.yaml | 33 ++++++++++ .../components/ens160/test.esp32-c3-idf.yaml | 13 ++++ tests/components/ens160/test.esp32-c3.yaml | 13 ++++ tests/components/ens160/test.esp32-idf.yaml | 13 ++++ tests/components/ens160/test.esp32.yaml | 13 ++++ tests/components/ens160/test.esp8266.yaml | 13 ++++ tests/components/ens160/test.rp2040.yaml | 13 ++++ .../components/ens210/test.esp32-c3-idf.yaml | 12 ++++ tests/components/ens210/test.esp32-c3.yaml | 12 ++++ tests/components/ens210/test.esp32-idf.yaml | 12 ++++ tests/components/ens210/test.esp32.yaml | 12 ++++ tests/components/ens210/test.esp8266.yaml | 12 ++++ tests/components/ens210/test.rp2040.yaml | 12 ++++ .../esp32_ble/test.esp32-c3-idf.yaml | 2 + tests/components/esp32_ble/test.esp32-c3.yaml | 2 + .../components/esp32_ble/test.esp32-idf.yaml | 2 + tests/components/esp32_ble/test.esp32.yaml | 2 + .../esp32_ble_beacon/test.esp32-c3-idf.yaml | 3 + .../esp32_ble_beacon/test.esp32-c3.yaml | 3 + .../esp32_ble_beacon/test.esp32-idf.yaml | 3 + .../esp32_ble_beacon/test.esp32.yaml | 3 + .../esp32_ble_client/test.esp32-c3-idf.yaml | 5 ++ .../esp32_ble_client/test.esp32-c3.yaml | 5 ++ .../esp32_ble_client/test.esp32-idf.yaml | 5 ++ .../esp32_ble_client/test.esp32.yaml | 5 ++ .../esp32_ble_server/test.esp32-c3-idf.yaml | 3 + .../esp32_ble_server/test.esp32-c3.yaml | 3 + .../esp32_ble_server/test.esp32-idf.yaml | 3 + .../esp32_ble_server/test.esp32.yaml | 3 + .../esp32_ble_tracker/test.esp32-c3-idf.yaml | 41 +++++++++++++ .../esp32_ble_tracker/test.esp32-c3.yaml | 41 +++++++++++++ .../esp32_ble_tracker/test.esp32-idf.yaml | 41 +++++++++++++ .../esp32_ble_tracker/test.esp32.yaml | 41 +++++++++++++ .../esp32_camera/test.esp32-idf.yaml | 28 +++++++++ tests/components/esp32_camera/test.esp32.yaml | 28 +++++++++ .../test.esp32-idf.yaml | 34 +++++++++++ .../esp32_camera_web_server/test.esp32.yaml | 34 +++++++++++ .../esp32_can/test.esp32-c3-idf.yaml | 45 ++++++++++++++ tests/components/esp32_can/test.esp32-c3.yaml | 45 ++++++++++++++ .../components/esp32_can/test.esp32-idf.yaml | 45 ++++++++++++++ tests/components/esp32_can/test.esp32.yaml | 45 ++++++++++++++ .../components/esp32_dac/test.esp32-idf.yaml | 4 ++ tests/components/esp32_dac/test.esp32.yaml | 4 ++ .../components/esp32_hall/test.esp32-idf.yaml | 3 + tests/components/esp32_hall/test.esp32.yaml | 3 + .../esp32_improv/test.esp32-c3-idf.yaml | 18 ++++++ .../esp32_improv/test.esp32-c3.yaml | 18 ++++++ .../esp32_improv/test.esp32-idf.yaml | 18 ++++++ tests/components/esp32_improv/test.esp32.yaml | 18 ++++++ .../test.esp32-c3-idf.yaml | 18 ++++++ .../esp32_rmt_led_strip/test.esp32-c3.yaml | 18 ++++++ .../esp32_rmt_led_strip/test.esp32-idf.yaml | 18 ++++++ .../esp32_rmt_led_strip/test.esp32.yaml | 18 ++++++ .../esp32_touch/test.esp32-idf.yaml | 16 +++++ tests/components/esp32_touch/test.esp32.yaml | 16 +++++ .../components/esp8266_pwm/test.esp8266.yaml | 8 +++ tests/components/ethernet/test.esp32-idf.yaml | 12 ++++ tests/components/ethernet/test.esp32.yaml | 12 ++++ .../ethernet_info/test.esp32-idf.yaml | 17 ++++++ .../components/ethernet_info/test.esp32.yaml | 17 ++++++ .../test.esp32-c3-idf.yaml | 9 +++ .../exposure_notifications/test.esp32-c3.yaml | 9 +++ .../test.esp32-idf.yaml | 9 +++ .../exposure_notifications/test.esp32.yaml | 9 +++ .../test.esp32-c3-idf.yaml | 6 ++ .../external_components/test.esp32-c3.yaml | 6 ++ .../external_components/test.esp32-idf.yaml | 6 ++ .../external_components/test.esp32.yaml | 6 ++ .../external_components/test.esp8266.yaml | 6 ++ .../external_components/test.rp2040.yaml | 6 ++ tests/components/ezo/test.esp32-c3-idf.yaml | 10 +++ tests/components/ezo/test.esp32-c3.yaml | 10 +++ tests/components/ezo/test.esp32-idf.yaml | 10 +++ tests/components/ezo/test.esp32.yaml | 10 +++ tests/components/ezo/test.esp8266.yaml | 10 +++ tests/components/ezo/test.rp2040.yaml | 10 +++ .../components/ezo_pmp/test.esp32-c3-idf.yaml | 61 +++++++++++++++++++ tests/components/ezo_pmp/test.esp32-c3.yaml | 61 +++++++++++++++++++ tests/components/ezo_pmp/test.esp32-idf.yaml | 61 +++++++++++++++++++ tests/components/ezo_pmp/test.esp32.yaml | 61 +++++++++++++++++++ tests/components/ezo_pmp/test.esp8266.yaml | 61 +++++++++++++++++++ tests/components/ezo_pmp/test.rp2040.yaml | 61 +++++++++++++++++++ 111 files changed, 2106 insertions(+) create mode 100644 tests/components/e131/test.esp32-c3-idf.yaml create mode 100644 tests/components/e131/test.esp32-c3.yaml create mode 100644 tests/components/e131/test.esp32-idf.yaml create mode 100644 tests/components/e131/test.esp32.yaml create mode 100644 tests/components/e131/test.esp8266.yaml create mode 100644 tests/components/e131/test.rp2040.yaml create mode 100644 tests/components/ee895/test.esp32-c3-idf.yaml create mode 100644 tests/components/ee895/test.esp32-c3.yaml create mode 100644 tests/components/ee895/test.esp32-idf.yaml create mode 100644 tests/components/ee895/test.esp32.yaml create mode 100644 tests/components/ee895/test.esp8266.yaml create mode 100644 tests/components/ee895/test.rp2040.yaml create mode 100644 tests/components/ektf2232/test.esp32-c3-idf.yaml create mode 100644 tests/components/ektf2232/test.esp32-c3.yaml create mode 100644 tests/components/ektf2232/test.esp32-idf.yaml create mode 100644 tests/components/ektf2232/test.esp32.yaml create mode 100644 tests/components/ektf2232/test.esp8266.yaml create mode 100644 tests/components/ektf2232/test.rp2040.yaml create mode 100644 tests/components/emc2101/test.esp32-c3-idf.yaml create mode 100644 tests/components/emc2101/test.esp32-c3.yaml create mode 100644 tests/components/emc2101/test.esp32-idf.yaml create mode 100644 tests/components/emc2101/test.esp32.yaml create mode 100644 tests/components/emc2101/test.esp8266.yaml create mode 100644 tests/components/emc2101/test.rp2040.yaml create mode 100644 tests/components/endstop/test.esp32-c3-idf.yaml create mode 100644 tests/components/endstop/test.esp32-c3.yaml create mode 100644 tests/components/endstop/test.esp32-idf.yaml create mode 100644 tests/components/endstop/test.esp32.yaml create mode 100644 tests/components/endstop/test.esp8266.yaml create mode 100644 tests/components/endstop/test.rp2040.yaml create mode 100644 tests/components/ens160/test.esp32-c3-idf.yaml create mode 100644 tests/components/ens160/test.esp32-c3.yaml create mode 100644 tests/components/ens160/test.esp32-idf.yaml create mode 100644 tests/components/ens160/test.esp32.yaml create mode 100644 tests/components/ens160/test.esp8266.yaml create mode 100644 tests/components/ens160/test.rp2040.yaml create mode 100644 tests/components/ens210/test.esp32-c3-idf.yaml create mode 100644 tests/components/ens210/test.esp32-c3.yaml create mode 100644 tests/components/ens210/test.esp32-idf.yaml create mode 100644 tests/components/ens210/test.esp32.yaml create mode 100644 tests/components/ens210/test.esp8266.yaml create mode 100644 tests/components/ens210/test.rp2040.yaml create mode 100644 tests/components/esp32_ble/test.esp32-c3-idf.yaml create mode 100644 tests/components/esp32_ble/test.esp32-c3.yaml create mode 100644 tests/components/esp32_ble/test.esp32-idf.yaml create mode 100644 tests/components/esp32_ble/test.esp32.yaml create mode 100644 tests/components/esp32_ble_beacon/test.esp32-c3-idf.yaml create mode 100644 tests/components/esp32_ble_beacon/test.esp32-c3.yaml create mode 100644 tests/components/esp32_ble_beacon/test.esp32-idf.yaml create mode 100644 tests/components/esp32_ble_beacon/test.esp32.yaml create mode 100644 tests/components/esp32_ble_client/test.esp32-c3-idf.yaml create mode 100644 tests/components/esp32_ble_client/test.esp32-c3.yaml create mode 100644 tests/components/esp32_ble_client/test.esp32-idf.yaml create mode 100644 tests/components/esp32_ble_client/test.esp32.yaml create mode 100644 tests/components/esp32_ble_server/test.esp32-c3-idf.yaml create mode 100644 tests/components/esp32_ble_server/test.esp32-c3.yaml create mode 100644 tests/components/esp32_ble_server/test.esp32-idf.yaml create mode 100644 tests/components/esp32_ble_server/test.esp32.yaml create mode 100644 tests/components/esp32_ble_tracker/test.esp32-c3-idf.yaml create mode 100644 tests/components/esp32_ble_tracker/test.esp32-c3.yaml create mode 100644 tests/components/esp32_ble_tracker/test.esp32-idf.yaml create mode 100644 tests/components/esp32_ble_tracker/test.esp32.yaml create mode 100644 tests/components/esp32_camera/test.esp32-idf.yaml create mode 100644 tests/components/esp32_camera/test.esp32.yaml create mode 100644 tests/components/esp32_camera_web_server/test.esp32-idf.yaml create mode 100644 tests/components/esp32_camera_web_server/test.esp32.yaml create mode 100644 tests/components/esp32_can/test.esp32-c3-idf.yaml create mode 100644 tests/components/esp32_can/test.esp32-c3.yaml create mode 100644 tests/components/esp32_can/test.esp32-idf.yaml create mode 100644 tests/components/esp32_can/test.esp32.yaml create mode 100644 tests/components/esp32_dac/test.esp32-idf.yaml create mode 100644 tests/components/esp32_dac/test.esp32.yaml create mode 100644 tests/components/esp32_hall/test.esp32-idf.yaml create mode 100644 tests/components/esp32_hall/test.esp32.yaml create mode 100644 tests/components/esp32_improv/test.esp32-c3-idf.yaml create mode 100644 tests/components/esp32_improv/test.esp32-c3.yaml create mode 100644 tests/components/esp32_improv/test.esp32-idf.yaml create mode 100644 tests/components/esp32_improv/test.esp32.yaml create mode 100644 tests/components/esp32_rmt_led_strip/test.esp32-c3-idf.yaml create mode 100644 tests/components/esp32_rmt_led_strip/test.esp32-c3.yaml create mode 100644 tests/components/esp32_rmt_led_strip/test.esp32-idf.yaml create mode 100644 tests/components/esp32_rmt_led_strip/test.esp32.yaml create mode 100644 tests/components/esp32_touch/test.esp32-idf.yaml create mode 100644 tests/components/esp32_touch/test.esp32.yaml create mode 100644 tests/components/esp8266_pwm/test.esp8266.yaml create mode 100644 tests/components/ethernet/test.esp32-idf.yaml create mode 100644 tests/components/ethernet/test.esp32.yaml create mode 100644 tests/components/ethernet_info/test.esp32-idf.yaml create mode 100644 tests/components/ethernet_info/test.esp32.yaml create mode 100644 tests/components/exposure_notifications/test.esp32-c3-idf.yaml create mode 100644 tests/components/exposure_notifications/test.esp32-c3.yaml create mode 100644 tests/components/exposure_notifications/test.esp32-idf.yaml create mode 100644 tests/components/exposure_notifications/test.esp32.yaml create mode 100644 tests/components/external_components/test.esp32-c3-idf.yaml create mode 100644 tests/components/external_components/test.esp32-c3.yaml create mode 100644 tests/components/external_components/test.esp32-idf.yaml create mode 100644 tests/components/external_components/test.esp32.yaml create mode 100644 tests/components/external_components/test.esp8266.yaml create mode 100644 tests/components/external_components/test.rp2040.yaml create mode 100644 tests/components/ezo/test.esp32-c3-idf.yaml create mode 100644 tests/components/ezo/test.esp32-c3.yaml create mode 100644 tests/components/ezo/test.esp32-idf.yaml create mode 100644 tests/components/ezo/test.esp32.yaml create mode 100644 tests/components/ezo/test.esp8266.yaml create mode 100644 tests/components/ezo/test.rp2040.yaml create mode 100644 tests/components/ezo_pmp/test.esp32-c3-idf.yaml create mode 100644 tests/components/ezo_pmp/test.esp32-c3.yaml create mode 100644 tests/components/ezo_pmp/test.esp32-idf.yaml create mode 100644 tests/components/ezo_pmp/test.esp32.yaml create mode 100644 tests/components/ezo_pmp/test.esp8266.yaml create mode 100644 tests/components/ezo_pmp/test.rp2040.yaml diff --git a/tests/components/e131/test.esp32-c3-idf.yaml b/tests/components/e131/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..25304cd3b4 --- /dev/null +++ b/tests/components/e131/test.esp32-c3-idf.yaml @@ -0,0 +1,18 @@ +wifi: + ssid: MySSID + password: password1 + +e131: + +light: + - platform: esp32_rmt_led_strip + id: led_matrix_32x8 + default_transition_length: 500ms + chipset: ws2812 + rgb_order: GRB + num_leds: 256 + pin: 2 + rmt_channel: 0 + effects: + - e131: + universe: 1 diff --git a/tests/components/e131/test.esp32-c3.yaml b/tests/components/e131/test.esp32-c3.yaml new file mode 100644 index 0000000000..25304cd3b4 --- /dev/null +++ b/tests/components/e131/test.esp32-c3.yaml @@ -0,0 +1,18 @@ +wifi: + ssid: MySSID + password: password1 + +e131: + +light: + - platform: esp32_rmt_led_strip + id: led_matrix_32x8 + default_transition_length: 500ms + chipset: ws2812 + rgb_order: GRB + num_leds: 256 + pin: 2 + rmt_channel: 0 + effects: + - e131: + universe: 1 diff --git a/tests/components/e131/test.esp32-idf.yaml b/tests/components/e131/test.esp32-idf.yaml new file mode 100644 index 0000000000..25304cd3b4 --- /dev/null +++ b/tests/components/e131/test.esp32-idf.yaml @@ -0,0 +1,18 @@ +wifi: + ssid: MySSID + password: password1 + +e131: + +light: + - platform: esp32_rmt_led_strip + id: led_matrix_32x8 + default_transition_length: 500ms + chipset: ws2812 + rgb_order: GRB + num_leds: 256 + pin: 2 + rmt_channel: 0 + effects: + - e131: + universe: 1 diff --git a/tests/components/e131/test.esp32.yaml b/tests/components/e131/test.esp32.yaml new file mode 100644 index 0000000000..25304cd3b4 --- /dev/null +++ b/tests/components/e131/test.esp32.yaml @@ -0,0 +1,18 @@ +wifi: + ssid: MySSID + password: password1 + +e131: + +light: + - platform: esp32_rmt_led_strip + id: led_matrix_32x8 + default_transition_length: 500ms + chipset: ws2812 + rgb_order: GRB + num_leds: 256 + pin: 2 + rmt_channel: 0 + effects: + - e131: + universe: 1 diff --git a/tests/components/e131/test.esp8266.yaml b/tests/components/e131/test.esp8266.yaml new file mode 100644 index 0000000000..54245014a5 --- /dev/null +++ b/tests/components/e131/test.esp8266.yaml @@ -0,0 +1,17 @@ +wifi: + ssid: MySSID + password: password1 + +e131: + +light: + - platform: neopixelbus + name: Neopixelbus Light + pin: 1 + type: GRBW + variant: SK6812 + method: ESP8266_UART0 + num_leds: 256 + effects: + - e131: + universe: 1 diff --git a/tests/components/e131/test.rp2040.yaml b/tests/components/e131/test.rp2040.yaml new file mode 100644 index 0000000000..0ae31f5403 --- /dev/null +++ b/tests/components/e131/test.rp2040.yaml @@ -0,0 +1,17 @@ +wifi: + ssid: MySSID + password: password1 + +e131: + +light: + - platform: rp2040_pio_led_strip + id: led_strip + pin: 2 + pio: 0 + num_leds: 256 + rgb_order: GRB + chipset: WS2812 + effects: + - e131: + universe: 1 diff --git a/tests/components/ee895/test.esp32-c3-idf.yaml b/tests/components/ee895/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..4a36117fab --- /dev/null +++ b/tests/components/ee895/test.esp32-c3-idf.yaml @@ -0,0 +1,14 @@ +i2c: + - id: i2c_ee895 + scl: 5 + sda: 4 + +sensor: + - platform: ee895 + address: 0x5F + co2: + name: EE895 CO2 + temperature: + name: EE895 Temperature + pressure: + name: EE895 Pressure diff --git a/tests/components/ee895/test.esp32-c3.yaml b/tests/components/ee895/test.esp32-c3.yaml new file mode 100644 index 0000000000..4a36117fab --- /dev/null +++ b/tests/components/ee895/test.esp32-c3.yaml @@ -0,0 +1,14 @@ +i2c: + - id: i2c_ee895 + scl: 5 + sda: 4 + +sensor: + - platform: ee895 + address: 0x5F + co2: + name: EE895 CO2 + temperature: + name: EE895 Temperature + pressure: + name: EE895 Pressure diff --git a/tests/components/ee895/test.esp32-idf.yaml b/tests/components/ee895/test.esp32-idf.yaml new file mode 100644 index 0000000000..241bdb9574 --- /dev/null +++ b/tests/components/ee895/test.esp32-idf.yaml @@ -0,0 +1,14 @@ +i2c: + - id: i2c_ee895 + scl: 16 + sda: 17 + +sensor: + - platform: ee895 + address: 0x5F + co2: + name: EE895 CO2 + temperature: + name: EE895 Temperature + pressure: + name: EE895 Pressure diff --git a/tests/components/ee895/test.esp32.yaml b/tests/components/ee895/test.esp32.yaml new file mode 100644 index 0000000000..241bdb9574 --- /dev/null +++ b/tests/components/ee895/test.esp32.yaml @@ -0,0 +1,14 @@ +i2c: + - id: i2c_ee895 + scl: 16 + sda: 17 + +sensor: + - platform: ee895 + address: 0x5F + co2: + name: EE895 CO2 + temperature: + name: EE895 Temperature + pressure: + name: EE895 Pressure diff --git a/tests/components/ee895/test.esp8266.yaml b/tests/components/ee895/test.esp8266.yaml new file mode 100644 index 0000000000..4a36117fab --- /dev/null +++ b/tests/components/ee895/test.esp8266.yaml @@ -0,0 +1,14 @@ +i2c: + - id: i2c_ee895 + scl: 5 + sda: 4 + +sensor: + - platform: ee895 + address: 0x5F + co2: + name: EE895 CO2 + temperature: + name: EE895 Temperature + pressure: + name: EE895 Pressure diff --git a/tests/components/ee895/test.rp2040.yaml b/tests/components/ee895/test.rp2040.yaml new file mode 100644 index 0000000000..4a36117fab --- /dev/null +++ b/tests/components/ee895/test.rp2040.yaml @@ -0,0 +1,14 @@ +i2c: + - id: i2c_ee895 + scl: 5 + sda: 4 + +sensor: + - platform: ee895 + address: 0x5F + co2: + name: EE895 CO2 + temperature: + name: EE895 Temperature + pressure: + name: EE895 Pressure diff --git a/tests/components/ektf2232/test.esp32-c3-idf.yaml b/tests/components/ektf2232/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..371f2795a2 --- /dev/null +++ b/tests/components/ektf2232/test.esp32-c3-idf.yaml @@ -0,0 +1,24 @@ +i2c: + - id: i2c_ektf2232 + scl: 5 + sda: 4 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 3 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: ektf2232 + interrupt_pin: 6 + rts_pin: 7 + display: ssd1306_display + on_touch: + - logger.log: + format: Touch at (%d, %d) + args: [touch.x, touch.y] diff --git a/tests/components/ektf2232/test.esp32-c3.yaml b/tests/components/ektf2232/test.esp32-c3.yaml new file mode 100644 index 0000000000..371f2795a2 --- /dev/null +++ b/tests/components/ektf2232/test.esp32-c3.yaml @@ -0,0 +1,24 @@ +i2c: + - id: i2c_ektf2232 + scl: 5 + sda: 4 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 3 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: ektf2232 + interrupt_pin: 6 + rts_pin: 7 + display: ssd1306_display + on_touch: + - logger.log: + format: Touch at (%d, %d) + args: [touch.x, touch.y] diff --git a/tests/components/ektf2232/test.esp32-idf.yaml b/tests/components/ektf2232/test.esp32-idf.yaml new file mode 100644 index 0000000000..9c6eef8bb3 --- /dev/null +++ b/tests/components/ektf2232/test.esp32-idf.yaml @@ -0,0 +1,24 @@ +i2c: + - id: i2c_ektf2232 + scl: 16 + sda: 17 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 13 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: ektf2232 + interrupt_pin: 14 + rts_pin: 15 + display: ssd1306_display + on_touch: + - logger.log: + format: Touch at (%d, %d) + args: [touch.x, touch.y] diff --git a/tests/components/ektf2232/test.esp32.yaml b/tests/components/ektf2232/test.esp32.yaml new file mode 100644 index 0000000000..9c6eef8bb3 --- /dev/null +++ b/tests/components/ektf2232/test.esp32.yaml @@ -0,0 +1,24 @@ +i2c: + - id: i2c_ektf2232 + scl: 16 + sda: 17 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 13 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: ektf2232 + interrupt_pin: 14 + rts_pin: 15 + display: ssd1306_display + on_touch: + - logger.log: + format: Touch at (%d, %d) + args: [touch.x, touch.y] diff --git a/tests/components/ektf2232/test.esp8266.yaml b/tests/components/ektf2232/test.esp8266.yaml new file mode 100644 index 0000000000..03f18f7184 --- /dev/null +++ b/tests/components/ektf2232/test.esp8266.yaml @@ -0,0 +1,24 @@ +i2c: + - id: i2c_ektf2232 + scl: 5 + sda: 4 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 3 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: ektf2232 + interrupt_pin: 12 + rts_pin: 13 + display: ssd1306_display + on_touch: + - logger.log: + format: Touch at (%d, %d) + args: [touch.x, touch.y] diff --git a/tests/components/ektf2232/test.rp2040.yaml b/tests/components/ektf2232/test.rp2040.yaml new file mode 100644 index 0000000000..371f2795a2 --- /dev/null +++ b/tests/components/ektf2232/test.rp2040.yaml @@ -0,0 +1,24 @@ +i2c: + - id: i2c_ektf2232 + scl: 5 + sda: 4 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 3 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: ektf2232 + interrupt_pin: 6 + rts_pin: 7 + display: ssd1306_display + on_touch: + - logger.log: + format: Touch at (%d, %d) + args: [touch.x, touch.y] diff --git a/tests/components/emc2101/test.esp32-c3-idf.yaml b/tests/components/emc2101/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..d95bc1b001 --- /dev/null +++ b/tests/components/emc2101/test.esp32-c3-idf.yaml @@ -0,0 +1,25 @@ +i2c: + - id: i2c_emc2101 + scl: 5 + sda: 4 + +emc2101: + pwm: + resolution: 8 + +output: + - platform: emc2101 + id: fan_duty_cycle + +sensor: + - platform: emc2101 + internal_temperature: + id: internal_temperature_sensor + name: Internal Temperature Sensor + speed: + id: speed_sensor + name: Speed Sensor + duty_cycle: + id: duty_cycle_sensor + name: Duty Cycle Sensor + update_interval: 5s diff --git a/tests/components/emc2101/test.esp32-c3.yaml b/tests/components/emc2101/test.esp32-c3.yaml new file mode 100644 index 0000000000..d95bc1b001 --- /dev/null +++ b/tests/components/emc2101/test.esp32-c3.yaml @@ -0,0 +1,25 @@ +i2c: + - id: i2c_emc2101 + scl: 5 + sda: 4 + +emc2101: + pwm: + resolution: 8 + +output: + - platform: emc2101 + id: fan_duty_cycle + +sensor: + - platform: emc2101 + internal_temperature: + id: internal_temperature_sensor + name: Internal Temperature Sensor + speed: + id: speed_sensor + name: Speed Sensor + duty_cycle: + id: duty_cycle_sensor + name: Duty Cycle Sensor + update_interval: 5s diff --git a/tests/components/emc2101/test.esp32-idf.yaml b/tests/components/emc2101/test.esp32-idf.yaml new file mode 100644 index 0000000000..34a7d22b71 --- /dev/null +++ b/tests/components/emc2101/test.esp32-idf.yaml @@ -0,0 +1,25 @@ +i2c: + - id: i2c_emc2101 + scl: 16 + sda: 17 + +emc2101: + pwm: + resolution: 8 + +output: + - platform: emc2101 + id: fan_duty_cycle + +sensor: + - platform: emc2101 + internal_temperature: + id: internal_temperature_sensor + name: Internal Temperature Sensor + speed: + id: speed_sensor + name: Speed Sensor + duty_cycle: + id: duty_cycle_sensor + name: Duty Cycle Sensor + update_interval: 5s diff --git a/tests/components/emc2101/test.esp32.yaml b/tests/components/emc2101/test.esp32.yaml new file mode 100644 index 0000000000..34a7d22b71 --- /dev/null +++ b/tests/components/emc2101/test.esp32.yaml @@ -0,0 +1,25 @@ +i2c: + - id: i2c_emc2101 + scl: 16 + sda: 17 + +emc2101: + pwm: + resolution: 8 + +output: + - platform: emc2101 + id: fan_duty_cycle + +sensor: + - platform: emc2101 + internal_temperature: + id: internal_temperature_sensor + name: Internal Temperature Sensor + speed: + id: speed_sensor + name: Speed Sensor + duty_cycle: + id: duty_cycle_sensor + name: Duty Cycle Sensor + update_interval: 5s diff --git a/tests/components/emc2101/test.esp8266.yaml b/tests/components/emc2101/test.esp8266.yaml new file mode 100644 index 0000000000..d95bc1b001 --- /dev/null +++ b/tests/components/emc2101/test.esp8266.yaml @@ -0,0 +1,25 @@ +i2c: + - id: i2c_emc2101 + scl: 5 + sda: 4 + +emc2101: + pwm: + resolution: 8 + +output: + - platform: emc2101 + id: fan_duty_cycle + +sensor: + - platform: emc2101 + internal_temperature: + id: internal_temperature_sensor + name: Internal Temperature Sensor + speed: + id: speed_sensor + name: Speed Sensor + duty_cycle: + id: duty_cycle_sensor + name: Duty Cycle Sensor + update_interval: 5s diff --git a/tests/components/emc2101/test.rp2040.yaml b/tests/components/emc2101/test.rp2040.yaml new file mode 100644 index 0000000000..d95bc1b001 --- /dev/null +++ b/tests/components/emc2101/test.rp2040.yaml @@ -0,0 +1,25 @@ +i2c: + - id: i2c_emc2101 + scl: 5 + sda: 4 + +emc2101: + pwm: + resolution: 8 + +output: + - platform: emc2101 + id: fan_duty_cycle + +sensor: + - platform: emc2101 + internal_temperature: + id: internal_temperature_sensor + name: Internal Temperature Sensor + speed: + id: speed_sensor + name: Speed Sensor + duty_cycle: + id: duty_cycle_sensor + name: Duty Cycle Sensor + update_interval: 5s diff --git a/tests/components/endstop/test.esp32-c3-idf.yaml b/tests/components/endstop/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..341fbf7260 --- /dev/null +++ b/tests/components/endstop/test.esp32-c3-idf.yaml @@ -0,0 +1,33 @@ +binary_sensor: + - platform: template + id: bin1 + lambda: |- + if (millis() > 10000) { + return true; + } else { + return false; + } + +switch: + - platform: template + id: template_switch1 + optimistic: true + - platform: template + id: template_switch2 + optimistic: true + +cover: + - platform: endstop + id: endstop_cover + name: Endstop Cover + stop_action: + - switch.turn_on: template_switch1 + open_endstop: bin1 + open_action: + - switch.turn_on: template_switch1 + open_duration: 5min + close_endstop: bin1 + close_action: + - switch.turn_on: template_switch2 + close_duration: 4.5min + max_duration: 10min diff --git a/tests/components/endstop/test.esp32-c3.yaml b/tests/components/endstop/test.esp32-c3.yaml new file mode 100644 index 0000000000..341fbf7260 --- /dev/null +++ b/tests/components/endstop/test.esp32-c3.yaml @@ -0,0 +1,33 @@ +binary_sensor: + - platform: template + id: bin1 + lambda: |- + if (millis() > 10000) { + return true; + } else { + return false; + } + +switch: + - platform: template + id: template_switch1 + optimistic: true + - platform: template + id: template_switch2 + optimistic: true + +cover: + - platform: endstop + id: endstop_cover + name: Endstop Cover + stop_action: + - switch.turn_on: template_switch1 + open_endstop: bin1 + open_action: + - switch.turn_on: template_switch1 + open_duration: 5min + close_endstop: bin1 + close_action: + - switch.turn_on: template_switch2 + close_duration: 4.5min + max_duration: 10min diff --git a/tests/components/endstop/test.esp32-idf.yaml b/tests/components/endstop/test.esp32-idf.yaml new file mode 100644 index 0000000000..341fbf7260 --- /dev/null +++ b/tests/components/endstop/test.esp32-idf.yaml @@ -0,0 +1,33 @@ +binary_sensor: + - platform: template + id: bin1 + lambda: |- + if (millis() > 10000) { + return true; + } else { + return false; + } + +switch: + - platform: template + id: template_switch1 + optimistic: true + - platform: template + id: template_switch2 + optimistic: true + +cover: + - platform: endstop + id: endstop_cover + name: Endstop Cover + stop_action: + - switch.turn_on: template_switch1 + open_endstop: bin1 + open_action: + - switch.turn_on: template_switch1 + open_duration: 5min + close_endstop: bin1 + close_action: + - switch.turn_on: template_switch2 + close_duration: 4.5min + max_duration: 10min diff --git a/tests/components/endstop/test.esp32.yaml b/tests/components/endstop/test.esp32.yaml new file mode 100644 index 0000000000..341fbf7260 --- /dev/null +++ b/tests/components/endstop/test.esp32.yaml @@ -0,0 +1,33 @@ +binary_sensor: + - platform: template + id: bin1 + lambda: |- + if (millis() > 10000) { + return true; + } else { + return false; + } + +switch: + - platform: template + id: template_switch1 + optimistic: true + - platform: template + id: template_switch2 + optimistic: true + +cover: + - platform: endstop + id: endstop_cover + name: Endstop Cover + stop_action: + - switch.turn_on: template_switch1 + open_endstop: bin1 + open_action: + - switch.turn_on: template_switch1 + open_duration: 5min + close_endstop: bin1 + close_action: + - switch.turn_on: template_switch2 + close_duration: 4.5min + max_duration: 10min diff --git a/tests/components/endstop/test.esp8266.yaml b/tests/components/endstop/test.esp8266.yaml new file mode 100644 index 0000000000..341fbf7260 --- /dev/null +++ b/tests/components/endstop/test.esp8266.yaml @@ -0,0 +1,33 @@ +binary_sensor: + - platform: template + id: bin1 + lambda: |- + if (millis() > 10000) { + return true; + } else { + return false; + } + +switch: + - platform: template + id: template_switch1 + optimistic: true + - platform: template + id: template_switch2 + optimistic: true + +cover: + - platform: endstop + id: endstop_cover + name: Endstop Cover + stop_action: + - switch.turn_on: template_switch1 + open_endstop: bin1 + open_action: + - switch.turn_on: template_switch1 + open_duration: 5min + close_endstop: bin1 + close_action: + - switch.turn_on: template_switch2 + close_duration: 4.5min + max_duration: 10min diff --git a/tests/components/endstop/test.rp2040.yaml b/tests/components/endstop/test.rp2040.yaml new file mode 100644 index 0000000000..341fbf7260 --- /dev/null +++ b/tests/components/endstop/test.rp2040.yaml @@ -0,0 +1,33 @@ +binary_sensor: + - platform: template + id: bin1 + lambda: |- + if (millis() > 10000) { + return true; + } else { + return false; + } + +switch: + - platform: template + id: template_switch1 + optimistic: true + - platform: template + id: template_switch2 + optimistic: true + +cover: + - platform: endstop + id: endstop_cover + name: Endstop Cover + stop_action: + - switch.turn_on: template_switch1 + open_endstop: bin1 + open_action: + - switch.turn_on: template_switch1 + open_duration: 5min + close_endstop: bin1 + close_action: + - switch.turn_on: template_switch2 + close_duration: 4.5min + max_duration: 10min diff --git a/tests/components/ens160/test.esp32-c3-idf.yaml b/tests/components/ens160/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..29f48e812f --- /dev/null +++ b/tests/components/ens160/test.esp32-c3-idf.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_ens160 + scl: 5 + sda: 4 + +sensor: + - platform: ens160 + eco2: + name: ENS160 eCO2 + tvoc: + name: ENS160 Total Volatile Organic Compounds + aqi: + name: ENS160 Air Quality Index diff --git a/tests/components/ens160/test.esp32-c3.yaml b/tests/components/ens160/test.esp32-c3.yaml new file mode 100644 index 0000000000..29f48e812f --- /dev/null +++ b/tests/components/ens160/test.esp32-c3.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_ens160 + scl: 5 + sda: 4 + +sensor: + - platform: ens160 + eco2: + name: ENS160 eCO2 + tvoc: + name: ENS160 Total Volatile Organic Compounds + aqi: + name: ENS160 Air Quality Index diff --git a/tests/components/ens160/test.esp32-idf.yaml b/tests/components/ens160/test.esp32-idf.yaml new file mode 100644 index 0000000000..23f7674aef --- /dev/null +++ b/tests/components/ens160/test.esp32-idf.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_ens160 + scl: 16 + sda: 17 + +sensor: + - platform: ens160 + eco2: + name: ENS160 eCO2 + tvoc: + name: ENS160 Total Volatile Organic Compounds + aqi: + name: ENS160 Air Quality Index diff --git a/tests/components/ens160/test.esp32.yaml b/tests/components/ens160/test.esp32.yaml new file mode 100644 index 0000000000..23f7674aef --- /dev/null +++ b/tests/components/ens160/test.esp32.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_ens160 + scl: 16 + sda: 17 + +sensor: + - platform: ens160 + eco2: + name: ENS160 eCO2 + tvoc: + name: ENS160 Total Volatile Organic Compounds + aqi: + name: ENS160 Air Quality Index diff --git a/tests/components/ens160/test.esp8266.yaml b/tests/components/ens160/test.esp8266.yaml new file mode 100644 index 0000000000..29f48e812f --- /dev/null +++ b/tests/components/ens160/test.esp8266.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_ens160 + scl: 5 + sda: 4 + +sensor: + - platform: ens160 + eco2: + name: ENS160 eCO2 + tvoc: + name: ENS160 Total Volatile Organic Compounds + aqi: + name: ENS160 Air Quality Index diff --git a/tests/components/ens160/test.rp2040.yaml b/tests/components/ens160/test.rp2040.yaml new file mode 100644 index 0000000000..29f48e812f --- /dev/null +++ b/tests/components/ens160/test.rp2040.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_ens160 + scl: 5 + sda: 4 + +sensor: + - platform: ens160 + eco2: + name: ENS160 eCO2 + tvoc: + name: ENS160 Total Volatile Organic Compounds + aqi: + name: ENS160 Air Quality Index diff --git a/tests/components/ens210/test.esp32-c3-idf.yaml b/tests/components/ens210/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..bacb71f9f8 --- /dev/null +++ b/tests/components/ens210/test.esp32-c3-idf.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_ens210 + scl: 5 + sda: 4 + +sensor: + - platform: ens210 + temperature: + name: ENS210 Temperature + humidity: + name: ENS210 Humidity + update_interval: 15s diff --git a/tests/components/ens210/test.esp32-c3.yaml b/tests/components/ens210/test.esp32-c3.yaml new file mode 100644 index 0000000000..bacb71f9f8 --- /dev/null +++ b/tests/components/ens210/test.esp32-c3.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_ens210 + scl: 5 + sda: 4 + +sensor: + - platform: ens210 + temperature: + name: ENS210 Temperature + humidity: + name: ENS210 Humidity + update_interval: 15s diff --git a/tests/components/ens210/test.esp32-idf.yaml b/tests/components/ens210/test.esp32-idf.yaml new file mode 100644 index 0000000000..8b2d29cc25 --- /dev/null +++ b/tests/components/ens210/test.esp32-idf.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_ens210 + scl: 16 + sda: 17 + +sensor: + - platform: ens210 + temperature: + name: ENS210 Temperature + humidity: + name: ENS210 Humidity + update_interval: 15s diff --git a/tests/components/ens210/test.esp32.yaml b/tests/components/ens210/test.esp32.yaml new file mode 100644 index 0000000000..8b2d29cc25 --- /dev/null +++ b/tests/components/ens210/test.esp32.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_ens210 + scl: 16 + sda: 17 + +sensor: + - platform: ens210 + temperature: + name: ENS210 Temperature + humidity: + name: ENS210 Humidity + update_interval: 15s diff --git a/tests/components/ens210/test.esp8266.yaml b/tests/components/ens210/test.esp8266.yaml new file mode 100644 index 0000000000..bacb71f9f8 --- /dev/null +++ b/tests/components/ens210/test.esp8266.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_ens210 + scl: 5 + sda: 4 + +sensor: + - platform: ens210 + temperature: + name: ENS210 Temperature + humidity: + name: ENS210 Humidity + update_interval: 15s diff --git a/tests/components/ens210/test.rp2040.yaml b/tests/components/ens210/test.rp2040.yaml new file mode 100644 index 0000000000..bacb71f9f8 --- /dev/null +++ b/tests/components/ens210/test.rp2040.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_ens210 + scl: 5 + sda: 4 + +sensor: + - platform: ens210 + temperature: + name: ENS210 Temperature + humidity: + name: ENS210 Humidity + update_interval: 15s diff --git a/tests/components/esp32_ble/test.esp32-c3-idf.yaml b/tests/components/esp32_ble/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..76b35fc8f8 --- /dev/null +++ b/tests/components/esp32_ble/test.esp32-c3-idf.yaml @@ -0,0 +1,2 @@ +esp32_ble: + io_capability: keyboard_only diff --git a/tests/components/esp32_ble/test.esp32-c3.yaml b/tests/components/esp32_ble/test.esp32-c3.yaml new file mode 100644 index 0000000000..76b35fc8f8 --- /dev/null +++ b/tests/components/esp32_ble/test.esp32-c3.yaml @@ -0,0 +1,2 @@ +esp32_ble: + io_capability: keyboard_only diff --git a/tests/components/esp32_ble/test.esp32-idf.yaml b/tests/components/esp32_ble/test.esp32-idf.yaml new file mode 100644 index 0000000000..76b35fc8f8 --- /dev/null +++ b/tests/components/esp32_ble/test.esp32-idf.yaml @@ -0,0 +1,2 @@ +esp32_ble: + io_capability: keyboard_only diff --git a/tests/components/esp32_ble/test.esp32.yaml b/tests/components/esp32_ble/test.esp32.yaml new file mode 100644 index 0000000000..76b35fc8f8 --- /dev/null +++ b/tests/components/esp32_ble/test.esp32.yaml @@ -0,0 +1,2 @@ +esp32_ble: + io_capability: keyboard_only diff --git a/tests/components/esp32_ble_beacon/test.esp32-c3-idf.yaml b/tests/components/esp32_ble_beacon/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..aafb0341d7 --- /dev/null +++ b/tests/components/esp32_ble_beacon/test.esp32-c3-idf.yaml @@ -0,0 +1,3 @@ +esp32_ble_beacon: + type: iBeacon + uuid: 'c29ce823-e67a-4e71-bff2-abaa32e77a98' diff --git a/tests/components/esp32_ble_beacon/test.esp32-c3.yaml b/tests/components/esp32_ble_beacon/test.esp32-c3.yaml new file mode 100644 index 0000000000..aafb0341d7 --- /dev/null +++ b/tests/components/esp32_ble_beacon/test.esp32-c3.yaml @@ -0,0 +1,3 @@ +esp32_ble_beacon: + type: iBeacon + uuid: 'c29ce823-e67a-4e71-bff2-abaa32e77a98' diff --git a/tests/components/esp32_ble_beacon/test.esp32-idf.yaml b/tests/components/esp32_ble_beacon/test.esp32-idf.yaml new file mode 100644 index 0000000000..aafb0341d7 --- /dev/null +++ b/tests/components/esp32_ble_beacon/test.esp32-idf.yaml @@ -0,0 +1,3 @@ +esp32_ble_beacon: + type: iBeacon + uuid: 'c29ce823-e67a-4e71-bff2-abaa32e77a98' diff --git a/tests/components/esp32_ble_beacon/test.esp32.yaml b/tests/components/esp32_ble_beacon/test.esp32.yaml new file mode 100644 index 0000000000..aafb0341d7 --- /dev/null +++ b/tests/components/esp32_ble_beacon/test.esp32.yaml @@ -0,0 +1,3 @@ +esp32_ble_beacon: + type: iBeacon + uuid: 'c29ce823-e67a-4e71-bff2-abaa32e77a98' diff --git a/tests/components/esp32_ble_client/test.esp32-c3-idf.yaml b/tests/components/esp32_ble_client/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..33b7205bf2 --- /dev/null +++ b/tests/components/esp32_ble_client/test.esp32-c3-idf.yaml @@ -0,0 +1,5 @@ +esp32_ble_tracker: + +ble_client: + - mac_address: 01:02:03:04:05:06 + id: blec diff --git a/tests/components/esp32_ble_client/test.esp32-c3.yaml b/tests/components/esp32_ble_client/test.esp32-c3.yaml new file mode 100644 index 0000000000..33b7205bf2 --- /dev/null +++ b/tests/components/esp32_ble_client/test.esp32-c3.yaml @@ -0,0 +1,5 @@ +esp32_ble_tracker: + +ble_client: + - mac_address: 01:02:03:04:05:06 + id: blec diff --git a/tests/components/esp32_ble_client/test.esp32-idf.yaml b/tests/components/esp32_ble_client/test.esp32-idf.yaml new file mode 100644 index 0000000000..33b7205bf2 --- /dev/null +++ b/tests/components/esp32_ble_client/test.esp32-idf.yaml @@ -0,0 +1,5 @@ +esp32_ble_tracker: + +ble_client: + - mac_address: 01:02:03:04:05:06 + id: blec diff --git a/tests/components/esp32_ble_client/test.esp32.yaml b/tests/components/esp32_ble_client/test.esp32.yaml new file mode 100644 index 0000000000..33b7205bf2 --- /dev/null +++ b/tests/components/esp32_ble_client/test.esp32.yaml @@ -0,0 +1,5 @@ +esp32_ble_tracker: + +ble_client: + - mac_address: 01:02:03:04:05:06 + id: blec diff --git a/tests/components/esp32_ble_server/test.esp32-c3-idf.yaml b/tests/components/esp32_ble_server/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..29a5407f84 --- /dev/null +++ b/tests/components/esp32_ble_server/test.esp32-c3-idf.yaml @@ -0,0 +1,3 @@ +esp32_ble_server: + id: ble + manufacturer_data: [0x72, 0x4, 0x00, 0x23] diff --git a/tests/components/esp32_ble_server/test.esp32-c3.yaml b/tests/components/esp32_ble_server/test.esp32-c3.yaml new file mode 100644 index 0000000000..29a5407f84 --- /dev/null +++ b/tests/components/esp32_ble_server/test.esp32-c3.yaml @@ -0,0 +1,3 @@ +esp32_ble_server: + id: ble + manufacturer_data: [0x72, 0x4, 0x00, 0x23] diff --git a/tests/components/esp32_ble_server/test.esp32-idf.yaml b/tests/components/esp32_ble_server/test.esp32-idf.yaml new file mode 100644 index 0000000000..29a5407f84 --- /dev/null +++ b/tests/components/esp32_ble_server/test.esp32-idf.yaml @@ -0,0 +1,3 @@ +esp32_ble_server: + id: ble + manufacturer_data: [0x72, 0x4, 0x00, 0x23] diff --git a/tests/components/esp32_ble_server/test.esp32.yaml b/tests/components/esp32_ble_server/test.esp32.yaml new file mode 100644 index 0000000000..29a5407f84 --- /dev/null +++ b/tests/components/esp32_ble_server/test.esp32.yaml @@ -0,0 +1,3 @@ +esp32_ble_server: + id: ble + manufacturer_data: [0x72, 0x4, 0x00, 0x23] diff --git a/tests/components/esp32_ble_tracker/test.esp32-c3-idf.yaml b/tests/components/esp32_ble_tracker/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..ef23635c9e --- /dev/null +++ b/tests/components/esp32_ble_tracker/test.esp32-c3-idf.yaml @@ -0,0 +1,41 @@ +esphome: + on_boot: + then: + - esp32_ble_tracker.start_scan + - esp32_ble_tracker.stop_scan + +esp32_ble_tracker: + on_ble_advertise: + - mac_address: + - AA:BB:CC:DD:EE:FF + - FF:EE:DD:CC:BB:AA + then: + # yamllint disable rule:line-length + - lambda: !lambda |- + ESP_LOGD("main", "The device address (%s) exists in list", x.address_str().c_str()); + # yamllint enable rule:line-length + - mac_address: AC:37:43:77:5F:4C + then: + # yamllint disable rule:line-length + - lambda: !lambda |- + ESP_LOGD("main", "The device address is %s", x.address_str().c_str()); + # yamllint enable rule:line-length + - then: + # yamllint disable rule:line-length + - lambda: !lambda |- + ESP_LOGD("main", "The device address is %s", x.address_str().c_str()); + # yamllint enable rule:line-length + on_ble_service_data_advertise: + - service_uuid: ABCD + then: + - lambda: !lambda |- + ESP_LOGD("main", "Length of service data is %i", x.size()); + on_ble_manufacturer_data_advertise: + - manufacturer_id: ABCD + then: + - lambda: !lambda |- + ESP_LOGD("main", "Length of manufacturer data is %i", x.size()); + on_scan_end: + - then: + - lambda: |- + ESP_LOGD("ble_auto", "The scan has ended!"); diff --git a/tests/components/esp32_ble_tracker/test.esp32-c3.yaml b/tests/components/esp32_ble_tracker/test.esp32-c3.yaml new file mode 100644 index 0000000000..ef23635c9e --- /dev/null +++ b/tests/components/esp32_ble_tracker/test.esp32-c3.yaml @@ -0,0 +1,41 @@ +esphome: + on_boot: + then: + - esp32_ble_tracker.start_scan + - esp32_ble_tracker.stop_scan + +esp32_ble_tracker: + on_ble_advertise: + - mac_address: + - AA:BB:CC:DD:EE:FF + - FF:EE:DD:CC:BB:AA + then: + # yamllint disable rule:line-length + - lambda: !lambda |- + ESP_LOGD("main", "The device address (%s) exists in list", x.address_str().c_str()); + # yamllint enable rule:line-length + - mac_address: AC:37:43:77:5F:4C + then: + # yamllint disable rule:line-length + - lambda: !lambda |- + ESP_LOGD("main", "The device address is %s", x.address_str().c_str()); + # yamllint enable rule:line-length + - then: + # yamllint disable rule:line-length + - lambda: !lambda |- + ESP_LOGD("main", "The device address is %s", x.address_str().c_str()); + # yamllint enable rule:line-length + on_ble_service_data_advertise: + - service_uuid: ABCD + then: + - lambda: !lambda |- + ESP_LOGD("main", "Length of service data is %i", x.size()); + on_ble_manufacturer_data_advertise: + - manufacturer_id: ABCD + then: + - lambda: !lambda |- + ESP_LOGD("main", "Length of manufacturer data is %i", x.size()); + on_scan_end: + - then: + - lambda: |- + ESP_LOGD("ble_auto", "The scan has ended!"); diff --git a/tests/components/esp32_ble_tracker/test.esp32-idf.yaml b/tests/components/esp32_ble_tracker/test.esp32-idf.yaml new file mode 100644 index 0000000000..ef23635c9e --- /dev/null +++ b/tests/components/esp32_ble_tracker/test.esp32-idf.yaml @@ -0,0 +1,41 @@ +esphome: + on_boot: + then: + - esp32_ble_tracker.start_scan + - esp32_ble_tracker.stop_scan + +esp32_ble_tracker: + on_ble_advertise: + - mac_address: + - AA:BB:CC:DD:EE:FF + - FF:EE:DD:CC:BB:AA + then: + # yamllint disable rule:line-length + - lambda: !lambda |- + ESP_LOGD("main", "The device address (%s) exists in list", x.address_str().c_str()); + # yamllint enable rule:line-length + - mac_address: AC:37:43:77:5F:4C + then: + # yamllint disable rule:line-length + - lambda: !lambda |- + ESP_LOGD("main", "The device address is %s", x.address_str().c_str()); + # yamllint enable rule:line-length + - then: + # yamllint disable rule:line-length + - lambda: !lambda |- + ESP_LOGD("main", "The device address is %s", x.address_str().c_str()); + # yamllint enable rule:line-length + on_ble_service_data_advertise: + - service_uuid: ABCD + then: + - lambda: !lambda |- + ESP_LOGD("main", "Length of service data is %i", x.size()); + on_ble_manufacturer_data_advertise: + - manufacturer_id: ABCD + then: + - lambda: !lambda |- + ESP_LOGD("main", "Length of manufacturer data is %i", x.size()); + on_scan_end: + - then: + - lambda: |- + ESP_LOGD("ble_auto", "The scan has ended!"); diff --git a/tests/components/esp32_ble_tracker/test.esp32.yaml b/tests/components/esp32_ble_tracker/test.esp32.yaml new file mode 100644 index 0000000000..ef23635c9e --- /dev/null +++ b/tests/components/esp32_ble_tracker/test.esp32.yaml @@ -0,0 +1,41 @@ +esphome: + on_boot: + then: + - esp32_ble_tracker.start_scan + - esp32_ble_tracker.stop_scan + +esp32_ble_tracker: + on_ble_advertise: + - mac_address: + - AA:BB:CC:DD:EE:FF + - FF:EE:DD:CC:BB:AA + then: + # yamllint disable rule:line-length + - lambda: !lambda |- + ESP_LOGD("main", "The device address (%s) exists in list", x.address_str().c_str()); + # yamllint enable rule:line-length + - mac_address: AC:37:43:77:5F:4C + then: + # yamllint disable rule:line-length + - lambda: !lambda |- + ESP_LOGD("main", "The device address is %s", x.address_str().c_str()); + # yamllint enable rule:line-length + - then: + # yamllint disable rule:line-length + - lambda: !lambda |- + ESP_LOGD("main", "The device address is %s", x.address_str().c_str()); + # yamllint enable rule:line-length + on_ble_service_data_advertise: + - service_uuid: ABCD + then: + - lambda: !lambda |- + ESP_LOGD("main", "Length of service data is %i", x.size()); + on_ble_manufacturer_data_advertise: + - manufacturer_id: ABCD + then: + - lambda: !lambda |- + ESP_LOGD("main", "Length of manufacturer data is %i", x.size()); + on_scan_end: + - then: + - lambda: |- + ESP_LOGD("ble_auto", "The scan has ended!"); diff --git a/tests/components/esp32_camera/test.esp32-idf.yaml b/tests/components/esp32_camera/test.esp32-idf.yaml new file mode 100644 index 0000000000..366f601657 --- /dev/null +++ b/tests/components/esp32_camera/test.esp32-idf.yaml @@ -0,0 +1,28 @@ +esp32_camera: + name: ESP32 Camera + data_pins: + - number: 17 + - number: 35 + - number: 34 + - number: 5 + - number: 39 + - number: 18 + - number: 36 + - number: 19 + vsync_pin: 22 + href_pin: 26 + pixel_clock_pin: 21 + external_clock: + pin: 27 + frequency: 20MHz + i2c_pins: + sda: 25 + scl: 23 + reset_pin: 15 + power_down_pin: 1 + resolution: 640x480 + jpeg_quality: 10 + on_image: + then: + - lambda: |- + ESP_LOGD("main", "image len=%d, data=%c", image.length, image.data[0]); diff --git a/tests/components/esp32_camera/test.esp32.yaml b/tests/components/esp32_camera/test.esp32.yaml new file mode 100644 index 0000000000..366f601657 --- /dev/null +++ b/tests/components/esp32_camera/test.esp32.yaml @@ -0,0 +1,28 @@ +esp32_camera: + name: ESP32 Camera + data_pins: + - number: 17 + - number: 35 + - number: 34 + - number: 5 + - number: 39 + - number: 18 + - number: 36 + - number: 19 + vsync_pin: 22 + href_pin: 26 + pixel_clock_pin: 21 + external_clock: + pin: 27 + frequency: 20MHz + i2c_pins: + sda: 25 + scl: 23 + reset_pin: 15 + power_down_pin: 1 + resolution: 640x480 + jpeg_quality: 10 + on_image: + then: + - lambda: |- + ESP_LOGD("main", "image len=%d, data=%c", image.length, image.data[0]); diff --git a/tests/components/esp32_camera_web_server/test.esp32-idf.yaml b/tests/components/esp32_camera_web_server/test.esp32-idf.yaml new file mode 100644 index 0000000000..14b7bd5c34 --- /dev/null +++ b/tests/components/esp32_camera_web_server/test.esp32-idf.yaml @@ -0,0 +1,34 @@ +esp32_camera: + name: ESP32 Camera + data_pins: + - number: 17 + - number: 35 + - number: 34 + - number: 5 + - number: 39 + - number: 18 + - number: 36 + - number: 19 + vsync_pin: 22 + href_pin: 26 + pixel_clock_pin: 21 + external_clock: + pin: 27 + frequency: 20MHz + i2c_pins: + sda: 25 + scl: 23 + reset_pin: 15 + power_down_pin: 1 + resolution: 640x480 + jpeg_quality: 10 + on_image: + then: + - lambda: |- + ESP_LOGD("main", "image len=%d, data=%c", image.length, image.data[0]); + +esp32_camera_web_server: + - port: 8080 + mode: stream + - port: 8081 + mode: snapshot diff --git a/tests/components/esp32_camera_web_server/test.esp32.yaml b/tests/components/esp32_camera_web_server/test.esp32.yaml new file mode 100644 index 0000000000..14b7bd5c34 --- /dev/null +++ b/tests/components/esp32_camera_web_server/test.esp32.yaml @@ -0,0 +1,34 @@ +esp32_camera: + name: ESP32 Camera + data_pins: + - number: 17 + - number: 35 + - number: 34 + - number: 5 + - number: 39 + - number: 18 + - number: 36 + - number: 19 + vsync_pin: 22 + href_pin: 26 + pixel_clock_pin: 21 + external_clock: + pin: 27 + frequency: 20MHz + i2c_pins: + sda: 25 + scl: 23 + reset_pin: 15 + power_down_pin: 1 + resolution: 640x480 + jpeg_quality: 10 + on_image: + then: + - lambda: |- + ESP_LOGD("main", "image len=%d, data=%c", image.length, image.data[0]); + +esp32_camera_web_server: + - port: 8080 + mode: stream + - port: 8081 + mode: snapshot diff --git a/tests/components/esp32_can/test.esp32-c3-idf.yaml b/tests/components/esp32_can/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..b4fd34cf51 --- /dev/null +++ b/tests/components/esp32_can/test.esp32-c3-idf.yaml @@ -0,0 +1,45 @@ +esphome: + on_boot: + then: + - canbus.send: + # Extended ID explicit + use_extended_id: true + can_id: 0x100 + data: [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08] + - canbus.send: + # Standard ID by default + can_id: 0x100 + data: [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08] + +canbus: + - platform: esp32_can + id: esp32_internal_can + rx_pin: 4 + tx_pin: 5 + can_id: 4 + bit_rate: 50kbps + on_frame: + - can_id: 500 + then: + - lambda: |- + std::string b(x.begin(), x.end()); + ESP_LOGD("canid 500", "%s", b.c_str() ); + - can_id: 0b00000000000000000000001000000 + can_id_mask: 0b11111000000000011111111000000 + use_extended_id: true + then: + - lambda: |- + auto pdo_id = can_id >> 14; + switch (pdo_id) + { + case 117: + ESP_LOGD("canbus", "exhaust_fan_duty"); + break; + case 118: + ESP_LOGD("canbus", "supply_fan_duty"); + break; + case 119: + ESP_LOGD("canbus", "supply_fan_flow"); + break; + // to be continued... + } diff --git a/tests/components/esp32_can/test.esp32-c3.yaml b/tests/components/esp32_can/test.esp32-c3.yaml new file mode 100644 index 0000000000..b4fd34cf51 --- /dev/null +++ b/tests/components/esp32_can/test.esp32-c3.yaml @@ -0,0 +1,45 @@ +esphome: + on_boot: + then: + - canbus.send: + # Extended ID explicit + use_extended_id: true + can_id: 0x100 + data: [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08] + - canbus.send: + # Standard ID by default + can_id: 0x100 + data: [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08] + +canbus: + - platform: esp32_can + id: esp32_internal_can + rx_pin: 4 + tx_pin: 5 + can_id: 4 + bit_rate: 50kbps + on_frame: + - can_id: 500 + then: + - lambda: |- + std::string b(x.begin(), x.end()); + ESP_LOGD("canid 500", "%s", b.c_str() ); + - can_id: 0b00000000000000000000001000000 + can_id_mask: 0b11111000000000011111111000000 + use_extended_id: true + then: + - lambda: |- + auto pdo_id = can_id >> 14; + switch (pdo_id) + { + case 117: + ESP_LOGD("canbus", "exhaust_fan_duty"); + break; + case 118: + ESP_LOGD("canbus", "supply_fan_duty"); + break; + case 119: + ESP_LOGD("canbus", "supply_fan_flow"); + break; + // to be continued... + } diff --git a/tests/components/esp32_can/test.esp32-idf.yaml b/tests/components/esp32_can/test.esp32-idf.yaml new file mode 100644 index 0000000000..159a695853 --- /dev/null +++ b/tests/components/esp32_can/test.esp32-idf.yaml @@ -0,0 +1,45 @@ +esphome: + on_boot: + then: + - canbus.send: + # Extended ID explicit + use_extended_id: true + can_id: 0x100 + data: [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08] + - canbus.send: + # Standard ID by default + can_id: 0x100 + data: [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08] + +canbus: + - platform: esp32_can + id: esp32_internal_can + rx_pin: 13 + tx_pin: 14 + can_id: 4 + bit_rate: 50kbps + on_frame: + - can_id: 500 + then: + - lambda: |- + std::string b(x.begin(), x.end()); + ESP_LOGD("canid 500", "%s", b.c_str() ); + - can_id: 0b00000000000000000000001000000 + can_id_mask: 0b11111000000000011111111000000 + use_extended_id: true + then: + - lambda: |- + auto pdo_id = can_id >> 14; + switch (pdo_id) + { + case 117: + ESP_LOGD("canbus", "exhaust_fan_duty"); + break; + case 118: + ESP_LOGD("canbus", "supply_fan_duty"); + break; + case 119: + ESP_LOGD("canbus", "supply_fan_flow"); + break; + // to be continued... + } diff --git a/tests/components/esp32_can/test.esp32.yaml b/tests/components/esp32_can/test.esp32.yaml new file mode 100644 index 0000000000..159a695853 --- /dev/null +++ b/tests/components/esp32_can/test.esp32.yaml @@ -0,0 +1,45 @@ +esphome: + on_boot: + then: + - canbus.send: + # Extended ID explicit + use_extended_id: true + can_id: 0x100 + data: [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08] + - canbus.send: + # Standard ID by default + can_id: 0x100 + data: [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08] + +canbus: + - platform: esp32_can + id: esp32_internal_can + rx_pin: 13 + tx_pin: 14 + can_id: 4 + bit_rate: 50kbps + on_frame: + - can_id: 500 + then: + - lambda: |- + std::string b(x.begin(), x.end()); + ESP_LOGD("canid 500", "%s", b.c_str() ); + - can_id: 0b00000000000000000000001000000 + can_id_mask: 0b11111000000000011111111000000 + use_extended_id: true + then: + - lambda: |- + auto pdo_id = can_id >> 14; + switch (pdo_id) + { + case 117: + ESP_LOGD("canbus", "exhaust_fan_duty"); + break; + case 118: + ESP_LOGD("canbus", "supply_fan_duty"); + break; + case 119: + ESP_LOGD("canbus", "supply_fan_flow"); + break; + // to be continued... + } diff --git a/tests/components/esp32_dac/test.esp32-idf.yaml b/tests/components/esp32_dac/test.esp32-idf.yaml new file mode 100644 index 0000000000..225627f5af --- /dev/null +++ b/tests/components/esp32_dac/test.esp32-idf.yaml @@ -0,0 +1,4 @@ +output: + - platform: esp32_dac + id: dac_output + pin: 25 diff --git a/tests/components/esp32_dac/test.esp32.yaml b/tests/components/esp32_dac/test.esp32.yaml new file mode 100644 index 0000000000..225627f5af --- /dev/null +++ b/tests/components/esp32_dac/test.esp32.yaml @@ -0,0 +1,4 @@ +output: + - platform: esp32_dac + id: dac_output + pin: 25 diff --git a/tests/components/esp32_hall/test.esp32-idf.yaml b/tests/components/esp32_hall/test.esp32-idf.yaml new file mode 100644 index 0000000000..f8429f5aa0 --- /dev/null +++ b/tests/components/esp32_hall/test.esp32-idf.yaml @@ -0,0 +1,3 @@ +sensor: + - platform: esp32_hall + name: ESP32 Hall Sensor diff --git a/tests/components/esp32_hall/test.esp32.yaml b/tests/components/esp32_hall/test.esp32.yaml new file mode 100644 index 0000000000..f8429f5aa0 --- /dev/null +++ b/tests/components/esp32_hall/test.esp32.yaml @@ -0,0 +1,3 @@ +sensor: + - platform: esp32_hall + name: ESP32 Hall Sensor diff --git a/tests/components/esp32_improv/test.esp32-c3-idf.yaml b/tests/components/esp32_improv/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..7eb3f9c0be --- /dev/null +++ b/tests/components/esp32_improv/test.esp32-c3-idf.yaml @@ -0,0 +1,18 @@ +wifi: + ssid: MySSID + password: password1 + +binary_sensor: + - platform: gpio + pin: 0 + id: io0_button + +output: + - platform: gpio + pin: 2 + id: built_in_led + +esp32_improv: + authorizer: io0_button + authorized_duration: 1min + status_indicator: built_in_led diff --git a/tests/components/esp32_improv/test.esp32-c3.yaml b/tests/components/esp32_improv/test.esp32-c3.yaml new file mode 100644 index 0000000000..7eb3f9c0be --- /dev/null +++ b/tests/components/esp32_improv/test.esp32-c3.yaml @@ -0,0 +1,18 @@ +wifi: + ssid: MySSID + password: password1 + +binary_sensor: + - platform: gpio + pin: 0 + id: io0_button + +output: + - platform: gpio + pin: 2 + id: built_in_led + +esp32_improv: + authorizer: io0_button + authorized_duration: 1min + status_indicator: built_in_led diff --git a/tests/components/esp32_improv/test.esp32-idf.yaml b/tests/components/esp32_improv/test.esp32-idf.yaml new file mode 100644 index 0000000000..7eb3f9c0be --- /dev/null +++ b/tests/components/esp32_improv/test.esp32-idf.yaml @@ -0,0 +1,18 @@ +wifi: + ssid: MySSID + password: password1 + +binary_sensor: + - platform: gpio + pin: 0 + id: io0_button + +output: + - platform: gpio + pin: 2 + id: built_in_led + +esp32_improv: + authorizer: io0_button + authorized_duration: 1min + status_indicator: built_in_led diff --git a/tests/components/esp32_improv/test.esp32.yaml b/tests/components/esp32_improv/test.esp32.yaml new file mode 100644 index 0000000000..7eb3f9c0be --- /dev/null +++ b/tests/components/esp32_improv/test.esp32.yaml @@ -0,0 +1,18 @@ +wifi: + ssid: MySSID + password: password1 + +binary_sensor: + - platform: gpio + pin: 0 + id: io0_button + +output: + - platform: gpio + pin: 2 + id: built_in_led + +esp32_improv: + authorizer: io0_button + authorized_duration: 1min + status_indicator: built_in_led diff --git a/tests/components/esp32_rmt_led_strip/test.esp32-c3-idf.yaml b/tests/components/esp32_rmt_led_strip/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..b226d1de06 --- /dev/null +++ b/tests/components/esp32_rmt_led_strip/test.esp32-c3-idf.yaml @@ -0,0 +1,18 @@ +light: + - platform: esp32_rmt_led_strip + id: led_strip + pin: 4 + num_leds: 60 + rmt_channel: 0 + rgb_order: GRB + chipset: ws2812 + - platform: esp32_rmt_led_strip + id: led_strip2 + pin: 5 + num_leds: 60 + rmt_channel: 1 + rgb_order: RGB + bit0_high: 100us + bit0_low: 100us + bit1_high: 100us + bit1_low: 100us diff --git a/tests/components/esp32_rmt_led_strip/test.esp32-c3.yaml b/tests/components/esp32_rmt_led_strip/test.esp32-c3.yaml new file mode 100644 index 0000000000..b226d1de06 --- /dev/null +++ b/tests/components/esp32_rmt_led_strip/test.esp32-c3.yaml @@ -0,0 +1,18 @@ +light: + - platform: esp32_rmt_led_strip + id: led_strip + pin: 4 + num_leds: 60 + rmt_channel: 0 + rgb_order: GRB + chipset: ws2812 + - platform: esp32_rmt_led_strip + id: led_strip2 + pin: 5 + num_leds: 60 + rmt_channel: 1 + rgb_order: RGB + bit0_high: 100us + bit0_low: 100us + bit1_high: 100us + bit1_low: 100us diff --git a/tests/components/esp32_rmt_led_strip/test.esp32-idf.yaml b/tests/components/esp32_rmt_led_strip/test.esp32-idf.yaml new file mode 100644 index 0000000000..d51a66451f --- /dev/null +++ b/tests/components/esp32_rmt_led_strip/test.esp32-idf.yaml @@ -0,0 +1,18 @@ +light: + - platform: esp32_rmt_led_strip + id: led_strip + pin: 13 + num_leds: 60 + rmt_channel: 6 + rgb_order: GRB + chipset: ws2812 + - platform: esp32_rmt_led_strip + id: led_strip2 + pin: 14 + num_leds: 60 + rmt_channel: 2 + rgb_order: RGB + bit0_high: 100us + bit0_low: 100us + bit1_high: 100us + bit1_low: 100us diff --git a/tests/components/esp32_rmt_led_strip/test.esp32.yaml b/tests/components/esp32_rmt_led_strip/test.esp32.yaml new file mode 100644 index 0000000000..d51a66451f --- /dev/null +++ b/tests/components/esp32_rmt_led_strip/test.esp32.yaml @@ -0,0 +1,18 @@ +light: + - platform: esp32_rmt_led_strip + id: led_strip + pin: 13 + num_leds: 60 + rmt_channel: 6 + rgb_order: GRB + chipset: ws2812 + - platform: esp32_rmt_led_strip + id: led_strip2 + pin: 14 + num_leds: 60 + rmt_channel: 2 + rgb_order: RGB + bit0_high: 100us + bit0_low: 100us + bit1_high: 100us + bit1_low: 100us diff --git a/tests/components/esp32_touch/test.esp32-idf.yaml b/tests/components/esp32_touch/test.esp32-idf.yaml new file mode 100644 index 0000000000..691cce8d86 --- /dev/null +++ b/tests/components/esp32_touch/test.esp32-idf.yaml @@ -0,0 +1,16 @@ +esp32_touch: + setup_mode: false + iir_filter: 10ms + sleep_duration: 27ms + measurement_duration: 8ms + low_voltage_reference: 0.5V + high_voltage_reference: 2.7V + voltage_attenuation: 1.5V + +binary_sensor: + - platform: esp32_touch + name: ESP32 Touch Pad + pin: 27 + threshold: 1000 + on_press: + - logger.log: "I'm touched!" diff --git a/tests/components/esp32_touch/test.esp32.yaml b/tests/components/esp32_touch/test.esp32.yaml new file mode 100644 index 0000000000..691cce8d86 --- /dev/null +++ b/tests/components/esp32_touch/test.esp32.yaml @@ -0,0 +1,16 @@ +esp32_touch: + setup_mode: false + iir_filter: 10ms + sleep_duration: 27ms + measurement_duration: 8ms + low_voltage_reference: 0.5V + high_voltage_reference: 2.7V + voltage_attenuation: 1.5V + +binary_sensor: + - platform: esp32_touch + name: ESP32 Touch Pad + pin: 27 + threshold: 1000 + on_press: + - logger.log: "I'm touched!" diff --git a/tests/components/esp8266_pwm/test.esp8266.yaml b/tests/components/esp8266_pwm/test.esp8266.yaml new file mode 100644 index 0000000000..52b290f91b --- /dev/null +++ b/tests/components/esp8266_pwm/test.esp8266.yaml @@ -0,0 +1,8 @@ +output: + - platform: esp8266_pwm + id: out + pin: 4 + frequency: 50Hz + - platform: esp8266_pwm + id: out2 + pin: 5 diff --git a/tests/components/ethernet/test.esp32-idf.yaml b/tests/components/ethernet/test.esp32-idf.yaml new file mode 100644 index 0000000000..b9ed9cb036 --- /dev/null +++ b/tests/components/ethernet/test.esp32-idf.yaml @@ -0,0 +1,12 @@ +ethernet: + type: LAN8720 + mdc_pin: 23 + mdio_pin: 25 + clk_mode: GPIO0_IN + phy_addr: 0 + power_pin: 26 + manual_ip: + static_ip: 192.168.178.56 + gateway: 192.168.178.1 + subnet: 255.255.255.0 + domain: .local diff --git a/tests/components/ethernet/test.esp32.yaml b/tests/components/ethernet/test.esp32.yaml new file mode 100644 index 0000000000..b9ed9cb036 --- /dev/null +++ b/tests/components/ethernet/test.esp32.yaml @@ -0,0 +1,12 @@ +ethernet: + type: LAN8720 + mdc_pin: 23 + mdio_pin: 25 + clk_mode: GPIO0_IN + phy_addr: 0 + power_pin: 26 + manual_ip: + static_ip: 192.168.178.56 + gateway: 192.168.178.1 + subnet: 255.255.255.0 + domain: .local diff --git a/tests/components/ethernet_info/test.esp32-idf.yaml b/tests/components/ethernet_info/test.esp32-idf.yaml new file mode 100644 index 0000000000..c5da2bb666 --- /dev/null +++ b/tests/components/ethernet_info/test.esp32-idf.yaml @@ -0,0 +1,17 @@ +ethernet: + type: LAN8720 + mdc_pin: 23 + mdio_pin: 25 + clk_mode: GPIO0_IN + phy_addr: 0 + power_pin: 26 + manual_ip: + static_ip: 192.168.178.56 + gateway: 192.168.178.1 + subnet: 255.255.255.0 + domain: .local + +text_sensor: + - platform: ethernet_info + ip_address: + name: IP Address diff --git a/tests/components/ethernet_info/test.esp32.yaml b/tests/components/ethernet_info/test.esp32.yaml new file mode 100644 index 0000000000..c5da2bb666 --- /dev/null +++ b/tests/components/ethernet_info/test.esp32.yaml @@ -0,0 +1,17 @@ +ethernet: + type: LAN8720 + mdc_pin: 23 + mdio_pin: 25 + clk_mode: GPIO0_IN + phy_addr: 0 + power_pin: 26 + manual_ip: + static_ip: 192.168.178.56 + gateway: 192.168.178.1 + subnet: 255.255.255.0 + domain: .local + +text_sensor: + - platform: ethernet_info + ip_address: + name: IP Address diff --git a/tests/components/exposure_notifications/test.esp32-c3-idf.yaml b/tests/components/exposure_notifications/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..faba5bb2d1 --- /dev/null +++ b/tests/components/exposure_notifications/test.esp32-c3-idf.yaml @@ -0,0 +1,9 @@ +esp32_ble_tracker: + +exposure_notifications: + on_exposure_notification: + then: + - lambda: | + ESP_LOGD("main", "Got notification:"); + ESP_LOGD("main", " RPI: %s", format_hex(x.rolling_proximity_identifier).c_str()); + ESP_LOGD("main", " RSSI: %d", x.rssi); diff --git a/tests/components/exposure_notifications/test.esp32-c3.yaml b/tests/components/exposure_notifications/test.esp32-c3.yaml new file mode 100644 index 0000000000..faba5bb2d1 --- /dev/null +++ b/tests/components/exposure_notifications/test.esp32-c3.yaml @@ -0,0 +1,9 @@ +esp32_ble_tracker: + +exposure_notifications: + on_exposure_notification: + then: + - lambda: | + ESP_LOGD("main", "Got notification:"); + ESP_LOGD("main", " RPI: %s", format_hex(x.rolling_proximity_identifier).c_str()); + ESP_LOGD("main", " RSSI: %d", x.rssi); diff --git a/tests/components/exposure_notifications/test.esp32-idf.yaml b/tests/components/exposure_notifications/test.esp32-idf.yaml new file mode 100644 index 0000000000..faba5bb2d1 --- /dev/null +++ b/tests/components/exposure_notifications/test.esp32-idf.yaml @@ -0,0 +1,9 @@ +esp32_ble_tracker: + +exposure_notifications: + on_exposure_notification: + then: + - lambda: | + ESP_LOGD("main", "Got notification:"); + ESP_LOGD("main", " RPI: %s", format_hex(x.rolling_proximity_identifier).c_str()); + ESP_LOGD("main", " RSSI: %d", x.rssi); diff --git a/tests/components/exposure_notifications/test.esp32.yaml b/tests/components/exposure_notifications/test.esp32.yaml new file mode 100644 index 0000000000..faba5bb2d1 --- /dev/null +++ b/tests/components/exposure_notifications/test.esp32.yaml @@ -0,0 +1,9 @@ +esp32_ble_tracker: + +exposure_notifications: + on_exposure_notification: + then: + - lambda: | + ESP_LOGD("main", "Got notification:"); + ESP_LOGD("main", " RPI: %s", format_hex(x.rolling_proximity_identifier).c_str()); + ESP_LOGD("main", " RSSI: %d", x.rssi); diff --git a/tests/components/external_components/test.esp32-c3-idf.yaml b/tests/components/external_components/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..2b51267ec6 --- /dev/null +++ b/tests/components/external_components/test.esp32-c3-idf.yaml @@ -0,0 +1,6 @@ +external_components: + - source: github://esphome/esphome@dev + refresh: 1d + components: [bh1750] + - source: ../../../esphome/components + components: [sntp] diff --git a/tests/components/external_components/test.esp32-c3.yaml b/tests/components/external_components/test.esp32-c3.yaml new file mode 100644 index 0000000000..2b51267ec6 --- /dev/null +++ b/tests/components/external_components/test.esp32-c3.yaml @@ -0,0 +1,6 @@ +external_components: + - source: github://esphome/esphome@dev + refresh: 1d + components: [bh1750] + - 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 new file mode 100644 index 0000000000..2b51267ec6 --- /dev/null +++ b/tests/components/external_components/test.esp32-idf.yaml @@ -0,0 +1,6 @@ +external_components: + - source: github://esphome/esphome@dev + refresh: 1d + components: [bh1750] + - source: ../../../esphome/components + components: [sntp] diff --git a/tests/components/external_components/test.esp32.yaml b/tests/components/external_components/test.esp32.yaml new file mode 100644 index 0000000000..2b51267ec6 --- /dev/null +++ b/tests/components/external_components/test.esp32.yaml @@ -0,0 +1,6 @@ +external_components: + - source: github://esphome/esphome@dev + refresh: 1d + components: [bh1750] + - source: ../../../esphome/components + components: [sntp] diff --git a/tests/components/external_components/test.esp8266.yaml b/tests/components/external_components/test.esp8266.yaml new file mode 100644 index 0000000000..2b51267ec6 --- /dev/null +++ b/tests/components/external_components/test.esp8266.yaml @@ -0,0 +1,6 @@ +external_components: + - source: github://esphome/esphome@dev + refresh: 1d + components: [bh1750] + - source: ../../../esphome/components + components: [sntp] diff --git a/tests/components/external_components/test.rp2040.yaml b/tests/components/external_components/test.rp2040.yaml new file mode 100644 index 0000000000..2b51267ec6 --- /dev/null +++ b/tests/components/external_components/test.rp2040.yaml @@ -0,0 +1,6 @@ +external_components: + - source: github://esphome/esphome@dev + refresh: 1d + components: [bh1750] + - source: ../../../esphome/components + components: [sntp] diff --git a/tests/components/ezo/test.esp32-c3-idf.yaml b/tests/components/ezo/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..93ceb9efd3 --- /dev/null +++ b/tests/components/ezo/test.esp32-c3-idf.yaml @@ -0,0 +1,10 @@ +i2c: + - id: i2c_ezo + scl: 5 + sda: 4 + +sensor: + - platform: ezo + id: ph_ezo + address: 99 + unit_of_measurement: pH diff --git a/tests/components/ezo/test.esp32-c3.yaml b/tests/components/ezo/test.esp32-c3.yaml new file mode 100644 index 0000000000..93ceb9efd3 --- /dev/null +++ b/tests/components/ezo/test.esp32-c3.yaml @@ -0,0 +1,10 @@ +i2c: + - id: i2c_ezo + scl: 5 + sda: 4 + +sensor: + - platform: ezo + id: ph_ezo + address: 99 + unit_of_measurement: pH diff --git a/tests/components/ezo/test.esp32-idf.yaml b/tests/components/ezo/test.esp32-idf.yaml new file mode 100644 index 0000000000..61a8d2b25f --- /dev/null +++ b/tests/components/ezo/test.esp32-idf.yaml @@ -0,0 +1,10 @@ +i2c: + - id: i2c_ezo + scl: 16 + sda: 17 + +sensor: + - platform: ezo + id: ph_ezo + address: 99 + unit_of_measurement: pH diff --git a/tests/components/ezo/test.esp32.yaml b/tests/components/ezo/test.esp32.yaml new file mode 100644 index 0000000000..61a8d2b25f --- /dev/null +++ b/tests/components/ezo/test.esp32.yaml @@ -0,0 +1,10 @@ +i2c: + - id: i2c_ezo + scl: 16 + sda: 17 + +sensor: + - platform: ezo + id: ph_ezo + address: 99 + unit_of_measurement: pH diff --git a/tests/components/ezo/test.esp8266.yaml b/tests/components/ezo/test.esp8266.yaml new file mode 100644 index 0000000000..93ceb9efd3 --- /dev/null +++ b/tests/components/ezo/test.esp8266.yaml @@ -0,0 +1,10 @@ +i2c: + - id: i2c_ezo + scl: 5 + sda: 4 + +sensor: + - platform: ezo + id: ph_ezo + address: 99 + unit_of_measurement: pH diff --git a/tests/components/ezo/test.rp2040.yaml b/tests/components/ezo/test.rp2040.yaml new file mode 100644 index 0000000000..93ceb9efd3 --- /dev/null +++ b/tests/components/ezo/test.rp2040.yaml @@ -0,0 +1,10 @@ +i2c: + - id: i2c_ezo + scl: 5 + sda: 4 + +sensor: + - platform: ezo + id: ph_ezo + address: 99 + unit_of_measurement: pH diff --git a/tests/components/ezo_pmp/test.esp32-c3-idf.yaml b/tests/components/ezo_pmp/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..fa047de3de --- /dev/null +++ b/tests/components/ezo_pmp/test.esp32-c3-idf.yaml @@ -0,0 +1,61 @@ +i2c: + - id: i2c_ezo_pmp + scl: 5 + sda: 4 + +ezo_pmp: + id: hcl_pump + update_interval: 1s + +binary_sensor: + - platform: ezo_pmp + pump_state: + name: Pump State + is_paused: + name: Is Paused + +sensor: + - platform: ezo_pmp + current_volume_dosed: + name: Current Volume Dosed + total_volume_dosed: + name: Total Volume Dosed + absolute_total_volume_dosed: + name: Absolute Total Volume Dosed + pump_voltage: + name: Pump Voltage + last_volume_requested: + name: Last Volume Requested + max_flow_rate: + name: Max Flow Rate + +text_sensor: + - platform: ezo_pmp + dosing_mode: + name: Dosing Mode + calibration_status: + name: Calibration Status + on_value: + - ezo_pmp.dose_volume: + id: hcl_pump + volume: 10 + - ezo_pmp.dose_volume_over_time: + id: hcl_pump + volume: 10 + duration: 2 + - ezo_pmp.dose_with_constant_flow_rate: + id: hcl_pump + volume_per_minute: 10 + duration: 2 + - ezo_pmp.set_calibration_volume: + id: hcl_pump + volume: 10 + - ezo_pmp.find: hcl_pump + - ezo_pmp.dose_continuously: hcl_pump + - ezo_pmp.clear_total_volume_dosed: hcl_pump + - ezo_pmp.clear_calibration: hcl_pump + - ezo_pmp.pause_dosing: hcl_pump + - ezo_pmp.stop_dosing: hcl_pump + - ezo_pmp.arbitrary_command: + id: hcl_pump + command: D,? diff --git a/tests/components/ezo_pmp/test.esp32-c3.yaml b/tests/components/ezo_pmp/test.esp32-c3.yaml new file mode 100644 index 0000000000..fa047de3de --- /dev/null +++ b/tests/components/ezo_pmp/test.esp32-c3.yaml @@ -0,0 +1,61 @@ +i2c: + - id: i2c_ezo_pmp + scl: 5 + sda: 4 + +ezo_pmp: + id: hcl_pump + update_interval: 1s + +binary_sensor: + - platform: ezo_pmp + pump_state: + name: Pump State + is_paused: + name: Is Paused + +sensor: + - platform: ezo_pmp + current_volume_dosed: + name: Current Volume Dosed + total_volume_dosed: + name: Total Volume Dosed + absolute_total_volume_dosed: + name: Absolute Total Volume Dosed + pump_voltage: + name: Pump Voltage + last_volume_requested: + name: Last Volume Requested + max_flow_rate: + name: Max Flow Rate + +text_sensor: + - platform: ezo_pmp + dosing_mode: + name: Dosing Mode + calibration_status: + name: Calibration Status + on_value: + - ezo_pmp.dose_volume: + id: hcl_pump + volume: 10 + - ezo_pmp.dose_volume_over_time: + id: hcl_pump + volume: 10 + duration: 2 + - ezo_pmp.dose_with_constant_flow_rate: + id: hcl_pump + volume_per_minute: 10 + duration: 2 + - ezo_pmp.set_calibration_volume: + id: hcl_pump + volume: 10 + - ezo_pmp.find: hcl_pump + - ezo_pmp.dose_continuously: hcl_pump + - ezo_pmp.clear_total_volume_dosed: hcl_pump + - ezo_pmp.clear_calibration: hcl_pump + - ezo_pmp.pause_dosing: hcl_pump + - ezo_pmp.stop_dosing: hcl_pump + - ezo_pmp.arbitrary_command: + id: hcl_pump + command: D,? diff --git a/tests/components/ezo_pmp/test.esp32-idf.yaml b/tests/components/ezo_pmp/test.esp32-idf.yaml new file mode 100644 index 0000000000..9fc929b365 --- /dev/null +++ b/tests/components/ezo_pmp/test.esp32-idf.yaml @@ -0,0 +1,61 @@ +i2c: + - id: i2c_ezo_pmp + scl: 16 + sda: 17 + +ezo_pmp: + id: hcl_pump + update_interval: 1s + +binary_sensor: + - platform: ezo_pmp + pump_state: + name: Pump State + is_paused: + name: Is Paused + +sensor: + - platform: ezo_pmp + current_volume_dosed: + name: Current Volume Dosed + total_volume_dosed: + name: Total Volume Dosed + absolute_total_volume_dosed: + name: Absolute Total Volume Dosed + pump_voltage: + name: Pump Voltage + last_volume_requested: + name: Last Volume Requested + max_flow_rate: + name: Max Flow Rate + +text_sensor: + - platform: ezo_pmp + dosing_mode: + name: Dosing Mode + calibration_status: + name: Calibration Status + on_value: + - ezo_pmp.dose_volume: + id: hcl_pump + volume: 10 + - ezo_pmp.dose_volume_over_time: + id: hcl_pump + volume: 10 + duration: 2 + - ezo_pmp.dose_with_constant_flow_rate: + id: hcl_pump + volume_per_minute: 10 + duration: 2 + - ezo_pmp.set_calibration_volume: + id: hcl_pump + volume: 10 + - ezo_pmp.find: hcl_pump + - ezo_pmp.dose_continuously: hcl_pump + - ezo_pmp.clear_total_volume_dosed: hcl_pump + - ezo_pmp.clear_calibration: hcl_pump + - ezo_pmp.pause_dosing: hcl_pump + - ezo_pmp.stop_dosing: hcl_pump + - ezo_pmp.arbitrary_command: + id: hcl_pump + command: D,? diff --git a/tests/components/ezo_pmp/test.esp32.yaml b/tests/components/ezo_pmp/test.esp32.yaml new file mode 100644 index 0000000000..9fc929b365 --- /dev/null +++ b/tests/components/ezo_pmp/test.esp32.yaml @@ -0,0 +1,61 @@ +i2c: + - id: i2c_ezo_pmp + scl: 16 + sda: 17 + +ezo_pmp: + id: hcl_pump + update_interval: 1s + +binary_sensor: + - platform: ezo_pmp + pump_state: + name: Pump State + is_paused: + name: Is Paused + +sensor: + - platform: ezo_pmp + current_volume_dosed: + name: Current Volume Dosed + total_volume_dosed: + name: Total Volume Dosed + absolute_total_volume_dosed: + name: Absolute Total Volume Dosed + pump_voltage: + name: Pump Voltage + last_volume_requested: + name: Last Volume Requested + max_flow_rate: + name: Max Flow Rate + +text_sensor: + - platform: ezo_pmp + dosing_mode: + name: Dosing Mode + calibration_status: + name: Calibration Status + on_value: + - ezo_pmp.dose_volume: + id: hcl_pump + volume: 10 + - ezo_pmp.dose_volume_over_time: + id: hcl_pump + volume: 10 + duration: 2 + - ezo_pmp.dose_with_constant_flow_rate: + id: hcl_pump + volume_per_minute: 10 + duration: 2 + - ezo_pmp.set_calibration_volume: + id: hcl_pump + volume: 10 + - ezo_pmp.find: hcl_pump + - ezo_pmp.dose_continuously: hcl_pump + - ezo_pmp.clear_total_volume_dosed: hcl_pump + - ezo_pmp.clear_calibration: hcl_pump + - ezo_pmp.pause_dosing: hcl_pump + - ezo_pmp.stop_dosing: hcl_pump + - ezo_pmp.arbitrary_command: + id: hcl_pump + command: D,? diff --git a/tests/components/ezo_pmp/test.esp8266.yaml b/tests/components/ezo_pmp/test.esp8266.yaml new file mode 100644 index 0000000000..fa047de3de --- /dev/null +++ b/tests/components/ezo_pmp/test.esp8266.yaml @@ -0,0 +1,61 @@ +i2c: + - id: i2c_ezo_pmp + scl: 5 + sda: 4 + +ezo_pmp: + id: hcl_pump + update_interval: 1s + +binary_sensor: + - platform: ezo_pmp + pump_state: + name: Pump State + is_paused: + name: Is Paused + +sensor: + - platform: ezo_pmp + current_volume_dosed: + name: Current Volume Dosed + total_volume_dosed: + name: Total Volume Dosed + absolute_total_volume_dosed: + name: Absolute Total Volume Dosed + pump_voltage: + name: Pump Voltage + last_volume_requested: + name: Last Volume Requested + max_flow_rate: + name: Max Flow Rate + +text_sensor: + - platform: ezo_pmp + dosing_mode: + name: Dosing Mode + calibration_status: + name: Calibration Status + on_value: + - ezo_pmp.dose_volume: + id: hcl_pump + volume: 10 + - ezo_pmp.dose_volume_over_time: + id: hcl_pump + volume: 10 + duration: 2 + - ezo_pmp.dose_with_constant_flow_rate: + id: hcl_pump + volume_per_minute: 10 + duration: 2 + - ezo_pmp.set_calibration_volume: + id: hcl_pump + volume: 10 + - ezo_pmp.find: hcl_pump + - ezo_pmp.dose_continuously: hcl_pump + - ezo_pmp.clear_total_volume_dosed: hcl_pump + - ezo_pmp.clear_calibration: hcl_pump + - ezo_pmp.pause_dosing: hcl_pump + - ezo_pmp.stop_dosing: hcl_pump + - ezo_pmp.arbitrary_command: + id: hcl_pump + command: D,? diff --git a/tests/components/ezo_pmp/test.rp2040.yaml b/tests/components/ezo_pmp/test.rp2040.yaml new file mode 100644 index 0000000000..fa047de3de --- /dev/null +++ b/tests/components/ezo_pmp/test.rp2040.yaml @@ -0,0 +1,61 @@ +i2c: + - id: i2c_ezo_pmp + scl: 5 + sda: 4 + +ezo_pmp: + id: hcl_pump + update_interval: 1s + +binary_sensor: + - platform: ezo_pmp + pump_state: + name: Pump State + is_paused: + name: Is Paused + +sensor: + - platform: ezo_pmp + current_volume_dosed: + name: Current Volume Dosed + total_volume_dosed: + name: Total Volume Dosed + absolute_total_volume_dosed: + name: Absolute Total Volume Dosed + pump_voltage: + name: Pump Voltage + last_volume_requested: + name: Last Volume Requested + max_flow_rate: + name: Max Flow Rate + +text_sensor: + - platform: ezo_pmp + dosing_mode: + name: Dosing Mode + calibration_status: + name: Calibration Status + on_value: + - ezo_pmp.dose_volume: + id: hcl_pump + volume: 10 + - ezo_pmp.dose_volume_over_time: + id: hcl_pump + volume: 10 + duration: 2 + - ezo_pmp.dose_with_constant_flow_rate: + id: hcl_pump + volume_per_minute: 10 + duration: 2 + - ezo_pmp.set_calibration_volume: + id: hcl_pump + volume: 10 + - ezo_pmp.find: hcl_pump + - ezo_pmp.dose_continuously: hcl_pump + - ezo_pmp.clear_total_volume_dosed: hcl_pump + - ezo_pmp.clear_calibration: hcl_pump + - ezo_pmp.pause_dosing: hcl_pump + - ezo_pmp.stop_dosing: hcl_pump + - ezo_pmp.arbitrary_command: + id: hcl_pump + command: D,? From 9b7438a56d0ebace3979c9d55e79093e3dd94469 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 19 Mar 2024 13:39:01 +1300 Subject: [PATCH 1117/2101] Require xsrf/csrf when using a password (#6396) --- esphome/dashboard/web_server.py | 6 ++++++ requirements.txt | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/esphome/dashboard/web_server.py b/esphome/dashboard/web_server.py index 3de1d69115..9ee2312781 100644 --- a/esphome/dashboard/web_server.py +++ b/esphome/dashboard/web_server.py @@ -688,6 +688,11 @@ class MainRequestHandler(BaseHandler): @authenticated def get(self) -> None: begin = bool(self.get_argument("begin", False)) + if settings.using_password: + # Simply accessing the xsrf_token sets the cookie for us + self.xsrf_token # pylint: disable=pointless-statement + else: + self.clear_cookie("_xsrf") self.render( "index.template.html", @@ -1102,6 +1107,7 @@ def make_app(debug=get_bool_env(ENV_DEV)) -> tornado.web.Application: "log_function": log_function, "websocket_ping_interval": 30.0, "template_path": get_base_frontend_path(), + "xsrf_cookies": settings.using_password, } rel = settings.relative_url return tornado.web.Application( diff --git a/requirements.txt b/requirements.txt index 9b5e06fc59..4b7e501e97 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ pyserial==3.5 platformio==6.1.13 # When updating platformio, also update Dockerfile esptool==4.7.0 click==8.1.7 -esphome-dashboard==20231107.0 +esphome-dashboard==20240319.0 aioesphomeapi==23.1.1 zeroconf==0.131.0 python-magic==0.4.27 From b3aa950c60714a4e49028946656588611761def7 Mon Sep 17 00:00:00 2001 From: swoboda1337 <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 18 Mar 2024 02:35:06 -0400 Subject: [PATCH 1118/2101] Fix bug in `remote_base` conditional (#6281) Co-authored-by: Jonathan Swoboda --- esphome/components/remote_base/remote_base.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/remote_base/remote_base.cpp b/esphome/components/remote_base/remote_base.cpp index 095f95053f..f3e86aaab6 100644 --- a/esphome/components/remote_base/remote_base.cpp +++ b/esphome/components/remote_base/remote_base.cpp @@ -16,7 +16,7 @@ RemoteRMTChannel::RemoteRMTChannel(uint8_t mem_block_num) : mem_block_num_(mem_b } void RemoteRMTChannel::config_rmt(rmt_config_t &rmt) { - if (rmt_channel_t(int(this->channel_) + this->mem_block_num_) >= RMT_CHANNEL_MAX) { + if (rmt_channel_t(int(this->channel_) + this->mem_block_num_) > RMT_CHANNEL_MAX) { this->mem_block_num_ = int(RMT_CHANNEL_MAX) - int(this->channel_); ESP_LOGW(TAG, "Not enough RMT memory blocks available, reduced to %i blocks.", this->mem_block_num_); } From 9442f7a2713d6ed324fbdf4ef6da70a3ca563fb6 Mon Sep 17 00:00:00 2001 From: Stefan Rado <628587+kroimon@users.noreply.github.com> Date: Mon, 18 Mar 2024 19:04:53 +0100 Subject: [PATCH 1119/2101] Fix sending packets to uponor_smatrix devices (#6392) --- esphome/components/uponor_smatrix/uponor_smatrix.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/esphome/components/uponor_smatrix/uponor_smatrix.cpp b/esphome/components/uponor_smatrix/uponor_smatrix.cpp index df81691fb1..a7014dc96c 100644 --- a/esphome/components/uponor_smatrix/uponor_smatrix.cpp +++ b/esphome/components/uponor_smatrix/uponor_smatrix.cpp @@ -173,7 +173,9 @@ bool UponorSmatrixComponent::send(uint16_t device_address, const UponorSmatrixDa return false; // Assemble packet for send queue. All fields are big-endian except for the little-endian checksum. - std::vector packet(6 + 3 * data_len); + std::vector packet; + packet.reserve(6 + 3 * data_len); + packet.push_back(this->address_ >> 8); packet.push_back(this->address_ >> 0); packet.push_back(device_address >> 8); From db1b187e80029ab9aad61fe347d24fe3fcd24dfe Mon Sep 17 00:00:00 2001 From: Stefan Rado <628587+kroimon@users.noreply.github.com> Date: Mon, 18 Mar 2024 19:06:17 +0100 Subject: [PATCH 1120/2101] Fix wrong initialization of vectors in ade7953_i2c (#6393) --- .../components/ade7953_i2c/ade7953_i2c.cpp | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/esphome/components/ade7953_i2c/ade7953_i2c.cpp b/esphome/components/ade7953_i2c/ade7953_i2c.cpp index 572337428a..ae381824db 100644 --- a/esphome/components/ade7953_i2c/ade7953_i2c.cpp +++ b/esphome/components/ade7953_i2c/ade7953_i2c.cpp @@ -13,29 +13,29 @@ void AdE7953I2c::dump_config() { ade7953_base::ADE7953::dump_config(); } bool AdE7953I2c::ade_write_8(uint16_t reg, uint8_t value) { - std::vector data(3); - data.push_back(reg >> 8); - data.push_back(reg >> 0); - data.push_back(value); - return this->write(data.data(), data.size()) != i2c::ERROR_OK; + uint8_t data[3]; + data[0] = reg >> 8; + data[1] = reg >> 0; + data[2] = value; + return this->write(data, 3) != i2c::ERROR_OK; } bool AdE7953I2c::ade_write_16(uint16_t reg, uint16_t value) { - std::vector data(4); - data.push_back(reg >> 8); - data.push_back(reg >> 0); - data.push_back(value >> 8); - data.push_back(value >> 0); - return this->write(data.data(), data.size()) != i2c::ERROR_OK; + uint8_t data[4]; + data[0] = reg >> 8; + data[1] = reg >> 0; + data[2] = value >> 8; + data[3] = value >> 0; + return this->write(data, 4) != i2c::ERROR_OK; } bool AdE7953I2c::ade_write_32(uint16_t reg, uint32_t value) { - std::vector data(6); - data.push_back(reg >> 8); - data.push_back(reg >> 0); - data.push_back(value >> 24); - data.push_back(value >> 16); - data.push_back(value >> 8); - data.push_back(value >> 0); - return this->write(data.data(), data.size()) != i2c::ERROR_OK; + uint8_t data[6]; + data[0] = reg >> 8; + data[1] = reg >> 0; + data[2] = value >> 24; + data[3] = value >> 16; + data[4] = value >> 8; + data[5] = value >> 0; + return this->write(data, 6) != i2c::ERROR_OK; } bool AdE7953I2c::ade_read_8(uint16_t reg, uint8_t *value) { uint8_t reg_data[2]; From a3bd8ad02526a831bc0ab52e76ddfcec78f39440 Mon Sep 17 00:00:00 2001 From: Mike La Spina Date: Mon, 18 Mar 2024 13:26:39 -0500 Subject: [PATCH 1121/2101] ld2420: Firmware v1.5.4+ bug workaround (#6168) --- esphome/components/ld2420/ld2420.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/esphome/components/ld2420/ld2420.cpp b/esphome/components/ld2420/ld2420.cpp index bda1764cfc..bf1412ee9f 100644 --- a/esphome/components/ld2420/ld2420.cpp +++ b/esphome/components/ld2420/ld2420.cpp @@ -211,10 +211,11 @@ void LD2420Component::factory_reset_action() { void LD2420Component::restart_module_action() { ESP_LOGCONFIG(TAG, "Restarting LD2420 module..."); this->send_module_restart(); - delay_microseconds_safe(45000); - this->set_config_mode(true); - this->set_system_mode(system_mode_); - this->set_config_mode(false); + this->set_timeout(250, [this]() { + this->set_config_mode(true); + this->set_system_mode(system_mode_); + this->set_config_mode(false); + }); ESP_LOGCONFIG(TAG, "LD2420 Restarted."); } @@ -527,18 +528,16 @@ int LD2420Component::send_cmd_from_array(CmdFrameT frame) { this->write_byte(cmd_buffer[index]); } - delay_microseconds_safe(500); // give the module a moment to process it error = 0; if (frame.command == CMD_RESTART) { - delay_microseconds_safe(25000); // Wait for the restart - return 0; // restart does not reply exit now + return 0; // restart does not reply exit now } while (!this->cmd_reply_.ack) { while (available()) { this->readline_(read(), ack_buffer, sizeof(ack_buffer)); } - delay_microseconds_safe(250); + delay_microseconds_safe(1450); if (loop_count <= 0) { error = LD2420_ERROR_TIMEOUT; retry--; From c56c40cb824e34ed2b89ba1cb8a3a5eb31459c74 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 19 Mar 2024 13:39:01 +1300 Subject: [PATCH 1122/2101] Require xsrf/csrf when using a password (#6396) --- esphome/dashboard/web_server.py | 6 ++++++ requirements.txt | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/esphome/dashboard/web_server.py b/esphome/dashboard/web_server.py index 3de1d69115..9ee2312781 100644 --- a/esphome/dashboard/web_server.py +++ b/esphome/dashboard/web_server.py @@ -688,6 +688,11 @@ class MainRequestHandler(BaseHandler): @authenticated def get(self) -> None: begin = bool(self.get_argument("begin", False)) + if settings.using_password: + # Simply accessing the xsrf_token sets the cookie for us + self.xsrf_token # pylint: disable=pointless-statement + else: + self.clear_cookie("_xsrf") self.render( "index.template.html", @@ -1102,6 +1107,7 @@ def make_app(debug=get_bool_env(ENV_DEV)) -> tornado.web.Application: "log_function": log_function, "websocket_ping_interval": 30.0, "template_path": get_base_frontend_path(), + "xsrf_cookies": settings.using_password, } rel = settings.relative_url return tornado.web.Application( diff --git a/requirements.txt b/requirements.txt index 9b5e06fc59..4b7e501e97 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ pyserial==3.5 platformio==6.1.13 # When updating platformio, also update Dockerfile esptool==4.7.0 click==8.1.7 -esphome-dashboard==20231107.0 +esphome-dashboard==20240319.0 aioesphomeapi==23.1.1 zeroconf==0.131.0 python-magic==0.4.27 From 855b1fd7062e1fabfe60c57bad08749aa7c1f390 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 19 Mar 2024 14:22:28 +1300 Subject: [PATCH 1123/2101] Bump version to 2024.3.0b4 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 60ea6f0423..2b5724c9f3 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.3.0b3" +__version__ = "2024.3.0b4" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 19022ace12595295fadcc3fbb36c69a8d5c846f4 Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Tue, 19 Mar 2024 03:56:36 +0100 Subject: [PATCH 1124/2101] Make SPI compile with IDF >= 5.0 (#6383) Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> --- esphome/components/spi_device/spi_device.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/esphome/components/spi_device/spi_device.cpp b/esphome/components/spi_device/spi_device.cpp index 4e0b72ae60..1f579cb802 100644 --- a/esphome/components/spi_device/spi_device.cpp +++ b/esphome/components/spi_device/spi_device.cpp @@ -1,6 +1,7 @@ #include "spi_device.h" #include "esphome/core/log.h" #include "esphome/core/hal.h" +#include namespace esphome { namespace spi_device { @@ -18,9 +19,9 @@ void SPIDeviceComponent::dump_config() { LOG_PIN(" CS pin: ", this->cs_); ESP_LOGCONFIG(TAG, " Mode: %d", this->mode_); if (this->data_rate_ < 1000000) { - ESP_LOGCONFIG(TAG, " Data rate: %dkHz", this->data_rate_ / 1000); + ESP_LOGCONFIG(TAG, " Data rate: %" PRId32 "kHz", this->data_rate_ / 1000); } else { - ESP_LOGCONFIG(TAG, " Data rate: %dMHz", this->data_rate_ / 1000000); + ESP_LOGCONFIG(TAG, " Data rate: %" PRId32 "MHz", this->data_rate_ / 1000000); } } From af3fb615ead27b90c8c98fdbaf33e80e6eaf87f4 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Tue, 19 Mar 2024 00:18:03 -0500 Subject: [PATCH 1125/2101] Fix esp32-camera test yaml (#6398) * Fix esp32-camera test yaml * Fix esp32-camera test yaml, take 2 --- .../components/esp32_camera/test.esp32-idf.yaml | 16 ++++++++-------- tests/components/esp32_camera/test.esp32.yaml | 16 ++++++++-------- .../esp32_camera_web_server/test.esp32-idf.yaml | 16 ++++++++-------- .../esp32_camera_web_server/test.esp32.yaml | 16 ++++++++-------- 4 files changed, 32 insertions(+), 32 deletions(-) diff --git a/tests/components/esp32_camera/test.esp32-idf.yaml b/tests/components/esp32_camera/test.esp32-idf.yaml index 366f601657..2f5f792f1c 100644 --- a/tests/components/esp32_camera/test.esp32-idf.yaml +++ b/tests/components/esp32_camera/test.esp32-idf.yaml @@ -3,12 +3,12 @@ esp32_camera: data_pins: - number: 17 - number: 35 - - number: 34 - - number: 5 - - number: 39 - - number: 18 - - number: 36 - - number: 19 + - number: 34 + - number: 5 + - number: 39 + - number: 18 + - number: 36 + - number: 19 vsync_pin: 22 href_pin: 26 pixel_clock_pin: 21 @@ -24,5 +24,5 @@ esp32_camera: jpeg_quality: 10 on_image: then: - - lambda: |- - ESP_LOGD("main", "image len=%d, data=%c", image.length, image.data[0]); + - lambda: |- + ESP_LOGD("main", "image len=%d, data=%c", image.length, image.data[0]); diff --git a/tests/components/esp32_camera/test.esp32.yaml b/tests/components/esp32_camera/test.esp32.yaml index 366f601657..2f5f792f1c 100644 --- a/tests/components/esp32_camera/test.esp32.yaml +++ b/tests/components/esp32_camera/test.esp32.yaml @@ -3,12 +3,12 @@ esp32_camera: data_pins: - number: 17 - number: 35 - - number: 34 - - number: 5 - - number: 39 - - number: 18 - - number: 36 - - number: 19 + - number: 34 + - number: 5 + - number: 39 + - number: 18 + - number: 36 + - number: 19 vsync_pin: 22 href_pin: 26 pixel_clock_pin: 21 @@ -24,5 +24,5 @@ esp32_camera: jpeg_quality: 10 on_image: then: - - lambda: |- - ESP_LOGD("main", "image len=%d, data=%c", image.length, image.data[0]); + - lambda: |- + ESP_LOGD("main", "image len=%d, data=%c", image.length, image.data[0]); diff --git a/tests/components/esp32_camera_web_server/test.esp32-idf.yaml b/tests/components/esp32_camera_web_server/test.esp32-idf.yaml index 14b7bd5c34..5edefdf0a8 100644 --- a/tests/components/esp32_camera_web_server/test.esp32-idf.yaml +++ b/tests/components/esp32_camera_web_server/test.esp32-idf.yaml @@ -3,12 +3,12 @@ esp32_camera: data_pins: - number: 17 - number: 35 - - number: 34 - - number: 5 - - number: 39 - - number: 18 - - number: 36 - - number: 19 + - number: 34 + - number: 5 + - number: 39 + - number: 18 + - number: 36 + - number: 19 vsync_pin: 22 href_pin: 26 pixel_clock_pin: 21 @@ -24,8 +24,8 @@ esp32_camera: jpeg_quality: 10 on_image: then: - - lambda: |- - ESP_LOGD("main", "image len=%d, data=%c", image.length, image.data[0]); + - lambda: |- + ESP_LOGD("main", "image len=%d, data=%c", image.length, image.data[0]); esp32_camera_web_server: - port: 8080 diff --git a/tests/components/esp32_camera_web_server/test.esp32.yaml b/tests/components/esp32_camera_web_server/test.esp32.yaml index 14b7bd5c34..5edefdf0a8 100644 --- a/tests/components/esp32_camera_web_server/test.esp32.yaml +++ b/tests/components/esp32_camera_web_server/test.esp32.yaml @@ -3,12 +3,12 @@ esp32_camera: data_pins: - number: 17 - number: 35 - - number: 34 - - number: 5 - - number: 39 - - number: 18 - - number: 36 - - number: 19 + - number: 34 + - number: 5 + - number: 39 + - number: 18 + - number: 36 + - number: 19 vsync_pin: 22 href_pin: 26 pixel_clock_pin: 21 @@ -24,8 +24,8 @@ esp32_camera: jpeg_quality: 10 on_image: then: - - lambda: |- - ESP_LOGD("main", "image len=%d, data=%c", image.length, image.data[0]); + - lambda: |- + ESP_LOGD("main", "image len=%d, data=%c", image.length, image.data[0]); esp32_camera_web_server: - port: 8080 From f0936dd22dd2c6ce62f75f3afe42964d578340c6 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Wed, 20 Mar 2024 10:53:01 +1100 Subject: [PATCH 1126/2101] AHT10: Use state machine to avoid blocking delay (#6401) --- esphome/components/aht10/aht10.cpp | 107 +++++++++++++++-------------- esphome/components/aht10/aht10.h | 5 ++ 2 files changed, 61 insertions(+), 51 deletions(-) diff --git a/esphome/components/aht10/aht10.cpp b/esphome/components/aht10/aht10.cpp index 57102e6d27..d5af06c2a2 100644 --- a/esphome/components/aht10/aht10.cpp +++ b/esphome/components/aht10/aht10.cpp @@ -36,6 +36,7 @@ static const uint8_t AHT10_INIT_ATTEMPTS = 10; static const uint8_t AHT10_STATUS_BUSY = 0x80; void AHT10Component::setup() { + this->read_delay_ = this->humidity_sensor_ != nullptr ? AHT10_HUMIDITY_DELAY : AHT10_DEFAULT_DELAY; if (this->write(AHT10_SOFTRESET_CMD, sizeof(AHT10_SOFTRESET_CMD)) != i2c::ERROR_OK) { ESP_LOGE(TAG, "Reset AHT10 failed!"); } @@ -83,74 +84,78 @@ void AHT10Component::setup() { ESP_LOGV(TAG, "AHT10 initialization"); } -void AHT10Component::update() { - if (this->write(AHT10_MEASURE_CMD, sizeof(AHT10_MEASURE_CMD)) != i2c::ERROR_OK) { - ESP_LOGE(TAG, "Communication with AHT10 failed!"); - this->status_set_warning(); - return; - } - uint8_t data[6]; - uint8_t delay_ms = AHT10_DEFAULT_DELAY; - if (this->humidity_sensor_ != nullptr) - delay_ms = AHT10_HUMIDITY_DELAY; - bool success = false; - for (int i = 0; i < AHT10_ATTEMPTS; ++i) { - ESP_LOGVV(TAG, "Attempt %d at %6" PRIu32, i, millis()); - delay(delay_ms); - if (this->read(data, 6) != i2c::ERROR_OK) { - ESP_LOGD(TAG, "Communication with AHT10 failed, waiting..."); - continue; - } - - if ((data[0] & 0x80) == 0x80) { // Bit[7] = 0b1, device is busy - ESP_LOGD(TAG, "AHT10 is busy, waiting..."); - } else if (data[1] == 0x0 && data[2] == 0x0 && (data[3] >> 4) == 0x0) { - // Unrealistic humidity (0x0) - if (this->humidity_sensor_ == nullptr) { - ESP_LOGVV(TAG, "ATH10 Unrealistic humidity (0x0), but humidity is not required"); - break; - } else { - ESP_LOGD(TAG, "ATH10 Unrealistic humidity (0x0), retrying..."); - if (this->write(AHT10_MEASURE_CMD, sizeof(AHT10_MEASURE_CMD)) != i2c::ERROR_OK) { - ESP_LOGE(TAG, "Communication with AHT10 failed!"); - this->status_set_warning(); - return; - } - } - } else { - // data is valid, we can break the loop - ESP_LOGVV(TAG, "Answer at %6" PRIu32, millis()); - success = true; - break; - } - } - if (!success || (data[0] & 0x80) == 0x80) { +void AHT10Component::restart_read_() { + if (this->read_count_ == AHT10_ATTEMPTS) { + this->read_count_ = 0; ESP_LOGE(TAG, "Measurements reading timed-out!"); - this->status_set_warning(); + this->status_set_error(); + return; + } + this->read_count_++; + this->set_timeout(this->read_delay_, [this]() { this->read_data_(); }); +} + +void AHT10Component::read_data_() { + uint8_t data[6]; + ESP_LOGD(TAG, "Read attempt %d at %ums", this->read_count_, (unsigned) (millis() - this->start_time_)); + if (this->read(data, 6) != i2c::ERROR_OK) { + ESP_LOGD(TAG, "Communication with AHT10 failed, waiting..."); + this->restart_read_(); return; } + if ((data[0] & 0x80) == 0x80) { // Bit[7] = 0b1, device is busy + ESP_LOGD(TAG, "AHT10 is busy, waiting..."); + this->restart_read_(); + return; + } + if (data[1] == 0x0 && data[2] == 0x0 && (data[3] >> 4) == 0x0) { + // Unrealistic humidity (0x0) + if (this->humidity_sensor_ == nullptr) { + ESP_LOGV(TAG, "ATH10 Unrealistic humidity (0x0), but humidity is not required"); + } else { + ESP_LOGD(TAG, "ATH10 Unrealistic humidity (0x0), retrying..."); + if (this->write(AHT10_MEASURE_CMD, sizeof(AHT10_MEASURE_CMD)) != i2c::ERROR_OK) { + ESP_LOGE(TAG, "Communication with AHT10 failed!"); + this->status_set_warning(); + } + this->restart_read_(); + return; + } + } + ESP_LOGD(TAG, "Success at %ums", (unsigned) (millis() - this->start_time_)); uint32_t raw_temperature = ((data[3] & 0x0F) << 16) | (data[4] << 8) | data[5]; uint32_t raw_humidity = ((data[1] << 16) | (data[2] << 8) | data[3]) >> 4; - float temperature = ((200.0f * (float) raw_temperature) / 1048576.0f) - 50.0f; - float humidity; - if (raw_humidity == 0) { // unrealistic value - humidity = NAN; - } else { - humidity = (float) raw_humidity * 100.0f / 1048576.0f; - } - if (this->temperature_sensor_ != nullptr) { + float temperature = ((200.0f * (float) raw_temperature) / 1048576.0f) - 50.0f; this->temperature_sensor_->publish_state(temperature); } if (this->humidity_sensor_ != nullptr) { + float humidity; + if (raw_humidity == 0) { // unrealistic value + humidity = NAN; + } else { + humidity = (float) raw_humidity * 100.0f / 1048576.0f; + } if (std::isnan(humidity)) { ESP_LOGW(TAG, "Invalid humidity! Sensor reported 0%% Hum"); } this->humidity_sensor_->publish_state(humidity); } this->status_clear_warning(); + this->read_count_ = 0; +} +void AHT10Component::update() { + if (this->read_count_ != 0) + return; + this->start_time_ = millis(); + if (this->write(AHT10_MEASURE_CMD, sizeof(AHT10_MEASURE_CMD)) != i2c::ERROR_OK) { + ESP_LOGE(TAG, "Communication with AHT10 failed!"); + this->status_set_warning(); + return; + } + this->restart_read_(); } float AHT10Component::get_setup_priority() const { return setup_priority::DATA; } diff --git a/esphome/components/aht10/aht10.h b/esphome/components/aht10/aht10.h index 3840609d56..76f051878e 100644 --- a/esphome/components/aht10/aht10.h +++ b/esphome/components/aht10/aht10.h @@ -26,6 +26,11 @@ class AHT10Component : public PollingComponent, public i2c::I2CDevice { sensor::Sensor *temperature_sensor_{nullptr}; sensor::Sensor *humidity_sensor_{nullptr}; AHT10Variant variant_{}; + unsigned read_count_{}; + unsigned read_delay_{}; + void read_data_(); + void restart_read_(); + uint32_t start_time_{}; }; } // namespace aht10 From 774cbde1b6c6d121a8b2a92a2aa53f79a77f320f Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Wed, 20 Mar 2024 10:56:43 +1100 Subject: [PATCH 1127/2101] Show component warnings and errors in the log; (#6400) --- esphome/core/component.cpp | 29 +++++++++++++++++++++++------ esphome/core/component.h | 8 ++++---- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index d737ec0ae3..b9a7697015 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -141,18 +141,35 @@ bool Component::is_ready() { (this->component_state_ & COMPONENT_STATE_MASK) == COMPONENT_STATE_SETUP; } bool Component::can_proceed() { return true; } -bool Component::status_has_warning() { return this->component_state_ & STATUS_LED_WARNING; } -bool Component::status_has_error() { return this->component_state_ & STATUS_LED_ERROR; } -void Component::status_set_warning() { +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; } +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) + return; this->component_state_ |= STATUS_LED_WARNING; App.app_state_ |= STATUS_LED_WARNING; + ESP_LOGW(this->get_component_source(), "Warning set: %s", message); } -void Component::status_set_error() { +void Component::status_set_error(const char *message) { + if ((this->component_state_ & STATUS_LED_ERROR) != 0) + return; this->component_state_ |= STATUS_LED_ERROR; App.app_state_ |= STATUS_LED_ERROR; + ESP_LOGE(this->get_component_source(), "Error set: %s", message); +} +void Component::status_clear_warning() { + if ((this->component_state_ & STATUS_LED_WARNING) == 0) + return; + this->component_state_ &= ~STATUS_LED_WARNING; + ESP_LOGW(this->get_component_source(), "Warning cleared"); +} +void Component::status_clear_error() { + if ((this->component_state_ & STATUS_LED_ERROR) == 0) + return; + this->component_state_ &= ~STATUS_LED_ERROR; + ESP_LOGE(this->get_component_source(), "Error cleared"); } -void Component::status_clear_warning() { this->component_state_ &= ~STATUS_LED_WARNING; } -void Component::status_clear_error() { this->component_state_ &= ~STATUS_LED_ERROR; } void Component::status_momentary_warning(const std::string &name, uint32_t length) { this->status_set_warning(); this->set_timeout(name, length, [this]() { this->status_clear_warning(); }); diff --git a/esphome/core/component.h b/esphome/core/component.h index deefedf3d8..4f244e5fcb 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -124,13 +124,13 @@ class Component { virtual bool can_proceed(); - bool status_has_warning(); + bool status_has_warning() const; - bool status_has_error(); + bool status_has_error() const; - void status_set_warning(); + void status_set_warning(const char *message = "unspecified"); - void status_set_error(); + void status_set_error(const char *message = "unspecified"); void status_clear_warning(); From 7e8e658999d169757c0a00b56d97cbde09113a60 Mon Sep 17 00:00:00 2001 From: RFDarter Date: Wed, 20 Mar 2024 04:37:18 +0100 Subject: [PATCH 1128/2101] web_server support for v3 (#6203) --- esphome/components/web_server/__init__.py | 9 +++++++-- esphome/components/web_server/web_server.cpp | 2 +- esphome/components/web_server/web_server.h | 2 +- tests/test10.yaml | 3 +++ 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/esphome/components/web_server/__init__.py b/esphome/components/web_server/__init__.py index 2708b5d06e..bbd5bc662e 100644 --- a/esphome/components/web_server/__init__.py +++ b/esphome/components/web_server/__init__.py @@ -44,6 +44,11 @@ def default_url(config): config[CONF_CSS_URL] = "" if not (CONF_JS_URL in config): config[CONF_JS_URL] = "https://oi.esphome.io/v2/www.js" + if config[CONF_VERSION] == 3: + if not (CONF_CSS_URL in config): + config[CONF_CSS_URL] = "" + if not (CONF_JS_URL in config): + config[CONF_JS_URL] = "https://oi.esphome.io/v3/www.js" return config @@ -64,7 +69,7 @@ CONFIG_SCHEMA = cv.All( { cv.GenerateID(): cv.declare_id(WebServer), cv.Optional(CONF_PORT, default=80): cv.port, - cv.Optional(CONF_VERSION, default=2): cv.one_of(1, 2, int=True), + cv.Optional(CONF_VERSION, default=2): cv.one_of(1, 2, 3, int=True), cv.Optional(CONF_CSS_URL): cv.string, cv.Optional(CONF_CSS_INCLUDE): cv.file_, cv.Optional(CONF_JS_URL): cv.string, @@ -152,7 +157,7 @@ async def to_code(config): cg.add_define("USE_WEBSERVER") cg.add_define("USE_WEBSERVER_PORT", config[CONF_PORT]) cg.add_define("USE_WEBSERVER_VERSION", version) - if version == 2: + if version >= 2: # Don't compress the index HTML as the data sizes are almost the same. add_resource_as_progmem("INDEX_HTML", build_index_html(config), compress=False) else: diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index 69d601ed49..f065dc6684 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -358,7 +358,7 @@ void WebServer::handle_index_request(AsyncWebServerRequest *request) { stream->print(F("")); request->send(stream); } -#elif USE_WEBSERVER_VERSION == 2 +#elif USE_WEBSERVER_VERSION >= 2 void WebServer::handle_index_request(AsyncWebServerRequest *request) { AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", ESPHOME_WEBSERVER_INDEX_HTML, ESPHOME_WEBSERVER_INDEX_HTML_SIZE); diff --git a/esphome/components/web_server/web_server.h b/esphome/components/web_server/web_server.h index 06c59ecaca..57cbbe1339 100644 --- a/esphome/components/web_server/web_server.h +++ b/esphome/components/web_server/web_server.h @@ -13,7 +13,7 @@ #include #endif -#if USE_WEBSERVER_VERSION == 2 +#if USE_WEBSERVER_VERSION >= 2 extern const uint8_t ESPHOME_WEBSERVER_INDEX_HTML[] PROGMEM; extern const size_t ESPHOME_WEBSERVER_INDEX_HTML_SIZE; #endif diff --git a/tests/test10.yaml b/tests/test10.yaml index 7e3a685b36..854173cfe9 100644 --- a/tests/test10.yaml +++ b/tests/test10.yaml @@ -23,6 +23,9 @@ logger: api: reboot_timeout: 10min +web_server: + version: 3 + time: - platform: sntp From 507568db647d24a58e765a256a43ca04dcc5aeb3 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Wed, 20 Mar 2024 10:53:01 +1100 Subject: [PATCH 1129/2101] AHT10: Use state machine to avoid blocking delay (#6401) --- esphome/components/aht10/aht10.cpp | 107 +++++++++++++++-------------- esphome/components/aht10/aht10.h | 5 ++ 2 files changed, 61 insertions(+), 51 deletions(-) diff --git a/esphome/components/aht10/aht10.cpp b/esphome/components/aht10/aht10.cpp index 57102e6d27..d5af06c2a2 100644 --- a/esphome/components/aht10/aht10.cpp +++ b/esphome/components/aht10/aht10.cpp @@ -36,6 +36,7 @@ static const uint8_t AHT10_INIT_ATTEMPTS = 10; static const uint8_t AHT10_STATUS_BUSY = 0x80; void AHT10Component::setup() { + this->read_delay_ = this->humidity_sensor_ != nullptr ? AHT10_HUMIDITY_DELAY : AHT10_DEFAULT_DELAY; if (this->write(AHT10_SOFTRESET_CMD, sizeof(AHT10_SOFTRESET_CMD)) != i2c::ERROR_OK) { ESP_LOGE(TAG, "Reset AHT10 failed!"); } @@ -83,74 +84,78 @@ void AHT10Component::setup() { ESP_LOGV(TAG, "AHT10 initialization"); } -void AHT10Component::update() { - if (this->write(AHT10_MEASURE_CMD, sizeof(AHT10_MEASURE_CMD)) != i2c::ERROR_OK) { - ESP_LOGE(TAG, "Communication with AHT10 failed!"); - this->status_set_warning(); - return; - } - uint8_t data[6]; - uint8_t delay_ms = AHT10_DEFAULT_DELAY; - if (this->humidity_sensor_ != nullptr) - delay_ms = AHT10_HUMIDITY_DELAY; - bool success = false; - for (int i = 0; i < AHT10_ATTEMPTS; ++i) { - ESP_LOGVV(TAG, "Attempt %d at %6" PRIu32, i, millis()); - delay(delay_ms); - if (this->read(data, 6) != i2c::ERROR_OK) { - ESP_LOGD(TAG, "Communication with AHT10 failed, waiting..."); - continue; - } - - if ((data[0] & 0x80) == 0x80) { // Bit[7] = 0b1, device is busy - ESP_LOGD(TAG, "AHT10 is busy, waiting..."); - } else if (data[1] == 0x0 && data[2] == 0x0 && (data[3] >> 4) == 0x0) { - // Unrealistic humidity (0x0) - if (this->humidity_sensor_ == nullptr) { - ESP_LOGVV(TAG, "ATH10 Unrealistic humidity (0x0), but humidity is not required"); - break; - } else { - ESP_LOGD(TAG, "ATH10 Unrealistic humidity (0x0), retrying..."); - if (this->write(AHT10_MEASURE_CMD, sizeof(AHT10_MEASURE_CMD)) != i2c::ERROR_OK) { - ESP_LOGE(TAG, "Communication with AHT10 failed!"); - this->status_set_warning(); - return; - } - } - } else { - // data is valid, we can break the loop - ESP_LOGVV(TAG, "Answer at %6" PRIu32, millis()); - success = true; - break; - } - } - if (!success || (data[0] & 0x80) == 0x80) { +void AHT10Component::restart_read_() { + if (this->read_count_ == AHT10_ATTEMPTS) { + this->read_count_ = 0; ESP_LOGE(TAG, "Measurements reading timed-out!"); - this->status_set_warning(); + this->status_set_error(); + return; + } + this->read_count_++; + this->set_timeout(this->read_delay_, [this]() { this->read_data_(); }); +} + +void AHT10Component::read_data_() { + uint8_t data[6]; + ESP_LOGD(TAG, "Read attempt %d at %ums", this->read_count_, (unsigned) (millis() - this->start_time_)); + if (this->read(data, 6) != i2c::ERROR_OK) { + ESP_LOGD(TAG, "Communication with AHT10 failed, waiting..."); + this->restart_read_(); return; } + if ((data[0] & 0x80) == 0x80) { // Bit[7] = 0b1, device is busy + ESP_LOGD(TAG, "AHT10 is busy, waiting..."); + this->restart_read_(); + return; + } + if (data[1] == 0x0 && data[2] == 0x0 && (data[3] >> 4) == 0x0) { + // Unrealistic humidity (0x0) + if (this->humidity_sensor_ == nullptr) { + ESP_LOGV(TAG, "ATH10 Unrealistic humidity (0x0), but humidity is not required"); + } else { + ESP_LOGD(TAG, "ATH10 Unrealistic humidity (0x0), retrying..."); + if (this->write(AHT10_MEASURE_CMD, sizeof(AHT10_MEASURE_CMD)) != i2c::ERROR_OK) { + ESP_LOGE(TAG, "Communication with AHT10 failed!"); + this->status_set_warning(); + } + this->restart_read_(); + return; + } + } + ESP_LOGD(TAG, "Success at %ums", (unsigned) (millis() - this->start_time_)); uint32_t raw_temperature = ((data[3] & 0x0F) << 16) | (data[4] << 8) | data[5]; uint32_t raw_humidity = ((data[1] << 16) | (data[2] << 8) | data[3]) >> 4; - float temperature = ((200.0f * (float) raw_temperature) / 1048576.0f) - 50.0f; - float humidity; - if (raw_humidity == 0) { // unrealistic value - humidity = NAN; - } else { - humidity = (float) raw_humidity * 100.0f / 1048576.0f; - } - if (this->temperature_sensor_ != nullptr) { + float temperature = ((200.0f * (float) raw_temperature) / 1048576.0f) - 50.0f; this->temperature_sensor_->publish_state(temperature); } if (this->humidity_sensor_ != nullptr) { + float humidity; + if (raw_humidity == 0) { // unrealistic value + humidity = NAN; + } else { + humidity = (float) raw_humidity * 100.0f / 1048576.0f; + } if (std::isnan(humidity)) { ESP_LOGW(TAG, "Invalid humidity! Sensor reported 0%% Hum"); } this->humidity_sensor_->publish_state(humidity); } this->status_clear_warning(); + this->read_count_ = 0; +} +void AHT10Component::update() { + if (this->read_count_ != 0) + return; + this->start_time_ = millis(); + if (this->write(AHT10_MEASURE_CMD, sizeof(AHT10_MEASURE_CMD)) != i2c::ERROR_OK) { + ESP_LOGE(TAG, "Communication with AHT10 failed!"); + this->status_set_warning(); + return; + } + this->restart_read_(); } float AHT10Component::get_setup_priority() const { return setup_priority::DATA; } diff --git a/esphome/components/aht10/aht10.h b/esphome/components/aht10/aht10.h index 3840609d56..76f051878e 100644 --- a/esphome/components/aht10/aht10.h +++ b/esphome/components/aht10/aht10.h @@ -26,6 +26,11 @@ class AHT10Component : public PollingComponent, public i2c::I2CDevice { sensor::Sensor *temperature_sensor_{nullptr}; sensor::Sensor *humidity_sensor_{nullptr}; AHT10Variant variant_{}; + unsigned read_count_{}; + unsigned read_delay_{}; + void read_data_(); + void restart_read_(); + uint32_t start_time_{}; }; } // namespace aht10 From e27e3429276b9b5eea17721262b62bafe52a7ce5 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Wed, 20 Mar 2024 10:56:43 +1100 Subject: [PATCH 1130/2101] Show component warnings and errors in the log; (#6400) --- esphome/core/component.cpp | 29 +++++++++++++++++++++++------ esphome/core/component.h | 8 ++++---- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index d737ec0ae3..b9a7697015 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -141,18 +141,35 @@ bool Component::is_ready() { (this->component_state_ & COMPONENT_STATE_MASK) == COMPONENT_STATE_SETUP; } bool Component::can_proceed() { return true; } -bool Component::status_has_warning() { return this->component_state_ & STATUS_LED_WARNING; } -bool Component::status_has_error() { return this->component_state_ & STATUS_LED_ERROR; } -void Component::status_set_warning() { +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; } +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) + return; this->component_state_ |= STATUS_LED_WARNING; App.app_state_ |= STATUS_LED_WARNING; + ESP_LOGW(this->get_component_source(), "Warning set: %s", message); } -void Component::status_set_error() { +void Component::status_set_error(const char *message) { + if ((this->component_state_ & STATUS_LED_ERROR) != 0) + return; this->component_state_ |= STATUS_LED_ERROR; App.app_state_ |= STATUS_LED_ERROR; + ESP_LOGE(this->get_component_source(), "Error set: %s", message); +} +void Component::status_clear_warning() { + if ((this->component_state_ & STATUS_LED_WARNING) == 0) + return; + this->component_state_ &= ~STATUS_LED_WARNING; + ESP_LOGW(this->get_component_source(), "Warning cleared"); +} +void Component::status_clear_error() { + if ((this->component_state_ & STATUS_LED_ERROR) == 0) + return; + this->component_state_ &= ~STATUS_LED_ERROR; + ESP_LOGE(this->get_component_source(), "Error cleared"); } -void Component::status_clear_warning() { this->component_state_ &= ~STATUS_LED_WARNING; } -void Component::status_clear_error() { this->component_state_ &= ~STATUS_LED_ERROR; } void Component::status_momentary_warning(const std::string &name, uint32_t length) { this->status_set_warning(); this->set_timeout(name, length, [this]() { this->status_clear_warning(); }); diff --git a/esphome/core/component.h b/esphome/core/component.h index deefedf3d8..4f244e5fcb 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -124,13 +124,13 @@ class Component { virtual bool can_proceed(); - bool status_has_warning(); + bool status_has_warning() const; - bool status_has_error(); + bool status_has_error() const; - void status_set_warning(); + void status_set_warning(const char *message = "unspecified"); - void status_set_error(); + void status_set_error(const char *message = "unspecified"); void status_clear_warning(); From ccca5458623077a77e63f3e5be20229e1cd26b3a Mon Sep 17 00:00:00 2001 From: RFDarter Date: Wed, 20 Mar 2024 04:37:18 +0100 Subject: [PATCH 1131/2101] web_server support for v3 (#6203) --- esphome/components/web_server/__init__.py | 9 +++++++-- esphome/components/web_server/web_server.cpp | 2 +- esphome/components/web_server/web_server.h | 2 +- tests/test10.yaml | 3 +++ 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/esphome/components/web_server/__init__.py b/esphome/components/web_server/__init__.py index 2708b5d06e..bbd5bc662e 100644 --- a/esphome/components/web_server/__init__.py +++ b/esphome/components/web_server/__init__.py @@ -44,6 +44,11 @@ def default_url(config): config[CONF_CSS_URL] = "" if not (CONF_JS_URL in config): config[CONF_JS_URL] = "https://oi.esphome.io/v2/www.js" + if config[CONF_VERSION] == 3: + if not (CONF_CSS_URL in config): + config[CONF_CSS_URL] = "" + if not (CONF_JS_URL in config): + config[CONF_JS_URL] = "https://oi.esphome.io/v3/www.js" return config @@ -64,7 +69,7 @@ CONFIG_SCHEMA = cv.All( { cv.GenerateID(): cv.declare_id(WebServer), cv.Optional(CONF_PORT, default=80): cv.port, - cv.Optional(CONF_VERSION, default=2): cv.one_of(1, 2, int=True), + cv.Optional(CONF_VERSION, default=2): cv.one_of(1, 2, 3, int=True), cv.Optional(CONF_CSS_URL): cv.string, cv.Optional(CONF_CSS_INCLUDE): cv.file_, cv.Optional(CONF_JS_URL): cv.string, @@ -152,7 +157,7 @@ async def to_code(config): cg.add_define("USE_WEBSERVER") cg.add_define("USE_WEBSERVER_PORT", config[CONF_PORT]) cg.add_define("USE_WEBSERVER_VERSION", version) - if version == 2: + if version >= 2: # Don't compress the index HTML as the data sizes are almost the same. add_resource_as_progmem("INDEX_HTML", build_index_html(config), compress=False) else: diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index 69d601ed49..f065dc6684 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -358,7 +358,7 @@ void WebServer::handle_index_request(AsyncWebServerRequest *request) { stream->print(F("")); request->send(stream); } -#elif USE_WEBSERVER_VERSION == 2 +#elif USE_WEBSERVER_VERSION >= 2 void WebServer::handle_index_request(AsyncWebServerRequest *request) { AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", ESPHOME_WEBSERVER_INDEX_HTML, ESPHOME_WEBSERVER_INDEX_HTML_SIZE); diff --git a/esphome/components/web_server/web_server.h b/esphome/components/web_server/web_server.h index 06c59ecaca..57cbbe1339 100644 --- a/esphome/components/web_server/web_server.h +++ b/esphome/components/web_server/web_server.h @@ -13,7 +13,7 @@ #include #endif -#if USE_WEBSERVER_VERSION == 2 +#if USE_WEBSERVER_VERSION >= 2 extern const uint8_t ESPHOME_WEBSERVER_INDEX_HTML[] PROGMEM; extern const size_t ESPHOME_WEBSERVER_INDEX_HTML_SIZE; #endif diff --git a/tests/test10.yaml b/tests/test10.yaml index 7e3a685b36..854173cfe9 100644 --- a/tests/test10.yaml +++ b/tests/test10.yaml @@ -23,6 +23,9 @@ logger: api: reboot_timeout: 10min +web_server: + version: 3 + time: - platform: sntp From 6f7273d9cb00d1c6a4618c2b819d00b01601ffd1 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 20 Mar 2024 16:38:15 +1300 Subject: [PATCH 1132/2101] Bump version to 2024.3.0b5 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 2b5724c9f3..e573a64e1d 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.3.0b4" +__version__ = "2024.3.0b5" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 9541df9d88ed99677335c4dc9affef30373dce8e Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 20 Mar 2024 17:15:19 +1300 Subject: [PATCH 1133/2101] Bump version to 2024.3.0 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index e573a64e1d..e386448462 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.3.0b5" +__version__ = "2024.3.0" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From afbaf56c0bdc90d6b6894b334dc7247ae9a17d95 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 20 Mar 2024 21:14:15 +1300 Subject: [PATCH 1134/2101] Bump pytest-asyncio from 0.23.5.post1 to 0.23.6 (#6402) 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 29e5420d78..8fb59683b4 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -8,6 +8,6 @@ pre-commit pytest==8.1.1 pytest-cov==4.1.0 pytest-mock==3.12.0 -pytest-asyncio==0.23.5.post1 +pytest-asyncio==0.23.6 asyncmock==0.4.2 hypothesis==6.92.1 From bdb6881cd5a700b65d8aef312ac45f1cc20bfdcc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 20 Mar 2024 21:14:52 +1300 Subject: [PATCH 1135/2101] Bump actions/cache from 4.0.1 to 4.0.2 in /.github/actions/restore-python (#6403) 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 756e279635..aa4f7ba887 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@v4.0.1 + uses: actions/cache/restore@v4.0.2 with: path: venv # yamllint disable-line rule:line-length From b12ccd460b4a9b530475e3dc9e01c866d4b7b711 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 20 Mar 2024 21:15:03 +1300 Subject: [PATCH 1136/2101] Bump actions/cache from 4.0.1 to 4.0.2 (#6404) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 47709739dc..871f2e72c8 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@v4.0.1 + uses: actions/cache@v4.0.2 with: path: venv # yamllint disable-line rule:line-length @@ -367,7 +367,7 @@ jobs: python-version: ${{ env.DEFAULT_PYTHON }} cache-key: ${{ needs.common.outputs.cache-key }} - name: Cache platformio - uses: actions/cache@v4.0.1 + uses: actions/cache@v4.0.2 with: path: ~/.platformio # yamllint disable-line rule:line-length From 7d9fc3ceaab4db660a8aeddb55499d640b549cbe Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Wed, 20 Mar 2024 09:16:10 +0100 Subject: [PATCH 1137/2101] Bump ESP8266 Arduino versions (#5359) --- esphome/components/esp8266/__init__.py | 12 ++++++++---- esphome/components/mqtt/mqtt_client.cpp | 4 ---- esphome/components/wifi/wifi_component_esp8266.cpp | 10 +++++++++- esphome/core/defines.h | 2 +- platformio.ini | 4 ++-- 5 files changed, 20 insertions(+), 12 deletions(-) diff --git a/esphome/components/esp8266/__init__.py b/esphome/components/esp8266/__init__.py index 5336842b9d..00729921a3 100644 --- a/esphome/components/esp8266/__init__.py +++ b/esphome/components/esp8266/__init__.py @@ -83,20 +83,22 @@ def _format_framework_arduino_version(ver: cv.Version) -> str: # The default/recommended arduino framework version # - https://github.com/esp8266/Arduino/releases # - https://api.registry.platformio.org/v3/packages/platformio/tool/framework-arduinoespressif8266 -RECOMMENDED_ARDUINO_FRAMEWORK_VERSION = cv.Version(3, 0, 2) +RECOMMENDED_ARDUINO_FRAMEWORK_VERSION = cv.Version(3, 1, 2) # The platformio/espressif8266 version to use for arduino 2 framework versions # - https://github.com/platformio/platform-espressif8266/releases # - https://api.registry.platformio.org/v3/packages/platformio/platform/espressif8266 ARDUINO_2_PLATFORM_VERSION = cv.Version(2, 6, 3) # for arduino 3 framework versions ARDUINO_3_PLATFORM_VERSION = cv.Version(3, 2, 0) +# for arduino 4 framework versions +ARDUINO_4_PLATFORM_VERSION = cv.Version(4, 2, 1) def _arduino_check_versions(value): value = value.copy() lookups = { - "dev": (cv.Version(3, 0, 2), "https://github.com/esp8266/Arduino.git"), - "latest": (cv.Version(3, 0, 2), None), + "dev": (cv.Version(3, 1, 2), "https://github.com/esp8266/Arduino.git"), + "latest": (cv.Version(3, 1, 2), None), "recommended": (RECOMMENDED_ARDUINO_FRAMEWORK_VERSION, None), } @@ -116,7 +118,9 @@ def _arduino_check_versions(value): platform_version = value.get(CONF_PLATFORM_VERSION) if platform_version is None: - if version >= cv.Version(3, 0, 0): + if version >= cv.Version(3, 1, 0): + platform_version = _parse_platform_version(str(ARDUINO_4_PLATFORM_VERSION)) + elif version >= cv.Version(3, 0, 0): platform_version = _parse_platform_version(str(ARDUINO_3_PLATFORM_VERSION)) elif version >= cv.Version(2, 5, 0): platform_version = _parse_platform_version(str(ARDUINO_2_PLATFORM_VERSION)) diff --git a/esphome/components/mqtt/mqtt_client.cpp b/esphome/components/mqtt/mqtt_client.cpp index 0f5f49abc1..abcbb414d9 100644 --- a/esphome/components/mqtt/mqtt_client.cpp +++ b/esphome/components/mqtt/mqtt_client.cpp @@ -187,11 +187,7 @@ void MQTTClientComponent::start_dnslookup_() { default: case ERR_ARG: { // error -#if defined(USE_ESP8266) - ESP_LOGW(TAG, "Error resolving MQTT broker IP address: %ld", err); -#else ESP_LOGW(TAG, "Error resolving MQTT broker IP address: %d", err); -#endif break; } } diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index f274e37a9f..838250972b 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -21,10 +21,14 @@ extern "C" { #include #if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(3, 0, 0) #include "LwipDhcpServer.h" +#if USE_ARDUINO_VERSION_CODE < VERSION_CODE(3, 1, 0) +#include +#include "ESP8266WiFiAP.h" #define wifi_softap_set_dhcps_lease(lease) dhcpSoftAP.set_dhcps_lease(lease) #define wifi_softap_set_dhcps_lease_time(time) dhcpSoftAP.set_dhcps_lease_time(time) #define wifi_softap_set_dhcps_offer_option(offer, mode) dhcpSoftAP.set_dhcps_offer_option(offer, mode) #endif +#endif } #include "esphome/core/helpers.h" @@ -721,7 +725,7 @@ bool WiFiComponent::wifi_ap_ip_config_(optional manual_ip) { return false; } -#if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(3, 0, 0) +#if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(3, 0, 0) && USE_ARDUINO_VERSION_CODE < VERSION_CODE(3, 1, 0) dhcpSoftAP.begin(&info); #endif @@ -745,12 +749,16 @@ bool WiFiComponent::wifi_ap_ip_config_(optional manual_ip) { return false; } +#if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(3, 1, 0) + ESP8266WiFiClass::softAPDhcpServer().setRouter(true); // send ROUTER option with netif's gateway IP +#else uint8_t mode = 1; // bit0, 1 enables router information from ESP8266 SoftAP DHCP server. if (!wifi_softap_set_dhcps_offer_option(OFFER_ROUTER, &mode)) { ESP_LOGV(TAG, "wifi_softap_set_dhcps_offer_option failed!"); return false; } +#endif if (!wifi_softap_dhcps_start()) { ESP_LOGV(TAG, "Starting SoftAP DHCPS failed!"); diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 86f89e7bf6..501dccc6fa 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -98,7 +98,7 @@ // ESP8266-specific feature flags #ifdef USE_ESP8266 #define USE_ADC_SENSOR_VCC -#define USE_ARDUINO_VERSION_CODE VERSION_CODE(3, 0, 2) +#define USE_ARDUINO_VERSION_CODE VERSION_CODE(3, 1, 2) #define USE_ESP8266_PREFERENCES_FLASH #define USE_HTTP_REQUEST_ESP8266_HTTPS #define USE_SOCKET_IMPL_LWIP_TCP diff --git a/platformio.ini b/platformio.ini index 8ba8b8a2cf..b326c9722e 100644 --- a/platformio.ini +++ b/platformio.ini @@ -80,9 +80,9 @@ build_flags = ; This are common settings for the ESP8266 using Arduino. [common:esp8266-arduino] extends = common:arduino -platform = platformio/espressif8266@3.2.0 +platform = platformio/espressif8266@4.2.1 platform_packages = - platformio/framework-arduinoespressif8266@~3.30002.0 + platformio/framework-arduinoespressif8266@~3.30102.0 framework = arduino lib_deps = From b95a7f6438461e1b46f8eb95871345d2be246cf6 Mon Sep 17 00:00:00 2001 From: cvwillegen Date: Wed, 20 Mar 2024 09:16:52 +0100 Subject: [PATCH 1138/2101] Allow accept/reject delta to be specified. (#5060) --- esphome/components/remote_base/__init__.py | 3 +++ esphome/components/remote_base/pronto_protocol.cpp | 5 +++-- esphome/components/remote_base/pronto_protocol.h | 3 +++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/esphome/components/remote_base/__init__.py b/esphome/components/remote_base/__init__.py index 1d8c6e0967..08652bbfc9 100644 --- a/esphome/components/remote_base/__init__.py +++ b/esphome/components/remote_base/__init__.py @@ -32,6 +32,7 @@ from esphome.const import ( CONF_MAGNITUDE, CONF_WAND_ID, CONF_LEVEL, + CONF_DELTA, ) from esphome.core import coroutine from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor @@ -792,6 +793,7 @@ async def pioneer_action(var, config, args): PRONTO_SCHEMA = cv.Schema( { cv.Required(CONF_DATA): cv.string, + cv.Optional(CONF_DELTA, default=-1): cv.int_, } ) @@ -803,6 +805,7 @@ def pronto_binary_sensor(var, config): cg.StructInitializer( ProntoData, ("data", config[CONF_DATA]), + ("delta", config[CONF_DELTA]), ) ) ) diff --git a/esphome/components/remote_base/pronto_protocol.cpp b/esphome/components/remote_base/pronto_protocol.cpp index ccae64449a..625af76235 100644 --- a/esphome/components/remote_base/pronto_protocol.cpp +++ b/esphome/components/remote_base/pronto_protocol.cpp @@ -49,13 +49,13 @@ bool ProntoData::operator==(const ProntoData &rhs) const { for (std::vector::size_type i = 0; i < data1.size() - 1; ++i) { int diff = data2[i] - data1[i]; diff *= diff; - if (diff > 9) + if (rhs.delta == -1 && diff > 9) return false; total_diff += diff; } - return total_diff <= data1.size() * 3; + return total_diff <= (rhs.delta == -1 ? data1.size() * 3 : rhs.delta); } // DO NOT EXPORT from this file @@ -222,6 +222,7 @@ optional ProntoProtocol::decode(RemoteReceiveData src) { prontodata += compensate_and_dump_sequence_(data, timebase); out.data = prontodata; + out.delta = -1; return out; } diff --git a/esphome/components/remote_base/pronto_protocol.h b/esphome/components/remote_base/pronto_protocol.h index 8b2163af12..e600834d1a 100644 --- a/esphome/components/remote_base/pronto_protocol.h +++ b/esphome/components/remote_base/pronto_protocol.h @@ -12,6 +12,7 @@ std::vector encode_pronto(const std::string &str); struct ProntoData { std::string data; + int delta; bool operator==(const ProntoData &rhs) const; }; @@ -40,10 +41,12 @@ DECLARE_REMOTE_PROTOCOL(Pronto) template class ProntoAction : public RemoteTransmitterActionBase { public: TEMPLATABLE_VALUE(std::string, data) + TEMPLATABLE_VALUE(int, delta) void encode(RemoteTransmitData *dst, Ts... x) override { ProntoData data{}; data.data = this->data_.value(x...); + data.delta = this->delta_.value(x...); ProntoProtocol().encode(dst, data); } }; From b0db7319f90452f66bfaecd6e16a0bc3d8e730d3 Mon Sep 17 00:00:00 2001 From: Gagootron Date: Wed, 20 Mar 2024 09:17:32 +0100 Subject: [PATCH 1139/2101] Allow setting htop for ledc (#6340) --- esphome/components/ledc/ledc_output.cpp | 14 ++++++++++++-- esphome/components/ledc/ledc_output.h | 2 ++ esphome/components/ledc/output.py | 6 ++++++ tests/components/cwww/test.esp32-c3-idf.yaml | 3 +++ tests/components/cwww/test.esp32-idf.yaml | 3 +++ 5 files changed, 26 insertions(+), 2 deletions(-) diff --git a/esphome/components/ledc/ledc_output.cpp b/esphome/components/ledc/ledc_output.cpp index dfb84c1e76..0533143d37 100644 --- a/esphome/components/ledc/ledc_output.cpp +++ b/esphome/components/ledc/ledc_output.cpp @@ -96,6 +96,12 @@ esp_err_t configure_timer_frequency(ledc_mode_t speed_mode, ledc_timer_t timer_n } #endif +#ifdef USE_ESP_IDF +constexpr int ledc_angle_to_htop(float angle, uint8_t bit_depth) { + return static_cast(angle * ((1U << bit_depth) - 1) / 360.); +} +#endif // USE_ESP_IDF + void LEDCOutput::write_state(float state) { if (!initialized_) { ESP_LOGW(TAG, "LEDC output hasn't been initialized yet!"); @@ -117,7 +123,8 @@ void LEDCOutput::write_state(float state) { #ifdef USE_ESP_IDF auto speed_mode = get_speed_mode(channel_); auto chan_num = static_cast(channel_ % 8); - ledc_set_duty(speed_mode, chan_num, duty); + int hpoint = ledc_angle_to_htop(this->phase_angle_, this->bit_depth_); + ledc_set_duty_with_hpoint(speed_mode, chan_num, duty, hpoint); ledc_update_duty(speed_mode, chan_num); #endif } @@ -143,8 +150,10 @@ void LEDCOutput::setup() { this->status_set_error(); return; } + 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", this->frequency_, this->bit_depth_); + ESP_LOGV(TAG, "Angle of %.1f° results in hpoint %u", this->phase_angle_, hpoint); ledc_channel_config_t chan_conf{}; chan_conf.gpio_num = pin_->get_pin(); @@ -153,7 +162,7 @@ void LEDCOutput::setup() { chan_conf.intr_type = LEDC_INTR_DISABLE; chan_conf.timer_sel = timer_num; chan_conf.duty = inverted_ == pin_->is_inverted() ? 0 : (1U << bit_depth_); - chan_conf.hpoint = 0; + chan_conf.hpoint = hpoint; ledc_channel_config(&chan_conf); initialized_ = true; this->status_clear_error(); @@ -165,6 +174,7 @@ void LEDCOutput::dump_config() { LOG_PIN(" Pin ", this->pin_); ESP_LOGCONFIG(TAG, " LEDC Channel: %u", this->channel_); ESP_LOGCONFIG(TAG, " PWM Frequency: %.1f Hz", this->frequency_); + ESP_LOGCONFIG(TAG, " Phase angle: %.1f°", this->phase_angle_); ESP_LOGCONFIG(TAG, " Bit depth: %u", this->bit_depth_); ESP_LOGV(TAG, " Max frequency for bit depth: %f", ledc_max_frequency_for_bit_depth(this->bit_depth_)); ESP_LOGV(TAG, " Min frequency for bit depth: %f", diff --git a/esphome/components/ledc/ledc_output.h b/esphome/components/ledc/ledc_output.h index a78bf440a9..f04543bc5b 100644 --- a/esphome/components/ledc/ledc_output.h +++ b/esphome/components/ledc/ledc_output.h @@ -19,6 +19,7 @@ class LEDCOutput : public output::FloatOutput, public Component { void set_channel(uint8_t channel) { this->channel_ = channel; } void set_frequency(float frequency) { this->frequency_ = frequency; } + void set_phase_angle(float angle) { this->phase_angle_ = angle; } /// Dynamically change frequency at runtime void update_frequency(float frequency) override; @@ -35,6 +36,7 @@ class LEDCOutput : public output::FloatOutput, public Component { InternalGPIOPin *pin_; uint8_t channel_{}; uint8_t bit_depth_{}; + float phase_angle_{0.0f}; float frequency_{}; float duty_{0.0f}; bool initialized_ = false; diff --git a/esphome/components/ledc/output.py b/esphome/components/ledc/output.py index f6dc89cd9b..32c68f8d24 100644 --- a/esphome/components/ledc/output.py +++ b/esphome/components/ledc/output.py @@ -3,6 +3,7 @@ from esphome.components import output import esphome.config_validation as cv import esphome.codegen as cg from esphome.const import ( + CONF_PHASE_ANGLE, CONF_CHANNEL, CONF_FREQUENCY, CONF_ID, @@ -46,6 +47,9 @@ CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend( cv.Required(CONF_PIN): pins.internal_gpio_output_pin_schema, cv.Optional(CONF_FREQUENCY, default="1kHz"): cv.frequency, cv.Optional(CONF_CHANNEL): cv.int_range(min=0, max=15), + cv.Optional(CONF_PHASE_ANGLE): cv.All( + cv.only_with_esp_idf, cv.angle, cv.float_range(min=0.0, max=360.0) + ), } ).extend(cv.COMPONENT_SCHEMA) @@ -58,6 +62,8 @@ async def to_code(config): if CONF_CHANNEL in config: cg.add(var.set_channel(config[CONF_CHANNEL])) cg.add(var.set_frequency(config[CONF_FREQUENCY])) + if CONF_PHASE_ANGLE in config: + cg.add(var.set_phase_angle(config[CONF_PHASE_ANGLE])) @automation.register_action( diff --git a/tests/components/cwww/test.esp32-c3-idf.yaml b/tests/components/cwww/test.esp32-c3-idf.yaml index c829ca2a2b..2760a167ee 100644 --- a/tests/components/cwww/test.esp32-c3-idf.yaml +++ b/tests/components/cwww/test.esp32-c3-idf.yaml @@ -2,9 +2,12 @@ output: - platform: ledc id: light_output_1 pin: 1 + channel: 0 - platform: ledc id: light_output_2 pin: 2 + channel: 1 + phase_angle: 180° light: - platform: cwww diff --git a/tests/components/cwww/test.esp32-idf.yaml b/tests/components/cwww/test.esp32-idf.yaml index f108d96ad3..27fa160e56 100644 --- a/tests/components/cwww/test.esp32-idf.yaml +++ b/tests/components/cwww/test.esp32-idf.yaml @@ -2,9 +2,12 @@ output: - platform: ledc id: light_output_1 pin: 12 + channel: 0 - platform: ledc id: light_output_2 pin: 13 + channel: 1 + phase_angle: 180° light: - platform: cwww From 98466cb7f5edf1dd4540efc76ff1a5f6f7b21ff8 Mon Sep 17 00:00:00 2001 From: Jasper Albering Date: Wed, 20 Mar 2024 09:17:59 +0100 Subject: [PATCH 1140/2101] sm2135: add separate_modes option to support different chip variants (#6152) --- esphome/components/sm2135/__init__.py | 3 +++ esphome/components/sm2135/sm2135.cpp | 31 +++++++++++++++++---------- esphome/components/sm2135/sm2135.h | 3 +++ 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/esphome/components/sm2135/__init__.py b/esphome/components/sm2135/__init__.py index ce78d5337f..52128f1f24 100644 --- a/esphome/components/sm2135/__init__.py +++ b/esphome/components/sm2135/__init__.py @@ -15,6 +15,7 @@ SM2135 = sm2135_ns.class_("SM2135", cg.Component) CONF_RGB_CURRENT = "rgb_current" CONF_CW_CURRENT = "cw_current" +CONF_SEPARATE_MODES = "separate_modes" SM2135Current = sm2135_ns.enum("SM2135Current") @@ -51,6 +52,7 @@ CONFIG_SCHEMA = cv.Schema( cv.Required(CONF_CLOCK_PIN): pins.gpio_output_pin_schema, cv.Optional(CONF_RGB_CURRENT, "20mA"): cv.enum(DRIVE_STRENGTHS_RGB), cv.Optional(CONF_CW_CURRENT, "10mA"): cv.enum(DRIVE_STRENGTHS_CW), + cv.Optional(CONF_SEPARATE_MODES, default=True): cv.boolean, } ).extend(cv.COMPONENT_SCHEMA) @@ -66,3 +68,4 @@ async def to_code(config): cg.add(var.set_rgb_current(config[CONF_RGB_CURRENT])) cg.add(var.set_cw_current(config[CONF_CW_CURRENT])) + cg.add(var.set_separate_modes(config[CONF_SEPARATE_MODES])) diff --git a/esphome/components/sm2135/sm2135.cpp b/esphome/components/sm2135/sm2135.cpp index f9cd4235ed..9a576859ac 100644 --- a/esphome/components/sm2135/sm2135.cpp +++ b/esphome/components/sm2135/sm2135.cpp @@ -97,23 +97,32 @@ void SM2135::loop() { this->write_byte_(SM2135_ADDR_MC); this->write_byte_(current_mask_); - if (this->update_channel_ == 3 || this->update_channel_ == 4) { - // No color so must be Cold/Warm + if (this->separate_modes_) { + if (this->update_channel_ == 3 || this->update_channel_ == 4) { + // No color so must be Cold/Warm - this->write_byte_(SM2135_CW); - this->sm2135_stop_(); - delay(1); - this->sm2135_start_(); - this->write_byte_(SM2135_ADDR_C); - this->write_byte_(this->pwm_amounts_[4]); // Warm - this->write_byte_(this->pwm_amounts_[3]); // Cold + this->write_byte_(SM2135_CW); + this->sm2135_stop_(); + delay(1); + this->sm2135_start_(); + this->write_byte_(SM2135_ADDR_C); + this->write_byte_(this->pwm_amounts_[4]); // Warm + this->write_byte_(this->pwm_amounts_[3]); // Cold + } else { + // Color + + this->write_byte_(SM2135_RGB); + this->write_byte_(this->pwm_amounts_[1]); // Green + this->write_byte_(this->pwm_amounts_[0]); // Red + this->write_byte_(this->pwm_amounts_[2]); // Blue + } } else { - // Color - this->write_byte_(SM2135_RGB); this->write_byte_(this->pwm_amounts_[1]); // Green this->write_byte_(this->pwm_amounts_[0]); // Red this->write_byte_(this->pwm_amounts_[2]); // Blue + this->write_byte_(this->pwm_amounts_[4]); // Warm + this->write_byte_(this->pwm_amounts_[3]); // Cold } this->sm2135_stop_(); diff --git a/esphome/components/sm2135/sm2135.h b/esphome/components/sm2135/sm2135.h index a557fc3287..6f207d093a 100644 --- a/esphome/components/sm2135/sm2135.h +++ b/esphome/components/sm2135/sm2135.h @@ -39,6 +39,8 @@ class SM2135 : public Component { this->current_mask_ = (this->rgb_current_ << 4) | this->cw_current_; } + void set_separate_modes(bool separate_modes) { this->separate_modes_ = separate_modes; } + void setup() override; void dump_config() override; @@ -78,6 +80,7 @@ class SM2135 : public Component { uint8_t current_mask_; SM2135Current rgb_current_; SM2135Current cw_current_; + bool separate_modes_; uint8_t update_channel_; std::vector pwm_amounts_; bool update_{true}; From 0cb1cc9e1c1ee2ada27b81b7f6fad54f6b2fea63 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Wed, 20 Mar 2024 19:20:42 +1100 Subject: [PATCH 1141/2101] AHT10: fix temperature-only operation; add warning/error messages (#6405) --- esphome/components/aht10/aht10.cpp | 23 ++++++++++------------- esphome/components/aht10/aht10.h | 1 - 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/esphome/components/aht10/aht10.cpp b/esphome/components/aht10/aht10.cpp index d5af06c2a2..d812d8ef2d 100644 --- a/esphome/components/aht10/aht10.cpp +++ b/esphome/components/aht10/aht10.cpp @@ -15,7 +15,6 @@ #include "aht10.h" #include "esphome/core/log.h" #include "esphome/core/hal.h" -#include namespace esphome { namespace aht10 { @@ -27,7 +26,7 @@ static const uint8_t AHT10_MEASURE_CMD[] = {0xAC, 0x33, 0x00}; static const uint8_t AHT10_SOFTRESET_CMD[] = {0xBA}; static const uint8_t AHT10_DEFAULT_DELAY = 5; // ms, for initialization and temperature measurement -static const uint8_t AHT10_HUMIDITY_DELAY = 30; // ms +static const uint8_t AHT10_READ_DELAY = 80; // ms, time to wait for conversion result static const uint8_t AHT10_SOFTRESET_DELAY = 30; // ms static const uint8_t AHT10_ATTEMPTS = 3; // safety margin, normally 3 attempts are enough: 3*30=90ms @@ -36,7 +35,6 @@ static const uint8_t AHT10_INIT_ATTEMPTS = 10; static const uint8_t AHT10_STATUS_BUSY = 0x80; void AHT10Component::setup() { - this->read_delay_ = this->humidity_sensor_ != nullptr ? AHT10_HUMIDITY_DELAY : AHT10_DEFAULT_DELAY; if (this->write(AHT10_SOFTRESET_CMD, sizeof(AHT10_SOFTRESET_CMD)) != i2c::ERROR_OK) { ESP_LOGE(TAG, "Reset AHT10 failed!"); } @@ -87,19 +85,19 @@ void AHT10Component::setup() { void AHT10Component::restart_read_() { if (this->read_count_ == AHT10_ATTEMPTS) { this->read_count_ = 0; - ESP_LOGE(TAG, "Measurements reading timed-out!"); - this->status_set_error(); + this->status_set_error("Measurements reading timed-out!"); return; } this->read_count_++; - this->set_timeout(this->read_delay_, [this]() { this->read_data_(); }); + this->set_timeout(AHT10_READ_DELAY, [this]() { this->read_data_(); }); } void AHT10Component::read_data_() { uint8_t data[6]; - ESP_LOGD(TAG, "Read attempt %d at %ums", this->read_count_, (unsigned) (millis() - this->start_time_)); + if (this->read_count_ > 1) + ESP_LOGD(TAG, "Read attempt %d at %ums", this->read_count_, (unsigned) (millis() - this->start_time_)); if (this->read(data, 6) != i2c::ERROR_OK) { - ESP_LOGD(TAG, "Communication with AHT10 failed, waiting..."); + this->status_set_warning("AHT10 read failed, retrying soon"); this->restart_read_(); return; } @@ -116,14 +114,14 @@ void AHT10Component::read_data_() { } else { ESP_LOGD(TAG, "ATH10 Unrealistic humidity (0x0), retrying..."); if (this->write(AHT10_MEASURE_CMD, sizeof(AHT10_MEASURE_CMD)) != i2c::ERROR_OK) { - ESP_LOGE(TAG, "Communication with AHT10 failed!"); - this->status_set_warning(); + this->status_set_warning("Communication with AHT10 failed!"); } this->restart_read_(); return; } } - ESP_LOGD(TAG, "Success at %ums", (unsigned) (millis() - this->start_time_)); + if (this->read_count_ > 1) + ESP_LOGD(TAG, "Success at %ums", (unsigned) (millis() - this->start_time_)); uint32_t raw_temperature = ((data[3] & 0x0F) << 16) | (data[4] << 8) | data[5]; uint32_t raw_humidity = ((data[1] << 16) | (data[2] << 8) | data[3]) >> 4; @@ -151,8 +149,7 @@ void AHT10Component::update() { return; this->start_time_ = millis(); if (this->write(AHT10_MEASURE_CMD, sizeof(AHT10_MEASURE_CMD)) != i2c::ERROR_OK) { - ESP_LOGE(TAG, "Communication with AHT10 failed!"); - this->status_set_warning(); + this->status_set_warning("Communication with AHT10 failed!"); return; } this->restart_read_(); diff --git a/esphome/components/aht10/aht10.h b/esphome/components/aht10/aht10.h index 76f051878e..a3320c77e0 100644 --- a/esphome/components/aht10/aht10.h +++ b/esphome/components/aht10/aht10.h @@ -27,7 +27,6 @@ class AHT10Component : public PollingComponent, public i2c::I2CDevice { sensor::Sensor *humidity_sensor_{nullptr}; AHT10Variant variant_{}; unsigned read_count_{}; - unsigned read_delay_{}; void read_data_(); void restart_read_(); uint32_t start_time_{}; From b637fb3adc8dc0d0620f706dc3f20b5cbb53fcbe Mon Sep 17 00:00:00 2001 From: DAVe3283 Date: Wed, 20 Mar 2024 17:57:27 -0600 Subject: [PATCH 1142/2101] Fix logger compile error on ESP32-C6 (#6323) --- esphome/components/logger/logger_esp32.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/logger/logger_esp32.cpp b/esphome/components/logger/logger_esp32.cpp index 7c4d6781c9..740e086f92 100644 --- a/esphome/components/logger/logger_esp32.cpp +++ b/esphome/components/logger/logger_esp32.cpp @@ -129,7 +129,7 @@ void Logger::pre_setup() { this->uart_num_ = UART_NUM_2; break; #endif -#if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) +#ifdef USE_LOGGER_USB_CDC case UART_SELECTION_USB_CDC: this->uart_num_ = -1; break; From 13059805d074173878132501c58727be286a3d54 Mon Sep 17 00:00:00 2001 From: Moriah Morgan Date: Wed, 20 Mar 2024 19:40:14 -0500 Subject: [PATCH 1143/2101] Add support for new modes in Tuya Climate (#5159) * Add support support for new modes Added support for Fan Only Mode, Dry Mode, Swing Mode and Fan Speed Control. Also added/fixed support for entity states syncing with current operation mode. * Add support for more climate modes in climate.tuya Added support for Fan Only Mode, Dry Mode, Swing Mode and Fan Speed Control. Also added/fixed support for entity states syncing with current operation mode. This commit fixes the namespace, because I uploaded the test files to start with. * Code Formatting Changes per Clang format. * More clang formatting fixes. * Breaking Change: Group YAML entries by type Add grouping to Preset, Swing Mode, Fan Speed and Active State. This is a breaking change. * Formatting Changes for validation Formatting changes to be compliant with black and flake8. Also changed constants to match expected format. * More constant value fixes * Final black formatting check? * Changes to init.py according to reviewer requests Make changes to _init_.py according to https://github.com/esphome/esphome/pull/5159/files/649b923804c05fa6ee750e824e3d7d70fadeabd9#r1278620976, https://github.com/esphome/esphome/pull/5159/files/649b923804c05fa6ee750e824e3d7d70fadeabd9#r1278621039, https://github.com/esphome/esphome/pull/5159/files/649b923804c05fa6ee750e824e3d7d70fadeabd9#r1278620904, and https://github.com/esphome/esphome/pull/5159/files/649b923804c05fa6ee750e824e3d7d70fadeabd9#r1278620549 Also put Sleep preset in its own config block to be consistent with other presets and fix logic for validate_cooling_values function to better align with existing documentation. * Commit reviewed change Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> * update deprecated config option wording * add "this->" to member variables that were missed adding "this->" to some member variables in the swing_mode function. * Update _init_.py to use Python 3.8 Walrus operator Adding Walrus Operator in the to_code function for _init_.py similar to https://github.com/esphome/esphome/pull/5181 * Fix Temperature_Multiplier config entry for code generation --------- Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Co-authored-by: Keith Burzinski --- esphome/components/tuya/climate/__init__.py | 246 ++++++++++++------ .../components/tuya/climate/tuya_climate.cpp | 241 ++++++++++++++++- .../components/tuya/climate/tuya_climate.h | 42 +++ 3 files changed, 449 insertions(+), 80 deletions(-) diff --git a/esphome/components/tuya/climate/__init__.py b/esphome/components/tuya/climate/__init__.py index 199c2eabeb..b3d401e5a4 100644 --- a/esphome/components/tuya/climate/__init__.py +++ b/esphome/components/tuya/climate/__init__.py @@ -7,15 +7,22 @@ from esphome.const import ( CONF_SWITCH_DATAPOINT, CONF_SUPPORTS_COOL, CONF_SUPPORTS_HEAT, + CONF_PRESET, + CONF_SWING_MODE, + CONF_FAN_MODE, + CONF_TEMPERATURE, ) from .. import tuya_ns, CONF_TUYA_ID, Tuya DEPENDENCIES = ["tuya"] CODEOWNERS = ["@jesserockz"] -CONF_ACTIVE_STATE_DATAPOINT = "active_state_datapoint" -CONF_ACTIVE_STATE_HEATING_VALUE = "active_state_heating_value" -CONF_ACTIVE_STATE_COOLING_VALUE = "active_state_cooling_value" +CONF_ACTIVE_STATE = "active_state" +CONF_DATAPOINT = "datapoint" +CONF_HEATING_VALUE = "heating_value" +CONF_COOLING_VALUE = "cooling_value" +CONF_DRYING_VALUE = "drying_value" +CONF_FANONLY_VALUE = "fanonly_value" CONF_HEATING_STATE_PIN = "heating_state_pin" CONF_COOLING_STATE_PIN = "cooling_state_pin" CONF_TARGET_TEMPERATURE_DATAPOINT = "target_temperature_datapoint" @@ -23,9 +30,17 @@ CONF_CURRENT_TEMPERATURE_DATAPOINT = "current_temperature_datapoint" CONF_TEMPERATURE_MULTIPLIER = "temperature_multiplier" CONF_CURRENT_TEMPERATURE_MULTIPLIER = "current_temperature_multiplier" CONF_TARGET_TEMPERATURE_MULTIPLIER = "target_temperature_multiplier" -CONF_ECO_DATAPOINT = "eco_datapoint" -CONF_ECO_TEMPERATURE = "eco_temperature" +CONF_ECO = "eco" +CONF_SLEEP = "sleep" +CONF_SLEEP_DATAPOINT = "sleep_datapoint" CONF_REPORTS_FAHRENHEIT = "reports_fahrenheit" +CONF_VERTICAL_DATAPOINT = "vertical_datapoint" +CONF_HORIZONTAL_DATAPOINT = "horizontal_datapoint" +CONF_LOW_VALUE = "low_value" +CONF_MEDIUM_VALUE = "medium_value" +CONF_MIDDLE_VALUE = "middle_value" +CONF_HIGH_VALUE = "high_value" +CONF_AUTO_VALUE = "auto_value" TuyaClimate = tuya_ns.class_("TuyaClimate", climate.Climate, cg.Component) @@ -67,30 +82,73 @@ def validate_temperature_multipliers(value): return value -def validate_active_state_values(value): - if CONF_ACTIVE_STATE_DATAPOINT not in value: - if CONF_ACTIVE_STATE_COOLING_VALUE in value: - raise cv.Invalid( - f"{CONF_ACTIVE_STATE_DATAPOINT} required if using " - f"{CONF_ACTIVE_STATE_COOLING_VALUE}" - ) - else: - if value[CONF_SUPPORTS_COOL] and CONF_ACTIVE_STATE_COOLING_VALUE not in value: - raise cv.Invalid( - f"{CONF_ACTIVE_STATE_COOLING_VALUE} required if using " - f"{CONF_ACTIVE_STATE_DATAPOINT} and device supports cooling" - ) +def validate_cooling_values(value): + if CONF_SUPPORTS_COOL in value: + cooling_supported = value[CONF_SUPPORTS_COOL] + if not cooling_supported and CONF_ACTIVE_STATE in value: + active_state_config = value[CONF_ACTIVE_STATE] + if ( + CONF_COOLING_VALUE in active_state_config + or CONF_COOLING_STATE_PIN in value + ): + raise cv.Invalid( + f"Device does not support cooling, but {CONF_COOLING_VALUE} or {CONF_COOLING_STATE_PIN} specified." + f" Please add '{CONF_SUPPORTS_COOL}: true' to your configuration." + ) + elif cooling_supported and CONF_ACTIVE_STATE in value: + active_state_config = value[CONF_ACTIVE_STATE] + if ( + CONF_COOLING_VALUE not in active_state_config + and CONF_COOLING_STATE_PIN not in value + ): + raise cv.Invalid( + f"Either {CONF_ACTIVE_STATE} {CONF_COOLING_VALUE} or {CONF_COOLING_STATE_PIN} is required if" + f" {CONF_SUPPORTS_COOL}: true' is in your configuration." + ) return value -def validate_eco_values(value): - if CONF_ECO_TEMPERATURE in value and CONF_ECO_DATAPOINT not in value: - raise cv.Invalid( - f"{CONF_ECO_DATAPOINT} required if using {CONF_ECO_TEMPERATURE}" - ) - return value +ACTIVE_STATES = cv.Schema( + { + cv.Required(CONF_DATAPOINT): cv.uint8_t, + cv.Optional(CONF_HEATING_VALUE, default=1): cv.uint8_t, + cv.Optional(CONF_COOLING_VALUE): cv.uint8_t, + cv.Optional(CONF_DRYING_VALUE): cv.uint8_t, + cv.Optional(CONF_FANONLY_VALUE): cv.uint8_t, + }, +) +PRESETS = cv.Schema( + { + cv.Optional(CONF_ECO): { + cv.Required(CONF_DATAPOINT): cv.uint8_t, + cv.Optional(CONF_TEMPERATURE): cv.temperature, + }, + cv.Optional(CONF_SLEEP): { + cv.Required(CONF_DATAPOINT): cv.uint8_t, + }, + }, +) + +FAN_MODES = cv.Schema( + { + cv.Required(CONF_DATAPOINT): cv.uint8_t, + cv.Optional(CONF_AUTO_VALUE): cv.uint8_t, + cv.Optional(CONF_LOW_VALUE): cv.uint8_t, + cv.Optional(CONF_MEDIUM_VALUE): cv.uint8_t, + cv.Optional(CONF_MIDDLE_VALUE): cv.uint8_t, + cv.Optional(CONF_HIGH_VALUE): cv.uint8_t, + } +) + +SWING_MODES = cv.Schema( + { + cv.Optional(CONF_VERTICAL_DATAPOINT): cv.uint8_t, + cv.Optional(CONF_HORIZONTAL_DATAPOINT): cv.uint8_t, + }, +) + CONFIG_SCHEMA = cv.All( climate.CLIMATE_SCHEMA.extend( { @@ -99,9 +157,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_SUPPORTS_HEAT, default=True): cv.boolean, cv.Optional(CONF_SUPPORTS_COOL, default=False): cv.boolean, cv.Optional(CONF_SWITCH_DATAPOINT): cv.uint8_t, - cv.Optional(CONF_ACTIVE_STATE_DATAPOINT): cv.uint8_t, - cv.Optional(CONF_ACTIVE_STATE_HEATING_VALUE, default=1): cv.uint8_t, - cv.Optional(CONF_ACTIVE_STATE_COOLING_VALUE): cv.uint8_t, + cv.Optional(CONF_ACTIVE_STATE): ACTIVE_STATES, cv.Optional(CONF_HEATING_STATE_PIN): pins.gpio_input_pin_schema, cv.Optional(CONF_COOLING_STATE_PIN): pins.gpio_input_pin_schema, cv.Optional(CONF_TARGET_TEMPERATURE_DATAPOINT): cv.uint8_t, @@ -109,17 +165,32 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_TEMPERATURE_MULTIPLIER): cv.positive_float, cv.Optional(CONF_CURRENT_TEMPERATURE_MULTIPLIER): cv.positive_float, cv.Optional(CONF_TARGET_TEMPERATURE_MULTIPLIER): cv.positive_float, - cv.Optional(CONF_ECO_DATAPOINT): cv.uint8_t, - cv.Optional(CONF_ECO_TEMPERATURE): cv.temperature, cv.Optional(CONF_REPORTS_FAHRENHEIT, default=False): cv.boolean, + cv.Optional(CONF_PRESET): PRESETS, + cv.Optional(CONF_FAN_MODE): FAN_MODES, + cv.Optional(CONF_SWING_MODE): SWING_MODES, + cv.Optional("active_state_datapoint"): cv.invalid( + "'active_state_datapoint' has been moved inside of the 'active_state' config block as 'datapoint'" + ), + cv.Optional("active_state_heating_value"): cv.invalid( + "'active_state_heating_value' has been moved inside of the 'active_state' config block as 'heating_value'" + ), + cv.Optional("active_state_cooling_value"): cv.invalid( + "'active_state_cooling_value' has been moved inside of the 'active_state' config block as 'cooling_value'" + ), + cv.Optional("eco_datapoint"): cv.invalid( + "'eco_datapoint' has been moved inside of the 'eco' config block under 'preset' as 'datapoint'" + ), + cv.Optional("eco_temperature"): cv.invalid( + "'eco_temperature' has been moved inside of the 'eco' config block under 'preset' as 'temperature'" + ), } ).extend(cv.COMPONENT_SCHEMA), cv.has_at_least_one_key(CONF_TARGET_TEMPERATURE_DATAPOINT, CONF_SWITCH_DATAPOINT), validate_temperature_multipliers, - validate_active_state_values, - cv.has_at_most_one_key(CONF_ACTIVE_STATE_DATAPOINT, CONF_HEATING_STATE_PIN), - cv.has_at_most_one_key(CONF_ACTIVE_STATE_DATAPOINT, CONF_COOLING_STATE_PIN), - validate_eco_values, + validate_cooling_values, + cv.has_at_most_one_key(CONF_ACTIVE_STATE, CONF_HEATING_STATE_PIN), + cv.has_at_most_one_key(CONF_ACTIVE_STATE, CONF_COOLING_STATE_PIN), ) @@ -133,61 +204,78 @@ async def to_code(config): cg.add(var.set_supports_heat(config[CONF_SUPPORTS_HEAT])) cg.add(var.set_supports_cool(config[CONF_SUPPORTS_COOL])) - if CONF_SWITCH_DATAPOINT in config: - cg.add(var.set_switch_id(config[CONF_SWITCH_DATAPOINT])) - if CONF_ACTIVE_STATE_DATAPOINT in config: - cg.add(var.set_active_state_id(config[CONF_ACTIVE_STATE_DATAPOINT])) - if CONF_ACTIVE_STATE_HEATING_VALUE in config: - cg.add( - var.set_active_state_heating_value( - config[CONF_ACTIVE_STATE_HEATING_VALUE] - ) - ) - if CONF_ACTIVE_STATE_COOLING_VALUE in config: - cg.add( - var.set_active_state_cooling_value( - config[CONF_ACTIVE_STATE_COOLING_VALUE] - ) - ) + if switch_datapoint := config.get(CONF_SWITCH_DATAPOINT): + cg.add(var.set_switch_id(switch_datapoint)) + + if active_state_config := config.get(CONF_ACTIVE_STATE): + cg.add(var.set_active_state_id(CONF_DATAPOINT)) + if (heating_value := active_state_config.get(CONF_HEATING_VALUE)) is not None: + cg.add(var.set_active_state_heating_value(heating_value)) + if (cooling_value := active_state_config.get(CONF_COOLING_VALUE)) is not None: + cg.add(var.set_active_state_cooling_value(cooling_value)) + if (drying_value := active_state_config.get(CONF_DRYING_VALUE)) is not None: + cg.add(var.set_active_state_drying_value(drying_value)) + if (fanonly_value := active_state_config.get(CONF_FANONLY_VALUE)) is not None: + cg.add(var.set_active_state_fanonly_value(fanonly_value)) else: - if CONF_HEATING_STATE_PIN in config: + if heating_state_pin_config := config.get(CONF_HEATING_STATE_PIN): heating_state_pin = await cg.gpio_pin_expression( - config[CONF_HEATING_STATE_PIN] + config(heating_state_pin_config) ) cg.add(var.set_heating_state_pin(heating_state_pin)) - if CONF_COOLING_STATE_PIN in config: + if cooling_state_pin_config := config.get(CONF_COOLING_STATE_PIN): cooling_state_pin = await cg.gpio_pin_expression( - config[CONF_COOLING_STATE_PIN] + config(cooling_state_pin_config) ) cg.add(var.set_cooling_state_pin(cooling_state_pin)) - if CONF_TARGET_TEMPERATURE_DATAPOINT in config: - cg.add(var.set_target_temperature_id(config[CONF_TARGET_TEMPERATURE_DATAPOINT])) - if CONF_CURRENT_TEMPERATURE_DATAPOINT in config: - cg.add( - var.set_current_temperature_id(config[CONF_CURRENT_TEMPERATURE_DATAPOINT]) - ) - if CONF_TEMPERATURE_MULTIPLIER in config: - cg.add( - var.set_target_temperature_multiplier(config[CONF_TEMPERATURE_MULTIPLIER]) - ) - cg.add( - var.set_current_temperature_multiplier(config[CONF_TEMPERATURE_MULTIPLIER]) - ) + + if target_temperature_datapoint := config.get(CONF_TARGET_TEMPERATURE_DATAPOINT): + cg.add(var.set_target_temperature_id(target_temperature_datapoint)) + if current_temperature_datapoint := config.get(CONF_CURRENT_TEMPERATURE_DATAPOINT): + cg.add(var.set_current_temperature_id(current_temperature_datapoint)) + + if temperature_multiplier := config.get(CONF_TEMPERATURE_MULTIPLIER): + cg.add(var.set_target_temperature_multiplier(temperature_multiplier)) + cg.add(var.set_current_temperature_multiplier(temperature_multiplier)) else: - cg.add( - var.set_current_temperature_multiplier( - config[CONF_CURRENT_TEMPERATURE_MULTIPLIER] + if current_temperature_multiplier := config.get( + CONF_CURRENT_TEMPERATURE_MULTIPLIER + ): + cg.add( + var.set_current_temperature_multiplier(current_temperature_multiplier) ) - ) - cg.add( - var.set_target_temperature_multiplier( - config[CONF_TARGET_TEMPERATURE_MULTIPLIER] - ) - ) - if CONF_ECO_DATAPOINT in config: - cg.add(var.set_eco_id(config[CONF_ECO_DATAPOINT])) - if CONF_ECO_TEMPERATURE in config: - cg.add(var.set_eco_temperature(config[CONF_ECO_TEMPERATURE])) + if target_temperature_multiplier := config.get( + CONF_TARGET_TEMPERATURE_MULTIPLIER + ): + cg.add(var.set_target_temperature_multiplier(target_temperature_multiplier)) if config[CONF_REPORTS_FAHRENHEIT]: cg.add(var.set_reports_fahrenheit()) + + if preset_config := config.get(CONF_PRESET, {}): + if eco_config := preset_config.get(CONF_ECO, {}): + cg.add(var.set_eco_id(CONF_DATAPOINT)) + if eco_temperature := eco_config.get(CONF_TEMPERATURE): + cg.add(var.set_eco_temperature(eco_temperature)) + if CONF_SLEEP in preset_config: + cg.add(var.set_sleep_id(CONF_DATAPOINT)) + + if swing_mode_config := config.get(CONF_SWING_MODE): + if swing_vertical_datapoint := swing_mode_config.get(CONF_VERTICAL_DATAPOINT): + cg.add(var.set_swing_vertical_id(swing_vertical_datapoint)) + if swing_horizontal_datapoint := swing_mode_config.get( + CONF_HORIZONTAL_DATAPOINT + ): + cg.add(var.set_swing_horizontal_id(swing_horizontal_datapoint)) + if fan_mode_config := config.get(CONF_FAN_MODE): + cg.add(var.set_fan_speed_id(CONF_DATAPOINT)) + if (fan_auto_value := fan_mode_config.get(CONF_AUTO_VALUE)) is not None: + cg.add(var.set_fan_speed_auto_value(fan_auto_value)) + if (fan_low_value := fan_mode_config.get(CONF_LOW_VALUE)) is not None: + cg.add(var.set_fan_speed_low_value(fan_low_value)) + if (fan_medium_value := fan_mode_config.get(CONF_MEDIUM_VALUE)) is not None: + cg.add(var.set_fan_speed_medium_value(fan_medium_value)) + if (fan_middle_value := fan_mode_config.get(CONF_MIDDLE_VALUE)) is not None: + cg.add(var.set_fan_speed_middle_value(fan_middle_value)) + if (fan_high_value := fan_mode_config.get(CONF_HIGH_VALUE)) is not None: + cg.add(var.set_fan_speed_high_value(fan_high_value)) diff --git a/esphome/components/tuya/climate/tuya_climate.cpp b/esphome/components/tuya/climate/tuya_climate.cpp index 687764e30f..274e19a69e 100644 --- a/esphome/components/tuya/climate/tuya_climate.cpp +++ b/esphome/components/tuya/climate/tuya_climate.cpp @@ -75,6 +75,41 @@ void TuyaClimate::setup() { this->publish_state(); }); } + if (this->sleep_id_.has_value()) { + this->parent_->register_listener(*this->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_(); + this->compute_target_temperature_(); + this->publish_state(); + }); + } + if (this->swing_vertical_id_.has_value()) { + this->parent_->register_listener(*this->swing_vertical_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_(); + this->publish_state(); + }); + } + + if (this->swing_horizontal_id_.has_value()) { + this->parent_->register_listener(*this->swing_horizontal_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_(); + this->publish_state(); + }); + } + + if (this->fan_speed_id_.has_value()) { + this->parent_->register_listener(*this->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_(); + this->publish_state(); + }); + } } void TuyaClimate::loop() { @@ -110,8 +145,22 @@ void TuyaClimate::control(const climate::ClimateCall &call) { const bool switch_state = *call.get_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(); + + if (new_mode == climate::CLIMATE_MODE_HEAT && this->supports_heat_) { + this->parent_->set_enum_datapoint_value(*this->active_state_id_, *this->active_state_heating_value_); + } else if (new_mode == climate::CLIMATE_MODE_COOL && this->supports_cool_) { + this->parent_->set_enum_datapoint_value(*this->active_state_id_, *this->active_state_cooling_value_); + } else if (new_mode == climate::CLIMATE_MODE_DRY && this->active_state_drying_value_.has_value()) { + this->parent_->set_enum_datapoint_value(*this->active_state_id_, *this->active_state_drying_value_); + } else if (new_mode == climate::CLIMATE_MODE_FAN_ONLY && this->active_state_fanonly_value_.has_value()) { + this->parent_->set_enum_datapoint_value(*this->active_state_id_, *this->active_state_fanonly_value_); + } } + control_swing_mode_(call); + control_fan_mode_(call); + if (call.get_target_temperature().has_value()) { float target_temperature = *call.get_target_temperature(); if (this->reports_fahrenheit_) @@ -129,6 +178,106 @@ void TuyaClimate::control(const climate::ClimateCall &call) { ESP_LOGV(TAG, "Setting eco: %s", ONOFF(eco)); this->parent_->set_boolean_datapoint_value(*this->eco_id_, eco); } + if (this->sleep_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); + } + } +} + +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(); + + switch (swing_mode) { + case climate::CLIMATE_SWING_OFF: + if (swing_vertical_ || swing_horizontal_) { + this->swing_vertical_ = false; + this->swing_horizontal_ = false; + vertical_swing_changed = true; + horizontal_swing_changed = true; + } + break; + + case climate::CLIMATE_SWING_BOTH: + if (!swing_vertical_ || !swing_horizontal_) { + this->swing_vertical_ = true; + this->swing_horizontal_ = true; + vertical_swing_changed = true; + horizontal_swing_changed = true; + } + break; + + case climate::CLIMATE_SWING_VERTICAL: + if (!swing_vertical_ || swing_horizontal_) { + this->swing_vertical_ = true; + this->swing_horizontal_ = false; + vertical_swing_changed = true; + horizontal_swing_changed = true; + } + break; + + case climate::CLIMATE_SWING_HORIZONTAL: + if (swing_vertical_ || !swing_horizontal_) { + this->swing_vertical_ = false; + this->swing_horizontal_ = true; + vertical_swing_changed = true; + horizontal_swing_changed = true; + } + break; + + default: + break; + } + } + + if (vertical_swing_changed && this->swing_vertical_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_); + } + + if (horizontal_swing_changed && this->swing_horizontal_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_); + } + + // Publish the state after updating the swing mode + this->publish_state(); +} + +void TuyaClimate::control_fan_mode_(const climate::ClimateCall &call) { + if (call.get_fan_mode().has_value()) { + climate::ClimateFanMode fan_mode = *call.get_fan_mode(); + + uint8_t tuya_fan_speed; + switch (fan_mode) { + case climate::CLIMATE_FAN_LOW: + tuya_fan_speed = *fan_speed_low_value_; + break; + case climate::CLIMATE_FAN_MEDIUM: + tuya_fan_speed = *fan_speed_medium_value_; + break; + case climate::CLIMATE_FAN_MIDDLE: + tuya_fan_speed = *fan_speed_middle_value_; + break; + case climate::CLIMATE_FAN_HIGH: + tuya_fan_speed = *fan_speed_high_value_; + break; + case climate::CLIMATE_FAN_AUTO: + tuya_fan_speed = *fan_speed_auto_value_; + 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); + } } } @@ -140,10 +289,46 @@ climate::ClimateTraits TuyaClimate::traits() { traits.add_supported_mode(climate::CLIMATE_MODE_HEAT); if (supports_cool_) traits.add_supported_mode(climate::CLIMATE_MODE_COOL); + if (this->active_state_drying_value_.has_value()) + traits.add_supported_mode(climate::CLIMATE_MODE_DRY); + if (this->active_state_fanonly_value_.has_value()) + traits.add_supported_mode(climate::CLIMATE_MODE_FAN_ONLY); if (this->eco_id_.has_value()) { - traits.add_supported_preset(climate::CLIMATE_PRESET_NONE); traits.add_supported_preset(climate::CLIMATE_PRESET_ECO); } + if (this->sleep_id_.has_value()) { + traits.add_supported_preset(climate::CLIMATE_PRESET_SLEEP); + } + if (this->sleep_id_.has_value() || this->eco_id_.has_value()) { + traits.add_supported_preset(climate::CLIMATE_PRESET_NONE); + } + if (this->swing_vertical_id_.has_value() && this->swing_horizontal_id_.has_value()) { + std::set supported_swing_modes = { + climate::CLIMATE_SWING_OFF, climate::CLIMATE_SWING_BOTH, climate::CLIMATE_SWING_VERTICAL, + climate::CLIMATE_SWING_HORIZONTAL}; + traits.set_supported_swing_modes(std::move(supported_swing_modes)); + } else if (this->swing_vertical_id_.has_value()) { + std::set supported_swing_modes = {climate::CLIMATE_SWING_OFF, + climate::CLIMATE_SWING_VERTICAL}; + traits.set_supported_swing_modes(std::move(supported_swing_modes)); + } else if (this->swing_horizontal_id_.has_value()) { + std::set supported_swing_modes = {climate::CLIMATE_SWING_OFF, + climate::CLIMATE_SWING_HORIZONTAL}; + traits.set_supported_swing_modes(std::move(supported_swing_modes)); + } + + if (fan_speed_id_) { + if (fan_speed_low_value_) + traits.add_supported_fan_mode(climate::CLIMATE_FAN_LOW); + if (fan_speed_medium_value_) + traits.add_supported_fan_mode(climate::CLIMATE_FAN_MEDIUM); + if (fan_speed_middle_value_) + traits.add_supported_fan_mode(climate::CLIMATE_FAN_MIDDLE); + if (fan_speed_high_value_) + traits.add_supported_fan_mode(climate::CLIMATE_FAN_HIGH); + if (fan_speed_auto_value_) + traits.add_supported_fan_mode(climate::CLIMATE_FAN_AUTO); + } return traits; } @@ -166,16 +351,56 @@ void TuyaClimate::dump_config() { if (this->eco_id_.has_value()) { ESP_LOGCONFIG(TAG, " Eco has datapoint ID %u", *this->eco_id_); } + if (this->sleep_id_.has_value()) { + ESP_LOGCONFIG(TAG, " Sleep has datapoint ID %u", *this->sleep_id_); + } + if (this->swing_vertical_id_.has_value()) { + ESP_LOGCONFIG(TAG, " Swing Vertical has datapoint ID %u", *this->swing_vertical_id_); + } + if (this->swing_horizontal_id_.has_value()) { + ESP_LOGCONFIG(TAG, " Swing Horizontal has datapoint ID %u", *this->swing_horizontal_id_); + } } void TuyaClimate::compute_preset_() { if (this->eco_) { this->preset = climate::CLIMATE_PRESET_ECO; + } else if (this->sleep_) { + this->preset = climate::CLIMATE_PRESET_SLEEP; } else { this->preset = climate::CLIMATE_PRESET_NONE; } } +void TuyaClimate::compute_swingmode_() { + if (this->swing_vertical_ && this->swing_horizontal_) { + this->swing_mode = climate::CLIMATE_SWING_BOTH; + } else if (this->swing_vertical_) { + this->swing_mode = climate::CLIMATE_SWING_VERTICAL; + } else if (this->swing_horizontal_) { + this->swing_mode = climate::CLIMATE_SWING_HORIZONTAL; + } else { + this->swing_mode = climate::CLIMATE_SWING_OFF; + } +} + +void TuyaClimate::compute_fanmode_() { + if (this->fan_speed_id_.has_value()) { + // Use state from MCU datapoint + if (this->fan_speed_auto_value_.has_value() && this->fan_state_ == this->fan_speed_auto_value_) { + this->fan_mode = climate::CLIMATE_FAN_AUTO; + } else if (this->fan_speed_high_value_.has_value() && this->fan_state_ == this->fan_speed_high_value_) { + this->fan_mode = climate::CLIMATE_FAN_HIGH; + } else if (this->fan_speed_medium_value_.has_value() && this->fan_state_ == this->fan_speed_medium_value_) { + this->fan_mode = climate::CLIMATE_FAN_MEDIUM; + } else if (this->fan_speed_middle_value_.has_value() && this->fan_state_ == this->fan_speed_middle_value_) { + this->fan_mode = climate::CLIMATE_FAN_MIDDLE; + } else if (this->fan_speed_low_value_.has_value() && this->fan_state_ == this->fan_speed_low_value_) { + this->fan_mode = climate::CLIMATE_FAN_LOW; + } + } +} + void TuyaClimate::compute_target_temperature_() { if (this->eco_ && this->eco_temperature_.has_value()) { this->target_temperature = *this->eco_temperature_; @@ -202,16 +427,28 @@ void TuyaClimate::compute_state_() { if (this->supports_heat_ && this->active_state_heating_value_.has_value() && this->active_state_ == this->active_state_heating_value_) { target_action = climate::CLIMATE_ACTION_HEATING; + this->mode = climate::CLIMATE_MODE_HEAT; } else if (this->supports_cool_ && this->active_state_cooling_value_.has_value() && this->active_state_ == this->active_state_cooling_value_) { target_action = climate::CLIMATE_ACTION_COOLING; + this->mode = climate::CLIMATE_MODE_COOL; + } else if (this->active_state_drying_value_.has_value() && + this->active_state_ == this->active_state_drying_value_) { + target_action = climate::CLIMATE_ACTION_DRYING; + this->mode = climate::CLIMATE_MODE_DRY; + } else if (this->active_state_fanonly_value_.has_value() && + this->active_state_ == this->active_state_fanonly_value_) { + target_action = climate::CLIMATE_ACTION_FAN; + this->mode = climate::CLIMATE_MODE_FAN_ONLY; } } else if (this->heating_state_pin_ != nullptr || this->cooling_state_pin_ != nullptr) { // Use state from input pins if (this->heating_state_) { target_action = climate::CLIMATE_ACTION_HEATING; + this->mode = climate::CLIMATE_MODE_HEAT; } else if (this->cooling_state_) { target_action = climate::CLIMATE_ACTION_COOLING; + this->mode = climate::CLIMATE_MODE_COOL; } } else { // Fallback to active state calc based on temp and hysteresis @@ -219,8 +456,10 @@ void TuyaClimate::compute_state_() { if (std::abs(temp_diff) > this->hysteresis_) { if (this->supports_heat_ && temp_diff > 0) { target_action = climate::CLIMATE_ACTION_HEATING; + this->mode = climate::CLIMATE_MODE_HEAT; } else if (this->supports_cool_ && temp_diff < 0) { target_action = climate::CLIMATE_ACTION_COOLING; + this->mode = climate::CLIMATE_MODE_COOL; } } } diff --git a/esphome/components/tuya/climate/tuya_climate.h b/esphome/components/tuya/climate/tuya_climate.h index 7c18625c4e..d6258c21e1 100644 --- a/esphome/components/tuya/climate/tuya_climate.h +++ b/esphome/components/tuya/climate/tuya_climate.h @@ -18,8 +18,22 @@ class TuyaClimate : public climate::Climate, public Component { void set_active_state_id(uint8_t state_id) { this->active_state_id_ = state_id; } void set_active_state_heating_value(uint8_t value) { this->active_state_heating_value_ = value; } void set_active_state_cooling_value(uint8_t value) { this->active_state_cooling_value_ = value; } + void set_active_state_drying_value(uint8_t value) { this->active_state_drying_value_ = value; } + void set_active_state_fanonly_value(uint8_t value) { this->active_state_fanonly_value_ = value; } void set_heating_state_pin(GPIOPin *pin) { this->heating_state_pin_ = pin; } void set_cooling_state_pin(GPIOPin *pin) { this->cooling_state_pin_ = pin; } + void set_swing_vertical_id(uint8_t swing_vertical_id) { this->swing_vertical_id_ = swing_vertical_id; } + void set_swing_horizontal_id(uint8_t swing_horizontal_id) { this->swing_horizontal_id_ = swing_horizontal_id; } + void set_fan_speed_id(uint8_t fan_speed_id) { this->fan_speed_id_ = fan_speed_id; } + void set_fan_speed_low_value(uint8_t fan_speed_low_value) { this->fan_speed_low_value_ = fan_speed_low_value; } + void set_fan_speed_medium_value(uint8_t fan_speed_medium_value) { + this->fan_speed_medium_value_ = fan_speed_medium_value; + } + void set_fan_speed_middle_value(uint8_t fan_speed_middle_value) { + this->fan_speed_middle_value_ = fan_speed_middle_value; + } + void set_fan_speed_high_value(uint8_t fan_speed_high_value) { this->fan_speed_high_value_ = fan_speed_high_value; } + void set_fan_speed_auto_value(uint8_t fan_speed_auto_value) { this->fan_speed_auto_value_ = fan_speed_auto_value; } void set_target_temperature_id(uint8_t target_temperature_id) { this->target_temperature_id_ = target_temperature_id; } @@ -34,6 +48,7 @@ class TuyaClimate : public climate::Climate, public Component { } void set_eco_id(uint8_t eco_id) { this->eco_id_ = eco_id; } void set_eco_temperature(float eco_temperature) { this->eco_temperature_ = eco_temperature; } + void set_sleep_id(uint8_t sleep_id) { this->sleep_id_ = sleep_id; } void set_reports_fahrenheit() { this->reports_fahrenheit_ = true; } @@ -43,6 +58,12 @@ class TuyaClimate : public climate::Climate, public Component { /// Override control to change settings of the climate device. void control(const climate::ClimateCall &call) override; + /// Override control to change settings of swing mode. + void control_swing_mode_(const climate::ClimateCall &call); + + /// Override control to change settings of fan mode. + void control_fan_mode_(const climate::ClimateCall &call); + /// Return the traits of this controller. climate::ClimateTraits traits() override; @@ -55,6 +76,12 @@ class TuyaClimate : public climate::Climate, public Component { /// Re-compute the state of this climate controller. void compute_state_(); + /// Re-Compute the swing mode of this climate controller. + void compute_swingmode_(); + + /// Re-Compute the fan mode of this climate controller. + void compute_fanmode_(); + /// Switch the climate device to the given climate mode. void switch_to_action_(climate::ClimateAction action); @@ -65,6 +92,8 @@ class TuyaClimate : public climate::Climate, public Component { optional active_state_id_{}; optional active_state_heating_value_{}; optional active_state_cooling_value_{}; + optional active_state_drying_value_{}; + optional active_state_fanonly_value_{}; GPIOPin *heating_state_pin_{nullptr}; GPIOPin *cooling_state_pin_{nullptr}; optional target_temperature_id_{}; @@ -73,12 +102,25 @@ class TuyaClimate : public climate::Climate, public Component { float target_temperature_multiplier_{1.0f}; float hysteresis_{1.0f}; optional eco_id_{}; + optional sleep_id_{}; optional eco_temperature_{}; uint8_t active_state_; + uint8_t fan_state_; + optional swing_vertical_id_{}; + optional swing_horizontal_id_{}; + optional fan_speed_id_{}; + optional fan_speed_low_value_{}; + optional fan_speed_medium_value_{}; + optional fan_speed_middle_value_{}; + optional fan_speed_high_value_{}; + optional fan_speed_auto_value_{}; + bool swing_vertical_{false}; + bool swing_horizontal_{false}; bool heating_state_{false}; bool cooling_state_{false}; float manual_temperature_; bool eco_; + bool sleep_; bool reports_fahrenheit_{false}; }; From 1d6f245ced851d5875eac1e691fbda2cf2a692be Mon Sep 17 00:00:00 2001 From: Mat931 <49403702+Mat931@users.noreply.github.com> Date: Thu, 21 Mar 2024 03:23:30 +0000 Subject: [PATCH 1144/2101] Add sun_gtil2 component (for SUN-1000G2 / SUN-2000G2 grid tie inverters) (#4958) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- CODEOWNERS | 1 + esphome/components/sun_gtil2/__init__.py | 26 ++++ esphome/components/sun_gtil2/sensor.py | 87 +++++++++++ esphome/components/sun_gtil2/sun_gtil2.cpp | 135 ++++++++++++++++++ esphome/components/sun_gtil2/sun_gtil2.h | 58 ++++++++ esphome/components/sun_gtil2/text_sensor.py | 31 ++++ .../sun_gtil2/test.esp32-c3-idf.yaml | 44 ++++++ tests/components/sun_gtil2/test.esp32-c3.yaml | 44 ++++++ .../components/sun_gtil2/test.esp32-idf.yaml | 44 ++++++ tests/components/sun_gtil2/test.esp32.yaml | 44 ++++++ tests/components/sun_gtil2/test.esp8266.yaml | 44 ++++++ tests/components/sun_gtil2/test.rp2040.yaml | 44 ++++++ 12 files changed, 602 insertions(+) create mode 100644 esphome/components/sun_gtil2/__init__.py create mode 100644 esphome/components/sun_gtil2/sensor.py create mode 100644 esphome/components/sun_gtil2/sun_gtil2.cpp create mode 100644 esphome/components/sun_gtil2/sun_gtil2.h create mode 100644 esphome/components/sun_gtil2/text_sensor.py create mode 100644 tests/components/sun_gtil2/test.esp32-c3-idf.yaml create mode 100644 tests/components/sun_gtil2/test.esp32-c3.yaml create mode 100644 tests/components/sun_gtil2/test.esp32-idf.yaml create mode 100644 tests/components/sun_gtil2/test.esp32.yaml create mode 100644 tests/components/sun_gtil2/test.esp8266.yaml create mode 100644 tests/components/sun_gtil2/test.rp2040.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 4c24096faa..2c1b8f04ae 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -345,6 +345,7 @@ esphome/components/st7789v/* @kbx81 esphome/components/st7920/* @marsjan155 esphome/components/substitutions/* @esphome/core esphome/components/sun/* @OttoWinter +esphome/components/sun_gtil2/* @Mat931 esphome/components/switch/* @esphome/core esphome/components/t6615/* @tylermenezes esphome/components/tca9548a/* @andreashergert1984 diff --git a/esphome/components/sun_gtil2/__init__.py b/esphome/components/sun_gtil2/__init__.py new file mode 100644 index 0000000000..f4d46fade7 --- /dev/null +++ b/esphome/components/sun_gtil2/__init__.py @@ -0,0 +1,26 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import uart +from esphome.const import CONF_ID + +CODEOWNERS = ["@Mat931"] +MULTI_CONF = True +DEPENDENCIES = ["uart"] + +CONF_SUN_GTIL2_ID = "sun_gtil2_id" + +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) + + +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) diff --git a/esphome/components/sun_gtil2/sensor.py b/esphome/components/sun_gtil2/sensor.py new file mode 100644 index 0000000000..6d1be9c740 --- /dev/null +++ b/esphome/components/sun_gtil2/sensor.py @@ -0,0 +1,87 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import sensor +from esphome.const import ( + DEVICE_CLASS_VOLTAGE, + DEVICE_CLASS_POWER, + DEVICE_CLASS_TEMPERATURE, + ICON_FLASH, + UNIT_VOLT, + ICON_THERMOMETER, + UNIT_WATT, + UNIT_CELSIUS, + CONF_TEMPERATURE, +) +from . import SunGTIL2Component, CONF_SUN_GTIL2_ID + +CONF_AC_VOLTAGE = "ac_voltage" +CONF_DC_VOLTAGE = "dc_voltage" +CONF_AC_POWER = "ac_power" +CONF_DC_POWER = "dc_power" +CONF_LIMITER_POWER = "limiter_power" + +CONFIG_SCHEMA = cv.All( + cv.Schema( + { + cv.GenerateID(CONF_SUN_GTIL2_ID): cv.use_id(SunGTIL2Component), + cv.Optional(CONF_AC_VOLTAGE): sensor.sensor_schema( + unit_of_measurement=UNIT_VOLT, + icon=ICON_FLASH, + accuracy_decimals=1, + device_class=DEVICE_CLASS_VOLTAGE, + ), + cv.Optional(CONF_DC_VOLTAGE): sensor.sensor_schema( + unit_of_measurement=UNIT_VOLT, + icon=ICON_FLASH, + accuracy_decimals=1, + device_class=DEVICE_CLASS_VOLTAGE, + ), + cv.Optional(CONF_AC_POWER): sensor.sensor_schema( + unit_of_measurement=UNIT_WATT, + icon=ICON_FLASH, + accuracy_decimals=1, + device_class=DEVICE_CLASS_POWER, + ), + cv.Optional(CONF_DC_POWER): sensor.sensor_schema( + unit_of_measurement=UNIT_WATT, + icon=ICON_FLASH, + accuracy_decimals=1, + device_class=DEVICE_CLASS_POWER, + ), + cv.Optional(CONF_LIMITER_POWER): sensor.sensor_schema( + unit_of_measurement=UNIT_WATT, + icon=ICON_FLASH, + accuracy_decimals=1, + device_class=DEVICE_CLASS_POWER, + ), + cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema( + unit_of_measurement=UNIT_CELSIUS, + icon=ICON_THERMOMETER, + accuracy_decimals=1, + device_class=DEVICE_CLASS_TEMPERATURE, + ), + } + ).extend(cv.COMPONENT_SCHEMA) +) + + +async def to_code(config): + hub = await cg.get_variable(config[CONF_SUN_GTIL2_ID]) + if ac_voltage_config := config.get(CONF_AC_VOLTAGE): + sens = await sensor.new_sensor(ac_voltage_config) + cg.add(hub.set_ac_voltage(sens)) + if dc_voltage_config := config.get(CONF_DC_VOLTAGE): + sens = await sensor.new_sensor(dc_voltage_config) + cg.add(hub.set_dc_voltage(sens)) + if ac_power_config := config.get(CONF_AC_POWER): + sens = await sensor.new_sensor(ac_power_config) + cg.add(hub.set_ac_power(sens)) + if dc_power_config := config.get(CONF_DC_POWER): + sens = await sensor.new_sensor(dc_power_config) + cg.add(hub.set_dc_power(sens)) + if limiter_power_config := config.get(CONF_LIMITER_POWER): + sens = await sensor.new_sensor(limiter_power_config) + cg.add(hub.set_limiter_power(sens)) + if temperature_config := config.get(CONF_TEMPERATURE): + sens = await sensor.new_sensor(temperature_config) + cg.add(hub.set_temperature(sens)) diff --git a/esphome/components/sun_gtil2/sun_gtil2.cpp b/esphome/components/sun_gtil2/sun_gtil2.cpp new file mode 100644 index 0000000000..1653f937dd --- /dev/null +++ b/esphome/components/sun_gtil2/sun_gtil2.cpp @@ -0,0 +1,135 @@ +#include "sun_gtil2.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace sun_gtil2 { + +static const char *const TAG = "sun_gtil2"; + +static const double NTC_A = 0.0011591051055979914; +static const double NTC_B = 0.00022878183547845582; +static const double NTC_C = 1.0396291358342124e-07; +static const float PULLUP_RESISTANCE = 10000.0f; +static const uint16_t ADC_MAX = 1023; // ADC of the inverter controller, not the ESP + +struct SunGTIL2Message { + uint16_t sync; + uint8_t ac_waveform[277]; + uint8_t frequency; + uint16_t ac_voltage; + uint16_t ac_power; + uint16_t dc_voltage; + uint8_t state; + uint8_t unknown1; + uint8_t unknown2; + uint8_t unknown3; + uint8_t limiter_mode; + uint8_t unknown4; + uint16_t temperature; + uint32_t limiter_power; + uint16_t dc_power; + char serial_number[10]; + uint8_t unknown5; + uint8_t end[39]; +} __attribute__((packed)); + +static const uint16_t MESSAGE_SIZE = sizeof(SunGTIL2Message); + +static_assert(MESSAGE_SIZE == 350, "Expected the message size to be 350 bytes"); + +void SunGTIL2::setup() { this->rx_message_.reserve(MESSAGE_SIZE); } + +void SunGTIL2::loop() { + while (this->available()) { + uint8_t c; + this->read_byte(&c); + this->handle_char_(c); + } +} + +std::string SunGTIL2::state_to_string_(uint8_t state) { + switch (state) { + case 0x02: + return "Starting voltage too low"; + case 0x07: + return "Working"; + default: + return str_sprintf("Unknown (0x%02x)", state); + } +} + +float SunGTIL2::calculate_temperature_(uint16_t adc_value) { + if (adc_value >= ADC_MAX || adc_value == 0) { + return NAN; + } + + float ntc_resistance = PULLUP_RESISTANCE / ((static_cast(ADC_MAX) / adc_value) - 1.0f); + double lr = log(double(ntc_resistance)); + double v = NTC_A + NTC_B * lr + NTC_C * lr * lr * lr; + return float(1.0 / v - 273.15); +} + +void SunGTIL2::handle_char_(uint8_t c) { + if (this->rx_message_.size() > 1 || c == 0x07) { + this->rx_message_.push_back(c); + } else if (!this->rx_message_.empty()) { + this->rx_message_.clear(); + } + if (this->rx_message_.size() < MESSAGE_SIZE) { + return; + } + + SunGTIL2Message msg; + memcpy(&msg, this->rx_message_.data(), MESSAGE_SIZE); + this->rx_message_.clear(); + + if (!((msg.end[0] == 0) && (msg.end[38] == 0x08))) + return; + + ESP_LOGVV(TAG, "Frequency raw value: %02x", msg.frequency); + ESP_LOGVV(TAG, "Unknown values: %02x %02x %02x %02x %02x", msg.unknown1, msg.unknown2, msg.unknown3, msg.unknown4, + msg.unknown5); + +#ifdef USE_SENSOR + if (this->ac_voltage_ != nullptr) + this->ac_voltage_->publish_state(__builtin_bswap16(msg.ac_voltage) / 10.0f); + if (this->dc_voltage_ != nullptr) + this->dc_voltage_->publish_state(__builtin_bswap16(msg.dc_voltage) / 8.0f); + if (this->ac_power_ != nullptr) + this->ac_power_->publish_state(__builtin_bswap16(msg.ac_power) / 10.0f); + if (this->dc_power_ != nullptr) + this->dc_power_->publish_state(__builtin_bswap16(msg.dc_power) / 10.0f); + if (this->limiter_power_ != nullptr) + this->limiter_power_->publish_state(static_cast(__builtin_bswap32(msg.limiter_power)) / 10.0f); + if (this->temperature_ != nullptr) + this->temperature_->publish_state(calculate_temperature_(__builtin_bswap16(msg.temperature))); +#endif +#ifdef USE_TEXT_SENSOR + if (this->state_ != nullptr) { + this->state_->publish_state(this->state_to_string_(msg.state)); + } + if (this->serial_number_ != nullptr) { + std::string serial_number; + serial_number.assign(msg.serial_number, 10); + this->serial_number_->publish_state(serial_number); + } +#endif +} + +void SunGTIL2::dump_config() { +#ifdef USE_SENSOR + LOG_SENSOR("", "AC Voltage", this->ac_voltage_); + LOG_SENSOR("", "DC Voltage", this->dc_voltage_); + LOG_SENSOR("", "AC Power", this->ac_power_); + LOG_SENSOR("", "DC Power", this->dc_power_); + LOG_SENSOR("", "Limiter Power", this->limiter_power_); + LOG_SENSOR("", "Temperature", this->temperature_); +#endif +#ifdef USE_TEXT_SENSOR + LOG_TEXT_SENSOR("", "State", this->state_); + LOG_TEXT_SENSOR("", "Serial Number", this->serial_number_); +#endif +} + +} // namespace sun_gtil2 +} // namespace esphome diff --git a/esphome/components/sun_gtil2/sun_gtil2.h b/esphome/components/sun_gtil2/sun_gtil2.h new file mode 100644 index 0000000000..0c29ae695d --- /dev/null +++ b/esphome/components/sun_gtil2/sun_gtil2.h @@ -0,0 +1,58 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/core/defines.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" + +namespace esphome { +namespace sun_gtil2 { + +class SunGTIL2 : public Component, public uart::UARTDevice { + public: + float get_setup_priority() const override { return setup_priority::LATE; } + void setup() override; + void loop() override; + void dump_config() override; + +#ifdef USE_SENSOR + void set_ac_voltage(sensor::Sensor *sensor) { ac_voltage_ = sensor; } + void set_dc_voltage(sensor::Sensor *sensor) { dc_voltage_ = sensor; } + void set_ac_power(sensor::Sensor *sensor) { ac_power_ = sensor; } + void set_dc_power(sensor::Sensor *sensor) { dc_power_ = sensor; } + void set_limiter_power(sensor::Sensor *sensor) { limiter_power_ = sensor; } + void set_temperature(sensor::Sensor *sensor) { temperature_ = sensor; } +#endif +#ifdef USE_TEXT_SENSOR + void set_state(text_sensor::TextSensor *text_sensor) { state_ = text_sensor; } + void set_serial_number(text_sensor::TextSensor *text_sensor) { serial_number_ = text_sensor; } +#endif + + protected: + std::string state_to_string_(uint8_t state); +#ifdef USE_SENSOR + sensor::Sensor *ac_voltage_{nullptr}; + sensor::Sensor *dc_voltage_{nullptr}; + sensor::Sensor *ac_power_{nullptr}; + sensor::Sensor *dc_power_{nullptr}; + sensor::Sensor *limiter_power_{nullptr}; + sensor::Sensor *temperature_{nullptr}; +#endif +#ifdef USE_TEXT_SENSOR + text_sensor::TextSensor *state_{nullptr}; + text_sensor::TextSensor *serial_number_{nullptr}; +#endif + + float calculate_temperature_(uint16_t adc_value); + void handle_char_(uint8_t c); + std::vector rx_message_; +}; + +} // namespace sun_gtil2 +} // namespace esphome diff --git a/esphome/components/sun_gtil2/text_sensor.py b/esphome/components/sun_gtil2/text_sensor.py new file mode 100644 index 0000000000..d9d3e3ca66 --- /dev/null +++ b/esphome/components/sun_gtil2/text_sensor.py @@ -0,0 +1,31 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import text_sensor +from esphome.const import CONF_STATE +from . import SunGTIL2Component, CONF_SUN_GTIL2_ID + +CONF_SERIAL_NUMBER = "serial_number" + +CONFIG_SCHEMA = cv.All( + cv.Schema( + { + cv.GenerateID(CONF_SUN_GTIL2_ID): cv.use_id(SunGTIL2Component), + cv.Optional(CONF_STATE): text_sensor.text_sensor_schema( + text_sensor.TextSensor + ), + cv.Optional(CONF_SERIAL_NUMBER): text_sensor.text_sensor_schema( + text_sensor.TextSensor + ), + } + ).extend(cv.COMPONENT_SCHEMA) +) + + +async def to_code(config): + hub = await cg.get_variable(config[CONF_SUN_GTIL2_ID]) + if state_config := config.get(CONF_STATE): + sens = await text_sensor.new_text_sensor(state_config) + cg.add(hub.set_state(sens)) + if serial_number_config := config.get(CONF_SERIAL_NUMBER): + sens = await text_sensor.new_text_sensor(serial_number_config) + cg.add(hub.set_serial_number(sens)) diff --git a/tests/components/sun_gtil2/test.esp32-c3-idf.yaml b/tests/components/sun_gtil2/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..6ec834db98 --- /dev/null +++ b/tests/components/sun_gtil2/test.esp32-c3-idf.yaml @@ -0,0 +1,44 @@ +uart: + - id: control_to_display + rx_pin: + number: 5 + baud_rate: 9600 + +sun_gtil2: + uart_id: control_to_display + +sensor: + - platform: sun_gtil2 + temperature: + id: gtil_temperature + name: "Heatsink Temperature" + filters: + - throttle_average: 30s + dc_voltage: + id: gtil_dc_voltage + name: "DC Voltage" + filters: + - throttle_average: 30s + ac_voltage: + id: gtil_ac_voltage + name: "AC Voltage" + filters: + - throttle_average: 30s + ac_power: + id: gtil_ac_power + name: "AC Power" + dc_power: + id: gtil_dc_power + name: "DC Power" + limiter_power: + id: gtil_limiter_power + internal: true + +text_sensor: + - platform: sun_gtil2 + state: + id: gtil_state + name: "State" + serial_number: + id: gtil_serial_number + internal: true diff --git a/tests/components/sun_gtil2/test.esp32-c3.yaml b/tests/components/sun_gtil2/test.esp32-c3.yaml new file mode 100644 index 0000000000..6ec834db98 --- /dev/null +++ b/tests/components/sun_gtil2/test.esp32-c3.yaml @@ -0,0 +1,44 @@ +uart: + - id: control_to_display + rx_pin: + number: 5 + baud_rate: 9600 + +sun_gtil2: + uart_id: control_to_display + +sensor: + - platform: sun_gtil2 + temperature: + id: gtil_temperature + name: "Heatsink Temperature" + filters: + - throttle_average: 30s + dc_voltage: + id: gtil_dc_voltage + name: "DC Voltage" + filters: + - throttle_average: 30s + ac_voltage: + id: gtil_ac_voltage + name: "AC Voltage" + filters: + - throttle_average: 30s + ac_power: + id: gtil_ac_power + name: "AC Power" + dc_power: + id: gtil_dc_power + name: "DC Power" + limiter_power: + id: gtil_limiter_power + internal: true + +text_sensor: + - platform: sun_gtil2 + state: + id: gtil_state + name: "State" + serial_number: + id: gtil_serial_number + internal: true diff --git a/tests/components/sun_gtil2/test.esp32-idf.yaml b/tests/components/sun_gtil2/test.esp32-idf.yaml new file mode 100644 index 0000000000..ed1e68e574 --- /dev/null +++ b/tests/components/sun_gtil2/test.esp32-idf.yaml @@ -0,0 +1,44 @@ +uart: + - id: control_to_display + rx_pin: + number: 16 + baud_rate: 9600 + +sun_gtil2: + uart_id: control_to_display + +sensor: + - platform: sun_gtil2 + temperature: + id: gtil_temperature + name: "Heatsink Temperature" + filters: + - throttle_average: 30s + dc_voltage: + id: gtil_dc_voltage + name: "DC Voltage" + filters: + - throttle_average: 30s + ac_voltage: + id: gtil_ac_voltage + name: "AC Voltage" + filters: + - throttle_average: 30s + ac_power: + id: gtil_ac_power + name: "AC Power" + dc_power: + id: gtil_dc_power + name: "DC Power" + limiter_power: + id: gtil_limiter_power + internal: true + +text_sensor: + - platform: sun_gtil2 + state: + id: gtil_state + name: "State" + serial_number: + id: gtil_serial_number + internal: true diff --git a/tests/components/sun_gtil2/test.esp32.yaml b/tests/components/sun_gtil2/test.esp32.yaml new file mode 100644 index 0000000000..ed1e68e574 --- /dev/null +++ b/tests/components/sun_gtil2/test.esp32.yaml @@ -0,0 +1,44 @@ +uart: + - id: control_to_display + rx_pin: + number: 16 + baud_rate: 9600 + +sun_gtil2: + uart_id: control_to_display + +sensor: + - platform: sun_gtil2 + temperature: + id: gtil_temperature + name: "Heatsink Temperature" + filters: + - throttle_average: 30s + dc_voltage: + id: gtil_dc_voltage + name: "DC Voltage" + filters: + - throttle_average: 30s + ac_voltage: + id: gtil_ac_voltage + name: "AC Voltage" + filters: + - throttle_average: 30s + ac_power: + id: gtil_ac_power + name: "AC Power" + dc_power: + id: gtil_dc_power + name: "DC Power" + limiter_power: + id: gtil_limiter_power + internal: true + +text_sensor: + - platform: sun_gtil2 + state: + id: gtil_state + name: "State" + serial_number: + id: gtil_serial_number + internal: true diff --git a/tests/components/sun_gtil2/test.esp8266.yaml b/tests/components/sun_gtil2/test.esp8266.yaml new file mode 100644 index 0000000000..6ec834db98 --- /dev/null +++ b/tests/components/sun_gtil2/test.esp8266.yaml @@ -0,0 +1,44 @@ +uart: + - id: control_to_display + rx_pin: + number: 5 + baud_rate: 9600 + +sun_gtil2: + uart_id: control_to_display + +sensor: + - platform: sun_gtil2 + temperature: + id: gtil_temperature + name: "Heatsink Temperature" + filters: + - throttle_average: 30s + dc_voltage: + id: gtil_dc_voltage + name: "DC Voltage" + filters: + - throttle_average: 30s + ac_voltage: + id: gtil_ac_voltage + name: "AC Voltage" + filters: + - throttle_average: 30s + ac_power: + id: gtil_ac_power + name: "AC Power" + dc_power: + id: gtil_dc_power + name: "DC Power" + limiter_power: + id: gtil_limiter_power + internal: true + +text_sensor: + - platform: sun_gtil2 + state: + id: gtil_state + name: "State" + serial_number: + id: gtil_serial_number + internal: true diff --git a/tests/components/sun_gtil2/test.rp2040.yaml b/tests/components/sun_gtil2/test.rp2040.yaml new file mode 100644 index 0000000000..6ec834db98 --- /dev/null +++ b/tests/components/sun_gtil2/test.rp2040.yaml @@ -0,0 +1,44 @@ +uart: + - id: control_to_display + rx_pin: + number: 5 + baud_rate: 9600 + +sun_gtil2: + uart_id: control_to_display + +sensor: + - platform: sun_gtil2 + temperature: + id: gtil_temperature + name: "Heatsink Temperature" + filters: + - throttle_average: 30s + dc_voltage: + id: gtil_dc_voltage + name: "DC Voltage" + filters: + - throttle_average: 30s + ac_voltage: + id: gtil_ac_voltage + name: "AC Voltage" + filters: + - throttle_average: 30s + ac_power: + id: gtil_ac_power + name: "AC Power" + dc_power: + id: gtil_dc_power + name: "DC Power" + limiter_power: + id: gtil_limiter_power + internal: true + +text_sensor: + - platform: sun_gtil2 + state: + id: gtil_state + name: "State" + serial_number: + id: gtil_serial_number + internal: true From d0ced3471e8acce2c72e11458005d870ee5eb88c Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Thu, 21 Mar 2024 14:25:11 +1100 Subject: [PATCH 1145/2101] SPI: Make some validation failures give more useful messages. (#6413) --- esphome/components/spi/__init__.py | 9 +++++++++ tests/components/xpt2046/test.esp32-c3-idf.yaml | 9 +++++---- tests/components/xpt2046/test.esp32-c3.yaml | 9 +++++---- tests/components/xpt2046/test.esp32-idf.yaml | 9 +++++---- tests/components/xpt2046/test.esp32.yaml | 9 +++++---- tests/components/xpt2046/test.esp8266.yaml | 9 +++++---- tests/components/xpt2046/test.rp2040.yaml | 9 +++++---- 7 files changed, 39 insertions(+), 24 deletions(-) diff --git a/esphome/components/spi/__init__.py b/esphome/components/spi/__init__.py index 2847c5bfa1..fdf19bb56e 100644 --- a/esphome/components/spi/__init__.py +++ b/esphome/components/spi/__init__.py @@ -268,6 +268,9 @@ SPI_SCHEMA = cv.All( *sum(get_hw_interface_list(), ["software", "hardware", "any"]), lower=True, ), + cv.Optional(CONF_DATA_PINS): cv.invalid( + "'data_pins' should be used with 'type: quad' only" + ), } ), cv.has_at_least_one_key(CONF_MISO_PIN, CONF_MOSI_PIN), @@ -287,6 +290,12 @@ SPI_QUAD_SCHEMA = cv.All( *sum(get_hw_interface_list(), ["hardware"]), lower=True, ), + cv.Optional(CONF_MISO_PIN): cv.invalid( + "'miso_pin' should not be used with quad SPI" + ), + cv.Optional(CONF_MOSI_PIN): cv.invalid( + "'mosi_pin' should not be used with quad SPI" + ), } ), cv.only_on([PLATFORM_ESP32]), diff --git a/tests/components/xpt2046/test.esp32-c3-idf.yaml b/tests/components/xpt2046/test.esp32-c3-idf.yaml index 38a1da74ae..f3a2cf9aae 100644 --- a/tests/components/xpt2046/test.esp32-c3-idf.yaml +++ b/tests/components/xpt2046/test.esp32-c3-idf.yaml @@ -23,10 +23,11 @@ touchscreen: display: xpt_display update_interval: 50ms threshold: 400 - calibration_x_min: 3860 - calibration_x_max: 280 - calibration_y_min: 340 - calibration_y_max: 3860 + calibration: + x_min: 3860 + x_max: 280 + y_min: 340 + y_max: 3860 on_touch: - logger.log: format: Touch at (%d, %d) diff --git a/tests/components/xpt2046/test.esp32-c3.yaml b/tests/components/xpt2046/test.esp32-c3.yaml index 38a1da74ae..f3a2cf9aae 100644 --- a/tests/components/xpt2046/test.esp32-c3.yaml +++ b/tests/components/xpt2046/test.esp32-c3.yaml @@ -23,10 +23,11 @@ touchscreen: display: xpt_display update_interval: 50ms threshold: 400 - calibration_x_min: 3860 - calibration_x_max: 280 - calibration_y_min: 340 - calibration_y_max: 3860 + calibration: + x_min: 3860 + x_max: 280 + y_min: 340 + y_max: 3860 on_touch: - logger.log: format: Touch at (%d, %d) diff --git a/tests/components/xpt2046/test.esp32-idf.yaml b/tests/components/xpt2046/test.esp32-idf.yaml index 7f8617d176..bb166866f4 100644 --- a/tests/components/xpt2046/test.esp32-idf.yaml +++ b/tests/components/xpt2046/test.esp32-idf.yaml @@ -23,10 +23,11 @@ touchscreen: display: xpt_display update_interval: 50ms threshold: 400 - calibration_x_min: 3860 - calibration_x_max: 280 - calibration_y_min: 340 - calibration_y_max: 3860 + calibration: + x_min: 3860 + x_max: 280 + y_min: 340 + y_max: 3860 on_touch: - logger.log: format: Touch at (%d, %d) diff --git a/tests/components/xpt2046/test.esp32.yaml b/tests/components/xpt2046/test.esp32.yaml index 7f8617d176..bb166866f4 100644 --- a/tests/components/xpt2046/test.esp32.yaml +++ b/tests/components/xpt2046/test.esp32.yaml @@ -23,10 +23,11 @@ touchscreen: display: xpt_display update_interval: 50ms threshold: 400 - calibration_x_min: 3860 - calibration_x_max: 280 - calibration_y_min: 340 - calibration_y_max: 3860 + calibration: + x_min: 3860 + x_max: 280 + y_min: 340 + y_max: 3860 on_touch: - logger.log: format: Touch at (%d, %d) diff --git a/tests/components/xpt2046/test.esp8266.yaml b/tests/components/xpt2046/test.esp8266.yaml index a998d2df14..a917290e8e 100644 --- a/tests/components/xpt2046/test.esp8266.yaml +++ b/tests/components/xpt2046/test.esp8266.yaml @@ -23,10 +23,11 @@ touchscreen: display: xpt_display update_interval: 50ms threshold: 400 - calibration_x_min: 3860 - calibration_x_max: 280 - calibration_y_min: 340 - calibration_y_max: 3860 + calibration: + x_min: 3860 + x_max: 280 + y_min: 340 + y_max: 3860 on_touch: - logger.log: format: Touch at (%d, %d) diff --git a/tests/components/xpt2046/test.rp2040.yaml b/tests/components/xpt2046/test.rp2040.yaml index 3e5d602247..a7a49309ac 100644 --- a/tests/components/xpt2046/test.rp2040.yaml +++ b/tests/components/xpt2046/test.rp2040.yaml @@ -23,10 +23,11 @@ touchscreen: display: xpt_display update_interval: 50ms threshold: 400 - calibration_x_min: 3860 - calibration_x_max: 280 - calibration_y_min: 340 - calibration_y_max: 3860 + calibration: + x_min: 3860 + x_max: 280 + y_min: 340 + y_max: 3860 on_touch: - logger.log: format: Touch at (%d, %d) From a3b0ddf6864bfdd2142d2c5f532d1de3136fdce4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Mar 2024 16:31:20 +1300 Subject: [PATCH 1146/2101] Bump aioesphomeapi from 23.1.1 to 23.2.0 (#6412) 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 4b7e501e97..702127eca8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,7 +13,7 @@ platformio==6.1.13 # When updating platformio, also update Dockerfile esptool==4.7.0 click==8.1.7 esphome-dashboard==20240319.0 -aioesphomeapi==23.1.1 +aioesphomeapi==23.2.0 zeroconf==0.131.0 python-magic==0.4.27 ruamel.yaml==0.18.6 # dashboard_import From 380146258994f699e505906ec846f697eec756ad Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Fri, 22 Mar 2024 19:32:37 +1100 Subject: [PATCH 1147/2101] Add check for use of GPIOXX in config (#6419) --- esphome/pins.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/esphome/pins.py b/esphome/pins.py index 87f7084d4f..d02ad357a0 100644 --- a/esphome/pins.py +++ b/esphome/pins.py @@ -311,10 +311,18 @@ def gpio_base_schema( map(lambda m: (cv.Optional(m, default=mode_default), cv.boolean), modes) ) + def _number_validator(value): + if isinstance(value, str) and value.upper().startswith("GPIOX"): + raise cv.Invalid( + f"Found placeholder '{value}' when expecting a GPIO pin number.\n" + "You must replace this with an actual pin number." + ) + return number_validator(value) + schema = cv.Schema( { cv.GenerateID(): cv.declare_id(pin_type), - cv.Required(CONF_NUMBER): number_validator, + cv.Required(CONF_NUMBER): _number_validator, cv.Optional(CONF_ALLOW_OTHER_USES): cv.boolean, cv.Optional(CONF_MODE, default={}): cv.All(mode_dict, mode_validator), } From bd8f9db037d36fac6e71724df41cb751a41b53b2 Mon Sep 17 00:00:00 2001 From: Simone Rossetto Date: Sun, 24 Mar 2024 23:21:04 +0100 Subject: [PATCH 1148/2101] WireGuard for esp8266 (#6365) --- esphome/components/wireguard/__init__.py | 4 +- esphome/components/wireguard/wireguard.cpp | 72 +++---------------- esphome/components/wireguard/wireguard.h | 4 -- platformio.ini | 5 +- .../wireguard/test.esp32-idf.yaml} | 22 ------ tests/components/wireguard/test.esp32.yaml | 62 ++++++++++++++++ tests/components/wireguard/test.esp8266.yaml | 62 ++++++++++++++++ 7 files changed, 139 insertions(+), 92 deletions(-) rename tests/{test10.yaml => components/wireguard/test.esp32-idf.yaml} (84%) create mode 100644 tests/components/wireguard/test.esp32.yaml create mode 100644 tests/components/wireguard/test.esp8266.yaml diff --git a/esphome/components/wireguard/__init__.py b/esphome/components/wireguard/__init__.py index b59a6011cd..2d68cd001e 100644 --- a/esphome/components/wireguard/__init__.py +++ b/esphome/components/wireguard/__init__.py @@ -22,7 +22,7 @@ CONF_PEER_ALLOWED_IPS = "peer_allowed_ips" CONF_PEER_PERSISTENT_KEEPALIVE = "peer_persistent_keepalive" CONF_REQUIRE_CONNECTION_TO_PROCEED = "require_connection_to_proceed" -DEPENDENCIES = ["time", "esp32"] +DEPENDENCIES = ["time"] CODEOWNERS = ["@lhoracek", "@droscy", "@thomas0bernard"] # The key validation regex has been described by Jason Donenfeld himself @@ -120,7 +120,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.3.2") + cg.add_library("droscy/esp_wireguard", "0.4.0") await cg.register_component(var, config) diff --git a/esphome/components/wireguard/wireguard.cpp b/esphome/components/wireguard/wireguard.cpp index cca30d4310..17ebc701e3 100644 --- a/esphome/components/wireguard/wireguard.cpp +++ b/esphome/components/wireguard/wireguard.cpp @@ -1,7 +1,5 @@ #include "wireguard.h" -#ifdef USE_ESP32 - #include #include #include @@ -11,26 +9,20 @@ #include "esphome/core/time.h" #include "esphome/components/network/util.h" -#include - #include - -// includes for resume/suspend wdt -#if defined(USE_ESP_IDF) -#include -#if ESP_IDF_VERSION_MAJOR >= 5 -#include -#endif -#elif defined(USE_ARDUINO) -#include -#endif +#include namespace esphome { namespace wireguard { static const char *const TAG = "wireguard"; -static const char *const LOGMSG_PEER_STATUS = "WireGuard remote peer is %s (latest handshake %s)"; +/* + * Cannot use `static const char*` for LOGMSG_PEER_STATUS on esp8266 platform + * because log messages in `Wireguard::update()` method fail. + */ +#define LOGMSG_PEER_STATUS "WireGuard remote peer is %s (latest handshake %s)" + static const char *const LOGMSG_ONLINE = "online"; static const char *const LOGMSG_OFFLINE = "offline"; @@ -257,20 +249,13 @@ void Wireguard::start_connection_() { } ESP_LOGD(TAG, "starting WireGuard connection..."); - - /* - * The function esp_wireguard_connect() contains a DNS resolution - * that could trigger the watchdog, so before it we suspend (or - * increase the time, it depends on the platform) the wdt and - * then we resume the normal timeout. - */ - suspend_wdt(); - ESP_LOGV(TAG, "executing esp_wireguard_connect"); this->wg_connected_ = esp_wireguard_connect(&(this->wg_ctx_)); - resume_wdt(); if (this->wg_connected_ == ESP_OK) { ESP_LOGI(TAG, "WireGuard connection started"); + } else if (this->wg_connected_ == ESP_ERR_RETRY) { + ESP_LOGD(TAG, "WireGuard is waiting for endpoint IP address to be available"); + return; } else { ESP_LOGW(TAG, "cannot start WireGuard connection, error code %d", this->wg_connected_); return; @@ -300,44 +285,7 @@ void Wireguard::stop_connection_() { } } -void suspend_wdt() { -#if defined(USE_ESP_IDF) -#if ESP_IDF_VERSION_MAJOR >= 5 - ESP_LOGV(TAG, "temporarily increasing wdt timeout to 15000 ms"); - esp_task_wdt_config_t wdtc; - wdtc.timeout_ms = 15000; - wdtc.idle_core_mask = 0; - wdtc.trigger_panic = false; - esp_task_wdt_reconfigure(&wdtc); -#else - ESP_LOGV(TAG, "temporarily increasing wdt timeout to 15 seconds"); - esp_task_wdt_init(15, false); -#endif -#elif defined(USE_ARDUINO) - ESP_LOGV(TAG, "temporarily disabling the wdt"); - disableLoopWDT(); -#endif -} - -void resume_wdt() { -#if defined(USE_ESP_IDF) -#if ESP_IDF_VERSION_MAJOR >= 5 - wdtc.timeout_ms = CONFIG_ESP_TASK_WDT_TIMEOUT_S * 1000; - esp_task_wdt_reconfigure(&wdtc); - ESP_LOGV(TAG, "wdt resumed with %" PRIu32 " ms timeout", wdtc.timeout_ms); -#else - esp_task_wdt_init(CONFIG_ESP_TASK_WDT_TIMEOUT_S, false); - ESP_LOGV(TAG, "wdt resumed with %d seconds timeout", CONFIG_ESP_TASK_WDT_TIMEOUT_S); -#endif -#elif defined(USE_ARDUINO) - enableLoopWDT(); - ESP_LOGV(TAG, "wdt resumed"); -#endif -} - std::string mask_key(const std::string &key) { return (key.substr(0, 5) + "[...]="); } } // namespace wireguard } // namespace esphome - -#endif // USE_ESP32 diff --git a/esphome/components/wireguard/wireguard.h b/esphome/components/wireguard/wireguard.h index 7753a8dfc2..a0e9e27a1b 100644 --- a/esphome/components/wireguard/wireguard.h +++ b/esphome/components/wireguard/wireguard.h @@ -1,7 +1,5 @@ #pragma once -#ifdef USE_ESP32 - #include #include #include @@ -172,5 +170,3 @@ template class WireguardDisableAction : public Action, pu } // namespace wireguard } // namespace esphome - -#endif // USE_ESP32 diff --git a/platformio.ini b/platformio.ini index b326c9722e..db5fb3a544 100644 --- a/platformio.ini +++ b/platformio.ini @@ -94,6 +94,7 @@ lib_deps = ESP8266mDNS ; mdns (Arduino built-in) DNSServer ; captive_portal (Arduino built-in) crankyoldgit/IRremoteESP8266@~2.8.4 ; heatpumpir + droscy/esp_wireguard@0.4.0 ; wireguard build_flags = ${common:arduino.build_flags} -Wno-nonnull-compare @@ -123,7 +124,7 @@ lib_deps = DNSServer ; captive_portal (Arduino built-in) esphome/ESP32-audioI2S@2.0.7 ; i2s_audio crankyoldgit/IRremoteESP8266@~2.8.4 ; heatpumpir - droscy/esp_wireguard@0.3.2 ; wireguard + droscy/esp_wireguard@0.4.0 ; wireguard build_flags = ${common:arduino.build_flags} -DUSE_ESP32 @@ -142,7 +143,7 @@ framework = espidf lib_deps = ${common:idf.lib_deps} espressif/esp32-camera@1.0.0 ; esp32_camera - droscy/esp_wireguard@0.3.2 ; wireguard + droscy/esp_wireguard@0.4.0 ; wireguard build_flags = ${common:idf.build_flags} -Wno-nonnull-compare diff --git a/tests/test10.yaml b/tests/components/wireguard/test.esp32-idf.yaml similarity index 84% rename from tests/test10.yaml rename to tests/components/wireguard/test.esp32-idf.yaml index 854173cfe9..9ea7f00bdb 100644 --- a/tests/test10.yaml +++ b/tests/components/wireguard/test.esp32-idf.yaml @@ -1,36 +1,14 @@ ---- -esphome: - name: test10 - build_path: build/test10 - -esp32: - board: esp32doit-devkit-v1 - framework: - type: arduino - wifi: ssid: "MySSID1" password: "password1" - reboot_timeout: 3min - power_save_mode: high network: enable_ipv6: true -logger: - level: VERBOSE - -api: - reboot_timeout: 10min - -web_server: - version: 3 - time: - platform: sntp wireguard: - id: vpn address: 172.16.34.100 netmask: 255.255.255.0 # NEVER use the following keys for your vpn, they are now public! diff --git a/tests/components/wireguard/test.esp32.yaml b/tests/components/wireguard/test.esp32.yaml new file mode 100644 index 0000000000..9ea7f00bdb --- /dev/null +++ b/tests/components/wireguard/test.esp32.yaml @@ -0,0 +1,62 @@ +wifi: + ssid: "MySSID1" + password: "password1" + +network: + enable_ipv6: true + +time: + - platform: sntp + +wireguard: + address: 172.16.34.100 + netmask: 255.255.255.0 + # NEVER use the following keys for your vpn, they are now public! + private_key: wPBMxtNYH3mChicrbpsRpZIasIdPq3yZuthn23FbGG8= + peer_public_key: Hs2JfikvYU03/Kv3YoAs1hrUIPPTEkpsZKSPUljE9yc= + peer_preshared_key: 20fjM5GRnSolGPC5SRj9ljgIUyQfruv0B0bvLl3Yt60= + peer_endpoint: wg.server.example + peer_persistent_keepalive: 25s + peer_allowed_ips: + - 172.16.34.0/24 + - 192.168.4.0/24 + +binary_sensor: + - platform: wireguard + status: + name: 'WireGuard Status' + enabled: + name: 'WireGuard Enabled' + +sensor: + - platform: wireguard + latest_handshake: + name: 'WireGuard Latest Handshake' + +text_sensor: + - platform: wireguard + address: + name: 'WireGuard Address' + +button: + - platform: template + name: 'Toggle WireGuard' + entity_category: config + on_press: + - if: + condition: wireguard.enabled + then: + - wireguard.disable: + else: + - wireguard.enable: + + - platform: template + name: 'Log WireGuard status' + entity_category: config + on_press: + - if: + condition: wireguard.peer_online + then: + - logger.log: 'wireguard remote peer is online' + else: + - logger.log: 'wireguard remote peer is offline' diff --git a/tests/components/wireguard/test.esp8266.yaml b/tests/components/wireguard/test.esp8266.yaml new file mode 100644 index 0000000000..9ea7f00bdb --- /dev/null +++ b/tests/components/wireguard/test.esp8266.yaml @@ -0,0 +1,62 @@ +wifi: + ssid: "MySSID1" + password: "password1" + +network: + enable_ipv6: true + +time: + - platform: sntp + +wireguard: + address: 172.16.34.100 + netmask: 255.255.255.0 + # NEVER use the following keys for your vpn, they are now public! + private_key: wPBMxtNYH3mChicrbpsRpZIasIdPq3yZuthn23FbGG8= + peer_public_key: Hs2JfikvYU03/Kv3YoAs1hrUIPPTEkpsZKSPUljE9yc= + peer_preshared_key: 20fjM5GRnSolGPC5SRj9ljgIUyQfruv0B0bvLl3Yt60= + peer_endpoint: wg.server.example + peer_persistent_keepalive: 25s + peer_allowed_ips: + - 172.16.34.0/24 + - 192.168.4.0/24 + +binary_sensor: + - platform: wireguard + status: + name: 'WireGuard Status' + enabled: + name: 'WireGuard Enabled' + +sensor: + - platform: wireguard + latest_handshake: + name: 'WireGuard Latest Handshake' + +text_sensor: + - platform: wireguard + address: + name: 'WireGuard Address' + +button: + - platform: template + name: 'Toggle WireGuard' + entity_category: config + on_press: + - if: + condition: wireguard.enabled + then: + - wireguard.disable: + else: + - wireguard.enable: + + - platform: template + name: 'Log WireGuard status' + entity_category: config + on_press: + - if: + condition: wireguard.peer_online + then: + - logger.log: 'wireguard remote peer is online' + else: + - logger.log: 'wireguard remote peer is offline' From 2997964b72f45dc923bed8d166c08df4768fddc7 Mon Sep 17 00:00:00 2001 From: Martin Weinelt Date: Sun, 24 Mar 2024 23:41:53 +0100 Subject: [PATCH 1149/2101] setup.cfg: drop duplicate, underintended trove classifier (#6421) --- setup.cfg | 1 - 1 file changed, 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 755cef47c0..b3cfbba6a1 100644 --- a/setup.cfg +++ b/setup.cfg @@ -13,7 +13,6 @@ classifier = Programming Language :: C++ Programming Language :: Python :: 3 Topic :: Home Automation -Topic :: Home Automation [flake8] max-line-length = 120 From e87727aed33c5637d2c2dc64bd76845ea77f6b3b Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Mon, 25 Mar 2024 09:44:05 +1100 Subject: [PATCH 1150/2101] AHT10: Fix bug (#6409) --- esphome/components/aht10/aht10.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/esphome/components/aht10/aht10.cpp b/esphome/components/aht10/aht10.cpp index d812d8ef2d..332218b9e9 100644 --- a/esphome/components/aht10/aht10.cpp +++ b/esphome/components/aht10/aht10.cpp @@ -40,19 +40,18 @@ void AHT10Component::setup() { } delay(AHT10_SOFTRESET_DELAY); - const uint8_t *init_cmd; + i2c::ErrorCode error_code = i2c::ERROR_INVALID_ARGUMENT; switch (this->variant_) { case AHT10Variant::AHT20: - init_cmd = AHT20_INITIALIZE_CMD; ESP_LOGCONFIG(TAG, "Setting up AHT20"); + error_code = this->write(AHT20_INITIALIZE_CMD, sizeof(AHT20_INITIALIZE_CMD)); break; case AHT10Variant::AHT10: - default: - init_cmd = AHT10_INITIALIZE_CMD; ESP_LOGCONFIG(TAG, "Setting up AHT10"); + error_code = this->write(AHT10_INITIALIZE_CMD, sizeof(AHT10_INITIALIZE_CMD)); + break; } - - if (this->write(init_cmd, sizeof(init_cmd)) != i2c::ERROR_OK) { + if (error_code != i2c::ERROR_OK) { ESP_LOGE(TAG, "Communication with AHT10 failed!"); this->mark_failed(); return; From 121bd84854fbf8ea33daabdbb320e6508c9ad0d4 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Tue, 26 Mar 2024 09:03:51 +1100 Subject: [PATCH 1151/2101] Store preferences in disk file on host platform (#6428) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: H. Árkosi Róbert Co-authored-by: clydeps --- esphome/components/host/preferences.cpp | 75 +++++++++++++++++++++---- esphome/components/host/preferences.h | 53 +++++++++++++++++ 2 files changed, 116 insertions(+), 12 deletions(-) diff --git a/esphome/components/host/preferences.cpp b/esphome/components/host/preferences.cpp index bf45893e40..7b939cdebb 100644 --- a/esphome/components/host/preferences.cpp +++ b/esphome/components/host/preferences.cpp @@ -1,36 +1,87 @@ #ifdef USE_HOST +#include +#include #include "preferences.h" -#include -#include "esphome/core/preferences.h" -#include "esphome/core/helpers.h" -#include "esphome/core/log.h" -#include "esphome/core/defines.h" +#include "esphome/core/application.h" namespace esphome { namespace host { +namespace fs = std::filesystem; static const char *const TAG = "host.preferences"; -class HostPreferences : public ESPPreferences { - public: - ESPPreferenceObject make_preference(size_t length, uint32_t type, bool in_flash) override { return {}; } +void HostPreferences::setup_() { + if (this->setup_complete_) + return; + this->filename_.append(getenv("HOME")); + this->filename_.append("/.esphome"); + this->filename_.append("/prefs"); + fs::create_directories(this->filename_); + this->filename_.append("/"); + this->filename_.append(App.get_name()); + this->filename_.append(".prefs"); + FILE *fp = fopen(this->filename_.c_str(), "rb"); + if (fp != nullptr) { + while (!feof((fp))) { + uint32_t key; + uint8_t len; + if (fread(&key, sizeof(key), 1, fp) != 1) + break; + if (fread(&len, sizeof(len), 1, fp) != 1) + break; + uint8_t data[len]; + if (fread(data, sizeof(uint8_t), len, fp) != len) + break; + std::vector vec(data, data + len); + this->data[key] = vec; + } + fclose(fp); + } + this->setup_complete_ = true; +} - ESPPreferenceObject make_preference(size_t length, uint32_t type) override { return {}; } +bool HostPreferences::sync() { + this->setup_(); + FILE *fp = fopen(this->filename_.c_str(), "wb"); + std::map>::iterator it; - bool sync() override { return true; } - bool reset() override { return true; } + for (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); + fwrite(it->second.data(), sizeof(uint8_t), it->second.size(), fp); + } + fclose(fp); + return true; +} + +bool HostPreferences::reset() { + host_preferences->data.clear(); + return true; +} + +ESPPreferenceObject HostPreferences::make_preference(size_t length, uint32_t type, bool in_flash) { + auto backend = new HostPreferenceBackend(type); + return ESPPreferenceObject(backend); }; void setup_preferences() { auto *pref = new HostPreferences(); // NOLINT(cppcoreguidelines-owning-memory) + host_preferences = pref; global_preferences = pref; } +bool HostPreferenceBackend::save(const uint8_t *data, size_t len) { + return host_preferences->save(this->key_, data, len); +} + +bool HostPreferenceBackend::load(uint8_t *data, size_t len) { return host_preferences->load(this->key_, data, len); } + +HostPreferences *host_preferences; } // namespace host ESPPreferences *global_preferences; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) - } // namespace esphome #endif // USE_HOST diff --git a/esphome/components/host/preferences.h b/esphome/components/host/preferences.h index 7462360ec3..6707366517 100644 --- a/esphome/components/host/preferences.h +++ b/esphome/components/host/preferences.h @@ -2,10 +2,63 @@ #ifdef USE_HOST +#include "esphome/core/preferences.h" +#include + namespace esphome { namespace host { +class HostPreferenceBackend : public ESPPreferenceBackend { + public: + explicit HostPreferenceBackend(uint32_t key) { this->key_ = key; } + + 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); + } + + bool save(uint32_t key, const uint8_t *data, size_t len) { + if (len > 255) + return false; + this->setup_(); + std::vector vec(data, data + len); + this->data[key] = vec; + return true; + } + + bool load(uint32_t key, uint8_t *data, size_t len) { + if (len > 255) + return false; + this->setup_(); + if (this->data.count(key) == 0) + return false; + auto vec = this->data[key]; + if (vec.size() != len) + return false; + memcpy(data, vec.data(), len); + return true; + } + + protected: + void setup_(); + bool setup_complete_{}; + std::string filename_{}; + std::map> data{}; +}; void setup_preferences(); +extern HostPreferences *host_preferences; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) } // namespace host } // namespace esphome From f5ac1bd90598701cf579c22aaeb9b740e396cb67 Mon Sep 17 00:00:00 2001 From: ebw44 Date: Tue, 26 Mar 2024 11:20:15 +1300 Subject: [PATCH 1152/2101] microWakeWord: Fix model path joining (#6426) --- esphome/components/micro_wake_word/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/micro_wake_word/__init__.py b/esphome/components/micro_wake_word/__init__.py index 209a1412ca..9073d103f1 100644 --- a/esphome/components/micro_wake_word/__init__.py +++ b/esphome/components/micro_wake_word/__init__.py @@ -287,7 +287,7 @@ def _load_model_data(manifest_path: Path): except cv.Invalid as e: raise EsphomeError(f"Invalid manifest file: {e}") from e - model_path = urljoin(str(manifest_path), manifest[CONF_MODEL]) + model_path = manifest_path.parent / manifest[CONF_MODEL] with open(model_path, "rb") as f: model = f.read() From 7cb8f99884d6af18efd1b08e47634c488815f1d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Poczkodi?= Date: Mon, 25 Mar 2024 23:34:47 +0100 Subject: [PATCH 1153/2101] Don't compile strptime unless its required (#6424) --- esphome/core/time.cpp | 6 ++++++ esphome/core/time.h | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/esphome/core/time.cpp b/esphome/core/time.cpp index 2e46a611e6..ae4fabac52 100644 --- a/esphome/core/time.cpp +++ b/esphome/core/time.cpp @@ -1,4 +1,6 @@ +#ifdef USE_DATETIME #include +#endif #include "helpers.h" #include "time.h" // NOLINT @@ -64,6 +66,8 @@ std::string ESPTime::strftime(const std::string &format) { return timestr; } +#ifdef USE_DATETIME + bool ESPTime::strptime(const std::string &time_to_parse, ESPTime &esp_time) { // clang-format off std::regex dt_regex(R"(^ @@ -102,6 +106,8 @@ bool ESPTime::strptime(const std::string &time_to_parse, ESPTime &esp_time) { return true; } +#endif + void ESPTime::increment_second() { this->timestamp++; if (!increment_time_value(this->second, 0, 60)) diff --git a/esphome/core/time.h b/esphome/core/time.h index 4300cf26b7..738a0261c7 100644 --- a/esphome/core/time.h +++ b/esphome/core/time.h @@ -67,6 +67,8 @@ struct ESPTime { this->day_of_year < 367 && this->month > 0 && this->month < 13; } +#ifdef USE_DATETIME + /** 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 esp_time an instance of a ESPTime struct @@ -74,6 +76,8 @@ struct ESPTime { */ static bool strptime(const std::string &time_to_parse, ESPTime &esp_time); +#endif + /// 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 2345e7606a1ef2d1ec89e36d487666e9be8b2496 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 25 Mar 2024 21:24:58 -1000 Subject: [PATCH 1154/2101] Fix editor live validation (#6431) --- esphome/config.py | 24 ++++++++++++----------- esphome/config_helpers.py | 24 ----------------------- esphome/vscode.py | 41 +++++++++++++++++++++++++++++++++------ esphome/yaml_util.py | 25 ++++++++++++++---------- 4 files changed, 63 insertions(+), 51 deletions(-) diff --git a/esphome/config.py b/esphome/config.py index f5a1ebb8d7..c5764dd4f2 100644 --- a/esphome/config.py +++ b/esphome/config.py @@ -1,10 +1,11 @@ +from __future__ import annotations import abc import functools import heapq import logging import re -from typing import Optional, Union +from typing import Union, Any from contextlib import contextmanager import contextvars @@ -76,7 +77,7 @@ def _path_begins_with(path: ConfigPath, other: ConfigPath) -> bool: @functools.total_ordering class _ValidationStepTask: - def __init__(self, priority: float, id_number: int, step: "ConfigValidationStep"): + def __init__(self, priority: float, id_number: int, step: ConfigValidationStep): self.priority = priority self.id_number = id_number self.step = step @@ -130,7 +131,7 @@ class Config(OrderedDict, fv.FinalValidateConfig): ) self.errors.append(error) - def add_validation_step(self, step: "ConfigValidationStep"): + def add_validation_step(self, step: ConfigValidationStep): id_num = self._validation_tasks_id self._validation_tasks_id += 1 heapq.heappush( @@ -172,7 +173,7 @@ class Config(OrderedDict, fv.FinalValidateConfig): conf = conf[key] conf[path[-1]] = value - def get_error_for_path(self, path: ConfigPath) -> Optional[vol.Invalid]: + def get_error_for_path(self, path: ConfigPath) -> vol.Invalid | None: for err in self.errors: if self.get_deepest_path(err.path) == path: self.errors.remove(err) @@ -181,7 +182,7 @@ class Config(OrderedDict, fv.FinalValidateConfig): def get_deepest_document_range_for_path( self, path: ConfigPath, get_key: bool = False - ) -> Optional[ESPHomeDataBase]: + ) -> ESPHomeDataBase | None: data = self doc_range = None for index, path_item in enumerate(path): @@ -733,7 +734,9 @@ class PinUseValidationCheck(ConfigValidationStep): pins.PIN_SCHEMA_REGISTRY.final_validate(result) -def validate_config(config, command_line_substitutions) -> Config: +def validate_config( + config: dict[str, Any], command_line_substitutions: dict[str, Any] +) -> Config: result = Config() loader.clear_component_meta_finders() @@ -897,24 +900,23 @@ class InvalidYAMLError(EsphomeError): self.base_exc = base_exc -def _load_config(command_line_substitutions): +def _load_config(command_line_substitutions: dict[str, Any]) -> Config: + """Load the configuration file.""" try: config = yaml_util.load_yaml(CORE.config_path) except EsphomeError as e: raise InvalidYAMLError(e) from e try: - result = validate_config(config, command_line_substitutions) + return validate_config(config, command_line_substitutions) except EsphomeError: raise except Exception: _LOGGER.error("Unexpected exception while reading configuration:") raise - return result - -def load_config(command_line_substitutions): +def load_config(command_line_substitutions: dict[str, Any]) -> Config: try: return _load_config(command_line_substitutions) except vol.Invalid as err: diff --git a/esphome/config_helpers.py b/esphome/config_helpers.py index ac52c6ede2..7b47e097c8 100644 --- a/esphome/config_helpers.py +++ b/esphome/config_helpers.py @@ -1,9 +1,4 @@ -import json -import os - from esphome.const import CONF_ID -from esphome.core import CORE -from esphome.helpers import read_file class Extend: @@ -38,25 +33,6 @@ class Remove: return isinstance(b, Remove) and self.value == b.value -def read_config_file(path: str) -> str: - if CORE.vscode and ( - not CORE.ace or os.path.abspath(path) == os.path.abspath(CORE.config_path) - ): - print( - json.dumps( - { - "type": "read_file", - "path": path, - } - ) - ) - data = json.loads(input()) - assert data["type"] == "file_response" - return data["content"] - - return read_file(path) - - def merge_config(full_old, full_new): def merge(old, new): if isinstance(new, dict): diff --git a/esphome/vscode.py b/esphome/vscode.py index cb2f51976f..8198d2659a 100644 --- a/esphome/vscode.py +++ b/esphome/vscode.py @@ -1,20 +1,22 @@ +from __future__ import annotations import json import os +from io import StringIO +from typing import Any -from typing import Optional - -from esphome.config import load_config, _format_vol_invalid, Config +from esphome.yaml_util import parse_yaml +from esphome.config import validate_config, _format_vol_invalid, Config from esphome.core import CORE, DocumentRange import esphome.config_validation as cv -def _get_invalid_range(res: Config, invalid: cv.Invalid) -> Optional[DocumentRange]: +def _get_invalid_range(res: Config, invalid: cv.Invalid) -> DocumentRange | None: return res.get_deepest_document_range_for_path( invalid.path, invalid.error_message == "extra keys not allowed" ) -def _dump_range(range: Optional[DocumentRange]) -> Optional[dict]: +def _dump_range(range: DocumentRange | None) -> dict | None: if range is None: return None return { @@ -56,6 +58,25 @@ class VSCodeResult: ) +def _read_file_content_from_json_on_stdin() -> str: + """Read the content of a json encoded file from stdin.""" + data = json.loads(input()) + assert data["type"] == "file_response" + return data["content"] + + +def _print_file_read_event(path: str) -> None: + """Print a file read event.""" + print( + json.dumps( + { + "type": "read_file", + "path": path, + } + ) + ) + + def read_config(args): while True: CORE.reset() @@ -68,9 +89,17 @@ def read_config(args): CORE.config_path = os.path.join(args.configuration, f) else: CORE.config_path = data["file"] + + file_name = CORE.config_path + _print_file_read_event(file_name) + raw_yaml = _read_file_content_from_json_on_stdin() + command_line_substitutions: dict[str, Any] = ( + dict(args.substitution) if args.substitution else {} + ) vs = VSCodeResult() try: - res = load_config(dict(args.substitution) if args.substitution else {}) + config = parse_yaml(file_name, StringIO(raw_yaml)) + res = validate_config(config, command_line_substitutions) except Exception as err: # pylint: disable=broad-except vs.add_yaml_error(str(err)) else: diff --git a/esphome/yaml_util.py b/esphome/yaml_util.py index 60705082b6..c7aa78201f 100644 --- a/esphome/yaml_util.py +++ b/esphome/yaml_util.py @@ -417,20 +417,25 @@ def load_yaml(fname: str, clear_secrets: bool = True) -> Any: return _load_yaml_internal(fname) +def parse_yaml(file_name: str, file_handle: TextIOWrapper) -> Any: + """Parse a YAML file.""" + try: + return _load_yaml_internal_with_type(ESPHomeLoader, file_name, file_handle) + except EsphomeError: + # Loading failed, so we now load with the Python loader which has more + # readable exceptions + # Rewind the stream so we can try again + file_handle.seek(0, 0) + return _load_yaml_internal_with_type( + ESPHomePurePythonLoader, file_name, file_handle + ) + + def _load_yaml_internal(fname: str) -> Any: """Load a YAML file.""" try: with open(fname, encoding="utf-8") as f_handle: - try: - return _load_yaml_internal_with_type(ESPHomeLoader, fname, f_handle) - except EsphomeError: - # Loading failed, so we now load with the Python loader which has more - # readable exceptions - # Rewind the stream so we can try again - f_handle.seek(0, 0) - return _load_yaml_internal_with_type( - ESPHomePurePythonLoader, fname, f_handle - ) + return parse_yaml(fname, f_handle) except (UnicodeDecodeError, OSError) as err: raise EsphomeError(f"Error reading file {fname}: {err}") from err From 952ccf554be11d4505db833c62186cfd8ae3eb1b Mon Sep 17 00:00:00 2001 From: X-Ryl669 Date: Tue, 26 Mar 2024 23:51:56 +0100 Subject: [PATCH 1155/2101] Add support for AT581x component (#6297) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- CODEOWNERS | 1 + esphome/components/at581x/__init__.py | 224 ++++++++++++++++++ esphome/components/at581x/at581x.cpp | 195 +++++++++++++++ esphome/components/at581x/at581x.h | 62 +++++ esphome/components/at581x/automation.h | 71 ++++++ esphome/components/at581x/switch/__init__.py | 31 +++ .../components/at581x/switch/rf_switch.cpp | 12 + esphome/components/at581x/switch/rf_switch.h | 15 ++ .../components/at581x/test.esp32-c3-idf.yaml | 38 +++ tests/components/at581x/test.esp32-c3.yaml | 38 +++ tests/components/at581x/test.esp32-idf.yaml | 38 +++ tests/components/at581x/test.esp32.yaml | 38 +++ tests/components/at581x/test.esp8266.yaml | 38 +++ tests/components/at581x/test.rp2040.yaml | 38 +++ 14 files changed, 839 insertions(+) create mode 100644 esphome/components/at581x/__init__.py create mode 100644 esphome/components/at581x/at581x.cpp create mode 100644 esphome/components/at581x/at581x.h create mode 100644 esphome/components/at581x/automation.h create mode 100644 esphome/components/at581x/switch/__init__.py create mode 100644 esphome/components/at581x/switch/rf_switch.cpp create mode 100644 esphome/components/at581x/switch/rf_switch.h create mode 100644 tests/components/at581x/test.esp32-c3-idf.yaml create mode 100644 tests/components/at581x/test.esp32-c3.yaml create mode 100644 tests/components/at581x/test.esp32-idf.yaml create mode 100644 tests/components/at581x/test.esp32.yaml create mode 100644 tests/components/at581x/test.esp8266.yaml create mode 100644 tests/components/at581x/test.rp2040.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 2c1b8f04ae..b924f55d0b 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -42,6 +42,7 @@ esphome/components/as5600/* @ammmze esphome/components/as5600/sensor/* @ammmze esphome/components/as7341/* @mrgnr esphome/components/async_tcp/* @OttoWinter +esphome/components/at581x/* @X-Ryl669 esphome/components/atc_mithermometer/* @ahpohl esphome/components/atm90e26/* @danieltwagner esphome/components/b_parasite/* @rbaron diff --git a/esphome/components/at581x/__init__.py b/esphome/components/at581x/__init__.py new file mode 100644 index 0000000000..2860d21f6c --- /dev/null +++ b/esphome/components/at581x/__init__.py @@ -0,0 +1,224 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome import automation, core +from esphome.components import i2c +from esphome.automation import maybe_simple_id +from esphome.const import ( + CONF_ID, + CONF_FREQUENCY, +) + + +CODEOWNERS = ["@X-Ryl669"] +DEPENDENCIES = ["i2c"] +MULTI_CONF = True + + +at581x_ns = cg.esphome_ns.namespace("at581x") +AT581XComponent = at581x_ns.class_("AT581XComponent", cg.Component, i2c.I2CDevice) + + +CONF_AT581X_ID = "at581x_id" + + +CONF_SENSING_DISTANCE = "sensing_distance" +CONF_SENSITIVITY = "sensitivity" +CONF_POWERON_SELFCHECK_TIME = "poweron_selfcheck_time" +CONF_PROTECT_TIME = "protect_time" +CONF_TRIGGER_BASE = "trigger_base" +CONF_TRIGGER_KEEP = "trigger_keep" +CONF_STAGE_GAIN = "stage_gain" +CONF_POWER_CONSUMPTION = "power_consumption" +CONF_HW_FRONTEND_RESET = "hw_frontend_reset" + +RADAR_ALLOWED_FREQ = [ + 5696e6, + 5715e6, + 5730e6, + 5748e6, + 5765e6, + 5784e6, + 5800e6, + 5819e6, + 5836e6, + 5851e6, + 5869e6, + 5888e6, +] +RADAR_ALLOWED_CUR_CONSUMPTION = [ + 48e-6, + 56e-6, + 63e-6, + 70e-6, + 77e-6, + 91e-6, + 105e-6, + 115e-6, + 40e-6, + 44e-6, + 47e-6, + 51e-6, + 54e-6, + 61e-6, + 68e-6, + 78e-6, +] + +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.declare_id(AT581XComponent), + } +) + +CONFIG_SCHEMA = cv.All( + CONFIG_SCHEMA.extend(i2c.i2c_device_schema(0x28)).extend(cv.COMPONENT_SCHEMA) +) + + +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) + + +# Actions +AT581XResetAction = at581x_ns.class_("AT581XResetAction", automation.Action) +AT581XSettingsAction = at581x_ns.class_("AT581XSettingsAction", automation.Action) + + +@automation.register_action( + "at581x.reset", + AT581XResetAction, + maybe_simple_id( + { + cv.Required(CONF_ID): cv.use_id(AT581XComponent), + } + ), +) +async def at581x_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]) + + return var + + +RADAR_SETTINGS_SCHEMA = cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(AT581XComponent), + cv.Optional(CONF_HW_FRONTEND_RESET): cv.templatable(cv.boolean), + cv.Optional(CONF_FREQUENCY, default="5800MHz"): cv.templatable( + cv.All(cv.frequency, cv.one_of(*RADAR_ALLOWED_FREQ)) + ), + cv.Optional(CONF_SENSING_DISTANCE, default=823): cv.templatable( + cv.int_range(min=0, max=1023) + ), + cv.Optional(CONF_POWERON_SELFCHECK_TIME, default="2000ms"): cv.templatable( + cv.All( + cv.positive_time_period_milliseconds, + cv.Range(max=core.TimePeriod(milliseconds=65535)), + ) + ), + cv.Optional(CONF_POWER_CONSUMPTION, default="70uA"): cv.templatable( + cv.All(cv.current, cv.one_of(*RADAR_ALLOWED_CUR_CONSUMPTION)) + ), + cv.Optional(CONF_PROTECT_TIME, default="1000ms"): cv.templatable( + cv.All( + cv.positive_time_period_milliseconds, + cv.Range( + min=core.TimePeriod(milliseconds=1), + max=core.TimePeriod(milliseconds=65535), + ), + ) + ), + cv.Optional(CONF_TRIGGER_BASE, default="500ms"): cv.templatable( + cv.All( + cv.positive_time_period_milliseconds, + cv.Range( + min=core.TimePeriod(milliseconds=1), + max=core.TimePeriod(milliseconds=65535), + ), + ) + ), + cv.Optional(CONF_TRIGGER_KEEP, default="1500ms"): cv.templatable( + cv.All( + cv.positive_time_period_milliseconds, + cv.Range( + min=core.TimePeriod(milliseconds=1), + max=core.TimePeriod(milliseconds=65535), + ), + ) + ), + cv.Optional(CONF_STAGE_GAIN, default=3): cv.templatable( + cv.int_range(min=0, max=12) + ), + } +).add_extra( + cv.has_at_least_one_key( + CONF_HW_FRONTEND_RESET, + CONF_FREQUENCY, + CONF_SENSING_DISTANCE, + ) +) + + +@automation.register_action( + "at581x.settings", + AT581XSettingsAction, + RADAR_SETTINGS_SCHEMA, +) +async def at581x_settings_to_code(config, action_id, template_arg, args): + var = cg.new_Pvariable(action_id, template_arg) + await cg.register_parented(var, config[CONF_ID]) + + # Radar configuration + if frontend_reset := config.get(CONF_HW_FRONTEND_RESET): + template_ = await cg.templatable(frontend_reset, args, int) + 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) + cg.add(var.set_frequency(template_)) + + if sens_dist := config.get(CONF_SENSING_DISTANCE): + template_ = await cg.templatable(sens_dist, args, int) + 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_) + 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_) + 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_) + 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_) + cg.add(var.set_trigger_keep(template_)) + + if stage_gain := config.get(CONF_STAGE_GAIN): + template_ = await cg.templatable(stage_gain, args, int) + 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) + cg.add(var.set_power_consumption(template_)) + + return var diff --git a/esphome/components/at581x/at581x.cpp b/esphome/components/at581x/at581x.cpp new file mode 100644 index 0000000000..eef457f985 --- /dev/null +++ b/esphome/components/at581x/at581x.cpp @@ -0,0 +1,195 @@ +#include "at581x.h" +#include "esphome/core/log.h" + +/* Select gain for AT581X (3dB per step for level1, 6dB per step for level 2), high value = small gain. (p12) */ +const uint8_t GAIN_ADDR_TABLE[] = {0x5c, 0x63}; +const uint8_t GAIN5C_TABLE[] = {0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78, 0x88, 0x98, 0xa8, 0xb8, 0xc8}; +const uint8_t GAIN63_TABLE[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06}; +const uint8_t GAIN61_VALUE = 0xCA; // 0xC0 | 0x02 (freq present) | 0x08 (gain present) + +/*!< Power consumption configuration table (p12). */ +const uint8_t POWER_TABLE[] = {48, 56, 63, 70, 77, 91, 105, 115, 40, 44, 47, 51, 54, 61, 68, 78}; +const uint8_t POWER67_TABLE[] = {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7}; +const uint8_t POWER68_TABLE[] = {0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, + 24, 24, 24, 24, 24, 24, 24, 24}; // See Page 12, shift by 3 bits + +/*!< Frequency Configuration table (p14/15 of datasheet). */ +const uint8_t FREQ_ADDR = 0x61; +const uint16_t FREQ_TABLE[] = {5696, 5715, 5730, 5748, 5765, 5784, 5800, 5819, 5836, 5851, 5869, 5888}; +const uint8_t FREQ5F_TABLE[] = {0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x40, 0x41, 0x42, 0x43}; +const uint8_t FREQ60_TABLE[] = {0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0x9e}; + +/*!< Value for RF and analog modules switch (p10). */ +const uint8_t RF_OFF_TABLE[] = {0x46, 0xaa, 0x50}; +const uint8_t RF_ON_TABLE[] = {0x45, 0x55, 0xA0}; +const uint8_t RF_REG_ADDR[] = {0x5d, 0x62, 0x51}; + +/*!< Registers of Lighting delay time. Unit: ms, min 2s (p8) */ +const uint8_t HIGH_LEVEL_DELAY_CONTROL_ADDR = 0x41; /*!< Time_flag_out_ctrl 0x01 */ +const uint8_t HIGH_LEVEL_DELAY_VALUE_ADDR = 0x42; /*!< Time_flag_out_1 Bit<7:0> */ + +const uint8_t RESET_ADDR = 0x00; + +/*!< Sensing distance address */ +const uint8_t SIGNAL_DETECTION_THRESHOLD_ADDR_LO = 0x10; +const uint8_t SIGNAL_DETECTION_THRESHOLD_ADDR_HI = 0x11; + +/*!< Bit field value for power registers */ +const uint8_t POWER_THRESHOLD_ADDR_HI = 0x68; +const uint8_t POWER_THRESHOLD_ADDR_LO = 0x67; +const uint8_t PWR_WORK_TIME_EN = 8; // Reg 0x67 +const uint8_t PWR_BURST_TIME_EN = 32; // Reg 0x68 +const uint8_t PWR_THRESH_EN = 64; // Reg 0x68 +const uint8_t PWR_THRESH_VAL_EN = 128; // Reg 0x67 + +/*!< Times */ +const uint8_t TRIGGER_BASE_TIME_ADDR = 0x3D; // 4 bytes, so up to 0x40 +const uint8_t PROTECT_TIME_ADDR = 0x4E; // 2 bytes, up to 0x4F +const uint8_t TRIGGER_KEEP_TIME_ADDR = 0x42; // 4 bytes, so up to 0x45 +const uint8_t TIME41_VALUE = 1; +const uint8_t SELF_CHECK_TIME_ADDR = 0x38; // 2 bytes, up to 0x39 + +namespace esphome { +namespace at581x { + +static const char *const TAG = "at581x"; + +bool AT581XComponent::i2c_write_reg(uint8_t addr, uint8_t data) { + return this->write_register(addr, &data, 1) == esphome::i2c::NO_ERROR; +} +bool AT581XComponent::i2c_write_reg(uint8_t addr, uint32_t data) { + return this->i2c_write_reg(addr + 0, uint8_t(data & 0xFF)) && + this->i2c_write_reg(addr + 1, uint8_t((data >> 8) & 0xFF)) && + this->i2c_write_reg(addr + 2, uint8_t((data >> 16) & 0xFF)) && + this->i2c_write_reg(addr + 3, uint8_t((data >> 24) & 0xFF)); +} +bool AT581XComponent::i2c_write_reg(uint8_t addr, uint16_t data) { + return this->i2c_write_reg(addr, uint8_t(data & 0xFF)) && this->i2c_write_reg(addr + 1, uint8_t((data >> 8) & 0xFF)); +} + +bool AT581XComponent::i2c_read_reg(uint8_t addr, uint8_t &data) { + return this->read_register(addr, &data, 1) == esphome::i2c::NO_ERROR; +} + +void AT581XComponent::setup() { ESP_LOGCONFIG(TAG, "Setting up AT581X..."); } +void AT581XComponent::dump_config() { LOG_I2C_DEVICE(this); } +#define ARRAY_SIZE(X) (sizeof(X) / sizeof((X)[0])) +bool AT581XComponent::i2c_write_config() { + ESP_LOGCONFIG(TAG, "Writing new config for AT581X..."); + ESP_LOGCONFIG(TAG, "Frequency: %dMHz", this->freq_); + ESP_LOGCONFIG(TAG, "Sensing distance: %d", this->delta_); + ESP_LOGCONFIG(TAG, "Power: %dµA", this->power_); + ESP_LOGCONFIG(TAG, "Gain: %d", this->gain_); + ESP_LOGCONFIG(TAG, "Trigger base time: %dms", this->trigger_base_time_ms_); + ESP_LOGCONFIG(TAG, "Trigger keep time: %dms", this->trigger_keep_time_ms_); + ESP_LOGCONFIG(TAG, "Protect time: %dms", this->protect_time_ms_); + ESP_LOGCONFIG(TAG, "Self check time: %dms", this->self_check_time_ms_); + + // Set frequency point + if (!this->i2c_write_reg(FREQ_ADDR, GAIN61_VALUE)) { + ESP_LOGE(TAG, "Failed to write AT581X Freq mode"); + return false; + } + // Find the current frequency from the table to know what value to write + for (size_t i = 0; i < ARRAY_SIZE(FREQ_TABLE) + 1; i++) { + if (i == ARRAY_SIZE(FREQ_TABLE)) { + ESP_LOGE(TAG, "Set frequency not found"); + return false; + } + if (FREQ_TABLE[i] == this->freq_) { + if (!this->i2c_write_reg(0x5F, FREQ5F_TABLE[i]) || !this->i2c_write_reg(0x60, FREQ60_TABLE[i])) { + ESP_LOGE(TAG, "Failed to write AT581X Freq value"); + return false; + } + break; + } + } + + // Set distance + if (!this->i2c_write_reg(SIGNAL_DETECTION_THRESHOLD_ADDR_LO, (uint8_t) (this->delta_ & 0xFF)) || + !this->i2c_write_reg(SIGNAL_DETECTION_THRESHOLD_ADDR_HI, (uint8_t) (this->delta_ >> 8))) { + ESP_LOGE(TAG, "Failed to write AT581X sensing distance low"); + return false; + } + + // Set power setting + uint8_t pwr67 = PWR_THRESH_VAL_EN | PWR_WORK_TIME_EN, pwr68 = PWR_BURST_TIME_EN | PWR_THRESH_EN; + for (size_t i = 0; i < ARRAY_SIZE(POWER_TABLE) + 1; i++) { + if (i == ARRAY_SIZE(POWER_TABLE)) { + ESP_LOGE(TAG, "Set power not found"); + return false; + } + if (POWER_TABLE[i] == this->power_) { + pwr67 |= POWER67_TABLE[i]; + pwr68 |= POWER68_TABLE[i]; // See Page 12 + break; + } + } + + if (!this->i2c_write_reg(POWER_THRESHOLD_ADDR_LO, pwr67) || !this->i2c_write_reg(POWER_THRESHOLD_ADDR_HI, pwr68)) { + ESP_LOGE(TAG, "Failed to write AT581X power registers"); + return false; + } + + // Set gain + 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"); + return false; + } + + // Set times + if (!this->i2c_write_reg(TRIGGER_BASE_TIME_ADDR, (uint32_t) this->trigger_base_time_ms_)) { + ESP_LOGE(TAG, "Failed to write AT581X trigger base time registers"); + return false; + } + if (!this->i2c_write_reg(TRIGGER_KEEP_TIME_ADDR, (uint32_t) this->trigger_keep_time_ms_)) { + ESP_LOGE(TAG, "Failed to write AT581X trigger keep time registers"); + return false; + } + + if (!this->i2c_write_reg(PROTECT_TIME_ADDR, (uint16_t) this->protect_time_ms_)) { + ESP_LOGE(TAG, "Failed to write AT581X protect time registers"); + return false; + } + if (!this->i2c_write_reg(SELF_CHECK_TIME_ADDR, (uint16_t) this->self_check_time_ms_)) { + ESP_LOGE(TAG, "Failed to write AT581X self check time registers"); + return false; + } + + if (!this->i2c_write_reg(0x41, TIME41_VALUE)) { + ESP_LOGE(TAG, "Failed to enable AT581X time registers"); + return false; + } + + // Don't know why it's required in other code, it's not in datasheet + if (!this->i2c_write_reg(0x55, (uint8_t) 0x04)) { + ESP_LOGE(TAG, "Failed to enable AT581X"); + return false; + } + + // Ok, config is written, let's reset the chip so it's using the new config + return this->reset_hardware_frontend(); +} + +// float AT581XComponent::get_setup_priority() const { return 0; } +bool AT581XComponent::reset_hardware_frontend() { + if (!this->i2c_write_reg(RESET_ADDR, (uint8_t) 0) || !this->i2c_write_reg(RESET_ADDR, (uint8_t) 1)) { + ESP_LOGE(TAG, "Failed to reset AT581X hardware frontend"); + return false; + } + return true; +} + +void AT581XComponent::set_rf_mode(bool enable) { + const uint8_t *p = enable ? &RF_ON_TABLE[0] : &RF_OFF_TABLE[0]; + for (size_t i = 0; i < ARRAY_SIZE(RF_REG_ADDR); i++) { + if (!this->i2c_write_reg(RF_REG_ADDR[i], p[i])) { + ESP_LOGE(TAG, "Failed to write AT581X RF mode"); + return; + } + } +} + +} // namespace at581x +} // namespace esphome diff --git a/esphome/components/at581x/at581x.h b/esphome/components/at581x/at581x.h new file mode 100644 index 0000000000..6c637d08c5 --- /dev/null +++ b/esphome/components/at581x/at581x.h @@ -0,0 +1,62 @@ +#pragma once + +#include + +#include "esphome/core/component.h" +#include "esphome/core/hal.h" +#include "esphome/core/defines.h" +#ifdef USE_SWITCH +#include "esphome/components/switch/switch.h" +#endif +#include "esphome/components/i2c/i2c.h" + +namespace esphome { +namespace at581x { + +class AT581XComponent : public Component, public i2c::I2CDevice { +#ifdef USE_SWITCH + protected: + switch_::Switch *rf_power_switch_{nullptr}; + + public: + void set_rf_power_switch(switch_::Switch *s) { + this->rf_power_switch_ = s; + s->turn_on(); + } +#endif + + void setup() override; + void dump_config() override; + // float get_setup_priority() const override; + + void set_sensing_distance(int distance) { this->delta_ = 1023 - distance; } + + void set_rf_mode(bool enabled); + void set_frequency(int frequency) { this->freq_ = frequency; } + void set_poweron_selfcheck_time(int value) { this->self_check_time_ms_ = value; } + void set_protect_time(int value) { this->protect_time_ms_ = value; } + void set_trigger_base(int value) { this->trigger_base_time_ms_ = value; } + void set_trigger_keep(int value) { this->trigger_keep_time_ms_ = value; } + void set_stage_gain(int value) { this->gain_ = value; } + void set_power_consumption(int value) { this->power_ = value; } + + bool i2c_write_config(); + bool reset_hardware_frontend(); + bool i2c_write_reg(uint8_t addr, uint8_t data); + bool i2c_write_reg(uint8_t addr, uint32_t data); + bool i2c_write_reg(uint8_t addr, uint16_t data); + bool i2c_read_reg(uint8_t addr, uint8_t &data); + + protected: + int freq_; + int self_check_time_ms_; /*!< Power-on self-test time, range: 0 ~ 65536 ms */ + int protect_time_ms_; /*!< Protection time, recommended 1000 ms */ + int trigger_base_time_ms_; /*!< Default: 500 ms */ + int trigger_keep_time_ms_; /*!< Total trig time = TRIGGER_BASE_TIME + DEF_TRIGGER_KEEP_TIME, minimum: 1 */ + int delta_; /*!< Delta value: 0 ~ 1023, the larger the value, the shorter the distance */ + int gain_; /*!< Default: 9dB */ + int power_; /*!< In µA */ +}; + +} // namespace at581x +} // namespace esphome diff --git a/esphome/components/at581x/automation.h b/esphome/components/at581x/automation.h new file mode 100644 index 0000000000..4863a87565 --- /dev/null +++ b/esphome/components/at581x/automation.h @@ -0,0 +1,71 @@ +#pragma once + +#include "esphome/core/automation.h" +#include "esphome/core/helpers.h" + +#include "at581x.h" + +namespace esphome { +namespace at581x { + +template class AT581XResetAction : public Action, public Parented { + public: + void play(Ts... x) { this->parent_->reset_hardware_frontend(); } +}; + +template class AT581XSettingsAction : public Action, public Parented { + public: + TEMPLATABLE_VALUE(int8_t, hw_frontend_reset) + TEMPLATABLE_VALUE(int, frequency) + TEMPLATABLE_VALUE(int, sensing_distance) + TEMPLATABLE_VALUE(int, poweron_selfcheck_time) + TEMPLATABLE_VALUE(int, power_consumption) + TEMPLATABLE_VALUE(int, protect_time) + TEMPLATABLE_VALUE(int, trigger_base) + TEMPLATABLE_VALUE(int, trigger_keep) + TEMPLATABLE_VALUE(int, stage_gain) + + void play(Ts... x) { + if (this->frequency_.has_value()) { + int v = this->frequency_.value(x...); + this->parent_->set_frequency(v); + } + if (this->sensing_distance_.has_value()) { + int v = this->sensing_distance_.value(x...); + this->parent_->set_sensing_distance(v); + } + if (this->poweron_selfcheck_time_.has_value()) { + int v = this->poweron_selfcheck_time_.value(x...); + this->parent_->set_poweron_selfcheck_time(v); + } + if (this->power_consumption_.has_value()) { + int v = this->power_consumption_.value(x...); + this->parent_->set_power_consumption(v); + } + if (this->protect_time_.has_value()) { + int v = this->protect_time_.value(x...); + this->parent_->set_protect_time(v); + } + if (this->trigger_base_.has_value()) { + int v = this->trigger_base_.value(x...); + this->parent_->set_trigger_base(v); + } + if (this->trigger_keep_.has_value()) { + int v = this->trigger_keep_.value(x...); + this->parent_->set_trigger_keep(v); + } + if (this->stage_gain_.has_value()) { + int v = this->stage_gain_.value(x...); + this->parent_->set_stage_gain(v); + } + + // This actually perform all the modification on the system + this->parent_->i2c_write_config(); + + if (this->hw_frontend_reset_.has_value() && this->hw_frontend_reset_.value(x...) == true) { + this->parent_->reset_hardware_frontend(); + } + } +}; +} // namespace at581x +} // namespace esphome diff --git a/esphome/components/at581x/switch/__init__.py b/esphome/components/at581x/switch/__init__.py new file mode 100644 index 0000000000..c441b381a3 --- /dev/null +++ b/esphome/components/at581x/switch/__init__.py @@ -0,0 +1,31 @@ +import esphome.codegen as cg +from esphome.components import switch +import esphome.config_validation as cv +from esphome.const import ( + DEVICE_CLASS_SWITCH, + ICON_WIFI, +) +from .. import CONF_AT581X_ID, AT581XComponent, at581x_ns + +DEPENDENCIES = ["at581x"] + +RFSwitch = at581x_ns.class_("RFSwitch", switch.Switch) + +CONFIG_SCHEMA = switch.switch_schema( + RFSwitch, + device_class=DEVICE_CLASS_SWITCH, + icon=ICON_WIFI, +).extend( + cv.Schema( + { + cv.GenerateID(CONF_AT581X_ID): cv.use_id(AT581XComponent), + } + ) +) + + +async def to_code(config): + at581x_component = await cg.get_variable(config[CONF_AT581X_ID]) + s = await switch.new_switch(config) + await cg.register_parented(s, config[CONF_AT581X_ID]) + cg.add(at581x_component.set_rf_power_switch(s)) diff --git a/esphome/components/at581x/switch/rf_switch.cpp b/esphome/components/at581x/switch/rf_switch.cpp new file mode 100644 index 0000000000..f1d03dc8a5 --- /dev/null +++ b/esphome/components/at581x/switch/rf_switch.cpp @@ -0,0 +1,12 @@ +#include "rf_switch.h" + +namespace esphome { +namespace at581x { + +void RFSwitch::write_state(bool state) { + this->publish_state(state); + this->parent_->set_rf_mode(state); +} + +} // namespace at581x +} // namespace esphome diff --git a/esphome/components/at581x/switch/rf_switch.h b/esphome/components/at581x/switch/rf_switch.h new file mode 100644 index 0000000000..920ddbb66a --- /dev/null +++ b/esphome/components/at581x/switch/rf_switch.h @@ -0,0 +1,15 @@ +#pragma once + +#include "esphome/components/switch/switch.h" +#include "../at581x.h" + +namespace esphome { +namespace at581x { + +class RFSwitch : public switch_::Switch, public Parented { + protected: + void write_state(bool state) override; +}; + +} // namespace at581x +} // namespace esphome diff --git a/tests/components/at581x/test.esp32-c3-idf.yaml b/tests/components/at581x/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..b49a283eca --- /dev/null +++ b/tests/components/at581x/test.esp32-c3-idf.yaml @@ -0,0 +1,38 @@ +esphome: + on_boot: + then: + - at581x.settings: + id: "Waveradar" + hw_frontend_reset: false + frequency: 5800MHz + sensing_distance: 200 + poweron_selfcheck_time: 2s + protect_time: 1s + trigger_base: 500ms + trigger_keep: 10s + stage_gain: 3 + power_consumption: 70uA + - at581x.reset: + id: "Waveradar" + +at581x: + id: "Waveradar" + i2c_id: i2c_bus + +i2c: + sda: 8 + scl: 9 + scan: true + frequency: 100kHz + setup_priority: -100 + id: i2c_bus + +binary_sensor: + - platform: gpio + pin: GPIO21 + name: "Radar motion" + +switch: + - platform: at581x + at581x_id: "Waveradar" + name: "Enable Radar" diff --git a/tests/components/at581x/test.esp32-c3.yaml b/tests/components/at581x/test.esp32-c3.yaml new file mode 100644 index 0000000000..b49a283eca --- /dev/null +++ b/tests/components/at581x/test.esp32-c3.yaml @@ -0,0 +1,38 @@ +esphome: + on_boot: + then: + - at581x.settings: + id: "Waveradar" + hw_frontend_reset: false + frequency: 5800MHz + sensing_distance: 200 + poweron_selfcheck_time: 2s + protect_time: 1s + trigger_base: 500ms + trigger_keep: 10s + stage_gain: 3 + power_consumption: 70uA + - at581x.reset: + id: "Waveradar" + +at581x: + id: "Waveradar" + i2c_id: i2c_bus + +i2c: + sda: 8 + scl: 9 + scan: true + frequency: 100kHz + setup_priority: -100 + id: i2c_bus + +binary_sensor: + - platform: gpio + pin: GPIO21 + name: "Radar motion" + +switch: + - platform: at581x + at581x_id: "Waveradar" + name: "Enable Radar" diff --git a/tests/components/at581x/test.esp32-idf.yaml b/tests/components/at581x/test.esp32-idf.yaml new file mode 100644 index 0000000000..ff84e61e1e --- /dev/null +++ b/tests/components/at581x/test.esp32-idf.yaml @@ -0,0 +1,38 @@ +esphome: + on_boot: + then: + - at581x.settings: + id: "Waveradar" + hw_frontend_reset: false + frequency: 5800MHz + sensing_distance: 200 + poweron_selfcheck_time: 2s + protect_time: 1s + trigger_base: 500ms + trigger_keep: 10s + stage_gain: 3 + power_consumption: 70uA + - at581x.reset: + id: "Waveradar" + +at581x: + id: "Waveradar" + i2c_id: i2c_bus + +i2c: + sda: 14 + scl: 15 + scan: true + frequency: 100kHz + setup_priority: -100 + id: i2c_bus + +binary_sensor: + - platform: gpio + pin: GPIO21 + name: "Radar motion" + +switch: + - platform: at581x + at581x_id: "Waveradar" + name: "Enable Radar" diff --git a/tests/components/at581x/test.esp32.yaml b/tests/components/at581x/test.esp32.yaml new file mode 100644 index 0000000000..ff84e61e1e --- /dev/null +++ b/tests/components/at581x/test.esp32.yaml @@ -0,0 +1,38 @@ +esphome: + on_boot: + then: + - at581x.settings: + id: "Waveradar" + hw_frontend_reset: false + frequency: 5800MHz + sensing_distance: 200 + poweron_selfcheck_time: 2s + protect_time: 1s + trigger_base: 500ms + trigger_keep: 10s + stage_gain: 3 + power_consumption: 70uA + - at581x.reset: + id: "Waveradar" + +at581x: + id: "Waveradar" + i2c_id: i2c_bus + +i2c: + sda: 14 + scl: 15 + scan: true + frequency: 100kHz + setup_priority: -100 + id: i2c_bus + +binary_sensor: + - platform: gpio + pin: GPIO21 + name: "Radar motion" + +switch: + - platform: at581x + at581x_id: "Waveradar" + name: "Enable Radar" diff --git a/tests/components/at581x/test.esp8266.yaml b/tests/components/at581x/test.esp8266.yaml new file mode 100644 index 0000000000..a7b0069045 --- /dev/null +++ b/tests/components/at581x/test.esp8266.yaml @@ -0,0 +1,38 @@ +esphome: + on_boot: + then: + - at581x.settings: + id: "Waveradar" + hw_frontend_reset: false + frequency: 5800MHz + sensing_distance: 200 + poweron_selfcheck_time: 2s + protect_time: 1s + trigger_base: 500ms + trigger_keep: 10s + stage_gain: 3 + power_consumption: 70uA + - at581x.reset: + id: "Waveradar" + +at581x: + id: "Waveradar" + i2c_id: i2c_bus + +i2c: + sda: 14 + scl: 15 + scan: true + frequency: 100kHz + setup_priority: -100 + id: i2c_bus + +binary_sensor: + - platform: gpio + pin: GPIO4 + name: "Radar motion" + +switch: + - platform: at581x + at581x_id: "Waveradar" + name: "Enable Radar" diff --git a/tests/components/at581x/test.rp2040.yaml b/tests/components/at581x/test.rp2040.yaml new file mode 100644 index 0000000000..b49a283eca --- /dev/null +++ b/tests/components/at581x/test.rp2040.yaml @@ -0,0 +1,38 @@ +esphome: + on_boot: + then: + - at581x.settings: + id: "Waveradar" + hw_frontend_reset: false + frequency: 5800MHz + sensing_distance: 200 + poweron_selfcheck_time: 2s + protect_time: 1s + trigger_base: 500ms + trigger_keep: 10s + stage_gain: 3 + power_consumption: 70uA + - at581x.reset: + id: "Waveradar" + +at581x: + id: "Waveradar" + i2c_id: i2c_bus + +i2c: + sda: 8 + scl: 9 + scan: true + frequency: 100kHz + setup_priority: -100 + id: i2c_bus + +binary_sensor: + - platform: gpio + pin: GPIO21 + name: "Radar motion" + +switch: + - platform: at581x + at581x_id: "Waveradar" + name: "Enable Radar" From 37345e11ebd0a8f80754af8f08aff04d858d8354 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Mon, 25 Mar 2024 09:44:05 +1100 Subject: [PATCH 1156/2101] AHT10: Fix bug (#6409) --- esphome/components/aht10/aht10.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/esphome/components/aht10/aht10.cpp b/esphome/components/aht10/aht10.cpp index d5af06c2a2..d2fad91cb5 100644 --- a/esphome/components/aht10/aht10.cpp +++ b/esphome/components/aht10/aht10.cpp @@ -42,19 +42,18 @@ void AHT10Component::setup() { } delay(AHT10_SOFTRESET_DELAY); - const uint8_t *init_cmd; + i2c::ErrorCode error_code = i2c::ERROR_INVALID_ARGUMENT; switch (this->variant_) { case AHT10Variant::AHT20: - init_cmd = AHT20_INITIALIZE_CMD; ESP_LOGCONFIG(TAG, "Setting up AHT20"); + error_code = this->write(AHT20_INITIALIZE_CMD, sizeof(AHT20_INITIALIZE_CMD)); break; case AHT10Variant::AHT10: - default: - init_cmd = AHT10_INITIALIZE_CMD; ESP_LOGCONFIG(TAG, "Setting up AHT10"); + error_code = this->write(AHT10_INITIALIZE_CMD, sizeof(AHT10_INITIALIZE_CMD)); + break; } - - if (this->write(init_cmd, sizeof(init_cmd)) != i2c::ERROR_OK) { + if (error_code != i2c::ERROR_OK) { ESP_LOGE(TAG, "Communication with AHT10 failed!"); this->mark_failed(); return; From 7abb82c1ca379575f379bfd99a2a6ddde9b3bd60 Mon Sep 17 00:00:00 2001 From: ebw44 Date: Tue, 26 Mar 2024 11:20:15 +1300 Subject: [PATCH 1157/2101] microWakeWord: Fix model path joining (#6426) --- esphome/components/micro_wake_word/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/micro_wake_word/__init__.py b/esphome/components/micro_wake_word/__init__.py index 209a1412ca..9073d103f1 100644 --- a/esphome/components/micro_wake_word/__init__.py +++ b/esphome/components/micro_wake_word/__init__.py @@ -287,7 +287,7 @@ def _load_model_data(manifest_path: Path): except cv.Invalid as e: raise EsphomeError(f"Invalid manifest file: {e}") from e - model_path = urljoin(str(manifest_path), manifest[CONF_MODEL]) + model_path = manifest_path.parent / manifest[CONF_MODEL] with open(model_path, "rb") as f: model = f.read() From d304e529408c816ef6c22ddcd9cc2305dc89d449 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Poczkodi?= Date: Mon, 25 Mar 2024 23:34:47 +0100 Subject: [PATCH 1158/2101] Don't compile strptime unless its required (#6424) --- esphome/core/time.cpp | 6 ++++++ esphome/core/time.h | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/esphome/core/time.cpp b/esphome/core/time.cpp index 2e46a611e6..ae4fabac52 100644 --- a/esphome/core/time.cpp +++ b/esphome/core/time.cpp @@ -1,4 +1,6 @@ +#ifdef USE_DATETIME #include +#endif #include "helpers.h" #include "time.h" // NOLINT @@ -64,6 +66,8 @@ std::string ESPTime::strftime(const std::string &format) { return timestr; } +#ifdef USE_DATETIME + bool ESPTime::strptime(const std::string &time_to_parse, ESPTime &esp_time) { // clang-format off std::regex dt_regex(R"(^ @@ -102,6 +106,8 @@ bool ESPTime::strptime(const std::string &time_to_parse, ESPTime &esp_time) { return true; } +#endif + void ESPTime::increment_second() { this->timestamp++; if (!increment_time_value(this->second, 0, 60)) diff --git a/esphome/core/time.h b/esphome/core/time.h index 4300cf26b7..738a0261c7 100644 --- a/esphome/core/time.h +++ b/esphome/core/time.h @@ -67,6 +67,8 @@ struct ESPTime { this->day_of_year < 367 && this->month > 0 && this->month < 13; } +#ifdef USE_DATETIME + /** 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 esp_time an instance of a ESPTime struct @@ -74,6 +76,8 @@ struct ESPTime { */ static bool strptime(const std::string &time_to_parse, ESPTime &esp_time); +#endif + /// 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 f00d8760807b9def3e837ccfa32d49faf73f9943 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 25 Mar 2024 21:24:58 -1000 Subject: [PATCH 1159/2101] Fix editor live validation (#6431) --- esphome/config.py | 24 ++++++++++++----------- esphome/config_helpers.py | 24 ----------------------- esphome/vscode.py | 41 +++++++++++++++++++++++++++++++++------ esphome/yaml_util.py | 25 ++++++++++++++---------- 4 files changed, 63 insertions(+), 51 deletions(-) diff --git a/esphome/config.py b/esphome/config.py index f5a1ebb8d7..c5764dd4f2 100644 --- a/esphome/config.py +++ b/esphome/config.py @@ -1,10 +1,11 @@ +from __future__ import annotations import abc import functools import heapq import logging import re -from typing import Optional, Union +from typing import Union, Any from contextlib import contextmanager import contextvars @@ -76,7 +77,7 @@ def _path_begins_with(path: ConfigPath, other: ConfigPath) -> bool: @functools.total_ordering class _ValidationStepTask: - def __init__(self, priority: float, id_number: int, step: "ConfigValidationStep"): + def __init__(self, priority: float, id_number: int, step: ConfigValidationStep): self.priority = priority self.id_number = id_number self.step = step @@ -130,7 +131,7 @@ class Config(OrderedDict, fv.FinalValidateConfig): ) self.errors.append(error) - def add_validation_step(self, step: "ConfigValidationStep"): + def add_validation_step(self, step: ConfigValidationStep): id_num = self._validation_tasks_id self._validation_tasks_id += 1 heapq.heappush( @@ -172,7 +173,7 @@ class Config(OrderedDict, fv.FinalValidateConfig): conf = conf[key] conf[path[-1]] = value - def get_error_for_path(self, path: ConfigPath) -> Optional[vol.Invalid]: + def get_error_for_path(self, path: ConfigPath) -> vol.Invalid | None: for err in self.errors: if self.get_deepest_path(err.path) == path: self.errors.remove(err) @@ -181,7 +182,7 @@ class Config(OrderedDict, fv.FinalValidateConfig): def get_deepest_document_range_for_path( self, path: ConfigPath, get_key: bool = False - ) -> Optional[ESPHomeDataBase]: + ) -> ESPHomeDataBase | None: data = self doc_range = None for index, path_item in enumerate(path): @@ -733,7 +734,9 @@ class PinUseValidationCheck(ConfigValidationStep): pins.PIN_SCHEMA_REGISTRY.final_validate(result) -def validate_config(config, command_line_substitutions) -> Config: +def validate_config( + config: dict[str, Any], command_line_substitutions: dict[str, Any] +) -> Config: result = Config() loader.clear_component_meta_finders() @@ -897,24 +900,23 @@ class InvalidYAMLError(EsphomeError): self.base_exc = base_exc -def _load_config(command_line_substitutions): +def _load_config(command_line_substitutions: dict[str, Any]) -> Config: + """Load the configuration file.""" try: config = yaml_util.load_yaml(CORE.config_path) except EsphomeError as e: raise InvalidYAMLError(e) from e try: - result = validate_config(config, command_line_substitutions) + return validate_config(config, command_line_substitutions) except EsphomeError: raise except Exception: _LOGGER.error("Unexpected exception while reading configuration:") raise - return result - -def load_config(command_line_substitutions): +def load_config(command_line_substitutions: dict[str, Any]) -> Config: try: return _load_config(command_line_substitutions) except vol.Invalid as err: diff --git a/esphome/config_helpers.py b/esphome/config_helpers.py index ac52c6ede2..7b47e097c8 100644 --- a/esphome/config_helpers.py +++ b/esphome/config_helpers.py @@ -1,9 +1,4 @@ -import json -import os - from esphome.const import CONF_ID -from esphome.core import CORE -from esphome.helpers import read_file class Extend: @@ -38,25 +33,6 @@ class Remove: return isinstance(b, Remove) and self.value == b.value -def read_config_file(path: str) -> str: - if CORE.vscode and ( - not CORE.ace or os.path.abspath(path) == os.path.abspath(CORE.config_path) - ): - print( - json.dumps( - { - "type": "read_file", - "path": path, - } - ) - ) - data = json.loads(input()) - assert data["type"] == "file_response" - return data["content"] - - return read_file(path) - - def merge_config(full_old, full_new): def merge(old, new): if isinstance(new, dict): diff --git a/esphome/vscode.py b/esphome/vscode.py index cb2f51976f..8198d2659a 100644 --- a/esphome/vscode.py +++ b/esphome/vscode.py @@ -1,20 +1,22 @@ +from __future__ import annotations import json import os +from io import StringIO +from typing import Any -from typing import Optional - -from esphome.config import load_config, _format_vol_invalid, Config +from esphome.yaml_util import parse_yaml +from esphome.config import validate_config, _format_vol_invalid, Config from esphome.core import CORE, DocumentRange import esphome.config_validation as cv -def _get_invalid_range(res: Config, invalid: cv.Invalid) -> Optional[DocumentRange]: +def _get_invalid_range(res: Config, invalid: cv.Invalid) -> DocumentRange | None: return res.get_deepest_document_range_for_path( invalid.path, invalid.error_message == "extra keys not allowed" ) -def _dump_range(range: Optional[DocumentRange]) -> Optional[dict]: +def _dump_range(range: DocumentRange | None) -> dict | None: if range is None: return None return { @@ -56,6 +58,25 @@ class VSCodeResult: ) +def _read_file_content_from_json_on_stdin() -> str: + """Read the content of a json encoded file from stdin.""" + data = json.loads(input()) + assert data["type"] == "file_response" + return data["content"] + + +def _print_file_read_event(path: str) -> None: + """Print a file read event.""" + print( + json.dumps( + { + "type": "read_file", + "path": path, + } + ) + ) + + def read_config(args): while True: CORE.reset() @@ -68,9 +89,17 @@ def read_config(args): CORE.config_path = os.path.join(args.configuration, f) else: CORE.config_path = data["file"] + + file_name = CORE.config_path + _print_file_read_event(file_name) + raw_yaml = _read_file_content_from_json_on_stdin() + command_line_substitutions: dict[str, Any] = ( + dict(args.substitution) if args.substitution else {} + ) vs = VSCodeResult() try: - res = load_config(dict(args.substitution) if args.substitution else {}) + config = parse_yaml(file_name, StringIO(raw_yaml)) + res = validate_config(config, command_line_substitutions) except Exception as err: # pylint: disable=broad-except vs.add_yaml_error(str(err)) else: diff --git a/esphome/yaml_util.py b/esphome/yaml_util.py index 60705082b6..c7aa78201f 100644 --- a/esphome/yaml_util.py +++ b/esphome/yaml_util.py @@ -417,20 +417,25 @@ def load_yaml(fname: str, clear_secrets: bool = True) -> Any: return _load_yaml_internal(fname) +def parse_yaml(file_name: str, file_handle: TextIOWrapper) -> Any: + """Parse a YAML file.""" + try: + return _load_yaml_internal_with_type(ESPHomeLoader, file_name, file_handle) + except EsphomeError: + # Loading failed, so we now load with the Python loader which has more + # readable exceptions + # Rewind the stream so we can try again + file_handle.seek(0, 0) + return _load_yaml_internal_with_type( + ESPHomePurePythonLoader, file_name, file_handle + ) + + def _load_yaml_internal(fname: str) -> Any: """Load a YAML file.""" try: with open(fname, encoding="utf-8") as f_handle: - try: - return _load_yaml_internal_with_type(ESPHomeLoader, fname, f_handle) - except EsphomeError: - # Loading failed, so we now load with the Python loader which has more - # readable exceptions - # Rewind the stream so we can try again - f_handle.seek(0, 0) - return _load_yaml_internal_with_type( - ESPHomePurePythonLoader, fname, f_handle - ) + return parse_yaml(fname, f_handle) except (UnicodeDecodeError, OSError) as err: raise EsphomeError(f"Error reading file {fname}: {err}") from err From 4d30c81b0b181b38f2d0079445c2499c63216c57 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 27 Mar 2024 12:17:31 +1300 Subject: [PATCH 1160/2101] Bump version to 2024.3.1 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index e386448462..b09d0a8eb0 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.3.0" +__version__ = "2024.3.1" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 0948a3c30690f71f6a16c3e28f29edccb68872ba Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Tue, 26 Mar 2024 20:06:57 -0500 Subject: [PATCH 1161/2101] Add some components to the new testing framework (F) (#6177) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- .../factory_reset/test.esp32-c3-idf.yaml | 3 + .../factory_reset/test.esp32-c3.yaml | 3 + .../factory_reset/test.esp32-idf.yaml | 3 + .../components/factory_reset/test.esp32.yaml | 3 + .../factory_reset/test.esp8266.yaml | 3 + .../components/factory_reset/test.rp2040.yaml | 3 + .../fastled_clockless/test.esp32.yaml | 71 +++++++++++++++++++ tests/components/fastled_spi/test.esp32.yaml | 71 +++++++++++++++++++ .../feedback/test.esp32-c3-idf.yaml | 39 ++++++++++ tests/components/feedback/test.esp32-c3.yaml | 39 ++++++++++ tests/components/feedback/test.esp32-idf.yaml | 39 ++++++++++ tests/components/feedback/test.esp32.yaml | 39 ++++++++++ tests/components/feedback/test.esp8266.yaml | 39 ++++++++++ tests/components/feedback/test.rp2040.yaml | 39 ++++++++++ .../fingerprint_grow/test.esp32-c3-idf.yaml | 56 +++++++++++++++ .../fingerprint_grow/test.esp32-c3.yaml | 56 +++++++++++++++ .../fingerprint_grow/test.esp32-idf.yaml | 56 +++++++++++++++ .../fingerprint_grow/test.esp32.yaml | 56 +++++++++++++++ .../fingerprint_grow/test.esp8266.yaml | 56 +++++++++++++++ .../fingerprint_grow/test.rp2040.yaml | 56 +++++++++++++++ tests/components/font/test.esp32-c3-idf.yaml | 19 +++++ tests/components/font/test.esp32-c3.yaml | 19 +++++ tests/components/font/test.esp32-idf.yaml | 19 +++++ tests/components/font/test.esp8266.yaml | 19 +++++ tests/components/font/test.rp2040.yaml | 19 +++++ .../components/fs3000/test.esp32-c3-idf.yaml | 10 +++ tests/components/fs3000/test.esp32-c3.yaml | 10 +++ tests/components/fs3000/test.esp32-idf.yaml | 10 +++ tests/components/fs3000/test.esp32.yaml | 10 +++ tests/components/fs3000/test.esp8266.yaml | 10 +++ tests/components/fs3000/test.rp2040.yaml | 10 +++ .../components/ft5x06/test.esp32-c3-idf.yaml | 21 ++++++ tests/components/ft5x06/test.esp32-c3.yaml | 21 ++++++ tests/components/ft5x06/test.esp32-idf.yaml | 21 ++++++ tests/components/ft5x06/test.esp32.yaml | 21 ++++++ tests/components/ft5x06/test.esp8266.yaml | 21 ++++++ tests/components/ft5x06/test.rp2040.yaml | 21 ++++++ .../components/ft63x6/test.esp32-c3-idf.yaml | 21 ++++++ tests/components/ft63x6/test.esp32-c3.yaml | 21 ++++++ tests/components/ft63x6/test.esp32-idf.yaml | 21 ++++++ tests/components/ft63x6/test.esp8266.yaml | 21 ++++++ tests/components/ft63x6/test.rp2040.yaml | 21 ++++++ .../fujitsu_general/test.esp32-c3-idf.yaml | 7 ++ .../fujitsu_general/test.esp32-c3.yaml | 7 ++ .../fujitsu_general/test.esp32-idf.yaml | 7 ++ .../fujitsu_general/test.esp32.yaml | 7 ++ .../fujitsu_general/test.esp8266.yaml | 7 ++ 47 files changed, 1151 insertions(+) create mode 100644 tests/components/factory_reset/test.esp32-c3-idf.yaml create mode 100644 tests/components/factory_reset/test.esp32-c3.yaml create mode 100644 tests/components/factory_reset/test.esp32-idf.yaml create mode 100644 tests/components/factory_reset/test.esp32.yaml create mode 100644 tests/components/factory_reset/test.esp8266.yaml create mode 100644 tests/components/factory_reset/test.rp2040.yaml create mode 100644 tests/components/fastled_clockless/test.esp32.yaml create mode 100644 tests/components/fastled_spi/test.esp32.yaml create mode 100644 tests/components/feedback/test.esp32-c3-idf.yaml create mode 100644 tests/components/feedback/test.esp32-c3.yaml create mode 100644 tests/components/feedback/test.esp32-idf.yaml create mode 100644 tests/components/feedback/test.esp32.yaml create mode 100644 tests/components/feedback/test.esp8266.yaml create mode 100644 tests/components/feedback/test.rp2040.yaml create mode 100644 tests/components/fingerprint_grow/test.esp32-c3-idf.yaml create mode 100644 tests/components/fingerprint_grow/test.esp32-c3.yaml create mode 100644 tests/components/fingerprint_grow/test.esp32-idf.yaml create mode 100644 tests/components/fingerprint_grow/test.esp32.yaml create mode 100644 tests/components/fingerprint_grow/test.esp8266.yaml create mode 100644 tests/components/fingerprint_grow/test.rp2040.yaml create mode 100644 tests/components/font/test.esp32-c3-idf.yaml create mode 100644 tests/components/font/test.esp32-c3.yaml create mode 100644 tests/components/font/test.esp32-idf.yaml create mode 100644 tests/components/font/test.esp8266.yaml create mode 100644 tests/components/font/test.rp2040.yaml create mode 100644 tests/components/fs3000/test.esp32-c3-idf.yaml create mode 100644 tests/components/fs3000/test.esp32-c3.yaml create mode 100644 tests/components/fs3000/test.esp32-idf.yaml create mode 100644 tests/components/fs3000/test.esp32.yaml create mode 100644 tests/components/fs3000/test.esp8266.yaml create mode 100644 tests/components/fs3000/test.rp2040.yaml create mode 100644 tests/components/ft5x06/test.esp32-c3-idf.yaml create mode 100644 tests/components/ft5x06/test.esp32-c3.yaml create mode 100644 tests/components/ft5x06/test.esp32-idf.yaml create mode 100644 tests/components/ft5x06/test.esp32.yaml create mode 100644 tests/components/ft5x06/test.esp8266.yaml create mode 100644 tests/components/ft5x06/test.rp2040.yaml create mode 100644 tests/components/ft63x6/test.esp32-c3-idf.yaml create mode 100644 tests/components/ft63x6/test.esp32-c3.yaml create mode 100644 tests/components/ft63x6/test.esp32-idf.yaml create mode 100644 tests/components/ft63x6/test.esp8266.yaml create mode 100644 tests/components/ft63x6/test.rp2040.yaml create mode 100644 tests/components/fujitsu_general/test.esp32-c3-idf.yaml create mode 100644 tests/components/fujitsu_general/test.esp32-c3.yaml create mode 100644 tests/components/fujitsu_general/test.esp32-idf.yaml create mode 100644 tests/components/fujitsu_general/test.esp32.yaml create mode 100644 tests/components/fujitsu_general/test.esp8266.yaml diff --git a/tests/components/factory_reset/test.esp32-c3-idf.yaml b/tests/components/factory_reset/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..ad3abd603e --- /dev/null +++ b/tests/components/factory_reset/test.esp32-c3-idf.yaml @@ -0,0 +1,3 @@ +button: + - platform: factory_reset + name: Reset to Factory Default Settings diff --git a/tests/components/factory_reset/test.esp32-c3.yaml b/tests/components/factory_reset/test.esp32-c3.yaml new file mode 100644 index 0000000000..ad3abd603e --- /dev/null +++ b/tests/components/factory_reset/test.esp32-c3.yaml @@ -0,0 +1,3 @@ +button: + - platform: factory_reset + name: Reset to Factory Default Settings diff --git a/tests/components/factory_reset/test.esp32-idf.yaml b/tests/components/factory_reset/test.esp32-idf.yaml new file mode 100644 index 0000000000..ad3abd603e --- /dev/null +++ b/tests/components/factory_reset/test.esp32-idf.yaml @@ -0,0 +1,3 @@ +button: + - platform: factory_reset + name: Reset to Factory Default Settings diff --git a/tests/components/factory_reset/test.esp32.yaml b/tests/components/factory_reset/test.esp32.yaml new file mode 100644 index 0000000000..ad3abd603e --- /dev/null +++ b/tests/components/factory_reset/test.esp32.yaml @@ -0,0 +1,3 @@ +button: + - platform: factory_reset + name: Reset to Factory Default Settings diff --git a/tests/components/factory_reset/test.esp8266.yaml b/tests/components/factory_reset/test.esp8266.yaml new file mode 100644 index 0000000000..ad3abd603e --- /dev/null +++ b/tests/components/factory_reset/test.esp8266.yaml @@ -0,0 +1,3 @@ +button: + - platform: factory_reset + name: Reset to Factory Default Settings diff --git a/tests/components/factory_reset/test.rp2040.yaml b/tests/components/factory_reset/test.rp2040.yaml new file mode 100644 index 0000000000..ad3abd603e --- /dev/null +++ b/tests/components/factory_reset/test.rp2040.yaml @@ -0,0 +1,3 @@ +button: + - platform: factory_reset + name: Reset to Factory Default Settings diff --git a/tests/components/fastled_clockless/test.esp32.yaml b/tests/components/fastled_clockless/test.esp32.yaml new file mode 100644 index 0000000000..8b1447a17a --- /dev/null +++ b/tests/components/fastled_clockless/test.esp32.yaml @@ -0,0 +1,71 @@ +light: + - platform: fastled_clockless + id: addr1 + chipset: WS2811 + pin: 13 + num_leds: 100 + rgb_order: BRG + max_refresh_rate: 20ms + color_correct: [75%, 100%, 50%] + name: FastLED WS2811 Light + effects: + - addressable_color_wipe: + - addressable_color_wipe: + name: Color Wipe Effect With Custom Values + colors: + - red: 100% + green: 100% + blue: 100% + num_leds: 1 + - red: 0% + green: 0% + blue: 0% + num_leds: 1 + add_led_interval: 100ms + reverse: false + - addressable_scan: + - addressable_scan: + name: Scan Effect With Custom Values + move_interval: 100ms + - addressable_twinkle: + - addressable_twinkle: + name: Twinkle Effect With Custom Values + twinkle_probability: 5% + progress_interval: 4ms + - addressable_random_twinkle: + - addressable_random_twinkle: + name: Random Twinkle Effect With Custom Values + twinkle_probability: 5% + progress_interval: 32ms + - addressable_fireworks: + - addressable_fireworks: + name: Fireworks Effect With Custom Values + update_interval: 32ms + spark_probability: 10% + use_random_color: false + fade_out_rate: 120 + - addressable_flicker: + - addressable_flicker: + name: Flicker Effect With Custom Values + update_interval: 16ms + intensity: 5% + - addressable_lambda: + name: Test For Custom Lambda Effect + lambda: |- + if (initial_run) { + it[0] = current_color; + } + - automation: + name: Custom Effect + sequence: + - light.addressable_set: + id: addr1 + red: 100% + green: 100% + blue: 0% + - delay: 100ms + - light.addressable_set: + id: addr1 + red: 0% + green: 100% + blue: 0% diff --git a/tests/components/fastled_spi/test.esp32.yaml b/tests/components/fastled_spi/test.esp32.yaml new file mode 100644 index 0000000000..f6f7c5553b --- /dev/null +++ b/tests/components/fastled_spi/test.esp32.yaml @@ -0,0 +1,71 @@ +light: + - platform: fastled_spi + id: addr1 + chipset: WS2801 + clock_pin: 22 + data_pin: 23 + data_rate: 2MHz + num_leds: 60 + rgb_order: BRG + name: FastLED SPI Light + effects: + - addressable_color_wipe: + - addressable_color_wipe: + name: Color Wipe Effect With Custom Values + colors: + - red: 100% + green: 100% + blue: 100% + num_leds: 1 + - red: 0% + green: 0% + blue: 0% + num_leds: 1 + add_led_interval: 100ms + reverse: false + - addressable_scan: + - addressable_scan: + name: Scan Effect With Custom Values + move_interval: 100ms + - addressable_twinkle: + - addressable_twinkle: + name: Twinkle Effect With Custom Values + twinkle_probability: 5% + progress_interval: 4ms + - addressable_random_twinkle: + - addressable_random_twinkle: + name: Random Twinkle Effect With Custom Values + twinkle_probability: 5% + progress_interval: 32ms + - addressable_fireworks: + - addressable_fireworks: + name: Fireworks Effect With Custom Values + update_interval: 32ms + spark_probability: 10% + use_random_color: false + fade_out_rate: 120 + - addressable_flicker: + - addressable_flicker: + name: Flicker Effect With Custom Values + update_interval: 16ms + intensity: 5% + - addressable_lambda: + name: Test For Custom Lambda Effect + lambda: |- + if (initial_run) { + it[0] = current_color; + } + - automation: + name: Custom Effect + sequence: + - light.addressable_set: + id: addr1 + red: 100% + green: 100% + blue: 0% + - delay: 100ms + - light.addressable_set: + id: addr1 + red: 0% + green: 100% + blue: 0% diff --git a/tests/components/feedback/test.esp32-c3-idf.yaml b/tests/components/feedback/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..f93d54e8b6 --- /dev/null +++ b/tests/components/feedback/test.esp32-c3-idf.yaml @@ -0,0 +1,39 @@ +binary_sensor: + - platform: template + id: open_endstop_sensor + - platform: template + id: open_sensor + - platform: template + id: open_obstacle_sensor + - platform: template + id: close_endstop_sensor + - platform: template + id: close_sensor + - platform: template + id: close_obstacle_sensor + +cover: + - platform: feedback + name: Feedback Cover + id: gate + device_class: gate + infer_endstop_from_movement: false + has_built_in_endstop: false + max_duration: 30s + direction_change_wait_time: 300ms + acceleration_wait_time: 150ms + obstacle_rollback: 10% + open_duration: 22.1s + open_endstop: open_endstop_sensor + open_sensor: open_sensor + open_obstacle_sensor: open_obstacle_sensor + close_duration: 22.4s + close_endstop: close_endstop_sensor + close_sensor: close_sensor + close_obstacle_sensor: close_obstacle_sensor + open_action: + - logger.log: Open Action + close_action: + - logger.log: Close Action + stop_action: + - logger.log: Stop Action diff --git a/tests/components/feedback/test.esp32-c3.yaml b/tests/components/feedback/test.esp32-c3.yaml new file mode 100644 index 0000000000..f93d54e8b6 --- /dev/null +++ b/tests/components/feedback/test.esp32-c3.yaml @@ -0,0 +1,39 @@ +binary_sensor: + - platform: template + id: open_endstop_sensor + - platform: template + id: open_sensor + - platform: template + id: open_obstacle_sensor + - platform: template + id: close_endstop_sensor + - platform: template + id: close_sensor + - platform: template + id: close_obstacle_sensor + +cover: + - platform: feedback + name: Feedback Cover + id: gate + device_class: gate + infer_endstop_from_movement: false + has_built_in_endstop: false + max_duration: 30s + direction_change_wait_time: 300ms + acceleration_wait_time: 150ms + obstacle_rollback: 10% + open_duration: 22.1s + open_endstop: open_endstop_sensor + open_sensor: open_sensor + open_obstacle_sensor: open_obstacle_sensor + close_duration: 22.4s + close_endstop: close_endstop_sensor + close_sensor: close_sensor + close_obstacle_sensor: close_obstacle_sensor + open_action: + - logger.log: Open Action + close_action: + - logger.log: Close Action + stop_action: + - logger.log: Stop Action diff --git a/tests/components/feedback/test.esp32-idf.yaml b/tests/components/feedback/test.esp32-idf.yaml new file mode 100644 index 0000000000..f93d54e8b6 --- /dev/null +++ b/tests/components/feedback/test.esp32-idf.yaml @@ -0,0 +1,39 @@ +binary_sensor: + - platform: template + id: open_endstop_sensor + - platform: template + id: open_sensor + - platform: template + id: open_obstacle_sensor + - platform: template + id: close_endstop_sensor + - platform: template + id: close_sensor + - platform: template + id: close_obstacle_sensor + +cover: + - platform: feedback + name: Feedback Cover + id: gate + device_class: gate + infer_endstop_from_movement: false + has_built_in_endstop: false + max_duration: 30s + direction_change_wait_time: 300ms + acceleration_wait_time: 150ms + obstacle_rollback: 10% + open_duration: 22.1s + open_endstop: open_endstop_sensor + open_sensor: open_sensor + open_obstacle_sensor: open_obstacle_sensor + close_duration: 22.4s + close_endstop: close_endstop_sensor + close_sensor: close_sensor + close_obstacle_sensor: close_obstacle_sensor + open_action: + - logger.log: Open Action + close_action: + - logger.log: Close Action + stop_action: + - logger.log: Stop Action diff --git a/tests/components/feedback/test.esp32.yaml b/tests/components/feedback/test.esp32.yaml new file mode 100644 index 0000000000..f93d54e8b6 --- /dev/null +++ b/tests/components/feedback/test.esp32.yaml @@ -0,0 +1,39 @@ +binary_sensor: + - platform: template + id: open_endstop_sensor + - platform: template + id: open_sensor + - platform: template + id: open_obstacle_sensor + - platform: template + id: close_endstop_sensor + - platform: template + id: close_sensor + - platform: template + id: close_obstacle_sensor + +cover: + - platform: feedback + name: Feedback Cover + id: gate + device_class: gate + infer_endstop_from_movement: false + has_built_in_endstop: false + max_duration: 30s + direction_change_wait_time: 300ms + acceleration_wait_time: 150ms + obstacle_rollback: 10% + open_duration: 22.1s + open_endstop: open_endstop_sensor + open_sensor: open_sensor + open_obstacle_sensor: open_obstacle_sensor + close_duration: 22.4s + close_endstop: close_endstop_sensor + close_sensor: close_sensor + close_obstacle_sensor: close_obstacle_sensor + open_action: + - logger.log: Open Action + close_action: + - logger.log: Close Action + stop_action: + - logger.log: Stop Action diff --git a/tests/components/feedback/test.esp8266.yaml b/tests/components/feedback/test.esp8266.yaml new file mode 100644 index 0000000000..f93d54e8b6 --- /dev/null +++ b/tests/components/feedback/test.esp8266.yaml @@ -0,0 +1,39 @@ +binary_sensor: + - platform: template + id: open_endstop_sensor + - platform: template + id: open_sensor + - platform: template + id: open_obstacle_sensor + - platform: template + id: close_endstop_sensor + - platform: template + id: close_sensor + - platform: template + id: close_obstacle_sensor + +cover: + - platform: feedback + name: Feedback Cover + id: gate + device_class: gate + infer_endstop_from_movement: false + has_built_in_endstop: false + max_duration: 30s + direction_change_wait_time: 300ms + acceleration_wait_time: 150ms + obstacle_rollback: 10% + open_duration: 22.1s + open_endstop: open_endstop_sensor + open_sensor: open_sensor + open_obstacle_sensor: open_obstacle_sensor + close_duration: 22.4s + close_endstop: close_endstop_sensor + close_sensor: close_sensor + close_obstacle_sensor: close_obstacle_sensor + open_action: + - logger.log: Open Action + close_action: + - logger.log: Close Action + stop_action: + - logger.log: Stop Action diff --git a/tests/components/feedback/test.rp2040.yaml b/tests/components/feedback/test.rp2040.yaml new file mode 100644 index 0000000000..f93d54e8b6 --- /dev/null +++ b/tests/components/feedback/test.rp2040.yaml @@ -0,0 +1,39 @@ +binary_sensor: + - platform: template + id: open_endstop_sensor + - platform: template + id: open_sensor + - platform: template + id: open_obstacle_sensor + - platform: template + id: close_endstop_sensor + - platform: template + id: close_sensor + - platform: template + id: close_obstacle_sensor + +cover: + - platform: feedback + name: Feedback Cover + id: gate + device_class: gate + infer_endstop_from_movement: false + has_built_in_endstop: false + max_duration: 30s + direction_change_wait_time: 300ms + acceleration_wait_time: 150ms + obstacle_rollback: 10% + open_duration: 22.1s + open_endstop: open_endstop_sensor + open_sensor: open_sensor + open_obstacle_sensor: open_obstacle_sensor + close_duration: 22.4s + close_endstop: close_endstop_sensor + close_sensor: close_sensor + close_obstacle_sensor: close_obstacle_sensor + open_action: + - logger.log: Open Action + close_action: + - logger.log: Close Action + stop_action: + - logger.log: Stop Action diff --git a/tests/components/fingerprint_grow/test.esp32-c3-idf.yaml b/tests/components/fingerprint_grow/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..e7ac08eb28 --- /dev/null +++ b/tests/components/fingerprint_grow/test.esp32-c3-idf.yaml @@ -0,0 +1,56 @@ +esphome: + on_boot: + then: + - fingerprint_grow.enroll: + finger_id: 2 + num_scans: 2 + - fingerprint_grow.cancel_enroll: + - fingerprint_grow.delete: + finger_id: 2 + - fingerprint_grow.delete_all: + +uart: + - id: uart_fingerprint_grow + tx_pin: 4 + rx_pin: 5 + baud_rate: 57600 + +fingerprint_grow: + sensing_pin: 6 + password: 0x12FE37DC + new_password: 0xA65B9840 + on_finger_scan_start: + - logger.log: test_fingerprint_grow_finger_scan_start + on_finger_scan_invalid: + - logger.log: test_fingerprint_grow_finger_scan_invalid + on_finger_scan_matched: + - logger.log: test_fingerprint_grow_finger_scan_matched + on_finger_scan_unmatched: + - logger.log: test_fingerprint_grow_finger_scan_unmatched + on_finger_scan_misplaced: + - logger.log: test_fingerprint_grow_finger_scan_misplaced + on_enrollment_scan: + - logger.log: test_fingerprint_grow_enrollment_scan + on_enrollment_done: + - logger.log: test_fingerprint_grow_node_enrollment_done + on_enrollment_failed: + - logger.log: test_fingerprint_grow_enrollment_failed + +binary_sensor: + - platform: fingerprint_grow + name: Fingerprint Enrolling + +sensor: + - platform: fingerprint_grow + fingerprint_count: + name: Fingerprint Count + status: + name: Fingerprint Status + capacity: + name: Fingerprint Capacity + security_level: + name: Fingerprint Security Level + last_finger_id: + name: Fingerprint Last Finger ID + last_confidence: + name: Fingerprint Last Confidence diff --git a/tests/components/fingerprint_grow/test.esp32-c3.yaml b/tests/components/fingerprint_grow/test.esp32-c3.yaml new file mode 100644 index 0000000000..e7ac08eb28 --- /dev/null +++ b/tests/components/fingerprint_grow/test.esp32-c3.yaml @@ -0,0 +1,56 @@ +esphome: + on_boot: + then: + - fingerprint_grow.enroll: + finger_id: 2 + num_scans: 2 + - fingerprint_grow.cancel_enroll: + - fingerprint_grow.delete: + finger_id: 2 + - fingerprint_grow.delete_all: + +uart: + - id: uart_fingerprint_grow + tx_pin: 4 + rx_pin: 5 + baud_rate: 57600 + +fingerprint_grow: + sensing_pin: 6 + password: 0x12FE37DC + new_password: 0xA65B9840 + on_finger_scan_start: + - logger.log: test_fingerprint_grow_finger_scan_start + on_finger_scan_invalid: + - logger.log: test_fingerprint_grow_finger_scan_invalid + on_finger_scan_matched: + - logger.log: test_fingerprint_grow_finger_scan_matched + on_finger_scan_unmatched: + - logger.log: test_fingerprint_grow_finger_scan_unmatched + on_finger_scan_misplaced: + - logger.log: test_fingerprint_grow_finger_scan_misplaced + on_enrollment_scan: + - logger.log: test_fingerprint_grow_enrollment_scan + on_enrollment_done: + - logger.log: test_fingerprint_grow_node_enrollment_done + on_enrollment_failed: + - logger.log: test_fingerprint_grow_enrollment_failed + +binary_sensor: + - platform: fingerprint_grow + name: Fingerprint Enrolling + +sensor: + - platform: fingerprint_grow + fingerprint_count: + name: Fingerprint Count + status: + name: Fingerprint Status + capacity: + name: Fingerprint Capacity + security_level: + name: Fingerprint Security Level + last_finger_id: + name: Fingerprint Last Finger ID + last_confidence: + name: Fingerprint Last Confidence diff --git a/tests/components/fingerprint_grow/test.esp32-idf.yaml b/tests/components/fingerprint_grow/test.esp32-idf.yaml new file mode 100644 index 0000000000..0950145a05 --- /dev/null +++ b/tests/components/fingerprint_grow/test.esp32-idf.yaml @@ -0,0 +1,56 @@ +esphome: + on_boot: + then: + - fingerprint_grow.enroll: + finger_id: 2 + num_scans: 2 + - fingerprint_grow.cancel_enroll: + - fingerprint_grow.delete: + finger_id: 2 + - fingerprint_grow.delete_all: + +uart: + - id: uart_fingerprint_grow + tx_pin: 17 + rx_pin: 16 + baud_rate: 57600 + +fingerprint_grow: + sensing_pin: 18 + password: 0x12FE37DC + new_password: 0xA65B9840 + on_finger_scan_start: + - logger.log: test_fingerprint_grow_finger_scan_start + on_finger_scan_invalid: + - logger.log: test_fingerprint_grow_finger_scan_invalid + on_finger_scan_matched: + - logger.log: test_fingerprint_grow_finger_scan_matched + on_finger_scan_unmatched: + - logger.log: test_fingerprint_grow_finger_scan_unmatched + on_finger_scan_misplaced: + - logger.log: test_fingerprint_grow_finger_scan_misplaced + on_enrollment_scan: + - logger.log: test_fingerprint_grow_enrollment_scan + on_enrollment_done: + - logger.log: test_fingerprint_grow_node_enrollment_done + on_enrollment_failed: + - logger.log: test_fingerprint_grow_enrollment_failed + +binary_sensor: + - platform: fingerprint_grow + name: Fingerprint Enrolling + +sensor: + - platform: fingerprint_grow + fingerprint_count: + name: Fingerprint Count + status: + name: Fingerprint Status + capacity: + name: Fingerprint Capacity + security_level: + name: Fingerprint Security Level + last_finger_id: + name: Fingerprint Last Finger ID + last_confidence: + name: Fingerprint Last Confidence diff --git a/tests/components/fingerprint_grow/test.esp32.yaml b/tests/components/fingerprint_grow/test.esp32.yaml new file mode 100644 index 0000000000..0950145a05 --- /dev/null +++ b/tests/components/fingerprint_grow/test.esp32.yaml @@ -0,0 +1,56 @@ +esphome: + on_boot: + then: + - fingerprint_grow.enroll: + finger_id: 2 + num_scans: 2 + - fingerprint_grow.cancel_enroll: + - fingerprint_grow.delete: + finger_id: 2 + - fingerprint_grow.delete_all: + +uart: + - id: uart_fingerprint_grow + tx_pin: 17 + rx_pin: 16 + baud_rate: 57600 + +fingerprint_grow: + sensing_pin: 18 + password: 0x12FE37DC + new_password: 0xA65B9840 + on_finger_scan_start: + - logger.log: test_fingerprint_grow_finger_scan_start + on_finger_scan_invalid: + - logger.log: test_fingerprint_grow_finger_scan_invalid + on_finger_scan_matched: + - logger.log: test_fingerprint_grow_finger_scan_matched + on_finger_scan_unmatched: + - logger.log: test_fingerprint_grow_finger_scan_unmatched + on_finger_scan_misplaced: + - logger.log: test_fingerprint_grow_finger_scan_misplaced + on_enrollment_scan: + - logger.log: test_fingerprint_grow_enrollment_scan + on_enrollment_done: + - logger.log: test_fingerprint_grow_node_enrollment_done + on_enrollment_failed: + - logger.log: test_fingerprint_grow_enrollment_failed + +binary_sensor: + - platform: fingerprint_grow + name: Fingerprint Enrolling + +sensor: + - platform: fingerprint_grow + fingerprint_count: + name: Fingerprint Count + status: + name: Fingerprint Status + capacity: + name: Fingerprint Capacity + security_level: + name: Fingerprint Security Level + last_finger_id: + name: Fingerprint Last Finger ID + last_confidence: + name: Fingerprint Last Confidence diff --git a/tests/components/fingerprint_grow/test.esp8266.yaml b/tests/components/fingerprint_grow/test.esp8266.yaml new file mode 100644 index 0000000000..1d00d977b9 --- /dev/null +++ b/tests/components/fingerprint_grow/test.esp8266.yaml @@ -0,0 +1,56 @@ +esphome: + on_boot: + then: + - fingerprint_grow.enroll: + finger_id: 2 + num_scans: 2 + - fingerprint_grow.cancel_enroll: + - fingerprint_grow.delete: + finger_id: 2 + - fingerprint_grow.delete_all: + +uart: + - id: uart_fingerprint_grow + tx_pin: 4 + rx_pin: 5 + baud_rate: 57600 + +fingerprint_grow: + sensing_pin: 16 + password: 0x12FE37DC + new_password: 0xA65B9840 + on_finger_scan_start: + - logger.log: test_fingerprint_grow_finger_scan_start + on_finger_scan_invalid: + - logger.log: test_fingerprint_grow_finger_scan_invalid + on_finger_scan_matched: + - logger.log: test_fingerprint_grow_finger_scan_matched + on_finger_scan_unmatched: + - logger.log: test_fingerprint_grow_finger_scan_unmatched + on_finger_scan_misplaced: + - logger.log: test_fingerprint_grow_finger_scan_misplaced + on_enrollment_scan: + - logger.log: test_fingerprint_grow_enrollment_scan + on_enrollment_done: + - logger.log: test_fingerprint_grow_node_enrollment_done + on_enrollment_failed: + - logger.log: test_fingerprint_grow_enrollment_failed + +binary_sensor: + - platform: fingerprint_grow + name: Fingerprint Enrolling + +sensor: + - platform: fingerprint_grow + fingerprint_count: + name: Fingerprint Count + status: + name: Fingerprint Status + capacity: + name: Fingerprint Capacity + security_level: + name: Fingerprint Security Level + last_finger_id: + name: Fingerprint Last Finger ID + last_confidence: + name: Fingerprint Last Confidence diff --git a/tests/components/fingerprint_grow/test.rp2040.yaml b/tests/components/fingerprint_grow/test.rp2040.yaml new file mode 100644 index 0000000000..e7ac08eb28 --- /dev/null +++ b/tests/components/fingerprint_grow/test.rp2040.yaml @@ -0,0 +1,56 @@ +esphome: + on_boot: + then: + - fingerprint_grow.enroll: + finger_id: 2 + num_scans: 2 + - fingerprint_grow.cancel_enroll: + - fingerprint_grow.delete: + finger_id: 2 + - fingerprint_grow.delete_all: + +uart: + - id: uart_fingerprint_grow + tx_pin: 4 + rx_pin: 5 + baud_rate: 57600 + +fingerprint_grow: + sensing_pin: 6 + password: 0x12FE37DC + new_password: 0xA65B9840 + on_finger_scan_start: + - logger.log: test_fingerprint_grow_finger_scan_start + on_finger_scan_invalid: + - logger.log: test_fingerprint_grow_finger_scan_invalid + on_finger_scan_matched: + - logger.log: test_fingerprint_grow_finger_scan_matched + on_finger_scan_unmatched: + - logger.log: test_fingerprint_grow_finger_scan_unmatched + on_finger_scan_misplaced: + - logger.log: test_fingerprint_grow_finger_scan_misplaced + on_enrollment_scan: + - logger.log: test_fingerprint_grow_enrollment_scan + on_enrollment_done: + - logger.log: test_fingerprint_grow_node_enrollment_done + on_enrollment_failed: + - logger.log: test_fingerprint_grow_enrollment_failed + +binary_sensor: + - platform: fingerprint_grow + name: Fingerprint Enrolling + +sensor: + - platform: fingerprint_grow + fingerprint_count: + name: Fingerprint Count + status: + name: Fingerprint Status + capacity: + name: Fingerprint Capacity + security_level: + name: Fingerprint Security Level + last_finger_id: + name: Fingerprint Last Finger ID + last_confidence: + name: Fingerprint Last Confidence diff --git a/tests/components/font/test.esp32-c3-idf.yaml b/tests/components/font/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..b63b4d025a --- /dev/null +++ b/tests/components/font/test.esp32-c3-idf.yaml @@ -0,0 +1,19 @@ +i2c: + - id: i2c_font + scl: 5 + sda: 4 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 3 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +font: + - file: "gfonts://Roboto" + id: roboto + size: 20 diff --git a/tests/components/font/test.esp32-c3.yaml b/tests/components/font/test.esp32-c3.yaml new file mode 100644 index 0000000000..b63b4d025a --- /dev/null +++ b/tests/components/font/test.esp32-c3.yaml @@ -0,0 +1,19 @@ +i2c: + - id: i2c_font + scl: 5 + sda: 4 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 3 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +font: + - file: "gfonts://Roboto" + id: roboto + size: 20 diff --git a/tests/components/font/test.esp32-idf.yaml b/tests/components/font/test.esp32-idf.yaml new file mode 100644 index 0000000000..dcf8fb49d5 --- /dev/null +++ b/tests/components/font/test.esp32-idf.yaml @@ -0,0 +1,19 @@ +i2c: + - id: i2c_font + scl: 16 + sda: 17 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 13 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +font: + - file: "gfonts://Roboto" + id: roboto + size: 20 diff --git a/tests/components/font/test.esp8266.yaml b/tests/components/font/test.esp8266.yaml new file mode 100644 index 0000000000..b63b4d025a --- /dev/null +++ b/tests/components/font/test.esp8266.yaml @@ -0,0 +1,19 @@ +i2c: + - id: i2c_font + scl: 5 + sda: 4 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 3 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +font: + - file: "gfonts://Roboto" + id: roboto + size: 20 diff --git a/tests/components/font/test.rp2040.yaml b/tests/components/font/test.rp2040.yaml new file mode 100644 index 0000000000..b63b4d025a --- /dev/null +++ b/tests/components/font/test.rp2040.yaml @@ -0,0 +1,19 @@ +i2c: + - id: i2c_font + scl: 5 + sda: 4 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 3 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +font: + - file: "gfonts://Roboto" + id: roboto + size: 20 diff --git a/tests/components/fs3000/test.esp32-c3-idf.yaml b/tests/components/fs3000/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..69de83b463 --- /dev/null +++ b/tests/components/fs3000/test.esp32-c3-idf.yaml @@ -0,0 +1,10 @@ +i2c: + - id: i2c_fs3000 + scl: 5 + sda: 4 + +sensor: + - platform: fs3000 + name: Air Velocity + model: 1005 + update_interval: 60s diff --git a/tests/components/fs3000/test.esp32-c3.yaml b/tests/components/fs3000/test.esp32-c3.yaml new file mode 100644 index 0000000000..69de83b463 --- /dev/null +++ b/tests/components/fs3000/test.esp32-c3.yaml @@ -0,0 +1,10 @@ +i2c: + - id: i2c_fs3000 + scl: 5 + sda: 4 + +sensor: + - platform: fs3000 + name: Air Velocity + model: 1005 + update_interval: 60s diff --git a/tests/components/fs3000/test.esp32-idf.yaml b/tests/components/fs3000/test.esp32-idf.yaml new file mode 100644 index 0000000000..53b49cc9a2 --- /dev/null +++ b/tests/components/fs3000/test.esp32-idf.yaml @@ -0,0 +1,10 @@ +i2c: + - id: i2c_fs3000 + scl: 16 + sda: 17 + +sensor: + - platform: fs3000 + name: Air Velocity + model: 1005 + update_interval: 60s diff --git a/tests/components/fs3000/test.esp32.yaml b/tests/components/fs3000/test.esp32.yaml new file mode 100644 index 0000000000..53b49cc9a2 --- /dev/null +++ b/tests/components/fs3000/test.esp32.yaml @@ -0,0 +1,10 @@ +i2c: + - id: i2c_fs3000 + scl: 16 + sda: 17 + +sensor: + - platform: fs3000 + name: Air Velocity + model: 1005 + update_interval: 60s diff --git a/tests/components/fs3000/test.esp8266.yaml b/tests/components/fs3000/test.esp8266.yaml new file mode 100644 index 0000000000..69de83b463 --- /dev/null +++ b/tests/components/fs3000/test.esp8266.yaml @@ -0,0 +1,10 @@ +i2c: + - id: i2c_fs3000 + scl: 5 + sda: 4 + +sensor: + - platform: fs3000 + name: Air Velocity + model: 1005 + update_interval: 60s diff --git a/tests/components/fs3000/test.rp2040.yaml b/tests/components/fs3000/test.rp2040.yaml new file mode 100644 index 0000000000..69de83b463 --- /dev/null +++ b/tests/components/fs3000/test.rp2040.yaml @@ -0,0 +1,10 @@ +i2c: + - id: i2c_fs3000 + scl: 5 + sda: 4 + +sensor: + - platform: fs3000 + name: Air Velocity + model: 1005 + update_interval: 60s diff --git a/tests/components/ft5x06/test.esp32-c3-idf.yaml b/tests/components/ft5x06/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..4fa9532f53 --- /dev/null +++ b/tests/components/ft5x06/test.esp32-c3-idf.yaml @@ -0,0 +1,21 @@ +i2c: + - id: i2c_ft5x06 + scl: 5 + sda: 4 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 3 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: ft5x06 + on_touch: + - logger.log: + format: Touch at (%d, %d) + args: [touch.x, touch.y] diff --git a/tests/components/ft5x06/test.esp32-c3.yaml b/tests/components/ft5x06/test.esp32-c3.yaml new file mode 100644 index 0000000000..4fa9532f53 --- /dev/null +++ b/tests/components/ft5x06/test.esp32-c3.yaml @@ -0,0 +1,21 @@ +i2c: + - id: i2c_ft5x06 + scl: 5 + sda: 4 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 3 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: ft5x06 + on_touch: + - logger.log: + format: Touch at (%d, %d) + args: [touch.x, touch.y] diff --git a/tests/components/ft5x06/test.esp32-idf.yaml b/tests/components/ft5x06/test.esp32-idf.yaml new file mode 100644 index 0000000000..648929896d --- /dev/null +++ b/tests/components/ft5x06/test.esp32-idf.yaml @@ -0,0 +1,21 @@ +i2c: + - id: i2c_ft5x06 + scl: 16 + sda: 17 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 18 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: ft5x06 + on_touch: + - logger.log: + format: Touch at (%d, %d) + args: [touch.x, touch.y] diff --git a/tests/components/ft5x06/test.esp32.yaml b/tests/components/ft5x06/test.esp32.yaml new file mode 100644 index 0000000000..648929896d --- /dev/null +++ b/tests/components/ft5x06/test.esp32.yaml @@ -0,0 +1,21 @@ +i2c: + - id: i2c_ft5x06 + scl: 16 + sda: 17 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 18 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: ft5x06 + on_touch: + - logger.log: + format: Touch at (%d, %d) + args: [touch.x, touch.y] diff --git a/tests/components/ft5x06/test.esp8266.yaml b/tests/components/ft5x06/test.esp8266.yaml new file mode 100644 index 0000000000..4fa9532f53 --- /dev/null +++ b/tests/components/ft5x06/test.esp8266.yaml @@ -0,0 +1,21 @@ +i2c: + - id: i2c_ft5x06 + scl: 5 + sda: 4 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 3 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: ft5x06 + on_touch: + - logger.log: + format: Touch at (%d, %d) + args: [touch.x, touch.y] diff --git a/tests/components/ft5x06/test.rp2040.yaml b/tests/components/ft5x06/test.rp2040.yaml new file mode 100644 index 0000000000..4fa9532f53 --- /dev/null +++ b/tests/components/ft5x06/test.rp2040.yaml @@ -0,0 +1,21 @@ +i2c: + - id: i2c_ft5x06 + scl: 5 + sda: 4 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 3 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: ft5x06 + on_touch: + - logger.log: + format: Touch at (%d, %d) + args: [touch.x, touch.y] diff --git a/tests/components/ft63x6/test.esp32-c3-idf.yaml b/tests/components/ft63x6/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..19ca4cfc19 --- /dev/null +++ b/tests/components/ft63x6/test.esp32-c3-idf.yaml @@ -0,0 +1,21 @@ +i2c: + - id: i2c_ft63x6 + scl: 5 + sda: 4 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 3 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: ft63x6 + on_touch: + - logger.log: + format: Touch at (%d, %d) + args: [touch.x, touch.y] diff --git a/tests/components/ft63x6/test.esp32-c3.yaml b/tests/components/ft63x6/test.esp32-c3.yaml new file mode 100644 index 0000000000..19ca4cfc19 --- /dev/null +++ b/tests/components/ft63x6/test.esp32-c3.yaml @@ -0,0 +1,21 @@ +i2c: + - id: i2c_ft63x6 + scl: 5 + sda: 4 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 3 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: ft63x6 + on_touch: + - logger.log: + format: Touch at (%d, %d) + args: [touch.x, touch.y] diff --git a/tests/components/ft63x6/test.esp32-idf.yaml b/tests/components/ft63x6/test.esp32-idf.yaml new file mode 100644 index 0000000000..5ceb107e31 --- /dev/null +++ b/tests/components/ft63x6/test.esp32-idf.yaml @@ -0,0 +1,21 @@ +i2c: + - id: i2c_ft63x6 + scl: 16 + sda: 17 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 18 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: ft63x6 + on_touch: + - logger.log: + format: Touch at (%d, %d) + args: [touch.x, touch.y] diff --git a/tests/components/ft63x6/test.esp8266.yaml b/tests/components/ft63x6/test.esp8266.yaml new file mode 100644 index 0000000000..19ca4cfc19 --- /dev/null +++ b/tests/components/ft63x6/test.esp8266.yaml @@ -0,0 +1,21 @@ +i2c: + - id: i2c_ft63x6 + scl: 5 + sda: 4 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 3 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: ft63x6 + on_touch: + - logger.log: + format: Touch at (%d, %d) + args: [touch.x, touch.y] diff --git a/tests/components/ft63x6/test.rp2040.yaml b/tests/components/ft63x6/test.rp2040.yaml new file mode 100644 index 0000000000..19ca4cfc19 --- /dev/null +++ b/tests/components/ft63x6/test.rp2040.yaml @@ -0,0 +1,21 @@ +i2c: + - id: i2c_ft63x6 + scl: 5 + sda: 4 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 3 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: ft63x6 + on_touch: + - logger.log: + format: Touch at (%d, %d) + args: [touch.x, touch.y] diff --git a/tests/components/fujitsu_general/test.esp32-c3-idf.yaml b/tests/components/fujitsu_general/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..b4146f2a18 --- /dev/null +++ b/tests/components/fujitsu_general/test.esp32-c3-idf.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +climate: + - platform: fujitsu_general + name: Fujitsu General Climate diff --git a/tests/components/fujitsu_general/test.esp32-c3.yaml b/tests/components/fujitsu_general/test.esp32-c3.yaml new file mode 100644 index 0000000000..b4146f2a18 --- /dev/null +++ b/tests/components/fujitsu_general/test.esp32-c3.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +climate: + - platform: fujitsu_general + name: Fujitsu General Climate diff --git a/tests/components/fujitsu_general/test.esp32-idf.yaml b/tests/components/fujitsu_general/test.esp32-idf.yaml new file mode 100644 index 0000000000..b4146f2a18 --- /dev/null +++ b/tests/components/fujitsu_general/test.esp32-idf.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +climate: + - platform: fujitsu_general + name: Fujitsu General Climate diff --git a/tests/components/fujitsu_general/test.esp32.yaml b/tests/components/fujitsu_general/test.esp32.yaml new file mode 100644 index 0000000000..b4146f2a18 --- /dev/null +++ b/tests/components/fujitsu_general/test.esp32.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +climate: + - platform: fujitsu_general + name: Fujitsu General Climate diff --git a/tests/components/fujitsu_general/test.esp8266.yaml b/tests/components/fujitsu_general/test.esp8266.yaml new file mode 100644 index 0000000000..2a05bdde6b --- /dev/null +++ b/tests/components/fujitsu_general/test.esp8266.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 5 + carrier_duty_percent: 50% + +climate: + - platform: fujitsu_general + name: Fujitsu General Climate From 58de8a4ee6cea6df248a904bde7e4a6dcf041a70 Mon Sep 17 00:00:00 2001 From: Ben Kristinsson Date: Wed, 27 Mar 2024 02:13:41 +0100 Subject: [PATCH 1162/2101] Add get_contrast() and get_brightness() to SSD1306 class to get protected variables (#6435) --- esphome/components/ssd1306_base/ssd1306_base.cpp | 2 ++ esphome/components/ssd1306_base/ssd1306_base.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/esphome/components/ssd1306_base/ssd1306_base.cpp b/esphome/components/ssd1306_base/ssd1306_base.cpp index 749c3511c1..90b805a79f 100644 --- a/esphome/components/ssd1306_base/ssd1306_base.cpp +++ b/esphome/components/ssd1306_base/ssd1306_base.cpp @@ -236,6 +236,7 @@ void SSD1306::set_invert(bool invert) { // Inverse display mode (0xA6, 0xA7) this->command(SSD1306_COMMAND_NORMAL_DISPLAY | this->invert_); } +float SSD1306::get_contrast() { return this->contrast_; }; void SSD1306::set_contrast(float contrast) { // validation this->contrast_ = clamp(contrast, 0.0F, 1.0F); @@ -243,6 +244,7 @@ void SSD1306::set_contrast(float contrast) { this->command(SSD1306_COMMAND_SET_CONTRAST); this->command(int(SSD1306_MAX_CONTRAST * (this->contrast_))); } +float SSD1306::get_brightness() { return this->brightness_; }; void SSD1306::set_brightness(float brightness) { // validation if (!this->is_ssd1305_()) diff --git a/esphome/components/ssd1306_base/ssd1306_base.h b/esphome/components/ssd1306_base/ssd1306_base.h index 2e09755863..14ec309ae0 100644 --- a/esphome/components/ssd1306_base/ssd1306_base.h +++ b/esphome/components/ssd1306_base/ssd1306_base.h @@ -36,7 +36,9 @@ class SSD1306 : public display::DisplayBuffer { void set_reset_pin(GPIOPin *reset_pin) { this->reset_pin_ = reset_pin; } void set_external_vcc(bool external_vcc) { this->external_vcc_ = external_vcc; } void init_contrast(float contrast) { this->contrast_ = contrast; } + float get_contrast(); void set_contrast(float contrast); + float get_brightness(); void init_brightness(float brightness) { this->brightness_ = brightness; } void set_brightness(float brightness); void init_flip_x(bool flip_x) { this->flip_x_ = flip_x; } From 94e9476838368cb3b896fc58fe8bcb70ff6177cf Mon Sep 17 00:00:00 2001 From: Mafus1 Date: Wed, 27 Mar 2024 02:14:23 +0100 Subject: [PATCH 1163/2101] Add new Component: Ultrasonic Distance Sensor JSN-SR04T (#6023) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- CODEOWNERS | 1 + esphome/components/jsn_sr04t/__init__.py | 1 + esphome/components/jsn_sr04t/jsn_sr04t.cpp | 58 +++++++++++++++++++ esphome/components/jsn_sr04t/jsn_sr04t.h | 28 +++++++++ esphome/components/jsn_sr04t/sensor.py | 44 ++++++++++++++ .../jsn_sr04t/test.esp32-c3-idf.yaml | 14 +++++ tests/components/jsn_sr04t/test.esp32-c3.yaml | 14 +++++ .../components/jsn_sr04t/test.esp32-idf.yaml | 14 +++++ tests/components/jsn_sr04t/test.esp32.yaml | 14 +++++ tests/components/jsn_sr04t/test.esp8266.yaml | 14 +++++ tests/components/jsn_sr04t/test.rp2040.yaml | 14 +++++ 11 files changed, 216 insertions(+) create mode 100644 esphome/components/jsn_sr04t/__init__.py create mode 100644 esphome/components/jsn_sr04t/jsn_sr04t.cpp create mode 100644 esphome/components/jsn_sr04t/jsn_sr04t.h create mode 100644 esphome/components/jsn_sr04t/sensor.py create mode 100644 tests/components/jsn_sr04t/test.esp32-c3-idf.yaml create mode 100644 tests/components/jsn_sr04t/test.esp32-c3.yaml create mode 100644 tests/components/jsn_sr04t/test.esp32-idf.yaml create mode 100644 tests/components/jsn_sr04t/test.esp32.yaml create mode 100644 tests/components/jsn_sr04t/test.esp8266.yaml create mode 100644 tests/components/jsn_sr04t/test.rp2040.yaml diff --git a/CODEOWNERS b/CODEOWNERS index b924f55d0b..d6ec3843a5 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -173,6 +173,7 @@ esphome/components/inkplate6/* @jesserockz esphome/components/integration/* @OttoWinter esphome/components/internal_temperature/* @Mat931 esphome/components/interval/* @esphome/core +esphome/components/jsn_sr04t/* @Mafus1 esphome/components/json/* @OttoWinter esphome/components/kamstrup_kmp/* @cfeenstra1024 esphome/components/key_collector/* @ssieb diff --git a/esphome/components/jsn_sr04t/__init__.py b/esphome/components/jsn_sr04t/__init__.py new file mode 100644 index 0000000000..ef6335f316 --- /dev/null +++ b/esphome/components/jsn_sr04t/__init__.py @@ -0,0 +1 @@ +CODEOWNERS = ["@Mafus1"] diff --git a/esphome/components/jsn_sr04t/jsn_sr04t.cpp b/esphome/components/jsn_sr04t/jsn_sr04t.cpp new file mode 100644 index 0000000000..70e21a137d --- /dev/null +++ b/esphome/components/jsn_sr04t/jsn_sr04t.cpp @@ -0,0 +1,58 @@ +#include "jsn_sr04t.h" +#include "esphome/core/helpers.h" +#include "esphome/core/log.h" + +#include + +// Very basic support for JSN_SR04T V3.0 distance sensor in mode 2 + +namespace esphome { +namespace jsn_sr04t { + +static const char *const TAG = "jsn_sr04t.sensor"; + +void Jsnsr04tComponent::update() { + this->write_byte(0x55); + ESP_LOGV(TAG, "Request read out from sensor"); +} + +void Jsnsr04tComponent::loop() { + while (this->available() > 0) { + uint8_t data; + this->read_byte(&data); + + ESP_LOGV(TAG, "Read byte from sensor: %x", data); + + if (this->buffer_.empty() && data != 0xFF) + continue; + + this->buffer_.push_back(data); + if (this->buffer_.size() == 4) + this->check_buffer_(); + } +} + +void Jsnsr04tComponent::check_buffer_() { + uint8_t checksum = this->buffer_[0] + this->buffer_[1] + this->buffer_[2]; + if (this->buffer_[3] == checksum) { + uint16_t distance = encode_uint16(this->buffer_[1], this->buffer_[2]); + if (distance > 250) { + float meters = distance / 1000.0f; + ESP_LOGV(TAG, "Distance from sensor: %" PRIu32 "mm, %.3fm", distance, meters); + this->publish_state(meters); + } else { + ESP_LOGW(TAG, "Invalid data read from sensor: %s", format_hex_pretty(this->buffer_).c_str()); + } + } else { + ESP_LOGW(TAG, "checksum failed: %02x != %02x", checksum, this->buffer_[3]); + } + this->buffer_.clear(); +} + +void Jsnsr04tComponent::dump_config() { + LOG_SENSOR("", "JST_SR04T Sensor", this); + LOG_UPDATE_INTERVAL(this); +} + +} // namespace jsn_sr04t +} // namespace esphome diff --git a/esphome/components/jsn_sr04t/jsn_sr04t.h b/esphome/components/jsn_sr04t/jsn_sr04t.h new file mode 100644 index 0000000000..bd43252be8 --- /dev/null +++ b/esphome/components/jsn_sr04t/jsn_sr04t.h @@ -0,0 +1,28 @@ +#pragma once + +#include + +#include "esphome/core/component.h" +#include "esphome/components/sensor/sensor.h" +#include "esphome/components/uart/uart.h" + +namespace esphome { +namespace jsn_sr04t { + +class Jsnsr04tComponent : public sensor::Sensor, public PollingComponent, public uart::UARTDevice { + public: + // Nothing really public. + + // ========== INTERNAL METHODS ========== + void update() override; + void loop() override; + void dump_config() override; + + protected: + void check_buffer_(); + + std::vector buffer_; +}; + +} // namespace jsn_sr04t +} // namespace esphome diff --git a/esphome/components/jsn_sr04t/sensor.py b/esphome/components/jsn_sr04t/sensor.py new file mode 100644 index 0000000000..4b062e81e9 --- /dev/null +++ b/esphome/components/jsn_sr04t/sensor.py @@ -0,0 +1,44 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import sensor, uart +from esphome.const import ( + STATE_CLASS_MEASUREMENT, + UNIT_METER, + ICON_ARROW_EXPAND_VERTICAL, +) + +CODEOWNERS = ["@Mafus1"] +DEPENDENCIES = ["uart"] + +jsn_sr04t_ns = cg.esphome_ns.namespace("jsn_sr04t") +Jsnsr04tComponent = jsn_sr04t_ns.class_( + "Jsnsr04tComponent", sensor.Sensor, cg.PollingComponent, uart.UARTDevice +) + +CONFIG_SCHEMA = ( + sensor.sensor_schema( + Jsnsr04tComponent, + unit_of_measurement=UNIT_METER, + icon=ICON_ARROW_EXPAND_VERTICAL, + accuracy_decimals=3, + state_class=STATE_CLASS_MEASUREMENT, + ) + .extend(cv.polling_component_schema("60s")) + .extend(uart.UART_DEVICE_SCHEMA) +) + +FINAL_VALIDATE_SCHEMA = uart.final_validate_device_schema( + "jsn_sr04t", + baud_rate=9600, + require_tx=True, + require_rx=True, + data_bits=8, + parity=None, + stop_bits=1, +) + + +async def to_code(config): + var = await sensor.new_sensor(config) + await cg.register_component(var, config) + await uart.register_uart_device(var, config) diff --git a/tests/components/jsn_sr04t/test.esp32-c3-idf.yaml b/tests/components/jsn_sr04t/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..5a37418a7d --- /dev/null +++ b/tests/components/jsn_sr04t/test.esp32-c3-idf.yaml @@ -0,0 +1,14 @@ +uart: + - id: uart_jsn_sr04t + tx_pin: + number: 4 + rx_pin: + number: 5 + baud_rate: 9600 + +sensor: + - platform: jsn_sr04t + id: jsn_sr04t_sensor + name: "jsn_sr04t Distance" + uart_id: uart_jsn_sr04t + update_interval: 1s diff --git a/tests/components/jsn_sr04t/test.esp32-c3.yaml b/tests/components/jsn_sr04t/test.esp32-c3.yaml new file mode 100644 index 0000000000..5a37418a7d --- /dev/null +++ b/tests/components/jsn_sr04t/test.esp32-c3.yaml @@ -0,0 +1,14 @@ +uart: + - id: uart_jsn_sr04t + tx_pin: + number: 4 + rx_pin: + number: 5 + baud_rate: 9600 + +sensor: + - platform: jsn_sr04t + id: jsn_sr04t_sensor + name: "jsn_sr04t Distance" + uart_id: uart_jsn_sr04t + update_interval: 1s diff --git a/tests/components/jsn_sr04t/test.esp32-idf.yaml b/tests/components/jsn_sr04t/test.esp32-idf.yaml new file mode 100644 index 0000000000..32b4221b3f --- /dev/null +++ b/tests/components/jsn_sr04t/test.esp32-idf.yaml @@ -0,0 +1,14 @@ +uart: + - id: uart_jsn_sr04t + tx_pin: + number: 17 + rx_pin: + number: 16 + baud_rate: 9600 + +sensor: + - platform: jsn_sr04t + id: jsn_sr04t_sensor + name: "jsn_sr04t Distance" + uart_id: uart_jsn_sr04t + update_interval: 1s diff --git a/tests/components/jsn_sr04t/test.esp32.yaml b/tests/components/jsn_sr04t/test.esp32.yaml new file mode 100644 index 0000000000..32b4221b3f --- /dev/null +++ b/tests/components/jsn_sr04t/test.esp32.yaml @@ -0,0 +1,14 @@ +uart: + - id: uart_jsn_sr04t + tx_pin: + number: 17 + rx_pin: + number: 16 + baud_rate: 9600 + +sensor: + - platform: jsn_sr04t + id: jsn_sr04t_sensor + name: "jsn_sr04t Distance" + uart_id: uart_jsn_sr04t + update_interval: 1s diff --git a/tests/components/jsn_sr04t/test.esp8266.yaml b/tests/components/jsn_sr04t/test.esp8266.yaml new file mode 100644 index 0000000000..5a37418a7d --- /dev/null +++ b/tests/components/jsn_sr04t/test.esp8266.yaml @@ -0,0 +1,14 @@ +uart: + - id: uart_jsn_sr04t + tx_pin: + number: 4 + rx_pin: + number: 5 + baud_rate: 9600 + +sensor: + - platform: jsn_sr04t + id: jsn_sr04t_sensor + name: "jsn_sr04t Distance" + uart_id: uart_jsn_sr04t + update_interval: 1s diff --git a/tests/components/jsn_sr04t/test.rp2040.yaml b/tests/components/jsn_sr04t/test.rp2040.yaml new file mode 100644 index 0000000000..5a37418a7d --- /dev/null +++ b/tests/components/jsn_sr04t/test.rp2040.yaml @@ -0,0 +1,14 @@ +uart: + - id: uart_jsn_sr04t + tx_pin: + number: 4 + rx_pin: + number: 5 + baud_rate: 9600 + +sensor: + - platform: jsn_sr04t + id: jsn_sr04t_sensor + name: "jsn_sr04t Distance" + uart_id: uart_jsn_sr04t + update_interval: 1s From eee71466142dafb573c8578923b75d0712a99792 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Tue, 26 Mar 2024 20:22:01 -0500 Subject: [PATCH 1164/2101] Add some components to the new testing framework (G) (#6178) --- tests/components/gcja5/test.esp32-c3-idf.yaml | 25 ++++ tests/components/gcja5/test.esp32-c3.yaml | 25 ++++ tests/components/gcja5/test.esp32-idf.yaml | 25 ++++ tests/components/gcja5/test.esp32.yaml | 25 ++++ tests/components/gcja5/test.esp8266.yaml | 25 ++++ tests/components/gcja5/test.rp2040.yaml | 25 ++++ .../components/globals/test.esp32-c3-idf.yaml | 28 ++++ tests/components/globals/test.esp32-c3.yaml | 28 ++++ tests/components/globals/test.esp32-idf.yaml | 28 ++++ tests/components/globals/test.esp32.yaml | 28 ++++ tests/components/globals/test.esp8266.yaml | 28 ++++ tests/components/globals/test.rp2040.yaml | 28 ++++ .../components/gp8403/test.esp32-c3-idf.yaml | 20 +++ tests/components/gp8403/test.esp32-c3.yaml | 20 +++ tests/components/gp8403/test.esp32-idf.yaml | 20 +++ tests/components/gp8403/test.esp32.yaml | 20 +++ tests/components/gp8403/test.esp8266.yaml | 20 +++ tests/components/gp8403/test.rp2040.yaml | 20 +++ tests/components/gpio/test.esp32-c3-idf.yaml | 14 ++ tests/components/gpio/test.esp32-c3.yaml | 14 ++ tests/components/gpio/test.esp32-idf.yaml | 14 ++ tests/components/gpio/test.esp32.yaml | 14 ++ tests/components/gpio/test.esp8266.yaml | 14 ++ tests/components/gpio/test.rp2040.yaml | 14 ++ tests/components/gps/test.esp32-c3.yaml | 14 ++ tests/components/gps/test.esp32.yaml | 14 ++ tests/components/gps/test.esp8266.yaml | 14 ++ tests/components/gps/test.rp2040.yaml | 14 ++ tests/components/graph/test.esp32-c3-idf.yaml | 25 ++++ tests/components/graph/test.esp32-c3.yaml | 25 ++++ tests/components/graph/test.esp32-idf.yaml | 25 ++++ tests/components/graph/test.esp32.yaml | 25 ++++ tests/components/graph/test.esp8266.yaml | 25 ++++ tests/components/graph/test.rp2040.yaml | 25 ++++ .../test.esp32-c3-idf.yaml | 120 ++++++++++++++++++ .../graphical_display_menu/test.esp32-c3.yaml | 120 ++++++++++++++++++ .../test.esp32-idf.yaml | 120 ++++++++++++++++++ .../graphical_display_menu/test.esp32.yaml | 120 ++++++++++++++++++ .../graphical_display_menu/test.esp8266.yaml | 120 ++++++++++++++++++ .../graphical_display_menu/test.rp2040.yaml | 120 ++++++++++++++++++ tests/components/gree/test.esp32-c3-idf.yaml | 8 ++ tests/components/gree/test.esp32-c3.yaml | 8 ++ tests/components/gree/test.esp32-idf.yaml | 8 ++ tests/components/gree/test.esp32.yaml | 8 ++ tests/components/gree/test.esp8266.yaml | 8 ++ .../grove_tb6612fng/test.esp32-c3-idf.yaml | 23 ++++ .../grove_tb6612fng/test.esp32-c3.yaml | 23 ++++ .../grove_tb6612fng/test.esp32-idf.yaml | 23 ++++ .../grove_tb6612fng/test.esp32.yaml | 23 ++++ .../grove_tb6612fng/test.esp8266.yaml | 23 ++++ .../grove_tb6612fng/test.rp2040.yaml | 23 ++++ .../growatt_solar/test.esp32-c3-idf.yaml | 62 +++++++++ .../growatt_solar/test.esp32-c3.yaml | 62 +++++++++ .../growatt_solar/test.esp32-idf.yaml | 62 +++++++++ .../components/growatt_solar/test.esp32.yaml | 62 +++++++++ .../growatt_solar/test.esp8266.yaml | 62 +++++++++ .../components/growatt_solar/test.rp2040.yaml | 62 +++++++++ tests/components/gt911/test.esp32-c3-idf.yaml | 24 ++++ tests/components/gt911/test.esp32-c3.yaml | 24 ++++ tests/components/gt911/test.esp32-idf.yaml | 24 ++++ tests/components/gt911/test.esp32.yaml | 24 ++++ tests/components/gt911/test.esp8266.yaml | 24 ++++ tests/components/gt911/test.rp2040.yaml | 24 ++++ 63 files changed, 2142 insertions(+) create mode 100644 tests/components/gcja5/test.esp32-c3-idf.yaml create mode 100644 tests/components/gcja5/test.esp32-c3.yaml create mode 100644 tests/components/gcja5/test.esp32-idf.yaml create mode 100644 tests/components/gcja5/test.esp32.yaml create mode 100644 tests/components/gcja5/test.esp8266.yaml create mode 100644 tests/components/gcja5/test.rp2040.yaml create mode 100644 tests/components/globals/test.esp32-c3-idf.yaml create mode 100644 tests/components/globals/test.esp32-c3.yaml create mode 100644 tests/components/globals/test.esp32-idf.yaml create mode 100644 tests/components/globals/test.esp32.yaml create mode 100644 tests/components/globals/test.esp8266.yaml create mode 100644 tests/components/globals/test.rp2040.yaml create mode 100644 tests/components/gp8403/test.esp32-c3-idf.yaml create mode 100644 tests/components/gp8403/test.esp32-c3.yaml create mode 100644 tests/components/gp8403/test.esp32-idf.yaml create mode 100644 tests/components/gp8403/test.esp32.yaml create mode 100644 tests/components/gp8403/test.esp8266.yaml create mode 100644 tests/components/gp8403/test.rp2040.yaml create mode 100644 tests/components/gpio/test.esp32-c3-idf.yaml create mode 100644 tests/components/gpio/test.esp32-c3.yaml create mode 100644 tests/components/gpio/test.esp32-idf.yaml create mode 100644 tests/components/gpio/test.esp32.yaml create mode 100644 tests/components/gpio/test.esp8266.yaml create mode 100644 tests/components/gpio/test.rp2040.yaml create mode 100644 tests/components/gps/test.esp32-c3.yaml create mode 100644 tests/components/gps/test.esp32.yaml create mode 100644 tests/components/gps/test.esp8266.yaml create mode 100644 tests/components/gps/test.rp2040.yaml create mode 100644 tests/components/graph/test.esp32-c3-idf.yaml create mode 100644 tests/components/graph/test.esp32-c3.yaml create mode 100644 tests/components/graph/test.esp32-idf.yaml create mode 100644 tests/components/graph/test.esp32.yaml create mode 100644 tests/components/graph/test.esp8266.yaml create mode 100644 tests/components/graph/test.rp2040.yaml create mode 100644 tests/components/graphical_display_menu/test.esp32-c3-idf.yaml create mode 100644 tests/components/graphical_display_menu/test.esp32-c3.yaml create mode 100644 tests/components/graphical_display_menu/test.esp32-idf.yaml create mode 100644 tests/components/graphical_display_menu/test.esp32.yaml create mode 100644 tests/components/graphical_display_menu/test.esp8266.yaml create mode 100644 tests/components/graphical_display_menu/test.rp2040.yaml create mode 100644 tests/components/gree/test.esp32-c3-idf.yaml create mode 100644 tests/components/gree/test.esp32-c3.yaml create mode 100644 tests/components/gree/test.esp32-idf.yaml create mode 100644 tests/components/gree/test.esp32.yaml create mode 100644 tests/components/gree/test.esp8266.yaml create mode 100644 tests/components/grove_tb6612fng/test.esp32-c3-idf.yaml create mode 100644 tests/components/grove_tb6612fng/test.esp32-c3.yaml create mode 100644 tests/components/grove_tb6612fng/test.esp32-idf.yaml create mode 100644 tests/components/grove_tb6612fng/test.esp32.yaml create mode 100644 tests/components/grove_tb6612fng/test.esp8266.yaml create mode 100644 tests/components/grove_tb6612fng/test.rp2040.yaml create mode 100644 tests/components/growatt_solar/test.esp32-c3-idf.yaml create mode 100644 tests/components/growatt_solar/test.esp32-c3.yaml create mode 100644 tests/components/growatt_solar/test.esp32-idf.yaml create mode 100644 tests/components/growatt_solar/test.esp32.yaml create mode 100644 tests/components/growatt_solar/test.esp8266.yaml create mode 100644 tests/components/growatt_solar/test.rp2040.yaml create mode 100644 tests/components/gt911/test.esp32-c3-idf.yaml create mode 100644 tests/components/gt911/test.esp32-c3.yaml create mode 100644 tests/components/gt911/test.esp32-idf.yaml create mode 100644 tests/components/gt911/test.esp32.yaml create mode 100644 tests/components/gt911/test.esp8266.yaml create mode 100644 tests/components/gt911/test.rp2040.yaml diff --git a/tests/components/gcja5/test.esp32-c3-idf.yaml b/tests/components/gcja5/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..ec8765be52 --- /dev/null +++ b/tests/components/gcja5/test.esp32-c3-idf.yaml @@ -0,0 +1,25 @@ +uart: + - id: uart_gcja5 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + parity: EVEN + +sensor: + - platform: gcja5 + pm_1_0: + name: "Particulate Matter <1.0µm Concentration" + pm_2_5: + name: "Particulate Matter <2.5µm Concentration" + pm_10_0: + name: "Particulate Matter <10.0µm Concentration" + pmc_0_5: + name: "PMC 0.5" + pmc_1_0: + name: "PMC 1.0" + pmc_2_5: + name: "PMC 2.5" + pmc_5_0: + name: "PMC 5.0" + pmc_10_0: + name: "PMC 10.0" diff --git a/tests/components/gcja5/test.esp32-c3.yaml b/tests/components/gcja5/test.esp32-c3.yaml new file mode 100644 index 0000000000..ec8765be52 --- /dev/null +++ b/tests/components/gcja5/test.esp32-c3.yaml @@ -0,0 +1,25 @@ +uart: + - id: uart_gcja5 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + parity: EVEN + +sensor: + - platform: gcja5 + pm_1_0: + name: "Particulate Matter <1.0µm Concentration" + pm_2_5: + name: "Particulate Matter <2.5µm Concentration" + pm_10_0: + name: "Particulate Matter <10.0µm Concentration" + pmc_0_5: + name: "PMC 0.5" + pmc_1_0: + name: "PMC 1.0" + pmc_2_5: + name: "PMC 2.5" + pmc_5_0: + name: "PMC 5.0" + pmc_10_0: + name: "PMC 10.0" diff --git a/tests/components/gcja5/test.esp32-idf.yaml b/tests/components/gcja5/test.esp32-idf.yaml new file mode 100644 index 0000000000..bc0f89eb9e --- /dev/null +++ b/tests/components/gcja5/test.esp32-idf.yaml @@ -0,0 +1,25 @@ +uart: + - id: uart_gcja5 + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + parity: EVEN + +sensor: + - platform: gcja5 + pm_1_0: + name: "Particulate Matter <1.0µm Concentration" + pm_2_5: + name: "Particulate Matter <2.5µm Concentration" + pm_10_0: + name: "Particulate Matter <10.0µm Concentration" + pmc_0_5: + name: "PMC 0.5" + pmc_1_0: + name: "PMC 1.0" + pmc_2_5: + name: "PMC 2.5" + pmc_5_0: + name: "PMC 5.0" + pmc_10_0: + name: "PMC 10.0" diff --git a/tests/components/gcja5/test.esp32.yaml b/tests/components/gcja5/test.esp32.yaml new file mode 100644 index 0000000000..bc0f89eb9e --- /dev/null +++ b/tests/components/gcja5/test.esp32.yaml @@ -0,0 +1,25 @@ +uart: + - id: uart_gcja5 + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + parity: EVEN + +sensor: + - platform: gcja5 + pm_1_0: + name: "Particulate Matter <1.0µm Concentration" + pm_2_5: + name: "Particulate Matter <2.5µm Concentration" + pm_10_0: + name: "Particulate Matter <10.0µm Concentration" + pmc_0_5: + name: "PMC 0.5" + pmc_1_0: + name: "PMC 1.0" + pmc_2_5: + name: "PMC 2.5" + pmc_5_0: + name: "PMC 5.0" + pmc_10_0: + name: "PMC 10.0" diff --git a/tests/components/gcja5/test.esp8266.yaml b/tests/components/gcja5/test.esp8266.yaml new file mode 100644 index 0000000000..ec8765be52 --- /dev/null +++ b/tests/components/gcja5/test.esp8266.yaml @@ -0,0 +1,25 @@ +uart: + - id: uart_gcja5 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + parity: EVEN + +sensor: + - platform: gcja5 + pm_1_0: + name: "Particulate Matter <1.0µm Concentration" + pm_2_5: + name: "Particulate Matter <2.5µm Concentration" + pm_10_0: + name: "Particulate Matter <10.0µm Concentration" + pmc_0_5: + name: "PMC 0.5" + pmc_1_0: + name: "PMC 1.0" + pmc_2_5: + name: "PMC 2.5" + pmc_5_0: + name: "PMC 5.0" + pmc_10_0: + name: "PMC 10.0" diff --git a/tests/components/gcja5/test.rp2040.yaml b/tests/components/gcja5/test.rp2040.yaml new file mode 100644 index 0000000000..ec8765be52 --- /dev/null +++ b/tests/components/gcja5/test.rp2040.yaml @@ -0,0 +1,25 @@ +uart: + - id: uart_gcja5 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + parity: EVEN + +sensor: + - platform: gcja5 + pm_1_0: + name: "Particulate Matter <1.0µm Concentration" + pm_2_5: + name: "Particulate Matter <2.5µm Concentration" + pm_10_0: + name: "Particulate Matter <10.0µm Concentration" + pmc_0_5: + name: "PMC 0.5" + pmc_1_0: + name: "PMC 1.0" + pmc_2_5: + name: "PMC 2.5" + pmc_5_0: + name: "PMC 5.0" + pmc_10_0: + name: "PMC 10.0" diff --git a/tests/components/globals/test.esp32-c3-idf.yaml b/tests/components/globals/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..224a91a270 --- /dev/null +++ b/tests/components/globals/test.esp32-c3-idf.yaml @@ -0,0 +1,28 @@ +esphome: + on_boot: + then: + - globals.set: + id: glob_int + value: "10" + +globals: + - id: glob_int + type: int + restore_value: true + initial_value: "0" + - id: glob_float + type: float + restore_value: true + initial_value: "0.0f" + - id: glob_bool + type: bool + restore_value: false + initial_value: "true" + - id: glob_string + type: std::string + restore_value: false + # initial_value: "" + - id: glob_bool_processed + type: bool + restore_value: false + initial_value: "false" diff --git a/tests/components/globals/test.esp32-c3.yaml b/tests/components/globals/test.esp32-c3.yaml new file mode 100644 index 0000000000..224a91a270 --- /dev/null +++ b/tests/components/globals/test.esp32-c3.yaml @@ -0,0 +1,28 @@ +esphome: + on_boot: + then: + - globals.set: + id: glob_int + value: "10" + +globals: + - id: glob_int + type: int + restore_value: true + initial_value: "0" + - id: glob_float + type: float + restore_value: true + initial_value: "0.0f" + - id: glob_bool + type: bool + restore_value: false + initial_value: "true" + - id: glob_string + type: std::string + restore_value: false + # initial_value: "" + - id: glob_bool_processed + type: bool + restore_value: false + initial_value: "false" diff --git a/tests/components/globals/test.esp32-idf.yaml b/tests/components/globals/test.esp32-idf.yaml new file mode 100644 index 0000000000..224a91a270 --- /dev/null +++ b/tests/components/globals/test.esp32-idf.yaml @@ -0,0 +1,28 @@ +esphome: + on_boot: + then: + - globals.set: + id: glob_int + value: "10" + +globals: + - id: glob_int + type: int + restore_value: true + initial_value: "0" + - id: glob_float + type: float + restore_value: true + initial_value: "0.0f" + - id: glob_bool + type: bool + restore_value: false + initial_value: "true" + - id: glob_string + type: std::string + restore_value: false + # initial_value: "" + - id: glob_bool_processed + type: bool + restore_value: false + initial_value: "false" diff --git a/tests/components/globals/test.esp32.yaml b/tests/components/globals/test.esp32.yaml new file mode 100644 index 0000000000..224a91a270 --- /dev/null +++ b/tests/components/globals/test.esp32.yaml @@ -0,0 +1,28 @@ +esphome: + on_boot: + then: + - globals.set: + id: glob_int + value: "10" + +globals: + - id: glob_int + type: int + restore_value: true + initial_value: "0" + - id: glob_float + type: float + restore_value: true + initial_value: "0.0f" + - id: glob_bool + type: bool + restore_value: false + initial_value: "true" + - id: glob_string + type: std::string + restore_value: false + # initial_value: "" + - id: glob_bool_processed + type: bool + restore_value: false + initial_value: "false" diff --git a/tests/components/globals/test.esp8266.yaml b/tests/components/globals/test.esp8266.yaml new file mode 100644 index 0000000000..224a91a270 --- /dev/null +++ b/tests/components/globals/test.esp8266.yaml @@ -0,0 +1,28 @@ +esphome: + on_boot: + then: + - globals.set: + id: glob_int + value: "10" + +globals: + - id: glob_int + type: int + restore_value: true + initial_value: "0" + - id: glob_float + type: float + restore_value: true + initial_value: "0.0f" + - id: glob_bool + type: bool + restore_value: false + initial_value: "true" + - id: glob_string + type: std::string + restore_value: false + # initial_value: "" + - id: glob_bool_processed + type: bool + restore_value: false + initial_value: "false" diff --git a/tests/components/globals/test.rp2040.yaml b/tests/components/globals/test.rp2040.yaml new file mode 100644 index 0000000000..224a91a270 --- /dev/null +++ b/tests/components/globals/test.rp2040.yaml @@ -0,0 +1,28 @@ +esphome: + on_boot: + then: + - globals.set: + id: glob_int + value: "10" + +globals: + - id: glob_int + type: int + restore_value: true + initial_value: "0" + - id: glob_float + type: float + restore_value: true + initial_value: "0.0f" + - id: glob_bool + type: bool + restore_value: false + initial_value: "true" + - id: glob_string + type: std::string + restore_value: false + # initial_value: "" + - id: glob_bool_processed + type: bool + restore_value: false + initial_value: "false" diff --git a/tests/components/gp8403/test.esp32-c3-idf.yaml b/tests/components/gp8403/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..fbc40b948b --- /dev/null +++ b/tests/components/gp8403/test.esp32-c3-idf.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_gp8403 + scl: 5 + sda: 4 + +gp8403: + - id: gp8403_5v + voltage: 5V + - id: gp8403_10v + voltage: 10V + +output: + - platform: gp8403 + id: gp8403_output_0 + gp8403_id: gp8403_5v + channel: 0 + - platform: gp8403 + gp8403_id: gp8403_10v + id: gp8403_output_1 + channel: 1 diff --git a/tests/components/gp8403/test.esp32-c3.yaml b/tests/components/gp8403/test.esp32-c3.yaml new file mode 100644 index 0000000000..fbc40b948b --- /dev/null +++ b/tests/components/gp8403/test.esp32-c3.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_gp8403 + scl: 5 + sda: 4 + +gp8403: + - id: gp8403_5v + voltage: 5V + - id: gp8403_10v + voltage: 10V + +output: + - platform: gp8403 + id: gp8403_output_0 + gp8403_id: gp8403_5v + channel: 0 + - platform: gp8403 + gp8403_id: gp8403_10v + id: gp8403_output_1 + channel: 1 diff --git a/tests/components/gp8403/test.esp32-idf.yaml b/tests/components/gp8403/test.esp32-idf.yaml new file mode 100644 index 0000000000..8470a303e1 --- /dev/null +++ b/tests/components/gp8403/test.esp32-idf.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_gp8403 + scl: 16 + sda: 17 + +gp8403: + - id: gp8403_5v + voltage: 5V + - id: gp8403_10v + voltage: 10V + +output: + - platform: gp8403 + id: gp8403_output_0 + gp8403_id: gp8403_5v + channel: 0 + - platform: gp8403 + gp8403_id: gp8403_10v + id: gp8403_output_1 + channel: 1 diff --git a/tests/components/gp8403/test.esp32.yaml b/tests/components/gp8403/test.esp32.yaml new file mode 100644 index 0000000000..8470a303e1 --- /dev/null +++ b/tests/components/gp8403/test.esp32.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_gp8403 + scl: 16 + sda: 17 + +gp8403: + - id: gp8403_5v + voltage: 5V + - id: gp8403_10v + voltage: 10V + +output: + - platform: gp8403 + id: gp8403_output_0 + gp8403_id: gp8403_5v + channel: 0 + - platform: gp8403 + gp8403_id: gp8403_10v + id: gp8403_output_1 + channel: 1 diff --git a/tests/components/gp8403/test.esp8266.yaml b/tests/components/gp8403/test.esp8266.yaml new file mode 100644 index 0000000000..fbc40b948b --- /dev/null +++ b/tests/components/gp8403/test.esp8266.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_gp8403 + scl: 5 + sda: 4 + +gp8403: + - id: gp8403_5v + voltage: 5V + - id: gp8403_10v + voltage: 10V + +output: + - platform: gp8403 + id: gp8403_output_0 + gp8403_id: gp8403_5v + channel: 0 + - platform: gp8403 + gp8403_id: gp8403_10v + id: gp8403_output_1 + channel: 1 diff --git a/tests/components/gp8403/test.rp2040.yaml b/tests/components/gp8403/test.rp2040.yaml new file mode 100644 index 0000000000..fbc40b948b --- /dev/null +++ b/tests/components/gp8403/test.rp2040.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_gp8403 + scl: 5 + sda: 4 + +gp8403: + - id: gp8403_5v + voltage: 5V + - id: gp8403_10v + voltage: 10V + +output: + - platform: gp8403 + id: gp8403_output_0 + gp8403_id: gp8403_5v + channel: 0 + - platform: gp8403 + gp8403_id: gp8403_10v + id: gp8403_output_1 + channel: 1 diff --git a/tests/components/gpio/test.esp32-c3-idf.yaml b/tests/components/gpio/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..3ca285117d --- /dev/null +++ b/tests/components/gpio/test.esp32-c3-idf.yaml @@ -0,0 +1,14 @@ +binary_sensor: + - platform: gpio + pin: 2 + id: gpio_binary_sensor + +output: + - platform: gpio + pin: 3 + id: gpio_output + +switch: + - platform: gpio + pin: 4 + id: gpio_switch diff --git a/tests/components/gpio/test.esp32-c3.yaml b/tests/components/gpio/test.esp32-c3.yaml new file mode 100644 index 0000000000..3ca285117d --- /dev/null +++ b/tests/components/gpio/test.esp32-c3.yaml @@ -0,0 +1,14 @@ +binary_sensor: + - platform: gpio + pin: 2 + id: gpio_binary_sensor + +output: + - platform: gpio + pin: 3 + id: gpio_output + +switch: + - platform: gpio + pin: 4 + id: gpio_switch diff --git a/tests/components/gpio/test.esp32-idf.yaml b/tests/components/gpio/test.esp32-idf.yaml new file mode 100644 index 0000000000..30dfa94b68 --- /dev/null +++ b/tests/components/gpio/test.esp32-idf.yaml @@ -0,0 +1,14 @@ +binary_sensor: + - platform: gpio + pin: 12 + id: gpio_binary_sensor + +output: + - platform: gpio + pin: 13 + id: gpio_output + +switch: + - platform: gpio + pin: 14 + id: gpio_switch diff --git a/tests/components/gpio/test.esp32.yaml b/tests/components/gpio/test.esp32.yaml new file mode 100644 index 0000000000..30dfa94b68 --- /dev/null +++ b/tests/components/gpio/test.esp32.yaml @@ -0,0 +1,14 @@ +binary_sensor: + - platform: gpio + pin: 12 + id: gpio_binary_sensor + +output: + - platform: gpio + pin: 13 + id: gpio_output + +switch: + - platform: gpio + pin: 14 + id: gpio_switch diff --git a/tests/components/gpio/test.esp8266.yaml b/tests/components/gpio/test.esp8266.yaml new file mode 100644 index 0000000000..30dfa94b68 --- /dev/null +++ b/tests/components/gpio/test.esp8266.yaml @@ -0,0 +1,14 @@ +binary_sensor: + - platform: gpio + pin: 12 + id: gpio_binary_sensor + +output: + - platform: gpio + pin: 13 + id: gpio_output + +switch: + - platform: gpio + pin: 14 + id: gpio_switch diff --git a/tests/components/gpio/test.rp2040.yaml b/tests/components/gpio/test.rp2040.yaml new file mode 100644 index 0000000000..3ca285117d --- /dev/null +++ b/tests/components/gpio/test.rp2040.yaml @@ -0,0 +1,14 @@ +binary_sensor: + - platform: gpio + pin: 2 + id: gpio_binary_sensor + +output: + - platform: gpio + pin: 3 + id: gpio_output + +switch: + - platform: gpio + pin: 4 + id: gpio_switch diff --git a/tests/components/gps/test.esp32-c3.yaml b/tests/components/gps/test.esp32-c3.yaml new file mode 100644 index 0000000000..031f45b873 --- /dev/null +++ b/tests/components/gps/test.esp32-c3.yaml @@ -0,0 +1,14 @@ +uart: + - id: uart_gps + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + parity: EVEN + +gps: + +time: + - platform: gps + on_time_sync: + then: + logger.log: "It's time!" diff --git a/tests/components/gps/test.esp32.yaml b/tests/components/gps/test.esp32.yaml new file mode 100644 index 0000000000..c4e4cf9f6f --- /dev/null +++ b/tests/components/gps/test.esp32.yaml @@ -0,0 +1,14 @@ +uart: + - id: uart_gps + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + parity: EVEN + +gps: + +time: + - platform: gps + on_time_sync: + then: + logger.log: "It's time!" diff --git a/tests/components/gps/test.esp8266.yaml b/tests/components/gps/test.esp8266.yaml new file mode 100644 index 0000000000..031f45b873 --- /dev/null +++ b/tests/components/gps/test.esp8266.yaml @@ -0,0 +1,14 @@ +uart: + - id: uart_gps + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + parity: EVEN + +gps: + +time: + - platform: gps + on_time_sync: + then: + logger.log: "It's time!" diff --git a/tests/components/gps/test.rp2040.yaml b/tests/components/gps/test.rp2040.yaml new file mode 100644 index 0000000000..031f45b873 --- /dev/null +++ b/tests/components/gps/test.rp2040.yaml @@ -0,0 +1,14 @@ +uart: + - id: uart_gps + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + parity: EVEN + +gps: + +time: + - platform: gps + on_time_sync: + then: + logger.log: "It's time!" diff --git a/tests/components/graph/test.esp32-c3-idf.yaml b/tests/components/graph/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..8ce40e84ac --- /dev/null +++ b/tests/components/graph/test.esp32-c3-idf.yaml @@ -0,0 +1,25 @@ +i2c: + - id: i2c_graph + scl: 5 + sda: 4 + +sensor: + - platform: template + id: some_sensor + +graph: + - id: some_graph + sensor: some_sensor + duration: 1h + width: 100 + height: 100 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 3 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); diff --git a/tests/components/graph/test.esp32-c3.yaml b/tests/components/graph/test.esp32-c3.yaml new file mode 100644 index 0000000000..8ce40e84ac --- /dev/null +++ b/tests/components/graph/test.esp32-c3.yaml @@ -0,0 +1,25 @@ +i2c: + - id: i2c_graph + scl: 5 + sda: 4 + +sensor: + - platform: template + id: some_sensor + +graph: + - id: some_graph + sensor: some_sensor + duration: 1h + width: 100 + height: 100 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 3 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); diff --git a/tests/components/graph/test.esp32-idf.yaml b/tests/components/graph/test.esp32-idf.yaml new file mode 100644 index 0000000000..8c0c0d4c9e --- /dev/null +++ b/tests/components/graph/test.esp32-idf.yaml @@ -0,0 +1,25 @@ +i2c: + - id: i2c_graph + scl: 16 + sda: 17 + +sensor: + - platform: template + id: some_sensor + +graph: + - id: some_graph + sensor: some_sensor + duration: 1h + width: 100 + height: 100 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 13 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); diff --git a/tests/components/graph/test.esp32.yaml b/tests/components/graph/test.esp32.yaml new file mode 100644 index 0000000000..8c0c0d4c9e --- /dev/null +++ b/tests/components/graph/test.esp32.yaml @@ -0,0 +1,25 @@ +i2c: + - id: i2c_graph + scl: 16 + sda: 17 + +sensor: + - platform: template + id: some_sensor + +graph: + - id: some_graph + sensor: some_sensor + duration: 1h + width: 100 + height: 100 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 13 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); diff --git a/tests/components/graph/test.esp8266.yaml b/tests/components/graph/test.esp8266.yaml new file mode 100644 index 0000000000..33318355d5 --- /dev/null +++ b/tests/components/graph/test.esp8266.yaml @@ -0,0 +1,25 @@ +i2c: + - id: i2c_graph + scl: 5 + sda: 4 + +sensor: + - platform: template + id: some_sensor + +graph: + - id: some_graph + sensor: some_sensor + duration: 1h + width: 100 + height: 100 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 13 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); diff --git a/tests/components/graph/test.rp2040.yaml b/tests/components/graph/test.rp2040.yaml new file mode 100644 index 0000000000..8ce40e84ac --- /dev/null +++ b/tests/components/graph/test.rp2040.yaml @@ -0,0 +1,25 @@ +i2c: + - id: i2c_graph + scl: 5 + sda: 4 + +sensor: + - platform: template + id: some_sensor + +graph: + - id: some_graph + sensor: some_sensor + duration: 1h + width: 100 + height: 100 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 3 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); diff --git a/tests/components/graphical_display_menu/test.esp32-c3-idf.yaml b/tests/components/graphical_display_menu/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..23acd4e4d9 --- /dev/null +++ b/tests/components/graphical_display_menu/test.esp32-c3-idf.yaml @@ -0,0 +1,120 @@ +i2c: + - id: i2c_graphical_display_menu + scl: 5 + sda: 4 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 3 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +font: + - file: "gfonts://Roboto" + id: roboto + size: 20 + +number: + - platform: template + id: test_number + min_value: 0 + step: 1 + max_value: 10 + optimistic: true + +select: + - platform: template + id: test_select + options: + - one + - two + optimistic: true + +switch: + - platform: template + id: test_switch + optimistic: true + +graphical_display_menu: + id: test_graphical_display_menu + display: ssd1306_display + font: roboto + active: false + mode: rotary + on_enter: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "root enter");' + on_leave: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "root leave");' + items: + - type: back + text: "Back" + - type: label + - type: menu + text: "Submenu 1" + items: + - type: back + text: "Back" + - type: menu + text: "Submenu 21" + items: + - type: back + text: "Back" + - type: command + text: "Show Main" + on_value: + then: + - display_menu.show_main: test_graphical_display_menu + - type: select + text: "Enum Item" + immediate_edit: true + select: test_select + on_enter: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "select enter: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_leave: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "select leave: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_value: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "select value: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + - type: number + text: "Number" + number: test_number + on_enter: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "number enter: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_leave: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "number leave: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_value: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "number value: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + - type: command + text: "Hide" + on_value: + then: + - display_menu.hide: test_graphical_display_menu + - type: switch + text: "Switch" + switch: test_switch + on_text: "Bright" + off_text: "Dark" + immediate_edit: false + on_value: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "switch value: %s", it->get_value_text().c_str());' + - type: custom + text: !lambda 'return "Custom";' + value_lambda: 'return "Val";' + on_next: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "custom next: %s", it->get_text().c_str());' + on_prev: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "custom prev: %s", it->get_text().c_str());' diff --git a/tests/components/graphical_display_menu/test.esp32-c3.yaml b/tests/components/graphical_display_menu/test.esp32-c3.yaml new file mode 100644 index 0000000000..23acd4e4d9 --- /dev/null +++ b/tests/components/graphical_display_menu/test.esp32-c3.yaml @@ -0,0 +1,120 @@ +i2c: + - id: i2c_graphical_display_menu + scl: 5 + sda: 4 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 3 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +font: + - file: "gfonts://Roboto" + id: roboto + size: 20 + +number: + - platform: template + id: test_number + min_value: 0 + step: 1 + max_value: 10 + optimistic: true + +select: + - platform: template + id: test_select + options: + - one + - two + optimistic: true + +switch: + - platform: template + id: test_switch + optimistic: true + +graphical_display_menu: + id: test_graphical_display_menu + display: ssd1306_display + font: roboto + active: false + mode: rotary + on_enter: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "root enter");' + on_leave: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "root leave");' + items: + - type: back + text: "Back" + - type: label + - type: menu + text: "Submenu 1" + items: + - type: back + text: "Back" + - type: menu + text: "Submenu 21" + items: + - type: back + text: "Back" + - type: command + text: "Show Main" + on_value: + then: + - display_menu.show_main: test_graphical_display_menu + - type: select + text: "Enum Item" + immediate_edit: true + select: test_select + on_enter: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "select enter: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_leave: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "select leave: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_value: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "select value: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + - type: number + text: "Number" + number: test_number + on_enter: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "number enter: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_leave: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "number leave: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_value: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "number value: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + - type: command + text: "Hide" + on_value: + then: + - display_menu.hide: test_graphical_display_menu + - type: switch + text: "Switch" + switch: test_switch + on_text: "Bright" + off_text: "Dark" + immediate_edit: false + on_value: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "switch value: %s", it->get_value_text().c_str());' + - type: custom + text: !lambda 'return "Custom";' + value_lambda: 'return "Val";' + on_next: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "custom next: %s", it->get_text().c_str());' + on_prev: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "custom prev: %s", it->get_text().c_str());' diff --git a/tests/components/graphical_display_menu/test.esp32-idf.yaml b/tests/components/graphical_display_menu/test.esp32-idf.yaml new file mode 100644 index 0000000000..a0897536d7 --- /dev/null +++ b/tests/components/graphical_display_menu/test.esp32-idf.yaml @@ -0,0 +1,120 @@ +i2c: + - id: i2c_graphical_display_menu + scl: 16 + sda: 17 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 13 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +font: + - file: "gfonts://Roboto" + id: roboto + size: 20 + +number: + - platform: template + id: test_number + min_value: 0 + step: 1 + max_value: 10 + optimistic: true + +select: + - platform: template + id: test_select + options: + - one + - two + optimistic: true + +switch: + - platform: template + id: test_switch + optimistic: true + +graphical_display_menu: + id: test_graphical_display_menu + display: ssd1306_display + font: roboto + active: false + mode: rotary + on_enter: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "root enter");' + on_leave: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "root leave");' + items: + - type: back + text: "Back" + - type: label + - type: menu + text: "Submenu 1" + items: + - type: back + text: "Back" + - type: menu + text: "Submenu 21" + items: + - type: back + text: "Back" + - type: command + text: "Show Main" + on_value: + then: + - display_menu.show_main: test_graphical_display_menu + - type: select + text: "Enum Item" + immediate_edit: true + select: test_select + on_enter: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "select enter: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_leave: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "select leave: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_value: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "select value: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + - type: number + text: "Number" + number: test_number + on_enter: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "number enter: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_leave: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "number leave: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_value: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "number value: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + - type: command + text: "Hide" + on_value: + then: + - display_menu.hide: test_graphical_display_menu + - type: switch + text: "Switch" + switch: test_switch + on_text: "Bright" + off_text: "Dark" + immediate_edit: false + on_value: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "switch value: %s", it->get_value_text().c_str());' + - type: custom + text: !lambda 'return "Custom";' + value_lambda: 'return "Val";' + on_next: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "custom next: %s", it->get_text().c_str());' + on_prev: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "custom prev: %s", it->get_text().c_str());' diff --git a/tests/components/graphical_display_menu/test.esp32.yaml b/tests/components/graphical_display_menu/test.esp32.yaml new file mode 100644 index 0000000000..a0897536d7 --- /dev/null +++ b/tests/components/graphical_display_menu/test.esp32.yaml @@ -0,0 +1,120 @@ +i2c: + - id: i2c_graphical_display_menu + scl: 16 + sda: 17 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 13 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +font: + - file: "gfonts://Roboto" + id: roboto + size: 20 + +number: + - platform: template + id: test_number + min_value: 0 + step: 1 + max_value: 10 + optimistic: true + +select: + - platform: template + id: test_select + options: + - one + - two + optimistic: true + +switch: + - platform: template + id: test_switch + optimistic: true + +graphical_display_menu: + id: test_graphical_display_menu + display: ssd1306_display + font: roboto + active: false + mode: rotary + on_enter: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "root enter");' + on_leave: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "root leave");' + items: + - type: back + text: "Back" + - type: label + - type: menu + text: "Submenu 1" + items: + - type: back + text: "Back" + - type: menu + text: "Submenu 21" + items: + - type: back + text: "Back" + - type: command + text: "Show Main" + on_value: + then: + - display_menu.show_main: test_graphical_display_menu + - type: select + text: "Enum Item" + immediate_edit: true + select: test_select + on_enter: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "select enter: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_leave: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "select leave: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_value: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "select value: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + - type: number + text: "Number" + number: test_number + on_enter: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "number enter: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_leave: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "number leave: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_value: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "number value: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + - type: command + text: "Hide" + on_value: + then: + - display_menu.hide: test_graphical_display_menu + - type: switch + text: "Switch" + switch: test_switch + on_text: "Bright" + off_text: "Dark" + immediate_edit: false + on_value: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "switch value: %s", it->get_value_text().c_str());' + - type: custom + text: !lambda 'return "Custom";' + value_lambda: 'return "Val";' + on_next: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "custom next: %s", it->get_text().c_str());' + on_prev: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "custom prev: %s", it->get_text().c_str());' diff --git a/tests/components/graphical_display_menu/test.esp8266.yaml b/tests/components/graphical_display_menu/test.esp8266.yaml new file mode 100644 index 0000000000..28c1a7298d --- /dev/null +++ b/tests/components/graphical_display_menu/test.esp8266.yaml @@ -0,0 +1,120 @@ +i2c: + - id: i2c_graphical_display_menu + scl: 5 + sda: 4 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 13 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +font: + - file: "gfonts://Roboto" + id: roboto + size: 20 + +number: + - platform: template + id: test_number + min_value: 0 + step: 1 + max_value: 10 + optimistic: true + +select: + - platform: template + id: test_select + options: + - one + - two + optimistic: true + +switch: + - platform: template + id: test_switch + optimistic: true + +graphical_display_menu: + id: test_graphical_display_menu + display: ssd1306_display + font: roboto + active: false + mode: rotary + on_enter: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "root enter");' + on_leave: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "root leave");' + items: + - type: back + text: "Back" + - type: label + - type: menu + text: "Submenu 1" + items: + - type: back + text: "Back" + - type: menu + text: "Submenu 21" + items: + - type: back + text: "Back" + - type: command + text: "Show Main" + on_value: + then: + - display_menu.show_main: test_graphical_display_menu + - type: select + text: "Enum Item" + immediate_edit: true + select: test_select + on_enter: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "select enter: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_leave: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "select leave: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_value: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "select value: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + - type: number + text: "Number" + number: test_number + on_enter: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "number enter: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_leave: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "number leave: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_value: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "number value: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + - type: command + text: "Hide" + on_value: + then: + - display_menu.hide: test_graphical_display_menu + - type: switch + text: "Switch" + switch: test_switch + on_text: "Bright" + off_text: "Dark" + immediate_edit: false + on_value: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "switch value: %s", it->get_value_text().c_str());' + - type: custom + text: !lambda 'return "Custom";' + value_lambda: 'return "Val";' + on_next: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "custom next: %s", it->get_text().c_str());' + on_prev: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "custom prev: %s", it->get_text().c_str());' diff --git a/tests/components/graphical_display_menu/test.rp2040.yaml b/tests/components/graphical_display_menu/test.rp2040.yaml new file mode 100644 index 0000000000..23acd4e4d9 --- /dev/null +++ b/tests/components/graphical_display_menu/test.rp2040.yaml @@ -0,0 +1,120 @@ +i2c: + - id: i2c_graphical_display_menu + scl: 5 + sda: 4 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 3 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +font: + - file: "gfonts://Roboto" + id: roboto + size: 20 + +number: + - platform: template + id: test_number + min_value: 0 + step: 1 + max_value: 10 + optimistic: true + +select: + - platform: template + id: test_select + options: + - one + - two + optimistic: true + +switch: + - platform: template + id: test_switch + optimistic: true + +graphical_display_menu: + id: test_graphical_display_menu + display: ssd1306_display + font: roboto + active: false + mode: rotary + on_enter: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "root enter");' + on_leave: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "root leave");' + items: + - type: back + text: "Back" + - type: label + - type: menu + text: "Submenu 1" + items: + - type: back + text: "Back" + - type: menu + text: "Submenu 21" + items: + - type: back + text: "Back" + - type: command + text: "Show Main" + on_value: + then: + - display_menu.show_main: test_graphical_display_menu + - type: select + text: "Enum Item" + immediate_edit: true + select: test_select + on_enter: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "select enter: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_leave: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "select leave: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_value: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "select value: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + - type: number + text: "Number" + number: test_number + on_enter: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "number enter: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_leave: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "number leave: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_value: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "number value: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + - type: command + text: "Hide" + on_value: + then: + - display_menu.hide: test_graphical_display_menu + - type: switch + text: "Switch" + switch: test_switch + on_text: "Bright" + off_text: "Dark" + immediate_edit: false + on_value: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "switch value: %s", it->get_value_text().c_str());' + - type: custom + text: !lambda 'return "Custom";' + value_lambda: 'return "Val";' + on_next: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "custom next: %s", it->get_text().c_str());' + on_prev: + then: + lambda: 'ESP_LOGI("graphical_display_menu", "custom prev: %s", it->get_text().c_str());' diff --git a/tests/components/gree/test.esp32-c3-idf.yaml b/tests/components/gree/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..91491d7e16 --- /dev/null +++ b/tests/components/gree/test.esp32-c3-idf.yaml @@ -0,0 +1,8 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +climate: + - platform: gree + name: GREE + model: generic diff --git a/tests/components/gree/test.esp32-c3.yaml b/tests/components/gree/test.esp32-c3.yaml new file mode 100644 index 0000000000..91491d7e16 --- /dev/null +++ b/tests/components/gree/test.esp32-c3.yaml @@ -0,0 +1,8 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +climate: + - platform: gree + name: GREE + model: generic diff --git a/tests/components/gree/test.esp32-idf.yaml b/tests/components/gree/test.esp32-idf.yaml new file mode 100644 index 0000000000..91491d7e16 --- /dev/null +++ b/tests/components/gree/test.esp32-idf.yaml @@ -0,0 +1,8 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +climate: + - platform: gree + name: GREE + model: generic diff --git a/tests/components/gree/test.esp32.yaml b/tests/components/gree/test.esp32.yaml new file mode 100644 index 0000000000..91491d7e16 --- /dev/null +++ b/tests/components/gree/test.esp32.yaml @@ -0,0 +1,8 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +climate: + - platform: gree + name: GREE + model: generic diff --git a/tests/components/gree/test.esp8266.yaml b/tests/components/gree/test.esp8266.yaml new file mode 100644 index 0000000000..d0542973ce --- /dev/null +++ b/tests/components/gree/test.esp8266.yaml @@ -0,0 +1,8 @@ +remote_transmitter: + pin: 5 + carrier_duty_percent: 50% + +climate: + - platform: gree + name: GREE + model: generic diff --git a/tests/components/grove_tb6612fng/test.esp32-c3-idf.yaml b/tests/components/grove_tb6612fng/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..ef6dff6539 --- /dev/null +++ b/tests/components/grove_tb6612fng/test.esp32-c3-idf.yaml @@ -0,0 +1,23 @@ +esphome: + on_boot: + then: + - grove_tb6612fng.run: + channel: 1 + speed: 255 + direction: BACKWARD + id: test_motor + - grove_tb6612fng.stop: + channel: 1 + id: test_motor + - grove_tb6612fng.break: + channel: 1 + id: test_motor + +i2c: + - id: i2c_grove_tb6612fng + scl: 5 + sda: 4 + +grove_tb6612fng: + id: test_motor + address: 0x14 diff --git a/tests/components/grove_tb6612fng/test.esp32-c3.yaml b/tests/components/grove_tb6612fng/test.esp32-c3.yaml new file mode 100644 index 0000000000..ef6dff6539 --- /dev/null +++ b/tests/components/grove_tb6612fng/test.esp32-c3.yaml @@ -0,0 +1,23 @@ +esphome: + on_boot: + then: + - grove_tb6612fng.run: + channel: 1 + speed: 255 + direction: BACKWARD + id: test_motor + - grove_tb6612fng.stop: + channel: 1 + id: test_motor + - grove_tb6612fng.break: + channel: 1 + id: test_motor + +i2c: + - id: i2c_grove_tb6612fng + scl: 5 + sda: 4 + +grove_tb6612fng: + id: test_motor + address: 0x14 diff --git a/tests/components/grove_tb6612fng/test.esp32-idf.yaml b/tests/components/grove_tb6612fng/test.esp32-idf.yaml new file mode 100644 index 0000000000..3271fb754f --- /dev/null +++ b/tests/components/grove_tb6612fng/test.esp32-idf.yaml @@ -0,0 +1,23 @@ +esphome: + on_boot: + then: + - grove_tb6612fng.run: + channel: 1 + speed: 255 + direction: BACKWARD + id: test_motor + - grove_tb6612fng.stop: + channel: 1 + id: test_motor + - grove_tb6612fng.break: + channel: 1 + id: test_motor + +i2c: + - id: i2c_grove_tb6612fng + scl: 16 + sda: 17 + +grove_tb6612fng: + id: test_motor + address: 0x14 diff --git a/tests/components/grove_tb6612fng/test.esp32.yaml b/tests/components/grove_tb6612fng/test.esp32.yaml new file mode 100644 index 0000000000..3271fb754f --- /dev/null +++ b/tests/components/grove_tb6612fng/test.esp32.yaml @@ -0,0 +1,23 @@ +esphome: + on_boot: + then: + - grove_tb6612fng.run: + channel: 1 + speed: 255 + direction: BACKWARD + id: test_motor + - grove_tb6612fng.stop: + channel: 1 + id: test_motor + - grove_tb6612fng.break: + channel: 1 + id: test_motor + +i2c: + - id: i2c_grove_tb6612fng + scl: 16 + sda: 17 + +grove_tb6612fng: + id: test_motor + address: 0x14 diff --git a/tests/components/grove_tb6612fng/test.esp8266.yaml b/tests/components/grove_tb6612fng/test.esp8266.yaml new file mode 100644 index 0000000000..ef6dff6539 --- /dev/null +++ b/tests/components/grove_tb6612fng/test.esp8266.yaml @@ -0,0 +1,23 @@ +esphome: + on_boot: + then: + - grove_tb6612fng.run: + channel: 1 + speed: 255 + direction: BACKWARD + id: test_motor + - grove_tb6612fng.stop: + channel: 1 + id: test_motor + - grove_tb6612fng.break: + channel: 1 + id: test_motor + +i2c: + - id: i2c_grove_tb6612fng + scl: 5 + sda: 4 + +grove_tb6612fng: + id: test_motor + address: 0x14 diff --git a/tests/components/grove_tb6612fng/test.rp2040.yaml b/tests/components/grove_tb6612fng/test.rp2040.yaml new file mode 100644 index 0000000000..ef6dff6539 --- /dev/null +++ b/tests/components/grove_tb6612fng/test.rp2040.yaml @@ -0,0 +1,23 @@ +esphome: + on_boot: + then: + - grove_tb6612fng.run: + channel: 1 + speed: 255 + direction: BACKWARD + id: test_motor + - grove_tb6612fng.stop: + channel: 1 + id: test_motor + - grove_tb6612fng.break: + channel: 1 + id: test_motor + +i2c: + - id: i2c_grove_tb6612fng + scl: 5 + sda: 4 + +grove_tb6612fng: + id: test_motor + address: 0x14 diff --git a/tests/components/growatt_solar/test.esp32-c3-idf.yaml b/tests/components/growatt_solar/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..3b5e2e4ce4 --- /dev/null +++ b/tests/components/growatt_solar/test.esp32-c3-idf.yaml @@ -0,0 +1,62 @@ +uart: + - id: uart_growatt_solar + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +modbus: + flow_control_pin: 3 + +sensor: + - platform: growatt_solar + update_interval: 10s + protocol_version: RTU + inverter_status: + name: Growatt Status Code + phase_a: + voltage: + name: Growatt Voltage Phase A + current: + name: Growatt Current Phase A + active_power: + name: Growatt Power Phase A + phase_b: + voltage: + name: Growatt Voltage Phase B + current: + name: Growatt Current Phase B + active_power: + name: Growatt Power Phase B + phase_c: + voltage: + name: Growatt Voltage Phase C + current: + name: Growatt Current Phase C + active_power: + name: Growatt Power Phase C + pv1: + voltage: + name: Growatt PV1 Voltage + current: + name: Growatt PV1 Current + active_power: + name: Growatt PV1 Active Power + pv2: + voltage: + name: Growatt PV2 Voltage + current: + name: Growatt PV2 Current + active_power: + name: Growatt PV2 Active Power + active_power: + name: Growatt Grid Active Power + pv_active_power: + name: Growatt PV Active Power + frequency: + name: Growatt Frequency + energy_production_day: + name: Growatt Today's Generation + total_energy_production: + name: Growatt Total Energy Production + inverter_module_temp: + name: Growatt Inverter Module Temp diff --git a/tests/components/growatt_solar/test.esp32-c3.yaml b/tests/components/growatt_solar/test.esp32-c3.yaml new file mode 100644 index 0000000000..3b5e2e4ce4 --- /dev/null +++ b/tests/components/growatt_solar/test.esp32-c3.yaml @@ -0,0 +1,62 @@ +uart: + - id: uart_growatt_solar + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +modbus: + flow_control_pin: 3 + +sensor: + - platform: growatt_solar + update_interval: 10s + protocol_version: RTU + inverter_status: + name: Growatt Status Code + phase_a: + voltage: + name: Growatt Voltage Phase A + current: + name: Growatt Current Phase A + active_power: + name: Growatt Power Phase A + phase_b: + voltage: + name: Growatt Voltage Phase B + current: + name: Growatt Current Phase B + active_power: + name: Growatt Power Phase B + phase_c: + voltage: + name: Growatt Voltage Phase C + current: + name: Growatt Current Phase C + active_power: + name: Growatt Power Phase C + pv1: + voltage: + name: Growatt PV1 Voltage + current: + name: Growatt PV1 Current + active_power: + name: Growatt PV1 Active Power + pv2: + voltage: + name: Growatt PV2 Voltage + current: + name: Growatt PV2 Current + active_power: + name: Growatt PV2 Active Power + active_power: + name: Growatt Grid Active Power + pv_active_power: + name: Growatt PV Active Power + frequency: + name: Growatt Frequency + energy_production_day: + name: Growatt Today's Generation + total_energy_production: + name: Growatt Total Energy Production + inverter_module_temp: + name: Growatt Inverter Module Temp diff --git a/tests/components/growatt_solar/test.esp32-idf.yaml b/tests/components/growatt_solar/test.esp32-idf.yaml new file mode 100644 index 0000000000..a0670fdbd6 --- /dev/null +++ b/tests/components/growatt_solar/test.esp32-idf.yaml @@ -0,0 +1,62 @@ +uart: + - id: uart_growatt_solar + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +modbus: + flow_control_pin: 13 + +sensor: + - platform: growatt_solar + update_interval: 10s + protocol_version: RTU + inverter_status: + name: Growatt Status Code + phase_a: + voltage: + name: Growatt Voltage Phase A + current: + name: Growatt Current Phase A + active_power: + name: Growatt Power Phase A + phase_b: + voltage: + name: Growatt Voltage Phase B + current: + name: Growatt Current Phase B + active_power: + name: Growatt Power Phase B + phase_c: + voltage: + name: Growatt Voltage Phase C + current: + name: Growatt Current Phase C + active_power: + name: Growatt Power Phase C + pv1: + voltage: + name: Growatt PV1 Voltage + current: + name: Growatt PV1 Current + active_power: + name: Growatt PV1 Active Power + pv2: + voltage: + name: Growatt PV2 Voltage + current: + name: Growatt PV2 Current + active_power: + name: Growatt PV2 Active Power + active_power: + name: Growatt Grid Active Power + pv_active_power: + name: Growatt PV Active Power + frequency: + name: Growatt Frequency + energy_production_day: + name: Growatt Today's Generation + total_energy_production: + name: Growatt Total Energy Production + inverter_module_temp: + name: Growatt Inverter Module Temp diff --git a/tests/components/growatt_solar/test.esp32.yaml b/tests/components/growatt_solar/test.esp32.yaml new file mode 100644 index 0000000000..a0670fdbd6 --- /dev/null +++ b/tests/components/growatt_solar/test.esp32.yaml @@ -0,0 +1,62 @@ +uart: + - id: uart_growatt_solar + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +modbus: + flow_control_pin: 13 + +sensor: + - platform: growatt_solar + update_interval: 10s + protocol_version: RTU + inverter_status: + name: Growatt Status Code + phase_a: + voltage: + name: Growatt Voltage Phase A + current: + name: Growatt Current Phase A + active_power: + name: Growatt Power Phase A + phase_b: + voltage: + name: Growatt Voltage Phase B + current: + name: Growatt Current Phase B + active_power: + name: Growatt Power Phase B + phase_c: + voltage: + name: Growatt Voltage Phase C + current: + name: Growatt Current Phase C + active_power: + name: Growatt Power Phase C + pv1: + voltage: + name: Growatt PV1 Voltage + current: + name: Growatt PV1 Current + active_power: + name: Growatt PV1 Active Power + pv2: + voltage: + name: Growatt PV2 Voltage + current: + name: Growatt PV2 Current + active_power: + name: Growatt PV2 Active Power + active_power: + name: Growatt Grid Active Power + pv_active_power: + name: Growatt PV Active Power + frequency: + name: Growatt Frequency + energy_production_day: + name: Growatt Today's Generation + total_energy_production: + name: Growatt Total Energy Production + inverter_module_temp: + name: Growatt Inverter Module Temp diff --git a/tests/components/growatt_solar/test.esp8266.yaml b/tests/components/growatt_solar/test.esp8266.yaml new file mode 100644 index 0000000000..fed27ffda1 --- /dev/null +++ b/tests/components/growatt_solar/test.esp8266.yaml @@ -0,0 +1,62 @@ +uart: + - id: uart_growatt_solar + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +modbus: + flow_control_pin: 13 + +sensor: + - platform: growatt_solar + update_interval: 10s + protocol_version: RTU + inverter_status: + name: Growatt Status Code + phase_a: + voltage: + name: Growatt Voltage Phase A + current: + name: Growatt Current Phase A + active_power: + name: Growatt Power Phase A + phase_b: + voltage: + name: Growatt Voltage Phase B + current: + name: Growatt Current Phase B + active_power: + name: Growatt Power Phase B + phase_c: + voltage: + name: Growatt Voltage Phase C + current: + name: Growatt Current Phase C + active_power: + name: Growatt Power Phase C + pv1: + voltage: + name: Growatt PV1 Voltage + current: + name: Growatt PV1 Current + active_power: + name: Growatt PV1 Active Power + pv2: + voltage: + name: Growatt PV2 Voltage + current: + name: Growatt PV2 Current + active_power: + name: Growatt PV2 Active Power + active_power: + name: Growatt Grid Active Power + pv_active_power: + name: Growatt PV Active Power + frequency: + name: Growatt Frequency + energy_production_day: + name: Growatt Today's Generation + total_energy_production: + name: Growatt Total Energy Production + inverter_module_temp: + name: Growatt Inverter Module Temp diff --git a/tests/components/growatt_solar/test.rp2040.yaml b/tests/components/growatt_solar/test.rp2040.yaml new file mode 100644 index 0000000000..3b5e2e4ce4 --- /dev/null +++ b/tests/components/growatt_solar/test.rp2040.yaml @@ -0,0 +1,62 @@ +uart: + - id: uart_growatt_solar + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +modbus: + flow_control_pin: 3 + +sensor: + - platform: growatt_solar + update_interval: 10s + protocol_version: RTU + inverter_status: + name: Growatt Status Code + phase_a: + voltage: + name: Growatt Voltage Phase A + current: + name: Growatt Current Phase A + active_power: + name: Growatt Power Phase A + phase_b: + voltage: + name: Growatt Voltage Phase B + current: + name: Growatt Current Phase B + active_power: + name: Growatt Power Phase B + phase_c: + voltage: + name: Growatt Voltage Phase C + current: + name: Growatt Current Phase C + active_power: + name: Growatt Power Phase C + pv1: + voltage: + name: Growatt PV1 Voltage + current: + name: Growatt PV1 Current + active_power: + name: Growatt PV1 Active Power + pv2: + voltage: + name: Growatt PV2 Voltage + current: + name: Growatt PV2 Current + active_power: + name: Growatt PV2 Active Power + active_power: + name: Growatt Grid Active Power + pv_active_power: + name: Growatt PV Active Power + frequency: + name: Growatt Frequency + energy_production_day: + name: Growatt Today's Generation + total_energy_production: + name: Growatt Total Energy Production + inverter_module_temp: + name: Growatt Inverter Module Temp diff --git a/tests/components/gt911/test.esp32-c3-idf.yaml b/tests/components/gt911/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..43f7ac5902 --- /dev/null +++ b/tests/components/gt911/test.esp32-c3-idf.yaml @@ -0,0 +1,24 @@ +i2c: + - id: i2c_gt911 + scl: 5 + sda: 4 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 3 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: gt911 + display: ssd1306_display + interrupt_pin: 6 + +binary_sensor: + - platform: gt911 + id: touch_key_911 + index: 0 diff --git a/tests/components/gt911/test.esp32-c3.yaml b/tests/components/gt911/test.esp32-c3.yaml new file mode 100644 index 0000000000..43f7ac5902 --- /dev/null +++ b/tests/components/gt911/test.esp32-c3.yaml @@ -0,0 +1,24 @@ +i2c: + - id: i2c_gt911 + scl: 5 + sda: 4 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 3 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: gt911 + display: ssd1306_display + interrupt_pin: 6 + +binary_sensor: + - platform: gt911 + id: touch_key_911 + index: 0 diff --git a/tests/components/gt911/test.esp32-idf.yaml b/tests/components/gt911/test.esp32-idf.yaml new file mode 100644 index 0000000000..a47f7bf260 --- /dev/null +++ b/tests/components/gt911/test.esp32-idf.yaml @@ -0,0 +1,24 @@ +i2c: + - id: i2c_gt911 + scl: 16 + sda: 17 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 13 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: gt911 + display: ssd1306_display + interrupt_pin: 14 + +binary_sensor: + - platform: gt911 + id: touch_key_911 + index: 0 diff --git a/tests/components/gt911/test.esp32.yaml b/tests/components/gt911/test.esp32.yaml new file mode 100644 index 0000000000..a47f7bf260 --- /dev/null +++ b/tests/components/gt911/test.esp32.yaml @@ -0,0 +1,24 @@ +i2c: + - id: i2c_gt911 + scl: 16 + sda: 17 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 13 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: gt911 + display: ssd1306_display + interrupt_pin: 14 + +binary_sensor: + - platform: gt911 + id: touch_key_911 + index: 0 diff --git a/tests/components/gt911/test.esp8266.yaml b/tests/components/gt911/test.esp8266.yaml new file mode 100644 index 0000000000..8b76eff29e --- /dev/null +++ b/tests/components/gt911/test.esp8266.yaml @@ -0,0 +1,24 @@ +i2c: + - id: i2c_gt911 + scl: 5 + sda: 4 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 13 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: gt911 + display: ssd1306_display + interrupt_pin: 12 + +binary_sensor: + - platform: gt911 + id: touch_key_911 + index: 0 diff --git a/tests/components/gt911/test.rp2040.yaml b/tests/components/gt911/test.rp2040.yaml new file mode 100644 index 0000000000..43f7ac5902 --- /dev/null +++ b/tests/components/gt911/test.rp2040.yaml @@ -0,0 +1,24 @@ +i2c: + - id: i2c_gt911 + scl: 5 + sda: 4 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 3 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: gt911 + display: ssd1306_display + interrupt_pin: 6 + +binary_sensor: + - platform: gt911 + id: touch_key_911 + index: 0 From ca6020e11a801b65f334c268a3638ae73b629f66 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Tue, 26 Mar 2024 20:22:54 -0500 Subject: [PATCH 1165/2101] Add some components to the new testing framework (K) (#6186) --- .../key_collector/test.esp32-c3-idf.yaml | 28 +++++++++++++++++++ .../key_collector/test.esp32-c3.yaml | 28 +++++++++++++++++++ .../key_collector/test.esp32-idf.yaml | 28 +++++++++++++++++++ .../components/key_collector/test.esp32.yaml | 28 +++++++++++++++++++ .../key_collector/test.esp8266.yaml | 28 +++++++++++++++++++ .../components/key_collector/test.rp2040.yaml | 28 +++++++++++++++++++ .../kmeteriso/test.esp32-c3-idf.yaml | 12 ++++++++ tests/components/kmeteriso/test.esp32-c3.yaml | 12 ++++++++ .../components/kmeteriso/test.esp32-idf.yaml | 12 ++++++++ tests/components/kmeteriso/test.esp32.yaml | 12 ++++++++ tests/components/kmeteriso/test.esp8266.yaml | 12 ++++++++ tests/components/kmeteriso/test.rp2040.yaml | 12 ++++++++ .../components/kuntze/test.esp32-c3-idf.yaml | 15 ++++++++++ tests/components/kuntze/test.esp32-c3.yaml | 15 ++++++++++ tests/components/kuntze/test.esp32-idf.yaml | 15 ++++++++++ tests/components/kuntze/test.esp32.yaml | 15 ++++++++++ tests/components/kuntze/test.esp8266.yaml | 15 ++++++++++ tests/components/kuntze/test.rp2040.yaml | 15 ++++++++++ 18 files changed, 330 insertions(+) create mode 100644 tests/components/key_collector/test.esp32-c3-idf.yaml create mode 100644 tests/components/key_collector/test.esp32-c3.yaml create mode 100644 tests/components/key_collector/test.esp32-idf.yaml create mode 100644 tests/components/key_collector/test.esp32.yaml create mode 100644 tests/components/key_collector/test.esp8266.yaml create mode 100644 tests/components/key_collector/test.rp2040.yaml create mode 100644 tests/components/kmeteriso/test.esp32-c3-idf.yaml create mode 100644 tests/components/kmeteriso/test.esp32-c3.yaml create mode 100644 tests/components/kmeteriso/test.esp32-idf.yaml create mode 100644 tests/components/kmeteriso/test.esp32.yaml create mode 100644 tests/components/kmeteriso/test.esp8266.yaml create mode 100644 tests/components/kmeteriso/test.rp2040.yaml create mode 100644 tests/components/kuntze/test.esp32-c3-idf.yaml create mode 100644 tests/components/kuntze/test.esp32-c3.yaml create mode 100644 tests/components/kuntze/test.esp32-idf.yaml create mode 100644 tests/components/kuntze/test.esp32.yaml create mode 100644 tests/components/kuntze/test.esp8266.yaml create mode 100644 tests/components/kuntze/test.rp2040.yaml diff --git a/tests/components/key_collector/test.esp32-c3-idf.yaml b/tests/components/key_collector/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..a186d4fa23 --- /dev/null +++ b/tests/components/key_collector/test.esp32-c3-idf.yaml @@ -0,0 +1,28 @@ +matrix_keypad: + id: keypad + rows: + - pin: 1 + - pin: 2 + columns: + - pin: 3 + - pin: 4 + keys: "1234" + has_pulldowns: true + +key_collector: + - id: reader + source_id: keypad + min_length: 4 + max_length: 4 + on_progress: + - logger.log: + format: "input progress: '%s', started by '%c'" + args: [ 'x.c_str()', "(start == 0 ? '~' : start)" ] + on_result: + - logger.log: + format: "input result: '%s', started by '%c', ended by '%c'" + args: [ 'x.c_str()', "(start == 0 ? '~' : start)", "(end == 0 ? '~' : end)" ] + on_timeout: + - logger.log: + format: "input timeout: '%s', started by '%c'" + args: [ 'x.c_str()', "(start == 0 ? '~' : start)" ] diff --git a/tests/components/key_collector/test.esp32-c3.yaml b/tests/components/key_collector/test.esp32-c3.yaml new file mode 100644 index 0000000000..a186d4fa23 --- /dev/null +++ b/tests/components/key_collector/test.esp32-c3.yaml @@ -0,0 +1,28 @@ +matrix_keypad: + id: keypad + rows: + - pin: 1 + - pin: 2 + columns: + - pin: 3 + - pin: 4 + keys: "1234" + has_pulldowns: true + +key_collector: + - id: reader + source_id: keypad + min_length: 4 + max_length: 4 + on_progress: + - logger.log: + format: "input progress: '%s', started by '%c'" + args: [ 'x.c_str()', "(start == 0 ? '~' : start)" ] + on_result: + - logger.log: + format: "input result: '%s', started by '%c', ended by '%c'" + args: [ 'x.c_str()', "(start == 0 ? '~' : start)", "(end == 0 ? '~' : end)" ] + on_timeout: + - logger.log: + format: "input timeout: '%s', started by '%c'" + args: [ 'x.c_str()', "(start == 0 ? '~' : start)" ] diff --git a/tests/components/key_collector/test.esp32-idf.yaml b/tests/components/key_collector/test.esp32-idf.yaml new file mode 100644 index 0000000000..d357b33279 --- /dev/null +++ b/tests/components/key_collector/test.esp32-idf.yaml @@ -0,0 +1,28 @@ +matrix_keypad: + id: keypad + rows: + - pin: 12 + - pin: 13 + columns: + - pin: 14 + - pin: 15 + keys: "1234" + has_pulldowns: true + +key_collector: + - id: reader + source_id: keypad + min_length: 4 + max_length: 4 + on_progress: + - logger.log: + format: "input progress: '%s', started by '%c'" + args: [ 'x.c_str()', "(start == 0 ? '~' : start)" ] + on_result: + - logger.log: + format: "input result: '%s', started by '%c', ended by '%c'" + args: [ 'x.c_str()', "(start == 0 ? '~' : start)", "(end == 0 ? '~' : end)" ] + on_timeout: + - logger.log: + format: "input timeout: '%s', started by '%c'" + args: [ 'x.c_str()', "(start == 0 ? '~' : start)" ] diff --git a/tests/components/key_collector/test.esp32.yaml b/tests/components/key_collector/test.esp32.yaml new file mode 100644 index 0000000000..d357b33279 --- /dev/null +++ b/tests/components/key_collector/test.esp32.yaml @@ -0,0 +1,28 @@ +matrix_keypad: + id: keypad + rows: + - pin: 12 + - pin: 13 + columns: + - pin: 14 + - pin: 15 + keys: "1234" + has_pulldowns: true + +key_collector: + - id: reader + source_id: keypad + min_length: 4 + max_length: 4 + on_progress: + - logger.log: + format: "input progress: '%s', started by '%c'" + args: [ 'x.c_str()', "(start == 0 ? '~' : start)" ] + on_result: + - logger.log: + format: "input result: '%s', started by '%c', ended by '%c'" + args: [ 'x.c_str()', "(start == 0 ? '~' : start)", "(end == 0 ? '~' : end)" ] + on_timeout: + - logger.log: + format: "input timeout: '%s', started by '%c'" + args: [ 'x.c_str()', "(start == 0 ? '~' : start)" ] diff --git a/tests/components/key_collector/test.esp8266.yaml b/tests/components/key_collector/test.esp8266.yaml new file mode 100644 index 0000000000..d357b33279 --- /dev/null +++ b/tests/components/key_collector/test.esp8266.yaml @@ -0,0 +1,28 @@ +matrix_keypad: + id: keypad + rows: + - pin: 12 + - pin: 13 + columns: + - pin: 14 + - pin: 15 + keys: "1234" + has_pulldowns: true + +key_collector: + - id: reader + source_id: keypad + min_length: 4 + max_length: 4 + on_progress: + - logger.log: + format: "input progress: '%s', started by '%c'" + args: [ 'x.c_str()', "(start == 0 ? '~' : start)" ] + on_result: + - logger.log: + format: "input result: '%s', started by '%c', ended by '%c'" + args: [ 'x.c_str()', "(start == 0 ? '~' : start)", "(end == 0 ? '~' : end)" ] + on_timeout: + - logger.log: + format: "input timeout: '%s', started by '%c'" + args: [ 'x.c_str()', "(start == 0 ? '~' : start)" ] diff --git a/tests/components/key_collector/test.rp2040.yaml b/tests/components/key_collector/test.rp2040.yaml new file mode 100644 index 0000000000..a186d4fa23 --- /dev/null +++ b/tests/components/key_collector/test.rp2040.yaml @@ -0,0 +1,28 @@ +matrix_keypad: + id: keypad + rows: + - pin: 1 + - pin: 2 + columns: + - pin: 3 + - pin: 4 + keys: "1234" + has_pulldowns: true + +key_collector: + - id: reader + source_id: keypad + min_length: 4 + max_length: 4 + on_progress: + - logger.log: + format: "input progress: '%s', started by '%c'" + args: [ 'x.c_str()', "(start == 0 ? '~' : start)" ] + on_result: + - logger.log: + format: "input result: '%s', started by '%c', ended by '%c'" + args: [ 'x.c_str()', "(start == 0 ? '~' : start)", "(end == 0 ? '~' : end)" ] + on_timeout: + - logger.log: + format: "input timeout: '%s', started by '%c'" + args: [ 'x.c_str()', "(start == 0 ? '~' : start)" ] diff --git a/tests/components/kmeteriso/test.esp32-c3-idf.yaml b/tests/components/kmeteriso/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..7780cfea32 --- /dev/null +++ b/tests/components/kmeteriso/test.esp32-c3-idf.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_kmeteriso + scl: 5 + sda: 4 + +sensor: + - platform: kmeteriso + temperature: + name: Outside Temperature + internal_temperature: + name: Internal Temperature + update_interval: 15s diff --git a/tests/components/kmeteriso/test.esp32-c3.yaml b/tests/components/kmeteriso/test.esp32-c3.yaml new file mode 100644 index 0000000000..7780cfea32 --- /dev/null +++ b/tests/components/kmeteriso/test.esp32-c3.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_kmeteriso + scl: 5 + sda: 4 + +sensor: + - platform: kmeteriso + temperature: + name: Outside Temperature + internal_temperature: + name: Internal Temperature + update_interval: 15s diff --git a/tests/components/kmeteriso/test.esp32-idf.yaml b/tests/components/kmeteriso/test.esp32-idf.yaml new file mode 100644 index 0000000000..2c375dda31 --- /dev/null +++ b/tests/components/kmeteriso/test.esp32-idf.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_kmeteriso + scl: 16 + sda: 17 + +sensor: + - platform: kmeteriso + temperature: + name: Outside Temperature + internal_temperature: + name: Internal Temperature + update_interval: 15s diff --git a/tests/components/kmeteriso/test.esp32.yaml b/tests/components/kmeteriso/test.esp32.yaml new file mode 100644 index 0000000000..2c375dda31 --- /dev/null +++ b/tests/components/kmeteriso/test.esp32.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_kmeteriso + scl: 16 + sda: 17 + +sensor: + - platform: kmeteriso + temperature: + name: Outside Temperature + internal_temperature: + name: Internal Temperature + update_interval: 15s diff --git a/tests/components/kmeteriso/test.esp8266.yaml b/tests/components/kmeteriso/test.esp8266.yaml new file mode 100644 index 0000000000..7780cfea32 --- /dev/null +++ b/tests/components/kmeteriso/test.esp8266.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_kmeteriso + scl: 5 + sda: 4 + +sensor: + - platform: kmeteriso + temperature: + name: Outside Temperature + internal_temperature: + name: Internal Temperature + update_interval: 15s diff --git a/tests/components/kmeteriso/test.rp2040.yaml b/tests/components/kmeteriso/test.rp2040.yaml new file mode 100644 index 0000000000..7780cfea32 --- /dev/null +++ b/tests/components/kmeteriso/test.rp2040.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_kmeteriso + scl: 5 + sda: 4 + +sensor: + - platform: kmeteriso + temperature: + name: Outside Temperature + internal_temperature: + name: Internal Temperature + update_interval: 15s diff --git a/tests/components/kuntze/test.esp32-c3-idf.yaml b/tests/components/kuntze/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..08278c3c82 --- /dev/null +++ b/tests/components/kuntze/test.esp32-c3-idf.yaml @@ -0,0 +1,15 @@ +uart: + - id: uart_kuntze + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +modbus: + flow_control_pin: 3 + +sensor: + - platform: kuntze + ph: + name: Kuntze pH + temperature: + name: Kuntze temperature diff --git a/tests/components/kuntze/test.esp32-c3.yaml b/tests/components/kuntze/test.esp32-c3.yaml new file mode 100644 index 0000000000..08278c3c82 --- /dev/null +++ b/tests/components/kuntze/test.esp32-c3.yaml @@ -0,0 +1,15 @@ +uart: + - id: uart_kuntze + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +modbus: + flow_control_pin: 3 + +sensor: + - platform: kuntze + ph: + name: Kuntze pH + temperature: + name: Kuntze temperature diff --git a/tests/components/kuntze/test.esp32-idf.yaml b/tests/components/kuntze/test.esp32-idf.yaml new file mode 100644 index 0000000000..6b6c638971 --- /dev/null +++ b/tests/components/kuntze/test.esp32-idf.yaml @@ -0,0 +1,15 @@ +uart: + - id: uart_kuntze + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +modbus: + flow_control_pin: 13 + +sensor: + - platform: kuntze + ph: + name: Kuntze pH + temperature: + name: Kuntze temperature diff --git a/tests/components/kuntze/test.esp32.yaml b/tests/components/kuntze/test.esp32.yaml new file mode 100644 index 0000000000..6b6c638971 --- /dev/null +++ b/tests/components/kuntze/test.esp32.yaml @@ -0,0 +1,15 @@ +uart: + - id: uart_kuntze + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +modbus: + flow_control_pin: 13 + +sensor: + - platform: kuntze + ph: + name: Kuntze pH + temperature: + name: Kuntze temperature diff --git a/tests/components/kuntze/test.esp8266.yaml b/tests/components/kuntze/test.esp8266.yaml new file mode 100644 index 0000000000..eba6cddc2d --- /dev/null +++ b/tests/components/kuntze/test.esp8266.yaml @@ -0,0 +1,15 @@ +uart: + - id: uart_kuntze + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +modbus: + flow_control_pin: 13 + +sensor: + - platform: kuntze + ph: + name: Kuntze pH + temperature: + name: Kuntze temperature diff --git a/tests/components/kuntze/test.rp2040.yaml b/tests/components/kuntze/test.rp2040.yaml new file mode 100644 index 0000000000..08278c3c82 --- /dev/null +++ b/tests/components/kuntze/test.rp2040.yaml @@ -0,0 +1,15 @@ +uart: + - id: uart_kuntze + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +modbus: + flow_control_pin: 3 + +sensor: + - platform: kuntze + ph: + name: Kuntze pH + temperature: + name: Kuntze temperature From 9779989f674a19e1475a31728accd5e10438d434 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Tue, 26 Mar 2024 20:24:32 -0500 Subject: [PATCH 1166/2101] Add some components to the new testing framework (N) (#6210) --- .../components/neopixelbus/test.esp32-c3.yaml | 19 ++++++ tests/components/neopixelbus/test.esp32.yaml | 17 ++++++ .../components/neopixelbus/test.esp8266.yaml | 17 ++++++ .../components/network/test.esp32-c3-idf.yaml | 6 ++ tests/components/network/test.esp32-c3.yaml | 6 ++ tests/components/network/test.esp32-idf.yaml | 6 ++ tests/components/network/test.esp32.yaml | 6 ++ tests/components/network/test.esp8266.yaml | 6 ++ tests/components/network/test.rp2040.yaml | 6 ++ .../components/nextion/test.esp32-c3-idf.yaml | 60 +++++++++++++++++++ tests/components/nextion/test.esp32-c3.yaml | 60 +++++++++++++++++++ tests/components/nextion/test.esp32-idf.yaml | 60 +++++++++++++++++++ tests/components/nextion/test.esp32.yaml | 60 +++++++++++++++++++ tests/components/nextion/test.esp8266.yaml | 60 +++++++++++++++++++ tests/components/nextion/test.rp2040.yaml | 55 +++++++++++++++++ .../components/noblex/test.esp32-c3-idf.yaml | 20 +++++++ tests/components/noblex/test.esp32-c3.yaml | 20 +++++++ tests/components/noblex/test.esp32-idf.yaml | 20 +++++++ tests/components/noblex/test.esp32.yaml | 20 +++++++ tests/components/noblex/test.esp8266.yaml | 20 +++++++ tests/components/ntc/test.esp32-c3.yaml | 26 ++++++++ tests/components/ntc/test.esp32-idf.yaml | 26 ++++++++ tests/components/ntc/test.esp32-s2.yaml | 26 ++++++++ tests/components/ntc/test.esp32-s3.yaml | 26 ++++++++ tests/components/ntc/test.esp32.yaml | 26 ++++++++ tests/components/ntc/test.esp8266.yaml | 25 ++++++++ tests/components/ntc/test.rp2040.yaml | 25 ++++++++ 27 files changed, 724 insertions(+) create mode 100644 tests/components/neopixelbus/test.esp32-c3.yaml create mode 100644 tests/components/neopixelbus/test.esp32.yaml create mode 100644 tests/components/neopixelbus/test.esp8266.yaml create mode 100644 tests/components/network/test.esp32-c3-idf.yaml create mode 100644 tests/components/network/test.esp32-c3.yaml create mode 100644 tests/components/network/test.esp32-idf.yaml create mode 100644 tests/components/network/test.esp32.yaml create mode 100644 tests/components/network/test.esp8266.yaml create mode 100644 tests/components/network/test.rp2040.yaml create mode 100644 tests/components/nextion/test.esp32-c3-idf.yaml create mode 100644 tests/components/nextion/test.esp32-c3.yaml create mode 100644 tests/components/nextion/test.esp32-idf.yaml create mode 100644 tests/components/nextion/test.esp32.yaml create mode 100644 tests/components/nextion/test.esp8266.yaml create mode 100644 tests/components/nextion/test.rp2040.yaml create mode 100644 tests/components/noblex/test.esp32-c3-idf.yaml create mode 100644 tests/components/noblex/test.esp32-c3.yaml create mode 100644 tests/components/noblex/test.esp32-idf.yaml create mode 100644 tests/components/noblex/test.esp32.yaml create mode 100644 tests/components/noblex/test.esp8266.yaml create mode 100644 tests/components/ntc/test.esp32-c3.yaml create mode 100644 tests/components/ntc/test.esp32-idf.yaml create mode 100644 tests/components/ntc/test.esp32-s2.yaml create mode 100644 tests/components/ntc/test.esp32-s3.yaml create mode 100644 tests/components/ntc/test.esp32.yaml create mode 100644 tests/components/ntc/test.esp8266.yaml create mode 100644 tests/components/ntc/test.rp2040.yaml diff --git a/tests/components/neopixelbus/test.esp32-c3.yaml b/tests/components/neopixelbus/test.esp32-c3.yaml new file mode 100644 index 0000000000..f2b53ab1e9 --- /dev/null +++ b/tests/components/neopixelbus/test.esp32-c3.yaml @@ -0,0 +1,19 @@ +light: + - platform: neopixelbus + id: addr3 + name: Neopixelbus Light + gamma_correct: 2.8 + color_correct: [0.0, 0.0, 0.0, 0.0] + default_transition_length: 10s + effects: + - addressable_flicker: + name: Flicker Effect With Custom Values + update_interval: 16ms + intensity: 5% + type: GRBW + variant: SK6812 + method: + type: esp32_rmt + channel: 0 + num_leds: 5 + pin: 4 diff --git a/tests/components/neopixelbus/test.esp32.yaml b/tests/components/neopixelbus/test.esp32.yaml new file mode 100644 index 0000000000..fd468586e0 --- /dev/null +++ b/tests/components/neopixelbus/test.esp32.yaml @@ -0,0 +1,17 @@ +light: + - platform: neopixelbus + id: addr3 + name: Neopixelbus Light + gamma_correct: 2.8 + color_correct: [0.0, 0.0, 0.0, 0.0] + default_transition_length: 10s + effects: + - addressable_flicker: + name: Flicker Effect With Custom Values + update_interval: 16ms + intensity: 5% + type: GRBW + variant: SK6812 + method: ESP32_I2S_0 + num_leds: 5 + pin: 4 diff --git a/tests/components/neopixelbus/test.esp8266.yaml b/tests/components/neopixelbus/test.esp8266.yaml new file mode 100644 index 0000000000..2c1f16a38c --- /dev/null +++ b/tests/components/neopixelbus/test.esp8266.yaml @@ -0,0 +1,17 @@ +light: + - platform: neopixelbus + id: addr3 + name: Neopixelbus Light + gamma_correct: 2.8 + color_correct: [0.0, 0.0, 0.0, 0.0] + default_transition_length: 10s + effects: + - addressable_flicker: + name: Flicker Effect With Custom Values + update_interval: 16ms + intensity: 5% + type: GRBW + variant: SK6812 + method: esp8266_uart + num_leds: 5 + pin: 2 diff --git a/tests/components/network/test.esp32-c3-idf.yaml b/tests/components/network/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..147afd1e81 --- /dev/null +++ b/tests/components/network/test.esp32-c3-idf.yaml @@ -0,0 +1,6 @@ +wifi: + ssid: MySSID + password: password1 + +network: + enable_ipv6: true diff --git a/tests/components/network/test.esp32-c3.yaml b/tests/components/network/test.esp32-c3.yaml new file mode 100644 index 0000000000..147afd1e81 --- /dev/null +++ b/tests/components/network/test.esp32-c3.yaml @@ -0,0 +1,6 @@ +wifi: + ssid: MySSID + password: password1 + +network: + enable_ipv6: true diff --git a/tests/components/network/test.esp32-idf.yaml b/tests/components/network/test.esp32-idf.yaml new file mode 100644 index 0000000000..147afd1e81 --- /dev/null +++ b/tests/components/network/test.esp32-idf.yaml @@ -0,0 +1,6 @@ +wifi: + ssid: MySSID + password: password1 + +network: + enable_ipv6: true diff --git a/tests/components/network/test.esp32.yaml b/tests/components/network/test.esp32.yaml new file mode 100644 index 0000000000..147afd1e81 --- /dev/null +++ b/tests/components/network/test.esp32.yaml @@ -0,0 +1,6 @@ +wifi: + ssid: MySSID + password: password1 + +network: + enable_ipv6: true diff --git a/tests/components/network/test.esp8266.yaml b/tests/components/network/test.esp8266.yaml new file mode 100644 index 0000000000..147afd1e81 --- /dev/null +++ b/tests/components/network/test.esp8266.yaml @@ -0,0 +1,6 @@ +wifi: + ssid: MySSID + password: password1 + +network: + enable_ipv6: true diff --git a/tests/components/network/test.rp2040.yaml b/tests/components/network/test.rp2040.yaml new file mode 100644 index 0000000000..147afd1e81 --- /dev/null +++ b/tests/components/network/test.rp2040.yaml @@ -0,0 +1,6 @@ +wifi: + ssid: MySSID + password: password1 + +network: + enable_ipv6: true diff --git a/tests/components/nextion/test.esp32-c3-idf.yaml b/tests/components/nextion/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..5881d6e165 --- /dev/null +++ b/tests/components/nextion/test.esp32-c3-idf.yaml @@ -0,0 +1,60 @@ +wifi: + ssid: MySSID + password: password1 + +uart: + - id: uart_nextion + tx_pin: 4 + rx_pin: 5 + baud_rate: 115200 + +binary_sensor: + - platform: nextion + page_id: 0 + component_id: 2 + name: Nextion Touch Component + - platform: nextion + id: r0_sensor + name: R0 Sensor + component_name: page0.r0 + +sensor: + - platform: nextion + id: testnumber + name: testnumber + variable_name: testnumber + - platform: nextion + id: testwave + name: testwave + component_id: 2 + wave_channel_id: 1 + +switch: + - platform: nextion + id: r0 + name: R0 Switch + component_name: page0.r0 + +text_sensor: + - platform: nextion + name: text0 + id: text0 + update_interval: 4s + component_name: text0 + +display: + - platform: nextion + tft_url: http://esphome.io/default35.tft + 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);' diff --git a/tests/components/nextion/test.esp32-c3.yaml b/tests/components/nextion/test.esp32-c3.yaml new file mode 100644 index 0000000000..5881d6e165 --- /dev/null +++ b/tests/components/nextion/test.esp32-c3.yaml @@ -0,0 +1,60 @@ +wifi: + ssid: MySSID + password: password1 + +uart: + - id: uart_nextion + tx_pin: 4 + rx_pin: 5 + baud_rate: 115200 + +binary_sensor: + - platform: nextion + page_id: 0 + component_id: 2 + name: Nextion Touch Component + - platform: nextion + id: r0_sensor + name: R0 Sensor + component_name: page0.r0 + +sensor: + - platform: nextion + id: testnumber + name: testnumber + variable_name: testnumber + - platform: nextion + id: testwave + name: testwave + component_id: 2 + wave_channel_id: 1 + +switch: + - platform: nextion + id: r0 + name: R0 Switch + component_name: page0.r0 + +text_sensor: + - platform: nextion + name: text0 + id: text0 + update_interval: 4s + component_name: text0 + +display: + - platform: nextion + tft_url: http://esphome.io/default35.tft + 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);' diff --git a/tests/components/nextion/test.esp32-idf.yaml b/tests/components/nextion/test.esp32-idf.yaml new file mode 100644 index 0000000000..27568ebc2a --- /dev/null +++ b/tests/components/nextion/test.esp32-idf.yaml @@ -0,0 +1,60 @@ +wifi: + ssid: MySSID + password: password1 + +uart: + - id: uart_nextion + tx_pin: 17 + rx_pin: 16 + baud_rate: 115200 + +binary_sensor: + - platform: nextion + page_id: 0 + component_id: 2 + name: Nextion Touch Component + - platform: nextion + id: r0_sensor + name: R0 Sensor + component_name: page0.r0 + +sensor: + - platform: nextion + id: testnumber + name: testnumber + variable_name: testnumber + - platform: nextion + id: testwave + name: testwave + component_id: 2 + wave_channel_id: 1 + +switch: + - platform: nextion + id: r0 + name: R0 Switch + component_name: page0.r0 + +text_sensor: + - platform: nextion + name: text0 + id: text0 + update_interval: 4s + component_name: text0 + +display: + - platform: nextion + tft_url: http://esphome.io/default35.tft + 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);' diff --git a/tests/components/nextion/test.esp32.yaml b/tests/components/nextion/test.esp32.yaml new file mode 100644 index 0000000000..27568ebc2a --- /dev/null +++ b/tests/components/nextion/test.esp32.yaml @@ -0,0 +1,60 @@ +wifi: + ssid: MySSID + password: password1 + +uart: + - id: uart_nextion + tx_pin: 17 + rx_pin: 16 + baud_rate: 115200 + +binary_sensor: + - platform: nextion + page_id: 0 + component_id: 2 + name: Nextion Touch Component + - platform: nextion + id: r0_sensor + name: R0 Sensor + component_name: page0.r0 + +sensor: + - platform: nextion + id: testnumber + name: testnumber + variable_name: testnumber + - platform: nextion + id: testwave + name: testwave + component_id: 2 + wave_channel_id: 1 + +switch: + - platform: nextion + id: r0 + name: R0 Switch + component_name: page0.r0 + +text_sensor: + - platform: nextion + name: text0 + id: text0 + update_interval: 4s + component_name: text0 + +display: + - platform: nextion + tft_url: http://esphome.io/default35.tft + 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);' diff --git a/tests/components/nextion/test.esp8266.yaml b/tests/components/nextion/test.esp8266.yaml new file mode 100644 index 0000000000..5881d6e165 --- /dev/null +++ b/tests/components/nextion/test.esp8266.yaml @@ -0,0 +1,60 @@ +wifi: + ssid: MySSID + password: password1 + +uart: + - id: uart_nextion + tx_pin: 4 + rx_pin: 5 + baud_rate: 115200 + +binary_sensor: + - platform: nextion + page_id: 0 + component_id: 2 + name: Nextion Touch Component + - platform: nextion + id: r0_sensor + name: R0 Sensor + component_name: page0.r0 + +sensor: + - platform: nextion + id: testnumber + name: testnumber + variable_name: testnumber + - platform: nextion + id: testwave + name: testwave + component_id: 2 + wave_channel_id: 1 + +switch: + - platform: nextion + id: r0 + name: R0 Switch + component_name: page0.r0 + +text_sensor: + - platform: nextion + name: text0 + id: text0 + update_interval: 4s + component_name: text0 + +display: + - platform: nextion + tft_url: http://esphome.io/default35.tft + 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);' diff --git a/tests/components/nextion/test.rp2040.yaml b/tests/components/nextion/test.rp2040.yaml new file mode 100644 index 0000000000..a1c5848ce6 --- /dev/null +++ b/tests/components/nextion/test.rp2040.yaml @@ -0,0 +1,55 @@ +uart: + - id: uart_nextion + tx_pin: 4 + rx_pin: 5 + baud_rate: 115200 + +binary_sensor: + - platform: nextion + page_id: 0 + component_id: 2 + name: Nextion Touch Component + - platform: nextion + id: r0_sensor + name: R0 Sensor + component_name: page0.r0 + +sensor: + - platform: nextion + id: testnumber + name: testnumber + variable_name: testnumber + - platform: nextion + id: testwave + name: testwave + component_id: 2 + wave_channel_id: 1 + +switch: + - platform: nextion + id: r0 + name: R0 Switch + component_name: page0.r0 + +text_sensor: + - platform: nextion + name: text0 + id: text0 + update_interval: 4s + component_name: text0 + +display: + - platform: nextion + 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);' diff --git a/tests/components/noblex/test.esp32-c3-idf.yaml b/tests/components/noblex/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..f5e471a9a7 --- /dev/null +++ b/tests/components/noblex/test.esp32-c3-idf.yaml @@ -0,0 +1,20 @@ +remote_receiver: + id: rcvr + pin: 4 + dump: all + +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +sensor: + - platform: template + id: noblex_ac_sensor + lambda: "return 21;" + +climate: + - platform: noblex + name: AC Living + id: noblex_ac + sensor: noblex_ac_sensor + receiver_id: rcvr diff --git a/tests/components/noblex/test.esp32-c3.yaml b/tests/components/noblex/test.esp32-c3.yaml new file mode 100644 index 0000000000..f5e471a9a7 --- /dev/null +++ b/tests/components/noblex/test.esp32-c3.yaml @@ -0,0 +1,20 @@ +remote_receiver: + id: rcvr + pin: 4 + dump: all + +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +sensor: + - platform: template + id: noblex_ac_sensor + lambda: "return 21;" + +climate: + - platform: noblex + name: AC Living + id: noblex_ac + sensor: noblex_ac_sensor + receiver_id: rcvr diff --git a/tests/components/noblex/test.esp32-idf.yaml b/tests/components/noblex/test.esp32-idf.yaml new file mode 100644 index 0000000000..f5e471a9a7 --- /dev/null +++ b/tests/components/noblex/test.esp32-idf.yaml @@ -0,0 +1,20 @@ +remote_receiver: + id: rcvr + pin: 4 + dump: all + +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +sensor: + - platform: template + id: noblex_ac_sensor + lambda: "return 21;" + +climate: + - platform: noblex + name: AC Living + id: noblex_ac + sensor: noblex_ac_sensor + receiver_id: rcvr diff --git a/tests/components/noblex/test.esp32.yaml b/tests/components/noblex/test.esp32.yaml new file mode 100644 index 0000000000..f5e471a9a7 --- /dev/null +++ b/tests/components/noblex/test.esp32.yaml @@ -0,0 +1,20 @@ +remote_receiver: + id: rcvr + pin: 4 + dump: all + +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +sensor: + - platform: template + id: noblex_ac_sensor + lambda: "return 21;" + +climate: + - platform: noblex + name: AC Living + id: noblex_ac + sensor: noblex_ac_sensor + receiver_id: rcvr diff --git a/tests/components/noblex/test.esp8266.yaml b/tests/components/noblex/test.esp8266.yaml new file mode 100644 index 0000000000..f5e471a9a7 --- /dev/null +++ b/tests/components/noblex/test.esp8266.yaml @@ -0,0 +1,20 @@ +remote_receiver: + id: rcvr + pin: 4 + dump: all + +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +sensor: + - platform: template + id: noblex_ac_sensor + lambda: "return 21;" + +climate: + - platform: noblex + name: AC Living + id: noblex_ac + sensor: noblex_ac_sensor + receiver_id: rcvr diff --git a/tests/components/ntc/test.esp32-c3.yaml b/tests/components/ntc/test.esp32-c3.yaml new file mode 100644 index 0000000000..c0edb83d9d --- /dev/null +++ b/tests/components/ntc/test.esp32-c3.yaml @@ -0,0 +1,26 @@ +sensor: + - platform: adc + id: my_sensor + pin: 4 + attenuation: 11db + - platform: resistance + sensor: my_sensor + configuration: DOWNSTREAM + resistor: 10kΩ + reference_voltage: 3.3V + name: Resistance + id: resist + - platform: ntc + sensor: resist + name: NTC Sensor + calibration: + b_constant: 3950 + reference_resistance: 10k + reference_temperature: 25°C + - platform: ntc + sensor: resist + name: NTC Sensor2 + calibration: + - 10.0kOhm -> 25°C + - 27.219kOhm -> 0°C + - 14.674kOhm -> 15°C diff --git a/tests/components/ntc/test.esp32-idf.yaml b/tests/components/ntc/test.esp32-idf.yaml new file mode 100644 index 0000000000..3e0e901b6e --- /dev/null +++ b/tests/components/ntc/test.esp32-idf.yaml @@ -0,0 +1,26 @@ +sensor: + - platform: adc + id: my_sensor + pin: 32 + attenuation: 11db + - platform: resistance + sensor: my_sensor + configuration: DOWNSTREAM + resistor: 10kΩ + reference_voltage: 3.3V + name: Resistance + id: resist + - platform: ntc + sensor: resist + name: NTC Sensor + calibration: + b_constant: 3950 + reference_resistance: 10k + reference_temperature: 25°C + - platform: ntc + sensor: resist + name: NTC Sensor2 + calibration: + - 10.0kOhm -> 25°C + - 27.219kOhm -> 0°C + - 14.674kOhm -> 15°C diff --git a/tests/components/ntc/test.esp32-s2.yaml b/tests/components/ntc/test.esp32-s2.yaml new file mode 100644 index 0000000000..c0edb83d9d --- /dev/null +++ b/tests/components/ntc/test.esp32-s2.yaml @@ -0,0 +1,26 @@ +sensor: + - platform: adc + id: my_sensor + pin: 4 + attenuation: 11db + - platform: resistance + sensor: my_sensor + configuration: DOWNSTREAM + resistor: 10kΩ + reference_voltage: 3.3V + name: Resistance + id: resist + - platform: ntc + sensor: resist + name: NTC Sensor + calibration: + b_constant: 3950 + reference_resistance: 10k + reference_temperature: 25°C + - platform: ntc + sensor: resist + name: NTC Sensor2 + calibration: + - 10.0kOhm -> 25°C + - 27.219kOhm -> 0°C + - 14.674kOhm -> 15°C diff --git a/tests/components/ntc/test.esp32-s3.yaml b/tests/components/ntc/test.esp32-s3.yaml new file mode 100644 index 0000000000..c0edb83d9d --- /dev/null +++ b/tests/components/ntc/test.esp32-s3.yaml @@ -0,0 +1,26 @@ +sensor: + - platform: adc + id: my_sensor + pin: 4 + attenuation: 11db + - platform: resistance + sensor: my_sensor + configuration: DOWNSTREAM + resistor: 10kΩ + reference_voltage: 3.3V + name: Resistance + id: resist + - platform: ntc + sensor: resist + name: NTC Sensor + calibration: + b_constant: 3950 + reference_resistance: 10k + reference_temperature: 25°C + - platform: ntc + sensor: resist + name: NTC Sensor2 + calibration: + - 10.0kOhm -> 25°C + - 27.219kOhm -> 0°C + - 14.674kOhm -> 15°C diff --git a/tests/components/ntc/test.esp32.yaml b/tests/components/ntc/test.esp32.yaml new file mode 100644 index 0000000000..3e0e901b6e --- /dev/null +++ b/tests/components/ntc/test.esp32.yaml @@ -0,0 +1,26 @@ +sensor: + - platform: adc + id: my_sensor + pin: 32 + attenuation: 11db + - platform: resistance + sensor: my_sensor + configuration: DOWNSTREAM + resistor: 10kΩ + reference_voltage: 3.3V + name: Resistance + id: resist + - platform: ntc + sensor: resist + name: NTC Sensor + calibration: + b_constant: 3950 + reference_resistance: 10k + reference_temperature: 25°C + - platform: ntc + sensor: resist + name: NTC Sensor2 + calibration: + - 10.0kOhm -> 25°C + - 27.219kOhm -> 0°C + - 14.674kOhm -> 15°C diff --git a/tests/components/ntc/test.esp8266.yaml b/tests/components/ntc/test.esp8266.yaml new file mode 100644 index 0000000000..370d16d3f7 --- /dev/null +++ b/tests/components/ntc/test.esp8266.yaml @@ -0,0 +1,25 @@ +sensor: + - platform: adc + id: my_sensor + pin: A0 + - platform: resistance + sensor: my_sensor + configuration: DOWNSTREAM + resistor: 10kΩ + reference_voltage: 3.3V + name: Resistance + id: resist + - platform: ntc + sensor: resist + name: NTC Sensor + calibration: + b_constant: 3950 + reference_resistance: 10k + reference_temperature: 25°C + - platform: ntc + sensor: resist + name: NTC Sensor2 + calibration: + - 10.0kOhm -> 25°C + - 27.219kOhm -> 0°C + - 14.674kOhm -> 15°C diff --git a/tests/components/ntc/test.rp2040.yaml b/tests/components/ntc/test.rp2040.yaml new file mode 100644 index 0000000000..9c7ba7b539 --- /dev/null +++ b/tests/components/ntc/test.rp2040.yaml @@ -0,0 +1,25 @@ +sensor: + - platform: adc + id: my_sensor + pin: 26 + - platform: resistance + sensor: my_sensor + configuration: DOWNSTREAM + resistor: 10kΩ + reference_voltage: 3.3V + name: Resistance + id: resist + - platform: ntc + sensor: resist + name: NTC Sensor + calibration: + b_constant: 3950 + reference_resistance: 10k + reference_temperature: 25°C + - platform: ntc + sensor: resist + name: NTC Sensor2 + calibration: + - 10.0kOhm -> 25°C + - 27.219kOhm -> 0°C + - 14.674kOhm -> 15°C From c36d7c0c3c758849ad3af52144aaccd6de6491ba Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Tue, 26 Mar 2024 20:25:02 -0500 Subject: [PATCH 1167/2101] Add some components to the new testing framework (Q) (#6218) --- .../qmc5883l/test.esp32-c3-idf.yaml | 19 +++++++++++++++++++ tests/components/qmc5883l/test.esp32-c3.yaml | 19 +++++++++++++++++++ tests/components/qmc5883l/test.esp32-idf.yaml | 19 +++++++++++++++++++ tests/components/qmc5883l/test.esp32.yaml | 19 +++++++++++++++++++ tests/components/qmc5883l/test.esp8266.yaml | 19 +++++++++++++++++++ tests/components/qmc5883l/test.rp2040.yaml | 19 +++++++++++++++++++ .../components/qmp6988/test.esp32-c3-idf.yaml | 16 ++++++++++++++++ tests/components/qmp6988/test.esp32-c3.yaml | 16 ++++++++++++++++ tests/components/qmp6988/test.esp32-idf.yaml | 16 ++++++++++++++++ tests/components/qmp6988/test.esp32.yaml | 16 ++++++++++++++++ tests/components/qmp6988/test.esp8266.yaml | 16 ++++++++++++++++ tests/components/qmp6988/test.rp2040.yaml | 16 ++++++++++++++++ .../components/qr_code/test.esp32-c3-idf.yaml | 17 +++++++++++++++++ tests/components/qr_code/test.esp32-c3.yaml | 17 +++++++++++++++++ tests/components/qr_code/test.esp32-idf.yaml | 17 +++++++++++++++++ tests/components/qr_code/test.esp32.yaml | 17 +++++++++++++++++ tests/components/qr_code/test.esp8266.yaml | 17 +++++++++++++++++ tests/components/qr_code/test.rp2040.yaml | 17 +++++++++++++++++ .../qwiic_pir/test.esp32-c3-idf.yaml | 8 ++++++++ tests/components/qwiic_pir/test.esp32-c3.yaml | 8 ++++++++ .../components/qwiic_pir/test.esp32-idf.yaml | 8 ++++++++ tests/components/qwiic_pir/test.esp32.yaml | 8 ++++++++ tests/components/qwiic_pir/test.esp8266.yaml | 8 ++++++++ tests/components/qwiic_pir/test.rp2040.yaml | 8 ++++++++ 24 files changed, 360 insertions(+) create mode 100644 tests/components/qmc5883l/test.esp32-c3-idf.yaml create mode 100644 tests/components/qmc5883l/test.esp32-c3.yaml create mode 100644 tests/components/qmc5883l/test.esp32-idf.yaml create mode 100644 tests/components/qmc5883l/test.esp32.yaml create mode 100644 tests/components/qmc5883l/test.esp8266.yaml create mode 100644 tests/components/qmc5883l/test.rp2040.yaml create mode 100644 tests/components/qmp6988/test.esp32-c3-idf.yaml create mode 100644 tests/components/qmp6988/test.esp32-c3.yaml create mode 100644 tests/components/qmp6988/test.esp32-idf.yaml create mode 100644 tests/components/qmp6988/test.esp32.yaml create mode 100644 tests/components/qmp6988/test.esp8266.yaml create mode 100644 tests/components/qmp6988/test.rp2040.yaml create mode 100644 tests/components/qr_code/test.esp32-c3-idf.yaml create mode 100644 tests/components/qr_code/test.esp32-c3.yaml create mode 100644 tests/components/qr_code/test.esp32-idf.yaml create mode 100644 tests/components/qr_code/test.esp32.yaml create mode 100644 tests/components/qr_code/test.esp8266.yaml create mode 100644 tests/components/qr_code/test.rp2040.yaml create mode 100644 tests/components/qwiic_pir/test.esp32-c3-idf.yaml create mode 100644 tests/components/qwiic_pir/test.esp32-c3.yaml create mode 100644 tests/components/qwiic_pir/test.esp32-idf.yaml create mode 100644 tests/components/qwiic_pir/test.esp32.yaml create mode 100644 tests/components/qwiic_pir/test.esp8266.yaml create mode 100644 tests/components/qwiic_pir/test.rp2040.yaml diff --git a/tests/components/qmc5883l/test.esp32-c3-idf.yaml b/tests/components/qmc5883l/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..c638f7e5be --- /dev/null +++ b/tests/components/qmc5883l/test.esp32-c3-idf.yaml @@ -0,0 +1,19 @@ +i2c: + - id: i2c_qmc5883l + scl: 5 + sda: 4 + +sensor: + - platform: qmc5883l + address: 0x0D + field_strength_x: + name: QMC5883L Field Strength X + field_strength_y: + name: QMC5883L Field Strength Y + field_strength_z: + name: QMC5883L Field Strength Z + heading: + name: QMC5883L Heading + range: 800uT + oversampling: 256x + update_interval: 15s diff --git a/tests/components/qmc5883l/test.esp32-c3.yaml b/tests/components/qmc5883l/test.esp32-c3.yaml new file mode 100644 index 0000000000..c638f7e5be --- /dev/null +++ b/tests/components/qmc5883l/test.esp32-c3.yaml @@ -0,0 +1,19 @@ +i2c: + - id: i2c_qmc5883l + scl: 5 + sda: 4 + +sensor: + - platform: qmc5883l + address: 0x0D + field_strength_x: + name: QMC5883L Field Strength X + field_strength_y: + name: QMC5883L Field Strength Y + field_strength_z: + name: QMC5883L Field Strength Z + heading: + name: QMC5883L Heading + range: 800uT + oversampling: 256x + update_interval: 15s diff --git a/tests/components/qmc5883l/test.esp32-idf.yaml b/tests/components/qmc5883l/test.esp32-idf.yaml new file mode 100644 index 0000000000..1aafa86cfa --- /dev/null +++ b/tests/components/qmc5883l/test.esp32-idf.yaml @@ -0,0 +1,19 @@ +i2c: + - id: i2c_qmc5883l + scl: 16 + sda: 17 + +sensor: + - platform: qmc5883l + address: 0x0D + field_strength_x: + name: QMC5883L Field Strength X + field_strength_y: + name: QMC5883L Field Strength Y + field_strength_z: + name: QMC5883L Field Strength Z + heading: + name: QMC5883L Heading + range: 800uT + oversampling: 256x + update_interval: 15s diff --git a/tests/components/qmc5883l/test.esp32.yaml b/tests/components/qmc5883l/test.esp32.yaml new file mode 100644 index 0000000000..1aafa86cfa --- /dev/null +++ b/tests/components/qmc5883l/test.esp32.yaml @@ -0,0 +1,19 @@ +i2c: + - id: i2c_qmc5883l + scl: 16 + sda: 17 + +sensor: + - platform: qmc5883l + address: 0x0D + field_strength_x: + name: QMC5883L Field Strength X + field_strength_y: + name: QMC5883L Field Strength Y + field_strength_z: + name: QMC5883L Field Strength Z + heading: + name: QMC5883L Heading + range: 800uT + oversampling: 256x + update_interval: 15s diff --git a/tests/components/qmc5883l/test.esp8266.yaml b/tests/components/qmc5883l/test.esp8266.yaml new file mode 100644 index 0000000000..c638f7e5be --- /dev/null +++ b/tests/components/qmc5883l/test.esp8266.yaml @@ -0,0 +1,19 @@ +i2c: + - id: i2c_qmc5883l + scl: 5 + sda: 4 + +sensor: + - platform: qmc5883l + address: 0x0D + field_strength_x: + name: QMC5883L Field Strength X + field_strength_y: + name: QMC5883L Field Strength Y + field_strength_z: + name: QMC5883L Field Strength Z + heading: + name: QMC5883L Heading + range: 800uT + oversampling: 256x + update_interval: 15s diff --git a/tests/components/qmc5883l/test.rp2040.yaml b/tests/components/qmc5883l/test.rp2040.yaml new file mode 100644 index 0000000000..c638f7e5be --- /dev/null +++ b/tests/components/qmc5883l/test.rp2040.yaml @@ -0,0 +1,19 @@ +i2c: + - id: i2c_qmc5883l + scl: 5 + sda: 4 + +sensor: + - platform: qmc5883l + address: 0x0D + field_strength_x: + name: QMC5883L Field Strength X + field_strength_y: + name: QMC5883L Field Strength Y + field_strength_z: + name: QMC5883L Field Strength Z + heading: + name: QMC5883L Heading + range: 800uT + oversampling: 256x + update_interval: 15s diff --git a/tests/components/qmp6988/test.esp32-c3-idf.yaml b/tests/components/qmp6988/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..bcd87ae6b8 --- /dev/null +++ b/tests/components/qmp6988/test.esp32-c3-idf.yaml @@ -0,0 +1,16 @@ +i2c: + - id: i2c_qmp6988 + scl: 5 + sda: 4 + +sensor: + - platform: qmp6988 + temperature: + name: QMP6988 Temperature + oversampling: 32x + pressure: + name: QMP6988 Pressure + oversampling: 2x + address: 0x70 + update_interval: 30s + iir_filter: 16x diff --git a/tests/components/qmp6988/test.esp32-c3.yaml b/tests/components/qmp6988/test.esp32-c3.yaml new file mode 100644 index 0000000000..bcd87ae6b8 --- /dev/null +++ b/tests/components/qmp6988/test.esp32-c3.yaml @@ -0,0 +1,16 @@ +i2c: + - id: i2c_qmp6988 + scl: 5 + sda: 4 + +sensor: + - platform: qmp6988 + temperature: + name: QMP6988 Temperature + oversampling: 32x + pressure: + name: QMP6988 Pressure + oversampling: 2x + address: 0x70 + update_interval: 30s + iir_filter: 16x diff --git a/tests/components/qmp6988/test.esp32-idf.yaml b/tests/components/qmp6988/test.esp32-idf.yaml new file mode 100644 index 0000000000..f3fbf75bbe --- /dev/null +++ b/tests/components/qmp6988/test.esp32-idf.yaml @@ -0,0 +1,16 @@ +i2c: + - id: i2c_qmp6988 + scl: 16 + sda: 17 + +sensor: + - platform: qmp6988 + temperature: + name: QMP6988 Temperature + oversampling: 32x + pressure: + name: QMP6988 Pressure + oversampling: 2x + address: 0x70 + update_interval: 30s + iir_filter: 16x diff --git a/tests/components/qmp6988/test.esp32.yaml b/tests/components/qmp6988/test.esp32.yaml new file mode 100644 index 0000000000..f3fbf75bbe --- /dev/null +++ b/tests/components/qmp6988/test.esp32.yaml @@ -0,0 +1,16 @@ +i2c: + - id: i2c_qmp6988 + scl: 16 + sda: 17 + +sensor: + - platform: qmp6988 + temperature: + name: QMP6988 Temperature + oversampling: 32x + pressure: + name: QMP6988 Pressure + oversampling: 2x + address: 0x70 + update_interval: 30s + iir_filter: 16x diff --git a/tests/components/qmp6988/test.esp8266.yaml b/tests/components/qmp6988/test.esp8266.yaml new file mode 100644 index 0000000000..bcd87ae6b8 --- /dev/null +++ b/tests/components/qmp6988/test.esp8266.yaml @@ -0,0 +1,16 @@ +i2c: + - id: i2c_qmp6988 + scl: 5 + sda: 4 + +sensor: + - platform: qmp6988 + temperature: + name: QMP6988 Temperature + oversampling: 32x + pressure: + name: QMP6988 Pressure + oversampling: 2x + address: 0x70 + update_interval: 30s + iir_filter: 16x diff --git a/tests/components/qmp6988/test.rp2040.yaml b/tests/components/qmp6988/test.rp2040.yaml new file mode 100644 index 0000000000..bcd87ae6b8 --- /dev/null +++ b/tests/components/qmp6988/test.rp2040.yaml @@ -0,0 +1,16 @@ +i2c: + - id: i2c_qmp6988 + scl: 5 + sda: 4 + +sensor: + - platform: qmp6988 + temperature: + name: QMP6988 Temperature + oversampling: 32x + pressure: + name: QMP6988 Pressure + oversampling: 2x + address: 0x70 + update_interval: 30s + iir_filter: 16x diff --git a/tests/components/qr_code/test.esp32-c3-idf.yaml b/tests/components/qr_code/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..3e875c026c --- /dev/null +++ b/tests/components/qr_code/test.esp32-c3-idf.yaml @@ -0,0 +1,17 @@ +spi: + - id: spi_main_lcd + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +display: + - platform: ili9xxx + id: main_lcd + model: ili9342 + cs_pin: 8 + dc_pin: 9 + reset_pin: 10 + +qr_code: + - id: homepage_qr + value: https://esphome.io/index.html diff --git a/tests/components/qr_code/test.esp32-c3.yaml b/tests/components/qr_code/test.esp32-c3.yaml new file mode 100644 index 0000000000..3e875c026c --- /dev/null +++ b/tests/components/qr_code/test.esp32-c3.yaml @@ -0,0 +1,17 @@ +spi: + - id: spi_main_lcd + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +display: + - platform: ili9xxx + id: main_lcd + model: ili9342 + cs_pin: 8 + dc_pin: 9 + reset_pin: 10 + +qr_code: + - id: homepage_qr + value: https://esphome.io/index.html diff --git a/tests/components/qr_code/test.esp32-idf.yaml b/tests/components/qr_code/test.esp32-idf.yaml new file mode 100644 index 0000000000..b354a3f512 --- /dev/null +++ b/tests/components/qr_code/test.esp32-idf.yaml @@ -0,0 +1,17 @@ +spi: + - id: spi_main_lcd + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +display: + - platform: ili9xxx + id: main_lcd + model: ili9342 + cs_pin: 12 + dc_pin: 13 + reset_pin: 21 + +qr_code: + - id: homepage_qr + value: https://esphome.io/index.html diff --git a/tests/components/qr_code/test.esp32.yaml b/tests/components/qr_code/test.esp32.yaml new file mode 100644 index 0000000000..b354a3f512 --- /dev/null +++ b/tests/components/qr_code/test.esp32.yaml @@ -0,0 +1,17 @@ +spi: + - id: spi_main_lcd + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +display: + - platform: ili9xxx + id: main_lcd + model: ili9342 + cs_pin: 12 + dc_pin: 13 + reset_pin: 21 + +qr_code: + - id: homepage_qr + value: https://esphome.io/index.html diff --git a/tests/components/qr_code/test.esp8266.yaml b/tests/components/qr_code/test.esp8266.yaml new file mode 100644 index 0000000000..dd0d75c472 --- /dev/null +++ b/tests/components/qr_code/test.esp8266.yaml @@ -0,0 +1,17 @@ +spi: + - id: spi_main_lcd + clk_pin: 14 + mosi_pin: 13 + miso_pin: 12 + +display: + - platform: ili9xxx + id: main_lcd + model: ili9342 + cs_pin: 5 + dc_pin: 15 + reset_pin: 16 + +qr_code: + - id: homepage_qr + value: https://esphome.io/index.html diff --git a/tests/components/qr_code/test.rp2040.yaml b/tests/components/qr_code/test.rp2040.yaml new file mode 100644 index 0000000000..b0e046d275 --- /dev/null +++ b/tests/components/qr_code/test.rp2040.yaml @@ -0,0 +1,17 @@ +spi: + - id: spi_main_lcd + clk_pin: 2 + mosi_pin: 3 + miso_pin: 4 + +display: + - platform: ili9xxx + id: main_lcd + model: ili9342 + cs_pin: 20 + dc_pin: 21 + reset_pin: 22 + +qr_code: + - id: homepage_qr + value: https://esphome.io/index.html diff --git a/tests/components/qwiic_pir/test.esp32-c3-idf.yaml b/tests/components/qwiic_pir/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..ad52ac91c5 --- /dev/null +++ b/tests/components/qwiic_pir/test.esp32-c3-idf.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_qwiic_pir + scl: 5 + sda: 4 + +binary_sensor: + - platform: qwiic_pir + name: Qwiic PIR Motion Sensor diff --git a/tests/components/qwiic_pir/test.esp32-c3.yaml b/tests/components/qwiic_pir/test.esp32-c3.yaml new file mode 100644 index 0000000000..ad52ac91c5 --- /dev/null +++ b/tests/components/qwiic_pir/test.esp32-c3.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_qwiic_pir + scl: 5 + sda: 4 + +binary_sensor: + - platform: qwiic_pir + name: Qwiic PIR Motion Sensor diff --git a/tests/components/qwiic_pir/test.esp32-idf.yaml b/tests/components/qwiic_pir/test.esp32-idf.yaml new file mode 100644 index 0000000000..da2e275cf3 --- /dev/null +++ b/tests/components/qwiic_pir/test.esp32-idf.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_qwiic_pir + scl: 16 + sda: 17 + +binary_sensor: + - platform: qwiic_pir + name: Qwiic PIR Motion Sensor diff --git a/tests/components/qwiic_pir/test.esp32.yaml b/tests/components/qwiic_pir/test.esp32.yaml new file mode 100644 index 0000000000..da2e275cf3 --- /dev/null +++ b/tests/components/qwiic_pir/test.esp32.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_qwiic_pir + scl: 16 + sda: 17 + +binary_sensor: + - platform: qwiic_pir + name: Qwiic PIR Motion Sensor diff --git a/tests/components/qwiic_pir/test.esp8266.yaml b/tests/components/qwiic_pir/test.esp8266.yaml new file mode 100644 index 0000000000..ad52ac91c5 --- /dev/null +++ b/tests/components/qwiic_pir/test.esp8266.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_qwiic_pir + scl: 5 + sda: 4 + +binary_sensor: + - platform: qwiic_pir + name: Qwiic PIR Motion Sensor diff --git a/tests/components/qwiic_pir/test.rp2040.yaml b/tests/components/qwiic_pir/test.rp2040.yaml new file mode 100644 index 0000000000..ad52ac91c5 --- /dev/null +++ b/tests/components/qwiic_pir/test.rp2040.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_qwiic_pir + scl: 5 + sda: 4 + +binary_sensor: + - platform: qwiic_pir + name: Qwiic PIR Motion Sensor From dc071bed24bd5ee29f386c2eddd70c972a61fdf5 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Tue, 26 Mar 2024 20:26:50 -0500 Subject: [PATCH 1168/2101] Add some components to the new testing framework (U) (#6230) --- tests/components/uart/test.esp32-c3-idf.yaml | 15 ++++++++++ tests/components/uart/test.esp32-c3.yaml | 15 ++++++++++ tests/components/uart/test.esp32-idf.yaml | 15 ++++++++++ tests/components/uart/test.esp32.yaml | 15 ++++++++++ tests/components/uart/test.esp8266.yaml | 15 ++++++++++ tests/components/uart/test.rp2040.yaml | 15 ++++++++++ .../ufire_ec/test.esp32-c3-idf.yaml | 25 ++++++++++++++++ tests/components/ufire_ec/test.esp32-c3.yaml | 25 ++++++++++++++++ tests/components/ufire_ec/test.esp32-idf.yaml | 25 ++++++++++++++++ tests/components/ufire_ec/test.esp32.yaml | 25 ++++++++++++++++ tests/components/ufire_ec/test.esp8266.yaml | 25 ++++++++++++++++ tests/components/ufire_ec/test.rp2040.yaml | 25 ++++++++++++++++ .../ufire_ise/test.esp32-c3-idf.yaml | 25 ++++++++++++++++ tests/components/ufire_ise/test.esp32-c3.yaml | 25 ++++++++++++++++ .../components/ufire_ise/test.esp32-idf.yaml | 25 ++++++++++++++++ tests/components/ufire_ise/test.esp32.yaml | 25 ++++++++++++++++ tests/components/ufire_ise/test.esp8266.yaml | 25 ++++++++++++++++ tests/components/ufire_ise/test.rp2040.yaml | 25 ++++++++++++++++ .../components/uln2003/test.esp32-c3-idf.yaml | 29 +++++++++++++++++++ tests/components/uln2003/test.esp32-c3.yaml | 29 +++++++++++++++++++ tests/components/uln2003/test.esp32-idf.yaml | 29 +++++++++++++++++++ tests/components/uln2003/test.esp32.yaml | 29 +++++++++++++++++++ tests/components/uln2003/test.esp8266.yaml | 29 +++++++++++++++++++ tests/components/uln2003/test.rp2040.yaml | 29 +++++++++++++++++++ .../ultrasonic/test.esp32-c3-idf.yaml | 7 +++++ .../components/ultrasonic/test.esp32-c3.yaml | 7 +++++ .../components/ultrasonic/test.esp32-idf.yaml | 7 +++++ tests/components/ultrasonic/test.esp32.yaml | 7 +++++ tests/components/ultrasonic/test.esp8266.yaml | 7 +++++ tests/components/ultrasonic/test.rp2040.yaml | 7 +++++ .../components/uptime/test.esp32-c3-idf.yaml | 3 ++ tests/components/uptime/test.esp32-c3.yaml | 3 ++ tests/components/uptime/test.esp32-idf.yaml | 3 ++ tests/components/uptime/test.esp32.yaml | 3 ++ tests/components/uptime/test.esp8266.yaml | 3 ++ tests/components/uptime/test.rp2040.yaml | 3 ++ 36 files changed, 624 insertions(+) create mode 100644 tests/components/uart/test.esp32-c3-idf.yaml create mode 100644 tests/components/uart/test.esp32-c3.yaml create mode 100644 tests/components/uart/test.esp32-idf.yaml create mode 100644 tests/components/uart/test.esp32.yaml create mode 100644 tests/components/uart/test.esp8266.yaml create mode 100644 tests/components/uart/test.rp2040.yaml create mode 100644 tests/components/ufire_ec/test.esp32-c3-idf.yaml create mode 100644 tests/components/ufire_ec/test.esp32-c3.yaml create mode 100644 tests/components/ufire_ec/test.esp32-idf.yaml create mode 100644 tests/components/ufire_ec/test.esp32.yaml create mode 100644 tests/components/ufire_ec/test.esp8266.yaml create mode 100644 tests/components/ufire_ec/test.rp2040.yaml create mode 100644 tests/components/ufire_ise/test.esp32-c3-idf.yaml create mode 100644 tests/components/ufire_ise/test.esp32-c3.yaml create mode 100644 tests/components/ufire_ise/test.esp32-idf.yaml create mode 100644 tests/components/ufire_ise/test.esp32.yaml create mode 100644 tests/components/ufire_ise/test.esp8266.yaml create mode 100644 tests/components/ufire_ise/test.rp2040.yaml create mode 100644 tests/components/uln2003/test.esp32-c3-idf.yaml create mode 100644 tests/components/uln2003/test.esp32-c3.yaml create mode 100644 tests/components/uln2003/test.esp32-idf.yaml create mode 100644 tests/components/uln2003/test.esp32.yaml create mode 100644 tests/components/uln2003/test.esp8266.yaml create mode 100644 tests/components/uln2003/test.rp2040.yaml create mode 100644 tests/components/ultrasonic/test.esp32-c3-idf.yaml create mode 100644 tests/components/ultrasonic/test.esp32-c3.yaml create mode 100644 tests/components/ultrasonic/test.esp32-idf.yaml create mode 100644 tests/components/ultrasonic/test.esp32.yaml create mode 100644 tests/components/ultrasonic/test.esp8266.yaml create mode 100644 tests/components/ultrasonic/test.rp2040.yaml create mode 100644 tests/components/uptime/test.esp32-c3-idf.yaml create mode 100644 tests/components/uptime/test.esp32-c3.yaml create mode 100644 tests/components/uptime/test.esp32-idf.yaml create mode 100644 tests/components/uptime/test.esp32.yaml create mode 100644 tests/components/uptime/test.esp8266.yaml create mode 100644 tests/components/uptime/test.rp2040.yaml diff --git a/tests/components/uart/test.esp32-c3-idf.yaml b/tests/components/uart/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..09178f1663 --- /dev/null +++ b/tests/components/uart/test.esp32-c3-idf.yaml @@ -0,0 +1,15 @@ +esphome: + on_boot: + then: + - uart.write: 'Hello World' + - uart.write: [0x00, 0x20, 0x42] + +uart: + - id: uart_uart + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + data_bits: 8 + rx_buffer_size: 512 + parity: EVEN + stop_bits: 2 diff --git a/tests/components/uart/test.esp32-c3.yaml b/tests/components/uart/test.esp32-c3.yaml new file mode 100644 index 0000000000..09178f1663 --- /dev/null +++ b/tests/components/uart/test.esp32-c3.yaml @@ -0,0 +1,15 @@ +esphome: + on_boot: + then: + - uart.write: 'Hello World' + - uart.write: [0x00, 0x20, 0x42] + +uart: + - id: uart_uart + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + data_bits: 8 + rx_buffer_size: 512 + parity: EVEN + stop_bits: 2 diff --git a/tests/components/uart/test.esp32-idf.yaml b/tests/components/uart/test.esp32-idf.yaml new file mode 100644 index 0000000000..bef5b460ab --- /dev/null +++ b/tests/components/uart/test.esp32-idf.yaml @@ -0,0 +1,15 @@ +esphome: + on_boot: + then: + - uart.write: 'Hello World' + - uart.write: [0x00, 0x20, 0x42] + +uart: + - id: uart_uart + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + data_bits: 8 + rx_buffer_size: 512 + parity: EVEN + stop_bits: 2 diff --git a/tests/components/uart/test.esp32.yaml b/tests/components/uart/test.esp32.yaml new file mode 100644 index 0000000000..bef5b460ab --- /dev/null +++ b/tests/components/uart/test.esp32.yaml @@ -0,0 +1,15 @@ +esphome: + on_boot: + then: + - uart.write: 'Hello World' + - uart.write: [0x00, 0x20, 0x42] + +uart: + - id: uart_uart + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + data_bits: 8 + rx_buffer_size: 512 + parity: EVEN + stop_bits: 2 diff --git a/tests/components/uart/test.esp8266.yaml b/tests/components/uart/test.esp8266.yaml new file mode 100644 index 0000000000..09178f1663 --- /dev/null +++ b/tests/components/uart/test.esp8266.yaml @@ -0,0 +1,15 @@ +esphome: + on_boot: + then: + - uart.write: 'Hello World' + - uart.write: [0x00, 0x20, 0x42] + +uart: + - id: uart_uart + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + data_bits: 8 + rx_buffer_size: 512 + parity: EVEN + stop_bits: 2 diff --git a/tests/components/uart/test.rp2040.yaml b/tests/components/uart/test.rp2040.yaml new file mode 100644 index 0000000000..09178f1663 --- /dev/null +++ b/tests/components/uart/test.rp2040.yaml @@ -0,0 +1,15 @@ +esphome: + on_boot: + then: + - uart.write: 'Hello World' + - uart.write: [0x00, 0x20, 0x42] + +uart: + - id: uart_uart + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + data_bits: 8 + rx_buffer_size: 512 + parity: EVEN + stop_bits: 2 diff --git a/tests/components/ufire_ec/test.esp32-c3-idf.yaml b/tests/components/ufire_ec/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..aa72c992b8 --- /dev/null +++ b/tests/components/ufire_ec/test.esp32-c3-idf.yaml @@ -0,0 +1,25 @@ +esphome: + on_boot: + then: + - ufire_ec.calibrate_probe: + id: ufire_ec_board + solution: 0.146 + temperature: !lambda "return id(test_sensor).state;" + - ufire_ec.reset: + +i2c: + - id: i2c_ufire_ec + scl: 5 + sda: 4 + +sensor: + - platform: template + id: test_sensor + lambda: "return 21;" + - platform: ufire_ec + id: ufire_ec_board + ec: + name: Ufire EC + temperature_sensor: test_sensor + temperature_compensation: 20.0 + temperature_coefficient: 0.019 diff --git a/tests/components/ufire_ec/test.esp32-c3.yaml b/tests/components/ufire_ec/test.esp32-c3.yaml new file mode 100644 index 0000000000..aa72c992b8 --- /dev/null +++ b/tests/components/ufire_ec/test.esp32-c3.yaml @@ -0,0 +1,25 @@ +esphome: + on_boot: + then: + - ufire_ec.calibrate_probe: + id: ufire_ec_board + solution: 0.146 + temperature: !lambda "return id(test_sensor).state;" + - ufire_ec.reset: + +i2c: + - id: i2c_ufire_ec + scl: 5 + sda: 4 + +sensor: + - platform: template + id: test_sensor + lambda: "return 21;" + - platform: ufire_ec + id: ufire_ec_board + ec: + name: Ufire EC + temperature_sensor: test_sensor + temperature_compensation: 20.0 + temperature_coefficient: 0.019 diff --git a/tests/components/ufire_ec/test.esp32-idf.yaml b/tests/components/ufire_ec/test.esp32-idf.yaml new file mode 100644 index 0000000000..5e6a0daa9e --- /dev/null +++ b/tests/components/ufire_ec/test.esp32-idf.yaml @@ -0,0 +1,25 @@ +esphome: + on_boot: + then: + - ufire_ec.calibrate_probe: + id: ufire_ec_board + solution: 0.146 + temperature: !lambda "return id(test_sensor).state;" + - ufire_ec.reset: + +i2c: + - id: i2c_ufire_ec + scl: 16 + sda: 17 + +sensor: + - platform: template + id: test_sensor + lambda: "return 21;" + - platform: ufire_ec + id: ufire_ec_board + ec: + name: Ufire EC + temperature_sensor: test_sensor + temperature_compensation: 20.0 + temperature_coefficient: 0.019 diff --git a/tests/components/ufire_ec/test.esp32.yaml b/tests/components/ufire_ec/test.esp32.yaml new file mode 100644 index 0000000000..5e6a0daa9e --- /dev/null +++ b/tests/components/ufire_ec/test.esp32.yaml @@ -0,0 +1,25 @@ +esphome: + on_boot: + then: + - ufire_ec.calibrate_probe: + id: ufire_ec_board + solution: 0.146 + temperature: !lambda "return id(test_sensor).state;" + - ufire_ec.reset: + +i2c: + - id: i2c_ufire_ec + scl: 16 + sda: 17 + +sensor: + - platform: template + id: test_sensor + lambda: "return 21;" + - platform: ufire_ec + id: ufire_ec_board + ec: + name: Ufire EC + temperature_sensor: test_sensor + temperature_compensation: 20.0 + temperature_coefficient: 0.019 diff --git a/tests/components/ufire_ec/test.esp8266.yaml b/tests/components/ufire_ec/test.esp8266.yaml new file mode 100644 index 0000000000..aa72c992b8 --- /dev/null +++ b/tests/components/ufire_ec/test.esp8266.yaml @@ -0,0 +1,25 @@ +esphome: + on_boot: + then: + - ufire_ec.calibrate_probe: + id: ufire_ec_board + solution: 0.146 + temperature: !lambda "return id(test_sensor).state;" + - ufire_ec.reset: + +i2c: + - id: i2c_ufire_ec + scl: 5 + sda: 4 + +sensor: + - platform: template + id: test_sensor + lambda: "return 21;" + - platform: ufire_ec + id: ufire_ec_board + ec: + name: Ufire EC + temperature_sensor: test_sensor + temperature_compensation: 20.0 + temperature_coefficient: 0.019 diff --git a/tests/components/ufire_ec/test.rp2040.yaml b/tests/components/ufire_ec/test.rp2040.yaml new file mode 100644 index 0000000000..aa72c992b8 --- /dev/null +++ b/tests/components/ufire_ec/test.rp2040.yaml @@ -0,0 +1,25 @@ +esphome: + on_boot: + then: + - ufire_ec.calibrate_probe: + id: ufire_ec_board + solution: 0.146 + temperature: !lambda "return id(test_sensor).state;" + - ufire_ec.reset: + +i2c: + - id: i2c_ufire_ec + scl: 5 + sda: 4 + +sensor: + - platform: template + id: test_sensor + lambda: "return 21;" + - platform: ufire_ec + id: ufire_ec_board + ec: + name: Ufire EC + temperature_sensor: test_sensor + temperature_compensation: 20.0 + temperature_coefficient: 0.019 diff --git a/tests/components/ufire_ise/test.esp32-c3-idf.yaml b/tests/components/ufire_ise/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..36aec73113 --- /dev/null +++ b/tests/components/ufire_ise/test.esp32-c3-idf.yaml @@ -0,0 +1,25 @@ +esphome: + on_boot: + then: + - ufire_ise.calibrate_probe_high: + id: ufire_ise_sensor + solution: 7.0 + - ufire_ise.calibrate_probe_low: + id: ufire_ise_sensor + solution: 4.0 + - ufire_ise.reset: + +i2c: + - id: i2c_ufire_ise + scl: 5 + sda: 4 + +sensor: + - platform: template + id: test_sensor + lambda: "return 21;" + - platform: ufire_ise + id: ufire_ise_sensor + temperature_sensor: test_sensor + ph: + name: Ufire pH diff --git a/tests/components/ufire_ise/test.esp32-c3.yaml b/tests/components/ufire_ise/test.esp32-c3.yaml new file mode 100644 index 0000000000..36aec73113 --- /dev/null +++ b/tests/components/ufire_ise/test.esp32-c3.yaml @@ -0,0 +1,25 @@ +esphome: + on_boot: + then: + - ufire_ise.calibrate_probe_high: + id: ufire_ise_sensor + solution: 7.0 + - ufire_ise.calibrate_probe_low: + id: ufire_ise_sensor + solution: 4.0 + - ufire_ise.reset: + +i2c: + - id: i2c_ufire_ise + scl: 5 + sda: 4 + +sensor: + - platform: template + id: test_sensor + lambda: "return 21;" + - platform: ufire_ise + id: ufire_ise_sensor + temperature_sensor: test_sensor + ph: + name: Ufire pH diff --git a/tests/components/ufire_ise/test.esp32-idf.yaml b/tests/components/ufire_ise/test.esp32-idf.yaml new file mode 100644 index 0000000000..9ed0ac433a --- /dev/null +++ b/tests/components/ufire_ise/test.esp32-idf.yaml @@ -0,0 +1,25 @@ +esphome: + on_boot: + then: + - ufire_ise.calibrate_probe_high: + id: ufire_ise_sensor + solution: 7.0 + - ufire_ise.calibrate_probe_low: + id: ufire_ise_sensor + solution: 4.0 + - ufire_ise.reset: + +i2c: + - id: i2c_ufire_ise + scl: 16 + sda: 17 + +sensor: + - platform: template + id: test_sensor + lambda: "return 21;" + - platform: ufire_ise + id: ufire_ise_sensor + temperature_sensor: test_sensor + ph: + name: Ufire pH diff --git a/tests/components/ufire_ise/test.esp32.yaml b/tests/components/ufire_ise/test.esp32.yaml new file mode 100644 index 0000000000..9ed0ac433a --- /dev/null +++ b/tests/components/ufire_ise/test.esp32.yaml @@ -0,0 +1,25 @@ +esphome: + on_boot: + then: + - ufire_ise.calibrate_probe_high: + id: ufire_ise_sensor + solution: 7.0 + - ufire_ise.calibrate_probe_low: + id: ufire_ise_sensor + solution: 4.0 + - ufire_ise.reset: + +i2c: + - id: i2c_ufire_ise + scl: 16 + sda: 17 + +sensor: + - platform: template + id: test_sensor + lambda: "return 21;" + - platform: ufire_ise + id: ufire_ise_sensor + temperature_sensor: test_sensor + ph: + name: Ufire pH diff --git a/tests/components/ufire_ise/test.esp8266.yaml b/tests/components/ufire_ise/test.esp8266.yaml new file mode 100644 index 0000000000..36aec73113 --- /dev/null +++ b/tests/components/ufire_ise/test.esp8266.yaml @@ -0,0 +1,25 @@ +esphome: + on_boot: + then: + - ufire_ise.calibrate_probe_high: + id: ufire_ise_sensor + solution: 7.0 + - ufire_ise.calibrate_probe_low: + id: ufire_ise_sensor + solution: 4.0 + - ufire_ise.reset: + +i2c: + - id: i2c_ufire_ise + scl: 5 + sda: 4 + +sensor: + - platform: template + id: test_sensor + lambda: "return 21;" + - platform: ufire_ise + id: ufire_ise_sensor + temperature_sensor: test_sensor + ph: + name: Ufire pH diff --git a/tests/components/ufire_ise/test.rp2040.yaml b/tests/components/ufire_ise/test.rp2040.yaml new file mode 100644 index 0000000000..36aec73113 --- /dev/null +++ b/tests/components/ufire_ise/test.rp2040.yaml @@ -0,0 +1,25 @@ +esphome: + on_boot: + then: + - ufire_ise.calibrate_probe_high: + id: ufire_ise_sensor + solution: 7.0 + - ufire_ise.calibrate_probe_low: + id: ufire_ise_sensor + solution: 4.0 + - ufire_ise.reset: + +i2c: + - id: i2c_ufire_ise + scl: 5 + sda: 4 + +sensor: + - platform: template + id: test_sensor + lambda: "return 21;" + - platform: ufire_ise + id: ufire_ise_sensor + temperature_sensor: test_sensor + ph: + name: Ufire pH diff --git a/tests/components/uln2003/test.esp32-c3-idf.yaml b/tests/components/uln2003/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..2d19d4dba3 --- /dev/null +++ b/tests/components/uln2003/test.esp32-c3-idf.yaml @@ -0,0 +1,29 @@ +esphome: + on_boot: + then: + - stepper.report_position: + id: uln2003_stepper + position: 250 + - stepper.set_target: + id: uln2003_stepper + target: 250 + - stepper.set_acceleration: + id: uln2003_stepper + acceleration: 250 steps/s^2 + - stepper.set_deceleration: + id: uln2003_stepper + deceleration: 250 steps/s^2 + - stepper.set_speed: + id: uln2003_stepper + speed: 250 steps/s + +stepper: + - platform: uln2003 + id: uln2003_stepper + pin_a: 0 + pin_b: 1 + pin_c: 2 + pin_d: 3 + max_speed: 250 steps/s + acceleration: 100 steps/s^2 + deceleration: 200 steps/s^2 diff --git a/tests/components/uln2003/test.esp32-c3.yaml b/tests/components/uln2003/test.esp32-c3.yaml new file mode 100644 index 0000000000..2d19d4dba3 --- /dev/null +++ b/tests/components/uln2003/test.esp32-c3.yaml @@ -0,0 +1,29 @@ +esphome: + on_boot: + then: + - stepper.report_position: + id: uln2003_stepper + position: 250 + - stepper.set_target: + id: uln2003_stepper + target: 250 + - stepper.set_acceleration: + id: uln2003_stepper + acceleration: 250 steps/s^2 + - stepper.set_deceleration: + id: uln2003_stepper + deceleration: 250 steps/s^2 + - stepper.set_speed: + id: uln2003_stepper + speed: 250 steps/s + +stepper: + - platform: uln2003 + id: uln2003_stepper + pin_a: 0 + pin_b: 1 + pin_c: 2 + pin_d: 3 + max_speed: 250 steps/s + acceleration: 100 steps/s^2 + deceleration: 200 steps/s^2 diff --git a/tests/components/uln2003/test.esp32-idf.yaml b/tests/components/uln2003/test.esp32-idf.yaml new file mode 100644 index 0000000000..61a6e94396 --- /dev/null +++ b/tests/components/uln2003/test.esp32-idf.yaml @@ -0,0 +1,29 @@ +esphome: + on_boot: + then: + - stepper.report_position: + id: uln2003_stepper + position: 250 + - stepper.set_target: + id: uln2003_stepper + target: 250 + - stepper.set_acceleration: + id: uln2003_stepper + acceleration: 250 steps/s^2 + - stepper.set_deceleration: + id: uln2003_stepper + deceleration: 250 steps/s^2 + - stepper.set_speed: + id: uln2003_stepper + speed: 250 steps/s + +stepper: + - platform: uln2003 + id: uln2003_stepper + pin_a: 12 + pin_b: 13 + pin_c: 14 + pin_d: 15 + max_speed: 250 steps/s + acceleration: 100 steps/s^2 + deceleration: 200 steps/s^2 diff --git a/tests/components/uln2003/test.esp32.yaml b/tests/components/uln2003/test.esp32.yaml new file mode 100644 index 0000000000..61a6e94396 --- /dev/null +++ b/tests/components/uln2003/test.esp32.yaml @@ -0,0 +1,29 @@ +esphome: + on_boot: + then: + - stepper.report_position: + id: uln2003_stepper + position: 250 + - stepper.set_target: + id: uln2003_stepper + target: 250 + - stepper.set_acceleration: + id: uln2003_stepper + acceleration: 250 steps/s^2 + - stepper.set_deceleration: + id: uln2003_stepper + deceleration: 250 steps/s^2 + - stepper.set_speed: + id: uln2003_stepper + speed: 250 steps/s + +stepper: + - platform: uln2003 + id: uln2003_stepper + pin_a: 12 + pin_b: 13 + pin_c: 14 + pin_d: 15 + max_speed: 250 steps/s + acceleration: 100 steps/s^2 + deceleration: 200 steps/s^2 diff --git a/tests/components/uln2003/test.esp8266.yaml b/tests/components/uln2003/test.esp8266.yaml new file mode 100644 index 0000000000..61a6e94396 --- /dev/null +++ b/tests/components/uln2003/test.esp8266.yaml @@ -0,0 +1,29 @@ +esphome: + on_boot: + then: + - stepper.report_position: + id: uln2003_stepper + position: 250 + - stepper.set_target: + id: uln2003_stepper + target: 250 + - stepper.set_acceleration: + id: uln2003_stepper + acceleration: 250 steps/s^2 + - stepper.set_deceleration: + id: uln2003_stepper + deceleration: 250 steps/s^2 + - stepper.set_speed: + id: uln2003_stepper + speed: 250 steps/s + +stepper: + - platform: uln2003 + id: uln2003_stepper + pin_a: 12 + pin_b: 13 + pin_c: 14 + pin_d: 15 + max_speed: 250 steps/s + acceleration: 100 steps/s^2 + deceleration: 200 steps/s^2 diff --git a/tests/components/uln2003/test.rp2040.yaml b/tests/components/uln2003/test.rp2040.yaml new file mode 100644 index 0000000000..2d19d4dba3 --- /dev/null +++ b/tests/components/uln2003/test.rp2040.yaml @@ -0,0 +1,29 @@ +esphome: + on_boot: + then: + - stepper.report_position: + id: uln2003_stepper + position: 250 + - stepper.set_target: + id: uln2003_stepper + target: 250 + - stepper.set_acceleration: + id: uln2003_stepper + acceleration: 250 steps/s^2 + - stepper.set_deceleration: + id: uln2003_stepper + deceleration: 250 steps/s^2 + - stepper.set_speed: + id: uln2003_stepper + speed: 250 steps/s + +stepper: + - platform: uln2003 + id: uln2003_stepper + pin_a: 0 + pin_b: 1 + pin_c: 2 + pin_d: 3 + max_speed: 250 steps/s + acceleration: 100 steps/s^2 + deceleration: 200 steps/s^2 diff --git a/tests/components/ultrasonic/test.esp32-c3-idf.yaml b/tests/components/ultrasonic/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..f1f673d918 --- /dev/null +++ b/tests/components/ultrasonic/test.esp32-c3-idf.yaml @@ -0,0 +1,7 @@ +sensor: + - platform: ultrasonic + id: ultrasonic_sensor1 + name: Ultrasonic Sensor + echo_pin: 4 + trigger_pin: 5 + timeout: 5.5m diff --git a/tests/components/ultrasonic/test.esp32-c3.yaml b/tests/components/ultrasonic/test.esp32-c3.yaml new file mode 100644 index 0000000000..f1f673d918 --- /dev/null +++ b/tests/components/ultrasonic/test.esp32-c3.yaml @@ -0,0 +1,7 @@ +sensor: + - platform: ultrasonic + id: ultrasonic_sensor1 + name: Ultrasonic Sensor + echo_pin: 4 + trigger_pin: 5 + timeout: 5.5m diff --git a/tests/components/ultrasonic/test.esp32-idf.yaml b/tests/components/ultrasonic/test.esp32-idf.yaml new file mode 100644 index 0000000000..f1f673d918 --- /dev/null +++ b/tests/components/ultrasonic/test.esp32-idf.yaml @@ -0,0 +1,7 @@ +sensor: + - platform: ultrasonic + id: ultrasonic_sensor1 + name: Ultrasonic Sensor + echo_pin: 4 + trigger_pin: 5 + timeout: 5.5m diff --git a/tests/components/ultrasonic/test.esp32.yaml b/tests/components/ultrasonic/test.esp32.yaml new file mode 100644 index 0000000000..f1f673d918 --- /dev/null +++ b/tests/components/ultrasonic/test.esp32.yaml @@ -0,0 +1,7 @@ +sensor: + - platform: ultrasonic + id: ultrasonic_sensor1 + name: Ultrasonic Sensor + echo_pin: 4 + trigger_pin: 5 + timeout: 5.5m diff --git a/tests/components/ultrasonic/test.esp8266.yaml b/tests/components/ultrasonic/test.esp8266.yaml new file mode 100644 index 0000000000..f1f673d918 --- /dev/null +++ b/tests/components/ultrasonic/test.esp8266.yaml @@ -0,0 +1,7 @@ +sensor: + - platform: ultrasonic + id: ultrasonic_sensor1 + name: Ultrasonic Sensor + echo_pin: 4 + trigger_pin: 5 + timeout: 5.5m diff --git a/tests/components/ultrasonic/test.rp2040.yaml b/tests/components/ultrasonic/test.rp2040.yaml new file mode 100644 index 0000000000..f1f673d918 --- /dev/null +++ b/tests/components/ultrasonic/test.rp2040.yaml @@ -0,0 +1,7 @@ +sensor: + - platform: ultrasonic + id: ultrasonic_sensor1 + name: Ultrasonic Sensor + echo_pin: 4 + trigger_pin: 5 + timeout: 5.5m diff --git a/tests/components/uptime/test.esp32-c3-idf.yaml b/tests/components/uptime/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..872a0e7402 --- /dev/null +++ b/tests/components/uptime/test.esp32-c3-idf.yaml @@ -0,0 +1,3 @@ +sensor: + - platform: uptime + name: Uptime Sensor diff --git a/tests/components/uptime/test.esp32-c3.yaml b/tests/components/uptime/test.esp32-c3.yaml new file mode 100644 index 0000000000..872a0e7402 --- /dev/null +++ b/tests/components/uptime/test.esp32-c3.yaml @@ -0,0 +1,3 @@ +sensor: + - platform: uptime + name: Uptime Sensor diff --git a/tests/components/uptime/test.esp32-idf.yaml b/tests/components/uptime/test.esp32-idf.yaml new file mode 100644 index 0000000000..872a0e7402 --- /dev/null +++ b/tests/components/uptime/test.esp32-idf.yaml @@ -0,0 +1,3 @@ +sensor: + - platform: uptime + name: Uptime Sensor diff --git a/tests/components/uptime/test.esp32.yaml b/tests/components/uptime/test.esp32.yaml new file mode 100644 index 0000000000..872a0e7402 --- /dev/null +++ b/tests/components/uptime/test.esp32.yaml @@ -0,0 +1,3 @@ +sensor: + - platform: uptime + name: Uptime Sensor diff --git a/tests/components/uptime/test.esp8266.yaml b/tests/components/uptime/test.esp8266.yaml new file mode 100644 index 0000000000..872a0e7402 --- /dev/null +++ b/tests/components/uptime/test.esp8266.yaml @@ -0,0 +1,3 @@ +sensor: + - platform: uptime + name: Uptime Sensor diff --git a/tests/components/uptime/test.rp2040.yaml b/tests/components/uptime/test.rp2040.yaml new file mode 100644 index 0000000000..872a0e7402 --- /dev/null +++ b/tests/components/uptime/test.rp2040.yaml @@ -0,0 +1,3 @@ +sensor: + - platform: uptime + name: Uptime Sensor From 54a68bf069fc11d582f7c50b143b6f428f385e3f Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Wed, 27 Mar 2024 02:15:50 -0500 Subject: [PATCH 1169/2101] Fix spacing in new test yaml (#6441) --- .../growatt_solar/test.esp32-c3-idf.yaml | 30 +++++++++---------- .../growatt_solar/test.esp32-c3.yaml | 30 +++++++++---------- .../growatt_solar/test.esp32-idf.yaml | 30 +++++++++---------- .../components/growatt_solar/test.esp32.yaml | 30 +++++++++---------- .../growatt_solar/test.esp8266.yaml | 30 +++++++++---------- .../components/growatt_solar/test.rp2040.yaml | 30 +++++++++---------- .../key_collector/test.esp32-c3-idf.yaml | 6 ++-- .../key_collector/test.esp32-c3.yaml | 6 ++-- .../key_collector/test.esp32-idf.yaml | 6 ++-- .../components/key_collector/test.esp32.yaml | 6 ++-- .../key_collector/test.esp8266.yaml | 6 ++-- .../components/key_collector/test.rp2040.yaml | 6 ++-- 12 files changed, 108 insertions(+), 108 deletions(-) diff --git a/tests/components/growatt_solar/test.esp32-c3-idf.yaml b/tests/components/growatt_solar/test.esp32-c3-idf.yaml index 3b5e2e4ce4..7e73897856 100644 --- a/tests/components/growatt_solar/test.esp32-c3-idf.yaml +++ b/tests/components/growatt_solar/test.esp32-c3-idf.yaml @@ -15,39 +15,39 @@ sensor: name: Growatt Status Code phase_a: voltage: - name: Growatt Voltage Phase A + name: Growatt Voltage Phase A current: - name: Growatt Current Phase A + name: Growatt Current Phase A active_power: - name: Growatt Power Phase A + name: Growatt Power Phase A phase_b: voltage: - name: Growatt Voltage Phase B + name: Growatt Voltage Phase B current: - name: Growatt Current Phase B + name: Growatt Current Phase B active_power: - name: Growatt Power Phase B + name: Growatt Power Phase B phase_c: voltage: - name: Growatt Voltage Phase C + name: Growatt Voltage Phase C current: - name: Growatt Current Phase C + name: Growatt Current Phase C active_power: - name: Growatt Power Phase C + name: Growatt Power Phase C pv1: voltage: - name: Growatt PV1 Voltage + name: Growatt PV1 Voltage current: - name: Growatt PV1 Current + name: Growatt PV1 Current active_power: - name: Growatt PV1 Active Power + name: Growatt PV1 Active Power pv2: voltage: - name: Growatt PV2 Voltage + name: Growatt PV2 Voltage current: - name: Growatt PV2 Current + name: Growatt PV2 Current active_power: - name: Growatt PV2 Active Power + name: Growatt PV2 Active Power active_power: name: Growatt Grid Active Power pv_active_power: diff --git a/tests/components/growatt_solar/test.esp32-c3.yaml b/tests/components/growatt_solar/test.esp32-c3.yaml index 3b5e2e4ce4..7e73897856 100644 --- a/tests/components/growatt_solar/test.esp32-c3.yaml +++ b/tests/components/growatt_solar/test.esp32-c3.yaml @@ -15,39 +15,39 @@ sensor: name: Growatt Status Code phase_a: voltage: - name: Growatt Voltage Phase A + name: Growatt Voltage Phase A current: - name: Growatt Current Phase A + name: Growatt Current Phase A active_power: - name: Growatt Power Phase A + name: Growatt Power Phase A phase_b: voltage: - name: Growatt Voltage Phase B + name: Growatt Voltage Phase B current: - name: Growatt Current Phase B + name: Growatt Current Phase B active_power: - name: Growatt Power Phase B + name: Growatt Power Phase B phase_c: voltage: - name: Growatt Voltage Phase C + name: Growatt Voltage Phase C current: - name: Growatt Current Phase C + name: Growatt Current Phase C active_power: - name: Growatt Power Phase C + name: Growatt Power Phase C pv1: voltage: - name: Growatt PV1 Voltage + name: Growatt PV1 Voltage current: - name: Growatt PV1 Current + name: Growatt PV1 Current active_power: - name: Growatt PV1 Active Power + name: Growatt PV1 Active Power pv2: voltage: - name: Growatt PV2 Voltage + name: Growatt PV2 Voltage current: - name: Growatt PV2 Current + name: Growatt PV2 Current active_power: - name: Growatt PV2 Active Power + name: Growatt PV2 Active Power active_power: name: Growatt Grid Active Power pv_active_power: diff --git a/tests/components/growatt_solar/test.esp32-idf.yaml b/tests/components/growatt_solar/test.esp32-idf.yaml index a0670fdbd6..654f2ccedf 100644 --- a/tests/components/growatt_solar/test.esp32-idf.yaml +++ b/tests/components/growatt_solar/test.esp32-idf.yaml @@ -15,39 +15,39 @@ sensor: name: Growatt Status Code phase_a: voltage: - name: Growatt Voltage Phase A + name: Growatt Voltage Phase A current: - name: Growatt Current Phase A + name: Growatt Current Phase A active_power: - name: Growatt Power Phase A + name: Growatt Power Phase A phase_b: voltage: - name: Growatt Voltage Phase B + name: Growatt Voltage Phase B current: - name: Growatt Current Phase B + name: Growatt Current Phase B active_power: - name: Growatt Power Phase B + name: Growatt Power Phase B phase_c: voltage: - name: Growatt Voltage Phase C + name: Growatt Voltage Phase C current: - name: Growatt Current Phase C + name: Growatt Current Phase C active_power: - name: Growatt Power Phase C + name: Growatt Power Phase C pv1: voltage: - name: Growatt PV1 Voltage + name: Growatt PV1 Voltage current: - name: Growatt PV1 Current + name: Growatt PV1 Current active_power: - name: Growatt PV1 Active Power + name: Growatt PV1 Active Power pv2: voltage: - name: Growatt PV2 Voltage + name: Growatt PV2 Voltage current: - name: Growatt PV2 Current + name: Growatt PV2 Current active_power: - name: Growatt PV2 Active Power + name: Growatt PV2 Active Power active_power: name: Growatt Grid Active Power pv_active_power: diff --git a/tests/components/growatt_solar/test.esp32.yaml b/tests/components/growatt_solar/test.esp32.yaml index a0670fdbd6..654f2ccedf 100644 --- a/tests/components/growatt_solar/test.esp32.yaml +++ b/tests/components/growatt_solar/test.esp32.yaml @@ -15,39 +15,39 @@ sensor: name: Growatt Status Code phase_a: voltage: - name: Growatt Voltage Phase A + name: Growatt Voltage Phase A current: - name: Growatt Current Phase A + name: Growatt Current Phase A active_power: - name: Growatt Power Phase A + name: Growatt Power Phase A phase_b: voltage: - name: Growatt Voltage Phase B + name: Growatt Voltage Phase B current: - name: Growatt Current Phase B + name: Growatt Current Phase B active_power: - name: Growatt Power Phase B + name: Growatt Power Phase B phase_c: voltage: - name: Growatt Voltage Phase C + name: Growatt Voltage Phase C current: - name: Growatt Current Phase C + name: Growatt Current Phase C active_power: - name: Growatt Power Phase C + name: Growatt Power Phase C pv1: voltage: - name: Growatt PV1 Voltage + name: Growatt PV1 Voltage current: - name: Growatt PV1 Current + name: Growatt PV1 Current active_power: - name: Growatt PV1 Active Power + name: Growatt PV1 Active Power pv2: voltage: - name: Growatt PV2 Voltage + name: Growatt PV2 Voltage current: - name: Growatt PV2 Current + name: Growatt PV2 Current active_power: - name: Growatt PV2 Active Power + name: Growatt PV2 Active Power active_power: name: Growatt Grid Active Power pv_active_power: diff --git a/tests/components/growatt_solar/test.esp8266.yaml b/tests/components/growatt_solar/test.esp8266.yaml index fed27ffda1..a1cf8267ae 100644 --- a/tests/components/growatt_solar/test.esp8266.yaml +++ b/tests/components/growatt_solar/test.esp8266.yaml @@ -15,39 +15,39 @@ sensor: name: Growatt Status Code phase_a: voltage: - name: Growatt Voltage Phase A + name: Growatt Voltage Phase A current: - name: Growatt Current Phase A + name: Growatt Current Phase A active_power: - name: Growatt Power Phase A + name: Growatt Power Phase A phase_b: voltage: - name: Growatt Voltage Phase B + name: Growatt Voltage Phase B current: - name: Growatt Current Phase B + name: Growatt Current Phase B active_power: - name: Growatt Power Phase B + name: Growatt Power Phase B phase_c: voltage: - name: Growatt Voltage Phase C + name: Growatt Voltage Phase C current: - name: Growatt Current Phase C + name: Growatt Current Phase C active_power: - name: Growatt Power Phase C + name: Growatt Power Phase C pv1: voltage: - name: Growatt PV1 Voltage + name: Growatt PV1 Voltage current: - name: Growatt PV1 Current + name: Growatt PV1 Current active_power: - name: Growatt PV1 Active Power + name: Growatt PV1 Active Power pv2: voltage: - name: Growatt PV2 Voltage + name: Growatt PV2 Voltage current: - name: Growatt PV2 Current + name: Growatt PV2 Current active_power: - name: Growatt PV2 Active Power + name: Growatt PV2 Active Power active_power: name: Growatt Grid Active Power pv_active_power: diff --git a/tests/components/growatt_solar/test.rp2040.yaml b/tests/components/growatt_solar/test.rp2040.yaml index 3b5e2e4ce4..7e73897856 100644 --- a/tests/components/growatt_solar/test.rp2040.yaml +++ b/tests/components/growatt_solar/test.rp2040.yaml @@ -15,39 +15,39 @@ sensor: name: Growatt Status Code phase_a: voltage: - name: Growatt Voltage Phase A + name: Growatt Voltage Phase A current: - name: Growatt Current Phase A + name: Growatt Current Phase A active_power: - name: Growatt Power Phase A + name: Growatt Power Phase A phase_b: voltage: - name: Growatt Voltage Phase B + name: Growatt Voltage Phase B current: - name: Growatt Current Phase B + name: Growatt Current Phase B active_power: - name: Growatt Power Phase B + name: Growatt Power Phase B phase_c: voltage: - name: Growatt Voltage Phase C + name: Growatt Voltage Phase C current: - name: Growatt Current Phase C + name: Growatt Current Phase C active_power: - name: Growatt Power Phase C + name: Growatt Power Phase C pv1: voltage: - name: Growatt PV1 Voltage + name: Growatt PV1 Voltage current: - name: Growatt PV1 Current + name: Growatt PV1 Current active_power: - name: Growatt PV1 Active Power + name: Growatt PV1 Active Power pv2: voltage: - name: Growatt PV2 Voltage + name: Growatt PV2 Voltage current: - name: Growatt PV2 Current + name: Growatt PV2 Current active_power: - name: Growatt PV2 Active Power + name: Growatt PV2 Active Power active_power: name: Growatt Grid Active Power pv_active_power: diff --git a/tests/components/key_collector/test.esp32-c3-idf.yaml b/tests/components/key_collector/test.esp32-c3-idf.yaml index a186d4fa23..1f133c5cd8 100644 --- a/tests/components/key_collector/test.esp32-c3-idf.yaml +++ b/tests/components/key_collector/test.esp32-c3-idf.yaml @@ -17,12 +17,12 @@ key_collector: on_progress: - logger.log: format: "input progress: '%s', started by '%c'" - args: [ 'x.c_str()', "(start == 0 ? '~' : start)" ] + args: ['x.c_str()', "(start == 0 ? '~' : start)"] on_result: - logger.log: format: "input result: '%s', started by '%c', ended by '%c'" - args: [ 'x.c_str()', "(start == 0 ? '~' : start)", "(end == 0 ? '~' : end)" ] + args: ['x.c_str()', "(start == 0 ? '~' : start)", "(end == 0 ? '~' : end)"] on_timeout: - logger.log: format: "input timeout: '%s', started by '%c'" - args: [ 'x.c_str()', "(start == 0 ? '~' : start)" ] + args: ['x.c_str()', "(start == 0 ? '~' : start)"] diff --git a/tests/components/key_collector/test.esp32-c3.yaml b/tests/components/key_collector/test.esp32-c3.yaml index a186d4fa23..1f133c5cd8 100644 --- a/tests/components/key_collector/test.esp32-c3.yaml +++ b/tests/components/key_collector/test.esp32-c3.yaml @@ -17,12 +17,12 @@ key_collector: on_progress: - logger.log: format: "input progress: '%s', started by '%c'" - args: [ 'x.c_str()', "(start == 0 ? '~' : start)" ] + args: ['x.c_str()', "(start == 0 ? '~' : start)"] on_result: - logger.log: format: "input result: '%s', started by '%c', ended by '%c'" - args: [ 'x.c_str()', "(start == 0 ? '~' : start)", "(end == 0 ? '~' : end)" ] + args: ['x.c_str()', "(start == 0 ? '~' : start)", "(end == 0 ? '~' : end)"] on_timeout: - logger.log: format: "input timeout: '%s', started by '%c'" - args: [ 'x.c_str()', "(start == 0 ? '~' : start)" ] + args: ['x.c_str()', "(start == 0 ? '~' : start)"] diff --git a/tests/components/key_collector/test.esp32-idf.yaml b/tests/components/key_collector/test.esp32-idf.yaml index d357b33279..7cbe9c0fc1 100644 --- a/tests/components/key_collector/test.esp32-idf.yaml +++ b/tests/components/key_collector/test.esp32-idf.yaml @@ -17,12 +17,12 @@ key_collector: on_progress: - logger.log: format: "input progress: '%s', started by '%c'" - args: [ 'x.c_str()', "(start == 0 ? '~' : start)" ] + args: ['x.c_str()', "(start == 0 ? '~' : start)"] on_result: - logger.log: format: "input result: '%s', started by '%c', ended by '%c'" - args: [ 'x.c_str()', "(start == 0 ? '~' : start)", "(end == 0 ? '~' : end)" ] + args: ['x.c_str()', "(start == 0 ? '~' : start)", "(end == 0 ? '~' : end)"] on_timeout: - logger.log: format: "input timeout: '%s', started by '%c'" - args: [ 'x.c_str()', "(start == 0 ? '~' : start)" ] + args: ['x.c_str()', "(start == 0 ? '~' : start)"] diff --git a/tests/components/key_collector/test.esp32.yaml b/tests/components/key_collector/test.esp32.yaml index d357b33279..7cbe9c0fc1 100644 --- a/tests/components/key_collector/test.esp32.yaml +++ b/tests/components/key_collector/test.esp32.yaml @@ -17,12 +17,12 @@ key_collector: on_progress: - logger.log: format: "input progress: '%s', started by '%c'" - args: [ 'x.c_str()', "(start == 0 ? '~' : start)" ] + args: ['x.c_str()', "(start == 0 ? '~' : start)"] on_result: - logger.log: format: "input result: '%s', started by '%c', ended by '%c'" - args: [ 'x.c_str()', "(start == 0 ? '~' : start)", "(end == 0 ? '~' : end)" ] + args: ['x.c_str()', "(start == 0 ? '~' : start)", "(end == 0 ? '~' : end)"] on_timeout: - logger.log: format: "input timeout: '%s', started by '%c'" - args: [ 'x.c_str()', "(start == 0 ? '~' : start)" ] + args: ['x.c_str()', "(start == 0 ? '~' : start)"] diff --git a/tests/components/key_collector/test.esp8266.yaml b/tests/components/key_collector/test.esp8266.yaml index d357b33279..7cbe9c0fc1 100644 --- a/tests/components/key_collector/test.esp8266.yaml +++ b/tests/components/key_collector/test.esp8266.yaml @@ -17,12 +17,12 @@ key_collector: on_progress: - logger.log: format: "input progress: '%s', started by '%c'" - args: [ 'x.c_str()', "(start == 0 ? '~' : start)" ] + args: ['x.c_str()', "(start == 0 ? '~' : start)"] on_result: - logger.log: format: "input result: '%s', started by '%c', ended by '%c'" - args: [ 'x.c_str()', "(start == 0 ? '~' : start)", "(end == 0 ? '~' : end)" ] + args: ['x.c_str()', "(start == 0 ? '~' : start)", "(end == 0 ? '~' : end)"] on_timeout: - logger.log: format: "input timeout: '%s', started by '%c'" - args: [ 'x.c_str()', "(start == 0 ? '~' : start)" ] + args: ['x.c_str()', "(start == 0 ? '~' : start)"] diff --git a/tests/components/key_collector/test.rp2040.yaml b/tests/components/key_collector/test.rp2040.yaml index a186d4fa23..1f133c5cd8 100644 --- a/tests/components/key_collector/test.rp2040.yaml +++ b/tests/components/key_collector/test.rp2040.yaml @@ -17,12 +17,12 @@ key_collector: on_progress: - logger.log: format: "input progress: '%s', started by '%c'" - args: [ 'x.c_str()', "(start == 0 ? '~' : start)" ] + args: ['x.c_str()', "(start == 0 ? '~' : start)"] on_result: - logger.log: format: "input result: '%s', started by '%c', ended by '%c'" - args: [ 'x.c_str()', "(start == 0 ? '~' : start)", "(end == 0 ? '~' : end)" ] + args: ['x.c_str()', "(start == 0 ? '~' : start)", "(end == 0 ? '~' : end)"] on_timeout: - logger.log: format: "input timeout: '%s', started by '%c'" - args: [ 'x.c_str()', "(start == 0 ? '~' : start)" ] + args: ['x.c_str()', "(start == 0 ? '~' : start)"] From 0630cdded376eeefd3a628cfa19d70b1f2e764c7 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Wed, 27 Mar 2024 02:15:59 -0500 Subject: [PATCH 1170/2101] Add some components to the new testing framework (W) (#6232) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- .../components/wake_on_lan/test.esp32-c3.yaml | 9 ++ tests/components/wake_on_lan/test.esp32.yaml | 9 ++ .../components/wake_on_lan/test.esp8266.yaml | 9 ++ tests/components/wake_on_lan/test.rp2040.yaml | 9 ++ .../waveshare_epaper/test.esp32-c3-idf.yaml | 107 ++++++++++++++++++ .../waveshare_epaper/test.esp32-c3.yaml | 107 ++++++++++++++++++ .../waveshare_epaper/test.esp32-idf.yaml | 107 ++++++++++++++++++ .../waveshare_epaper/test.esp8266.yaml | 107 ++++++++++++++++++ .../waveshare_epaper/test.rp2040.yaml | 107 ++++++++++++++++++ .../web_server/test.esp32-c3-idf.yaml | 7 ++ .../components/web_server/test.esp32-c3.yaml | 7 ++ .../components/web_server/test.esp32-idf.yaml | 7 ++ tests/components/web_server/test.esp32.yaml | 7 ++ tests/components/web_server/test.esp8266.yaml | 7 ++ .../whirlpool/test.esp32-c3-idf.yaml | 7 ++ tests/components/whirlpool/test.esp32-c3.yaml | 7 ++ .../components/whirlpool/test.esp32-idf.yaml | 7 ++ tests/components/whirlpool/test.esp32.yaml | 7 ++ tests/components/whirlpool/test.esp8266.yaml | 7 ++ .../components/whynter/test.esp32-c3-idf.yaml | 7 ++ tests/components/whynter/test.esp32-c3.yaml | 7 ++ tests/components/whynter/test.esp32-idf.yaml | 7 ++ tests/components/whynter/test.esp32.yaml | 7 ++ tests/components/whynter/test.esp8266.yaml | 7 ++ .../components/wiegand/test.esp32-c3-idf.yaml | 10 ++ tests/components/wiegand/test.esp32-c3.yaml | 10 ++ tests/components/wiegand/test.esp32-idf.yaml | 10 ++ tests/components/wiegand/test.esp32.yaml | 10 ++ tests/components/wiegand/test.esp8266.yaml | 10 ++ tests/components/wiegand/test.rp2040.yaml | 10 ++ tests/components/wifi/test.esp32-c3-idf.yaml | 9 ++ tests/components/wifi/test.esp32-c3.yaml | 9 ++ tests/components/wifi/test.esp32-idf.yaml | 9 ++ tests/components/wifi/test.esp32.yaml | 9 ++ tests/components/wifi/test.esp8266.yaml | 9 ++ tests/components/wifi/test.rp2040.yaml | 9 ++ .../wifi_info/test.esp32-c3-idf.yaml | 18 +++ tests/components/wifi_info/test.esp32-c3.yaml | 18 +++ .../components/wifi_info/test.esp32-idf.yaml | 18 +++ tests/components/wifi_info/test.esp32.yaml | 18 +++ tests/components/wifi_info/test.esp8266.yaml | 18 +++ tests/components/wifi_info/test.rp2040.yaml | 18 +++ .../wifi_signal/test.esp32-c3-idf.yaml | 8 ++ .../components/wifi_signal/test.esp32-c3.yaml | 8 ++ .../wifi_signal/test.esp32-idf.yaml | 8 ++ tests/components/wifi_signal/test.esp32.yaml | 8 ++ .../components/wifi_signal/test.esp8266.yaml | 8 ++ tests/components/wifi_signal/test.rp2040.yaml | 8 ++ .../wireguard/test.esp32-c3-idf.yaml | 60 ++++++++++ tests/components/wireguard/test.esp32-c3.yaml | 60 ++++++++++ .../components/wl_134/test.esp32-c3-idf.yaml | 10 ++ tests/components/wl_134/test.esp32-c3.yaml | 10 ++ tests/components/wl_134/test.esp32-idf.yaml | 10 ++ tests/components/wl_134/test.esp32.yaml | 10 ++ tests/components/wl_134/test.esp8266.yaml | 10 ++ tests/components/wl_134/test.rp2040.yaml | 10 ++ tests/components/wled/test.esp32-c3.yaml | 17 +++ tests/components/wled/test.esp32.yaml | 17 +++ tests/components/wled/test.esp8266.yaml | 17 +++ 59 files changed, 1177 insertions(+) create mode 100644 tests/components/wake_on_lan/test.esp32-c3.yaml create mode 100644 tests/components/wake_on_lan/test.esp32.yaml create mode 100644 tests/components/wake_on_lan/test.esp8266.yaml create mode 100644 tests/components/wake_on_lan/test.rp2040.yaml create mode 100644 tests/components/waveshare_epaper/test.esp32-c3-idf.yaml create mode 100644 tests/components/waveshare_epaper/test.esp32-c3.yaml create mode 100644 tests/components/waveshare_epaper/test.esp32-idf.yaml create mode 100644 tests/components/waveshare_epaper/test.esp8266.yaml create mode 100644 tests/components/waveshare_epaper/test.rp2040.yaml create mode 100644 tests/components/web_server/test.esp32-c3-idf.yaml create mode 100644 tests/components/web_server/test.esp32-c3.yaml create mode 100644 tests/components/web_server/test.esp32-idf.yaml create mode 100644 tests/components/web_server/test.esp32.yaml create mode 100644 tests/components/web_server/test.esp8266.yaml create mode 100644 tests/components/whirlpool/test.esp32-c3-idf.yaml create mode 100644 tests/components/whirlpool/test.esp32-c3.yaml create mode 100644 tests/components/whirlpool/test.esp32-idf.yaml create mode 100644 tests/components/whirlpool/test.esp32.yaml create mode 100644 tests/components/whirlpool/test.esp8266.yaml create mode 100644 tests/components/whynter/test.esp32-c3-idf.yaml create mode 100644 tests/components/whynter/test.esp32-c3.yaml create mode 100644 tests/components/whynter/test.esp32-idf.yaml create mode 100644 tests/components/whynter/test.esp32.yaml create mode 100644 tests/components/whynter/test.esp8266.yaml create mode 100644 tests/components/wiegand/test.esp32-c3-idf.yaml create mode 100644 tests/components/wiegand/test.esp32-c3.yaml create mode 100644 tests/components/wiegand/test.esp32-idf.yaml create mode 100644 tests/components/wiegand/test.esp32.yaml create mode 100644 tests/components/wiegand/test.esp8266.yaml create mode 100644 tests/components/wiegand/test.rp2040.yaml create mode 100644 tests/components/wifi/test.esp32-c3-idf.yaml create mode 100644 tests/components/wifi/test.esp32-c3.yaml create mode 100644 tests/components/wifi/test.esp32-idf.yaml create mode 100644 tests/components/wifi/test.esp32.yaml create mode 100644 tests/components/wifi/test.esp8266.yaml create mode 100644 tests/components/wifi/test.rp2040.yaml create mode 100644 tests/components/wifi_info/test.esp32-c3-idf.yaml create mode 100644 tests/components/wifi_info/test.esp32-c3.yaml create mode 100644 tests/components/wifi_info/test.esp32-idf.yaml create mode 100644 tests/components/wifi_info/test.esp32.yaml create mode 100644 tests/components/wifi_info/test.esp8266.yaml create mode 100644 tests/components/wifi_info/test.rp2040.yaml create mode 100644 tests/components/wifi_signal/test.esp32-c3-idf.yaml create mode 100644 tests/components/wifi_signal/test.esp32-c3.yaml create mode 100644 tests/components/wifi_signal/test.esp32-idf.yaml create mode 100644 tests/components/wifi_signal/test.esp32.yaml create mode 100644 tests/components/wifi_signal/test.esp8266.yaml create mode 100644 tests/components/wifi_signal/test.rp2040.yaml create mode 100644 tests/components/wireguard/test.esp32-c3-idf.yaml create mode 100644 tests/components/wireguard/test.esp32-c3.yaml create mode 100644 tests/components/wl_134/test.esp32-c3-idf.yaml create mode 100644 tests/components/wl_134/test.esp32-c3.yaml create mode 100644 tests/components/wl_134/test.esp32-idf.yaml create mode 100644 tests/components/wl_134/test.esp32.yaml create mode 100644 tests/components/wl_134/test.esp8266.yaml create mode 100644 tests/components/wl_134/test.rp2040.yaml create mode 100644 tests/components/wled/test.esp32-c3.yaml create mode 100644 tests/components/wled/test.esp32.yaml create mode 100644 tests/components/wled/test.esp8266.yaml diff --git a/tests/components/wake_on_lan/test.esp32-c3.yaml b/tests/components/wake_on_lan/test.esp32-c3.yaml new file mode 100644 index 0000000000..6a5351b624 --- /dev/null +++ b/tests/components/wake_on_lan/test.esp32-c3.yaml @@ -0,0 +1,9 @@ +wifi: + ssid: MySSID + password: password1 + +button: + - platform: wake_on_lan + id: wol_1 + name: wol_test_1 + target_mac_address: 12:34:56:78:90:ab diff --git a/tests/components/wake_on_lan/test.esp32.yaml b/tests/components/wake_on_lan/test.esp32.yaml new file mode 100644 index 0000000000..6a5351b624 --- /dev/null +++ b/tests/components/wake_on_lan/test.esp32.yaml @@ -0,0 +1,9 @@ +wifi: + ssid: MySSID + password: password1 + +button: + - platform: wake_on_lan + id: wol_1 + name: wol_test_1 + target_mac_address: 12:34:56:78:90:ab diff --git a/tests/components/wake_on_lan/test.esp8266.yaml b/tests/components/wake_on_lan/test.esp8266.yaml new file mode 100644 index 0000000000..6a5351b624 --- /dev/null +++ b/tests/components/wake_on_lan/test.esp8266.yaml @@ -0,0 +1,9 @@ +wifi: + ssid: MySSID + password: password1 + +button: + - platform: wake_on_lan + id: wol_1 + name: wol_test_1 + target_mac_address: 12:34:56:78:90:ab diff --git a/tests/components/wake_on_lan/test.rp2040.yaml b/tests/components/wake_on_lan/test.rp2040.yaml new file mode 100644 index 0000000000..6a5351b624 --- /dev/null +++ b/tests/components/wake_on_lan/test.rp2040.yaml @@ -0,0 +1,9 @@ +wifi: + ssid: MySSID + password: password1 + +button: + - platform: wake_on_lan + id: wol_1 + name: wol_test_1 + target_mac_address: 12:34:56:78:90:ab diff --git a/tests/components/waveshare_epaper/test.esp32-c3-idf.yaml b/tests/components/waveshare_epaper/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..1c4547b7b4 --- /dev/null +++ b/tests/components/waveshare_epaper/test.esp32-c3-idf.yaml @@ -0,0 +1,107 @@ +spi: + - id: spi_waveshare_epaper + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +display: + - platform: waveshare_epaper + cs_pin: + allow_other_uses: true + number: 4 + dc_pin: + allow_other_uses: true + number: 4 + busy_pin: + allow_other_uses: true + number: 4 + reset_pin: + allow_other_uses: true + number: 4 + model: 2.13in-ttgo-b1 + full_update_every: 30 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - platform: waveshare_epaper + cs_pin: + allow_other_uses: true + number: 4 + dc_pin: + allow_other_uses: true + number: 4 + busy_pin: + allow_other_uses: true + number: 4 + reset_pin: + allow_other_uses: true + number: 4 + model: 2.90in + full_update_every: 30 + reset_duration: 200ms + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - platform: waveshare_epaper + cs_pin: + allow_other_uses: true + number: 4 + dc_pin: + allow_other_uses: true + number: 4 + busy_pin: + allow_other_uses: true + number: 4 + reset_pin: + allow_other_uses: true + number: 4 + model: 2.90inv2 + full_update_every: 30 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - platform: waveshare_epaper + cs_pin: + allow_other_uses: true + number: 4 + dc_pin: + allow_other_uses: true + number: 4 + busy_pin: + allow_other_uses: true + number: 4 + reset_pin: + allow_other_uses: true + number: 4 + model: 2.70in-b + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - platform: waveshare_epaper + cs_pin: + allow_other_uses: true + number: 4 + dc_pin: + allow_other_uses: true + number: 4 + busy_pin: + allow_other_uses: true + number: 4 + reset_pin: + allow_other_uses: true + number: 4 + model: 2.70in-bv2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - platform: waveshare_epaper + cs_pin: + allow_other_uses: true + number: 4 + dc_pin: + allow_other_uses: true + number: 4 + busy_pin: + allow_other_uses: true + number: 4 + reset_pin: + allow_other_uses: true + number: 4 + model: 1.54in-m5coreink-m09 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); diff --git a/tests/components/waveshare_epaper/test.esp32-c3.yaml b/tests/components/waveshare_epaper/test.esp32-c3.yaml new file mode 100644 index 0000000000..1c4547b7b4 --- /dev/null +++ b/tests/components/waveshare_epaper/test.esp32-c3.yaml @@ -0,0 +1,107 @@ +spi: + - id: spi_waveshare_epaper + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +display: + - platform: waveshare_epaper + cs_pin: + allow_other_uses: true + number: 4 + dc_pin: + allow_other_uses: true + number: 4 + busy_pin: + allow_other_uses: true + number: 4 + reset_pin: + allow_other_uses: true + number: 4 + model: 2.13in-ttgo-b1 + full_update_every: 30 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - platform: waveshare_epaper + cs_pin: + allow_other_uses: true + number: 4 + dc_pin: + allow_other_uses: true + number: 4 + busy_pin: + allow_other_uses: true + number: 4 + reset_pin: + allow_other_uses: true + number: 4 + model: 2.90in + full_update_every: 30 + reset_duration: 200ms + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - platform: waveshare_epaper + cs_pin: + allow_other_uses: true + number: 4 + dc_pin: + allow_other_uses: true + number: 4 + busy_pin: + allow_other_uses: true + number: 4 + reset_pin: + allow_other_uses: true + number: 4 + model: 2.90inv2 + full_update_every: 30 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - platform: waveshare_epaper + cs_pin: + allow_other_uses: true + number: 4 + dc_pin: + allow_other_uses: true + number: 4 + busy_pin: + allow_other_uses: true + number: 4 + reset_pin: + allow_other_uses: true + number: 4 + model: 2.70in-b + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - platform: waveshare_epaper + cs_pin: + allow_other_uses: true + number: 4 + dc_pin: + allow_other_uses: true + number: 4 + busy_pin: + allow_other_uses: true + number: 4 + reset_pin: + allow_other_uses: true + number: 4 + model: 2.70in-bv2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - platform: waveshare_epaper + cs_pin: + allow_other_uses: true + number: 4 + dc_pin: + allow_other_uses: true + number: 4 + busy_pin: + allow_other_uses: true + number: 4 + reset_pin: + allow_other_uses: true + number: 4 + model: 1.54in-m5coreink-m09 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); diff --git a/tests/components/waveshare_epaper/test.esp32-idf.yaml b/tests/components/waveshare_epaper/test.esp32-idf.yaml new file mode 100644 index 0000000000..b6082fcfbf --- /dev/null +++ b/tests/components/waveshare_epaper/test.esp32-idf.yaml @@ -0,0 +1,107 @@ +spi: + - id: spi_bme280 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +display: + - platform: waveshare_epaper + cs_pin: + allow_other_uses: true + number: 4 + dc_pin: + allow_other_uses: true + number: 4 + busy_pin: + allow_other_uses: true + number: 4 + reset_pin: + allow_other_uses: true + number: 4 + model: 2.13in-ttgo-b1 + full_update_every: 30 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - platform: waveshare_epaper + cs_pin: + allow_other_uses: true + number: 4 + dc_pin: + allow_other_uses: true + number: 4 + busy_pin: + allow_other_uses: true + number: 4 + reset_pin: + allow_other_uses: true + number: 4 + model: 2.90in + full_update_every: 30 + reset_duration: 200ms + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - platform: waveshare_epaper + cs_pin: + allow_other_uses: true + number: 4 + dc_pin: + allow_other_uses: true + number: 4 + busy_pin: + allow_other_uses: true + number: 4 + reset_pin: + allow_other_uses: true + number: 4 + model: 2.90inv2 + full_update_every: 30 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - platform: waveshare_epaper + cs_pin: + allow_other_uses: true + number: 4 + dc_pin: + allow_other_uses: true + number: 4 + busy_pin: + allow_other_uses: true + number: 4 + reset_pin: + allow_other_uses: true + number: 4 + model: 2.70in-b + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - platform: waveshare_epaper + cs_pin: + allow_other_uses: true + number: 4 + dc_pin: + allow_other_uses: true + number: 4 + busy_pin: + allow_other_uses: true + number: 4 + reset_pin: + allow_other_uses: true + number: 4 + model: 2.70in-bv2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - platform: waveshare_epaper + cs_pin: + allow_other_uses: true + number: 4 + dc_pin: + allow_other_uses: true + number: 4 + busy_pin: + allow_other_uses: true + number: 4 + reset_pin: + allow_other_uses: true + number: 4 + model: 1.54in-m5coreink-m09 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); diff --git a/tests/components/waveshare_epaper/test.esp8266.yaml b/tests/components/waveshare_epaper/test.esp8266.yaml new file mode 100644 index 0000000000..1f076a67be --- /dev/null +++ b/tests/components/waveshare_epaper/test.esp8266.yaml @@ -0,0 +1,107 @@ +spi: + - id: spi_bme280 + clk_pin: 14 + mosi_pin: 13 + miso_pin: 12 + +display: + - platform: waveshare_epaper + cs_pin: + allow_other_uses: true + number: 4 + dc_pin: + allow_other_uses: true + number: 4 + busy_pin: + allow_other_uses: true + number: 4 + reset_pin: + allow_other_uses: true + number: 4 + model: 2.13in-ttgo-b1 + full_update_every: 30 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - platform: waveshare_epaper + cs_pin: + allow_other_uses: true + number: 4 + dc_pin: + allow_other_uses: true + number: 4 + busy_pin: + allow_other_uses: true + number: 4 + reset_pin: + allow_other_uses: true + number: 4 + model: 2.90in + full_update_every: 30 + reset_duration: 200ms + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - platform: waveshare_epaper + cs_pin: + allow_other_uses: true + number: 4 + dc_pin: + allow_other_uses: true + number: 4 + busy_pin: + allow_other_uses: true + number: 4 + reset_pin: + allow_other_uses: true + number: 4 + model: 2.90inv2 + full_update_every: 30 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - platform: waveshare_epaper + cs_pin: + allow_other_uses: true + number: 4 + dc_pin: + allow_other_uses: true + number: 4 + busy_pin: + allow_other_uses: true + number: 4 + reset_pin: + allow_other_uses: true + number: 4 + model: 2.70in-b + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - platform: waveshare_epaper + cs_pin: + allow_other_uses: true + number: 4 + dc_pin: + allow_other_uses: true + number: 4 + busy_pin: + allow_other_uses: true + number: 4 + reset_pin: + allow_other_uses: true + number: 4 + model: 2.70in-bv2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - platform: waveshare_epaper + cs_pin: + allow_other_uses: true + number: 4 + dc_pin: + allow_other_uses: true + number: 4 + busy_pin: + allow_other_uses: true + number: 4 + reset_pin: + allow_other_uses: true + number: 4 + model: 1.54in-m5coreink-m09 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); diff --git a/tests/components/waveshare_epaper/test.rp2040.yaml b/tests/components/waveshare_epaper/test.rp2040.yaml new file mode 100644 index 0000000000..6050062d7e --- /dev/null +++ b/tests/components/waveshare_epaper/test.rp2040.yaml @@ -0,0 +1,107 @@ +spi: + - id: spi_bme280 + clk_pin: 2 + mosi_pin: 3 + miso_pin: 4 + +display: + - platform: waveshare_epaper + cs_pin: + allow_other_uses: true + number: 5 + dc_pin: + allow_other_uses: true + number: 5 + busy_pin: + allow_other_uses: true + number: 5 + reset_pin: + allow_other_uses: true + number: 5 + model: 2.13in-ttgo-b1 + full_update_every: 30 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - platform: waveshare_epaper + cs_pin: + allow_other_uses: true + number: 5 + dc_pin: + allow_other_uses: true + number: 5 + busy_pin: + allow_other_uses: true + number: 5 + reset_pin: + allow_other_uses: true + number: 5 + model: 2.90in + full_update_every: 30 + reset_duration: 200ms + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - platform: waveshare_epaper + cs_pin: + allow_other_uses: true + number: 5 + dc_pin: + allow_other_uses: true + number: 5 + busy_pin: + allow_other_uses: true + number: 5 + reset_pin: + allow_other_uses: true + number: 5 + model: 2.90inv2 + full_update_every: 30 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - platform: waveshare_epaper + cs_pin: + allow_other_uses: true + number: 5 + dc_pin: + allow_other_uses: true + number: 5 + busy_pin: + allow_other_uses: true + number: 5 + reset_pin: + allow_other_uses: true + number: 5 + model: 2.70in-b + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - platform: waveshare_epaper + cs_pin: + allow_other_uses: true + number: 5 + dc_pin: + allow_other_uses: true + number: 5 + busy_pin: + allow_other_uses: true + number: 5 + reset_pin: + allow_other_uses: true + number: 5 + model: 2.70in-bv2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - platform: waveshare_epaper + cs_pin: + allow_other_uses: true + number: 5 + dc_pin: + allow_other_uses: true + number: 5 + busy_pin: + allow_other_uses: true + number: 5 + reset_pin: + allow_other_uses: true + number: 5 + model: 1.54in-m5coreink-m09 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); diff --git a/tests/components/web_server/test.esp32-c3-idf.yaml b/tests/components/web_server/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..94388726c3 --- /dev/null +++ b/tests/components/web_server/test.esp32-c3-idf.yaml @@ -0,0 +1,7 @@ +wifi: + ssid: MySSID + password: password1 + +web_server: + port: 8080 + version: 2 diff --git a/tests/components/web_server/test.esp32-c3.yaml b/tests/components/web_server/test.esp32-c3.yaml new file mode 100644 index 0000000000..94388726c3 --- /dev/null +++ b/tests/components/web_server/test.esp32-c3.yaml @@ -0,0 +1,7 @@ +wifi: + ssid: MySSID + password: password1 + +web_server: + port: 8080 + version: 2 diff --git a/tests/components/web_server/test.esp32-idf.yaml b/tests/components/web_server/test.esp32-idf.yaml new file mode 100644 index 0000000000..94388726c3 --- /dev/null +++ b/tests/components/web_server/test.esp32-idf.yaml @@ -0,0 +1,7 @@ +wifi: + ssid: MySSID + password: password1 + +web_server: + port: 8080 + version: 2 diff --git a/tests/components/web_server/test.esp32.yaml b/tests/components/web_server/test.esp32.yaml new file mode 100644 index 0000000000..94388726c3 --- /dev/null +++ b/tests/components/web_server/test.esp32.yaml @@ -0,0 +1,7 @@ +wifi: + ssid: MySSID + password: password1 + +web_server: + port: 8080 + version: 2 diff --git a/tests/components/web_server/test.esp8266.yaml b/tests/components/web_server/test.esp8266.yaml new file mode 100644 index 0000000000..94388726c3 --- /dev/null +++ b/tests/components/web_server/test.esp8266.yaml @@ -0,0 +1,7 @@ +wifi: + ssid: MySSID + password: password1 + +web_server: + port: 8080 + version: 2 diff --git a/tests/components/whirlpool/test.esp32-c3-idf.yaml b/tests/components/whirlpool/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..4d0afc39a4 --- /dev/null +++ b/tests/components/whirlpool/test.esp32-c3-idf.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +climate: + - platform: whirlpool + name: Whirlpool Climate diff --git a/tests/components/whirlpool/test.esp32-c3.yaml b/tests/components/whirlpool/test.esp32-c3.yaml new file mode 100644 index 0000000000..4d0afc39a4 --- /dev/null +++ b/tests/components/whirlpool/test.esp32-c3.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +climate: + - platform: whirlpool + name: Whirlpool Climate diff --git a/tests/components/whirlpool/test.esp32-idf.yaml b/tests/components/whirlpool/test.esp32-idf.yaml new file mode 100644 index 0000000000..4d0afc39a4 --- /dev/null +++ b/tests/components/whirlpool/test.esp32-idf.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +climate: + - platform: whirlpool + name: Whirlpool Climate diff --git a/tests/components/whirlpool/test.esp32.yaml b/tests/components/whirlpool/test.esp32.yaml new file mode 100644 index 0000000000..4d0afc39a4 --- /dev/null +++ b/tests/components/whirlpool/test.esp32.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +climate: + - platform: whirlpool + name: Whirlpool Climate diff --git a/tests/components/whirlpool/test.esp8266.yaml b/tests/components/whirlpool/test.esp8266.yaml new file mode 100644 index 0000000000..efd530c160 --- /dev/null +++ b/tests/components/whirlpool/test.esp8266.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 5 + carrier_duty_percent: 50% + +climate: + - platform: whirlpool + name: Whirlpool Climate diff --git a/tests/components/whynter/test.esp32-c3-idf.yaml b/tests/components/whynter/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..dc8fb9584d --- /dev/null +++ b/tests/components/whynter/test.esp32-c3-idf.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +climate: + - platform: whynter + name: Whynter Climate diff --git a/tests/components/whynter/test.esp32-c3.yaml b/tests/components/whynter/test.esp32-c3.yaml new file mode 100644 index 0000000000..dc8fb9584d --- /dev/null +++ b/tests/components/whynter/test.esp32-c3.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +climate: + - platform: whynter + name: Whynter Climate diff --git a/tests/components/whynter/test.esp32-idf.yaml b/tests/components/whynter/test.esp32-idf.yaml new file mode 100644 index 0000000000..dc8fb9584d --- /dev/null +++ b/tests/components/whynter/test.esp32-idf.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +climate: + - platform: whynter + name: Whynter Climate diff --git a/tests/components/whynter/test.esp32.yaml b/tests/components/whynter/test.esp32.yaml new file mode 100644 index 0000000000..dc8fb9584d --- /dev/null +++ b/tests/components/whynter/test.esp32.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +climate: + - platform: whynter + name: Whynter Climate diff --git a/tests/components/whynter/test.esp8266.yaml b/tests/components/whynter/test.esp8266.yaml new file mode 100644 index 0000000000..a656a7427d --- /dev/null +++ b/tests/components/whynter/test.esp8266.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 5 + carrier_duty_percent: 50% + +climate: + - platform: whynter + name: Whynter Climate diff --git a/tests/components/wiegand/test.esp32-c3-idf.yaml b/tests/components/wiegand/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..4e15a44b89 --- /dev/null +++ b/tests/components/wiegand/test.esp32-c3-idf.yaml @@ -0,0 +1,10 @@ +wiegand: + - id: test_wiegand + d0: 5 + d1: 4 + on_key: + - lambda: ESP_LOGI("KEY", "Received key %d", x); + on_tag: + - lambda: ESP_LOGI("TAG", "Received tag %s", x.c_str()); + on_raw: + - lambda: ESP_LOGI("RAW", "Received raw %d bits, value %llx", bits, value); diff --git a/tests/components/wiegand/test.esp32-c3.yaml b/tests/components/wiegand/test.esp32-c3.yaml new file mode 100644 index 0000000000..4e15a44b89 --- /dev/null +++ b/tests/components/wiegand/test.esp32-c3.yaml @@ -0,0 +1,10 @@ +wiegand: + - id: test_wiegand + d0: 5 + d1: 4 + on_key: + - lambda: ESP_LOGI("KEY", "Received key %d", x); + on_tag: + - lambda: ESP_LOGI("TAG", "Received tag %s", x.c_str()); + on_raw: + - lambda: ESP_LOGI("RAW", "Received raw %d bits, value %llx", bits, value); diff --git a/tests/components/wiegand/test.esp32-idf.yaml b/tests/components/wiegand/test.esp32-idf.yaml new file mode 100644 index 0000000000..4e15a44b89 --- /dev/null +++ b/tests/components/wiegand/test.esp32-idf.yaml @@ -0,0 +1,10 @@ +wiegand: + - id: test_wiegand + d0: 5 + d1: 4 + on_key: + - lambda: ESP_LOGI("KEY", "Received key %d", x); + on_tag: + - lambda: ESP_LOGI("TAG", "Received tag %s", x.c_str()); + on_raw: + - lambda: ESP_LOGI("RAW", "Received raw %d bits, value %llx", bits, value); diff --git a/tests/components/wiegand/test.esp32.yaml b/tests/components/wiegand/test.esp32.yaml new file mode 100644 index 0000000000..4e15a44b89 --- /dev/null +++ b/tests/components/wiegand/test.esp32.yaml @@ -0,0 +1,10 @@ +wiegand: + - id: test_wiegand + d0: 5 + d1: 4 + on_key: + - lambda: ESP_LOGI("KEY", "Received key %d", x); + on_tag: + - lambda: ESP_LOGI("TAG", "Received tag %s", x.c_str()); + on_raw: + - lambda: ESP_LOGI("RAW", "Received raw %d bits, value %llx", bits, value); diff --git a/tests/components/wiegand/test.esp8266.yaml b/tests/components/wiegand/test.esp8266.yaml new file mode 100644 index 0000000000..4e15a44b89 --- /dev/null +++ b/tests/components/wiegand/test.esp8266.yaml @@ -0,0 +1,10 @@ +wiegand: + - id: test_wiegand + d0: 5 + d1: 4 + on_key: + - lambda: ESP_LOGI("KEY", "Received key %d", x); + on_tag: + - lambda: ESP_LOGI("TAG", "Received tag %s", x.c_str()); + on_raw: + - lambda: ESP_LOGI("RAW", "Received raw %d bits, value %llx", bits, value); diff --git a/tests/components/wiegand/test.rp2040.yaml b/tests/components/wiegand/test.rp2040.yaml new file mode 100644 index 0000000000..4e15a44b89 --- /dev/null +++ b/tests/components/wiegand/test.rp2040.yaml @@ -0,0 +1,10 @@ +wiegand: + - id: test_wiegand + d0: 5 + d1: 4 + on_key: + - lambda: ESP_LOGI("KEY", "Received key %d", x); + on_tag: + - lambda: ESP_LOGI("TAG", "Received tag %s", x.c_str()); + on_raw: + - lambda: ESP_LOGI("RAW", "Received raw %d bits, value %llx", bits, value); diff --git a/tests/components/wifi/test.esp32-c3-idf.yaml b/tests/components/wifi/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..003f6347be --- /dev/null +++ b/tests/components/wifi/test.esp32-c3-idf.yaml @@ -0,0 +1,9 @@ +esphome: + on_boot: + then: + - wifi.disable + - wifi.enable + +wifi: + ssid: MySSID + password: password1 diff --git a/tests/components/wifi/test.esp32-c3.yaml b/tests/components/wifi/test.esp32-c3.yaml new file mode 100644 index 0000000000..003f6347be --- /dev/null +++ b/tests/components/wifi/test.esp32-c3.yaml @@ -0,0 +1,9 @@ +esphome: + on_boot: + then: + - wifi.disable + - wifi.enable + +wifi: + ssid: MySSID + password: password1 diff --git a/tests/components/wifi/test.esp32-idf.yaml b/tests/components/wifi/test.esp32-idf.yaml new file mode 100644 index 0000000000..003f6347be --- /dev/null +++ b/tests/components/wifi/test.esp32-idf.yaml @@ -0,0 +1,9 @@ +esphome: + on_boot: + then: + - wifi.disable + - wifi.enable + +wifi: + ssid: MySSID + password: password1 diff --git a/tests/components/wifi/test.esp32.yaml b/tests/components/wifi/test.esp32.yaml new file mode 100644 index 0000000000..003f6347be --- /dev/null +++ b/tests/components/wifi/test.esp32.yaml @@ -0,0 +1,9 @@ +esphome: + on_boot: + then: + - wifi.disable + - wifi.enable + +wifi: + ssid: MySSID + password: password1 diff --git a/tests/components/wifi/test.esp8266.yaml b/tests/components/wifi/test.esp8266.yaml new file mode 100644 index 0000000000..003f6347be --- /dev/null +++ b/tests/components/wifi/test.esp8266.yaml @@ -0,0 +1,9 @@ +esphome: + on_boot: + then: + - wifi.disable + - wifi.enable + +wifi: + ssid: MySSID + password: password1 diff --git a/tests/components/wifi/test.rp2040.yaml b/tests/components/wifi/test.rp2040.yaml new file mode 100644 index 0000000000..003f6347be --- /dev/null +++ b/tests/components/wifi/test.rp2040.yaml @@ -0,0 +1,9 @@ +esphome: + on_boot: + then: + - wifi.disable + - wifi.enable + +wifi: + ssid: MySSID + password: password1 diff --git a/tests/components/wifi_info/test.esp32-c3-idf.yaml b/tests/components/wifi_info/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..cf5ea563ba --- /dev/null +++ b/tests/components/wifi_info/test.esp32-c3-idf.yaml @@ -0,0 +1,18 @@ +wifi: + ssid: MySSID + password: password1 + +text_sensor: + - platform: wifi_info + scan_results: + name: Scan Results + ip_address: + name: IP Address + ssid: + name: SSID + bssid: + name: BSSID + mac_address: + name: Mac Address + dns_address: + name: DNS ADdress diff --git a/tests/components/wifi_info/test.esp32-c3.yaml b/tests/components/wifi_info/test.esp32-c3.yaml new file mode 100644 index 0000000000..cf5ea563ba --- /dev/null +++ b/tests/components/wifi_info/test.esp32-c3.yaml @@ -0,0 +1,18 @@ +wifi: + ssid: MySSID + password: password1 + +text_sensor: + - platform: wifi_info + scan_results: + name: Scan Results + ip_address: + name: IP Address + ssid: + name: SSID + bssid: + name: BSSID + mac_address: + name: Mac Address + dns_address: + name: DNS ADdress diff --git a/tests/components/wifi_info/test.esp32-idf.yaml b/tests/components/wifi_info/test.esp32-idf.yaml new file mode 100644 index 0000000000..cf5ea563ba --- /dev/null +++ b/tests/components/wifi_info/test.esp32-idf.yaml @@ -0,0 +1,18 @@ +wifi: + ssid: MySSID + password: password1 + +text_sensor: + - platform: wifi_info + scan_results: + name: Scan Results + ip_address: + name: IP Address + ssid: + name: SSID + bssid: + name: BSSID + mac_address: + name: Mac Address + dns_address: + name: DNS ADdress diff --git a/tests/components/wifi_info/test.esp32.yaml b/tests/components/wifi_info/test.esp32.yaml new file mode 100644 index 0000000000..cf5ea563ba --- /dev/null +++ b/tests/components/wifi_info/test.esp32.yaml @@ -0,0 +1,18 @@ +wifi: + ssid: MySSID + password: password1 + +text_sensor: + - platform: wifi_info + scan_results: + name: Scan Results + ip_address: + name: IP Address + ssid: + name: SSID + bssid: + name: BSSID + mac_address: + name: Mac Address + dns_address: + name: DNS ADdress diff --git a/tests/components/wifi_info/test.esp8266.yaml b/tests/components/wifi_info/test.esp8266.yaml new file mode 100644 index 0000000000..cf5ea563ba --- /dev/null +++ b/tests/components/wifi_info/test.esp8266.yaml @@ -0,0 +1,18 @@ +wifi: + ssid: MySSID + password: password1 + +text_sensor: + - platform: wifi_info + scan_results: + name: Scan Results + ip_address: + name: IP Address + ssid: + name: SSID + bssid: + name: BSSID + mac_address: + name: Mac Address + dns_address: + name: DNS ADdress diff --git a/tests/components/wifi_info/test.rp2040.yaml b/tests/components/wifi_info/test.rp2040.yaml new file mode 100644 index 0000000000..cf5ea563ba --- /dev/null +++ b/tests/components/wifi_info/test.rp2040.yaml @@ -0,0 +1,18 @@ +wifi: + ssid: MySSID + password: password1 + +text_sensor: + - platform: wifi_info + scan_results: + name: Scan Results + ip_address: + name: IP Address + ssid: + name: SSID + bssid: + name: BSSID + mac_address: + name: Mac Address + dns_address: + name: DNS ADdress diff --git a/tests/components/wifi_signal/test.esp32-c3-idf.yaml b/tests/components/wifi_signal/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..58d1cab244 --- /dev/null +++ b/tests/components/wifi_signal/test.esp32-c3-idf.yaml @@ -0,0 +1,8 @@ +wifi: + ssid: MySSID + password: password1 + +sensor: + - platform: wifi_signal + name: WiFi Signal Sensor + update_interval: 15s diff --git a/tests/components/wifi_signal/test.esp32-c3.yaml b/tests/components/wifi_signal/test.esp32-c3.yaml new file mode 100644 index 0000000000..58d1cab244 --- /dev/null +++ b/tests/components/wifi_signal/test.esp32-c3.yaml @@ -0,0 +1,8 @@ +wifi: + ssid: MySSID + password: password1 + +sensor: + - platform: wifi_signal + name: WiFi Signal Sensor + update_interval: 15s diff --git a/tests/components/wifi_signal/test.esp32-idf.yaml b/tests/components/wifi_signal/test.esp32-idf.yaml new file mode 100644 index 0000000000..58d1cab244 --- /dev/null +++ b/tests/components/wifi_signal/test.esp32-idf.yaml @@ -0,0 +1,8 @@ +wifi: + ssid: MySSID + password: password1 + +sensor: + - platform: wifi_signal + name: WiFi Signal Sensor + update_interval: 15s diff --git a/tests/components/wifi_signal/test.esp32.yaml b/tests/components/wifi_signal/test.esp32.yaml new file mode 100644 index 0000000000..58d1cab244 --- /dev/null +++ b/tests/components/wifi_signal/test.esp32.yaml @@ -0,0 +1,8 @@ +wifi: + ssid: MySSID + password: password1 + +sensor: + - platform: wifi_signal + name: WiFi Signal Sensor + update_interval: 15s diff --git a/tests/components/wifi_signal/test.esp8266.yaml b/tests/components/wifi_signal/test.esp8266.yaml new file mode 100644 index 0000000000..58d1cab244 --- /dev/null +++ b/tests/components/wifi_signal/test.esp8266.yaml @@ -0,0 +1,8 @@ +wifi: + ssid: MySSID + password: password1 + +sensor: + - platform: wifi_signal + name: WiFi Signal Sensor + update_interval: 15s diff --git a/tests/components/wifi_signal/test.rp2040.yaml b/tests/components/wifi_signal/test.rp2040.yaml new file mode 100644 index 0000000000..58d1cab244 --- /dev/null +++ b/tests/components/wifi_signal/test.rp2040.yaml @@ -0,0 +1,8 @@ +wifi: + ssid: MySSID + password: password1 + +sensor: + - platform: wifi_signal + name: WiFi Signal Sensor + update_interval: 15s diff --git a/tests/components/wireguard/test.esp32-c3-idf.yaml b/tests/components/wireguard/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..37d1727842 --- /dev/null +++ b/tests/components/wireguard/test.esp32-c3-idf.yaml @@ -0,0 +1,60 @@ +wifi: + ssid: MySSID + password: password1 + +time: + - platform: sntp + +wireguard: + id: vpn + address: 172.16.34.100 + netmask: 255.255.255.0 + # NEVER use the following keys for your vpn, they are now public! + private_key: wPBMxtNYH3mChicrbpsRpZIasIdPq3yZuthn23FbGG8= + peer_public_key: Hs2JfikvYU03/Kv3YoAs1hrUIPPTEkpsZKSPUljE9yc= + peer_preshared_key: 20fjM5GRnSolGPC5SRj9ljgIUyQfruv0B0bvLl3Yt60= + peer_endpoint: wg.server.example + peer_persistent_keepalive: 25s + peer_allowed_ips: + - 172.16.34.0/24 + - 192.168.4.0/24 + +binary_sensor: + - platform: wireguard + status: + name: 'WireGuard Status' + enabled: + name: 'WireGuard Enabled' + +sensor: + - platform: wireguard + latest_handshake: + name: 'WireGuard Latest Handshake' + +text_sensor: + - platform: wireguard + address: + name: 'WireGuard Address' + +button: + - platform: template + name: 'Toggle WireGuard' + entity_category: config + on_press: + - if: + condition: wireguard.enabled + then: + - wireguard.disable: + else: + - wireguard.enable: + + - platform: template + name: 'Log WireGuard status' + entity_category: config + on_press: + - if: + condition: wireguard.peer_online + then: + - logger.log: 'wireguard remote peer is online' + else: + - logger.log: 'wireguard remote peer is offline' diff --git a/tests/components/wireguard/test.esp32-c3.yaml b/tests/components/wireguard/test.esp32-c3.yaml new file mode 100644 index 0000000000..37d1727842 --- /dev/null +++ b/tests/components/wireguard/test.esp32-c3.yaml @@ -0,0 +1,60 @@ +wifi: + ssid: MySSID + password: password1 + +time: + - platform: sntp + +wireguard: + id: vpn + address: 172.16.34.100 + netmask: 255.255.255.0 + # NEVER use the following keys for your vpn, they are now public! + private_key: wPBMxtNYH3mChicrbpsRpZIasIdPq3yZuthn23FbGG8= + peer_public_key: Hs2JfikvYU03/Kv3YoAs1hrUIPPTEkpsZKSPUljE9yc= + peer_preshared_key: 20fjM5GRnSolGPC5SRj9ljgIUyQfruv0B0bvLl3Yt60= + peer_endpoint: wg.server.example + peer_persistent_keepalive: 25s + peer_allowed_ips: + - 172.16.34.0/24 + - 192.168.4.0/24 + +binary_sensor: + - platform: wireguard + status: + name: 'WireGuard Status' + enabled: + name: 'WireGuard Enabled' + +sensor: + - platform: wireguard + latest_handshake: + name: 'WireGuard Latest Handshake' + +text_sensor: + - platform: wireguard + address: + name: 'WireGuard Address' + +button: + - platform: template + name: 'Toggle WireGuard' + entity_category: config + on_press: + - if: + condition: wireguard.enabled + then: + - wireguard.disable: + else: + - wireguard.enable: + + - platform: template + name: 'Log WireGuard status' + entity_category: config + on_press: + - if: + condition: wireguard.peer_online + then: + - logger.log: 'wireguard remote peer is online' + else: + - logger.log: 'wireguard remote peer is offline' diff --git a/tests/components/wl_134/test.esp32-c3-idf.yaml b/tests/components/wl_134/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..7cda1ba060 --- /dev/null +++ b/tests/components/wl_134/test.esp32-c3-idf.yaml @@ -0,0 +1,10 @@ +uart: + - id: uart_wl_134 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +text_sensor: + - platform: wl_134 + name: Transponder Code + reset: true diff --git a/tests/components/wl_134/test.esp32-c3.yaml b/tests/components/wl_134/test.esp32-c3.yaml new file mode 100644 index 0000000000..7cda1ba060 --- /dev/null +++ b/tests/components/wl_134/test.esp32-c3.yaml @@ -0,0 +1,10 @@ +uart: + - id: uart_wl_134 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +text_sensor: + - platform: wl_134 + name: Transponder Code + reset: true diff --git a/tests/components/wl_134/test.esp32-idf.yaml b/tests/components/wl_134/test.esp32-idf.yaml new file mode 100644 index 0000000000..d517889d28 --- /dev/null +++ b/tests/components/wl_134/test.esp32-idf.yaml @@ -0,0 +1,10 @@ +uart: + - id: uart_wl_134 + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +text_sensor: + - platform: wl_134 + name: Transponder Code + reset: true diff --git a/tests/components/wl_134/test.esp32.yaml b/tests/components/wl_134/test.esp32.yaml new file mode 100644 index 0000000000..d517889d28 --- /dev/null +++ b/tests/components/wl_134/test.esp32.yaml @@ -0,0 +1,10 @@ +uart: + - id: uart_wl_134 + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +text_sensor: + - platform: wl_134 + name: Transponder Code + reset: true diff --git a/tests/components/wl_134/test.esp8266.yaml b/tests/components/wl_134/test.esp8266.yaml new file mode 100644 index 0000000000..7cda1ba060 --- /dev/null +++ b/tests/components/wl_134/test.esp8266.yaml @@ -0,0 +1,10 @@ +uart: + - id: uart_wl_134 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +text_sensor: + - platform: wl_134 + name: Transponder Code + reset: true diff --git a/tests/components/wl_134/test.rp2040.yaml b/tests/components/wl_134/test.rp2040.yaml new file mode 100644 index 0000000000..7cda1ba060 --- /dev/null +++ b/tests/components/wl_134/test.rp2040.yaml @@ -0,0 +1,10 @@ +uart: + - id: uart_wl_134 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +text_sensor: + - platform: wl_134 + name: Transponder Code + reset: true diff --git a/tests/components/wled/test.esp32-c3.yaml b/tests/components/wled/test.esp32-c3.yaml new file mode 100644 index 0000000000..a24f28e154 --- /dev/null +++ b/tests/components/wled/test.esp32-c3.yaml @@ -0,0 +1,17 @@ +wifi: + ssid: MySSID + password: password1 + +wled: + +light: + - platform: esp32_rmt_led_strip + id: led_matrix_32x8 + default_transition_length: 500ms + chipset: ws2812 + rgb_order: GRB + num_leds: 256 + pin: 2 + rmt_channel: 0 + effects: + - wled: diff --git a/tests/components/wled/test.esp32.yaml b/tests/components/wled/test.esp32.yaml new file mode 100644 index 0000000000..a24f28e154 --- /dev/null +++ b/tests/components/wled/test.esp32.yaml @@ -0,0 +1,17 @@ +wifi: + ssid: MySSID + password: password1 + +wled: + +light: + - platform: esp32_rmt_led_strip + id: led_matrix_32x8 + default_transition_length: 500ms + chipset: ws2812 + rgb_order: GRB + num_leds: 256 + pin: 2 + rmt_channel: 0 + effects: + - wled: diff --git a/tests/components/wled/test.esp8266.yaml b/tests/components/wled/test.esp8266.yaml new file mode 100644 index 0000000000..e291af927c --- /dev/null +++ b/tests/components/wled/test.esp8266.yaml @@ -0,0 +1,17 @@ +wifi: + ssid: MySSID + password: password1 + +wled: + +light: + - platform: neopixelbus + id: addr + name: Neopixelbus Light + method: esp8266_uart + num_leds: 5 + pin: 2 + type: GRBW + variant: SK6812 + effects: + - wled: From 92b3d94cc70c52ce18fd92204259c16507036540 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Wed, 27 Mar 2024 02:30:13 -0500 Subject: [PATCH 1171/2101] Add some components to the new testing framework (L) (#6195) --- .../lcd_gpio/test.esp32-c3-idf.yaml | 13 ++ tests/components/lcd_gpio/test.esp32-c3.yaml | 13 ++ tests/components/lcd_gpio/test.esp32-idf.yaml | 13 ++ tests/components/lcd_gpio/test.esp32.yaml | 13 ++ tests/components/lcd_gpio/test.esp8266.yaml | 13 ++ tests/components/lcd_gpio/test.rp2040.yaml | 13 ++ .../lcd_menu/test.esp32-c3-idf.yaml | 118 ++++++++++++ tests/components/lcd_menu/test.esp32-c3.yaml | 118 ++++++++++++ tests/components/lcd_menu/test.esp32-idf.yaml | 118 ++++++++++++ tests/components/lcd_menu/test.esp32.yaml | 118 ++++++++++++ tests/components/lcd_menu/test.esp8266.yaml | 118 ++++++++++++ tests/components/lcd_menu/test.rp2040.yaml | 118 ++++++++++++ .../lcd_pcf8574/test.esp32-c3-idf.yaml | 22 +++ .../components/lcd_pcf8574/test.esp32-c3.yaml | 22 +++ .../lcd_pcf8574/test.esp32-idf.yaml | 22 +++ tests/components/lcd_pcf8574/test.esp32.yaml | 22 +++ .../components/lcd_pcf8574/test.esp8266.yaml | 22 +++ tests/components/lcd_pcf8574/test.rp2040.yaml | 22 +++ .../components/ld2410/test.esp32-c3-idf.yaml | 169 ++++++++++++++++++ tests/components/ld2410/test.esp32-c3.yaml | 169 ++++++++++++++++++ tests/components/ld2410/test.esp32-idf.yaml | 169 ++++++++++++++++++ tests/components/ld2410/test.esp32.yaml | 169 ++++++++++++++++++ tests/components/ld2410/test.esp8266.yaml | 169 ++++++++++++++++++ tests/components/ld2410/test.rp2040.yaml | 169 ++++++++++++++++++ .../components/ld2420/test.esp32-c3-idf.yaml | 132 ++++++++++++++ tests/components/ld2420/test.esp32-c3.yaml | 132 ++++++++++++++ tests/components/ld2420/test.esp32-idf.yaml | 132 ++++++++++++++ tests/components/ld2420/test.esp32.yaml | 132 ++++++++++++++ tests/components/ld2420/test.esp8266.yaml | 132 ++++++++++++++ tests/components/ld2420/test.rp2040.yaml | 132 ++++++++++++++ tests/components/ledc/test.esp32-c3-idf.yaml | 11 ++ tests/components/ledc/test.esp32-c3.yaml | 11 ++ tests/components/ledc/test.esp32-idf.yaml | 11 ++ tests/components/ledc/test.esp32.yaml | 11 ++ tests/components/light/test.esp32-c3-idf.yaml | 132 ++++++++++++++ tests/components/light/test.esp32-c3.yaml | 132 ++++++++++++++ tests/components/light/test.esp32-idf.yaml | 132 ++++++++++++++ tests/components/light/test.esp32.yaml | 132 ++++++++++++++ tests/components/light/test.esp8266.yaml | 132 ++++++++++++++ tests/components/light/test.rp2040.yaml | 132 ++++++++++++++ .../components/lightwaverf/test.esp8266.yaml | 13 ++ .../lilygo_t5_47/test.esp32-c3-idf.yaml | 24 +++ .../lilygo_t5_47/test.esp32-c3.yaml | 24 +++ .../lilygo_t5_47/test.esp32-idf.yaml | 24 +++ tests/components/lilygo_t5_47/test.esp32.yaml | 24 +++ .../components/lilygo_t5_47/test.esp8266.yaml | 24 +++ .../components/lilygo_t5_47/test.rp2040.yaml | 24 +++ tests/components/lock/test.esp32-c3-idf.yaml | 36 ++++ tests/components/lock/test.esp32-c3.yaml | 36 ++++ tests/components/lock/test.esp32-idf.yaml | 36 ++++ tests/components/lock/test.esp32.yaml | 36 ++++ tests/components/lock/test.esp8266.yaml | 36 ++++ tests/components/lock/test.rp2040.yaml | 36 ++++ .../components/logger/test.esp32-c3-idf.yaml | 7 + tests/components/logger/test.esp32-c3.yaml | 7 + tests/components/logger/test.esp32-idf.yaml | 7 + tests/components/logger/test.esp32.yaml | 7 + tests/components/logger/test.esp8266.yaml | 7 + tests/components/logger/test.rp2040.yaml | 7 + .../components/ltr390/test.esp32-c3-idf.yaml | 20 +++ tests/components/ltr390/test.esp32-c3.yaml | 20 +++ tests/components/ltr390/test.esp32-idf.yaml | 20 +++ tests/components/ltr390/test.esp32.yaml | 20 +++ tests/components/ltr390/test.esp8266.yaml | 20 +++ tests/components/ltr390/test.rp2040.yaml | 20 +++ 65 files changed, 4095 insertions(+) create mode 100644 tests/components/lcd_gpio/test.esp32-c3-idf.yaml create mode 100644 tests/components/lcd_gpio/test.esp32-c3.yaml create mode 100644 tests/components/lcd_gpio/test.esp32-idf.yaml create mode 100644 tests/components/lcd_gpio/test.esp32.yaml create mode 100644 tests/components/lcd_gpio/test.esp8266.yaml create mode 100644 tests/components/lcd_gpio/test.rp2040.yaml create mode 100644 tests/components/lcd_menu/test.esp32-c3-idf.yaml create mode 100644 tests/components/lcd_menu/test.esp32-c3.yaml create mode 100644 tests/components/lcd_menu/test.esp32-idf.yaml create mode 100644 tests/components/lcd_menu/test.esp32.yaml create mode 100644 tests/components/lcd_menu/test.esp8266.yaml create mode 100644 tests/components/lcd_menu/test.rp2040.yaml create mode 100644 tests/components/lcd_pcf8574/test.esp32-c3-idf.yaml create mode 100644 tests/components/lcd_pcf8574/test.esp32-c3.yaml create mode 100644 tests/components/lcd_pcf8574/test.esp32-idf.yaml create mode 100644 tests/components/lcd_pcf8574/test.esp32.yaml create mode 100644 tests/components/lcd_pcf8574/test.esp8266.yaml create mode 100644 tests/components/lcd_pcf8574/test.rp2040.yaml create mode 100644 tests/components/ld2410/test.esp32-c3-idf.yaml create mode 100644 tests/components/ld2410/test.esp32-c3.yaml create mode 100644 tests/components/ld2410/test.esp32-idf.yaml create mode 100644 tests/components/ld2410/test.esp32.yaml create mode 100644 tests/components/ld2410/test.esp8266.yaml create mode 100644 tests/components/ld2410/test.rp2040.yaml create mode 100644 tests/components/ld2420/test.esp32-c3-idf.yaml create mode 100644 tests/components/ld2420/test.esp32-c3.yaml create mode 100644 tests/components/ld2420/test.esp32-idf.yaml create mode 100644 tests/components/ld2420/test.esp32.yaml create mode 100644 tests/components/ld2420/test.esp8266.yaml create mode 100644 tests/components/ld2420/test.rp2040.yaml create mode 100644 tests/components/ledc/test.esp32-c3-idf.yaml create mode 100644 tests/components/ledc/test.esp32-c3.yaml create mode 100644 tests/components/ledc/test.esp32-idf.yaml create mode 100644 tests/components/ledc/test.esp32.yaml create mode 100644 tests/components/light/test.esp32-c3-idf.yaml create mode 100644 tests/components/light/test.esp32-c3.yaml create mode 100644 tests/components/light/test.esp32-idf.yaml create mode 100644 tests/components/light/test.esp32.yaml create mode 100644 tests/components/light/test.esp8266.yaml create mode 100644 tests/components/light/test.rp2040.yaml create mode 100644 tests/components/lightwaverf/test.esp8266.yaml create mode 100644 tests/components/lilygo_t5_47/test.esp32-c3-idf.yaml create mode 100644 tests/components/lilygo_t5_47/test.esp32-c3.yaml create mode 100644 tests/components/lilygo_t5_47/test.esp32-idf.yaml create mode 100644 tests/components/lilygo_t5_47/test.esp32.yaml create mode 100644 tests/components/lilygo_t5_47/test.esp8266.yaml create mode 100644 tests/components/lilygo_t5_47/test.rp2040.yaml create mode 100644 tests/components/lock/test.esp32-c3-idf.yaml create mode 100644 tests/components/lock/test.esp32-c3.yaml create mode 100644 tests/components/lock/test.esp32-idf.yaml create mode 100644 tests/components/lock/test.esp32.yaml create mode 100644 tests/components/lock/test.esp8266.yaml create mode 100644 tests/components/lock/test.rp2040.yaml create mode 100644 tests/components/logger/test.esp32-c3-idf.yaml create mode 100644 tests/components/logger/test.esp32-c3.yaml create mode 100644 tests/components/logger/test.esp32-idf.yaml create mode 100644 tests/components/logger/test.esp32.yaml create mode 100644 tests/components/logger/test.esp8266.yaml create mode 100644 tests/components/logger/test.rp2040.yaml create mode 100644 tests/components/ltr390/test.esp32-c3-idf.yaml create mode 100644 tests/components/ltr390/test.esp32-c3.yaml create mode 100644 tests/components/ltr390/test.esp32-idf.yaml create mode 100644 tests/components/ltr390/test.esp32.yaml create mode 100644 tests/components/ltr390/test.esp8266.yaml create mode 100644 tests/components/ltr390/test.rp2040.yaml diff --git a/tests/components/lcd_gpio/test.esp32-c3-idf.yaml b/tests/components/lcd_gpio/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..b89715a755 --- /dev/null +++ b/tests/components/lcd_gpio/test.esp32-c3-idf.yaml @@ -0,0 +1,13 @@ +display: + - platform: lcd_gpio + id: my_lcd_gpio + dimensions: 18x4 + data_pins: + - number: 1 + - number: 2 + - number: 3 + - number: 4 + enable_pin: 5 + rs_pin: 6 + lambda: |- + it.print("Hello World!"); diff --git a/tests/components/lcd_gpio/test.esp32-c3.yaml b/tests/components/lcd_gpio/test.esp32-c3.yaml new file mode 100644 index 0000000000..b89715a755 --- /dev/null +++ b/tests/components/lcd_gpio/test.esp32-c3.yaml @@ -0,0 +1,13 @@ +display: + - platform: lcd_gpio + id: my_lcd_gpio + dimensions: 18x4 + data_pins: + - number: 1 + - number: 2 + - number: 3 + - number: 4 + enable_pin: 5 + rs_pin: 6 + lambda: |- + it.print("Hello World!"); diff --git a/tests/components/lcd_gpio/test.esp32-idf.yaml b/tests/components/lcd_gpio/test.esp32-idf.yaml new file mode 100644 index 0000000000..d2b33aeb3a --- /dev/null +++ b/tests/components/lcd_gpio/test.esp32-idf.yaml @@ -0,0 +1,13 @@ +display: + - platform: lcd_gpio + id: my_lcd_gpio + dimensions: 18x4 + data_pins: + - number: 12 + - number: 13 + - number: 14 + - number: 15 + enable_pin: 16 + rs_pin: 5 + lambda: |- + it.print("Hello World!"); diff --git a/tests/components/lcd_gpio/test.esp32.yaml b/tests/components/lcd_gpio/test.esp32.yaml new file mode 100644 index 0000000000..d2b33aeb3a --- /dev/null +++ b/tests/components/lcd_gpio/test.esp32.yaml @@ -0,0 +1,13 @@ +display: + - platform: lcd_gpio + id: my_lcd_gpio + dimensions: 18x4 + data_pins: + - number: 12 + - number: 13 + - number: 14 + - number: 15 + enable_pin: 16 + rs_pin: 5 + lambda: |- + it.print("Hello World!"); diff --git a/tests/components/lcd_gpio/test.esp8266.yaml b/tests/components/lcd_gpio/test.esp8266.yaml new file mode 100644 index 0000000000..d2b33aeb3a --- /dev/null +++ b/tests/components/lcd_gpio/test.esp8266.yaml @@ -0,0 +1,13 @@ +display: + - platform: lcd_gpio + id: my_lcd_gpio + dimensions: 18x4 + data_pins: + - number: 12 + - number: 13 + - number: 14 + - number: 15 + enable_pin: 16 + rs_pin: 5 + lambda: |- + it.print("Hello World!"); diff --git a/tests/components/lcd_gpio/test.rp2040.yaml b/tests/components/lcd_gpio/test.rp2040.yaml new file mode 100644 index 0000000000..b89715a755 --- /dev/null +++ b/tests/components/lcd_gpio/test.rp2040.yaml @@ -0,0 +1,13 @@ +display: + - platform: lcd_gpio + id: my_lcd_gpio + dimensions: 18x4 + data_pins: + - number: 1 + - number: 2 + - number: 3 + - number: 4 + enable_pin: 5 + rs_pin: 6 + lambda: |- + it.print("Hello World!"); diff --git a/tests/components/lcd_menu/test.esp32-c3-idf.yaml b/tests/components/lcd_menu/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..39d2278d3d --- /dev/null +++ b/tests/components/lcd_menu/test.esp32-c3-idf.yaml @@ -0,0 +1,118 @@ +number: + - platform: template + id: test_number + min_value: 0 + step: 1 + max_value: 10 + optimistic: true + +select: + - platform: template + id: test_select + options: + - one + - two + optimistic: true + +switch: + - platform: template + name: Template Switch + id: my_switch + optimistic: true + +display: + - platform: lcd_gpio + id: my_lcd_gpio + dimensions: 18x4 + data_pins: + - number: 1 + - number: 2 + - number: 3 + - number: 4 + enable_pin: 5 + rs_pin: 6 + lambda: |- + it.print("Hello World!"); + +lcd_menu: + id: test_lcd_menu + display_id: my_lcd_gpio + mark_back: 0x5e + mark_selected: 0x3e + mark_editing: 0x2a + mark_submenu: 0x7e + active: false + mode: rotary + on_enter: + then: + lambda: 'ESP_LOGI("lcd_menu", "root enter");' + on_leave: + then: + lambda: 'ESP_LOGI("lcd_menu", "root leave");' + items: + - type: back + text: Back + - type: label + - type: menu + text: Submenu 1 + items: + - type: back + text: Back + - type: menu + text: Submenu 21 + items: + - type: back + text: Back + - type: command + text: Show Main + on_value: + then: + - display_menu.show_main: test_lcd_menu + - type: select + text: Enum Item + immediate_edit: true + select: test_select + on_enter: + then: + lambda: 'ESP_LOGI("lcd_menu", "select enter: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_leave: + then: + lambda: 'ESP_LOGI("lcd_menu", "select leave: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_value: + then: + lambda: 'ESP_LOGI("lcd_menu", "select value: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + - type: number + text: Number + number: test_number + on_enter: + then: + lambda: 'ESP_LOGI("lcd_menu", "number enter: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_leave: + then: + lambda: 'ESP_LOGI("lcd_menu", "number leave: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_value: + then: + lambda: 'ESP_LOGI("lcd_menu", "number value: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + - type: command + text: Hide + on_value: + then: + - display_menu.hide: test_lcd_menu + - type: switch + text: Switch + switch: my_switch + on_text: Bright + off_text: Dark + immediate_edit: false + on_value: + then: + lambda: 'ESP_LOGI("lcd_menu", "switch value: %s", it->get_value_text().c_str());' + - type: custom + text: !lambda 'return "Custom";' + value_lambda: 'return "Val";' + on_next: + then: + lambda: 'ESP_LOGI("lcd_menu", "custom next: %s", it->get_text().c_str());' + on_prev: + then: + lambda: 'ESP_LOGI("lcd_menu", "custom prev: %s", it->get_text().c_str());' diff --git a/tests/components/lcd_menu/test.esp32-c3.yaml b/tests/components/lcd_menu/test.esp32-c3.yaml new file mode 100644 index 0000000000..39d2278d3d --- /dev/null +++ b/tests/components/lcd_menu/test.esp32-c3.yaml @@ -0,0 +1,118 @@ +number: + - platform: template + id: test_number + min_value: 0 + step: 1 + max_value: 10 + optimistic: true + +select: + - platform: template + id: test_select + options: + - one + - two + optimistic: true + +switch: + - platform: template + name: Template Switch + id: my_switch + optimistic: true + +display: + - platform: lcd_gpio + id: my_lcd_gpio + dimensions: 18x4 + data_pins: + - number: 1 + - number: 2 + - number: 3 + - number: 4 + enable_pin: 5 + rs_pin: 6 + lambda: |- + it.print("Hello World!"); + +lcd_menu: + id: test_lcd_menu + display_id: my_lcd_gpio + mark_back: 0x5e + mark_selected: 0x3e + mark_editing: 0x2a + mark_submenu: 0x7e + active: false + mode: rotary + on_enter: + then: + lambda: 'ESP_LOGI("lcd_menu", "root enter");' + on_leave: + then: + lambda: 'ESP_LOGI("lcd_menu", "root leave");' + items: + - type: back + text: Back + - type: label + - type: menu + text: Submenu 1 + items: + - type: back + text: Back + - type: menu + text: Submenu 21 + items: + - type: back + text: Back + - type: command + text: Show Main + on_value: + then: + - display_menu.show_main: test_lcd_menu + - type: select + text: Enum Item + immediate_edit: true + select: test_select + on_enter: + then: + lambda: 'ESP_LOGI("lcd_menu", "select enter: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_leave: + then: + lambda: 'ESP_LOGI("lcd_menu", "select leave: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_value: + then: + lambda: 'ESP_LOGI("lcd_menu", "select value: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + - type: number + text: Number + number: test_number + on_enter: + then: + lambda: 'ESP_LOGI("lcd_menu", "number enter: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_leave: + then: + lambda: 'ESP_LOGI("lcd_menu", "number leave: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_value: + then: + lambda: 'ESP_LOGI("lcd_menu", "number value: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + - type: command + text: Hide + on_value: + then: + - display_menu.hide: test_lcd_menu + - type: switch + text: Switch + switch: my_switch + on_text: Bright + off_text: Dark + immediate_edit: false + on_value: + then: + lambda: 'ESP_LOGI("lcd_menu", "switch value: %s", it->get_value_text().c_str());' + - type: custom + text: !lambda 'return "Custom";' + value_lambda: 'return "Val";' + on_next: + then: + lambda: 'ESP_LOGI("lcd_menu", "custom next: %s", it->get_text().c_str());' + on_prev: + then: + lambda: 'ESP_LOGI("lcd_menu", "custom prev: %s", it->get_text().c_str());' diff --git a/tests/components/lcd_menu/test.esp32-idf.yaml b/tests/components/lcd_menu/test.esp32-idf.yaml new file mode 100644 index 0000000000..833ea2169a --- /dev/null +++ b/tests/components/lcd_menu/test.esp32-idf.yaml @@ -0,0 +1,118 @@ +number: + - platform: template + id: test_number + min_value: 0 + step: 1 + max_value: 10 + optimistic: true + +select: + - platform: template + id: test_select + options: + - one + - two + optimistic: true + +switch: + - platform: template + name: Template Switch + id: my_switch + optimistic: true + +display: + - platform: lcd_gpio + id: my_lcd_gpio + dimensions: 18x4 + data_pins: + - number: 12 + - number: 13 + - number: 14 + - number: 15 + enable_pin: 16 + rs_pin: 5 + lambda: |- + it.print("Hello World!"); + +lcd_menu: + id: test_lcd_menu + display_id: my_lcd_gpio + mark_back: 0x5e + mark_selected: 0x3e + mark_editing: 0x2a + mark_submenu: 0x7e + active: false + mode: rotary + on_enter: + then: + lambda: 'ESP_LOGI("lcd_menu", "root enter");' + on_leave: + then: + lambda: 'ESP_LOGI("lcd_menu", "root leave");' + items: + - type: back + text: Back + - type: label + - type: menu + text: Submenu 1 + items: + - type: back + text: Back + - type: menu + text: Submenu 21 + items: + - type: back + text: Back + - type: command + text: Show Main + on_value: + then: + - display_menu.show_main: test_lcd_menu + - type: select + text: Enum Item + immediate_edit: true + select: test_select + on_enter: + then: + lambda: 'ESP_LOGI("lcd_menu", "select enter: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_leave: + then: + lambda: 'ESP_LOGI("lcd_menu", "select leave: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_value: + then: + lambda: 'ESP_LOGI("lcd_menu", "select value: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + - type: number + text: Number + number: test_number + on_enter: + then: + lambda: 'ESP_LOGI("lcd_menu", "number enter: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_leave: + then: + lambda: 'ESP_LOGI("lcd_menu", "number leave: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_value: + then: + lambda: 'ESP_LOGI("lcd_menu", "number value: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + - type: command + text: Hide + on_value: + then: + - display_menu.hide: test_lcd_menu + - type: switch + text: Switch + switch: my_switch + on_text: Bright + off_text: Dark + immediate_edit: false + on_value: + then: + lambda: 'ESP_LOGI("lcd_menu", "switch value: %s", it->get_value_text().c_str());' + - type: custom + text: !lambda 'return "Custom";' + value_lambda: 'return "Val";' + on_next: + then: + lambda: 'ESP_LOGI("lcd_menu", "custom next: %s", it->get_text().c_str());' + on_prev: + then: + lambda: 'ESP_LOGI("lcd_menu", "custom prev: %s", it->get_text().c_str());' diff --git a/tests/components/lcd_menu/test.esp32.yaml b/tests/components/lcd_menu/test.esp32.yaml new file mode 100644 index 0000000000..833ea2169a --- /dev/null +++ b/tests/components/lcd_menu/test.esp32.yaml @@ -0,0 +1,118 @@ +number: + - platform: template + id: test_number + min_value: 0 + step: 1 + max_value: 10 + optimistic: true + +select: + - platform: template + id: test_select + options: + - one + - two + optimistic: true + +switch: + - platform: template + name: Template Switch + id: my_switch + optimistic: true + +display: + - platform: lcd_gpio + id: my_lcd_gpio + dimensions: 18x4 + data_pins: + - number: 12 + - number: 13 + - number: 14 + - number: 15 + enable_pin: 16 + rs_pin: 5 + lambda: |- + it.print("Hello World!"); + +lcd_menu: + id: test_lcd_menu + display_id: my_lcd_gpio + mark_back: 0x5e + mark_selected: 0x3e + mark_editing: 0x2a + mark_submenu: 0x7e + active: false + mode: rotary + on_enter: + then: + lambda: 'ESP_LOGI("lcd_menu", "root enter");' + on_leave: + then: + lambda: 'ESP_LOGI("lcd_menu", "root leave");' + items: + - type: back + text: Back + - type: label + - type: menu + text: Submenu 1 + items: + - type: back + text: Back + - type: menu + text: Submenu 21 + items: + - type: back + text: Back + - type: command + text: Show Main + on_value: + then: + - display_menu.show_main: test_lcd_menu + - type: select + text: Enum Item + immediate_edit: true + select: test_select + on_enter: + then: + lambda: 'ESP_LOGI("lcd_menu", "select enter: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_leave: + then: + lambda: 'ESP_LOGI("lcd_menu", "select leave: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_value: + then: + lambda: 'ESP_LOGI("lcd_menu", "select value: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + - type: number + text: Number + number: test_number + on_enter: + then: + lambda: 'ESP_LOGI("lcd_menu", "number enter: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_leave: + then: + lambda: 'ESP_LOGI("lcd_menu", "number leave: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_value: + then: + lambda: 'ESP_LOGI("lcd_menu", "number value: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + - type: command + text: Hide + on_value: + then: + - display_menu.hide: test_lcd_menu + - type: switch + text: Switch + switch: my_switch + on_text: Bright + off_text: Dark + immediate_edit: false + on_value: + then: + lambda: 'ESP_LOGI("lcd_menu", "switch value: %s", it->get_value_text().c_str());' + - type: custom + text: !lambda 'return "Custom";' + value_lambda: 'return "Val";' + on_next: + then: + lambda: 'ESP_LOGI("lcd_menu", "custom next: %s", it->get_text().c_str());' + on_prev: + then: + lambda: 'ESP_LOGI("lcd_menu", "custom prev: %s", it->get_text().c_str());' diff --git a/tests/components/lcd_menu/test.esp8266.yaml b/tests/components/lcd_menu/test.esp8266.yaml new file mode 100644 index 0000000000..833ea2169a --- /dev/null +++ b/tests/components/lcd_menu/test.esp8266.yaml @@ -0,0 +1,118 @@ +number: + - platform: template + id: test_number + min_value: 0 + step: 1 + max_value: 10 + optimistic: true + +select: + - platform: template + id: test_select + options: + - one + - two + optimistic: true + +switch: + - platform: template + name: Template Switch + id: my_switch + optimistic: true + +display: + - platform: lcd_gpio + id: my_lcd_gpio + dimensions: 18x4 + data_pins: + - number: 12 + - number: 13 + - number: 14 + - number: 15 + enable_pin: 16 + rs_pin: 5 + lambda: |- + it.print("Hello World!"); + +lcd_menu: + id: test_lcd_menu + display_id: my_lcd_gpio + mark_back: 0x5e + mark_selected: 0x3e + mark_editing: 0x2a + mark_submenu: 0x7e + active: false + mode: rotary + on_enter: + then: + lambda: 'ESP_LOGI("lcd_menu", "root enter");' + on_leave: + then: + lambda: 'ESP_LOGI("lcd_menu", "root leave");' + items: + - type: back + text: Back + - type: label + - type: menu + text: Submenu 1 + items: + - type: back + text: Back + - type: menu + text: Submenu 21 + items: + - type: back + text: Back + - type: command + text: Show Main + on_value: + then: + - display_menu.show_main: test_lcd_menu + - type: select + text: Enum Item + immediate_edit: true + select: test_select + on_enter: + then: + lambda: 'ESP_LOGI("lcd_menu", "select enter: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_leave: + then: + lambda: 'ESP_LOGI("lcd_menu", "select leave: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_value: + then: + lambda: 'ESP_LOGI("lcd_menu", "select value: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + - type: number + text: Number + number: test_number + on_enter: + then: + lambda: 'ESP_LOGI("lcd_menu", "number enter: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_leave: + then: + lambda: 'ESP_LOGI("lcd_menu", "number leave: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_value: + then: + lambda: 'ESP_LOGI("lcd_menu", "number value: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + - type: command + text: Hide + on_value: + then: + - display_menu.hide: test_lcd_menu + - type: switch + text: Switch + switch: my_switch + on_text: Bright + off_text: Dark + immediate_edit: false + on_value: + then: + lambda: 'ESP_LOGI("lcd_menu", "switch value: %s", it->get_value_text().c_str());' + - type: custom + text: !lambda 'return "Custom";' + value_lambda: 'return "Val";' + on_next: + then: + lambda: 'ESP_LOGI("lcd_menu", "custom next: %s", it->get_text().c_str());' + on_prev: + then: + lambda: 'ESP_LOGI("lcd_menu", "custom prev: %s", it->get_text().c_str());' diff --git a/tests/components/lcd_menu/test.rp2040.yaml b/tests/components/lcd_menu/test.rp2040.yaml new file mode 100644 index 0000000000..39d2278d3d --- /dev/null +++ b/tests/components/lcd_menu/test.rp2040.yaml @@ -0,0 +1,118 @@ +number: + - platform: template + id: test_number + min_value: 0 + step: 1 + max_value: 10 + optimistic: true + +select: + - platform: template + id: test_select + options: + - one + - two + optimistic: true + +switch: + - platform: template + name: Template Switch + id: my_switch + optimistic: true + +display: + - platform: lcd_gpio + id: my_lcd_gpio + dimensions: 18x4 + data_pins: + - number: 1 + - number: 2 + - number: 3 + - number: 4 + enable_pin: 5 + rs_pin: 6 + lambda: |- + it.print("Hello World!"); + +lcd_menu: + id: test_lcd_menu + display_id: my_lcd_gpio + mark_back: 0x5e + mark_selected: 0x3e + mark_editing: 0x2a + mark_submenu: 0x7e + active: false + mode: rotary + on_enter: + then: + lambda: 'ESP_LOGI("lcd_menu", "root enter");' + on_leave: + then: + lambda: 'ESP_LOGI("lcd_menu", "root leave");' + items: + - type: back + text: Back + - type: label + - type: menu + text: Submenu 1 + items: + - type: back + text: Back + - type: menu + text: Submenu 21 + items: + - type: back + text: Back + - type: command + text: Show Main + on_value: + then: + - display_menu.show_main: test_lcd_menu + - type: select + text: Enum Item + immediate_edit: true + select: test_select + on_enter: + then: + lambda: 'ESP_LOGI("lcd_menu", "select enter: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_leave: + then: + lambda: 'ESP_LOGI("lcd_menu", "select leave: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_value: + then: + lambda: 'ESP_LOGI("lcd_menu", "select value: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + - type: number + text: Number + number: test_number + on_enter: + then: + lambda: 'ESP_LOGI("lcd_menu", "number enter: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_leave: + then: + lambda: 'ESP_LOGI("lcd_menu", "number leave: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + on_value: + then: + lambda: 'ESP_LOGI("lcd_menu", "number value: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' + - type: command + text: Hide + on_value: + then: + - display_menu.hide: test_lcd_menu + - type: switch + text: Switch + switch: my_switch + on_text: Bright + off_text: Dark + immediate_edit: false + on_value: + then: + lambda: 'ESP_LOGI("lcd_menu", "switch value: %s", it->get_value_text().c_str());' + - type: custom + text: !lambda 'return "Custom";' + value_lambda: 'return "Val";' + on_next: + then: + lambda: 'ESP_LOGI("lcd_menu", "custom next: %s", it->get_text().c_str());' + on_prev: + then: + lambda: 'ESP_LOGI("lcd_menu", "custom prev: %s", it->get_text().c_str());' diff --git a/tests/components/lcd_pcf8574/test.esp32-c3-idf.yaml b/tests/components/lcd_pcf8574/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..41eba26950 --- /dev/null +++ b/tests/components/lcd_pcf8574/test.esp32-c3-idf.yaml @@ -0,0 +1,22 @@ +i2c: + - id: i2c_lcd_pcf8574 + scl: 5 + sda: 4 + +display: + - platform: lcd_pcf8574 + dimensions: 18x4 + address: 0x3F + user_characters: + - position: 0 + data: + - 0b00000 + - 0b01010 + - 0b00000 + - 0b00100 + - 0b00100 + - 0b10001 + - 0b01110 + - 0b00000 + lambda: |- + it.print("Hello World!"); diff --git a/tests/components/lcd_pcf8574/test.esp32-c3.yaml b/tests/components/lcd_pcf8574/test.esp32-c3.yaml new file mode 100644 index 0000000000..41eba26950 --- /dev/null +++ b/tests/components/lcd_pcf8574/test.esp32-c3.yaml @@ -0,0 +1,22 @@ +i2c: + - id: i2c_lcd_pcf8574 + scl: 5 + sda: 4 + +display: + - platform: lcd_pcf8574 + dimensions: 18x4 + address: 0x3F + user_characters: + - position: 0 + data: + - 0b00000 + - 0b01010 + - 0b00000 + - 0b00100 + - 0b00100 + - 0b10001 + - 0b01110 + - 0b00000 + lambda: |- + it.print("Hello World!"); diff --git a/tests/components/lcd_pcf8574/test.esp32-idf.yaml b/tests/components/lcd_pcf8574/test.esp32-idf.yaml new file mode 100644 index 0000000000..9d7d475f30 --- /dev/null +++ b/tests/components/lcd_pcf8574/test.esp32-idf.yaml @@ -0,0 +1,22 @@ +i2c: + - id: i2c_lcd_pcf8574 + scl: 16 + sda: 17 + +display: + - platform: lcd_pcf8574 + dimensions: 18x4 + address: 0x3F + user_characters: + - position: 0 + data: + - 0b00000 + - 0b01010 + - 0b00000 + - 0b00100 + - 0b00100 + - 0b10001 + - 0b01110 + - 0b00000 + lambda: |- + it.print("Hello World!"); diff --git a/tests/components/lcd_pcf8574/test.esp32.yaml b/tests/components/lcd_pcf8574/test.esp32.yaml new file mode 100644 index 0000000000..9d7d475f30 --- /dev/null +++ b/tests/components/lcd_pcf8574/test.esp32.yaml @@ -0,0 +1,22 @@ +i2c: + - id: i2c_lcd_pcf8574 + scl: 16 + sda: 17 + +display: + - platform: lcd_pcf8574 + dimensions: 18x4 + address: 0x3F + user_characters: + - position: 0 + data: + - 0b00000 + - 0b01010 + - 0b00000 + - 0b00100 + - 0b00100 + - 0b10001 + - 0b01110 + - 0b00000 + lambda: |- + it.print("Hello World!"); diff --git a/tests/components/lcd_pcf8574/test.esp8266.yaml b/tests/components/lcd_pcf8574/test.esp8266.yaml new file mode 100644 index 0000000000..41eba26950 --- /dev/null +++ b/tests/components/lcd_pcf8574/test.esp8266.yaml @@ -0,0 +1,22 @@ +i2c: + - id: i2c_lcd_pcf8574 + scl: 5 + sda: 4 + +display: + - platform: lcd_pcf8574 + dimensions: 18x4 + address: 0x3F + user_characters: + - position: 0 + data: + - 0b00000 + - 0b01010 + - 0b00000 + - 0b00100 + - 0b00100 + - 0b10001 + - 0b01110 + - 0b00000 + lambda: |- + it.print("Hello World!"); diff --git a/tests/components/lcd_pcf8574/test.rp2040.yaml b/tests/components/lcd_pcf8574/test.rp2040.yaml new file mode 100644 index 0000000000..41eba26950 --- /dev/null +++ b/tests/components/lcd_pcf8574/test.rp2040.yaml @@ -0,0 +1,22 @@ +i2c: + - id: i2c_lcd_pcf8574 + scl: 5 + sda: 4 + +display: + - platform: lcd_pcf8574 + dimensions: 18x4 + address: 0x3F + user_characters: + - position: 0 + data: + - 0b00000 + - 0b01010 + - 0b00000 + - 0b00100 + - 0b00100 + - 0b10001 + - 0b01110 + - 0b00000 + lambda: |- + it.print("Hello World!"); diff --git a/tests/components/ld2410/test.esp32-c3-idf.yaml b/tests/components/ld2410/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..afcaa81b3e --- /dev/null +++ b/tests/components/ld2410/test.esp32-c3-idf.yaml @@ -0,0 +1,169 @@ +uart: + - id: uart_ld2410 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +ld2410: + id: my_ld2410 + +binary_sensor: + - platform: ld2410 + has_target: + name: presence + has_moving_target: + name: movement + has_still_target: + name: still + out_pin_presence_status: + name: out pin presence status + +button: + - platform: ld2410 + factory_reset: + name: factory reset + restart: + name: restart + query_params: + name: query params + +number: + - platform: ld2410 + light_threshold: + name: light threshold + timeout: + name: timeout + max_move_distance_gate: + name: max move distance gate + max_still_distance_gate: + name: max still distance gate + g0: + move_threshold: + name: g0 move threshold + still_threshold: + name: g0 still threshold + g1: + move_threshold: + name: g1 move threshold + still_threshold: + name: g1 still threshold + g2: + move_threshold: + name: g2 move threshold + still_threshold: + name: g2 still threshold + g3: + move_threshold: + name: g3 move threshold + still_threshold: + name: g3 still threshold + g4: + move_threshold: + name: g4 move threshold + still_threshold: + name: g4 still threshold + g5: + move_threshold: + name: g5 move threshold + still_threshold: + name: g5 still threshold + g6: + move_threshold: + name: g6 move threshold + still_threshold: + name: g6 still threshold + g7: + move_threshold: + name: g7 move threshold + still_threshold: + name: g7 still threshold + g8: + move_threshold: + name: g8 move threshold + still_threshold: + name: g8 still threshold + +select: + - platform: ld2410 + distance_resolution: + name: distance resolution + baud_rate: + name: baud rate + light_function: + name: light function + out_pin_level: + name: out ping level + +sensor: + - platform: ld2410 + light: + name: light + moving_distance: + name: Moving distance + still_distance: + name: Still Distance + moving_energy: + name: Move Energy + still_energy: + name: Still Energy + detection_distance: + name: Distance Detection + g0: + move_energy: + name: g0 move energy + still_energy: + name: g0 still energy + g1: + move_energy: + name: g1 move energy + still_energy: + name: g1 still energy + g2: + move_energy: + name: g2 move energy + still_energy: + name: g2 still energy + g3: + move_energy: + name: g3 move energy + still_energy: + name: g3 still energy + g4: + move_energy: + name: g4 move energy + still_energy: + name: g4 still energy + g5: + move_energy: + name: g5 move energy + still_energy: + name: g5 still energy + g6: + move_energy: + name: g6 move energy + still_energy: + name: g6 still energy + g7: + move_energy: + name: g7 move energy + still_energy: + name: g7 still energy + g8: + move_energy: + name: g8 move energy + still_energy: + name: g8 still energy + +switch: + - platform: ld2410 + engineering_mode: + name: control ld2410 engineering mode + bluetooth: + name: control ld2410 bluetooth + +text_sensor: + - platform: ld2410 + version: + name: presenece sensor version + mac_address: + name: presenece sensor mac address diff --git a/tests/components/ld2410/test.esp32-c3.yaml b/tests/components/ld2410/test.esp32-c3.yaml new file mode 100644 index 0000000000..afcaa81b3e --- /dev/null +++ b/tests/components/ld2410/test.esp32-c3.yaml @@ -0,0 +1,169 @@ +uart: + - id: uart_ld2410 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +ld2410: + id: my_ld2410 + +binary_sensor: + - platform: ld2410 + has_target: + name: presence + has_moving_target: + name: movement + has_still_target: + name: still + out_pin_presence_status: + name: out pin presence status + +button: + - platform: ld2410 + factory_reset: + name: factory reset + restart: + name: restart + query_params: + name: query params + +number: + - platform: ld2410 + light_threshold: + name: light threshold + timeout: + name: timeout + max_move_distance_gate: + name: max move distance gate + max_still_distance_gate: + name: max still distance gate + g0: + move_threshold: + name: g0 move threshold + still_threshold: + name: g0 still threshold + g1: + move_threshold: + name: g1 move threshold + still_threshold: + name: g1 still threshold + g2: + move_threshold: + name: g2 move threshold + still_threshold: + name: g2 still threshold + g3: + move_threshold: + name: g3 move threshold + still_threshold: + name: g3 still threshold + g4: + move_threshold: + name: g4 move threshold + still_threshold: + name: g4 still threshold + g5: + move_threshold: + name: g5 move threshold + still_threshold: + name: g5 still threshold + g6: + move_threshold: + name: g6 move threshold + still_threshold: + name: g6 still threshold + g7: + move_threshold: + name: g7 move threshold + still_threshold: + name: g7 still threshold + g8: + move_threshold: + name: g8 move threshold + still_threshold: + name: g8 still threshold + +select: + - platform: ld2410 + distance_resolution: + name: distance resolution + baud_rate: + name: baud rate + light_function: + name: light function + out_pin_level: + name: out ping level + +sensor: + - platform: ld2410 + light: + name: light + moving_distance: + name: Moving distance + still_distance: + name: Still Distance + moving_energy: + name: Move Energy + still_energy: + name: Still Energy + detection_distance: + name: Distance Detection + g0: + move_energy: + name: g0 move energy + still_energy: + name: g0 still energy + g1: + move_energy: + name: g1 move energy + still_energy: + name: g1 still energy + g2: + move_energy: + name: g2 move energy + still_energy: + name: g2 still energy + g3: + move_energy: + name: g3 move energy + still_energy: + name: g3 still energy + g4: + move_energy: + name: g4 move energy + still_energy: + name: g4 still energy + g5: + move_energy: + name: g5 move energy + still_energy: + name: g5 still energy + g6: + move_energy: + name: g6 move energy + still_energy: + name: g6 still energy + g7: + move_energy: + name: g7 move energy + still_energy: + name: g7 still energy + g8: + move_energy: + name: g8 move energy + still_energy: + name: g8 still energy + +switch: + - platform: ld2410 + engineering_mode: + name: control ld2410 engineering mode + bluetooth: + name: control ld2410 bluetooth + +text_sensor: + - platform: ld2410 + version: + name: presenece sensor version + mac_address: + name: presenece sensor mac address diff --git a/tests/components/ld2410/test.esp32-idf.yaml b/tests/components/ld2410/test.esp32-idf.yaml new file mode 100644 index 0000000000..48ed179d93 --- /dev/null +++ b/tests/components/ld2410/test.esp32-idf.yaml @@ -0,0 +1,169 @@ +uart: + - id: uart_ld2410 + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +ld2410: + id: my_ld2410 + +binary_sensor: + - platform: ld2410 + has_target: + name: presence + has_moving_target: + name: movement + has_still_target: + name: still + out_pin_presence_status: + name: out pin presence status + +button: + - platform: ld2410 + factory_reset: + name: factory reset + restart: + name: restart + query_params: + name: query params + +number: + - platform: ld2410 + light_threshold: + name: light threshold + timeout: + name: timeout + max_move_distance_gate: + name: max move distance gate + max_still_distance_gate: + name: max still distance gate + g0: + move_threshold: + name: g0 move threshold + still_threshold: + name: g0 still threshold + g1: + move_threshold: + name: g1 move threshold + still_threshold: + name: g1 still threshold + g2: + move_threshold: + name: g2 move threshold + still_threshold: + name: g2 still threshold + g3: + move_threshold: + name: g3 move threshold + still_threshold: + name: g3 still threshold + g4: + move_threshold: + name: g4 move threshold + still_threshold: + name: g4 still threshold + g5: + move_threshold: + name: g5 move threshold + still_threshold: + name: g5 still threshold + g6: + move_threshold: + name: g6 move threshold + still_threshold: + name: g6 still threshold + g7: + move_threshold: + name: g7 move threshold + still_threshold: + name: g7 still threshold + g8: + move_threshold: + name: g8 move threshold + still_threshold: + name: g8 still threshold + +select: + - platform: ld2410 + distance_resolution: + name: distance resolution + baud_rate: + name: baud rate + light_function: + name: light function + out_pin_level: + name: out ping level + +sensor: + - platform: ld2410 + light: + name: light + moving_distance: + name: Moving distance + still_distance: + name: Still Distance + moving_energy: + name: Move Energy + still_energy: + name: Still Energy + detection_distance: + name: Distance Detection + g0: + move_energy: + name: g0 move energy + still_energy: + name: g0 still energy + g1: + move_energy: + name: g1 move energy + still_energy: + name: g1 still energy + g2: + move_energy: + name: g2 move energy + still_energy: + name: g2 still energy + g3: + move_energy: + name: g3 move energy + still_energy: + name: g3 still energy + g4: + move_energy: + name: g4 move energy + still_energy: + name: g4 still energy + g5: + move_energy: + name: g5 move energy + still_energy: + name: g5 still energy + g6: + move_energy: + name: g6 move energy + still_energy: + name: g6 still energy + g7: + move_energy: + name: g7 move energy + still_energy: + name: g7 still energy + g8: + move_energy: + name: g8 move energy + still_energy: + name: g8 still energy + +switch: + - platform: ld2410 + engineering_mode: + name: control ld2410 engineering mode + bluetooth: + name: control ld2410 bluetooth + +text_sensor: + - platform: ld2410 + version: + name: presenece sensor version + mac_address: + name: presenece sensor mac address diff --git a/tests/components/ld2410/test.esp32.yaml b/tests/components/ld2410/test.esp32.yaml new file mode 100644 index 0000000000..48ed179d93 --- /dev/null +++ b/tests/components/ld2410/test.esp32.yaml @@ -0,0 +1,169 @@ +uart: + - id: uart_ld2410 + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +ld2410: + id: my_ld2410 + +binary_sensor: + - platform: ld2410 + has_target: + name: presence + has_moving_target: + name: movement + has_still_target: + name: still + out_pin_presence_status: + name: out pin presence status + +button: + - platform: ld2410 + factory_reset: + name: factory reset + restart: + name: restart + query_params: + name: query params + +number: + - platform: ld2410 + light_threshold: + name: light threshold + timeout: + name: timeout + max_move_distance_gate: + name: max move distance gate + max_still_distance_gate: + name: max still distance gate + g0: + move_threshold: + name: g0 move threshold + still_threshold: + name: g0 still threshold + g1: + move_threshold: + name: g1 move threshold + still_threshold: + name: g1 still threshold + g2: + move_threshold: + name: g2 move threshold + still_threshold: + name: g2 still threshold + g3: + move_threshold: + name: g3 move threshold + still_threshold: + name: g3 still threshold + g4: + move_threshold: + name: g4 move threshold + still_threshold: + name: g4 still threshold + g5: + move_threshold: + name: g5 move threshold + still_threshold: + name: g5 still threshold + g6: + move_threshold: + name: g6 move threshold + still_threshold: + name: g6 still threshold + g7: + move_threshold: + name: g7 move threshold + still_threshold: + name: g7 still threshold + g8: + move_threshold: + name: g8 move threshold + still_threshold: + name: g8 still threshold + +select: + - platform: ld2410 + distance_resolution: + name: distance resolution + baud_rate: + name: baud rate + light_function: + name: light function + out_pin_level: + name: out ping level + +sensor: + - platform: ld2410 + light: + name: light + moving_distance: + name: Moving distance + still_distance: + name: Still Distance + moving_energy: + name: Move Energy + still_energy: + name: Still Energy + detection_distance: + name: Distance Detection + g0: + move_energy: + name: g0 move energy + still_energy: + name: g0 still energy + g1: + move_energy: + name: g1 move energy + still_energy: + name: g1 still energy + g2: + move_energy: + name: g2 move energy + still_energy: + name: g2 still energy + g3: + move_energy: + name: g3 move energy + still_energy: + name: g3 still energy + g4: + move_energy: + name: g4 move energy + still_energy: + name: g4 still energy + g5: + move_energy: + name: g5 move energy + still_energy: + name: g5 still energy + g6: + move_energy: + name: g6 move energy + still_energy: + name: g6 still energy + g7: + move_energy: + name: g7 move energy + still_energy: + name: g7 still energy + g8: + move_energy: + name: g8 move energy + still_energy: + name: g8 still energy + +switch: + - platform: ld2410 + engineering_mode: + name: control ld2410 engineering mode + bluetooth: + name: control ld2410 bluetooth + +text_sensor: + - platform: ld2410 + version: + name: presenece sensor version + mac_address: + name: presenece sensor mac address diff --git a/tests/components/ld2410/test.esp8266.yaml b/tests/components/ld2410/test.esp8266.yaml new file mode 100644 index 0000000000..afcaa81b3e --- /dev/null +++ b/tests/components/ld2410/test.esp8266.yaml @@ -0,0 +1,169 @@ +uart: + - id: uart_ld2410 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +ld2410: + id: my_ld2410 + +binary_sensor: + - platform: ld2410 + has_target: + name: presence + has_moving_target: + name: movement + has_still_target: + name: still + out_pin_presence_status: + name: out pin presence status + +button: + - platform: ld2410 + factory_reset: + name: factory reset + restart: + name: restart + query_params: + name: query params + +number: + - platform: ld2410 + light_threshold: + name: light threshold + timeout: + name: timeout + max_move_distance_gate: + name: max move distance gate + max_still_distance_gate: + name: max still distance gate + g0: + move_threshold: + name: g0 move threshold + still_threshold: + name: g0 still threshold + g1: + move_threshold: + name: g1 move threshold + still_threshold: + name: g1 still threshold + g2: + move_threshold: + name: g2 move threshold + still_threshold: + name: g2 still threshold + g3: + move_threshold: + name: g3 move threshold + still_threshold: + name: g3 still threshold + g4: + move_threshold: + name: g4 move threshold + still_threshold: + name: g4 still threshold + g5: + move_threshold: + name: g5 move threshold + still_threshold: + name: g5 still threshold + g6: + move_threshold: + name: g6 move threshold + still_threshold: + name: g6 still threshold + g7: + move_threshold: + name: g7 move threshold + still_threshold: + name: g7 still threshold + g8: + move_threshold: + name: g8 move threshold + still_threshold: + name: g8 still threshold + +select: + - platform: ld2410 + distance_resolution: + name: distance resolution + baud_rate: + name: baud rate + light_function: + name: light function + out_pin_level: + name: out ping level + +sensor: + - platform: ld2410 + light: + name: light + moving_distance: + name: Moving distance + still_distance: + name: Still Distance + moving_energy: + name: Move Energy + still_energy: + name: Still Energy + detection_distance: + name: Distance Detection + g0: + move_energy: + name: g0 move energy + still_energy: + name: g0 still energy + g1: + move_energy: + name: g1 move energy + still_energy: + name: g1 still energy + g2: + move_energy: + name: g2 move energy + still_energy: + name: g2 still energy + g3: + move_energy: + name: g3 move energy + still_energy: + name: g3 still energy + g4: + move_energy: + name: g4 move energy + still_energy: + name: g4 still energy + g5: + move_energy: + name: g5 move energy + still_energy: + name: g5 still energy + g6: + move_energy: + name: g6 move energy + still_energy: + name: g6 still energy + g7: + move_energy: + name: g7 move energy + still_energy: + name: g7 still energy + g8: + move_energy: + name: g8 move energy + still_energy: + name: g8 still energy + +switch: + - platform: ld2410 + engineering_mode: + name: control ld2410 engineering mode + bluetooth: + name: control ld2410 bluetooth + +text_sensor: + - platform: ld2410 + version: + name: presenece sensor version + mac_address: + name: presenece sensor mac address diff --git a/tests/components/ld2410/test.rp2040.yaml b/tests/components/ld2410/test.rp2040.yaml new file mode 100644 index 0000000000..afcaa81b3e --- /dev/null +++ b/tests/components/ld2410/test.rp2040.yaml @@ -0,0 +1,169 @@ +uart: + - id: uart_ld2410 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +ld2410: + id: my_ld2410 + +binary_sensor: + - platform: ld2410 + has_target: + name: presence + has_moving_target: + name: movement + has_still_target: + name: still + out_pin_presence_status: + name: out pin presence status + +button: + - platform: ld2410 + factory_reset: + name: factory reset + restart: + name: restart + query_params: + name: query params + +number: + - platform: ld2410 + light_threshold: + name: light threshold + timeout: + name: timeout + max_move_distance_gate: + name: max move distance gate + max_still_distance_gate: + name: max still distance gate + g0: + move_threshold: + name: g0 move threshold + still_threshold: + name: g0 still threshold + g1: + move_threshold: + name: g1 move threshold + still_threshold: + name: g1 still threshold + g2: + move_threshold: + name: g2 move threshold + still_threshold: + name: g2 still threshold + g3: + move_threshold: + name: g3 move threshold + still_threshold: + name: g3 still threshold + g4: + move_threshold: + name: g4 move threshold + still_threshold: + name: g4 still threshold + g5: + move_threshold: + name: g5 move threshold + still_threshold: + name: g5 still threshold + g6: + move_threshold: + name: g6 move threshold + still_threshold: + name: g6 still threshold + g7: + move_threshold: + name: g7 move threshold + still_threshold: + name: g7 still threshold + g8: + move_threshold: + name: g8 move threshold + still_threshold: + name: g8 still threshold + +select: + - platform: ld2410 + distance_resolution: + name: distance resolution + baud_rate: + name: baud rate + light_function: + name: light function + out_pin_level: + name: out ping level + +sensor: + - platform: ld2410 + light: + name: light + moving_distance: + name: Moving distance + still_distance: + name: Still Distance + moving_energy: + name: Move Energy + still_energy: + name: Still Energy + detection_distance: + name: Distance Detection + g0: + move_energy: + name: g0 move energy + still_energy: + name: g0 still energy + g1: + move_energy: + name: g1 move energy + still_energy: + name: g1 still energy + g2: + move_energy: + name: g2 move energy + still_energy: + name: g2 still energy + g3: + move_energy: + name: g3 move energy + still_energy: + name: g3 still energy + g4: + move_energy: + name: g4 move energy + still_energy: + name: g4 still energy + g5: + move_energy: + name: g5 move energy + still_energy: + name: g5 still energy + g6: + move_energy: + name: g6 move energy + still_energy: + name: g6 still energy + g7: + move_energy: + name: g7 move energy + still_energy: + name: g7 still energy + g8: + move_energy: + name: g8 move energy + still_energy: + name: g8 still energy + +switch: + - platform: ld2410 + engineering_mode: + name: control ld2410 engineering mode + bluetooth: + name: control ld2410 bluetooth + +text_sensor: + - platform: ld2410 + version: + name: presenece sensor version + mac_address: + name: presenece sensor mac address diff --git a/tests/components/ld2420/test.esp32-c3-idf.yaml b/tests/components/ld2420/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..5e0b9db1c2 --- /dev/null +++ b/tests/components/ld2420/test.esp32-c3-idf.yaml @@ -0,0 +1,132 @@ +uart: + - id: uart_ld2420 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +ld2420: + id: my_ld2420 + +binary_sensor: + - platform: ld2420 + has_target: + name: Presence + +button: + - platform: ld2420 + apply_config: + name: Apply Config + factory_reset: + name: Factory Reset + restart_module: + name: Restart Module + revert_config: + name: Undo Edits + +number: + - platform: ld2420 + presence_timeout: + name: Detection Presence Timeout + min_gate_distance: + name: Detection Gate Minimum + max_gate_distance: + name: Detection Gate Maximum + gate_move_sensitivity: + name: Move Calibration Sensitivity Factor + gate_still_sensitivity: + name: Still Calibration Sensitivity Factor + gate_0: + move_threshold: + name: Gate 0 Move Threshold + still_threshold: + name: Gate 0 Still Threshold + gate_1: + move_threshold: + name: Gate 1 Move Threshold + still_threshold: + name: Gate 1 Still Threshold + gate_2: + move_threshold: + name: Gate 2 Move Threshold + still_threshold: + name: Gate 2 Still Threshold + gate_3: + move_threshold: + name: Gate 3 Move Threshold + still_threshold: + name: Gate 3 Still Threshold + gate_4: + move_threshold: + name: Gate 4 Move Threshold + still_threshold: + name: Gate 4 Still Threshold + gate_5: + move_threshold: + name: Gate 5 Move Threshold + still_threshold: + name: Gate 5 Still Threshold + gate_6: + move_threshold: + name: Gate 6 Move Threshold + still_threshold: + name: Gate 6 Still Threshold + gate_7: + move_threshold: + name: Gate 7 Move Threshold + still_threshold: + name: Gate 7 Still Threshold + gate_8: + move_threshold: + name: Gate 8 Move Threshold + still_threshold: + name: Gate 8 Still Threshold + gate_9: + move_threshold: + name: Gate 9 Move Threshold + still_threshold: + name: Gate 9 Still Threshold + gate_10: + move_threshold: + name: Gate 10 Move Threshold + still_threshold: + name: Gate 10 Still Threshold + gate_11: + move_threshold: + name: Gate 11 Move Threshold + still_threshold: + name: Gate 11 Still Threshold + gate_12: + move_threshold: + name: Gate 12 Move Threshold + still_threshold: + name: Gate 12 Still Threshold + gate_13: + move_threshold: + name: Gate 13 Move Threshold + still_threshold: + name: Gate 13 Still Threshold + gate_14: + move_threshold: + name: Gate 14 Move Threshold + still_threshold: + name: Gate 14 Still Threshold + gate_15: + move_threshold: + name: Gate 15 Move Threshold + still_threshold: + name: Gate 15 Still Threshold + +select: + - platform: ld2420 + operating_mode: + name: Operating Mode + +sensor: + - platform: ld2420 + moving_distance: + name: "Moving distance (cm)" + +text_sensor: + - platform: ld2420 + fw_version: + name: LD2420 Firmware diff --git a/tests/components/ld2420/test.esp32-c3.yaml b/tests/components/ld2420/test.esp32-c3.yaml new file mode 100644 index 0000000000..5e0b9db1c2 --- /dev/null +++ b/tests/components/ld2420/test.esp32-c3.yaml @@ -0,0 +1,132 @@ +uart: + - id: uart_ld2420 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +ld2420: + id: my_ld2420 + +binary_sensor: + - platform: ld2420 + has_target: + name: Presence + +button: + - platform: ld2420 + apply_config: + name: Apply Config + factory_reset: + name: Factory Reset + restart_module: + name: Restart Module + revert_config: + name: Undo Edits + +number: + - platform: ld2420 + presence_timeout: + name: Detection Presence Timeout + min_gate_distance: + name: Detection Gate Minimum + max_gate_distance: + name: Detection Gate Maximum + gate_move_sensitivity: + name: Move Calibration Sensitivity Factor + gate_still_sensitivity: + name: Still Calibration Sensitivity Factor + gate_0: + move_threshold: + name: Gate 0 Move Threshold + still_threshold: + name: Gate 0 Still Threshold + gate_1: + move_threshold: + name: Gate 1 Move Threshold + still_threshold: + name: Gate 1 Still Threshold + gate_2: + move_threshold: + name: Gate 2 Move Threshold + still_threshold: + name: Gate 2 Still Threshold + gate_3: + move_threshold: + name: Gate 3 Move Threshold + still_threshold: + name: Gate 3 Still Threshold + gate_4: + move_threshold: + name: Gate 4 Move Threshold + still_threshold: + name: Gate 4 Still Threshold + gate_5: + move_threshold: + name: Gate 5 Move Threshold + still_threshold: + name: Gate 5 Still Threshold + gate_6: + move_threshold: + name: Gate 6 Move Threshold + still_threshold: + name: Gate 6 Still Threshold + gate_7: + move_threshold: + name: Gate 7 Move Threshold + still_threshold: + name: Gate 7 Still Threshold + gate_8: + move_threshold: + name: Gate 8 Move Threshold + still_threshold: + name: Gate 8 Still Threshold + gate_9: + move_threshold: + name: Gate 9 Move Threshold + still_threshold: + name: Gate 9 Still Threshold + gate_10: + move_threshold: + name: Gate 10 Move Threshold + still_threshold: + name: Gate 10 Still Threshold + gate_11: + move_threshold: + name: Gate 11 Move Threshold + still_threshold: + name: Gate 11 Still Threshold + gate_12: + move_threshold: + name: Gate 12 Move Threshold + still_threshold: + name: Gate 12 Still Threshold + gate_13: + move_threshold: + name: Gate 13 Move Threshold + still_threshold: + name: Gate 13 Still Threshold + gate_14: + move_threshold: + name: Gate 14 Move Threshold + still_threshold: + name: Gate 14 Still Threshold + gate_15: + move_threshold: + name: Gate 15 Move Threshold + still_threshold: + name: Gate 15 Still Threshold + +select: + - platform: ld2420 + operating_mode: + name: Operating Mode + +sensor: + - platform: ld2420 + moving_distance: + name: "Moving distance (cm)" + +text_sensor: + - platform: ld2420 + fw_version: + name: LD2420 Firmware diff --git a/tests/components/ld2420/test.esp32-idf.yaml b/tests/components/ld2420/test.esp32-idf.yaml new file mode 100644 index 0000000000..8c883664ec --- /dev/null +++ b/tests/components/ld2420/test.esp32-idf.yaml @@ -0,0 +1,132 @@ +uart: + - id: uart_ld2420 + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +ld2420: + id: my_ld2420 + +binary_sensor: + - platform: ld2420 + has_target: + name: Presence + +button: + - platform: ld2420 + apply_config: + name: Apply Config + factory_reset: + name: Factory Reset + restart_module: + name: Restart Module + revert_config: + name: Undo Edits + +number: + - platform: ld2420 + presence_timeout: + name: Detection Presence Timeout + min_gate_distance: + name: Detection Gate Minimum + max_gate_distance: + name: Detection Gate Maximum + gate_move_sensitivity: + name: Move Calibration Sensitivity Factor + gate_still_sensitivity: + name: Still Calibration Sensitivity Factor + gate_0: + move_threshold: + name: Gate 0 Move Threshold + still_threshold: + name: Gate 0 Still Threshold + gate_1: + move_threshold: + name: Gate 1 Move Threshold + still_threshold: + name: Gate 1 Still Threshold + gate_2: + move_threshold: + name: Gate 2 Move Threshold + still_threshold: + name: Gate 2 Still Threshold + gate_3: + move_threshold: + name: Gate 3 Move Threshold + still_threshold: + name: Gate 3 Still Threshold + gate_4: + move_threshold: + name: Gate 4 Move Threshold + still_threshold: + name: Gate 4 Still Threshold + gate_5: + move_threshold: + name: Gate 5 Move Threshold + still_threshold: + name: Gate 5 Still Threshold + gate_6: + move_threshold: + name: Gate 6 Move Threshold + still_threshold: + name: Gate 6 Still Threshold + gate_7: + move_threshold: + name: Gate 7 Move Threshold + still_threshold: + name: Gate 7 Still Threshold + gate_8: + move_threshold: + name: Gate 8 Move Threshold + still_threshold: + name: Gate 8 Still Threshold + gate_9: + move_threshold: + name: Gate 9 Move Threshold + still_threshold: + name: Gate 9 Still Threshold + gate_10: + move_threshold: + name: Gate 10 Move Threshold + still_threshold: + name: Gate 10 Still Threshold + gate_11: + move_threshold: + name: Gate 11 Move Threshold + still_threshold: + name: Gate 11 Still Threshold + gate_12: + move_threshold: + name: Gate 12 Move Threshold + still_threshold: + name: Gate 12 Still Threshold + gate_13: + move_threshold: + name: Gate 13 Move Threshold + still_threshold: + name: Gate 13 Still Threshold + gate_14: + move_threshold: + name: Gate 14 Move Threshold + still_threshold: + name: Gate 14 Still Threshold + gate_15: + move_threshold: + name: Gate 15 Move Threshold + still_threshold: + name: Gate 15 Still Threshold + +select: + - platform: ld2420 + operating_mode: + name: Operating Mode + +sensor: + - platform: ld2420 + moving_distance: + name: "Moving distance (cm)" + +text_sensor: + - platform: ld2420 + fw_version: + name: LD2420 Firmware diff --git a/tests/components/ld2420/test.esp32.yaml b/tests/components/ld2420/test.esp32.yaml new file mode 100644 index 0000000000..8c883664ec --- /dev/null +++ b/tests/components/ld2420/test.esp32.yaml @@ -0,0 +1,132 @@ +uart: + - id: uart_ld2420 + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +ld2420: + id: my_ld2420 + +binary_sensor: + - platform: ld2420 + has_target: + name: Presence + +button: + - platform: ld2420 + apply_config: + name: Apply Config + factory_reset: + name: Factory Reset + restart_module: + name: Restart Module + revert_config: + name: Undo Edits + +number: + - platform: ld2420 + presence_timeout: + name: Detection Presence Timeout + min_gate_distance: + name: Detection Gate Minimum + max_gate_distance: + name: Detection Gate Maximum + gate_move_sensitivity: + name: Move Calibration Sensitivity Factor + gate_still_sensitivity: + name: Still Calibration Sensitivity Factor + gate_0: + move_threshold: + name: Gate 0 Move Threshold + still_threshold: + name: Gate 0 Still Threshold + gate_1: + move_threshold: + name: Gate 1 Move Threshold + still_threshold: + name: Gate 1 Still Threshold + gate_2: + move_threshold: + name: Gate 2 Move Threshold + still_threshold: + name: Gate 2 Still Threshold + gate_3: + move_threshold: + name: Gate 3 Move Threshold + still_threshold: + name: Gate 3 Still Threshold + gate_4: + move_threshold: + name: Gate 4 Move Threshold + still_threshold: + name: Gate 4 Still Threshold + gate_5: + move_threshold: + name: Gate 5 Move Threshold + still_threshold: + name: Gate 5 Still Threshold + gate_6: + move_threshold: + name: Gate 6 Move Threshold + still_threshold: + name: Gate 6 Still Threshold + gate_7: + move_threshold: + name: Gate 7 Move Threshold + still_threshold: + name: Gate 7 Still Threshold + gate_8: + move_threshold: + name: Gate 8 Move Threshold + still_threshold: + name: Gate 8 Still Threshold + gate_9: + move_threshold: + name: Gate 9 Move Threshold + still_threshold: + name: Gate 9 Still Threshold + gate_10: + move_threshold: + name: Gate 10 Move Threshold + still_threshold: + name: Gate 10 Still Threshold + gate_11: + move_threshold: + name: Gate 11 Move Threshold + still_threshold: + name: Gate 11 Still Threshold + gate_12: + move_threshold: + name: Gate 12 Move Threshold + still_threshold: + name: Gate 12 Still Threshold + gate_13: + move_threshold: + name: Gate 13 Move Threshold + still_threshold: + name: Gate 13 Still Threshold + gate_14: + move_threshold: + name: Gate 14 Move Threshold + still_threshold: + name: Gate 14 Still Threshold + gate_15: + move_threshold: + name: Gate 15 Move Threshold + still_threshold: + name: Gate 15 Still Threshold + +select: + - platform: ld2420 + operating_mode: + name: Operating Mode + +sensor: + - platform: ld2420 + moving_distance: + name: "Moving distance (cm)" + +text_sensor: + - platform: ld2420 + fw_version: + name: LD2420 Firmware diff --git a/tests/components/ld2420/test.esp8266.yaml b/tests/components/ld2420/test.esp8266.yaml new file mode 100644 index 0000000000..5e0b9db1c2 --- /dev/null +++ b/tests/components/ld2420/test.esp8266.yaml @@ -0,0 +1,132 @@ +uart: + - id: uart_ld2420 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +ld2420: + id: my_ld2420 + +binary_sensor: + - platform: ld2420 + has_target: + name: Presence + +button: + - platform: ld2420 + apply_config: + name: Apply Config + factory_reset: + name: Factory Reset + restart_module: + name: Restart Module + revert_config: + name: Undo Edits + +number: + - platform: ld2420 + presence_timeout: + name: Detection Presence Timeout + min_gate_distance: + name: Detection Gate Minimum + max_gate_distance: + name: Detection Gate Maximum + gate_move_sensitivity: + name: Move Calibration Sensitivity Factor + gate_still_sensitivity: + name: Still Calibration Sensitivity Factor + gate_0: + move_threshold: + name: Gate 0 Move Threshold + still_threshold: + name: Gate 0 Still Threshold + gate_1: + move_threshold: + name: Gate 1 Move Threshold + still_threshold: + name: Gate 1 Still Threshold + gate_2: + move_threshold: + name: Gate 2 Move Threshold + still_threshold: + name: Gate 2 Still Threshold + gate_3: + move_threshold: + name: Gate 3 Move Threshold + still_threshold: + name: Gate 3 Still Threshold + gate_4: + move_threshold: + name: Gate 4 Move Threshold + still_threshold: + name: Gate 4 Still Threshold + gate_5: + move_threshold: + name: Gate 5 Move Threshold + still_threshold: + name: Gate 5 Still Threshold + gate_6: + move_threshold: + name: Gate 6 Move Threshold + still_threshold: + name: Gate 6 Still Threshold + gate_7: + move_threshold: + name: Gate 7 Move Threshold + still_threshold: + name: Gate 7 Still Threshold + gate_8: + move_threshold: + name: Gate 8 Move Threshold + still_threshold: + name: Gate 8 Still Threshold + gate_9: + move_threshold: + name: Gate 9 Move Threshold + still_threshold: + name: Gate 9 Still Threshold + gate_10: + move_threshold: + name: Gate 10 Move Threshold + still_threshold: + name: Gate 10 Still Threshold + gate_11: + move_threshold: + name: Gate 11 Move Threshold + still_threshold: + name: Gate 11 Still Threshold + gate_12: + move_threshold: + name: Gate 12 Move Threshold + still_threshold: + name: Gate 12 Still Threshold + gate_13: + move_threshold: + name: Gate 13 Move Threshold + still_threshold: + name: Gate 13 Still Threshold + gate_14: + move_threshold: + name: Gate 14 Move Threshold + still_threshold: + name: Gate 14 Still Threshold + gate_15: + move_threshold: + name: Gate 15 Move Threshold + still_threshold: + name: Gate 15 Still Threshold + +select: + - platform: ld2420 + operating_mode: + name: Operating Mode + +sensor: + - platform: ld2420 + moving_distance: + name: "Moving distance (cm)" + +text_sensor: + - platform: ld2420 + fw_version: + name: LD2420 Firmware diff --git a/tests/components/ld2420/test.rp2040.yaml b/tests/components/ld2420/test.rp2040.yaml new file mode 100644 index 0000000000..5e0b9db1c2 --- /dev/null +++ b/tests/components/ld2420/test.rp2040.yaml @@ -0,0 +1,132 @@ +uart: + - id: uart_ld2420 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +ld2420: + id: my_ld2420 + +binary_sensor: + - platform: ld2420 + has_target: + name: Presence + +button: + - platform: ld2420 + apply_config: + name: Apply Config + factory_reset: + name: Factory Reset + restart_module: + name: Restart Module + revert_config: + name: Undo Edits + +number: + - platform: ld2420 + presence_timeout: + name: Detection Presence Timeout + min_gate_distance: + name: Detection Gate Minimum + max_gate_distance: + name: Detection Gate Maximum + gate_move_sensitivity: + name: Move Calibration Sensitivity Factor + gate_still_sensitivity: + name: Still Calibration Sensitivity Factor + gate_0: + move_threshold: + name: Gate 0 Move Threshold + still_threshold: + name: Gate 0 Still Threshold + gate_1: + move_threshold: + name: Gate 1 Move Threshold + still_threshold: + name: Gate 1 Still Threshold + gate_2: + move_threshold: + name: Gate 2 Move Threshold + still_threshold: + name: Gate 2 Still Threshold + gate_3: + move_threshold: + name: Gate 3 Move Threshold + still_threshold: + name: Gate 3 Still Threshold + gate_4: + move_threshold: + name: Gate 4 Move Threshold + still_threshold: + name: Gate 4 Still Threshold + gate_5: + move_threshold: + name: Gate 5 Move Threshold + still_threshold: + name: Gate 5 Still Threshold + gate_6: + move_threshold: + name: Gate 6 Move Threshold + still_threshold: + name: Gate 6 Still Threshold + gate_7: + move_threshold: + name: Gate 7 Move Threshold + still_threshold: + name: Gate 7 Still Threshold + gate_8: + move_threshold: + name: Gate 8 Move Threshold + still_threshold: + name: Gate 8 Still Threshold + gate_9: + move_threshold: + name: Gate 9 Move Threshold + still_threshold: + name: Gate 9 Still Threshold + gate_10: + move_threshold: + name: Gate 10 Move Threshold + still_threshold: + name: Gate 10 Still Threshold + gate_11: + move_threshold: + name: Gate 11 Move Threshold + still_threshold: + name: Gate 11 Still Threshold + gate_12: + move_threshold: + name: Gate 12 Move Threshold + still_threshold: + name: Gate 12 Still Threshold + gate_13: + move_threshold: + name: Gate 13 Move Threshold + still_threshold: + name: Gate 13 Still Threshold + gate_14: + move_threshold: + name: Gate 14 Move Threshold + still_threshold: + name: Gate 14 Still Threshold + gate_15: + move_threshold: + name: Gate 15 Move Threshold + still_threshold: + name: Gate 15 Still Threshold + +select: + - platform: ld2420 + operating_mode: + name: Operating Mode + +sensor: + - platform: ld2420 + moving_distance: + name: "Moving distance (cm)" + +text_sensor: + - platform: ld2420 + fw_version: + name: LD2420 Firmware diff --git a/tests/components/ledc/test.esp32-c3-idf.yaml b/tests/components/ledc/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..70352b4519 --- /dev/null +++ b/tests/components/ledc/test.esp32-c3-idf.yaml @@ -0,0 +1,11 @@ +esphome: + on_boot: + then: + - output.ledc.set_frequency: + id: test_ledc + frequency: 100Hz + +output: + - platform: ledc + id: test_ledc + pin: 4 diff --git a/tests/components/ledc/test.esp32-c3.yaml b/tests/components/ledc/test.esp32-c3.yaml new file mode 100644 index 0000000000..70352b4519 --- /dev/null +++ b/tests/components/ledc/test.esp32-c3.yaml @@ -0,0 +1,11 @@ +esphome: + on_boot: + then: + - output.ledc.set_frequency: + id: test_ledc + frequency: 100Hz + +output: + - platform: ledc + id: test_ledc + pin: 4 diff --git a/tests/components/ledc/test.esp32-idf.yaml b/tests/components/ledc/test.esp32-idf.yaml new file mode 100644 index 0000000000..70352b4519 --- /dev/null +++ b/tests/components/ledc/test.esp32-idf.yaml @@ -0,0 +1,11 @@ +esphome: + on_boot: + then: + - output.ledc.set_frequency: + id: test_ledc + frequency: 100Hz + +output: + - platform: ledc + id: test_ledc + pin: 4 diff --git a/tests/components/ledc/test.esp32.yaml b/tests/components/ledc/test.esp32.yaml new file mode 100644 index 0000000000..70352b4519 --- /dev/null +++ b/tests/components/ledc/test.esp32.yaml @@ -0,0 +1,11 @@ +esphome: + on_boot: + then: + - output.ledc.set_frequency: + id: test_ledc + frequency: 100Hz + +output: + - platform: ledc + id: test_ledc + pin: 4 diff --git a/tests/components/light/test.esp32-c3-idf.yaml b/tests/components/light/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..8e1709838a --- /dev/null +++ b/tests/components/light/test.esp32-c3-idf.yaml @@ -0,0 +1,132 @@ +esphome: + on_boot: + then: + - light.toggle: test_binary_light + - light.turn_off: test_rgb_light + - light.turn_on: + id: test_rgb_light + brightness: 100% + red: 100% + green: 100% + blue: 1.0 + - light.control: + id: test_monochromatic_light + state: on + - light.dim_relative: + id: test_monochromatic_light + relative_brightness: 5% + +output: + - platform: gpio + id: test_binary + pin: 0 + - platform: ledc + id: test_ledc_1 + pin: 1 + - platform: ledc + id: test_ledc_2 + pin: 2 + - platform: ledc + id: test_ledc_3 + pin: 3 + - platform: ledc + id: test_ledc_4 + pin: 4 + - platform: ledc + id: test_ledc_5 + pin: 5 + +light: + - platform: binary + id: test_binary_light + name: Binary Light + output: test_binary + effects: + - strobe: + on_state: + - logger.log: Binary light state changed + - platform: monochromatic + id: test_monochromatic_light + name: Monochromatic Light + output: test_ledc_1 + gamma_correct: 2.8 + default_transition_length: 2s + effects: + - strobe: + - flicker: + - flicker: + name: My Flicker + alpha: 98% + intensity: 1.5% + - lambda: + name: My Custom Effect + update_interval: 1s + lambda: |- + static int state = 0; + state += 1; + if (state == 4) + state = 0; + - pulse: + transition_length: 10s + update_interval: 20s + min_brightness: 10% + max_brightness: 90% + - pulse: + name: pulse2 + transition_length: + on_length: 10s + off_length: 5s + update_interval: 15s + min_brightness: 10% + max_brightness: 90% + - platform: rgb + id: test_rgb_light + name: RGB Light + red: test_ledc_1 + green: test_ledc_2 + blue: test_ledc_3 + - platform: rgbw + id: test_rgbw_light + name: RGBW Light + red: test_ledc_1 + green: test_ledc_2 + blue: test_ledc_3 + white: test_ledc_4 + color_interlock: true + - platform: rgbww + id: test_rgbww_light + name: RGBWW Light + red: test_ledc_1 + green: test_ledc_2 + blue: test_ledc_3 + cold_white: test_ledc_4 + warm_white: test_ledc_5 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds + color_interlock: true + - platform: rgbct + id: test_rgbct_light + name: RGBCT Light + red: test_ledc_1 + green: test_ledc_2 + blue: test_ledc_3 + color_temperature: test_ledc_4 + white_brightness: test_ledc_5 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds + color_interlock: true + - platform: cwww + id: test_cwww_light + name: CWWW Light + cold_white: test_ledc_1 + warm_white: test_ledc_2 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds + constant_brightness: true + - platform: color_temperature + id: test_color_temperature_light + name: CT Light + color_temperature: test_ledc_1 + brightness: test_ledc_2 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds diff --git a/tests/components/light/test.esp32-c3.yaml b/tests/components/light/test.esp32-c3.yaml new file mode 100644 index 0000000000..8e1709838a --- /dev/null +++ b/tests/components/light/test.esp32-c3.yaml @@ -0,0 +1,132 @@ +esphome: + on_boot: + then: + - light.toggle: test_binary_light + - light.turn_off: test_rgb_light + - light.turn_on: + id: test_rgb_light + brightness: 100% + red: 100% + green: 100% + blue: 1.0 + - light.control: + id: test_monochromatic_light + state: on + - light.dim_relative: + id: test_monochromatic_light + relative_brightness: 5% + +output: + - platform: gpio + id: test_binary + pin: 0 + - platform: ledc + id: test_ledc_1 + pin: 1 + - platform: ledc + id: test_ledc_2 + pin: 2 + - platform: ledc + id: test_ledc_3 + pin: 3 + - platform: ledc + id: test_ledc_4 + pin: 4 + - platform: ledc + id: test_ledc_5 + pin: 5 + +light: + - platform: binary + id: test_binary_light + name: Binary Light + output: test_binary + effects: + - strobe: + on_state: + - logger.log: Binary light state changed + - platform: monochromatic + id: test_monochromatic_light + name: Monochromatic Light + output: test_ledc_1 + gamma_correct: 2.8 + default_transition_length: 2s + effects: + - strobe: + - flicker: + - flicker: + name: My Flicker + alpha: 98% + intensity: 1.5% + - lambda: + name: My Custom Effect + update_interval: 1s + lambda: |- + static int state = 0; + state += 1; + if (state == 4) + state = 0; + - pulse: + transition_length: 10s + update_interval: 20s + min_brightness: 10% + max_brightness: 90% + - pulse: + name: pulse2 + transition_length: + on_length: 10s + off_length: 5s + update_interval: 15s + min_brightness: 10% + max_brightness: 90% + - platform: rgb + id: test_rgb_light + name: RGB Light + red: test_ledc_1 + green: test_ledc_2 + blue: test_ledc_3 + - platform: rgbw + id: test_rgbw_light + name: RGBW Light + red: test_ledc_1 + green: test_ledc_2 + blue: test_ledc_3 + white: test_ledc_4 + color_interlock: true + - platform: rgbww + id: test_rgbww_light + name: RGBWW Light + red: test_ledc_1 + green: test_ledc_2 + blue: test_ledc_3 + cold_white: test_ledc_4 + warm_white: test_ledc_5 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds + color_interlock: true + - platform: rgbct + id: test_rgbct_light + name: RGBCT Light + red: test_ledc_1 + green: test_ledc_2 + blue: test_ledc_3 + color_temperature: test_ledc_4 + white_brightness: test_ledc_5 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds + color_interlock: true + - platform: cwww + id: test_cwww_light + name: CWWW Light + cold_white: test_ledc_1 + warm_white: test_ledc_2 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds + constant_brightness: true + - platform: color_temperature + id: test_color_temperature_light + name: CT Light + color_temperature: test_ledc_1 + brightness: test_ledc_2 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds diff --git a/tests/components/light/test.esp32-idf.yaml b/tests/components/light/test.esp32-idf.yaml new file mode 100644 index 0000000000..7e5718d8d4 --- /dev/null +++ b/tests/components/light/test.esp32-idf.yaml @@ -0,0 +1,132 @@ +esphome: + on_boot: + then: + - light.toggle: test_binary_light + - light.turn_off: test_rgb_light + - light.turn_on: + id: test_rgb_light + brightness: 100% + red: 100% + green: 100% + blue: 1.0 + - light.control: + id: test_monochromatic_light + state: on + - light.dim_relative: + id: test_monochromatic_light + relative_brightness: 5% + +output: + - platform: gpio + id: test_binary + pin: 12 + - platform: ledc + id: test_ledc_1 + pin: 13 + - platform: ledc + id: test_ledc_2 + pin: 14 + - platform: ledc + id: test_ledc_3 + pin: 15 + - platform: ledc + id: test_ledc_4 + pin: 16 + - platform: ledc + id: test_ledc_5 + pin: 17 + +light: + - platform: binary + id: test_binary_light + name: Binary Light + output: test_binary + effects: + - strobe: + on_state: + - logger.log: Binary light state changed + - platform: monochromatic + id: test_monochromatic_light + name: Monochromatic Light + output: test_ledc_1 + gamma_correct: 2.8 + default_transition_length: 2s + effects: + - strobe: + - flicker: + - flicker: + name: My Flicker + alpha: 98% + intensity: 1.5% + - lambda: + name: My Custom Effect + update_interval: 1s + lambda: |- + static int state = 0; + state += 1; + if (state == 4) + state = 0; + - pulse: + transition_length: 10s + update_interval: 20s + min_brightness: 10% + max_brightness: 90% + - pulse: + name: pulse2 + transition_length: + on_length: 10s + off_length: 5s + update_interval: 15s + min_brightness: 10% + max_brightness: 90% + - platform: rgb + id: test_rgb_light + name: RGB Light + red: test_ledc_1 + green: test_ledc_2 + blue: test_ledc_3 + - platform: rgbw + id: test_rgbw_light + name: RGBW Light + red: test_ledc_1 + green: test_ledc_2 + blue: test_ledc_3 + white: test_ledc_4 + color_interlock: true + - platform: rgbww + id: test_rgbww_light + name: RGBWW Light + red: test_ledc_1 + green: test_ledc_2 + blue: test_ledc_3 + cold_white: test_ledc_4 + warm_white: test_ledc_5 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds + color_interlock: true + - platform: rgbct + id: test_rgbct_light + name: RGBCT Light + red: test_ledc_1 + green: test_ledc_2 + blue: test_ledc_3 + color_temperature: test_ledc_4 + white_brightness: test_ledc_5 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds + color_interlock: true + - platform: cwww + id: test_cwww_light + name: CWWW Light + cold_white: test_ledc_1 + warm_white: test_ledc_2 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds + constant_brightness: true + - platform: color_temperature + id: test_color_temperature_light + name: CT Light + color_temperature: test_ledc_1 + brightness: test_ledc_2 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds diff --git a/tests/components/light/test.esp32.yaml b/tests/components/light/test.esp32.yaml new file mode 100644 index 0000000000..7e5718d8d4 --- /dev/null +++ b/tests/components/light/test.esp32.yaml @@ -0,0 +1,132 @@ +esphome: + on_boot: + then: + - light.toggle: test_binary_light + - light.turn_off: test_rgb_light + - light.turn_on: + id: test_rgb_light + brightness: 100% + red: 100% + green: 100% + blue: 1.0 + - light.control: + id: test_monochromatic_light + state: on + - light.dim_relative: + id: test_monochromatic_light + relative_brightness: 5% + +output: + - platform: gpio + id: test_binary + pin: 12 + - platform: ledc + id: test_ledc_1 + pin: 13 + - platform: ledc + id: test_ledc_2 + pin: 14 + - platform: ledc + id: test_ledc_3 + pin: 15 + - platform: ledc + id: test_ledc_4 + pin: 16 + - platform: ledc + id: test_ledc_5 + pin: 17 + +light: + - platform: binary + id: test_binary_light + name: Binary Light + output: test_binary + effects: + - strobe: + on_state: + - logger.log: Binary light state changed + - platform: monochromatic + id: test_monochromatic_light + name: Monochromatic Light + output: test_ledc_1 + gamma_correct: 2.8 + default_transition_length: 2s + effects: + - strobe: + - flicker: + - flicker: + name: My Flicker + alpha: 98% + intensity: 1.5% + - lambda: + name: My Custom Effect + update_interval: 1s + lambda: |- + static int state = 0; + state += 1; + if (state == 4) + state = 0; + - pulse: + transition_length: 10s + update_interval: 20s + min_brightness: 10% + max_brightness: 90% + - pulse: + name: pulse2 + transition_length: + on_length: 10s + off_length: 5s + update_interval: 15s + min_brightness: 10% + max_brightness: 90% + - platform: rgb + id: test_rgb_light + name: RGB Light + red: test_ledc_1 + green: test_ledc_2 + blue: test_ledc_3 + - platform: rgbw + id: test_rgbw_light + name: RGBW Light + red: test_ledc_1 + green: test_ledc_2 + blue: test_ledc_3 + white: test_ledc_4 + color_interlock: true + - platform: rgbww + id: test_rgbww_light + name: RGBWW Light + red: test_ledc_1 + green: test_ledc_2 + blue: test_ledc_3 + cold_white: test_ledc_4 + warm_white: test_ledc_5 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds + color_interlock: true + - platform: rgbct + id: test_rgbct_light + name: RGBCT Light + red: test_ledc_1 + green: test_ledc_2 + blue: test_ledc_3 + color_temperature: test_ledc_4 + white_brightness: test_ledc_5 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds + color_interlock: true + - platform: cwww + id: test_cwww_light + name: CWWW Light + cold_white: test_ledc_1 + warm_white: test_ledc_2 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds + constant_brightness: true + - platform: color_temperature + id: test_color_temperature_light + name: CT Light + color_temperature: test_ledc_1 + brightness: test_ledc_2 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds diff --git a/tests/components/light/test.esp8266.yaml b/tests/components/light/test.esp8266.yaml new file mode 100644 index 0000000000..4611fb374a --- /dev/null +++ b/tests/components/light/test.esp8266.yaml @@ -0,0 +1,132 @@ +esphome: + on_boot: + then: + - light.toggle: test_binary_light + - light.turn_off: test_rgb_light + - light.turn_on: + id: test_rgb_light + brightness: 100% + red: 100% + green: 100% + blue: 1.0 + - light.control: + id: test_monochromatic_light + state: on + - light.dim_relative: + id: test_monochromatic_light + relative_brightness: 5% + +output: + - platform: gpio + id: test_binary + pin: 4 + - platform: esp8266_pwm + id: test_ledc_1 + pin: 12 + - platform: esp8266_pwm + id: test_ledc_2 + pin: 13 + - platform: esp8266_pwm + id: test_ledc_3 + pin: 14 + - platform: esp8266_pwm + id: test_ledc_4 + pin: 15 + - platform: esp8266_pwm + id: test_ledc_5 + pin: 16 + +light: + - platform: binary + id: test_binary_light + name: Binary Light + output: test_binary + effects: + - strobe: + on_state: + - logger.log: Binary light state changed + - platform: monochromatic + id: test_monochromatic_light + name: Monochromatic Light + output: test_ledc_1 + gamma_correct: 2.8 + default_transition_length: 2s + effects: + - strobe: + - flicker: + - flicker: + name: My Flicker + alpha: 98% + intensity: 1.5% + - lambda: + name: My Custom Effect + update_interval: 1s + lambda: |- + static int state = 0; + state += 1; + if (state == 4) + state = 0; + - pulse: + transition_length: 10s + update_interval: 20s + min_brightness: 10% + max_brightness: 90% + - pulse: + name: pulse2 + transition_length: + on_length: 10s + off_length: 5s + update_interval: 15s + min_brightness: 10% + max_brightness: 90% + - platform: rgb + id: test_rgb_light + name: RGB Light + red: test_ledc_1 + green: test_ledc_2 + blue: test_ledc_3 + - platform: rgbw + id: test_rgbw_light + name: RGBW Light + red: test_ledc_1 + green: test_ledc_2 + blue: test_ledc_3 + white: test_ledc_4 + color_interlock: true + - platform: rgbww + id: test_rgbww_light + name: RGBWW Light + red: test_ledc_1 + green: test_ledc_2 + blue: test_ledc_3 + cold_white: test_ledc_4 + warm_white: test_ledc_5 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds + color_interlock: true + - platform: rgbct + id: test_rgbct_light + name: RGBCT Light + red: test_ledc_1 + green: test_ledc_2 + blue: test_ledc_3 + color_temperature: test_ledc_4 + white_brightness: test_ledc_5 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds + color_interlock: true + - platform: cwww + id: test_cwww_light + name: CWWW Light + cold_white: test_ledc_1 + warm_white: test_ledc_2 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds + constant_brightness: true + - platform: color_temperature + id: test_color_temperature_light + name: CT Light + color_temperature: test_ledc_1 + brightness: test_ledc_2 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds diff --git a/tests/components/light/test.rp2040.yaml b/tests/components/light/test.rp2040.yaml new file mode 100644 index 0000000000..0215a17e71 --- /dev/null +++ b/tests/components/light/test.rp2040.yaml @@ -0,0 +1,132 @@ +esphome: + on_boot: + then: + - light.toggle: test_binary_light + - light.turn_off: test_rgb_light + - light.turn_on: + id: test_rgb_light + brightness: 100% + red: 100% + green: 100% + blue: 1.0 + - light.control: + id: test_monochromatic_light + state: on + - light.dim_relative: + id: test_monochromatic_light + relative_brightness: 5% + +output: + - platform: gpio + id: test_binary + pin: 0 + - platform: rp2040_pwm + id: test_ledc_1 + pin: 1 + - platform: rp2040_pwm + id: test_ledc_2 + pin: 2 + - platform: rp2040_pwm + id: test_ledc_3 + pin: 3 + - platform: rp2040_pwm + id: test_ledc_4 + pin: 4 + - platform: rp2040_pwm + id: test_ledc_5 + pin: 5 + +light: + - platform: binary + id: test_binary_light + name: Binary Light + output: test_binary + effects: + - strobe: + on_state: + - logger.log: Binary light state changed + - platform: monochromatic + id: test_monochromatic_light + name: Monochromatic Light + output: test_ledc_1 + gamma_correct: 2.8 + default_transition_length: 2s + effects: + - strobe: + - flicker: + - flicker: + name: My Flicker + alpha: 98% + intensity: 1.5% + - lambda: + name: My Custom Effect + update_interval: 1s + lambda: |- + static int state = 0; + state += 1; + if (state == 4) + state = 0; + - pulse: + transition_length: 10s + update_interval: 20s + min_brightness: 10% + max_brightness: 90% + - pulse: + name: pulse2 + transition_length: + on_length: 10s + off_length: 5s + update_interval: 15s + min_brightness: 10% + max_brightness: 90% + - platform: rgb + id: test_rgb_light + name: RGB Light + red: test_ledc_1 + green: test_ledc_2 + blue: test_ledc_3 + - platform: rgbw + id: test_rgbw_light + name: RGBW Light + red: test_ledc_1 + green: test_ledc_2 + blue: test_ledc_3 + white: test_ledc_4 + color_interlock: true + - platform: rgbww + id: test_rgbww_light + name: RGBWW Light + red: test_ledc_1 + green: test_ledc_2 + blue: test_ledc_3 + cold_white: test_ledc_4 + warm_white: test_ledc_5 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds + color_interlock: true + - platform: rgbct + id: test_rgbct_light + name: RGBCT Light + red: test_ledc_1 + green: test_ledc_2 + blue: test_ledc_3 + color_temperature: test_ledc_4 + white_brightness: test_ledc_5 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds + color_interlock: true + - platform: cwww + id: test_cwww_light + name: CWWW Light + cold_white: test_ledc_1 + warm_white: test_ledc_2 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds + constant_brightness: true + - platform: color_temperature + id: test_color_temperature_light + name: CT Light + color_temperature: test_ledc_1 + brightness: test_ledc_2 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds diff --git a/tests/components/lightwaverf/test.esp8266.yaml b/tests/components/lightwaverf/test.esp8266.yaml new file mode 100644 index 0000000000..8f983a3cca --- /dev/null +++ b/tests/components/lightwaverf/test.esp8266.yaml @@ -0,0 +1,13 @@ +lightwaverf: + read_pin: 5 + write_pin: 4 + +button: + - platform: template + name: "Turn off sofa" + id: light_off_ceiling_sofa + on_press: + lightwaverf.send_raw: + code: [0x04, 0x00, 0x00, 0x00, 0x0f, 0x03, 0x0d, 0x09, 0x08, 0x08] + name: "Sofa" + repeat: 1 diff --git a/tests/components/lilygo_t5_47/test.esp32-c3-idf.yaml b/tests/components/lilygo_t5_47/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..41e81103ac --- /dev/null +++ b/tests/components/lilygo_t5_47/test.esp32-c3-idf.yaml @@ -0,0 +1,24 @@ +i2c: + - id: i2c_lilygo_t5_47 + scl: 5 + sda: 4 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 3 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: lilygo_t5_47 + id: lilygo_touchscreen + interrupt_pin: 6 + display: ssd1306_display + on_touch: + - logger.log: + format: Touch at (%d, %d) + args: [touch.x, touch.y] diff --git a/tests/components/lilygo_t5_47/test.esp32-c3.yaml b/tests/components/lilygo_t5_47/test.esp32-c3.yaml new file mode 100644 index 0000000000..41e81103ac --- /dev/null +++ b/tests/components/lilygo_t5_47/test.esp32-c3.yaml @@ -0,0 +1,24 @@ +i2c: + - id: i2c_lilygo_t5_47 + scl: 5 + sda: 4 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 3 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: lilygo_t5_47 + id: lilygo_touchscreen + interrupt_pin: 6 + display: ssd1306_display + on_touch: + - logger.log: + format: Touch at (%d, %d) + args: [touch.x, touch.y] diff --git a/tests/components/lilygo_t5_47/test.esp32-idf.yaml b/tests/components/lilygo_t5_47/test.esp32-idf.yaml new file mode 100644 index 0000000000..35eb3df022 --- /dev/null +++ b/tests/components/lilygo_t5_47/test.esp32-idf.yaml @@ -0,0 +1,24 @@ +i2c: + - id: i2c_lilygo_t5_47 + scl: 16 + sda: 17 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 13 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: lilygo_t5_47 + id: lilygo_touchscreen + interrupt_pin: 14 + display: ssd1306_display + on_touch: + - logger.log: + format: Touch at (%d, %d) + args: [touch.x, touch.y] diff --git a/tests/components/lilygo_t5_47/test.esp32.yaml b/tests/components/lilygo_t5_47/test.esp32.yaml new file mode 100644 index 0000000000..35eb3df022 --- /dev/null +++ b/tests/components/lilygo_t5_47/test.esp32.yaml @@ -0,0 +1,24 @@ +i2c: + - id: i2c_lilygo_t5_47 + scl: 16 + sda: 17 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 13 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: lilygo_t5_47 + id: lilygo_touchscreen + interrupt_pin: 14 + display: ssd1306_display + on_touch: + - logger.log: + format: Touch at (%d, %d) + args: [touch.x, touch.y] diff --git a/tests/components/lilygo_t5_47/test.esp8266.yaml b/tests/components/lilygo_t5_47/test.esp8266.yaml new file mode 100644 index 0000000000..766c492b12 --- /dev/null +++ b/tests/components/lilygo_t5_47/test.esp8266.yaml @@ -0,0 +1,24 @@ +i2c: + - id: i2c_lilygo_t5_47 + scl: 5 + sda: 4 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 3 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: lilygo_t5_47 + id: lilygo_touchscreen + interrupt_pin: 12 + display: ssd1306_display + on_touch: + - logger.log: + format: Touch at (%d, %d) + args: [touch.x, touch.y] diff --git a/tests/components/lilygo_t5_47/test.rp2040.yaml b/tests/components/lilygo_t5_47/test.rp2040.yaml new file mode 100644 index 0000000000..41e81103ac --- /dev/null +++ b/tests/components/lilygo_t5_47/test.rp2040.yaml @@ -0,0 +1,24 @@ +i2c: + - id: i2c_lilygo_t5_47 + scl: 5 + sda: 4 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 3 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: lilygo_t5_47 + id: lilygo_touchscreen + interrupt_pin: 6 + display: ssd1306_display + on_touch: + - logger.log: + format: Touch at (%d, %d) + args: [touch.x, touch.y] diff --git a/tests/components/lock/test.esp32-c3-idf.yaml b/tests/components/lock/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..82297a3da4 --- /dev/null +++ b/tests/components/lock/test.esp32-c3-idf.yaml @@ -0,0 +1,36 @@ +esphome: + on_boot: + then: + - lock.lock: test_lock1 + - lock.unlock: test_lock1 + - lock.open: test_lock1 + +output: + - platform: gpio + id: test_binary + pin: 4 + +lock: + - platform: template + id: test_lock1 + name: Template Lock + lambda: |- + if (millis() > 10000) { + return LOCK_STATE_LOCKED; + } else { + return LOCK_STATE_UNLOCKED; + } + optimistic: true + assumed_state: false + on_unlock: + - lock.template.publish: + id: test_lock1 + state: !lambda "return LOCK_STATE_UNLOCKED;" + on_lock: + - lock.template.publish: + id: test_lock1 + state: !lambda "return LOCK_STATE_LOCKED;" + - platform: output + name: Generic Output Lock + id: test_lock2 + output: test_binary diff --git a/tests/components/lock/test.esp32-c3.yaml b/tests/components/lock/test.esp32-c3.yaml new file mode 100644 index 0000000000..82297a3da4 --- /dev/null +++ b/tests/components/lock/test.esp32-c3.yaml @@ -0,0 +1,36 @@ +esphome: + on_boot: + then: + - lock.lock: test_lock1 + - lock.unlock: test_lock1 + - lock.open: test_lock1 + +output: + - platform: gpio + id: test_binary + pin: 4 + +lock: + - platform: template + id: test_lock1 + name: Template Lock + lambda: |- + if (millis() > 10000) { + return LOCK_STATE_LOCKED; + } else { + return LOCK_STATE_UNLOCKED; + } + optimistic: true + assumed_state: false + on_unlock: + - lock.template.publish: + id: test_lock1 + state: !lambda "return LOCK_STATE_UNLOCKED;" + on_lock: + - lock.template.publish: + id: test_lock1 + state: !lambda "return LOCK_STATE_LOCKED;" + - platform: output + name: Generic Output Lock + id: test_lock2 + output: test_binary diff --git a/tests/components/lock/test.esp32-idf.yaml b/tests/components/lock/test.esp32-idf.yaml new file mode 100644 index 0000000000..82297a3da4 --- /dev/null +++ b/tests/components/lock/test.esp32-idf.yaml @@ -0,0 +1,36 @@ +esphome: + on_boot: + then: + - lock.lock: test_lock1 + - lock.unlock: test_lock1 + - lock.open: test_lock1 + +output: + - platform: gpio + id: test_binary + pin: 4 + +lock: + - platform: template + id: test_lock1 + name: Template Lock + lambda: |- + if (millis() > 10000) { + return LOCK_STATE_LOCKED; + } else { + return LOCK_STATE_UNLOCKED; + } + optimistic: true + assumed_state: false + on_unlock: + - lock.template.publish: + id: test_lock1 + state: !lambda "return LOCK_STATE_UNLOCKED;" + on_lock: + - lock.template.publish: + id: test_lock1 + state: !lambda "return LOCK_STATE_LOCKED;" + - platform: output + name: Generic Output Lock + id: test_lock2 + output: test_binary diff --git a/tests/components/lock/test.esp32.yaml b/tests/components/lock/test.esp32.yaml new file mode 100644 index 0000000000..82297a3da4 --- /dev/null +++ b/tests/components/lock/test.esp32.yaml @@ -0,0 +1,36 @@ +esphome: + on_boot: + then: + - lock.lock: test_lock1 + - lock.unlock: test_lock1 + - lock.open: test_lock1 + +output: + - platform: gpio + id: test_binary + pin: 4 + +lock: + - platform: template + id: test_lock1 + name: Template Lock + lambda: |- + if (millis() > 10000) { + return LOCK_STATE_LOCKED; + } else { + return LOCK_STATE_UNLOCKED; + } + optimistic: true + assumed_state: false + on_unlock: + - lock.template.publish: + id: test_lock1 + state: !lambda "return LOCK_STATE_UNLOCKED;" + on_lock: + - lock.template.publish: + id: test_lock1 + state: !lambda "return LOCK_STATE_LOCKED;" + - platform: output + name: Generic Output Lock + id: test_lock2 + output: test_binary diff --git a/tests/components/lock/test.esp8266.yaml b/tests/components/lock/test.esp8266.yaml new file mode 100644 index 0000000000..82297a3da4 --- /dev/null +++ b/tests/components/lock/test.esp8266.yaml @@ -0,0 +1,36 @@ +esphome: + on_boot: + then: + - lock.lock: test_lock1 + - lock.unlock: test_lock1 + - lock.open: test_lock1 + +output: + - platform: gpio + id: test_binary + pin: 4 + +lock: + - platform: template + id: test_lock1 + name: Template Lock + lambda: |- + if (millis() > 10000) { + return LOCK_STATE_LOCKED; + } else { + return LOCK_STATE_UNLOCKED; + } + optimistic: true + assumed_state: false + on_unlock: + - lock.template.publish: + id: test_lock1 + state: !lambda "return LOCK_STATE_UNLOCKED;" + on_lock: + - lock.template.publish: + id: test_lock1 + state: !lambda "return LOCK_STATE_LOCKED;" + - platform: output + name: Generic Output Lock + id: test_lock2 + output: test_binary diff --git a/tests/components/lock/test.rp2040.yaml b/tests/components/lock/test.rp2040.yaml new file mode 100644 index 0000000000..82297a3da4 --- /dev/null +++ b/tests/components/lock/test.rp2040.yaml @@ -0,0 +1,36 @@ +esphome: + on_boot: + then: + - lock.lock: test_lock1 + - lock.unlock: test_lock1 + - lock.open: test_lock1 + +output: + - platform: gpio + id: test_binary + pin: 4 + +lock: + - platform: template + id: test_lock1 + name: Template Lock + lambda: |- + if (millis() > 10000) { + return LOCK_STATE_LOCKED; + } else { + return LOCK_STATE_UNLOCKED; + } + optimistic: true + assumed_state: false + on_unlock: + - lock.template.publish: + id: test_lock1 + state: !lambda "return LOCK_STATE_UNLOCKED;" + on_lock: + - lock.template.publish: + id: test_lock1 + state: !lambda "return LOCK_STATE_LOCKED;" + - platform: output + name: Generic Output Lock + id: test_lock2 + output: test_binary diff --git a/tests/components/logger/test.esp32-c3-idf.yaml b/tests/components/logger/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..70b485daac --- /dev/null +++ b/tests/components/logger/test.esp32-c3-idf.yaml @@ -0,0 +1,7 @@ +esphome: + on_boot: + then: + - logger.log: Hello world + +logger: + level: DEBUG diff --git a/tests/components/logger/test.esp32-c3.yaml b/tests/components/logger/test.esp32-c3.yaml new file mode 100644 index 0000000000..70b485daac --- /dev/null +++ b/tests/components/logger/test.esp32-c3.yaml @@ -0,0 +1,7 @@ +esphome: + on_boot: + then: + - logger.log: Hello world + +logger: + level: DEBUG diff --git a/tests/components/logger/test.esp32-idf.yaml b/tests/components/logger/test.esp32-idf.yaml new file mode 100644 index 0000000000..70b485daac --- /dev/null +++ b/tests/components/logger/test.esp32-idf.yaml @@ -0,0 +1,7 @@ +esphome: + on_boot: + then: + - logger.log: Hello world + +logger: + level: DEBUG diff --git a/tests/components/logger/test.esp32.yaml b/tests/components/logger/test.esp32.yaml new file mode 100644 index 0000000000..70b485daac --- /dev/null +++ b/tests/components/logger/test.esp32.yaml @@ -0,0 +1,7 @@ +esphome: + on_boot: + then: + - logger.log: Hello world + +logger: + level: DEBUG diff --git a/tests/components/logger/test.esp8266.yaml b/tests/components/logger/test.esp8266.yaml new file mode 100644 index 0000000000..70b485daac --- /dev/null +++ b/tests/components/logger/test.esp8266.yaml @@ -0,0 +1,7 @@ +esphome: + on_boot: + then: + - logger.log: Hello world + +logger: + level: DEBUG diff --git a/tests/components/logger/test.rp2040.yaml b/tests/components/logger/test.rp2040.yaml new file mode 100644 index 0000000000..70b485daac --- /dev/null +++ b/tests/components/logger/test.rp2040.yaml @@ -0,0 +1,7 @@ +esphome: + on_boot: + then: + - logger.log: Hello world + +logger: + level: DEBUG diff --git a/tests/components/ltr390/test.esp32-c3-idf.yaml b/tests/components/ltr390/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..fee0f37ce1 --- /dev/null +++ b/tests/components/ltr390/test.esp32-c3-idf.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_ltr390 + scl: 5 + sda: 4 + +sensor: + - platform: ltr390 + uv: + name: LTR390 UV + uv_index: + name: LTR390 UVI + light: + name: LTR390 Light + ambient_light: + name: LTR390 ALS + gain: X3 + resolution: 18 + window_correction_factor: 1.0 + address: 0x53 + update_interval: 60s diff --git a/tests/components/ltr390/test.esp32-c3.yaml b/tests/components/ltr390/test.esp32-c3.yaml new file mode 100644 index 0000000000..fee0f37ce1 --- /dev/null +++ b/tests/components/ltr390/test.esp32-c3.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_ltr390 + scl: 5 + sda: 4 + +sensor: + - platform: ltr390 + uv: + name: LTR390 UV + uv_index: + name: LTR390 UVI + light: + name: LTR390 Light + ambient_light: + name: LTR390 ALS + gain: X3 + resolution: 18 + window_correction_factor: 1.0 + address: 0x53 + update_interval: 60s diff --git a/tests/components/ltr390/test.esp32-idf.yaml b/tests/components/ltr390/test.esp32-idf.yaml new file mode 100644 index 0000000000..9786c7dac3 --- /dev/null +++ b/tests/components/ltr390/test.esp32-idf.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_ltr390 + scl: 16 + sda: 17 + +sensor: + - platform: ltr390 + uv: + name: LTR390 UV + uv_index: + name: LTR390 UVI + light: + name: LTR390 Light + ambient_light: + name: LTR390 ALS + gain: X3 + resolution: 18 + window_correction_factor: 1.0 + address: 0x53 + update_interval: 60s diff --git a/tests/components/ltr390/test.esp32.yaml b/tests/components/ltr390/test.esp32.yaml new file mode 100644 index 0000000000..9786c7dac3 --- /dev/null +++ b/tests/components/ltr390/test.esp32.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_ltr390 + scl: 16 + sda: 17 + +sensor: + - platform: ltr390 + uv: + name: LTR390 UV + uv_index: + name: LTR390 UVI + light: + name: LTR390 Light + ambient_light: + name: LTR390 ALS + gain: X3 + resolution: 18 + window_correction_factor: 1.0 + address: 0x53 + update_interval: 60s diff --git a/tests/components/ltr390/test.esp8266.yaml b/tests/components/ltr390/test.esp8266.yaml new file mode 100644 index 0000000000..fee0f37ce1 --- /dev/null +++ b/tests/components/ltr390/test.esp8266.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_ltr390 + scl: 5 + sda: 4 + +sensor: + - platform: ltr390 + uv: + name: LTR390 UV + uv_index: + name: LTR390 UVI + light: + name: LTR390 Light + ambient_light: + name: LTR390 ALS + gain: X3 + resolution: 18 + window_correction_factor: 1.0 + address: 0x53 + update_interval: 60s diff --git a/tests/components/ltr390/test.rp2040.yaml b/tests/components/ltr390/test.rp2040.yaml new file mode 100644 index 0000000000..fee0f37ce1 --- /dev/null +++ b/tests/components/ltr390/test.rp2040.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_ltr390 + scl: 5 + sda: 4 + +sensor: + - platform: ltr390 + uv: + name: LTR390 UV + uv_index: + name: LTR390 UVI + light: + name: LTR390 Light + ambient_light: + name: LTR390 ALS + gain: X3 + resolution: 18 + window_correction_factor: 1.0 + address: 0x53 + update_interval: 60s From 6b7f9b15ea52ba15a48f37e22e70c6a49dbdc8d7 Mon Sep 17 00:00:00 2001 From: MagicBear Date: Thu, 28 Mar 2024 02:56:19 +0800 Subject: [PATCH 1172/2101] feat: Add Daikin ARC (tested on Daikin ARC472A62) (#6429) --- CODEOWNERS | 1 + esphome/components/daikin_arc/__init__.py | 1 + esphome/components/daikin_arc/climate.py | 18 + esphome/components/daikin_arc/daikin_arc.cpp | 487 ++++++++++++++++++ esphome/components/daikin_arc/daikin_arc.h | 76 +++ tests/components/daikin_arc/test.esp32.yaml | 19 + tests/components/daikin_arc/test.esp8266.yaml | 19 + 7 files changed, 621 insertions(+) create mode 100644 esphome/components/daikin_arc/__init__.py create mode 100644 esphome/components/daikin_arc/climate.py create mode 100644 esphome/components/daikin_arc/daikin_arc.cpp create mode 100644 esphome/components/daikin_arc/daikin_arc.h create mode 100644 tests/components/daikin_arc/test.esp32.yaml create mode 100644 tests/components/daikin_arc/test.esp8266.yaml diff --git a/CODEOWNERS b/CODEOWNERS index d6ec3843a5..7c1f7ff70b 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -87,6 +87,7 @@ esphome/components/cst816/* @clydebarrow esphome/components/ct_clamp/* @jesserockz esphome/components/current_based/* @djwmarcx esphome/components/dac7678/* @NickB1 +esphome/components/daikin_arc/* @MagicBear esphome/components/daikin_brc/* @hagak esphome/components/daly_bms/* @s1lvi0 esphome/components/dashboard_import/* @esphome/core diff --git a/esphome/components/daikin_arc/__init__.py b/esphome/components/daikin_arc/__init__.py new file mode 100644 index 0000000000..f9164fb02b --- /dev/null +++ b/esphome/components/daikin_arc/__init__.py @@ -0,0 +1 @@ +CODEOWNERS = ["@MagicBear"] diff --git a/esphome/components/daikin_arc/climate.py b/esphome/components/daikin_arc/climate.py new file mode 100644 index 0000000000..51f253e9cb --- /dev/null +++ b/esphome/components/daikin_arc/climate.py @@ -0,0 +1,18 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import climate_ir +from esphome.const import CONF_ID + +AUTO_LOAD = ["climate_ir"] + +daikin_arc_ns = cg.esphome_ns.namespace("daikin_arc") +DaikinArcClimate = daikin_arc_ns.class_("DaikinArcClimate", climate_ir.ClimateIR) + +CONFIG_SCHEMA = climate_ir.CLIMATE_IR_WITH_RECEIVER_SCHEMA.extend( + {cv.GenerateID(): cv.declare_id(DaikinArcClimate)} +) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + await climate_ir.register_climate_ir(var, config) diff --git a/esphome/components/daikin_arc/daikin_arc.cpp b/esphome/components/daikin_arc/daikin_arc.cpp new file mode 100644 index 0000000000..f806463d00 --- /dev/null +++ b/esphome/components/daikin_arc/daikin_arc.cpp @@ -0,0 +1,487 @@ +#include "daikin_arc.h" + +#include + +#include "esphome/components/remote_base/remote_base.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace daikin_arc { + +static const char *const TAG = "daikin.climate"; + +void DaikinArcClimate::setup() { + climate_ir::ClimateIR::setup(); + + // Never send nan to HA + if (std::isnan(this->target_humidity)) + this->target_humidity = 0; + if (std::isnan(this->current_temperature)) + this->current_temperature = 0; + if (std::isnan(this->current_humidity)) + this->current_humidity = 0; +} + +void DaikinArcClimate::transmit_query_() { + uint8_t remote_header[8] = {0x11, 0xDA, 0x27, 0x00, 0x84, 0x87, 0x20, 0x00}; + + // Calculate checksum + for (int i = 0; i < sizeof(remote_header) - 1; i++) { + remote_header[sizeof(remote_header) - 1] += remote_header[i]; + } + + auto transmit = this->transmitter_->transmit(); + auto *data = transmit.get_data(); + data->set_carrier_frequency(DAIKIN_IR_FREQUENCY); + + data->mark(DAIKIN_ARC_PRE_MARK); + data->space(DAIKIN_ARC_PRE_SPACE); + + data->mark(DAIKIN_HEADER_MARK); + data->space(DAIKIN_HEADER_SPACE); + + for (uint8_t i : remote_header) { + for (uint8_t mask = 1; mask > 0; mask <<= 1) { // iterate through bit mask + data->mark(DAIKIN_BIT_MARK); + bool bit = i & mask; + data->space(bit ? DAIKIN_ONE_SPACE : DAIKIN_ZERO_SPACE); + } + } + data->mark(DAIKIN_BIT_MARK); + data->space(0); + + transmit.perform(); +} + +void DaikinArcClimate::transmit_state() { + // 0x11, 0xDA, 0x27, 0x00, 0xC5, 0x00, 0x00, 0xD7, 0x11, 0xDA, 0x27, 0x00, + // 0x42, 0x49, 0x05, 0xA2, + uint8_t remote_header[20] = {0x11, 0xDA, 0x27, 0x00, 0x02, 0xd0, 0x02, 0x03, 0x80, 0x03, 0x82, 0x30, 0x41, 0x1f, 0x82, + 0xf4, + /* とつど */ + /* 0x13 */ + 0x00, 0x24, 0x00, 0x00}; + + // 05 0 [1:3]MODE 1 [OFF TMR] [ON TMR] Power + // 06-07 TEMP + // 08 [0:3] SPEED [4:7] Swing + // 09 00 + // 10 00 + // 11, 12: timer + // 13 [0:6] 0000000 [7] POWERMODE + // 14 0a + // 15 c4 + // 16 [0:3] 8 00 [6:7] SENSOR WIND = 11 / NORMAL = 00 + // 17 24 + + uint8_t remote_state[19] = { + 0x11, 0xDA, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x60, 0x00, 0x0a, 0xC4, + /* MODE TEMP HUMD FANH FANL + パワフル音声応答 */ + /* ON + 0x01入 0x0a */ + /* OF + 0x00切 0x02 */ + 0x80, 0x24, 0x00 + /* センサー風 */ + /* ON 0x83 */ + /* OF 0x80 */ + }; + + 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) { + 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]; + } + uint16_t fan_speed = this->fan_speed_(); + remote_state[8] = fan_speed >> 8; + remote_state[9] = fan_speed & 0xff; + + // Calculate checksum + for (int i = 0; i < sizeof(remote_header) - 1; i++) { + remote_header[sizeof(remote_header) - 1] += remote_header[i]; + } + + // Calculate checksum + for (int i = 0; i < DAIKIN_STATE_FRAME_SIZE - 1; i++) { + remote_state[DAIKIN_STATE_FRAME_SIZE - 1] += remote_state[i]; + } + + auto transmit = this->transmitter_->transmit(); + auto *data = transmit.get_data(); + data->set_carrier_frequency(DAIKIN_IR_FREQUENCY); + + data->mark(DAIKIN_ARC_PRE_MARK); + data->space(DAIKIN_ARC_PRE_SPACE); + + data->mark(DAIKIN_HEADER_MARK); + data->space(DAIKIN_HEADER_SPACE); + + for (uint8_t i : remote_header) { + for (uint8_t mask = 1; mask > 0; mask <<= 1) { // iterate through bit mask + data->mark(DAIKIN_BIT_MARK); + bool bit = i & mask; + data->space(bit ? DAIKIN_ONE_SPACE : DAIKIN_ZERO_SPACE); + } + } + data->mark(DAIKIN_BIT_MARK); + data->space(DAIKIN_MESSAGE_SPACE); + + data->mark(DAIKIN_HEADER_MARK); + data->space(DAIKIN_HEADER_SPACE); + + for (uint8_t i : remote_state) { + for (uint8_t mask = 1; mask > 0; mask <<= 1) { // iterate through bit mask + data->mark(DAIKIN_BIT_MARK); + bool bit = i & mask; + data->space(bit ? DAIKIN_ONE_SPACE : DAIKIN_ZERO_SPACE); + } + } + data->mark(DAIKIN_BIT_MARK); + data->space(0); + + transmit.perform(); +} + +uint8_t DaikinArcClimate::operation_mode_() { + uint8_t operating_mode = DAIKIN_MODE_ON; + switch (this->mode) { + case climate::CLIMATE_MODE_COOL: + operating_mode |= DAIKIN_MODE_COOL; + break; + case climate::CLIMATE_MODE_DRY: + operating_mode |= DAIKIN_MODE_DRY; + break; + case climate::CLIMATE_MODE_HEAT: + operating_mode |= DAIKIN_MODE_HEAT; + break; + case climate::CLIMATE_MODE_HEAT_COOL: + operating_mode |= DAIKIN_MODE_AUTO; + break; + case climate::CLIMATE_MODE_FAN_ONLY: + operating_mode |= DAIKIN_MODE_FAN; + break; + case climate::CLIMATE_MODE_OFF: + default: + operating_mode = DAIKIN_MODE_OFF; + break; + } + + return operating_mode; +} + +uint16_t DaikinArcClimate::fan_speed_() { + uint16_t fan_speed; + switch (this->fan_mode.value()) { + case climate::CLIMATE_FAN_LOW: + fan_speed = DAIKIN_FAN_1 << 8; + break; + case climate::CLIMATE_FAN_MEDIUM: + fan_speed = DAIKIN_FAN_3 << 8; + break; + case climate::CLIMATE_FAN_HIGH: + fan_speed = DAIKIN_FAN_5 << 8; + break; + case climate::CLIMATE_FAN_AUTO: + default: + fan_speed = DAIKIN_FAN_AUTO << 8; + } + + // If swing is enabled switch first 4 bits to 1111 + switch (this->swing_mode) { + case climate::CLIMATE_SWING_VERTICAL: + fan_speed |= 0x0F00; + break; + case climate::CLIMATE_SWING_HORIZONTAL: + fan_speed |= 0x000F; + break; + case climate::CLIMATE_SWING_BOTH: + fan_speed |= 0x0F0F; + break; + default: + break; + } + return fan_speed; +} + +uint8_t DaikinArcClimate::temperature_() { + // Force special temperatures depending on the mode + switch (this->mode) { + case climate::CLIMATE_MODE_FAN_ONLY: + return 0x32; + case climate::CLIMATE_MODE_HEAT_COOL: + case climate::CLIMATE_MODE_DRY: + return 0xc0; + default: + float new_temp = clamp(this->target_temperature, DAIKIN_TEMP_MIN, DAIKIN_TEMP_MAX); + uint8_t temperature = (uint8_t) floor(new_temp); + return temperature << 1 | (new_temp - temperature > 0 ? 0x01 : 0); + } +} + +uint8_t DaikinArcClimate::humidity_() { + if (this->target_humidity == 39) { + return 0; + } else if (this->target_humidity <= 40 || this->target_humidity == 44) { + return 40; + } else if (this->target_humidity <= 45 || this->target_humidity == 49) // 41 - 45 + { + return 45; + } else if (this->target_humidity <= 50 || this->target_humidity == 52) // 45 - 50 + { + return 50; + } else { + return 0xff; + } +} + +climate::ClimateTraits DaikinArcClimate::traits() { + climate::ClimateTraits traits = climate_ir::ClimateIR::traits(); + traits.set_supports_current_temperature(true); + traits.set_supports_current_humidity(false); + traits.set_supports_target_humidity(true); + traits.set_visual_min_humidity(38); + traits.set_visual_max_humidity(52); + return traits; +} + +bool DaikinArcClimate::parse_state_frame_(const uint8_t frame[]) { + uint8_t checksum = 0; + for (int i = 0; i < (DAIKIN_STATE_FRAME_SIZE - 1); i++) { + checksum += frame[i]; + } + if (frame[DAIKIN_STATE_FRAME_SIZE - 1] != checksum) { + ESP_LOGI(TAG, "checksum error"); + return false; + } + + char buf[DAIKIN_STATE_FRAME_SIZE * 3 + 1] = {0}; + for (size_t i = 0; i < DAIKIN_STATE_FRAME_SIZE; i++) { + sprintf(buf, "%s%02x ", buf, frame[i]); + } + ESP_LOGD(TAG, "FRAME %s", buf); + + uint8_t mode = frame[5]; + if (mode & DAIKIN_MODE_ON) { + switch (mode & 0xF0) { + case DAIKIN_MODE_COOL: + this->mode = climate::CLIMATE_MODE_COOL; + break; + case DAIKIN_MODE_DRY: + this->mode = climate::CLIMATE_MODE_DRY; + break; + case DAIKIN_MODE_HEAT: + this->mode = climate::CLIMATE_MODE_HEAT; + break; + case DAIKIN_MODE_AUTO: + this->mode = climate::CLIMATE_MODE_HEAT_COOL; + break; + case DAIKIN_MODE_FAN: + this->mode = climate::CLIMATE_MODE_FAN_ONLY; + break; + } + } else { + this->mode = climate::CLIMATE_MODE_OFF; + } + uint8_t temperature = frame[6]; + if (!(temperature & 0xC0)) { + this->target_temperature = temperature >> 1; + this->target_temperature += (temperature & 0x1) ? 0.5 : 0; + } + this->target_humidity = frame[7]; // 0, 40, 45, 50, 0xff + uint8_t fan_mode = frame[8]; + uint8_t swing_mode = frame[9]; + if (fan_mode & 0xF && swing_mode & 0xF) { + this->swing_mode = climate::CLIMATE_SWING_BOTH; + } else if (fan_mode & 0xF) { + this->swing_mode = climate::CLIMATE_SWING_VERTICAL; + } else if (swing_mode & 0xF) { + this->swing_mode = climate::CLIMATE_SWING_HORIZONTAL; + } else { + this->swing_mode = climate::CLIMATE_SWING_OFF; + } + switch (fan_mode & 0xF0) { + case DAIKIN_FAN_1: + case DAIKIN_FAN_2: + case DAIKIN_FAN_SILENT: + this->fan_mode = climate::CLIMATE_FAN_LOW; + break; + case DAIKIN_FAN_3: + this->fan_mode = climate::CLIMATE_FAN_MEDIUM; + break; + case DAIKIN_FAN_4: + case DAIKIN_FAN_5: + this->fan_mode = climate::CLIMATE_FAN_HIGH; + break; + case DAIKIN_FAN_AUTO: + this->fan_mode = climate::CLIMATE_FAN_AUTO; + break; + } + /* + 05 0 [1:3]MODE 1 [OFF TMR] [ON TMR] Power + 06-07 TEMP + 08 [0:3] SPEED [4:7] Swing + 09 00 + 10 00 + 11, 12: timer + 13 [0:6] 0000000 [7] POWERMODE + 14 0a + 15 c4 + 16 [0:3] 8 00 [6:7] SENSOR WIND = 11 / NORMAL = 00 + 17 24 + 05 06 07 08 09 10 11 12 13 14 15 16 17 18 + None FRAME 11 da 27 00 00 49 2e 00 b0 00 00 06 60 00 0a c4 80 24 11 + 1H FRAME 11 da 27 00 00 4d 2e 00 b0 00 00 c6 30 00 2a c4 80 24 c5 + 1H30 FRAME 11 da 27 00 00 4d 2e 00 b0 00 00 a6 32 00 2a c4 80 24 a7 + 2H FRAME 11 da 27 00 00 4d 2e 00 b0 00 00 86 34 00 2a c4 80 24 89 + + */ + this->publish_state(); + return true; +} + +bool DaikinArcClimate::on_receive(remote_base::RemoteReceiveData data) { + uint8_t state_frame[DAIKIN_STATE_FRAME_SIZE] = {}; + + bool valid_daikin_frame = false; + if (data.expect_item(DAIKIN_HEADER_MARK, DAIKIN_HEADER_SPACE)) { + valid_daikin_frame = true; + int bytes_count = data.size() / 2 / 8; + std::unique_ptr buf(new char[bytes_count * 3 + 1]); + buf[0] = '\0'; + for (size_t i = 0; i < bytes_count; i++) { + uint8_t byte = 0; + for (int8_t bit = 0; bit < 8; bit++) { + if (data.expect_item(DAIKIN_BIT_MARK, DAIKIN_ONE_SPACE)) { + byte |= 1 << bit; + } else if (!data.expect_item(DAIKIN_BIT_MARK, DAIKIN_ZERO_SPACE)) { + valid_daikin_frame = false; + break; + } + } + sprintf(buf.get(), "%s%02x ", buf.get(), 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'; + for (size_t j = 0; j < 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'; + } + char type_ch = ' '; + // debug_tolerance = 25% + + if (DAIKIN_DBG_LOWER(DAIKIN_ARC_PRE_MARK) <= data[j] && data[j] <= DAIKIN_DBG_UPPER(DAIKIN_ARC_PRE_MARK)) + type_ch = 'P'; + if (DAIKIN_DBG_LOWER(DAIKIN_ARC_PRE_SPACE) <= -data[j] && -data[j] <= DAIKIN_DBG_UPPER(DAIKIN_ARC_PRE_SPACE)) + type_ch = 'a'; + if (DAIKIN_DBG_LOWER(DAIKIN_HEADER_MARK) <= data[j] && data[j] <= DAIKIN_DBG_UPPER(DAIKIN_HEADER_MARK)) + type_ch = 'H'; + if (DAIKIN_DBG_LOWER(DAIKIN_HEADER_SPACE) <= -data[j] && -data[j] <= DAIKIN_DBG_UPPER(DAIKIN_HEADER_SPACE)) + type_ch = 'h'; + if (DAIKIN_DBG_LOWER(DAIKIN_BIT_MARK) <= data[j] && data[j] <= DAIKIN_DBG_UPPER(DAIKIN_BIT_MARK)) + type_ch = 'B'; + if (DAIKIN_DBG_LOWER(DAIKIN_ONE_SPACE) <= -data[j] && -data[j] <= DAIKIN_DBG_UPPER(DAIKIN_ONE_SPACE)) + type_ch = '1'; + if (DAIKIN_DBG_LOWER(DAIKIN_ZERO_SPACE) <= -data[j] && -data[j] <= DAIKIN_DBG_UPPER(DAIKIN_ZERO_SPACE)) + type_ch = '0'; + + if (abs(data[j]) > 100000) { + sprintf(sbuf, "%s%-5d[%c] ", sbuf, data[j] > 0 ? 99999 : -99999, type_ch); + } else { + sprintf(sbuf, "%s%-5d[%c] ", sbuf, (int) (round(data[j] / 10.) * 10), type_ch); + } + if (j == data.size() - 1) { + ESP_LOGD(TAG, "DATA %04x: %s", (j - 8 > 0xffff ? 0 : j - 8), sbuf); + } + } + } + + data.reset(); + + if (!data.expect_item(DAIKIN_HEADER_MARK, DAIKIN_HEADER_SPACE)) { + ESP_LOGI(TAG, "non daikin_arc expect item"); + return false; + } + + for (uint8_t pos = 0; pos < DAIKIN_STATE_FRAME_SIZE; pos++) { + uint8_t byte = 0; + for (int8_t bit = 0; bit < 8; bit++) { + if (data.expect_item(DAIKIN_BIT_MARK, DAIKIN_ONE_SPACE)) { + byte |= 1 << bit; + } else if (!data.expect_item(DAIKIN_BIT_MARK, DAIKIN_ZERO_SPACE)) { + ESP_LOGI(TAG, "non daikin_arc expect item pos: %d", pos); + return false; + } + } + state_frame[pos] = byte; + if (pos == 0) { + // frame header + if (byte != 0x11) { + ESP_LOGI(TAG, "non daikin_arc expect pos: %d header: %02x", pos, byte); + return false; + } + } else if (pos == 1) { + // frame header + if (byte != 0xDA) { + ESP_LOGI(TAG, "non daikin_arc expect pos: %d header: %02x", pos, byte); + return false; + } + } else if (pos == 2) { + // frame header + if (byte != 0x27) { + ESP_LOGI(TAG, "non daikin_arc expect pos: %d header: %02x", pos, byte); + return false; + } + } else if (pos == 3) { // NOLINT(bugprone-branch-clone) + // frame header + if (byte != 0x00) { + ESP_LOGI(TAG, "non daikin_arc expect pos: %d header: %02x", pos, byte); + return false; + } + } else if (pos == 4) { + // frame type + if (byte != 0x00) { + ESP_LOGI(TAG, "non daikin_arc expect pos: %d header: %02x", pos, byte); + return false; + } + } else if (pos == 5) { + if (data.size() == 385) { + /* + 11 da 27 00 00 1a 0c 04 2c 21 61 07 00 07 0c 00 18 00 0e 3c 00 6c 1b 61 + Inside Temp + Outside Temp + Humdidity + + */ + this->current_temperature = state_frame[5]; // Inside temperature + // this->current_temperature = state_frame[6]; // Outside temperature + this->publish_state(); + return true; + } else if ((byte & 0x40) != 0x40) { + ESP_LOGI(TAG, "non daikin_arc expect pos: %d header: %02x", pos, byte); + return false; + } + } + } + return this->parse_state_frame_(state_frame); +} + +void DaikinArcClimate::control(const climate::ClimateCall &call) { + if (call.get_target_humidity().has_value()) { + this->target_humidity = *call.get_target_humidity(); + } + climate_ir::ClimateIR::control(call); +} + +} // namespace daikin_arc +} // namespace esphome diff --git a/esphome/components/daikin_arc/daikin_arc.h b/esphome/components/daikin_arc/daikin_arc.h new file mode 100644 index 0000000000..6cfffd4725 --- /dev/null +++ b/esphome/components/daikin_arc/daikin_arc.h @@ -0,0 +1,76 @@ +#pragma once + +#include "esphome/components/climate_ir/climate_ir.h" + +namespace esphome { +namespace daikin_arc { + +// Values for Daikin ARC43XXX IR Controllers +// Temperature +const uint8_t DAIKIN_TEMP_MIN = 10; // Celsius +const uint8_t DAIKIN_TEMP_MAX = 30; // Celsius + +// Modes +const uint8_t DAIKIN_MODE_AUTO = 0x00; +const uint8_t DAIKIN_MODE_COOL = 0x30; +const uint8_t DAIKIN_MODE_HEAT = 0x40; +const uint8_t DAIKIN_MODE_DRY = 0x20; +const uint8_t DAIKIN_MODE_FAN = 0x60; +const uint8_t DAIKIN_MODE_OFF = 0x00; +const uint8_t DAIKIN_MODE_ON = 0x01; + +// Fan Speed +const uint8_t DAIKIN_FAN_AUTO = 0xA0; +const uint8_t DAIKIN_FAN_SILENT = 0xB0; +const uint8_t DAIKIN_FAN_1 = 0x30; +const uint8_t DAIKIN_FAN_2 = 0x40; +const uint8_t DAIKIN_FAN_3 = 0x50; +const uint8_t DAIKIN_FAN_4 = 0x60; +const uint8_t DAIKIN_FAN_5 = 0x70; + +// IR Transmission +const uint32_t DAIKIN_IR_FREQUENCY = 38000; +const uint32_t DAIKIN_ARC_PRE_MARK = 9950; +const uint32_t DAIKIN_ARC_PRE_SPACE = 25100; +const uint32_t DAIKIN_HEADER_MARK = 3450; +const uint32_t DAIKIN_HEADER_SPACE = 1760; +const uint32_t DAIKIN_BIT_MARK = 400; +const uint32_t DAIKIN_ONE_SPACE = 1300; +const uint32_t DAIKIN_ZERO_SPACE = 480; +const uint32_t DAIKIN_MESSAGE_SPACE = 35000; + +const uint8_t DAIKIN_DBG_TOLERANCE = 25; +#define DAIKIN_DBG_LOWER(x) ((100 - DAIKIN_DBG_TOLERANCE) * (x) / 100U) +#define DAIKIN_DBG_UPPER(x) ((100 + DAIKIN_DBG_TOLERANCE) * (x) / 100U) + +// State Frame size +const uint8_t DAIKIN_STATE_FRAME_SIZE = 19; + +class DaikinArcClimate : public climate_ir::ClimateIR { + public: + DaikinArcClimate() + : climate_ir::ClimateIR(DAIKIN_TEMP_MIN, DAIKIN_TEMP_MAX, 0.5f, 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, + climate::CLIMATE_SWING_HORIZONTAL, climate::CLIMATE_SWING_BOTH}) {} + + void setup() override; + + protected: + void control(const climate::ClimateCall &call) override; + // Transmit via IR the state of this climate controller. + void transmit_query_(); + void transmit_state() override; + climate::ClimateTraits traits() override; + uint8_t operation_mode_(); + uint16_t fan_speed_(); + uint8_t temperature_(); + uint8_t humidity_(); + // Handle received IR Buffer + bool on_receive(remote_base::RemoteReceiveData data) override; + bool parse_state_frame_(const uint8_t frame[]); +}; + +} // namespace daikin_arc +} // namespace esphome diff --git a/tests/components/daikin_arc/test.esp32.yaml b/tests/components/daikin_arc/test.esp32.yaml new file mode 100644 index 0000000000..a8556e8576 --- /dev/null +++ b/tests/components/daikin_arc/test.esp32.yaml @@ -0,0 +1,19 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + id: tsvr + +remote_receiver: + id: rcvr + pin: + number: 27 + inverted: true + mode: + input: true + pullup: true + tolerance: 40% + +climate: + - platform: daikin_arc + name: "AC" + receiver_id: rcvr diff --git a/tests/components/daikin_arc/test.esp8266.yaml b/tests/components/daikin_arc/test.esp8266.yaml new file mode 100644 index 0000000000..abf1b34a6e --- /dev/null +++ b/tests/components/daikin_arc/test.esp8266.yaml @@ -0,0 +1,19 @@ +remote_transmitter: + pin: 5 + carrier_duty_percent: 50% + id: tsvr + +remote_receiver: + id: rcvr + pin: + number: 2 + inverted: true + mode: + input: true + pullup: true + tolerance: 40% + +climate: + - platform: daikin_arc + name: "AC" + receiver_id: rcvr From 0ff543ffe5c38509ab1f8cd7ddcaffb4617b1a99 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 28 Mar 2024 10:20:51 +1300 Subject: [PATCH 1173/2101] Disable truthy yamllint rule (#6442) --- .github/workflows/ci-api-proto.yml | 1 - .github/workflows/ci-docker.yml | 2 +- .github/workflows/ci.yml | 1 - .github/workflows/lock.yml | 1 - .github/workflows/needs-docs.yml | 1 - .github/workflows/release.yml | 1 - .github/workflows/stale.yml | 1 - .github/workflows/sync-device-classes.yml | 1 - .github/workflows/yaml-lint.yml | 1 - .yamllint | 1 + tests/components/lightwaverf/test.esp8266.yaml | 2 +- 11 files changed, 3 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci-api-proto.yml b/.github/workflows/ci-api-proto.yml index 038ef3a587..0b2465d1aa 100644 --- a/.github/workflows/ci-api-proto.yml +++ b/.github/workflows/ci-api-proto.yml @@ -1,6 +1,5 @@ name: API Proto CI -# yamllint disable-line rule:truthy on: pull_request: paths: diff --git a/.github/workflows/ci-docker.yml b/.github/workflows/ci-docker.yml index 8a7b35fe33..f02efadf4d 100644 --- a/.github/workflows/ci-docker.yml +++ b/.github/workflows/ci-docker.yml @@ -2,7 +2,7 @@ name: CI for docker images # Only run when docker paths change -# yamllint disable-line rule:truthy + on: push: branches: [dev, beta, release] diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 871f2e72c8..b0ac840972 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,7 +1,6 @@ --- name: CI -# yamllint disable-line rule:truthy on: push: branches: [dev, beta, release] diff --git a/.github/workflows/lock.yml b/.github/workflows/lock.yml index e3d75f6d58..ee10f49f61 100644 --- a/.github/workflows/lock.yml +++ b/.github/workflows/lock.yml @@ -1,7 +1,6 @@ --- name: Lock -# yamllint disable-line rule:truthy on: schedule: - cron: "30 0 * * *" diff --git a/.github/workflows/needs-docs.yml b/.github/workflows/needs-docs.yml index 6a66e5769c..628b5cc5e3 100644 --- a/.github/workflows/needs-docs.yml +++ b/.github/workflows/needs-docs.yml @@ -1,6 +1,5 @@ name: Needs Docs -# yamllint disable-line rule:truthy on: pull_request: types: [labeled, unlabeled] diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6b567b5b6f..16469c904b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,7 +1,6 @@ --- name: Publish Release -# yamllint disable-line rule:truthy on: workflow_dispatch: release: diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 5f510ffe75..95f275e5a4 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -1,7 +1,6 @@ --- name: Stale -# yamllint disable-line rule:truthy on: schedule: - cron: "30 0 * * *" diff --git a/.github/workflows/sync-device-classes.yml b/.github/workflows/sync-device-classes.yml index 36fce2bbcf..3f8af4249a 100644 --- a/.github/workflows/sync-device-classes.yml +++ b/.github/workflows/sync-device-classes.yml @@ -1,7 +1,6 @@ --- name: Synchronise Device Classes from Home Assistant -# yamllint disable-line rule:truthy on: workflow_dispatch: schedule: diff --git a/.github/workflows/yaml-lint.yml b/.github/workflows/yaml-lint.yml index 3694436866..a3c1937e56 100644 --- a/.github/workflows/yaml-lint.yml +++ b/.github/workflows/yaml-lint.yml @@ -1,7 +1,6 @@ --- name: YAML lint -# yamllint disable-line rule:truthy on: push: branches: [dev, beta, release] diff --git a/.yamllint b/.yamllint index 9cd1482869..22e9237f61 100644 --- a/.yamllint +++ b/.yamllint @@ -16,3 +16,4 @@ rules: indent-sequences: true check-multi-line-strings: false line-length: disable + truthy: disable diff --git a/tests/components/lightwaverf/test.esp8266.yaml b/tests/components/lightwaverf/test.esp8266.yaml index 8f983a3cca..7ed8000271 100644 --- a/tests/components/lightwaverf/test.esp8266.yaml +++ b/tests/components/lightwaverf/test.esp8266.yaml @@ -8,6 +8,6 @@ button: id: light_off_ceiling_sofa on_press: lightwaverf.send_raw: - code: [0x04, 0x00, 0x00, 0x00, 0x0f, 0x03, 0x0d, 0x09, 0x08, 0x08] + code: [0x04, 0x00, 0x00, 0x00, 0x0f, 0x03, 0x0d, 0x09, 0x08, 0x08] name: "Sofa" repeat: 1 From 9194f7eb27f503e0f712d3e6407e48a16fc4ef99 Mon Sep 17 00:00:00 2001 From: Daniel Eisterhold Date: Wed, 27 Mar 2024 18:56:26 -0500 Subject: [PATCH 1174/2101] Add get_size method to QR Code header (#6430) --- esphome/components/qr_code/qr_code.cpp | 12 ++++++++++++ esphome/components/qr_code/qr_code.h | 2 ++ tests/components/qr_code/test.esp32-c3-idf.yaml | 7 +++++++ tests/components/qr_code/test.esp32-c3.yaml | 7 +++++++ tests/components/qr_code/test.esp32-idf.yaml | 7 +++++++ tests/components/qr_code/test.esp32.yaml | 7 +++++++ tests/components/qr_code/test.esp8266.yaml | 7 +++++++ tests/components/qr_code/test.rp2040.yaml | 7 +++++++ 8 files changed, 56 insertions(+) diff --git a/esphome/components/qr_code/qr_code.cpp b/esphome/components/qr_code/qr_code.cpp index aecf7628dc..b60e60a4b0 100644 --- a/esphome/components/qr_code/qr_code.cpp +++ b/esphome/components/qr_code/qr_code.cpp @@ -51,5 +51,17 @@ void QrCode::draw(display::Display *buff, uint16_t x_offset, uint16_t y_offset, } } } + +uint8_t QrCode::get_size() { + if (this->needs_update_) { + this->generate_qr_code(); + this->needs_update_ = false; + } + + uint8_t size = qrcodegen_getSize(this->qr_); + + return size; +} + } // namespace qr_code } // namespace esphome diff --git a/esphome/components/qr_code/qr_code.h b/esphome/components/qr_code/qr_code.h index d88e0aa09a..ab4c587b6d 100644 --- a/esphome/components/qr_code/qr_code.h +++ b/esphome/components/qr_code/qr_code.h @@ -24,6 +24,8 @@ class QrCode : public Component { void generate_qr_code(); + uint8_t get_size(); + protected: std::string value_; qrcodegen_Ecc ecc_; diff --git a/tests/components/qr_code/test.esp32-c3-idf.yaml b/tests/components/qr_code/test.esp32-c3-idf.yaml index 3e875c026c..63973b1aa2 100644 --- a/tests/components/qr_code/test.esp32-c3-idf.yaml +++ b/tests/components/qr_code/test.esp32-c3-idf.yaml @@ -11,6 +11,13 @@ display: cs_pin: 8 dc_pin: 9 reset_pin: 10 + lambda: |- + // Draw a QR code in the center of the screen + auto scale = 2; + auto size = id(homepage_qr).get_size() * scale; + auto x = (it.get_width() / 2) - (size / 2); + auto y = (it.get_height() / 2) - (size / 2); + it.qr_code(x, y, id(homepage_qr), Color(255,255,255), scale); qr_code: - id: homepage_qr diff --git a/tests/components/qr_code/test.esp32-c3.yaml b/tests/components/qr_code/test.esp32-c3.yaml index 3e875c026c..63973b1aa2 100644 --- a/tests/components/qr_code/test.esp32-c3.yaml +++ b/tests/components/qr_code/test.esp32-c3.yaml @@ -11,6 +11,13 @@ display: cs_pin: 8 dc_pin: 9 reset_pin: 10 + lambda: |- + // Draw a QR code in the center of the screen + auto scale = 2; + auto size = id(homepage_qr).get_size() * scale; + auto x = (it.get_width() / 2) - (size / 2); + auto y = (it.get_height() / 2) - (size / 2); + it.qr_code(x, y, id(homepage_qr), Color(255,255,255), scale); qr_code: - id: homepage_qr diff --git a/tests/components/qr_code/test.esp32-idf.yaml b/tests/components/qr_code/test.esp32-idf.yaml index b354a3f512..3e70d3258f 100644 --- a/tests/components/qr_code/test.esp32-idf.yaml +++ b/tests/components/qr_code/test.esp32-idf.yaml @@ -11,6 +11,13 @@ display: cs_pin: 12 dc_pin: 13 reset_pin: 21 + lambda: |- + // Draw a QR code in the center of the screen + auto scale = 2; + auto size = id(homepage_qr).get_size() * scale; + auto x = (it.get_width() / 2) - (size / 2); + auto y = (it.get_height() / 2) - (size / 2); + it.qr_code(x, y, id(homepage_qr), Color(255,255,255), scale); qr_code: - id: homepage_qr diff --git a/tests/components/qr_code/test.esp32.yaml b/tests/components/qr_code/test.esp32.yaml index b354a3f512..3e70d3258f 100644 --- a/tests/components/qr_code/test.esp32.yaml +++ b/tests/components/qr_code/test.esp32.yaml @@ -11,6 +11,13 @@ display: cs_pin: 12 dc_pin: 13 reset_pin: 21 + lambda: |- + // Draw a QR code in the center of the screen + auto scale = 2; + auto size = id(homepage_qr).get_size() * scale; + auto x = (it.get_width() / 2) - (size / 2); + auto y = (it.get_height() / 2) - (size / 2); + it.qr_code(x, y, id(homepage_qr), Color(255,255,255), scale); qr_code: - id: homepage_qr diff --git a/tests/components/qr_code/test.esp8266.yaml b/tests/components/qr_code/test.esp8266.yaml index dd0d75c472..3c304d7575 100644 --- a/tests/components/qr_code/test.esp8266.yaml +++ b/tests/components/qr_code/test.esp8266.yaml @@ -11,6 +11,13 @@ display: cs_pin: 5 dc_pin: 15 reset_pin: 16 + lambda: |- + // Draw a QR code in the center of the screen + auto scale = 2; + auto size = id(homepage_qr).get_size() * scale; + auto x = (it.get_width() / 2) - (size / 2); + auto y = (it.get_height() / 2) - (size / 2); + it.qr_code(x, y, id(homepage_qr), Color(255,255,255), scale); qr_code: - id: homepage_qr diff --git a/tests/components/qr_code/test.rp2040.yaml b/tests/components/qr_code/test.rp2040.yaml index b0e046d275..94cb772ba3 100644 --- a/tests/components/qr_code/test.rp2040.yaml +++ b/tests/components/qr_code/test.rp2040.yaml @@ -11,6 +11,13 @@ display: cs_pin: 20 dc_pin: 21 reset_pin: 22 + lambda: |- + // Draw a QR code in the center of the screen + auto scale = 2; + auto size = id(homepage_qr).get_size() * scale; + auto x = (it.get_width() / 2) - (size / 2); + auto y = (it.get_height() / 2) - (size / 2); + it.qr_code(x, y, id(homepage_qr), Color(255,255,255), scale); qr_code: - id: homepage_qr From 731dcc40bcbadb197f0f2a091c4d3790f28e5980 Mon Sep 17 00:00:00 2001 From: mrtoy-me <118446898+mrtoy-me@users.noreply.github.com> Date: Thu, 28 Mar 2024 12:19:27 +1000 Subject: [PATCH 1175/2101] Minor change to support sht85 sensor (#6415) --- CODEOWNERS | 1 + esphome/components/sht3xd/sensor.py | 6 ++++-- esphome/components/sht3xd/sht3xd.cpp | 21 ++++++++++++++++----- esphome/components/sht3xd/sht3xd.h | 1 + 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index 7c1f7ff70b..fafbaae6c6 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -309,6 +309,7 @@ esphome/components/sfa30/* @ghsensdev esphome/components/sgp40/* @SenexCrenshaw esphome/components/sgp4x/* @SenexCrenshaw @martgras esphome/components/shelly_dimmer/* @edge90 @rnauber +esphome/components/sht3xd/* @mrtoy-me esphome/components/sht4x/* @sjtrny esphome/components/shutdown/* @esphome/core @jsuanet esphome/components/sigma_delta_output/* @Cat-Ion diff --git a/esphome/components/sht3xd/sensor.py b/esphome/components/sht3xd/sensor.py index 80e15a1ab9..1286489b29 100644 --- a/esphome/components/sht3xd/sensor.py +++ b/esphome/components/sht3xd/sensor.py @@ -14,6 +14,8 @@ from esphome.const import ( CONF_HEATER_ENABLED = "heater_enabled" +CODEOWNERS = ["@mrtoy-me"] + DEPENDENCIES = ["i2c"] AUTO_LOAD = ["sensirion_common"] @@ -26,13 +28,13 @@ CONFIG_SCHEMA = ( cv.Schema( { cv.GenerateID(): cv.declare_id(SHT3XDComponent), - cv.Required(CONF_TEMPERATURE): sensor.sensor_schema( + 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.Required(CONF_HUMIDITY): sensor.sensor_schema( + cv.Optional(CONF_HUMIDITY): sensor.sensor_schema( unit_of_measurement=UNIT_PERCENT, accuracy_decimals=1, device_class=DEVICE_CLASS_HUMIDITY, diff --git a/esphome/components/sht3xd/sht3xd.cpp b/esphome/components/sht3xd/sht3xd.cpp index 25332165c0..888e954c6b 100644 --- a/esphome/components/sht3xd/sht3xd.cpp +++ b/esphome/components/sht3xd/sht3xd.cpp @@ -6,7 +6,11 @@ namespace sht3xd { static const char *const TAG = "sht3xd"; -static const uint16_t SHT3XD_COMMAND_READ_SERIAL_NUMBER = 0x3780; +// use read serial number register with clock stretching disabled as per other SHT3XD_COMMAND registers +// which provides support for SHT85 sensor +// SHT85 does not support clock stretching and uses same registers as SHT3xd with clock stretching disabled +static const uint16_t SHT3XD_COMMAND_READ_SERIAL_NUMBER = 0x3682; + static const uint16_t SHT3XD_COMMAND_READ_STATUS = 0xF32D; static const uint16_t SHT3XD_COMMAND_CLEAR_STATUS = 0x3041; static const uint16_t SHT3XD_COMMAND_HEATER_ENABLE = 0x306D; @@ -22,25 +26,32 @@ void SHT3XDComponent::setup() { this->mark_failed(); return; } + 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->mark_failed(); return; } - uint32_t serial_number = (uint32_t(raw_serial_number[0]) << 16) | uint32_t(raw_serial_number[1]); - ESP_LOGV(TAG, " Serial Number: 0x%08" PRIX32, serial_number); } + void SHT3XDComponent::dump_config() { ESP_LOGCONFIG(TAG, "SHT3xD:"); - LOG_I2C_DEVICE(this); if (this->is_failed()) { - ESP_LOGE(TAG, "Communication with SHT3xD failed!"); + ESP_LOGE(TAG, " Communication with SHT3xD failed!"); + return; } + ESP_LOGD(TAG, " Serial Number: 0x%08" PRIX32, this->serial_number_); + ESP_LOGD(TAG, " Heater Enabled: %s", this->heater_enabled_ ? "true" : "false"); + + LOG_I2C_DEVICE(this); LOG_UPDATE_INTERVAL(this); LOG_SENSOR(" ", "Temperature", this->temperature_sensor_); 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 4133bf7b93..d1a3360e69 100644 --- a/esphome/components/sht3xd/sht3xd.h +++ b/esphome/components/sht3xd/sht3xd.h @@ -25,6 +25,7 @@ class SHT3XDComponent : public PollingComponent, public sensirion_common::Sensir sensor::Sensor *temperature_sensor_{nullptr}; sensor::Sensor *humidity_sensor_{nullptr}; bool heater_enabled_{true}; + uint32_t serial_number_{0}; }; } // namespace sht3xd From dc0a7b1e205f5fa4e25fd1cadd507c27173636e1 Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Thu, 28 Mar 2024 12:51:01 -0700 Subject: [PATCH 1176/2101] Add missing ethernet types (#6444) --- esphome/components/ethernet/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/components/ethernet/__init__.py b/esphome/components/ethernet/__init__.py index de6040339a..ade94cb9f5 100644 --- a/esphome/components/ethernet/__init__.py +++ b/esphome/components/ethernet/__init__.py @@ -155,6 +155,8 @@ CONFIG_SCHEMA = cv.All( "DP83848": RMII_SCHEMA, "IP101": RMII_SCHEMA, "JL1101": RMII_SCHEMA, + "KSZ8081": RMII_SCHEMA, + "KSZ8081RNA": RMII_SCHEMA, "W5500": SPI_SCHEMA, }, upper=True, From f4e8a8972635bd99c72b47a69cde7c6a19cf61bb Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Mon, 1 Apr 2024 01:40:11 +0200 Subject: [PATCH 1177/2101] IPv6 string representation follows RFC5952 (#6449) --- esphome/components/network/ip_address.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/esphome/components/network/ip_address.h b/esphome/components/network/ip_address.h index b02c358a77..30a426e458 100644 --- a/esphome/components/network/ip_address.h +++ b/esphome/components/network/ip_address.h @@ -4,6 +4,7 @@ #include #include #include "esphome/core/macros.h" +#include "esphome/core/helpers.h" #if defined(USE_ESP_IDF) || defined(USE_LIBRETINY) || USE_ARDUINO_VERSION_CODE > VERSION_CODE(3, 0, 0) #include @@ -116,7 +117,7 @@ struct IPAddress { bool is_set() { return !ip_addr_isany(&ip_addr_); } bool is_ip4() { return IP_IS_V4(&ip_addr_); } bool is_ip6() { return IP_IS_V6(&ip_addr_); } - std::string str() const { return ipaddr_ntoa(&ip_addr_); } + std::string str() const { return str_lower_case(ipaddr_ntoa(&ip_addr_)); } 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 1207eda4ca19bce2db574f84d9f30f3068183856 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Apr 2024 12:41:43 +1300 Subject: [PATCH 1178/2101] Bump actions/setup-python from 5.0.0 to 5.1.0 (#6437) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-api-proto.yml | 2 +- .github/workflows/ci-docker.yml | 2 +- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 4 ++-- .github/workflows/sync-device-classes.yml | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-api-proto.yml b/.github/workflows/ci-api-proto.yml index 0b2465d1aa..40766ad728 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@v4.1.1 - name: Set up Python - uses: actions/setup-python@v5.0.0 + uses: actions/setup-python@v5.1.0 with: python-version: "3.11" diff --git a/.github/workflows/ci-docker.yml b/.github/workflows/ci-docker.yml index f02efadf4d..d8fd4efa0e 100644 --- a/.github/workflows/ci-docker.yml +++ b/.github/workflows/ci-docker.yml @@ -42,7 +42,7 @@ jobs: steps: - uses: actions/checkout@v4.1.1 - name: Set up Python - uses: actions/setup-python@v5.0.0 + uses: actions/setup-python@v5.1.0 with: python-version: "3.9" - name: Set up Docker Buildx diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b0ac840972..7df57acb08 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,7 +41,7 @@ jobs: run: echo key="${{ hashFiles('requirements.txt', 'requirements_optional.txt', 'requirements_test.txt') }}" >> $GITHUB_OUTPUT - name: Set up Python ${{ env.DEFAULT_PYTHON }} id: python - uses: actions/setup-python@v5.0.0 + uses: actions/setup-python@v5.1.0 with: python-version: ${{ env.DEFAULT_PYTHON }} - name: Restore Python virtual environment diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 16469c904b..cb7defc2b0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -44,7 +44,7 @@ jobs: steps: - uses: actions/checkout@v4.1.1 - name: Set up Python - uses: actions/setup-python@v5.0.0 + uses: actions/setup-python@v5.1.0 with: python-version: "3.x" - name: Set up python environment @@ -79,7 +79,7 @@ jobs: steps: - uses: actions/checkout@v4.1.1 - name: Set up Python - uses: actions/setup-python@v5.0.0 + uses: actions/setup-python@v5.1.0 with: python-version: "3.9" diff --git a/.github/workflows/sync-device-classes.yml b/.github/workflows/sync-device-classes.yml index 3f8af4249a..c12f1f31b5 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@v5.0.0 + uses: actions/setup-python@v5.1.0 with: python-version: 3.11 From 3a49e91ce03201c13133dee1a2bf0f474805682d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Apr 2024 12:42:02 +1300 Subject: [PATCH 1179/2101] Bump actions/setup-python from 5.0.0 to 5.1.0 in /.github/actions/restore-python (#6438) 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 aa4f7ba887..4ad9e2eaed 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@v5.0.0 + uses: actions/setup-python@v5.1.0 with: python-version: ${{ inputs.python-version }} - name: Restore Python virtual environment From 1be5d14fd946b708bb1016bc26158bdc2e20d1f2 Mon Sep 17 00:00:00 2001 From: NewoPL <27411874+NewoPL@users.noreply.github.com> Date: Mon, 1 Apr 2024 01:43:49 +0200 Subject: [PATCH 1180/2101] fix: changing the content source when playing is paused blocks the player (#6454) --- .../i2s_audio/media_player/i2s_audio_media_player.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/i2s_audio/media_player/i2s_audio_media_player.cpp b/esphome/components/i2s_audio/media_player/i2s_audio_media_player.cpp index 9e2e3f136a..6e07983920 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 @@ -12,12 +12,12 @@ static const char *const TAG = "audio"; void I2SAudioMediaPlayer::control(const media_player::MediaPlayerCall &call) { if (call.get_media_url().has_value()) { this->current_url_ = call.get_media_url(); - - if (this->state == media_player::MEDIA_PLAYER_STATE_PLAYING && this->audio_ != nullptr) { + 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->state = media_player::MEDIA_PLAYER_STATE_PLAYING; } else { this->start(); } From 63db07a156756b30aa2fdc9b35e14f9d4c0ed16f Mon Sep 17 00:00:00 2001 From: tronikos Date: Mon, 1 Apr 2024 13:21:53 -0700 Subject: [PATCH 1181/2101] Optimize QMC5883L: Read registers only for enabled sensors (#6458) --- esphome/components/qmc5883l/qmc5883l.cpp | 45 +++++++++++++++++------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/esphome/components/qmc5883l/qmc5883l.cpp b/esphome/components/qmc5883l/qmc5883l.cpp index f03b6af191..4052b395f9 100644 --- a/esphome/components/qmc5883l/qmc5883l.cpp +++ b/esphome/components/qmc5883l/qmc5883l.cpp @@ -76,15 +76,8 @@ void QMC5883LComponent::dump_config() { float QMC5883LComponent::get_setup_priority() const { return setup_priority::DATA; } void QMC5883LComponent::update() { uint8_t status = false; - this->read_byte(QMC5883L_REGISTER_STATUS, &status); - - uint16_t raw_x, raw_y, raw_z; - if (!this->read_byte_16_(QMC5883L_REGISTER_DATA_X_LSB, &raw_x) || - !this->read_byte_16_(QMC5883L_REGISTER_DATA_Y_LSB, &raw_y) || - !this->read_byte_16_(QMC5883L_REGISTER_DATA_Z_LSB, &raw_z)) { - this->status_set_warning(); - return; - } + if (ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_DEBUG) + this->read_byte(QMC5883L_REGISTER_STATUS, &status); float mg_per_bit; switch (this->range_) { @@ -99,11 +92,37 @@ void QMC5883LComponent::update() { } // in µT - const float x = int16_t(raw_x) * mg_per_bit * 0.1f; - const float y = int16_t(raw_y) * mg_per_bit * 0.1f; - const float z = int16_t(raw_z) * mg_per_bit * 0.1f; + float x = NAN, y = NAN, z = NAN; + if (this->x_sensor_ != nullptr || this->heading_sensor_ != nullptr) { + uint16_t raw_x; + if (!this->read_byte_16_(QMC5883L_REGISTER_DATA_X_LSB, &raw_x)) { + this->status_set_warning(); + return; + } + x = int16_t(raw_x) * mg_per_bit * 0.1f; + } + if (this->y_sensor_ != nullptr || this->heading_sensor_ != nullptr) { + uint16_t raw_y; + if (!this->read_byte_16_(QMC5883L_REGISTER_DATA_Y_LSB, &raw_y)) { + this->status_set_warning(); + return; + } + y = int16_t(raw_y) * mg_per_bit * 0.1f; + } + if (this->z_sensor_ != nullptr) { + uint16_t raw_z; + if (!this->read_byte_16_(QMC5883L_REGISTER_DATA_Z_LSB, &raw_z)) { + this->status_set_warning(); + return; + } + z = int16_t(raw_z) * mg_per_bit * 0.1f; + } + + float heading = NAN; + if (this->heading_sensor_ != nullptr) { + heading = atan2f(0.0f - x, y) * 180.0f / M_PI; + } - float heading = atan2f(0.0f - x, y) * 180.0f / M_PI; ESP_LOGD(TAG, "Got x=%0.02fµT y=%0.02fµT z=%0.02fµT heading=%0.01f° status=%u", x, y, z, heading, status); if (this->x_sensor_ != nullptr) From 6deb253fa68879d8b03b05be97644d05cf572fd3 Mon Sep 17 00:00:00 2001 From: Leland Sindt Date: Mon, 1 Apr 2024 21:32:40 -0500 Subject: [PATCH 1182/2101] minor refactor to allow commit hash as ref value. (#6446) --- esphome/git.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/esphome/git.py b/esphome/git.py index 4f0911233e..e41777f425 100644 --- a/esphome/git.py +++ b/esphome/git.py @@ -59,17 +59,14 @@ def clone_or_update( ) repo_dir = _compute_destination_path(key, domain) - fetch_pr_branch = ref is not None and ref.startswith("pull/") if not repo_dir.is_dir(): _LOGGER.info("Cloning %s", key) _LOGGER.debug("Location: %s", repo_dir) cmd = ["git", "clone", "--depth=1"] - if ref is not None and not fetch_pr_branch: - cmd += ["--branch", ref] cmd += ["--", url, str(repo_dir)] run_git_command(cmd) - if fetch_pr_branch: + 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) From e32b8296702539e2d5cfafa4dbefae280a1abc06 Mon Sep 17 00:00:00 2001 From: mrtoy-me <118446898+mrtoy-me@users.noreply.github.com> Date: Tue, 2 Apr 2024 12:35:59 +1000 Subject: [PATCH 1183/2101] TMP117 fix polling period config (#6452) --- esphome/components/tmp117/sensor.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/esphome/components/tmp117/sensor.py b/esphome/components/tmp117/sensor.py index fb97258bc1..82d099cf12 100644 --- a/esphome/components/tmp117/sensor.py +++ b/esphome/components/tmp117/sensor.py @@ -30,37 +30,37 @@ CONFIG_SCHEMA = cv.All( def determine_config_register(polling_period): - if polling_period >= 16.0: + if polling_period >= 16000: # 64 averaged conversions, max conversion time # 0000 00 111 11 00000 # 0000 0011 1110 0000 return 0x03E0 - if polling_period >= 8.0: + if polling_period >= 8000: # 64 averaged conversions, high conversion time # 0000 00 110 11 00000 # 0000 0011 0110 0000 return 0x0360 - if polling_period >= 4.0: + if polling_period >= 4000: # 64 averaged conversions, mid conversion time # 0000 00 101 11 00000 # 0000 0010 1110 0000 return 0x02E0 - if polling_period >= 1.0: + if polling_period >= 1000: # 64 averaged conversions, min conversion time # 0000 00 000 11 00000 # 0000 0000 0110 0000 return 0x0060 - if polling_period >= 0.5: + if polling_period >= 500: # 32 averaged conversions, min conversion time # 0000 00 000 10 00000 # 0000 0000 0100 0000 return 0x0040 - if polling_period >= 0.25: + if polling_period >= 250: # 8 averaged conversions, mid conversion time # 0000 00 010 01 00000 # 0000 0001 0010 0000 return 0x0120 - if polling_period >= 0.125: + if polling_period >= 125: # 8 averaged conversions, min conversion time # 0000 00 000 01 00000 # 0000 0000 0010 0000 @@ -76,5 +76,5 @@ async def to_code(config): await cg.register_component(var, config) await i2c.register_i2c_device(var, config) - update_period = config[CONF_UPDATE_INTERVAL].total_seconds + update_period = config[CONF_UPDATE_INTERVAL].total_milliseconds cg.add(var.set_config(determine_config_register(update_period))) From ec32501d405a462bb8120d94ae504265d7832f15 Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Tue, 2 Apr 2024 05:00:47 +0200 Subject: [PATCH 1184/2101] Bump Arduino Pico Framework to 3.7.2 and Platform to 1.12.0 (#6386) --- esphome/components/rp2040/__init__.py | 4 ++-- platformio.ini | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/esphome/components/rp2040/__init__.py b/esphome/components/rp2040/__init__.py index d027f48244..b262a068fb 100644 --- a/esphome/components/rp2040/__init__.py +++ b/esphome/components/rp2040/__init__.py @@ -74,12 +74,12 @@ def _format_framework_arduino_version(ver: cv.Version) -> str: # 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, 6, 0) +RECOMMENDED_ARDUINO_FRAMEWORK_VERSION = cv.Version(3, 7, 2) # The platformio/raspberrypi version to use for arduino frameworks # - https://github.com/platformio/platform-raspberrypi/releases # - https://api.registry.platformio.org/v3/packages/platformio/platform/raspberrypi -ARDUINO_PLATFORM_VERSION = cv.Version(1, 10, 0) +ARDUINO_PLATFORM_VERSION = cv.Version(1, 12, 0) def _arduino_check_versions(value): diff --git a/platformio.ini b/platformio.ini index db5fb3a544..5fedd14086 100644 --- a/platformio.ini +++ b/platformio.ini @@ -154,13 +154,12 @@ extra_scripts = post:esphome/components/esp32/post_build.py.script ; These are common settings for the RP2040 using Arduino. [common:rp2040-arduino] extends = common:arduino -board_build.core = earlephilhower board_build.filesystem_size = 0.5m platform = https://github.com/maxgerhardt/platform-raspberrypi.git 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.6.0/rp2040-3.6.0.zip + earlephilhower/framework-arduinopico@https://github.com/earlephilhower/arduino-pico/releases/download/3.7.2/rp2040-3.7.2.zip framework = arduino lib_deps = From 4fcb26d69dd4b245023df25d63946e5a974a391c Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 3 Apr 2024 07:33:18 +1300 Subject: [PATCH 1185/2101] Display menu: Allow "left" key to exit current menu if not editing (#6460) --- esphome/components/display_menu_base/display_menu_base.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/components/display_menu_base/display_menu_base.cpp b/esphome/components/display_menu_base/display_menu_base.cpp index 0bfee338ca..5502623607 100644 --- a/esphome/components/display_menu_base/display_menu_base.cpp +++ b/esphome/components/display_menu_base/display_menu_base.cpp @@ -60,6 +60,8 @@ void DisplayMenuComponent::left() { if (this->editing_) { this->finish_editing_(); changed = true; + } else { + changed = this->leave_menu_(); } break; case MENU_MODE_JOYSTICK: From 02632f0cad8a6026225765e9da48ffb5ff353a26 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 3 Apr 2024 15:16:38 +1300 Subject: [PATCH 1186/2101] Fix NOLINT on inclusive-language check (#6464) --- esphome/components/pmsx003/pmsx003.h | 9 +++++---- script/ci-custom.py | 26 +++++++++++++++++++------- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/esphome/components/pmsx003/pmsx003.h b/esphome/components/pmsx003/pmsx003.h index eb33f66909..cb5c16aecf 100644 --- a/esphome/components/pmsx003/pmsx003.h +++ b/esphome/components/pmsx003/pmsx003.h @@ -1,16 +1,17 @@ #pragma once -#include "esphome/core/component.h" #include "esphome/components/sensor/sensor.h" #include "esphome/components/uart/uart.h" +#include "esphome/core/component.h" namespace esphome { namespace pmsx003 { // known command bytes -#define PMS_CMD_AUTO_MANUAL 0xE1 // data=0: perform measurement manually, data=1: perform measurement automatically -#define PMS_CMD_TRIG_MANUAL 0xE2 // trigger a manual measurement -#define PMS_CMD_ON_STANDBY 0xE4 // data=0: go to standby mode, data=1: go to normal mode +static const uint8_t PMS_CMD_AUTO_MANUAL = + 0xE1; // data=0: perform measurement manually, data=1: perform measurement automatically +static const uint8_t PMS_CMD_TRIG_MANUAL = 0xE2; // trigger a manual measurement +static const uint8_t PMS_CMD_ON_STANDBY = 0xE4; // data=0: go to standby mode, data=1: go to normal mode static const uint16_t PMS_STABILISING_MS = 30000; // time taken for the sensor to become stable after power on diff --git a/script/ci-custom.py b/script/ci-custom.py index 422fdf52f0..1ad44dc930 100755 --- a/script/ci-custom.py +++ b/script/ci-custom.py @@ -57,6 +57,7 @@ file_types = ( "", ) cpp_include = ("*.h", "*.c", "*.cpp", "*.tcc") +py_include = ("*.py",) ignore_types = (".ico", ".png", ".woff", ".woff2", "") LINT_FILE_CHECKS = [] @@ -265,7 +266,8 @@ def lint_end_newline(fname, content): return None -CPP_RE_EOL = r"\s*?(?://.*?)?$" +CPP_RE_EOL = r".*?(?://.*?)?$" +PY_RE_EOL = r".*?(?:#.*?)?$" def highlight(s): @@ -273,7 +275,7 @@ def highlight(s): @lint_re_check( - r"^#define\s+([a-zA-Z0-9_]+)\s+([0-9bx]+)" + CPP_RE_EOL, + r"^#define\s+([a-zA-Z0-9_]+)\s+(0b[10]+|0x[0-9a-fA-F]+|\d+)\s*?(?:\/\/.*?)?$", include=cpp_include, exclude=[ "esphome/core/log.h", @@ -574,11 +576,6 @@ def lint_pragma_once(fname, content): return None -@lint_re_check( - r"(whitelist|blacklist|slave)", - exclude=["script/ci-custom.py"], - flags=re.IGNORECASE | re.MULTILINE, -) def lint_inclusive_language(fname, match): # From https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=49decddd39e5f6132ccd7d9fdc3d7c470b0061bb return ( @@ -596,6 +593,21 @@ def lint_inclusive_language(fname, match): ) +lint_re_check( + r"(whitelist|blacklist|slave)" + PY_RE_EOL, + include=py_include, + exclude=["script/ci-custom.py"], + flags=re.IGNORECASE | re.MULTILINE, +)(lint_inclusive_language) + + +lint_re_check( + r"(whitelist|blacklist|slave)" + CPP_RE_EOL, + include=cpp_include, + flags=re.IGNORECASE | re.MULTILINE, +)(lint_inclusive_language) + + @lint_re_check(r"[\t\r\f\v ]+$") def lint_trailing_whitespace(fname, match): return "Trailing whitespace detected" From be8d188a558cc0cf239b11133789f9f42c69c57b Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 3 Apr 2024 15:16:59 +1300 Subject: [PATCH 1187/2101] Add yamllint to dev requirements (#6466) --- requirements_dev.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements_dev.txt b/requirements_dev.txt index 6b6319d0a0..6bfa015c6f 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -1,3 +1,4 @@ # Useful stuff when working in a development environment clang-format==13.0.1 clang-tidy==14.0.6 +yamllint==1.35.1 From 96f4c70b6b256fb43420f9f5431f3d5bc6df7c67 Mon Sep 17 00:00:00 2001 From: tronikos Date: Tue, 2 Apr 2024 19:57:05 -0700 Subject: [PATCH 1188/2101] Add temperature for QMC5883L (#6456) --- esphome/components/qmc5883l/qmc5883l.cpp | 16 +++++++++++++++- esphome/components/qmc5883l/qmc5883l.h | 2 ++ esphome/components/qmc5883l/sensor.py | 13 +++++++++++++ tests/components/qmc5883l/test.esp32-c3-idf.yaml | 2 ++ tests/components/qmc5883l/test.esp32-c3.yaml | 2 ++ tests/components/qmc5883l/test.esp32-idf.yaml | 2 ++ tests/components/qmc5883l/test.esp32.yaml | 2 ++ tests/components/qmc5883l/test.esp8266.yaml | 2 ++ tests/components/qmc5883l/test.rp2040.yaml | 2 ++ 9 files changed, 42 insertions(+), 1 deletion(-) diff --git a/esphome/components/qmc5883l/qmc5883l.cpp b/esphome/components/qmc5883l/qmc5883l.cpp index 4052b395f9..4946ad1b77 100644 --- a/esphome/components/qmc5883l/qmc5883l.cpp +++ b/esphome/components/qmc5883l/qmc5883l.cpp @@ -72,6 +72,7 @@ void QMC5883LComponent::dump_config() { LOG_SENSOR(" ", "Y Axis", this->y_sensor_); LOG_SENSOR(" ", "Z Axis", this->z_sensor_); LOG_SENSOR(" ", "Heading", this->heading_sensor_); + LOG_SENSOR(" ", "Temperature", this->temperature_sensor_); } float QMC5883LComponent::get_setup_priority() const { return setup_priority::DATA; } void QMC5883LComponent::update() { @@ -123,7 +124,18 @@ void QMC5883LComponent::update() { heading = atan2f(0.0f - x, y) * 180.0f / M_PI; } - ESP_LOGD(TAG, "Got x=%0.02fµT y=%0.02fµT z=%0.02fµT heading=%0.01f° status=%u", x, y, z, heading, status); + float temp = NAN; + if (this->temperature_sensor_ != nullptr) { + uint16_t raw_temp; + if (!this->read_byte_16_(QMC5883L_REGISTER_TEMPERATURE_LSB, &raw_temp)) { + this->status_set_warning(); + return; + } + temp = int16_t(raw_temp) * 0.01f; + } + + ESP_LOGD(TAG, "Got x=%0.02fµT y=%0.02fµT z=%0.02fµT heading=%0.01f° temperature=%0.01f°C status=%u", x, y, z, heading, + temp, status); if (this->x_sensor_ != nullptr) this->x_sensor_->publish_state(x); @@ -133,6 +145,8 @@ void QMC5883LComponent::update() { this->z_sensor_->publish_state(z); if (this->heading_sensor_ != nullptr) this->heading_sensor_->publish_state(heading); + if (this->temperature_sensor_ != nullptr) + this->temperature_sensor_->publish_state(temp); } bool QMC5883LComponent::read_byte_16_(uint8_t a_register, uint16_t *data) { diff --git a/esphome/components/qmc5883l/qmc5883l.h b/esphome/components/qmc5883l/qmc5883l.h index 15ef435ce5..b0c0af40d2 100644 --- a/esphome/components/qmc5883l/qmc5883l.h +++ b/esphome/components/qmc5883l/qmc5883l.h @@ -40,6 +40,7 @@ class QMC5883LComponent : public PollingComponent, public i2c::I2CDevice { void set_y_sensor(sensor::Sensor *y_sensor) { y_sensor_ = y_sensor; } void set_z_sensor(sensor::Sensor *z_sensor) { z_sensor_ = z_sensor; } void set_heading_sensor(sensor::Sensor *heading_sensor) { heading_sensor_ = heading_sensor; } + void set_temperature_sensor(sensor::Sensor *temperature_sensor) { temperature_sensor_ = temperature_sensor; } protected: QMC5883LDatarate datarate_{QMC5883L_DATARATE_10_HZ}; @@ -49,6 +50,7 @@ class QMC5883LComponent : public PollingComponent, public i2c::I2CDevice { sensor::Sensor *y_sensor_{nullptr}; sensor::Sensor *z_sensor_{nullptr}; sensor::Sensor *heading_sensor_{nullptr}; + sensor::Sensor *temperature_sensor_{nullptr}; enum ErrorCode { NONE = 0, COMMUNICATION_FAILED, diff --git a/esphome/components/qmc5883l/sensor.py b/esphome/components/qmc5883l/sensor.py index b819fecfe1..24e1019507 100644 --- a/esphome/components/qmc5883l/sensor.py +++ b/esphome/components/qmc5883l/sensor.py @@ -6,12 +6,15 @@ from esphome.const import ( CONF_FIELD_STRENGTH_X, CONF_FIELD_STRENGTH_Y, CONF_FIELD_STRENGTH_Z, + CONF_TEMPERATURE, CONF_ID, CONF_OVERSAMPLING, CONF_RANGE, + DEVICE_CLASS_TEMPERATURE, ICON_MAGNET, STATE_CLASS_MEASUREMENT, UNIT_MICROTESLA, + UNIT_CELSIUS, UNIT_DEGREES, ICON_SCREEN_ROTATION, CONF_UPDATE_INTERVAL, @@ -79,6 +82,12 @@ heading_schema = sensor.sensor_schema( icon=ICON_SCREEN_ROTATION, accuracy_decimals=1, ) +temperature_schema = sensor.sensor_schema( + unit_of_measurement=UNIT_CELSIUS, + accuracy_decimals=1, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, +) CONFIG_SCHEMA = ( cv.Schema( @@ -95,6 +104,7 @@ CONFIG_SCHEMA = ( cv.Optional(CONF_FIELD_STRENGTH_Y): field_strength_schema, cv.Optional(CONF_FIELD_STRENGTH_Z): field_strength_schema, cv.Optional(CONF_HEADING): heading_schema, + cv.Optional(CONF_TEMPERATURE): temperature_schema, } ) .extend(cv.polling_component_schema("60s")) @@ -131,3 +141,6 @@ async def to_code(config): if CONF_HEADING in config: sens = await sensor.new_sensor(config[CONF_HEADING]) cg.add(var.set_heading_sensor(sens)) + if CONF_TEMPERATURE in config: + sens = await sensor.new_sensor(config[CONF_TEMPERATURE]) + cg.add(var.set_temperature_sensor(sens)) diff --git a/tests/components/qmc5883l/test.esp32-c3-idf.yaml b/tests/components/qmc5883l/test.esp32-c3-idf.yaml index c638f7e5be..841bbd5d1e 100644 --- a/tests/components/qmc5883l/test.esp32-c3-idf.yaml +++ b/tests/components/qmc5883l/test.esp32-c3-idf.yaml @@ -14,6 +14,8 @@ sensor: name: QMC5883L Field Strength Z heading: name: QMC5883L Heading + temperature: + name: QMC5883L Temperature range: 800uT oversampling: 256x update_interval: 15s diff --git a/tests/components/qmc5883l/test.esp32-c3.yaml b/tests/components/qmc5883l/test.esp32-c3.yaml index c638f7e5be..841bbd5d1e 100644 --- a/tests/components/qmc5883l/test.esp32-c3.yaml +++ b/tests/components/qmc5883l/test.esp32-c3.yaml @@ -14,6 +14,8 @@ sensor: name: QMC5883L Field Strength Z heading: name: QMC5883L Heading + temperature: + name: QMC5883L Temperature range: 800uT oversampling: 256x update_interval: 15s diff --git a/tests/components/qmc5883l/test.esp32-idf.yaml b/tests/components/qmc5883l/test.esp32-idf.yaml index 1aafa86cfa..9acd391497 100644 --- a/tests/components/qmc5883l/test.esp32-idf.yaml +++ b/tests/components/qmc5883l/test.esp32-idf.yaml @@ -14,6 +14,8 @@ sensor: name: QMC5883L Field Strength Z heading: name: QMC5883L Heading + temperature: + name: QMC5883L Temperature range: 800uT oversampling: 256x update_interval: 15s diff --git a/tests/components/qmc5883l/test.esp32.yaml b/tests/components/qmc5883l/test.esp32.yaml index 1aafa86cfa..9acd391497 100644 --- a/tests/components/qmc5883l/test.esp32.yaml +++ b/tests/components/qmc5883l/test.esp32.yaml @@ -14,6 +14,8 @@ sensor: name: QMC5883L Field Strength Z heading: name: QMC5883L Heading + temperature: + name: QMC5883L Temperature range: 800uT oversampling: 256x update_interval: 15s diff --git a/tests/components/qmc5883l/test.esp8266.yaml b/tests/components/qmc5883l/test.esp8266.yaml index c638f7e5be..841bbd5d1e 100644 --- a/tests/components/qmc5883l/test.esp8266.yaml +++ b/tests/components/qmc5883l/test.esp8266.yaml @@ -14,6 +14,8 @@ sensor: name: QMC5883L Field Strength Z heading: name: QMC5883L Heading + temperature: + name: QMC5883L Temperature range: 800uT oversampling: 256x update_interval: 15s diff --git a/tests/components/qmc5883l/test.rp2040.yaml b/tests/components/qmc5883l/test.rp2040.yaml index c638f7e5be..841bbd5d1e 100644 --- a/tests/components/qmc5883l/test.rp2040.yaml +++ b/tests/components/qmc5883l/test.rp2040.yaml @@ -14,6 +14,8 @@ sensor: name: QMC5883L Field Strength Z heading: name: QMC5883L Heading + temperature: + name: QMC5883L Temperature range: 800uT oversampling: 256x update_interval: 15s From 5cc3d60feef8e674342f5d6c97f76f1b6a7305e2 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 4 Apr 2024 11:13:59 +1300 Subject: [PATCH 1189/2101] web_server: Return early if no clients connected (#6467) --- .../components/web_server/list_entities.cpp | 30 +++++++++++++++++ esphome/components/web_server/web_server.cpp | 32 ++++++++++++++++++- .../web_server_idf/web_server_idf.h | 6 ++-- 3 files changed, 65 insertions(+), 3 deletions(-) diff --git a/esphome/components/web_server/list_entities.cpp b/esphome/components/web_server/list_entities.cpp index 197af1eb14..2252f55008 100644 --- a/esphome/components/web_server/list_entities.cpp +++ b/esphome/components/web_server/list_entities.cpp @@ -12,6 +12,8 @@ ListEntitiesIterator::ListEntitiesIterator(WebServer *web_server) : web_server_( #ifdef USE_BINARY_SENSOR bool ListEntitiesIterator::on_binary_sensor(binary_sensor::BinarySensor *binary_sensor) { + if (this->web_server_->events_.count() == 0) + return true; this->web_server_->events_.send( this->web_server_->binary_sensor_json(binary_sensor, binary_sensor->state, DETAIL_ALL).c_str(), "state"); return true; @@ -19,30 +21,40 @@ bool ListEntitiesIterator::on_binary_sensor(binary_sensor::BinarySensor *binary_ #endif #ifdef USE_COVER bool ListEntitiesIterator::on_cover(cover::Cover *cover) { + if (this->web_server_->events_.count() == 0) + return true; this->web_server_->events_.send(this->web_server_->cover_json(cover, DETAIL_ALL).c_str(), "state"); return true; } #endif #ifdef USE_FAN bool ListEntitiesIterator::on_fan(fan::Fan *fan) { + if (this->web_server_->events_.count() == 0) + return true; this->web_server_->events_.send(this->web_server_->fan_json(fan, DETAIL_ALL).c_str(), "state"); return true; } #endif #ifdef USE_LIGHT bool ListEntitiesIterator::on_light(light::LightState *light) { + if (this->web_server_->events_.count() == 0) + return true; this->web_server_->events_.send(this->web_server_->light_json(light, DETAIL_ALL).c_str(), "state"); return true; } #endif #ifdef USE_SENSOR bool ListEntitiesIterator::on_sensor(sensor::Sensor *sensor) { + if (this->web_server_->events_.count() == 0) + return true; this->web_server_->events_.send(this->web_server_->sensor_json(sensor, sensor->state, DETAIL_ALL).c_str(), "state"); return true; } #endif #ifdef USE_SWITCH bool ListEntitiesIterator::on_switch(switch_::Switch *a_switch) { + if (this->web_server_->events_.count() == 0) + return true; this->web_server_->events_.send(this->web_server_->switch_json(a_switch, a_switch->state, DETAIL_ALL).c_str(), "state"); return true; @@ -50,12 +62,16 @@ bool ListEntitiesIterator::on_switch(switch_::Switch *a_switch) { #endif #ifdef USE_BUTTON bool ListEntitiesIterator::on_button(button::Button *button) { + if (this->web_server_->events_.count() == 0) + return true; this->web_server_->events_.send(this->web_server_->button_json(button, DETAIL_ALL).c_str(), "state"); return true; } #endif #ifdef USE_TEXT_SENSOR bool ListEntitiesIterator::on_text_sensor(text_sensor::TextSensor *text_sensor) { + if (this->web_server_->events_.count() == 0) + return true; this->web_server_->events_.send( this->web_server_->text_sensor_json(text_sensor, text_sensor->state, DETAIL_ALL).c_str(), "state"); return true; @@ -63,6 +79,8 @@ bool ListEntitiesIterator::on_text_sensor(text_sensor::TextSensor *text_sensor) #endif #ifdef USE_LOCK bool ListEntitiesIterator::on_lock(lock::Lock *a_lock) { + if (this->web_server_->events_.count() == 0) + return true; this->web_server_->events_.send(this->web_server_->lock_json(a_lock, a_lock->state, DETAIL_ALL).c_str(), "state"); return true; } @@ -70,6 +88,8 @@ bool ListEntitiesIterator::on_lock(lock::Lock *a_lock) { #ifdef USE_CLIMATE bool ListEntitiesIterator::on_climate(climate::Climate *climate) { + if (this->web_server_->events_.count() == 0) + return true; this->web_server_->events_.send(this->web_server_->climate_json(climate, DETAIL_ALL).c_str(), "state"); return true; } @@ -77,6 +97,8 @@ bool ListEntitiesIterator::on_climate(climate::Climate *climate) { #ifdef USE_NUMBER bool ListEntitiesIterator::on_number(number::Number *number) { + if (this->web_server_->events_.count() == 0) + return true; this->web_server_->events_.send(this->web_server_->number_json(number, number->state, DETAIL_ALL).c_str(), "state"); return true; } @@ -84,6 +106,8 @@ bool ListEntitiesIterator::on_number(number::Number *number) { #ifdef USE_DATETIME_DATE bool ListEntitiesIterator::on_date(datetime::DateEntity *date) { + if (this->web_server_->events_.count() == 0) + return true; this->web_server_->events_.send(this->web_server_->date_json(date, DETAIL_ALL).c_str(), "state"); return true; } @@ -91,6 +115,8 @@ bool ListEntitiesIterator::on_date(datetime::DateEntity *date) { #ifdef USE_TEXT bool ListEntitiesIterator::on_text(text::Text *text) { + if (this->web_server_->events_.count() == 0) + return true; this->web_server_->events_.send(this->web_server_->text_json(text, text->state, DETAIL_ALL).c_str(), "state"); return true; } @@ -98,6 +124,8 @@ bool ListEntitiesIterator::on_text(text::Text *text) { #ifdef USE_SELECT bool ListEntitiesIterator::on_select(select::Select *select) { + if (this->web_server_->events_.count() == 0) + return true; this->web_server_->events_.send(this->web_server_->select_json(select, select->state, DETAIL_ALL).c_str(), "state"); return true; } @@ -105,6 +133,8 @@ bool ListEntitiesIterator::on_select(select::Select *select) { #ifdef USE_ALARM_CONTROL_PANEL bool ListEntitiesIterator::on_alarm_control_panel(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel) { + if (this->web_server_->events_.count() == 0) + return true; this->web_server_->events_.send( this->web_server_->alarm_control_panel_json(a_alarm_control_panel, a_alarm_control_panel->get_state(), DETAIL_ALL) .c_str(), diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index f065dc6684..4e6797ae1f 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -416,6 +416,8 @@ void WebServer::handle_js_request(AsyncWebServerRequest *request) { #ifdef USE_SENSOR void WebServer::on_sensor_update(sensor::Sensor *obj, float state) { + if (this->events_.count() == 0) + return; this->events_.send(this->sensor_json(obj, state, DETAIL_STATE).c_str(), "state"); } void WebServer::handle_sensor_request(AsyncWebServerRequest *request, const UrlMatch &match) { @@ -449,6 +451,8 @@ std::string WebServer::sensor_json(sensor::Sensor *obj, float value, JsonDetail #ifdef USE_TEXT_SENSOR void WebServer::on_text_sensor_update(text_sensor::TextSensor *obj, const std::string &state) { + if (this->events_.count() == 0) + return; this->events_.send(this->text_sensor_json(obj, state, DETAIL_STATE).c_str(), "state"); } void WebServer::handle_text_sensor_request(AsyncWebServerRequest *request, const UrlMatch &match) { @@ -471,6 +475,8 @@ std::string WebServer::text_sensor_json(text_sensor::TextSensor *obj, const std: #ifdef USE_SWITCH void WebServer::on_switch_update(switch_::Switch *obj, bool state) { + if (this->events_.count() == 0) + return; this->events_.send(this->switch_json(obj, state, DETAIL_STATE).c_str(), "state"); } std::string WebServer::switch_json(switch_::Switch *obj, bool value, JsonDetail start_config) { @@ -532,6 +538,8 @@ void WebServer::handle_button_request(AsyncWebServerRequest *request, const UrlM #ifdef USE_BINARY_SENSOR void WebServer::on_binary_sensor_update(binary_sensor::BinarySensor *obj, bool state) { + if (this->events_.count() == 0) + return; this->events_.send(this->binary_sensor_json(obj, state, DETAIL_STATE).c_str(), "state"); } std::string WebServer::binary_sensor_json(binary_sensor::BinarySensor *obj, bool value, JsonDetail start_config) { @@ -553,7 +561,11 @@ void WebServer::handle_binary_sensor_request(AsyncWebServerRequest *request, con #endif #ifdef USE_FAN -void WebServer::on_fan_update(fan::Fan *obj) { this->events_.send(this->fan_json(obj, DETAIL_STATE).c_str(), "state"); } +void WebServer::on_fan_update(fan::Fan *obj) { + if (this->events_.count() == 0) + return; + this->events_.send(this->fan_json(obj, DETAIL_STATE).c_str(), "state"); +} std::string WebServer::fan_json(fan::Fan *obj, JsonDetail start_config) { return json::build_json([obj, start_config](JsonObject root) { set_json_icon_state_value(root, obj, "fan-" + obj->get_object_id(), obj->state ? "ON" : "OFF", obj->state, @@ -623,6 +635,8 @@ void WebServer::handle_fan_request(AsyncWebServerRequest *request, const UrlMatc #ifdef USE_LIGHT void WebServer::on_light_update(light::LightState *obj) { + if (this->events_.count() == 0) + return; this->events_.send(this->light_json(obj, DETAIL_STATE).c_str(), "state"); } void WebServer::handle_light_request(AsyncWebServerRequest *request, const UrlMatch &match) { @@ -729,6 +743,8 @@ std::string WebServer::light_json(light::LightState *obj, JsonDetail start_confi #ifdef USE_COVER void WebServer::on_cover_update(cover::Cover *obj) { + if (this->events_.count() == 0) + return; this->events_.send(this->cover_json(obj, DETAIL_STATE).c_str(), "state"); } void WebServer::handle_cover_request(AsyncWebServerRequest *request, const UrlMatch &match) { @@ -798,6 +814,8 @@ std::string WebServer::cover_json(cover::Cover *obj, JsonDetail start_config) { #ifdef USE_NUMBER void WebServer::on_number_update(number::Number *obj, float state) { + if (this->events_.count() == 0) + return; this->events_.send(this->number_json(obj, state, DETAIL_STATE).c_str(), "state"); } void WebServer::handle_number_request(AsyncWebServerRequest *request, const UrlMatch &match) { @@ -856,6 +874,8 @@ std::string WebServer::number_json(number::Number *obj, float value, JsonDetail #ifdef USE_DATETIME_DATE void WebServer::on_date_update(datetime::DateEntity *obj) { + if (this->events_.count() == 0) + return; this->events_.send(this->date_json(obj, DETAIL_STATE).c_str(), "state"); } void WebServer::handle_date_request(AsyncWebServerRequest *request, const UrlMatch &match) { @@ -903,6 +923,8 @@ std::string WebServer::date_json(datetime::DateEntity *obj, JsonDetail start_con #ifdef USE_TEXT void WebServer::on_text_update(text::Text *obj, const std::string &state) { + if (this->events_.count() == 0) + return; this->events_.send(this->text_json(obj, state, DETAIL_STATE).c_str(), "state"); } void WebServer::handle_text_request(AsyncWebServerRequest *request, const UrlMatch &match) { @@ -954,6 +976,8 @@ std::string WebServer::text_json(text::Text *obj, const std::string &value, Json #ifdef USE_SELECT void WebServer::on_select_update(select::Select *obj, const std::string &state, size_t index) { + if (this->events_.count() == 0) + return; this->events_.send(this->select_json(obj, state, DETAIL_STATE).c_str(), "state"); } void WebServer::handle_select_request(AsyncWebServerRequest *request, const UrlMatch &match) { @@ -1008,6 +1032,8 @@ std::string WebServer::select_json(select::Select *obj, const std::string &value #ifdef USE_CLIMATE void WebServer::on_climate_update(climate::Climate *obj) { + if (this->events_.count() == 0) + return; this->events_.send(this->climate_json(obj, DETAIL_STATE).c_str(), "state"); } @@ -1149,6 +1175,8 @@ std::string WebServer::climate_json(climate::Climate *obj, JsonDetail start_conf #ifdef USE_LOCK void WebServer::on_lock_update(lock::Lock *obj) { + if (this->events_.count() == 0) + return; this->events_.send(this->lock_json(obj, obj->state, DETAIL_STATE).c_str(), "state"); } std::string WebServer::lock_json(lock::Lock *obj, lock::LockState value, JsonDetail start_config) { @@ -1185,6 +1213,8 @@ void WebServer::handle_lock_request(AsyncWebServerRequest *request, const UrlMat #ifdef USE_ALARM_CONTROL_PANEL void WebServer::on_alarm_control_panel_update(alarm_control_panel::AlarmControlPanel *obj) { + if (this->events_.count() == 0) + return; this->events_.send(this->alarm_control_panel_json(obj, obj->get_state(), DETAIL_STATE).c_str(), "state"); } std::string WebServer::alarm_control_panel_json(alarm_control_panel::AlarmControlPanel *obj, diff --git a/esphome/components/web_server_idf/web_server_idf.h b/esphome/components/web_server_idf/web_server_idf.h index 750f890fc7..2ead5e3f03 100644 --- a/esphome/components/web_server_idf/web_server_idf.h +++ b/esphome/components/web_server_idf/web_server_idf.h @@ -3,11 +3,11 @@ #include -#include #include -#include #include #include +#include +#include namespace esphome { namespace web_server_idf { @@ -251,6 +251,8 @@ class AsyncEventSource : public AsyncWebHandler { void send(const char *message, const char *event = nullptr, uint32_t id = 0, uint32_t reconnect = 0); + size_t count() const { return this->sessions_.size(); } + protected: std::string url_; std::set sessions_; From f09bfa731181e7dce43165d9d2a2b886053c5afd Mon Sep 17 00:00:00 2001 From: Faidon Liambotis Date: Thu, 4 Apr 2024 02:55:24 +0300 Subject: [PATCH 1190/2101] ESP32 Arduino WiFi: misc bug fixes (#6470) --- esphome/components/wifi/wifi_component_esp32_arduino.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/wifi/wifi_component_esp32_arduino.cpp b/esphome/components/wifi/wifi_component_esp32_arduino.cpp index 35e6c57e62..44d77b4eed 100644 --- a/esphome/components/wifi/wifi_component_esp32_arduino.cpp +++ b/esphome/components/wifi/wifi_component_esp32_arduino.cpp @@ -582,14 +582,14 @@ void WiFiComponent::wifi_pre_setup_() { } WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() { auto status = WiFiClass::status(); - if (status == WL_CONNECTED) { - return WiFiSTAConnectStatus::CONNECTED; - } else if (status == WL_CONNECT_FAILED || status == WL_CONNECTION_LOST) { + if (status == WL_CONNECT_FAILED || status == WL_CONNECTION_LOST) { return WiFiSTAConnectStatus::ERROR_CONNECT_FAILED; } else if (status == WL_NO_SSID_AVAIL) { return WiFiSTAConnectStatus::ERROR_NETWORK_NOT_FOUND; } else if (s_sta_connecting) { return WiFiSTAConnectStatus::CONNECTING; + } else if (status == WL_CONNECTED) { + return WiFiSTAConnectStatus::CONNECTED; } return WiFiSTAConnectStatus::IDLE; } @@ -707,7 +707,7 @@ bool WiFiComponent::wifi_start_ap_(const WiFiAP &ap) { *conf.ap.password = 0; } else { conf.ap.authmode = WIFI_AUTH_WPA2_PSK; - strncpy(reinterpret_cast(conf.ap.password), ap.get_password().c_str(), sizeof(conf.ap.ssid)); + strncpy(reinterpret_cast(conf.ap.password), ap.get_password().c_str(), sizeof(conf.ap.password)); } conf.ap.pairwise_cipher = WIFI_CIPHER_TYPE_CCMP; From 0148ebcaa604f929aba06b6722697bb1b6e4c83c Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 4 Apr 2024 13:41:41 +1300 Subject: [PATCH 1191/2101] Replace std::regex with sscanf calls (#6468) * Replace std::regex with sscanf calls * Fix CI * Use regular formatting placeholders * Fix --- esphome/core/time.cpp | 77 +++++++++++++++++++++---------------------- esphome/core/time.h | 4 --- 2 files changed, 37 insertions(+), 44 deletions(-) diff --git a/esphome/core/time.cpp b/esphome/core/time.cpp index ae4fabac52..0004fc7e8e 100644 --- a/esphome/core/time.cpp +++ b/esphome/core/time.cpp @@ -1,9 +1,7 @@ -#ifdef USE_DATETIME -#include -#endif - -#include "helpers.h" #include "time.h" // NOLINT +#include "helpers.h" + +#include namespace esphome { @@ -66,48 +64,47 @@ std::string ESPTime::strftime(const std::string &format) { return timestr; } -#ifdef USE_DATETIME - bool ESPTime::strptime(const std::string &time_to_parse, ESPTime &esp_time) { - // clang-format off - std::regex dt_regex(R"(^ - ( - (\d{4})-(\d{1,2})-(\d{1,2}) - (?:\s(?=.+)) - )? - ( - (\d{1,2}):(\d{2}) - (?::(\d{2}))? - )? - $)"); - // clang-format on + uint16_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint8_t second; + int num; - std::smatch match; - if (std::regex_match(time_to_parse, match, dt_regex) == 0) + 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 == time_to_parse.size()) { + esp_time.year = year; + esp_time.month = month; + esp_time.day_of_month = day; + esp_time.hour = hour; + esp_time.minute = minute; + esp_time.second = second; + } else if (sscanf(time_to_parse.c_str(), "%02hhu:%02hhu:%02hhu %n", &hour, &minute, &second, &num) == 3 && // NOLINT + num == time_to_parse.size()) { + esp_time.hour = hour; + 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 == time_to_parse.size()) { + 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 == time_to_parse.size()) { + esp_time.year = year; + esp_time.month = month; + esp_time.day_of_month = day; + } else { return false; - - if (match[1].matched) { // Has date parts - - esp_time.year = parse_number(match[2].str()).value_or(0); - esp_time.month = parse_number(match[3].str()).value_or(0); - esp_time.day_of_month = parse_number(match[4].str()).value_or(0); } - if (match[5].matched) { // Has time parts - - esp_time.hour = parse_number(match[6].str()).value_or(0); - esp_time.minute = parse_number(match[7].str()).value_or(0); - if (match[8].matched) { - esp_time.second = parse_number(match[8].str()).value_or(0); - } else { - esp_time.second = 0; - } - } - return true; } -#endif - void ESPTime::increment_second() { this->timestamp++; if (!increment_time_value(this->second, 0, 60)) diff --git a/esphome/core/time.h b/esphome/core/time.h index 738a0261c7..4300cf26b7 100644 --- a/esphome/core/time.h +++ b/esphome/core/time.h @@ -67,8 +67,6 @@ struct ESPTime { this->day_of_year < 367 && this->month > 0 && this->month < 13; } -#ifdef USE_DATETIME - /** 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 esp_time an instance of a ESPTime struct @@ -76,8 +74,6 @@ struct ESPTime { */ static bool strptime(const std::string &time_to_parse, ESPTime &esp_time); -#endif - /// 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 4c9bcc71cbcf285daa7a73e30b7eadf834503e64 Mon Sep 17 00:00:00 2001 From: DAVe3283 Date: Wed, 20 Mar 2024 17:57:27 -0600 Subject: [PATCH 1192/2101] Fix logger compile error on ESP32-C6 (#6323) --- esphome/components/logger/logger_esp32.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/logger/logger_esp32.cpp b/esphome/components/logger/logger_esp32.cpp index 7c4d6781c9..740e086f92 100644 --- a/esphome/components/logger/logger_esp32.cpp +++ b/esphome/components/logger/logger_esp32.cpp @@ -129,7 +129,7 @@ void Logger::pre_setup() { this->uart_num_ = UART_NUM_2; break; #endif -#if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) +#ifdef USE_LOGGER_USB_CDC case UART_SELECTION_USB_CDC: this->uart_num_ = -1; break; From 87c4ad025698b2e240c397d54332a3a62e92cd81 Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Thu, 28 Mar 2024 12:51:01 -0700 Subject: [PATCH 1193/2101] Add missing ethernet types (#6444) --- esphome/components/ethernet/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/components/ethernet/__init__.py b/esphome/components/ethernet/__init__.py index de6040339a..ade94cb9f5 100644 --- a/esphome/components/ethernet/__init__.py +++ b/esphome/components/ethernet/__init__.py @@ -155,6 +155,8 @@ CONFIG_SCHEMA = cv.All( "DP83848": RMII_SCHEMA, "IP101": RMII_SCHEMA, "JL1101": RMII_SCHEMA, + "KSZ8081": RMII_SCHEMA, + "KSZ8081RNA": RMII_SCHEMA, "W5500": SPI_SCHEMA, }, upper=True, From d2b386146509837264079d93d9d5d3fb598f1137 Mon Sep 17 00:00:00 2001 From: NewoPL <27411874+NewoPL@users.noreply.github.com> Date: Mon, 1 Apr 2024 01:43:49 +0200 Subject: [PATCH 1194/2101] fix: changing the content source when playing is paused blocks the player (#6454) --- .../i2s_audio/media_player/i2s_audio_media_player.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/i2s_audio/media_player/i2s_audio_media_player.cpp b/esphome/components/i2s_audio/media_player/i2s_audio_media_player.cpp index 9e2e3f136a..6e07983920 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 @@ -12,12 +12,12 @@ static const char *const TAG = "audio"; void I2SAudioMediaPlayer::control(const media_player::MediaPlayerCall &call) { if (call.get_media_url().has_value()) { this->current_url_ = call.get_media_url(); - - if (this->state == media_player::MEDIA_PLAYER_STATE_PLAYING && this->audio_ != nullptr) { + 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->state = media_player::MEDIA_PLAYER_STATE_PLAYING; } else { this->start(); } From c029ef51181412dd8e35ef8e5280d5cd2a38abdc Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 4 Apr 2024 18:12:28 +1300 Subject: [PATCH 1195/2101] Bump version to 2024.3.2 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index b09d0a8eb0..5368f0bc9a 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.3.1" +__version__ = "2024.3.2" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 2c67d83976305e21ae2bcd93f0412db0a6e13814 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Fri, 5 Apr 2024 15:21:56 +1100 Subject: [PATCH 1196/2101] Include "Failed" status in config log. (#6482) --- esphome/core/component.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index b9a7697015..803bc11e02 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -76,7 +76,12 @@ bool Component::cancel_timeout(const std::string &name) { // NOLINT void Component::call_loop() { this->loop(); } void Component::call_setup() { this->setup(); } -void Component::call_dump_config() { this->dump_config(); } +void Component::call_dump_config() { + this->dump_config(); + if (this->is_failed()) { + ESP_LOGE(this->get_component_source(), " Component is marked FAILED"); + } +} uint32_t Component::get_component_state() const { return this->component_state_; } void Component::call() { From 38233444e7e30a031defb3198f6be12c08fed328 Mon Sep 17 00:00:00 2001 From: Remy van Elst Date: Sun, 7 Apr 2024 04:48:42 +0200 Subject: [PATCH 1197/2101] Fix Microphone IsCapturingCondition (#6490) --- esphome/components/microphone/automation.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/microphone/automation.h b/esphome/components/microphone/automation.h index 5313f07f72..29c0ec5df2 100644 --- a/esphome/components/microphone/automation.h +++ b/esphome/components/microphone/automation.h @@ -23,7 +23,7 @@ class DataTrigger : public Trigger &> { } }; -template class IsCapturingActon : public Condition, public Parented { +template class IsCapturingCondition : public Condition, public Parented { public: bool check(Ts... x) override { return this->parent_->is_running(); } }; From 97ff87b71893f4d1e01b61722bf4e556014699b6 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Mon, 8 Apr 2024 14:13:12 +1000 Subject: [PATCH 1198/2101] Remove misleading tag/line in messages (#6495) --- esphome/core/component.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index 803bc11e02..594e8ff7df 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -79,7 +79,7 @@ void Component::call_setup() { this->setup(); } void Component::call_dump_config() { this->dump_config(); if (this->is_failed()) { - ESP_LOGE(this->get_component_source(), " Component is marked FAILED"); + ESP_LOGE(TAG, " Component %s is marked FAILED", this->get_component_source()); } } @@ -154,26 +154,26 @@ void Component::status_set_warning(const char *message) { return; this->component_state_ |= STATUS_LED_WARNING; App.app_state_ |= STATUS_LED_WARNING; - ESP_LOGW(this->get_component_source(), "Warning set: %s", message); + ESP_LOGW(TAG, "Component %s set Warning flag: %s", this->get_component_source(), message); } void Component::status_set_error(const char *message) { if ((this->component_state_ & STATUS_LED_ERROR) != 0) return; this->component_state_ |= STATUS_LED_ERROR; App.app_state_ |= STATUS_LED_ERROR; - ESP_LOGE(this->get_component_source(), "Error set: %s", message); + ESP_LOGE(TAG, "Component %s set Error flag: %s", this->get_component_source(), message); } void Component::status_clear_warning() { if ((this->component_state_ & STATUS_LED_WARNING) == 0) return; this->component_state_ &= ~STATUS_LED_WARNING; - ESP_LOGW(this->get_component_source(), "Warning cleared"); + ESP_LOGW(TAG, "Component %s cleared Warning flag", this->get_component_source()); } void Component::status_clear_error() { if ((this->component_state_ & STATUS_LED_ERROR) == 0) return; this->component_state_ &= ~STATUS_LED_ERROR; - ESP_LOGE(this->get_component_source(), "Error cleared"); + ESP_LOGE(TAG, "Component %s cleared Error flag", this->get_component_source()); } void Component::status_momentary_warning(const std::string &name, uint32_t length) { this->status_set_warning(); From 6f71363d9b9b2b35f13ff6bdde5870e9135e4977 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 8 Apr 2024 16:19:22 +1200 Subject: [PATCH 1199/2101] Send/Receive Voice Assistant audio via API (#6471) Co-authored-by: Michael Hansen --- esphome/components/api/api.proto | 19 ++- esphome/components/api/api_connection.cpp | 27 ++++- esphome/components/api/api_connection.h | 1 + esphome/components/api/api_pb2.cpp | 83 ++++++++++++- esphome/components/api/api_pb2.h | 21 +++- esphome/components/api/api_pb2_service.cpp | 19 +++ esphome/components/api/api_pb2_service.h | 4 + .../voice_assistant/voice_assistant.cpp | 109 +++++++++++++----- .../voice_assistant/voice_assistant.h | 40 ++++++- 9 files changed, 275 insertions(+), 48 deletions(-) diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index 7efc7aef64..6b685b8974 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -217,7 +217,8 @@ message DeviceInfoResponse { string friendly_name = 13; - uint32 voice_assistant_version = 14; + uint32 legacy_voice_assistant_version = 14; + uint32 voice_assistant_feature_flags = 17; string suggested_area = 16; } @@ -1422,12 +1423,18 @@ message BluetoothDeviceClearCacheResponse { } // ==================== PUSH TO TALK ==================== +enum VoiceAssistantSubscribeFlag { + VOICE_ASSISTANT_SUBSCRIBE_NONE = 0; + VOICE_ASSISTANT_SUBSCRIBE_API_AUDIO = 1; +} + message SubscribeVoiceAssistantRequest { option (id) = 89; option (source) = SOURCE_CLIENT; option (ifdef) = "USE_VOICE_ASSISTANT"; bool subscribe = 1; + uint32 flags = 2; } enum VoiceAssistantRequestFlag { @@ -1495,6 +1502,16 @@ message VoiceAssistantEventResponse { repeated VoiceAssistantEventData data = 2; } +message VoiceAssistantAudio { + option (id) = 106; + option (source) = SOURCE_BOTH; + option (ifdef) = "USE_VOICE_ASSISTANT"; + + bytes data = 1; + bool end = 2; +} + + // ==================== ALARM CONTROL PANEL ==================== enum AlarmControlPanelState { ALARM_STATE_DISARMED = 0; diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index bd4790df95..e9607f7f77 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1040,10 +1040,15 @@ void APIConnection::on_voice_assistant_response(const VoiceAssistantResponse &ms voice_assistant::global_voice_assistant->failed_to_start(); return; } - struct sockaddr_storage storage; - socklen_t len = sizeof(storage); - this->helper_->getpeername((struct sockaddr *) &storage, &len); - voice_assistant::global_voice_assistant->start_streaming(&storage, msg.port); + if (msg.port == 0) { + // Use API Audio + voice_assistant::global_voice_assistant->start_streaming(); + } else { + struct sockaddr_storage storage; + socklen_t len = sizeof(storage); + this->helper_->getpeername((struct sockaddr *) &storage, &len); + voice_assistant::global_voice_assistant->start_streaming(&storage, msg.port); + } } }; void APIConnection::on_voice_assistant_event_response(const VoiceAssistantEventResponse &msg) { @@ -1055,6 +1060,15 @@ void APIConnection::on_voice_assistant_event_response(const VoiceAssistantEventR voice_assistant::global_voice_assistant->on_event(msg); } } +void APIConnection::on_voice_assistant_audio(const VoiceAssistantAudio &msg) { + if (voice_assistant::global_voice_assistant != nullptr) { + if (voice_assistant::global_voice_assistant->get_api_connection() != this) { + return; + } + + voice_assistant::global_voice_assistant->on_audio(msg); + } +}; #endif @@ -1142,7 +1156,7 @@ HelloResponse APIConnection::hello(const HelloRequest &msg) { HelloResponse resp; resp.api_version_major = 1; - resp.api_version_minor = 9; + resp.api_version_minor = 10; resp.server_info = App.get_name() + " (esphome v" ESPHOME_VERSION ")"; resp.name = App.get_name(); @@ -1203,7 +1217,8 @@ DeviceInfoResponse APIConnection::device_info(const DeviceInfoRequest &msg) { resp.bluetooth_proxy_feature_flags = bluetooth_proxy::global_bluetooth_proxy->get_feature_flags(); #endif #ifdef USE_VOICE_ASSISTANT - resp.voice_assistant_version = voice_assistant::global_voice_assistant->get_version(); + resp.legacy_voice_assistant_version = voice_assistant::global_voice_assistant->get_legacy_version(); + resp.voice_assistant_feature_flags = voice_assistant::global_voice_assistant->get_feature_flags(); #endif return resp; } diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index 6fe6e0d509..c19c209969 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -134,6 +134,7 @@ class APIConnection : public APIServerConnection { void subscribe_voice_assistant(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; #endif #ifdef USE_ALARM_CONTROL_PANEL diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index 32654f3148..f6325d0854 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -410,6 +410,19 @@ const char *proto_enum_to_string(enums::Bluet } #endif #ifdef HAS_PROTO_MESSAGE_DUMP +template<> +const char *proto_enum_to_string(enums::VoiceAssistantSubscribeFlag value) { + switch (value) { + case enums::VOICE_ASSISTANT_SUBSCRIBE_NONE: + return "VOICE_ASSISTANT_SUBSCRIBE_NONE"; + case enums::VOICE_ASSISTANT_SUBSCRIBE_API_AUDIO: + return "VOICE_ASSISTANT_SUBSCRIBE_API_AUDIO"; + default: + return "UNKNOWN"; + } +} +#endif +#ifdef HAS_PROTO_MESSAGE_DUMP template<> const char *proto_enum_to_string(enums::VoiceAssistantRequestFlag value) { switch (value) { case enums::VOICE_ASSISTANT_REQUEST_NONE: @@ -716,7 +729,11 @@ bool DeviceInfoResponse::decode_varint(uint32_t field_id, ProtoVarInt value) { return true; } case 14: { - this->voice_assistant_version = value.as_uint32(); + this->legacy_voice_assistant_version = value.as_uint32(); + return true; + } + case 17: { + this->voice_assistant_feature_flags = value.as_uint32(); return true; } default: @@ -784,7 +801,8 @@ void DeviceInfoResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(15, this->bluetooth_proxy_feature_flags); buffer.encode_string(12, this->manufacturer); buffer.encode_string(13, this->friendly_name); - buffer.encode_uint32(14, this->voice_assistant_version); + buffer.encode_uint32(14, this->legacy_voice_assistant_version); + buffer.encode_uint32(17, this->voice_assistant_feature_flags); buffer.encode_string(16, this->suggested_area); } #ifdef HAS_PROTO_MESSAGE_DUMP @@ -850,8 +868,13 @@ void DeviceInfoResponse::dump_to(std::string &out) const { out.append("'").append(this->friendly_name).append("'"); out.append("\n"); - out.append(" voice_assistant_version: "); - sprintf(buffer, "%" PRIu32, this->voice_assistant_version); + out.append(" legacy_voice_assistant_version: "); + sprintf(buffer, "%" PRIu32, this->legacy_voice_assistant_version); + out.append(buffer); + out.append("\n"); + + out.append(" voice_assistant_feature_flags: "); + sprintf(buffer, "%" PRIu32, this->voice_assistant_feature_flags); out.append(buffer); out.append("\n"); @@ -6514,11 +6537,18 @@ bool SubscribeVoiceAssistantRequest::decode_varint(uint32_t field_id, ProtoVarIn this->subscribe = value.as_bool(); return true; } + case 2: { + this->flags = value.as_uint32(); + return true; + } default: return false; } } -void SubscribeVoiceAssistantRequest::encode(ProtoWriteBuffer buffer) const { buffer.encode_bool(1, this->subscribe); } +void SubscribeVoiceAssistantRequest::encode(ProtoWriteBuffer buffer) const { + buffer.encode_bool(1, this->subscribe); + buffer.encode_uint32(2, this->flags); +} #ifdef HAS_PROTO_MESSAGE_DUMP void SubscribeVoiceAssistantRequest::dump_to(std::string &out) const { __attribute__((unused)) char buffer[64]; @@ -6526,6 +6556,11 @@ void SubscribeVoiceAssistantRequest::dump_to(std::string &out) const { out.append(" subscribe: "); out.append(YESNO(this->subscribe)); out.append("\n"); + + out.append(" flags: "); + sprintf(buffer, "%" PRIu32, this->flags); + out.append(buffer); + out.append("\n"); out.append("}"); } #endif @@ -6752,6 +6787,44 @@ void VoiceAssistantEventResponse::dump_to(std::string &out) const { out.append("}"); } #endif +bool VoiceAssistantAudio::decode_varint(uint32_t field_id, ProtoVarInt value) { + switch (field_id) { + case 2: { + this->end = value.as_bool(); + return true; + } + default: + return false; + } +} +bool VoiceAssistantAudio::decode_length(uint32_t field_id, ProtoLengthDelimited value) { + switch (field_id) { + case 1: { + this->data = value.as_string(); + return true; + } + default: + return false; + } +} +void VoiceAssistantAudio::encode(ProtoWriteBuffer buffer) const { + buffer.encode_string(1, this->data); + buffer.encode_bool(2, this->end); +} +#ifdef HAS_PROTO_MESSAGE_DUMP +void VoiceAssistantAudio::dump_to(std::string &out) const { + __attribute__((unused)) char buffer[64]; + out.append("VoiceAssistantAudio {\n"); + out.append(" data: "); + out.append("'").append(this->data).append("'"); + out.append("\n"); + + out.append(" end: "); + out.append(YESNO(this->end)); + out.append("\n"); + out.append("}"); +} +#endif bool ListEntitiesAlarmControlPanelResponse::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { case 6: { diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index f9847a6a19..e361e6b8e1 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -165,6 +165,10 @@ enum BluetoothDeviceRequestType : uint32_t { BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITHOUT_CACHE = 5, BLUETOOTH_DEVICE_REQUEST_TYPE_CLEAR_CACHE = 6, }; +enum VoiceAssistantSubscribeFlag : uint32_t { + VOICE_ASSISTANT_SUBSCRIBE_NONE = 0, + VOICE_ASSISTANT_SUBSCRIBE_API_AUDIO = 1, +}; enum VoiceAssistantRequestFlag : uint32_t { VOICE_ASSISTANT_REQUEST_NONE = 0, VOICE_ASSISTANT_REQUEST_USE_VAD = 1, @@ -327,7 +331,8 @@ class DeviceInfoResponse : public ProtoMessage { uint32_t bluetooth_proxy_feature_flags{0}; std::string manufacturer{}; std::string friendly_name{}; - uint32_t voice_assistant_version{0}; + uint32_t legacy_voice_assistant_version{0}; + uint32_t voice_assistant_feature_flags{0}; std::string suggested_area{}; void encode(ProtoWriteBuffer buffer) const override; #ifdef HAS_PROTO_MESSAGE_DUMP @@ -1674,6 +1679,7 @@ class BluetoothDeviceClearCacheResponse : public ProtoMessage { class SubscribeVoiceAssistantRequest : public ProtoMessage { public: bool subscribe{false}; + uint32_t flags{0}; void encode(ProtoWriteBuffer buffer) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; @@ -1749,6 +1755,19 @@ class VoiceAssistantEventResponse : public ProtoMessage { bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; bool decode_varint(uint32_t field_id, ProtoVarInt value) override; }; +class VoiceAssistantAudio : public ProtoMessage { + public: + std::string data{}; + bool end{false}; + void encode(ProtoWriteBuffer buffer) const override; +#ifdef HAS_PROTO_MESSAGE_DUMP + void dump_to(std::string &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 ListEntitiesAlarmControlPanelResponse : public ProtoMessage { public: std::string object_id{}; diff --git a/esphome/components/api/api_pb2_service.cpp b/esphome/components/api/api_pb2_service.cpp index 4e61893bae..2067f530ce 100644 --- a/esphome/components/api/api_pb2_service.cpp +++ b/esphome/components/api/api_pb2_service.cpp @@ -476,6 +476,14 @@ bool APIServerConnectionBase::send_voice_assistant_request(const VoiceAssistantR #endif #ifdef USE_VOICE_ASSISTANT #endif +#ifdef USE_VOICE_ASSISTANT +bool APIServerConnectionBase::send_voice_assistant_audio(const VoiceAssistantAudio &msg) { +#ifdef HAS_PROTO_MESSAGE_DUMP + ESP_LOGVV(TAG, "send_voice_assistant_audio: %s", msg.dump().c_str()); +#endif + return this->send_message_(msg, 106); +} +#endif #ifdef USE_ALARM_CONTROL_PANEL bool APIServerConnectionBase::send_list_entities_alarm_control_panel_response( const ListEntitiesAlarmControlPanelResponse &msg) { @@ -971,6 +979,17 @@ bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, ESP_LOGVV(TAG, "on_date_command_request: %s", msg.dump().c_str()); #endif this->on_date_command_request(msg); +#endif + break; + } + case 106: { +#ifdef USE_VOICE_ASSISTANT + 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()); +#endif + this->on_voice_assistant_audio(msg); #endif break; } diff --git a/esphome/components/api/api_pb2_service.h b/esphome/components/api/api_pb2_service.h index a3c53a7534..effcfc30f4 100644 --- a/esphome/components/api/api_pb2_service.h +++ b/esphome/components/api/api_pb2_service.h @@ -240,6 +240,10 @@ class APIServerConnectionBase : public ProtoService { #ifdef USE_VOICE_ASSISTANT virtual void on_voice_assistant_event_response(const VoiceAssistantEventResponse &value){}; #endif +#ifdef USE_VOICE_ASSISTANT + bool send_voice_assistant_audio(const VoiceAssistantAudio &msg); + virtual void on_voice_assistant_audio(const VoiceAssistantAudio &value){}; +#endif #ifdef USE_ALARM_CONTROL_PANEL bool send_list_entities_alarm_control_panel_response(const ListEntitiesAlarmControlPanelResponse &msg); #endif diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index 49b8fdc959..34a26eec01 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -24,28 +24,24 @@ static const size_t SPEAKER_BUFFER_SIZE = 16 * RECEIVE_SIZE; float VoiceAssistant::get_setup_priority() const { return setup_priority::AFTER_CONNECTION; } -void VoiceAssistant::setup() { - ESP_LOGCONFIG(TAG, "Setting up Voice Assistant..."); - - global_voice_assistant = this; - +bool VoiceAssistant::start_udp_socket_() { this->socket_ = socket::socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); - if (socket_ == nullptr) { - ESP_LOGW(TAG, "Could not create socket"); + if (this->socket_ == nullptr) { + ESP_LOGE(TAG, "Could not create socket"); this->mark_failed(); - return; + return false; } int enable = 1; - int err = socket_->setsockopt(SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)); + 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); // we can still continue } - err = socket_->setblocking(false); + err = this->socket_->setblocking(false); if (err != 0) { - ESP_LOGW(TAG, "Socket unable to set nonblocking mode: errno %d", err); + ESP_LOGE(TAG, "Socket unable to set nonblocking mode: errno %d", err); this->mark_failed(); - return; + return false; } #ifdef USE_SPEAKER @@ -54,18 +50,30 @@ void VoiceAssistant::setup() { socklen_t sl = socket::set_sockaddr_any((struct sockaddr *) &server, sizeof(server), 6055); if (sl == 0) { - ESP_LOGW(TAG, "Socket unable to set sockaddr: errno %d", errno); + ESP_LOGE(TAG, "Socket unable to set sockaddr: errno %d", errno); this->mark_failed(); - return; + return false; } - err = socket_->bind((struct sockaddr *) &server, sizeof(server)); + err = this->socket_->bind((struct sockaddr *) &server, sizeof(server)); if (err != 0) { - ESP_LOGW(TAG, "Socket unable to bind: errno %d", errno); + ESP_LOGE(TAG, "Socket unable to bind: errno %d", errno); this->mark_failed(); - return; + return false; } + } +#endif + this->udp_socket_running_ = true; + return true; +} +void VoiceAssistant::setup() { + ESP_LOGCONFIG(TAG, "Setting up Voice Assistant..."); + + global_voice_assistant = this; + +#ifdef USE_SPEAKER + if (this->speaker_ != nullptr) { ExternalRAMAllocator speaker_allocator(ExternalRAMAllocator::ALLOW_FAILURE); this->speaker_buffer_ = speaker_allocator.allocate(SPEAKER_BUFFER_SIZE); if (this->speaker_buffer_ == nullptr) { @@ -238,8 +246,20 @@ void VoiceAssistant::loop() { size_t available = this->ring_buffer_->available(); while (available >= SEND_BUFFER_SIZE) { size_t read_bytes = this->ring_buffer_->read((void *) this->send_buffer_, SEND_BUFFER_SIZE, 0); - this->socket_->sendto(this->send_buffer_, read_bytes, 0, (struct sockaddr *) &this->dest_addr_, - sizeof(this->dest_addr_)); + if (this->audio_mode_ == AUDIO_MODE_API) { + api::VoiceAssistantAudio msg; + msg.data.assign((char *) this->send_buffer_, read_bytes); + this->api_client_->send_voice_assistant_audio(msg); + } else { + if (!this->udp_socket_running_) { + if (!this->start_udp_socket_()) { + this->set_state_(State::STOP_MICROPHONE, State::IDLE); + break; + } + } + this->socket_->sendto(this->send_buffer_, read_bytes, 0, (struct sockaddr *) &this->dest_addr_, + sizeof(this->dest_addr_)); + } available = this->ring_buffer_->available(); } @@ -268,22 +288,25 @@ void VoiceAssistant::loop() { #ifdef USE_SPEAKER if (this->speaker_ != nullptr) { ssize_t received_len = 0; - if (this->speaker_buffer_index_ + RECEIVE_SIZE < SPEAKER_BUFFER_SIZE) { - received_len = this->socket_->read(this->speaker_buffer_ + this->speaker_buffer_index_, RECEIVE_SIZE); - if (received_len > 0) { - this->speaker_buffer_index_ += received_len; - this->speaker_buffer_size_ += received_len; - this->speaker_bytes_received_ += received_len; + if (this->audio_mode_ == AUDIO_MODE_UDP) { + if (this->speaker_buffer_index_ + RECEIVE_SIZE < SPEAKER_BUFFER_SIZE) { + received_len = this->socket_->read(this->speaker_buffer_ + this->speaker_buffer_index_, RECEIVE_SIZE); + if (received_len > 0) { + this->speaker_buffer_index_ += received_len; + this->speaker_buffer_size_ += received_len; + this->speaker_bytes_received_ += received_len; + } + } else { + ESP_LOGD(TAG, "Receive buffer full"); } - } else { - ESP_LOGD(TAG, "Receive buffer full"); } // Build a small buffer of audio before sending to the speaker - if (this->speaker_bytes_received_ > RECEIVE_SIZE * 4) + bool end_of_stream = this->stream_ended_ && (this->audio_mode_ == AUDIO_MODE_API || received_len < 0); + if (this->speaker_bytes_received_ > RECEIVE_SIZE * 4 || end_of_stream) this->write_speaker_(); if (this->wait_for_stream_end_) { this->cancel_timeout("playing"); - if (this->stream_ended_ && received_len < 0) { + if (end_of_stream) { ESP_LOGD(TAG, "End of audio stream received"); this->cancel_timeout("speaker-timeout"); this->set_state_(State::RESPONSE_FINISHED, State::RESPONSE_FINISHED); @@ -428,6 +451,22 @@ void VoiceAssistant::failed_to_start() { this->set_state_(State::STOP_MICROPHONE, State::IDLE); } +void VoiceAssistant::start_streaming() { + if (this->state_ != State::STARTING_PIPELINE) { + this->signal_stop_(); + return; + } + + ESP_LOGD(TAG, "Client started, streaming microphone"); + this->audio_mode_ = AUDIO_MODE_API; + + if (this->mic_->is_running()) { + this->set_state_(State::STREAMING_MICROPHONE, State::STREAMING_MICROPHONE); + } else { + this->set_state_(State::START_MICROPHONE, State::STREAMING_MICROPHONE); + } +} + void VoiceAssistant::start_streaming(struct sockaddr_storage *addr, uint16_t port) { if (this->state_ != State::STARTING_PIPELINE) { this->signal_stop_(); @@ -435,6 +474,7 @@ void VoiceAssistant::start_streaming(struct sockaddr_storage *addr, uint16_t por } ESP_LOGD(TAG, "Client started, streaming microphone"); + this->audio_mode_ = AUDIO_MODE_UDP; memcpy(&this->dest_addr_, addr, sizeof(this->dest_addr_)); if (this->dest_addr_.ss_family == AF_INET) { @@ -688,6 +728,17 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { } } +void VoiceAssistant::on_audio(const api::VoiceAssistantAudio &msg) { + if (this->speaker_buffer_index_ + msg.data.length() < SPEAKER_BUFFER_SIZE) { + memcpy(this->speaker_buffer_ + this->speaker_buffer_index_, msg.data.data(), msg.data.length()); + this->speaker_buffer_index_ += msg.data.length(); + this->speaker_buffer_size_ += msg.data.length(); + this->speaker_bytes_received_ += msg.data.length(); + } else { + ESP_LOGE(TAG, "Cannot receive audio, buffer is full"); + } +} + VoiceAssistant *global_voice_assistant = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) } // namespace voice_assistant diff --git a/esphome/components/voice_assistant/voice_assistant.h b/esphome/components/voice_assistant/voice_assistant.h index 14352bf3ae..d6b1502381 100644 --- a/esphome/components/voice_assistant/voice_assistant.h +++ b/esphome/components/voice_assistant/voice_assistant.h @@ -29,9 +29,14 @@ namespace voice_assistant { // Version 1: Initial version // Version 2: Adds raw speaker support -// Version 3: Unused/skip -static const uint32_t INITIAL_VERSION = 1; -static const uint32_t SPEAKER_SUPPORT = 2; +static const uint32_t LEGACY_INITIAL_VERSION = 1; +static const uint32_t LEGACY_SPEAKER_SUPPORT = 2; + +enum VoiceAssistantFeature : uint32_t { + FEATURE_VOICE_ASSISTANT = 1 << 0, + FEATURE_SPEAKER = 1 << 1, + FEATURE_API_AUDIO = 1 << 2, +}; enum class State { IDLE, @@ -49,11 +54,17 @@ enum class State { RESPONSE_FINISHED, }; +enum AudioMode : uint8_t { + AUDIO_MODE_UDP, + AUDIO_MODE_API, +}; + class VoiceAssistant : public Component { public: void setup() override; void loop() override; float get_setup_priority() const override; + void start_streaming(); void start_streaming(struct sockaddr_storage *addr, uint16_t port); void failed_to_start(); @@ -71,19 +82,32 @@ class VoiceAssistant : public Component { } #endif - uint32_t get_version() const { + uint32_t get_legacy_version() const { #ifdef USE_SPEAKER if (this->speaker_ != nullptr) { - return SPEAKER_SUPPORT; + return LEGACY_SPEAKER_SUPPORT; } #endif - return INITIAL_VERSION; + return LEGACY_INITIAL_VERSION; + } + + uint32_t get_feature_flags() const { + uint32_t flags = 0; + flags |= VoiceAssistantFeature::FEATURE_VOICE_ASSISTANT; +#ifdef USE_SPEAKER + if (this->speaker_ != nullptr) { + flags |= VoiceAssistantFeature::FEATURE_SPEAKER; + flags |= VoiceAssistantFeature::FEATURE_API_AUDIO; + } +#endif + return flags; } void request_start(bool continuous, bool silence_detection); void request_stop(); void on_event(const api::VoiceAssistantEventResponse &msg); + void on_audio(const api::VoiceAssistantAudio &msg); bool is_running() const { return this->state_ != State::IDLE; } void set_continuous(bool continuous) { this->continuous_ = continuous; } @@ -201,6 +225,10 @@ class VoiceAssistant : public Component { State state_{State::IDLE}; State desired_state_{State::IDLE}; + + AudioMode audio_mode_{AUDIO_MODE_UDP}; + bool udp_socket_running_{false}; + bool start_udp_socket_(); }; template class StartAction : public Action, public Parented { From d6352b3be416a90e454f2c5b4fa168c4ef4fe1a2 Mon Sep 17 00:00:00 2001 From: RFDarter Date: Mon, 8 Apr 2024 09:36:23 +0200 Subject: [PATCH 1200/2101] Datetime date initial value fix (#6483) --- esphome/components/template/datetime/__init__.py | 11 ++++++++++- esphome/components/web_server/web_server.cpp | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/esphome/components/template/datetime/__init__.py b/esphome/components/template/datetime/__init__.py index 034be9b3b8..16f341301e 100644 --- a/esphome/components/template/datetime/__init__.py +++ b/esphome/components/template/datetime/__init__.py @@ -8,6 +8,9 @@ from esphome.const import ( CONF_OPTIMISTIC, CONF_RESTORE_VALUE, CONF_SET_ACTION, + CONF_DAY, + CONF_MONTH, + CONF_YEAR, ) from esphome.core import coroutine_with_priority @@ -82,7 +85,13 @@ async def to_code(config): cg.add(var.set_restore_value(config[CONF_RESTORE_VALUE])) if initial_value := config.get(CONF_INITIAL_VALUE): - cg.add(var.set_initial_value(initial_value)) + date_struct = cg.StructInitializer( + cg.ESPTime, + ("day_of_month", initial_value[CONF_DAY]), + ("month", initial_value[CONF_MONTH]), + ("year", initial_value[CONF_YEAR]), + ) + cg.add(var.set_initial_value(date_struct)) if CONF_SET_ACTION in config: await automation.build_automation( diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index 4e6797ae1f..6c3e4e5eec 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -914,7 +914,7 @@ void WebServer::handle_date_request(AsyncWebServerRequest *request, const UrlMat std::string WebServer::date_json(datetime::DateEntity *obj, JsonDetail start_config) { return json::build_json([obj, start_config](JsonObject root) { set_json_id(root, obj, "date-" + obj->get_object_id(), start_config); - std::string value = str_sprintf("%d-%d-%d", obj->year, obj->month, obj->day); + std::string value = str_sprintf("%d-%02d-%02d", obj->year, obj->month, obj->day); root["value"] = value; root["state"] = value; }); From e6b1187689b81d38fc4f755a88922cdd820319e1 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Mon, 8 Apr 2024 17:56:08 +1000 Subject: [PATCH 1201/2101] If the loop() took more than the required time, don't delay further (#6496) --- esphome/core/application.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/esphome/core/application.cpp b/esphome/core/application.cpp index d82a7a5d37..a4550bcd9e 100644 --- a/esphome/core/application.cpp +++ b/esphome/core/application.cpp @@ -81,13 +81,11 @@ void Application::loop() { const uint32_t now = millis(); - if (HighFrequencyLoopRequester::is_high_frequency()) { + auto elapsed = now - this->last_loop_; + if (elapsed >= this->loop_interval_ || HighFrequencyLoopRequester::is_high_frequency()) { yield(); } else { - uint32_t delay_time = this->loop_interval_; - if (now - this->last_loop_ < this->loop_interval_) - delay_time = this->loop_interval_ - (now - this->last_loop_); - + uint32_t delay_time = this->loop_interval_ - elapsed; uint32_t next_schedule = this->scheduler.next_schedule_in().value_or(delay_time); // next_schedule is max 0.5*delay_time // otherwise interval=0 schedules result in constant looping with almost no sleep From 46c63f48c25e278dcf485bc7c4cf315e4d9a9a42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Mon, 8 Apr 2024 21:19:50 +0200 Subject: [PATCH 1202/2101] Bump LibreTiny version to 1.5.1 (#6500) --- esphome/components/libretiny/__init__.py | 2 +- esphome/components/rtl87xx/boards.py | 132 +++++++++++++---------- 2 files changed, 74 insertions(+), 60 deletions(-) diff --git a/esphome/components/libretiny/__init__.py b/esphome/components/libretiny/__init__.py index 7dca370eff..34aff0ae16 100644 --- a/esphome/components/libretiny/__init__.py +++ b/esphome/components/libretiny/__init__.py @@ -170,7 +170,7 @@ def _notify_old_style(config): ARDUINO_VERSIONS = { "dev": (cv.Version(0, 0, 0), "https://github.com/libretiny-eu/libretiny.git"), "latest": (cv.Version(0, 0, 0), None), - "recommended": (cv.Version(1, 4, 1), None), + "recommended": (cv.Version(1, 5, 1), None), } diff --git a/esphome/components/rtl87xx/boards.py b/esphome/components/rtl87xx/boards.py index 6c29467f6e..e737767a56 100644 --- a/esphome/components/rtl87xx/boards.py +++ b/esphome/components/rtl87xx/boards.py @@ -36,6 +36,10 @@ RTL87XX_BOARDS = { "name": "T103_V1.0", "family": FAMILY_RTL8710B, }, + "t112-v1.1": { + "name": "T112_V1.1", + "family": FAMILY_RTL8710B, + }, "wr1": { "name": "WR1 Wi-Fi Module", "family": FAMILY_RTL8710B, @@ -125,7 +129,6 @@ RTL87XX_BOARD_PINS = { "PA23": 23, "PA29": 29, "PA30": 30, - "PWM0": 23, "PWM1": 15, "PWM2": 0, "PWM3": 12, @@ -136,9 +139,7 @@ RTL87XX_BOARD_PINS = { "RX2": 29, "SCK0": 18, "SCK1": 18, - "SCL0": 22, "SCL1": 18, - "SDA0": 30, "SDA1": 23, "TX0": 23, "TX2": 30, @@ -180,11 +181,9 @@ RTL87XX_BOARD_PINS = { "SERIAL2_RTS": 20, "SERIAL2_RX": 15, "SERIAL2_TX": 16, - "CS0": 15, "CTS1": 4, "CTS2": 19, "MISO0": 20, - "MOSI0": 19, "PA00": 0, "PA0": 0, "PA01": 1, @@ -203,23 +202,15 @@ RTL87XX_BOARD_PINS = { "PA18": 18, "PA19": 19, "PA20": 20, - "PWM0": 0, "PWM1": 1, - "PWM2": 14, - "PWM3": 3, - "PWM4": 16, "PWM5": 17, "PWM6": 18, - "PWM7": 13, "RTS2": 20, "RX0": 13, - "RX1": 0, "RX2": 15, - "SCK0": 3, "SCL0": 19, "SDA0": 3, "TX0": 14, - "TX1": 1, "TX2": 16, "D0": 17, "D1": 18, @@ -294,7 +285,6 @@ RTL87XX_BOARD_PINS = { "PA23": 23, "PA29": 29, "PA30": 30, - "PWM0": 23, "PWM1": 15, "PWM2": 0, "PWM3": 12, @@ -305,9 +295,7 @@ RTL87XX_BOARD_PINS = { "RX2": 29, "SCK0": 18, "SCK1": 18, - "SCL0": 29, "SCL1": 18, - "SDA0": 30, "SDA1": 23, "TX0": 23, "TX2": 30, @@ -390,7 +378,6 @@ RTL87XX_BOARD_PINS = { "PA23": 23, "PA29": 29, "PA30": 30, - "PWM0": 23, "PWM1": 15, "PWM2": 0, "PWM3": 12, @@ -401,9 +388,7 @@ RTL87XX_BOARD_PINS = { "RX2": 29, "SCK0": 18, "SCK1": 18, - "SCL0": 29, "SCL1": 18, - "SDA0": 30, "SDA1": 23, "TX0": 23, "TX2": 30, @@ -485,7 +470,6 @@ RTL87XX_BOARD_PINS = { "PA23": 23, "PA29": 29, "PA30": 30, - "PWM0": 23, "PWM1": 15, "PWM2": 0, "PWM3": 12, @@ -496,9 +480,7 @@ RTL87XX_BOARD_PINS = { "RX2": 29, "SCK0": 18, "SCK1": 18, - "SCL0": 29, "SCL1": 18, - "SDA0": 30, "SDA1": 23, "TX0": 23, "TX2": 30, @@ -560,7 +542,6 @@ RTL87XX_BOARD_PINS = { "CTS0": 10, "CTS1": 4, "CTS2": 19, - "MISO0": 20, "MOSI0": 19, "PA00": 0, "PA0": 0, @@ -591,23 +572,13 @@ RTL87XX_BOARD_PINS = { "PA20": 20, "PA23": 23, "PWM0": 20, - "PWM1": 12, - "PWM2": 14, - "PWM3": 15, - "PWM4": 16, "PWM5": 17, "PWM6": 18, "PWM7": 23, "RTS0": 9, "RTS2": 20, - "RX0": 13, - "RX1": 2, "RX2": 15, "SCK0": 16, - "SCL0": 19, - "SDA0": 20, - "TX0": 14, - "TX1": 3, "TX2": 16, "D0": 0, "D1": 1, @@ -652,7 +623,6 @@ RTL87XX_BOARD_PINS = { "PA23": 23, "PA29": 29, "PA30": 30, - "PWM0": 14, "PWM1": 15, "PWM2": 0, "PWM3": 12, @@ -720,7 +690,6 @@ RTL87XX_BOARD_PINS = { "PA23": 23, "PA29": 29, "PA30": 30, - "PWM0": 23, "PWM1": 15, "PWM2": 0, "PWM3": 12, @@ -731,9 +700,7 @@ RTL87XX_BOARD_PINS = { "RX2": 29, "SCK0": 18, "SCK1": 18, - "SCL0": 29, "SCL1": 18, - "SDA0": 30, "SDA1": 23, "TX0": 23, "TX2": 30, @@ -751,6 +718,75 @@ RTL87XX_BOARD_PINS = { "A0": 19, "A1": 41, }, + "t112-v1.1": { + "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": 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": 30, + "PWM5": 22, + "RTS0": 22, + "RX0": 18, + "RX2": 29, + "SCK0": 18, + "SCK1": 18, + "SCL1": 18, + "SDA1": 23, + "TX0": 23, + "TX2": 30, + "D0": 29, + "D1": 19, + "D2": 15, + "D3": 14, + "D4": 0, + "D5": 5, + "D6": 18, + "D7": 12, + "D8": 23, + "D9": 22, + "D10": 30, + "A0": 19, + }, "wr1": { "SPI0_CS": 19, "SPI0_MISO": 22, @@ -793,7 +829,6 @@ RTL87XX_BOARD_PINS = { "PA23": 23, "PA29": 29, "PA30": 30, - "PWM0": 14, "PWM1": 15, "PWM2": 0, "PWM4": 29, @@ -803,9 +838,7 @@ RTL87XX_BOARD_PINS = { "RX2": 29, "SCK0": 18, "SCK1": 18, - "SCL0": 22, "SCL1": 18, - "SDA0": 19, "SDA1": 23, "TX0": 23, "TX2": 30, @@ -863,7 +896,6 @@ RTL87XX_BOARD_PINS = { "PA23": 23, "PA29": 29, "PA30": 30, - "PWM0": 14, "PWM1": 15, "PWM3": 12, "PWM4": 29, @@ -873,9 +905,7 @@ RTL87XX_BOARD_PINS = { "RX2": 29, "SCK0": 18, "SCK1": 18, - "SCL0": 22, "SCL1": 18, - "SDA0": 19, "SDA1": 23, "TX0": 23, "TX2": 30, @@ -915,7 +945,6 @@ RTL87XX_BOARD_PINS = { "PA23": 23, "PA29": 29, "PA30": 30, - "PWM0": 14, "PWM1": 15, "PWM2": 0, "PWM3": 12, @@ -969,7 +998,6 @@ RTL87XX_BOARD_PINS = { "PA23": 23, "PA29": 29, "PA30": 30, - "PWM0": 14, "PWM1": 15, "PWM3": 12, "PWM4": 29, @@ -979,7 +1007,6 @@ RTL87XX_BOARD_PINS = { "SCK1": 18, "SCL0": 29, "SCL1": 18, - "SDA0": 30, "SDA1": 23, "TX0": 23, "TX2": 30, @@ -1083,7 +1110,6 @@ RTL87XX_BOARD_PINS = { "PA23": 23, "PA29": 29, "PA30": 30, - "PWM0": 23, "PWM1": 15, "PWM2": 0, "PWM3": 12, @@ -1094,9 +1120,7 @@ RTL87XX_BOARD_PINS = { "RX2": 29, "SCK0": 18, "SCK1": 18, - "SCL0": 29, "SCL1": 18, - "SDA0": 30, "SDA1": 23, "TX0": 23, "TX2": 30, @@ -1157,7 +1181,6 @@ RTL87XX_BOARD_PINS = { "PA23": 23, "PA29": 29, "PA30": 30, - "PWM0": 23, "PWM1": 15, "PWM2": 0, "PWM3": 12, @@ -1168,9 +1191,7 @@ RTL87XX_BOARD_PINS = { "RX2": 29, "SCK0": 18, "SCK1": 18, - "SCL0": 22, "SCL1": 18, - "SDA0": 19, "SDA1": 23, "TX0": 23, "TX2": 30, @@ -1231,7 +1252,6 @@ RTL87XX_BOARD_PINS = { "PA23": 23, "PA29": 29, "PA30": 30, - "PWM0": 23, "PWM1": 15, "PWM2": 0, "PWM3": 12, @@ -1242,9 +1262,7 @@ RTL87XX_BOARD_PINS = { "RX2": 29, "SCK0": 18, "SCK1": 18, - "SCL0": 29, "SCL1": 18, - "SDA0": 30, "SDA1": 23, "TX0": 23, "TX2": 30, @@ -1305,7 +1323,6 @@ RTL87XX_BOARD_PINS = { "PA23": 23, "PA29": 29, "PA30": 30, - "PWM0": 23, "PWM1": 15, "PWM2": 0, "PWM3": 12, @@ -1316,9 +1333,7 @@ RTL87XX_BOARD_PINS = { "RX2": 29, "SCK0": 18, "SCK1": 18, - "SCL0": 22, "SCL1": 18, - "SDA0": 19, "SDA1": 23, "TX0": 23, "TX2": 30, @@ -1359,7 +1374,6 @@ RTL87XX_BOARD_PINS = { "PA23": 23, "PA29": 29, "PA30": 30, - "PWM0": 23, "PWM1": 15, "PWM2": 0, "PWM3": 12, From 270fb5e7ac24cfea3841e8e1f173a308c5437d2e Mon Sep 17 00:00:00 2001 From: Mat931 <49403702+Mat931@users.noreply.github.com> Date: Mon, 8 Apr 2024 19:21:51 +0000 Subject: [PATCH 1203/2101] Internal temperature: Support Beken platform (#6491) --- .../internal_temperature/internal_temperature.cpp | 15 +++++++++++++++ esphome/components/internal_temperature/sensor.py | 3 ++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/esphome/components/internal_temperature/internal_temperature.cpp b/esphome/components/internal_temperature/internal_temperature.cpp index a387708263..255d95f6f8 100644 --- a/esphome/components/internal_temperature/internal_temperature.cpp +++ b/esphome/components/internal_temperature/internal_temperature.cpp @@ -14,6 +14,11 @@ uint8_t temprature_sens_read(); #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 namespace esphome { namespace internal_temperature { @@ -46,6 +51,16 @@ void InternalTemperatureSensor::update() { 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); +#ifdef USE_LIBRETINY_VARIANT_BK7231T + temperature = raw * 0.04f; +#else + temperature = raw * 0.128f; +#endif // USE_LIBRETINY_VARIANT_BK7231T +#endif // USE_BK72XX if (success && std::isfinite(temperature)) { this->publish_state(temperature); } else { diff --git a/esphome/components/internal_temperature/sensor.py b/esphome/components/internal_temperature/sensor.py index 2daf816538..809d7a40b9 100644 --- a/esphome/components/internal_temperature/sensor.py +++ b/esphome/components/internal_temperature/sensor.py @@ -14,6 +14,7 @@ from esphome.const import ( KEY_FRAMEWORK_VERSION, PLATFORM_ESP32, PLATFORM_RP2040, + PLATFORM_BK72XX, ) from esphome.core import CORE @@ -51,7 +52,7 @@ 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]), + cv.only_on([PLATFORM_ESP32, PLATFORM_RP2040, PLATFORM_BK72XX]), validate_config, ) From 708d5034cb5eb92654056c546bdb1e5c0b25ecb4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Apr 2024 09:48:04 +1200 Subject: [PATCH 1204/2101] Bump docker/setup-buildx-action from 3.2.0 to 3.3.0 (#6502) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-docker.yml | 2 +- .github/workflows/release.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-docker.yml b/.github/workflows/ci-docker.yml index d8fd4efa0e..6063d1e052 100644 --- a/.github/workflows/ci-docker.yml +++ b/.github/workflows/ci-docker.yml @@ -46,7 +46,7 @@ jobs: with: python-version: "3.9" - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3.2.0 + uses: docker/setup-buildx-action@v3.3.0 - name: Set up QEMU uses: docker/setup-qemu-action@v3.0.0 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index cb7defc2b0..7c0ec0270b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -84,7 +84,7 @@ jobs: python-version: "3.9" - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3.2.0 + uses: docker/setup-buildx-action@v3.3.0 - name: Set up QEMU if: matrix.platform != 'linux/amd64' uses: docker/setup-qemu-action@v3.0.0 @@ -162,7 +162,7 @@ jobs: name: digests-${{ matrix.image.target }}-${{ matrix.registry }} path: /tmp/digests - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3.2.0 + uses: docker/setup-buildx-action@v3.3.0 - name: Log in to docker hub if: matrix.registry == 'dockerhub' From efc9fd060d3f46d7a843fd0dfc523910075ccca9 Mon Sep 17 00:00:00 2001 From: fariouche Date: Tue, 9 Apr 2024 00:17:51 +0200 Subject: [PATCH 1205/2101] add support for Tuya pink version of miflora (#5402) --- CODEOWNERS | 1 + .../components/xiaomi_hhccjcy10/__init__.py | 1 + esphome/components/xiaomi_hhccjcy10/sensor.py | 96 +++++++++++++++++++ .../xiaomi_hhccjcy10/xiaomi_hhccjcy10.cpp | 68 +++++++++++++ .../xiaomi_hhccjcy10/xiaomi_hhccjcy10.h | 38 ++++++++ tests/test2.yaml | 12 +++ 6 files changed, 216 insertions(+) create mode 100644 esphome/components/xiaomi_hhccjcy10/__init__.py create mode 100644 esphome/components/xiaomi_hhccjcy10/sensor.py create mode 100644 esphome/components/xiaomi_hhccjcy10/xiaomi_hhccjcy10.cpp create mode 100644 esphome/components/xiaomi_hhccjcy10/xiaomi_hhccjcy10.h diff --git a/CODEOWNERS b/CODEOWNERS index fafbaae6c6..d2a86cd3d9 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -404,6 +404,7 @@ esphome/components/wireguard/* @droscy @lhoracek @thomas0bernard esphome/components/wl_134/* @hobbypunk90 esphome/components/x9c/* @EtienneMD esphome/components/xgzp68xx/* @gcormier +esphome/components/xiaomi_hhccjcy10/* @fariouche esphome/components/xiaomi_lywsd03mmc/* @ahpohl esphome/components/xiaomi_mhoc303/* @drug123 esphome/components/xiaomi_mhoc401/* @vevsvevs diff --git a/esphome/components/xiaomi_hhccjcy10/__init__.py b/esphome/components/xiaomi_hhccjcy10/__init__.py new file mode 100644 index 0000000000..d47cef13c6 --- /dev/null +++ b/esphome/components/xiaomi_hhccjcy10/__init__.py @@ -0,0 +1 @@ +CODEOWNERS = ["@fariouche"] diff --git a/esphome/components/xiaomi_hhccjcy10/sensor.py b/esphome/components/xiaomi_hhccjcy10/sensor.py new file mode 100644 index 0000000000..4f77fa8103 --- /dev/null +++ b/esphome/components/xiaomi_hhccjcy10/sensor.py @@ -0,0 +1,96 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import sensor, esp32_ble_tracker +from esphome.const import ( + CONF_MAC_ADDRESS, + CONF_TEMPERATURE, + DEVICE_CLASS_ILLUMINANCE, + DEVICE_CLASS_TEMPERATURE, + ENTITY_CATEGORY_DIAGNOSTIC, + ICON_WATER_PERCENT, + STATE_CLASS_MEASUREMENT, + UNIT_CELSIUS, + UNIT_PERCENT, + CONF_ID, + CONF_MOISTURE, + CONF_ILLUMINANCE, + UNIT_LUX, + CONF_CONDUCTIVITY, + UNIT_MICROSIEMENS_PER_CENTIMETER, + ICON_FLOWER, + DEVICE_CLASS_BATTERY, + CONF_BATTERY_LEVEL, +) + +DEPENDENCIES = ["esp32_ble_tracker"] + +xiaomi_hhccjcy10_ns = cg.esphome_ns.namespace("xiaomi_hhccjcy10") +XiaomiHHCCJCY10 = xiaomi_hhccjcy10_ns.class_( + "XiaomiHHCCJCY10", esp32_ble_tracker.ESPBTDeviceListener, cg.Component +) + +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(XiaomiHHCCJCY10), + cv.Required(CONF_MAC_ADDRESS): cv.mac_address, + 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_MOISTURE): sensor.sensor_schema( + unit_of_measurement=UNIT_PERCENT, + icon=ICON_WATER_PERCENT, + accuracy_decimals=0, + 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, + ), + cv.Optional(CONF_CONDUCTIVITY): sensor.sensor_schema( + unit_of_measurement=UNIT_MICROSIEMENS_PER_CENTIMETER, + icon=ICON_FLOWER, + accuracy_decimals=0, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_BATTERY_LEVEL): sensor.sensor_schema( + unit_of_measurement=UNIT_PERCENT, + accuracy_decimals=0, + device_class=DEVICE_CLASS_BATTERY, + state_class=STATE_CLASS_MEASUREMENT, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + ), + } + ) + .extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA) + .extend(cv.COMPONENT_SCHEMA) +) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + 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 temperature_config := config.get(CONF_TEMPERATURE): + sens = await sensor.new_sensor(temperature_config) + cg.add(var.set_temperature(sens)) + if moisture_config := config.get(CONF_MOISTURE): + sens = await sensor.new_sensor(moisture_config) + cg.add(var.set_moisture(sens)) + if illuminance_config := config.get(CONF_ILLUMINANCE): + sens = await sensor.new_sensor(illuminance_config) + cg.add(var.set_illuminance(sens)) + if conductivity_config := config.get(CONF_CONDUCTIVITY): + sens = await sensor.new_sensor(conductivity_config) + cg.add(var.set_conductivity(sens)) + if battery_level_config := config.get(CONF_BATTERY_LEVEL): + sens = await sensor.new_sensor(battery_level_config) + cg.add(var.set_battery_level(sens)) diff --git a/esphome/components/xiaomi_hhccjcy10/xiaomi_hhccjcy10.cpp b/esphome/components/xiaomi_hhccjcy10/xiaomi_hhccjcy10.cpp new file mode 100644 index 0000000000..45d4cceb52 --- /dev/null +++ b/esphome/components/xiaomi_hhccjcy10/xiaomi_hhccjcy10.cpp @@ -0,0 +1,68 @@ +#include "xiaomi_hhccjcy10.h" +#include "esphome/core/log.h" +#include "esphome/core/helpers.h" + +#ifdef USE_ESP32 + +namespace esphome { +namespace xiaomi_hhccjcy10 { + +static const char *const TAG = "xiaomi_hhccjcy10"; + +void XiaomiHHCCJCY10::dump_config() { + ESP_LOGCONFIG(TAG, "Xiaomi HHCCJCY10"); + LOG_SENSOR(" ", "Temperature", this->temperature_); + LOG_SENSOR(" ", "Moisture", this->moisture_); + LOG_SENSOR(" ", "Conductivity", this->conductivity_); + LOG_SENSOR(" ", "Illuminance", this->illuminance_); + LOG_SENSOR(" ", "Battery Level", this->battery_level_); +} + +bool XiaomiHHCCJCY10::parse_device(const esp32_ble_tracker::ESPBTDevice &device) { + if (device.address_uint64() != this->address_) { + ESP_LOGVV(TAG, "parse_device(): unknown MAC address."); + return false; + } + ESP_LOGVV(TAG, "parse_device(): MAC address %s found.", device.address_str().c_str()); + + bool success = false; + for (auto &service_data : device.get_service_datas()) { + if (!service_data.uuid.contains(0x50, 0xFD)) { + ESP_LOGVV(TAG, "no tuya service data UUID."); + continue; + } + if (service_data.data.size() != 9) { // tuya alternate between two service data + continue; + } + const uint8_t *data = service_data.data.data(); + + if (this->temperature_ != nullptr) { + const int16_t temperature = encode_uint16(data[1], data[2]); + this->temperature_->publish_state((float) temperature / 10.0f); + } + + if (this->moisture_ != nullptr) + this->moisture_->publish_state(data[0]); + + if (this->conductivity_ != nullptr) { + const uint16_t conductivity = encode_uint16(data[7], data[8]); + this->conductivity_->publish_state((float) conductivity); + } + + if (this->illuminance_ != nullptr) { + const uint32_t illuminance = encode_uint24(data[3], data[4], data[5]); + this->illuminance_->publish_state((float) illuminance); + } + + if (this->battery_level_ != nullptr) + this->battery_level_->publish_state(data[6]); + success = true; + } + + return success; +} + +} // namespace xiaomi_hhccjcy10 +} // namespace esphome + +#endif diff --git a/esphome/components/xiaomi_hhccjcy10/xiaomi_hhccjcy10.h b/esphome/components/xiaomi_hhccjcy10/xiaomi_hhccjcy10.h new file mode 100644 index 0000000000..bc1e580ce4 --- /dev/null +++ b/esphome/components/xiaomi_hhccjcy10/xiaomi_hhccjcy10.h @@ -0,0 +1,38 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/components/sensor/sensor.h" +#include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h" + +#ifdef USE_ESP32 + +namespace esphome { +namespace xiaomi_hhccjcy10 { + +class XiaomiHHCCJCY10 : public Component, public esp32_ble_tracker::ESPBTDeviceListener { + public: + void set_address(uint64_t address) { this->address_ = address; } + + bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override; + + void dump_config() override; + float get_setup_priority() const override { return setup_priority::DATA; } + void set_temperature(sensor::Sensor *temperature) { this->temperature_ = temperature; } + void set_moisture(sensor::Sensor *moisture) { this->moisture_ = moisture; } + void set_conductivity(sensor::Sensor *conductivity) { this->conductivity_ = conductivity; } + void set_illuminance(sensor::Sensor *illuminance) { this->illuminance_ = illuminance; } + void set_battery_level(sensor::Sensor *battery_level) { this->battery_level_ = battery_level; } + + protected: + uint64_t address_; + sensor::Sensor *temperature_{nullptr}; + sensor::Sensor *moisture_{nullptr}; + sensor::Sensor *conductivity_{nullptr}; + sensor::Sensor *illuminance_{nullptr}; + sensor::Sensor *battery_level_{nullptr}; +}; + +} // namespace xiaomi_hhccjcy10 +} // namespace esphome + +#endif diff --git a/tests/test2.yaml b/tests/test2.yaml index a1e310be9c..2fdef72c08 100644 --- a/tests/test2.yaml +++ b/tests/test2.yaml @@ -203,6 +203,18 @@ sensor: name: Xiaomi HHCCJCY01 Soil Conductivity battery_level: name: Xiaomi HHCCJCY01 Battery Level + - platform: xiaomi_hhccjcy10 + mac_address: DD:25:6D:E4:FF:8F + temperature: + name: "Xiaomi HHCCJCY10 Temperature" + moisture: + name: "Xiaomi HHCCJCY10 Moisture" + illuminance: + name: "Xiaomi HHCCJCY10 Illuminance" + conductivity: + name: "Xiaomi HHCCJCY10 Soil Conductivity" + battery_level: + name: "Xiaomi HHCCJCY10 Battery Level" - platform: xiaomi_lywsdcgq mac_address: 7A:80:8E:19:36:BA temperature: From 16d154e2e5ec31957f233173dfcf55b37eead1c8 Mon Sep 17 00:00:00 2001 From: cvwillegen Date: Tue, 9 Apr 2024 03:07:04 +0200 Subject: [PATCH 1206/2101] Add MAC address to WiFi config reply (#6489) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- .../components/captive_portal/captive_index.h | 190 +++++++++--------- .../captive_portal/captive_portal.cpp | 2 +- 2 files changed, 97 insertions(+), 95 deletions(-) diff --git a/esphome/components/captive_portal/captive_index.h b/esphome/components/captive_portal/captive_index.h index 56071f3d2a..d262a89b09 100644 --- a/esphome/components/captive_portal/captive_index.h +++ b/esphome/components/captive_portal/captive_index.h @@ -6,100 +6,102 @@ namespace esphome { namespace captive_portal { const uint8_t INDEX_GZ[] PROGMEM = { - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xdd, 0x58, 0x5b, 0x8f, 0xdb, 0x36, 0x16, 0x7e, 0xef, - 0xaf, 0xe0, 0x2a, 0x49, 0x2d, 0x37, 0x23, 0xea, 0x66, 0xf9, 0x2a, 0xa9, 0x48, 0xb2, 0x29, 0x5a, 0x20, 0x69, 0x03, - 0xcc, 0xb4, 0xfb, 0x10, 0x04, 0x18, 0x5a, 0xa2, 0x2c, 0x66, 0x24, 0x4a, 0x15, 0xe9, 0x5b, 0x0c, 0xef, 0x6f, 0xdf, - 0x43, 0x52, 0xf6, 0x38, 0xb3, 0x99, 0x05, 0x52, 0xec, 0x62, 0xd1, 0x4e, 0x26, 0x1c, 0x92, 0x3a, 0xd7, 0x4f, 0x3c, - 0x17, 0x2a, 0xfe, 0x5b, 0xde, 0x64, 0x72, 0xdf, 0x52, 0x54, 0xca, 0xba, 0x4a, 0x63, 0x35, 0xa2, 0x8a, 0xf0, 0x55, - 0x42, 0x39, 0xac, 0x28, 0xc9, 0xd3, 0xb8, 0xa6, 0x92, 0xa0, 0xac, 0x24, 0x9d, 0xa0, 0x32, 0xf9, 0xf5, 0xe6, 0x07, - 0x67, 0x8a, 0xdc, 0x34, 0xae, 0x18, 0xbf, 0x43, 0x1d, 0xad, 0x12, 0x96, 0x35, 0x1c, 0x95, 0x1d, 0x2d, 0x92, 0x9c, - 0x48, 0x32, 0x67, 0x35, 0x59, 0x51, 0x45, 0xa0, 0xd9, 0x38, 0xa9, 0x69, 0xb2, 0x61, 0x74, 0xdb, 0x36, 0x9d, 0x44, - 0x40, 0x29, 0x29, 0x97, 0x89, 0xb5, 0x65, 0xb9, 0x2c, 0x93, 0x9c, 0x6e, 0x58, 0x46, 0x1d, 0xbd, 0xb8, 0x62, 0x9c, - 0x49, 0x46, 0x2a, 0x47, 0x64, 0xa4, 0xa2, 0x89, 0x7f, 0xb5, 0x16, 0xb4, 0xd3, 0x0b, 0xb2, 0x84, 0x35, 0x6f, 0x2c, - 0x10, 0x29, 0xb2, 0x8e, 0xb5, 0x12, 0x29, 0x7b, 0x93, 0xba, 0xc9, 0xd7, 0x15, 0x4d, 0x5d, 0x97, 0x08, 0xb0, 0x4b, - 0xb8, 0x8c, 0xe7, 0x74, 0x87, 0xa7, 0xb3, 0x68, 0x32, 0x9e, 0xe6, 0x13, 0xfc, 0x51, 0x7c, 0x03, 0x9e, 0xad, 0x6b, - 0x50, 0x87, 0xab, 0x26, 0x23, 0x92, 0x35, 0x1c, 0x0b, 0x4a, 0xba, 0xac, 0x4c, 0x92, 0xc4, 0xfa, 0x5e, 0x90, 0x0d, - 0xb5, 0xbe, 0xfd, 0xd6, 0x3e, 0x13, 0xad, 0xa8, 0x7c, 0x5d, 0x51, 0x35, 0x15, 0x2f, 0xf7, 0x37, 0x64, 0xf5, 0x33, - 0x58, 0x6e, 0x5b, 0x44, 0xb0, 0x9c, 0x5a, 0xc3, 0xf7, 0xde, 0x07, 0x2c, 0xe4, 0xbe, 0xa2, 0x38, 0x67, 0xa2, 0xad, - 0xc8, 0x3e, 0xb1, 0x96, 0x20, 0xf5, 0xce, 0x1a, 0x2e, 0x8a, 0x35, 0xcf, 0x94, 0x70, 0x24, 0x6c, 0x3a, 0x3c, 0x54, - 0x14, 0xcc, 0x4b, 0xde, 0x12, 0x59, 0xe2, 0x9a, 0xec, 0x6c, 0x33, 0x61, 0xdc, 0x0e, 0xbe, 0xb3, 0xe9, 0x73, 0xdf, - 0xf3, 0x86, 0x57, 0x7a, 0xf0, 0x86, 0x2e, 0xfc, 0x5d, 0x74, 0x54, 0xae, 0x3b, 0x8e, 0x88, 0x7d, 0x1b, 0xb7, 0x40, - 0x89, 0xf2, 0xc4, 0xaa, 0xfd, 0x00, 0x7b, 0xde, 0x14, 0xf9, 0x33, 0x1c, 0x44, 0x8e, 0xef, 0xe3, 0xd0, 0xf1, 0xa3, - 0x6c, 0xe2, 0x44, 0xc8, 0x1f, 0xc1, 0x10, 0x04, 0x38, 0x42, 0xde, 0x27, 0x0b, 0x15, 0xac, 0xaa, 0x12, 0x8b, 0x37, - 0x9c, 0x5a, 0x48, 0xc8, 0xae, 0xb9, 0xa3, 0x89, 0x95, 0xad, 0xbb, 0x0e, 0xec, 0x7f, 0xd5, 0x54, 0x4d, 0x07, 0x70, - 0x7d, 0x83, 0x3e, 0xfb, 0xf9, 0x6a, 0x15, 0xb2, 0x23, 0x5c, 0x14, 0x4d, 0x57, 0x27, 0x96, 0x7e, 0x29, 0xf6, 0xd3, - 0x83, 0x3c, 0x22, 0x35, 0x0c, 0x2f, 0x1e, 0x3a, 0x4d, 0xc7, 0x56, 0x8c, 0x27, 0x96, 0x1f, 0x20, 0x7f, 0x0a, 0x6a, - 0x6f, 0x87, 0xc7, 0x33, 0x26, 0x44, 0x61, 0xd2, 0x7b, 0xd9, 0xd8, 0xef, 0x6f, 0x63, 0xb1, 0x59, 0xa1, 0x5d, 0x5d, - 0x71, 0x91, 0x58, 0xa5, 0x94, 0xed, 0xdc, 0x75, 0xb7, 0xdb, 0x2d, 0xde, 0x86, 0xb8, 0xe9, 0x56, 0x6e, 0xe0, 0x79, - 0x9e, 0x0b, 0x14, 0x16, 0x32, 0xe7, 0xc3, 0x0a, 0x46, 0x16, 0x2a, 0x29, 0x5b, 0x95, 0x52, 0xcf, 0xd3, 0xa7, 0x07, - 0x7a, 0x8c, 0x15, 0x45, 0x7a, 0xfb, 0xe1, 0x42, 0x4b, 0x77, 0xa1, 0x85, 0x7e, 0x7f, 0x81, 0xe6, 0xe0, 0xad, 0x32, - 0x6a, 0x42, 0x02, 0x14, 0x20, 0x4f, 0xff, 0x0b, 0x1c, 0x35, 0xef, 0x57, 0xce, 0x83, 0x15, 0xba, 0x58, 0xc1, 0x5f, - 0xc0, 0x2f, 0xa8, 0xc7, 0xce, 0xec, 0xcc, 0xee, 0xab, 0xc7, 0x1b, 0xdf, 0xbb, 0xdf, 0x50, 0x3c, 0x3f, 0x8e, 0x2f, - 0xd7, 0x4e, 0xf0, 0x9b, 0x22, 0x50, 0xd8, 0x9f, 0x99, 0x9c, 0xa0, 0xf4, 0x7f, 0x1b, 0x93, 0x08, 0x45, 0xfd, 0x4e, - 0xe4, 0xa8, 0xf9, 0x79, 0xa5, 0x34, 0xa1, 0x68, 0x03, 0x54, 0xb5, 0x33, 0x76, 0x22, 0x12, 0xa2, 0xb0, 0x37, 0x09, - 0x66, 0xb0, 0x3d, 0x06, 0xe6, 0x8b, 0x3d, 0x27, 0xfc, 0x34, 0x50, 0x30, 0xcf, 0x2d, 0xeb, 0x1e, 0x83, 0xe6, 0x12, - 0x03, 0xfc, 0xb1, 0x81, 0x33, 0x67, 0x59, 0x80, 0x11, 0x95, 0x59, 0x69, 0x5b, 0x2e, 0x44, 0x5e, 0xc1, 0x56, 0x10, - 0x15, 0x0d, 0xb7, 0x86, 0x58, 0x96, 0x94, 0xdb, 0x27, 0x56, 0xc5, 0x48, 0xf5, 0x13, 0xfb, 0xe1, 0x13, 0x39, 0x3c, - 0x9c, 0xe3, 0x43, 0x32, 0x09, 0x71, 0x28, 0xb1, 0x8a, 0xe8, 0xab, 0xf3, 0xee, 0xb2, 0xc9, 0xf7, 0x8f, 0x84, 0x4e, - 0xe9, 0x9b, 0xb8, 0x61, 0x9c, 0xd3, 0xee, 0x86, 0xee, 0xe0, 0x1d, 0xfe, 0x83, 0xfd, 0xc0, 0xd0, 0xcf, 0x54, 0x6e, - 0x9b, 0xee, 0x4e, 0xcc, 0x91, 0xf5, 0xdc, 0x88, 0x5b, 0xa8, 0xa8, 0x61, 0x20, 0x9b, 0xb4, 0x02, 0x8b, 0x0a, 0x72, - 0x82, 0xed, 0x0f, 0x21, 0x7e, 0xda, 0x7b, 0x4b, 0xf8, 0xc9, 0xb9, 0xdb, 0x38, 0x67, 0x1b, 0x94, 0x55, 0x10, 0xf5, - 0x70, 0xfc, 0x8d, 0x28, 0x0b, 0xf5, 0x47, 0xbd, 0xe1, 0x19, 0x70, 0xdf, 0x25, 0xd6, 0x17, 0xa2, 0xfa, 0xe5, 0xfe, - 0xa7, 0xdc, 0x1e, 0x08, 0x88, 0xe7, 0xc1, 0x10, 0x6f, 0x48, 0xb5, 0xa6, 0x28, 0x41, 0xb2, 0x64, 0xe2, 0xde, 0xc0, - 0xc5, 0xa3, 0x6c, 0xad, 0xb8, 0x03, 0xae, 0x02, 0x1e, 0x0b, 0x7b, 0x68, 0x9d, 0x22, 0x2b, 0x26, 0x26, 0xef, 0x59, - 0x4f, 0xac, 0x07, 0x16, 0x39, 0x15, 0x2d, 0xa4, 0x75, 0x1f, 0x81, 0x4f, 0x0f, 0xc2, 0xe6, 0xb8, 0x03, 0xed, 0xc3, - 0xe3, 0x79, 0x33, 0x16, 0x2d, 0xe1, 0x0f, 0x19, 0x95, 0x81, 0xea, 0xa0, 0x43, 0xb2, 0x82, 0x99, 0x3a, 0xed, 0x40, - 0x74, 0x56, 0xe8, 0x92, 0xd3, 0xf4, 0xe9, 0xa1, 0x03, 0x89, 0x2a, 0x07, 0x9d, 0x25, 0xc6, 0x2e, 0x40, 0x93, 0xde, - 0x1e, 0x87, 0xf7, 0x7e, 0xfc, 0xbe, 0xa6, 0xdd, 0xfe, 0x9a, 0x56, 0x34, 0x93, 0x4d, 0x67, 0x5b, 0x4f, 0x40, 0x0b, - 0xbc, 0x7e, 0xed, 0xf0, 0x8f, 0x37, 0x6f, 0xdf, 0x24, 0x8d, 0xcd, 0x86, 0x57, 0x8f, 0x51, 0xab, 0x0c, 0xff, 0x1e, - 0x32, 0xfc, 0x3f, 0x93, 0x81, 0xca, 0xf1, 0x83, 0x0f, 0xc0, 0xaa, 0xfd, 0xbd, 0xbd, 0x4f, 0xf4, 0x2a, 0x18, 0x9f, - 0x43, 0x40, 0x5f, 0x29, 0x0f, 0x9d, 0x71, 0x34, 0x3c, 0x82, 0x7e, 0xb0, 0x00, 0xec, 0xd6, 0xb9, 0x1a, 0x72, 0xb6, - 0x4a, 0x9b, 0xe9, 0x77, 0x87, 0x65, 0xb3, 0x73, 0x04, 0xfb, 0xc4, 0xf8, 0x6a, 0xce, 0x78, 0x49, 0x3b, 0x26, 0x8f, - 0x60, 0x2e, 0xa4, 0xfd, 0x76, 0x2d, 0x0f, 0x2d, 0xc9, 0x73, 0xf5, 0x24, 0x6a, 0x77, 0x8b, 0x02, 0x8a, 0x84, 0xa2, - 0xa4, 0x73, 0x9f, 0xd6, 0x47, 0xf3, 0x5c, 0xe7, 0x83, 0xf9, 0x2c, 0x7a, 0x76, 0x54, 0x07, 0xee, 0x20, 0xe1, 0x65, - 0x39, 0xa4, 0x62, 0x2b, 0x3e, 0xcf, 0xc0, 0x70, 0xda, 0x19, 0xa6, 0x82, 0xd4, 0xac, 0xda, 0xcf, 0x05, 0x64, 0x26, - 0x07, 0xaa, 0x07, 0x2b, 0x8e, 0xcb, 0xb5, 0x94, 0x0d, 0x07, 0xdd, 0x5d, 0x4e, 0xbb, 0xb9, 0xb7, 0x30, 0x13, 0xa7, - 0x23, 0x39, 0x5b, 0x8b, 0x39, 0x0e, 0x3b, 0x5a, 0x2f, 0x96, 0x24, 0xbb, 0x5b, 0x75, 0xcd, 0x9a, 0xe7, 0x4e, 0xa6, - 0x32, 0xe7, 0xfc, 0x89, 0x5f, 0x90, 0x90, 0x66, 0x8b, 0x7e, 0x55, 0x14, 0xc5, 0x02, 0xa0, 0xa0, 0x8e, 0xc9, 0x44, - 0xf3, 0x00, 0x8f, 0x14, 0xdb, 0x85, 0x99, 0x38, 0x50, 0x1b, 0xc6, 0x46, 0x48, 0xeb, 0xcf, 0x16, 0x27, 0x77, 0xbc, - 0x05, 0xa4, 0x64, 0x01, 0x42, 0x5a, 0x88, 0x47, 0x30, 0xf3, 0x58, 0x13, 0xc6, 0x2f, 0xad, 0x57, 0xc7, 0x64, 0xd1, - 0x97, 0x14, 0x80, 0x45, 0xab, 0xd1, 0x85, 0x65, 0x01, 0x45, 0xc3, 0x14, 0xc6, 0x79, 0x30, 0xf6, 0xda, 0xdd, 0x11, - 0xf7, 0x07, 0xe4, 0x70, 0xa2, 0x2e, 0x2a, 0xba, 0x5b, 0x7c, 0x5c, 0x0b, 0xc9, 0x8a, 0xbd, 0xd3, 0x17, 0xd6, 0x39, - 0x1c, 0x16, 0x28, 0xa8, 0x4b, 0x20, 0xa5, 0x94, 0x2f, 0xb4, 0x0e, 0x87, 0x49, 0x5a, 0x8b, 0x1e, 0xa7, 0xb3, 0x18, - 0x7d, 0x40, 0x3f, 0x97, 0xf5, 0x9f, 0xa8, 0xd5, 0x59, 0x3c, 0xd4, 0xa4, 0x83, 0x44, 0xef, 0x2c, 0x1b, 0xc0, 0xb4, - 0x9e, 0x3b, 0x13, 0x78, 0x57, 0xfd, 0x96, 0x12, 0x06, 0x9e, 0x83, 0x99, 0xba, 0x5e, 0x9e, 0xf0, 0xf6, 0xdb, 0x1d, - 0x12, 0x4d, 0xc5, 0xf2, 0x9e, 0x4e, 0x93, 0x20, 0xef, 0x0c, 0x8f, 0x0f, 0xaf, 0x1b, 0xa9, 0xbd, 0x13, 0xd4, 0xa3, - 0x62, 0x4a, 0x7c, 0xef, 0x0b, 0x6f, 0x24, 0x2f, 0x8a, 0x60, 0x59, 0x9c, 0x91, 0x52, 0x65, 0xef, 0xc8, 0xfa, 0x53, - 0x11, 0x8c, 0x40, 0xc0, 0xe9, 0xdd, 0xc0, 0xfc, 0xc8, 0x74, 0x58, 0x1c, 0x2e, 0xa4, 0xe8, 0xa3, 0x3a, 0x5f, 0x77, - 0x95, 0x6d, 0x7d, 0xe1, 0xe8, 0x3e, 0x0b, 0x5f, 0xdd, 0x97, 0xa5, 0xc1, 0xe3, 0x65, 0x69, 0x80, 0x54, 0x23, 0xf3, - 0xb2, 0xd9, 0x25, 0x03, 0x5d, 0x20, 0x46, 0xf0, 0x3b, 0x78, 0x16, 0xbe, 0x06, 0xfe, 0xff, 0x4a, 0xbd, 0xf9, 0xc3, - 0xc5, 0xe6, 0x2b, 0x2a, 0xcd, 0x57, 0x56, 0x19, 0xe3, 0x9d, 0x72, 0x1e, 0x66, 0x50, 0x4e, 0x18, 0x16, 0x6c, 0xe5, - 0xff, 0x2f, 0xa0, 0xfd, 0x77, 0x1c, 0xc3, 0x17, 0xfe, 0x14, 0xcf, 0x90, 0x1e, 0x0c, 0x44, 0x38, 0x9c, 0xa2, 0xc9, - 0xab, 0x11, 0x1e, 0xf9, 0x48, 0xb5, 0x30, 0x63, 0x34, 0x81, 0x7e, 0x0f, 0xf9, 0x63, 0x1c, 0x4e, 0x60, 0x03, 0x05, - 0x3e, 0x8e, 0xde, 0x04, 0x21, 0x1e, 0x47, 0x40, 0x15, 0x78, 0x38, 0x0c, 0x90, 0xa1, 0x1d, 0xe3, 0x00, 0xc4, 0x29, - 0x92, 0xb0, 0x06, 0xa0, 0xb3, 0x10, 0x7b, 0x13, 0x10, 0x37, 0xc6, 0xde, 0x0c, 0x4f, 0xc7, 0x68, 0x8a, 0x27, 0x00, - 0x1d, 0x1e, 0x45, 0x95, 0x13, 0x61, 0x1f, 0xb6, 0xc3, 0x31, 0x99, 0xe2, 0x51, 0x88, 0xf4, 0x60, 0xe0, 0x98, 0x80, - 0x08, 0x07, 0x7b, 0xfe, 0x9b, 0x10, 0x07, 0x13, 0xd0, 0x3b, 0x1a, 0xbd, 0x00, 0xb1, 0xb3, 0x11, 0x32, 0xa3, 0x81, - 0x17, 0x14, 0x44, 0x8f, 0x81, 0x16, 0xfc, 0x75, 0x41, 0x03, 0x48, 0x7c, 0x14, 0xe2, 0x19, 0xc4, 0xae, 0xaf, 0xf8, - 0xcd, 0x68, 0x70, 0xf3, 0x7d, 0xe4, 0xfd, 0x61, 0xcc, 0xc2, 0xbf, 0x2e, 0x66, 0xbe, 0x42, 0x00, 0xa6, 0xa0, 0x1b, - 0xe4, 0x20, 0x3d, 0x18, 0xdd, 0xc0, 0x3c, 0x7d, 0x35, 0x43, 0x53, 0xe0, 0x1a, 0x4f, 0xd1, 0x0c, 0x45, 0x0a, 0x5d, - 0x60, 0x1f, 0x19, 0x26, 0x07, 0x98, 0xbe, 0x12, 0xc6, 0xd1, 0x9f, 0x18, 0xc6, 0xc7, 0x7c, 0xfa, 0x13, 0xbb, 0xf4, - 0xff, 0x48, 0x41, 0xd0, 0x8e, 0xe9, 0x36, 0x2c, 0x76, 0xcd, 0x95, 0x5e, 0x75, 0x51, 0x70, 0x43, 0x87, 0x6e, 0x04, - 0x2e, 0xf9, 0x3e, 0x62, 0x79, 0x52, 0xfa, 0xe9, 0x67, 0xdd, 0x39, 0x50, 0xfa, 0x69, 0xac, 0xcb, 0x79, 0x7a, 0x53, - 0x52, 0xf4, 0xfa, 0xfa, 0x1d, 0xdc, 0xca, 0xaa, 0x0a, 0xf1, 0x66, 0x0b, 0x97, 0xbf, 0x3d, 0x92, 0x8d, 0xba, 0xce, - 0x73, 0xe8, 0x15, 0xd5, 0x14, 0xee, 0x0d, 0xa8, 0x6f, 0x16, 0x30, 0xc6, 0xf1, 0xb2, 0x4b, 0xdf, 0x55, 0x94, 0x08, - 0x8a, 0x56, 0x6c, 0x43, 0x11, 0x93, 0xd0, 0x07, 0xd4, 0x14, 0x49, 0xa6, 0x86, 0x33, 0xa3, 0xa6, 0x83, 0x9e, 0x56, - 0x2b, 0x31, 0xdd, 0x30, 0x58, 0x02, 0x62, 0xd2, 0xbe, 0xed, 0x8d, 0xcb, 0xd0, 0x58, 0x75, 0x4d, 0xa5, 0x84, 0x8e, - 0x41, 0x59, 0x15, 0xa6, 0xb1, 0xba, 0x76, 0x22, 0xa2, 0x2f, 0x06, 0x89, 0xbb, 0x65, 0x05, 0x53, 0x97, 0xf9, 0x34, - 0xd6, 0xad, 0xa2, 0x92, 0xa0, 0xba, 0x15, 0xf3, 0xe5, 0x41, 0xcf, 0x2a, 0xca, 0x57, 0x70, 0x9b, 0x84, 0x77, 0x01, - 0xcd, 0x43, 0x46, 0xcb, 0xa6, 0x82, 0xe6, 0x24, 0xb9, 0xbe, 0xfe, 0xe9, 0xef, 0xea, 0x33, 0x85, 0x32, 0xe1, 0xcc, - 0x09, 0x7d, 0xbe, 0x61, 0x54, 0x93, 0x9e, 0x6f, 0x3c, 0x32, 0x1f, 0x1c, 0x5a, 0xe8, 0xd3, 0xc1, 0xbf, 0xfc, 0x33, - 0x29, 0xef, 0x4e, 0x9b, 0xbd, 0x24, 0xfd, 0x5f, 0x37, 0x9d, 0x86, 0x49, 0xac, 0x97, 0x35, 0x93, 0xe9, 0x35, 0x18, - 0x18, 0xbb, 0xe6, 0x01, 0x38, 0xa7, 0x1c, 0x30, 0xb4, 0x65, 0xcf, 0x03, 0x60, 0xff, 0x72, 0xf3, 0x02, 0xfd, 0xda, - 0xc2, 0x09, 0xa6, 0x06, 0x7b, 0xed, 0x65, 0x4d, 0x65, 0xd9, 0xe4, 0xc9, 0xbb, 0x5f, 0xae, 0x6f, 0xce, 0x1e, 0xaf, - 0x35, 0x11, 0xa2, 0x3c, 0x33, 0x1f, 0x42, 0xd6, 0x95, 0x64, 0x2d, 0xe9, 0xa4, 0x16, 0xeb, 0xa8, 0x10, 0x38, 0x79, - 0xa4, 0x9f, 0x17, 0xac, 0xa2, 0xc6, 0xa9, 0x9e, 0xd1, 0x4d, 0xd1, 0x97, 0x6c, 0x3c, 0xe9, 0x7e, 0x60, 0xa5, 0x6b, - 0x4e, 0x89, 0x6b, 0x8e, 0x8c, 0xab, 0x3f, 0x13, 0xfd, 0x0b, 0x65, 0x37, 0xa3, 0x8e, 0x36, 0x12, 0x00, 0x00}; + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xdd, 0x58, 0x69, 0x6f, 0xdc, 0x36, 0x1a, 0xfe, 0xde, + 0x5f, 0xc1, 0x2a, 0x49, 0x47, 0xd3, 0x58, 0xd4, 0x35, 0x9a, 0x53, 0x9a, 0xc2, 0xf1, 0xa6, 0x68, 0x81, 0xa4, 0x0d, + 0x60, 0xb7, 0xfd, 0x10, 0x04, 0x30, 0x47, 0xa2, 0x46, 0x8c, 0x25, 0x4a, 0x2b, 0x72, 0xae, 0x0c, 0x66, 0x7f, 0xfb, + 0xbe, 0x24, 0x35, 0xe3, 0xb1, 0x37, 0x5e, 0x6c, 0x8a, 0x2d, 0x8a, 0xd6, 0x71, 0x68, 0x1e, 0xef, 0xf9, 0x88, 0xef, + 0x21, 0xc5, 0x5f, 0x67, 0x75, 0x2a, 0x77, 0x0d, 0x45, 0x85, 0xac, 0xca, 0x79, 0xac, 0x46, 0x54, 0x12, 0xbe, 0x4c, + 0x28, 0x87, 0x15, 0x25, 0xd9, 0x3c, 0xae, 0xa8, 0x24, 0x28, 0x2d, 0x48, 0x2b, 0xa8, 0x4c, 0x7e, 0xb9, 0xf9, 0xde, + 0x19, 0x23, 0x77, 0x1e, 0x97, 0x8c, 0xdf, 0xa1, 0x96, 0x96, 0x09, 0x4b, 0x6b, 0x8e, 0x8a, 0x96, 0xe6, 0x49, 0x46, + 0x24, 0x99, 0xb2, 0x8a, 0x2c, 0xa9, 0x22, 0xd0, 0x6c, 0x9c, 0x54, 0x34, 0x59, 0x33, 0xba, 0x69, 0xea, 0x56, 0x22, + 0xa0, 0x94, 0x94, 0xcb, 0xc4, 0xda, 0xb0, 0x4c, 0x16, 0x49, 0x46, 0xd7, 0x2c, 0xa5, 0x8e, 0x5e, 0x5c, 0x30, 0xce, + 0x24, 0x23, 0xa5, 0x23, 0x52, 0x52, 0xd2, 0xc4, 0xbf, 0x58, 0x09, 0xda, 0xea, 0x05, 0x59, 0xc0, 0x9a, 0xd7, 0x16, + 0x88, 0x14, 0x69, 0xcb, 0x1a, 0x89, 0x94, 0xbd, 0x49, 0x55, 0x67, 0xab, 0x92, 0xce, 0x5d, 0x97, 0x08, 0xb0, 0x4b, + 0xb8, 0x8c, 0x67, 0x74, 0x8b, 0x87, 0x61, 0x98, 0x06, 0x64, 0x94, 0xe3, 0x8f, 0xe2, 0x2b, 0xf0, 0x6c, 0x55, 0x81, + 0x3a, 0x5c, 0xd6, 0x29, 0x91, 0xac, 0xe6, 0x58, 0x50, 0xd2, 0xa6, 0x45, 0x92, 0x24, 0xd6, 0x77, 0x82, 0xac, 0xa9, + 0xf5, 0xcd, 0x37, 0xf6, 0x89, 0x68, 0x49, 0xe5, 0xeb, 0x92, 0xaa, 0xa9, 0x78, 0xb5, 0xbb, 0x21, 0xcb, 0x9f, 0xc0, + 0x72, 0xdb, 0x22, 0x82, 0x65, 0xd4, 0xea, 0xbf, 0xf7, 0x3e, 0x60, 0x21, 0x77, 0x25, 0xc5, 0x19, 0x13, 0x4d, 0x49, + 0x76, 0x89, 0xb5, 0x00, 0xa9, 0x77, 0x56, 0x7f, 0x96, 0xaf, 0x78, 0xaa, 0x84, 0x23, 0x61, 0xd3, 0xfe, 0xbe, 0xa4, + 0x60, 0x5e, 0xf2, 0x96, 0xc8, 0x02, 0x57, 0x64, 0x6b, 0x9b, 0x09, 0xe3, 0x76, 0xf0, 0xad, 0x4d, 0x5f, 0xfa, 0x9e, + 0xd7, 0xbf, 0xd0, 0x83, 0xd7, 0x77, 0xe1, 0xef, 0xac, 0xa5, 0x72, 0xd5, 0x72, 0x44, 0xec, 0xdb, 0xb8, 0x01, 0x4a, + 0x94, 0x25, 0x56, 0xe5, 0x07, 0xd8, 0xf3, 0xc6, 0xc8, 0x9f, 0xe0, 0x20, 0x72, 0x7c, 0x1f, 0x87, 0x8e, 0x1f, 0xa5, + 0x23, 0x27, 0x42, 0xfe, 0x00, 0x86, 0x20, 0xc0, 0x11, 0xf2, 0x3e, 0x59, 0x28, 0x67, 0x65, 0x99, 0x58, 0xbc, 0xe6, + 0xd4, 0x42, 0x42, 0xb6, 0xf5, 0x1d, 0x4d, 0xac, 0x74, 0xd5, 0xb6, 0x60, 0xff, 0x55, 0x5d, 0xd6, 0x2d, 0xc0, 0xf5, + 0x15, 0x7a, 0xf0, 0xf3, 0xc5, 0x2a, 0x64, 0x4b, 0xb8, 0xc8, 0xeb, 0xb6, 0x4a, 0x2c, 0xfd, 0x50, 0xec, 0xe7, 0x7b, + 0x79, 0x40, 0x6a, 0xe8, 0x9f, 0x1d, 0x3a, 0x75, 0xcb, 0x96, 0x8c, 0x27, 0x96, 0x1f, 0x20, 0x7f, 0x0c, 0x6a, 0x6f, + 0xfb, 0x87, 0x13, 0x26, 0x44, 0x61, 0xd2, 0x79, 0x59, 0xdb, 0xef, 0x6f, 0x63, 0xb1, 0x5e, 0xa2, 0x6d, 0x55, 0x72, + 0x91, 0x58, 0x85, 0x94, 0xcd, 0xd4, 0x75, 0x37, 0x9b, 0x0d, 0xde, 0x84, 0xb8, 0x6e, 0x97, 0x6e, 0xe0, 0x79, 0x9e, + 0x0b, 0x14, 0x16, 0x32, 0xf7, 0xc3, 0x0a, 0x06, 0x16, 0x2a, 0x28, 0x5b, 0x16, 0x52, 0xcf, 0xe7, 0xcf, 0xf7, 0xf4, + 0x10, 0x2b, 0x8a, 0xf9, 0xed, 0x87, 0x33, 0x2d, 0xec, 0x4c, 0x0b, 0xfd, 0xee, 0x0c, 0xcd, 0xde, 0x5b, 0x65, 0xd4, + 0x88, 0x04, 0x28, 0x40, 0x9e, 0xfe, 0x17, 0x38, 0x6a, 0xde, 0xad, 0x9c, 0x47, 0x2b, 0x74, 0xb6, 0x82, 0xbf, 0x80, + 0x5f, 0x50, 0x0d, 0x9d, 0xc9, 0x89, 0xdd, 0x57, 0xc7, 0x6b, 0xdf, 0xbb, 0xdf, 0x50, 0x3c, 0x3f, 0x0c, 0xcf, 0xd7, + 0x4e, 0xf0, 0xab, 0x22, 0x50, 0xd8, 0x9f, 0x98, 0x9c, 0xa0, 0xf0, 0x7f, 0x1d, 0x92, 0x08, 0x45, 0xdd, 0x4e, 0xe4, + 0xa8, 0xf9, 0x69, 0xa5, 0x34, 0xa1, 0x68, 0x0d, 0x54, 0x95, 0x33, 0x74, 0x22, 0x12, 0xa2, 0xb0, 0x33, 0x09, 0x66, + 0xb0, 0x3d, 0x04, 0xe6, 0xb3, 0x3d, 0x27, 0xfc, 0xd4, 0x53, 0x30, 0x4f, 0x2d, 0xeb, 0x1e, 0x83, 0xfa, 0x1c, 0x03, + 0xfc, 0xb1, 0x86, 0x3b, 0x67, 0x59, 0x80, 0x11, 0x95, 0x69, 0x61, 0x5b, 0x2e, 0x44, 0x5e, 0xce, 0x96, 0x10, 0x15, + 0x35, 0xb7, 0xfa, 0x58, 0x16, 0x94, 0xdb, 0x47, 0x56, 0xc5, 0x48, 0xf5, 0x89, 0xfd, 0xf8, 0x44, 0xf6, 0xf7, 0xa7, + 0xf8, 0x90, 0x4c, 0x42, 0x1c, 0x4a, 0xac, 0x22, 0xfa, 0xe2, 0xb4, 0xbb, 0xa8, 0xb3, 0xdd, 0x13, 0xa1, 0x53, 0xf8, + 0x26, 0x6e, 0x18, 0xe7, 0xb4, 0xbd, 0xa1, 0x5b, 0x78, 0x86, 0x6f, 0x2f, 0xaf, 0xd0, 0x65, 0x96, 0xb5, 0x54, 0x88, + 0x29, 0xb2, 0x5e, 0x4a, 0x88, 0x91, 0xf4, 0x7f, 0x97, 0xe5, 0x3f, 0x90, 0xf5, 0x1b, 0xfb, 0x9e, 0xa1, 0x9f, 0xa8, + 0xdc, 0xd4, 0xed, 0x5d, 0x27, 0x4d, 0x99, 0x36, 0x53, 0x11, 0xd8, 0x82, 0x9d, 0xa4, 0x11, 0x58, 0x94, 0x90, 0x5f, + 0x6c, 0xbf, 0x0f, 0x7a, 0x9a, 0x7b, 0xaf, 0xf8, 0x11, 0xa8, 0xdb, 0x38, 0x63, 0x6b, 0x94, 0x96, 0x90, 0x41, 0x20, + 0x94, 0x8c, 0x28, 0x0b, 0x75, 0x61, 0x53, 0xf3, 0x14, 0xb8, 0xef, 0x12, 0xeb, 0x33, 0x19, 0xe2, 0xd5, 0xee, 0xc7, + 0xcc, 0xee, 0x09, 0xc8, 0x0d, 0xbd, 0x3e, 0x5e, 0x93, 0x72, 0x45, 0x51, 0x82, 0x64, 0xc1, 0xc4, 0xbd, 0x81, 0xb3, + 0x27, 0xd9, 0x1a, 0x71, 0x07, 0x5c, 0x39, 0x1c, 0x0b, 0xbb, 0x6f, 0x1d, 0xa3, 0x34, 0x26, 0x26, 0x87, 0x5a, 0xcf, + 0xac, 0x47, 0x16, 0x39, 0x25, 0xcd, 0xa5, 0x75, 0x1f, 0xcd, 0xcf, 0xf7, 0xc2, 0xe6, 0xb8, 0x05, 0xed, 0xfd, 0xc3, + 0x69, 0x33, 0x16, 0x0d, 0xe1, 0x8f, 0x19, 0x95, 0x81, 0x2a, 0x68, 0x20, 0xf1, 0xc1, 0x4c, 0x45, 0x0e, 0x10, 0x9d, + 0x14, 0xba, 0xe4, 0x38, 0x7d, 0xbe, 0x67, 0x20, 0x51, 0xe5, 0xb3, 0x93, 0xc4, 0xd8, 0x05, 0x68, 0xe6, 0xb7, 0x87, + 0xfe, 0xbd, 0x1f, 0xff, 0x5c, 0xd1, 0x76, 0x77, 0x4d, 0x4b, 0x9a, 0xca, 0xba, 0xb5, 0xad, 0x67, 0xa0, 0x05, 0xae, + 0x92, 0x76, 0xf8, 0x87, 0x9b, 0xb7, 0x6f, 0x92, 0xda, 0x6e, 0xfb, 0x17, 0x4f, 0x51, 0xab, 0x6a, 0xf1, 0x1e, 0xaa, + 0xc5, 0xbf, 0x92, 0x9e, 0xaa, 0x17, 0xbd, 0x0f, 0xc0, 0xaa, 0xfd, 0xbd, 0xbd, 0x2f, 0x1a, 0x2a, 0xb0, 0x5f, 0x42, + 0x72, 0xb8, 0x50, 0x1e, 0x3a, 0xc3, 0xa8, 0x7f, 0x00, 0xfd, 0x60, 0x01, 0xd8, 0xad, 0xf3, 0x3e, 0xe4, 0x7f, 0x95, + 0x82, 0xe7, 0xdf, 0xee, 0x17, 0xf5, 0xd6, 0x11, 0xec, 0x13, 0xe3, 0xcb, 0x29, 0xe3, 0x05, 0x6d, 0x99, 0x3c, 0x80, + 0xb9, 0x50, 0x42, 0x9a, 0x95, 0xdc, 0x37, 0x24, 0xcb, 0xd4, 0x49, 0xd4, 0x6c, 0x67, 0x39, 0x14, 0x1c, 0x45, 0x49, + 0xa7, 0x3e, 0xad, 0x0e, 0xe6, 0x5c, 0xe7, 0x96, 0xe9, 0x24, 0x7a, 0x71, 0x50, 0x17, 0x6e, 0x2f, 0xe1, 0x61, 0x39, + 0xa4, 0x64, 0x4b, 0x3e, 0x4d, 0xc1, 0x70, 0xda, 0x1a, 0xa6, 0x9c, 0x54, 0xac, 0xdc, 0x4d, 0x05, 0x64, 0x39, 0x07, + 0x2a, 0x11, 0xcb, 0x0f, 0x8b, 0x95, 0x94, 0x35, 0x07, 0xdd, 0x6d, 0x46, 0xdb, 0xa9, 0x37, 0x33, 0x13, 0xa7, 0x25, + 0x19, 0x5b, 0x89, 0x29, 0x0e, 0x5b, 0x5a, 0xcd, 0x16, 0x24, 0xbd, 0x5b, 0xb6, 0xf5, 0x8a, 0x67, 0x4e, 0xaa, 0xb2, + 0xf0, 0xf4, 0x99, 0x9f, 0x93, 0x90, 0xa6, 0xb3, 0x6e, 0x95, 0xe7, 0xf9, 0x0c, 0xa0, 0xa0, 0x8e, 0xc9, 0x6a, 0xd3, + 0x00, 0x0f, 0x14, 0xdb, 0x99, 0x99, 0x38, 0x50, 0x1b, 0xc6, 0x46, 0x28, 0x11, 0x2f, 0x66, 0x47, 0x77, 0xbc, 0x19, + 0xa4, 0x77, 0x01, 0x42, 0x1a, 0x88, 0x6d, 0x30, 0xf3, 0x50, 0x11, 0xc6, 0xcf, 0xad, 0x57, 0xd7, 0x64, 0xd6, 0x95, + 0x27, 0x80, 0x45, 0xab, 0xd1, 0x45, 0x6a, 0x06, 0x05, 0xc8, 0x14, 0xd9, 0x69, 0x30, 0xf4, 0x9a, 0xed, 0x01, 0x77, + 0x17, 0x64, 0x7f, 0xa4, 0xce, 0x4b, 0xba, 0x9d, 0x7d, 0x5c, 0x09, 0xc9, 0xf2, 0x9d, 0xd3, 0x15, 0xe9, 0x29, 0x5c, + 0x16, 0x28, 0xce, 0x0b, 0x20, 0xa5, 0x94, 0xcf, 0xb4, 0x0e, 0x87, 0x49, 0x5a, 0x89, 0x0e, 0xa7, 0x93, 0x18, 0x7d, + 0x41, 0x1f, 0xca, 0xfa, 0x6f, 0xd4, 0xea, 0x2e, 0xee, 0x2b, 0xd2, 0x42, 0xd1, 0x70, 0x16, 0x35, 0x60, 0x5a, 0x4d, + 0x9d, 0x11, 0x3c, 0xab, 0x6e, 0x4b, 0x09, 0x03, 0xcf, 0xc1, 0x4c, 0x5d, 0x7b, 0x8f, 0x78, 0xfb, 0xcd, 0x16, 0x89, + 0xba, 0x64, 0x59, 0x47, 0xa7, 0x49, 0x90, 0x77, 0x82, 0xc7, 0x87, 0xc7, 0x8d, 0xd4, 0xde, 0x11, 0xea, 0x41, 0x3e, + 0x26, 0xbe, 0xf7, 0x99, 0x27, 0x92, 0xe5, 0x79, 0xb0, 0xc8, 0x4f, 0x48, 0xa9, 0x12, 0x7a, 0x60, 0xdd, 0xad, 0x08, + 0x06, 0x20, 0xe0, 0xf8, 0x6c, 0x60, 0x7e, 0x60, 0x3a, 0x2c, 0xf6, 0x67, 0x52, 0xf4, 0x55, 0x9d, 0xae, 0xda, 0xd2, + 0xb6, 0x3e, 0x73, 0x75, 0x5f, 0x84, 0x57, 0xf7, 0x25, 0xae, 0xf7, 0x74, 0x89, 0xeb, 0x21, 0xd5, 0x14, 0xbd, 0xaa, + 0xb7, 0x49, 0x4f, 0x17, 0x9b, 0x01, 0xfc, 0xf6, 0x5e, 0x84, 0xaf, 0x81, 0xff, 0xff, 0x52, 0xbb, 0x7e, 0x77, 0xe1, + 0xfa, 0x82, 0xaa, 0xf5, 0x85, 0x15, 0xcb, 0x78, 0xa7, 0x9c, 0x87, 0x19, 0x94, 0x26, 0x86, 0x05, 0x5b, 0xfa, 0x7f, + 0x04, 0xb4, 0xff, 0x89, 0x63, 0x78, 0xe9, 0x8f, 0xf1, 0x04, 0xe9, 0xc1, 0x40, 0x84, 0xc3, 0x31, 0x1a, 0x5d, 0x0d, + 0xf0, 0xc0, 0x47, 0xaa, 0x1d, 0x1a, 0xa2, 0x11, 0x1e, 0x03, 0xc1, 0x10, 0x87, 0x23, 0xd8, 0x40, 0x81, 0x8f, 0xa3, + 0x37, 0x41, 0x88, 0x87, 0x11, 0x50, 0x05, 0x1e, 0x0e, 0x03, 0x64, 0x68, 0x87, 0x38, 0x00, 0x71, 0x8a, 0x24, 0xac, + 0x00, 0xe8, 0x34, 0xc4, 0xde, 0x08, 0xc4, 0x0d, 0xb1, 0x37, 0xc1, 0xe3, 0x21, 0x1a, 0xe3, 0x11, 0x40, 0x87, 0x07, + 0x51, 0xe9, 0x44, 0xd8, 0x87, 0xed, 0x70, 0x48, 0xc6, 0x78, 0x10, 0x22, 0x3d, 0x18, 0x38, 0x46, 0x20, 0xc2, 0xc1, + 0x9e, 0xff, 0x26, 0xc4, 0xc1, 0x08, 0xf4, 0x0e, 0x06, 0x97, 0x20, 0x76, 0x32, 0x40, 0x66, 0x34, 0xf0, 0x82, 0x82, + 0xe8, 0x29, 0xd0, 0x82, 0xbf, 0x2f, 0x68, 0x00, 0x89, 0x8f, 0x42, 0x3c, 0x81, 0xd8, 0xf5, 0x15, 0xbf, 0x19, 0x0d, + 0x6e, 0xbe, 0x8f, 0xbc, 0xdf, 0x8d, 0x59, 0xf8, 0xf7, 0xc5, 0xcc, 0x57, 0x08, 0xc0, 0x14, 0x74, 0x83, 0x1c, 0xa4, + 0x07, 0xa3, 0x1b, 0x98, 0xc7, 0x57, 0x13, 0x34, 0x06, 0xae, 0xe1, 0x18, 0x4d, 0x50, 0xa4, 0xd0, 0x05, 0xf6, 0x81, + 0x61, 0x72, 0x80, 0xe9, 0x0b, 0x61, 0x1c, 0xfc, 0x85, 0x61, 0x7c, 0xca, 0xa7, 0xbf, 0xb0, 0x4b, 0x7f, 0x46, 0x0a, + 0x82, 0x76, 0x4c, 0xb7, 0x61, 0xb1, 0x6b, 0x3e, 0x0f, 0xa8, 0x2e, 0x0a, 0xde, 0xf6, 0xa1, 0x1b, 0x99, 0xc7, 0x85, + 0x8f, 0x58, 0x96, 0x40, 0x57, 0x3f, 0x3f, 0x6b, 0xf5, 0x81, 0xd0, 0x3f, 0x1e, 0xc1, 0xec, 0x41, 0xe3, 0x6e, 0xce, + 0x74, 0xa5, 0x9f, 0xdf, 0x14, 0x14, 0xbd, 0xbe, 0x7e, 0x07, 0x2f, 0x7f, 0x65, 0x89, 0x78, 0xbd, 0x81, 0x77, 0xcc, + 0x1d, 0x92, 0xb5, 0xfa, 0x6a, 0xc0, 0xa1, 0x8d, 0x54, 0x53, 0x78, 0x3d, 0x41, 0x5d, 0x1f, 0x81, 0x31, 0x8e, 0x17, + 0xed, 0xfc, 0x5d, 0x49, 0x89, 0xa0, 0x68, 0xc9, 0xd6, 0x14, 0x31, 0x09, 0x2d, 0x42, 0x45, 0x91, 0x64, 0x6a, 0x38, + 0x31, 0x6a, 0x3a, 0x68, 0x77, 0xb5, 0x12, 0xd3, 0x28, 0x83, 0x25, 0x20, 0x66, 0xde, 0x75, 0xc4, 0x71, 0x11, 0x1a, + 0xab, 0xae, 0xa9, 0x94, 0xd0, 0x4c, 0x28, 0xab, 0xc2, 0x79, 0xac, 0xde, 0x6e, 0x11, 0xd1, 0xef, 0x0c, 0x89, 0xbb, + 0x61, 0x39, 0x53, 0xdf, 0x0c, 0xe6, 0xb1, 0xee, 0x22, 0x95, 0x04, 0xd5, 0xc8, 0x98, 0x0f, 0x1c, 0x7a, 0x56, 0x52, + 0xbe, 0x84, 0x97, 0x56, 0x78, 0x4c, 0xd0, 0x57, 0xa4, 0xb4, 0xa8, 0x4b, 0xe8, 0x5b, 0x92, 0xeb, 0xeb, 0x1f, 0xff, + 0xa1, 0xbe, 0x86, 0x28, 0x13, 0x4e, 0x9c, 0xf0, 0x0a, 0x60, 0x18, 0xd5, 0xa4, 0xe3, 0x1b, 0x0e, 0xcc, 0x77, 0x8d, + 0x06, 0x5a, 0x78, 0xf0, 0x2f, 0x7b, 0x20, 0xe5, 0xdd, 0x71, 0xb3, 0x93, 0xa4, 0xff, 0xeb, 0x7e, 0xd4, 0x30, 0x89, + 0xd5, 0xa2, 0x62, 0x72, 0x7e, 0x0d, 0x06, 0xc6, 0xae, 0x39, 0x00, 0xe7, 0x94, 0x03, 0x86, 0xb6, 0xe8, 0x78, 0x00, + 0xec, 0x9f, 0x6f, 0x2e, 0xd1, 0x2f, 0x0d, 0x5c, 0x6e, 0x6a, 0xb0, 0xd7, 0x5e, 0x56, 0x54, 0x16, 0x75, 0x96, 0xbc, + 0xfb, 0xf9, 0xfa, 0xe6, 0xe4, 0xf1, 0x4a, 0x13, 0x21, 0xca, 0x53, 0xf3, 0xbd, 0x65, 0x55, 0x4a, 0xd6, 0x90, 0x56, + 0x6a, 0xb1, 0x8e, 0x8a, 0x8e, 0xa3, 0x47, 0xfa, 0x3c, 0x67, 0x25, 0x35, 0x4e, 0x75, 0x8c, 0xee, 0x1c, 0x7d, 0xce, + 0xc6, 0xa3, 0xee, 0x47, 0x56, 0xba, 0xe6, 0x02, 0xb9, 0xe6, 0x36, 0xb9, 0xfa, 0x6b, 0xd4, 0xbf, 0x01, 0x14, 0xee, + 0xbc, 0x64, 0x9d, 0x12, 0x00, 0x00}; } // namespace captive_portal } // namespace esphome diff --git a/esphome/components/captive_portal/captive_portal.cpp b/esphome/components/captive_portal/captive_portal.cpp index 78eee4b226..630e00f0b7 100644 --- a/esphome/components/captive_portal/captive_portal.cpp +++ b/esphome/components/captive_portal/captive_portal.cpp @@ -12,7 +12,7 @@ static const char *const TAG = "captive_portal"; void CaptivePortal::handle_config(AsyncWebServerRequest *request) { AsyncResponseStream *stream = request->beginResponseStream("application/json"); stream->addHeader("cache-control", "public, max-age=0, must-revalidate"); - stream->printf(R"({"name":"%s","aps":[{})", App.get_name().c_str()); + stream->printf(R"({"mac":"%s","name":"%s","aps":[{})", get_mac_address_pretty().c_str(), App.get_name().c_str()); for (auto &scan : wifi::global_wifi_component->get_scan_result()) { if (scan.get_is_hidden()) From 5441213b270d933f8f35830ee425010612adc935 Mon Sep 17 00:00:00 2001 From: tracestep <16390082+tracestep@users.noreply.github.com> Date: Mon, 8 Apr 2024 22:11:46 -0300 Subject: [PATCH 1207/2101] Adds i2c timeout config (#4614) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/i2c/__init__.py | 45 ++++++++++++++++++++-- esphome/components/i2c/i2c_bus_arduino.cpp | 21 ++++++++++ esphome/components/i2c/i2c_bus_arduino.h | 2 + esphome/components/i2c/i2c_bus_esp_idf.cpp | 29 +++++++++++--- esphome/components/i2c/i2c_bus_esp_idf.h | 2 + 5 files changed, 90 insertions(+), 9 deletions(-) diff --git a/esphome/components/i2c/__init__.py b/esphome/components/i2c/__init__.py index 0a1f049b93..f52a0edb9f 100644 --- a/esphome/components/i2c/__init__.py +++ b/esphome/components/i2c/__init__.py @@ -4,6 +4,7 @@ import esphome.final_validate as fv from esphome import pins from esphome.const import ( CONF_FREQUENCY, + CONF_TIMEOUT, CONF_ID, CONF_INPUT, CONF_OUTPUT, @@ -59,6 +60,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_FREQUENCY, default="50kHz"): cv.All( cv.frequency, cv.Range(min=0, min_included=False) ), + cv.Optional(CONF_TIMEOUT): cv.positive_time_period, cv.Optional(CONF_SCAN, default=True): cv.boolean, } ).extend(cv.COMPONENT_SCHEMA), @@ -81,6 +83,8 @@ async def to_code(config): cg.add(var.set_frequency(int(config[CONF_FREQUENCY]))) cg.add(var.set_scan(config[CONF_SCAN])) + if CONF_TIMEOUT in config: + cg.add(var.set_timeout(int(config[CONF_TIMEOUT].total_microseconds))) if CORE.using_arduino: cg.add_library("Wire", None) @@ -119,23 +123,56 @@ async def register_i2c_device(var, config): def final_validate_device_schema( - name: str, *, min_frequency: cv.frequency = None, max_frequency: cv.frequency = None + name: str, + *, + min_frequency: cv.frequency = None, + max_frequency: cv.frequency = None, + min_timeout: cv.time_period = None, + max_timeout: cv.time_period = None, ): hub_schema = {} - if min_frequency is not None: + if (min_frequency is not None) and (max_frequency is not None): + hub_schema[cv.Required(CONF_FREQUENCY)] = cv.Range( + min=cv.frequency(min_frequency), + min_included=True, + max=cv.frequency(max_frequency), + max_included=True, + msg=f"Component {name} requires a frequency between {min_frequency} and {max_frequency} for the I2C bus", + ) + elif min_frequency is not None: hub_schema[cv.Required(CONF_FREQUENCY)] = cv.Range( min=cv.frequency(min_frequency), min_included=True, msg=f"Component {name} requires a minimum frequency of {min_frequency} for the I2C bus", ) - - if max_frequency is not None: + elif max_frequency is not None: hub_schema[cv.Required(CONF_FREQUENCY)] = cv.Range( max=cv.frequency(max_frequency), max_included=True, msg=f"Component {name} cannot be used with a frequency of over {max_frequency} for the I2C bus", ) + if (min_timeout is not None) and (max_timeout is not None): + hub_schema[cv.Required(CONF_TIMEOUT)] = cv.Range( + min=cv.time_period(min_timeout), + min_included=True, + max=cv.time_period(max_timeout), + max_included=True, + msg=f"Component {name} requires a timeout between {min_timeout} and {max_timeout} for the I2C bus", + ) + elif min_timeout is not None: + hub_schema[cv.Required(CONF_TIMEOUT)] = cv.Range( + min=cv.time_period(min_timeout), + min_included=True, + msg=f"Component {name} requires a minimum timeout of {min_timeout} for the I2C bus", + ) + elif max_timeout is not None: + hub_schema[cv.Required(CONF_TIMEOUT)] = cv.Range( + max=cv.time_period(max_timeout), + max_included=True, + msg=f"Component {name} cannot be used with a timeout of over {max_timeout} for the I2C bus", + ) + return cv.Schema( {cv.Required(CONF_I2C_ID): fv.id_declaration_match_schema(hub_schema)}, extra=cv.ALLOW_EXTRA, diff --git a/esphome/components/i2c/i2c_bus_arduino.cpp b/esphome/components/i2c/i2c_bus_arduino.cpp index 0966bd4d97..cd1b2aacc7 100644 --- a/esphome/components/i2c/i2c_bus_arduino.cpp +++ b/esphome/components/i2c/i2c_bus_arduino.cpp @@ -52,6 +52,18 @@ void ArduinoI2CBus::set_pins_and_clock_() { #else wire_->begin(static_cast(sda_pin_), static_cast(scl_pin_)); #endif + if (timeout_ > 0) { // if timeout specified in yaml +#if defined(USE_ESP32) + // https://github.com/espressif/arduino-esp32/blob/master/libraries/Wire/src/Wire.cpp + wire_->setTimeOut(timeout_ / 1000); // unit: ms +#elif defined(USE_ESP8266) + // https://github.com/esp8266/Arduino/blob/master/libraries/Wire/Wire.h + wire_->setClockStretchLimit(timeout_); // unit: us +#elif defined(USE_RP2040) + // https://github.com/earlephilhower/ArduinoCore-API/blob/e37df85425e0ac020bfad226d927f9b00d2e0fb7/api/Stream.h + wire_->setTimeout(timeout_ / 1000); // unit: ms +#endif + } wire_->setClock(frequency_); } @@ -60,6 +72,15 @@ void ArduinoI2CBus::dump_config() { ESP_LOGCONFIG(TAG, " SDA Pin: GPIO%u", this->sda_pin_); ESP_LOGCONFIG(TAG, " SCL Pin: GPIO%u", this->scl_pin_); ESP_LOGCONFIG(TAG, " Frequency: %u Hz", this->frequency_); + if (timeout_ > 0) { +#if defined(USE_ESP32) + ESP_LOGCONFIG(TAG, " Timeout: %u ms", this->timeout_ / 1000); +#elif defined(USE_ESP8266) + ESP_LOGCONFIG(TAG, " Timeout: %u us", this->timeout_); +#elif defined(USE_RP2040) + ESP_LOGCONFIG(TAG, " Timeout: %u ms", this->timeout_ / 1000); +#endif + } switch (this->recovery_result_) { case RECOVERY_COMPLETED: ESP_LOGCONFIG(TAG, " Recovery: bus successfully recovered"); diff --git a/esphome/components/i2c/i2c_bus_arduino.h b/esphome/components/i2c/i2c_bus_arduino.h index 6304c2b039..6a670a2a05 100644 --- a/esphome/components/i2c/i2c_bus_arduino.h +++ b/esphome/components/i2c/i2c_bus_arduino.h @@ -27,6 +27,7 @@ class ArduinoI2CBus : public I2CBus, public Component { void set_sda_pin(uint8_t sda_pin) { sda_pin_ = sda_pin; } void set_scl_pin(uint8_t scl_pin) { scl_pin_ = scl_pin; } void set_frequency(uint32_t frequency) { frequency_ = frequency; } + void set_timeout(uint32_t timeout) { timeout_ = timeout; } private: void recover_(); @@ -38,6 +39,7 @@ class ArduinoI2CBus : public I2CBus, public Component { uint8_t sda_pin_; uint8_t scl_pin_; uint32_t frequency_; + uint32_t timeout_ = 0; bool initialized_ = false; }; diff --git a/esphome/components/i2c/i2c_bus_esp_idf.cpp b/esphome/components/i2c/i2c_bus_esp_idf.cpp index 5d35c1968b..cbb748cca1 100644 --- a/esphome/components/i2c/i2c_bus_esp_idf.cpp +++ b/esphome/components/i2c/i2c_bus_esp_idf.cpp @@ -1,12 +1,12 @@ #ifdef USE_ESP_IDF #include "i2c_bus_esp_idf.h" -#include "esphome/core/hal.h" -#include "esphome/core/log.h" -#include "esphome/core/helpers.h" -#include "esphome/core/application.h" -#include #include +#include +#include "esphome/core/application.h" +#include "esphome/core/hal.h" +#include "esphome/core/helpers.h" +#include "esphome/core/log.h" namespace esphome { namespace i2c { @@ -45,6 +45,20 @@ void IDFI2CBus::setup() { this->mark_failed(); return; } + if (timeout_ > 0) { // if timeout specified in yaml: + if (timeout_ > 13000) { + ESP_LOGW(TAG, "i2c timeout of %" PRIu32 "us greater than max of 13ms on esp-idf, setting to max", timeout_); + timeout_ = 13000; + } + err = i2c_set_timeout(port_, timeout_ * 80); // unit: APB 80MHz clock cycle + if (err != ESP_OK) { + ESP_LOGW(TAG, "i2c_set_timeout failed: %s", esp_err_to_name(err)); + this->mark_failed(); + return; + } else { + ESP_LOGV(TAG, "i2c_timeout set to %d ticks (%d us)", timeout_ * 80, timeout_); + } + } err = i2c_driver_install(port_, I2C_MODE_MASTER, 0, 0, ESP_INTR_FLAG_IRAM); if (err != ESP_OK) { ESP_LOGW(TAG, "i2c_driver_install failed: %s", esp_err_to_name(err)); @@ -62,6 +76,9 @@ void IDFI2CBus::dump_config() { ESP_LOGCONFIG(TAG, " SDA Pin: GPIO%u", this->sda_pin_); ESP_LOGCONFIG(TAG, " SCL Pin: GPIO%u", this->scl_pin_); ESP_LOGCONFIG(TAG, " Frequency: %" PRIu32 " Hz", this->frequency_); + if (timeout_ > 0) { + ESP_LOGCONFIG(TAG, " Timeout: %" PRIu32 "us", this->timeout_); + } switch (this->recovery_result_) { case RECOVERY_COMPLETED: ESP_LOGCONFIG(TAG, " Recovery: bus successfully recovered"); @@ -127,6 +144,8 @@ ErrorCode IDFI2CBus::readv(uint8_t address, ReadBuffer *buffers, size_t cnt) { return ERROR_UNKNOWN; } err = i2c_master_cmd_begin(port_, cmd, 20 / portTICK_PERIOD_MS); + // i2c_master_cmd_begin() will block for a whole second if no ack: + // https://github.com/espressif/esp-idf/issues/4999 i2c_cmd_link_delete(cmd); if (err == ESP_FAIL) { // transfer not acked diff --git a/esphome/components/i2c/i2c_bus_esp_idf.h b/esphome/components/i2c/i2c_bus_esp_idf.h index c80ea8c99d..afb4c2d22b 100644 --- a/esphome/components/i2c/i2c_bus_esp_idf.h +++ b/esphome/components/i2c/i2c_bus_esp_idf.h @@ -29,6 +29,7 @@ class IDFI2CBus : public I2CBus, public Component { void set_scl_pin(uint8_t scl_pin) { scl_pin_ = scl_pin; } void set_scl_pullup_enabled(bool scl_pullup_enabled) { scl_pullup_enabled_ = scl_pullup_enabled; } void set_frequency(uint32_t frequency) { frequency_ = frequency; } + void set_timeout(uint32_t timeout) { timeout_ = timeout; } private: void recover_(); @@ -41,6 +42,7 @@ class IDFI2CBus : public I2CBus, public Component { uint8_t scl_pin_; bool scl_pullup_enabled_; uint32_t frequency_; + uint32_t timeout_ = 0; bool initialized_ = false; }; From 3b6e8fa66649ab5e842c2e1c02e810f3af48ca5e Mon Sep 17 00:00:00 2001 From: Mat931 <49403702+Mat931@users.noreply.github.com> Date: Tue, 9 Apr 2024 01:43:53 +0000 Subject: [PATCH 1208/2101] Add ABB-Welcome / Busch-Welcome Door Intercom Protocol (#4689) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/remote_base/__init__.py | 102 +++++++ .../remote_base/abbwelcome_protocol.cpp | 123 +++++++++ .../remote_base/abbwelcome_protocol.h | 251 ++++++++++++++++++ 3 files changed, 476 insertions(+) create mode 100644 esphome/components/remote_base/abbwelcome_protocol.cpp create mode 100644 esphome/components/remote_base/abbwelcome_protocol.h diff --git a/esphome/components/remote_base/__init__.py b/esphome/components/remote_base/__init__.py index 08652bbfc9..c771f406d8 100644 --- a/esphome/components/remote_base/__init__.py +++ b/esphome/components/remote_base/__init__.py @@ -1718,3 +1718,105 @@ async def haier_action(var, config, args): vec_ = cg.std_vector.template(cg.uint8) template_ = await cg.templatable(config[CONF_CODE], args, vec_, vec_) cg.add(var.set_code(template_)) + + +# ABBWelcome +( + ABBWelcomeData, + ABBWelcomeBinarySensor, + ABBWelcomeTrigger, + ABBWelcomeAction, + ABBWelcomeDumper, +) = declare_protocol("ABBWelcome") + +CONF_SOURCE_ADDRESS = "source_address" +CONF_DESTINATION_ADDRESS = "destination_address" +CONF_THREE_BYTE_ADDRESS = "three_byte_address" +CONF_MESSAGE_TYPE = "message_type" +CONF_MESSAGE_ID = "message_id" +CONF_RETRANSMISSION = "retransmission" + +ABB_WELCOME_SCHEMA = cv.Schema( + { + cv.Required(CONF_SOURCE_ADDRESS): cv.hex_uint32_t, + cv.Required(CONF_DESTINATION_ADDRESS): cv.hex_uint32_t, + cv.Optional(CONF_RETRANSMISSION, default=False): cv.boolean, + cv.Optional(CONF_THREE_BYTE_ADDRESS, default=False): cv.boolean, + cv.Required(CONF_MESSAGE_TYPE): cv.Any(cv.hex_uint8_t, cv.uint8_t), + cv.Optional(CONF_MESSAGE_ID): cv.Any(cv.hex_uint8_t, cv.uint8_t), + cv.Optional(CONF_DATA): cv.All( + [cv.Any(cv.hex_uint8_t, cv.uint8_t)], + cv.Length(min=0, max=7), + ), + } +) + + +@register_binary_sensor("abbwelcome", ABBWelcomeBinarySensor, ABB_WELCOME_SCHEMA) +def abbwelcome_binary_sensor(var, config): + cg.add(var.set_three_byte_address(config[CONF_THREE_BYTE_ADDRESS])) + cg.add(var.set_source_address(config[CONF_SOURCE_ADDRESS])) + cg.add(var.set_destination_address(config[CONF_DESTINATION_ADDRESS])) + cg.add(var.set_retransmission(config[CONF_RETRANSMISSION])) + cg.add(var.set_message_type(config[CONF_MESSAGE_TYPE])) + cg.add(var.set_auto_message_id(CONF_MESSAGE_ID not in config)) + if CONF_MESSAGE_ID in config: + cg.add(var.set_message_id(config[CONF_MESSAGE_ID])) + if CONF_DATA in config: + cg.add(var.set_data(config[CONF_DATA])) + cg.add(var.finalize()) + + +@register_trigger("abbwelcome", ABBWelcomeTrigger, ABBWelcomeData) +def abbwelcome_trigger(var, config): + pass + + +@register_dumper("abbwelcome", ABBWelcomeDumper) +def abbwelcome_dumper(var, config): + pass + + +@register_action("abbwelcome", ABBWelcomeAction, ABB_WELCOME_SCHEMA) +async def abbwelcome_action(var, config, args): + cg.add( + var.set_three_byte_address( + await cg.templatable(config[CONF_THREE_BYTE_ADDRESS], args, cg.bool_) + ) + ) + cg.add( + var.set_source_address( + await cg.templatable(config[CONF_SOURCE_ADDRESS], args, cg.uint16) + ) + ) + cg.add( + var.set_destination_address( + await cg.templatable(config[CONF_DESTINATION_ADDRESS], args, cg.uint16) + ) + ) + cg.add( + var.set_retransmission( + await cg.templatable(config[CONF_RETRANSMISSION], args, cg.bool_) + ) + ) + cg.add( + var.set_message_type( + await cg.templatable(config[CONF_MESSAGE_TYPE], args, cg.uint8) + ) + ) + cg.add(var.set_auto_message_id(CONF_MESSAGE_ID not in config)) + if CONF_MESSAGE_ID in config: + cg.add( + var.set_message_id( + await cg.templatable(config[CONF_MESSAGE_ID], args, cg.uint8) + ) + ) + if CONF_DATA in config: + data_ = config[CONF_DATA] + if cg.is_template(data_): + template_ = await cg.templatable( + data_, args, cg.std_vector.template(cg.uint8) + ) + cg.add(var.set_data_template(template_)) + else: + cg.add(var.set_data_static(data_)) diff --git a/esphome/components/remote_base/abbwelcome_protocol.cpp b/esphome/components/remote_base/abbwelcome_protocol.cpp new file mode 100644 index 0000000000..88f928901b --- /dev/null +++ b/esphome/components/remote_base/abbwelcome_protocol.cpp @@ -0,0 +1,123 @@ +#include "abbwelcome_protocol.h" +#include "esphome/core/log.h" + +namespace esphome { +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; + +uint8_t ABBWelcomeData::calc_cs_() const { + uint8_t checksum = 0; + for (uint8_t i = 0; i < this->size() - 1; i++) { + uint16_t temp = checksum ^ (this->data_[i]); + temp = temp ^ (uint16_t) (((uint32_t) temp << 0x11) >> 0x10) ^ (uint16_t) (((uint32_t) temp << 0x12) >> 0x10) ^ + (uint16_t) (((uint32_t) temp << 0x13) >> 0x10) ^ (uint16_t) (((uint32_t) temp << 0x14) >> 0x10) ^ + (uint16_t) (((uint32_t) temp << 0x15) >> 0x10) ^ (uint16_t) (((uint32_t) temp << 0x16) >> 0x10) ^ + (uint16_t) (((uint32_t) temp << 0x17) >> 0x10); + checksum = (temp & 0xfe) ^ ((temp >> 8) & 1); + } + return ~checksum; +} + +void ABBWelcomeProtocol::encode_byte_(RemoteTransmitData *dst, uint8_t data) const { + // space = bus high, mark = activate bus pulldown + dst->mark(BIT_ZERO_MARK_US); + uint32_t next_space = BIT_ZERO_SPACE_US; + for (uint8_t mask = 1 << 7; mask; mask >>= 1) { + if (data & mask) { + next_space += BIT_ONE_SPACE_US; + } else { + dst->space(next_space); + dst->mark(BIT_ZERO_MARK_US); + next_space = BIT_ZERO_SPACE_US; + } + } + next_space += BYTE_SPACE_US; + dst->space(next_space); +} + +void ABBWelcomeProtocol::encode(RemoteTransmitData *dst, const ABBWelcomeData &src) { + dst->set_carrier_frequency(0); + uint32_t reserve_count = 0; + for (size_t i = 0; i < src.size(); i++) { + reserve_count += 2 * (9 - (src[i] & 1) - ((src[i] >> 1) & 1) - ((src[i] >> 2) & 1) - ((src[i] >> 3) & 1) - + ((src[i] >> 4) & 1) - ((src[i] >> 5) & 1) - ((src[i] >> 6) & 1) - ((src[i] >> 7) & 1)); + } + dst->reserve(reserve_count); + for (size_t i = 0; i < src.size(); i++) + this->encode_byte_(dst, src[i]); + ESP_LOGD(TAG, "Transmitting: %s", src.to_string().c_str()); +} + +bool ABBWelcomeProtocol::decode_byte_(RemoteReceiveData &src, bool &done, uint8_t &data) { + if (!src.expect_mark(BIT_ZERO_MARK_US)) + return false; + uint32_t next_space = BIT_ZERO_SPACE_US; + for (uint8_t mask = 1 << 7; mask; mask >>= 1) { + // if (!src.peek_space_at_least(next_space, 0)) + // return false; + if (src.expect_space(next_space)) { + if (!src.expect_mark(BIT_ZERO_MARK_US)) + return false; + next_space = BIT_ZERO_SPACE_US; + } else { + data |= mask; + next_space += BIT_ONE_SPACE_US; + } + } + next_space += BYTE_SPACE_US; + // if (!src.peek_space_at_least(next_space, 0)) + // return false; + done = !(src.expect_space(next_space)); + return true; +} + +optional ABBWelcomeProtocol::decode(RemoteReceiveData src) { + if (src.expect_item(BIT_ZERO_MARK_US, BIT_ZERO_SPACE_US) && + src.expect_item(BIT_ZERO_MARK_US, BIT_ZERO_SPACE_US + BIT_ONE_SPACE_US) && + src.expect_item(BIT_ZERO_MARK_US, BIT_ZERO_SPACE_US + BIT_ONE_SPACE_US) && + src.expect_item(BIT_ZERO_MARK_US, BIT_ZERO_SPACE_US + BIT_ONE_SPACE_US) && + src.expect_item(BIT_ZERO_MARK_US, BIT_ZERO_SPACE_US + BIT_ONE_SPACE_US + BYTE_SPACE_US) && + src.expect_item(BIT_ZERO_MARK_US, BIT_ZERO_SPACE_US + 8 * BIT_ONE_SPACE_US + BYTE_SPACE_US)) { + ESP_LOGVV(TAG, "Received Header: 0x55FF"); + ABBWelcomeData out; + out[0] = 0x55; + out[1] = 0xff; + bool done = false; + uint8_t length = 10; + uint8_t received_bytes = 2; + for (; (received_bytes < length) && !done; received_bytes++) { + uint8_t data = 0; + if (!this->decode_byte_(src, done, data)) { + ESP_LOGW(TAG, "Received incomplete packet: %s", out.to_string(received_bytes).c_str()); + return {}; + } + if (received_bytes == 2) { + length += std::min(static_cast(data & DATA_LENGTH_MASK), MAX_DATA_LENGTH); + if (data & 0x40) { + length += 2; + } + } + ESP_LOGVV(TAG, "Received Byte: 0x%02X", data); + out[received_bytes] = data; + } + if (out.is_valid()) { + ESP_LOGI(TAG, "Received: %s", out.to_string().c_str()); + return out; + } + ESP_LOGW(TAG, "Received malformed packet: %s", out.to_string(received_bytes).c_str()); + } + return {}; +} + +void ABBWelcomeProtocol::dump(const ABBWelcomeData &data) { + ESP_LOGD(TAG, "Received ABBWelcome: %s", data.to_string().c_str()); +} + +} // namespace remote_base +} // namespace esphome diff --git a/esphome/components/remote_base/abbwelcome_protocol.h b/esphome/components/remote_base/abbwelcome_protocol.h new file mode 100644 index 0000000000..0493993926 --- /dev/null +++ b/esphome/components/remote_base/abbwelcome_protocol.h @@ -0,0 +1,251 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/core/helpers.h" +#include "remote_base.h" +#include +#include +#include + +namespace esphome { +namespace remote_base { + +static const uint8_t MAX_DATA_LENGTH = 15; +static const uint8_t DATA_LENGTH_MASK = 0x3f; + +/* +Message Format: + 2 bytes: Sync (0x55FF) + 1 bit: Retransmission flag (High means retransmission) + 1 bit: Address length flag (Low means 2 bytes, High means 3 bytes) + 2 bits: Unknown + 4 bits: Data length (in bytes) + 1 bit: Reply flag (High means this is a reply to a previous message with the same message type) + 7 bits: Message type + 2-3 bytes: Destination address + 2-3 bytes: Source address + 1 byte: Message ID (randomized, does not change for retransmissions) + 0-? bytes: Data + 1 byte: Checksum +*/ + +class ABBWelcomeData { + public: + // Make default + ABBWelcomeData() { + std::fill(std::begin(this->data_), std::end(this->data_), 0); + this->data_[0] = 0x55; + this->data_[1] = 0xff; + } + // Make from initializer_list + ABBWelcomeData(std::initializer_list data) { + std::fill(std::begin(this->data_), std::end(this->data_), 0); + std::copy_n(data.begin(), std::min(data.size(), this->data_.size()), this->data_.begin()); + } + // Make from vector + ABBWelcomeData(const std::vector &data) { + std::fill(std::begin(this->data_), std::end(this->data_), 0); + std::copy_n(data.begin(), std::min(data.size(), this->data_.size()), this->data_.begin()); + } + // Default copy constructor + ABBWelcomeData(const ABBWelcomeData &) = default; + + bool auto_message_id{false}; + + uint8_t *data() { return this->data_.data(); } + const uint8_t *data() const { return this->data_.data(); } + uint8_t size() const { + return std::min(static_cast(6 + (2 * this->get_address_length()) + (this->data_[2] & DATA_LENGTH_MASK)), + static_cast(this->data_.size())); + } + bool is_valid() const { + return this->data_[0] == 0x55 && this->data_[1] == 0xff && + ((this->data_[2] & DATA_LENGTH_MASK) <= MAX_DATA_LENGTH) && + (this->data_[this->size() - 1] == this->calc_cs_()); + } + void set_retransmission(bool retransmission) { + if (retransmission) { + this->data_[2] |= 0x80; + } else { + this->data_[2] &= 0x7f; + } + } + bool get_retransmission() const { return this->data_[2] & 0x80; } + // set_three_byte_address must be called before set_source_address, set_destination_address, set_message_id and + // set_data! + void set_three_byte_address(bool three_byte_address) { + if (three_byte_address) { + this->data_[2] |= 0x40; + } else { + this->data_[2] &= 0xbf; + } + } + uint8_t get_three_byte_address() const { return (this->data_[2] & 0x40); } + uint8_t get_address_length() const { return this->get_three_byte_address() ? 3 : 2; } + void set_message_type(uint8_t message_type) { this->data_[3] = message_type; } + uint8_t get_message_type() const { return this->data_[3]; } + void set_destination_address(uint32_t address) { + if (this->get_address_length() == 2) { + this->data_[4] = (address >> 8) & 0xff; + this->data_[5] = address & 0xff; + } else { + this->data_[4] = (address >> 16) & 0xff; + this->data_[5] = (address >> 8) & 0xff; + this->data_[6] = address & 0xff; + } + } + uint32_t get_destination_address() const { + if (this->get_address_length() == 2) { + return (this->data_[4] << 8) + this->data_[5]; + } + return (this->data_[4] << 16) + (this->data_[5] << 8) + this->data_[6]; + } + void set_source_address(uint32_t address) { + if (this->get_address_length() == 2) { + this->data_[6] = (address >> 8) & 0xff; + this->data_[7] = address & 0xff; + } else { + this->data_[7] = (address >> 16) & 0xff; + this->data_[8] = (address >> 8) & 0xff; + this->data_[9] = address & 0xff; + } + } + uint32_t get_source_address() const { + if (this->get_address_length() == 2) { + return (this->data_[6] << 8) + this->data_[7]; + } + return (this->data_[7] << 16) + (this->data_[8] << 8) + this->data_[9]; + } + void set_message_id(uint8_t message_id) { this->data_[4 + 2 * this->get_address_length()] = message_id; } + uint8_t get_message_id() const { return this->data_[4 + 2 * this->get_address_length()]; } + void set_data(std::vector data) { + uint8_t size = std::min(MAX_DATA_LENGTH, static_cast(data.size())); + this->data_[2] &= (0xff ^ DATA_LENGTH_MASK); + this->data_[2] |= (size & DATA_LENGTH_MASK); + if (size) + std::copy_n(data.begin(), size, this->data_.begin() + 5 + 2 * this->get_address_length()); + } + std::vector get_data() const { + std::vector data(this->data_.begin() + 5 + 2 * this->get_address_length(), + this->data_.begin() + 5 + 2 * this->get_address_length() + this->get_data_size()); + return data; + } + uint8_t get_data_size() const { + return std::min(MAX_DATA_LENGTH, static_cast(this->data_[2] & DATA_LENGTH_MASK)); + } + void finalize() { + if (this->auto_message_id && !this->get_retransmission() && !(this->data_[3] & 0x80)) { + this->set_message_id(static_cast(random_uint32())); + } + this->data_[0] = 0x55; + this->data_[1] = 0xff; + this->data_[this->size() - 1] = this->calc_cs_(); + } + std::string to_string(uint8_t max_print_bytes = 255) const { + std::string info; + if (this->is_valid()) { + info = str_sprintf(this->get_three_byte_address() ? "[%06X %s %06X] Type: %02X" : "[%04X %s %04X] Type: %02X", + this->get_source_address(), this->get_retransmission() ? "»" : ">", + this->get_destination_address(), this->get_message_type()); + if (this->get_data_size()) + info += str_sprintf(", Data: %s", format_hex_pretty(this->get_data()).c_str()); + } else { + info = "[Invalid]"; + } + uint8_t print_bytes = std::min(this->size(), max_print_bytes); + if (print_bytes) + info = str_sprintf("%s %s", format_hex_pretty(this->data_.data(), print_bytes).c_str(), info.c_str()); + return info; + } + bool operator==(const ABBWelcomeData &rhs) const { + if (std::equal(this->data_.begin(), this->data_.begin() + this->size(), rhs.data_.begin())) + return true; + return (this->auto_message_id || rhs.auto_message_id) && this->is_valid() && rhs.is_valid() && + (this->get_message_type() == rhs.get_message_type()) && + (this->get_source_address() == rhs.get_source_address()) && + (this->get_destination_address() == rhs.get_destination_address()) && (this->get_data() == rhs.get_data()); + } + uint8_t &operator[](size_t idx) { return this->data_[idx]; } + const uint8_t &operator[](size_t idx) const { return this->data_[idx]; } + + protected: + std::array data_; + // Calculate checksum + uint8_t calc_cs_() const; +}; + +class ABBWelcomeProtocol : public RemoteProtocol { + public: + void encode(RemoteTransmitData *dst, const ABBWelcomeData &src) override; + optional decode(RemoteReceiveData src) override; + void dump(const ABBWelcomeData &data) override; + + protected: + void encode_byte_(RemoteTransmitData *dst, uint8_t data) const; + bool decode_byte_(RemoteReceiveData &src, bool &done, uint8_t &data); +}; + +class ABBWelcomeBinarySensor : public RemoteReceiverBinarySensorBase { + public: + bool matches(RemoteReceiveData src) override { + auto data = ABBWelcomeProtocol().decode(src); + return data.has_value() && data.value() == this->data_; + } + void set_source_address(const uint32_t source_address) { this->data_.set_source_address(source_address); } + void set_destination_address(const uint32_t destination_address) { + this->data_.set_destination_address(destination_address); + } + void set_retransmission(const bool retransmission) { this->data_.set_retransmission(retransmission); } + void set_three_byte_address(const bool three_byte_address) { this->data_.set_three_byte_address(three_byte_address); } + void set_message_type(const uint8_t message_type) { this->data_.set_message_type(message_type); } + void set_message_id(const uint8_t message_id) { this->data_.set_message_id(message_id); } + void set_auto_message_id(const bool auto_message_id) { this->data_.auto_message_id = auto_message_id; } + void set_data(const std::vector &data) { this->data_.set_data(data); } + void finalize() { this->data_.finalize(); } + + protected: + ABBWelcomeData data_; +}; + +using ABBWelcomeTrigger = RemoteReceiverTrigger; +using ABBWelcomeDumper = RemoteReceiverDumper; + +template class ABBWelcomeAction : public RemoteTransmitterActionBase { + TEMPLATABLE_VALUE(uint32_t, source_address) + TEMPLATABLE_VALUE(uint32_t, destination_address) + TEMPLATABLE_VALUE(bool, retransmission) + TEMPLATABLE_VALUE(bool, three_byte_address) + TEMPLATABLE_VALUE(uint8_t, message_type) + TEMPLATABLE_VALUE(uint8_t, message_id) + TEMPLATABLE_VALUE(bool, auto_message_id) + void set_data_static(std::vector data) { data_static_ = std::move(data); } + void set_data_template(std::function(Ts...)> func) { + this->data_func_ = func; + has_data_func_ = true; + } + void encode(RemoteTransmitData *dst, Ts... x) override { + ABBWelcomeData data; + data.set_three_byte_address(this->three_byte_address_.value(x...)); + data.set_source_address(this->source_address_.value(x...)); + data.set_destination_address(this->destination_address_.value(x...)); + data.set_retransmission(this->retransmission_.value(x...)); + data.set_message_type(this->message_type_.value(x...)); + data.set_message_id(this->message_id_.value(x...)); + data.auto_message_id = this->auto_message_id_.value(x...); + if (has_data_func_) { + data.set_data(this->data_func_(x...)); + } else { + data.set_data(this->data_static_); + } + data.finalize(); + ABBWelcomeProtocol().encode(dst, data); + } + + protected: + std::function(Ts...)> data_func_{}; + std::vector data_static_{}; + bool has_data_func_{false}; +}; + +} // namespace remote_base +} // namespace esphome From 76c53379877c0c8f40200ec0b1253ba0e5d39151 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 9 Apr 2024 13:46:35 +1200 Subject: [PATCH 1209/2101] Add support for time entities (#6399) * Add time entities * Add tests * Add myself to datetime codeowners * Fix publishing times with 0 values * Log performing TimeCall * Implement `on_time` trigger * Rename var * Fix initial value for time * Add arg name for clarity * Remove useless checks --- CODEOWNERS | 2 +- esphome/components/api/api.proto | 42 ++++ esphome/components/api/api_connection.cpp | 37 +++ esphome/components/api/api_connection.h | 5 + esphome/components/api/api_pb2.cpp | 219 ++++++++++++++++++ esphome/components/api/api_pb2.h | 50 ++++ esphome/components/api/api_pb2_service.cpp | 42 ++++ esphome/components/api/api_pb2_service.h | 15 ++ esphome/components/api/api_server.cpp | 9 + esphome/components/api/api_server.h | 3 + esphome/components/api/list_entities.cpp | 4 + esphome/components/api/list_entities.h | 3 + esphome/components/api/subscribe_state.cpp | 3 + esphome/components/api/subscribe_state.h | 3 + esphome/components/datetime/__init__.py | 83 ++++++- esphome/components/datetime/time_entity.cpp | 156 +++++++++++++ esphome/components/datetime/time_entity.h | 137 +++++++++++ esphome/components/mqtt/__init__.py | 3 +- esphome/components/mqtt/mqtt_date.h | 4 +- esphome/components/mqtt/mqtt_time.cpp | 68 ++++++ esphome/components/mqtt/mqtt_time.h | 45 ++++ .../components/template/datetime/__init__.py | 38 ++- .../template/datetime/template_time.cpp | 111 +++++++++ .../template/datetime/template_time.h | 46 ++++ .../components/web_server/list_entities.cpp | 7 + esphome/components/web_server/list_entities.h | 3 + esphome/components/web_server/web_server.cpp | 58 +++++ esphome/components/web_server/web_server.h | 11 +- esphome/core/application.h | 19 ++ esphome/core/component_iterator.cpp | 15 ++ esphome/core/component_iterator.h | 6 + esphome/core/controller.cpp | 6 + esphome/core/controller.h | 6 + esphome/core/defines.h | 1 + script/ci-custom.py | 1 + .../datetime/{date.all.yaml => test.all.yaml} | 0 tests/components/template/test.all.yaml | 13 ++ 37 files changed, 1251 insertions(+), 23 deletions(-) create mode 100644 esphome/components/datetime/time_entity.cpp create mode 100644 esphome/components/datetime/time_entity.h create mode 100644 esphome/components/mqtt/mqtt_time.cpp create mode 100644 esphome/components/mqtt/mqtt_time.h create mode 100644 esphome/components/template/datetime/template_time.cpp create mode 100644 esphome/components/template/datetime/template_time.h rename tests/components/datetime/{date.all.yaml => test.all.yaml} (100%) diff --git a/CODEOWNERS b/CODEOWNERS index d2a86cd3d9..4a3205acf0 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -91,7 +91,7 @@ esphome/components/daikin_arc/* @MagicBear esphome/components/daikin_brc/* @hagak esphome/components/daly_bms/* @s1lvi0 esphome/components/dashboard_import/* @esphome/core -esphome/components/datetime/* @rfdarter +esphome/components/datetime/* @jesserockz @rfdarter esphome/components/debug/* @OttoWinter esphome/components/delonghi/* @grob6000 esphome/components/dfplayer/* @glmnet diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index 6b685b8974..8d5459e717 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -45,6 +45,7 @@ service APIConnection { rpc lock_command (LockCommandRequest) returns (void) {} rpc media_player_command (MediaPlayerCommandRequest) returns (void) {} rpc date_command (DateCommandRequest) returns (void) {} + rpc time_command (TimeCommandRequest) returns (void) {} rpc subscribe_bluetooth_le_advertisements(SubscribeBluetoothLEAdvertisementsRequest) returns (void) {} rpc bluetooth_device_request(BluetoothDeviceRequest) returns (void) {} @@ -1658,3 +1659,44 @@ message DateCommandRequest { uint32 month = 3; uint32 day = 4; } + +// ==================== DATETIME TIME ==================== +message ListEntitiesTimeResponse { + option (id) = 103; + option (source) = SOURCE_SERVER; + option (ifdef) = "USE_DATETIME_TIME"; + + string object_id = 1; + fixed32 key = 2; + string name = 3; + string unique_id = 4; + + string icon = 5; + bool disabled_by_default = 6; + EntityCategory entity_category = 7; +} +message TimeStateResponse { + option (id) = 104; + option (source) = SOURCE_SERVER; + option (ifdef) = "USE_DATETIME_TIME"; + option (no_delay) = true; + + fixed32 key = 1; + // 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; + uint32 hour = 3; + uint32 minute = 4; + uint32 second = 5; +} +message TimeCommandRequest { + option (id) = 105; + option (source) = SOURCE_CLIENT; + option (ifdef) = "USE_DATETIME_TIME"; + option (no_delay) = true; + + fixed32 key = 1; + uint32 hour = 2; + uint32 minute = 3; + uint32 second = 4; +} diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index e9607f7f77..e51fa8c154 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -735,6 +735,43 @@ void APIConnection::date_command(const DateCommandRequest &msg) { } #endif +#ifdef USE_DATETIME_TIME +bool APIConnection::send_time_state(datetime::TimeEntity *time) { + if (!this->state_subscription_) + return false; + + TimeStateResponse resp{}; + resp.key = time->get_object_id_hash(); + resp.missing_state = !time->has_state(); + resp.hour = time->hour; + resp.minute = time->minute; + resp.second = time->second; + return this->send_time_state_response(resp); +} +bool APIConnection::send_time_info(datetime::TimeEntity *time) { + ListEntitiesTimeResponse msg; + msg.key = time->get_object_id_hash(); + msg.object_id = time->get_object_id(); + if (time->has_own_name()) + msg.name = time->get_name(); + msg.unique_id = get_default_unique_id("time", time); + msg.icon = time->get_icon(); + msg.disabled_by_default = time->is_disabled_by_default(); + msg.entity_category = static_cast(time->get_entity_category()); + + return this->send_list_entities_time_response(msg); +} +void APIConnection::time_command(const TimeCommandRequest &msg) { + datetime::TimeEntity *time = App.get_time_by_key(msg.key); + if (time == nullptr) + return; + + auto call = time->make_call(); + call.set_time(msg.hour, msg.minute, msg.second); + call.perform(); +} +#endif + #ifdef USE_TEXT bool APIConnection::send_text_state(text::Text *text, std::string state) { if (!this->state_subscription_) diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index c19c209969..5c0a78015d 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -77,6 +77,11 @@ class APIConnection : public APIServerConnection { bool send_date_info(datetime::DateEntity *date); void date_command(const DateCommandRequest &msg) override; #endif +#ifdef USE_DATETIME_TIME + bool send_time_state(datetime::TimeEntity *time); + bool send_time_info(datetime::TimeEntity *time); + void time_command(const TimeCommandRequest &msg) override; +#endif #ifdef USE_TEXT bool send_text_state(text::Text *text, std::string state); bool send_text_info(text::Text *text); diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index f6325d0854..884396bda3 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -7476,6 +7476,225 @@ void DateCommandRequest::dump_to(std::string &out) const { out.append("}"); } #endif +bool ListEntitiesTimeResponse::decode_varint(uint32_t field_id, ProtoVarInt value) { + switch (field_id) { + case 6: { + this->disabled_by_default = value.as_bool(); + return true; + } + case 7: { + this->entity_category = value.as_enum(); + return true; + } + default: + return false; + } +} +bool ListEntitiesTimeResponse::decode_length(uint32_t field_id, ProtoLengthDelimited value) { + switch (field_id) { + case 1: { + this->object_id = value.as_string(); + return true; + } + case 3: { + this->name = value.as_string(); + return true; + } + case 4: { + this->unique_id = value.as_string(); + return true; + } + case 5: { + this->icon = value.as_string(); + return true; + } + default: + return false; + } +} +bool ListEntitiesTimeResponse::decode_32bit(uint32_t field_id, Proto32Bit value) { + switch (field_id) { + case 2: { + this->key = value.as_fixed32(); + return true; + } + default: + return false; + } +} +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); + buffer.encode_string(4, this->unique_id); + buffer.encode_string(5, this->icon); + buffer.encode_bool(6, this->disabled_by_default); + buffer.encode_enum(7, this->entity_category); +} +#ifdef HAS_PROTO_MESSAGE_DUMP +void ListEntitiesTimeResponse::dump_to(std::string &out) const { + __attribute__((unused)) char buffer[64]; + out.append("ListEntitiesTimeResponse {\n"); + out.append(" object_id: "); + out.append("'").append(this->object_id).append("'"); + out.append("\n"); + + out.append(" key: "); + sprintf(buffer, "%" PRIu32, this->key); + out.append(buffer); + out.append("\n"); + + out.append(" name: "); + out.append("'").append(this->name).append("'"); + out.append("\n"); + + out.append(" unique_id: "); + out.append("'").append(this->unique_id).append("'"); + out.append("\n"); + + out.append(" icon: "); + out.append("'").append(this->icon).append("'"); + out.append("\n"); + + out.append(" disabled_by_default: "); + out.append(YESNO(this->disabled_by_default)); + out.append("\n"); + + out.append(" entity_category: "); + out.append(proto_enum_to_string(this->entity_category)); + out.append("\n"); + out.append("}"); +} +#endif +bool TimeStateResponse::decode_varint(uint32_t field_id, ProtoVarInt value) { + switch (field_id) { + case 2: { + this->missing_state = value.as_bool(); + return true; + } + case 3: { + this->hour = value.as_uint32(); + return true; + } + case 4: { + this->minute = value.as_uint32(); + return true; + } + case 5: { + this->second = value.as_uint32(); + return true; + } + default: + return false; + } +} +bool TimeStateResponse::decode_32bit(uint32_t field_id, Proto32Bit value) { + switch (field_id) { + case 1: { + this->key = value.as_fixed32(); + return true; + } + default: + return false; + } +} +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); + buffer.encode_uint32(4, this->minute); + buffer.encode_uint32(5, this->second); +} +#ifdef HAS_PROTO_MESSAGE_DUMP +void TimeStateResponse::dump_to(std::string &out) const { + __attribute__((unused)) char buffer[64]; + out.append("TimeStateResponse {\n"); + out.append(" key: "); + sprintf(buffer, "%" PRIu32, this->key); + out.append(buffer); + out.append("\n"); + + out.append(" missing_state: "); + out.append(YESNO(this->missing_state)); + out.append("\n"); + + out.append(" hour: "); + sprintf(buffer, "%" PRIu32, this->hour); + out.append(buffer); + out.append("\n"); + + out.append(" minute: "); + sprintf(buffer, "%" PRIu32, this->minute); + out.append(buffer); + out.append("\n"); + + out.append(" second: "); + sprintf(buffer, "%" PRIu32, this->second); + out.append(buffer); + out.append("\n"); + out.append("}"); +} +#endif +bool TimeCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { + switch (field_id) { + case 2: { + this->hour = value.as_uint32(); + return true; + } + case 3: { + this->minute = value.as_uint32(); + return true; + } + case 4: { + this->second = value.as_uint32(); + return true; + } + default: + return false; + } +} +bool TimeCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { + switch (field_id) { + case 1: { + this->key = value.as_fixed32(); + return true; + } + default: + return false; + } +} +void TimeCommandRequest::encode(ProtoWriteBuffer buffer) const { + buffer.encode_fixed32(1, this->key); + buffer.encode_uint32(2, this->hour); + buffer.encode_uint32(3, this->minute); + buffer.encode_uint32(4, this->second); +} +#ifdef HAS_PROTO_MESSAGE_DUMP +void TimeCommandRequest::dump_to(std::string &out) const { + __attribute__((unused)) char buffer[64]; + out.append("TimeCommandRequest {\n"); + out.append(" key: "); + sprintf(buffer, "%" PRIu32, this->key); + out.append(buffer); + out.append("\n"); + + out.append(" hour: "); + sprintf(buffer, "%" PRIu32, this->hour); + out.append(buffer); + out.append("\n"); + + out.append(" minute: "); + sprintf(buffer, "%" PRIu32, this->minute); + out.append(buffer); + out.append("\n"); + + out.append(" second: "); + sprintf(buffer, "%" PRIu32, this->second); + out.append(buffer); + out.append("\n"); + out.append("}"); +} +#endif } // namespace api } // namespace esphome diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index e361e6b8e1..2ae6fd2bb6 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -1919,6 +1919,56 @@ class DateCommandRequest : public ProtoMessage { bool decode_32bit(uint32_t field_id, Proto32Bit value) override; bool decode_varint(uint32_t field_id, ProtoVarInt value) override; }; +class ListEntitiesTimeResponse : public ProtoMessage { + public: + std::string object_id{}; + uint32_t key{0}; + std::string name{}; + std::string unique_id{}; + std::string icon{}; + bool disabled_by_default{false}; + enums::EntityCategory entity_category{}; + void encode(ProtoWriteBuffer buffer) const override; +#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 TimeStateResponse : public ProtoMessage { + public: + uint32_t key{0}; + bool missing_state{false}; + uint32_t hour{0}; + uint32_t minute{0}; + uint32_t second{0}; + void encode(ProtoWriteBuffer buffer) const override; +#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_varint(uint32_t field_id, ProtoVarInt value) override; +}; +class TimeCommandRequest : public ProtoMessage { + public: + uint32_t key{0}; + uint32_t hour{0}; + uint32_t minute{0}; + uint32_t second{0}; + void encode(ProtoWriteBuffer buffer) const override; +#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_varint(uint32_t field_id, ProtoVarInt value) override; +}; } // namespace api } // namespace esphome diff --git a/esphome/components/api/api_pb2_service.cpp b/esphome/components/api/api_pb2_service.cpp index 2067f530ce..7a97df1ce0 100644 --- a/esphome/components/api/api_pb2_service.cpp +++ b/esphome/components/api/api_pb2_service.cpp @@ -539,6 +539,24 @@ bool APIServerConnectionBase::send_date_state_response(const DateStateResponse & #endif #ifdef USE_DATETIME_DATE #endif +#ifdef USE_DATETIME_TIME +bool APIServerConnectionBase::send_list_entities_time_response(const ListEntitiesTimeResponse &msg) { +#ifdef HAS_PROTO_MESSAGE_DUMP + ESP_LOGVV(TAG, "send_list_entities_time_response: %s", msg.dump().c_str()); +#endif + return this->send_message_(msg, 103); +} +#endif +#ifdef USE_DATETIME_TIME +bool APIServerConnectionBase::send_time_state_response(const TimeStateResponse &msg) { +#ifdef HAS_PROTO_MESSAGE_DUMP + ESP_LOGVV(TAG, "send_time_state_response: %s", msg.dump().c_str()); +#endif + return this->send_message_(msg, 104); +} +#endif +#ifdef USE_DATETIME_TIME +#endif bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) { switch (msg_type) { case 1: { @@ -979,6 +997,17 @@ bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, ESP_LOGVV(TAG, "on_date_command_request: %s", msg.dump().c_str()); #endif this->on_date_command_request(msg); +#endif + break; + } + case 105: { +#ifdef USE_DATETIME_TIME + 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()); +#endif + this->on_time_command_request(msg); #endif break; } @@ -1279,6 +1308,19 @@ void APIServerConnection::on_date_command_request(const DateCommandRequest &msg) this->date_command(msg); } #endif +#ifdef USE_DATETIME_TIME +void APIServerConnection::on_time_command_request(const TimeCommandRequest &msg) { + if (!this->is_connection_setup()) { + this->on_no_setup_connection(); + return; + } + if (!this->is_authenticated()) { + this->on_unauthenticated_access(); + return; + } + this->time_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 effcfc30f4..095ce51b0f 100644 --- a/esphome/components/api/api_pb2_service.h +++ b/esphome/components/api/api_pb2_service.h @@ -270,6 +270,15 @@ class APIServerConnectionBase : public ProtoService { #endif #ifdef USE_DATETIME_DATE virtual void on_date_command_request(const DateCommandRequest &value){}; +#endif +#ifdef USE_DATETIME_TIME + bool send_list_entities_time_response(const ListEntitiesTimeResponse &msg); +#endif +#ifdef USE_DATETIME_TIME + bool send_time_state_response(const TimeStateResponse &msg); +#endif +#ifdef USE_DATETIME_TIME + virtual void on_time_command_request(const TimeCommandRequest &value){}; #endif protected: bool read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) override; @@ -328,6 +337,9 @@ class APIServerConnection : public APIServerConnectionBase { #ifdef USE_DATETIME_DATE virtual void date_command(const DateCommandRequest &msg) = 0; #endif +#ifdef USE_DATETIME_TIME + virtual void time_command(const TimeCommandRequest &msg) = 0; +#endif #ifdef USE_BLUETOOTH_PROXY virtual void subscribe_bluetooth_le_advertisements(const SubscribeBluetoothLEAdvertisementsRequest &msg) = 0; #endif @@ -417,6 +429,9 @@ class APIServerConnection : public APIServerConnectionBase { #ifdef USE_DATETIME_DATE void on_date_command_request(const DateCommandRequest &msg) override; #endif +#ifdef USE_DATETIME_TIME + void on_time_command_request(const TimeCommandRequest &msg) override; +#endif #ifdef USE_BLUETOOTH_PROXY void on_subscribe_bluetooth_le_advertisements_request(const SubscribeBluetoothLEAdvertisementsRequest &msg) override; #endif diff --git a/esphome/components/api/api_server.cpp b/esphome/components/api/api_server.cpp index b17555bb49..4c809126e6 100644 --- a/esphome/components/api/api_server.cpp +++ b/esphome/components/api/api_server.cpp @@ -264,6 +264,15 @@ void APIServer::on_date_update(datetime::DateEntity *obj) { } #endif +#ifdef USE_DATETIME_TIME +void APIServer::on_time_update(datetime::TimeEntity *obj) { + if (obj->is_internal()) + return; + for (auto &c : this->clients_) + c->send_time_state(obj); +} +#endif + #ifdef USE_TEXT void APIServer::on_text_update(text::Text *obj, const std::string &state) { if (obj->is_internal()) diff --git a/esphome/components/api/api_server.h b/esphome/components/api/api_server.h index c12355cc8b..8a9c26af73 100644 --- a/esphome/components/api/api_server.h +++ b/esphome/components/api/api_server.h @@ -69,6 +69,9 @@ class APIServer : public Component, public Controller { #ifdef USE_DATETIME_DATE void on_date_update(datetime::DateEntity *obj) override; #endif +#ifdef USE_DATETIME_TIME + void on_time_update(datetime::TimeEntity *obj) override; +#endif #ifdef USE_TEXT void on_text_update(text::Text *obj, const std::string &state) override; #endif diff --git a/esphome/components/api/list_entities.cpp b/esphome/components/api/list_entities.cpp index cd1841de5e..18685ee4d1 100644 --- a/esphome/components/api/list_entities.cpp +++ b/esphome/components/api/list_entities.cpp @@ -64,6 +64,10 @@ bool ListEntitiesIterator::on_number(number::Number *number) { return this->clie bool ListEntitiesIterator::on_date(datetime::DateEntity *date) { return this->client_->send_date_info(date); } #endif +#ifdef USE_DATETIME_TIME +bool ListEntitiesIterator::on_time(datetime::TimeEntity *time) { return this->client_->send_time_info(time); } +#endif + #ifdef USE_TEXT bool ListEntitiesIterator::on_text(text::Text *text) { return this->client_->send_text_info(text); } #endif diff --git a/esphome/components/api/list_entities.h b/esphome/components/api/list_entities.h index b49867048d..95a09fc25b 100644 --- a/esphome/components/api/list_entities.h +++ b/esphome/components/api/list_entities.h @@ -49,6 +49,9 @@ class ListEntitiesIterator : public ComponentIterator { #ifdef USE_DATETIME_DATE bool on_date(datetime::DateEntity *date) override; #endif +#ifdef USE_DATETIME_TIME + bool on_time(datetime::TimeEntity *time) override; +#endif #ifdef USE_TEXT bool on_text(text::Text *text) override; #endif diff --git a/esphome/components/api/subscribe_state.cpp b/esphome/components/api/subscribe_state.cpp index 4e7216ddef..5eb40cfa7e 100644 --- a/esphome/components/api/subscribe_state.cpp +++ b/esphome/components/api/subscribe_state.cpp @@ -45,6 +45,9 @@ bool InitialStateIterator::on_number(number::Number *number) { #ifdef USE_DATETIME_DATE bool InitialStateIterator::on_date(datetime::DateEntity *date) { return this->client_->send_date_state(date); } #endif +#ifdef USE_DATETIME_TIME +bool InitialStateIterator::on_time(datetime::TimeEntity *time) { return this->client_->send_time_state(time); } +#endif #ifdef USE_TEXT bool InitialStateIterator::on_text(text::Text *text) { return this->client_->send_text_state(text, text->state); } #endif diff --git a/esphome/components/api/subscribe_state.h b/esphome/components/api/subscribe_state.h index 4a96659b76..447f1707d2 100644 --- a/esphome/components/api/subscribe_state.h +++ b/esphome/components/api/subscribe_state.h @@ -46,6 +46,9 @@ class InitialStateIterator : public ComponentIterator { #ifdef USE_DATETIME_DATE bool on_date(datetime::DateEntity *date) override; #endif +#ifdef USE_DATETIME_TIME + bool on_time(datetime::TimeEntity *time) override; +#endif #ifdef USE_TEXT bool on_text(text::Text *text) override; #endif diff --git a/esphome/components/datetime/__init__.py b/esphome/components/datetime/__init__.py index 3ae99cfff6..b255a27303 100644 --- a/esphome/components/datetime/__init__.py +++ b/esphome/components/datetime/__init__.py @@ -3,38 +3,50 @@ import esphome.codegen as cg # import cpp_generator as cpp import esphome.config_validation as cv from esphome import automation -from esphome.components import mqtt +from esphome.components import mqtt, time from esphome.const import ( CONF_ID, + CONF_ON_TIME, CONF_ON_VALUE, + CONF_TIME_ID, CONF_TRIGGER_ID, CONF_TYPE, CONF_MQTT_ID, CONF_DATE, + CONF_TIME, CONF_YEAR, CONF_MONTH, CONF_DAY, + CONF_SECOND, + CONF_HOUR, + CONF_MINUTE, ) from esphome.core import CORE, coroutine_with_priority from esphome.cpp_generator import MockObjClass from esphome.cpp_helpers import setup_entity -CODEOWNERS = ["@rfdarter"] +CODEOWNERS = ["@rfdarter", "@jesserockz"] IS_PLATFORM_COMPONENT = True datetime_ns = cg.esphome_ns.namespace("datetime") DateTimeBase = datetime_ns.class_("DateTimeBase", cg.EntityBase) DateEntity = datetime_ns.class_("DateEntity", DateTimeBase) +TimeEntity = datetime_ns.class_("TimeEntity", DateTimeBase) # Actions DateSetAction = datetime_ns.class_("DateSetAction", automation.Action) +TimeSetAction = datetime_ns.class_("TimeSetAction", automation.Action) DateTimeStateTrigger = datetime_ns.class_( "DateTimeStateTrigger", automation.Trigger.template(cg.ESPTime) ) +OnTimeTrigger = datetime_ns.class_( + "OnTimeTrigger", automation.Trigger, cg.Component, cg.Parented.template(TimeEntity) +) + DATETIME_MODES = [ "DATE", "TIME", @@ -44,7 +56,6 @@ DATETIME_MODES = [ _DATETIME_SCHEMA = cv.Schema( { - cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTDatetimeComponent), cv.Optional(CONF_ON_VALUE): automation.validate_automation( { cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(DateTimeStateTrigger), @@ -57,6 +68,7 @@ _DATETIME_SCHEMA = cv.Schema( def date_schema(class_: MockObjClass) -> cv.Schema: schema = { cv.GenerateID(): cv.declare_id(class_), + cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTDateComponent), cv.Optional(CONF_TYPE, default="DATE"): cv.one_of("DATE", upper=True), } return _DATETIME_SCHEMA.extend(schema) @@ -65,7 +77,20 @@ def date_schema(class_: MockObjClass) -> cv.Schema: def time_schema(class_: MockObjClass) -> cv.Schema: schema = { cv.GenerateID(): cv.declare_id(class_), + cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTTimeComponent), cv.Optional(CONF_TYPE, default="TIME"): cv.one_of("TIME", upper=True), + cv.Inclusive( + CONF_ON_TIME, + group_of_inclusion=CONF_ON_TIME, + msg="`on_time` and `time_id` must both be specified", + ): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(OnTimeTrigger), + } + ), + cv.Inclusive(CONF_TIME_ID, group_of_inclusion=CONF_ON_TIME): cv.use_id( + time.RealTimeClock + ), } return _DATETIME_SCHEMA.extend(schema) @@ -88,6 +113,17 @@ async def setup_datetime_core_(var, config): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) await automation.build_automation(trigger, [(cg.ESPTime, "x")], conf) + rtc_id = config.get(CONF_TIME_ID) + rtc = None + if rtc_id is not None: + rtc = await cg.get_variable(rtc_id) + for conf in config.get(CONF_ON_TIME, []): + assert rtc is not None + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], rtc) + await automation.build_automation(trigger, [], conf) + await cg.register_component(trigger, conf) + await cg.register_parented(trigger, var) + async def register_datetime(var, config): if not CORE.has_id(config[CONF_ID]): @@ -109,18 +145,12 @@ async def to_code(config): cg.add_global(datetime_ns.using) -OPERATION_BASE_SCHEMA = cv.Schema( - { - cv.Required(CONF_ID): cv.use_id(DateEntity), - } -) - - @automation.register_action( "datetime.date.set", DateSetAction, - OPERATION_BASE_SCHEMA.extend( + cv.Schema( { + cv.Required(CONF_ID): cv.use_id(DateEntity), cv.Required(CONF_DATE): cv.Any( cv.returning_lambda, cv.date_time(allowed_time=False) ), @@ -144,3 +174,34 @@ async def datetime_date_set_to_code(config, action_id, template_arg, args): ) cg.add(action_var.set_date(date_struct)) return action_var + + +@automation.register_action( + "datetime.time.set", + TimeSetAction, + cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(TimeEntity), + cv.Required(CONF_TIME): cv.Any( + cv.returning_lambda, cv.date_time(allowed_date=False) + ), + } + ), +) +async def datetime_time_set_to_code(config, action_id, template_arg, args): + action_var = cg.new_Pvariable(action_id, template_arg) + await cg.register_parented(action_var, config[CONF_ID]) + + time_config = config[CONF_TIME] + if cg.is_template(time_config): + template_ = await cg.templatable(config[CONF_TIME], [], cg.ESPTime) + cg.add(action_var.set_time(template_)) + else: + time_struct = cg.StructInitializer( + cg.ESPTime, + ("second", time_config[CONF_SECOND]), + ("minute", time_config[CONF_MINUTE]), + ("hour", time_config[CONF_HOUR]), + ) + cg.add(action_var.set_time(time_struct)) + return action_var diff --git a/esphome/components/datetime/time_entity.cpp b/esphome/components/datetime/time_entity.cpp new file mode 100644 index 0000000000..98558152d7 --- /dev/null +++ b/esphome/components/datetime/time_entity.cpp @@ -0,0 +1,156 @@ +#include "time_entity.h" + +#ifdef USE_DATETIME_TIME + +#include "esphome/core/log.h" + +namespace esphome { +namespace datetime { + +static const char *const TAG = "datetime.time_entity"; + +void TimeEntity::publish_state() { + if (this->hour_ > 23) { + this->has_state_ = false; + ESP_LOGE(TAG, "Hour must be between 0 and 23"); + return; + } + if (this->minute_ > 59) { + this->has_state_ = false; + ESP_LOGE(TAG, "Minute must be between 0 and 59"); + return; + } + if (this->second_ > 59) { + this->has_state_ = false; + ESP_LOGE(TAG, "Second must be between 0 and 59"); + return; + } + this->has_state_ = true; + ESP_LOGD(TAG, "'%s': Sending time %02d:%02d:%02d", this->get_name().c_str(), this->hour_, this->minute_, + this->second_); + this->state_callback_.call(); +} + +TimeCall TimeEntity::make_call() { return TimeCall(this); } + +void TimeCall::validate_() { + if (this->hour_.has_value() && this->hour_ > 23) { + ESP_LOGE(TAG, "Hour must be between 0 and 23"); + this->hour_.reset(); + } + if (this->minute_.has_value() && this->minute_ > 59) { + ESP_LOGE(TAG, "Minute must be between 0 and 59"); + this->minute_.reset(); + } + if (this->second_.has_value() && this->second_ > 59) { + ESP_LOGE(TAG, "Second must be between 0 and 59"); + this->second_.reset(); + } +} + +void TimeCall::perform() { + this->validate_(); + ESP_LOGD(TAG, "'%s' - Setting", this->parent_->get_name().c_str()); + if (this->hour_.has_value()) { + ESP_LOGD(TAG, " Hour: %d", *this->hour_); + } + if (this->minute_.has_value()) { + ESP_LOGD(TAG, " Minute: %d", *this->minute_); + } + if (this->second_.has_value()) { + ESP_LOGD(TAG, " Second: %d", *this->second_); + } + this->parent_->control(*this); +} + +TimeCall &TimeCall::set_time(uint8_t hour, uint8_t minute, uint8_t second) { + this->hour_ = hour; + this->minute_ = minute; + this->second_ = second; + return *this; +}; + +TimeCall &TimeCall::set_time(ESPTime time) { return this->set_time(time.hour, time.minute, time.second); }; + +TimeCall &TimeCall::set_time(const std::string &time) { + ESPTime val{}; + if (!ESPTime::strptime(time, val)) { + ESP_LOGE(TAG, "Could not convert the time string to an ESPTime object"); + return *this; + } + return this->set_time(val); +} + +TimeCall TimeEntityRestoreState::to_call(TimeEntity *time) { + TimeCall call = time->make_call(); + call.set_time(this->hour, this->minute, this->second); + return call; +} + +void TimeEntityRestoreState::apply(TimeEntity *time) { + time->hour_ = this->hour; + time->minute_ = this->minute; + time->second_ = this->second; + time->publish_state(); +} + +#ifdef USE_TIME + +static const int MAX_TIMESTAMP_DRIFT = 900; // how far can the clock drift before we consider + // there has been a drastic time synchronization + +void OnTimeTrigger::loop() { + if (!this->parent_->has_state()) { + return; + } + ESPTime time = this->rtc_->now(); + if (!time.is_valid()) { + return; + } + if (this->last_check_.has_value()) { + if (*this->last_check_ > time && this->last_check_->timestamp - time.timestamp > MAX_TIMESTAMP_DRIFT) { + // We went back in time (a lot), probably caused by time synchronization + ESP_LOGW(TAG, "Time has jumped back!"); + } else if (*this->last_check_ >= time) { + // already handled this one + return; + } else if (time > *this->last_check_ && time.timestamp - this->last_check_->timestamp > MAX_TIMESTAMP_DRIFT) { + // We went ahead in time (a lot), probably caused by time synchronization + ESP_LOGW(TAG, "Time has jumped ahead!"); + this->last_check_ = time; + return; + } + + while (true) { + this->last_check_->increment_second(); + if (*this->last_check_ >= time) + break; + + if (this->matches_(*this->last_check_)) { + this->trigger(); + break; + } + } + } + + this->last_check_ = time; + if (!time.fields_in_range()) { + ESP_LOGW(TAG, "Time is out of range!"); + ESP_LOGD(TAG, "Second=%02u Minute=%02u Hour=%02u", time.second, time.minute, time.hour); + } + + if (this->matches_(time)) + this->trigger(); +} + +bool OnTimeTrigger::matches_(const ESPTime &time) const { + return time.is_valid() && time.hour == this->parent_->hour && time.minute == this->parent_->minute && + time.second == this->parent_->second; +} + +#endif + +} // namespace datetime +} // namespace esphome + +#endif // USE_DATETIME_TIME diff --git a/esphome/components/datetime/time_entity.h b/esphome/components/datetime/time_entity.h new file mode 100644 index 0000000000..956c09e2b4 --- /dev/null +++ b/esphome/components/datetime/time_entity.h @@ -0,0 +1,137 @@ +#pragma once + +#include "esphome/core/defines.h" + +#ifdef USE_DATETIME_TIME + +#include "esphome/core/automation.h" +#include "esphome/core/helpers.h" +#include "esphome/core/time.h" + +#include "datetime_base.h" + +#ifdef USE_TIME +#include "esphome/components/time/real_time_clock.h" +#endif + +namespace esphome { +namespace 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().empty()) { \ + ESP_LOGCONFIG(TAG, "%s Icon: '%s'", prefix, (obj)->get_icon().c_str()); \ + } \ + } + +class TimeCall; +class TimeEntity; + +struct TimeEntityRestoreState { + uint8_t hour; + uint8_t minute; + uint8_t second; + + TimeCall to_call(TimeEntity *time); + void apply(TimeEntity *time); +} __attribute__((packed)); + +class TimeEntity : public DateTimeBase { + protected: + uint8_t hour_; + uint8_t minute_; + uint8_t second_; + + public: + void publish_state(); + TimeCall make_call(); + + ESPTime state_as_esptime() const override { + ESPTime obj; + obj.hour = this->hour_; + obj.minute = this->minute_; + obj.second = this->second_; + return obj; + } + + const uint8_t &hour = hour_; + const uint8_t &minute = minute_; + const uint8_t &second = second_; + + protected: + friend class TimeCall; + friend struct TimeEntityRestoreState; + + virtual void control(const TimeCall &call) = 0; +}; + +class TimeCall { + public: + explicit TimeCall(TimeEntity *parent) : parent_(parent) {} + 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_hour(uint8_t hour) { + this->hour_ = hour; + return *this; + } + TimeCall &set_minute(uint8_t minute) { + this->minute_ = minute; + return *this; + } + TimeCall &set_second(uint8_t second) { + this->second_ = second; + return *this; + } + + optional get_hour() const { return this->hour_; } + optional get_minute() const { return this->minute_; } + optional get_second() const { return this->second_; } + + protected: + void validate_(); + + TimeEntity *parent_; + + optional hour_; + optional minute_; + optional second_; +}; + +template class TimeSetAction : public Action, public Parented { + public: + TEMPLATABLE_VALUE(ESPTime, time) + + void play(Ts... x) override { + auto call = this->parent_->make_call(); + + if (this->time_.has_value()) { + call.set_time(this->time_.value(x...)); + } + call.perform(); + } +}; + +#ifdef USE_TIME + +class OnTimeTrigger : public Trigger<>, public Component, public Parented { + public: + explicit OnTimeTrigger(time::RealTimeClock *rtc) : rtc_(rtc) {} + void loop() override; + + protected: + bool matches_(const ESPTime &time) const; + + time::RealTimeClock *rtc_; + optional last_check_; +}; + +#endif + +} // namespace datetime +} // namespace esphome + +#endif // USE_DATETIME_TIME diff --git a/esphome/components/mqtt/__init__.py b/esphome/components/mqtt/__init__.py index e442eb9146..b2c03c1546 100644 --- a/esphome/components/mqtt/__init__.py +++ b/esphome/components/mqtt/__init__.py @@ -113,7 +113,8 @@ MQTTSensorComponent = mqtt_ns.class_("MQTTSensorComponent", MQTTComponent) MQTTSwitchComponent = mqtt_ns.class_("MQTTSwitchComponent", MQTTComponent) MQTTTextSensor = mqtt_ns.class_("MQTTTextSensor", MQTTComponent) MQTTNumberComponent = mqtt_ns.class_("MQTTNumberComponent", MQTTComponent) -MQTTDatetimeComponent = mqtt_ns.class_("MQTTDatetimeComponent", MQTTComponent) +MQTTDateComponent = mqtt_ns.class_("MQTTDateComponent", MQTTComponent) +MQTTTimeComponent = mqtt_ns.class_("MQTTTimeComponent", MQTTComponent) MQTTTextComponent = mqtt_ns.class_("MQTTTextComponent", MQTTComponent) MQTTSelectComponent = mqtt_ns.class_("MQTTSelectComponent", MQTTComponent) MQTTButtonComponent = mqtt_ns.class_("MQTTButtonComponent", MQTTComponent) diff --git a/esphome/components/mqtt/mqtt_date.h b/esphome/components/mqtt/mqtt_date.h index 2776893d32..5147afe7e7 100644 --- a/esphome/components/mqtt/mqtt_date.h +++ b/esphome/components/mqtt/mqtt_date.h @@ -13,9 +13,9 @@ namespace mqtt { class MQTTDateComponent : public mqtt::MQTTComponent { public: - /** Construct this MQTTDatetimeComponent instance with the provided friendly_name and datetime + /** Construct this MQTTDateComponent instance with the provided friendly_name and date * - * @param datetime The datetime component. + * @param date The date component. */ explicit MQTTDateComponent(datetime::DateEntity *date); diff --git a/esphome/components/mqtt/mqtt_time.cpp b/esphome/components/mqtt/mqtt_time.cpp new file mode 100644 index 0000000000..332ef53cbc --- /dev/null +++ b/esphome/components/mqtt/mqtt_time.cpp @@ -0,0 +1,68 @@ +#include "mqtt_time.h" + +#include +#include "esphome/core/log.h" + +#include "mqtt_const.h" + +#ifdef USE_MQTT +#ifdef USE_DATETIME_TIME + +namespace esphome { +namespace mqtt { + +static const char *const TAG = "mqtt.datetime.time"; + +using namespace esphome::datetime; + +MQTTTimeComponent::MQTTTimeComponent(TimeEntity *time) : time_(time) {} + +void MQTTTimeComponent::setup() { + this->subscribe_json(this->get_command_topic_(), [this](const std::string &topic, JsonObject root) { + auto call = this->time_->make_call(); + if (root.containsKey("hour")) { + call.set_hour(root["hour"]); + } + if (root.containsKey("minute")) { + call.set_minute(root["minute"]); + } + if (root.containsKey("second")) { + call.set_second(root["second"]); + } + call.perform(); + }); + this->time_->add_on_state_callback( + [this]() { this->publish_state(this->time_->hour, this->time_->minute, this->time_->second); }); +} + +void MQTTTimeComponent::dump_config() { + ESP_LOGCONFIG(TAG, "MQTT Time '%s':", this->time_->get_name().c_str()); + LOG_MQTT_COMPONENT(true, true) +} + +std::string MQTTTimeComponent::component_type() const { return "time"; } +const EntityBase *MQTTTimeComponent::get_entity() const { return this->time_; } + +void MQTTTimeComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { + // Nothing extra to add here +} +bool MQTTTimeComponent::send_initial_state() { + if (this->time_->has_state()) { + return this->publish_state(this->time_->hour, this->time_->minute, this->time_->second); + } else { + return true; + } +} +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) { + root["hour"] = hour; + root["minute"] = minute; + root["second"] = second; + }); +} + +} // namespace mqtt +} // namespace esphome + +#endif // USE_DATETIME_TIME +#endif // USE_MQTT diff --git a/esphome/components/mqtt/mqtt_time.h b/esphome/components/mqtt/mqtt_time.h new file mode 100644 index 0000000000..b9dd822a73 --- /dev/null +++ b/esphome/components/mqtt/mqtt_time.h @@ -0,0 +1,45 @@ +#pragma once + +#include "esphome/core/defines.h" + +#ifdef USE_MQTT +#ifdef USE_DATETIME_TIME + +#include "esphome/components/datetime/time_entity.h" +#include "mqtt_component.h" + +namespace esphome { +namespace mqtt { + +class MQTTTimeComponent : public mqtt::MQTTComponent { + public: + /** Construct this MQTTTimeComponent instance with the provided friendly_name and time + * + * @param time The time entity. + */ + explicit MQTTTimeComponent(datetime::TimeEntity *time); + + // ========== INTERNAL METHODS ========== + // (In most use cases you won't need these) + /// Override setup. + void setup() override; + void dump_config() override; + + void send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) override; + + bool send_initial_state() override; + + bool publish_state(uint8_t hour, uint8_t minute, uint8_t second); + + protected: + std::string component_type() const override; + const EntityBase *get_entity() const override; + + datetime::TimeEntity *time_; +}; + +} // namespace mqtt +} // namespace esphome + +#endif // USE_DATETIME_DATE +#endif // USE_MQTT diff --git a/esphome/components/template/datetime/__init__.py b/esphome/components/template/datetime/__init__.py index 16f341301e..53d9d1b9d3 100644 --- a/esphome/components/template/datetime/__init__.py +++ b/esphome/components/template/datetime/__init__.py @@ -9,7 +9,11 @@ from esphome.const import ( CONF_RESTORE_VALUE, CONF_SET_ACTION, CONF_DAY, + CONF_HOUR, + CONF_MINUTE, CONF_MONTH, + CONF_SECOND, + CONF_TYPE, CONF_YEAR, ) @@ -23,6 +27,10 @@ TemplateDate = template_ns.class_( "TemplateDate", datetime.DateEntity, cg.PollingComponent ) +TemplateTime = template_ns.class_( + "TemplateTime", datetime.TimeEntity, cg.PollingComponent +) + def validate(config): config = config.copy() @@ -63,6 +71,13 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_INITIAL_VALUE): cv.date_time(allowed_time=False), } ), + "TIME": datetime.time_schema(TemplateTime) + .extend(_BASE_SCHEMA) + .extend( + { + cv.Optional(CONF_INITIAL_VALUE): cv.date_time(allowed_date=False), + } + ), }, upper=True, ), @@ -85,13 +100,22 @@ async def to_code(config): cg.add(var.set_restore_value(config[CONF_RESTORE_VALUE])) if initial_value := config.get(CONF_INITIAL_VALUE): - date_struct = cg.StructInitializer( - cg.ESPTime, - ("day_of_month", initial_value[CONF_DAY]), - ("month", initial_value[CONF_MONTH]), - ("year", initial_value[CONF_YEAR]), - ) - cg.add(var.set_initial_value(date_struct)) + if config[CONF_TYPE] == "DATE": + date_struct = cg.StructInitializer( + cg.ESPTime, + ("day_of_month", initial_value[CONF_DAY]), + ("month", initial_value[CONF_MONTH]), + ("year", initial_value[CONF_YEAR]), + ) + cg.add(var.set_initial_value(date_struct)) + elif config[CONF_TYPE] == "TIME": + time_struct = cg.StructInitializer( + cg.ESPTime, + ("second", initial_value[CONF_SECOND]), + ("minute", initial_value[CONF_MINUTE]), + ("hour", initial_value[CONF_HOUR]), + ) + cg.add(var.set_initial_value(time_struct)) if CONF_SET_ACTION in config: await automation.build_automation( diff --git a/esphome/components/template/datetime/template_time.cpp b/esphome/components/template/datetime/template_time.cpp new file mode 100644 index 0000000000..0e4d734d16 --- /dev/null +++ b/esphome/components/template/datetime/template_time.cpp @@ -0,0 +1,111 @@ +#include "template_time.h" + +#ifdef USE_DATETIME_TIME + +#include "esphome/core/log.h" + +namespace esphome { +namespace template_ { + +static const char *const TAG = "template.time"; + +void TemplateTime::setup() { + if (this->f_.has_value()) + return; + + ESPTime state{}; + + if (!this->restore_value_) { + state = this->initial_value_; + } else { + datetime::TimeEntityRestoreState temp; + this->pref_ = + global_preferences->make_preference(194434060U ^ this->get_object_id_hash()); + if (this->pref_.load(&temp)) { + temp.apply(this); + return; + } else { + // set to inital value if loading from pref failed + state = this->initial_value_; + } + } + + this->hour_ = state.hour; + this->minute_ = state.minute; + this->second_ = state.second; + this->publish_state(); +} + +void TemplateTime::update() { + if (!this->f_.has_value()) + return; + + auto val = (*this->f_)(); + if (!val.has_value()) + return; + + this->hour_ = val->hour; + this->minute_ = val->minute; + this->second_ = val->second; + this->publish_state(); +} + +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(); + + ESPTime value = {}; + if (has_hour) + value.hour = *call.get_hour(); + + if (has_minute) + value.minute = *call.get_minute(); + + if (has_second) + value.second = *call.get_second(); + + this->set_trigger_->trigger(value); + + if (this->optimistic_) { + if (has_hour) + this->hour_ = *call.get_hour(); + if (has_minute) + this->minute_ = *call.get_minute(); + if (has_second) + this->second_ = *call.get_second(); + this->publish_state(); + } + + if (this->restore_value_) { + datetime::TimeEntityRestoreState temp = {}; + if (has_hour) { + temp.hour = *call.get_hour(); + } else { + temp.hour = this->hour_; + } + if (has_minute) { + temp.minute = *call.get_minute(); + } else { + temp.minute = this->minute_; + } + if (has_second) { + temp.second = *call.get_second(); + } else { + temp.second = this->second_; + } + + this->pref_.save(&temp); + } +} + +void TemplateTime::dump_config() { + LOG_DATETIME_TIME("", "Template Time", this); + ESP_LOGCONFIG(TAG, " Optimistic: %s", YESNO(this->optimistic_)); + LOG_UPDATE_INTERVAL(this); +} + +} // namespace template_ +} // namespace esphome + +#endif // USE_DATETIME_TIME diff --git a/esphome/components/template/datetime/template_time.h b/esphome/components/template/datetime/template_time.h new file mode 100644 index 0000000000..4a7c0098ec --- /dev/null +++ b/esphome/components/template/datetime/template_time.h @@ -0,0 +1,46 @@ +#pragma once + +#include "esphome/core/defines.h" + +#ifdef USE_DATETIME_TIME + +#include "esphome/components/datetime/time_entity.h" +#include "esphome/core/automation.h" +#include "esphome/core/component.h" +#include "esphome/core/preferences.h" +#include "esphome/core/time.h" + +namespace esphome { +namespace template_ { + +class TemplateTime : public datetime::TimeEntity, public PollingComponent { + public: + void set_template(std::function()> &&f) { this->f_ = f; } + + void setup() override; + void update() override; + void dump_config() override; + 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_value(ESPTime initial_value) { this->initial_value_ = initial_value; } + void set_restore_value(bool restore_value) { this->restore_value_ = restore_value; } + + protected: + void control(const datetime::TimeCall &call) override; + + bool optimistic_{false}; + ESPTime initial_value_{}; + bool restore_value_{false}; + Trigger *set_trigger_ = new Trigger(); + optional()>> f_; + + ESPPreferenceObject pref_; +}; + +} // namespace template_ +} // namespace esphome + +#endif // USE_DATETIME_TIME diff --git a/esphome/components/web_server/list_entities.cpp b/esphome/components/web_server/list_entities.cpp index 2252f55008..dd9fd4afe4 100644 --- a/esphome/components/web_server/list_entities.cpp +++ b/esphome/components/web_server/list_entities.cpp @@ -113,6 +113,13 @@ bool ListEntitiesIterator::on_date(datetime::DateEntity *date) { } #endif +#ifdef USE_DATETIME_TIME +bool ListEntitiesIterator::on_time(datetime::TimeEntity *time) { + this->web_server_->events_.send(this->web_server_->time_json(time, DETAIL_ALL).c_str(), "state"); + return true; +} +#endif + #ifdef USE_TEXT bool ListEntitiesIterator::on_text(text::Text *text) { if (this->web_server_->events_.count() == 0) diff --git a/esphome/components/web_server/list_entities.h b/esphome/components/web_server/list_entities.h index cd7c9099d6..fc48186b32 100644 --- a/esphome/components/web_server/list_entities.h +++ b/esphome/components/web_server/list_entities.h @@ -44,6 +44,9 @@ class ListEntitiesIterator : public ComponentIterator { #ifdef USE_DATETIME_DATE bool on_date(datetime::DateEntity *date) override; #endif +#ifdef USE_DATETIME_TIME + bool on_time(datetime::TimeEntity *time) override; +#endif #ifdef USE_TEXT bool on_text(text::Text *text) override; #endif diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index 6c3e4e5eec..b48a39cbcb 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -921,6 +921,52 @@ std::string WebServer::date_json(datetime::DateEntity *obj, JsonDetail start_con } #endif // USE_DATETIME_DATE +#ifdef USE_DATETIME_TIME +void WebServer::on_time_update(datetime::TimeEntity *obj) { + this->events_.send(this->time_json(obj, DETAIL_STATE).c_str(), "state"); +} +void WebServer::handle_time_request(AsyncWebServerRequest *request, const UrlMatch &match) { + for (auto *obj : App.get_times()) { + if (obj->get_object_id() != match.id) + continue; + if (request->method() == HTTP_GET && match.method.empty()) { + std::string data = this->time_json(obj, DETAIL_STATE); + request->send(200, "application/json", data.c_str()); + return; + } + if (match.method != "set") { + request->send(404); + return; + } + + auto call = obj->make_call(); + + if (!request->hasParam("value")) { + request->send(409); + return; + } + + if (request->hasParam("value")) { + std::string value = request->getParam("value")->value().c_str(); + call.set_time(value); + } + + this->schedule_([call]() mutable { call.perform(); }); + request->send(200); + return; + } + request->send(404); +} +std::string WebServer::time_json(datetime::TimeEntity *obj, JsonDetail start_config) { + return json::build_json([obj, start_config](JsonObject root) { + set_json_id(root, obj, "time-" + obj->get_object_id(), start_config); + std::string value = str_sprintf("%02d:%02d:%02d", obj->hour, obj->minute, obj->second); + root["value"] = value; + root["state"] = value; + }); +} +#endif // USE_DATETIME_TIME + #ifdef USE_TEXT void WebServer::on_text_update(text::Text *obj, const std::string &state) { if (this->events_.count() == 0) @@ -1320,6 +1366,11 @@ bool WebServer::canHandle(AsyncWebServerRequest *request) { return true; #endif +#ifdef USE_DATETIME_TIME + if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain == "time") + return true; +#endif + #ifdef USE_TEXT if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain == "text") return true; @@ -1445,6 +1496,13 @@ void WebServer::handleRequest(AsyncWebServerRequest *request) { } #endif +#ifdef USE_DATETIME_TIME + if (match.domain == "time") { + this->handle_time_request(request, match); + return; + } +#endif + #ifdef USE_TEXT if (match.domain == "text") { this->handle_text_request(request, match); diff --git a/esphome/components/web_server/web_server.h b/esphome/components/web_server/web_server.h index 57cbbe1339..1935f8d076 100644 --- a/esphome/components/web_server/web_server.h +++ b/esphome/components/web_server/web_server.h @@ -8,9 +8,9 @@ #include #ifdef USE_ESP32 -#include #include #include +#include #endif #if USE_WEBSERVER_VERSION >= 2 @@ -230,6 +230,15 @@ class WebServer : public Controller, public Component, public AsyncWebHandler { std::string date_json(datetime::DateEntity *obj, JsonDetail start_config); #endif +#ifdef USE_DATETIME_TIME + void on_time_update(datetime::TimeEntity *obj) override; + /// Handle a time request under '/time/'. + void handle_time_request(AsyncWebServerRequest *request, const UrlMatch &match); + + /// Dump the time state with its value as a JSON string. + std::string time_json(datetime::TimeEntity *obj, JsonDetail start_config); +#endif + #ifdef USE_TEXT void on_text_update(text::Text *obj, const std::string &state) override; /// Handle a text input request under '/text/'. diff --git a/esphome/core/application.h b/esphome/core/application.h index 26125dd935..73330d27e3 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -42,6 +42,9 @@ #ifdef USE_DATETIME_DATE #include "esphome/components/datetime/date_entity.h" #endif +#ifdef USE_DATETIME_TIME +#include "esphome/components/datetime/time_entity.h" +#endif #ifdef USE_TEXT #include "esphome/components/text/text.h" #endif @@ -128,6 +131,10 @@ class Application { void register_date(datetime::DateEntity *date) { this->dates_.push_back(date); } #endif +#ifdef USE_DATETIME_TIME + void register_time(datetime::TimeEntity *time) { this->times_.push_back(time); } +#endif + #ifdef USE_TEXT void register_text(text::Text *text) { this->texts_.push_back(text); } #endif @@ -305,6 +312,15 @@ class Application { return nullptr; } #endif +#ifdef USE_DATETIME_TIME + const std::vector &get_times() { return this->times_; } + datetime::TimeEntity *get_time_by_key(uint32_t key, bool include_internal = false) { + for (auto *obj : this->times_) + if (obj->get_object_id_hash() == key && (include_internal || !obj->is_internal())) + return obj; + return nullptr; + } +#endif #ifdef USE_TEXT const std::vector &get_texts() { return this->texts_; } text::Text *get_text_by_key(uint32_t key, bool include_internal = false) { @@ -401,6 +417,9 @@ class Application { #ifdef USE_DATETIME_DATE std::vector dates_{}; #endif +#ifdef USE_DATETIME_TIME + std::vector times_{}; +#endif #ifdef USE_SELECT std::vector selects_{}; #endif diff --git a/esphome/core/component_iterator.cpp b/esphome/core/component_iterator.cpp index 1e06221af6..228cf64d54 100644 --- a/esphome/core/component_iterator.cpp +++ b/esphome/core/component_iterator.cpp @@ -217,6 +217,21 @@ void ComponentIterator::advance() { } break; #endif +#ifdef USE_DATETIME_TIME + case IteratorState::DATETIME_TIME: + if (this->at_ >= App.get_times().size()) { + advance_platform = true; + } else { + auto *time = App.get_times()[this->at_]; + if (time->is_internal() && !this->include_internal_) { + success = true; + break; + } else { + success = this->on_time(time); + } + } + break; +#endif #ifdef USE_TEXT case IteratorState::TEXT: if (this->at_ >= App.get_texts().size()) { diff --git a/esphome/core/component_iterator.h b/esphome/core/component_iterator.h index 02c6dddacb..d7f19f2850 100644 --- a/esphome/core/component_iterator.h +++ b/esphome/core/component_iterator.h @@ -60,6 +60,9 @@ class ComponentIterator { #ifdef USE_DATETIME_DATE virtual bool on_date(datetime::DateEntity *date) = 0; #endif +#ifdef USE_DATETIME_TIME + virtual bool on_time(datetime::TimeEntity *time) = 0; +#endif #ifdef USE_TEXT virtual bool on_text(text::Text *text) = 0; #endif @@ -120,6 +123,9 @@ class ComponentIterator { #ifdef USE_DATETIME_DATE DATETIME_DATE, #endif +#ifdef USE_DATETIME_TIME + DATETIME_TIME, +#endif #ifdef USE_TEXT TEXT, #endif diff --git a/esphome/core/controller.cpp b/esphome/core/controller.cpp index 43b8fea50c..db5818d455 100644 --- a/esphome/core/controller.cpp +++ b/esphome/core/controller.cpp @@ -65,6 +65,12 @@ void Controller::setup_controller(bool include_internal) { obj->add_on_state_callback([this, obj]() { this->on_date_update(obj); }); } #endif +#ifdef USE_DATETIME_TIME + for (auto *obj : App.get_times()) { + if (include_internal || !obj->is_internal()) + obj->add_on_state_callback([this, obj]() { this->on_time_update(obj); }); + } +#endif #ifdef USE_TEXT for (auto *obj : App.get_texts()) { if (include_internal || !obj->is_internal()) diff --git a/esphome/core/controller.h b/esphome/core/controller.h index c31cd22d07..9b1cfd93c6 100644 --- a/esphome/core/controller.h +++ b/esphome/core/controller.h @@ -34,6 +34,9 @@ #ifdef USE_DATETIME_DATE #include "esphome/components/datetime/date_entity.h" #endif +#ifdef USE_DATETIME_TIME +#include "esphome/components/datetime/time_entity.h" +#endif #ifdef USE_TEXT #include "esphome/components/text/text.h" #endif @@ -85,6 +88,9 @@ class Controller { #ifdef USE_DATETIME_DATE virtual void on_date_update(datetime::DateEntity *obj){}; #endif +#ifdef USE_DATETIME_TIME + virtual void on_time_update(datetime::TimeEntity *obj){}; +#endif #ifdef USE_TEXT virtual void on_text_update(text::Text *obj, const std::string &state){}; #endif diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 501dccc6fa..22153de5de 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -36,6 +36,7 @@ #define USE_NUMBER #define USE_DATETIME #define USE_DATETIME_DATE +#define USE_DATETIME_TIME #define USE_OTA #define USE_OTA_PASSWORD #define USE_OTA_STATE_CALLBACK diff --git a/script/ci-custom.py b/script/ci-custom.py index 1ad44dc930..3be7be76a2 100755 --- a/script/ci-custom.py +++ b/script/ci-custom.py @@ -622,6 +622,7 @@ def lint_trailing_whitespace(fname, match): "esphome/components/climate/climate.h", "esphome/components/cover/cover.h", "esphome/components/datetime/date_entity.h", + "esphome/components/datetime/time_entity.h", "esphome/components/display/display.h", "esphome/components/fan/fan.h", "esphome/components/i2c/i2c.h", diff --git a/tests/components/datetime/date.all.yaml b/tests/components/datetime/test.all.yaml similarity index 100% rename from tests/components/datetime/date.all.yaml rename to tests/components/datetime/test.all.yaml diff --git a/tests/components/template/test.all.yaml b/tests/components/template/test.all.yaml index e50ffd7f67..29dc83b649 100644 --- a/tests/components/template/test.all.yaml +++ b/tests/components/template/test.all.yaml @@ -153,3 +153,16 @@ datetime: - x.year - x.month - x.day_of_month + - platform: template + name: Time + id: test_time + type: time + set_action: + - logger.log: "set_value" + on_value: + - logger.log: + format: "Time: %02d:%02d:%02d" + args: + - x.hour + - x.minute + - x.second From 55c49281a224966b4e40b38c0e2e56f39cf93e3b Mon Sep 17 00:00:00 2001 From: MRemy2 <95053616+MRemy2@users.noreply.github.com> Date: Tue, 9 Apr 2024 04:49:37 +0300 Subject: [PATCH 1210/2101] Fix Match by IRK (#6499) Co-authored-by: Remus --- esphome/components/ble_presence/ble_presence_device.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/esphome/components/ble_presence/ble_presence_device.h b/esphome/components/ble_presence/ble_presence_device.h index 0d86f6a40d..e74c2f4f45 100644 --- a/esphome/components/ble_presence/ble_presence_device.h +++ b/esphome/components/ble_presence/ble_presence_device.h @@ -73,8 +73,7 @@ class BLEPresenceDevice : public binary_sensor::BinarySensorInitiallyOff, break; case MATCH_BY_IRK: if (resolve_irk_(device.address_uint64(), this->irk_)) { - this->publish_state(true); - this->found_ = true; + this->set_found_(true); return true; } break; From c66b2c52c1fb22fcc872edf8bf0caa5f3a369344 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 9 Apr 2024 13:53:57 +1200 Subject: [PATCH 1211/2101] Add rmt_channel to remote_transmitter and remote_receiver (#6497) * Add rmt_channel to remote_transmitter and remote_receiver * Add codeowner * Add tests --- CODEOWNERS | 1 + esphome/components/esp32_rmt/__init__.py | 55 ++++++ .../components/esp32_rmt_led_strip/light.py | 26 +-- .../components/remote_base/remote_base.cpp | 3 + esphome/components/remote_base/remote_base.h | 5 +- .../components/remote_receiver/__init__.py | 11 +- .../remote_receiver/remote_receiver.h | 5 +- .../components/remote_transmitter/__init__.py | 10 +- .../remote_transmitter/remote_transmitter.h | 11 +- esphome/const.py | 1 + .../remote_receiver/esp32-common.yaml | 18 ++ .../remote_receiver/test.esp32-c3-idf.yaml | 6 + .../remote_receiver/test.esp32-c3.yaml | 6 + .../remote_receiver/test.esp32-idf.yaml | 6 + .../remote_receiver/test.esp32-s3-idf.yaml | 6 + .../remote_receiver/test.esp32.yaml | 6 + .../remote_receiver/test.esp8266.yaml | 17 ++ .../remote_transmitter/common-buttons.yaml | 178 ++++++++++++++++++ .../remote_transmitter/esp32-common.yaml | 8 + .../remote_transmitter/test.esp32-c3-idf.yaml | 6 + .../remote_transmitter/test.esp32-c3.yaml | 6 + .../remote_transmitter/test.esp32-idf.yaml | 6 + .../remote_transmitter/test.esp32-s3-idf.yaml | 6 + .../remote_transmitter/test.esp32.yaml | 6 + .../remote_transmitter/test.esp8266.yaml | 7 + 25 files changed, 383 insertions(+), 33 deletions(-) create mode 100644 esphome/components/esp32_rmt/__init__.py create mode 100644 tests/components/remote_receiver/esp32-common.yaml create mode 100644 tests/components/remote_receiver/test.esp32-c3-idf.yaml create mode 100644 tests/components/remote_receiver/test.esp32-c3.yaml create mode 100644 tests/components/remote_receiver/test.esp32-idf.yaml create mode 100644 tests/components/remote_receiver/test.esp32-s3-idf.yaml create mode 100644 tests/components/remote_receiver/test.esp32.yaml create mode 100644 tests/components/remote_receiver/test.esp8266.yaml create mode 100644 tests/components/remote_transmitter/common-buttons.yaml create mode 100644 tests/components/remote_transmitter/esp32-common.yaml create mode 100644 tests/components/remote_transmitter/test.esp32-c3-idf.yaml create mode 100644 tests/components/remote_transmitter/test.esp32-c3.yaml create mode 100644 tests/components/remote_transmitter/test.esp32-idf.yaml create mode 100644 tests/components/remote_transmitter/test.esp32-s3-idf.yaml create mode 100644 tests/components/remote_transmitter/test.esp32.yaml create mode 100644 tests/components/remote_transmitter/test.esp8266.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 4a3205acf0..126513943f 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -115,6 +115,7 @@ esphome/components/esp32_ble_server/* @Rapsssito @clydebarrow @jesserockz esphome/components/esp32_camera_web_server/* @ayufan esphome/components/esp32_can/* @Sympatron esphome/components/esp32_improv/* @jesserockz +esphome/components/esp32_rmt/* @jesserockz esphome/components/esp32_rmt_led_strip/* @jesserockz esphome/components/esp8266/* @esphome/core esphome/components/ethernet_info/* @gtjadsonsantos diff --git a/esphome/components/esp32_rmt/__init__.py b/esphome/components/esp32_rmt/__init__.py new file mode 100644 index 0000000000..bda240680b --- /dev/null +++ b/esphome/components/esp32_rmt/__init__.py @@ -0,0 +1,55 @@ +import esphome.config_validation as cv +import esphome.codegen as cg + +from esphome.components import esp32 + +CODEOWNERS = ["@jesserockz"] + +RMT_TX_CHANNELS = { + esp32.const.VARIANT_ESP32: [0, 1, 2, 3, 4, 5, 6, 7], + esp32.const.VARIANT_ESP32S2: [0, 1, 2, 3], + esp32.const.VARIANT_ESP32S3: [0, 1, 2, 3], + esp32.const.VARIANT_ESP32C3: [0, 1], + esp32.const.VARIANT_ESP32C6: [0, 1], + esp32.const.VARIANT_ESP32H2: [0, 1], +} + +RMT_RX_CHANNELS = { + esp32.const.VARIANT_ESP32: [0, 1, 2, 3, 4, 5, 6, 7], + esp32.const.VARIANT_ESP32S2: [0, 1, 2, 3], + esp32.const.VARIANT_ESP32S3: [4, 5, 6, 7], + esp32.const.VARIANT_ESP32C3: [2, 3], + esp32.const.VARIANT_ESP32C6: [2, 3], + esp32.const.VARIANT_ESP32H2: [2, 3], +} + +rmt_channel_t = cg.global_ns.enum("rmt_channel_t") +RMT_CHANNEL_ENUMS = { + 0: rmt_channel_t.RMT_CHANNEL_0, + 1: rmt_channel_t.RMT_CHANNEL_1, + 2: rmt_channel_t.RMT_CHANNEL_2, + 3: rmt_channel_t.RMT_CHANNEL_3, + 4: rmt_channel_t.RMT_CHANNEL_4, + 5: rmt_channel_t.RMT_CHANNEL_5, + 6: rmt_channel_t.RMT_CHANNEL_6, + 7: rmt_channel_t.RMT_CHANNEL_7, +} + + +def validate_rmt_channel(*, tx: bool): + + rmt_channels = RMT_TX_CHANNELS if tx else RMT_RX_CHANNELS + + def _validator(value): + cv.only_on_esp32(value) + value = cv.int_(value) + variant = esp32.get_esp32_variant() + if variant not in rmt_channels: + raise cv.Invalid(f"ESP32 variant {variant} does not support RMT.") + if value not in rmt_channels[variant]: + raise cv.Invalid( + f"RMT channel {value} does not support {'transmitting' if tx else 'receiving'} for ESP32 variant {variant}." + ) + return cv.enum(RMT_CHANNEL_ENUMS)(value) + + return _validator diff --git a/esphome/components/esp32_rmt_led_strip/light.py b/esphome/components/esp32_rmt_led_strip/light.py index d38c7abeb8..3442940e3f 100644 --- a/esphome/components/esp32_rmt_led_strip/light.py +++ b/esphome/components/esp32_rmt_led_strip/light.py @@ -3,7 +3,7 @@ from dataclasses import dataclass import esphome.codegen as cg import esphome.config_validation as cv from esphome import pins -from esphome.components import esp32, light +from esphome.components import esp32_rmt, light from esphome.const import ( CONF_CHIPSET, CONF_MAX_REFRESH_RATE, @@ -11,6 +11,7 @@ from esphome.const import ( CONF_OUTPUT_ID, CONF_PIN, CONF_RGB_ORDER, + CONF_RMT_CHANNEL, ) CODEOWNERS = ["@jesserockz"] @@ -57,27 +58,6 @@ CONF_BIT0_HIGH = "bit0_high" CONF_BIT0_LOW = "bit0_low" CONF_BIT1_HIGH = "bit1_high" CONF_BIT1_LOW = "bit1_low" -CONF_RMT_CHANNEL = "rmt_channel" - -RMT_CHANNELS = { - esp32.const.VARIANT_ESP32: [0, 1, 2, 3, 4, 5, 6, 7], - esp32.const.VARIANT_ESP32S2: [0, 1, 2, 3], - esp32.const.VARIANT_ESP32S3: [0, 1, 2, 3], - esp32.const.VARIANT_ESP32C3: [0, 1], - esp32.const.VARIANT_ESP32C6: [0, 1], - esp32.const.VARIANT_ESP32H2: [0, 1], -} - - -def _validate_rmt_channel(value): - variant = esp32.get_esp32_variant() - if variant not in RMT_CHANNELS: - raise cv.Invalid(f"ESP32 variant {variant} does not support RMT.") - if value not in RMT_CHANNELS[variant]: - raise cv.Invalid( - f"RMT channel {value} is not supported for ESP32 variant {variant}." - ) - return value CONFIG_SCHEMA = cv.All( @@ -87,7 +67,7 @@ CONFIG_SCHEMA = cv.All( cv.Required(CONF_PIN): pins.internal_gpio_output_pin_number, cv.Required(CONF_NUM_LEDS): cv.positive_not_null_int, cv.Required(CONF_RGB_ORDER): cv.enum(RGB_ORDERS, upper=True), - cv.Required(CONF_RMT_CHANNEL): _validate_rmt_channel, + cv.Required(CONF_RMT_CHANNEL): esp32_rmt.validate_rmt_channel(tx=True), cv.Optional(CONF_MAX_REFRESH_RATE): cv.positive_time_period_microseconds, cv.Optional(CONF_CHIPSET): cv.one_of(*CHIPSETS, upper=True), cv.Optional(CONF_IS_RGBW, default=False): cv.boolean, diff --git a/esphome/components/remote_base/remote_base.cpp b/esphome/components/remote_base/remote_base.cpp index f3e86aaab6..0e9cef8cca 100644 --- a/esphome/components/remote_base/remote_base.cpp +++ b/esphome/components/remote_base/remote_base.cpp @@ -15,6 +15,9 @@ RemoteRMTChannel::RemoteRMTChannel(uint8_t mem_block_num) : mem_block_num_(mem_b next_rmt_channel = rmt_channel_t(int(next_rmt_channel) + mem_block_num); } +RemoteRMTChannel::RemoteRMTChannel(rmt_channel_t channel, uint8_t mem_block_num) + : channel_(channel), mem_block_num_(mem_block_num) {} + void RemoteRMTChannel::config_rmt(rmt_config_t &rmt) { if (rmt_channel_t(int(this->channel_) + this->mem_block_num_) > RMT_CHANNEL_MAX) { this->mem_block_num_ = int(RMT_CHANNEL_MAX) - int(this->channel_); diff --git a/esphome/components/remote_base/remote_base.h b/esphome/components/remote_base/remote_base.h index ebbb528a23..b2a4b543ea 100644 --- a/esphome/components/remote_base/remote_base.h +++ b/esphome/components/remote_base/remote_base.h @@ -3,10 +3,10 @@ #pragma once +#include "esphome/components/binary_sensor/binary_sensor.h" +#include "esphome/core/automation.h" #include "esphome/core/component.h" #include "esphome/core/hal.h" -#include "esphome/core/automation.h" -#include "esphome/components/binary_sensor/binary_sensor.h" #ifdef USE_ESP32 #include @@ -86,6 +86,7 @@ class RemoteComponentBase { class RemoteRMTChannel { public: explicit RemoteRMTChannel(uint8_t mem_block_num = 1); + explicit RemoteRMTChannel(rmt_channel_t channel, uint8_t mem_block_num = 1); void config_rmt(rmt_config_t &rmt); void set_clock_divider(uint8_t clock_divider) { this->clock_divider_ = clock_divider; } diff --git a/esphome/components/remote_receiver/__init__.py b/esphome/components/remote_receiver/__init__.py index 5737957adb..6a68c8b254 100644 --- a/esphome/components/remote_receiver/__init__.py +++ b/esphome/components/remote_receiver/__init__.py @@ -1,7 +1,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import pins -from esphome.components import remote_base +from esphome.components import remote_base, esp32_rmt from esphome.const import ( CONF_BUFFER_SIZE, CONF_DUMP, @@ -11,6 +11,7 @@ from esphome.const import ( CONF_PIN, CONF_TOLERANCE, CONF_MEMORY_BLOCKS, + CONF_RMT_CHANNEL, ) from esphome.core import CORE, TimePeriod @@ -45,6 +46,7 @@ CONFIG_SCHEMA = remote_base.validate_triggers( CONF_IDLE, default="10ms" ): cv.positive_time_period_microseconds, cv.Optional(CONF_MEMORY_BLOCKS, default=3): cv.Range(min=1, max=8), + cv.Optional(CONF_RMT_CHANNEL): esp32_rmt.validate_rmt_channel(tx=False), } ).extend(cv.COMPONENT_SCHEMA) ) @@ -53,7 +55,12 @@ CONFIG_SCHEMA = remote_base.validate_triggers( async def to_code(config): pin = await cg.gpio_pin_expression(config[CONF_PIN]) if CORE.is_esp32: - var = cg.new_Pvariable(config[CONF_ID], pin, config[CONF_MEMORY_BLOCKS]) + if (rmt_channel := config.get(CONF_RMT_CHANNEL, None)) is not None: + var = cg.new_Pvariable( + config[CONF_ID], pin, rmt_channel, config[CONF_MEMORY_BLOCKS] + ) + else: + var = cg.new_Pvariable(config[CONF_ID], pin, config[CONF_MEMORY_BLOCKS]) else: var = cg.new_Pvariable(config[CONF_ID], pin) diff --git a/esphome/components/remote_receiver/remote_receiver.h b/esphome/components/remote_receiver/remote_receiver.h index c1343a8603..f29145a59e 100644 --- a/esphome/components/remote_receiver/remote_receiver.h +++ b/esphome/components/remote_receiver/remote_receiver.h @@ -1,7 +1,7 @@ #pragma once -#include "esphome/core/component.h" #include "esphome/components/remote_base/remote_base.h" +#include "esphome/core/component.h" #include @@ -38,6 +38,9 @@ class RemoteReceiverComponent : public remote_base::RemoteReceiverBase, #ifdef USE_ESP32 RemoteReceiverComponent(InternalGPIOPin *pin, uint8_t mem_block_num = 1) : RemoteReceiverBase(pin), remote_base::RemoteRMTChannel(mem_block_num) {} + + RemoteReceiverComponent(InternalGPIOPin *pin, rmt_channel_t channel, uint8_t mem_block_num = 1) + : RemoteReceiverBase(pin), remote_base::RemoteRMTChannel(channel, mem_block_num) {} #else RemoteReceiverComponent(InternalGPIOPin *pin) : RemoteReceiverBase(pin) {} #endif diff --git a/esphome/components/remote_transmitter/__init__.py b/esphome/components/remote_transmitter/__init__.py index e09e4c7f55..d203ff3417 100644 --- a/esphome/components/remote_transmitter/__init__.py +++ b/esphome/components/remote_transmitter/__init__.py @@ -1,8 +1,8 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import pins -from esphome.components import remote_base -from esphome.const import CONF_CARRIER_DUTY_PERCENT, CONF_ID, CONF_PIN +from esphome.components import remote_base, esp32_rmt +from esphome.const import CONF_CARRIER_DUTY_PERCENT, CONF_ID, CONF_PIN, CONF_RMT_CHANNEL AUTO_LOAD = ["remote_base"] remote_transmitter_ns = cg.esphome_ns.namespace("remote_transmitter") @@ -18,13 +18,17 @@ CONFIG_SCHEMA = cv.Schema( cv.Required(CONF_CARRIER_DUTY_PERCENT): cv.All( cv.percentage_int, cv.Range(min=1, max=100) ), + cv.Optional(CONF_RMT_CHANNEL): esp32_rmt.validate_rmt_channel(tx=True), } ).extend(cv.COMPONENT_SCHEMA) async def to_code(config): pin = await cg.gpio_pin_expression(config[CONF_PIN]) - var = cg.new_Pvariable(config[CONF_ID], pin) + if (rmt_channel := config.get(CONF_RMT_CHANNEL, None)) is not None: + var = cg.new_Pvariable(config[CONF_ID], pin, rmt_channel) + else: + var = cg.new_Pvariable(config[CONF_ID], pin) await cg.register_component(var, config) cg.add(var.set_carrier_duty_percent(config[CONF_CARRIER_DUTY_PERCENT])) diff --git a/esphome/components/remote_transmitter/remote_transmitter.h b/esphome/components/remote_transmitter/remote_transmitter.h index 686a6ec09b..e736172cda 100644 --- a/esphome/components/remote_transmitter/remote_transmitter.h +++ b/esphome/components/remote_transmitter/remote_transmitter.h @@ -1,7 +1,7 @@ #pragma once -#include "esphome/core/component.h" #include "esphome/components/remote_base/remote_base.h" +#include "esphome/core/component.h" #include @@ -16,8 +16,15 @@ class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase, #endif { public: - explicit RemoteTransmitterComponent(InternalGPIOPin *pin) : remote_base::RemoteTransmitterBase(pin) {} +#ifdef USE_ESP32 + RemoteTransmitterComponent(InternalGPIOPin *pin, uint8_t mem_block_num = 1) + : remote_base::RemoteTransmitterBase(pin), remote_base::RemoteRMTChannel(mem_block_num) {} + RemoteTransmitterComponent(InternalGPIOPin *pin, rmt_channel_t channel, uint8_t mem_block_num = 1) + : remote_base::RemoteTransmitterBase(pin), remote_base::RemoteRMTChannel(channel, mem_block_num) {} +#else + explicit RemoteTransmitterComponent(InternalGPIOPin *pin) : remote_base::RemoteTransmitterBase(pin) {} +#endif void setup() override; void dump_config() override; diff --git a/esphome/const.py b/esphome/const.py index 8e3fd59ff0..7304653363 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -676,6 +676,7 @@ CONF_REVERSED = "reversed" CONF_RGB_ORDER = "rgb_order" CONF_RGBW = "rgbw" CONF_RISING_EDGE = "rising_edge" +CONF_RMT_CHANNEL = "rmt_channel" CONF_ROTATION = "rotation" CONF_RS_PIN = "rs_pin" CONF_RTD_NOMINAL_RESISTANCE = "rtd_nominal_resistance" diff --git a/tests/components/remote_receiver/esp32-common.yaml b/tests/components/remote_receiver/esp32-common.yaml new file mode 100644 index 0000000000..d1d47661c5 --- /dev/null +++ b/tests/components/remote_receiver/esp32-common.yaml @@ -0,0 +1,18 @@ +remote_receiver: + id: rcvr + pin: ${pin} + rmt_channel: ${rmt_channel} + dump: all + on_coolix: + then: + delay: !lambda "return x.first + x.second;" + on_rc_switch: + then: + delay: !lambda "return uint32_t(x.code) + x.protocol;" + +binary_sensor: + - platform: remote_receiver + name: Panasonic Remote Input + panasonic: + address: 0x4004 + command: 0x100BCBD diff --git a/tests/components/remote_receiver/test.esp32-c3-idf.yaml b/tests/components/remote_receiver/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..16d276958a --- /dev/null +++ b/tests/components/remote_receiver/test.esp32-c3-idf.yaml @@ -0,0 +1,6 @@ +substitutions: + pin: GPIO2 + rmt_channel: "2" + +packages: + common: !include esp32-common.yaml diff --git a/tests/components/remote_receiver/test.esp32-c3.yaml b/tests/components/remote_receiver/test.esp32-c3.yaml new file mode 100644 index 0000000000..16d276958a --- /dev/null +++ b/tests/components/remote_receiver/test.esp32-c3.yaml @@ -0,0 +1,6 @@ +substitutions: + pin: GPIO2 + rmt_channel: "2" + +packages: + common: !include esp32-common.yaml diff --git a/tests/components/remote_receiver/test.esp32-idf.yaml b/tests/components/remote_receiver/test.esp32-idf.yaml new file mode 100644 index 0000000000..16d276958a --- /dev/null +++ b/tests/components/remote_receiver/test.esp32-idf.yaml @@ -0,0 +1,6 @@ +substitutions: + pin: GPIO2 + rmt_channel: "2" + +packages: + common: !include esp32-common.yaml diff --git a/tests/components/remote_receiver/test.esp32-s3-idf.yaml b/tests/components/remote_receiver/test.esp32-s3-idf.yaml new file mode 100644 index 0000000000..265ecda771 --- /dev/null +++ b/tests/components/remote_receiver/test.esp32-s3-idf.yaml @@ -0,0 +1,6 @@ +substitutions: + pin: GPIO38 + rmt_channel: "5" + +packages: + common: !include esp32-common.yaml diff --git a/tests/components/remote_receiver/test.esp32.yaml b/tests/components/remote_receiver/test.esp32.yaml new file mode 100644 index 0000000000..16d276958a --- /dev/null +++ b/tests/components/remote_receiver/test.esp32.yaml @@ -0,0 +1,6 @@ +substitutions: + pin: GPIO2 + rmt_channel: "2" + +packages: + common: !include esp32-common.yaml diff --git a/tests/components/remote_receiver/test.esp8266.yaml b/tests/components/remote_receiver/test.esp8266.yaml new file mode 100644 index 0000000000..a7c283da1e --- /dev/null +++ b/tests/components/remote_receiver/test.esp8266.yaml @@ -0,0 +1,17 @@ +remote_receiver: + id: rcvr + pin: GPIO5 + dump: all + on_coolix: + then: + delay: !lambda "return x.first + x.second;" + on_rc_switch: + then: + delay: !lambda "return uint32_t(x.code) + x.protocol;" + +binary_sensor: + - platform: remote_receiver + name: Panasonic Remote Input + panasonic: + address: 0x4004 + command: 0x100BCBD diff --git a/tests/components/remote_transmitter/common-buttons.yaml b/tests/components/remote_transmitter/common-buttons.yaml new file mode 100644 index 0000000000..5f655acb7c --- /dev/null +++ b/tests/components/remote_transmitter/common-buttons.yaml @@ -0,0 +1,178 @@ +button: + - platform: template + name: JVC Off + id: living_room_lights_on + on_press: + remote_transmitter.transmit_jvc: + data: 0x10EF + - platform: template + name: MagiQuest + on_press: + remote_transmitter.transmit_magiquest: + wand_id: 0x01234567 + - platform: template + name: NEC + id: living_room_lights_off + on_press: + remote_transmitter.transmit_nec: + address: 0x4242 + command: 0x8484 + - platform: template + name: LG + on_press: + remote_transmitter.transmit_lg: + data: 4294967295 + nbits: 28 + - platform: template + name: Samsung + on_press: + remote_transmitter.transmit_samsung: + data: 0xABCDEF + - platform: template + name: Samsung36 + on_press: + remote_transmitter.transmit_samsung36: + address: 0x0400 + command: 0x000E00FF + - platform: template + name: ToshibaAC + on_press: + - remote_transmitter.transmit_toshiba_ac: + rc_code_1: 0xB24DBF4050AF + rc_code_2: 0xD5660001003C + - platform: template + name: Sony + on_press: + remote_transmitter.transmit_sony: + data: 0xABCDEF + nbits: 12 + - platform: template + name: Panasonic + on_press: + remote_transmitter.transmit_panasonic: + address: 0x4004 + command: 0x1000BCD + - platform: template + name: Pioneer + on_press: + - remote_transmitter.transmit_pioneer: + rc_code_1: 0xA556 + rc_code_2: 0xA506 + repeat: + times: 2 + - platform: template + name: RC Switch Raw + on_press: + remote_transmitter.transmit_rc_switch_raw: + code: "00101001100111110101xxxx" + protocol: 1 + - platform: template + name: RC Switch Type A + on_press: + remote_transmitter.transmit_rc_switch_type_a: + group: "11001" + device: "01000" + state: true + protocol: + pulse_length: 175 + sync: [1, 31] + zero: [1, 3] + one: [3, 1] + inverted: false + - platform: template + name: RC Switch Type B + on_press: + remote_transmitter.transmit_rc_switch_type_b: + address: 4 + channel: 2 + state: true + - platform: template + name: RC Switch Type C + on_press: + remote_transmitter.transmit_rc_switch_type_c: + family: "a" + group: 1 + device: 2 + state: true + - platform: template + name: RC Switch Type D + on_press: + remote_transmitter.transmit_rc_switch_type_d: + group: "a" + device: 2 + state: true + - platform: template + name: RC5 + on_press: + remote_transmitter.transmit_rc5: + address: 0x00 + command: 0x0B + - platform: template + name: RC5 + on_press: + remote_transmitter.transmit_raw: + code: [1000, -1000] + - platform: template + name: AEHA + id: eaha_hitachi_climate_power_on + on_press: + remote_transmitter.transmit_aeha: + address: 0x8008 + data: + [ + 0x00, + 0x02, + 0xFD, + 0xFF, + 0x00, + 0x33, + 0xCC, + 0x49, + 0xB6, + 0xC8, + 0x37, + 0x16, + 0xE9, + 0x00, + 0xFF, + 0x00, + 0xFF, + 0x00, + 0xFF, + 0x00, + 0xFF, + 0x00, + 0xFF, + 0xCA, + 0x35, + 0x8F, + 0x70, + 0x00, + 0xFF, + 0x00, + 0xFF, + 0x00, + 0xFF, + 0x00, + 0xFF, + ] + - platform: template + name: Haier + on_press: + remote_transmitter.transmit_haier: + code: + [ + 0xA6, + 0xDA, + 0x00, + 0x00, + 0x40, + 0x40, + 0x00, + 0x80, + 0x00, + 0x00, + 0x00, + 0x00, + 0x05, + ] diff --git a/tests/components/remote_transmitter/esp32-common.yaml b/tests/components/remote_transmitter/esp32-common.yaml new file mode 100644 index 0000000000..3f3cd3f8c7 --- /dev/null +++ b/tests/components/remote_transmitter/esp32-common.yaml @@ -0,0 +1,8 @@ +remote_transmitter: + id: rcvr + pin: ${pin} + rmt_channel: ${rmt_channel} + carrier_duty_percent: 50% + +packages: + buttons: !include common-buttons.yaml diff --git a/tests/components/remote_transmitter/test.esp32-c3-idf.yaml b/tests/components/remote_transmitter/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..3e2dc88e5a --- /dev/null +++ b/tests/components/remote_transmitter/test.esp32-c3-idf.yaml @@ -0,0 +1,6 @@ +substitutions: + pin: GPIO2 + rmt_channel: "1" + +packages: + common: !include esp32-common.yaml diff --git a/tests/components/remote_transmitter/test.esp32-c3.yaml b/tests/components/remote_transmitter/test.esp32-c3.yaml new file mode 100644 index 0000000000..3e2dc88e5a --- /dev/null +++ b/tests/components/remote_transmitter/test.esp32-c3.yaml @@ -0,0 +1,6 @@ +substitutions: + pin: GPIO2 + rmt_channel: "1" + +packages: + common: !include esp32-common.yaml diff --git a/tests/components/remote_transmitter/test.esp32-idf.yaml b/tests/components/remote_transmitter/test.esp32-idf.yaml new file mode 100644 index 0000000000..16d276958a --- /dev/null +++ b/tests/components/remote_transmitter/test.esp32-idf.yaml @@ -0,0 +1,6 @@ +substitutions: + pin: GPIO2 + rmt_channel: "2" + +packages: + common: !include esp32-common.yaml diff --git a/tests/components/remote_transmitter/test.esp32-s3-idf.yaml b/tests/components/remote_transmitter/test.esp32-s3-idf.yaml new file mode 100644 index 0000000000..31851dc54c --- /dev/null +++ b/tests/components/remote_transmitter/test.esp32-s3-idf.yaml @@ -0,0 +1,6 @@ +substitutions: + pin: GPIO38 + rmt_channel: "3" + +packages: + common: !include esp32-common.yaml diff --git a/tests/components/remote_transmitter/test.esp32.yaml b/tests/components/remote_transmitter/test.esp32.yaml new file mode 100644 index 0000000000..16d276958a --- /dev/null +++ b/tests/components/remote_transmitter/test.esp32.yaml @@ -0,0 +1,6 @@ +substitutions: + pin: GPIO2 + rmt_channel: "2" + +packages: + common: !include esp32-common.yaml diff --git a/tests/components/remote_transmitter/test.esp8266.yaml b/tests/components/remote_transmitter/test.esp8266.yaml new file mode 100644 index 0000000000..de494485f4 --- /dev/null +++ b/tests/components/remote_transmitter/test.esp8266.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + id: trns + pin: GPIO5 + carrier_duty_percent: 50% + +packages: + buttons: !include common-buttons.yaml From 12aa2722349fd494b5d0e8063d57c77bb46186d1 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 9 Apr 2024 15:51:54 +1200 Subject: [PATCH 1212/2101] Rework tlc5947 to remove AUTO_LOAD (#6503) --- esphome/components/tlc5947/__init__.py | 1 - .../tlc5947/{output.py => output/__init__.py} | 13 ++++---- .../tlc5947/output/tlc5947_output.cpp | 12 ++++++++ .../tlc5947/output/tlc5947_output.h | 22 ++++++++++++++ esphome/components/tlc5947/tlc5947.cpp | 9 ++++++ esphome/components/tlc5947/tlc5947.h | 30 ++----------------- tests/components/tlc5947/common.yaml | 13 ++++++++ .../components/tlc5947/test.esp32-c3-idf.yaml | 7 +++++ tests/components/tlc5947/test.esp32-c3.yaml | 7 +++++ tests/components/tlc5947/test.esp32-idf.yaml | 7 +++++ tests/components/tlc5947/test.esp32.yaml | 7 +++++ tests/components/tlc5947/test.esp8266.yaml | 7 +++++ tests/components/tlc5947/test.rp2040.yaml | 7 +++++ 13 files changed, 107 insertions(+), 35 deletions(-) rename esphome/components/tlc5947/{output.py => output/__init__.py} (69%) create mode 100644 esphome/components/tlc5947/output/tlc5947_output.cpp create mode 100644 esphome/components/tlc5947/output/tlc5947_output.h create mode 100644 tests/components/tlc5947/common.yaml create mode 100644 tests/components/tlc5947/test.esp32-c3-idf.yaml create mode 100644 tests/components/tlc5947/test.esp32-c3.yaml create mode 100644 tests/components/tlc5947/test.esp32-idf.yaml create mode 100644 tests/components/tlc5947/test.esp32.yaml create mode 100644 tests/components/tlc5947/test.esp8266.yaml create mode 100644 tests/components/tlc5947/test.rp2040.yaml diff --git a/esphome/components/tlc5947/__init__.py b/esphome/components/tlc5947/__init__.py index 84380bdace..8a4bd5e0ce 100644 --- a/esphome/components/tlc5947/__init__.py +++ b/esphome/components/tlc5947/__init__.py @@ -14,7 +14,6 @@ from esphome.const import ( CONF_LAT_PIN = "lat_pin" CONF_OE_PIN = "oe_pin" -AUTO_LOAD = ["output"] CODEOWNERS = ["@rnauber"] tlc5947_ns = cg.esphome_ns.namespace("tlc5947") diff --git a/esphome/components/tlc5947/output.py b/esphome/components/tlc5947/output/__init__.py similarity index 69% rename from esphome/components/tlc5947/output.py rename to esphome/components/tlc5947/output/__init__.py index ece47fa63d..1b5dff1854 100644 --- a/esphome/components/tlc5947/output.py +++ b/esphome/components/tlc5947/output/__init__.py @@ -2,18 +2,19 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import output from esphome.const import CONF_CHANNEL, CONF_ID -from . import TLC5947 +from .. import TLC5947, tlc5947_ns DEPENDENCIES = ["tlc5947"] -CODEOWNERS = ["@rnauber"] -Channel = TLC5947.class_("Channel", output.FloatOutput) +TLC5947Channel = tlc5947_ns.class_( + "TLC5947Channel", output.FloatOutput, cg.Parented.template(TLC5947) +) CONF_TLC5947_ID = "tlc5947_id" CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend( { cv.GenerateID(CONF_TLC5947_ID): cv.use_id(TLC5947), - cv.Required(CONF_ID): cv.declare_id(Channel), + cv.Required(CONF_ID): cv.declare_id(TLC5947Channel), cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=65535), } ).extend(cv.COMPONENT_SCHEMA) @@ -22,7 +23,5 @@ CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend( async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await output.register_output(var, config) - - parent = await cg.get_variable(config[CONF_TLC5947_ID]) - cg.add(var.set_parent(parent)) + await cg.register_parented(var, config[CONF_TLC5947_ID]) cg.add(var.set_channel(config[CONF_CHANNEL])) diff --git a/esphome/components/tlc5947/output/tlc5947_output.cpp b/esphome/components/tlc5947/output/tlc5947_output.cpp new file mode 100644 index 0000000000..9630fb8c1e --- /dev/null +++ b/esphome/components/tlc5947/output/tlc5947_output.cpp @@ -0,0 +1,12 @@ +#include "tlc5947_output.h" + +namespace esphome { +namespace tlc5947 { + +void TLC5947Channel::write_state(float state) { + auto amount = static_cast(state * 0xfff); + this->parent_->set_channel_value(this->channel_, amount); +} + +} // namespace tlc5947 +} // namespace esphome diff --git a/esphome/components/tlc5947/output/tlc5947_output.h b/esphome/components/tlc5947/output/tlc5947_output.h new file mode 100644 index 0000000000..5b2c51020c --- /dev/null +++ b/esphome/components/tlc5947/output/tlc5947_output.h @@ -0,0 +1,22 @@ +#pragma once + +#include "esphome/core/helpers.h" + +#include "esphome/components/output/float_output.h" + +#include "../tlc5947.h" + +namespace esphome { +namespace tlc5947 { + +class TLC5947Channel : public output::FloatOutput, public Parented { + public: + void set_channel(uint8_t channel) { this->channel_ = channel; } + + protected: + void write_state(float state) override; + uint8_t channel_; +}; + +} // namespace tlc5947 +} // namespace esphome diff --git a/esphome/components/tlc5947/tlc5947.cpp b/esphome/components/tlc5947/tlc5947.cpp index 8f3f60f087..5a5c0c17c0 100644 --- a/esphome/components/tlc5947/tlc5947.cpp +++ b/esphome/components/tlc5947/tlc5947.cpp @@ -60,5 +60,14 @@ void TLC5947::loop() { this->update_ = false; } +void TLC5947::set_channel_value(uint16_t channel, uint16_t value) { + if (channel >= this->num_chips_ * N_CHANNELS_PER_CHIP) + return; + if (this->pwm_amounts_[channel] != value) { + this->update_ = true; + } + this->pwm_amounts_[channel] = value; +} + } // namespace tlc5947 } // namespace esphome diff --git a/esphome/components/tlc5947/tlc5947.h b/esphome/components/tlc5947/tlc5947.h index 0eb7f10604..95d76408c9 100644 --- a/esphome/components/tlc5947/tlc5947.h +++ b/esphome/components/tlc5947/tlc5947.h @@ -2,18 +2,16 @@ // TLC5947 24-Channel, 12-Bit PWM LED Driver // https://www.ti.com/lit/ds/symlink/tlc5947.pdf +#include +#include "esphome/components/output/float_output.h" #include "esphome/core/component.h" #include "esphome/core/hal.h" -#include "esphome/components/output/float_output.h" -#include namespace esphome { namespace tlc5947 { class TLC5947 : public Component { public: - class Channel; - const uint8_t N_CHANNELS_PER_CHIP = 24; void set_data_pin(GPIOPin *data_pin) { data_pin_ = data_pin; } @@ -31,31 +29,9 @@ class TLC5947 : public Component { /// Send new values if they were updated. void loop() override; - class Channel : public output::FloatOutput { - public: - void set_parent(TLC5947 *parent) { parent_ = parent; } - void set_channel(uint8_t channel) { channel_ = channel; } - - protected: - void write_state(float state) override { - auto amount = static_cast(state * 0xfff); - this->parent_->set_channel_value_(this->channel_, amount); - } - - TLC5947 *parent_; - uint8_t channel_; - }; + void set_channel_value(uint16_t channel, uint16_t value); protected: - void set_channel_value_(uint16_t channel, uint16_t value) { - if (channel >= this->num_chips_ * N_CHANNELS_PER_CHIP) - return; - if (this->pwm_amounts_[channel] != value) { - this->update_ = true; - } - this->pwm_amounts_[channel] = value; - } - GPIOPin *data_pin_; GPIOPin *clock_pin_; GPIOPin *lat_pin_; diff --git a/tests/components/tlc5947/common.yaml b/tests/components/tlc5947/common.yaml new file mode 100644 index 0000000000..89588f3c76 --- /dev/null +++ b/tests/components/tlc5947/common.yaml @@ -0,0 +1,13 @@ +tlc5947: + clock_pin: ${clock_pin} + data_pin: ${data_pin} + lat_pin: ${lat_pin} + +output: + - platform: tlc5947 + id: output_1 + channel: 0 + max_power: 0.8 + - platform: tlc5947 + id: output_2 + channel: 1 diff --git a/tests/components/tlc5947/test.esp32-c3-idf.yaml b/tests/components/tlc5947/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..4694c43642 --- /dev/null +++ b/tests/components/tlc5947/test.esp32-c3-idf.yaml @@ -0,0 +1,7 @@ +substitutions: + clock_pin: GPIO5 + data_pin: GPIO4 + lat_pin: GPIO3 + +packages: + common: !include common.yaml diff --git a/tests/components/tlc5947/test.esp32-c3.yaml b/tests/components/tlc5947/test.esp32-c3.yaml new file mode 100644 index 0000000000..4694c43642 --- /dev/null +++ b/tests/components/tlc5947/test.esp32-c3.yaml @@ -0,0 +1,7 @@ +substitutions: + clock_pin: GPIO5 + data_pin: GPIO4 + lat_pin: GPIO3 + +packages: + common: !include common.yaml diff --git a/tests/components/tlc5947/test.esp32-idf.yaml b/tests/components/tlc5947/test.esp32-idf.yaml new file mode 100644 index 0000000000..52411bc1e9 --- /dev/null +++ b/tests/components/tlc5947/test.esp32-idf.yaml @@ -0,0 +1,7 @@ +substitutions: + clock_pin: GPIO15 + data_pin: GPIO14 + lat_pin: GPIO13 + +packages: + common: !include common.yaml diff --git a/tests/components/tlc5947/test.esp32.yaml b/tests/components/tlc5947/test.esp32.yaml new file mode 100644 index 0000000000..52411bc1e9 --- /dev/null +++ b/tests/components/tlc5947/test.esp32.yaml @@ -0,0 +1,7 @@ +substitutions: + clock_pin: GPIO15 + data_pin: GPIO14 + lat_pin: GPIO13 + +packages: + common: !include common.yaml diff --git a/tests/components/tlc5947/test.esp8266.yaml b/tests/components/tlc5947/test.esp8266.yaml new file mode 100644 index 0000000000..44da5a07b3 --- /dev/null +++ b/tests/components/tlc5947/test.esp8266.yaml @@ -0,0 +1,7 @@ +substitutions: + clock_pin: GPIO5 + data_pin: GPIO4 + lat_pin: GPIO13 + +packages: + common: !include common.yaml diff --git a/tests/components/tlc5947/test.rp2040.yaml b/tests/components/tlc5947/test.rp2040.yaml new file mode 100644 index 0000000000..4694c43642 --- /dev/null +++ b/tests/components/tlc5947/test.rp2040.yaml @@ -0,0 +1,7 @@ +substitutions: + clock_pin: GPIO5 + data_pin: GPIO4 + lat_pin: GPIO3 + +packages: + common: !include common.yaml From 0ba4e8c0bac001a2c59a2e209cc2904ae1d8b7e8 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 9 Apr 2024 16:55:20 +1200 Subject: [PATCH 1213/2101] UART: ignore require_tx/rx if not a native uart implementation (#6504) --- esphome/components/uart/__init__.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/esphome/components/uart/__init__.py b/esphome/components/uart/__init__.py index 9005422ce6..82bc6caaa4 100644 --- a/esphome/components/uart/__init__.py +++ b/esphome/components/uart/__init__.py @@ -46,6 +46,14 @@ LibreTinyUARTComponent = uart_ns.class_( "LibreTinyUARTComponent", UARTComponent, cg.Component ) +NATIVE_UART_CLASSES = ( + str(IDFUARTComponent), + str(ESP32ArduinoUARTComponent), + str(ESP8266UartComponent), + str(RP2040UartComponent), + str(LibreTinyUARTComponent), +) + UARTDevice = uart_ns.class_("UARTDevice") UARTWriteAction = uart_ns.class_("UARTWriteAction", automation.Action) UARTDebugger = uart_ns.class_("UARTDebugger", cg.Component, automation.Action) @@ -299,17 +307,18 @@ def final_validate_device_schema( def validate_hub(hub_config): hub_schema = {} uart_id = hub_config[CONF_ID] + uart_id_type_str = str(uart_id.type) devices = fv.full_config.get().data.setdefault(KEY_UART_DEVICES, {}) device = devices.setdefault(uart_id, {}) - if require_tx: + if require_tx and uart_id_type_str in NATIVE_UART_CLASSES: hub_schema[ cv.Required( CONF_TX_PIN, msg=f"Component {name} requires this uart bus to declare a tx_pin", ) ] = validate_pin(CONF_TX_PIN, device) - if require_rx: + if require_rx and uart_id_type_str in NATIVE_UART_CLASSES: hub_schema[ cv.Required( CONF_RX_PIN, From 857b8ef363e93b5755533f400406d490526ca6dc Mon Sep 17 00:00:00 2001 From: Mat931 <49403702+Mat931@users.noreply.github.com> Date: Tue, 9 Apr 2024 19:14:56 +0000 Subject: [PATCH 1214/2101] esp32_rmt_led_strip bugfixes (#6506) --- esphome/components/esp32_rmt_led_strip/led_strip.h | 2 +- esphome/components/esp32_rmt_led_strip/light.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/esp32_rmt_led_strip/led_strip.h b/esphome/components/esp32_rmt_led_strip/led_strip.h index 51eed8e01c..e9b19c9399 100644 --- a/esphome/components/esp32_rmt_led_strip/led_strip.h +++ b/esphome/components/esp32_rmt_led_strip/led_strip.h @@ -64,7 +64,7 @@ class ESP32RMTLEDStripLightOutput : public light::AddressableLight { protected: light::ESPColorView get_view_internal(int32_t index) const override; - size_t get_buffer_size_() const { return this->num_leds_ * (3 + this->is_rgbw_); } + size_t get_buffer_size_() const { return this->num_leds_ * (this->is_rgbw_ || this->is_wrgb_ ? 4 : 3); } uint8_t *buf_{nullptr}; uint8_t *effect_data_{nullptr}; diff --git a/esphome/components/esp32_rmt_led_strip/light.py b/esphome/components/esp32_rmt_led_strip/light.py index 3442940e3f..1c15a468d9 100644 --- a/esphome/components/esp32_rmt_led_strip/light.py +++ b/esphome/components/esp32_rmt_led_strip/light.py @@ -48,7 +48,7 @@ CHIPSETS = { "WS2812": LEDStripTimings(400, 1000, 1000, 400), "SK6812": LEDStripTimings(300, 900, 600, 600), "APA106": LEDStripTimings(350, 1360, 1360, 350), - "SM16703": LEDStripTimings(300, 900, 1360, 350), + "SM16703": LEDStripTimings(300, 900, 900, 300), } From 3adfed3675b3515f74ca9f8147c28092d69bda3d Mon Sep 17 00:00:00 2001 From: IJssel Date: Tue, 9 Apr 2024 22:03:18 +0200 Subject: [PATCH 1215/2101] Implemented support for the TLC5971 as an output component (#6494) --- CODEOWNERS | 1 + esphome/components/tlc5971/__init__.py | 40 +++++++ esphome/components/tlc5971/output/__init__.py | 27 +++++ .../tlc5971/output/tlc5971_output.cpp | 12 +++ .../tlc5971/output/tlc5971_output.h | 22 ++++ esphome/components/tlc5971/tlc5971.cpp | 101 ++++++++++++++++++ esphome/components/tlc5971/tlc5971.h | 43 ++++++++ tests/components/tlc5971/common.yaml | 12 +++ .../components/tlc5971/test.esp32-c3-idf.yaml | 6 ++ tests/components/tlc5971/test.esp32-c3.yaml | 6 ++ tests/components/tlc5971/test.esp32-idf.yaml | 6 ++ tests/components/tlc5971/test.esp32-s2.yaml | 6 ++ tests/components/tlc5971/test.esp32.yaml | 7 ++ tests/components/tlc5971/test.esp8266.yaml | 7 ++ tests/components/tlc5971/test.rp2040.yaml | 7 ++ 15 files changed, 303 insertions(+) create mode 100644 esphome/components/tlc5971/__init__.py create mode 100644 esphome/components/tlc5971/output/__init__.py create mode 100644 esphome/components/tlc5971/output/tlc5971_output.cpp create mode 100644 esphome/components/tlc5971/output/tlc5971_output.h create mode 100644 esphome/components/tlc5971/tlc5971.cpp create mode 100644 esphome/components/tlc5971/tlc5971.h create mode 100644 tests/components/tlc5971/common.yaml create mode 100644 tests/components/tlc5971/test.esp32-c3-idf.yaml create mode 100644 tests/components/tlc5971/test.esp32-c3.yaml create mode 100644 tests/components/tlc5971/test.esp32-idf.yaml create mode 100644 tests/components/tlc5971/test.esp32-s2.yaml create mode 100644 tests/components/tlc5971/test.esp32.yaml create mode 100644 tests/components/tlc5971/test.esp8266.yaml create mode 100644 tests/components/tlc5971/test.rp2040.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 126513943f..9f770d4efc 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -364,6 +364,7 @@ esphome/components/text/* @mauritskorse esphome/components/thermostat/* @kbx81 esphome/components/time/* @OttoWinter esphome/components/tlc5947/* @rnauber +esphome/components/tlc5971/* @IJIJI esphome/components/tm1621/* @Philippe12 esphome/components/tm1637/* @glmnet esphome/components/tm1638/* @skykingjwc diff --git a/esphome/components/tlc5971/__init__.py b/esphome/components/tlc5971/__init__.py new file mode 100644 index 0000000000..0ff2a5d176 --- /dev/null +++ b/esphome/components/tlc5971/__init__.py @@ -0,0 +1,40 @@ +# this component is for the "TLC5971 12-Channel, 12-Bit PWM LED Driver" [https://www.ti.com/lit/ds/symlink/tlc5971.pdf], +# which is used e.g. on [https://www.adafruit.com/product/1455]. The code is based on the TLC5947 component by @rnauber. + +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome import pins +from esphome.const import ( + CONF_CLOCK_PIN, + CONF_DATA_PIN, + CONF_ID, + CONF_NUM_CHIPS, +) + + +CODEOWNERS = ["@IJIJI"] + +tlc5971_ns = cg.esphome_ns.namespace("tlc5971") +TLC5971 = tlc5971_ns.class_("TLC5971", cg.Component) + +MULTI_CONF = True +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.declare_id(TLC5971), + cv.Required(CONF_DATA_PIN): pins.gpio_output_pin_schema, + cv.Required(CONF_CLOCK_PIN): pins.gpio_output_pin_schema, + cv.Optional(CONF_NUM_CHIPS, default=1): cv.int_range(min=1, max=85), + } +).extend(cv.COMPONENT_SCHEMA) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, config) + + data = await cg.gpio_pin_expression(config[CONF_DATA_PIN]) + cg.add(var.set_data_pin(data)) + clock = await cg.gpio_pin_expression(config[CONF_CLOCK_PIN]) + cg.add(var.set_clock_pin(clock)) + + cg.add(var.set_num_chips(config[CONF_NUM_CHIPS])) diff --git a/esphome/components/tlc5971/output/__init__.py b/esphome/components/tlc5971/output/__init__.py new file mode 100644 index 0000000000..9fe7b18294 --- /dev/null +++ b/esphome/components/tlc5971/output/__init__.py @@ -0,0 +1,27 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import output +from esphome.const import CONF_CHANNEL, CONF_ID +from .. import TLC5971, tlc5971_ns + +DEPENDENCIES = ["tlc5971"] + +TLC5971Channel = tlc5971_ns.class_( + "TLC5971Channel", output.FloatOutput, cg.Parented.template(TLC5971) +) + +CONF_TLC5971_ID = "tlc5971_id" +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), + } +).extend(cv.COMPONENT_SCHEMA) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + await output.register_output(var, config) + await cg.register_parented(var, config[CONF_TLC5971_ID]) + cg.add(var.set_channel(config[CONF_CHANNEL])) diff --git a/esphome/components/tlc5971/output/tlc5971_output.cpp b/esphome/components/tlc5971/output/tlc5971_output.cpp new file mode 100644 index 0000000000..b437889072 --- /dev/null +++ b/esphome/components/tlc5971/output/tlc5971_output.cpp @@ -0,0 +1,12 @@ +#include "tlc5971_output.h" + +namespace esphome { +namespace tlc5971 { + +void TLC5971Channel::write_state(float state) { + auto amount = static_cast(state * 0xffff); + this->parent_->set_channel_value(this->channel_, amount); +} + +} // namespace tlc5971 +} // namespace esphome diff --git a/esphome/components/tlc5971/output/tlc5971_output.h b/esphome/components/tlc5971/output/tlc5971_output.h new file mode 100644 index 0000000000..944ee19b2d --- /dev/null +++ b/esphome/components/tlc5971/output/tlc5971_output.h @@ -0,0 +1,22 @@ +#pragma once + +#include "esphome/core/helpers.h" + +#include "esphome/components/output/float_output.h" + +#include "../tlc5971.h" + +namespace esphome { +namespace tlc5971 { + +class TLC5971Channel : public output::FloatOutput, public Parented { + public: + void set_channel(uint8_t channel) { this->channel_ = channel; } + + protected: + void write_state(float state) override; + uint8_t channel_; +}; + +} // namespace tlc5971 +} // namespace esphome diff --git a/esphome/components/tlc5971/tlc5971.cpp b/esphome/components/tlc5971/tlc5971.cpp new file mode 100644 index 0000000000..ebcc3af361 --- /dev/null +++ b/esphome/components/tlc5971/tlc5971.cpp @@ -0,0 +1,101 @@ +#include "tlc5971.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace tlc5971 { + +static const char *const TAG = "tlc5971"; + +void TLC5971::setup() { + this->data_pin_->setup(); + this->data_pin_->digital_write(true); + this->clock_pin_->setup(); + this->clock_pin_->digital_write(true); + + this->pwm_amounts_.resize(this->num_chips_ * N_CHANNELS_PER_CHIP, 0); + + ESP_LOGCONFIG(TAG, "Done setting up TLC5971 output component."); +} +void TLC5971::dump_config() { + ESP_LOGCONFIG(TAG, "TLC5971:"); + LOG_PIN(" Data Pin: ", this->data_pin_); + LOG_PIN(" Clock Pin: ", this->clock_pin_); + ESP_LOGCONFIG(TAG, " Number of chips: %u", this->num_chips_); +} + +void TLC5971::loop() { + if (!this->update_) + return; + + uint32_t command; + + // Magic word for write + command = 0x25; + + command <<= 5; + // OUTTMG = 1, EXTGCK = 0, TMGRST = 1, DSPRPT = 1, BLANK = 0 -> 0x16 + command |= 0x16; + + command <<= 7; + command |= 0x7F; // default 100% brigthness + + command <<= 7; + command |= 0x7F; // default 100% brigthness + + command <<= 7; + command |= 0x7F; // default 100% brigthness + + for (uint8_t n = 0; n < num_chips_; n++) { + this->transfer_(command >> 24); + this->transfer_(command >> 16); + this->transfer_(command >> 8); + this->transfer_(command); + + // 12 channels per TLC59711 + for (int8_t c = 11; c >= 0; c--) { + // 16 bits per channel, send MSB first + this->transfer_(pwm_amounts_.at(n * 12 + c) >> 8); + this->transfer_(pwm_amounts_.at(n * 12 + c)); + } + } + + this->update_ = false; +} + +void TLC5971::transfer_(uint8_t send) { + uint8_t startbit = 0x80; + + bool towrite, lastmosi = !(send & startbit); + uint8_t bitdelay_us = (1000000 / 1000000) / 2; + + for (uint8_t b = startbit; b != 0; b = b >> 1) { + if (bitdelay_us) { + delayMicroseconds(bitdelay_us); + } + + towrite = send & b; + if ((lastmosi != towrite)) { + this->data_pin_->digital_write(towrite); + lastmosi = towrite; + } + + this->clock_pin_->digital_write(true); + + if (bitdelay_us) { + delayMicroseconds(bitdelay_us); + } + + this->clock_pin_->digital_write(false); + } +} +void TLC5971::set_channel_value(uint16_t channel, uint16_t value) { + if (channel >= this->num_chips_ * N_CHANNELS_PER_CHIP) + return; + if (this->pwm_amounts_[channel] != value) { + this->update_ = true; + } + this->pwm_amounts_[channel] = value; +} + +} // namespace tlc5971 +} // namespace esphome diff --git a/esphome/components/tlc5971/tlc5971.h b/esphome/components/tlc5971/tlc5971.h new file mode 100644 index 0000000000..6b0daf10d1 --- /dev/null +++ b/esphome/components/tlc5971/tlc5971.h @@ -0,0 +1,43 @@ +#pragma once +// TLC5971 12-Channel, 16-Bit PWM LED Driver +// https://www.ti.com/lit/ds/symlink/tlc5971.pdf + +#include "esphome/core/component.h" +#include "esphome/core/hal.h" +#include "esphome/components/output/float_output.h" +#include + +namespace esphome { +namespace tlc5971 { + +class TLC5971 : public Component { + public: + const uint8_t N_CHANNELS_PER_CHIP = 12; + + void set_data_pin(GPIOPin *data_pin) { data_pin_ = data_pin; } + void set_clock_pin(GPIOPin *clock_pin) { clock_pin_ = clock_pin; } + void set_num_chips(uint8_t num_chips) { num_chips_ = num_chips; } + + void setup() override; + + void dump_config() override; + + float get_setup_priority() const override { return setup_priority::HARDWARE; } + + /// Send new values if they were updated. + void loop() override; + + void set_channel_value(uint16_t channel, uint16_t value); + + protected: + void transfer_(uint8_t send); + + GPIOPin *data_pin_; + GPIOPin *clock_pin_; + uint8_t num_chips_; + + std::vector pwm_amounts_; + bool update_{true}; +}; +} // namespace tlc5971 +} // namespace esphome diff --git a/tests/components/tlc5971/common.yaml b/tests/components/tlc5971/common.yaml new file mode 100644 index 0000000000..fe7fe25f0e --- /dev/null +++ b/tests/components/tlc5971/common.yaml @@ -0,0 +1,12 @@ +tlc5971: + clock_pin: ${clock_pin} + data_pin: ${data_pin} + +output: + - platform: tlc5971 + id: output_1 + channel: 0 + max_power: 0.8 + - platform: tlc5971 + id: output_2 + channel: 1 diff --git a/tests/components/tlc5971/test.esp32-c3-idf.yaml b/tests/components/tlc5971/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..d898a21d46 --- /dev/null +++ b/tests/components/tlc5971/test.esp32-c3-idf.yaml @@ -0,0 +1,6 @@ +substitutions: + clock_pin: GPIO5 + data_pin: GPIO4 + +packages: + common: !include common.yaml diff --git a/tests/components/tlc5971/test.esp32-c3.yaml b/tests/components/tlc5971/test.esp32-c3.yaml new file mode 100644 index 0000000000..d898a21d46 --- /dev/null +++ b/tests/components/tlc5971/test.esp32-c3.yaml @@ -0,0 +1,6 @@ +substitutions: + clock_pin: GPIO5 + data_pin: GPIO4 + +packages: + common: !include common.yaml diff --git a/tests/components/tlc5971/test.esp32-idf.yaml b/tests/components/tlc5971/test.esp32-idf.yaml new file mode 100644 index 0000000000..e8943a572a --- /dev/null +++ b/tests/components/tlc5971/test.esp32-idf.yaml @@ -0,0 +1,6 @@ +substitutions: + clock_pin: GPIO15 + data_pin: GPIO14 + +packages: + common: !include common.yaml diff --git a/tests/components/tlc5971/test.esp32-s2.yaml b/tests/components/tlc5971/test.esp32-s2.yaml new file mode 100644 index 0000000000..7bba0b0117 --- /dev/null +++ b/tests/components/tlc5971/test.esp32-s2.yaml @@ -0,0 +1,6 @@ +substitutions: + clock_pin: GPIO36 + data_pin: GPIO35 + +packages: + common: !include common.yaml diff --git a/tests/components/tlc5971/test.esp32.yaml b/tests/components/tlc5971/test.esp32.yaml new file mode 100644 index 0000000000..52411bc1e9 --- /dev/null +++ b/tests/components/tlc5971/test.esp32.yaml @@ -0,0 +1,7 @@ +substitutions: + clock_pin: GPIO15 + data_pin: GPIO14 + lat_pin: GPIO13 + +packages: + common: !include common.yaml diff --git a/tests/components/tlc5971/test.esp8266.yaml b/tests/components/tlc5971/test.esp8266.yaml new file mode 100644 index 0000000000..52411bc1e9 --- /dev/null +++ b/tests/components/tlc5971/test.esp8266.yaml @@ -0,0 +1,7 @@ +substitutions: + clock_pin: GPIO15 + data_pin: GPIO14 + lat_pin: GPIO13 + +packages: + common: !include common.yaml diff --git a/tests/components/tlc5971/test.rp2040.yaml b/tests/components/tlc5971/test.rp2040.yaml new file mode 100644 index 0000000000..4694c43642 --- /dev/null +++ b/tests/components/tlc5971/test.rp2040.yaml @@ -0,0 +1,7 @@ +substitutions: + clock_pin: GPIO5 + data_pin: GPIO4 + lat_pin: GPIO3 + +packages: + common: !include common.yaml From 522b43bb41d8ef37bc6492ee895980d921db239d Mon Sep 17 00:00:00 2001 From: bukureckid Date: Tue, 9 Apr 2024 23:04:35 +0200 Subject: [PATCH 1216/2101] Add Dooya protocol to remote_base (#6488) --- esphome/components/remote_base/__init__.py | 54 ++++++++ .../components/remote_base/dooya_protocol.cpp | 120 ++++++++++++++++++ .../components/remote_base/dooya_protocol.h | 49 +++++++ .../xiaomi_rtcgq02lm/binary_sensor.py | 3 +- esphome/const.py | 3 + 5 files changed, 227 insertions(+), 2 deletions(-) create mode 100644 esphome/components/remote_base/dooya_protocol.cpp create mode 100644 esphome/components/remote_base/dooya_protocol.h diff --git a/esphome/components/remote_base/__init__.py b/esphome/components/remote_base/__init__.py index c771f406d8..6deab63c60 100644 --- a/esphome/components/remote_base/__init__.py +++ b/esphome/components/remote_base/__init__.py @@ -33,6 +33,9 @@ from esphome.const import ( CONF_WAND_ID, CONF_LEVEL, CONF_DELTA, + CONF_ID, + CONF_BUTTON, + CONF_CHECK, ) from esphome.core import coroutine from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor @@ -512,6 +515,57 @@ async def dish_action(var, config, args): cg.add(var.set_command(template_)) +# Dooya +DooyaData, DooyaBinarySensor, DooyaTrigger, DooyaAction, DooyaDumper = declare_protocol( + "Dooya" +) +DOOYA_SCHEMA = cv.Schema( + { + cv.Required(CONF_ID): cv.hex_int_range(0, 16777215), + cv.Required(CONF_CHANNEL): cv.hex_int_range(0, 255), + cv.Required(CONF_BUTTON): cv.hex_int_range(0, 15), + cv.Required(CONF_CHECK): cv.hex_int_range(0, 15), + } +) + + +@register_binary_sensor("dooya", DooyaBinarySensor, DOOYA_SCHEMA) +def dooya_binary_sensor(var, config): + cg.add( + var.set_data( + cg.StructInitializer( + DooyaData, + ("id", config[CONF_ID]), + ("channel", config[CONF_CHANNEL]), + ("button", config[CONF_BUTTON]), + ("check", config[CONF_CHECK]), + ) + ) + ) + + +@register_trigger("dooya", DooyaTrigger, DooyaData) +def dooya_trigger(var, config): + pass + + +@register_dumper("dooya", DooyaDumper) +def dooya_dumper(var, config): + pass + + +@register_action("dooya", DooyaAction, DOOYA_SCHEMA) +async def dooya_action(var, config, args): + template_ = await cg.templatable(config[CONF_ID], args, cg.uint32) + cg.add(var.set_id(template_)) + template_ = await cg.templatable(config[CONF_CHANNEL], args, cg.uint8) + cg.add(var.set_channel(template_)) + template_ = await cg.templatable(config[CONF_BUTTON], args, cg.uint8) + cg.add(var.set_button(template_)) + template_ = await cg.templatable(config[CONF_CHECK], args, cg.uint8) + cg.add(var.set_check(template_)) + + # JVC JVCData, JVCBinarySensor, JVCTrigger, JVCAction, JVCDumper = declare_protocol("JVC") JVC_SCHEMA = cv.Schema({cv.Required(CONF_DATA): cv.hex_uint32_t}) diff --git a/esphome/components/remote_base/dooya_protocol.cpp b/esphome/components/remote_base/dooya_protocol.cpp new file mode 100644 index 0000000000..d979bca8c5 --- /dev/null +++ b/esphome/components/remote_base/dooya_protocol.cpp @@ -0,0 +1,120 @@ +#include "dooya_protocol.h" +#include "esphome/core/log.h" + +namespace esphome { +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 = 750; +static const uint32_t BIT_ZERO_LOW_US = 350; +static const uint32_t BIT_ONE_HIGH_US = 350; +static const uint32_t BIT_ONE_LOW_US = 750; + +void DooyaProtocol::encode(RemoteTransmitData *dst, const DooyaData &data) { + dst->set_carrier_frequency(0); + dst->reserve(2 + 40 * 2u); + + dst->item(HEADER_HIGH_US, HEADER_LOW_US); + + for (uint32_t mask = 1UL << (23); mask != 0; mask >>= 1) { + if (data.id & mask) { + dst->item(BIT_ONE_HIGH_US, BIT_ONE_LOW_US); + } else { + dst->item(BIT_ZERO_HIGH_US, BIT_ZERO_LOW_US); + } + } + + for (uint32_t mask = 1UL << (7); mask != 0; mask >>= 1) { + if (data.channel & mask) { + dst->item(BIT_ONE_HIGH_US, BIT_ONE_LOW_US); + } else { + dst->item(BIT_ZERO_HIGH_US, BIT_ZERO_LOW_US); + } + } + + for (uint32_t mask = 1UL << (3); mask != 0; mask >>= 1) { + if (data.button & mask) { + dst->item(BIT_ONE_HIGH_US, BIT_ONE_LOW_US); + } else { + dst->item(BIT_ZERO_HIGH_US, BIT_ZERO_LOW_US); + } + } + + for (uint32_t mask = 1UL << (3); mask != 0; mask >>= 1) { + if (data.check & mask) { + dst->item(BIT_ONE_HIGH_US, BIT_ONE_LOW_US); + } else { + dst->item(BIT_ZERO_HIGH_US, BIT_ZERO_LOW_US); + } + } +} +optional DooyaProtocol::decode(RemoteReceiveData src) { + DooyaData out{ + .id = 0, + .channel = 0, + .button = 0, + .check = 0, + }; + if (!src.expect_item(HEADER_HIGH_US, HEADER_LOW_US)) + return {}; + + for (uint8_t i = 0; i < 24; i++) { + if (src.expect_item(BIT_ONE_HIGH_US, BIT_ONE_LOW_US)) { + out.id = (out.id << 1) | 1; + } else if (src.expect_item(BIT_ZERO_HIGH_US, BIT_ZERO_LOW_US)) { + out.id = (out.id << 1) | 0; + } else { + return {}; + } + } + + for (uint8_t i = 0; i < 8; i++) { + if (src.expect_item(BIT_ONE_HIGH_US, BIT_ONE_LOW_US)) { + out.channel = (out.channel << 1) | 1; + } else if (src.expect_item(BIT_ZERO_HIGH_US, BIT_ZERO_LOW_US)) { + out.channel = (out.channel << 1) | 0; + } else { + return {}; + } + } + + for (uint8_t i = 0; i < 4; i++) { + if (src.expect_item(BIT_ONE_HIGH_US, BIT_ONE_LOW_US)) { + out.button = (out.button << 1) | 1; + } else if (src.expect_item(BIT_ZERO_HIGH_US, BIT_ZERO_LOW_US)) { + out.button = (out.button << 1) | 0; + } else { + return {}; + } + } + + for (uint8_t i = 0; i < 3; i++) { + if (src.expect_item(BIT_ONE_HIGH_US, BIT_ONE_LOW_US)) { + out.check = (out.check << 1) | 1; + } else if (src.expect_item(BIT_ZERO_HIGH_US, BIT_ZERO_LOW_US)) { + out.check = (out.check << 1) | 0; + } else { + return {}; + } + } + // Last bit is not received properly but can be decoded + if (src.expect_mark(BIT_ONE_HIGH_US)) { + out.check = (out.check << 1) | 1; + } else if (src.expect_mark(BIT_ZERO_HIGH_US)) { + out.check = (out.check << 1) | 0; + } else { + return {}; + } + + return out; +} +void DooyaProtocol::dump(const DooyaData &data) { + ESP_LOGI(TAG, "Received Dooya: id=0x%08" PRIX32 ", channel=%d, button=%d, check=%d", data.id, data.channel, + data.button, data.check); +} + +} // namespace remote_base +} // namespace esphome diff --git a/esphome/components/remote_base/dooya_protocol.h b/esphome/components/remote_base/dooya_protocol.h new file mode 100644 index 0000000000..9d17ad5d5e --- /dev/null +++ b/esphome/components/remote_base/dooya_protocol.h @@ -0,0 +1,49 @@ +#pragma once + +#include "esphome/core/component.h" +#include "remote_base.h" + +#include + +namespace esphome { +namespace remote_base { + +struct DooyaData { + uint32_t id; + uint8_t channel; + uint8_t button; + uint8_t check; + + bool operator==(const DooyaData &rhs) const { + return id == rhs.id && channel == rhs.channel && button == rhs.button && check == rhs.check; + } +}; + +class DooyaProtocol : public RemoteProtocol { + public: + void encode(RemoteTransmitData *dst, const DooyaData &data) override; + optional decode(RemoteReceiveData src) override; + void dump(const DooyaData &data) override; +}; + +DECLARE_REMOTE_PROTOCOL(Dooya) + +template class DooyaAction : public RemoteTransmitterActionBase { + public: + TEMPLATABLE_VALUE(uint32_t, id) + TEMPLATABLE_VALUE(uint8_t, channel) + TEMPLATABLE_VALUE(uint8_t, button) + TEMPLATABLE_VALUE(uint8_t, check) + + void encode(RemoteTransmitData *dst, Ts... x) override { + DooyaData data{}; + data.id = this->id_.value(x...); + data.channel = this->channel_.value(x...); + data.button = this->button_.value(x...); + data.check = this->check_.value(x...); + DooyaProtocol().encode(dst, data); + } +}; + +} // namespace remote_base +} // namespace esphome diff --git a/esphome/components/xiaomi_rtcgq02lm/binary_sensor.py b/esphome/components/xiaomi_rtcgq02lm/binary_sensor.py index 8eee10685e..ef8a472d66 100644 --- a/esphome/components/xiaomi_rtcgq02lm/binary_sensor.py +++ b/esphome/components/xiaomi_rtcgq02lm/binary_sensor.py @@ -8,6 +8,7 @@ from esphome.const import ( DEVICE_CLASS_LIGHT, DEVICE_CLASS_MOTION, CONF_ID, + CONF_BUTTON, ) from esphome.core import TimePeriod @@ -15,8 +16,6 @@ from . import XiaomiRTCGQ02LM DEPENDENCIES = ["xiaomi_rtcgq02lm"] -CONF_BUTTON = "button" - CONFIG_SCHEMA = cv.Schema( { diff --git a/esphome/const.py b/esphome/const.py index 7304653363..992d148bdc 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -96,6 +96,7 @@ CONF_BUFFER_SIZE = "buffer_size" CONF_BUILD_PATH = "build_path" CONF_BUS_VOLTAGE = "bus_voltage" CONF_BUSY_PIN = "busy_pin" +CONF_BUTTON = "button" CONF_BYTES = "bytes" CONF_CALCULATED_LUX = "calculated_lux" CONF_CALIBRATE_LINEAR = "calibrate_linear" @@ -110,6 +111,7 @@ CONF_CHANGE_MODE_EVERY = "change_mode_every" CONF_CHANNEL = "channel" CONF_CHANNELS = "channels" CONF_CHARACTERISTIC_UUID = "characteristic_uuid" +CONF_CHECK = "check" CONF_CHIPSET = "chipset" CONF_CLEAR_IMPEDANCE = "clear_impedance" CONF_CLIENT_CERTIFICATE = "client_certificate" @@ -220,6 +222,7 @@ CONF_DNS_ADDRESS = "dns_address" CONF_DNS1 = "dns1" CONF_DNS2 = "dns2" CONF_DOMAIN = "domain" +CONF_DOOYA = "dooya" CONF_DRY_ACTION = "dry_action" CONF_DRY_MODE = "dry_mode" CONF_DUMMY_RECEIVER = "dummy_receiver" From e5e8bc85152ae93d3531a329ab85d08752338162 Mon Sep 17 00:00:00 2001 From: leejoow Date: Wed, 10 Apr 2024 01:22:18 +0200 Subject: [PATCH 1217/2101] Only give error for connected sensors at startup (#6474) Co-authored-by: Leo Schelvis --- esphome/components/dallas/dallas_component.cpp | 18 +++++++++++++++--- esphome/components/dallas/dallas_component.h | 1 + 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/esphome/components/dallas/dallas_component.cpp b/esphome/components/dallas/dallas_component.cpp index b1983fef72..a51bc369a1 100644 --- a/esphome/components/dallas/dallas_component.cpp +++ b/esphome/components/dallas/dallas_component.cpp @@ -60,7 +60,7 @@ void DallasComponent::setup() { for (auto *sensor : this->sensors_) { if (sensor->get_index().has_value()) { if (*sensor->get_index() >= this->found_sensors_.size()) { - this->status_set_error(); + this->status_set_error("Sensor configured by index but not found"); continue; } sensor->set_address(this->found_sensors_[*sensor->get_index()]); @@ -109,8 +109,12 @@ void DallasComponent::update() { result = this->one_wire_->reset(); } if (!result) { - ESP_LOGE(TAG, "Requesting conversion failed"); - this->status_set_warning(); + if (!this->found_sensors_.empty()) { + // Only log error if at the start sensors were found (and thus are disconnected during uptime) + ESP_LOGE(TAG, "Requesting conversion failed"); + this->status_set_warning(); + } + for (auto *sensor : this->sensors_) { sensor->publish_state(NAN); } @@ -124,6 +128,12 @@ void DallasComponent::update() { } for (auto *sensor : this->sensors_) { + if (sensor->get_address() == 0) { + ESP_LOGV(TAG, "'%s' - Indexed sensor not found at startup, skipping update", sensor->get_name().c_str()); + sensor->publish_state(NAN); + continue; + } + this->set_timeout(sensor->get_address_name(), sensor->millis_to_wait_for_conversion(), [this, sensor] { bool res = sensor->read_scratch_pad(); @@ -152,6 +162,8 @@ void DallasTemperatureSensor::set_resolution(uint8_t resolution) { this->resolut optional DallasTemperatureSensor::get_index() const { return this->index_; } void DallasTemperatureSensor::set_index(uint8_t index) { this->index_ = index; } uint8_t *DallasTemperatureSensor::get_address8() { return reinterpret_cast(&this->address_); } +uint64_t DallasTemperatureSensor::get_address() { return this->address_; } + const std::string &DallasTemperatureSensor::get_address_name() { if (this->address_name_.empty()) { this->address_name_ = std::string("0x") + format_hex(this->address_); diff --git a/esphome/components/dallas/dallas_component.h b/esphome/components/dallas/dallas_component.h index b21bc02e54..10bde7338b 100644 --- a/esphome/components/dallas/dallas_component.h +++ b/esphome/components/dallas/dallas_component.h @@ -37,6 +37,7 @@ class DallasTemperatureSensor : public sensor::Sensor { void set_parent(DallasComponent *parent) { parent_ = parent; } /// Helper to get a pointer to the address as uint8_t. uint8_t *get_address8(); + uint64_t get_address(); /// Helper to create (and cache) the name for this sensor. For example "0xfe0000031f1eaf29". const std::string &get_address_name(); From b4b4e81c1c443add8811c7e9dd36875ff93d71fc Mon Sep 17 00:00:00 2001 From: RFDarter Date: Wed, 10 Apr 2024 01:33:26 +0200 Subject: [PATCH 1218/2101] Webserver float to string fix (#6507) --- esphome/components/web_server/web_server.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index b48a39cbcb..2e6206b691 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -851,9 +851,12 @@ std::string WebServer::number_json(number::Number *obj, float value, JsonDetail return json::build_json([obj, value, start_config](JsonObject root) { set_json_id(root, obj, "number-" + obj->get_object_id(), start_config); if (start_config == DETAIL_ALL) { - root["min_value"] = obj->traits.get_min_value(); - root["max_value"] = obj->traits.get_max_value(); - root["step"] = obj->traits.get_step(); + root["min_value"] = + value_accuracy_to_string(obj->traits.get_min_value(), step_to_accuracy_decimals(obj->traits.get_step())); + root["max_value"] = + value_accuracy_to_string(obj->traits.get_max_value(), step_to_accuracy_decimals(obj->traits.get_step())); + root["step"] = + value_accuracy_to_string(obj->traits.get_step(), step_to_accuracy_decimals(obj->traits.get_step())); root["mode"] = (int) obj->traits.get_mode(); if (!obj->traits.get_unit_of_measurement().empty()) root["uom"] = obj->traits.get_unit_of_measurement(); @@ -862,7 +865,7 @@ std::string WebServer::number_json(number::Number *obj, float value, JsonDetail root["value"] = "\"NaN\""; root["state"] = "NA"; } else { - root["value"] = value; + root["value"] = value_accuracy_to_string(value, step_to_accuracy_decimals(obj->traits.get_step())); std::string state = value_accuracy_to_string(value, step_to_accuracy_decimals(obj->traits.get_step())); if (!obj->traits.get_unit_of_measurement().empty()) state += " " + obj->traits.get_unit_of_measurement(); From 9af083af037fab54d9973691aaf59e1069bfe040 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 10 Apr 2024 12:49:45 +1200 Subject: [PATCH 1219/2101] Bump version to 2024.4.0b1 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 992d148bdc..5f8082c395 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.4.0-dev" +__version__ = "2024.4.0b1" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From a102e982b380da03fe1bd566efa6d647def82c91 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 10 Apr 2024 12:49:45 +1200 Subject: [PATCH 1220/2101] Bump version to 2024.5.0-dev --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 992d148bdc..8410d36708 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.4.0-dev" +__version__ = "2024.5.0-dev" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 1e0f6e139a67313f80715196c366236aae467106 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 10 Apr 2024 19:25:35 +1200 Subject: [PATCH 1221/2101] Add dooya remote transmitter test (#6508) --- tests/components/remote_transmitter/common-buttons.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/components/remote_transmitter/common-buttons.yaml b/tests/components/remote_transmitter/common-buttons.yaml index 5f655acb7c..27683b387f 100644 --- a/tests/components/remote_transmitter/common-buttons.yaml +++ b/tests/components/remote_transmitter/common-buttons.yaml @@ -176,3 +176,11 @@ button: 0x00, 0x05, ] + - platform: template + name: Dooya + on_press: + remote_transmitter.transmit_dooya: + id: 0x123456 + channel: 1 + button: 1 + check: 1 From e59b81612fb5d6b6d7611269b6834afbbeeabbb4 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Wed, 10 Apr 2024 03:57:22 -0500 Subject: [PATCH 1222/2101] Add some components to the new testing framework (H) (#6179) * Add some components to the new testing framework (H) * Remove C3 * Fix indentation --------- Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- .../havells_solar/test.esp32-c3-idf.yaml | 79 +++++++++++++++++++ .../havells_solar/test.esp32-c3.yaml | 79 +++++++++++++++++++ .../havells_solar/test.esp32-idf.yaml | 79 +++++++++++++++++++ .../components/havells_solar/test.esp32.yaml | 79 +++++++++++++++++++ .../havells_solar/test.esp8266.yaml | 79 +++++++++++++++++++ .../components/havells_solar/test.rp2040.yaml | 79 +++++++++++++++++++ .../components/hbridge/test.esp32-c3-idf.yaml | 33 ++++++++ tests/components/hbridge/test.esp32-c3.yaml | 33 ++++++++ tests/components/hbridge/test.esp32-idf.yaml | 33 ++++++++ tests/components/hbridge/test.esp32.yaml | 33 ++++++++ tests/components/hbridge/test.esp8266.yaml | 33 ++++++++ tests/components/hbridge/test.rp2040.yaml | 33 ++++++++ .../components/hdc1080/test.esp32-c3-idf.yaml | 12 +++ tests/components/hdc1080/test.esp32-c3.yaml | 12 +++ tests/components/hdc1080/test.esp32-idf.yaml | 12 +++ tests/components/hdc1080/test.esp32.yaml | 12 +++ tests/components/hdc1080/test.esp8266.yaml | 12 +++ tests/components/hdc1080/test.rp2040.yaml | 12 +++ tests/components/he60r/test.esp32-c3-idf.yaml | 13 +++ tests/components/he60r/test.esp32-c3.yaml | 13 +++ tests/components/he60r/test.esp32-idf.yaml | 13 +++ tests/components/he60r/test.esp32.yaml | 13 +++ tests/components/he60r/test.esp8266.yaml | 13 +++ tests/components/he60r/test.rp2040.yaml | 13 +++ tests/components/heatpumpir/test.esp32.yaml | 19 +++++ tests/components/heatpumpir/test.esp8266.yaml | 19 +++++ .../hitachi_ac344/test.esp32-c3-idf.yaml | 7 ++ .../hitachi_ac344/test.esp32-c3.yaml | 7 ++ .../hitachi_ac344/test.esp32-idf.yaml | 7 ++ .../components/hitachi_ac344/test.esp32.yaml | 7 ++ .../hitachi_ac344/test.esp8266.yaml | 7 ++ .../hitachi_ac424/test.esp32-c3-idf.yaml | 7 ++ .../hitachi_ac424/test.esp32-c3.yaml | 7 ++ .../hitachi_ac424/test.esp32-idf.yaml | 7 ++ .../components/hitachi_ac424/test.esp32.yaml | 7 ++ .../hitachi_ac424/test.esp8266.yaml | 7 ++ .../components/hlw8012/test.esp32-c3-idf.yaml | 21 +++++ tests/components/hlw8012/test.esp32-c3.yaml | 21 +++++ tests/components/hlw8012/test.esp32-idf.yaml | 21 +++++ tests/components/hlw8012/test.esp32.yaml | 21 +++++ tests/components/hlw8012/test.esp8266.yaml | 21 +++++ tests/components/hlw8012/test.rp2040.yaml | 21 +++++ .../components/hm3301/test.esp32-c3-idf.yaml | 16 ++++ tests/components/hm3301/test.esp32-c3.yaml | 16 ++++ tests/components/hm3301/test.esp32-idf.yaml | 16 ++++ tests/components/hm3301/test.esp32.yaml | 16 ++++ tests/components/hm3301/test.esp8266.yaml | 16 ++++ tests/components/hm3301/test.rp2040.yaml | 16 ++++ .../hmc5883l/test.esp32-c3-idf.yaml | 19 +++++ tests/components/hmc5883l/test.esp32-c3.yaml | 19 +++++ tests/components/hmc5883l/test.esp32-idf.yaml | 19 +++++ tests/components/hmc5883l/test.esp32.yaml | 19 +++++ tests/components/hmc5883l/test.esp8266.yaml | 19 +++++ tests/components/hmc5883l/test.rp2040.yaml | 19 +++++ .../homeassistant/test.esp32-c3-idf.yaml | 39 +++++++++ .../homeassistant/test.esp32-c3.yaml | 39 +++++++++ .../homeassistant/test.esp32-idf.yaml | 39 +++++++++ .../components/homeassistant/test.esp32.yaml | 39 +++++++++ .../homeassistant/test.esp8266.yaml | 39 +++++++++ .../components/homeassistant/test.rp2040.yaml | 39 +++++++++ .../honeywell_hih_i2c/test.esp32-c3-idf.yaml | 12 +++ .../honeywell_hih_i2c/test.esp32-c3.yaml | 12 +++ .../honeywell_hih_i2c/test.esp32-idf.yaml | 12 +++ .../honeywell_hih_i2c/test.esp32.yaml | 12 +++ .../honeywell_hih_i2c/test.esp8266.yaml | 12 +++ .../honeywell_hih_i2c/test.rp2040.yaml | 12 +++ .../honeywellabp/test.esp32-c3-idf.yaml | 15 ++++ .../honeywellabp/test.esp32-c3.yaml | 15 ++++ .../honeywellabp/test.esp32-idf.yaml | 15 ++++ tests/components/honeywellabp/test.esp32.yaml | 15 ++++ .../components/honeywellabp/test.esp8266.yaml | 15 ++++ .../components/honeywellabp/test.rp2040.yaml | 15 ++++ .../honeywellabp2_i2c/test.esp32-c3-idf.yaml | 15 ++++ .../honeywellabp2_i2c/test.esp32-c3.yaml | 15 ++++ .../honeywellabp2_i2c/test.esp32-idf.yaml | 15 ++++ .../honeywellabp2_i2c/test.esp32.yaml | 15 ++++ .../honeywellabp2_i2c/test.esp8266.yaml | 15 ++++ .../honeywellabp2_i2c/test.rp2040.yaml | 15 ++++ .../hrxl_maxsonar_wr/test.esp32-c3-idf.yaml | 10 +++ .../hrxl_maxsonar_wr/test.esp32-c3.yaml | 10 +++ .../hrxl_maxsonar_wr/test.esp32-idf.yaml | 10 +++ .../hrxl_maxsonar_wr/test.esp32.yaml | 10 +++ .../hrxl_maxsonar_wr/test.esp8266.yaml | 10 +++ .../hrxl_maxsonar_wr/test.rp2040.yaml | 10 +++ .../components/hte501/test.esp32-c3-idf.yaml | 12 +++ tests/components/hte501/test.esp32-c3.yaml | 12 +++ tests/components/hte501/test.esp32-idf.yaml | 12 +++ tests/components/hte501/test.esp32.yaml | 12 +++ tests/components/hte501/test.esp8266.yaml | 12 +++ tests/components/hte501/test.rp2040.yaml | 12 +++ .../http_request/test.esp32-c3.yaml | 7 ++ tests/components/http_request/test.esp32.yaml | 7 ++ .../components/http_request/test.esp8266.yaml | 7 ++ .../components/htu21d/test.esp32-c3-idf.yaml | 14 ++++ tests/components/htu21d/test.esp32-c3.yaml | 14 ++++ tests/components/htu21d/test.esp32-idf.yaml | 14 ++++ tests/components/htu21d/test.esp32.yaml | 14 ++++ tests/components/htu21d/test.esp8266.yaml | 14 ++++ tests/components/htu21d/test.rp2040.yaml | 14 ++++ tests/components/hx711/test.esp32-c3-idf.yaml | 7 ++ tests/components/hx711/test.esp32-c3.yaml | 7 ++ tests/components/hx711/test.esp32-idf.yaml | 7 ++ tests/components/hx711/test.esp32.yaml | 7 ++ tests/components/hx711/test.esp8266.yaml | 7 ++ tests/components/hx711/test.rp2040.yaml | 7 ++ .../hydreon_rgxx/test.esp32-c3-idf.yaml | 37 +++++++++ .../hydreon_rgxx/test.esp32-c3.yaml | 37 +++++++++ .../hydreon_rgxx/test.esp32-idf.yaml | 37 +++++++++ tests/components/hydreon_rgxx/test.esp32.yaml | 37 +++++++++ .../components/hydreon_rgxx/test.esp8266.yaml | 37 +++++++++ .../components/hydreon_rgxx/test.rp2040.yaml | 37 +++++++++ .../components/hyt271/test.esp32-c3-idf.yaml | 11 +++ tests/components/hyt271/test.esp32-c3.yaml | 11 +++ tests/components/hyt271/test.esp32-idf.yaml | 11 +++ tests/components/hyt271/test.esp32.yaml | 11 +++ tests/components/hyt271/test.esp8266.yaml | 11 +++ tests/components/hyt271/test.rp2040.yaml | 11 +++ 117 files changed, 2319 insertions(+) create mode 100644 tests/components/havells_solar/test.esp32-c3-idf.yaml create mode 100644 tests/components/havells_solar/test.esp32-c3.yaml create mode 100644 tests/components/havells_solar/test.esp32-idf.yaml create mode 100644 tests/components/havells_solar/test.esp32.yaml create mode 100644 tests/components/havells_solar/test.esp8266.yaml create mode 100644 tests/components/havells_solar/test.rp2040.yaml create mode 100644 tests/components/hbridge/test.esp32-c3-idf.yaml create mode 100644 tests/components/hbridge/test.esp32-c3.yaml create mode 100644 tests/components/hbridge/test.esp32-idf.yaml create mode 100644 tests/components/hbridge/test.esp32.yaml create mode 100644 tests/components/hbridge/test.esp8266.yaml create mode 100644 tests/components/hbridge/test.rp2040.yaml create mode 100644 tests/components/hdc1080/test.esp32-c3-idf.yaml create mode 100644 tests/components/hdc1080/test.esp32-c3.yaml create mode 100644 tests/components/hdc1080/test.esp32-idf.yaml create mode 100644 tests/components/hdc1080/test.esp32.yaml create mode 100644 tests/components/hdc1080/test.esp8266.yaml create mode 100644 tests/components/hdc1080/test.rp2040.yaml create mode 100644 tests/components/he60r/test.esp32-c3-idf.yaml create mode 100644 tests/components/he60r/test.esp32-c3.yaml create mode 100644 tests/components/he60r/test.esp32-idf.yaml create mode 100644 tests/components/he60r/test.esp32.yaml create mode 100644 tests/components/he60r/test.esp8266.yaml create mode 100644 tests/components/he60r/test.rp2040.yaml create mode 100644 tests/components/heatpumpir/test.esp32.yaml create mode 100644 tests/components/heatpumpir/test.esp8266.yaml create mode 100644 tests/components/hitachi_ac344/test.esp32-c3-idf.yaml create mode 100644 tests/components/hitachi_ac344/test.esp32-c3.yaml create mode 100644 tests/components/hitachi_ac344/test.esp32-idf.yaml create mode 100644 tests/components/hitachi_ac344/test.esp32.yaml create mode 100644 tests/components/hitachi_ac344/test.esp8266.yaml create mode 100644 tests/components/hitachi_ac424/test.esp32-c3-idf.yaml create mode 100644 tests/components/hitachi_ac424/test.esp32-c3.yaml create mode 100644 tests/components/hitachi_ac424/test.esp32-idf.yaml create mode 100644 tests/components/hitachi_ac424/test.esp32.yaml create mode 100644 tests/components/hitachi_ac424/test.esp8266.yaml create mode 100644 tests/components/hlw8012/test.esp32-c3-idf.yaml create mode 100644 tests/components/hlw8012/test.esp32-c3.yaml create mode 100644 tests/components/hlw8012/test.esp32-idf.yaml create mode 100644 tests/components/hlw8012/test.esp32.yaml create mode 100644 tests/components/hlw8012/test.esp8266.yaml create mode 100644 tests/components/hlw8012/test.rp2040.yaml create mode 100644 tests/components/hm3301/test.esp32-c3-idf.yaml create mode 100644 tests/components/hm3301/test.esp32-c3.yaml create mode 100644 tests/components/hm3301/test.esp32-idf.yaml create mode 100644 tests/components/hm3301/test.esp32.yaml create mode 100644 tests/components/hm3301/test.esp8266.yaml create mode 100644 tests/components/hm3301/test.rp2040.yaml create mode 100644 tests/components/hmc5883l/test.esp32-c3-idf.yaml create mode 100644 tests/components/hmc5883l/test.esp32-c3.yaml create mode 100644 tests/components/hmc5883l/test.esp32-idf.yaml create mode 100644 tests/components/hmc5883l/test.esp32.yaml create mode 100644 tests/components/hmc5883l/test.esp8266.yaml create mode 100644 tests/components/hmc5883l/test.rp2040.yaml create mode 100644 tests/components/homeassistant/test.esp32-c3-idf.yaml create mode 100644 tests/components/homeassistant/test.esp32-c3.yaml create mode 100644 tests/components/homeassistant/test.esp32-idf.yaml create mode 100644 tests/components/homeassistant/test.esp32.yaml create mode 100644 tests/components/homeassistant/test.esp8266.yaml create mode 100644 tests/components/homeassistant/test.rp2040.yaml create mode 100644 tests/components/honeywell_hih_i2c/test.esp32-c3-idf.yaml create mode 100644 tests/components/honeywell_hih_i2c/test.esp32-c3.yaml create mode 100644 tests/components/honeywell_hih_i2c/test.esp32-idf.yaml create mode 100644 tests/components/honeywell_hih_i2c/test.esp32.yaml create mode 100644 tests/components/honeywell_hih_i2c/test.esp8266.yaml create mode 100644 tests/components/honeywell_hih_i2c/test.rp2040.yaml create mode 100644 tests/components/honeywellabp/test.esp32-c3-idf.yaml create mode 100644 tests/components/honeywellabp/test.esp32-c3.yaml create mode 100644 tests/components/honeywellabp/test.esp32-idf.yaml create mode 100644 tests/components/honeywellabp/test.esp32.yaml create mode 100644 tests/components/honeywellabp/test.esp8266.yaml create mode 100644 tests/components/honeywellabp/test.rp2040.yaml create mode 100644 tests/components/honeywellabp2_i2c/test.esp32-c3-idf.yaml create mode 100644 tests/components/honeywellabp2_i2c/test.esp32-c3.yaml create mode 100644 tests/components/honeywellabp2_i2c/test.esp32-idf.yaml create mode 100644 tests/components/honeywellabp2_i2c/test.esp32.yaml create mode 100644 tests/components/honeywellabp2_i2c/test.esp8266.yaml create mode 100644 tests/components/honeywellabp2_i2c/test.rp2040.yaml create mode 100644 tests/components/hrxl_maxsonar_wr/test.esp32-c3-idf.yaml create mode 100644 tests/components/hrxl_maxsonar_wr/test.esp32-c3.yaml create mode 100644 tests/components/hrxl_maxsonar_wr/test.esp32-idf.yaml create mode 100644 tests/components/hrxl_maxsonar_wr/test.esp32.yaml create mode 100644 tests/components/hrxl_maxsonar_wr/test.esp8266.yaml create mode 100644 tests/components/hrxl_maxsonar_wr/test.rp2040.yaml create mode 100644 tests/components/hte501/test.esp32-c3-idf.yaml create mode 100644 tests/components/hte501/test.esp32-c3.yaml create mode 100644 tests/components/hte501/test.esp32-idf.yaml create mode 100644 tests/components/hte501/test.esp32.yaml create mode 100644 tests/components/hte501/test.esp8266.yaml create mode 100644 tests/components/hte501/test.rp2040.yaml create mode 100644 tests/components/http_request/test.esp32-c3.yaml create mode 100644 tests/components/http_request/test.esp32.yaml create mode 100644 tests/components/http_request/test.esp8266.yaml create mode 100644 tests/components/htu21d/test.esp32-c3-idf.yaml create mode 100644 tests/components/htu21d/test.esp32-c3.yaml create mode 100644 tests/components/htu21d/test.esp32-idf.yaml create mode 100644 tests/components/htu21d/test.esp32.yaml create mode 100644 tests/components/htu21d/test.esp8266.yaml create mode 100644 tests/components/htu21d/test.rp2040.yaml create mode 100644 tests/components/hx711/test.esp32-c3-idf.yaml create mode 100644 tests/components/hx711/test.esp32-c3.yaml create mode 100644 tests/components/hx711/test.esp32-idf.yaml create mode 100644 tests/components/hx711/test.esp32.yaml create mode 100644 tests/components/hx711/test.esp8266.yaml create mode 100644 tests/components/hx711/test.rp2040.yaml create mode 100644 tests/components/hydreon_rgxx/test.esp32-c3-idf.yaml create mode 100644 tests/components/hydreon_rgxx/test.esp32-c3.yaml create mode 100644 tests/components/hydreon_rgxx/test.esp32-idf.yaml create mode 100644 tests/components/hydreon_rgxx/test.esp32.yaml create mode 100644 tests/components/hydreon_rgxx/test.esp8266.yaml create mode 100644 tests/components/hydreon_rgxx/test.rp2040.yaml create mode 100644 tests/components/hyt271/test.esp32-c3-idf.yaml create mode 100644 tests/components/hyt271/test.esp32-c3.yaml create mode 100644 tests/components/hyt271/test.esp32-idf.yaml create mode 100644 tests/components/hyt271/test.esp32.yaml create mode 100644 tests/components/hyt271/test.esp8266.yaml create mode 100644 tests/components/hyt271/test.rp2040.yaml diff --git a/tests/components/havells_solar/test.esp32-c3-idf.yaml b/tests/components/havells_solar/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..5cb911cf71 --- /dev/null +++ b/tests/components/havells_solar/test.esp32-c3-idf.yaml @@ -0,0 +1,79 @@ +uart: + - id: uart_havells_solar + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +modbus: + flow_control_pin: 3 + +sensor: + - platform: havells_solar + update_interval: 60s + phase_a: + voltage: + name: Phase A Voltage + current: + name: Phase A Current + phase_b: + voltage: + name: Voltage Phase B + current: + name: Current Phase B + phase_c: + voltage: + name: Voltage Phase C + current: + name: Current Phase C + pv1: + voltage: + name: PV1 Voltage + current: + name: PV1 Current + active_power: + name: PV1 Active Power + voltage_sampled_by_secondary_cpu: + name: PV1 Voltage Sampled By Secondary CPU + insulation_of_p_to_ground: + name: PV1 Insulation Of +VE To Ground + pv2: + voltage: + name: PV2 Voltage + current: + name: PV2 Current + active_power: + name: PV2 Active Power + voltage_sampled_by_secondary_cpu: + name: PV2 Voltage Sampled By Secondary CPU + insulation_of_p_to_ground: + name: PV2 Insulation Of +VE To Ground + active_power: + name: Active Power + reactive_power: + name: Reactive Power + frequency: + name: Frequency + energy_production_day: + name: Today's Generation + total_energy_production: + name: Total Energy Production + total_generation_time: + name: Total Generation Time + today_generation_time: + name: Today Generation Time + inverter_module_temp: + name: Inverter Module Temp + inverter_inner_temp: + name: Inverter Inner Temp + inverter_bus_voltage: + name: Inverter BUS Voltage + insulation_of_pv_n_to_ground: + name: Insulation Of PV- To Ground + gfci_value: + name: GFCI Value + dci_of_r: + name: DCI Of R + dci_of_s: + name: DCI Of S + dci_of_t: + name: DCI Of T diff --git a/tests/components/havells_solar/test.esp32-c3.yaml b/tests/components/havells_solar/test.esp32-c3.yaml new file mode 100644 index 0000000000..5cb911cf71 --- /dev/null +++ b/tests/components/havells_solar/test.esp32-c3.yaml @@ -0,0 +1,79 @@ +uart: + - id: uart_havells_solar + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +modbus: + flow_control_pin: 3 + +sensor: + - platform: havells_solar + update_interval: 60s + phase_a: + voltage: + name: Phase A Voltage + current: + name: Phase A Current + phase_b: + voltage: + name: Voltage Phase B + current: + name: Current Phase B + phase_c: + voltage: + name: Voltage Phase C + current: + name: Current Phase C + pv1: + voltage: + name: PV1 Voltage + current: + name: PV1 Current + active_power: + name: PV1 Active Power + voltage_sampled_by_secondary_cpu: + name: PV1 Voltage Sampled By Secondary CPU + insulation_of_p_to_ground: + name: PV1 Insulation Of +VE To Ground + pv2: + voltage: + name: PV2 Voltage + current: + name: PV2 Current + active_power: + name: PV2 Active Power + voltage_sampled_by_secondary_cpu: + name: PV2 Voltage Sampled By Secondary CPU + insulation_of_p_to_ground: + name: PV2 Insulation Of +VE To Ground + active_power: + name: Active Power + reactive_power: + name: Reactive Power + frequency: + name: Frequency + energy_production_day: + name: Today's Generation + total_energy_production: + name: Total Energy Production + total_generation_time: + name: Total Generation Time + today_generation_time: + name: Today Generation Time + inverter_module_temp: + name: Inverter Module Temp + inverter_inner_temp: + name: Inverter Inner Temp + inverter_bus_voltage: + name: Inverter BUS Voltage + insulation_of_pv_n_to_ground: + name: Insulation Of PV- To Ground + gfci_value: + name: GFCI Value + dci_of_r: + name: DCI Of R + dci_of_s: + name: DCI Of S + dci_of_t: + name: DCI Of T diff --git a/tests/components/havells_solar/test.esp32-idf.yaml b/tests/components/havells_solar/test.esp32-idf.yaml new file mode 100644 index 0000000000..2cda8e37be --- /dev/null +++ b/tests/components/havells_solar/test.esp32-idf.yaml @@ -0,0 +1,79 @@ +uart: + - id: uart_havells_solar + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +modbus: + flow_control_pin: 3 + +sensor: + - platform: havells_solar + update_interval: 60s + phase_a: + voltage: + name: Phase A Voltage + current: + name: Phase A Current + phase_b: + voltage: + name: Voltage Phase B + current: + name: Current Phase B + phase_c: + voltage: + name: Voltage Phase C + current: + name: Current Phase C + pv1: + voltage: + name: PV1 Voltage + current: + name: PV1 Current + active_power: + name: PV1 Active Power + voltage_sampled_by_secondary_cpu: + name: PV1 Voltage Sampled By Secondary CPU + insulation_of_p_to_ground: + name: PV1 Insulation Of +VE To Ground + pv2: + voltage: + name: PV2 Voltage + current: + name: PV2 Current + active_power: + name: PV2 Active Power + voltage_sampled_by_secondary_cpu: + name: PV2 Voltage Sampled By Secondary CPU + insulation_of_p_to_ground: + name: PV2 Insulation Of +VE To Ground + active_power: + name: Active Power + reactive_power: + name: Reactive Power + frequency: + name: Frequency + energy_production_day: + name: Today's Generation + total_energy_production: + name: Total Energy Production + total_generation_time: + name: Total Generation Time + today_generation_time: + name: Today Generation Time + inverter_module_temp: + name: Inverter Module Temp + inverter_inner_temp: + name: Inverter Inner Temp + inverter_bus_voltage: + name: Inverter BUS Voltage + insulation_of_pv_n_to_ground: + name: Insulation Of PV- To Ground + gfci_value: + name: GFCI Value + dci_of_r: + name: DCI Of R + dci_of_s: + name: DCI Of S + dci_of_t: + name: DCI Of T diff --git a/tests/components/havells_solar/test.esp32.yaml b/tests/components/havells_solar/test.esp32.yaml new file mode 100644 index 0000000000..2cda8e37be --- /dev/null +++ b/tests/components/havells_solar/test.esp32.yaml @@ -0,0 +1,79 @@ +uart: + - id: uart_havells_solar + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +modbus: + flow_control_pin: 3 + +sensor: + - platform: havells_solar + update_interval: 60s + phase_a: + voltage: + name: Phase A Voltage + current: + name: Phase A Current + phase_b: + voltage: + name: Voltage Phase B + current: + name: Current Phase B + phase_c: + voltage: + name: Voltage Phase C + current: + name: Current Phase C + pv1: + voltage: + name: PV1 Voltage + current: + name: PV1 Current + active_power: + name: PV1 Active Power + voltage_sampled_by_secondary_cpu: + name: PV1 Voltage Sampled By Secondary CPU + insulation_of_p_to_ground: + name: PV1 Insulation Of +VE To Ground + pv2: + voltage: + name: PV2 Voltage + current: + name: PV2 Current + active_power: + name: PV2 Active Power + voltage_sampled_by_secondary_cpu: + name: PV2 Voltage Sampled By Secondary CPU + insulation_of_p_to_ground: + name: PV2 Insulation Of +VE To Ground + active_power: + name: Active Power + reactive_power: + name: Reactive Power + frequency: + name: Frequency + energy_production_day: + name: Today's Generation + total_energy_production: + name: Total Energy Production + total_generation_time: + name: Total Generation Time + today_generation_time: + name: Today Generation Time + inverter_module_temp: + name: Inverter Module Temp + inverter_inner_temp: + name: Inverter Inner Temp + inverter_bus_voltage: + name: Inverter BUS Voltage + insulation_of_pv_n_to_ground: + name: Insulation Of PV- To Ground + gfci_value: + name: GFCI Value + dci_of_r: + name: DCI Of R + dci_of_s: + name: DCI Of S + dci_of_t: + name: DCI Of T diff --git a/tests/components/havells_solar/test.esp8266.yaml b/tests/components/havells_solar/test.esp8266.yaml new file mode 100644 index 0000000000..5cb911cf71 --- /dev/null +++ b/tests/components/havells_solar/test.esp8266.yaml @@ -0,0 +1,79 @@ +uart: + - id: uart_havells_solar + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +modbus: + flow_control_pin: 3 + +sensor: + - platform: havells_solar + update_interval: 60s + phase_a: + voltage: + name: Phase A Voltage + current: + name: Phase A Current + phase_b: + voltage: + name: Voltage Phase B + current: + name: Current Phase B + phase_c: + voltage: + name: Voltage Phase C + current: + name: Current Phase C + pv1: + voltage: + name: PV1 Voltage + current: + name: PV1 Current + active_power: + name: PV1 Active Power + voltage_sampled_by_secondary_cpu: + name: PV1 Voltage Sampled By Secondary CPU + insulation_of_p_to_ground: + name: PV1 Insulation Of +VE To Ground + pv2: + voltage: + name: PV2 Voltage + current: + name: PV2 Current + active_power: + name: PV2 Active Power + voltage_sampled_by_secondary_cpu: + name: PV2 Voltage Sampled By Secondary CPU + insulation_of_p_to_ground: + name: PV2 Insulation Of +VE To Ground + active_power: + name: Active Power + reactive_power: + name: Reactive Power + frequency: + name: Frequency + energy_production_day: + name: Today's Generation + total_energy_production: + name: Total Energy Production + total_generation_time: + name: Total Generation Time + today_generation_time: + name: Today Generation Time + inverter_module_temp: + name: Inverter Module Temp + inverter_inner_temp: + name: Inverter Inner Temp + inverter_bus_voltage: + name: Inverter BUS Voltage + insulation_of_pv_n_to_ground: + name: Insulation Of PV- To Ground + gfci_value: + name: GFCI Value + dci_of_r: + name: DCI Of R + dci_of_s: + name: DCI Of S + dci_of_t: + name: DCI Of T diff --git a/tests/components/havells_solar/test.rp2040.yaml b/tests/components/havells_solar/test.rp2040.yaml new file mode 100644 index 0000000000..5cb911cf71 --- /dev/null +++ b/tests/components/havells_solar/test.rp2040.yaml @@ -0,0 +1,79 @@ +uart: + - id: uart_havells_solar + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +modbus: + flow_control_pin: 3 + +sensor: + - platform: havells_solar + update_interval: 60s + phase_a: + voltage: + name: Phase A Voltage + current: + name: Phase A Current + phase_b: + voltage: + name: Voltage Phase B + current: + name: Current Phase B + phase_c: + voltage: + name: Voltage Phase C + current: + name: Current Phase C + pv1: + voltage: + name: PV1 Voltage + current: + name: PV1 Current + active_power: + name: PV1 Active Power + voltage_sampled_by_secondary_cpu: + name: PV1 Voltage Sampled By Secondary CPU + insulation_of_p_to_ground: + name: PV1 Insulation Of +VE To Ground + pv2: + voltage: + name: PV2 Voltage + current: + name: PV2 Current + active_power: + name: PV2 Active Power + voltage_sampled_by_secondary_cpu: + name: PV2 Voltage Sampled By Secondary CPU + insulation_of_p_to_ground: + name: PV2 Insulation Of +VE To Ground + active_power: + name: Active Power + reactive_power: + name: Reactive Power + frequency: + name: Frequency + energy_production_day: + name: Today's Generation + total_energy_production: + name: Total Energy Production + total_generation_time: + name: Total Generation Time + today_generation_time: + name: Today Generation Time + inverter_module_temp: + name: Inverter Module Temp + inverter_inner_temp: + name: Inverter Inner Temp + inverter_bus_voltage: + name: Inverter BUS Voltage + insulation_of_pv_n_to_ground: + name: Insulation Of PV- To Ground + gfci_value: + name: GFCI Value + dci_of_r: + name: DCI Of R + dci_of_s: + name: DCI Of S + dci_of_t: + name: DCI Of T diff --git a/tests/components/hbridge/test.esp32-c3-idf.yaml b/tests/components/hbridge/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..70cfd6ab6f --- /dev/null +++ b/tests/components/hbridge/test.esp32-c3-idf.yaml @@ -0,0 +1,33 @@ +output: + - platform: ledc + pin: 4 + id: gpio_output1 + - platform: ledc + pin: 5 + id: gpio_output2 + - platform: ledc + pin: 6 + id: gpio_output3 + - platform: ledc + pin: 7 + id: gpio_output4 + +light: + - platform: hbridge + name: Icicle Lights + pin_a: gpio_output3 + pin_b: gpio_output4 + +fan: + - platform: hbridge + id: fan_hbridge + speed_count: 4 + name: H-bridge Fan with Presets + pin_a: gpio_output1 + pin_b: gpio_output2 + preset_modes: + - Preset 1 + - Preset 2 + on_preset_set: + then: + - logger.log: Preset mode was changed! diff --git a/tests/components/hbridge/test.esp32-c3.yaml b/tests/components/hbridge/test.esp32-c3.yaml new file mode 100644 index 0000000000..70cfd6ab6f --- /dev/null +++ b/tests/components/hbridge/test.esp32-c3.yaml @@ -0,0 +1,33 @@ +output: + - platform: ledc + pin: 4 + id: gpio_output1 + - platform: ledc + pin: 5 + id: gpio_output2 + - platform: ledc + pin: 6 + id: gpio_output3 + - platform: ledc + pin: 7 + id: gpio_output4 + +light: + - platform: hbridge + name: Icicle Lights + pin_a: gpio_output3 + pin_b: gpio_output4 + +fan: + - platform: hbridge + id: fan_hbridge + speed_count: 4 + name: H-bridge Fan with Presets + pin_a: gpio_output1 + pin_b: gpio_output2 + preset_modes: + - Preset 1 + - Preset 2 + on_preset_set: + then: + - logger.log: Preset mode was changed! diff --git a/tests/components/hbridge/test.esp32-idf.yaml b/tests/components/hbridge/test.esp32-idf.yaml new file mode 100644 index 0000000000..6a80aaaf3b --- /dev/null +++ b/tests/components/hbridge/test.esp32-idf.yaml @@ -0,0 +1,33 @@ +output: + - platform: ledc + pin: 14 + id: gpio_output1 + - platform: ledc + pin: 15 + id: gpio_output2 + - platform: ledc + pin: 12 + id: gpio_output3 + - platform: ledc + pin: 13 + id: gpio_output4 + +light: + - platform: hbridge + name: Icicle Lights + pin_a: gpio_output3 + pin_b: gpio_output4 + +fan: + - platform: hbridge + id: fan_hbridge + speed_count: 4 + name: H-bridge Fan with Presets + pin_a: gpio_output1 + pin_b: gpio_output2 + preset_modes: + - Preset 1 + - Preset 2 + on_preset_set: + then: + - logger.log: Preset mode was changed! diff --git a/tests/components/hbridge/test.esp32.yaml b/tests/components/hbridge/test.esp32.yaml new file mode 100644 index 0000000000..6a80aaaf3b --- /dev/null +++ b/tests/components/hbridge/test.esp32.yaml @@ -0,0 +1,33 @@ +output: + - platform: ledc + pin: 14 + id: gpio_output1 + - platform: ledc + pin: 15 + id: gpio_output2 + - platform: ledc + pin: 12 + id: gpio_output3 + - platform: ledc + pin: 13 + id: gpio_output4 + +light: + - platform: hbridge + name: Icicle Lights + pin_a: gpio_output3 + pin_b: gpio_output4 + +fan: + - platform: hbridge + id: fan_hbridge + speed_count: 4 + name: H-bridge Fan with Presets + pin_a: gpio_output1 + pin_b: gpio_output2 + preset_modes: + - Preset 1 + - Preset 2 + on_preset_set: + then: + - logger.log: Preset mode was changed! diff --git a/tests/components/hbridge/test.esp8266.yaml b/tests/components/hbridge/test.esp8266.yaml new file mode 100644 index 0000000000..4f8915879d --- /dev/null +++ b/tests/components/hbridge/test.esp8266.yaml @@ -0,0 +1,33 @@ +output: + - platform: esp8266_pwm + pin: 4 + id: gpio_output1 + - platform: esp8266_pwm + pin: 5 + id: gpio_output2 + - platform: esp8266_pwm + pin: 12 + id: gpio_output3 + - platform: esp8266_pwm + pin: 13 + id: gpio_output4 + +light: + - platform: hbridge + name: Icicle Lights + pin_a: gpio_output3 + pin_b: gpio_output4 + +fan: + - platform: hbridge + id: fan_hbridge + speed_count: 4 + name: H-bridge Fan with Presets + pin_a: gpio_output1 + pin_b: gpio_output2 + preset_modes: + - Preset 1 + - Preset 2 + on_preset_set: + then: + - logger.log: Preset mode was changed! diff --git a/tests/components/hbridge/test.rp2040.yaml b/tests/components/hbridge/test.rp2040.yaml new file mode 100644 index 0000000000..e21b55091d --- /dev/null +++ b/tests/components/hbridge/test.rp2040.yaml @@ -0,0 +1,33 @@ +output: + - platform: rp2040_pwm + pin: 4 + id: gpio_output1 + - platform: rp2040_pwm + pin: 5 + id: gpio_output2 + - platform: rp2040_pwm + pin: 6 + id: gpio_output3 + - platform: rp2040_pwm + pin: 7 + id: gpio_output4 + +light: + - platform: hbridge + name: Icicle Lights + pin_a: gpio_output3 + pin_b: gpio_output4 + +fan: + - platform: hbridge + id: fan_hbridge + speed_count: 4 + name: H-bridge Fan with Presets + pin_a: gpio_output1 + pin_b: gpio_output2 + preset_modes: + - Preset 1 + - Preset 2 + on_preset_set: + then: + - logger.log: Preset mode was changed! diff --git a/tests/components/hdc1080/test.esp32-c3-idf.yaml b/tests/components/hdc1080/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..7bf7af6fa7 --- /dev/null +++ b/tests/components/hdc1080/test.esp32-c3-idf.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_hdc1080 + scl: 5 + sda: 4 + +sensor: + - platform: hdc1080 + temperature: + name: Temperature + humidity: + name: Humidity + update_interval: 15s diff --git a/tests/components/hdc1080/test.esp32-c3.yaml b/tests/components/hdc1080/test.esp32-c3.yaml new file mode 100644 index 0000000000..7bf7af6fa7 --- /dev/null +++ b/tests/components/hdc1080/test.esp32-c3.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_hdc1080 + scl: 5 + sda: 4 + +sensor: + - platform: hdc1080 + temperature: + name: Temperature + humidity: + name: Humidity + update_interval: 15s diff --git a/tests/components/hdc1080/test.esp32-idf.yaml b/tests/components/hdc1080/test.esp32-idf.yaml new file mode 100644 index 0000000000..8e313dfa40 --- /dev/null +++ b/tests/components/hdc1080/test.esp32-idf.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_hdc1080 + scl: 16 + sda: 17 + +sensor: + - platform: hdc1080 + temperature: + name: Temperature + humidity: + name: Humidity + update_interval: 15s diff --git a/tests/components/hdc1080/test.esp32.yaml b/tests/components/hdc1080/test.esp32.yaml new file mode 100644 index 0000000000..8e313dfa40 --- /dev/null +++ b/tests/components/hdc1080/test.esp32.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_hdc1080 + scl: 16 + sda: 17 + +sensor: + - platform: hdc1080 + temperature: + name: Temperature + humidity: + name: Humidity + update_interval: 15s diff --git a/tests/components/hdc1080/test.esp8266.yaml b/tests/components/hdc1080/test.esp8266.yaml new file mode 100644 index 0000000000..7bf7af6fa7 --- /dev/null +++ b/tests/components/hdc1080/test.esp8266.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_hdc1080 + scl: 5 + sda: 4 + +sensor: + - platform: hdc1080 + temperature: + name: Temperature + humidity: + name: Humidity + update_interval: 15s diff --git a/tests/components/hdc1080/test.rp2040.yaml b/tests/components/hdc1080/test.rp2040.yaml new file mode 100644 index 0000000000..7bf7af6fa7 --- /dev/null +++ b/tests/components/hdc1080/test.rp2040.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_hdc1080 + scl: 5 + sda: 4 + +sensor: + - platform: hdc1080 + temperature: + name: Temperature + humidity: + name: Humidity + update_interval: 15s diff --git a/tests/components/he60r/test.esp32-c3-idf.yaml b/tests/components/he60r/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..bcbb544442 --- /dev/null +++ b/tests/components/he60r/test.esp32-c3-idf.yaml @@ -0,0 +1,13 @@ +uart: + - id: uart_he60r + tx_pin: 4 + rx_pin: 5 + baud_rate: 1200 + parity: EVEN + +cover: + - platform: he60r + id: garage_door + name: Garage Door + open_duration: 14s + close_duration: 14s diff --git a/tests/components/he60r/test.esp32-c3.yaml b/tests/components/he60r/test.esp32-c3.yaml new file mode 100644 index 0000000000..bcbb544442 --- /dev/null +++ b/tests/components/he60r/test.esp32-c3.yaml @@ -0,0 +1,13 @@ +uart: + - id: uart_he60r + tx_pin: 4 + rx_pin: 5 + baud_rate: 1200 + parity: EVEN + +cover: + - platform: he60r + id: garage_door + name: Garage Door + open_duration: 14s + close_duration: 14s diff --git a/tests/components/he60r/test.esp32-idf.yaml b/tests/components/he60r/test.esp32-idf.yaml new file mode 100644 index 0000000000..840387ae36 --- /dev/null +++ b/tests/components/he60r/test.esp32-idf.yaml @@ -0,0 +1,13 @@ +uart: + - id: uart_he60r + tx_pin: 17 + rx_pin: 16 + baud_rate: 1200 + parity: EVEN + +cover: + - platform: he60r + id: garage_door + name: Garage Door + open_duration: 14s + close_duration: 14s diff --git a/tests/components/he60r/test.esp32.yaml b/tests/components/he60r/test.esp32.yaml new file mode 100644 index 0000000000..840387ae36 --- /dev/null +++ b/tests/components/he60r/test.esp32.yaml @@ -0,0 +1,13 @@ +uart: + - id: uart_he60r + tx_pin: 17 + rx_pin: 16 + baud_rate: 1200 + parity: EVEN + +cover: + - platform: he60r + id: garage_door + name: Garage Door + open_duration: 14s + close_duration: 14s diff --git a/tests/components/he60r/test.esp8266.yaml b/tests/components/he60r/test.esp8266.yaml new file mode 100644 index 0000000000..bcbb544442 --- /dev/null +++ b/tests/components/he60r/test.esp8266.yaml @@ -0,0 +1,13 @@ +uart: + - id: uart_he60r + tx_pin: 4 + rx_pin: 5 + baud_rate: 1200 + parity: EVEN + +cover: + - platform: he60r + id: garage_door + name: Garage Door + open_duration: 14s + close_duration: 14s diff --git a/tests/components/he60r/test.rp2040.yaml b/tests/components/he60r/test.rp2040.yaml new file mode 100644 index 0000000000..bcbb544442 --- /dev/null +++ b/tests/components/he60r/test.rp2040.yaml @@ -0,0 +1,13 @@ +uart: + - id: uart_he60r + tx_pin: 4 + rx_pin: 5 + baud_rate: 1200 + parity: EVEN + +cover: + - platform: he60r + id: garage_door + name: Garage Door + open_duration: 14s + close_duration: 14s diff --git a/tests/components/heatpumpir/test.esp32.yaml b/tests/components/heatpumpir/test.esp32.yaml new file mode 100644 index 0000000000..db3f81f6a0 --- /dev/null +++ b/tests/components/heatpumpir/test.esp32.yaml @@ -0,0 +1,19 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +climate: + - platform: heatpumpir + protocol: mitsubishi_heavy_zm + horizontal_default: left + vertical_default: up + name: HeatpumpIR Climate + min_temperature: 18 + max_temperature: 30 + - platform: heatpumpir + protocol: greeyt + horizontal_default: left + vertical_default: up + name: HeatpumpIR Climate + min_temperature: 18 + max_temperature: 30 diff --git a/tests/components/heatpumpir/test.esp8266.yaml b/tests/components/heatpumpir/test.esp8266.yaml new file mode 100644 index 0000000000..26a01cb198 --- /dev/null +++ b/tests/components/heatpumpir/test.esp8266.yaml @@ -0,0 +1,19 @@ +remote_transmitter: + pin: 5 + carrier_duty_percent: 50% + +climate: + - platform: heatpumpir + protocol: mitsubishi_heavy_zm + horizontal_default: left + vertical_default: up + name: HeatpumpIR Climate + min_temperature: 18 + max_temperature: 30 + - platform: heatpumpir + protocol: greeyt + horizontal_default: left + vertical_default: up + name: HeatpumpIR Climate + min_temperature: 18 + max_temperature: 30 diff --git a/tests/components/hitachi_ac344/test.esp32-c3-idf.yaml b/tests/components/hitachi_ac344/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..684d5899de --- /dev/null +++ b/tests/components/hitachi_ac344/test.esp32-c3-idf.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +climate: + - platform: hitachi_ac344 + name: Hitachi Climate diff --git a/tests/components/hitachi_ac344/test.esp32-c3.yaml b/tests/components/hitachi_ac344/test.esp32-c3.yaml new file mode 100644 index 0000000000..684d5899de --- /dev/null +++ b/tests/components/hitachi_ac344/test.esp32-c3.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +climate: + - platform: hitachi_ac344 + name: Hitachi Climate diff --git a/tests/components/hitachi_ac344/test.esp32-idf.yaml b/tests/components/hitachi_ac344/test.esp32-idf.yaml new file mode 100644 index 0000000000..684d5899de --- /dev/null +++ b/tests/components/hitachi_ac344/test.esp32-idf.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +climate: + - platform: hitachi_ac344 + name: Hitachi Climate diff --git a/tests/components/hitachi_ac344/test.esp32.yaml b/tests/components/hitachi_ac344/test.esp32.yaml new file mode 100644 index 0000000000..684d5899de --- /dev/null +++ b/tests/components/hitachi_ac344/test.esp32.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +climate: + - platform: hitachi_ac344 + name: Hitachi Climate diff --git a/tests/components/hitachi_ac344/test.esp8266.yaml b/tests/components/hitachi_ac344/test.esp8266.yaml new file mode 100644 index 0000000000..e6203e3084 --- /dev/null +++ b/tests/components/hitachi_ac344/test.esp8266.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 5 + carrier_duty_percent: 50% + +climate: + - platform: hitachi_ac344 + name: Hitachi Climate diff --git a/tests/components/hitachi_ac424/test.esp32-c3-idf.yaml b/tests/components/hitachi_ac424/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..a09821b9c6 --- /dev/null +++ b/tests/components/hitachi_ac424/test.esp32-c3-idf.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +climate: + - platform: hitachi_ac424 + name: Hitachi Climate diff --git a/tests/components/hitachi_ac424/test.esp32-c3.yaml b/tests/components/hitachi_ac424/test.esp32-c3.yaml new file mode 100644 index 0000000000..a09821b9c6 --- /dev/null +++ b/tests/components/hitachi_ac424/test.esp32-c3.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +climate: + - platform: hitachi_ac424 + name: Hitachi Climate diff --git a/tests/components/hitachi_ac424/test.esp32-idf.yaml b/tests/components/hitachi_ac424/test.esp32-idf.yaml new file mode 100644 index 0000000000..a09821b9c6 --- /dev/null +++ b/tests/components/hitachi_ac424/test.esp32-idf.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +climate: + - platform: hitachi_ac424 + name: Hitachi Climate diff --git a/tests/components/hitachi_ac424/test.esp32.yaml b/tests/components/hitachi_ac424/test.esp32.yaml new file mode 100644 index 0000000000..a09821b9c6 --- /dev/null +++ b/tests/components/hitachi_ac424/test.esp32.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +climate: + - platform: hitachi_ac424 + name: Hitachi Climate diff --git a/tests/components/hitachi_ac424/test.esp8266.yaml b/tests/components/hitachi_ac424/test.esp8266.yaml new file mode 100644 index 0000000000..78b9e7c98c --- /dev/null +++ b/tests/components/hitachi_ac424/test.esp8266.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 5 + carrier_duty_percent: 50% + +climate: + - platform: hitachi_ac424 + name: Hitachi Climate diff --git a/tests/components/hlw8012/test.esp32-c3-idf.yaml b/tests/components/hlw8012/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..da6053a1b9 --- /dev/null +++ b/tests/components/hlw8012/test.esp32-c3-idf.yaml @@ -0,0 +1,21 @@ +sensor: + - platform: hlw8012 + model: hlw8012 + sel_pin: 2 + cf_pin: 4 + cf1_pin: 3 + current: + name: HLW8012 Current + voltage: + name: HLW8012 Voltage + power: + name: HLW8012 Power + id: hlw8012_power + energy: + name: HLW8012 Energy + id: hlw8012_energy + update_interval: 15s + current_resistor: 0.001 ohm + voltage_divider: 2351 + change_mode_every: "never" + initial_mode: VOLTAGE diff --git a/tests/components/hlw8012/test.esp32-c3.yaml b/tests/components/hlw8012/test.esp32-c3.yaml new file mode 100644 index 0000000000..da6053a1b9 --- /dev/null +++ b/tests/components/hlw8012/test.esp32-c3.yaml @@ -0,0 +1,21 @@ +sensor: + - platform: hlw8012 + model: hlw8012 + sel_pin: 2 + cf_pin: 4 + cf1_pin: 3 + current: + name: HLW8012 Current + voltage: + name: HLW8012 Voltage + power: + name: HLW8012 Power + id: hlw8012_power + energy: + name: HLW8012 Energy + id: hlw8012_energy + update_interval: 15s + current_resistor: 0.001 ohm + voltage_divider: 2351 + change_mode_every: "never" + initial_mode: VOLTAGE diff --git a/tests/components/hlw8012/test.esp32-idf.yaml b/tests/components/hlw8012/test.esp32-idf.yaml new file mode 100644 index 0000000000..5b2d865722 --- /dev/null +++ b/tests/components/hlw8012/test.esp32-idf.yaml @@ -0,0 +1,21 @@ +sensor: + - platform: hlw8012 + model: hlw8012 + sel_pin: 12 + cf_pin: 14 + cf1_pin: 13 + current: + name: HLW8012 Current + voltage: + name: HLW8012 Voltage + power: + name: HLW8012 Power + id: hlw8012_power + energy: + name: HLW8012 Energy + id: hlw8012_energy + update_interval: 15s + current_resistor: 0.001 ohm + voltage_divider: 2351 + change_mode_every: "never" + initial_mode: VOLTAGE diff --git a/tests/components/hlw8012/test.esp32.yaml b/tests/components/hlw8012/test.esp32.yaml new file mode 100644 index 0000000000..5b2d865722 --- /dev/null +++ b/tests/components/hlw8012/test.esp32.yaml @@ -0,0 +1,21 @@ +sensor: + - platform: hlw8012 + model: hlw8012 + sel_pin: 12 + cf_pin: 14 + cf1_pin: 13 + current: + name: HLW8012 Current + voltage: + name: HLW8012 Voltage + power: + name: HLW8012 Power + id: hlw8012_power + energy: + name: HLW8012 Energy + id: hlw8012_energy + update_interval: 15s + current_resistor: 0.001 ohm + voltage_divider: 2351 + change_mode_every: "never" + initial_mode: VOLTAGE diff --git a/tests/components/hlw8012/test.esp8266.yaml b/tests/components/hlw8012/test.esp8266.yaml new file mode 100644 index 0000000000..5b2d865722 --- /dev/null +++ b/tests/components/hlw8012/test.esp8266.yaml @@ -0,0 +1,21 @@ +sensor: + - platform: hlw8012 + model: hlw8012 + sel_pin: 12 + cf_pin: 14 + cf1_pin: 13 + current: + name: HLW8012 Current + voltage: + name: HLW8012 Voltage + power: + name: HLW8012 Power + id: hlw8012_power + energy: + name: HLW8012 Energy + id: hlw8012_energy + update_interval: 15s + current_resistor: 0.001 ohm + voltage_divider: 2351 + change_mode_every: "never" + initial_mode: VOLTAGE diff --git a/tests/components/hlw8012/test.rp2040.yaml b/tests/components/hlw8012/test.rp2040.yaml new file mode 100644 index 0000000000..da6053a1b9 --- /dev/null +++ b/tests/components/hlw8012/test.rp2040.yaml @@ -0,0 +1,21 @@ +sensor: + - platform: hlw8012 + model: hlw8012 + sel_pin: 2 + cf_pin: 4 + cf1_pin: 3 + current: + name: HLW8012 Current + voltage: + name: HLW8012 Voltage + power: + name: HLW8012 Power + id: hlw8012_power + energy: + name: HLW8012 Energy + id: hlw8012_energy + update_interval: 15s + current_resistor: 0.001 ohm + voltage_divider: 2351 + change_mode_every: "never" + initial_mode: VOLTAGE diff --git a/tests/components/hm3301/test.esp32-c3-idf.yaml b/tests/components/hm3301/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..eb6c4a14e6 --- /dev/null +++ b/tests/components/hm3301/test.esp32-c3-idf.yaml @@ -0,0 +1,16 @@ +i2c: + - id: i2c_hm3301 + scl: 5 + sda: 4 + +sensor: + - platform: hm3301 + pm_1_0: + name: PM1.0 + pm_2_5: + name: PM2.5 + pm_10_0: + name: PM10.0 + aqi: + name: AQI + calculation_type: CAQI diff --git a/tests/components/hm3301/test.esp32-c3.yaml b/tests/components/hm3301/test.esp32-c3.yaml new file mode 100644 index 0000000000..eb6c4a14e6 --- /dev/null +++ b/tests/components/hm3301/test.esp32-c3.yaml @@ -0,0 +1,16 @@ +i2c: + - id: i2c_hm3301 + scl: 5 + sda: 4 + +sensor: + - platform: hm3301 + pm_1_0: + name: PM1.0 + pm_2_5: + name: PM2.5 + pm_10_0: + name: PM10.0 + aqi: + name: AQI + calculation_type: CAQI diff --git a/tests/components/hm3301/test.esp32-idf.yaml b/tests/components/hm3301/test.esp32-idf.yaml new file mode 100644 index 0000000000..413e88a265 --- /dev/null +++ b/tests/components/hm3301/test.esp32-idf.yaml @@ -0,0 +1,16 @@ +i2c: + - id: i2c_hm3301 + scl: 16 + sda: 17 + +sensor: + - platform: hm3301 + pm_1_0: + name: PM1.0 + pm_2_5: + name: PM2.5 + pm_10_0: + name: PM10.0 + aqi: + name: AQI + calculation_type: CAQI diff --git a/tests/components/hm3301/test.esp32.yaml b/tests/components/hm3301/test.esp32.yaml new file mode 100644 index 0000000000..413e88a265 --- /dev/null +++ b/tests/components/hm3301/test.esp32.yaml @@ -0,0 +1,16 @@ +i2c: + - id: i2c_hm3301 + scl: 16 + sda: 17 + +sensor: + - platform: hm3301 + pm_1_0: + name: PM1.0 + pm_2_5: + name: PM2.5 + pm_10_0: + name: PM10.0 + aqi: + name: AQI + calculation_type: CAQI diff --git a/tests/components/hm3301/test.esp8266.yaml b/tests/components/hm3301/test.esp8266.yaml new file mode 100644 index 0000000000..eb6c4a14e6 --- /dev/null +++ b/tests/components/hm3301/test.esp8266.yaml @@ -0,0 +1,16 @@ +i2c: + - id: i2c_hm3301 + scl: 5 + sda: 4 + +sensor: + - platform: hm3301 + pm_1_0: + name: PM1.0 + pm_2_5: + name: PM2.5 + pm_10_0: + name: PM10.0 + aqi: + name: AQI + calculation_type: CAQI diff --git a/tests/components/hm3301/test.rp2040.yaml b/tests/components/hm3301/test.rp2040.yaml new file mode 100644 index 0000000000..eb6c4a14e6 --- /dev/null +++ b/tests/components/hm3301/test.rp2040.yaml @@ -0,0 +1,16 @@ +i2c: + - id: i2c_hm3301 + scl: 5 + sda: 4 + +sensor: + - platform: hm3301 + pm_1_0: + name: PM1.0 + pm_2_5: + name: PM2.5 + pm_10_0: + name: PM10.0 + aqi: + name: AQI + calculation_type: CAQI diff --git a/tests/components/hmc5883l/test.esp32-c3-idf.yaml b/tests/components/hmc5883l/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..e65b2e5c5b --- /dev/null +++ b/tests/components/hmc5883l/test.esp32-c3-idf.yaml @@ -0,0 +1,19 @@ +i2c: + - id: i2c_hmc5883l + scl: 5 + sda: 4 + +sensor: + - platform: hmc5883l + address: 0x68 + field_strength_x: + name: HMC5883L Field Strength X + field_strength_y: + name: HMC5883L Field Strength Y + field_strength_z: + name: HMC5883L Field Strength Z + heading: + name: HMC5883L Heading + range: 130uT + oversampling: 8x + update_interval: 15s diff --git a/tests/components/hmc5883l/test.esp32-c3.yaml b/tests/components/hmc5883l/test.esp32-c3.yaml new file mode 100644 index 0000000000..e65b2e5c5b --- /dev/null +++ b/tests/components/hmc5883l/test.esp32-c3.yaml @@ -0,0 +1,19 @@ +i2c: + - id: i2c_hmc5883l + scl: 5 + sda: 4 + +sensor: + - platform: hmc5883l + address: 0x68 + field_strength_x: + name: HMC5883L Field Strength X + field_strength_y: + name: HMC5883L Field Strength Y + field_strength_z: + name: HMC5883L Field Strength Z + heading: + name: HMC5883L Heading + range: 130uT + oversampling: 8x + update_interval: 15s diff --git a/tests/components/hmc5883l/test.esp32-idf.yaml b/tests/components/hmc5883l/test.esp32-idf.yaml new file mode 100644 index 0000000000..db632fc411 --- /dev/null +++ b/tests/components/hmc5883l/test.esp32-idf.yaml @@ -0,0 +1,19 @@ +i2c: + - id: i2c_hmc5883l + scl: 16 + sda: 17 + +sensor: + - platform: hmc5883l + address: 0x68 + field_strength_x: + name: HMC5883L Field Strength X + field_strength_y: + name: HMC5883L Field Strength Y + field_strength_z: + name: HMC5883L Field Strength Z + heading: + name: HMC5883L Heading + range: 130uT + oversampling: 8x + update_interval: 15s diff --git a/tests/components/hmc5883l/test.esp32.yaml b/tests/components/hmc5883l/test.esp32.yaml new file mode 100644 index 0000000000..db632fc411 --- /dev/null +++ b/tests/components/hmc5883l/test.esp32.yaml @@ -0,0 +1,19 @@ +i2c: + - id: i2c_hmc5883l + scl: 16 + sda: 17 + +sensor: + - platform: hmc5883l + address: 0x68 + field_strength_x: + name: HMC5883L Field Strength X + field_strength_y: + name: HMC5883L Field Strength Y + field_strength_z: + name: HMC5883L Field Strength Z + heading: + name: HMC5883L Heading + range: 130uT + oversampling: 8x + update_interval: 15s diff --git a/tests/components/hmc5883l/test.esp8266.yaml b/tests/components/hmc5883l/test.esp8266.yaml new file mode 100644 index 0000000000..e65b2e5c5b --- /dev/null +++ b/tests/components/hmc5883l/test.esp8266.yaml @@ -0,0 +1,19 @@ +i2c: + - id: i2c_hmc5883l + scl: 5 + sda: 4 + +sensor: + - platform: hmc5883l + address: 0x68 + field_strength_x: + name: HMC5883L Field Strength X + field_strength_y: + name: HMC5883L Field Strength Y + field_strength_z: + name: HMC5883L Field Strength Z + heading: + name: HMC5883L Heading + range: 130uT + oversampling: 8x + update_interval: 15s diff --git a/tests/components/hmc5883l/test.rp2040.yaml b/tests/components/hmc5883l/test.rp2040.yaml new file mode 100644 index 0000000000..e65b2e5c5b --- /dev/null +++ b/tests/components/hmc5883l/test.rp2040.yaml @@ -0,0 +1,19 @@ +i2c: + - id: i2c_hmc5883l + scl: 5 + sda: 4 + +sensor: + - platform: hmc5883l + address: 0x68 + field_strength_x: + name: HMC5883L Field Strength X + field_strength_y: + name: HMC5883L Field Strength Y + field_strength_z: + name: HMC5883L Field Strength Z + heading: + name: HMC5883L Heading + range: 130uT + oversampling: 8x + update_interval: 15s diff --git a/tests/components/homeassistant/test.esp32-c3-idf.yaml b/tests/components/homeassistant/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..d2608f077c --- /dev/null +++ b/tests/components/homeassistant/test.esp32-c3-idf.yaml @@ -0,0 +1,39 @@ +wifi: + ssid: MySSID + password: password1 + +api: + +binary_sensor: + - platform: homeassistant + entity_id: binary_sensor.hello_world + id: ha_hello_world_binary + - platform: homeassistant + entity_id: binary_sensor.hello + attribute: world + id: ha_hello_world_binary_attribute + +sensor: + - platform: homeassistant + entity_id: sensor.hello_world + id: ha_hello_world + - platform: homeassistant + entity_id: climate.living_room + attribute: temperature + id: ha_hello_world_temperature + +text_sensor: + - platform: homeassistant + entity_id: sensor.hello_world + id: ha_hello_world_text + - platform: homeassistant + entity_id: sensor.hello_world1 + id: ha_hello_world_text2 + attribute: some_attribute + +time: + - platform: homeassistant + on_time: + - at: "16:00:00" + then: + - logger.log: It's 16:00 diff --git a/tests/components/homeassistant/test.esp32-c3.yaml b/tests/components/homeassistant/test.esp32-c3.yaml new file mode 100644 index 0000000000..d2608f077c --- /dev/null +++ b/tests/components/homeassistant/test.esp32-c3.yaml @@ -0,0 +1,39 @@ +wifi: + ssid: MySSID + password: password1 + +api: + +binary_sensor: + - platform: homeassistant + entity_id: binary_sensor.hello_world + id: ha_hello_world_binary + - platform: homeassistant + entity_id: binary_sensor.hello + attribute: world + id: ha_hello_world_binary_attribute + +sensor: + - platform: homeassistant + entity_id: sensor.hello_world + id: ha_hello_world + - platform: homeassistant + entity_id: climate.living_room + attribute: temperature + id: ha_hello_world_temperature + +text_sensor: + - platform: homeassistant + entity_id: sensor.hello_world + id: ha_hello_world_text + - platform: homeassistant + entity_id: sensor.hello_world1 + id: ha_hello_world_text2 + attribute: some_attribute + +time: + - platform: homeassistant + on_time: + - at: "16:00:00" + then: + - logger.log: It's 16:00 diff --git a/tests/components/homeassistant/test.esp32-idf.yaml b/tests/components/homeassistant/test.esp32-idf.yaml new file mode 100644 index 0000000000..d2608f077c --- /dev/null +++ b/tests/components/homeassistant/test.esp32-idf.yaml @@ -0,0 +1,39 @@ +wifi: + ssid: MySSID + password: password1 + +api: + +binary_sensor: + - platform: homeassistant + entity_id: binary_sensor.hello_world + id: ha_hello_world_binary + - platform: homeassistant + entity_id: binary_sensor.hello + attribute: world + id: ha_hello_world_binary_attribute + +sensor: + - platform: homeassistant + entity_id: sensor.hello_world + id: ha_hello_world + - platform: homeassistant + entity_id: climate.living_room + attribute: temperature + id: ha_hello_world_temperature + +text_sensor: + - platform: homeassistant + entity_id: sensor.hello_world + id: ha_hello_world_text + - platform: homeassistant + entity_id: sensor.hello_world1 + id: ha_hello_world_text2 + attribute: some_attribute + +time: + - platform: homeassistant + on_time: + - at: "16:00:00" + then: + - logger.log: It's 16:00 diff --git a/tests/components/homeassistant/test.esp32.yaml b/tests/components/homeassistant/test.esp32.yaml new file mode 100644 index 0000000000..d2608f077c --- /dev/null +++ b/tests/components/homeassistant/test.esp32.yaml @@ -0,0 +1,39 @@ +wifi: + ssid: MySSID + password: password1 + +api: + +binary_sensor: + - platform: homeassistant + entity_id: binary_sensor.hello_world + id: ha_hello_world_binary + - platform: homeassistant + entity_id: binary_sensor.hello + attribute: world + id: ha_hello_world_binary_attribute + +sensor: + - platform: homeassistant + entity_id: sensor.hello_world + id: ha_hello_world + - platform: homeassistant + entity_id: climate.living_room + attribute: temperature + id: ha_hello_world_temperature + +text_sensor: + - platform: homeassistant + entity_id: sensor.hello_world + id: ha_hello_world_text + - platform: homeassistant + entity_id: sensor.hello_world1 + id: ha_hello_world_text2 + attribute: some_attribute + +time: + - platform: homeassistant + on_time: + - at: "16:00:00" + then: + - logger.log: It's 16:00 diff --git a/tests/components/homeassistant/test.esp8266.yaml b/tests/components/homeassistant/test.esp8266.yaml new file mode 100644 index 0000000000..d2608f077c --- /dev/null +++ b/tests/components/homeassistant/test.esp8266.yaml @@ -0,0 +1,39 @@ +wifi: + ssid: MySSID + password: password1 + +api: + +binary_sensor: + - platform: homeassistant + entity_id: binary_sensor.hello_world + id: ha_hello_world_binary + - platform: homeassistant + entity_id: binary_sensor.hello + attribute: world + id: ha_hello_world_binary_attribute + +sensor: + - platform: homeassistant + entity_id: sensor.hello_world + id: ha_hello_world + - platform: homeassistant + entity_id: climate.living_room + attribute: temperature + id: ha_hello_world_temperature + +text_sensor: + - platform: homeassistant + entity_id: sensor.hello_world + id: ha_hello_world_text + - platform: homeassistant + entity_id: sensor.hello_world1 + id: ha_hello_world_text2 + attribute: some_attribute + +time: + - platform: homeassistant + on_time: + - at: "16:00:00" + then: + - logger.log: It's 16:00 diff --git a/tests/components/homeassistant/test.rp2040.yaml b/tests/components/homeassistant/test.rp2040.yaml new file mode 100644 index 0000000000..d2608f077c --- /dev/null +++ b/tests/components/homeassistant/test.rp2040.yaml @@ -0,0 +1,39 @@ +wifi: + ssid: MySSID + password: password1 + +api: + +binary_sensor: + - platform: homeassistant + entity_id: binary_sensor.hello_world + id: ha_hello_world_binary + - platform: homeassistant + entity_id: binary_sensor.hello + attribute: world + id: ha_hello_world_binary_attribute + +sensor: + - platform: homeassistant + entity_id: sensor.hello_world + id: ha_hello_world + - platform: homeassistant + entity_id: climate.living_room + attribute: temperature + id: ha_hello_world_temperature + +text_sensor: + - platform: homeassistant + entity_id: sensor.hello_world + id: ha_hello_world_text + - platform: homeassistant + entity_id: sensor.hello_world1 + id: ha_hello_world_text2 + attribute: some_attribute + +time: + - platform: homeassistant + on_time: + - at: "16:00:00" + then: + - logger.log: It's 16:00 diff --git a/tests/components/honeywell_hih_i2c/test.esp32-c3-idf.yaml b/tests/components/honeywell_hih_i2c/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..5dae3d5d52 --- /dev/null +++ b/tests/components/honeywell_hih_i2c/test.esp32-c3-idf.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_honeywell_hih + scl: 5 + sda: 4 + +sensor: + - platform: honeywell_hih_i2c + temperature: + name: Temperature + humidity: + name: Humidity + update_interval: 15s diff --git a/tests/components/honeywell_hih_i2c/test.esp32-c3.yaml b/tests/components/honeywell_hih_i2c/test.esp32-c3.yaml new file mode 100644 index 0000000000..5dae3d5d52 --- /dev/null +++ b/tests/components/honeywell_hih_i2c/test.esp32-c3.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_honeywell_hih + scl: 5 + sda: 4 + +sensor: + - platform: honeywell_hih_i2c + temperature: + name: Temperature + humidity: + name: Humidity + update_interval: 15s diff --git a/tests/components/honeywell_hih_i2c/test.esp32-idf.yaml b/tests/components/honeywell_hih_i2c/test.esp32-idf.yaml new file mode 100644 index 0000000000..0119aec3f3 --- /dev/null +++ b/tests/components/honeywell_hih_i2c/test.esp32-idf.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_honeywell_hih + scl: 16 + sda: 17 + +sensor: + - platform: honeywell_hih_i2c + temperature: + name: Temperature + humidity: + name: Humidity + update_interval: 15s diff --git a/tests/components/honeywell_hih_i2c/test.esp32.yaml b/tests/components/honeywell_hih_i2c/test.esp32.yaml new file mode 100644 index 0000000000..0119aec3f3 --- /dev/null +++ b/tests/components/honeywell_hih_i2c/test.esp32.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_honeywell_hih + scl: 16 + sda: 17 + +sensor: + - platform: honeywell_hih_i2c + temperature: + name: Temperature + humidity: + name: Humidity + update_interval: 15s diff --git a/tests/components/honeywell_hih_i2c/test.esp8266.yaml b/tests/components/honeywell_hih_i2c/test.esp8266.yaml new file mode 100644 index 0000000000..5dae3d5d52 --- /dev/null +++ b/tests/components/honeywell_hih_i2c/test.esp8266.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_honeywell_hih + scl: 5 + sda: 4 + +sensor: + - platform: honeywell_hih_i2c + temperature: + name: Temperature + humidity: + name: Humidity + update_interval: 15s diff --git a/tests/components/honeywell_hih_i2c/test.rp2040.yaml b/tests/components/honeywell_hih_i2c/test.rp2040.yaml new file mode 100644 index 0000000000..5dae3d5d52 --- /dev/null +++ b/tests/components/honeywell_hih_i2c/test.rp2040.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_honeywell_hih + scl: 5 + sda: 4 + +sensor: + - platform: honeywell_hih_i2c + temperature: + name: Temperature + humidity: + name: Humidity + update_interval: 15s diff --git a/tests/components/honeywellabp/test.esp32-c3-idf.yaml b/tests/components/honeywellabp/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..a53e3296dd --- /dev/null +++ b/tests/components/honeywellabp/test.esp32-c3-idf.yaml @@ -0,0 +1,15 @@ +spi: + - id: spi_honeywellabp + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +sensor: + - platform: honeywellabp + cs_pin: 8 + pressure: + name: Honeywell pressure + min_pressure: 0 + max_pressure: 15 + temperature: + name: Honeywell temperature diff --git a/tests/components/honeywellabp/test.esp32-c3.yaml b/tests/components/honeywellabp/test.esp32-c3.yaml new file mode 100644 index 0000000000..a53e3296dd --- /dev/null +++ b/tests/components/honeywellabp/test.esp32-c3.yaml @@ -0,0 +1,15 @@ +spi: + - id: spi_honeywellabp + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +sensor: + - platform: honeywellabp + cs_pin: 8 + pressure: + name: Honeywell pressure + min_pressure: 0 + max_pressure: 15 + temperature: + name: Honeywell temperature diff --git a/tests/components/honeywellabp/test.esp32-idf.yaml b/tests/components/honeywellabp/test.esp32-idf.yaml new file mode 100644 index 0000000000..6bf9fa0f4d --- /dev/null +++ b/tests/components/honeywellabp/test.esp32-idf.yaml @@ -0,0 +1,15 @@ +spi: + - id: spi_bme280 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +sensor: + - platform: honeywellabp + cs_pin: 12 + pressure: + name: Honeywell pressure + min_pressure: 0 + max_pressure: 15 + temperature: + name: Honeywell temperature diff --git a/tests/components/honeywellabp/test.esp32.yaml b/tests/components/honeywellabp/test.esp32.yaml new file mode 100644 index 0000000000..6bf9fa0f4d --- /dev/null +++ b/tests/components/honeywellabp/test.esp32.yaml @@ -0,0 +1,15 @@ +spi: + - id: spi_bme280 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +sensor: + - platform: honeywellabp + cs_pin: 12 + pressure: + name: Honeywell pressure + min_pressure: 0 + max_pressure: 15 + temperature: + name: Honeywell temperature diff --git a/tests/components/honeywellabp/test.esp8266.yaml b/tests/components/honeywellabp/test.esp8266.yaml new file mode 100644 index 0000000000..31988c035e --- /dev/null +++ b/tests/components/honeywellabp/test.esp8266.yaml @@ -0,0 +1,15 @@ +spi: + - id: spi_bme280 + clk_pin: 14 + mosi_pin: 13 + miso_pin: 12 + +sensor: + - platform: honeywellabp + cs_pin: 15 + pressure: + name: Honeywell pressure + min_pressure: 0 + max_pressure: 15 + temperature: + name: Honeywell temperature diff --git a/tests/components/honeywellabp/test.rp2040.yaml b/tests/components/honeywellabp/test.rp2040.yaml new file mode 100644 index 0000000000..2e0c471fa0 --- /dev/null +++ b/tests/components/honeywellabp/test.rp2040.yaml @@ -0,0 +1,15 @@ +spi: + - id: spi_bme280 + clk_pin: 2 + mosi_pin: 3 + miso_pin: 4 + +sensor: + - platform: honeywellabp + cs_pin: 6 + pressure: + name: Honeywell pressure + min_pressure: 0 + max_pressure: 15 + temperature: + name: Honeywell temperature diff --git a/tests/components/honeywellabp2_i2c/test.esp32-c3-idf.yaml b/tests/components/honeywellabp2_i2c/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..b47411c238 --- /dev/null +++ b/tests/components/honeywellabp2_i2c/test.esp32-c3-idf.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_honeywellabp2 + scl: 5 + sda: 4 + +sensor: + - platform: honeywellabp2_i2c + address: 0x28 + pressure: + name: Honeywell2 pressure + min_pressure: 0 + max_pressure: 16000 + transfer_function: A + temperature: + name: Honeywell temperature diff --git a/tests/components/honeywellabp2_i2c/test.esp32-c3.yaml b/tests/components/honeywellabp2_i2c/test.esp32-c3.yaml new file mode 100644 index 0000000000..b47411c238 --- /dev/null +++ b/tests/components/honeywellabp2_i2c/test.esp32-c3.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_honeywellabp2 + scl: 5 + sda: 4 + +sensor: + - platform: honeywellabp2_i2c + address: 0x28 + pressure: + name: Honeywell2 pressure + min_pressure: 0 + max_pressure: 16000 + transfer_function: A + temperature: + name: Honeywell temperature diff --git a/tests/components/honeywellabp2_i2c/test.esp32-idf.yaml b/tests/components/honeywellabp2_i2c/test.esp32-idf.yaml new file mode 100644 index 0000000000..0f0d61ca06 --- /dev/null +++ b/tests/components/honeywellabp2_i2c/test.esp32-idf.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_honeywellabp2 + scl: 16 + sda: 17 + +sensor: + - platform: honeywellabp2_i2c + address: 0x28 + pressure: + name: Honeywell2 pressure + min_pressure: 0 + max_pressure: 16000 + transfer_function: A + temperature: + name: Honeywell temperature diff --git a/tests/components/honeywellabp2_i2c/test.esp32.yaml b/tests/components/honeywellabp2_i2c/test.esp32.yaml new file mode 100644 index 0000000000..0f0d61ca06 --- /dev/null +++ b/tests/components/honeywellabp2_i2c/test.esp32.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_honeywellabp2 + scl: 16 + sda: 17 + +sensor: + - platform: honeywellabp2_i2c + address: 0x28 + pressure: + name: Honeywell2 pressure + min_pressure: 0 + max_pressure: 16000 + transfer_function: A + temperature: + name: Honeywell temperature diff --git a/tests/components/honeywellabp2_i2c/test.esp8266.yaml b/tests/components/honeywellabp2_i2c/test.esp8266.yaml new file mode 100644 index 0000000000..b47411c238 --- /dev/null +++ b/tests/components/honeywellabp2_i2c/test.esp8266.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_honeywellabp2 + scl: 5 + sda: 4 + +sensor: + - platform: honeywellabp2_i2c + address: 0x28 + pressure: + name: Honeywell2 pressure + min_pressure: 0 + max_pressure: 16000 + transfer_function: A + temperature: + name: Honeywell temperature diff --git a/tests/components/honeywellabp2_i2c/test.rp2040.yaml b/tests/components/honeywellabp2_i2c/test.rp2040.yaml new file mode 100644 index 0000000000..b47411c238 --- /dev/null +++ b/tests/components/honeywellabp2_i2c/test.rp2040.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_honeywellabp2 + scl: 5 + sda: 4 + +sensor: + - platform: honeywellabp2_i2c + address: 0x28 + pressure: + name: Honeywell2 pressure + min_pressure: 0 + max_pressure: 16000 + transfer_function: A + temperature: + name: Honeywell temperature diff --git a/tests/components/hrxl_maxsonar_wr/test.esp32-c3-idf.yaml b/tests/components/hrxl_maxsonar_wr/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..729cb96120 --- /dev/null +++ b/tests/components/hrxl_maxsonar_wr/test.esp32-c3-idf.yaml @@ -0,0 +1,10 @@ +uart: + - id: uart_hrxl_maxsonar_wr + tx_pin: 4 + rx_pin: 5 + baud_rate: 115200 + +sensor: + - platform: hrxl_maxsonar_wr + id: hrxl_maxsonar_wr_sensor + name: Rainwater Tank Level diff --git a/tests/components/hrxl_maxsonar_wr/test.esp32-c3.yaml b/tests/components/hrxl_maxsonar_wr/test.esp32-c3.yaml new file mode 100644 index 0000000000..729cb96120 --- /dev/null +++ b/tests/components/hrxl_maxsonar_wr/test.esp32-c3.yaml @@ -0,0 +1,10 @@ +uart: + - id: uart_hrxl_maxsonar_wr + tx_pin: 4 + rx_pin: 5 + baud_rate: 115200 + +sensor: + - platform: hrxl_maxsonar_wr + id: hrxl_maxsonar_wr_sensor + name: Rainwater Tank Level diff --git a/tests/components/hrxl_maxsonar_wr/test.esp32-idf.yaml b/tests/components/hrxl_maxsonar_wr/test.esp32-idf.yaml new file mode 100644 index 0000000000..da283cc072 --- /dev/null +++ b/tests/components/hrxl_maxsonar_wr/test.esp32-idf.yaml @@ -0,0 +1,10 @@ +uart: + - id: uart_hrxl_maxsonar_wr + tx_pin: 17 + rx_pin: 16 + baud_rate: 115200 + +sensor: + - platform: hrxl_maxsonar_wr + id: hrxl_maxsonar_wr_sensor + name: Rainwater Tank Level diff --git a/tests/components/hrxl_maxsonar_wr/test.esp32.yaml b/tests/components/hrxl_maxsonar_wr/test.esp32.yaml new file mode 100644 index 0000000000..da283cc072 --- /dev/null +++ b/tests/components/hrxl_maxsonar_wr/test.esp32.yaml @@ -0,0 +1,10 @@ +uart: + - id: uart_hrxl_maxsonar_wr + tx_pin: 17 + rx_pin: 16 + baud_rate: 115200 + +sensor: + - platform: hrxl_maxsonar_wr + id: hrxl_maxsonar_wr_sensor + name: Rainwater Tank Level diff --git a/tests/components/hrxl_maxsonar_wr/test.esp8266.yaml b/tests/components/hrxl_maxsonar_wr/test.esp8266.yaml new file mode 100644 index 0000000000..729cb96120 --- /dev/null +++ b/tests/components/hrxl_maxsonar_wr/test.esp8266.yaml @@ -0,0 +1,10 @@ +uart: + - id: uart_hrxl_maxsonar_wr + tx_pin: 4 + rx_pin: 5 + baud_rate: 115200 + +sensor: + - platform: hrxl_maxsonar_wr + id: hrxl_maxsonar_wr_sensor + name: Rainwater Tank Level diff --git a/tests/components/hrxl_maxsonar_wr/test.rp2040.yaml b/tests/components/hrxl_maxsonar_wr/test.rp2040.yaml new file mode 100644 index 0000000000..729cb96120 --- /dev/null +++ b/tests/components/hrxl_maxsonar_wr/test.rp2040.yaml @@ -0,0 +1,10 @@ +uart: + - id: uart_hrxl_maxsonar_wr + tx_pin: 4 + rx_pin: 5 + baud_rate: 115200 + +sensor: + - platform: hrxl_maxsonar_wr + id: hrxl_maxsonar_wr_sensor + name: Rainwater Tank Level diff --git a/tests/components/hte501/test.esp32-c3-idf.yaml b/tests/components/hte501/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..e14b589dbd --- /dev/null +++ b/tests/components/hte501/test.esp32-c3-idf.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_hte501 + scl: 5 + sda: 4 + +sensor: + - platform: hte501 + address: 0x40 + temperature: + name: Temperature + humidity: + name: Humidity diff --git a/tests/components/hte501/test.esp32-c3.yaml b/tests/components/hte501/test.esp32-c3.yaml new file mode 100644 index 0000000000..e14b589dbd --- /dev/null +++ b/tests/components/hte501/test.esp32-c3.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_hte501 + scl: 5 + sda: 4 + +sensor: + - platform: hte501 + address: 0x40 + temperature: + name: Temperature + humidity: + name: Humidity diff --git a/tests/components/hte501/test.esp32-idf.yaml b/tests/components/hte501/test.esp32-idf.yaml new file mode 100644 index 0000000000..83e4d26603 --- /dev/null +++ b/tests/components/hte501/test.esp32-idf.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_hte501 + scl: 16 + sda: 17 + +sensor: + - platform: hte501 + address: 0x40 + temperature: + name: Temperature + humidity: + name: Humidity diff --git a/tests/components/hte501/test.esp32.yaml b/tests/components/hte501/test.esp32.yaml new file mode 100644 index 0000000000..83e4d26603 --- /dev/null +++ b/tests/components/hte501/test.esp32.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_hte501 + scl: 16 + sda: 17 + +sensor: + - platform: hte501 + address: 0x40 + temperature: + name: Temperature + humidity: + name: Humidity diff --git a/tests/components/hte501/test.esp8266.yaml b/tests/components/hte501/test.esp8266.yaml new file mode 100644 index 0000000000..e14b589dbd --- /dev/null +++ b/tests/components/hte501/test.esp8266.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_hte501 + scl: 5 + sda: 4 + +sensor: + - platform: hte501 + address: 0x40 + temperature: + name: Temperature + humidity: + name: Humidity diff --git a/tests/components/hte501/test.rp2040.yaml b/tests/components/hte501/test.rp2040.yaml new file mode 100644 index 0000000000..e14b589dbd --- /dev/null +++ b/tests/components/hte501/test.rp2040.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_hte501 + scl: 5 + sda: 4 + +sensor: + - platform: hte501 + address: 0x40 + temperature: + name: Temperature + humidity: + name: Humidity diff --git a/tests/components/http_request/test.esp32-c3.yaml b/tests/components/http_request/test.esp32-c3.yaml new file mode 100644 index 0000000000..19fc6af2c4 --- /dev/null +++ b/tests/components/http_request/test.esp32-c3.yaml @@ -0,0 +1,7 @@ +wifi: + ssid: MySSID + password: password1 + +http_request: + useragent: esphome/tagreader + timeout: 10s diff --git a/tests/components/http_request/test.esp32.yaml b/tests/components/http_request/test.esp32.yaml new file mode 100644 index 0000000000..19fc6af2c4 --- /dev/null +++ b/tests/components/http_request/test.esp32.yaml @@ -0,0 +1,7 @@ +wifi: + ssid: MySSID + password: password1 + +http_request: + useragent: esphome/tagreader + timeout: 10s diff --git a/tests/components/http_request/test.esp8266.yaml b/tests/components/http_request/test.esp8266.yaml new file mode 100644 index 0000000000..19fc6af2c4 --- /dev/null +++ b/tests/components/http_request/test.esp8266.yaml @@ -0,0 +1,7 @@ +wifi: + ssid: MySSID + password: password1 + +http_request: + useragent: esphome/tagreader + timeout: 10s diff --git a/tests/components/htu21d/test.esp32-c3-idf.yaml b/tests/components/htu21d/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..d9fbb09550 --- /dev/null +++ b/tests/components/htu21d/test.esp32-c3-idf.yaml @@ -0,0 +1,14 @@ +i2c: + - id: i2c_htu21d + scl: 5 + sda: 4 + +sensor: + - platform: htu21d + temperature: + name: Temperature + humidity: + name: Humidity + heater: + name: Heater + update_interval: 15s diff --git a/tests/components/htu21d/test.esp32-c3.yaml b/tests/components/htu21d/test.esp32-c3.yaml new file mode 100644 index 0000000000..d9fbb09550 --- /dev/null +++ b/tests/components/htu21d/test.esp32-c3.yaml @@ -0,0 +1,14 @@ +i2c: + - id: i2c_htu21d + scl: 5 + sda: 4 + +sensor: + - platform: htu21d + temperature: + name: Temperature + humidity: + name: Humidity + heater: + name: Heater + update_interval: 15s diff --git a/tests/components/htu21d/test.esp32-idf.yaml b/tests/components/htu21d/test.esp32-idf.yaml new file mode 100644 index 0000000000..48f03eb368 --- /dev/null +++ b/tests/components/htu21d/test.esp32-idf.yaml @@ -0,0 +1,14 @@ +i2c: + - id: i2c_htu21d + scl: 16 + sda: 17 + +sensor: + - platform: htu21d + temperature: + name: Temperature + humidity: + name: Humidity + heater: + name: Heater + update_interval: 15s diff --git a/tests/components/htu21d/test.esp32.yaml b/tests/components/htu21d/test.esp32.yaml new file mode 100644 index 0000000000..48f03eb368 --- /dev/null +++ b/tests/components/htu21d/test.esp32.yaml @@ -0,0 +1,14 @@ +i2c: + - id: i2c_htu21d + scl: 16 + sda: 17 + +sensor: + - platform: htu21d + temperature: + name: Temperature + humidity: + name: Humidity + heater: + name: Heater + update_interval: 15s diff --git a/tests/components/htu21d/test.esp8266.yaml b/tests/components/htu21d/test.esp8266.yaml new file mode 100644 index 0000000000..d9fbb09550 --- /dev/null +++ b/tests/components/htu21d/test.esp8266.yaml @@ -0,0 +1,14 @@ +i2c: + - id: i2c_htu21d + scl: 5 + sda: 4 + +sensor: + - platform: htu21d + temperature: + name: Temperature + humidity: + name: Humidity + heater: + name: Heater + update_interval: 15s diff --git a/tests/components/htu21d/test.rp2040.yaml b/tests/components/htu21d/test.rp2040.yaml new file mode 100644 index 0000000000..d9fbb09550 --- /dev/null +++ b/tests/components/htu21d/test.rp2040.yaml @@ -0,0 +1,14 @@ +i2c: + - id: i2c_htu21d + scl: 5 + sda: 4 + +sensor: + - platform: htu21d + temperature: + name: Temperature + humidity: + name: Humidity + heater: + name: Heater + update_interval: 15s diff --git a/tests/components/hx711/test.esp32-c3-idf.yaml b/tests/components/hx711/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..9850417440 --- /dev/null +++ b/tests/components/hx711/test.esp32-c3-idf.yaml @@ -0,0 +1,7 @@ +sensor: + - platform: hx711 + name: HX711 Value + dout_pin: 4 + clk_pin: 5 + gain: 128 + update_interval: 15s diff --git a/tests/components/hx711/test.esp32-c3.yaml b/tests/components/hx711/test.esp32-c3.yaml new file mode 100644 index 0000000000..9850417440 --- /dev/null +++ b/tests/components/hx711/test.esp32-c3.yaml @@ -0,0 +1,7 @@ +sensor: + - platform: hx711 + name: HX711 Value + dout_pin: 4 + clk_pin: 5 + gain: 128 + update_interval: 15s diff --git a/tests/components/hx711/test.esp32-idf.yaml b/tests/components/hx711/test.esp32-idf.yaml new file mode 100644 index 0000000000..554b184422 --- /dev/null +++ b/tests/components/hx711/test.esp32-idf.yaml @@ -0,0 +1,7 @@ +sensor: + - platform: hx711 + name: HX711 Value + dout_pin: 14 + clk_pin: 15 + gain: 128 + update_interval: 15s diff --git a/tests/components/hx711/test.esp32.yaml b/tests/components/hx711/test.esp32.yaml new file mode 100644 index 0000000000..554b184422 --- /dev/null +++ b/tests/components/hx711/test.esp32.yaml @@ -0,0 +1,7 @@ +sensor: + - platform: hx711 + name: HX711 Value + dout_pin: 14 + clk_pin: 15 + gain: 128 + update_interval: 15s diff --git a/tests/components/hx711/test.esp8266.yaml b/tests/components/hx711/test.esp8266.yaml new file mode 100644 index 0000000000..9850417440 --- /dev/null +++ b/tests/components/hx711/test.esp8266.yaml @@ -0,0 +1,7 @@ +sensor: + - platform: hx711 + name: HX711 Value + dout_pin: 4 + clk_pin: 5 + gain: 128 + update_interval: 15s diff --git a/tests/components/hx711/test.rp2040.yaml b/tests/components/hx711/test.rp2040.yaml new file mode 100644 index 0000000000..9850417440 --- /dev/null +++ b/tests/components/hx711/test.rp2040.yaml @@ -0,0 +1,7 @@ +sensor: + - platform: hx711 + name: HX711 Value + dout_pin: 4 + clk_pin: 5 + gain: 128 + update_interval: 15s diff --git a/tests/components/hydreon_rgxx/test.esp32-c3-idf.yaml b/tests/components/hydreon_rgxx/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..f62f4942db --- /dev/null +++ b/tests/components/hydreon_rgxx/test.esp32-c3-idf.yaml @@ -0,0 +1,37 @@ +uart: + - id: uart_hydreon_rgxx + tx_pin: 4 + rx_pin: 5 + baud_rate: 115200 + +binary_sensor: + - platform: hydreon_rgxx + hydreon_rgxx_id: hydreon_rg9 + too_cold: + name: rg9_toocold + em_sat: + name: rg9_emsat + lens_bad: + name: rg9_lens_bad + +sensor: + - platform: hydreon_rgxx + id: hydreon_rg9 + model: RG 9 + moisture: + name: hydreon_rain + id: hydreon_rain + temperature: + name: hydreon_temperature + disable_led: true + - platform: hydreon_rgxx + id: hydreon_rg15 + model: RG_15 + acc: + name: hydreon_acc + event_acc: + name: hydreon_event_acc + total_acc: + name: hydreon_total_acc + r_int: + name: hydreon_r_int diff --git a/tests/components/hydreon_rgxx/test.esp32-c3.yaml b/tests/components/hydreon_rgxx/test.esp32-c3.yaml new file mode 100644 index 0000000000..f62f4942db --- /dev/null +++ b/tests/components/hydreon_rgxx/test.esp32-c3.yaml @@ -0,0 +1,37 @@ +uart: + - id: uart_hydreon_rgxx + tx_pin: 4 + rx_pin: 5 + baud_rate: 115200 + +binary_sensor: + - platform: hydreon_rgxx + hydreon_rgxx_id: hydreon_rg9 + too_cold: + name: rg9_toocold + em_sat: + name: rg9_emsat + lens_bad: + name: rg9_lens_bad + +sensor: + - platform: hydreon_rgxx + id: hydreon_rg9 + model: RG 9 + moisture: + name: hydreon_rain + id: hydreon_rain + temperature: + name: hydreon_temperature + disable_led: true + - platform: hydreon_rgxx + id: hydreon_rg15 + model: RG_15 + acc: + name: hydreon_acc + event_acc: + name: hydreon_event_acc + total_acc: + name: hydreon_total_acc + r_int: + name: hydreon_r_int diff --git a/tests/components/hydreon_rgxx/test.esp32-idf.yaml b/tests/components/hydreon_rgxx/test.esp32-idf.yaml new file mode 100644 index 0000000000..b6f9486d86 --- /dev/null +++ b/tests/components/hydreon_rgxx/test.esp32-idf.yaml @@ -0,0 +1,37 @@ +uart: + - id: uart_hydreon_rgxx + tx_pin: 17 + rx_pin: 16 + baud_rate: 115200 + +binary_sensor: + - platform: hydreon_rgxx + hydreon_rgxx_id: hydreon_rg9 + too_cold: + name: rg9_toocold + em_sat: + name: rg9_emsat + lens_bad: + name: rg9_lens_bad + +sensor: + - platform: hydreon_rgxx + id: hydreon_rg9 + model: RG 9 + moisture: + name: hydreon_rain + id: hydreon_rain + temperature: + name: hydreon_temperature + disable_led: true + - platform: hydreon_rgxx + id: hydreon_rg15 + model: RG_15 + acc: + name: hydreon_acc + event_acc: + name: hydreon_event_acc + total_acc: + name: hydreon_total_acc + r_int: + name: hydreon_r_int diff --git a/tests/components/hydreon_rgxx/test.esp32.yaml b/tests/components/hydreon_rgxx/test.esp32.yaml new file mode 100644 index 0000000000..b6f9486d86 --- /dev/null +++ b/tests/components/hydreon_rgxx/test.esp32.yaml @@ -0,0 +1,37 @@ +uart: + - id: uart_hydreon_rgxx + tx_pin: 17 + rx_pin: 16 + baud_rate: 115200 + +binary_sensor: + - platform: hydreon_rgxx + hydreon_rgxx_id: hydreon_rg9 + too_cold: + name: rg9_toocold + em_sat: + name: rg9_emsat + lens_bad: + name: rg9_lens_bad + +sensor: + - platform: hydreon_rgxx + id: hydreon_rg9 + model: RG 9 + moisture: + name: hydreon_rain + id: hydreon_rain + temperature: + name: hydreon_temperature + disable_led: true + - platform: hydreon_rgxx + id: hydreon_rg15 + model: RG_15 + acc: + name: hydreon_acc + event_acc: + name: hydreon_event_acc + total_acc: + name: hydreon_total_acc + r_int: + name: hydreon_r_int diff --git a/tests/components/hydreon_rgxx/test.esp8266.yaml b/tests/components/hydreon_rgxx/test.esp8266.yaml new file mode 100644 index 0000000000..f62f4942db --- /dev/null +++ b/tests/components/hydreon_rgxx/test.esp8266.yaml @@ -0,0 +1,37 @@ +uart: + - id: uart_hydreon_rgxx + tx_pin: 4 + rx_pin: 5 + baud_rate: 115200 + +binary_sensor: + - platform: hydreon_rgxx + hydreon_rgxx_id: hydreon_rg9 + too_cold: + name: rg9_toocold + em_sat: + name: rg9_emsat + lens_bad: + name: rg9_lens_bad + +sensor: + - platform: hydreon_rgxx + id: hydreon_rg9 + model: RG 9 + moisture: + name: hydreon_rain + id: hydreon_rain + temperature: + name: hydreon_temperature + disable_led: true + - platform: hydreon_rgxx + id: hydreon_rg15 + model: RG_15 + acc: + name: hydreon_acc + event_acc: + name: hydreon_event_acc + total_acc: + name: hydreon_total_acc + r_int: + name: hydreon_r_int diff --git a/tests/components/hydreon_rgxx/test.rp2040.yaml b/tests/components/hydreon_rgxx/test.rp2040.yaml new file mode 100644 index 0000000000..f62f4942db --- /dev/null +++ b/tests/components/hydreon_rgxx/test.rp2040.yaml @@ -0,0 +1,37 @@ +uart: + - id: uart_hydreon_rgxx + tx_pin: 4 + rx_pin: 5 + baud_rate: 115200 + +binary_sensor: + - platform: hydreon_rgxx + hydreon_rgxx_id: hydreon_rg9 + too_cold: + name: rg9_toocold + em_sat: + name: rg9_emsat + lens_bad: + name: rg9_lens_bad + +sensor: + - platform: hydreon_rgxx + id: hydreon_rg9 + model: RG 9 + moisture: + name: hydreon_rain + id: hydreon_rain + temperature: + name: hydreon_temperature + disable_led: true + - platform: hydreon_rgxx + id: hydreon_rg15 + model: RG_15 + acc: + name: hydreon_acc + event_acc: + name: hydreon_event_acc + total_acc: + name: hydreon_total_acc + r_int: + name: hydreon_r_int diff --git a/tests/components/hyt271/test.esp32-c3-idf.yaml b/tests/components/hyt271/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..c44f0a1f5d --- /dev/null +++ b/tests/components/hyt271/test.esp32-c3-idf.yaml @@ -0,0 +1,11 @@ +i2c: + - id: i2c_hyt271 + scl: 5 + sda: 4 + +sensor: + - platform: hyt271 + temperature: + name: Temperature + humidity: + name: Humidity diff --git a/tests/components/hyt271/test.esp32-c3.yaml b/tests/components/hyt271/test.esp32-c3.yaml new file mode 100644 index 0000000000..c44f0a1f5d --- /dev/null +++ b/tests/components/hyt271/test.esp32-c3.yaml @@ -0,0 +1,11 @@ +i2c: + - id: i2c_hyt271 + scl: 5 + sda: 4 + +sensor: + - platform: hyt271 + temperature: + name: Temperature + humidity: + name: Humidity diff --git a/tests/components/hyt271/test.esp32-idf.yaml b/tests/components/hyt271/test.esp32-idf.yaml new file mode 100644 index 0000000000..297611a89b --- /dev/null +++ b/tests/components/hyt271/test.esp32-idf.yaml @@ -0,0 +1,11 @@ +i2c: + - id: i2c_hyt271 + scl: 16 + sda: 17 + +sensor: + - platform: hyt271 + temperature: + name: Temperature + humidity: + name: Humidity diff --git a/tests/components/hyt271/test.esp32.yaml b/tests/components/hyt271/test.esp32.yaml new file mode 100644 index 0000000000..297611a89b --- /dev/null +++ b/tests/components/hyt271/test.esp32.yaml @@ -0,0 +1,11 @@ +i2c: + - id: i2c_hyt271 + scl: 16 + sda: 17 + +sensor: + - platform: hyt271 + temperature: + name: Temperature + humidity: + name: Humidity diff --git a/tests/components/hyt271/test.esp8266.yaml b/tests/components/hyt271/test.esp8266.yaml new file mode 100644 index 0000000000..c44f0a1f5d --- /dev/null +++ b/tests/components/hyt271/test.esp8266.yaml @@ -0,0 +1,11 @@ +i2c: + - id: i2c_hyt271 + scl: 5 + sda: 4 + +sensor: + - platform: hyt271 + temperature: + name: Temperature + humidity: + name: Humidity diff --git a/tests/components/hyt271/test.rp2040.yaml b/tests/components/hyt271/test.rp2040.yaml new file mode 100644 index 0000000000..c44f0a1f5d --- /dev/null +++ b/tests/components/hyt271/test.rp2040.yaml @@ -0,0 +1,11 @@ +i2c: + - id: i2c_hyt271 + scl: 5 + sda: 4 + +sensor: + - platform: hyt271 + temperature: + name: Temperature + humidity: + name: Humidity From 6d480c5f058323933bc1f24de891928f86b36e95 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 11 Apr 2024 10:09:25 +1200 Subject: [PATCH 1223/2101] ads1115: remove auto-load and split sensor into platform folder (#5981) --- esphome/components/ads1115/__init__.py | 3 +- esphome/components/ads1115/ads1115.cpp | 31 +++++----------- esphome/components/ads1115/ads1115.h | 31 ++-------------- .../ads1115/{sensor.py => sensor/__init__.py} | 21 +++-------- .../ads1115/sensor/ads1115_sensor.cpp | 30 ++++++++++++++++ .../ads1115/sensor/ads1115_sensor.h | 35 +++++++++++++++++++ 6 files changed, 82 insertions(+), 69 deletions(-) rename esphome/components/ads1115/{sensor.py => sensor/__init__.py} (82%) create mode 100644 esphome/components/ads1115/sensor/ads1115_sensor.cpp create mode 100644 esphome/components/ads1115/sensor/ads1115_sensor.h diff --git a/esphome/components/ads1115/__init__.py b/esphome/components/ads1115/__init__.py index e8861a2f67..a463d8390d 100644 --- a/esphome/components/ads1115/__init__.py +++ b/esphome/components/ads1115/__init__.py @@ -4,13 +4,14 @@ from esphome.components import i2c from esphome.const import CONF_ID DEPENDENCIES = ["i2c"] -AUTO_LOAD = ["sensor", "voltage_sampler"] MULTI_CONF = True ads1115_ns = cg.esphome_ns.namespace("ads1115") ADS1115Component = ads1115_ns.class_("ADS1115Component", cg.Component, i2c.I2CDevice) CONF_CONTINUOUS_MODE = "continuous_mode" +CONF_ADS1115_ID = "ads1115_id" + CONFIG_SCHEMA = ( cv.Schema( { diff --git a/esphome/components/ads1115/ads1115.cpp b/esphome/components/ads1115/ads1115.cpp index c3f3c00c63..218edc4c81 100644 --- a/esphome/components/ads1115/ads1115.cpp +++ b/esphome/components/ads1115/ads1115.cpp @@ -1,6 +1,6 @@ #include "ads1115.h" -#include "esphome/core/log.h" #include "esphome/core/hal.h" +#include "esphome/core/log.h" namespace esphome { namespace ads1115 { @@ -75,25 +75,19 @@ void ADS1115Component::dump_config() { if (this->is_failed()) { ESP_LOGE(TAG, "Communication with ADS1115 failed!"); } - - for (auto *sensor : this->sensors_) { - LOG_SENSOR(" ", "Sensor", sensor); - ESP_LOGCONFIG(TAG, " Multiplexer: %u", sensor->get_multiplexer()); - ESP_LOGCONFIG(TAG, " Gain: %u", sensor->get_gain()); - ESP_LOGCONFIG(TAG, " Resolution: %u", sensor->get_resolution()); - } } -float ADS1115Component::request_measurement(ADS1115Sensor *sensor) { +float ADS1115Component::request_measurement(ADS1115Multiplexer multiplexer, ADS1115Gain gain, + ADS1115Resolution resolution) { uint16_t config = this->prev_config_; // Multiplexer // 0bxBBBxxxxxxxxxxxx config &= 0b1000111111111111; - config |= (sensor->get_multiplexer() & 0b111) << 12; + config |= (multiplexer & 0b111) << 12; // Gain // 0bxxxxBBBxxxxxxxxx config &= 0b1111000111111111; - config |= (sensor->get_gain() & 0b111) << 9; + config |= (gain & 0b111) << 9; if (!this->continuous_mode_) { // Start conversion @@ -132,7 +126,7 @@ float ADS1115Component::request_measurement(ADS1115Sensor *sensor) { return NAN; } - if (sensor->get_resolution() == ADS1015_12_BITS) { + if (resolution == ADS1015_12_BITS) { bool negative = (raw_conversion >> 15) == 1; // shift raw_conversion as it's only 12-bits, left justified @@ -151,8 +145,8 @@ float ADS1115Component::request_measurement(ADS1115Sensor *sensor) { auto signed_conversion = static_cast(raw_conversion); float millivolts; - float divider = (sensor->get_resolution() == ADS1115_16_BITS) ? 32768.0f : 2048.0f; - switch (sensor->get_gain()) { + float divider = (resolution == ADS1115_16_BITS) ? 32768.0f : 2048.0f; + switch (gain) { case ADS1115_GAIN_6P144: millivolts = (signed_conversion * 6144) / divider; break; @@ -179,14 +173,5 @@ float ADS1115Component::request_measurement(ADS1115Sensor *sensor) { return millivolts / 1e3f; } -float ADS1115Sensor::sample() { return this->parent_->request_measurement(this); } -void ADS1115Sensor::update() { - float v = this->parent_->request_measurement(this); - if (!std::isnan(v)) { - ESP_LOGD(TAG, "'%s': Got Voltage=%fV", this->get_name().c_str(), v); - this->publish_state(v); - } -} - } // namespace ads1115 } // namespace esphome diff --git a/esphome/components/ads1115/ads1115.h b/esphome/components/ads1115/ads1115.h index 0b8bfb339b..509333d2c8 100644 --- a/esphome/components/ads1115/ads1115.h +++ b/esphome/components/ads1115/ads1115.h @@ -1,9 +1,7 @@ #pragma once -#include "esphome/core/component.h" -#include "esphome/components/sensor/sensor.h" #include "esphome/components/i2c/i2c.h" -#include "esphome/components/voltage_sampler/voltage_sampler.h" +#include "esphome/core/component.h" #include @@ -35,12 +33,8 @@ enum ADS1115Resolution { ADS1015_12_BITS = 12, }; -class ADS1115Sensor; - class ADS1115Component : public Component, public i2c::I2CDevice { public: - void register_sensor(ADS1115Sensor *obj) { this->sensors_.push_back(obj); } - /// Set up the internal sensor array. void setup() override; void dump_config() override; /// HARDWARE_LATE setup priority @@ -48,33 +42,12 @@ class ADS1115Component : public Component, public i2c::I2CDevice { void set_continuous_mode(bool continuous_mode) { continuous_mode_ = continuous_mode; } /// Helper method to request a measurement from a sensor. - float request_measurement(ADS1115Sensor *sensor); + float request_measurement(ADS1115Multiplexer multiplexer, ADS1115Gain gain, ADS1115Resolution resolution); protected: - std::vector sensors_; uint16_t prev_config_{0}; bool continuous_mode_; }; -/// Internal holder class that is in instance of Sensor so that the hub can create individual sensors. -class ADS1115Sensor : public sensor::Sensor, public PollingComponent, public voltage_sampler::VoltageSampler { - public: - ADS1115Sensor(ADS1115Component *parent) : parent_(parent) {} - void update() override; - void set_multiplexer(ADS1115Multiplexer multiplexer) { multiplexer_ = multiplexer; } - void set_gain(ADS1115Gain gain) { gain_ = gain; } - void set_resolution(ADS1115Resolution resolution) { resolution_ = resolution; } - float sample() override; - uint8_t get_multiplexer() const { return multiplexer_; } - uint8_t get_gain() const { return gain_; } - uint8_t get_resolution() const { return resolution_; } - - protected: - ADS1115Component *parent_; - ADS1115Multiplexer multiplexer_; - ADS1115Gain gain_; - ADS1115Resolution resolution_; -}; - } // namespace ads1115 } // namespace esphome diff --git a/esphome/components/ads1115/sensor.py b/esphome/components/ads1115/sensor/__init__.py similarity index 82% rename from esphome/components/ads1115/sensor.py rename to esphome/components/ads1115/sensor/__init__.py index f0d894e2af..baec31d35c 100644 --- a/esphome/components/ads1115/sensor.py +++ b/esphome/components/ads1115/sensor/__init__.py @@ -10,8 +10,9 @@ from esphome.const import ( UNIT_VOLT, CONF_ID, ) -from . import ads1115_ns, ADS1115Component +from .. import ads1115_ns, ADS1115Component, CONF_ADS1115_ID +AUTO_LOAD = ["voltage_sampler"] DEPENDENCIES = ["ads1115"] ADS1115Multiplexer = ads1115_ns.enum("ADS1115Multiplexer") @@ -43,20 +44,10 @@ RESOLUTION = { } -def validate_gain(value): - if isinstance(value, float): - value = f"{value:0.03f}" - elif not isinstance(value, str): - raise cv.Invalid(f'invalid gain "{value}"') - - return cv.enum(GAIN)(value) - - ADS1115Sensor = ads1115_ns.class_( "ADS1115Sensor", sensor.Sensor, cg.PollingComponent, voltage_sampler.VoltageSampler ) -CONF_ADS1115_ID = "ads1115_id" CONFIG_SCHEMA = ( sensor.sensor_schema( ADS1115Sensor, @@ -69,7 +60,7 @@ CONFIG_SCHEMA = ( { cv.GenerateID(CONF_ADS1115_ID): cv.use_id(ADS1115Component), cv.Required(CONF_MULTIPLEXER): cv.enum(MUX, upper=True, space="_"), - cv.Required(CONF_GAIN): validate_gain, + cv.Required(CONF_GAIN): cv.enum(GAIN, string=True), cv.Optional(CONF_RESOLUTION, default="16_BITS"): cv.enum( RESOLUTION, upper=True, space="_" ), @@ -80,13 +71,11 @@ CONFIG_SCHEMA = ( async def to_code(config): - paren = await cg.get_variable(config[CONF_ADS1115_ID]) - var = cg.new_Pvariable(config[CONF_ID], paren) + var = cg.new_Pvariable(config[CONF_ID]) await sensor.register_sensor(var, config) await cg.register_component(var, config) + await cg.register_parented(var, config[CONF_ADS1115_ID]) cg.add(var.set_multiplexer(config[CONF_MULTIPLEXER])) cg.add(var.set_gain(config[CONF_GAIN])) cg.add(var.set_resolution(config[CONF_RESOLUTION])) - - cg.add(paren.register_sensor(var)) diff --git a/esphome/components/ads1115/sensor/ads1115_sensor.cpp b/esphome/components/ads1115/sensor/ads1115_sensor.cpp new file mode 100644 index 0000000000..335fca4845 --- /dev/null +++ b/esphome/components/ads1115/sensor/ads1115_sensor.cpp @@ -0,0 +1,30 @@ +#include "ads1115_sensor.h" + +#include "esphome/core/log.h" + +namespace esphome { +namespace ads1115 { + +static const char *const TAG = "ads1115.sensor"; + +float ADS1115Sensor::sample() { + return this->parent_->request_measurement(this->multiplexer_, this->gain_, this->resolution_); +} + +void ADS1115Sensor::update() { + float v = this->sample(); + if (!std::isnan(v)) { + ESP_LOGD(TAG, "'%s': Got Voltage=%fV", this->get_name().c_str(), v); + this->publish_state(v); + } +} + +void ADS1115Sensor::dump_config() { + LOG_SENSOR(" ", "ADS1115 Sensor", this); + ESP_LOGCONFIG(TAG, " Multiplexer: %u", this->multiplexer_); + ESP_LOGCONFIG(TAG, " Gain: %u", this->gain_); + ESP_LOGCONFIG(TAG, " Resolution: %u", this->resolution_); +} + +} // namespace ads1115 +} // namespace esphome diff --git a/esphome/components/ads1115/sensor/ads1115_sensor.h b/esphome/components/ads1115/sensor/ads1115_sensor.h new file mode 100644 index 0000000000..191afc3de6 --- /dev/null +++ b/esphome/components/ads1115/sensor/ads1115_sensor.h @@ -0,0 +1,35 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/core/helpers.h" + +#include "esphome/components/sensor/sensor.h" +#include "esphome/components/voltage_sampler/voltage_sampler.h" + +#include "../ads1115.h" + +namespace esphome { +namespace ads1115 { + +/// Internal holder class that is in instance of Sensor so that the hub can create individual sensors. +class ADS1115Sensor : public sensor::Sensor, + public PollingComponent, + public voltage_sampler::VoltageSampler, + public Parented { + public: + void update() override; + void set_multiplexer(ADS1115Multiplexer multiplexer) { this->multiplexer_ = multiplexer; } + void set_gain(ADS1115Gain gain) { this->gain_ = gain; } + void set_resolution(ADS1115Resolution resolution) { this->resolution_ = resolution; } + float sample() override; + + void dump_config() override; + + protected: + ADS1115Multiplexer multiplexer_; + ADS1115Gain gain_; + ADS1115Resolution resolution_; +}; + +} // namespace ads1115 +} // namespace esphome From e6bfa275fca4056cd2417023850c3c94b622c291 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 12 Apr 2024 07:57:41 +1200 Subject: [PATCH 1224/2101] Bump esphome-dashboard to 20240412.0 (#6517) --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 702127eca8..4abc4d98d2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ pyserial==3.5 platformio==6.1.13 # When updating platformio, also update Dockerfile esptool==4.7.0 click==8.1.7 -esphome-dashboard==20240319.0 +esphome-dashboard==20240412.0 aioesphomeapi==23.2.0 zeroconf==0.131.0 python-magic==0.4.27 From 68b4d8865c14ecde4f8d9bdc1febae981962b0a6 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 10 Apr 2024 19:25:35 +1200 Subject: [PATCH 1225/2101] Add dooya remote transmitter test (#6508) --- tests/components/remote_transmitter/common-buttons.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/components/remote_transmitter/common-buttons.yaml b/tests/components/remote_transmitter/common-buttons.yaml index 5f655acb7c..27683b387f 100644 --- a/tests/components/remote_transmitter/common-buttons.yaml +++ b/tests/components/remote_transmitter/common-buttons.yaml @@ -176,3 +176,11 @@ button: 0x00, 0x05, ] + - platform: template + name: Dooya + on_press: + remote_transmitter.transmit_dooya: + id: 0x123456 + channel: 1 + button: 1 + check: 1 From 1d4c074ee6aa301dea5fb7f9f161e83abd83f313 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 11 Apr 2024 10:09:25 +1200 Subject: [PATCH 1226/2101] ads1115: remove auto-load and split sensor into platform folder (#5981) --- esphome/components/ads1115/__init__.py | 3 +- esphome/components/ads1115/ads1115.cpp | 31 +++++----------- esphome/components/ads1115/ads1115.h | 31 ++-------------- .../ads1115/{sensor.py => sensor/__init__.py} | 21 +++-------- .../ads1115/sensor/ads1115_sensor.cpp | 30 ++++++++++++++++ .../ads1115/sensor/ads1115_sensor.h | 35 +++++++++++++++++++ 6 files changed, 82 insertions(+), 69 deletions(-) rename esphome/components/ads1115/{sensor.py => sensor/__init__.py} (82%) create mode 100644 esphome/components/ads1115/sensor/ads1115_sensor.cpp create mode 100644 esphome/components/ads1115/sensor/ads1115_sensor.h diff --git a/esphome/components/ads1115/__init__.py b/esphome/components/ads1115/__init__.py index e8861a2f67..a463d8390d 100644 --- a/esphome/components/ads1115/__init__.py +++ b/esphome/components/ads1115/__init__.py @@ -4,13 +4,14 @@ from esphome.components import i2c from esphome.const import CONF_ID DEPENDENCIES = ["i2c"] -AUTO_LOAD = ["sensor", "voltage_sampler"] MULTI_CONF = True ads1115_ns = cg.esphome_ns.namespace("ads1115") ADS1115Component = ads1115_ns.class_("ADS1115Component", cg.Component, i2c.I2CDevice) CONF_CONTINUOUS_MODE = "continuous_mode" +CONF_ADS1115_ID = "ads1115_id" + CONFIG_SCHEMA = ( cv.Schema( { diff --git a/esphome/components/ads1115/ads1115.cpp b/esphome/components/ads1115/ads1115.cpp index c3f3c00c63..218edc4c81 100644 --- a/esphome/components/ads1115/ads1115.cpp +++ b/esphome/components/ads1115/ads1115.cpp @@ -1,6 +1,6 @@ #include "ads1115.h" -#include "esphome/core/log.h" #include "esphome/core/hal.h" +#include "esphome/core/log.h" namespace esphome { namespace ads1115 { @@ -75,25 +75,19 @@ void ADS1115Component::dump_config() { if (this->is_failed()) { ESP_LOGE(TAG, "Communication with ADS1115 failed!"); } - - for (auto *sensor : this->sensors_) { - LOG_SENSOR(" ", "Sensor", sensor); - ESP_LOGCONFIG(TAG, " Multiplexer: %u", sensor->get_multiplexer()); - ESP_LOGCONFIG(TAG, " Gain: %u", sensor->get_gain()); - ESP_LOGCONFIG(TAG, " Resolution: %u", sensor->get_resolution()); - } } -float ADS1115Component::request_measurement(ADS1115Sensor *sensor) { +float ADS1115Component::request_measurement(ADS1115Multiplexer multiplexer, ADS1115Gain gain, + ADS1115Resolution resolution) { uint16_t config = this->prev_config_; // Multiplexer // 0bxBBBxxxxxxxxxxxx config &= 0b1000111111111111; - config |= (sensor->get_multiplexer() & 0b111) << 12; + config |= (multiplexer & 0b111) << 12; // Gain // 0bxxxxBBBxxxxxxxxx config &= 0b1111000111111111; - config |= (sensor->get_gain() & 0b111) << 9; + config |= (gain & 0b111) << 9; if (!this->continuous_mode_) { // Start conversion @@ -132,7 +126,7 @@ float ADS1115Component::request_measurement(ADS1115Sensor *sensor) { return NAN; } - if (sensor->get_resolution() == ADS1015_12_BITS) { + if (resolution == ADS1015_12_BITS) { bool negative = (raw_conversion >> 15) == 1; // shift raw_conversion as it's only 12-bits, left justified @@ -151,8 +145,8 @@ float ADS1115Component::request_measurement(ADS1115Sensor *sensor) { auto signed_conversion = static_cast(raw_conversion); float millivolts; - float divider = (sensor->get_resolution() == ADS1115_16_BITS) ? 32768.0f : 2048.0f; - switch (sensor->get_gain()) { + float divider = (resolution == ADS1115_16_BITS) ? 32768.0f : 2048.0f; + switch (gain) { case ADS1115_GAIN_6P144: millivolts = (signed_conversion * 6144) / divider; break; @@ -179,14 +173,5 @@ float ADS1115Component::request_measurement(ADS1115Sensor *sensor) { return millivolts / 1e3f; } -float ADS1115Sensor::sample() { return this->parent_->request_measurement(this); } -void ADS1115Sensor::update() { - float v = this->parent_->request_measurement(this); - if (!std::isnan(v)) { - ESP_LOGD(TAG, "'%s': Got Voltage=%fV", this->get_name().c_str(), v); - this->publish_state(v); - } -} - } // namespace ads1115 } // namespace esphome diff --git a/esphome/components/ads1115/ads1115.h b/esphome/components/ads1115/ads1115.h index 0b8bfb339b..509333d2c8 100644 --- a/esphome/components/ads1115/ads1115.h +++ b/esphome/components/ads1115/ads1115.h @@ -1,9 +1,7 @@ #pragma once -#include "esphome/core/component.h" -#include "esphome/components/sensor/sensor.h" #include "esphome/components/i2c/i2c.h" -#include "esphome/components/voltage_sampler/voltage_sampler.h" +#include "esphome/core/component.h" #include @@ -35,12 +33,8 @@ enum ADS1115Resolution { ADS1015_12_BITS = 12, }; -class ADS1115Sensor; - class ADS1115Component : public Component, public i2c::I2CDevice { public: - void register_sensor(ADS1115Sensor *obj) { this->sensors_.push_back(obj); } - /// Set up the internal sensor array. void setup() override; void dump_config() override; /// HARDWARE_LATE setup priority @@ -48,33 +42,12 @@ class ADS1115Component : public Component, public i2c::I2CDevice { void set_continuous_mode(bool continuous_mode) { continuous_mode_ = continuous_mode; } /// Helper method to request a measurement from a sensor. - float request_measurement(ADS1115Sensor *sensor); + float request_measurement(ADS1115Multiplexer multiplexer, ADS1115Gain gain, ADS1115Resolution resolution); protected: - std::vector sensors_; uint16_t prev_config_{0}; bool continuous_mode_; }; -/// Internal holder class that is in instance of Sensor so that the hub can create individual sensors. -class ADS1115Sensor : public sensor::Sensor, public PollingComponent, public voltage_sampler::VoltageSampler { - public: - ADS1115Sensor(ADS1115Component *parent) : parent_(parent) {} - void update() override; - void set_multiplexer(ADS1115Multiplexer multiplexer) { multiplexer_ = multiplexer; } - void set_gain(ADS1115Gain gain) { gain_ = gain; } - void set_resolution(ADS1115Resolution resolution) { resolution_ = resolution; } - float sample() override; - uint8_t get_multiplexer() const { return multiplexer_; } - uint8_t get_gain() const { return gain_; } - uint8_t get_resolution() const { return resolution_; } - - protected: - ADS1115Component *parent_; - ADS1115Multiplexer multiplexer_; - ADS1115Gain gain_; - ADS1115Resolution resolution_; -}; - } // namespace ads1115 } // namespace esphome diff --git a/esphome/components/ads1115/sensor.py b/esphome/components/ads1115/sensor/__init__.py similarity index 82% rename from esphome/components/ads1115/sensor.py rename to esphome/components/ads1115/sensor/__init__.py index f0d894e2af..baec31d35c 100644 --- a/esphome/components/ads1115/sensor.py +++ b/esphome/components/ads1115/sensor/__init__.py @@ -10,8 +10,9 @@ from esphome.const import ( UNIT_VOLT, CONF_ID, ) -from . import ads1115_ns, ADS1115Component +from .. import ads1115_ns, ADS1115Component, CONF_ADS1115_ID +AUTO_LOAD = ["voltage_sampler"] DEPENDENCIES = ["ads1115"] ADS1115Multiplexer = ads1115_ns.enum("ADS1115Multiplexer") @@ -43,20 +44,10 @@ RESOLUTION = { } -def validate_gain(value): - if isinstance(value, float): - value = f"{value:0.03f}" - elif not isinstance(value, str): - raise cv.Invalid(f'invalid gain "{value}"') - - return cv.enum(GAIN)(value) - - ADS1115Sensor = ads1115_ns.class_( "ADS1115Sensor", sensor.Sensor, cg.PollingComponent, voltage_sampler.VoltageSampler ) -CONF_ADS1115_ID = "ads1115_id" CONFIG_SCHEMA = ( sensor.sensor_schema( ADS1115Sensor, @@ -69,7 +60,7 @@ CONFIG_SCHEMA = ( { cv.GenerateID(CONF_ADS1115_ID): cv.use_id(ADS1115Component), cv.Required(CONF_MULTIPLEXER): cv.enum(MUX, upper=True, space="_"), - cv.Required(CONF_GAIN): validate_gain, + cv.Required(CONF_GAIN): cv.enum(GAIN, string=True), cv.Optional(CONF_RESOLUTION, default="16_BITS"): cv.enum( RESOLUTION, upper=True, space="_" ), @@ -80,13 +71,11 @@ CONFIG_SCHEMA = ( async def to_code(config): - paren = await cg.get_variable(config[CONF_ADS1115_ID]) - var = cg.new_Pvariable(config[CONF_ID], paren) + var = cg.new_Pvariable(config[CONF_ID]) await sensor.register_sensor(var, config) await cg.register_component(var, config) + await cg.register_parented(var, config[CONF_ADS1115_ID]) cg.add(var.set_multiplexer(config[CONF_MULTIPLEXER])) cg.add(var.set_gain(config[CONF_GAIN])) cg.add(var.set_resolution(config[CONF_RESOLUTION])) - - cg.add(paren.register_sensor(var)) diff --git a/esphome/components/ads1115/sensor/ads1115_sensor.cpp b/esphome/components/ads1115/sensor/ads1115_sensor.cpp new file mode 100644 index 0000000000..335fca4845 --- /dev/null +++ b/esphome/components/ads1115/sensor/ads1115_sensor.cpp @@ -0,0 +1,30 @@ +#include "ads1115_sensor.h" + +#include "esphome/core/log.h" + +namespace esphome { +namespace ads1115 { + +static const char *const TAG = "ads1115.sensor"; + +float ADS1115Sensor::sample() { + return this->parent_->request_measurement(this->multiplexer_, this->gain_, this->resolution_); +} + +void ADS1115Sensor::update() { + float v = this->sample(); + if (!std::isnan(v)) { + ESP_LOGD(TAG, "'%s': Got Voltage=%fV", this->get_name().c_str(), v); + this->publish_state(v); + } +} + +void ADS1115Sensor::dump_config() { + LOG_SENSOR(" ", "ADS1115 Sensor", this); + ESP_LOGCONFIG(TAG, " Multiplexer: %u", this->multiplexer_); + ESP_LOGCONFIG(TAG, " Gain: %u", this->gain_); + ESP_LOGCONFIG(TAG, " Resolution: %u", this->resolution_); +} + +} // namespace ads1115 +} // namespace esphome diff --git a/esphome/components/ads1115/sensor/ads1115_sensor.h b/esphome/components/ads1115/sensor/ads1115_sensor.h new file mode 100644 index 0000000000..191afc3de6 --- /dev/null +++ b/esphome/components/ads1115/sensor/ads1115_sensor.h @@ -0,0 +1,35 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/core/helpers.h" + +#include "esphome/components/sensor/sensor.h" +#include "esphome/components/voltage_sampler/voltage_sampler.h" + +#include "../ads1115.h" + +namespace esphome { +namespace ads1115 { + +/// Internal holder class that is in instance of Sensor so that the hub can create individual sensors. +class ADS1115Sensor : public sensor::Sensor, + public PollingComponent, + public voltage_sampler::VoltageSampler, + public Parented { + public: + void update() override; + void set_multiplexer(ADS1115Multiplexer multiplexer) { this->multiplexer_ = multiplexer; } + void set_gain(ADS1115Gain gain) { this->gain_ = gain; } + void set_resolution(ADS1115Resolution resolution) { this->resolution_ = resolution; } + float sample() override; + + void dump_config() override; + + protected: + ADS1115Multiplexer multiplexer_; + ADS1115Gain gain_; + ADS1115Resolution resolution_; +}; + +} // namespace ads1115 +} // namespace esphome From 4ebbd4ebd8c1e4960f4ee081a8c46fa6d3a8d7ee Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 12 Apr 2024 07:57:41 +1200 Subject: [PATCH 1227/2101] Bump esphome-dashboard to 20240412.0 (#6517) --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 702127eca8..4abc4d98d2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ pyserial==3.5 platformio==6.1.13 # When updating platformio, also update Dockerfile esptool==4.7.0 click==8.1.7 -esphome-dashboard==20240319.0 +esphome-dashboard==20240412.0 aioesphomeapi==23.2.0 zeroconf==0.131.0 python-magic==0.4.27 From 8ada8f5e11f3ce4045a3752d0ff8fbf11d748a2a Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 12 Apr 2024 08:02:52 +1200 Subject: [PATCH 1228/2101] Bump version to 2024.4.0b2 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 5f8082c395..08a1a42ea3 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.4.0b1" +__version__ = "2024.4.0b2" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 55433463d75c65405296972b4fd389b9f0e39cdd Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 12 Apr 2024 10:19:49 +1200 Subject: [PATCH 1229/2101] Fix missing ifdefs in voice assistant (#6520) --- esphome/components/voice_assistant/voice_assistant.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index 34a26eec01..e68e00948e 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -729,6 +729,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { } void VoiceAssistant::on_audio(const api::VoiceAssistantAudio &msg) { +#ifdef USE_SPEAKER // We should never get to this function if there is no speaker anyway if (this->speaker_buffer_index_ + msg.data.length() < SPEAKER_BUFFER_SIZE) { memcpy(this->speaker_buffer_ + this->speaker_buffer_index_, msg.data.data(), msg.data.length()); this->speaker_buffer_index_ += msg.data.length(); @@ -737,6 +738,7 @@ void VoiceAssistant::on_audio(const api::VoiceAssistantAudio &msg) { } else { ESP_LOGE(TAG, "Cannot receive audio, buffer is full"); } +#endif } VoiceAssistant *global_voice_assistant = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) From 39947a163440e3bbdee2d4082c11599de46ffbd0 Mon Sep 17 00:00:00 2001 From: MRemy2 <95053616+MRemy2@users.noreply.github.com> Date: Fri, 12 Apr 2024 02:28:59 +0300 Subject: [PATCH 1230/2101] Added Htu21d model option (#6511) Co-authored-by: Remus Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/htu21d/htu21d.cpp | 21 ++++++++++++++++--- esphome/components/htu21d/htu21d.h | 4 ++++ esphome/components/htu21d/sensor.py | 11 +++++++++- .../components/htu21d/test.esp32-c3-idf.yaml | 1 + tests/components/htu21d/test.esp32-c3.yaml | 1 + tests/components/htu21d/test.esp32-idf.yaml | 1 + tests/components/htu21d/test.esp32.yaml | 1 + tests/components/htu21d/test.esp8266.yaml | 1 + tests/components/htu21d/test.rp2040.yaml | 1 + 9 files changed, 38 insertions(+), 4 deletions(-) diff --git a/esphome/components/htu21d/htu21d.cpp b/esphome/components/htu21d/htu21d.cpp index d0dbb15a43..411d1e1d6a 100644 --- a/esphome/components/htu21d/htu21d.cpp +++ b/esphome/components/htu21d/htu21d.cpp @@ -76,12 +76,27 @@ void HTU21DComponent::update() { float humidity = (float(raw_humidity & 0xFFFC)) * 125.0f / 65536.0f - 6.0f; - int8_t heater_level = this->get_heater_level(); - - ESP_LOGD(TAG, "Got Humidity=%.1f%% Heater Level=%d", humidity, heater_level); + ESP_LOGD(TAG, "Got Humidity=%.1f%%", humidity); if (this->humidity_ != nullptr) this->humidity_->publish_state(humidity); + + int8_t heater_level; + + // HTU21D does have a heater module but does not have heater level + // Setting heater level to 1 in case the heater is ON + if (this->sensor_model_ == HTU21D_SENSOR_MODEL_HTU21D) { + if (this->is_heater_enabled()) { + heater_level = 1; + } else { + heater_level = 0; + } + } else { + heater_level = this->get_heater_level(); + } + + ESP_LOGD(TAG, "Heater Level=%d", heater_level); + if (this->heater_ != nullptr) this->heater_->publish_state(heater_level); this->status_clear_warning(); diff --git a/esphome/components/htu21d/htu21d.h b/esphome/components/htu21d/htu21d.h index a77a8e3ada..8533875d43 100644 --- a/esphome/components/htu21d/htu21d.h +++ b/esphome/components/htu21d/htu21d.h @@ -8,6 +8,8 @@ namespace esphome { namespace htu21d { +enum HTU21DSensorModels { HTU21D_SENSOR_MODEL_HTU21D = 0, HTU21D_SENSOR_MODEL_SI7021, HTU21D_SENSOR_MODEL_SHT21 }; + class HTU21DComponent : public PollingComponent, public i2c::I2CDevice { public: void set_temperature(sensor::Sensor *temperature) { temperature_ = temperature; } @@ -17,6 +19,7 @@ class HTU21DComponent : public PollingComponent, public i2c::I2CDevice { /// Setup (reset) the sensor and check connection. void setup() override; void dump_config() override; + void set_sensor_model(HTU21DSensorModels sensor_model) { sensor_model_ = sensor_model; } /// Update the sensor values (temperature+humidity). void update() override; @@ -31,6 +34,7 @@ class HTU21DComponent : public PollingComponent, public i2c::I2CDevice { sensor::Sensor *temperature_{nullptr}; sensor::Sensor *humidity_{nullptr}; sensor::Sensor *heater_{nullptr}; + HTU21DSensorModels sensor_model_{HTU21D_SENSOR_MODEL_HTU21D}; }; template class SetHeaterLevelAction : public Action, public Parented { diff --git a/esphome/components/htu21d/sensor.py b/esphome/components/htu21d/sensor.py index 1f878230f8..bf0b9a23fb 100644 --- a/esphome/components/htu21d/sensor.py +++ b/esphome/components/htu21d/sensor.py @@ -5,6 +5,7 @@ from esphome import automation from esphome.const import ( CONF_HUMIDITY, CONF_ID, + CONF_MODEL, CONF_TEMPERATURE, DEVICE_CLASS_HUMIDITY, DEVICE_CLASS_TEMPERATURE, @@ -23,10 +24,15 @@ htu21d_ns = cg.esphome_ns.namespace("htu21d") HTU21DComponent = htu21d_ns.class_( "HTU21DComponent", cg.PollingComponent, i2c.I2CDevice ) - SetHeaterLevelAction = htu21d_ns.class_("SetHeaterLevelAction", automation.Action) SetHeaterAction = htu21d_ns.class_("SetHeaterAction", automation.Action) +HTU21DSensorModels = htu21d_ns.enum("HTU21DSensorModels") +MODELS = { + "HTU21D": HTU21DSensorModels.HTU21D_SENSOR_MODEL_HTU21D, + "SI7021": HTU21DSensorModels.HTU21D_SENSOR_MODEL_SI7021, + "SHT21": HTU21DSensorModels.HTU21D_SENSOR_MODEL_SHT21, +} CONFIG_SCHEMA = ( cv.Schema( @@ -49,6 +55,7 @@ CONFIG_SCHEMA = ( accuracy_decimals=1, state_class=STATE_CLASS_MEASUREMENT, ), + cv.Optional(CONF_MODEL, default="HTU21D"): cv.enum(MODELS, upper=True), } ) .extend(cv.polling_component_schema("60s")) @@ -73,6 +80,8 @@ async def to_code(config): sens = await sensor.new_sensor(config[CONF_HEATER]) cg.add(var.set_heater(sens)) + cg.add(var.set_sensor_model(config[CONF_MODEL])) + @automation.register_action( "htu21d.set_heater_level", diff --git a/tests/components/htu21d/test.esp32-c3-idf.yaml b/tests/components/htu21d/test.esp32-c3-idf.yaml index d9fbb09550..8131d13661 100644 --- a/tests/components/htu21d/test.esp32-c3-idf.yaml +++ b/tests/components/htu21d/test.esp32-c3-idf.yaml @@ -5,6 +5,7 @@ i2c: sensor: - platform: htu21d + model: htu21d temperature: name: Temperature humidity: diff --git a/tests/components/htu21d/test.esp32-c3.yaml b/tests/components/htu21d/test.esp32-c3.yaml index d9fbb09550..8131d13661 100644 --- a/tests/components/htu21d/test.esp32-c3.yaml +++ b/tests/components/htu21d/test.esp32-c3.yaml @@ -5,6 +5,7 @@ i2c: sensor: - platform: htu21d + model: htu21d temperature: name: Temperature humidity: diff --git a/tests/components/htu21d/test.esp32-idf.yaml b/tests/components/htu21d/test.esp32-idf.yaml index 48f03eb368..6655a1cc1a 100644 --- a/tests/components/htu21d/test.esp32-idf.yaml +++ b/tests/components/htu21d/test.esp32-idf.yaml @@ -5,6 +5,7 @@ i2c: sensor: - platform: htu21d + model: htu21d temperature: name: Temperature humidity: diff --git a/tests/components/htu21d/test.esp32.yaml b/tests/components/htu21d/test.esp32.yaml index 48f03eb368..6655a1cc1a 100644 --- a/tests/components/htu21d/test.esp32.yaml +++ b/tests/components/htu21d/test.esp32.yaml @@ -5,6 +5,7 @@ i2c: sensor: - platform: htu21d + model: htu21d temperature: name: Temperature humidity: diff --git a/tests/components/htu21d/test.esp8266.yaml b/tests/components/htu21d/test.esp8266.yaml index d9fbb09550..8131d13661 100644 --- a/tests/components/htu21d/test.esp8266.yaml +++ b/tests/components/htu21d/test.esp8266.yaml @@ -5,6 +5,7 @@ i2c: sensor: - platform: htu21d + model: htu21d temperature: name: Temperature humidity: diff --git a/tests/components/htu21d/test.rp2040.yaml b/tests/components/htu21d/test.rp2040.yaml index d9fbb09550..8131d13661 100644 --- a/tests/components/htu21d/test.rp2040.yaml +++ b/tests/components/htu21d/test.rp2040.yaml @@ -5,6 +5,7 @@ i2c: sensor: - platform: htu21d + model: htu21d temperature: name: Temperature humidity: From 810cf3b0a4d705a35d0cd2285ff304485e7905df Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 12 Apr 2024 11:56:18 +1200 Subject: [PATCH 1231/2101] Add bk72xx base test file (#6522) --- .../build_components_base.bk72xx.yaml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 tests/test_build_components/build_components_base.bk72xx.yaml diff --git a/tests/test_build_components/build_components_base.bk72xx.yaml b/tests/test_build_components/build_components_base.bk72xx.yaml new file mode 100644 index 0000000000..7fdaebc768 --- /dev/null +++ b/tests/test_build_components/build_components_base.bk72xx.yaml @@ -0,0 +1,18 @@ +esphome: + name: componenttestespbk72xx + friendly_name: $component_name + +bk72xx: + board: cb3s + +logger: + level: VERY_VERBOSE + +packages: + component_under_test: !include + file: $component_test_file + vars: + component_name: $component_name + test_name: $test_name + target_platform: $target_platform + component_test_file: $component_test_file From 7eb524f920143ce7be075c84ac13c4856544ac91 Mon Sep 17 00:00:00 2001 From: Peter Zich Date: Thu, 11 Apr 2024 20:46:59 -0700 Subject: [PATCH 1232/2101] Add "log" alias for "logs" command (#6519) --- esphome/__main__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/__main__.py b/esphome/__main__.py index 95d444ca9b..dcd2dddb4b 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -785,6 +785,7 @@ def parse_args(argv): parser_logs = subparsers.add_parser( "logs", help="Validate the configuration and show all logs.", + aliases=["log"], parents=[mqtt_options], ) parser_logs.add_argument( From 76daefe21c5f7a405d3f7df232bb7df0a2f4fe09 Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Fri, 12 Apr 2024 06:03:08 +0200 Subject: [PATCH 1233/2101] Add ethernet DNS text sensor and simplify DNS display format (#6450) --- .../ethernet/ethernet_component.cpp | 5 +++++ .../components/ethernet/ethernet_component.h | 1 + .../ethernet_info_text_sensor.cpp | 1 + .../ethernet_info/ethernet_info_text_sensor.h | 21 +++++++++++++++++++ .../components/ethernet_info/text_sensor.py | 17 ++++++++++++--- .../wifi_info/wifi_info_text_sensor.h | 7 +------ .../ethernet_info/test.esp32-idf.yaml | 2 ++ .../components/ethernet_info/test.esp32.yaml | 2 ++ 8 files changed, 47 insertions(+), 9 deletions(-) diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index 3c61fbe0a6..243135de89 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -340,6 +340,11 @@ network::IPAddresses EthernetComponent::get_ip_addresses() { return addresses; } +network::IPAddress EthernetComponent::get_dns_address(uint8_t num) { + 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; diff --git a/esphome/components/ethernet/ethernet_component.h b/esphome/components/ethernet/ethernet_component.h index 621ac87c10..daeb5a2029 100644 --- a/esphome/components/ethernet/ethernet_component.h +++ b/esphome/components/ethernet/ethernet_component.h @@ -70,6 +70,7 @@ class EthernetComponent : public Component { void set_manual_ip(const ManualIP &manual_ip); network::IPAddresses get_ip_addresses(); + network::IPAddress get_dns_address(uint8_t num); std::string get_use_address() const; void set_use_address(const std::string &use_address); bool powerdown(); diff --git a/esphome/components/ethernet_info/ethernet_info_text_sensor.cpp b/esphome/components/ethernet_info/ethernet_info_text_sensor.cpp index f841875396..c8b2b5885b 100644 --- a/esphome/components/ethernet_info/ethernet_info_text_sensor.cpp +++ b/esphome/components/ethernet_info/ethernet_info_text_sensor.cpp @@ -9,6 +9,7 @@ namespace ethernet_info { static const char *const TAG = "ethernet_info"; void IPAddressEthernetInfo::dump_config() { LOG_TEXT_SENSOR("", "EthernetInfo IPAddress", this); } +void DNSAddressEthernetInfo::dump_config() { LOG_TEXT_SENSOR("", "EthernetInfo DNS Address", this); } } // namespace ethernet_info } // namespace esphome diff --git a/esphome/components/ethernet_info/ethernet_info_text_sensor.h b/esphome/components/ethernet_info/ethernet_info_text_sensor.h index b5764d2519..82a7dcf56e 100644 --- a/esphome/components/ethernet_info/ethernet_info_text_sensor.h +++ b/esphome/components/ethernet_info/ethernet_info_text_sensor.h @@ -38,6 +38,27 @@ class IPAddressEthernetInfo : public PollingComponent, public text_sensor::TextS std::array ip_sensors_; }; +class DNSAddressEthernetInfo : public PollingComponent, public text_sensor::TextSensor { + public: + void update() override { + auto dns_one = ethernet::global_eth_component->get_dns_address(0); + auto dns_two = ethernet::global_eth_component->get_dns_address(1); + + std::string dns_results = dns_one.str() + " " + dns_two.str(); + + if (dns_results != this->last_results_) { + this->last_results_ = dns_results; + this->publish_state(dns_results); + } + } + float get_setup_priority() const override { return setup_priority::ETHERNET; } + std::string unique_id() override { return get_mac_address() + "-ethernetinfo-dns"; } + void dump_config() override; + + protected: + std::string last_results_; +}; + } // namespace ethernet_info } // namespace esphome diff --git a/esphome/components/ethernet_info/text_sensor.py b/esphome/components/ethernet_info/text_sensor.py index b802c427e8..292673c182 100644 --- a/esphome/components/ethernet_info/text_sensor.py +++ b/esphome/components/ethernet_info/text_sensor.py @@ -3,6 +3,7 @@ import esphome.config_validation as cv from esphome.components import text_sensor from esphome.const import ( CONF_IP_ADDRESS, + CONF_DNS_ADDRESS, ENTITY_CATEGORY_DIAGNOSTIC, ) @@ -10,14 +11,18 @@ DEPENDENCIES = ["ethernet"] ethernet_info_ns = cg.esphome_ns.namespace("ethernet_info") -IPAddressEsthernetInfo = ethernet_info_ns.class_( +IPAddressEthernetInfo = ethernet_info_ns.class_( "IPAddressEthernetInfo", text_sensor.TextSensor, cg.PollingComponent ) +DNSAddressEthernetInfo = ethernet_info_ns.class_( + "DNSAddressEthernetInfo", text_sensor.TextSensor, cg.PollingComponent +) + CONFIG_SCHEMA = cv.Schema( { cv.Optional(CONF_IP_ADDRESS): text_sensor.text_sensor_schema( - IPAddressEsthernetInfo, entity_category=ENTITY_CATEGORY_DIAGNOSTIC + IPAddressEthernetInfo, entity_category=ENTITY_CATEGORY_DIAGNOSTIC ) .extend(cv.polling_component_schema("1s")) .extend( @@ -27,7 +32,10 @@ CONFIG_SCHEMA = cv.Schema( ) for x in range(5) } - ) + ), + cv.Optional(CONF_DNS_ADDRESS): text_sensor.text_sensor_schema( + DNSAddressEthernetInfo, entity_category=ENTITY_CATEGORY_DIAGNOSTIC + ).extend(cv.polling_component_schema("1s")), } ) @@ -40,3 +48,6 @@ async def to_code(config): if sensor_conf := conf.get(f"address_{x}"): 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]) diff --git a/esphome/components/wifi_info/wifi_info_text_sensor.h b/esphome/components/wifi_info/wifi_info_text_sensor.h index 6f189da3a3..0f31a57cc5 100644 --- a/esphome/components/wifi_info/wifi_info_text_sensor.h +++ b/esphome/components/wifi_info/wifi_info_text_sensor.h @@ -39,15 +39,10 @@ class IPAddressWiFiInfo : public PollingComponent, public text_sensor::TextSenso class DNSAddressWifiInfo : public PollingComponent, public text_sensor::TextSensor { public: void update() override { - std::string dns_results; - auto dns_one = wifi::global_wifi_component->get_dns_address(0); auto dns_two = wifi::global_wifi_component->get_dns_address(1); - dns_results += "DNS1: "; - dns_results += dns_one.str(); - dns_results += " DNS2: "; - dns_results += dns_two.str(); + std::string dns_results = dns_one.str() + " " + dns_two.str(); if (dns_results != this->last_results_) { this->last_results_ = dns_results; diff --git a/tests/components/ethernet_info/test.esp32-idf.yaml b/tests/components/ethernet_info/test.esp32-idf.yaml index c5da2bb666..dade4d7ca5 100644 --- a/tests/components/ethernet_info/test.esp32-idf.yaml +++ b/tests/components/ethernet_info/test.esp32-idf.yaml @@ -15,3 +15,5 @@ text_sensor: - platform: ethernet_info ip_address: name: IP Address + dns_address: + name: DNS Address diff --git a/tests/components/ethernet_info/test.esp32.yaml b/tests/components/ethernet_info/test.esp32.yaml index c5da2bb666..dade4d7ca5 100644 --- a/tests/components/ethernet_info/test.esp32.yaml +++ b/tests/components/ethernet_info/test.esp32.yaml @@ -15,3 +15,5 @@ text_sensor: - platform: ethernet_info ip_address: name: IP Address + dns_address: + name: DNS Address From 1ab4fc8faf8de4c1d505522e16256c1e810a6b17 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Fri, 12 Apr 2024 04:35:12 -0500 Subject: [PATCH 1234/2101] Add all missing `remote_receiver` `on_...` tests (#6524) --- .../remote_receiver/esp32-common.yaml | 138 +++++++++++++++++- .../remote_receiver/test.esp8266.yaml | 138 +++++++++++++++++- 2 files changed, 272 insertions(+), 4 deletions(-) diff --git a/tests/components/remote_receiver/esp32-common.yaml b/tests/components/remote_receiver/esp32-common.yaml index d1d47661c5..0e71143fc3 100644 --- a/tests/components/remote_receiver/esp32-common.yaml +++ b/tests/components/remote_receiver/esp32-common.yaml @@ -3,12 +3,146 @@ remote_receiver: pin: ${pin} rmt_channel: ${rmt_channel} dump: all + on_abbwelcome: + then: + - logger.log: + format: "on_abbwelcome: %u" + args: ["x.data()[0]"] + on_aeha: + then: + - logger.log: + format: "on_aeha: %u %u" + args: ["x.address", "x.data.front()"] + on_byronsx: + then: + - logger.log: + format: "on_byronsx: %u %u" + args: ["x.address", "x.command"] + on_canalsat: + then: + - logger.log: + format: "on_canalsat: %u %u" + args: ["x.address", "x.command"] + # on_canalsatld: + # then: + # - logger.log: + # format: "on_canalsatld: %u %u" + # args: ["x.address", "x.command"] on_coolix: then: - delay: !lambda "return x.first + x.second;" + - logger.log: + format: "on_coolix: %u %u" + args: ["x.first", "x.second"] + on_dish: + then: + - logger.log: + format: "on_dish: %u %u" + args: ["x.address", "x.command"] + on_dooya: + then: + - logger.log: + format: "on_dooya: %u %u %u" + args: ["x.channel", "x.button", "x.check"] + on_drayton: + then: + - logger.log: + format: "on_drayton: %u %u %u" + args: ["x.address", "x.channel", "x.command"] + on_jvc: + then: + - logger.log: + format: "on_jvc: %u" + args: ["x.data"] + on_keeloq: + then: + - logger.log: + format: "on_keeloq: %u %u %u" + args: ["x.encrypted", "x.address", "x.command"] + on_haier: + then: + - logger.log: + format: "on_haier: %u" + args: ["x.data.front()"] + on_lg: + then: + - logger.log: + format: "on_lg: %u %u" + args: ["x.data", "x.nbits"] + on_magiquest: + then: + - logger.log: + format: "on_magiquest: %u %u" + args: ["x.magnitude", "x.wand_id"] + on_midea: + then: + - logger.log: + format: "on_midea: %u %u" + args: ["x.size()", "x.data()[0]"] + on_nec: + then: + - logger.log: + format: "on_nec: %u %u" + args: ["x.address", "x.command"] + on_nexa: + then: + - logger.log: + format: "on_nexa: %u %u %u %u %u" + args: ["x.device", "x.group", "x.state", "x.channel", "x.level"] + on_panasonic: + then: + - logger.log: + format: "on_panasonic: %u %u" + args: ["x.address", "x.command"] + on_pioneer: + then: + - logger.log: + format: "on_pioneer: %u %u" + args: ["x.rc_code_1", "x.rc_code_2"] + on_pronto: + then: + - logger.log: + format: "on_pronto: %s" + args: ["x.data.c_str()"] + on_raw: + then: + - logger.log: + format: "on_raw: %u" + args: ["x.front()"] + on_rc5: + then: + - logger.log: + format: "on_rc5: %u %u" + args: ["x.address", "x.command"] + on_rc6: + then: + - logger.log: + format: "on_rc6: %u %u" + args: ["x.address", "x.command"] on_rc_switch: then: - delay: !lambda "return uint32_t(x.code) + x.protocol;" + - logger.log: + format: "on_rc_switch: %llu %u" + args: ["x.code", "x.protocol"] + on_samsung: + then: + - logger.log: + format: "on_samsung: %llu %u" + args: ["x.data", "x.nbits"] + on_samsung36: + then: + - logger.log: + format: "on_samsung36: %u %u" + args: ["x.address", "x.command"] + on_sony: + then: + - logger.log: + format: "on_sony: %u %u" + args: ["x.data", "x.nbits"] + on_toshiba_ac: + then: + - logger.log: + format: "on_toshiba_ac: %llu %llu" + args: ["x.rc_code_1", "x.rc_code_2"] binary_sensor: - platform: remote_receiver diff --git a/tests/components/remote_receiver/test.esp8266.yaml b/tests/components/remote_receiver/test.esp8266.yaml index a7c283da1e..e96f031e90 100644 --- a/tests/components/remote_receiver/test.esp8266.yaml +++ b/tests/components/remote_receiver/test.esp8266.yaml @@ -2,12 +2,146 @@ remote_receiver: id: rcvr pin: GPIO5 dump: all + on_abbwelcome: + then: + - logger.log: + format: "on_abbwelcome: %u" + args: ["x.data()[0]"] + on_aeha: + then: + - logger.log: + format: "on_aeha: %u %u" + args: ["x.address", "x.data.front()"] + on_byronsx: + then: + - logger.log: + format: "on_byronsx: %u %u" + args: ["x.address", "x.command"] + on_canalsat: + then: + - logger.log: + format: "on_canalsat: %u %u" + args: ["x.address", "x.command"] + # on_canalsatld: + # then: + # - logger.log: + # format: "on_canalsatld: %u %u" + # args: ["x.address", "x.command"] on_coolix: then: - delay: !lambda "return x.first + x.second;" + - logger.log: + format: "on_coolix: %u %u" + args: ["x.first", "x.second"] + on_dish: + then: + - logger.log: + format: "on_dish: %u %u" + args: ["x.address", "x.command"] + on_dooya: + then: + - logger.log: + format: "on_dooya: %u %u %u" + args: ["x.channel", "x.button", "x.check"] + on_drayton: + then: + - logger.log: + format: "on_drayton: %u %u %u" + args: ["x.address", "x.channel", "x.command"] + on_jvc: + then: + - logger.log: + format: "on_jvc: %u" + args: ["x.data"] + on_keeloq: + then: + - logger.log: + format: "on_keeloq: %u %u %u" + args: ["x.encrypted", "x.address", "x.command"] + on_haier: + then: + - logger.log: + format: "on_haier: %u" + args: ["x.data.front()"] + on_lg: + then: + - logger.log: + format: "on_lg: %u %u" + args: ["x.data", "x.nbits"] + on_magiquest: + then: + - logger.log: + format: "on_magiquest: %u %u" + args: ["x.magnitude", "x.wand_id"] + on_midea: + then: + - logger.log: + format: "on_midea: %u %u" + args: ["x.size()", "x.data()[0]"] + on_nec: + then: + - logger.log: + format: "on_nec: %u %u" + args: ["x.address", "x.command"] + on_nexa: + then: + - logger.log: + format: "on_nexa: %u %u %u %u %u" + args: ["x.device", "x.group", "x.state", "x.channel", "x.level"] + on_panasonic: + then: + - logger.log: + format: "on_panasonic: %u %u" + args: ["x.address", "x.command"] + on_pioneer: + then: + - logger.log: + format: "on_pioneer: %u %u" + args: ["x.rc_code_1", "x.rc_code_2"] + on_pronto: + then: + - logger.log: + format: "on_pronto: %s" + args: ["x.data.c_str()"] + on_raw: + then: + - logger.log: + format: "on_raw: %u" + args: ["x.front()"] + on_rc5: + then: + - logger.log: + format: "on_rc5: %u %u" + args: ["x.address", "x.command"] + on_rc6: + then: + - logger.log: + format: "on_rc6: %u %u" + args: ["x.address", "x.command"] on_rc_switch: then: - delay: !lambda "return uint32_t(x.code) + x.protocol;" + - logger.log: + format: "on_rc_switch: %llu %u" + args: ["x.code", "x.protocol"] + on_samsung: + then: + - logger.log: + format: "on_samsung: %llu %u" + args: ["x.data", "x.nbits"] + on_samsung36: + then: + - logger.log: + format: "on_samsung36: %u %u" + args: ["x.address", "x.command"] + on_sony: + then: + - logger.log: + format: "on_sony: %u %u" + args: ["x.data", "x.nbits"] + on_toshiba_ac: + then: + - logger.log: + format: "on_toshiba_ac: %llu %llu" + args: ["x.rc_code_1", "x.rc_code_2"] binary_sensor: - platform: remote_receiver From 6370e68670f35b82cd02a29f814a75561d1c856b Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Sun, 14 Apr 2024 16:38:31 -0500 Subject: [PATCH 1235/2101] Add actions to http_request tests (#6529) --- tests/components/http_request/common.yaml | 37 +++++++++++++++++++ .../http_request/test.esp32-c3.yaml | 9 +---- tests/components/http_request/test.esp32.yaml | 9 +---- .../components/http_request/test.esp8266.yaml | 9 +---- 4 files changed, 43 insertions(+), 21 deletions(-) create mode 100644 tests/components/http_request/common.yaml diff --git a/tests/components/http_request/common.yaml b/tests/components/http_request/common.yaml new file mode 100644 index 0000000000..848fe3f509 --- /dev/null +++ b/tests/components/http_request/common.yaml @@ -0,0 +1,37 @@ +esphome: + on_boot: + then: + - http_request.get: + url: https://esphome.io + headers: + Content-Type: application/json + verify_ssl: false + on_response: + then: + - logger.log: + format: 'Response status: %d, Duration: %u ms' + args: + - status_code + - duration_ms + - http_request.post: + url: https://esphome.io + headers: + Content-Type: application/json + json: + key: value + verify_ssl: false + - http_request.send: + method: PUT + url: https://esphome.io + headers: + Content-Type: application/json + body: "Some data" + verify_ssl: false + +wifi: + ssid: MySSID + password: password1 + +http_request: + useragent: esphome/tagreader + timeout: 10s diff --git a/tests/components/http_request/test.esp32-c3.yaml b/tests/components/http_request/test.esp32-c3.yaml index 19fc6af2c4..25cb37a0b4 100644 --- a/tests/components/http_request/test.esp32-c3.yaml +++ b/tests/components/http_request/test.esp32-c3.yaml @@ -1,7 +1,2 @@ -wifi: - ssid: MySSID - password: password1 - -http_request: - useragent: esphome/tagreader - timeout: 10s +packages: + common: !include common.yaml diff --git a/tests/components/http_request/test.esp32.yaml b/tests/components/http_request/test.esp32.yaml index 19fc6af2c4..25cb37a0b4 100644 --- a/tests/components/http_request/test.esp32.yaml +++ b/tests/components/http_request/test.esp32.yaml @@ -1,7 +1,2 @@ -wifi: - ssid: MySSID - password: password1 - -http_request: - useragent: esphome/tagreader - timeout: 10s +packages: + common: !include common.yaml diff --git a/tests/components/http_request/test.esp8266.yaml b/tests/components/http_request/test.esp8266.yaml index 19fc6af2c4..25cb37a0b4 100644 --- a/tests/components/http_request/test.esp8266.yaml +++ b/tests/components/http_request/test.esp8266.yaml @@ -1,7 +1,2 @@ -wifi: - ssid: MySSID - password: password1 - -http_request: - useragent: esphome/tagreader - timeout: 10s +packages: + common: !include common.yaml From dc200948fa2c779e0c2b2bb4eded62ba347254dc Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 15 Apr 2024 12:02:19 +1200 Subject: [PATCH 1236/2101] Fix project version longer than 30 characters breaking compilation (#6535) --- esphome/core/base_automation.h | 2 +- esphome/core/config.py | 1 + esphome/core/defines.h | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/esphome/core/base_automation.h b/esphome/core/base_automation.h index b0ae0aff84..1bf0efb9a4 100644 --- a/esphome/core/base_automation.h +++ b/esphome/core/base_automation.h @@ -134,7 +134,7 @@ class ProjectUpdateTrigger : public Trigger, public Component { uint32_t hash = fnv1_hash(ESPHOME_PROJECT_NAME); ESPPreferenceObject pref = global_preferences->make_preference(hash, true); char previous_version[30]; - char current_version[30] = ESPHOME_PROJECT_VERSION; + char current_version[30] = ESPHOME_PROJECT_VERSION_30; if (pref.load(&previous_version)) { int cmp = strcmp(previous_version, current_version); if (cmp < 0) { diff --git a/esphome/core/config.py b/esphome/core/config.py index 792f9da6dd..2d87796987 100644 --- a/esphome/core/config.py +++ b/esphome/core/config.py @@ -394,6 +394,7 @@ async def to_code(config): if project_conf := config.get(CONF_PROJECT): cg.add_define("ESPHOME_PROJECT_NAME", project_conf[CONF_NAME]) cg.add_define("ESPHOME_PROJECT_VERSION", project_conf[CONF_VERSION]) + cg.add_define("ESPHOME_PROJECT_VERSION_30", project_conf[CONF_VERSION][:30]) for conf in project_conf.get(CONF_ON_UPDATE, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID]) await cg.register_component(trigger, conf) diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 22153de5de..f13ae968f0 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -11,6 +11,7 @@ #define ESPHOME_BOARD "dummy_board" #define ESPHOME_PROJECT_NAME "dummy project" #define ESPHOME_PROJECT_VERSION "v2" +#define ESPHOME_PROJECT_VERSION_30 "v2" #define ESPHOME_VARIANT "ESP32" // Feature flags From b43ad5da6d91b082290a9fca877c9d182af3185f Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Sun, 14 Apr 2024 19:25:10 -0500 Subject: [PATCH 1237/2101] Update homeassistant component tests with actions (#6528) --- tests/components/homeassistant/common.yaml | 67 +++++++++++++++++++ .../components/homeassistant/test.bk72xx.yaml | 2 + .../homeassistant/test.esp32-c3-idf.yaml | 41 +----------- .../homeassistant/test.esp32-c3.yaml | 41 +----------- .../homeassistant/test.esp32-idf.yaml | 41 +----------- .../components/homeassistant/test.esp32.yaml | 41 +----------- .../homeassistant/test.esp8266.yaml | 41 +----------- .../components/homeassistant/test.rp2040.yaml | 41 +----------- 8 files changed, 81 insertions(+), 234 deletions(-) create mode 100644 tests/components/homeassistant/common.yaml create mode 100644 tests/components/homeassistant/test.bk72xx.yaml diff --git a/tests/components/homeassistant/common.yaml b/tests/components/homeassistant/common.yaml new file mode 100644 index 0000000000..ae016a3bea --- /dev/null +++ b/tests/components/homeassistant/common.yaml @@ -0,0 +1,67 @@ +esphome: + on_boot: + then: + - homeassistant.event: + event: esphome.button_pressed + data: + message: Button was pressed + - homeassistant.event: + event: esphome.html5 + data: + message: New Humidity + data_template: + message: The humidity is {{ my_variable }}%. + variables: + my_variable: "return id(ha_hello_world_temperature).state;" + - homeassistant.service: + service: notify.html5 + data: + message: Button was pressed + - homeassistant.service: + service: notify.html5 + data: + title: New Humidity + data_template: + message: The humidity is {{ my_variable }}%. + variables: + my_variable: "return id(ha_hello_world_temperature).state;" + +wifi: + ssid: MySSID + password: password1 + +api: + +binary_sensor: + - platform: homeassistant + entity_id: binary_sensor.hello_world + id: ha_hello_world_binary + - platform: homeassistant + entity_id: binary_sensor.hello + attribute: world + id: ha_hello_world_binary_attribute + +sensor: + - platform: homeassistant + entity_id: sensor.hello_world + id: ha_hello_world + - platform: homeassistant + entity_id: climate.living_room + attribute: temperature + id: ha_hello_world_temperature + +text_sensor: + - platform: homeassistant + entity_id: sensor.hello_world + id: ha_hello_world_text + - platform: homeassistant + entity_id: sensor.hello_world1 + id: ha_hello_world_text2 + attribute: some_attribute + +time: + - platform: homeassistant + on_time: + - at: "16:00:00" + then: + - logger.log: It's 16:00 diff --git a/tests/components/homeassistant/test.bk72xx.yaml b/tests/components/homeassistant/test.bk72xx.yaml new file mode 100644 index 0000000000..25cb37a0b4 --- /dev/null +++ b/tests/components/homeassistant/test.bk72xx.yaml @@ -0,0 +1,2 @@ +packages: + common: !include common.yaml diff --git a/tests/components/homeassistant/test.esp32-c3-idf.yaml b/tests/components/homeassistant/test.esp32-c3-idf.yaml index d2608f077c..25cb37a0b4 100644 --- a/tests/components/homeassistant/test.esp32-c3-idf.yaml +++ b/tests/components/homeassistant/test.esp32-c3-idf.yaml @@ -1,39 +1,2 @@ -wifi: - ssid: MySSID - password: password1 - -api: - -binary_sensor: - - platform: homeassistant - entity_id: binary_sensor.hello_world - id: ha_hello_world_binary - - platform: homeassistant - entity_id: binary_sensor.hello - attribute: world - id: ha_hello_world_binary_attribute - -sensor: - - platform: homeassistant - entity_id: sensor.hello_world - id: ha_hello_world - - platform: homeassistant - entity_id: climate.living_room - attribute: temperature - id: ha_hello_world_temperature - -text_sensor: - - platform: homeassistant - entity_id: sensor.hello_world - id: ha_hello_world_text - - platform: homeassistant - entity_id: sensor.hello_world1 - id: ha_hello_world_text2 - attribute: some_attribute - -time: - - platform: homeassistant - on_time: - - at: "16:00:00" - then: - - logger.log: It's 16:00 +packages: + common: !include common.yaml diff --git a/tests/components/homeassistant/test.esp32-c3.yaml b/tests/components/homeassistant/test.esp32-c3.yaml index d2608f077c..25cb37a0b4 100644 --- a/tests/components/homeassistant/test.esp32-c3.yaml +++ b/tests/components/homeassistant/test.esp32-c3.yaml @@ -1,39 +1,2 @@ -wifi: - ssid: MySSID - password: password1 - -api: - -binary_sensor: - - platform: homeassistant - entity_id: binary_sensor.hello_world - id: ha_hello_world_binary - - platform: homeassistant - entity_id: binary_sensor.hello - attribute: world - id: ha_hello_world_binary_attribute - -sensor: - - platform: homeassistant - entity_id: sensor.hello_world - id: ha_hello_world - - platform: homeassistant - entity_id: climate.living_room - attribute: temperature - id: ha_hello_world_temperature - -text_sensor: - - platform: homeassistant - entity_id: sensor.hello_world - id: ha_hello_world_text - - platform: homeassistant - entity_id: sensor.hello_world1 - id: ha_hello_world_text2 - attribute: some_attribute - -time: - - platform: homeassistant - on_time: - - at: "16:00:00" - then: - - logger.log: It's 16:00 +packages: + common: !include common.yaml diff --git a/tests/components/homeassistant/test.esp32-idf.yaml b/tests/components/homeassistant/test.esp32-idf.yaml index d2608f077c..25cb37a0b4 100644 --- a/tests/components/homeassistant/test.esp32-idf.yaml +++ b/tests/components/homeassistant/test.esp32-idf.yaml @@ -1,39 +1,2 @@ -wifi: - ssid: MySSID - password: password1 - -api: - -binary_sensor: - - platform: homeassistant - entity_id: binary_sensor.hello_world - id: ha_hello_world_binary - - platform: homeassistant - entity_id: binary_sensor.hello - attribute: world - id: ha_hello_world_binary_attribute - -sensor: - - platform: homeassistant - entity_id: sensor.hello_world - id: ha_hello_world - - platform: homeassistant - entity_id: climate.living_room - attribute: temperature - id: ha_hello_world_temperature - -text_sensor: - - platform: homeassistant - entity_id: sensor.hello_world - id: ha_hello_world_text - - platform: homeassistant - entity_id: sensor.hello_world1 - id: ha_hello_world_text2 - attribute: some_attribute - -time: - - platform: homeassistant - on_time: - - at: "16:00:00" - then: - - logger.log: It's 16:00 +packages: + common: !include common.yaml diff --git a/tests/components/homeassistant/test.esp32.yaml b/tests/components/homeassistant/test.esp32.yaml index d2608f077c..25cb37a0b4 100644 --- a/tests/components/homeassistant/test.esp32.yaml +++ b/tests/components/homeassistant/test.esp32.yaml @@ -1,39 +1,2 @@ -wifi: - ssid: MySSID - password: password1 - -api: - -binary_sensor: - - platform: homeassistant - entity_id: binary_sensor.hello_world - id: ha_hello_world_binary - - platform: homeassistant - entity_id: binary_sensor.hello - attribute: world - id: ha_hello_world_binary_attribute - -sensor: - - platform: homeassistant - entity_id: sensor.hello_world - id: ha_hello_world - - platform: homeassistant - entity_id: climate.living_room - attribute: temperature - id: ha_hello_world_temperature - -text_sensor: - - platform: homeassistant - entity_id: sensor.hello_world - id: ha_hello_world_text - - platform: homeassistant - entity_id: sensor.hello_world1 - id: ha_hello_world_text2 - attribute: some_attribute - -time: - - platform: homeassistant - on_time: - - at: "16:00:00" - then: - - logger.log: It's 16:00 +packages: + common: !include common.yaml diff --git a/tests/components/homeassistant/test.esp8266.yaml b/tests/components/homeassistant/test.esp8266.yaml index d2608f077c..25cb37a0b4 100644 --- a/tests/components/homeassistant/test.esp8266.yaml +++ b/tests/components/homeassistant/test.esp8266.yaml @@ -1,39 +1,2 @@ -wifi: - ssid: MySSID - password: password1 - -api: - -binary_sensor: - - platform: homeassistant - entity_id: binary_sensor.hello_world - id: ha_hello_world_binary - - platform: homeassistant - entity_id: binary_sensor.hello - attribute: world - id: ha_hello_world_binary_attribute - -sensor: - - platform: homeassistant - entity_id: sensor.hello_world - id: ha_hello_world - - platform: homeassistant - entity_id: climate.living_room - attribute: temperature - id: ha_hello_world_temperature - -text_sensor: - - platform: homeassistant - entity_id: sensor.hello_world - id: ha_hello_world_text - - platform: homeassistant - entity_id: sensor.hello_world1 - id: ha_hello_world_text2 - attribute: some_attribute - -time: - - platform: homeassistant - on_time: - - at: "16:00:00" - then: - - logger.log: It's 16:00 +packages: + common: !include common.yaml diff --git a/tests/components/homeassistant/test.rp2040.yaml b/tests/components/homeassistant/test.rp2040.yaml index d2608f077c..25cb37a0b4 100644 --- a/tests/components/homeassistant/test.rp2040.yaml +++ b/tests/components/homeassistant/test.rp2040.yaml @@ -1,39 +1,2 @@ -wifi: - ssid: MySSID - password: password1 - -api: - -binary_sensor: - - platform: homeassistant - entity_id: binary_sensor.hello_world - id: ha_hello_world_binary - - platform: homeassistant - entity_id: binary_sensor.hello - attribute: world - id: ha_hello_world_binary_attribute - -sensor: - - platform: homeassistant - entity_id: sensor.hello_world - id: ha_hello_world - - platform: homeassistant - entity_id: climate.living_room - attribute: temperature - id: ha_hello_world_temperature - -text_sensor: - - platform: homeassistant - entity_id: sensor.hello_world - id: ha_hello_world_text - - platform: homeassistant - entity_id: sensor.hello_world1 - id: ha_hello_world_text2 - attribute: some_attribute - -time: - - platform: homeassistant - on_time: - - at: "16:00:00" - then: - - logger.log: It's 16:00 +packages: + common: !include common.yaml From 86f9af13aa1642b58bf2759f2df984e38bc5f11a Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Mon, 15 Apr 2024 11:08:35 +1000 Subject: [PATCH 1238/2101] Fix no-release bug on ft6x36 (#6527) --- esphome/components/ft63x6/ft63x6.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/esphome/components/ft63x6/ft63x6.cpp b/esphome/components/ft63x6/ft63x6.cpp index fe64f76fac..e5f7613901 100644 --- a/esphome/components/ft63x6/ft63x6.cpp +++ b/esphome/components/ft63x6/ft63x6.cpp @@ -32,7 +32,7 @@ void FT63X6Touchscreen::setup() { if (this->interrupt_pin_ != nullptr) { this->interrupt_pin_->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP); this->interrupt_pin_->setup(); - this->attach_interrupt_(this->interrupt_pin_, gpio::INTERRUPT_FALLING_EDGE); + this->attach_interrupt_(this->interrupt_pin_, gpio::INTERRUPT_ANY_EDGE); } if (this->reset_pin_ != nullptr) { @@ -78,13 +78,12 @@ void FT63X6Touchscreen::update_touches() { uint16_t touch_id, x, y; uint8_t touches = this->read_touch_number_(); + ESP_LOGV(TAG, "Touches found: %d", touches); if ((touches == 0x00) || (touches == 0xff)) { // ESP_LOGD(TAG, "No touches detected"); return; } - ESP_LOGV(TAG, "Touches found: %d", touches); - for (auto point = 0; point < touches; point++) { if (((this->read_touch_event_(point)) & 0x01) == 0) { // checking event flag bit 6 if it is null touch_id = this->read_touch_id_(point); // id1 = 0 or 1 From ff0d33ffe32595402f5cbd4bd4b50853ec673a69 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 12 Apr 2024 10:19:49 +1200 Subject: [PATCH 1239/2101] Fix missing ifdefs in voice assistant (#6520) --- esphome/components/voice_assistant/voice_assistant.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index 34a26eec01..e68e00948e 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -729,6 +729,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { } void VoiceAssistant::on_audio(const api::VoiceAssistantAudio &msg) { +#ifdef USE_SPEAKER // We should never get to this function if there is no speaker anyway if (this->speaker_buffer_index_ + msg.data.length() < SPEAKER_BUFFER_SIZE) { memcpy(this->speaker_buffer_ + this->speaker_buffer_index_, msg.data.data(), msg.data.length()); this->speaker_buffer_index_ += msg.data.length(); @@ -737,6 +738,7 @@ void VoiceAssistant::on_audio(const api::VoiceAssistantAudio &msg) { } else { ESP_LOGE(TAG, "Cannot receive audio, buffer is full"); } +#endif } VoiceAssistant *global_voice_assistant = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) From ed02747ebc1d5808d13d7010d20116a758fd1447 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 15 Apr 2024 12:02:19 +1200 Subject: [PATCH 1240/2101] Fix project version longer than 30 characters breaking compilation (#6535) --- esphome/core/base_automation.h | 2 +- esphome/core/config.py | 1 + esphome/core/defines.h | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/esphome/core/base_automation.h b/esphome/core/base_automation.h index b0ae0aff84..1bf0efb9a4 100644 --- a/esphome/core/base_automation.h +++ b/esphome/core/base_automation.h @@ -134,7 +134,7 @@ class ProjectUpdateTrigger : public Trigger, public Component { uint32_t hash = fnv1_hash(ESPHOME_PROJECT_NAME); ESPPreferenceObject pref = global_preferences->make_preference(hash, true); char previous_version[30]; - char current_version[30] = ESPHOME_PROJECT_VERSION; + char current_version[30] = ESPHOME_PROJECT_VERSION_30; if (pref.load(&previous_version)) { int cmp = strcmp(previous_version, current_version); if (cmp < 0) { diff --git a/esphome/core/config.py b/esphome/core/config.py index 792f9da6dd..2d87796987 100644 --- a/esphome/core/config.py +++ b/esphome/core/config.py @@ -394,6 +394,7 @@ async def to_code(config): if project_conf := config.get(CONF_PROJECT): cg.add_define("ESPHOME_PROJECT_NAME", project_conf[CONF_NAME]) cg.add_define("ESPHOME_PROJECT_VERSION", project_conf[CONF_VERSION]) + cg.add_define("ESPHOME_PROJECT_VERSION_30", project_conf[CONF_VERSION][:30]) for conf in project_conf.get(CONF_ON_UPDATE, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID]) await cg.register_component(trigger, conf) diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 22153de5de..f13ae968f0 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -11,6 +11,7 @@ #define ESPHOME_BOARD "dummy_board" #define ESPHOME_PROJECT_NAME "dummy project" #define ESPHOME_PROJECT_VERSION "v2" +#define ESPHOME_PROJECT_VERSION_30 "v2" #define ESPHOME_VARIANT "ESP32" // Feature flags From 09fbddea21356d506f68b638c425818fd84df415 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Mon, 15 Apr 2024 11:08:35 +1000 Subject: [PATCH 1241/2101] Fix no-release bug on ft6x36 (#6527) --- esphome/components/ft63x6/ft63x6.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/esphome/components/ft63x6/ft63x6.cpp b/esphome/components/ft63x6/ft63x6.cpp index fe64f76fac..e5f7613901 100644 --- a/esphome/components/ft63x6/ft63x6.cpp +++ b/esphome/components/ft63x6/ft63x6.cpp @@ -32,7 +32,7 @@ void FT63X6Touchscreen::setup() { if (this->interrupt_pin_ != nullptr) { this->interrupt_pin_->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP); this->interrupt_pin_->setup(); - this->attach_interrupt_(this->interrupt_pin_, gpio::INTERRUPT_FALLING_EDGE); + this->attach_interrupt_(this->interrupt_pin_, gpio::INTERRUPT_ANY_EDGE); } if (this->reset_pin_ != nullptr) { @@ -78,13 +78,12 @@ void FT63X6Touchscreen::update_touches() { uint16_t touch_id, x, y; uint8_t touches = this->read_touch_number_(); + ESP_LOGV(TAG, "Touches found: %d", touches); if ((touches == 0x00) || (touches == 0xff)) { // ESP_LOGD(TAG, "No touches detected"); return; } - ESP_LOGV(TAG, "Touches found: %d", touches); - for (auto point = 0; point < touches; point++) { if (((this->read_touch_event_(point)) & 0x01) == 0) { // checking event flag bit 6 if it is null touch_id = this->read_touch_id_(point); // id1 = 0 or 1 From b6f1cfd69fbff80979f500d2fdd1fc3beb83dba9 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 15 Apr 2024 13:27:01 +1200 Subject: [PATCH 1242/2101] Bump version to 2024.4.0b3 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 08a1a42ea3..66da96bc82 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.4.0b2" +__version__ = "2024.4.0b3" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 6876c65edada3710687260c91302ccfa432d4f08 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Mon, 15 Apr 2024 07:13:31 +0200 Subject: [PATCH 1243/2101] Define `USE_PSRAM` (#6526) --- esphome/components/esp32_ble_tracker/esp32_ble_tracker.h | 5 +++-- esphome/components/psram/__init__.py | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h index 0d986804ce..76dee875c5 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h @@ -2,6 +2,7 @@ #include "esphome/core/automation.h" #include "esphome/core/component.h" +#include "esphome/core/defines.h" #include "esphome/core/helpers.h" #include @@ -248,11 +249,11 @@ class ESP32BLETracker : public Component, SemaphoreHandle_t scan_result_lock_; SemaphoreHandle_t scan_end_lock_; size_t scan_result_index_{0}; -#if CONFIG_SPIRAM +#ifdef USE_PSRAM const static u_int8_t SCAN_RESULT_BUFFER_SIZE = 32; #else const static u_int8_t SCAN_RESULT_BUFFER_SIZE = 16; -#endif // CONFIG_SPIRAM +#endif // USE_PSRAM esp_ble_gap_cb_param_t::ble_scan_result_evt_param *scan_result_buffer_; esp_bt_status_t scan_start_failed_{ESP_BT_STATUS_SUCCESS}; esp_bt_status_t scan_set_param_failed_{ESP_BT_STATUS_SUCCESS}; diff --git a/esphome/components/psram/__init__.py b/esphome/components/psram/__init__.py index f7a2ef7b92..796957c315 100644 --- a/esphome/components/psram/__init__.py +++ b/esphome/components/psram/__init__.py @@ -54,5 +54,7 @@ async def to_code(config): if CONF_SPEED in config: add_idf_sdkconfig_option(f"{SPIRAM_SPEEDS[config[CONF_SPEED]]}", True) + cg.add_define("USE_PSRAM") + var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) From b3f02e54cdb07e9536413c0933895fc1392f6386 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Apr 2024 08:58:10 +1200 Subject: [PATCH 1244/2101] Bump black from 24.2.0 to 24.4.0 (#6539) 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 8fb59683b4..f94b2a5c51 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,6 +1,6 @@ pylint==3.0.3 flake8==7.0.0 # also change in .pre-commit-config.yaml when updating -black==24.2.0 # also change in .pre-commit-config.yaml when updating +black==24.4.0 # also change in .pre-commit-config.yaml when updating pyupgrade==3.15.1 # also change in .pre-commit-config.yaml when updating pre-commit From cca5f818e53fea55df60668455dde3fd3580d0f2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Apr 2024 09:39:27 +1200 Subject: [PATCH 1245/2101] Bump peter-evans/create-pull-request from 6.0.2 to 6.0.3 (#6525) 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 c12f1f31b5..6d3449b84a 100644 --- a/.github/workflows/sync-device-classes.yml +++ b/.github/workflows/sync-device-classes.yml @@ -36,7 +36,7 @@ jobs: python ./script/sync-device_class.py - name: Commit changes - uses: peter-evans/create-pull-request@v6.0.2 + uses: peter-evans/create-pull-request@v6.0.3 with: commit-message: "Synchronise Device Classes from Home Assistant" committer: esphomebot From 27b286b57f832ed7f3b301f6616e912c0bdd5268 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 16 Apr 2024 09:42:15 +1200 Subject: [PATCH 1246/2101] Bump python version in sync-device-classes workflow to 3.12 for HA (#6541) --- .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 6d3449b84a..62b9c7df9b 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@v5.1.0 with: - python-version: 3.11 + python-version: 3.12 - name: Install Home Assistant run: | From 01419822f73e8784ed7047950c437b5416efb861 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Apr 2024 10:59:44 +1200 Subject: [PATCH 1247/2101] Bump pylint from 3.0.3 to 3.1.0 (#6287) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/font/__init__.py | 3 +-- esphome/components/time/__init__.py | 2 +- esphome/loader.py | 13 ++++++++++--- requirements_test.txt | 2 +- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/esphome/components/font/__init__.py b/esphome/components/font/__init__.py index 76eb05e6ad..b3a5beb199 100644 --- a/esphome/components/font/__init__.py +++ b/esphome/components/font/__init__.py @@ -400,8 +400,7 @@ class BitmapFontWrapper: for glyph in glyphs: mask = self.getmask(glyph, mode="1") _, height = mask.size - if height > max_height: - max_height = height + max_height = max(max_height, height) return (max_height, 0) diff --git a/esphome/components/time/__init__.py b/esphome/components/time/__init__.py index 2bb3a0cd63..c888705ba2 100644 --- a/esphome/components/time/__init__.py +++ b/esphome/components/time/__init__.py @@ -49,7 +49,7 @@ def _load_tzdata(iana_key: str) -> Optional[bytes]: package = "tzdata.zoneinfo." + package_loc.replace("/", ".") try: - return resources.read_binary(package, resource) + return (resources.files(package) / resource).read_bytes() except (FileNotFoundError, ModuleNotFoundError): return None diff --git a/esphome/loader.py b/esphome/loader.py index 40a38d0a14..e0457eb425 100644 --- a/esphome/loader.py +++ b/esphome/loader.py @@ -23,7 +23,9 @@ class FileResource: resource: str def path(self) -> ContextManager[Path]: - return importlib.resources.path(self.package, self.resource) + return importlib.resources.as_file( + importlib.resources.files(self.package) / self.resource + ) class ComponentManifest: @@ -101,10 +103,15 @@ class ComponentManifest: loaded .py file (does not look through subdirectories) """ ret = [] - for resource in importlib.resources.contents(self.package): + + for resource in ( + r.name + for r in importlib.resources.files(self.package).iterdir() + if r.is_file() + ): if Path(resource).suffix not in SOURCE_FILE_EXTENSIONS: continue - if not importlib.resources.is_resource(self.package, resource): + if not importlib.resources.files(self.package).joinpath(resource).is_file(): # Not a resource = this is a directory (yeah this is confusing) continue ret.append(FileResource(self.package, resource)) diff --git a/requirements_test.txt b/requirements_test.txt index f94b2a5c51..16e9ec7422 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,4 +1,4 @@ -pylint==3.0.3 +pylint==3.1.0 flake8==7.0.0 # also change in .pre-commit-config.yaml when updating black==24.4.0 # also change in .pre-commit-config.yaml when updating pyupgrade==3.15.1 # also change in .pre-commit-config.yaml when updating From 80488a2b721727f4bc9615263feb7515ae87728a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Apr 2024 19:34:56 +0000 Subject: [PATCH 1248/2101] Bump aioesphomeapi from 23.2.0 to 24.0.0 (#6544) 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 4abc4d98d2..7424267d08 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,7 +13,7 @@ platformio==6.1.13 # When updating platformio, also update Dockerfile esptool==4.7.0 click==8.1.7 esphome-dashboard==20240412.0 -aioesphomeapi==23.2.0 +aioesphomeapi==24.0.0 zeroconf==0.131.0 python-magic==0.4.27 ruamel.yaml==0.18.6 # dashboard_import From 7d99676fe88858ef29e7bd21c81eb5b1bebb8349 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Apr 2024 19:50:22 +0000 Subject: [PATCH 1249/2101] Bump pyupgrade from 3.15.1 to 3.15.2 (#6543) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- .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 7865c52abd..69aafd4d15 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -27,7 +27,7 @@ repos: - --branch=release - --branch=beta - repo: https://github.com/asottile/pyupgrade - rev: v3.15.1 + rev: v3.15.2 hooks: - id: pyupgrade args: [--py39-plus] diff --git a/requirements_test.txt b/requirements_test.txt index 16e9ec7422..767018d07a 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,7 +1,7 @@ pylint==3.1.0 flake8==7.0.0 # also change in .pre-commit-config.yaml when updating black==24.4.0 # also change in .pre-commit-config.yaml when updating -pyupgrade==3.15.1 # also change in .pre-commit-config.yaml when updating +pyupgrade==3.15.2 # also change in .pre-commit-config.yaml when updating pre-commit # Unit tests From 6a1ea0674469a5c487ee3b83da40e96f6dac792f Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 17 Apr 2024 11:04:10 +1200 Subject: [PATCH 1250/2101] Add enum option to typed_schema (#6546) * Add enum option to typed_schema * Assert keys all match --- esphome/config_validation.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/esphome/config_validation.py b/esphome/config_validation.py index 358608cd35..bc58979f33 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -1590,6 +1590,10 @@ def typed_schema(schemas, **kwargs): """Create a schema that has a key to distinguish between schemas""" key = kwargs.pop("key", CONF_TYPE) default_schema_option = kwargs.pop("default_type", None) + enum_mapping = kwargs.pop("enum", None) + if enum_mapping is not None: + assert isinstance(enum_mapping, dict) + assert set(enum_mapping.keys()) == set(schemas.keys()) key_validator = one_of(*schemas, **kwargs) def validator(value): @@ -1600,6 +1604,9 @@ def typed_schema(schemas, **kwargs): if schema_option is None: raise Invalid(f"{key} not specified!") key_v = key_validator(schema_option) + if enum_mapping is not None: + key_v = add_class_to_obj(key_v, core.EnumValue) + key_v.enum_value = enum_mapping[key_v] value = Schema(schemas[key_v])(value) value[key] = key_v return value From f2a12589f3619601ade5f698a9c2f75f1d980ba3 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 17 Apr 2024 13:08:27 +1200 Subject: [PATCH 1251/2101] Bump version to 2024.4.0 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 66da96bc82..76320e6c71 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.4.0b3" +__version__ = "2024.4.0" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 0af26fdfd41671b571755ea906c744f7d1a3fc2c Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 17 Apr 2024 14:43:29 +1200 Subject: [PATCH 1252/2101] Move esphome-fork startup script to main repo. (#6523) Co-authored-by: Blair McBride --- .../etc/cont-init.d/30-esphome-fork.sh | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100755 docker/ha-addon-rootfs/etc/cont-init.d/30-esphome-fork.sh diff --git a/docker/ha-addon-rootfs/etc/cont-init.d/30-esphome-fork.sh b/docker/ha-addon-rootfs/etc/cont-init.d/30-esphome-fork.sh new file mode 100755 index 0000000000..03dbb34c8f --- /dev/null +++ b/docker/ha-addon-rootfs/etc/cont-init.d/30-esphome-fork.sh @@ -0,0 +1,47 @@ +#!/usr/bin/with-contenv bashio +# ============================================================================== +# This file installs the user ESPHome fork if specified. +# The fork must be up to date with the latest ESPHome dev branch +# and have no conflicts. +# This config option only exists in the ESPHome Dev add-on. +# ============================================================================== + +declare esphome_fork + +if bashio::config.has_value 'esphome_fork'; then + esphome_fork=$(bashio::config 'esphome_fork') + # format: [username][/repository]:ref + if [[ "$esphome_fork" =~ ^(([^/]+)(/([^:]+))?:)?([^:/]+)$ ]]; then + username="${BASH_REMATCH[2]:-esphome}" + repository="${BASH_REMATCH[4]:-esphome}" + ref="${BASH_REMATCH[5]}" + else + bashio::exit.nok "Invalid esphome_fork format: $esphome_fork" + fi + full_url="https://github.com/${username}/${repository}/archive/${ref}.tar.gz" + bashio::log.info "Checking forked ESPHome" + dev_version=$(python3 -c "from esphome.const import __version__; print(__version__)") + bashio::log.info "Downloading ESPHome from fork '${esphome_fork}' (${full_url})..." + curl -L -o /tmp/esphome.tar.gz "${full_url}" -qq || + bashio::exit.nok "Failed downloading ESPHome fork." + bashio::log.info "Installing ESPHome from fork '${esphome_fork}' (${full_url})..." + rm -rf /esphome || bashio::exit.nok "Failed to remove ESPHome." + mkdir /esphome + tar -zxf /tmp/esphome.tar.gz -C /esphome --strip-components=1 || + bashio::exit.nok "Failed installing ESPHome from fork." + pip install -U -e /esphome || bashio::exit.nok "Failed installing ESPHome from fork." + rm -f /tmp/esphome.tar.gz + fork_version=$(python3 -c "from esphome.const import __version__; print(__version__)") + + if [[ "$fork_version" != "$dev_version" ]]; then + bashio::log.error "############################" + bashio::log.error "Uninstalled fork as version does not match" + bashio::log.error "Update (or ask the author to update) the branch" + bashio::log.error "This is important as the dev addon and the dev ESPHome" + bashio::log.error "branch can have changes that are not compatible with old forks" + bashio::log.error "and get reported as bugs which we cannot solve easily." + bashio::log.error "############################" + bashio::exit.nok + fi + bashio::log.info "Installed ESPHome from fork '${esphome_fork}' (${full_url})..." +fi From ca5d38f413f3b7d723ed376a2f7a0da968c95669 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 17 Apr 2024 15:32:19 +1200 Subject: [PATCH 1253/2101] Call workflow for addon with dev version (#6549) --- .github/workflows/release.yml | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7c0ec0270b..2e1177d13f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -17,14 +17,16 @@ jobs: runs-on: ubuntu-latest outputs: tag: ${{ steps.tag.outputs.tag }} + branch_build: ${{ steps.tag.outputs.branch_build }} steps: - uses: actions/checkout@v4.1.1 - name: Get tag id: tag # yamllint disable rule:line-length run: | - if [[ "$GITHUB_EVENT_NAME" = "release" ]]; then - TAG="${GITHUB_REF#refs/tags/}" + if [[ "${{ github.event_name }}" = "release" ]]; then + TAG="${{ github.event.release.tag_name}}" + BRANCH_BUILD="false" else TAG=$(cat esphome/const.py | sed -n -E "s/^__version__\s+=\s+\"(.+)\"$/\1/p") today="$(date --utc '+%Y%m%d')" @@ -32,9 +34,13 @@ jobs: BRANCH=${GITHUB_REF#refs/heads/} if [[ "$BRANCH" != "dev" ]]; then TAG="${TAG}-${BRANCH}" + BRANCH_BUILD="true" + else + BRANCH_BUILD="false" fi fi echo "tag=${TAG}" >> $GITHUB_OUTPUT + echo "branch_build=${BRANCH_BUILD}" >> $GITHUB_OUTPUT # yamllint enable rule:line-length deploy-pypi: @@ -197,22 +203,28 @@ jobs: $(printf '${{ steps.tags.outputs.image }}@sha256:%s ' *) deploy-ha-addon-repo: - if: github.repository == 'esphome/esphome' && github.event_name == 'release' + if: github.repository == 'esphome/esphome' && needs.init.outputs.branch_build == 'false' runs-on: ubuntu-latest - needs: [deploy-manifest] + needs: + - init + - deploy-manifest steps: - name: Trigger Workflow uses: actions/github-script@v7.0.1 with: github-token: ${{ secrets.DEPLOY_HA_ADDON_REPO_TOKEN }} script: | + let description = "ESPHome"; + if (context.eventName == "release") { + description = ${{ toJSON(github.event.release.body) }}; + } github.rest.actions.createWorkflowDispatch({ owner: "esphome", repo: "home-assistant-addon", workflow_id: "bump-version.yml", ref: "main", inputs: { - version: "${{ github.event.release.tag_name }}", - content: ${{ toJSON(github.event.release.body) }} + version: "${{ needs.init.outputs.tag }}", + content: description } }) From 83feae4eb2b043f63e710acdc2959143cb746fc8 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 17 Apr 2024 16:55:13 +1200 Subject: [PATCH 1254/2101] Use trusted publishing token for pypi (#6545) --- .github/workflows/release.yml | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2e1177d13f..72b06ab4fe 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -47,6 +47,9 @@ jobs: name: Build and publish to PyPi if: github.repository == 'esphome/esphome' && github.event_name == 'release' runs-on: ubuntu-latest + permissions: + contents: read + id-token: write steps: - uses: actions/checkout@v4.1.1 - name: Set up Python @@ -56,16 +59,11 @@ jobs: - name: Set up python environment env: ESPHOME_NO_VENV: 1 - run: | - script/setup - pip install twine + run: script/setup - name: Build run: python setup.py sdist bdist_wheel - - name: Upload - env: - TWINE_USERNAME: __token__ - TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }} - run: twine upload dist/* + - name: Publish + uses: pypa/gh-action-pypi-publish@v1.8.14 deploy-docker: name: Build ESPHome ${{ matrix.platform }} From 6104e7591eb02d1e530241998600c89c0a8a2869 Mon Sep 17 00:00:00 2001 From: luar123 <49960470+luar123@users.noreply.github.com> Date: Wed, 17 Apr 2024 06:57:26 +0200 Subject: [PATCH 1255/2101] Fix uart to work with new enum definition in esp-idf-v5.2.1 (#6487) --- esphome/components/logger/logger_esp32.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/esphome/components/logger/logger_esp32.cpp b/esphome/components/logger/logger_esp32.cpp index 740e086f92..b0f1051d34 100644 --- a/esphome/components/logger/logger_esp32.cpp +++ b/esphome/components/logger/logger_esp32.cpp @@ -120,30 +120,28 @@ 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_); break; case UART_SELECTION_UART1: this->uart_num_ = UART_NUM_1; + init_uart(this->uart_num_, baud_rate_, 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_); break; #endif #ifdef USE_LOGGER_USB_CDC case UART_SELECTION_USB_CDC: - this->uart_num_ = -1; break; #endif #ifdef USE_LOGGER_USB_SERIAL_JTAG case UART_SELECTION_USB_SERIAL_JTAG: - this->uart_num_ = -1; init_usb_serial_jtag_(); break; #endif } - if (this->uart_num_ >= 0) { - init_uart(this->uart_num_, baud_rate_, tx_buffer_size_); - } #endif // USE_ESP_IDF } From 717cea548f99b0953853378bdaec889d2c0812b4 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 17 Apr 2024 17:42:40 +1200 Subject: [PATCH 1256/2101] Housecleaning: Use walrus operator in datetime (#6552) --- esphome/components/datetime/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/datetime/__init__.py b/esphome/components/datetime/__init__.py index b255a27303..a22c60aae9 100644 --- a/esphome/components/datetime/__init__.py +++ b/esphome/components/datetime/__init__.py @@ -106,8 +106,8 @@ def datetime_schema(class_: MockObjClass) -> cv.Schema: async def setup_datetime_core_(var, config): await setup_entity(var, config) - if CONF_MQTT_ID in config: - mqtt_ = cg.new_Pvariable(config[CONF_MQTT_ID], var) + 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) for conf in config.get(CONF_ON_VALUE, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) From 2fc2d5839fabdd47fdf2154d4d216a9a8adc5b2b Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 17 Apr 2024 18:22:52 +1200 Subject: [PATCH 1257/2101] Housecleaning: Use walrus operator in text (#6560) --- esphome/components/text/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/text/__init__.py b/esphome/components/text/__init__.py index 21c23ce73b..c0140ff082 100644 --- a/esphome/components/text/__init__.py +++ b/esphome/components/text/__init__.py @@ -73,8 +73,8 @@ async def setup_text_core_( trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) await automation.build_automation(trigger, [(cg.std_string, "x")], conf) - if CONF_MQTT_ID in config: - mqtt_ = cg.new_Pvariable(config[CONF_MQTT_ID], var) + 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) From 3f015562d7109d3c245fcf38ab9bc150390dbce8 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 17 Apr 2024 18:26:36 +1200 Subject: [PATCH 1258/2101] Housecleaning: Use walrus operator in light (#6556) --- esphome/components/light/__init__.py | 34 +++++++++++++--------------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/esphome/components/light/__init__.py b/esphome/components/light/__init__.py index ba3a26ebe5..fdc4676758 100644 --- a/esphome/components/light/__init__.py +++ b/esphome/components/light/__init__.py @@ -137,18 +137,16 @@ async def setup_light_core_(light_var, output_var, config): cg.add(light_var.set_restore_mode(config[CONF_RESTORE_MODE])) - if CONF_DEFAULT_TRANSITION_LENGTH in config: - cg.add( - light_var.set_default_transition_length( - config[CONF_DEFAULT_TRANSITION_LENGTH] - ) - ) - if CONF_FLASH_TRANSITION_LENGTH in config: - cg.add( - light_var.set_flash_transition_length(config[CONF_FLASH_TRANSITION_LENGTH]) - ) - if CONF_GAMMA_CORRECT in config: - cg.add(light_var.set_gamma_correct(config[CONF_GAMMA_CORRECT])) + if ( + default_transition_length := config.get(CONF_DEFAULT_TRANSITION_LENGTH) + ) is not None: + cg.add(light_var.set_default_transition_length(default_transition_length)) + if ( + flash_transition_length := config.get(CONF_FLASH_TRANSITION_LENGTH) + ) is not None: + 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)) effects = await cg.build_registry_list( EFFECTS_REGISTRY, config.get(CONF_EFFECTS, []) ) @@ -164,15 +162,15 @@ async def setup_light_core_(light_var, output_var, config): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], light_var) await auto.build_automation(trigger, [], conf) - if CONF_COLOR_CORRECT in config: - cg.add(output_var.set_correction(*config[CONF_COLOR_CORRECT])) + if (color_correct := config.get(CONF_COLOR_CORRECT)) is not None: + cg.add(output_var.set_correction(*color_correct)) - if CONF_POWER_SUPPLY in config: - var_ = await cg.get_variable(config[CONF_POWER_SUPPLY]) + if (power_supply_id := config.get(CONF_POWER_SUPPLY)) is not None: + var_ = await cg.get_variable(power_supply_id) cg.add(output_var.set_power_supply(var_)) - if CONF_MQTT_ID in config: - mqtt_ = cg.new_Pvariable(config[CONF_MQTT_ID], light_var) + if (mqtt_id := config.get(CONF_MQTT_ID)) is not None: + mqtt_ = cg.new_Pvariable(mqtt_id, light_var) await mqtt.register_mqtt_component(mqtt_, config) From 8eff3435e74194a02aa5b16c2508e996c1c90416 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 17 Apr 2024 18:26:49 +1200 Subject: [PATCH 1259/2101] Housecleaning: Use walrus operator in select (#6557) --- esphome/components/select/__init__.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/esphome/components/select/__init__.py b/esphome/components/select/__init__.py index 760f7600b7..7ad14f2440 100644 --- a/esphome/components/select/__init__.py +++ b/esphome/components/select/__init__.py @@ -95,8 +95,8 @@ async def setup_select_core_(var, config, *, options: list[str]): trigger, [(cg.std_string, "x"), (cg.size_t, "i")], conf ) - if CONF_MQTT_ID in config: - mqtt_ = cg.new_Pvariable(config[CONF_MQTT_ID], var) + 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) @@ -223,14 +223,14 @@ async def select_set_index_to_code(config, action_id, template_arg, args): async def select_operation_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_OPERATION in config: - op_ = await cg.templatable(config[CONF_OPERATION], args, SelectOperation) + if (operation := config.get(CONF_OPERATION)) is not None: + op_ = await cg.templatable(operation, args, SelectOperation) cg.add(var.set_operation(op_)) - if CONF_CYCLE in config: - cycle_ = await cg.templatable(config[CONF_CYCLE], args, bool) - cg.add(var.set_cycle(cycle_)) - if CONF_MODE in config: - cg.add(var.set_operation(SELECT_OPERATION_OPTIONS[config[CONF_MODE]])) - if CONF_CYCLE in config: - cg.add(var.set_cycle(config[CONF_CYCLE])) + if (cycle := config.get(CONF_CYCLE)) is not None: + template_ = await cg.templatable(cycle, args, bool) + cg.add(var.set_cycle(template_)) + if (mode := config.get(CONF_MODE)) is not None: + cg.add(var.set_operation(SELECT_OPERATION_OPTIONS[mode])) + if (cycle := config.get(CONF_CYCLE)) is not None: + cg.add(var.set_cycle(cycle)) return var From 21e3faad3876fdbc194b344da4bace6ff01d82d7 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 17 Apr 2024 18:27:04 +1200 Subject: [PATCH 1260/2101] Housecleaning: Use walrus operator in number (#6561) --- esphome/components/number/__init__.py | 39 ++++++++++++++------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/esphome/components/number/__init__.py b/esphome/components/number/__init__.py index ecc2ab2ee7..6d7ec97c90 100644 --- a/esphome/components/number/__init__.py +++ b/esphome/components/number/__init__.py @@ -239,13 +239,14 @@ async def setup_number_core_( cg.add(trigger.set_max(template_)) await automation.build_automation(trigger, [(float, "x")], conf) - if CONF_UNIT_OF_MEASUREMENT in config: - cg.add(var.traits.set_unit_of_measurement(config[CONF_UNIT_OF_MEASUREMENT])) - if CONF_MQTT_ID in config: - mqtt_ = cg.new_Pvariable(config[CONF_MQTT_ID], var) + 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)) + + 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) - if CONF_DEVICE_CLASS in config: - cg.add(var.traits.set_device_class(config[CONF_DEVICE_CLASS])) async def register_number( @@ -284,10 +285,10 @@ async def number_in_range_to_code(config, condition_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) var = cg.new_Pvariable(condition_id, template_arg, paren) - if CONF_ABOVE in config: - cg.add(var.set_min(config[CONF_ABOVE])) - if CONF_BELOW in config: - cg.add(var.set_max(config[CONF_BELOW])) + if (above := config.get(CONF_ABOVE)) is not None: + cg.add(var.set_min(above)) + if (below := config.get(CONF_BELOW)) is not None: + cg.add(var.set_max(below)) return var @@ -391,14 +392,14 @@ async def number_set_to_code(config, action_id, template_arg, args): async def number_to_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_OPERATION in config: - to_ = await cg.templatable(config[CONF_OPERATION], args, NumberOperation) + if (operation := config.get(CONF_OPERATION)) is not None: + to_ = await cg.templatable(operation, args, NumberOperation) cg.add(var.set_operation(to_)) - if CONF_CYCLE in config: - cycle_ = await cg.templatable(config[CONF_CYCLE], args, bool) - cg.add(var.set_cycle(cycle_)) - if CONF_MODE in config: - cg.add(var.set_operation(NUMBER_OPERATION_OPTIONS[config[CONF_MODE]])) - if CONF_CYCLE in config: - cg.add(var.set_cycle(config[CONF_CYCLE])) + if (cycle := config.get(CONF_CYCLE)) is not None: + template_ = await cg.templatable(cycle, args, bool) + cg.add(var.set_cycle(template_)) + if (mode := config.get(CONF_MODE)) is not None: + cg.add(var.set_operation(NUMBER_OPERATION_OPTIONS[mode])) + if (cycle := config.get(CONF_CYCLE)) is not None: + cg.add(var.set_cycle(cycle)) return var From fa1adf752816555e28fc4a055161430730d26c8a Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 17 Apr 2024 18:28:01 +1200 Subject: [PATCH 1261/2101] Housecleaning: Use walrus operator in cover (#6562) --- esphome/components/cover/__init__.py | 48 +++++++++++++--------------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/esphome/components/cover/__init__.py b/esphome/components/cover/__init__.py index 90e5ee1f03..8e0371017d 100644 --- a/esphome/components/cover/__init__.py +++ b/esphome/components/cover/__init__.py @@ -122,8 +122,8 @@ COVER_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA).ex async def setup_cover_core_(var, config): await setup_entity(var, config) - if CONF_DEVICE_CLASS in config: - cg.add(var.set_device_class(config[CONF_DEVICE_CLASS])) + 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) @@ -132,24 +132,20 @@ async def setup_cover_core_(var, config): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) await automation.build_automation(trigger, [], conf) - if CONF_MQTT_ID in config: - mqtt_ = cg.new_Pvariable(config[CONF_MQTT_ID], var) + 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) - if CONF_POSITION_STATE_TOPIC in config: - cg.add( - mqtt_.set_custom_position_state_topic(config[CONF_POSITION_STATE_TOPIC]) - ) - if CONF_POSITION_COMMAND_TOPIC in config: - cg.add( - mqtt_.set_custom_position_command_topic( - config[CONF_POSITION_COMMAND_TOPIC] - ) - ) - if CONF_TILT_STATE_TOPIC in config: - cg.add(mqtt_.set_custom_tilt_state_topic(config[CONF_TILT_STATE_TOPIC])) - if CONF_TILT_COMMAND_TOPIC in config: - cg.add(mqtt_.set_custom_tilt_command_topic(config[CONF_TILT_COMMAND_TOPIC])) + if (position_state_topic := config.get(CONF_POSITION_STATE_TOPIC)) is not None: + cg.add(mqtt_.set_custom_position_state_topic(position_state_topic)) + if ( + position_command_topic := config.get(CONF_POSITION_COMMAND_TOPIC) + ) is not None: + cg.add(mqtt_.set_custom_position_command_topic(position_command_topic)) + 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: + cg.add(mqtt_.set_custom_tilt_command_topic(tilt_command_topic)) async def register_cover(var, config): @@ -205,17 +201,17 @@ COVER_CONTROL_ACTION_SCHEMA = cv.Schema( 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) - if CONF_STOP in config: - template_ = await cg.templatable(config[CONF_STOP], args, bool) + if (stop := config.get(CONF_STOP)) is not None: + template_ = await cg.templatable(stop, args, bool) cg.add(var.set_stop(template_)) - if CONF_STATE in config: - template_ = await cg.templatable(config[CONF_STATE], args, float) + if (state := config.get(CONF_STATE)) is not None: + template_ = await cg.templatable(state, args, float) cg.add(var.set_position(template_)) - if CONF_POSITION in config: - template_ = await cg.templatable(config[CONF_POSITION], args, float) + if (position := config.get(CONF_POSITION)) is not None: + template_ = await cg.templatable(position, args, float) cg.add(var.set_position(template_)) - if CONF_TILT in config: - template_ = await cg.templatable(config[CONF_TILT], args, float) + if (tilt := config.get(CONF_TILT)) is not None: + template_ = await cg.templatable(tilt, args, float) cg.add(var.set_tilt(template_)) return var From 77ade12ee9e3a62b708fad712d90e9364a9cedfa Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 17 Apr 2024 18:58:20 +1200 Subject: [PATCH 1262/2101] Housecleaning: Use walrus operator in climate (#6551) --- esphome/components/climate/__init__.py | 218 +++++++++++++------------ 1 file changed, 118 insertions(+), 100 deletions(-) diff --git a/esphome/components/climate/__init__.py b/esphome/components/climate/__init__.py index c9c3900a0c..7b0a27feae 100644 --- a/esphome/components/climate/__init__.py +++ b/esphome/components/climate/__init__.py @@ -244,122 +244,150 @@ async def setup_climate_core_(var, config): await setup_entity(var, config) visual = config[CONF_VISUAL] - if CONF_MIN_TEMPERATURE in visual: - cg.add(var.set_visual_min_temperature_override(visual[CONF_MIN_TEMPERATURE])) - if CONF_MAX_TEMPERATURE in visual: - cg.add(var.set_visual_max_temperature_override(visual[CONF_MAX_TEMPERATURE])) - if CONF_TEMPERATURE_STEP in visual: + if (min_temp := visual.get(CONF_MIN_TEMPERATURE)) is not None: + cg.add(var.set_visual_min_temperature_override(min_temp)) + if (max_temp := visual.get(CONF_MAX_TEMPERATURE)) is not None: + cg.add(var.set_visual_max_temperature_override(max_temp)) + if (temp_step := visual.get(CONF_TEMPERATURE_STEP)) is not None: cg.add( var.set_visual_temperature_step_override( - visual[CONF_TEMPERATURE_STEP][CONF_TARGET_TEMPERATURE], - visual[CONF_TEMPERATURE_STEP][CONF_CURRENT_TEMPERATURE], + temp_step[CONF_TARGET_TEMPERATURE], + temp_step[CONF_CURRENT_TEMPERATURE], ) ) - if CONF_MIN_HUMIDITY in visual: - cg.add(var.set_visual_min_humidity_override(visual[CONF_MIN_HUMIDITY])) - if CONF_MAX_HUMIDITY in visual: - cg.add(var.set_visual_max_humidity_override(visual[CONF_MAX_HUMIDITY])) + if (min_humidity := visual.get(CONF_MIN_HUMIDITY)) is not None: + cg.add(var.set_visual_min_humidity_override(min_humidity)) + if (max_humidity := visual.get(CONF_MAX_HUMIDITY)) is not None: + cg.add(var.set_visual_max_humidity_override(max_humidity)) - if CONF_MQTT_ID in config: - mqtt_ = cg.new_Pvariable(config[CONF_MQTT_ID], var) + 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) - if CONF_ACTION_STATE_TOPIC in config: - cg.add(mqtt_.set_custom_action_state_topic(config[CONF_ACTION_STATE_TOPIC])) - if CONF_AWAY_COMMAND_TOPIC in config: - cg.add(mqtt_.set_custom_away_command_topic(config[CONF_AWAY_COMMAND_TOPIC])) - if CONF_AWAY_STATE_TOPIC in config: - cg.add(mqtt_.set_custom_away_state_topic(config[CONF_AWAY_STATE_TOPIC])) - if CONF_CURRENT_TEMPERATURE_STATE_TOPIC in config: + if (action_state_topic := config.get(CONF_ACTION_STATE_TOPIC)) is not None: + cg.add(mqtt_.set_custom_action_state_topic(action_state_topic)) + if (away_command_topic := config.get(CONF_AWAY_COMMAND_TOPIC)) is not None: + cg.add(mqtt_.set_custom_away_command_topic(away_command_topic)) + if (away_state_topic := config.get(CONF_AWAY_STATE_TOPIC)) is not None: + cg.add(mqtt_.set_custom_away_state_topic(away_state_topic)) + if ( + current_temperature_state_topic := config.get( + CONF_CURRENT_TEMPERATURE_STATE_TOPIC + ) + ) is not None: cg.add( mqtt_.set_custom_current_temperature_state_topic( - config[CONF_CURRENT_TEMPERATURE_STATE_TOPIC] + current_temperature_state_topic ) ) - if CONF_CURRENT_HUMIDITY_STATE_TOPIC in config: + if ( + current_humidity_state_topic := config.get( + CONF_CURRENT_HUMIDITY_STATE_TOPIC + ) + ) is not None: cg.add( mqtt_.set_custom_current_humidity_state_topic( - config[CONF_CURRENT_HUMIDITY_STATE_TOPIC] + current_humidity_state_topic ) ) - if CONF_FAN_MODE_COMMAND_TOPIC in config: - cg.add( - mqtt_.set_custom_fan_mode_command_topic( - config[CONF_FAN_MODE_COMMAND_TOPIC] - ) + if ( + fan_mode_command_topic := config.get(CONF_FAN_MODE_COMMAND_TOPIC) + ) is not None: + cg.add(mqtt_.set_custom_fan_mode_command_topic(fan_mode_command_topic)) + if (fan_mode_state_topic := config.get(CONF_FAN_MODE_STATE_TOPIC)) is not None: + cg.add(mqtt_.set_custom_fan_mode_state_topic(fan_mode_state_topic)) + if (mode_command_topic := config.get(CONF_MODE_COMMAND_TOPIC)) is not None: + cg.add(mqtt_.set_custom_mode_command_topic(mode_command_topic)) + if (mode_state_topic := config.get(CONF_MODE_STATE_TOPIC)) is not None: + cg.add(mqtt_.set_custom_mode_state_topic(mode_state_topic)) + if (preset_command_topic := config.get(CONF_PRESET_COMMAND_TOPIC)) is not None: + cg.add(mqtt_.set_custom_preset_command_topic(preset_command_topic)) + if (preset_state_topic := config.get(CONF_PRESET_STATE_TOPIC)) is not None: + cg.add(mqtt_.set_custom_preset_state_topic(preset_state_topic)) + if ( + swing_mode_command_topic := config.get(CONF_SWING_MODE_COMMAND_TOPIC) + ) is not None: + cg.add(mqtt_.set_custom_swing_mode_command_topic(swing_mode_command_topic)) + if ( + swing_mode_state_topic := config.get(CONF_SWING_MODE_STATE_TOPIC) + ) is not None: + cg.add(mqtt_.set_custom_swing_mode_state_topic(swing_mode_state_topic)) + if ( + target_temperature_command_topic := config.get( + CONF_TARGET_TEMPERATURE_COMMAND_TOPIC ) - if CONF_FAN_MODE_STATE_TOPIC in config: - cg.add( - mqtt_.set_custom_fan_mode_state_topic(config[CONF_FAN_MODE_STATE_TOPIC]) - ) - if CONF_MODE_COMMAND_TOPIC in config: - cg.add(mqtt_.set_custom_mode_command_topic(config[CONF_MODE_COMMAND_TOPIC])) - if CONF_MODE_STATE_TOPIC in config: - cg.add(mqtt_.set_custom_mode_state_topic(config[CONF_MODE_STATE_TOPIC])) - if CONF_PRESET_COMMAND_TOPIC in config: - cg.add( - mqtt_.set_custom_preset_command_topic(config[CONF_PRESET_COMMAND_TOPIC]) - ) - if CONF_PRESET_STATE_TOPIC in config: - cg.add(mqtt_.set_custom_preset_state_topic(config[CONF_PRESET_STATE_TOPIC])) - if CONF_SWING_MODE_COMMAND_TOPIC in config: - cg.add( - mqtt_.set_custom_swing_mode_command_topic( - config[CONF_SWING_MODE_COMMAND_TOPIC] - ) - ) - if CONF_SWING_MODE_STATE_TOPIC in config: - cg.add( - mqtt_.set_custom_swing_mode_state_topic( - config[CONF_SWING_MODE_STATE_TOPIC] - ) - ) - if CONF_TARGET_TEMPERATURE_COMMAND_TOPIC in config: + ) is not None: cg.add( mqtt_.set_custom_target_temperature_command_topic( - config[CONF_TARGET_TEMPERATURE_COMMAND_TOPIC] + target_temperature_command_topic ) ) - if CONF_TARGET_TEMPERATURE_STATE_TOPIC in config: + if ( + target_temperature_state_topic := config.get( + CONF_TARGET_TEMPERATURE_STATE_TOPIC + ) + ) is not None: cg.add( mqtt_.set_custom_target_temperature_state_topic( - config[CONF_TARGET_TEMPERATURE_STATE_TOPIC] + target_temperature_state_topic ) ) - if CONF_TARGET_TEMPERATURE_HIGH_COMMAND_TOPIC in config: + if ( + target_temperature_high_command_topic := config.get( + CONF_TARGET_TEMPERATURE_HIGH_COMMAND_TOPIC + ) + ) is not None: cg.add( mqtt_.set_custom_target_temperature_high_command_topic( - config[CONF_TARGET_TEMPERATURE_HIGH_COMMAND_TOPIC] + target_temperature_high_command_topic ) ) - if CONF_TARGET_TEMPERATURE_HIGH_STATE_TOPIC in config: + if ( + target_temperature_high_state_topic := config.get( + CONF_TARGET_TEMPERATURE_HIGH_STATE_TOPIC + ) + ) is not None: cg.add( mqtt_.set_custom_target_temperature_high_state_topic( - config[CONF_TARGET_TEMPERATURE_HIGH_STATE_TOPIC] + target_temperature_high_state_topic ) ) - if CONF_TARGET_TEMPERATURE_LOW_COMMAND_TOPIC in config: + if ( + target_temperature_low_command_topic := config.get( + CONF_TARGET_TEMPERATURE_LOW_COMMAND_TOPIC + ) + ) is not None: cg.add( mqtt_.set_custom_target_temperature_low_command_topic( - config[CONF_TARGET_TEMPERATURE_LOW_COMMAND_TOPIC] + target_temperature_low_command_topic ) ) - if CONF_TARGET_TEMPERATURE_LOW_STATE_TOPIC in config: + if ( + target_temperature_low_state_topic := config.get( + CONF_TARGET_TEMPERATURE_LOW_STATE_TOPIC + ) + ) is not None: cg.add( mqtt_.set_custom_target_temperature_state_topic( - config[CONF_TARGET_TEMPERATURE_LOW_STATE_TOPIC] + target_temperature_low_state_topic ) ) - if CONF_TARGET_HUMIDITY_COMMAND_TOPIC in config: + if ( + target_humidity_command_topic := config.get( + CONF_TARGET_HUMIDITY_COMMAND_TOPIC + ) + ) is not None: cg.add( mqtt_.set_custom_target_humidity_command_topic( - config[CONF_TARGET_HUMIDITY_COMMAND_TOPIC] + target_humidity_command_topic ) ) - if CONF_TARGET_HUMIDITY_STATE_TOPIC in config: + if ( + target_humidity_state_topic := config.get(CONF_TARGET_HUMIDITY_STATE_TOPIC) + ) is not None: cg.add( mqtt_.set_custom_target_humidity_state_topic( - config[CONF_TARGET_HUMIDITY_STATE_TOPIC] + target_humidity_state_topic ) ) @@ -411,45 +439,35 @@ CLIMATE_CONTROL_ACTION_SCHEMA = cv.Schema( async def climate_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_MODE in config: - template_ = await cg.templatable(config[CONF_MODE], args, ClimateMode) + if (mode := config.get(CONF_MODE)) is not None: + template_ = await cg.templatable(mode, args, ClimateMode) cg.add(var.set_mode(template_)) - if CONF_TARGET_TEMPERATURE in config: - template_ = await cg.templatable(config[CONF_TARGET_TEMPERATURE], args, float) + if (target_temp := config.get(CONF_TARGET_TEMPERATURE)) is not None: + template_ = await cg.templatable(target_temp, args, float) cg.add(var.set_target_temperature(template_)) - if CONF_TARGET_TEMPERATURE_LOW in config: - template_ = await cg.templatable( - config[CONF_TARGET_TEMPERATURE_LOW], args, float - ) + if (target_temp_low := config.get(CONF_TARGET_TEMPERATURE_LOW)) is not None: + template_ = await cg.templatable(target_temp_low, args, float) cg.add(var.set_target_temperature_low(template_)) - if CONF_TARGET_TEMPERATURE_HIGH in config: - template_ = await cg.templatable( - config[CONF_TARGET_TEMPERATURE_HIGH], args, float - ) + if (target_temp_high := config.get(CONF_TARGET_TEMPERATURE_HIGH)) is not None: + template_ = await cg.templatable(target_temp_high, args, float) cg.add(var.set_target_temperature_high(template_)) - if CONF_TARGET_HUMIDITY in config: - template_ = await cg.templatable(config[CONF_TARGET_HUMIDITY], args, float) + if (target_humidity := config.get(CONF_TARGET_HUMIDITY)) is not None: + template_ = await cg.templatable(target_humidity, args, float) cg.add(var.set_target_humidity(template_)) - if CONF_FAN_MODE in config: - template_ = await cg.templatable(config[CONF_FAN_MODE], args, ClimateFanMode) + if (fan_mode := config.get(CONF_FAN_MODE)) is not None: + template_ = await cg.templatable(fan_mode, args, ClimateFanMode) cg.add(var.set_fan_mode(template_)) - if CONF_CUSTOM_FAN_MODE in config: - template_ = await cg.templatable( - config[CONF_CUSTOM_FAN_MODE], args, cg.std_string - ) + if (custom_fan_mode := config.get(CONF_CUSTOM_FAN_MODE)) is not None: + template_ = await cg.templatable(custom_fan_mode, args, cg.std_string) cg.add(var.set_custom_fan_mode(template_)) - if CONF_PRESET in config: - template_ = await cg.templatable(config[CONF_PRESET], args, ClimatePreset) + if (preset := config.get(CONF_PRESET)) is not None: + template_ = await cg.templatable(preset, args, ClimatePreset) cg.add(var.set_preset(template_)) - if CONF_CUSTOM_PRESET in config: - template_ = await cg.templatable( - config[CONF_CUSTOM_PRESET], args, cg.std_string - ) + if (custom_preset := config.get(CONF_CUSTOM_PRESET)) is not None: + template_ = await cg.templatable(custom_preset, args, cg.std_string) cg.add(var.set_custom_preset(template_)) - if CONF_SWING_MODE in config: - template_ = await cg.templatable( - config[CONF_SWING_MODE], args, ClimateSwingMode - ) + if (swing_mode := config.get(CONF_SWING_MODE)) is not None: + template_ = await cg.templatable(swing_mode, args, ClimateSwingMode) cg.add(var.set_swing_mode(template_)) return var From 214c237c8dc978970fcff7cf958043c3abe36ef2 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 17 Apr 2024 19:03:57 +1200 Subject: [PATCH 1263/2101] Housecleaning: Use walrus operator in fan (#6555) Co-authored-by: Keith Burzinski --- esphome/components/fan/__init__.py | 62 ++++++++++++++---------------- 1 file changed, 28 insertions(+), 34 deletions(-) diff --git a/esphome/components/fan/__init__.py b/esphome/components/fan/__init__.py index 05e276d987..14cf6cc9c9 100644 --- a/esphome/components/fan/__init__.py +++ b/esphome/components/fan/__init__.py @@ -180,40 +180,34 @@ async def setup_fan_core_(var, config): cg.add(var.set_restore_mode(config[CONF_RESTORE_MODE])) - if CONF_MQTT_ID in config: - mqtt_ = cg.new_Pvariable(config[CONF_MQTT_ID], var) + 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) - if CONF_OSCILLATION_STATE_TOPIC in config: + if ( + oscillation_state_topic := config.get(CONF_OSCILLATION_STATE_TOPIC) + ) is not None: + cg.add(mqtt_.set_custom_oscillation_state_topic(oscillation_state_topic)) + if ( + oscillation_command_topic := config.get(CONF_OSCILLATION_COMMAND_TOPIC) + ) is not None: cg.add( - mqtt_.set_custom_oscillation_state_topic( - config[CONF_OSCILLATION_STATE_TOPIC] - ) + mqtt_.set_custom_oscillation_command_topic(oscillation_command_topic) ) - if CONF_OSCILLATION_COMMAND_TOPIC in config: + if ( + speed_level_state_topic := config.get(CONF_SPEED_LEVEL_STATE_TOPIC) + ) is not None: + cg.add(mqtt_.set_custom_speed_level_state_topic(speed_level_state_topic)) + if ( + speed_level_command_topic := config.get(CONF_SPEED_LEVEL_COMMAND_TOPIC) + ) is not None: cg.add( - mqtt_.set_custom_oscillation_command_topic( - config[CONF_OSCILLATION_COMMAND_TOPIC] - ) - ) - if CONF_SPEED_LEVEL_STATE_TOPIC in config: - cg.add( - mqtt_.set_custom_speed_level_state_topic( - config[CONF_SPEED_LEVEL_STATE_TOPIC] - ) - ) - if CONF_SPEED_LEVEL_COMMAND_TOPIC in config: - cg.add( - mqtt_.set_custom_speed_level_command_topic( - config[CONF_SPEED_LEVEL_COMMAND_TOPIC] - ) - ) - if CONF_SPEED_STATE_TOPIC in config: - cg.add(mqtt_.set_custom_speed_state_topic(config[CONF_SPEED_STATE_TOPIC])) - if CONF_SPEED_COMMAND_TOPIC in config: - cg.add( - mqtt_.set_custom_speed_command_topic(config[CONF_SPEED_COMMAND_TOPIC]) + mqtt_.set_custom_speed_level_command_topic(speed_level_command_topic) ) + if (speed_state_topic := config.get(CONF_SPEED_STATE_TOPIC)) is not None: + cg.add(mqtt_.set_custom_speed_state_topic(speed_state_topic)) + if (speed_command_topic := config.get(CONF_SPEED_COMMAND_TOPIC)) is not None: + cg.add(mqtt_.set_custom_speed_command_topic(speed_command_topic)) for conf in config.get(CONF_ON_STATE, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) @@ -288,14 +282,14 @@ async def fan_turn_off_to_code(config, action_id, template_arg, args): async def fan_turn_on_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_OSCILLATING in config: - template_ = await cg.templatable(config[CONF_OSCILLATING], args, bool) + if (oscillating := config.get(CONF_OSCILLATING)) is not None: + template_ = await cg.templatable(oscillating, args, bool) cg.add(var.set_oscillating(template_)) - if CONF_SPEED in config: - template_ = await cg.templatable(config[CONF_SPEED], args, int) + if (speed := config.get(CONF_SPEED)) is not None: + template_ = await cg.templatable(speed, args, int) cg.add(var.set_speed(template_)) - if CONF_DIRECTION in config: - template_ = await cg.templatable(config[CONF_DIRECTION], args, FanDirection) + if (direction := config.get(CONF_DIRECTION)) is not None: + template_ = await cg.templatable(direction, args, FanDirection) cg.add(var.set_direction(template_)) return var From 7733781e091199d3638e1fa78a181eefff4b2b19 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 17 Apr 2024 19:51:33 +1200 Subject: [PATCH 1264/2101] Housecleaning: Use walrus operator in text_sensor (#6559) --- esphome/components/text_sensor/__init__.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/text_sensor/__init__.py b/esphome/components/text_sensor/__init__.py index cf7d23aec7..6c28b57b3d 100644 --- a/esphome/components/text_sensor/__init__.py +++ b/esphome/components/text_sensor/__init__.py @@ -186,8 +186,8 @@ async def build_filters(config): async def setup_text_sensor_core_(var, config): await setup_entity(var, config) - if CONF_DEVICE_CLASS in config: - cg.add(var.set_device_class(config[CONF_DEVICE_CLASS])) + if (device_class := config.get(CONF_DEVICE_CLASS)) is not None: + cg.add(var.set_device_class(device_class)) if config.get(CONF_FILTERS): # must exist and not be empty filters = await build_filters(config[CONF_FILTERS]) @@ -201,8 +201,8 @@ async def setup_text_sensor_core_(var, config): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) await automation.build_automation(trigger, [(cg.std_string, "x")], conf) - if CONF_MQTT_ID in config: - mqtt_ = cg.new_Pvariable(config[CONF_MQTT_ID], var) + 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) From 987ffcbaba01be4642c36b68fc14e02bae553103 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 17 Apr 2024 16:09:42 -0500 Subject: [PATCH 1265/2101] Bump zeroconf to 0.132.2 (#6548) --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 7424267d08..68041675f6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -14,7 +14,7 @@ esptool==4.7.0 click==8.1.7 esphome-dashboard==20240412.0 aioesphomeapi==24.0.0 -zeroconf==0.131.0 +zeroconf==0.132.2 python-magic==0.4.27 ruamel.yaml==0.18.6 # dashboard_import From 51ed6d62d928ec66496bb972ec3c1be36c6f8bb3 Mon Sep 17 00:00:00 2001 From: zry98 Date: Wed, 17 Apr 2024 23:31:20 +0200 Subject: [PATCH 1266/2101] [Tuya Climate] Fix compilation error caused by codegen (#6568) --- esphome/components/tuya/climate/__init__.py | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/esphome/components/tuya/climate/__init__.py b/esphome/components/tuya/climate/__init__.py index b3d401e5a4..56eb377ed7 100644 --- a/esphome/components/tuya/climate/__init__.py +++ b/esphome/components/tuya/climate/__init__.py @@ -208,7 +208,7 @@ async def to_code(config): cg.add(var.set_switch_id(switch_datapoint)) if active_state_config := config.get(CONF_ACTIVE_STATE): - cg.add(var.set_active_state_id(CONF_DATAPOINT)) + cg.add(var.set_active_state_id(active_state_config.get(CONF_DATAPOINT))) if (heating_value := active_state_config.get(CONF_HEATING_VALUE)) is not None: cg.add(var.set_active_state_heating_value(heating_value)) if (cooling_value := active_state_config.get(CONF_COOLING_VALUE)) is not None: @@ -219,14 +219,10 @@ async def to_code(config): cg.add(var.set_active_state_fanonly_value(fanonly_value)) else: if heating_state_pin_config := config.get(CONF_HEATING_STATE_PIN): - heating_state_pin = await cg.gpio_pin_expression( - config(heating_state_pin_config) - ) + heating_state_pin = await cg.gpio_pin_expression(heating_state_pin_config) cg.add(var.set_heating_state_pin(heating_state_pin)) if cooling_state_pin_config := config.get(CONF_COOLING_STATE_PIN): - cooling_state_pin = await cg.gpio_pin_expression( - config(cooling_state_pin_config) - ) + cooling_state_pin = await cg.gpio_pin_expression(cooling_state_pin_config) cg.add(var.set_cooling_state_pin(cooling_state_pin)) if target_temperature_datapoint := config.get(CONF_TARGET_TEMPERATURE_DATAPOINT): @@ -254,11 +250,11 @@ async def to_code(config): if preset_config := config.get(CONF_PRESET, {}): if eco_config := preset_config.get(CONF_ECO, {}): - cg.add(var.set_eco_id(CONF_DATAPOINT)) + cg.add(var.set_eco_id(eco_config.get(CONF_DATAPOINT))) if eco_temperature := eco_config.get(CONF_TEMPERATURE): cg.add(var.set_eco_temperature(eco_temperature)) - if CONF_SLEEP in preset_config: - cg.add(var.set_sleep_id(CONF_DATAPOINT)) + if sleep_config := preset_config.get(CONF_SLEEP, {}): + cg.add(var.set_sleep_id(sleep_config.get(CONF_DATAPOINT))) if swing_mode_config := config.get(CONF_SWING_MODE): if swing_vertical_datapoint := swing_mode_config.get(CONF_VERTICAL_DATAPOINT): @@ -268,7 +264,7 @@ async def to_code(config): ): cg.add(var.set_swing_horizontal_id(swing_horizontal_datapoint)) if fan_mode_config := config.get(CONF_FAN_MODE): - cg.add(var.set_fan_speed_id(CONF_DATAPOINT)) + cg.add(var.set_fan_speed_id(fan_mode_config.get(CONF_DATAPOINT))) if (fan_auto_value := fan_mode_config.get(CONF_AUTO_VALUE)) is not None: cg.add(var.set_fan_speed_auto_value(fan_auto_value)) if (fan_low_value := fan_mode_config.get(CONF_LOW_VALUE)) is not None: From c8cdb30459146c9e1e854098328d7cdf817df448 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 18 Apr 2024 09:43:00 +1200 Subject: [PATCH 1267/2101] Housecleaning: Use walrus operator in switch (#6558) --- esphome/components/switch/__init__.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/esphome/components/switch/__init__.py b/esphome/components/switch/__init__.py index 21cbe3dfe4..e997ec7ca5 100644 --- a/esphome/components/switch/__init__.py +++ b/esphome/components/switch/__init__.py @@ -138,8 +138,8 @@ SWITCH_SCHEMA = switch_schema() # for compatibility async def setup_switch_core_(var, config): await setup_entity(var, config) - if CONF_INVERTED in config: - cg.add(var.set_inverted(config[CONF_INVERTED])) + if (inverted := config.get(CONF_INVERTED)) is not None: + cg.add(var.set_inverted(inverted)) for conf in config.get(CONF_ON_TURN_ON, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) await automation.build_automation(trigger, [], conf) @@ -147,12 +147,12 @@ async def setup_switch_core_(var, config): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) await automation.build_automation(trigger, [], conf) - if CONF_MQTT_ID in config: - mqtt_ = cg.new_Pvariable(config[CONF_MQTT_ID], var) + 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) - if CONF_DEVICE_CLASS in config: - cg.add(var.set_device_class(config[CONF_DEVICE_CLASS])) + if (device_class := config.get(CONF_DEVICE_CLASS)) is not None: + cg.add(var.set_device_class(device_class)) cg.add(var.set_restore_mode(config[CONF_RESTORE_MODE])) From 72c1c3f0910ff12448857574f2386ff72de3682b Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 18 Apr 2024 09:43:11 +1200 Subject: [PATCH 1268/2101] Housecleaning: Use walrus operator in lock (#6554) Co-authored-by: Keith Burzinski --- esphome/components/lock/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/lock/__init__.py b/esphome/components/lock/__init__.py index f659c48a6e..457ffa278a 100644 --- a/esphome/components/lock/__init__.py +++ b/esphome/components/lock/__init__.py @@ -57,8 +57,8 @@ async def setup_lock_core_(var, config): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) await automation.build_automation(trigger, [], conf) - if CONF_MQTT_ID in config: - mqtt_ = cg.new_Pvariable(config[CONF_MQTT_ID], var) + if mqtt_id := config.get(CONF_MQTT_ID): + mqtt_ = cg.new_Pvariable(mqtt_id, var) await mqtt.register_mqtt_component(mqtt_, config) From 4559e963b340e2dae8a0edd3bc9893b0d4e140d0 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 18 Apr 2024 09:43:18 +1200 Subject: [PATCH 1269/2101] Housecleaning: Use walrus operator in sensor (#6553) Co-authored-by: Keith Burzinski --- esphome/components/sensor/__init__.py | 42 +++++++++++++-------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index 46295fe958..ece232e1a6 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -732,14 +732,14 @@ async def build_filters(config): async def setup_sensor_core_(var, config): await setup_entity(var, config) - if CONF_DEVICE_CLASS in config: - cg.add(var.set_device_class(config[CONF_DEVICE_CLASS])) - if CONF_STATE_CLASS in config: - cg.add(var.set_state_class(config[CONF_STATE_CLASS])) - if CONF_UNIT_OF_MEASUREMENT in config: - cg.add(var.set_unit_of_measurement(config[CONF_UNIT_OF_MEASUREMENT])) - if CONF_ACCURACY_DECIMALS in config: - cg.add(var.set_accuracy_decimals(config[CONF_ACCURACY_DECIMALS])) + if (device_class := config.get(CONF_DEVICE_CLASS)) is not None: + cg.add(var.set_device_class(device_class)) + 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)) cg.add(var.set_force_update(config[CONF_FORCE_UPDATE])) if config.get(CONF_FILTERS): # must exist and not be empty filters = await build_filters(config[CONF_FILTERS]) @@ -754,23 +754,23 @@ async def setup_sensor_core_(var, config): 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) + if (above := conf.get(CONF_ABOVE)) is not None: + template_ = await cg.templatable(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) + 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) - if CONF_MQTT_ID in config: - mqtt_ = cg.new_Pvariable(config[CONF_MQTT_ID], var) + 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) - if CONF_EXPIRE_AFTER in config: - if config[CONF_EXPIRE_AFTER] is None: + if (expire_after := config.get(CONF_EXPIRE_AFTER, _UNDEF)) is not _UNDEF: + if expire_after is None: cg.add(mqtt_.disable_expire_after()) else: - cg.add(mqtt_.set_expire_after(config[CONF_EXPIRE_AFTER])) + cg.add(mqtt_.set_expire_after(expire_after)) async def register_sensor(var, config): @@ -803,10 +803,10 @@ async def sensor_in_range_to_code(config, condition_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) var = cg.new_Pvariable(condition_id, template_arg, paren) - if CONF_ABOVE in config: - cg.add(var.set_min(config[CONF_ABOVE])) - if CONF_BELOW in config: - cg.add(var.set_max(config[CONF_BELOW])) + if (above := config.get(CONF_ABOVE)) is not None: + cg.add(var.set_min(above)) + if (below := config.get(CONF_BELOW)) is not None: + cg.add(var.set_max(below)) return var From 09def255dd70c8f406e046b87fe1cd77953fd9ef Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 18 Apr 2024 11:02:37 +1200 Subject: [PATCH 1270/2101] Bump pytest-mock from 3.12.0 to 3.14.0 (#6572) 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 767018d07a..78820765f4 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -7,7 +7,7 @@ pre-commit # Unit tests pytest==8.1.1 pytest-cov==4.1.0 -pytest-mock==3.12.0 +pytest-mock==3.14.0 pytest-asyncio==0.23.6 asyncmock==0.4.2 hypothesis==6.92.1 From 6075067e843788eb7fae90333ae8ff7f59b25a8d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 18 Apr 2024 11:02:54 +1200 Subject: [PATCH 1271/2101] Bump peter-evans/create-pull-request from 6.0.3 to 6.0.4 (#6569) 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 62b9c7df9b..c9614618d5 100644 --- a/.github/workflows/sync-device-classes.yml +++ b/.github/workflows/sync-device-classes.yml @@ -36,7 +36,7 @@ jobs: python ./script/sync-device_class.py - name: Commit changes - uses: peter-evans/create-pull-request@v6.0.3 + uses: peter-evans/create-pull-request@v6.0.4 with: commit-message: "Synchronise Device Classes from Home Assistant" committer: esphomebot From 8c323e2e4c9941f3e300ba4aa98887a3a09bfda7 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Thu, 18 Apr 2024 01:07:05 +0200 Subject: [PATCH 1272/2101] Nextion - Review set_protocol_reparse_mode() (#6567) --- esphome/components/nextion/nextion.h | 22 ++++++++++---- .../components/nextion/nextion_commands.cpp | 29 ++++++++++--------- 2 files changed, 32 insertions(+), 19 deletions(-) diff --git a/esphome/components/nextion/nextion.h b/esphome/components/nextion/nextion.h index f9f01de72c..d84f1df3de 100644 --- a/esphome/components/nextion/nextion.h +++ b/esphome/components/nextion/nextion.h @@ -878,12 +878,24 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe */ void sleep(bool sleep); /** - * Sets Nextion Protocol Reparse mode between active or passive - * @param True or false. - * active_mode=true to enter active protocol reparse mode - * active_mode=false to enter passive protocol reparse mode. + * @brief Sets the Nextion display's protocol reparse mode. + * + * This function toggles the Nextion display's protocol reparse mode between active and passive. + * In active mode, the display actively parses incoming data. + * In passive mode, it does not parse data unless specifically instructed to do so. + * This is useful for managing how the Nextion display interprets incoming commands, + * especially during initialization or in scenarios where precise control over command processing is needed. + * + * @param active_mode A boolean value indicating the desired reparse mode. + * - true to set the display to active protocol reparse mode, where it actively parses incoming commands. + * - false to set the display to passive protocol reparse mode, where command parsing is done only on explicit + * instruction. + * + * @return bool Returns true if all commands were sent successfully to the Nextion display, indicating that the mode + * was set as expected. Returns false if any of the commands failed to send, indicating that the desired reparse mode + * may not be correctly set. */ - void set_protocol_reparse_mode(bool active_mode); + bool set_protocol_reparse_mode(bool active_mode); // ========== INTERNAL METHODS ========== // (In most use cases you won't need these) diff --git a/esphome/components/nextion/nextion_commands.cpp b/esphome/components/nextion/nextion_commands.cpp index e378111376..a2325861a3 100644 --- a/esphome/components/nextion/nextion_commands.cpp +++ b/esphome/components/nextion/nextion_commands.cpp @@ -36,22 +36,23 @@ void Nextion::sleep(bool sleep) { // End sleep safe commands // Protocol reparse mode -void Nextion::set_protocol_reparse_mode(bool active_mode) { - const uint8_t to_send[3] = {0xFF, 0xFF, 0xFF}; +bool Nextion::set_protocol_reparse_mode(bool active_mode) { + ESP_LOGV(TAG, "Set Nextion protocol reparse mode: %s", YESNO(active_mode)); + this->ignore_is_setup_ = true; // if not in reparse mode setup will fail, so it should be ignored + bool all_commands_sent = true; if (active_mode) { // Sets active protocol reparse mode - this->write_str( - "recmod=1"); // send_command_ cannot be used as Nextion might not be setup if incorrect reparse mode - this->write_array(to_send, sizeof(to_send)); - } else { // Sets passive protocol reparse mode - this->write_str("DRAKJHSUYDGBNCJHGJKSHBDN"); // To exit active reparse mode this sequence must be sent - this->write_array(to_send, sizeof(to_send)); - this->write_str("recmod=0"); // Sending recmode=0 twice is recommended - this->write_array(to_send, sizeof(to_send)); - this->write_str("recmod=0"); - this->write_array(to_send, sizeof(to_send)); + all_commands_sent &= this->send_command_("recmod=1"); + } else { // Sets passive protocol reparse mode + all_commands_sent &= + this->send_command_("DRAKJHSUYDGBNCJHGJKSHBDN"); // To exit active reparse mode this sequence must be sent + all_commands_sent &= this->send_command_("recmod=0"); // Sending recmode=0 twice is recommended + all_commands_sent &= this->send_command_("recmod=0"); } - this->write_str("connect"); - this->write_array(to_send, sizeof(to_send)); + if (!this->nextion_reports_is_setup_) { // No need to connect if is already setup + all_commands_sent &= this->send_command_("connect"); + } + this->ignore_is_setup_ = false; + return all_commands_sent; } void Nextion::set_exit_reparse_on_start(bool exit_reparse) { this->exit_reparse_on_start_ = exit_reparse; } From abc09a15c38b4c77a1316ccad32b97a4638b03d8 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Wed, 17 Apr 2024 18:47:34 -0500 Subject: [PATCH 1273/2101] Allow component final_validate (#6475) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/config.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/esphome/config.py b/esphome/config.py index c5764dd4f2..1f6867eb59 100644 --- a/esphome/config.py +++ b/esphome/config.py @@ -333,10 +333,11 @@ class LoadValidationStep(ConfigValidationStep): if load not in result: result.add_validation_step(AutoLoadValidationStep(load)) + result.add_validation_step( + MetadataValidationStep([self.domain], self.domain, self.conf, component) + ) + if not component.is_platform_component: - result.add_validation_step( - MetadataValidationStep([self.domain], self.domain, self.conf, component) - ) return # This is a platform component, proceed to reading platform entries @@ -520,8 +521,6 @@ class SchemaValidationStep(ConfigValidationStep): self.comp = comp def run(self, result: Config) -> None: - if self.comp.config_schema is None: - return token = path_context.set(self.path) with result.catch_error(self.path): if self.comp.is_platform: @@ -536,7 +535,7 @@ class SchemaValidationStep(ConfigValidationStep): validated["platform"] = platform_val validated.move_to_end("platform", last=False) result.set_by_path(self.path, validated) - else: + elif self.comp.config_schema is not None: schema = cv.Schema(self.comp.config_schema) validated = schema(self.conf) result.set_by_path(self.path, validated) From 5a093acbf509f958fb79af5d4d705f6e49befbd4 Mon Sep 17 00:00:00 2001 From: Cossid <83468485+Cossid@users.noreply.github.com> Date: Wed, 17 Apr 2024 19:03:59 -0500 Subject: [PATCH 1274/2101] SM2135 - Use standard channel ordering. (#6573) --- esphome/components/sm2135/sm2135.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/esphome/components/sm2135/sm2135.cpp b/esphome/components/sm2135/sm2135.cpp index 9a576859ac..ee5948bb3a 100644 --- a/esphome/components/sm2135/sm2135.cpp +++ b/esphome/components/sm2135/sm2135.cpp @@ -106,23 +106,23 @@ void SM2135::loop() { delay(1); this->sm2135_start_(); this->write_byte_(SM2135_ADDR_C); - this->write_byte_(this->pwm_amounts_[4]); // Warm - this->write_byte_(this->pwm_amounts_[3]); // Cold + this->write_byte_(this->pwm_amounts_[3]); + this->write_byte_(this->pwm_amounts_[4]); } else { // Color this->write_byte_(SM2135_RGB); - this->write_byte_(this->pwm_amounts_[1]); // Green - this->write_byte_(this->pwm_amounts_[0]); // Red - this->write_byte_(this->pwm_amounts_[2]); // Blue + this->write_byte_(this->pwm_amounts_[0]); + this->write_byte_(this->pwm_amounts_[1]); + this->write_byte_(this->pwm_amounts_[2]); } } else { this->write_byte_(SM2135_RGB); - this->write_byte_(this->pwm_amounts_[1]); // Green - this->write_byte_(this->pwm_amounts_[0]); // Red - this->write_byte_(this->pwm_amounts_[2]); // Blue - this->write_byte_(this->pwm_amounts_[4]); // Warm - this->write_byte_(this->pwm_amounts_[3]); // Cold + this->write_byte_(this->pwm_amounts_[0]); + this->write_byte_(this->pwm_amounts_[1]); + this->write_byte_(this->pwm_amounts_[2]); + this->write_byte_(this->pwm_amounts_[3]); + this->write_byte_(this->pwm_amounts_[4]); } this->sm2135_stop_(); From 39deb8910868d72ab043e579f861eef0e8227508 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Thu, 18 Apr 2024 02:05:37 +0200 Subject: [PATCH 1275/2101] Nextion - Do not refresh sensors while updating (#6566) --- .../binary_sensor/nextion_binarysensor.cpp | 4 ++-- esphome/components/nextion/nextion.cpp | 2 ++ esphome/components/nextion/nextion.h | 20 +++++++++++++++++++ esphome/components/nextion/nextion_base.h | 2 ++ .../nextion/sensor/nextion_sensor.cpp | 4 ++-- .../nextion/switch/nextion_switch.cpp | 4 ++-- .../text_sensor/nextion_textsensor.cpp | 4 ++-- 7 files changed, 32 insertions(+), 8 deletions(-) diff --git a/esphome/components/nextion/binary_sensor/nextion_binarysensor.cpp b/esphome/components/nextion/binary_sensor/nextion_binarysensor.cpp index bf6e74cb38..499cd901c0 100644 --- a/esphome/components/nextion/binary_sensor/nextion_binarysensor.cpp +++ b/esphome/components/nextion/binary_sensor/nextion_binarysensor.cpp @@ -27,7 +27,7 @@ void NextionBinarySensor::process_touch(uint8_t page_id, uint8_t component_id, b } void NextionBinarySensor::update() { - if (!this->nextion_->is_setup()) + if (!this->nextion_->is_setup() || this->nextion_->is_updating()) return; if (this->variable_name_.empty()) // This is a touch component @@ -37,7 +37,7 @@ void NextionBinarySensor::update() { } void NextionBinarySensor::set_state(bool state, bool publish, bool send_to_nextion) { - if (!this->nextion_->is_setup()) + if (!this->nextion_->is_setup() || this->nextion_->is_updating()) return; if (this->component_id_ == 0) // This is a legacy touch component diff --git a/esphome/components/nextion/nextion.cpp b/esphome/components/nextion/nextion.cpp index 29dcfa6cef..ac8a96fa7f 100644 --- a/esphome/components/nextion/nextion.cpp +++ b/esphome/components/nextion/nextion.cpp @@ -1137,5 +1137,7 @@ void Nextion::set_writer(const nextion_writer_t &writer) { this->writer_ = write ESPDEPRECATED("set_wait_for_ack(bool) is deprecated and has no effect", "v1.20") void Nextion::set_wait_for_ack(bool wait_for_ack) { ESP_LOGE(TAG, "This command is deprecated"); } +bool Nextion::is_updating() { return this->is_updating_; } + } // namespace nextion } // namespace esphome diff --git a/esphome/components/nextion/nextion.h b/esphome/components/nextion/nextion.h index d84f1df3de..0769b3f93f 100644 --- a/esphome/components/nextion/nextion.h +++ b/esphome/components/nextion/nextion.h @@ -1031,6 +1031,26 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe */ size_t queue_size() { return this->nextion_queue_.size(); } + /** + * @brief Check if the TFT update process is currently running. + * + * This method provides a way to determine if the Nextion display is in the + * process of updating its TFT firmware. When a TFT update is in progress, + * certain operations or commands may be restricted or could interfere with the + * update process. By checking the state of the update process, the system can + * make informed decisions about performing actions that involve communication + * with the Nextion display. + * + * @return true if the TFT update process is active, indicating that the Nextion + * display is currently updating its firmware. This implies that caution + * should be taken with commands sent to the display to avoid interrupting + * the update process. + * @return false if the TFT update process is not active, indicating that the Nextion + * display is not currently updating its firmware and is in a normal operational + * state, ready to receive and process commands as usual. + */ + bool is_updating() override; + protected: std::deque nextion_queue_; std::deque waveform_queue_; diff --git a/esphome/components/nextion/nextion_base.h b/esphome/components/nextion/nextion_base.h index b5729a1df1..f16eabc003 100644 --- a/esphome/components/nextion/nextion_base.h +++ b/esphome/components/nextion/nextion_base.h @@ -48,6 +48,8 @@ class NextionBase { virtual void show_component(const char *component) = 0; virtual void hide_component(const char *component) = 0; + virtual bool is_updating() { return false; } + bool is_sleeping() { return this->is_sleeping_; } bool is_setup() { return this->is_setup_; } bool is_detected() { return this->is_detected_; } diff --git a/esphome/components/nextion/sensor/nextion_sensor.cpp b/esphome/components/nextion/sensor/nextion_sensor.cpp index 566dd30acf..6cc641fcf3 100644 --- a/esphome/components/nextion/sensor/nextion_sensor.cpp +++ b/esphome/components/nextion/sensor/nextion_sensor.cpp @@ -30,7 +30,7 @@ void NextionSensor::add_to_wave_buffer(float state) { } void NextionSensor::update() { - if (!this->nextion_->is_setup()) + if (!this->nextion_->is_setup() || this->nextion_->is_updating()) return; if (this->wave_chan_id_ == UINT8_MAX) { @@ -45,7 +45,7 @@ void NextionSensor::update() { } void NextionSensor::set_state(float state, bool publish, bool send_to_nextion) { - if (!this->nextion_->is_setup()) + if (!this->nextion_->is_setup() || this->nextion_->is_updating()) return; if (std::isnan(state)) diff --git a/esphome/components/nextion/switch/nextion_switch.cpp b/esphome/components/nextion/switch/nextion_switch.cpp index 1f32ad3425..63c1882b48 100644 --- a/esphome/components/nextion/switch/nextion_switch.cpp +++ b/esphome/components/nextion/switch/nextion_switch.cpp @@ -18,13 +18,13 @@ void NextionSwitch::process_bool(const std::string &variable_name, bool on) { } void NextionSwitch::update() { - if (!this->nextion_->is_setup()) + if (!this->nextion_->is_setup() || this->nextion_->is_updating()) return; this->nextion_->add_to_get_queue(this); } void NextionSwitch::set_state(bool state, bool publish, bool send_to_nextion) { - if (!this->nextion_->is_setup()) + if (!this->nextion_->is_setup() || this->nextion_->is_updating()) return; if (send_to_nextion) { diff --git a/esphome/components/nextion/text_sensor/nextion_textsensor.cpp b/esphome/components/nextion/text_sensor/nextion_textsensor.cpp index 08f032df74..a3fc9390f5 100644 --- a/esphome/components/nextion/text_sensor/nextion_textsensor.cpp +++ b/esphome/components/nextion/text_sensor/nextion_textsensor.cpp @@ -16,13 +16,13 @@ void NextionTextSensor::process_text(const std::string &variable_name, const std } void NextionTextSensor::update() { - if (!this->nextion_->is_setup()) + if (!this->nextion_->is_setup() || this->nextion_->is_updating()) return; this->nextion_->add_to_get_queue(this); } void NextionTextSensor::set_state(const std::string &state, bool publish, bool send_to_nextion) { - if (!this->nextion_->is_setup()) + if (!this->nextion_->is_setup() || this->nextion_->is_updating()) return; if (send_to_nextion) { From 197f9d6d0322210984de4c50681a7afb72cd0105 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Thu, 18 Apr 2024 02:10:10 +0200 Subject: [PATCH 1276/2101] Nextion - Review types (#6565) --- esphome/components/nextion/display.py | 4 +- esphome/components/nextion/nextion.cpp | 12 +- esphome/components/nextion/nextion.h | 137 ++++++++++++------ esphome/components/nextion/nextion_base.h | 4 +- .../components/nextion/nextion_commands.cpp | 137 ++++++++++-------- 5 files changed, 183 insertions(+), 111 deletions(-) diff --git a/esphome/components/nextion/display.py b/esphome/components/nextion/display.py index 27f2030f0d..6487c12f36 100644 --- a/esphome/components/nextion/display.py +++ b/esphome/components/nextion/display.py @@ -68,8 +68,8 @@ CONFIG_SCHEMA = ( } ), cv.Optional(CONF_TOUCH_SLEEP_TIMEOUT): cv.int_range(min=3, max=65535), - cv.Optional(CONF_WAKE_UP_PAGE): cv.positive_int, - cv.Optional(CONF_START_UP_PAGE): cv.positive_int, + cv.Optional(CONF_WAKE_UP_PAGE): cv.uint8_t, + cv.Optional(CONF_START_UP_PAGE): cv.uint8_t, cv.Optional(CONF_AUTO_WAKE_ON_TOUCH, default=True): cv.boolean, cv.Optional(CONF_EXIT_REPARSE_ON_START, default=False): cv.boolean, } diff --git a/esphome/components/nextion/nextion.cpp b/esphome/components/nextion/nextion.cpp index ac8a96fa7f..8de5ca9143 100644 --- a/esphome/components/nextion/nextion.cpp +++ b/esphome/components/nextion/nextion.cpp @@ -138,11 +138,11 @@ void Nextion::dump_config() { } if (this->wake_up_page_ != -1) { - ESP_LOGCONFIG(TAG, " Wake Up Page: %d", this->wake_up_page_); + ESP_LOGCONFIG(TAG, " Wake Up Page: %" PRId16, this->wake_up_page_); } if (this->start_up_page_ != -1) { - ESP_LOGCONFIG(TAG, " Start Up Page: %d", this->start_up_page_); + ESP_LOGCONFIG(TAG, " Start Up Page: %" PRId16, this->start_up_page_); } } @@ -1024,23 +1024,23 @@ bool Nextion::add_no_result_to_queue_with_printf_(const std::string &variable_na * @param is_sleep_safe The command is safe to send when the Nextion is sleeping */ -void Nextion::add_no_result_to_queue_with_set(NextionComponentBase *component, int state_value) { +void Nextion::add_no_result_to_queue_with_set(NextionComponentBase *component, int32_t state_value) { this->add_no_result_to_queue_with_set(component->get_variable_name(), component->get_variable_name_to_send(), state_value); } void Nextion::add_no_result_to_queue_with_set(const std::string &variable_name, - const std::string &variable_name_to_send, int state_value) { + const std::string &variable_name_to_send, int32_t state_value) { this->add_no_result_to_queue_with_set_internal_(variable_name, variable_name_to_send, state_value); } void Nextion::add_no_result_to_queue_with_set_internal_(const std::string &variable_name, - const std::string &variable_name_to_send, int state_value, + const std::string &variable_name_to_send, int32_t state_value, bool is_sleep_safe) { if ((!this->is_setup() && !this->ignore_is_setup_) || (!is_sleep_safe && this->is_sleeping())) return; - this->add_no_result_to_queue_with_ignore_sleep_printf_(variable_name, "%s=%d", variable_name_to_send.c_str(), + this->add_no_result_to_queue_with_ignore_sleep_printf_(variable_name, "%s=%" PRId32, variable_name_to_send.c_str(), state_value); } diff --git a/esphome/components/nextion/nextion.h b/esphome/components/nextion/nextion.h index 0769b3f93f..bc75df3ce6 100644 --- a/esphome/components/nextion/nextion.h +++ b/esphome/components/nextion/nextion.h @@ -50,6 +50,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * This will set the `txt` property of the component `textview` to `Hello World`. */ void set_component_text(const char *component, const char *text); + /** * Set the text of a component to a formatted string * @param component The component name. @@ -66,6 +67,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * For example when `uptime_sensor` = 506, then, `The uptime is: 506` will be displayed. */ void set_component_text_printf(const char *component, const char *format, ...) __attribute__((format(printf, 3, 4))); + /** * Set the integer value of a component * @param component The component name. @@ -78,7 +80,8 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * * This will change the property `value` of the component `gauge` to 50. */ - void set_component_value(const char *component, int value); + void set_component_value(const char *component, int32_t value); + /** * Set the picture of an image component. * @param component The component name. @@ -92,6 +95,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * This will change the image of the component `pic` to the image with ID `4`. */ void set_component_picture(const char *component, uint8_t picture_id); + /** * Set the background color of a component. * @param component The component name. @@ -107,6 +111,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * Nextion HMI colors. */ void set_component_background_color(const char *component, uint16_t color); + /** * Set the background color of a component. * @param component The component name. @@ -121,6 +126,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * Use [Nextion Instruction Set](https://nextion.tech/instruction-set/#s5) for a list of Nextion HMI colors constants. */ void set_component_background_color(const char *component, const char *color); + /** * Set the background color of a component. * @param component The component name. @@ -135,6 +141,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * This will change the background color of the component `button` to blue. */ void set_component_background_color(const char *component, Color color) override; + /** * Set the pressed background color of a component. * @param component The component name. @@ -151,6 +158,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * Nextion HMI colors. */ void set_component_pressed_background_color(const char *component, uint16_t color); + /** * Set the pressed background color of a component. * @param component The component name. @@ -166,6 +174,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * Use [Nextion Instruction Set](https://nextion.tech/instruction-set/#s5) for a list of Nextion HMI colors constants. */ void set_component_pressed_background_color(const char *component, const char *color); + /** * Set the pressed background color of a component. * @param component The component name. @@ -181,6 +190,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * is shown when the component is pressed. */ void set_component_pressed_background_color(const char *component, Color color) override; + /** * Set the foreground color of a component. * @param component The component name. @@ -196,6 +206,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * Nextion HMI colors. */ void set_component_foreground_color(const char *component, uint16_t color); + /** * Set the foreground color of a component. * @param component The component name. @@ -210,6 +221,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * Use [Nextion Instruction Set](https://nextion.tech/instruction-set/#s5) for a list of Nextion HMI colors constants. */ void set_component_foreground_color(const char *component, const char *color); + /** * Set the foreground color of a component. * @param component The component name. @@ -223,6 +235,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * This will change the foreground color of the component `button` to black. */ void set_component_foreground_color(const char *component, Color color) override; + /** * Set the pressed foreground color of a component. * @param component The component name. @@ -239,6 +252,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * Nextion HMI colors. */ void set_component_pressed_foreground_color(const char *component, uint16_t color); + /** * Set the pressed foreground color of a component. * @param component The component name. @@ -254,6 +268,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * Use [Nextion Instruction Set](https://nextion.tech/instruction-set/#s5) for a list of Nextion HMI colors constants. */ void set_component_pressed_foreground_color(const char *component, const char *color); + /** * Set the pressed foreground color of a component. * @param component The component name. @@ -283,6 +298,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * This will change the picture id of the component `textview`. */ void set_component_pic(const char *component, uint8_t pic_id); + /** * Set the background picture id of component. * @param component The component name. @@ -312,6 +328,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * Nextion HMI colors. */ void set_component_font_color(const char *component, uint16_t color); + /** * Set the font color of a component. * @param component The component name. @@ -326,6 +343,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * Use [Nextion Instruction Set](https://nextion.tech/instruction-set/#s5) for a list of Nextion HMI colors constants. */ void set_component_font_color(const char *component, const char *color); + /** * Set the font color of a component. * @param component The component name. @@ -339,6 +357,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * This will change the font color of the component `textview` to black. */ void set_component_font_color(const char *component, Color color) override; + /** * Set the pressed font color of a component. * @param component The component name. @@ -354,6 +373,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * Nextion HMI colors. */ void set_component_pressed_font_color(const char *component, uint16_t color); + /** * Set the pressed font color of a component. * @param component The component name. @@ -368,6 +388,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * Use [Nextion Instruction Set](https://nextion.tech/instruction-set/#s5) for a list of Nextion HMI colors constants. */ void set_component_pressed_font_color(const char *component, const char *color); + /** * Set the pressed font color of a component. * @param component The component name. @@ -381,6 +402,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * This will change the pressed font color of the component `button` to black. */ void set_component_pressed_font_color(const char *component, Color color) override; + /** * Set the coordinates of a component on screen. * @param component The component name. @@ -394,7 +416,8 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * * This will move the position of the component `pic` to the x coordinate `55` and y coordinate `100`. */ - void set_component_coordinates(const char *component, int x, int y); + void set_component_coordinates(const char *component, uint16_t x, uint16_t y); + /** * Set the font id for a component. * @param component The component name. @@ -408,6 +431,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * Changes the font of the component named `textveiw`. Font IDs are set in the Nextion Editor. */ void set_component_font(const char *component, uint8_t font_id) override; + /** * Send the current time to the nextion display. * @param time The time instance to send (get this with id(my_time).now() ). @@ -426,6 +450,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * Switches to the page named `main`. Pages are named in the Nextion Editor. */ void goto_page(const char *page); + /** * Show the page with a given id. * @param page The id of the page. @@ -438,6 +463,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * Switches to the page named `main`. Pages are named in the Nextion Editor. */ void goto_page(uint8_t page); + /** * Hide a component. * @param component The component name. @@ -450,6 +476,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * Hides the component named `button`. */ void hide_component(const char *component) override; + /** * Show a component. * @param component The component name. @@ -462,6 +489,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * Shows the component named `button`. */ void show_component(const char *component) override; + /** * Enable touch for a component. * @param component The component name. @@ -474,6 +502,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * Enables touch for component named `button`. */ void enable_component_touch(const char *component); + /** * Disable touch for a component. * @param component The component name. @@ -486,14 +515,17 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * Disables touch for component named `button`. */ void disable_component_touch(const char *component); + /** * Add waveform data to a waveform component * @param component_id The integer component id. * @param channel_number The channel number to write to. * @param value The value to write. */ - void add_waveform_data(int component_id, uint8_t channel_number, uint8_t value); - void open_waveform_channel(int component_id, uint8_t channel_number, uint8_t value); + 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); + /** * Display a picture at coordinates. * @param picture_id The picture id. @@ -507,7 +539,8 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * * Displays the picture who has the id `2` at the x coordinates `15` and y coordinates `25`. */ - void display_picture(int picture_id, int x_start, int y_start); + void display_picture(uint16_t picture_id, uint16_t x_start, uint16_t y_start); + /** * Fill a rectangle with a color. * @param x1 The starting x coordinate. @@ -526,7 +559,8 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * Use this [color picker](https://nodtem66.github.io/nextion-hmi-color-convert/index.html) to convert color codes to * Nextion HMI colors. */ - void fill_area(int x1, int y1, int width, int height, uint16_t color); + void fill_area(uint16_t x1, uint16_t y1, uint16_t width, uint16_t height, uint16_t color); + /** * Fill a rectangle with a color. * @param x1 The starting x coordinate. @@ -544,7 +578,8 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * the red color. * Use [Nextion Instruction Set](https://nextion.tech/instruction-set/#s5) for a list of Nextion HMI colors constants. */ - void fill_area(int x1, int y1, int width, int height, const char *color); + void fill_area(uint16_t x1, uint16_t y1, uint16_t width, uint16_t height, const char *color); + /** * Fill a rectangle with a color. * @param x1 The starting x coordinate. @@ -562,7 +597,8 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * Fills an area that starts at x coordinate `50` and y coordinate `50` with a height of `100` and width of `100` with * blue color. */ - void fill_area(int x1, int y1, int width, int height, Color color); + void fill_area(uint16_t x1, uint16_t y1, uint16_t width, uint16_t height, Color color); + /** * Draw a line on the screen. * @param x1 The starting x coordinate. @@ -581,7 +617,8 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * Use this [color picker](https://nodtem66.github.io/nextion-hmi-color-convert/index.html) to convert color codes to * Nextion HMI colors. */ - void line(int x1, int y1, int x2, int y2, uint16_t color); + void line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color); + /** * Draw a line on the screen. * @param x1 The starting x coordinate. @@ -599,7 +636,8 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * `75` with the blue color. * Use [Nextion Instruction Set](https://nextion.tech/instruction-set/#s5) for a list of Nextion HMI colors constants. */ - void line(int x1, int y1, int x2, int y2, const char *color); + void line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, const char *color); + /** * Draw a line on the screen. * @param x1 The starting x coordinate. @@ -617,7 +655,8 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * Makes a line that starts at x coordinate `50` and y coordinate `50` and ends at x coordinate `75` and y coordinate * `75` with blue color. */ - void line(int x1, int y1, int x2, int y2, Color color); + void line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, Color color); + /** * Draw a rectangle outline. * @param x1 The starting x coordinate. @@ -636,7 +675,8 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * Use this [color picker](https://nodtem66.github.io/nextion-hmi-color-convert/index.html) to convert color codes to * Nextion HMI colors. */ - void rectangle(int x1, int y1, int width, int height, uint16_t color); + void rectangle(uint16_t x1, uint16_t y1, uint16_t width, uint16_t height, uint16_t color); + /** * Draw a rectangle outline. * @param x1 The starting x coordinate. @@ -654,7 +694,8 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * length of `50` with the blue color. * Use [Nextion Instruction Set](https://nextion.tech/instruction-set/#s5) for a list of Nextion HMI colors constants. */ - void rectangle(int x1, int y1, int width, int height, const char *color); + void rectangle(uint16_t x1, uint16_t y1, uint16_t width, uint16_t height, const char *color); + /** * Draw a rectangle outline. * @param x1 The starting x coordinate. @@ -672,7 +713,8 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * Makes a outline of a rectangle that starts at x coordinate `25` and y coordinate `35` and has a width of `40` and a * length of `50` with blue color. */ - void rectangle(int x1, int y1, int width, int height, Color color); + void rectangle(uint16_t x1, uint16_t y1, uint16_t width, uint16_t height, Color color); + /** * Draw a circle outline * @param center_x The center x coordinate. @@ -682,7 +724,8 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * Use this [color picker](https://nodtem66.github.io/nextion-hmi-color-convert/index.html) to convert color codes to * Nextion HMI colors. */ - void circle(int center_x, int center_y, int radius, uint16_t color); + void circle(uint16_t center_x, uint16_t center_y, uint16_t radius, uint16_t color); + /** * Draw a circle outline * @param center_x The center x coordinate. @@ -691,7 +734,8 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * @param color The color to draw with (as a string). * Use [Nextion Instruction Set](https://nextion.tech/instruction-set/#s5) for a list of Nextion HMI colors constants. */ - void circle(int center_x, int center_y, int radius, const char *color); + void circle(uint16_t center_x, uint16_t center_y, uint16_t radius, const char *color); + /** * Draw a circle outline * @param center_x The center x coordinate. @@ -699,7 +743,8 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * @param radius The circle radius. * @param color The color to draw with (as Color). */ - void circle(int center_x, int center_y, int radius, Color color); + void circle(uint16_t center_x, uint16_t center_y, uint16_t radius, Color color); + /** * Draw a filled circled. * @param center_x The center x coordinate. @@ -716,7 +761,8 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * Use this [color picker](https://nodtem66.github.io/nextion-hmi-color-convert/index.html) to convert color codes to * Nextion HMI colors. */ - void filled_circle(int center_x, int center_y, int radius, uint16_t color); + void filled_circle(uint16_t center_x, uint16_t center_y, uint16_t radius, uint16_t color); + /** * Draw a filled circled. * @param center_x The center x coordinate. @@ -732,7 +778,8 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * Makes a filled circle at the x coordinate `25` and y coordinate `25` with a radius of `10` with the blue color. * Use [Nextion Instruction Set](https://nextion.tech/instruction-set/#s5) for a list of Nextion HMI colors constants. */ - void filled_circle(int center_x, int center_y, int radius, const char *color); + void filled_circle(uint16_t center_x, uint16_t center_y, uint16_t radius, const char *color); + /** * Draw a filled circled. * @param center_x The center x coordinate. @@ -748,7 +795,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * * Makes a filled circle at the x coordinate `25` and y coordinate `25` with a radius of `10` with blue color. */ - void filled_circle(int center_x, int center_y, int radius, Color color); + void filled_circle(uint16_t center_x, uint16_t center_y, uint16_t radius, Color color); /** * Draws a QR code in the screen @@ -768,8 +815,9 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * * Draws a QR code with a Wi-Fi network credentials starting at the given coordinates (25,25). */ - void qrcode(int x1, int y1, const char *content, int size = 200, uint16_t background_color = 65535, - uint16_t foreground_color = 0, int logo_pic = -1, uint8_t border_width = 8); + void qrcode(uint16_t x1, uint16_t y1, const char *content, uint16_t size = 200, uint16_t background_color = 65535, + uint16_t foreground_color = 0, uint8_t logo_pic = -1, uint8_t border_width = 8); + /** * Draws a QR code in the screen * @param x1 The top left x coordinate to start the QR code. @@ -791,8 +839,9 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * Draws a QR code with a Wi-Fi network credentials starting at the given coordinates (25,25) with size of 150px in * red on a blue background. */ - void qrcode(int x1, int y1, const char *content, int size, Color background_color = Color(255, 255, 255), - Color foreground_color = Color(0, 0, 0), int logo_pic = -1, uint8_t border_width = 8); + void qrcode(uint16_t x1, uint16_t y1, const char *content, uint16_t size, + Color background_color = Color(255, 255, 255), Color foreground_color = Color(0, 0, 0), + uint8_t logo_pic = -1, uint8_t border_width = 8); /** Set the brightness of the backlight. * @@ -806,6 +855,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * Changes the brightness of the display to 30%. */ void set_backlight_brightness(float brightness); + /** * Set the touch sleep timeout of the display. * @param timeout Timeout in seconds. @@ -819,6 +869,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * `thup`. */ void set_touch_sleep_timeout(uint16_t timeout); + /** * Sets which page Nextion loads when exiting sleep mode. Note this can be set even when Nextion is in sleep mode. * @param page_id The page id, from 0 to the lage page in Nextion. Set 255 (not set to any existing page) to @@ -832,6 +883,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * The display will wake up to page 2. */ void set_wake_up_page(uint8_t page_id = 255); + /** * Sets which page Nextion loads when connecting to ESPHome. * @param page_id The page id, from 0 to the lage page in Nextion. Set 255 (not set to any existing page) to @@ -859,6 +911,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * The display will wake up by touch. */ void set_auto_wake_on_touch(bool auto_wake); + /** * Sets if Nextion should exit the active reparse mode before the "connect" command is sent * @param exit_reparse True or false. When exit_reparse is true, the exit reparse command @@ -872,11 +925,13 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * The display will be requested to leave active reparse mode before setup. */ void set_exit_reparse_on_start(bool exit_reparse); + /** * Sets Nextion mode between sleep and awake * @param True or false. Sleep=true to enter sleep mode or sleep=false to exit sleep mode. */ void sleep(bool sleep); + /** * @brief Sets the Nextion display's protocol reparse mode. * @@ -928,7 +983,6 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * Set the tft file URL. https seems problematic with arduino.. */ void set_tft_url(const std::string &tft_url) { this->tft_url_ = tft_url; } - #endif /** @@ -992,9 +1046,9 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe void set_nextion_sensor_state(NextionQueueType queue_type, const std::string &name, float state); void set_nextion_text_state(const std::string &name, const std::string &state); - void add_no_result_to_queue_with_set(NextionComponentBase *component, int state_value) override; + void add_no_result_to_queue_with_set(NextionComponentBase *component, int32_t state_value) override; void add_no_result_to_queue_with_set(const std::string &variable_name, const std::string &variable_name_to_send, - int state_value) override; + int32_t state_value) override; void add_no_result_to_queue_with_set(NextionComponentBase *component, const std::string &state_value) override; void add_no_result_to_queue_with_set(const std::string &variable_name, const std::string &variable_name_to_send, @@ -1070,8 +1124,8 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe void process_serial_(); bool is_updating_ = false; uint32_t touch_sleep_timeout_ = 0; - int wake_up_page_ = -1; - int start_up_page_ = -1; + int16_t wake_up_page_ = -1; + int16_t start_up_page_ = -1; bool auto_wake_on_touch_ = true; bool exit_reparse_on_start_ = false; @@ -1089,7 +1143,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe __attribute__((format(printf, 3, 4))); void add_no_result_to_queue_with_set_internal_(const std::string &variable_name, - const std::string &variable_name_to_send, int state_value, + const std::string &variable_name_to_send, int32_t state_value, bool is_sleep_safe = false); void add_no_result_to_queue_with_set_internal_(const std::string &variable_name, @@ -1099,13 +1153,21 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe void check_pending_waveform_(); #ifdef USE_NEXTION_TFT_UPLOAD + uint32_t content_length_ = 0; + int tft_size_ = 0; + uint32_t original_baud_rate_ = 0; + bool upload_first_chunk_sent_ = false; + + std::string tft_url_; + uint8_t *transfer_buffer_{nullptr}; + size_t transfer_buffer_size_; + #ifdef USE_ESP8266 WiFiClient *wifi_client_{nullptr}; BearSSL::WiFiClientSecure *wifi_client_secure_{nullptr}; WiFiClient *get_wifi_client_(); #endif - int content_length_ = 0; - int tft_size_ = 0; + #ifdef ARDUINO /** * will request chunk_size chunks from the web server @@ -1178,13 +1240,6 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe void remove_front_no_sensors_(); -#ifdef USE_NEXTION_TFT_UPLOAD - std::string tft_url_; - uint8_t *transfer_buffer_{nullptr}; - size_t transfer_buffer_size_; - bool upload_first_chunk_sent_ = false; -#endif - #ifdef NEXTION_PROTOCOL_LOG void print_queue_members_(); #endif @@ -1192,8 +1247,8 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe std::string command_data_; bool is_connected_ = false; - uint32_t startup_override_ms_ = 8000; - uint32_t max_q_age_ms_ = 8000; + const uint16_t startup_override_ms_ = 8000; + const uint16_t max_q_age_ms_ = 8000; uint32_t started_ms_ = 0; bool sent_setup_commands_ = false; }; diff --git a/esphome/components/nextion/nextion_base.h b/esphome/components/nextion/nextion_base.h index f16eabc003..b88dd399f8 100644 --- a/esphome/components/nextion/nextion_base.h +++ b/esphome/components/nextion/nextion_base.h @@ -24,9 +24,9 @@ class NextionBase; class NextionBase { public: - virtual void add_no_result_to_queue_with_set(NextionComponentBase *component, int state_value) = 0; + virtual void add_no_result_to_queue_with_set(NextionComponentBase *component, int32_t state_value) = 0; virtual void add_no_result_to_queue_with_set(const std::string &variable_name, - const std::string &variable_name_to_send, int state_value) = 0; + const std::string &variable_name_to_send, int32_t state_value) = 0; virtual void add_no_result_to_queue_with_set(NextionComponentBase *component, const std::string &state_value) = 0; virtual void add_no_result_to_queue_with_set(const std::string &variable_name, diff --git a/esphome/components/nextion/nextion_commands.cpp b/esphome/components/nextion/nextion_commands.cpp index a2325861a3..fdd6c74d99 100644 --- a/esphome/components/nextion/nextion_commands.cpp +++ b/esphome/components/nextion/nextion_commands.cpp @@ -144,11 +144,11 @@ void Nextion::set_component_pressed_font_color(const char *component, Color colo // Set picture void Nextion::set_component_pic(const char *component, uint8_t pic_id) { - this->add_no_result_to_queue_with_printf_("set_component_pic", "%s.pic=%d", component, pic_id); + this->add_no_result_to_queue_with_printf_("set_component_pic", "%s.pic=%" PRIu8, component, pic_id); } void Nextion::set_component_picc(const char *component, uint8_t pic_id) { - this->add_no_result_to_queue_with_printf_("set_component_pic", "%s.picc=%d", component, pic_id); + this->add_no_result_to_queue_with_printf_("set_component_pic", "%s.picc=%" PRIu8, component, pic_id); } void Nextion::set_component_text_printf(const char *component, const char *format, ...) { @@ -179,7 +179,7 @@ void Nextion::set_auto_wake_on_touch(bool auto_wake) { // 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=%d", component, font_id); + this->add_no_result_to_queue_with_printf_("set_component_font", "%s.font=%" PRIu8, component, font_id); } void Nextion::hide_component(const char *component) { @@ -199,113 +199,130 @@ void Nextion::disable_component_touch(const char *component) { } void Nextion::set_component_picture(const char *component, uint8_t picture_id) { - this->add_no_result_to_queue_with_printf_("set_component_picture", "%s.pic=%d", component, picture_id); + this->add_no_result_to_queue_with_printf_("set_component_picture", "%s.pic=%" PRIu8, component, picture_id); } 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); } -void Nextion::set_component_value(const char *component, int value) { - this->add_no_result_to_queue_with_printf_("set_component_value", "%s.val=%d", component, value); +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); } -void Nextion::add_waveform_data(int component_id, uint8_t channel_number, uint8_t value) { - this->add_no_result_to_queue_with_printf_("add_waveform_data", "add %d,%u,%u", component_id, channel_number, 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); } -void Nextion::open_waveform_channel(int component_id, uint8_t channel_number, uint8_t value) { - this->add_no_result_to_queue_with_printf_("open_waveform_channel", "addt %d,%u,%u", 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); } -void Nextion::set_component_coordinates(const char *component, int x, int y) { - this->add_no_result_to_queue_with_printf_("set_component_coordinates command 1", "%s.xcen=%d", component, x); - this->add_no_result_to_queue_with_printf_("set_component_coordinates command 2", "%s.ycen=%d", component, y); +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); } // Drawing -void Nextion::display_picture(int picture_id, int x_start, int y_start) { - this->add_no_result_to_queue_with_printf_("display_picture", "pic %d, %d, %d", x_start, y_start, picture_id); +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); } -void Nextion::fill_area(int x1, int y1, int width, int height, uint16_t color) { - this->add_no_result_to_queue_with_printf_("fill_area", "fill %d,%d,%d,%d,%" PRIu16, x1, y1, width, height, color); +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(int x1, int y1, int width, int height, const char *color) { - this->add_no_result_to_queue_with_printf_("fill_area", "fill %d,%d,%d,%d,%s", 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, + y1, width, height, color); } -void Nextion::fill_area(int x1, int y1, int width, int height, Color color) { - this->add_no_result_to_queue_with_printf_("fill_area", "fill %d,%d,%d,%d,%d", x1, y1, width, height, - display::ColorUtil::color_to_565(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)); } -void Nextion::line(int x1, int y1, int x2, int y2, uint16_t color) { - this->add_no_result_to_queue_with_printf_("line", "line %d,%d,%d,%d,%" PRIu16, x1, y1, x2, y2, color); +void Nextion::line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) { + this->add_no_result_to_queue_with_printf_("line", "line %" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu16, x1, + y1, x2, y2, color); } -void Nextion::line(int x1, int y1, int x2, int y2, const char *color) { - this->add_no_result_to_queue_with_printf_("line", "line %d,%d,%d,%d,%s", x1, y1, x2, y2, color); +void Nextion::line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, const char *color) { + this->add_no_result_to_queue_with_printf_("line", "line %" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%s", x1, y1, + x2, y2, color); } -void Nextion::line(int x1, int y1, int x2, int y2, Color color) { - this->add_no_result_to_queue_with_printf_("line", "line %d,%d,%d,%d,%d", x1, y1, x2, y2, - display::ColorUtil::color_to_565(color)); +void Nextion::line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, Color color) { + this->add_no_result_to_queue_with_printf_("line", "line %" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu16, x1, + y1, x2, y2, display::ColorUtil::color_to_565(color)); } -void Nextion::rectangle(int x1, int y1, int width, int height, uint16_t color) { - this->add_no_result_to_queue_with_printf_("draw", "draw %d,%d,%d,%d,%" PRIu16, x1, y1, x1 + width, y1 + height, +void Nextion::rectangle(uint16_t x1, uint16_t y1, uint16_t width, uint16_t height, uint16_t color) { + this->add_no_result_to_queue_with_printf_("draw", "draw %" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu16, x1, + y1, static_cast(x1 + width), static_cast(y1 + height), color); } -void Nextion::rectangle(int x1, int y1, int width, int height, const char *color) { - this->add_no_result_to_queue_with_printf_("draw", "draw %d,%d,%d,%d,%s", x1, y1, x1 + width, y1 + height, color); +void Nextion::rectangle(uint16_t x1, uint16_t y1, uint16_t width, uint16_t height, const char *color) { + this->add_no_result_to_queue_with_printf_("draw", "draw %" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%s", x1, y1, + static_cast(x1 + width), static_cast(y1 + height), + color); } -void Nextion::rectangle(int x1, int y1, int width, int height, Color color) { - this->add_no_result_to_queue_with_printf_("draw", "draw %d,%d,%d,%d,%d", x1, y1, x1 + width, y1 + height, +void Nextion::rectangle(uint16_t x1, uint16_t y1, uint16_t width, uint16_t height, Color color) { + this->add_no_result_to_queue_with_printf_("draw", "draw %" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu16, x1, + y1, static_cast(x1 + width), static_cast(y1 + height), display::ColorUtil::color_to_565(color)); } -void Nextion::circle(int center_x, int center_y, int radius, uint16_t color) { - this->add_no_result_to_queue_with_printf_("cir", "cir %d,%d,%d,%" PRIu16, center_x, center_y, radius, color); +void Nextion::circle(uint16_t center_x, uint16_t center_y, uint16_t radius, uint16_t color) { + this->add_no_result_to_queue_with_printf_("cir", "cir %" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu16, center_x, + center_y, radius, color); } -void Nextion::circle(int center_x, int center_y, int radius, const char *color) { - this->add_no_result_to_queue_with_printf_("cir", "cir %d,%d,%d,%s", center_x, center_y, radius, color); +void Nextion::circle(uint16_t center_x, uint16_t center_y, uint16_t radius, const char *color) { + this->add_no_result_to_queue_with_printf_("cir", "cir %" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%s", center_x, center_y, + radius, color); } -void Nextion::circle(int center_x, int center_y, int radius, Color color) { - this->add_no_result_to_queue_with_printf_("cir", "cir %d,%d,%d,%d", center_x, center_y, radius, - display::ColorUtil::color_to_565(color)); +void Nextion::circle(uint16_t center_x, uint16_t center_y, uint16_t radius, Color color) { + this->add_no_result_to_queue_with_printf_("cir", "cir %" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu16, center_x, + center_y, radius, display::ColorUtil::color_to_565(color)); } -void Nextion::filled_circle(int center_x, int center_y, int radius, uint16_t color) { - this->add_no_result_to_queue_with_printf_("cirs", "cirs %d,%d,%d,%" PRIu16, center_x, center_y, radius, color); +void Nextion::filled_circle(uint16_t center_x, uint16_t center_y, uint16_t radius, uint16_t color) { + this->add_no_result_to_queue_with_printf_("cirs", "cirs %" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu16, center_x, + center_y, radius, color); } -void Nextion::filled_circle(int center_x, int center_y, int radius, const char *color) { - this->add_no_result_to_queue_with_printf_("cirs", "cirs %d,%d,%d,%s", center_x, center_y, radius, color); +void Nextion::filled_circle(uint16_t center_x, uint16_t center_y, uint16_t radius, const char *color) { + this->add_no_result_to_queue_with_printf_("cirs", "cirs %" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%s", center_x, center_y, + radius, color); } -void Nextion::filled_circle(int center_x, int center_y, int radius, Color color) { - this->add_no_result_to_queue_with_printf_("cirs", "cirs %d,%d,%d,%d", center_x, center_y, radius, - display::ColorUtil::color_to_565(color)); +void Nextion::filled_circle(uint16_t center_x, uint16_t center_y, uint16_t radius, Color color) { + this->add_no_result_to_queue_with_printf_("cirs", "cirs %" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu16, center_x, + center_y, radius, display::ColorUtil::color_to_565(color)); } -void Nextion::qrcode(int x1, int y1, const char *content, int size, uint16_t background_color, - uint16_t foreground_color, int logo_pic, uint8_t border_width) { - this->add_no_result_to_queue_with_printf_("qrcode", "qrcode %d,%d,%d,%d,%d,%d,%d,\"%s\"", x1, y1, size, - background_color, foreground_color, logo_pic, border_width, content); -} - -void Nextion::qrcode(int x1, int y1, const char *content, int size, Color background_color, Color foreground_color, - int logo_pic, uint8_t border_width) { +void Nextion::qrcode(uint16_t x1, uint16_t y1, const char *content, uint16_t size, uint16_t background_color, + uint16_t foreground_color, uint8_t logo_pic, uint8_t border_width) { this->add_no_result_to_queue_with_printf_( - "qrcode", "qrcode %d,%d,%d,%d,%d,%d,%d,\"%s\"", x1, y1, size, display::ColorUtil::color_to_565(background_color), - display::ColorUtil::color_to_565(foreground_color), logo_pic, border_width, content); + "qrcode", "qrcode %" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu8 ",%" 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, uint8_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, + y1, size, display::ColorUtil::color_to_565(background_color), display::ColorUtil::color_to_565(foreground_color), + logo_pic, border_width, content); } void Nextion::set_nextion_rtc_time(ESPTime time) { From 2fed6955de41aad58f353d3feed5e5fcb1e70ddc Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Thu, 18 Apr 2024 10:11:00 +1000 Subject: [PATCH 1277/2101] On failure, dump the output of preceding jobs in CI status (#6564) --- .github/workflows/ci.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7df57acb08..d3ac7981d3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -472,6 +472,7 @@ jobs: - compile-tests - clang-tidy - test-build-components + - list-components if: always() steps: - name: Success @@ -479,4 +480,8 @@ jobs: run: exit 0 - name: Failure if: ${{ contains(needs.*.result, 'failure') }} - run: exit 1 + env: + JSON_DOC: ${{ toJSON(needs) }} + run: | + echo $JSON_DOC | jq + exit 1 From 2e7ac26adacd5a7c1aa02ff47de785f4b9e79fee Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Thu, 18 Apr 2024 04:16:49 +0200 Subject: [PATCH 1278/2101] Nextion `send_command` method (#6540) This is a simplified version of `send_command_printf` without the `printf` support. Manually send a raw command to the display. param command The pcommand, like "page 0" return Whether the send was successful. --- esphome/components/nextion/nextion.cpp | 11 +++++++++++ esphome/components/nextion/nextion.h | 6 ++++++ 2 files changed, 17 insertions(+) diff --git a/esphome/components/nextion/nextion.cpp b/esphome/components/nextion/nextion.cpp index 8de5ca9143..ddbd3328ef 100644 --- a/esphome/components/nextion/nextion.cpp +++ b/esphome/components/nextion/nextion.cpp @@ -194,6 +194,17 @@ void Nextion::update_all_components() { } } +bool Nextion::send_command(const char *command) { + if ((!this->is_setup() && !this->ignore_is_setup_) || this->is_sleeping()) + return false; + + if (this->send_command_(command)) { + this->add_no_result_to_queue_("send_command"); + return true; + } + return false; +} + bool Nextion::send_command_printf(const char *format, ...) { if ((!this->is_setup() && !this->ignore_is_setup_) || this->is_sleeping()) return false; diff --git a/esphome/components/nextion/nextion.h b/esphome/components/nextion/nextion.h index bc75df3ce6..a8f0ea8ba9 100644 --- a/esphome/components/nextion/nextion.h +++ b/esphome/components/nextion/nextion.h @@ -970,6 +970,12 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe // This function has been deprecated void set_wait_for_ack(bool wait_for_ack); + /** + * Manually send a raw command to the display. + * @param command The pcommand, like "page 0" + * @return Whether the send was successful. + */ + bool send_command(const char *command); /** * Manually send a raw formatted command to the display. * @param format The printf-style command format, like "vis %s,0" From 8c31aea94fca4d83e7357593c0567e0b381135d0 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Thu, 18 Apr 2024 15:03:15 +1000 Subject: [PATCH 1279/2101] Fix some printf formats for size_t. (#6542) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/select/select.cpp | 2 +- esphome/components/select/select_call.cpp | 2 +- esphome/components/sensor/filter.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/select/select.cpp b/esphome/components/select/select.cpp index f4583b4e2e..806882ad94 100644 --- a/esphome/components/select/select.cpp +++ b/esphome/components/select/select.cpp @@ -12,7 +12,7 @@ void Select::publish_state(const std::string &state) { if (index.has_value()) { this->has_state_ = true; this->state = state; - ESP_LOGD(TAG, "'%s': Sending state %s (index %d)", name, state.c_str(), index.value()); + ESP_LOGD(TAG, "'%s': Sending state %s (index %zu)", name, state.c_str(), index.value()); this->state_callback_.call(state, index.value()); } else { ESP_LOGE(TAG, "'%s': invalid state for publish_state(): %s", name, state.c_str()); diff --git a/esphome/components/select/select_call.cpp b/esphome/components/select/select_call.cpp index 6ee41b1029..85f755645c 100644 --- a/esphome/components/select/select_call.cpp +++ b/esphome/components/select/select_call.cpp @@ -71,7 +71,7 @@ void SelectCall::perform() { return; } if (this->index_.value() >= options.size()) { - ESP_LOGW(TAG, "'%s' - Index value %d out of bounds", name, this->index_.value()); + ESP_LOGW(TAG, "'%s' - Index value %zu out of bounds", name, this->index_.value()); return; } target_value = options[this->index_.value()]; diff --git a/esphome/components/sensor/filter.cpp b/esphome/components/sensor/filter.cpp index 6d7acad7e0..3f67af59be 100644 --- a/esphome/components/sensor/filter.cpp +++ b/esphome/components/sensor/filter.cpp @@ -79,7 +79,7 @@ SkipInitialFilter::SkipInitialFilter(size_t num_to_ignore) : num_to_ignore_(num_ optional SkipInitialFilter::new_value(float value) { if (num_to_ignore_ > 0) { num_to_ignore_--; - ESP_LOGV(TAG, "SkipInitialFilter(%p)::new_value(%f) SKIPPING, %u left", this, value, num_to_ignore_); + ESP_LOGV(TAG, "SkipInitialFilter(%p)::new_value(%f) SKIPPING, %zu left", this, value, num_to_ignore_); return {}; } From 655dbc48b5f7e53a4ceee83f4aa159e276d8b864 Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Thu, 18 Apr 2024 14:52:22 -0700 Subject: [PATCH 1280/2101] remove delay from tmp102 (#6577) Co-authored-by: Samuel Sieb --- esphome/components/tmp102/tmp102.cpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/esphome/components/tmp102/tmp102.cpp b/esphome/components/tmp102/tmp102.cpp index be60a2d8d4..f35fbf5d4b 100644 --- a/esphome/components/tmp102/tmp102.cpp +++ b/esphome/components/tmp102/tmp102.cpp @@ -28,23 +28,24 @@ void TMP102Component::dump_config() { } void TMP102Component::update() { - int16_t raw_temperature; if (this->write(&TMP102_REGISTER_TEMPERATURE, 1) != i2c::ERROR_OK) { this->status_set_warning(); return; } - delay(50); // NOLINT - if (this->read(reinterpret_cast(&raw_temperature), 2) != i2c::ERROR_OK) { - this->status_set_warning(); - return; - } - raw_temperature = i2c::i2ctohs(raw_temperature); - raw_temperature = raw_temperature >> 4; - float temperature = raw_temperature * TMP102_CONVERSION_FACTOR; - ESP_LOGD(TAG, "Got Temperature=%.1f°C", temperature); + this->set_timeout("read_temp", 50, [this]() { + int16_t raw_temperature; + if (this->read(reinterpret_cast(&raw_temperature), 2) != i2c::ERROR_OK) { + this->status_set_warning(); + return; + } + raw_temperature = i2c::i2ctohs(raw_temperature); + raw_temperature = raw_temperature >> 4; + float temperature = raw_temperature * TMP102_CONVERSION_FACTOR; + ESP_LOGD(TAG, "Got Temperature=%.1f°C", temperature); - this->publish_state(temperature); - this->status_clear_warning(); + this->publish_state(temperature); + this->status_clear_warning(); + }); } float TMP102Component::get_setup_priority() const { return setup_priority::DATA; } From 45ae78de03cbed77809f51ee89f461d68fd66907 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 22 Apr 2024 10:29:56 +1200 Subject: [PATCH 1281/2101] =?UTF-8?q?Create=20``component=5Fdir``=20substi?= =?UTF-8?q?tution=20for=20local=20files=20to=20be=20included=20in=E2=80=A6?= =?UTF-8?q?=20(#6575)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- script/ci-custom.py | 2 +- tests/components/font/Monocraft.ttf | Bin 0 -> 202764 bytes tests/components/font/common.yaml | 38 ++++++++++++++++ tests/components/font/test.esp32-c3-idf.yaml | 24 +++------- tests/components/font/test.esp32-c3.yaml | 24 +++------- tests/components/font/test.esp32-idf.yaml | 24 +++------- tests/components/font/test.esp32.yaml | 43 +++--------------- tests/components/font/test.esp8266.yaml | 24 +++------- tests/components/font/test.rp2040.yaml | 24 +++------- .../build_components_base.bk72xx.yaml | 1 + .../build_components_base.esp32-ard.yaml | 1 + .../build_components_base.esp32-c3-ard.yaml | 1 + .../build_components_base.esp32-c3-idf.yaml | 1 + .../build_components_base.esp32-idf.yaml | 1 + .../build_components_base.esp32-s2-ard.yaml | 1 + .../build_components_base.esp32-s2-idf.yaml | 1 + .../build_components_base.esp32-s3-ard.yaml | 1 + .../build_components_base.esp32-s3-idf.yaml | 1 + .../build_components_base.esp8266.yaml | 1 + .../build_components_base.host.yaml | 1 + .../build_components_base.rp2040.yaml | 1 + 21 files changed, 87 insertions(+), 128 deletions(-) create mode 100644 tests/components/font/Monocraft.ttf create mode 100644 tests/components/font/common.yaml diff --git a/script/ci-custom.py b/script/ci-custom.py index 3be7be76a2..c3cfc7a331 100755 --- a/script/ci-custom.py +++ b/script/ci-custom.py @@ -58,7 +58,7 @@ file_types = ( ) cpp_include = ("*.h", "*.c", "*.cpp", "*.tcc") py_include = ("*.py",) -ignore_types = (".ico", ".png", ".woff", ".woff2", "") +ignore_types = (".ico", ".png", ".woff", ".woff2", "", ".ttf", ".otf") LINT_FILE_CHECKS = [] LINT_CONTENT_CHECKS = [] diff --git a/tests/components/font/Monocraft.ttf b/tests/components/font/Monocraft.ttf new file mode 100644 index 0000000000000000000000000000000000000000..4066b0a9889c2505d31b953487ac1d48fafaf9e9 GIT binary patch literal 202764 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

aqJ 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 H`;q?xJ@PKt literal 0 HcmV?d00001 diff --git a/tests/components/font/common.yaml b/tests/components/font/common.yaml new file mode 100644 index 0000000000..a81457a05d --- /dev/null +++ b/tests/components/font/common.yaml @@ -0,0 +1,38 @@ +font: + - file: "gfonts://Roboto" + id: roboto + size: 20 + glyphs: "0123456789." + extras: + - file: "gfonts://Roboto" + glyphs: ["\u00C4", "\u00C5", "\U000000C7"] + - file: "gfonts://Roboto" + id: roboto_web + size: 20 + - file: "https://github.com/IdreesInc/Monocraft/releases/download/v3.0/Monocraft.ttf" + id: monocraft + size: 20 + - file: + type: web + url: "https://github.com/IdreesInc/Monocraft/releases/download/v3.0/Monocraft.ttf" + id: monocraft2 + size: 24 + - file: $component_dir/Monocraft.ttf + id: monocraft3 + size: 28 + +i2c: + scl: ${i2c_scl} + sda: ${i2c_sda} + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: ${display_reset_pin} + lambda: |- + it.print(0, 0, id(roboto), "Hello, World!"); + it.print(0, 20, id(roboto_web), "Hello, World!"); + it.print(0, 40, id(monocraft), "Hello, World!"); + it.print(0, 60, id(monocraft2), "Hello, World!"); + it.print(0, 80, id(monocraft3), "Hello, World!"); diff --git a/tests/components/font/test.esp32-c3-idf.yaml b/tests/components/font/test.esp32-c3-idf.yaml index b63b4d025a..ad14a2e9a6 100644 --- a/tests/components/font/test.esp32-c3-idf.yaml +++ b/tests/components/font/test.esp32-c3-idf.yaml @@ -1,19 +1,7 @@ -i2c: - - id: i2c_font - scl: 5 - sda: 4 +substitutions: + i2c_scl: GPIO5 + i2c_sda: GPIO4 + display_reset_pin: GPIO3 -display: - - platform: ssd1306_i2c - id: ssd1306_display - model: SSD1306_128X64 - reset_pin: 3 - pages: - - id: page1 - lambda: |- - it.rectangle(0, 0, it.get_width(), it.get_height()); - -font: - - file: "gfonts://Roboto" - id: roboto - size: 20 +packages: + common: !include common.yaml diff --git a/tests/components/font/test.esp32-c3.yaml b/tests/components/font/test.esp32-c3.yaml index b63b4d025a..ad14a2e9a6 100644 --- a/tests/components/font/test.esp32-c3.yaml +++ b/tests/components/font/test.esp32-c3.yaml @@ -1,19 +1,7 @@ -i2c: - - id: i2c_font - scl: 5 - sda: 4 +substitutions: + i2c_scl: GPIO5 + i2c_sda: GPIO4 + display_reset_pin: GPIO3 -display: - - platform: ssd1306_i2c - id: ssd1306_display - model: SSD1306_128X64 - reset_pin: 3 - pages: - - id: page1 - lambda: |- - it.rectangle(0, 0, it.get_width(), it.get_height()); - -font: - - file: "gfonts://Roboto" - id: roboto - size: 20 +packages: + common: !include common.yaml diff --git a/tests/components/font/test.esp32-idf.yaml b/tests/components/font/test.esp32-idf.yaml index dcf8fb49d5..d98600a51b 100644 --- a/tests/components/font/test.esp32-idf.yaml +++ b/tests/components/font/test.esp32-idf.yaml @@ -1,19 +1,7 @@ -i2c: - - id: i2c_font - scl: 16 - sda: 17 +substitutions: + i2c_scl: GPIO16 + i2c_sda: GPIO17 + display_reset_pin: GPIO13 -display: - - platform: ssd1306_i2c - id: ssd1306_display - model: SSD1306_128X64 - reset_pin: 13 - pages: - - id: page1 - lambda: |- - it.rectangle(0, 0, it.get_width(), it.get_height()); - -font: - - file: "gfonts://Roboto" - id: roboto - size: 20 +packages: + common: !include common.yaml diff --git a/tests/components/font/test.esp32.yaml b/tests/components/font/test.esp32.yaml index d142463893..d98600a51b 100644 --- a/tests/components/font/test.esp32.yaml +++ b/tests/components/font/test.esp32.yaml @@ -1,38 +1,7 @@ -font: - - file: "gfonts://Roboto" - id: roboto - size: 20 - glyphs: "0123456789." - extras: - - file: "gfonts://Roboto" - glyphs: ["\u00C4", "\u00C5", "\U000000C7"] - - file: "gfonts://Roboto" - id: roboto_web - size: 20 - - file: "https://github.com/IdreesInc/Monocraft/releases/download/v3.0/Monocraft.ttf" - id: monocraft - size: 20 - - file: - type: web - url: "https://github.com/IdreesInc/Monocraft/releases/download/v3.0/Monocraft.ttf" - id: monocraft2 - size: 24 - -spi: - clk_pin: 14 - mosi_pin: 13 - -display: - - id: my_display - platform: ili9xxx - dimensions: 480x320 - model: ST7796 - cs_pin: 15 - dc_pin: 21 - reset_pin: 22 - transform: - swap_xy: true - mirror_x: true - mirror_y: true - auto_clear_enabled: false +substitutions: + i2c_scl: GPIO16 + i2c_sda: GPIO17 + display_reset_pin: GPIO13 +packages: + common: !include common.yaml diff --git a/tests/components/font/test.esp8266.yaml b/tests/components/font/test.esp8266.yaml index b63b4d025a..ad14a2e9a6 100644 --- a/tests/components/font/test.esp8266.yaml +++ b/tests/components/font/test.esp8266.yaml @@ -1,19 +1,7 @@ -i2c: - - id: i2c_font - scl: 5 - sda: 4 +substitutions: + i2c_scl: GPIO5 + i2c_sda: GPIO4 + display_reset_pin: GPIO3 -display: - - platform: ssd1306_i2c - id: ssd1306_display - model: SSD1306_128X64 - reset_pin: 3 - pages: - - id: page1 - lambda: |- - it.rectangle(0, 0, it.get_width(), it.get_height()); - -font: - - file: "gfonts://Roboto" - id: roboto - size: 20 +packages: + common: !include common.yaml diff --git a/tests/components/font/test.rp2040.yaml b/tests/components/font/test.rp2040.yaml index b63b4d025a..ad14a2e9a6 100644 --- a/tests/components/font/test.rp2040.yaml +++ b/tests/components/font/test.rp2040.yaml @@ -1,19 +1,7 @@ -i2c: - - id: i2c_font - scl: 5 - sda: 4 +substitutions: + i2c_scl: GPIO5 + i2c_sda: GPIO4 + display_reset_pin: GPIO3 -display: - - platform: ssd1306_i2c - id: ssd1306_display - model: SSD1306_128X64 - reset_pin: 3 - pages: - - id: page1 - lambda: |- - it.rectangle(0, 0, it.get_width(), it.get_height()); - -font: - - file: "gfonts://Roboto" - id: roboto - size: 20 +packages: + common: !include common.yaml diff --git a/tests/test_build_components/build_components_base.bk72xx.yaml b/tests/test_build_components/build_components_base.bk72xx.yaml index 7fdaebc768..d74cc651eb 100644 --- a/tests/test_build_components/build_components_base.bk72xx.yaml +++ b/tests/test_build_components/build_components_base.bk72xx.yaml @@ -16,3 +16,4 @@ packages: test_name: $test_name target_platform: $target_platform component_test_file: $component_test_file + component_dir: "../../components/$component_name" diff --git a/tests/test_build_components/build_components_base.esp32-ard.yaml b/tests/test_build_components/build_components_base.esp32-ard.yaml index f460c57298..e345adcafc 100644 --- a/tests/test_build_components/build_components_base.esp32-ard.yaml +++ b/tests/test_build_components/build_components_base.esp32-ard.yaml @@ -18,3 +18,4 @@ packages: test_name: $test_name target_platform: $target_platform component_test_file: $component_test_file + component_dir: "../../components/$component_name" diff --git a/tests/test_build_components/build_components_base.esp32-c3-ard.yaml b/tests/test_build_components/build_components_base.esp32-c3-ard.yaml index 8a52e0c916..136ee62d4b 100644 --- a/tests/test_build_components/build_components_base.esp32-c3-ard.yaml +++ b/tests/test_build_components/build_components_base.esp32-c3-ard.yaml @@ -18,3 +18,4 @@ packages: test_name: $test_name target_platform: $target_platform component_test_file: $component_test_file + component_dir: "../../components/$component_name" diff --git a/tests/test_build_components/build_components_base.esp32-c3-idf.yaml b/tests/test_build_components/build_components_base.esp32-c3-idf.yaml index 6b4b61fe58..4e809dd7ce 100644 --- a/tests/test_build_components/build_components_base.esp32-c3-idf.yaml +++ b/tests/test_build_components/build_components_base.esp32-c3-idf.yaml @@ -18,3 +18,4 @@ packages: test_name: $test_name target_platform: $target_platform component_test_file: $component_test_file + component_dir: "../../components/$component_name" diff --git a/tests/test_build_components/build_components_base.esp32-idf.yaml b/tests/test_build_components/build_components_base.esp32-idf.yaml index ab1bda2a19..3c4532a958 100644 --- a/tests/test_build_components/build_components_base.esp32-idf.yaml +++ b/tests/test_build_components/build_components_base.esp32-idf.yaml @@ -18,3 +18,4 @@ packages: test_name: $test_name target_platform: $target_platform component_test_file: $component_test_file + component_dir: "../../components/$component_name" diff --git a/tests/test_build_components/build_components_base.esp32-s2-ard.yaml b/tests/test_build_components/build_components_base.esp32-s2-ard.yaml index ffb912d3d9..db62cdff6a 100644 --- a/tests/test_build_components/build_components_base.esp32-s2-ard.yaml +++ b/tests/test_build_components/build_components_base.esp32-s2-ard.yaml @@ -19,3 +19,4 @@ packages: test_name: $test_name target_platform: $target_platform component_test_file: $component_test_file + component_dir: "../../components/$component_name" diff --git a/tests/test_build_components/build_components_base.esp32-s2-idf.yaml b/tests/test_build_components/build_components_base.esp32-s2-idf.yaml index 4d1378b2b2..19fb657d8b 100644 --- a/tests/test_build_components/build_components_base.esp32-s2-idf.yaml +++ b/tests/test_build_components/build_components_base.esp32-s2-idf.yaml @@ -19,3 +19,4 @@ packages: test_name: $test_name target_platform: $target_platform component_test_file: $component_test_file + component_dir: "../../components/$component_name" diff --git a/tests/test_build_components/build_components_base.esp32-s3-ard.yaml b/tests/test_build_components/build_components_base.esp32-s3-ard.yaml index c850c9665f..39e12de08c 100644 --- a/tests/test_build_components/build_components_base.esp32-s3-ard.yaml +++ b/tests/test_build_components/build_components_base.esp32-s3-ard.yaml @@ -19,3 +19,4 @@ packages: test_name: $test_name target_platform: $target_platform component_test_file: $component_test_file + component_dir: "../../components/$component_name" diff --git a/tests/test_build_components/build_components_base.esp32-s3-idf.yaml b/tests/test_build_components/build_components_base.esp32-s3-idf.yaml index a43a2a6736..95c73f917e 100644 --- a/tests/test_build_components/build_components_base.esp32-s3-idf.yaml +++ b/tests/test_build_components/build_components_base.esp32-s3-idf.yaml @@ -19,3 +19,4 @@ packages: test_name: $test_name target_platform: $target_platform component_test_file: $component_test_file + component_dir: "../../components/$component_name" diff --git a/tests/test_build_components/build_components_base.esp8266.yaml b/tests/test_build_components/build_components_base.esp8266.yaml index d7bdc03659..0019298ef0 100644 --- a/tests/test_build_components/build_components_base.esp8266.yaml +++ b/tests/test_build_components/build_components_base.esp8266.yaml @@ -16,3 +16,4 @@ packages: test_name: $test_name target_platform: $target_platform component_test_file: $component_test_file + component_dir: "../../components/$component_name" diff --git a/tests/test_build_components/build_components_base.host.yaml b/tests/test_build_components/build_components_base.host.yaml index 00b252da2d..ec7570d99a 100644 --- a/tests/test_build_components/build_components_base.host.yaml +++ b/tests/test_build_components/build_components_base.host.yaml @@ -16,3 +16,4 @@ packages: test_name: $test_name target_platform: $target_platform component_test_file: $component_test_file + component_dir: "../../components/$component_name" diff --git a/tests/test_build_components/build_components_base.rp2040.yaml b/tests/test_build_components/build_components_base.rp2040.yaml index a02942ea35..cb1cb6359b 100644 --- a/tests/test_build_components/build_components_base.rp2040.yaml +++ b/tests/test_build_components/build_components_base.rp2040.yaml @@ -19,3 +19,4 @@ packages: test_name: $test_name target_platform: $target_platform component_test_file: $component_test_file + component_dir: "../../components/$component_name" From 16e0b78c643867e94fde5fe912f08c77f5ab6921 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Mon, 22 Apr 2024 13:05:50 +0200 Subject: [PATCH 1282/2101] Define `USE_ESP32_BLE` (#6585) --- esphome/components/esp32_ble/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/components/esp32_ble/__init__.py b/esphome/components/esp32_ble/__init__.py index 57a7341505..088a3b6d1e 100644 --- a/esphome/components/esp32_ble/__init__.py +++ b/esphome/components/esp32_ble/__init__.py @@ -65,6 +65,8 @@ async def to_code(config): add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True) add_idf_sdkconfig_option("CONFIG_BT_BLE_42_FEATURES_SUPPORTED", True) + cg.add_define("USE_ESP32_BLE") + @automation.register_condition("ble.enabled", BLEEnabledCondition, cv.Schema({})) async def ble_enabled_to_code(config, condition_id, template_arg, args): From 927caf062bab2e08e483666b3d67b94c4a6fb764 Mon Sep 17 00:00:00 2001 From: Javier Peletier Date: Mon, 22 Apr 2024 22:48:06 +0200 Subject: [PATCH 1283/2101] wifi: fix reconnect issue due to enablement of fast connect (#6598) --- esphome/components/wifi/wifi_component.cpp | 8 ++++++-- esphome/components/wifi/wifi_component.h | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 8f46bf29a0..075e683bb5 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -128,7 +128,7 @@ void WiFiComponent::loop() { case WIFI_COMPONENT_STATE_COOLDOWN: { this->status_set_warning(); if (millis() - this->action_started_ > 5000) { - if (this->fast_connect_) { + if (this->fast_connect_ || this->retry_hidden_) { this->start_connecting(this->sta_[0], false); } else { this->start_scanning(); @@ -591,6 +591,9 @@ void WiFiComponent::check_connecting_finished() { return; } + // We won't retry hidden networks unless a reconnect fails more than three times again + this->retry_hidden_ = false; + ESP_LOGI(TAG, "WiFi Connected!"); this->print_connect_params_(); @@ -668,10 +671,11 @@ void WiFiComponent::retry_connect() { this->wifi_mode_(false, {}); delay(100); // NOLINT this->num_retried_ = 0; + this->retry_hidden_ = false; } else { // Try hidden networks after 3 failed retries ESP_LOGD(TAG, "Retrying with hidden networks..."); - this->fast_connect_ = true; + this->retry_hidden_ = true; this->num_retried_++; } } else { diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index d9cb6a9ae2..133fa2970c 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -371,6 +371,7 @@ class WiFiComponent : public Component { std::vector sta_priorities_; WiFiAP selected_ap_; bool fast_connect_{false}; + bool retry_hidden_{false}; bool has_ap_{false}; WiFiAP ap_; From 50e3ce4c809489a5cd2b0166d7120d1c990d0c0d Mon Sep 17 00:00:00 2001 From: Mat931 <49403702+Mat931@users.noreply.github.com> Date: Mon, 22 Apr 2024 20:59:06 +0000 Subject: [PATCH 1284/2101] Calibrate Beken internal temperature (#6599) --- .../internal_temperature/internal_temperature.cpp | 8 +++++--- tests/components/internal_temperature/test.bk72xx.yaml | 3 +++ .../internal_temperature/test.esp32-c3-idf.yaml | 3 +++ tests/components/internal_temperature/test.esp32-c3.yaml | 3 +++ tests/components/internal_temperature/test.esp32-idf.yaml | 3 +++ tests/components/internal_temperature/test.esp32.yaml | 3 +++ tests/components/internal_temperature/test.rp2040.yaml | 3 +++ 7 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 tests/components/internal_temperature/test.bk72xx.yaml create mode 100644 tests/components/internal_temperature/test.esp32-c3-idf.yaml create mode 100644 tests/components/internal_temperature/test.esp32-c3.yaml create mode 100644 tests/components/internal_temperature/test.esp32-idf.yaml create mode 100644 tests/components/internal_temperature/test.esp32.yaml create mode 100644 tests/components/internal_temperature/test.rp2040.yaml diff --git a/esphome/components/internal_temperature/internal_temperature.cpp b/esphome/components/internal_temperature/internal_temperature.cpp index 255d95f6f8..47f516f568 100644 --- a/esphome/components/internal_temperature/internal_temperature.cpp +++ b/esphome/components/internal_temperature/internal_temperature.cpp @@ -55,11 +55,13 @@ void InternalTemperatureSensor::update() { uint32_t raw, result; result = temp_single_get_current_temperature(&raw); success = (result == 0); -#ifdef USE_LIBRETINY_VARIANT_BK7231T +#if defined(USE_LIBRETINY_VARIANT_BK7231N) + temperature = raw * -0.38f + 156.0f; +#elif defined(USE_LIBRETINY_VARIANT_BK7231T) temperature = raw * 0.04f; -#else +#else // USE_LIBRETINY_VARIANT temperature = raw * 0.128f; -#endif // USE_LIBRETINY_VARIANT_BK7231T +#endif // USE_LIBRETINY_VARIANT #endif // USE_BK72XX if (success && std::isfinite(temperature)) { this->publish_state(temperature); diff --git a/tests/components/internal_temperature/test.bk72xx.yaml b/tests/components/internal_temperature/test.bk72xx.yaml new file mode 100644 index 0000000000..28df4a6d9f --- /dev/null +++ b/tests/components/internal_temperature/test.bk72xx.yaml @@ -0,0 +1,3 @@ +sensor: + - platform: internal_temperature + name: "Internal Temperature" diff --git a/tests/components/internal_temperature/test.esp32-c3-idf.yaml b/tests/components/internal_temperature/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..28df4a6d9f --- /dev/null +++ b/tests/components/internal_temperature/test.esp32-c3-idf.yaml @@ -0,0 +1,3 @@ +sensor: + - platform: internal_temperature + name: "Internal Temperature" diff --git a/tests/components/internal_temperature/test.esp32-c3.yaml b/tests/components/internal_temperature/test.esp32-c3.yaml new file mode 100644 index 0000000000..28df4a6d9f --- /dev/null +++ b/tests/components/internal_temperature/test.esp32-c3.yaml @@ -0,0 +1,3 @@ +sensor: + - platform: internal_temperature + name: "Internal Temperature" diff --git a/tests/components/internal_temperature/test.esp32-idf.yaml b/tests/components/internal_temperature/test.esp32-idf.yaml new file mode 100644 index 0000000000..28df4a6d9f --- /dev/null +++ b/tests/components/internal_temperature/test.esp32-idf.yaml @@ -0,0 +1,3 @@ +sensor: + - platform: internal_temperature + name: "Internal Temperature" diff --git a/tests/components/internal_temperature/test.esp32.yaml b/tests/components/internal_temperature/test.esp32.yaml new file mode 100644 index 0000000000..28df4a6d9f --- /dev/null +++ b/tests/components/internal_temperature/test.esp32.yaml @@ -0,0 +1,3 @@ +sensor: + - platform: internal_temperature + name: "Internal Temperature" diff --git a/tests/components/internal_temperature/test.rp2040.yaml b/tests/components/internal_temperature/test.rp2040.yaml new file mode 100644 index 0000000000..28df4a6d9f --- /dev/null +++ b/tests/components/internal_temperature/test.rp2040.yaml @@ -0,0 +1,3 @@ +sensor: + - platform: internal_temperature + name: "Internal Temperature" From a9a9be32d3a6869aab78d37bb77b6d385c95837b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Apr 2024 09:14:56 +1200 Subject: [PATCH 1285/2101] Bump aioesphomeapi from 24.0.0 to 24.3.0 (#6602) 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 68041675f6..df94b8b77c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,7 +13,7 @@ platformio==6.1.13 # When updating platformio, also update Dockerfile esptool==4.7.0 click==8.1.7 esphome-dashboard==20240412.0 -aioesphomeapi==24.0.0 +aioesphomeapi==24.3.0 zeroconf==0.132.2 python-magic==0.4.27 ruamel.yaml==0.18.6 # dashboard_import From 7c893aa3309bcd7756432c6ba5b96a8c57d9e4ff Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Mon, 22 Apr 2024 15:48:29 -0600 Subject: [PATCH 1286/2101] fix streaming logs from MQTT for ESP32 devices using TLS (#6605) --- esphome/mqtt.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/esphome/mqtt.py b/esphome/mqtt.py index 166301005d..667a20bcf8 100644 --- a/esphome/mqtt.py +++ b/esphome/mqtt.py @@ -10,6 +10,7 @@ import paho.mqtt.client as mqtt from esphome.const import ( CONF_BROKER, + CONF_CERTIFICATE_AUTHORITY, CONF_DISCOVERY_PREFIX, CONF_ESPHOME, CONF_LOG_TOPIC, @@ -99,7 +100,9 @@ def prepare( elif username: client.username_pw_set(username, password) - if config[CONF_MQTT].get(CONF_SSL_FINGERPRINTS): + if config[CONF_MQTT].get(CONF_SSL_FINGERPRINTS) or config[CONF_MQTT].get( + CONF_CERTIFICATE_AUTHORITY + ): if sys.version_info >= (2, 7, 13): tls_version = ssl.PROTOCOL_TLS # pylint: disable=no-member else: From c7bfd9b46b63a52ad4ccd45e35e36cd4b073dbd9 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Tue, 23 Apr 2024 08:04:56 +1000 Subject: [PATCH 1287/2101] Disallow variant/family override for known boards (#6512) --- esphome/components/esp32/__init__.py | 25 +++++++++++++------ esphome/components/libretiny/__init__.py | 31 +++++++++++++++--------- 2 files changed, 37 insertions(+), 19 deletions(-) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 50d6d229f9..8ae6262f2f 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -316,17 +316,26 @@ def _parse_platform_version(value): def _detect_variant(value): - if CONF_VARIANT not in value: - board = value[CONF_BOARD] - if board not in BOARDS: + board = value[CONF_BOARD] + if board in BOARDS: + variant = BOARDS[board][KEY_VARIANT] + if CONF_VARIANT in value and variant != value[CONF_VARIANT]: raise cv.Invalid( - "This board is unknown, please set the variant manually", + f"Option '{CONF_VARIANT}' does not match selected board.", + path=[CONF_VARIANT], + ) + value = value.copy() + value[CONF_VARIANT] = variant + else: + if CONF_VARIANT not in value: + raise cv.Invalid( + "This board is unknown, if you are sure you want to compile with this board selection, " + f"override with option '{CONF_VARIANT}'", path=[CONF_BOARD], ) - - value = value.copy() - value[CONF_VARIANT] = BOARDS[board][KEY_VARIANT] - + _LOGGER.warning( + "This board is unknown. Make sure the chosen chip component is correct.", + ) return value diff --git a/esphome/components/libretiny/__init__.py b/esphome/components/libretiny/__init__.py index 34aff0ae16..a8034f8fab 100644 --- a/esphome/components/libretiny/__init__.py +++ b/esphome/components/libretiny/__init__.py @@ -1,6 +1,10 @@ import json import logging -from os.path import dirname, isfile, join +from os.path import ( + dirname, + isfile, + join, +) import esphome.codegen as cg import esphome.config_validation as cv @@ -55,15 +59,25 @@ def _detect_variant(value): component: LibreTinyComponent = CORE.data[KEY_LIBRETINY][KEY_COMPONENT_DATA] board = value[CONF_BOARD] # read board-default family if not specified - if CONF_FAMILY not in value: - if board not in component.boards: + if board not in component.boards: + if CONF_FAMILY not in value: raise cv.Invalid( - "This board is unknown, please set the family manually. " - "Also, make sure the chosen chip component is correct.", + "This board is unknown, if you are sure you want to compile with this board selection, " + f"override with option '{CONF_FAMILY}'", path=[CONF_BOARD], ) + _LOGGER.warning( + "This board is unknown. Make sure the chosen chip component is correct.", + ) + else: + family = component.boards[board][KEY_FAMILY] + if CONF_FAMILY in value and family != value[CONF_FAMILY]: + raise cv.Invalid( + f"Option '{CONF_FAMILY}' does not match selected board.", + path=[CONF_FAMILY], + ) value = value.copy() - value[CONF_FAMILY] = component.boards[board][KEY_FAMILY] + value[CONF_FAMILY] = family # read component name matching this family value[CONF_COMPONENT_ID] = FAMILY_COMPONENT[value[CONF_FAMILY]] # make sure the chosen component matches the family @@ -72,11 +86,6 @@ def _detect_variant(value): f"The chosen family doesn't belong to '{component.name}' component. The correct component is '{value[CONF_COMPONENT_ID]}'", path=[CONF_FAMILY], ) - # warn anyway if the board wasn't found - if board not in component.boards: - _LOGGER.warning( - "This board is unknown. Make sure the chosen chip component is correct.", - ) return value From 7510468a9bd9956b097d5bd4f00ef8e751c97b17 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Tue, 23 Apr 2024 08:10:07 +1000 Subject: [PATCH 1288/2101] Add yamllint and clang-format to pre-commit hooks (#6578) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- .pre-commit-config.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 69aafd4d15..15e59b7eb7 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -31,3 +31,12 @@ repos: hooks: - id: pyupgrade args: [--py39-plus] + - repo: https://github.com/adrienverge/yamllint.git + rev: v1.35.1 + hooks: + - id: yamllint + - repo: https://github.com/pre-commit/mirrors-clang-format + rev: v13.0.1 + hooks: + - id: clang-format + From aee2a49cad466232b087dc0a690e0cd50f10a802 Mon Sep 17 00:00:00 2001 From: polyfloyd Date: Tue, 23 Apr 2024 00:17:00 +0200 Subject: [PATCH 1289/2101] esp32_ble: Consider ESP_BT_STATUS_DONE a successful state (#6493) Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> --- esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp | 6 +++++- 1 file changed, 5 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 a5bbd85b47..a5209c764a 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp @@ -364,7 +364,11 @@ void ESP32BLETracker::gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_ga } void ESP32BLETracker::gap_scan_set_param_complete_(const esp_ble_gap_cb_param_t::ble_scan_param_cmpl_evt_param ¶m) { - this->scan_set_param_failed_ = param.status; + if (param.status == ESP_BT_STATUS_DONE) { + this->scan_set_param_failed_ = ESP_BT_STATUS_SUCCESS; + } else { + this->scan_set_param_failed_ = param.status; + } } void ESP32BLETracker::gap_scan_start_complete_(const esp_ble_gap_cb_param_t::ble_scan_start_cmpl_evt_param ¶m) { From 0874440a317bc8541b79f829a253209608be9568 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 22 Apr 2024 18:48:30 -0400 Subject: [PATCH 1290/2101] Fix or filter (#6574) Co-authored-by: Jonathan Swoboda --- esphome/components/sensor/filter.cpp | 6 +++++- esphome/components/sensor/filter.h | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/esphome/components/sensor/filter.cpp b/esphome/components/sensor/filter.cpp index 3f67af59be..eaa909429b 100644 --- a/esphome/components/sensor/filter.cpp +++ b/esphome/components/sensor/filter.cpp @@ -359,11 +359,15 @@ OrFilter::OrFilter(std::vector filters) : filters_(std::move(filters)) OrFilter::PhiNode::PhiNode(OrFilter *or_parent) : or_parent_(or_parent) {} optional OrFilter::PhiNode::new_value(float value) { - this->or_parent_->output(value); + if (!this->or_parent_->has_value_) { + this->or_parent_->output(value); + this->or_parent_->has_value_ = true; + } return {}; } optional OrFilter::new_value(float value) { + this->has_value_ = false; for (Filter *filter : this->filters_) filter->input(value); diff --git a/esphome/components/sensor/filter.h b/esphome/components/sensor/filter.h index 1a08699d7b..c13cb3420a 100644 --- a/esphome/components/sensor/filter.h +++ b/esphome/components/sensor/filter.h @@ -388,6 +388,7 @@ class OrFilter : public Filter { }; std::vector filters_; + bool has_value_{false}; PhiNode phi_; }; From 496b7f45db59958eb5e3c75ebc19f24fc752b698 Mon Sep 17 00:00:00 2001 From: zry98 Date: Wed, 17 Apr 2024 23:31:20 +0200 Subject: [PATCH 1291/2101] [Tuya Climate] Fix compilation error caused by codegen (#6568) --- esphome/components/tuya/climate/__init__.py | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/esphome/components/tuya/climate/__init__.py b/esphome/components/tuya/climate/__init__.py index b3d401e5a4..56eb377ed7 100644 --- a/esphome/components/tuya/climate/__init__.py +++ b/esphome/components/tuya/climate/__init__.py @@ -208,7 +208,7 @@ async def to_code(config): cg.add(var.set_switch_id(switch_datapoint)) if active_state_config := config.get(CONF_ACTIVE_STATE): - cg.add(var.set_active_state_id(CONF_DATAPOINT)) + cg.add(var.set_active_state_id(active_state_config.get(CONF_DATAPOINT))) if (heating_value := active_state_config.get(CONF_HEATING_VALUE)) is not None: cg.add(var.set_active_state_heating_value(heating_value)) if (cooling_value := active_state_config.get(CONF_COOLING_VALUE)) is not None: @@ -219,14 +219,10 @@ async def to_code(config): cg.add(var.set_active_state_fanonly_value(fanonly_value)) else: if heating_state_pin_config := config.get(CONF_HEATING_STATE_PIN): - heating_state_pin = await cg.gpio_pin_expression( - config(heating_state_pin_config) - ) + heating_state_pin = await cg.gpio_pin_expression(heating_state_pin_config) cg.add(var.set_heating_state_pin(heating_state_pin)) if cooling_state_pin_config := config.get(CONF_COOLING_STATE_PIN): - cooling_state_pin = await cg.gpio_pin_expression( - config(cooling_state_pin_config) - ) + cooling_state_pin = await cg.gpio_pin_expression(cooling_state_pin_config) cg.add(var.set_cooling_state_pin(cooling_state_pin)) if target_temperature_datapoint := config.get(CONF_TARGET_TEMPERATURE_DATAPOINT): @@ -254,11 +250,11 @@ async def to_code(config): if preset_config := config.get(CONF_PRESET, {}): if eco_config := preset_config.get(CONF_ECO, {}): - cg.add(var.set_eco_id(CONF_DATAPOINT)) + cg.add(var.set_eco_id(eco_config.get(CONF_DATAPOINT))) if eco_temperature := eco_config.get(CONF_TEMPERATURE): cg.add(var.set_eco_temperature(eco_temperature)) - if CONF_SLEEP in preset_config: - cg.add(var.set_sleep_id(CONF_DATAPOINT)) + if sleep_config := preset_config.get(CONF_SLEEP, {}): + cg.add(var.set_sleep_id(sleep_config.get(CONF_DATAPOINT))) if swing_mode_config := config.get(CONF_SWING_MODE): if swing_vertical_datapoint := swing_mode_config.get(CONF_VERTICAL_DATAPOINT): @@ -268,7 +264,7 @@ async def to_code(config): ): cg.add(var.set_swing_horizontal_id(swing_horizontal_datapoint)) if fan_mode_config := config.get(CONF_FAN_MODE): - cg.add(var.set_fan_speed_id(CONF_DATAPOINT)) + cg.add(var.set_fan_speed_id(fan_mode_config.get(CONF_DATAPOINT))) if (fan_auto_value := fan_mode_config.get(CONF_AUTO_VALUE)) is not None: cg.add(var.set_fan_speed_auto_value(fan_auto_value)) if (fan_low_value := fan_mode_config.get(CONF_LOW_VALUE)) is not None: From 1a152169e0fb6ea0d1cd0873b9f140c201ae4def Mon Sep 17 00:00:00 2001 From: Javier Peletier Date: Mon, 22 Apr 2024 22:48:06 +0200 Subject: [PATCH 1292/2101] wifi: fix reconnect issue due to enablement of fast connect (#6598) --- esphome/components/wifi/wifi_component.cpp | 8 ++++++-- esphome/components/wifi/wifi_component.h | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 8f46bf29a0..075e683bb5 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -128,7 +128,7 @@ void WiFiComponent::loop() { case WIFI_COMPONENT_STATE_COOLDOWN: { this->status_set_warning(); if (millis() - this->action_started_ > 5000) { - if (this->fast_connect_) { + if (this->fast_connect_ || this->retry_hidden_) { this->start_connecting(this->sta_[0], false); } else { this->start_scanning(); @@ -591,6 +591,9 @@ void WiFiComponent::check_connecting_finished() { return; } + // We won't retry hidden networks unless a reconnect fails more than three times again + this->retry_hidden_ = false; + ESP_LOGI(TAG, "WiFi Connected!"); this->print_connect_params_(); @@ -668,10 +671,11 @@ void WiFiComponent::retry_connect() { this->wifi_mode_(false, {}); delay(100); // NOLINT this->num_retried_ = 0; + this->retry_hidden_ = false; } else { // Try hidden networks after 3 failed retries ESP_LOGD(TAG, "Retrying with hidden networks..."); - this->fast_connect_ = true; + this->retry_hidden_ = true; this->num_retried_++; } } else { diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index d9cb6a9ae2..133fa2970c 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -371,6 +371,7 @@ class WiFiComponent : public Component { std::vector sta_priorities_; WiFiAP selected_ap_; bool fast_connect_{false}; + bool retry_hidden_{false}; bool has_ap_{false}; WiFiAP ap_; From a29e634af103baa07dbcdaf02cd898e638d79d3a Mon Sep 17 00:00:00 2001 From: Mat931 <49403702+Mat931@users.noreply.github.com> Date: Mon, 22 Apr 2024 20:59:06 +0000 Subject: [PATCH 1293/2101] Calibrate Beken internal temperature (#6599) --- .../internal_temperature/internal_temperature.cpp | 8 +++++--- tests/components/internal_temperature/test.bk72xx.yaml | 3 +++ .../internal_temperature/test.esp32-c3-idf.yaml | 3 +++ tests/components/internal_temperature/test.esp32-c3.yaml | 3 +++ tests/components/internal_temperature/test.esp32-idf.yaml | 3 +++ tests/components/internal_temperature/test.esp32.yaml | 3 +++ tests/components/internal_temperature/test.rp2040.yaml | 3 +++ 7 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 tests/components/internal_temperature/test.bk72xx.yaml create mode 100644 tests/components/internal_temperature/test.esp32-c3-idf.yaml create mode 100644 tests/components/internal_temperature/test.esp32-c3.yaml create mode 100644 tests/components/internal_temperature/test.esp32-idf.yaml create mode 100644 tests/components/internal_temperature/test.esp32.yaml create mode 100644 tests/components/internal_temperature/test.rp2040.yaml diff --git a/esphome/components/internal_temperature/internal_temperature.cpp b/esphome/components/internal_temperature/internal_temperature.cpp index 255d95f6f8..47f516f568 100644 --- a/esphome/components/internal_temperature/internal_temperature.cpp +++ b/esphome/components/internal_temperature/internal_temperature.cpp @@ -55,11 +55,13 @@ void InternalTemperatureSensor::update() { uint32_t raw, result; result = temp_single_get_current_temperature(&raw); success = (result == 0); -#ifdef USE_LIBRETINY_VARIANT_BK7231T +#if defined(USE_LIBRETINY_VARIANT_BK7231N) + temperature = raw * -0.38f + 156.0f; +#elif defined(USE_LIBRETINY_VARIANT_BK7231T) temperature = raw * 0.04f; -#else +#else // USE_LIBRETINY_VARIANT temperature = raw * 0.128f; -#endif // USE_LIBRETINY_VARIANT_BK7231T +#endif // USE_LIBRETINY_VARIANT #endif // USE_BK72XX if (success && std::isfinite(temperature)) { this->publish_state(temperature); diff --git a/tests/components/internal_temperature/test.bk72xx.yaml b/tests/components/internal_temperature/test.bk72xx.yaml new file mode 100644 index 0000000000..28df4a6d9f --- /dev/null +++ b/tests/components/internal_temperature/test.bk72xx.yaml @@ -0,0 +1,3 @@ +sensor: + - platform: internal_temperature + name: "Internal Temperature" diff --git a/tests/components/internal_temperature/test.esp32-c3-idf.yaml b/tests/components/internal_temperature/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..28df4a6d9f --- /dev/null +++ b/tests/components/internal_temperature/test.esp32-c3-idf.yaml @@ -0,0 +1,3 @@ +sensor: + - platform: internal_temperature + name: "Internal Temperature" diff --git a/tests/components/internal_temperature/test.esp32-c3.yaml b/tests/components/internal_temperature/test.esp32-c3.yaml new file mode 100644 index 0000000000..28df4a6d9f --- /dev/null +++ b/tests/components/internal_temperature/test.esp32-c3.yaml @@ -0,0 +1,3 @@ +sensor: + - platform: internal_temperature + name: "Internal Temperature" diff --git a/tests/components/internal_temperature/test.esp32-idf.yaml b/tests/components/internal_temperature/test.esp32-idf.yaml new file mode 100644 index 0000000000..28df4a6d9f --- /dev/null +++ b/tests/components/internal_temperature/test.esp32-idf.yaml @@ -0,0 +1,3 @@ +sensor: + - platform: internal_temperature + name: "Internal Temperature" diff --git a/tests/components/internal_temperature/test.esp32.yaml b/tests/components/internal_temperature/test.esp32.yaml new file mode 100644 index 0000000000..28df4a6d9f --- /dev/null +++ b/tests/components/internal_temperature/test.esp32.yaml @@ -0,0 +1,3 @@ +sensor: + - platform: internal_temperature + name: "Internal Temperature" diff --git a/tests/components/internal_temperature/test.rp2040.yaml b/tests/components/internal_temperature/test.rp2040.yaml new file mode 100644 index 0000000000..28df4a6d9f --- /dev/null +++ b/tests/components/internal_temperature/test.rp2040.yaml @@ -0,0 +1,3 @@ +sensor: + - platform: internal_temperature + name: "Internal Temperature" From dd8be524b433ddd80c68c7556b5ba156b58cf81b Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Mon, 22 Apr 2024 15:48:29 -0600 Subject: [PATCH 1294/2101] fix streaming logs from MQTT for ESP32 devices using TLS (#6605) --- esphome/mqtt.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/esphome/mqtt.py b/esphome/mqtt.py index 166301005d..667a20bcf8 100644 --- a/esphome/mqtt.py +++ b/esphome/mqtt.py @@ -10,6 +10,7 @@ import paho.mqtt.client as mqtt from esphome.const import ( CONF_BROKER, + CONF_CERTIFICATE_AUTHORITY, CONF_DISCOVERY_PREFIX, CONF_ESPHOME, CONF_LOG_TOPIC, @@ -99,7 +100,9 @@ def prepare( elif username: client.username_pw_set(username, password) - if config[CONF_MQTT].get(CONF_SSL_FINGERPRINTS): + if config[CONF_MQTT].get(CONF_SSL_FINGERPRINTS) or config[CONF_MQTT].get( + CONF_CERTIFICATE_AUTHORITY + ): if sys.version_info >= (2, 7, 13): tls_version = ssl.PROTOCOL_TLS # pylint: disable=no-member else: From 03d547d2c0a0b1e89487a5fec8a4696d6afd8685 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Tue, 23 Apr 2024 08:04:56 +1000 Subject: [PATCH 1295/2101] Disallow variant/family override for known boards (#6512) --- esphome/components/esp32/__init__.py | 25 +++++++++++++------ esphome/components/libretiny/__init__.py | 31 +++++++++++++++--------- 2 files changed, 37 insertions(+), 19 deletions(-) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 50d6d229f9..8ae6262f2f 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -316,17 +316,26 @@ def _parse_platform_version(value): def _detect_variant(value): - if CONF_VARIANT not in value: - board = value[CONF_BOARD] - if board not in BOARDS: + board = value[CONF_BOARD] + if board in BOARDS: + variant = BOARDS[board][KEY_VARIANT] + if CONF_VARIANT in value and variant != value[CONF_VARIANT]: raise cv.Invalid( - "This board is unknown, please set the variant manually", + f"Option '{CONF_VARIANT}' does not match selected board.", + path=[CONF_VARIANT], + ) + value = value.copy() + value[CONF_VARIANT] = variant + else: + if CONF_VARIANT not in value: + raise cv.Invalid( + "This board is unknown, if you are sure you want to compile with this board selection, " + f"override with option '{CONF_VARIANT}'", path=[CONF_BOARD], ) - - value = value.copy() - value[CONF_VARIANT] = BOARDS[board][KEY_VARIANT] - + _LOGGER.warning( + "This board is unknown. Make sure the chosen chip component is correct.", + ) return value diff --git a/esphome/components/libretiny/__init__.py b/esphome/components/libretiny/__init__.py index 34aff0ae16..a8034f8fab 100644 --- a/esphome/components/libretiny/__init__.py +++ b/esphome/components/libretiny/__init__.py @@ -1,6 +1,10 @@ import json import logging -from os.path import dirname, isfile, join +from os.path import ( + dirname, + isfile, + join, +) import esphome.codegen as cg import esphome.config_validation as cv @@ -55,15 +59,25 @@ def _detect_variant(value): component: LibreTinyComponent = CORE.data[KEY_LIBRETINY][KEY_COMPONENT_DATA] board = value[CONF_BOARD] # read board-default family if not specified - if CONF_FAMILY not in value: - if board not in component.boards: + if board not in component.boards: + if CONF_FAMILY not in value: raise cv.Invalid( - "This board is unknown, please set the family manually. " - "Also, make sure the chosen chip component is correct.", + "This board is unknown, if you are sure you want to compile with this board selection, " + f"override with option '{CONF_FAMILY}'", path=[CONF_BOARD], ) + _LOGGER.warning( + "This board is unknown. Make sure the chosen chip component is correct.", + ) + else: + family = component.boards[board][KEY_FAMILY] + if CONF_FAMILY in value and family != value[CONF_FAMILY]: + raise cv.Invalid( + f"Option '{CONF_FAMILY}' does not match selected board.", + path=[CONF_FAMILY], + ) value = value.copy() - value[CONF_FAMILY] = component.boards[board][KEY_FAMILY] + value[CONF_FAMILY] = family # read component name matching this family value[CONF_COMPONENT_ID] = FAMILY_COMPONENT[value[CONF_FAMILY]] # make sure the chosen component matches the family @@ -72,11 +86,6 @@ def _detect_variant(value): f"The chosen family doesn't belong to '{component.name}' component. The correct component is '{value[CONF_COMPONENT_ID]}'", path=[CONF_FAMILY], ) - # warn anyway if the board wasn't found - if board not in component.boards: - _LOGGER.warning( - "This board is unknown. Make sure the chosen chip component is correct.", - ) return value From 44d13f2405abba7d7f21334e1364b2ca90967a07 Mon Sep 17 00:00:00 2001 From: polyfloyd Date: Tue, 23 Apr 2024 00:17:00 +0200 Subject: [PATCH 1296/2101] esp32_ble: Consider ESP_BT_STATUS_DONE a successful state (#6493) Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> --- esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp | 6 +++++- 1 file changed, 5 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 a5bbd85b47..a5209c764a 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp @@ -364,7 +364,11 @@ void ESP32BLETracker::gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_ga } void ESP32BLETracker::gap_scan_set_param_complete_(const esp_ble_gap_cb_param_t::ble_scan_param_cmpl_evt_param ¶m) { - this->scan_set_param_failed_ = param.status; + if (param.status == ESP_BT_STATUS_DONE) { + this->scan_set_param_failed_ = ESP_BT_STATUS_SUCCESS; + } else { + this->scan_set_param_failed_ = param.status; + } } void ESP32BLETracker::gap_scan_start_complete_(const esp_ble_gap_cb_param_t::ble_scan_start_cmpl_evt_param ¶m) { From 3e6487609714d207a69d2a984ab40f9b9c0539a5 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 22 Apr 2024 18:48:30 -0400 Subject: [PATCH 1297/2101] Fix or filter (#6574) Co-authored-by: Jonathan Swoboda --- esphome/components/sensor/filter.cpp | 6 +++++- esphome/components/sensor/filter.h | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/esphome/components/sensor/filter.cpp b/esphome/components/sensor/filter.cpp index 6d7acad7e0..18cc10ed8b 100644 --- a/esphome/components/sensor/filter.cpp +++ b/esphome/components/sensor/filter.cpp @@ -359,11 +359,15 @@ OrFilter::OrFilter(std::vector filters) : filters_(std::move(filters)) OrFilter::PhiNode::PhiNode(OrFilter *or_parent) : or_parent_(or_parent) {} optional OrFilter::PhiNode::new_value(float value) { - this->or_parent_->output(value); + if (!this->or_parent_->has_value_) { + this->or_parent_->output(value); + this->or_parent_->has_value_ = true; + } return {}; } optional OrFilter::new_value(float value) { + this->has_value_ = false; for (Filter *filter : this->filters_) filter->input(value); diff --git a/esphome/components/sensor/filter.h b/esphome/components/sensor/filter.h index 1a08699d7b..c13cb3420a 100644 --- a/esphome/components/sensor/filter.h +++ b/esphome/components/sensor/filter.h @@ -388,6 +388,7 @@ class OrFilter : public Filter { }; std::vector filters_; + bool has_value_{false}; PhiNode phi_; }; From 7ae36b023cec67a6e183df1ee7d183c12dd1d2a2 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 23 Apr 2024 10:50:41 +1200 Subject: [PATCH 1298/2101] Bump version to 2024.4.1 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 76320e6c71..69949dc086 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.4.0" +__version__ = "2024.4.1" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From a7fb2ce3e114c96b4148b27516581b3455f09f40 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 23 Apr 2024 11:01:20 +1200 Subject: [PATCH 1299/2101] Use clang-format version from requirements_dev file (#6606) --- .github/workflows/ci.yml | 3 +-- requirements_dev.txt | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d3ac7981d3..15f0904df4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,6 @@ permissions: env: DEFAULT_PYTHON: "3.9" PYUPGRADE_TARGET: "--py39-plus" - CLANG_FORMAT_VERSION: "13.0.1" concurrency: # yamllint disable-line rule:line-length @@ -239,7 +238,7 @@ jobs: - name: Install clang-format run: | . venv/bin/activate - pip install clang-format==${{ env.CLANG_FORMAT_VERSION }} + pip install clang-format -c requirements_dev.txt - name: Run clang-format run: | . venv/bin/activate diff --git a/requirements_dev.txt b/requirements_dev.txt index 6bfa015c6f..eb749a861d 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 -clang-tidy==14.0.6 -yamllint==1.35.1 +clang-format==13.0.1 # also change in .pre-commit-config.yaml and Dockerfile when updating +clang-tidy==14.0.6 # When updating clang-tidy, also update Dockerfile +yamllint==1.35.1 # also change in .pre-commit-config.yaml when updating From b737fe70a6c3fc811845d0e43097a4d4a5abf88c Mon Sep 17 00:00:00 2001 From: mrtoy-me <118446898+mrtoy-me@users.noreply.github.com> Date: Tue, 23 Apr 2024 09:16:55 +1000 Subject: [PATCH 1300/2101] Fix SHT3xd fails sometimes in 2024.4.0 (#6592) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/sht3xd/sht3xd.cpp | 34 +++++++++++++++++++++++----- esphome/components/sht3xd/sht3xd.h | 7 ++++++ 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/esphome/components/sht3xd/sht3xd.cpp b/esphome/components/sht3xd/sht3xd.cpp index 888e954c6b..ffaf5db322 100644 --- a/esphome/components/sht3xd/sht3xd.cpp +++ b/esphome/components/sht3xd/sht3xd.cpp @@ -6,9 +6,14 @@ namespace sht3xd { static const char *const TAG = "sht3xd"; -// use read serial number register with clock stretching disabled as per other SHT3XD_COMMAND registers -// which provides support for SHT85 sensor -// SHT85 does not support clock stretching and uses same registers as SHT3xd with clock stretching disabled +// https://sensirion.com/media/documents/E5762713/63D103C2/Sensirion_electronic_identification_code_SHT3x.pdf +// indicates two possible read serial number registers either with clock stretching enabled or disabled. +// Other SHT3XD_COMMAND registers use the clock stretching disabled register. +// 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. + +static const uint16_t SHT3XD_COMMAND_READ_SERIAL_NUMBER_CLOCK_STRETCHING = 0x3780; static const uint16_t SHT3XD_COMMAND_READ_SERIAL_NUMBER = 0x3682; static const uint16_t SHT3XD_COMMAND_READ_STATUS = 0xF32D; @@ -22,13 +27,19 @@ static const uint16_t SHT3XD_COMMAND_FETCH_DATA = 0xE000; void SHT3XDComponent::setup() { ESP_LOGCONFIG(TAG, "Setting up SHT3xD..."); uint16_t raw_serial_number[2]; - if (!this->get_register(SHT3XD_COMMAND_READ_SERIAL_NUMBER, raw_serial_number, 2)) { - this->mark_failed(); - return; + 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; + } } + 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(); return; } @@ -36,10 +47,21 @@ void SHT3XDComponent::setup() { 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, " Setup successful"); ESP_LOGD(TAG, " Serial Number: 0x%08" PRIX32, this->serial_number_); ESP_LOGD(TAG, " Heater Enabled: %s", this->heater_enabled_ ? "true" : "false"); diff --git a/esphome/components/sht3xd/sht3xd.h b/esphome/components/sht3xd/sht3xd.h index d1a3360e69..74f155121b 100644 --- a/esphome/components/sht3xd/sht3xd.h +++ b/esphome/components/sht3xd/sht3xd.h @@ -22,6 +22,13 @@ 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 057f473a4a19f05de5780337cfd84de6b2ec9061 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Mon, 22 Apr 2024 22:38:51 -0500 Subject: [PATCH 1301/2101] Add some components to the new testing framework (P) (#6213) --- .../partition/test.esp32-c3-idf.yaml | 22 ++ tests/components/partition/test.esp32-c3.yaml | 22 ++ .../components/partition/test.esp32-idf.yaml | 22 ++ tests/components/partition/test.esp32.yaml | 22 ++ .../pca6416a/test.esp32-c3-idf.yaml | 17 ++ tests/components/pca6416a/test.esp32-c3.yaml | 17 ++ tests/components/pca6416a/test.esp32-idf.yaml | 17 ++ tests/components/pca6416a/test.esp32.yaml | 17 ++ tests/components/pca6416a/test.esp8266.yaml | 17 ++ tests/components/pca6416a/test.rp2040.yaml | 17 ++ .../components/pca9554/test.esp32-c3-idf.yaml | 26 ++ tests/components/pca9554/test.esp32-c3.yaml | 26 ++ tests/components/pca9554/test.esp32-idf.yaml | 26 ++ tests/components/pca9554/test.esp32.yaml | 26 ++ tests/components/pca9554/test.esp8266.yaml | 26 ++ tests/components/pca9554/test.rp2040.yaml | 26 ++ .../components/pca9685/test.esp32-c3-idf.yaml | 34 +++ tests/components/pca9685/test.esp32-c3.yaml | 34 +++ tests/components/pca9685/test.esp32-idf.yaml | 34 +++ tests/components/pca9685/test.esp32.yaml | 34 +++ tests/components/pca9685/test.esp8266.yaml | 34 +++ tests/components/pca9685/test.rp2040.yaml | 26 ++ .../components/pcd8544/test.esp32-c3-idf.yaml | 14 + tests/components/pcd8544/test.esp32-c3.yaml | 14 + tests/components/pcd8544/test.esp32-idf.yaml | 14 + tests/components/pcd8544/test.esp32.yaml | 14 + tests/components/pcd8544/test.esp8266.yaml | 14 + tests/components/pcd8544/test.rp2040.yaml | 14 + .../pcf85063/test.esp32-c3-idf.yaml | 12 + tests/components/pcf85063/test.esp32-c3.yaml | 12 + tests/components/pcf85063/test.esp32-idf.yaml | 12 + tests/components/pcf85063/test.esp32.yaml | 12 + tests/components/pcf85063/test.esp8266.yaml | 12 + tests/components/pcf85063/test.rp2040.yaml | 12 + .../components/pcf8563/test.esp32-c3-idf.yaml | 12 + tests/components/pcf8563/test.esp32-c3.yaml | 12 + tests/components/pcf8563/test.esp32-idf.yaml | 12 + tests/components/pcf8563/test.esp32.yaml | 12 + tests/components/pcf8563/test.esp8266.yaml | 12 + tests/components/pcf8563/test.rp2040.yaml | 12 + .../components/pcf8574/test.esp32-c3-idf.yaml | 28 ++ tests/components/pcf8574/test.esp32-c3.yaml | 28 ++ tests/components/pcf8574/test.esp32-idf.yaml | 28 ++ tests/components/pcf8574/test.esp32.yaml | 28 ++ tests/components/pcf8574/test.esp8266.yaml | 28 ++ tests/components/pcf8574/test.rp2040.yaml | 28 ++ tests/components/pid/test.esp32-c3-idf.yaml | 56 ++++ tests/components/pid/test.esp32-c3.yaml | 56 ++++ tests/components/pid/test.esp32-idf.yaml | 56 ++++ tests/components/pid/test.esp32.yaml | 56 ++++ tests/components/pid/test.esp8266.yaml | 56 ++++ tests/components/pid/test.rp2040.yaml | 56 ++++ .../pipsolar/test.esp32-c3-idf.yaml | 247 ++++++++++++++++++ tests/components/pipsolar/test.esp32-c3.yaml | 247 ++++++++++++++++++ tests/components/pipsolar/test.esp32-idf.yaml | 247 ++++++++++++++++++ tests/components/pipsolar/test.esp32.yaml | 247 ++++++++++++++++++ tests/components/pipsolar/test.esp8266.yaml | 247 ++++++++++++++++++ tests/components/pipsolar/test.rp2040.yaml | 247 ++++++++++++++++++ .../components/pm1006/test.esp32-c3-idf.yaml | 10 + tests/components/pm1006/test.esp32-c3.yaml | 10 + tests/components/pm1006/test.esp32-idf.yaml | 10 + tests/components/pm1006/test.esp32.yaml | 10 + tests/components/pm1006/test.esp8266.yaml | 10 + tests/components/pm1006/test.rp2040.yaml | 10 + .../pmsa003i/test.esp32-c3-idf.yaml | 27 ++ tests/components/pmsa003i/test.esp32-c3.yaml | 27 ++ tests/components/pmsa003i/test.esp32-idf.yaml | 27 ++ tests/components/pmsa003i/test.esp32.yaml | 27 ++ tests/components/pmsa003i/test.esp8266.yaml | 27 ++ tests/components/pmsa003i/test.rp2040.yaml | 27 ++ .../components/pmsx003/test.esp32-c3-idf.yaml | 34 +++ tests/components/pmsx003/test.esp32-c3.yaml | 34 +++ tests/components/pmsx003/test.esp32-idf.yaml | 34 +++ tests/components/pmsx003/test.esp32.yaml | 34 +++ tests/components/pmsx003/test.esp8266.yaml | 34 +++ tests/components/pmsx003/test.rp2040.yaml | 34 +++ .../components/pmwcs3/test.esp32-c3-idf.yaml | 15 ++ tests/components/pmwcs3/test.esp32-c3.yaml | 15 ++ tests/components/pmwcs3/test.esp32-idf.yaml | 15 ++ tests/components/pmwcs3/test.esp32.yaml | 15 ++ tests/components/pmwcs3/test.esp8266.yaml | 15 ++ tests/components/pmwcs3/test.rp2040.yaml | 15 ++ .../pn532_i2c/test.esp32-c3-idf.yaml | 13 + tests/components/pn532_i2c/test.esp32-c3.yaml | 13 + .../components/pn532_i2c/test.esp32-idf.yaml | 13 + tests/components/pn532_i2c/test.esp32.yaml | 13 + tests/components/pn532_i2c/test.esp8266.yaml | 13 + tests/components/pn532_i2c/test.rp2040.yaml | 13 + .../pn532_spi/test.esp32-c3-idf.yaml | 15 ++ tests/components/pn532_spi/test.esp32-c3.yaml | 15 ++ .../components/pn532_spi/test.esp32-idf.yaml | 15 ++ tests/components/pn532_spi/test.esp32.yaml | 15 ++ tests/components/pn532_spi/test.esp8266.yaml | 15 ++ tests/components/pn532_spi/test.rp2040.yaml | 15 ++ .../pn7150_i2c/test.esp32-c3-idf.yaml | 35 +++ .../components/pn7150_i2c/test.esp32-c3.yaml | 35 +++ .../components/pn7150_i2c/test.esp32-idf.yaml | 35 +++ tests/components/pn7150_i2c/test.esp32.yaml | 35 +++ tests/components/pn7150_i2c/test.esp8266.yaml | 35 +++ tests/components/pn7150_i2c/test.rp2040.yaml | 35 +++ .../pn7160_i2c/test.esp32-c3-idf.yaml | 35 +++ .../components/pn7160_i2c/test.esp32-c3.yaml | 35 +++ .../components/pn7160_i2c/test.esp32-idf.yaml | 35 +++ tests/components/pn7160_i2c/test.esp32.yaml | 35 +++ tests/components/pn7160_i2c/test.esp8266.yaml | 35 +++ tests/components/pn7160_i2c/test.rp2040.yaml | 35 +++ .../pn7160_spi/test.esp32-c3-idf.yaml | 37 +++ .../components/pn7160_spi/test.esp32-c3.yaml | 37 +++ .../components/pn7160_spi/test.esp32-idf.yaml | 37 +++ tests/components/pn7160_spi/test.esp32.yaml | 37 +++ tests/components/pn7160_spi/test.esp8266.yaml | 37 +++ tests/components/pn7160_spi/test.rp2040.yaml | 37 +++ .../power_supply/test.esp32-c3-idf.yaml | 6 + .../power_supply/test.esp32-c3.yaml | 6 + .../power_supply/test.esp32-idf.yaml | 6 + tests/components/power_supply/test.esp32.yaml | 6 + .../components/power_supply/test.esp8266.yaml | 6 + .../components/power_supply/test.rp2040.yaml | 6 + .../prometheus/test.esp32-c3-idf.yaml | 21 ++ .../components/prometheus/test.esp32-c3.yaml | 21 ++ .../components/prometheus/test.esp32-idf.yaml | 21 ++ tests/components/prometheus/test.esp32.yaml | 21 ++ tests/components/prometheus/test.esp8266.yaml | 21 ++ tests/components/psram/test.esp32-c3-idf.yaml | 3 + tests/components/psram/test.esp32-c3.yaml | 3 + tests/components/psram/test.esp32-idf.yaml | 3 + tests/components/psram/test.esp32.yaml | 3 + .../pulse_counter/test.esp32-c3-idf.yaml | 9 + .../pulse_counter/test.esp32-c3.yaml | 9 + .../pulse_counter/test.esp32-idf.yaml | 9 + .../components/pulse_counter/test.esp32.yaml | 9 + .../pulse_counter/test.esp8266.yaml | 9 + .../components/pulse_counter/test.rp2040.yaml | 9 + .../pulse_meter/test.esp32-c3-idf.yaml | 13 + .../components/pulse_meter/test.esp32-c3.yaml | 13 + .../pulse_meter/test.esp32-idf.yaml | 13 + tests/components/pulse_meter/test.esp32.yaml | 13 + .../components/pulse_meter/test.esp8266.yaml | 13 + tests/components/pulse_meter/test.rp2040.yaml | 13 + .../pulse_width/test.esp32-c3-idf.yaml | 4 + .../components/pulse_width/test.esp32-c3.yaml | 4 + .../pulse_width/test.esp32-idf.yaml | 4 + tests/components/pulse_width/test.esp32.yaml | 4 + .../components/pulse_width/test.esp8266.yaml | 4 + tests/components/pulse_width/test.rp2040.yaml | 4 + .../pvvx_mithermometer/test.esp32-c3-idf.yaml | 44 ++++ .../pvvx_mithermometer/test.esp32-c3.yaml | 44 ++++ .../pvvx_mithermometer/test.esp32-idf.yaml | 44 ++++ .../pvvx_mithermometer/test.esp32.yaml | 44 ++++ .../pylontech/test.esp32-c3-idf.yaml | 48 ++++ tests/components/pylontech/test.esp32-c3.yaml | 48 ++++ .../components/pylontech/test.esp32-idf.yaml | 48 ++++ tests/components/pylontech/test.esp32.yaml | 48 ++++ tests/components/pylontech/test.esp8266.yaml | 48 ++++ tests/components/pylontech/test.rp2040.yaml | 48 ++++ .../pzem004t/test.esp32-c3-idf.yaml | 14 + tests/components/pzem004t/test.esp32-c3.yaml | 14 + tests/components/pzem004t/test.esp32-idf.yaml | 14 + tests/components/pzem004t/test.esp32.yaml | 14 + tests/components/pzem004t/test.esp8266.yaml | 14 + tests/components/pzem004t/test.rp2040.yaml | 14 + .../components/pzemac/test.esp32-c3-idf.yaml | 28 ++ tests/components/pzemac/test.esp32-c3.yaml | 28 ++ tests/components/pzemac/test.esp32-idf.yaml | 28 ++ tests/components/pzemac/test.esp32.yaml | 28 ++ tests/components/pzemac/test.esp8266.yaml | 28 ++ tests/components/pzemac/test.rp2040.yaml | 28 ++ .../components/pzemdc/test.esp32-c3-idf.yaml | 23 ++ tests/components/pzemdc/test.esp32-c3.yaml | 23 ++ tests/components/pzemdc/test.esp32-idf.yaml | 23 ++ tests/components/pzemdc/test.esp32.yaml | 23 ++ tests/components/pzemdc/test.esp8266.yaml | 23 ++ tests/components/pzemdc/test.rp2040.yaml | 23 ++ 173 files changed, 5245 insertions(+) create mode 100644 tests/components/partition/test.esp32-c3-idf.yaml create mode 100644 tests/components/partition/test.esp32-c3.yaml create mode 100644 tests/components/partition/test.esp32-idf.yaml create mode 100644 tests/components/partition/test.esp32.yaml create mode 100644 tests/components/pca6416a/test.esp32-c3-idf.yaml create mode 100644 tests/components/pca6416a/test.esp32-c3.yaml create mode 100644 tests/components/pca6416a/test.esp32-idf.yaml create mode 100644 tests/components/pca6416a/test.esp32.yaml create mode 100644 tests/components/pca6416a/test.esp8266.yaml create mode 100644 tests/components/pca6416a/test.rp2040.yaml create mode 100644 tests/components/pca9554/test.esp32-c3-idf.yaml create mode 100644 tests/components/pca9554/test.esp32-c3.yaml create mode 100644 tests/components/pca9554/test.esp32-idf.yaml create mode 100644 tests/components/pca9554/test.esp32.yaml create mode 100644 tests/components/pca9554/test.esp8266.yaml create mode 100644 tests/components/pca9554/test.rp2040.yaml create mode 100644 tests/components/pca9685/test.esp32-c3-idf.yaml create mode 100644 tests/components/pca9685/test.esp32-c3.yaml create mode 100644 tests/components/pca9685/test.esp32-idf.yaml create mode 100644 tests/components/pca9685/test.esp32.yaml create mode 100644 tests/components/pca9685/test.esp8266.yaml create mode 100644 tests/components/pca9685/test.rp2040.yaml create mode 100644 tests/components/pcd8544/test.esp32-c3-idf.yaml create mode 100644 tests/components/pcd8544/test.esp32-c3.yaml create mode 100644 tests/components/pcd8544/test.esp32-idf.yaml create mode 100644 tests/components/pcd8544/test.esp32.yaml create mode 100644 tests/components/pcd8544/test.esp8266.yaml create mode 100644 tests/components/pcd8544/test.rp2040.yaml create mode 100644 tests/components/pcf85063/test.esp32-c3-idf.yaml create mode 100644 tests/components/pcf85063/test.esp32-c3.yaml create mode 100644 tests/components/pcf85063/test.esp32-idf.yaml create mode 100644 tests/components/pcf85063/test.esp32.yaml create mode 100644 tests/components/pcf85063/test.esp8266.yaml create mode 100644 tests/components/pcf85063/test.rp2040.yaml create mode 100644 tests/components/pcf8563/test.esp32-c3-idf.yaml create mode 100644 tests/components/pcf8563/test.esp32-c3.yaml create mode 100644 tests/components/pcf8563/test.esp32-idf.yaml create mode 100644 tests/components/pcf8563/test.esp32.yaml create mode 100644 tests/components/pcf8563/test.esp8266.yaml create mode 100644 tests/components/pcf8563/test.rp2040.yaml create mode 100644 tests/components/pcf8574/test.esp32-c3-idf.yaml create mode 100644 tests/components/pcf8574/test.esp32-c3.yaml create mode 100644 tests/components/pcf8574/test.esp32-idf.yaml create mode 100644 tests/components/pcf8574/test.esp32.yaml create mode 100644 tests/components/pcf8574/test.esp8266.yaml create mode 100644 tests/components/pcf8574/test.rp2040.yaml create mode 100644 tests/components/pid/test.esp32-c3-idf.yaml create mode 100644 tests/components/pid/test.esp32-c3.yaml create mode 100644 tests/components/pid/test.esp32-idf.yaml create mode 100644 tests/components/pid/test.esp32.yaml create mode 100644 tests/components/pid/test.esp8266.yaml create mode 100644 tests/components/pid/test.rp2040.yaml create mode 100644 tests/components/pipsolar/test.esp32-c3-idf.yaml create mode 100644 tests/components/pipsolar/test.esp32-c3.yaml create mode 100644 tests/components/pipsolar/test.esp32-idf.yaml create mode 100644 tests/components/pipsolar/test.esp32.yaml create mode 100644 tests/components/pipsolar/test.esp8266.yaml create mode 100644 tests/components/pipsolar/test.rp2040.yaml create mode 100644 tests/components/pm1006/test.esp32-c3-idf.yaml create mode 100644 tests/components/pm1006/test.esp32-c3.yaml create mode 100644 tests/components/pm1006/test.esp32-idf.yaml create mode 100644 tests/components/pm1006/test.esp32.yaml create mode 100644 tests/components/pm1006/test.esp8266.yaml create mode 100644 tests/components/pm1006/test.rp2040.yaml create mode 100644 tests/components/pmsa003i/test.esp32-c3-idf.yaml create mode 100644 tests/components/pmsa003i/test.esp32-c3.yaml create mode 100644 tests/components/pmsa003i/test.esp32-idf.yaml create mode 100644 tests/components/pmsa003i/test.esp32.yaml create mode 100644 tests/components/pmsa003i/test.esp8266.yaml create mode 100644 tests/components/pmsa003i/test.rp2040.yaml create mode 100644 tests/components/pmsx003/test.esp32-c3-idf.yaml create mode 100644 tests/components/pmsx003/test.esp32-c3.yaml create mode 100644 tests/components/pmsx003/test.esp32-idf.yaml create mode 100644 tests/components/pmsx003/test.esp32.yaml create mode 100644 tests/components/pmsx003/test.esp8266.yaml create mode 100644 tests/components/pmsx003/test.rp2040.yaml create mode 100644 tests/components/pmwcs3/test.esp32-c3-idf.yaml create mode 100644 tests/components/pmwcs3/test.esp32-c3.yaml create mode 100644 tests/components/pmwcs3/test.esp32-idf.yaml create mode 100644 tests/components/pmwcs3/test.esp32.yaml create mode 100644 tests/components/pmwcs3/test.esp8266.yaml create mode 100644 tests/components/pmwcs3/test.rp2040.yaml create mode 100644 tests/components/pn532_i2c/test.esp32-c3-idf.yaml create mode 100644 tests/components/pn532_i2c/test.esp32-c3.yaml create mode 100644 tests/components/pn532_i2c/test.esp32-idf.yaml create mode 100644 tests/components/pn532_i2c/test.esp32.yaml create mode 100644 tests/components/pn532_i2c/test.esp8266.yaml create mode 100644 tests/components/pn532_i2c/test.rp2040.yaml create mode 100644 tests/components/pn532_spi/test.esp32-c3-idf.yaml create mode 100644 tests/components/pn532_spi/test.esp32-c3.yaml create mode 100644 tests/components/pn532_spi/test.esp32-idf.yaml create mode 100644 tests/components/pn532_spi/test.esp32.yaml create mode 100644 tests/components/pn532_spi/test.esp8266.yaml create mode 100644 tests/components/pn532_spi/test.rp2040.yaml create mode 100644 tests/components/pn7150_i2c/test.esp32-c3-idf.yaml create mode 100644 tests/components/pn7150_i2c/test.esp32-c3.yaml create mode 100644 tests/components/pn7150_i2c/test.esp32-idf.yaml create mode 100644 tests/components/pn7150_i2c/test.esp32.yaml create mode 100644 tests/components/pn7150_i2c/test.esp8266.yaml create mode 100644 tests/components/pn7150_i2c/test.rp2040.yaml create mode 100644 tests/components/pn7160_i2c/test.esp32-c3-idf.yaml create mode 100644 tests/components/pn7160_i2c/test.esp32-c3.yaml create mode 100644 tests/components/pn7160_i2c/test.esp32-idf.yaml create mode 100644 tests/components/pn7160_i2c/test.esp32.yaml create mode 100644 tests/components/pn7160_i2c/test.esp8266.yaml create mode 100644 tests/components/pn7160_i2c/test.rp2040.yaml create mode 100644 tests/components/pn7160_spi/test.esp32-c3-idf.yaml create mode 100644 tests/components/pn7160_spi/test.esp32-c3.yaml create mode 100644 tests/components/pn7160_spi/test.esp32-idf.yaml create mode 100644 tests/components/pn7160_spi/test.esp32.yaml create mode 100644 tests/components/pn7160_spi/test.esp8266.yaml create mode 100644 tests/components/pn7160_spi/test.rp2040.yaml create mode 100644 tests/components/power_supply/test.esp32-c3-idf.yaml create mode 100644 tests/components/power_supply/test.esp32-c3.yaml create mode 100644 tests/components/power_supply/test.esp32-idf.yaml create mode 100644 tests/components/power_supply/test.esp32.yaml create mode 100644 tests/components/power_supply/test.esp8266.yaml create mode 100644 tests/components/power_supply/test.rp2040.yaml create mode 100644 tests/components/prometheus/test.esp32-c3-idf.yaml create mode 100644 tests/components/prometheus/test.esp32-c3.yaml create mode 100644 tests/components/prometheus/test.esp32-idf.yaml create mode 100644 tests/components/prometheus/test.esp32.yaml create mode 100644 tests/components/prometheus/test.esp8266.yaml create mode 100644 tests/components/psram/test.esp32-c3-idf.yaml create mode 100644 tests/components/psram/test.esp32-c3.yaml create mode 100644 tests/components/psram/test.esp32-idf.yaml create mode 100644 tests/components/psram/test.esp32.yaml create mode 100644 tests/components/pulse_counter/test.esp32-c3-idf.yaml create mode 100644 tests/components/pulse_counter/test.esp32-c3.yaml create mode 100644 tests/components/pulse_counter/test.esp32-idf.yaml create mode 100644 tests/components/pulse_counter/test.esp32.yaml create mode 100644 tests/components/pulse_counter/test.esp8266.yaml create mode 100644 tests/components/pulse_counter/test.rp2040.yaml create mode 100644 tests/components/pulse_meter/test.esp32-c3-idf.yaml create mode 100644 tests/components/pulse_meter/test.esp32-c3.yaml create mode 100644 tests/components/pulse_meter/test.esp32-idf.yaml create mode 100644 tests/components/pulse_meter/test.esp32.yaml create mode 100644 tests/components/pulse_meter/test.esp8266.yaml create mode 100644 tests/components/pulse_meter/test.rp2040.yaml create mode 100644 tests/components/pulse_width/test.esp32-c3-idf.yaml create mode 100644 tests/components/pulse_width/test.esp32-c3.yaml create mode 100644 tests/components/pulse_width/test.esp32-idf.yaml create mode 100644 tests/components/pulse_width/test.esp32.yaml create mode 100644 tests/components/pulse_width/test.esp8266.yaml create mode 100644 tests/components/pulse_width/test.rp2040.yaml create mode 100644 tests/components/pvvx_mithermometer/test.esp32-c3-idf.yaml create mode 100644 tests/components/pvvx_mithermometer/test.esp32-c3.yaml create mode 100644 tests/components/pvvx_mithermometer/test.esp32-idf.yaml create mode 100644 tests/components/pvvx_mithermometer/test.esp32.yaml create mode 100644 tests/components/pylontech/test.esp32-c3-idf.yaml create mode 100644 tests/components/pylontech/test.esp32-c3.yaml create mode 100644 tests/components/pylontech/test.esp32-idf.yaml create mode 100644 tests/components/pylontech/test.esp32.yaml create mode 100644 tests/components/pylontech/test.esp8266.yaml create mode 100644 tests/components/pylontech/test.rp2040.yaml create mode 100644 tests/components/pzem004t/test.esp32-c3-idf.yaml create mode 100644 tests/components/pzem004t/test.esp32-c3.yaml create mode 100644 tests/components/pzem004t/test.esp32-idf.yaml create mode 100644 tests/components/pzem004t/test.esp32.yaml create mode 100644 tests/components/pzem004t/test.esp8266.yaml create mode 100644 tests/components/pzem004t/test.rp2040.yaml create mode 100644 tests/components/pzemac/test.esp32-c3-idf.yaml create mode 100644 tests/components/pzemac/test.esp32-c3.yaml create mode 100644 tests/components/pzemac/test.esp32-idf.yaml create mode 100644 tests/components/pzemac/test.esp32.yaml create mode 100644 tests/components/pzemac/test.esp8266.yaml create mode 100644 tests/components/pzemac/test.rp2040.yaml create mode 100644 tests/components/pzemdc/test.esp32-c3-idf.yaml create mode 100644 tests/components/pzemdc/test.esp32-c3.yaml create mode 100644 tests/components/pzemdc/test.esp32-idf.yaml create mode 100644 tests/components/pzemdc/test.esp32.yaml create mode 100644 tests/components/pzemdc/test.esp8266.yaml create mode 100644 tests/components/pzemdc/test.rp2040.yaml diff --git a/tests/components/partition/test.esp32-c3-idf.yaml b/tests/components/partition/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..77cfc5ad44 --- /dev/null +++ b/tests/components/partition/test.esp32-c3-idf.yaml @@ -0,0 +1,22 @@ +light: + - platform: esp32_rmt_led_strip + id: part_leds + default_transition_length: 500ms + chipset: ws2812 + rgb_order: GRB + num_leds: 256 + pin: 2 + rmt_channel: 0 + - platform: partition + name: Partition Light + segments: + - id: part_leds + from: 0 + to: 0 + - id: part_leds + from: 1 + to: 10 + - id: part_leds + from: 20 + to: 25 + - single_light_id: part_leds diff --git a/tests/components/partition/test.esp32-c3.yaml b/tests/components/partition/test.esp32-c3.yaml new file mode 100644 index 0000000000..77cfc5ad44 --- /dev/null +++ b/tests/components/partition/test.esp32-c3.yaml @@ -0,0 +1,22 @@ +light: + - platform: esp32_rmt_led_strip + id: part_leds + default_transition_length: 500ms + chipset: ws2812 + rgb_order: GRB + num_leds: 256 + pin: 2 + rmt_channel: 0 + - platform: partition + name: Partition Light + segments: + - id: part_leds + from: 0 + to: 0 + - id: part_leds + from: 1 + to: 10 + - id: part_leds + from: 20 + to: 25 + - single_light_id: part_leds diff --git a/tests/components/partition/test.esp32-idf.yaml b/tests/components/partition/test.esp32-idf.yaml new file mode 100644 index 0000000000..77cfc5ad44 --- /dev/null +++ b/tests/components/partition/test.esp32-idf.yaml @@ -0,0 +1,22 @@ +light: + - platform: esp32_rmt_led_strip + id: part_leds + default_transition_length: 500ms + chipset: ws2812 + rgb_order: GRB + num_leds: 256 + pin: 2 + rmt_channel: 0 + - platform: partition + name: Partition Light + segments: + - id: part_leds + from: 0 + to: 0 + - id: part_leds + from: 1 + to: 10 + - id: part_leds + from: 20 + to: 25 + - single_light_id: part_leds diff --git a/tests/components/partition/test.esp32.yaml b/tests/components/partition/test.esp32.yaml new file mode 100644 index 0000000000..c8eae67d40 --- /dev/null +++ b/tests/components/partition/test.esp32.yaml @@ -0,0 +1,22 @@ +light: + - platform: fastled_clockless + id: part_leds + chipset: WS2812B + pin: 2 + num_leds: 256 + rgb_order: GRB + default_transition_length: 0s + color_correct: [50%, 50%, 50%] + - platform: partition + name: Partition Light + segments: + - id: part_leds + from: 0 + to: 0 + - id: part_leds + from: 1 + to: 10 + - id: part_leds + from: 20 + to: 25 + - single_light_id: part_leds diff --git a/tests/components/pca6416a/test.esp32-c3-idf.yaml b/tests/components/pca6416a/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..fe940c44cc --- /dev/null +++ b/tests/components/pca6416a/test.esp32-c3-idf.yaml @@ -0,0 +1,17 @@ +i2c: + - id: i2c_pca6416a + scl: 5 + sda: 4 + +pca6416a: + - id: pca6416a_hub + address: 0x21 + +binary_sensor: + - platform: gpio + name: PCA6416A Binary Sensor + pin: + pca6416a: pca6416a_hub + number: 15 + mode: INPUT + inverted: true diff --git a/tests/components/pca6416a/test.esp32-c3.yaml b/tests/components/pca6416a/test.esp32-c3.yaml new file mode 100644 index 0000000000..fe940c44cc --- /dev/null +++ b/tests/components/pca6416a/test.esp32-c3.yaml @@ -0,0 +1,17 @@ +i2c: + - id: i2c_pca6416a + scl: 5 + sda: 4 + +pca6416a: + - id: pca6416a_hub + address: 0x21 + +binary_sensor: + - platform: gpio + name: PCA6416A Binary Sensor + pin: + pca6416a: pca6416a_hub + number: 15 + mode: INPUT + inverted: true diff --git a/tests/components/pca6416a/test.esp32-idf.yaml b/tests/components/pca6416a/test.esp32-idf.yaml new file mode 100644 index 0000000000..669e9416e4 --- /dev/null +++ b/tests/components/pca6416a/test.esp32-idf.yaml @@ -0,0 +1,17 @@ +i2c: + - id: i2c_pca6416a + scl: 16 + sda: 17 + +pca6416a: + - id: pca6416a_hub + address: 0x21 + +binary_sensor: + - platform: gpio + name: PCA6416A Binary Sensor + pin: + pca6416a: pca6416a_hub + number: 15 + mode: INPUT + inverted: true diff --git a/tests/components/pca6416a/test.esp32.yaml b/tests/components/pca6416a/test.esp32.yaml new file mode 100644 index 0000000000..669e9416e4 --- /dev/null +++ b/tests/components/pca6416a/test.esp32.yaml @@ -0,0 +1,17 @@ +i2c: + - id: i2c_pca6416a + scl: 16 + sda: 17 + +pca6416a: + - id: pca6416a_hub + address: 0x21 + +binary_sensor: + - platform: gpio + name: PCA6416A Binary Sensor + pin: + pca6416a: pca6416a_hub + number: 15 + mode: INPUT + inverted: true diff --git a/tests/components/pca6416a/test.esp8266.yaml b/tests/components/pca6416a/test.esp8266.yaml new file mode 100644 index 0000000000..fe940c44cc --- /dev/null +++ b/tests/components/pca6416a/test.esp8266.yaml @@ -0,0 +1,17 @@ +i2c: + - id: i2c_pca6416a + scl: 5 + sda: 4 + +pca6416a: + - id: pca6416a_hub + address: 0x21 + +binary_sensor: + - platform: gpio + name: PCA6416A Binary Sensor + pin: + pca6416a: pca6416a_hub + number: 15 + mode: INPUT + inverted: true diff --git a/tests/components/pca6416a/test.rp2040.yaml b/tests/components/pca6416a/test.rp2040.yaml new file mode 100644 index 0000000000..fe940c44cc --- /dev/null +++ b/tests/components/pca6416a/test.rp2040.yaml @@ -0,0 +1,17 @@ +i2c: + - id: i2c_pca6416a + scl: 5 + sda: 4 + +pca6416a: + - id: pca6416a_hub + address: 0x21 + +binary_sensor: + - platform: gpio + name: PCA6416A Binary Sensor + pin: + pca6416a: pca6416a_hub + number: 15 + mode: INPUT + inverted: true diff --git a/tests/components/pca9554/test.esp32-c3-idf.yaml b/tests/components/pca9554/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..0ff453e64f --- /dev/null +++ b/tests/components/pca9554/test.esp32-c3-idf.yaml @@ -0,0 +1,26 @@ +i2c: + - id: i2c_pca9554 + scl: 5 + sda: 4 + +pca9554: + - id: pca9554_hub + pin_count: 8 + address: 0x3F + +binary_sensor: + - platform: gpio + id: pca9554_input + name: PCA9554 Binary Sensor + pin: + pca9554: pca9554_hub + number: 1 + mode: INPUT + inverted: true + - platform: gpio + id: pca9554_output + pin: + pca9554: pca9554_hub + number: 0 + mode: OUTPUT + inverted: false diff --git a/tests/components/pca9554/test.esp32-c3.yaml b/tests/components/pca9554/test.esp32-c3.yaml new file mode 100644 index 0000000000..0ff453e64f --- /dev/null +++ b/tests/components/pca9554/test.esp32-c3.yaml @@ -0,0 +1,26 @@ +i2c: + - id: i2c_pca9554 + scl: 5 + sda: 4 + +pca9554: + - id: pca9554_hub + pin_count: 8 + address: 0x3F + +binary_sensor: + - platform: gpio + id: pca9554_input + name: PCA9554 Binary Sensor + pin: + pca9554: pca9554_hub + number: 1 + mode: INPUT + inverted: true + - platform: gpio + id: pca9554_output + pin: + pca9554: pca9554_hub + number: 0 + mode: OUTPUT + inverted: false diff --git a/tests/components/pca9554/test.esp32-idf.yaml b/tests/components/pca9554/test.esp32-idf.yaml new file mode 100644 index 0000000000..8fe9686303 --- /dev/null +++ b/tests/components/pca9554/test.esp32-idf.yaml @@ -0,0 +1,26 @@ +i2c: + - id: i2c_pca9554 + scl: 16 + sda: 17 + +pca9554: + - id: pca9554_hub + pin_count: 8 + address: 0x3F + +binary_sensor: + - platform: gpio + id: pca9554_input + name: PCA9554 Binary Sensor + pin: + pca9554: pca9554_hub + number: 1 + mode: INPUT + inverted: true + - platform: gpio + id: pca9554_output + pin: + pca9554: pca9554_hub + number: 0 + mode: OUTPUT + inverted: false diff --git a/tests/components/pca9554/test.esp32.yaml b/tests/components/pca9554/test.esp32.yaml new file mode 100644 index 0000000000..8fe9686303 --- /dev/null +++ b/tests/components/pca9554/test.esp32.yaml @@ -0,0 +1,26 @@ +i2c: + - id: i2c_pca9554 + scl: 16 + sda: 17 + +pca9554: + - id: pca9554_hub + pin_count: 8 + address: 0x3F + +binary_sensor: + - platform: gpio + id: pca9554_input + name: PCA9554 Binary Sensor + pin: + pca9554: pca9554_hub + number: 1 + mode: INPUT + inverted: true + - platform: gpio + id: pca9554_output + pin: + pca9554: pca9554_hub + number: 0 + mode: OUTPUT + inverted: false diff --git a/tests/components/pca9554/test.esp8266.yaml b/tests/components/pca9554/test.esp8266.yaml new file mode 100644 index 0000000000..0ff453e64f --- /dev/null +++ b/tests/components/pca9554/test.esp8266.yaml @@ -0,0 +1,26 @@ +i2c: + - id: i2c_pca9554 + scl: 5 + sda: 4 + +pca9554: + - id: pca9554_hub + pin_count: 8 + address: 0x3F + +binary_sensor: + - platform: gpio + id: pca9554_input + name: PCA9554 Binary Sensor + pin: + pca9554: pca9554_hub + number: 1 + mode: INPUT + inverted: true + - platform: gpio + id: pca9554_output + pin: + pca9554: pca9554_hub + number: 0 + mode: OUTPUT + inverted: false diff --git a/tests/components/pca9554/test.rp2040.yaml b/tests/components/pca9554/test.rp2040.yaml new file mode 100644 index 0000000000..0ff453e64f --- /dev/null +++ b/tests/components/pca9554/test.rp2040.yaml @@ -0,0 +1,26 @@ +i2c: + - id: i2c_pca9554 + scl: 5 + sda: 4 + +pca9554: + - id: pca9554_hub + pin_count: 8 + address: 0x3F + +binary_sensor: + - platform: gpio + id: pca9554_input + name: PCA9554 Binary Sensor + pin: + pca9554: pca9554_hub + number: 1 + mode: INPUT + inverted: true + - platform: gpio + id: pca9554_output + pin: + pca9554: pca9554_hub + number: 0 + mode: OUTPUT + inverted: false diff --git a/tests/components/pca9685/test.esp32-c3-idf.yaml b/tests/components/pca9685/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..e532f323be --- /dev/null +++ b/tests/components/pca9685/test.esp32-c3-idf.yaml @@ -0,0 +1,34 @@ +i2c: + - id: i2c_pca9685 + scl: 5 + sda: 4 + +pca9685: + frequency: 500 + address: 0x0 + +output: + - platform: pca9685 + id: pca_0 + channel: 0 + - platform: pca9685 + id: pca_1 + channel: 1 + - platform: pca9685 + id: pca_2 + channel: 2 + - platform: pca9685 + id: pca_3 + channel: 3 + - platform: pca9685 + id: pca_4 + channel: 4 + - platform: pca9685 + id: pca_5 + channel: 5 + - platform: pca9685 + id: pca_6 + channel: 6 + - platform: pca9685 + id: pca_7 + channel: 7 diff --git a/tests/components/pca9685/test.esp32-c3.yaml b/tests/components/pca9685/test.esp32-c3.yaml new file mode 100644 index 0000000000..e532f323be --- /dev/null +++ b/tests/components/pca9685/test.esp32-c3.yaml @@ -0,0 +1,34 @@ +i2c: + - id: i2c_pca9685 + scl: 5 + sda: 4 + +pca9685: + frequency: 500 + address: 0x0 + +output: + - platform: pca9685 + id: pca_0 + channel: 0 + - platform: pca9685 + id: pca_1 + channel: 1 + - platform: pca9685 + id: pca_2 + channel: 2 + - platform: pca9685 + id: pca_3 + channel: 3 + - platform: pca9685 + id: pca_4 + channel: 4 + - platform: pca9685 + id: pca_5 + channel: 5 + - platform: pca9685 + id: pca_6 + channel: 6 + - platform: pca9685 + id: pca_7 + channel: 7 diff --git a/tests/components/pca9685/test.esp32-idf.yaml b/tests/components/pca9685/test.esp32-idf.yaml new file mode 100644 index 0000000000..d02a16bcd1 --- /dev/null +++ b/tests/components/pca9685/test.esp32-idf.yaml @@ -0,0 +1,34 @@ +i2c: + - id: i2c_pca9685 + scl: 16 + sda: 17 + +pca9685: + frequency: 500 + address: 0x0 + +output: + - platform: pca9685 + id: pca_0 + channel: 0 + - platform: pca9685 + id: pca_1 + channel: 1 + - platform: pca9685 + id: pca_2 + channel: 2 + - platform: pca9685 + id: pca_3 + channel: 3 + - platform: pca9685 + id: pca_4 + channel: 4 + - platform: pca9685 + id: pca_5 + channel: 5 + - platform: pca9685 + id: pca_6 + channel: 6 + - platform: pca9685 + id: pca_7 + channel: 7 diff --git a/tests/components/pca9685/test.esp32.yaml b/tests/components/pca9685/test.esp32.yaml new file mode 100644 index 0000000000..d02a16bcd1 --- /dev/null +++ b/tests/components/pca9685/test.esp32.yaml @@ -0,0 +1,34 @@ +i2c: + - id: i2c_pca9685 + scl: 16 + sda: 17 + +pca9685: + frequency: 500 + address: 0x0 + +output: + - platform: pca9685 + id: pca_0 + channel: 0 + - platform: pca9685 + id: pca_1 + channel: 1 + - platform: pca9685 + id: pca_2 + channel: 2 + - platform: pca9685 + id: pca_3 + channel: 3 + - platform: pca9685 + id: pca_4 + channel: 4 + - platform: pca9685 + id: pca_5 + channel: 5 + - platform: pca9685 + id: pca_6 + channel: 6 + - platform: pca9685 + id: pca_7 + channel: 7 diff --git a/tests/components/pca9685/test.esp8266.yaml b/tests/components/pca9685/test.esp8266.yaml new file mode 100644 index 0000000000..e532f323be --- /dev/null +++ b/tests/components/pca9685/test.esp8266.yaml @@ -0,0 +1,34 @@ +i2c: + - id: i2c_pca9685 + scl: 5 + sda: 4 + +pca9685: + frequency: 500 + address: 0x0 + +output: + - platform: pca9685 + id: pca_0 + channel: 0 + - platform: pca9685 + id: pca_1 + channel: 1 + - platform: pca9685 + id: pca_2 + channel: 2 + - platform: pca9685 + id: pca_3 + channel: 3 + - platform: pca9685 + id: pca_4 + channel: 4 + - platform: pca9685 + id: pca_5 + channel: 5 + - platform: pca9685 + id: pca_6 + channel: 6 + - platform: pca9685 + id: pca_7 + channel: 7 diff --git a/tests/components/pca9685/test.rp2040.yaml b/tests/components/pca9685/test.rp2040.yaml new file mode 100644 index 0000000000..0ff453e64f --- /dev/null +++ b/tests/components/pca9685/test.rp2040.yaml @@ -0,0 +1,26 @@ +i2c: + - id: i2c_pca9554 + scl: 5 + sda: 4 + +pca9554: + - id: pca9554_hub + pin_count: 8 + address: 0x3F + +binary_sensor: + - platform: gpio + id: pca9554_input + name: PCA9554 Binary Sensor + pin: + pca9554: pca9554_hub + number: 1 + mode: INPUT + inverted: true + - platform: gpio + id: pca9554_output + pin: + pca9554: pca9554_hub + number: 0 + mode: OUTPUT + inverted: false diff --git a/tests/components/pcd8544/test.esp32-c3-idf.yaml b/tests/components/pcd8544/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..57771d2d73 --- /dev/null +++ b/tests/components/pcd8544/test.esp32-c3-idf.yaml @@ -0,0 +1,14 @@ +spi: + - id: spi_pcd8544 + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +display: + - platform: pcd8544 + cs_pin: 2 + dc_pin: 3 + reset_pin: 1 + contrast: 60 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); diff --git a/tests/components/pcd8544/test.esp32-c3.yaml b/tests/components/pcd8544/test.esp32-c3.yaml new file mode 100644 index 0000000000..57771d2d73 --- /dev/null +++ b/tests/components/pcd8544/test.esp32-c3.yaml @@ -0,0 +1,14 @@ +spi: + - id: spi_pcd8544 + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +display: + - platform: pcd8544 + cs_pin: 2 + dc_pin: 3 + reset_pin: 1 + contrast: 60 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); diff --git a/tests/components/pcd8544/test.esp32-idf.yaml b/tests/components/pcd8544/test.esp32-idf.yaml new file mode 100644 index 0000000000..20c05c407f --- /dev/null +++ b/tests/components/pcd8544/test.esp32-idf.yaml @@ -0,0 +1,14 @@ +spi: + - id: spi_pcd8544 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +display: + - platform: pcd8544 + cs_pin: 12 + dc_pin: 13 + reset_pin: 14 + contrast: 60 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); diff --git a/tests/components/pcd8544/test.esp32.yaml b/tests/components/pcd8544/test.esp32.yaml new file mode 100644 index 0000000000..20c05c407f --- /dev/null +++ b/tests/components/pcd8544/test.esp32.yaml @@ -0,0 +1,14 @@ +spi: + - id: spi_pcd8544 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +display: + - platform: pcd8544 + cs_pin: 12 + dc_pin: 13 + reset_pin: 14 + contrast: 60 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); diff --git a/tests/components/pcd8544/test.esp8266.yaml b/tests/components/pcd8544/test.esp8266.yaml new file mode 100644 index 0000000000..6e6022c6d2 --- /dev/null +++ b/tests/components/pcd8544/test.esp8266.yaml @@ -0,0 +1,14 @@ +spi: + - id: spi_pcd8544 + clk_pin: 14 + mosi_pin: 13 + miso_pin: 12 + +display: + - platform: pcd8544 + cs_pin: 15 + dc_pin: 16 + reset_pin: 5 + contrast: 60 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); diff --git a/tests/components/pcd8544/test.rp2040.yaml b/tests/components/pcd8544/test.rp2040.yaml new file mode 100644 index 0000000000..7181f99fb1 --- /dev/null +++ b/tests/components/pcd8544/test.rp2040.yaml @@ -0,0 +1,14 @@ +spi: + - id: spi_pcd8544 + clk_pin: 2 + mosi_pin: 3 + miso_pin: 4 + +display: + - platform: pcd8544 + cs_pin: 6 + dc_pin: 5 + reset_pin: 7 + contrast: 60 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); diff --git a/tests/components/pcf85063/test.esp32-c3-idf.yaml b/tests/components/pcf85063/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..9e1a3da81e --- /dev/null +++ b/tests/components/pcf85063/test.esp32-c3-idf.yaml @@ -0,0 +1,12 @@ +esphome: + on_boot: + - pcf85063.read_time + - pcf85063.write_time + +i2c: + - id: i2c_pcf85063 + scl: 5 + sda: 4 + +time: + - platform: pcf85063 diff --git a/tests/components/pcf85063/test.esp32-c3.yaml b/tests/components/pcf85063/test.esp32-c3.yaml new file mode 100644 index 0000000000..9e1a3da81e --- /dev/null +++ b/tests/components/pcf85063/test.esp32-c3.yaml @@ -0,0 +1,12 @@ +esphome: + on_boot: + - pcf85063.read_time + - pcf85063.write_time + +i2c: + - id: i2c_pcf85063 + scl: 5 + sda: 4 + +time: + - platform: pcf85063 diff --git a/tests/components/pcf85063/test.esp32-idf.yaml b/tests/components/pcf85063/test.esp32-idf.yaml new file mode 100644 index 0000000000..9cce415103 --- /dev/null +++ b/tests/components/pcf85063/test.esp32-idf.yaml @@ -0,0 +1,12 @@ +esphome: + on_boot: + - pcf85063.read_time + - pcf85063.write_time + +i2c: + - id: i2c_pcf85063 + scl: 16 + sda: 17 + +time: + - platform: pcf85063 diff --git a/tests/components/pcf85063/test.esp32.yaml b/tests/components/pcf85063/test.esp32.yaml new file mode 100644 index 0000000000..9cce415103 --- /dev/null +++ b/tests/components/pcf85063/test.esp32.yaml @@ -0,0 +1,12 @@ +esphome: + on_boot: + - pcf85063.read_time + - pcf85063.write_time + +i2c: + - id: i2c_pcf85063 + scl: 16 + sda: 17 + +time: + - platform: pcf85063 diff --git a/tests/components/pcf85063/test.esp8266.yaml b/tests/components/pcf85063/test.esp8266.yaml new file mode 100644 index 0000000000..9e1a3da81e --- /dev/null +++ b/tests/components/pcf85063/test.esp8266.yaml @@ -0,0 +1,12 @@ +esphome: + on_boot: + - pcf85063.read_time + - pcf85063.write_time + +i2c: + - id: i2c_pcf85063 + scl: 5 + sda: 4 + +time: + - platform: pcf85063 diff --git a/tests/components/pcf85063/test.rp2040.yaml b/tests/components/pcf85063/test.rp2040.yaml new file mode 100644 index 0000000000..9e1a3da81e --- /dev/null +++ b/tests/components/pcf85063/test.rp2040.yaml @@ -0,0 +1,12 @@ +esphome: + on_boot: + - pcf85063.read_time + - pcf85063.write_time + +i2c: + - id: i2c_pcf85063 + scl: 5 + sda: 4 + +time: + - platform: pcf85063 diff --git a/tests/components/pcf8563/test.esp32-c3-idf.yaml b/tests/components/pcf8563/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..f91a465e0f --- /dev/null +++ b/tests/components/pcf8563/test.esp32-c3-idf.yaml @@ -0,0 +1,12 @@ +esphome: + on_boot: + - pcf8563.read_time + - pcf8563.write_time + +i2c: + - id: i2c_pcf8563 + scl: 5 + sda: 4 + +time: + - platform: pcf8563 diff --git a/tests/components/pcf8563/test.esp32-c3.yaml b/tests/components/pcf8563/test.esp32-c3.yaml new file mode 100644 index 0000000000..f91a465e0f --- /dev/null +++ b/tests/components/pcf8563/test.esp32-c3.yaml @@ -0,0 +1,12 @@ +esphome: + on_boot: + - pcf8563.read_time + - pcf8563.write_time + +i2c: + - id: i2c_pcf8563 + scl: 5 + sda: 4 + +time: + - platform: pcf8563 diff --git a/tests/components/pcf8563/test.esp32-idf.yaml b/tests/components/pcf8563/test.esp32-idf.yaml new file mode 100644 index 0000000000..e95b487b19 --- /dev/null +++ b/tests/components/pcf8563/test.esp32-idf.yaml @@ -0,0 +1,12 @@ +esphome: + on_boot: + - pcf8563.read_time + - pcf8563.write_time + +i2c: + - id: i2c_pcf8563 + scl: 16 + sda: 17 + +time: + - platform: pcf8563 diff --git a/tests/components/pcf8563/test.esp32.yaml b/tests/components/pcf8563/test.esp32.yaml new file mode 100644 index 0000000000..e95b487b19 --- /dev/null +++ b/tests/components/pcf8563/test.esp32.yaml @@ -0,0 +1,12 @@ +esphome: + on_boot: + - pcf8563.read_time + - pcf8563.write_time + +i2c: + - id: i2c_pcf8563 + scl: 16 + sda: 17 + +time: + - platform: pcf8563 diff --git a/tests/components/pcf8563/test.esp8266.yaml b/tests/components/pcf8563/test.esp8266.yaml new file mode 100644 index 0000000000..f91a465e0f --- /dev/null +++ b/tests/components/pcf8563/test.esp8266.yaml @@ -0,0 +1,12 @@ +esphome: + on_boot: + - pcf8563.read_time + - pcf8563.write_time + +i2c: + - id: i2c_pcf8563 + scl: 5 + sda: 4 + +time: + - platform: pcf8563 diff --git a/tests/components/pcf8563/test.rp2040.yaml b/tests/components/pcf8563/test.rp2040.yaml new file mode 100644 index 0000000000..f91a465e0f --- /dev/null +++ b/tests/components/pcf8563/test.rp2040.yaml @@ -0,0 +1,12 @@ +esphome: + on_boot: + - pcf8563.read_time + - pcf8563.write_time + +i2c: + - id: i2c_pcf8563 + scl: 5 + sda: 4 + +time: + - platform: pcf8563 diff --git a/tests/components/pcf8574/test.esp32-c3-idf.yaml b/tests/components/pcf8574/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..551e425892 --- /dev/null +++ b/tests/components/pcf8574/test.esp32-c3-idf.yaml @@ -0,0 +1,28 @@ +i2c: + - id: i2c_pcf8563 + scl: 5 + sda: 4 + +pcf8574: + - id: pcf8574_hub + address: 0x21 + pcf8575: false + +binary_sensor: + - platform: gpio + id: pcf8574_binary_sensor + name: PCF Binary Sensor + pin: + pcf8574: pcf8574_hub + number: 1 + mode: INPUT + inverted: true + +output: + - platform: gpio + id: pcf8574_output + pin: + pcf8574: pcf8574_hub + number: 0 + mode: OUTPUT + inverted: false diff --git a/tests/components/pcf8574/test.esp32-c3.yaml b/tests/components/pcf8574/test.esp32-c3.yaml new file mode 100644 index 0000000000..551e425892 --- /dev/null +++ b/tests/components/pcf8574/test.esp32-c3.yaml @@ -0,0 +1,28 @@ +i2c: + - id: i2c_pcf8563 + scl: 5 + sda: 4 + +pcf8574: + - id: pcf8574_hub + address: 0x21 + pcf8575: false + +binary_sensor: + - platform: gpio + id: pcf8574_binary_sensor + name: PCF Binary Sensor + pin: + pcf8574: pcf8574_hub + number: 1 + mode: INPUT + inverted: true + +output: + - platform: gpio + id: pcf8574_output + pin: + pcf8574: pcf8574_hub + number: 0 + mode: OUTPUT + inverted: false diff --git a/tests/components/pcf8574/test.esp32-idf.yaml b/tests/components/pcf8574/test.esp32-idf.yaml new file mode 100644 index 0000000000..aeed55f4fe --- /dev/null +++ b/tests/components/pcf8574/test.esp32-idf.yaml @@ -0,0 +1,28 @@ +i2c: + - id: i2c_pcf8563 + scl: 16 + sda: 17 + +pcf8574: + - id: pcf8574_hub + address: 0x21 + pcf8575: false + +binary_sensor: + - platform: gpio + id: pcf8574_binary_sensor + name: PCF Binary Sensor + pin: + pcf8574: pcf8574_hub + number: 1 + mode: INPUT + inverted: true + +output: + - platform: gpio + id: pcf8574_output + pin: + pcf8574: pcf8574_hub + number: 0 + mode: OUTPUT + inverted: false diff --git a/tests/components/pcf8574/test.esp32.yaml b/tests/components/pcf8574/test.esp32.yaml new file mode 100644 index 0000000000..aeed55f4fe --- /dev/null +++ b/tests/components/pcf8574/test.esp32.yaml @@ -0,0 +1,28 @@ +i2c: + - id: i2c_pcf8563 + scl: 16 + sda: 17 + +pcf8574: + - id: pcf8574_hub + address: 0x21 + pcf8575: false + +binary_sensor: + - platform: gpio + id: pcf8574_binary_sensor + name: PCF Binary Sensor + pin: + pcf8574: pcf8574_hub + number: 1 + mode: INPUT + inverted: true + +output: + - platform: gpio + id: pcf8574_output + pin: + pcf8574: pcf8574_hub + number: 0 + mode: OUTPUT + inverted: false diff --git a/tests/components/pcf8574/test.esp8266.yaml b/tests/components/pcf8574/test.esp8266.yaml new file mode 100644 index 0000000000..551e425892 --- /dev/null +++ b/tests/components/pcf8574/test.esp8266.yaml @@ -0,0 +1,28 @@ +i2c: + - id: i2c_pcf8563 + scl: 5 + sda: 4 + +pcf8574: + - id: pcf8574_hub + address: 0x21 + pcf8575: false + +binary_sensor: + - platform: gpio + id: pcf8574_binary_sensor + name: PCF Binary Sensor + pin: + pcf8574: pcf8574_hub + number: 1 + mode: INPUT + inverted: true + +output: + - platform: gpio + id: pcf8574_output + pin: + pcf8574: pcf8574_hub + number: 0 + mode: OUTPUT + inverted: false diff --git a/tests/components/pcf8574/test.rp2040.yaml b/tests/components/pcf8574/test.rp2040.yaml new file mode 100644 index 0000000000..551e425892 --- /dev/null +++ b/tests/components/pcf8574/test.rp2040.yaml @@ -0,0 +1,28 @@ +i2c: + - id: i2c_pcf8563 + scl: 5 + sda: 4 + +pcf8574: + - id: pcf8574_hub + address: 0x21 + pcf8575: false + +binary_sensor: + - platform: gpio + id: pcf8574_binary_sensor + name: PCF Binary Sensor + pin: + pcf8574: pcf8574_hub + number: 1 + mode: INPUT + inverted: true + +output: + - platform: gpio + id: pcf8574_output + pin: + pcf8574: pcf8574_hub + number: 0 + mode: OUTPUT + inverted: false diff --git a/tests/components/pid/test.esp32-c3-idf.yaml b/tests/components/pid/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..5f7762872f --- /dev/null +++ b/tests/components/pid/test.esp32-c3-idf.yaml @@ -0,0 +1,56 @@ +esphome: + on_boot: + then: + - climate.pid.autotune: pid_climate + - climate.pid.autotune: + id: pid_climate + noiseband: 0.25 + positive_output: 25% + negative_output: -25% + - climate.pid.set_control_parameters: + id: pid_climate + kp: 0.0 + ki: 0.0 + kd: 0.0 + - climate.pid.reset_integral_term: pid_climate + +output: + - platform: slow_pwm + pin: 4 + id: pid_slow_pwm + period: 15s + restart_cycle_on_state_change: false + +sensor: + - platform: template + id: template_sensor1 + lambda: |- + if (millis() > 10000) { + return 42.0; + } else { + return 0.0; + } + update_interval: 60s + +climate: + - platform: pid + id: pid_climate + name: PID Climate Controller + sensor: template_sensor1 + humidity_sensor: template_sensor1 + default_target_temperature: 21°C + heat_output: pid_slow_pwm + control_parameters: + kp: 0.0 + ki: 0.0 + kd: 0.0 + max_integral: 0.0 + output_averaging_samples: 1 + derivative_averaging_samples: 1 + deadband_parameters: + threshold_high: 0.4 + threshold_low: -2.0 + kp_multiplier: 0.0 + ki_multiplier: 0.0 + kd_multiplier: 0.0 + deadband_output_averaging_samples: 1 diff --git a/tests/components/pid/test.esp32-c3.yaml b/tests/components/pid/test.esp32-c3.yaml new file mode 100644 index 0000000000..5f7762872f --- /dev/null +++ b/tests/components/pid/test.esp32-c3.yaml @@ -0,0 +1,56 @@ +esphome: + on_boot: + then: + - climate.pid.autotune: pid_climate + - climate.pid.autotune: + id: pid_climate + noiseband: 0.25 + positive_output: 25% + negative_output: -25% + - climate.pid.set_control_parameters: + id: pid_climate + kp: 0.0 + ki: 0.0 + kd: 0.0 + - climate.pid.reset_integral_term: pid_climate + +output: + - platform: slow_pwm + pin: 4 + id: pid_slow_pwm + period: 15s + restart_cycle_on_state_change: false + +sensor: + - platform: template + id: template_sensor1 + lambda: |- + if (millis() > 10000) { + return 42.0; + } else { + return 0.0; + } + update_interval: 60s + +climate: + - platform: pid + id: pid_climate + name: PID Climate Controller + sensor: template_sensor1 + humidity_sensor: template_sensor1 + default_target_temperature: 21°C + heat_output: pid_slow_pwm + control_parameters: + kp: 0.0 + ki: 0.0 + kd: 0.0 + max_integral: 0.0 + output_averaging_samples: 1 + derivative_averaging_samples: 1 + deadband_parameters: + threshold_high: 0.4 + threshold_low: -2.0 + kp_multiplier: 0.0 + ki_multiplier: 0.0 + kd_multiplier: 0.0 + deadband_output_averaging_samples: 1 diff --git a/tests/components/pid/test.esp32-idf.yaml b/tests/components/pid/test.esp32-idf.yaml new file mode 100644 index 0000000000..5f7762872f --- /dev/null +++ b/tests/components/pid/test.esp32-idf.yaml @@ -0,0 +1,56 @@ +esphome: + on_boot: + then: + - climate.pid.autotune: pid_climate + - climate.pid.autotune: + id: pid_climate + noiseband: 0.25 + positive_output: 25% + negative_output: -25% + - climate.pid.set_control_parameters: + id: pid_climate + kp: 0.0 + ki: 0.0 + kd: 0.0 + - climate.pid.reset_integral_term: pid_climate + +output: + - platform: slow_pwm + pin: 4 + id: pid_slow_pwm + period: 15s + restart_cycle_on_state_change: false + +sensor: + - platform: template + id: template_sensor1 + lambda: |- + if (millis() > 10000) { + return 42.0; + } else { + return 0.0; + } + update_interval: 60s + +climate: + - platform: pid + id: pid_climate + name: PID Climate Controller + sensor: template_sensor1 + humidity_sensor: template_sensor1 + default_target_temperature: 21°C + heat_output: pid_slow_pwm + control_parameters: + kp: 0.0 + ki: 0.0 + kd: 0.0 + max_integral: 0.0 + output_averaging_samples: 1 + derivative_averaging_samples: 1 + deadband_parameters: + threshold_high: 0.4 + threshold_low: -2.0 + kp_multiplier: 0.0 + ki_multiplier: 0.0 + kd_multiplier: 0.0 + deadband_output_averaging_samples: 1 diff --git a/tests/components/pid/test.esp32.yaml b/tests/components/pid/test.esp32.yaml new file mode 100644 index 0000000000..5f7762872f --- /dev/null +++ b/tests/components/pid/test.esp32.yaml @@ -0,0 +1,56 @@ +esphome: + on_boot: + then: + - climate.pid.autotune: pid_climate + - climate.pid.autotune: + id: pid_climate + noiseband: 0.25 + positive_output: 25% + negative_output: -25% + - climate.pid.set_control_parameters: + id: pid_climate + kp: 0.0 + ki: 0.0 + kd: 0.0 + - climate.pid.reset_integral_term: pid_climate + +output: + - platform: slow_pwm + pin: 4 + id: pid_slow_pwm + period: 15s + restart_cycle_on_state_change: false + +sensor: + - platform: template + id: template_sensor1 + lambda: |- + if (millis() > 10000) { + return 42.0; + } else { + return 0.0; + } + update_interval: 60s + +climate: + - platform: pid + id: pid_climate + name: PID Climate Controller + sensor: template_sensor1 + humidity_sensor: template_sensor1 + default_target_temperature: 21°C + heat_output: pid_slow_pwm + control_parameters: + kp: 0.0 + ki: 0.0 + kd: 0.0 + max_integral: 0.0 + output_averaging_samples: 1 + derivative_averaging_samples: 1 + deadband_parameters: + threshold_high: 0.4 + threshold_low: -2.0 + kp_multiplier: 0.0 + ki_multiplier: 0.0 + kd_multiplier: 0.0 + deadband_output_averaging_samples: 1 diff --git a/tests/components/pid/test.esp8266.yaml b/tests/components/pid/test.esp8266.yaml new file mode 100644 index 0000000000..5f7762872f --- /dev/null +++ b/tests/components/pid/test.esp8266.yaml @@ -0,0 +1,56 @@ +esphome: + on_boot: + then: + - climate.pid.autotune: pid_climate + - climate.pid.autotune: + id: pid_climate + noiseband: 0.25 + positive_output: 25% + negative_output: -25% + - climate.pid.set_control_parameters: + id: pid_climate + kp: 0.0 + ki: 0.0 + kd: 0.0 + - climate.pid.reset_integral_term: pid_climate + +output: + - platform: slow_pwm + pin: 4 + id: pid_slow_pwm + period: 15s + restart_cycle_on_state_change: false + +sensor: + - platform: template + id: template_sensor1 + lambda: |- + if (millis() > 10000) { + return 42.0; + } else { + return 0.0; + } + update_interval: 60s + +climate: + - platform: pid + id: pid_climate + name: PID Climate Controller + sensor: template_sensor1 + humidity_sensor: template_sensor1 + default_target_temperature: 21°C + heat_output: pid_slow_pwm + control_parameters: + kp: 0.0 + ki: 0.0 + kd: 0.0 + max_integral: 0.0 + output_averaging_samples: 1 + derivative_averaging_samples: 1 + deadband_parameters: + threshold_high: 0.4 + threshold_low: -2.0 + kp_multiplier: 0.0 + ki_multiplier: 0.0 + kd_multiplier: 0.0 + deadband_output_averaging_samples: 1 diff --git a/tests/components/pid/test.rp2040.yaml b/tests/components/pid/test.rp2040.yaml new file mode 100644 index 0000000000..5f7762872f --- /dev/null +++ b/tests/components/pid/test.rp2040.yaml @@ -0,0 +1,56 @@ +esphome: + on_boot: + then: + - climate.pid.autotune: pid_climate + - climate.pid.autotune: + id: pid_climate + noiseband: 0.25 + positive_output: 25% + negative_output: -25% + - climate.pid.set_control_parameters: + id: pid_climate + kp: 0.0 + ki: 0.0 + kd: 0.0 + - climate.pid.reset_integral_term: pid_climate + +output: + - platform: slow_pwm + pin: 4 + id: pid_slow_pwm + period: 15s + restart_cycle_on_state_change: false + +sensor: + - platform: template + id: template_sensor1 + lambda: |- + if (millis() > 10000) { + return 42.0; + } else { + return 0.0; + } + update_interval: 60s + +climate: + - platform: pid + id: pid_climate + name: PID Climate Controller + sensor: template_sensor1 + humidity_sensor: template_sensor1 + default_target_temperature: 21°C + heat_output: pid_slow_pwm + control_parameters: + kp: 0.0 + ki: 0.0 + kd: 0.0 + max_integral: 0.0 + output_averaging_samples: 1 + derivative_averaging_samples: 1 + deadband_parameters: + threshold_high: 0.4 + threshold_low: -2.0 + kp_multiplier: 0.0 + ki_multiplier: 0.0 + kd_multiplier: 0.0 + deadband_output_averaging_samples: 1 diff --git a/tests/components/pipsolar/test.esp32-c3-idf.yaml b/tests/components/pipsolar/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..12e9266343 --- /dev/null +++ b/tests/components/pipsolar/test.esp32-c3-idf.yaml @@ -0,0 +1,247 @@ +esphome: + on_boot: + then: + - output.pipsolar.set_level: + id: inverter0_battery_recharge_voltage_out + value: 48.0 + +uart: + - id: uart_pipsolar + tx_pin: 4 + rx_pin: 5 + baud_rate: 115200 + +pipsolar: + id: inverter0 + +binary_sensor: + - platform: pipsolar + pipsolar_id: inverter0 + add_sbu_priority_version: + id: inverter0_add_sbu_priority_version + name: inverter0_add_sbu_priority_version + configuration_status: + id: inverter0_configuration_status + name: inverter0_configuration_status + scc_firmware_version: + id: inverter0_scc_firmware_version + name: inverter0_scc_firmware_version + load_status: + id: inverter0_load_status + name: inverter0_load_status + battery_voltage_to_steady_while_charging: + id: inverter0_battery_voltage_to_steady_while_charging + name: inverter0_battery_voltage_to_steady_while_charging + charging_status: + id: inverter0_charging_status + name: inverter0_charging_status + scc_charging_status: + id: inverter0_scc_charging_status + name: inverter0_scc_charging_status + ac_charging_status: + id: inverter0_ac_charging_status + name: inverter0_ac_charging_status + charging_to_floating_mode: + id: inverter0_charging_to_floating_mode + name: inverter0_charging_to_floating_mode + switch_on: + id: inverter0_switch_on + name: inverter0_switch_on + dustproof_installed: + id: inverter0_dustproof_installed + name: inverter0_dustproof_installed + silence_buzzer_open_buzzer: + id: inverter0_silence_buzzer_open_buzzer + name: inverter0_silence_buzzer_open_buzzer + overload_bypass_function: + id: inverter0_overload_bypass_function + name: inverter0_overload_bypass_function + lcd_escape_to_default: + id: inverter0_lcd_escape_to_default + name: inverter0_lcd_escape_to_default + overload_restart_function: + id: inverter0_overload_restart_function + name: inverter0_overload_restart_function + over_temperature_restart_function: + id: inverter0_over_temperature_restart_function + name: inverter0_over_temperature_restart_function + backlight_on: + id: inverter0_backlight_on + name: inverter0_backlight_on + +output: + - platform: pipsolar + pipsolar_id: inverter0 + battery_recharge_voltage: + id: inverter0_battery_recharge_voltage_out + +sensor: + - platform: pipsolar + pipsolar_id: inverter0 + grid_rating_voltage: + id: inverter0_grid_rating_voltage + name: inverter0_grid_rating_voltage + grid_rating_current: + id: inverter0_grid_rating_current + name: inverter0_grid_rating_current + ac_output_rating_voltage: + id: inverter0_ac_output_rating_voltage + name: inverter0_ac_output_rating_voltage + ac_output_rating_frequency: + id: inverter0_ac_output_rating_frequency + name: inverter0_ac_output_rating_frequency + ac_output_rating_current: + id: inverter0_ac_output_rating_current + name: inverter0_ac_output_rating_current + ac_output_rating_apparent_power: + id: inverter0_ac_output_rating_apparent_power + name: inverter0_ac_output_rating_apparent_power + ac_output_rating_active_power: + id: inverter0_ac_output_rating_active_power + name: inverter0_ac_output_rating_active_power + battery_rating_voltage: + id: inverter0_battery_rating_voltage + name: inverter0_battery_rating_voltage + battery_recharge_voltage: + id: inverter0_battery_recharge_voltage + name: inverter0_battery_recharge_voltage + battery_under_voltage: + id: inverter0_battery_under_voltage + name: inverter0_battery_under_voltage + battery_bulk_voltage: + id: inverter0_battery_bulk_voltage + name: inverter0_battery_bulk_voltage + battery_float_voltage: + id: inverter0_battery_float_voltage + name: inverter0_battery_float_voltage + battery_type: + id: inverter0_battery_type + name: inverter0_battery_type + current_max_ac_charging_current: + id: inverter0_current_max_ac_charging_current + name: inverter0_current_max_ac_charging_current + current_max_charging_current: + id: inverter0_current_max_charging_current + name: inverter0_current_max_charging_current + input_voltage_range: + id: inverter0_input_voltage_range + name: inverter0_input_voltage_range + output_source_priority: + id: inverter0_output_source_priority + name: inverter0_output_source_priority + charger_source_priority: + id: inverter0_charger_source_priority + name: inverter0_charger_source_priority + parallel_max_num: + id: inverter0_parallel_max_num + name: inverter0_parallel_max_num + machine_type: + id: inverter0_machine_type + name: inverter0_machine_type + topology: + id: inverter0_topology + name: inverter0_topology + output_mode: + id: inverter0_output_mode + name: inverter0_output_mode + battery_redischarge_voltage: + id: inverter0_battery_redischarge_voltage + name: inverter0_battery_redischarge_voltage + pv_ok_condition_for_parallel: + id: inverter0_pv_ok_condition_for_parallel + name: inverter0_pv_ok_condition_for_parallel + pv_power_balance: + id: inverter0_pv_power_balance + name: inverter0_pv_power_balance + grid_voltage: + id: inverter0_grid_voltage + name: inverter0_grid_voltage + grid_frequency: + id: inverter0_grid_frequency + name: inverter0_grid_frequency + ac_output_voltage: + id: inverter0_ac_output_voltage + name: inverter0_ac_output_voltage + ac_output_frequency: + id: inverter0_ac_output_frequency + name: inverter0_ac_output_frequency + ac_output_apparent_power: + id: inverter0_ac_output_apparent_power + name: inverter0_ac_output_apparent_power + ac_output_active_power: + id: inverter0_ac_output_active_power + name: inverter0_ac_output_active_power + output_load_percent: + id: inverter0_output_load_percent + name: inverter0_output_load_percent + bus_voltage: + id: inverter0_bus_voltage + name: inverter0_bus_voltage + battery_voltage: + id: inverter0_battery_voltage + name: inverter0_battery_voltage + battery_charging_current: + id: inverter0_battery_charging_current + name: inverter0_battery_charging_current + battery_capacity_percent: + id: inverter0_battery_capacity_percent + name: inverter0_battery_capacity_percent + inverter_heat_sink_temperature: + id: inverter0_inverter_heat_sink_temperature + name: inverter0_inverter_heat_sink_temperature + pv_input_current_for_battery: + id: inverter0_pv_input_current_for_battery + name: inverter0_pv_input_current_for_battery + pv_input_voltage: + id: inverter0_pv_input_voltage + name: inverter0_pv_input_voltage + battery_voltage_scc: + id: inverter0_battery_voltage_scc + name: inverter0_battery_voltage_scc + battery_discharge_current: + id: inverter0_battery_discharge_current + name: inverter0_battery_discharge_current + battery_voltage_offset_for_fans_on: + id: inverter0_battery_voltage_offset_for_fans_on + name: inverter0_battery_voltage_offset_for_fans_on + eeprom_version: + id: inverter0_eeprom_version + name: inverter0_eeprom_version + pv_charging_power: + id: inverter0_pv_charging_power + name: inverter0_pv_charging_power + +switch: + - platform: pipsolar + pipsolar_id: inverter0 + output_source_priority_utility: + name: inverter0_output_source_priority_utility + output_source_priority_solar: + name: inverter0_output_source_priority_solar + output_source_priority_battery: + name: inverter0_output_source_priority_battery + input_voltage_range: + name: inverter0_input_voltage_range + pv_ok_condition_for_parallel: + name: inverter0_pv_ok_condition_for_parallel + pv_power_balance: + name: inverter0_pv_power_balance + +text_sensor: + - platform: pipsolar + pipsolar_id: inverter0 + device_mode: + id: inverter0_device_mode + name: inverter0_device_mode + last_qpigs: + id: inverter0_last_qpigs + name: inverter0_last_qpigs + last_qpiri: + id: inverter0_last_qpiri + name: inverter0_last_qpiri + last_qmod: + id: inverter0_last_qmod + name: inverter0_last_qmod + last_qflag: + id: inverter0_last_qflag + name: inverter0_last_qflag diff --git a/tests/components/pipsolar/test.esp32-c3.yaml b/tests/components/pipsolar/test.esp32-c3.yaml new file mode 100644 index 0000000000..12e9266343 --- /dev/null +++ b/tests/components/pipsolar/test.esp32-c3.yaml @@ -0,0 +1,247 @@ +esphome: + on_boot: + then: + - output.pipsolar.set_level: + id: inverter0_battery_recharge_voltage_out + value: 48.0 + +uart: + - id: uart_pipsolar + tx_pin: 4 + rx_pin: 5 + baud_rate: 115200 + +pipsolar: + id: inverter0 + +binary_sensor: + - platform: pipsolar + pipsolar_id: inverter0 + add_sbu_priority_version: + id: inverter0_add_sbu_priority_version + name: inverter0_add_sbu_priority_version + configuration_status: + id: inverter0_configuration_status + name: inverter0_configuration_status + scc_firmware_version: + id: inverter0_scc_firmware_version + name: inverter0_scc_firmware_version + load_status: + id: inverter0_load_status + name: inverter0_load_status + battery_voltage_to_steady_while_charging: + id: inverter0_battery_voltage_to_steady_while_charging + name: inverter0_battery_voltage_to_steady_while_charging + charging_status: + id: inverter0_charging_status + name: inverter0_charging_status + scc_charging_status: + id: inverter0_scc_charging_status + name: inverter0_scc_charging_status + ac_charging_status: + id: inverter0_ac_charging_status + name: inverter0_ac_charging_status + charging_to_floating_mode: + id: inverter0_charging_to_floating_mode + name: inverter0_charging_to_floating_mode + switch_on: + id: inverter0_switch_on + name: inverter0_switch_on + dustproof_installed: + id: inverter0_dustproof_installed + name: inverter0_dustproof_installed + silence_buzzer_open_buzzer: + id: inverter0_silence_buzzer_open_buzzer + name: inverter0_silence_buzzer_open_buzzer + overload_bypass_function: + id: inverter0_overload_bypass_function + name: inverter0_overload_bypass_function + lcd_escape_to_default: + id: inverter0_lcd_escape_to_default + name: inverter0_lcd_escape_to_default + overload_restart_function: + id: inverter0_overload_restart_function + name: inverter0_overload_restart_function + over_temperature_restart_function: + id: inverter0_over_temperature_restart_function + name: inverter0_over_temperature_restart_function + backlight_on: + id: inverter0_backlight_on + name: inverter0_backlight_on + +output: + - platform: pipsolar + pipsolar_id: inverter0 + battery_recharge_voltage: + id: inverter0_battery_recharge_voltage_out + +sensor: + - platform: pipsolar + pipsolar_id: inverter0 + grid_rating_voltage: + id: inverter0_grid_rating_voltage + name: inverter0_grid_rating_voltage + grid_rating_current: + id: inverter0_grid_rating_current + name: inverter0_grid_rating_current + ac_output_rating_voltage: + id: inverter0_ac_output_rating_voltage + name: inverter0_ac_output_rating_voltage + ac_output_rating_frequency: + id: inverter0_ac_output_rating_frequency + name: inverter0_ac_output_rating_frequency + ac_output_rating_current: + id: inverter0_ac_output_rating_current + name: inverter0_ac_output_rating_current + ac_output_rating_apparent_power: + id: inverter0_ac_output_rating_apparent_power + name: inverter0_ac_output_rating_apparent_power + ac_output_rating_active_power: + id: inverter0_ac_output_rating_active_power + name: inverter0_ac_output_rating_active_power + battery_rating_voltage: + id: inverter0_battery_rating_voltage + name: inverter0_battery_rating_voltage + battery_recharge_voltage: + id: inverter0_battery_recharge_voltage + name: inverter0_battery_recharge_voltage + battery_under_voltage: + id: inverter0_battery_under_voltage + name: inverter0_battery_under_voltage + battery_bulk_voltage: + id: inverter0_battery_bulk_voltage + name: inverter0_battery_bulk_voltage + battery_float_voltage: + id: inverter0_battery_float_voltage + name: inverter0_battery_float_voltage + battery_type: + id: inverter0_battery_type + name: inverter0_battery_type + current_max_ac_charging_current: + id: inverter0_current_max_ac_charging_current + name: inverter0_current_max_ac_charging_current + current_max_charging_current: + id: inverter0_current_max_charging_current + name: inverter0_current_max_charging_current + input_voltage_range: + id: inverter0_input_voltage_range + name: inverter0_input_voltage_range + output_source_priority: + id: inverter0_output_source_priority + name: inverter0_output_source_priority + charger_source_priority: + id: inverter0_charger_source_priority + name: inverter0_charger_source_priority + parallel_max_num: + id: inverter0_parallel_max_num + name: inverter0_parallel_max_num + machine_type: + id: inverter0_machine_type + name: inverter0_machine_type + topology: + id: inverter0_topology + name: inverter0_topology + output_mode: + id: inverter0_output_mode + name: inverter0_output_mode + battery_redischarge_voltage: + id: inverter0_battery_redischarge_voltage + name: inverter0_battery_redischarge_voltage + pv_ok_condition_for_parallel: + id: inverter0_pv_ok_condition_for_parallel + name: inverter0_pv_ok_condition_for_parallel + pv_power_balance: + id: inverter0_pv_power_balance + name: inverter0_pv_power_balance + grid_voltage: + id: inverter0_grid_voltage + name: inverter0_grid_voltage + grid_frequency: + id: inverter0_grid_frequency + name: inverter0_grid_frequency + ac_output_voltage: + id: inverter0_ac_output_voltage + name: inverter0_ac_output_voltage + ac_output_frequency: + id: inverter0_ac_output_frequency + name: inverter0_ac_output_frequency + ac_output_apparent_power: + id: inverter0_ac_output_apparent_power + name: inverter0_ac_output_apparent_power + ac_output_active_power: + id: inverter0_ac_output_active_power + name: inverter0_ac_output_active_power + output_load_percent: + id: inverter0_output_load_percent + name: inverter0_output_load_percent + bus_voltage: + id: inverter0_bus_voltage + name: inverter0_bus_voltage + battery_voltage: + id: inverter0_battery_voltage + name: inverter0_battery_voltage + battery_charging_current: + id: inverter0_battery_charging_current + name: inverter0_battery_charging_current + battery_capacity_percent: + id: inverter0_battery_capacity_percent + name: inverter0_battery_capacity_percent + inverter_heat_sink_temperature: + id: inverter0_inverter_heat_sink_temperature + name: inverter0_inverter_heat_sink_temperature + pv_input_current_for_battery: + id: inverter0_pv_input_current_for_battery + name: inverter0_pv_input_current_for_battery + pv_input_voltage: + id: inverter0_pv_input_voltage + name: inverter0_pv_input_voltage + battery_voltage_scc: + id: inverter0_battery_voltage_scc + name: inverter0_battery_voltage_scc + battery_discharge_current: + id: inverter0_battery_discharge_current + name: inverter0_battery_discharge_current + battery_voltage_offset_for_fans_on: + id: inverter0_battery_voltage_offset_for_fans_on + name: inverter0_battery_voltage_offset_for_fans_on + eeprom_version: + id: inverter0_eeprom_version + name: inverter0_eeprom_version + pv_charging_power: + id: inverter0_pv_charging_power + name: inverter0_pv_charging_power + +switch: + - platform: pipsolar + pipsolar_id: inverter0 + output_source_priority_utility: + name: inverter0_output_source_priority_utility + output_source_priority_solar: + name: inverter0_output_source_priority_solar + output_source_priority_battery: + name: inverter0_output_source_priority_battery + input_voltage_range: + name: inverter0_input_voltage_range + pv_ok_condition_for_parallel: + name: inverter0_pv_ok_condition_for_parallel + pv_power_balance: + name: inverter0_pv_power_balance + +text_sensor: + - platform: pipsolar + pipsolar_id: inverter0 + device_mode: + id: inverter0_device_mode + name: inverter0_device_mode + last_qpigs: + id: inverter0_last_qpigs + name: inverter0_last_qpigs + last_qpiri: + id: inverter0_last_qpiri + name: inverter0_last_qpiri + last_qmod: + id: inverter0_last_qmod + name: inverter0_last_qmod + last_qflag: + id: inverter0_last_qflag + name: inverter0_last_qflag diff --git a/tests/components/pipsolar/test.esp32-idf.yaml b/tests/components/pipsolar/test.esp32-idf.yaml new file mode 100644 index 0000000000..fcd4575739 --- /dev/null +++ b/tests/components/pipsolar/test.esp32-idf.yaml @@ -0,0 +1,247 @@ +esphome: + on_boot: + then: + - output.pipsolar.set_level: + id: inverter0_battery_recharge_voltage_out + value: 48.0 + +uart: + - id: uart_pipsolar + tx_pin: 17 + rx_pin: 16 + baud_rate: 115200 + +pipsolar: + id: inverter0 + +binary_sensor: + - platform: pipsolar + pipsolar_id: inverter0 + add_sbu_priority_version: + id: inverter0_add_sbu_priority_version + name: inverter0_add_sbu_priority_version + configuration_status: + id: inverter0_configuration_status + name: inverter0_configuration_status + scc_firmware_version: + id: inverter0_scc_firmware_version + name: inverter0_scc_firmware_version + load_status: + id: inverter0_load_status + name: inverter0_load_status + battery_voltage_to_steady_while_charging: + id: inverter0_battery_voltage_to_steady_while_charging + name: inverter0_battery_voltage_to_steady_while_charging + charging_status: + id: inverter0_charging_status + name: inverter0_charging_status + scc_charging_status: + id: inverter0_scc_charging_status + name: inverter0_scc_charging_status + ac_charging_status: + id: inverter0_ac_charging_status + name: inverter0_ac_charging_status + charging_to_floating_mode: + id: inverter0_charging_to_floating_mode + name: inverter0_charging_to_floating_mode + switch_on: + id: inverter0_switch_on + name: inverter0_switch_on + dustproof_installed: + id: inverter0_dustproof_installed + name: inverter0_dustproof_installed + silence_buzzer_open_buzzer: + id: inverter0_silence_buzzer_open_buzzer + name: inverter0_silence_buzzer_open_buzzer + overload_bypass_function: + id: inverter0_overload_bypass_function + name: inverter0_overload_bypass_function + lcd_escape_to_default: + id: inverter0_lcd_escape_to_default + name: inverter0_lcd_escape_to_default + overload_restart_function: + id: inverter0_overload_restart_function + name: inverter0_overload_restart_function + over_temperature_restart_function: + id: inverter0_over_temperature_restart_function + name: inverter0_over_temperature_restart_function + backlight_on: + id: inverter0_backlight_on + name: inverter0_backlight_on + +output: + - platform: pipsolar + pipsolar_id: inverter0 + battery_recharge_voltage: + id: inverter0_battery_recharge_voltage_out + +sensor: + - platform: pipsolar + pipsolar_id: inverter0 + grid_rating_voltage: + id: inverter0_grid_rating_voltage + name: inverter0_grid_rating_voltage + grid_rating_current: + id: inverter0_grid_rating_current + name: inverter0_grid_rating_current + ac_output_rating_voltage: + id: inverter0_ac_output_rating_voltage + name: inverter0_ac_output_rating_voltage + ac_output_rating_frequency: + id: inverter0_ac_output_rating_frequency + name: inverter0_ac_output_rating_frequency + ac_output_rating_current: + id: inverter0_ac_output_rating_current + name: inverter0_ac_output_rating_current + ac_output_rating_apparent_power: + id: inverter0_ac_output_rating_apparent_power + name: inverter0_ac_output_rating_apparent_power + ac_output_rating_active_power: + id: inverter0_ac_output_rating_active_power + name: inverter0_ac_output_rating_active_power + battery_rating_voltage: + id: inverter0_battery_rating_voltage + name: inverter0_battery_rating_voltage + battery_recharge_voltage: + id: inverter0_battery_recharge_voltage + name: inverter0_battery_recharge_voltage + battery_under_voltage: + id: inverter0_battery_under_voltage + name: inverter0_battery_under_voltage + battery_bulk_voltage: + id: inverter0_battery_bulk_voltage + name: inverter0_battery_bulk_voltage + battery_float_voltage: + id: inverter0_battery_float_voltage + name: inverter0_battery_float_voltage + battery_type: + id: inverter0_battery_type + name: inverter0_battery_type + current_max_ac_charging_current: + id: inverter0_current_max_ac_charging_current + name: inverter0_current_max_ac_charging_current + current_max_charging_current: + id: inverter0_current_max_charging_current + name: inverter0_current_max_charging_current + input_voltage_range: + id: inverter0_input_voltage_range + name: inverter0_input_voltage_range + output_source_priority: + id: inverter0_output_source_priority + name: inverter0_output_source_priority + charger_source_priority: + id: inverter0_charger_source_priority + name: inverter0_charger_source_priority + parallel_max_num: + id: inverter0_parallel_max_num + name: inverter0_parallel_max_num + machine_type: + id: inverter0_machine_type + name: inverter0_machine_type + topology: + id: inverter0_topology + name: inverter0_topology + output_mode: + id: inverter0_output_mode + name: inverter0_output_mode + battery_redischarge_voltage: + id: inverter0_battery_redischarge_voltage + name: inverter0_battery_redischarge_voltage + pv_ok_condition_for_parallel: + id: inverter0_pv_ok_condition_for_parallel + name: inverter0_pv_ok_condition_for_parallel + pv_power_balance: + id: inverter0_pv_power_balance + name: inverter0_pv_power_balance + grid_voltage: + id: inverter0_grid_voltage + name: inverter0_grid_voltage + grid_frequency: + id: inverter0_grid_frequency + name: inverter0_grid_frequency + ac_output_voltage: + id: inverter0_ac_output_voltage + name: inverter0_ac_output_voltage + ac_output_frequency: + id: inverter0_ac_output_frequency + name: inverter0_ac_output_frequency + ac_output_apparent_power: + id: inverter0_ac_output_apparent_power + name: inverter0_ac_output_apparent_power + ac_output_active_power: + id: inverter0_ac_output_active_power + name: inverter0_ac_output_active_power + output_load_percent: + id: inverter0_output_load_percent + name: inverter0_output_load_percent + bus_voltage: + id: inverter0_bus_voltage + name: inverter0_bus_voltage + battery_voltage: + id: inverter0_battery_voltage + name: inverter0_battery_voltage + battery_charging_current: + id: inverter0_battery_charging_current + name: inverter0_battery_charging_current + battery_capacity_percent: + id: inverter0_battery_capacity_percent + name: inverter0_battery_capacity_percent + inverter_heat_sink_temperature: + id: inverter0_inverter_heat_sink_temperature + name: inverter0_inverter_heat_sink_temperature + pv_input_current_for_battery: + id: inverter0_pv_input_current_for_battery + name: inverter0_pv_input_current_for_battery + pv_input_voltage: + id: inverter0_pv_input_voltage + name: inverter0_pv_input_voltage + battery_voltage_scc: + id: inverter0_battery_voltage_scc + name: inverter0_battery_voltage_scc + battery_discharge_current: + id: inverter0_battery_discharge_current + name: inverter0_battery_discharge_current + battery_voltage_offset_for_fans_on: + id: inverter0_battery_voltage_offset_for_fans_on + name: inverter0_battery_voltage_offset_for_fans_on + eeprom_version: + id: inverter0_eeprom_version + name: inverter0_eeprom_version + pv_charging_power: + id: inverter0_pv_charging_power + name: inverter0_pv_charging_power + +switch: + - platform: pipsolar + pipsolar_id: inverter0 + output_source_priority_utility: + name: inverter0_output_source_priority_utility + output_source_priority_solar: + name: inverter0_output_source_priority_solar + output_source_priority_battery: + name: inverter0_output_source_priority_battery + input_voltage_range: + name: inverter0_input_voltage_range + pv_ok_condition_for_parallel: + name: inverter0_pv_ok_condition_for_parallel + pv_power_balance: + name: inverter0_pv_power_balance + +text_sensor: + - platform: pipsolar + pipsolar_id: inverter0 + device_mode: + id: inverter0_device_mode + name: inverter0_device_mode + last_qpigs: + id: inverter0_last_qpigs + name: inverter0_last_qpigs + last_qpiri: + id: inverter0_last_qpiri + name: inverter0_last_qpiri + last_qmod: + id: inverter0_last_qmod + name: inverter0_last_qmod + last_qflag: + id: inverter0_last_qflag + name: inverter0_last_qflag diff --git a/tests/components/pipsolar/test.esp32.yaml b/tests/components/pipsolar/test.esp32.yaml new file mode 100644 index 0000000000..fcd4575739 --- /dev/null +++ b/tests/components/pipsolar/test.esp32.yaml @@ -0,0 +1,247 @@ +esphome: + on_boot: + then: + - output.pipsolar.set_level: + id: inverter0_battery_recharge_voltage_out + value: 48.0 + +uart: + - id: uart_pipsolar + tx_pin: 17 + rx_pin: 16 + baud_rate: 115200 + +pipsolar: + id: inverter0 + +binary_sensor: + - platform: pipsolar + pipsolar_id: inverter0 + add_sbu_priority_version: + id: inverter0_add_sbu_priority_version + name: inverter0_add_sbu_priority_version + configuration_status: + id: inverter0_configuration_status + name: inverter0_configuration_status + scc_firmware_version: + id: inverter0_scc_firmware_version + name: inverter0_scc_firmware_version + load_status: + id: inverter0_load_status + name: inverter0_load_status + battery_voltage_to_steady_while_charging: + id: inverter0_battery_voltage_to_steady_while_charging + name: inverter0_battery_voltage_to_steady_while_charging + charging_status: + id: inverter0_charging_status + name: inverter0_charging_status + scc_charging_status: + id: inverter0_scc_charging_status + name: inverter0_scc_charging_status + ac_charging_status: + id: inverter0_ac_charging_status + name: inverter0_ac_charging_status + charging_to_floating_mode: + id: inverter0_charging_to_floating_mode + name: inverter0_charging_to_floating_mode + switch_on: + id: inverter0_switch_on + name: inverter0_switch_on + dustproof_installed: + id: inverter0_dustproof_installed + name: inverter0_dustproof_installed + silence_buzzer_open_buzzer: + id: inverter0_silence_buzzer_open_buzzer + name: inverter0_silence_buzzer_open_buzzer + overload_bypass_function: + id: inverter0_overload_bypass_function + name: inverter0_overload_bypass_function + lcd_escape_to_default: + id: inverter0_lcd_escape_to_default + name: inverter0_lcd_escape_to_default + overload_restart_function: + id: inverter0_overload_restart_function + name: inverter0_overload_restart_function + over_temperature_restart_function: + id: inverter0_over_temperature_restart_function + name: inverter0_over_temperature_restart_function + backlight_on: + id: inverter0_backlight_on + name: inverter0_backlight_on + +output: + - platform: pipsolar + pipsolar_id: inverter0 + battery_recharge_voltage: + id: inverter0_battery_recharge_voltage_out + +sensor: + - platform: pipsolar + pipsolar_id: inverter0 + grid_rating_voltage: + id: inverter0_grid_rating_voltage + name: inverter0_grid_rating_voltage + grid_rating_current: + id: inverter0_grid_rating_current + name: inverter0_grid_rating_current + ac_output_rating_voltage: + id: inverter0_ac_output_rating_voltage + name: inverter0_ac_output_rating_voltage + ac_output_rating_frequency: + id: inverter0_ac_output_rating_frequency + name: inverter0_ac_output_rating_frequency + ac_output_rating_current: + id: inverter0_ac_output_rating_current + name: inverter0_ac_output_rating_current + ac_output_rating_apparent_power: + id: inverter0_ac_output_rating_apparent_power + name: inverter0_ac_output_rating_apparent_power + ac_output_rating_active_power: + id: inverter0_ac_output_rating_active_power + name: inverter0_ac_output_rating_active_power + battery_rating_voltage: + id: inverter0_battery_rating_voltage + name: inverter0_battery_rating_voltage + battery_recharge_voltage: + id: inverter0_battery_recharge_voltage + name: inverter0_battery_recharge_voltage + battery_under_voltage: + id: inverter0_battery_under_voltage + name: inverter0_battery_under_voltage + battery_bulk_voltage: + id: inverter0_battery_bulk_voltage + name: inverter0_battery_bulk_voltage + battery_float_voltage: + id: inverter0_battery_float_voltage + name: inverter0_battery_float_voltage + battery_type: + id: inverter0_battery_type + name: inverter0_battery_type + current_max_ac_charging_current: + id: inverter0_current_max_ac_charging_current + name: inverter0_current_max_ac_charging_current + current_max_charging_current: + id: inverter0_current_max_charging_current + name: inverter0_current_max_charging_current + input_voltage_range: + id: inverter0_input_voltage_range + name: inverter0_input_voltage_range + output_source_priority: + id: inverter0_output_source_priority + name: inverter0_output_source_priority + charger_source_priority: + id: inverter0_charger_source_priority + name: inverter0_charger_source_priority + parallel_max_num: + id: inverter0_parallel_max_num + name: inverter0_parallel_max_num + machine_type: + id: inverter0_machine_type + name: inverter0_machine_type + topology: + id: inverter0_topology + name: inverter0_topology + output_mode: + id: inverter0_output_mode + name: inverter0_output_mode + battery_redischarge_voltage: + id: inverter0_battery_redischarge_voltage + name: inverter0_battery_redischarge_voltage + pv_ok_condition_for_parallel: + id: inverter0_pv_ok_condition_for_parallel + name: inverter0_pv_ok_condition_for_parallel + pv_power_balance: + id: inverter0_pv_power_balance + name: inverter0_pv_power_balance + grid_voltage: + id: inverter0_grid_voltage + name: inverter0_grid_voltage + grid_frequency: + id: inverter0_grid_frequency + name: inverter0_grid_frequency + ac_output_voltage: + id: inverter0_ac_output_voltage + name: inverter0_ac_output_voltage + ac_output_frequency: + id: inverter0_ac_output_frequency + name: inverter0_ac_output_frequency + ac_output_apparent_power: + id: inverter0_ac_output_apparent_power + name: inverter0_ac_output_apparent_power + ac_output_active_power: + id: inverter0_ac_output_active_power + name: inverter0_ac_output_active_power + output_load_percent: + id: inverter0_output_load_percent + name: inverter0_output_load_percent + bus_voltage: + id: inverter0_bus_voltage + name: inverter0_bus_voltage + battery_voltage: + id: inverter0_battery_voltage + name: inverter0_battery_voltage + battery_charging_current: + id: inverter0_battery_charging_current + name: inverter0_battery_charging_current + battery_capacity_percent: + id: inverter0_battery_capacity_percent + name: inverter0_battery_capacity_percent + inverter_heat_sink_temperature: + id: inverter0_inverter_heat_sink_temperature + name: inverter0_inverter_heat_sink_temperature + pv_input_current_for_battery: + id: inverter0_pv_input_current_for_battery + name: inverter0_pv_input_current_for_battery + pv_input_voltage: + id: inverter0_pv_input_voltage + name: inverter0_pv_input_voltage + battery_voltage_scc: + id: inverter0_battery_voltage_scc + name: inverter0_battery_voltage_scc + battery_discharge_current: + id: inverter0_battery_discharge_current + name: inverter0_battery_discharge_current + battery_voltage_offset_for_fans_on: + id: inverter0_battery_voltage_offset_for_fans_on + name: inverter0_battery_voltage_offset_for_fans_on + eeprom_version: + id: inverter0_eeprom_version + name: inverter0_eeprom_version + pv_charging_power: + id: inverter0_pv_charging_power + name: inverter0_pv_charging_power + +switch: + - platform: pipsolar + pipsolar_id: inverter0 + output_source_priority_utility: + name: inverter0_output_source_priority_utility + output_source_priority_solar: + name: inverter0_output_source_priority_solar + output_source_priority_battery: + name: inverter0_output_source_priority_battery + input_voltage_range: + name: inverter0_input_voltage_range + pv_ok_condition_for_parallel: + name: inverter0_pv_ok_condition_for_parallel + pv_power_balance: + name: inverter0_pv_power_balance + +text_sensor: + - platform: pipsolar + pipsolar_id: inverter0 + device_mode: + id: inverter0_device_mode + name: inverter0_device_mode + last_qpigs: + id: inverter0_last_qpigs + name: inverter0_last_qpigs + last_qpiri: + id: inverter0_last_qpiri + name: inverter0_last_qpiri + last_qmod: + id: inverter0_last_qmod + name: inverter0_last_qmod + last_qflag: + id: inverter0_last_qflag + name: inverter0_last_qflag diff --git a/tests/components/pipsolar/test.esp8266.yaml b/tests/components/pipsolar/test.esp8266.yaml new file mode 100644 index 0000000000..12e9266343 --- /dev/null +++ b/tests/components/pipsolar/test.esp8266.yaml @@ -0,0 +1,247 @@ +esphome: + on_boot: + then: + - output.pipsolar.set_level: + id: inverter0_battery_recharge_voltage_out + value: 48.0 + +uart: + - id: uart_pipsolar + tx_pin: 4 + rx_pin: 5 + baud_rate: 115200 + +pipsolar: + id: inverter0 + +binary_sensor: + - platform: pipsolar + pipsolar_id: inverter0 + add_sbu_priority_version: + id: inverter0_add_sbu_priority_version + name: inverter0_add_sbu_priority_version + configuration_status: + id: inverter0_configuration_status + name: inverter0_configuration_status + scc_firmware_version: + id: inverter0_scc_firmware_version + name: inverter0_scc_firmware_version + load_status: + id: inverter0_load_status + name: inverter0_load_status + battery_voltage_to_steady_while_charging: + id: inverter0_battery_voltage_to_steady_while_charging + name: inverter0_battery_voltage_to_steady_while_charging + charging_status: + id: inverter0_charging_status + name: inverter0_charging_status + scc_charging_status: + id: inverter0_scc_charging_status + name: inverter0_scc_charging_status + ac_charging_status: + id: inverter0_ac_charging_status + name: inverter0_ac_charging_status + charging_to_floating_mode: + id: inverter0_charging_to_floating_mode + name: inverter0_charging_to_floating_mode + switch_on: + id: inverter0_switch_on + name: inverter0_switch_on + dustproof_installed: + id: inverter0_dustproof_installed + name: inverter0_dustproof_installed + silence_buzzer_open_buzzer: + id: inverter0_silence_buzzer_open_buzzer + name: inverter0_silence_buzzer_open_buzzer + overload_bypass_function: + id: inverter0_overload_bypass_function + name: inverter0_overload_bypass_function + lcd_escape_to_default: + id: inverter0_lcd_escape_to_default + name: inverter0_lcd_escape_to_default + overload_restart_function: + id: inverter0_overload_restart_function + name: inverter0_overload_restart_function + over_temperature_restart_function: + id: inverter0_over_temperature_restart_function + name: inverter0_over_temperature_restart_function + backlight_on: + id: inverter0_backlight_on + name: inverter0_backlight_on + +output: + - platform: pipsolar + pipsolar_id: inverter0 + battery_recharge_voltage: + id: inverter0_battery_recharge_voltage_out + +sensor: + - platform: pipsolar + pipsolar_id: inverter0 + grid_rating_voltage: + id: inverter0_grid_rating_voltage + name: inverter0_grid_rating_voltage + grid_rating_current: + id: inverter0_grid_rating_current + name: inverter0_grid_rating_current + ac_output_rating_voltage: + id: inverter0_ac_output_rating_voltage + name: inverter0_ac_output_rating_voltage + ac_output_rating_frequency: + id: inverter0_ac_output_rating_frequency + name: inverter0_ac_output_rating_frequency + ac_output_rating_current: + id: inverter0_ac_output_rating_current + name: inverter0_ac_output_rating_current + ac_output_rating_apparent_power: + id: inverter0_ac_output_rating_apparent_power + name: inverter0_ac_output_rating_apparent_power + ac_output_rating_active_power: + id: inverter0_ac_output_rating_active_power + name: inverter0_ac_output_rating_active_power + battery_rating_voltage: + id: inverter0_battery_rating_voltage + name: inverter0_battery_rating_voltage + battery_recharge_voltage: + id: inverter0_battery_recharge_voltage + name: inverter0_battery_recharge_voltage + battery_under_voltage: + id: inverter0_battery_under_voltage + name: inverter0_battery_under_voltage + battery_bulk_voltage: + id: inverter0_battery_bulk_voltage + name: inverter0_battery_bulk_voltage + battery_float_voltage: + id: inverter0_battery_float_voltage + name: inverter0_battery_float_voltage + battery_type: + id: inverter0_battery_type + name: inverter0_battery_type + current_max_ac_charging_current: + id: inverter0_current_max_ac_charging_current + name: inverter0_current_max_ac_charging_current + current_max_charging_current: + id: inverter0_current_max_charging_current + name: inverter0_current_max_charging_current + input_voltage_range: + id: inverter0_input_voltage_range + name: inverter0_input_voltage_range + output_source_priority: + id: inverter0_output_source_priority + name: inverter0_output_source_priority + charger_source_priority: + id: inverter0_charger_source_priority + name: inverter0_charger_source_priority + parallel_max_num: + id: inverter0_parallel_max_num + name: inverter0_parallel_max_num + machine_type: + id: inverter0_machine_type + name: inverter0_machine_type + topology: + id: inverter0_topology + name: inverter0_topology + output_mode: + id: inverter0_output_mode + name: inverter0_output_mode + battery_redischarge_voltage: + id: inverter0_battery_redischarge_voltage + name: inverter0_battery_redischarge_voltage + pv_ok_condition_for_parallel: + id: inverter0_pv_ok_condition_for_parallel + name: inverter0_pv_ok_condition_for_parallel + pv_power_balance: + id: inverter0_pv_power_balance + name: inverter0_pv_power_balance + grid_voltage: + id: inverter0_grid_voltage + name: inverter0_grid_voltage + grid_frequency: + id: inverter0_grid_frequency + name: inverter0_grid_frequency + ac_output_voltage: + id: inverter0_ac_output_voltage + name: inverter0_ac_output_voltage + ac_output_frequency: + id: inverter0_ac_output_frequency + name: inverter0_ac_output_frequency + ac_output_apparent_power: + id: inverter0_ac_output_apparent_power + name: inverter0_ac_output_apparent_power + ac_output_active_power: + id: inverter0_ac_output_active_power + name: inverter0_ac_output_active_power + output_load_percent: + id: inverter0_output_load_percent + name: inverter0_output_load_percent + bus_voltage: + id: inverter0_bus_voltage + name: inverter0_bus_voltage + battery_voltage: + id: inverter0_battery_voltage + name: inverter0_battery_voltage + battery_charging_current: + id: inverter0_battery_charging_current + name: inverter0_battery_charging_current + battery_capacity_percent: + id: inverter0_battery_capacity_percent + name: inverter0_battery_capacity_percent + inverter_heat_sink_temperature: + id: inverter0_inverter_heat_sink_temperature + name: inverter0_inverter_heat_sink_temperature + pv_input_current_for_battery: + id: inverter0_pv_input_current_for_battery + name: inverter0_pv_input_current_for_battery + pv_input_voltage: + id: inverter0_pv_input_voltage + name: inverter0_pv_input_voltage + battery_voltage_scc: + id: inverter0_battery_voltage_scc + name: inverter0_battery_voltage_scc + battery_discharge_current: + id: inverter0_battery_discharge_current + name: inverter0_battery_discharge_current + battery_voltage_offset_for_fans_on: + id: inverter0_battery_voltage_offset_for_fans_on + name: inverter0_battery_voltage_offset_for_fans_on + eeprom_version: + id: inverter0_eeprom_version + name: inverter0_eeprom_version + pv_charging_power: + id: inverter0_pv_charging_power + name: inverter0_pv_charging_power + +switch: + - platform: pipsolar + pipsolar_id: inverter0 + output_source_priority_utility: + name: inverter0_output_source_priority_utility + output_source_priority_solar: + name: inverter0_output_source_priority_solar + output_source_priority_battery: + name: inverter0_output_source_priority_battery + input_voltage_range: + name: inverter0_input_voltage_range + pv_ok_condition_for_parallel: + name: inverter0_pv_ok_condition_for_parallel + pv_power_balance: + name: inverter0_pv_power_balance + +text_sensor: + - platform: pipsolar + pipsolar_id: inverter0 + device_mode: + id: inverter0_device_mode + name: inverter0_device_mode + last_qpigs: + id: inverter0_last_qpigs + name: inverter0_last_qpigs + last_qpiri: + id: inverter0_last_qpiri + name: inverter0_last_qpiri + last_qmod: + id: inverter0_last_qmod + name: inverter0_last_qmod + last_qflag: + id: inverter0_last_qflag + name: inverter0_last_qflag diff --git a/tests/components/pipsolar/test.rp2040.yaml b/tests/components/pipsolar/test.rp2040.yaml new file mode 100644 index 0000000000..12e9266343 --- /dev/null +++ b/tests/components/pipsolar/test.rp2040.yaml @@ -0,0 +1,247 @@ +esphome: + on_boot: + then: + - output.pipsolar.set_level: + id: inverter0_battery_recharge_voltage_out + value: 48.0 + +uart: + - id: uart_pipsolar + tx_pin: 4 + rx_pin: 5 + baud_rate: 115200 + +pipsolar: + id: inverter0 + +binary_sensor: + - platform: pipsolar + pipsolar_id: inverter0 + add_sbu_priority_version: + id: inverter0_add_sbu_priority_version + name: inverter0_add_sbu_priority_version + configuration_status: + id: inverter0_configuration_status + name: inverter0_configuration_status + scc_firmware_version: + id: inverter0_scc_firmware_version + name: inverter0_scc_firmware_version + load_status: + id: inverter0_load_status + name: inverter0_load_status + battery_voltage_to_steady_while_charging: + id: inverter0_battery_voltage_to_steady_while_charging + name: inverter0_battery_voltage_to_steady_while_charging + charging_status: + id: inverter0_charging_status + name: inverter0_charging_status + scc_charging_status: + id: inverter0_scc_charging_status + name: inverter0_scc_charging_status + ac_charging_status: + id: inverter0_ac_charging_status + name: inverter0_ac_charging_status + charging_to_floating_mode: + id: inverter0_charging_to_floating_mode + name: inverter0_charging_to_floating_mode + switch_on: + id: inverter0_switch_on + name: inverter0_switch_on + dustproof_installed: + id: inverter0_dustproof_installed + name: inverter0_dustproof_installed + silence_buzzer_open_buzzer: + id: inverter0_silence_buzzer_open_buzzer + name: inverter0_silence_buzzer_open_buzzer + overload_bypass_function: + id: inverter0_overload_bypass_function + name: inverter0_overload_bypass_function + lcd_escape_to_default: + id: inverter0_lcd_escape_to_default + name: inverter0_lcd_escape_to_default + overload_restart_function: + id: inverter0_overload_restart_function + name: inverter0_overload_restart_function + over_temperature_restart_function: + id: inverter0_over_temperature_restart_function + name: inverter0_over_temperature_restart_function + backlight_on: + id: inverter0_backlight_on + name: inverter0_backlight_on + +output: + - platform: pipsolar + pipsolar_id: inverter0 + battery_recharge_voltage: + id: inverter0_battery_recharge_voltage_out + +sensor: + - platform: pipsolar + pipsolar_id: inverter0 + grid_rating_voltage: + id: inverter0_grid_rating_voltage + name: inverter0_grid_rating_voltage + grid_rating_current: + id: inverter0_grid_rating_current + name: inverter0_grid_rating_current + ac_output_rating_voltage: + id: inverter0_ac_output_rating_voltage + name: inverter0_ac_output_rating_voltage + ac_output_rating_frequency: + id: inverter0_ac_output_rating_frequency + name: inverter0_ac_output_rating_frequency + ac_output_rating_current: + id: inverter0_ac_output_rating_current + name: inverter0_ac_output_rating_current + ac_output_rating_apparent_power: + id: inverter0_ac_output_rating_apparent_power + name: inverter0_ac_output_rating_apparent_power + ac_output_rating_active_power: + id: inverter0_ac_output_rating_active_power + name: inverter0_ac_output_rating_active_power + battery_rating_voltage: + id: inverter0_battery_rating_voltage + name: inverter0_battery_rating_voltage + battery_recharge_voltage: + id: inverter0_battery_recharge_voltage + name: inverter0_battery_recharge_voltage + battery_under_voltage: + id: inverter0_battery_under_voltage + name: inverter0_battery_under_voltage + battery_bulk_voltage: + id: inverter0_battery_bulk_voltage + name: inverter0_battery_bulk_voltage + battery_float_voltage: + id: inverter0_battery_float_voltage + name: inverter0_battery_float_voltage + battery_type: + id: inverter0_battery_type + name: inverter0_battery_type + current_max_ac_charging_current: + id: inverter0_current_max_ac_charging_current + name: inverter0_current_max_ac_charging_current + current_max_charging_current: + id: inverter0_current_max_charging_current + name: inverter0_current_max_charging_current + input_voltage_range: + id: inverter0_input_voltage_range + name: inverter0_input_voltage_range + output_source_priority: + id: inverter0_output_source_priority + name: inverter0_output_source_priority + charger_source_priority: + id: inverter0_charger_source_priority + name: inverter0_charger_source_priority + parallel_max_num: + id: inverter0_parallel_max_num + name: inverter0_parallel_max_num + machine_type: + id: inverter0_machine_type + name: inverter0_machine_type + topology: + id: inverter0_topology + name: inverter0_topology + output_mode: + id: inverter0_output_mode + name: inverter0_output_mode + battery_redischarge_voltage: + id: inverter0_battery_redischarge_voltage + name: inverter0_battery_redischarge_voltage + pv_ok_condition_for_parallel: + id: inverter0_pv_ok_condition_for_parallel + name: inverter0_pv_ok_condition_for_parallel + pv_power_balance: + id: inverter0_pv_power_balance + name: inverter0_pv_power_balance + grid_voltage: + id: inverter0_grid_voltage + name: inverter0_grid_voltage + grid_frequency: + id: inverter0_grid_frequency + name: inverter0_grid_frequency + ac_output_voltage: + id: inverter0_ac_output_voltage + name: inverter0_ac_output_voltage + ac_output_frequency: + id: inverter0_ac_output_frequency + name: inverter0_ac_output_frequency + ac_output_apparent_power: + id: inverter0_ac_output_apparent_power + name: inverter0_ac_output_apparent_power + ac_output_active_power: + id: inverter0_ac_output_active_power + name: inverter0_ac_output_active_power + output_load_percent: + id: inverter0_output_load_percent + name: inverter0_output_load_percent + bus_voltage: + id: inverter0_bus_voltage + name: inverter0_bus_voltage + battery_voltage: + id: inverter0_battery_voltage + name: inverter0_battery_voltage + battery_charging_current: + id: inverter0_battery_charging_current + name: inverter0_battery_charging_current + battery_capacity_percent: + id: inverter0_battery_capacity_percent + name: inverter0_battery_capacity_percent + inverter_heat_sink_temperature: + id: inverter0_inverter_heat_sink_temperature + name: inverter0_inverter_heat_sink_temperature + pv_input_current_for_battery: + id: inverter0_pv_input_current_for_battery + name: inverter0_pv_input_current_for_battery + pv_input_voltage: + id: inverter0_pv_input_voltage + name: inverter0_pv_input_voltage + battery_voltage_scc: + id: inverter0_battery_voltage_scc + name: inverter0_battery_voltage_scc + battery_discharge_current: + id: inverter0_battery_discharge_current + name: inverter0_battery_discharge_current + battery_voltage_offset_for_fans_on: + id: inverter0_battery_voltage_offset_for_fans_on + name: inverter0_battery_voltage_offset_for_fans_on + eeprom_version: + id: inverter0_eeprom_version + name: inverter0_eeprom_version + pv_charging_power: + id: inverter0_pv_charging_power + name: inverter0_pv_charging_power + +switch: + - platform: pipsolar + pipsolar_id: inverter0 + output_source_priority_utility: + name: inverter0_output_source_priority_utility + output_source_priority_solar: + name: inverter0_output_source_priority_solar + output_source_priority_battery: + name: inverter0_output_source_priority_battery + input_voltage_range: + name: inverter0_input_voltage_range + pv_ok_condition_for_parallel: + name: inverter0_pv_ok_condition_for_parallel + pv_power_balance: + name: inverter0_pv_power_balance + +text_sensor: + - platform: pipsolar + pipsolar_id: inverter0 + device_mode: + id: inverter0_device_mode + name: inverter0_device_mode + last_qpigs: + id: inverter0_last_qpigs + name: inverter0_last_qpigs + last_qpiri: + id: inverter0_last_qpiri + name: inverter0_last_qpiri + last_qmod: + id: inverter0_last_qmod + name: inverter0_last_qmod + last_qflag: + id: inverter0_last_qflag + name: inverter0_last_qflag diff --git a/tests/components/pm1006/test.esp32-c3-idf.yaml b/tests/components/pm1006/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..15ee077f3e --- /dev/null +++ b/tests/components/pm1006/test.esp32-c3-idf.yaml @@ -0,0 +1,10 @@ +uart: + - id: uart_pm1006 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sensor: + - platform: pm1006 + pm_2_5: + name: Particulate Matter 2.5µm Concentration diff --git a/tests/components/pm1006/test.esp32-c3.yaml b/tests/components/pm1006/test.esp32-c3.yaml new file mode 100644 index 0000000000..15ee077f3e --- /dev/null +++ b/tests/components/pm1006/test.esp32-c3.yaml @@ -0,0 +1,10 @@ +uart: + - id: uart_pm1006 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sensor: + - platform: pm1006 + pm_2_5: + name: Particulate Matter 2.5µm Concentration diff --git a/tests/components/pm1006/test.esp32-idf.yaml b/tests/components/pm1006/test.esp32-idf.yaml new file mode 100644 index 0000000000..635af37b25 --- /dev/null +++ b/tests/components/pm1006/test.esp32-idf.yaml @@ -0,0 +1,10 @@ +uart: + - id: uart_pm1006 + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +sensor: + - platform: pm1006 + pm_2_5: + name: Particulate Matter 2.5µm Concentration diff --git a/tests/components/pm1006/test.esp32.yaml b/tests/components/pm1006/test.esp32.yaml new file mode 100644 index 0000000000..635af37b25 --- /dev/null +++ b/tests/components/pm1006/test.esp32.yaml @@ -0,0 +1,10 @@ +uart: + - id: uart_pm1006 + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +sensor: + - platform: pm1006 + pm_2_5: + name: Particulate Matter 2.5µm Concentration diff --git a/tests/components/pm1006/test.esp8266.yaml b/tests/components/pm1006/test.esp8266.yaml new file mode 100644 index 0000000000..15ee077f3e --- /dev/null +++ b/tests/components/pm1006/test.esp8266.yaml @@ -0,0 +1,10 @@ +uart: + - id: uart_pm1006 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sensor: + - platform: pm1006 + pm_2_5: + name: Particulate Matter 2.5µm Concentration diff --git a/tests/components/pm1006/test.rp2040.yaml b/tests/components/pm1006/test.rp2040.yaml new file mode 100644 index 0000000000..15ee077f3e --- /dev/null +++ b/tests/components/pm1006/test.rp2040.yaml @@ -0,0 +1,10 @@ +uart: + - id: uart_pm1006 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sensor: + - platform: pm1006 + pm_2_5: + name: Particulate Matter 2.5µm Concentration diff --git a/tests/components/pmsa003i/test.esp32-c3-idf.yaml b/tests/components/pmsa003i/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..70e28303a2 --- /dev/null +++ b/tests/components/pmsa003i/test.esp32-c3-idf.yaml @@ -0,0 +1,27 @@ +i2c: + - id: i2c_pmsa003i + scl: 5 + sda: 4 + +sensor: + - platform: pmsa003i + pm_1_0: + name: PMSA003i PM1.0 + pm_2_5: + name: PMSA003i PM2.5 + pm_10_0: + name: PMSA003i PM10.0 + pmc_0_3: + name: PMSA003i PMC <0.3µm + pmc_0_5: + name: PMSA003i PMC <0.5µm + pmc_1_0: + name: PMSA003i PMC <1µm + pmc_2_5: + name: PMSA003i PMC <2.5µm + pmc_5_0: + name: PMSA003i PMC <5µm + pmc_10_0: + name: PMSA003i PMC <10µm + address: 0x12 + standard_units: true diff --git a/tests/components/pmsa003i/test.esp32-c3.yaml b/tests/components/pmsa003i/test.esp32-c3.yaml new file mode 100644 index 0000000000..70e28303a2 --- /dev/null +++ b/tests/components/pmsa003i/test.esp32-c3.yaml @@ -0,0 +1,27 @@ +i2c: + - id: i2c_pmsa003i + scl: 5 + sda: 4 + +sensor: + - platform: pmsa003i + pm_1_0: + name: PMSA003i PM1.0 + pm_2_5: + name: PMSA003i PM2.5 + pm_10_0: + name: PMSA003i PM10.0 + pmc_0_3: + name: PMSA003i PMC <0.3µm + pmc_0_5: + name: PMSA003i PMC <0.5µm + pmc_1_0: + name: PMSA003i PMC <1µm + pmc_2_5: + name: PMSA003i PMC <2.5µm + pmc_5_0: + name: PMSA003i PMC <5µm + pmc_10_0: + name: PMSA003i PMC <10µm + address: 0x12 + standard_units: true diff --git a/tests/components/pmsa003i/test.esp32-idf.yaml b/tests/components/pmsa003i/test.esp32-idf.yaml new file mode 100644 index 0000000000..d8d96400f6 --- /dev/null +++ b/tests/components/pmsa003i/test.esp32-idf.yaml @@ -0,0 +1,27 @@ +i2c: + - id: i2c_pmsa003i + scl: 16 + sda: 17 + +sensor: + - platform: pmsa003i + pm_1_0: + name: PMSA003i PM1.0 + pm_2_5: + name: PMSA003i PM2.5 + pm_10_0: + name: PMSA003i PM10.0 + pmc_0_3: + name: PMSA003i PMC <0.3µm + pmc_0_5: + name: PMSA003i PMC <0.5µm + pmc_1_0: + name: PMSA003i PMC <1µm + pmc_2_5: + name: PMSA003i PMC <2.5µm + pmc_5_0: + name: PMSA003i PMC <5µm + pmc_10_0: + name: PMSA003i PMC <10µm + address: 0x12 + standard_units: true diff --git a/tests/components/pmsa003i/test.esp32.yaml b/tests/components/pmsa003i/test.esp32.yaml new file mode 100644 index 0000000000..d8d96400f6 --- /dev/null +++ b/tests/components/pmsa003i/test.esp32.yaml @@ -0,0 +1,27 @@ +i2c: + - id: i2c_pmsa003i + scl: 16 + sda: 17 + +sensor: + - platform: pmsa003i + pm_1_0: + name: PMSA003i PM1.0 + pm_2_5: + name: PMSA003i PM2.5 + pm_10_0: + name: PMSA003i PM10.0 + pmc_0_3: + name: PMSA003i PMC <0.3µm + pmc_0_5: + name: PMSA003i PMC <0.5µm + pmc_1_0: + name: PMSA003i PMC <1µm + pmc_2_5: + name: PMSA003i PMC <2.5µm + pmc_5_0: + name: PMSA003i PMC <5µm + pmc_10_0: + name: PMSA003i PMC <10µm + address: 0x12 + standard_units: true diff --git a/tests/components/pmsa003i/test.esp8266.yaml b/tests/components/pmsa003i/test.esp8266.yaml new file mode 100644 index 0000000000..70e28303a2 --- /dev/null +++ b/tests/components/pmsa003i/test.esp8266.yaml @@ -0,0 +1,27 @@ +i2c: + - id: i2c_pmsa003i + scl: 5 + sda: 4 + +sensor: + - platform: pmsa003i + pm_1_0: + name: PMSA003i PM1.0 + pm_2_5: + name: PMSA003i PM2.5 + pm_10_0: + name: PMSA003i PM10.0 + pmc_0_3: + name: PMSA003i PMC <0.3µm + pmc_0_5: + name: PMSA003i PMC <0.5µm + pmc_1_0: + name: PMSA003i PMC <1µm + pmc_2_5: + name: PMSA003i PMC <2.5µm + pmc_5_0: + name: PMSA003i PMC <5µm + pmc_10_0: + name: PMSA003i PMC <10µm + address: 0x12 + standard_units: true diff --git a/tests/components/pmsa003i/test.rp2040.yaml b/tests/components/pmsa003i/test.rp2040.yaml new file mode 100644 index 0000000000..70e28303a2 --- /dev/null +++ b/tests/components/pmsa003i/test.rp2040.yaml @@ -0,0 +1,27 @@ +i2c: + - id: i2c_pmsa003i + scl: 5 + sda: 4 + +sensor: + - platform: pmsa003i + pm_1_0: + name: PMSA003i PM1.0 + pm_2_5: + name: PMSA003i PM2.5 + pm_10_0: + name: PMSA003i PM10.0 + pmc_0_3: + name: PMSA003i PMC <0.3µm + pmc_0_5: + name: PMSA003i PMC <0.5µm + pmc_1_0: + name: PMSA003i PMC <1µm + pmc_2_5: + name: PMSA003i PMC <2.5µm + pmc_5_0: + name: PMSA003i PMC <5µm + pmc_10_0: + name: PMSA003i PMC <10µm + address: 0x12 + standard_units: true diff --git a/tests/components/pmsx003/test.esp32-c3-idf.yaml b/tests/components/pmsx003/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..58adc9390a --- /dev/null +++ b/tests/components/pmsx003/test.esp32-c3-idf.yaml @@ -0,0 +1,34 @@ +uart: + - id: uart_pmsx003 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sensor: + - platform: pmsx003 + type: PMSX003 + pm_1_0: + name: PM 1.0 Concentration + pm_2_5: + name: PM 2.5 Concentration + pm_10_0: + name: PM 10.0 Concentration + pm_1_0_std: + name: PM 1.0 Standard Atmospher Concentration + pm_2_5_std: + name: PM 2.5 Standard Atmospher Concentration + pm_10_0_std: + name: PM 10.0 Standard Atmospher Concentration + pm_0_3um: + name: Particulate Count >0.3um + pm_0_5um: + name: Particulate Count >0.5um + pm_1_0um: + name: Particulate Count >1.0um + pm_2_5um: + name: Particulate Count >2.5um + pm_5_0um: + name: Particulate Count >5.0um + pm_10_0um: + name: Particulate Count >10.0um + update_interval: 30s diff --git a/tests/components/pmsx003/test.esp32-c3.yaml b/tests/components/pmsx003/test.esp32-c3.yaml new file mode 100644 index 0000000000..58adc9390a --- /dev/null +++ b/tests/components/pmsx003/test.esp32-c3.yaml @@ -0,0 +1,34 @@ +uart: + - id: uart_pmsx003 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sensor: + - platform: pmsx003 + type: PMSX003 + pm_1_0: + name: PM 1.0 Concentration + pm_2_5: + name: PM 2.5 Concentration + pm_10_0: + name: PM 10.0 Concentration + pm_1_0_std: + name: PM 1.0 Standard Atmospher Concentration + pm_2_5_std: + name: PM 2.5 Standard Atmospher Concentration + pm_10_0_std: + name: PM 10.0 Standard Atmospher Concentration + pm_0_3um: + name: Particulate Count >0.3um + pm_0_5um: + name: Particulate Count >0.5um + pm_1_0um: + name: Particulate Count >1.0um + pm_2_5um: + name: Particulate Count >2.5um + pm_5_0um: + name: Particulate Count >5.0um + pm_10_0um: + name: Particulate Count >10.0um + update_interval: 30s diff --git a/tests/components/pmsx003/test.esp32-idf.yaml b/tests/components/pmsx003/test.esp32-idf.yaml new file mode 100644 index 0000000000..5e7ebbbb2e --- /dev/null +++ b/tests/components/pmsx003/test.esp32-idf.yaml @@ -0,0 +1,34 @@ +uart: + - id: uart_pmsx003 + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +sensor: + - platform: pmsx003 + type: PMSX003 + pm_1_0: + name: PM 1.0 Concentration + pm_2_5: + name: PM 2.5 Concentration + pm_10_0: + name: PM 10.0 Concentration + pm_1_0_std: + name: PM 1.0 Standard Atmospher Concentration + pm_2_5_std: + name: PM 2.5 Standard Atmospher Concentration + pm_10_0_std: + name: PM 10.0 Standard Atmospher Concentration + pm_0_3um: + name: Particulate Count >0.3um + pm_0_5um: + name: Particulate Count >0.5um + pm_1_0um: + name: Particulate Count >1.0um + pm_2_5um: + name: Particulate Count >2.5um + pm_5_0um: + name: Particulate Count >5.0um + pm_10_0um: + name: Particulate Count >10.0um + update_interval: 30s diff --git a/tests/components/pmsx003/test.esp32.yaml b/tests/components/pmsx003/test.esp32.yaml new file mode 100644 index 0000000000..5e7ebbbb2e --- /dev/null +++ b/tests/components/pmsx003/test.esp32.yaml @@ -0,0 +1,34 @@ +uart: + - id: uart_pmsx003 + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +sensor: + - platform: pmsx003 + type: PMSX003 + pm_1_0: + name: PM 1.0 Concentration + pm_2_5: + name: PM 2.5 Concentration + pm_10_0: + name: PM 10.0 Concentration + pm_1_0_std: + name: PM 1.0 Standard Atmospher Concentration + pm_2_5_std: + name: PM 2.5 Standard Atmospher Concentration + pm_10_0_std: + name: PM 10.0 Standard Atmospher Concentration + pm_0_3um: + name: Particulate Count >0.3um + pm_0_5um: + name: Particulate Count >0.5um + pm_1_0um: + name: Particulate Count >1.0um + pm_2_5um: + name: Particulate Count >2.5um + pm_5_0um: + name: Particulate Count >5.0um + pm_10_0um: + name: Particulate Count >10.0um + update_interval: 30s diff --git a/tests/components/pmsx003/test.esp8266.yaml b/tests/components/pmsx003/test.esp8266.yaml new file mode 100644 index 0000000000..58adc9390a --- /dev/null +++ b/tests/components/pmsx003/test.esp8266.yaml @@ -0,0 +1,34 @@ +uart: + - id: uart_pmsx003 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sensor: + - platform: pmsx003 + type: PMSX003 + pm_1_0: + name: PM 1.0 Concentration + pm_2_5: + name: PM 2.5 Concentration + pm_10_0: + name: PM 10.0 Concentration + pm_1_0_std: + name: PM 1.0 Standard Atmospher Concentration + pm_2_5_std: + name: PM 2.5 Standard Atmospher Concentration + pm_10_0_std: + name: PM 10.0 Standard Atmospher Concentration + pm_0_3um: + name: Particulate Count >0.3um + pm_0_5um: + name: Particulate Count >0.5um + pm_1_0um: + name: Particulate Count >1.0um + pm_2_5um: + name: Particulate Count >2.5um + pm_5_0um: + name: Particulate Count >5.0um + pm_10_0um: + name: Particulate Count >10.0um + update_interval: 30s diff --git a/tests/components/pmsx003/test.rp2040.yaml b/tests/components/pmsx003/test.rp2040.yaml new file mode 100644 index 0000000000..58adc9390a --- /dev/null +++ b/tests/components/pmsx003/test.rp2040.yaml @@ -0,0 +1,34 @@ +uart: + - id: uart_pmsx003 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sensor: + - platform: pmsx003 + type: PMSX003 + pm_1_0: + name: PM 1.0 Concentration + pm_2_5: + name: PM 2.5 Concentration + pm_10_0: + name: PM 10.0 Concentration + pm_1_0_std: + name: PM 1.0 Standard Atmospher Concentration + pm_2_5_std: + name: PM 2.5 Standard Atmospher Concentration + pm_10_0_std: + name: PM 10.0 Standard Atmospher Concentration + pm_0_3um: + name: Particulate Count >0.3um + pm_0_5um: + name: Particulate Count >0.5um + pm_1_0um: + name: Particulate Count >1.0um + pm_2_5um: + name: Particulate Count >2.5um + pm_5_0um: + name: Particulate Count >5.0um + pm_10_0um: + name: Particulate Count >10.0um + update_interval: 30s diff --git a/tests/components/pmwcs3/test.esp32-c3-idf.yaml b/tests/components/pmwcs3/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..7e7e72692d --- /dev/null +++ b/tests/components/pmwcs3/test.esp32-c3-idf.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_pmwcs3 + scl: 5 + sda: 4 + +sensor: + - platform: pmwcs3 + e25: + name: pmwcs3_e25 + ec: + name: pmwcs3_ec + temperature: + name: pmwcs3_temperature + vwc: + name: pmwcs3_vwc diff --git a/tests/components/pmwcs3/test.esp32-c3.yaml b/tests/components/pmwcs3/test.esp32-c3.yaml new file mode 100644 index 0000000000..7e7e72692d --- /dev/null +++ b/tests/components/pmwcs3/test.esp32-c3.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_pmwcs3 + scl: 5 + sda: 4 + +sensor: + - platform: pmwcs3 + e25: + name: pmwcs3_e25 + ec: + name: pmwcs3_ec + temperature: + name: pmwcs3_temperature + vwc: + name: pmwcs3_vwc diff --git a/tests/components/pmwcs3/test.esp32-idf.yaml b/tests/components/pmwcs3/test.esp32-idf.yaml new file mode 100644 index 0000000000..787eaca650 --- /dev/null +++ b/tests/components/pmwcs3/test.esp32-idf.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_pmwcs3 + scl: 16 + sda: 17 + +sensor: + - platform: pmwcs3 + e25: + name: pmwcs3_e25 + ec: + name: pmwcs3_ec + temperature: + name: pmwcs3_temperature + vwc: + name: pmwcs3_vwc diff --git a/tests/components/pmwcs3/test.esp32.yaml b/tests/components/pmwcs3/test.esp32.yaml new file mode 100644 index 0000000000..787eaca650 --- /dev/null +++ b/tests/components/pmwcs3/test.esp32.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_pmwcs3 + scl: 16 + sda: 17 + +sensor: + - platform: pmwcs3 + e25: + name: pmwcs3_e25 + ec: + name: pmwcs3_ec + temperature: + name: pmwcs3_temperature + vwc: + name: pmwcs3_vwc diff --git a/tests/components/pmwcs3/test.esp8266.yaml b/tests/components/pmwcs3/test.esp8266.yaml new file mode 100644 index 0000000000..7e7e72692d --- /dev/null +++ b/tests/components/pmwcs3/test.esp8266.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_pmwcs3 + scl: 5 + sda: 4 + +sensor: + - platform: pmwcs3 + e25: + name: pmwcs3_e25 + ec: + name: pmwcs3_ec + temperature: + name: pmwcs3_temperature + vwc: + name: pmwcs3_vwc diff --git a/tests/components/pmwcs3/test.rp2040.yaml b/tests/components/pmwcs3/test.rp2040.yaml new file mode 100644 index 0000000000..7e7e72692d --- /dev/null +++ b/tests/components/pmwcs3/test.rp2040.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_pmwcs3 + scl: 5 + sda: 4 + +sensor: + - platform: pmwcs3 + e25: + name: pmwcs3_e25 + ec: + name: pmwcs3_ec + temperature: + name: pmwcs3_temperature + vwc: + name: pmwcs3_vwc diff --git a/tests/components/pn532_i2c/test.esp32-c3-idf.yaml b/tests/components/pn532_i2c/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..62816d2ace --- /dev/null +++ b/tests/components/pn532_i2c/test.esp32-c3-idf.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_pn532 + scl: 5 + sda: 4 + +pn532_i2c: + id: pn532_nfcc + +binary_sensor: + - platform: pn532 + pn532_id: pn532_nfcc + name: PN532 NFC Tag + uid: 74-10-37-94 diff --git a/tests/components/pn532_i2c/test.esp32-c3.yaml b/tests/components/pn532_i2c/test.esp32-c3.yaml new file mode 100644 index 0000000000..62816d2ace --- /dev/null +++ b/tests/components/pn532_i2c/test.esp32-c3.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_pn532 + scl: 5 + sda: 4 + +pn532_i2c: + id: pn532_nfcc + +binary_sensor: + - platform: pn532 + pn532_id: pn532_nfcc + name: PN532 NFC Tag + uid: 74-10-37-94 diff --git a/tests/components/pn532_i2c/test.esp32-idf.yaml b/tests/components/pn532_i2c/test.esp32-idf.yaml new file mode 100644 index 0000000000..a50533b1d0 --- /dev/null +++ b/tests/components/pn532_i2c/test.esp32-idf.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_pn532 + scl: 16 + sda: 17 + +pn532_i2c: + id: pn532_nfcc + +binary_sensor: + - platform: pn532 + pn532_id: pn532_nfcc + name: PN532 NFC Tag + uid: 74-10-37-94 diff --git a/tests/components/pn532_i2c/test.esp32.yaml b/tests/components/pn532_i2c/test.esp32.yaml new file mode 100644 index 0000000000..a50533b1d0 --- /dev/null +++ b/tests/components/pn532_i2c/test.esp32.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_pn532 + scl: 16 + sda: 17 + +pn532_i2c: + id: pn532_nfcc + +binary_sensor: + - platform: pn532 + pn532_id: pn532_nfcc + name: PN532 NFC Tag + uid: 74-10-37-94 diff --git a/tests/components/pn532_i2c/test.esp8266.yaml b/tests/components/pn532_i2c/test.esp8266.yaml new file mode 100644 index 0000000000..62816d2ace --- /dev/null +++ b/tests/components/pn532_i2c/test.esp8266.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_pn532 + scl: 5 + sda: 4 + +pn532_i2c: + id: pn532_nfcc + +binary_sensor: + - platform: pn532 + pn532_id: pn532_nfcc + name: PN532 NFC Tag + uid: 74-10-37-94 diff --git a/tests/components/pn532_i2c/test.rp2040.yaml b/tests/components/pn532_i2c/test.rp2040.yaml new file mode 100644 index 0000000000..62816d2ace --- /dev/null +++ b/tests/components/pn532_i2c/test.rp2040.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_pn532 + scl: 5 + sda: 4 + +pn532_i2c: + id: pn532_nfcc + +binary_sensor: + - platform: pn532 + pn532_id: pn532_nfcc + name: PN532 NFC Tag + uid: 74-10-37-94 diff --git a/tests/components/pn532_spi/test.esp32-c3-idf.yaml b/tests/components/pn532_spi/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..d21d50aa5c --- /dev/null +++ b/tests/components/pn532_spi/test.esp32-c3-idf.yaml @@ -0,0 +1,15 @@ +spi: + - id: spi_pn532 + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +pn532_spi: + id: pn532_nfcc + cs_pin: 4 + +binary_sensor: + - platform: pn532 + pn532_id: pn532_nfcc + name: PN532 NFC Tag + uid: 74-10-37-94 diff --git a/tests/components/pn532_spi/test.esp32-c3.yaml b/tests/components/pn532_spi/test.esp32-c3.yaml new file mode 100644 index 0000000000..d21d50aa5c --- /dev/null +++ b/tests/components/pn532_spi/test.esp32-c3.yaml @@ -0,0 +1,15 @@ +spi: + - id: spi_pn532 + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +pn532_spi: + id: pn532_nfcc + cs_pin: 4 + +binary_sensor: + - platform: pn532 + pn532_id: pn532_nfcc + name: PN532 NFC Tag + uid: 74-10-37-94 diff --git a/tests/components/pn532_spi/test.esp32-idf.yaml b/tests/components/pn532_spi/test.esp32-idf.yaml new file mode 100644 index 0000000000..18a382a007 --- /dev/null +++ b/tests/components/pn532_spi/test.esp32-idf.yaml @@ -0,0 +1,15 @@ +spi: + - id: spi_pn532 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +pn532_spi: + id: pn532_nfcc + cs_pin: 12 + +binary_sensor: + - platform: pn532 + pn532_id: pn532_nfcc + name: PN532 NFC Tag + uid: 74-10-37-94 diff --git a/tests/components/pn532_spi/test.esp32.yaml b/tests/components/pn532_spi/test.esp32.yaml new file mode 100644 index 0000000000..18a382a007 --- /dev/null +++ b/tests/components/pn532_spi/test.esp32.yaml @@ -0,0 +1,15 @@ +spi: + - id: spi_pn532 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +pn532_spi: + id: pn532_nfcc + cs_pin: 12 + +binary_sensor: + - platform: pn532 + pn532_id: pn532_nfcc + name: PN532 NFC Tag + uid: 74-10-37-94 diff --git a/tests/components/pn532_spi/test.esp8266.yaml b/tests/components/pn532_spi/test.esp8266.yaml new file mode 100644 index 0000000000..1dba38e63e --- /dev/null +++ b/tests/components/pn532_spi/test.esp8266.yaml @@ -0,0 +1,15 @@ +spi: + - id: spi_pn532 + clk_pin: 14 + mosi_pin: 13 + miso_pin: 12 + +pn532_spi: + id: pn532_nfcc + cs_pin: 15 + +binary_sensor: + - platform: pn532 + pn532_id: pn532_nfcc + name: PN532 NFC Tag + uid: 74-10-37-94 diff --git a/tests/components/pn532_spi/test.rp2040.yaml b/tests/components/pn532_spi/test.rp2040.yaml new file mode 100644 index 0000000000..ab02b2cc47 --- /dev/null +++ b/tests/components/pn532_spi/test.rp2040.yaml @@ -0,0 +1,15 @@ +spi: + - id: spi_pn532 + clk_pin: 2 + mosi_pin: 3 + miso_pin: 4 + +pn532_spi: + id: pn532_nfcc + cs_pin: 6 + +binary_sensor: + - platform: pn532 + pn532_id: pn532_nfcc + name: PN532 NFC Tag + uid: 74-10-37-94 diff --git a/tests/components/pn7150_i2c/test.esp32-c3-idf.yaml b/tests/components/pn7150_i2c/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..aee1886cd4 --- /dev/null +++ b/tests/components/pn7150_i2c/test.esp32-c3-idf.yaml @@ -0,0 +1,35 @@ +esphome: + on_boot: + then: + - tag.set_clean_mode: nfcc_pn7150 + - tag.set_format_mode: nfcc_pn7150 + - tag.set_read_mode: nfcc_pn7150 + - tag.set_write_message: + message: https://www.home-assistant.io/tag/pulse + include_android_app_record: false + - tag.set_write_mode: nfcc_pn7150 + - tag.set_emulation_message: + message: https://www.home-assistant.io/tag/pulse + include_android_app_record: false + - tag.emulation_off: nfcc_pn7150 + - tag.emulation_on: nfcc_pn7150 + - tag.polling_off: nfcc_pn7150 + - tag.polling_on: nfcc_pn7150 + +i2c: + - id: i2c_pn7150 + scl: 5 + sda: 4 + +pn7150_i2c: + id: nfcc_pn7150 + irq_pin: 2 + ven_pin: 3 + emulation_message: https://www.home-assistant.io/tag/pulse_ce + tag_ttl: 1000ms + on_tag: + - logger.log: "Tag" + on_tag_removed: + - logger.log: "Tag removed" + on_emulated_tag_scan: + - logger.log: "Tag emulated" diff --git a/tests/components/pn7150_i2c/test.esp32-c3.yaml b/tests/components/pn7150_i2c/test.esp32-c3.yaml new file mode 100644 index 0000000000..aee1886cd4 --- /dev/null +++ b/tests/components/pn7150_i2c/test.esp32-c3.yaml @@ -0,0 +1,35 @@ +esphome: + on_boot: + then: + - tag.set_clean_mode: nfcc_pn7150 + - tag.set_format_mode: nfcc_pn7150 + - tag.set_read_mode: nfcc_pn7150 + - tag.set_write_message: + message: https://www.home-assistant.io/tag/pulse + include_android_app_record: false + - tag.set_write_mode: nfcc_pn7150 + - tag.set_emulation_message: + message: https://www.home-assistant.io/tag/pulse + include_android_app_record: false + - tag.emulation_off: nfcc_pn7150 + - tag.emulation_on: nfcc_pn7150 + - tag.polling_off: nfcc_pn7150 + - tag.polling_on: nfcc_pn7150 + +i2c: + - id: i2c_pn7150 + scl: 5 + sda: 4 + +pn7150_i2c: + id: nfcc_pn7150 + irq_pin: 2 + ven_pin: 3 + emulation_message: https://www.home-assistant.io/tag/pulse_ce + tag_ttl: 1000ms + on_tag: + - logger.log: "Tag" + on_tag_removed: + - logger.log: "Tag removed" + on_emulated_tag_scan: + - logger.log: "Tag emulated" diff --git a/tests/components/pn7150_i2c/test.esp32-idf.yaml b/tests/components/pn7150_i2c/test.esp32-idf.yaml new file mode 100644 index 0000000000..23d1061608 --- /dev/null +++ b/tests/components/pn7150_i2c/test.esp32-idf.yaml @@ -0,0 +1,35 @@ +esphome: + on_boot: + then: + - tag.set_clean_mode: nfcc_pn7150 + - tag.set_format_mode: nfcc_pn7150 + - tag.set_read_mode: nfcc_pn7150 + - tag.set_write_message: + message: https://www.home-assistant.io/tag/pulse + include_android_app_record: false + - tag.set_write_mode: nfcc_pn7150 + - tag.set_emulation_message: + message: https://www.home-assistant.io/tag/pulse + include_android_app_record: false + - tag.emulation_off: nfcc_pn7150 + - tag.emulation_on: nfcc_pn7150 + - tag.polling_off: nfcc_pn7150 + - tag.polling_on: nfcc_pn7150 + +i2c: + - id: i2c_pn7150 + scl: 16 + sda: 17 + +pn7150_i2c: + id: nfcc_pn7150 + irq_pin: 12 + ven_pin: 13 + emulation_message: https://www.home-assistant.io/tag/pulse_ce + tag_ttl: 1000ms + on_tag: + - logger.log: "Tag" + on_tag_removed: + - logger.log: "Tag removed" + on_emulated_tag_scan: + - logger.log: "Tag emulated" diff --git a/tests/components/pn7150_i2c/test.esp32.yaml b/tests/components/pn7150_i2c/test.esp32.yaml new file mode 100644 index 0000000000..23d1061608 --- /dev/null +++ b/tests/components/pn7150_i2c/test.esp32.yaml @@ -0,0 +1,35 @@ +esphome: + on_boot: + then: + - tag.set_clean_mode: nfcc_pn7150 + - tag.set_format_mode: nfcc_pn7150 + - tag.set_read_mode: nfcc_pn7150 + - tag.set_write_message: + message: https://www.home-assistant.io/tag/pulse + include_android_app_record: false + - tag.set_write_mode: nfcc_pn7150 + - tag.set_emulation_message: + message: https://www.home-assistant.io/tag/pulse + include_android_app_record: false + - tag.emulation_off: nfcc_pn7150 + - tag.emulation_on: nfcc_pn7150 + - tag.polling_off: nfcc_pn7150 + - tag.polling_on: nfcc_pn7150 + +i2c: + - id: i2c_pn7150 + scl: 16 + sda: 17 + +pn7150_i2c: + id: nfcc_pn7150 + irq_pin: 12 + ven_pin: 13 + emulation_message: https://www.home-assistant.io/tag/pulse_ce + tag_ttl: 1000ms + on_tag: + - logger.log: "Tag" + on_tag_removed: + - logger.log: "Tag removed" + on_emulated_tag_scan: + - logger.log: "Tag emulated" diff --git a/tests/components/pn7150_i2c/test.esp8266.yaml b/tests/components/pn7150_i2c/test.esp8266.yaml new file mode 100644 index 0000000000..6017d548ca --- /dev/null +++ b/tests/components/pn7150_i2c/test.esp8266.yaml @@ -0,0 +1,35 @@ +esphome: + on_boot: + then: + - tag.set_clean_mode: nfcc_pn7150 + - tag.set_format_mode: nfcc_pn7150 + - tag.set_read_mode: nfcc_pn7150 + - tag.set_write_message: + message: https://www.home-assistant.io/tag/pulse + include_android_app_record: false + - tag.set_write_mode: nfcc_pn7150 + - tag.set_emulation_message: + message: https://www.home-assistant.io/tag/pulse + include_android_app_record: false + - tag.emulation_off: nfcc_pn7150 + - tag.emulation_on: nfcc_pn7150 + - tag.polling_off: nfcc_pn7150 + - tag.polling_on: nfcc_pn7150 + +i2c: + - id: i2c_pn7150 + scl: 5 + sda: 4 + +pn7150_i2c: + id: nfcc_pn7150 + irq_pin: 12 + ven_pin: 13 + emulation_message: https://www.home-assistant.io/tag/pulse_ce + tag_ttl: 1000ms + on_tag: + - logger.log: "Tag" + on_tag_removed: + - logger.log: "Tag removed" + on_emulated_tag_scan: + - logger.log: "Tag emulated" diff --git a/tests/components/pn7150_i2c/test.rp2040.yaml b/tests/components/pn7150_i2c/test.rp2040.yaml new file mode 100644 index 0000000000..aee1886cd4 --- /dev/null +++ b/tests/components/pn7150_i2c/test.rp2040.yaml @@ -0,0 +1,35 @@ +esphome: + on_boot: + then: + - tag.set_clean_mode: nfcc_pn7150 + - tag.set_format_mode: nfcc_pn7150 + - tag.set_read_mode: nfcc_pn7150 + - tag.set_write_message: + message: https://www.home-assistant.io/tag/pulse + include_android_app_record: false + - tag.set_write_mode: nfcc_pn7150 + - tag.set_emulation_message: + message: https://www.home-assistant.io/tag/pulse + include_android_app_record: false + - tag.emulation_off: nfcc_pn7150 + - tag.emulation_on: nfcc_pn7150 + - tag.polling_off: nfcc_pn7150 + - tag.polling_on: nfcc_pn7150 + +i2c: + - id: i2c_pn7150 + scl: 5 + sda: 4 + +pn7150_i2c: + id: nfcc_pn7150 + irq_pin: 2 + ven_pin: 3 + emulation_message: https://www.home-assistant.io/tag/pulse_ce + tag_ttl: 1000ms + on_tag: + - logger.log: "Tag" + on_tag_removed: + - logger.log: "Tag removed" + on_emulated_tag_scan: + - logger.log: "Tag emulated" diff --git a/tests/components/pn7160_i2c/test.esp32-c3-idf.yaml b/tests/components/pn7160_i2c/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..d1d7947352 --- /dev/null +++ b/tests/components/pn7160_i2c/test.esp32-c3-idf.yaml @@ -0,0 +1,35 @@ +esphome: + on_boot: + then: + - tag.set_clean_mode: nfcc_pn7160 + - tag.set_format_mode: nfcc_pn7160 + - tag.set_read_mode: nfcc_pn7160 + - tag.set_write_message: + message: https://www.home-assistant.io/tag/pulse + include_android_app_record: false + - tag.set_write_mode: nfcc_pn7160 + - tag.set_emulation_message: + message: https://www.home-assistant.io/tag/pulse + include_android_app_record: false + - tag.emulation_off: nfcc_pn7160 + - tag.emulation_on: nfcc_pn7160 + - tag.polling_off: nfcc_pn7160 + - tag.polling_on: nfcc_pn7160 + +i2c: + - id: i2c_pn7160 + scl: 5 + sda: 4 + +pn7160_i2c: + id: nfcc_pn7160 + irq_pin: 2 + ven_pin: 3 + emulation_message: https://www.home-assistant.io/tag/pulse_ce + tag_ttl: 1000ms + on_tag: + - logger.log: "Tag" + on_tag_removed: + - logger.log: "Tag removed" + on_emulated_tag_scan: + - logger.log: "Tag emulated" diff --git a/tests/components/pn7160_i2c/test.esp32-c3.yaml b/tests/components/pn7160_i2c/test.esp32-c3.yaml new file mode 100644 index 0000000000..d1d7947352 --- /dev/null +++ b/tests/components/pn7160_i2c/test.esp32-c3.yaml @@ -0,0 +1,35 @@ +esphome: + on_boot: + then: + - tag.set_clean_mode: nfcc_pn7160 + - tag.set_format_mode: nfcc_pn7160 + - tag.set_read_mode: nfcc_pn7160 + - tag.set_write_message: + message: https://www.home-assistant.io/tag/pulse + include_android_app_record: false + - tag.set_write_mode: nfcc_pn7160 + - tag.set_emulation_message: + message: https://www.home-assistant.io/tag/pulse + include_android_app_record: false + - tag.emulation_off: nfcc_pn7160 + - tag.emulation_on: nfcc_pn7160 + - tag.polling_off: nfcc_pn7160 + - tag.polling_on: nfcc_pn7160 + +i2c: + - id: i2c_pn7160 + scl: 5 + sda: 4 + +pn7160_i2c: + id: nfcc_pn7160 + irq_pin: 2 + ven_pin: 3 + emulation_message: https://www.home-assistant.io/tag/pulse_ce + tag_ttl: 1000ms + on_tag: + - logger.log: "Tag" + on_tag_removed: + - logger.log: "Tag removed" + on_emulated_tag_scan: + - logger.log: "Tag emulated" diff --git a/tests/components/pn7160_i2c/test.esp32-idf.yaml b/tests/components/pn7160_i2c/test.esp32-idf.yaml new file mode 100644 index 0000000000..d1a3cf5c77 --- /dev/null +++ b/tests/components/pn7160_i2c/test.esp32-idf.yaml @@ -0,0 +1,35 @@ +esphome: + on_boot: + then: + - tag.set_clean_mode: nfcc_pn7160 + - tag.set_format_mode: nfcc_pn7160 + - tag.set_read_mode: nfcc_pn7160 + - tag.set_write_message: + message: https://www.home-assistant.io/tag/pulse + include_android_app_record: false + - tag.set_write_mode: nfcc_pn7160 + - tag.set_emulation_message: + message: https://www.home-assistant.io/tag/pulse + include_android_app_record: false + - tag.emulation_off: nfcc_pn7160 + - tag.emulation_on: nfcc_pn7160 + - tag.polling_off: nfcc_pn7160 + - tag.polling_on: nfcc_pn7160 + +i2c: + - id: i2c_pn7160 + scl: 16 + sda: 17 + +pn7150_i2c: + id: nfcc_pn7160 + irq_pin: 12 + ven_pin: 13 + emulation_message: https://www.home-assistant.io/tag/pulse_ce + tag_ttl: 1000ms + on_tag: + - logger.log: "Tag" + on_tag_removed: + - logger.log: "Tag removed" + on_emulated_tag_scan: + - logger.log: "Tag emulated" diff --git a/tests/components/pn7160_i2c/test.esp32.yaml b/tests/components/pn7160_i2c/test.esp32.yaml new file mode 100644 index 0000000000..d1a3cf5c77 --- /dev/null +++ b/tests/components/pn7160_i2c/test.esp32.yaml @@ -0,0 +1,35 @@ +esphome: + on_boot: + then: + - tag.set_clean_mode: nfcc_pn7160 + - tag.set_format_mode: nfcc_pn7160 + - tag.set_read_mode: nfcc_pn7160 + - tag.set_write_message: + message: https://www.home-assistant.io/tag/pulse + include_android_app_record: false + - tag.set_write_mode: nfcc_pn7160 + - tag.set_emulation_message: + message: https://www.home-assistant.io/tag/pulse + include_android_app_record: false + - tag.emulation_off: nfcc_pn7160 + - tag.emulation_on: nfcc_pn7160 + - tag.polling_off: nfcc_pn7160 + - tag.polling_on: nfcc_pn7160 + +i2c: + - id: i2c_pn7160 + scl: 16 + sda: 17 + +pn7150_i2c: + id: nfcc_pn7160 + irq_pin: 12 + ven_pin: 13 + emulation_message: https://www.home-assistant.io/tag/pulse_ce + tag_ttl: 1000ms + on_tag: + - logger.log: "Tag" + on_tag_removed: + - logger.log: "Tag removed" + on_emulated_tag_scan: + - logger.log: "Tag emulated" diff --git a/tests/components/pn7160_i2c/test.esp8266.yaml b/tests/components/pn7160_i2c/test.esp8266.yaml new file mode 100644 index 0000000000..57bd965fc9 --- /dev/null +++ b/tests/components/pn7160_i2c/test.esp8266.yaml @@ -0,0 +1,35 @@ +esphome: + on_boot: + then: + - tag.set_clean_mode: nfcc_pn7160 + - tag.set_format_mode: nfcc_pn7160 + - tag.set_read_mode: nfcc_pn7160 + - tag.set_write_message: + message: https://www.home-assistant.io/tag/pulse + include_android_app_record: false + - tag.set_write_mode: nfcc_pn7160 + - tag.set_emulation_message: + message: https://www.home-assistant.io/tag/pulse + include_android_app_record: false + - tag.emulation_off: nfcc_pn7160 + - tag.emulation_on: nfcc_pn7160 + - tag.polling_off: nfcc_pn7160 + - tag.polling_on: nfcc_pn7160 + +i2c: + - id: i2c_pn7160 + scl: 5 + sda: 4 + +pn7150_i2c: + id: nfcc_pn7160 + irq_pin: 12 + ven_pin: 13 + emulation_message: https://www.home-assistant.io/tag/pulse_ce + tag_ttl: 1000ms + on_tag: + - logger.log: "Tag" + on_tag_removed: + - logger.log: "Tag removed" + on_emulated_tag_scan: + - logger.log: "Tag emulated" diff --git a/tests/components/pn7160_i2c/test.rp2040.yaml b/tests/components/pn7160_i2c/test.rp2040.yaml new file mode 100644 index 0000000000..5224b465ed --- /dev/null +++ b/tests/components/pn7160_i2c/test.rp2040.yaml @@ -0,0 +1,35 @@ +esphome: + on_boot: + then: + - tag.set_clean_mode: nfcc_pn7160 + - tag.set_format_mode: nfcc_pn7160 + - tag.set_read_mode: nfcc_pn7160 + - tag.set_write_message: + message: https://www.home-assistant.io/tag/pulse + include_android_app_record: false + - tag.set_write_mode: nfcc_pn7160 + - tag.set_emulation_message: + message: https://www.home-assistant.io/tag/pulse + include_android_app_record: false + - tag.emulation_off: nfcc_pn7160 + - tag.emulation_on: nfcc_pn7160 + - tag.polling_off: nfcc_pn7160 + - tag.polling_on: nfcc_pn7160 + +i2c: + - id: i2c_pn7160 + scl: 5 + sda: 4 + +pn7150_i2c: + id: nfcc_pn7160 + irq_pin: 2 + ven_pin: 3 + emulation_message: https://www.home-assistant.io/tag/pulse_ce + tag_ttl: 1000ms + on_tag: + - logger.log: "Tag" + on_tag_removed: + - logger.log: "Tag removed" + on_emulated_tag_scan: + - logger.log: "Tag emulated" diff --git a/tests/components/pn7160_spi/test.esp32-c3-idf.yaml b/tests/components/pn7160_spi/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..fd19a53b2b --- /dev/null +++ b/tests/components/pn7160_spi/test.esp32-c3-idf.yaml @@ -0,0 +1,37 @@ +esphome: + on_boot: + then: + - tag.set_clean_mode: nfcc_pn7160 + - tag.set_format_mode: nfcc_pn7160 + - tag.set_read_mode: nfcc_pn7160 + - tag.set_write_message: + message: https://www.home-assistant.io/tag/pulse + include_android_app_record: false + - tag.set_write_mode: nfcc_pn7160 + - tag.set_emulation_message: + message: https://www.home-assistant.io/tag/pulse + include_android_app_record: false + - tag.emulation_off: nfcc_pn7160 + - tag.emulation_on: nfcc_pn7160 + - tag.polling_off: nfcc_pn7160 + - tag.polling_on: nfcc_pn7160 + +spi: + - id: spi_pn7160 + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +pn7160_spi: + id: nfcc_pn7160 + cs_pin: 4 + irq_pin: 2 + ven_pin: 3 + emulation_message: https://www.home-assistant.io/tag/pulse_ce + tag_ttl: 1000ms + on_tag: + - logger.log: "Tag" + on_tag_removed: + - logger.log: "Tag removed" + on_emulated_tag_scan: + - logger.log: "Tag emulated" diff --git a/tests/components/pn7160_spi/test.esp32-c3.yaml b/tests/components/pn7160_spi/test.esp32-c3.yaml new file mode 100644 index 0000000000..fd19a53b2b --- /dev/null +++ b/tests/components/pn7160_spi/test.esp32-c3.yaml @@ -0,0 +1,37 @@ +esphome: + on_boot: + then: + - tag.set_clean_mode: nfcc_pn7160 + - tag.set_format_mode: nfcc_pn7160 + - tag.set_read_mode: nfcc_pn7160 + - tag.set_write_message: + message: https://www.home-assistant.io/tag/pulse + include_android_app_record: false + - tag.set_write_mode: nfcc_pn7160 + - tag.set_emulation_message: + message: https://www.home-assistant.io/tag/pulse + include_android_app_record: false + - tag.emulation_off: nfcc_pn7160 + - tag.emulation_on: nfcc_pn7160 + - tag.polling_off: nfcc_pn7160 + - tag.polling_on: nfcc_pn7160 + +spi: + - id: spi_pn7160 + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +pn7160_spi: + id: nfcc_pn7160 + cs_pin: 4 + irq_pin: 2 + ven_pin: 3 + emulation_message: https://www.home-assistant.io/tag/pulse_ce + tag_ttl: 1000ms + on_tag: + - logger.log: "Tag" + on_tag_removed: + - logger.log: "Tag removed" + on_emulated_tag_scan: + - logger.log: "Tag emulated" diff --git a/tests/components/pn7160_spi/test.esp32-idf.yaml b/tests/components/pn7160_spi/test.esp32-idf.yaml new file mode 100644 index 0000000000..0319648f13 --- /dev/null +++ b/tests/components/pn7160_spi/test.esp32-idf.yaml @@ -0,0 +1,37 @@ +esphome: + on_boot: + then: + - tag.set_clean_mode: nfcc_pn7160 + - tag.set_format_mode: nfcc_pn7160 + - tag.set_read_mode: nfcc_pn7160 + - tag.set_write_message: + message: https://www.home-assistant.io/tag/pulse + include_android_app_record: false + - tag.set_write_mode: nfcc_pn7160 + - tag.set_emulation_message: + message: https://www.home-assistant.io/tag/pulse + include_android_app_record: false + - tag.emulation_off: nfcc_pn7160 + - tag.emulation_on: nfcc_pn7160 + - tag.polling_off: nfcc_pn7160 + - tag.polling_on: nfcc_pn7160 + +spi: + - id: spi_pn7160 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +pn7160_spi: + id: nfcc_pn7160 + cs_pin: 12 + irq_pin: 14 + ven_pin: 13 + emulation_message: https://www.home-assistant.io/tag/pulse_ce + tag_ttl: 1000ms + on_tag: + - logger.log: "Tag" + on_tag_removed: + - logger.log: "Tag removed" + on_emulated_tag_scan: + - logger.log: "Tag emulated" diff --git a/tests/components/pn7160_spi/test.esp32.yaml b/tests/components/pn7160_spi/test.esp32.yaml new file mode 100644 index 0000000000..0319648f13 --- /dev/null +++ b/tests/components/pn7160_spi/test.esp32.yaml @@ -0,0 +1,37 @@ +esphome: + on_boot: + then: + - tag.set_clean_mode: nfcc_pn7160 + - tag.set_format_mode: nfcc_pn7160 + - tag.set_read_mode: nfcc_pn7160 + - tag.set_write_message: + message: https://www.home-assistant.io/tag/pulse + include_android_app_record: false + - tag.set_write_mode: nfcc_pn7160 + - tag.set_emulation_message: + message: https://www.home-assistant.io/tag/pulse + include_android_app_record: false + - tag.emulation_off: nfcc_pn7160 + - tag.emulation_on: nfcc_pn7160 + - tag.polling_off: nfcc_pn7160 + - tag.polling_on: nfcc_pn7160 + +spi: + - id: spi_pn7160 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +pn7160_spi: + id: nfcc_pn7160 + cs_pin: 12 + irq_pin: 14 + ven_pin: 13 + emulation_message: https://www.home-assistant.io/tag/pulse_ce + tag_ttl: 1000ms + on_tag: + - logger.log: "Tag" + on_tag_removed: + - logger.log: "Tag removed" + on_emulated_tag_scan: + - logger.log: "Tag emulated" diff --git a/tests/components/pn7160_spi/test.esp8266.yaml b/tests/components/pn7160_spi/test.esp8266.yaml new file mode 100644 index 0000000000..fa356d5610 --- /dev/null +++ b/tests/components/pn7160_spi/test.esp8266.yaml @@ -0,0 +1,37 @@ +esphome: + on_boot: + then: + - tag.set_clean_mode: nfcc_pn7160 + - tag.set_format_mode: nfcc_pn7160 + - tag.set_read_mode: nfcc_pn7160 + - tag.set_write_message: + message: https://www.home-assistant.io/tag/pulse + include_android_app_record: false + - tag.set_write_mode: nfcc_pn7160 + - tag.set_emulation_message: + message: https://www.home-assistant.io/tag/pulse + include_android_app_record: false + - tag.emulation_off: nfcc_pn7160 + - tag.emulation_on: nfcc_pn7160 + - tag.polling_off: nfcc_pn7160 + - tag.polling_on: nfcc_pn7160 + +spi: + - id: spi_pn7160 + clk_pin: 14 + mosi_pin: 13 + miso_pin: 12 + +pn7160_spi: + id: nfcc_pn7160 + cs_pin: 15 + irq_pin: 4 + ven_pin: 5 + emulation_message: https://www.home-assistant.io/tag/pulse_ce + tag_ttl: 1000ms + on_tag: + - logger.log: "Tag" + on_tag_removed: + - logger.log: "Tag removed" + on_emulated_tag_scan: + - logger.log: "Tag emulated" diff --git a/tests/components/pn7160_spi/test.rp2040.yaml b/tests/components/pn7160_spi/test.rp2040.yaml new file mode 100644 index 0000000000..b36650032f --- /dev/null +++ b/tests/components/pn7160_spi/test.rp2040.yaml @@ -0,0 +1,37 @@ +esphome: + on_boot: + then: + - tag.set_clean_mode: nfcc_pn7160 + - tag.set_format_mode: nfcc_pn7160 + - tag.set_read_mode: nfcc_pn7160 + - tag.set_write_message: + message: https://www.home-assistant.io/tag/pulse + include_android_app_record: false + - tag.set_write_mode: nfcc_pn7160 + - tag.set_emulation_message: + message: https://www.home-assistant.io/tag/pulse + include_android_app_record: false + - tag.emulation_off: nfcc_pn7160 + - tag.emulation_on: nfcc_pn7160 + - tag.polling_off: nfcc_pn7160 + - tag.polling_on: nfcc_pn7160 + +spi: + - id: spi_pn7160 + clk_pin: 2 + mosi_pin: 3 + miso_pin: 4 + +pn7160_spi: + id: nfcc_pn7160 + cs_pin: 6 + irq_pin: 7 + ven_pin: 5 + emulation_message: https://www.home-assistant.io/tag/pulse_ce + tag_ttl: 1000ms + on_tag: + - logger.log: "Tag" + on_tag_removed: + - logger.log: "Tag removed" + on_emulated_tag_scan: + - logger.log: "Tag emulated" diff --git a/tests/components/power_supply/test.esp32-c3-idf.yaml b/tests/components/power_supply/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..3fefc4d425 --- /dev/null +++ b/tests/components/power_supply/test.esp32-c3-idf.yaml @@ -0,0 +1,6 @@ +power_supply: + - id: atx_power_supply + enable_time: 20ms + keep_on_time: 10s + enable_on_boot: true + pin: 4 diff --git a/tests/components/power_supply/test.esp32-c3.yaml b/tests/components/power_supply/test.esp32-c3.yaml new file mode 100644 index 0000000000..3fefc4d425 --- /dev/null +++ b/tests/components/power_supply/test.esp32-c3.yaml @@ -0,0 +1,6 @@ +power_supply: + - id: atx_power_supply + enable_time: 20ms + keep_on_time: 10s + enable_on_boot: true + pin: 4 diff --git a/tests/components/power_supply/test.esp32-idf.yaml b/tests/components/power_supply/test.esp32-idf.yaml new file mode 100644 index 0000000000..3fefc4d425 --- /dev/null +++ b/tests/components/power_supply/test.esp32-idf.yaml @@ -0,0 +1,6 @@ +power_supply: + - id: atx_power_supply + enable_time: 20ms + keep_on_time: 10s + enable_on_boot: true + pin: 4 diff --git a/tests/components/power_supply/test.esp32.yaml b/tests/components/power_supply/test.esp32.yaml new file mode 100644 index 0000000000..3fefc4d425 --- /dev/null +++ b/tests/components/power_supply/test.esp32.yaml @@ -0,0 +1,6 @@ +power_supply: + - id: atx_power_supply + enable_time: 20ms + keep_on_time: 10s + enable_on_boot: true + pin: 4 diff --git a/tests/components/power_supply/test.esp8266.yaml b/tests/components/power_supply/test.esp8266.yaml new file mode 100644 index 0000000000..3fefc4d425 --- /dev/null +++ b/tests/components/power_supply/test.esp8266.yaml @@ -0,0 +1,6 @@ +power_supply: + - id: atx_power_supply + enable_time: 20ms + keep_on_time: 10s + enable_on_boot: true + pin: 4 diff --git a/tests/components/power_supply/test.rp2040.yaml b/tests/components/power_supply/test.rp2040.yaml new file mode 100644 index 0000000000..3fefc4d425 --- /dev/null +++ b/tests/components/power_supply/test.rp2040.yaml @@ -0,0 +1,6 @@ +power_supply: + - id: atx_power_supply + enable_time: 20ms + keep_on_time: 10s + enable_on_boot: true + pin: 4 diff --git a/tests/components/prometheus/test.esp32-c3-idf.yaml b/tests/components/prometheus/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..c8ce17da88 --- /dev/null +++ b/tests/components/prometheus/test.esp32-c3-idf.yaml @@ -0,0 +1,21 @@ +wifi: + ssid: MySSID + password: password1 + +sensor: + - platform: template + id: template_sensor1 + lambda: |- + if (millis() > 10000) { + return 42.0; + } else { + return 0.0; + } + update_interval: 60s + +prometheus: + include_internal: true + relabel: + template_sensor1: + id: hellow_world + name: Hello World diff --git a/tests/components/prometheus/test.esp32-c3.yaml b/tests/components/prometheus/test.esp32-c3.yaml new file mode 100644 index 0000000000..c8ce17da88 --- /dev/null +++ b/tests/components/prometheus/test.esp32-c3.yaml @@ -0,0 +1,21 @@ +wifi: + ssid: MySSID + password: password1 + +sensor: + - platform: template + id: template_sensor1 + lambda: |- + if (millis() > 10000) { + return 42.0; + } else { + return 0.0; + } + update_interval: 60s + +prometheus: + include_internal: true + relabel: + template_sensor1: + id: hellow_world + name: Hello World diff --git a/tests/components/prometheus/test.esp32-idf.yaml b/tests/components/prometheus/test.esp32-idf.yaml new file mode 100644 index 0000000000..c8ce17da88 --- /dev/null +++ b/tests/components/prometheus/test.esp32-idf.yaml @@ -0,0 +1,21 @@ +wifi: + ssid: MySSID + password: password1 + +sensor: + - platform: template + id: template_sensor1 + lambda: |- + if (millis() > 10000) { + return 42.0; + } else { + return 0.0; + } + update_interval: 60s + +prometheus: + include_internal: true + relabel: + template_sensor1: + id: hellow_world + name: Hello World diff --git a/tests/components/prometheus/test.esp32.yaml b/tests/components/prometheus/test.esp32.yaml new file mode 100644 index 0000000000..c8ce17da88 --- /dev/null +++ b/tests/components/prometheus/test.esp32.yaml @@ -0,0 +1,21 @@ +wifi: + ssid: MySSID + password: password1 + +sensor: + - platform: template + id: template_sensor1 + lambda: |- + if (millis() > 10000) { + return 42.0; + } else { + return 0.0; + } + update_interval: 60s + +prometheus: + include_internal: true + relabel: + template_sensor1: + id: hellow_world + name: Hello World diff --git a/tests/components/prometheus/test.esp8266.yaml b/tests/components/prometheus/test.esp8266.yaml new file mode 100644 index 0000000000..c8ce17da88 --- /dev/null +++ b/tests/components/prometheus/test.esp8266.yaml @@ -0,0 +1,21 @@ +wifi: + ssid: MySSID + password: password1 + +sensor: + - platform: template + id: template_sensor1 + lambda: |- + if (millis() > 10000) { + return 42.0; + } else { + return 0.0; + } + update_interval: 60s + +prometheus: + include_internal: true + relabel: + template_sensor1: + id: hellow_world + name: Hello World diff --git a/tests/components/psram/test.esp32-c3-idf.yaml b/tests/components/psram/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..cfd39f77fe --- /dev/null +++ b/tests/components/psram/test.esp32-c3-idf.yaml @@ -0,0 +1,3 @@ +psram: + mode: octal + speed: 80MHz diff --git a/tests/components/psram/test.esp32-c3.yaml b/tests/components/psram/test.esp32-c3.yaml new file mode 100644 index 0000000000..cfd39f77fe --- /dev/null +++ b/tests/components/psram/test.esp32-c3.yaml @@ -0,0 +1,3 @@ +psram: + mode: octal + speed: 80MHz diff --git a/tests/components/psram/test.esp32-idf.yaml b/tests/components/psram/test.esp32-idf.yaml new file mode 100644 index 0000000000..cfd39f77fe --- /dev/null +++ b/tests/components/psram/test.esp32-idf.yaml @@ -0,0 +1,3 @@ +psram: + mode: octal + speed: 80MHz diff --git a/tests/components/psram/test.esp32.yaml b/tests/components/psram/test.esp32.yaml new file mode 100644 index 0000000000..cfd39f77fe --- /dev/null +++ b/tests/components/psram/test.esp32.yaml @@ -0,0 +1,3 @@ +psram: + mode: octal + speed: 80MHz diff --git a/tests/components/pulse_counter/test.esp32-c3-idf.yaml b/tests/components/pulse_counter/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..556b43ee6f --- /dev/null +++ b/tests/components/pulse_counter/test.esp32-c3-idf.yaml @@ -0,0 +1,9 @@ +sensor: + - platform: pulse_counter + name: Pulse Counter + pin: 4 + count_mode: + rising_edge: INCREMENT + falling_edge: DECREMENT + internal_filter: 13us + update_interval: 15s diff --git a/tests/components/pulse_counter/test.esp32-c3.yaml b/tests/components/pulse_counter/test.esp32-c3.yaml new file mode 100644 index 0000000000..556b43ee6f --- /dev/null +++ b/tests/components/pulse_counter/test.esp32-c3.yaml @@ -0,0 +1,9 @@ +sensor: + - platform: pulse_counter + name: Pulse Counter + pin: 4 + count_mode: + rising_edge: INCREMENT + falling_edge: DECREMENT + internal_filter: 13us + update_interval: 15s diff --git a/tests/components/pulse_counter/test.esp32-idf.yaml b/tests/components/pulse_counter/test.esp32-idf.yaml new file mode 100644 index 0000000000..556b43ee6f --- /dev/null +++ b/tests/components/pulse_counter/test.esp32-idf.yaml @@ -0,0 +1,9 @@ +sensor: + - platform: pulse_counter + name: Pulse Counter + pin: 4 + count_mode: + rising_edge: INCREMENT + falling_edge: DECREMENT + internal_filter: 13us + update_interval: 15s diff --git a/tests/components/pulse_counter/test.esp32.yaml b/tests/components/pulse_counter/test.esp32.yaml new file mode 100644 index 0000000000..556b43ee6f --- /dev/null +++ b/tests/components/pulse_counter/test.esp32.yaml @@ -0,0 +1,9 @@ +sensor: + - platform: pulse_counter + name: Pulse Counter + pin: 4 + count_mode: + rising_edge: INCREMENT + falling_edge: DECREMENT + internal_filter: 13us + update_interval: 15s diff --git a/tests/components/pulse_counter/test.esp8266.yaml b/tests/components/pulse_counter/test.esp8266.yaml new file mode 100644 index 0000000000..556b43ee6f --- /dev/null +++ b/tests/components/pulse_counter/test.esp8266.yaml @@ -0,0 +1,9 @@ +sensor: + - platform: pulse_counter + name: Pulse Counter + pin: 4 + count_mode: + rising_edge: INCREMENT + falling_edge: DECREMENT + internal_filter: 13us + update_interval: 15s diff --git a/tests/components/pulse_counter/test.rp2040.yaml b/tests/components/pulse_counter/test.rp2040.yaml new file mode 100644 index 0000000000..556b43ee6f --- /dev/null +++ b/tests/components/pulse_counter/test.rp2040.yaml @@ -0,0 +1,9 @@ +sensor: + - platform: pulse_counter + name: Pulse Counter + pin: 4 + count_mode: + rising_edge: INCREMENT + falling_edge: DECREMENT + internal_filter: 13us + update_interval: 15s diff --git a/tests/components/pulse_meter/test.esp32-c3-idf.yaml b/tests/components/pulse_meter/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..a83ec478bb --- /dev/null +++ b/tests/components/pulse_meter/test.esp32-c3-idf.yaml @@ -0,0 +1,13 @@ +sensor: + - platform: pulse_meter + id: pulse_meter_sensor + name: Pulse Meter + pin: 4 + internal_filter: 100ms + timeout: 2 min + on_value: + - pulse_meter.set_total_pulses: + id: pulse_meter_sensor + value: 12345 + total: + name: Pulse Meter Total diff --git a/tests/components/pulse_meter/test.esp32-c3.yaml b/tests/components/pulse_meter/test.esp32-c3.yaml new file mode 100644 index 0000000000..a83ec478bb --- /dev/null +++ b/tests/components/pulse_meter/test.esp32-c3.yaml @@ -0,0 +1,13 @@ +sensor: + - platform: pulse_meter + id: pulse_meter_sensor + name: Pulse Meter + pin: 4 + internal_filter: 100ms + timeout: 2 min + on_value: + - pulse_meter.set_total_pulses: + id: pulse_meter_sensor + value: 12345 + total: + name: Pulse Meter Total diff --git a/tests/components/pulse_meter/test.esp32-idf.yaml b/tests/components/pulse_meter/test.esp32-idf.yaml new file mode 100644 index 0000000000..a83ec478bb --- /dev/null +++ b/tests/components/pulse_meter/test.esp32-idf.yaml @@ -0,0 +1,13 @@ +sensor: + - platform: pulse_meter + id: pulse_meter_sensor + name: Pulse Meter + pin: 4 + internal_filter: 100ms + timeout: 2 min + on_value: + - pulse_meter.set_total_pulses: + id: pulse_meter_sensor + value: 12345 + total: + name: Pulse Meter Total diff --git a/tests/components/pulse_meter/test.esp32.yaml b/tests/components/pulse_meter/test.esp32.yaml new file mode 100644 index 0000000000..a83ec478bb --- /dev/null +++ b/tests/components/pulse_meter/test.esp32.yaml @@ -0,0 +1,13 @@ +sensor: + - platform: pulse_meter + id: pulse_meter_sensor + name: Pulse Meter + pin: 4 + internal_filter: 100ms + timeout: 2 min + on_value: + - pulse_meter.set_total_pulses: + id: pulse_meter_sensor + value: 12345 + total: + name: Pulse Meter Total diff --git a/tests/components/pulse_meter/test.esp8266.yaml b/tests/components/pulse_meter/test.esp8266.yaml new file mode 100644 index 0000000000..a83ec478bb --- /dev/null +++ b/tests/components/pulse_meter/test.esp8266.yaml @@ -0,0 +1,13 @@ +sensor: + - platform: pulse_meter + id: pulse_meter_sensor + name: Pulse Meter + pin: 4 + internal_filter: 100ms + timeout: 2 min + on_value: + - pulse_meter.set_total_pulses: + id: pulse_meter_sensor + value: 12345 + total: + name: Pulse Meter Total diff --git a/tests/components/pulse_meter/test.rp2040.yaml b/tests/components/pulse_meter/test.rp2040.yaml new file mode 100644 index 0000000000..a83ec478bb --- /dev/null +++ b/tests/components/pulse_meter/test.rp2040.yaml @@ -0,0 +1,13 @@ +sensor: + - platform: pulse_meter + id: pulse_meter_sensor + name: Pulse Meter + pin: 4 + internal_filter: 100ms + timeout: 2 min + on_value: + - pulse_meter.set_total_pulses: + id: pulse_meter_sensor + value: 12345 + total: + name: Pulse Meter Total diff --git a/tests/components/pulse_width/test.esp32-c3-idf.yaml b/tests/components/pulse_width/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..fbda7cda28 --- /dev/null +++ b/tests/components/pulse_width/test.esp32-c3-idf.yaml @@ -0,0 +1,4 @@ +sensor: + - platform: pulse_width + name: Pulse Width + pin: 4 diff --git a/tests/components/pulse_width/test.esp32-c3.yaml b/tests/components/pulse_width/test.esp32-c3.yaml new file mode 100644 index 0000000000..fbda7cda28 --- /dev/null +++ b/tests/components/pulse_width/test.esp32-c3.yaml @@ -0,0 +1,4 @@ +sensor: + - platform: pulse_width + name: Pulse Width + pin: 4 diff --git a/tests/components/pulse_width/test.esp32-idf.yaml b/tests/components/pulse_width/test.esp32-idf.yaml new file mode 100644 index 0000000000..fbda7cda28 --- /dev/null +++ b/tests/components/pulse_width/test.esp32-idf.yaml @@ -0,0 +1,4 @@ +sensor: + - platform: pulse_width + name: Pulse Width + pin: 4 diff --git a/tests/components/pulse_width/test.esp32.yaml b/tests/components/pulse_width/test.esp32.yaml new file mode 100644 index 0000000000..fbda7cda28 --- /dev/null +++ b/tests/components/pulse_width/test.esp32.yaml @@ -0,0 +1,4 @@ +sensor: + - platform: pulse_width + name: Pulse Width + pin: 4 diff --git a/tests/components/pulse_width/test.esp8266.yaml b/tests/components/pulse_width/test.esp8266.yaml new file mode 100644 index 0000000000..fbda7cda28 --- /dev/null +++ b/tests/components/pulse_width/test.esp8266.yaml @@ -0,0 +1,4 @@ +sensor: + - platform: pulse_width + name: Pulse Width + pin: 4 diff --git a/tests/components/pulse_width/test.rp2040.yaml b/tests/components/pulse_width/test.rp2040.yaml new file mode 100644 index 0000000000..fbda7cda28 --- /dev/null +++ b/tests/components/pulse_width/test.rp2040.yaml @@ -0,0 +1,4 @@ +sensor: + - platform: pulse_width + name: Pulse Width + pin: 4 diff --git a/tests/components/pvvx_mithermometer/test.esp32-c3-idf.yaml b/tests/components/pvvx_mithermometer/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..972f23122c --- /dev/null +++ b/tests/components/pvvx_mithermometer/test.esp32-c3-idf.yaml @@ -0,0 +1,44 @@ +wifi: + ssid: MySSID + password: password1 + +esp32_ble_tracker: + +ble_client: + - mac_address: 01:02:03:04:05:06 + id: pvvx_ble_display + +display: + - platform: pvvx_mithermometer + ble_client_id: pvvx_ble_display + time_id: sntp_time + disconnect_delay: 3s + update_interval: 10min + validity_period: 20min + lambda: |- + it.print_bignum(188.8); + it.print_unit(pvvx_mithermometer::UNIT_DEG_E); + it.print_smallnum(88); + it.print_percent(true); + it.print_happy(true); + it.print_sad(true); + it.print_bracket(true); + it.print_battery(true); + +sensor: + - platform: pvvx_mithermometer + mac_address: A4:C1:38:4E:16:78 + temperature: + name: PVVX Temperature + humidity: + name: PVVX Humidity + battery_level: + name: PVVX Battery-Level + battery_voltage: + name: PVVX Battery-Voltage + +time: + - platform: sntp + id: sntp_time + servers: + - 0.pool.ntp.org diff --git a/tests/components/pvvx_mithermometer/test.esp32-c3.yaml b/tests/components/pvvx_mithermometer/test.esp32-c3.yaml new file mode 100644 index 0000000000..972f23122c --- /dev/null +++ b/tests/components/pvvx_mithermometer/test.esp32-c3.yaml @@ -0,0 +1,44 @@ +wifi: + ssid: MySSID + password: password1 + +esp32_ble_tracker: + +ble_client: + - mac_address: 01:02:03:04:05:06 + id: pvvx_ble_display + +display: + - platform: pvvx_mithermometer + ble_client_id: pvvx_ble_display + time_id: sntp_time + disconnect_delay: 3s + update_interval: 10min + validity_period: 20min + lambda: |- + it.print_bignum(188.8); + it.print_unit(pvvx_mithermometer::UNIT_DEG_E); + it.print_smallnum(88); + it.print_percent(true); + it.print_happy(true); + it.print_sad(true); + it.print_bracket(true); + it.print_battery(true); + +sensor: + - platform: pvvx_mithermometer + mac_address: A4:C1:38:4E:16:78 + temperature: + name: PVVX Temperature + humidity: + name: PVVX Humidity + battery_level: + name: PVVX Battery-Level + battery_voltage: + name: PVVX Battery-Voltage + +time: + - platform: sntp + id: sntp_time + servers: + - 0.pool.ntp.org diff --git a/tests/components/pvvx_mithermometer/test.esp32-idf.yaml b/tests/components/pvvx_mithermometer/test.esp32-idf.yaml new file mode 100644 index 0000000000..972f23122c --- /dev/null +++ b/tests/components/pvvx_mithermometer/test.esp32-idf.yaml @@ -0,0 +1,44 @@ +wifi: + ssid: MySSID + password: password1 + +esp32_ble_tracker: + +ble_client: + - mac_address: 01:02:03:04:05:06 + id: pvvx_ble_display + +display: + - platform: pvvx_mithermometer + ble_client_id: pvvx_ble_display + time_id: sntp_time + disconnect_delay: 3s + update_interval: 10min + validity_period: 20min + lambda: |- + it.print_bignum(188.8); + it.print_unit(pvvx_mithermometer::UNIT_DEG_E); + it.print_smallnum(88); + it.print_percent(true); + it.print_happy(true); + it.print_sad(true); + it.print_bracket(true); + it.print_battery(true); + +sensor: + - platform: pvvx_mithermometer + mac_address: A4:C1:38:4E:16:78 + temperature: + name: PVVX Temperature + humidity: + name: PVVX Humidity + battery_level: + name: PVVX Battery-Level + battery_voltage: + name: PVVX Battery-Voltage + +time: + - platform: sntp + id: sntp_time + servers: + - 0.pool.ntp.org diff --git a/tests/components/pvvx_mithermometer/test.esp32.yaml b/tests/components/pvvx_mithermometer/test.esp32.yaml new file mode 100644 index 0000000000..972f23122c --- /dev/null +++ b/tests/components/pvvx_mithermometer/test.esp32.yaml @@ -0,0 +1,44 @@ +wifi: + ssid: MySSID + password: password1 + +esp32_ble_tracker: + +ble_client: + - mac_address: 01:02:03:04:05:06 + id: pvvx_ble_display + +display: + - platform: pvvx_mithermometer + ble_client_id: pvvx_ble_display + time_id: sntp_time + disconnect_delay: 3s + update_interval: 10min + validity_period: 20min + lambda: |- + it.print_bignum(188.8); + it.print_unit(pvvx_mithermometer::UNIT_DEG_E); + it.print_smallnum(88); + it.print_percent(true); + it.print_happy(true); + it.print_sad(true); + it.print_bracket(true); + it.print_battery(true); + +sensor: + - platform: pvvx_mithermometer + mac_address: A4:C1:38:4E:16:78 + temperature: + name: PVVX Temperature + humidity: + name: PVVX Humidity + battery_level: + name: PVVX Battery-Level + battery_voltage: + name: PVVX Battery-Voltage + +time: + - platform: sntp + id: sntp_time + servers: + - 0.pool.ntp.org diff --git a/tests/components/pylontech/test.esp32-c3-idf.yaml b/tests/components/pylontech/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..f7ec493422 --- /dev/null +++ b/tests/components/pylontech/test.esp32-c3-idf.yaml @@ -0,0 +1,48 @@ +uart: + - id: uart_pylontech0 + tx_pin: 4 + rx_pin: 5 + baud_rate: 115200 + +pylontech: + - id: pylontech0 + - id: pylontech1 + +sensor: + - platform: pylontech + pylontech_id: pylontech0 + battery: 1 + voltage: + id: pyl01_voltage + current: + id: pyl01_current + coulomb: + id: pyl01_soc + mos_temperature: + id: pyl01_mos_temperature + - platform: pylontech + pylontech_id: pylontech1 + battery: 1 + voltage: + id: pyl13_voltage + temperature_low: + id: pyl13_temperature_low + temperature_high: + id: pyl13_temperature_high + voltage_low: + id: pyl13_voltage_low + voltage_high: + id: pyl13_voltage_high + +text_sensor: + - platform: pylontech + pylontech_id: pylontech0 + battery: 1 + base_state: + id: pyl0_base_state + voltage_state: + id: pyl0_voltage_state + current_state: + id: pyl0_current_state + temperature_state: + id: pyl0_temperature_state diff --git a/tests/components/pylontech/test.esp32-c3.yaml b/tests/components/pylontech/test.esp32-c3.yaml new file mode 100644 index 0000000000..f7ec493422 --- /dev/null +++ b/tests/components/pylontech/test.esp32-c3.yaml @@ -0,0 +1,48 @@ +uart: + - id: uart_pylontech0 + tx_pin: 4 + rx_pin: 5 + baud_rate: 115200 + +pylontech: + - id: pylontech0 + - id: pylontech1 + +sensor: + - platform: pylontech + pylontech_id: pylontech0 + battery: 1 + voltage: + id: pyl01_voltage + current: + id: pyl01_current + coulomb: + id: pyl01_soc + mos_temperature: + id: pyl01_mos_temperature + - platform: pylontech + pylontech_id: pylontech1 + battery: 1 + voltage: + id: pyl13_voltage + temperature_low: + id: pyl13_temperature_low + temperature_high: + id: pyl13_temperature_high + voltage_low: + id: pyl13_voltage_low + voltage_high: + id: pyl13_voltage_high + +text_sensor: + - platform: pylontech + pylontech_id: pylontech0 + battery: 1 + base_state: + id: pyl0_base_state + voltage_state: + id: pyl0_voltage_state + current_state: + id: pyl0_current_state + temperature_state: + id: pyl0_temperature_state diff --git a/tests/components/pylontech/test.esp32-idf.yaml b/tests/components/pylontech/test.esp32-idf.yaml new file mode 100644 index 0000000000..a4c168fb47 --- /dev/null +++ b/tests/components/pylontech/test.esp32-idf.yaml @@ -0,0 +1,48 @@ +uart: + - id: uart_pylontech0 + tx_pin: 17 + rx_pin: 16 + baud_rate: 115200 + +pylontech: + - id: pylontech0 + - id: pylontech1 + +sensor: + - platform: pylontech + pylontech_id: pylontech0 + battery: 1 + voltage: + id: pyl01_voltage + current: + id: pyl01_current + coulomb: + id: pyl01_soc + mos_temperature: + id: pyl01_mos_temperature + - platform: pylontech + pylontech_id: pylontech1 + battery: 1 + voltage: + id: pyl13_voltage + temperature_low: + id: pyl13_temperature_low + temperature_high: + id: pyl13_temperature_high + voltage_low: + id: pyl13_voltage_low + voltage_high: + id: pyl13_voltage_high + +text_sensor: + - platform: pylontech + pylontech_id: pylontech0 + battery: 1 + base_state: + id: pyl0_base_state + voltage_state: + id: pyl0_voltage_state + current_state: + id: pyl0_current_state + temperature_state: + id: pyl0_temperature_state diff --git a/tests/components/pylontech/test.esp32.yaml b/tests/components/pylontech/test.esp32.yaml new file mode 100644 index 0000000000..a4c168fb47 --- /dev/null +++ b/tests/components/pylontech/test.esp32.yaml @@ -0,0 +1,48 @@ +uart: + - id: uart_pylontech0 + tx_pin: 17 + rx_pin: 16 + baud_rate: 115200 + +pylontech: + - id: pylontech0 + - id: pylontech1 + +sensor: + - platform: pylontech + pylontech_id: pylontech0 + battery: 1 + voltage: + id: pyl01_voltage + current: + id: pyl01_current + coulomb: + id: pyl01_soc + mos_temperature: + id: pyl01_mos_temperature + - platform: pylontech + pylontech_id: pylontech1 + battery: 1 + voltage: + id: pyl13_voltage + temperature_low: + id: pyl13_temperature_low + temperature_high: + id: pyl13_temperature_high + voltage_low: + id: pyl13_voltage_low + voltage_high: + id: pyl13_voltage_high + +text_sensor: + - platform: pylontech + pylontech_id: pylontech0 + battery: 1 + base_state: + id: pyl0_base_state + voltage_state: + id: pyl0_voltage_state + current_state: + id: pyl0_current_state + temperature_state: + id: pyl0_temperature_state diff --git a/tests/components/pylontech/test.esp8266.yaml b/tests/components/pylontech/test.esp8266.yaml new file mode 100644 index 0000000000..f7ec493422 --- /dev/null +++ b/tests/components/pylontech/test.esp8266.yaml @@ -0,0 +1,48 @@ +uart: + - id: uart_pylontech0 + tx_pin: 4 + rx_pin: 5 + baud_rate: 115200 + +pylontech: + - id: pylontech0 + - id: pylontech1 + +sensor: + - platform: pylontech + pylontech_id: pylontech0 + battery: 1 + voltage: + id: pyl01_voltage + current: + id: pyl01_current + coulomb: + id: pyl01_soc + mos_temperature: + id: pyl01_mos_temperature + - platform: pylontech + pylontech_id: pylontech1 + battery: 1 + voltage: + id: pyl13_voltage + temperature_low: + id: pyl13_temperature_low + temperature_high: + id: pyl13_temperature_high + voltage_low: + id: pyl13_voltage_low + voltage_high: + id: pyl13_voltage_high + +text_sensor: + - platform: pylontech + pylontech_id: pylontech0 + battery: 1 + base_state: + id: pyl0_base_state + voltage_state: + id: pyl0_voltage_state + current_state: + id: pyl0_current_state + temperature_state: + id: pyl0_temperature_state diff --git a/tests/components/pylontech/test.rp2040.yaml b/tests/components/pylontech/test.rp2040.yaml new file mode 100644 index 0000000000..f7ec493422 --- /dev/null +++ b/tests/components/pylontech/test.rp2040.yaml @@ -0,0 +1,48 @@ +uart: + - id: uart_pylontech0 + tx_pin: 4 + rx_pin: 5 + baud_rate: 115200 + +pylontech: + - id: pylontech0 + - id: pylontech1 + +sensor: + - platform: pylontech + pylontech_id: pylontech0 + battery: 1 + voltage: + id: pyl01_voltage + current: + id: pyl01_current + coulomb: + id: pyl01_soc + mos_temperature: + id: pyl01_mos_temperature + - platform: pylontech + pylontech_id: pylontech1 + battery: 1 + voltage: + id: pyl13_voltage + temperature_low: + id: pyl13_temperature_low + temperature_high: + id: pyl13_temperature_high + voltage_low: + id: pyl13_voltage_low + voltage_high: + id: pyl13_voltage_high + +text_sensor: + - platform: pylontech + pylontech_id: pylontech0 + battery: 1 + base_state: + id: pyl0_base_state + voltage_state: + id: pyl0_voltage_state + current_state: + id: pyl0_current_state + temperature_state: + id: pyl0_temperature_state diff --git a/tests/components/pzem004t/test.esp32-c3-idf.yaml b/tests/components/pzem004t/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..b9c93f8761 --- /dev/null +++ b/tests/components/pzem004t/test.esp32-c3-idf.yaml @@ -0,0 +1,14 @@ +uart: + - id: uart_pzem004t + tx_pin: 4 + rx_pin: 5 + baud_rate: 115200 + +sensor: + - platform: pzem004t + voltage: + name: PZEM004T Voltage + current: + name: PZEM004T Current + power: + name: PZEM004T Power diff --git a/tests/components/pzem004t/test.esp32-c3.yaml b/tests/components/pzem004t/test.esp32-c3.yaml new file mode 100644 index 0000000000..b9c93f8761 --- /dev/null +++ b/tests/components/pzem004t/test.esp32-c3.yaml @@ -0,0 +1,14 @@ +uart: + - id: uart_pzem004t + tx_pin: 4 + rx_pin: 5 + baud_rate: 115200 + +sensor: + - platform: pzem004t + voltage: + name: PZEM004T Voltage + current: + name: PZEM004T Current + power: + name: PZEM004T Power diff --git a/tests/components/pzem004t/test.esp32-idf.yaml b/tests/components/pzem004t/test.esp32-idf.yaml new file mode 100644 index 0000000000..23f2bd0eca --- /dev/null +++ b/tests/components/pzem004t/test.esp32-idf.yaml @@ -0,0 +1,14 @@ +uart: + - id: uart_pzem004t + tx_pin: 17 + rx_pin: 16 + baud_rate: 115200 + +sensor: + - platform: pzem004t + voltage: + name: PZEM004T Voltage + current: + name: PZEM004T Current + power: + name: PZEM004T Power diff --git a/tests/components/pzem004t/test.esp32.yaml b/tests/components/pzem004t/test.esp32.yaml new file mode 100644 index 0000000000..23f2bd0eca --- /dev/null +++ b/tests/components/pzem004t/test.esp32.yaml @@ -0,0 +1,14 @@ +uart: + - id: uart_pzem004t + tx_pin: 17 + rx_pin: 16 + baud_rate: 115200 + +sensor: + - platform: pzem004t + voltage: + name: PZEM004T Voltage + current: + name: PZEM004T Current + power: + name: PZEM004T Power diff --git a/tests/components/pzem004t/test.esp8266.yaml b/tests/components/pzem004t/test.esp8266.yaml new file mode 100644 index 0000000000..b9c93f8761 --- /dev/null +++ b/tests/components/pzem004t/test.esp8266.yaml @@ -0,0 +1,14 @@ +uart: + - id: uart_pzem004t + tx_pin: 4 + rx_pin: 5 + baud_rate: 115200 + +sensor: + - platform: pzem004t + voltage: + name: PZEM004T Voltage + current: + name: PZEM004T Current + power: + name: PZEM004T Power diff --git a/tests/components/pzem004t/test.rp2040.yaml b/tests/components/pzem004t/test.rp2040.yaml new file mode 100644 index 0000000000..b9c93f8761 --- /dev/null +++ b/tests/components/pzem004t/test.rp2040.yaml @@ -0,0 +1,14 @@ +uart: + - id: uart_pzem004t + tx_pin: 4 + rx_pin: 5 + baud_rate: 115200 + +sensor: + - platform: pzem004t + voltage: + name: PZEM004T Voltage + current: + name: PZEM004T Current + power: + name: PZEM004T Power diff --git a/tests/components/pzemac/test.esp32-c3-idf.yaml b/tests/components/pzemac/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..6d9abbebe9 --- /dev/null +++ b/tests/components/pzemac/test.esp32-c3-idf.yaml @@ -0,0 +1,28 @@ +esphome: + on_boot: + then: + - pzemac.reset_energy: pzemac1 + +uart: + - id: uart_pzemac + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +modbus: + +sensor: + - platform: pzemac + id: pzemac1 + voltage: + name: PZEMAC Voltage + current: + name: PZEMAC Current + power: + name: PZEMAC Power + energy: + name: PZEMAC Energy + frequency: + name: PZEMAC Frequency + power_factor: + name: PZEMAC Power Factor diff --git a/tests/components/pzemac/test.esp32-c3.yaml b/tests/components/pzemac/test.esp32-c3.yaml new file mode 100644 index 0000000000..6d9abbebe9 --- /dev/null +++ b/tests/components/pzemac/test.esp32-c3.yaml @@ -0,0 +1,28 @@ +esphome: + on_boot: + then: + - pzemac.reset_energy: pzemac1 + +uart: + - id: uart_pzemac + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +modbus: + +sensor: + - platform: pzemac + id: pzemac1 + voltage: + name: PZEMAC Voltage + current: + name: PZEMAC Current + power: + name: PZEMAC Power + energy: + name: PZEMAC Energy + frequency: + name: PZEMAC Frequency + power_factor: + name: PZEMAC Power Factor diff --git a/tests/components/pzemac/test.esp32-idf.yaml b/tests/components/pzemac/test.esp32-idf.yaml new file mode 100644 index 0000000000..ce431a6100 --- /dev/null +++ b/tests/components/pzemac/test.esp32-idf.yaml @@ -0,0 +1,28 @@ +esphome: + on_boot: + then: + - pzemac.reset_energy: pzemac1 + +uart: + - id: uart_pzemac + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +modbus: + +sensor: + - platform: pzemac + id: pzemac1 + voltage: + name: PZEMAC Voltage + current: + name: PZEMAC Current + power: + name: PZEMAC Power + energy: + name: PZEMAC Energy + frequency: + name: PZEMAC Frequency + power_factor: + name: PZEMAC Power Factor diff --git a/tests/components/pzemac/test.esp32.yaml b/tests/components/pzemac/test.esp32.yaml new file mode 100644 index 0000000000..ce431a6100 --- /dev/null +++ b/tests/components/pzemac/test.esp32.yaml @@ -0,0 +1,28 @@ +esphome: + on_boot: + then: + - pzemac.reset_energy: pzemac1 + +uart: + - id: uart_pzemac + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +modbus: + +sensor: + - platform: pzemac + id: pzemac1 + voltage: + name: PZEMAC Voltage + current: + name: PZEMAC Current + power: + name: PZEMAC Power + energy: + name: PZEMAC Energy + frequency: + name: PZEMAC Frequency + power_factor: + name: PZEMAC Power Factor diff --git a/tests/components/pzemac/test.esp8266.yaml b/tests/components/pzemac/test.esp8266.yaml new file mode 100644 index 0000000000..6d9abbebe9 --- /dev/null +++ b/tests/components/pzemac/test.esp8266.yaml @@ -0,0 +1,28 @@ +esphome: + on_boot: + then: + - pzemac.reset_energy: pzemac1 + +uart: + - id: uart_pzemac + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +modbus: + +sensor: + - platform: pzemac + id: pzemac1 + voltage: + name: PZEMAC Voltage + current: + name: PZEMAC Current + power: + name: PZEMAC Power + energy: + name: PZEMAC Energy + frequency: + name: PZEMAC Frequency + power_factor: + name: PZEMAC Power Factor diff --git a/tests/components/pzemac/test.rp2040.yaml b/tests/components/pzemac/test.rp2040.yaml new file mode 100644 index 0000000000..6d9abbebe9 --- /dev/null +++ b/tests/components/pzemac/test.rp2040.yaml @@ -0,0 +1,28 @@ +esphome: + on_boot: + then: + - pzemac.reset_energy: pzemac1 + +uart: + - id: uart_pzemac + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +modbus: + +sensor: + - platform: pzemac + id: pzemac1 + voltage: + name: PZEMAC Voltage + current: + name: PZEMAC Current + power: + name: PZEMAC Power + energy: + name: PZEMAC Energy + frequency: + name: PZEMAC Frequency + power_factor: + name: PZEMAC Power Factor diff --git a/tests/components/pzemdc/test.esp32-c3-idf.yaml b/tests/components/pzemdc/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..02114b781d --- /dev/null +++ b/tests/components/pzemdc/test.esp32-c3-idf.yaml @@ -0,0 +1,23 @@ +esphome: + on_boot: + then: + - pzemdc.reset_energy: pzemdc1 + +uart: + - id: uart_pzemdc + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + stop_bits: 2 + +sensor: + - platform: pzemdc + id: pzemdc1 + voltage: + name: PZEMDC Voltage + current: + name: PZEMDC Current + power: + name: PZEMDC Power + energy: + name: PZEMDC Energy diff --git a/tests/components/pzemdc/test.esp32-c3.yaml b/tests/components/pzemdc/test.esp32-c3.yaml new file mode 100644 index 0000000000..02114b781d --- /dev/null +++ b/tests/components/pzemdc/test.esp32-c3.yaml @@ -0,0 +1,23 @@ +esphome: + on_boot: + then: + - pzemdc.reset_energy: pzemdc1 + +uart: + - id: uart_pzemdc + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + stop_bits: 2 + +sensor: + - platform: pzemdc + id: pzemdc1 + voltage: + name: PZEMDC Voltage + current: + name: PZEMDC Current + power: + name: PZEMDC Power + energy: + name: PZEMDC Energy diff --git a/tests/components/pzemdc/test.esp32-idf.yaml b/tests/components/pzemdc/test.esp32-idf.yaml new file mode 100644 index 0000000000..9cc61137de --- /dev/null +++ b/tests/components/pzemdc/test.esp32-idf.yaml @@ -0,0 +1,23 @@ +esphome: + on_boot: + then: + - pzemdc.reset_energy: pzemdc1 + +uart: + - id: uart_pzemdc + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + stop_bits: 2 + +sensor: + - platform: pzemdc + id: pzemdc1 + voltage: + name: PZEMDC Voltage + current: + name: PZEMDC Current + power: + name: PZEMDC Power + energy: + name: PZEMDC Energy diff --git a/tests/components/pzemdc/test.esp32.yaml b/tests/components/pzemdc/test.esp32.yaml new file mode 100644 index 0000000000..9cc61137de --- /dev/null +++ b/tests/components/pzemdc/test.esp32.yaml @@ -0,0 +1,23 @@ +esphome: + on_boot: + then: + - pzemdc.reset_energy: pzemdc1 + +uart: + - id: uart_pzemdc + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + stop_bits: 2 + +sensor: + - platform: pzemdc + id: pzemdc1 + voltage: + name: PZEMDC Voltage + current: + name: PZEMDC Current + power: + name: PZEMDC Power + energy: + name: PZEMDC Energy diff --git a/tests/components/pzemdc/test.esp8266.yaml b/tests/components/pzemdc/test.esp8266.yaml new file mode 100644 index 0000000000..02114b781d --- /dev/null +++ b/tests/components/pzemdc/test.esp8266.yaml @@ -0,0 +1,23 @@ +esphome: + on_boot: + then: + - pzemdc.reset_energy: pzemdc1 + +uart: + - id: uart_pzemdc + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + stop_bits: 2 + +sensor: + - platform: pzemdc + id: pzemdc1 + voltage: + name: PZEMDC Voltage + current: + name: PZEMDC Current + power: + name: PZEMDC Power + energy: + name: PZEMDC Energy diff --git a/tests/components/pzemdc/test.rp2040.yaml b/tests/components/pzemdc/test.rp2040.yaml new file mode 100644 index 0000000000..02114b781d --- /dev/null +++ b/tests/components/pzemdc/test.rp2040.yaml @@ -0,0 +1,23 @@ +esphome: + on_boot: + then: + - pzemdc.reset_energy: pzemdc1 + +uart: + - id: uart_pzemdc + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + stop_bits: 2 + +sensor: + - platform: pzemdc + id: pzemdc1 + voltage: + name: PZEMDC Voltage + current: + name: PZEMDC Current + power: + name: PZEMDC Power + energy: + name: PZEMDC Energy From 2b215fecc953496d62db17407ec04f85d27abe23 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Mon, 22 Apr 2024 22:45:12 -0500 Subject: [PATCH 1302/2101] Add some components to the new testing framework (M part 1) (#6207) --- .../matrix_keypad/test.esp32-c3-idf.yaml | 19 ++++++++ .../matrix_keypad/test.esp32-c3.yaml | 19 ++++++++ .../matrix_keypad/test.esp32-idf.yaml | 19 ++++++++ .../components/matrix_keypad/test.esp32.yaml | 19 ++++++++ .../matrix_keypad/test.esp8266.yaml | 19 ++++++++ .../components/matrix_keypad/test.rp2040.yaml | 19 ++++++++ .../max31855/test.esp32-c3-idf.yaml | 13 ++++++ tests/components/max31855/test.esp32-c3.yaml | 13 ++++++ tests/components/max31855/test.esp32-idf.yaml | 13 ++++++ tests/components/max31855/test.esp32.yaml | 13 ++++++ tests/components/max31855/test.esp8266.yaml | 13 ++++++ tests/components/max31855/test.rp2040.yaml | 13 ++++++ .../max31856/test.esp32-c3-idf.yaml | 12 +++++ tests/components/max31856/test.esp32-c3.yaml | 12 +++++ tests/components/max31856/test.esp32-idf.yaml | 12 +++++ tests/components/max31856/test.esp32.yaml | 12 +++++ tests/components/max31856/test.esp8266.yaml | 12 +++++ tests/components/max31856/test.rp2040.yaml | 12 +++++ .../max31865/test.esp32-c3-idf.yaml | 13 ++++++ tests/components/max31865/test.esp32-c3.yaml | 13 ++++++ tests/components/max31865/test.esp32-idf.yaml | 13 ++++++ tests/components/max31865/test.esp32.yaml | 13 ++++++ tests/components/max31865/test.esp8266.yaml | 13 ++++++ tests/components/max31865/test.rp2040.yaml | 13 ++++++ .../max44009/test.esp32-c3-idf.yaml | 12 +++++ tests/components/max44009/test.esp32-c3.yaml | 12 +++++ tests/components/max44009/test.esp32-idf.yaml | 12 +++++ tests/components/max44009/test.esp32.yaml | 12 +++++ tests/components/max44009/test.esp8266.yaml | 12 +++++ tests/components/max44009/test.rp2040.yaml | 12 +++++ .../components/max6675/test.esp32-c3-idf.yaml | 11 +++++ tests/components/max6675/test.esp32-c3.yaml | 11 +++++ tests/components/max6675/test.esp32-idf.yaml | 11 +++++ tests/components/max6675/test.esp32.yaml | 11 +++++ tests/components/max6675/test.esp8266.yaml | 11 +++++ tests/components/max6675/test.rp2040.yaml | 11 +++++ .../components/max6956/test.esp32-c3-idf.yaml | 19 ++++++++ tests/components/max6956/test.esp32-c3.yaml | 19 ++++++++ tests/components/max6956/test.esp32-idf.yaml | 19 ++++++++ tests/components/max6956/test.esp32.yaml | 19 ++++++++ tests/components/max6956/test.esp8266.yaml | 19 ++++++++ tests/components/max6956/test.rp2040.yaml | 19 ++++++++ .../components/max7219/test.esp32-c3-idf.yaml | 12 +++++ tests/components/max7219/test.esp32-c3.yaml | 12 +++++ tests/components/max7219/test.esp32-idf.yaml | 12 +++++ tests/components/max7219/test.esp32.yaml | 12 +++++ tests/components/max7219/test.esp8266.yaml | 12 +++++ tests/components/max7219/test.rp2040.yaml | 12 +++++ .../max7219digit/test.esp32-c3-idf.yaml | 16 +++++++ .../max7219digit/test.esp32-c3.yaml | 16 +++++++ .../max7219digit/test.esp32-idf.yaml | 16 +++++++ tests/components/max7219digit/test.esp32.yaml | 16 +++++++ .../components/max7219digit/test.esp8266.yaml | 16 +++++++ .../components/max7219digit/test.rp2040.yaml | 16 +++++++ .../components/max9611/test.esp32-c3-idf.yaml | 18 ++++++++ tests/components/max9611/test.esp32-c3.yaml | 18 ++++++++ tests/components/max9611/test.esp32-idf.yaml | 18 ++++++++ tests/components/max9611/test.esp32.yaml | 18 ++++++++ tests/components/max9611/test.esp8266.yaml | 18 ++++++++ tests/components/max9611/test.rp2040.yaml | 18 ++++++++ .../mcp23008/test.esp32-c3-idf.yaml | 23 ++++++++++ tests/components/mcp23008/test.esp32-c3.yaml | 23 ++++++++++ tests/components/mcp23008/test.esp32-idf.yaml | 23 ++++++++++ tests/components/mcp23008/test.esp32.yaml | 23 ++++++++++ tests/components/mcp23008/test.esp8266.yaml | 23 ++++++++++ tests/components/mcp23008/test.rp2040.yaml | 23 ++++++++++ .../mcp23016/test.esp32-c3-idf.yaml | 23 ++++++++++ tests/components/mcp23016/test.esp32-c3.yaml | 23 ++++++++++ tests/components/mcp23016/test.esp32-idf.yaml | 23 ++++++++++ tests/components/mcp23016/test.esp32.yaml | 23 ++++++++++ tests/components/mcp23016/test.esp8266.yaml | 23 ++++++++++ tests/components/mcp23016/test.rp2040.yaml | 23 ++++++++++ .../mcp23017/test.esp32-c3-idf.yaml | 23 ++++++++++ tests/components/mcp23017/test.esp32-c3.yaml | 23 ++++++++++ tests/components/mcp23017/test.esp32-idf.yaml | 23 ++++++++++ tests/components/mcp23017/test.esp32.yaml | 23 ++++++++++ tests/components/mcp23017/test.esp8266.yaml | 23 ++++++++++ tests/components/mcp23017/test.rp2040.yaml | 23 ++++++++++ .../mcp23s08/test.esp32-c3-idf.yaml | 10 +++++ tests/components/mcp23s08/test.esp32-c3.yaml | 10 +++++ tests/components/mcp23s08/test.esp32-idf.yaml | 10 +++++ tests/components/mcp23s08/test.esp32.yaml | 10 +++++ tests/components/mcp23s08/test.esp8266.yaml | 10 +++++ tests/components/mcp23s08/test.rp2040.yaml | 10 +++++ .../mcp23s17/test.esp32-c3-idf.yaml | 10 +++++ tests/components/mcp23s17/test.esp32-c3.yaml | 10 +++++ tests/components/mcp23s17/test.esp32-idf.yaml | 10 +++++ tests/components/mcp23s17/test.esp32.yaml | 10 +++++ tests/components/mcp23s17/test.esp8266.yaml | 10 +++++ tests/components/mcp23s17/test.rp2040.yaml | 10 +++++ .../components/mcp2515/test.esp32-c3-idf.yaml | 44 +++++++++++++++++++ tests/components/mcp2515/test.esp32-c3.yaml | 44 +++++++++++++++++++ tests/components/mcp2515/test.esp32-idf.yaml | 44 +++++++++++++++++++ tests/components/mcp2515/test.esp32.yaml | 44 +++++++++++++++++++ tests/components/mcp2515/test.esp8266.yaml | 44 +++++++++++++++++++ tests/components/mcp2515/test.rp2040.yaml | 44 +++++++++++++++++++ .../components/mcp3008/test.esp32-c3-idf.yaml | 17 +++++++ tests/components/mcp3008/test.esp32-c3.yaml | 17 +++++++ tests/components/mcp3008/test.esp32-idf.yaml | 17 +++++++ tests/components/mcp3008/test.esp32.yaml | 17 +++++++ tests/components/mcp3008/test.esp8266.yaml | 17 +++++++ tests/components/mcp3008/test.rp2040.yaml | 17 +++++++ .../components/mcp3204/test.esp32-c3-idf.yaml | 16 +++++++ tests/components/mcp3204/test.esp32-c3.yaml | 16 +++++++ tests/components/mcp3204/test.esp32-idf.yaml | 16 +++++++ tests/components/mcp3204/test.esp32.yaml | 16 +++++++ tests/components/mcp3204/test.esp8266.yaml | 16 +++++++ tests/components/mcp3204/test.rp2040.yaml | 16 +++++++ .../components/mcp4725/test.esp32-c3-idf.yaml | 8 ++++ tests/components/mcp4725/test.esp32-c3.yaml | 8 ++++ tests/components/mcp4725/test.esp32-idf.yaml | 8 ++++ tests/components/mcp4725/test.esp32.yaml | 8 ++++ tests/components/mcp4725/test.esp8266.yaml | 8 ++++ tests/components/mcp4725/test.rp2040.yaml | 8 ++++ .../components/mcp4728/test.esp32-c3-idf.yaml | 31 +++++++++++++ tests/components/mcp4728/test.esp32-c3.yaml | 31 +++++++++++++ tests/components/mcp4728/test.esp32-idf.yaml | 31 +++++++++++++ tests/components/mcp4728/test.esp32.yaml | 31 +++++++++++++ tests/components/mcp4728/test.esp8266.yaml | 31 +++++++++++++ tests/components/mcp4728/test.rp2040.yaml | 31 +++++++++++++ .../components/mcp47a1/test.esp32-c3-idf.yaml | 8 ++++ tests/components/mcp47a1/test.esp32-c3.yaml | 8 ++++ tests/components/mcp47a1/test.esp32-idf.yaml | 8 ++++ tests/components/mcp47a1/test.esp32.yaml | 8 ++++ tests/components/mcp47a1/test.esp8266.yaml | 8 ++++ tests/components/mcp47a1/test.rp2040.yaml | 8 ++++ .../components/mcp9600/test.esp32-c3-idf.yaml | 12 +++++ tests/components/mcp9600/test.esp32-c3.yaml | 12 +++++ tests/components/mcp9600/test.esp32-idf.yaml | 12 +++++ tests/components/mcp9600/test.esp32.yaml | 12 +++++ tests/components/mcp9600/test.esp8266.yaml | 12 +++++ tests/components/mcp9600/test.rp2040.yaml | 12 +++++ .../components/mcp9808/test.esp32-c3-idf.yaml | 8 ++++ tests/components/mcp9808/test.esp32-c3.yaml | 8 ++++ tests/components/mcp9808/test.esp32-idf.yaml | 8 ++++ tests/components/mcp9808/test.esp32.yaml | 8 ++++ tests/components/mcp9808/test.esp8266.yaml | 8 ++++ tests/components/mcp9808/test.rp2040.yaml | 8 ++++ tests/components/mdns/test.esp32-c3-idf.yaml | 6 +++ tests/components/mdns/test.esp32-c3.yaml | 6 +++ tests/components/mdns/test.esp32-idf.yaml | 6 +++ tests/components/mdns/test.esp32.yaml | 6 +++ tests/components/mdns/test.esp8266.yaml | 6 +++ tests/components/mdns/test.rp2040.yaml | 6 +++ tests/components/media_player/test.esp32.yaml | 32 ++++++++++++++ tests/components/mhz19/test.esp32-c3-idf.yaml | 14 ++++++ tests/components/mhz19/test.esp32-c3.yaml | 14 ++++++ tests/components/mhz19/test.esp32-idf.yaml | 14 ++++++ tests/components/mhz19/test.esp32.yaml | 14 ++++++ tests/components/mhz19/test.esp8266.yaml | 14 ++++++ tests/components/mhz19/test.rp2040.yaml | 14 ++++++ 151 files changed, 2420 insertions(+) create mode 100644 tests/components/matrix_keypad/test.esp32-c3-idf.yaml create mode 100644 tests/components/matrix_keypad/test.esp32-c3.yaml create mode 100644 tests/components/matrix_keypad/test.esp32-idf.yaml create mode 100644 tests/components/matrix_keypad/test.esp32.yaml create mode 100644 tests/components/matrix_keypad/test.esp8266.yaml create mode 100644 tests/components/matrix_keypad/test.rp2040.yaml create mode 100644 tests/components/max31855/test.esp32-c3-idf.yaml create mode 100644 tests/components/max31855/test.esp32-c3.yaml create mode 100644 tests/components/max31855/test.esp32-idf.yaml create mode 100644 tests/components/max31855/test.esp32.yaml create mode 100644 tests/components/max31855/test.esp8266.yaml create mode 100644 tests/components/max31855/test.rp2040.yaml create mode 100644 tests/components/max31856/test.esp32-c3-idf.yaml create mode 100644 tests/components/max31856/test.esp32-c3.yaml create mode 100644 tests/components/max31856/test.esp32-idf.yaml create mode 100644 tests/components/max31856/test.esp32.yaml create mode 100644 tests/components/max31856/test.esp8266.yaml create mode 100644 tests/components/max31856/test.rp2040.yaml create mode 100644 tests/components/max31865/test.esp32-c3-idf.yaml create mode 100644 tests/components/max31865/test.esp32-c3.yaml create mode 100644 tests/components/max31865/test.esp32-idf.yaml create mode 100644 tests/components/max31865/test.esp32.yaml create mode 100644 tests/components/max31865/test.esp8266.yaml create mode 100644 tests/components/max31865/test.rp2040.yaml create mode 100644 tests/components/max44009/test.esp32-c3-idf.yaml create mode 100644 tests/components/max44009/test.esp32-c3.yaml create mode 100644 tests/components/max44009/test.esp32-idf.yaml create mode 100644 tests/components/max44009/test.esp32.yaml create mode 100644 tests/components/max44009/test.esp8266.yaml create mode 100644 tests/components/max44009/test.rp2040.yaml create mode 100644 tests/components/max6675/test.esp32-c3-idf.yaml create mode 100644 tests/components/max6675/test.esp32-c3.yaml create mode 100644 tests/components/max6675/test.esp32-idf.yaml create mode 100644 tests/components/max6675/test.esp32.yaml create mode 100644 tests/components/max6675/test.esp8266.yaml create mode 100644 tests/components/max6675/test.rp2040.yaml create mode 100644 tests/components/max6956/test.esp32-c3-idf.yaml create mode 100644 tests/components/max6956/test.esp32-c3.yaml create mode 100644 tests/components/max6956/test.esp32-idf.yaml create mode 100644 tests/components/max6956/test.esp32.yaml create mode 100644 tests/components/max6956/test.esp8266.yaml create mode 100644 tests/components/max6956/test.rp2040.yaml create mode 100644 tests/components/max7219/test.esp32-c3-idf.yaml create mode 100644 tests/components/max7219/test.esp32-c3.yaml create mode 100644 tests/components/max7219/test.esp32-idf.yaml create mode 100644 tests/components/max7219/test.esp32.yaml create mode 100644 tests/components/max7219/test.esp8266.yaml create mode 100644 tests/components/max7219/test.rp2040.yaml create mode 100644 tests/components/max7219digit/test.esp32-c3-idf.yaml create mode 100644 tests/components/max7219digit/test.esp32-c3.yaml create mode 100644 tests/components/max7219digit/test.esp32-idf.yaml create mode 100644 tests/components/max7219digit/test.esp32.yaml create mode 100644 tests/components/max7219digit/test.esp8266.yaml create mode 100644 tests/components/max7219digit/test.rp2040.yaml create mode 100644 tests/components/max9611/test.esp32-c3-idf.yaml create mode 100644 tests/components/max9611/test.esp32-c3.yaml create mode 100644 tests/components/max9611/test.esp32-idf.yaml create mode 100644 tests/components/max9611/test.esp32.yaml create mode 100644 tests/components/max9611/test.esp8266.yaml create mode 100644 tests/components/max9611/test.rp2040.yaml create mode 100644 tests/components/mcp23008/test.esp32-c3-idf.yaml create mode 100644 tests/components/mcp23008/test.esp32-c3.yaml create mode 100644 tests/components/mcp23008/test.esp32-idf.yaml create mode 100644 tests/components/mcp23008/test.esp32.yaml create mode 100644 tests/components/mcp23008/test.esp8266.yaml create mode 100644 tests/components/mcp23008/test.rp2040.yaml create mode 100644 tests/components/mcp23016/test.esp32-c3-idf.yaml create mode 100644 tests/components/mcp23016/test.esp32-c3.yaml create mode 100644 tests/components/mcp23016/test.esp32-idf.yaml create mode 100644 tests/components/mcp23016/test.esp32.yaml create mode 100644 tests/components/mcp23016/test.esp8266.yaml create mode 100644 tests/components/mcp23016/test.rp2040.yaml create mode 100644 tests/components/mcp23017/test.esp32-c3-idf.yaml create mode 100644 tests/components/mcp23017/test.esp32-c3.yaml create mode 100644 tests/components/mcp23017/test.esp32-idf.yaml create mode 100644 tests/components/mcp23017/test.esp32.yaml create mode 100644 tests/components/mcp23017/test.esp8266.yaml create mode 100644 tests/components/mcp23017/test.rp2040.yaml create mode 100644 tests/components/mcp23s08/test.esp32-c3-idf.yaml create mode 100644 tests/components/mcp23s08/test.esp32-c3.yaml create mode 100644 tests/components/mcp23s08/test.esp32-idf.yaml create mode 100644 tests/components/mcp23s08/test.esp32.yaml create mode 100644 tests/components/mcp23s08/test.esp8266.yaml create mode 100644 tests/components/mcp23s08/test.rp2040.yaml create mode 100644 tests/components/mcp23s17/test.esp32-c3-idf.yaml create mode 100644 tests/components/mcp23s17/test.esp32-c3.yaml create mode 100644 tests/components/mcp23s17/test.esp32-idf.yaml create mode 100644 tests/components/mcp23s17/test.esp32.yaml create mode 100644 tests/components/mcp23s17/test.esp8266.yaml create mode 100644 tests/components/mcp23s17/test.rp2040.yaml create mode 100644 tests/components/mcp2515/test.esp32-c3-idf.yaml create mode 100644 tests/components/mcp2515/test.esp32-c3.yaml create mode 100644 tests/components/mcp2515/test.esp32-idf.yaml create mode 100644 tests/components/mcp2515/test.esp32.yaml create mode 100644 tests/components/mcp2515/test.esp8266.yaml create mode 100644 tests/components/mcp2515/test.rp2040.yaml create mode 100644 tests/components/mcp3008/test.esp32-c3-idf.yaml create mode 100644 tests/components/mcp3008/test.esp32-c3.yaml create mode 100644 tests/components/mcp3008/test.esp32-idf.yaml create mode 100644 tests/components/mcp3008/test.esp32.yaml create mode 100644 tests/components/mcp3008/test.esp8266.yaml create mode 100644 tests/components/mcp3008/test.rp2040.yaml create mode 100644 tests/components/mcp3204/test.esp32-c3-idf.yaml create mode 100644 tests/components/mcp3204/test.esp32-c3.yaml create mode 100644 tests/components/mcp3204/test.esp32-idf.yaml create mode 100644 tests/components/mcp3204/test.esp32.yaml create mode 100644 tests/components/mcp3204/test.esp8266.yaml create mode 100644 tests/components/mcp3204/test.rp2040.yaml create mode 100644 tests/components/mcp4725/test.esp32-c3-idf.yaml create mode 100644 tests/components/mcp4725/test.esp32-c3.yaml create mode 100644 tests/components/mcp4725/test.esp32-idf.yaml create mode 100644 tests/components/mcp4725/test.esp32.yaml create mode 100644 tests/components/mcp4725/test.esp8266.yaml create mode 100644 tests/components/mcp4725/test.rp2040.yaml create mode 100644 tests/components/mcp4728/test.esp32-c3-idf.yaml create mode 100644 tests/components/mcp4728/test.esp32-c3.yaml create mode 100644 tests/components/mcp4728/test.esp32-idf.yaml create mode 100644 tests/components/mcp4728/test.esp32.yaml create mode 100644 tests/components/mcp4728/test.esp8266.yaml create mode 100644 tests/components/mcp4728/test.rp2040.yaml create mode 100644 tests/components/mcp47a1/test.esp32-c3-idf.yaml create mode 100644 tests/components/mcp47a1/test.esp32-c3.yaml create mode 100644 tests/components/mcp47a1/test.esp32-idf.yaml create mode 100644 tests/components/mcp47a1/test.esp32.yaml create mode 100644 tests/components/mcp47a1/test.esp8266.yaml create mode 100644 tests/components/mcp47a1/test.rp2040.yaml create mode 100644 tests/components/mcp9600/test.esp32-c3-idf.yaml create mode 100644 tests/components/mcp9600/test.esp32-c3.yaml create mode 100644 tests/components/mcp9600/test.esp32-idf.yaml create mode 100644 tests/components/mcp9600/test.esp32.yaml create mode 100644 tests/components/mcp9600/test.esp8266.yaml create mode 100644 tests/components/mcp9600/test.rp2040.yaml create mode 100644 tests/components/mcp9808/test.esp32-c3-idf.yaml create mode 100644 tests/components/mcp9808/test.esp32-c3.yaml create mode 100644 tests/components/mcp9808/test.esp32-idf.yaml create mode 100644 tests/components/mcp9808/test.esp32.yaml create mode 100644 tests/components/mcp9808/test.esp8266.yaml create mode 100644 tests/components/mcp9808/test.rp2040.yaml create mode 100644 tests/components/mdns/test.esp32-c3-idf.yaml create mode 100644 tests/components/mdns/test.esp32-c3.yaml create mode 100644 tests/components/mdns/test.esp32-idf.yaml create mode 100644 tests/components/mdns/test.esp32.yaml create mode 100644 tests/components/mdns/test.esp8266.yaml create mode 100644 tests/components/mdns/test.rp2040.yaml create mode 100644 tests/components/media_player/test.esp32.yaml create mode 100644 tests/components/mhz19/test.esp32-c3-idf.yaml create mode 100644 tests/components/mhz19/test.esp32-c3.yaml create mode 100644 tests/components/mhz19/test.esp32-idf.yaml create mode 100644 tests/components/mhz19/test.esp32.yaml create mode 100644 tests/components/mhz19/test.esp8266.yaml create mode 100644 tests/components/mhz19/test.rp2040.yaml diff --git a/tests/components/matrix_keypad/test.esp32-c3-idf.yaml b/tests/components/matrix_keypad/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..d15e6af21a --- /dev/null +++ b/tests/components/matrix_keypad/test.esp32-c3-idf.yaml @@ -0,0 +1,19 @@ +binary_sensor: + - platform: matrix_keypad + id: key4 + row: 1 + col: 1 + - platform: matrix_keypad + id: key1 + key: 1 + +matrix_keypad: + id: keypad + rows: + - pin: 1 + - pin: 2 + columns: + - pin: 3 + - pin: 4 + keys: "1234" + has_pulldowns: true diff --git a/tests/components/matrix_keypad/test.esp32-c3.yaml b/tests/components/matrix_keypad/test.esp32-c3.yaml new file mode 100644 index 0000000000..d15e6af21a --- /dev/null +++ b/tests/components/matrix_keypad/test.esp32-c3.yaml @@ -0,0 +1,19 @@ +binary_sensor: + - platform: matrix_keypad + id: key4 + row: 1 + col: 1 + - platform: matrix_keypad + id: key1 + key: 1 + +matrix_keypad: + id: keypad + rows: + - pin: 1 + - pin: 2 + columns: + - pin: 3 + - pin: 4 + keys: "1234" + has_pulldowns: true diff --git a/tests/components/matrix_keypad/test.esp32-idf.yaml b/tests/components/matrix_keypad/test.esp32-idf.yaml new file mode 100644 index 0000000000..c8e9b54534 --- /dev/null +++ b/tests/components/matrix_keypad/test.esp32-idf.yaml @@ -0,0 +1,19 @@ +binary_sensor: + - platform: matrix_keypad + id: key4 + row: 1 + col: 1 + - platform: matrix_keypad + id: key1 + key: 1 + +matrix_keypad: + id: keypad + rows: + - pin: 12 + - pin: 13 + columns: + - pin: 14 + - pin: 15 + keys: "1234" + has_pulldowns: true diff --git a/tests/components/matrix_keypad/test.esp32.yaml b/tests/components/matrix_keypad/test.esp32.yaml new file mode 100644 index 0000000000..c8e9b54534 --- /dev/null +++ b/tests/components/matrix_keypad/test.esp32.yaml @@ -0,0 +1,19 @@ +binary_sensor: + - platform: matrix_keypad + id: key4 + row: 1 + col: 1 + - platform: matrix_keypad + id: key1 + key: 1 + +matrix_keypad: + id: keypad + rows: + - pin: 12 + - pin: 13 + columns: + - pin: 14 + - pin: 15 + keys: "1234" + has_pulldowns: true diff --git a/tests/components/matrix_keypad/test.esp8266.yaml b/tests/components/matrix_keypad/test.esp8266.yaml new file mode 100644 index 0000000000..c8e9b54534 --- /dev/null +++ b/tests/components/matrix_keypad/test.esp8266.yaml @@ -0,0 +1,19 @@ +binary_sensor: + - platform: matrix_keypad + id: key4 + row: 1 + col: 1 + - platform: matrix_keypad + id: key1 + key: 1 + +matrix_keypad: + id: keypad + rows: + - pin: 12 + - pin: 13 + columns: + - pin: 14 + - pin: 15 + keys: "1234" + has_pulldowns: true diff --git a/tests/components/matrix_keypad/test.rp2040.yaml b/tests/components/matrix_keypad/test.rp2040.yaml new file mode 100644 index 0000000000..d15e6af21a --- /dev/null +++ b/tests/components/matrix_keypad/test.rp2040.yaml @@ -0,0 +1,19 @@ +binary_sensor: + - platform: matrix_keypad + id: key4 + row: 1 + col: 1 + - platform: matrix_keypad + id: key1 + key: 1 + +matrix_keypad: + id: keypad + rows: + - pin: 1 + - pin: 2 + columns: + - pin: 3 + - pin: 4 + keys: "1234" + has_pulldowns: true diff --git a/tests/components/max31855/test.esp32-c3-idf.yaml b/tests/components/max31855/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..e7c8f3f824 --- /dev/null +++ b/tests/components/max31855/test.esp32-c3-idf.yaml @@ -0,0 +1,13 @@ +spi: + - id: spi_max31855 + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +sensor: + - platform: max31855 + name: MAX31855 Temperature + cs_pin: 8 + update_interval: 15s + reference_temperature: + name: MAX31855 Internal Temperature diff --git a/tests/components/max31855/test.esp32-c3.yaml b/tests/components/max31855/test.esp32-c3.yaml new file mode 100644 index 0000000000..e7c8f3f824 --- /dev/null +++ b/tests/components/max31855/test.esp32-c3.yaml @@ -0,0 +1,13 @@ +spi: + - id: spi_max31855 + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +sensor: + - platform: max31855 + name: MAX31855 Temperature + cs_pin: 8 + update_interval: 15s + reference_temperature: + name: MAX31855 Internal Temperature diff --git a/tests/components/max31855/test.esp32-idf.yaml b/tests/components/max31855/test.esp32-idf.yaml new file mode 100644 index 0000000000..25fee986d2 --- /dev/null +++ b/tests/components/max31855/test.esp32-idf.yaml @@ -0,0 +1,13 @@ +spi: + - id: spi_max31855 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +sensor: + - platform: max31855 + name: MAX31855 Temperature + cs_pin: 12 + update_interval: 15s + reference_temperature: + name: MAX31855 Internal Temperature diff --git a/tests/components/max31855/test.esp32.yaml b/tests/components/max31855/test.esp32.yaml new file mode 100644 index 0000000000..25fee986d2 --- /dev/null +++ b/tests/components/max31855/test.esp32.yaml @@ -0,0 +1,13 @@ +spi: + - id: spi_max31855 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +sensor: + - platform: max31855 + name: MAX31855 Temperature + cs_pin: 12 + update_interval: 15s + reference_temperature: + name: MAX31855 Internal Temperature diff --git a/tests/components/max31855/test.esp8266.yaml b/tests/components/max31855/test.esp8266.yaml new file mode 100644 index 0000000000..7e02d41fce --- /dev/null +++ b/tests/components/max31855/test.esp8266.yaml @@ -0,0 +1,13 @@ +spi: + - id: spi_max31855 + clk_pin: 14 + mosi_pin: 13 + miso_pin: 12 + +sensor: + - platform: max31855 + name: MAX31855 Temperature + cs_pin: 15 + update_interval: 15s + reference_temperature: + name: MAX31855 Internal Temperature diff --git a/tests/components/max31855/test.rp2040.yaml b/tests/components/max31855/test.rp2040.yaml new file mode 100644 index 0000000000..379d4d33d6 --- /dev/null +++ b/tests/components/max31855/test.rp2040.yaml @@ -0,0 +1,13 @@ +spi: + - id: spi_max31855 + clk_pin: 2 + mosi_pin: 3 + miso_pin: 4 + +sensor: + - platform: max31855 + name: MAX31855 Temperature + cs_pin: 6 + update_interval: 15s + reference_temperature: + name: MAX31855 Internal Temperature diff --git a/tests/components/max31856/test.esp32-c3-idf.yaml b/tests/components/max31856/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..2794866c59 --- /dev/null +++ b/tests/components/max31856/test.esp32-c3-idf.yaml @@ -0,0 +1,12 @@ +spi: + - id: spi_max31856 + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +sensor: + - platform: max31856 + name: MAX31856 Temperature + cs_pin: 8 + update_interval: 15s + mains_filter: 50Hz diff --git a/tests/components/max31856/test.esp32-c3.yaml b/tests/components/max31856/test.esp32-c3.yaml new file mode 100644 index 0000000000..2794866c59 --- /dev/null +++ b/tests/components/max31856/test.esp32-c3.yaml @@ -0,0 +1,12 @@ +spi: + - id: spi_max31856 + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +sensor: + - platform: max31856 + name: MAX31856 Temperature + cs_pin: 8 + update_interval: 15s + mains_filter: 50Hz diff --git a/tests/components/max31856/test.esp32-idf.yaml b/tests/components/max31856/test.esp32-idf.yaml new file mode 100644 index 0000000000..5561903207 --- /dev/null +++ b/tests/components/max31856/test.esp32-idf.yaml @@ -0,0 +1,12 @@ +spi: + - id: spi_max31856 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +sensor: + - platform: max31856 + name: MAX31856 Temperature + cs_pin: 12 + update_interval: 15s + mains_filter: 50Hz diff --git a/tests/components/max31856/test.esp32.yaml b/tests/components/max31856/test.esp32.yaml new file mode 100644 index 0000000000..5561903207 --- /dev/null +++ b/tests/components/max31856/test.esp32.yaml @@ -0,0 +1,12 @@ +spi: + - id: spi_max31856 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +sensor: + - platform: max31856 + name: MAX31856 Temperature + cs_pin: 12 + update_interval: 15s + mains_filter: 50Hz diff --git a/tests/components/max31856/test.esp8266.yaml b/tests/components/max31856/test.esp8266.yaml new file mode 100644 index 0000000000..dfd9572ca9 --- /dev/null +++ b/tests/components/max31856/test.esp8266.yaml @@ -0,0 +1,12 @@ +spi: + - id: spi_max31856 + clk_pin: 14 + mosi_pin: 13 + miso_pin: 12 + +sensor: + - platform: max31856 + name: MAX31856 Temperature + cs_pin: 15 + update_interval: 15s + mains_filter: 50Hz diff --git a/tests/components/max31856/test.rp2040.yaml b/tests/components/max31856/test.rp2040.yaml new file mode 100644 index 0000000000..0abc8a081b --- /dev/null +++ b/tests/components/max31856/test.rp2040.yaml @@ -0,0 +1,12 @@ +spi: + - id: spi_max31856 + clk_pin: 2 + mosi_pin: 3 + miso_pin: 4 + +sensor: + - platform: max31856 + name: MAX31856 Temperature + cs_pin: 6 + update_interval: 15s + mains_filter: 50Hz diff --git a/tests/components/max31865/test.esp32-c3-idf.yaml b/tests/components/max31865/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..45de22331e --- /dev/null +++ b/tests/components/max31865/test.esp32-c3-idf.yaml @@ -0,0 +1,13 @@ +spi: + - id: spi_max31865 + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +sensor: + - platform: max31865 + name: MAX31865 Temperature + cs_pin: 8 + update_interval: 15s + reference_resistance: 430 Ω + rtd_nominal_resistance: 100 Ω diff --git a/tests/components/max31865/test.esp32-c3.yaml b/tests/components/max31865/test.esp32-c3.yaml new file mode 100644 index 0000000000..45de22331e --- /dev/null +++ b/tests/components/max31865/test.esp32-c3.yaml @@ -0,0 +1,13 @@ +spi: + - id: spi_max31865 + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +sensor: + - platform: max31865 + name: MAX31865 Temperature + cs_pin: 8 + update_interval: 15s + reference_resistance: 430 Ω + rtd_nominal_resistance: 100 Ω diff --git a/tests/components/max31865/test.esp32-idf.yaml b/tests/components/max31865/test.esp32-idf.yaml new file mode 100644 index 0000000000..8326a578ee --- /dev/null +++ b/tests/components/max31865/test.esp32-idf.yaml @@ -0,0 +1,13 @@ +spi: + - id: spi_max31865 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +sensor: + - platform: max31865 + name: MAX31865 Temperature + cs_pin: 12 + update_interval: 15s + reference_resistance: 430 Ω + rtd_nominal_resistance: 100 Ω diff --git a/tests/components/max31865/test.esp32.yaml b/tests/components/max31865/test.esp32.yaml new file mode 100644 index 0000000000..8326a578ee --- /dev/null +++ b/tests/components/max31865/test.esp32.yaml @@ -0,0 +1,13 @@ +spi: + - id: spi_max31865 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +sensor: + - platform: max31865 + name: MAX31865 Temperature + cs_pin: 12 + update_interval: 15s + reference_resistance: 430 Ω + rtd_nominal_resistance: 100 Ω diff --git a/tests/components/max31865/test.esp8266.yaml b/tests/components/max31865/test.esp8266.yaml new file mode 100644 index 0000000000..4828019acc --- /dev/null +++ b/tests/components/max31865/test.esp8266.yaml @@ -0,0 +1,13 @@ +spi: + - id: spi_max31865 + clk_pin: 14 + mosi_pin: 13 + miso_pin: 12 + +sensor: + - platform: max31865 + name: MAX31865 Temperature + cs_pin: 15 + update_interval: 15s + reference_resistance: 430 Ω + rtd_nominal_resistance: 100 Ω diff --git a/tests/components/max31865/test.rp2040.yaml b/tests/components/max31865/test.rp2040.yaml new file mode 100644 index 0000000000..5af64b41ad --- /dev/null +++ b/tests/components/max31865/test.rp2040.yaml @@ -0,0 +1,13 @@ +spi: + - id: spi_max31865 + clk_pin: 2 + mosi_pin: 3 + miso_pin: 4 + +sensor: + - platform: max31865 + name: MAX31865 Temperature + cs_pin: 6 + update_interval: 15s + reference_resistance: 430 Ω + rtd_nominal_resistance: 100 Ω diff --git a/tests/components/max44009/test.esp32-c3-idf.yaml b/tests/components/max44009/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..593d4bd48c --- /dev/null +++ b/tests/components/max44009/test.esp32-c3-idf.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_max44009 + scl: 5 + sda: 4 + +sensor: + - platform: max44009 + name: MAX44009 Brightness + internal: true + mode: low_power + address: 0x4A + update_interval: 30s diff --git a/tests/components/max44009/test.esp32-c3.yaml b/tests/components/max44009/test.esp32-c3.yaml new file mode 100644 index 0000000000..593d4bd48c --- /dev/null +++ b/tests/components/max44009/test.esp32-c3.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_max44009 + scl: 5 + sda: 4 + +sensor: + - platform: max44009 + name: MAX44009 Brightness + internal: true + mode: low_power + address: 0x4A + update_interval: 30s diff --git a/tests/components/max44009/test.esp32-idf.yaml b/tests/components/max44009/test.esp32-idf.yaml new file mode 100644 index 0000000000..56eecebc4a --- /dev/null +++ b/tests/components/max44009/test.esp32-idf.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_max44009 + scl: 16 + sda: 17 + +sensor: + - platform: max44009 + name: MAX44009 Brightness + internal: true + mode: low_power + address: 0x4A + update_interval: 30s diff --git a/tests/components/max44009/test.esp32.yaml b/tests/components/max44009/test.esp32.yaml new file mode 100644 index 0000000000..56eecebc4a --- /dev/null +++ b/tests/components/max44009/test.esp32.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_max44009 + scl: 16 + sda: 17 + +sensor: + - platform: max44009 + name: MAX44009 Brightness + internal: true + mode: low_power + address: 0x4A + update_interval: 30s diff --git a/tests/components/max44009/test.esp8266.yaml b/tests/components/max44009/test.esp8266.yaml new file mode 100644 index 0000000000..593d4bd48c --- /dev/null +++ b/tests/components/max44009/test.esp8266.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_max44009 + scl: 5 + sda: 4 + +sensor: + - platform: max44009 + name: MAX44009 Brightness + internal: true + mode: low_power + address: 0x4A + update_interval: 30s diff --git a/tests/components/max44009/test.rp2040.yaml b/tests/components/max44009/test.rp2040.yaml new file mode 100644 index 0000000000..593d4bd48c --- /dev/null +++ b/tests/components/max44009/test.rp2040.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_max44009 + scl: 5 + sda: 4 + +sensor: + - platform: max44009 + name: MAX44009 Brightness + internal: true + mode: low_power + address: 0x4A + update_interval: 30s diff --git a/tests/components/max6675/test.esp32-c3-idf.yaml b/tests/components/max6675/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..2f05102ca1 --- /dev/null +++ b/tests/components/max6675/test.esp32-c3-idf.yaml @@ -0,0 +1,11 @@ +spi: + - id: spi_max6675 + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +sensor: + - platform: max6675 + name: Temperature + cs_pin: 8 + update_interval: 15s diff --git a/tests/components/max6675/test.esp32-c3.yaml b/tests/components/max6675/test.esp32-c3.yaml new file mode 100644 index 0000000000..2f05102ca1 --- /dev/null +++ b/tests/components/max6675/test.esp32-c3.yaml @@ -0,0 +1,11 @@ +spi: + - id: spi_max6675 + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +sensor: + - platform: max6675 + name: Temperature + cs_pin: 8 + update_interval: 15s diff --git a/tests/components/max6675/test.esp32-idf.yaml b/tests/components/max6675/test.esp32-idf.yaml new file mode 100644 index 0000000000..9771bf9d5f --- /dev/null +++ b/tests/components/max6675/test.esp32-idf.yaml @@ -0,0 +1,11 @@ +spi: + - id: spi_max6675 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +sensor: + - platform: max6675 + name: Temperature + cs_pin: 12 + update_interval: 15s diff --git a/tests/components/max6675/test.esp32.yaml b/tests/components/max6675/test.esp32.yaml new file mode 100644 index 0000000000..9771bf9d5f --- /dev/null +++ b/tests/components/max6675/test.esp32.yaml @@ -0,0 +1,11 @@ +spi: + - id: spi_max6675 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +sensor: + - platform: max6675 + name: Temperature + cs_pin: 12 + update_interval: 15s diff --git a/tests/components/max6675/test.esp8266.yaml b/tests/components/max6675/test.esp8266.yaml new file mode 100644 index 0000000000..f67e9e04a8 --- /dev/null +++ b/tests/components/max6675/test.esp8266.yaml @@ -0,0 +1,11 @@ +spi: + - id: spi_max6675 + clk_pin: 14 + mosi_pin: 13 + miso_pin: 12 + +sensor: + - platform: max6675 + name: Temperature + cs_pin: 15 + update_interval: 15s diff --git a/tests/components/max6675/test.rp2040.yaml b/tests/components/max6675/test.rp2040.yaml new file mode 100644 index 0000000000..89c0932f94 --- /dev/null +++ b/tests/components/max6675/test.rp2040.yaml @@ -0,0 +1,11 @@ +spi: + - id: spi_max6675 + clk_pin: 2 + mosi_pin: 3 + miso_pin: 4 + +sensor: + - platform: max6675 + name: Temperature + cs_pin: 6 + update_interval: 15s diff --git a/tests/components/max6956/test.esp32-c3-idf.yaml b/tests/components/max6956/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..690941784c --- /dev/null +++ b/tests/components/max6956/test.esp32-c3-idf.yaml @@ -0,0 +1,19 @@ +i2c: + - id: i2c_max6956 + scl: 5 + sda: 4 + +max6956: + - id: max6956_1 + address: 0x40 + +binary_sensor: + - platform: gpio + name: Max Input Pin 4 + pin: + max6956: max6956_1 + number: 4 + mode: + input: true + pullup: true + inverted: false diff --git a/tests/components/max6956/test.esp32-c3.yaml b/tests/components/max6956/test.esp32-c3.yaml new file mode 100644 index 0000000000..690941784c --- /dev/null +++ b/tests/components/max6956/test.esp32-c3.yaml @@ -0,0 +1,19 @@ +i2c: + - id: i2c_max6956 + scl: 5 + sda: 4 + +max6956: + - id: max6956_1 + address: 0x40 + +binary_sensor: + - platform: gpio + name: Max Input Pin 4 + pin: + max6956: max6956_1 + number: 4 + mode: + input: true + pullup: true + inverted: false diff --git a/tests/components/max6956/test.esp32-idf.yaml b/tests/components/max6956/test.esp32-idf.yaml new file mode 100644 index 0000000000..abd1404634 --- /dev/null +++ b/tests/components/max6956/test.esp32-idf.yaml @@ -0,0 +1,19 @@ +i2c: + - id: i2c_max6956 + scl: 16 + sda: 17 + +max6956: + - id: max6956_1 + address: 0x40 + +binary_sensor: + - platform: gpio + name: Max Input Pin 4 + pin: + max6956: max6956_1 + number: 4 + mode: + input: true + pullup: true + inverted: false diff --git a/tests/components/max6956/test.esp32.yaml b/tests/components/max6956/test.esp32.yaml new file mode 100644 index 0000000000..abd1404634 --- /dev/null +++ b/tests/components/max6956/test.esp32.yaml @@ -0,0 +1,19 @@ +i2c: + - id: i2c_max6956 + scl: 16 + sda: 17 + +max6956: + - id: max6956_1 + address: 0x40 + +binary_sensor: + - platform: gpio + name: Max Input Pin 4 + pin: + max6956: max6956_1 + number: 4 + mode: + input: true + pullup: true + inverted: false diff --git a/tests/components/max6956/test.esp8266.yaml b/tests/components/max6956/test.esp8266.yaml new file mode 100644 index 0000000000..690941784c --- /dev/null +++ b/tests/components/max6956/test.esp8266.yaml @@ -0,0 +1,19 @@ +i2c: + - id: i2c_max6956 + scl: 5 + sda: 4 + +max6956: + - id: max6956_1 + address: 0x40 + +binary_sensor: + - platform: gpio + name: Max Input Pin 4 + pin: + max6956: max6956_1 + number: 4 + mode: + input: true + pullup: true + inverted: false diff --git a/tests/components/max6956/test.rp2040.yaml b/tests/components/max6956/test.rp2040.yaml new file mode 100644 index 0000000000..690941784c --- /dev/null +++ b/tests/components/max6956/test.rp2040.yaml @@ -0,0 +1,19 @@ +i2c: + - id: i2c_max6956 + scl: 5 + sda: 4 + +max6956: + - id: max6956_1 + address: 0x40 + +binary_sensor: + - platform: gpio + name: Max Input Pin 4 + pin: + max6956: max6956_1 + number: 4 + mode: + input: true + pullup: true + inverted: false diff --git a/tests/components/max7219/test.esp32-c3-idf.yaml b/tests/components/max7219/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..fa1ac15f33 --- /dev/null +++ b/tests/components/max7219/test.esp32-c3-idf.yaml @@ -0,0 +1,12 @@ +spi: + - id: spi_max7219 + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +display: + - platform: max7219 + cs_pin: 8 + num_chips: 1 + lambda: |- + it.print("01234567"); diff --git a/tests/components/max7219/test.esp32-c3.yaml b/tests/components/max7219/test.esp32-c3.yaml new file mode 100644 index 0000000000..fa1ac15f33 --- /dev/null +++ b/tests/components/max7219/test.esp32-c3.yaml @@ -0,0 +1,12 @@ +spi: + - id: spi_max7219 + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +display: + - platform: max7219 + cs_pin: 8 + num_chips: 1 + lambda: |- + it.print("01234567"); diff --git a/tests/components/max7219/test.esp32-idf.yaml b/tests/components/max7219/test.esp32-idf.yaml new file mode 100644 index 0000000000..2985345a48 --- /dev/null +++ b/tests/components/max7219/test.esp32-idf.yaml @@ -0,0 +1,12 @@ +spi: + - id: spi_max6675 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +display: + - platform: max7219 + cs_pin: 12 + num_chips: 1 + lambda: |- + it.print("01234567"); diff --git a/tests/components/max7219/test.esp32.yaml b/tests/components/max7219/test.esp32.yaml new file mode 100644 index 0000000000..2985345a48 --- /dev/null +++ b/tests/components/max7219/test.esp32.yaml @@ -0,0 +1,12 @@ +spi: + - id: spi_max6675 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +display: + - platform: max7219 + cs_pin: 12 + num_chips: 1 + lambda: |- + it.print("01234567"); diff --git a/tests/components/max7219/test.esp8266.yaml b/tests/components/max7219/test.esp8266.yaml new file mode 100644 index 0000000000..a8c280daff --- /dev/null +++ b/tests/components/max7219/test.esp8266.yaml @@ -0,0 +1,12 @@ +spi: + - id: spi_max6675 + clk_pin: 14 + mosi_pin: 13 + miso_pin: 12 + +display: + - platform: max7219 + cs_pin: 15 + num_chips: 1 + lambda: |- + it.print("01234567"); diff --git a/tests/components/max7219/test.rp2040.yaml b/tests/components/max7219/test.rp2040.yaml new file mode 100644 index 0000000000..37b2220649 --- /dev/null +++ b/tests/components/max7219/test.rp2040.yaml @@ -0,0 +1,12 @@ +spi: + - id: spi_max6675 + clk_pin: 2 + mosi_pin: 3 + miso_pin: 4 + +display: + - platform: max7219 + cs_pin: 6 + num_chips: 1 + lambda: |- + it.print("01234567"); diff --git a/tests/components/max7219digit/test.esp32-c3-idf.yaml b/tests/components/max7219digit/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..0c04784380 --- /dev/null +++ b/tests/components/max7219digit/test.esp32-c3-idf.yaml @@ -0,0 +1,16 @@ +spi: + - id: spi_max7219digit + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +display: + - platform: max7219digit + cs_pin: 8 + num_chips: 4 + rotate_chip: 0 + intensity: 10 + scroll_mode: STOP + id: my_matrix + lambda: |- + it.printdigit("hello"); diff --git a/tests/components/max7219digit/test.esp32-c3.yaml b/tests/components/max7219digit/test.esp32-c3.yaml new file mode 100644 index 0000000000..0c04784380 --- /dev/null +++ b/tests/components/max7219digit/test.esp32-c3.yaml @@ -0,0 +1,16 @@ +spi: + - id: spi_max7219digit + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +display: + - platform: max7219digit + cs_pin: 8 + num_chips: 4 + rotate_chip: 0 + intensity: 10 + scroll_mode: STOP + id: my_matrix + lambda: |- + it.printdigit("hello"); diff --git a/tests/components/max7219digit/test.esp32-idf.yaml b/tests/components/max7219digit/test.esp32-idf.yaml new file mode 100644 index 0000000000..7f3aed964a --- /dev/null +++ b/tests/components/max7219digit/test.esp32-idf.yaml @@ -0,0 +1,16 @@ +spi: + - id: spi_max7219digit + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +display: + - platform: max7219digit + cs_pin: 12 + num_chips: 4 + rotate_chip: 0 + intensity: 10 + scroll_mode: STOP + id: my_matrix + lambda: |- + it.printdigit("hello"); diff --git a/tests/components/max7219digit/test.esp32.yaml b/tests/components/max7219digit/test.esp32.yaml new file mode 100644 index 0000000000..7f3aed964a --- /dev/null +++ b/tests/components/max7219digit/test.esp32.yaml @@ -0,0 +1,16 @@ +spi: + - id: spi_max7219digit + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +display: + - platform: max7219digit + cs_pin: 12 + num_chips: 4 + rotate_chip: 0 + intensity: 10 + scroll_mode: STOP + id: my_matrix + lambda: |- + it.printdigit("hello"); diff --git a/tests/components/max7219digit/test.esp8266.yaml b/tests/components/max7219digit/test.esp8266.yaml new file mode 100644 index 0000000000..52587e8b0e --- /dev/null +++ b/tests/components/max7219digit/test.esp8266.yaml @@ -0,0 +1,16 @@ +spi: + - id: spi_max7219digit + clk_pin: 14 + mosi_pin: 13 + miso_pin: 12 + +display: + - platform: max7219digit + cs_pin: 15 + num_chips: 4 + rotate_chip: 0 + intensity: 10 + scroll_mode: STOP + id: my_matrix + lambda: |- + it.printdigit("hello"); diff --git a/tests/components/max7219digit/test.rp2040.yaml b/tests/components/max7219digit/test.rp2040.yaml new file mode 100644 index 0000000000..f986483ec2 --- /dev/null +++ b/tests/components/max7219digit/test.rp2040.yaml @@ -0,0 +1,16 @@ +spi: + - id: spi_max7219digit + clk_pin: 2 + mosi_pin: 3 + miso_pin: 4 + +display: + - platform: max7219digit + cs_pin: 6 + num_chips: 4 + rotate_chip: 0 + intensity: 10 + scroll_mode: STOP + id: my_matrix + lambda: |- + it.printdigit("hello"); diff --git a/tests/components/max9611/test.esp32-c3-idf.yaml b/tests/components/max9611/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..00f8330280 --- /dev/null +++ b/tests/components/max9611/test.esp32-c3-idf.yaml @@ -0,0 +1,18 @@ +i2c: + - id: i2c_max9611 + scl: 5 + sda: 4 + +sensor: + - platform: max9611 + shunt_resistance: 0.2 ohm + gain: 1X + voltage: + name: Max9611 Voltage + current: + name: Max9611 Current + power: + name: Max9611 Watts + temperature: + name: Max9611 Temp + update_interval: 1s diff --git a/tests/components/max9611/test.esp32-c3.yaml b/tests/components/max9611/test.esp32-c3.yaml new file mode 100644 index 0000000000..00f8330280 --- /dev/null +++ b/tests/components/max9611/test.esp32-c3.yaml @@ -0,0 +1,18 @@ +i2c: + - id: i2c_max9611 + scl: 5 + sda: 4 + +sensor: + - platform: max9611 + shunt_resistance: 0.2 ohm + gain: 1X + voltage: + name: Max9611 Voltage + current: + name: Max9611 Current + power: + name: Max9611 Watts + temperature: + name: Max9611 Temp + update_interval: 1s diff --git a/tests/components/max9611/test.esp32-idf.yaml b/tests/components/max9611/test.esp32-idf.yaml new file mode 100644 index 0000000000..5c480cc815 --- /dev/null +++ b/tests/components/max9611/test.esp32-idf.yaml @@ -0,0 +1,18 @@ +i2c: + - id: i2c_max9611 + scl: 16 + sda: 17 + +sensor: + - platform: max9611 + shunt_resistance: 0.2 ohm + gain: 1X + voltage: + name: Max9611 Voltage + current: + name: Max9611 Current + power: + name: Max9611 Watts + temperature: + name: Max9611 Temp + update_interval: 1s diff --git a/tests/components/max9611/test.esp32.yaml b/tests/components/max9611/test.esp32.yaml new file mode 100644 index 0000000000..5c480cc815 --- /dev/null +++ b/tests/components/max9611/test.esp32.yaml @@ -0,0 +1,18 @@ +i2c: + - id: i2c_max9611 + scl: 16 + sda: 17 + +sensor: + - platform: max9611 + shunt_resistance: 0.2 ohm + gain: 1X + voltage: + name: Max9611 Voltage + current: + name: Max9611 Current + power: + name: Max9611 Watts + temperature: + name: Max9611 Temp + update_interval: 1s diff --git a/tests/components/max9611/test.esp8266.yaml b/tests/components/max9611/test.esp8266.yaml new file mode 100644 index 0000000000..00f8330280 --- /dev/null +++ b/tests/components/max9611/test.esp8266.yaml @@ -0,0 +1,18 @@ +i2c: + - id: i2c_max9611 + scl: 5 + sda: 4 + +sensor: + - platform: max9611 + shunt_resistance: 0.2 ohm + gain: 1X + voltage: + name: Max9611 Voltage + current: + name: Max9611 Current + power: + name: Max9611 Watts + temperature: + name: Max9611 Temp + update_interval: 1s diff --git a/tests/components/max9611/test.rp2040.yaml b/tests/components/max9611/test.rp2040.yaml new file mode 100644 index 0000000000..00f8330280 --- /dev/null +++ b/tests/components/max9611/test.rp2040.yaml @@ -0,0 +1,18 @@ +i2c: + - id: i2c_max9611 + scl: 5 + sda: 4 + +sensor: + - platform: max9611 + shunt_resistance: 0.2 ohm + gain: 1X + voltage: + name: Max9611 Voltage + current: + name: Max9611 Current + power: + name: Max9611 Watts + temperature: + name: Max9611 Temp + update_interval: 1s diff --git a/tests/components/mcp23008/test.esp32-c3-idf.yaml b/tests/components/mcp23008/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..eabd5a7311 --- /dev/null +++ b/tests/components/mcp23008/test.esp32-c3-idf.yaml @@ -0,0 +1,23 @@ +i2c: + - id: i2c_mcp23008 + scl: 5 + sda: 4 + +mcp23008: + id: mcp23008_hub + +binary_sensor: + - platform: gpio + id: mcp23008_binary_sensor + pin: + mcp23xxx: mcp23008_hub + number: 0 + mode: INPUT + +switch: + - platform: gpio + id: mcp23008_switch + pin: + mcp23xxx: mcp23008_hub + number: 1 + mode: OUTPUT diff --git a/tests/components/mcp23008/test.esp32-c3.yaml b/tests/components/mcp23008/test.esp32-c3.yaml new file mode 100644 index 0000000000..eabd5a7311 --- /dev/null +++ b/tests/components/mcp23008/test.esp32-c3.yaml @@ -0,0 +1,23 @@ +i2c: + - id: i2c_mcp23008 + scl: 5 + sda: 4 + +mcp23008: + id: mcp23008_hub + +binary_sensor: + - platform: gpio + id: mcp23008_binary_sensor + pin: + mcp23xxx: mcp23008_hub + number: 0 + mode: INPUT + +switch: + - platform: gpio + id: mcp23008_switch + pin: + mcp23xxx: mcp23008_hub + number: 1 + mode: OUTPUT diff --git a/tests/components/mcp23008/test.esp32-idf.yaml b/tests/components/mcp23008/test.esp32-idf.yaml new file mode 100644 index 0000000000..cbf03f371c --- /dev/null +++ b/tests/components/mcp23008/test.esp32-idf.yaml @@ -0,0 +1,23 @@ +i2c: + - id: i2c_mcp23008 + scl: 16 + sda: 17 + +mcp23008: + id: mcp23008_hub + +binary_sensor: + - platform: gpio + id: mcp23008_binary_sensor + pin: + mcp23xxx: mcp23008_hub + number: 0 + mode: INPUT + +switch: + - platform: gpio + id: mcp23008_switch + pin: + mcp23xxx: mcp23008_hub + number: 1 + mode: OUTPUT diff --git a/tests/components/mcp23008/test.esp32.yaml b/tests/components/mcp23008/test.esp32.yaml new file mode 100644 index 0000000000..cbf03f371c --- /dev/null +++ b/tests/components/mcp23008/test.esp32.yaml @@ -0,0 +1,23 @@ +i2c: + - id: i2c_mcp23008 + scl: 16 + sda: 17 + +mcp23008: + id: mcp23008_hub + +binary_sensor: + - platform: gpio + id: mcp23008_binary_sensor + pin: + mcp23xxx: mcp23008_hub + number: 0 + mode: INPUT + +switch: + - platform: gpio + id: mcp23008_switch + pin: + mcp23xxx: mcp23008_hub + number: 1 + mode: OUTPUT diff --git a/tests/components/mcp23008/test.esp8266.yaml b/tests/components/mcp23008/test.esp8266.yaml new file mode 100644 index 0000000000..eabd5a7311 --- /dev/null +++ b/tests/components/mcp23008/test.esp8266.yaml @@ -0,0 +1,23 @@ +i2c: + - id: i2c_mcp23008 + scl: 5 + sda: 4 + +mcp23008: + id: mcp23008_hub + +binary_sensor: + - platform: gpio + id: mcp23008_binary_sensor + pin: + mcp23xxx: mcp23008_hub + number: 0 + mode: INPUT + +switch: + - platform: gpio + id: mcp23008_switch + pin: + mcp23xxx: mcp23008_hub + number: 1 + mode: OUTPUT diff --git a/tests/components/mcp23008/test.rp2040.yaml b/tests/components/mcp23008/test.rp2040.yaml new file mode 100644 index 0000000000..eabd5a7311 --- /dev/null +++ b/tests/components/mcp23008/test.rp2040.yaml @@ -0,0 +1,23 @@ +i2c: + - id: i2c_mcp23008 + scl: 5 + sda: 4 + +mcp23008: + id: mcp23008_hub + +binary_sensor: + - platform: gpio + id: mcp23008_binary_sensor + pin: + mcp23xxx: mcp23008_hub + number: 0 + mode: INPUT + +switch: + - platform: gpio + id: mcp23008_switch + pin: + mcp23xxx: mcp23008_hub + number: 1 + mode: OUTPUT diff --git a/tests/components/mcp23016/test.esp32-c3-idf.yaml b/tests/components/mcp23016/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..2211931e3d --- /dev/null +++ b/tests/components/mcp23016/test.esp32-c3-idf.yaml @@ -0,0 +1,23 @@ +i2c: + - id: i2c_mcp23016 + scl: 5 + sda: 4 + +mcp23016: + id: mcp23016_hub + +binary_sensor: + - platform: gpio + id: mcp23016_binary_sensor + pin: + mcp23016: mcp23016_hub + number: 0 + mode: INPUT + +switch: + - platform: gpio + id: mcp23016_switch + pin: + mcp23016: mcp23016_hub + number: 1 + mode: OUTPUT diff --git a/tests/components/mcp23016/test.esp32-c3.yaml b/tests/components/mcp23016/test.esp32-c3.yaml new file mode 100644 index 0000000000..2211931e3d --- /dev/null +++ b/tests/components/mcp23016/test.esp32-c3.yaml @@ -0,0 +1,23 @@ +i2c: + - id: i2c_mcp23016 + scl: 5 + sda: 4 + +mcp23016: + id: mcp23016_hub + +binary_sensor: + - platform: gpio + id: mcp23016_binary_sensor + pin: + mcp23016: mcp23016_hub + number: 0 + mode: INPUT + +switch: + - platform: gpio + id: mcp23016_switch + pin: + mcp23016: mcp23016_hub + number: 1 + mode: OUTPUT diff --git a/tests/components/mcp23016/test.esp32-idf.yaml b/tests/components/mcp23016/test.esp32-idf.yaml new file mode 100644 index 0000000000..48574a9b01 --- /dev/null +++ b/tests/components/mcp23016/test.esp32-idf.yaml @@ -0,0 +1,23 @@ +i2c: + - id: i2c_mcp23016 + scl: 16 + sda: 17 + +mcp23016: + id: mcp23016_hub + +binary_sensor: + - platform: gpio + id: mcp23016_binary_sensor + pin: + mcp23016: mcp23016_hub + number: 0 + mode: INPUT + +switch: + - platform: gpio + id: mcp23016_switch + pin: + mcp23016: mcp23016_hub + number: 1 + mode: OUTPUT diff --git a/tests/components/mcp23016/test.esp32.yaml b/tests/components/mcp23016/test.esp32.yaml new file mode 100644 index 0000000000..48574a9b01 --- /dev/null +++ b/tests/components/mcp23016/test.esp32.yaml @@ -0,0 +1,23 @@ +i2c: + - id: i2c_mcp23016 + scl: 16 + sda: 17 + +mcp23016: + id: mcp23016_hub + +binary_sensor: + - platform: gpio + id: mcp23016_binary_sensor + pin: + mcp23016: mcp23016_hub + number: 0 + mode: INPUT + +switch: + - platform: gpio + id: mcp23016_switch + pin: + mcp23016: mcp23016_hub + number: 1 + mode: OUTPUT diff --git a/tests/components/mcp23016/test.esp8266.yaml b/tests/components/mcp23016/test.esp8266.yaml new file mode 100644 index 0000000000..2211931e3d --- /dev/null +++ b/tests/components/mcp23016/test.esp8266.yaml @@ -0,0 +1,23 @@ +i2c: + - id: i2c_mcp23016 + scl: 5 + sda: 4 + +mcp23016: + id: mcp23016_hub + +binary_sensor: + - platform: gpio + id: mcp23016_binary_sensor + pin: + mcp23016: mcp23016_hub + number: 0 + mode: INPUT + +switch: + - platform: gpio + id: mcp23016_switch + pin: + mcp23016: mcp23016_hub + number: 1 + mode: OUTPUT diff --git a/tests/components/mcp23016/test.rp2040.yaml b/tests/components/mcp23016/test.rp2040.yaml new file mode 100644 index 0000000000..2211931e3d --- /dev/null +++ b/tests/components/mcp23016/test.rp2040.yaml @@ -0,0 +1,23 @@ +i2c: + - id: i2c_mcp23016 + scl: 5 + sda: 4 + +mcp23016: + id: mcp23016_hub + +binary_sensor: + - platform: gpio + id: mcp23016_binary_sensor + pin: + mcp23016: mcp23016_hub + number: 0 + mode: INPUT + +switch: + - platform: gpio + id: mcp23016_switch + pin: + mcp23016: mcp23016_hub + number: 1 + mode: OUTPUT diff --git a/tests/components/mcp23017/test.esp32-c3-idf.yaml b/tests/components/mcp23017/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..863b2b8f0b --- /dev/null +++ b/tests/components/mcp23017/test.esp32-c3-idf.yaml @@ -0,0 +1,23 @@ +i2c: + - id: i2c_mcp23017 + scl: 5 + sda: 4 + +mcp23017: + id: mcp23017_hub + +binary_sensor: + - platform: gpio + id: mcp23017_binary_sensor + pin: + mcp23xxx: mcp23017_hub + number: 0 + mode: INPUT + +switch: + - platform: gpio + id: mcp23017_switch + pin: + mcp23xxx: mcp23017_hub + number: 1 + mode: OUTPUT diff --git a/tests/components/mcp23017/test.esp32-c3.yaml b/tests/components/mcp23017/test.esp32-c3.yaml new file mode 100644 index 0000000000..863b2b8f0b --- /dev/null +++ b/tests/components/mcp23017/test.esp32-c3.yaml @@ -0,0 +1,23 @@ +i2c: + - id: i2c_mcp23017 + scl: 5 + sda: 4 + +mcp23017: + id: mcp23017_hub + +binary_sensor: + - platform: gpio + id: mcp23017_binary_sensor + pin: + mcp23xxx: mcp23017_hub + number: 0 + mode: INPUT + +switch: + - platform: gpio + id: mcp23017_switch + pin: + mcp23xxx: mcp23017_hub + number: 1 + mode: OUTPUT diff --git a/tests/components/mcp23017/test.esp32-idf.yaml b/tests/components/mcp23017/test.esp32-idf.yaml new file mode 100644 index 0000000000..9b7c45eb8a --- /dev/null +++ b/tests/components/mcp23017/test.esp32-idf.yaml @@ -0,0 +1,23 @@ +i2c: + - id: i2c_mcp23017 + scl: 16 + sda: 17 + +mcp23017: + id: mcp23017_hub + +binary_sensor: + - platform: gpio + id: mcp23017_binary_sensor + pin: + mcp23xxx: mcp23017_hub + number: 0 + mode: INPUT + +switch: + - platform: gpio + id: mcp23017_switch + pin: + mcp23xxx: mcp23017_hub + number: 1 + mode: OUTPUT diff --git a/tests/components/mcp23017/test.esp32.yaml b/tests/components/mcp23017/test.esp32.yaml new file mode 100644 index 0000000000..9b7c45eb8a --- /dev/null +++ b/tests/components/mcp23017/test.esp32.yaml @@ -0,0 +1,23 @@ +i2c: + - id: i2c_mcp23017 + scl: 16 + sda: 17 + +mcp23017: + id: mcp23017_hub + +binary_sensor: + - platform: gpio + id: mcp23017_binary_sensor + pin: + mcp23xxx: mcp23017_hub + number: 0 + mode: INPUT + +switch: + - platform: gpio + id: mcp23017_switch + pin: + mcp23xxx: mcp23017_hub + number: 1 + mode: OUTPUT diff --git a/tests/components/mcp23017/test.esp8266.yaml b/tests/components/mcp23017/test.esp8266.yaml new file mode 100644 index 0000000000..863b2b8f0b --- /dev/null +++ b/tests/components/mcp23017/test.esp8266.yaml @@ -0,0 +1,23 @@ +i2c: + - id: i2c_mcp23017 + scl: 5 + sda: 4 + +mcp23017: + id: mcp23017_hub + +binary_sensor: + - platform: gpio + id: mcp23017_binary_sensor + pin: + mcp23xxx: mcp23017_hub + number: 0 + mode: INPUT + +switch: + - platform: gpio + id: mcp23017_switch + pin: + mcp23xxx: mcp23017_hub + number: 1 + mode: OUTPUT diff --git a/tests/components/mcp23017/test.rp2040.yaml b/tests/components/mcp23017/test.rp2040.yaml new file mode 100644 index 0000000000..863b2b8f0b --- /dev/null +++ b/tests/components/mcp23017/test.rp2040.yaml @@ -0,0 +1,23 @@ +i2c: + - id: i2c_mcp23017 + scl: 5 + sda: 4 + +mcp23017: + id: mcp23017_hub + +binary_sensor: + - platform: gpio + id: mcp23017_binary_sensor + pin: + mcp23xxx: mcp23017_hub + number: 0 + mode: INPUT + +switch: + - platform: gpio + id: mcp23017_switch + pin: + mcp23xxx: mcp23017_hub + number: 1 + mode: OUTPUT diff --git a/tests/components/mcp23s08/test.esp32-c3-idf.yaml b/tests/components/mcp23s08/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..f1af8a71a9 --- /dev/null +++ b/tests/components/mcp23s08/test.esp32-c3-idf.yaml @@ -0,0 +1,10 @@ +spi: + - id: spi_mcp23s08 + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +mcp23s08: + - id: mcp23s08_hub + cs_pin: 8 + deviceaddress: 0 diff --git a/tests/components/mcp23s08/test.esp32-c3.yaml b/tests/components/mcp23s08/test.esp32-c3.yaml new file mode 100644 index 0000000000..f1af8a71a9 --- /dev/null +++ b/tests/components/mcp23s08/test.esp32-c3.yaml @@ -0,0 +1,10 @@ +spi: + - id: spi_mcp23s08 + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +mcp23s08: + - id: mcp23s08_hub + cs_pin: 8 + deviceaddress: 0 diff --git a/tests/components/mcp23s08/test.esp32-idf.yaml b/tests/components/mcp23s08/test.esp32-idf.yaml new file mode 100644 index 0000000000..0b26035c3e --- /dev/null +++ b/tests/components/mcp23s08/test.esp32-idf.yaml @@ -0,0 +1,10 @@ +spi: + - id: spi_mcp23s08 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +mcp23s08: + - id: mcp23s08_hub + cs_pin: 12 + deviceaddress: 0 diff --git a/tests/components/mcp23s08/test.esp32.yaml b/tests/components/mcp23s08/test.esp32.yaml new file mode 100644 index 0000000000..0b26035c3e --- /dev/null +++ b/tests/components/mcp23s08/test.esp32.yaml @@ -0,0 +1,10 @@ +spi: + - id: spi_mcp23s08 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +mcp23s08: + - id: mcp23s08_hub + cs_pin: 12 + deviceaddress: 0 diff --git a/tests/components/mcp23s08/test.esp8266.yaml b/tests/components/mcp23s08/test.esp8266.yaml new file mode 100644 index 0000000000..eff856aca9 --- /dev/null +++ b/tests/components/mcp23s08/test.esp8266.yaml @@ -0,0 +1,10 @@ +spi: + - id: spi_mcp23s08 + clk_pin: 14 + mosi_pin: 13 + miso_pin: 12 + +mcp23s08: + - id: mcp23s08_hub + cs_pin: 15 + deviceaddress: 0 diff --git a/tests/components/mcp23s08/test.rp2040.yaml b/tests/components/mcp23s08/test.rp2040.yaml new file mode 100644 index 0000000000..1b23d2d3b5 --- /dev/null +++ b/tests/components/mcp23s08/test.rp2040.yaml @@ -0,0 +1,10 @@ +spi: + - id: spi_mcp23s08 + clk_pin: 2 + mosi_pin: 3 + miso_pin: 4 + +mcp23s08: + - id: mcp23s08_hub + cs_pin: 6 + deviceaddress: 0 diff --git a/tests/components/mcp23s17/test.esp32-c3-idf.yaml b/tests/components/mcp23s17/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..d83f66d3b1 --- /dev/null +++ b/tests/components/mcp23s17/test.esp32-c3-idf.yaml @@ -0,0 +1,10 @@ +spi: + - id: spi_mcp23s17 + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +mcp23s17: + - id: mcp23s17_hub + cs_pin: 8 + deviceaddress: 0 diff --git a/tests/components/mcp23s17/test.esp32-c3.yaml b/tests/components/mcp23s17/test.esp32-c3.yaml new file mode 100644 index 0000000000..d83f66d3b1 --- /dev/null +++ b/tests/components/mcp23s17/test.esp32-c3.yaml @@ -0,0 +1,10 @@ +spi: + - id: spi_mcp23s17 + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +mcp23s17: + - id: mcp23s17_hub + cs_pin: 8 + deviceaddress: 0 diff --git a/tests/components/mcp23s17/test.esp32-idf.yaml b/tests/components/mcp23s17/test.esp32-idf.yaml new file mode 100644 index 0000000000..9a42c12e85 --- /dev/null +++ b/tests/components/mcp23s17/test.esp32-idf.yaml @@ -0,0 +1,10 @@ +spi: + - id: spi_mcp23s17 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +mcp23s17: + - id: mcp23s17_hub + cs_pin: 12 + deviceaddress: 0 diff --git a/tests/components/mcp23s17/test.esp32.yaml b/tests/components/mcp23s17/test.esp32.yaml new file mode 100644 index 0000000000..9a42c12e85 --- /dev/null +++ b/tests/components/mcp23s17/test.esp32.yaml @@ -0,0 +1,10 @@ +spi: + - id: spi_mcp23s17 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +mcp23s17: + - id: mcp23s17_hub + cs_pin: 12 + deviceaddress: 0 diff --git a/tests/components/mcp23s17/test.esp8266.yaml b/tests/components/mcp23s17/test.esp8266.yaml new file mode 100644 index 0000000000..36dac63f6f --- /dev/null +++ b/tests/components/mcp23s17/test.esp8266.yaml @@ -0,0 +1,10 @@ +spi: + - id: spi_mcp23s17 + clk_pin: 14 + mosi_pin: 13 + miso_pin: 12 + +mcp23s17: + - id: mcp23s17_hub + cs_pin: 15 + deviceaddress: 0 diff --git a/tests/components/mcp23s17/test.rp2040.yaml b/tests/components/mcp23s17/test.rp2040.yaml new file mode 100644 index 0000000000..2730f6a9d6 --- /dev/null +++ b/tests/components/mcp23s17/test.rp2040.yaml @@ -0,0 +1,10 @@ +spi: + - id: spi_mcp23s17 + clk_pin: 2 + mosi_pin: 3 + miso_pin: 4 + +mcp23s17: + - id: mcp23s17_hub + cs_pin: 6 + deviceaddress: 0 diff --git a/tests/components/mcp2515/test.esp32-c3-idf.yaml b/tests/components/mcp2515/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..3ceeea268f --- /dev/null +++ b/tests/components/mcp2515/test.esp32-c3-idf.yaml @@ -0,0 +1,44 @@ +spi: + - id: spi_mcp2515 + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +canbus: + - platform: mcp2515 + id: mcp2515_can + cs_pin: 8 + can_id: 4 + bit_rate: 50kbps + on_frame: + - can_id: 500 + then: + - lambda: |- + std::string b(x.begin(), x.end()); + ESP_LOGD("can_id 500", "%s", b.c_str()); + - can_id: 23 + then: + - if: + condition: + lambda: "return x[0] == 0x11;" + then: + logger.log: "x[0] == 0x11" + - can_id: 0b00000000000000000000001000000 + can_id_mask: 0b11111000000000011111111000000 + use_extended_id: true + then: + - lambda: |- + auto pdo_id = can_id >> 14; + switch (pdo_id) + { + case 117: + ESP_LOGD("canbus", "exhaust_fan_duty"); + break; + case 118: + ESP_LOGD("canbus", "supply_fan_duty"); + break; + case 119: + ESP_LOGD("canbus", "supply_fan_flow"); + break; + // to be continued... + } diff --git a/tests/components/mcp2515/test.esp32-c3.yaml b/tests/components/mcp2515/test.esp32-c3.yaml new file mode 100644 index 0000000000..3ceeea268f --- /dev/null +++ b/tests/components/mcp2515/test.esp32-c3.yaml @@ -0,0 +1,44 @@ +spi: + - id: spi_mcp2515 + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +canbus: + - platform: mcp2515 + id: mcp2515_can + cs_pin: 8 + can_id: 4 + bit_rate: 50kbps + on_frame: + - can_id: 500 + then: + - lambda: |- + std::string b(x.begin(), x.end()); + ESP_LOGD("can_id 500", "%s", b.c_str()); + - can_id: 23 + then: + - if: + condition: + lambda: "return x[0] == 0x11;" + then: + logger.log: "x[0] == 0x11" + - can_id: 0b00000000000000000000001000000 + can_id_mask: 0b11111000000000011111111000000 + use_extended_id: true + then: + - lambda: |- + auto pdo_id = can_id >> 14; + switch (pdo_id) + { + case 117: + ESP_LOGD("canbus", "exhaust_fan_duty"); + break; + case 118: + ESP_LOGD("canbus", "supply_fan_duty"); + break; + case 119: + ESP_LOGD("canbus", "supply_fan_flow"); + break; + // to be continued... + } diff --git a/tests/components/mcp2515/test.esp32-idf.yaml b/tests/components/mcp2515/test.esp32-idf.yaml new file mode 100644 index 0000000000..07fae36cc3 --- /dev/null +++ b/tests/components/mcp2515/test.esp32-idf.yaml @@ -0,0 +1,44 @@ +spi: + - id: spi_mcp2515 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +canbus: + - platform: mcp2515 + id: mcp2515_can + cs_pin: 12 + can_id: 4 + bit_rate: 50kbps + on_frame: + - can_id: 500 + then: + - lambda: |- + std::string b(x.begin(), x.end()); + ESP_LOGD("can_id 500", "%s", b.c_str()); + - can_id: 23 + then: + - if: + condition: + lambda: "return x[0] == 0x11;" + then: + logger.log: "x[0] == 0x11" + - can_id: 0b00000000000000000000001000000 + can_id_mask: 0b11111000000000011111111000000 + use_extended_id: true + then: + - lambda: |- + auto pdo_id = can_id >> 14; + switch (pdo_id) + { + case 117: + ESP_LOGD("canbus", "exhaust_fan_duty"); + break; + case 118: + ESP_LOGD("canbus", "supply_fan_duty"); + break; + case 119: + ESP_LOGD("canbus", "supply_fan_flow"); + break; + // to be continued... + } diff --git a/tests/components/mcp2515/test.esp32.yaml b/tests/components/mcp2515/test.esp32.yaml new file mode 100644 index 0000000000..07fae36cc3 --- /dev/null +++ b/tests/components/mcp2515/test.esp32.yaml @@ -0,0 +1,44 @@ +spi: + - id: spi_mcp2515 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +canbus: + - platform: mcp2515 + id: mcp2515_can + cs_pin: 12 + can_id: 4 + bit_rate: 50kbps + on_frame: + - can_id: 500 + then: + - lambda: |- + std::string b(x.begin(), x.end()); + ESP_LOGD("can_id 500", "%s", b.c_str()); + - can_id: 23 + then: + - if: + condition: + lambda: "return x[0] == 0x11;" + then: + logger.log: "x[0] == 0x11" + - can_id: 0b00000000000000000000001000000 + can_id_mask: 0b11111000000000011111111000000 + use_extended_id: true + then: + - lambda: |- + auto pdo_id = can_id >> 14; + switch (pdo_id) + { + case 117: + ESP_LOGD("canbus", "exhaust_fan_duty"); + break; + case 118: + ESP_LOGD("canbus", "supply_fan_duty"); + break; + case 119: + ESP_LOGD("canbus", "supply_fan_flow"); + break; + // to be continued... + } diff --git a/tests/components/mcp2515/test.esp8266.yaml b/tests/components/mcp2515/test.esp8266.yaml new file mode 100644 index 0000000000..1096a0e809 --- /dev/null +++ b/tests/components/mcp2515/test.esp8266.yaml @@ -0,0 +1,44 @@ +spi: + - id: spi_mcp2515 + clk_pin: 14 + mosi_pin: 13 + miso_pin: 12 + +canbus: + - platform: mcp2515 + id: mcp2515_can + cs_pin: 15 + can_id: 4 + bit_rate: 50kbps + on_frame: + - can_id: 500 + then: + - lambda: |- + std::string b(x.begin(), x.end()); + ESP_LOGD("can_id 500", "%s", b.c_str()); + - can_id: 23 + then: + - if: + condition: + lambda: "return x[0] == 0x11;" + then: + logger.log: "x[0] == 0x11" + - can_id: 0b00000000000000000000001000000 + can_id_mask: 0b11111000000000011111111000000 + use_extended_id: true + then: + - lambda: |- + auto pdo_id = can_id >> 14; + switch (pdo_id) + { + case 117: + ESP_LOGD("canbus", "exhaust_fan_duty"); + break; + case 118: + ESP_LOGD("canbus", "supply_fan_duty"); + break; + case 119: + ESP_LOGD("canbus", "supply_fan_flow"); + break; + // to be continued... + } diff --git a/tests/components/mcp2515/test.rp2040.yaml b/tests/components/mcp2515/test.rp2040.yaml new file mode 100644 index 0000000000..678c817d3d --- /dev/null +++ b/tests/components/mcp2515/test.rp2040.yaml @@ -0,0 +1,44 @@ +spi: + - id: spi_mcp2515 + clk_pin: 2 + mosi_pin: 3 + miso_pin: 4 + +canbus: + - platform: mcp2515 + id: mcp2515_can + cs_pin: 6 + can_id: 4 + bit_rate: 50kbps + on_frame: + - can_id: 500 + then: + - lambda: |- + std::string b(x.begin(), x.end()); + ESP_LOGD("can_id 500", "%s", b.c_str()); + - can_id: 23 + then: + - if: + condition: + lambda: "return x[0] == 0x11;" + then: + logger.log: "x[0] == 0x11" + - can_id: 0b00000000000000000000001000000 + can_id_mask: 0b11111000000000011111111000000 + use_extended_id: true + then: + - lambda: |- + auto pdo_id = can_id >> 14; + switch (pdo_id) + { + case 117: + ESP_LOGD("canbus", "exhaust_fan_duty"); + break; + case 118: + ESP_LOGD("canbus", "supply_fan_duty"); + break; + case 119: + ESP_LOGD("canbus", "supply_fan_flow"); + break; + // to be continued... + } diff --git a/tests/components/mcp3008/test.esp32-c3-idf.yaml b/tests/components/mcp3008/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..9e66372e4f --- /dev/null +++ b/tests/components/mcp3008/test.esp32-c3-idf.yaml @@ -0,0 +1,17 @@ +spi: + - id: spi_mcp3008 + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +mcp3008: + - id: mcp3008_hub + cs_pin: 8 + +sensor: + - platform: mcp3008 + id: mcp3008_sensor + mcp3008_id: mcp3008_hub + number: 0 + reference_voltage: 3.19 + update_interval: 5s diff --git a/tests/components/mcp3008/test.esp32-c3.yaml b/tests/components/mcp3008/test.esp32-c3.yaml new file mode 100644 index 0000000000..9e66372e4f --- /dev/null +++ b/tests/components/mcp3008/test.esp32-c3.yaml @@ -0,0 +1,17 @@ +spi: + - id: spi_mcp3008 + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +mcp3008: + - id: mcp3008_hub + cs_pin: 8 + +sensor: + - platform: mcp3008 + id: mcp3008_sensor + mcp3008_id: mcp3008_hub + number: 0 + reference_voltage: 3.19 + update_interval: 5s diff --git a/tests/components/mcp3008/test.esp32-idf.yaml b/tests/components/mcp3008/test.esp32-idf.yaml new file mode 100644 index 0000000000..a66fbeb7a1 --- /dev/null +++ b/tests/components/mcp3008/test.esp32-idf.yaml @@ -0,0 +1,17 @@ +spi: + - id: spi_mcp3008 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +mcp3008: + - id: mcp3008_hub + cs_pin: 12 + +sensor: + - platform: mcp3008 + id: mcp3008_sensor + mcp3008_id: mcp3008_hub + number: 0 + reference_voltage: 3.19 + update_interval: 5s diff --git a/tests/components/mcp3008/test.esp32.yaml b/tests/components/mcp3008/test.esp32.yaml new file mode 100644 index 0000000000..a66fbeb7a1 --- /dev/null +++ b/tests/components/mcp3008/test.esp32.yaml @@ -0,0 +1,17 @@ +spi: + - id: spi_mcp3008 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +mcp3008: + - id: mcp3008_hub + cs_pin: 12 + +sensor: + - platform: mcp3008 + id: mcp3008_sensor + mcp3008_id: mcp3008_hub + number: 0 + reference_voltage: 3.19 + update_interval: 5s diff --git a/tests/components/mcp3008/test.esp8266.yaml b/tests/components/mcp3008/test.esp8266.yaml new file mode 100644 index 0000000000..eaccca0765 --- /dev/null +++ b/tests/components/mcp3008/test.esp8266.yaml @@ -0,0 +1,17 @@ +spi: + - id: spi_mcp3008 + clk_pin: 14 + mosi_pin: 13 + miso_pin: 12 + +mcp3008: + - id: mcp3008_hub + cs_pin: 15 + +sensor: + - platform: mcp3008 + id: mcp3008_sensor + mcp3008_id: mcp3008_hub + number: 0 + reference_voltage: 3.19 + update_interval: 5s diff --git a/tests/components/mcp3008/test.rp2040.yaml b/tests/components/mcp3008/test.rp2040.yaml new file mode 100644 index 0000000000..8ab9630553 --- /dev/null +++ b/tests/components/mcp3008/test.rp2040.yaml @@ -0,0 +1,17 @@ +spi: + - id: spi_mcp3008 + clk_pin: 2 + mosi_pin: 3 + miso_pin: 4 + +mcp3008: + - id: mcp3008_hub + cs_pin: 6 + +sensor: + - platform: mcp3008 + id: mcp3008_sensor + mcp3008_id: mcp3008_hub + number: 0 + reference_voltage: 3.19 + update_interval: 5s diff --git a/tests/components/mcp3204/test.esp32-c3-idf.yaml b/tests/components/mcp3204/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..5bf5ba81e1 --- /dev/null +++ b/tests/components/mcp3204/test.esp32-c3-idf.yaml @@ -0,0 +1,16 @@ +spi: + - id: spi_mcp3204 + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +mcp3204: + - id: mcp3204_hub + cs_pin: 8 + +sensor: + - platform: mcp3204 + id: mcp3204_sensor + mcp3204_id: mcp3204_hub + number: 0 + update_interval: 5s diff --git a/tests/components/mcp3204/test.esp32-c3.yaml b/tests/components/mcp3204/test.esp32-c3.yaml new file mode 100644 index 0000000000..5bf5ba81e1 --- /dev/null +++ b/tests/components/mcp3204/test.esp32-c3.yaml @@ -0,0 +1,16 @@ +spi: + - id: spi_mcp3204 + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +mcp3204: + - id: mcp3204_hub + cs_pin: 8 + +sensor: + - platform: mcp3204 + id: mcp3204_sensor + mcp3204_id: mcp3204_hub + number: 0 + update_interval: 5s diff --git a/tests/components/mcp3204/test.esp32-idf.yaml b/tests/components/mcp3204/test.esp32-idf.yaml new file mode 100644 index 0000000000..c340797c8e --- /dev/null +++ b/tests/components/mcp3204/test.esp32-idf.yaml @@ -0,0 +1,16 @@ +spi: + - id: spi_mcp3204 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +mcp3204: + - id: mcp3204_hub + cs_pin: 12 + +sensor: + - platform: mcp3204 + id: mcp3204_sensor + mcp3204_id: mcp3204_hub + number: 0 + update_interval: 5s diff --git a/tests/components/mcp3204/test.esp32.yaml b/tests/components/mcp3204/test.esp32.yaml new file mode 100644 index 0000000000..c340797c8e --- /dev/null +++ b/tests/components/mcp3204/test.esp32.yaml @@ -0,0 +1,16 @@ +spi: + - id: spi_mcp3204 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +mcp3204: + - id: mcp3204_hub + cs_pin: 12 + +sensor: + - platform: mcp3204 + id: mcp3204_sensor + mcp3204_id: mcp3204_hub + number: 0 + update_interval: 5s diff --git a/tests/components/mcp3204/test.esp8266.yaml b/tests/components/mcp3204/test.esp8266.yaml new file mode 100644 index 0000000000..d208e3e06c --- /dev/null +++ b/tests/components/mcp3204/test.esp8266.yaml @@ -0,0 +1,16 @@ +spi: + - id: spi_mcp3204 + clk_pin: 14 + mosi_pin: 13 + miso_pin: 12 + +mcp3204: + - id: mcp3204_hub + cs_pin: 15 + +sensor: + - platform: mcp3204 + id: mcp3204_sensor + mcp3204_id: mcp3204_hub + number: 0 + update_interval: 5s diff --git a/tests/components/mcp3204/test.rp2040.yaml b/tests/components/mcp3204/test.rp2040.yaml new file mode 100644 index 0000000000..63f30e3621 --- /dev/null +++ b/tests/components/mcp3204/test.rp2040.yaml @@ -0,0 +1,16 @@ +spi: + - id: spi_mcp3204 + clk_pin: 2 + mosi_pin: 3 + miso_pin: 4 + +mcp3204: + - id: mcp3204_hub + cs_pin: 6 + +sensor: + - platform: mcp3204 + id: mcp3204_sensor + mcp3204_id: mcp3204_hub + number: 0 + update_interval: 5s diff --git a/tests/components/mcp4725/test.esp32-c3-idf.yaml b/tests/components/mcp4725/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..5fc799203d --- /dev/null +++ b/tests/components/mcp4725/test.esp32-c3-idf.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_mcp4725 + scl: 5 + sda: 4 + +output: + - platform: mcp4725 + id: mcp4725_dac_output diff --git a/tests/components/mcp4725/test.esp32-c3.yaml b/tests/components/mcp4725/test.esp32-c3.yaml new file mode 100644 index 0000000000..5fc799203d --- /dev/null +++ b/tests/components/mcp4725/test.esp32-c3.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_mcp4725 + scl: 5 + sda: 4 + +output: + - platform: mcp4725 + id: mcp4725_dac_output diff --git a/tests/components/mcp4725/test.esp32-idf.yaml b/tests/components/mcp4725/test.esp32-idf.yaml new file mode 100644 index 0000000000..a523ad95e1 --- /dev/null +++ b/tests/components/mcp4725/test.esp32-idf.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_mcp4725 + scl: 16 + sda: 17 + +output: + - platform: mcp4725 + id: mcp4725_dac_output diff --git a/tests/components/mcp4725/test.esp32.yaml b/tests/components/mcp4725/test.esp32.yaml new file mode 100644 index 0000000000..a523ad95e1 --- /dev/null +++ b/tests/components/mcp4725/test.esp32.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_mcp4725 + scl: 16 + sda: 17 + +output: + - platform: mcp4725 + id: mcp4725_dac_output diff --git a/tests/components/mcp4725/test.esp8266.yaml b/tests/components/mcp4725/test.esp8266.yaml new file mode 100644 index 0000000000..5fc799203d --- /dev/null +++ b/tests/components/mcp4725/test.esp8266.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_mcp4725 + scl: 5 + sda: 4 + +output: + - platform: mcp4725 + id: mcp4725_dac_output diff --git a/tests/components/mcp4725/test.rp2040.yaml b/tests/components/mcp4725/test.rp2040.yaml new file mode 100644 index 0000000000..5fc799203d --- /dev/null +++ b/tests/components/mcp4725/test.rp2040.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_mcp4725 + scl: 5 + sda: 4 + +output: + - platform: mcp4725 + id: mcp4725_dac_output diff --git a/tests/components/mcp4728/test.esp32-c3-idf.yaml b/tests/components/mcp4728/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..2f24dd0b8c --- /dev/null +++ b/tests/components/mcp4728/test.esp32-c3-idf.yaml @@ -0,0 +1,31 @@ +i2c: + - id: i2c_mcp4728 + scl: 5 + sda: 4 + +mcp4728: + - id: mcp4728_dac + +output: + - platform: mcp4728 + id: mcp4728_dac_output_a + channel: A + vref: vdd + power_down: normal + - platform: mcp4728 + id: mcp4728_dac_output_b + channel: B + vref: internal + gain: X1 + power_down: gnd_1k + - platform: mcp4728 + id: mcp4728_dac_output_c + channel: C + vref: vdd + power_down: gnd_100k + - platform: mcp4728 + id: mcp4728_dac_output_d + channel: D + vref: internal + gain: X2 + power_down: gnd_500k diff --git a/tests/components/mcp4728/test.esp32-c3.yaml b/tests/components/mcp4728/test.esp32-c3.yaml new file mode 100644 index 0000000000..2f24dd0b8c --- /dev/null +++ b/tests/components/mcp4728/test.esp32-c3.yaml @@ -0,0 +1,31 @@ +i2c: + - id: i2c_mcp4728 + scl: 5 + sda: 4 + +mcp4728: + - id: mcp4728_dac + +output: + - platform: mcp4728 + id: mcp4728_dac_output_a + channel: A + vref: vdd + power_down: normal + - platform: mcp4728 + id: mcp4728_dac_output_b + channel: B + vref: internal + gain: X1 + power_down: gnd_1k + - platform: mcp4728 + id: mcp4728_dac_output_c + channel: C + vref: vdd + power_down: gnd_100k + - platform: mcp4728 + id: mcp4728_dac_output_d + channel: D + vref: internal + gain: X2 + power_down: gnd_500k diff --git a/tests/components/mcp4728/test.esp32-idf.yaml b/tests/components/mcp4728/test.esp32-idf.yaml new file mode 100644 index 0000000000..b29a6ee53c --- /dev/null +++ b/tests/components/mcp4728/test.esp32-idf.yaml @@ -0,0 +1,31 @@ +i2c: + - id: i2c_mcp4728 + scl: 16 + sda: 17 + +mcp4728: + - id: mcp4728_dac + +output: + - platform: mcp4728 + id: mcp4728_dac_output_a + channel: A + vref: vdd + power_down: normal + - platform: mcp4728 + id: mcp4728_dac_output_b + channel: B + vref: internal + gain: X1 + power_down: gnd_1k + - platform: mcp4728 + id: mcp4728_dac_output_c + channel: C + vref: vdd + power_down: gnd_100k + - platform: mcp4728 + id: mcp4728_dac_output_d + channel: D + vref: internal + gain: X2 + power_down: gnd_500k diff --git a/tests/components/mcp4728/test.esp32.yaml b/tests/components/mcp4728/test.esp32.yaml new file mode 100644 index 0000000000..b29a6ee53c --- /dev/null +++ b/tests/components/mcp4728/test.esp32.yaml @@ -0,0 +1,31 @@ +i2c: + - id: i2c_mcp4728 + scl: 16 + sda: 17 + +mcp4728: + - id: mcp4728_dac + +output: + - platform: mcp4728 + id: mcp4728_dac_output_a + channel: A + vref: vdd + power_down: normal + - platform: mcp4728 + id: mcp4728_dac_output_b + channel: B + vref: internal + gain: X1 + power_down: gnd_1k + - platform: mcp4728 + id: mcp4728_dac_output_c + channel: C + vref: vdd + power_down: gnd_100k + - platform: mcp4728 + id: mcp4728_dac_output_d + channel: D + vref: internal + gain: X2 + power_down: gnd_500k diff --git a/tests/components/mcp4728/test.esp8266.yaml b/tests/components/mcp4728/test.esp8266.yaml new file mode 100644 index 0000000000..2f24dd0b8c --- /dev/null +++ b/tests/components/mcp4728/test.esp8266.yaml @@ -0,0 +1,31 @@ +i2c: + - id: i2c_mcp4728 + scl: 5 + sda: 4 + +mcp4728: + - id: mcp4728_dac + +output: + - platform: mcp4728 + id: mcp4728_dac_output_a + channel: A + vref: vdd + power_down: normal + - platform: mcp4728 + id: mcp4728_dac_output_b + channel: B + vref: internal + gain: X1 + power_down: gnd_1k + - platform: mcp4728 + id: mcp4728_dac_output_c + channel: C + vref: vdd + power_down: gnd_100k + - platform: mcp4728 + id: mcp4728_dac_output_d + channel: D + vref: internal + gain: X2 + power_down: gnd_500k diff --git a/tests/components/mcp4728/test.rp2040.yaml b/tests/components/mcp4728/test.rp2040.yaml new file mode 100644 index 0000000000..2f24dd0b8c --- /dev/null +++ b/tests/components/mcp4728/test.rp2040.yaml @@ -0,0 +1,31 @@ +i2c: + - id: i2c_mcp4728 + scl: 5 + sda: 4 + +mcp4728: + - id: mcp4728_dac + +output: + - platform: mcp4728 + id: mcp4728_dac_output_a + channel: A + vref: vdd + power_down: normal + - platform: mcp4728 + id: mcp4728_dac_output_b + channel: B + vref: internal + gain: X1 + power_down: gnd_1k + - platform: mcp4728 + id: mcp4728_dac_output_c + channel: C + vref: vdd + power_down: gnd_100k + - platform: mcp4728 + id: mcp4728_dac_output_d + channel: D + vref: internal + gain: X2 + power_down: gnd_500k diff --git a/tests/components/mcp47a1/test.esp32-c3-idf.yaml b/tests/components/mcp47a1/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..68273e00eb --- /dev/null +++ b/tests/components/mcp47a1/test.esp32-c3-idf.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_mcp47a1 + scl: 5 + sda: 4 + +output: + - platform: mcp47a1 + id: output_mcp47a1 diff --git a/tests/components/mcp47a1/test.esp32-c3.yaml b/tests/components/mcp47a1/test.esp32-c3.yaml new file mode 100644 index 0000000000..68273e00eb --- /dev/null +++ b/tests/components/mcp47a1/test.esp32-c3.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_mcp47a1 + scl: 5 + sda: 4 + +output: + - platform: mcp47a1 + id: output_mcp47a1 diff --git a/tests/components/mcp47a1/test.esp32-idf.yaml b/tests/components/mcp47a1/test.esp32-idf.yaml new file mode 100644 index 0000000000..9e2133de66 --- /dev/null +++ b/tests/components/mcp47a1/test.esp32-idf.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_mcp47a1 + scl: 16 + sda: 17 + +output: + - platform: mcp47a1 + id: output_mcp47a1 diff --git a/tests/components/mcp47a1/test.esp32.yaml b/tests/components/mcp47a1/test.esp32.yaml new file mode 100644 index 0000000000..9e2133de66 --- /dev/null +++ b/tests/components/mcp47a1/test.esp32.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_mcp47a1 + scl: 16 + sda: 17 + +output: + - platform: mcp47a1 + id: output_mcp47a1 diff --git a/tests/components/mcp47a1/test.esp8266.yaml b/tests/components/mcp47a1/test.esp8266.yaml new file mode 100644 index 0000000000..68273e00eb --- /dev/null +++ b/tests/components/mcp47a1/test.esp8266.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_mcp47a1 + scl: 5 + sda: 4 + +output: + - platform: mcp47a1 + id: output_mcp47a1 diff --git a/tests/components/mcp47a1/test.rp2040.yaml b/tests/components/mcp47a1/test.rp2040.yaml new file mode 100644 index 0000000000..68273e00eb --- /dev/null +++ b/tests/components/mcp47a1/test.rp2040.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_mcp47a1 + scl: 5 + sda: 4 + +output: + - platform: mcp47a1 + id: output_mcp47a1 diff --git a/tests/components/mcp9600/test.esp32-c3-idf.yaml b/tests/components/mcp9600/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..b07f4589ce --- /dev/null +++ b/tests/components/mcp9600/test.esp32-c3-idf.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_mcp9600 + scl: 5 + sda: 4 + +sensor: + - platform: mcp9600 + thermocouple_type: K + hot_junction: + name: Thermocouple Temperature + cold_junction: + name: Ambient Temperature diff --git a/tests/components/mcp9600/test.esp32-c3.yaml b/tests/components/mcp9600/test.esp32-c3.yaml new file mode 100644 index 0000000000..b07f4589ce --- /dev/null +++ b/tests/components/mcp9600/test.esp32-c3.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_mcp9600 + scl: 5 + sda: 4 + +sensor: + - platform: mcp9600 + thermocouple_type: K + hot_junction: + name: Thermocouple Temperature + cold_junction: + name: Ambient Temperature diff --git a/tests/components/mcp9600/test.esp32-idf.yaml b/tests/components/mcp9600/test.esp32-idf.yaml new file mode 100644 index 0000000000..0c94f099ae --- /dev/null +++ b/tests/components/mcp9600/test.esp32-idf.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_mcp9600 + scl: 16 + sda: 17 + +sensor: + - platform: mcp9600 + thermocouple_type: K + hot_junction: + name: Thermocouple Temperature + cold_junction: + name: Ambient Temperature diff --git a/tests/components/mcp9600/test.esp32.yaml b/tests/components/mcp9600/test.esp32.yaml new file mode 100644 index 0000000000..0c94f099ae --- /dev/null +++ b/tests/components/mcp9600/test.esp32.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_mcp9600 + scl: 16 + sda: 17 + +sensor: + - platform: mcp9600 + thermocouple_type: K + hot_junction: + name: Thermocouple Temperature + cold_junction: + name: Ambient Temperature diff --git a/tests/components/mcp9600/test.esp8266.yaml b/tests/components/mcp9600/test.esp8266.yaml new file mode 100644 index 0000000000..b07f4589ce --- /dev/null +++ b/tests/components/mcp9600/test.esp8266.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_mcp9600 + scl: 5 + sda: 4 + +sensor: + - platform: mcp9600 + thermocouple_type: K + hot_junction: + name: Thermocouple Temperature + cold_junction: + name: Ambient Temperature diff --git a/tests/components/mcp9600/test.rp2040.yaml b/tests/components/mcp9600/test.rp2040.yaml new file mode 100644 index 0000000000..b07f4589ce --- /dev/null +++ b/tests/components/mcp9600/test.rp2040.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_mcp9600 + scl: 5 + sda: 4 + +sensor: + - platform: mcp9600 + thermocouple_type: K + hot_junction: + name: Thermocouple Temperature + cold_junction: + name: Ambient Temperature diff --git a/tests/components/mcp9808/test.esp32-c3-idf.yaml b/tests/components/mcp9808/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..86b4d7f181 --- /dev/null +++ b/tests/components/mcp9808/test.esp32-c3-idf.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_mcp9808 + scl: 5 + sda: 4 + +sensor: + - platform: mcp9808 + name: MCP9808 Temperature diff --git a/tests/components/mcp9808/test.esp32-c3.yaml b/tests/components/mcp9808/test.esp32-c3.yaml new file mode 100644 index 0000000000..86b4d7f181 --- /dev/null +++ b/tests/components/mcp9808/test.esp32-c3.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_mcp9808 + scl: 5 + sda: 4 + +sensor: + - platform: mcp9808 + name: MCP9808 Temperature diff --git a/tests/components/mcp9808/test.esp32-idf.yaml b/tests/components/mcp9808/test.esp32-idf.yaml new file mode 100644 index 0000000000..1e5affdac0 --- /dev/null +++ b/tests/components/mcp9808/test.esp32-idf.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_mcp9808 + scl: 16 + sda: 17 + +sensor: + - platform: mcp9808 + name: MCP9808 Temperature diff --git a/tests/components/mcp9808/test.esp32.yaml b/tests/components/mcp9808/test.esp32.yaml new file mode 100644 index 0000000000..1e5affdac0 --- /dev/null +++ b/tests/components/mcp9808/test.esp32.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_mcp9808 + scl: 16 + sda: 17 + +sensor: + - platform: mcp9808 + name: MCP9808 Temperature diff --git a/tests/components/mcp9808/test.esp8266.yaml b/tests/components/mcp9808/test.esp8266.yaml new file mode 100644 index 0000000000..86b4d7f181 --- /dev/null +++ b/tests/components/mcp9808/test.esp8266.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_mcp9808 + scl: 5 + sda: 4 + +sensor: + - platform: mcp9808 + name: MCP9808 Temperature diff --git a/tests/components/mcp9808/test.rp2040.yaml b/tests/components/mcp9808/test.rp2040.yaml new file mode 100644 index 0000000000..86b4d7f181 --- /dev/null +++ b/tests/components/mcp9808/test.rp2040.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_mcp9808 + scl: 5 + sda: 4 + +sensor: + - platform: mcp9808 + name: MCP9808 Temperature diff --git a/tests/components/mdns/test.esp32-c3-idf.yaml b/tests/components/mdns/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..bc31e32783 --- /dev/null +++ b/tests/components/mdns/test.esp32-c3-idf.yaml @@ -0,0 +1,6 @@ +wifi: + ssid: MySSID + password: password1 + +mdns: + disabled: false diff --git a/tests/components/mdns/test.esp32-c3.yaml b/tests/components/mdns/test.esp32-c3.yaml new file mode 100644 index 0000000000..bc31e32783 --- /dev/null +++ b/tests/components/mdns/test.esp32-c3.yaml @@ -0,0 +1,6 @@ +wifi: + ssid: MySSID + password: password1 + +mdns: + disabled: false diff --git a/tests/components/mdns/test.esp32-idf.yaml b/tests/components/mdns/test.esp32-idf.yaml new file mode 100644 index 0000000000..bc31e32783 --- /dev/null +++ b/tests/components/mdns/test.esp32-idf.yaml @@ -0,0 +1,6 @@ +wifi: + ssid: MySSID + password: password1 + +mdns: + disabled: false diff --git a/tests/components/mdns/test.esp32.yaml b/tests/components/mdns/test.esp32.yaml new file mode 100644 index 0000000000..bc31e32783 --- /dev/null +++ b/tests/components/mdns/test.esp32.yaml @@ -0,0 +1,6 @@ +wifi: + ssid: MySSID + password: password1 + +mdns: + disabled: false diff --git a/tests/components/mdns/test.esp8266.yaml b/tests/components/mdns/test.esp8266.yaml new file mode 100644 index 0000000000..bc31e32783 --- /dev/null +++ b/tests/components/mdns/test.esp8266.yaml @@ -0,0 +1,6 @@ +wifi: + ssid: MySSID + password: password1 + +mdns: + disabled: false diff --git a/tests/components/mdns/test.rp2040.yaml b/tests/components/mdns/test.rp2040.yaml new file mode 100644 index 0000000000..bc31e32783 --- /dev/null +++ b/tests/components/mdns/test.rp2040.yaml @@ -0,0 +1,6 @@ +wifi: + ssid: MySSID + password: password1 + +mdns: + disabled: false diff --git a/tests/components/media_player/test.esp32.yaml b/tests/components/media_player/test.esp32.yaml new file mode 100644 index 0000000000..24b85cd474 --- /dev/null +++ b/tests/components/media_player/test.esp32.yaml @@ -0,0 +1,32 @@ +wifi: + ssid: MySSID + password: password1 + +i2s_audio: + i2s_lrclk_pin: 13 + i2s_bclk_pin: 14 + i2s_mclk_pin: 15 + +media_player: + - platform: i2s_audio + name: None + dac_type: external + i2s_dout_pin: 18 + mute_pin: 19 + on_state: + - media_player.play: + - media_player.play_media: http://localhost/media.mp3 + - media_player.play_media: !lambda 'return "http://localhost/media.mp3";' + on_idle: + - media_player.pause: + on_play: + - media_player.stop: + on_pause: + - media_player.toggle: + - wait_until: + media_player.is_idle: + - wait_until: + media_player.is_playing: + - media_player.volume_up: + - media_player.volume_down: + - media_player.volume_set: 50% diff --git a/tests/components/mhz19/test.esp32-c3-idf.yaml b/tests/components/mhz19/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..1edfa49c23 --- /dev/null +++ b/tests/components/mhz19/test.esp32-c3-idf.yaml @@ -0,0 +1,14 @@ +uart: + - id: uart_mhz19 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sensor: + - platform: mhz19 + co2: + name: MH-Z19 CO2 Value + temperature: + name: MH-Z19 Temperature + automatic_baseline_calibration: false + update_interval: 15s diff --git a/tests/components/mhz19/test.esp32-c3.yaml b/tests/components/mhz19/test.esp32-c3.yaml new file mode 100644 index 0000000000..1edfa49c23 --- /dev/null +++ b/tests/components/mhz19/test.esp32-c3.yaml @@ -0,0 +1,14 @@ +uart: + - id: uart_mhz19 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sensor: + - platform: mhz19 + co2: + name: MH-Z19 CO2 Value + temperature: + name: MH-Z19 Temperature + automatic_baseline_calibration: false + update_interval: 15s diff --git a/tests/components/mhz19/test.esp32-idf.yaml b/tests/components/mhz19/test.esp32-idf.yaml new file mode 100644 index 0000000000..0e30713b54 --- /dev/null +++ b/tests/components/mhz19/test.esp32-idf.yaml @@ -0,0 +1,14 @@ +uart: + - id: uart_mhz19 + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +sensor: + - platform: mhz19 + co2: + name: MH-Z19 CO2 Value + temperature: + name: MH-Z19 Temperature + automatic_baseline_calibration: false + update_interval: 15s diff --git a/tests/components/mhz19/test.esp32.yaml b/tests/components/mhz19/test.esp32.yaml new file mode 100644 index 0000000000..0e30713b54 --- /dev/null +++ b/tests/components/mhz19/test.esp32.yaml @@ -0,0 +1,14 @@ +uart: + - id: uart_mhz19 + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +sensor: + - platform: mhz19 + co2: + name: MH-Z19 CO2 Value + temperature: + name: MH-Z19 Temperature + automatic_baseline_calibration: false + update_interval: 15s diff --git a/tests/components/mhz19/test.esp8266.yaml b/tests/components/mhz19/test.esp8266.yaml new file mode 100644 index 0000000000..1edfa49c23 --- /dev/null +++ b/tests/components/mhz19/test.esp8266.yaml @@ -0,0 +1,14 @@ +uart: + - id: uart_mhz19 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sensor: + - platform: mhz19 + co2: + name: MH-Z19 CO2 Value + temperature: + name: MH-Z19 Temperature + automatic_baseline_calibration: false + update_interval: 15s diff --git a/tests/components/mhz19/test.rp2040.yaml b/tests/components/mhz19/test.rp2040.yaml new file mode 100644 index 0000000000..1edfa49c23 --- /dev/null +++ b/tests/components/mhz19/test.rp2040.yaml @@ -0,0 +1,14 @@ +uart: + - id: uart_mhz19 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sensor: + - platform: mhz19 + co2: + name: MH-Z19 CO2 Value + temperature: + name: MH-Z19 Temperature + automatic_baseline_calibration: false + update_interval: 15s From c0dc9c20fc7b383659d962cf4ef6de283ca45ba1 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Mon, 22 Apr 2024 22:45:25 -0500 Subject: [PATCH 1303/2101] Add some components to the new testing framework (M part 2) (#6208) --- .../micronova/test.esp32-c3-idf.yaml | 49 +++++++++++++++ tests/components/micronova/test.esp32-c3.yaml | 49 +++++++++++++++ .../components/micronova/test.esp32-idf.yaml | 49 +++++++++++++++ tests/components/micronova/test.esp32.yaml | 49 +++++++++++++++ tests/components/micronova/test.esp8266.yaml | 49 +++++++++++++++ tests/components/micronova/test.rp2040.yaml | 49 +++++++++++++++ .../microphone/test.esp32-c3-idf.yaml | 11 ++++ .../components/microphone/test.esp32-c3.yaml | 11 ++++ .../components/microphone/test.esp32-idf.yaml | 15 +++++ tests/components/microphone/test.esp32.yaml | 15 +++++ .../mics_4514/test.esp32-c3-idf.yaml | 20 +++++++ tests/components/mics_4514/test.esp32-c3.yaml | 20 +++++++ .../components/mics_4514/test.esp32-idf.yaml | 20 +++++++ tests/components/mics_4514/test.esp32.yaml | 20 +++++++ tests/components/mics_4514/test.esp8266.yaml | 20 +++++++ tests/components/mics_4514/test.rp2040.yaml | 20 +++++++ tests/components/midea/test.esp32-c3.yaml | 59 +++++++++++++++++++ tests/components/midea/test.esp32.yaml | 59 +++++++++++++++++++ tests/components/midea/test.esp8266.yaml | 59 +++++++++++++++++++ .../midea_ir/test.esp32-c3-idf.yaml | 8 +++ tests/components/midea_ir/test.esp32-c3.yaml | 8 +++ tests/components/midea_ir/test.esp32-idf.yaml | 8 +++ tests/components/midea_ir/test.esp32.yaml | 8 +++ tests/components/midea_ir/test.esp8266.yaml | 8 +++ .../mitsubishi/test.esp32-c3-idf.yaml | 7 +++ .../components/mitsubishi/test.esp32-c3.yaml | 7 +++ .../components/mitsubishi/test.esp32-idf.yaml | 7 +++ tests/components/mitsubishi/test.esp32.yaml | 7 +++ tests/components/mitsubishi/test.esp8266.yaml | 7 +++ .../mlx90393/test.esp32-c3-idf.yaml | 20 +++++++ tests/components/mlx90393/test.esp32-c3.yaml | 20 +++++++ tests/components/mlx90393/test.esp32-idf.yaml | 20 +++++++ tests/components/mlx90393/test.esp32.yaml | 20 +++++++ tests/components/mlx90393/test.esp8266.yaml | 20 +++++++ tests/components/mlx90393/test.rp2040.yaml | 20 +++++++ .../mlx90614/test.esp32-c3-idf.yaml | 12 ++++ tests/components/mlx90614/test.esp32-c3.yaml | 12 ++++ tests/components/mlx90614/test.esp32-idf.yaml | 12 ++++ tests/components/mlx90614/test.esp32.yaml | 12 ++++ tests/components/mlx90614/test.esp8266.yaml | 12 ++++ tests/components/mlx90614/test.rp2040.yaml | 12 ++++ .../components/mmc5603/test.esp32-c3-idf.yaml | 14 +++++ tests/components/mmc5603/test.esp32-c3.yaml | 14 +++++ tests/components/mmc5603/test.esp32-idf.yaml | 14 +++++ tests/components/mmc5603/test.esp32.yaml | 14 +++++ tests/components/mmc5603/test.esp8266.yaml | 14 +++++ tests/components/mmc5603/test.rp2040.yaml | 14 +++++ .../components/mmc5983/test.esp32-c3-idf.yaml | 16 +++++ tests/components/mmc5983/test.esp32-c3.yaml | 16 +++++ tests/components/mmc5983/test.esp32-idf.yaml | 16 +++++ tests/components/mmc5983/test.esp32.yaml | 16 +++++ tests/components/mmc5983/test.esp8266.yaml | 16 +++++ tests/components/mmc5983/test.rp2040.yaml | 16 +++++ .../components/modbus/test.esp32-c3-idf.yaml | 9 +++ tests/components/modbus/test.esp32-c3.yaml | 9 +++ tests/components/modbus/test.esp32-idf.yaml | 9 +++ tests/components/modbus/test.esp32.yaml | 9 +++ tests/components/modbus/test.esp8266.yaml | 9 +++ tests/components/modbus/test.rp2040.yaml | 9 +++ .../modbus_controller/test.esp32-c3-idf.yaml | 14 +++++ .../modbus_controller/test.esp32-c3.yaml | 14 +++++ .../modbus_controller/test.esp32-idf.yaml | 14 +++++ .../modbus_controller/test.esp32.yaml | 14 +++++ .../modbus_controller/test.esp8266.yaml | 14 +++++ .../modbus_controller/test.rp2040.yaml | 14 +++++ .../monochromatic/test.esp32-c3-idf.yaml | 40 +++++++++++++ .../monochromatic/test.esp32-c3.yaml | 40 +++++++++++++ .../monochromatic/test.esp32-idf.yaml | 40 +++++++++++++ .../components/monochromatic/test.esp32.yaml | 40 +++++++++++++ .../monochromatic/test.esp8266.yaml | 40 +++++++++++++ .../components/monochromatic/test.rp2040.yaml | 40 +++++++++++++ .../mopeka_ble/test.esp32-c3-idf.yaml | 3 + .../components/mopeka_ble/test.esp32-c3.yaml | 3 + .../components/mopeka_ble/test.esp32-idf.yaml | 3 + tests/components/mopeka_ble/test.esp32.yaml | 3 + .../mopeka_pro_check/test.esp32-c3-idf.yaml | 16 +++++ .../mopeka_pro_check/test.esp32-c3.yaml | 16 +++++ .../mopeka_pro_check/test.esp32-idf.yaml | 16 +++++ .../mopeka_pro_check/test.esp32.yaml | 16 +++++ .../mopeka_std_check/test.esp32-c3-idf.yaml | 16 +++++ .../mopeka_std_check/test.esp32-c3.yaml | 16 +++++ .../mopeka_std_check/test.esp32-idf.yaml | 16 +++++ .../mpl3115a2/test.esp32-c3-idf.yaml | 12 ++++ tests/components/mpl3115a2/test.esp32-c3.yaml | 12 ++++ .../components/mpl3115a2/test.esp32-idf.yaml | 12 ++++ tests/components/mpl3115a2/test.esp32.yaml | 12 ++++ tests/components/mpl3115a2/test.esp8266.yaml | 12 ++++ tests/components/mpl3115a2/test.rp2040.yaml | 12 ++++ .../components/mpr121/test.esp32-c3-idf.yaml | 26 ++++++++ tests/components/mpr121/test.esp32-c3.yaml | 26 ++++++++ tests/components/mpr121/test.esp32-idf.yaml | 26 ++++++++ tests/components/mpr121/test.esp32.yaml | 26 ++++++++ tests/components/mpr121/test.esp8266.yaml | 26 ++++++++ tests/components/mpr121/test.rp2040.yaml | 26 ++++++++ .../components/mpu6050/test.esp32-c3-idf.yaml | 22 +++++++ tests/components/mpu6050/test.esp32-c3.yaml | 22 +++++++ tests/components/mpu6050/test.esp32-idf.yaml | 22 +++++++ tests/components/mpu6050/test.esp32.yaml | 22 +++++++ tests/components/mpu6050/test.esp8266.yaml | 22 +++++++ tests/components/mpu6050/test.rp2040.yaml | 22 +++++++ .../components/mpu6886/test.esp32-c3-idf.yaml | 22 +++++++ tests/components/mpu6886/test.esp32-c3.yaml | 22 +++++++ tests/components/mpu6886/test.esp32-idf.yaml | 22 +++++++ tests/components/mpu6886/test.esp32.yaml | 22 +++++++ tests/components/mpu6886/test.esp8266.yaml | 22 +++++++ tests/components/mpu6886/test.rp2040.yaml | 22 +++++++ tests/components/mqtt/test.esp32-c3-idf.yaml | 16 +++++ tests/components/mqtt/test.esp32-c3.yaml | 15 +++++ tests/components/mqtt/test.esp32-idf.yaml | 16 +++++ tests/components/mqtt/test.esp32.yaml | 15 +++++ tests/components/mqtt/test.esp8266.yaml | 15 +++++ .../mqtt_subscribe/test.esp32-c3-idf.yaml | 37 ++++++++++++ .../mqtt_subscribe/test.esp32-c3.yaml | 36 +++++++++++ .../mqtt_subscribe/test.esp32-idf.yaml | 37 ++++++++++++ .../components/mqtt_subscribe/test.esp32.yaml | 36 +++++++++++ .../mqtt_subscribe/test.esp8266.yaml | 36 +++++++++++ .../components/ms5611/test.esp32-c3-idf.yaml | 13 ++++ tests/components/ms5611/test.esp32-c3.yaml | 13 ++++ tests/components/ms5611/test.esp32-idf.yaml | 13 ++++ tests/components/ms5611/test.esp32.yaml | 13 ++++ tests/components/ms5611/test.esp8266.yaml | 13 ++++ tests/components/ms5611/test.rp2040.yaml | 13 ++++ .../components/my9231/test.esp32-c3-idf.yaml | 26 ++++++++ tests/components/my9231/test.esp32-c3.yaml | 26 ++++++++ tests/components/my9231/test.esp32-idf.yaml | 26 ++++++++ tests/components/my9231/test.esp32.yaml | 26 ++++++++ tests/components/my9231/test.esp8266.yaml | 26 ++++++++ tests/components/my9231/test.rp2040.yaml | 26 ++++++++ 128 files changed, 2577 insertions(+) create mode 100644 tests/components/micronova/test.esp32-c3-idf.yaml create mode 100644 tests/components/micronova/test.esp32-c3.yaml create mode 100644 tests/components/micronova/test.esp32-idf.yaml create mode 100644 tests/components/micronova/test.esp32.yaml create mode 100644 tests/components/micronova/test.esp8266.yaml create mode 100644 tests/components/micronova/test.rp2040.yaml create mode 100644 tests/components/microphone/test.esp32-c3-idf.yaml create mode 100644 tests/components/microphone/test.esp32-c3.yaml create mode 100644 tests/components/microphone/test.esp32-idf.yaml create mode 100644 tests/components/microphone/test.esp32.yaml create mode 100644 tests/components/mics_4514/test.esp32-c3-idf.yaml create mode 100644 tests/components/mics_4514/test.esp32-c3.yaml create mode 100644 tests/components/mics_4514/test.esp32-idf.yaml create mode 100644 tests/components/mics_4514/test.esp32.yaml create mode 100644 tests/components/mics_4514/test.esp8266.yaml create mode 100644 tests/components/mics_4514/test.rp2040.yaml create mode 100644 tests/components/midea/test.esp32-c3.yaml create mode 100644 tests/components/midea/test.esp32.yaml create mode 100644 tests/components/midea/test.esp8266.yaml create mode 100644 tests/components/midea_ir/test.esp32-c3-idf.yaml create mode 100644 tests/components/midea_ir/test.esp32-c3.yaml create mode 100644 tests/components/midea_ir/test.esp32-idf.yaml create mode 100644 tests/components/midea_ir/test.esp32.yaml create mode 100644 tests/components/midea_ir/test.esp8266.yaml create mode 100644 tests/components/mitsubishi/test.esp32-c3-idf.yaml create mode 100644 tests/components/mitsubishi/test.esp32-c3.yaml create mode 100644 tests/components/mitsubishi/test.esp32-idf.yaml create mode 100644 tests/components/mitsubishi/test.esp32.yaml create mode 100644 tests/components/mitsubishi/test.esp8266.yaml create mode 100644 tests/components/mlx90393/test.esp32-c3-idf.yaml create mode 100644 tests/components/mlx90393/test.esp32-c3.yaml create mode 100644 tests/components/mlx90393/test.esp32-idf.yaml create mode 100644 tests/components/mlx90393/test.esp32.yaml create mode 100644 tests/components/mlx90393/test.esp8266.yaml create mode 100644 tests/components/mlx90393/test.rp2040.yaml create mode 100644 tests/components/mlx90614/test.esp32-c3-idf.yaml create mode 100644 tests/components/mlx90614/test.esp32-c3.yaml create mode 100644 tests/components/mlx90614/test.esp32-idf.yaml create mode 100644 tests/components/mlx90614/test.esp32.yaml create mode 100644 tests/components/mlx90614/test.esp8266.yaml create mode 100644 tests/components/mlx90614/test.rp2040.yaml create mode 100644 tests/components/mmc5603/test.esp32-c3-idf.yaml create mode 100644 tests/components/mmc5603/test.esp32-c3.yaml create mode 100644 tests/components/mmc5603/test.esp32-idf.yaml create mode 100644 tests/components/mmc5603/test.esp32.yaml create mode 100644 tests/components/mmc5603/test.esp8266.yaml create mode 100644 tests/components/mmc5603/test.rp2040.yaml create mode 100644 tests/components/mmc5983/test.esp32-c3-idf.yaml create mode 100644 tests/components/mmc5983/test.esp32-c3.yaml create mode 100644 tests/components/mmc5983/test.esp32-idf.yaml create mode 100644 tests/components/mmc5983/test.esp32.yaml create mode 100644 tests/components/mmc5983/test.esp8266.yaml create mode 100644 tests/components/mmc5983/test.rp2040.yaml create mode 100644 tests/components/modbus/test.esp32-c3-idf.yaml create mode 100644 tests/components/modbus/test.esp32-c3.yaml create mode 100644 tests/components/modbus/test.esp32-idf.yaml create mode 100644 tests/components/modbus/test.esp32.yaml create mode 100644 tests/components/modbus/test.esp8266.yaml create mode 100644 tests/components/modbus/test.rp2040.yaml create mode 100644 tests/components/modbus_controller/test.esp32-c3-idf.yaml create mode 100644 tests/components/modbus_controller/test.esp32-c3.yaml create mode 100644 tests/components/modbus_controller/test.esp32-idf.yaml create mode 100644 tests/components/modbus_controller/test.esp32.yaml create mode 100644 tests/components/modbus_controller/test.esp8266.yaml create mode 100644 tests/components/modbus_controller/test.rp2040.yaml create mode 100644 tests/components/monochromatic/test.esp32-c3-idf.yaml create mode 100644 tests/components/monochromatic/test.esp32-c3.yaml create mode 100644 tests/components/monochromatic/test.esp32-idf.yaml create mode 100644 tests/components/monochromatic/test.esp32.yaml create mode 100644 tests/components/monochromatic/test.esp8266.yaml create mode 100644 tests/components/monochromatic/test.rp2040.yaml create mode 100644 tests/components/mopeka_ble/test.esp32-c3-idf.yaml create mode 100644 tests/components/mopeka_ble/test.esp32-c3.yaml create mode 100644 tests/components/mopeka_ble/test.esp32-idf.yaml create mode 100644 tests/components/mopeka_ble/test.esp32.yaml create mode 100644 tests/components/mopeka_pro_check/test.esp32-c3-idf.yaml create mode 100644 tests/components/mopeka_pro_check/test.esp32-c3.yaml create mode 100644 tests/components/mopeka_pro_check/test.esp32-idf.yaml create mode 100644 tests/components/mopeka_pro_check/test.esp32.yaml create mode 100644 tests/components/mopeka_std_check/test.esp32-c3-idf.yaml create mode 100644 tests/components/mopeka_std_check/test.esp32-c3.yaml create mode 100644 tests/components/mopeka_std_check/test.esp32-idf.yaml create mode 100644 tests/components/mpl3115a2/test.esp32-c3-idf.yaml create mode 100644 tests/components/mpl3115a2/test.esp32-c3.yaml create mode 100644 tests/components/mpl3115a2/test.esp32-idf.yaml create mode 100644 tests/components/mpl3115a2/test.esp32.yaml create mode 100644 tests/components/mpl3115a2/test.esp8266.yaml create mode 100644 tests/components/mpl3115a2/test.rp2040.yaml create mode 100644 tests/components/mpr121/test.esp32-c3-idf.yaml create mode 100644 tests/components/mpr121/test.esp32-c3.yaml create mode 100644 tests/components/mpr121/test.esp32-idf.yaml create mode 100644 tests/components/mpr121/test.esp32.yaml create mode 100644 tests/components/mpr121/test.esp8266.yaml create mode 100644 tests/components/mpr121/test.rp2040.yaml create mode 100644 tests/components/mpu6050/test.esp32-c3-idf.yaml create mode 100644 tests/components/mpu6050/test.esp32-c3.yaml create mode 100644 tests/components/mpu6050/test.esp32-idf.yaml create mode 100644 tests/components/mpu6050/test.esp32.yaml create mode 100644 tests/components/mpu6050/test.esp8266.yaml create mode 100644 tests/components/mpu6050/test.rp2040.yaml create mode 100644 tests/components/mpu6886/test.esp32-c3-idf.yaml create mode 100644 tests/components/mpu6886/test.esp32-c3.yaml create mode 100644 tests/components/mpu6886/test.esp32-idf.yaml create mode 100644 tests/components/mpu6886/test.esp32.yaml create mode 100644 tests/components/mpu6886/test.esp8266.yaml create mode 100644 tests/components/mpu6886/test.rp2040.yaml create mode 100644 tests/components/mqtt/test.esp32-c3-idf.yaml create mode 100644 tests/components/mqtt/test.esp32-c3.yaml create mode 100644 tests/components/mqtt/test.esp32-idf.yaml create mode 100644 tests/components/mqtt/test.esp32.yaml create mode 100644 tests/components/mqtt/test.esp8266.yaml create mode 100644 tests/components/mqtt_subscribe/test.esp32-c3-idf.yaml create mode 100644 tests/components/mqtt_subscribe/test.esp32-c3.yaml create mode 100644 tests/components/mqtt_subscribe/test.esp32-idf.yaml create mode 100644 tests/components/mqtt_subscribe/test.esp32.yaml create mode 100644 tests/components/mqtt_subscribe/test.esp8266.yaml create mode 100644 tests/components/ms5611/test.esp32-c3-idf.yaml create mode 100644 tests/components/ms5611/test.esp32-c3.yaml create mode 100644 tests/components/ms5611/test.esp32-idf.yaml create mode 100644 tests/components/ms5611/test.esp32.yaml create mode 100644 tests/components/ms5611/test.esp8266.yaml create mode 100644 tests/components/ms5611/test.rp2040.yaml create mode 100644 tests/components/my9231/test.esp32-c3-idf.yaml create mode 100644 tests/components/my9231/test.esp32-c3.yaml create mode 100644 tests/components/my9231/test.esp32-idf.yaml create mode 100644 tests/components/my9231/test.esp32.yaml create mode 100644 tests/components/my9231/test.esp8266.yaml create mode 100644 tests/components/my9231/test.rp2040.yaml diff --git a/tests/components/micronova/test.esp32-c3-idf.yaml b/tests/components/micronova/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..ec9699909e --- /dev/null +++ b/tests/components/micronova/test.esp32-c3-idf.yaml @@ -0,0 +1,49 @@ +uart: + - id: uart_micronova + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +micronova: + enable_rx_pin: 6 + +button: + - platform: micronova + custom_button: + name: Custom Micronova Button + memory_location: 0xA0 + memory_address: 0x7D + memory_data: 0x0F + +number: + - platform: micronova + thermostat_temperature: + name: Micronova Thermostaat + step: 1 + power_level: + name: Micronova Power level + +sensor: + - platform: micronova + room_temperature: + name: Room Temperature + fumes_temperature: + name: Fumes Temperature + water_temperature: + name: Water temperature + water_pressure: + name: Water pressure + stove_power: + name: Stove Power + fan_speed: + fan_rpm_offset: 240 + name: Fan RPM + memory_address_sensor: + memory_location: 0x20 + memory_address: 0x7d + name: Adres sensor + +switch: + - platform: micronova + stove: + name: Stove on/off diff --git a/tests/components/micronova/test.esp32-c3.yaml b/tests/components/micronova/test.esp32-c3.yaml new file mode 100644 index 0000000000..ec9699909e --- /dev/null +++ b/tests/components/micronova/test.esp32-c3.yaml @@ -0,0 +1,49 @@ +uart: + - id: uart_micronova + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +micronova: + enable_rx_pin: 6 + +button: + - platform: micronova + custom_button: + name: Custom Micronova Button + memory_location: 0xA0 + memory_address: 0x7D + memory_data: 0x0F + +number: + - platform: micronova + thermostat_temperature: + name: Micronova Thermostaat + step: 1 + power_level: + name: Micronova Power level + +sensor: + - platform: micronova + room_temperature: + name: Room Temperature + fumes_temperature: + name: Fumes Temperature + water_temperature: + name: Water temperature + water_pressure: + name: Water pressure + stove_power: + name: Stove Power + fan_speed: + fan_rpm_offset: 240 + name: Fan RPM + memory_address_sensor: + memory_location: 0x20 + memory_address: 0x7d + name: Adres sensor + +switch: + - platform: micronova + stove: + name: Stove on/off diff --git a/tests/components/micronova/test.esp32-idf.yaml b/tests/components/micronova/test.esp32-idf.yaml new file mode 100644 index 0000000000..9156f7d6a9 --- /dev/null +++ b/tests/components/micronova/test.esp32-idf.yaml @@ -0,0 +1,49 @@ +uart: + - id: uart_micronova + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +micronova: + enable_rx_pin: 18 + +button: + - platform: micronova + custom_button: + name: Custom Micronova Button + memory_location: 0xA0 + memory_address: 0x7D + memory_data: 0x0F + +number: + - platform: micronova + thermostat_temperature: + name: Micronova Thermostaat + step: 1 + power_level: + name: Micronova Power level + +sensor: + - platform: micronova + room_temperature: + name: Room Temperature + fumes_temperature: + name: Fumes Temperature + water_temperature: + name: Water temperature + water_pressure: + name: Water pressure + stove_power: + name: Stove Power + fan_speed: + fan_rpm_offset: 240 + name: Fan RPM + memory_address_sensor: + memory_location: 0x20 + memory_address: 0x7d + name: Adres sensor + +switch: + - platform: micronova + stove: + name: Stove on/off diff --git a/tests/components/micronova/test.esp32.yaml b/tests/components/micronova/test.esp32.yaml new file mode 100644 index 0000000000..9156f7d6a9 --- /dev/null +++ b/tests/components/micronova/test.esp32.yaml @@ -0,0 +1,49 @@ +uart: + - id: uart_micronova + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +micronova: + enable_rx_pin: 18 + +button: + - platform: micronova + custom_button: + name: Custom Micronova Button + memory_location: 0xA0 + memory_address: 0x7D + memory_data: 0x0F + +number: + - platform: micronova + thermostat_temperature: + name: Micronova Thermostaat + step: 1 + power_level: + name: Micronova Power level + +sensor: + - platform: micronova + room_temperature: + name: Room Temperature + fumes_temperature: + name: Fumes Temperature + water_temperature: + name: Water temperature + water_pressure: + name: Water pressure + stove_power: + name: Stove Power + fan_speed: + fan_rpm_offset: 240 + name: Fan RPM + memory_address_sensor: + memory_location: 0x20 + memory_address: 0x7d + name: Adres sensor + +switch: + - platform: micronova + stove: + name: Stove on/off diff --git a/tests/components/micronova/test.esp8266.yaml b/tests/components/micronova/test.esp8266.yaml new file mode 100644 index 0000000000..d10ab7ad7a --- /dev/null +++ b/tests/components/micronova/test.esp8266.yaml @@ -0,0 +1,49 @@ +uart: + - id: uart_micronova + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +micronova: + enable_rx_pin: 16 + +button: + - platform: micronova + custom_button: + name: Custom Micronova Button + memory_location: 0xA0 + memory_address: 0x7D + memory_data: 0x0F + +number: + - platform: micronova + thermostat_temperature: + name: Micronova Thermostaat + step: 1 + power_level: + name: Micronova Power level + +sensor: + - platform: micronova + room_temperature: + name: Room Temperature + fumes_temperature: + name: Fumes Temperature + water_temperature: + name: Water temperature + water_pressure: + name: Water pressure + stove_power: + name: Stove Power + fan_speed: + fan_rpm_offset: 240 + name: Fan RPM + memory_address_sensor: + memory_location: 0x20 + memory_address: 0x7d + name: Adres sensor + +switch: + - platform: micronova + stove: + name: Stove on/off diff --git a/tests/components/micronova/test.rp2040.yaml b/tests/components/micronova/test.rp2040.yaml new file mode 100644 index 0000000000..ec9699909e --- /dev/null +++ b/tests/components/micronova/test.rp2040.yaml @@ -0,0 +1,49 @@ +uart: + - id: uart_micronova + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +micronova: + enable_rx_pin: 6 + +button: + - platform: micronova + custom_button: + name: Custom Micronova Button + memory_location: 0xA0 + memory_address: 0x7D + memory_data: 0x0F + +number: + - platform: micronova + thermostat_temperature: + name: Micronova Thermostaat + step: 1 + power_level: + name: Micronova Power level + +sensor: + - platform: micronova + room_temperature: + name: Room Temperature + fumes_temperature: + name: Fumes Temperature + water_temperature: + name: Water temperature + water_pressure: + name: Water pressure + stove_power: + name: Stove Power + fan_speed: + fan_rpm_offset: 240 + name: Fan RPM + memory_address_sensor: + memory_location: 0x20 + memory_address: 0x7d + name: Adres sensor + +switch: + - platform: micronova + stove: + name: Stove on/off diff --git a/tests/components/microphone/test.esp32-c3-idf.yaml b/tests/components/microphone/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..706a38f910 --- /dev/null +++ b/tests/components/microphone/test.esp32-c3-idf.yaml @@ -0,0 +1,11 @@ +i2s_audio: + i2s_lrclk_pin: 6 + i2s_bclk_pin: 7 + i2s_mclk_pin: 8 + +microphone: + - platform: i2s_audio + id: mic_id_external + i2s_din_pin: 3 + adc_type: external + pdm: false diff --git a/tests/components/microphone/test.esp32-c3.yaml b/tests/components/microphone/test.esp32-c3.yaml new file mode 100644 index 0000000000..706a38f910 --- /dev/null +++ b/tests/components/microphone/test.esp32-c3.yaml @@ -0,0 +1,11 @@ +i2s_audio: + i2s_lrclk_pin: 6 + i2s_bclk_pin: 7 + i2s_mclk_pin: 8 + +microphone: + - platform: i2s_audio + id: mic_id_external + i2s_din_pin: 3 + adc_type: external + pdm: false diff --git a/tests/components/microphone/test.esp32-idf.yaml b/tests/components/microphone/test.esp32-idf.yaml new file mode 100644 index 0000000000..166eedb54d --- /dev/null +++ b/tests/components/microphone/test.esp32-idf.yaml @@ -0,0 +1,15 @@ +i2s_audio: + i2s_lrclk_pin: 13 + i2s_bclk_pin: 14 + i2s_mclk_pin: 15 + +microphone: + - platform: i2s_audio + id: mic_id_adc + adc_pin: 32 + adc_type: internal + - platform: i2s_audio + id: mic_id_external + i2s_din_pin: 33 + adc_type: external + pdm: false diff --git a/tests/components/microphone/test.esp32.yaml b/tests/components/microphone/test.esp32.yaml new file mode 100644 index 0000000000..166eedb54d --- /dev/null +++ b/tests/components/microphone/test.esp32.yaml @@ -0,0 +1,15 @@ +i2s_audio: + i2s_lrclk_pin: 13 + i2s_bclk_pin: 14 + i2s_mclk_pin: 15 + +microphone: + - platform: i2s_audio + id: mic_id_adc + adc_pin: 32 + adc_type: internal + - platform: i2s_audio + id: mic_id_external + i2s_din_pin: 33 + adc_type: external + pdm: false diff --git a/tests/components/mics_4514/test.esp32-c3-idf.yaml b/tests/components/mics_4514/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..72369bec01 --- /dev/null +++ b/tests/components/mics_4514/test.esp32-c3-idf.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_mics_4514 + scl: 5 + sda: 4 + +sensor: + - platform: mics_4514 + update_interval: 60s + nitrogen_dioxide: + name: MICS-4514 NO2 + carbon_monoxide: + name: MICS-4514 CO + methane: + name: MICS-4514 CH4 + hydrogen: + name: MICS-4514 H2 + ethanol: + name: MICS-4514 C2H5OH + ammonia: + name: MICS-4514 NH3 diff --git a/tests/components/mics_4514/test.esp32-c3.yaml b/tests/components/mics_4514/test.esp32-c3.yaml new file mode 100644 index 0000000000..72369bec01 --- /dev/null +++ b/tests/components/mics_4514/test.esp32-c3.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_mics_4514 + scl: 5 + sda: 4 + +sensor: + - platform: mics_4514 + update_interval: 60s + nitrogen_dioxide: + name: MICS-4514 NO2 + carbon_monoxide: + name: MICS-4514 CO + methane: + name: MICS-4514 CH4 + hydrogen: + name: MICS-4514 H2 + ethanol: + name: MICS-4514 C2H5OH + ammonia: + name: MICS-4514 NH3 diff --git a/tests/components/mics_4514/test.esp32-idf.yaml b/tests/components/mics_4514/test.esp32-idf.yaml new file mode 100644 index 0000000000..234839c91c --- /dev/null +++ b/tests/components/mics_4514/test.esp32-idf.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_mics_4514 + scl: 16 + sda: 17 + +sensor: + - platform: mics_4514 + update_interval: 60s + nitrogen_dioxide: + name: MICS-4514 NO2 + carbon_monoxide: + name: MICS-4514 CO + methane: + name: MICS-4514 CH4 + hydrogen: + name: MICS-4514 H2 + ethanol: + name: MICS-4514 C2H5OH + ammonia: + name: MICS-4514 NH3 diff --git a/tests/components/mics_4514/test.esp32.yaml b/tests/components/mics_4514/test.esp32.yaml new file mode 100644 index 0000000000..234839c91c --- /dev/null +++ b/tests/components/mics_4514/test.esp32.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_mics_4514 + scl: 16 + sda: 17 + +sensor: + - platform: mics_4514 + update_interval: 60s + nitrogen_dioxide: + name: MICS-4514 NO2 + carbon_monoxide: + name: MICS-4514 CO + methane: + name: MICS-4514 CH4 + hydrogen: + name: MICS-4514 H2 + ethanol: + name: MICS-4514 C2H5OH + ammonia: + name: MICS-4514 NH3 diff --git a/tests/components/mics_4514/test.esp8266.yaml b/tests/components/mics_4514/test.esp8266.yaml new file mode 100644 index 0000000000..72369bec01 --- /dev/null +++ b/tests/components/mics_4514/test.esp8266.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_mics_4514 + scl: 5 + sda: 4 + +sensor: + - platform: mics_4514 + update_interval: 60s + nitrogen_dioxide: + name: MICS-4514 NO2 + carbon_monoxide: + name: MICS-4514 CO + methane: + name: MICS-4514 CH4 + hydrogen: + name: MICS-4514 H2 + ethanol: + name: MICS-4514 C2H5OH + ammonia: + name: MICS-4514 NH3 diff --git a/tests/components/mics_4514/test.rp2040.yaml b/tests/components/mics_4514/test.rp2040.yaml new file mode 100644 index 0000000000..72369bec01 --- /dev/null +++ b/tests/components/mics_4514/test.rp2040.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_mics_4514 + scl: 5 + sda: 4 + +sensor: + - platform: mics_4514 + update_interval: 60s + nitrogen_dioxide: + name: MICS-4514 NO2 + carbon_monoxide: + name: MICS-4514 CO + methane: + name: MICS-4514 CH4 + hydrogen: + name: MICS-4514 H2 + ethanol: + name: MICS-4514 C2H5OH + ammonia: + name: MICS-4514 NH3 diff --git a/tests/components/midea/test.esp32-c3.yaml b/tests/components/midea/test.esp32-c3.yaml new file mode 100644 index 0000000000..bcb8635eaf --- /dev/null +++ b/tests/components/midea/test.esp32-c3.yaml @@ -0,0 +1,59 @@ +wifi: + ssid: MySSID + password: password1 + +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +uart: + - id: uart_midea + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +climate: + - platform: midea + id: midea_unit + name: Midea Climate + on_control: + - logger.log: Control message received! + - lambda: |- + x.set_mode(CLIMATE_MODE_FAN_ONLY); + on_state: + - logger.log: State changed! + transmitter_id: + period: 1s + num_attempts: 5 + timeout: 2s + beeper: false + autoconf: true + visual: + min_temperature: 17 °C + max_temperature: 30 °C + temperature_step: 0.5 °C + supported_modes: + - FAN_ONLY + - HEAT_COOL + - COOL + - HEAT + - DRY + custom_fan_modes: + - SILENT + - TURBO + supported_presets: + - ECO + - BOOST + - SLEEP + custom_presets: + - FREEZE_PROTECTION + supported_swing_modes: + - VERTICAL + - HORIZONTAL + - BOTH + outdoor_temperature: + name: Temp + power_usage: + name: Power + humidity_setpoint: + name: Humidity diff --git a/tests/components/midea/test.esp32.yaml b/tests/components/midea/test.esp32.yaml new file mode 100644 index 0000000000..5c638b9613 --- /dev/null +++ b/tests/components/midea/test.esp32.yaml @@ -0,0 +1,59 @@ +wifi: + ssid: MySSID + password: password1 + +remote_transmitter: + pin: 18 + carrier_duty_percent: 50% + +uart: + - id: uart_midea + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +climate: + - platform: midea + id: midea_unit + name: Midea Climate + on_control: + - logger.log: Control message received! + - lambda: |- + x.set_mode(CLIMATE_MODE_FAN_ONLY); + on_state: + - logger.log: State changed! + transmitter_id: + period: 1s + num_attempts: 5 + timeout: 2s + beeper: false + autoconf: true + visual: + min_temperature: 17 °C + max_temperature: 30 °C + temperature_step: 0.5 °C + supported_modes: + - FAN_ONLY + - HEAT_COOL + - COOL + - HEAT + - DRY + custom_fan_modes: + - SILENT + - TURBO + supported_presets: + - ECO + - BOOST + - SLEEP + custom_presets: + - FREEZE_PROTECTION + supported_swing_modes: + - VERTICAL + - HORIZONTAL + - BOTH + outdoor_temperature: + name: Temp + power_usage: + name: Power + humidity_setpoint: + name: Humidity diff --git a/tests/components/midea/test.esp8266.yaml b/tests/components/midea/test.esp8266.yaml new file mode 100644 index 0000000000..b0ed7eb472 --- /dev/null +++ b/tests/components/midea/test.esp8266.yaml @@ -0,0 +1,59 @@ +wifi: + ssid: MySSID + password: password1 + +remote_transmitter: + pin: 12 + carrier_duty_percent: 50% + +uart: + - id: uart_midea + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +climate: + - platform: midea + id: midea_unit + name: Midea Climate + on_control: + - logger.log: Control message received! + - lambda: |- + x.set_mode(CLIMATE_MODE_FAN_ONLY); + on_state: + - logger.log: State changed! + transmitter_id: + period: 1s + num_attempts: 5 + timeout: 2s + beeper: false + autoconf: true + visual: + min_temperature: 17 °C + max_temperature: 30 °C + temperature_step: 0.5 °C + supported_modes: + - FAN_ONLY + - HEAT_COOL + - COOL + - HEAT + - DRY + custom_fan_modes: + - SILENT + - TURBO + supported_presets: + - ECO + - BOOST + - SLEEP + custom_presets: + - FREEZE_PROTECTION + supported_swing_modes: + - VERTICAL + - HORIZONTAL + - BOTH + outdoor_temperature: + name: Temp + power_usage: + name: Power + humidity_setpoint: + name: Humidity diff --git a/tests/components/midea_ir/test.esp32-c3-idf.yaml b/tests/components/midea_ir/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..e8d89cecc2 --- /dev/null +++ b/tests/components/midea_ir/test.esp32-c3-idf.yaml @@ -0,0 +1,8 @@ +remote_transmitter: + pin: 4 + carrier_duty_percent: 50% + +climate: + - platform: midea_ir + name: Midea IR + use_fahrenheit: true diff --git a/tests/components/midea_ir/test.esp32-c3.yaml b/tests/components/midea_ir/test.esp32-c3.yaml new file mode 100644 index 0000000000..e8d89cecc2 --- /dev/null +++ b/tests/components/midea_ir/test.esp32-c3.yaml @@ -0,0 +1,8 @@ +remote_transmitter: + pin: 4 + carrier_duty_percent: 50% + +climate: + - platform: midea_ir + name: Midea IR + use_fahrenheit: true diff --git a/tests/components/midea_ir/test.esp32-idf.yaml b/tests/components/midea_ir/test.esp32-idf.yaml new file mode 100644 index 0000000000..e8d89cecc2 --- /dev/null +++ b/tests/components/midea_ir/test.esp32-idf.yaml @@ -0,0 +1,8 @@ +remote_transmitter: + pin: 4 + carrier_duty_percent: 50% + +climate: + - platform: midea_ir + name: Midea IR + use_fahrenheit: true diff --git a/tests/components/midea_ir/test.esp32.yaml b/tests/components/midea_ir/test.esp32.yaml new file mode 100644 index 0000000000..e8d89cecc2 --- /dev/null +++ b/tests/components/midea_ir/test.esp32.yaml @@ -0,0 +1,8 @@ +remote_transmitter: + pin: 4 + carrier_duty_percent: 50% + +climate: + - platform: midea_ir + name: Midea IR + use_fahrenheit: true diff --git a/tests/components/midea_ir/test.esp8266.yaml b/tests/components/midea_ir/test.esp8266.yaml new file mode 100644 index 0000000000..e8d89cecc2 --- /dev/null +++ b/tests/components/midea_ir/test.esp8266.yaml @@ -0,0 +1,8 @@ +remote_transmitter: + pin: 4 + carrier_duty_percent: 50% + +climate: + - platform: midea_ir + name: Midea IR + use_fahrenheit: true diff --git a/tests/components/mitsubishi/test.esp32-c3-idf.yaml b/tests/components/mitsubishi/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..c0fc959c5b --- /dev/null +++ b/tests/components/mitsubishi/test.esp32-c3-idf.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 4 + carrier_duty_percent: 50% + +climate: + - platform: mitsubishi + name: Mitsubishi diff --git a/tests/components/mitsubishi/test.esp32-c3.yaml b/tests/components/mitsubishi/test.esp32-c3.yaml new file mode 100644 index 0000000000..c0fc959c5b --- /dev/null +++ b/tests/components/mitsubishi/test.esp32-c3.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 4 + carrier_duty_percent: 50% + +climate: + - platform: mitsubishi + name: Mitsubishi diff --git a/tests/components/mitsubishi/test.esp32-idf.yaml b/tests/components/mitsubishi/test.esp32-idf.yaml new file mode 100644 index 0000000000..c0fc959c5b --- /dev/null +++ b/tests/components/mitsubishi/test.esp32-idf.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 4 + carrier_duty_percent: 50% + +climate: + - platform: mitsubishi + name: Mitsubishi diff --git a/tests/components/mitsubishi/test.esp32.yaml b/tests/components/mitsubishi/test.esp32.yaml new file mode 100644 index 0000000000..c0fc959c5b --- /dev/null +++ b/tests/components/mitsubishi/test.esp32.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 4 + carrier_duty_percent: 50% + +climate: + - platform: mitsubishi + name: Mitsubishi diff --git a/tests/components/mitsubishi/test.esp8266.yaml b/tests/components/mitsubishi/test.esp8266.yaml new file mode 100644 index 0000000000..c0fc959c5b --- /dev/null +++ b/tests/components/mitsubishi/test.esp8266.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 4 + carrier_duty_percent: 50% + +climate: + - platform: mitsubishi + name: Mitsubishi diff --git a/tests/components/mlx90393/test.esp32-c3-idf.yaml b/tests/components/mlx90393/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..549eea8032 --- /dev/null +++ b/tests/components/mlx90393/test.esp32-c3-idf.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_mlx90393 + scl: 5 + sda: 4 + +sensor: + - platform: mlx90393 + oversampling: 1 + filter: 0 + gain: 3X + x_axis: + name: mlxxaxis + y_axis: + name: mlxyaxis + z_axis: + name: mlxzaxis + resolution: 17BIT + temperature: + name: mlxtemp + oversampling: 2 diff --git a/tests/components/mlx90393/test.esp32-c3.yaml b/tests/components/mlx90393/test.esp32-c3.yaml new file mode 100644 index 0000000000..549eea8032 --- /dev/null +++ b/tests/components/mlx90393/test.esp32-c3.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_mlx90393 + scl: 5 + sda: 4 + +sensor: + - platform: mlx90393 + oversampling: 1 + filter: 0 + gain: 3X + x_axis: + name: mlxxaxis + y_axis: + name: mlxyaxis + z_axis: + name: mlxzaxis + resolution: 17BIT + temperature: + name: mlxtemp + oversampling: 2 diff --git a/tests/components/mlx90393/test.esp32-idf.yaml b/tests/components/mlx90393/test.esp32-idf.yaml new file mode 100644 index 0000000000..089fd136f4 --- /dev/null +++ b/tests/components/mlx90393/test.esp32-idf.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_mlx90393 + scl: 16 + sda: 17 + +sensor: + - platform: mlx90393 + oversampling: 1 + filter: 0 + gain: 3X + x_axis: + name: mlxxaxis + y_axis: + name: mlxyaxis + z_axis: + name: mlxzaxis + resolution: 17BIT + temperature: + name: mlxtemp + oversampling: 2 diff --git a/tests/components/mlx90393/test.esp32.yaml b/tests/components/mlx90393/test.esp32.yaml new file mode 100644 index 0000000000..089fd136f4 --- /dev/null +++ b/tests/components/mlx90393/test.esp32.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_mlx90393 + scl: 16 + sda: 17 + +sensor: + - platform: mlx90393 + oversampling: 1 + filter: 0 + gain: 3X + x_axis: + name: mlxxaxis + y_axis: + name: mlxyaxis + z_axis: + name: mlxzaxis + resolution: 17BIT + temperature: + name: mlxtemp + oversampling: 2 diff --git a/tests/components/mlx90393/test.esp8266.yaml b/tests/components/mlx90393/test.esp8266.yaml new file mode 100644 index 0000000000..549eea8032 --- /dev/null +++ b/tests/components/mlx90393/test.esp8266.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_mlx90393 + scl: 5 + sda: 4 + +sensor: + - platform: mlx90393 + oversampling: 1 + filter: 0 + gain: 3X + x_axis: + name: mlxxaxis + y_axis: + name: mlxyaxis + z_axis: + name: mlxzaxis + resolution: 17BIT + temperature: + name: mlxtemp + oversampling: 2 diff --git a/tests/components/mlx90393/test.rp2040.yaml b/tests/components/mlx90393/test.rp2040.yaml new file mode 100644 index 0000000000..549eea8032 --- /dev/null +++ b/tests/components/mlx90393/test.rp2040.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_mlx90393 + scl: 5 + sda: 4 + +sensor: + - platform: mlx90393 + oversampling: 1 + filter: 0 + gain: 3X + x_axis: + name: mlxxaxis + y_axis: + name: mlxyaxis + z_axis: + name: mlxzaxis + resolution: 17BIT + temperature: + name: mlxtemp + oversampling: 2 diff --git a/tests/components/mlx90614/test.esp32-c3-idf.yaml b/tests/components/mlx90614/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..a863e0ee2e --- /dev/null +++ b/tests/components/mlx90614/test.esp32-c3-idf.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_mlx90614 + scl: 5 + sda: 4 + +sensor: + - platform: mlx90614 + ambient: + name: Ambient + object: + name: Object + emissivity: 1.0 diff --git a/tests/components/mlx90614/test.esp32-c3.yaml b/tests/components/mlx90614/test.esp32-c3.yaml new file mode 100644 index 0000000000..a863e0ee2e --- /dev/null +++ b/tests/components/mlx90614/test.esp32-c3.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_mlx90614 + scl: 5 + sda: 4 + +sensor: + - platform: mlx90614 + ambient: + name: Ambient + object: + name: Object + emissivity: 1.0 diff --git a/tests/components/mlx90614/test.esp32-idf.yaml b/tests/components/mlx90614/test.esp32-idf.yaml new file mode 100644 index 0000000000..8c1ee68f42 --- /dev/null +++ b/tests/components/mlx90614/test.esp32-idf.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_mlx90614 + scl: 16 + sda: 17 + +sensor: + - platform: mlx90614 + ambient: + name: Ambient + object: + name: Object + emissivity: 1.0 diff --git a/tests/components/mlx90614/test.esp32.yaml b/tests/components/mlx90614/test.esp32.yaml new file mode 100644 index 0000000000..8c1ee68f42 --- /dev/null +++ b/tests/components/mlx90614/test.esp32.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_mlx90614 + scl: 16 + sda: 17 + +sensor: + - platform: mlx90614 + ambient: + name: Ambient + object: + name: Object + emissivity: 1.0 diff --git a/tests/components/mlx90614/test.esp8266.yaml b/tests/components/mlx90614/test.esp8266.yaml new file mode 100644 index 0000000000..a863e0ee2e --- /dev/null +++ b/tests/components/mlx90614/test.esp8266.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_mlx90614 + scl: 5 + sda: 4 + +sensor: + - platform: mlx90614 + ambient: + name: Ambient + object: + name: Object + emissivity: 1.0 diff --git a/tests/components/mlx90614/test.rp2040.yaml b/tests/components/mlx90614/test.rp2040.yaml new file mode 100644 index 0000000000..a863e0ee2e --- /dev/null +++ b/tests/components/mlx90614/test.rp2040.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_mlx90614 + scl: 5 + sda: 4 + +sensor: + - platform: mlx90614 + ambient: + name: Ambient + object: + name: Object + emissivity: 1.0 diff --git a/tests/components/mmc5603/test.esp32-c3-idf.yaml b/tests/components/mmc5603/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..834591bb39 --- /dev/null +++ b/tests/components/mmc5603/test.esp32-c3-idf.yaml @@ -0,0 +1,14 @@ +i2c: + - id: i2c_mmc5603 + scl: 5 + sda: 4 + +sensor: + - platform: mmc5603 + address: 0x30 + field_strength_x: + name: HMC5883L Field Strength X + field_strength_y: + name: HMC5883L Field Strength Y + field_strength_z: + name: HMC5883L Field Strength Z diff --git a/tests/components/mmc5603/test.esp32-c3.yaml b/tests/components/mmc5603/test.esp32-c3.yaml new file mode 100644 index 0000000000..834591bb39 --- /dev/null +++ b/tests/components/mmc5603/test.esp32-c3.yaml @@ -0,0 +1,14 @@ +i2c: + - id: i2c_mmc5603 + scl: 5 + sda: 4 + +sensor: + - platform: mmc5603 + address: 0x30 + field_strength_x: + name: HMC5883L Field Strength X + field_strength_y: + name: HMC5883L Field Strength Y + field_strength_z: + name: HMC5883L Field Strength Z diff --git a/tests/components/mmc5603/test.esp32-idf.yaml b/tests/components/mmc5603/test.esp32-idf.yaml new file mode 100644 index 0000000000..fbb83cd9f8 --- /dev/null +++ b/tests/components/mmc5603/test.esp32-idf.yaml @@ -0,0 +1,14 @@ +i2c: + - id: i2c_mmc5603 + scl: 16 + sda: 17 + +sensor: + - platform: mmc5603 + address: 0x30 + field_strength_x: + name: HMC5883L Field Strength X + field_strength_y: + name: HMC5883L Field Strength Y + field_strength_z: + name: HMC5883L Field Strength Z diff --git a/tests/components/mmc5603/test.esp32.yaml b/tests/components/mmc5603/test.esp32.yaml new file mode 100644 index 0000000000..fbb83cd9f8 --- /dev/null +++ b/tests/components/mmc5603/test.esp32.yaml @@ -0,0 +1,14 @@ +i2c: + - id: i2c_mmc5603 + scl: 16 + sda: 17 + +sensor: + - platform: mmc5603 + address: 0x30 + field_strength_x: + name: HMC5883L Field Strength X + field_strength_y: + name: HMC5883L Field Strength Y + field_strength_z: + name: HMC5883L Field Strength Z diff --git a/tests/components/mmc5603/test.esp8266.yaml b/tests/components/mmc5603/test.esp8266.yaml new file mode 100644 index 0000000000..834591bb39 --- /dev/null +++ b/tests/components/mmc5603/test.esp8266.yaml @@ -0,0 +1,14 @@ +i2c: + - id: i2c_mmc5603 + scl: 5 + sda: 4 + +sensor: + - platform: mmc5603 + address: 0x30 + field_strength_x: + name: HMC5883L Field Strength X + field_strength_y: + name: HMC5883L Field Strength Y + field_strength_z: + name: HMC5883L Field Strength Z diff --git a/tests/components/mmc5603/test.rp2040.yaml b/tests/components/mmc5603/test.rp2040.yaml new file mode 100644 index 0000000000..834591bb39 --- /dev/null +++ b/tests/components/mmc5603/test.rp2040.yaml @@ -0,0 +1,14 @@ +i2c: + - id: i2c_mmc5603 + scl: 5 + sda: 4 + +sensor: + - platform: mmc5603 + address: 0x30 + field_strength_x: + name: HMC5883L Field Strength X + field_strength_y: + name: HMC5883L Field Strength Y + field_strength_z: + name: HMC5883L Field Strength Z diff --git a/tests/components/mmc5983/test.esp32-c3-idf.yaml b/tests/components/mmc5983/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..68d821e9a5 --- /dev/null +++ b/tests/components/mmc5983/test.esp32-c3-idf.yaml @@ -0,0 +1,16 @@ +i2c: + - id: i2c_mmc5983 + scl: 5 + sda: 4 + +sensor: + - platform: mmc5983 + field_strength_x: + name: "Magnet X" + id: magnet_x + field_strength_y: + name: "Magnet Y" + id: magnet_y + field_strength_z: + name: "Magnet Z" + id: magnet_z diff --git a/tests/components/mmc5983/test.esp32-c3.yaml b/tests/components/mmc5983/test.esp32-c3.yaml new file mode 100644 index 0000000000..68d821e9a5 --- /dev/null +++ b/tests/components/mmc5983/test.esp32-c3.yaml @@ -0,0 +1,16 @@ +i2c: + - id: i2c_mmc5983 + scl: 5 + sda: 4 + +sensor: + - platform: mmc5983 + field_strength_x: + name: "Magnet X" + id: magnet_x + field_strength_y: + name: "Magnet Y" + id: magnet_y + field_strength_z: + name: "Magnet Z" + id: magnet_z diff --git a/tests/components/mmc5983/test.esp32-idf.yaml b/tests/components/mmc5983/test.esp32-idf.yaml new file mode 100644 index 0000000000..6104be9b83 --- /dev/null +++ b/tests/components/mmc5983/test.esp32-idf.yaml @@ -0,0 +1,16 @@ +i2c: + - id: i2c_mmc5983 + scl: 16 + sda: 17 + +sensor: + - platform: mmc5983 + field_strength_x: + name: "Magnet X" + id: magnet_x + field_strength_y: + name: "Magnet Y" + id: magnet_y + field_strength_z: + name: "Magnet Z" + id: magnet_z diff --git a/tests/components/mmc5983/test.esp32.yaml b/tests/components/mmc5983/test.esp32.yaml new file mode 100644 index 0000000000..6104be9b83 --- /dev/null +++ b/tests/components/mmc5983/test.esp32.yaml @@ -0,0 +1,16 @@ +i2c: + - id: i2c_mmc5983 + scl: 16 + sda: 17 + +sensor: + - platform: mmc5983 + field_strength_x: + name: "Magnet X" + id: magnet_x + field_strength_y: + name: "Magnet Y" + id: magnet_y + field_strength_z: + name: "Magnet Z" + id: magnet_z diff --git a/tests/components/mmc5983/test.esp8266.yaml b/tests/components/mmc5983/test.esp8266.yaml new file mode 100644 index 0000000000..68d821e9a5 --- /dev/null +++ b/tests/components/mmc5983/test.esp8266.yaml @@ -0,0 +1,16 @@ +i2c: + - id: i2c_mmc5983 + scl: 5 + sda: 4 + +sensor: + - platform: mmc5983 + field_strength_x: + name: "Magnet X" + id: magnet_x + field_strength_y: + name: "Magnet Y" + id: magnet_y + field_strength_z: + name: "Magnet Z" + id: magnet_z diff --git a/tests/components/mmc5983/test.rp2040.yaml b/tests/components/mmc5983/test.rp2040.yaml new file mode 100644 index 0000000000..68d821e9a5 --- /dev/null +++ b/tests/components/mmc5983/test.rp2040.yaml @@ -0,0 +1,16 @@ +i2c: + - id: i2c_mmc5983 + scl: 5 + sda: 4 + +sensor: + - platform: mmc5983 + field_strength_x: + name: "Magnet X" + id: magnet_x + field_strength_y: + name: "Magnet Y" + id: magnet_y + field_strength_z: + name: "Magnet Z" + id: magnet_z diff --git a/tests/components/modbus/test.esp32-c3-idf.yaml b/tests/components/modbus/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..d22b507be0 --- /dev/null +++ b/tests/components/modbus/test.esp32-c3-idf.yaml @@ -0,0 +1,9 @@ +uart: + - id: uart_modbus + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +modbus: + id: mod_bus1 + flow_control_pin: 6 diff --git a/tests/components/modbus/test.esp32-c3.yaml b/tests/components/modbus/test.esp32-c3.yaml new file mode 100644 index 0000000000..d22b507be0 --- /dev/null +++ b/tests/components/modbus/test.esp32-c3.yaml @@ -0,0 +1,9 @@ +uart: + - id: uart_modbus + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +modbus: + id: mod_bus1 + flow_control_pin: 6 diff --git a/tests/components/modbus/test.esp32-idf.yaml b/tests/components/modbus/test.esp32-idf.yaml new file mode 100644 index 0000000000..20cf238b1b --- /dev/null +++ b/tests/components/modbus/test.esp32-idf.yaml @@ -0,0 +1,9 @@ +uart: + - id: uart_modbus + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +modbus: + id: mod_bus1 + flow_control_pin: 15 diff --git a/tests/components/modbus/test.esp32.yaml b/tests/components/modbus/test.esp32.yaml new file mode 100644 index 0000000000..20cf238b1b --- /dev/null +++ b/tests/components/modbus/test.esp32.yaml @@ -0,0 +1,9 @@ +uart: + - id: uart_modbus + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +modbus: + id: mod_bus1 + flow_control_pin: 15 diff --git a/tests/components/modbus/test.esp8266.yaml b/tests/components/modbus/test.esp8266.yaml new file mode 100644 index 0000000000..560c044766 --- /dev/null +++ b/tests/components/modbus/test.esp8266.yaml @@ -0,0 +1,9 @@ +uart: + - id: uart_modbus + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +modbus: + id: mod_bus1 + flow_control_pin: 12 diff --git a/tests/components/modbus/test.rp2040.yaml b/tests/components/modbus/test.rp2040.yaml new file mode 100644 index 0000000000..d22b507be0 --- /dev/null +++ b/tests/components/modbus/test.rp2040.yaml @@ -0,0 +1,9 @@ +uart: + - id: uart_modbus + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +modbus: + id: mod_bus1 + flow_control_pin: 6 diff --git a/tests/components/modbus_controller/test.esp32-c3-idf.yaml b/tests/components/modbus_controller/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..476e65ecb0 --- /dev/null +++ b/tests/components/modbus_controller/test.esp32-c3-idf.yaml @@ -0,0 +1,14 @@ +uart: + - id: uart_modbus + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +modbus: + id: mod_bus1 + flow_control_pin: 6 + +modbus_controller: + - id: modbus_controller1 + address: 0x2 + modbus_id: mod_bus1 diff --git a/tests/components/modbus_controller/test.esp32-c3.yaml b/tests/components/modbus_controller/test.esp32-c3.yaml new file mode 100644 index 0000000000..476e65ecb0 --- /dev/null +++ b/tests/components/modbus_controller/test.esp32-c3.yaml @@ -0,0 +1,14 @@ +uart: + - id: uart_modbus + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +modbus: + id: mod_bus1 + flow_control_pin: 6 + +modbus_controller: + - id: modbus_controller1 + address: 0x2 + modbus_id: mod_bus1 diff --git a/tests/components/modbus_controller/test.esp32-idf.yaml b/tests/components/modbus_controller/test.esp32-idf.yaml new file mode 100644 index 0000000000..c5fe3fd057 --- /dev/null +++ b/tests/components/modbus_controller/test.esp32-idf.yaml @@ -0,0 +1,14 @@ +uart: + - id: uart_modbus + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +modbus: + id: mod_bus1 + flow_control_pin: 15 + +modbus_controller: + - id: modbus_controller1 + address: 0x2 + modbus_id: mod_bus1 diff --git a/tests/components/modbus_controller/test.esp32.yaml b/tests/components/modbus_controller/test.esp32.yaml new file mode 100644 index 0000000000..c5fe3fd057 --- /dev/null +++ b/tests/components/modbus_controller/test.esp32.yaml @@ -0,0 +1,14 @@ +uart: + - id: uart_modbus + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +modbus: + id: mod_bus1 + flow_control_pin: 15 + +modbus_controller: + - id: modbus_controller1 + address: 0x2 + modbus_id: mod_bus1 diff --git a/tests/components/modbus_controller/test.esp8266.yaml b/tests/components/modbus_controller/test.esp8266.yaml new file mode 100644 index 0000000000..67cac65d1b --- /dev/null +++ b/tests/components/modbus_controller/test.esp8266.yaml @@ -0,0 +1,14 @@ +uart: + - id: uart_modbus + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +modbus: + id: mod_bus1 + flow_control_pin: 12 + +modbus_controller: + - id: modbus_controller1 + address: 0x2 + modbus_id: mod_bus1 diff --git a/tests/components/modbus_controller/test.rp2040.yaml b/tests/components/modbus_controller/test.rp2040.yaml new file mode 100644 index 0000000000..476e65ecb0 --- /dev/null +++ b/tests/components/modbus_controller/test.rp2040.yaml @@ -0,0 +1,14 @@ +uart: + - id: uart_modbus + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +modbus: + id: mod_bus1 + flow_control_pin: 6 + +modbus_controller: + - id: modbus_controller1 + address: 0x2 + modbus_id: mod_bus1 diff --git a/tests/components/monochromatic/test.esp32-c3-idf.yaml b/tests/components/monochromatic/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..9524efcb2d --- /dev/null +++ b/tests/components/monochromatic/test.esp32-c3-idf.yaml @@ -0,0 +1,40 @@ +output: + - platform: ledc + id: light_output_1 + pin: 4 + +light: + - platform: monochromatic + name: Monochromatic Light + id: monochromatic_light + output: light_output_1 + gamma_correct: 2.8 + default_transition_length: 2s + effects: + - strobe: + - flicker: + - flicker: + name: My Flicker + alpha: 98% + intensity: 1.5% + - lambda: + name: My Custom Effect + update_interval: 1s + lambda: |- + static int state = 0; + state += 1; + if (state == 4) + state = 0; + - pulse: + transition_length: 10s + update_interval: 20s + min_brightness: 10% + max_brightness: 90% + - pulse: + name: pulse2 + transition_length: + on_length: 10s + off_length: 5s + update_interval: 15s + min_brightness: 10% + max_brightness: 90% diff --git a/tests/components/monochromatic/test.esp32-c3.yaml b/tests/components/monochromatic/test.esp32-c3.yaml new file mode 100644 index 0000000000..9524efcb2d --- /dev/null +++ b/tests/components/monochromatic/test.esp32-c3.yaml @@ -0,0 +1,40 @@ +output: + - platform: ledc + id: light_output_1 + pin: 4 + +light: + - platform: monochromatic + name: Monochromatic Light + id: monochromatic_light + output: light_output_1 + gamma_correct: 2.8 + default_transition_length: 2s + effects: + - strobe: + - flicker: + - flicker: + name: My Flicker + alpha: 98% + intensity: 1.5% + - lambda: + name: My Custom Effect + update_interval: 1s + lambda: |- + static int state = 0; + state += 1; + if (state == 4) + state = 0; + - pulse: + transition_length: 10s + update_interval: 20s + min_brightness: 10% + max_brightness: 90% + - pulse: + name: pulse2 + transition_length: + on_length: 10s + off_length: 5s + update_interval: 15s + min_brightness: 10% + max_brightness: 90% diff --git a/tests/components/monochromatic/test.esp32-idf.yaml b/tests/components/monochromatic/test.esp32-idf.yaml new file mode 100644 index 0000000000..9524efcb2d --- /dev/null +++ b/tests/components/monochromatic/test.esp32-idf.yaml @@ -0,0 +1,40 @@ +output: + - platform: ledc + id: light_output_1 + pin: 4 + +light: + - platform: monochromatic + name: Monochromatic Light + id: monochromatic_light + output: light_output_1 + gamma_correct: 2.8 + default_transition_length: 2s + effects: + - strobe: + - flicker: + - flicker: + name: My Flicker + alpha: 98% + intensity: 1.5% + - lambda: + name: My Custom Effect + update_interval: 1s + lambda: |- + static int state = 0; + state += 1; + if (state == 4) + state = 0; + - pulse: + transition_length: 10s + update_interval: 20s + min_brightness: 10% + max_brightness: 90% + - pulse: + name: pulse2 + transition_length: + on_length: 10s + off_length: 5s + update_interval: 15s + min_brightness: 10% + max_brightness: 90% diff --git a/tests/components/monochromatic/test.esp32.yaml b/tests/components/monochromatic/test.esp32.yaml new file mode 100644 index 0000000000..9524efcb2d --- /dev/null +++ b/tests/components/monochromatic/test.esp32.yaml @@ -0,0 +1,40 @@ +output: + - platform: ledc + id: light_output_1 + pin: 4 + +light: + - platform: monochromatic + name: Monochromatic Light + id: monochromatic_light + output: light_output_1 + gamma_correct: 2.8 + default_transition_length: 2s + effects: + - strobe: + - flicker: + - flicker: + name: My Flicker + alpha: 98% + intensity: 1.5% + - lambda: + name: My Custom Effect + update_interval: 1s + lambda: |- + static int state = 0; + state += 1; + if (state == 4) + state = 0; + - pulse: + transition_length: 10s + update_interval: 20s + min_brightness: 10% + max_brightness: 90% + - pulse: + name: pulse2 + transition_length: + on_length: 10s + off_length: 5s + update_interval: 15s + min_brightness: 10% + max_brightness: 90% diff --git a/tests/components/monochromatic/test.esp8266.yaml b/tests/components/monochromatic/test.esp8266.yaml new file mode 100644 index 0000000000..94d849581d --- /dev/null +++ b/tests/components/monochromatic/test.esp8266.yaml @@ -0,0 +1,40 @@ +output: + - platform: esp8266_pwm + id: light_output_1 + pin: 4 + +light: + - platform: monochromatic + name: Monochromatic Light + id: monochromatic_light + output: light_output_1 + gamma_correct: 2.8 + default_transition_length: 2s + effects: + - strobe: + - flicker: + - flicker: + name: My Flicker + alpha: 98% + intensity: 1.5% + - lambda: + name: My Custom Effect + update_interval: 1s + lambda: |- + static int state = 0; + state += 1; + if (state == 4) + state = 0; + - pulse: + transition_length: 10s + update_interval: 20s + min_brightness: 10% + max_brightness: 90% + - pulse: + name: pulse2 + transition_length: + on_length: 10s + off_length: 5s + update_interval: 15s + min_brightness: 10% + max_brightness: 90% diff --git a/tests/components/monochromatic/test.rp2040.yaml b/tests/components/monochromatic/test.rp2040.yaml new file mode 100644 index 0000000000..093577e256 --- /dev/null +++ b/tests/components/monochromatic/test.rp2040.yaml @@ -0,0 +1,40 @@ +output: + - platform: rp2040_pwm + id: light_output_1 + pin: 4 + +light: + - platform: monochromatic + name: Monochromatic Light + id: monochromatic_light + output: light_output_1 + gamma_correct: 2.8 + default_transition_length: 2s + effects: + - strobe: + - flicker: + - flicker: + name: My Flicker + alpha: 98% + intensity: 1.5% + - lambda: + name: My Custom Effect + update_interval: 1s + lambda: |- + static int state = 0; + state += 1; + if (state == 4) + state = 0; + - pulse: + transition_length: 10s + update_interval: 20s + min_brightness: 10% + max_brightness: 90% + - pulse: + name: pulse2 + transition_length: + on_length: 10s + off_length: 5s + update_interval: 15s + min_brightness: 10% + max_brightness: 90% diff --git a/tests/components/mopeka_ble/test.esp32-c3-idf.yaml b/tests/components/mopeka_ble/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..a115404f1c --- /dev/null +++ b/tests/components/mopeka_ble/test.esp32-c3-idf.yaml @@ -0,0 +1,3 @@ +esp32_ble_tracker: + +mopeka_ble: diff --git a/tests/components/mopeka_ble/test.esp32-c3.yaml b/tests/components/mopeka_ble/test.esp32-c3.yaml new file mode 100644 index 0000000000..a115404f1c --- /dev/null +++ b/tests/components/mopeka_ble/test.esp32-c3.yaml @@ -0,0 +1,3 @@ +esp32_ble_tracker: + +mopeka_ble: diff --git a/tests/components/mopeka_ble/test.esp32-idf.yaml b/tests/components/mopeka_ble/test.esp32-idf.yaml new file mode 100644 index 0000000000..a115404f1c --- /dev/null +++ b/tests/components/mopeka_ble/test.esp32-idf.yaml @@ -0,0 +1,3 @@ +esp32_ble_tracker: + +mopeka_ble: diff --git a/tests/components/mopeka_ble/test.esp32.yaml b/tests/components/mopeka_ble/test.esp32.yaml new file mode 100644 index 0000000000..a115404f1c --- /dev/null +++ b/tests/components/mopeka_ble/test.esp32.yaml @@ -0,0 +1,3 @@ +esp32_ble_tracker: + +mopeka_ble: diff --git a/tests/components/mopeka_pro_check/test.esp32-c3-idf.yaml b/tests/components/mopeka_pro_check/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..147cbcb9de --- /dev/null +++ b/tests/components/mopeka_pro_check/test.esp32-c3-idf.yaml @@ -0,0 +1,16 @@ +esp32_ble_tracker: + +sensor: + - platform: mopeka_pro_check + mac_address: D3:75:F2:DC:16:91 + tank_type: CUSTOM + custom_distance_full: 40cm + custom_distance_empty: 10mm + temperature: + name: Propane test temp + level: + name: Propane test level + distance: + name: Propane test distance + battery_level: + name: Propane test battery level diff --git a/tests/components/mopeka_pro_check/test.esp32-c3.yaml b/tests/components/mopeka_pro_check/test.esp32-c3.yaml new file mode 100644 index 0000000000..147cbcb9de --- /dev/null +++ b/tests/components/mopeka_pro_check/test.esp32-c3.yaml @@ -0,0 +1,16 @@ +esp32_ble_tracker: + +sensor: + - platform: mopeka_pro_check + mac_address: D3:75:F2:DC:16:91 + tank_type: CUSTOM + custom_distance_full: 40cm + custom_distance_empty: 10mm + temperature: + name: Propane test temp + level: + name: Propane test level + distance: + name: Propane test distance + battery_level: + name: Propane test battery level diff --git a/tests/components/mopeka_pro_check/test.esp32-idf.yaml b/tests/components/mopeka_pro_check/test.esp32-idf.yaml new file mode 100644 index 0000000000..147cbcb9de --- /dev/null +++ b/tests/components/mopeka_pro_check/test.esp32-idf.yaml @@ -0,0 +1,16 @@ +esp32_ble_tracker: + +sensor: + - platform: mopeka_pro_check + mac_address: D3:75:F2:DC:16:91 + tank_type: CUSTOM + custom_distance_full: 40cm + custom_distance_empty: 10mm + temperature: + name: Propane test temp + level: + name: Propane test level + distance: + name: Propane test distance + battery_level: + name: Propane test battery level diff --git a/tests/components/mopeka_pro_check/test.esp32.yaml b/tests/components/mopeka_pro_check/test.esp32.yaml new file mode 100644 index 0000000000..147cbcb9de --- /dev/null +++ b/tests/components/mopeka_pro_check/test.esp32.yaml @@ -0,0 +1,16 @@ +esp32_ble_tracker: + +sensor: + - platform: mopeka_pro_check + mac_address: D3:75:F2:DC:16:91 + tank_type: CUSTOM + custom_distance_full: 40cm + custom_distance_empty: 10mm + temperature: + name: Propane test temp + level: + name: Propane test level + distance: + name: Propane test distance + battery_level: + name: Propane test battery level diff --git a/tests/components/mopeka_std_check/test.esp32-c3-idf.yaml b/tests/components/mopeka_std_check/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..830adf952f --- /dev/null +++ b/tests/components/mopeka_std_check/test.esp32-c3-idf.yaml @@ -0,0 +1,16 @@ +esp32_ble_tracker: + +sensor: + # Example using 11kg 100% propane tank. + - platform: mopeka_std_check + mac_address: D3:75:F2:DC:16:91 + tank_type: Europe_11kg + temperature: + name: "Propane test temp" + level: + name: "Propane test level" + distance: + name: "Propane test distance" + battery_level: + name: "Propane test battery level" + diff --git a/tests/components/mopeka_std_check/test.esp32-c3.yaml b/tests/components/mopeka_std_check/test.esp32-c3.yaml new file mode 100644 index 0000000000..830adf952f --- /dev/null +++ b/tests/components/mopeka_std_check/test.esp32-c3.yaml @@ -0,0 +1,16 @@ +esp32_ble_tracker: + +sensor: + # Example using 11kg 100% propane tank. + - platform: mopeka_std_check + mac_address: D3:75:F2:DC:16:91 + tank_type: Europe_11kg + temperature: + name: "Propane test temp" + level: + name: "Propane test level" + distance: + name: "Propane test distance" + battery_level: + name: "Propane test battery level" + diff --git a/tests/components/mopeka_std_check/test.esp32-idf.yaml b/tests/components/mopeka_std_check/test.esp32-idf.yaml new file mode 100644 index 0000000000..830adf952f --- /dev/null +++ b/tests/components/mopeka_std_check/test.esp32-idf.yaml @@ -0,0 +1,16 @@ +esp32_ble_tracker: + +sensor: + # Example using 11kg 100% propane tank. + - platform: mopeka_std_check + mac_address: D3:75:F2:DC:16:91 + tank_type: Europe_11kg + temperature: + name: "Propane test temp" + level: + name: "Propane test level" + distance: + name: "Propane test distance" + battery_level: + name: "Propane test battery level" + diff --git a/tests/components/mpl3115a2/test.esp32-c3-idf.yaml b/tests/components/mpl3115a2/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..9cbe08d920 --- /dev/null +++ b/tests/components/mpl3115a2/test.esp32-c3-idf.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_mpl3115a2 + scl: 5 + sda: 4 + +sensor: + - platform: mpl3115a2 + temperature: + name: MPL3115A2 Temperature + pressure: + name: MPL3115A2 Pressure + update_interval: 10s diff --git a/tests/components/mpl3115a2/test.esp32-c3.yaml b/tests/components/mpl3115a2/test.esp32-c3.yaml new file mode 100644 index 0000000000..9cbe08d920 --- /dev/null +++ b/tests/components/mpl3115a2/test.esp32-c3.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_mpl3115a2 + scl: 5 + sda: 4 + +sensor: + - platform: mpl3115a2 + temperature: + name: MPL3115A2 Temperature + pressure: + name: MPL3115A2 Pressure + update_interval: 10s diff --git a/tests/components/mpl3115a2/test.esp32-idf.yaml b/tests/components/mpl3115a2/test.esp32-idf.yaml new file mode 100644 index 0000000000..5e9d6d190d --- /dev/null +++ b/tests/components/mpl3115a2/test.esp32-idf.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_mpl3115a2 + scl: 16 + sda: 17 + +sensor: + - platform: mpl3115a2 + temperature: + name: MPL3115A2 Temperature + pressure: + name: MPL3115A2 Pressure + update_interval: 10s diff --git a/tests/components/mpl3115a2/test.esp32.yaml b/tests/components/mpl3115a2/test.esp32.yaml new file mode 100644 index 0000000000..5e9d6d190d --- /dev/null +++ b/tests/components/mpl3115a2/test.esp32.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_mpl3115a2 + scl: 16 + sda: 17 + +sensor: + - platform: mpl3115a2 + temperature: + name: MPL3115A2 Temperature + pressure: + name: MPL3115A2 Pressure + update_interval: 10s diff --git a/tests/components/mpl3115a2/test.esp8266.yaml b/tests/components/mpl3115a2/test.esp8266.yaml new file mode 100644 index 0000000000..9cbe08d920 --- /dev/null +++ b/tests/components/mpl3115a2/test.esp8266.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_mpl3115a2 + scl: 5 + sda: 4 + +sensor: + - platform: mpl3115a2 + temperature: + name: MPL3115A2 Temperature + pressure: + name: MPL3115A2 Pressure + update_interval: 10s diff --git a/tests/components/mpl3115a2/test.rp2040.yaml b/tests/components/mpl3115a2/test.rp2040.yaml new file mode 100644 index 0000000000..9cbe08d920 --- /dev/null +++ b/tests/components/mpl3115a2/test.rp2040.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_mpl3115a2 + scl: 5 + sda: 4 + +sensor: + - platform: mpl3115a2 + temperature: + name: MPL3115A2 Temperature + pressure: + name: MPL3115A2 Pressure + update_interval: 10s diff --git a/tests/components/mpr121/test.esp32-c3-idf.yaml b/tests/components/mpr121/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..517e092560 --- /dev/null +++ b/tests/components/mpr121/test.esp32-c3-idf.yaml @@ -0,0 +1,26 @@ +i2c: + - id: i2c_mpr121 + scl: 5 + sda: 4 + +mpr121: + id: mpr121_first + address: 0x5A + +binary_sensor: + - platform: mpr121 + id: touchkey0 + name: touchkey0 + channel: 0 + - platform: mpr121 + id: bin1 + name: touchkey1 + channel: 1 + - platform: mpr121 + id: bin2 + name: touchkey2 + channel: 2 + - platform: mpr121 + id: bin3 + name: touchkey3 + channel: 3 diff --git a/tests/components/mpr121/test.esp32-c3.yaml b/tests/components/mpr121/test.esp32-c3.yaml new file mode 100644 index 0000000000..517e092560 --- /dev/null +++ b/tests/components/mpr121/test.esp32-c3.yaml @@ -0,0 +1,26 @@ +i2c: + - id: i2c_mpr121 + scl: 5 + sda: 4 + +mpr121: + id: mpr121_first + address: 0x5A + +binary_sensor: + - platform: mpr121 + id: touchkey0 + name: touchkey0 + channel: 0 + - platform: mpr121 + id: bin1 + name: touchkey1 + channel: 1 + - platform: mpr121 + id: bin2 + name: touchkey2 + channel: 2 + - platform: mpr121 + id: bin3 + name: touchkey3 + channel: 3 diff --git a/tests/components/mpr121/test.esp32-idf.yaml b/tests/components/mpr121/test.esp32-idf.yaml new file mode 100644 index 0000000000..96996fd8ee --- /dev/null +++ b/tests/components/mpr121/test.esp32-idf.yaml @@ -0,0 +1,26 @@ +i2c: + - id: i2c_mpr121 + scl: 16 + sda: 17 + +mpr121: + id: mpr121_first + address: 0x5A + +binary_sensor: + - platform: mpr121 + id: touchkey0 + name: touchkey0 + channel: 0 + - platform: mpr121 + id: bin1 + name: touchkey1 + channel: 1 + - platform: mpr121 + id: bin2 + name: touchkey2 + channel: 2 + - platform: mpr121 + id: bin3 + name: touchkey3 + channel: 3 diff --git a/tests/components/mpr121/test.esp32.yaml b/tests/components/mpr121/test.esp32.yaml new file mode 100644 index 0000000000..96996fd8ee --- /dev/null +++ b/tests/components/mpr121/test.esp32.yaml @@ -0,0 +1,26 @@ +i2c: + - id: i2c_mpr121 + scl: 16 + sda: 17 + +mpr121: + id: mpr121_first + address: 0x5A + +binary_sensor: + - platform: mpr121 + id: touchkey0 + name: touchkey0 + channel: 0 + - platform: mpr121 + id: bin1 + name: touchkey1 + channel: 1 + - platform: mpr121 + id: bin2 + name: touchkey2 + channel: 2 + - platform: mpr121 + id: bin3 + name: touchkey3 + channel: 3 diff --git a/tests/components/mpr121/test.esp8266.yaml b/tests/components/mpr121/test.esp8266.yaml new file mode 100644 index 0000000000..517e092560 --- /dev/null +++ b/tests/components/mpr121/test.esp8266.yaml @@ -0,0 +1,26 @@ +i2c: + - id: i2c_mpr121 + scl: 5 + sda: 4 + +mpr121: + id: mpr121_first + address: 0x5A + +binary_sensor: + - platform: mpr121 + id: touchkey0 + name: touchkey0 + channel: 0 + - platform: mpr121 + id: bin1 + name: touchkey1 + channel: 1 + - platform: mpr121 + id: bin2 + name: touchkey2 + channel: 2 + - platform: mpr121 + id: bin3 + name: touchkey3 + channel: 3 diff --git a/tests/components/mpr121/test.rp2040.yaml b/tests/components/mpr121/test.rp2040.yaml new file mode 100644 index 0000000000..517e092560 --- /dev/null +++ b/tests/components/mpr121/test.rp2040.yaml @@ -0,0 +1,26 @@ +i2c: + - id: i2c_mpr121 + scl: 5 + sda: 4 + +mpr121: + id: mpr121_first + address: 0x5A + +binary_sensor: + - platform: mpr121 + id: touchkey0 + name: touchkey0 + channel: 0 + - platform: mpr121 + id: bin1 + name: touchkey1 + channel: 1 + - platform: mpr121 + id: bin2 + name: touchkey2 + channel: 2 + - platform: mpr121 + id: bin3 + name: touchkey3 + channel: 3 diff --git a/tests/components/mpu6050/test.esp32-c3-idf.yaml b/tests/components/mpu6050/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..39c8506d2b --- /dev/null +++ b/tests/components/mpu6050/test.esp32-c3-idf.yaml @@ -0,0 +1,22 @@ +i2c: + - id: i2c_mpu6050 + scl: 5 + sda: 4 + +sensor: + - platform: mpu6050 + address: 0x68 + accel_x: + name: MPU6050 Accel X + accel_y: + name: MPU6050 Accel Y + accel_z: + name: MPU6050 Accel z + gyro_x: + name: MPU6050 Gyro X + gyro_y: + name: MPU6050 Gyro Y + gyro_z: + name: MPU6050 Gyro z + temperature: + name: MPU6050 Temperature diff --git a/tests/components/mpu6050/test.esp32-c3.yaml b/tests/components/mpu6050/test.esp32-c3.yaml new file mode 100644 index 0000000000..39c8506d2b --- /dev/null +++ b/tests/components/mpu6050/test.esp32-c3.yaml @@ -0,0 +1,22 @@ +i2c: + - id: i2c_mpu6050 + scl: 5 + sda: 4 + +sensor: + - platform: mpu6050 + address: 0x68 + accel_x: + name: MPU6050 Accel X + accel_y: + name: MPU6050 Accel Y + accel_z: + name: MPU6050 Accel z + gyro_x: + name: MPU6050 Gyro X + gyro_y: + name: MPU6050 Gyro Y + gyro_z: + name: MPU6050 Gyro z + temperature: + name: MPU6050 Temperature diff --git a/tests/components/mpu6050/test.esp32-idf.yaml b/tests/components/mpu6050/test.esp32-idf.yaml new file mode 100644 index 0000000000..45bca55dea --- /dev/null +++ b/tests/components/mpu6050/test.esp32-idf.yaml @@ -0,0 +1,22 @@ +i2c: + - id: i2c_mpu6050 + scl: 16 + sda: 17 + +sensor: + - platform: mpu6050 + address: 0x68 + accel_x: + name: MPU6050 Accel X + accel_y: + name: MPU6050 Accel Y + accel_z: + name: MPU6050 Accel z + gyro_x: + name: MPU6050 Gyro X + gyro_y: + name: MPU6050 Gyro Y + gyro_z: + name: MPU6050 Gyro z + temperature: + name: MPU6050 Temperature diff --git a/tests/components/mpu6050/test.esp32.yaml b/tests/components/mpu6050/test.esp32.yaml new file mode 100644 index 0000000000..45bca55dea --- /dev/null +++ b/tests/components/mpu6050/test.esp32.yaml @@ -0,0 +1,22 @@ +i2c: + - id: i2c_mpu6050 + scl: 16 + sda: 17 + +sensor: + - platform: mpu6050 + address: 0x68 + accel_x: + name: MPU6050 Accel X + accel_y: + name: MPU6050 Accel Y + accel_z: + name: MPU6050 Accel z + gyro_x: + name: MPU6050 Gyro X + gyro_y: + name: MPU6050 Gyro Y + gyro_z: + name: MPU6050 Gyro z + temperature: + name: MPU6050 Temperature diff --git a/tests/components/mpu6050/test.esp8266.yaml b/tests/components/mpu6050/test.esp8266.yaml new file mode 100644 index 0000000000..39c8506d2b --- /dev/null +++ b/tests/components/mpu6050/test.esp8266.yaml @@ -0,0 +1,22 @@ +i2c: + - id: i2c_mpu6050 + scl: 5 + sda: 4 + +sensor: + - platform: mpu6050 + address: 0x68 + accel_x: + name: MPU6050 Accel X + accel_y: + name: MPU6050 Accel Y + accel_z: + name: MPU6050 Accel z + gyro_x: + name: MPU6050 Gyro X + gyro_y: + name: MPU6050 Gyro Y + gyro_z: + name: MPU6050 Gyro z + temperature: + name: MPU6050 Temperature diff --git a/tests/components/mpu6050/test.rp2040.yaml b/tests/components/mpu6050/test.rp2040.yaml new file mode 100644 index 0000000000..39c8506d2b --- /dev/null +++ b/tests/components/mpu6050/test.rp2040.yaml @@ -0,0 +1,22 @@ +i2c: + - id: i2c_mpu6050 + scl: 5 + sda: 4 + +sensor: + - platform: mpu6050 + address: 0x68 + accel_x: + name: MPU6050 Accel X + accel_y: + name: MPU6050 Accel Y + accel_z: + name: MPU6050 Accel z + gyro_x: + name: MPU6050 Gyro X + gyro_y: + name: MPU6050 Gyro Y + gyro_z: + name: MPU6050 Gyro z + temperature: + name: MPU6050 Temperature diff --git a/tests/components/mpu6886/test.esp32-c3-idf.yaml b/tests/components/mpu6886/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..fad51a80b4 --- /dev/null +++ b/tests/components/mpu6886/test.esp32-c3-idf.yaml @@ -0,0 +1,22 @@ +i2c: + - id: i2c_mpu6886 + scl: 5 + sda: 4 + +sensor: + - platform: mpu6886 + address: 0x68 + accel_x: + name: MPU6886 Accel X + accel_y: + name: MPU6886 Accel Y + accel_z: + name: MPU6886 Accel z + gyro_x: + name: MPU6886 Gyro X + gyro_y: + name: MPU6886 Gyro Y + gyro_z: + name: MPU6886 Gyro z + temperature: + name: MPU6886 Temperature diff --git a/tests/components/mpu6886/test.esp32-c3.yaml b/tests/components/mpu6886/test.esp32-c3.yaml new file mode 100644 index 0000000000..fad51a80b4 --- /dev/null +++ b/tests/components/mpu6886/test.esp32-c3.yaml @@ -0,0 +1,22 @@ +i2c: + - id: i2c_mpu6886 + scl: 5 + sda: 4 + +sensor: + - platform: mpu6886 + address: 0x68 + accel_x: + name: MPU6886 Accel X + accel_y: + name: MPU6886 Accel Y + accel_z: + name: MPU6886 Accel z + gyro_x: + name: MPU6886 Gyro X + gyro_y: + name: MPU6886 Gyro Y + gyro_z: + name: MPU6886 Gyro z + temperature: + name: MPU6886 Temperature diff --git a/tests/components/mpu6886/test.esp32-idf.yaml b/tests/components/mpu6886/test.esp32-idf.yaml new file mode 100644 index 0000000000..84e4d56739 --- /dev/null +++ b/tests/components/mpu6886/test.esp32-idf.yaml @@ -0,0 +1,22 @@ +i2c: + - id: i2c_mpu6886 + scl: 16 + sda: 17 + +sensor: + - platform: mpu6886 + address: 0x68 + accel_x: + name: MPU6886 Accel X + accel_y: + name: MPU6886 Accel Y + accel_z: + name: MPU6886 Accel z + gyro_x: + name: MPU6886 Gyro X + gyro_y: + name: MPU6886 Gyro Y + gyro_z: + name: MPU6886 Gyro z + temperature: + name: MPU6886 Temperature diff --git a/tests/components/mpu6886/test.esp32.yaml b/tests/components/mpu6886/test.esp32.yaml new file mode 100644 index 0000000000..84e4d56739 --- /dev/null +++ b/tests/components/mpu6886/test.esp32.yaml @@ -0,0 +1,22 @@ +i2c: + - id: i2c_mpu6886 + scl: 16 + sda: 17 + +sensor: + - platform: mpu6886 + address: 0x68 + accel_x: + name: MPU6886 Accel X + accel_y: + name: MPU6886 Accel Y + accel_z: + name: MPU6886 Accel z + gyro_x: + name: MPU6886 Gyro X + gyro_y: + name: MPU6886 Gyro Y + gyro_z: + name: MPU6886 Gyro z + temperature: + name: MPU6886 Temperature diff --git a/tests/components/mpu6886/test.esp8266.yaml b/tests/components/mpu6886/test.esp8266.yaml new file mode 100644 index 0000000000..fad51a80b4 --- /dev/null +++ b/tests/components/mpu6886/test.esp8266.yaml @@ -0,0 +1,22 @@ +i2c: + - id: i2c_mpu6886 + scl: 5 + sda: 4 + +sensor: + - platform: mpu6886 + address: 0x68 + accel_x: + name: MPU6886 Accel X + accel_y: + name: MPU6886 Accel Y + accel_z: + name: MPU6886 Accel z + gyro_x: + name: MPU6886 Gyro X + gyro_y: + name: MPU6886 Gyro Y + gyro_z: + name: MPU6886 Gyro z + temperature: + name: MPU6886 Temperature diff --git a/tests/components/mpu6886/test.rp2040.yaml b/tests/components/mpu6886/test.rp2040.yaml new file mode 100644 index 0000000000..fad51a80b4 --- /dev/null +++ b/tests/components/mpu6886/test.rp2040.yaml @@ -0,0 +1,22 @@ +i2c: + - id: i2c_mpu6886 + scl: 5 + sda: 4 + +sensor: + - platform: mpu6886 + address: 0x68 + accel_x: + name: MPU6886 Accel X + accel_y: + name: MPU6886 Accel Y + accel_z: + name: MPU6886 Accel z + gyro_x: + name: MPU6886 Gyro X + gyro_y: + name: MPU6886 Gyro Y + gyro_z: + name: MPU6886 Gyro z + temperature: + name: MPU6886 Temperature diff --git a/tests/components/mqtt/test.esp32-c3-idf.yaml b/tests/components/mqtt/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..7702ed5610 --- /dev/null +++ b/tests/components/mqtt/test.esp32-c3-idf.yaml @@ -0,0 +1,16 @@ +wifi: + ssid: MySSID + password: password1 + +mqtt: + broker: test.mosquitto.org + port: 1883 + discovery: true + discovery_prefix: homeassistant + idf_send_async: false + log_topic: + on_message: + topic: testing/sensor/testing_sensor/state + qos: 0 + then: + - logger.log: Mqtt Test diff --git a/tests/components/mqtt/test.esp32-c3.yaml b/tests/components/mqtt/test.esp32-c3.yaml new file mode 100644 index 0000000000..692d504d6d --- /dev/null +++ b/tests/components/mqtt/test.esp32-c3.yaml @@ -0,0 +1,15 @@ +wifi: + ssid: MySSID + password: password1 + +mqtt: + broker: test.mosquitto.org + port: 1883 + discovery: true + discovery_prefix: homeassistant + log_topic: + on_message: + topic: testing/sensor/testing_sensor/state + qos: 0 + then: + - logger.log: Mqtt Test diff --git a/tests/components/mqtt/test.esp32-idf.yaml b/tests/components/mqtt/test.esp32-idf.yaml new file mode 100644 index 0000000000..7702ed5610 --- /dev/null +++ b/tests/components/mqtt/test.esp32-idf.yaml @@ -0,0 +1,16 @@ +wifi: + ssid: MySSID + password: password1 + +mqtt: + broker: test.mosquitto.org + port: 1883 + discovery: true + discovery_prefix: homeassistant + idf_send_async: false + log_topic: + on_message: + topic: testing/sensor/testing_sensor/state + qos: 0 + then: + - logger.log: Mqtt Test diff --git a/tests/components/mqtt/test.esp32.yaml b/tests/components/mqtt/test.esp32.yaml new file mode 100644 index 0000000000..692d504d6d --- /dev/null +++ b/tests/components/mqtt/test.esp32.yaml @@ -0,0 +1,15 @@ +wifi: + ssid: MySSID + password: password1 + +mqtt: + broker: test.mosquitto.org + port: 1883 + discovery: true + discovery_prefix: homeassistant + log_topic: + on_message: + topic: testing/sensor/testing_sensor/state + qos: 0 + then: + - logger.log: Mqtt Test diff --git a/tests/components/mqtt/test.esp8266.yaml b/tests/components/mqtt/test.esp8266.yaml new file mode 100644 index 0000000000..692d504d6d --- /dev/null +++ b/tests/components/mqtt/test.esp8266.yaml @@ -0,0 +1,15 @@ +wifi: + ssid: MySSID + password: password1 + +mqtt: + broker: test.mosquitto.org + port: 1883 + discovery: true + discovery_prefix: homeassistant + log_topic: + on_message: + topic: testing/sensor/testing_sensor/state + qos: 0 + then: + - logger.log: Mqtt Test diff --git a/tests/components/mqtt_subscribe/test.esp32-c3-idf.yaml b/tests/components/mqtt_subscribe/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..070672f15c --- /dev/null +++ b/tests/components/mqtt_subscribe/test.esp32-c3-idf.yaml @@ -0,0 +1,37 @@ +wifi: + ssid: MySSID + password: password1 + +mqtt: + broker: test.mosquitto.org + port: 1883 + discovery: true + discovery_prefix: homeassistant + idf_send_async: false + log_topic: + on_message: + topic: testing/sensor/testing_sensor/state + qos: 0 + then: + - logger.log: Mqtt Test + +sensor: + - platform: mqtt_subscribe + name: MQTT Subscribe Sensor + topic: mqtt/topic + id: the_sensor + qos: 2 + on_value: + - mqtt.publish_json: + topic: the/topic + payload: |- + root["key"] = id(the_sensor).state; + root["greeting"] = "Hello World"; + +text_sensor: + - platform: mqtt_subscribe + name: MQTT Subscribe Text + topic: "the/topic" + qos: 2 + on_value: + - logger.log: "Text sensor got value" diff --git a/tests/components/mqtt_subscribe/test.esp32-c3.yaml b/tests/components/mqtt_subscribe/test.esp32-c3.yaml new file mode 100644 index 0000000000..13ed311b17 --- /dev/null +++ b/tests/components/mqtt_subscribe/test.esp32-c3.yaml @@ -0,0 +1,36 @@ +wifi: + ssid: MySSID + password: password1 + +mqtt: + broker: test.mosquitto.org + port: 1883 + discovery: true + discovery_prefix: homeassistant + log_topic: + on_message: + topic: testing/sensor/testing_sensor/state + qos: 0 + then: + - logger.log: Mqtt Test + +sensor: + - platform: mqtt_subscribe + name: MQTT Subscribe Sensor + topic: mqtt/topic + id: the_sensor + qos: 2 + on_value: + - mqtt.publish_json: + topic: the/topic + payload: |- + root["key"] = id(the_sensor).state; + root["greeting"] = "Hello World"; + +text_sensor: + - platform: mqtt_subscribe + name: MQTT Subscribe Text + topic: "the/topic" + qos: 2 + on_value: + - logger.log: "Text sensor got value" diff --git a/tests/components/mqtt_subscribe/test.esp32-idf.yaml b/tests/components/mqtt_subscribe/test.esp32-idf.yaml new file mode 100644 index 0000000000..070672f15c --- /dev/null +++ b/tests/components/mqtt_subscribe/test.esp32-idf.yaml @@ -0,0 +1,37 @@ +wifi: + ssid: MySSID + password: password1 + +mqtt: + broker: test.mosquitto.org + port: 1883 + discovery: true + discovery_prefix: homeassistant + idf_send_async: false + log_topic: + on_message: + topic: testing/sensor/testing_sensor/state + qos: 0 + then: + - logger.log: Mqtt Test + +sensor: + - platform: mqtt_subscribe + name: MQTT Subscribe Sensor + topic: mqtt/topic + id: the_sensor + qos: 2 + on_value: + - mqtt.publish_json: + topic: the/topic + payload: |- + root["key"] = id(the_sensor).state; + root["greeting"] = "Hello World"; + +text_sensor: + - platform: mqtt_subscribe + name: MQTT Subscribe Text + topic: "the/topic" + qos: 2 + on_value: + - logger.log: "Text sensor got value" diff --git a/tests/components/mqtt_subscribe/test.esp32.yaml b/tests/components/mqtt_subscribe/test.esp32.yaml new file mode 100644 index 0000000000..13ed311b17 --- /dev/null +++ b/tests/components/mqtt_subscribe/test.esp32.yaml @@ -0,0 +1,36 @@ +wifi: + ssid: MySSID + password: password1 + +mqtt: + broker: test.mosquitto.org + port: 1883 + discovery: true + discovery_prefix: homeassistant + log_topic: + on_message: + topic: testing/sensor/testing_sensor/state + qos: 0 + then: + - logger.log: Mqtt Test + +sensor: + - platform: mqtt_subscribe + name: MQTT Subscribe Sensor + topic: mqtt/topic + id: the_sensor + qos: 2 + on_value: + - mqtt.publish_json: + topic: the/topic + payload: |- + root["key"] = id(the_sensor).state; + root["greeting"] = "Hello World"; + +text_sensor: + - platform: mqtt_subscribe + name: MQTT Subscribe Text + topic: "the/topic" + qos: 2 + on_value: + - logger.log: "Text sensor got value" diff --git a/tests/components/mqtt_subscribe/test.esp8266.yaml b/tests/components/mqtt_subscribe/test.esp8266.yaml new file mode 100644 index 0000000000..13ed311b17 --- /dev/null +++ b/tests/components/mqtt_subscribe/test.esp8266.yaml @@ -0,0 +1,36 @@ +wifi: + ssid: MySSID + password: password1 + +mqtt: + broker: test.mosquitto.org + port: 1883 + discovery: true + discovery_prefix: homeassistant + log_topic: + on_message: + topic: testing/sensor/testing_sensor/state + qos: 0 + then: + - logger.log: Mqtt Test + +sensor: + - platform: mqtt_subscribe + name: MQTT Subscribe Sensor + topic: mqtt/topic + id: the_sensor + qos: 2 + on_value: + - mqtt.publish_json: + topic: the/topic + payload: |- + root["key"] = id(the_sensor).state; + root["greeting"] = "Hello World"; + +text_sensor: + - platform: mqtt_subscribe + name: MQTT Subscribe Text + topic: "the/topic" + qos: 2 + on_value: + - logger.log: "Text sensor got value" diff --git a/tests/components/ms5611/test.esp32-c3-idf.yaml b/tests/components/ms5611/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..8f18501eef --- /dev/null +++ b/tests/components/ms5611/test.esp32-c3-idf.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_ms5611 + scl: 5 + sda: 4 + +sensor: + - platform: ms5611 + temperature: + name: Outside Temperature + pressure: + name: Outside Pressure + address: 0x77 + update_interval: 15s diff --git a/tests/components/ms5611/test.esp32-c3.yaml b/tests/components/ms5611/test.esp32-c3.yaml new file mode 100644 index 0000000000..8f18501eef --- /dev/null +++ b/tests/components/ms5611/test.esp32-c3.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_ms5611 + scl: 5 + sda: 4 + +sensor: + - platform: ms5611 + temperature: + name: Outside Temperature + pressure: + name: Outside Pressure + address: 0x77 + update_interval: 15s diff --git a/tests/components/ms5611/test.esp32-idf.yaml b/tests/components/ms5611/test.esp32-idf.yaml new file mode 100644 index 0000000000..b090eeaa93 --- /dev/null +++ b/tests/components/ms5611/test.esp32-idf.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_ms5611 + scl: 16 + sda: 17 + +sensor: + - platform: ms5611 + temperature: + name: Outside Temperature + pressure: + name: Outside Pressure + address: 0x77 + update_interval: 15s diff --git a/tests/components/ms5611/test.esp32.yaml b/tests/components/ms5611/test.esp32.yaml new file mode 100644 index 0000000000..b090eeaa93 --- /dev/null +++ b/tests/components/ms5611/test.esp32.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_ms5611 + scl: 16 + sda: 17 + +sensor: + - platform: ms5611 + temperature: + name: Outside Temperature + pressure: + name: Outside Pressure + address: 0x77 + update_interval: 15s diff --git a/tests/components/ms5611/test.esp8266.yaml b/tests/components/ms5611/test.esp8266.yaml new file mode 100644 index 0000000000..8f18501eef --- /dev/null +++ b/tests/components/ms5611/test.esp8266.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_ms5611 + scl: 5 + sda: 4 + +sensor: + - platform: ms5611 + temperature: + name: Outside Temperature + pressure: + name: Outside Pressure + address: 0x77 + update_interval: 15s diff --git a/tests/components/ms5611/test.rp2040.yaml b/tests/components/ms5611/test.rp2040.yaml new file mode 100644 index 0000000000..8f18501eef --- /dev/null +++ b/tests/components/ms5611/test.rp2040.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_ms5611 + scl: 5 + sda: 4 + +sensor: + - platform: ms5611 + temperature: + name: Outside Temperature + pressure: + name: Outside Pressure + address: 0x77 + update_interval: 15s diff --git a/tests/components/my9231/test.esp32-c3-idf.yaml b/tests/components/my9231/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..3f2e81ef98 --- /dev/null +++ b/tests/components/my9231/test.esp32-c3-idf.yaml @@ -0,0 +1,26 @@ +my9231: + clock_pin: 5 + data_pin: 4 + num_channels: 6 + num_chips: 2 + bit_depth: 16 + +output: + - platform: my9231 + id: my_0 + channel: 0 + - platform: my9231 + id: my_1 + channel: 1 + - platform: my9231 + id: my_2 + channel: 2 + - platform: my9231 + id: my_3 + channel: 3 + - platform: my9231 + id: my_4 + channel: 4 + - platform: my9231 + id: my_5 + channel: 5 diff --git a/tests/components/my9231/test.esp32-c3.yaml b/tests/components/my9231/test.esp32-c3.yaml new file mode 100644 index 0000000000..3f2e81ef98 --- /dev/null +++ b/tests/components/my9231/test.esp32-c3.yaml @@ -0,0 +1,26 @@ +my9231: + clock_pin: 5 + data_pin: 4 + num_channels: 6 + num_chips: 2 + bit_depth: 16 + +output: + - platform: my9231 + id: my_0 + channel: 0 + - platform: my9231 + id: my_1 + channel: 1 + - platform: my9231 + id: my_2 + channel: 2 + - platform: my9231 + id: my_3 + channel: 3 + - platform: my9231 + id: my_4 + channel: 4 + - platform: my9231 + id: my_5 + channel: 5 diff --git a/tests/components/my9231/test.esp32-idf.yaml b/tests/components/my9231/test.esp32-idf.yaml new file mode 100644 index 0000000000..3f2e81ef98 --- /dev/null +++ b/tests/components/my9231/test.esp32-idf.yaml @@ -0,0 +1,26 @@ +my9231: + clock_pin: 5 + data_pin: 4 + num_channels: 6 + num_chips: 2 + bit_depth: 16 + +output: + - platform: my9231 + id: my_0 + channel: 0 + - platform: my9231 + id: my_1 + channel: 1 + - platform: my9231 + id: my_2 + channel: 2 + - platform: my9231 + id: my_3 + channel: 3 + - platform: my9231 + id: my_4 + channel: 4 + - platform: my9231 + id: my_5 + channel: 5 diff --git a/tests/components/my9231/test.esp32.yaml b/tests/components/my9231/test.esp32.yaml new file mode 100644 index 0000000000..3f2e81ef98 --- /dev/null +++ b/tests/components/my9231/test.esp32.yaml @@ -0,0 +1,26 @@ +my9231: + clock_pin: 5 + data_pin: 4 + num_channels: 6 + num_chips: 2 + bit_depth: 16 + +output: + - platform: my9231 + id: my_0 + channel: 0 + - platform: my9231 + id: my_1 + channel: 1 + - platform: my9231 + id: my_2 + channel: 2 + - platform: my9231 + id: my_3 + channel: 3 + - platform: my9231 + id: my_4 + channel: 4 + - platform: my9231 + id: my_5 + channel: 5 diff --git a/tests/components/my9231/test.esp8266.yaml b/tests/components/my9231/test.esp8266.yaml new file mode 100644 index 0000000000..3f2e81ef98 --- /dev/null +++ b/tests/components/my9231/test.esp8266.yaml @@ -0,0 +1,26 @@ +my9231: + clock_pin: 5 + data_pin: 4 + num_channels: 6 + num_chips: 2 + bit_depth: 16 + +output: + - platform: my9231 + id: my_0 + channel: 0 + - platform: my9231 + id: my_1 + channel: 1 + - platform: my9231 + id: my_2 + channel: 2 + - platform: my9231 + id: my_3 + channel: 3 + - platform: my9231 + id: my_4 + channel: 4 + - platform: my9231 + id: my_5 + channel: 5 diff --git a/tests/components/my9231/test.rp2040.yaml b/tests/components/my9231/test.rp2040.yaml new file mode 100644 index 0000000000..3f2e81ef98 --- /dev/null +++ b/tests/components/my9231/test.rp2040.yaml @@ -0,0 +1,26 @@ +my9231: + clock_pin: 5 + data_pin: 4 + num_channels: 6 + num_chips: 2 + bit_depth: 16 + +output: + - platform: my9231 + id: my_0 + channel: 0 + - platform: my9231 + id: my_1 + channel: 1 + - platform: my9231 + id: my_2 + channel: 2 + - platform: my9231 + id: my_3 + channel: 3 + - platform: my9231 + id: my_4 + channel: 4 + - platform: my9231 + id: my_5 + channel: 5 From 6806cb28f616287a4db61eb18ea1f6206e35a50f Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Mon, 22 Apr 2024 22:45:59 -0500 Subject: [PATCH 1304/2101] Add some components to the new testing framework (O) (#6211) --- tests/components/ota/test.esp32-c3-idf.yaml | 30 +++++++++++++++++++ tests/components/ota/test.esp32-c3.yaml | 30 +++++++++++++++++++ tests/components/ota/test.esp32-idf.yaml | 30 +++++++++++++++++++ tests/components/ota/test.esp32.yaml | 30 +++++++++++++++++++ tests/components/ota/test.esp8266.yaml | 30 +++++++++++++++++++ tests/components/ota/test.rp2040.yaml | 30 +++++++++++++++++++ .../components/output/test.esp32-c3-idf.yaml | 13 ++++++++ tests/components/output/test.esp32-c3.yaml | 13 ++++++++ tests/components/output/test.esp32-idf.yaml | 13 ++++++++ tests/components/output/test.esp32.yaml | 13 ++++++++ tests/components/output/test.esp8266.yaml | 13 ++++++++ tests/components/output/test.rp2040.yaml | 13 ++++++++ 12 files changed, 258 insertions(+) create mode 100644 tests/components/ota/test.esp32-c3-idf.yaml create mode 100644 tests/components/ota/test.esp32-c3.yaml create mode 100644 tests/components/ota/test.esp32-idf.yaml create mode 100644 tests/components/ota/test.esp32.yaml create mode 100644 tests/components/ota/test.esp8266.yaml create mode 100644 tests/components/ota/test.rp2040.yaml create mode 100644 tests/components/output/test.esp32-c3-idf.yaml create mode 100644 tests/components/output/test.esp32-c3.yaml create mode 100644 tests/components/output/test.esp32-idf.yaml create mode 100644 tests/components/output/test.esp32.yaml create mode 100644 tests/components/output/test.esp8266.yaml create mode 100644 tests/components/output/test.rp2040.yaml diff --git a/tests/components/ota/test.esp32-c3-idf.yaml b/tests/components/ota/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..367454995f --- /dev/null +++ b/tests/components/ota/test.esp32-c3-idf.yaml @@ -0,0 +1,30 @@ +wifi: + ssid: MySSID + password: password1 + +ota: + safe_mode: true + password: "superlongpasswordthatnoonewillknow" + port: 3286 + reboot_timeout: 2min + num_attempts: 5 + 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); diff --git a/tests/components/ota/test.esp32-c3.yaml b/tests/components/ota/test.esp32-c3.yaml new file mode 100644 index 0000000000..367454995f --- /dev/null +++ b/tests/components/ota/test.esp32-c3.yaml @@ -0,0 +1,30 @@ +wifi: + ssid: MySSID + password: password1 + +ota: + safe_mode: true + password: "superlongpasswordthatnoonewillknow" + port: 3286 + reboot_timeout: 2min + num_attempts: 5 + 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); diff --git a/tests/components/ota/test.esp32-idf.yaml b/tests/components/ota/test.esp32-idf.yaml new file mode 100644 index 0000000000..367454995f --- /dev/null +++ b/tests/components/ota/test.esp32-idf.yaml @@ -0,0 +1,30 @@ +wifi: + ssid: MySSID + password: password1 + +ota: + safe_mode: true + password: "superlongpasswordthatnoonewillknow" + port: 3286 + reboot_timeout: 2min + num_attempts: 5 + 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); diff --git a/tests/components/ota/test.esp32.yaml b/tests/components/ota/test.esp32.yaml new file mode 100644 index 0000000000..367454995f --- /dev/null +++ b/tests/components/ota/test.esp32.yaml @@ -0,0 +1,30 @@ +wifi: + ssid: MySSID + password: password1 + +ota: + safe_mode: true + password: "superlongpasswordthatnoonewillknow" + port: 3286 + reboot_timeout: 2min + num_attempts: 5 + 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); diff --git a/tests/components/ota/test.esp8266.yaml b/tests/components/ota/test.esp8266.yaml new file mode 100644 index 0000000000..367454995f --- /dev/null +++ b/tests/components/ota/test.esp8266.yaml @@ -0,0 +1,30 @@ +wifi: + ssid: MySSID + password: password1 + +ota: + safe_mode: true + password: "superlongpasswordthatnoonewillknow" + port: 3286 + reboot_timeout: 2min + num_attempts: 5 + 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); diff --git a/tests/components/ota/test.rp2040.yaml b/tests/components/ota/test.rp2040.yaml new file mode 100644 index 0000000000..367454995f --- /dev/null +++ b/tests/components/ota/test.rp2040.yaml @@ -0,0 +1,30 @@ +wifi: + ssid: MySSID + password: password1 + +ota: + safe_mode: true + password: "superlongpasswordthatnoonewillknow" + port: 3286 + reboot_timeout: 2min + num_attempts: 5 + 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); diff --git a/tests/components/output/test.esp32-c3-idf.yaml b/tests/components/output/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..c56d85c296 --- /dev/null +++ b/tests/components/output/test.esp32-c3-idf.yaml @@ -0,0 +1,13 @@ +esphome: + on_boot: + then: + - output.turn_off: light_output_1 + - output.turn_on: light_output_1 + - output.set_level: + id: light_output_1 + level: 50% + +output: + - platform: ledc + id: light_output_1 + pin: 1 diff --git a/tests/components/output/test.esp32-c3.yaml b/tests/components/output/test.esp32-c3.yaml new file mode 100644 index 0000000000..c56d85c296 --- /dev/null +++ b/tests/components/output/test.esp32-c3.yaml @@ -0,0 +1,13 @@ +esphome: + on_boot: + then: + - output.turn_off: light_output_1 + - output.turn_on: light_output_1 + - output.set_level: + id: light_output_1 + level: 50% + +output: + - platform: ledc + id: light_output_1 + pin: 1 diff --git a/tests/components/output/test.esp32-idf.yaml b/tests/components/output/test.esp32-idf.yaml new file mode 100644 index 0000000000..480f9dfe1f --- /dev/null +++ b/tests/components/output/test.esp32-idf.yaml @@ -0,0 +1,13 @@ +esphome: + on_boot: + then: + - output.turn_off: light_output_1 + - output.turn_on: light_output_1 + - output.set_level: + id: light_output_1 + level: 50% + +output: + - platform: ledc + id: light_output_1 + pin: 12 diff --git a/tests/components/output/test.esp32.yaml b/tests/components/output/test.esp32.yaml new file mode 100644 index 0000000000..480f9dfe1f --- /dev/null +++ b/tests/components/output/test.esp32.yaml @@ -0,0 +1,13 @@ +esphome: + on_boot: + then: + - output.turn_off: light_output_1 + - output.turn_on: light_output_1 + - output.set_level: + id: light_output_1 + level: 50% + +output: + - platform: ledc + id: light_output_1 + pin: 12 diff --git a/tests/components/output/test.esp8266.yaml b/tests/components/output/test.esp8266.yaml new file mode 100644 index 0000000000..d9cb353636 --- /dev/null +++ b/tests/components/output/test.esp8266.yaml @@ -0,0 +1,13 @@ +esphome: + on_boot: + then: + - output.turn_off: light_output_1 + - output.turn_on: light_output_1 + - output.set_level: + id: light_output_1 + level: 50% + +output: + - platform: esp8266_pwm + id: light_output_1 + pin: 12 diff --git a/tests/components/output/test.rp2040.yaml b/tests/components/output/test.rp2040.yaml new file mode 100644 index 0000000000..399259fdd9 --- /dev/null +++ b/tests/components/output/test.rp2040.yaml @@ -0,0 +1,13 @@ +esphome: + on_boot: + then: + - output.turn_off: light_output_1 + - output.turn_on: light_output_1 + - output.set_level: + id: light_output_1 + level: 50% + +output: + - platform: rp2040_pwm + id: light_output_1 + pin: 12 From fa8d09aca9dc26befd101df0720d4563dd8c1577 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 23 Apr 2024 16:20:37 +1200 Subject: [PATCH 1305/2101] [mopeka_std_check] Fix test file indentation (#6610) --- tests/components/mopeka_std_check/test.esp32-c3-idf.yaml | 9 ++++----- tests/components/mopeka_std_check/test.esp32-c3.yaml | 9 ++++----- tests/components/mopeka_std_check/test.esp32-idf.yaml | 9 ++++----- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/tests/components/mopeka_std_check/test.esp32-c3-idf.yaml b/tests/components/mopeka_std_check/test.esp32-c3-idf.yaml index 830adf952f..383e2e2a19 100644 --- a/tests/components/mopeka_std_check/test.esp32-c3-idf.yaml +++ b/tests/components/mopeka_std_check/test.esp32-c3-idf.yaml @@ -6,11 +6,10 @@ sensor: mac_address: D3:75:F2:DC:16:91 tank_type: Europe_11kg temperature: - name: "Propane test temp" + name: "Propane test temp" level: - name: "Propane test level" + name: "Propane test level" distance: - name: "Propane test distance" + name: "Propane test distance" battery_level: - name: "Propane test battery level" - + name: "Propane test battery level" diff --git a/tests/components/mopeka_std_check/test.esp32-c3.yaml b/tests/components/mopeka_std_check/test.esp32-c3.yaml index 830adf952f..383e2e2a19 100644 --- a/tests/components/mopeka_std_check/test.esp32-c3.yaml +++ b/tests/components/mopeka_std_check/test.esp32-c3.yaml @@ -6,11 +6,10 @@ sensor: mac_address: D3:75:F2:DC:16:91 tank_type: Europe_11kg temperature: - name: "Propane test temp" + name: "Propane test temp" level: - name: "Propane test level" + name: "Propane test level" distance: - name: "Propane test distance" + name: "Propane test distance" battery_level: - name: "Propane test battery level" - + name: "Propane test battery level" diff --git a/tests/components/mopeka_std_check/test.esp32-idf.yaml b/tests/components/mopeka_std_check/test.esp32-idf.yaml index 830adf952f..383e2e2a19 100644 --- a/tests/components/mopeka_std_check/test.esp32-idf.yaml +++ b/tests/components/mopeka_std_check/test.esp32-idf.yaml @@ -6,11 +6,10 @@ sensor: mac_address: D3:75:F2:DC:16:91 tank_type: Europe_11kg temperature: - name: "Propane test temp" + name: "Propane test temp" level: - name: "Propane test level" + name: "Propane test level" distance: - name: "Propane test distance" + name: "Propane test distance" battery_level: - name: "Propane test battery level" - + name: "Propane test battery level" From eb89d99999941a6de6872d3bea01d2ef3c684924 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Mon, 22 Apr 2024 23:47:03 -0500 Subject: [PATCH 1306/2101] Add valve component (#6447) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- CODEOWNERS | 1 + esphome/components/api/api.proto | 51 ++++ esphome/components/api/api_connection.cpp | 42 +++ esphome/components/api/api_connection.h | 5 + esphome/components/api/api_pb2.cpp | 247 ++++++++++++++++++ esphome/components/api/api_pb2.h | 57 ++++ esphome/components/api/api_pb2_service.cpp | 42 +++ esphome/components/api/api_pb2_service.h | 15 ++ esphome/components/api/api_server.cpp | 9 + 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.cpp | 3 + esphome/components/api/subscribe_state.h | 3 + esphome/components/mqtt/__init__.py | 1 + esphome/components/mqtt/mqtt_valve.cpp | 90 +++++++ esphome/components/mqtt/mqtt_valve.h | 41 +++ esphome/components/template/valve/__init__.py | 118 +++++++++ .../template/valve/template_valve.cpp | 131 ++++++++++ .../template/valve/template_valve.h | 60 +++++ esphome/components/valve/__init__.py | 186 +++++++++++++ esphome/components/valve/automation.h | 129 +++++++++ esphome/components/valve/valve.cpp | 179 +++++++++++++ esphome/components/valve/valve.h | 152 +++++++++++ esphome/components/valve/valve_traits.h | 27 ++ .../components/web_server/list_entities.cpp | 9 + esphome/components/web_server/list_entities.h | 3 + esphome/components/web_server/web_server.cpp | 74 ++++++ esphome/components/web_server/web_server.h | 10 + esphome/core/application.h | 19 ++ esphome/core/component_iterator.cpp | 15 ++ esphome/core/component_iterator.h | 6 + esphome/core/controller.cpp | 6 + esphome/core/controller.h | 6 + esphome/core/defines.h | 1 + script/ci-custom.py | 1 + tests/components/template/test.all.yaml | 17 ++ 37 files changed, 1765 insertions(+) create mode 100644 esphome/components/mqtt/mqtt_valve.cpp create mode 100644 esphome/components/mqtt/mqtt_valve.h create mode 100644 esphome/components/template/valve/__init__.py create mode 100644 esphome/components/template/valve/template_valve.cpp create mode 100644 esphome/components/template/valve/template_valve.h create mode 100644 esphome/components/valve/__init__.py create mode 100644 esphome/components/valve/automation.h create mode 100644 esphome/components/valve/valve.cpp create mode 100644 esphome/components/valve/valve.h create mode 100644 esphome/components/valve/valve_traits.h diff --git a/CODEOWNERS b/CODEOWNERS index 9f770d4efc..28ce8e7b6a 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -390,6 +390,7 @@ esphome/components/ufire_ec/* @pvizeli esphome/components/ufire_ise/* @pvizeli esphome/components/ultrasonic/* @OttoWinter esphome/components/uponor_smatrix/* @kroimon +esphome/components/valve/* @esphome/core esphome/components/vbus/* @ssieb esphome/components/veml3235/* @kbx81 esphome/components/veml7700/* @latonita diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index 8d5459e717..12b7ef0958 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -43,6 +43,7 @@ service APIConnection { rpc select_command (SelectCommandRequest) returns (void) {} rpc button_command (ButtonCommandRequest) returns (void) {} rpc lock_command (LockCommandRequest) returns (void) {} + rpc valve_command (ValveCommandRequest) returns (void) {} rpc media_player_command (MediaPlayerCommandRequest) returns (void) {} rpc date_command (DateCommandRequest) returns (void) {} rpc time_command (TimeCommandRequest) returns (void) {} @@ -1700,3 +1701,53 @@ message TimeCommandRequest { uint32 minute = 3; uint32 second = 4; } + + +// ==================== VALVE ==================== +message ListEntitiesValveResponse { + option (id) = 109; + option (source) = SOURCE_SERVER; + option (ifdef) = "USE_VALVE"; + + string object_id = 1; + fixed32 key = 2; + string name = 3; + string unique_id = 4; + + string icon = 5; + bool disabled_by_default = 6; + EntityCategory entity_category = 7; + string device_class = 8; + + bool assumed_state = 9; + bool supports_position = 10; + bool supports_stop = 11; +} + +enum ValveOperation { + VALVE_OPERATION_IDLE = 0; + VALVE_OPERATION_IS_OPENING = 1; + VALVE_OPERATION_IS_CLOSING = 2; +} +message ValveStateResponse { + option (id) = 110; + option (source) = SOURCE_SERVER; + option (ifdef) = "USE_VALVE"; + option (no_delay) = true; + + fixed32 key = 1; + float position = 2; + ValveOperation current_operation = 3; +} + +message ValveCommandRequest { + option (id) = 111; + option (source) = SOURCE_CLIENT; + option (ifdef) = "USE_VALVE"; + option (no_delay) = true; + + fixed32 key = 1; + bool has_position = 2; + float position = 3; + bool stop = 4; +} diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index e51fa8c154..47136fff98 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -915,6 +915,48 @@ void APIConnection::lock_command(const LockCommandRequest &msg) { } #endif +#ifdef USE_VALVE +bool APIConnection::send_valve_state(valve::Valve *valve) { + if (!this->state_subscription_) + return false; + + ValveStateResponse resp{}; + resp.key = valve->get_object_id_hash(); + resp.position = valve->position; + resp.current_operation = static_cast(valve->current_operation); + return this->send_valve_state_response(resp); +} +bool APIConnection::send_valve_info(valve::Valve *valve) { + auto traits = valve->get_traits(); + ListEntitiesValveResponse msg; + msg.key = valve->get_object_id_hash(); + msg.object_id = valve->get_object_id(); + if (valve->has_own_name()) + msg.name = valve->get_name(); + msg.unique_id = get_default_unique_id("valve", valve); + msg.icon = valve->get_icon(); + msg.disabled_by_default = valve->is_disabled_by_default(); + msg.entity_category = static_cast(valve->get_entity_category()); + msg.device_class = valve->get_device_class(); + msg.assumed_state = traits.get_is_assumed_state(); + msg.supports_position = traits.get_supports_position(); + msg.supports_stop = traits.get_supports_stop(); + return this->send_list_entities_valve_response(msg); +} +void APIConnection::valve_command(const ValveCommandRequest &msg) { + valve::Valve *valve = App.get_valve_by_key(msg.key); + if (valve == nullptr) + return; + + auto call = valve->make_call(); + if (msg.has_position) + call.set_position(msg.position); + if (msg.stop) + call.set_command_stop(); + call.perform(); +} +#endif + #ifdef USE_MEDIA_PLAYER bool APIConnection::send_media_player_state(media_player::MediaPlayer *media_player) { if (!this->state_subscription_) diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index 5c0a78015d..af2dd9e681 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -101,6 +101,11 @@ class APIConnection : public APIServerConnection { bool send_lock_info(lock::Lock *a_lock); void lock_command(const LockCommandRequest &msg) override; #endif +#ifdef USE_VALVE + bool send_valve_state(valve::Valve *valve); + bool send_valve_info(valve::Valve *valve); + void valve_command(const ValveCommandRequest &msg) override; +#endif #ifdef USE_MEDIA_PLAYER bool send_media_player_state(media_player::MediaPlayer *media_player); bool send_media_player_info(media_player::MediaPlayer *media_player); diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index 884396bda3..508947ba24 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -537,6 +537,20 @@ template<> const char *proto_enum_to_string(enums::TextMode val } } #endif +#ifdef HAS_PROTO_MESSAGE_DUMP +template<> const char *proto_enum_to_string(enums::ValveOperation value) { + switch (value) { + case enums::VALVE_OPERATION_IDLE: + return "VALVE_OPERATION_IDLE"; + case enums::VALVE_OPERATION_IS_OPENING: + return "VALVE_OPERATION_IS_OPENING"; + case enums::VALVE_OPERATION_IS_CLOSING: + return "VALVE_OPERATION_IS_CLOSING"; + default: + return "UNKNOWN"; + } +} +#endif bool HelloRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { case 2: { @@ -7695,6 +7709,239 @@ void TimeCommandRequest::dump_to(std::string &out) const { out.append("}"); } #endif +bool ListEntitiesValveResponse::decode_varint(uint32_t field_id, ProtoVarInt value) { + switch (field_id) { + case 6: { + this->disabled_by_default = value.as_bool(); + return true; + } + case 7: { + this->entity_category = value.as_enum(); + return true; + } + case 9: { + this->assumed_state = value.as_bool(); + return true; + } + case 10: { + this->supports_position = value.as_bool(); + return true; + } + case 11: { + this->supports_stop = value.as_bool(); + return true; + } + default: + return false; + } +} +bool ListEntitiesValveResponse::decode_length(uint32_t field_id, ProtoLengthDelimited value) { + switch (field_id) { + case 1: { + this->object_id = value.as_string(); + return true; + } + case 3: { + this->name = value.as_string(); + return true; + } + case 4: { + this->unique_id = value.as_string(); + return true; + } + case 5: { + this->icon = value.as_string(); + return true; + } + case 8: { + this->device_class = value.as_string(); + return true; + } + default: + return false; + } +} +bool ListEntitiesValveResponse::decode_32bit(uint32_t field_id, Proto32Bit value) { + switch (field_id) { + case 2: { + this->key = value.as_fixed32(); + return true; + } + default: + return false; + } +} +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); + buffer.encode_string(4, this->unique_id); + buffer.encode_string(5, this->icon); + buffer.encode_bool(6, this->disabled_by_default); + buffer.encode_enum(7, 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); +} +#ifdef HAS_PROTO_MESSAGE_DUMP +void ListEntitiesValveResponse::dump_to(std::string &out) const { + __attribute__((unused)) char buffer[64]; + out.append("ListEntitiesValveResponse {\n"); + out.append(" object_id: "); + out.append("'").append(this->object_id).append("'"); + out.append("\n"); + + out.append(" key: "); + sprintf(buffer, "%" PRIu32, this->key); + out.append(buffer); + out.append("\n"); + + out.append(" name: "); + out.append("'").append(this->name).append("'"); + out.append("\n"); + + out.append(" unique_id: "); + out.append("'").append(this->unique_id).append("'"); + out.append("\n"); + + out.append(" icon: "); + out.append("'").append(this->icon).append("'"); + out.append("\n"); + + out.append(" disabled_by_default: "); + out.append(YESNO(this->disabled_by_default)); + out.append("\n"); + + out.append(" entity_category: "); + out.append(proto_enum_to_string(this->entity_category)); + out.append("\n"); + + out.append(" device_class: "); + out.append("'").append(this->device_class).append("'"); + out.append("\n"); + + out.append(" assumed_state: "); + out.append(YESNO(this->assumed_state)); + out.append("\n"); + + out.append(" supports_position: "); + out.append(YESNO(this->supports_position)); + out.append("\n"); + + out.append(" supports_stop: "); + out.append(YESNO(this->supports_stop)); + out.append("\n"); + out.append("}"); +} +#endif +bool ValveStateResponse::decode_varint(uint32_t field_id, ProtoVarInt value) { + switch (field_id) { + case 3: { + this->current_operation = value.as_enum(); + return true; + } + default: + return false; + } +} +bool ValveStateResponse::decode_32bit(uint32_t field_id, Proto32Bit value) { + switch (field_id) { + case 1: { + this->key = value.as_fixed32(); + return true; + } + case 2: { + this->position = value.as_float(); + return true; + } + default: + return false; + } +} +void ValveStateResponse::encode(ProtoWriteBuffer buffer) const { + buffer.encode_fixed32(1, this->key); + buffer.encode_float(2, this->position); + buffer.encode_enum(3, this->current_operation); +} +#ifdef HAS_PROTO_MESSAGE_DUMP +void ValveStateResponse::dump_to(std::string &out) const { + __attribute__((unused)) char buffer[64]; + out.append("ValveStateResponse {\n"); + out.append(" key: "); + sprintf(buffer, "%" PRIu32, this->key); + out.append(buffer); + out.append("\n"); + + out.append(" position: "); + sprintf(buffer, "%g", this->position); + out.append(buffer); + out.append("\n"); + + out.append(" current_operation: "); + out.append(proto_enum_to_string(this->current_operation)); + out.append("\n"); + out.append("}"); +} +#endif +bool ValveCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { + switch (field_id) { + case 2: { + this->has_position = value.as_bool(); + return true; + } + case 4: { + this->stop = value.as_bool(); + return true; + } + default: + return false; + } +} +bool ValveCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { + switch (field_id) { + case 1: { + this->key = value.as_fixed32(); + return true; + } + case 3: { + this->position = value.as_float(); + return true; + } + default: + return false; + } +} +void ValveCommandRequest::encode(ProtoWriteBuffer buffer) const { + buffer.encode_fixed32(1, this->key); + buffer.encode_bool(2, this->has_position); + buffer.encode_float(3, this->position); + buffer.encode_bool(4, this->stop); +} +#ifdef HAS_PROTO_MESSAGE_DUMP +void ValveCommandRequest::dump_to(std::string &out) const { + __attribute__((unused)) char buffer[64]; + out.append("ValveCommandRequest {\n"); + out.append(" key: "); + sprintf(buffer, "%" PRIu32, this->key); + out.append(buffer); + out.append("\n"); + + out.append(" has_position: "); + out.append(YESNO(this->has_position)); + out.append("\n"); + + out.append(" position: "); + sprintf(buffer, "%g", this->position); + out.append(buffer); + out.append("\n"); + + out.append(" stop: "); + out.append(YESNO(this->stop)); + out.append("\n"); + out.append("}"); +} +#endif } // namespace api } // namespace esphome diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index 2ae6fd2bb6..950ffcdc88 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -216,6 +216,11 @@ enum TextMode : uint32_t { TEXT_MODE_TEXT = 0, TEXT_MODE_PASSWORD = 1, }; +enum ValveOperation : uint32_t { + VALVE_OPERATION_IDLE = 0, + VALVE_OPERATION_IS_OPENING = 1, + VALVE_OPERATION_IS_CLOSING = 2, +}; } // namespace enums @@ -1969,6 +1974,58 @@ class TimeCommandRequest : public ProtoMessage { bool decode_32bit(uint32_t field_id, Proto32Bit value) override; bool decode_varint(uint32_t field_id, ProtoVarInt value) override; }; +class ListEntitiesValveResponse : public ProtoMessage { + public: + std::string object_id{}; + uint32_t key{0}; + std::string name{}; + std::string unique_id{}; + std::string icon{}; + bool disabled_by_default{false}; + enums::EntityCategory entity_category{}; + std::string device_class{}; + bool assumed_state{false}; + bool supports_position{false}; + bool supports_stop{false}; + void encode(ProtoWriteBuffer buffer) const override; +#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 ValveStateResponse : public ProtoMessage { + public: + uint32_t key{0}; + float position{0.0f}; + enums::ValveOperation current_operation{}; + void encode(ProtoWriteBuffer buffer) const override; +#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_varint(uint32_t field_id, ProtoVarInt value) override; +}; +class ValveCommandRequest : public ProtoMessage { + public: + uint32_t key{0}; + bool has_position{false}; + float position{0.0f}; + bool stop{false}; + void encode(ProtoWriteBuffer buffer) const override; +#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_varint(uint32_t field_id, ProtoVarInt value) override; +}; } // namespace api } // namespace esphome diff --git a/esphome/components/api/api_pb2_service.cpp b/esphome/components/api/api_pb2_service.cpp index 7a97df1ce0..4b8b8cf5ae 100644 --- a/esphome/components/api/api_pb2_service.cpp +++ b/esphome/components/api/api_pb2_service.cpp @@ -557,6 +557,24 @@ bool APIServerConnectionBase::send_time_state_response(const TimeStateResponse & #endif #ifdef USE_DATETIME_TIME #endif +#ifdef USE_VALVE +bool APIServerConnectionBase::send_list_entities_valve_response(const ListEntitiesValveResponse &msg) { +#ifdef HAS_PROTO_MESSAGE_DUMP + ESP_LOGVV(TAG, "send_list_entities_valve_response: %s", msg.dump().c_str()); +#endif + return this->send_message_(msg, 109); +} +#endif +#ifdef USE_VALVE +bool APIServerConnectionBase::send_valve_state_response(const ValveStateResponse &msg) { +#ifdef HAS_PROTO_MESSAGE_DUMP + ESP_LOGVV(TAG, "send_valve_state_response: %s", msg.dump().c_str()); +#endif + return this->send_message_(msg, 110); +} +#endif +#ifdef USE_VALVE +#endif bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) { switch (msg_type) { case 1: { @@ -1019,6 +1037,17 @@ bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, ESP_LOGVV(TAG, "on_voice_assistant_audio: %s", msg.dump().c_str()); #endif this->on_voice_assistant_audio(msg); +#endif + break; + } + case 111: { +#ifdef USE_VALVE + 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()); +#endif + this->on_valve_command_request(msg); #endif break; } @@ -1282,6 +1311,19 @@ void APIServerConnection::on_lock_command_request(const LockCommandRequest &msg) this->lock_command(msg); } #endif +#ifdef USE_VALVE +void APIServerConnection::on_valve_command_request(const ValveCommandRequest &msg) { + if (!this->is_connection_setup()) { + this->on_no_setup_connection(); + return; + } + if (!this->is_authenticated()) { + this->on_unauthenticated_access(); + return; + } + this->valve_command(msg); +} +#endif #ifdef USE_MEDIA_PLAYER void APIServerConnection::on_media_player_command_request(const MediaPlayerCommandRequest &msg) { if (!this->is_connection_setup()) { diff --git a/esphome/components/api/api_pb2_service.h b/esphome/components/api/api_pb2_service.h index 095ce51b0f..9f1d711257 100644 --- a/esphome/components/api/api_pb2_service.h +++ b/esphome/components/api/api_pb2_service.h @@ -279,6 +279,15 @@ class APIServerConnectionBase : public ProtoService { #endif #ifdef USE_DATETIME_TIME virtual void on_time_command_request(const TimeCommandRequest &value){}; +#endif +#ifdef USE_VALVE + bool send_list_entities_valve_response(const ListEntitiesValveResponse &msg); +#endif +#ifdef USE_VALVE + bool send_valve_state_response(const ValveStateResponse &msg); +#endif +#ifdef USE_VALVE + virtual void on_valve_command_request(const ValveCommandRequest &value){}; #endif protected: bool read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) override; @@ -331,6 +340,9 @@ class APIServerConnection : public APIServerConnectionBase { #ifdef USE_LOCK virtual void lock_command(const LockCommandRequest &msg) = 0; #endif +#ifdef USE_VALVE + virtual void valve_command(const ValveCommandRequest &msg) = 0; +#endif #ifdef USE_MEDIA_PLAYER virtual void media_player_command(const MediaPlayerCommandRequest &msg) = 0; #endif @@ -423,6 +435,9 @@ class APIServerConnection : public APIServerConnectionBase { #ifdef USE_LOCK void on_lock_command_request(const LockCommandRequest &msg) override; #endif +#ifdef USE_VALVE + void on_valve_command_request(const ValveCommandRequest &msg) override; +#endif #ifdef USE_MEDIA_PLAYER void on_media_player_command_request(const MediaPlayerCommandRequest &msg) override; #endif diff --git a/esphome/components/api/api_server.cpp b/esphome/components/api/api_server.cpp index 4c809126e6..457eeb1229 100644 --- a/esphome/components/api/api_server.cpp +++ b/esphome/components/api/api_server.cpp @@ -300,6 +300,15 @@ void APIServer::on_lock_update(lock::Lock *obj) { } #endif +#ifdef USE_VALVE +void APIServer::on_valve_update(valve::Valve *obj) { + if (obj->is_internal()) + return; + for (auto &c : this->clients_) + c->send_valve_state(obj); +} +#endif + #ifdef USE_MEDIA_PLAYER void APIServer::on_media_player_update(media_player::MediaPlayer *obj) { if (obj->is_internal()) diff --git a/esphome/components/api/api_server.h b/esphome/components/api/api_server.h index 8a9c26af73..d64643b961 100644 --- a/esphome/components/api/api_server.h +++ b/esphome/components/api/api_server.h @@ -81,6 +81,9 @@ class APIServer : public Component, public Controller { #ifdef USE_LOCK void on_lock_update(lock::Lock *obj) override; #endif +#ifdef USE_VALVE + void on_valve_update(valve::Valve *obj) override; +#endif #ifdef USE_MEDIA_PLAYER void on_media_player_update(media_player::MediaPlayer *obj) override; #endif diff --git a/esphome/components/api/list_entities.cpp b/esphome/components/api/list_entities.cpp index 18685ee4d1..d6ff8e5557 100644 --- a/esphome/components/api/list_entities.cpp +++ b/esphome/components/api/list_entities.cpp @@ -38,6 +38,9 @@ bool ListEntitiesIterator::on_text_sensor(text_sensor::TextSensor *text_sensor) #ifdef USE_LOCK bool ListEntitiesIterator::on_lock(lock::Lock *a_lock) { return this->client_->send_lock_info(a_lock); } #endif +#ifdef USE_VALVE +bool ListEntitiesIterator::on_valve(valve::Valve *valve) { return this->client_->send_valve_info(valve); } +#endif bool ListEntitiesIterator::on_end() { return this->client_->send_list_info_done(); } ListEntitiesIterator::ListEntitiesIterator(APIConnection *client) : client_(client) {} diff --git a/esphome/components/api/list_entities.h b/esphome/components/api/list_entities.h index 95a09fc25b..5d0c243f4a 100644 --- a/esphome/components/api/list_entities.h +++ b/esphome/components/api/list_entities.h @@ -61,6 +61,9 @@ class ListEntitiesIterator : public ComponentIterator { #ifdef USE_LOCK bool on_lock(lock::Lock *a_lock) override; #endif +#ifdef USE_VALVE + bool on_valve(valve::Valve *valve) override; +#endif #ifdef USE_MEDIA_PLAYER bool on_media_player(media_player::MediaPlayer *media_player) override; #endif diff --git a/esphome/components/api/subscribe_state.cpp b/esphome/components/api/subscribe_state.cpp index 5eb40cfa7e..7aa8e8ffac 100644 --- a/esphome/components/api/subscribe_state.cpp +++ b/esphome/components/api/subscribe_state.cpp @@ -59,6 +59,9 @@ bool InitialStateIterator::on_select(select::Select *select) { #ifdef USE_LOCK bool InitialStateIterator::on_lock(lock::Lock *a_lock) { return this->client_->send_lock_state(a_lock, a_lock->state); } #endif +#ifdef USE_VALVE +bool InitialStateIterator::on_valve(valve::Valve *valve) { return this->client_->send_valve_state(valve); } +#endif #ifdef USE_MEDIA_PLAYER bool InitialStateIterator::on_media_player(media_player::MediaPlayer *media_player) { return this->client_->send_media_player_state(media_player); diff --git a/esphome/components/api/subscribe_state.h b/esphome/components/api/subscribe_state.h index 447f1707d2..8d50e0d89a 100644 --- a/esphome/components/api/subscribe_state.h +++ b/esphome/components/api/subscribe_state.h @@ -58,6 +58,9 @@ class InitialStateIterator : public ComponentIterator { #ifdef USE_LOCK bool on_lock(lock::Lock *a_lock) override; #endif +#ifdef USE_VALVE + bool on_valve(valve::Valve *valve) override; +#endif #ifdef USE_MEDIA_PLAYER bool on_media_player(media_player::MediaPlayer *media_player) override; #endif diff --git a/esphome/components/mqtt/__init__.py b/esphome/components/mqtt/__init__.py index b2c03c1546..72ee81dbbc 100644 --- a/esphome/components/mqtt/__init__.py +++ b/esphome/components/mqtt/__init__.py @@ -119,6 +119,7 @@ MQTTTextComponent = mqtt_ns.class_("MQTTTextComponent", MQTTComponent) MQTTSelectComponent = mqtt_ns.class_("MQTTSelectComponent", MQTTComponent) MQTTButtonComponent = mqtt_ns.class_("MQTTButtonComponent", MQTTComponent) MQTTLockComponent = mqtt_ns.class_("MQTTLockComponent", MQTTComponent) +MQTTValveComponent = mqtt_ns.class_("MQTTValveComponent", MQTTComponent) MQTTDiscoveryUniqueIdGenerator = mqtt_ns.enum("MQTTDiscoveryUniqueIdGenerator") MQTT_DISCOVERY_UNIQUE_ID_GENERATOR_OPTIONS = { diff --git a/esphome/components/mqtt/mqtt_valve.cpp b/esphome/components/mqtt/mqtt_valve.cpp new file mode 100644 index 0000000000..07eeca08d6 --- /dev/null +++ b/esphome/components/mqtt/mqtt_valve.cpp @@ -0,0 +1,90 @@ +#include "mqtt_valve.h" +#include "esphome/core/log.h" + +#include "mqtt_const.h" + +#ifdef USE_MQTT +#ifdef USE_VALVE + +namespace esphome { +namespace mqtt { + +static const char *const TAG = "mqtt.valve"; + +using namespace esphome::valve; + +MQTTValveComponent::MQTTValveComponent(Valve *valve) : valve_(valve) {} +void MQTTValveComponent::setup() { + auto traits = this->valve_->get_traits(); + this->valve_->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->valve_->make_call(); + call.set_command(payload.c_str()); + call.perform(); + }); + if (traits.get_supports_position()) { + this->subscribe(this->get_position_command_topic(), [this](const std::string &topic, const std::string &payload) { + auto value = parse_number(payload); + if (!value.has_value()) { + ESP_LOGW(TAG, "Invalid position value: '%s'", payload.c_str()); + return; + } + auto call = this->valve_->make_call(); + call.set_position(*value / 100.0f); + call.perform(); + }); + } +} + +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) + if (traits.get_supports_position()) { + ESP_LOGCONFIG(TAG, " Position State Topic: '%s'", this->get_position_state_topic().c_str()); + ESP_LOGCONFIG(TAG, " Position Command Topic: '%s'", this->get_position_command_topic().c_str()); + } +} +void MQTTValveComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { + if (!this->valve_->get_device_class().empty()) + root[MQTT_DEVICE_CLASS] = this->valve_->get_device_class(); + + auto traits = this->valve_->get_traits(); + 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(); + } +} + +std::string MQTTValveComponent::component_type() const { return "valve"; } +const EntityBase *MQTTValveComponent::get_entity() const { return this->valve_; } + +bool MQTTValveComponent::send_initial_state() { return this->publish_state(); } +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); + if (!this->publish(this->get_position_state_topic(), pos)) + 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"; + if (!this->publish(this->get_state_topic_(), state_s)) + success = false; + return success; +} + +} // namespace mqtt +} // namespace esphome + +#endif +#endif // USE_MQTT diff --git a/esphome/components/mqtt/mqtt_valve.h b/esphome/components/mqtt/mqtt_valve.h new file mode 100644 index 0000000000..63a0462193 --- /dev/null +++ b/esphome/components/mqtt/mqtt_valve.h @@ -0,0 +1,41 @@ +#pragma once + +#include "esphome/core/defines.h" +#include "mqtt_component.h" + +#ifdef USE_MQTT +#ifdef USE_VALVE + +#include "esphome/components/valve/valve.h" + +namespace esphome { +namespace mqtt { + +class MQTTValveComponent : public mqtt::MQTTComponent { + public: + explicit MQTTValveComponent(valve::Valve *valve); + + void setup() override; + void send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) override; + + MQTT_COMPONENT_CUSTOM_TOPIC(position, command) + MQTT_COMPONENT_CUSTOM_TOPIC(position, state) + + bool send_initial_state() override; + + bool publish_state(); + + void dump_config() override; + + protected: + std::string component_type() const override; + const EntityBase *get_entity() const override; + + valve::Valve *valve_; +}; + +} // namespace mqtt +} // namespace esphome + +#endif +#endif // USE_MQTT diff --git a/esphome/components/template/valve/__init__.py b/esphome/components/template/valve/__init__.py new file mode 100644 index 0000000000..89d776dfdd --- /dev/null +++ b/esphome/components/template/valve/__init__.py @@ -0,0 +1,118 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome import automation +from esphome.components import valve +from esphome.const import ( + CONF_ASSUMED_STATE, + CONF_CLOSE_ACTION, + CONF_CURRENT_OPERATION, + CONF_ID, + CONF_LAMBDA, + CONF_OPEN_ACTION, + CONF_OPTIMISTIC, + CONF_POSITION, + CONF_POSITION_ACTION, + CONF_RESTORE_MODE, + CONF_STATE, + CONF_STOP_ACTION, +) +from .. import template_ns + +TemplateValve = template_ns.class_("TemplateValve", valve.Valve, cg.Component) + +TemplateValveRestoreMode = template_ns.enum("TemplateValveRestoreMode") +RESTORE_MODES = { + "NO_RESTORE": TemplateValveRestoreMode.VALVE_NO_RESTORE, + "RESTORE": TemplateValveRestoreMode.VALVE_RESTORE, + "RESTORE_AND_CALL": TemplateValveRestoreMode.VALVE_RESTORE_AND_CALL, +} + +CONF_HAS_POSITION = "has_position" +CONF_TOGGLE_ACTION = "toggle_action" + +CONFIG_SCHEMA = valve.VALVE_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(TemplateValve), + cv.Optional(CONF_LAMBDA): cv.returning_lambda, + cv.Optional(CONF_OPTIMISTIC, default=False): cv.boolean, + cv.Optional(CONF_ASSUMED_STATE, default=False): cv.boolean, + cv.Optional(CONF_HAS_POSITION, default=False): cv.boolean, + cv.Optional(CONF_OPEN_ACTION): automation.validate_automation(single=True), + cv.Optional(CONF_CLOSE_ACTION): automation.validate_automation(single=True), + cv.Optional(CONF_STOP_ACTION): automation.validate_automation(single=True), + cv.Optional(CONF_TOGGLE_ACTION): automation.validate_automation(single=True), + cv.Optional(CONF_POSITION_ACTION): automation.validate_automation(single=True), + cv.Optional(CONF_RESTORE_MODE, default="NO_RESTORE"): cv.enum( + RESTORE_MODES, upper=True + ), + } +).extend(cv.COMPONENT_SCHEMA) + + +async def to_code(config): + var = await valve.new_valve(config) + await cg.register_component(var, config) + if lambda_config := config.get(CONF_LAMBDA): + template_ = await cg.process_lambda( + lambda_config, [], return_type=cg.optional.template(float) + ) + cg.add(var.set_state_lambda(template_)) + if open_action_config := config.get(CONF_OPEN_ACTION): + await automation.build_automation( + var.get_open_trigger(), [], open_action_config + ) + if close_action_config := config.get(CONF_CLOSE_ACTION): + await automation.build_automation( + var.get_close_trigger(), [], close_action_config + ) + if stop_action_config := config.get(CONF_STOP_ACTION): + await automation.build_automation( + var.get_stop_trigger(), [], stop_action_config + ) + cg.add(var.set_has_stop(True)) + if toggle_action_config := config.get(CONF_TOGGLE_ACTION): + await automation.build_automation( + var.get_toggle_trigger(), [], toggle_action_config + ) + cg.add(var.set_has_toggle(True)) + if position_action_config := config.get(CONF_POSITION_ACTION): + await automation.build_automation( + var.get_position_trigger(), [(float, "pos")], position_action_config + ) + cg.add(var.set_has_position(True)) + else: + cg.add(var.set_has_position(config[CONF_HAS_POSITION])) + 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])) + + +@automation.register_action( + "valve.template.publish", + valve.ValvePublishAction, + cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(valve.Valve), + cv.Exclusive(CONF_STATE, "pos"): cv.templatable(valve.validate_valve_state), + cv.Exclusive(CONF_POSITION, "pos"): cv.templatable(cv.percentage), + cv.Optional(CONF_CURRENT_OPERATION): cv.templatable( + valve.validate_valve_operation + ), + } + ), +) +async def valve_template_publish_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 state_config := config.get(CONF_STATE): + template_ = await cg.templatable(state_config, args, float) + cg.add(var.set_position(template_)) + if (position_config := config.get(CONF_POSITION)) is not None: + template_ = await cg.templatable(position_config, args, float) + cg.add(var.set_position(template_)) + if current_operation_config := config.get(CONF_CURRENT_OPERATION): + template_ = await cg.templatable( + current_operation_config, args, valve.ValveOperation + ) + cg.add(var.set_current_operation(template_)) + return var diff --git a/esphome/components/template/valve/template_valve.cpp b/esphome/components/template/valve/template_valve.cpp new file mode 100644 index 0000000000..f943e19da9 --- /dev/null +++ b/esphome/components/template/valve/template_valve.cpp @@ -0,0 +1,131 @@ +#include "template_valve.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace template_ { + +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()) {} + +void TemplateValve::setup() { + ESP_LOGCONFIG(TAG, "Setting up template valve '%s'...", this->name_.c_str()); + switch (this->restore_mode_) { + case VALVE_NO_RESTORE: + break; + case VALVE_RESTORE: { + auto restore = this->restore_state_(); + if (restore.has_value()) + restore->apply(this); + break; + } + case VALVE_RESTORE_AND_CALL: { + auto restore = this->restore_state_(); + if (restore.has_value()) { + restore->to_call(this).perform(); + } + break; + } + } +} + +void TemplateValve::loop() { + bool changed = false; + + if (this->state_f_.has_value()) { + auto s = (*this->state_f_)(); + if (s.has_value()) { + auto pos = clamp(*s, 0.0f, 1.0f); + if (pos != this->position) { + this->position = pos; + changed = true; + } + } + } + + if (changed) + this->publish_state(); +} + +void TemplateValve::set_optimistic(bool optimistic) { this->optimistic_ = optimistic; } +void TemplateValve::set_assumed_state(bool assumed_state) { this->assumed_state_ = assumed_state; } +void TemplateValve::set_state_lambda(std::function()> &&f) { this->state_f_ = f; } +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_; } + +void TemplateValve::dump_config() { + LOG_VALVE("", "Template Valve", this); + ESP_LOGCONFIG(TAG, " Has position: %s", YESNO(this->has_position_)); + ESP_LOGCONFIG(TAG, " Optimistic: %s", YESNO(this->optimistic_)); +} + +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->publish_state(); + } + if (call.get_toggle().has_value()) { + this->stop_prev_trigger_(); + this->toggle_trigger_->trigger(); + this->prev_command_trigger_ = this->toggle_trigger_; + this->publish_state(); + } + if (call.get_position().has_value()) { + auto pos = *call.get_position(); + this->stop_prev_trigger_(); + + if (pos == VALVE_OPEN) { + 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_; + } else { + this->position_trigger_->trigger(pos); + } + + if (this->optimistic_) { + this->position = pos; + } + } + + this->publish_state(); +} + +ValveTraits TemplateValve::get_traits() { + auto traits = ValveTraits(); + traits.set_is_assumed_state(this->assumed_state_); + traits.set_supports_stop(this->has_stop_); + traits.set_supports_toggle(this->has_toggle_); + traits.set_supports_position(this->has_position_); + return traits; +} + +Trigger *TemplateValve::get_position_trigger() const { 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; } +void TemplateValve::set_has_position(bool has_position) { this->has_position_ = has_position; } + +void TemplateValve::stop_prev_trigger_() { + if (this->prev_command_trigger_ != nullptr) { + this->prev_command_trigger_->stop_action(); + this->prev_command_trigger_ = nullptr; + } +} + +} // namespace template_ +} // namespace esphome diff --git a/esphome/components/template/valve/template_valve.h b/esphome/components/template/valve/template_valve.h new file mode 100644 index 0000000000..5e3fb6aff3 --- /dev/null +++ b/esphome/components/template/valve/template_valve.h @@ -0,0 +1,60 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/core/automation.h" +#include "esphome/components/valve/valve.h" + +namespace esphome { +namespace template_ { + +enum TemplateValveRestoreMode { + VALVE_NO_RESTORE, + VALVE_RESTORE, + VALVE_RESTORE_AND_CALL, +}; + +class TemplateValve : public valve::Valve, public Component { + public: + TemplateValve(); + + void set_state_lambda(std::function()> &&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; + void set_optimistic(bool optimistic); + void set_assumed_state(bool assumed_state); + void set_has_stop(bool has_stop); + void set_has_position(bool has_position); + void set_has_toggle(bool has_toggle); + void set_restore_mode(TemplateValveRestoreMode restore_mode) { restore_mode_ = restore_mode; } + + void setup() override; + void loop() override; + void dump_config() override; + + float get_setup_priority() const override; + + protected: + void control(const valve::ValveCall &call) override; + valve::ValveTraits get_traits() override; + void stop_prev_trigger_(); + + TemplateValveRestoreMode restore_mode_{VALVE_NO_RESTORE}; + optional()>> state_f_; + bool assumed_state_{false}; + bool optimistic_{false}; + Trigger<> *open_trigger_; + Trigger<> *close_trigger_; + bool has_stop_{false}; + bool has_toggle_{false}; + Trigger<> *stop_trigger_; + Trigger<> *toggle_trigger_; + Trigger<> *prev_command_trigger_{nullptr}; + Trigger *position_trigger_; + bool has_position_{false}; +}; + +} // namespace template_ +} // namespace esphome diff --git a/esphome/components/valve/__init__.py b/esphome/components/valve/__init__.py new file mode 100644 index 0000000000..22d617cc36 --- /dev/null +++ b/esphome/components/valve/__init__.py @@ -0,0 +1,186 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome import automation +from esphome.automation import maybe_simple_id, Condition +from esphome.components import mqtt +from esphome.const import ( + CONF_DEVICE_CLASS, + CONF_ID, + CONF_MQTT_ID, + CONF_ON_OPEN, + CONF_POSITION, + CONF_POSITION_COMMAND_TOPIC, + CONF_POSITION_STATE_TOPIC, + CONF_STATE, + CONF_STOP, + CONF_TRIGGER_ID, +) +from esphome.core import CORE, coroutine_with_priority +from esphome.cpp_helpers import setup_entity + +IS_PLATFORM_COMPONENT = True + +CODEOWNERS = ["@esphome/core"] + +valve_ns = cg.esphome_ns.namespace("valve") + +Valve = valve_ns.class_("Valve", cg.EntityBase) + +VALVE_OPEN = valve_ns.VALVE_OPEN +VALVE_CLOSED = valve_ns.VALVE_CLOSED + +VALVE_STATES = { + "OPEN": VALVE_OPEN, + "CLOSED": VALVE_CLOSED, +} +validate_valve_state = cv.enum(VALVE_STATES, upper=True) + +ValveOperation = valve_ns.enum("ValveOperation") +VALVE_OPERATIONS = { + "IDLE": ValveOperation.VALVE_OPERATION_IDLE, + "OPENING": ValveOperation.VALVE_OPERATION_OPENING, + "CLOSING": ValveOperation.VALVE_OPERATION_CLOSING, +} +validate_valve_operation = cv.enum(VALVE_OPERATIONS, upper=True) + +# Actions +OpenAction = valve_ns.class_("OpenAction", automation.Action) +CloseAction = valve_ns.class_("CloseAction", automation.Action) +StopAction = valve_ns.class_("StopAction", automation.Action) +ToggleAction = valve_ns.class_("ToggleAction", automation.Action) +ControlAction = valve_ns.class_("ControlAction", automation.Action) +ValvePublishAction = valve_ns.class_("ValvePublishAction", automation.Action) +ValveIsOpenCondition = valve_ns.class_("ValveIsOpenCondition", Condition) +ValveIsClosedCondition = valve_ns.class_("ValveIsClosedCondition", Condition) + +# Triggers +ValveOpenTrigger = valve_ns.class_("ValveOpenTrigger", automation.Trigger.template()) +ValveClosedTrigger = valve_ns.class_( + "ValveClosedTrigger", automation.Trigger.template() +) + +CONF_ON_CLOSED = "on_closed" + +VALVE_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA).extend( + { + cv.GenerateID(): cv.declare_id(Valve), + cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTValveComponent), + cv.Optional(CONF_POSITION_COMMAND_TOPIC): cv.All( + cv.requires_component("mqtt"), cv.subscribe_topic + ), + cv.Optional(CONF_POSITION_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(ValveOpenTrigger), + } + ), + cv.Optional(CONF_ON_CLOSED): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ValveClosedTrigger), + } + ), + } +) + + +async def setup_valve_core_(var, config): + await setup_entity(var, config) + + if device_class_config := config.get(CONF_DEVICE_CLASS): + cg.add(var.set_device_class(device_class_config)) + + 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 mqtt_id_config := config.get(CONF_MQTT_ID): + mqtt_ = cg.new_Pvariable(mqtt_id_config, var) + await mqtt.register_mqtt_component(mqtt_, config) + + if position_state_topic_config := config.get(CONF_POSITION_STATE_TOPIC): + cg.add(mqtt_.set_custom_position_state_topic(position_state_topic_config)) + if position_command_topic_config := config.get(CONF_POSITION_COMMAND_TOPIC): + cg.add( + mqtt_.set_custom_position_command_topic(position_command_topic_config) + ) + + +async def register_valve(var, config): + if not CORE.has_id(config[CONF_ID]): + var = cg.Pvariable(config[CONF_ID], var) + cg.add(cg.App.register_valve(var)) + await setup_valve_core_(var, config) + + +async def new_valve(config, *args): + var = cg.new_Pvariable(config[CONF_ID], *args) + await register_valve(var, config) + return var + + +VALVE_ACTION_SCHEMA = maybe_simple_id( + { + cv.Required(CONF_ID): cv.use_id(Valve), + } +) + + +@automation.register_action("valve.open", OpenAction, VALVE_ACTION_SCHEMA) +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) +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) +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) +def valve_toggle_to_code(config, action_id, template_arg, args): + paren = yield cg.get_variable(config[CONF_ID]) + yield cg.new_Pvariable(action_id, template_arg, paren) + + +VALVE_CONTROL_ACTION_SCHEMA = cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(Valve), + cv.Optional(CONF_STOP): cv.templatable(cv.boolean), + cv.Exclusive(CONF_STATE, "pos"): cv.templatable(validate_valve_state), + cv.Exclusive(CONF_POSITION, "pos"): cv.templatable(cv.percentage), + } +) + + +@automation.register_action("valve.control", ControlAction, VALVE_CONTROL_ACTION_SCHEMA) +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) + if stop_config := config.get(CONF_STOP): + template_ = await cg.templatable(stop_config, args, bool) + cg.add(var.set_stop(template_)) + if state_config := config.get(CONF_STATE): + template_ = await cg.templatable(state_config, args, float) + cg.add(var.set_position(template_)) + if (position_config := config.get(CONF_POSITION)) is not None: + template_ = await cg.templatable(position_config, args, float) + cg.add(var.set_position(template_)) + return var + + +@coroutine_with_priority(100.0) +async def to_code(config): + cg.add_define("USE_VALVE") + cg.add_global(valve_ns.using) diff --git a/esphome/components/valve/automation.h b/esphome/components/valve/automation.h new file mode 100644 index 0000000000..24c94a5570 --- /dev/null +++ b/esphome/components/valve/automation.h @@ -0,0 +1,129 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/core/automation.h" +#include "valve.h" + +namespace esphome { +namespace valve { + +template class OpenAction : public Action { + public: + explicit OpenAction(Valve *valve) : valve_(valve) {} + + void play(Ts... x) override { this->valve_->make_call().set_command_open().perform(); } + + protected: + Valve *valve_; +}; + +template class CloseAction : public Action { + public: + explicit CloseAction(Valve *valve) : valve_(valve) {} + + void play(Ts... x) override { this->valve_->make_call().set_command_close().perform(); } + + protected: + Valve *valve_; +}; + +template class StopAction : public Action { + public: + explicit StopAction(Valve *valve) : valve_(valve) {} + + void play(Ts... x) override { this->valve_->make_call().set_command_stop().perform(); } + + protected: + Valve *valve_; +}; + +template class ToggleAction : public Action { + public: + explicit ToggleAction(Valve *valve) : valve_(valve) {} + + void play(Ts... x) override { this->valve_->make_call().set_command_toggle().perform(); } + + protected: + Valve *valve_; +}; + +template class ControlAction : public Action { + public: + explicit ControlAction(Valve *valve) : valve_(valve) {} + + TEMPLATABLE_VALUE(bool, stop) + TEMPLATABLE_VALUE(float, position) + + void play(Ts... x) override { + auto call = this->valve_->make_call(); + if (this->stop_.has_value()) + call.set_stop(this->stop_.value(x...)); + if (this->position_.has_value()) + call.set_position(this->position_.value(x...)); + call.perform(); + } + + protected: + Valve *valve_; +}; + +template class ValvePublishAction : public Action { + public: + ValvePublishAction(Valve *valve) : valve_(valve) {} + TEMPLATABLE_VALUE(float, position) + TEMPLATABLE_VALUE(ValveOperation, current_operation) + + void play(Ts... x) override { + if (this->position_.has_value()) + this->valve_->position = this->position_.value(x...); + if (this->current_operation_.has_value()) + this->valve_->current_operation = this->current_operation_.value(x...); + this->valve_->publish_state(); + } + + protected: + Valve *valve_; +}; + +template class ValveIsOpenCondition : public Condition { + public: + ValveIsOpenCondition(Valve *valve) : valve_(valve) {} + bool check(Ts... x) override { return this->valve_->is_fully_open(); } + + protected: + Valve *valve_; +}; + +template class ValveIsClosedCondition : public Condition { + public: + ValveIsClosedCondition(Valve *valve) : valve_(valve) {} + bool check(Ts... x) override { return this->valve_->is_fully_closed(); } + + protected: + Valve *valve_; +}; + +class ValveOpenTrigger : public Trigger<> { + public: + ValveOpenTrigger(Valve *a_valve) { + a_valve->add_on_state_callback([this, a_valve]() { + if (a_valve->is_fully_open()) { + this->trigger(); + } + }); + } +}; + +class ValveClosedTrigger : public Trigger<> { + public: + ValveClosedTrigger(Valve *a_valve) { + a_valve->add_on_state_callback([this, a_valve]() { + if (a_valve->is_fully_closed()) { + this->trigger(); + } + }); + } +}; + +} // namespace valve +} // namespace esphome diff --git a/esphome/components/valve/valve.cpp b/esphome/components/valve/valve.cpp new file mode 100644 index 0000000000..d1ec17945a --- /dev/null +++ b/esphome/components/valve/valve.cpp @@ -0,0 +1,179 @@ +#include "valve.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace valve { + +static const char *const TAG = "valve"; + +const float VALVE_OPEN = 1.0f; +const float VALVE_CLOSED = 0.0f; + +const char *valve_command_to_str(float pos) { + if (pos == VALVE_OPEN) { + return "OPEN"; + } else if (pos == VALVE_CLOSED) { + return "CLOSE"; + } else { + return "UNKNOWN"; + } +} +const char *valve_operation_to_str(ValveOperation op) { + switch (op) { + case VALVE_OPERATION_IDLE: + return "IDLE"; + case VALVE_OPERATION_OPENING: + return "OPENING"; + case VALVE_OPERATION_CLOSING: + return "CLOSING"; + default: + return "UNKNOWN"; + } +} + +Valve::Valve() : position{VALVE_OPEN} {} + +ValveCall::ValveCall(Valve *parent) : parent_(parent) {} +ValveCall &ValveCall::set_command(const char *command) { + if (strcasecmp(command, "OPEN") == 0) { + this->set_command_open(); + } else if (strcasecmp(command, "CLOSE") == 0) { + this->set_command_close(); + } else if (strcasecmp(command, "STOP") == 0) { + this->set_command_stop(); + } else if (strcasecmp(command, "TOGGLE") == 0) { + this->set_command_toggle(); + } else { + ESP_LOGW(TAG, "'%s' - Unrecognized command %s", this->parent_->get_name().c_str(), command); + } + return *this; +} +ValveCall &ValveCall::set_command_open() { + this->position_ = VALVE_OPEN; + return *this; +} +ValveCall &ValveCall::set_command_close() { + this->position_ = VALVE_CLOSED; + return *this; +} +ValveCall &ValveCall::set_command_stop() { + this->stop_ = true; + return *this; +} +ValveCall &ValveCall::set_command_toggle() { + this->toggle_ = true; + return *this; +} +ValveCall &ValveCall::set_position(float position) { + this->position_ = position; + return *this; +} +void ValveCall::perform() { + ESP_LOGD(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"); + } + if (this->position_.has_value()) { + if (traits.get_supports_position()) { + ESP_LOGD(TAG, " Position: %.0f%%", *this->position_ * 100.0f); + } else { + ESP_LOGD(TAG, " Command: %s", valve_command_to_str(*this->position_)); + } + } + if (this->toggle_.has_value()) { + ESP_LOGD(TAG, " Command: TOGGLE"); + } + this->parent_->control(*this); +} +const optional &ValveCall::get_position() const { return this->position_; } +const optional &ValveCall::get_toggle() const { return this->toggle_; } +void ValveCall::validate_() { + auto traits = this->parent_->get_traits(); + if (this->position_.has_value()) { + auto pos = *this->position_; + if (!traits.get_supports_position() && pos != VALVE_OPEN && pos != VALVE_CLOSED) { + ESP_LOGW(TAG, "'%s' - This valve device does not support setting position!", this->parent_->get_name().c_str()); + this->position_.reset(); + } else if (pos < 0.0f || pos > 1.0f) { + ESP_LOGW(TAG, "'%s' - Position %.2f is out of range [0.0 - 1.0]", this->parent_->get_name().c_str(), pos); + this->position_ = clamp(pos, 0.0f, 1.0f); + } + } + if (this->toggle_.has_value()) { + if (!traits.get_supports_toggle()) { + ESP_LOGW(TAG, "'%s' - This valve device does not support toggle!", this->parent_->get_name().c_str()); + this->toggle_.reset(); + } + } + if (this->stop_) { + if (this->position_.has_value()) { + ESP_LOGW(TAG, "Cannot set position when stopping a valve!"); + this->position_.reset(); + } + if (this->toggle_.has_value()) { + ESP_LOGW(TAG, "Cannot set toggle when stopping a valve!"); + this->toggle_.reset(); + } + } +} +ValveCall &ValveCall::set_stop(bool stop) { + this->stop_ = stop; + return *this; +} +bool ValveCall::get_stop() const { return this->stop_; } + +ValveCall Valve::make_call() { return {this}; } + +void Valve::add_on_state_callback(std::function &&f) { this->state_callback_.add(std::move(f)); } +void Valve::publish_state(bool save) { + this->position = clamp(this->position, 0.0f, 1.0f); + + ESP_LOGD(TAG, "'%s' - Publishing:", this->name_.c_str()); + auto traits = this->get_traits(); + if (traits.get_supports_position()) { + ESP_LOGD(TAG, " Position: %.0f%%", this->position * 100.0f); + } else { + if (this->position == VALVE_OPEN) { + ESP_LOGD(TAG, " State: OPEN"); + } else if (this->position == VALVE_CLOSED) { + ESP_LOGD(TAG, " State: CLOSED"); + } else { + ESP_LOGD(TAG, " State: UNKNOWN"); + } + } + ESP_LOGD(TAG, " Current Operation: %s", valve_operation_to_str(this->current_operation)); + + this->state_callback_.call(); + + if (save) { + ValveRestoreState restore{}; + memset(&restore, 0, sizeof(restore)); + restore.position = this->position; + this->rtc_.save(&restore); + } +} +optional Valve::restore_state_() { + this->rtc_ = global_preferences->make_preference(this->get_object_id_hash()); + ValveRestoreState recovered{}; + if (!this->rtc_.load(&recovered)) + return {}; + return recovered; +} + +bool Valve::is_fully_open() const { return this->position == VALVE_OPEN; } +bool Valve::is_fully_closed() const { return this->position == VALVE_CLOSED; } + +ValveCall ValveRestoreState::to_call(Valve *valve) { + auto call = valve->make_call(); + call.set_position(this->position); + return call; +} +void ValveRestoreState::apply(Valve *valve) { + valve->position = this->position; + valve->publish_state(); +} + +} // namespace valve +} // namespace esphome diff --git a/esphome/components/valve/valve.h b/esphome/components/valve/valve.h new file mode 100644 index 0000000000..0e14a8d8f0 --- /dev/null +++ b/esphome/components/valve/valve.h @@ -0,0 +1,152 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/core/entity_base.h" +#include "esphome/core/helpers.h" +#include "esphome/core/preferences.h" +#include "valve_traits.h" + +namespace esphome { +namespace valve { + +const extern float VALVE_OPEN; +const extern float VALVE_CLOSED; + +#define LOG_VALVE(prefix, type, obj) \ + if ((obj) != nullptr) { \ + ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \ + auto traits_ = (obj)->get_traits(); \ + if (traits_.get_is_assumed_state()) { \ + ESP_LOGCONFIG(TAG, "%s Assumed State: YES", prefix); \ + } \ + if (!(obj)->get_device_class().empty()) { \ + ESP_LOGCONFIG(TAG, "%s Device Class: '%s'", prefix, (obj)->get_device_class().c_str()); \ + } \ + } + +class Valve; + +class ValveCall { + public: + ValveCall(Valve *parent); + + /// Set the command as a string, "STOP", "OPEN", "CLOSE", "TOGGLE". + ValveCall &set_command(const char *command); + /// Set the command to open the valve. + ValveCall &set_command_open(); + /// Set the command to close the valve. + ValveCall &set_command_close(); + /// Set the command to stop the valve. + ValveCall &set_command_stop(); + /// Set the command to toggle the valve. + ValveCall &set_command_toggle(); + /// Set the call to a certain target position. + ValveCall &set_position(float position); + /// Set whether this valve call should stop the valve. + ValveCall &set_stop(bool stop); + + /// Perform the valve call. + void perform(); + + const optional &get_position() const; + bool get_stop() const; + const optional &get_toggle() const; + + protected: + void validate_(); + + Valve *parent_; + bool stop_{false}; + optional position_{}; + optional toggle_{}; +}; + +/// Struct used to store the restored state of a valve +struct ValveRestoreState { + float position; + + /// Convert this struct to a valve call that can be performed. + ValveCall to_call(Valve *valve); + /// Apply these settings to the valve + void apply(Valve *valve); +} __attribute__((packed)); + +/// Enum encoding the current operation of a valve. +enum ValveOperation : uint8_t { + /// The valve is currently idle (not moving) + VALVE_OPERATION_IDLE = 0, + /// The valve is currently opening. + VALVE_OPERATION_OPENING, + /// The valve is currently closing. + VALVE_OPERATION_CLOSING, +}; + +const char *valve_operation_to_str(ValveOperation op); + +/** Base class for all valve devices. + * + * Valves currently have three properties: + * - position - The current position of the valve from 0.0 (fully closed) to 1.0 (fully open). + * For valves with only binary OPEN/CLOSED position this will always be either 0.0 or 1.0 + * - current_operation - The operation the valve is currently performing, this can + * be one of IDLE, OPENING and CLOSING. + * + * For users: All valve operations must be performed over the .make_call() interface. + * To command a valve, use .make_call() to create a call object, set all properties + * you wish to set, and activate the command with .perform(). + * For reading out the current values of the valve, use the public .position, etc. + * properties (these are read-only for users) + * + * For integrations: Integrations must implement two methods: control() and get_traits(). + * Control will be called with the arguments supplied by the user and should be used + * 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 { + public: + explicit Valve(); + + /// The current operation of the valve (idle, opening, closing). + ValveOperation current_operation{VALVE_OPERATION_IDLE}; + /** The position of the valve from 0.0 (fully closed) to 1.0 (fully open). + * + * For binary valves this is always equals to 0.0 or 1.0 (see also VALVE_OPEN and + * VALVE_CLOSED constants). + */ + float position; + + /// Construct a new valve call used to control the valve. + ValveCall make_call(); + + void add_on_state_callback(std::function &&f); + + /** Publish the current state of the valve. + * + * First set the .position, etc. values and then call this method + * to publish the state of the valve. + * + * @param save Whether to save the updated values in RTC area. + */ + void publish_state(bool save = true); + + virtual ValveTraits get_traits() = 0; + + /// Helper method to check if the valve is fully open. Equivalent to comparing .position against 1.0 + bool is_fully_open() const; + /// Helper method to check if the valve is fully closed. Equivalent to comparing .position against 0.0 + bool is_fully_closed() const; + + protected: + friend ValveCall; + + virtual void control(const ValveCall &call) = 0; + + optional restore_state_(); + + CallbackManager state_callback_{}; + + ESPPreferenceObject rtc_; +}; + +} // namespace valve +} // namespace esphome diff --git a/esphome/components/valve/valve_traits.h b/esphome/components/valve/valve_traits.h new file mode 100644 index 0000000000..7e9aab2f26 --- /dev/null +++ b/esphome/components/valve/valve_traits.h @@ -0,0 +1,27 @@ +#pragma once + +namespace esphome { +namespace valve { + +class ValveTraits { + public: + ValveTraits() = default; + + bool get_is_assumed_state() const { return this->is_assumed_state_; } + void set_is_assumed_state(bool is_assumed_state) { this->is_assumed_state_ = is_assumed_state; } + bool get_supports_position() const { return this->supports_position_; } + void set_supports_position(bool supports_position) { this->supports_position_ = supports_position; } + bool get_supports_toggle() const { return this->supports_toggle_; } + void set_supports_toggle(bool supports_toggle) { this->supports_toggle_ = supports_toggle; } + bool get_supports_stop() const { return this->supports_stop_; } + void set_supports_stop(bool supports_stop) { this->supports_stop_ = supports_stop; } + + protected: + bool is_assumed_state_{false}; + bool supports_position_{false}; + bool supports_toggle_{false}; + bool supports_stop_{false}; +}; + +} // namespace valve +} // namespace esphome diff --git a/esphome/components/web_server/list_entities.cpp b/esphome/components/web_server/list_entities.cpp index dd9fd4afe4..13e396dc82 100644 --- a/esphome/components/web_server/list_entities.cpp +++ b/esphome/components/web_server/list_entities.cpp @@ -86,6 +86,15 @@ bool ListEntitiesIterator::on_lock(lock::Lock *a_lock) { } #endif +#ifdef USE_VALVE +bool ListEntitiesIterator::on_valve(valve::Valve *valve) { + if (this->web_server_->events_.count() == 0) + return true; + this->web_server_->events_.send(this->web_server_->valve_json(valve, DETAIL_ALL).c_str(), "state"); + return true; +} +#endif + #ifdef USE_CLIMATE bool ListEntitiesIterator::on_climate(climate::Climate *climate) { if (this->web_server_->events_.count() == 0) diff --git a/esphome/components/web_server/list_entities.h b/esphome/components/web_server/list_entities.h index fc48186b32..d0b8dda233 100644 --- a/esphome/components/web_server/list_entities.h +++ b/esphome/components/web_server/list_entities.h @@ -56,6 +56,9 @@ class ListEntitiesIterator : public ComponentIterator { #ifdef USE_LOCK bool on_lock(lock::Lock *a_lock) override; #endif +#ifdef USE_VALVE + bool on_valve(valve::Valve *valve) override; +#endif #ifdef USE_ALARM_CONTROL_PANEL bool on_alarm_control_panel(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel) override; #endif diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index 2e6206b691..412f8816ee 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -1260,6 +1260,68 @@ void WebServer::handle_lock_request(AsyncWebServerRequest *request, const UrlMat } #endif +#ifdef USE_VALVE +void WebServer::on_valve_update(valve::Valve *obj) { + if (this->events_.count() == 0) + return; + this->events_.send(this->valve_json(obj, DETAIL_STATE).c_str(), "state"); +} +void WebServer::handle_valve_request(AsyncWebServerRequest *request, const UrlMatch &match) { + for (valve::Valve *obj : App.get_valves()) { + if (obj->get_object_id() != match.id) + continue; + + if (request->method() == HTTP_GET && match.method.empty()) { + std::string data = this->valve_json(obj, DETAIL_STATE); + request->send(200, "application/json", data.c_str()); + continue; + } + + auto call = obj->make_call(); + if (match.method == "open") { + call.set_command_open(); + } else if (match.method == "close") { + call.set_command_close(); + } else if (match.method == "stop") { + call.set_command_stop(); + } else if (match.method == "toggle") { + call.set_command_toggle(); + } else if (match.method != "set") { + request->send(404); + return; + } + + auto traits = obj->get_traits(); + if (request->hasParam("position") && !traits.get_supports_position()) { + request->send(409); + return; + } + + if (request->hasParam("position")) { + auto position = parse_number(request->getParam("position")->value().c_str()); + if (position.has_value()) { + call.set_position(*position); + } + } + + this->schedule_([call]() mutable { call.perform(); }); + request->send(200); + return; + } + request->send(404); +} +std::string WebServer::valve_json(valve::Valve *obj, JsonDetail start_config) { + return json::build_json([obj, start_config](JsonObject root) { + set_json_icon_state_value(root, obj, "valve-" + obj->get_object_id(), obj->is_fully_closed() ? "CLOSED" : "OPEN", + obj->position, start_config); + root["current_operation"] = valve::valve_operation_to_str(obj->current_operation); + + if (obj->get_traits().get_supports_position()) + root["position"] = obj->position; + }); +} +#endif + #ifdef USE_ALARM_CONTROL_PANEL void WebServer::on_alarm_control_panel_update(alarm_control_panel::AlarmControlPanel *obj) { if (this->events_.count() == 0) @@ -1394,6 +1456,11 @@ bool WebServer::canHandle(AsyncWebServerRequest *request) { return true; #endif +#ifdef USE_VALVE + if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain == "valve") + return true; +#endif + #ifdef USE_ALARM_CONTROL_PANEL if (request->method() == HTTP_GET && match.domain == "alarm_control_panel") return true; @@ -1535,6 +1602,13 @@ void WebServer::handleRequest(AsyncWebServerRequest *request) { } #endif +#ifdef USE_VALVE + if (match.domain == "valve") { + this->handle_valve_request(request, match); + return; + } +#endif + #ifdef USE_ALARM_CONTROL_PANEL if (match.domain == "alarm_control_panel") { this->handle_alarm_control_panel_request(request, match); diff --git a/esphome/components/web_server/web_server.h b/esphome/components/web_server/web_server.h index 1935f8d076..9f807efc43 100644 --- a/esphome/components/web_server/web_server.h +++ b/esphome/components/web_server/web_server.h @@ -276,6 +276,16 @@ class WebServer : public Controller, public Component, public AsyncWebHandler { std::string lock_json(lock::Lock *obj, lock::LockState value, JsonDetail start_config); #endif +#ifdef USE_VALVE + void on_valve_update(valve::Valve *obj) override; + + /// Handle a valve request under '/valve//'. + void handle_valve_request(AsyncWebServerRequest *request, const UrlMatch &match); + + /// Dump the valve state as a JSON string. + std::string valve_json(valve::Valve *obj, JsonDetail start_config); +#endif + #ifdef USE_ALARM_CONTROL_PANEL void on_alarm_control_panel_update(alarm_control_panel::AlarmControlPanel *obj) override; diff --git a/esphome/core/application.h b/esphome/core/application.h index 73330d27e3..ee931282a6 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -54,6 +54,9 @@ #ifdef USE_LOCK #include "esphome/components/lock/lock.h" #endif +#ifdef USE_VALVE +#include "esphome/components/valve/valve.h" +#endif #ifdef USE_MEDIA_PLAYER #include "esphome/components/media_player/media_player.h" #endif @@ -147,6 +150,10 @@ class Application { void register_lock(lock::Lock *a_lock) { this->locks_.push_back(a_lock); } #endif +#ifdef USE_VALVE + void register_valve(valve::Valve *valve) { this->valves_.push_back(valve); } +#endif + #ifdef USE_MEDIA_PLAYER void register_media_player(media_player::MediaPlayer *media_player) { this->media_players_.push_back(media_player); } #endif @@ -348,6 +355,15 @@ class Application { return nullptr; } #endif +#ifdef USE_VALVE + const std::vector &get_valves() { return this->valves_; } + valve::Valve *get_valve_by_key(uint32_t key, bool include_internal = false) { + for (auto *obj : this->valves_) + if (obj->get_object_id_hash() == key && (include_internal || !obj->is_internal())) + return obj; + return nullptr; + } +#endif #ifdef USE_MEDIA_PLAYER const std::vector &get_media_players() { return this->media_players_; } media_player::MediaPlayer *get_media_player_by_key(uint32_t key, bool include_internal = false) { @@ -429,6 +445,9 @@ class Application { #ifdef USE_LOCK std::vector locks_{}; #endif +#ifdef USE_VALVE + std::vector valves_{}; +#endif #ifdef USE_MEDIA_PLAYER std::vector media_players_{}; #endif diff --git a/esphome/core/component_iterator.cpp b/esphome/core/component_iterator.cpp index 228cf64d54..b00154c685 100644 --- a/esphome/core/component_iterator.cpp +++ b/esphome/core/component_iterator.cpp @@ -277,6 +277,21 @@ void ComponentIterator::advance() { } break; #endif +#ifdef USE_VALVE + case IteratorState::VALVE: + if (this->at_ >= App.get_valves().size()) { + advance_platform = true; + } else { + auto *valve = App.get_valves()[this->at_]; + if (valve->is_internal() && !this->include_internal_) { + success = true; + break; + } else { + success = this->on_valve(valve); + } + } + break; +#endif #ifdef USE_MEDIA_PLAYER case IteratorState::MEDIA_PLAYER: if (this->at_ >= App.get_media_players().size()) { diff --git a/esphome/core/component_iterator.h b/esphome/core/component_iterator.h index d7f19f2850..3fbbc0bc19 100644 --- a/esphome/core/component_iterator.h +++ b/esphome/core/component_iterator.h @@ -72,6 +72,9 @@ class ComponentIterator { #ifdef USE_LOCK virtual bool on_lock(lock::Lock *a_lock) = 0; #endif +#ifdef USE_VALVE + virtual bool on_valve(valve::Valve *valve) = 0; +#endif #ifdef USE_MEDIA_PLAYER virtual bool on_media_player(media_player::MediaPlayer *media_player); #endif @@ -135,6 +138,9 @@ class ComponentIterator { #ifdef USE_LOCK LOCK, #endif +#ifdef USE_VALVE + VALVE, +#endif #ifdef USE_MEDIA_PLAYER MEDIA_PLAYER, #endif diff --git a/esphome/core/controller.cpp b/esphome/core/controller.cpp index db5818d455..eab818bdb4 100644 --- a/esphome/core/controller.cpp +++ b/esphome/core/controller.cpp @@ -91,6 +91,12 @@ void Controller::setup_controller(bool include_internal) { obj->add_on_state_callback([this, obj]() { this->on_lock_update(obj); }); } #endif +#ifdef USE_VALVE + for (auto *obj : App.get_valves()) { + if (include_internal || !obj->is_internal()) + obj->add_on_state_callback([this, obj]() { this->on_valve_update(obj); }); + } +#endif #ifdef USE_MEDIA_PLAYER for (auto *obj : App.get_media_players()) { if (include_internal || !obj->is_internal()) diff --git a/esphome/core/controller.h b/esphome/core/controller.h index 9b1cfd93c6..94a4acb7c7 100644 --- a/esphome/core/controller.h +++ b/esphome/core/controller.h @@ -46,6 +46,9 @@ #ifdef USE_LOCK #include "esphome/components/lock/lock.h" #endif +#ifdef USE_VALVE +#include "esphome/components/valve/valve.h" +#endif #ifdef USE_MEDIA_PLAYER #include "esphome/components/media_player/media_player.h" #endif @@ -100,6 +103,9 @@ class Controller { #ifdef USE_LOCK virtual void on_lock_update(lock::Lock *obj){}; #endif +#ifdef USE_VALVE + virtual void on_valve_update(valve::Valve *obj){}; +#endif #ifdef USE_MEDIA_PLAYER virtual void on_media_player_update(media_player::MediaPlayer *obj){}; #endif diff --git a/esphome/core/defines.h b/esphome/core/defines.h index f13ae968f0..2064ca1356 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -54,6 +54,7 @@ #define USE_TIME #define USE_TOUCHSCREEN #define USE_UART_DEBUGGER +#define USE_VALVE #define USE_WIFI #define USE_WIFI_AP #define USE_GRAPHICAL_DISPLAY_MENU diff --git a/script/ci-custom.py b/script/ci-custom.py index c3cfc7a331..c591bfe5c3 100755 --- a/script/ci-custom.py +++ b/script/ci-custom.py @@ -638,6 +638,7 @@ def lint_trailing_whitespace(fname, match): "esphome/components/stepper/stepper.h", "esphome/components/switch/switch.h", "esphome/components/text_sensor/text_sensor.h", + "esphome/components/valve/valve.h", "esphome/core/component.h", "esphome/core/gpio.h", "esphome/core/log.h", diff --git a/tests/components/template/test.all.yaml b/tests/components/template/test.all.yaml index 29dc83b649..64faec36c2 100644 --- a/tests/components/template/test.all.yaml +++ b/tests/components/template/test.all.yaml @@ -125,6 +125,23 @@ lock: open_action: - logger.log: open_action +valve: + - platform: template + name: "Template Valve" + lambda: |- + if (id(some_binary_sensor).state) { + return VALVE_OPEN; + } else { + return VALVE_CLOSED; + } + open_action: + - logger.log: open_action + close_action: + - logger.log: close_action + stop_action: + - logger.log: stop_action + optimistic: true + text: - platform: template name: "Template text" From 7e5b100b7778ba451d2ebda597ca7c4dc37ac3c1 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Mon, 22 Apr 2024 23:53:13 -0500 Subject: [PATCH 1307/2101] Add some components to the new testing framework (R) (#6219) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- .../radon_eye_ble/test.esp32-c3-idf.yaml | 3 ++ .../radon_eye_ble/test.esp32-c3.yaml | 3 ++ .../radon_eye_ble/test.esp32-idf.yaml | 3 ++ .../components/radon_eye_ble/test.esp32.yaml | 3 ++ .../radon_eye_rd200/test.esp32-c3-idf.yaml | 14 ++++++++ .../radon_eye_rd200/test.esp32-c3.yaml | 14 ++++++++ .../radon_eye_rd200/test.esp32-idf.yaml | 14 ++++++++ .../radon_eye_rd200/test.esp32.yaml | 14 ++++++++ .../rc522_i2c/test.esp32-c3-idf.yaml | 17 +++++++++ tests/components/rc522_i2c/test.esp32-c3.yaml | 17 +++++++++ .../components/rc522_i2c/test.esp32-idf.yaml | 17 +++++++++ tests/components/rc522_i2c/test.esp32.yaml | 17 +++++++++ tests/components/rc522_i2c/test.esp8266.yaml | 17 +++++++++ tests/components/rc522_i2c/test.rp2040.yaml | 17 +++++++++ .../rc522_spi/test.esp32-c3-idf.yaml | 15 ++++++++ tests/components/rc522_spi/test.esp32-c3.yaml | 15 ++++++++ .../components/rc522_spi/test.esp32-idf.yaml | 15 ++++++++ tests/components/rc522_spi/test.esp32.yaml | 15 ++++++++ tests/components/rc522_spi/test.esp8266.yaml | 15 ++++++++ tests/components/rc522_spi/test.rp2040.yaml | 15 ++++++++ .../components/rdm6300/test.esp32-c3-idf.yaml | 12 +++++++ tests/components/rdm6300/test.esp32-c3.yaml | 12 +++++++ tests/components/rdm6300/test.esp32-idf.yaml | 12 +++++++ tests/components/rdm6300/test.esp32.yaml | 12 +++++++ tests/components/rdm6300/test.esp8266.yaml | 12 +++++++ tests/components/rdm6300/test.rp2040.yaml | 12 +++++++ .../components/resistance/test.esp32-c3.yaml | 12 +++++++ .../components/resistance/test.esp32-idf.yaml | 12 +++++++ .../components/resistance/test.esp32-s2.yaml | 12 +++++++ .../components/resistance/test.esp32-s3.yaml | 12 +++++++ tests/components/resistance/test.esp32.yaml | 12 +++++++ tests/components/resistance/test.esp8266.yaml | 11 ++++++ tests/components/resistance/test.rp2040.yaml | 12 +++++++ .../components/restart/test.esp32-c3-idf.yaml | 7 ++++ tests/components/restart/test.esp32-c3.yaml | 7 ++++ tests/components/restart/test.esp32-idf.yaml | 7 ++++ tests/components/restart/test.esp32.yaml | 7 ++++ tests/components/restart/test.esp8266.yaml | 7 ++++ tests/components/restart/test.rp2040.yaml | 7 ++++ .../rf_bridge/test.esp32-c3-idf.yaml | 35 +++++++++++++++++++ tests/components/rf_bridge/test.esp32-c3.yaml | 35 +++++++++++++++++++ .../components/rf_bridge/test.esp32-idf.yaml | 35 +++++++++++++++++++ tests/components/rf_bridge/test.esp32.yaml | 35 +++++++++++++++++++ tests/components/rf_bridge/test.esp8266.yaml | 35 +++++++++++++++++++ tests/components/rf_bridge/test.rp2040.yaml | 35 +++++++++++++++++++ tests/components/rgb/test.esp32-c3-idf.yaml | 18 ++++++++++ tests/components/rgb/test.esp32-c3.yaml | 18 ++++++++++ tests/components/rgb/test.esp32-idf.yaml | 18 ++++++++++ tests/components/rgb/test.esp32.yaml | 18 ++++++++++ tests/components/rgb/test.esp8266.yaml | 18 ++++++++++ tests/components/rgb/test.rp2040.yaml | 18 ++++++++++ tests/components/rgbct/test.esp32-c3-idf.yaml | 28 +++++++++++++++ tests/components/rgbct/test.esp32-c3.yaml | 28 +++++++++++++++ tests/components/rgbct/test.esp32-idf.yaml | 28 +++++++++++++++ tests/components/rgbct/test.esp32.yaml | 28 +++++++++++++++ tests/components/rgbct/test.esp8266.yaml | 28 +++++++++++++++ tests/components/rgbct/test.rp2040.yaml | 28 +++++++++++++++ tests/components/rgbw/test.esp32-c3-idf.yaml | 22 ++++++++++++ tests/components/rgbw/test.esp32-c3.yaml | 22 ++++++++++++ tests/components/rgbw/test.esp32-idf.yaml | 22 ++++++++++++ tests/components/rgbw/test.esp32.yaml | 22 ++++++++++++ tests/components/rgbw/test.esp8266.yaml | 22 ++++++++++++ tests/components/rgbw/test.rp2040.yaml | 22 ++++++++++++ tests/components/rgbww/test.esp32-c3-idf.yaml | 28 +++++++++++++++ tests/components/rgbww/test.esp32-c3.yaml | 28 +++++++++++++++ tests/components/rgbww/test.esp32-idf.yaml | 28 +++++++++++++++ tests/components/rgbww/test.esp32.yaml | 28 +++++++++++++++ tests/components/rgbww/test.esp8266.yaml | 28 +++++++++++++++ tests/components/rgbww/test.rp2040.yaml | 28 +++++++++++++++ .../rotary_encoder/test.esp32-c3-idf.yaml | 25 +++++++++++++ .../rotary_encoder/test.esp32-c3.yaml | 25 +++++++++++++ .../rotary_encoder/test.esp32-idf.yaml | 25 +++++++++++++ .../components/rotary_encoder/test.esp32.yaml | 25 +++++++++++++ .../rotary_encoder/test.esp8266.yaml | 25 +++++++++++++ .../rotary_encoder/test.rp2040.yaml | 25 +++++++++++++ .../rp2040_pio_led_strip/test.rp2040.yaml | 18 ++++++++++ tests/components/rp2040_pwm/test.rp2040.yaml | 7 ++++ tests/components/rtttl/test.esp32-c3-idf.yaml | 16 +++++++++ tests/components/rtttl/test.esp32-c3.yaml | 16 +++++++++ tests/components/rtttl/test.esp32-idf.yaml | 16 +++++++++ tests/components/rtttl/test.esp32.yaml | 16 +++++++++ tests/components/rtttl/test.esp8266.yaml | 15 ++++++++ tests/components/rtttl/test.rp2040.yaml | 15 ++++++++ .../ruuvi_ble/test.esp32-c3-idf.yaml | 3 ++ tests/components/ruuvi_ble/test.esp32-c3.yaml | 3 ++ .../components/ruuvi_ble/test.esp32-idf.yaml | 3 ++ tests/components/ruuvi_ble/test.esp32.yaml | 3 ++ .../ruuvitag/test.esp32-c3-idf.yaml | 27 ++++++++++++++ tests/components/ruuvitag/test.esp32-c3.yaml | 27 ++++++++++++++ tests/components/ruuvitag/test.esp32-idf.yaml | 27 ++++++++++++++ tests/components/ruuvitag/test.esp32.yaml | 27 ++++++++++++++ 91 files changed, 1632 insertions(+) create mode 100644 tests/components/radon_eye_ble/test.esp32-c3-idf.yaml create mode 100644 tests/components/radon_eye_ble/test.esp32-c3.yaml create mode 100644 tests/components/radon_eye_ble/test.esp32-idf.yaml create mode 100644 tests/components/radon_eye_ble/test.esp32.yaml create mode 100644 tests/components/radon_eye_rd200/test.esp32-c3-idf.yaml create mode 100644 tests/components/radon_eye_rd200/test.esp32-c3.yaml create mode 100644 tests/components/radon_eye_rd200/test.esp32-idf.yaml create mode 100644 tests/components/radon_eye_rd200/test.esp32.yaml create mode 100644 tests/components/rc522_i2c/test.esp32-c3-idf.yaml create mode 100644 tests/components/rc522_i2c/test.esp32-c3.yaml create mode 100644 tests/components/rc522_i2c/test.esp32-idf.yaml create mode 100644 tests/components/rc522_i2c/test.esp32.yaml create mode 100644 tests/components/rc522_i2c/test.esp8266.yaml create mode 100644 tests/components/rc522_i2c/test.rp2040.yaml create mode 100644 tests/components/rc522_spi/test.esp32-c3-idf.yaml create mode 100644 tests/components/rc522_spi/test.esp32-c3.yaml create mode 100644 tests/components/rc522_spi/test.esp32-idf.yaml create mode 100644 tests/components/rc522_spi/test.esp32.yaml create mode 100644 tests/components/rc522_spi/test.esp8266.yaml create mode 100644 tests/components/rc522_spi/test.rp2040.yaml create mode 100644 tests/components/rdm6300/test.esp32-c3-idf.yaml create mode 100644 tests/components/rdm6300/test.esp32-c3.yaml create mode 100644 tests/components/rdm6300/test.esp32-idf.yaml create mode 100644 tests/components/rdm6300/test.esp32.yaml create mode 100644 tests/components/rdm6300/test.esp8266.yaml create mode 100644 tests/components/rdm6300/test.rp2040.yaml create mode 100644 tests/components/resistance/test.esp32-c3.yaml create mode 100644 tests/components/resistance/test.esp32-idf.yaml create mode 100644 tests/components/resistance/test.esp32-s2.yaml create mode 100644 tests/components/resistance/test.esp32-s3.yaml create mode 100644 tests/components/resistance/test.esp32.yaml create mode 100644 tests/components/resistance/test.esp8266.yaml create mode 100644 tests/components/resistance/test.rp2040.yaml create mode 100644 tests/components/restart/test.esp32-c3-idf.yaml create mode 100644 tests/components/restart/test.esp32-c3.yaml create mode 100644 tests/components/restart/test.esp32-idf.yaml create mode 100644 tests/components/restart/test.esp32.yaml create mode 100644 tests/components/restart/test.esp8266.yaml create mode 100644 tests/components/restart/test.rp2040.yaml create mode 100644 tests/components/rf_bridge/test.esp32-c3-idf.yaml create mode 100644 tests/components/rf_bridge/test.esp32-c3.yaml create mode 100644 tests/components/rf_bridge/test.esp32-idf.yaml create mode 100644 tests/components/rf_bridge/test.esp32.yaml create mode 100644 tests/components/rf_bridge/test.esp8266.yaml create mode 100644 tests/components/rf_bridge/test.rp2040.yaml create mode 100644 tests/components/rgb/test.esp32-c3-idf.yaml create mode 100644 tests/components/rgb/test.esp32-c3.yaml create mode 100644 tests/components/rgb/test.esp32-idf.yaml create mode 100644 tests/components/rgb/test.esp32.yaml create mode 100644 tests/components/rgb/test.esp8266.yaml create mode 100644 tests/components/rgb/test.rp2040.yaml create mode 100644 tests/components/rgbct/test.esp32-c3-idf.yaml create mode 100644 tests/components/rgbct/test.esp32-c3.yaml create mode 100644 tests/components/rgbct/test.esp32-idf.yaml create mode 100644 tests/components/rgbct/test.esp32.yaml create mode 100644 tests/components/rgbct/test.esp8266.yaml create mode 100644 tests/components/rgbct/test.rp2040.yaml create mode 100644 tests/components/rgbw/test.esp32-c3-idf.yaml create mode 100644 tests/components/rgbw/test.esp32-c3.yaml create mode 100644 tests/components/rgbw/test.esp32-idf.yaml create mode 100644 tests/components/rgbw/test.esp32.yaml create mode 100644 tests/components/rgbw/test.esp8266.yaml create mode 100644 tests/components/rgbw/test.rp2040.yaml create mode 100644 tests/components/rgbww/test.esp32-c3-idf.yaml create mode 100644 tests/components/rgbww/test.esp32-c3.yaml create mode 100644 tests/components/rgbww/test.esp32-idf.yaml create mode 100644 tests/components/rgbww/test.esp32.yaml create mode 100644 tests/components/rgbww/test.esp8266.yaml create mode 100644 tests/components/rgbww/test.rp2040.yaml create mode 100644 tests/components/rotary_encoder/test.esp32-c3-idf.yaml create mode 100644 tests/components/rotary_encoder/test.esp32-c3.yaml create mode 100644 tests/components/rotary_encoder/test.esp32-idf.yaml create mode 100644 tests/components/rotary_encoder/test.esp32.yaml create mode 100644 tests/components/rotary_encoder/test.esp8266.yaml create mode 100644 tests/components/rotary_encoder/test.rp2040.yaml create mode 100644 tests/components/rp2040_pio_led_strip/test.rp2040.yaml create mode 100644 tests/components/rp2040_pwm/test.rp2040.yaml create mode 100644 tests/components/rtttl/test.esp32-c3-idf.yaml create mode 100644 tests/components/rtttl/test.esp32-c3.yaml create mode 100644 tests/components/rtttl/test.esp32-idf.yaml create mode 100644 tests/components/rtttl/test.esp32.yaml create mode 100644 tests/components/rtttl/test.esp8266.yaml create mode 100644 tests/components/rtttl/test.rp2040.yaml create mode 100644 tests/components/ruuvi_ble/test.esp32-c3-idf.yaml create mode 100644 tests/components/ruuvi_ble/test.esp32-c3.yaml create mode 100644 tests/components/ruuvi_ble/test.esp32-idf.yaml create mode 100644 tests/components/ruuvi_ble/test.esp32.yaml create mode 100644 tests/components/ruuvitag/test.esp32-c3-idf.yaml create mode 100644 tests/components/ruuvitag/test.esp32-c3.yaml create mode 100644 tests/components/ruuvitag/test.esp32-idf.yaml create mode 100644 tests/components/ruuvitag/test.esp32.yaml diff --git a/tests/components/radon_eye_ble/test.esp32-c3-idf.yaml b/tests/components/radon_eye_ble/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..85638d5c0e --- /dev/null +++ b/tests/components/radon_eye_ble/test.esp32-c3-idf.yaml @@ -0,0 +1,3 @@ +esp32_ble_tracker: + +radon_eye_ble: diff --git a/tests/components/radon_eye_ble/test.esp32-c3.yaml b/tests/components/radon_eye_ble/test.esp32-c3.yaml new file mode 100644 index 0000000000..85638d5c0e --- /dev/null +++ b/tests/components/radon_eye_ble/test.esp32-c3.yaml @@ -0,0 +1,3 @@ +esp32_ble_tracker: + +radon_eye_ble: diff --git a/tests/components/radon_eye_ble/test.esp32-idf.yaml b/tests/components/radon_eye_ble/test.esp32-idf.yaml new file mode 100644 index 0000000000..85638d5c0e --- /dev/null +++ b/tests/components/radon_eye_ble/test.esp32-idf.yaml @@ -0,0 +1,3 @@ +esp32_ble_tracker: + +radon_eye_ble: diff --git a/tests/components/radon_eye_ble/test.esp32.yaml b/tests/components/radon_eye_ble/test.esp32.yaml new file mode 100644 index 0000000000..85638d5c0e --- /dev/null +++ b/tests/components/radon_eye_ble/test.esp32.yaml @@ -0,0 +1,3 @@ +esp32_ble_tracker: + +radon_eye_ble: diff --git a/tests/components/radon_eye_rd200/test.esp32-c3-idf.yaml b/tests/components/radon_eye_rd200/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..d06979be6f --- /dev/null +++ b/tests/components/radon_eye_rd200/test.esp32-c3-idf.yaml @@ -0,0 +1,14 @@ +esp32_ble_tracker: + +ble_client: + - mac_address: 01:02:03:04:05:06 + id: radon_eye_blec + +sensor: + - platform: radon_eye_rd200 + ble_client_id: radon_eye_blec + radon: + name: RD200 Radon + radon_long_term: + name: RD200 Radon Long Term + update_interval: 10min diff --git a/tests/components/radon_eye_rd200/test.esp32-c3.yaml b/tests/components/radon_eye_rd200/test.esp32-c3.yaml new file mode 100644 index 0000000000..d06979be6f --- /dev/null +++ b/tests/components/radon_eye_rd200/test.esp32-c3.yaml @@ -0,0 +1,14 @@ +esp32_ble_tracker: + +ble_client: + - mac_address: 01:02:03:04:05:06 + id: radon_eye_blec + +sensor: + - platform: radon_eye_rd200 + ble_client_id: radon_eye_blec + radon: + name: RD200 Radon + radon_long_term: + name: RD200 Radon Long Term + update_interval: 10min diff --git a/tests/components/radon_eye_rd200/test.esp32-idf.yaml b/tests/components/radon_eye_rd200/test.esp32-idf.yaml new file mode 100644 index 0000000000..d06979be6f --- /dev/null +++ b/tests/components/radon_eye_rd200/test.esp32-idf.yaml @@ -0,0 +1,14 @@ +esp32_ble_tracker: + +ble_client: + - mac_address: 01:02:03:04:05:06 + id: radon_eye_blec + +sensor: + - platform: radon_eye_rd200 + ble_client_id: radon_eye_blec + radon: + name: RD200 Radon + radon_long_term: + name: RD200 Radon Long Term + update_interval: 10min diff --git a/tests/components/radon_eye_rd200/test.esp32.yaml b/tests/components/radon_eye_rd200/test.esp32.yaml new file mode 100644 index 0000000000..d06979be6f --- /dev/null +++ b/tests/components/radon_eye_rd200/test.esp32.yaml @@ -0,0 +1,14 @@ +esp32_ble_tracker: + +ble_client: + - mac_address: 01:02:03:04:05:06 + id: radon_eye_blec + +sensor: + - platform: radon_eye_rd200 + ble_client_id: radon_eye_blec + radon: + name: RD200 Radon + radon_long_term: + name: RD200 Radon Long Term + update_interval: 10min diff --git a/tests/components/rc522_i2c/test.esp32-c3-idf.yaml b/tests/components/rc522_i2c/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..8c8819e257 --- /dev/null +++ b/tests/components/rc522_i2c/test.esp32-c3-idf.yaml @@ -0,0 +1,17 @@ +i2c: + - id: i2c_rc522 + scl: 5 + sda: 4 + +rc522_i2c: + - id: rc522_nfcc + update_interval: 1s + on_tag: + - lambda: |- + ESP_LOGD("main", "Found tag %s", x.c_str()); + +binary_sensor: + - platform: rc522 + rc522_id: rc522_nfcc + name: RC522 NFC Tag + uid: 74-10-37-94 diff --git a/tests/components/rc522_i2c/test.esp32-c3.yaml b/tests/components/rc522_i2c/test.esp32-c3.yaml new file mode 100644 index 0000000000..8c8819e257 --- /dev/null +++ b/tests/components/rc522_i2c/test.esp32-c3.yaml @@ -0,0 +1,17 @@ +i2c: + - id: i2c_rc522 + scl: 5 + sda: 4 + +rc522_i2c: + - id: rc522_nfcc + update_interval: 1s + on_tag: + - lambda: |- + ESP_LOGD("main", "Found tag %s", x.c_str()); + +binary_sensor: + - platform: rc522 + rc522_id: rc522_nfcc + name: RC522 NFC Tag + uid: 74-10-37-94 diff --git a/tests/components/rc522_i2c/test.esp32-idf.yaml b/tests/components/rc522_i2c/test.esp32-idf.yaml new file mode 100644 index 0000000000..69b7d892a4 --- /dev/null +++ b/tests/components/rc522_i2c/test.esp32-idf.yaml @@ -0,0 +1,17 @@ +i2c: + - id: i2c_rc522 + scl: 16 + sda: 17 + +rc522_i2c: + - id: rc522_nfcc + update_interval: 1s + on_tag: + - lambda: |- + ESP_LOGD("main", "Found tag %s", x.c_str()); + +binary_sensor: + - platform: rc522 + rc522_id: rc522_nfcc + name: RC522 NFC Tag + uid: 74-10-37-94 diff --git a/tests/components/rc522_i2c/test.esp32.yaml b/tests/components/rc522_i2c/test.esp32.yaml new file mode 100644 index 0000000000..69b7d892a4 --- /dev/null +++ b/tests/components/rc522_i2c/test.esp32.yaml @@ -0,0 +1,17 @@ +i2c: + - id: i2c_rc522 + scl: 16 + sda: 17 + +rc522_i2c: + - id: rc522_nfcc + update_interval: 1s + on_tag: + - lambda: |- + ESP_LOGD("main", "Found tag %s", x.c_str()); + +binary_sensor: + - platform: rc522 + rc522_id: rc522_nfcc + name: RC522 NFC Tag + uid: 74-10-37-94 diff --git a/tests/components/rc522_i2c/test.esp8266.yaml b/tests/components/rc522_i2c/test.esp8266.yaml new file mode 100644 index 0000000000..8c8819e257 --- /dev/null +++ b/tests/components/rc522_i2c/test.esp8266.yaml @@ -0,0 +1,17 @@ +i2c: + - id: i2c_rc522 + scl: 5 + sda: 4 + +rc522_i2c: + - id: rc522_nfcc + update_interval: 1s + on_tag: + - lambda: |- + ESP_LOGD("main", "Found tag %s", x.c_str()); + +binary_sensor: + - platform: rc522 + rc522_id: rc522_nfcc + name: RC522 NFC Tag + uid: 74-10-37-94 diff --git a/tests/components/rc522_i2c/test.rp2040.yaml b/tests/components/rc522_i2c/test.rp2040.yaml new file mode 100644 index 0000000000..8c8819e257 --- /dev/null +++ b/tests/components/rc522_i2c/test.rp2040.yaml @@ -0,0 +1,17 @@ +i2c: + - id: i2c_rc522 + scl: 5 + sda: 4 + +rc522_i2c: + - id: rc522_nfcc + update_interval: 1s + on_tag: + - lambda: |- + ESP_LOGD("main", "Found tag %s", x.c_str()); + +binary_sensor: + - platform: rc522 + rc522_id: rc522_nfcc + name: RC522 NFC Tag + uid: 74-10-37-94 diff --git a/tests/components/rc522_spi/test.esp32-c3-idf.yaml b/tests/components/rc522_spi/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..8bcab84700 --- /dev/null +++ b/tests/components/rc522_spi/test.esp32-c3-idf.yaml @@ -0,0 +1,15 @@ +spi: + - id: spi_rc522 + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +rc522_spi: + id: rc522_nfcc + cs_pin: 4 + +binary_sensor: + - platform: rc522 + rc522_id: rc522_nfcc + name: PN532 NFC Tag + uid: 74-10-37-94 diff --git a/tests/components/rc522_spi/test.esp32-c3.yaml b/tests/components/rc522_spi/test.esp32-c3.yaml new file mode 100644 index 0000000000..8bcab84700 --- /dev/null +++ b/tests/components/rc522_spi/test.esp32-c3.yaml @@ -0,0 +1,15 @@ +spi: + - id: spi_rc522 + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +rc522_spi: + id: rc522_nfcc + cs_pin: 4 + +binary_sensor: + - platform: rc522 + rc522_id: rc522_nfcc + name: PN532 NFC Tag + uid: 74-10-37-94 diff --git a/tests/components/rc522_spi/test.esp32-idf.yaml b/tests/components/rc522_spi/test.esp32-idf.yaml new file mode 100644 index 0000000000..5c0b698a08 --- /dev/null +++ b/tests/components/rc522_spi/test.esp32-idf.yaml @@ -0,0 +1,15 @@ +spi: + - id: spi_rc522 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +rc522_spi: + id: rc522_nfcc + cs_pin: 12 + +binary_sensor: + - platform: rc522 + rc522_id: rc522_nfcc + name: PN532 NFC Tag + uid: 74-10-37-94 diff --git a/tests/components/rc522_spi/test.esp32.yaml b/tests/components/rc522_spi/test.esp32.yaml new file mode 100644 index 0000000000..5c0b698a08 --- /dev/null +++ b/tests/components/rc522_spi/test.esp32.yaml @@ -0,0 +1,15 @@ +spi: + - id: spi_rc522 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +rc522_spi: + id: rc522_nfcc + cs_pin: 12 + +binary_sensor: + - platform: rc522 + rc522_id: rc522_nfcc + name: PN532 NFC Tag + uid: 74-10-37-94 diff --git a/tests/components/rc522_spi/test.esp8266.yaml b/tests/components/rc522_spi/test.esp8266.yaml new file mode 100644 index 0000000000..3c33311266 --- /dev/null +++ b/tests/components/rc522_spi/test.esp8266.yaml @@ -0,0 +1,15 @@ +spi: + - id: spi_rc522 + clk_pin: 14 + mosi_pin: 13 + miso_pin: 12 + +rc522_spi: + id: rc522_nfcc + cs_pin: 15 + +binary_sensor: + - platform: rc522 + rc522_id: rc522_nfcc + name: PN532 NFC Tag + uid: 74-10-37-94 diff --git a/tests/components/rc522_spi/test.rp2040.yaml b/tests/components/rc522_spi/test.rp2040.yaml new file mode 100644 index 0000000000..ed2827dbb9 --- /dev/null +++ b/tests/components/rc522_spi/test.rp2040.yaml @@ -0,0 +1,15 @@ +spi: + - id: spi_rc522 + clk_pin: 2 + mosi_pin: 3 + miso_pin: 4 + +rc522_spi: + id: rc522_nfcc + cs_pin: 6 + +binary_sensor: + - platform: rc522 + rc522_id: rc522_nfcc + name: PN532 NFC Tag + uid: 74-10-37-94 diff --git a/tests/components/rdm6300/test.esp32-c3-idf.yaml b/tests/components/rdm6300/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..b92fce06e2 --- /dev/null +++ b/tests/components/rdm6300/test.esp32-c3-idf.yaml @@ -0,0 +1,12 @@ +uart: + - id: uart_rdm6300 + tx_pin: 4 + rx_pin: 5 + baud_rate: 115200 + +rdm6300: + +binary_sensor: + - platform: rdm6300 + uid: 7616525 + name: RDM6300 NFC Tag diff --git a/tests/components/rdm6300/test.esp32-c3.yaml b/tests/components/rdm6300/test.esp32-c3.yaml new file mode 100644 index 0000000000..b92fce06e2 --- /dev/null +++ b/tests/components/rdm6300/test.esp32-c3.yaml @@ -0,0 +1,12 @@ +uart: + - id: uart_rdm6300 + tx_pin: 4 + rx_pin: 5 + baud_rate: 115200 + +rdm6300: + +binary_sensor: + - platform: rdm6300 + uid: 7616525 + name: RDM6300 NFC Tag diff --git a/tests/components/rdm6300/test.esp32-idf.yaml b/tests/components/rdm6300/test.esp32-idf.yaml new file mode 100644 index 0000000000..4159248124 --- /dev/null +++ b/tests/components/rdm6300/test.esp32-idf.yaml @@ -0,0 +1,12 @@ +uart: + - id: uart_rdm6300 + tx_pin: 17 + rx_pin: 16 + baud_rate: 115200 + +rdm6300: + +binary_sensor: + - platform: rdm6300 + uid: 7616525 + name: RDM6300 NFC Tag diff --git a/tests/components/rdm6300/test.esp32.yaml b/tests/components/rdm6300/test.esp32.yaml new file mode 100644 index 0000000000..4159248124 --- /dev/null +++ b/tests/components/rdm6300/test.esp32.yaml @@ -0,0 +1,12 @@ +uart: + - id: uart_rdm6300 + tx_pin: 17 + rx_pin: 16 + baud_rate: 115200 + +rdm6300: + +binary_sensor: + - platform: rdm6300 + uid: 7616525 + name: RDM6300 NFC Tag diff --git a/tests/components/rdm6300/test.esp8266.yaml b/tests/components/rdm6300/test.esp8266.yaml new file mode 100644 index 0000000000..b92fce06e2 --- /dev/null +++ b/tests/components/rdm6300/test.esp8266.yaml @@ -0,0 +1,12 @@ +uart: + - id: uart_rdm6300 + tx_pin: 4 + rx_pin: 5 + baud_rate: 115200 + +rdm6300: + +binary_sensor: + - platform: rdm6300 + uid: 7616525 + name: RDM6300 NFC Tag diff --git a/tests/components/rdm6300/test.rp2040.yaml b/tests/components/rdm6300/test.rp2040.yaml new file mode 100644 index 0000000000..b92fce06e2 --- /dev/null +++ b/tests/components/rdm6300/test.rp2040.yaml @@ -0,0 +1,12 @@ +uart: + - id: uart_rdm6300 + tx_pin: 4 + rx_pin: 5 + baud_rate: 115200 + +rdm6300: + +binary_sensor: + - platform: rdm6300 + uid: 7616525 + name: RDM6300 NFC Tag diff --git a/tests/components/resistance/test.esp32-c3.yaml b/tests/components/resistance/test.esp32-c3.yaml new file mode 100644 index 0000000000..84e23d5115 --- /dev/null +++ b/tests/components/resistance/test.esp32-c3.yaml @@ -0,0 +1,12 @@ +sensor: + - platform: adc + id: my_sensor + pin: 4 + attenuation: 11db + - platform: resistance + sensor: my_sensor + configuration: DOWNSTREAM + resistor: 10kΩ + reference_voltage: 3.3V + name: Resistance + id: resist diff --git a/tests/components/resistance/test.esp32-idf.yaml b/tests/components/resistance/test.esp32-idf.yaml new file mode 100644 index 0000000000..b1ffc64972 --- /dev/null +++ b/tests/components/resistance/test.esp32-idf.yaml @@ -0,0 +1,12 @@ +sensor: + - platform: adc + id: my_sensor + pin: 32 + attenuation: 11db + - platform: resistance + sensor: my_sensor + configuration: DOWNSTREAM + resistor: 10kΩ + reference_voltage: 3.3V + name: Resistance + id: resist diff --git a/tests/components/resistance/test.esp32-s2.yaml b/tests/components/resistance/test.esp32-s2.yaml new file mode 100644 index 0000000000..4ebd6b5c49 --- /dev/null +++ b/tests/components/resistance/test.esp32-s2.yaml @@ -0,0 +1,12 @@ +sensor: + - platform: adc + id: my_sensor + pin: 1 + attenuation: 11db + - platform: resistance + sensor: my_sensor + configuration: DOWNSTREAM + resistor: 10kΩ + reference_voltage: 3.3V + name: Resistance + id: resist diff --git a/tests/components/resistance/test.esp32-s3.yaml b/tests/components/resistance/test.esp32-s3.yaml new file mode 100644 index 0000000000..4ebd6b5c49 --- /dev/null +++ b/tests/components/resistance/test.esp32-s3.yaml @@ -0,0 +1,12 @@ +sensor: + - platform: adc + id: my_sensor + pin: 1 + attenuation: 11db + - platform: resistance + sensor: my_sensor + configuration: DOWNSTREAM + resistor: 10kΩ + reference_voltage: 3.3V + name: Resistance + id: resist diff --git a/tests/components/resistance/test.esp32.yaml b/tests/components/resistance/test.esp32.yaml new file mode 100644 index 0000000000..b1ffc64972 --- /dev/null +++ b/tests/components/resistance/test.esp32.yaml @@ -0,0 +1,12 @@ +sensor: + - platform: adc + id: my_sensor + pin: 32 + attenuation: 11db + - platform: resistance + sensor: my_sensor + configuration: DOWNSTREAM + resistor: 10kΩ + reference_voltage: 3.3V + name: Resistance + id: resist diff --git a/tests/components/resistance/test.esp8266.yaml b/tests/components/resistance/test.esp8266.yaml new file mode 100644 index 0000000000..f723f7c7c7 --- /dev/null +++ b/tests/components/resistance/test.esp8266.yaml @@ -0,0 +1,11 @@ +sensor: + - platform: adc + id: my_sensor + pin: VCC + - platform: resistance + sensor: my_sensor + configuration: DOWNSTREAM + resistor: 10kΩ + reference_voltage: 3.3V + name: Resistance + id: resist diff --git a/tests/components/resistance/test.rp2040.yaml b/tests/components/resistance/test.rp2040.yaml new file mode 100644 index 0000000000..5cc643926a --- /dev/null +++ b/tests/components/resistance/test.rp2040.yaml @@ -0,0 +1,12 @@ +sensor: + - platform: adc + id: my_sensor + name: VSYS + pin: VCC + - platform: resistance + sensor: my_sensor + configuration: DOWNSTREAM + resistor: 10kΩ + reference_voltage: 3.3V + name: Resistance + id: resist diff --git a/tests/components/restart/test.esp32-c3-idf.yaml b/tests/components/restart/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..f0d25809ac --- /dev/null +++ b/tests/components/restart/test.esp32-c3-idf.yaml @@ -0,0 +1,7 @@ +button: + - platform: restart + name: Restart Button + +switch: + - platform: restart + name: Restart Switch diff --git a/tests/components/restart/test.esp32-c3.yaml b/tests/components/restart/test.esp32-c3.yaml new file mode 100644 index 0000000000..f0d25809ac --- /dev/null +++ b/tests/components/restart/test.esp32-c3.yaml @@ -0,0 +1,7 @@ +button: + - platform: restart + name: Restart Button + +switch: + - platform: restart + name: Restart Switch diff --git a/tests/components/restart/test.esp32-idf.yaml b/tests/components/restart/test.esp32-idf.yaml new file mode 100644 index 0000000000..f0d25809ac --- /dev/null +++ b/tests/components/restart/test.esp32-idf.yaml @@ -0,0 +1,7 @@ +button: + - platform: restart + name: Restart Button + +switch: + - platform: restart + name: Restart Switch diff --git a/tests/components/restart/test.esp32.yaml b/tests/components/restart/test.esp32.yaml new file mode 100644 index 0000000000..f0d25809ac --- /dev/null +++ b/tests/components/restart/test.esp32.yaml @@ -0,0 +1,7 @@ +button: + - platform: restart + name: Restart Button + +switch: + - platform: restart + name: Restart Switch diff --git a/tests/components/restart/test.esp8266.yaml b/tests/components/restart/test.esp8266.yaml new file mode 100644 index 0000000000..f0d25809ac --- /dev/null +++ b/tests/components/restart/test.esp8266.yaml @@ -0,0 +1,7 @@ +button: + - platform: restart + name: Restart Button + +switch: + - platform: restart + name: Restart Switch diff --git a/tests/components/restart/test.rp2040.yaml b/tests/components/restart/test.rp2040.yaml new file mode 100644 index 0000000000..f0d25809ac --- /dev/null +++ b/tests/components/restart/test.rp2040.yaml @@ -0,0 +1,7 @@ +button: + - platform: restart + name: Restart Button + +switch: + - platform: restart + name: Restart Switch diff --git a/tests/components/rf_bridge/test.esp32-c3-idf.yaml b/tests/components/rf_bridge/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..95a7aa861a --- /dev/null +++ b/tests/components/rf_bridge/test.esp32-c3-idf.yaml @@ -0,0 +1,35 @@ +uart: + - id: uart_rf_bridge + tx_pin: 4 + rx_pin: 5 + baud_rate: 115200 + +rf_bridge: + on_code_received: + - lambda: |- + uint32_t test; + test = data.sync; + test = data.low; + test = data.high; + test = data.code; + - rf_bridge.send_code: + sync: 0x1234 + low: 0x1234 + high: 0x1234 + code: 0x123456 + - rf_bridge.learn + on_advanced_code_received: + - lambda: |- + uint32_t test; + std::string test_code; + test = data.length; + test = data.protocol; + test_code = data.code; + - rf_bridge.start_advanced_sniffing: + - rf_bridge.stop_advanced_sniffing: + - rf_bridge.send_advanced_code: + length: 0x04 + protocol: 0x01 + code: "ABC123" + - rf_bridge.send_raw: + raw: "AAA5070008001000ABC12355" diff --git a/tests/components/rf_bridge/test.esp32-c3.yaml b/tests/components/rf_bridge/test.esp32-c3.yaml new file mode 100644 index 0000000000..95a7aa861a --- /dev/null +++ b/tests/components/rf_bridge/test.esp32-c3.yaml @@ -0,0 +1,35 @@ +uart: + - id: uart_rf_bridge + tx_pin: 4 + rx_pin: 5 + baud_rate: 115200 + +rf_bridge: + on_code_received: + - lambda: |- + uint32_t test; + test = data.sync; + test = data.low; + test = data.high; + test = data.code; + - rf_bridge.send_code: + sync: 0x1234 + low: 0x1234 + high: 0x1234 + code: 0x123456 + - rf_bridge.learn + on_advanced_code_received: + - lambda: |- + uint32_t test; + std::string test_code; + test = data.length; + test = data.protocol; + test_code = data.code; + - rf_bridge.start_advanced_sniffing: + - rf_bridge.stop_advanced_sniffing: + - rf_bridge.send_advanced_code: + length: 0x04 + protocol: 0x01 + code: "ABC123" + - rf_bridge.send_raw: + raw: "AAA5070008001000ABC12355" diff --git a/tests/components/rf_bridge/test.esp32-idf.yaml b/tests/components/rf_bridge/test.esp32-idf.yaml new file mode 100644 index 0000000000..9ade7f0ac0 --- /dev/null +++ b/tests/components/rf_bridge/test.esp32-idf.yaml @@ -0,0 +1,35 @@ +uart: + - id: uart_rf_bridge + tx_pin: 17 + rx_pin: 16 + baud_rate: 115200 + +rf_bridge: + on_code_received: + - lambda: |- + uint32_t test; + test = data.sync; + test = data.low; + test = data.high; + test = data.code; + - rf_bridge.send_code: + sync: 0x1234 + low: 0x1234 + high: 0x1234 + code: 0x123456 + - rf_bridge.learn + on_advanced_code_received: + - lambda: |- + uint32_t test; + std::string test_code; + test = data.length; + test = data.protocol; + test_code = data.code; + - rf_bridge.start_advanced_sniffing: + - rf_bridge.stop_advanced_sniffing: + - rf_bridge.send_advanced_code: + length: 0x04 + protocol: 0x01 + code: "ABC123" + - rf_bridge.send_raw: + raw: "AAA5070008001000ABC12355" diff --git a/tests/components/rf_bridge/test.esp32.yaml b/tests/components/rf_bridge/test.esp32.yaml new file mode 100644 index 0000000000..9ade7f0ac0 --- /dev/null +++ b/tests/components/rf_bridge/test.esp32.yaml @@ -0,0 +1,35 @@ +uart: + - id: uart_rf_bridge + tx_pin: 17 + rx_pin: 16 + baud_rate: 115200 + +rf_bridge: + on_code_received: + - lambda: |- + uint32_t test; + test = data.sync; + test = data.low; + test = data.high; + test = data.code; + - rf_bridge.send_code: + sync: 0x1234 + low: 0x1234 + high: 0x1234 + code: 0x123456 + - rf_bridge.learn + on_advanced_code_received: + - lambda: |- + uint32_t test; + std::string test_code; + test = data.length; + test = data.protocol; + test_code = data.code; + - rf_bridge.start_advanced_sniffing: + - rf_bridge.stop_advanced_sniffing: + - rf_bridge.send_advanced_code: + length: 0x04 + protocol: 0x01 + code: "ABC123" + - rf_bridge.send_raw: + raw: "AAA5070008001000ABC12355" diff --git a/tests/components/rf_bridge/test.esp8266.yaml b/tests/components/rf_bridge/test.esp8266.yaml new file mode 100644 index 0000000000..95a7aa861a --- /dev/null +++ b/tests/components/rf_bridge/test.esp8266.yaml @@ -0,0 +1,35 @@ +uart: + - id: uart_rf_bridge + tx_pin: 4 + rx_pin: 5 + baud_rate: 115200 + +rf_bridge: + on_code_received: + - lambda: |- + uint32_t test; + test = data.sync; + test = data.low; + test = data.high; + test = data.code; + - rf_bridge.send_code: + sync: 0x1234 + low: 0x1234 + high: 0x1234 + code: 0x123456 + - rf_bridge.learn + on_advanced_code_received: + - lambda: |- + uint32_t test; + std::string test_code; + test = data.length; + test = data.protocol; + test_code = data.code; + - rf_bridge.start_advanced_sniffing: + - rf_bridge.stop_advanced_sniffing: + - rf_bridge.send_advanced_code: + length: 0x04 + protocol: 0x01 + code: "ABC123" + - rf_bridge.send_raw: + raw: "AAA5070008001000ABC12355" diff --git a/tests/components/rf_bridge/test.rp2040.yaml b/tests/components/rf_bridge/test.rp2040.yaml new file mode 100644 index 0000000000..95a7aa861a --- /dev/null +++ b/tests/components/rf_bridge/test.rp2040.yaml @@ -0,0 +1,35 @@ +uart: + - id: uart_rf_bridge + tx_pin: 4 + rx_pin: 5 + baud_rate: 115200 + +rf_bridge: + on_code_received: + - lambda: |- + uint32_t test; + test = data.sync; + test = data.low; + test = data.high; + test = data.code; + - rf_bridge.send_code: + sync: 0x1234 + low: 0x1234 + high: 0x1234 + code: 0x123456 + - rf_bridge.learn + on_advanced_code_received: + - lambda: |- + uint32_t test; + std::string test_code; + test = data.length; + test = data.protocol; + test_code = data.code; + - rf_bridge.start_advanced_sniffing: + - rf_bridge.stop_advanced_sniffing: + - rf_bridge.send_advanced_code: + length: 0x04 + protocol: 0x01 + code: "ABC123" + - rf_bridge.send_raw: + raw: "AAA5070008001000ABC12355" diff --git a/tests/components/rgb/test.esp32-c3-idf.yaml b/tests/components/rgb/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..30ff1527b4 --- /dev/null +++ b/tests/components/rgb/test.esp32-c3-idf.yaml @@ -0,0 +1,18 @@ +output: + - platform: ledc + id: light_output_1 + pin: 1 + - platform: ledc + id: light_output_2 + pin: 2 + - platform: ledc + id: light_output_3 + pin: 3 + +light: + - platform: rgb + name: RGB Light + id: rgb_light + red: light_output_1 + green: light_output_2 + blue: light_output_3 diff --git a/tests/components/rgb/test.esp32-c3.yaml b/tests/components/rgb/test.esp32-c3.yaml new file mode 100644 index 0000000000..30ff1527b4 --- /dev/null +++ b/tests/components/rgb/test.esp32-c3.yaml @@ -0,0 +1,18 @@ +output: + - platform: ledc + id: light_output_1 + pin: 1 + - platform: ledc + id: light_output_2 + pin: 2 + - platform: ledc + id: light_output_3 + pin: 3 + +light: + - platform: rgb + name: RGB Light + id: rgb_light + red: light_output_1 + green: light_output_2 + blue: light_output_3 diff --git a/tests/components/rgb/test.esp32-idf.yaml b/tests/components/rgb/test.esp32-idf.yaml new file mode 100644 index 0000000000..2173e718be --- /dev/null +++ b/tests/components/rgb/test.esp32-idf.yaml @@ -0,0 +1,18 @@ +output: + - platform: ledc + id: light_output_1 + pin: 12 + - platform: ledc + id: light_output_2 + pin: 13 + - platform: ledc + id: light_output_3 + pin: 14 + +light: + - platform: rgb + name: RGB Light + id: rgb_light + red: light_output_1 + green: light_output_2 + blue: light_output_3 diff --git a/tests/components/rgb/test.esp32.yaml b/tests/components/rgb/test.esp32.yaml new file mode 100644 index 0000000000..2173e718be --- /dev/null +++ b/tests/components/rgb/test.esp32.yaml @@ -0,0 +1,18 @@ +output: + - platform: ledc + id: light_output_1 + pin: 12 + - platform: ledc + id: light_output_2 + pin: 13 + - platform: ledc + id: light_output_3 + pin: 14 + +light: + - platform: rgb + name: RGB Light + id: rgb_light + red: light_output_1 + green: light_output_2 + blue: light_output_3 diff --git a/tests/components/rgb/test.esp8266.yaml b/tests/components/rgb/test.esp8266.yaml new file mode 100644 index 0000000000..60c5a7e04f --- /dev/null +++ b/tests/components/rgb/test.esp8266.yaml @@ -0,0 +1,18 @@ +output: + - platform: esp8266_pwm + id: light_output_1 + pin: 12 + - platform: esp8266_pwm + id: light_output_2 + pin: 13 + - platform: esp8266_pwm + id: light_output_3 + pin: 14 + +light: + - platform: rgb + name: RGB Light + id: rgb_light + red: light_output_1 + green: light_output_2 + blue: light_output_3 diff --git a/tests/components/rgb/test.rp2040.yaml b/tests/components/rgb/test.rp2040.yaml new file mode 100644 index 0000000000..fd6519707b --- /dev/null +++ b/tests/components/rgb/test.rp2040.yaml @@ -0,0 +1,18 @@ +output: + - platform: rp2040_pwm + id: light_output_1 + pin: 12 + - platform: rp2040_pwm + id: light_output_2 + pin: 13 + - platform: rp2040_pwm + id: light_output_3 + pin: 14 + +light: + - platform: rgb + name: RGB Light + id: rgb_light + red: light_output_1 + green: light_output_2 + blue: light_output_3 diff --git a/tests/components/rgbct/test.esp32-c3-idf.yaml b/tests/components/rgbct/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..426c4b8937 --- /dev/null +++ b/tests/components/rgbct/test.esp32-c3-idf.yaml @@ -0,0 +1,28 @@ +output: + - platform: ledc + id: light_output_1 + pin: 1 + - platform: ledc + id: light_output_2 + pin: 2 + - platform: ledc + id: light_output_3 + pin: 3 + - platform: ledc + id: light_output_4 + pin: 4 + - platform: ledc + id: light_output_5 + pin: 5 + +light: + - platform: rgbct + name: RGBCT Light + red: light_output_1 + green: light_output_2 + blue: light_output_3 + color_temperature: light_output_4 + white_brightness: light_output_5 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds + color_interlock: true diff --git a/tests/components/rgbct/test.esp32-c3.yaml b/tests/components/rgbct/test.esp32-c3.yaml new file mode 100644 index 0000000000..426c4b8937 --- /dev/null +++ b/tests/components/rgbct/test.esp32-c3.yaml @@ -0,0 +1,28 @@ +output: + - platform: ledc + id: light_output_1 + pin: 1 + - platform: ledc + id: light_output_2 + pin: 2 + - platform: ledc + id: light_output_3 + pin: 3 + - platform: ledc + id: light_output_4 + pin: 4 + - platform: ledc + id: light_output_5 + pin: 5 + +light: + - platform: rgbct + name: RGBCT Light + red: light_output_1 + green: light_output_2 + blue: light_output_3 + color_temperature: light_output_4 + white_brightness: light_output_5 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds + color_interlock: true diff --git a/tests/components/rgbct/test.esp32-idf.yaml b/tests/components/rgbct/test.esp32-idf.yaml new file mode 100644 index 0000000000..d9758c9ec7 --- /dev/null +++ b/tests/components/rgbct/test.esp32-idf.yaml @@ -0,0 +1,28 @@ +output: + - platform: ledc + id: light_output_1 + pin: 12 + - platform: ledc + id: light_output_2 + pin: 13 + - platform: ledc + id: light_output_3 + pin: 14 + - platform: ledc + id: light_output_4 + pin: 15 + - platform: ledc + id: light_output_5 + pin: 16 + +light: + - platform: rgbct + name: RGBCT Light + red: light_output_1 + green: light_output_2 + blue: light_output_3 + color_temperature: light_output_4 + white_brightness: light_output_5 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds + color_interlock: true diff --git a/tests/components/rgbct/test.esp32.yaml b/tests/components/rgbct/test.esp32.yaml new file mode 100644 index 0000000000..d9758c9ec7 --- /dev/null +++ b/tests/components/rgbct/test.esp32.yaml @@ -0,0 +1,28 @@ +output: + - platform: ledc + id: light_output_1 + pin: 12 + - platform: ledc + id: light_output_2 + pin: 13 + - platform: ledc + id: light_output_3 + pin: 14 + - platform: ledc + id: light_output_4 + pin: 15 + - platform: ledc + id: light_output_5 + pin: 16 + +light: + - platform: rgbct + name: RGBCT Light + red: light_output_1 + green: light_output_2 + blue: light_output_3 + color_temperature: light_output_4 + white_brightness: light_output_5 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds + color_interlock: true diff --git a/tests/components/rgbct/test.esp8266.yaml b/tests/components/rgbct/test.esp8266.yaml new file mode 100644 index 0000000000..b7008c9ae3 --- /dev/null +++ b/tests/components/rgbct/test.esp8266.yaml @@ -0,0 +1,28 @@ +output: + - platform: esp8266_pwm + id: light_output_1 + pin: 12 + - platform: esp8266_pwm + id: light_output_2 + pin: 13 + - platform: esp8266_pwm + id: light_output_3 + pin: 14 + - platform: esp8266_pwm + id: light_output_4 + pin: 15 + - platform: esp8266_pwm + id: light_output_5 + pin: 16 + +light: + - platform: rgbct + name: RGBCT Light + red: light_output_1 + green: light_output_2 + blue: light_output_3 + color_temperature: light_output_4 + white_brightness: light_output_5 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds + color_interlock: true diff --git a/tests/components/rgbct/test.rp2040.yaml b/tests/components/rgbct/test.rp2040.yaml new file mode 100644 index 0000000000..e7e959b2a4 --- /dev/null +++ b/tests/components/rgbct/test.rp2040.yaml @@ -0,0 +1,28 @@ +output: + - platform: rp2040_pwm + id: light_output_1 + pin: 12 + - platform: rp2040_pwm + id: light_output_2 + pin: 13 + - platform: rp2040_pwm + id: light_output_3 + pin: 14 + - platform: rp2040_pwm + id: light_output_4 + pin: 15 + - platform: rp2040_pwm + id: light_output_5 + pin: 16 + +light: + - platform: rgbct + name: RGBCT Light + red: light_output_1 + green: light_output_2 + blue: light_output_3 + color_temperature: light_output_4 + white_brightness: light_output_5 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds + color_interlock: true diff --git a/tests/components/rgbw/test.esp32-c3-idf.yaml b/tests/components/rgbw/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..c5d4fceb9d --- /dev/null +++ b/tests/components/rgbw/test.esp32-c3-idf.yaml @@ -0,0 +1,22 @@ +output: + - platform: ledc + id: light_output_1 + pin: 1 + - platform: ledc + id: light_output_2 + pin: 2 + - platform: ledc + id: light_output_3 + pin: 3 + - platform: ledc + id: light_output_4 + pin: 4 + +light: + - platform: rgbw + name: RGBW Light + red: light_output_1 + green: light_output_2 + blue: light_output_3 + white: light_output_4 + color_interlock: true diff --git a/tests/components/rgbw/test.esp32-c3.yaml b/tests/components/rgbw/test.esp32-c3.yaml new file mode 100644 index 0000000000..c5d4fceb9d --- /dev/null +++ b/tests/components/rgbw/test.esp32-c3.yaml @@ -0,0 +1,22 @@ +output: + - platform: ledc + id: light_output_1 + pin: 1 + - platform: ledc + id: light_output_2 + pin: 2 + - platform: ledc + id: light_output_3 + pin: 3 + - platform: ledc + id: light_output_4 + pin: 4 + +light: + - platform: rgbw + name: RGBW Light + red: light_output_1 + green: light_output_2 + blue: light_output_3 + white: light_output_4 + color_interlock: true diff --git a/tests/components/rgbw/test.esp32-idf.yaml b/tests/components/rgbw/test.esp32-idf.yaml new file mode 100644 index 0000000000..6e9e92a03c --- /dev/null +++ b/tests/components/rgbw/test.esp32-idf.yaml @@ -0,0 +1,22 @@ +output: + - platform: ledc + id: light_output_1 + pin: 12 + - platform: ledc + id: light_output_2 + pin: 13 + - platform: ledc + id: light_output_3 + pin: 14 + - platform: ledc + id: light_output_4 + pin: 15 + +light: + - platform: rgbw + name: RGBW Light + red: light_output_1 + green: light_output_2 + blue: light_output_3 + white: light_output_4 + color_interlock: true diff --git a/tests/components/rgbw/test.esp32.yaml b/tests/components/rgbw/test.esp32.yaml new file mode 100644 index 0000000000..6e9e92a03c --- /dev/null +++ b/tests/components/rgbw/test.esp32.yaml @@ -0,0 +1,22 @@ +output: + - platform: ledc + id: light_output_1 + pin: 12 + - platform: ledc + id: light_output_2 + pin: 13 + - platform: ledc + id: light_output_3 + pin: 14 + - platform: ledc + id: light_output_4 + pin: 15 + +light: + - platform: rgbw + name: RGBW Light + red: light_output_1 + green: light_output_2 + blue: light_output_3 + white: light_output_4 + color_interlock: true diff --git a/tests/components/rgbw/test.esp8266.yaml b/tests/components/rgbw/test.esp8266.yaml new file mode 100644 index 0000000000..54098613e4 --- /dev/null +++ b/tests/components/rgbw/test.esp8266.yaml @@ -0,0 +1,22 @@ +output: + - platform: esp8266_pwm + id: light_output_1 + pin: 12 + - platform: esp8266_pwm + id: light_output_2 + pin: 13 + - platform: esp8266_pwm + id: light_output_3 + pin: 14 + - platform: esp8266_pwm + id: light_output_4 + pin: 15 + +light: + - platform: rgbw + name: RGBW Light + red: light_output_1 + green: light_output_2 + blue: light_output_3 + white: light_output_4 + color_interlock: true diff --git a/tests/components/rgbw/test.rp2040.yaml b/tests/components/rgbw/test.rp2040.yaml new file mode 100644 index 0000000000..6a4437b898 --- /dev/null +++ b/tests/components/rgbw/test.rp2040.yaml @@ -0,0 +1,22 @@ +output: + - platform: rp2040_pwm + id: light_output_1 + pin: 12 + - platform: rp2040_pwm + id: light_output_2 + pin: 13 + - platform: rp2040_pwm + id: light_output_3 + pin: 14 + - platform: rp2040_pwm + id: light_output_4 + pin: 15 + +light: + - platform: rgbw + name: RGBW Light + red: light_output_1 + green: light_output_2 + blue: light_output_3 + white: light_output_4 + color_interlock: true diff --git a/tests/components/rgbww/test.esp32-c3-idf.yaml b/tests/components/rgbww/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..49e9c7f331 --- /dev/null +++ b/tests/components/rgbww/test.esp32-c3-idf.yaml @@ -0,0 +1,28 @@ +output: + - platform: ledc + id: light_output_1 + pin: 1 + - platform: ledc + id: light_output_2 + pin: 2 + - platform: ledc + id: light_output_3 + pin: 3 + - platform: ledc + id: light_output_4 + pin: 4 + - platform: ledc + id: light_output_5 + pin: 5 + +light: + - platform: rgbww + name: RGBWW Light + red: light_output_1 + green: light_output_2 + blue: light_output_3 + cold_white: light_output_4 + warm_white: light_output_5 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds + color_interlock: true diff --git a/tests/components/rgbww/test.esp32-c3.yaml b/tests/components/rgbww/test.esp32-c3.yaml new file mode 100644 index 0000000000..49e9c7f331 --- /dev/null +++ b/tests/components/rgbww/test.esp32-c3.yaml @@ -0,0 +1,28 @@ +output: + - platform: ledc + id: light_output_1 + pin: 1 + - platform: ledc + id: light_output_2 + pin: 2 + - platform: ledc + id: light_output_3 + pin: 3 + - platform: ledc + id: light_output_4 + pin: 4 + - platform: ledc + id: light_output_5 + pin: 5 + +light: + - platform: rgbww + name: RGBWW Light + red: light_output_1 + green: light_output_2 + blue: light_output_3 + cold_white: light_output_4 + warm_white: light_output_5 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds + color_interlock: true diff --git a/tests/components/rgbww/test.esp32-idf.yaml b/tests/components/rgbww/test.esp32-idf.yaml new file mode 100644 index 0000000000..c24b6b7746 --- /dev/null +++ b/tests/components/rgbww/test.esp32-idf.yaml @@ -0,0 +1,28 @@ +output: + - platform: ledc + id: light_output_1 + pin: 12 + - platform: ledc + id: light_output_2 + pin: 13 + - platform: ledc + id: light_output_3 + pin: 14 + - platform: ledc + id: light_output_4 + pin: 15 + - platform: ledc + id: light_output_5 + pin: 16 + +light: + - platform: rgbww + name: RGBWW Light + red: light_output_1 + green: light_output_2 + blue: light_output_3 + cold_white: light_output_4 + warm_white: light_output_5 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds + color_interlock: true diff --git a/tests/components/rgbww/test.esp32.yaml b/tests/components/rgbww/test.esp32.yaml new file mode 100644 index 0000000000..c24b6b7746 --- /dev/null +++ b/tests/components/rgbww/test.esp32.yaml @@ -0,0 +1,28 @@ +output: + - platform: ledc + id: light_output_1 + pin: 12 + - platform: ledc + id: light_output_2 + pin: 13 + - platform: ledc + id: light_output_3 + pin: 14 + - platform: ledc + id: light_output_4 + pin: 15 + - platform: ledc + id: light_output_5 + pin: 16 + +light: + - platform: rgbww + name: RGBWW Light + red: light_output_1 + green: light_output_2 + blue: light_output_3 + cold_white: light_output_4 + warm_white: light_output_5 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds + color_interlock: true diff --git a/tests/components/rgbww/test.esp8266.yaml b/tests/components/rgbww/test.esp8266.yaml new file mode 100644 index 0000000000..4ea26e6526 --- /dev/null +++ b/tests/components/rgbww/test.esp8266.yaml @@ -0,0 +1,28 @@ +output: + - platform: esp8266_pwm + id: light_output_1 + pin: 12 + - platform: esp8266_pwm + id: light_output_2 + pin: 13 + - platform: esp8266_pwm + id: light_output_3 + pin: 14 + - platform: esp8266_pwm + id: light_output_4 + pin: 15 + - platform: esp8266_pwm + id: light_output_5 + pin: 16 + +light: + - platform: rgbww + name: RGBWW Light + red: light_output_1 + green: light_output_2 + blue: light_output_3 + cold_white: light_output_4 + warm_white: light_output_5 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds + color_interlock: true diff --git a/tests/components/rgbww/test.rp2040.yaml b/tests/components/rgbww/test.rp2040.yaml new file mode 100644 index 0000000000..0986f06e78 --- /dev/null +++ b/tests/components/rgbww/test.rp2040.yaml @@ -0,0 +1,28 @@ +output: + - platform: rp2040_pwm + id: light_output_1 + pin: 12 + - platform: rp2040_pwm + id: light_output_2 + pin: 13 + - platform: rp2040_pwm + id: light_output_3 + pin: 14 + - platform: rp2040_pwm + id: light_output_4 + pin: 15 + - platform: rp2040_pwm + id: light_output_5 + pin: 16 + +light: + - platform: rgbww + name: RGBWW Light + red: light_output_1 + green: light_output_2 + blue: light_output_3 + cold_white: light_output_4 + warm_white: light_output_5 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds + color_interlock: true diff --git a/tests/components/rotary_encoder/test.esp32-c3-idf.yaml b/tests/components/rotary_encoder/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..59f8b56abf --- /dev/null +++ b/tests/components/rotary_encoder/test.esp32-c3-idf.yaml @@ -0,0 +1,25 @@ +sensor: + - platform: rotary_encoder + name: Rotary Encoder + id: rotary_encoder1 + pin_a: 3 + pin_b: 4 + pin_reset: 5 + filters: + - or: + - debounce: 0.1s + - delta: 10 + resolution: 4 + min_value: -10 + max_value: 30 + on_value: + - sensor.rotary_encoder.set_value: + id: rotary_encoder1 + value: 10 + - sensor.rotary_encoder.set_value: + id: rotary_encoder1 + value: !lambda "return -1;" + on_clockwise: + - logger.log: Clockwise + on_anticlockwise: + - logger.log: Anticlockwise diff --git a/tests/components/rotary_encoder/test.esp32-c3.yaml b/tests/components/rotary_encoder/test.esp32-c3.yaml new file mode 100644 index 0000000000..59f8b56abf --- /dev/null +++ b/tests/components/rotary_encoder/test.esp32-c3.yaml @@ -0,0 +1,25 @@ +sensor: + - platform: rotary_encoder + name: Rotary Encoder + id: rotary_encoder1 + pin_a: 3 + pin_b: 4 + pin_reset: 5 + filters: + - or: + - debounce: 0.1s + - delta: 10 + resolution: 4 + min_value: -10 + max_value: 30 + on_value: + - sensor.rotary_encoder.set_value: + id: rotary_encoder1 + value: 10 + - sensor.rotary_encoder.set_value: + id: rotary_encoder1 + value: !lambda "return -1;" + on_clockwise: + - logger.log: Clockwise + on_anticlockwise: + - logger.log: Anticlockwise diff --git a/tests/components/rotary_encoder/test.esp32-idf.yaml b/tests/components/rotary_encoder/test.esp32-idf.yaml new file mode 100644 index 0000000000..da3843f82d --- /dev/null +++ b/tests/components/rotary_encoder/test.esp32-idf.yaml @@ -0,0 +1,25 @@ +sensor: + - platform: rotary_encoder + name: Rotary Encoder + id: rotary_encoder1 + pin_a: 13 + pin_b: 14 + pin_reset: 15 + filters: + - or: + - debounce: 0.1s + - delta: 10 + resolution: 4 + min_value: -10 + max_value: 30 + on_value: + - sensor.rotary_encoder.set_value: + id: rotary_encoder1 + value: 10 + - sensor.rotary_encoder.set_value: + id: rotary_encoder1 + value: !lambda "return -1;" + on_clockwise: + - logger.log: Clockwise + on_anticlockwise: + - logger.log: Anticlockwise diff --git a/tests/components/rotary_encoder/test.esp32.yaml b/tests/components/rotary_encoder/test.esp32.yaml new file mode 100644 index 0000000000..da3843f82d --- /dev/null +++ b/tests/components/rotary_encoder/test.esp32.yaml @@ -0,0 +1,25 @@ +sensor: + - platform: rotary_encoder + name: Rotary Encoder + id: rotary_encoder1 + pin_a: 13 + pin_b: 14 + pin_reset: 15 + filters: + - or: + - debounce: 0.1s + - delta: 10 + resolution: 4 + min_value: -10 + max_value: 30 + on_value: + - sensor.rotary_encoder.set_value: + id: rotary_encoder1 + value: 10 + - sensor.rotary_encoder.set_value: + id: rotary_encoder1 + value: !lambda "return -1;" + on_clockwise: + - logger.log: Clockwise + on_anticlockwise: + - logger.log: Anticlockwise diff --git a/tests/components/rotary_encoder/test.esp8266.yaml b/tests/components/rotary_encoder/test.esp8266.yaml new file mode 100644 index 0000000000..da3843f82d --- /dev/null +++ b/tests/components/rotary_encoder/test.esp8266.yaml @@ -0,0 +1,25 @@ +sensor: + - platform: rotary_encoder + name: Rotary Encoder + id: rotary_encoder1 + pin_a: 13 + pin_b: 14 + pin_reset: 15 + filters: + - or: + - debounce: 0.1s + - delta: 10 + resolution: 4 + min_value: -10 + max_value: 30 + on_value: + - sensor.rotary_encoder.set_value: + id: rotary_encoder1 + value: 10 + - sensor.rotary_encoder.set_value: + id: rotary_encoder1 + value: !lambda "return -1;" + on_clockwise: + - logger.log: Clockwise + on_anticlockwise: + - logger.log: Anticlockwise diff --git a/tests/components/rotary_encoder/test.rp2040.yaml b/tests/components/rotary_encoder/test.rp2040.yaml new file mode 100644 index 0000000000..da3843f82d --- /dev/null +++ b/tests/components/rotary_encoder/test.rp2040.yaml @@ -0,0 +1,25 @@ +sensor: + - platform: rotary_encoder + name: Rotary Encoder + id: rotary_encoder1 + pin_a: 13 + pin_b: 14 + pin_reset: 15 + filters: + - or: + - debounce: 0.1s + - delta: 10 + resolution: 4 + min_value: -10 + max_value: 30 + on_value: + - sensor.rotary_encoder.set_value: + id: rotary_encoder1 + value: 10 + - sensor.rotary_encoder.set_value: + id: rotary_encoder1 + value: !lambda "return -1;" + on_clockwise: + - logger.log: Clockwise + on_anticlockwise: + - logger.log: Anticlockwise diff --git a/tests/components/rp2040_pio_led_strip/test.rp2040.yaml b/tests/components/rp2040_pio_led_strip/test.rp2040.yaml new file mode 100644 index 0000000000..b9b1436cdb --- /dev/null +++ b/tests/components/rp2040_pio_led_strip/test.rp2040.yaml @@ -0,0 +1,18 @@ +light: + - platform: rp2040_pio_led_strip + id: led_strip + pin: 4 + num_leds: 60 + pio: 0 + rgb_order: GRB + chipset: WS2812 + - platform: rp2040_pio_led_strip + id: led_strip_custom_timings + pin: 5 + num_leds: 60 + pio: 1 + rgb_order: GRB + bit0_high: .1us + bit0_low: 1.2us + bit1_high: .69us + bit1_low: .4us diff --git a/tests/components/rp2040_pwm/test.rp2040.yaml b/tests/components/rp2040_pwm/test.rp2040.yaml new file mode 100644 index 0000000000..45c039106f --- /dev/null +++ b/tests/components/rp2040_pwm/test.rp2040.yaml @@ -0,0 +1,7 @@ +output: + - platform: rp2040_pwm + id: light_output_1 + pin: 2 + - platform: rp2040_pwm + id: light_output_2 + pin: 3 diff --git a/tests/components/rtttl/test.esp32-c3-idf.yaml b/tests/components/rtttl/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..c525f417de --- /dev/null +++ b/tests/components/rtttl/test.esp32-c3-idf.yaml @@ -0,0 +1,16 @@ +esphome: + on_boot: + then: + - rtttl.play: 'siren:d=8,o=5,b=100:d,e,d,e,d,e,d,e' + - rtttl.stop + +output: + - platform: ledc + id: rtttl_output + pin: 1 + frequency: 1500Hz + channel: 14 + max_power: 0.5 + +rtttl: + output: rtttl_output diff --git a/tests/components/rtttl/test.esp32-c3.yaml b/tests/components/rtttl/test.esp32-c3.yaml new file mode 100644 index 0000000000..c525f417de --- /dev/null +++ b/tests/components/rtttl/test.esp32-c3.yaml @@ -0,0 +1,16 @@ +esphome: + on_boot: + then: + - rtttl.play: 'siren:d=8,o=5,b=100:d,e,d,e,d,e,d,e' + - rtttl.stop + +output: + - platform: ledc + id: rtttl_output + pin: 1 + frequency: 1500Hz + channel: 14 + max_power: 0.5 + +rtttl: + output: rtttl_output diff --git a/tests/components/rtttl/test.esp32-idf.yaml b/tests/components/rtttl/test.esp32-idf.yaml new file mode 100644 index 0000000000..367a670741 --- /dev/null +++ b/tests/components/rtttl/test.esp32-idf.yaml @@ -0,0 +1,16 @@ +esphome: + on_boot: + then: + - rtttl.play: 'siren:d=8,o=5,b=100:d,e,d,e,d,e,d,e' + - rtttl.stop + +output: + - platform: ledc + id: rtttl_output + pin: 13 + frequency: 1500Hz + channel: 14 + max_power: 0.5 + +rtttl: + output: rtttl_output diff --git a/tests/components/rtttl/test.esp32.yaml b/tests/components/rtttl/test.esp32.yaml new file mode 100644 index 0000000000..367a670741 --- /dev/null +++ b/tests/components/rtttl/test.esp32.yaml @@ -0,0 +1,16 @@ +esphome: + on_boot: + then: + - rtttl.play: 'siren:d=8,o=5,b=100:d,e,d,e,d,e,d,e' + - rtttl.stop + +output: + - platform: ledc + id: rtttl_output + pin: 13 + frequency: 1500Hz + channel: 14 + max_power: 0.5 + +rtttl: + output: rtttl_output diff --git a/tests/components/rtttl/test.esp8266.yaml b/tests/components/rtttl/test.esp8266.yaml new file mode 100644 index 0000000000..c3b87c0f72 --- /dev/null +++ b/tests/components/rtttl/test.esp8266.yaml @@ -0,0 +1,15 @@ +esphome: + on_boot: + then: + - rtttl.play: 'siren:d=8,o=5,b=100:d,e,d,e,d,e,d,e' + - rtttl.stop + +output: + - platform: esp8266_pwm + id: rtttl_output + pin: 13 + frequency: 1500Hz + max_power: 0.5 + +rtttl: + output: rtttl_output diff --git a/tests/components/rtttl/test.rp2040.yaml b/tests/components/rtttl/test.rp2040.yaml new file mode 100644 index 0000000000..ea240aa34d --- /dev/null +++ b/tests/components/rtttl/test.rp2040.yaml @@ -0,0 +1,15 @@ +esphome: + on_boot: + then: + - rtttl.play: 'siren:d=8,o=5,b=100:d,e,d,e,d,e,d,e' + - rtttl.stop + +output: + - platform: rp2040_pwm + id: rtttl_output + pin: 3 + frequency: 1500Hz + max_power: 0.5 + +rtttl: + output: rtttl_output diff --git a/tests/components/ruuvi_ble/test.esp32-c3-idf.yaml b/tests/components/ruuvi_ble/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..1f155fd8e1 --- /dev/null +++ b/tests/components/ruuvi_ble/test.esp32-c3-idf.yaml @@ -0,0 +1,3 @@ +esp32_ble_tracker: + +ruuvi_ble: diff --git a/tests/components/ruuvi_ble/test.esp32-c3.yaml b/tests/components/ruuvi_ble/test.esp32-c3.yaml new file mode 100644 index 0000000000..1f155fd8e1 --- /dev/null +++ b/tests/components/ruuvi_ble/test.esp32-c3.yaml @@ -0,0 +1,3 @@ +esp32_ble_tracker: + +ruuvi_ble: diff --git a/tests/components/ruuvi_ble/test.esp32-idf.yaml b/tests/components/ruuvi_ble/test.esp32-idf.yaml new file mode 100644 index 0000000000..1f155fd8e1 --- /dev/null +++ b/tests/components/ruuvi_ble/test.esp32-idf.yaml @@ -0,0 +1,3 @@ +esp32_ble_tracker: + +ruuvi_ble: diff --git a/tests/components/ruuvi_ble/test.esp32.yaml b/tests/components/ruuvi_ble/test.esp32.yaml new file mode 100644 index 0000000000..1f155fd8e1 --- /dev/null +++ b/tests/components/ruuvi_ble/test.esp32.yaml @@ -0,0 +1,3 @@ +esp32_ble_tracker: + +ruuvi_ble: diff --git a/tests/components/ruuvitag/test.esp32-c3-idf.yaml b/tests/components/ruuvitag/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..7990617710 --- /dev/null +++ b/tests/components/ruuvitag/test.esp32-c3-idf.yaml @@ -0,0 +1,27 @@ +esp32_ble_tracker: + +sensor: + - platform: ruuvitag + mac_address: FF:56:D3:2F:7D:E8 + humidity: + name: RuuviTag Humidity + temperature: + name: RuuviTag Temperature + pressure: + name: RuuviTag Pressure + acceleration: + name: RuuviTag Acceleration + acceleration_x: + name: RuuviTag Acceleration X + acceleration_y: + name: RuuviTag Acceleration Y + acceleration_z: + name: RuuviTag Acceleration Z + battery_voltage: + name: RuuviTag Battery Voltage + tx_power: + name: RuuviTag TX Power + movement_counter: + name: RuuviTag Movement Counter + measurement_sequence_number: + name: RuuviTag Measurement Sequence Number diff --git a/tests/components/ruuvitag/test.esp32-c3.yaml b/tests/components/ruuvitag/test.esp32-c3.yaml new file mode 100644 index 0000000000..7990617710 --- /dev/null +++ b/tests/components/ruuvitag/test.esp32-c3.yaml @@ -0,0 +1,27 @@ +esp32_ble_tracker: + +sensor: + - platform: ruuvitag + mac_address: FF:56:D3:2F:7D:E8 + humidity: + name: RuuviTag Humidity + temperature: + name: RuuviTag Temperature + pressure: + name: RuuviTag Pressure + acceleration: + name: RuuviTag Acceleration + acceleration_x: + name: RuuviTag Acceleration X + acceleration_y: + name: RuuviTag Acceleration Y + acceleration_z: + name: RuuviTag Acceleration Z + battery_voltage: + name: RuuviTag Battery Voltage + tx_power: + name: RuuviTag TX Power + movement_counter: + name: RuuviTag Movement Counter + measurement_sequence_number: + name: RuuviTag Measurement Sequence Number diff --git a/tests/components/ruuvitag/test.esp32-idf.yaml b/tests/components/ruuvitag/test.esp32-idf.yaml new file mode 100644 index 0000000000..7990617710 --- /dev/null +++ b/tests/components/ruuvitag/test.esp32-idf.yaml @@ -0,0 +1,27 @@ +esp32_ble_tracker: + +sensor: + - platform: ruuvitag + mac_address: FF:56:D3:2F:7D:E8 + humidity: + name: RuuviTag Humidity + temperature: + name: RuuviTag Temperature + pressure: + name: RuuviTag Pressure + acceleration: + name: RuuviTag Acceleration + acceleration_x: + name: RuuviTag Acceleration X + acceleration_y: + name: RuuviTag Acceleration Y + acceleration_z: + name: RuuviTag Acceleration Z + battery_voltage: + name: RuuviTag Battery Voltage + tx_power: + name: RuuviTag TX Power + movement_counter: + name: RuuviTag Movement Counter + measurement_sequence_number: + name: RuuviTag Measurement Sequence Number diff --git a/tests/components/ruuvitag/test.esp32.yaml b/tests/components/ruuvitag/test.esp32.yaml new file mode 100644 index 0000000000..7990617710 --- /dev/null +++ b/tests/components/ruuvitag/test.esp32.yaml @@ -0,0 +1,27 @@ +esp32_ble_tracker: + +sensor: + - platform: ruuvitag + mac_address: FF:56:D3:2F:7D:E8 + humidity: + name: RuuviTag Humidity + temperature: + name: RuuviTag Temperature + pressure: + name: RuuviTag Pressure + acceleration: + name: RuuviTag Acceleration + acceleration_x: + name: RuuviTag Acceleration X + acceleration_y: + name: RuuviTag Acceleration Y + acceleration_z: + name: RuuviTag Acceleration Z + battery_voltage: + name: RuuviTag Battery Voltage + tx_power: + name: RuuviTag TX Power + movement_counter: + name: RuuviTag Movement Counter + measurement_sequence_number: + name: RuuviTag Measurement Sequence Number From 8cb809d84de843a5866760ccb05ba7d5a266347f Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 23 Apr 2024 17:22:14 +1200 Subject: [PATCH 1308/2101] [sn74hc595] Enforce type field to distinguish gpio vs spi mode (#6609) --- esphome/components/sn74hc595/__init__.py | 69 +++++++++---------- .../sn74hc595/test.esp32-c3-idf.yaml | 27 ++++++++ tests/components/sn74hc595/test.esp32-c3.yaml | 27 ++++++++ .../components/sn74hc595/test.esp32-idf.yaml | 27 ++++++++ tests/components/sn74hc595/test.esp32.yaml | 27 ++++++++ tests/components/sn74hc595/test.esp8266.yaml | 27 ++++++++ tests/components/sn74hc595/test.rp2040.yaml | 27 ++++++++ tests/test1.yaml | 1 + 8 files changed, 197 insertions(+), 35 deletions(-) create mode 100644 tests/components/sn74hc595/test.esp32-c3-idf.yaml create mode 100644 tests/components/sn74hc595/test.esp32-c3.yaml create mode 100644 tests/components/sn74hc595/test.esp32-idf.yaml create mode 100644 tests/components/sn74hc595/test.esp32.yaml create mode 100644 tests/components/sn74hc595/test.esp8266.yaml create mode 100644 tests/components/sn74hc595/test.rp2040.yaml diff --git a/esphome/components/sn74hc595/__init__.py b/esphome/components/sn74hc595/__init__.py index 11a6747656..e0cd5e70ad 100644 --- a/esphome/components/sn74hc595/__init__.py +++ b/esphome/components/sn74hc595/__init__.py @@ -4,14 +4,13 @@ from esphome import pins from esphome.components import spi from esphome.const import ( CONF_ID, - CONF_SPI_ID, CONF_NUMBER, CONF_INVERTED, CONF_DATA_PIN, CONF_CLOCK_PIN, CONF_OUTPUT, + CONF_TYPE, ) -from esphome.core import EsphomeError MULTI_CONF = True @@ -34,53 +33,53 @@ CONF_LATCH_PIN = "latch_pin" CONF_OE_PIN = "oe_pin" CONF_SR_COUNT = "sr_count" -CONFIG_SCHEMA = cv.Any( - cv.Schema( - { - cv.Required(CONF_ID): cv.declare_id(SN74HC595GPIOComponent), - cv.Required(CONF_DATA_PIN): pins.gpio_output_pin_schema, - cv.Required(CONF_CLOCK_PIN): pins.gpio_output_pin_schema, - cv.Required(CONF_LATCH_PIN): pins.gpio_output_pin_schema, - cv.Optional(CONF_OE_PIN): pins.gpio_output_pin_schema, - cv.Optional(CONF_SR_COUNT, default=1): cv.int_range(min=1, max=256), - } - ).extend(cv.COMPONENT_SCHEMA), - cv.Schema( - { - cv.Required(CONF_ID): cv.declare_id(SN74HC595SPIComponent), - cv.Required(CONF_LATCH_PIN): pins.gpio_output_pin_schema, - cv.Optional(CONF_OE_PIN): pins.gpio_output_pin_schema, - cv.Optional(CONF_SR_COUNT, default=1): cv.int_range(min=1, max=256), - } - ) - .extend(cv.COMPONENT_SCHEMA) - .extend(spi.spi_device_schema(cs_pin_required=False)) - .extend( - { - cv.Required(CONF_SPI_ID): cv.use_id(spi.SPIComponent), - } - ), - msg='Either "data_pin" and "clock_pin" must be set or "spi_id" must be set.', +TYPE_GPIO = "gpio" +TYPE_SPI = "spi" + +_COMMON_SCHEMA = cv.Schema( + { + cv.Required(CONF_LATCH_PIN): pins.gpio_output_pin_schema, + cv.Optional(CONF_OE_PIN): pins.gpio_output_pin_schema, + cv.Optional(CONF_SR_COUNT, default=1): cv.int_range(min=1, max=256), + } +) + +CONFIG_SCHEMA = cv.typed_schema( + { + TYPE_GPIO: _COMMON_SCHEMA.extend( + { + cv.Required(CONF_ID): cv.declare_id(SN74HC595GPIOComponent), + cv.Required(CONF_DATA_PIN): pins.gpio_output_pin_schema, + cv.Required(CONF_CLOCK_PIN): pins.gpio_output_pin_schema, + } + ).extend(cv.COMPONENT_SCHEMA), + TYPE_SPI: _COMMON_SCHEMA.extend( + { + cv.Required(CONF_ID): cv.declare_id(SN74HC595SPIComponent), + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(spi.spi_device_schema(cs_pin_required=False)), + }, + default_type=TYPE_GPIO, ) async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) - if CONF_DATA_PIN in config: + if config[CONF_TYPE] == TYPE_GPIO: data_pin = await cg.gpio_pin_expression(config[CONF_DATA_PIN]) cg.add(var.set_data_pin(data_pin)) clock_pin = await cg.gpio_pin_expression(config[CONF_CLOCK_PIN]) cg.add(var.set_clock_pin(clock_pin)) - elif CONF_SPI_ID in config: - await spi.register_spi_device(var, config) else: - raise EsphomeError("Not supported") + await spi.register_spi_device(var, config) latch_pin = await cg.gpio_pin_expression(config[CONF_LATCH_PIN]) cg.add(var.set_latch_pin(latch_pin)) - if CONF_OE_PIN in config: - oe_pin = await cg.gpio_pin_expression(config[CONF_OE_PIN]) + if oe_pin := config.get(CONF_OE_PIN): + oe_pin = await cg.gpio_pin_expression(oe_pin) cg.add(var.set_oe_pin(oe_pin)) cg.add(var.set_sr_count(config[CONF_SR_COUNT])) diff --git a/tests/components/sn74hc595/test.esp32-c3-idf.yaml b/tests/components/sn74hc595/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..9b093899d3 --- /dev/null +++ b/tests/components/sn74hc595/test.esp32-c3-idf.yaml @@ -0,0 +1,27 @@ +spi: + - id: spi_sn74hc595 + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +sn74hc595: + - id: sn74hc595_hub + clock_pin: 0 + data_pin: 1 + latch_pin: 2 + oe_pin: 3 + sr_count: 2 + - id: sn74hc595_hub_2 + latch_pin: 8 + oe_pin: 9 + spi_id: spi_sn74hc595 + type: spi + sr_count: 2 + +switch: + - platform: gpio + name: SN74HC595 Pin 0 + pin: + sn74hc595: sn74hc595_hub_2 + number: 0 + inverted: false diff --git a/tests/components/sn74hc595/test.esp32-c3.yaml b/tests/components/sn74hc595/test.esp32-c3.yaml new file mode 100644 index 0000000000..9b093899d3 --- /dev/null +++ b/tests/components/sn74hc595/test.esp32-c3.yaml @@ -0,0 +1,27 @@ +spi: + - id: spi_sn74hc595 + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +sn74hc595: + - id: sn74hc595_hub + clock_pin: 0 + data_pin: 1 + latch_pin: 2 + oe_pin: 3 + sr_count: 2 + - id: sn74hc595_hub_2 + latch_pin: 8 + oe_pin: 9 + spi_id: spi_sn74hc595 + type: spi + sr_count: 2 + +switch: + - platform: gpio + name: SN74HC595 Pin 0 + pin: + sn74hc595: sn74hc595_hub_2 + number: 0 + inverted: false diff --git a/tests/components/sn74hc595/test.esp32-idf.yaml b/tests/components/sn74hc595/test.esp32-idf.yaml new file mode 100644 index 0000000000..f695395797 --- /dev/null +++ b/tests/components/sn74hc595/test.esp32-idf.yaml @@ -0,0 +1,27 @@ +spi: + - id: spi_sn74hc595 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +sn74hc595: + - id: sn74hc595_hub + clock_pin: 12 + data_pin: 13 + latch_pin: 14 + oe_pin: 18 + sr_count: 2 + - id: sn74hc595_hub_2 + latch_pin: 21 + oe_pin: 22 + spi_id: spi_sn74hc595 + type: spi + sr_count: 2 + +switch: + - platform: gpio + name: SN74HC595 Pin 0 + pin: + sn74hc595: sn74hc595_hub_2 + number: 0 + inverted: false diff --git a/tests/components/sn74hc595/test.esp32.yaml b/tests/components/sn74hc595/test.esp32.yaml new file mode 100644 index 0000000000..f695395797 --- /dev/null +++ b/tests/components/sn74hc595/test.esp32.yaml @@ -0,0 +1,27 @@ +spi: + - id: spi_sn74hc595 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +sn74hc595: + - id: sn74hc595_hub + clock_pin: 12 + data_pin: 13 + latch_pin: 14 + oe_pin: 18 + sr_count: 2 + - id: sn74hc595_hub_2 + latch_pin: 21 + oe_pin: 22 + spi_id: spi_sn74hc595 + type: spi + sr_count: 2 + +switch: + - platform: gpio + name: SN74HC595 Pin 0 + pin: + sn74hc595: sn74hc595_hub_2 + number: 0 + inverted: false diff --git a/tests/components/sn74hc595/test.esp8266.yaml b/tests/components/sn74hc595/test.esp8266.yaml new file mode 100644 index 0000000000..64bf5d1925 --- /dev/null +++ b/tests/components/sn74hc595/test.esp8266.yaml @@ -0,0 +1,27 @@ +spi: + - id: spi_sn74hc595 + clk_pin: 14 + mosi_pin: 13 + miso_pin: 12 + +sn74hc595: + - id: sn74hc595_hub + clock_pin: 0 + data_pin: 2 + latch_pin: 4 + oe_pin: 5 + sr_count: 2 + - id: sn74hc595_hub_2 + latch_pin: 15 + oe_pin: 16 + spi_id: spi_sn74hc595 + type: spi + sr_count: 2 + +switch: + - platform: gpio + name: SN74HC595 Pin 0 + pin: + sn74hc595: sn74hc595_hub_2 + number: 0 + inverted: false diff --git a/tests/components/sn74hc595/test.rp2040.yaml b/tests/components/sn74hc595/test.rp2040.yaml new file mode 100644 index 0000000000..de8e192659 --- /dev/null +++ b/tests/components/sn74hc595/test.rp2040.yaml @@ -0,0 +1,27 @@ +spi: + - id: spi_sn74hc595 + clk_pin: 6 + mosi_pin: 5 + miso_pin: 4 + +sn74hc595: + - id: sn74hc595_hub + clock_pin: 0 + data_pin: 1 + latch_pin: 2 + oe_pin: 3 + sr_count: 2 + - id: sn74hc595_hub_2 + latch_pin: 8 + oe_pin: 9 + spi_id: spi_sn74hc595 + type: spi + sr_count: 2 + +switch: + - platform: gpio + name: SN74HC595 Pin 0 + pin: + sn74hc595: sn74hc595_hub_2 + number: 0 + inverted: false diff --git a/tests/test1.yaml b/tests/test1.yaml index c8ae9691c2..09994afa42 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -3996,6 +3996,7 @@ sn74hc595: number: GPIO32 sr_count: 2 spi_id: spi_bus + type: spi rtttl: output: gpio_19 From 06d3829b45911952a01c47b8a3961623ff1dab0b Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Mon, 22 Apr 2024 23:43:11 -0700 Subject: [PATCH 1309/2101] allow defaults with no include vars (#6613) --- esphome/yaml_util.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/esphome/yaml_util.py b/esphome/yaml_util.py index c7aa78201f..06bfd8b217 100644 --- a/esphome/yaml_util.py +++ b/esphome/yaml_util.py @@ -321,8 +321,9 @@ class ESPHomeLoaderMixin: file, vars = node.value, None result = _load_yaml_internal(self._rel_path(file)) - if vars: - result = substitute_vars(result, vars) + if not vars: + vars = {} + result = substitute_vars(result, vars) return result @_add_data_ref From b1839702f914621a90cc4c30644c449d32e006f1 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 23 Apr 2024 21:19:10 +1200 Subject: [PATCH 1310/2101] [tests] Run yaml tests in groups if over 100 to run (#6612) --- .github/workflows/ci.yml | 81 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 75 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 15f0904df4..fd7a45ff50 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -398,7 +398,8 @@ jobs: - common if: github.event_name == 'pull_request' outputs: - matrix: ${{ steps.set-matrix.outputs.matrix }} + components: ${{ steps.list-components.outputs.components }} + count: ${{ steps.list-components.outputs.count }} steps: - name: Check out code from GitHub uses: actions/checkout@v4.1.1 @@ -419,10 +420,18 @@ jobs: python-version: ${{ env.DEFAULT_PYTHON }} cache-key: ${{ needs.common.outputs.cache-key }} - name: Find changed components - id: set-matrix + id: list-components run: | . venv/bin/activate - echo "matrix=$(script/list-components.py --changed --branch ${{ steps.target-branch.outputs.branch }} | jq -R -s -c 'split("\n")[:-1]')" >> $GITHUB_OUTPUT + components=$(script/list-components.py --changed --branch ${{ steps.target-branch.outputs.branch }}) + output_components=$(echo "$components" | jq -R -s -c 'split("\n")[:-1] | map(select(length > 0))') + count=$(echo "$output_components" | jq length) + + echo "components=$output_components" >> $GITHUB_OUTPUT + echo "count=$count" >> $GITHUB_OUTPUT + + echo "$count Components:" + echo "$output_components" | jq test-build-components: name: Component test ${{ matrix.file }} @@ -430,12 +439,12 @@ jobs: needs: - common - list-components - if: ${{ github.event_name == 'pull_request' && needs.list-components.outputs.matrix != '[]' && needs.list-components.outputs.matrix != '' }} + if: github.event_name == 'pull_request' && fromJSON(needs.list-components.outputs.count) > 0 && fromJSON(needs.list-components.outputs.count) < 100 strategy: fail-fast: false max-parallel: 2 matrix: - file: ${{ fromJson(needs.list-components.outputs.matrix) }} + file: ${{ fromJson(needs.list-components.outputs.components) }} steps: - name: Install libsodium run: sudo apt-get install libsodium-dev @@ -456,6 +465,64 @@ jobs: . venv/bin/activate ./script/test_build_components -e compile -c ${{ matrix.file }} + test-build-components-splitter: + name: Split components for testing into 20 groups maximum + runs-on: ubuntu-latest + needs: + - common + - list-components + if: github.event_name == 'pull_request' && fromJSON(needs.list-components.outputs.count) >= 100 + outputs: + matrix: ${{ steps.split.outputs.components }} + steps: + - name: Check out code from GitHub + uses: actions/checkout@v4.1.1 + - name: Split components into 20 groups + id: split + run: | + components=$(echo '${{ needs.list-components.outputs.components }}' | jq -c '.[]' | shuf | jq -s -c '[_nwise(20) | join(" ")]') + echo "components=$components" >> $GITHUB_OUTPUT + + test-build-components-split: + name: Test split components + runs-on: ubuntu-latest + needs: + - common + - list-components + - test-build-components-splitter + if: github.event_name == 'pull_request' && fromJSON(needs.list-components.outputs.count) >= 100 + strategy: + fail-fast: false + max-parallel: 4 + matrix: + components: ${{ fromJson(needs.test-build-components-splitter.outputs.matrix) }} + steps: + - name: List components + run: echo ${{ matrix.components }} + + - name: Install libsodium + run: sudo apt-get install libsodium-dev + + - name: Check out code from GitHub + uses: actions/checkout@v4.1.1 + - name: Restore Python + uses: ./.github/actions/restore-python + with: + python-version: ${{ env.DEFAULT_PYTHON }} + cache-key: ${{ needs.common.outputs.cache-key }} + - name: Validate config + run: | + . venv/bin/activate + for component in ${{ matrix.components }}; do + ./script/test_build_components -e config -c $component + done + - name: Compile config + run: | + . venv/bin/activate + for component in ${{ matrix.components }}; do + ./script/test_build_components -e compile -c $component + done + ci-status: name: CI Status runs-on: ubuntu-latest @@ -470,8 +537,10 @@ jobs: - pyupgrade - compile-tests - clang-tidy - - test-build-components - list-components + - test-build-components + - test-build-components-splitter + - test-build-components-split if: always() steps: - name: Success From 18149bc2762b284c17a0a0030691fa7566a9d1c4 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Tue, 23 Apr 2024 04:36:30 -0500 Subject: [PATCH 1311/2101] Add some components to the new testing framework (I) (#6185) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- tests/components/i2c/test.esp32-c3-idf.yaml | 4 ++ tests/components/i2c/test.esp32-c3.yaml | 4 ++ tests/components/i2c/test.esp32-idf.yaml | 4 ++ tests/components/i2c/test.esp32.yaml | 4 ++ tests/components/i2c/test.esp8266.yaml | 4 ++ tests/components/i2c/test.rp2040.yaml | 4 ++ .../i2s_audio/test.esp32-c3-idf.yaml | 4 ++ tests/components/i2s_audio/test.esp32-c3.yaml | 4 ++ .../components/i2s_audio/test.esp32-idf.yaml | 4 ++ tests/components/i2s_audio/test.esp32.yaml | 4 ++ .../components/iaqcore/test.esp32-c3-idf.yaml | 11 ++++ tests/components/iaqcore/test.esp32-c3.yaml | 11 ++++ tests/components/iaqcore/test.esp32-idf.yaml | 11 ++++ tests/components/iaqcore/test.esp32.yaml | 11 ++++ tests/components/iaqcore/test.esp8266.yaml | 11 ++++ tests/components/iaqcore/test.rp2040.yaml | 11 ++++ .../components/ili9xxx/test.esp32-c3-idf.yaml | 35 +++++++++++ tests/components/ili9xxx/test.esp32-c3.yaml | 35 +++++++++++ tests/components/ili9xxx/test.esp32-idf.yaml | 35 +++++++++++ tests/components/ili9xxx/test.esp32.yaml | 37 ++++++++--- tests/components/ili9xxx/test.esp8266.yaml | 35 +++++++++++ tests/components/ili9xxx/test.rp2040.yaml | 35 +++++++++++ tests/components/image/test.esp32-c3-idf.yaml | 52 ++++++++++++++++ tests/components/image/test.esp32-c3.yaml | 52 ++++++++++++++++ tests/components/image/test.esp32-idf.yaml | 52 ++++++++++++++++ tests/components/image/test.esp32.yaml | 52 ++++++++++++++++ tests/components/image/test.esp8266.yaml | 52 ++++++++++++++++ tests/components/image/test.rp2040.yaml | 52 ++++++++++++++++ .../improv_serial/test.esp32-c3-idf.yaml | 5 ++ .../improv_serial/test.esp32-c3.yaml | 5 ++ .../improv_serial/test.esp32-idf.yaml | 5 ++ .../components/improv_serial/test.esp32.yaml | 5 ++ .../improv_serial/test.esp8266.yaml | 5 ++ .../components/improv_serial/test.rp2040.yaml | 5 ++ .../components/ina219/test.esp32-c3-idf.yaml | 20 ++++++ tests/components/ina219/test.esp32-c3.yaml | 20 ++++++ tests/components/ina219/test.esp32-idf.yaml | 20 ++++++ tests/components/ina219/test.esp32.yaml | 20 ++++++ tests/components/ina219/test.esp8266.yaml | 20 ++++++ tests/components/ina219/test.rp2040.yaml | 20 ++++++ .../components/ina226/test.esp32-c3-idf.yaml | 19 ++++++ tests/components/ina226/test.esp32-c3.yaml | 19 ++++++ tests/components/ina226/test.esp32-idf.yaml | 19 ++++++ tests/components/ina226/test.esp32.yaml | 19 ++++++ tests/components/ina226/test.esp8266.yaml | 19 ++++++ tests/components/ina226/test.rp2040.yaml | 19 ++++++ .../components/ina260/test.esp32-c3-idf.yaml | 15 +++++ tests/components/ina260/test.esp32-c3.yaml | 15 +++++ tests/components/ina260/test.esp32-idf.yaml | 15 +++++ tests/components/ina260/test.esp32.yaml | 15 +++++ tests/components/ina260/test.esp8266.yaml | 15 +++++ tests/components/ina260/test.rp2040.yaml | 15 +++++ .../components/ina3221/test.esp32-c3-idf.yaml | 19 ++++++ tests/components/ina3221/test.esp32-c3.yaml | 19 ++++++ tests/components/ina3221/test.esp32-idf.yaml | 19 ++++++ tests/components/ina3221/test.esp32.yaml | 19 ++++++ tests/components/ina3221/test.esp8266.yaml | 19 ++++++ tests/components/ina3221/test.rp2040.yaml | 19 ++++++ .../test.esp32-c3-idf.yaml | 11 ++++ .../inkbird_ibsth1_mini/test.esp32-c3.yaml | 11 ++++ .../inkbird_ibsth1_mini/test.esp32-idf.yaml | 11 ++++ .../inkbird_ibsth1_mini/test.esp32.yaml | 11 ++++ tests/components/inkplate6/test.esp32.yaml | 62 +++++++++++++++++++ .../components/integration/test.esp32-c3.yaml | 9 +++ .../integration/test.esp32-idf.yaml | 9 +++ .../components/integration/test.esp32-s2.yaml | 9 +++ .../components/integration/test.esp32-s3.yaml | 9 +++ tests/components/integration/test.esp32.yaml | 9 +++ .../components/integration/test.esp8266.yaml | 8 +++ tests/components/integration/test.rp2040.yaml | 8 +++ .../internal_temperature/test.esp32-c3.yaml | 2 +- .../internal_temperature/test.esp32-idf.yaml | 2 +- .../internal_temperature/test.esp32-s2.yaml | 3 + .../internal_temperature/test.esp32-s3.yaml | 7 +++ .../internal_temperature/test.esp32.yaml | 2 +- .../internal_temperature/test.rp2040.yaml | 2 +- .../interval/test.esp32-c3-idf.yaml | 4 ++ tests/components/interval/test.esp32-c3.yaml | 4 ++ tests/components/interval/test.esp32-idf.yaml | 4 ++ tests/components/interval/test.esp32.yaml | 4 ++ tests/components/interval/test.esp8266.yaml | 4 ++ tests/components/interval/test.rp2040.yaml | 4 ++ 82 files changed, 1296 insertions(+), 11 deletions(-) create mode 100644 tests/components/i2c/test.esp32-c3-idf.yaml create mode 100644 tests/components/i2c/test.esp32-c3.yaml create mode 100644 tests/components/i2c/test.esp32-idf.yaml create mode 100644 tests/components/i2c/test.esp32.yaml create mode 100644 tests/components/i2c/test.esp8266.yaml create mode 100644 tests/components/i2c/test.rp2040.yaml create mode 100644 tests/components/i2s_audio/test.esp32-c3-idf.yaml create mode 100644 tests/components/i2s_audio/test.esp32-c3.yaml create mode 100644 tests/components/i2s_audio/test.esp32-idf.yaml create mode 100644 tests/components/i2s_audio/test.esp32.yaml create mode 100644 tests/components/iaqcore/test.esp32-c3-idf.yaml create mode 100644 tests/components/iaqcore/test.esp32-c3.yaml create mode 100644 tests/components/iaqcore/test.esp32-idf.yaml create mode 100644 tests/components/iaqcore/test.esp32.yaml create mode 100644 tests/components/iaqcore/test.esp8266.yaml create mode 100644 tests/components/iaqcore/test.rp2040.yaml create mode 100644 tests/components/ili9xxx/test.esp32-c3-idf.yaml create mode 100644 tests/components/ili9xxx/test.esp32-c3.yaml create mode 100644 tests/components/ili9xxx/test.esp32-idf.yaml create mode 100644 tests/components/ili9xxx/test.esp8266.yaml create mode 100644 tests/components/ili9xxx/test.rp2040.yaml create mode 100644 tests/components/image/test.esp32-c3-idf.yaml create mode 100644 tests/components/image/test.esp32-c3.yaml create mode 100644 tests/components/image/test.esp32-idf.yaml create mode 100644 tests/components/image/test.esp32.yaml create mode 100644 tests/components/image/test.esp8266.yaml create mode 100644 tests/components/image/test.rp2040.yaml create mode 100644 tests/components/improv_serial/test.esp32-c3-idf.yaml create mode 100644 tests/components/improv_serial/test.esp32-c3.yaml create mode 100644 tests/components/improv_serial/test.esp32-idf.yaml create mode 100644 tests/components/improv_serial/test.esp32.yaml create mode 100644 tests/components/improv_serial/test.esp8266.yaml create mode 100644 tests/components/improv_serial/test.rp2040.yaml create mode 100644 tests/components/ina219/test.esp32-c3-idf.yaml create mode 100644 tests/components/ina219/test.esp32-c3.yaml create mode 100644 tests/components/ina219/test.esp32-idf.yaml create mode 100644 tests/components/ina219/test.esp32.yaml create mode 100644 tests/components/ina219/test.esp8266.yaml create mode 100644 tests/components/ina219/test.rp2040.yaml create mode 100644 tests/components/ina226/test.esp32-c3-idf.yaml create mode 100644 tests/components/ina226/test.esp32-c3.yaml create mode 100644 tests/components/ina226/test.esp32-idf.yaml create mode 100644 tests/components/ina226/test.esp32.yaml create mode 100644 tests/components/ina226/test.esp8266.yaml create mode 100644 tests/components/ina226/test.rp2040.yaml create mode 100644 tests/components/ina260/test.esp32-c3-idf.yaml create mode 100644 tests/components/ina260/test.esp32-c3.yaml create mode 100644 tests/components/ina260/test.esp32-idf.yaml create mode 100644 tests/components/ina260/test.esp32.yaml create mode 100644 tests/components/ina260/test.esp8266.yaml create mode 100644 tests/components/ina260/test.rp2040.yaml create mode 100644 tests/components/ina3221/test.esp32-c3-idf.yaml create mode 100644 tests/components/ina3221/test.esp32-c3.yaml create mode 100644 tests/components/ina3221/test.esp32-idf.yaml create mode 100644 tests/components/ina3221/test.esp32.yaml create mode 100644 tests/components/ina3221/test.esp8266.yaml create mode 100644 tests/components/ina3221/test.rp2040.yaml create mode 100644 tests/components/inkbird_ibsth1_mini/test.esp32-c3-idf.yaml create mode 100644 tests/components/inkbird_ibsth1_mini/test.esp32-c3.yaml create mode 100644 tests/components/inkbird_ibsth1_mini/test.esp32-idf.yaml create mode 100644 tests/components/inkbird_ibsth1_mini/test.esp32.yaml create mode 100644 tests/components/inkplate6/test.esp32.yaml create mode 100644 tests/components/integration/test.esp32-c3.yaml create mode 100644 tests/components/integration/test.esp32-idf.yaml create mode 100644 tests/components/integration/test.esp32-s2.yaml create mode 100644 tests/components/integration/test.esp32-s3.yaml create mode 100644 tests/components/integration/test.esp32.yaml create mode 100644 tests/components/integration/test.esp8266.yaml create mode 100644 tests/components/integration/test.rp2040.yaml create mode 100644 tests/components/internal_temperature/test.esp32-s2.yaml create mode 100644 tests/components/internal_temperature/test.esp32-s3.yaml create mode 100644 tests/components/interval/test.esp32-c3-idf.yaml create mode 100644 tests/components/interval/test.esp32-c3.yaml create mode 100644 tests/components/interval/test.esp32-idf.yaml create mode 100644 tests/components/interval/test.esp32.yaml create mode 100644 tests/components/interval/test.esp8266.yaml create mode 100644 tests/components/interval/test.rp2040.yaml diff --git a/tests/components/i2c/test.esp32-c3-idf.yaml b/tests/components/i2c/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..a881438faa --- /dev/null +++ b/tests/components/i2c/test.esp32-c3-idf.yaml @@ -0,0 +1,4 @@ +i2c: + - id: i2c_i2c + scl: 5 + sda: 4 diff --git a/tests/components/i2c/test.esp32-c3.yaml b/tests/components/i2c/test.esp32-c3.yaml new file mode 100644 index 0000000000..a881438faa --- /dev/null +++ b/tests/components/i2c/test.esp32-c3.yaml @@ -0,0 +1,4 @@ +i2c: + - id: i2c_i2c + scl: 5 + sda: 4 diff --git a/tests/components/i2c/test.esp32-idf.yaml b/tests/components/i2c/test.esp32-idf.yaml new file mode 100644 index 0000000000..19114a9e5d --- /dev/null +++ b/tests/components/i2c/test.esp32-idf.yaml @@ -0,0 +1,4 @@ +i2c: + - id: i2c_i2c + scl: 16 + sda: 17 diff --git a/tests/components/i2c/test.esp32.yaml b/tests/components/i2c/test.esp32.yaml new file mode 100644 index 0000000000..19114a9e5d --- /dev/null +++ b/tests/components/i2c/test.esp32.yaml @@ -0,0 +1,4 @@ +i2c: + - id: i2c_i2c + scl: 16 + sda: 17 diff --git a/tests/components/i2c/test.esp8266.yaml b/tests/components/i2c/test.esp8266.yaml new file mode 100644 index 0000000000..a881438faa --- /dev/null +++ b/tests/components/i2c/test.esp8266.yaml @@ -0,0 +1,4 @@ +i2c: + - id: i2c_i2c + scl: 5 + sda: 4 diff --git a/tests/components/i2c/test.rp2040.yaml b/tests/components/i2c/test.rp2040.yaml new file mode 100644 index 0000000000..a881438faa --- /dev/null +++ b/tests/components/i2c/test.rp2040.yaml @@ -0,0 +1,4 @@ +i2c: + - id: i2c_i2c + scl: 5 + sda: 4 diff --git a/tests/components/i2s_audio/test.esp32-c3-idf.yaml b/tests/components/i2s_audio/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..08cd56b1a7 --- /dev/null +++ b/tests/components/i2s_audio/test.esp32-c3-idf.yaml @@ -0,0 +1,4 @@ +i2s_audio: + i2s_bclk_pin: 7 + i2s_lrclk_pin: 6 + i2s_mclk_pin: 5 diff --git a/tests/components/i2s_audio/test.esp32-c3.yaml b/tests/components/i2s_audio/test.esp32-c3.yaml new file mode 100644 index 0000000000..08cd56b1a7 --- /dev/null +++ b/tests/components/i2s_audio/test.esp32-c3.yaml @@ -0,0 +1,4 @@ +i2s_audio: + i2s_bclk_pin: 7 + i2s_lrclk_pin: 6 + i2s_mclk_pin: 5 diff --git a/tests/components/i2s_audio/test.esp32-idf.yaml b/tests/components/i2s_audio/test.esp32-idf.yaml new file mode 100644 index 0000000000..938dd5c25f --- /dev/null +++ b/tests/components/i2s_audio/test.esp32-idf.yaml @@ -0,0 +1,4 @@ +i2s_audio: + i2s_bclk_pin: 27 + i2s_lrclk_pin: 26 + i2s_mclk_pin: 25 diff --git a/tests/components/i2s_audio/test.esp32.yaml b/tests/components/i2s_audio/test.esp32.yaml new file mode 100644 index 0000000000..938dd5c25f --- /dev/null +++ b/tests/components/i2s_audio/test.esp32.yaml @@ -0,0 +1,4 @@ +i2s_audio: + i2s_bclk_pin: 27 + i2s_lrclk_pin: 26 + i2s_mclk_pin: 25 diff --git a/tests/components/iaqcore/test.esp32-c3-idf.yaml b/tests/components/iaqcore/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..a1809dffd7 --- /dev/null +++ b/tests/components/iaqcore/test.esp32-c3-idf.yaml @@ -0,0 +1,11 @@ +i2c: + - id: i2c_iaqcore + scl: 5 + sda: 4 + +sensor: + - platform: iaqcore + co2: + name: iAQ Core CO2 Sensor + tvoc: + name: iAQ Core TVOC Sensor diff --git a/tests/components/iaqcore/test.esp32-c3.yaml b/tests/components/iaqcore/test.esp32-c3.yaml new file mode 100644 index 0000000000..a1809dffd7 --- /dev/null +++ b/tests/components/iaqcore/test.esp32-c3.yaml @@ -0,0 +1,11 @@ +i2c: + - id: i2c_iaqcore + scl: 5 + sda: 4 + +sensor: + - platform: iaqcore + co2: + name: iAQ Core CO2 Sensor + tvoc: + name: iAQ Core TVOC Sensor diff --git a/tests/components/iaqcore/test.esp32-idf.yaml b/tests/components/iaqcore/test.esp32-idf.yaml new file mode 100644 index 0000000000..26b01dadf9 --- /dev/null +++ b/tests/components/iaqcore/test.esp32-idf.yaml @@ -0,0 +1,11 @@ +i2c: + - id: i2c_iaqcore + scl: 16 + sda: 17 + +sensor: + - platform: iaqcore + co2: + name: iAQ Core CO2 Sensor + tvoc: + name: iAQ Core TVOC Sensor diff --git a/tests/components/iaqcore/test.esp32.yaml b/tests/components/iaqcore/test.esp32.yaml new file mode 100644 index 0000000000..26b01dadf9 --- /dev/null +++ b/tests/components/iaqcore/test.esp32.yaml @@ -0,0 +1,11 @@ +i2c: + - id: i2c_iaqcore + scl: 16 + sda: 17 + +sensor: + - platform: iaqcore + co2: + name: iAQ Core CO2 Sensor + tvoc: + name: iAQ Core TVOC Sensor diff --git a/tests/components/iaqcore/test.esp8266.yaml b/tests/components/iaqcore/test.esp8266.yaml new file mode 100644 index 0000000000..a1809dffd7 --- /dev/null +++ b/tests/components/iaqcore/test.esp8266.yaml @@ -0,0 +1,11 @@ +i2c: + - id: i2c_iaqcore + scl: 5 + sda: 4 + +sensor: + - platform: iaqcore + co2: + name: iAQ Core CO2 Sensor + tvoc: + name: iAQ Core TVOC Sensor diff --git a/tests/components/iaqcore/test.rp2040.yaml b/tests/components/iaqcore/test.rp2040.yaml new file mode 100644 index 0000000000..a1809dffd7 --- /dev/null +++ b/tests/components/iaqcore/test.rp2040.yaml @@ -0,0 +1,11 @@ +i2c: + - id: i2c_iaqcore + scl: 5 + sda: 4 + +sensor: + - platform: iaqcore + co2: + name: iAQ Core CO2 Sensor + tvoc: + name: iAQ Core TVOC Sensor diff --git a/tests/components/ili9xxx/test.esp32-c3-idf.yaml b/tests/components/ili9xxx/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..9526ae1f6b --- /dev/null +++ b/tests/components/ili9xxx/test.esp32-c3-idf.yaml @@ -0,0 +1,35 @@ +spi: + - id: spi_main_lcd + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +display: + - platform: ili9xxx + invert_colors: true + dimensions: 320x240 + transform: + swap_xy: true + mirror_x: true + mirror_y: false + model: TFT 2.4 + color_palette: GRAYSCALE + cs_pin: 8 + dc_pin: 9 + reset_pin: 10 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - platform: ili9xxx + dimensions: + width: 320 + height: 240 + offset_width: 20 + offset_height: 10 + model: TFT 2.4 + cs_pin: 2 + dc_pin: 3 + reset_pin: 4 + auto_clear_enabled: false + rotation: 90 + lambda: |- + it.fill(Color::WHITE); diff --git a/tests/components/ili9xxx/test.esp32-c3.yaml b/tests/components/ili9xxx/test.esp32-c3.yaml new file mode 100644 index 0000000000..9526ae1f6b --- /dev/null +++ b/tests/components/ili9xxx/test.esp32-c3.yaml @@ -0,0 +1,35 @@ +spi: + - id: spi_main_lcd + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +display: + - platform: ili9xxx + invert_colors: true + dimensions: 320x240 + transform: + swap_xy: true + mirror_x: true + mirror_y: false + model: TFT 2.4 + color_palette: GRAYSCALE + cs_pin: 8 + dc_pin: 9 + reset_pin: 10 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - platform: ili9xxx + dimensions: + width: 320 + height: 240 + offset_width: 20 + offset_height: 10 + model: TFT 2.4 + cs_pin: 2 + dc_pin: 3 + reset_pin: 4 + auto_clear_enabled: false + rotation: 90 + lambda: |- + it.fill(Color::WHITE); diff --git a/tests/components/ili9xxx/test.esp32-idf.yaml b/tests/components/ili9xxx/test.esp32-idf.yaml new file mode 100644 index 0000000000..0d7bda8ac6 --- /dev/null +++ b/tests/components/ili9xxx/test.esp32-idf.yaml @@ -0,0 +1,35 @@ +spi: + - id: spi_main_lcd + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +display: + - platform: ili9xxx + invert_colors: true + dimensions: 320x240 + transform: + swap_xy: true + mirror_x: true + mirror_y: false + model: TFT 2.4 + color_palette: GRAYSCALE + cs_pin: 12 + dc_pin: 13 + reset_pin: 14 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - platform: ili9xxx + dimensions: + width: 320 + height: 240 + offset_width: 20 + offset_height: 10 + model: TFT 2.4 + cs_pin: 25 + dc_pin: 26 + reset_pin: 27 + auto_clear_enabled: false + rotation: 90 + lambda: |- + it.fill(Color::WHITE); diff --git a/tests/components/ili9xxx/test.esp32.yaml b/tests/components/ili9xxx/test.esp32.yaml index 1095d565d2..ecee21686e 100644 --- a/tests/components/ili9xxx/test.esp32.yaml +++ b/tests/components/ili9xxx/test.esp32.yaml @@ -1,11 +1,34 @@ spi: - mosi_pin: GPIO23 - clk_pin: GPIO18 + - id: spi_main_lcd + clk_pin: 16 + mosi_pin: 17 display: - platform: ili9xxx - model: gc9a01a - id: gca901_display - cs_pin: GPIO5 - dc_pin: GPIO22 - reset_pin: GPIO21 + invert_colors: true + dimensions: 320x240 + transform: + swap_xy: true + mirror_x: true + mirror_y: false + model: TFT 2.4 + color_palette: GRAYSCALE + cs_pin: 12 + dc_pin: 13 + reset_pin: 14 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - platform: ili9xxx + dimensions: + width: 320 + height: 240 + offset_width: 20 + offset_height: 10 + model: TFT 2.4 + cs_pin: 25 + dc_pin: 26 + reset_pin: 27 + auto_clear_enabled: false + rotation: 90 + lambda: |- + it.fill(Color::WHITE); diff --git a/tests/components/ili9xxx/test.esp8266.yaml b/tests/components/ili9xxx/test.esp8266.yaml new file mode 100644 index 0000000000..0791c25aca --- /dev/null +++ b/tests/components/ili9xxx/test.esp8266.yaml @@ -0,0 +1,35 @@ +spi: + - id: spi_main_lcd + clk_pin: 14 + mosi_pin: 13 + miso_pin: 12 + +display: + - platform: ili9xxx + invert_colors: true + dimensions: 320x240 + transform: + swap_xy: true + mirror_x: true + mirror_y: false + model: TFT 2.4 + color_palette: GRAYSCALE + cs_pin: 5 + dc_pin: 15 + reset_pin: 16 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - platform: ili9xxx + dimensions: + width: 320 + height: 240 + offset_width: 20 + offset_height: 10 + model: TFT 2.4 + cs_pin: 2 + dc_pin: 4 + reset_pin: 0 + auto_clear_enabled: false + rotation: 90 + lambda: |- + it.fill(Color::WHITE); diff --git a/tests/components/ili9xxx/test.rp2040.yaml b/tests/components/ili9xxx/test.rp2040.yaml new file mode 100644 index 0000000000..54083ebce8 --- /dev/null +++ b/tests/components/ili9xxx/test.rp2040.yaml @@ -0,0 +1,35 @@ +spi: + - id: spi_main_lcd + clk_pin: 2 + mosi_pin: 3 + miso_pin: 4 + +display: + - platform: ili9xxx + invert_colors: true + dimensions: 320x240 + transform: + swap_xy: true + mirror_x: true + mirror_y: false + model: TFT 2.4 + color_palette: GRAYSCALE + cs_pin: 5 + dc_pin: 15 + reset_pin: 16 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - platform: ili9xxx + dimensions: + width: 320 + height: 240 + offset_width: 20 + offset_height: 10 + model: TFT 2.4 + cs_pin: 20 + dc_pin: 21 + reset_pin: 22 + auto_clear_enabled: false + rotation: 90 + lambda: |- + it.fill(Color::WHITE); diff --git a/tests/components/image/test.esp32-c3-idf.yaml b/tests/components/image/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..c083a97c94 --- /dev/null +++ b/tests/components/image/test.esp32-c3-idf.yaml @@ -0,0 +1,52 @@ +spi: + - id: spi_main_lcd + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +display: + - platform: ili9xxx + id: main_lcd + model: ili9342 + cs_pin: 8 + dc_pin: 9 + reset_pin: 10 + +image: + - id: binary_image + file: ../../pnglogo.png + type: BINARY + dither: FloydSteinberg + - id: transparent_transparent_image + file: ../../pnglogo.png + type: TRANSPARENT_BINARY + - id: rgba_image + file: ../../pnglogo.png + type: RGBA + resize: 50x50 + - id: rgb24_image + file: ../../pnglogo.png + type: RGB24 + use_transparency: yes + - id: rgb565_image + file: ../../pnglogo.png + type: RGB565 + use_transparency: no + - id: web_svg_image + file: https://raw.githubusercontent.com/esphome/esphome-docs/a62d7ab193c1a464ed791670170c7d518189109b/images/logo.svg + resize: 256x48 + type: TRANSPARENT_BINARY + - id: web_tiff_image + file: https://upload.wikimedia.org/wikipedia/commons/b/b6/SIPI_Jelly_Beans_4.1.07.tiff + type: RGB24 + resize: 48x48 + - id: web_redirect_image + file: https://avatars.githubusercontent.com/u/3060199?s=48&v=4 + type: RGB24 + resize: 48x48 + - id: mdi_alert + file: mdi:alert-circle-outline + resize: 50x50 + - id: another_alert_icon + file: mdi:alert-outline + type: BINARY diff --git a/tests/components/image/test.esp32-c3.yaml b/tests/components/image/test.esp32-c3.yaml new file mode 100644 index 0000000000..c083a97c94 --- /dev/null +++ b/tests/components/image/test.esp32-c3.yaml @@ -0,0 +1,52 @@ +spi: + - id: spi_main_lcd + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +display: + - platform: ili9xxx + id: main_lcd + model: ili9342 + cs_pin: 8 + dc_pin: 9 + reset_pin: 10 + +image: + - id: binary_image + file: ../../pnglogo.png + type: BINARY + dither: FloydSteinberg + - id: transparent_transparent_image + file: ../../pnglogo.png + type: TRANSPARENT_BINARY + - id: rgba_image + file: ../../pnglogo.png + type: RGBA + resize: 50x50 + - id: rgb24_image + file: ../../pnglogo.png + type: RGB24 + use_transparency: yes + - id: rgb565_image + file: ../../pnglogo.png + type: RGB565 + use_transparency: no + - id: web_svg_image + file: https://raw.githubusercontent.com/esphome/esphome-docs/a62d7ab193c1a464ed791670170c7d518189109b/images/logo.svg + resize: 256x48 + type: TRANSPARENT_BINARY + - id: web_tiff_image + file: https://upload.wikimedia.org/wikipedia/commons/b/b6/SIPI_Jelly_Beans_4.1.07.tiff + type: RGB24 + resize: 48x48 + - id: web_redirect_image + file: https://avatars.githubusercontent.com/u/3060199?s=48&v=4 + type: RGB24 + resize: 48x48 + - id: mdi_alert + file: mdi:alert-circle-outline + resize: 50x50 + - id: another_alert_icon + file: mdi:alert-outline + type: BINARY diff --git a/tests/components/image/test.esp32-idf.yaml b/tests/components/image/test.esp32-idf.yaml new file mode 100644 index 0000000000..ff9adde6b1 --- /dev/null +++ b/tests/components/image/test.esp32-idf.yaml @@ -0,0 +1,52 @@ +spi: + - id: spi_main_lcd + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +display: + - platform: ili9xxx + id: main_lcd + model: ili9342 + cs_pin: 12 + dc_pin: 13 + reset_pin: 21 + +image: + - id: binary_image + file: ../../pnglogo.png + type: BINARY + dither: FloydSteinberg + - id: transparent_transparent_image + file: ../../pnglogo.png + type: TRANSPARENT_BINARY + - id: rgba_image + file: ../../pnglogo.png + type: RGBA + resize: 50x50 + - id: rgb24_image + file: ../../pnglogo.png + type: RGB24 + use_transparency: yes + - id: rgb565_image + file: ../../pnglogo.png + type: RGB565 + use_transparency: no + - id: web_svg_image + file: https://raw.githubusercontent.com/esphome/esphome-docs/a62d7ab193c1a464ed791670170c7d518189109b/images/logo.svg + resize: 256x48 + type: TRANSPARENT_BINARY + - id: web_tiff_image + file: https://upload.wikimedia.org/wikipedia/commons/b/b6/SIPI_Jelly_Beans_4.1.07.tiff + type: RGB24 + resize: 48x48 + - id: web_redirect_image + file: https://avatars.githubusercontent.com/u/3060199?s=48&v=4 + type: RGB24 + resize: 48x48 + - id: mdi_alert + file: mdi:alert-circle-outline + resize: 50x50 + - id: another_alert_icon + file: mdi:alert-outline + type: BINARY diff --git a/tests/components/image/test.esp32.yaml b/tests/components/image/test.esp32.yaml new file mode 100644 index 0000000000..ff9adde6b1 --- /dev/null +++ b/tests/components/image/test.esp32.yaml @@ -0,0 +1,52 @@ +spi: + - id: spi_main_lcd + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +display: + - platform: ili9xxx + id: main_lcd + model: ili9342 + cs_pin: 12 + dc_pin: 13 + reset_pin: 21 + +image: + - id: binary_image + file: ../../pnglogo.png + type: BINARY + dither: FloydSteinberg + - id: transparent_transparent_image + file: ../../pnglogo.png + type: TRANSPARENT_BINARY + - id: rgba_image + file: ../../pnglogo.png + type: RGBA + resize: 50x50 + - id: rgb24_image + file: ../../pnglogo.png + type: RGB24 + use_transparency: yes + - id: rgb565_image + file: ../../pnglogo.png + type: RGB565 + use_transparency: no + - id: web_svg_image + file: https://raw.githubusercontent.com/esphome/esphome-docs/a62d7ab193c1a464ed791670170c7d518189109b/images/logo.svg + resize: 256x48 + type: TRANSPARENT_BINARY + - id: web_tiff_image + file: https://upload.wikimedia.org/wikipedia/commons/b/b6/SIPI_Jelly_Beans_4.1.07.tiff + type: RGB24 + resize: 48x48 + - id: web_redirect_image + file: https://avatars.githubusercontent.com/u/3060199?s=48&v=4 + type: RGB24 + resize: 48x48 + - id: mdi_alert + file: mdi:alert-circle-outline + resize: 50x50 + - id: another_alert_icon + file: mdi:alert-outline + type: BINARY diff --git a/tests/components/image/test.esp8266.yaml b/tests/components/image/test.esp8266.yaml new file mode 100644 index 0000000000..3632b95485 --- /dev/null +++ b/tests/components/image/test.esp8266.yaml @@ -0,0 +1,52 @@ +spi: + - id: spi_main_lcd + clk_pin: 14 + mosi_pin: 13 + miso_pin: 12 + +display: + - platform: ili9xxx + id: main_lcd + model: ili9342 + cs_pin: 5 + dc_pin: 15 + reset_pin: 16 + +image: + - id: binary_image + file: ../../pnglogo.png + type: BINARY + dither: FloydSteinberg + - id: transparent_transparent_image + file: ../../pnglogo.png + type: TRANSPARENT_BINARY + - id: rgba_image + file: ../../pnglogo.png + type: RGBA + resize: 50x50 + - id: rgb24_image + file: ../../pnglogo.png + type: RGB24 + use_transparency: yes + - id: rgb565_image + file: ../../pnglogo.png + type: RGB565 + use_transparency: no + - id: web_svg_image + file: https://raw.githubusercontent.com/esphome/esphome-docs/a62d7ab193c1a464ed791670170c7d518189109b/images/logo.svg + resize: 256x48 + type: TRANSPARENT_BINARY + - id: web_tiff_image + file: https://upload.wikimedia.org/wikipedia/commons/b/b6/SIPI_Jelly_Beans_4.1.07.tiff + type: RGB24 + resize: 48x48 + - id: web_redirect_image + file: https://avatars.githubusercontent.com/u/3060199?s=48&v=4 + type: RGB24 + resize: 48x48 + - id: mdi_alert + file: mdi:alert-circle-outline + resize: 50x50 + - id: another_alert_icon + file: mdi:alert-outline + type: BINARY diff --git a/tests/components/image/test.rp2040.yaml b/tests/components/image/test.rp2040.yaml new file mode 100644 index 0000000000..b79c8a9195 --- /dev/null +++ b/tests/components/image/test.rp2040.yaml @@ -0,0 +1,52 @@ +spi: + - id: spi_main_lcd + clk_pin: 2 + mosi_pin: 3 + miso_pin: 4 + +display: + - platform: ili9xxx + id: main_lcd + model: ili9342 + cs_pin: 20 + dc_pin: 21 + reset_pin: 22 + +image: + - id: binary_image + file: ../../pnglogo.png + type: BINARY + dither: FloydSteinberg + - id: transparent_transparent_image + file: ../../pnglogo.png + type: TRANSPARENT_BINARY + - id: rgba_image + file: ../../pnglogo.png + type: RGBA + resize: 50x50 + - id: rgb24_image + file: ../../pnglogo.png + type: RGB24 + use_transparency: yes + - id: rgb565_image + file: ../../pnglogo.png + type: RGB565 + use_transparency: no + - id: web_svg_image + file: https://raw.githubusercontent.com/esphome/esphome-docs/a62d7ab193c1a464ed791670170c7d518189109b/images/logo.svg + resize: 256x48 + type: TRANSPARENT_BINARY + - id: web_tiff_image + file: https://upload.wikimedia.org/wikipedia/commons/b/b6/SIPI_Jelly_Beans_4.1.07.tiff + type: RGB24 + resize: 48x48 + - id: web_redirect_image + file: https://avatars.githubusercontent.com/u/3060199?s=48&v=4 + type: RGB24 + resize: 48x48 + - id: mdi_alert + file: mdi:alert-circle-outline + resize: 50x50 + - id: another_alert_icon + file: mdi:alert-outline + type: BINARY diff --git a/tests/components/improv_serial/test.esp32-c3-idf.yaml b/tests/components/improv_serial/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..b36fe5a4a7 --- /dev/null +++ b/tests/components/improv_serial/test.esp32-c3-idf.yaml @@ -0,0 +1,5 @@ +wifi: + ssid: MySSID + password: password1 + +improv_serial: diff --git a/tests/components/improv_serial/test.esp32-c3.yaml b/tests/components/improv_serial/test.esp32-c3.yaml new file mode 100644 index 0000000000..b36fe5a4a7 --- /dev/null +++ b/tests/components/improv_serial/test.esp32-c3.yaml @@ -0,0 +1,5 @@ +wifi: + ssid: MySSID + password: password1 + +improv_serial: diff --git a/tests/components/improv_serial/test.esp32-idf.yaml b/tests/components/improv_serial/test.esp32-idf.yaml new file mode 100644 index 0000000000..b36fe5a4a7 --- /dev/null +++ b/tests/components/improv_serial/test.esp32-idf.yaml @@ -0,0 +1,5 @@ +wifi: + ssid: MySSID + password: password1 + +improv_serial: diff --git a/tests/components/improv_serial/test.esp32.yaml b/tests/components/improv_serial/test.esp32.yaml new file mode 100644 index 0000000000..b36fe5a4a7 --- /dev/null +++ b/tests/components/improv_serial/test.esp32.yaml @@ -0,0 +1,5 @@ +wifi: + ssid: MySSID + password: password1 + +improv_serial: diff --git a/tests/components/improv_serial/test.esp8266.yaml b/tests/components/improv_serial/test.esp8266.yaml new file mode 100644 index 0000000000..b36fe5a4a7 --- /dev/null +++ b/tests/components/improv_serial/test.esp8266.yaml @@ -0,0 +1,5 @@ +wifi: + ssid: MySSID + password: password1 + +improv_serial: diff --git a/tests/components/improv_serial/test.rp2040.yaml b/tests/components/improv_serial/test.rp2040.yaml new file mode 100644 index 0000000000..b36fe5a4a7 --- /dev/null +++ b/tests/components/improv_serial/test.rp2040.yaml @@ -0,0 +1,5 @@ +wifi: + ssid: MySSID + password: password1 + +improv_serial: diff --git a/tests/components/ina219/test.esp32-c3-idf.yaml b/tests/components/ina219/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..586add9d16 --- /dev/null +++ b/tests/components/ina219/test.esp32-c3-idf.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_ina219 + scl: 5 + sda: 4 + +sensor: + - platform: ina219 + address: 0x40 + shunt_resistance: 0.1 ohm + current: + name: INA219 Current + power: + name: INA219 Power + bus_voltage: + name: INA219 Bus Voltage + shunt_voltage: + name: INA219 Shunt Voltage + max_voltage: 32.0V + max_current: 3.2A + update_interval: 15s diff --git a/tests/components/ina219/test.esp32-c3.yaml b/tests/components/ina219/test.esp32-c3.yaml new file mode 100644 index 0000000000..586add9d16 --- /dev/null +++ b/tests/components/ina219/test.esp32-c3.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_ina219 + scl: 5 + sda: 4 + +sensor: + - platform: ina219 + address: 0x40 + shunt_resistance: 0.1 ohm + current: + name: INA219 Current + power: + name: INA219 Power + bus_voltage: + name: INA219 Bus Voltage + shunt_voltage: + name: INA219 Shunt Voltage + max_voltage: 32.0V + max_current: 3.2A + update_interval: 15s diff --git a/tests/components/ina219/test.esp32-idf.yaml b/tests/components/ina219/test.esp32-idf.yaml new file mode 100644 index 0000000000..affbec67c4 --- /dev/null +++ b/tests/components/ina219/test.esp32-idf.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_ina219 + scl: 16 + sda: 17 + +sensor: + - platform: ina219 + address: 0x40 + shunt_resistance: 0.1 ohm + current: + name: INA219 Current + power: + name: INA219 Power + bus_voltage: + name: INA219 Bus Voltage + shunt_voltage: + name: INA219 Shunt Voltage + max_voltage: 32.0V + max_current: 3.2A + update_interval: 15s diff --git a/tests/components/ina219/test.esp32.yaml b/tests/components/ina219/test.esp32.yaml new file mode 100644 index 0000000000..affbec67c4 --- /dev/null +++ b/tests/components/ina219/test.esp32.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_ina219 + scl: 16 + sda: 17 + +sensor: + - platform: ina219 + address: 0x40 + shunt_resistance: 0.1 ohm + current: + name: INA219 Current + power: + name: INA219 Power + bus_voltage: + name: INA219 Bus Voltage + shunt_voltage: + name: INA219 Shunt Voltage + max_voltage: 32.0V + max_current: 3.2A + update_interval: 15s diff --git a/tests/components/ina219/test.esp8266.yaml b/tests/components/ina219/test.esp8266.yaml new file mode 100644 index 0000000000..586add9d16 --- /dev/null +++ b/tests/components/ina219/test.esp8266.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_ina219 + scl: 5 + sda: 4 + +sensor: + - platform: ina219 + address: 0x40 + shunt_resistance: 0.1 ohm + current: + name: INA219 Current + power: + name: INA219 Power + bus_voltage: + name: INA219 Bus Voltage + shunt_voltage: + name: INA219 Shunt Voltage + max_voltage: 32.0V + max_current: 3.2A + update_interval: 15s diff --git a/tests/components/ina219/test.rp2040.yaml b/tests/components/ina219/test.rp2040.yaml new file mode 100644 index 0000000000..586add9d16 --- /dev/null +++ b/tests/components/ina219/test.rp2040.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_ina219 + scl: 5 + sda: 4 + +sensor: + - platform: ina219 + address: 0x40 + shunt_resistance: 0.1 ohm + current: + name: INA219 Current + power: + name: INA219 Power + bus_voltage: + name: INA219 Bus Voltage + shunt_voltage: + name: INA219 Shunt Voltage + max_voltage: 32.0V + max_current: 3.2A + update_interval: 15s diff --git a/tests/components/ina226/test.esp32-c3-idf.yaml b/tests/components/ina226/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..6581763294 --- /dev/null +++ b/tests/components/ina226/test.esp32-c3-idf.yaml @@ -0,0 +1,19 @@ +i2c: + - id: i2c_ina226 + scl: 5 + sda: 4 + +sensor: + - platform: ina226 + address: 0x40 + shunt_resistance: 0.1 ohm + current: + name: INA226 Current + power: + name: INA226 Power + bus_voltage: + name: INA226 Bus Voltage + shunt_voltage: + name: INA226 Shunt Voltage + max_current: 3.2A + update_interval: 15s diff --git a/tests/components/ina226/test.esp32-c3.yaml b/tests/components/ina226/test.esp32-c3.yaml new file mode 100644 index 0000000000..6581763294 --- /dev/null +++ b/tests/components/ina226/test.esp32-c3.yaml @@ -0,0 +1,19 @@ +i2c: + - id: i2c_ina226 + scl: 5 + sda: 4 + +sensor: + - platform: ina226 + address: 0x40 + shunt_resistance: 0.1 ohm + current: + name: INA226 Current + power: + name: INA226 Power + bus_voltage: + name: INA226 Bus Voltage + shunt_voltage: + name: INA226 Shunt Voltage + max_current: 3.2A + update_interval: 15s diff --git a/tests/components/ina226/test.esp32-idf.yaml b/tests/components/ina226/test.esp32-idf.yaml new file mode 100644 index 0000000000..feab5e146c --- /dev/null +++ b/tests/components/ina226/test.esp32-idf.yaml @@ -0,0 +1,19 @@ +i2c: + - id: i2c_ina226 + scl: 16 + sda: 17 + +sensor: + - platform: ina226 + address: 0x40 + shunt_resistance: 0.1 ohm + current: + name: INA226 Current + power: + name: INA226 Power + bus_voltage: + name: INA226 Bus Voltage + shunt_voltage: + name: INA226 Shunt Voltage + max_current: 3.2A + update_interval: 15s diff --git a/tests/components/ina226/test.esp32.yaml b/tests/components/ina226/test.esp32.yaml new file mode 100644 index 0000000000..feab5e146c --- /dev/null +++ b/tests/components/ina226/test.esp32.yaml @@ -0,0 +1,19 @@ +i2c: + - id: i2c_ina226 + scl: 16 + sda: 17 + +sensor: + - platform: ina226 + address: 0x40 + shunt_resistance: 0.1 ohm + current: + name: INA226 Current + power: + name: INA226 Power + bus_voltage: + name: INA226 Bus Voltage + shunt_voltage: + name: INA226 Shunt Voltage + max_current: 3.2A + update_interval: 15s diff --git a/tests/components/ina226/test.esp8266.yaml b/tests/components/ina226/test.esp8266.yaml new file mode 100644 index 0000000000..6581763294 --- /dev/null +++ b/tests/components/ina226/test.esp8266.yaml @@ -0,0 +1,19 @@ +i2c: + - id: i2c_ina226 + scl: 5 + sda: 4 + +sensor: + - platform: ina226 + address: 0x40 + shunt_resistance: 0.1 ohm + current: + name: INA226 Current + power: + name: INA226 Power + bus_voltage: + name: INA226 Bus Voltage + shunt_voltage: + name: INA226 Shunt Voltage + max_current: 3.2A + update_interval: 15s diff --git a/tests/components/ina226/test.rp2040.yaml b/tests/components/ina226/test.rp2040.yaml new file mode 100644 index 0000000000..6581763294 --- /dev/null +++ b/tests/components/ina226/test.rp2040.yaml @@ -0,0 +1,19 @@ +i2c: + - id: i2c_ina226 + scl: 5 + sda: 4 + +sensor: + - platform: ina226 + address: 0x40 + shunt_resistance: 0.1 ohm + current: + name: INA226 Current + power: + name: INA226 Power + bus_voltage: + name: INA226 Bus Voltage + shunt_voltage: + name: INA226 Shunt Voltage + max_current: 3.2A + update_interval: 15s diff --git a/tests/components/ina260/test.esp32-c3-idf.yaml b/tests/components/ina260/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..a1da63351d --- /dev/null +++ b/tests/components/ina260/test.esp32-c3-idf.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_ina260 + scl: 5 + sda: 4 + +sensor: + - platform: ina260 + address: 0x40 + current: + name: INA260 Current + power: + name: INA260 Power + bus_voltage: + name: INA260 Voltage + update_interval: 60s diff --git a/tests/components/ina260/test.esp32-c3.yaml b/tests/components/ina260/test.esp32-c3.yaml new file mode 100644 index 0000000000..a1da63351d --- /dev/null +++ b/tests/components/ina260/test.esp32-c3.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_ina260 + scl: 5 + sda: 4 + +sensor: + - platform: ina260 + address: 0x40 + current: + name: INA260 Current + power: + name: INA260 Power + bus_voltage: + name: INA260 Voltage + update_interval: 60s diff --git a/tests/components/ina260/test.esp32-idf.yaml b/tests/components/ina260/test.esp32-idf.yaml new file mode 100644 index 0000000000..be6cf73bff --- /dev/null +++ b/tests/components/ina260/test.esp32-idf.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_ina260 + scl: 16 + sda: 17 + +sensor: + - platform: ina260 + address: 0x40 + current: + name: INA260 Current + power: + name: INA260 Power + bus_voltage: + name: INA260 Voltage + update_interval: 60s diff --git a/tests/components/ina260/test.esp32.yaml b/tests/components/ina260/test.esp32.yaml new file mode 100644 index 0000000000..be6cf73bff --- /dev/null +++ b/tests/components/ina260/test.esp32.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_ina260 + scl: 16 + sda: 17 + +sensor: + - platform: ina260 + address: 0x40 + current: + name: INA260 Current + power: + name: INA260 Power + bus_voltage: + name: INA260 Voltage + update_interval: 60s diff --git a/tests/components/ina260/test.esp8266.yaml b/tests/components/ina260/test.esp8266.yaml new file mode 100644 index 0000000000..a1da63351d --- /dev/null +++ b/tests/components/ina260/test.esp8266.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_ina260 + scl: 5 + sda: 4 + +sensor: + - platform: ina260 + address: 0x40 + current: + name: INA260 Current + power: + name: INA260 Power + bus_voltage: + name: INA260 Voltage + update_interval: 60s diff --git a/tests/components/ina260/test.rp2040.yaml b/tests/components/ina260/test.rp2040.yaml new file mode 100644 index 0000000000..a1da63351d --- /dev/null +++ b/tests/components/ina260/test.rp2040.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_ina260 + scl: 5 + sda: 4 + +sensor: + - platform: ina260 + address: 0x40 + current: + name: INA260 Current + power: + name: INA260 Power + bus_voltage: + name: INA260 Voltage + update_interval: 60s diff --git a/tests/components/ina3221/test.esp32-c3-idf.yaml b/tests/components/ina3221/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..55990871a0 --- /dev/null +++ b/tests/components/ina3221/test.esp32-c3-idf.yaml @@ -0,0 +1,19 @@ +i2c: + - id: i2c_ina3221 + scl: 5 + sda: 4 + +sensor: + - platform: ina3221 + address: 0x40 + channel_1: + shunt_resistance: 0.1 ohm + current: + name: INA3221 Channel 1 Current + power: + name: INA3221 Channel 1 Power + bus_voltage: + name: INA3221 Channel 1 Bus Voltage + shunt_voltage: + name: INA3221 Channel 1 Shunt Voltage + update_interval: 15s diff --git a/tests/components/ina3221/test.esp32-c3.yaml b/tests/components/ina3221/test.esp32-c3.yaml new file mode 100644 index 0000000000..55990871a0 --- /dev/null +++ b/tests/components/ina3221/test.esp32-c3.yaml @@ -0,0 +1,19 @@ +i2c: + - id: i2c_ina3221 + scl: 5 + sda: 4 + +sensor: + - platform: ina3221 + address: 0x40 + channel_1: + shunt_resistance: 0.1 ohm + current: + name: INA3221 Channel 1 Current + power: + name: INA3221 Channel 1 Power + bus_voltage: + name: INA3221 Channel 1 Bus Voltage + shunt_voltage: + name: INA3221 Channel 1 Shunt Voltage + update_interval: 15s diff --git a/tests/components/ina3221/test.esp32-idf.yaml b/tests/components/ina3221/test.esp32-idf.yaml new file mode 100644 index 0000000000..ad9cf79e38 --- /dev/null +++ b/tests/components/ina3221/test.esp32-idf.yaml @@ -0,0 +1,19 @@ +i2c: + - id: i2c_ina3221 + scl: 16 + sda: 17 + +sensor: + - platform: ina3221 + address: 0x40 + channel_1: + shunt_resistance: 0.1 ohm + current: + name: INA3221 Channel 1 Current + power: + name: INA3221 Channel 1 Power + bus_voltage: + name: INA3221 Channel 1 Bus Voltage + shunt_voltage: + name: INA3221 Channel 1 Shunt Voltage + update_interval: 15s diff --git a/tests/components/ina3221/test.esp32.yaml b/tests/components/ina3221/test.esp32.yaml new file mode 100644 index 0000000000..ad9cf79e38 --- /dev/null +++ b/tests/components/ina3221/test.esp32.yaml @@ -0,0 +1,19 @@ +i2c: + - id: i2c_ina3221 + scl: 16 + sda: 17 + +sensor: + - platform: ina3221 + address: 0x40 + channel_1: + shunt_resistance: 0.1 ohm + current: + name: INA3221 Channel 1 Current + power: + name: INA3221 Channel 1 Power + bus_voltage: + name: INA3221 Channel 1 Bus Voltage + shunt_voltage: + name: INA3221 Channel 1 Shunt Voltage + update_interval: 15s diff --git a/tests/components/ina3221/test.esp8266.yaml b/tests/components/ina3221/test.esp8266.yaml new file mode 100644 index 0000000000..55990871a0 --- /dev/null +++ b/tests/components/ina3221/test.esp8266.yaml @@ -0,0 +1,19 @@ +i2c: + - id: i2c_ina3221 + scl: 5 + sda: 4 + +sensor: + - platform: ina3221 + address: 0x40 + channel_1: + shunt_resistance: 0.1 ohm + current: + name: INA3221 Channel 1 Current + power: + name: INA3221 Channel 1 Power + bus_voltage: + name: INA3221 Channel 1 Bus Voltage + shunt_voltage: + name: INA3221 Channel 1 Shunt Voltage + update_interval: 15s diff --git a/tests/components/ina3221/test.rp2040.yaml b/tests/components/ina3221/test.rp2040.yaml new file mode 100644 index 0000000000..55990871a0 --- /dev/null +++ b/tests/components/ina3221/test.rp2040.yaml @@ -0,0 +1,19 @@ +i2c: + - id: i2c_ina3221 + scl: 5 + sda: 4 + +sensor: + - platform: ina3221 + address: 0x40 + channel_1: + shunt_resistance: 0.1 ohm + current: + name: INA3221 Channel 1 Current + power: + name: INA3221 Channel 1 Power + bus_voltage: + name: INA3221 Channel 1 Bus Voltage + shunt_voltage: + name: INA3221 Channel 1 Shunt Voltage + update_interval: 15s diff --git a/tests/components/inkbird_ibsth1_mini/test.esp32-c3-idf.yaml b/tests/components/inkbird_ibsth1_mini/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..ba46b7dbf6 --- /dev/null +++ b/tests/components/inkbird_ibsth1_mini/test.esp32-c3-idf.yaml @@ -0,0 +1,11 @@ +esp32_ble_tracker: + +sensor: + - platform: inkbird_ibsth1_mini + mac_address: 38:81:D7:0A:9C:11 + temperature: + name: Inkbird IBS-TH1 Temperature + humidity: + name: Inkbird IBS-TH1 Humidity + battery_level: + name: Inkbird IBS-TH1 Battery Level diff --git a/tests/components/inkbird_ibsth1_mini/test.esp32-c3.yaml b/tests/components/inkbird_ibsth1_mini/test.esp32-c3.yaml new file mode 100644 index 0000000000..ba46b7dbf6 --- /dev/null +++ b/tests/components/inkbird_ibsth1_mini/test.esp32-c3.yaml @@ -0,0 +1,11 @@ +esp32_ble_tracker: + +sensor: + - platform: inkbird_ibsth1_mini + mac_address: 38:81:D7:0A:9C:11 + temperature: + name: Inkbird IBS-TH1 Temperature + humidity: + name: Inkbird IBS-TH1 Humidity + battery_level: + name: Inkbird IBS-TH1 Battery Level diff --git a/tests/components/inkbird_ibsth1_mini/test.esp32-idf.yaml b/tests/components/inkbird_ibsth1_mini/test.esp32-idf.yaml new file mode 100644 index 0000000000..ba46b7dbf6 --- /dev/null +++ b/tests/components/inkbird_ibsth1_mini/test.esp32-idf.yaml @@ -0,0 +1,11 @@ +esp32_ble_tracker: + +sensor: + - platform: inkbird_ibsth1_mini + mac_address: 38:81:D7:0A:9C:11 + temperature: + name: Inkbird IBS-TH1 Temperature + humidity: + name: Inkbird IBS-TH1 Humidity + battery_level: + name: Inkbird IBS-TH1 Battery Level diff --git a/tests/components/inkbird_ibsth1_mini/test.esp32.yaml b/tests/components/inkbird_ibsth1_mini/test.esp32.yaml new file mode 100644 index 0000000000..ba46b7dbf6 --- /dev/null +++ b/tests/components/inkbird_ibsth1_mini/test.esp32.yaml @@ -0,0 +1,11 @@ +esp32_ble_tracker: + +sensor: + - platform: inkbird_ibsth1_mini + mac_address: 38:81:D7:0A:9C:11 + temperature: + name: Inkbird IBS-TH1 Temperature + humidity: + name: Inkbird IBS-TH1 Humidity + battery_level: + name: Inkbird IBS-TH1 Battery Level diff --git a/tests/components/inkplate6/test.esp32.yaml b/tests/components/inkplate6/test.esp32.yaml new file mode 100644 index 0000000000..31b14e6c73 --- /dev/null +++ b/tests/components/inkplate6/test.esp32.yaml @@ -0,0 +1,62 @@ +i2c: + - id: i2c_inkplate6 + scl: 16 + sda: 17 + +display: + - platform: inkplate6 + id: inkplate_display + greyscale: false + partial_updating: false + update_interval: 60s + display_data_0_pin: + number: 1 + allow_other_uses: true + display_data_1_pin: + number: 1 + allow_other_uses: true + display_data_2_pin: + number: 1 + allow_other_uses: true + display_data_3_pin: + number: 1 + allow_other_uses: true + display_data_5_pin: + number: 1 + allow_other_uses: true + display_data_4_pin: + number: 1 + allow_other_uses: true + display_data_6_pin: + number: 1 + allow_other_uses: true + display_data_7_pin: + number: 1 + allow_other_uses: true + ckv_pin: + number: 1 + allow_other_uses: true + sph_pin: + number: 1 + allow_other_uses: true + gmod_pin: + number: 1 + allow_other_uses: true + gpio0_enable_pin: + number: 1 + allow_other_uses: true + oe_pin: + number: 1 + allow_other_uses: true + spv_pin: + number: 1 + allow_other_uses: true + powerup_pin: + number: 1 + allow_other_uses: true + wakeup_pin: + number: 1 + allow_other_uses: true + vcom_pin: + number: 1 + allow_other_uses: true diff --git a/tests/components/integration/test.esp32-c3.yaml b/tests/components/integration/test.esp32-c3.yaml new file mode 100644 index 0000000000..b68cb9f87d --- /dev/null +++ b/tests/components/integration/test.esp32-c3.yaml @@ -0,0 +1,9 @@ +sensor: + - platform: adc + id: my_sensor + pin: 4 + attenuation: 11db + - platform: integration + sensor: my_sensor + name: Integration Sensor + time_unit: s diff --git a/tests/components/integration/test.esp32-idf.yaml b/tests/components/integration/test.esp32-idf.yaml new file mode 100644 index 0000000000..0095fdb1ff --- /dev/null +++ b/tests/components/integration/test.esp32-idf.yaml @@ -0,0 +1,9 @@ +sensor: + - platform: adc + id: my_sensor + pin: A0 + attenuation: 2.5db + - platform: integration + sensor: my_sensor + name: Integration Sensor + time_unit: s diff --git a/tests/components/integration/test.esp32-s2.yaml b/tests/components/integration/test.esp32-s2.yaml new file mode 100644 index 0000000000..1415952571 --- /dev/null +++ b/tests/components/integration/test.esp32-s2.yaml @@ -0,0 +1,9 @@ +sensor: + - platform: adc + id: my_sensor + pin: 1 + attenuation: 11db + - platform: integration + sensor: my_sensor + name: Integration Sensor + time_unit: s diff --git a/tests/components/integration/test.esp32-s3.yaml b/tests/components/integration/test.esp32-s3.yaml new file mode 100644 index 0000000000..1415952571 --- /dev/null +++ b/tests/components/integration/test.esp32-s3.yaml @@ -0,0 +1,9 @@ +sensor: + - platform: adc + id: my_sensor + pin: 1 + attenuation: 11db + - platform: integration + sensor: my_sensor + name: Integration Sensor + time_unit: s diff --git a/tests/components/integration/test.esp32.yaml b/tests/components/integration/test.esp32.yaml new file mode 100644 index 0000000000..0095fdb1ff --- /dev/null +++ b/tests/components/integration/test.esp32.yaml @@ -0,0 +1,9 @@ +sensor: + - platform: adc + id: my_sensor + pin: A0 + attenuation: 2.5db + - platform: integration + sensor: my_sensor + name: Integration Sensor + time_unit: s diff --git a/tests/components/integration/test.esp8266.yaml b/tests/components/integration/test.esp8266.yaml new file mode 100644 index 0000000000..51d3e19077 --- /dev/null +++ b/tests/components/integration/test.esp8266.yaml @@ -0,0 +1,8 @@ +sensor: + - platform: adc + id: my_sensor + pin: VCC + - platform: integration + sensor: my_sensor + name: Integration Sensor + time_unit: s diff --git a/tests/components/integration/test.rp2040.yaml b/tests/components/integration/test.rp2040.yaml new file mode 100644 index 0000000000..51d3e19077 --- /dev/null +++ b/tests/components/integration/test.rp2040.yaml @@ -0,0 +1,8 @@ +sensor: + - platform: adc + id: my_sensor + pin: VCC + - platform: integration + sensor: my_sensor + name: Integration Sensor + time_unit: s diff --git a/tests/components/internal_temperature/test.esp32-c3.yaml b/tests/components/internal_temperature/test.esp32-c3.yaml index 28df4a6d9f..19f740339d 100644 --- a/tests/components/internal_temperature/test.esp32-c3.yaml +++ b/tests/components/internal_temperature/test.esp32-c3.yaml @@ -1,3 +1,3 @@ sensor: - platform: internal_temperature - name: "Internal Temperature" + name: Internal Temperature diff --git a/tests/components/internal_temperature/test.esp32-idf.yaml b/tests/components/internal_temperature/test.esp32-idf.yaml index 28df4a6d9f..19f740339d 100644 --- a/tests/components/internal_temperature/test.esp32-idf.yaml +++ b/tests/components/internal_temperature/test.esp32-idf.yaml @@ -1,3 +1,3 @@ sensor: - platform: internal_temperature - name: "Internal Temperature" + name: Internal Temperature diff --git a/tests/components/internal_temperature/test.esp32-s2.yaml b/tests/components/internal_temperature/test.esp32-s2.yaml new file mode 100644 index 0000000000..19f740339d --- /dev/null +++ b/tests/components/internal_temperature/test.esp32-s2.yaml @@ -0,0 +1,3 @@ +sensor: + - platform: internal_temperature + name: Internal Temperature diff --git a/tests/components/internal_temperature/test.esp32-s3.yaml b/tests/components/internal_temperature/test.esp32-s3.yaml new file mode 100644 index 0000000000..9eb1ec0b0f --- /dev/null +++ b/tests/components/internal_temperature/test.esp32-s3.yaml @@ -0,0 +1,7 @@ +sensor: + - platform: internal_temperature + name: Internal Temperature + +esp32: + framework: + version: 2.0.9 diff --git a/tests/components/internal_temperature/test.esp32.yaml b/tests/components/internal_temperature/test.esp32.yaml index 28df4a6d9f..19f740339d 100644 --- a/tests/components/internal_temperature/test.esp32.yaml +++ b/tests/components/internal_temperature/test.esp32.yaml @@ -1,3 +1,3 @@ sensor: - platform: internal_temperature - name: "Internal Temperature" + name: Internal Temperature diff --git a/tests/components/internal_temperature/test.rp2040.yaml b/tests/components/internal_temperature/test.rp2040.yaml index 28df4a6d9f..19f740339d 100644 --- a/tests/components/internal_temperature/test.rp2040.yaml +++ b/tests/components/internal_temperature/test.rp2040.yaml @@ -1,3 +1,3 @@ sensor: - platform: internal_temperature - name: "Internal Temperature" + name: Internal Temperature diff --git a/tests/components/interval/test.esp32-c3-idf.yaml b/tests/components/interval/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..2a3c979ae2 --- /dev/null +++ b/tests/components/interval/test.esp32-c3-idf.yaml @@ -0,0 +1,4 @@ +interval: + - interval: 1s + then: + - logger.log: Tick diff --git a/tests/components/interval/test.esp32-c3.yaml b/tests/components/interval/test.esp32-c3.yaml new file mode 100644 index 0000000000..2a3c979ae2 --- /dev/null +++ b/tests/components/interval/test.esp32-c3.yaml @@ -0,0 +1,4 @@ +interval: + - interval: 1s + then: + - logger.log: Tick diff --git a/tests/components/interval/test.esp32-idf.yaml b/tests/components/interval/test.esp32-idf.yaml new file mode 100644 index 0000000000..2a3c979ae2 --- /dev/null +++ b/tests/components/interval/test.esp32-idf.yaml @@ -0,0 +1,4 @@ +interval: + - interval: 1s + then: + - logger.log: Tick diff --git a/tests/components/interval/test.esp32.yaml b/tests/components/interval/test.esp32.yaml new file mode 100644 index 0000000000..2a3c979ae2 --- /dev/null +++ b/tests/components/interval/test.esp32.yaml @@ -0,0 +1,4 @@ +interval: + - interval: 1s + then: + - logger.log: Tick diff --git a/tests/components/interval/test.esp8266.yaml b/tests/components/interval/test.esp8266.yaml new file mode 100644 index 0000000000..2a3c979ae2 --- /dev/null +++ b/tests/components/interval/test.esp8266.yaml @@ -0,0 +1,4 @@ +interval: + - interval: 1s + then: + - logger.log: Tick diff --git a/tests/components/interval/test.rp2040.yaml b/tests/components/interval/test.rp2040.yaml new file mode 100644 index 0000000000..2a3c979ae2 --- /dev/null +++ b/tests/components/interval/test.rp2040.yaml @@ -0,0 +1,4 @@ +interval: + - interval: 1s + then: + - logger.log: Tick From ed381b45eb99c0774edf619b4239b7a35a1984e9 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Tue, 23 Apr 2024 04:49:03 -0500 Subject: [PATCH 1312/2101] Add some components to the new testing framework (T) (#6229) --- tests/components/t6615/test.esp32-c3-idf.yaml | 10 ++ tests/components/t6615/test.esp32-c3.yaml | 10 ++ tests/components/t6615/test.esp32-idf.yaml | 10 ++ tests/components/t6615/test.esp32.yaml | 10 ++ tests/components/t6615/test.esp8266.yaml | 10 ++ tests/components/t6615/test.rp2040.yaml | 10 ++ .../tca9548a/test.esp32-c3-idf.yaml | 15 +++ tests/components/tca9548a/test.esp32-c3.yaml | 15 +++ tests/components/tca9548a/test.esp32-idf.yaml | 15 +++ tests/components/tca9548a/test.esp32.yaml | 15 +++ tests/components/tca9548a/test.esp8266.yaml | 15 +++ tests/components/tca9548a/test.rp2040.yaml | 15 +++ .../components/tcl112/test.esp32-c3-idf.yaml | 15 +++ tests/components/tcl112/test.esp32-c3.yaml | 15 +++ tests/components/tcl112/test.esp32-idf.yaml | 15 +++ tests/components/tcl112/test.esp32.yaml | 15 +++ tests/components/tcl112/test.esp8266.yaml | 15 +++ .../tcs34725/test.esp32-c3-idf.yaml | 21 ++++ tests/components/tcs34725/test.esp32-c3.yaml | 21 ++++ tests/components/tcs34725/test.esp32-idf.yaml | 21 ++++ tests/components/tcs34725/test.esp32.yaml | 21 ++++ tests/components/tcs34725/test.esp8266.yaml | 21 ++++ tests/components/tcs34725/test.rp2040.yaml | 21 ++++ .../components/tee501/test.esp32-c3-idf.yaml | 9 ++ tests/components/tee501/test.esp32-c3.yaml | 9 ++ tests/components/tee501/test.esp32-idf.yaml | 9 ++ tests/components/tee501/test.esp32.yaml | 9 ++ tests/components/tee501/test.esp8266.yaml | 9 ++ tests/components/tee501/test.rp2040.yaml | 9 ++ .../teleinfo/test.esp32-c3-idf.yaml | 42 +++++++ tests/components/teleinfo/test.esp32-c3.yaml | 42 +++++++ tests/components/teleinfo/test.esp32-idf.yaml | 42 +++++++ tests/components/teleinfo/test.esp32.yaml | 42 +++++++ tests/components/teleinfo/test.esp8266.yaml | 42 +++++++ tests/components/teleinfo/test.rp2040.yaml | 42 +++++++ .../thermostat/test.esp32-c3-idf.yaml | 93 ++++++++++++++ .../components/thermostat/test.esp32-c3.yaml | 93 ++++++++++++++ .../components/thermostat/test.esp32-idf.yaml | 93 ++++++++++++++ tests/components/thermostat/test.esp32.yaml | 93 ++++++++++++++ tests/components/thermostat/test.esp8266.yaml | 93 ++++++++++++++ tests/components/thermostat/test.rp2040.yaml | 93 ++++++++++++++ tests/components/time/test.esp32-c3-idf.yaml | 10 ++ tests/components/time/test.esp32-c3.yaml | 10 ++ tests/components/time/test.esp32-idf.yaml | 10 ++ tests/components/time/test.esp32.yaml | 10 ++ tests/components/time/test.esp8266.yaml | 10 ++ tests/components/time/test.rp2040.yaml | 10 ++ .../time_based/test.esp32-c3-idf.yaml | 12 ++ .../components/time_based/test.esp32-c3.yaml | 12 ++ .../components/time_based/test.esp32-idf.yaml | 12 ++ tests/components/time_based/test.esp32.yaml | 12 ++ tests/components/time_based/test.esp8266.yaml | 12 ++ tests/components/time_based/test.rp2040.yaml | 12 ++ .../tlc59208f/test.esp32-c3-idf.yaml | 50 ++++++++ tests/components/tlc59208f/test.esp32-c3.yaml | 50 ++++++++ .../components/tlc59208f/test.esp32-idf.yaml | 50 ++++++++ tests/components/tlc59208f/test.esp32.yaml | 50 ++++++++ tests/components/tlc59208f/test.esp8266.yaml | 50 ++++++++ tests/components/tlc59208f/test.rp2040.yaml | 50 ++++++++ .../components/tm1621/test.esp32-c3-idf.yaml | 12 ++ tests/components/tm1621/test.esp32-c3.yaml | 12 ++ tests/components/tm1621/test.esp32-idf.yaml | 12 ++ tests/components/tm1621/test.esp32.yaml | 12 ++ tests/components/tm1621/test.esp8266.yaml | 12 ++ tests/components/tm1621/test.rp2040.yaml | 12 ++ .../components/tm1637/test.esp32-c3-idf.yaml | 7 ++ tests/components/tm1637/test.esp32-c3.yaml | 7 ++ tests/components/tm1637/test.esp32-idf.yaml | 7 ++ tests/components/tm1637/test.esp32.yaml | 7 ++ tests/components/tm1637/test.esp8266.yaml | 7 ++ tests/components/tm1637/test.rp2040.yaml | 7 ++ .../components/tm1638/test.esp32-c3-idf.yaml | 118 ++++++++++++++++++ tests/components/tm1638/test.esp32-c3.yaml | 118 ++++++++++++++++++ tests/components/tm1638/test.esp32-idf.yaml | 118 ++++++++++++++++++ tests/components/tm1638/test.esp32.yaml | 118 ++++++++++++++++++ tests/components/tm1638/test.esp8266.yaml | 118 ++++++++++++++++++ tests/components/tm1638/test.rp2040.yaml | 118 ++++++++++++++++++ tests/components/tm1651/test.esp32-c3.yaml | 21 ++++ tests/components/tm1651/test.esp32.yaml | 21 ++++ tests/components/tm1651/test.esp8266.yaml | 21 ++++ tests/components/tm1651/test.rp2040.yaml | 21 ++++ .../components/tmp102/test.esp32-c3-idf.yaml | 8 ++ tests/components/tmp102/test.esp32-c3.yaml | 8 ++ tests/components/tmp102/test.esp32-idf.yaml | 8 ++ tests/components/tmp102/test.esp32.yaml | 8 ++ tests/components/tmp102/test.esp8266.yaml | 8 ++ tests/components/tmp102/test.rp2040.yaml | 8 ++ .../components/tmp1075/test.esp32-c3-idf.yaml | 16 +++ tests/components/tmp1075/test.esp32-c3.yaml | 16 +++ tests/components/tmp1075/test.esp32-idf.yaml | 16 +++ tests/components/tmp1075/test.esp32.yaml | 16 +++ tests/components/tmp1075/test.esp8266.yaml | 16 +++ tests/components/tmp1075/test.rp2040.yaml | 16 +++ .../components/tmp117/test.esp32-c3-idf.yaml | 9 ++ tests/components/tmp117/test.esp32-c3.yaml | 9 ++ tests/components/tmp117/test.esp32-idf.yaml | 9 ++ tests/components/tmp117/test.esp32.yaml | 9 ++ tests/components/tmp117/test.esp8266.yaml | 9 ++ tests/components/tmp117/test.rp2040.yaml | 9 ++ .../tof10120/test.esp32-c3-idf.yaml | 9 ++ tests/components/tof10120/test.esp32-c3.yaml | 9 ++ tests/components/tof10120/test.esp32-idf.yaml | 9 ++ tests/components/tof10120/test.esp32.yaml | 9 ++ tests/components/tof10120/test.esp8266.yaml | 9 ++ tests/components/tof10120/test.rp2040.yaml | 9 ++ .../components/toshiba/test.esp32-c3-idf.yaml | 7 ++ tests/components/toshiba/test.esp32-c3.yaml | 7 ++ tests/components/toshiba/test.esp32-idf.yaml | 7 ++ tests/components/toshiba/test.esp32.yaml | 7 ++ tests/components/toshiba/test.esp8266.yaml | 7 ++ .../total_daily_energy/test.esp32-c3-idf.yaml | 32 +++++ .../total_daily_energy/test.esp32-c3.yaml | 32 +++++ .../total_daily_energy/test.esp32-idf.yaml | 32 +++++ .../total_daily_energy/test.esp32.yaml | 32 +++++ .../total_daily_energy/test.esp8266.yaml | 32 +++++ .../total_daily_energy/test.rp2040.yaml | 32 +++++ .../components/tsl2561/test.esp32-c3-idf.yaml | 13 ++ tests/components/tsl2561/test.esp32-c3.yaml | 13 ++ tests/components/tsl2561/test.esp32-idf.yaml | 13 ++ tests/components/tsl2561/test.esp32.yaml | 13 ++ tests/components/tsl2561/test.esp8266.yaml | 13 ++ tests/components/tsl2561/test.rp2040.yaml | 13 ++ .../components/tsl2591/test.esp32-c3-idf.yaml | 25 ++++ tests/components/tsl2591/test.esp32-c3.yaml | 25 ++++ tests/components/tsl2591/test.esp32-idf.yaml | 25 ++++ tests/components/tsl2591/test.esp32.yaml | 25 ++++ tests/components/tsl2591/test.esp8266.yaml | 25 ++++ tests/components/tsl2591/test.rp2040.yaml | 25 ++++ .../components/tt21100/test.esp32-c3-idf.yaml | 25 ++++ tests/components/tt21100/test.esp32-c3.yaml | 25 ++++ tests/components/tt21100/test.esp32-idf.yaml | 25 ++++ tests/components/tt21100/test.esp32.yaml | 25 ++++ tests/components/tt21100/test.esp8266.yaml | 25 ++++ tests/components/tt21100/test.rp2040.yaml | 25 ++++ .../ttp229_bsf/test.esp32-c3-idf.yaml | 8 ++ .../components/ttp229_bsf/test.esp32-c3.yaml | 8 ++ .../components/ttp229_bsf/test.esp32-idf.yaml | 8 ++ tests/components/ttp229_bsf/test.esp32.yaml | 8 ++ tests/components/ttp229_bsf/test.esp8266.yaml | 8 ++ tests/components/ttp229_bsf/test.rp2040.yaml | 8 ++ .../ttp229_lsf/test.esp32-c3-idf.yaml | 11 ++ .../components/ttp229_lsf/test.esp32-c3.yaml | 11 ++ .../components/ttp229_lsf/test.esp32-idf.yaml | 11 ++ tests/components/ttp229_lsf/test.esp32.yaml | 11 ++ tests/components/ttp229_lsf/test.esp8266.yaml | 11 ++ tests/components/ttp229_lsf/test.rp2040.yaml | 11 ++ tests/components/tuya/test.esp32-c3-idf.yaml | 78 ++++++++++++ tests/components/tuya/test.esp32-c3.yaml | 78 ++++++++++++ tests/components/tuya/test.esp32-idf.yaml | 78 ++++++++++++ tests/components/tuya/test.esp32.yaml | 78 ++++++++++++ tests/components/tuya/test.esp8266.yaml | 78 ++++++++++++ tests/components/tuya/test.rp2040.yaml | 78 ++++++++++++ tests/components/tx20/test.esp32-c3-idf.yaml | 7 ++ tests/components/tx20/test.esp32-c3.yaml | 7 ++ tests/components/tx20/test.esp32-idf.yaml | 7 ++ tests/components/tx20/test.esp32.yaml | 7 ++ tests/components/tx20/test.esp8266.yaml | 7 ++ tests/components/tx20/test.rp2040.yaml | 7 ++ 158 files changed, 4034 insertions(+) create mode 100644 tests/components/t6615/test.esp32-c3-idf.yaml create mode 100644 tests/components/t6615/test.esp32-c3.yaml create mode 100644 tests/components/t6615/test.esp32-idf.yaml create mode 100644 tests/components/t6615/test.esp32.yaml create mode 100644 tests/components/t6615/test.esp8266.yaml create mode 100644 tests/components/t6615/test.rp2040.yaml create mode 100644 tests/components/tca9548a/test.esp32-c3-idf.yaml create mode 100644 tests/components/tca9548a/test.esp32-c3.yaml create mode 100644 tests/components/tca9548a/test.esp32-idf.yaml create mode 100644 tests/components/tca9548a/test.esp32.yaml create mode 100644 tests/components/tca9548a/test.esp8266.yaml create mode 100644 tests/components/tca9548a/test.rp2040.yaml create mode 100644 tests/components/tcl112/test.esp32-c3-idf.yaml create mode 100644 tests/components/tcl112/test.esp32-c3.yaml create mode 100644 tests/components/tcl112/test.esp32-idf.yaml create mode 100644 tests/components/tcl112/test.esp32.yaml create mode 100644 tests/components/tcl112/test.esp8266.yaml create mode 100644 tests/components/tcs34725/test.esp32-c3-idf.yaml create mode 100644 tests/components/tcs34725/test.esp32-c3.yaml create mode 100644 tests/components/tcs34725/test.esp32-idf.yaml create mode 100644 tests/components/tcs34725/test.esp32.yaml create mode 100644 tests/components/tcs34725/test.esp8266.yaml create mode 100644 tests/components/tcs34725/test.rp2040.yaml create mode 100644 tests/components/tee501/test.esp32-c3-idf.yaml create mode 100644 tests/components/tee501/test.esp32-c3.yaml create mode 100644 tests/components/tee501/test.esp32-idf.yaml create mode 100644 tests/components/tee501/test.esp32.yaml create mode 100644 tests/components/tee501/test.esp8266.yaml create mode 100644 tests/components/tee501/test.rp2040.yaml create mode 100644 tests/components/teleinfo/test.esp32-c3-idf.yaml create mode 100644 tests/components/teleinfo/test.esp32-c3.yaml create mode 100644 tests/components/teleinfo/test.esp32-idf.yaml create mode 100644 tests/components/teleinfo/test.esp32.yaml create mode 100644 tests/components/teleinfo/test.esp8266.yaml create mode 100644 tests/components/teleinfo/test.rp2040.yaml create mode 100644 tests/components/thermostat/test.esp32-c3-idf.yaml create mode 100644 tests/components/thermostat/test.esp32-c3.yaml create mode 100644 tests/components/thermostat/test.esp32-idf.yaml create mode 100644 tests/components/thermostat/test.esp32.yaml create mode 100644 tests/components/thermostat/test.esp8266.yaml create mode 100644 tests/components/thermostat/test.rp2040.yaml create mode 100644 tests/components/time/test.esp32-c3-idf.yaml create mode 100644 tests/components/time/test.esp32-c3.yaml create mode 100644 tests/components/time/test.esp32-idf.yaml create mode 100644 tests/components/time/test.esp32.yaml create mode 100644 tests/components/time/test.esp8266.yaml create mode 100644 tests/components/time/test.rp2040.yaml create mode 100644 tests/components/time_based/test.esp32-c3-idf.yaml create mode 100644 tests/components/time_based/test.esp32-c3.yaml create mode 100644 tests/components/time_based/test.esp32-idf.yaml create mode 100644 tests/components/time_based/test.esp32.yaml create mode 100644 tests/components/time_based/test.esp8266.yaml create mode 100644 tests/components/time_based/test.rp2040.yaml create mode 100644 tests/components/tlc59208f/test.esp32-c3-idf.yaml create mode 100644 tests/components/tlc59208f/test.esp32-c3.yaml create mode 100644 tests/components/tlc59208f/test.esp32-idf.yaml create mode 100644 tests/components/tlc59208f/test.esp32.yaml create mode 100644 tests/components/tlc59208f/test.esp8266.yaml create mode 100644 tests/components/tlc59208f/test.rp2040.yaml create mode 100644 tests/components/tm1621/test.esp32-c3-idf.yaml create mode 100644 tests/components/tm1621/test.esp32-c3.yaml create mode 100644 tests/components/tm1621/test.esp32-idf.yaml create mode 100644 tests/components/tm1621/test.esp32.yaml create mode 100644 tests/components/tm1621/test.esp8266.yaml create mode 100644 tests/components/tm1621/test.rp2040.yaml create mode 100644 tests/components/tm1637/test.esp32-c3-idf.yaml create mode 100644 tests/components/tm1637/test.esp32-c3.yaml create mode 100644 tests/components/tm1637/test.esp32-idf.yaml create mode 100644 tests/components/tm1637/test.esp32.yaml create mode 100644 tests/components/tm1637/test.esp8266.yaml create mode 100644 tests/components/tm1637/test.rp2040.yaml create mode 100644 tests/components/tm1638/test.esp32-c3-idf.yaml create mode 100644 tests/components/tm1638/test.esp32-c3.yaml create mode 100644 tests/components/tm1638/test.esp32-idf.yaml create mode 100644 tests/components/tm1638/test.esp32.yaml create mode 100644 tests/components/tm1638/test.esp8266.yaml create mode 100644 tests/components/tm1638/test.rp2040.yaml create mode 100644 tests/components/tm1651/test.esp32-c3.yaml create mode 100644 tests/components/tm1651/test.esp32.yaml create mode 100644 tests/components/tm1651/test.esp8266.yaml create mode 100644 tests/components/tm1651/test.rp2040.yaml create mode 100644 tests/components/tmp102/test.esp32-c3-idf.yaml create mode 100644 tests/components/tmp102/test.esp32-c3.yaml create mode 100644 tests/components/tmp102/test.esp32-idf.yaml create mode 100644 tests/components/tmp102/test.esp32.yaml create mode 100644 tests/components/tmp102/test.esp8266.yaml create mode 100644 tests/components/tmp102/test.rp2040.yaml create mode 100644 tests/components/tmp1075/test.esp32-c3-idf.yaml create mode 100644 tests/components/tmp1075/test.esp32-c3.yaml create mode 100644 tests/components/tmp1075/test.esp32-idf.yaml create mode 100644 tests/components/tmp1075/test.esp32.yaml create mode 100644 tests/components/tmp1075/test.esp8266.yaml create mode 100644 tests/components/tmp1075/test.rp2040.yaml create mode 100644 tests/components/tmp117/test.esp32-c3-idf.yaml create mode 100644 tests/components/tmp117/test.esp32-c3.yaml create mode 100644 tests/components/tmp117/test.esp32-idf.yaml create mode 100644 tests/components/tmp117/test.esp32.yaml create mode 100644 tests/components/tmp117/test.esp8266.yaml create mode 100644 tests/components/tmp117/test.rp2040.yaml create mode 100644 tests/components/tof10120/test.esp32-c3-idf.yaml create mode 100644 tests/components/tof10120/test.esp32-c3.yaml create mode 100644 tests/components/tof10120/test.esp32-idf.yaml create mode 100644 tests/components/tof10120/test.esp32.yaml create mode 100644 tests/components/tof10120/test.esp8266.yaml create mode 100644 tests/components/tof10120/test.rp2040.yaml create mode 100644 tests/components/toshiba/test.esp32-c3-idf.yaml create mode 100644 tests/components/toshiba/test.esp32-c3.yaml create mode 100644 tests/components/toshiba/test.esp32-idf.yaml create mode 100644 tests/components/toshiba/test.esp32.yaml create mode 100644 tests/components/toshiba/test.esp8266.yaml create mode 100644 tests/components/total_daily_energy/test.esp32-c3-idf.yaml create mode 100644 tests/components/total_daily_energy/test.esp32-c3.yaml create mode 100644 tests/components/total_daily_energy/test.esp32-idf.yaml create mode 100644 tests/components/total_daily_energy/test.esp32.yaml create mode 100644 tests/components/total_daily_energy/test.esp8266.yaml create mode 100644 tests/components/total_daily_energy/test.rp2040.yaml create mode 100644 tests/components/tsl2561/test.esp32-c3-idf.yaml create mode 100644 tests/components/tsl2561/test.esp32-c3.yaml create mode 100644 tests/components/tsl2561/test.esp32-idf.yaml create mode 100644 tests/components/tsl2561/test.esp32.yaml create mode 100644 tests/components/tsl2561/test.esp8266.yaml create mode 100644 tests/components/tsl2561/test.rp2040.yaml create mode 100644 tests/components/tsl2591/test.esp32-c3-idf.yaml create mode 100644 tests/components/tsl2591/test.esp32-c3.yaml create mode 100644 tests/components/tsl2591/test.esp32-idf.yaml create mode 100644 tests/components/tsl2591/test.esp32.yaml create mode 100644 tests/components/tsl2591/test.esp8266.yaml create mode 100644 tests/components/tsl2591/test.rp2040.yaml create mode 100644 tests/components/tt21100/test.esp32-c3-idf.yaml create mode 100644 tests/components/tt21100/test.esp32-c3.yaml create mode 100644 tests/components/tt21100/test.esp32-idf.yaml create mode 100644 tests/components/tt21100/test.esp32.yaml create mode 100644 tests/components/tt21100/test.esp8266.yaml create mode 100644 tests/components/tt21100/test.rp2040.yaml create mode 100644 tests/components/ttp229_bsf/test.esp32-c3-idf.yaml create mode 100644 tests/components/ttp229_bsf/test.esp32-c3.yaml create mode 100644 tests/components/ttp229_bsf/test.esp32-idf.yaml create mode 100644 tests/components/ttp229_bsf/test.esp32.yaml create mode 100644 tests/components/ttp229_bsf/test.esp8266.yaml create mode 100644 tests/components/ttp229_bsf/test.rp2040.yaml create mode 100644 tests/components/ttp229_lsf/test.esp32-c3-idf.yaml create mode 100644 tests/components/ttp229_lsf/test.esp32-c3.yaml create mode 100644 tests/components/ttp229_lsf/test.esp32-idf.yaml create mode 100644 tests/components/ttp229_lsf/test.esp32.yaml create mode 100644 tests/components/ttp229_lsf/test.esp8266.yaml create mode 100644 tests/components/ttp229_lsf/test.rp2040.yaml create mode 100644 tests/components/tuya/test.esp32-c3-idf.yaml create mode 100644 tests/components/tuya/test.esp32-c3.yaml create mode 100644 tests/components/tuya/test.esp32-idf.yaml create mode 100644 tests/components/tuya/test.esp32.yaml create mode 100644 tests/components/tuya/test.esp8266.yaml create mode 100644 tests/components/tuya/test.rp2040.yaml create mode 100644 tests/components/tx20/test.esp32-c3-idf.yaml create mode 100644 tests/components/tx20/test.esp32-c3.yaml create mode 100644 tests/components/tx20/test.esp32-idf.yaml create mode 100644 tests/components/tx20/test.esp32.yaml create mode 100644 tests/components/tx20/test.esp8266.yaml create mode 100644 tests/components/tx20/test.rp2040.yaml diff --git a/tests/components/t6615/test.esp32-c3-idf.yaml b/tests/components/t6615/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..e8690c770f --- /dev/null +++ b/tests/components/t6615/test.esp32-c3-idf.yaml @@ -0,0 +1,10 @@ +uart: + - id: uart_t6615 + tx_pin: 4 + rx_pin: 5 + baud_rate: 19200 + +sensor: + - platform: t6615 + co2: + name: CO2 Sensor diff --git a/tests/components/t6615/test.esp32-c3.yaml b/tests/components/t6615/test.esp32-c3.yaml new file mode 100644 index 0000000000..e8690c770f --- /dev/null +++ b/tests/components/t6615/test.esp32-c3.yaml @@ -0,0 +1,10 @@ +uart: + - id: uart_t6615 + tx_pin: 4 + rx_pin: 5 + baud_rate: 19200 + +sensor: + - platform: t6615 + co2: + name: CO2 Sensor diff --git a/tests/components/t6615/test.esp32-idf.yaml b/tests/components/t6615/test.esp32-idf.yaml new file mode 100644 index 0000000000..2cfaa0ae5b --- /dev/null +++ b/tests/components/t6615/test.esp32-idf.yaml @@ -0,0 +1,10 @@ +uart: + - id: uart_t6615 + tx_pin: 17 + rx_pin: 16 + baud_rate: 19200 + +sensor: + - platform: t6615 + co2: + name: CO2 Sensor diff --git a/tests/components/t6615/test.esp32.yaml b/tests/components/t6615/test.esp32.yaml new file mode 100644 index 0000000000..2cfaa0ae5b --- /dev/null +++ b/tests/components/t6615/test.esp32.yaml @@ -0,0 +1,10 @@ +uart: + - id: uart_t6615 + tx_pin: 17 + rx_pin: 16 + baud_rate: 19200 + +sensor: + - platform: t6615 + co2: + name: CO2 Sensor diff --git a/tests/components/t6615/test.esp8266.yaml b/tests/components/t6615/test.esp8266.yaml new file mode 100644 index 0000000000..e8690c770f --- /dev/null +++ b/tests/components/t6615/test.esp8266.yaml @@ -0,0 +1,10 @@ +uart: + - id: uart_t6615 + tx_pin: 4 + rx_pin: 5 + baud_rate: 19200 + +sensor: + - platform: t6615 + co2: + name: CO2 Sensor diff --git a/tests/components/t6615/test.rp2040.yaml b/tests/components/t6615/test.rp2040.yaml new file mode 100644 index 0000000000..e8690c770f --- /dev/null +++ b/tests/components/t6615/test.rp2040.yaml @@ -0,0 +1,10 @@ +uart: + - id: uart_t6615 + tx_pin: 4 + rx_pin: 5 + baud_rate: 19200 + +sensor: + - platform: t6615 + co2: + name: CO2 Sensor diff --git a/tests/components/tca9548a/test.esp32-c3-idf.yaml b/tests/components/tca9548a/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..2294530d14 --- /dev/null +++ b/tests/components/tca9548a/test.esp32-c3-idf.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_tca9548a + scl: 5 + sda: 4 + +tca9548a: + - id: multiplex0 + address: 0x70 + channels: + - bus_id: multiplex0_chan0 + channel: 0 + i2c_id: i2c_tca9548a + - id: multiplex1 + address: 0x71 + i2c_id: multiplex0_chan0 diff --git a/tests/components/tca9548a/test.esp32-c3.yaml b/tests/components/tca9548a/test.esp32-c3.yaml new file mode 100644 index 0000000000..2294530d14 --- /dev/null +++ b/tests/components/tca9548a/test.esp32-c3.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_tca9548a + scl: 5 + sda: 4 + +tca9548a: + - id: multiplex0 + address: 0x70 + channels: + - bus_id: multiplex0_chan0 + channel: 0 + i2c_id: i2c_tca9548a + - id: multiplex1 + address: 0x71 + i2c_id: multiplex0_chan0 diff --git a/tests/components/tca9548a/test.esp32-idf.yaml b/tests/components/tca9548a/test.esp32-idf.yaml new file mode 100644 index 0000000000..7edb83c821 --- /dev/null +++ b/tests/components/tca9548a/test.esp32-idf.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_tca9548a + scl: 16 + sda: 17 + +tca9548a: + - id: multiplex0 + address: 0x70 + channels: + - bus_id: multiplex0_chan0 + channel: 0 + i2c_id: i2c_tca9548a + - id: multiplex1 + address: 0x71 + i2c_id: multiplex0_chan0 diff --git a/tests/components/tca9548a/test.esp32.yaml b/tests/components/tca9548a/test.esp32.yaml new file mode 100644 index 0000000000..7edb83c821 --- /dev/null +++ b/tests/components/tca9548a/test.esp32.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_tca9548a + scl: 16 + sda: 17 + +tca9548a: + - id: multiplex0 + address: 0x70 + channels: + - bus_id: multiplex0_chan0 + channel: 0 + i2c_id: i2c_tca9548a + - id: multiplex1 + address: 0x71 + i2c_id: multiplex0_chan0 diff --git a/tests/components/tca9548a/test.esp8266.yaml b/tests/components/tca9548a/test.esp8266.yaml new file mode 100644 index 0000000000..2294530d14 --- /dev/null +++ b/tests/components/tca9548a/test.esp8266.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_tca9548a + scl: 5 + sda: 4 + +tca9548a: + - id: multiplex0 + address: 0x70 + channels: + - bus_id: multiplex0_chan0 + channel: 0 + i2c_id: i2c_tca9548a + - id: multiplex1 + address: 0x71 + i2c_id: multiplex0_chan0 diff --git a/tests/components/tca9548a/test.rp2040.yaml b/tests/components/tca9548a/test.rp2040.yaml new file mode 100644 index 0000000000..2294530d14 --- /dev/null +++ b/tests/components/tca9548a/test.rp2040.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_tca9548a + scl: 5 + sda: 4 + +tca9548a: + - id: multiplex0 + address: 0x70 + channels: + - bus_id: multiplex0_chan0 + channel: 0 + i2c_id: i2c_tca9548a + - id: multiplex1 + address: 0x71 + i2c_id: multiplex0_chan0 diff --git a/tests/components/tcl112/test.esp32-c3-idf.yaml b/tests/components/tcl112/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..03c0e84fe5 --- /dev/null +++ b/tests/components/tcl112/test.esp32-c3-idf.yaml @@ -0,0 +1,15 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +sensor: + - platform: template + id: tcl112_sensor + lambda: "return 21;" + +climate: + - platform: tcl112 + name: TCL112 Climate with Sensor + supports_heat: true + supports_cool: true + sensor: tcl112_sensor diff --git a/tests/components/tcl112/test.esp32-c3.yaml b/tests/components/tcl112/test.esp32-c3.yaml new file mode 100644 index 0000000000..03c0e84fe5 --- /dev/null +++ b/tests/components/tcl112/test.esp32-c3.yaml @@ -0,0 +1,15 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +sensor: + - platform: template + id: tcl112_sensor + lambda: "return 21;" + +climate: + - platform: tcl112 + name: TCL112 Climate with Sensor + supports_heat: true + supports_cool: true + sensor: tcl112_sensor diff --git a/tests/components/tcl112/test.esp32-idf.yaml b/tests/components/tcl112/test.esp32-idf.yaml new file mode 100644 index 0000000000..03c0e84fe5 --- /dev/null +++ b/tests/components/tcl112/test.esp32-idf.yaml @@ -0,0 +1,15 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +sensor: + - platform: template + id: tcl112_sensor + lambda: "return 21;" + +climate: + - platform: tcl112 + name: TCL112 Climate with Sensor + supports_heat: true + supports_cool: true + sensor: tcl112_sensor diff --git a/tests/components/tcl112/test.esp32.yaml b/tests/components/tcl112/test.esp32.yaml new file mode 100644 index 0000000000..03c0e84fe5 --- /dev/null +++ b/tests/components/tcl112/test.esp32.yaml @@ -0,0 +1,15 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +sensor: + - platform: template + id: tcl112_sensor + lambda: "return 21;" + +climate: + - platform: tcl112 + name: TCL112 Climate with Sensor + supports_heat: true + supports_cool: true + sensor: tcl112_sensor diff --git a/tests/components/tcl112/test.esp8266.yaml b/tests/components/tcl112/test.esp8266.yaml new file mode 100644 index 0000000000..0a85536928 --- /dev/null +++ b/tests/components/tcl112/test.esp8266.yaml @@ -0,0 +1,15 @@ +remote_transmitter: + pin: 5 + carrier_duty_percent: 50% + +sensor: + - platform: template + id: tcl112_sensor + lambda: "return 21;" + +climate: + - platform: tcl112 + name: TCL112 Climate with Sensor + supports_heat: true + supports_cool: true + sensor: tcl112_sensor diff --git a/tests/components/tcs34725/test.esp32-c3-idf.yaml b/tests/components/tcs34725/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..9b459c9104 --- /dev/null +++ b/tests/components/tcs34725/test.esp32-c3-idf.yaml @@ -0,0 +1,21 @@ +i2c: + - id: i2c_tcs34725 + scl: 5 + sda: 4 + +sensor: + - platform: tcs34725 + red_channel: + name: Red Channel + green_channel: + name: Green Channel + blue_channel: + name: Blue Channel + clear_channel: + name: Clear Channel + illuminance: + name: Illuminance + color_temperature: + name: Color Temperature + integration_time: 614ms + gain: 60x diff --git a/tests/components/tcs34725/test.esp32-c3.yaml b/tests/components/tcs34725/test.esp32-c3.yaml new file mode 100644 index 0000000000..9b459c9104 --- /dev/null +++ b/tests/components/tcs34725/test.esp32-c3.yaml @@ -0,0 +1,21 @@ +i2c: + - id: i2c_tcs34725 + scl: 5 + sda: 4 + +sensor: + - platform: tcs34725 + red_channel: + name: Red Channel + green_channel: + name: Green Channel + blue_channel: + name: Blue Channel + clear_channel: + name: Clear Channel + illuminance: + name: Illuminance + color_temperature: + name: Color Temperature + integration_time: 614ms + gain: 60x diff --git a/tests/components/tcs34725/test.esp32-idf.yaml b/tests/components/tcs34725/test.esp32-idf.yaml new file mode 100644 index 0000000000..86ef82962e --- /dev/null +++ b/tests/components/tcs34725/test.esp32-idf.yaml @@ -0,0 +1,21 @@ +i2c: + - id: i2c_tcs34725 + scl: 16 + sda: 17 + +sensor: + - platform: tcs34725 + red_channel: + name: Red Channel + green_channel: + name: Green Channel + blue_channel: + name: Blue Channel + clear_channel: + name: Clear Channel + illuminance: + name: Illuminance + color_temperature: + name: Color Temperature + integration_time: 614ms + gain: 60x diff --git a/tests/components/tcs34725/test.esp32.yaml b/tests/components/tcs34725/test.esp32.yaml new file mode 100644 index 0000000000..86ef82962e --- /dev/null +++ b/tests/components/tcs34725/test.esp32.yaml @@ -0,0 +1,21 @@ +i2c: + - id: i2c_tcs34725 + scl: 16 + sda: 17 + +sensor: + - platform: tcs34725 + red_channel: + name: Red Channel + green_channel: + name: Green Channel + blue_channel: + name: Blue Channel + clear_channel: + name: Clear Channel + illuminance: + name: Illuminance + color_temperature: + name: Color Temperature + integration_time: 614ms + gain: 60x diff --git a/tests/components/tcs34725/test.esp8266.yaml b/tests/components/tcs34725/test.esp8266.yaml new file mode 100644 index 0000000000..9b459c9104 --- /dev/null +++ b/tests/components/tcs34725/test.esp8266.yaml @@ -0,0 +1,21 @@ +i2c: + - id: i2c_tcs34725 + scl: 5 + sda: 4 + +sensor: + - platform: tcs34725 + red_channel: + name: Red Channel + green_channel: + name: Green Channel + blue_channel: + name: Blue Channel + clear_channel: + name: Clear Channel + illuminance: + name: Illuminance + color_temperature: + name: Color Temperature + integration_time: 614ms + gain: 60x diff --git a/tests/components/tcs34725/test.rp2040.yaml b/tests/components/tcs34725/test.rp2040.yaml new file mode 100644 index 0000000000..9b459c9104 --- /dev/null +++ b/tests/components/tcs34725/test.rp2040.yaml @@ -0,0 +1,21 @@ +i2c: + - id: i2c_tcs34725 + scl: 5 + sda: 4 + +sensor: + - platform: tcs34725 + red_channel: + name: Red Channel + green_channel: + name: Green Channel + blue_channel: + name: Blue Channel + clear_channel: + name: Clear Channel + illuminance: + name: Illuminance + color_temperature: + name: Color Temperature + integration_time: 614ms + gain: 60x diff --git a/tests/components/tee501/test.esp32-c3-idf.yaml b/tests/components/tee501/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..11991a6153 --- /dev/null +++ b/tests/components/tee501/test.esp32-c3-idf.yaml @@ -0,0 +1,9 @@ +i2c: + - id: i2c_tee501 + scl: 5 + sda: 4 + +sensor: + - platform: tee501 + name: TEE501 Temperature + address: 0x48 diff --git a/tests/components/tee501/test.esp32-c3.yaml b/tests/components/tee501/test.esp32-c3.yaml new file mode 100644 index 0000000000..11991a6153 --- /dev/null +++ b/tests/components/tee501/test.esp32-c3.yaml @@ -0,0 +1,9 @@ +i2c: + - id: i2c_tee501 + scl: 5 + sda: 4 + +sensor: + - platform: tee501 + name: TEE501 Temperature + address: 0x48 diff --git a/tests/components/tee501/test.esp32-idf.yaml b/tests/components/tee501/test.esp32-idf.yaml new file mode 100644 index 0000000000..acf6fed4bf --- /dev/null +++ b/tests/components/tee501/test.esp32-idf.yaml @@ -0,0 +1,9 @@ +i2c: + - id: i2c_tee501 + scl: 16 + sda: 17 + +sensor: + - platform: tee501 + name: TEE501 Temperature + address: 0x48 diff --git a/tests/components/tee501/test.esp32.yaml b/tests/components/tee501/test.esp32.yaml new file mode 100644 index 0000000000..acf6fed4bf --- /dev/null +++ b/tests/components/tee501/test.esp32.yaml @@ -0,0 +1,9 @@ +i2c: + - id: i2c_tee501 + scl: 16 + sda: 17 + +sensor: + - platform: tee501 + name: TEE501 Temperature + address: 0x48 diff --git a/tests/components/tee501/test.esp8266.yaml b/tests/components/tee501/test.esp8266.yaml new file mode 100644 index 0000000000..11991a6153 --- /dev/null +++ b/tests/components/tee501/test.esp8266.yaml @@ -0,0 +1,9 @@ +i2c: + - id: i2c_tee501 + scl: 5 + sda: 4 + +sensor: + - platform: tee501 + name: TEE501 Temperature + address: 0x48 diff --git a/tests/components/tee501/test.rp2040.yaml b/tests/components/tee501/test.rp2040.yaml new file mode 100644 index 0000000000..11991a6153 --- /dev/null +++ b/tests/components/tee501/test.rp2040.yaml @@ -0,0 +1,9 @@ +i2c: + - id: i2c_tee501 + scl: 5 + sda: 4 + +sensor: + - platform: tee501 + name: TEE501 Temperature + address: 0x48 diff --git a/tests/components/teleinfo/test.esp32-c3-idf.yaml b/tests/components/teleinfo/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..55641e1e01 --- /dev/null +++ b/tests/components/teleinfo/test.esp32-c3-idf.yaml @@ -0,0 +1,42 @@ +uart: + - id: uart_teleinfo + tx_pin: 4 + rx_pin: 5 + baud_rate: 1200 + parity: EVEN + +button: + - platform: template + name: Poller component suspend test + on_press: + - component.suspend: test_teleinfo + - delay: 20s + - component.update: test_teleinfo + - delay: 20s + - component.resume: test_teleinfo + - delay: 20s + - component.resume: + id: test_teleinfo + update_interval: 2s + - delay: 20s + - component.resume: + id: test_teleinfo + update_interval: !lambda return 2500; + +teleinfo: + id: test_teleinfo + historical_mode: true + update_interval: 60s + +sensor: + - platform: teleinfo + name: hchc + tag_name: HCHC + teleinfo_id: test_teleinfo + unit_of_measurement: Wh + +text_sensor: + - platform: teleinfo + name: optarif + tag_name: OPTARIF + teleinfo_id: test_teleinfo diff --git a/tests/components/teleinfo/test.esp32-c3.yaml b/tests/components/teleinfo/test.esp32-c3.yaml new file mode 100644 index 0000000000..55641e1e01 --- /dev/null +++ b/tests/components/teleinfo/test.esp32-c3.yaml @@ -0,0 +1,42 @@ +uart: + - id: uart_teleinfo + tx_pin: 4 + rx_pin: 5 + baud_rate: 1200 + parity: EVEN + +button: + - platform: template + name: Poller component suspend test + on_press: + - component.suspend: test_teleinfo + - delay: 20s + - component.update: test_teleinfo + - delay: 20s + - component.resume: test_teleinfo + - delay: 20s + - component.resume: + id: test_teleinfo + update_interval: 2s + - delay: 20s + - component.resume: + id: test_teleinfo + update_interval: !lambda return 2500; + +teleinfo: + id: test_teleinfo + historical_mode: true + update_interval: 60s + +sensor: + - platform: teleinfo + name: hchc + tag_name: HCHC + teleinfo_id: test_teleinfo + unit_of_measurement: Wh + +text_sensor: + - platform: teleinfo + name: optarif + tag_name: OPTARIF + teleinfo_id: test_teleinfo diff --git a/tests/components/teleinfo/test.esp32-idf.yaml b/tests/components/teleinfo/test.esp32-idf.yaml new file mode 100644 index 0000000000..a5bd176143 --- /dev/null +++ b/tests/components/teleinfo/test.esp32-idf.yaml @@ -0,0 +1,42 @@ +uart: + - id: uart_teleinfo + tx_pin: 17 + rx_pin: 16 + baud_rate: 1200 + parity: EVEN + +button: + - platform: template + name: Poller component suspend test + on_press: + - component.suspend: test_teleinfo + - delay: 20s + - component.update: test_teleinfo + - delay: 20s + - component.resume: test_teleinfo + - delay: 20s + - component.resume: + id: test_teleinfo + update_interval: 2s + - delay: 20s + - component.resume: + id: test_teleinfo + update_interval: !lambda return 2500; + +teleinfo: + id: test_teleinfo + historical_mode: true + update_interval: 60s + +sensor: + - platform: teleinfo + name: hchc + tag_name: HCHC + teleinfo_id: test_teleinfo + unit_of_measurement: Wh + +text_sensor: + - platform: teleinfo + name: optarif + tag_name: OPTARIF + teleinfo_id: test_teleinfo diff --git a/tests/components/teleinfo/test.esp32.yaml b/tests/components/teleinfo/test.esp32.yaml new file mode 100644 index 0000000000..a5bd176143 --- /dev/null +++ b/tests/components/teleinfo/test.esp32.yaml @@ -0,0 +1,42 @@ +uart: + - id: uart_teleinfo + tx_pin: 17 + rx_pin: 16 + baud_rate: 1200 + parity: EVEN + +button: + - platform: template + name: Poller component suspend test + on_press: + - component.suspend: test_teleinfo + - delay: 20s + - component.update: test_teleinfo + - delay: 20s + - component.resume: test_teleinfo + - delay: 20s + - component.resume: + id: test_teleinfo + update_interval: 2s + - delay: 20s + - component.resume: + id: test_teleinfo + update_interval: !lambda return 2500; + +teleinfo: + id: test_teleinfo + historical_mode: true + update_interval: 60s + +sensor: + - platform: teleinfo + name: hchc + tag_name: HCHC + teleinfo_id: test_teleinfo + unit_of_measurement: Wh + +text_sensor: + - platform: teleinfo + name: optarif + tag_name: OPTARIF + teleinfo_id: test_teleinfo diff --git a/tests/components/teleinfo/test.esp8266.yaml b/tests/components/teleinfo/test.esp8266.yaml new file mode 100644 index 0000000000..55641e1e01 --- /dev/null +++ b/tests/components/teleinfo/test.esp8266.yaml @@ -0,0 +1,42 @@ +uart: + - id: uart_teleinfo + tx_pin: 4 + rx_pin: 5 + baud_rate: 1200 + parity: EVEN + +button: + - platform: template + name: Poller component suspend test + on_press: + - component.suspend: test_teleinfo + - delay: 20s + - component.update: test_teleinfo + - delay: 20s + - component.resume: test_teleinfo + - delay: 20s + - component.resume: + id: test_teleinfo + update_interval: 2s + - delay: 20s + - component.resume: + id: test_teleinfo + update_interval: !lambda return 2500; + +teleinfo: + id: test_teleinfo + historical_mode: true + update_interval: 60s + +sensor: + - platform: teleinfo + name: hchc + tag_name: HCHC + teleinfo_id: test_teleinfo + unit_of_measurement: Wh + +text_sensor: + - platform: teleinfo + name: optarif + tag_name: OPTARIF + teleinfo_id: test_teleinfo diff --git a/tests/components/teleinfo/test.rp2040.yaml b/tests/components/teleinfo/test.rp2040.yaml new file mode 100644 index 0000000000..55641e1e01 --- /dev/null +++ b/tests/components/teleinfo/test.rp2040.yaml @@ -0,0 +1,42 @@ +uart: + - id: uart_teleinfo + tx_pin: 4 + rx_pin: 5 + baud_rate: 1200 + parity: EVEN + +button: + - platform: template + name: Poller component suspend test + on_press: + - component.suspend: test_teleinfo + - delay: 20s + - component.update: test_teleinfo + - delay: 20s + - component.resume: test_teleinfo + - delay: 20s + - component.resume: + id: test_teleinfo + update_interval: 2s + - delay: 20s + - component.resume: + id: test_teleinfo + update_interval: !lambda return 2500; + +teleinfo: + id: test_teleinfo + historical_mode: true + update_interval: 60s + +sensor: + - platform: teleinfo + name: hchc + tag_name: HCHC + teleinfo_id: test_teleinfo + unit_of_measurement: Wh + +text_sensor: + - platform: teleinfo + name: optarif + tag_name: OPTARIF + teleinfo_id: test_teleinfo diff --git a/tests/components/thermostat/test.esp32-c3-idf.yaml b/tests/components/thermostat/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..d630a93efc --- /dev/null +++ b/tests/components/thermostat/test.esp32-c3-idf.yaml @@ -0,0 +1,93 @@ +sensor: + - platform: template + id: thermostat_sensor + lambda: "return 21;" + +climate: + - platform: thermostat + name: Test Thermostat + sensor: thermostat_sensor + humidity_sensor: thermostat_sensor + preset: + - name: Default Preset + default_target_temperature_low: 18°C + default_target_temperature_high: 24°C + - name: Away + default_target_temperature_low: 16°C + default_target_temperature_high: 20°C + idle_action: + - logger.log: idle_action + cool_action: + - logger.log: cool_action + supplemental_cooling_action: + - logger.log: supplemental_cooling_action + heat_action: + - logger.log: heat_action + supplemental_heating_action: + - logger.log: supplemental_heating_action + dry_action: + - logger.log: dry_action + fan_only_action: + - logger.log: fan_only_action + auto_mode: + - logger.log: auto_mode + off_mode: + - logger.log: off_mode + heat_mode: + - logger.log: heat_mode + cool_mode: + - logger.log: cool_mode + dry_mode: + - logger.log: dry_mode + fan_only_mode: + - logger.log: fan_only_mode + fan_mode_auto_action: + - logger.log: fan_mode_auto_action + fan_mode_on_action: + - logger.log: fan_mode_on_action + fan_mode_off_action: + - logger.log: fan_mode_off_action + fan_mode_low_action: + - logger.log: fan_mode_low_action + fan_mode_medium_action: + - logger.log: fan_mode_medium_action + fan_mode_high_action: + - logger.log: fan_mode_high_action + fan_mode_middle_action: + - logger.log: fan_mode_middle_action + fan_mode_focus_action: + - logger.log: fan_mode_focus_action + fan_mode_diffuse_action: + - logger.log: fan_mode_diffuse_action + fan_mode_quiet_action: + - logger.log: fan_mode_quiet_action + swing_off_action: + - logger.log: swing_off_action + swing_horizontal_action: + - logger.log: swing_horizontal_action + swing_vertical_action: + - logger.log: swing_vertical_action + swing_both_action: + - logger.log: swing_both_action + startup_delay: true + supplemental_cooling_delta: 2.0 + cool_deadband: 0.5 + cool_overrun: 0.5 + min_cooling_off_time: 300s + min_cooling_run_time: 300s + max_cooling_run_time: 600s + supplemental_heating_delta: 2.0 + heat_deadband: 0.5 + heat_overrun: 0.5 + min_heating_off_time: 300s + min_heating_run_time: 300s + max_heating_run_time: 600s + min_fanning_off_time: 30s + min_fanning_run_time: 30s + min_fan_mode_switching_time: 15s + min_idle_time: 30s + set_point_minimum_differential: 0.5 + fan_only_action_uses_fan_mode_timer: true + fan_only_cooling: true + fan_with_cooling: true + fan_with_heating: true diff --git a/tests/components/thermostat/test.esp32-c3.yaml b/tests/components/thermostat/test.esp32-c3.yaml new file mode 100644 index 0000000000..d630a93efc --- /dev/null +++ b/tests/components/thermostat/test.esp32-c3.yaml @@ -0,0 +1,93 @@ +sensor: + - platform: template + id: thermostat_sensor + lambda: "return 21;" + +climate: + - platform: thermostat + name: Test Thermostat + sensor: thermostat_sensor + humidity_sensor: thermostat_sensor + preset: + - name: Default Preset + default_target_temperature_low: 18°C + default_target_temperature_high: 24°C + - name: Away + default_target_temperature_low: 16°C + default_target_temperature_high: 20°C + idle_action: + - logger.log: idle_action + cool_action: + - logger.log: cool_action + supplemental_cooling_action: + - logger.log: supplemental_cooling_action + heat_action: + - logger.log: heat_action + supplemental_heating_action: + - logger.log: supplemental_heating_action + dry_action: + - logger.log: dry_action + fan_only_action: + - logger.log: fan_only_action + auto_mode: + - logger.log: auto_mode + off_mode: + - logger.log: off_mode + heat_mode: + - logger.log: heat_mode + cool_mode: + - logger.log: cool_mode + dry_mode: + - logger.log: dry_mode + fan_only_mode: + - logger.log: fan_only_mode + fan_mode_auto_action: + - logger.log: fan_mode_auto_action + fan_mode_on_action: + - logger.log: fan_mode_on_action + fan_mode_off_action: + - logger.log: fan_mode_off_action + fan_mode_low_action: + - logger.log: fan_mode_low_action + fan_mode_medium_action: + - logger.log: fan_mode_medium_action + fan_mode_high_action: + - logger.log: fan_mode_high_action + fan_mode_middle_action: + - logger.log: fan_mode_middle_action + fan_mode_focus_action: + - logger.log: fan_mode_focus_action + fan_mode_diffuse_action: + - logger.log: fan_mode_diffuse_action + fan_mode_quiet_action: + - logger.log: fan_mode_quiet_action + swing_off_action: + - logger.log: swing_off_action + swing_horizontal_action: + - logger.log: swing_horizontal_action + swing_vertical_action: + - logger.log: swing_vertical_action + swing_both_action: + - logger.log: swing_both_action + startup_delay: true + supplemental_cooling_delta: 2.0 + cool_deadband: 0.5 + cool_overrun: 0.5 + min_cooling_off_time: 300s + min_cooling_run_time: 300s + max_cooling_run_time: 600s + supplemental_heating_delta: 2.0 + heat_deadband: 0.5 + heat_overrun: 0.5 + min_heating_off_time: 300s + min_heating_run_time: 300s + max_heating_run_time: 600s + min_fanning_off_time: 30s + min_fanning_run_time: 30s + min_fan_mode_switching_time: 15s + min_idle_time: 30s + set_point_minimum_differential: 0.5 + fan_only_action_uses_fan_mode_timer: true + fan_only_cooling: true + fan_with_cooling: true + fan_with_heating: true diff --git a/tests/components/thermostat/test.esp32-idf.yaml b/tests/components/thermostat/test.esp32-idf.yaml new file mode 100644 index 0000000000..d630a93efc --- /dev/null +++ b/tests/components/thermostat/test.esp32-idf.yaml @@ -0,0 +1,93 @@ +sensor: + - platform: template + id: thermostat_sensor + lambda: "return 21;" + +climate: + - platform: thermostat + name: Test Thermostat + sensor: thermostat_sensor + humidity_sensor: thermostat_sensor + preset: + - name: Default Preset + default_target_temperature_low: 18°C + default_target_temperature_high: 24°C + - name: Away + default_target_temperature_low: 16°C + default_target_temperature_high: 20°C + idle_action: + - logger.log: idle_action + cool_action: + - logger.log: cool_action + supplemental_cooling_action: + - logger.log: supplemental_cooling_action + heat_action: + - logger.log: heat_action + supplemental_heating_action: + - logger.log: supplemental_heating_action + dry_action: + - logger.log: dry_action + fan_only_action: + - logger.log: fan_only_action + auto_mode: + - logger.log: auto_mode + off_mode: + - logger.log: off_mode + heat_mode: + - logger.log: heat_mode + cool_mode: + - logger.log: cool_mode + dry_mode: + - logger.log: dry_mode + fan_only_mode: + - logger.log: fan_only_mode + fan_mode_auto_action: + - logger.log: fan_mode_auto_action + fan_mode_on_action: + - logger.log: fan_mode_on_action + fan_mode_off_action: + - logger.log: fan_mode_off_action + fan_mode_low_action: + - logger.log: fan_mode_low_action + fan_mode_medium_action: + - logger.log: fan_mode_medium_action + fan_mode_high_action: + - logger.log: fan_mode_high_action + fan_mode_middle_action: + - logger.log: fan_mode_middle_action + fan_mode_focus_action: + - logger.log: fan_mode_focus_action + fan_mode_diffuse_action: + - logger.log: fan_mode_diffuse_action + fan_mode_quiet_action: + - logger.log: fan_mode_quiet_action + swing_off_action: + - logger.log: swing_off_action + swing_horizontal_action: + - logger.log: swing_horizontal_action + swing_vertical_action: + - logger.log: swing_vertical_action + swing_both_action: + - logger.log: swing_both_action + startup_delay: true + supplemental_cooling_delta: 2.0 + cool_deadband: 0.5 + cool_overrun: 0.5 + min_cooling_off_time: 300s + min_cooling_run_time: 300s + max_cooling_run_time: 600s + supplemental_heating_delta: 2.0 + heat_deadband: 0.5 + heat_overrun: 0.5 + min_heating_off_time: 300s + min_heating_run_time: 300s + max_heating_run_time: 600s + min_fanning_off_time: 30s + min_fanning_run_time: 30s + min_fan_mode_switching_time: 15s + min_idle_time: 30s + set_point_minimum_differential: 0.5 + fan_only_action_uses_fan_mode_timer: true + fan_only_cooling: true + fan_with_cooling: true + fan_with_heating: true diff --git a/tests/components/thermostat/test.esp32.yaml b/tests/components/thermostat/test.esp32.yaml new file mode 100644 index 0000000000..d630a93efc --- /dev/null +++ b/tests/components/thermostat/test.esp32.yaml @@ -0,0 +1,93 @@ +sensor: + - platform: template + id: thermostat_sensor + lambda: "return 21;" + +climate: + - platform: thermostat + name: Test Thermostat + sensor: thermostat_sensor + humidity_sensor: thermostat_sensor + preset: + - name: Default Preset + default_target_temperature_low: 18°C + default_target_temperature_high: 24°C + - name: Away + default_target_temperature_low: 16°C + default_target_temperature_high: 20°C + idle_action: + - logger.log: idle_action + cool_action: + - logger.log: cool_action + supplemental_cooling_action: + - logger.log: supplemental_cooling_action + heat_action: + - logger.log: heat_action + supplemental_heating_action: + - logger.log: supplemental_heating_action + dry_action: + - logger.log: dry_action + fan_only_action: + - logger.log: fan_only_action + auto_mode: + - logger.log: auto_mode + off_mode: + - logger.log: off_mode + heat_mode: + - logger.log: heat_mode + cool_mode: + - logger.log: cool_mode + dry_mode: + - logger.log: dry_mode + fan_only_mode: + - logger.log: fan_only_mode + fan_mode_auto_action: + - logger.log: fan_mode_auto_action + fan_mode_on_action: + - logger.log: fan_mode_on_action + fan_mode_off_action: + - logger.log: fan_mode_off_action + fan_mode_low_action: + - logger.log: fan_mode_low_action + fan_mode_medium_action: + - logger.log: fan_mode_medium_action + fan_mode_high_action: + - logger.log: fan_mode_high_action + fan_mode_middle_action: + - logger.log: fan_mode_middle_action + fan_mode_focus_action: + - logger.log: fan_mode_focus_action + fan_mode_diffuse_action: + - logger.log: fan_mode_diffuse_action + fan_mode_quiet_action: + - logger.log: fan_mode_quiet_action + swing_off_action: + - logger.log: swing_off_action + swing_horizontal_action: + - logger.log: swing_horizontal_action + swing_vertical_action: + - logger.log: swing_vertical_action + swing_both_action: + - logger.log: swing_both_action + startup_delay: true + supplemental_cooling_delta: 2.0 + cool_deadband: 0.5 + cool_overrun: 0.5 + min_cooling_off_time: 300s + min_cooling_run_time: 300s + max_cooling_run_time: 600s + supplemental_heating_delta: 2.0 + heat_deadband: 0.5 + heat_overrun: 0.5 + min_heating_off_time: 300s + min_heating_run_time: 300s + max_heating_run_time: 600s + min_fanning_off_time: 30s + min_fanning_run_time: 30s + min_fan_mode_switching_time: 15s + min_idle_time: 30s + set_point_minimum_differential: 0.5 + fan_only_action_uses_fan_mode_timer: true + fan_only_cooling: true + fan_with_cooling: true + fan_with_heating: true diff --git a/tests/components/thermostat/test.esp8266.yaml b/tests/components/thermostat/test.esp8266.yaml new file mode 100644 index 0000000000..d630a93efc --- /dev/null +++ b/tests/components/thermostat/test.esp8266.yaml @@ -0,0 +1,93 @@ +sensor: + - platform: template + id: thermostat_sensor + lambda: "return 21;" + +climate: + - platform: thermostat + name: Test Thermostat + sensor: thermostat_sensor + humidity_sensor: thermostat_sensor + preset: + - name: Default Preset + default_target_temperature_low: 18°C + default_target_temperature_high: 24°C + - name: Away + default_target_temperature_low: 16°C + default_target_temperature_high: 20°C + idle_action: + - logger.log: idle_action + cool_action: + - logger.log: cool_action + supplemental_cooling_action: + - logger.log: supplemental_cooling_action + heat_action: + - logger.log: heat_action + supplemental_heating_action: + - logger.log: supplemental_heating_action + dry_action: + - logger.log: dry_action + fan_only_action: + - logger.log: fan_only_action + auto_mode: + - logger.log: auto_mode + off_mode: + - logger.log: off_mode + heat_mode: + - logger.log: heat_mode + cool_mode: + - logger.log: cool_mode + dry_mode: + - logger.log: dry_mode + fan_only_mode: + - logger.log: fan_only_mode + fan_mode_auto_action: + - logger.log: fan_mode_auto_action + fan_mode_on_action: + - logger.log: fan_mode_on_action + fan_mode_off_action: + - logger.log: fan_mode_off_action + fan_mode_low_action: + - logger.log: fan_mode_low_action + fan_mode_medium_action: + - logger.log: fan_mode_medium_action + fan_mode_high_action: + - logger.log: fan_mode_high_action + fan_mode_middle_action: + - logger.log: fan_mode_middle_action + fan_mode_focus_action: + - logger.log: fan_mode_focus_action + fan_mode_diffuse_action: + - logger.log: fan_mode_diffuse_action + fan_mode_quiet_action: + - logger.log: fan_mode_quiet_action + swing_off_action: + - logger.log: swing_off_action + swing_horizontal_action: + - logger.log: swing_horizontal_action + swing_vertical_action: + - logger.log: swing_vertical_action + swing_both_action: + - logger.log: swing_both_action + startup_delay: true + supplemental_cooling_delta: 2.0 + cool_deadband: 0.5 + cool_overrun: 0.5 + min_cooling_off_time: 300s + min_cooling_run_time: 300s + max_cooling_run_time: 600s + supplemental_heating_delta: 2.0 + heat_deadband: 0.5 + heat_overrun: 0.5 + min_heating_off_time: 300s + min_heating_run_time: 300s + max_heating_run_time: 600s + min_fanning_off_time: 30s + min_fanning_run_time: 30s + min_fan_mode_switching_time: 15s + min_idle_time: 30s + set_point_minimum_differential: 0.5 + fan_only_action_uses_fan_mode_timer: true + fan_only_cooling: true + fan_with_cooling: true + fan_with_heating: true diff --git a/tests/components/thermostat/test.rp2040.yaml b/tests/components/thermostat/test.rp2040.yaml new file mode 100644 index 0000000000..d630a93efc --- /dev/null +++ b/tests/components/thermostat/test.rp2040.yaml @@ -0,0 +1,93 @@ +sensor: + - platform: template + id: thermostat_sensor + lambda: "return 21;" + +climate: + - platform: thermostat + name: Test Thermostat + sensor: thermostat_sensor + humidity_sensor: thermostat_sensor + preset: + - name: Default Preset + default_target_temperature_low: 18°C + default_target_temperature_high: 24°C + - name: Away + default_target_temperature_low: 16°C + default_target_temperature_high: 20°C + idle_action: + - logger.log: idle_action + cool_action: + - logger.log: cool_action + supplemental_cooling_action: + - logger.log: supplemental_cooling_action + heat_action: + - logger.log: heat_action + supplemental_heating_action: + - logger.log: supplemental_heating_action + dry_action: + - logger.log: dry_action + fan_only_action: + - logger.log: fan_only_action + auto_mode: + - logger.log: auto_mode + off_mode: + - logger.log: off_mode + heat_mode: + - logger.log: heat_mode + cool_mode: + - logger.log: cool_mode + dry_mode: + - logger.log: dry_mode + fan_only_mode: + - logger.log: fan_only_mode + fan_mode_auto_action: + - logger.log: fan_mode_auto_action + fan_mode_on_action: + - logger.log: fan_mode_on_action + fan_mode_off_action: + - logger.log: fan_mode_off_action + fan_mode_low_action: + - logger.log: fan_mode_low_action + fan_mode_medium_action: + - logger.log: fan_mode_medium_action + fan_mode_high_action: + - logger.log: fan_mode_high_action + fan_mode_middle_action: + - logger.log: fan_mode_middle_action + fan_mode_focus_action: + - logger.log: fan_mode_focus_action + fan_mode_diffuse_action: + - logger.log: fan_mode_diffuse_action + fan_mode_quiet_action: + - logger.log: fan_mode_quiet_action + swing_off_action: + - logger.log: swing_off_action + swing_horizontal_action: + - logger.log: swing_horizontal_action + swing_vertical_action: + - logger.log: swing_vertical_action + swing_both_action: + - logger.log: swing_both_action + startup_delay: true + supplemental_cooling_delta: 2.0 + cool_deadband: 0.5 + cool_overrun: 0.5 + min_cooling_off_time: 300s + min_cooling_run_time: 300s + max_cooling_run_time: 600s + supplemental_heating_delta: 2.0 + heat_deadband: 0.5 + heat_overrun: 0.5 + min_heating_off_time: 300s + min_heating_run_time: 300s + max_heating_run_time: 600s + min_fanning_off_time: 30s + min_fanning_run_time: 30s + min_fan_mode_switching_time: 15s + min_idle_time: 30s + set_point_minimum_differential: 0.5 + fan_only_action_uses_fan_mode_timer: true + fan_only_cooling: true + fan_with_cooling: true + fan_with_heating: true diff --git a/tests/components/time/test.esp32-c3-idf.yaml b/tests/components/time/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..465be045db --- /dev/null +++ b/tests/components/time/test.esp32-c3-idf.yaml @@ -0,0 +1,10 @@ +wifi: + ssid: MySSID + password: password1 + +api: + +time: + - platform: homeassistant + - platform: sntp + id: sntp_time diff --git a/tests/components/time/test.esp32-c3.yaml b/tests/components/time/test.esp32-c3.yaml new file mode 100644 index 0000000000..465be045db --- /dev/null +++ b/tests/components/time/test.esp32-c3.yaml @@ -0,0 +1,10 @@ +wifi: + ssid: MySSID + password: password1 + +api: + +time: + - platform: homeassistant + - platform: sntp + id: sntp_time diff --git a/tests/components/time/test.esp32-idf.yaml b/tests/components/time/test.esp32-idf.yaml new file mode 100644 index 0000000000..465be045db --- /dev/null +++ b/tests/components/time/test.esp32-idf.yaml @@ -0,0 +1,10 @@ +wifi: + ssid: MySSID + password: password1 + +api: + +time: + - platform: homeassistant + - platform: sntp + id: sntp_time diff --git a/tests/components/time/test.esp32.yaml b/tests/components/time/test.esp32.yaml new file mode 100644 index 0000000000..465be045db --- /dev/null +++ b/tests/components/time/test.esp32.yaml @@ -0,0 +1,10 @@ +wifi: + ssid: MySSID + password: password1 + +api: + +time: + - platform: homeassistant + - platform: sntp + id: sntp_time diff --git a/tests/components/time/test.esp8266.yaml b/tests/components/time/test.esp8266.yaml new file mode 100644 index 0000000000..465be045db --- /dev/null +++ b/tests/components/time/test.esp8266.yaml @@ -0,0 +1,10 @@ +wifi: + ssid: MySSID + password: password1 + +api: + +time: + - platform: homeassistant + - platform: sntp + id: sntp_time diff --git a/tests/components/time/test.rp2040.yaml b/tests/components/time/test.rp2040.yaml new file mode 100644 index 0000000000..465be045db --- /dev/null +++ b/tests/components/time/test.rp2040.yaml @@ -0,0 +1,10 @@ +wifi: + ssid: MySSID + password: password1 + +api: + +time: + - platform: homeassistant + - platform: sntp + id: sntp_time diff --git a/tests/components/time_based/test.esp32-c3-idf.yaml b/tests/components/time_based/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..48c86de90f --- /dev/null +++ b/tests/components/time_based/test.esp32-c3-idf.yaml @@ -0,0 +1,12 @@ +cover: + - platform: time_based + name: Time Based Cover + id: time_based_cover + stop_action: + - logger.log: stop_action + open_action: + - logger.log: open_action + open_duration: 5min + close_action: + - logger.log: close_action + close_duration: 4.5min diff --git a/tests/components/time_based/test.esp32-c3.yaml b/tests/components/time_based/test.esp32-c3.yaml new file mode 100644 index 0000000000..48c86de90f --- /dev/null +++ b/tests/components/time_based/test.esp32-c3.yaml @@ -0,0 +1,12 @@ +cover: + - platform: time_based + name: Time Based Cover + id: time_based_cover + stop_action: + - logger.log: stop_action + open_action: + - logger.log: open_action + open_duration: 5min + close_action: + - logger.log: close_action + close_duration: 4.5min diff --git a/tests/components/time_based/test.esp32-idf.yaml b/tests/components/time_based/test.esp32-idf.yaml new file mode 100644 index 0000000000..48c86de90f --- /dev/null +++ b/tests/components/time_based/test.esp32-idf.yaml @@ -0,0 +1,12 @@ +cover: + - platform: time_based + name: Time Based Cover + id: time_based_cover + stop_action: + - logger.log: stop_action + open_action: + - logger.log: open_action + open_duration: 5min + close_action: + - logger.log: close_action + close_duration: 4.5min diff --git a/tests/components/time_based/test.esp32.yaml b/tests/components/time_based/test.esp32.yaml new file mode 100644 index 0000000000..48c86de90f --- /dev/null +++ b/tests/components/time_based/test.esp32.yaml @@ -0,0 +1,12 @@ +cover: + - platform: time_based + name: Time Based Cover + id: time_based_cover + stop_action: + - logger.log: stop_action + open_action: + - logger.log: open_action + open_duration: 5min + close_action: + - logger.log: close_action + close_duration: 4.5min diff --git a/tests/components/time_based/test.esp8266.yaml b/tests/components/time_based/test.esp8266.yaml new file mode 100644 index 0000000000..48c86de90f --- /dev/null +++ b/tests/components/time_based/test.esp8266.yaml @@ -0,0 +1,12 @@ +cover: + - platform: time_based + name: Time Based Cover + id: time_based_cover + stop_action: + - logger.log: stop_action + open_action: + - logger.log: open_action + open_duration: 5min + close_action: + - logger.log: close_action + close_duration: 4.5min diff --git a/tests/components/time_based/test.rp2040.yaml b/tests/components/time_based/test.rp2040.yaml new file mode 100644 index 0000000000..48c86de90f --- /dev/null +++ b/tests/components/time_based/test.rp2040.yaml @@ -0,0 +1,12 @@ +cover: + - platform: time_based + name: Time Based Cover + id: time_based_cover + stop_action: + - logger.log: stop_action + open_action: + - logger.log: open_action + open_duration: 5min + close_action: + - logger.log: close_action + close_duration: 4.5min diff --git a/tests/components/tlc59208f/test.esp32-c3-idf.yaml b/tests/components/tlc59208f/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..923ea4b4a4 --- /dev/null +++ b/tests/components/tlc59208f/test.esp32-c3-idf.yaml @@ -0,0 +1,50 @@ +i2c: + - id: i2c_tlc59208f + scl: 5 + sda: 4 + +tlc59208f: + - address: 0x20 + id: tlc59208f_1 + - address: 0x22 + id: tlc59208f_2 + - address: 0x24 + id: tlc59208f_3 + +output: + - platform: tlc59208f + id: tlc_0 + channel: 0 + tlc59208f_id: tlc59208f_1 + - platform: tlc59208f + id: tlc_1 + channel: 1 + tlc59208f_id: tlc59208f_1 + - platform: tlc59208f + id: tlc_2 + channel: 2 + tlc59208f_id: tlc59208f_1 + - platform: tlc59208f + id: tlc_3 + channel: 0 + tlc59208f_id: tlc59208f_2 + - platform: tlc59208f + id: tlc_4 + channel: 1 + tlc59208f_id: tlc59208f_2 + - platform: tlc59208f + id: tlc_5 + channel: 2 + tlc59208f_id: tlc59208f_2 + - platform: tlc59208f + id: tlc_6 + channel: 0 + tlc59208f_id: tlc59208f_3 + - platform: tlc59208f + id: tlc_7 + channel: 1 + tlc59208f_id: tlc59208f_3 + - platform: tlc59208f + id: tlc_8 + channel: 2 + tlc59208f_id: tlc59208f_3 diff --git a/tests/components/tlc59208f/test.esp32-c3.yaml b/tests/components/tlc59208f/test.esp32-c3.yaml new file mode 100644 index 0000000000..923ea4b4a4 --- /dev/null +++ b/tests/components/tlc59208f/test.esp32-c3.yaml @@ -0,0 +1,50 @@ +i2c: + - id: i2c_tlc59208f + scl: 5 + sda: 4 + +tlc59208f: + - address: 0x20 + id: tlc59208f_1 + - address: 0x22 + id: tlc59208f_2 + - address: 0x24 + id: tlc59208f_3 + +output: + - platform: tlc59208f + id: tlc_0 + channel: 0 + tlc59208f_id: tlc59208f_1 + - platform: tlc59208f + id: tlc_1 + channel: 1 + tlc59208f_id: tlc59208f_1 + - platform: tlc59208f + id: tlc_2 + channel: 2 + tlc59208f_id: tlc59208f_1 + - platform: tlc59208f + id: tlc_3 + channel: 0 + tlc59208f_id: tlc59208f_2 + - platform: tlc59208f + id: tlc_4 + channel: 1 + tlc59208f_id: tlc59208f_2 + - platform: tlc59208f + id: tlc_5 + channel: 2 + tlc59208f_id: tlc59208f_2 + - platform: tlc59208f + id: tlc_6 + channel: 0 + tlc59208f_id: tlc59208f_3 + - platform: tlc59208f + id: tlc_7 + channel: 1 + tlc59208f_id: tlc59208f_3 + - platform: tlc59208f + id: tlc_8 + channel: 2 + tlc59208f_id: tlc59208f_3 diff --git a/tests/components/tlc59208f/test.esp32-idf.yaml b/tests/components/tlc59208f/test.esp32-idf.yaml new file mode 100644 index 0000000000..2639de3b3d --- /dev/null +++ b/tests/components/tlc59208f/test.esp32-idf.yaml @@ -0,0 +1,50 @@ +i2c: + - id: i2c_tlc59208f + scl: 16 + sda: 17 + +tlc59208f: + - address: 0x20 + id: tlc59208f_1 + - address: 0x22 + id: tlc59208f_2 + - address: 0x24 + id: tlc59208f_3 + +output: + - platform: tlc59208f + id: tlc_0 + channel: 0 + tlc59208f_id: tlc59208f_1 + - platform: tlc59208f + id: tlc_1 + channel: 1 + tlc59208f_id: tlc59208f_1 + - platform: tlc59208f + id: tlc_2 + channel: 2 + tlc59208f_id: tlc59208f_1 + - platform: tlc59208f + id: tlc_3 + channel: 0 + tlc59208f_id: tlc59208f_2 + - platform: tlc59208f + id: tlc_4 + channel: 1 + tlc59208f_id: tlc59208f_2 + - platform: tlc59208f + id: tlc_5 + channel: 2 + tlc59208f_id: tlc59208f_2 + - platform: tlc59208f + id: tlc_6 + channel: 0 + tlc59208f_id: tlc59208f_3 + - platform: tlc59208f + id: tlc_7 + channel: 1 + tlc59208f_id: tlc59208f_3 + - platform: tlc59208f + id: tlc_8 + channel: 2 + tlc59208f_id: tlc59208f_3 diff --git a/tests/components/tlc59208f/test.esp32.yaml b/tests/components/tlc59208f/test.esp32.yaml new file mode 100644 index 0000000000..2639de3b3d --- /dev/null +++ b/tests/components/tlc59208f/test.esp32.yaml @@ -0,0 +1,50 @@ +i2c: + - id: i2c_tlc59208f + scl: 16 + sda: 17 + +tlc59208f: + - address: 0x20 + id: tlc59208f_1 + - address: 0x22 + id: tlc59208f_2 + - address: 0x24 + id: tlc59208f_3 + +output: + - platform: tlc59208f + id: tlc_0 + channel: 0 + tlc59208f_id: tlc59208f_1 + - platform: tlc59208f + id: tlc_1 + channel: 1 + tlc59208f_id: tlc59208f_1 + - platform: tlc59208f + id: tlc_2 + channel: 2 + tlc59208f_id: tlc59208f_1 + - platform: tlc59208f + id: tlc_3 + channel: 0 + tlc59208f_id: tlc59208f_2 + - platform: tlc59208f + id: tlc_4 + channel: 1 + tlc59208f_id: tlc59208f_2 + - platform: tlc59208f + id: tlc_5 + channel: 2 + tlc59208f_id: tlc59208f_2 + - platform: tlc59208f + id: tlc_6 + channel: 0 + tlc59208f_id: tlc59208f_3 + - platform: tlc59208f + id: tlc_7 + channel: 1 + tlc59208f_id: tlc59208f_3 + - platform: tlc59208f + id: tlc_8 + channel: 2 + tlc59208f_id: tlc59208f_3 diff --git a/tests/components/tlc59208f/test.esp8266.yaml b/tests/components/tlc59208f/test.esp8266.yaml new file mode 100644 index 0000000000..923ea4b4a4 --- /dev/null +++ b/tests/components/tlc59208f/test.esp8266.yaml @@ -0,0 +1,50 @@ +i2c: + - id: i2c_tlc59208f + scl: 5 + sda: 4 + +tlc59208f: + - address: 0x20 + id: tlc59208f_1 + - address: 0x22 + id: tlc59208f_2 + - address: 0x24 + id: tlc59208f_3 + +output: + - platform: tlc59208f + id: tlc_0 + channel: 0 + tlc59208f_id: tlc59208f_1 + - platform: tlc59208f + id: tlc_1 + channel: 1 + tlc59208f_id: tlc59208f_1 + - platform: tlc59208f + id: tlc_2 + channel: 2 + tlc59208f_id: tlc59208f_1 + - platform: tlc59208f + id: tlc_3 + channel: 0 + tlc59208f_id: tlc59208f_2 + - platform: tlc59208f + id: tlc_4 + channel: 1 + tlc59208f_id: tlc59208f_2 + - platform: tlc59208f + id: tlc_5 + channel: 2 + tlc59208f_id: tlc59208f_2 + - platform: tlc59208f + id: tlc_6 + channel: 0 + tlc59208f_id: tlc59208f_3 + - platform: tlc59208f + id: tlc_7 + channel: 1 + tlc59208f_id: tlc59208f_3 + - platform: tlc59208f + id: tlc_8 + channel: 2 + tlc59208f_id: tlc59208f_3 diff --git a/tests/components/tlc59208f/test.rp2040.yaml b/tests/components/tlc59208f/test.rp2040.yaml new file mode 100644 index 0000000000..923ea4b4a4 --- /dev/null +++ b/tests/components/tlc59208f/test.rp2040.yaml @@ -0,0 +1,50 @@ +i2c: + - id: i2c_tlc59208f + scl: 5 + sda: 4 + +tlc59208f: + - address: 0x20 + id: tlc59208f_1 + - address: 0x22 + id: tlc59208f_2 + - address: 0x24 + id: tlc59208f_3 + +output: + - platform: tlc59208f + id: tlc_0 + channel: 0 + tlc59208f_id: tlc59208f_1 + - platform: tlc59208f + id: tlc_1 + channel: 1 + tlc59208f_id: tlc59208f_1 + - platform: tlc59208f + id: tlc_2 + channel: 2 + tlc59208f_id: tlc59208f_1 + - platform: tlc59208f + id: tlc_3 + channel: 0 + tlc59208f_id: tlc59208f_2 + - platform: tlc59208f + id: tlc_4 + channel: 1 + tlc59208f_id: tlc59208f_2 + - platform: tlc59208f + id: tlc_5 + channel: 2 + tlc59208f_id: tlc59208f_2 + - platform: tlc59208f + id: tlc_6 + channel: 0 + tlc59208f_id: tlc59208f_3 + - platform: tlc59208f + id: tlc_7 + channel: 1 + tlc59208f_id: tlc59208f_3 + - platform: tlc59208f + id: tlc_8 + channel: 2 + tlc59208f_id: tlc59208f_3 diff --git a/tests/components/tm1621/test.esp32-c3-idf.yaml b/tests/components/tm1621/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..cddd64f31f --- /dev/null +++ b/tests/components/tm1621/test.esp32-c3-idf.yaml @@ -0,0 +1,12 @@ +display: + - platform: tm1621 + id: tm1621_display + cs_pin: 7 + data_pin: 4 + read_pin: 5 + write_pin: 6 + lambda: |- + it.printf(0, "%.1f", 20.0); + it.display_celsius(true); + it.printf(1, "%.1f", 20.0); + it.display_humidity(true); diff --git a/tests/components/tm1621/test.esp32-c3.yaml b/tests/components/tm1621/test.esp32-c3.yaml new file mode 100644 index 0000000000..cddd64f31f --- /dev/null +++ b/tests/components/tm1621/test.esp32-c3.yaml @@ -0,0 +1,12 @@ +display: + - platform: tm1621 + id: tm1621_display + cs_pin: 7 + data_pin: 4 + read_pin: 5 + write_pin: 6 + lambda: |- + it.printf(0, "%.1f", 20.0); + it.display_celsius(true); + it.printf(1, "%.1f", 20.0); + it.display_humidity(true); diff --git a/tests/components/tm1621/test.esp32-idf.yaml b/tests/components/tm1621/test.esp32-idf.yaml new file mode 100644 index 0000000000..8eab46f000 --- /dev/null +++ b/tests/components/tm1621/test.esp32-idf.yaml @@ -0,0 +1,12 @@ +display: + - platform: tm1621 + id: tm1621_display + cs_pin: 15 + data_pin: 14 + read_pin: 12 + write_pin: 13 + lambda: |- + it.printf(0, "%.1f", 20.0); + it.display_celsius(true); + it.printf(1, "%.1f", 20.0); + it.display_humidity(true); diff --git a/tests/components/tm1621/test.esp32.yaml b/tests/components/tm1621/test.esp32.yaml new file mode 100644 index 0000000000..8eab46f000 --- /dev/null +++ b/tests/components/tm1621/test.esp32.yaml @@ -0,0 +1,12 @@ +display: + - platform: tm1621 + id: tm1621_display + cs_pin: 15 + data_pin: 14 + read_pin: 12 + write_pin: 13 + lambda: |- + it.printf(0, "%.1f", 20.0); + it.display_celsius(true); + it.printf(1, "%.1f", 20.0); + it.display_humidity(true); diff --git a/tests/components/tm1621/test.esp8266.yaml b/tests/components/tm1621/test.esp8266.yaml new file mode 100644 index 0000000000..8eab46f000 --- /dev/null +++ b/tests/components/tm1621/test.esp8266.yaml @@ -0,0 +1,12 @@ +display: + - platform: tm1621 + id: tm1621_display + cs_pin: 15 + data_pin: 14 + read_pin: 12 + write_pin: 13 + lambda: |- + it.printf(0, "%.1f", 20.0); + it.display_celsius(true); + it.printf(1, "%.1f", 20.0); + it.display_humidity(true); diff --git a/tests/components/tm1621/test.rp2040.yaml b/tests/components/tm1621/test.rp2040.yaml new file mode 100644 index 0000000000..cddd64f31f --- /dev/null +++ b/tests/components/tm1621/test.rp2040.yaml @@ -0,0 +1,12 @@ +display: + - platform: tm1621 + id: tm1621_display + cs_pin: 7 + data_pin: 4 + read_pin: 5 + write_pin: 6 + lambda: |- + it.printf(0, "%.1f", 20.0); + it.display_celsius(true); + it.printf(1, "%.1f", 20.0); + it.display_humidity(true); diff --git a/tests/components/tm1637/test.esp32-c3-idf.yaml b/tests/components/tm1637/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..fa4c95b443 --- /dev/null +++ b/tests/components/tm1637/test.esp32-c3-idf.yaml @@ -0,0 +1,7 @@ +display: + - platform: tm1637 + clk_pin: 5 + dio_pin: 4 + intensity: 3 + lambda: |- + it.print("1234"); diff --git a/tests/components/tm1637/test.esp32-c3.yaml b/tests/components/tm1637/test.esp32-c3.yaml new file mode 100644 index 0000000000..fa4c95b443 --- /dev/null +++ b/tests/components/tm1637/test.esp32-c3.yaml @@ -0,0 +1,7 @@ +display: + - platform: tm1637 + clk_pin: 5 + dio_pin: 4 + intensity: 3 + lambda: |- + it.print("1234"); diff --git a/tests/components/tm1637/test.esp32-idf.yaml b/tests/components/tm1637/test.esp32-idf.yaml new file mode 100644 index 0000000000..bf5f331cca --- /dev/null +++ b/tests/components/tm1637/test.esp32-idf.yaml @@ -0,0 +1,7 @@ +display: + - platform: tm1637 + clk_pin: 15 + dio_pin: 14 + intensity: 3 + lambda: |- + it.print("1234"); diff --git a/tests/components/tm1637/test.esp32.yaml b/tests/components/tm1637/test.esp32.yaml new file mode 100644 index 0000000000..bf5f331cca --- /dev/null +++ b/tests/components/tm1637/test.esp32.yaml @@ -0,0 +1,7 @@ +display: + - platform: tm1637 + clk_pin: 15 + dio_pin: 14 + intensity: 3 + lambda: |- + it.print("1234"); diff --git a/tests/components/tm1637/test.esp8266.yaml b/tests/components/tm1637/test.esp8266.yaml new file mode 100644 index 0000000000..fa4c95b443 --- /dev/null +++ b/tests/components/tm1637/test.esp8266.yaml @@ -0,0 +1,7 @@ +display: + - platform: tm1637 + clk_pin: 5 + dio_pin: 4 + intensity: 3 + lambda: |- + it.print("1234"); diff --git a/tests/components/tm1637/test.rp2040.yaml b/tests/components/tm1637/test.rp2040.yaml new file mode 100644 index 0000000000..fa4c95b443 --- /dev/null +++ b/tests/components/tm1637/test.rp2040.yaml @@ -0,0 +1,7 @@ +display: + - platform: tm1637 + clk_pin: 5 + dio_pin: 4 + intensity: 3 + lambda: |- + it.print("1234"); diff --git a/tests/components/tm1638/test.esp32-c3-idf.yaml b/tests/components/tm1638/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..b0c5cef528 --- /dev/null +++ b/tests/components/tm1638/test.esp32-c3-idf.yaml @@ -0,0 +1,118 @@ +display: + - platform: tm1638 + id: tm1638_display + stb_pin: 2 + clk_pin: 5 + dio_pin: 4 + update_interval: 5s + intensity: 5 + lambda: |- + it.print("81818181"); + +binary_sensor: + - platform: tm1638 + id: Button0 + key: 0 + filters: + - delayed_on: 10ms + on_press: + then: + - switch.turn_on: Led0 + on_release: + then: + - switch.turn_off: Led0 + - platform: tm1638 + id: Button1 + key: 1 + on_press: + then: + - switch.turn_on: Led1 + on_release: + then: + - switch.turn_off: Led1 + - platform: tm1638 + id: Button2 + key: 2 + on_press: + then: + - switch.turn_on: Led2 + on_release: + then: + - switch.turn_off: Led2 + - platform: tm1638 + id: Button3 + key: 3 + on_press: + then: + - switch.turn_on: Led3 + on_release: + then: + - switch.turn_off: Led3 + - platform: tm1638 + id: Button4 + key: 4 + on_press: + then: + - output.turn_on: Led4 + on_release: + then: + - output.turn_off: Led4 + - platform: tm1638 + id: Button5 + key: 5 + on_press: + then: + - output.turn_on: Led5 + on_release: + then: + - output.turn_off: Led5 + - platform: tm1638 + id: Button6 + key: 6 + on_press: + then: + - output.turn_on: Led6 + on_release: + then: + - output.turn_off: Led6 + - platform: tm1638 + id: Button7 + key: 7 + on_press: + then: + - output.turn_on: Led7 + on_release: + then: + - output.turn_off: Led7 + +switch: + - platform: tm1638 + id: Led0 + led: 0 + name: TM1638Led0 + - platform: tm1638 + id: Led1 + led: 1 + name: TM1638Led1 + - platform: tm1638 + id: Led2 + led: 2 + name: TM1638Led2 + - platform: tm1638 + id: Led3 + led: 3 + name: TM1638Led3 + +output: + - platform: tm1638 + id: Led4 + led: 4 + - platform: tm1638 + id: Led5 + led: 5 + - platform: tm1638 + id: Led6 + led: 6 + - platform: tm1638 + id: Led7 + led: 7 diff --git a/tests/components/tm1638/test.esp32-c3.yaml b/tests/components/tm1638/test.esp32-c3.yaml new file mode 100644 index 0000000000..b0c5cef528 --- /dev/null +++ b/tests/components/tm1638/test.esp32-c3.yaml @@ -0,0 +1,118 @@ +display: + - platform: tm1638 + id: tm1638_display + stb_pin: 2 + clk_pin: 5 + dio_pin: 4 + update_interval: 5s + intensity: 5 + lambda: |- + it.print("81818181"); + +binary_sensor: + - platform: tm1638 + id: Button0 + key: 0 + filters: + - delayed_on: 10ms + on_press: + then: + - switch.turn_on: Led0 + on_release: + then: + - switch.turn_off: Led0 + - platform: tm1638 + id: Button1 + key: 1 + on_press: + then: + - switch.turn_on: Led1 + on_release: + then: + - switch.turn_off: Led1 + - platform: tm1638 + id: Button2 + key: 2 + on_press: + then: + - switch.turn_on: Led2 + on_release: + then: + - switch.turn_off: Led2 + - platform: tm1638 + id: Button3 + key: 3 + on_press: + then: + - switch.turn_on: Led3 + on_release: + then: + - switch.turn_off: Led3 + - platform: tm1638 + id: Button4 + key: 4 + on_press: + then: + - output.turn_on: Led4 + on_release: + then: + - output.turn_off: Led4 + - platform: tm1638 + id: Button5 + key: 5 + on_press: + then: + - output.turn_on: Led5 + on_release: + then: + - output.turn_off: Led5 + - platform: tm1638 + id: Button6 + key: 6 + on_press: + then: + - output.turn_on: Led6 + on_release: + then: + - output.turn_off: Led6 + - platform: tm1638 + id: Button7 + key: 7 + on_press: + then: + - output.turn_on: Led7 + on_release: + then: + - output.turn_off: Led7 + +switch: + - platform: tm1638 + id: Led0 + led: 0 + name: TM1638Led0 + - platform: tm1638 + id: Led1 + led: 1 + name: TM1638Led1 + - platform: tm1638 + id: Led2 + led: 2 + name: TM1638Led2 + - platform: tm1638 + id: Led3 + led: 3 + name: TM1638Led3 + +output: + - platform: tm1638 + id: Led4 + led: 4 + - platform: tm1638 + id: Led5 + led: 5 + - platform: tm1638 + id: Led6 + led: 6 + - platform: tm1638 + id: Led7 + led: 7 diff --git a/tests/components/tm1638/test.esp32-idf.yaml b/tests/components/tm1638/test.esp32-idf.yaml new file mode 100644 index 0000000000..b0c5cef528 --- /dev/null +++ b/tests/components/tm1638/test.esp32-idf.yaml @@ -0,0 +1,118 @@ +display: + - platform: tm1638 + id: tm1638_display + stb_pin: 2 + clk_pin: 5 + dio_pin: 4 + update_interval: 5s + intensity: 5 + lambda: |- + it.print("81818181"); + +binary_sensor: + - platform: tm1638 + id: Button0 + key: 0 + filters: + - delayed_on: 10ms + on_press: + then: + - switch.turn_on: Led0 + on_release: + then: + - switch.turn_off: Led0 + - platform: tm1638 + id: Button1 + key: 1 + on_press: + then: + - switch.turn_on: Led1 + on_release: + then: + - switch.turn_off: Led1 + - platform: tm1638 + id: Button2 + key: 2 + on_press: + then: + - switch.turn_on: Led2 + on_release: + then: + - switch.turn_off: Led2 + - platform: tm1638 + id: Button3 + key: 3 + on_press: + then: + - switch.turn_on: Led3 + on_release: + then: + - switch.turn_off: Led3 + - platform: tm1638 + id: Button4 + key: 4 + on_press: + then: + - output.turn_on: Led4 + on_release: + then: + - output.turn_off: Led4 + - platform: tm1638 + id: Button5 + key: 5 + on_press: + then: + - output.turn_on: Led5 + on_release: + then: + - output.turn_off: Led5 + - platform: tm1638 + id: Button6 + key: 6 + on_press: + then: + - output.turn_on: Led6 + on_release: + then: + - output.turn_off: Led6 + - platform: tm1638 + id: Button7 + key: 7 + on_press: + then: + - output.turn_on: Led7 + on_release: + then: + - output.turn_off: Led7 + +switch: + - platform: tm1638 + id: Led0 + led: 0 + name: TM1638Led0 + - platform: tm1638 + id: Led1 + led: 1 + name: TM1638Led1 + - platform: tm1638 + id: Led2 + led: 2 + name: TM1638Led2 + - platform: tm1638 + id: Led3 + led: 3 + name: TM1638Led3 + +output: + - platform: tm1638 + id: Led4 + led: 4 + - platform: tm1638 + id: Led5 + led: 5 + - platform: tm1638 + id: Led6 + led: 6 + - platform: tm1638 + id: Led7 + led: 7 diff --git a/tests/components/tm1638/test.esp32.yaml b/tests/components/tm1638/test.esp32.yaml new file mode 100644 index 0000000000..b0c5cef528 --- /dev/null +++ b/tests/components/tm1638/test.esp32.yaml @@ -0,0 +1,118 @@ +display: + - platform: tm1638 + id: tm1638_display + stb_pin: 2 + clk_pin: 5 + dio_pin: 4 + update_interval: 5s + intensity: 5 + lambda: |- + it.print("81818181"); + +binary_sensor: + - platform: tm1638 + id: Button0 + key: 0 + filters: + - delayed_on: 10ms + on_press: + then: + - switch.turn_on: Led0 + on_release: + then: + - switch.turn_off: Led0 + - platform: tm1638 + id: Button1 + key: 1 + on_press: + then: + - switch.turn_on: Led1 + on_release: + then: + - switch.turn_off: Led1 + - platform: tm1638 + id: Button2 + key: 2 + on_press: + then: + - switch.turn_on: Led2 + on_release: + then: + - switch.turn_off: Led2 + - platform: tm1638 + id: Button3 + key: 3 + on_press: + then: + - switch.turn_on: Led3 + on_release: + then: + - switch.turn_off: Led3 + - platform: tm1638 + id: Button4 + key: 4 + on_press: + then: + - output.turn_on: Led4 + on_release: + then: + - output.turn_off: Led4 + - platform: tm1638 + id: Button5 + key: 5 + on_press: + then: + - output.turn_on: Led5 + on_release: + then: + - output.turn_off: Led5 + - platform: tm1638 + id: Button6 + key: 6 + on_press: + then: + - output.turn_on: Led6 + on_release: + then: + - output.turn_off: Led6 + - platform: tm1638 + id: Button7 + key: 7 + on_press: + then: + - output.turn_on: Led7 + on_release: + then: + - output.turn_off: Led7 + +switch: + - platform: tm1638 + id: Led0 + led: 0 + name: TM1638Led0 + - platform: tm1638 + id: Led1 + led: 1 + name: TM1638Led1 + - platform: tm1638 + id: Led2 + led: 2 + name: TM1638Led2 + - platform: tm1638 + id: Led3 + led: 3 + name: TM1638Led3 + +output: + - platform: tm1638 + id: Led4 + led: 4 + - platform: tm1638 + id: Led5 + led: 5 + - platform: tm1638 + id: Led6 + led: 6 + - platform: tm1638 + id: Led7 + led: 7 diff --git a/tests/components/tm1638/test.esp8266.yaml b/tests/components/tm1638/test.esp8266.yaml new file mode 100644 index 0000000000..b0c5cef528 --- /dev/null +++ b/tests/components/tm1638/test.esp8266.yaml @@ -0,0 +1,118 @@ +display: + - platform: tm1638 + id: tm1638_display + stb_pin: 2 + clk_pin: 5 + dio_pin: 4 + update_interval: 5s + intensity: 5 + lambda: |- + it.print("81818181"); + +binary_sensor: + - platform: tm1638 + id: Button0 + key: 0 + filters: + - delayed_on: 10ms + on_press: + then: + - switch.turn_on: Led0 + on_release: + then: + - switch.turn_off: Led0 + - platform: tm1638 + id: Button1 + key: 1 + on_press: + then: + - switch.turn_on: Led1 + on_release: + then: + - switch.turn_off: Led1 + - platform: tm1638 + id: Button2 + key: 2 + on_press: + then: + - switch.turn_on: Led2 + on_release: + then: + - switch.turn_off: Led2 + - platform: tm1638 + id: Button3 + key: 3 + on_press: + then: + - switch.turn_on: Led3 + on_release: + then: + - switch.turn_off: Led3 + - platform: tm1638 + id: Button4 + key: 4 + on_press: + then: + - output.turn_on: Led4 + on_release: + then: + - output.turn_off: Led4 + - platform: tm1638 + id: Button5 + key: 5 + on_press: + then: + - output.turn_on: Led5 + on_release: + then: + - output.turn_off: Led5 + - platform: tm1638 + id: Button6 + key: 6 + on_press: + then: + - output.turn_on: Led6 + on_release: + then: + - output.turn_off: Led6 + - platform: tm1638 + id: Button7 + key: 7 + on_press: + then: + - output.turn_on: Led7 + on_release: + then: + - output.turn_off: Led7 + +switch: + - platform: tm1638 + id: Led0 + led: 0 + name: TM1638Led0 + - platform: tm1638 + id: Led1 + led: 1 + name: TM1638Led1 + - platform: tm1638 + id: Led2 + led: 2 + name: TM1638Led2 + - platform: tm1638 + id: Led3 + led: 3 + name: TM1638Led3 + +output: + - platform: tm1638 + id: Led4 + led: 4 + - platform: tm1638 + id: Led5 + led: 5 + - platform: tm1638 + id: Led6 + led: 6 + - platform: tm1638 + id: Led7 + led: 7 diff --git a/tests/components/tm1638/test.rp2040.yaml b/tests/components/tm1638/test.rp2040.yaml new file mode 100644 index 0000000000..b0c5cef528 --- /dev/null +++ b/tests/components/tm1638/test.rp2040.yaml @@ -0,0 +1,118 @@ +display: + - platform: tm1638 + id: tm1638_display + stb_pin: 2 + clk_pin: 5 + dio_pin: 4 + update_interval: 5s + intensity: 5 + lambda: |- + it.print("81818181"); + +binary_sensor: + - platform: tm1638 + id: Button0 + key: 0 + filters: + - delayed_on: 10ms + on_press: + then: + - switch.turn_on: Led0 + on_release: + then: + - switch.turn_off: Led0 + - platform: tm1638 + id: Button1 + key: 1 + on_press: + then: + - switch.turn_on: Led1 + on_release: + then: + - switch.turn_off: Led1 + - platform: tm1638 + id: Button2 + key: 2 + on_press: + then: + - switch.turn_on: Led2 + on_release: + then: + - switch.turn_off: Led2 + - platform: tm1638 + id: Button3 + key: 3 + on_press: + then: + - switch.turn_on: Led3 + on_release: + then: + - switch.turn_off: Led3 + - platform: tm1638 + id: Button4 + key: 4 + on_press: + then: + - output.turn_on: Led4 + on_release: + then: + - output.turn_off: Led4 + - platform: tm1638 + id: Button5 + key: 5 + on_press: + then: + - output.turn_on: Led5 + on_release: + then: + - output.turn_off: Led5 + - platform: tm1638 + id: Button6 + key: 6 + on_press: + then: + - output.turn_on: Led6 + on_release: + then: + - output.turn_off: Led6 + - platform: tm1638 + id: Button7 + key: 7 + on_press: + then: + - output.turn_on: Led7 + on_release: + then: + - output.turn_off: Led7 + +switch: + - platform: tm1638 + id: Led0 + led: 0 + name: TM1638Led0 + - platform: tm1638 + id: Led1 + led: 1 + name: TM1638Led1 + - platform: tm1638 + id: Led2 + led: 2 + name: TM1638Led2 + - platform: tm1638 + id: Led3 + led: 3 + name: TM1638Led3 + +output: + - platform: tm1638 + id: Led4 + led: 4 + - platform: tm1638 + id: Led5 + led: 5 + - platform: tm1638 + id: Led6 + led: 6 + - platform: tm1638 + id: Led7 + led: 7 diff --git a/tests/components/tm1651/test.esp32-c3.yaml b/tests/components/tm1651/test.esp32-c3.yaml new file mode 100644 index 0000000000..667648f4d6 --- /dev/null +++ b/tests/components/tm1651/test.esp32-c3.yaml @@ -0,0 +1,21 @@ +tm1651: + id: tm1651_battery + clk_pin: 5 + dio_pin: 4 + +esphome: + on_boot: + then: + - tm1651.set_level_percent: + id: tm1651_battery + level_percent: 50 + - tm1651.set_level: + id: tm1651_battery + level: 5 + - tm1651.set_brightness: + id: tm1651_battery + brightness: 2 + - tm1651.turn_on: + id: tm1651_battery + - tm1651.turn_off: + id: tm1651_battery diff --git a/tests/components/tm1651/test.esp32.yaml b/tests/components/tm1651/test.esp32.yaml new file mode 100644 index 0000000000..667648f4d6 --- /dev/null +++ b/tests/components/tm1651/test.esp32.yaml @@ -0,0 +1,21 @@ +tm1651: + id: tm1651_battery + clk_pin: 5 + dio_pin: 4 + +esphome: + on_boot: + then: + - tm1651.set_level_percent: + id: tm1651_battery + level_percent: 50 + - tm1651.set_level: + id: tm1651_battery + level: 5 + - tm1651.set_brightness: + id: tm1651_battery + brightness: 2 + - tm1651.turn_on: + id: tm1651_battery + - tm1651.turn_off: + id: tm1651_battery diff --git a/tests/components/tm1651/test.esp8266.yaml b/tests/components/tm1651/test.esp8266.yaml new file mode 100644 index 0000000000..667648f4d6 --- /dev/null +++ b/tests/components/tm1651/test.esp8266.yaml @@ -0,0 +1,21 @@ +tm1651: + id: tm1651_battery + clk_pin: 5 + dio_pin: 4 + +esphome: + on_boot: + then: + - tm1651.set_level_percent: + id: tm1651_battery + level_percent: 50 + - tm1651.set_level: + id: tm1651_battery + level: 5 + - tm1651.set_brightness: + id: tm1651_battery + brightness: 2 + - tm1651.turn_on: + id: tm1651_battery + - tm1651.turn_off: + id: tm1651_battery diff --git a/tests/components/tm1651/test.rp2040.yaml b/tests/components/tm1651/test.rp2040.yaml new file mode 100644 index 0000000000..667648f4d6 --- /dev/null +++ b/tests/components/tm1651/test.rp2040.yaml @@ -0,0 +1,21 @@ +tm1651: + id: tm1651_battery + clk_pin: 5 + dio_pin: 4 + +esphome: + on_boot: + then: + - tm1651.set_level_percent: + id: tm1651_battery + level_percent: 50 + - tm1651.set_level: + id: tm1651_battery + level: 5 + - tm1651.set_brightness: + id: tm1651_battery + brightness: 2 + - tm1651.turn_on: + id: tm1651_battery + - tm1651.turn_off: + id: tm1651_battery diff --git a/tests/components/tmp102/test.esp32-c3-idf.yaml b/tests/components/tmp102/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..c1d35fca3f --- /dev/null +++ b/tests/components/tmp102/test.esp32-c3-idf.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_tmp102 + scl: 5 + sda: 4 + +sensor: + - platform: tmp102 + name: TMP102 Temperature diff --git a/tests/components/tmp102/test.esp32-c3.yaml b/tests/components/tmp102/test.esp32-c3.yaml new file mode 100644 index 0000000000..c1d35fca3f --- /dev/null +++ b/tests/components/tmp102/test.esp32-c3.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_tmp102 + scl: 5 + sda: 4 + +sensor: + - platform: tmp102 + name: TMP102 Temperature diff --git a/tests/components/tmp102/test.esp32-idf.yaml b/tests/components/tmp102/test.esp32-idf.yaml new file mode 100644 index 0000000000..840bf7edb3 --- /dev/null +++ b/tests/components/tmp102/test.esp32-idf.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_tmp102 + scl: 16 + sda: 17 + +sensor: + - platform: tmp102 + name: TMP102 Temperature diff --git a/tests/components/tmp102/test.esp32.yaml b/tests/components/tmp102/test.esp32.yaml new file mode 100644 index 0000000000..840bf7edb3 --- /dev/null +++ b/tests/components/tmp102/test.esp32.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_tmp102 + scl: 16 + sda: 17 + +sensor: + - platform: tmp102 + name: TMP102 Temperature diff --git a/tests/components/tmp102/test.esp8266.yaml b/tests/components/tmp102/test.esp8266.yaml new file mode 100644 index 0000000000..c1d35fca3f --- /dev/null +++ b/tests/components/tmp102/test.esp8266.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_tmp102 + scl: 5 + sda: 4 + +sensor: + - platform: tmp102 + name: TMP102 Temperature diff --git a/tests/components/tmp102/test.rp2040.yaml b/tests/components/tmp102/test.rp2040.yaml new file mode 100644 index 0000000000..c1d35fca3f --- /dev/null +++ b/tests/components/tmp102/test.rp2040.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_tmp102 + scl: 5 + sda: 4 + +sensor: + - platform: tmp102 + name: TMP102 Temperature diff --git a/tests/components/tmp1075/test.esp32-c3-idf.yaml b/tests/components/tmp1075/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..99433aa655 --- /dev/null +++ b/tests/components/tmp1075/test.esp32-c3-idf.yaml @@ -0,0 +1,16 @@ +i2c: + - id: i2c_tmp1075 + scl: 5 + sda: 4 + +sensor: + - platform: tmp1075 + name: Temperature TMP1075 + conversion_rate: 27.5ms + alert: + limit_low: 50 + limit_high: 75 + fault_count: 1 + polarity: active_high + function: comparator + update_interval: 10s diff --git a/tests/components/tmp1075/test.esp32-c3.yaml b/tests/components/tmp1075/test.esp32-c3.yaml new file mode 100644 index 0000000000..99433aa655 --- /dev/null +++ b/tests/components/tmp1075/test.esp32-c3.yaml @@ -0,0 +1,16 @@ +i2c: + - id: i2c_tmp1075 + scl: 5 + sda: 4 + +sensor: + - platform: tmp1075 + name: Temperature TMP1075 + conversion_rate: 27.5ms + alert: + limit_low: 50 + limit_high: 75 + fault_count: 1 + polarity: active_high + function: comparator + update_interval: 10s diff --git a/tests/components/tmp1075/test.esp32-idf.yaml b/tests/components/tmp1075/test.esp32-idf.yaml new file mode 100644 index 0000000000..6c50d0da77 --- /dev/null +++ b/tests/components/tmp1075/test.esp32-idf.yaml @@ -0,0 +1,16 @@ +i2c: + - id: i2c_tmp1075 + scl: 16 + sda: 17 + +sensor: + - platform: tmp1075 + name: Temperature TMP1075 + conversion_rate: 27.5ms + alert: + limit_low: 50 + limit_high: 75 + fault_count: 1 + polarity: active_high + function: comparator + update_interval: 10s diff --git a/tests/components/tmp1075/test.esp32.yaml b/tests/components/tmp1075/test.esp32.yaml new file mode 100644 index 0000000000..6c50d0da77 --- /dev/null +++ b/tests/components/tmp1075/test.esp32.yaml @@ -0,0 +1,16 @@ +i2c: + - id: i2c_tmp1075 + scl: 16 + sda: 17 + +sensor: + - platform: tmp1075 + name: Temperature TMP1075 + conversion_rate: 27.5ms + alert: + limit_low: 50 + limit_high: 75 + fault_count: 1 + polarity: active_high + function: comparator + update_interval: 10s diff --git a/tests/components/tmp1075/test.esp8266.yaml b/tests/components/tmp1075/test.esp8266.yaml new file mode 100644 index 0000000000..99433aa655 --- /dev/null +++ b/tests/components/tmp1075/test.esp8266.yaml @@ -0,0 +1,16 @@ +i2c: + - id: i2c_tmp1075 + scl: 5 + sda: 4 + +sensor: + - platform: tmp1075 + name: Temperature TMP1075 + conversion_rate: 27.5ms + alert: + limit_low: 50 + limit_high: 75 + fault_count: 1 + polarity: active_high + function: comparator + update_interval: 10s diff --git a/tests/components/tmp1075/test.rp2040.yaml b/tests/components/tmp1075/test.rp2040.yaml new file mode 100644 index 0000000000..99433aa655 --- /dev/null +++ b/tests/components/tmp1075/test.rp2040.yaml @@ -0,0 +1,16 @@ +i2c: + - id: i2c_tmp1075 + scl: 5 + sda: 4 + +sensor: + - platform: tmp1075 + name: Temperature TMP1075 + conversion_rate: 27.5ms + alert: + limit_low: 50 + limit_high: 75 + fault_count: 1 + polarity: active_high + function: comparator + update_interval: 10s diff --git a/tests/components/tmp117/test.esp32-c3-idf.yaml b/tests/components/tmp117/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..61fc2cc03d --- /dev/null +++ b/tests/components/tmp117/test.esp32-c3-idf.yaml @@ -0,0 +1,9 @@ +i2c: + - id: i2c_tmp117 + scl: 5 + sda: 4 + +sensor: + - platform: tmp117 + name: TMP117 Temperature + update_interval: 5s diff --git a/tests/components/tmp117/test.esp32-c3.yaml b/tests/components/tmp117/test.esp32-c3.yaml new file mode 100644 index 0000000000..61fc2cc03d --- /dev/null +++ b/tests/components/tmp117/test.esp32-c3.yaml @@ -0,0 +1,9 @@ +i2c: + - id: i2c_tmp117 + scl: 5 + sda: 4 + +sensor: + - platform: tmp117 + name: TMP117 Temperature + update_interval: 5s diff --git a/tests/components/tmp117/test.esp32-idf.yaml b/tests/components/tmp117/test.esp32-idf.yaml new file mode 100644 index 0000000000..03e0dd4e8e --- /dev/null +++ b/tests/components/tmp117/test.esp32-idf.yaml @@ -0,0 +1,9 @@ +i2c: + - id: i2c_tmp117 + scl: 16 + sda: 17 + +sensor: + - platform: tmp117 + name: TMP117 Temperature + update_interval: 5s diff --git a/tests/components/tmp117/test.esp32.yaml b/tests/components/tmp117/test.esp32.yaml new file mode 100644 index 0000000000..03e0dd4e8e --- /dev/null +++ b/tests/components/tmp117/test.esp32.yaml @@ -0,0 +1,9 @@ +i2c: + - id: i2c_tmp117 + scl: 16 + sda: 17 + +sensor: + - platform: tmp117 + name: TMP117 Temperature + update_interval: 5s diff --git a/tests/components/tmp117/test.esp8266.yaml b/tests/components/tmp117/test.esp8266.yaml new file mode 100644 index 0000000000..61fc2cc03d --- /dev/null +++ b/tests/components/tmp117/test.esp8266.yaml @@ -0,0 +1,9 @@ +i2c: + - id: i2c_tmp117 + scl: 5 + sda: 4 + +sensor: + - platform: tmp117 + name: TMP117 Temperature + update_interval: 5s diff --git a/tests/components/tmp117/test.rp2040.yaml b/tests/components/tmp117/test.rp2040.yaml new file mode 100644 index 0000000000..61fc2cc03d --- /dev/null +++ b/tests/components/tmp117/test.rp2040.yaml @@ -0,0 +1,9 @@ +i2c: + - id: i2c_tmp117 + scl: 5 + sda: 4 + +sensor: + - platform: tmp117 + name: TMP117 Temperature + update_interval: 5s diff --git a/tests/components/tof10120/test.esp32-c3-idf.yaml b/tests/components/tof10120/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..01cde0df6a --- /dev/null +++ b/tests/components/tof10120/test.esp32-c3-idf.yaml @@ -0,0 +1,9 @@ +i2c: + - id: i2c_tof10120 + scl: 5 + sda: 4 + +sensor: + - platform: tof10120 + name: Distance sensor + update_interval: 5s diff --git a/tests/components/tof10120/test.esp32-c3.yaml b/tests/components/tof10120/test.esp32-c3.yaml new file mode 100644 index 0000000000..01cde0df6a --- /dev/null +++ b/tests/components/tof10120/test.esp32-c3.yaml @@ -0,0 +1,9 @@ +i2c: + - id: i2c_tof10120 + scl: 5 + sda: 4 + +sensor: + - platform: tof10120 + name: Distance sensor + update_interval: 5s diff --git a/tests/components/tof10120/test.esp32-idf.yaml b/tests/components/tof10120/test.esp32-idf.yaml new file mode 100644 index 0000000000..74541ecde8 --- /dev/null +++ b/tests/components/tof10120/test.esp32-idf.yaml @@ -0,0 +1,9 @@ +i2c: + - id: i2c_tof10120 + scl: 16 + sda: 17 + +sensor: + - platform: tof10120 + name: Distance sensor + update_interval: 5s diff --git a/tests/components/tof10120/test.esp32.yaml b/tests/components/tof10120/test.esp32.yaml new file mode 100644 index 0000000000..74541ecde8 --- /dev/null +++ b/tests/components/tof10120/test.esp32.yaml @@ -0,0 +1,9 @@ +i2c: + - id: i2c_tof10120 + scl: 16 + sda: 17 + +sensor: + - platform: tof10120 + name: Distance sensor + update_interval: 5s diff --git a/tests/components/tof10120/test.esp8266.yaml b/tests/components/tof10120/test.esp8266.yaml new file mode 100644 index 0000000000..01cde0df6a --- /dev/null +++ b/tests/components/tof10120/test.esp8266.yaml @@ -0,0 +1,9 @@ +i2c: + - id: i2c_tof10120 + scl: 5 + sda: 4 + +sensor: + - platform: tof10120 + name: Distance sensor + update_interval: 5s diff --git a/tests/components/tof10120/test.rp2040.yaml b/tests/components/tof10120/test.rp2040.yaml new file mode 100644 index 0000000000..01cde0df6a --- /dev/null +++ b/tests/components/tof10120/test.rp2040.yaml @@ -0,0 +1,9 @@ +i2c: + - id: i2c_tof10120 + scl: 5 + sda: 4 + +sensor: + - platform: tof10120 + name: Distance sensor + update_interval: 5s diff --git a/tests/components/toshiba/test.esp32-c3-idf.yaml b/tests/components/toshiba/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..c134c7f5bd --- /dev/null +++ b/tests/components/toshiba/test.esp32-c3-idf.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +climate: + - platform: toshiba + name: Toshiba Climate diff --git a/tests/components/toshiba/test.esp32-c3.yaml b/tests/components/toshiba/test.esp32-c3.yaml new file mode 100644 index 0000000000..c134c7f5bd --- /dev/null +++ b/tests/components/toshiba/test.esp32-c3.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +climate: + - platform: toshiba + name: Toshiba Climate diff --git a/tests/components/toshiba/test.esp32-idf.yaml b/tests/components/toshiba/test.esp32-idf.yaml new file mode 100644 index 0000000000..c134c7f5bd --- /dev/null +++ b/tests/components/toshiba/test.esp32-idf.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +climate: + - platform: toshiba + name: Toshiba Climate diff --git a/tests/components/toshiba/test.esp32.yaml b/tests/components/toshiba/test.esp32.yaml new file mode 100644 index 0000000000..c134c7f5bd --- /dev/null +++ b/tests/components/toshiba/test.esp32.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +climate: + - platform: toshiba + name: Toshiba Climate diff --git a/tests/components/toshiba/test.esp8266.yaml b/tests/components/toshiba/test.esp8266.yaml new file mode 100644 index 0000000000..8730a5d4ab --- /dev/null +++ b/tests/components/toshiba/test.esp8266.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 5 + carrier_duty_percent: 50% + +climate: + - platform: toshiba + name: Toshiba Climate diff --git a/tests/components/total_daily_energy/test.esp32-c3-idf.yaml b/tests/components/total_daily_energy/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..71afa45ed5 --- /dev/null +++ b/tests/components/total_daily_energy/test.esp32-c3-idf.yaml @@ -0,0 +1,32 @@ +wifi: + ssid: MySSID + password: password1 + +time: + - platform: sntp + id: sntp_time + +sensor: + - platform: hlw8012 + sel_pin: 5 + cf_pin: 4 + cf1_pin: 3 + current: + name: HLW8012 Current + voltage: + name: HLW8012 Voltage + power: + name: HLW8012 Power + id: hlw8012_power + energy: + name: HLW8012 Energy + id: hlw8012_energy + update_interval: 15s + current_resistor: 0.001 ohm + voltage_divider: 2351 + change_mode_every: "never" + initial_mode: VOLTAGE + model: hlw8012 + - platform: total_daily_energy + name: HLW8012 Total Daily Energy + power_id: hlw8012_power diff --git a/tests/components/total_daily_energy/test.esp32-c3.yaml b/tests/components/total_daily_energy/test.esp32-c3.yaml new file mode 100644 index 0000000000..71afa45ed5 --- /dev/null +++ b/tests/components/total_daily_energy/test.esp32-c3.yaml @@ -0,0 +1,32 @@ +wifi: + ssid: MySSID + password: password1 + +time: + - platform: sntp + id: sntp_time + +sensor: + - platform: hlw8012 + sel_pin: 5 + cf_pin: 4 + cf1_pin: 3 + current: + name: HLW8012 Current + voltage: + name: HLW8012 Voltage + power: + name: HLW8012 Power + id: hlw8012_power + energy: + name: HLW8012 Energy + id: hlw8012_energy + update_interval: 15s + current_resistor: 0.001 ohm + voltage_divider: 2351 + change_mode_every: "never" + initial_mode: VOLTAGE + model: hlw8012 + - platform: total_daily_energy + name: HLW8012 Total Daily Energy + power_id: hlw8012_power diff --git a/tests/components/total_daily_energy/test.esp32-idf.yaml b/tests/components/total_daily_energy/test.esp32-idf.yaml new file mode 100644 index 0000000000..34d452aae5 --- /dev/null +++ b/tests/components/total_daily_energy/test.esp32-idf.yaml @@ -0,0 +1,32 @@ +wifi: + ssid: MySSID + password: password1 + +time: + - platform: sntp + id: sntp_time + +sensor: + - platform: hlw8012 + sel_pin: 15 + cf_pin: 14 + cf1_pin: 13 + current: + name: HLW8012 Current + voltage: + name: HLW8012 Voltage + power: + name: HLW8012 Power + id: hlw8012_power + energy: + name: HLW8012 Energy + id: hlw8012_energy + update_interval: 15s + current_resistor: 0.001 ohm + voltage_divider: 2351 + change_mode_every: "never" + initial_mode: VOLTAGE + model: hlw8012 + - platform: total_daily_energy + name: HLW8012 Total Daily Energy + power_id: hlw8012_power diff --git a/tests/components/total_daily_energy/test.esp32.yaml b/tests/components/total_daily_energy/test.esp32.yaml new file mode 100644 index 0000000000..34d452aae5 --- /dev/null +++ b/tests/components/total_daily_energy/test.esp32.yaml @@ -0,0 +1,32 @@ +wifi: + ssid: MySSID + password: password1 + +time: + - platform: sntp + id: sntp_time + +sensor: + - platform: hlw8012 + sel_pin: 15 + cf_pin: 14 + cf1_pin: 13 + current: + name: HLW8012 Current + voltage: + name: HLW8012 Voltage + power: + name: HLW8012 Power + id: hlw8012_power + energy: + name: HLW8012 Energy + id: hlw8012_energy + update_interval: 15s + current_resistor: 0.001 ohm + voltage_divider: 2351 + change_mode_every: "never" + initial_mode: VOLTAGE + model: hlw8012 + - platform: total_daily_energy + name: HLW8012 Total Daily Energy + power_id: hlw8012_power diff --git a/tests/components/total_daily_energy/test.esp8266.yaml b/tests/components/total_daily_energy/test.esp8266.yaml new file mode 100644 index 0000000000..34d452aae5 --- /dev/null +++ b/tests/components/total_daily_energy/test.esp8266.yaml @@ -0,0 +1,32 @@ +wifi: + ssid: MySSID + password: password1 + +time: + - platform: sntp + id: sntp_time + +sensor: + - platform: hlw8012 + sel_pin: 15 + cf_pin: 14 + cf1_pin: 13 + current: + name: HLW8012 Current + voltage: + name: HLW8012 Voltage + power: + name: HLW8012 Power + id: hlw8012_power + energy: + name: HLW8012 Energy + id: hlw8012_energy + update_interval: 15s + current_resistor: 0.001 ohm + voltage_divider: 2351 + change_mode_every: "never" + initial_mode: VOLTAGE + model: hlw8012 + - platform: total_daily_energy + name: HLW8012 Total Daily Energy + power_id: hlw8012_power diff --git a/tests/components/total_daily_energy/test.rp2040.yaml b/tests/components/total_daily_energy/test.rp2040.yaml new file mode 100644 index 0000000000..71afa45ed5 --- /dev/null +++ b/tests/components/total_daily_energy/test.rp2040.yaml @@ -0,0 +1,32 @@ +wifi: + ssid: MySSID + password: password1 + +time: + - platform: sntp + id: sntp_time + +sensor: + - platform: hlw8012 + sel_pin: 5 + cf_pin: 4 + cf1_pin: 3 + current: + name: HLW8012 Current + voltage: + name: HLW8012 Voltage + power: + name: HLW8012 Power + id: hlw8012_power + energy: + name: HLW8012 Energy + id: hlw8012_energy + update_interval: 15s + current_resistor: 0.001 ohm + voltage_divider: 2351 + change_mode_every: "never" + initial_mode: VOLTAGE + model: hlw8012 + - platform: total_daily_energy + name: HLW8012 Total Daily Energy + power_id: hlw8012_power diff --git a/tests/components/tsl2561/test.esp32-c3-idf.yaml b/tests/components/tsl2561/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..1ea768c5d9 --- /dev/null +++ b/tests/components/tsl2561/test.esp32-c3-idf.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_tsl2561 + scl: 5 + sda: 4 + +sensor: + - platform: tsl2561 + name: TSL2561 Ambient Light + address: 0x39 + is_cs_package: true + integration_time: 402ms + gain: 16x + update_interval: 15s diff --git a/tests/components/tsl2561/test.esp32-c3.yaml b/tests/components/tsl2561/test.esp32-c3.yaml new file mode 100644 index 0000000000..1ea768c5d9 --- /dev/null +++ b/tests/components/tsl2561/test.esp32-c3.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_tsl2561 + scl: 5 + sda: 4 + +sensor: + - platform: tsl2561 + name: TSL2561 Ambient Light + address: 0x39 + is_cs_package: true + integration_time: 402ms + gain: 16x + update_interval: 15s diff --git a/tests/components/tsl2561/test.esp32-idf.yaml b/tests/components/tsl2561/test.esp32-idf.yaml new file mode 100644 index 0000000000..8d43c62414 --- /dev/null +++ b/tests/components/tsl2561/test.esp32-idf.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_tsl2561 + scl: 16 + sda: 17 + +sensor: + - platform: tsl2561 + name: TSL2561 Ambient Light + address: 0x39 + is_cs_package: true + integration_time: 402ms + gain: 16x + update_interval: 15s diff --git a/tests/components/tsl2561/test.esp32.yaml b/tests/components/tsl2561/test.esp32.yaml new file mode 100644 index 0000000000..8d43c62414 --- /dev/null +++ b/tests/components/tsl2561/test.esp32.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_tsl2561 + scl: 16 + sda: 17 + +sensor: + - platform: tsl2561 + name: TSL2561 Ambient Light + address: 0x39 + is_cs_package: true + integration_time: 402ms + gain: 16x + update_interval: 15s diff --git a/tests/components/tsl2561/test.esp8266.yaml b/tests/components/tsl2561/test.esp8266.yaml new file mode 100644 index 0000000000..1ea768c5d9 --- /dev/null +++ b/tests/components/tsl2561/test.esp8266.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_tsl2561 + scl: 5 + sda: 4 + +sensor: + - platform: tsl2561 + name: TSL2561 Ambient Light + address: 0x39 + is_cs_package: true + integration_time: 402ms + gain: 16x + update_interval: 15s diff --git a/tests/components/tsl2561/test.rp2040.yaml b/tests/components/tsl2561/test.rp2040.yaml new file mode 100644 index 0000000000..1ea768c5d9 --- /dev/null +++ b/tests/components/tsl2561/test.rp2040.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_tsl2561 + scl: 5 + sda: 4 + +sensor: + - platform: tsl2561 + name: TSL2561 Ambient Light + address: 0x39 + is_cs_package: true + integration_time: 402ms + gain: 16x + update_interval: 15s diff --git a/tests/components/tsl2591/test.esp32-c3-idf.yaml b/tests/components/tsl2591/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..de57ef548a --- /dev/null +++ b/tests/components/tsl2591/test.esp32-c3-idf.yaml @@ -0,0 +1,25 @@ +i2c: + - id: i2c_tsl2591 + scl: 5 + sda: 4 + +sensor: + - platform: tsl2591 + id: test_tsl2591 + address: 0x29 + integration_time: 600ms + gain: high + visible: + name: tsl2591 visible + id: tsl2591_vis + unit_of_measurement: pH + infrared: + name: tsl2591 infrared + id: tsl2591_ir + full_spectrum: + name: tsl2591 full_spectrum + id: tsl2591_fs + calculated_lux: + name: tsl2591 calculated_lux + id: tsl2591_cl + update_interval: 15s diff --git a/tests/components/tsl2591/test.esp32-c3.yaml b/tests/components/tsl2591/test.esp32-c3.yaml new file mode 100644 index 0000000000..de57ef548a --- /dev/null +++ b/tests/components/tsl2591/test.esp32-c3.yaml @@ -0,0 +1,25 @@ +i2c: + - id: i2c_tsl2591 + scl: 5 + sda: 4 + +sensor: + - platform: tsl2591 + id: test_tsl2591 + address: 0x29 + integration_time: 600ms + gain: high + visible: + name: tsl2591 visible + id: tsl2591_vis + unit_of_measurement: pH + infrared: + name: tsl2591 infrared + id: tsl2591_ir + full_spectrum: + name: tsl2591 full_spectrum + id: tsl2591_fs + calculated_lux: + name: tsl2591 calculated_lux + id: tsl2591_cl + update_interval: 15s diff --git a/tests/components/tsl2591/test.esp32-idf.yaml b/tests/components/tsl2591/test.esp32-idf.yaml new file mode 100644 index 0000000000..14f9311ae6 --- /dev/null +++ b/tests/components/tsl2591/test.esp32-idf.yaml @@ -0,0 +1,25 @@ +i2c: + - id: i2c_tsl2591 + scl: 16 + sda: 17 + +sensor: + - platform: tsl2591 + id: test_tsl2591 + address: 0x29 + integration_time: 600ms + gain: high + visible: + name: tsl2591 visible + id: tsl2591_vis + unit_of_measurement: pH + infrared: + name: tsl2591 infrared + id: tsl2591_ir + full_spectrum: + name: tsl2591 full_spectrum + id: tsl2591_fs + calculated_lux: + name: tsl2591 calculated_lux + id: tsl2591_cl + update_interval: 15s diff --git a/tests/components/tsl2591/test.esp32.yaml b/tests/components/tsl2591/test.esp32.yaml new file mode 100644 index 0000000000..14f9311ae6 --- /dev/null +++ b/tests/components/tsl2591/test.esp32.yaml @@ -0,0 +1,25 @@ +i2c: + - id: i2c_tsl2591 + scl: 16 + sda: 17 + +sensor: + - platform: tsl2591 + id: test_tsl2591 + address: 0x29 + integration_time: 600ms + gain: high + visible: + name: tsl2591 visible + id: tsl2591_vis + unit_of_measurement: pH + infrared: + name: tsl2591 infrared + id: tsl2591_ir + full_spectrum: + name: tsl2591 full_spectrum + id: tsl2591_fs + calculated_lux: + name: tsl2591 calculated_lux + id: tsl2591_cl + update_interval: 15s diff --git a/tests/components/tsl2591/test.esp8266.yaml b/tests/components/tsl2591/test.esp8266.yaml new file mode 100644 index 0000000000..de57ef548a --- /dev/null +++ b/tests/components/tsl2591/test.esp8266.yaml @@ -0,0 +1,25 @@ +i2c: + - id: i2c_tsl2591 + scl: 5 + sda: 4 + +sensor: + - platform: tsl2591 + id: test_tsl2591 + address: 0x29 + integration_time: 600ms + gain: high + visible: + name: tsl2591 visible + id: tsl2591_vis + unit_of_measurement: pH + infrared: + name: tsl2591 infrared + id: tsl2591_ir + full_spectrum: + name: tsl2591 full_spectrum + id: tsl2591_fs + calculated_lux: + name: tsl2591 calculated_lux + id: tsl2591_cl + update_interval: 15s diff --git a/tests/components/tsl2591/test.rp2040.yaml b/tests/components/tsl2591/test.rp2040.yaml new file mode 100644 index 0000000000..de57ef548a --- /dev/null +++ b/tests/components/tsl2591/test.rp2040.yaml @@ -0,0 +1,25 @@ +i2c: + - id: i2c_tsl2591 + scl: 5 + sda: 4 + +sensor: + - platform: tsl2591 + id: test_tsl2591 + address: 0x29 + integration_time: 600ms + gain: high + visible: + name: tsl2591 visible + id: tsl2591_vis + unit_of_measurement: pH + infrared: + name: tsl2591 infrared + id: tsl2591_ir + full_spectrum: + name: tsl2591 full_spectrum + id: tsl2591_fs + calculated_lux: + name: tsl2591 calculated_lux + id: tsl2591_cl + update_interval: 15s diff --git a/tests/components/tt21100/test.esp32-c3-idf.yaml b/tests/components/tt21100/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..17b8c8065a --- /dev/null +++ b/tests/components/tt21100/test.esp32-c3-idf.yaml @@ -0,0 +1,25 @@ +i2c: + - id: i2c_tt21100 + scl: 5 + sda: 4 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 3 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: tt21100 + display: ssd1306_display + interrupt_pin: 6 + reset_pin: 7 + +binary_sensor: + - platform: tt21100 + name: Home Button + index: 1 diff --git a/tests/components/tt21100/test.esp32-c3.yaml b/tests/components/tt21100/test.esp32-c3.yaml new file mode 100644 index 0000000000..17b8c8065a --- /dev/null +++ b/tests/components/tt21100/test.esp32-c3.yaml @@ -0,0 +1,25 @@ +i2c: + - id: i2c_tt21100 + scl: 5 + sda: 4 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 3 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: tt21100 + display: ssd1306_display + interrupt_pin: 6 + reset_pin: 7 + +binary_sensor: + - platform: tt21100 + name: Home Button + index: 1 diff --git a/tests/components/tt21100/test.esp32-idf.yaml b/tests/components/tt21100/test.esp32-idf.yaml new file mode 100644 index 0000000000..2419b0ad6a --- /dev/null +++ b/tests/components/tt21100/test.esp32-idf.yaml @@ -0,0 +1,25 @@ +i2c: + - id: i2c_tt21100 + scl: 16 + sda: 17 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 13 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: tt21100 + display: ssd1306_display + interrupt_pin: 14 + reset_pin: 15 + +binary_sensor: + - platform: tt21100 + name: Home Button + index: 1 diff --git a/tests/components/tt21100/test.esp32.yaml b/tests/components/tt21100/test.esp32.yaml new file mode 100644 index 0000000000..2419b0ad6a --- /dev/null +++ b/tests/components/tt21100/test.esp32.yaml @@ -0,0 +1,25 @@ +i2c: + - id: i2c_tt21100 + scl: 16 + sda: 17 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 13 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: tt21100 + display: ssd1306_display + interrupt_pin: 14 + reset_pin: 15 + +binary_sensor: + - platform: tt21100 + name: Home Button + index: 1 diff --git a/tests/components/tt21100/test.esp8266.yaml b/tests/components/tt21100/test.esp8266.yaml new file mode 100644 index 0000000000..1393019417 --- /dev/null +++ b/tests/components/tt21100/test.esp8266.yaml @@ -0,0 +1,25 @@ +i2c: + - id: i2c_tt21100 + scl: 5 + sda: 4 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 13 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: tt21100 + display: ssd1306_display + interrupt_pin: 14 + reset_pin: 15 + +binary_sensor: + - platform: tt21100 + name: Home Button + index: 1 diff --git a/tests/components/tt21100/test.rp2040.yaml b/tests/components/tt21100/test.rp2040.yaml new file mode 100644 index 0000000000..17b8c8065a --- /dev/null +++ b/tests/components/tt21100/test.rp2040.yaml @@ -0,0 +1,25 @@ +i2c: + - id: i2c_tt21100 + scl: 5 + sda: 4 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 3 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: tt21100 + display: ssd1306_display + interrupt_pin: 6 + reset_pin: 7 + +binary_sensor: + - platform: tt21100 + name: Home Button + index: 1 diff --git a/tests/components/ttp229_bsf/test.esp32-c3-idf.yaml b/tests/components/ttp229_bsf/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..2006061c6e --- /dev/null +++ b/tests/components/ttp229_bsf/test.esp32-c3-idf.yaml @@ -0,0 +1,8 @@ +ttp229_bsf: + scl_pin: 5 + sdo_pin: 4 + +binary_sensor: + - platform: ttp229_bsf + name: TTP229 Channel 0 + channel: 0 diff --git a/tests/components/ttp229_bsf/test.esp32-c3.yaml b/tests/components/ttp229_bsf/test.esp32-c3.yaml new file mode 100644 index 0000000000..2006061c6e --- /dev/null +++ b/tests/components/ttp229_bsf/test.esp32-c3.yaml @@ -0,0 +1,8 @@ +ttp229_bsf: + scl_pin: 5 + sdo_pin: 4 + +binary_sensor: + - platform: ttp229_bsf + name: TTP229 Channel 0 + channel: 0 diff --git a/tests/components/ttp229_bsf/test.esp32-idf.yaml b/tests/components/ttp229_bsf/test.esp32-idf.yaml new file mode 100644 index 0000000000..edee6d164e --- /dev/null +++ b/tests/components/ttp229_bsf/test.esp32-idf.yaml @@ -0,0 +1,8 @@ +ttp229_bsf: + scl_pin: 16 + sdo_pin: 17 + +binary_sensor: + - platform: ttp229_bsf + name: TTP229 Channel 0 + channel: 0 diff --git a/tests/components/ttp229_bsf/test.esp32.yaml b/tests/components/ttp229_bsf/test.esp32.yaml new file mode 100644 index 0000000000..edee6d164e --- /dev/null +++ b/tests/components/ttp229_bsf/test.esp32.yaml @@ -0,0 +1,8 @@ +ttp229_bsf: + scl_pin: 16 + sdo_pin: 17 + +binary_sensor: + - platform: ttp229_bsf + name: TTP229 Channel 0 + channel: 0 diff --git a/tests/components/ttp229_bsf/test.esp8266.yaml b/tests/components/ttp229_bsf/test.esp8266.yaml new file mode 100644 index 0000000000..2006061c6e --- /dev/null +++ b/tests/components/ttp229_bsf/test.esp8266.yaml @@ -0,0 +1,8 @@ +ttp229_bsf: + scl_pin: 5 + sdo_pin: 4 + +binary_sensor: + - platform: ttp229_bsf + name: TTP229 Channel 0 + channel: 0 diff --git a/tests/components/ttp229_bsf/test.rp2040.yaml b/tests/components/ttp229_bsf/test.rp2040.yaml new file mode 100644 index 0000000000..2006061c6e --- /dev/null +++ b/tests/components/ttp229_bsf/test.rp2040.yaml @@ -0,0 +1,8 @@ +ttp229_bsf: + scl_pin: 5 + sdo_pin: 4 + +binary_sensor: + - platform: ttp229_bsf + name: TTP229 Channel 0 + channel: 0 diff --git a/tests/components/ttp229_lsf/test.esp32-c3-idf.yaml b/tests/components/ttp229_lsf/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..3927aff40e --- /dev/null +++ b/tests/components/ttp229_lsf/test.esp32-c3-idf.yaml @@ -0,0 +1,11 @@ +i2c: + - id: i2c_ttp229_lsf + scl: 5 + sda: 4 + +ttp229_lsf: + +binary_sensor: + - platform: ttp229_lsf + name: TTP229 Channel 0 + channel: 0 diff --git a/tests/components/ttp229_lsf/test.esp32-c3.yaml b/tests/components/ttp229_lsf/test.esp32-c3.yaml new file mode 100644 index 0000000000..3927aff40e --- /dev/null +++ b/tests/components/ttp229_lsf/test.esp32-c3.yaml @@ -0,0 +1,11 @@ +i2c: + - id: i2c_ttp229_lsf + scl: 5 + sda: 4 + +ttp229_lsf: + +binary_sensor: + - platform: ttp229_lsf + name: TTP229 Channel 0 + channel: 0 diff --git a/tests/components/ttp229_lsf/test.esp32-idf.yaml b/tests/components/ttp229_lsf/test.esp32-idf.yaml new file mode 100644 index 0000000000..81fb965883 --- /dev/null +++ b/tests/components/ttp229_lsf/test.esp32-idf.yaml @@ -0,0 +1,11 @@ +i2c: + - id: i2c_ttp229_lsf + scl: 16 + sda: 17 + +ttp229_lsf: + +binary_sensor: + - platform: ttp229_lsf + name: TTP229 Channel 0 + channel: 0 diff --git a/tests/components/ttp229_lsf/test.esp32.yaml b/tests/components/ttp229_lsf/test.esp32.yaml new file mode 100644 index 0000000000..81fb965883 --- /dev/null +++ b/tests/components/ttp229_lsf/test.esp32.yaml @@ -0,0 +1,11 @@ +i2c: + - id: i2c_ttp229_lsf + scl: 16 + sda: 17 + +ttp229_lsf: + +binary_sensor: + - platform: ttp229_lsf + name: TTP229 Channel 0 + channel: 0 diff --git a/tests/components/ttp229_lsf/test.esp8266.yaml b/tests/components/ttp229_lsf/test.esp8266.yaml new file mode 100644 index 0000000000..3927aff40e --- /dev/null +++ b/tests/components/ttp229_lsf/test.esp8266.yaml @@ -0,0 +1,11 @@ +i2c: + - id: i2c_ttp229_lsf + scl: 5 + sda: 4 + +ttp229_lsf: + +binary_sensor: + - platform: ttp229_lsf + name: TTP229 Channel 0 + channel: 0 diff --git a/tests/components/ttp229_lsf/test.rp2040.yaml b/tests/components/ttp229_lsf/test.rp2040.yaml new file mode 100644 index 0000000000..3927aff40e --- /dev/null +++ b/tests/components/ttp229_lsf/test.rp2040.yaml @@ -0,0 +1,11 @@ +i2c: + - id: i2c_ttp229_lsf + scl: 5 + sda: 4 + +ttp229_lsf: + +binary_sensor: + - platform: ttp229_lsf + name: TTP229 Channel 0 + channel: 0 diff --git a/tests/components/tuya/test.esp32-c3-idf.yaml b/tests/components/tuya/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..4892e807b1 --- /dev/null +++ b/tests/components/tuya/test.esp32-c3-idf.yaml @@ -0,0 +1,78 @@ +wifi: + ssid: MySSID + password: password1 + +uart: + - id: uart_tuya + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +tuya: + status_pin: + number: 6 + inverted: true + on_datapoint_update: + - sensor_datapoint: 6 + datapoint_type: raw + then: + - logger.log: Datapoint 6 updated + +binary_sensor: + - platform: tuya + id: tuya_binary_sensor + sensor_datapoint: 1 + +climate: + - platform: tuya + id: tuya_climate + switch_datapoint: 1 + target_temperature_datapoint: 3 + current_temperature_multiplier: 0.5 + target_temperature_multiplier: 0.5 + reports_fahrenheit: true + +cover: + - platform: tuya + id: tuya_cover + position_datapoint: 2 + +light: + - platform: tuya + id: tuya_light + switch_datapoint: 1 + dimmer_datapoint: 2 + min_value_datapoint: 3 + color_temperature_datapoint: 4 + min_value: 1 + max_value: 100 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds + gamma_correct: 1 + +number: + - platform: tuya + id: tuya_number + number_datapoint: 102 + min_value: 0 + max_value: 17 + step: 1 + +select: + - platform: tuya + id: tuya_select + enum_datapoint: 42 + options: + 0: Internal + 1: Floor + 2: Both + +sensor: + - platform: tuya + id: tuya_sensor + sensor_datapoint: 1 + +switch: + - platform: tuya + id: tuya_switch + switch_datapoint: 1 diff --git a/tests/components/tuya/test.esp32-c3.yaml b/tests/components/tuya/test.esp32-c3.yaml new file mode 100644 index 0000000000..4892e807b1 --- /dev/null +++ b/tests/components/tuya/test.esp32-c3.yaml @@ -0,0 +1,78 @@ +wifi: + ssid: MySSID + password: password1 + +uart: + - id: uart_tuya + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +tuya: + status_pin: + number: 6 + inverted: true + on_datapoint_update: + - sensor_datapoint: 6 + datapoint_type: raw + then: + - logger.log: Datapoint 6 updated + +binary_sensor: + - platform: tuya + id: tuya_binary_sensor + sensor_datapoint: 1 + +climate: + - platform: tuya + id: tuya_climate + switch_datapoint: 1 + target_temperature_datapoint: 3 + current_temperature_multiplier: 0.5 + target_temperature_multiplier: 0.5 + reports_fahrenheit: true + +cover: + - platform: tuya + id: tuya_cover + position_datapoint: 2 + +light: + - platform: tuya + id: tuya_light + switch_datapoint: 1 + dimmer_datapoint: 2 + min_value_datapoint: 3 + color_temperature_datapoint: 4 + min_value: 1 + max_value: 100 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds + gamma_correct: 1 + +number: + - platform: tuya + id: tuya_number + number_datapoint: 102 + min_value: 0 + max_value: 17 + step: 1 + +select: + - platform: tuya + id: tuya_select + enum_datapoint: 42 + options: + 0: Internal + 1: Floor + 2: Both + +sensor: + - platform: tuya + id: tuya_sensor + sensor_datapoint: 1 + +switch: + - platform: tuya + id: tuya_switch + switch_datapoint: 1 diff --git a/tests/components/tuya/test.esp32-idf.yaml b/tests/components/tuya/test.esp32-idf.yaml new file mode 100644 index 0000000000..9105522dcd --- /dev/null +++ b/tests/components/tuya/test.esp32-idf.yaml @@ -0,0 +1,78 @@ +wifi: + ssid: MySSID + password: password1 + +uart: + - id: uart_tuya + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +tuya: + status_pin: + number: 15 + inverted: true + on_datapoint_update: + - sensor_datapoint: 6 + datapoint_type: raw + then: + - logger.log: Datapoint 6 updated + +binary_sensor: + - platform: tuya + id: tuya_binary_sensor + sensor_datapoint: 1 + +climate: + - platform: tuya + id: tuya_climate + switch_datapoint: 1 + target_temperature_datapoint: 3 + current_temperature_multiplier: 0.5 + target_temperature_multiplier: 0.5 + reports_fahrenheit: true + +cover: + - platform: tuya + id: tuya_cover + position_datapoint: 2 + +light: + - platform: tuya + id: tuya_light + switch_datapoint: 1 + dimmer_datapoint: 2 + min_value_datapoint: 3 + color_temperature_datapoint: 4 + min_value: 1 + max_value: 100 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds + gamma_correct: 1 + +number: + - platform: tuya + id: tuya_number + number_datapoint: 102 + min_value: 0 + max_value: 17 + step: 1 + +select: + - platform: tuya + id: tuya_select + enum_datapoint: 42 + options: + 0: Internal + 1: Floor + 2: Both + +sensor: + - platform: tuya + id: tuya_sensor + sensor_datapoint: 1 + +switch: + - platform: tuya + id: tuya_switch + switch_datapoint: 1 diff --git a/tests/components/tuya/test.esp32.yaml b/tests/components/tuya/test.esp32.yaml new file mode 100644 index 0000000000..9105522dcd --- /dev/null +++ b/tests/components/tuya/test.esp32.yaml @@ -0,0 +1,78 @@ +wifi: + ssid: MySSID + password: password1 + +uart: + - id: uart_tuya + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +tuya: + status_pin: + number: 15 + inverted: true + on_datapoint_update: + - sensor_datapoint: 6 + datapoint_type: raw + then: + - logger.log: Datapoint 6 updated + +binary_sensor: + - platform: tuya + id: tuya_binary_sensor + sensor_datapoint: 1 + +climate: + - platform: tuya + id: tuya_climate + switch_datapoint: 1 + target_temperature_datapoint: 3 + current_temperature_multiplier: 0.5 + target_temperature_multiplier: 0.5 + reports_fahrenheit: true + +cover: + - platform: tuya + id: tuya_cover + position_datapoint: 2 + +light: + - platform: tuya + id: tuya_light + switch_datapoint: 1 + dimmer_datapoint: 2 + min_value_datapoint: 3 + color_temperature_datapoint: 4 + min_value: 1 + max_value: 100 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds + gamma_correct: 1 + +number: + - platform: tuya + id: tuya_number + number_datapoint: 102 + min_value: 0 + max_value: 17 + step: 1 + +select: + - platform: tuya + id: tuya_select + enum_datapoint: 42 + options: + 0: Internal + 1: Floor + 2: Both + +sensor: + - platform: tuya + id: tuya_sensor + sensor_datapoint: 1 + +switch: + - platform: tuya + id: tuya_switch + switch_datapoint: 1 diff --git a/tests/components/tuya/test.esp8266.yaml b/tests/components/tuya/test.esp8266.yaml new file mode 100644 index 0000000000..56177fb982 --- /dev/null +++ b/tests/components/tuya/test.esp8266.yaml @@ -0,0 +1,78 @@ +wifi: + ssid: MySSID + password: password1 + +uart: + - id: uart_tuya + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +tuya: + status_pin: + number: 16 + inverted: true + on_datapoint_update: + - sensor_datapoint: 6 + datapoint_type: raw + then: + - logger.log: Datapoint 6 updated + +binary_sensor: + - platform: tuya + id: tuya_binary_sensor + sensor_datapoint: 1 + +climate: + - platform: tuya + id: tuya_climate + switch_datapoint: 1 + target_temperature_datapoint: 3 + current_temperature_multiplier: 0.5 + target_temperature_multiplier: 0.5 + reports_fahrenheit: true + +cover: + - platform: tuya + id: tuya_cover + position_datapoint: 2 + +light: + - platform: tuya + id: tuya_light + switch_datapoint: 1 + dimmer_datapoint: 2 + min_value_datapoint: 3 + color_temperature_datapoint: 4 + min_value: 1 + max_value: 100 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds + gamma_correct: 1 + +number: + - platform: tuya + id: tuya_number + number_datapoint: 102 + min_value: 0 + max_value: 17 + step: 1 + +select: + - platform: tuya + id: tuya_select + enum_datapoint: 42 + options: + 0: Internal + 1: Floor + 2: Both + +sensor: + - platform: tuya + id: tuya_sensor + sensor_datapoint: 1 + +switch: + - platform: tuya + id: tuya_switch + switch_datapoint: 1 diff --git a/tests/components/tuya/test.rp2040.yaml b/tests/components/tuya/test.rp2040.yaml new file mode 100644 index 0000000000..4892e807b1 --- /dev/null +++ b/tests/components/tuya/test.rp2040.yaml @@ -0,0 +1,78 @@ +wifi: + ssid: MySSID + password: password1 + +uart: + - id: uart_tuya + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +tuya: + status_pin: + number: 6 + inverted: true + on_datapoint_update: + - sensor_datapoint: 6 + datapoint_type: raw + then: + - logger.log: Datapoint 6 updated + +binary_sensor: + - platform: tuya + id: tuya_binary_sensor + sensor_datapoint: 1 + +climate: + - platform: tuya + id: tuya_climate + switch_datapoint: 1 + target_temperature_datapoint: 3 + current_temperature_multiplier: 0.5 + target_temperature_multiplier: 0.5 + reports_fahrenheit: true + +cover: + - platform: tuya + id: tuya_cover + position_datapoint: 2 + +light: + - platform: tuya + id: tuya_light + switch_datapoint: 1 + dimmer_datapoint: 2 + min_value_datapoint: 3 + color_temperature_datapoint: 4 + min_value: 1 + max_value: 100 + cold_white_color_temperature: 153 mireds + warm_white_color_temperature: 500 mireds + gamma_correct: 1 + +number: + - platform: tuya + id: tuya_number + number_datapoint: 102 + min_value: 0 + max_value: 17 + step: 1 + +select: + - platform: tuya + id: tuya_select + enum_datapoint: 42 + options: + 0: Internal + 1: Floor + 2: Both + +sensor: + - platform: tuya + id: tuya_sensor + sensor_datapoint: 1 + +switch: + - platform: tuya + id: tuya_switch + switch_datapoint: 1 diff --git a/tests/components/tx20/test.esp32-c3-idf.yaml b/tests/components/tx20/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..d826059320 --- /dev/null +++ b/tests/components/tx20/test.esp32-c3-idf.yaml @@ -0,0 +1,7 @@ +sensor: + - platform: tx20 + wind_speed: + name: Windspeed + wind_direction_degrees: + name: Winddirection Degrees + pin: 4 diff --git a/tests/components/tx20/test.esp32-c3.yaml b/tests/components/tx20/test.esp32-c3.yaml new file mode 100644 index 0000000000..d826059320 --- /dev/null +++ b/tests/components/tx20/test.esp32-c3.yaml @@ -0,0 +1,7 @@ +sensor: + - platform: tx20 + wind_speed: + name: Windspeed + wind_direction_degrees: + name: Winddirection Degrees + pin: 4 diff --git a/tests/components/tx20/test.esp32-idf.yaml b/tests/components/tx20/test.esp32-idf.yaml new file mode 100644 index 0000000000..d826059320 --- /dev/null +++ b/tests/components/tx20/test.esp32-idf.yaml @@ -0,0 +1,7 @@ +sensor: + - platform: tx20 + wind_speed: + name: Windspeed + wind_direction_degrees: + name: Winddirection Degrees + pin: 4 diff --git a/tests/components/tx20/test.esp32.yaml b/tests/components/tx20/test.esp32.yaml new file mode 100644 index 0000000000..d826059320 --- /dev/null +++ b/tests/components/tx20/test.esp32.yaml @@ -0,0 +1,7 @@ +sensor: + - platform: tx20 + wind_speed: + name: Windspeed + wind_direction_degrees: + name: Winddirection Degrees + pin: 4 diff --git a/tests/components/tx20/test.esp8266.yaml b/tests/components/tx20/test.esp8266.yaml new file mode 100644 index 0000000000..d826059320 --- /dev/null +++ b/tests/components/tx20/test.esp8266.yaml @@ -0,0 +1,7 @@ +sensor: + - platform: tx20 + wind_speed: + name: Windspeed + wind_direction_degrees: + name: Winddirection Degrees + pin: 4 diff --git a/tests/components/tx20/test.rp2040.yaml b/tests/components/tx20/test.rp2040.yaml new file mode 100644 index 0000000000..d826059320 --- /dev/null +++ b/tests/components/tx20/test.rp2040.yaml @@ -0,0 +1,7 @@ +sensor: + - platform: tx20 + wind_speed: + name: Windspeed + wind_direction_degrees: + name: Winddirection Degrees + pin: 4 From 7e8ed5c391fa773ecf8f450196f05215bb5cf3d4 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Tue, 23 Apr 2024 04:49:15 -0500 Subject: [PATCH 1313/2101] Add some components to the new testing framework (S part 1) (#6224) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- .../safe_mode/test.esp32-c3-idf.yaml | 13 +++++ tests/components/safe_mode/test.esp32-c3.yaml | 13 +++++ .../components/safe_mode/test.esp32-idf.yaml | 13 +++++ tests/components/safe_mode/test.esp32.yaml | 13 +++++ tests/components/safe_mode/test.esp8266.yaml | 13 +++++ tests/components/safe_mode/test.rp2040.yaml | 13 +++++ tests/components/scd30/test.esp32-c3-idf.yaml | 20 ++++++++ tests/components/scd30/test.esp32-c3.yaml | 20 ++++++++ tests/components/scd30/test.esp32-idf.yaml | 20 ++++++++ tests/components/scd30/test.esp32.yaml | 20 ++++++++ tests/components/scd30/test.esp8266.yaml | 20 ++++++++ tests/components/scd30/test.rp2040.yaml | 20 ++++++++ tests/components/scd4x/test.esp32-c3-idf.yaml | 20 ++++++++ tests/components/scd4x/test.esp32-c3.yaml | 20 ++++++++ tests/components/scd4x/test.esp32-idf.yaml | 20 ++++++++ tests/components/scd4x/test.esp32.yaml | 20 ++++++++ tests/components/scd4x/test.esp8266.yaml | 20 ++++++++ tests/components/scd4x/test.rp2040.yaml | 20 ++++++++ .../components/script/test.esp32-c3-idf.yaml | 26 ++++++++++ tests/components/script/test.esp32-c3.yaml | 26 ++++++++++ tests/components/script/test.esp32-idf.yaml | 26 ++++++++++ tests/components/script/test.esp32.yaml | 26 ++++++++++ tests/components/script/test.esp8266.yaml | 26 ++++++++++ tests/components/script/test.rp2040.yaml | 26 ++++++++++ .../sdm_meter/test.esp32-c3-idf.yaml | 23 +++++++++ tests/components/sdm_meter/test.esp32-c3.yaml | 23 +++++++++ .../components/sdm_meter/test.esp32-idf.yaml | 23 +++++++++ tests/components/sdm_meter/test.esp32.yaml | 23 +++++++++ tests/components/sdm_meter/test.esp8266.yaml | 23 +++++++++ tests/components/sdm_meter/test.rp2040.yaml | 23 +++++++++ tests/components/sdp3x/test.esp32-c3-idf.yaml | 11 +++++ tests/components/sdp3x/test.esp32-c3.yaml | 11 +++++ tests/components/sdp3x/test.esp32-idf.yaml | 11 +++++ tests/components/sdp3x/test.esp32.yaml | 11 +++++ tests/components/sdp3x/test.esp8266.yaml | 11 +++++ tests/components/sdp3x/test.rp2040.yaml | 11 +++++ .../components/sds011/test.esp32-c3-idf.yaml | 14 ++++++ tests/components/sds011/test.esp32-c3.yaml | 14 ++++++ tests/components/sds011/test.esp32-idf.yaml | 14 ++++++ tests/components/sds011/test.esp32.yaml | 14 ++++++ tests/components/sds011/test.esp8266.yaml | 14 ++++++ tests/components/sds011/test.rp2040.yaml | 14 ++++++ .../selec_meter/test.esp32-c3-idf.yaml | 45 +++++++++++++++++ .../components/selec_meter/test.esp32-c3.yaml | 45 +++++++++++++++++ .../selec_meter/test.esp32-idf.yaml | 45 +++++++++++++++++ tests/components/selec_meter/test.esp32.yaml | 45 +++++++++++++++++ .../components/selec_meter/test.esp8266.yaml | 45 +++++++++++++++++ tests/components/selec_meter/test.rp2040.yaml | 45 +++++++++++++++++ .../components/sen0321/test.esp32-c3-idf.yaml | 10 ++++ tests/components/sen0321/test.esp32-c3.yaml | 10 ++++ tests/components/sen0321/test.esp32-idf.yaml | 10 ++++ tests/components/sen0321/test.esp32.yaml | 10 ++++ tests/components/sen0321/test.esp8266.yaml | 10 ++++ tests/components/sen0321/test.rp2040.yaml | 10 ++++ .../sen21231/test.esp32-c3-idf.yaml | 9 ++++ tests/components/sen21231/test.esp32-c3.yaml | 9 ++++ tests/components/sen21231/test.esp32-idf.yaml | 9 ++++ tests/components/sen21231/test.esp32.yaml | 9 ++++ tests/components/sen21231/test.esp8266.yaml | 9 ++++ tests/components/sen21231/test.rp2040.yaml | 9 ++++ tests/components/sen5x/test.esp32-c3-idf.yaml | 49 +++++++++++++++++++ tests/components/sen5x/test.esp32-c3.yaml | 49 +++++++++++++++++++ tests/components/sen5x/test.esp32-idf.yaml | 49 +++++++++++++++++++ tests/components/sen5x/test.esp32.yaml | 49 +++++++++++++++++++ tests/components/sen5x/test.esp8266.yaml | 49 +++++++++++++++++++ tests/components/sen5x/test.rp2040.yaml | 49 +++++++++++++++++++ .../senseair/test.esp32-c3-idf.yaml | 19 +++++++ tests/components/senseair/test.esp32-c3.yaml | 19 +++++++ tests/components/senseair/test.esp32-idf.yaml | 19 +++++++ tests/components/senseair/test.esp32.yaml | 19 +++++++ tests/components/senseair/test.esp8266.yaml | 19 +++++++ tests/components/senseair/test.rp2040.yaml | 19 +++++++ tests/components/servo/test.esp32-c3-idf.yaml | 19 +++++++ tests/components/servo/test.esp32-c3.yaml | 19 +++++++ tests/components/servo/test.esp32-idf.yaml | 19 +++++++ tests/components/servo/test.esp32.yaml | 19 +++++++ tests/components/servo/test.esp8266.yaml | 19 +++++++ tests/components/servo/test.rp2040.yaml | 19 +++++++ tests/components/sfa30/test.esp32-c3-idf.yaml | 15 ++++++ tests/components/sfa30/test.esp32-c3.yaml | 15 ++++++ tests/components/sfa30/test.esp32-idf.yaml | 15 ++++++ tests/components/sfa30/test.esp32.yaml | 15 ++++++ tests/components/sfa30/test.esp8266.yaml | 15 ++++++ tests/components/sfa30/test.rp2040.yaml | 15 ++++++ tests/components/sgp30/test.esp32-c3-idf.yaml | 15 ++++++ tests/components/sgp30/test.esp32-c3.yaml | 15 ++++++ tests/components/sgp30/test.esp32-idf.yaml | 15 ++++++ tests/components/sgp30/test.esp32.yaml | 15 ++++++ tests/components/sgp30/test.esp8266.yaml | 15 ++++++ tests/components/sgp30/test.rp2040.yaml | 15 ++++++ tests/components/sgp4x/test.esp32-c3-idf.yaml | 27 ++++++++++ tests/components/sgp4x/test.esp32-c3.yaml | 27 ++++++++++ tests/components/sgp4x/test.esp32-idf.yaml | 27 ++++++++++ tests/components/sgp4x/test.esp32.yaml | 27 ++++++++++ tests/components/sgp4x/test.esp8266.yaml | 27 ++++++++++ tests/components/sgp4x/test.rp2040.yaml | 27 ++++++++++ .../shelly_dimmer/test.esp8266.yaml | 19 +++++++ .../components/sht3xd/test.esp32-c3-idf.yaml | 13 +++++ tests/components/sht3xd/test.esp32-c3.yaml | 13 +++++ tests/components/sht3xd/test.esp32-idf.yaml | 13 +++++ tests/components/sht3xd/test.esp32.yaml | 13 +++++ tests/components/sht3xd/test.esp8266.yaml | 13 +++++ tests/components/sht3xd/test.rp2040.yaml | 13 +++++ tests/components/sht4x/test.esp32-c3-idf.yaml | 13 +++++ tests/components/sht4x/test.esp32-c3.yaml | 13 +++++ tests/components/sht4x/test.esp32-idf.yaml | 13 +++++ tests/components/sht4x/test.esp32.yaml | 13 +++++ tests/components/sht4x/test.esp8266.yaml | 13 +++++ tests/components/sht4x/test.rp2040.yaml | 13 +++++ tests/components/shtcx/test.esp32-c3-idf.yaml | 13 +++++ tests/components/shtcx/test.esp32-c3.yaml | 13 +++++ tests/components/shtcx/test.esp32-idf.yaml | 13 +++++ tests/components/shtcx/test.esp32.yaml | 13 +++++ tests/components/shtcx/test.esp8266.yaml | 13 +++++ tests/components/shtcx/test.rp2040.yaml | 13 +++++ .../shutdown/test.esp32-c3-idf.yaml | 7 +++ tests/components/shutdown/test.esp32-c3.yaml | 7 +++ tests/components/shutdown/test.esp32-idf.yaml | 7 +++ tests/components/shutdown/test.esp32.yaml | 7 +++ tests/components/shutdown/test.esp8266.yaml | 7 +++ tests/components/shutdown/test.rp2040.yaml | 7 +++ .../sigma_delta_output/test.esp32-c3-idf.yaml | 16 ++++++ .../sigma_delta_output/test.esp32-c3.yaml | 16 ++++++ .../sigma_delta_output/test.esp32-idf.yaml | 16 ++++++ .../sigma_delta_output/test.esp32.yaml | 16 ++++++ .../sigma_delta_output/test.esp8266.yaml | 16 ++++++ .../sigma_delta_output/test.rp2040.yaml | 16 ++++++ .../components/sim800l/test.esp32-c3-idf.yaml | 37 ++++++++++++++ tests/components/sim800l/test.esp32-c3.yaml | 37 ++++++++++++++ tests/components/sim800l/test.esp32-idf.yaml | 37 ++++++++++++++ tests/components/sim800l/test.esp32.yaml | 37 ++++++++++++++ tests/components/sim800l/test.esp8266.yaml | 37 ++++++++++++++ tests/components/sim800l/test.rp2040.yaml | 37 ++++++++++++++ .../slow_pwm/test.esp32-c3-idf.yaml | 6 +++ tests/components/slow_pwm/test.esp32-c3.yaml | 6 +++ tests/components/slow_pwm/test.esp32-idf.yaml | 6 +++ tests/components/slow_pwm/test.esp32.yaml | 6 +++ tests/components/slow_pwm/test.esp8266.yaml | 6 +++ tests/components/slow_pwm/test.rp2040.yaml | 6 +++ .../components/sm16716/test.esp32-c3-idf.yaml | 16 ++++++ tests/components/sm16716/test.esp32-c3.yaml | 16 ++++++ tests/components/sm16716/test.esp32-idf.yaml | 16 ++++++ tests/components/sm16716/test.esp32.yaml | 16 ++++++ tests/components/sm16716/test.esp8266.yaml | 16 ++++++ tests/components/sm16716/test.rp2040.yaml | 16 ++++++ .../components/sm2135/test.esp32-c3-idf.yaml | 22 +++++++++ tests/components/sm2135/test.esp32-c3.yaml | 22 +++++++++ tests/components/sm2135/test.esp32-idf.yaml | 22 +++++++++ tests/components/sm2135/test.esp32.yaml | 22 +++++++++ tests/components/sm2135/test.esp8266.yaml | 22 +++++++++ tests/components/sm2135/test.rp2040.yaml | 22 +++++++++ .../components/sm2235/test.esp32-c3-idf.yaml | 22 +++++++++ tests/components/sm2235/test.esp32-c3.yaml | 22 +++++++++ tests/components/sm2235/test.esp32-idf.yaml | 22 +++++++++ tests/components/sm2235/test.esp32.yaml | 22 +++++++++ tests/components/sm2235/test.esp8266.yaml | 22 +++++++++ tests/components/sm2235/test.rp2040.yaml | 22 +++++++++ .../components/sm2335/test.esp32-c3-idf.yaml | 22 +++++++++ tests/components/sm2335/test.esp32-c3.yaml | 22 +++++++++ tests/components/sm2335/test.esp32-idf.yaml | 22 +++++++++ tests/components/sm2335/test.esp32.yaml | 22 +++++++++ tests/components/sm2335/test.esp8266.yaml | 22 +++++++++ tests/components/sm2335/test.rp2040.yaml | 22 +++++++++ .../components/sm300d2/test.esp32-c3-idf.yaml | 23 +++++++++ tests/components/sm300d2/test.esp32-c3.yaml | 23 +++++++++ tests/components/sm300d2/test.esp32-idf.yaml | 23 +++++++++ tests/components/sm300d2/test.esp32.yaml | 23 +++++++++ tests/components/sm300d2/test.esp8266.yaml | 23 +++++++++ tests/components/sm300d2/test.rp2040.yaml | 23 +++++++++ tests/components/sml/test.esp32-c3-idf.yaml | 31 ++++++++++++ tests/components/sml/test.esp32-c3.yaml | 31 ++++++++++++ tests/components/sml/test.esp32-idf.yaml | 31 ++++++++++++ tests/components/sml/test.esp32.yaml | 31 ++++++++++++ tests/components/sml/test.esp8266.yaml | 31 ++++++++++++ tests/components/sml/test.rp2040.yaml | 31 ++++++++++++ .../components/smt100/test.esp32-c3-idf.yaml | 19 +++++++ tests/components/smt100/test.esp32-c3.yaml | 19 +++++++ tests/components/smt100/test.esp32-idf.yaml | 19 +++++++ tests/components/smt100/test.esp32.yaml | 19 +++++++ tests/components/smt100/test.esp8266.yaml | 19 +++++++ tests/components/smt100/test.rp2040.yaml | 19 +++++++ 181 files changed, 3589 insertions(+) create mode 100644 tests/components/safe_mode/test.esp32-c3-idf.yaml create mode 100644 tests/components/safe_mode/test.esp32-c3.yaml create mode 100644 tests/components/safe_mode/test.esp32-idf.yaml create mode 100644 tests/components/safe_mode/test.esp32.yaml create mode 100644 tests/components/safe_mode/test.esp8266.yaml create mode 100644 tests/components/safe_mode/test.rp2040.yaml create mode 100644 tests/components/scd30/test.esp32-c3-idf.yaml create mode 100644 tests/components/scd30/test.esp32-c3.yaml create mode 100644 tests/components/scd30/test.esp32-idf.yaml create mode 100644 tests/components/scd30/test.esp32.yaml create mode 100644 tests/components/scd30/test.esp8266.yaml create mode 100644 tests/components/scd30/test.rp2040.yaml create mode 100644 tests/components/scd4x/test.esp32-c3-idf.yaml create mode 100644 tests/components/scd4x/test.esp32-c3.yaml create mode 100644 tests/components/scd4x/test.esp32-idf.yaml create mode 100644 tests/components/scd4x/test.esp32.yaml create mode 100644 tests/components/scd4x/test.esp8266.yaml create mode 100644 tests/components/scd4x/test.rp2040.yaml create mode 100644 tests/components/script/test.esp32-c3-idf.yaml create mode 100644 tests/components/script/test.esp32-c3.yaml create mode 100644 tests/components/script/test.esp32-idf.yaml create mode 100644 tests/components/script/test.esp32.yaml create mode 100644 tests/components/script/test.esp8266.yaml create mode 100644 tests/components/script/test.rp2040.yaml create mode 100644 tests/components/sdm_meter/test.esp32-c3-idf.yaml create mode 100644 tests/components/sdm_meter/test.esp32-c3.yaml create mode 100644 tests/components/sdm_meter/test.esp32-idf.yaml create mode 100644 tests/components/sdm_meter/test.esp32.yaml create mode 100644 tests/components/sdm_meter/test.esp8266.yaml create mode 100644 tests/components/sdm_meter/test.rp2040.yaml create mode 100644 tests/components/sdp3x/test.esp32-c3-idf.yaml create mode 100644 tests/components/sdp3x/test.esp32-c3.yaml create mode 100644 tests/components/sdp3x/test.esp32-idf.yaml create mode 100644 tests/components/sdp3x/test.esp32.yaml create mode 100644 tests/components/sdp3x/test.esp8266.yaml create mode 100644 tests/components/sdp3x/test.rp2040.yaml create mode 100644 tests/components/sds011/test.esp32-c3-idf.yaml create mode 100644 tests/components/sds011/test.esp32-c3.yaml create mode 100644 tests/components/sds011/test.esp32-idf.yaml create mode 100644 tests/components/sds011/test.esp32.yaml create mode 100644 tests/components/sds011/test.esp8266.yaml create mode 100644 tests/components/sds011/test.rp2040.yaml create mode 100644 tests/components/selec_meter/test.esp32-c3-idf.yaml create mode 100644 tests/components/selec_meter/test.esp32-c3.yaml create mode 100644 tests/components/selec_meter/test.esp32-idf.yaml create mode 100644 tests/components/selec_meter/test.esp32.yaml create mode 100644 tests/components/selec_meter/test.esp8266.yaml create mode 100644 tests/components/selec_meter/test.rp2040.yaml create mode 100644 tests/components/sen0321/test.esp32-c3-idf.yaml create mode 100644 tests/components/sen0321/test.esp32-c3.yaml create mode 100644 tests/components/sen0321/test.esp32-idf.yaml create mode 100644 tests/components/sen0321/test.esp32.yaml create mode 100644 tests/components/sen0321/test.esp8266.yaml create mode 100644 tests/components/sen0321/test.rp2040.yaml create mode 100644 tests/components/sen21231/test.esp32-c3-idf.yaml create mode 100644 tests/components/sen21231/test.esp32-c3.yaml create mode 100644 tests/components/sen21231/test.esp32-idf.yaml create mode 100644 tests/components/sen21231/test.esp32.yaml create mode 100644 tests/components/sen21231/test.esp8266.yaml create mode 100644 tests/components/sen21231/test.rp2040.yaml create mode 100644 tests/components/sen5x/test.esp32-c3-idf.yaml create mode 100644 tests/components/sen5x/test.esp32-c3.yaml create mode 100644 tests/components/sen5x/test.esp32-idf.yaml create mode 100644 tests/components/sen5x/test.esp32.yaml create mode 100644 tests/components/sen5x/test.esp8266.yaml create mode 100644 tests/components/sen5x/test.rp2040.yaml create mode 100644 tests/components/senseair/test.esp32-c3-idf.yaml create mode 100644 tests/components/senseair/test.esp32-c3.yaml create mode 100644 tests/components/senseair/test.esp32-idf.yaml create mode 100644 tests/components/senseair/test.esp32.yaml create mode 100644 tests/components/senseair/test.esp8266.yaml create mode 100644 tests/components/senseair/test.rp2040.yaml create mode 100644 tests/components/servo/test.esp32-c3-idf.yaml create mode 100644 tests/components/servo/test.esp32-c3.yaml create mode 100644 tests/components/servo/test.esp32-idf.yaml create mode 100644 tests/components/servo/test.esp32.yaml create mode 100644 tests/components/servo/test.esp8266.yaml create mode 100644 tests/components/servo/test.rp2040.yaml create mode 100644 tests/components/sfa30/test.esp32-c3-idf.yaml create mode 100644 tests/components/sfa30/test.esp32-c3.yaml create mode 100644 tests/components/sfa30/test.esp32-idf.yaml create mode 100644 tests/components/sfa30/test.esp32.yaml create mode 100644 tests/components/sfa30/test.esp8266.yaml create mode 100644 tests/components/sfa30/test.rp2040.yaml create mode 100644 tests/components/sgp30/test.esp32-c3-idf.yaml create mode 100644 tests/components/sgp30/test.esp32-c3.yaml create mode 100644 tests/components/sgp30/test.esp32-idf.yaml create mode 100644 tests/components/sgp30/test.esp32.yaml create mode 100644 tests/components/sgp30/test.esp8266.yaml create mode 100644 tests/components/sgp30/test.rp2040.yaml create mode 100644 tests/components/sgp4x/test.esp32-c3-idf.yaml create mode 100644 tests/components/sgp4x/test.esp32-c3.yaml create mode 100644 tests/components/sgp4x/test.esp32-idf.yaml create mode 100644 tests/components/sgp4x/test.esp32.yaml create mode 100644 tests/components/sgp4x/test.esp8266.yaml create mode 100644 tests/components/sgp4x/test.rp2040.yaml create mode 100644 tests/components/shelly_dimmer/test.esp8266.yaml create mode 100644 tests/components/sht3xd/test.esp32-c3-idf.yaml create mode 100644 tests/components/sht3xd/test.esp32-c3.yaml create mode 100644 tests/components/sht3xd/test.esp32-idf.yaml create mode 100644 tests/components/sht3xd/test.esp32.yaml create mode 100644 tests/components/sht3xd/test.esp8266.yaml create mode 100644 tests/components/sht3xd/test.rp2040.yaml create mode 100644 tests/components/sht4x/test.esp32-c3-idf.yaml create mode 100644 tests/components/sht4x/test.esp32-c3.yaml create mode 100644 tests/components/sht4x/test.esp32-idf.yaml create mode 100644 tests/components/sht4x/test.esp32.yaml create mode 100644 tests/components/sht4x/test.esp8266.yaml create mode 100644 tests/components/sht4x/test.rp2040.yaml create mode 100644 tests/components/shtcx/test.esp32-c3-idf.yaml create mode 100644 tests/components/shtcx/test.esp32-c3.yaml create mode 100644 tests/components/shtcx/test.esp32-idf.yaml create mode 100644 tests/components/shtcx/test.esp32.yaml create mode 100644 tests/components/shtcx/test.esp8266.yaml create mode 100644 tests/components/shtcx/test.rp2040.yaml create mode 100644 tests/components/shutdown/test.esp32-c3-idf.yaml create mode 100644 tests/components/shutdown/test.esp32-c3.yaml create mode 100644 tests/components/shutdown/test.esp32-idf.yaml create mode 100644 tests/components/shutdown/test.esp32.yaml create mode 100644 tests/components/shutdown/test.esp8266.yaml create mode 100644 tests/components/shutdown/test.rp2040.yaml create mode 100644 tests/components/sigma_delta_output/test.esp32-c3-idf.yaml create mode 100644 tests/components/sigma_delta_output/test.esp32-c3.yaml create mode 100644 tests/components/sigma_delta_output/test.esp32-idf.yaml create mode 100644 tests/components/sigma_delta_output/test.esp32.yaml create mode 100644 tests/components/sigma_delta_output/test.esp8266.yaml create mode 100644 tests/components/sigma_delta_output/test.rp2040.yaml create mode 100644 tests/components/sim800l/test.esp32-c3-idf.yaml create mode 100644 tests/components/sim800l/test.esp32-c3.yaml create mode 100644 tests/components/sim800l/test.esp32-idf.yaml create mode 100644 tests/components/sim800l/test.esp32.yaml create mode 100644 tests/components/sim800l/test.esp8266.yaml create mode 100644 tests/components/sim800l/test.rp2040.yaml create mode 100644 tests/components/slow_pwm/test.esp32-c3-idf.yaml create mode 100644 tests/components/slow_pwm/test.esp32-c3.yaml create mode 100644 tests/components/slow_pwm/test.esp32-idf.yaml create mode 100644 tests/components/slow_pwm/test.esp32.yaml create mode 100644 tests/components/slow_pwm/test.esp8266.yaml create mode 100644 tests/components/slow_pwm/test.rp2040.yaml create mode 100644 tests/components/sm16716/test.esp32-c3-idf.yaml create mode 100644 tests/components/sm16716/test.esp32-c3.yaml create mode 100644 tests/components/sm16716/test.esp32-idf.yaml create mode 100644 tests/components/sm16716/test.esp32.yaml create mode 100644 tests/components/sm16716/test.esp8266.yaml create mode 100644 tests/components/sm16716/test.rp2040.yaml create mode 100644 tests/components/sm2135/test.esp32-c3-idf.yaml create mode 100644 tests/components/sm2135/test.esp32-c3.yaml create mode 100644 tests/components/sm2135/test.esp32-idf.yaml create mode 100644 tests/components/sm2135/test.esp32.yaml create mode 100644 tests/components/sm2135/test.esp8266.yaml create mode 100644 tests/components/sm2135/test.rp2040.yaml create mode 100644 tests/components/sm2235/test.esp32-c3-idf.yaml create mode 100644 tests/components/sm2235/test.esp32-c3.yaml create mode 100644 tests/components/sm2235/test.esp32-idf.yaml create mode 100644 tests/components/sm2235/test.esp32.yaml create mode 100644 tests/components/sm2235/test.esp8266.yaml create mode 100644 tests/components/sm2235/test.rp2040.yaml create mode 100644 tests/components/sm2335/test.esp32-c3-idf.yaml create mode 100644 tests/components/sm2335/test.esp32-c3.yaml create mode 100644 tests/components/sm2335/test.esp32-idf.yaml create mode 100644 tests/components/sm2335/test.esp32.yaml create mode 100644 tests/components/sm2335/test.esp8266.yaml create mode 100644 tests/components/sm2335/test.rp2040.yaml create mode 100644 tests/components/sm300d2/test.esp32-c3-idf.yaml create mode 100644 tests/components/sm300d2/test.esp32-c3.yaml create mode 100644 tests/components/sm300d2/test.esp32-idf.yaml create mode 100644 tests/components/sm300d2/test.esp32.yaml create mode 100644 tests/components/sm300d2/test.esp8266.yaml create mode 100644 tests/components/sm300d2/test.rp2040.yaml create mode 100644 tests/components/sml/test.esp32-c3-idf.yaml create mode 100644 tests/components/sml/test.esp32-c3.yaml create mode 100644 tests/components/sml/test.esp32-idf.yaml create mode 100644 tests/components/sml/test.esp32.yaml create mode 100644 tests/components/sml/test.esp8266.yaml create mode 100644 tests/components/sml/test.rp2040.yaml create mode 100644 tests/components/smt100/test.esp32-c3-idf.yaml create mode 100644 tests/components/smt100/test.esp32-c3.yaml create mode 100644 tests/components/smt100/test.esp32-idf.yaml create mode 100644 tests/components/smt100/test.esp32.yaml create mode 100644 tests/components/smt100/test.esp8266.yaml create mode 100644 tests/components/smt100/test.rp2040.yaml diff --git a/tests/components/safe_mode/test.esp32-c3-idf.yaml b/tests/components/safe_mode/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..df0abd9aec --- /dev/null +++ b/tests/components/safe_mode/test.esp32-c3-idf.yaml @@ -0,0 +1,13 @@ +wifi: + ssid: MySSID + password: password1 + +ota: + +button: + - platform: safe_mode + name: Safe Mode Button + +switch: + - platform: safe_mode + name: Safe Mode Switch diff --git a/tests/components/safe_mode/test.esp32-c3.yaml b/tests/components/safe_mode/test.esp32-c3.yaml new file mode 100644 index 0000000000..df0abd9aec --- /dev/null +++ b/tests/components/safe_mode/test.esp32-c3.yaml @@ -0,0 +1,13 @@ +wifi: + ssid: MySSID + password: password1 + +ota: + +button: + - platform: safe_mode + name: Safe Mode Button + +switch: + - platform: safe_mode + name: Safe Mode Switch diff --git a/tests/components/safe_mode/test.esp32-idf.yaml b/tests/components/safe_mode/test.esp32-idf.yaml new file mode 100644 index 0000000000..df0abd9aec --- /dev/null +++ b/tests/components/safe_mode/test.esp32-idf.yaml @@ -0,0 +1,13 @@ +wifi: + ssid: MySSID + password: password1 + +ota: + +button: + - platform: safe_mode + name: Safe Mode Button + +switch: + - platform: safe_mode + name: Safe Mode Switch diff --git a/tests/components/safe_mode/test.esp32.yaml b/tests/components/safe_mode/test.esp32.yaml new file mode 100644 index 0000000000..df0abd9aec --- /dev/null +++ b/tests/components/safe_mode/test.esp32.yaml @@ -0,0 +1,13 @@ +wifi: + ssid: MySSID + password: password1 + +ota: + +button: + - platform: safe_mode + name: Safe Mode Button + +switch: + - platform: safe_mode + name: Safe Mode Switch diff --git a/tests/components/safe_mode/test.esp8266.yaml b/tests/components/safe_mode/test.esp8266.yaml new file mode 100644 index 0000000000..df0abd9aec --- /dev/null +++ b/tests/components/safe_mode/test.esp8266.yaml @@ -0,0 +1,13 @@ +wifi: + ssid: MySSID + password: password1 + +ota: + +button: + - platform: safe_mode + name: Safe Mode Button + +switch: + - platform: safe_mode + name: Safe Mode Switch diff --git a/tests/components/safe_mode/test.rp2040.yaml b/tests/components/safe_mode/test.rp2040.yaml new file mode 100644 index 0000000000..df0abd9aec --- /dev/null +++ b/tests/components/safe_mode/test.rp2040.yaml @@ -0,0 +1,13 @@ +wifi: + ssid: MySSID + password: password1 + +ota: + +button: + - platform: safe_mode + name: Safe Mode Button + +switch: + - platform: safe_mode + name: Safe Mode Switch diff --git a/tests/components/scd30/test.esp32-c3-idf.yaml b/tests/components/scd30/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..80f02a1b87 --- /dev/null +++ b/tests/components/scd30/test.esp32-c3-idf.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_scd30 + scl: 5 + sda: 4 + +sensor: + - platform: scd30 + co2: + name: SCD30 CO2 + temperature: + id: scd30_temperature + name: SCD30 Temperature + humidity: + name: SCD30 Humidity + address: 0x61 + automatic_self_calibration: true + altitude_compensation: 10m + ambient_pressure_compensation: 961mBar + temperature_offset: 4.2C + update_interval: 15s diff --git a/tests/components/scd30/test.esp32-c3.yaml b/tests/components/scd30/test.esp32-c3.yaml new file mode 100644 index 0000000000..80f02a1b87 --- /dev/null +++ b/tests/components/scd30/test.esp32-c3.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_scd30 + scl: 5 + sda: 4 + +sensor: + - platform: scd30 + co2: + name: SCD30 CO2 + temperature: + id: scd30_temperature + name: SCD30 Temperature + humidity: + name: SCD30 Humidity + address: 0x61 + automatic_self_calibration: true + altitude_compensation: 10m + ambient_pressure_compensation: 961mBar + temperature_offset: 4.2C + update_interval: 15s diff --git a/tests/components/scd30/test.esp32-idf.yaml b/tests/components/scd30/test.esp32-idf.yaml new file mode 100644 index 0000000000..b48f8054c8 --- /dev/null +++ b/tests/components/scd30/test.esp32-idf.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_scd30 + scl: 16 + sda: 17 + +sensor: + - platform: scd30 + co2: + name: SCD30 CO2 + temperature: + id: scd30_temperature + name: SCD30 Temperature + humidity: + name: SCD30 Humidity + address: 0x61 + automatic_self_calibration: true + altitude_compensation: 10m + ambient_pressure_compensation: 961mBar + temperature_offset: 4.2C + update_interval: 15s diff --git a/tests/components/scd30/test.esp32.yaml b/tests/components/scd30/test.esp32.yaml new file mode 100644 index 0000000000..b48f8054c8 --- /dev/null +++ b/tests/components/scd30/test.esp32.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_scd30 + scl: 16 + sda: 17 + +sensor: + - platform: scd30 + co2: + name: SCD30 CO2 + temperature: + id: scd30_temperature + name: SCD30 Temperature + humidity: + name: SCD30 Humidity + address: 0x61 + automatic_self_calibration: true + altitude_compensation: 10m + ambient_pressure_compensation: 961mBar + temperature_offset: 4.2C + update_interval: 15s diff --git a/tests/components/scd30/test.esp8266.yaml b/tests/components/scd30/test.esp8266.yaml new file mode 100644 index 0000000000..80f02a1b87 --- /dev/null +++ b/tests/components/scd30/test.esp8266.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_scd30 + scl: 5 + sda: 4 + +sensor: + - platform: scd30 + co2: + name: SCD30 CO2 + temperature: + id: scd30_temperature + name: SCD30 Temperature + humidity: + name: SCD30 Humidity + address: 0x61 + automatic_self_calibration: true + altitude_compensation: 10m + ambient_pressure_compensation: 961mBar + temperature_offset: 4.2C + update_interval: 15s diff --git a/tests/components/scd30/test.rp2040.yaml b/tests/components/scd30/test.rp2040.yaml new file mode 100644 index 0000000000..80f02a1b87 --- /dev/null +++ b/tests/components/scd30/test.rp2040.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_scd30 + scl: 5 + sda: 4 + +sensor: + - platform: scd30 + co2: + name: SCD30 CO2 + temperature: + id: scd30_temperature + name: SCD30 Temperature + humidity: + name: SCD30 Humidity + address: 0x61 + automatic_self_calibration: true + altitude_compensation: 10m + ambient_pressure_compensation: 961mBar + temperature_offset: 4.2C + update_interval: 15s diff --git a/tests/components/scd4x/test.esp32-c3-idf.yaml b/tests/components/scd4x/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..353293be65 --- /dev/null +++ b/tests/components/scd4x/test.esp32-c3-idf.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_scd4x + scl: 5 + sda: 4 + +sensor: + - platform: scd4x + id: scd40 + co2: + name: SCD4X CO2 + temperature: + id: scd4x_temperature + name: SCD4X Temperature + humidity: + name: SCD4X Humidity + automatic_self_calibration: true + altitude_compensation: 10m + ambient_pressure_compensation: 961mBar + temperature_offset: 4.2C + update_interval: 15s diff --git a/tests/components/scd4x/test.esp32-c3.yaml b/tests/components/scd4x/test.esp32-c3.yaml new file mode 100644 index 0000000000..353293be65 --- /dev/null +++ b/tests/components/scd4x/test.esp32-c3.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_scd4x + scl: 5 + sda: 4 + +sensor: + - platform: scd4x + id: scd40 + co2: + name: SCD4X CO2 + temperature: + id: scd4x_temperature + name: SCD4X Temperature + humidity: + name: SCD4X Humidity + automatic_self_calibration: true + altitude_compensation: 10m + ambient_pressure_compensation: 961mBar + temperature_offset: 4.2C + update_interval: 15s diff --git a/tests/components/scd4x/test.esp32-idf.yaml b/tests/components/scd4x/test.esp32-idf.yaml new file mode 100644 index 0000000000..02cec921d2 --- /dev/null +++ b/tests/components/scd4x/test.esp32-idf.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_scd4x + scl: 16 + sda: 17 + +sensor: + - platform: scd4x + id: scd40 + co2: + name: SCD4X CO2 + temperature: + id: scd4x_temperature + name: SCD4X Temperature + humidity: + name: SCD4X Humidity + automatic_self_calibration: true + altitude_compensation: 10m + ambient_pressure_compensation: 961mBar + temperature_offset: 4.2C + update_interval: 15s diff --git a/tests/components/scd4x/test.esp32.yaml b/tests/components/scd4x/test.esp32.yaml new file mode 100644 index 0000000000..02cec921d2 --- /dev/null +++ b/tests/components/scd4x/test.esp32.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_scd4x + scl: 16 + sda: 17 + +sensor: + - platform: scd4x + id: scd40 + co2: + name: SCD4X CO2 + temperature: + id: scd4x_temperature + name: SCD4X Temperature + humidity: + name: SCD4X Humidity + automatic_self_calibration: true + altitude_compensation: 10m + ambient_pressure_compensation: 961mBar + temperature_offset: 4.2C + update_interval: 15s diff --git a/tests/components/scd4x/test.esp8266.yaml b/tests/components/scd4x/test.esp8266.yaml new file mode 100644 index 0000000000..353293be65 --- /dev/null +++ b/tests/components/scd4x/test.esp8266.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_scd4x + scl: 5 + sda: 4 + +sensor: + - platform: scd4x + id: scd40 + co2: + name: SCD4X CO2 + temperature: + id: scd4x_temperature + name: SCD4X Temperature + humidity: + name: SCD4X Humidity + automatic_self_calibration: true + altitude_compensation: 10m + ambient_pressure_compensation: 961mBar + temperature_offset: 4.2C + update_interval: 15s diff --git a/tests/components/scd4x/test.rp2040.yaml b/tests/components/scd4x/test.rp2040.yaml new file mode 100644 index 0000000000..353293be65 --- /dev/null +++ b/tests/components/scd4x/test.rp2040.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_scd4x + scl: 5 + sda: 4 + +sensor: + - platform: scd4x + id: scd40 + co2: + name: SCD4X CO2 + temperature: + id: scd4x_temperature + name: SCD4X Temperature + humidity: + name: SCD4X Humidity + automatic_self_calibration: true + altitude_compensation: 10m + ambient_pressure_compensation: 961mBar + temperature_offset: 4.2C + update_interval: 15s diff --git a/tests/components/script/test.esp32-c3-idf.yaml b/tests/components/script/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..3872c690ff --- /dev/null +++ b/tests/components/script/test.esp32-c3-idf.yaml @@ -0,0 +1,26 @@ +script: + - id: my_script + mode: single + then: + - lambda: 'ESP_LOGD("main", "Hello World!");' + - id: my_script_queued + mode: queued + max_runs: 2 + then: + - lambda: 'ESP_LOGD("main", "Hello World!");' + - id: my_script_parallel + mode: parallel + max_runs: 2 + then: + - lambda: 'ESP_LOGD("main", "Hello World!");' + - id: my_script_restart + mode: restart + then: + - lambda: 'ESP_LOGD("main", "Hello World!");' + - id: my_script_with_params + parameters: + prefix: string + param2: int + param3: bool + then: + - lambda: 'ESP_LOGD("main", (prefix + " Hello World!" + to_string(param2) + " " + to_string(param3)).c_str());' diff --git a/tests/components/script/test.esp32-c3.yaml b/tests/components/script/test.esp32-c3.yaml new file mode 100644 index 0000000000..3872c690ff --- /dev/null +++ b/tests/components/script/test.esp32-c3.yaml @@ -0,0 +1,26 @@ +script: + - id: my_script + mode: single + then: + - lambda: 'ESP_LOGD("main", "Hello World!");' + - id: my_script_queued + mode: queued + max_runs: 2 + then: + - lambda: 'ESP_LOGD("main", "Hello World!");' + - id: my_script_parallel + mode: parallel + max_runs: 2 + then: + - lambda: 'ESP_LOGD("main", "Hello World!");' + - id: my_script_restart + mode: restart + then: + - lambda: 'ESP_LOGD("main", "Hello World!");' + - id: my_script_with_params + parameters: + prefix: string + param2: int + param3: bool + then: + - lambda: 'ESP_LOGD("main", (prefix + " Hello World!" + to_string(param2) + " " + to_string(param3)).c_str());' diff --git a/tests/components/script/test.esp32-idf.yaml b/tests/components/script/test.esp32-idf.yaml new file mode 100644 index 0000000000..3872c690ff --- /dev/null +++ b/tests/components/script/test.esp32-idf.yaml @@ -0,0 +1,26 @@ +script: + - id: my_script + mode: single + then: + - lambda: 'ESP_LOGD("main", "Hello World!");' + - id: my_script_queued + mode: queued + max_runs: 2 + then: + - lambda: 'ESP_LOGD("main", "Hello World!");' + - id: my_script_parallel + mode: parallel + max_runs: 2 + then: + - lambda: 'ESP_LOGD("main", "Hello World!");' + - id: my_script_restart + mode: restart + then: + - lambda: 'ESP_LOGD("main", "Hello World!");' + - id: my_script_with_params + parameters: + prefix: string + param2: int + param3: bool + then: + - lambda: 'ESP_LOGD("main", (prefix + " Hello World!" + to_string(param2) + " " + to_string(param3)).c_str());' diff --git a/tests/components/script/test.esp32.yaml b/tests/components/script/test.esp32.yaml new file mode 100644 index 0000000000..3872c690ff --- /dev/null +++ b/tests/components/script/test.esp32.yaml @@ -0,0 +1,26 @@ +script: + - id: my_script + mode: single + then: + - lambda: 'ESP_LOGD("main", "Hello World!");' + - id: my_script_queued + mode: queued + max_runs: 2 + then: + - lambda: 'ESP_LOGD("main", "Hello World!");' + - id: my_script_parallel + mode: parallel + max_runs: 2 + then: + - lambda: 'ESP_LOGD("main", "Hello World!");' + - id: my_script_restart + mode: restart + then: + - lambda: 'ESP_LOGD("main", "Hello World!");' + - id: my_script_with_params + parameters: + prefix: string + param2: int + param3: bool + then: + - lambda: 'ESP_LOGD("main", (prefix + " Hello World!" + to_string(param2) + " " + to_string(param3)).c_str());' diff --git a/tests/components/script/test.esp8266.yaml b/tests/components/script/test.esp8266.yaml new file mode 100644 index 0000000000..ce0e40e7ee --- /dev/null +++ b/tests/components/script/test.esp8266.yaml @@ -0,0 +1,26 @@ +script: + - id: my_script + mode: single + then: + - lambda: 'ESP_LOGD("main", "Hello World!");' + - id: my_script_queued + mode: queued + max_runs: 2 + then: + - lambda: 'ESP_LOGD("main", "Hello World!");' + - id: my_script_parallel + mode: parallel + max_runs: 2 + then: + - lambda: 'ESP_LOGD("main", "Hello World!");' + - id: my_script_restart + mode: restart + then: + - lambda: 'ESP_LOGD("main", "Hello World!");' + - id: my_script_with_params + parameters: + prefix: string + param2: int + param3: bool + then: + - lambda: 'ESP_LOGD(prefix.c_str(), "Hello World! %i %i", param2, param3);' diff --git a/tests/components/script/test.rp2040.yaml b/tests/components/script/test.rp2040.yaml new file mode 100644 index 0000000000..3872c690ff --- /dev/null +++ b/tests/components/script/test.rp2040.yaml @@ -0,0 +1,26 @@ +script: + - id: my_script + mode: single + then: + - lambda: 'ESP_LOGD("main", "Hello World!");' + - id: my_script_queued + mode: queued + max_runs: 2 + then: + - lambda: 'ESP_LOGD("main", "Hello World!");' + - id: my_script_parallel + mode: parallel + max_runs: 2 + then: + - lambda: 'ESP_LOGD("main", "Hello World!");' + - id: my_script_restart + mode: restart + then: + - lambda: 'ESP_LOGD("main", "Hello World!");' + - id: my_script_with_params + parameters: + prefix: string + param2: int + param3: bool + then: + - lambda: 'ESP_LOGD("main", (prefix + " Hello World!" + to_string(param2) + " " + to_string(param3)).c_str());' diff --git a/tests/components/sdm_meter/test.esp32-c3-idf.yaml b/tests/components/sdm_meter/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..0c2144f983 --- /dev/null +++ b/tests/components/sdm_meter/test.esp32-c3-idf.yaml @@ -0,0 +1,23 @@ +uart: + - id: uart_sdm_meter + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sensor: + - platform: sdm_meter + phase_a: + current: + name: Phase A Current + voltage: + name: Phase A Voltage + active_power: + name: Phase A Power + power_factor: + name: Phase A Power Factor + apparent_power: + name: Phase A Apparent Power + reactive_power: + name: Phase A Reactive Power + phase_angle: + name: Phase A Phase Angle diff --git a/tests/components/sdm_meter/test.esp32-c3.yaml b/tests/components/sdm_meter/test.esp32-c3.yaml new file mode 100644 index 0000000000..0c2144f983 --- /dev/null +++ b/tests/components/sdm_meter/test.esp32-c3.yaml @@ -0,0 +1,23 @@ +uart: + - id: uart_sdm_meter + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sensor: + - platform: sdm_meter + phase_a: + current: + name: Phase A Current + voltage: + name: Phase A Voltage + active_power: + name: Phase A Power + power_factor: + name: Phase A Power Factor + apparent_power: + name: Phase A Apparent Power + reactive_power: + name: Phase A Reactive Power + phase_angle: + name: Phase A Phase Angle diff --git a/tests/components/sdm_meter/test.esp32-idf.yaml b/tests/components/sdm_meter/test.esp32-idf.yaml new file mode 100644 index 0000000000..eb3958db19 --- /dev/null +++ b/tests/components/sdm_meter/test.esp32-idf.yaml @@ -0,0 +1,23 @@ +uart: + - id: uart_sdm_meter + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +sensor: + - platform: sdm_meter + phase_a: + current: + name: Phase A Current + voltage: + name: Phase A Voltage + active_power: + name: Phase A Power + power_factor: + name: Phase A Power Factor + apparent_power: + name: Phase A Apparent Power + reactive_power: + name: Phase A Reactive Power + phase_angle: + name: Phase A Phase Angle diff --git a/tests/components/sdm_meter/test.esp32.yaml b/tests/components/sdm_meter/test.esp32.yaml new file mode 100644 index 0000000000..eb3958db19 --- /dev/null +++ b/tests/components/sdm_meter/test.esp32.yaml @@ -0,0 +1,23 @@ +uart: + - id: uart_sdm_meter + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +sensor: + - platform: sdm_meter + phase_a: + current: + name: Phase A Current + voltage: + name: Phase A Voltage + active_power: + name: Phase A Power + power_factor: + name: Phase A Power Factor + apparent_power: + name: Phase A Apparent Power + reactive_power: + name: Phase A Reactive Power + phase_angle: + name: Phase A Phase Angle diff --git a/tests/components/sdm_meter/test.esp8266.yaml b/tests/components/sdm_meter/test.esp8266.yaml new file mode 100644 index 0000000000..0c2144f983 --- /dev/null +++ b/tests/components/sdm_meter/test.esp8266.yaml @@ -0,0 +1,23 @@ +uart: + - id: uart_sdm_meter + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sensor: + - platform: sdm_meter + phase_a: + current: + name: Phase A Current + voltage: + name: Phase A Voltage + active_power: + name: Phase A Power + power_factor: + name: Phase A Power Factor + apparent_power: + name: Phase A Apparent Power + reactive_power: + name: Phase A Reactive Power + phase_angle: + name: Phase A Phase Angle diff --git a/tests/components/sdm_meter/test.rp2040.yaml b/tests/components/sdm_meter/test.rp2040.yaml new file mode 100644 index 0000000000..0c2144f983 --- /dev/null +++ b/tests/components/sdm_meter/test.rp2040.yaml @@ -0,0 +1,23 @@ +uart: + - id: uart_sdm_meter + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sensor: + - platform: sdm_meter + phase_a: + current: + name: Phase A Current + voltage: + name: Phase A Voltage + active_power: + name: Phase A Power + power_factor: + name: Phase A Power Factor + apparent_power: + name: Phase A Apparent Power + reactive_power: + name: Phase A Reactive Power + phase_angle: + name: Phase A Phase Angle diff --git a/tests/components/sdp3x/test.esp32-c3-idf.yaml b/tests/components/sdp3x/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..42b90f1b81 --- /dev/null +++ b/tests/components/sdp3x/test.esp32-c3-idf.yaml @@ -0,0 +1,11 @@ +i2c: + - id: i2c_sdp3x + scl: 5 + sda: 4 + +sensor: + - platform: sdp3x + id: filter_pressure + name: HVAC Filter Pressure drop + accuracy_decimals: 3 + update_interval: 5s diff --git a/tests/components/sdp3x/test.esp32-c3.yaml b/tests/components/sdp3x/test.esp32-c3.yaml new file mode 100644 index 0000000000..42b90f1b81 --- /dev/null +++ b/tests/components/sdp3x/test.esp32-c3.yaml @@ -0,0 +1,11 @@ +i2c: + - id: i2c_sdp3x + scl: 5 + sda: 4 + +sensor: + - platform: sdp3x + id: filter_pressure + name: HVAC Filter Pressure drop + accuracy_decimals: 3 + update_interval: 5s diff --git a/tests/components/sdp3x/test.esp32-idf.yaml b/tests/components/sdp3x/test.esp32-idf.yaml new file mode 100644 index 0000000000..00666082eb --- /dev/null +++ b/tests/components/sdp3x/test.esp32-idf.yaml @@ -0,0 +1,11 @@ +i2c: + - id: i2c_sdp3x + scl: 16 + sda: 17 + +sensor: + - platform: sdp3x + id: filter_pressure + name: HVAC Filter Pressure drop + accuracy_decimals: 3 + update_interval: 5s diff --git a/tests/components/sdp3x/test.esp32.yaml b/tests/components/sdp3x/test.esp32.yaml new file mode 100644 index 0000000000..00666082eb --- /dev/null +++ b/tests/components/sdp3x/test.esp32.yaml @@ -0,0 +1,11 @@ +i2c: + - id: i2c_sdp3x + scl: 16 + sda: 17 + +sensor: + - platform: sdp3x + id: filter_pressure + name: HVAC Filter Pressure drop + accuracy_decimals: 3 + update_interval: 5s diff --git a/tests/components/sdp3x/test.esp8266.yaml b/tests/components/sdp3x/test.esp8266.yaml new file mode 100644 index 0000000000..42b90f1b81 --- /dev/null +++ b/tests/components/sdp3x/test.esp8266.yaml @@ -0,0 +1,11 @@ +i2c: + - id: i2c_sdp3x + scl: 5 + sda: 4 + +sensor: + - platform: sdp3x + id: filter_pressure + name: HVAC Filter Pressure drop + accuracy_decimals: 3 + update_interval: 5s diff --git a/tests/components/sdp3x/test.rp2040.yaml b/tests/components/sdp3x/test.rp2040.yaml new file mode 100644 index 0000000000..42b90f1b81 --- /dev/null +++ b/tests/components/sdp3x/test.rp2040.yaml @@ -0,0 +1,11 @@ +i2c: + - id: i2c_sdp3x + scl: 5 + sda: 4 + +sensor: + - platform: sdp3x + id: filter_pressure + name: HVAC Filter Pressure drop + accuracy_decimals: 3 + update_interval: 5s diff --git a/tests/components/sds011/test.esp32-c3-idf.yaml b/tests/components/sds011/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..e680a62dfe --- /dev/null +++ b/tests/components/sds011/test.esp32-c3-idf.yaml @@ -0,0 +1,14 @@ +uart: + - id: uart_sdm_sds011 + tx_pin: 4 + rx_pin: 5 + baud_rate: 115200 + +sensor: + - platform: sds011 + pm_2_5: + name: SDS011 PM2.5 + pm_10_0: + name: SDS011 PM10.0 + rx_only: false + update_interval: 5min diff --git a/tests/components/sds011/test.esp32-c3.yaml b/tests/components/sds011/test.esp32-c3.yaml new file mode 100644 index 0000000000..e680a62dfe --- /dev/null +++ b/tests/components/sds011/test.esp32-c3.yaml @@ -0,0 +1,14 @@ +uart: + - id: uart_sdm_sds011 + tx_pin: 4 + rx_pin: 5 + baud_rate: 115200 + +sensor: + - platform: sds011 + pm_2_5: + name: SDS011 PM2.5 + pm_10_0: + name: SDS011 PM10.0 + rx_only: false + update_interval: 5min diff --git a/tests/components/sds011/test.esp32-idf.yaml b/tests/components/sds011/test.esp32-idf.yaml new file mode 100644 index 0000000000..275390f14c --- /dev/null +++ b/tests/components/sds011/test.esp32-idf.yaml @@ -0,0 +1,14 @@ +uart: + - id: uart_sdm_sds011 + tx_pin: 17 + rx_pin: 16 + baud_rate: 115200 + +sensor: + - platform: sds011 + pm_2_5: + name: SDS011 PM2.5 + pm_10_0: + name: SDS011 PM10.0 + rx_only: false + update_interval: 5min diff --git a/tests/components/sds011/test.esp32.yaml b/tests/components/sds011/test.esp32.yaml new file mode 100644 index 0000000000..275390f14c --- /dev/null +++ b/tests/components/sds011/test.esp32.yaml @@ -0,0 +1,14 @@ +uart: + - id: uart_sdm_sds011 + tx_pin: 17 + rx_pin: 16 + baud_rate: 115200 + +sensor: + - platform: sds011 + pm_2_5: + name: SDS011 PM2.5 + pm_10_0: + name: SDS011 PM10.0 + rx_only: false + update_interval: 5min diff --git a/tests/components/sds011/test.esp8266.yaml b/tests/components/sds011/test.esp8266.yaml new file mode 100644 index 0000000000..e680a62dfe --- /dev/null +++ b/tests/components/sds011/test.esp8266.yaml @@ -0,0 +1,14 @@ +uart: + - id: uart_sdm_sds011 + tx_pin: 4 + rx_pin: 5 + baud_rate: 115200 + +sensor: + - platform: sds011 + pm_2_5: + name: SDS011 PM2.5 + pm_10_0: + name: SDS011 PM10.0 + rx_only: false + update_interval: 5min diff --git a/tests/components/sds011/test.rp2040.yaml b/tests/components/sds011/test.rp2040.yaml new file mode 100644 index 0000000000..e680a62dfe --- /dev/null +++ b/tests/components/sds011/test.rp2040.yaml @@ -0,0 +1,14 @@ +uart: + - id: uart_sdm_sds011 + tx_pin: 4 + rx_pin: 5 + baud_rate: 115200 + +sensor: + - platform: sds011 + pm_2_5: + name: SDS011 PM2.5 + pm_10_0: + name: SDS011 PM10.0 + rx_only: false + update_interval: 5min diff --git a/tests/components/selec_meter/test.esp32-c3-idf.yaml b/tests/components/selec_meter/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..5f6e69f96f --- /dev/null +++ b/tests/components/selec_meter/test.esp32-c3-idf.yaml @@ -0,0 +1,45 @@ +uart: + - id: uart_selec_meter + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sensor: + - platform: selec_meter + total_active_energy: + name: SelecEM2M Total Active Energy + import_active_energy: + name: SelecEM2M Import Active Energy + export_active_energy: + name: SelecEM2M Export Active Energy + total_reactive_energy: + name: SelecEM2M Total Reactive Energy + import_reactive_energy: + name: SelecEM2M Import Reactive Energy + export_reactive_energy: + name: SelecEM2M Export Reactive Energy + apparent_energy: + name: SelecEM2M Apparent Energy + active_power: + name: SelecEM2M Active Power + reactive_power: + name: SelecEM2M Reactive Power + apparent_power: + name: SelecEM2M Apparent Power + voltage: + name: SelecEM2M Voltage + current: + name: SelecEM2M Current + power_factor: + name: SelecEM2M Power Factor + frequency: + name: SelecEM2M Frequency + maximum_demand_active_power: + name: SelecEM2M Maximum Demand Active Power + disabled_by_default: true + maximum_demand_reactive_power: + name: SelecEM2M Maximum Demand Reactive Power + disabled_by_default: true + maximum_demand_apparent_power: + name: SelecEM2M Maximum Demand Apparent Power + disabled_by_default: true diff --git a/tests/components/selec_meter/test.esp32-c3.yaml b/tests/components/selec_meter/test.esp32-c3.yaml new file mode 100644 index 0000000000..5f6e69f96f --- /dev/null +++ b/tests/components/selec_meter/test.esp32-c3.yaml @@ -0,0 +1,45 @@ +uart: + - id: uart_selec_meter + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sensor: + - platform: selec_meter + total_active_energy: + name: SelecEM2M Total Active Energy + import_active_energy: + name: SelecEM2M Import Active Energy + export_active_energy: + name: SelecEM2M Export Active Energy + total_reactive_energy: + name: SelecEM2M Total Reactive Energy + import_reactive_energy: + name: SelecEM2M Import Reactive Energy + export_reactive_energy: + name: SelecEM2M Export Reactive Energy + apparent_energy: + name: SelecEM2M Apparent Energy + active_power: + name: SelecEM2M Active Power + reactive_power: + name: SelecEM2M Reactive Power + apparent_power: + name: SelecEM2M Apparent Power + voltage: + name: SelecEM2M Voltage + current: + name: SelecEM2M Current + power_factor: + name: SelecEM2M Power Factor + frequency: + name: SelecEM2M Frequency + maximum_demand_active_power: + name: SelecEM2M Maximum Demand Active Power + disabled_by_default: true + maximum_demand_reactive_power: + name: SelecEM2M Maximum Demand Reactive Power + disabled_by_default: true + maximum_demand_apparent_power: + name: SelecEM2M Maximum Demand Apparent Power + disabled_by_default: true diff --git a/tests/components/selec_meter/test.esp32-idf.yaml b/tests/components/selec_meter/test.esp32-idf.yaml new file mode 100644 index 0000000000..648adc1757 --- /dev/null +++ b/tests/components/selec_meter/test.esp32-idf.yaml @@ -0,0 +1,45 @@ +uart: + - id: uart_selec_meter + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +sensor: + - platform: selec_meter + total_active_energy: + name: SelecEM2M Total Active Energy + import_active_energy: + name: SelecEM2M Import Active Energy + export_active_energy: + name: SelecEM2M Export Active Energy + total_reactive_energy: + name: SelecEM2M Total Reactive Energy + import_reactive_energy: + name: SelecEM2M Import Reactive Energy + export_reactive_energy: + name: SelecEM2M Export Reactive Energy + apparent_energy: + name: SelecEM2M Apparent Energy + active_power: + name: SelecEM2M Active Power + reactive_power: + name: SelecEM2M Reactive Power + apparent_power: + name: SelecEM2M Apparent Power + voltage: + name: SelecEM2M Voltage + current: + name: SelecEM2M Current + power_factor: + name: SelecEM2M Power Factor + frequency: + name: SelecEM2M Frequency + maximum_demand_active_power: + name: SelecEM2M Maximum Demand Active Power + disabled_by_default: true + maximum_demand_reactive_power: + name: SelecEM2M Maximum Demand Reactive Power + disabled_by_default: true + maximum_demand_apparent_power: + name: SelecEM2M Maximum Demand Apparent Power + disabled_by_default: true diff --git a/tests/components/selec_meter/test.esp32.yaml b/tests/components/selec_meter/test.esp32.yaml new file mode 100644 index 0000000000..648adc1757 --- /dev/null +++ b/tests/components/selec_meter/test.esp32.yaml @@ -0,0 +1,45 @@ +uart: + - id: uart_selec_meter + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +sensor: + - platform: selec_meter + total_active_energy: + name: SelecEM2M Total Active Energy + import_active_energy: + name: SelecEM2M Import Active Energy + export_active_energy: + name: SelecEM2M Export Active Energy + total_reactive_energy: + name: SelecEM2M Total Reactive Energy + import_reactive_energy: + name: SelecEM2M Import Reactive Energy + export_reactive_energy: + name: SelecEM2M Export Reactive Energy + apparent_energy: + name: SelecEM2M Apparent Energy + active_power: + name: SelecEM2M Active Power + reactive_power: + name: SelecEM2M Reactive Power + apparent_power: + name: SelecEM2M Apparent Power + voltage: + name: SelecEM2M Voltage + current: + name: SelecEM2M Current + power_factor: + name: SelecEM2M Power Factor + frequency: + name: SelecEM2M Frequency + maximum_demand_active_power: + name: SelecEM2M Maximum Demand Active Power + disabled_by_default: true + maximum_demand_reactive_power: + name: SelecEM2M Maximum Demand Reactive Power + disabled_by_default: true + maximum_demand_apparent_power: + name: SelecEM2M Maximum Demand Apparent Power + disabled_by_default: true diff --git a/tests/components/selec_meter/test.esp8266.yaml b/tests/components/selec_meter/test.esp8266.yaml new file mode 100644 index 0000000000..5f6e69f96f --- /dev/null +++ b/tests/components/selec_meter/test.esp8266.yaml @@ -0,0 +1,45 @@ +uart: + - id: uart_selec_meter + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sensor: + - platform: selec_meter + total_active_energy: + name: SelecEM2M Total Active Energy + import_active_energy: + name: SelecEM2M Import Active Energy + export_active_energy: + name: SelecEM2M Export Active Energy + total_reactive_energy: + name: SelecEM2M Total Reactive Energy + import_reactive_energy: + name: SelecEM2M Import Reactive Energy + export_reactive_energy: + name: SelecEM2M Export Reactive Energy + apparent_energy: + name: SelecEM2M Apparent Energy + active_power: + name: SelecEM2M Active Power + reactive_power: + name: SelecEM2M Reactive Power + apparent_power: + name: SelecEM2M Apparent Power + voltage: + name: SelecEM2M Voltage + current: + name: SelecEM2M Current + power_factor: + name: SelecEM2M Power Factor + frequency: + name: SelecEM2M Frequency + maximum_demand_active_power: + name: SelecEM2M Maximum Demand Active Power + disabled_by_default: true + maximum_demand_reactive_power: + name: SelecEM2M Maximum Demand Reactive Power + disabled_by_default: true + maximum_demand_apparent_power: + name: SelecEM2M Maximum Demand Apparent Power + disabled_by_default: true diff --git a/tests/components/selec_meter/test.rp2040.yaml b/tests/components/selec_meter/test.rp2040.yaml new file mode 100644 index 0000000000..5f6e69f96f --- /dev/null +++ b/tests/components/selec_meter/test.rp2040.yaml @@ -0,0 +1,45 @@ +uart: + - id: uart_selec_meter + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sensor: + - platform: selec_meter + total_active_energy: + name: SelecEM2M Total Active Energy + import_active_energy: + name: SelecEM2M Import Active Energy + export_active_energy: + name: SelecEM2M Export Active Energy + total_reactive_energy: + name: SelecEM2M Total Reactive Energy + import_reactive_energy: + name: SelecEM2M Import Reactive Energy + export_reactive_energy: + name: SelecEM2M Export Reactive Energy + apparent_energy: + name: SelecEM2M Apparent Energy + active_power: + name: SelecEM2M Active Power + reactive_power: + name: SelecEM2M Reactive Power + apparent_power: + name: SelecEM2M Apparent Power + voltage: + name: SelecEM2M Voltage + current: + name: SelecEM2M Current + power_factor: + name: SelecEM2M Power Factor + frequency: + name: SelecEM2M Frequency + maximum_demand_active_power: + name: SelecEM2M Maximum Demand Active Power + disabled_by_default: true + maximum_demand_reactive_power: + name: SelecEM2M Maximum Demand Reactive Power + disabled_by_default: true + maximum_demand_apparent_power: + name: SelecEM2M Maximum Demand Apparent Power + disabled_by_default: true diff --git a/tests/components/sen0321/test.esp32-c3-idf.yaml b/tests/components/sen0321/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..7fa461a7fa --- /dev/null +++ b/tests/components/sen0321/test.esp32-c3-idf.yaml @@ -0,0 +1,10 @@ +i2c: + - id: i2c_sen0321 + scl: 5 + sda: 4 + +sensor: + - platform: sen0321 + name: Workshop Ozone Sensor + id: sen0321_ozone + update_interval: 10s diff --git a/tests/components/sen0321/test.esp32-c3.yaml b/tests/components/sen0321/test.esp32-c3.yaml new file mode 100644 index 0000000000..7fa461a7fa --- /dev/null +++ b/tests/components/sen0321/test.esp32-c3.yaml @@ -0,0 +1,10 @@ +i2c: + - id: i2c_sen0321 + scl: 5 + sda: 4 + +sensor: + - platform: sen0321 + name: Workshop Ozone Sensor + id: sen0321_ozone + update_interval: 10s diff --git a/tests/components/sen0321/test.esp32-idf.yaml b/tests/components/sen0321/test.esp32-idf.yaml new file mode 100644 index 0000000000..44f76bf5e6 --- /dev/null +++ b/tests/components/sen0321/test.esp32-idf.yaml @@ -0,0 +1,10 @@ +i2c: + - id: i2c_sen0321 + scl: 16 + sda: 17 + +sensor: + - platform: sen0321 + name: Workshop Ozone Sensor + id: sen0321_ozone + update_interval: 10s diff --git a/tests/components/sen0321/test.esp32.yaml b/tests/components/sen0321/test.esp32.yaml new file mode 100644 index 0000000000..44f76bf5e6 --- /dev/null +++ b/tests/components/sen0321/test.esp32.yaml @@ -0,0 +1,10 @@ +i2c: + - id: i2c_sen0321 + scl: 16 + sda: 17 + +sensor: + - platform: sen0321 + name: Workshop Ozone Sensor + id: sen0321_ozone + update_interval: 10s diff --git a/tests/components/sen0321/test.esp8266.yaml b/tests/components/sen0321/test.esp8266.yaml new file mode 100644 index 0000000000..7fa461a7fa --- /dev/null +++ b/tests/components/sen0321/test.esp8266.yaml @@ -0,0 +1,10 @@ +i2c: + - id: i2c_sen0321 + scl: 5 + sda: 4 + +sensor: + - platform: sen0321 + name: Workshop Ozone Sensor + id: sen0321_ozone + update_interval: 10s diff --git a/tests/components/sen0321/test.rp2040.yaml b/tests/components/sen0321/test.rp2040.yaml new file mode 100644 index 0000000000..7fa461a7fa --- /dev/null +++ b/tests/components/sen0321/test.rp2040.yaml @@ -0,0 +1,10 @@ +i2c: + - id: i2c_sen0321 + scl: 5 + sda: 4 + +sensor: + - platform: sen0321 + name: Workshop Ozone Sensor + id: sen0321_ozone + update_interval: 10s diff --git a/tests/components/sen21231/test.esp32-c3-idf.yaml b/tests/components/sen21231/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..efd7843f56 --- /dev/null +++ b/tests/components/sen21231/test.esp32-c3-idf.yaml @@ -0,0 +1,9 @@ +i2c: + - id: i2c_sen21231 + scl: 5 + sda: 4 + +sensor: + - platform: sen21231 + id: sen21231_sensor1 + name: Person Sensor diff --git a/tests/components/sen21231/test.esp32-c3.yaml b/tests/components/sen21231/test.esp32-c3.yaml new file mode 100644 index 0000000000..efd7843f56 --- /dev/null +++ b/tests/components/sen21231/test.esp32-c3.yaml @@ -0,0 +1,9 @@ +i2c: + - id: i2c_sen21231 + scl: 5 + sda: 4 + +sensor: + - platform: sen21231 + id: sen21231_sensor1 + name: Person Sensor diff --git a/tests/components/sen21231/test.esp32-idf.yaml b/tests/components/sen21231/test.esp32-idf.yaml new file mode 100644 index 0000000000..3173683f17 --- /dev/null +++ b/tests/components/sen21231/test.esp32-idf.yaml @@ -0,0 +1,9 @@ +i2c: + - id: i2c_sen21231 + scl: 16 + sda: 17 + +sensor: + - platform: sen21231 + id: sen21231_sensor1 + name: Person Sensor diff --git a/tests/components/sen21231/test.esp32.yaml b/tests/components/sen21231/test.esp32.yaml new file mode 100644 index 0000000000..3173683f17 --- /dev/null +++ b/tests/components/sen21231/test.esp32.yaml @@ -0,0 +1,9 @@ +i2c: + - id: i2c_sen21231 + scl: 16 + sda: 17 + +sensor: + - platform: sen21231 + id: sen21231_sensor1 + name: Person Sensor diff --git a/tests/components/sen21231/test.esp8266.yaml b/tests/components/sen21231/test.esp8266.yaml new file mode 100644 index 0000000000..efd7843f56 --- /dev/null +++ b/tests/components/sen21231/test.esp8266.yaml @@ -0,0 +1,9 @@ +i2c: + - id: i2c_sen21231 + scl: 5 + sda: 4 + +sensor: + - platform: sen21231 + id: sen21231_sensor1 + name: Person Sensor diff --git a/tests/components/sen21231/test.rp2040.yaml b/tests/components/sen21231/test.rp2040.yaml new file mode 100644 index 0000000000..efd7843f56 --- /dev/null +++ b/tests/components/sen21231/test.rp2040.yaml @@ -0,0 +1,9 @@ +i2c: + - id: i2c_sen21231 + scl: 5 + sda: 4 + +sensor: + - platform: sen21231 + id: sen21231_sensor1 + name: Person Sensor diff --git a/tests/components/sen5x/test.esp32-c3-idf.yaml b/tests/components/sen5x/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..3352a59b17 --- /dev/null +++ b/tests/components/sen5x/test.esp32-c3-idf.yaml @@ -0,0 +1,49 @@ +i2c: + - id: i2c_sen5x + scl: 5 + sda: 4 + +sensor: + - platform: sen5x + id: sen54 + 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 + algorithm_tuning: + index_offset: 100 + learning_time_offset_hours: 12 + learning_time_gain_hours: 12 + gating_max_duration_minutes: 180 + std_initial: 50 + gain_factor: 230 + temperature_compensation: + offset: 0 + normalized_offset_slope: 0 + time_constant: 0 + auto_cleaning_interval: 604800s + acceleration_mode: low + store_baseline: true + address: 0x69 diff --git a/tests/components/sen5x/test.esp32-c3.yaml b/tests/components/sen5x/test.esp32-c3.yaml new file mode 100644 index 0000000000..3352a59b17 --- /dev/null +++ b/tests/components/sen5x/test.esp32-c3.yaml @@ -0,0 +1,49 @@ +i2c: + - id: i2c_sen5x + scl: 5 + sda: 4 + +sensor: + - platform: sen5x + id: sen54 + 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 + algorithm_tuning: + index_offset: 100 + learning_time_offset_hours: 12 + learning_time_gain_hours: 12 + gating_max_duration_minutes: 180 + std_initial: 50 + gain_factor: 230 + temperature_compensation: + offset: 0 + normalized_offset_slope: 0 + time_constant: 0 + auto_cleaning_interval: 604800s + acceleration_mode: low + store_baseline: true + address: 0x69 diff --git a/tests/components/sen5x/test.esp32-idf.yaml b/tests/components/sen5x/test.esp32-idf.yaml new file mode 100644 index 0000000000..b8f89c435f --- /dev/null +++ b/tests/components/sen5x/test.esp32-idf.yaml @@ -0,0 +1,49 @@ +i2c: + - id: i2c_sen5x + scl: 16 + sda: 17 + +sensor: + - platform: sen5x + id: sen54 + 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 + algorithm_tuning: + index_offset: 100 + learning_time_offset_hours: 12 + learning_time_gain_hours: 12 + gating_max_duration_minutes: 180 + std_initial: 50 + gain_factor: 230 + temperature_compensation: + offset: 0 + normalized_offset_slope: 0 + time_constant: 0 + auto_cleaning_interval: 604800s + acceleration_mode: low + store_baseline: true + address: 0x69 diff --git a/tests/components/sen5x/test.esp32.yaml b/tests/components/sen5x/test.esp32.yaml new file mode 100644 index 0000000000..b8f89c435f --- /dev/null +++ b/tests/components/sen5x/test.esp32.yaml @@ -0,0 +1,49 @@ +i2c: + - id: i2c_sen5x + scl: 16 + sda: 17 + +sensor: + - platform: sen5x + id: sen54 + 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 + algorithm_tuning: + index_offset: 100 + learning_time_offset_hours: 12 + learning_time_gain_hours: 12 + gating_max_duration_minutes: 180 + std_initial: 50 + gain_factor: 230 + temperature_compensation: + offset: 0 + normalized_offset_slope: 0 + time_constant: 0 + auto_cleaning_interval: 604800s + acceleration_mode: low + store_baseline: true + address: 0x69 diff --git a/tests/components/sen5x/test.esp8266.yaml b/tests/components/sen5x/test.esp8266.yaml new file mode 100644 index 0000000000..3352a59b17 --- /dev/null +++ b/tests/components/sen5x/test.esp8266.yaml @@ -0,0 +1,49 @@ +i2c: + - id: i2c_sen5x + scl: 5 + sda: 4 + +sensor: + - platform: sen5x + id: sen54 + 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 + algorithm_tuning: + index_offset: 100 + learning_time_offset_hours: 12 + learning_time_gain_hours: 12 + gating_max_duration_minutes: 180 + std_initial: 50 + gain_factor: 230 + temperature_compensation: + offset: 0 + normalized_offset_slope: 0 + time_constant: 0 + auto_cleaning_interval: 604800s + acceleration_mode: low + store_baseline: true + address: 0x69 diff --git a/tests/components/sen5x/test.rp2040.yaml b/tests/components/sen5x/test.rp2040.yaml new file mode 100644 index 0000000000..3352a59b17 --- /dev/null +++ b/tests/components/sen5x/test.rp2040.yaml @@ -0,0 +1,49 @@ +i2c: + - id: i2c_sen5x + scl: 5 + sda: 4 + +sensor: + - platform: sen5x + id: sen54 + 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 + algorithm_tuning: + index_offset: 100 + learning_time_offset_hours: 12 + learning_time_gain_hours: 12 + gating_max_duration_minutes: 180 + std_initial: 50 + gain_factor: 230 + temperature_compensation: + offset: 0 + normalized_offset_slope: 0 + time_constant: 0 + auto_cleaning_interval: 604800s + acceleration_mode: low + store_baseline: true + address: 0x69 diff --git a/tests/components/senseair/test.esp32-c3-idf.yaml b/tests/components/senseair/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..41a441f496 --- /dev/null +++ b/tests/components/senseair/test.esp32-c3-idf.yaml @@ -0,0 +1,19 @@ +uart: + - id: uart_senseair + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sensor: + - platform: senseair + id: senseair0 + co2: + name: SenseAir CO2 Value + on_value: + then: + - senseair.background_calibration: senseair0 + - senseair.background_calibration_result: senseair0 + - senseair.abc_get_period: senseair0 + - senseair.abc_enable: senseair0 + - senseair.abc_disable: senseair0 + update_interval: 15s diff --git a/tests/components/senseair/test.esp32-c3.yaml b/tests/components/senseair/test.esp32-c3.yaml new file mode 100644 index 0000000000..41a441f496 --- /dev/null +++ b/tests/components/senseair/test.esp32-c3.yaml @@ -0,0 +1,19 @@ +uart: + - id: uart_senseair + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sensor: + - platform: senseair + id: senseair0 + co2: + name: SenseAir CO2 Value + on_value: + then: + - senseair.background_calibration: senseair0 + - senseair.background_calibration_result: senseair0 + - senseair.abc_get_period: senseair0 + - senseair.abc_enable: senseair0 + - senseair.abc_disable: senseair0 + update_interval: 15s diff --git a/tests/components/senseair/test.esp32-idf.yaml b/tests/components/senseair/test.esp32-idf.yaml new file mode 100644 index 0000000000..daa4645f59 --- /dev/null +++ b/tests/components/senseair/test.esp32-idf.yaml @@ -0,0 +1,19 @@ +uart: + - id: uart_senseair + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +sensor: + - platform: senseair + id: senseair0 + co2: + name: SenseAir CO2 Value + on_value: + then: + - senseair.background_calibration: senseair0 + - senseair.background_calibration_result: senseair0 + - senseair.abc_get_period: senseair0 + - senseair.abc_enable: senseair0 + - senseair.abc_disable: senseair0 + update_interval: 15s diff --git a/tests/components/senseair/test.esp32.yaml b/tests/components/senseair/test.esp32.yaml new file mode 100644 index 0000000000..daa4645f59 --- /dev/null +++ b/tests/components/senseair/test.esp32.yaml @@ -0,0 +1,19 @@ +uart: + - id: uart_senseair + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +sensor: + - platform: senseair + id: senseair0 + co2: + name: SenseAir CO2 Value + on_value: + then: + - senseair.background_calibration: senseair0 + - senseair.background_calibration_result: senseair0 + - senseair.abc_get_period: senseair0 + - senseair.abc_enable: senseair0 + - senseair.abc_disable: senseair0 + update_interval: 15s diff --git a/tests/components/senseair/test.esp8266.yaml b/tests/components/senseair/test.esp8266.yaml new file mode 100644 index 0000000000..41a441f496 --- /dev/null +++ b/tests/components/senseair/test.esp8266.yaml @@ -0,0 +1,19 @@ +uart: + - id: uart_senseair + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sensor: + - platform: senseair + id: senseair0 + co2: + name: SenseAir CO2 Value + on_value: + then: + - senseair.background_calibration: senseair0 + - senseair.background_calibration_result: senseair0 + - senseair.abc_get_period: senseair0 + - senseair.abc_enable: senseair0 + - senseair.abc_disable: senseair0 + update_interval: 15s diff --git a/tests/components/senseair/test.rp2040.yaml b/tests/components/senseair/test.rp2040.yaml new file mode 100644 index 0000000000..41a441f496 --- /dev/null +++ b/tests/components/senseair/test.rp2040.yaml @@ -0,0 +1,19 @@ +uart: + - id: uart_senseair + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sensor: + - platform: senseair + id: senseair0 + co2: + name: SenseAir CO2 Value + on_value: + then: + - senseair.background_calibration: senseair0 + - senseair.background_calibration_result: senseair0 + - senseair.abc_get_period: senseair0 + - senseair.abc_enable: senseair0 + - senseair.abc_disable: senseair0 + update_interval: 15s diff --git a/tests/components/servo/test.esp32-c3-idf.yaml b/tests/components/servo/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..29ebea3359 --- /dev/null +++ b/tests/components/servo/test.esp32-c3-idf.yaml @@ -0,0 +1,19 @@ +esphome: + on_boot: + then: + - servo.write: + id: test_servo + level: -100.0% + - servo.detach: test_servo + +output: + - platform: ledc + id: servo_output_1 + pin: 1 + +servo: + id: test_servo + output: servo_output_1 + restore: true + min_level: 4% + max_level: 8% diff --git a/tests/components/servo/test.esp32-c3.yaml b/tests/components/servo/test.esp32-c3.yaml new file mode 100644 index 0000000000..29ebea3359 --- /dev/null +++ b/tests/components/servo/test.esp32-c3.yaml @@ -0,0 +1,19 @@ +esphome: + on_boot: + then: + - servo.write: + id: test_servo + level: -100.0% + - servo.detach: test_servo + +output: + - platform: ledc + id: servo_output_1 + pin: 1 + +servo: + id: test_servo + output: servo_output_1 + restore: true + min_level: 4% + max_level: 8% diff --git a/tests/components/servo/test.esp32-idf.yaml b/tests/components/servo/test.esp32-idf.yaml new file mode 100644 index 0000000000..e769f055b4 --- /dev/null +++ b/tests/components/servo/test.esp32-idf.yaml @@ -0,0 +1,19 @@ +esphome: + on_boot: + then: + - servo.write: + id: test_servo + level: -100.0% + - servo.detach: test_servo + +output: + - platform: ledc + id: servo_output_1 + pin: 12 + +servo: + id: test_servo + output: servo_output_1 + restore: true + min_level: 4% + max_level: 8% diff --git a/tests/components/servo/test.esp32.yaml b/tests/components/servo/test.esp32.yaml new file mode 100644 index 0000000000..e769f055b4 --- /dev/null +++ b/tests/components/servo/test.esp32.yaml @@ -0,0 +1,19 @@ +esphome: + on_boot: + then: + - servo.write: + id: test_servo + level: -100.0% + - servo.detach: test_servo + +output: + - platform: ledc + id: servo_output_1 + pin: 12 + +servo: + id: test_servo + output: servo_output_1 + restore: true + min_level: 4% + max_level: 8% diff --git a/tests/components/servo/test.esp8266.yaml b/tests/components/servo/test.esp8266.yaml new file mode 100644 index 0000000000..48b4421641 --- /dev/null +++ b/tests/components/servo/test.esp8266.yaml @@ -0,0 +1,19 @@ +esphome: + on_boot: + then: + - servo.write: + id: test_servo + level: -100.0% + - servo.detach: test_servo + +output: + - platform: esp8266_pwm + id: servo_output_1 + pin: 12 + +servo: + id: test_servo + output: servo_output_1 + restore: true + min_level: 4% + max_level: 8% diff --git a/tests/components/servo/test.rp2040.yaml b/tests/components/servo/test.rp2040.yaml new file mode 100644 index 0000000000..75efa9407e --- /dev/null +++ b/tests/components/servo/test.rp2040.yaml @@ -0,0 +1,19 @@ +esphome: + on_boot: + then: + - servo.write: + id: test_servo + level: -100.0% + - servo.detach: test_servo + +output: + - platform: rp2040_pwm + id: servo_output_1 + pin: 12 + +servo: + id: test_servo + output: servo_output_1 + restore: true + min_level: 4% + max_level: 8% diff --git a/tests/components/sfa30/test.esp32-c3-idf.yaml b/tests/components/sfa30/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..119059e4e2 --- /dev/null +++ b/tests/components/sfa30/test.esp32-c3-idf.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_sfa30 + scl: 5 + sda: 4 + +sensor: + - platform: sfa30 + formaldehyde: + name: "SFA30 formaldehyde" + temperature: + name: "SFA30 temperature" + humidity: + name: "SFA30 humidity" + address: 0x5D + update_interval: 30s diff --git a/tests/components/sfa30/test.esp32-c3.yaml b/tests/components/sfa30/test.esp32-c3.yaml new file mode 100644 index 0000000000..119059e4e2 --- /dev/null +++ b/tests/components/sfa30/test.esp32-c3.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_sfa30 + scl: 5 + sda: 4 + +sensor: + - platform: sfa30 + formaldehyde: + name: "SFA30 formaldehyde" + temperature: + name: "SFA30 temperature" + humidity: + name: "SFA30 humidity" + address: 0x5D + update_interval: 30s diff --git a/tests/components/sfa30/test.esp32-idf.yaml b/tests/components/sfa30/test.esp32-idf.yaml new file mode 100644 index 0000000000..dc7e4988e5 --- /dev/null +++ b/tests/components/sfa30/test.esp32-idf.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_sfa30 + scl: 16 + sda: 17 + +sensor: + - platform: sfa30 + formaldehyde: + name: "SFA30 formaldehyde" + temperature: + name: "SFA30 temperature" + humidity: + name: "SFA30 humidity" + address: 0x5D + update_interval: 30s diff --git a/tests/components/sfa30/test.esp32.yaml b/tests/components/sfa30/test.esp32.yaml new file mode 100644 index 0000000000..dc7e4988e5 --- /dev/null +++ b/tests/components/sfa30/test.esp32.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_sfa30 + scl: 16 + sda: 17 + +sensor: + - platform: sfa30 + formaldehyde: + name: "SFA30 formaldehyde" + temperature: + name: "SFA30 temperature" + humidity: + name: "SFA30 humidity" + address: 0x5D + update_interval: 30s diff --git a/tests/components/sfa30/test.esp8266.yaml b/tests/components/sfa30/test.esp8266.yaml new file mode 100644 index 0000000000..119059e4e2 --- /dev/null +++ b/tests/components/sfa30/test.esp8266.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_sfa30 + scl: 5 + sda: 4 + +sensor: + - platform: sfa30 + formaldehyde: + name: "SFA30 formaldehyde" + temperature: + name: "SFA30 temperature" + humidity: + name: "SFA30 humidity" + address: 0x5D + update_interval: 30s diff --git a/tests/components/sfa30/test.rp2040.yaml b/tests/components/sfa30/test.rp2040.yaml new file mode 100644 index 0000000000..119059e4e2 --- /dev/null +++ b/tests/components/sfa30/test.rp2040.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_sfa30 + scl: 5 + sda: 4 + +sensor: + - platform: sfa30 + formaldehyde: + name: "SFA30 formaldehyde" + temperature: + name: "SFA30 temperature" + humidity: + name: "SFA30 humidity" + address: 0x5D + update_interval: 30s diff --git a/tests/components/sgp30/test.esp32-c3-idf.yaml b/tests/components/sgp30/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..45de67e94b --- /dev/null +++ b/tests/components/sgp30/test.esp32-c3-idf.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_sgp30 + scl: 5 + sda: 4 + +sensor: + - platform: sgp30 + eco2: + name: Workshop eCO2 + accuracy_decimals: 1 + tvoc: + name: Workshop TVOC + accuracy_decimals: 1 + address: 0x58 + update_interval: 5s diff --git a/tests/components/sgp30/test.esp32-c3.yaml b/tests/components/sgp30/test.esp32-c3.yaml new file mode 100644 index 0000000000..45de67e94b --- /dev/null +++ b/tests/components/sgp30/test.esp32-c3.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_sgp30 + scl: 5 + sda: 4 + +sensor: + - platform: sgp30 + eco2: + name: Workshop eCO2 + accuracy_decimals: 1 + tvoc: + name: Workshop TVOC + accuracy_decimals: 1 + address: 0x58 + update_interval: 5s diff --git a/tests/components/sgp30/test.esp32-idf.yaml b/tests/components/sgp30/test.esp32-idf.yaml new file mode 100644 index 0000000000..6ea23c25cd --- /dev/null +++ b/tests/components/sgp30/test.esp32-idf.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_sgp30 + scl: 16 + sda: 17 + +sensor: + - platform: sgp30 + eco2: + name: Workshop eCO2 + accuracy_decimals: 1 + tvoc: + name: Workshop TVOC + accuracy_decimals: 1 + address: 0x58 + update_interval: 5s diff --git a/tests/components/sgp30/test.esp32.yaml b/tests/components/sgp30/test.esp32.yaml new file mode 100644 index 0000000000..6ea23c25cd --- /dev/null +++ b/tests/components/sgp30/test.esp32.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_sgp30 + scl: 16 + sda: 17 + +sensor: + - platform: sgp30 + eco2: + name: Workshop eCO2 + accuracy_decimals: 1 + tvoc: + name: Workshop TVOC + accuracy_decimals: 1 + address: 0x58 + update_interval: 5s diff --git a/tests/components/sgp30/test.esp8266.yaml b/tests/components/sgp30/test.esp8266.yaml new file mode 100644 index 0000000000..45de67e94b --- /dev/null +++ b/tests/components/sgp30/test.esp8266.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_sgp30 + scl: 5 + sda: 4 + +sensor: + - platform: sgp30 + eco2: + name: Workshop eCO2 + accuracy_decimals: 1 + tvoc: + name: Workshop TVOC + accuracy_decimals: 1 + address: 0x58 + update_interval: 5s diff --git a/tests/components/sgp30/test.rp2040.yaml b/tests/components/sgp30/test.rp2040.yaml new file mode 100644 index 0000000000..45de67e94b --- /dev/null +++ b/tests/components/sgp30/test.rp2040.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_sgp30 + scl: 5 + sda: 4 + +sensor: + - platform: sgp30 + eco2: + name: Workshop eCO2 + accuracy_decimals: 1 + tvoc: + name: Workshop TVOC + accuracy_decimals: 1 + address: 0x58 + update_interval: 5s diff --git a/tests/components/sgp4x/test.esp32-c3-idf.yaml b/tests/components/sgp4x/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..b2876478bd --- /dev/null +++ b/tests/components/sgp4x/test.esp32-c3-idf.yaml @@ -0,0 +1,27 @@ +i2c: + - id: i2c_sgp4x + scl: 5 + sda: 4 + +sensor: + - platform: sgp4x + voc: + name: VOC Index + id: sgp40_voc_index + algorithm_tuning: + index_offset: 100 + learning_time_offset_hours: 12 + learning_time_gain_hours: 12 + gating_max_duration_minutes: 180 + std_initial: 50 + gain_factor: 230 + nox: + name: NOx + algorithm_tuning: + index_offset: 100 + learning_time_offset_hours: 12 + learning_time_gain_hours: 12 + gating_max_duration_minutes: 180 + std_initial: 50 + gain_factor: 230 + update_interval: 5s diff --git a/tests/components/sgp4x/test.esp32-c3.yaml b/tests/components/sgp4x/test.esp32-c3.yaml new file mode 100644 index 0000000000..b2876478bd --- /dev/null +++ b/tests/components/sgp4x/test.esp32-c3.yaml @@ -0,0 +1,27 @@ +i2c: + - id: i2c_sgp4x + scl: 5 + sda: 4 + +sensor: + - platform: sgp4x + voc: + name: VOC Index + id: sgp40_voc_index + algorithm_tuning: + index_offset: 100 + learning_time_offset_hours: 12 + learning_time_gain_hours: 12 + gating_max_duration_minutes: 180 + std_initial: 50 + gain_factor: 230 + nox: + name: NOx + algorithm_tuning: + index_offset: 100 + learning_time_offset_hours: 12 + learning_time_gain_hours: 12 + gating_max_duration_minutes: 180 + std_initial: 50 + gain_factor: 230 + update_interval: 5s diff --git a/tests/components/sgp4x/test.esp32-idf.yaml b/tests/components/sgp4x/test.esp32-idf.yaml new file mode 100644 index 0000000000..c7380b5a10 --- /dev/null +++ b/tests/components/sgp4x/test.esp32-idf.yaml @@ -0,0 +1,27 @@ +i2c: + - id: i2c_sgp4x + scl: 16 + sda: 17 + +sensor: + - platform: sgp4x + voc: + name: VOC Index + id: sgp40_voc_index + algorithm_tuning: + index_offset: 100 + learning_time_offset_hours: 12 + learning_time_gain_hours: 12 + gating_max_duration_minutes: 180 + std_initial: 50 + gain_factor: 230 + nox: + name: NOx + algorithm_tuning: + index_offset: 100 + learning_time_offset_hours: 12 + learning_time_gain_hours: 12 + gating_max_duration_minutes: 180 + std_initial: 50 + gain_factor: 230 + update_interval: 5s diff --git a/tests/components/sgp4x/test.esp32.yaml b/tests/components/sgp4x/test.esp32.yaml new file mode 100644 index 0000000000..c7380b5a10 --- /dev/null +++ b/tests/components/sgp4x/test.esp32.yaml @@ -0,0 +1,27 @@ +i2c: + - id: i2c_sgp4x + scl: 16 + sda: 17 + +sensor: + - platform: sgp4x + voc: + name: VOC Index + id: sgp40_voc_index + algorithm_tuning: + index_offset: 100 + learning_time_offset_hours: 12 + learning_time_gain_hours: 12 + gating_max_duration_minutes: 180 + std_initial: 50 + gain_factor: 230 + nox: + name: NOx + algorithm_tuning: + index_offset: 100 + learning_time_offset_hours: 12 + learning_time_gain_hours: 12 + gating_max_duration_minutes: 180 + std_initial: 50 + gain_factor: 230 + update_interval: 5s diff --git a/tests/components/sgp4x/test.esp8266.yaml b/tests/components/sgp4x/test.esp8266.yaml new file mode 100644 index 0000000000..b2876478bd --- /dev/null +++ b/tests/components/sgp4x/test.esp8266.yaml @@ -0,0 +1,27 @@ +i2c: + - id: i2c_sgp4x + scl: 5 + sda: 4 + +sensor: + - platform: sgp4x + voc: + name: VOC Index + id: sgp40_voc_index + algorithm_tuning: + index_offset: 100 + learning_time_offset_hours: 12 + learning_time_gain_hours: 12 + gating_max_duration_minutes: 180 + std_initial: 50 + gain_factor: 230 + nox: + name: NOx + algorithm_tuning: + index_offset: 100 + learning_time_offset_hours: 12 + learning_time_gain_hours: 12 + gating_max_duration_minutes: 180 + std_initial: 50 + gain_factor: 230 + update_interval: 5s diff --git a/tests/components/sgp4x/test.rp2040.yaml b/tests/components/sgp4x/test.rp2040.yaml new file mode 100644 index 0000000000..b2876478bd --- /dev/null +++ b/tests/components/sgp4x/test.rp2040.yaml @@ -0,0 +1,27 @@ +i2c: + - id: i2c_sgp4x + scl: 5 + sda: 4 + +sensor: + - platform: sgp4x + voc: + name: VOC Index + id: sgp40_voc_index + algorithm_tuning: + index_offset: 100 + learning_time_offset_hours: 12 + learning_time_gain_hours: 12 + gating_max_duration_minutes: 180 + std_initial: 50 + gain_factor: 230 + nox: + name: NOx + algorithm_tuning: + index_offset: 100 + learning_time_offset_hours: 12 + learning_time_gain_hours: 12 + gating_max_duration_minutes: 180 + std_initial: 50 + gain_factor: 230 + update_interval: 5s diff --git a/tests/components/shelly_dimmer/test.esp8266.yaml b/tests/components/shelly_dimmer/test.esp8266.yaml new file mode 100644 index 0000000000..3acd0260d5 --- /dev/null +++ b/tests/components/shelly_dimmer/test.esp8266.yaml @@ -0,0 +1,19 @@ +uart: + - id: uart_shelly_dimmer + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +light: + - platform: shelly_dimmer + name: Shelly Dimmer Light + power: + name: Shelly Dimmer Power + voltage: + name: Shelly Dimmer Voltage + current: + name: Shelly Dimmer Current + max_brightness: 500 + firmware: "51.6" + nrst_pin: 13 + boot0_pin: 14 diff --git a/tests/components/sht3xd/test.esp32-c3-idf.yaml b/tests/components/sht3xd/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..0409ff65c6 --- /dev/null +++ b/tests/components/sht3xd/test.esp32-c3-idf.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_sht3xd + scl: 5 + sda: 4 + +sensor: + - platform: sht3xd + temperature: + name: SHT3XD Temperature + humidity: + name: SHT3XD Humidity + address: 0x44 + update_interval: 15s diff --git a/tests/components/sht3xd/test.esp32-c3.yaml b/tests/components/sht3xd/test.esp32-c3.yaml new file mode 100644 index 0000000000..0409ff65c6 --- /dev/null +++ b/tests/components/sht3xd/test.esp32-c3.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_sht3xd + scl: 5 + sda: 4 + +sensor: + - platform: sht3xd + temperature: + name: SHT3XD Temperature + humidity: + name: SHT3XD Humidity + address: 0x44 + update_interval: 15s diff --git a/tests/components/sht3xd/test.esp32-idf.yaml b/tests/components/sht3xd/test.esp32-idf.yaml new file mode 100644 index 0000000000..2b6ee50760 --- /dev/null +++ b/tests/components/sht3xd/test.esp32-idf.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_sht3xd + scl: 16 + sda: 17 + +sensor: + - platform: sht3xd + temperature: + name: SHT3XD Temperature + humidity: + name: SHT3XD Humidity + address: 0x44 + update_interval: 15s diff --git a/tests/components/sht3xd/test.esp32.yaml b/tests/components/sht3xd/test.esp32.yaml new file mode 100644 index 0000000000..2b6ee50760 --- /dev/null +++ b/tests/components/sht3xd/test.esp32.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_sht3xd + scl: 16 + sda: 17 + +sensor: + - platform: sht3xd + temperature: + name: SHT3XD Temperature + humidity: + name: SHT3XD Humidity + address: 0x44 + update_interval: 15s diff --git a/tests/components/sht3xd/test.esp8266.yaml b/tests/components/sht3xd/test.esp8266.yaml new file mode 100644 index 0000000000..0409ff65c6 --- /dev/null +++ b/tests/components/sht3xd/test.esp8266.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_sht3xd + scl: 5 + sda: 4 + +sensor: + - platform: sht3xd + temperature: + name: SHT3XD Temperature + humidity: + name: SHT3XD Humidity + address: 0x44 + update_interval: 15s diff --git a/tests/components/sht3xd/test.rp2040.yaml b/tests/components/sht3xd/test.rp2040.yaml new file mode 100644 index 0000000000..0409ff65c6 --- /dev/null +++ b/tests/components/sht3xd/test.rp2040.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_sht3xd + scl: 5 + sda: 4 + +sensor: + - platform: sht3xd + temperature: + name: SHT3XD Temperature + humidity: + name: SHT3XD Humidity + address: 0x44 + update_interval: 15s diff --git a/tests/components/sht4x/test.esp32-c3-idf.yaml b/tests/components/sht4x/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..0bcdd864f6 --- /dev/null +++ b/tests/components/sht4x/test.esp32-c3-idf.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_sht4x + scl: 5 + sda: 4 + +sensor: + - platform: sht4x + temperature: + name: SHT4X Temperature + humidity: + name: SHT4X Humidity + address: 0x44 + update_interval: 15s diff --git a/tests/components/sht4x/test.esp32-c3.yaml b/tests/components/sht4x/test.esp32-c3.yaml new file mode 100644 index 0000000000..0bcdd864f6 --- /dev/null +++ b/tests/components/sht4x/test.esp32-c3.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_sht4x + scl: 5 + sda: 4 + +sensor: + - platform: sht4x + temperature: + name: SHT4X Temperature + humidity: + name: SHT4X Humidity + address: 0x44 + update_interval: 15s diff --git a/tests/components/sht4x/test.esp32-idf.yaml b/tests/components/sht4x/test.esp32-idf.yaml new file mode 100644 index 0000000000..13ec524d7d --- /dev/null +++ b/tests/components/sht4x/test.esp32-idf.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_sht4x + scl: 16 + sda: 17 + +sensor: + - platform: sht4x + temperature: + name: SHT4X Temperature + humidity: + name: SHT4X Humidity + address: 0x44 + update_interval: 15s diff --git a/tests/components/sht4x/test.esp32.yaml b/tests/components/sht4x/test.esp32.yaml new file mode 100644 index 0000000000..13ec524d7d --- /dev/null +++ b/tests/components/sht4x/test.esp32.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_sht4x + scl: 16 + sda: 17 + +sensor: + - platform: sht4x + temperature: + name: SHT4X Temperature + humidity: + name: SHT4X Humidity + address: 0x44 + update_interval: 15s diff --git a/tests/components/sht4x/test.esp8266.yaml b/tests/components/sht4x/test.esp8266.yaml new file mode 100644 index 0000000000..0bcdd864f6 --- /dev/null +++ b/tests/components/sht4x/test.esp8266.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_sht4x + scl: 5 + sda: 4 + +sensor: + - platform: sht4x + temperature: + name: SHT4X Temperature + humidity: + name: SHT4X Humidity + address: 0x44 + update_interval: 15s diff --git a/tests/components/sht4x/test.rp2040.yaml b/tests/components/sht4x/test.rp2040.yaml new file mode 100644 index 0000000000..0bcdd864f6 --- /dev/null +++ b/tests/components/sht4x/test.rp2040.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_sht4x + scl: 5 + sda: 4 + +sensor: + - platform: sht4x + temperature: + name: SHT4X Temperature + humidity: + name: SHT4X Humidity + address: 0x44 + update_interval: 15s diff --git a/tests/components/shtcx/test.esp32-c3-idf.yaml b/tests/components/shtcx/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..c1c7a2a63f --- /dev/null +++ b/tests/components/shtcx/test.esp32-c3-idf.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_shtcx + scl: 5 + sda: 4 + +sensor: + - platform: shtcx + temperature: + name: SHTCX Temperature + humidity: + name: SHTCX Humidity + address: 0x70 + update_interval: 15s diff --git a/tests/components/shtcx/test.esp32-c3.yaml b/tests/components/shtcx/test.esp32-c3.yaml new file mode 100644 index 0000000000..c1c7a2a63f --- /dev/null +++ b/tests/components/shtcx/test.esp32-c3.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_shtcx + scl: 5 + sda: 4 + +sensor: + - platform: shtcx + temperature: + name: SHTCX Temperature + humidity: + name: SHTCX Humidity + address: 0x70 + update_interval: 15s diff --git a/tests/components/shtcx/test.esp32-idf.yaml b/tests/components/shtcx/test.esp32-idf.yaml new file mode 100644 index 0000000000..619bac9548 --- /dev/null +++ b/tests/components/shtcx/test.esp32-idf.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_shtcx + scl: 16 + sda: 17 + +sensor: + - platform: shtcx + temperature: + name: SHTCX Temperature + humidity: + name: SHTCX Humidity + address: 0x70 + update_interval: 15s diff --git a/tests/components/shtcx/test.esp32.yaml b/tests/components/shtcx/test.esp32.yaml new file mode 100644 index 0000000000..619bac9548 --- /dev/null +++ b/tests/components/shtcx/test.esp32.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_shtcx + scl: 16 + sda: 17 + +sensor: + - platform: shtcx + temperature: + name: SHTCX Temperature + humidity: + name: SHTCX Humidity + address: 0x70 + update_interval: 15s diff --git a/tests/components/shtcx/test.esp8266.yaml b/tests/components/shtcx/test.esp8266.yaml new file mode 100644 index 0000000000..c1c7a2a63f --- /dev/null +++ b/tests/components/shtcx/test.esp8266.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_shtcx + scl: 5 + sda: 4 + +sensor: + - platform: shtcx + temperature: + name: SHTCX Temperature + humidity: + name: SHTCX Humidity + address: 0x70 + update_interval: 15s diff --git a/tests/components/shtcx/test.rp2040.yaml b/tests/components/shtcx/test.rp2040.yaml new file mode 100644 index 0000000000..c1c7a2a63f --- /dev/null +++ b/tests/components/shtcx/test.rp2040.yaml @@ -0,0 +1,13 @@ +i2c: + - id: i2c_shtcx + scl: 5 + sda: 4 + +sensor: + - platform: shtcx + temperature: + name: SHTCX Temperature + humidity: + name: SHTCX Humidity + address: 0x70 + update_interval: 15s diff --git a/tests/components/shutdown/test.esp32-c3-idf.yaml b/tests/components/shutdown/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..f47e7da85d --- /dev/null +++ b/tests/components/shutdown/test.esp32-c3-idf.yaml @@ -0,0 +1,7 @@ +button: + - platform: shutdown + name: Shutdown Button + +switch: + - platform: shutdown + name: Shutdown Switch diff --git a/tests/components/shutdown/test.esp32-c3.yaml b/tests/components/shutdown/test.esp32-c3.yaml new file mode 100644 index 0000000000..f47e7da85d --- /dev/null +++ b/tests/components/shutdown/test.esp32-c3.yaml @@ -0,0 +1,7 @@ +button: + - platform: shutdown + name: Shutdown Button + +switch: + - platform: shutdown + name: Shutdown Switch diff --git a/tests/components/shutdown/test.esp32-idf.yaml b/tests/components/shutdown/test.esp32-idf.yaml new file mode 100644 index 0000000000..f47e7da85d --- /dev/null +++ b/tests/components/shutdown/test.esp32-idf.yaml @@ -0,0 +1,7 @@ +button: + - platform: shutdown + name: Shutdown Button + +switch: + - platform: shutdown + name: Shutdown Switch diff --git a/tests/components/shutdown/test.esp32.yaml b/tests/components/shutdown/test.esp32.yaml new file mode 100644 index 0000000000..f47e7da85d --- /dev/null +++ b/tests/components/shutdown/test.esp32.yaml @@ -0,0 +1,7 @@ +button: + - platform: shutdown + name: Shutdown Button + +switch: + - platform: shutdown + name: Shutdown Switch diff --git a/tests/components/shutdown/test.esp8266.yaml b/tests/components/shutdown/test.esp8266.yaml new file mode 100644 index 0000000000..f47e7da85d --- /dev/null +++ b/tests/components/shutdown/test.esp8266.yaml @@ -0,0 +1,7 @@ +button: + - platform: shutdown + name: Shutdown Button + +switch: + - platform: shutdown + name: Shutdown Switch diff --git a/tests/components/shutdown/test.rp2040.yaml b/tests/components/shutdown/test.rp2040.yaml new file mode 100644 index 0000000000..f47e7da85d --- /dev/null +++ b/tests/components/shutdown/test.rp2040.yaml @@ -0,0 +1,7 @@ +button: + - platform: shutdown + name: Shutdown Button + +switch: + - platform: shutdown + name: Shutdown Switch diff --git a/tests/components/sigma_delta_output/test.esp32-c3-idf.yaml b/tests/components/sigma_delta_output/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..2a9a5d2c3b --- /dev/null +++ b/tests/components/sigma_delta_output/test.esp32-c3-idf.yaml @@ -0,0 +1,16 @@ +output: + - platform: sigma_delta_output + id: sddac + pin: 4 + turn_on_action: + then: + - logger.log: "Turned on" + turn_off_action: + then: + - logger.log: "Turned off" + state_change_action: + then: + - logger.log: + format: "Changed state: %d" + args: ["state"] + update_interval: 60s diff --git a/tests/components/sigma_delta_output/test.esp32-c3.yaml b/tests/components/sigma_delta_output/test.esp32-c3.yaml new file mode 100644 index 0000000000..2a9a5d2c3b --- /dev/null +++ b/tests/components/sigma_delta_output/test.esp32-c3.yaml @@ -0,0 +1,16 @@ +output: + - platform: sigma_delta_output + id: sddac + pin: 4 + turn_on_action: + then: + - logger.log: "Turned on" + turn_off_action: + then: + - logger.log: "Turned off" + state_change_action: + then: + - logger.log: + format: "Changed state: %d" + args: ["state"] + update_interval: 60s diff --git a/tests/components/sigma_delta_output/test.esp32-idf.yaml b/tests/components/sigma_delta_output/test.esp32-idf.yaml new file mode 100644 index 0000000000..2a9a5d2c3b --- /dev/null +++ b/tests/components/sigma_delta_output/test.esp32-idf.yaml @@ -0,0 +1,16 @@ +output: + - platform: sigma_delta_output + id: sddac + pin: 4 + turn_on_action: + then: + - logger.log: "Turned on" + turn_off_action: + then: + - logger.log: "Turned off" + state_change_action: + then: + - logger.log: + format: "Changed state: %d" + args: ["state"] + update_interval: 60s diff --git a/tests/components/sigma_delta_output/test.esp32.yaml b/tests/components/sigma_delta_output/test.esp32.yaml new file mode 100644 index 0000000000..2a9a5d2c3b --- /dev/null +++ b/tests/components/sigma_delta_output/test.esp32.yaml @@ -0,0 +1,16 @@ +output: + - platform: sigma_delta_output + id: sddac + pin: 4 + turn_on_action: + then: + - logger.log: "Turned on" + turn_off_action: + then: + - logger.log: "Turned off" + state_change_action: + then: + - logger.log: + format: "Changed state: %d" + args: ["state"] + update_interval: 60s diff --git a/tests/components/sigma_delta_output/test.esp8266.yaml b/tests/components/sigma_delta_output/test.esp8266.yaml new file mode 100644 index 0000000000..2a9a5d2c3b --- /dev/null +++ b/tests/components/sigma_delta_output/test.esp8266.yaml @@ -0,0 +1,16 @@ +output: + - platform: sigma_delta_output + id: sddac + pin: 4 + turn_on_action: + then: + - logger.log: "Turned on" + turn_off_action: + then: + - logger.log: "Turned off" + state_change_action: + then: + - logger.log: + format: "Changed state: %d" + args: ["state"] + update_interval: 60s diff --git a/tests/components/sigma_delta_output/test.rp2040.yaml b/tests/components/sigma_delta_output/test.rp2040.yaml new file mode 100644 index 0000000000..2a9a5d2c3b --- /dev/null +++ b/tests/components/sigma_delta_output/test.rp2040.yaml @@ -0,0 +1,16 @@ +output: + - platform: sigma_delta_output + id: sddac + pin: 4 + turn_on_action: + then: + - logger.log: "Turned on" + turn_off_action: + then: + - logger.log: "Turned off" + state_change_action: + then: + - logger.log: + format: "Changed state: %d" + args: ["state"] + update_interval: 60s diff --git a/tests/components/sim800l/test.esp32-c3-idf.yaml b/tests/components/sim800l/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..7ff359d1e7 --- /dev/null +++ b/tests/components/sim800l/test.esp32-c3-idf.yaml @@ -0,0 +1,37 @@ +esphome: + on_boot: + then: + - sim800l.send_sms: + recipient: '+15551234567' + message: Hello there + - sim800l.dial: + recipient: '+15551234567' + - sim800l.connect + - sim800l.disconnect + - sim800l.send_ussd: + ussd: test_ussd + +uart: + - id: uart_sim800l + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sim800l: + on_sms_received: + - lambda: |- + std::string str; + str = sender; + str = message; + - sim800l.send_sms: + message: hello you + recipient: "+1234" + - sim800l.dial: + recipient: "+1234" + on_incoming_call: + - logger.log: + format: "Incoming call from '%s'" + args: ["caller_id.c_str()"] + - sim800l.disconnect + on_ussd_received: + - logger.log: "ussd_received" diff --git a/tests/components/sim800l/test.esp32-c3.yaml b/tests/components/sim800l/test.esp32-c3.yaml new file mode 100644 index 0000000000..7ff359d1e7 --- /dev/null +++ b/tests/components/sim800l/test.esp32-c3.yaml @@ -0,0 +1,37 @@ +esphome: + on_boot: + then: + - sim800l.send_sms: + recipient: '+15551234567' + message: Hello there + - sim800l.dial: + recipient: '+15551234567' + - sim800l.connect + - sim800l.disconnect + - sim800l.send_ussd: + ussd: test_ussd + +uart: + - id: uart_sim800l + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sim800l: + on_sms_received: + - lambda: |- + std::string str; + str = sender; + str = message; + - sim800l.send_sms: + message: hello you + recipient: "+1234" + - sim800l.dial: + recipient: "+1234" + on_incoming_call: + - logger.log: + format: "Incoming call from '%s'" + args: ["caller_id.c_str()"] + - sim800l.disconnect + on_ussd_received: + - logger.log: "ussd_received" diff --git a/tests/components/sim800l/test.esp32-idf.yaml b/tests/components/sim800l/test.esp32-idf.yaml new file mode 100644 index 0000000000..c116548c6f --- /dev/null +++ b/tests/components/sim800l/test.esp32-idf.yaml @@ -0,0 +1,37 @@ +esphome: + on_boot: + then: + - sim800l.send_sms: + recipient: '+15551234567' + message: Hello there + - sim800l.dial: + recipient: '+15551234567' + - sim800l.connect + - sim800l.disconnect + - sim800l.send_ussd: + ussd: test_ussd + +uart: + - id: uart_sim800l + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +sim800l: + on_sms_received: + - lambda: |- + std::string str; + str = sender; + str = message; + - sim800l.send_sms: + message: hello you + recipient: "+1234" + - sim800l.dial: + recipient: "+1234" + on_incoming_call: + - logger.log: + format: "Incoming call from '%s'" + args: ["caller_id.c_str()"] + - sim800l.disconnect + on_ussd_received: + - logger.log: "ussd_received" diff --git a/tests/components/sim800l/test.esp32.yaml b/tests/components/sim800l/test.esp32.yaml new file mode 100644 index 0000000000..c116548c6f --- /dev/null +++ b/tests/components/sim800l/test.esp32.yaml @@ -0,0 +1,37 @@ +esphome: + on_boot: + then: + - sim800l.send_sms: + recipient: '+15551234567' + message: Hello there + - sim800l.dial: + recipient: '+15551234567' + - sim800l.connect + - sim800l.disconnect + - sim800l.send_ussd: + ussd: test_ussd + +uart: + - id: uart_sim800l + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +sim800l: + on_sms_received: + - lambda: |- + std::string str; + str = sender; + str = message; + - sim800l.send_sms: + message: hello you + recipient: "+1234" + - sim800l.dial: + recipient: "+1234" + on_incoming_call: + - logger.log: + format: "Incoming call from '%s'" + args: ["caller_id.c_str()"] + - sim800l.disconnect + on_ussd_received: + - logger.log: "ussd_received" diff --git a/tests/components/sim800l/test.esp8266.yaml b/tests/components/sim800l/test.esp8266.yaml new file mode 100644 index 0000000000..7ff359d1e7 --- /dev/null +++ b/tests/components/sim800l/test.esp8266.yaml @@ -0,0 +1,37 @@ +esphome: + on_boot: + then: + - sim800l.send_sms: + recipient: '+15551234567' + message: Hello there + - sim800l.dial: + recipient: '+15551234567' + - sim800l.connect + - sim800l.disconnect + - sim800l.send_ussd: + ussd: test_ussd + +uart: + - id: uart_sim800l + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sim800l: + on_sms_received: + - lambda: |- + std::string str; + str = sender; + str = message; + - sim800l.send_sms: + message: hello you + recipient: "+1234" + - sim800l.dial: + recipient: "+1234" + on_incoming_call: + - logger.log: + format: "Incoming call from '%s'" + args: ["caller_id.c_str()"] + - sim800l.disconnect + on_ussd_received: + - logger.log: "ussd_received" diff --git a/tests/components/sim800l/test.rp2040.yaml b/tests/components/sim800l/test.rp2040.yaml new file mode 100644 index 0000000000..7ff359d1e7 --- /dev/null +++ b/tests/components/sim800l/test.rp2040.yaml @@ -0,0 +1,37 @@ +esphome: + on_boot: + then: + - sim800l.send_sms: + recipient: '+15551234567' + message: Hello there + - sim800l.dial: + recipient: '+15551234567' + - sim800l.connect + - sim800l.disconnect + - sim800l.send_ussd: + ussd: test_ussd + +uart: + - id: uart_sim800l + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sim800l: + on_sms_received: + - lambda: |- + std::string str; + str = sender; + str = message; + - sim800l.send_sms: + message: hello you + recipient: "+1234" + - sim800l.dial: + recipient: "+1234" + on_incoming_call: + - logger.log: + format: "Incoming call from '%s'" + args: ["caller_id.c_str()"] + - sim800l.disconnect + on_ussd_received: + - logger.log: "ussd_received" diff --git a/tests/components/slow_pwm/test.esp32-c3-idf.yaml b/tests/components/slow_pwm/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..6bfb2f8ac5 --- /dev/null +++ b/tests/components/slow_pwm/test.esp32-c3-idf.yaml @@ -0,0 +1,6 @@ +output: + - platform: slow_pwm + id: test_slow_pwm + pin: 4 + period: 15s + restart_cycle_on_state_change: false diff --git a/tests/components/slow_pwm/test.esp32-c3.yaml b/tests/components/slow_pwm/test.esp32-c3.yaml new file mode 100644 index 0000000000..6bfb2f8ac5 --- /dev/null +++ b/tests/components/slow_pwm/test.esp32-c3.yaml @@ -0,0 +1,6 @@ +output: + - platform: slow_pwm + id: test_slow_pwm + pin: 4 + period: 15s + restart_cycle_on_state_change: false diff --git a/tests/components/slow_pwm/test.esp32-idf.yaml b/tests/components/slow_pwm/test.esp32-idf.yaml new file mode 100644 index 0000000000..6bfb2f8ac5 --- /dev/null +++ b/tests/components/slow_pwm/test.esp32-idf.yaml @@ -0,0 +1,6 @@ +output: + - platform: slow_pwm + id: test_slow_pwm + pin: 4 + period: 15s + restart_cycle_on_state_change: false diff --git a/tests/components/slow_pwm/test.esp32.yaml b/tests/components/slow_pwm/test.esp32.yaml new file mode 100644 index 0000000000..6bfb2f8ac5 --- /dev/null +++ b/tests/components/slow_pwm/test.esp32.yaml @@ -0,0 +1,6 @@ +output: + - platform: slow_pwm + id: test_slow_pwm + pin: 4 + period: 15s + restart_cycle_on_state_change: false diff --git a/tests/components/slow_pwm/test.esp8266.yaml b/tests/components/slow_pwm/test.esp8266.yaml new file mode 100644 index 0000000000..6bfb2f8ac5 --- /dev/null +++ b/tests/components/slow_pwm/test.esp8266.yaml @@ -0,0 +1,6 @@ +output: + - platform: slow_pwm + id: test_slow_pwm + pin: 4 + period: 15s + restart_cycle_on_state_change: false diff --git a/tests/components/slow_pwm/test.rp2040.yaml b/tests/components/slow_pwm/test.rp2040.yaml new file mode 100644 index 0000000000..6bfb2f8ac5 --- /dev/null +++ b/tests/components/slow_pwm/test.rp2040.yaml @@ -0,0 +1,6 @@ +output: + - platform: slow_pwm + id: test_slow_pwm + pin: 4 + period: 15s + restart_cycle_on_state_change: false diff --git a/tests/components/sm16716/test.esp32-c3-idf.yaml b/tests/components/sm16716/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..3bf2712f4e --- /dev/null +++ b/tests/components/sm16716/test.esp32-c3-idf.yaml @@ -0,0 +1,16 @@ +sm16716: + clock_pin: 4 + data_pin: 5 + num_channels: 3 + num_chips: 1 + +output: + - platform: sm16716 + id: sm16716_red + channel: 1 + - platform: sm16716 + id: sm16716_green + channel: 0 + - platform: sm16716 + id: sm16716_blue + channel: 2 diff --git a/tests/components/sm16716/test.esp32-c3.yaml b/tests/components/sm16716/test.esp32-c3.yaml new file mode 100644 index 0000000000..3bf2712f4e --- /dev/null +++ b/tests/components/sm16716/test.esp32-c3.yaml @@ -0,0 +1,16 @@ +sm16716: + clock_pin: 4 + data_pin: 5 + num_channels: 3 + num_chips: 1 + +output: + - platform: sm16716 + id: sm16716_red + channel: 1 + - platform: sm16716 + id: sm16716_green + channel: 0 + - platform: sm16716 + id: sm16716_blue + channel: 2 diff --git a/tests/components/sm16716/test.esp32-idf.yaml b/tests/components/sm16716/test.esp32-idf.yaml new file mode 100644 index 0000000000..3bf2712f4e --- /dev/null +++ b/tests/components/sm16716/test.esp32-idf.yaml @@ -0,0 +1,16 @@ +sm16716: + clock_pin: 4 + data_pin: 5 + num_channels: 3 + num_chips: 1 + +output: + - platform: sm16716 + id: sm16716_red + channel: 1 + - platform: sm16716 + id: sm16716_green + channel: 0 + - platform: sm16716 + id: sm16716_blue + channel: 2 diff --git a/tests/components/sm16716/test.esp32.yaml b/tests/components/sm16716/test.esp32.yaml new file mode 100644 index 0000000000..3bf2712f4e --- /dev/null +++ b/tests/components/sm16716/test.esp32.yaml @@ -0,0 +1,16 @@ +sm16716: + clock_pin: 4 + data_pin: 5 + num_channels: 3 + num_chips: 1 + +output: + - platform: sm16716 + id: sm16716_red + channel: 1 + - platform: sm16716 + id: sm16716_green + channel: 0 + - platform: sm16716 + id: sm16716_blue + channel: 2 diff --git a/tests/components/sm16716/test.esp8266.yaml b/tests/components/sm16716/test.esp8266.yaml new file mode 100644 index 0000000000..3bf2712f4e --- /dev/null +++ b/tests/components/sm16716/test.esp8266.yaml @@ -0,0 +1,16 @@ +sm16716: + clock_pin: 4 + data_pin: 5 + num_channels: 3 + num_chips: 1 + +output: + - platform: sm16716 + id: sm16716_red + channel: 1 + - platform: sm16716 + id: sm16716_green + channel: 0 + - platform: sm16716 + id: sm16716_blue + channel: 2 diff --git a/tests/components/sm16716/test.rp2040.yaml b/tests/components/sm16716/test.rp2040.yaml new file mode 100644 index 0000000000..3bf2712f4e --- /dev/null +++ b/tests/components/sm16716/test.rp2040.yaml @@ -0,0 +1,16 @@ +sm16716: + clock_pin: 4 + data_pin: 5 + num_channels: 3 + num_chips: 1 + +output: + - platform: sm16716 + id: sm16716_red + channel: 1 + - platform: sm16716 + id: sm16716_green + channel: 0 + - platform: sm16716 + id: sm16716_blue + channel: 2 diff --git a/tests/components/sm2135/test.esp32-c3-idf.yaml b/tests/components/sm2135/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..9a0de60839 --- /dev/null +++ b/tests/components/sm2135/test.esp32-c3-idf.yaml @@ -0,0 +1,22 @@ +sm2135: + clock_pin: 4 + data_pin: 5 + rgb_current: 20mA + cw_current: 60mA + +output: + - platform: sm2135 + id: sm2135_0 + channel: 0 + - platform: sm2135 + id: sm2135_1 + channel: 1 + - platform: sm2135 + id: sm2135_2 + channel: 2 + - platform: sm2135 + id: sm2135_3 + channel: 3 + - platform: sm2135 + id: sm2135_4 + channel: 4 diff --git a/tests/components/sm2135/test.esp32-c3.yaml b/tests/components/sm2135/test.esp32-c3.yaml new file mode 100644 index 0000000000..9a0de60839 --- /dev/null +++ b/tests/components/sm2135/test.esp32-c3.yaml @@ -0,0 +1,22 @@ +sm2135: + clock_pin: 4 + data_pin: 5 + rgb_current: 20mA + cw_current: 60mA + +output: + - platform: sm2135 + id: sm2135_0 + channel: 0 + - platform: sm2135 + id: sm2135_1 + channel: 1 + - platform: sm2135 + id: sm2135_2 + channel: 2 + - platform: sm2135 + id: sm2135_3 + channel: 3 + - platform: sm2135 + id: sm2135_4 + channel: 4 diff --git a/tests/components/sm2135/test.esp32-idf.yaml b/tests/components/sm2135/test.esp32-idf.yaml new file mode 100644 index 0000000000..9a0de60839 --- /dev/null +++ b/tests/components/sm2135/test.esp32-idf.yaml @@ -0,0 +1,22 @@ +sm2135: + clock_pin: 4 + data_pin: 5 + rgb_current: 20mA + cw_current: 60mA + +output: + - platform: sm2135 + id: sm2135_0 + channel: 0 + - platform: sm2135 + id: sm2135_1 + channel: 1 + - platform: sm2135 + id: sm2135_2 + channel: 2 + - platform: sm2135 + id: sm2135_3 + channel: 3 + - platform: sm2135 + id: sm2135_4 + channel: 4 diff --git a/tests/components/sm2135/test.esp32.yaml b/tests/components/sm2135/test.esp32.yaml new file mode 100644 index 0000000000..9a0de60839 --- /dev/null +++ b/tests/components/sm2135/test.esp32.yaml @@ -0,0 +1,22 @@ +sm2135: + clock_pin: 4 + data_pin: 5 + rgb_current: 20mA + cw_current: 60mA + +output: + - platform: sm2135 + id: sm2135_0 + channel: 0 + - platform: sm2135 + id: sm2135_1 + channel: 1 + - platform: sm2135 + id: sm2135_2 + channel: 2 + - platform: sm2135 + id: sm2135_3 + channel: 3 + - platform: sm2135 + id: sm2135_4 + channel: 4 diff --git a/tests/components/sm2135/test.esp8266.yaml b/tests/components/sm2135/test.esp8266.yaml new file mode 100644 index 0000000000..9a0de60839 --- /dev/null +++ b/tests/components/sm2135/test.esp8266.yaml @@ -0,0 +1,22 @@ +sm2135: + clock_pin: 4 + data_pin: 5 + rgb_current: 20mA + cw_current: 60mA + +output: + - platform: sm2135 + id: sm2135_0 + channel: 0 + - platform: sm2135 + id: sm2135_1 + channel: 1 + - platform: sm2135 + id: sm2135_2 + channel: 2 + - platform: sm2135 + id: sm2135_3 + channel: 3 + - platform: sm2135 + id: sm2135_4 + channel: 4 diff --git a/tests/components/sm2135/test.rp2040.yaml b/tests/components/sm2135/test.rp2040.yaml new file mode 100644 index 0000000000..9a0de60839 --- /dev/null +++ b/tests/components/sm2135/test.rp2040.yaml @@ -0,0 +1,22 @@ +sm2135: + clock_pin: 4 + data_pin: 5 + rgb_current: 20mA + cw_current: 60mA + +output: + - platform: sm2135 + id: sm2135_0 + channel: 0 + - platform: sm2135 + id: sm2135_1 + channel: 1 + - platform: sm2135 + id: sm2135_2 + channel: 2 + - platform: sm2135 + id: sm2135_3 + channel: 3 + - platform: sm2135 + id: sm2135_4 + channel: 4 diff --git a/tests/components/sm2235/test.esp32-c3-idf.yaml b/tests/components/sm2235/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..043d43d6f1 --- /dev/null +++ b/tests/components/sm2235/test.esp32-c3-idf.yaml @@ -0,0 +1,22 @@ +sm2235: + clock_pin: 4 + data_pin: 5 + max_power_color_channels: 9 + max_power_white_channels: 9 + +output: + - platform: sm2235 + id: sm2235_red + channel: 1 + - platform: sm2235 + id: sm2235_green + channel: 0 + - platform: sm2235 + id: sm2235_blue + channel: 2 + - platform: sm2235 + id: sm2235_coldwhite + channel: 4 + - platform: sm2235 + id: sm2235_warmwhite + channel: 3 diff --git a/tests/components/sm2235/test.esp32-c3.yaml b/tests/components/sm2235/test.esp32-c3.yaml new file mode 100644 index 0000000000..043d43d6f1 --- /dev/null +++ b/tests/components/sm2235/test.esp32-c3.yaml @@ -0,0 +1,22 @@ +sm2235: + clock_pin: 4 + data_pin: 5 + max_power_color_channels: 9 + max_power_white_channels: 9 + +output: + - platform: sm2235 + id: sm2235_red + channel: 1 + - platform: sm2235 + id: sm2235_green + channel: 0 + - platform: sm2235 + id: sm2235_blue + channel: 2 + - platform: sm2235 + id: sm2235_coldwhite + channel: 4 + - platform: sm2235 + id: sm2235_warmwhite + channel: 3 diff --git a/tests/components/sm2235/test.esp32-idf.yaml b/tests/components/sm2235/test.esp32-idf.yaml new file mode 100644 index 0000000000..043d43d6f1 --- /dev/null +++ b/tests/components/sm2235/test.esp32-idf.yaml @@ -0,0 +1,22 @@ +sm2235: + clock_pin: 4 + data_pin: 5 + max_power_color_channels: 9 + max_power_white_channels: 9 + +output: + - platform: sm2235 + id: sm2235_red + channel: 1 + - platform: sm2235 + id: sm2235_green + channel: 0 + - platform: sm2235 + id: sm2235_blue + channel: 2 + - platform: sm2235 + id: sm2235_coldwhite + channel: 4 + - platform: sm2235 + id: sm2235_warmwhite + channel: 3 diff --git a/tests/components/sm2235/test.esp32.yaml b/tests/components/sm2235/test.esp32.yaml new file mode 100644 index 0000000000..043d43d6f1 --- /dev/null +++ b/tests/components/sm2235/test.esp32.yaml @@ -0,0 +1,22 @@ +sm2235: + clock_pin: 4 + data_pin: 5 + max_power_color_channels: 9 + max_power_white_channels: 9 + +output: + - platform: sm2235 + id: sm2235_red + channel: 1 + - platform: sm2235 + id: sm2235_green + channel: 0 + - platform: sm2235 + id: sm2235_blue + channel: 2 + - platform: sm2235 + id: sm2235_coldwhite + channel: 4 + - platform: sm2235 + id: sm2235_warmwhite + channel: 3 diff --git a/tests/components/sm2235/test.esp8266.yaml b/tests/components/sm2235/test.esp8266.yaml new file mode 100644 index 0000000000..043d43d6f1 --- /dev/null +++ b/tests/components/sm2235/test.esp8266.yaml @@ -0,0 +1,22 @@ +sm2235: + clock_pin: 4 + data_pin: 5 + max_power_color_channels: 9 + max_power_white_channels: 9 + +output: + - platform: sm2235 + id: sm2235_red + channel: 1 + - platform: sm2235 + id: sm2235_green + channel: 0 + - platform: sm2235 + id: sm2235_blue + channel: 2 + - platform: sm2235 + id: sm2235_coldwhite + channel: 4 + - platform: sm2235 + id: sm2235_warmwhite + channel: 3 diff --git a/tests/components/sm2235/test.rp2040.yaml b/tests/components/sm2235/test.rp2040.yaml new file mode 100644 index 0000000000..043d43d6f1 --- /dev/null +++ b/tests/components/sm2235/test.rp2040.yaml @@ -0,0 +1,22 @@ +sm2235: + clock_pin: 4 + data_pin: 5 + max_power_color_channels: 9 + max_power_white_channels: 9 + +output: + - platform: sm2235 + id: sm2235_red + channel: 1 + - platform: sm2235 + id: sm2235_green + channel: 0 + - platform: sm2235 + id: sm2235_blue + channel: 2 + - platform: sm2235 + id: sm2235_coldwhite + channel: 4 + - platform: sm2235 + id: sm2235_warmwhite + channel: 3 diff --git a/tests/components/sm2335/test.esp32-c3-idf.yaml b/tests/components/sm2335/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..a5b2aedeb5 --- /dev/null +++ b/tests/components/sm2335/test.esp32-c3-idf.yaml @@ -0,0 +1,22 @@ +sm2335: + clock_pin: 4 + data_pin: 5 + max_power_color_channels: 9 + max_power_white_channels: 9 + +output: + - platform: sm2335 + id: sm2335_red + channel: 1 + - platform: sm2335 + id: sm2335_green + channel: 0 + - platform: sm2335 + id: sm2335_blue + channel: 2 + - platform: sm2335 + id: sm2335_coldwhite + channel: 4 + - platform: sm2335 + id: sm2335_warmwhite + channel: 3 diff --git a/tests/components/sm2335/test.esp32-c3.yaml b/tests/components/sm2335/test.esp32-c3.yaml new file mode 100644 index 0000000000..a5b2aedeb5 --- /dev/null +++ b/tests/components/sm2335/test.esp32-c3.yaml @@ -0,0 +1,22 @@ +sm2335: + clock_pin: 4 + data_pin: 5 + max_power_color_channels: 9 + max_power_white_channels: 9 + +output: + - platform: sm2335 + id: sm2335_red + channel: 1 + - platform: sm2335 + id: sm2335_green + channel: 0 + - platform: sm2335 + id: sm2335_blue + channel: 2 + - platform: sm2335 + id: sm2335_coldwhite + channel: 4 + - platform: sm2335 + id: sm2335_warmwhite + channel: 3 diff --git a/tests/components/sm2335/test.esp32-idf.yaml b/tests/components/sm2335/test.esp32-idf.yaml new file mode 100644 index 0000000000..a5b2aedeb5 --- /dev/null +++ b/tests/components/sm2335/test.esp32-idf.yaml @@ -0,0 +1,22 @@ +sm2335: + clock_pin: 4 + data_pin: 5 + max_power_color_channels: 9 + max_power_white_channels: 9 + +output: + - platform: sm2335 + id: sm2335_red + channel: 1 + - platform: sm2335 + id: sm2335_green + channel: 0 + - platform: sm2335 + id: sm2335_blue + channel: 2 + - platform: sm2335 + id: sm2335_coldwhite + channel: 4 + - platform: sm2335 + id: sm2335_warmwhite + channel: 3 diff --git a/tests/components/sm2335/test.esp32.yaml b/tests/components/sm2335/test.esp32.yaml new file mode 100644 index 0000000000..a5b2aedeb5 --- /dev/null +++ b/tests/components/sm2335/test.esp32.yaml @@ -0,0 +1,22 @@ +sm2335: + clock_pin: 4 + data_pin: 5 + max_power_color_channels: 9 + max_power_white_channels: 9 + +output: + - platform: sm2335 + id: sm2335_red + channel: 1 + - platform: sm2335 + id: sm2335_green + channel: 0 + - platform: sm2335 + id: sm2335_blue + channel: 2 + - platform: sm2335 + id: sm2335_coldwhite + channel: 4 + - platform: sm2335 + id: sm2335_warmwhite + channel: 3 diff --git a/tests/components/sm2335/test.esp8266.yaml b/tests/components/sm2335/test.esp8266.yaml new file mode 100644 index 0000000000..a5b2aedeb5 --- /dev/null +++ b/tests/components/sm2335/test.esp8266.yaml @@ -0,0 +1,22 @@ +sm2335: + clock_pin: 4 + data_pin: 5 + max_power_color_channels: 9 + max_power_white_channels: 9 + +output: + - platform: sm2335 + id: sm2335_red + channel: 1 + - platform: sm2335 + id: sm2335_green + channel: 0 + - platform: sm2335 + id: sm2335_blue + channel: 2 + - platform: sm2335 + id: sm2335_coldwhite + channel: 4 + - platform: sm2335 + id: sm2335_warmwhite + channel: 3 diff --git a/tests/components/sm2335/test.rp2040.yaml b/tests/components/sm2335/test.rp2040.yaml new file mode 100644 index 0000000000..a5b2aedeb5 --- /dev/null +++ b/tests/components/sm2335/test.rp2040.yaml @@ -0,0 +1,22 @@ +sm2335: + clock_pin: 4 + data_pin: 5 + max_power_color_channels: 9 + max_power_white_channels: 9 + +output: + - platform: sm2335 + id: sm2335_red + channel: 1 + - platform: sm2335 + id: sm2335_green + channel: 0 + - platform: sm2335 + id: sm2335_blue + channel: 2 + - platform: sm2335 + id: sm2335_coldwhite + channel: 4 + - platform: sm2335 + id: sm2335_warmwhite + channel: 3 diff --git a/tests/components/sm300d2/test.esp32-c3-idf.yaml b/tests/components/sm300d2/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..bcd0a728b2 --- /dev/null +++ b/tests/components/sm300d2/test.esp32-c3-idf.yaml @@ -0,0 +1,23 @@ +uart: + - id: uart_sm300d2 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sensor: + - platform: sm300d2 + co2: + name: SM300D2 CO2 Value + formaldehyde: + name: SM300D2 Formaldehyde Value + tvoc: + name: SM300D2 TVOC Value + pm_2_5: + name: SM300D2 PM2.5 Value + pm_10_0: + name: SM300D2 PM10 Value + temperature: + name: SM300D2 Temperature Value + humidity: + name: SM300D2 Humidity Value + update_interval: 60s diff --git a/tests/components/sm300d2/test.esp32-c3.yaml b/tests/components/sm300d2/test.esp32-c3.yaml new file mode 100644 index 0000000000..bcd0a728b2 --- /dev/null +++ b/tests/components/sm300d2/test.esp32-c3.yaml @@ -0,0 +1,23 @@ +uart: + - id: uart_sm300d2 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sensor: + - platform: sm300d2 + co2: + name: SM300D2 CO2 Value + formaldehyde: + name: SM300D2 Formaldehyde Value + tvoc: + name: SM300D2 TVOC Value + pm_2_5: + name: SM300D2 PM2.5 Value + pm_10_0: + name: SM300D2 PM10 Value + temperature: + name: SM300D2 Temperature Value + humidity: + name: SM300D2 Humidity Value + update_interval: 60s diff --git a/tests/components/sm300d2/test.esp32-idf.yaml b/tests/components/sm300d2/test.esp32-idf.yaml new file mode 100644 index 0000000000..92dba4fb3b --- /dev/null +++ b/tests/components/sm300d2/test.esp32-idf.yaml @@ -0,0 +1,23 @@ +uart: + - id: uart_sm300d2 + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +sensor: + - platform: sm300d2 + co2: + name: SM300D2 CO2 Value + formaldehyde: + name: SM300D2 Formaldehyde Value + tvoc: + name: SM300D2 TVOC Value + pm_2_5: + name: SM300D2 PM2.5 Value + pm_10_0: + name: SM300D2 PM10 Value + temperature: + name: SM300D2 Temperature Value + humidity: + name: SM300D2 Humidity Value + update_interval: 60s diff --git a/tests/components/sm300d2/test.esp32.yaml b/tests/components/sm300d2/test.esp32.yaml new file mode 100644 index 0000000000..92dba4fb3b --- /dev/null +++ b/tests/components/sm300d2/test.esp32.yaml @@ -0,0 +1,23 @@ +uart: + - id: uart_sm300d2 + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +sensor: + - platform: sm300d2 + co2: + name: SM300D2 CO2 Value + formaldehyde: + name: SM300D2 Formaldehyde Value + tvoc: + name: SM300D2 TVOC Value + pm_2_5: + name: SM300D2 PM2.5 Value + pm_10_0: + name: SM300D2 PM10 Value + temperature: + name: SM300D2 Temperature Value + humidity: + name: SM300D2 Humidity Value + update_interval: 60s diff --git a/tests/components/sm300d2/test.esp8266.yaml b/tests/components/sm300d2/test.esp8266.yaml new file mode 100644 index 0000000000..bcd0a728b2 --- /dev/null +++ b/tests/components/sm300d2/test.esp8266.yaml @@ -0,0 +1,23 @@ +uart: + - id: uart_sm300d2 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sensor: + - platform: sm300d2 + co2: + name: SM300D2 CO2 Value + formaldehyde: + name: SM300D2 Formaldehyde Value + tvoc: + name: SM300D2 TVOC Value + pm_2_5: + name: SM300D2 PM2.5 Value + pm_10_0: + name: SM300D2 PM10 Value + temperature: + name: SM300D2 Temperature Value + humidity: + name: SM300D2 Humidity Value + update_interval: 60s diff --git a/tests/components/sm300d2/test.rp2040.yaml b/tests/components/sm300d2/test.rp2040.yaml new file mode 100644 index 0000000000..bcd0a728b2 --- /dev/null +++ b/tests/components/sm300d2/test.rp2040.yaml @@ -0,0 +1,23 @@ +uart: + - id: uart_sm300d2 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sensor: + - platform: sm300d2 + co2: + name: SM300D2 CO2 Value + formaldehyde: + name: SM300D2 Formaldehyde Value + tvoc: + name: SM300D2 TVOC Value + pm_2_5: + name: SM300D2 PM2.5 Value + pm_10_0: + name: SM300D2 PM10 Value + temperature: + name: SM300D2 Temperature Value + humidity: + name: SM300D2 Humidity Value + update_interval: 60s diff --git a/tests/components/sml/test.esp32-c3-idf.yaml b/tests/components/sml/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..903f968c26 --- /dev/null +++ b/tests/components/sml/test.esp32-c3-idf.yaml @@ -0,0 +1,31 @@ +uart: + - id: uart_sml + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sml: + id: mysml + on_data: + - logger.log: "SML on_data" + +sensor: + - platform: sml + name: Total energy + sml_id: mysml + server_id: 0123456789abcdef + obis_code: "1-0:1.8.0" + unit_of_measurement: kWh + accuracy_decimals: 1 + device_class: energy + state_class: total_increasing + filters: + - multiply: 0.0001 + +text_sensor: + - platform: sml + name: Manufacturer + sml_id: mysml + server_id: 0123456789abcdef + obis_code: "129-129:199.130.3" + format: text diff --git a/tests/components/sml/test.esp32-c3.yaml b/tests/components/sml/test.esp32-c3.yaml new file mode 100644 index 0000000000..903f968c26 --- /dev/null +++ b/tests/components/sml/test.esp32-c3.yaml @@ -0,0 +1,31 @@ +uart: + - id: uart_sml + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sml: + id: mysml + on_data: + - logger.log: "SML on_data" + +sensor: + - platform: sml + name: Total energy + sml_id: mysml + server_id: 0123456789abcdef + obis_code: "1-0:1.8.0" + unit_of_measurement: kWh + accuracy_decimals: 1 + device_class: energy + state_class: total_increasing + filters: + - multiply: 0.0001 + +text_sensor: + - platform: sml + name: Manufacturer + sml_id: mysml + server_id: 0123456789abcdef + obis_code: "129-129:199.130.3" + format: text diff --git a/tests/components/sml/test.esp32-idf.yaml b/tests/components/sml/test.esp32-idf.yaml new file mode 100644 index 0000000000..7217199380 --- /dev/null +++ b/tests/components/sml/test.esp32-idf.yaml @@ -0,0 +1,31 @@ +uart: + - id: uart_sml + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +sml: + id: mysml + on_data: + - logger.log: "SML on_data" + +sensor: + - platform: sml + name: Total energy + sml_id: mysml + server_id: 0123456789abcdef + obis_code: "1-0:1.8.0" + unit_of_measurement: kWh + accuracy_decimals: 1 + device_class: energy + state_class: total_increasing + filters: + - multiply: 0.0001 + +text_sensor: + - platform: sml + name: Manufacturer + sml_id: mysml + server_id: 0123456789abcdef + obis_code: "129-129:199.130.3" + format: text diff --git a/tests/components/sml/test.esp32.yaml b/tests/components/sml/test.esp32.yaml new file mode 100644 index 0000000000..7217199380 --- /dev/null +++ b/tests/components/sml/test.esp32.yaml @@ -0,0 +1,31 @@ +uart: + - id: uart_sml + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +sml: + id: mysml + on_data: + - logger.log: "SML on_data" + +sensor: + - platform: sml + name: Total energy + sml_id: mysml + server_id: 0123456789abcdef + obis_code: "1-0:1.8.0" + unit_of_measurement: kWh + accuracy_decimals: 1 + device_class: energy + state_class: total_increasing + filters: + - multiply: 0.0001 + +text_sensor: + - platform: sml + name: Manufacturer + sml_id: mysml + server_id: 0123456789abcdef + obis_code: "129-129:199.130.3" + format: text diff --git a/tests/components/sml/test.esp8266.yaml b/tests/components/sml/test.esp8266.yaml new file mode 100644 index 0000000000..903f968c26 --- /dev/null +++ b/tests/components/sml/test.esp8266.yaml @@ -0,0 +1,31 @@ +uart: + - id: uart_sml + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sml: + id: mysml + on_data: + - logger.log: "SML on_data" + +sensor: + - platform: sml + name: Total energy + sml_id: mysml + server_id: 0123456789abcdef + obis_code: "1-0:1.8.0" + unit_of_measurement: kWh + accuracy_decimals: 1 + device_class: energy + state_class: total_increasing + filters: + - multiply: 0.0001 + +text_sensor: + - platform: sml + name: Manufacturer + sml_id: mysml + server_id: 0123456789abcdef + obis_code: "129-129:199.130.3" + format: text diff --git a/tests/components/sml/test.rp2040.yaml b/tests/components/sml/test.rp2040.yaml new file mode 100644 index 0000000000..903f968c26 --- /dev/null +++ b/tests/components/sml/test.rp2040.yaml @@ -0,0 +1,31 @@ +uart: + - id: uart_sml + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sml: + id: mysml + on_data: + - logger.log: "SML on_data" + +sensor: + - platform: sml + name: Total energy + sml_id: mysml + server_id: 0123456789abcdef + obis_code: "1-0:1.8.0" + unit_of_measurement: kWh + accuracy_decimals: 1 + device_class: energy + state_class: total_increasing + filters: + - multiply: 0.0001 + +text_sensor: + - platform: sml + name: Manufacturer + sml_id: mysml + server_id: 0123456789abcdef + obis_code: "129-129:199.130.3" + format: text diff --git a/tests/components/smt100/test.esp32-c3-idf.yaml b/tests/components/smt100/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..4277f2567b --- /dev/null +++ b/tests/components/smt100/test.esp32-c3-idf.yaml @@ -0,0 +1,19 @@ +uart: + - id: uart_smt100 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sensor: + - platform: smt100 + counts: + name: Counts + dielectric_constant: + name: Dielectric Constant + temperature: + name: Temperature + moisture: + name: Moisture + voltage: + name: Voltage + update_interval: 60s diff --git a/tests/components/smt100/test.esp32-c3.yaml b/tests/components/smt100/test.esp32-c3.yaml new file mode 100644 index 0000000000..4277f2567b --- /dev/null +++ b/tests/components/smt100/test.esp32-c3.yaml @@ -0,0 +1,19 @@ +uart: + - id: uart_smt100 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sensor: + - platform: smt100 + counts: + name: Counts + dielectric_constant: + name: Dielectric Constant + temperature: + name: Temperature + moisture: + name: Moisture + voltage: + name: Voltage + update_interval: 60s diff --git a/tests/components/smt100/test.esp32-idf.yaml b/tests/components/smt100/test.esp32-idf.yaml new file mode 100644 index 0000000000..7c19f4bc45 --- /dev/null +++ b/tests/components/smt100/test.esp32-idf.yaml @@ -0,0 +1,19 @@ +uart: + - id: uart_smt100 + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +sensor: + - platform: smt100 + counts: + name: Counts + dielectric_constant: + name: Dielectric Constant + temperature: + name: Temperature + moisture: + name: Moisture + voltage: + name: Voltage + update_interval: 60s diff --git a/tests/components/smt100/test.esp32.yaml b/tests/components/smt100/test.esp32.yaml new file mode 100644 index 0000000000..7c19f4bc45 --- /dev/null +++ b/tests/components/smt100/test.esp32.yaml @@ -0,0 +1,19 @@ +uart: + - id: uart_smt100 + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +sensor: + - platform: smt100 + counts: + name: Counts + dielectric_constant: + name: Dielectric Constant + temperature: + name: Temperature + moisture: + name: Moisture + voltage: + name: Voltage + update_interval: 60s diff --git a/tests/components/smt100/test.esp8266.yaml b/tests/components/smt100/test.esp8266.yaml new file mode 100644 index 0000000000..4277f2567b --- /dev/null +++ b/tests/components/smt100/test.esp8266.yaml @@ -0,0 +1,19 @@ +uart: + - id: uart_smt100 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sensor: + - platform: smt100 + counts: + name: Counts + dielectric_constant: + name: Dielectric Constant + temperature: + name: Temperature + moisture: + name: Moisture + voltage: + name: Voltage + update_interval: 60s diff --git a/tests/components/smt100/test.rp2040.yaml b/tests/components/smt100/test.rp2040.yaml new file mode 100644 index 0000000000..4277f2567b --- /dev/null +++ b/tests/components/smt100/test.rp2040.yaml @@ -0,0 +1,19 @@ +uart: + - id: uart_smt100 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +sensor: + - platform: smt100 + counts: + name: Counts + dielectric_constant: + name: Dielectric Constant + temperature: + name: Temperature + moisture: + name: Moisture + voltage: + name: Voltage + update_interval: 60s From 06829b53fe134cb74a06afd00d618c85cc189052 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Tue, 23 Apr 2024 14:40:20 -0500 Subject: [PATCH 1314/2101] Add some components to the new testing framework (S part 2) (#6227) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- .../sn74hc165/test.esp32-c3-idf.yaml | 14 ++++ tests/components/sn74hc165/test.esp32-c3.yaml | 14 ++++ .../components/sn74hc165/test.esp32-idf.yaml | 14 ++++ tests/components/sn74hc165/test.esp32.yaml | 14 ++++ tests/components/sn74hc165/test.esp8266.yaml | 14 ++++ tests/components/sn74hc165/test.rp2040.yaml | 14 ++++ tests/components/sntp/test.esp32-c3-idf.yaml | 15 ++++ tests/components/sntp/test.esp32-c3.yaml | 15 ++++ tests/components/sntp/test.esp32-idf.yaml | 15 ++++ tests/components/sntp/test.esp32.yaml | 15 ++++ tests/components/sntp/test.esp8266.yaml | 15 ++++ tests/components/sntp/test.rp2040.yaml | 15 ++++ .../components/sonoff_d1/test.esp32-idf.yaml | 12 +++ tests/components/sonoff_d1/test.esp32.yaml | 12 +++ tests/components/sonoff_d1/test.esp8266.yaml | 12 +++ .../components/speaker/test.esp32-c3-idf.yaml | 17 ++++ tests/components/speaker/test.esp32-c3.yaml | 17 ++++ tests/components/speaker/test.esp32-idf.yaml | 17 ++++ tests/components/speaker/test.esp32.yaml | 17 ++++ tests/components/speed/test.esp32-c3-idf.yaml | 9 ++ tests/components/speed/test.esp32-c3.yaml | 9 ++ tests/components/speed/test.esp32-idf.yaml | 9 ++ tests/components/speed/test.esp32.yaml | 9 ++ tests/components/speed/test.esp8266.yaml | 9 ++ tests/components/speed/test.rp2040.yaml | 9 ++ tests/components/spi/test.esp32-c3-idf.yaml | 5 ++ tests/components/spi/test.esp32-c3.yaml | 5 ++ tests/components/spi/test.esp32-idf.yaml | 5 ++ tests/components/spi/test.esp32.yaml | 5 ++ tests/components/spi/test.esp8266.yaml | 5 ++ tests/components/spi/test.rp2040.yaml | 5 ++ .../spi_device/test.esp32-c3-idf.yaml | 11 +++ .../components/spi_device/test.esp32-c3.yaml | 11 +++ .../components/spi_device/test.esp32-idf.yaml | 11 +++ tests/components/spi_device/test.esp32.yaml | 11 +++ tests/components/spi_device/test.esp8266.yaml | 11 +++ tests/components/spi_device/test.rp2040.yaml | 11 +++ .../spi_led_strip/test.esp32-c3-idf.yaml | 13 +++ .../spi_led_strip/test.esp32-c3.yaml | 13 +++ .../spi_led_strip/test.esp32-idf.yaml | 13 +++ .../components/spi_led_strip/test.esp32.yaml | 13 +++ .../spi_led_strip/test.esp8266.yaml | 13 +++ .../components/spi_led_strip/test.rp2040.yaml | 13 +++ .../sprinkler/test.esp32-c3-idf.yaml | 83 +++++++++++++++++++ tests/components/sprinkler/test.esp32-c3.yaml | 83 +++++++++++++++++++ .../components/sprinkler/test.esp32-idf.yaml | 83 +++++++++++++++++++ tests/components/sprinkler/test.esp32.yaml | 83 +++++++++++++++++++ tests/components/sprinkler/test.esp8266.yaml | 83 +++++++++++++++++++ tests/components/sprinkler/test.rp2040.yaml | 83 +++++++++++++++++++ tests/components/sps30/test.esp32-c3-idf.yaml | 36 ++++++++ tests/components/sps30/test.esp32-c3.yaml | 36 ++++++++ tests/components/sps30/test.esp32-idf.yaml | 36 ++++++++ tests/components/sps30/test.esp32.yaml | 36 ++++++++ tests/components/sps30/test.esp8266.yaml | 36 ++++++++ tests/components/sps30/test.rp2040.yaml | 36 ++++++++ .../ssd1306_i2c/test.esp32-c3-idf.yaml | 25 ++++++ .../components/ssd1306_i2c/test.esp32-c3.yaml | 25 ++++++ .../ssd1306_i2c/test.esp32-idf.yaml | 25 ++++++ tests/components/ssd1306_i2c/test.esp32.yaml | 25 ++++++ .../components/ssd1306_i2c/test.esp8266.yaml | 25 ++++++ tests/components/ssd1306_i2c/test.rp2040.yaml | 25 ++++++ .../ssd1306_spi/test.esp32-c3-idf.yaml | 25 ++++++ .../components/ssd1306_spi/test.esp32-c3.yaml | 25 ++++++ .../ssd1306_spi/test.esp32-idf.yaml | 25 ++++++ tests/components/ssd1306_spi/test.esp32.yaml | 25 ++++++ .../components/ssd1306_spi/test.esp8266.yaml | 25 ++++++ tests/components/ssd1306_spi/test.rp2040.yaml | 25 ++++++ .../ssd1322_spi/test.esp32-c3-idf.yaml | 25 ++++++ .../components/ssd1322_spi/test.esp32-c3.yaml | 25 ++++++ .../ssd1322_spi/test.esp32-idf.yaml | 25 ++++++ tests/components/ssd1322_spi/test.esp32.yaml | 25 ++++++ .../components/ssd1322_spi/test.esp8266.yaml | 25 ++++++ tests/components/ssd1322_spi/test.rp2040.yaml | 25 ++++++ .../ssd1325_spi/test.esp32-c3-idf.yaml | 25 ++++++ .../components/ssd1325_spi/test.esp32-c3.yaml | 25 ++++++ .../ssd1325_spi/test.esp32-idf.yaml | 25 ++++++ tests/components/ssd1325_spi/test.esp32.yaml | 25 ++++++ .../components/ssd1325_spi/test.esp8266.yaml | 25 ++++++ tests/components/ssd1325_spi/test.rp2040.yaml | 25 ++++++ .../ssd1327_i2c/test.esp32-c3-idf.yaml | 24 ++++++ .../components/ssd1327_i2c/test.esp32-c3.yaml | 24 ++++++ .../ssd1327_i2c/test.esp32-idf.yaml | 24 ++++++ tests/components/ssd1327_i2c/test.esp32.yaml | 24 ++++++ .../components/ssd1327_i2c/test.esp8266.yaml | 24 ++++++ tests/components/ssd1327_i2c/test.rp2040.yaml | 24 ++++++ .../ssd1327_spi/test.esp32-c3-idf.yaml | 25 ++++++ .../components/ssd1327_spi/test.esp32-c3.yaml | 25 ++++++ .../ssd1327_spi/test.esp32-idf.yaml | 25 ++++++ tests/components/ssd1327_spi/test.esp32.yaml | 25 ++++++ .../components/ssd1327_spi/test.esp8266.yaml | 25 ++++++ tests/components/ssd1327_spi/test.rp2040.yaml | 25 ++++++ .../ssd1331_spi/test.esp32-c3-idf.yaml | 24 ++++++ .../components/ssd1331_spi/test.esp32-c3.yaml | 24 ++++++ .../ssd1331_spi/test.esp32-idf.yaml | 24 ++++++ tests/components/ssd1331_spi/test.esp32.yaml | 24 ++++++ .../components/ssd1331_spi/test.esp8266.yaml | 24 ++++++ tests/components/ssd1331_spi/test.rp2040.yaml | 24 ++++++ .../ssd1351_spi/test.esp32-c3-idf.yaml | 25 ++++++ .../components/ssd1351_spi/test.esp32-c3.yaml | 25 ++++++ .../ssd1351_spi/test.esp32-idf.yaml | 25 ++++++ tests/components/ssd1351_spi/test.esp32.yaml | 25 ++++++ .../components/ssd1351_spi/test.esp8266.yaml | 25 ++++++ tests/components/ssd1351_spi/test.rp2040.yaml | 25 ++++++ .../st7567_i2c/test.esp32-c3-idf.yaml | 23 +++++ .../components/st7567_i2c/test.esp32-c3.yaml | 23 +++++ .../components/st7567_i2c/test.esp32-idf.yaml | 23 +++++ tests/components/st7567_i2c/test.esp32.yaml | 23 +++++ tests/components/st7567_i2c/test.esp8266.yaml | 23 +++++ tests/components/st7567_i2c/test.rp2040.yaml | 23 +++++ .../st7567_spi/test.esp32-c3-idf.yaml | 24 ++++++ .../components/st7567_spi/test.esp32-c3.yaml | 24 ++++++ .../components/st7567_spi/test.esp32-idf.yaml | 24 ++++++ tests/components/st7567_spi/test.esp32.yaml | 24 ++++++ tests/components/st7567_spi/test.esp8266.yaml | 24 ++++++ tests/components/st7567_spi/test.rp2040.yaml | 24 ++++++ .../components/st7735/test.esp32-c3-idf.yaml | 29 +++++++ tests/components/st7735/test.esp32-c3.yaml | 29 +++++++ tests/components/st7735/test.esp32-idf.yaml | 29 +++++++ tests/components/st7735/test.esp32.yaml | 29 +++++++ tests/components/st7735/test.esp8266.yaml | 29 +++++++ tests/components/st7735/test.rp2040.yaml | 29 +++++++ .../components/st7789v/test.esp32-c3-idf.yaml | 25 ++++++ tests/components/st7789v/test.esp32-c3.yaml | 25 ++++++ tests/components/st7789v/test.esp32-idf.yaml | 25 ++++++ tests/components/st7789v/test.esp32.yaml | 25 ++++++ tests/components/st7789v/test.esp8266.yaml | 25 ++++++ tests/components/st7789v/test.rp2040.yaml | 25 ++++++ .../components/st7920/test.esp32-c3-idf.yaml | 24 ++++++ tests/components/st7920/test.esp32-c3.yaml | 24 ++++++ tests/components/st7920/test.esp32-idf.yaml | 24 ++++++ tests/components/st7920/test.esp32.yaml | 24 ++++++ tests/components/st7920/test.esp8266.yaml | 24 ++++++ tests/components/st7920/test.rp2040.yaml | 24 ++++++ .../components/status/test.esp32-c3-idf.yaml | 10 +++ tests/components/status/test.esp32-c3.yaml | 10 +++ tests/components/status/test.esp32-idf.yaml | 10 +++ tests/components/status/test.esp32.yaml | 10 +++ tests/components/status/test.esp8266.yaml | 10 +++ tests/components/status/test.rp2040.yaml | 10 +++ .../status_led/test.esp32-c3-idf.yaml | 10 +++ .../components/status_led/test.esp32-c3.yaml | 10 +++ .../components/status_led/test.esp32-idf.yaml | 10 +++ tests/components/status_led/test.esp32.yaml | 10 +++ tests/components/status_led/test.esp8266.yaml | 10 +++ tests/components/status_led/test.rp2040.yaml | 10 +++ .../components/stepper/test.esp32-c3-idf.yaml | 27 ++++++ tests/components/stepper/test.esp32-c3.yaml | 27 ++++++ tests/components/stepper/test.esp32-idf.yaml | 27 ++++++ tests/components/stepper/test.esp32.yaml | 27 ++++++ tests/components/stepper/test.esp8266.yaml | 27 ++++++ tests/components/stepper/test.rp2040.yaml | 27 ++++++ tests/components/sts3x/test.esp32-c3-idf.yaml | 10 +++ tests/components/sts3x/test.esp32-c3.yaml | 10 +++ tests/components/sts3x/test.esp32-idf.yaml | 10 +++ tests/components/sts3x/test.esp32.yaml | 10 +++ tests/components/sts3x/test.esp8266.yaml | 10 +++ tests/components/sts3x/test.rp2040.yaml | 10 +++ tests/components/sun/test.esp32-c3-idf.yaml | 38 +++++++++ tests/components/sun/test.esp32-c3.yaml | 38 +++++++++ tests/components/sun/test.esp32-idf.yaml | 38 +++++++++ tests/components/sun/test.esp32.yaml | 38 +++++++++ tests/components/sun/test.esp8266.yaml | 38 +++++++++ tests/components/sun/test.rp2040.yaml | 38 +++++++++ .../components/sx1509/test.esp32-c3-idf.yaml | 15 ++++ tests/components/sx1509/test.esp32-c3.yaml | 15 ++++ tests/components/sx1509/test.esp32-idf.yaml | 15 ++++ tests/components/sx1509/test.esp32.yaml | 15 ++++ tests/components/sx1509/test.esp8266.yaml | 15 ++++ tests/components/sx1509/test.rp2040.yaml | 15 ++++ 169 files changed, 3818 insertions(+) create mode 100644 tests/components/sn74hc165/test.esp32-c3-idf.yaml create mode 100644 tests/components/sn74hc165/test.esp32-c3.yaml create mode 100644 tests/components/sn74hc165/test.esp32-idf.yaml create mode 100644 tests/components/sn74hc165/test.esp32.yaml create mode 100644 tests/components/sn74hc165/test.esp8266.yaml create mode 100644 tests/components/sn74hc165/test.rp2040.yaml create mode 100644 tests/components/sntp/test.esp32-c3-idf.yaml create mode 100644 tests/components/sntp/test.esp32-c3.yaml create mode 100644 tests/components/sntp/test.esp32-idf.yaml create mode 100644 tests/components/sntp/test.esp32.yaml create mode 100644 tests/components/sntp/test.esp8266.yaml create mode 100644 tests/components/sntp/test.rp2040.yaml create mode 100644 tests/components/sonoff_d1/test.esp32-idf.yaml create mode 100644 tests/components/sonoff_d1/test.esp32.yaml create mode 100644 tests/components/sonoff_d1/test.esp8266.yaml create mode 100644 tests/components/speaker/test.esp32-c3-idf.yaml create mode 100644 tests/components/speaker/test.esp32-c3.yaml create mode 100644 tests/components/speaker/test.esp32-idf.yaml create mode 100644 tests/components/speaker/test.esp32.yaml create mode 100644 tests/components/speed/test.esp32-c3-idf.yaml create mode 100644 tests/components/speed/test.esp32-c3.yaml create mode 100644 tests/components/speed/test.esp32-idf.yaml create mode 100644 tests/components/speed/test.esp32.yaml create mode 100644 tests/components/speed/test.esp8266.yaml create mode 100644 tests/components/speed/test.rp2040.yaml create mode 100644 tests/components/spi/test.esp32-c3-idf.yaml create mode 100644 tests/components/spi/test.esp32-c3.yaml create mode 100644 tests/components/spi/test.esp32-idf.yaml create mode 100644 tests/components/spi/test.esp32.yaml create mode 100644 tests/components/spi/test.esp8266.yaml create mode 100644 tests/components/spi/test.rp2040.yaml create mode 100644 tests/components/spi_device/test.esp32-c3-idf.yaml create mode 100644 tests/components/spi_device/test.esp32-c3.yaml create mode 100644 tests/components/spi_device/test.esp32-idf.yaml create mode 100644 tests/components/spi_device/test.esp32.yaml create mode 100644 tests/components/spi_device/test.esp8266.yaml create mode 100644 tests/components/spi_device/test.rp2040.yaml create mode 100644 tests/components/spi_led_strip/test.esp32-c3-idf.yaml create mode 100644 tests/components/spi_led_strip/test.esp32-c3.yaml create mode 100644 tests/components/spi_led_strip/test.esp32-idf.yaml create mode 100644 tests/components/spi_led_strip/test.esp32.yaml create mode 100644 tests/components/spi_led_strip/test.esp8266.yaml create mode 100644 tests/components/spi_led_strip/test.rp2040.yaml create mode 100644 tests/components/sprinkler/test.esp32-c3-idf.yaml create mode 100644 tests/components/sprinkler/test.esp32-c3.yaml create mode 100644 tests/components/sprinkler/test.esp32-idf.yaml create mode 100644 tests/components/sprinkler/test.esp32.yaml create mode 100644 tests/components/sprinkler/test.esp8266.yaml create mode 100644 tests/components/sprinkler/test.rp2040.yaml create mode 100644 tests/components/sps30/test.esp32-c3-idf.yaml create mode 100644 tests/components/sps30/test.esp32-c3.yaml create mode 100644 tests/components/sps30/test.esp32-idf.yaml create mode 100644 tests/components/sps30/test.esp32.yaml create mode 100644 tests/components/sps30/test.esp8266.yaml create mode 100644 tests/components/sps30/test.rp2040.yaml create mode 100644 tests/components/ssd1306_i2c/test.esp32-c3-idf.yaml create mode 100644 tests/components/ssd1306_i2c/test.esp32-c3.yaml create mode 100644 tests/components/ssd1306_i2c/test.esp32-idf.yaml create mode 100644 tests/components/ssd1306_i2c/test.esp32.yaml create mode 100644 tests/components/ssd1306_i2c/test.esp8266.yaml create mode 100644 tests/components/ssd1306_i2c/test.rp2040.yaml create mode 100644 tests/components/ssd1306_spi/test.esp32-c3-idf.yaml create mode 100644 tests/components/ssd1306_spi/test.esp32-c3.yaml create mode 100644 tests/components/ssd1306_spi/test.esp32-idf.yaml create mode 100644 tests/components/ssd1306_spi/test.esp32.yaml create mode 100644 tests/components/ssd1306_spi/test.esp8266.yaml create mode 100644 tests/components/ssd1306_spi/test.rp2040.yaml create mode 100644 tests/components/ssd1322_spi/test.esp32-c3-idf.yaml create mode 100644 tests/components/ssd1322_spi/test.esp32-c3.yaml create mode 100644 tests/components/ssd1322_spi/test.esp32-idf.yaml create mode 100644 tests/components/ssd1322_spi/test.esp32.yaml create mode 100644 tests/components/ssd1322_spi/test.esp8266.yaml create mode 100644 tests/components/ssd1322_spi/test.rp2040.yaml create mode 100644 tests/components/ssd1325_spi/test.esp32-c3-idf.yaml create mode 100644 tests/components/ssd1325_spi/test.esp32-c3.yaml create mode 100644 tests/components/ssd1325_spi/test.esp32-idf.yaml create mode 100644 tests/components/ssd1325_spi/test.esp32.yaml create mode 100644 tests/components/ssd1325_spi/test.esp8266.yaml create mode 100644 tests/components/ssd1325_spi/test.rp2040.yaml create mode 100644 tests/components/ssd1327_i2c/test.esp32-c3-idf.yaml create mode 100644 tests/components/ssd1327_i2c/test.esp32-c3.yaml create mode 100644 tests/components/ssd1327_i2c/test.esp32-idf.yaml create mode 100644 tests/components/ssd1327_i2c/test.esp32.yaml create mode 100644 tests/components/ssd1327_i2c/test.esp8266.yaml create mode 100644 tests/components/ssd1327_i2c/test.rp2040.yaml create mode 100644 tests/components/ssd1327_spi/test.esp32-c3-idf.yaml create mode 100644 tests/components/ssd1327_spi/test.esp32-c3.yaml create mode 100644 tests/components/ssd1327_spi/test.esp32-idf.yaml create mode 100644 tests/components/ssd1327_spi/test.esp32.yaml create mode 100644 tests/components/ssd1327_spi/test.esp8266.yaml create mode 100644 tests/components/ssd1327_spi/test.rp2040.yaml create mode 100644 tests/components/ssd1331_spi/test.esp32-c3-idf.yaml create mode 100644 tests/components/ssd1331_spi/test.esp32-c3.yaml create mode 100644 tests/components/ssd1331_spi/test.esp32-idf.yaml create mode 100644 tests/components/ssd1331_spi/test.esp32.yaml create mode 100644 tests/components/ssd1331_spi/test.esp8266.yaml create mode 100644 tests/components/ssd1331_spi/test.rp2040.yaml create mode 100644 tests/components/ssd1351_spi/test.esp32-c3-idf.yaml create mode 100644 tests/components/ssd1351_spi/test.esp32-c3.yaml create mode 100644 tests/components/ssd1351_spi/test.esp32-idf.yaml create mode 100644 tests/components/ssd1351_spi/test.esp32.yaml create mode 100644 tests/components/ssd1351_spi/test.esp8266.yaml create mode 100644 tests/components/ssd1351_spi/test.rp2040.yaml create mode 100644 tests/components/st7567_i2c/test.esp32-c3-idf.yaml create mode 100644 tests/components/st7567_i2c/test.esp32-c3.yaml create mode 100644 tests/components/st7567_i2c/test.esp32-idf.yaml create mode 100644 tests/components/st7567_i2c/test.esp32.yaml create mode 100644 tests/components/st7567_i2c/test.esp8266.yaml create mode 100644 tests/components/st7567_i2c/test.rp2040.yaml create mode 100644 tests/components/st7567_spi/test.esp32-c3-idf.yaml create mode 100644 tests/components/st7567_spi/test.esp32-c3.yaml create mode 100644 tests/components/st7567_spi/test.esp32-idf.yaml create mode 100644 tests/components/st7567_spi/test.esp32.yaml create mode 100644 tests/components/st7567_spi/test.esp8266.yaml create mode 100644 tests/components/st7567_spi/test.rp2040.yaml create mode 100644 tests/components/st7735/test.esp32-c3-idf.yaml create mode 100644 tests/components/st7735/test.esp32-c3.yaml create mode 100644 tests/components/st7735/test.esp32-idf.yaml create mode 100644 tests/components/st7735/test.esp32.yaml create mode 100644 tests/components/st7735/test.esp8266.yaml create mode 100644 tests/components/st7735/test.rp2040.yaml create mode 100644 tests/components/st7789v/test.esp32-c3-idf.yaml create mode 100644 tests/components/st7789v/test.esp32-c3.yaml create mode 100644 tests/components/st7789v/test.esp32-idf.yaml create mode 100644 tests/components/st7789v/test.esp32.yaml create mode 100644 tests/components/st7789v/test.esp8266.yaml create mode 100644 tests/components/st7789v/test.rp2040.yaml create mode 100644 tests/components/st7920/test.esp32-c3-idf.yaml create mode 100644 tests/components/st7920/test.esp32-c3.yaml create mode 100644 tests/components/st7920/test.esp32-idf.yaml create mode 100644 tests/components/st7920/test.esp32.yaml create mode 100644 tests/components/st7920/test.esp8266.yaml create mode 100644 tests/components/st7920/test.rp2040.yaml create mode 100644 tests/components/status/test.esp32-c3-idf.yaml create mode 100644 tests/components/status/test.esp32-c3.yaml create mode 100644 tests/components/status/test.esp32-idf.yaml create mode 100644 tests/components/status/test.esp32.yaml create mode 100644 tests/components/status/test.esp8266.yaml create mode 100644 tests/components/status/test.rp2040.yaml create mode 100644 tests/components/status_led/test.esp32-c3-idf.yaml create mode 100644 tests/components/status_led/test.esp32-c3.yaml create mode 100644 tests/components/status_led/test.esp32-idf.yaml create mode 100644 tests/components/status_led/test.esp32.yaml create mode 100644 tests/components/status_led/test.esp8266.yaml create mode 100644 tests/components/status_led/test.rp2040.yaml create mode 100644 tests/components/stepper/test.esp32-c3-idf.yaml create mode 100644 tests/components/stepper/test.esp32-c3.yaml create mode 100644 tests/components/stepper/test.esp32-idf.yaml create mode 100644 tests/components/stepper/test.esp32.yaml create mode 100644 tests/components/stepper/test.esp8266.yaml create mode 100644 tests/components/stepper/test.rp2040.yaml create mode 100644 tests/components/sts3x/test.esp32-c3-idf.yaml create mode 100644 tests/components/sts3x/test.esp32-c3.yaml create mode 100644 tests/components/sts3x/test.esp32-idf.yaml create mode 100644 tests/components/sts3x/test.esp32.yaml create mode 100644 tests/components/sts3x/test.esp8266.yaml create mode 100644 tests/components/sts3x/test.rp2040.yaml create mode 100644 tests/components/sun/test.esp32-c3-idf.yaml create mode 100644 tests/components/sun/test.esp32-c3.yaml create mode 100644 tests/components/sun/test.esp32-idf.yaml create mode 100644 tests/components/sun/test.esp32.yaml create mode 100644 tests/components/sun/test.esp8266.yaml create mode 100644 tests/components/sun/test.rp2040.yaml create mode 100644 tests/components/sx1509/test.esp32-c3-idf.yaml create mode 100644 tests/components/sx1509/test.esp32-c3.yaml create mode 100644 tests/components/sx1509/test.esp32-idf.yaml create mode 100644 tests/components/sx1509/test.esp32.yaml create mode 100644 tests/components/sx1509/test.esp8266.yaml create mode 100644 tests/components/sx1509/test.rp2040.yaml diff --git a/tests/components/sn74hc165/test.esp32-c3-idf.yaml b/tests/components/sn74hc165/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..f687b23c9d --- /dev/null +++ b/tests/components/sn74hc165/test.esp32-c3-idf.yaml @@ -0,0 +1,14 @@ +sn74hc165: + id: sn74hc165_hub + clock_pin: 3 + data_pin: 4 + load_pin: 5 + clock_inhibit_pin: 6 + sr_count: 2 + +binary_sensor: + - platform: gpio + id: sn74hc165_pin_0 + pin: + sn74hc165: sn74hc165_hub + number: 0 diff --git a/tests/components/sn74hc165/test.esp32-c3.yaml b/tests/components/sn74hc165/test.esp32-c3.yaml new file mode 100644 index 0000000000..f687b23c9d --- /dev/null +++ b/tests/components/sn74hc165/test.esp32-c3.yaml @@ -0,0 +1,14 @@ +sn74hc165: + id: sn74hc165_hub + clock_pin: 3 + data_pin: 4 + load_pin: 5 + clock_inhibit_pin: 6 + sr_count: 2 + +binary_sensor: + - platform: gpio + id: sn74hc165_pin_0 + pin: + sn74hc165: sn74hc165_hub + number: 0 diff --git a/tests/components/sn74hc165/test.esp32-idf.yaml b/tests/components/sn74hc165/test.esp32-idf.yaml new file mode 100644 index 0000000000..55b06aec9b --- /dev/null +++ b/tests/components/sn74hc165/test.esp32-idf.yaml @@ -0,0 +1,14 @@ +sn74hc165: + id: sn74hc165_hub + clock_pin: 13 + data_pin: 14 + load_pin: 15 + clock_inhibit_pin: 16 + sr_count: 2 + +binary_sensor: + - platform: gpio + id: sn74hc165_pin_0 + pin: + sn74hc165: sn74hc165_hub + number: 0 diff --git a/tests/components/sn74hc165/test.esp32.yaml b/tests/components/sn74hc165/test.esp32.yaml new file mode 100644 index 0000000000..55b06aec9b --- /dev/null +++ b/tests/components/sn74hc165/test.esp32.yaml @@ -0,0 +1,14 @@ +sn74hc165: + id: sn74hc165_hub + clock_pin: 13 + data_pin: 14 + load_pin: 15 + clock_inhibit_pin: 16 + sr_count: 2 + +binary_sensor: + - platform: gpio + id: sn74hc165_pin_0 + pin: + sn74hc165: sn74hc165_hub + number: 0 diff --git a/tests/components/sn74hc165/test.esp8266.yaml b/tests/components/sn74hc165/test.esp8266.yaml new file mode 100644 index 0000000000..55b06aec9b --- /dev/null +++ b/tests/components/sn74hc165/test.esp8266.yaml @@ -0,0 +1,14 @@ +sn74hc165: + id: sn74hc165_hub + clock_pin: 13 + data_pin: 14 + load_pin: 15 + clock_inhibit_pin: 16 + sr_count: 2 + +binary_sensor: + - platform: gpio + id: sn74hc165_pin_0 + pin: + sn74hc165: sn74hc165_hub + number: 0 diff --git a/tests/components/sn74hc165/test.rp2040.yaml b/tests/components/sn74hc165/test.rp2040.yaml new file mode 100644 index 0000000000..f687b23c9d --- /dev/null +++ b/tests/components/sn74hc165/test.rp2040.yaml @@ -0,0 +1,14 @@ +sn74hc165: + id: sn74hc165_hub + clock_pin: 3 + data_pin: 4 + load_pin: 5 + clock_inhibit_pin: 6 + sr_count: 2 + +binary_sensor: + - platform: gpio + id: sn74hc165_pin_0 + pin: + sn74hc165: sn74hc165_hub + number: 0 diff --git a/tests/components/sntp/test.esp32-c3-idf.yaml b/tests/components/sntp/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..3e9e465296 --- /dev/null +++ b/tests/components/sntp/test.esp32-c3-idf.yaml @@ -0,0 +1,15 @@ +wifi: + ssid: MySSID + password: password1 + +time: + - platform: sntp + id: sntp_time + servers: + - 0.pool.ntp.org + - 1.pool.ntp.org + - 192.168.178.1 + on_time: + cron: "/30 0-30,30/5 * ? JAN-DEC MON,SAT-SUN,TUE-FRI" + then: + - lambda: 'ESP_LOGD("main", "time");' diff --git a/tests/components/sntp/test.esp32-c3.yaml b/tests/components/sntp/test.esp32-c3.yaml new file mode 100644 index 0000000000..3e9e465296 --- /dev/null +++ b/tests/components/sntp/test.esp32-c3.yaml @@ -0,0 +1,15 @@ +wifi: + ssid: MySSID + password: password1 + +time: + - platform: sntp + id: sntp_time + servers: + - 0.pool.ntp.org + - 1.pool.ntp.org + - 192.168.178.1 + on_time: + cron: "/30 0-30,30/5 * ? JAN-DEC MON,SAT-SUN,TUE-FRI" + then: + - lambda: 'ESP_LOGD("main", "time");' diff --git a/tests/components/sntp/test.esp32-idf.yaml b/tests/components/sntp/test.esp32-idf.yaml new file mode 100644 index 0000000000..3e9e465296 --- /dev/null +++ b/tests/components/sntp/test.esp32-idf.yaml @@ -0,0 +1,15 @@ +wifi: + ssid: MySSID + password: password1 + +time: + - platform: sntp + id: sntp_time + servers: + - 0.pool.ntp.org + - 1.pool.ntp.org + - 192.168.178.1 + on_time: + cron: "/30 0-30,30/5 * ? JAN-DEC MON,SAT-SUN,TUE-FRI" + then: + - lambda: 'ESP_LOGD("main", "time");' diff --git a/tests/components/sntp/test.esp32.yaml b/tests/components/sntp/test.esp32.yaml new file mode 100644 index 0000000000..3e9e465296 --- /dev/null +++ b/tests/components/sntp/test.esp32.yaml @@ -0,0 +1,15 @@ +wifi: + ssid: MySSID + password: password1 + +time: + - platform: sntp + id: sntp_time + servers: + - 0.pool.ntp.org + - 1.pool.ntp.org + - 192.168.178.1 + on_time: + cron: "/30 0-30,30/5 * ? JAN-DEC MON,SAT-SUN,TUE-FRI" + then: + - lambda: 'ESP_LOGD("main", "time");' diff --git a/tests/components/sntp/test.esp8266.yaml b/tests/components/sntp/test.esp8266.yaml new file mode 100644 index 0000000000..3e9e465296 --- /dev/null +++ b/tests/components/sntp/test.esp8266.yaml @@ -0,0 +1,15 @@ +wifi: + ssid: MySSID + password: password1 + +time: + - platform: sntp + id: sntp_time + servers: + - 0.pool.ntp.org + - 1.pool.ntp.org + - 192.168.178.1 + on_time: + cron: "/30 0-30,30/5 * ? JAN-DEC MON,SAT-SUN,TUE-FRI" + then: + - lambda: 'ESP_LOGD("main", "time");' diff --git a/tests/components/sntp/test.rp2040.yaml b/tests/components/sntp/test.rp2040.yaml new file mode 100644 index 0000000000..3e9e465296 --- /dev/null +++ b/tests/components/sntp/test.rp2040.yaml @@ -0,0 +1,15 @@ +wifi: + ssid: MySSID + password: password1 + +time: + - platform: sntp + id: sntp_time + servers: + - 0.pool.ntp.org + - 1.pool.ntp.org + - 192.168.178.1 + on_time: + cron: "/30 0-30,30/5 * ? JAN-DEC MON,SAT-SUN,TUE-FRI" + then: + - lambda: 'ESP_LOGD("main", "time");' diff --git a/tests/components/sonoff_d1/test.esp32-idf.yaml b/tests/components/sonoff_d1/test.esp32-idf.yaml new file mode 100644 index 0000000000..dc35e3b6ac --- /dev/null +++ b/tests/components/sonoff_d1/test.esp32-idf.yaml @@ -0,0 +1,12 @@ +uart: + - id: uart_sonoff_d1 + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +light: + - platform: sonoff_d1 + id: d1_light + name: Sonoff D1 Dimmer + restore_mode: RESTORE_DEFAULT_OFF + use_rm433_remote: false diff --git a/tests/components/sonoff_d1/test.esp32.yaml b/tests/components/sonoff_d1/test.esp32.yaml new file mode 100644 index 0000000000..dc35e3b6ac --- /dev/null +++ b/tests/components/sonoff_d1/test.esp32.yaml @@ -0,0 +1,12 @@ +uart: + - id: uart_sonoff_d1 + tx_pin: 17 + rx_pin: 16 + baud_rate: 9600 + +light: + - platform: sonoff_d1 + id: d1_light + name: Sonoff D1 Dimmer + restore_mode: RESTORE_DEFAULT_OFF + use_rm433_remote: false diff --git a/tests/components/sonoff_d1/test.esp8266.yaml b/tests/components/sonoff_d1/test.esp8266.yaml new file mode 100644 index 0000000000..c4a62f4cb3 --- /dev/null +++ b/tests/components/sonoff_d1/test.esp8266.yaml @@ -0,0 +1,12 @@ +uart: + - id: uart_sonoff_d1 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +light: + - platform: sonoff_d1 + id: d1_light + name: Sonoff D1 Dimmer + restore_mode: RESTORE_DEFAULT_OFF + use_rm433_remote: false diff --git a/tests/components/speaker/test.esp32-c3-idf.yaml b/tests/components/speaker/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..c7809baace --- /dev/null +++ b/tests/components/speaker/test.esp32-c3-idf.yaml @@ -0,0 +1,17 @@ +esphome: + on_boot: + then: + - speaker.play: [0, 1, 2, 3] + - speaker.stop + +i2s_audio: + i2s_lrclk_pin: 6 + i2s_bclk_pin: 7 + i2s_mclk_pin: 5 + +speaker: + - platform: i2s_audio + id: speaker_id + dac_type: external + i2s_dout_pin: 3 + mode: mono diff --git a/tests/components/speaker/test.esp32-c3.yaml b/tests/components/speaker/test.esp32-c3.yaml new file mode 100644 index 0000000000..c7809baace --- /dev/null +++ b/tests/components/speaker/test.esp32-c3.yaml @@ -0,0 +1,17 @@ +esphome: + on_boot: + then: + - speaker.play: [0, 1, 2, 3] + - speaker.stop + +i2s_audio: + i2s_lrclk_pin: 6 + i2s_bclk_pin: 7 + i2s_mclk_pin: 5 + +speaker: + - platform: i2s_audio + id: speaker_id + dac_type: external + i2s_dout_pin: 3 + mode: mono diff --git a/tests/components/speaker/test.esp32-idf.yaml b/tests/components/speaker/test.esp32-idf.yaml new file mode 100644 index 0000000000..416e203d7b --- /dev/null +++ b/tests/components/speaker/test.esp32-idf.yaml @@ -0,0 +1,17 @@ +esphome: + on_boot: + then: + - speaker.play: [0, 1, 2, 3] + - speaker.stop + +i2s_audio: + i2s_lrclk_pin: 16 + i2s_bclk_pin: 17 + i2s_mclk_pin: 15 + +speaker: + - platform: i2s_audio + id: speaker_id + dac_type: external + i2s_dout_pin: 13 + mode: mono diff --git a/tests/components/speaker/test.esp32.yaml b/tests/components/speaker/test.esp32.yaml new file mode 100644 index 0000000000..416e203d7b --- /dev/null +++ b/tests/components/speaker/test.esp32.yaml @@ -0,0 +1,17 @@ +esphome: + on_boot: + then: + - speaker.play: [0, 1, 2, 3] + - speaker.stop + +i2s_audio: + i2s_lrclk_pin: 16 + i2s_bclk_pin: 17 + i2s_mclk_pin: 15 + +speaker: + - platform: i2s_audio + id: speaker_id + dac_type: external + i2s_dout_pin: 13 + mode: mono diff --git a/tests/components/speed/test.esp32-c3-idf.yaml b/tests/components/speed/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..fa1920676e --- /dev/null +++ b/tests/components/speed/test.esp32-c3-idf.yaml @@ -0,0 +1,9 @@ +output: + - platform: ledc + id: fan_output_1 + pin: 2 + +fan: + - platform: speed + id: fan_speed + output: fan_output_1 diff --git a/tests/components/speed/test.esp32-c3.yaml b/tests/components/speed/test.esp32-c3.yaml new file mode 100644 index 0000000000..fa1920676e --- /dev/null +++ b/tests/components/speed/test.esp32-c3.yaml @@ -0,0 +1,9 @@ +output: + - platform: ledc + id: fan_output_1 + pin: 2 + +fan: + - platform: speed + id: fan_speed + output: fan_output_1 diff --git a/tests/components/speed/test.esp32-idf.yaml b/tests/components/speed/test.esp32-idf.yaml new file mode 100644 index 0000000000..29a55e9edd --- /dev/null +++ b/tests/components/speed/test.esp32-idf.yaml @@ -0,0 +1,9 @@ +output: + - platform: ledc + id: fan_output_1 + pin: 12 + +fan: + - platform: speed + id: fan_speed + output: fan_output_1 diff --git a/tests/components/speed/test.esp32.yaml b/tests/components/speed/test.esp32.yaml new file mode 100644 index 0000000000..29a55e9edd --- /dev/null +++ b/tests/components/speed/test.esp32.yaml @@ -0,0 +1,9 @@ +output: + - platform: ledc + id: fan_output_1 + pin: 12 + +fan: + - platform: speed + id: fan_speed + output: fan_output_1 diff --git a/tests/components/speed/test.esp8266.yaml b/tests/components/speed/test.esp8266.yaml new file mode 100644 index 0000000000..6ed9949cf5 --- /dev/null +++ b/tests/components/speed/test.esp8266.yaml @@ -0,0 +1,9 @@ +output: + - platform: esp8266_pwm + id: fan_output_1 + pin: 12 + +fan: + - platform: speed + id: fan_speed + output: fan_output_1 diff --git a/tests/components/speed/test.rp2040.yaml b/tests/components/speed/test.rp2040.yaml new file mode 100644 index 0000000000..02b572db75 --- /dev/null +++ b/tests/components/speed/test.rp2040.yaml @@ -0,0 +1,9 @@ +output: + - platform: rp2040_pwm + id: fan_output_1 + pin: 12 + +fan: + - platform: speed + id: fan_speed + output: fan_output_1 diff --git a/tests/components/spi/test.esp32-c3-idf.yaml b/tests/components/spi/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..f49470ad07 --- /dev/null +++ b/tests/components/spi/test.esp32-c3-idf.yaml @@ -0,0 +1,5 @@ +spi: + - id: spi_spi + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 diff --git a/tests/components/spi/test.esp32-c3.yaml b/tests/components/spi/test.esp32-c3.yaml new file mode 100644 index 0000000000..f49470ad07 --- /dev/null +++ b/tests/components/spi/test.esp32-c3.yaml @@ -0,0 +1,5 @@ +spi: + - id: spi_spi + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 diff --git a/tests/components/spi/test.esp32-idf.yaml b/tests/components/spi/test.esp32-idf.yaml new file mode 100644 index 0000000000..1cdcf461dd --- /dev/null +++ b/tests/components/spi/test.esp32-idf.yaml @@ -0,0 +1,5 @@ +spi: + - id: spi_spi + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 diff --git a/tests/components/spi/test.esp32.yaml b/tests/components/spi/test.esp32.yaml new file mode 100644 index 0000000000..1cdcf461dd --- /dev/null +++ b/tests/components/spi/test.esp32.yaml @@ -0,0 +1,5 @@ +spi: + - id: spi_spi + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 diff --git a/tests/components/spi/test.esp8266.yaml b/tests/components/spi/test.esp8266.yaml new file mode 100644 index 0000000000..83f110921f --- /dev/null +++ b/tests/components/spi/test.esp8266.yaml @@ -0,0 +1,5 @@ +spi: + - id: spi_spi + clk_pin: 14 + mosi_pin: 13 + miso_pin: 12 diff --git a/tests/components/spi/test.rp2040.yaml b/tests/components/spi/test.rp2040.yaml new file mode 100644 index 0000000000..1e39d247fe --- /dev/null +++ b/tests/components/spi/test.rp2040.yaml @@ -0,0 +1,5 @@ +spi: + - id: spi_spi + clk_pin: 2 + mosi_pin: 3 + miso_pin: 4 diff --git a/tests/components/spi_device/test.esp32-c3-idf.yaml b/tests/components/spi_device/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..49e2733676 --- /dev/null +++ b/tests/components/spi_device/test.esp32-c3-idf.yaml @@ -0,0 +1,11 @@ +spi: + - id: spi_device1 + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +spi_device: + id: spi_device_test + data_rate: 2MHz + mode: 3 + bit_order: lsb_first diff --git a/tests/components/spi_device/test.esp32-c3.yaml b/tests/components/spi_device/test.esp32-c3.yaml new file mode 100644 index 0000000000..49e2733676 --- /dev/null +++ b/tests/components/spi_device/test.esp32-c3.yaml @@ -0,0 +1,11 @@ +spi: + - id: spi_device1 + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +spi_device: + id: spi_device_test + data_rate: 2MHz + mode: 3 + bit_order: lsb_first diff --git a/tests/components/spi_device/test.esp32-idf.yaml b/tests/components/spi_device/test.esp32-idf.yaml new file mode 100644 index 0000000000..cad8ca49f8 --- /dev/null +++ b/tests/components/spi_device/test.esp32-idf.yaml @@ -0,0 +1,11 @@ +spi: + - id: spi_device1 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +spi_device: + id: spi_device_test + data_rate: 2MHz + mode: 3 + bit_order: lsb_first diff --git a/tests/components/spi_device/test.esp32.yaml b/tests/components/spi_device/test.esp32.yaml new file mode 100644 index 0000000000..cad8ca49f8 --- /dev/null +++ b/tests/components/spi_device/test.esp32.yaml @@ -0,0 +1,11 @@ +spi: + - id: spi_device1 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +spi_device: + id: spi_device_test + data_rate: 2MHz + mode: 3 + bit_order: lsb_first diff --git a/tests/components/spi_device/test.esp8266.yaml b/tests/components/spi_device/test.esp8266.yaml new file mode 100644 index 0000000000..1b191bdb6a --- /dev/null +++ b/tests/components/spi_device/test.esp8266.yaml @@ -0,0 +1,11 @@ +spi: + - id: spi_device1 + clk_pin: 14 + mosi_pin: 13 + miso_pin: 12 + +spi_device: + id: spi_device_test + data_rate: 2MHz + mode: 3 + bit_order: lsb_first diff --git a/tests/components/spi_device/test.rp2040.yaml b/tests/components/spi_device/test.rp2040.yaml new file mode 100644 index 0000000000..c70493c70d --- /dev/null +++ b/tests/components/spi_device/test.rp2040.yaml @@ -0,0 +1,11 @@ +spi: + - id: spi_device1 + clk_pin: 2 + mosi_pin: 3 + miso_pin: 4 + +spi_device: + id: spi_device_test + data_rate: 2MHz + mode: 3 + bit_order: lsb_first diff --git a/tests/components/spi_led_strip/test.esp32-c3-idf.yaml b/tests/components/spi_led_strip/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..983ad2863f --- /dev/null +++ b/tests/components/spi_led_strip/test.esp32-c3-idf.yaml @@ -0,0 +1,13 @@ +spi: + - id: spi_spi_led_strip + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +light: + - platform: spi_led_strip + num_leds: 4 + color_correct: [80%, 60%, 100%] + id: rgb_led + name: "RGB LED" + data_rate: 8MHz diff --git a/tests/components/spi_led_strip/test.esp32-c3.yaml b/tests/components/spi_led_strip/test.esp32-c3.yaml new file mode 100644 index 0000000000..983ad2863f --- /dev/null +++ b/tests/components/spi_led_strip/test.esp32-c3.yaml @@ -0,0 +1,13 @@ +spi: + - id: spi_spi_led_strip + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +light: + - platform: spi_led_strip + num_leds: 4 + color_correct: [80%, 60%, 100%] + id: rgb_led + name: "RGB LED" + data_rate: 8MHz diff --git a/tests/components/spi_led_strip/test.esp32-idf.yaml b/tests/components/spi_led_strip/test.esp32-idf.yaml new file mode 100644 index 0000000000..f4a760bf4c --- /dev/null +++ b/tests/components/spi_led_strip/test.esp32-idf.yaml @@ -0,0 +1,13 @@ +spi: + - id: spi_spi_led_strip + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +light: + - platform: spi_led_strip + num_leds: 4 + color_correct: [80%, 60%, 100%] + id: rgb_led + name: "RGB LED" + data_rate: 8MHz diff --git a/tests/components/spi_led_strip/test.esp32.yaml b/tests/components/spi_led_strip/test.esp32.yaml new file mode 100644 index 0000000000..f4a760bf4c --- /dev/null +++ b/tests/components/spi_led_strip/test.esp32.yaml @@ -0,0 +1,13 @@ +spi: + - id: spi_spi_led_strip + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +light: + - platform: spi_led_strip + num_leds: 4 + color_correct: [80%, 60%, 100%] + id: rgb_led + name: "RGB LED" + data_rate: 8MHz diff --git a/tests/components/spi_led_strip/test.esp8266.yaml b/tests/components/spi_led_strip/test.esp8266.yaml new file mode 100644 index 0000000000..8e76303b6a --- /dev/null +++ b/tests/components/spi_led_strip/test.esp8266.yaml @@ -0,0 +1,13 @@ +spi: + - id: spi_spi_led_strip + clk_pin: 14 + mosi_pin: 13 + miso_pin: 12 + +light: + - platform: spi_led_strip + num_leds: 4 + color_correct: [80%, 60%, 100%] + id: rgb_led + name: "RGB LED" + data_rate: 8MHz diff --git a/tests/components/spi_led_strip/test.rp2040.yaml b/tests/components/spi_led_strip/test.rp2040.yaml new file mode 100644 index 0000000000..9d12f1592b --- /dev/null +++ b/tests/components/spi_led_strip/test.rp2040.yaml @@ -0,0 +1,13 @@ +spi: + - id: spi_spi_led_strip + clk_pin: 2 + mosi_pin: 3 + miso_pin: 4 + +light: + - platform: spi_led_strip + num_leds: 4 + color_correct: [80%, 60%, 100%] + id: rgb_led + name: "RGB LED" + data_rate: 8MHz diff --git a/tests/components/sprinkler/test.esp32-c3-idf.yaml b/tests/components/sprinkler/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..f099f77729 --- /dev/null +++ b/tests/components/sprinkler/test.esp32-c3-idf.yaml @@ -0,0 +1,83 @@ +esphome: + on_boot: + then: + - sprinkler.start_full_cycle: yard_sprinkler_ctrlr + - sprinkler.start_from_queue: yard_sprinkler_ctrlr + - sprinkler.start_single_valve: + id: yard_sprinkler_ctrlr + valve_number: 0 + run_duration: 600s + - sprinkler.shutdown: yard_sprinkler_ctrlr + - sprinkler.next_valve: yard_sprinkler_ctrlr + - sprinkler.previous_valve: yard_sprinkler_ctrlr + - sprinkler.pause: yard_sprinkler_ctrlr + - sprinkler.resume: yard_sprinkler_ctrlr + - sprinkler.resume_or_start_full_cycle: yard_sprinkler_ctrlr + - sprinkler.queue_valve: + id: yard_sprinkler_ctrlr + valve_number: 2 + run_duration: 900s + - sprinkler.clear_queued_valves: yard_sprinkler_ctrlr + - sprinkler.set_multiplier: + id: yard_sprinkler_ctrlr + multiplier: 1.5 + - sprinkler.set_repeat: + id: yard_sprinkler_ctrlr + repeat: 2 + - sprinkler.set_divider: + id: yard_sprinkler_ctrlr + divider: 2 + - sprinkler.set_valve_run_duration: + id: yard_sprinkler_ctrlr + valve_number: 0 + run_duration: 600s + +switch: + - platform: template + id: switch1 + optimistic: true + - platform: template + id: switch2 + optimistic: true + +sprinkler: + - id: yard_sprinkler_ctrlr + main_switch: Yard Sprinklers + auto_advance_switch: Yard Sprinklers Auto Advance + reverse_switch: Yard Sprinklers Reverse + pump_start_pump_delay: 2s + pump_stop_valve_delay: 4s + pump_switch_off_during_valve_open_delay: true + valve_open_delay: 5s + valves: + - valve_switch: Yard Valve 0 + enable_switch: Enable Yard Valve 0 + pump_switch_id: switch1 + run_duration: 10s + valve_switch_id: switch2 + - valve_switch: Yard Valve 1 + enable_switch: Enable Yard Valve 1 + pump_switch_id: switch1 + run_duration: 10s + valve_switch_id: switch2 + - valve_switch: Yard Valve 2 + enable_switch: Enable Yard Valve 2 + pump_switch_id: switch1 + run_duration: 10s + valve_switch_id: switch2 + - id: garden_sprinkler_ctrlr + main_switch: Garden Sprinklers + auto_advance_switch: Garden Sprinklers Auto Advance + reverse_switch: Garden Sprinklers Reverse + valve_overlap: 5s + valves: + - valve_switch: Garden Valve 0 + enable_switch: Enable Garden Valve 0 + pump_switch_id: switch1 + run_duration: 10s + valve_switch_id: switch2 + - valve_switch: Garden Valve 1 + enable_switch: Enable Garden Valve 1 + pump_switch_id: switch1 + run_duration: 10s + valve_switch_id: switch2 diff --git a/tests/components/sprinkler/test.esp32-c3.yaml b/tests/components/sprinkler/test.esp32-c3.yaml new file mode 100644 index 0000000000..f099f77729 --- /dev/null +++ b/tests/components/sprinkler/test.esp32-c3.yaml @@ -0,0 +1,83 @@ +esphome: + on_boot: + then: + - sprinkler.start_full_cycle: yard_sprinkler_ctrlr + - sprinkler.start_from_queue: yard_sprinkler_ctrlr + - sprinkler.start_single_valve: + id: yard_sprinkler_ctrlr + valve_number: 0 + run_duration: 600s + - sprinkler.shutdown: yard_sprinkler_ctrlr + - sprinkler.next_valve: yard_sprinkler_ctrlr + - sprinkler.previous_valve: yard_sprinkler_ctrlr + - sprinkler.pause: yard_sprinkler_ctrlr + - sprinkler.resume: yard_sprinkler_ctrlr + - sprinkler.resume_or_start_full_cycle: yard_sprinkler_ctrlr + - sprinkler.queue_valve: + id: yard_sprinkler_ctrlr + valve_number: 2 + run_duration: 900s + - sprinkler.clear_queued_valves: yard_sprinkler_ctrlr + - sprinkler.set_multiplier: + id: yard_sprinkler_ctrlr + multiplier: 1.5 + - sprinkler.set_repeat: + id: yard_sprinkler_ctrlr + repeat: 2 + - sprinkler.set_divider: + id: yard_sprinkler_ctrlr + divider: 2 + - sprinkler.set_valve_run_duration: + id: yard_sprinkler_ctrlr + valve_number: 0 + run_duration: 600s + +switch: + - platform: template + id: switch1 + optimistic: true + - platform: template + id: switch2 + optimistic: true + +sprinkler: + - id: yard_sprinkler_ctrlr + main_switch: Yard Sprinklers + auto_advance_switch: Yard Sprinklers Auto Advance + reverse_switch: Yard Sprinklers Reverse + pump_start_pump_delay: 2s + pump_stop_valve_delay: 4s + pump_switch_off_during_valve_open_delay: true + valve_open_delay: 5s + valves: + - valve_switch: Yard Valve 0 + enable_switch: Enable Yard Valve 0 + pump_switch_id: switch1 + run_duration: 10s + valve_switch_id: switch2 + - valve_switch: Yard Valve 1 + enable_switch: Enable Yard Valve 1 + pump_switch_id: switch1 + run_duration: 10s + valve_switch_id: switch2 + - valve_switch: Yard Valve 2 + enable_switch: Enable Yard Valve 2 + pump_switch_id: switch1 + run_duration: 10s + valve_switch_id: switch2 + - id: garden_sprinkler_ctrlr + main_switch: Garden Sprinklers + auto_advance_switch: Garden Sprinklers Auto Advance + reverse_switch: Garden Sprinklers Reverse + valve_overlap: 5s + valves: + - valve_switch: Garden Valve 0 + enable_switch: Enable Garden Valve 0 + pump_switch_id: switch1 + run_duration: 10s + valve_switch_id: switch2 + - valve_switch: Garden Valve 1 + enable_switch: Enable Garden Valve 1 + pump_switch_id: switch1 + run_duration: 10s + valve_switch_id: switch2 diff --git a/tests/components/sprinkler/test.esp32-idf.yaml b/tests/components/sprinkler/test.esp32-idf.yaml new file mode 100644 index 0000000000..f099f77729 --- /dev/null +++ b/tests/components/sprinkler/test.esp32-idf.yaml @@ -0,0 +1,83 @@ +esphome: + on_boot: + then: + - sprinkler.start_full_cycle: yard_sprinkler_ctrlr + - sprinkler.start_from_queue: yard_sprinkler_ctrlr + - sprinkler.start_single_valve: + id: yard_sprinkler_ctrlr + valve_number: 0 + run_duration: 600s + - sprinkler.shutdown: yard_sprinkler_ctrlr + - sprinkler.next_valve: yard_sprinkler_ctrlr + - sprinkler.previous_valve: yard_sprinkler_ctrlr + - sprinkler.pause: yard_sprinkler_ctrlr + - sprinkler.resume: yard_sprinkler_ctrlr + - sprinkler.resume_or_start_full_cycle: yard_sprinkler_ctrlr + - sprinkler.queue_valve: + id: yard_sprinkler_ctrlr + valve_number: 2 + run_duration: 900s + - sprinkler.clear_queued_valves: yard_sprinkler_ctrlr + - sprinkler.set_multiplier: + id: yard_sprinkler_ctrlr + multiplier: 1.5 + - sprinkler.set_repeat: + id: yard_sprinkler_ctrlr + repeat: 2 + - sprinkler.set_divider: + id: yard_sprinkler_ctrlr + divider: 2 + - sprinkler.set_valve_run_duration: + id: yard_sprinkler_ctrlr + valve_number: 0 + run_duration: 600s + +switch: + - platform: template + id: switch1 + optimistic: true + - platform: template + id: switch2 + optimistic: true + +sprinkler: + - id: yard_sprinkler_ctrlr + main_switch: Yard Sprinklers + auto_advance_switch: Yard Sprinklers Auto Advance + reverse_switch: Yard Sprinklers Reverse + pump_start_pump_delay: 2s + pump_stop_valve_delay: 4s + pump_switch_off_during_valve_open_delay: true + valve_open_delay: 5s + valves: + - valve_switch: Yard Valve 0 + enable_switch: Enable Yard Valve 0 + pump_switch_id: switch1 + run_duration: 10s + valve_switch_id: switch2 + - valve_switch: Yard Valve 1 + enable_switch: Enable Yard Valve 1 + pump_switch_id: switch1 + run_duration: 10s + valve_switch_id: switch2 + - valve_switch: Yard Valve 2 + enable_switch: Enable Yard Valve 2 + pump_switch_id: switch1 + run_duration: 10s + valve_switch_id: switch2 + - id: garden_sprinkler_ctrlr + main_switch: Garden Sprinklers + auto_advance_switch: Garden Sprinklers Auto Advance + reverse_switch: Garden Sprinklers Reverse + valve_overlap: 5s + valves: + - valve_switch: Garden Valve 0 + enable_switch: Enable Garden Valve 0 + pump_switch_id: switch1 + run_duration: 10s + valve_switch_id: switch2 + - valve_switch: Garden Valve 1 + enable_switch: Enable Garden Valve 1 + pump_switch_id: switch1 + run_duration: 10s + valve_switch_id: switch2 diff --git a/tests/components/sprinkler/test.esp32.yaml b/tests/components/sprinkler/test.esp32.yaml new file mode 100644 index 0000000000..f099f77729 --- /dev/null +++ b/tests/components/sprinkler/test.esp32.yaml @@ -0,0 +1,83 @@ +esphome: + on_boot: + then: + - sprinkler.start_full_cycle: yard_sprinkler_ctrlr + - sprinkler.start_from_queue: yard_sprinkler_ctrlr + - sprinkler.start_single_valve: + id: yard_sprinkler_ctrlr + valve_number: 0 + run_duration: 600s + - sprinkler.shutdown: yard_sprinkler_ctrlr + - sprinkler.next_valve: yard_sprinkler_ctrlr + - sprinkler.previous_valve: yard_sprinkler_ctrlr + - sprinkler.pause: yard_sprinkler_ctrlr + - sprinkler.resume: yard_sprinkler_ctrlr + - sprinkler.resume_or_start_full_cycle: yard_sprinkler_ctrlr + - sprinkler.queue_valve: + id: yard_sprinkler_ctrlr + valve_number: 2 + run_duration: 900s + - sprinkler.clear_queued_valves: yard_sprinkler_ctrlr + - sprinkler.set_multiplier: + id: yard_sprinkler_ctrlr + multiplier: 1.5 + - sprinkler.set_repeat: + id: yard_sprinkler_ctrlr + repeat: 2 + - sprinkler.set_divider: + id: yard_sprinkler_ctrlr + divider: 2 + - sprinkler.set_valve_run_duration: + id: yard_sprinkler_ctrlr + valve_number: 0 + run_duration: 600s + +switch: + - platform: template + id: switch1 + optimistic: true + - platform: template + id: switch2 + optimistic: true + +sprinkler: + - id: yard_sprinkler_ctrlr + main_switch: Yard Sprinklers + auto_advance_switch: Yard Sprinklers Auto Advance + reverse_switch: Yard Sprinklers Reverse + pump_start_pump_delay: 2s + pump_stop_valve_delay: 4s + pump_switch_off_during_valve_open_delay: true + valve_open_delay: 5s + valves: + - valve_switch: Yard Valve 0 + enable_switch: Enable Yard Valve 0 + pump_switch_id: switch1 + run_duration: 10s + valve_switch_id: switch2 + - valve_switch: Yard Valve 1 + enable_switch: Enable Yard Valve 1 + pump_switch_id: switch1 + run_duration: 10s + valve_switch_id: switch2 + - valve_switch: Yard Valve 2 + enable_switch: Enable Yard Valve 2 + pump_switch_id: switch1 + run_duration: 10s + valve_switch_id: switch2 + - id: garden_sprinkler_ctrlr + main_switch: Garden Sprinklers + auto_advance_switch: Garden Sprinklers Auto Advance + reverse_switch: Garden Sprinklers Reverse + valve_overlap: 5s + valves: + - valve_switch: Garden Valve 0 + enable_switch: Enable Garden Valve 0 + pump_switch_id: switch1 + run_duration: 10s + valve_switch_id: switch2 + - valve_switch: Garden Valve 1 + enable_switch: Enable Garden Valve 1 + pump_switch_id: switch1 + run_duration: 10s + valve_switch_id: switch2 diff --git a/tests/components/sprinkler/test.esp8266.yaml b/tests/components/sprinkler/test.esp8266.yaml new file mode 100644 index 0000000000..f099f77729 --- /dev/null +++ b/tests/components/sprinkler/test.esp8266.yaml @@ -0,0 +1,83 @@ +esphome: + on_boot: + then: + - sprinkler.start_full_cycle: yard_sprinkler_ctrlr + - sprinkler.start_from_queue: yard_sprinkler_ctrlr + - sprinkler.start_single_valve: + id: yard_sprinkler_ctrlr + valve_number: 0 + run_duration: 600s + - sprinkler.shutdown: yard_sprinkler_ctrlr + - sprinkler.next_valve: yard_sprinkler_ctrlr + - sprinkler.previous_valve: yard_sprinkler_ctrlr + - sprinkler.pause: yard_sprinkler_ctrlr + - sprinkler.resume: yard_sprinkler_ctrlr + - sprinkler.resume_or_start_full_cycle: yard_sprinkler_ctrlr + - sprinkler.queue_valve: + id: yard_sprinkler_ctrlr + valve_number: 2 + run_duration: 900s + - sprinkler.clear_queued_valves: yard_sprinkler_ctrlr + - sprinkler.set_multiplier: + id: yard_sprinkler_ctrlr + multiplier: 1.5 + - sprinkler.set_repeat: + id: yard_sprinkler_ctrlr + repeat: 2 + - sprinkler.set_divider: + id: yard_sprinkler_ctrlr + divider: 2 + - sprinkler.set_valve_run_duration: + id: yard_sprinkler_ctrlr + valve_number: 0 + run_duration: 600s + +switch: + - platform: template + id: switch1 + optimistic: true + - platform: template + id: switch2 + optimistic: true + +sprinkler: + - id: yard_sprinkler_ctrlr + main_switch: Yard Sprinklers + auto_advance_switch: Yard Sprinklers Auto Advance + reverse_switch: Yard Sprinklers Reverse + pump_start_pump_delay: 2s + pump_stop_valve_delay: 4s + pump_switch_off_during_valve_open_delay: true + valve_open_delay: 5s + valves: + - valve_switch: Yard Valve 0 + enable_switch: Enable Yard Valve 0 + pump_switch_id: switch1 + run_duration: 10s + valve_switch_id: switch2 + - valve_switch: Yard Valve 1 + enable_switch: Enable Yard Valve 1 + pump_switch_id: switch1 + run_duration: 10s + valve_switch_id: switch2 + - valve_switch: Yard Valve 2 + enable_switch: Enable Yard Valve 2 + pump_switch_id: switch1 + run_duration: 10s + valve_switch_id: switch2 + - id: garden_sprinkler_ctrlr + main_switch: Garden Sprinklers + auto_advance_switch: Garden Sprinklers Auto Advance + reverse_switch: Garden Sprinklers Reverse + valve_overlap: 5s + valves: + - valve_switch: Garden Valve 0 + enable_switch: Enable Garden Valve 0 + pump_switch_id: switch1 + run_duration: 10s + valve_switch_id: switch2 + - valve_switch: Garden Valve 1 + enable_switch: Enable Garden Valve 1 + pump_switch_id: switch1 + run_duration: 10s + valve_switch_id: switch2 diff --git a/tests/components/sprinkler/test.rp2040.yaml b/tests/components/sprinkler/test.rp2040.yaml new file mode 100644 index 0000000000..f099f77729 --- /dev/null +++ b/tests/components/sprinkler/test.rp2040.yaml @@ -0,0 +1,83 @@ +esphome: + on_boot: + then: + - sprinkler.start_full_cycle: yard_sprinkler_ctrlr + - sprinkler.start_from_queue: yard_sprinkler_ctrlr + - sprinkler.start_single_valve: + id: yard_sprinkler_ctrlr + valve_number: 0 + run_duration: 600s + - sprinkler.shutdown: yard_sprinkler_ctrlr + - sprinkler.next_valve: yard_sprinkler_ctrlr + - sprinkler.previous_valve: yard_sprinkler_ctrlr + - sprinkler.pause: yard_sprinkler_ctrlr + - sprinkler.resume: yard_sprinkler_ctrlr + - sprinkler.resume_or_start_full_cycle: yard_sprinkler_ctrlr + - sprinkler.queue_valve: + id: yard_sprinkler_ctrlr + valve_number: 2 + run_duration: 900s + - sprinkler.clear_queued_valves: yard_sprinkler_ctrlr + - sprinkler.set_multiplier: + id: yard_sprinkler_ctrlr + multiplier: 1.5 + - sprinkler.set_repeat: + id: yard_sprinkler_ctrlr + repeat: 2 + - sprinkler.set_divider: + id: yard_sprinkler_ctrlr + divider: 2 + - sprinkler.set_valve_run_duration: + id: yard_sprinkler_ctrlr + valve_number: 0 + run_duration: 600s + +switch: + - platform: template + id: switch1 + optimistic: true + - platform: template + id: switch2 + optimistic: true + +sprinkler: + - id: yard_sprinkler_ctrlr + main_switch: Yard Sprinklers + auto_advance_switch: Yard Sprinklers Auto Advance + reverse_switch: Yard Sprinklers Reverse + pump_start_pump_delay: 2s + pump_stop_valve_delay: 4s + pump_switch_off_during_valve_open_delay: true + valve_open_delay: 5s + valves: + - valve_switch: Yard Valve 0 + enable_switch: Enable Yard Valve 0 + pump_switch_id: switch1 + run_duration: 10s + valve_switch_id: switch2 + - valve_switch: Yard Valve 1 + enable_switch: Enable Yard Valve 1 + pump_switch_id: switch1 + run_duration: 10s + valve_switch_id: switch2 + - valve_switch: Yard Valve 2 + enable_switch: Enable Yard Valve 2 + pump_switch_id: switch1 + run_duration: 10s + valve_switch_id: switch2 + - id: garden_sprinkler_ctrlr + main_switch: Garden Sprinklers + auto_advance_switch: Garden Sprinklers Auto Advance + reverse_switch: Garden Sprinklers Reverse + valve_overlap: 5s + valves: + - valve_switch: Garden Valve 0 + enable_switch: Enable Garden Valve 0 + pump_switch_id: switch1 + run_duration: 10s + valve_switch_id: switch2 + - valve_switch: Garden Valve 1 + enable_switch: Enable Garden Valve 1 + pump_switch_id: switch1 + run_duration: 10s + valve_switch_id: switch2 diff --git a/tests/components/sps30/test.esp32-c3-idf.yaml b/tests/components/sps30/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..e071a00936 --- /dev/null +++ b/tests/components/sps30/test.esp32-c3-idf.yaml @@ -0,0 +1,36 @@ +i2c: + - id: i2c_sps30 + scl: 5 + sda: 4 + +sensor: + - platform: sps30 + pm_1_0: + name: Workshop PM <1µm Weight concentration + id: workshop_PM_1_0 + pm_2_5: + name: Workshop PM <2.5µm Weight concentration + id: workshop_PM_2_5 + pm_4_0: + name: Workshop PM <4µm Weight concentration + id: workshop_PM_4_0 + pm_10_0: + name: Workshop PM <10µm Weight concentration + id: workshop_PM_10_0 + pmc_0_5: + name: Workshop PM <0.5µm Number concentration + id: workshop_PMC_0_5 + pmc_1_0: + name: Workshop PM <1µm Number concentration + id: workshop_PMC_1_0 + pmc_2_5: + name: Workshop PM <2.5µm Number concentration + id: workshop_PMC_2_5 + pmc_4_0: + name: Workshop PM <4µm Number concentration + id: workshop_PMC_4_0 + pmc_10_0: + name: Workshop PM <10µm Number concentration + id: workshop_PMC_10_0 + address: 0x69 + update_interval: 10s diff --git a/tests/components/sps30/test.esp32-c3.yaml b/tests/components/sps30/test.esp32-c3.yaml new file mode 100644 index 0000000000..e071a00936 --- /dev/null +++ b/tests/components/sps30/test.esp32-c3.yaml @@ -0,0 +1,36 @@ +i2c: + - id: i2c_sps30 + scl: 5 + sda: 4 + +sensor: + - platform: sps30 + pm_1_0: + name: Workshop PM <1µm Weight concentration + id: workshop_PM_1_0 + pm_2_5: + name: Workshop PM <2.5µm Weight concentration + id: workshop_PM_2_5 + pm_4_0: + name: Workshop PM <4µm Weight concentration + id: workshop_PM_4_0 + pm_10_0: + name: Workshop PM <10µm Weight concentration + id: workshop_PM_10_0 + pmc_0_5: + name: Workshop PM <0.5µm Number concentration + id: workshop_PMC_0_5 + pmc_1_0: + name: Workshop PM <1µm Number concentration + id: workshop_PMC_1_0 + pmc_2_5: + name: Workshop PM <2.5µm Number concentration + id: workshop_PMC_2_5 + pmc_4_0: + name: Workshop PM <4µm Number concentration + id: workshop_PMC_4_0 + pmc_10_0: + name: Workshop PM <10µm Number concentration + id: workshop_PMC_10_0 + address: 0x69 + update_interval: 10s diff --git a/tests/components/sps30/test.esp32-idf.yaml b/tests/components/sps30/test.esp32-idf.yaml new file mode 100644 index 0000000000..f9d1ee4e55 --- /dev/null +++ b/tests/components/sps30/test.esp32-idf.yaml @@ -0,0 +1,36 @@ +i2c: + - id: i2c_sps30 + scl: 16 + sda: 17 + +sensor: + - platform: sps30 + pm_1_0: + name: Workshop PM <1µm Weight concentration + id: workshop_PM_1_0 + pm_2_5: + name: Workshop PM <2.5µm Weight concentration + id: workshop_PM_2_5 + pm_4_0: + name: Workshop PM <4µm Weight concentration + id: workshop_PM_4_0 + pm_10_0: + name: Workshop PM <10µm Weight concentration + id: workshop_PM_10_0 + pmc_0_5: + name: Workshop PM <0.5µm Number concentration + id: workshop_PMC_0_5 + pmc_1_0: + name: Workshop PM <1µm Number concentration + id: workshop_PMC_1_0 + pmc_2_5: + name: Workshop PM <2.5µm Number concentration + id: workshop_PMC_2_5 + pmc_4_0: + name: Workshop PM <4µm Number concentration + id: workshop_PMC_4_0 + pmc_10_0: + name: Workshop PM <10µm Number concentration + id: workshop_PMC_10_0 + address: 0x69 + update_interval: 10s diff --git a/tests/components/sps30/test.esp32.yaml b/tests/components/sps30/test.esp32.yaml new file mode 100644 index 0000000000..f9d1ee4e55 --- /dev/null +++ b/tests/components/sps30/test.esp32.yaml @@ -0,0 +1,36 @@ +i2c: + - id: i2c_sps30 + scl: 16 + sda: 17 + +sensor: + - platform: sps30 + pm_1_0: + name: Workshop PM <1µm Weight concentration + id: workshop_PM_1_0 + pm_2_5: + name: Workshop PM <2.5µm Weight concentration + id: workshop_PM_2_5 + pm_4_0: + name: Workshop PM <4µm Weight concentration + id: workshop_PM_4_0 + pm_10_0: + name: Workshop PM <10µm Weight concentration + id: workshop_PM_10_0 + pmc_0_5: + name: Workshop PM <0.5µm Number concentration + id: workshop_PMC_0_5 + pmc_1_0: + name: Workshop PM <1µm Number concentration + id: workshop_PMC_1_0 + pmc_2_5: + name: Workshop PM <2.5µm Number concentration + id: workshop_PMC_2_5 + pmc_4_0: + name: Workshop PM <4µm Number concentration + id: workshop_PMC_4_0 + pmc_10_0: + name: Workshop PM <10µm Number concentration + id: workshop_PMC_10_0 + address: 0x69 + update_interval: 10s diff --git a/tests/components/sps30/test.esp8266.yaml b/tests/components/sps30/test.esp8266.yaml new file mode 100644 index 0000000000..e071a00936 --- /dev/null +++ b/tests/components/sps30/test.esp8266.yaml @@ -0,0 +1,36 @@ +i2c: + - id: i2c_sps30 + scl: 5 + sda: 4 + +sensor: + - platform: sps30 + pm_1_0: + name: Workshop PM <1µm Weight concentration + id: workshop_PM_1_0 + pm_2_5: + name: Workshop PM <2.5µm Weight concentration + id: workshop_PM_2_5 + pm_4_0: + name: Workshop PM <4µm Weight concentration + id: workshop_PM_4_0 + pm_10_0: + name: Workshop PM <10µm Weight concentration + id: workshop_PM_10_0 + pmc_0_5: + name: Workshop PM <0.5µm Number concentration + id: workshop_PMC_0_5 + pmc_1_0: + name: Workshop PM <1µm Number concentration + id: workshop_PMC_1_0 + pmc_2_5: + name: Workshop PM <2.5µm Number concentration + id: workshop_PMC_2_5 + pmc_4_0: + name: Workshop PM <4µm Number concentration + id: workshop_PMC_4_0 + pmc_10_0: + name: Workshop PM <10µm Number concentration + id: workshop_PMC_10_0 + address: 0x69 + update_interval: 10s diff --git a/tests/components/sps30/test.rp2040.yaml b/tests/components/sps30/test.rp2040.yaml new file mode 100644 index 0000000000..e071a00936 --- /dev/null +++ b/tests/components/sps30/test.rp2040.yaml @@ -0,0 +1,36 @@ +i2c: + - id: i2c_sps30 + scl: 5 + sda: 4 + +sensor: + - platform: sps30 + pm_1_0: + name: Workshop PM <1µm Weight concentration + id: workshop_PM_1_0 + pm_2_5: + name: Workshop PM <2.5µm Weight concentration + id: workshop_PM_2_5 + pm_4_0: + name: Workshop PM <4µm Weight concentration + id: workshop_PM_4_0 + pm_10_0: + name: Workshop PM <10µm Weight concentration + id: workshop_PM_10_0 + pmc_0_5: + name: Workshop PM <0.5µm Number concentration + id: workshop_PMC_0_5 + pmc_1_0: + name: Workshop PM <1µm Number concentration + id: workshop_PMC_1_0 + pmc_2_5: + name: Workshop PM <2.5µm Number concentration + id: workshop_PMC_2_5 + pmc_4_0: + name: Workshop PM <4µm Number concentration + id: workshop_PMC_4_0 + pmc_10_0: + name: Workshop PM <10µm Number concentration + id: workshop_PMC_10_0 + address: 0x69 + update_interval: 10s diff --git a/tests/components/ssd1306_i2c/test.esp32-c3-idf.yaml b/tests/components/ssd1306_i2c/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..f4a301db51 --- /dev/null +++ b/tests/components/ssd1306_i2c/test.esp32-c3-idf.yaml @@ -0,0 +1,25 @@ +i2c: + - id: i2c_ssd1306_i2c + scl: 5 + sda: 4 + +display: + - platform: ssd1306_i2c + model: SSD1306_128X64 + reset_pin: 3 + address: 0x3C + id: display1 + contrast: 60% + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, 10, 10); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1306_i2c/test.esp32-c3.yaml b/tests/components/ssd1306_i2c/test.esp32-c3.yaml new file mode 100644 index 0000000000..f4a301db51 --- /dev/null +++ b/tests/components/ssd1306_i2c/test.esp32-c3.yaml @@ -0,0 +1,25 @@ +i2c: + - id: i2c_ssd1306_i2c + scl: 5 + sda: 4 + +display: + - platform: ssd1306_i2c + model: SSD1306_128X64 + reset_pin: 3 + address: 0x3C + id: display1 + contrast: 60% + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, 10, 10); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1306_i2c/test.esp32-idf.yaml b/tests/components/ssd1306_i2c/test.esp32-idf.yaml new file mode 100644 index 0000000000..dddc67309c --- /dev/null +++ b/tests/components/ssd1306_i2c/test.esp32-idf.yaml @@ -0,0 +1,25 @@ +i2c: + - id: i2c_ssd1306_i2c + scl: 16 + sda: 17 + +display: + - platform: ssd1306_i2c + model: SSD1306_128X64 + reset_pin: 3 + address: 0x3C + id: display1 + contrast: 60% + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, 10, 10); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1306_i2c/test.esp32.yaml b/tests/components/ssd1306_i2c/test.esp32.yaml new file mode 100644 index 0000000000..dddc67309c --- /dev/null +++ b/tests/components/ssd1306_i2c/test.esp32.yaml @@ -0,0 +1,25 @@ +i2c: + - id: i2c_ssd1306_i2c + scl: 16 + sda: 17 + +display: + - platform: ssd1306_i2c + model: SSD1306_128X64 + reset_pin: 3 + address: 0x3C + id: display1 + contrast: 60% + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, 10, 10); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1306_i2c/test.esp8266.yaml b/tests/components/ssd1306_i2c/test.esp8266.yaml new file mode 100644 index 0000000000..f4a301db51 --- /dev/null +++ b/tests/components/ssd1306_i2c/test.esp8266.yaml @@ -0,0 +1,25 @@ +i2c: + - id: i2c_ssd1306_i2c + scl: 5 + sda: 4 + +display: + - platform: ssd1306_i2c + model: SSD1306_128X64 + reset_pin: 3 + address: 0x3C + id: display1 + contrast: 60% + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, 10, 10); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1306_i2c/test.rp2040.yaml b/tests/components/ssd1306_i2c/test.rp2040.yaml new file mode 100644 index 0000000000..f4a301db51 --- /dev/null +++ b/tests/components/ssd1306_i2c/test.rp2040.yaml @@ -0,0 +1,25 @@ +i2c: + - id: i2c_ssd1306_i2c + scl: 5 + sda: 4 + +display: + - platform: ssd1306_i2c + model: SSD1306_128X64 + reset_pin: 3 + address: 0x3C + id: display1 + contrast: 60% + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, 10, 10); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1306_spi/test.esp32-c3-idf.yaml b/tests/components/ssd1306_spi/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..01b2d0e4a8 --- /dev/null +++ b/tests/components/ssd1306_spi/test.esp32-c3-idf.yaml @@ -0,0 +1,25 @@ +spi: + - id: spi_ssd1306_spi + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +display: + - platform: ssd1306_spi + model: SSD1306 128x64 + cs_pin: 2 + dc_pin: 3 + reset_pin: 4 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1306_spi/test.esp32-c3.yaml b/tests/components/ssd1306_spi/test.esp32-c3.yaml new file mode 100644 index 0000000000..01b2d0e4a8 --- /dev/null +++ b/tests/components/ssd1306_spi/test.esp32-c3.yaml @@ -0,0 +1,25 @@ +spi: + - id: spi_ssd1306_spi + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +display: + - platform: ssd1306_spi + model: SSD1306 128x64 + cs_pin: 2 + dc_pin: 3 + reset_pin: 4 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1306_spi/test.esp32-idf.yaml b/tests/components/ssd1306_spi/test.esp32-idf.yaml new file mode 100644 index 0000000000..b0e5e0f1a2 --- /dev/null +++ b/tests/components/ssd1306_spi/test.esp32-idf.yaml @@ -0,0 +1,25 @@ +spi: + - id: spi_ssd1306_spi + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +display: + - platform: ssd1306_spi + model: SSD1306 128x64 + cs_pin: 12 + dc_pin: 13 + reset_pin: 14 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1306_spi/test.esp32.yaml b/tests/components/ssd1306_spi/test.esp32.yaml new file mode 100644 index 0000000000..b0e5e0f1a2 --- /dev/null +++ b/tests/components/ssd1306_spi/test.esp32.yaml @@ -0,0 +1,25 @@ +spi: + - id: spi_ssd1306_spi + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +display: + - platform: ssd1306_spi + model: SSD1306 128x64 + cs_pin: 12 + dc_pin: 13 + reset_pin: 14 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1306_spi/test.esp8266.yaml b/tests/components/ssd1306_spi/test.esp8266.yaml new file mode 100644 index 0000000000..135e364bb2 --- /dev/null +++ b/tests/components/ssd1306_spi/test.esp8266.yaml @@ -0,0 +1,25 @@ +spi: + - id: spi_ssd1306_spi + clk_pin: 14 + mosi_pin: 13 + miso_pin: 12 + +display: + - platform: ssd1306_spi + model: SSD1306 128x64 + cs_pin: 15 + dc_pin: 16 + reset_pin: 5 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1306_spi/test.rp2040.yaml b/tests/components/ssd1306_spi/test.rp2040.yaml new file mode 100644 index 0000000000..94c4b85158 --- /dev/null +++ b/tests/components/ssd1306_spi/test.rp2040.yaml @@ -0,0 +1,25 @@ +spi: + - id: spi_ssd1306_spi + clk_pin: 2 + mosi_pin: 3 + miso_pin: 4 + +display: + - platform: ssd1306_spi + model: SSD1306 128x64 + cs_pin: 5 + dc_pin: 6 + reset_pin: 7 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1322_spi/test.esp32-c3-idf.yaml b/tests/components/ssd1322_spi/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..4fa9f86594 --- /dev/null +++ b/tests/components/ssd1322_spi/test.esp32-c3-idf.yaml @@ -0,0 +1,25 @@ +spi: + - id: spi_ssd1322_spi + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +display: + - platform: ssd1322_spi + model: SSD1322 256x64 + cs_pin: 2 + dc_pin: 3 + reset_pin: 4 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1322_spi/test.esp32-c3.yaml b/tests/components/ssd1322_spi/test.esp32-c3.yaml new file mode 100644 index 0000000000..4fa9f86594 --- /dev/null +++ b/tests/components/ssd1322_spi/test.esp32-c3.yaml @@ -0,0 +1,25 @@ +spi: + - id: spi_ssd1322_spi + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +display: + - platform: ssd1322_spi + model: SSD1322 256x64 + cs_pin: 2 + dc_pin: 3 + reset_pin: 4 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1322_spi/test.esp32-idf.yaml b/tests/components/ssd1322_spi/test.esp32-idf.yaml new file mode 100644 index 0000000000..aa6d0fbf01 --- /dev/null +++ b/tests/components/ssd1322_spi/test.esp32-idf.yaml @@ -0,0 +1,25 @@ +spi: + - id: spi_ssd1322_spi + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +display: + - platform: ssd1322_spi + model: SSD1322 256x64 + cs_pin: 12 + dc_pin: 13 + reset_pin: 14 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1322_spi/test.esp32.yaml b/tests/components/ssd1322_spi/test.esp32.yaml new file mode 100644 index 0000000000..aa6d0fbf01 --- /dev/null +++ b/tests/components/ssd1322_spi/test.esp32.yaml @@ -0,0 +1,25 @@ +spi: + - id: spi_ssd1322_spi + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +display: + - platform: ssd1322_spi + model: SSD1322 256x64 + cs_pin: 12 + dc_pin: 13 + reset_pin: 14 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1322_spi/test.esp8266.yaml b/tests/components/ssd1322_spi/test.esp8266.yaml new file mode 100644 index 0000000000..a5aa565c09 --- /dev/null +++ b/tests/components/ssd1322_spi/test.esp8266.yaml @@ -0,0 +1,25 @@ +spi: + - id: spi_ssd1322_spi + clk_pin: 14 + mosi_pin: 13 + miso_pin: 12 + +display: + - platform: ssd1322_spi + model: SSD1322 256x64 + cs_pin: 15 + dc_pin: 16 + reset_pin: 5 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1322_spi/test.rp2040.yaml b/tests/components/ssd1322_spi/test.rp2040.yaml new file mode 100644 index 0000000000..59544e7878 --- /dev/null +++ b/tests/components/ssd1322_spi/test.rp2040.yaml @@ -0,0 +1,25 @@ +spi: + - id: spi_ssd1322_spi + clk_pin: 2 + mosi_pin: 3 + miso_pin: 4 + +display: + - platform: ssd1322_spi + model: SSD1322 256x64 + cs_pin: 5 + dc_pin: 6 + reset_pin: 7 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1325_spi/test.esp32-c3-idf.yaml b/tests/components/ssd1325_spi/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..0fa8cb6488 --- /dev/null +++ b/tests/components/ssd1325_spi/test.esp32-c3-idf.yaml @@ -0,0 +1,25 @@ +spi: + - id: spi_ssd1325_spi + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +display: + - platform: ssd1325_spi + model: SSD1325 128x64 + cs_pin: 2 + dc_pin: 3 + reset_pin: 4 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1325_spi/test.esp32-c3.yaml b/tests/components/ssd1325_spi/test.esp32-c3.yaml new file mode 100644 index 0000000000..0fa8cb6488 --- /dev/null +++ b/tests/components/ssd1325_spi/test.esp32-c3.yaml @@ -0,0 +1,25 @@ +spi: + - id: spi_ssd1325_spi + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +display: + - platform: ssd1325_spi + model: SSD1325 128x64 + cs_pin: 2 + dc_pin: 3 + reset_pin: 4 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1325_spi/test.esp32-idf.yaml b/tests/components/ssd1325_spi/test.esp32-idf.yaml new file mode 100644 index 0000000000..84d94eff28 --- /dev/null +++ b/tests/components/ssd1325_spi/test.esp32-idf.yaml @@ -0,0 +1,25 @@ +spi: + - id: spi_ssd1325_spi + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +display: + - platform: ssd1325_spi + model: SSD1325 128x64 + cs_pin: 12 + dc_pin: 13 + reset_pin: 14 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1325_spi/test.esp32.yaml b/tests/components/ssd1325_spi/test.esp32.yaml new file mode 100644 index 0000000000..84d94eff28 --- /dev/null +++ b/tests/components/ssd1325_spi/test.esp32.yaml @@ -0,0 +1,25 @@ +spi: + - id: spi_ssd1325_spi + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +display: + - platform: ssd1325_spi + model: SSD1325 128x64 + cs_pin: 12 + dc_pin: 13 + reset_pin: 14 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1325_spi/test.esp8266.yaml b/tests/components/ssd1325_spi/test.esp8266.yaml new file mode 100644 index 0000000000..9d7e483585 --- /dev/null +++ b/tests/components/ssd1325_spi/test.esp8266.yaml @@ -0,0 +1,25 @@ +spi: + - id: spi_ssd1325_spi + clk_pin: 14 + mosi_pin: 13 + miso_pin: 12 + +display: + - platform: ssd1325_spi + model: SSD1325 128x64 + cs_pin: 15 + dc_pin: 16 + reset_pin: 5 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1325_spi/test.rp2040.yaml b/tests/components/ssd1325_spi/test.rp2040.yaml new file mode 100644 index 0000000000..869663c19d --- /dev/null +++ b/tests/components/ssd1325_spi/test.rp2040.yaml @@ -0,0 +1,25 @@ +spi: + - id: spi_ssd1325_spi + clk_pin: 2 + mosi_pin: 3 + miso_pin: 4 + +display: + - platform: ssd1325_spi + model: SSD1325 128x64 + cs_pin: 5 + dc_pin: 6 + reset_pin: 7 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1327_i2c/test.esp32-c3-idf.yaml b/tests/components/ssd1327_i2c/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..cd28795ff1 --- /dev/null +++ b/tests/components/ssd1327_i2c/test.esp32-c3-idf.yaml @@ -0,0 +1,24 @@ +i2c: + - id: i2c_ssd1327_i2c + scl: 5 + sda: 4 + +display: + - platform: ssd1327_i2c + model: SSD1327_128x128 + reset_pin: 3 + address: 0x3C + id: display1 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, 10, 10); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1327_i2c/test.esp32-c3.yaml b/tests/components/ssd1327_i2c/test.esp32-c3.yaml new file mode 100644 index 0000000000..cd28795ff1 --- /dev/null +++ b/tests/components/ssd1327_i2c/test.esp32-c3.yaml @@ -0,0 +1,24 @@ +i2c: + - id: i2c_ssd1327_i2c + scl: 5 + sda: 4 + +display: + - platform: ssd1327_i2c + model: SSD1327_128x128 + reset_pin: 3 + address: 0x3C + id: display1 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, 10, 10); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1327_i2c/test.esp32-idf.yaml b/tests/components/ssd1327_i2c/test.esp32-idf.yaml new file mode 100644 index 0000000000..e72a9c7b7a --- /dev/null +++ b/tests/components/ssd1327_i2c/test.esp32-idf.yaml @@ -0,0 +1,24 @@ +i2c: + - id: i2c_ssd1327_i2c + scl: 16 + sda: 17 + +display: + - platform: ssd1327_i2c + model: SSD1327_128x128 + reset_pin: 3 + address: 0x3C + id: display1 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, 10, 10); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1327_i2c/test.esp32.yaml b/tests/components/ssd1327_i2c/test.esp32.yaml new file mode 100644 index 0000000000..e72a9c7b7a --- /dev/null +++ b/tests/components/ssd1327_i2c/test.esp32.yaml @@ -0,0 +1,24 @@ +i2c: + - id: i2c_ssd1327_i2c + scl: 16 + sda: 17 + +display: + - platform: ssd1327_i2c + model: SSD1327_128x128 + reset_pin: 3 + address: 0x3C + id: display1 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, 10, 10); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1327_i2c/test.esp8266.yaml b/tests/components/ssd1327_i2c/test.esp8266.yaml new file mode 100644 index 0000000000..cd28795ff1 --- /dev/null +++ b/tests/components/ssd1327_i2c/test.esp8266.yaml @@ -0,0 +1,24 @@ +i2c: + - id: i2c_ssd1327_i2c + scl: 5 + sda: 4 + +display: + - platform: ssd1327_i2c + model: SSD1327_128x128 + reset_pin: 3 + address: 0x3C + id: display1 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, 10, 10); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1327_i2c/test.rp2040.yaml b/tests/components/ssd1327_i2c/test.rp2040.yaml new file mode 100644 index 0000000000..cd28795ff1 --- /dev/null +++ b/tests/components/ssd1327_i2c/test.rp2040.yaml @@ -0,0 +1,24 @@ +i2c: + - id: i2c_ssd1327_i2c + scl: 5 + sda: 4 + +display: + - platform: ssd1327_i2c + model: SSD1327_128x128 + reset_pin: 3 + address: 0x3C + id: display1 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, 10, 10); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1327_spi/test.esp32-c3-idf.yaml b/tests/components/ssd1327_spi/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..ec5795d716 --- /dev/null +++ b/tests/components/ssd1327_spi/test.esp32-c3-idf.yaml @@ -0,0 +1,25 @@ +spi: + - id: spi_ssd1327_spi + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +display: + - platform: ssd1327_spi + model: SSD1327 128x128 + cs_pin: 2 + dc_pin: 3 + reset_pin: 4 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1327_spi/test.esp32-c3.yaml b/tests/components/ssd1327_spi/test.esp32-c3.yaml new file mode 100644 index 0000000000..ec5795d716 --- /dev/null +++ b/tests/components/ssd1327_spi/test.esp32-c3.yaml @@ -0,0 +1,25 @@ +spi: + - id: spi_ssd1327_spi + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +display: + - platform: ssd1327_spi + model: SSD1327 128x128 + cs_pin: 2 + dc_pin: 3 + reset_pin: 4 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1327_spi/test.esp32-idf.yaml b/tests/components/ssd1327_spi/test.esp32-idf.yaml new file mode 100644 index 0000000000..e103ded187 --- /dev/null +++ b/tests/components/ssd1327_spi/test.esp32-idf.yaml @@ -0,0 +1,25 @@ +spi: + - id: spi_ssd1327_spi + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +display: + - platform: ssd1327_spi + model: SSD1327 128x128 + cs_pin: 12 + dc_pin: 13 + reset_pin: 14 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1327_spi/test.esp32.yaml b/tests/components/ssd1327_spi/test.esp32.yaml new file mode 100644 index 0000000000..e103ded187 --- /dev/null +++ b/tests/components/ssd1327_spi/test.esp32.yaml @@ -0,0 +1,25 @@ +spi: + - id: spi_ssd1327_spi + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +display: + - platform: ssd1327_spi + model: SSD1327 128x128 + cs_pin: 12 + dc_pin: 13 + reset_pin: 14 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1327_spi/test.esp8266.yaml b/tests/components/ssd1327_spi/test.esp8266.yaml new file mode 100644 index 0000000000..30455d24ee --- /dev/null +++ b/tests/components/ssd1327_spi/test.esp8266.yaml @@ -0,0 +1,25 @@ +spi: + - id: spi_ssd1327_spi + clk_pin: 14 + mosi_pin: 13 + miso_pin: 12 + +display: + - platform: ssd1327_spi + model: SSD1327 128x128 + cs_pin: 15 + dc_pin: 16 + reset_pin: 5 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1327_spi/test.rp2040.yaml b/tests/components/ssd1327_spi/test.rp2040.yaml new file mode 100644 index 0000000000..f819ab2c41 --- /dev/null +++ b/tests/components/ssd1327_spi/test.rp2040.yaml @@ -0,0 +1,25 @@ +spi: + - id: spi_ssd1327_spi + clk_pin: 2 + mosi_pin: 3 + miso_pin: 4 + +display: + - platform: ssd1327_spi + model: SSD1327 128x128 + cs_pin: 5 + dc_pin: 6 + reset_pin: 7 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1331_spi/test.esp32-c3-idf.yaml b/tests/components/ssd1331_spi/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..9a35918faf --- /dev/null +++ b/tests/components/ssd1331_spi/test.esp32-c3-idf.yaml @@ -0,0 +1,24 @@ +spi: + - id: spi_ssd1331_spi + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +display: + - platform: ssd1331_spi + cs_pin: 2 + dc_pin: 3 + reset_pin: 4 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1331_spi/test.esp32-c3.yaml b/tests/components/ssd1331_spi/test.esp32-c3.yaml new file mode 100644 index 0000000000..9a35918faf --- /dev/null +++ b/tests/components/ssd1331_spi/test.esp32-c3.yaml @@ -0,0 +1,24 @@ +spi: + - id: spi_ssd1331_spi + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +display: + - platform: ssd1331_spi + cs_pin: 2 + dc_pin: 3 + reset_pin: 4 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1331_spi/test.esp32-idf.yaml b/tests/components/ssd1331_spi/test.esp32-idf.yaml new file mode 100644 index 0000000000..e9eb8ea9ad --- /dev/null +++ b/tests/components/ssd1331_spi/test.esp32-idf.yaml @@ -0,0 +1,24 @@ +spi: + - id: spi_ssd1331_spi + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +display: + - platform: ssd1331_spi + cs_pin: 12 + dc_pin: 13 + reset_pin: 14 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1331_spi/test.esp32.yaml b/tests/components/ssd1331_spi/test.esp32.yaml new file mode 100644 index 0000000000..e9eb8ea9ad --- /dev/null +++ b/tests/components/ssd1331_spi/test.esp32.yaml @@ -0,0 +1,24 @@ +spi: + - id: spi_ssd1331_spi + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +display: + - platform: ssd1331_spi + cs_pin: 12 + dc_pin: 13 + reset_pin: 14 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1331_spi/test.esp8266.yaml b/tests/components/ssd1331_spi/test.esp8266.yaml new file mode 100644 index 0000000000..3b319ef38e --- /dev/null +++ b/tests/components/ssd1331_spi/test.esp8266.yaml @@ -0,0 +1,24 @@ +spi: + - id: spi_ssd1331_spi + clk_pin: 14 + mosi_pin: 13 + miso_pin: 12 + +display: + - platform: ssd1331_spi + cs_pin: 15 + dc_pin: 16 + reset_pin: 5 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1331_spi/test.rp2040.yaml b/tests/components/ssd1331_spi/test.rp2040.yaml new file mode 100644 index 0000000000..947685b07a --- /dev/null +++ b/tests/components/ssd1331_spi/test.rp2040.yaml @@ -0,0 +1,24 @@ +spi: + - id: spi_ssd1331_spi + clk_pin: 2 + mosi_pin: 3 + miso_pin: 4 + +display: + - platform: ssd1331_spi + cs_pin: 5 + dc_pin: 6 + reset_pin: 7 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1351_spi/test.esp32-c3-idf.yaml b/tests/components/ssd1351_spi/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..2a7266f502 --- /dev/null +++ b/tests/components/ssd1351_spi/test.esp32-c3-idf.yaml @@ -0,0 +1,25 @@ +spi: + - id: spi_ssd1351_spi + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +display: + - platform: ssd1351_spi + model: "SSD1351 128x128" + cs_pin: 2 + dc_pin: 3 + reset_pin: 4 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1351_spi/test.esp32-c3.yaml b/tests/components/ssd1351_spi/test.esp32-c3.yaml new file mode 100644 index 0000000000..2a7266f502 --- /dev/null +++ b/tests/components/ssd1351_spi/test.esp32-c3.yaml @@ -0,0 +1,25 @@ +spi: + - id: spi_ssd1351_spi + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +display: + - platform: ssd1351_spi + model: "SSD1351 128x128" + cs_pin: 2 + dc_pin: 3 + reset_pin: 4 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1351_spi/test.esp32-idf.yaml b/tests/components/ssd1351_spi/test.esp32-idf.yaml new file mode 100644 index 0000000000..8342cb972b --- /dev/null +++ b/tests/components/ssd1351_spi/test.esp32-idf.yaml @@ -0,0 +1,25 @@ +spi: + - id: spi_ssd1351_spi + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +display: + - platform: ssd1351_spi + model: "SSD1351 128x128" + cs_pin: 12 + dc_pin: 13 + reset_pin: 14 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1351_spi/test.esp32.yaml b/tests/components/ssd1351_spi/test.esp32.yaml new file mode 100644 index 0000000000..8342cb972b --- /dev/null +++ b/tests/components/ssd1351_spi/test.esp32.yaml @@ -0,0 +1,25 @@ +spi: + - id: spi_ssd1351_spi + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +display: + - platform: ssd1351_spi + model: "SSD1351 128x128" + cs_pin: 12 + dc_pin: 13 + reset_pin: 14 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1351_spi/test.esp8266.yaml b/tests/components/ssd1351_spi/test.esp8266.yaml new file mode 100644 index 0000000000..7ed9a31dde --- /dev/null +++ b/tests/components/ssd1351_spi/test.esp8266.yaml @@ -0,0 +1,25 @@ +spi: + - id: spi_ssd1351_spi + clk_pin: 14 + mosi_pin: 13 + miso_pin: 12 + +display: + - platform: ssd1351_spi + model: "SSD1351 128x128" + cs_pin: 15 + dc_pin: 16 + reset_pin: 5 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/ssd1351_spi/test.rp2040.yaml b/tests/components/ssd1351_spi/test.rp2040.yaml new file mode 100644 index 0000000000..72936d046b --- /dev/null +++ b/tests/components/ssd1351_spi/test.rp2040.yaml @@ -0,0 +1,25 @@ +spi: + - id: spi_ssd1351_spi + clk_pin: 2 + mosi_pin: 3 + miso_pin: 4 + +display: + - platform: ssd1351_spi + model: "SSD1351 128x128" + cs_pin: 5 + dc_pin: 6 + reset_pin: 7 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/st7567_i2c/test.esp32-c3-idf.yaml b/tests/components/st7567_i2c/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..d779040500 --- /dev/null +++ b/tests/components/st7567_i2c/test.esp32-c3-idf.yaml @@ -0,0 +1,23 @@ +i2c: + - id: i2c_st7567_i2c + scl: 5 + sda: 4 + +display: + - platform: st7567_i2c + reset_pin: 3 + address: 0x3C + id: display1 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, 10, 10); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/st7567_i2c/test.esp32-c3.yaml b/tests/components/st7567_i2c/test.esp32-c3.yaml new file mode 100644 index 0000000000..d779040500 --- /dev/null +++ b/tests/components/st7567_i2c/test.esp32-c3.yaml @@ -0,0 +1,23 @@ +i2c: + - id: i2c_st7567_i2c + scl: 5 + sda: 4 + +display: + - platform: st7567_i2c + reset_pin: 3 + address: 0x3C + id: display1 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, 10, 10); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/st7567_i2c/test.esp32-idf.yaml b/tests/components/st7567_i2c/test.esp32-idf.yaml new file mode 100644 index 0000000000..b7aee61b68 --- /dev/null +++ b/tests/components/st7567_i2c/test.esp32-idf.yaml @@ -0,0 +1,23 @@ +i2c: + - id: i2c_st7567_i2c + scl: 16 + sda: 17 + +display: + - platform: st7567_i2c + reset_pin: 3 + address: 0x3C + id: display1 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, 10, 10); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/st7567_i2c/test.esp32.yaml b/tests/components/st7567_i2c/test.esp32.yaml new file mode 100644 index 0000000000..b7aee61b68 --- /dev/null +++ b/tests/components/st7567_i2c/test.esp32.yaml @@ -0,0 +1,23 @@ +i2c: + - id: i2c_st7567_i2c + scl: 16 + sda: 17 + +display: + - platform: st7567_i2c + reset_pin: 3 + address: 0x3C + id: display1 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, 10, 10); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/st7567_i2c/test.esp8266.yaml b/tests/components/st7567_i2c/test.esp8266.yaml new file mode 100644 index 0000000000..d779040500 --- /dev/null +++ b/tests/components/st7567_i2c/test.esp8266.yaml @@ -0,0 +1,23 @@ +i2c: + - id: i2c_st7567_i2c + scl: 5 + sda: 4 + +display: + - platform: st7567_i2c + reset_pin: 3 + address: 0x3C + id: display1 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, 10, 10); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/st7567_i2c/test.rp2040.yaml b/tests/components/st7567_i2c/test.rp2040.yaml new file mode 100644 index 0000000000..d779040500 --- /dev/null +++ b/tests/components/st7567_i2c/test.rp2040.yaml @@ -0,0 +1,23 @@ +i2c: + - id: i2c_st7567_i2c + scl: 5 + sda: 4 + +display: + - platform: st7567_i2c + reset_pin: 3 + address: 0x3C + id: display1 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, 10, 10); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/st7567_spi/test.esp32-c3-idf.yaml b/tests/components/st7567_spi/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..b799ce7302 --- /dev/null +++ b/tests/components/st7567_spi/test.esp32-c3-idf.yaml @@ -0,0 +1,24 @@ +spi: + - id: spi_st7567_spi + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +display: + - platform: st7567_spi + cs_pin: 2 + dc_pin: 3 + reset_pin: 4 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/st7567_spi/test.esp32-c3.yaml b/tests/components/st7567_spi/test.esp32-c3.yaml new file mode 100644 index 0000000000..b799ce7302 --- /dev/null +++ b/tests/components/st7567_spi/test.esp32-c3.yaml @@ -0,0 +1,24 @@ +spi: + - id: spi_st7567_spi + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +display: + - platform: st7567_spi + cs_pin: 2 + dc_pin: 3 + reset_pin: 4 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/st7567_spi/test.esp32-idf.yaml b/tests/components/st7567_spi/test.esp32-idf.yaml new file mode 100644 index 0000000000..bb4530248f --- /dev/null +++ b/tests/components/st7567_spi/test.esp32-idf.yaml @@ -0,0 +1,24 @@ +spi: + - id: spi_st7567_spi + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +display: + - platform: st7567_spi + cs_pin: 12 + dc_pin: 13 + reset_pin: 14 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/st7567_spi/test.esp32.yaml b/tests/components/st7567_spi/test.esp32.yaml new file mode 100644 index 0000000000..bb4530248f --- /dev/null +++ b/tests/components/st7567_spi/test.esp32.yaml @@ -0,0 +1,24 @@ +spi: + - id: spi_st7567_spi + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +display: + - platform: st7567_spi + cs_pin: 12 + dc_pin: 13 + reset_pin: 14 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/st7567_spi/test.esp8266.yaml b/tests/components/st7567_spi/test.esp8266.yaml new file mode 100644 index 0000000000..bbc47e67f6 --- /dev/null +++ b/tests/components/st7567_spi/test.esp8266.yaml @@ -0,0 +1,24 @@ +spi: + - id: spi_st7567_spi + clk_pin: 14 + mosi_pin: 13 + miso_pin: 12 + +display: + - platform: st7567_spi + cs_pin: 15 + dc_pin: 16 + reset_pin: 5 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/st7567_spi/test.rp2040.yaml b/tests/components/st7567_spi/test.rp2040.yaml new file mode 100644 index 0000000000..1b491101a8 --- /dev/null +++ b/tests/components/st7567_spi/test.rp2040.yaml @@ -0,0 +1,24 @@ +spi: + - id: spi_st7567_spi + clk_pin: 2 + mosi_pin: 3 + miso_pin: 4 + +display: + - platform: st7567_spi + cs_pin: 5 + dc_pin: 6 + reset_pin: 7 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/st7735/test.esp32-c3-idf.yaml b/tests/components/st7735/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..fc6c2421c4 --- /dev/null +++ b/tests/components/st7735/test.esp32-c3-idf.yaml @@ -0,0 +1,29 @@ +spi: + - id: spi_st7735 + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +display: + - platform: st7735 + model: "INITR_18BLACKTAB" + cs_pin: 2 + dc_pin: 3 + reset_pin: 4 + device_width: 128 + device_height: 160 + col_start: 0 + row_start: 0 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/st7735/test.esp32-c3.yaml b/tests/components/st7735/test.esp32-c3.yaml new file mode 100644 index 0000000000..fc6c2421c4 --- /dev/null +++ b/tests/components/st7735/test.esp32-c3.yaml @@ -0,0 +1,29 @@ +spi: + - id: spi_st7735 + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +display: + - platform: st7735 + model: "INITR_18BLACKTAB" + cs_pin: 2 + dc_pin: 3 + reset_pin: 4 + device_width: 128 + device_height: 160 + col_start: 0 + row_start: 0 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/st7735/test.esp32-idf.yaml b/tests/components/st7735/test.esp32-idf.yaml new file mode 100644 index 0000000000..fd3f6cade6 --- /dev/null +++ b/tests/components/st7735/test.esp32-idf.yaml @@ -0,0 +1,29 @@ +spi: + - id: spi_st7735 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +display: + - platform: st7735 + model: "INITR_18BLACKTAB" + cs_pin: 12 + dc_pin: 13 + reset_pin: 14 + device_width: 128 + device_height: 160 + col_start: 0 + row_start: 0 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/st7735/test.esp32.yaml b/tests/components/st7735/test.esp32.yaml new file mode 100644 index 0000000000..fd3f6cade6 --- /dev/null +++ b/tests/components/st7735/test.esp32.yaml @@ -0,0 +1,29 @@ +spi: + - id: spi_st7735 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +display: + - platform: st7735 + model: "INITR_18BLACKTAB" + cs_pin: 12 + dc_pin: 13 + reset_pin: 14 + device_width: 128 + device_height: 160 + col_start: 0 + row_start: 0 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/st7735/test.esp8266.yaml b/tests/components/st7735/test.esp8266.yaml new file mode 100644 index 0000000000..ea8fa93c36 --- /dev/null +++ b/tests/components/st7735/test.esp8266.yaml @@ -0,0 +1,29 @@ +spi: + - id: spi_st7735 + clk_pin: 14 + mosi_pin: 13 + miso_pin: 12 + +display: + - platform: st7735 + model: "INITR_18BLACKTAB" + cs_pin: 15 + dc_pin: 16 + reset_pin: 5 + device_width: 128 + device_height: 160 + col_start: 0 + row_start: 0 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/st7735/test.rp2040.yaml b/tests/components/st7735/test.rp2040.yaml new file mode 100644 index 0000000000..828f9a3ae1 --- /dev/null +++ b/tests/components/st7735/test.rp2040.yaml @@ -0,0 +1,29 @@ +spi: + - id: spi_st7735 + clk_pin: 2 + mosi_pin: 3 + miso_pin: 4 + +display: + - platform: st7735 + model: "INITR_18BLACKTAB" + cs_pin: 5 + dc_pin: 6 + reset_pin: 7 + device_width: 128 + device_height: 160 + col_start: 0 + row_start: 0 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/st7789v/test.esp32-c3-idf.yaml b/tests/components/st7789v/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..1cb8d22fcb --- /dev/null +++ b/tests/components/st7789v/test.esp32-c3-idf.yaml @@ -0,0 +1,25 @@ +spi: + - id: spi_st7789v + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +display: + - platform: st7789v + model: TTGO TDisplay 135x240 + cs_pin: 2 + dc_pin: 3 + reset_pin: 8 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/st7789v/test.esp32-c3.yaml b/tests/components/st7789v/test.esp32-c3.yaml new file mode 100644 index 0000000000..1cb8d22fcb --- /dev/null +++ b/tests/components/st7789v/test.esp32-c3.yaml @@ -0,0 +1,25 @@ +spi: + - id: spi_st7789v + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +display: + - platform: st7789v + model: TTGO TDisplay 135x240 + cs_pin: 2 + dc_pin: 3 + reset_pin: 8 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/st7789v/test.esp32-idf.yaml b/tests/components/st7789v/test.esp32-idf.yaml new file mode 100644 index 0000000000..54a9db6da1 --- /dev/null +++ b/tests/components/st7789v/test.esp32-idf.yaml @@ -0,0 +1,25 @@ +spi: + - id: spi_st7789v + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +display: + - platform: st7789v + model: TTGO TDisplay 135x240 + cs_pin: 12 + dc_pin: 13 + reset_pin: 14 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/st7789v/test.esp32.yaml b/tests/components/st7789v/test.esp32.yaml new file mode 100644 index 0000000000..54a9db6da1 --- /dev/null +++ b/tests/components/st7789v/test.esp32.yaml @@ -0,0 +1,25 @@ +spi: + - id: spi_st7789v + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +display: + - platform: st7789v + model: TTGO TDisplay 135x240 + cs_pin: 12 + dc_pin: 13 + reset_pin: 14 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/st7789v/test.esp8266.yaml b/tests/components/st7789v/test.esp8266.yaml new file mode 100644 index 0000000000..deeceb8c9a --- /dev/null +++ b/tests/components/st7789v/test.esp8266.yaml @@ -0,0 +1,25 @@ +spi: + - id: spi_st7789v + clk_pin: 14 + mosi_pin: 13 + miso_pin: 12 + +display: + - platform: st7789v + model: TTGO TDisplay 135x240 + cs_pin: 15 + dc_pin: 16 + reset_pin: 5 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/st7789v/test.rp2040.yaml b/tests/components/st7789v/test.rp2040.yaml new file mode 100644 index 0000000000..778aa2aa55 --- /dev/null +++ b/tests/components/st7789v/test.rp2040.yaml @@ -0,0 +1,25 @@ +spi: + - id: spi_st7789v + clk_pin: 2 + mosi_pin: 3 + miso_pin: 8 + +display: + - platform: st7789v + model: TTGO TDisplay 135x240 + cs_pin: 5 + dc_pin: 6 + reset_pin: 7 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/st7920/test.esp32-c3-idf.yaml b/tests/components/st7920/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..84ae88461f --- /dev/null +++ b/tests/components/st7920/test.esp32-c3-idf.yaml @@ -0,0 +1,24 @@ +spi: + - id: spi_st7920 + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +display: + - platform: st7920 + cs_pin: 2 + height: 128 + width: 64 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/st7920/test.esp32-c3.yaml b/tests/components/st7920/test.esp32-c3.yaml new file mode 100644 index 0000000000..84ae88461f --- /dev/null +++ b/tests/components/st7920/test.esp32-c3.yaml @@ -0,0 +1,24 @@ +spi: + - id: spi_st7920 + clk_pin: 6 + mosi_pin: 7 + miso_pin: 5 + +display: + - platform: st7920 + cs_pin: 2 + height: 128 + width: 64 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/st7920/test.esp32-idf.yaml b/tests/components/st7920/test.esp32-idf.yaml new file mode 100644 index 0000000000..cdcbc85642 --- /dev/null +++ b/tests/components/st7920/test.esp32-idf.yaml @@ -0,0 +1,24 @@ +spi: + - id: spi_st7920 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +display: + - platform: st7920 + cs_pin: 12 + height: 128 + width: 64 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/st7920/test.esp32.yaml b/tests/components/st7920/test.esp32.yaml new file mode 100644 index 0000000000..cdcbc85642 --- /dev/null +++ b/tests/components/st7920/test.esp32.yaml @@ -0,0 +1,24 @@ +spi: + - id: spi_st7920 + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +display: + - platform: st7920 + cs_pin: 12 + height: 128 + width: 64 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/st7920/test.esp8266.yaml b/tests/components/st7920/test.esp8266.yaml new file mode 100644 index 0000000000..0450bf1c5e --- /dev/null +++ b/tests/components/st7920/test.esp8266.yaml @@ -0,0 +1,24 @@ +spi: + - id: spi_st7920 + clk_pin: 14 + mosi_pin: 13 + miso_pin: 12 + +display: + - platform: st7920 + cs_pin: 15 + height: 128 + width: 64 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/st7920/test.rp2040.yaml b/tests/components/st7920/test.rp2040.yaml new file mode 100644 index 0000000000..f442820e7b --- /dev/null +++ b/tests/components/st7920/test.rp2040.yaml @@ -0,0 +1,24 @@ +spi: + - id: spi_st7920 + clk_pin: 2 + mosi_pin: 3 + miso_pin: 4 + +display: + - platform: st7920 + cs_pin: 5 + height: 128 + width: 64 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - id: page2 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + on_page_change: + from: page1 + to: page2 + then: + lambda: |- + ESP_LOGD("display", "1 -> 2"); diff --git a/tests/components/status/test.esp32-c3-idf.yaml b/tests/components/status/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..c14157566b --- /dev/null +++ b/tests/components/status/test.esp32-c3-idf.yaml @@ -0,0 +1,10 @@ +wifi: + ssid: MySSID + password: password1 + +api: + +binary_sensor: + - platform: status + id: node_status + name: Node Status diff --git a/tests/components/status/test.esp32-c3.yaml b/tests/components/status/test.esp32-c3.yaml new file mode 100644 index 0000000000..c14157566b --- /dev/null +++ b/tests/components/status/test.esp32-c3.yaml @@ -0,0 +1,10 @@ +wifi: + ssid: MySSID + password: password1 + +api: + +binary_sensor: + - platform: status + id: node_status + name: Node Status diff --git a/tests/components/status/test.esp32-idf.yaml b/tests/components/status/test.esp32-idf.yaml new file mode 100644 index 0000000000..c14157566b --- /dev/null +++ b/tests/components/status/test.esp32-idf.yaml @@ -0,0 +1,10 @@ +wifi: + ssid: MySSID + password: password1 + +api: + +binary_sensor: + - platform: status + id: node_status + name: Node Status diff --git a/tests/components/status/test.esp32.yaml b/tests/components/status/test.esp32.yaml new file mode 100644 index 0000000000..c14157566b --- /dev/null +++ b/tests/components/status/test.esp32.yaml @@ -0,0 +1,10 @@ +wifi: + ssid: MySSID + password: password1 + +api: + +binary_sensor: + - platform: status + id: node_status + name: Node Status diff --git a/tests/components/status/test.esp8266.yaml b/tests/components/status/test.esp8266.yaml new file mode 100644 index 0000000000..c14157566b --- /dev/null +++ b/tests/components/status/test.esp8266.yaml @@ -0,0 +1,10 @@ +wifi: + ssid: MySSID + password: password1 + +api: + +binary_sensor: + - platform: status + id: node_status + name: Node Status diff --git a/tests/components/status/test.rp2040.yaml b/tests/components/status/test.rp2040.yaml new file mode 100644 index 0000000000..c14157566b --- /dev/null +++ b/tests/components/status/test.rp2040.yaml @@ -0,0 +1,10 @@ +wifi: + ssid: MySSID + password: password1 + +api: + +binary_sensor: + - platform: status + id: node_status + name: Node Status diff --git a/tests/components/status_led/test.esp32-c3-idf.yaml b/tests/components/status_led/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..ec66c219d3 --- /dev/null +++ b/tests/components/status_led/test.esp32-c3-idf.yaml @@ -0,0 +1,10 @@ +wifi: + ssid: MySSID + password: password1 + +api: + +light: + - platform: status_led + name: Switch State + pin: 4 diff --git a/tests/components/status_led/test.esp32-c3.yaml b/tests/components/status_led/test.esp32-c3.yaml new file mode 100644 index 0000000000..ec66c219d3 --- /dev/null +++ b/tests/components/status_led/test.esp32-c3.yaml @@ -0,0 +1,10 @@ +wifi: + ssid: MySSID + password: password1 + +api: + +light: + - platform: status_led + name: Switch State + pin: 4 diff --git a/tests/components/status_led/test.esp32-idf.yaml b/tests/components/status_led/test.esp32-idf.yaml new file mode 100644 index 0000000000..ec66c219d3 --- /dev/null +++ b/tests/components/status_led/test.esp32-idf.yaml @@ -0,0 +1,10 @@ +wifi: + ssid: MySSID + password: password1 + +api: + +light: + - platform: status_led + name: Switch State + pin: 4 diff --git a/tests/components/status_led/test.esp32.yaml b/tests/components/status_led/test.esp32.yaml new file mode 100644 index 0000000000..ec66c219d3 --- /dev/null +++ b/tests/components/status_led/test.esp32.yaml @@ -0,0 +1,10 @@ +wifi: + ssid: MySSID + password: password1 + +api: + +light: + - platform: status_led + name: Switch State + pin: 4 diff --git a/tests/components/status_led/test.esp8266.yaml b/tests/components/status_led/test.esp8266.yaml new file mode 100644 index 0000000000..ec66c219d3 --- /dev/null +++ b/tests/components/status_led/test.esp8266.yaml @@ -0,0 +1,10 @@ +wifi: + ssid: MySSID + password: password1 + +api: + +light: + - platform: status_led + name: Switch State + pin: 4 diff --git a/tests/components/status_led/test.rp2040.yaml b/tests/components/status_led/test.rp2040.yaml new file mode 100644 index 0000000000..ec66c219d3 --- /dev/null +++ b/tests/components/status_led/test.rp2040.yaml @@ -0,0 +1,10 @@ +wifi: + ssid: MySSID + password: password1 + +api: + +light: + - platform: status_led + name: Switch State + pin: 4 diff --git a/tests/components/stepper/test.esp32-c3-idf.yaml b/tests/components/stepper/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..fcf5759618 --- /dev/null +++ b/tests/components/stepper/test.esp32-c3-idf.yaml @@ -0,0 +1,27 @@ +stepper: + - platform: a4988 + id: test_stepper + step_pin: 3 + dir_pin: 4 + sleep_pin: 5 + max_speed: 250 steps/s + acceleration: 100 steps/s^2 + deceleration: 200 steps/s^2 + +switch: + - platform: template + name: Stepper Switch + assumed_state: true + turn_on_action: + - stepper.set_target: + id: test_stepper + target: !lambda |- + static int32_t i = 0; + i += 1000; + if (i > 5000) { + i = -5000; + } + return i; + - stepper.report_position: + id: test_stepper + position: 0 diff --git a/tests/components/stepper/test.esp32-c3.yaml b/tests/components/stepper/test.esp32-c3.yaml new file mode 100644 index 0000000000..fcf5759618 --- /dev/null +++ b/tests/components/stepper/test.esp32-c3.yaml @@ -0,0 +1,27 @@ +stepper: + - platform: a4988 + id: test_stepper + step_pin: 3 + dir_pin: 4 + sleep_pin: 5 + max_speed: 250 steps/s + acceleration: 100 steps/s^2 + deceleration: 200 steps/s^2 + +switch: + - platform: template + name: Stepper Switch + assumed_state: true + turn_on_action: + - stepper.set_target: + id: test_stepper + target: !lambda |- + static int32_t i = 0; + i += 1000; + if (i > 5000) { + i = -5000; + } + return i; + - stepper.report_position: + id: test_stepper + position: 0 diff --git a/tests/components/stepper/test.esp32-idf.yaml b/tests/components/stepper/test.esp32-idf.yaml new file mode 100644 index 0000000000..fcf5759618 --- /dev/null +++ b/tests/components/stepper/test.esp32-idf.yaml @@ -0,0 +1,27 @@ +stepper: + - platform: a4988 + id: test_stepper + step_pin: 3 + dir_pin: 4 + sleep_pin: 5 + max_speed: 250 steps/s + acceleration: 100 steps/s^2 + deceleration: 200 steps/s^2 + +switch: + - platform: template + name: Stepper Switch + assumed_state: true + turn_on_action: + - stepper.set_target: + id: test_stepper + target: !lambda |- + static int32_t i = 0; + i += 1000; + if (i > 5000) { + i = -5000; + } + return i; + - stepper.report_position: + id: test_stepper + position: 0 diff --git a/tests/components/stepper/test.esp32.yaml b/tests/components/stepper/test.esp32.yaml new file mode 100644 index 0000000000..fcf5759618 --- /dev/null +++ b/tests/components/stepper/test.esp32.yaml @@ -0,0 +1,27 @@ +stepper: + - platform: a4988 + id: test_stepper + step_pin: 3 + dir_pin: 4 + sleep_pin: 5 + max_speed: 250 steps/s + acceleration: 100 steps/s^2 + deceleration: 200 steps/s^2 + +switch: + - platform: template + name: Stepper Switch + assumed_state: true + turn_on_action: + - stepper.set_target: + id: test_stepper + target: !lambda |- + static int32_t i = 0; + i += 1000; + if (i > 5000) { + i = -5000; + } + return i; + - stepper.report_position: + id: test_stepper + position: 0 diff --git a/tests/components/stepper/test.esp8266.yaml b/tests/components/stepper/test.esp8266.yaml new file mode 100644 index 0000000000..fcf5759618 --- /dev/null +++ b/tests/components/stepper/test.esp8266.yaml @@ -0,0 +1,27 @@ +stepper: + - platform: a4988 + id: test_stepper + step_pin: 3 + dir_pin: 4 + sleep_pin: 5 + max_speed: 250 steps/s + acceleration: 100 steps/s^2 + deceleration: 200 steps/s^2 + +switch: + - platform: template + name: Stepper Switch + assumed_state: true + turn_on_action: + - stepper.set_target: + id: test_stepper + target: !lambda |- + static int32_t i = 0; + i += 1000; + if (i > 5000) { + i = -5000; + } + return i; + - stepper.report_position: + id: test_stepper + position: 0 diff --git a/tests/components/stepper/test.rp2040.yaml b/tests/components/stepper/test.rp2040.yaml new file mode 100644 index 0000000000..fcf5759618 --- /dev/null +++ b/tests/components/stepper/test.rp2040.yaml @@ -0,0 +1,27 @@ +stepper: + - platform: a4988 + id: test_stepper + step_pin: 3 + dir_pin: 4 + sleep_pin: 5 + max_speed: 250 steps/s + acceleration: 100 steps/s^2 + deceleration: 200 steps/s^2 + +switch: + - platform: template + name: Stepper Switch + assumed_state: true + turn_on_action: + - stepper.set_target: + id: test_stepper + target: !lambda |- + static int32_t i = 0; + i += 1000; + if (i > 5000) { + i = -5000; + } + return i; + - stepper.report_position: + id: test_stepper + position: 0 diff --git a/tests/components/sts3x/test.esp32-c3-idf.yaml b/tests/components/sts3x/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..87980ce3a7 --- /dev/null +++ b/tests/components/sts3x/test.esp32-c3-idf.yaml @@ -0,0 +1,10 @@ +i2c: + - id: i2c_sts3x + scl: 5 + sda: 4 + +sensor: + - platform: sts3x + id: sts3x_sensor + name: STS3X Temperature + address: 0x4A diff --git a/tests/components/sts3x/test.esp32-c3.yaml b/tests/components/sts3x/test.esp32-c3.yaml new file mode 100644 index 0000000000..87980ce3a7 --- /dev/null +++ b/tests/components/sts3x/test.esp32-c3.yaml @@ -0,0 +1,10 @@ +i2c: + - id: i2c_sts3x + scl: 5 + sda: 4 + +sensor: + - platform: sts3x + id: sts3x_sensor + name: STS3X Temperature + address: 0x4A diff --git a/tests/components/sts3x/test.esp32-idf.yaml b/tests/components/sts3x/test.esp32-idf.yaml new file mode 100644 index 0000000000..a74d61e748 --- /dev/null +++ b/tests/components/sts3x/test.esp32-idf.yaml @@ -0,0 +1,10 @@ +i2c: + - id: i2c_sts3x + scl: 16 + sda: 17 + +sensor: + - platform: sts3x + id: sts3x_sensor + name: STS3X Temperature + address: 0x4A diff --git a/tests/components/sts3x/test.esp32.yaml b/tests/components/sts3x/test.esp32.yaml new file mode 100644 index 0000000000..a74d61e748 --- /dev/null +++ b/tests/components/sts3x/test.esp32.yaml @@ -0,0 +1,10 @@ +i2c: + - id: i2c_sts3x + scl: 16 + sda: 17 + +sensor: + - platform: sts3x + id: sts3x_sensor + name: STS3X Temperature + address: 0x4A diff --git a/tests/components/sts3x/test.esp8266.yaml b/tests/components/sts3x/test.esp8266.yaml new file mode 100644 index 0000000000..87980ce3a7 --- /dev/null +++ b/tests/components/sts3x/test.esp8266.yaml @@ -0,0 +1,10 @@ +i2c: + - id: i2c_sts3x + scl: 5 + sda: 4 + +sensor: + - platform: sts3x + id: sts3x_sensor + name: STS3X Temperature + address: 0x4A diff --git a/tests/components/sts3x/test.rp2040.yaml b/tests/components/sts3x/test.rp2040.yaml new file mode 100644 index 0000000000..87980ce3a7 --- /dev/null +++ b/tests/components/sts3x/test.rp2040.yaml @@ -0,0 +1,10 @@ +i2c: + - id: i2c_sts3x + scl: 5 + sda: 4 + +sensor: + - platform: sts3x + id: sts3x_sensor + name: STS3X Temperature + address: 0x4A diff --git a/tests/components/sun/test.esp32-c3-idf.yaml b/tests/components/sun/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..e0157424a0 --- /dev/null +++ b/tests/components/sun/test.esp32-c3-idf.yaml @@ -0,0 +1,38 @@ +wifi: + ssid: MySSID + password: password1 + +api: + +time: + - platform: homeassistant + id: homeassistant_time + +sun: + latitude: 48.8584° + longitude: 2.2945° + on_sunrise: + - then: + - logger.log: Good morning + - elevation: 5° + then: + - logger.log: Good morning again + on_sunset: + - then: + - logger.log: Good evening + +sensor: + - platform: sun + name: Sun Elevation + type: elevation + - platform: sun + name: Sun Azimuth + type: azimuth + +text_sensor: + - platform: sun + name: Sun Next Sunrise + type: sunrise + - platform: sun + name: Sun Next Sunset + type: sunset diff --git a/tests/components/sun/test.esp32-c3.yaml b/tests/components/sun/test.esp32-c3.yaml new file mode 100644 index 0000000000..e0157424a0 --- /dev/null +++ b/tests/components/sun/test.esp32-c3.yaml @@ -0,0 +1,38 @@ +wifi: + ssid: MySSID + password: password1 + +api: + +time: + - platform: homeassistant + id: homeassistant_time + +sun: + latitude: 48.8584° + longitude: 2.2945° + on_sunrise: + - then: + - logger.log: Good morning + - elevation: 5° + then: + - logger.log: Good morning again + on_sunset: + - then: + - logger.log: Good evening + +sensor: + - platform: sun + name: Sun Elevation + type: elevation + - platform: sun + name: Sun Azimuth + type: azimuth + +text_sensor: + - platform: sun + name: Sun Next Sunrise + type: sunrise + - platform: sun + name: Sun Next Sunset + type: sunset diff --git a/tests/components/sun/test.esp32-idf.yaml b/tests/components/sun/test.esp32-idf.yaml new file mode 100644 index 0000000000..e0157424a0 --- /dev/null +++ b/tests/components/sun/test.esp32-idf.yaml @@ -0,0 +1,38 @@ +wifi: + ssid: MySSID + password: password1 + +api: + +time: + - platform: homeassistant + id: homeassistant_time + +sun: + latitude: 48.8584° + longitude: 2.2945° + on_sunrise: + - then: + - logger.log: Good morning + - elevation: 5° + then: + - logger.log: Good morning again + on_sunset: + - then: + - logger.log: Good evening + +sensor: + - platform: sun + name: Sun Elevation + type: elevation + - platform: sun + name: Sun Azimuth + type: azimuth + +text_sensor: + - platform: sun + name: Sun Next Sunrise + type: sunrise + - platform: sun + name: Sun Next Sunset + type: sunset diff --git a/tests/components/sun/test.esp32.yaml b/tests/components/sun/test.esp32.yaml new file mode 100644 index 0000000000..e0157424a0 --- /dev/null +++ b/tests/components/sun/test.esp32.yaml @@ -0,0 +1,38 @@ +wifi: + ssid: MySSID + password: password1 + +api: + +time: + - platform: homeassistant + id: homeassistant_time + +sun: + latitude: 48.8584° + longitude: 2.2945° + on_sunrise: + - then: + - logger.log: Good morning + - elevation: 5° + then: + - logger.log: Good morning again + on_sunset: + - then: + - logger.log: Good evening + +sensor: + - platform: sun + name: Sun Elevation + type: elevation + - platform: sun + name: Sun Azimuth + type: azimuth + +text_sensor: + - platform: sun + name: Sun Next Sunrise + type: sunrise + - platform: sun + name: Sun Next Sunset + type: sunset diff --git a/tests/components/sun/test.esp8266.yaml b/tests/components/sun/test.esp8266.yaml new file mode 100644 index 0000000000..e0157424a0 --- /dev/null +++ b/tests/components/sun/test.esp8266.yaml @@ -0,0 +1,38 @@ +wifi: + ssid: MySSID + password: password1 + +api: + +time: + - platform: homeassistant + id: homeassistant_time + +sun: + latitude: 48.8584° + longitude: 2.2945° + on_sunrise: + - then: + - logger.log: Good morning + - elevation: 5° + then: + - logger.log: Good morning again + on_sunset: + - then: + - logger.log: Good evening + +sensor: + - platform: sun + name: Sun Elevation + type: elevation + - platform: sun + name: Sun Azimuth + type: azimuth + +text_sensor: + - platform: sun + name: Sun Next Sunrise + type: sunrise + - platform: sun + name: Sun Next Sunset + type: sunset diff --git a/tests/components/sun/test.rp2040.yaml b/tests/components/sun/test.rp2040.yaml new file mode 100644 index 0000000000..e0157424a0 --- /dev/null +++ b/tests/components/sun/test.rp2040.yaml @@ -0,0 +1,38 @@ +wifi: + ssid: MySSID + password: password1 + +api: + +time: + - platform: homeassistant + id: homeassistant_time + +sun: + latitude: 48.8584° + longitude: 2.2945° + on_sunrise: + - then: + - logger.log: Good morning + - elevation: 5° + then: + - logger.log: Good morning again + on_sunset: + - then: + - logger.log: Good evening + +sensor: + - platform: sun + name: Sun Elevation + type: elevation + - platform: sun + name: Sun Azimuth + type: azimuth + +text_sensor: + - platform: sun + name: Sun Next Sunrise + type: sunrise + - platform: sun + name: Sun Next Sunset + type: sunset diff --git a/tests/components/sx1509/test.esp32-c3-idf.yaml b/tests/components/sx1509/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..ced849b3df --- /dev/null +++ b/tests/components/sx1509/test.esp32-c3-idf.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_sx1509 + scl: 5 + sda: 4 + +sx1509: + - id: sx1509_hub + address: 0x3E + +binary_sensor: + - platform: gpio + name: GPIO SX1509 Test + pin: + sx1509: sx1509_hub + number: 3 diff --git a/tests/components/sx1509/test.esp32-c3.yaml b/tests/components/sx1509/test.esp32-c3.yaml new file mode 100644 index 0000000000..ced849b3df --- /dev/null +++ b/tests/components/sx1509/test.esp32-c3.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_sx1509 + scl: 5 + sda: 4 + +sx1509: + - id: sx1509_hub + address: 0x3E + +binary_sensor: + - platform: gpio + name: GPIO SX1509 Test + pin: + sx1509: sx1509_hub + number: 3 diff --git a/tests/components/sx1509/test.esp32-idf.yaml b/tests/components/sx1509/test.esp32-idf.yaml new file mode 100644 index 0000000000..1698f2abc4 --- /dev/null +++ b/tests/components/sx1509/test.esp32-idf.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_sx1509 + scl: 16 + sda: 17 + +sx1509: + - id: sx1509_hub + address: 0x3E + +binary_sensor: + - platform: gpio + name: GPIO SX1509 Test + pin: + sx1509: sx1509_hub + number: 3 diff --git a/tests/components/sx1509/test.esp32.yaml b/tests/components/sx1509/test.esp32.yaml new file mode 100644 index 0000000000..1698f2abc4 --- /dev/null +++ b/tests/components/sx1509/test.esp32.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_sx1509 + scl: 16 + sda: 17 + +sx1509: + - id: sx1509_hub + address: 0x3E + +binary_sensor: + - platform: gpio + name: GPIO SX1509 Test + pin: + sx1509: sx1509_hub + number: 3 diff --git a/tests/components/sx1509/test.esp8266.yaml b/tests/components/sx1509/test.esp8266.yaml new file mode 100644 index 0000000000..ced849b3df --- /dev/null +++ b/tests/components/sx1509/test.esp8266.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_sx1509 + scl: 5 + sda: 4 + +sx1509: + - id: sx1509_hub + address: 0x3E + +binary_sensor: + - platform: gpio + name: GPIO SX1509 Test + pin: + sx1509: sx1509_hub + number: 3 diff --git a/tests/components/sx1509/test.rp2040.yaml b/tests/components/sx1509/test.rp2040.yaml new file mode 100644 index 0000000000..ced849b3df --- /dev/null +++ b/tests/components/sx1509/test.rp2040.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_sx1509 + scl: 5 + sda: 4 + +sx1509: + - id: sx1509_hub + address: 0x3E + +binary_sensor: + - platform: gpio + name: GPIO SX1509 Test + pin: + sx1509: sx1509_hub + number: 3 From 8027921ba3c226fd489dd8f12ccbe8f3f6f2aa80 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Wed, 24 Apr 2024 05:55:27 +1000 Subject: [PATCH 1315/2101] `graphical_display_menu` requires a Display, not DisplayBuffer (#6614) --- esphome/components/graphical_display_menu/__init__.py | 2 +- .../graphical_display_menu/graphical_display_menu.cpp | 3 ++- esphome/core/color.h | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/esphome/components/graphical_display_menu/__init__.py b/esphome/components/graphical_display_menu/__init__.py index dc49358efd..3849449523 100644 --- a/esphome/components/graphical_display_menu/__init__.py +++ b/esphome/components/graphical_display_menu/__init__.py @@ -38,7 +38,7 @@ CONFIG_SCHEMA = DISPLAY_MENU_BASE_SCHEMA.extend( cv.Schema( { cv.GenerateID(): cv.declare_id(GraphicalDisplayMenu), - cv.Optional(CONF_DISPLAY): cv.use_id(display.DisplayBuffer), + cv.Optional(CONF_DISPLAY): cv.use_id(display.Display), cv.Required(CONF_FONT): cv.use_id(font.Font), cv.Optional(CONF_MENU_ITEM_VALUE): cv.templatable(cv.string), cv.Optional(CONF_FOREGROUND_COLOR): cv.use_id(color.ColorStruct), diff --git a/esphome/components/graphical_display_menu/graphical_display_menu.cpp b/esphome/components/graphical_display_menu/graphical_display_menu.cpp index 2e4c14fb7b..fcbad41388 100644 --- a/esphome/components/graphical_display_menu/graphical_display_menu.cpp +++ b/esphome/components/graphical_display_menu/graphical_display_menu.cpp @@ -229,7 +229,8 @@ inline void GraphicalDisplayMenu::draw_item(display::Display *display, const dis label.append(this->menu_item_value_.value(&args)); } - display->print(bounds->x, bounds->y, this->font_, foreground_color, display::TextAlign::TOP_LEFT, label.c_str()); + display->print(bounds->x, bounds->y, this->font_, foreground_color, display::TextAlign::TOP_LEFT, label.c_str(), + ~foreground_color); } void GraphicalDisplayMenu::draw_item(const display_menu_base::MenuItem *item, const uint8_t row, const bool selected) { diff --git a/esphome/core/color.h b/esphome/core/color.h index 45b2d4c871..fb72973017 100644 --- a/esphome/core/color.h +++ b/esphome/core/color.h @@ -62,6 +62,7 @@ struct Color { return Color(esp_scale8(this->red, scale), esp_scale8(this->green, scale), esp_scale8(this->blue, scale), esp_scale8(this->white, scale)); } + inline Color operator~() const ALWAYS_INLINE { return Color(255 - this->red, 255 - this->green, 255 - this->blue); } inline Color &operator*=(uint8_t scale) ALWAYS_INLINE { this->red = esp_scale8(this->red, scale); this->green = esp_scale8(this->green, scale); From b8f0182fc5b93c45eeafb048695ac655bcf3297e Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Wed, 24 Apr 2024 06:49:14 +1000 Subject: [PATCH 1316/2101] Add null GPIO pin (#6611) --- .../cst226/touchscreen/cst226_touchscreen.cpp | 18 +++++++----------- .../cst226/touchscreen/cst226_touchscreen.h | 2 +- esphome/core/gpio.h | 18 ++++++++++++++++++ 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/esphome/components/cst226/touchscreen/cst226_touchscreen.cpp b/esphome/components/cst226/touchscreen/cst226_touchscreen.cpp index d4e43d30f5..69728dc666 100644 --- a/esphome/components/cst226/touchscreen/cst226_touchscreen.cpp +++ b/esphome/components/cst226/touchscreen/cst226_touchscreen.cpp @@ -5,17 +5,13 @@ namespace cst226 { void CST226Touchscreen::setup() { esph_log_config(TAG, "Setting up CST226 Touchscreen..."); - if (this->reset_pin_ != nullptr) { - this->reset_pin_->setup(); - this->reset_pin_->digital_write(true); - delay(5); - this->reset_pin_->digital_write(false); - delay(5); - this->reset_pin_->digital_write(true); - this->set_timeout(30, [this] { this->continue_setup_(); }); - } else { - this->continue_setup_(); - } + this->reset_pin_->setup(); + this->reset_pin_->digital_write(true); + delay(5); + this->reset_pin_->digital_write(false); + delay(5); + this->reset_pin_->digital_write(true); + this->set_timeout(30, [this] { this->continue_setup_(); }); } void CST226Touchscreen::update_touches() { diff --git a/esphome/components/cst226/touchscreen/cst226_touchscreen.h b/esphome/components/cst226/touchscreen/cst226_touchscreen.h index 9f518e5068..1b15b952c4 100644 --- a/esphome/components/cst226/touchscreen/cst226_touchscreen.h +++ b/esphome/components/cst226/touchscreen/cst226_touchscreen.h @@ -35,7 +35,7 @@ class CST226Touchscreen : public touchscreen::Touchscreen, public i2c::I2CDevice void continue_setup_(); InternalGPIOPin *interrupt_pin_{}; - GPIOPin *reset_pin_{}; + GPIOPin *reset_pin_{NULL_PIN}; uint8_t chip_id_{}; bool setup_complete_{}; }; diff --git a/esphome/core/gpio.h b/esphome/core/gpio.h index 1b6f2ba1e6..b3f6b00196 100644 --- a/esphome/core/gpio.h +++ b/esphome/core/gpio.h @@ -62,6 +62,24 @@ class GPIOPin { virtual bool is_internal() { return false; } }; +/** + * A pin to replace those that don't exist. + */ +class NullPin : public GPIOPin { + public: + void setup() override {} + + void pin_mode(gpio::Flags _) override {} + + bool digital_read() override { return false; } + + void digital_write(bool _) override {} + + std::string dump_summary() const override { return {"Not used"}; } +}; + +static GPIOPin *const NULL_PIN = new NullPin(); + /// Copy of GPIOPin that is safe to use from ISRs (with no virtual functions) class ISRInternalGPIOPin { public: From f9ce35c89443b7245b889ed728f45f964d89a439 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 24 Apr 2024 09:59:19 +1200 Subject: [PATCH 1317/2101] Allow UART to be AUTO LOADed (#6617) --- esphome/components/uart/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/uart/__init__.py b/esphome/components/uart/__init__.py index 82bc6caaa4..088227afe5 100644 --- a/esphome/components/uart/__init__.py +++ b/esphome/components/uart/__init__.py @@ -59,6 +59,7 @@ UARTWriteAction = uart_ns.class_("UARTWriteAction", automation.Action) UARTDebugger = uart_ns.class_("UARTDebugger", cg.Component, automation.Action) UARTDummyReceiver = uart_ns.class_("UARTDummyReceiver", cg.Component) MULTI_CONF = True +MULTI_CONF_NO_DEFAULT = True def validate_raw_data(value): From f8cdb087fc0eec5199312da94379c6407cdc3339 Mon Sep 17 00:00:00 2001 From: Jean Louis-Guerin Date: Wed, 24 Apr 2024 03:21:44 +0200 Subject: [PATCH 1318/2101] Add the WeiKai SPI/I2C UART/IO Expander components to esphome (#5218) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- CODEOWNERS | 11 + esphome/components/weikai/__init__.py | 108 +++ esphome/components/weikai/weikai.cpp | 615 ++++++++++++++++++ esphome/components/weikai/weikai.h | 443 +++++++++++++ esphome/components/weikai/wk_reg_def.h | 304 +++++++++ esphome/components/weikai_i2c/__init__.py | 1 + esphome/components/weikai_i2c/weikai_i2c.cpp | 177 +++++ esphome/components/weikai_i2c/weikai_i2c.h | 61 ++ esphome/components/weikai_spi/__init__.py | 1 + esphome/components/weikai_spi/weikai_spi.cpp | 189 ++++++ esphome/components/weikai_spi/weikai_spi.h | 54 ++ esphome/components/wk2132_i2c/__init__.py | 30 + esphome/components/wk2132_i2c/wk2132_i2c.cpp | 4 + esphome/components/wk2132_spi/__init__.py | 31 + esphome/components/wk2168_i2c/__init__.py | 64 ++ esphome/components/wk2168_spi/__init__.py | 62 ++ esphome/components/wk2204_i2c/__init__.py | 30 + esphome/components/wk2204_spi/__init__.py | 30 + esphome/components/wk2212_i2c/__init__.py | 64 ++ esphome/components/wk2212_spi/__init__.py | 62 ++ tests/components/wk2132_i2c/common.yaml | 20 + .../components/wk2132_i2c/test.esp32-idf.yaml | 5 + .../wk2132_i2c/test.esp32-s3-idf.yaml | 5 + .../components/wk2132_i2c/test.esp32-s3.yaml | 5 + tests/components/wk2132_i2c/test.esp32.yaml | 5 + tests/components/wk2132_spi/common.yaml | 21 + .../components/wk2132_spi/test.esp32-idf.yaml | 7 + .../wk2132_spi/test.esp32-s3-idf.yaml | 7 + .../components/wk2132_spi/test.esp32-s3.yaml | 7 + tests/components/wk2132_spi/test.esp32.yaml | 7 + tests/components/wk2168_i2c/common.yaml | 63 ++ .../components/wk2168_i2c/test.esp32-idf.yaml | 5 + .../wk2168_i2c/test.esp32-s3-idf.yaml | 5 + .../components/wk2168_i2c/test.esp32-s3.yaml | 5 + tests/components/wk2168_i2c/test.esp32.yaml | 5 + tests/components/wk2168_spi/common.yaml | 63 ++ .../components/wk2168_spi/test.esp32-idf.yaml | 7 + .../wk2168_spi/test.esp32-s3-idf.yaml | 7 + .../components/wk2168_spi/test.esp32-s3.yaml | 7 + tests/components/wk2168_spi/test.esp32.yaml | 7 + tests/components/wk2204_i2c/common.yaml | 28 + .../components/wk2204_i2c/test.esp32-idf.yaml | 5 + .../wk2204_i2c/test.esp32-s3-idf.yaml | 5 + .../components/wk2204_i2c/test.esp32-s3.yaml | 5 + tests/components/wk2204_i2c/test.esp32.yaml | 5 + tests/components/wk2204_spi/common.yaml | 29 + .../components/wk2204_spi/test.esp32-idf.yaml | 7 + .../wk2204_spi/test.esp32-s3-idf.yaml | 7 + .../components/wk2204_spi/test.esp32-s3.yaml | 7 + tests/components/wk2204_spi/test.esp32.yaml | 7 + tests/components/wk2212_i2c/common.yaml | 59 ++ .../components/wk2212_i2c/test.esp32-idf.yaml | 5 + .../wk2212_i2c/test.esp32-s3-idf.yaml | 5 + .../components/wk2212_i2c/test.esp32-s3.yaml | 5 + tests/components/wk2212_i2c/test.esp32.yaml | 5 + tests/components/wk2212_spi/common.yaml | 58 ++ .../components/wk2212_spi/test.esp32-idf.yaml | 7 + .../wk2212_spi/test.esp32-s3-idf.yaml | 7 + .../components/wk2212_spi/test.esp32-s3.yaml | 7 + tests/components/wk2212_spi/test.esp32.yaml | 7 + 60 files changed, 2874 insertions(+) create mode 100644 esphome/components/weikai/__init__.py create mode 100644 esphome/components/weikai/weikai.cpp create mode 100644 esphome/components/weikai/weikai.h create mode 100644 esphome/components/weikai/wk_reg_def.h create mode 100644 esphome/components/weikai_i2c/__init__.py create mode 100644 esphome/components/weikai_i2c/weikai_i2c.cpp create mode 100644 esphome/components/weikai_i2c/weikai_i2c.h create mode 100644 esphome/components/weikai_spi/__init__.py create mode 100644 esphome/components/weikai_spi/weikai_spi.cpp create mode 100644 esphome/components/weikai_spi/weikai_spi.h create mode 100644 esphome/components/wk2132_i2c/__init__.py create mode 100644 esphome/components/wk2132_i2c/wk2132_i2c.cpp create mode 100644 esphome/components/wk2132_spi/__init__.py create mode 100644 esphome/components/wk2168_i2c/__init__.py create mode 100644 esphome/components/wk2168_spi/__init__.py create mode 100644 esphome/components/wk2204_i2c/__init__.py create mode 100644 esphome/components/wk2204_spi/__init__.py create mode 100644 esphome/components/wk2212_i2c/__init__.py create mode 100644 esphome/components/wk2212_spi/__init__.py create mode 100644 tests/components/wk2132_i2c/common.yaml create mode 100644 tests/components/wk2132_i2c/test.esp32-idf.yaml create mode 100644 tests/components/wk2132_i2c/test.esp32-s3-idf.yaml create mode 100644 tests/components/wk2132_i2c/test.esp32-s3.yaml create mode 100644 tests/components/wk2132_i2c/test.esp32.yaml create mode 100644 tests/components/wk2132_spi/common.yaml create mode 100644 tests/components/wk2132_spi/test.esp32-idf.yaml create mode 100644 tests/components/wk2132_spi/test.esp32-s3-idf.yaml create mode 100644 tests/components/wk2132_spi/test.esp32-s3.yaml create mode 100644 tests/components/wk2132_spi/test.esp32.yaml create mode 100644 tests/components/wk2168_i2c/common.yaml create mode 100644 tests/components/wk2168_i2c/test.esp32-idf.yaml create mode 100644 tests/components/wk2168_i2c/test.esp32-s3-idf.yaml create mode 100644 tests/components/wk2168_i2c/test.esp32-s3.yaml create mode 100644 tests/components/wk2168_i2c/test.esp32.yaml create mode 100644 tests/components/wk2168_spi/common.yaml create mode 100644 tests/components/wk2168_spi/test.esp32-idf.yaml create mode 100644 tests/components/wk2168_spi/test.esp32-s3-idf.yaml create mode 100644 tests/components/wk2168_spi/test.esp32-s3.yaml create mode 100644 tests/components/wk2168_spi/test.esp32.yaml create mode 100644 tests/components/wk2204_i2c/common.yaml create mode 100644 tests/components/wk2204_i2c/test.esp32-idf.yaml create mode 100644 tests/components/wk2204_i2c/test.esp32-s3-idf.yaml create mode 100644 tests/components/wk2204_i2c/test.esp32-s3.yaml create mode 100644 tests/components/wk2204_i2c/test.esp32.yaml create mode 100644 tests/components/wk2204_spi/common.yaml create mode 100644 tests/components/wk2204_spi/test.esp32-idf.yaml create mode 100644 tests/components/wk2204_spi/test.esp32-s3-idf.yaml create mode 100644 tests/components/wk2204_spi/test.esp32-s3.yaml create mode 100644 tests/components/wk2204_spi/test.esp32.yaml create mode 100644 tests/components/wk2212_i2c/common.yaml create mode 100644 tests/components/wk2212_i2c/test.esp32-idf.yaml create mode 100644 tests/components/wk2212_i2c/test.esp32-s3-idf.yaml create mode 100644 tests/components/wk2212_i2c/test.esp32-s3.yaml create mode 100644 tests/components/wk2212_i2c/test.esp32.yaml create mode 100644 tests/components/wk2212_spi/common.yaml create mode 100644 tests/components/wk2212_spi/test.esp32-idf.yaml create mode 100644 tests/components/wk2212_spi/test.esp32-s3-idf.yaml create mode 100644 tests/components/wk2212_spi/test.esp32-s3.yaml create mode 100644 tests/components/wk2212_spi/test.esp32.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 28ce8e7b6a..8da1618636 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -400,10 +400,21 @@ esphome/components/wake_on_lan/* @willwill2will54 esphome/components/waveshare_epaper/* @clydebarrow esphome/components/web_server_base/* @OttoWinter esphome/components/web_server_idf/* @dentra +esphome/components/weikai/* @DrCoolZic +esphome/components/weikai_i2c/* @DrCoolZic +esphome/components/weikai_spi/* @DrCoolZic esphome/components/whirlpool/* @glmnet esphome/components/whynter/* @aeonsablaze esphome/components/wiegand/* @ssieb esphome/components/wireguard/* @droscy @lhoracek @thomas0bernard +esphome/components/wk2132_i2c/* @DrCoolZic +esphome/components/wk2132_spi/* @DrCoolZic +esphome/components/wk2168_i2c/* @DrCoolZic +esphome/components/wk2168_spi/* @DrCoolZic +esphome/components/wk2204_i2c/* @DrCoolZic +esphome/components/wk2204_spi/* @DrCoolZic +esphome/components/wk2212_i2c/* @DrCoolZic +esphome/components/wk2212_spi/* @DrCoolZic esphome/components/wl_134/* @hobbypunk90 esphome/components/x9c/* @EtienneMD esphome/components/xgzp68xx/* @gcormier diff --git a/esphome/components/weikai/__init__.py b/esphome/components/weikai/__init__.py new file mode 100644 index 0000000000..4248c48e35 --- /dev/null +++ b/esphome/components/weikai/__init__.py @@ -0,0 +1,108 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import uart +from esphome.const import ( + CONF_BAUD_RATE, + CONF_CHANNEL, + CONF_ID, + CONF_INPUT, + CONF_INVERTED, + CONF_MODE, + CONF_NUMBER, + CONF_OUTPUT, +) + +CODEOWNERS = ["@DrCoolZic"] +AUTO_LOAD = ["uart"] + +MULTI_CONF = True +CONF_STOP_BITS = "stop_bits" +CONF_PARITY = "parity" +CONF_CRYSTAL = "crystal" +CONF_UART = "uart" +CONF_TEST_MODE = "test_mode" + +weikai_ns = cg.esphome_ns.namespace("weikai") +WeikaiComponent = weikai_ns.class_("WeikaiComponent", cg.Component) +WeikaiChannel = weikai_ns.class_("WeikaiChannel", uart.UARTComponent) + + +def check_channel_max(value, max): + channel_uniq = [] + channel_dup = [] + for x in value[CONF_UART]: + if x[CONF_CHANNEL] > max - 1: + raise cv.Invalid(f"Invalid channel number: {x[CONF_CHANNEL]}") + if x[CONF_CHANNEL] not in channel_uniq: + channel_uniq.append(x[CONF_CHANNEL]) + else: + channel_dup.append(x[CONF_CHANNEL]) + if len(channel_dup) > 0: + raise cv.Invalid(f"Duplicate channel list: {channel_dup}") + return value + + +def check_channel_max_4(value): + return check_channel_max(value, 4) + + +def check_channel_max_2(value): + return check_channel_max(value, 2) + + +WKBASE_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.declare_id(WeikaiComponent), + cv.Optional(CONF_CRYSTAL, default=14745600): cv.int_, + cv.Optional(CONF_TEST_MODE, default=0): cv.int_, + cv.Required(CONF_UART): cv.ensure_list( + { + cv.Required(CONF_ID): cv.declare_id(WeikaiChannel), + cv.Optional(CONF_CHANNEL, default=0): cv.int_range(min=0, max=3), + 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_PARITY, default="NONE"): cv.enum( + uart.UART_PARITY_OPTIONS, upper=True + ), + } + ), + } +).extend(cv.COMPONENT_SCHEMA) + + +async def register_weikai(var, config): + """Register an weikai device with the given config.""" + cg.add(var.set_crystal(config[CONF_CRYSTAL])) + cg.add(var.set_test_mode(config[CONF_TEST_MODE])) + await cg.register_component(var, config) + for uart_elem in config[CONF_UART]: + chan = cg.new_Pvariable(uart_elem[CONF_ID]) + cg.add(chan.set_channel_name(str(uart_elem[CONF_ID]))) + cg.add(chan.set_parent(var)) + cg.add(chan.set_channel(uart_elem[CONF_CHANNEL])) + cg.add(chan.set_baud_rate(uart_elem[CONF_BAUD_RATE])) + cg.add(chan.set_stop_bits(uart_elem[CONF_STOP_BITS])) + cg.add(chan.set_parity(uart_elem[CONF_PARITY])) + + +def validate_pin_mode(value): + """Checks input/output mode inconsistency""" + if not (value[CONF_MODE][CONF_INPUT] or value[CONF_MODE][CONF_OUTPUT]): + raise cv.Invalid("Mode must be either input or output") + if value[CONF_MODE][CONF_INPUT] and value[CONF_MODE][CONF_OUTPUT]: + raise cv.Invalid("Mode must be either input or output") + return value + + +WEIKAI_PIN_SCHEMA = cv.Schema( + { + cv.Required(CONF_NUMBER): cv.int_range(min=0, max=7), + cv.Optional(CONF_MODE, default={}): cv.All( + { + cv.Optional(CONF_INPUT, default=False): cv.boolean, + cv.Optional(CONF_OUTPUT, default=False): cv.boolean, + }, + ), + cv.Optional(CONF_INVERTED, default=False): cv.boolean, + } +) diff --git a/esphome/components/weikai/weikai.cpp b/esphome/components/weikai/weikai.cpp new file mode 100644 index 0000000000..a04bc0a574 --- /dev/null +++ b/esphome/components/weikai/weikai.cpp @@ -0,0 +1,615 @@ +/// @file weikai.cpp +/// @brief WeiKai component family - classes implementation +/// @date Last Modified: 2024/04/06 15:13:11 +/// @details The classes declared in this file can be used by the Weikai family + +#include "weikai.h" + +namespace esphome { +namespace weikai { + +/*! @mainpage Weikai source code documentation + This documentation provides information about the implementation of the family of WeiKai Components in ESPHome. + Here is the class diagram related to Weikai family of components: + @image html weikai_class.png + + @section WKRingBuffer_ The WKRingBuffer template class +The WKRingBuffer template class has it names implies implement a simple ring buffer helper class. This straightforward +container implements FIFO functionality, enabling bytes to be pushed into one side and popped from the other in the +order of entry. Implementation is classic and therefore not described in any details. + + @section WeikaiRegister_ The WeikaiRegister class + The WeikaiRegister helper class creates objects that act as proxies to the device registers. + @details This is an abstract virtual class (interface) that provides all the necessary access to registers while hiding + the actual implementation. The access to the registers can be made through an I²C bus in for example for wk2168_i2c + component or through a SPI bus for example in the case of the wk2168_spi component. Derived classes will actually + performs the specific bus operations. + + @section WeikaiRegisterI2C_ WeikaiRegisterI2C + The weikai_i2c::WeikaiRegisterI2C class implements the virtual methods of the WeikaiRegister class for an I2C bus. + + @section WeikaiRegisterSPI_ WeikaiRegisterSPI + The weikai_spi::WeikaiRegisterSPI class implements the virtual methods of the WeikaiRegister class for an SPI bus. + + @section WeikaiComponent_ The WeikaiComponent class +The WeikaiComponent class stores the information global to a WeiKai family component and provides methods to set/access +this information. It also serves as a container for WeikaiChannel instances. This is done by maintaining an array of +references these WeikaiChannel instances. This class derives from the esphome::Component classes. This class override +esphome::Component::loop() method to facilitate the seamless transfer of accumulated bytes from the receive +FIFO into the ring buffer. This process ensures quick access to the stored bytes, enhancing the overall efficiency of +the component. + + @section WeikaiComponentI2C_ WeikaiComponentI2C + The weikai_i2c::WeikaiComponentI2C class implements the virtual methods of the WeikaiComponent class for an I2C bus. + + @section WeikaiComponentSPI_ WeikaiComponentSPI + The weikai_spi::WeikaiComponentSPI class implements the virtual methods of the WeikaiComponent class for an SPI bus. + + @section WeikaiGPIOPin_ WeikaiGPIOPin class + The WeikaiGPIOPin class is an helper class to expose the GPIO pins of WK family components as if they were internal + GPIO pins. It also provides the setup() and dump_summary() methods. + + @section WeikaiChannel_ The WeikaiChannel class + The WeikaiChannel class is used to implement all the virtual methods of the ESPHome uart::UARTComponent class. An + individual instance of this class is created for each UART channel. It has a link back to the WeikaiComponent object it + belongs to. This class derives from the uart::UARTComponent class. It collaborates through an aggregation with + WeikaiComponent. This implies that WeikaiComponent acts as a container, housing several WeikaiChannel instances. + Furthermore, the WeikaiChannel class derives from the ESPHome uart::UARTComponent class, it also has an association + relationship with the WKRingBuffer and WeikaiRegister helper classes. Consequently, when a WeikaiChannel instance is + destroyed, the associated WKRingBuffer instance is also destroyed. + +*/ + +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 +uint32_t elapsed_ms(uint32_t &last_time) { + uint32_t e = millis() - last_time; + last_time = millis(); + return e; +}; + +/// @brief Converts the parity enum value to a C string +/// @param parity enum +/// @return the string +const char *p2s(uart::UARTParityOptions parity) { + using namespace uart; + switch (parity) { + case UART_CONFIG_PARITY_NONE: + return "NONE"; + case UART_CONFIG_PARITY_EVEN: + return "EVEN"; + case UART_CONFIG_PARITY_ODD: + return "ODD"; + default: + return "UNKNOWN"; + } +} + +/// @brief Display a buffer in hexadecimal format (32 hex values / line) for debug +void print_buffer(const uint8_t *data, size_t length) { + char hex_buffer[100]; + hex_buffer[(3 * 32) + 1] = 0; + for (size_t i = 0; i < length; i++) { + snprintf(&hex_buffer[3 * (i % 32)], sizeof(hex_buffer), "%02X ", data[i]); + if (i % 32 == 31) { + ESP_LOGVV(TAG, " %s", hex_buffer); + } + } + if (length % 32) { + // null terminate if incomplete line + hex_buffer[3 * (length % 32) + 2] = 0; + ESP_LOGVV(TAG, " %s", hex_buffer); + } +} + +static const char *const REG_TO_STR_P0[16] = {"GENA", "GRST", "GMUT", "SPAGE", "SCR", "LCR", "FCR", "SIER", + "SIFR", "TFCNT", "RFCNT", "FSR", "LSR", "FDAT", "FWCR", "RS485"}; +static const char *const REG_TO_STR_P1[16] = {"GENA", "GRST", "GMUT", "SPAGE", "BAUD1", "BAUD0", "PRES", "RFTL", + "TFTL", "FWTH", "FWTL", "XON1", "XOFF1", "SADR", "SAEN", "RTSDLY"}; + +// method to print a register value as text: used in the log messages ... +const char *reg_to_str(int reg, bool page1) { + if (reg == WKREG_GPDAT) { + return "GPDAT"; + } else if (reg == WKREG_GPDIR) { + return "GPDIR"; + } else { + return page1 ? REG_TO_STR_P1[reg & 0x0F] : REG_TO_STR_P0[reg & 0x0F]; + } +} + +enum RegType { REG = 0, FIFO = 1 }; ///< Register or FIFO + +/////////////////////////////////////////////////////////////////////////////// +// The WeikaiRegister methods +/////////////////////////////////////////////////////////////////////////////// +WeikaiRegister &WeikaiRegister::operator=(uint8_t value) { + write_reg(value); + return *this; +} + +WeikaiRegister &WeikaiRegister::operator&=(uint8_t value) { + value &= read_reg(); + write_reg(value); + return *this; +} + +WeikaiRegister &WeikaiRegister::operator|=(uint8_t value) { + value |= read_reg(); + write_reg(value); + return *this; +} + +/////////////////////////////////////////////////////////////////////////////// +// The WeikaiComponent methods +/////////////////////////////////////////////////////////////////////////////// +void WeikaiComponent::loop() { + if ((this->component_state_ & COMPONENT_STATE_MASK) != COMPONENT_STATE_LOOP) + return; + + // If there are some bytes in the receive FIFO we transfers them to the ring buffers + size_t transferred = 0; + for (auto *child : this->children_) { + // we look if some characters has been received in the fifo + transferred += child->xfer_fifo_to_buffer_(); + } + if (transferred > 0) { + ESP_LOGV(TAG, "we transferred %d bytes from fifo to buffer...", transferred); + } + +#ifdef TEST_COMPONENT + static uint32_t loop_time = 0; + static uint32_t loop_count = 0; + uint32_t time = 0; + + if (test_mode_ == 1) { // test component in loopback + ESP_LOGI(TAG, "Component loop %" PRIu32 " for %s : %" PRIu32 " ms since last call ...", loop_count++, + this->get_name(), millis() - loop_time); + loop_time = millis(); + char message[64]; + elapsed_ms(time); // set time to now + for (int i = 0; i < this->children_.size(); i++) { + if (i != ((loop_count - 1) % this->children_.size())) // we do only one per loop + continue; + snprintf(message, sizeof(message), "%s:%s", this->get_name(), children_[i]->get_channel_name()); + children_[i]->uart_send_test_(message); + uint32_t const start_time = millis(); + while (children_[i]->tx_fifo_is_not_empty_()) { // wait until buffer empty + if (millis() - start_time > 1500) { + ESP_LOGE(TAG, "timeout while flushing - %d bytes left in buffer...", children_[i]->tx_in_fifo_()); + break; + } + yield(); // reschedule our thread to avoid blocking + } + bool status = children_[i]->uart_receive_test_(message); + ESP_LOGI(TAG, "Test %s => send/received %u bytes %s - execution time %" PRIu32 " ms...", message, + RING_BUFFER_SIZE, status ? "correctly" : "with error", elapsed_ms(time)); + } + } + + if (this->test_mode_ == 2) { // test component in echo mode + for (auto *child : this->children_) { + uint8_t data = 0; + if (child->available()) { + child->read_byte(&data); + ESP_LOGI(TAG, "echo mode: read -> send %02X", data); + child->write_byte(data); + } + } + } + if (test_mode_ == 3) { + test_gpio_input_(); + } + + if (test_mode_ == 4) { + test_gpio_output_(); + } +#endif +} + +#if defined(TEST_COMPONENT) +void WeikaiComponent::test_gpio_input_() { + static bool init_input{false}; + static uint8_t state{0}; + uint8_t value; + 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)); + } + value = this->reg(WKREG_GPDAT, 0); + if (value != state) { + ESP_LOGI(TAG, "Input data changed from %02X to %02X (%s)", state, value, I2S2CS(value)); + state = value; + } +} + +void WeikaiComponent::test_gpio_output_() { + static bool init_output{false}; + static uint8_t state{0}; + if (!init_output) { + init_output = true; + // set all pins in output mode + this->reg(WKREG_GPDIR, 0) = 0xFF; + ESP_LOGI(TAG, "initializing all pins to output mode"); + this->reg(WKREG_GPDAT, 0) = state; + ESP_LOGI(TAG, "setting all outputs to 0"); + } + state = ~state; + this->reg(WKREG_GPDAT, 0) = state; + ESP_LOGI(TAG, "Flipping all outputs to %02X (%s)", state, I2S2CS(state)); + delay(100); // NOLINT +} +#endif + +/////////////////////////////////////////////////////////////////////////////// +// The WeikaiGPIOPin methods +/////////////////////////////////////////////////////////////////////////////// +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_)); + return this->input_state_ & (1 << pin); +} + +void WeikaiComponent::write_pin_val_(uint8_t pin, bool value) { + if (value) { + this->output_state_ |= (1 << pin); + } 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_)); + this->reg(WKREG_GPDAT, 0) = this->output_state_; +} + +void WeikaiComponent::set_pin_direction_(uint8_t pin, gpio::Flags flags) { + if (flags == gpio::FLAG_INPUT) { + this->pin_config_ &= ~(1 << pin); // clear bit (input mode) + } else { + if (flags == gpio::FLAG_OUTPUT) { + this->pin_config_ |= 1 << pin; // set bit (output mode) + } else { + 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_)); + this->reg(WKREG_GPDIR, 0) = this->pin_config_; // TODO check ~ +} + +void WeikaiGPIOPin::setup() { + ESP_LOGCONFIG(TAG, "Setting GPIO pin %d mode to %s", this->pin_, + 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_); +} + +std::string WeikaiGPIOPin::dump_summary() const { + char buffer[32]; + snprintf(buffer, sizeof(buffer), "%u via WeiKai %s", this->pin_, this->parent_->get_name()); + return buffer; +} + +/////////////////////////////////////////////////////////////////////////////// +// The WeikaiChannel methods +/////////////////////////////////////////////////////////////////////////////// +void WeikaiChannel::setup_channel() { + ESP_LOGCONFIG(TAG, " Setting up UART %s:%s ...", this->parent_->get_name(), this->get_channel_name()); + // we enable transmit and receive on this channel + if (this->check_channel_down()) { + ESP_LOGCONFIG(TAG, " Error channel %s not working...", this->get_channel_name()); + } + this->reset_fifo_(); + this->receive_buffer_.clear(); + this->set_line_param_(); + this->set_baudrate_(); +} + +void WeikaiChannel::dump_channel() { + ESP_LOGCONFIG(TAG, " UART %s ...", this->get_channel_name()); + ESP_LOGCONFIG(TAG, " Baud rate: %" PRIu32 " Bd", this->baud_rate_); + ESP_LOGCONFIG(TAG, " Data bits: %u", this->data_bits_); + ESP_LOGCONFIG(TAG, " Stop bits: %u", this->stop_bits_); + ESP_LOGCONFIG(TAG, " Parity: %s", p2s(this->parity_)); +} + +void WeikaiChannel::reset_fifo_() { + // enable transmission and reception + this->reg(WKREG_SCR) = SCR_RXEN | SCR_TXEN; + // we reset and enable transmit and receive FIFO + this->reg(WKREG_FCR) = FCR_TFEN | FCR_RFEN | FCR_TFRST | FCR_RFRST; +} + +void WeikaiChannel::set_line_param_() { + this->data_bits_ = 8; // always equal to 8 for WeiKai (cant be changed) + uint8_t lcr = 0; + if (this->stop_bits_ == 2) + lcr |= LCR_STPL; + switch (this->parity_) { // parity selection settings + case uart::UART_CONFIG_PARITY_ODD: + lcr |= (LCR_PAEN | LCR_PAR_ODD); + break; + case uart::UART_CONFIG_PARITY_EVEN: + lcr |= (LCR_PAEN | LCR_PAR_EVEN); + break; + default: + break; // no parity 000x + } + this->reg(WKREG_LCR) = lcr; // write LCR + 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)); +} + +void WeikaiChannel::set_baudrate_() { + if (this->baud_rate_ > this->parent_->crystal_ / 16) { + baud_rate_ = this->parent_->crystal_ / 16; + ESP_LOGE(TAG, " Requested baudrate too high for crystal=%" PRIu32 " Hz. Has been reduced to %" PRIu32 " Bd", + this->parent_->crystal_, this->baud_rate_); + }; + uint16_t const val_int = this->parent_->crystal_ / (this->baud_rate_ * 16) - 1; + uint16_t val_dec = (this->parent_->crystal_ % (this->baud_rate_ * 16)) / (this->baud_rate_ * 16); + uint8_t const baud_high = (uint8_t) (val_int >> 8); + uint8_t const baud_low = (uint8_t) (val_int & 0xFF); + while (val_dec > 0x0A) + val_dec /= 0x0A; + uint8_t const baud_dec = (uint8_t) (val_dec); + + this->parent_->page1_ = true; // switch to page 1 + this->reg(WKREG_SPAGE) = 1; + this->reg(WKREG_BRH) = baud_high; + this->reg(WKREG_BRL) = baud_low; + this->reg(WKREG_BRD) = baud_dec; + this->parent_->page1_ = false; // switch back to page 0 + this->reg(WKREG_SPAGE) = 0; + + ESP_LOGV(TAG, " Crystal=%d baudrate=%d => registers [%d %d %d]", this->parent_->crystal_, this->baud_rate_, + baud_high, baud_low, baud_dec); +} + +inline bool WeikaiChannel::tx_fifo_is_not_empty_() { return this->reg(WKREG_FSR) & FSR_TFDAT; } + +size_t WeikaiChannel::tx_in_fifo_() { + size_t tfcnt = this->reg(WKREG_TFCNT); + 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)); + tfcnt = FIFO_SIZE; + } + } + ESP_LOGVV(TAG, "tx FIFO contains %d bytes", tfcnt); + return tfcnt; +} + +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)) { + if (fsr & FSR_RFOE) + ESP_LOGE(TAG, "Receive data overflow FSR=%s", I2S2CS(fsr)); + if (fsr & FSR_RFLB) + ESP_LOGE(TAG, "Receive line break FSR=%s", I2S2CS(fsr)); + if (fsr & FSR_RFFE) + ESP_LOGE(TAG, "Receive frame error FSR=%s", I2S2CS(fsr)); + if (fsr & FSR_RFPE) + ESP_LOGE(TAG, "Receive parity error FSR=%s", I2S2CS(fsr)); + } + if ((available == 0) && (fsr & FSR_RFDAT)) { + // here we should be very careful because we can have something like this: + // - at time t0 we read RFCNT=0 because nothing yet received + // - at time t0+delta we might read FIFO not empty because one byte has just been received + // - 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)); + available = FIFO_SIZE; + } + } + ESP_LOGVV(TAG, "rx FIFO contain %d bytes - FSR status=%s", available, I2S2CS(fsr)); + return available; +} + +bool WeikaiChannel::check_channel_down() { + // to check if we channel is up we write to the LCR W/R register + // note that this will put a break on the tx line for few ms + WeikaiRegister &lcr = this->reg(WKREG_LCR); + lcr = 0x3F; + uint8_t val = lcr; + if (val != 0x3F) { + ESP_LOGE(TAG, "R/W of register failed expected 0x3F received 0x%02X", val); + return true; + } + lcr = 0; + val = lcr; + if (val != 0x00) { + ESP_LOGE(TAG, "R/W of register failed expected 0x00 received 0x%02X", val); + return true; + } + return false; +} + +bool WeikaiChannel::peek_byte(uint8_t *buffer) { + auto available = this->receive_buffer_.count(); + if (!available) + xfer_fifo_to_buffer_(); + return this->receive_buffer_.peek(*buffer); +} + +int WeikaiChannel::available() { + size_t available = this->receive_buffer_.count(); + if (!available) + available = xfer_fifo_to_buffer_(); + return available; +} + +bool WeikaiChannel::read_array(uint8_t *buffer, size_t length) { + bool status = true; + auto available = this->receive_buffer_.count(); + if (length > available) { + ESP_LOGW(TAG, "read_array: buffer underflow requested %d bytes only %d bytes available...", length, available); + length = available; + status = false; + } + // retrieve the bytes from ring buffer + for (size_t i = 0; i < length; i++) { + this->receive_buffer_.pop(buffer[i]); + } + ESP_LOGVV(TAG, "read_array(ch=%d buffer[0]=%02X, length=%d): status %s", this->channel_, *buffer, length, + status ? "OK" : "ERROR"); + return status; +} + +void WeikaiChannel::write_array(const uint8_t *buffer, size_t length) { + if (length > XFER_MAX_SIZE) { + ESP_LOGE(TAG, "Write_array: invalid call - requested %d bytes but max size %d ...", length, XFER_MAX_SIZE); + length = XFER_MAX_SIZE; + } + this->reg(0).write_fifo(const_cast(buffer), length); +} + +void 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; + } + yield(); // reschedule our thread to avoid blocking + } +} + +size_t WeikaiChannel::xfer_fifo_to_buffer_() { + size_t to_transfer; + size_t free; + while ((to_transfer = this->rx_in_fifo_()) && (free = this->receive_buffer_.free())) { + // while bytes in fifo and some room in the buffer we transfer + if (to_transfer > XFER_MAX_SIZE) + to_transfer = XFER_MAX_SIZE; // we can only do so much + if (to_transfer > free) + to_transfer = free; // we'll do the rest next time + if (to_transfer) { + uint8_t data[to_transfer]; + this->reg(0).read_fifo(data, to_transfer); + for (size_t i = 0; i < to_transfer; i++) + this->receive_buffer_.push(data[i]); + } + } // while work to do + return to_transfer; +} + +/// +// TEST COMPONENT +// +#ifdef TEST_COMPONENT +/// @addtogroup test_ Test component information +/// @{ + +/// @brief An increment "Functor" (i.e. a class object that acts like a method with state!) +/// +/// Functors are objects that can be treated as though they are a function or function pointer. +class Increment { + public: + /// @brief constructor: initialize current value to 0 + Increment() : i_(0) {} + /// @brief overload of the parenthesis operator. + /// Returns the current value and auto increment it + /// @return the current value. + uint8_t operator()() { return i_++; } + + private: + uint8_t i_; +}; + +/// @brief Hex converter to print/display a buffer in hexadecimal format (32 hex values / line). +/// @param buffer contains the values to display +void print_buffer(std::vector buffer) { + char hex_buffer[100]; + hex_buffer[(3 * 32) + 1] = 0; + for (size_t i = 0; i < buffer.size(); i++) { + snprintf(&hex_buffer[3 * (i % 32)], sizeof(hex_buffer), "%02X ", buffer[i]); + if (i % 32 == 31) + ESP_LOGI(TAG, " %s", hex_buffer); + } + if (buffer.size() % 32) { + // null terminate if incomplete line + hex_buffer[3 * (buffer.size() % 32) + 1] = 0; + ESP_LOGI(TAG, " %s", hex_buffer); + } +} + +/// @brief test the write_array method +void WeikaiChannel::uart_send_test_(char *message) { + auto start_exec = micros(); + std::vector output_buffer(XFER_MAX_SIZE); + generate(output_buffer.begin(), output_buffer.end(), Increment()); // fill with incrementing number + size_t to_send = RING_BUFFER_SIZE; + while (to_send) { + this->write_array(&output_buffer[0], XFER_MAX_SIZE); // we send the buffer + this->flush(); + to_send -= XFER_MAX_SIZE; + } + ESP_LOGV(TAG, "%s => sent %d bytes - exec time %d µs ...", message, RING_BUFFER_SIZE, micros() - start_exec); +} + +/// @brief test read_array method +bool WeikaiChannel::uart_receive_test_(char *message) { + auto start_exec = micros(); + bool status = true; + size_t received = 0; + std::vector buffer(RING_BUFFER_SIZE); + + // we wait until we have received all the bytes + uint32_t const start_time = millis(); + status = true; + while (received < RING_BUFFER_SIZE) { + while (XFER_MAX_SIZE > this->available()) { + this->xfer_fifo_to_buffer_(); + if (millis() - start_time > 1500) { + ESP_LOGE(TAG, "uart_receive_test_() timeout: only %d bytes received...", this->available()); + break; + } + yield(); // reschedule our thread to avoid blocking + } + status = this->read_array(&buffer[received], XFER_MAX_SIZE) && status; + received += XFER_MAX_SIZE; + } + + uint8_t peek_value = 0; + this->peek_byte(&peek_value); + if (peek_value != 0) { + ESP_LOGE(TAG, "Peek first byte value error..."); + status = false; + } + + for (size_t i = 0; i < RING_BUFFER_SIZE; i++) { + if (buffer[i] != i % XFER_MAX_SIZE) { + ESP_LOGE(TAG, "Read buffer contains error...b=%x i=%x", buffer[i], i % XFER_MAX_SIZE); + print_buffer(buffer); + status = false; + break; + } + } + + ESP_LOGV(TAG, "%s => received %d bytes status %s - exec time %d µs ...", message, received, status ? "OK" : "ERROR", + micros() - start_exec); + return status; +} + +/// @} +#endif + +} // namespace weikai +} // namespace esphome diff --git a/esphome/components/weikai/weikai.h b/esphome/components/weikai/weikai.h new file mode 100644 index 0000000000..042c729162 --- /dev/null +++ b/esphome/components/weikai/weikai.h @@ -0,0 +1,443 @@ +/// @file weikai.h +/// @author DrCoolZic +/// @brief WeiKai component family - classes declaration +/// @date Last Modified: 2024/04/06 14:44:17 +/// @details The classes declared in this file can be used by the Weikai family +/// of UART and GPIO expander components. As of today it provides support for +/// wk2124_spi, wk2132_spi, wk2168_spi, wk2204_spi, wk2212_spi, +/// wk2132_i2c, wk2168_i2c, wk2204_i2c, wk2212_i2c + +#pragma once +#include +#include +#include +#include "esphome/core/component.h" +#include "esphome/components/uart/uart.h" +#include "wk_reg_def.h" + +/// When the TEST_COMPONENT flag is defined we include some auto-test methods. Used to test the software during +/// development but can also be used in situ to test if the component is working correctly. For release we do +/// not set it by default but you can set it by using the following lines in you configuration file: +/// @code +/// esphome: +/// platformio_options: +/// build_flags: +/// - -DTEST_COMPONENT +/// @endcode +// #define TEST_COMPONENT + +namespace esphome { +namespace weikai { + +/// @brief XFER_MAX_SIZE defines the maximum number of bytes allowed during one transfer. +#if defined(I2C_BUFFER_LENGTH) +constexpr size_t XFER_MAX_SIZE = I2C_BUFFER_LENGTH; +#else +constexpr size_t XFER_MAX_SIZE = 128; +#endif + +/// @brief size of the internal WeiKai FIFO +constexpr size_t FIFO_SIZE = 256; + +/// @brief size of the ring buffer set to size of the FIFO +constexpr size_t RING_BUFFER_SIZE = FIFO_SIZE; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// @brief This is an helper class that provides a simple ring buffers that works as a FIFO +/// @details This ring buffer is used to buffer the bytes received in the FIFO of the Weika device. The best way to read +/// characters from the device FIFO, is to first check how many bytes were received and then read them all at once. +/// Unfortunately in all the code I have reviewed the characters are read one by one in a while loop by checking if +/// bytes are available then reading the byte until no more byte available. This is pretty inefficient for two reasons: +/// - Fist you need to perform a test for each byte to read +/// - and second you call the read byte method for each character. +/// . +/// Assuming you need to read 100 bytes that results into 200 calls. This is to compare to 2 calls (one to find the +/// number of bytes available plus one to read all the bytes) in the best case! If the registers you read are located on +/// the micro-controller this is acceptable because the registers can be accessed fast. But when the registers are +/// located on a remote device accessing them requires several cycles on a slow bus. As it it not possible to fix this +/// problem by asking users to rewrite their code, I have implemented this ring buffer that store the bytes received +/// locally. +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template class WKRingBuffer { + public: + /// @brief pushes an item at the tail of the fifo + /// @param item item to push + /// @return true if item has been pushed, false il item could not pushed (buffer full) + bool push(const T item) { + if (is_full()) + return false; + this->rb_[this->head_] = item; + this->head_ = (this->head_ + 1) % SIZE; + this->count_++; + return true; + } + + /// @brief return and remove the item at head of the fifo + /// @param item item read + /// @return true if an item has been retrieved, false il no item available (buffer empty) + bool pop(T &item) { + if (is_empty()) + return false; + item = this->rb_[this->tail_]; + this->tail_ = (this->tail_ + 1) % SIZE; + this->count_--; + return true; + } + + /// @brief return the value of the item at fifo's head without removing it + /// @param item pointer to item to return + /// @return true if item has been retrieved, false il no item available (buffer empty) + bool peek(T &item) { + if (is_empty()) + return false; + item = this->rb_[this->tail_]; + return true; + } + + /// @brief test is the Ring Buffer is empty ? + /// @return true if empty + inline bool is_empty() { return (this->count_ == 0); } + + /// @brief test is the ring buffer is full ? + /// @return true if full + inline bool is_full() { return (this->count_ == SIZE); } + + /// @brief return the number of item in the ring buffer + /// @return the number of items + inline size_t count() { return this->count_; } + + /// @brief returns the number of free positions in the buffer + /// @return how many items can be added + inline size_t free() { return SIZE - this->count_; } + + /// @brief clear the buffer content + inline void clear() { this->head_ = this->tail_ = this->count_ = 0; } + + protected: + std::array rb_{0}; ///< the ring buffer + int tail_{0}; ///< position of the next element to read + int head_{0}; ///< position of the next element to write + size_t count_{0}; ///< count number of element in the buffer +}; + +class WeikaiComponent; +// class WeikaiComponentSPI; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// @brief WeikaiRegister objects acts as proxies to access remote register independently of the bus type. +/// @details This is an abstract interface class that provides many operations to access to registers while hiding +/// the actual implementation. This allow to accesses the registers in the Weikai component abstract class independently +/// of the actual bus (I2C, SPI). The derived classes will actually implements the specific bus operations dependant of +/// the bus used. +/// @n typical usage of WeikaiRegister: +/// @code +/// WeikaiRegister reg_X {&WeikaiComponent, ADDR_REGISTER_X, CHANNEL_NUM} // declaration +/// reg_X |= 0x01; // set bit 0 of the weikai register +/// reg_X &= ~0x01; // reset bit 0 of the weikai register +/// reg_X = 10; // Set the value of weikai register +/// uint val = reg_X; // get the value of weikai register +/// @endcode +class WeikaiRegister { + public: + /// @brief WeikaiRegister constructor. + /// @param comp our parent WeikaiComponent + /// @param reg address of the register + /// @param channel the channel of this register + WeikaiRegister(WeikaiComponent *const comp, uint8_t reg, uint8_t channel) + : comp_(comp), register_(reg), channel_(channel) {} + virtual ~WeikaiRegister() {} + + /// @brief overloads the = operator. This is used to set a value into the weikai register + /// @param value to be set + /// @return this object + WeikaiRegister &operator=(uint8_t value); + + /// @brief overloads the compound &= operator. This is often used to reset bits in the weikai register + /// @param value performs an & operation with value and store the result + /// @return this object + WeikaiRegister &operator&=(uint8_t value); + + /// @brief overloads the compound |= operator. This is often used to set bits in the weikai register + /// @param value performs an | operation with value and store the result + /// @return this object + WeikaiRegister &operator|=(uint8_t value); + + /// @brief cast operator that returns the content of the weikai register + operator uint8_t() const { return read_reg(); } + + /// @brief reads the register + /// @return the value read from the register + virtual uint8_t read_reg() const = 0; + + /// @brief writes the register + /// @param value to write in the register + virtual void write_reg(uint8_t value) = 0; + + /// @brief read an array of bytes from the receiver fifo + /// @param data pointer to data buffer + /// @param length number of bytes to read + virtual void read_fifo(uint8_t *data, size_t length) const = 0; + + /// @brief write an array of bytes to the transmitter fifo + /// @param data pointer to data buffer + /// @param length number of bytes to write + virtual void write_fifo(uint8_t *data, size_t length) = 0; + + WeikaiComponent *const comp_; ///< pointer to our parent (aggregation) + uint8_t register_; ///< address of the register + uint8_t channel_; ///< channel for this register +}; + +class WeikaiChannel; // forward declaration +//////////////////////////////////////////////////////////////////////////////////// +/// @brief The WeikaiComponent class stores the information global to the WeiKai component +/// and provides methods to set/access this information. It is also the container of +/// the WeikaiChannel children objects. This class is derived from esphome::Component +/// class. +//////////////////////////////////////////////////////////////////////////////////// +class WeikaiComponent : public Component { + public: + /// @brief virtual destructor + virtual ~WeikaiComponent() {} + + /// @brief store crystal frequency + /// @param crystal frequency + void set_crystal(uint32_t crystal) { this->crystal_ = crystal; } + + /// @brief store if the component is in test mode + /// @param test_mode 0=normal mode any other values mean component in test mode + void set_test_mode(int test_mode) { this->test_mode_ = test_mode; } + + /// @brief store the name for the component + /// @param name the name as defined by the python code generator + void set_name(std::string name) { this->name_ = std::move(name); } + + /// @brief Get the name of the component + /// @return the name + const char *get_name() { return this->name_.c_str(); } + + /// @brief override the Component loop() + void loop() override; + + bool page1() { return page1_; } + + /// @brief Factory method to create a Register object + /// @param reg address of the register + /// @param channel channel associated with this register + /// @return a reference to WeikaiRegister + virtual WeikaiRegister ®(uint8_t reg, uint8_t channel) = 0; + + protected: + friend class WeikaiChannel; + + /// @brief Get the priority of the component + /// @return the priority + /// @details The priority is set below setup_priority::BUS because we use + /// the spi/i2c busses (which has a priority of BUS) to communicate and the WeiKai + /// therefore it is seen by our client almost as if it was a bus. + float get_setup_priority() const override { return setup_priority::BUS - 0.1F; } + + friend class WeikaiGPIOPin; + /// Helper method to read the value of a pin. + bool read_pin_val_(uint8_t pin); + + /// Helper method to write the value of a pin. + void write_pin_val_(uint8_t pin, bool value); + + /// Helper method to set the pin mode of a pin. + void set_pin_direction_(uint8_t pin, gpio::Flags flags); + +#ifdef TEST_COMPONENT + /// @defgroup test_ Test component information + /// @brief Contains information about the auto-tests of the component + /// @{ + void test_gpio_input_(); + void test_gpio_output_(); + /// @} +#endif + + uint8_t pin_config_{0x00}; ///< pin config mask: 1 means OUTPUT, 0 means INPUT + uint8_t output_state_{0x00}; ///< output state: 1 means HIGH, 0 means LOW + uint8_t input_state_{0x00}; ///< input pin states: 1 means HIGH, 0 means LOW + uint32_t crystal_; ///< crystal value; + int test_mode_; ///< test mode value (0 -> no tests) + bool page1_{false}; ///< set to true when in "page1 mode" + std::vector children_{}; ///< the list of WeikaiChannel UART children + std::string name_; ///< name of entity +}; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Helper class to expose a WeiKai family IO pin as an internal GPIO pin. +/////////////////////////////////////////////////////////////////////////////// +class WeikaiGPIOPin : public GPIOPin { + public: + void set_parent(WeikaiComponent *parent) { this->parent_ = parent; } + void set_pin(uint8_t pin) { this->pin_ = pin; } + void set_inverted(bool inverted) { this->inverted_ = inverted; } + void set_flags(gpio::Flags flags) { this->flags_ = flags; } + + void setup() override; + std::string dump_summary() const override; + void pin_mode(gpio::Flags flags) override { this->parent_->set_pin_direction_(this->pin_, flags); } + bool digital_read() override { return this->parent_->read_pin_val_(this->pin_) != this->inverted_; } + void digital_write(bool value) override { this->parent_->write_pin_val_(this->pin_, value != this->inverted_); } + + protected: + WeikaiComponent *parent_{nullptr}; + uint8_t pin_; + bool inverted_; + gpio::Flags flags_; +}; + +/////////////////////////////////////////////////////////////////////////////////////////////////// +/// @brief The WeikaiChannel class is used to implement all the virtual methods of the ESPHome +/// uart::UARTComponent virtual class. This class is common to the different members of the Weikai +/// components family and therefore avoid code duplication. +/////////////////////////////////////////////////////////////////////////////////////////////////// +class WeikaiChannel : public uart::UARTComponent { + public: + /// @brief We belongs to this WeikaiComponent + /// @param parent pointer to the component we belongs to + void set_parent(WeikaiComponent *parent) { + this->parent_ = parent; + this->parent_->children_.push_back(this); // add ourself to the list (vector) + } + + /// @brief Sets the channel number + /// @param channel number + void set_channel(uint8_t channel) { this->channel_ = channel; } + + /// @brief The name as generated by the Python code generator + /// @param name of the channel + void set_channel_name(std::string name) { this->name_ = std::move(name); } + + /// @brief Get the channel name + /// @return the name + const char *get_channel_name() { return this->name_.c_str(); } + + /// @brief Setup the channel + void virtual setup_channel(); + + /// @brief dump channel information + void virtual dump_channel(); + + /// @brief Factory method to create a WeikaiRegister proxy object + /// @param reg address of the register + /// @return a reference to WeikaiRegister + WeikaiRegister ®(uint8_t reg) { return this->parent_->reg(reg, channel_); } + + // + // we implements/overrides the virtual class from UARTComponent + // + + /// @brief Writes a specified number of bytes to a serial port + /// @param buffer pointer to the buffer + /// @param length number of bytes to write + /// @details This method sends 'length' characters from the buffer to the serial line. Unfortunately (unlike the + /// Arduino equivalent) this method does not return any flag and therefore it is not possible to know if any/all bytes + /// have been transmitted correctly. Another problem is that it is not possible to know ahead of time how many bytes + /// we can safely send as there is no tx_available() method provided! To avoid overrun when using the write method you + /// can use the flush() method to wait until the transmit fifo is empty. + /// @n Typical usage could be: + /// @code + /// // ... + /// uint8_t buffer[128]; + /// // ... + /// write_array(&buffer, length); + /// flush(); + /// // ... + /// @endcode + void write_array(const uint8_t *buffer, size_t length) override; + + /// @brief Reads a specified number of bytes from a serial port + /// @param buffer buffer to store the bytes + /// @param length number of bytes to read + /// @return true if succeed, false otherwise + /// @details Typical usage: + /// @code + /// // ... + /// auto length = available(); + /// uint8_t buffer[128]; + /// if (length > 0) { + /// auto status = read_array(&buffer, length) + /// // test status ... + /// } + /// @endcode + bool read_array(uint8_t *buffer, size_t length) override; + + /// @brief Reads the first byte in FIFO without removing it + /// @param buffer pointer to the byte + /// @return true if succeed reading one byte, false if no character available + /// @details This method returns the next byte from receiving buffer without removing it from the internal fifo. It + /// returns true if a character is available and has been read, false otherwise.\n + bool peek_byte(uint8_t *buffer) override; + + /// @brief Returns the number of bytes in the receive buffer + /// @return the number of bytes available in the receiver fifo + int 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 + /// 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; + + protected: + friend class WeikaiComponent; + + /// @brief this cannot happen with external uart therefore we do nothing + void check_logger_conflict() override {} + + /// @brief reset the weikai internal FIFO + void reset_fifo_(); + + /// @brief set the line parameters + void set_line_param_(); + + /// @brief set the baud rate + void set_baudrate_(); + + /// @brief Returns the number of bytes in the receive fifo + /// @return the number of bytes in the fifo + size_t rx_in_fifo_(); + + /// @brief Returns the number of bytes in the transmit fifo + /// @return the number of bytes in the fifo + size_t tx_in_fifo_(); + + /// @brief test if transmit buffer is not empty in the status register (optimization) + /// @return true if not emptygroup test_ + bool tx_fifo_is_not_empty_(); + + /// @brief transfer bytes from the weikai internal FIFO to the buffer (if any) + /// @return number of bytes transferred + size_t xfer_fifo_to_buffer_(); + + /// @brief check if channel is alive + /// @return true if OK + bool virtual check_channel_down(); + +#ifdef TEST_COMPONENT + /// @ingroup test_ + /// @{ + + /// @brief Test the write_array() method + /// @param message to display + void uart_send_test_(char *message); + + /// @brief Test the read_array() method + /// @param message to display + /// @return true if success + bool uart_receive_test_(char *message); + /// @} +#endif + + /// @brief the buffer where we store temporarily the bytes received + WKRingBuffer receive_buffer_; + WeikaiComponent *parent_; ///< our WK2168component parent + uint8_t channel_; ///< our Channel number + uint8_t data_; ///< a one byte buffer for register read storage + std::string name_; ///< name of the entity +}; + +} // namespace weikai +} // namespace esphome diff --git a/esphome/components/weikai/wk_reg_def.h b/esphome/components/weikai/wk_reg_def.h new file mode 100644 index 0000000000..f3c90b196a --- /dev/null +++ b/esphome/components/weikai/wk_reg_def.h @@ -0,0 +1,304 @@ +/// @file wk_reg_def.h +/// @author DrCoolZic +/// @brief WeiKai component family - registers' definition +/// @date Last Modified: 2024/02/18 15:49:18 +#pragma once + +namespace esphome { +namespace weikai { + +//////////////////////////////////////////////////////////////////////////////////////// +/// Definition of the WeiKai registers +//////////////////////////////////////////////////////////////////////////////////////// + +/// @defgroup wk2168_gr_ WeiKai Global Registers +/// This section groups all **Global Registers**: these registers are global to the +/// the WeiKai chip (i.e. independent of the UART channel used) +/// @note only registers and parameters used have been fully documented +/// @{ + +/// @brief Global Control Register - 00 0000 +/// @details @code +/// ------------------------------------------------------------------------- +/// | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 | bit +/// ------------------------------------------------------------------------- +/// | M0 | M1 | RSV | C4EN | C3EN | C2EN | C1EN | name +/// ------------------------------------------------------------------------- +/// | R | R | R | R | W/R | W/R | W/R | W/R | type +/// ------------------------------------------------------------------------- +/// | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | reset +/// ------------------------------------------------------------------------- +/// @endcode +constexpr uint8_t WKREG_GENA = 0x00; +/// @brief Channel 4 enable clock (0: disable, 1: enable) +constexpr uint8_t GENA_C4EN = 1 << 3; +/// @brief Channel 3 enable clock (0: disable, 1: enable) +constexpr uint8_t GENA_C3EN = 1 << 2; +/// @brief Channel 2 enable clock (0: disable, 1: enable) +constexpr uint8_t GENA_C2EN = 1 << 1; +/// @brief Channel 1 enable clock (0: disable, 1: enable) +constexpr uint8_t GENA_C1EN = 1 << 0; + +/// @brief Global Reset Register - 00 0001 +/// @details @code +/// ------------------------------------------------------------------------- +/// | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 | bit +/// ------------------------------------------------------------------------- +/// | C4SLEEP| C3SLEEP| C2SLEEP| C1SLEEP| C4RST | C3RST | C2RST | C1RST | name +/// ------------------------------------------------------------------------- +/// | R | R | R | R | W1/R0 | W1/R0 | W1/R0 | W1/R0 | type +/// ------------------------------------------------------------------------- +/// | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | reset +/// ------------------------------------------------------------------------- +/// @endcode +constexpr uint8_t WKREG_GRST = 0x01; +/// @brief Channel 4 soft reset (0: not reset, 1: reset) +constexpr uint8_t GRST_C4RST = 1 << 3; +/// @brief Channel 3 soft reset (0: not reset, 1: reset) +constexpr uint8_t GRST_C3RST = 1 << 2; +/// @brief Channel 2 soft reset (0: not reset, 1: reset) +constexpr uint8_t GRST_C2RST = 1 << 1; +/// @brief Channel 1 soft reset (0: not reset, 1: reset) +constexpr uint8_t GRST_C1RST = 1 << 0; + +/// @brief Global Master channel control register (not used) - 000010 +constexpr uint8_t WKREG_GMUT = 0x02; + +/// Global interrupt register (not used) - 01 0000 +constexpr uint8_t WKREG_GIER = 0x10; + +/// Global interrupt flag register (not used) 01 0001 +constexpr uint8_t WKREG_GIFR = 0x11; + +/// @brief Global GPIO direction register - 10 0001 +/// @details @code +/// ------------------------------------------------------------------------- +/// | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 | bit +/// ------------------------------------------------------------------------- +/// | PD7 | PD6 | PD5 | PD4 | PD3 | PD2 | PD1 | PD0 | name +/// ------------------------------------------------------------------------- +/// | W/R | W/R | W/R | W/R | W/R | W/R | W/R | W/R | type +/// ------------------------------------------------------------------------- +/// | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | reset +/// ------------------------------------------------------------------------- +/// @endcode +constexpr uint8_t WKREG_GPDIR = 0x21; + +/// @brief Global GPIO data register - 11 0001 +/// @details @code +/// ------------------------------------------------------------------------- +/// | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 | bit +/// ------------------------------------------------------------------------- +/// | PV7 | PV6 | PV5 | PV4 | PV3 | PV2 | PV1 | PV0 | name +/// ------------------------------------------------------------------------- +/// | W/R | W/R | W/R | W/R | W/R | W/R | W/R | W/R | type +/// ------------------------------------------------------------------------- +/// | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | reset +/// ------------------------------------------------------------------------- +/// @endcode +constexpr uint8_t WKREG_GPDAT = 0x31; + +/// @} +/// @defgroup WeiKai_cr_ WeiKai Channel Registers +/// @brief Definition of the register linked to a particular channel +/// @details This topic groups all the **Channel Registers**: these registers are specific +/// to the a specific channel i.e. each channel has its own set of registers +/// @note only registers and parameters used have been documented +/// @{ + +/// @defgroup cr_p0 Channel registers when SPAGE=0 +/// @brief Definition of the register linked to a particular channel when SPAGE=0 +/// @details The channel registers are further splitted into two groups. +/// This first group is defined when the Global register WKREG_SPAGE is 0 +/// @{ + +/// @brief Global Page register c0/c1 0011 +/// @details @code +/// ------------------------------------------------------------------------- +/// | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 | bit +/// ------------------------------------------------------------------------- +/// | RSV | PAGE | name +/// ------------------------------------------------------------------------- +/// | R | R | R | R | R | R | R | W/R | type +/// ------------------------------------------------------------------------- +/// | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | reset +/// ------------------------------------------------------------------------- +/// @endcode +constexpr uint8_t WKREG_SPAGE = 0x03; + +/// @brief Serial Control Register - c0/c1 0100 +/// @details @code +/// ------------------------------------------------------------------------- +/// | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 | bit +/// ------------------------------------------------------------------------- +/// | RSV | SLPEN | TXEN | RXEN | name +/// ------------------------------------------------------------------------- +/// | R | R | R | R | R | R/W | R/W | W/R | type +/// ------------------------------------------------------------------------- +/// | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | reset +/// ------------------------------------------------------------------------- +/// @endcode +constexpr uint8_t WKREG_SCR = 0x04; +/// @brief transmission control (0: enable, 1: disable) +constexpr uint8_t SCR_TXEN = 1 << 1; +/// @brief receiving control (0: enable, 1: disable) +constexpr uint8_t SCR_RXEN = 1 << 0; + +/// @brief Line Configuration Register - c0/c1 0101 +/// @details @code +/// ------------------------------------------------------------------------- +/// | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 | bit +/// ------------------------------------------------------------------------- +/// | RSV | BREAK | IREN | PAEN | PARITY | STPL | name +/// ------------------------------------------------------------------------- +/// | W/R | W/R | W/R | W/R | W/R | W/R | W/R | W/R | type +/// ------------------------------------------------------------------------- +/// | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | reset +/// ------------------------------------------------------------------------- +/// @endcode +constexpr uint8_t WKREG_LCR = 0x05; +/// @brief Parity enable (0: no check, 1: check) +constexpr uint8_t LCR_PAEN = 1 << 3; +/// @brief Parity force 0 +constexpr uint8_t LCR_PAR_F0 = 0 << 1; +/// @brief Parity odd +constexpr uint8_t LCR_PAR_ODD = 1 << 1; +/// @brief Parity even +constexpr uint8_t LCR_PAR_EVEN = 2 << 1; +/// @brief Parity force 1 +constexpr uint8_t LCR_PAR_F1 = 3 << 1; +/// @brief Stop length (0: 1 bit, 1: 2 bits) +constexpr uint8_t LCR_STPL = 1 << 0; + +/// @brief FIFO Control Register - c0/c1 0110 +/// @details @code +/// ------------------------------------------------------------------------- +/// | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 | bit +/// ------------------------------------------------------------------------- +/// | TFTRIG | RFTRIG | TFEN | RFEN | TFRST | RFRST | name +/// ------------------------------------------------------------------------- +/// | W/R | W/R | W/R | W/R | W/R | W/R | W/R | W/R | type +/// ------------------------------------------------------------------------- +/// | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | reset +/// ------------------------------------------------------------------------- +/// @endcode +constexpr uint8_t WKREG_FCR = 0x06; +/// @brief Transmitter FIFO enable +constexpr uint8_t FCR_TFEN = 1 << 3; +/// @brief Receiver FIFO enable +constexpr uint8_t FCR_RFEN = 1 << 2; +/// @brief Transmitter FIFO reset +constexpr uint8_t FCR_TFRST = 1 << 1; +/// @brief Receiver FIFO reset +constexpr uint8_t FCR_RFRST = 1 << 0; + +/// @brief Serial Interrupt Enable Register (not used) - c0/c1 0111 +constexpr uint8_t WKREG_SIER = 0x07; + +/// @brief Serial Interrupt Flag Register (not used) - c0/c1 1000 +constexpr uint8_t WKREG_SIFR = 0x08; + +/// @brief Transmitter FIFO Count - c0/c1 1001 +/// @details @code +/// ------------------------------------------------------------------------- +/// | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 | +/// ------------------------------------------------------------------------- +/// | NUMBER OF DATA IN TRANSMITTER FIFO | +/// ------------------------------------------------------------------------- +/// @endcode +constexpr uint8_t WKREG_TFCNT = 0x09; + +/// @brief Receiver FIFO count - c0/c1 1010 +/// @details @code +/// ------------------------------------------------------------------------- +/// | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 | +/// ------------------------------------------------------------------------- +/// | NUMBER OF DATA IN RECEIVER FIFO | +/// ------------------------------------------------------------------------- +/// @endcode +constexpr uint8_t WKREG_RFCNT = 0x0A; + +/// @brief FIFO Status Register - c0/c1 1011 +/// @details @code +/// ------------------------------------------------------------------------- +/// | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 | bit +/// ------------------------------------------------------------------------- +/// | RFOE | RFLB | RFFE | RFPE | RFDAT | TFDAT | TFFULL | TBUSY | name +/// ------------------------------------------------------------------------- +/// | R | W/R | W/R | W/R | W/R | W/R | W/R | W/R | type +/// ------------------------------------------------------------------------- +/// | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | reset +/// ------------------------------------------------------------------------- +/// @endcode +/// @warning The received buffer can hold 256 bytes. However, as the RFCNT reg +/// is 8 bits, if we have 256 byte in the register this is reported as 0 ! Therefore +/// RFCNT=0 can indicate that there are 0 **or** 256 bytes in the buffer. If we +/// have RFDAT = 1 and RFCNT = 0 it should be interpreted as 256 bytes in the FIFO. +/// @note Note that in case of overflow the RFOE goes to one **but** as soon as you read +/// the FSR this bit is cleared. Therefore Overflow can be read only once. +/// @n The same problem applies to the transmit buffer but here we have to check the +/// TFFULL flag. So if TFFULL is set and TFCNT is 0 this should be interpreted as 256 +constexpr uint8_t WKREG_FSR = 0x0B; +/// @brief Receiver FIFO Overflow Error (0: no OE, 1: OE) +constexpr uint8_t FSR_RFOE = 1 << 7; +/// @brief Receiver FIFO Line Break (0: no LB, 1: LB) +constexpr uint8_t FSR_RFLB = 1 << 6; +/// @brief Receiver FIFO Frame Error (0: no FE, 1: FE) +constexpr uint8_t FSR_RFFE = 1 << 5; +/// @brief Receiver Parity Error (0: no PE, 1: PE) +constexpr uint8_t FSR_RFPE = 1 << 4; +/// @brief Receiver FIFO count (0: empty, 1: not empty) +constexpr uint8_t FSR_RFDAT = 1 << 3; +/// @brief Transmitter FIFO count (0: empty, 1: not empty) +constexpr uint8_t FSR_TFDAT = 1 << 2; +/// @brief Transmitter FIFO full (0: not full, 1: full) +constexpr uint8_t FSR_TFFULL = 1 << 1; +/// @brief Transmitter busy (0 nothing to transmit, 1: transmitter busy sending) +constexpr uint8_t FSR_TBUSY = 1 << 0; + +/// @brief Line Status Register (not used - using FIFO) +constexpr uint8_t WKREG_LSR = 0x0C; + +/// @brief FIFO Data Register (not used - does not seems to work) +constexpr uint8_t WKREG_FDAT = 0x0D; + +/// @} +/// @defgroup cr_p1 Channel registers for SPAGE=1 +/// @brief Definition of the register linked to a particular channel when SPAGE=1 +/// @details The channel registers are further splitted into two groups. +/// This second group is defined when the Global register WKREG_SPAGE is 1 +/// @{ + +/// @brief Baud rate configuration register: high byte - c0/c1 0100 +/// @details @code +/// ------------------------------------------------------------------------- +/// | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 | +/// ------------------------------------------------------------------------- +/// | High byte of the baud rate | +/// ------------------------------------------------------------------------- +/// @endcode +constexpr uint8_t WKREG_BRH = 0x04; + +/// @brief Baud rate configuration register: low byte - c0/c1 0101 +/// @details @code +/// ------------------------------------------------------------------------- +/// | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 | +/// ------------------------------------------------------------------------- +/// | Low byte of the baud rate | +/// ------------------------------------------------------------------------- +/// @endcode +constexpr uint8_t WKREG_BRL = 0x05; + +/// @brief Baud rate configuration register decimal part - c0/c1 0110 +constexpr uint8_t WKREG_BRD = 0x06; + +/// @brief Receive FIFO Interrupt trigger configuration (not used) - c0/c1 0111 +constexpr uint8_t WKREG_RFI = 0x07; + +/// @brief Transmit FIFO interrupt trigger configuration (not used) - c0/c1 1000 +constexpr uint8_t WKREG_TFI = 0x08; + +/// @} +/// @} +} // namespace weikai +} // namespace esphome diff --git a/esphome/components/weikai_i2c/__init__.py b/esphome/components/weikai_i2c/__init__.py new file mode 100644 index 0000000000..2c6a421a0a --- /dev/null +++ b/esphome/components/weikai_i2c/__init__.py @@ -0,0 +1 @@ +CODEOWNERS = ["@DrCoolZic"] diff --git a/esphome/components/weikai_i2c/weikai_i2c.cpp b/esphome/components/weikai_i2c/weikai_i2c.cpp new file mode 100644 index 0000000000..9d0c9446ec --- /dev/null +++ b/esphome/components/weikai_i2c/weikai_i2c.cpp @@ -0,0 +1,177 @@ +/// @file weikai_i2c.cpp +/// @brief WeiKai component family - classes implementation +/// @date Last Modified: 2024/04/06 14:43:31 +/// @details The classes declared in this file can be used by the Weikai family + +#include "weikai_i2c.h" + +namespace esphome { +namespace weikai_i2c { +static const char *const TAG = "weikai_i2c"; + +/// @brief Display a buffer in hexadecimal format (32 hex values / line). +void print_buffer(const uint8_t *data, size_t length) { + char hex_buffer[100]; + hex_buffer[(3 * 32) + 1] = 0; + for (size_t i = 0; i < length; i++) { + snprintf(&hex_buffer[3 * (i % 32)], sizeof(hex_buffer), "%02X ", data[i]); + if (i % 32 == 31) { + ESP_LOGVV(TAG, " %s", hex_buffer); + } + } + if (length % 32) { + // null terminate if incomplete line + hex_buffer[3 * (length % 32) + 2] = 0; + ESP_LOGVV(TAG, " %s", hex_buffer); + } +} + +static const char *const REG_TO_STR_P0[16] = {"GENA", "GRST", "GMUT", "SPAGE", "SCR", "LCR", "FCR", "SIER", + "SIFR", "TFCNT", "RFCNT", "FSR", "LSR", "FDAT", "FWCR", "RS485"}; +static const char *const REG_TO_STR_P1[16] = {"GENA", "GRST", "GMUT", "SPAGE", "BAUD1", "BAUD0", "PRES", "RFTL", + "TFTL", "FWTH", "FWTL", "XON1", "XOFF1", "SADR", "SAEN", "RTSDLY"}; +using namespace weikai; +// method to print a register value as text: used in the log messages ... +const char *reg_to_str(int reg, bool page1) { + if (reg == WKREG_GPDAT) { + return "GPDAT"; + } else if (reg == WKREG_GPDIR) { + return "GPDIR"; + } else { + return page1 ? REG_TO_STR_P1[reg & 0x0F] : REG_TO_STR_P0[reg & 0x0F]; + } +} +enum RegType { REG = 0, FIFO = 1 }; ///< Register or FIFO + +/// @brief Computes the I²C bus's address used to access the component +/// @param base_address the base address of the component - set by the A1 A0 pins +/// @param channel (0-3) the UART channel +/// @param fifo (0-1) 0 = access to internal register, 1 = direct access to fifo +/// @return the i2c address to use +inline uint8_t i2c_address(uint8_t base_address, uint8_t channel, RegType fifo) { + // the address of the device is: + // +----+----+----+----+----+----+----+----+ + // | 0 | A1 | A0 | 1 | 0 | C1 | C0 | F | + // +----+----+----+----+----+----+----+----+ + // where: + // - A1,A0 is the address read from A1,A0 switch + // - C1,C0 is the channel number (in practice only 00 or 01) + // - F is: 0 when accessing register, one when accessing FIFO + uint8_t const addr = base_address | channel << 1 | fifo << 0; + return addr; +} + +/////////////////////////////////////////////////////////////////////////////// +// The WeikaiRegisterI2C methods +/////////////////////////////////////////////////////////////////////////////// +uint8_t WeikaiRegisterI2C::read_reg() const { + uint8_t value = 0x00; + WeikaiComponentI2C *comp_i2c = static_cast(this->comp_); + uint8_t address = i2c_address(comp_i2c->base_address_, this->channel_, REG); + comp_i2c->set_i2c_address(address); + auto error = comp_i2c->read_register(this->register_, &value, 1); + if (error == i2c::NO_ERROR) { + this->comp_->status_clear_warning(); + ESP_LOGVV(TAG, "WeikaiRegisterI2C::read_reg() @%02X reg=%s ch=%u I2C_code:%d, buf=%02X", address, + reg_to_str(this->register_, comp_i2c->page1()), this->channel_, (int) error, value); + } else { // error + this->comp_->status_set_warning(); + ESP_LOGE(TAG, "WeikaiRegisterI2C::read_reg() @%02X reg=%s ch=%u I2C_code:%d, buf=%02X", address, + reg_to_str(this->register_, comp_i2c->page1()), this->channel_, (int) error, value); + } + return value; +} + +void WeikaiRegisterI2C::read_fifo(uint8_t *data, size_t length) const { + WeikaiComponentI2C *comp_i2c = static_cast(this->comp_); + uint8_t address = i2c_address(comp_i2c->base_address_, this->channel_, FIFO); + comp_i2c->set_i2c_address(address); + auto error = comp_i2c->read(data, length); + if (error == i2c::NO_ERROR) { + this->comp_->status_clear_warning(); +#ifdef ESPHOME_LOG_HAS_VERY_VERBOSE + ESP_LOGVV(TAG, "WeikaiRegisterI2C::read_fifo() @%02X ch=%d I2C_code:%d len=%d buffer", address, this->channel_, + (int) error, length); + print_buffer(data, length); +#endif + } else { // error + this->comp_->status_set_warning(); + ESP_LOGE(TAG, "WeikaiRegisterI2C::read_fifo() @%02X reg=N/A ch=%d I2C_code:%d len=%d buf=%02X...", address, + this->channel_, (int) error, length, data[0]); + } +} + +void WeikaiRegisterI2C::write_reg(uint8_t value) { + WeikaiComponentI2C *comp_i2c = static_cast(this->comp_); + uint8_t address = i2c_address(comp_i2c->base_address_, this->channel_, REG); // update the i2c bus + comp_i2c->set_i2c_address(address); + auto error = comp_i2c->write_register(this->register_, &value, 1); + if (error == i2c::NO_ERROR) { + this->comp_->status_clear_warning(); + ESP_LOGVV(TAG, "WK2168Reg::write_reg() @%02X reg=%s ch=%d I2C_code:%d buf=%02X", address, + reg_to_str(this->register_, comp_i2c->page1()), this->channel_, (int) error, value); + } else { // error + this->comp_->status_set_warning(); + ESP_LOGE(TAG, "WK2168Reg::write_reg() @%02X reg=%s ch=%d I2C_code:%d buf=%d", address, + reg_to_str(this->register_, comp_i2c->page1()), this->channel_, (int) error, value); + } +} + +void WeikaiRegisterI2C::write_fifo(uint8_t *data, size_t length) { + WeikaiComponentI2C *comp_i2c = static_cast(this->comp_); + uint8_t address = i2c_address(comp_i2c->base_address_, this->channel_, FIFO); // set fifo flag + comp_i2c->set_i2c_address(address); + auto error = comp_i2c->write(data, length); + if (error == i2c::NO_ERROR) { + this->comp_->status_clear_warning(); +#ifdef ESPHOME_LOG_HAS_VERY_VERBOSE + ESP_LOGVV(TAG, "WK2168Reg::write_fifo() @%02X ch=%d I2C_code:%d len=%d buffer", address, this->channel_, + (int) error, length); + print_buffer(data, length); +#endif + } else { // error + this->comp_->status_set_warning(); + ESP_LOGE(TAG, "WK2168Reg::write_fifo() @%02X reg=N/A, ch=%d I2C_code:%d len=%d, buf=%02X...", address, + this->channel_, (int) error, length, data[0]); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// The WeikaiComponentI2C methods +/////////////////////////////////////////////////////////////////////////////// +void WeikaiComponentI2C::setup() { + // before any manipulation we store the address to base_address_ for future use + this->base_address_ = this->address_; + ESP_LOGCONFIG(TAG, "Setting up wk2168_i2c: %s with %d UARTs at @%02X ...", this->get_name(), this->children_.size(), + this->base_address_); + + // enable all channels + this->reg(WKREG_GENA, 0) = GENA_C1EN | GENA_C2EN | GENA_C3EN | GENA_C4EN; + // reset all channels + this->reg(WKREG_GRST, 0) = GRST_C1RST | GRST_C2RST | GRST_C3RST | GRST_C4RST; + // initialize the spage register to page 0 + this->reg(WKREG_SPAGE, 0) = 0; + this->page1_ = false; + + // we setup our children channels + for (auto *child : this->children_) { + child->setup_channel(); + } +} + +void WeikaiComponentI2C::dump_config() { + ESP_LOGCONFIG(TAG, "Initialization of %s with %d UARTs completed", this->get_name(), this->children_.size()); + ESP_LOGCONFIG(TAG, " Crystal: %" PRIu32, this->crystal_); + if (test_mode_) + ESP_LOGCONFIG(TAG, " Test mode: %d", test_mode_); + ESP_LOGCONFIG(TAG, " Transfer buffer size: %d", XFER_MAX_SIZE); + this->address_ = this->base_address_; // we restore the base_address before display (less confusing) + LOG_I2C_DEVICE(this); + + for (auto *child : this->children_) { + child->dump_channel(); + } +} + +} // namespace weikai_i2c +} // namespace esphome diff --git a/esphome/components/weikai_i2c/weikai_i2c.h b/esphome/components/weikai_i2c/weikai_i2c.h new file mode 100644 index 0000000000..0da9ed9cde --- /dev/null +++ b/esphome/components/weikai_i2c/weikai_i2c.h @@ -0,0 +1,61 @@ +/// @file weikai_i2c.h +/// @author DrCoolZic +/// @brief WeiKai component family - classes declaration +/// @date Last Modified: 2024/03/01 13:31:57 +/// @details The classes declared in this file can be used by the Weikai family +/// wk2132_i2c, wk2168_i2c, wk2204_i2c, wk2212_i2c + +#pragma once +#include +#include +#include "esphome/core/component.h" +#include "esphome/components/uart/uart.h" +#include "esphome/components/i2c/i2c.h" +#include "esphome/components/weikai/weikai.h" + +namespace esphome { +namespace weikai_i2c { + +class WeikaiComponentI2C; + +// using namespace weikai; +//////////////////////////////////////////////////////////////////////////////////// +/// @brief WeikaiRegisterI2C objects acts as proxies to access remote register through an I2C Bus +//////////////////////////////////////////////////////////////////////////////////// +class WeikaiRegisterI2C : public weikai::WeikaiRegister { + public: + uint8_t read_reg() const override; + void write_reg(uint8_t value) override; + void read_fifo(uint8_t *data, size_t length) const override; + void write_fifo(uint8_t *data, size_t length) override; + + protected: + friend WeikaiComponentI2C; + WeikaiRegisterI2C(weikai::WeikaiComponent *const comp, uint8_t reg, uint8_t channel) + : weikai::WeikaiRegister(comp, reg, channel) {} +}; + +//////////////////////////////////////////////////////////////////////////////////// +/// @brief The WeikaiComponentI2C class stores the information to the WeiKai component +/// connected through an I2C bus. +//////////////////////////////////////////////////////////////////////////////////// +class WeikaiComponentI2C : public weikai::WeikaiComponent, public i2c::I2CDevice { + public: + weikai::WeikaiRegister ®(uint8_t reg, uint8_t channel) override { + reg_i2c_.register_ = reg; + reg_i2c_.channel_ = channel; + return reg_i2c_; + } + + // + // override Component methods + // + void setup() override; + void dump_config() override; + + uint8_t base_address_; ///< base address of I2C device + WeikaiRegisterI2C reg_i2c_{this, 0, 0}; ///< init to this component +}; + +} // namespace weikai_i2c +} // namespace esphome diff --git a/esphome/components/weikai_spi/__init__.py b/esphome/components/weikai_spi/__init__.py new file mode 100644 index 0000000000..2c6a421a0a --- /dev/null +++ b/esphome/components/weikai_spi/__init__.py @@ -0,0 +1 @@ +CODEOWNERS = ["@DrCoolZic"] diff --git a/esphome/components/weikai_spi/weikai_spi.cpp b/esphome/components/weikai_spi/weikai_spi.cpp new file mode 100644 index 0000000000..22c63bbd2d --- /dev/null +++ b/esphome/components/weikai_spi/weikai_spi.cpp @@ -0,0 +1,189 @@ +/// @file weikai_spi.cpp +/// @brief WeiKai component family - classes implementation +/// @date Last Modified: 2024/04/06 14:46:09 +/// @details The classes declared in this file can be used by the Weikai family + +#include "weikai_spi.h" + +namespace esphome { +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 +uint32_t elapsed_ms(uint32_t &last_time) { + uint32_t e = millis() - last_time; + last_time = millis(); + return e; +}; + +/// @brief Converts the parity enum value to a C string +/// @param parity enum +/// @return the string +const char *p2s(uart::UARTParityOptions parity) { + using namespace uart; + switch (parity) { + case UART_CONFIG_PARITY_NONE: + return "NONE"; + case UART_CONFIG_PARITY_EVEN: + return "EVEN"; + case UART_CONFIG_PARITY_ODD: + return "ODD"; + default: + return "UNKNOWN"; + } +} + +/// @brief Display a buffer in hexadecimal format (32 hex values / line). +void print_buffer(const uint8_t *data, size_t length) { + char hex_buffer[100]; + hex_buffer[(3 * 32) + 1] = 0; + for (size_t i = 0; i < length; i++) { + snprintf(&hex_buffer[3 * (i % 32)], sizeof(hex_buffer), "%02X ", data[i]); + if (i % 32 == 31) { + ESP_LOGVV(TAG, " %s", hex_buffer); + } + } + if (length % 32) { + // null terminate if incomplete line + hex_buffer[3 * (length % 32) + 2] = 0; + ESP_LOGVV(TAG, " %s", hex_buffer); + } +} + +static const char *const REG_TO_STR_P0[16] = {"GENA", "GRST", "GMUT", "SPAGE", "SCR", "LCR", "FCR", "SIER", + "SIFR", "TFCNT", "RFCNT", "FSR", "LSR", "FDAT", "FWCR", "RS485"}; +static const char *const REG_TO_STR_P1[16] = {"GENA", "GRST", "GMUT", "SPAGE", "BAUD1", "BAUD0", "PRES", "RFTL", + "TFTL", "FWTH", "FWTL", "XON1", "XOFF1", "SADR", "SAEN", "RTSDLY"}; + +// method to print a register value as text: used in the log messages ... +const char *reg_to_str(int reg, bool page1) { + if (reg == WKREG_GPDAT) { + return "GPDAT"; + } else if (reg == WKREG_GPDIR) { + return "GPDIR"; + } else { + return page1 ? REG_TO_STR_P1[reg & 0x0F] : REG_TO_STR_P0[reg & 0x0F]; + } +} + +enum RegType { REG = 0, FIFO = 1 }; ///< Register or FIFO +enum CmdType { WRITE_CMD = 0, READ_CMD = 1 }; ///< Read or Write transfer + +/// @brief Computes the SPI command byte +/// @param transfer_type read or write command +/// @param reg (0-15) the address of the register +/// @param channel (0-3) the UART channel +/// @param fifo (0-1) 0 = access to internal register, 1 = direct access to fifo +/// @return the spi command byte +/// @details +/// +------+------+------+------+------+------+------+------+ +/// | FIFO | R/W | C1-C0 | A3-A0 | +/// +------+------+-------------+---------------------------+ +/// FIFO: 0 = register, 1 = FIFO +/// R/W: 0 = write, 1 = read +/// C1-C0: Channel (0-1) +/// A3-A0: Address (0-F) +inline static uint8_t cmd_byte(RegType fifo, CmdType transfer_type, uint8_t channel, uint8_t reg) { + return (fifo << 7 | transfer_type << 6 | channel << 4 | reg << 0); +} + +/////////////////////////////////////////////////////////////////////////////// +// The WeikaiRegisterSPI methods +/////////////////////////////////////////////////////////////////////////////// +uint8_t WeikaiRegisterSPI::read_reg() const { + auto *spi_comp = static_cast(this->comp_); + uint8_t cmd = cmd_byte(REG, READ_CMD, this->channel_, this->register_); + spi_comp->enable(); + 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, + reg_to_str(this->register_, this->comp_->page1()), this->channel_, val); + return val; +} + +void WeikaiRegisterSPI::read_fifo(uint8_t *data, size_t length) const { + auto *spi_comp = static_cast(this->comp_); + uint8_t cmd = cmd_byte(FIFO, READ_CMD, this->channel_, this->register_); + spi_comp->enable(); + spi_comp->write_byte(cmd); + 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); + print_buffer(data, length); +#endif +} + +void WeikaiRegisterSPI::write_reg(uint8_t value) { + auto *spi_comp = static_cast(this->comp_); + uint8_t buf[2]{cmd_byte(REG, WRITE_CMD, this->channel_, this->register_), 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]); +} + +void WeikaiRegisterSPI::write_fifo(uint8_t *data, size_t length) { + auto *spi_comp = static_cast(this->comp_); + uint8_t cmd = cmd_byte(FIFO, WRITE_CMD, this->channel_, this->register_); + spi_comp->enable(); + spi_comp->write_byte(cmd); + spi_comp->write_array(data, 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); + print_buffer(data, length); +#endif +} + +/////////////////////////////////////////////////////////////////////////////// +// The WeikaiComponentSPI methods +/////////////////////////////////////////////////////////////////////////////// +void WeikaiComponentSPI::setup() { + using namespace weikai; + ESP_LOGCONFIG(TAG, "Setting up wk2168_spi: %s with %d UARTs...", this->get_name(), this->children_.size()); + this->spi_setup(); + // enable all channels + this->reg(WKREG_GENA, 0) = GENA_C1EN | GENA_C2EN | GENA_C3EN | GENA_C4EN; + // reset all channels + this->reg(WKREG_GRST, 0) = GRST_C1RST | GRST_C2RST | GRST_C3RST | GRST_C4RST; + // initialize the spage register to page 0 + this->reg(WKREG_SPAGE, 0) = 0; + this->page1_ = false; + + // we setup our children channels + for (auto *child : this->children_) { + child->setup_channel(); + } +} + +void WeikaiComponentSPI::dump_config() { + ESP_LOGCONFIG(TAG, "Initialization of %s with %d UARTs completed", this->get_name(), this->children_.size()); + ESP_LOGCONFIG(TAG, " Crystal: %" PRIu32 "", this->crystal_); + if (test_mode_) + ESP_LOGCONFIG(TAG, " Test mode: %d", test_mode_); + ESP_LOGCONFIG(TAG, " Transfer buffer size: %d", XFER_MAX_SIZE); + LOG_PIN(" CS Pin: ", this->cs_); + + for (auto *child : this->children_) { + child->dump_channel(); + } +} + +} // namespace weikai_spi +} // namespace esphome diff --git a/esphome/components/weikai_spi/weikai_spi.h b/esphome/components/weikai_spi/weikai_spi.h new file mode 100644 index 0000000000..dd0dc8d495 --- /dev/null +++ b/esphome/components/weikai_spi/weikai_spi.h @@ -0,0 +1,54 @@ +/// @file weikai.h +/// @author DrCoolZic +/// @brief WeiKai component family - classes declaration +/// @date Last Modified: 2024/02/29 17:20:32 +/// @details The classes declared in this file can be used by the Weikai family +/// 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" +#include "esphome/components/spi/spi.h" +#include "esphome/components/weikai/weikai.h" + +namespace esphome { +namespace weikai_spi { +//////////////////////////////////////////////////////////////////////////////////// +/// @brief WeikaiRegisterSPI objects acts as proxies to access remote register through an SPI Bus +//////////////////////////////////////////////////////////////////////////////////// +class WeikaiRegisterSPI : public weikai::WeikaiRegister { + public: + WeikaiRegisterSPI(weikai::WeikaiComponent *const comp, uint8_t reg, uint8_t channel) + : weikai::WeikaiRegister(comp, reg, channel) {} + + uint8_t read_reg() const override; + void write_reg(uint8_t value) override; + void read_fifo(uint8_t *data, size_t length) const override; + void write_fifo(uint8_t *data, size_t length) override; +}; + +//////////////////////////////////////////////////////////////////////////////////// +/// @brief The WeikaiComponentSPI class stores the information to the WeiKai component +/// connected through an SPI bus. +//////////////////////////////////////////////////////////////////////////////////// +class WeikaiComponentSPI : public weikai::WeikaiComponent, + public spi::SPIDevice { + public: + weikai::WeikaiRegister ®(uint8_t reg, uint8_t channel) override { + reg_spi_.register_ = reg; + reg_spi_.channel_ = channel; + return reg_spi_; + } + + void setup() override; + void dump_config() override; + + protected: + WeikaiRegisterSPI reg_spi_{this, 0, 0}; ///< init to this component +}; + +} // namespace weikai_spi +} // namespace esphome diff --git a/esphome/components/wk2132_i2c/__init__.py b/esphome/components/wk2132_i2c/__init__.py new file mode 100644 index 0000000000..912ab04236 --- /dev/null +++ b/esphome/components/wk2132_i2c/__init__.py @@ -0,0 +1,30 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import i2c, weikai +from esphome.const import CONF_ID + +CODEOWNERS = ["@DrCoolZic"] +DEPENDENCIES = ["i2c"] +AUTO_LOAD = ["weikai", "weikai_i2c"] +MULTI_CONF = True + +weikai_i2c_ns = cg.esphome_ns.namespace("weikai_i2c") +WeikaiComponentI2C = weikai_i2c_ns.class_( + "WeikaiComponentI2C", weikai.WeikaiComponent, i2c.I2CDevice +) + +CONFIG_SCHEMA = cv.All( + weikai.WKBASE_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(WeikaiComponentI2C), + } + ).extend(i2c.i2c_device_schema(0x2C)), + weikai.check_channel_max_2, +) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + cg.add(var.set_name(str(config[CONF_ID]))) + await weikai.register_weikai(var, config) + await i2c.register_i2c_device(var, config) diff --git a/esphome/components/wk2132_i2c/wk2132_i2c.cpp b/esphome/components/wk2132_i2c/wk2132_i2c.cpp new file mode 100644 index 0000000000..aaefae6f97 --- /dev/null +++ b/esphome/components/wk2132_i2c/wk2132_i2c.cpp @@ -0,0 +1,4 @@ +/* compiling with esp-idf framework requires a .cpp file for some reason ? */ +namespace esphome { +namespace wk2132_i2c {} +} // namespace esphome diff --git a/esphome/components/wk2132_spi/__init__.py b/esphome/components/wk2132_spi/__init__.py new file mode 100644 index 0000000000..02c5fd9604 --- /dev/null +++ b/esphome/components/wk2132_spi/__init__.py @@ -0,0 +1,31 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import spi, weikai + +from esphome.const import CONF_ID + +CODEOWNERS = ["@DrCoolZic"] +DEPENDENCIES = ["spi"] +AUTO_LOAD = ["weikai", "weikai_spi"] +MULTI_CONF = True + +weikai_spi_ns = cg.esphome_ns.namespace("weikai_spi") +WeikaiComponentSPI = weikai_spi_ns.class_( + "WeikaiComponentSPI", weikai.WeikaiComponent, spi.SPIDevice +) + +CONFIG_SCHEMA = cv.All( + weikai.WKBASE_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(WeikaiComponentSPI), + } + ).extend(spi.spi_device_schema()), + weikai.check_channel_max_2, +) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + cg.add(var.set_name(str(config[CONF_ID]))) + await weikai.register_weikai(var, config) + await spi.register_spi_device(var, config) diff --git a/esphome/components/wk2168_i2c/__init__.py b/esphome/components/wk2168_i2c/__init__.py new file mode 100644 index 0000000000..93a8161e8e --- /dev/null +++ b/esphome/components/wk2168_i2c/__init__.py @@ -0,0 +1,64 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome import pins +from esphome.components import i2c, weikai +from esphome.const import ( + CONF_ID, + CONF_INVERTED, + CONF_MODE, + CONF_NUMBER, +) + +CODEOWNERS = ["@DrCoolZic"] +DEPENDENCIES = ["i2c"] +AUTO_LOAD = ["weikai", "weikai_i2c"] +MULTI_CONF = True +CONF_WK2168_I2C = "wk2168_i2c" + +weikai_ns = cg.esphome_ns.namespace("weikai") +weikai_i2c_ns = cg.esphome_ns.namespace("weikai_i2c") +WeikaiComponentI2C = weikai_i2c_ns.class_( + "WeikaiComponentI2C", weikai.WeikaiComponent, i2c.I2CDevice +) +WeikaiGPIOPin = weikai_ns.class_( + "WeikaiGPIOPin", cg.GPIOPin, cg.Parented.template(WeikaiComponentI2C) +) + +CONFIG_SCHEMA = cv.All( + weikai.WKBASE_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(WeikaiComponentI2C), + } + ).extend(i2c.i2c_device_schema(0x2C)), + weikai.check_channel_max_4, +) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + cg.add(var.set_name(str(config[CONF_ID]))) + await weikai.register_weikai(var, config) + await i2c.register_i2c_device(var, config) + + +WK2168_PIN_SCHEMA = cv.All( + weikai.WEIKAI_PIN_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(WeikaiGPIOPin), + cv.Required(CONF_WK2168_I2C): cv.use_id(WeikaiComponentI2C), + } + ), + weikai.validate_pin_mode, +) + + +@pins.PIN_SCHEMA_REGISTRY.register(CONF_WK2168_I2C, WK2168_PIN_SCHEMA) +async def sc16is75x_pin_to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + parent = await cg.get_variable(config[CONF_WK2168_I2C]) + 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/wk2168_spi/__init__.py b/esphome/components/wk2168_spi/__init__.py new file mode 100644 index 0000000000..8861a6738c --- /dev/null +++ b/esphome/components/wk2168_spi/__init__.py @@ -0,0 +1,62 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome import pins +from esphome.components import spi, weikai +from esphome.const import ( + CONF_ID, + CONF_INVERTED, + CONF_MODE, + CONF_NUMBER, +) + +CODEOWNERS = ["@DrCoolZic"] +DEPENDENCIES = ["spi"] +AUTO_LOAD = ["weikai", "weikai_spi"] +MULTI_CONF = True +CONF_WK2168_SPI = "wk2168_spi" + +weikai_spi_ns = cg.esphome_ns.namespace("weikai_spi") +weikai_ns = cg.esphome_ns.namespace("weikai") +WeikaiComponentSPI = weikai_spi_ns.class_( + "WeikaiComponentSPI", weikai.WeikaiComponent, spi.SPIDevice +) +WeikaiGPIOPin = weikai_ns.class_( + "WeikaiGPIOPin", cg.GPIOPin, cg.Parented.template(WeikaiComponentSPI) +) + +CONFIG_SCHEMA = cv.All( + weikai.WKBASE_SCHEMA.extend( + {cv.GenerateID(): cv.declare_id(WeikaiComponentSPI)} + ).extend(spi.spi_device_schema()), + weikai.check_channel_max_4, +) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + cg.add(var.set_name(str(config[CONF_ID]))) + await weikai.register_weikai(var, config) + await spi.register_spi_device(var, config) + + +WK2168_PIN_SCHEMA = cv.All( + weikai.WEIKAI_PIN_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(WeikaiGPIOPin), + cv.Required(CONF_WK2168_SPI): cv.use_id(WeikaiComponentSPI), + }, + ), + weikai.validate_pin_mode, +) + + +@pins.PIN_SCHEMA_REGISTRY.register(CONF_WK2168_SPI, WK2168_PIN_SCHEMA) +async def sc16is75x_pin_to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + parent = await cg.get_variable(config[CONF_WK2168_SPI]) + 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/wk2204_i2c/__init__.py b/esphome/components/wk2204_i2c/__init__.py new file mode 100644 index 0000000000..98eca56c4d --- /dev/null +++ b/esphome/components/wk2204_i2c/__init__.py @@ -0,0 +1,30 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import i2c, weikai +from esphome.const import CONF_ID + +CODEOWNERS = ["@DrCoolZic"] +DEPENDENCIES = ["i2c"] +AUTO_LOAD = ["weikai", "weikai_i2c"] +MULTI_CONF = True + +weikai_i2c_ns = cg.esphome_ns.namespace("weikai_i2c") +WeikaiComponentI2C = weikai_i2c_ns.class_( + "WeikaiComponentI2C", weikai.WeikaiComponent, i2c.I2CDevice +) + +CONFIG_SCHEMA = cv.All( + weikai.WKBASE_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(WeikaiComponentI2C), + } + ).extend(i2c.i2c_device_schema(0x2C)), + weikai.check_channel_max_4, +) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + cg.add(var.set_name(str(config[CONF_ID]))) + await weikai.register_weikai(var, config) + await i2c.register_i2c_device(var, config) diff --git a/esphome/components/wk2204_spi/__init__.py b/esphome/components/wk2204_spi/__init__.py new file mode 100644 index 0000000000..447805375d --- /dev/null +++ b/esphome/components/wk2204_spi/__init__.py @@ -0,0 +1,30 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import spi, weikai +from esphome.const import CONF_ID + +CODEOWNERS = ["@DrCoolZic"] +DEPENDENCIES = ["spi"] +AUTO_LOAD = ["weikai", "weikai_spi"] +MULTI_CONF = True + +weikai_spi_ns = cg.esphome_ns.namespace("weikai_spi") +WeikaiComponentSPI = weikai_spi_ns.class_( + "WeikaiComponentSPI", weikai.WeikaiComponent, spi.SPIDevice +) + +CONFIG_SCHEMA = cv.All( + weikai.WKBASE_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(WeikaiComponentSPI), + } + ).extend(spi.spi_device_schema()), + weikai.check_channel_max_4, +) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + cg.add(var.set_name(str(config[CONF_ID]))) + await weikai.register_weikai(var, config) + await spi.register_spi_device(var, config) diff --git a/esphome/components/wk2212_i2c/__init__.py b/esphome/components/wk2212_i2c/__init__.py new file mode 100644 index 0000000000..fd4d717b31 --- /dev/null +++ b/esphome/components/wk2212_i2c/__init__.py @@ -0,0 +1,64 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome import pins +from esphome.components import i2c, weikai +from esphome.const import ( + CONF_ID, + CONF_INVERTED, + CONF_MODE, + CONF_NUMBER, +) + +CODEOWNERS = ["@DrCoolZic"] +DEPENDENCIES = ["i2c"] +AUTO_LOAD = ["weikai", "weikai_i2c"] +MULTI_CONF = True +CONF_WK2212_I2C = "wk2212_i2c" + +weikai_ns = cg.esphome_ns.namespace("weikai") +weikai_i2c_ns = cg.esphome_ns.namespace("weikai_i2c") +WeikaiComponentI2C = weikai_i2c_ns.class_( + "WeikaiComponentI2C", weikai.WeikaiComponent, i2c.I2CDevice +) +WeikaiGPIOPin = weikai_ns.class_( + "WeikaiGPIOPin", cg.GPIOPin, cg.Parented.template(WeikaiComponentI2C) +) + +CONFIG_SCHEMA = cv.All( + weikai.WKBASE_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(WeikaiComponentI2C), + } + ).extend(i2c.i2c_device_schema(0x2C)), + weikai.check_channel_max_2, +) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + cg.add(var.set_name(str(config[CONF_ID]))) + await weikai.register_weikai(var, config) + await i2c.register_i2c_device(var, config) + + +WK2212_PIN_SCHEMA = cv.All( + weikai.WEIKAI_PIN_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(WeikaiGPIOPin), + cv.Required(CONF_WK2212_I2C): cv.use_id(WeikaiComponentI2C), + } + ), + weikai.validate_pin_mode, +) + + +@pins.PIN_SCHEMA_REGISTRY.register(CONF_WK2212_I2C, WK2212_PIN_SCHEMA) +async def sc16is75x_pin_to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + parent = await cg.get_variable(config[CONF_WK2212_I2C]) + 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/wk2212_spi/__init__.py b/esphome/components/wk2212_spi/__init__.py new file mode 100644 index 0000000000..bfeca87c22 --- /dev/null +++ b/esphome/components/wk2212_spi/__init__.py @@ -0,0 +1,62 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome import pins +from esphome.components import spi, weikai +from esphome.const import ( + CONF_ID, + CONF_INVERTED, + CONF_MODE, + CONF_NUMBER, +) + +CODEOWNERS = ["@DrCoolZic"] +DEPENDENCIES = ["spi"] +AUTO_LOAD = ["weikai", "weikai_spi"] +MULTI_CONF = True +CONF_WK2212_SPI = "wk2212_spi" + +weikai_ns = cg.esphome_ns.namespace("weikai") +weikai_spi_ns = cg.esphome_ns.namespace("weikai_spi") +WeikaiComponentSPI = weikai_spi_ns.class_( + "WeikaiComponentSPI", weikai.WeikaiComponent, spi.SPIDevice +) +WeikaiGPIOPin = weikai_ns.class_( + "WeikaiGPIOPin", cg.GPIOPin, cg.Parented.template(WeikaiComponentSPI) +) + +CONFIG_SCHEMA = cv.All( + weikai.WKBASE_SCHEMA.extend( + {cv.GenerateID(): cv.declare_id(WeikaiComponentSPI)} + ).extend(spi.spi_device_schema()), + weikai.check_channel_max_2, +) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + cg.add(var.set_name(str(config[CONF_ID]))) + await weikai.register_weikai(var, config) + await spi.register_spi_device(var, config) + + +WK2212_PIN_SCHEMA = cv.All( + weikai.WEIKAI_PIN_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(WeikaiGPIOPin), + cv.Required(CONF_WK2212_SPI): cv.use_id(WeikaiComponentSPI), + }, + ), + weikai.validate_pin_mode, +) + + +@pins.PIN_SCHEMA_REGISTRY.register(CONF_WK2212_SPI, WK2212_PIN_SCHEMA) +async def sc16is75x_pin_to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + parent = await cg.get_variable(config[CONF_WK2212_SPI]) + 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/tests/components/wk2132_i2c/common.yaml b/tests/components/wk2132_i2c/common.yaml new file mode 100644 index 0000000000..f9c8ab756d --- /dev/null +++ b/tests/components/wk2132_i2c/common.yaml @@ -0,0 +1,20 @@ +i2c: + id: i2c_bus + scl: ${scl_pin} + sda: ${sda_pin} + scan: true + frequency: 600kHz + +wk2132_i2c: + - id: wk2132_i2c_id + address: 0x70 + i2c_id: i2c_bus + uart: + - id: wk2132_id_0 + channel: 0 + baud_rate: 115200 + stop_bits: 1 + parity: none + - id: wk2132_id_1 + channel: 1 + baud_rate: 19200 diff --git a/tests/components/wk2132_i2c/test.esp32-idf.yaml b/tests/components/wk2132_i2c/test.esp32-idf.yaml new file mode 100644 index 0000000000..3b761d3fc1 --- /dev/null +++ b/tests/components/wk2132_i2c/test.esp32-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO22 + sda_pin: GPIO21 + +<<: !include common.yaml diff --git a/tests/components/wk2132_i2c/test.esp32-s3-idf.yaml b/tests/components/wk2132_i2c/test.esp32-s3-idf.yaml new file mode 100644 index 0000000000..4942e3c2b3 --- /dev/null +++ b/tests/components/wk2132_i2c/test.esp32-s3-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO40 + sda_pin: GPIO41 + +<<: !include common.yaml diff --git a/tests/components/wk2132_i2c/test.esp32-s3.yaml b/tests/components/wk2132_i2c/test.esp32-s3.yaml new file mode 100644 index 0000000000..4942e3c2b3 --- /dev/null +++ b/tests/components/wk2132_i2c/test.esp32-s3.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO40 + sda_pin: GPIO41 + +<<: !include common.yaml diff --git a/tests/components/wk2132_i2c/test.esp32.yaml b/tests/components/wk2132_i2c/test.esp32.yaml new file mode 100644 index 0000000000..3b761d3fc1 --- /dev/null +++ b/tests/components/wk2132_i2c/test.esp32.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO22 + sda_pin: GPIO21 + +<<: !include common.yaml diff --git a/tests/components/wk2132_spi/common.yaml b/tests/components/wk2132_spi/common.yaml new file mode 100644 index 0000000000..b21e89120c --- /dev/null +++ b/tests/components/wk2132_spi/common.yaml @@ -0,0 +1,21 @@ +spi: + id: spi_bus + clk_pin: ${clk_pin} + mosi_pin: ${mosi_pin} + miso_pin: ${miso_pin} + +wk2132_spi: + - id: wk2132_spi_id + cs_pin: ${cs_pin} + spi_id: spi_bus + crystal: 11059200 + data_rate: 1MHz + uart: + - id: wk2132_spi_id0 + channel: 0 + baud_rate: 115200 + stop_bits: 1 + parity: none + - id: wk2132_spi_id1 + channel: 1 + baud_rate: 921600 diff --git a/tests/components/wk2132_spi/test.esp32-idf.yaml b/tests/components/wk2132_spi/test.esp32-idf.yaml new file mode 100644 index 0000000000..76e7138ab0 --- /dev/null +++ b/tests/components/wk2132_spi/test.esp32-idf.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO18 + miso_pin: GPIO19 + mosi_pin: GPIO23 + cs_pin: GPIO5 + +<<: !include common.yaml diff --git a/tests/components/wk2132_spi/test.esp32-s3-idf.yaml b/tests/components/wk2132_spi/test.esp32-s3-idf.yaml new file mode 100644 index 0000000000..b0aadf620a --- /dev/null +++ b/tests/components/wk2132_spi/test.esp32-s3-idf.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO40 + miso_pin: GPIO41 + mosi_pin: GPIO6 + cs_pin: GPIO19 + +<<: !include common.yaml diff --git a/tests/components/wk2132_spi/test.esp32-s3.yaml b/tests/components/wk2132_spi/test.esp32-s3.yaml new file mode 100644 index 0000000000..b0aadf620a --- /dev/null +++ b/tests/components/wk2132_spi/test.esp32-s3.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO40 + miso_pin: GPIO41 + mosi_pin: GPIO6 + cs_pin: GPIO19 + +<<: !include common.yaml diff --git a/tests/components/wk2132_spi/test.esp32.yaml b/tests/components/wk2132_spi/test.esp32.yaml new file mode 100644 index 0000000000..76e7138ab0 --- /dev/null +++ b/tests/components/wk2132_spi/test.esp32.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO18 + miso_pin: GPIO19 + mosi_pin: GPIO23 + cs_pin: GPIO5 + +<<: !include common.yaml diff --git a/tests/components/wk2168_i2c/common.yaml b/tests/components/wk2168_i2c/common.yaml new file mode 100644 index 0000000000..fe4689d6db --- /dev/null +++ b/tests/components/wk2168_i2c/common.yaml @@ -0,0 +1,63 @@ +i2c: + id: i2c_bus + scl: ${scl_pin} + sda: ${sda_pin} + scan: true + frequency: 600kHz + +# component declaration +wk2168_i2c: + - id: bridge_i2c + i2c_id: i2c_bus + address: 0x70 + uart: + - id: id0 + channel: 0 + baud_rate: 115200 + stop_bits: 1 + parity: none + - id: id1 + channel: 1 + baud_rate: 115200 + - id: id2 + channel: 2 + baud_rate: 115200 + - id: id3 + channel: 3 + baud_rate: 115200 + +# individual binary_sensor inputs +binary_sensor: + - platform: gpio + name: "pin_0" + pin: + wk2168_i2c: bridge_i2c + number: 0 + mode: + input: true + - platform: gpio + name: "pin_1" + pin: + wk2168_i2c: bridge_i2c + number: 1 + mode: + input: true + inverted: true + +# Individual binary outputs +switch: + - platform: gpio + name: "pin_2" + pin: + wk2168_i2c: bridge_i2c + number: 2 + mode: + output: true + - platform: gpio + name: "pin_3" + pin: + wk2168_i2c: bridge_i2c + number: 3 + mode: + output: true + inverted: true diff --git a/tests/components/wk2168_i2c/test.esp32-idf.yaml b/tests/components/wk2168_i2c/test.esp32-idf.yaml new file mode 100644 index 0000000000..3b761d3fc1 --- /dev/null +++ b/tests/components/wk2168_i2c/test.esp32-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO22 + sda_pin: GPIO21 + +<<: !include common.yaml diff --git a/tests/components/wk2168_i2c/test.esp32-s3-idf.yaml b/tests/components/wk2168_i2c/test.esp32-s3-idf.yaml new file mode 100644 index 0000000000..4942e3c2b3 --- /dev/null +++ b/tests/components/wk2168_i2c/test.esp32-s3-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO40 + sda_pin: GPIO41 + +<<: !include common.yaml diff --git a/tests/components/wk2168_i2c/test.esp32-s3.yaml b/tests/components/wk2168_i2c/test.esp32-s3.yaml new file mode 100644 index 0000000000..4942e3c2b3 --- /dev/null +++ b/tests/components/wk2168_i2c/test.esp32-s3.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO40 + sda_pin: GPIO41 + +<<: !include common.yaml diff --git a/tests/components/wk2168_i2c/test.esp32.yaml b/tests/components/wk2168_i2c/test.esp32.yaml new file mode 100644 index 0000000000..3b761d3fc1 --- /dev/null +++ b/tests/components/wk2168_i2c/test.esp32.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO22 + sda_pin: GPIO21 + +<<: !include common.yaml diff --git a/tests/components/wk2168_spi/common.yaml b/tests/components/wk2168_spi/common.yaml new file mode 100644 index 0000000000..7626e18df6 --- /dev/null +++ b/tests/components/wk2168_spi/common.yaml @@ -0,0 +1,63 @@ +spi: + id: spi_bus + clk_pin: ${clk_pin} + mosi_pin: ${mosi_pin} + miso_pin: ${miso_pin} + +wk2168_spi: + - id: bridge_spi + cs_pin: ${cs_pin} + spi_id: spi_bus + crystal: 11059200 + data_rate: 1MHz + uart: + - id: id0 + channel: 0 + baud_rate: 115200 + stop_bits: 1 + parity: none + - id: id1 + channel: 1 + baud_rate: 115200 + - id: id2 + channel: 2 + baud_rate: 115200 + - id: id3 + channel: 3 + baud_rate: 115200 + +# individual binary_sensor inputs +binary_sensor: + - platform: gpio + name: "pin_0" + pin: + wk2168_spi: bridge_spi + number: 0 + mode: + input: true + - platform: gpio + name: "pin_1" + pin: + wk2168_spi: bridge_spi + number: 1 + mode: + input: true + inverted: true + +# Individual binary outputs +switch: + - platform: gpio + name: "pin_2" + pin: + wk2168_spi: bridge_spi + number: 2 + mode: + output: true + - platform: gpio + name: "pin_3" + pin: + wk2168_spi: bridge_spi + number: 3 + mode: + output: true + inverted: true diff --git a/tests/components/wk2168_spi/test.esp32-idf.yaml b/tests/components/wk2168_spi/test.esp32-idf.yaml new file mode 100644 index 0000000000..76e7138ab0 --- /dev/null +++ b/tests/components/wk2168_spi/test.esp32-idf.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO18 + miso_pin: GPIO19 + mosi_pin: GPIO23 + cs_pin: GPIO5 + +<<: !include common.yaml diff --git a/tests/components/wk2168_spi/test.esp32-s3-idf.yaml b/tests/components/wk2168_spi/test.esp32-s3-idf.yaml new file mode 100644 index 0000000000..b0aadf620a --- /dev/null +++ b/tests/components/wk2168_spi/test.esp32-s3-idf.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO40 + miso_pin: GPIO41 + mosi_pin: GPIO6 + cs_pin: GPIO19 + +<<: !include common.yaml diff --git a/tests/components/wk2168_spi/test.esp32-s3.yaml b/tests/components/wk2168_spi/test.esp32-s3.yaml new file mode 100644 index 0000000000..b0aadf620a --- /dev/null +++ b/tests/components/wk2168_spi/test.esp32-s3.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO40 + miso_pin: GPIO41 + mosi_pin: GPIO6 + cs_pin: GPIO19 + +<<: !include common.yaml diff --git a/tests/components/wk2168_spi/test.esp32.yaml b/tests/components/wk2168_spi/test.esp32.yaml new file mode 100644 index 0000000000..76e7138ab0 --- /dev/null +++ b/tests/components/wk2168_spi/test.esp32.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO18 + miso_pin: GPIO19 + mosi_pin: GPIO23 + cs_pin: GPIO5 + +<<: !include common.yaml diff --git a/tests/components/wk2204_i2c/common.yaml b/tests/components/wk2204_i2c/common.yaml new file mode 100644 index 0000000000..80f636c690 --- /dev/null +++ b/tests/components/wk2204_i2c/common.yaml @@ -0,0 +1,28 @@ +i2c: + id: i2c_bus + scl: ${scl_pin} + sda: ${sda_pin} + scan: true + frequency: 600kHz + +wk2204_i2c: + - id: wk2204_i2c_id + i2c_id: i2c_bus + address: 0x70 + uart: + - id: wk2204_id_0 + channel: 0 + baud_rate: 115200 + stop_bits: 1 + parity: none + - id: wk2204_id_1 + channel: 1 + baud_rate: 19200 + - id: wk2204_id_2 + channel: 2 + baud_rate: 115200 + stop_bits: 1 + parity: none + - id: wk2204_id_3 + channel: 3 + baud_rate: 19200 diff --git a/tests/components/wk2204_i2c/test.esp32-idf.yaml b/tests/components/wk2204_i2c/test.esp32-idf.yaml new file mode 100644 index 0000000000..3b761d3fc1 --- /dev/null +++ b/tests/components/wk2204_i2c/test.esp32-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO22 + sda_pin: GPIO21 + +<<: !include common.yaml diff --git a/tests/components/wk2204_i2c/test.esp32-s3-idf.yaml b/tests/components/wk2204_i2c/test.esp32-s3-idf.yaml new file mode 100644 index 0000000000..4942e3c2b3 --- /dev/null +++ b/tests/components/wk2204_i2c/test.esp32-s3-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO40 + sda_pin: GPIO41 + +<<: !include common.yaml diff --git a/tests/components/wk2204_i2c/test.esp32-s3.yaml b/tests/components/wk2204_i2c/test.esp32-s3.yaml new file mode 100644 index 0000000000..4942e3c2b3 --- /dev/null +++ b/tests/components/wk2204_i2c/test.esp32-s3.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO40 + sda_pin: GPIO41 + +<<: !include common.yaml diff --git a/tests/components/wk2204_i2c/test.esp32.yaml b/tests/components/wk2204_i2c/test.esp32.yaml new file mode 100644 index 0000000000..3b761d3fc1 --- /dev/null +++ b/tests/components/wk2204_i2c/test.esp32.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO22 + sda_pin: GPIO21 + +<<: !include common.yaml diff --git a/tests/components/wk2204_spi/common.yaml b/tests/components/wk2204_spi/common.yaml new file mode 100644 index 0000000000..3bae9c9a6d --- /dev/null +++ b/tests/components/wk2204_spi/common.yaml @@ -0,0 +1,29 @@ +spi: + id: spi_bus + clk_pin: ${clk_pin} + mosi_pin: ${mosi_pin} + miso_pin: ${miso_pin} + +wk2204_spi: + - id: wk2204_spi_id + cs_pin: ${cs_pin} + spi_id: spi_bus + crystal: 11059200 + data_rate: 1MHz + uart: + - id: wk2204_spi_id0 + channel: 0 + baud_rate: 115200 + stop_bits: 1 + parity: none + - id: wk2204_spi_id1 + channel: 1 + baud_rate: 921600 + - id: wk2204_spi_id2 + channel: 2 + baud_rate: 115200 + stop_bits: 1 + parity: none + - id: wk2204_spi_id3 + channel: 3 + baud_rate: 921600 diff --git a/tests/components/wk2204_spi/test.esp32-idf.yaml b/tests/components/wk2204_spi/test.esp32-idf.yaml new file mode 100644 index 0000000000..76e7138ab0 --- /dev/null +++ b/tests/components/wk2204_spi/test.esp32-idf.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO18 + miso_pin: GPIO19 + mosi_pin: GPIO23 + cs_pin: GPIO5 + +<<: !include common.yaml diff --git a/tests/components/wk2204_spi/test.esp32-s3-idf.yaml b/tests/components/wk2204_spi/test.esp32-s3-idf.yaml new file mode 100644 index 0000000000..b0aadf620a --- /dev/null +++ b/tests/components/wk2204_spi/test.esp32-s3-idf.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO40 + miso_pin: GPIO41 + mosi_pin: GPIO6 + cs_pin: GPIO19 + +<<: !include common.yaml diff --git a/tests/components/wk2204_spi/test.esp32-s3.yaml b/tests/components/wk2204_spi/test.esp32-s3.yaml new file mode 100644 index 0000000000..b0aadf620a --- /dev/null +++ b/tests/components/wk2204_spi/test.esp32-s3.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO40 + miso_pin: GPIO41 + mosi_pin: GPIO6 + cs_pin: GPIO19 + +<<: !include common.yaml diff --git a/tests/components/wk2204_spi/test.esp32.yaml b/tests/components/wk2204_spi/test.esp32.yaml new file mode 100644 index 0000000000..76e7138ab0 --- /dev/null +++ b/tests/components/wk2204_spi/test.esp32.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO18 + miso_pin: GPIO19 + mosi_pin: GPIO23 + cs_pin: GPIO5 + +<<: !include common.yaml diff --git a/tests/components/wk2212_i2c/common.yaml b/tests/components/wk2212_i2c/common.yaml new file mode 100644 index 0000000000..2e891c5520 --- /dev/null +++ b/tests/components/wk2212_i2c/common.yaml @@ -0,0 +1,59 @@ +i2c: + id: i2c_bus + scl: ${scl_pin} + sda: ${sda_pin} + scan: true + frequency: 600kHz + +# component declaration +wk2212_i2c: + - id: bridge_i2c + i2c_id: i2c_bus + address: 0x70 + uart: + - id: uart_i2c_id0 + channel: 0 + baud_rate: 115200 + stop_bits: 1 + parity: none + - id: uart_i2c_id1 + channel: 1 + baud_rate: 115200 + stop_bits: 1 + parity: none + +# individual binary_sensor inputs +binary_sensor: + - platform: gpio + name: "pin_0" + pin: + wk2212_i2c: bridge_i2c + number: 0 + mode: + input: true + - platform: gpio + name: "pin_1" + pin: + wk2212_i2c: bridge_i2c + number: 1 + mode: + input: true + inverted: true + +# Individual binary outputs +switch: + - platform: gpio + name: "pin_2" + pin: + wk2212_i2c: bridge_i2c + number: 2 + mode: + output: true + - platform: gpio + name: "pin_3" + pin: + wk2212_i2c: bridge_i2c + number: 3 + mode: + output: true + inverted: true diff --git a/tests/components/wk2212_i2c/test.esp32-idf.yaml b/tests/components/wk2212_i2c/test.esp32-idf.yaml new file mode 100644 index 0000000000..3b761d3fc1 --- /dev/null +++ b/tests/components/wk2212_i2c/test.esp32-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO22 + sda_pin: GPIO21 + +<<: !include common.yaml diff --git a/tests/components/wk2212_i2c/test.esp32-s3-idf.yaml b/tests/components/wk2212_i2c/test.esp32-s3-idf.yaml new file mode 100644 index 0000000000..4942e3c2b3 --- /dev/null +++ b/tests/components/wk2212_i2c/test.esp32-s3-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO40 + sda_pin: GPIO41 + +<<: !include common.yaml diff --git a/tests/components/wk2212_i2c/test.esp32-s3.yaml b/tests/components/wk2212_i2c/test.esp32-s3.yaml new file mode 100644 index 0000000000..4942e3c2b3 --- /dev/null +++ b/tests/components/wk2212_i2c/test.esp32-s3.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO40 + sda_pin: GPIO41 + +<<: !include common.yaml diff --git a/tests/components/wk2212_i2c/test.esp32.yaml b/tests/components/wk2212_i2c/test.esp32.yaml new file mode 100644 index 0000000000..3b761d3fc1 --- /dev/null +++ b/tests/components/wk2212_i2c/test.esp32.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO22 + sda_pin: GPIO21 + +<<: !include common.yaml diff --git a/tests/components/wk2212_spi/common.yaml b/tests/components/wk2212_spi/common.yaml new file mode 100644 index 0000000000..ad9f11d9e8 --- /dev/null +++ b/tests/components/wk2212_spi/common.yaml @@ -0,0 +1,58 @@ +spi: + id: spi_bus + clk_pin: ${clk_pin} + mosi_pin: ${mosi_pin} + miso_pin: ${miso_pin} + +wk2212_spi: + - id: bridge_spi + cs_pin: ${cs_pin} + spi_id: spi_bus + crystal: 11059200 + data_rate: 1MHz + uart: + - id: id0 + channel: 0 + baud_rate: 115200 + stop_bits: 1 + parity: none + - id: id1 + channel: 1 + baud_rate: 115200 + +# individual binary_sensor inputs +binary_sensor: + - platform: gpio + name: "pin_0" + pin: + wk2212_spi: bridge_spi + number: 0 + mode: + input: true + - platform: gpio + name: "pin_1" + pin: + wk2212_spi: bridge_spi + number: 1 + mode: + input: true + inverted: true + +# Individual binary outputs +switch: + - platform: gpio + name: "pin_2" + pin: + wk2212_spi: bridge_spi + number: 2 + mode: + output: true + - platform: gpio + name: "pin_3" + pin: + wk2212_spi: bridge_spi + number: 3 + mode: + output: true + inverted: true + diff --git a/tests/components/wk2212_spi/test.esp32-idf.yaml b/tests/components/wk2212_spi/test.esp32-idf.yaml new file mode 100644 index 0000000000..76e7138ab0 --- /dev/null +++ b/tests/components/wk2212_spi/test.esp32-idf.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO18 + miso_pin: GPIO19 + mosi_pin: GPIO23 + cs_pin: GPIO5 + +<<: !include common.yaml diff --git a/tests/components/wk2212_spi/test.esp32-s3-idf.yaml b/tests/components/wk2212_spi/test.esp32-s3-idf.yaml new file mode 100644 index 0000000000..b0aadf620a --- /dev/null +++ b/tests/components/wk2212_spi/test.esp32-s3-idf.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO40 + miso_pin: GPIO41 + mosi_pin: GPIO6 + cs_pin: GPIO19 + +<<: !include common.yaml diff --git a/tests/components/wk2212_spi/test.esp32-s3.yaml b/tests/components/wk2212_spi/test.esp32-s3.yaml new file mode 100644 index 0000000000..b0aadf620a --- /dev/null +++ b/tests/components/wk2212_spi/test.esp32-s3.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO40 + miso_pin: GPIO41 + mosi_pin: GPIO6 + cs_pin: GPIO19 + +<<: !include common.yaml diff --git a/tests/components/wk2212_spi/test.esp32.yaml b/tests/components/wk2212_spi/test.esp32.yaml new file mode 100644 index 0000000000..76e7138ab0 --- /dev/null +++ b/tests/components/wk2212_spi/test.esp32.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO18 + miso_pin: GPIO19 + mosi_pin: GPIO23 + cs_pin: GPIO5 + +<<: !include common.yaml From 217988fd9937b44257794bd10ab304c72039903f Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 24 Apr 2024 13:49:08 +1200 Subject: [PATCH 1319/2101] Sort mqtt_const alphabetically (#6619) --- esphome/components/mqtt/mqtt_const.h | 257 +++++++++++++-------------- 1 file changed, 128 insertions(+), 129 deletions(-) diff --git a/esphome/components/mqtt/mqtt_const.h b/esphome/components/mqtt/mqtt_const.h index 3d9e0b4c00..2209f96e7a 100644 --- a/esphome/components/mqtt/mqtt_const.h +++ b/esphome/components/mqtt/mqtt_const.h @@ -9,8 +9,8 @@ namespace mqtt { #ifdef USE_MQTT_ABBREVIATIONS -constexpr const char *const MQTT_ACTION_TOPIC = "act_t"; constexpr const char *const MQTT_ACTION_TEMPLATE = "act_tpl"; +constexpr const char *const MQTT_ACTION_TOPIC = "act_t"; constexpr const char *const MQTT_AUTOMATION_TYPE = "atype"; constexpr const char *const MQTT_AUX_COMMAND_TOPIC = "aux_cmd_t"; constexpr const char *const MQTT_AUX_STATE_TEMPLATE = "aux_stat_tpl"; @@ -21,60 +21,68 @@ constexpr const char *const MQTT_AVAILABILITY_TOPIC = "avty_t"; constexpr const char *const MQTT_AWAY_MODE_COMMAND_TOPIC = "away_mode_cmd_t"; constexpr const char *const MQTT_AWAY_MODE_STATE_TEMPLATE = "away_mode_stat_tpl"; constexpr const char *const MQTT_AWAY_MODE_STATE_TOPIC = "away_mode_stat_t"; +constexpr const char *const MQTT_BATTERY_LEVEL_TEMPLATE = "bat_lev_tpl"; +constexpr const char *const MQTT_BATTERY_LEVEL_TOPIC = "bat_lev_t"; constexpr const char *const MQTT_BLUE_TEMPLATE = "b_tpl"; constexpr const char *const MQTT_BRIGHTNESS_COMMAND_TOPIC = "bri_cmd_t"; constexpr const char *const MQTT_BRIGHTNESS_SCALE = "bri_scl"; constexpr const char *const MQTT_BRIGHTNESS_STATE_TOPIC = "bri_stat_t"; constexpr const char *const MQTT_BRIGHTNESS_TEMPLATE = "bri_tpl"; constexpr const char *const MQTT_BRIGHTNESS_VALUE_TEMPLATE = "bri_val_tpl"; -constexpr const char *const MQTT_COLOR_TEMP_COMMAND_TEMPLATE = "clr_temp_cmd_tpl"; -constexpr const char *const MQTT_BATTERY_LEVEL_TOPIC = "bat_lev_t"; -constexpr const char *const MQTT_BATTERY_LEVEL_TEMPLATE = "bat_lev_tpl"; -constexpr const char *const MQTT_CONFIGURATION_URL = "cu"; -constexpr const char *const MQTT_CHARGING_TOPIC = "chrg_t"; constexpr const char *const MQTT_CHARGING_TEMPLATE = "chrg_tpl"; +constexpr const char *const MQTT_CHARGING_TOPIC = "chrg_t"; +constexpr const char *const MQTT_CLEANING_TEMPLATE = "cln_tpl"; +constexpr const char *const MQTT_CLEANING_TOPIC = "cln_t"; +constexpr const char *const MQTT_CODE_ARM_REQUIRED = "cod_arm_req"; +constexpr const char *const MQTT_CODE_DISARM_REQUIRED = "cod_dis_req"; constexpr const char *const MQTT_COLOR_MODE = "clrm"; constexpr const char *const MQTT_COLOR_MODE_STATE_TOPIC = "clrm_stat_t"; constexpr const char *const MQTT_COLOR_MODE_VALUE_TEMPLATE = "clrm_val_tpl"; +constexpr const char *const MQTT_COLOR_TEMP_COMMAND_TEMPLATE = "clr_temp_cmd_tpl"; constexpr const char *const MQTT_COLOR_TEMP_COMMAND_TOPIC = "clr_temp_cmd_t"; constexpr const char *const MQTT_COLOR_TEMP_STATE_TOPIC = "clr_temp_stat_t"; constexpr const char *const MQTT_COLOR_TEMP_TEMPLATE = "clr_temp_tpl"; constexpr const char *const MQTT_COLOR_TEMP_VALUE_TEMPLATE = "clr_temp_val_tpl"; -constexpr const char *const MQTT_CLEANING_TOPIC = "cln_t"; -constexpr const char *const MQTT_CLEANING_TEMPLATE = "cln_tpl"; constexpr const char *const MQTT_COMMAND_OFF_TEMPLATE = "cmd_off_tpl"; constexpr const char *const MQTT_COMMAND_ON_TEMPLATE = "cmd_on_tpl"; -constexpr const char *const MQTT_COMMAND_TOPIC = "cmd_t"; constexpr const char *const MQTT_COMMAND_RETAIN = "ret"; constexpr const char *const MQTT_COMMAND_TEMPLATE = "cmd_tpl"; -constexpr const char *const MQTT_CODE_ARM_REQUIRED = "cod_arm_req"; -constexpr const char *const MQTT_CODE_DISARM_REQUIRED = "cod_dis_req"; -constexpr const char *const MQTT_CURRENT_TEMPERATURE_TOPIC = "curr_temp_t"; -constexpr const char *const MQTT_CURRENT_TEMPERATURE_TEMPLATE = "curr_temp_tpl"; -constexpr const char *const MQTT_CURRENT_HUMIDITY_TOPIC = "curr_hum_t"; +constexpr const char *const MQTT_COMMAND_TOPIC = "cmd_t"; +constexpr const char *const MQTT_CONFIGURATION_URL = "cu"; constexpr const char *const MQTT_CURRENT_HUMIDITY_TEMPLATE = "curr_hum_tpl"; +constexpr const char *const MQTT_CURRENT_HUMIDITY_TOPIC = "curr_hum_t"; +constexpr const char *const MQTT_CURRENT_TEMPERATURE_TEMPLATE = "curr_temp_tpl"; +constexpr const char *const MQTT_CURRENT_TEMPERATURE_TOPIC = "curr_temp_t"; constexpr const char *const MQTT_DEVICE = "dev"; constexpr const char *const MQTT_DEVICE_CLASS = "dev_cla"; -constexpr const char *const MQTT_DOCKED_TOPIC = "dock_t"; +constexpr const char *const MQTT_DEVICE_CONNECTIONS = "cns"; +constexpr const char *const MQTT_DEVICE_IDENTIFIERS = "ids"; +constexpr const char *const MQTT_DEVICE_MANUFACTURER = "mf"; +constexpr const char *const MQTT_DEVICE_MODEL = "mdl"; +constexpr const char *const MQTT_DEVICE_NAME = "name"; +constexpr const char *const MQTT_DEVICE_SUGGESTED_AREA = "sa"; +constexpr const char *const MQTT_DEVICE_SW_VERSION = "sw"; constexpr const char *const MQTT_DOCKED_TEMPLATE = "dock_tpl"; -constexpr const char *const MQTT_ENABLED_BY_DEFAULT = "en"; -constexpr const char *const MQTT_ERROR_TOPIC = "err_t"; -constexpr const char *const MQTT_ERROR_TEMPLATE = "err_tpl"; -constexpr const char *const MQTT_FAN_SPEED_TOPIC = "fanspd_t"; -constexpr const char *const MQTT_FAN_SPEED_TEMPLATE = "fanspd_tpl"; -constexpr const char *const MQTT_FAN_SPEED_LIST = "fanspd_lst"; -constexpr const char *const MQTT_FLASH_TIME_LONG = "flsh_tlng"; -constexpr const char *const MQTT_FLASH_TIME_SHORT = "flsh_tsht"; +constexpr const char *const MQTT_DOCKED_TOPIC = "dock_t"; constexpr const char *const MQTT_EFFECT_COMMAND_TOPIC = "fx_cmd_t"; constexpr const char *const MQTT_EFFECT_LIST = "fx_list"; constexpr const char *const MQTT_EFFECT_STATE_TOPIC = "fx_stat_t"; constexpr const char *const MQTT_EFFECT_TEMPLATE = "fx_tpl"; constexpr const char *const MQTT_EFFECT_VALUE_TEMPLATE = "fx_val_tpl"; +constexpr const char *const MQTT_ENABLED_BY_DEFAULT = "en"; +constexpr const char *const MQTT_ENTITY_CATEGORY = "ent_cat"; +constexpr const char *const MQTT_ERROR_TEMPLATE = "err_tpl"; +constexpr const char *const MQTT_ERROR_TOPIC = "err_t"; constexpr const char *const MQTT_EXPIRE_AFTER = "exp_aft"; constexpr const char *const MQTT_FAN_MODE_COMMAND_TEMPLATE = "fan_mode_cmd_tpl"; constexpr const char *const MQTT_FAN_MODE_COMMAND_TOPIC = "fan_mode_cmd_t"; constexpr const char *const MQTT_FAN_MODE_STATE_TEMPLATE = "fan_mode_stat_tpl"; constexpr const char *const MQTT_FAN_MODE_STATE_TOPIC = "fan_mode_stat_t"; +constexpr const char *const MQTT_FAN_SPEED_LIST = "fanspd_lst"; +constexpr const char *const MQTT_FAN_SPEED_TEMPLATE = "fanspd_tpl"; +constexpr const char *const MQTT_FAN_SPEED_TOPIC = "fanspd_t"; +constexpr const char *const MQTT_FLASH_TIME_LONG = "flsh_tlng"; +constexpr const char *const MQTT_FLASH_TIME_SHORT = "flsh_tsht"; constexpr const char *const MQTT_FORCE_UPDATE = "frc_upd"; constexpr const char *const MQTT_GREEN_TEMPLATE = "g_tpl"; constexpr const char *const MQTT_HOLD_COMMAND_TEMPLATE = "hold_cmd_tpl"; @@ -86,56 +94,49 @@ constexpr const char *const MQTT_HS_STATE_TOPIC = "hs_stat_t"; constexpr const char *const MQTT_HS_VALUE_TEMPLATE = "hs_val_tpl"; constexpr const char *const MQTT_ICON = "ic"; constexpr const char *const MQTT_INITIAL = "init"; -constexpr const char *const MQTT_TARGET_HUMIDITY_COMMAND_TOPIC = "hum_cmd_t"; -constexpr const char *const MQTT_TARGET_HUMIDITY_COMMAND_TEMPLATE = "hum_cmd_tpl"; -constexpr const char *const MQTT_TARGET_HUMIDITY_STATE_TOPIC = "hum_stat_t"; -constexpr const char *const MQTT_TARGET_HUMIDITY_STATE_TEMPLATE = "hum_state_tpl"; constexpr const char *const MQTT_JSON_ATTRIBUTES = "json_attr"; -constexpr const char *const MQTT_JSON_ATTRIBUTES_TOPIC = "json_attr_t"; constexpr const char *const MQTT_JSON_ATTRIBUTES_TEMPLATE = "json_attr_tpl"; +constexpr const char *const MQTT_JSON_ATTRIBUTES_TOPIC = "json_attr_t"; constexpr const char *const MQTT_LAST_RESET_TOPIC = "lrst_t"; constexpr const char *const MQTT_LAST_RESET_VALUE_TEMPLATE = "lrst_val_tpl"; constexpr const char *const MQTT_MAX = "max"; -constexpr const char *const MQTT_MIN = "min"; constexpr const char *const MQTT_MAX_HUMIDITY = "max_hum"; -constexpr const char *const MQTT_MIN_HUMIDITY = "min_hum"; constexpr const char *const MQTT_MAX_MIREDS = "max_mirs"; -constexpr const char *const MQTT_MIN_MIREDS = "min_mirs"; constexpr const char *const MQTT_MAX_TEMP = "max_temp"; +constexpr const char *const MQTT_MIN = "min"; +constexpr const char *const MQTT_MIN_HUMIDITY = "min_hum"; +constexpr const char *const MQTT_MIN_MIREDS = "min_mirs"; constexpr const char *const MQTT_MIN_TEMP = "min_temp"; +constexpr const char *const MQTT_MODE = "mode"; constexpr const char *const MQTT_MODE_COMMAND_TEMPLATE = "mode_cmd_tpl"; constexpr const char *const MQTT_MODE_COMMAND_TOPIC = "mode_cmd_t"; -constexpr const char *const MQTT_MODE_STATE_TOPIC = "mode_stat_t"; constexpr const char *const MQTT_MODE_STATE_TEMPLATE = "mode_stat_tpl"; +constexpr const char *const MQTT_MODE_STATE_TOPIC = "mode_stat_t"; constexpr const char *const MQTT_MODES = "modes"; constexpr const char *const MQTT_NAME = "name"; constexpr const char *const MQTT_OBJECT_ID = "obj_id"; constexpr const char *const MQTT_OFF_DELAY = "off_dly"; constexpr const char *const MQTT_ON_COMMAND_TYPE = "on_cmd_type"; -constexpr const char *const MQTT_OPTIONS = "ops"; constexpr const char *const MQTT_OPTIMISTIC = "opt"; -constexpr const char *const MQTT_OSCILLATION_COMMAND_TOPIC = "osc_cmd_t"; +constexpr const char *const MQTT_OPTIONS = "ops"; constexpr const char *const MQTT_OSCILLATION_COMMAND_TEMPLATE = "osc_cmd_tpl"; +constexpr const char *const MQTT_OSCILLATION_COMMAND_TOPIC = "osc_cmd_t"; constexpr const char *const MQTT_OSCILLATION_STATE_TOPIC = "osc_stat_t"; constexpr const char *const MQTT_OSCILLATION_VALUE_TEMPLATE = "osc_val_tpl"; -constexpr const char *const MQTT_PERCENTAGE_COMMAND_TOPIC = "pct_cmd_t"; -constexpr const char *const MQTT_PERCENTAGE_COMMAND_TEMPLATE = "pct_cmd_tpl"; -constexpr const char *const MQTT_PERCENTAGE_STATE_TOPIC = "pct_stat_t"; -constexpr const char *const MQTT_PERCENTAGE_VALUE_TEMPLATE = "pct_val_tpl"; constexpr const char *const MQTT_PAYLOAD = "pl"; constexpr const char *const MQTT_PAYLOAD_ARM_AWAY = "pl_arm_away"; +constexpr const char *const MQTT_PAYLOAD_ARM_CUSTOM_BYPASS = "pl_arm_custom_b"; constexpr const char *const MQTT_PAYLOAD_ARM_HOME = "pl_arm_home"; constexpr const char *const MQTT_PAYLOAD_ARM_NIGHT = "pl_arm_nite"; constexpr const char *const MQTT_PAYLOAD_ARM_VACATION = "pl_arm_vacation"; -constexpr const char *const MQTT_PAYLOAD_ARM_CUSTOM_BYPASS = "pl_arm_custom_b"; constexpr const char *const MQTT_PAYLOAD_AVAILABLE = "pl_avail"; constexpr const char *const MQTT_PAYLOAD_CLEAN_SPOT = "pl_cln_sp"; constexpr const char *const MQTT_PAYLOAD_CLOSE = "pl_cls"; constexpr const char *const MQTT_PAYLOAD_DISARM = "pl_disarm"; constexpr const char *const MQTT_PAYLOAD_HIGH_SPEED = "pl_hi_spd"; constexpr const char *const MQTT_PAYLOAD_HOME = "pl_home"; -constexpr const char *const MQTT_PAYLOAD_LOCK = "pl_lock"; constexpr const char *const MQTT_PAYLOAD_LOCATE = "pl_loc"; +constexpr const char *const MQTT_PAYLOAD_LOCK = "pl_lock"; constexpr const char *const MQTT_PAYLOAD_LOW_SPEED = "pl_lo_spd"; constexpr const char *const MQTT_PAYLOAD_MEDIUM_SPEED = "pl_med_spd"; constexpr const char *const MQTT_PAYLOAD_NOT_AVAILABLE = "pl_not_avail"; @@ -152,20 +153,26 @@ constexpr const char *const MQTT_PAYLOAD_RESET_HUMIDITY = "pl_rst_hum"; constexpr const char *const MQTT_PAYLOAD_RESET_MODE = "pl_rst_mode"; constexpr const char *const MQTT_PAYLOAD_RESET_PERCENTAGE = "pl_rst_pct"; constexpr const char *const MQTT_PAYLOAD_RESET_PRESET_MODE = "pl_rst_pr_mode"; -constexpr const char *const MQTT_PAYLOAD_STOP = "pl_stop"; +constexpr const char *const MQTT_PAYLOAD_RETURN_TO_BASE = "pl_ret"; constexpr const char *const MQTT_PAYLOAD_START = "pl_strt"; constexpr const char *const MQTT_PAYLOAD_START_PAUSE = "pl_stpa"; -constexpr const char *const MQTT_PAYLOAD_RETURN_TO_BASE = "pl_ret"; +constexpr const char *const MQTT_PAYLOAD_STOP = "pl_stop"; constexpr const char *const MQTT_PAYLOAD_TURN_OFF = "pl_toff"; constexpr const char *const MQTT_PAYLOAD_TURN_ON = "pl_ton"; constexpr const char *const MQTT_PAYLOAD_UNLOCK = "pl_unlk"; +constexpr const char *const MQTT_PERCENTAGE_COMMAND_TEMPLATE = "pct_cmd_tpl"; +constexpr const char *const MQTT_PERCENTAGE_COMMAND_TOPIC = "pct_cmd_t"; +constexpr const char *const MQTT_PERCENTAGE_STATE_TOPIC = "pct_stat_t"; +constexpr const char *const MQTT_PERCENTAGE_VALUE_TEMPLATE = "pct_val_tpl"; constexpr const char *const MQTT_POSITION_CLOSED = "pos_clsd"; constexpr const char *const MQTT_POSITION_OPEN = "pos_open"; +constexpr const char *const MQTT_POSITION_TEMPLATE = "pos_tpl"; +constexpr const char *const MQTT_POSITION_TOPIC = "pos_t"; constexpr const char *const MQTT_POWER_COMMAND_TOPIC = "pow_cmd_t"; -constexpr const char *const MQTT_POWER_STATE_TOPIC = "pow_stat_t"; constexpr const char *const MQTT_POWER_STATE_TEMPLATE = "pow_stat_tpl"; -constexpr const char *const MQTT_PRESET_MODE_COMMAND_TOPIC = "pr_mode_cmd_t"; +constexpr const char *const MQTT_POWER_STATE_TOPIC = "pow_stat_t"; constexpr const char *const MQTT_PRESET_MODE_COMMAND_TEMPLATE = "pr_mode_cmd_tpl"; +constexpr const char *const MQTT_PRESET_MODE_COMMAND_TOPIC = "pr_mode_cmd_t"; constexpr const char *const MQTT_PRESET_MODE_STATE_TOPIC = "pr_mode_stat_t"; constexpr const char *const MQTT_PRESET_MODE_VALUE_TEMPLATE = "pr_mode_val_tpl"; constexpr const char *const MQTT_PRESET_MODES = "pr_modes"; @@ -188,36 +195,38 @@ constexpr const char *const MQTT_SEND_IF_OFF = "send_if_off"; constexpr const char *const MQTT_SET_FAN_SPEED_TOPIC = "set_fan_spd_t"; constexpr const char *const MQTT_SET_POSITION_TEMPLATE = "set_pos_tpl"; constexpr const char *const MQTT_SET_POSITION_TOPIC = "set_pos_t"; -constexpr const char *const MQTT_POSITION_TOPIC = "pos_t"; -constexpr const char *const MQTT_POSITION_TEMPLATE = "pos_tpl"; +constexpr const char *const MQTT_SOURCE_TYPE = "src_type"; constexpr const char *const MQTT_SPEED_COMMAND_TOPIC = "spd_cmd_t"; -constexpr const char *const MQTT_SPEED_STATE_TOPIC = "spd_stat_t"; -constexpr const char *const MQTT_SPEED_RANGE_MIN = "spd_rng_min"; constexpr const char *const MQTT_SPEED_RANGE_MAX = "spd_rng_max"; +constexpr const char *const MQTT_SPEED_RANGE_MIN = "spd_rng_min"; +constexpr const char *const MQTT_SPEED_STATE_TOPIC = "spd_stat_t"; constexpr const char *const MQTT_SPEED_VALUE_TEMPLATE = "spd_val_tpl"; constexpr const char *const MQTT_SPEEDS = "spds"; -constexpr const char *const MQTT_SOURCE_TYPE = "src_type"; constexpr const char *const MQTT_STATE_CLASS = "stat_cla"; constexpr const char *const MQTT_STATE_CLOSED = "stat_clsd"; constexpr const char *const MQTT_STATE_CLOSING = "stat_closing"; +constexpr const char *const MQTT_STATE_LOCKED = "stat_locked"; constexpr const char *const MQTT_STATE_OFF = "stat_off"; constexpr const char *const MQTT_STATE_ON = "stat_on"; constexpr const char *const MQTT_STATE_OPEN = "stat_open"; constexpr const char *const MQTT_STATE_OPENING = "stat_opening"; constexpr const char *const MQTT_STATE_STOPPED = "stat_stopped"; -constexpr const char *const MQTT_STATE_LOCKED = "stat_locked"; -constexpr const char *const MQTT_STATE_UNLOCKED = "stat_unlocked"; -constexpr const char *const MQTT_STATE_TOPIC = "stat_t"; constexpr const char *const MQTT_STATE_TEMPLATE = "stat_tpl"; +constexpr const char *const MQTT_STATE_TOPIC = "stat_t"; +constexpr const char *const MQTT_STATE_UNLOCKED = "stat_unlocked"; constexpr const char *const MQTT_STATE_VALUE_TEMPLATE = "stat_val_tpl"; constexpr const char *const MQTT_STEP = "step"; constexpr const char *const MQTT_SUBTYPE = "stype"; -constexpr const char *const MQTT_SUPPORTED_FEATURES = "sup_feat"; constexpr const char *const MQTT_SUPPORTED_COLOR_MODES = "sup_clrm"; +constexpr const char *const MQTT_SUPPORTED_FEATURES = "sup_feat"; constexpr const char *const MQTT_SWING_MODE_COMMAND_TEMPLATE = "swing_mode_cmd_tpl"; constexpr const char *const MQTT_SWING_MODE_COMMAND_TOPIC = "swing_mode_cmd_t"; constexpr const char *const MQTT_SWING_MODE_STATE_TEMPLATE = "swing_mode_stat_tpl"; constexpr const char *const MQTT_SWING_MODE_STATE_TOPIC = "swing_mode_stat_t"; +constexpr const char *const MQTT_TARGET_HUMIDITY_COMMAND_TEMPLATE = "hum_cmd_tpl"; +constexpr const char *const MQTT_TARGET_HUMIDITY_COMMAND_TOPIC = "hum_cmd_t"; +constexpr const char *const MQTT_TARGET_HUMIDITY_STATE_TEMPLATE = "hum_state_tpl"; +constexpr const char *const MQTT_TARGET_HUMIDITY_STATE_TOPIC = "hum_stat_t"; constexpr const char *const MQTT_TEMPERATURE_COMMAND_TEMPLATE = "temp_cmd_tpl"; constexpr const char *const MQTT_TEMPERATURE_COMMAND_TOPIC = "temp_cmd_t"; constexpr const char *const MQTT_TEMPERATURE_HIGH_COMMAND_TEMPLATE = "temp_hi_cmd_tpl"; @@ -232,15 +241,15 @@ constexpr const char *const MQTT_TEMPERATURE_STATE_TEMPLATE = "temp_stat_tpl"; constexpr const char *const MQTT_TEMPERATURE_STATE_TOPIC = "temp_stat_t"; constexpr const char *const MQTT_TEMPERATURE_UNIT = "temp_unit"; constexpr const char *const MQTT_TILT_CLOSED_VALUE = "tilt_clsd_val"; -constexpr const char *const MQTT_TILT_COMMAND_TOPIC = "tilt_cmd_t"; constexpr const char *const MQTT_TILT_COMMAND_TEMPLATE = "tilt_cmd_tpl"; +constexpr const char *const MQTT_TILT_COMMAND_TOPIC = "tilt_cmd_t"; constexpr const char *const MQTT_TILT_INVERT_STATE = "tilt_inv_stat"; constexpr const char *const MQTT_TILT_MAX = "tilt_max"; constexpr const char *const MQTT_TILT_MIN = "tilt_min"; constexpr const char *const MQTT_TILT_OPENED_VALUE = "tilt_opnd_val"; constexpr const char *const MQTT_TILT_OPTIMISTIC = "tilt_opt"; -constexpr const char *const MQTT_TILT_STATUS_TOPIC = "tilt_status_t"; constexpr const char *const MQTT_TILT_STATUS_TEMPLATE = "tilt_status_tpl"; +constexpr const char *const MQTT_TILT_STATUS_TOPIC = "tilt_status_t"; constexpr const char *const MQTT_TOPIC = "t"; constexpr const char *const MQTT_UNIQUE_ID = "uniq_id"; constexpr const char *const MQTT_UNIT_OF_MEASUREMENT = "unit_of_meas"; @@ -255,18 +264,10 @@ constexpr const char *const MQTT_XY_COMMAND_TOPIC = "xy_cmd_t"; constexpr const char *const MQTT_XY_STATE_TOPIC = "xy_stat_t"; constexpr const char *const MQTT_XY_VALUE_TEMPLATE = "xy_val_tpl"; -constexpr const char *const MQTT_DEVICE_CONNECTIONS = "cns"; -constexpr const char *const MQTT_DEVICE_IDENTIFIERS = "ids"; -constexpr const char *const MQTT_DEVICE_NAME = "name"; -constexpr const char *const MQTT_DEVICE_MANUFACTURER = "mf"; -constexpr const char *const MQTT_DEVICE_MODEL = "mdl"; -constexpr const char *const MQTT_DEVICE_SW_VERSION = "sw"; -constexpr const char *const MQTT_DEVICE_SUGGESTED_AREA = "sa"; - #else -constexpr const char *const MQTT_ACTION_TOPIC = "action_topic"; constexpr const char *const MQTT_ACTION_TEMPLATE = "action_template"; +constexpr const char *const MQTT_ACTION_TOPIC = "action_topic"; constexpr const char *const MQTT_AUTOMATION_TYPE = "automation_type"; constexpr const char *const MQTT_AUX_COMMAND_TOPIC = "aux_command_topic"; constexpr const char *const MQTT_AUX_STATE_TEMPLATE = "aux_state_template"; @@ -277,60 +278,68 @@ constexpr const char *const MQTT_AVAILABILITY_TOPIC = "availability_topic"; constexpr const char *const MQTT_AWAY_MODE_COMMAND_TOPIC = "away_mode_command_topic"; constexpr const char *const MQTT_AWAY_MODE_STATE_TEMPLATE = "away_mode_state_template"; constexpr const char *const MQTT_AWAY_MODE_STATE_TOPIC = "away_mode_state_topic"; +constexpr const char *const MQTT_BATTERY_LEVEL_TEMPLATE = "battery_level_template"; +constexpr const char *const MQTT_BATTERY_LEVEL_TOPIC = "battery_level_topic"; constexpr const char *const MQTT_BLUE_TEMPLATE = "blue_template"; constexpr const char *const MQTT_BRIGHTNESS_COMMAND_TOPIC = "brightness_command_topic"; constexpr const char *const MQTT_BRIGHTNESS_SCALE = "brightness_scale"; constexpr const char *const MQTT_BRIGHTNESS_STATE_TOPIC = "brightness_state_topic"; constexpr const char *const MQTT_BRIGHTNESS_TEMPLATE = "brightness_template"; constexpr const char *const MQTT_BRIGHTNESS_VALUE_TEMPLATE = "brightness_value_template"; -constexpr const char *const MQTT_COLOR_TEMP_COMMAND_TEMPLATE = "color_temp_command_template"; -constexpr const char *const MQTT_BATTERY_LEVEL_TOPIC = "battery_level_topic"; -constexpr const char *const MQTT_BATTERY_LEVEL_TEMPLATE = "battery_level_template"; -constexpr const char *const MQTT_CONFIGURATION_URL = "configuration_url"; -constexpr const char *const MQTT_CHARGING_TOPIC = "charging_topic"; constexpr const char *const MQTT_CHARGING_TEMPLATE = "charging_template"; +constexpr const char *const MQTT_CHARGING_TOPIC = "charging_topic"; +constexpr const char *const MQTT_CLEANING_TEMPLATE = "cleaning_template"; +constexpr const char *const MQTT_CLEANING_TOPIC = "cleaning_topic"; +constexpr const char *const MQTT_CODE_ARM_REQUIRED = "code_arm_required"; +constexpr const char *const MQTT_CODE_DISARM_REQUIRED = "code_disarm_required"; constexpr const char *const MQTT_COLOR_MODE = "color_mode"; constexpr const char *const MQTT_COLOR_MODE_STATE_TOPIC = "color_mode_state_topic"; constexpr const char *const MQTT_COLOR_MODE_VALUE_TEMPLATE = "color_mode_value_template"; +constexpr const char *const MQTT_COLOR_TEMP_COMMAND_TEMPLATE = "color_temp_command_template"; constexpr const char *const MQTT_COLOR_TEMP_COMMAND_TOPIC = "color_temp_command_topic"; constexpr const char *const MQTT_COLOR_TEMP_STATE_TOPIC = "color_temp_state_topic"; constexpr const char *const MQTT_COLOR_TEMP_TEMPLATE = "color_temp_template"; constexpr const char *const MQTT_COLOR_TEMP_VALUE_TEMPLATE = "color_temp_value_template"; -constexpr const char *const MQTT_CLEANING_TOPIC = "cleaning_topic"; -constexpr const char *const MQTT_CLEANING_TEMPLATE = "cleaning_template"; constexpr const char *const MQTT_COMMAND_OFF_TEMPLATE = "command_off_template"; constexpr const char *const MQTT_COMMAND_ON_TEMPLATE = "command_on_template"; -constexpr const char *const MQTT_COMMAND_TOPIC = "command_topic"; constexpr const char *const MQTT_COMMAND_RETAIN = "retain"; constexpr const char *const MQTT_COMMAND_TEMPLATE = "command_template"; -constexpr const char *const MQTT_CODE_ARM_REQUIRED = "code_arm_required"; -constexpr const char *const MQTT_CODE_DISARM_REQUIRED = "code_disarm_required"; -constexpr const char *const MQTT_CURRENT_TEMPERATURE_TOPIC = "current_temperature_topic"; -constexpr const char *const MQTT_CURRENT_TEMPERATURE_TEMPLATE = "current_temperature_template"; -constexpr const char *const MQTT_CURRENT_HUMIDITY_TOPIC = "current_humidity_topic"; +constexpr const char *const MQTT_COMMAND_TOPIC = "command_topic"; +constexpr const char *const MQTT_CONFIGURATION_URL = "configuration_url"; constexpr const char *const MQTT_CURRENT_HUMIDITY_TEMPLATE = "current_humidity_template"; +constexpr const char *const MQTT_CURRENT_HUMIDITY_TOPIC = "current_humidity_topic"; +constexpr const char *const MQTT_CURRENT_TEMPERATURE_TEMPLATE = "current_temperature_template"; +constexpr const char *const MQTT_CURRENT_TEMPERATURE_TOPIC = "current_temperature_topic"; constexpr const char *const MQTT_DEVICE = "device"; constexpr const char *const MQTT_DEVICE_CLASS = "device_class"; -constexpr const char *const MQTT_DOCKED_TOPIC = "docked_topic"; +constexpr const char *const MQTT_DEVICE_CONNECTIONS = "connections"; +constexpr const char *const MQTT_DEVICE_IDENTIFIERS = "identifiers"; +constexpr const char *const MQTT_DEVICE_MANUFACTURER = "manufacturer"; +constexpr const char *const MQTT_DEVICE_MODEL = "model"; +constexpr const char *const MQTT_DEVICE_NAME = "name"; +constexpr const char *const MQTT_DEVICE_SUGGESTED_AREA = "suggested_area"; +constexpr const char *const MQTT_DEVICE_SW_VERSION = "sw_version"; constexpr const char *const MQTT_DOCKED_TEMPLATE = "docked_template"; -constexpr const char *const MQTT_ENABLED_BY_DEFAULT = "enabled_by_default"; -constexpr const char *const MQTT_ERROR_TOPIC = "error_topic"; -constexpr const char *const MQTT_ERROR_TEMPLATE = "error_template"; -constexpr const char *const MQTT_FAN_SPEED_TOPIC = "fan_speed_topic"; -constexpr const char *const MQTT_FAN_SPEED_TEMPLATE = "fan_speed_template"; -constexpr const char *const MQTT_FAN_SPEED_LIST = "fan_speed_list"; -constexpr const char *const MQTT_FLASH_TIME_LONG = "flash_time_long"; -constexpr const char *const MQTT_FLASH_TIME_SHORT = "flash_time_short"; +constexpr const char *const MQTT_DOCKED_TOPIC = "docked_topic"; constexpr const char *const MQTT_EFFECT_COMMAND_TOPIC = "effect_command_topic"; constexpr const char *const MQTT_EFFECT_LIST = "effect_list"; constexpr const char *const MQTT_EFFECT_STATE_TOPIC = "effect_state_topic"; constexpr const char *const MQTT_EFFECT_TEMPLATE = "effect_template"; constexpr const char *const MQTT_EFFECT_VALUE_TEMPLATE = "effect_value_template"; +constexpr const char *const MQTT_ENABLED_BY_DEFAULT = "enabled_by_default"; +constexpr const char *const MQTT_ENTITY_CATEGORY = "entity_category"; +constexpr const char *const MQTT_ERROR_TEMPLATE = "error_template"; +constexpr const char *const MQTT_ERROR_TOPIC = "error_topic"; constexpr const char *const MQTT_EXPIRE_AFTER = "expire_after"; constexpr const char *const MQTT_FAN_MODE_COMMAND_TEMPLATE = "fan_mode_command_template"; constexpr const char *const MQTT_FAN_MODE_COMMAND_TOPIC = "fan_mode_command_topic"; constexpr const char *const MQTT_FAN_MODE_STATE_TEMPLATE = "fan_mode_state_template"; constexpr const char *const MQTT_FAN_MODE_STATE_TOPIC = "fan_mode_state_topic"; +constexpr const char *const MQTT_FAN_SPEED_LIST = "fan_speed_list"; +constexpr const char *const MQTT_FAN_SPEED_TEMPLATE = "fan_speed_template"; +constexpr const char *const MQTT_FAN_SPEED_TOPIC = "fan_speed_topic"; +constexpr const char *const MQTT_FLASH_TIME_LONG = "flash_time_long"; +constexpr const char *const MQTT_FLASH_TIME_SHORT = "flash_time_short"; constexpr const char *const MQTT_FORCE_UPDATE = "force_update"; constexpr const char *const MQTT_GREEN_TEMPLATE = "green_template"; constexpr const char *const MQTT_HOLD_COMMAND_TEMPLATE = "hold_command_template"; @@ -342,56 +351,49 @@ constexpr const char *const MQTT_HS_STATE_TOPIC = "hs_state_topic"; constexpr const char *const MQTT_HS_VALUE_TEMPLATE = "hs_value_template"; constexpr const char *const MQTT_ICON = "icon"; constexpr const char *const MQTT_INITIAL = "initial"; -constexpr const char *const MQTT_TARGET_HUMIDITY_COMMAND_TOPIC = "target_humidity_command_topic"; -constexpr const char *const MQTT_TARGET_HUMIDITY_COMMAND_TEMPLATE = "target_humidity_command_template"; -constexpr const char *const MQTT_TARGET_HUMIDITY_STATE_TOPIC = "target_humidity_state_topic"; -constexpr const char *const MQTT_TARGET_HUMIDITY_STATE_TEMPLATE = "target_humidity_state_template"; constexpr const char *const MQTT_JSON_ATTRIBUTES = "json_attributes"; -constexpr const char *const MQTT_JSON_ATTRIBUTES_TOPIC = "json_attributes_topic"; constexpr const char *const MQTT_JSON_ATTRIBUTES_TEMPLATE = "json_attributes_template"; +constexpr const char *const MQTT_JSON_ATTRIBUTES_TOPIC = "json_attributes_topic"; constexpr const char *const MQTT_LAST_RESET_TOPIC = "last_reset_topic"; constexpr const char *const MQTT_LAST_RESET_VALUE_TEMPLATE = "last_reset_value_template"; constexpr const char *const MQTT_MAX = "max"; -constexpr const char *const MQTT_MIN = "min"; constexpr const char *const MQTT_MAX_HUMIDITY = "max_humidity"; -constexpr const char *const MQTT_MIN_HUMIDITY = "min_humidity"; constexpr const char *const MQTT_MAX_MIREDS = "max_mireds"; -constexpr const char *const MQTT_MIN_MIREDS = "min_mireds"; constexpr const char *const MQTT_MAX_TEMP = "max_temp"; +constexpr const char *const MQTT_MIN = "min"; +constexpr const char *const MQTT_MIN_HUMIDITY = "min_humidity"; +constexpr const char *const MQTT_MIN_MIREDS = "min_mireds"; constexpr const char *const MQTT_MIN_TEMP = "min_temp"; +constexpr const char *const MQTT_MODE = "mode"; constexpr const char *const MQTT_MODE_COMMAND_TEMPLATE = "mode_command_template"; constexpr const char *const MQTT_MODE_COMMAND_TOPIC = "mode_command_topic"; -constexpr const char *const MQTT_MODE_STATE_TOPIC = "mode_state_topic"; constexpr const char *const MQTT_MODE_STATE_TEMPLATE = "mode_state_template"; +constexpr const char *const MQTT_MODE_STATE_TOPIC = "mode_state_topic"; constexpr const char *const MQTT_MODES = "modes"; constexpr const char *const MQTT_NAME = "name"; constexpr const char *const MQTT_OBJECT_ID = "object_id"; constexpr const char *const MQTT_OFF_DELAY = "off_delay"; constexpr const char *const MQTT_ON_COMMAND_TYPE = "on_command_type"; -constexpr const char *const MQTT_OPTIONS = "options"; constexpr const char *const MQTT_OPTIMISTIC = "optimistic"; -constexpr const char *const MQTT_OSCILLATION_COMMAND_TOPIC = "oscillation_command_topic"; +constexpr const char *const MQTT_OPTIONS = "options"; constexpr const char *const MQTT_OSCILLATION_COMMAND_TEMPLATE = "oscillation_command_template"; +constexpr const char *const MQTT_OSCILLATION_COMMAND_TOPIC = "oscillation_command_topic"; constexpr const char *const MQTT_OSCILLATION_STATE_TOPIC = "oscillation_state_topic"; constexpr const char *const MQTT_OSCILLATION_VALUE_TEMPLATE = "oscillation_value_template"; -constexpr const char *const MQTT_PERCENTAGE_COMMAND_TOPIC = "percentage_command_topic"; -constexpr const char *const MQTT_PERCENTAGE_COMMAND_TEMPLATE = "percentage_command_template"; -constexpr const char *const MQTT_PERCENTAGE_STATE_TOPIC = "percentage_state_topic"; -constexpr const char *const MQTT_PERCENTAGE_VALUE_TEMPLATE = "percentage_value_template"; constexpr const char *const MQTT_PAYLOAD = "payload"; constexpr const char *const MQTT_PAYLOAD_ARM_AWAY = "payload_arm_away"; +constexpr const char *const MQTT_PAYLOAD_ARM_CUSTOM_BYPASS = "payload_arm_custom_bypass"; constexpr const char *const MQTT_PAYLOAD_ARM_HOME = "payload_arm_home"; constexpr const char *const MQTT_PAYLOAD_ARM_NIGHT = "payload_arm_night"; constexpr const char *const MQTT_PAYLOAD_ARM_VACATION = "payload_arm_vacation"; -constexpr const char *const MQTT_PAYLOAD_ARM_CUSTOM_BYPASS = "payload_arm_custom_bypass"; constexpr const char *const MQTT_PAYLOAD_AVAILABLE = "payload_available"; constexpr const char *const MQTT_PAYLOAD_CLEAN_SPOT = "payload_clean_spot"; constexpr const char *const MQTT_PAYLOAD_CLOSE = "payload_close"; constexpr const char *const MQTT_PAYLOAD_DISARM = "payload_disarm"; constexpr const char *const MQTT_PAYLOAD_HIGH_SPEED = "payload_high_speed"; constexpr const char *const MQTT_PAYLOAD_HOME = "payload_home"; -constexpr const char *const MQTT_PAYLOAD_LOCK = "payload_lock"; constexpr const char *const MQTT_PAYLOAD_LOCATE = "payload_locate"; +constexpr const char *const MQTT_PAYLOAD_LOCK = "payload_lock"; constexpr const char *const MQTT_PAYLOAD_LOW_SPEED = "payload_low_speed"; constexpr const char *const MQTT_PAYLOAD_MEDIUM_SPEED = "payload_medium_speed"; constexpr const char *const MQTT_PAYLOAD_NOT_AVAILABLE = "payload_not_available"; @@ -408,20 +410,26 @@ constexpr const char *const MQTT_PAYLOAD_RESET_HUMIDITY = "payload_reset_humidit constexpr const char *const MQTT_PAYLOAD_RESET_MODE = "payload_reset_mode"; constexpr const char *const MQTT_PAYLOAD_RESET_PERCENTAGE = "payload_reset_percentage"; constexpr const char *const MQTT_PAYLOAD_RESET_PRESET_MODE = "payload_reset_preset_mode"; -constexpr const char *const MQTT_PAYLOAD_STOP = "payload_stop"; +constexpr const char *const MQTT_PAYLOAD_RETURN_TO_BASE = "payload_return_to_base"; constexpr const char *const MQTT_PAYLOAD_START = "payload_start"; constexpr const char *const MQTT_PAYLOAD_START_PAUSE = "payload_start_pause"; -constexpr const char *const MQTT_PAYLOAD_RETURN_TO_BASE = "payload_return_to_base"; +constexpr const char *const MQTT_PAYLOAD_STOP = "payload_stop"; constexpr const char *const MQTT_PAYLOAD_TURN_OFF = "payload_turn_off"; constexpr const char *const MQTT_PAYLOAD_TURN_ON = "payload_turn_on"; constexpr const char *const MQTT_PAYLOAD_UNLOCK = "payload_unlock"; +constexpr const char *const MQTT_PERCENTAGE_COMMAND_TEMPLATE = "percentage_command_template"; +constexpr const char *const MQTT_PERCENTAGE_COMMAND_TOPIC = "percentage_command_topic"; +constexpr const char *const MQTT_PERCENTAGE_STATE_TOPIC = "percentage_state_topic"; +constexpr const char *const MQTT_PERCENTAGE_VALUE_TEMPLATE = "percentage_value_template"; constexpr const char *const MQTT_POSITION_CLOSED = "position_closed"; constexpr const char *const MQTT_POSITION_OPEN = "position_open"; +constexpr const char *const MQTT_POSITION_TEMPLATE = "position_template"; +constexpr const char *const MQTT_POSITION_TOPIC = "position_topic"; constexpr const char *const MQTT_POWER_COMMAND_TOPIC = "power_command_topic"; -constexpr const char *const MQTT_POWER_STATE_TOPIC = "power_state_topic"; constexpr const char *const MQTT_POWER_STATE_TEMPLATE = "power_state_template"; -constexpr const char *const MQTT_PRESET_MODE_COMMAND_TOPIC = "preset_mode_command_topic"; +constexpr const char *const MQTT_POWER_STATE_TOPIC = "power_state_topic"; constexpr const char *const MQTT_PRESET_MODE_COMMAND_TEMPLATE = "preset_mode_command_template"; +constexpr const char *const MQTT_PRESET_MODE_COMMAND_TOPIC = "preset_mode_command_topic"; constexpr const char *const MQTT_PRESET_MODE_STATE_TOPIC = "preset_mode_state_topic"; constexpr const char *const MQTT_PRESET_MODE_VALUE_TEMPLATE = "preset_mode_value_template"; constexpr const char *const MQTT_PRESET_MODES = "preset_modes"; @@ -444,36 +452,38 @@ constexpr const char *const MQTT_SEND_IF_OFF = "send_if_off"; constexpr const char *const MQTT_SET_FAN_SPEED_TOPIC = "set_fan_speed_topic"; constexpr const char *const MQTT_SET_POSITION_TEMPLATE = "set_position_template"; constexpr const char *const MQTT_SET_POSITION_TOPIC = "set_position_topic"; -constexpr const char *const MQTT_POSITION_TOPIC = "position_topic"; -constexpr const char *const MQTT_POSITION_TEMPLATE = "position_template"; +constexpr const char *const MQTT_SOURCE_TYPE = "source_type"; constexpr const char *const MQTT_SPEED_COMMAND_TOPIC = "speed_command_topic"; -constexpr const char *const MQTT_SPEED_STATE_TOPIC = "speed_state_topic"; -constexpr const char *const MQTT_SPEED_RANGE_MIN = "speed_range_min"; constexpr const char *const MQTT_SPEED_RANGE_MAX = "speed_range_max"; +constexpr const char *const MQTT_SPEED_RANGE_MIN = "speed_range_min"; +constexpr const char *const MQTT_SPEED_STATE_TOPIC = "speed_state_topic"; constexpr const char *const MQTT_SPEED_VALUE_TEMPLATE = "speed_value_template"; constexpr const char *const MQTT_SPEEDS = "speeds"; -constexpr const char *const MQTT_SOURCE_TYPE = "source_type"; constexpr const char *const MQTT_STATE_CLASS = "state_class"; constexpr const char *const MQTT_STATE_CLOSED = "state_closed"; constexpr const char *const MQTT_STATE_CLOSING = "state_closing"; +constexpr const char *const MQTT_STATE_LOCKED = "state_locked"; constexpr const char *const MQTT_STATE_OFF = "state_off"; constexpr const char *const MQTT_STATE_ON = "state_on"; constexpr const char *const MQTT_STATE_OPEN = "state_open"; constexpr const char *const MQTT_STATE_OPENING = "state_opening"; constexpr const char *const MQTT_STATE_STOPPED = "state_stopped"; -constexpr const char *const MQTT_STATE_LOCKED = "state_locked"; -constexpr const char *const MQTT_STATE_UNLOCKED = "state_unlocked"; -constexpr const char *const MQTT_STATE_TOPIC = "state_topic"; constexpr const char *const MQTT_STATE_TEMPLATE = "state_template"; +constexpr const char *const MQTT_STATE_TOPIC = "state_topic"; +constexpr const char *const MQTT_STATE_UNLOCKED = "state_unlocked"; constexpr const char *const MQTT_STATE_VALUE_TEMPLATE = "state_value_template"; constexpr const char *const MQTT_STEP = "step"; constexpr const char *const MQTT_SUBTYPE = "subtype"; -constexpr const char *const MQTT_SUPPORTED_FEATURES = "supported_features"; constexpr const char *const MQTT_SUPPORTED_COLOR_MODES = "supported_color_modes"; +constexpr const char *const MQTT_SUPPORTED_FEATURES = "supported_features"; constexpr const char *const MQTT_SWING_MODE_COMMAND_TEMPLATE = "swing_mode_command_template"; constexpr const char *const MQTT_SWING_MODE_COMMAND_TOPIC = "swing_mode_command_topic"; constexpr const char *const MQTT_SWING_MODE_STATE_TEMPLATE = "swing_mode_state_template"; constexpr const char *const MQTT_SWING_MODE_STATE_TOPIC = "swing_mode_state_topic"; +constexpr const char *const MQTT_TARGET_HUMIDITY_COMMAND_TEMPLATE = "target_humidity_command_template"; +constexpr const char *const MQTT_TARGET_HUMIDITY_COMMAND_TOPIC = "target_humidity_command_topic"; +constexpr const char *const MQTT_TARGET_HUMIDITY_STATE_TEMPLATE = "target_humidity_state_template"; +constexpr const char *const MQTT_TARGET_HUMIDITY_STATE_TOPIC = "target_humidity_state_topic"; constexpr const char *const MQTT_TEMPERATURE_COMMAND_TEMPLATE = "temperature_command_template"; constexpr const char *const MQTT_TEMPERATURE_COMMAND_TOPIC = "temperature_command_topic"; constexpr const char *const MQTT_TEMPERATURE_HIGH_COMMAND_TEMPLATE = "temperature_high_command_template"; @@ -488,15 +498,15 @@ constexpr const char *const MQTT_TEMPERATURE_STATE_TEMPLATE = "temperature_state constexpr const char *const MQTT_TEMPERATURE_STATE_TOPIC = "temperature_state_topic"; constexpr const char *const MQTT_TEMPERATURE_UNIT = "temperature_unit"; constexpr const char *const MQTT_TILT_CLOSED_VALUE = "tilt_closed_value"; -constexpr const char *const MQTT_TILT_COMMAND_TOPIC = "tilt_command_topic"; constexpr const char *const MQTT_TILT_COMMAND_TEMPLATE = "tilt_command_template"; +constexpr const char *const MQTT_TILT_COMMAND_TOPIC = "tilt_command_topic"; constexpr const char *const MQTT_TILT_INVERT_STATE = "tilt_invert_state"; constexpr const char *const MQTT_TILT_MAX = "tilt_max"; constexpr const char *const MQTT_TILT_MIN = "tilt_min"; constexpr const char *const MQTT_TILT_OPENED_VALUE = "tilt_opened_value"; constexpr const char *const MQTT_TILT_OPTIMISTIC = "tilt_optimistic"; -constexpr const char *const MQTT_TILT_STATUS_TOPIC = "tilt_status_topic"; constexpr const char *const MQTT_TILT_STATUS_TEMPLATE = "tilt_status_template"; +constexpr const char *const MQTT_TILT_STATUS_TOPIC = "tilt_status_topic"; constexpr const char *const MQTT_TOPIC = "topic"; constexpr const char *const MQTT_UNIQUE_ID = "unique_id"; constexpr const char *const MQTT_UNIT_OF_MEASUREMENT = "unit_of_measurement"; @@ -511,19 +521,8 @@ constexpr const char *const MQTT_XY_COMMAND_TOPIC = "xy_command_topic"; constexpr const char *const MQTT_XY_STATE_TOPIC = "xy_state_topic"; constexpr const char *const MQTT_XY_VALUE_TEMPLATE = "xy_value_template"; -constexpr const char *const MQTT_DEVICE_CONNECTIONS = "connections"; -constexpr const char *const MQTT_DEVICE_IDENTIFIERS = "identifiers"; -constexpr const char *const MQTT_DEVICE_NAME = "name"; -constexpr const char *const MQTT_DEVICE_MANUFACTURER = "manufacturer"; -constexpr const char *const MQTT_DEVICE_MODEL = "model"; -constexpr const char *const MQTT_DEVICE_SW_VERSION = "sw_version"; -constexpr const char *const MQTT_DEVICE_SUGGESTED_AREA = "suggested_area"; #endif -// Additional MQTT fields where no abbreviation is defined in HA source -constexpr const char *const MQTT_ENTITY_CATEGORY = "entity_category"; -constexpr const char *const MQTT_MODE = "mode"; - } // namespace mqtt } // namespace esphome From b03d0f37a43e177174316f786586623629efe749 Mon Sep 17 00:00:00 2001 From: Mike La Spina Date: Tue, 23 Apr 2024 21:01:28 -0500 Subject: [PATCH 1320/2101] Limit Rx wait loop time to 3 seconds. (#6594) Co-authored-by: descipher --- esphome/components/ld2420/ld2420.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/esphome/components/ld2420/ld2420.cpp b/esphome/components/ld2420/ld2420.cpp index 58c9a289a3..e57fdbc84e 100644 --- a/esphome/components/ld2420/ld2420.cpp +++ b/esphome/components/ld2420/ld2420.cpp @@ -493,19 +493,16 @@ void LD2420Component::handle_ack_data_(uint8_t *buffer, int len) { } int LD2420Component::send_cmd_from_array(CmdFrameT frame) { + uint32_t start_millis = millis(); uint8_t error = 0; uint8_t ack_buffer[64]; uint8_t cmd_buffer[64]; - uint16_t loop_count; this->cmd_reply_.ack = false; if (frame.command != CMD_RESTART) this->set_cmd_active_(true); // Restart does not reply, thus no ack state required. uint8_t retry = 3; while (retry) { - // TODO setup a dynamic method e.g. millis time count etc. to tune for non ESP32 240Mhz devices - // this is ok for now since the module firmware is changing like the weather atm frame.length = 0; - loop_count = 1250; uint16_t frame_data_bytes = frame.data_length + 2; // Always add two bytes for the cmd size memcpy(&cmd_buffer[frame.length], &frame.header, sizeof(frame.header)); @@ -538,12 +535,13 @@ int LD2420Component::send_cmd_from_array(CmdFrameT frame) { this->readline_(read(), ack_buffer, sizeof(ack_buffer)); } delay_microseconds_safe(1450); - if (loop_count <= 0) { + // Wait on an Rx from the LD2420 for up to 3 1 second loops, otherwise it could trigger a WDT. + if ((millis() - start_millis) > 1000) { + start_millis = millis(); error = LD2420_ERROR_TIMEOUT; retry--; break; } - loop_count--; } if (this->cmd_reply_.ack) retry = 0; From c531a528f0fd56d0778921aad96a01df80062222 Mon Sep 17 00:00:00 2001 From: David Friedland Date: Tue, 23 Apr 2024 19:35:26 -0700 Subject: [PATCH 1321/2101] Event entity support (#6451) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- CODEOWNERS | 2 + esphome/components/api/api.proto | 26 +++ esphome/components/api/api_connection.cpp | 24 +++ esphome/components/api/api_connection.h | 5 + esphome/components/api/api_pb2.cpp | 151 ++++++++++++++++++ esphome/components/api/api_pb2.h | 34 ++++ esphome/components/api/api_pb2_service.cpp | 16 ++ esphome/components/api/api_pb2_service.h | 6 + esphome/components/api/api_server.cpp | 7 + 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/event/__init__.py | 134 ++++++++++++++++ esphome/components/event/automation.h | 25 +++ esphome/components/event/event.cpp | 24 +++ esphome/components/event/event.h | 37 +++++ esphome/components/mqtt/__init__.py | 1 + esphome/components/mqtt/mqtt_const.h | 4 + esphome/components/mqtt/mqtt_event.cpp | 54 +++++++ esphome/components/mqtt/mqtt_event.h | 39 +++++ esphome/components/template/event/__init__.py | 24 +++ .../template/event/template_event.h | 12 ++ .../components/web_server/list_entities.cpp | 9 ++ esphome/components/web_server/list_entities.h | 3 + esphome/components/web_server/web_server.cpp | 22 +++ esphome/components/web_server/web_server.h | 7 + esphome/const.py | 5 + esphome/core/application.h | 20 +++ esphome/core/component_iterator.cpp | 15 ++ esphome/core/component_iterator.h | 6 + esphome/core/controller.cpp | 6 + esphome/core/controller.h | 6 + esphome/core/defines.h | 1 + script/ci-custom.py | 1 + tests/components/event/test.esp32-c3-idf.yaml | 9 ++ tests/components/event/test.esp32-c3.yaml | 9 ++ tests/components/event/test.esp32-idf.yaml | 9 ++ tests/components/event/test.esp32.yaml | 9 ++ tests/components/event/test.esp8266.yaml | 9 ++ tests/components/event/test.rp2040.yaml | 9 ++ 41 files changed, 792 insertions(+) create mode 100644 esphome/components/event/__init__.py create mode 100644 esphome/components/event/automation.h create mode 100644 esphome/components/event/event.cpp create mode 100644 esphome/components/event/event.h create mode 100644 esphome/components/mqtt/mqtt_event.cpp create mode 100644 esphome/components/mqtt/mqtt_event.h create mode 100644 esphome/components/template/event/__init__.py create mode 100644 esphome/components/template/event/template_event.h create mode 100644 tests/components/event/test.esp32-c3-idf.yaml create mode 100644 tests/components/event/test.esp32-c3.yaml create mode 100644 tests/components/event/test.esp32-idf.yaml create mode 100644 tests/components/event/test.esp32.yaml create mode 100644 tests/components/event/test.esp8266.yaml create mode 100644 tests/components/event/test.rp2040.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 8da1618636..a60a5c3099 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -119,6 +119,7 @@ esphome/components/esp32_rmt/* @jesserockz esphome/components/esp32_rmt_led_strip/* @jesserockz esphome/components/esp8266/* @esphome/core esphome/components/ethernet_info/* @gtjadsonsantos +esphome/components/event/* @nohat esphome/components/exposure_notifications/* @OttoWinter esphome/components/ezo/* @ssieb esphome/components/ezo_pmp/* @carlos-sarmiento @@ -359,6 +360,7 @@ esphome/components/tee501/* @Stock-M esphome/components/teleinfo/* @0hax esphome/components/template/alarm_control_panel/* @grahambrown11 @hwstar esphome/components/template/datetime/* @rfdarter +esphome/components/template/event/* @nohat esphome/components/template/fan/* @ssieb esphome/components/text/* @mauritskorse esphome/components/thermostat/* @kbx81 diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index 12b7ef0958..17826ea7ed 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -1702,6 +1702,32 @@ message TimeCommandRequest { uint32 second = 4; } +// ==================== EVENT ==================== +message ListEntitiesEventResponse { + option (id) = 107; + option (source) = SOURCE_SERVER; + option (ifdef) = "USE_EVENT"; + + string object_id = 1; + fixed32 key = 2; + string name = 3; + string unique_id = 4; + + string icon = 5; + bool disabled_by_default = 6; + EntityCategory entity_category = 7; + string device_class = 8; + + repeated string event_types = 9; +} +message EventResponse { + option (id) = 108; + option (source) = SOURCE_SERVER; + option (ifdef) = "USE_EVENT"; + + fixed32 key = 1; + string event_type = 2; +} // ==================== VALVE ==================== message ListEntitiesValveResponse { diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 47136fff98..ec09604d95 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1209,6 +1209,30 @@ void APIConnection::alarm_control_panel_command(const AlarmControlPanelCommandRe } #endif +#ifdef USE_EVENT +bool APIConnection::send_event(event::Event *event, std::string event_type) { + EventResponse resp{}; + resp.key = event->get_object_id_hash(); + resp.event_type = std::move(event_type); + return this->send_event_response(resp); +} +bool APIConnection::send_event_info(event::Event *event) { + ListEntitiesEventResponse msg; + msg.key = event->get_object_id_hash(); + msg.object_id = event->get_object_id(); + if (event->has_own_name()) + msg.name = event->get_name(); + msg.unique_id = get_default_unique_id("event", event); + msg.icon = event->get_icon(); + msg.disabled_by_default = event->is_disabled_by_default(); + msg.entity_category = static_cast(event->get_entity_category()); + msg.device_class = event->get_device_class(); + for (const auto &event_type : event->get_event_types()) + msg.event_types.push_back(event_type); + return this->send_list_entities_event_response(msg); +} +#endif + bool APIConnection::send_log_message(int level, const char *tag, const char *line) { if (this->log_subscription_ < level) return false; diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index af2dd9e681..2c1d733d3e 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -153,6 +153,11 @@ class APIConnection : public APIServerConnection { void alarm_control_panel_command(const AlarmControlPanelCommandRequest &msg) override; #endif +#ifdef USE_EVENT + bool send_event(event::Event *event, std::string event_type); + bool send_event_info(event::Event *event); +#endif + void on_disconnect_response(const DisconnectResponse &value) override; void on_ping_response(const PingResponse &value) override { // we initiated ping diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index 508947ba24..3f01d88c58 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -7709,6 +7709,157 @@ void TimeCommandRequest::dump_to(std::string &out) const { out.append("}"); } #endif +bool ListEntitiesEventResponse::decode_varint(uint32_t field_id, ProtoVarInt value) { + switch (field_id) { + case 6: { + this->disabled_by_default = value.as_bool(); + return true; + } + case 7: { + this->entity_category = value.as_enum(); + return true; + } + default: + return false; + } +} +bool ListEntitiesEventResponse::decode_length(uint32_t field_id, ProtoLengthDelimited value) { + switch (field_id) { + case 1: { + this->object_id = value.as_string(); + return true; + } + case 3: { + this->name = value.as_string(); + return true; + } + case 4: { + this->unique_id = value.as_string(); + return true; + } + case 5: { + this->icon = value.as_string(); + return true; + } + case 8: { + this->device_class = value.as_string(); + return true; + } + case 9: { + this->event_types.push_back(value.as_string()); + return true; + } + default: + return false; + } +} +bool ListEntitiesEventResponse::decode_32bit(uint32_t field_id, Proto32Bit value) { + switch (field_id) { + case 2: { + this->key = value.as_fixed32(); + return true; + } + default: + return false; + } +} +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); + buffer.encode_string(4, this->unique_id); + buffer.encode_string(5, this->icon); + buffer.encode_bool(6, this->disabled_by_default); + buffer.encode_enum(7, this->entity_category); + buffer.encode_string(8, this->device_class); + for (auto &it : this->event_types) { + buffer.encode_string(9, it, true); + } +} +#ifdef HAS_PROTO_MESSAGE_DUMP +void ListEntitiesEventResponse::dump_to(std::string &out) const { + __attribute__((unused)) char buffer[64]; + out.append("ListEntitiesEventResponse {\n"); + out.append(" object_id: "); + out.append("'").append(this->object_id).append("'"); + out.append("\n"); + + out.append(" key: "); + sprintf(buffer, "%" PRIu32, this->key); + out.append(buffer); + out.append("\n"); + + out.append(" name: "); + out.append("'").append(this->name).append("'"); + out.append("\n"); + + out.append(" unique_id: "); + out.append("'").append(this->unique_id).append("'"); + out.append("\n"); + + out.append(" icon: "); + out.append("'").append(this->icon).append("'"); + out.append("\n"); + + out.append(" disabled_by_default: "); + out.append(YESNO(this->disabled_by_default)); + out.append("\n"); + + out.append(" entity_category: "); + out.append(proto_enum_to_string(this->entity_category)); + out.append("\n"); + + out.append(" device_class: "); + out.append("'").append(this->device_class).append("'"); + out.append("\n"); + + for (const auto &it : this->event_types) { + out.append(" event_types: "); + out.append("'").append(it).append("'"); + out.append("\n"); + } + out.append("}"); +} +#endif +bool EventResponse::decode_length(uint32_t field_id, ProtoLengthDelimited value) { + switch (field_id) { + case 2: { + this->event_type = value.as_string(); + return true; + } + default: + return false; + } +} +bool EventResponse::decode_32bit(uint32_t field_id, Proto32Bit value) { + switch (field_id) { + case 1: { + this->key = value.as_fixed32(); + return true; + } + default: + return false; + } +} +void EventResponse::encode(ProtoWriteBuffer buffer) const { + buffer.encode_fixed32(1, this->key); + buffer.encode_string(2, this->event_type); +} +#ifdef HAS_PROTO_MESSAGE_DUMP +void EventResponse::dump_to(std::string &out) const { + __attribute__((unused)) char buffer[64]; + out.append("EventResponse {\n"); + out.append(" key: "); + sprintf(buffer, "%" PRIu32, this->key); + out.append(buffer); + out.append("\n"); + + out.append(" event_type: "); + out.append("'").append(this->event_type).append("'"); + out.append("\n"); + out.append("}"); +} +#endif bool ListEntitiesValveResponse::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { case 6: { diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index 950ffcdc88..9a6aab254d 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -1974,6 +1974,40 @@ class TimeCommandRequest : public ProtoMessage { bool decode_32bit(uint32_t field_id, Proto32Bit value) override; bool decode_varint(uint32_t field_id, ProtoVarInt value) override; }; +class ListEntitiesEventResponse : public ProtoMessage { + public: + std::string object_id{}; + uint32_t key{0}; + std::string name{}; + std::string unique_id{}; + std::string icon{}; + bool disabled_by_default{false}; + enums::EntityCategory entity_category{}; + std::string device_class{}; + std::vector event_types{}; + void encode(ProtoWriteBuffer buffer) const override; +#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 EventResponse : public ProtoMessage { + public: + uint32_t key{0}; + std::string event_type{}; + void encode(ProtoWriteBuffer buffer) const override; +#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; +}; class ListEntitiesValveResponse : public ProtoMessage { public: std::string object_id{}; diff --git a/esphome/components/api/api_pb2_service.cpp b/esphome/components/api/api_pb2_service.cpp index 4b8b8cf5ae..ced81fa643 100644 --- a/esphome/components/api/api_pb2_service.cpp +++ b/esphome/components/api/api_pb2_service.cpp @@ -557,6 +557,22 @@ bool APIServerConnectionBase::send_time_state_response(const TimeStateResponse & #endif #ifdef USE_DATETIME_TIME #endif +#ifdef USE_EVENT +bool APIServerConnectionBase::send_list_entities_event_response(const ListEntitiesEventResponse &msg) { +#ifdef HAS_PROTO_MESSAGE_DUMP + ESP_LOGVV(TAG, "send_list_entities_event_response: %s", msg.dump().c_str()); +#endif + return this->send_message_(msg, 107); +} +#endif +#ifdef USE_EVENT +bool APIServerConnectionBase::send_event_response(const EventResponse &msg) { +#ifdef HAS_PROTO_MESSAGE_DUMP + ESP_LOGVV(TAG, "send_event_response: %s", msg.dump().c_str()); +#endif + return this->send_message_(msg, 108); +} +#endif #ifdef USE_VALVE bool APIServerConnectionBase::send_list_entities_valve_response(const ListEntitiesValveResponse &msg) { #ifdef HAS_PROTO_MESSAGE_DUMP diff --git a/esphome/components/api/api_pb2_service.h b/esphome/components/api/api_pb2_service.h index 9f1d711257..c8b2bc5789 100644 --- a/esphome/components/api/api_pb2_service.h +++ b/esphome/components/api/api_pb2_service.h @@ -280,6 +280,12 @@ class APIServerConnectionBase : public ProtoService { #ifdef USE_DATETIME_TIME virtual void on_time_command_request(const TimeCommandRequest &value){}; #endif +#ifdef USE_EVENT + bool send_list_entities_event_response(const ListEntitiesEventResponse &msg); +#endif +#ifdef USE_EVENT + bool send_event_response(const EventResponse &msg); +#endif #ifdef USE_VALVE bool send_list_entities_valve_response(const ListEntitiesValveResponse &msg); #endif diff --git a/esphome/components/api/api_server.cpp b/esphome/components/api/api_server.cpp index 457eeb1229..6d4e4db1e8 100644 --- a/esphome/components/api/api_server.cpp +++ b/esphome/components/api/api_server.cpp @@ -318,6 +318,13 @@ void APIServer::on_media_player_update(media_player::MediaPlayer *obj) { } #endif +#ifdef USE_EVENT +void APIServer::on_event(event::Event *obj, const std::string &event_type) { + for (auto &c : this->clients_) + c->send_event(obj, event_type); +} +#endif + float APIServer::get_setup_priority() const { return setup_priority::AFTER_WIFI; } void APIServer::set_port(uint16_t port) { this->port_ = port; } APIServer *global_api_server = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) diff --git a/esphome/components/api/api_server.h b/esphome/components/api/api_server.h index d64643b961..e9e03cde0d 100644 --- a/esphome/components/api/api_server.h +++ b/esphome/components/api/api_server.h @@ -96,6 +96,9 @@ class APIServer : public Component, public Controller { #ifdef USE_ALARM_CONTROL_PANEL void on_alarm_control_panel_update(alarm_control_panel::AlarmControlPanel *obj) override; #endif +#ifdef USE_EVENT + void on_event(event::Event *obj, const std::string &event_type) override; +#endif bool is_connected() const; diff --git a/esphome/components/api/list_entities.cpp b/esphome/components/api/list_entities.cpp index d6ff8e5557..82bfd45333 100644 --- a/esphome/components/api/list_entities.cpp +++ b/esphome/components/api/list_entities.cpp @@ -89,6 +89,9 @@ bool ListEntitiesIterator::on_alarm_control_panel(alarm_control_panel::AlarmCont return this->client_->send_alarm_control_panel_info(a_alarm_control_panel); } #endif +#ifdef USE_EVENT +bool ListEntitiesIterator::on_event(event::Event *event) { return this->client_->send_event_info(event); } +#endif } // namespace api } // namespace esphome diff --git a/esphome/components/api/list_entities.h b/esphome/components/api/list_entities.h index 5d0c243f4a..19cd99ea01 100644 --- a/esphome/components/api/list_entities.h +++ b/esphome/components/api/list_entities.h @@ -69,6 +69,9 @@ class ListEntitiesIterator : public ComponentIterator { #endif #ifdef USE_ALARM_CONTROL_PANEL bool on_alarm_control_panel(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel) override; +#endif +#ifdef USE_EVENT + bool on_event(event::Event *event) override; #endif bool on_end() override; diff --git a/esphome/components/api/subscribe_state.h b/esphome/components/api/subscribe_state.h index 8d50e0d89a..17d444c441 100644 --- a/esphome/components/api/subscribe_state.h +++ b/esphome/components/api/subscribe_state.h @@ -66,6 +66,9 @@ class InitialStateIterator : public ComponentIterator { #endif #ifdef USE_ALARM_CONTROL_PANEL bool on_alarm_control_panel(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel) override; +#endif +#ifdef USE_EVENT + bool on_event(event::Event *event) override { return true; }; #endif protected: APIConnection *client_; diff --git a/esphome/components/event/__init__.py b/esphome/components/event/__init__.py new file mode 100644 index 0000000000..789f121cf3 --- /dev/null +++ b/esphome/components/event/__init__.py @@ -0,0 +1,134 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome import automation +from esphome.components import mqtt +from esphome.const import ( + CONF_DEVICE_CLASS, + CONF_ENTITY_CATEGORY, + CONF_ICON, + CONF_ID, + CONF_ON_EVENT, + CONF_TRIGGER_ID, + CONF_MQTT_ID, + CONF_EVENT_TYPE, + DEVICE_CLASS_BUTTON, + DEVICE_CLASS_DOORBELL, + DEVICE_CLASS_EMPTY, + DEVICE_CLASS_MOTION, +) +from esphome.core import CORE, coroutine_with_priority +from esphome.cpp_helpers import setup_entity +from esphome.cpp_generator import MockObjClass + +CODEOWNERS = ["@nohat"] +IS_PLATFORM_COMPONENT = True + +DEVICE_CLASSES = [ + DEVICE_CLASS_BUTTON, + DEVICE_CLASS_EMPTY, + DEVICE_CLASS_DOORBELL, + DEVICE_CLASS_MOTION, +] + +event_ns = cg.esphome_ns.namespace("event") +Event = event_ns.class_("Event", cg.EntityBase) +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 = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMPONENT_SCHEMA).extend( + { + 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), + } + ), + } +) + +_UNDEF = object() + + +def event_schema( + class_: MockObjClass = _UNDEF, + *, + icon: str = _UNDEF, + entity_category: str = _UNDEF, + device_class: str = _UNDEF, +) -> cv.Schema: + schema = {} + + if class_ is not _UNDEF: + schema[cv.GenerateID()] = cv.declare_id(class_) + + for key, default, validator in [ + (CONF_ICON, icon, cv.icon), + (CONF_ENTITY_CATEGORY, entity_category, cv.entity_category), + (CONF_DEVICE_CLASS, device_class, validate_device_class), + ]: + if default is not _UNDEF: + schema[cv.Optional(key, default=default)] = validator + + return EVENT_SCHEMA.extend(schema) + + +async def setup_event_core_(var, config, *, event_types: list[str]): + await setup_entity(var, config) + + 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 + ) + + 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)) + + if mqtt_id := config.get(CONF_MQTT_ID): + mqtt_ = cg.new_Pvariable(mqtt_id, var) + await mqtt.register_mqtt_component(mqtt_, config) + + +async def register_event(var, config, *, event_types: list[str]): + if not CORE.has_id(config[CONF_ID]): + var = cg.Pvariable(config[CONF_ID], var) + cg.add(cg.App.register_event(var)) + await setup_event_core_(var, config, event_types=event_types) + + +async def new_event(config, *, event_types: list[str]): + var = cg.new_Pvariable(config[CONF_ID]) + await register_event(var, config, event_types=event_types) + return var + + +TRIGGER_EVENT_SCHEMA = cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(Event), + cv.Required(CONF_EVENT_TYPE): cv.templatable(cv.string_strict), + } +) + + +@automation.register_action("event.trigger", TriggerEventAction, TRIGGER_EVENT_SCHEMA) +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]) + templ = await cg.templatable(config[CONF_EVENT_TYPE], args, cg.std_string) + cg.add(var.set_event_type(templ)) + return var + + +@coroutine_with_priority(100.0) +async def to_code(config): + cg.add_define("USE_EVENT") + cg.add_global(event_ns.using) diff --git a/esphome/components/event/automation.h b/esphome/components/event/automation.h new file mode 100644 index 0000000000..9ebcb654a0 --- /dev/null +++ b/esphome/components/event/automation.h @@ -0,0 +1,25 @@ +#pragma once + +#include "esphome/components/event/event.h" +#include "esphome/core/automation.h" +#include "esphome/core/component.h" + +namespace esphome { +namespace event { + +template class TriggerEventAction : public Action, public Parented { + public: + TEMPLATABLE_VALUE(std::string, event_type) + + void play(Ts... x) override { this->parent_->trigger(this->event_type_.value(x...)); } +}; + +class EventTrigger : public Trigger { + public: + EventTrigger(Event *event) { + event->add_on_event_callback([this](const std::string &event_type) { this->trigger(event_type); }); + } +}; + +} // namespace event +} // namespace esphome diff --git a/esphome/components/event/event.cpp b/esphome/components/event/event.cpp new file mode 100644 index 0000000000..061afcb026 --- /dev/null +++ b/esphome/components/event/event.cpp @@ -0,0 +1,24 @@ +#include "event.h" + +#include "esphome/core/log.h" + +namespace esphome { +namespace event { + +static const char *const TAG = "event"; + +void Event::trigger(const std::string &event_type) { + if (types_.find(event_type) == types_.end()) { + ESP_LOGE(TAG, "'%s': invalid event type for trigger(): %s", this->get_name().c_str(), event_type.c_str()); + return; + } + ESP_LOGD(TAG, "'%s' Triggered event '%s'", this->get_name().c_str(), event_type.c_str()); + this->event_callback_.call(event_type); +} + +void Event::add_on_event_callback(std::function &&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 new file mode 100644 index 0000000000..067a867360 --- /dev/null +++ b/esphome/components/event/event.h @@ -0,0 +1,37 @@ +#pragma once + +#include +#include + +#include "esphome/core/component.h" +#include "esphome/core/entity_base.h" +#include "esphome/core/helpers.h" + +namespace esphome { +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().empty()) { \ + ESP_LOGCONFIG(TAG, "%s Icon: '%s'", prefix, (obj)->get_icon().c_str()); \ + } \ + if (!(obj)->get_device_class().empty()) { \ + ESP_LOGCONFIG(TAG, "%s Device Class: '%s'", prefix, (obj)->get_device_class().c_str()); \ + } \ + } + +class Event : public EntityBase, public EntityBase_DeviceClass { + public: + void trigger(const std::string &event_type); + void set_event_types(const std::set &event_types) { this->types_ = event_types; } + std::set get_event_types() const { return this->types_; } + void add_on_event_callback(std::function &&callback); + + protected: + CallbackManager event_callback_; + std::set types_; +}; + +} // namespace event +} // namespace esphome diff --git a/esphome/components/mqtt/__init__.py b/esphome/components/mqtt/__init__.py index 72ee81dbbc..7a42140ef6 100644 --- a/esphome/components/mqtt/__init__.py +++ b/esphome/components/mqtt/__init__.py @@ -119,6 +119,7 @@ MQTTTextComponent = mqtt_ns.class_("MQTTTextComponent", MQTTComponent) MQTTSelectComponent = mqtt_ns.class_("MQTTSelectComponent", MQTTComponent) MQTTButtonComponent = mqtt_ns.class_("MQTTButtonComponent", MQTTComponent) MQTTLockComponent = mqtt_ns.class_("MQTTLockComponent", MQTTComponent) +MQTTEventComponent = mqtt_ns.class_("MQTTEventComponent", MQTTComponent) MQTTValveComponent = mqtt_ns.class_("MQTTValveComponent", MQTTComponent) MQTTDiscoveryUniqueIdGenerator = mqtt_ns.enum("MQTTDiscoveryUniqueIdGenerator") diff --git a/esphome/components/mqtt/mqtt_const.h b/esphome/components/mqtt/mqtt_const.h index 2209f96e7a..66872680bb 100644 --- a/esphome/components/mqtt/mqtt_const.h +++ b/esphome/components/mqtt/mqtt_const.h @@ -73,6 +73,8 @@ constexpr const char *const MQTT_ENABLED_BY_DEFAULT = "en"; constexpr const char *const MQTT_ENTITY_CATEGORY = "ent_cat"; constexpr const char *const MQTT_ERROR_TEMPLATE = "err_tpl"; constexpr const char *const MQTT_ERROR_TOPIC = "err_t"; +constexpr const char *const MQTT_EVENT_TYPE = "event_type"; +constexpr const char *const MQTT_EVENT_TYPES = "evt_typ"; constexpr const char *const MQTT_EXPIRE_AFTER = "exp_aft"; constexpr const char *const MQTT_FAN_MODE_COMMAND_TEMPLATE = "fan_mode_cmd_tpl"; constexpr const char *const MQTT_FAN_MODE_COMMAND_TOPIC = "fan_mode_cmd_t"; @@ -330,6 +332,8 @@ constexpr const char *const MQTT_ENABLED_BY_DEFAULT = "enabled_by_default"; constexpr const char *const MQTT_ENTITY_CATEGORY = "entity_category"; constexpr const char *const MQTT_ERROR_TEMPLATE = "error_template"; constexpr const char *const MQTT_ERROR_TOPIC = "error_topic"; +constexpr const char *const MQTT_EVENT_TYPE = "event_type"; +constexpr const char *const MQTT_EVENT_TYPES = "event_types"; constexpr const char *const MQTT_EXPIRE_AFTER = "expire_after"; constexpr const char *const MQTT_FAN_MODE_COMMAND_TEMPLATE = "fan_mode_command_template"; constexpr const char *const MQTT_FAN_MODE_COMMAND_TOPIC = "fan_mode_command_topic"; diff --git a/esphome/components/mqtt/mqtt_event.cpp b/esphome/components/mqtt/mqtt_event.cpp new file mode 100644 index 0000000000..cf0b90e3d6 --- /dev/null +++ b/esphome/components/mqtt/mqtt_event.cpp @@ -0,0 +1,54 @@ +#include "mqtt_event.h" +#include "esphome/core/log.h" + +#include "mqtt_const.h" + +#ifdef USE_MQTT +#ifdef USE_EVENT + +namespace esphome { +namespace mqtt { + +static const char *const TAG = "mqtt.event"; + +using namespace esphome::event; + +MQTTEventComponent::MQTTEventComponent(event::Event *event) : event_(event) {} + +void MQTTEventComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { + JsonArray event_types = root.createNestedArray(MQTT_EVENT_TYPES); + for (const auto &event_type : this->event_->get_event_types()) + event_types.add(event_type); + + if (!this->event_->get_device_class().empty()) + root[MQTT_DEVICE_CLASS] = this->event_->get_device_class(); + + config.command_topic = false; +} + +void MQTTEventComponent::setup() { + this->event_->add_on_event_callback([this](const std::string &event_type) { this->publish_event_(event_type); }); +} + +void MQTTEventComponent::dump_config() { + ESP_LOGCONFIG(TAG, "MQTT Event '%s': ", this->event_->get_name().c_str()); + ESP_LOGCONFIG(TAG, "Event Types: "); + for (const auto &event_type : this->event_->get_event_types()) { + ESP_LOGCONFIG(TAG, "- %s", event_type.c_str()); + } + LOG_MQTT_COMPONENT(true, true); +} + +bool MQTTEventComponent::publish_event_(const std::string &event_type) { + return this->publish_json(this->get_state_topic_(), + [event_type](JsonObject root) { root[MQTT_EVENT_TYPE] = event_type; }); +} + +std::string MQTTEventComponent::component_type() const { return "event"; } +const EntityBase *MQTTEventComponent::get_entity() const { return this->event_; } + +} // namespace mqtt +} // namespace esphome + +#endif +#endif // USE_MQTT diff --git a/esphome/components/mqtt/mqtt_event.h b/esphome/components/mqtt/mqtt_event.h new file mode 100644 index 0000000000..4335820e53 --- /dev/null +++ b/esphome/components/mqtt/mqtt_event.h @@ -0,0 +1,39 @@ +#pragma once + +#include "esphome/core/defines.h" + +#ifdef USE_MQTT +#ifdef USE_EVENT + +#include "esphome/components/event/event.h" +#include "mqtt_component.h" + +namespace esphome { +namespace mqtt { + +class MQTTEventComponent : public mqtt::MQTTComponent { + public: + explicit MQTTEventComponent(event::Event *event); + + void send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) override; + + void setup() override; + + void dump_config() override; + + /// Events do not send a state so just return true. + bool send_initial_state() override { return true; } + + protected: + bool publish_event_(const std::string &event_type); + std::string component_type() const override; + const EntityBase *get_entity() const override; + + event::Event *event_; +}; + +} // namespace mqtt +} // namespace esphome + +#endif +#endif // USE_MQTT diff --git a/esphome/components/template/event/__init__.py b/esphome/components/template/event/__init__.py new file mode 100644 index 0000000000..2a948cfdfd --- /dev/null +++ b/esphome/components/template/event/__init__.py @@ -0,0 +1,24 @@ +import esphome.config_validation as cv + +from esphome.components import event + +import esphome.codegen as cg + +from esphome.const import CONF_EVENT_TYPES + +from .. import template_ns + +CODEOWNERS = ["@nohat"] + +TemplateEvent = template_ns.class_("TemplateEvent", event.Event, cg.Component) + +CONFIG_SCHEMA = event.event_schema(TemplateEvent).extend( + { + cv.Required(CONF_EVENT_TYPES): cv.ensure_list(cv.string_strict), + } +) + + +async def to_code(config): + var = await event.new_event(config, event_types=config[CONF_EVENT_TYPES]) + await cg.register_component(var, config) diff --git a/esphome/components/template/event/template_event.h b/esphome/components/template/event/template_event.h new file mode 100644 index 0000000000..251ae9299b --- /dev/null +++ b/esphome/components/template/event/template_event.h @@ -0,0 +1,12 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/components/event/event.h" + +namespace esphome { +namespace template_ { + +class TemplateEvent : public Component, public event::Event {}; + +} // namespace template_ +} // namespace esphome diff --git a/esphome/components/web_server/list_entities.cpp b/esphome/components/web_server/list_entities.cpp index 13e396dc82..8d08783c8c 100644 --- a/esphome/components/web_server/list_entities.cpp +++ b/esphome/components/web_server/list_entities.cpp @@ -159,5 +159,14 @@ bool ListEntitiesIterator::on_alarm_control_panel(alarm_control_panel::AlarmCont } #endif +#ifdef USE_EVENT +bool ListEntitiesIterator::on_event(event::Event *event) { + // Null event type, since we are just iterating over entities + const std::string null_event_type = ""; + this->web_server_->events_.send(this->web_server_->event_json(event, null_event_type, DETAIL_ALL).c_str(), "state"); + return true; +} +#endif + } // namespace web_server } // namespace esphome diff --git a/esphome/components/web_server/list_entities.h b/esphome/components/web_server/list_entities.h index d0b8dda233..af84cb1d2b 100644 --- a/esphome/components/web_server/list_entities.h +++ b/esphome/components/web_server/list_entities.h @@ -62,6 +62,9 @@ class ListEntitiesIterator : public ComponentIterator { #ifdef USE_ALARM_CONTROL_PANEL bool on_alarm_control_panel(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel) override; #endif +#ifdef USE_EVENT + bool on_event(event::Event *event) override; +#endif protected: WebServer *web_server_; diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index 412f8816ee..0202038ffc 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -1352,6 +1352,28 @@ void WebServer::handle_alarm_control_panel_request(AsyncWebServerRequest *reques } #endif +#ifdef USE_EVENT +void WebServer::on_event(event::Event *obj, const std::string &event_type) { + this->events_.send(this->event_json(obj, event_type, DETAIL_STATE).c_str(), "state"); +} + +std::string WebServer::event_json(event::Event *obj, const std::string &event_type, JsonDetail start_config) { + return json::build_json([obj, event_type, start_config](JsonObject root) { + set_json_id(root, obj, "event-" + obj->get_object_id(), start_config); + if (!event_type.empty()) { + root["event_type"] = event_type; + } + if (start_config == DETAIL_ALL) { + JsonArray event_types = root.createNestedArray("event_types"); + for (auto const &event_type : obj->get_event_types()) { + event_types.add(event_type); + } + root["device_class"] = obj->get_device_class(); + } + }); +} +#endif + bool WebServer::canHandle(AsyncWebServerRequest *request) { if (request->url() == "/") return true; diff --git a/esphome/components/web_server/web_server.h b/esphome/components/web_server/web_server.h index 9f807efc43..5e8f3f8236 100644 --- a/esphome/components/web_server/web_server.h +++ b/esphome/components/web_server/web_server.h @@ -297,6 +297,13 @@ class WebServer : public Controller, public Component, public AsyncWebHandler { alarm_control_panel::AlarmControlPanelState value, JsonDetail start_config); #endif +#ifdef USE_EVENT + void on_event(event::Event *obj, const std::string &event_type) override; + + /// Dump the event details with its value as a JSON string. + std::string event_json(event::Event *obj, const std::string &event_type, JsonDetail start_config); +#endif + /// Override the web handler's canHandle method. bool canHandle(AsyncWebServerRequest *request) override; /// Override the web handler's handleRequest method. diff --git a/esphome/const.py b/esphome/const.py index 8410d36708..dfb7fe464c 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -251,6 +251,8 @@ CONF_ESP8266_DISABLE_SSL_SUPPORT = "esp8266_disable_ssl_support" CONF_ESPHOME = "esphome" CONF_ETHERNET = "ethernet" CONF_EVENT = "event" +CONF_EVENT_TYPE = "event_type" +CONF_EVENT_TYPES = "event_types" CONF_EXPIRE_AFTER = "expire_after" CONF_EXPORT_ACTIVE_ENERGY = "export_active_energy" CONF_EXPORT_REACTIVE_ENERGY = "export_reactive_energy" @@ -517,6 +519,7 @@ CONF_ON_DOUBLE_CLICK = "on_double_click" CONF_ON_ENROLLMENT_DONE = "on_enrollment_done" CONF_ON_ENROLLMENT_FAILED = "on_enrollment_failed" CONF_ON_ENROLLMENT_SCAN = "on_enrollment_scan" +CONF_ON_EVENT = "on_event" CONF_ON_FINGER_SCAN_INVALID = "on_finger_scan_invalid" CONF_ON_FINGER_SCAN_MATCHED = "on_finger_scan_matched" CONF_ON_FINGER_SCAN_MISPLACED = "on_finger_scan_misplaced" @@ -1024,6 +1027,7 @@ DEVICE_CLASS_AWNING = "awning" DEVICE_CLASS_BATTERY = "battery" DEVICE_CLASS_BATTERY_CHARGING = "battery_charging" DEVICE_CLASS_BLIND = "blind" +DEVICE_CLASS_BUTTON = "button" DEVICE_CLASS_CARBON_DIOXIDE = "carbon_dioxide" DEVICE_CLASS_CARBON_MONOXIDE = "carbon_monoxide" DEVICE_CLASS_COLD = "cold" @@ -1036,6 +1040,7 @@ DEVICE_CLASS_DATA_SIZE = "data_size" DEVICE_CLASS_DATE = "date" DEVICE_CLASS_DISTANCE = "distance" DEVICE_CLASS_DOOR = "door" +DEVICE_CLASS_DOORBELL = "doorbell" DEVICE_CLASS_DURATION = "duration" DEVICE_CLASS_EMPTY = "" DEVICE_CLASS_ENERGY = "energy" diff --git a/esphome/core/application.h b/esphome/core/application.h index ee931282a6..35df350ec3 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -63,6 +63,9 @@ #ifdef USE_ALARM_CONTROL_PANEL #include "esphome/components/alarm_control_panel/alarm_control_panel.h" #endif +#ifdef USE_EVENT +#include "esphome/components/event/event.h" +#endif namespace esphome { @@ -164,6 +167,10 @@ class Application { } #endif +#ifdef USE_EVENT + void register_event(event::Event *event) { this->events_.push_back(event); } +#endif + /// Register the component in this Application instance. template C *register_component(C *c) { static_assert(std::is_base_of::value, "Only Component subclasses can be registered"); @@ -386,6 +393,16 @@ class Application { } #endif +#ifdef USE_EVENT + const std::vector &get_events() { return this->events_; } + event::Event *get_event_by_key(uint32_t key, bool include_internal = false) { + for (auto *obj : this->events_) + if (obj->get_object_id_hash() == key && (include_internal || !obj->is_internal())) + return obj; + return nullptr; + } +#endif + Scheduler scheduler; protected: @@ -409,6 +426,9 @@ class Application { #ifdef USE_BUTTON std::vector buttons_{}; #endif +#ifdef USE_EVENT + std::vector events_{}; +#endif #ifdef USE_SENSOR std::vector sensors_{}; #endif diff --git a/esphome/core/component_iterator.cpp b/esphome/core/component_iterator.cpp index b00154c685..687f1f6e23 100644 --- a/esphome/core/component_iterator.cpp +++ b/esphome/core/component_iterator.cpp @@ -321,6 +321,21 @@ void ComponentIterator::advance() { } } break; +#endif +#ifdef USE_EVENT + case IteratorState::EVENT: + if (this->at_ >= App.get_events().size()) { + advance_platform = true; + } else { + auto *event = App.get_events()[this->at_]; + if (event->is_internal() && !this->include_internal_) { + success = true; + break; + } else { + success = this->on_event(event); + } + } + break; #endif case IteratorState::MAX: if (this->on_end()) { diff --git a/esphome/core/component_iterator.h b/esphome/core/component_iterator.h index 3fbbc0bc19..8f0398cbb3 100644 --- a/esphome/core/component_iterator.h +++ b/esphome/core/component_iterator.h @@ -80,6 +80,9 @@ class ComponentIterator { #endif #ifdef USE_ALARM_CONTROL_PANEL virtual bool on_alarm_control_panel(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel) = 0; +#endif +#ifdef USE_EVENT + virtual bool on_event(event::Event *event) = 0; #endif virtual bool on_end(); @@ -146,6 +149,9 @@ class ComponentIterator { #endif #ifdef USE_ALARM_CONTROL_PANEL ALARM_CONTROL_PANEL, +#endif +#ifdef USE_EVENT + EVENT, #endif MAX, } state_{IteratorState::NONE}; diff --git a/esphome/core/controller.cpp b/esphome/core/controller.cpp index eab818bdb4..eb975eaf6f 100644 --- a/esphome/core/controller.cpp +++ b/esphome/core/controller.cpp @@ -109,6 +109,12 @@ void Controller::setup_controller(bool include_internal) { obj->add_on_state_callback([this, obj]() { this->on_alarm_control_panel_update(obj); }); } #endif +#ifdef USE_EVENT + for (auto *obj : App.get_events()) { + if (include_internal || !obj->is_internal()) + obj->add_on_event_callback([this, obj](const std::string &event_type) { this->on_event(obj, event_type); }); + } +#endif } } // namespace esphome diff --git a/esphome/core/controller.h b/esphome/core/controller.h index 94a4acb7c7..da9dbc00a6 100644 --- a/esphome/core/controller.h +++ b/esphome/core/controller.h @@ -55,6 +55,9 @@ #ifdef USE_ALARM_CONTROL_PANEL #include "esphome/components/alarm_control_panel/alarm_control_panel.h" #endif +#ifdef USE_EVENT +#include "esphome/components/event/event.h" +#endif namespace esphome { @@ -112,6 +115,9 @@ class Controller { #ifdef USE_ALARM_CONTROL_PANEL virtual void on_alarm_control_panel_update(alarm_control_panel::AlarmControlPanel *obj){}; #endif +#ifdef USE_EVENT + virtual void on_event(event::Event *obj, const std::string &event_type){}; +#endif }; } // namespace esphome diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 2064ca1356..fed73098d2 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -24,6 +24,7 @@ #define USE_CLIMATE #define USE_COVER #define USE_DEEP_SLEEP +#define USE_EVENT #define USE_FAN #define USE_GRAPH #define USE_HOMEASSISTANT_TIME diff --git a/script/ci-custom.py b/script/ci-custom.py index c591bfe5c3..27fcd480f5 100755 --- a/script/ci-custom.py +++ b/script/ci-custom.py @@ -624,6 +624,7 @@ def lint_trailing_whitespace(fname, match): "esphome/components/datetime/date_entity.h", "esphome/components/datetime/time_entity.h", "esphome/components/display/display.h", + "esphome/components/event/event.h", "esphome/components/fan/fan.h", "esphome/components/i2c/i2c.h", "esphome/components/lock/lock.h", diff --git a/tests/components/event/test.esp32-c3-idf.yaml b/tests/components/event/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..71cc19a6b0 --- /dev/null +++ b/tests/components/event/test.esp32-c3-idf.yaml @@ -0,0 +1,9 @@ +event: + - platform: template + name: Event + id: some_event + event_types: + - template_event_type1 + - template_event_type2 + on_event: + - logger.log: Event fired diff --git a/tests/components/event/test.esp32-c3.yaml b/tests/components/event/test.esp32-c3.yaml new file mode 100644 index 0000000000..71cc19a6b0 --- /dev/null +++ b/tests/components/event/test.esp32-c3.yaml @@ -0,0 +1,9 @@ +event: + - platform: template + name: Event + id: some_event + event_types: + - template_event_type1 + - template_event_type2 + on_event: + - logger.log: Event fired diff --git a/tests/components/event/test.esp32-idf.yaml b/tests/components/event/test.esp32-idf.yaml new file mode 100644 index 0000000000..71cc19a6b0 --- /dev/null +++ b/tests/components/event/test.esp32-idf.yaml @@ -0,0 +1,9 @@ +event: + - platform: template + name: Event + id: some_event + event_types: + - template_event_type1 + - template_event_type2 + on_event: + - logger.log: Event fired diff --git a/tests/components/event/test.esp32.yaml b/tests/components/event/test.esp32.yaml new file mode 100644 index 0000000000..71cc19a6b0 --- /dev/null +++ b/tests/components/event/test.esp32.yaml @@ -0,0 +1,9 @@ +event: + - platform: template + name: Event + id: some_event + event_types: + - template_event_type1 + - template_event_type2 + on_event: + - logger.log: Event fired diff --git a/tests/components/event/test.esp8266.yaml b/tests/components/event/test.esp8266.yaml new file mode 100644 index 0000000000..71cc19a6b0 --- /dev/null +++ b/tests/components/event/test.esp8266.yaml @@ -0,0 +1,9 @@ +event: + - platform: template + name: Event + id: some_event + event_types: + - template_event_type1 + - template_event_type2 + on_event: + - logger.log: Event fired diff --git a/tests/components/event/test.rp2040.yaml b/tests/components/event/test.rp2040.yaml new file mode 100644 index 0000000000..71cc19a6b0 --- /dev/null +++ b/tests/components/event/test.rp2040.yaml @@ -0,0 +1,9 @@ +event: + - platform: template + name: Event + id: some_event + event_types: + - template_event_type1 + - template_event_type2 + on_event: + - logger.log: Event fired From 1ac855f2e0d38564678ffddeb4a8182e2fea5721 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 24 Apr 2024 14:49:16 +1200 Subject: [PATCH 1322/2101] Only check c/c++ files with clang-format (#6620) --- .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 15e59b7eb7..6f4bb52104 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -39,4 +39,4 @@ repos: rev: v13.0.1 hooks: - id: clang-format - + types_or: [c, c++] From a7079f8fba599da736a033885dcb112f2dc8ee05 Mon Sep 17 00:00:00 2001 From: Evgeny Date: Wed, 24 Apr 2024 05:07:07 +0200 Subject: [PATCH 1323/2101] Added base64 helper (#4866) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/core/helpers.cpp | 97 ++++++++++++++++++++++++++++++++++++++++ esphome/core/helpers.h | 10 +++++ 2 files changed, 107 insertions(+) diff --git a/esphome/core/helpers.cpp b/esphome/core/helpers.cpp index 0f7afc6a4e..4368576301 100644 --- a/esphome/core/helpers.cpp +++ b/esphome/core/helpers.cpp @@ -433,6 +433,103 @@ int8_t step_to_accuracy_decimals(float step) { return str.length() - dot_pos - 1; } +static inline bool is_base64(char c) { return (isalnum(c) || (c == '+') || (c == '/')); } + +std::string base64_encode(const std::vector &buf) { return base64_encode(buf.data(), buf.size()); } + +std::string base64_encode(const char *buf, unsigned int 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[char_array_4[i]]; + i = 0; + } + } + + if (i) { + for (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[char_array_4[j]]; + + while ((i++ < 3)) + ret += '='; + } + + return ret; +} + +size_t base64_decode(const std::string &encoded_string, uint8_t *buf, size_t buf_len) { + std::vector decoded = base64_decode(encoded_string); + if (decoded.size() > buf_len) { + ESP_LOGW(TAG, "Base64 decode: buffer too small, truncating"); + decoded.resize(buf_len); + } + memcpy(buf, decoded.data(), decoded.size()); + return decoded.size(); +} + +std::vector base64_decode(const std::string &encoded_string) { + int in_len = encoded_string.size(); + int i = 0; + int j = 0; + int in = 0; + uint8_t char_array_4[4], char_array_3[3]; + std::vector ret; + + while (in_len-- && (encoded_string[in] != '=') && is_base64(encoded_string[in])) { + char_array_4[i++] = encoded_string[in]; + in++; + if (i == 4) { + for (i = 0; i < 4; i++) + char_array_4[i] = BASE64_CHARS.find(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++) + ret.push_back(char_array_3[i]); + i = 0; + } + } + + if (i) { + for (j = i; j < 4; j++) + char_array_4[j] = 0; + + for (j = 0; j < 4; j++) + char_array_4[j] = BASE64_CHARS.find(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++) + ret.push_back(char_array_3[j]); + } + + return ret; +} + // Colors float gamma_correct(float value, float gamma) { diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index c3ed443bf0..b2d72b0fab 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -435,6 +435,16 @@ std::string value_accuracy_to_string(float value, int8_t accuracy_decimals); /// Derive accuracy in decimals from an increment step. int8_t step_to_accuracy_decimals(float step); +static const std::string BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + +std::string base64_encode(const uint8_t *buf, size_t buf_len); +std::string base64_encode(const std::vector &buf); + +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); + ///@} /// @name Colors From e2b0d561bc02c9b9707cb06aeae46bba522145a7 Mon Sep 17 00:00:00 2001 From: rforro Date: Wed, 24 Apr 2024 05:21:08 +0200 Subject: [PATCH 1324/2101] Add Roomba IR protocol (#4595) Co-authored-by: Richard Forro Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/remote_base/__init__.py | 39 +++++++++++++ .../remote_base/roomba_protocol.cpp | 56 +++++++++++++++++++ .../components/remote_base/roomba_protocol.h | 35 ++++++++++++ 3 files changed, 130 insertions(+) create mode 100644 esphome/components/remote_base/roomba_protocol.cpp create mode 100644 esphome/components/remote_base/roomba_protocol.h diff --git a/esphome/components/remote_base/__init__.py b/esphome/components/remote_base/__init__.py index 6deab63c60..8a1d50d1c6 100644 --- a/esphome/components/remote_base/__init__.py +++ b/esphome/components/remote_base/__init__.py @@ -881,6 +881,45 @@ async def pronto_action(var, config, args): cg.add(var.set_data(template_)) +# Roomba +( + RoombaData, + RoombaBinarySensor, + RoombaTrigger, + RoombaAction, + RoombaDumper, +) = declare_protocol("Roomba") +ROOMBA_SCHEMA = cv.Schema({cv.Required(CONF_DATA): cv.hex_uint8_t}) + + +@register_binary_sensor("roomba", RoombaBinarySensor, ROOMBA_SCHEMA) +def roomba_binary_sensor(var, config): + cg.add( + var.set_data( + cg.StructInitializer( + RoombaData, + ("data", config[CONF_DATA]), + ) + ) + ) + + +@register_trigger("roomba", RoombaTrigger, RoombaData) +def roomba_trigger(var, config): + pass + + +@register_dumper("roomba", RoombaDumper) +def roomba_dumper(var, config): + pass + + +@register_action("roomba", RoombaAction, ROOMBA_SCHEMA) +async def roomba_action(var, config, args): + template_ = await cg.templatable(config[CONF_DATA], args, cg.uint8) + cg.add(var.set_data(template_)) + + # Sony SonyData, SonyBinarySensor, SonyTrigger, SonyAction, SonyDumper = declare_protocol( "Sony" diff --git a/esphome/components/remote_base/roomba_protocol.cpp b/esphome/components/remote_base/roomba_protocol.cpp new file mode 100644 index 0000000000..2d2dde114a --- /dev/null +++ b/esphome/components/remote_base/roomba_protocol.cpp @@ -0,0 +1,56 @@ +#include "roomba_protocol.h" +#include "esphome/core/log.h" + +namespace esphome { +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; + +void RoombaProtocol::encode(RemoteTransmitData *dst, const RoombaData &data) { + dst->set_carrier_frequency(38000); + dst->reserve(NBITS * 2u); + + for (uint32_t mask = 1UL << (NBITS - 1); mask != 0; mask >>= 1) { + if (data.data & mask) { + dst->item(BIT_ONE_HIGH_US, BIT_ONE_LOW_US); + } else { + dst->item(BIT_ZERO_HIGH_US, BIT_ZERO_LOW_US); + } + } +} +optional RoombaProtocol::decode(RemoteReceiveData src) { + RoombaData out{.data = 0}; + + for (uint8_t i = 0; i < (NBITS - 1); i++) { + out.data <<= 1UL; + if (src.expect_item(BIT_ONE_HIGH_US, BIT_ONE_LOW_US)) { + out.data |= 1UL; + } else if (src.expect_item(BIT_ZERO_HIGH_US, BIT_ZERO_LOW_US)) { + out.data |= 0UL; + } else { + return {}; + } + } + + // not possible to measure space on last bit, check only mark + out.data <<= 1UL; + if (src.expect_mark(BIT_ONE_HIGH_US)) { + out.data |= 1UL; + } else if (src.expect_mark(BIT_ZERO_HIGH_US)) { + out.data |= 0UL; + } else { + return {}; + } + + return out; +} +void RoombaProtocol::dump(const RoombaData &data) { ESP_LOGD(TAG, "Received Roomba: data=0x%02X", data.data); } + +} // namespace remote_base +} // namespace esphome diff --git a/esphome/components/remote_base/roomba_protocol.h b/esphome/components/remote_base/roomba_protocol.h new file mode 100644 index 0000000000..f94cb7df1b --- /dev/null +++ b/esphome/components/remote_base/roomba_protocol.h @@ -0,0 +1,35 @@ +#pragma once + +#include "remote_base.h" + +namespace esphome { +namespace remote_base { + +struct RoombaData { + uint8_t data; + + bool operator==(const RoombaData &rhs) const { return data == rhs.data; } +}; + +class RoombaProtocol : public RemoteProtocol { + public: + void encode(RemoteTransmitData *dst, const RoombaData &data) override; + optional decode(RemoteReceiveData src) override; + void dump(const RoombaData &data) override; +}; + +DECLARE_REMOTE_PROTOCOL(Roomba) + +template class RoombaAction : public RemoteTransmitterActionBase { + public: + TEMPLATABLE_VALUE(uint8_t, data) + + void encode(RemoteTransmitData *dst, Ts... x) override { + RoombaData data{}; + data.data = this->data_.value(x...); + RoombaProtocol().encode(dst, data); + } +}; + +} // namespace remote_base +} // namespace esphome From 1775c73e53f991194fdb318022ece516255c5ce6 Mon Sep 17 00:00:00 2001 From: Patrick Date: Wed, 24 Apr 2024 05:56:56 +0200 Subject: [PATCH 1325/2101] Fix issue when setting cw/ww brightness via temperature (#5976) --- esphome/components/light/light_call.cpp | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/esphome/components/light/light_call.cpp b/esphome/components/light/light_call.cpp index 8dc5d4fbe7..c2600d05c2 100644 --- a/esphome/components/light/light_call.cpp +++ b/esphome/components/light/light_call.cpp @@ -337,9 +337,12 @@ LightColorValues LightCall::validate_() { void LightCall::transform_parameters_() { auto traits = this->parent_->get_traits(); - // Allow CWWW modes to be set with a white value and/or color temperature. This is used by HA, - // which doesn't support CWWW modes (yet?), and for compatibility with the pre-colormode model, - // as CWWW and RGBWW lights used to represent their values as white + color temperature. + // 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" + // - RGBWW lights with color_interlock=true, which also sets "brightness" and + // "color_temperature" (without color_interlock, CW/WW are set directly) + // - Legacy Home Assistant (pre-colormode), which sets "white" and "color_temperature" if (((this->white_.has_value() && *this->white_ > 0.0f) || this->color_temperature_.has_value()) && // (*this->color_mode_ & ColorCapability::COLD_WARM_WHITE) && // !(*this->color_mode_ & ColorCapability::WHITE) && // @@ -347,21 +350,17 @@ void LightCall::transform_parameters_() { traits.get_min_mireds() > 0.0f && traits.get_max_mireds() > 0.0f) { ESP_LOGD(TAG, "'%s' - Setting cold/warm white channels using white/color temperature values.", this->parent_->get_name().c_str()); - auto current_values = this->parent_->remote_values; if (this->color_temperature_.has_value()) { - const float white = - this->white_.value_or(fmaxf(current_values.get_cold_white(), current_values.get_warm_white())); const float color_temp = clamp(*this->color_temperature_, traits.get_min_mireds(), traits.get_max_mireds()); const float ww_fraction = (color_temp - traits.get_min_mireds()) / (traits.get_max_mireds() - traits.get_min_mireds()); const float cw_fraction = 1.0f - ww_fraction; const float max_cw_ww = std::max(ww_fraction, cw_fraction); - this->cold_white_ = white * gamma_uncorrect(cw_fraction / max_cw_ww, this->parent_->get_gamma_correct()); - this->warm_white_ = white * gamma_uncorrect(ww_fraction / max_cw_ww, this->parent_->get_gamma_correct()); - } else { - const float max_cw_ww = std::max(current_values.get_warm_white(), current_values.get_cold_white()); - this->cold_white_ = *this->white_ * current_values.get_cold_white() / max_cw_ww; - this->warm_white_ = *this->white_ * current_values.get_warm_white() / max_cw_ww; + this->cold_white_ = gamma_uncorrect(cw_fraction / max_cw_ww, this->parent_->get_gamma_correct()); + this->warm_white_ = gamma_uncorrect(ww_fraction / max_cw_ww, this->parent_->get_gamma_correct()); + } + if (this->white_.has_value()) { + this->brightness_ = *this->white_; } } } From 41b19504bc8490e318f3e35bb7e10386fd44ab0b Mon Sep 17 00:00:00 2001 From: Daniel Kent <129895318+danielkent-net@users.noreply.github.com> Date: Wed, 24 Apr 2024 00:18:54 -0400 Subject: [PATCH 1326/2101] Add get/set color temperature functions in Kelvin (#5006) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/light/light_color_values.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/esphome/components/light/light_color_values.h b/esphome/components/light/light_color_values.h index 10a3c2f335..bad180ce6d 100644 --- a/esphome/components/light/light_color_values.h +++ b/esphome/components/light/light_color_values.h @@ -266,6 +266,21 @@ class LightColorValues { /// Set the color temperature property of these light color values in mired. void set_color_temperature(float color_temperature) { this->color_temperature_ = color_temperature; } + /// Get the color temperature property of these light color values in kelvin. + float get_color_temperature_kelvin() const { + if (this->color_temperature_ <= 0) { + return this->color_temperature_; + } + return 1000000.0 / this->color_temperature_; + } + /// Set the color temperature property of these light color values in kelvin. + void set_color_temperature_kelvin(float color_temperature) { + if (color_temperature <= 0) { + return; + } + this->color_temperature_ = 1000000.0 / color_temperature; + } + /// Get the cold white property of these light color values. In range 0.0 to 1.0. float get_cold_white() const { return this->cold_white_; } /// Set the cold white property of these light color values. In range 0.0 to 1.0. From bdc9c66f7e781d431cc507393877944313b80046 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Thu, 25 Apr 2024 11:50:41 +0200 Subject: [PATCH 1327/2101] Move CONF_PLATFORM_VERSION to global const.py (#6629) * remove duplicated definition * format --- esphome/components/esp32/__init__.py | 3 +-- esphome/components/esp8266/__init__.py | 2 +- esphome/components/rp2040/__init__.py | 3 +-- esphome/const.py | 1 + 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 8ae6262f2f..5d74838daa 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -32,6 +32,7 @@ from esphome.const import ( TYPE_GIT, TYPE_LOCAL, __version__, + CONF_PLATFORM_VERSION, ) from esphome.core import CORE, HexInt, TimePeriod import esphome.config_validation as cv @@ -365,8 +366,6 @@ def final_validate(config): return config -CONF_PLATFORM_VERSION = "platform_version" - ARDUINO_FRAMEWORK_SCHEMA = cv.All( cv.Schema( { diff --git a/esphome/components/esp8266/__init__.py b/esphome/components/esp8266/__init__.py index 00729921a3..64b127bda3 100644 --- a/esphome/components/esp8266/__init__.py +++ b/esphome/components/esp8266/__init__.py @@ -12,6 +12,7 @@ from esphome.const import ( KEY_TARGET_FRAMEWORK, KEY_TARGET_PLATFORM, PLATFORM_ESP8266, + CONF_PLATFORM_VERSION, ) from esphome.core import CORE, coroutine_with_priority import esphome.config_validation as cv @@ -146,7 +147,6 @@ def _parse_platform_version(value): return value -CONF_PLATFORM_VERSION = "platform_version" ARDUINO_FRAMEWORK_SCHEMA = cv.All( cv.Schema( { diff --git a/esphome/components/rp2040/__init__.py b/esphome/components/rp2040/__init__.py index b262a068fb..ace455add7 100644 --- a/esphome/components/rp2040/__init__.py +++ b/esphome/components/rp2040/__init__.py @@ -15,6 +15,7 @@ from esphome.const import ( KEY_TARGET_FRAMEWORK, KEY_TARGET_PLATFORM, PLATFORM_RP2040, + CONF_PLATFORM_VERSION, ) from esphome.core import CORE, coroutine_with_priority, EsphomeError from esphome.helpers import mkdir_p, write_file, copy_file_if_changed @@ -125,8 +126,6 @@ def _parse_platform_version(value): return value -CONF_PLATFORM_VERSION = "platform_version" - ARDUINO_FRAMEWORK_SCHEMA = cv.All( cv.Schema( { diff --git a/esphome/const.py b/esphome/const.py index dfb7fe464c..a64bc73f59 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -597,6 +597,7 @@ CONF_PIN_D = "pin_d" CONF_PINS = "pins" CONF_PIXEL_MAPPER = "pixel_mapper" CONF_PLATFORM = "platform" +CONF_PLATFORM_VERSION = "platform_version" CONF_PLATFORMIO_OPTIONS = "platformio_options" CONF_PM_0_3UM = "pm_0_3um" CONF_PM_0_5UM = "pm_0_5um" From 2fa58468939b1319b072f7fc3f123dcc1f916605 Mon Sep 17 00:00:00 2001 From: Joakim Plate Date: Thu, 25 Apr 2024 12:05:30 +0200 Subject: [PATCH 1328/2101] Ble client fixes for proxy (#6596) --- esphome/components/alpha3/alpha3.cpp | 8 +++-- .../components/am43/sensor/am43_sensor.cpp | 4 ++- .../bluetooth_proxy/bluetooth_connection.cpp | 33 +++++-------------- .../esp32_ble_client/ble_client_base.cpp | 2 +- .../display/pvvx_display.cpp | 6 ++-- 5 files changed, 21 insertions(+), 32 deletions(-) diff --git a/esphome/components/alpha3/alpha3.cpp b/esphome/components/alpha3/alpha3.cpp index 17899c31cb..344f2d5a03 100644 --- a/esphome/components/alpha3/alpha3.cpp +++ b/esphome/components/alpha3/alpha3.cpp @@ -97,9 +97,11 @@ void Alpha3::handle_geni_response_(const uint8_t *response, uint16_t length) { void Alpha3::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param) { switch (event) { case ESP_GATTC_OPEN_EVT: { - this->response_offset_ = 0; - this->response_length_ = 0; - ESP_LOGI(TAG, "[%s] connection open", this->parent_->address_str().c_str()); + if (param->open.status == ESP_GATT_OK) { + this->response_offset_ = 0; + this->response_length_ = 0; + ESP_LOGI(TAG, "[%s] connection open", this->parent_->address_str().c_str()); + } break; } case ESP_GATTC_CONNECT_EVT: { diff --git a/esphome/components/am43/sensor/am43_sensor.cpp b/esphome/components/am43/sensor/am43_sensor.cpp index 008c7768ed..4cc99001ae 100644 --- a/esphome/components/am43/sensor/am43_sensor.cpp +++ b/esphome/components/am43/sensor/am43_sensor.cpp @@ -26,7 +26,9 @@ void Am43::setup() { void Am43::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param) { switch (event) { case ESP_GATTC_OPEN_EVT: { - this->logged_in_ = false; + if (param->open.status == ESP_GATT_OK) { + this->logged_in_ = false; + } break; } case ESP_GATTC_DISCONNECT_EVT: { diff --git a/esphome/components/bluetooth_proxy/bluetooth_connection.cpp b/esphome/components/bluetooth_proxy/bluetooth_connection.cpp index 97a25262cb..543752853e 100644 --- a/esphome/components/bluetooth_proxy/bluetooth_connection.cpp +++ b/esphome/components/bluetooth_proxy/bluetooth_connection.cpp @@ -25,9 +25,13 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga this->proxy_->send_connections_free(); break; } + case ESP_GATTC_CLOSE_EVT: { + this->proxy_->send_device_connection(this->address_, false, 0, param->close.reason); + this->set_address(0); + this->proxy_->send_connections_free(); + break; + } case ESP_GATTC_OPEN_EVT: { - if (param->open.conn_id != this->conn_id_) - break; if (param->open.status != ESP_GATT_OK && param->open.status != ESP_GATT_ALREADY_OPEN) { this->proxy_->send_device_connection(this->address_, false, 0, param->open.status); this->set_address(0); @@ -39,9 +43,8 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga this->seen_mtu_or_services_ = false; break; } - case ESP_GATTC_CFG_MTU_EVT: { - if (param->cfg_mtu.conn_id != this->conn_id_) - break; + case ESP_GATTC_CFG_MTU_EVT: + case ESP_GATTC_SEARCH_CMPL_EVT: { if (!this->seen_mtu_or_services_) { // We don't know if we will get the MTU or the services first, so // only send the device connection true if we have already received @@ -53,24 +56,8 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga this->proxy_->send_connections_free(); break; } - case ESP_GATTC_SEARCH_CMPL_EVT: { - if (param->search_cmpl.conn_id != this->conn_id_) - break; - if (!this->seen_mtu_or_services_) { - // We don't know if we will get the MTU or the services first, so - // only send the device connection true if we have already received - // the mtu. - this->seen_mtu_or_services_ = true; - break; - } - this->proxy_->send_device_connection(this->address_, true, this->mtu_); - this->proxy_->send_connections_free(); - break; - } case ESP_GATTC_READ_DESCR_EVT: case ESP_GATTC_READ_CHAR_EVT: { - if (param->read.conn_id != this->conn_id_) - break; if (param->read.status != ESP_GATT_OK) { ESP_LOGW(TAG, "[%d] [%s] Error reading char/descriptor at handle 0x%2X, status=%d", this->connection_index_, this->address_str_.c_str(), param->read.handle, param->read.status); @@ -89,8 +76,6 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga } case ESP_GATTC_WRITE_CHAR_EVT: case ESP_GATTC_WRITE_DESCR_EVT: { - if (param->write.conn_id != this->conn_id_) - break; if (param->write.status != ESP_GATT_OK) { ESP_LOGW(TAG, "[%d] [%s] Error writing char/descriptor at handle 0x%2X, status=%d", this->connection_index_, this->address_str_.c_str(), param->write.handle, param->write.status); @@ -131,8 +116,6 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga break; } case ESP_GATTC_NOTIFY_EVT: { - if (param->notify.conn_id != this->conn_id_) - break; ESP_LOGV(TAG, "[%d] [%s] ESP_GATTC_NOTIFY_EVT: handle=0x%2X", this->connection_index_, this->address_str_.c_str(), param->notify.handle); api::BluetoothGATTNotifyDataResponse resp; diff --git a/esphome/components/esp32_ble_client/ble_client_base.cpp b/esphome/components/esp32_ble_client/ble_client_base.cpp index ae83715aea..98e7792792 100644 --- a/esphome/components/esp32_ble_client/ble_client_base.cpp +++ b/esphome/components/esp32_ble_client/ble_client_base.cpp @@ -142,7 +142,7 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ ESP_LOGW(TAG, "[%d] [%s] Connection failed, status=%d", this->connection_index_, this->address_str_.c_str(), param->open.status); this->set_state(espbt::ClientState::IDLE); - return false; + break; } auto ret = esp_ble_gattc_send_mtu_req(this->gattc_if_, param->open.conn_id); if (ret) { diff --git a/esphome/components/pvvx_mithermometer/display/pvvx_display.cpp b/esphome/components/pvvx_mithermometer/display/pvvx_display.cpp index d192e62430..1856a023cc 100644 --- a/esphome/components/pvvx_mithermometer/display/pvvx_display.cpp +++ b/esphome/components/pvvx_mithermometer/display/pvvx_display.cpp @@ -24,8 +24,10 @@ void PVVXDisplay::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t esp_ble_gattc_cb_param_t *param) { switch (event) { case ESP_GATTC_OPEN_EVT: - ESP_LOGV(TAG, "[%s] Connected successfully!", this->parent_->address_str().c_str()); - this->delayed_disconnect_(); + if (param->open.status == ESP_GATT_OK) { + ESP_LOGV(TAG, "[%s] Connected successfully!", this->parent_->address_str().c_str()); + this->delayed_disconnect_(); + } break; case ESP_GATTC_DISCONNECT_EVT: ESP_LOGV(TAG, "[%s] Disconnected", this->parent_->address_str().c_str()); From 0662c5e0fb3e760fe488b80ab4cc312e6bd1011c Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Fri, 26 Apr 2024 07:00:01 +1000 Subject: [PATCH 1329/2101] Fix for #6614- use background_color, improve anti-aliasing (#6618) --- esphome/components/font/font.cpp | 17 ++++++++++------- .../graphical_display_menu.cpp | 15 ++++++++------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/esphome/components/font/font.cpp b/esphome/components/font/font.cpp index 5a18429789..3b62b8ca66 100644 --- a/esphome/components/font/font.cpp +++ b/esphome/components/font/font.cpp @@ -129,7 +129,13 @@ void Font::print(int x_start, int y_start, display::Display *display, Color colo uint8_t bitmask = 0; uint8_t pixel_data = 0; - float bpp_max = (1 << this->bpp_) - 1; + uint8_t bpp_max = (1 << this->bpp_) - 1; + auto diff_r = (float) color.r - (float) background.r; + auto diff_g = (float) color.g - (float) background.g; + auto diff_b = (float) color.b - (float) background.b; + auto b_r = (float) background.r; + auto b_g = (float) background.g; + auto b_b = (float) background.g; for (int glyph_y = y_start + scan_y1; glyph_y != max_y; glyph_y++) { for (int glyph_x = x_at + scan_x1; glyph_x != max_x; glyph_x++) { uint8_t pixel = 0; @@ -146,12 +152,9 @@ void Font::print(int x_start, int y_start, display::Display *display, Color colo if (pixel == bpp_max) { display->draw_pixel_at(glyph_x, glyph_y, color); } else if (pixel != 0) { - float on = (float) pixel / bpp_max; - float off = 1.0 - on; - Color blended; - blended.r = color.r * on + background.r * off; - blended.g = color.r * on + background.g * off; - blended.b = color.r * on + background.b * off; + auto on = (float) pixel / (float) bpp_max; + auto blended = + Color((uint8_t) (diff_r * on + b_r), (uint8_t) (diff_g * on + b_g), (uint8_t) (diff_b * on + b_b)); display->draw_pixel_at(glyph_x, glyph_y, blended); } } diff --git a/esphome/components/graphical_display_menu/graphical_display_menu.cpp b/esphome/components/graphical_display_menu/graphical_display_menu.cpp index fcbad41388..4a4e519009 100644 --- a/esphome/components/graphical_display_menu/graphical_display_menu.cpp +++ b/esphome/components/graphical_display_menu/graphical_display_menu.cpp @@ -104,7 +104,8 @@ void GraphicalDisplayMenu::draw(display::Display *display, const display::Rect * } void GraphicalDisplayMenu::draw_menu_internal_(display::Display *display, const display::Rect *bounds) { - int total_height = 0; + int16_t total_height = 0; + int16_t max_width = 0; int y_padding = 2; bool scroll_menu_items = false; std::vector menu_dimensions; @@ -118,6 +119,7 @@ void GraphicalDisplayMenu::draw_menu_internal_(display::Display *display, const menu_dimensions.push_back(item_dimensions); total_height += item_dimensions.h + (i == 0 ? 0 : y_padding); + max_width = std::max(max_width, item_dimensions.w); if (total_height <= bounds->h) { number_items_fit_to_screen++; @@ -166,7 +168,8 @@ void GraphicalDisplayMenu::draw_menu_internal_(display::Display *display, const // Render the items into the view port display->start_clipping(*bounds); - int y_offset = bounds->y; + display->filled_rectangle(bounds->x, bounds->y, max_width, total_height, this->background_color_); + auto y_offset = bounds->y; for (size_t i = first_item_index; i <= last_item_index; i++) { const auto *item = this->displayed_item_->get_item(i); const bool selected = i == this->cursor_index_; @@ -176,7 +179,7 @@ void GraphicalDisplayMenu::draw_menu_internal_(display::Display *display, const dimensions.x = bounds->x; this->draw_item(display, item, &dimensions, selected); - y_offset = dimensions.y + dimensions.h + y_padding; + y_offset += dimensions.h + y_padding; } display->end_clipping(); @@ -219,9 +222,7 @@ inline void GraphicalDisplayMenu::draw_item(display::Display *display, const dis // int background_width = std::max(bounds->width, available_width); int background_width = bounds->w; - if (selected) { - display->filled_rectangle(bounds->x, bounds->y, background_width, bounds->h, background_color); - } + display->filled_rectangle(bounds->x, bounds->y, background_width, bounds->h, background_color); std::string label = item->get_text(); if (item->has_value()) { @@ -230,7 +231,7 @@ inline void GraphicalDisplayMenu::draw_item(display::Display *display, const dis } display->print(bounds->x, bounds->y, this->font_, foreground_color, display::TextAlign::TOP_LEFT, label.c_str(), - ~foreground_color); + background_color); } void GraphicalDisplayMenu::draw_item(const display_menu_base::MenuItem *item, const uint8_t row, const bool selected) { From de2a92e45de9444b7bcc88e8a0c8984c6240b53b Mon Sep 17 00:00:00 2001 From: chiahsing Date: Fri, 26 Apr 2024 05:01:51 +0800 Subject: [PATCH 1330/2101] Fix graph hangs when y <= 0 (#6593) --- esphome/components/graph/graph.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/esphome/components/graph/graph.cpp b/esphome/components/graph/graph.cpp index 0e437a3425..1178af911d 100644 --- a/esphome/components/graph/graph.cpp +++ b/esphome/components/graph/graph.cpp @@ -164,7 +164,7 @@ void Graph::draw(Display *buff, uint16_t x_offset, uint16_t y_offset, Color colo ESP_LOGV(TAG, "Updating graph. ymin %f, ymax %f", ymin, ymax); for (auto *trace : traces_) { Color c = trace->get_line_color(); - uint16_t thick = trace->get_line_thickness(); + int16_t thick = trace->get_line_thickness(); bool continuous = trace->get_continuous(); bool has_prev = false; bool prev_b = false; @@ -178,20 +178,20 @@ void Graph::draw(Display *buff, uint16_t x_offset, uint16_t y_offset, Color colo if (b) { int16_t y = (int16_t) roundf((this->height_ - 1) * (1.0 - v)) - thick / 2 + y_offset; if (!continuous || !has_prev || !prev_b || (abs(y - prev_y) <= thick)) { - for (uint16_t t = 0; t < thick; t++) { + for (int16_t t = 0; t < thick; t++) { buff->draw_pixel_at(x, y + t, c); } } else { int16_t mid_y = (y + prev_y + thick) / 2; if (y > prev_y) { - for (uint16_t t = prev_y + thick; t <= mid_y; t++) + for (int16_t t = prev_y + thick; t <= mid_y; t++) buff->draw_pixel_at(x + 1, t, c); - for (uint16_t t = mid_y + 1; t < y + thick; t++) + for (int16_t t = mid_y + 1; t < y + thick; t++) buff->draw_pixel_at(x, t, c); } else { - for (uint16_t t = prev_y - 1; t >= mid_y; t--) + for (int16_t t = prev_y - 1; t >= mid_y; t--) buff->draw_pixel_at(x + 1, t, c); - for (uint16_t t = mid_y - 1; t >= y; t--) + for (int16_t t = mid_y - 1; t >= y; t--) buff->draw_pixel_at(x, t, c); } } From 5288d5ac9539cbb1d8e67e6094c7aeb35844c66e Mon Sep 17 00:00:00 2001 From: Nico Peter Date: Thu, 25 Apr 2024 23:04:20 +0200 Subject: [PATCH 1331/2101] Feature add last_operation to time based cover (#6084) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/time_based/time_based_cover.h | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/time_based/time_based_cover.h b/esphome/components/time_based/time_based_cover.h index b7a826d237..42cf66c2ab 100644 --- a/esphome/components/time_based/time_based_cover.h +++ b/esphome/components/time_based/time_based_cover.h @@ -23,6 +23,7 @@ class TimeBasedCover : public cover::Cover, public Component { void set_has_built_in_endstop(bool value) { this->has_built_in_endstop_ = value; } void set_manual_control(bool value) { this->manual_control_ = value; } void set_assumed_state(bool value) { this->assumed_state_ = value; } + cover::CoverOperation get_last_operation() const { return this->last_operation_; } protected: void control(const cover::CoverCall &call) override; From bcef64a6fa67e8c85ae0a03f4f2986361be3e58d Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Thu, 25 Apr 2024 16:04:48 -0500 Subject: [PATCH 1332/2101] Add `event`, `text_sensor` and `valve` device classes to sync script (#6624) --- script/sync-device_class.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/script/sync-device_class.py b/script/sync-device_class.py index 8f91b97997..26d271535f 100755 --- a/script/sync-device_class.py +++ b/script/sync-device_class.py @@ -6,9 +6,12 @@ import re from homeassistant.components.binary_sensor import BinarySensorDeviceClass from homeassistant.components.button import ButtonDeviceClass from homeassistant.components.cover import CoverDeviceClass +from homeassistant.components.event import EventDeviceClass from homeassistant.components.number import NumberDeviceClass from homeassistant.components.sensor import SensorDeviceClass from homeassistant.components.switch import SwitchDeviceClass +from homeassistant.components.text_sensor import TextSensorDeviceClass +from homeassistant.components.valve import ValveDeviceClass # pylint: enable=import-error @@ -21,9 +24,12 @@ DOMAINS = { "binary_sensor": BinarySensorDeviceClass, "button": ButtonDeviceClass, "cover": CoverDeviceClass, + "event": EventDeviceClass, "number": NumberDeviceClass, "sensor": SensorDeviceClass, "switch": SwitchDeviceClass, + "text_sensor": TextSensorDeviceClass, + "valve": ValveDeviceClass, } From 8ef7b41c91deefe9514cf6c6130e0fcbb99ecb6d Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 26 Apr 2024 09:19:54 +1200 Subject: [PATCH 1333/2101] Add datetime entities (#6513) --- esphome/components/api/api.proto | 38 +++ esphome/components/api/api_connection.cpp | 38 +++ esphome/components/api/api_connection.h | 5 + esphome/components/api/api_pb2.cpp | 173 ++++++++++++ esphome/components/api/api_pb2.h | 45 ++++ esphome/components/api/api_pb2_service.cpp | 42 +++ esphome/components/api/api_pb2_service.h | 15 ++ esphome/components/api/api_server.cpp | 9 + esphome/components/api/api_server.h | 3 + esphome/components/api/list_entities.cpp | 6 + esphome/components/api/list_entities.h | 3 + esphome/components/api/subscribe_state.cpp | 5 + esphome/components/api/subscribe_state.h | 3 + esphome/components/datetime/__init__.py | 129 ++++++--- esphome/components/datetime/date_entity.cpp | 3 + esphome/components/datetime/datetime_base.h | 7 + .../components/datetime/datetime_entity.cpp | 252 ++++++++++++++++++ esphome/components/datetime/datetime_entity.h | 150 +++++++++++ esphome/components/datetime/time_entity.cpp | 6 +- esphome/components/datetime/time_entity.h | 12 +- esphome/components/mqtt/__init__.py | 1 + esphome/components/mqtt/mqtt_datetime.cpp | 84 ++++++ esphome/components/mqtt/mqtt_datetime.h | 45 ++++ .../components/template/datetime/__init__.py | 22 ++ .../template/datetime/template_datetime.cpp | 150 +++++++++++ .../template/datetime/template_datetime.h | 46 ++++ esphome/components/time/real_time_clock.cpp | 2 + .../components/web_server/list_entities.cpp | 9 + esphome/components/web_server/list_entities.h | 3 + esphome/components/web_server/web_server.cpp | 63 +++++ esphome/components/web_server/web_server.h | 9 + esphome/const.py | 1 + esphome/core/application.h | 19 ++ esphome/core/component_iterator.cpp | 15 ++ esphome/core/component_iterator.h | 6 + esphome/core/controller.cpp | 6 + esphome/core/controller.h | 6 + esphome/core/defines.h | 1 + esphome/core/time.cpp | 9 + esphome/core/time.h | 3 + script/ci-custom.py | 1 + tests/components/datetime/test.all.yaml | 2 + .../template/{test.all.yaml => common.yaml} | 22 ++ tests/components/template/test.bk72xx.yaml | 2 + .../template/test.esp32-c3-idf.yaml | 2 + tests/components/template/test.esp32-c3.yaml | 2 + tests/components/template/test.esp32-idf.yaml | 2 + .../template/test.esp32-s3-idf.yaml | 2 + tests/components/template/test.esp32.yaml | 2 + tests/components/template/test.esp8266.yaml | 2 + tests/components/template/test.rp2040.yaml | 2 + 51 files changed, 1430 insertions(+), 55 deletions(-) create mode 100644 esphome/components/datetime/datetime_entity.cpp create mode 100644 esphome/components/datetime/datetime_entity.h create mode 100644 esphome/components/mqtt/mqtt_datetime.cpp create mode 100644 esphome/components/mqtt/mqtt_datetime.h create mode 100644 esphome/components/template/datetime/template_datetime.cpp create mode 100644 esphome/components/template/datetime/template_datetime.h rename tests/components/template/{test.all.yaml => common.yaml} (88%) create mode 100644 tests/components/template/test.bk72xx.yaml create mode 100644 tests/components/template/test.esp32-c3-idf.yaml create mode 100644 tests/components/template/test.esp32-c3.yaml create mode 100644 tests/components/template/test.esp32-idf.yaml create mode 100644 tests/components/template/test.esp32-s3-idf.yaml create mode 100644 tests/components/template/test.esp32.yaml create mode 100644 tests/components/template/test.esp8266.yaml create mode 100644 tests/components/template/test.rp2040.yaml diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index 17826ea7ed..b8073abc19 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -47,6 +47,7 @@ service APIConnection { rpc media_player_command (MediaPlayerCommandRequest) returns (void) {} rpc date_command (DateCommandRequest) returns (void) {} rpc time_command (TimeCommandRequest) returns (void) {} + rpc datetime_command (DateTimeCommandRequest) returns (void) {} rpc subscribe_bluetooth_le_advertisements(SubscribeBluetoothLEAdvertisementsRequest) returns (void) {} rpc bluetooth_device_request(BluetoothDeviceRequest) returns (void) {} @@ -1777,3 +1778,40 @@ message ValveCommandRequest { float position = 3; bool stop = 4; } + +// ==================== DATETIME DATETIME ==================== +message ListEntitiesDateTimeResponse { + option (id) = 112; + option (source) = SOURCE_SERVER; + option (ifdef) = "USE_DATETIME_DATETIME"; + + string object_id = 1; + fixed32 key = 2; + string name = 3; + string unique_id = 4; + + string icon = 5; + bool disabled_by_default = 6; + EntityCategory entity_category = 7; +} +message DateTimeStateResponse { + option (id) = 113; + option (source) = SOURCE_SERVER; + option (ifdef) = "USE_DATETIME_DATETIME"; + option (no_delay) = true; + + fixed32 key = 1; + // 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; + fixed32 epoch_seconds = 3; +} +message DateTimeCommandRequest { + option (id) = 114; + option (source) = SOURCE_CLIENT; + option (ifdef) = "USE_DATETIME_DATETIME"; + option (no_delay) = true; + + fixed32 key = 1; + fixed32 epoch_seconds = 2; +} diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index ec09604d95..b31212bbdb 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -772,6 +772,44 @@ void APIConnection::time_command(const TimeCommandRequest &msg) { } #endif +#ifdef USE_DATETIME_DATETIME +bool APIConnection::send_datetime_state(datetime::DateTimeEntity *datetime) { + if (!this->state_subscription_) + return false; + + DateTimeStateResponse resp{}; + resp.key = datetime->get_object_id_hash(); + resp.missing_state = !datetime->has_state(); + if (datetime->has_state()) { + ESPTime state = datetime->state_as_esptime(); + resp.epoch_seconds = state.timestamp; + } + return this->send_date_time_state_response(resp); +} +bool APIConnection::send_datetime_info(datetime::DateTimeEntity *datetime) { + ListEntitiesDateTimeResponse msg; + msg.key = datetime->get_object_id_hash(); + msg.object_id = datetime->get_object_id(); + if (datetime->has_own_name()) + msg.name = datetime->get_name(); + msg.unique_id = get_default_unique_id("datetime", datetime); + msg.icon = datetime->get_icon(); + msg.disabled_by_default = datetime->is_disabled_by_default(); + msg.entity_category = static_cast(datetime->get_entity_category()); + + return this->send_list_entities_date_time_response(msg); +} +void APIConnection::datetime_command(const DateTimeCommandRequest &msg) { + datetime::DateTimeEntity *datetime = App.get_datetime_by_key(msg.key); + if (datetime == nullptr) + return; + + auto call = datetime->make_call(); + call.set_datetime(msg.epoch_seconds); + call.perform(); +} +#endif + #ifdef USE_TEXT bool APIConnection::send_text_state(text::Text *text, std::string state) { if (!this->state_subscription_) diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index 2c1d733d3e..ee466c5d10 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -82,6 +82,11 @@ class APIConnection : public APIServerConnection { bool send_time_info(datetime::TimeEntity *time); void time_command(const TimeCommandRequest &msg) override; #endif +#ifdef USE_DATETIME_DATETIME + bool send_datetime_state(datetime::DateTimeEntity *datetime); + bool send_datetime_info(datetime::DateTimeEntity *datetime); + void datetime_command(const DateTimeCommandRequest &msg) override; +#endif #ifdef USE_TEXT bool send_text_state(text::Text *text, std::string state); bool send_text_info(text::Text *text); diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index 3f01d88c58..6ec1870d72 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -8093,6 +8093,179 @@ void ValveCommandRequest::dump_to(std::string &out) const { out.append("}"); } #endif +bool ListEntitiesDateTimeResponse::decode_varint(uint32_t field_id, ProtoVarInt value) { + switch (field_id) { + case 6: { + this->disabled_by_default = value.as_bool(); + return true; + } + case 7: { + this->entity_category = value.as_enum(); + return true; + } + default: + return false; + } +} +bool ListEntitiesDateTimeResponse::decode_length(uint32_t field_id, ProtoLengthDelimited value) { + switch (field_id) { + case 1: { + this->object_id = value.as_string(); + return true; + } + case 3: { + this->name = value.as_string(); + return true; + } + case 4: { + this->unique_id = value.as_string(); + return true; + } + case 5: { + this->icon = value.as_string(); + return true; + } + default: + return false; + } +} +bool ListEntitiesDateTimeResponse::decode_32bit(uint32_t field_id, Proto32Bit value) { + switch (field_id) { + case 2: { + this->key = value.as_fixed32(); + return true; + } + default: + return false; + } +} +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); + buffer.encode_string(4, this->unique_id); + buffer.encode_string(5, this->icon); + buffer.encode_bool(6, this->disabled_by_default); + buffer.encode_enum(7, this->entity_category); +} +#ifdef HAS_PROTO_MESSAGE_DUMP +void ListEntitiesDateTimeResponse::dump_to(std::string &out) const { + __attribute__((unused)) char buffer[64]; + out.append("ListEntitiesDateTimeResponse {\n"); + out.append(" object_id: "); + out.append("'").append(this->object_id).append("'"); + out.append("\n"); + + out.append(" key: "); + sprintf(buffer, "%" PRIu32, this->key); + out.append(buffer); + out.append("\n"); + + out.append(" name: "); + out.append("'").append(this->name).append("'"); + out.append("\n"); + + out.append(" unique_id: "); + out.append("'").append(this->unique_id).append("'"); + out.append("\n"); + + out.append(" icon: "); + out.append("'").append(this->icon).append("'"); + out.append("\n"); + + out.append(" disabled_by_default: "); + out.append(YESNO(this->disabled_by_default)); + out.append("\n"); + + out.append(" entity_category: "); + out.append(proto_enum_to_string(this->entity_category)); + out.append("\n"); + out.append("}"); +} +#endif +bool DateTimeStateResponse::decode_varint(uint32_t field_id, ProtoVarInt value) { + switch (field_id) { + case 2: { + this->missing_state = value.as_bool(); + return true; + } + default: + return false; + } +} +bool DateTimeStateResponse::decode_32bit(uint32_t field_id, Proto32Bit value) { + switch (field_id) { + case 1: { + this->key = value.as_fixed32(); + return true; + } + case 3: { + this->epoch_seconds = value.as_fixed32(); + return true; + } + default: + return false; + } +} +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); +} +#ifdef HAS_PROTO_MESSAGE_DUMP +void DateTimeStateResponse::dump_to(std::string &out) const { + __attribute__((unused)) char buffer[64]; + out.append("DateTimeStateResponse {\n"); + out.append(" key: "); + sprintf(buffer, "%" PRIu32, this->key); + out.append(buffer); + out.append("\n"); + + out.append(" missing_state: "); + out.append(YESNO(this->missing_state)); + out.append("\n"); + + out.append(" epoch_seconds: "); + sprintf(buffer, "%" PRIu32, this->epoch_seconds); + out.append(buffer); + out.append("\n"); + out.append("}"); +} +#endif +bool DateTimeCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { + switch (field_id) { + case 1: { + this->key = value.as_fixed32(); + return true; + } + case 2: { + this->epoch_seconds = value.as_fixed32(); + return true; + } + default: + return false; + } +} +void DateTimeCommandRequest::encode(ProtoWriteBuffer buffer) const { + buffer.encode_fixed32(1, this->key); + buffer.encode_fixed32(2, this->epoch_seconds); +} +#ifdef HAS_PROTO_MESSAGE_DUMP +void DateTimeCommandRequest::dump_to(std::string &out) const { + __attribute__((unused)) char buffer[64]; + out.append("DateTimeCommandRequest {\n"); + out.append(" key: "); + sprintf(buffer, "%" PRIu32, this->key); + out.append(buffer); + out.append("\n"); + + out.append(" epoch_seconds: "); + sprintf(buffer, "%" PRIu32, this->epoch_seconds); + out.append(buffer); + out.append("\n"); + out.append("}"); +} +#endif } // namespace api } // namespace esphome diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index 9a6aab254d..14fd95df37 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -2060,6 +2060,51 @@ class ValveCommandRequest : public ProtoMessage { bool decode_32bit(uint32_t field_id, Proto32Bit value) override; bool decode_varint(uint32_t field_id, ProtoVarInt value) override; }; +class ListEntitiesDateTimeResponse : public ProtoMessage { + public: + std::string object_id{}; + uint32_t key{0}; + std::string name{}; + std::string unique_id{}; + std::string icon{}; + bool disabled_by_default{false}; + enums::EntityCategory entity_category{}; + void encode(ProtoWriteBuffer buffer) const override; +#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 DateTimeStateResponse : public ProtoMessage { + public: + uint32_t key{0}; + bool missing_state{false}; + uint32_t epoch_seconds{0}; + void encode(ProtoWriteBuffer buffer) const override; +#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_varint(uint32_t field_id, ProtoVarInt value) override; +}; +class DateTimeCommandRequest : public ProtoMessage { + public: + uint32_t key{0}; + uint32_t epoch_seconds{0}; + void encode(ProtoWriteBuffer buffer) const override; +#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; +}; } // namespace api } // namespace esphome diff --git a/esphome/components/api/api_pb2_service.cpp b/esphome/components/api/api_pb2_service.cpp index ced81fa643..093fe917e0 100644 --- a/esphome/components/api/api_pb2_service.cpp +++ b/esphome/components/api/api_pb2_service.cpp @@ -591,6 +591,24 @@ bool APIServerConnectionBase::send_valve_state_response(const ValveStateResponse #endif #ifdef USE_VALVE #endif +#ifdef USE_DATETIME_DATETIME +bool APIServerConnectionBase::send_list_entities_date_time_response(const ListEntitiesDateTimeResponse &msg) { +#ifdef HAS_PROTO_MESSAGE_DUMP + ESP_LOGVV(TAG, "send_list_entities_date_time_response: %s", msg.dump().c_str()); +#endif + return this->send_message_(msg, 112); +} +#endif +#ifdef USE_DATETIME_DATETIME +bool APIServerConnectionBase::send_date_time_state_response(const DateTimeStateResponse &msg) { +#ifdef HAS_PROTO_MESSAGE_DUMP + ESP_LOGVV(TAG, "send_date_time_state_response: %s", msg.dump().c_str()); +#endif + return this->send_message_(msg, 113); +} +#endif +#ifdef USE_DATETIME_DATETIME +#endif bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) { switch (msg_type) { case 1: { @@ -1064,6 +1082,17 @@ bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, ESP_LOGVV(TAG, "on_valve_command_request: %s", msg.dump().c_str()); #endif this->on_valve_command_request(msg); +#endif + break; + } + case 114: { +#ifdef USE_DATETIME_DATETIME + 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()); +#endif + this->on_date_time_command_request(msg); #endif break; } @@ -1379,6 +1408,19 @@ void APIServerConnection::on_time_command_request(const TimeCommandRequest &msg) this->time_command(msg); } #endif +#ifdef USE_DATETIME_DATETIME +void APIServerConnection::on_date_time_command_request(const DateTimeCommandRequest &msg) { + if (!this->is_connection_setup()) { + this->on_no_setup_connection(); + return; + } + if (!this->is_authenticated()) { + this->on_unauthenticated_access(); + return; + } + this->datetime_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 c8b2bc5789..196d904aca 100644 --- a/esphome/components/api/api_pb2_service.h +++ b/esphome/components/api/api_pb2_service.h @@ -294,6 +294,15 @@ class APIServerConnectionBase : public ProtoService { #endif #ifdef USE_VALVE virtual void on_valve_command_request(const ValveCommandRequest &value){}; +#endif +#ifdef USE_DATETIME_DATETIME + bool send_list_entities_date_time_response(const ListEntitiesDateTimeResponse &msg); +#endif +#ifdef USE_DATETIME_DATETIME + bool send_date_time_state_response(const DateTimeStateResponse &msg); +#endif +#ifdef USE_DATETIME_DATETIME + virtual void on_date_time_command_request(const DateTimeCommandRequest &value){}; #endif protected: bool read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) override; @@ -358,6 +367,9 @@ class APIServerConnection : public APIServerConnectionBase { #ifdef USE_DATETIME_TIME virtual void time_command(const TimeCommandRequest &msg) = 0; #endif +#ifdef USE_DATETIME_DATETIME + virtual void datetime_command(const DateTimeCommandRequest &msg) = 0; +#endif #ifdef USE_BLUETOOTH_PROXY virtual void subscribe_bluetooth_le_advertisements(const SubscribeBluetoothLEAdvertisementsRequest &msg) = 0; #endif @@ -453,6 +465,9 @@ class APIServerConnection : public APIServerConnectionBase { #ifdef USE_DATETIME_TIME void on_time_command_request(const TimeCommandRequest &msg) override; #endif +#ifdef USE_DATETIME_DATETIME + void on_date_time_command_request(const DateTimeCommandRequest &msg) override; +#endif #ifdef USE_BLUETOOTH_PROXY void on_subscribe_bluetooth_le_advertisements_request(const SubscribeBluetoothLEAdvertisementsRequest &msg) override; #endif diff --git a/esphome/components/api/api_server.cpp b/esphome/components/api/api_server.cpp index 6d4e4db1e8..0725547771 100644 --- a/esphome/components/api/api_server.cpp +++ b/esphome/components/api/api_server.cpp @@ -273,6 +273,15 @@ void APIServer::on_time_update(datetime::TimeEntity *obj) { } #endif +#ifdef USE_DATETIME_DATETIME +void APIServer::on_datetime_update(datetime::DateTimeEntity *obj) { + if (obj->is_internal()) + return; + for (auto &c : this->clients_) + c->send_datetime_state(obj); +} +#endif + #ifdef USE_TEXT void APIServer::on_text_update(text::Text *obj, const std::string &state) { if (obj->is_internal()) diff --git a/esphome/components/api/api_server.h b/esphome/components/api/api_server.h index e9e03cde0d..2e1fbdf67c 100644 --- a/esphome/components/api/api_server.h +++ b/esphome/components/api/api_server.h @@ -72,6 +72,9 @@ class APIServer : public Component, public Controller { #ifdef USE_DATETIME_TIME void on_time_update(datetime::TimeEntity *obj) override; #endif +#ifdef USE_DATETIME_DATETIME + void on_datetime_update(datetime::DateTimeEntity *obj) override; +#endif #ifdef USE_TEXT void on_text_update(text::Text *obj, const std::string &state) override; #endif diff --git a/esphome/components/api/list_entities.cpp b/esphome/components/api/list_entities.cpp index 82bfd45333..a7dbf9a6e7 100644 --- a/esphome/components/api/list_entities.cpp +++ b/esphome/components/api/list_entities.cpp @@ -71,6 +71,12 @@ bool ListEntitiesIterator::on_date(datetime::DateEntity *date) { return this->cl bool ListEntitiesIterator::on_time(datetime::TimeEntity *time) { return this->client_->send_time_info(time); } #endif +#ifdef USE_DATETIME_DATETIME +bool ListEntitiesIterator::on_datetime(datetime::DateTimeEntity *datetime) { + return this->client_->send_datetime_info(datetime); +} +#endif + #ifdef USE_TEXT bool ListEntitiesIterator::on_text(text::Text *text) { return this->client_->send_text_info(text); } #endif diff --git a/esphome/components/api/list_entities.h b/esphome/components/api/list_entities.h index 19cd99ea01..c1fd8b82c4 100644 --- a/esphome/components/api/list_entities.h +++ b/esphome/components/api/list_entities.h @@ -52,6 +52,9 @@ class ListEntitiesIterator : public ComponentIterator { #ifdef USE_DATETIME_TIME bool on_time(datetime::TimeEntity *time) override; #endif +#ifdef USE_DATETIME_DATETIME + bool on_datetime(datetime::DateTimeEntity *datetime) override; +#endif #ifdef USE_TEXT bool on_text(text::Text *text) override; #endif diff --git a/esphome/components/api/subscribe_state.cpp b/esphome/components/api/subscribe_state.cpp index 7aa8e8ffac..005ab0e6da 100644 --- a/esphome/components/api/subscribe_state.cpp +++ b/esphome/components/api/subscribe_state.cpp @@ -48,6 +48,11 @@ bool InitialStateIterator::on_date(datetime::DateEntity *date) { return this->cl #ifdef USE_DATETIME_TIME bool InitialStateIterator::on_time(datetime::TimeEntity *time) { return this->client_->send_time_state(time); } #endif +#ifdef USE_DATETIME_DATETIME +bool InitialStateIterator::on_datetime(datetime::DateTimeEntity *datetime) { + return this->client_->send_datetime_state(datetime); +} +#endif #ifdef USE_TEXT bool InitialStateIterator::on_text(text::Text *text) { return this->client_->send_text_state(text, text->state); } #endif diff --git a/esphome/components/api/subscribe_state.h b/esphome/components/api/subscribe_state.h index 17d444c441..8c725e422e 100644 --- a/esphome/components/api/subscribe_state.h +++ b/esphome/components/api/subscribe_state.h @@ -49,6 +49,9 @@ class InitialStateIterator : public ComponentIterator { #ifdef USE_DATETIME_TIME bool on_time(datetime::TimeEntity *time) override; #endif +#ifdef USE_DATETIME_DATETIME + bool on_datetime(datetime::DateTimeEntity *datetime) override; +#endif #ifdef USE_TEXT bool on_text(text::Text *text) override; #endif diff --git a/esphome/components/datetime/__init__.py b/esphome/components/datetime/__init__.py index a22c60aae9..639a035159 100644 --- a/esphome/components/datetime/__init__.py +++ b/esphome/components/datetime/__init__.py @@ -1,6 +1,5 @@ import esphome.codegen as cg -# import cpp_generator as cpp import esphome.config_validation as cv from esphome import automation from esphome.components import mqtt, time @@ -13,6 +12,7 @@ from esphome.const import ( CONF_TYPE, CONF_MQTT_ID, CONF_DATE, + CONF_DATETIME, CONF_TIME, CONF_YEAR, CONF_MONTH, @@ -27,6 +27,7 @@ from esphome.cpp_helpers import setup_entity CODEOWNERS = ["@rfdarter", "@jesserockz"] +DEPENDENCIES = ["time"] IS_PLATFORM_COMPONENT = True @@ -34,10 +35,12 @@ datetime_ns = cg.esphome_ns.namespace("datetime") DateTimeBase = datetime_ns.class_("DateTimeBase", cg.EntityBase) DateEntity = datetime_ns.class_("DateEntity", DateTimeBase) TimeEntity = datetime_ns.class_("TimeEntity", DateTimeBase) +DateTimeEntity = datetime_ns.class_("DateTimeEntity", DateTimeBase) # Actions DateSetAction = datetime_ns.class_("DateSetAction", automation.Action) TimeSetAction = datetime_ns.class_("TimeSetAction", automation.Action) +DateTimeSetAction = datetime_ns.class_("DateTimeSetAction", automation.Action) DateTimeStateTrigger = datetime_ns.class_( "DateTimeStateTrigger", automation.Trigger.template(cg.ESPTime) @@ -46,6 +49,12 @@ DateTimeStateTrigger = datetime_ns.class_( OnTimeTrigger = datetime_ns.class_( "OnTimeTrigger", automation.Trigger, cg.Component, cg.Parented.template(TimeEntity) ) +OnDateTimeTrigger = datetime_ns.class_( + "OnDateTimeTrigger", + automation.Trigger, + cg.Component, + cg.Parented.template(DateTimeEntity), +) DATETIME_MODES = [ "DATE", @@ -61,45 +70,55 @@ _DATETIME_SCHEMA = cv.Schema( cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(DateTimeStateTrigger), } ), + cv.GenerateID(CONF_TIME_ID): cv.use_id(time.RealTimeClock), } ).extend(cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA)) def date_schema(class_: MockObjClass) -> cv.Schema: - schema = { - cv.GenerateID(): cv.declare_id(class_), - cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTDateComponent), - cv.Optional(CONF_TYPE, default="DATE"): cv.one_of("DATE", upper=True), - } + schema = cv.Schema( + { + cv.GenerateID(): cv.declare_id(class_), + cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTDateComponent), + cv.Optional(CONF_TYPE, default="DATE"): cv.one_of("DATE", upper=True), + } + ) return _DATETIME_SCHEMA.extend(schema) def time_schema(class_: MockObjClass) -> cv.Schema: - schema = { - cv.GenerateID(): cv.declare_id(class_), - cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTTimeComponent), - cv.Optional(CONF_TYPE, default="TIME"): cv.one_of("TIME", upper=True), - cv.Inclusive( - CONF_ON_TIME, - group_of_inclusion=CONF_ON_TIME, - msg="`on_time` and `time_id` must both be specified", - ): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(OnTimeTrigger), - } - ), - cv.Inclusive(CONF_TIME_ID, group_of_inclusion=CONF_ON_TIME): cv.use_id( - time.RealTimeClock - ), - } + schema = cv.Schema( + { + cv.GenerateID(): cv.declare_id(class_), + cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTTimeComponent), + cv.Optional(CONF_TYPE, default="TIME"): cv.one_of("TIME", upper=True), + cv.Optional(CONF_ON_TIME): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(OnTimeTrigger), + } + ), + } + ) return _DATETIME_SCHEMA.extend(schema) def datetime_schema(class_: MockObjClass) -> cv.Schema: - schema = { - cv.GenerateID(): cv.declare_id(class_), - cv.Optional(CONF_TYPE, default="DATETIME"): cv.one_of("DATETIME", upper=True), - } + schema = cv.Schema( + { + cv.GenerateID(): cv.declare_id(class_), + cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id( + mqtt.MQTTDateTimeComponent + ), + cv.Optional(CONF_TYPE, default="DATETIME"): cv.one_of( + "DATETIME", upper=True + ), + cv.Optional(CONF_ON_TIME): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(OnDateTimeTrigger), + } + ), + } + ) return _DATETIME_SCHEMA.extend(schema) @@ -113,13 +132,11 @@ async def setup_datetime_core_(var, config): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) await automation.build_automation(trigger, [(cg.ESPTime, "x")], conf) - rtc_id = config.get(CONF_TIME_ID) - rtc = None - if rtc_id is not None: - rtc = await cg.get_variable(rtc_id) + rtc = await cg.get_variable(config[CONF_TIME_ID]) + cg.add(var.set_rtc(rtc)) + for conf in config.get(CONF_ON_TIME, []): - assert rtc is not None - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], rtc) + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID]) await automation.build_automation(trigger, [], conf) await cg.register_component(trigger, conf) await cg.register_parented(trigger, var) @@ -161,16 +178,16 @@ async def datetime_date_set_to_code(config, action_id, template_arg, args): action_var = cg.new_Pvariable(action_id, template_arg) await cg.register_parented(action_var, config[CONF_ID]) - date = config[CONF_DATE] - if cg.is_template(date): - template_ = await cg.templatable(config[CONF_DATE], [], cg.ESPTime) + date_config = config[CONF_DATE] + if cg.is_template(date_config): + template_ = await cg.templatable(date_config, [], cg.ESPTime) cg.add(action_var.set_date(template_)) else: date_struct = cg.StructInitializer( cg.ESPTime, - ("day_of_month", date[CONF_DAY]), - ("month", date[CONF_MONTH]), - ("year", date[CONF_YEAR]), + ("day_of_month", date_config[CONF_DAY]), + ("month", date_config[CONF_MONTH]), + ("year", date_config[CONF_YEAR]), ) cg.add(action_var.set_date(date_struct)) return action_var @@ -194,7 +211,7 @@ async def datetime_time_set_to_code(config, action_id, template_arg, args): time_config = config[CONF_TIME] if cg.is_template(time_config): - template_ = await cg.templatable(config[CONF_TIME], [], cg.ESPTime) + template_ = await cg.templatable(time_config, [], cg.ESPTime) cg.add(action_var.set_time(template_)) else: time_struct = cg.StructInitializer( @@ -205,3 +222,35 @@ async def datetime_time_set_to_code(config, action_id, template_arg, args): ) cg.add(action_var.set_time(time_struct)) return action_var + + +@automation.register_action( + "datetime.datetime.set", + DateTimeSetAction, + cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(DateTimeEntity), + cv.Required(CONF_DATETIME): cv.Any(cv.returning_lambda, cv.date_time()), + }, + ), +) +async def datetime_datetime_set_to_code(config, action_id, template_arg, args): + action_var = cg.new_Pvariable(action_id, template_arg) + await cg.register_parented(action_var, config[CONF_ID]) + + datetime_config = config[CONF_DATETIME] + if cg.is_template(datetime_config): + template_ = await cg.templatable(datetime_config, [], cg.ESPTime) + cg.add(action_var.set_datetime(template_)) + else: + datetime_struct = cg.StructInitializer( + cg.ESPTime, + ("second", datetime_config[CONF_SECOND]), + ("minute", datetime_config[CONF_MINUTE]), + ("hour", datetime_config[CONF_HOUR]), + ("day_of_month", datetime_config[CONF_DAY]), + ("month", datetime_config[CONF_MONTH]), + ("year", datetime_config[CONF_YEAR]), + ) + cg.add(action_var.set_datetime(datetime_struct)) + return action_var diff --git a/esphome/components/datetime/date_entity.cpp b/esphome/components/datetime/date_entity.cpp index 8b58a8faf7..19399c1e59 100644 --- a/esphome/components/datetime/date_entity.cpp +++ b/esphome/components/datetime/date_entity.cpp @@ -40,10 +40,13 @@ void DateCall::validate_() { if (this->year_.has_value() && (this->year_ < 1970 || this->year_ > 3000)) { ESP_LOGE(TAG, "Year must be between 1970 and 3000"); this->year_.reset(); + this->month_.reset(); + this->day_.reset(); } if (this->month_.has_value() && (this->month_ < 1 || this->month_ > 12)) { ESP_LOGE(TAG, "Month must be between 1 and 12"); this->month_.reset(); + this->day_.reset(); } if (this->day_.has_value()) { uint16_t year = 0; diff --git a/esphome/components/datetime/datetime_base.h b/esphome/components/datetime/datetime_base.h index 2f2d27e102..c8240390e3 100644 --- a/esphome/components/datetime/datetime_base.h +++ b/esphome/components/datetime/datetime_base.h @@ -5,6 +5,8 @@ #include "esphome/core/entity_base.h" #include "esphome/core/time.h" +#include "esphome/components/time/real_time_clock.h" + namespace esphome { namespace datetime { @@ -17,9 +19,14 @@ class DateTimeBase : public EntityBase { void add_on_state_callback(std::function &&callback) { this->state_callback_.add(std::move(callback)); } + void set_rtc(time::RealTimeClock *rtc) { this->rtc_ = rtc; } + time::RealTimeClock *get_rtc() const { return this->rtc_; } + protected: CallbackManager state_callback_; + time::RealTimeClock *rtc_; + bool has_state_{false}; }; diff --git a/esphome/components/datetime/datetime_entity.cpp b/esphome/components/datetime/datetime_entity.cpp new file mode 100644 index 0000000000..9a61d341e4 --- /dev/null +++ b/esphome/components/datetime/datetime_entity.cpp @@ -0,0 +1,252 @@ +#include "datetime_entity.h" + +#ifdef USE_DATETIME_DATETIME + +#include "esphome/core/log.h" + +namespace esphome { +namespace datetime { + +static const char *const TAG = "datetime.datetime_entity"; + +void DateTimeEntity::publish_state() { + if (this->year_ == 0 || this->month_ == 0 || this->day_ == 0) { + this->has_state_ = false; + return; + } + if (this->year_ < 1970 || this->year_ > 3000) { + this->has_state_ = false; + ESP_LOGE(TAG, "Year must be between 1970 and 3000"); + return; + } + if (this->month_ < 1 || this->month_ > 12) { + this->has_state_ = false; + ESP_LOGE(TAG, "Month must be between 1 and 12"); + return; + } + if (this->day_ > days_in_month(this->month_, this->year_)) { + this->has_state_ = false; + ESP_LOGE(TAG, "Day must be between 1 and %d for month %d", days_in_month(this->month_, this->year_), this->month_); + return; + } + if (this->hour_ > 23) { + this->has_state_ = false; + ESP_LOGE(TAG, "Hour must be between 0 and 23"); + return; + } + if (this->minute_ > 59) { + this->has_state_ = false; + ESP_LOGE(TAG, "Minute must be between 0 and 59"); + return; + } + if (this->second_ > 59) { + this->has_state_ = false; + ESP_LOGE(TAG, "Second must be between 0 and 59"); + return; + } + this->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_); + this->state_callback_.call(); +} + +DateTimeCall DateTimeEntity::make_call() { return DateTimeCall(this); } + +ESPTime DateTimeEntity::state_as_esptime() const { + ESPTime obj; + obj.year = this->year_; + obj.month = this->month_; + obj.day_of_month = this->day_; + obj.hour = this->hour_; + obj.minute = this->minute_; + obj.second = this->second_; + obj.day_of_week = 1; // Required to be valid for recalc_timestamp_local but not used. + obj.day_of_year = 1; // Required to be valid for recalc_timestamp_local but not used. + obj.recalc_timestamp_local(false); + return obj; +} + +void DateTimeCall::validate_() { + if (this->year_.has_value() && (this->year_ < 1970 || this->year_ > 3000)) { + ESP_LOGE(TAG, "Year must be between 1970 and 3000"); + this->year_.reset(); + this->month_.reset(); + this->day_.reset(); + } + if (this->month_.has_value() && (this->month_ < 1 || this->month_ > 12)) { + ESP_LOGE(TAG, "Month must be between 1 and 12"); + this->month_.reset(); + this->day_.reset(); + } + if (this->day_.has_value()) { + uint16_t year = 0; + uint8_t month = 0; + if (this->month_.has_value()) { + month = *this->month_; + } else { + if (this->parent_->month != 0) { + month = this->parent_->month; + } else { + ESP_LOGE(TAG, "Month must be set to validate day"); + this->day_.reset(); + } + } + if (this->year_.has_value()) { + year = *this->year_; + } else { + if (this->parent_->year != 0) { + year = this->parent_->year; + } else { + ESP_LOGE(TAG, "Year must be set to validate day"); + this->day_.reset(); + } + } + if (this->day_.has_value() && *this->day_ > days_in_month(month, year)) { + ESP_LOGE(TAG, "Day must be between 1 and %d for month %d", days_in_month(month, year), month); + this->day_.reset(); + } + } + + if (this->hour_.has_value() && this->hour_ > 23) { + ESP_LOGE(TAG, "Hour must be between 0 and 23"); + this->hour_.reset(); + } + if (this->minute_.has_value() && this->minute_ > 59) { + ESP_LOGE(TAG, "Minute must be between 0 and 59"); + this->minute_.reset(); + } + if (this->second_.has_value() && this->second_ > 59) { + ESP_LOGE(TAG, "Second must be between 0 and 59"); + this->second_.reset(); + } +} + +void DateTimeCall::perform() { + this->validate_(); + ESP_LOGD(TAG, "'%s' - Setting", this->parent_->get_name().c_str()); + + if (this->year_.has_value()) { + ESP_LOGD(TAG, " Year: %d", *this->year_); + } + if (this->month_.has_value()) { + ESP_LOGD(TAG, " Month: %d", *this->month_); + } + if (this->day_.has_value()) { + ESP_LOGD(TAG, " Day: %d", *this->day_); + } + if (this->hour_.has_value()) { + ESP_LOGD(TAG, " Hour: %d", *this->hour_); + } + if (this->minute_.has_value()) { + ESP_LOGD(TAG, " Minute: %d", *this->minute_); + } + if (this->second_.has_value()) { + ESP_LOGD(TAG, " Second: %d", *this->second_); + } + this->parent_->control(*this); +} + +DateTimeCall &DateTimeCall::set_datetime(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, + uint8_t second) { + this->year_ = year; + this->month_ = month; + this->day_ = day; + this->hour_ = hour; + this->minute_ = minute; + this->second_ = second; + return *this; +}; + +DateTimeCall &DateTimeCall::set_datetime(ESPTime datetime) { + return this->set_datetime(datetime.year, datetime.month, datetime.day_of_month, datetime.hour, datetime.minute, + datetime.second); +}; + +DateTimeCall &DateTimeCall::set_datetime(const std::string &datetime) { + ESPTime val{}; + if (!ESPTime::strptime(datetime, val)) { + ESP_LOGE(TAG, "Could not convert the time string to an ESPTime object"); + return *this; + } + return this->set_datetime(val); +} + +DateTimeCall &DateTimeCall::set_datetime(time_t epoch_seconds) { + ESPTime val = ESPTime::from_epoch_local(epoch_seconds); + return this->set_datetime(val); +} + +DateTimeCall DateTimeEntityRestoreState::to_call(DateTimeEntity *datetime) { + DateTimeCall call = datetime->make_call(); + call.set_datetime(this->year, this->month, this->day, this->hour, this->minute, this->second); + return call; +} + +void DateTimeEntityRestoreState::apply(DateTimeEntity *time) { + time->year_ = this->year; + time->month_ = this->month; + time->day_ = this->day; + time->hour_ = this->hour; + time->minute_ = this->minute; + time->second_ = this->second; + time->publish_state(); +} + +static const int MAX_TIMESTAMP_DRIFT = 900; // how far can the clock drift before we consider + // there has been a drastic time synchronization + +void OnDateTimeTrigger::loop() { + if (!this->parent_->has_state()) { + return; + } + ESPTime time = this->parent_->rtc_->now(); + if (!time.is_valid()) { + return; + } + if (this->last_check_.has_value()) { + if (*this->last_check_ > time && this->last_check_->timestamp - time.timestamp > MAX_TIMESTAMP_DRIFT) { + // We went back in time (a lot), probably caused by time synchronization + ESP_LOGW(TAG, "Time has jumped back!"); + } else if (*this->last_check_ >= time) { + // already handled this one + return; + } else if (time > *this->last_check_ && time.timestamp - this->last_check_->timestamp > MAX_TIMESTAMP_DRIFT) { + // We went ahead in time (a lot), probably caused by time synchronization + ESP_LOGW(TAG, "Time has jumped ahead!"); + this->last_check_ = time; + return; + } + + while (true) { + this->last_check_->increment_second(); + if (*this->last_check_ >= time) + break; + + if (this->matches_(*this->last_check_)) { + this->trigger(); + break; + } + } + } + + this->last_check_ = time; + if (!time.fields_in_range()) { + ESP_LOGW(TAG, "Time is out of range!"); + ESP_LOGD(TAG, "Second=%02u Minute=%02u Hour=%02u Day=%02u Month=%02u Year=%04u", time.second, time.minute, + time.hour, time.day_of_month, time.month, time.year); + } + + if (this->matches_(time)) + this->trigger(); +} + +bool OnDateTimeTrigger::matches_(const ESPTime &time) const { + return time.is_valid() && time.year == this->parent_->year && time.month == this->parent_->month && + time.day_of_month == this->parent_->day && time.hour == this->parent_->hour && + time.minute == this->parent_->minute && time.second == this->parent_->second; +} + +} // namespace datetime +} // namespace esphome + +#endif // USE_DATETIME_TIME diff --git a/esphome/components/datetime/datetime_entity.h b/esphome/components/datetime/datetime_entity.h new file mode 100644 index 0000000000..d541fa96b1 --- /dev/null +++ b/esphome/components/datetime/datetime_entity.h @@ -0,0 +1,150 @@ +#pragma once + +#include "esphome/core/defines.h" + +#ifdef USE_DATETIME_DATETIME + +#include "esphome/core/automation.h" +#include "esphome/core/helpers.h" +#include "esphome/core/time.h" + +#include "datetime_base.h" + +namespace esphome { +namespace 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().empty()) { \ + ESP_LOGCONFIG(TAG, "%s Icon: '%s'", prefix, (obj)->get_icon().c_str()); \ + } \ + } + +class DateTimeCall; +class DateTimeEntity; + +struct DateTimeEntityRestoreState { + uint16_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint8_t second; + + DateTimeCall to_call(DateTimeEntity *datetime); + void apply(DateTimeEntity *datetime); +} __attribute__((packed)); + +class DateTimeEntity : public DateTimeBase { + protected: + uint16_t year_; + uint8_t month_; + uint8_t day_; + uint8_t hour_; + uint8_t minute_; + uint8_t second_; + + public: + void publish_state(); + DateTimeCall make_call(); + + ESPTime state_as_esptime() const override; + + const uint16_t &year = year_; + const uint8_t &month = month_; + const uint8_t &day = day_; + const uint8_t &hour = hour_; + const uint8_t &minute = minute_; + const uint8_t &second = second_; + + protected: + friend class DateTimeCall; + friend struct DateTimeEntityRestoreState; + friend class OnDateTimeTrigger; + + virtual void control(const DateTimeCall &call) = 0; +}; + +class DateTimeCall { + public: + explicit DateTimeCall(DateTimeEntity *parent) : parent_(parent) {} + 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(time_t epoch_seconds); + + DateTimeCall &set_year(uint16_t year) { + this->year_ = year; + return *this; + } + DateTimeCall &set_month(uint8_t month) { + this->month_ = month; + return *this; + } + DateTimeCall &set_day(uint8_t day) { + this->day_ = day; + return *this; + } + DateTimeCall &set_hour(uint8_t hour) { + this->hour_ = hour; + return *this; + } + DateTimeCall &set_minute(uint8_t minute) { + this->minute_ = minute; + return *this; + } + DateTimeCall &set_second(uint8_t second) { + this->second_ = second; + return *this; + } + + optional get_year() const { return this->year_; } + optional get_month() const { return this->month_; } + optional get_day() const { return this->day_; } + optional get_hour() const { return this->hour_; } + optional get_minute() const { return this->minute_; } + optional get_second() const { return this->second_; } + + protected: + void validate_(); + + DateTimeEntity *parent_; + + optional year_; + optional month_; + optional day_; + optional hour_; + optional minute_; + optional second_; +}; + +template class DateTimeSetAction : public Action, public Parented { + public: + TEMPLATABLE_VALUE(ESPTime, datetime) + + void play(Ts... x) override { + auto call = this->parent_->make_call(); + + if (this->datetime_.has_value()) { + call.set_datetime(this->datetime_.value(x...)); + } + call.perform(); + } +}; + +class OnDateTimeTrigger : public Trigger<>, public Component, public Parented { + public: + void loop() override; + + protected: + bool matches_(const ESPTime &time) const; + + optional last_check_; +}; + +} // namespace datetime +} // namespace esphome + +#endif // USE_DATETIME_DATETIME diff --git a/esphome/components/datetime/time_entity.cpp b/esphome/components/datetime/time_entity.cpp index 98558152d7..ea5e6684d0 100644 --- a/esphome/components/datetime/time_entity.cpp +++ b/esphome/components/datetime/time_entity.cpp @@ -94,8 +94,6 @@ void TimeEntityRestoreState::apply(TimeEntity *time) { time->publish_state(); } -#ifdef USE_TIME - static const int MAX_TIMESTAMP_DRIFT = 900; // how far can the clock drift before we consider // there has been a drastic time synchronization @@ -103,7 +101,7 @@ void OnTimeTrigger::loop() { if (!this->parent_->has_state()) { return; } - ESPTime time = this->rtc_->now(); + ESPTime time = this->parent_->rtc_->now(); if (!time.is_valid()) { return; } @@ -148,8 +146,6 @@ bool OnTimeTrigger::matches_(const ESPTime &time) const { time.second == this->parent_->second; } -#endif - } // namespace datetime } // namespace esphome diff --git a/esphome/components/datetime/time_entity.h b/esphome/components/datetime/time_entity.h index 956c09e2b4..62e593d28a 100644 --- a/esphome/components/datetime/time_entity.h +++ b/esphome/components/datetime/time_entity.h @@ -10,10 +10,6 @@ #include "datetime_base.h" -#ifdef USE_TIME -#include "esphome/components/time/real_time_clock.h" -#endif - namespace esphome { namespace datetime { @@ -27,6 +23,7 @@ namespace datetime { class TimeCall; class TimeEntity; +class OnTimeTrigger; struct TimeEntityRestoreState { uint8_t hour; @@ -62,6 +59,7 @@ class TimeEntity : public DateTimeBase { protected: friend class TimeCall; friend struct TimeEntityRestoreState; + friend class OnTimeTrigger; virtual void control(const TimeCall &call) = 0; }; @@ -115,22 +113,16 @@ template class TimeSetAction : public Action, public Pare } }; -#ifdef USE_TIME - class OnTimeTrigger : public Trigger<>, public Component, public Parented { public: - explicit OnTimeTrigger(time::RealTimeClock *rtc) : rtc_(rtc) {} void loop() override; protected: bool matches_(const ESPTime &time) const; - time::RealTimeClock *rtc_; optional last_check_; }; -#endif - } // namespace datetime } // namespace esphome diff --git a/esphome/components/mqtt/__init__.py b/esphome/components/mqtt/__init__.py index 7a42140ef6..064362c619 100644 --- a/esphome/components/mqtt/__init__.py +++ b/esphome/components/mqtt/__init__.py @@ -115,6 +115,7 @@ MQTTTextSensor = mqtt_ns.class_("MQTTTextSensor", MQTTComponent) MQTTNumberComponent = mqtt_ns.class_("MQTTNumberComponent", MQTTComponent) MQTTDateComponent = mqtt_ns.class_("MQTTDateComponent", MQTTComponent) MQTTTimeComponent = mqtt_ns.class_("MQTTTimeComponent", MQTTComponent) +MQTTDateTimeComponent = mqtt_ns.class_("MQTTDateTimeComponent", MQTTComponent) MQTTTextComponent = mqtt_ns.class_("MQTTTextComponent", MQTTComponent) MQTTSelectComponent = mqtt_ns.class_("MQTTSelectComponent", MQTTComponent) MQTTButtonComponent = mqtt_ns.class_("MQTTButtonComponent", MQTTComponent) diff --git a/esphome/components/mqtt/mqtt_datetime.cpp b/esphome/components/mqtt/mqtt_datetime.cpp new file mode 100644 index 0000000000..4fa44aafb8 --- /dev/null +++ b/esphome/components/mqtt/mqtt_datetime.cpp @@ -0,0 +1,84 @@ +#include "mqtt_datetime.h" + +#include +#include "esphome/core/log.h" + +#include "mqtt_const.h" + +#ifdef USE_MQTT +#ifdef USE_DATETIME_TIME + +namespace esphome { +namespace mqtt { + +static const char *const TAG = "mqtt.datetime.time"; + +using namespace esphome::datetime; + +MQTTDateTimeComponent::MQTTDateTimeComponent(DateTimeEntity *datetime) : datetime_(datetime) {} + +void MQTTDateTimeComponent::setup() { + this->subscribe_json(this->get_command_topic_(), [this](const std::string &topic, JsonObject root) { + auto call = this->datetime_->make_call(); + if (root.containsKey("year")) { + call.set_year(root["year"]); + } + if (root.containsKey("month")) { + call.set_month(root["month"]); + } + if (root.containsKey("day")) { + call.set_day(root["day"]); + } + if (root.containsKey("hour")) { + call.set_hour(root["hour"]); + } + if (root.containsKey("minute")) { + call.set_minute(root["minute"]); + } + if (root.containsKey("second")) { + call.set_second(root["second"]); + } + call.perform(); + }); + this->datetime_->add_on_state_callback([this]() { + this->publish_state(this->datetime_->year, this->datetime_->month, this->datetime_->day, this->datetime_->hour, + this->datetime_->minute, this->datetime_->second); + }); +} + +void MQTTDateTimeComponent::dump_config() { + ESP_LOGCONFIG(TAG, "MQTT DateTime '%s':", this->datetime_->get_name().c_str()); + LOG_MQTT_COMPONENT(true, true) +} + +std::string MQTTDateTimeComponent::component_type() const { return "datetime"; } +const EntityBase *MQTTDateTimeComponent::get_entity() const { return this->datetime_; } + +void MQTTDateTimeComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { + // Nothing extra to add here +} +bool MQTTDateTimeComponent::send_initial_state() { + if (this->datetime_->has_state()) { + return this->publish_state(this->datetime_->year, this->datetime_->month, this->datetime_->day, + this->datetime_->hour, this->datetime_->minute, this->datetime_->second); + } else { + return true; + } +} +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) { + root["year"] = year; + root["month"] = month; + root["day"] = day; + root["hour"] = hour; + root["minute"] = minute; + root["second"] = second; + }); +} + +} // namespace mqtt +} // namespace esphome + +#endif // USE_DATETIME_TIME +#endif // USE_MQTT diff --git a/esphome/components/mqtt/mqtt_datetime.h b/esphome/components/mqtt/mqtt_datetime.h new file mode 100644 index 0000000000..f0d68ad2e1 --- /dev/null +++ b/esphome/components/mqtt/mqtt_datetime.h @@ -0,0 +1,45 @@ +#pragma once + +#include "esphome/core/defines.h" + +#ifdef USE_MQTT +#ifdef USE_DATETIME_TIME + +#include "esphome/components/datetime/datetime_entity.h" +#include "mqtt_component.h" + +namespace esphome { +namespace mqtt { + +class MQTTDateTimeComponent : public mqtt::MQTTComponent { + public: + /** Construct this MQTTDateTimeComponent instance with the provided friendly_name and time + * + * @param time The time entity. + */ + explicit MQTTDateTimeComponent(datetime::DateTimeEntity *time); + + // ========== INTERNAL METHODS ========== + // (In most use cases you won't need these) + /// Override setup. + void setup() override; + void dump_config() override; + + void send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) override; + + bool send_initial_state() override; + + 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 EntityBase *get_entity() const override; + + datetime::DateTimeEntity *datetime_; +}; + +} // namespace mqtt +} // namespace esphome + +#endif // USE_DATETIME_DATE +#endif // USE_MQTT diff --git a/esphome/components/template/datetime/__init__.py b/esphome/components/template/datetime/__init__.py index 53d9d1b9d3..bf7154ef76 100644 --- a/esphome/components/template/datetime/__init__.py +++ b/esphome/components/template/datetime/__init__.py @@ -31,6 +31,10 @@ TemplateTime = template_ns.class_( "TemplateTime", datetime.TimeEntity, cg.PollingComponent ) +TemplateDateTime = template_ns.class_( + "TemplateDateTime", datetime.DateTimeEntity, cg.PollingComponent +) + def validate(config): config = config.copy() @@ -78,6 +82,13 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_INITIAL_VALUE): cv.date_time(allowed_date=False), } ), + "DATETIME": datetime.datetime_schema(TemplateDateTime) + .extend(_BASE_SCHEMA) + .extend( + { + cv.Optional(CONF_INITIAL_VALUE): cv.date_time(), + } + ), }, upper=True, ), @@ -116,6 +127,17 @@ async def to_code(config): ("hour", initial_value[CONF_HOUR]), ) cg.add(var.set_initial_value(time_struct)) + elif config[CONF_TYPE] == "DATETIME": + datetime_struct = cg.StructInitializer( + cg.ESPTime, + ("second", initial_value[CONF_SECOND]), + ("minute", initial_value[CONF_MINUTE]), + ("hour", initial_value[CONF_HOUR]), + ("day_of_month", initial_value[CONF_DAY]), + ("month", initial_value[CONF_MONTH]), + ("year", initial_value[CONF_YEAR]), + ) + cg.add(var.set_initial_value(datetime_struct)) if CONF_SET_ACTION in config: await automation.build_automation( diff --git a/esphome/components/template/datetime/template_datetime.cpp b/esphome/components/template/datetime/template_datetime.cpp new file mode 100644 index 0000000000..3ab74e197f --- /dev/null +++ b/esphome/components/template/datetime/template_datetime.cpp @@ -0,0 +1,150 @@ +#include "template_datetime.h" + +#ifdef USE_DATETIME_DATETIME + +#include "esphome/core/log.h" + +namespace esphome { +namespace template_ { + +static const char *const TAG = "template.datetime"; + +void TemplateDateTime::setup() { + if (this->f_.has_value()) + return; + + ESPTime state{}; + + if (!this->restore_value_) { + state = this->initial_value_; + } else { + datetime::DateTimeEntityRestoreState temp; + this->pref_ = global_preferences->make_preference(194434090U ^ + this->get_object_id_hash()); + if (this->pref_.load(&temp)) { + temp.apply(this); + return; + } else { + // set to inital value if loading from pref failed + state = this->initial_value_; + } + } + + this->year_ = state.year; + this->month_ = state.month; + this->day_ = state.day_of_month; + this->hour_ = state.hour; + this->minute_ = state.minute; + this->second_ = state.second; + this->publish_state(); +} + +void TemplateDateTime::update() { + if (!this->f_.has_value()) + return; + + auto val = (*this->f_)(); + if (!val.has_value()) + return; + + this->year_ = val->year; + this->month_ = val->month; + this->day_ = val->day_of_month; + this->hour_ = val->hour; + this->minute_ = val->minute; + this->second_ = val->second; + this->publish_state(); +} + +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(); + + ESPTime value = {}; + if (has_year) + value.year = *call.get_year(); + + if (has_month) + value.month = *call.get_month(); + + if (has_day) + value.day_of_month = *call.get_day(); + + if (has_hour) + value.hour = *call.get_hour(); + + if (has_minute) + value.minute = *call.get_minute(); + + if (has_second) + value.second = *call.get_second(); + + this->set_trigger_->trigger(value); + + if (this->optimistic_) { + if (has_year) + this->year_ = *call.get_year(); + if (has_month) + this->month_ = *call.get_month(); + if (has_day) + this->day_ = *call.get_day(); + if (has_hour) + this->hour_ = *call.get_hour(); + if (has_minute) + this->minute_ = *call.get_minute(); + if (has_second) + this->second_ = *call.get_second(); + this->publish_state(); + } + + if (this->restore_value_) { + datetime::DateTimeEntityRestoreState temp = {}; + if (has_year) { + temp.year = *call.get_year(); + } else { + temp.year = this->year_; + } + if (has_month) { + temp.month = *call.get_month(); + } else { + temp.month = this->month_; + } + if (has_day) { + temp.day = *call.get_day(); + } else { + temp.day = this->day_; + } + if (has_hour) { + temp.hour = *call.get_hour(); + } else { + temp.hour = this->hour_; + } + if (has_minute) { + temp.minute = *call.get_minute(); + } else { + temp.minute = this->minute_; + } + if (has_second) { + temp.second = *call.get_second(); + } else { + temp.second = this->second_; + } + + this->pref_.save(&temp); + } +} + +void TemplateDateTime::dump_config() { + LOG_DATETIME_DATETIME("", "Template DateTime", this); + ESP_LOGCONFIG(TAG, " Optimistic: %s", YESNO(this->optimistic_)); + LOG_UPDATE_INTERVAL(this); +} + +} // namespace template_ +} // namespace esphome + +#endif // USE_DATETIME_DATETIME diff --git a/esphome/components/template/datetime/template_datetime.h b/esphome/components/template/datetime/template_datetime.h new file mode 100644 index 0000000000..cb1fd01132 --- /dev/null +++ b/esphome/components/template/datetime/template_datetime.h @@ -0,0 +1,46 @@ +#pragma once + +#include "esphome/core/defines.h" + +#ifdef USE_DATETIME_TIME + +#include "esphome/components/datetime/datetime_entity.h" +#include "esphome/core/automation.h" +#include "esphome/core/component.h" +#include "esphome/core/preferences.h" +#include "esphome/core/time.h" + +namespace esphome { +namespace template_ { + +class TemplateDateTime : public datetime::DateTimeEntity, public PollingComponent { + public: + void set_template(std::function()> &&f) { this->f_ = f; } + + void setup() override; + void update() override; + void dump_config() override; + 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_value(ESPTime initial_value) { this->initial_value_ = initial_value; } + void set_restore_value(bool restore_value) { this->restore_value_ = restore_value; } + + protected: + void control(const datetime::DateTimeCall &call) override; + + bool optimistic_{false}; + ESPTime initial_value_{}; + bool restore_value_{false}; + Trigger *set_trigger_ = new Trigger(); + optional()>> f_; + + ESPPreferenceObject pref_; +}; + +} // namespace template_ +} // namespace esphome + +#endif // USE_DATETIME_TIME diff --git a/esphome/components/time/real_time_clock.cpp b/esphome/components/time/real_time_clock.cpp index 9b903d098b..2b9a95c6bd 100644 --- a/esphome/components/time/real_time_clock.cpp +++ b/esphome/components/time/real_time_clock.cpp @@ -13,6 +13,8 @@ #endif #include +#include + namespace esphome { namespace time { diff --git a/esphome/components/web_server/list_entities.cpp b/esphome/components/web_server/list_entities.cpp index 8d08783c8c..42af72e872 100644 --- a/esphome/components/web_server/list_entities.cpp +++ b/esphome/components/web_server/list_entities.cpp @@ -129,6 +129,15 @@ bool ListEntitiesIterator::on_time(datetime::TimeEntity *time) { } #endif +#ifdef USE_DATETIME_DATETIME +bool ListEntitiesIterator::on_datetime(datetime::DateTimeEntity *datetime) { + if (this->web_server_->events_.count() == 0) + return true; + this->web_server_->events_.send(this->web_server_->datetime_json(datetime, DETAIL_ALL).c_str(), "state"); + return true; +} +#endif + #ifdef USE_TEXT bool ListEntitiesIterator::on_text(text::Text *text) { if (this->web_server_->events_.count() == 0) diff --git a/esphome/components/web_server/list_entities.h b/esphome/components/web_server/list_entities.h index af84cb1d2b..47d427d9b5 100644 --- a/esphome/components/web_server/list_entities.h +++ b/esphome/components/web_server/list_entities.h @@ -47,6 +47,9 @@ class ListEntitiesIterator : public ComponentIterator { #ifdef USE_DATETIME_TIME bool on_time(datetime::TimeEntity *time) override; #endif +#ifdef USE_DATETIME_DATETIME + bool on_datetime(datetime::DateTimeEntity *datetime) override; +#endif #ifdef USE_TEXT bool on_text(text::Text *text) override; #endif diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index 0202038ffc..6a7b4121f0 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -926,6 +926,8 @@ std::string WebServer::date_json(datetime::DateEntity *obj, JsonDetail start_con #ifdef USE_DATETIME_TIME void WebServer::on_time_update(datetime::TimeEntity *obj) { + if (this->events_.count() == 0) + return; this->events_.send(this->time_json(obj, DETAIL_STATE).c_str(), "state"); } void WebServer::handle_time_request(AsyncWebServerRequest *request, const UrlMatch &match) { @@ -970,6 +972,55 @@ std::string WebServer::time_json(datetime::TimeEntity *obj, JsonDetail start_con } #endif // USE_DATETIME_TIME +#ifdef USE_DATETIME_DATETIME +void WebServer::on_datetime_update(datetime::DateTimeEntity *obj) { + if (this->events_.count() == 0) + return; + this->events_.send(this->datetime_json(obj, DETAIL_STATE).c_str(), "state"); +} +void WebServer::handle_datetime_request(AsyncWebServerRequest *request, const UrlMatch &match) { + for (auto *obj : App.get_datetimes()) { + if (obj->get_object_id() != match.id) + continue; + if (request->method() == HTTP_GET && match.method.empty()) { + std::string data = this->datetime_json(obj, DETAIL_STATE); + request->send(200, "application/json", data.c_str()); + return; + } + if (match.method != "set") { + request->send(404); + return; + } + + auto call = obj->make_call(); + + if (!request->hasParam("value")) { + request->send(409); + return; + } + + if (request->hasParam("value")) { + std::string value = request->getParam("value")->value().c_str(); + call.set_datetime(value); + } + + this->schedule_([call]() mutable { call.perform(); }); + request->send(200); + return; + } + request->send(404); +} +std::string WebServer::datetime_json(datetime::DateTimeEntity *obj, JsonDetail start_config) { + return json::build_json([obj, start_config](JsonObject root) { + set_json_id(root, obj, "datetime-" + obj->get_object_id(), start_config); + std::string value = str_sprintf("%d-%02d-%02d %02d:%02d:%02d", obj->year, obj->month, obj->day, obj->hour, + obj->minute, obj->second); + root["value"] = value; + root["state"] = value; + }); +} +#endif // USE_DATETIME_DATETIME + #ifdef USE_TEXT void WebServer::on_text_update(text::Text *obj, const std::string &state) { if (this->events_.count() == 0) @@ -1458,6 +1509,11 @@ bool WebServer::canHandle(AsyncWebServerRequest *request) { return true; #endif +#ifdef USE_DATETIME_DATETIME + if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain == "datetime") + return true; +#endif + #ifdef USE_TEXT if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain == "text") return true; @@ -1595,6 +1651,13 @@ void WebServer::handleRequest(AsyncWebServerRequest *request) { } #endif +#ifdef USE_DATETIME_DATETIME + if (match.domain == "datetime") { + this->handle_datetime_request(request, match); + return; + } +#endif + #ifdef USE_TEXT if (match.domain == "text") { this->handle_text_request(request, match); diff --git a/esphome/components/web_server/web_server.h b/esphome/components/web_server/web_server.h index 5e8f3f8236..dda14a7e05 100644 --- a/esphome/components/web_server/web_server.h +++ b/esphome/components/web_server/web_server.h @@ -239,6 +239,15 @@ class WebServer : public Controller, public Component, public AsyncWebHandler { std::string time_json(datetime::TimeEntity *obj, JsonDetail start_config); #endif +#ifdef USE_DATETIME_DATETIME + void on_datetime_update(datetime::DateTimeEntity *obj) override; + /// Handle a datetime request under '/datetime/'. + void handle_datetime_request(AsyncWebServerRequest *request, const UrlMatch &match); + + /// Dump the datetime state with its value as a JSON string. + std::string datetime_json(datetime::DateTimeEntity *obj, JsonDetail start_config); +#endif + #ifdef USE_TEXT void on_text_update(text::Text *obj, const std::string &state) override; /// Handle a text input request under '/text/'. diff --git a/esphome/const.py b/esphome/const.py index a64bc73f59..324b32e847 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -179,6 +179,7 @@ CONF_DATA_PINS = "data_pins" CONF_DATA_RATE = "data_rate" CONF_DATA_TEMPLATE = "data_template" CONF_DATE = "date" +CONF_DATETIME = "datetime" CONF_DAY = "day" CONF_DAYS_OF_MONTH = "days_of_month" CONF_DAYS_OF_WEEK = "days_of_week" diff --git a/esphome/core/application.h b/esphome/core/application.h index 35df350ec3..7487780412 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -45,6 +45,9 @@ #ifdef USE_DATETIME_TIME #include "esphome/components/datetime/time_entity.h" #endif +#ifdef USE_DATETIME_DATETIME +#include "esphome/components/datetime/datetime_entity.h" +#endif #ifdef USE_TEXT #include "esphome/components/text/text.h" #endif @@ -141,6 +144,10 @@ class Application { void register_time(datetime::TimeEntity *time) { this->times_.push_back(time); } #endif +#ifdef USE_DATETIME_DATETIME + void register_datetime(datetime::DateTimeEntity *datetime) { this->datetimes_.push_back(datetime); } +#endif + #ifdef USE_TEXT void register_text(text::Text *text) { this->texts_.push_back(text); } #endif @@ -335,6 +342,15 @@ class Application { return nullptr; } #endif +#ifdef USE_DATETIME_DATETIME + const std::vector &get_datetimes() { return this->datetimes_; } + datetime::DateTimeEntity *get_datetime_by_key(uint32_t key, bool include_internal = false) { + for (auto *obj : this->datetimes_) + if (obj->get_object_id_hash() == key && (include_internal || !obj->is_internal())) + return obj; + return nullptr; + } +#endif #ifdef USE_TEXT const std::vector &get_texts() { return this->texts_; } text::Text *get_text_by_key(uint32_t key, bool include_internal = false) { @@ -456,6 +472,9 @@ class Application { #ifdef USE_DATETIME_TIME std::vector times_{}; #endif +#ifdef USE_DATETIME_DATETIME + std::vector datetimes_{}; +#endif #ifdef USE_SELECT std::vector selects_{}; #endif diff --git a/esphome/core/component_iterator.cpp b/esphome/core/component_iterator.cpp index 687f1f6e23..9b02bf527b 100644 --- a/esphome/core/component_iterator.cpp +++ b/esphome/core/component_iterator.cpp @@ -232,6 +232,21 @@ void ComponentIterator::advance() { } break; #endif +#ifdef USE_DATETIME_DATETIME + case IteratorState::DATETIME_DATETIME: + if (this->at_ >= App.get_datetimes().size()) { + advance_platform = true; + } else { + auto *datetime = App.get_datetimes()[this->at_]; + if (datetime->is_internal() && !this->include_internal_) { + success = true; + break; + } else { + success = this->on_datetime(datetime); + } + } + break; +#endif #ifdef USE_TEXT case IteratorState::TEXT: if (this->at_ >= App.get_texts().size()) { diff --git a/esphome/core/component_iterator.h b/esphome/core/component_iterator.h index 8f0398cbb3..2b847bc088 100644 --- a/esphome/core/component_iterator.h +++ b/esphome/core/component_iterator.h @@ -63,6 +63,9 @@ class ComponentIterator { #ifdef USE_DATETIME_TIME virtual bool on_time(datetime::TimeEntity *time) = 0; #endif +#ifdef USE_DATETIME_DATETIME + virtual bool on_datetime(datetime::DateTimeEntity *datetime) = 0; +#endif #ifdef USE_TEXT virtual bool on_text(text::Text *text) = 0; #endif @@ -132,6 +135,9 @@ class ComponentIterator { #ifdef USE_DATETIME_TIME DATETIME_TIME, #endif +#ifdef USE_DATETIME_DATETIME + DATETIME_DATETIME, +#endif #ifdef USE_TEXT TEXT, #endif diff --git a/esphome/core/controller.cpp b/esphome/core/controller.cpp index eb975eaf6f..0957329500 100644 --- a/esphome/core/controller.cpp +++ b/esphome/core/controller.cpp @@ -71,6 +71,12 @@ void Controller::setup_controller(bool include_internal) { obj->add_on_state_callback([this, obj]() { this->on_time_update(obj); }); } #endif +#ifdef USE_DATETIME_DATETIME + for (auto *obj : App.get_datetimes()) { + if (include_internal || !obj->is_internal()) + obj->add_on_state_callback([this, obj]() { this->on_datetime_update(obj); }); + } +#endif #ifdef USE_TEXT for (auto *obj : App.get_texts()) { if (include_internal || !obj->is_internal()) diff --git a/esphome/core/controller.h b/esphome/core/controller.h index da9dbc00a6..e1bf93193a 100644 --- a/esphome/core/controller.h +++ b/esphome/core/controller.h @@ -37,6 +37,9 @@ #ifdef USE_DATETIME_TIME #include "esphome/components/datetime/time_entity.h" #endif +#ifdef USE_DATETIME_DATETIME +#include "esphome/components/datetime/datetime_entity.h" +#endif #ifdef USE_TEXT #include "esphome/components/text/text.h" #endif @@ -97,6 +100,9 @@ class Controller { #ifdef USE_DATETIME_TIME virtual void on_time_update(datetime::TimeEntity *obj){}; #endif +#ifdef USE_DATETIME_DATETIME + virtual void on_datetime_update(datetime::DateTimeEntity *obj){}; +#endif #ifdef USE_TEXT virtual void on_text_update(text::Text *obj, const std::string &state){}; #endif diff --git a/esphome/core/defines.h b/esphome/core/defines.h index fed73098d2..619a956071 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -39,6 +39,7 @@ #define USE_DATETIME #define USE_DATETIME_DATE #define USE_DATETIME_TIME +#define USE_DATETIME_DATETIME #define USE_OTA #define USE_OTA_PASSWORD #define USE_OTA_STATE_CALLBACK diff --git a/esphome/core/time.cpp b/esphome/core/time.cpp index 0004fc7e8e..add671701f 100644 --- a/esphome/core/time.cpp +++ b/esphome/core/time.cpp @@ -178,6 +178,15 @@ void ESPTime::recalc_timestamp_utc(bool use_day_of_year) { this->timestamp = res; } +void ESPTime::recalc_timestamp_local(bool use_day_of_year) { + this->recalc_timestamp_utc(use_day_of_year); + this->timestamp -= ESPTime::timezone_offset(); + ESPTime temp = ESPTime::from_epoch_local(this->timestamp); + if (temp.is_dst) { + this->timestamp -= 3600; + } +} + int32_t ESPTime::timezone_offset() { int32_t offset = 0; time_t now = ::time(nullptr); diff --git a/esphome/core/time.h b/esphome/core/time.h index 4300cf26b7..bce1108d93 100644 --- a/esphome/core/time.h +++ b/esphome/core/time.h @@ -99,6 +99,9 @@ struct ESPTime { /// Recalculate the timestamp field from the other fields of this ESPTime instance (must be UTC). void recalc_timestamp_utc(bool use_day_of_year = true); + /// Recalculate the timestamp field from the other fields of this ESPTime instance assuming local fields. + void recalc_timestamp_local(bool use_day_of_year = true); + /// Convert this ESPTime instance back to a tm struct. struct tm to_c_tm(); diff --git a/script/ci-custom.py b/script/ci-custom.py index 27fcd480f5..abe004dba3 100755 --- a/script/ci-custom.py +++ b/script/ci-custom.py @@ -623,6 +623,7 @@ def lint_trailing_whitespace(fname, match): "esphome/components/cover/cover.h", "esphome/components/datetime/date_entity.h", "esphome/components/datetime/time_entity.h", + "esphome/components/datetime/datetime_entity.h", "esphome/components/display/display.h", "esphome/components/event/event.h", "esphome/components/fan/fan.h", diff --git a/tests/components/datetime/test.all.yaml b/tests/components/datetime/test.all.yaml index 3f5996bb8b..4e26b68121 100644 --- a/tests/components/datetime/test.all.yaml +++ b/tests/components/datetime/test.all.yaml @@ -1 +1,3 @@ datetime: + +time: diff --git a/tests/components/template/test.all.yaml b/tests/components/template/common.yaml similarity index 88% rename from tests/components/template/test.all.yaml rename to tests/components/template/common.yaml index 64faec36c2..ba7167157b 100644 --- a/tests/components/template/test.all.yaml +++ b/tests/components/template/common.yaml @@ -183,3 +183,25 @@ datetime: - x.hour - x.minute - x.second + - platform: template + name: DateTime + id: test_datetime + type: datetime + set_action: + - logger.log: "set_value" + on_value: + - logger.log: + format: "DateTime: %04d-%02d-%02d %02d:%02d:%02d" + args: + - x.year + - x.month + - x.day_of_month + - x.hour + - x.minute + - x.second + +time: + - platform: sntp # Required for datetime + +wifi: # Required for sntp time + ap: diff --git a/tests/components/template/test.bk72xx.yaml b/tests/components/template/test.bk72xx.yaml new file mode 100644 index 0000000000..25cb37a0b4 --- /dev/null +++ b/tests/components/template/test.bk72xx.yaml @@ -0,0 +1,2 @@ +packages: + common: !include common.yaml diff --git a/tests/components/template/test.esp32-c3-idf.yaml b/tests/components/template/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..25cb37a0b4 --- /dev/null +++ b/tests/components/template/test.esp32-c3-idf.yaml @@ -0,0 +1,2 @@ +packages: + common: !include common.yaml diff --git a/tests/components/template/test.esp32-c3.yaml b/tests/components/template/test.esp32-c3.yaml new file mode 100644 index 0000000000..25cb37a0b4 --- /dev/null +++ b/tests/components/template/test.esp32-c3.yaml @@ -0,0 +1,2 @@ +packages: + common: !include common.yaml diff --git a/tests/components/template/test.esp32-idf.yaml b/tests/components/template/test.esp32-idf.yaml new file mode 100644 index 0000000000..25cb37a0b4 --- /dev/null +++ b/tests/components/template/test.esp32-idf.yaml @@ -0,0 +1,2 @@ +packages: + common: !include common.yaml diff --git a/tests/components/template/test.esp32-s3-idf.yaml b/tests/components/template/test.esp32-s3-idf.yaml new file mode 100644 index 0000000000..25cb37a0b4 --- /dev/null +++ b/tests/components/template/test.esp32-s3-idf.yaml @@ -0,0 +1,2 @@ +packages: + common: !include common.yaml diff --git a/tests/components/template/test.esp32.yaml b/tests/components/template/test.esp32.yaml new file mode 100644 index 0000000000..25cb37a0b4 --- /dev/null +++ b/tests/components/template/test.esp32.yaml @@ -0,0 +1,2 @@ +packages: + common: !include common.yaml diff --git a/tests/components/template/test.esp8266.yaml b/tests/components/template/test.esp8266.yaml new file mode 100644 index 0000000000..25cb37a0b4 --- /dev/null +++ b/tests/components/template/test.esp8266.yaml @@ -0,0 +1,2 @@ +packages: + common: !include common.yaml diff --git a/tests/components/template/test.rp2040.yaml b/tests/components/template/test.rp2040.yaml new file mode 100644 index 0000000000..25cb37a0b4 --- /dev/null +++ b/tests/components/template/test.rp2040.yaml @@ -0,0 +1,2 @@ +packages: + common: !include common.yaml From 8fcfcccbc3f3bb5edb4706a6c4b55a677a5dda99 Mon Sep 17 00:00:00 2001 From: Anton Viktorov Date: Thu, 25 Apr 2024 23:20:21 +0200 Subject: [PATCH 1334/2101] Multiple Daly-BMS support (#6615) --- esphome/components/daly_bms/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/daly_bms/__init__.py b/esphome/components/daly_bms/__init__.py index 2cc2c512f3..669d40a68d 100644 --- a/esphome/components/daly_bms/__init__.py +++ b/esphome/components/daly_bms/__init__.py @@ -4,6 +4,7 @@ from esphome.components import uart from esphome.const import CONF_ID, CONF_ADDRESS CODEOWNERS = ["@s1lvi0"] +MULTI_CONF = True DEPENDENCIES = ["uart"] CONF_BMS_DALY_ID = "bms_daly_id" From 3997503071bae2f208f761f668036f3cc8e62452 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Thu, 25 Apr 2024 18:03:24 -0500 Subject: [PATCH 1335/2101] Remove text_sensor from sync-device-class job (#6637) --- script/sync-device_class.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/script/sync-device_class.py b/script/sync-device_class.py index 26d271535f..12e1bb6a9f 100755 --- a/script/sync-device_class.py +++ b/script/sync-device_class.py @@ -10,7 +10,6 @@ from homeassistant.components.event import EventDeviceClass from homeassistant.components.number import NumberDeviceClass from homeassistant.components.sensor import SensorDeviceClass from homeassistant.components.switch import SwitchDeviceClass -from homeassistant.components.text_sensor import TextSensorDeviceClass from homeassistant.components.valve import ValveDeviceClass # pylint: enable=import-error @@ -28,7 +27,6 @@ DOMAINS = { "number": NumberDeviceClass, "sensor": SensorDeviceClass, "switch": SwitchDeviceClass, - "text_sensor": TextSensorDeviceClass, "valve": ValveDeviceClass, } From 3ecb5fa57f71c199ffd18c017ea3ebda6e05da58 Mon Sep 17 00:00:00 2001 From: esphomebot Date: Fri, 26 Apr 2024 11:40:19 +1200 Subject: [PATCH 1336/2101] Synchronise Device Classes from Home Assistant (#6638) --- esphome/components/event/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/event/__init__.py b/esphome/components/event/__init__.py index 789f121cf3..241e884386 100644 --- a/esphome/components/event/__init__.py +++ b/esphome/components/event/__init__.py @@ -25,8 +25,8 @@ IS_PLATFORM_COMPONENT = True DEVICE_CLASSES = [ DEVICE_CLASS_BUTTON, - DEVICE_CLASS_EMPTY, DEVICE_CLASS_DOORBELL, + DEVICE_CLASS_EMPTY, DEVICE_CLASS_MOTION, ] From 031e26ad989fae720aae645bab9b6480336ac3e2 Mon Sep 17 00:00:00 2001 From: NP v/d Spek Date: Fri, 26 Apr 2024 05:23:28 +0200 Subject: [PATCH 1337/2101] Display: add diagnostic test_card option (#6608) Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> --- esphome/components/display/__init__.py | 4 ++ esphome/components/display/display.cpp | 64 ++++++++++++++++++++++++-- esphome/components/display/display.h | 4 ++ 3 files changed, 69 insertions(+), 3 deletions(-) diff --git a/esphome/components/display/__init__.py b/esphome/components/display/__init__.py index 992799008a..c4bb12b75d 100644 --- a/esphome/components/display/__init__.py +++ b/esphome/components/display/__init__.py @@ -38,6 +38,7 @@ DisplayOnPageChangeTrigger = display_ns.class_( ) CONF_ON_PAGE_CHANGE = "on_page_change" +CONF_SHOW_TEST_CARD = "show_test_card" DISPLAY_ROTATIONS = { 0: display_ns.DISPLAY_ROTATION_0_DEGREES, @@ -82,6 +83,7 @@ FULL_DISPLAY_SCHEMA = BASIC_DISPLAY_SCHEMA.extend( } ), cv.Optional(CONF_AUTO_CLEAR_ENABLED, default=True): cv.boolean, + cv.Optional(CONF_SHOW_TEST_CARD): cv.boolean, } ) @@ -113,6 +115,8 @@ async def setup_display_core_(var, config): await automation.build_automation( trigger, [(DisplayPagePtr, "from"), (DisplayPagePtr, "to")], conf ) + if config.get(CONF_SHOW_TEST_CARD): + cg.add(var.show_test_card()) async def register_display(var, config): diff --git a/esphome/components/display/display.cpp b/esphome/components/display/display.cpp index 010e6eca0b..75205292f7 100644 --- a/esphome/components/display/display.cpp +++ b/esphome/components/display/display.cpp @@ -1,7 +1,7 @@ #include "display.h" - +#include "display_color_utils.h" #include - +#include "esphome/core/hal.h" #include "esphome/core/log.h" namespace esphome { @@ -507,7 +507,9 @@ void Display::do_update_() { if (this->auto_clear_enabled_) { this->clear(); } - if (this->page_ != nullptr) { + if (this->show_test_card_) { + this->test_card(); + } else if (this->page_ != nullptr) { this->page_->get_writer()(*this); } else if (this->writer_.has_value()) { (*this->writer_)(*this); @@ -608,6 +610,62 @@ 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' + +void Display::test_card() { + int w = get_width(), h = get_height(), image_w, image_h; + this->clear(); + this->show_test_card_ = false; + if (this->get_display_type() == DISPLAY_TYPE_COLOR) { + Color r(255, 0, 0), g(0, 255, 0), b(0, 0, 255); + image_w = std::min(w - 20, 310); + image_h = std::min(h - 20, 255); + + int shift_x = (w - image_w) / 2; + int shift_y = (h - image_h) / 2; + int line_w = (image_w - 6) / 6; + int image_c = image_w / 2; + for (auto i = 0; i <= image_h; i++) { + int c = esp_scale(i, image_h); + this->horizontal_line(shift_x + 0, shift_y + i, line_w, r.fade_to_white(c)); + this->horizontal_line(shift_x + line_w, shift_y + i, line_w, r.fade_to_black(c)); // + + this->horizontal_line(shift_x + image_c - line_w, shift_y + i, line_w, g.fade_to_white(c)); + this->horizontal_line(shift_x + image_c, shift_y + i, line_w, g.fade_to_black(c)); + + this->horizontal_line(shift_x + image_w - (line_w * 2), shift_y + i, line_w, b.fade_to_white(c)); + this->horizontal_line(shift_x + image_w - line_w, shift_y + i, line_w, b.fade_to_black(c)); + } + this->rectangle(shift_x, shift_y, image_w, image_h, Color(127, 127, 0)); + + uint16_t shift_r = shift_x + line_w - (8 * 3); + uint16_t shift_g = shift_x + image_c - (8 * 3); + uint16_t shift_b = shift_x + image_w - line_w - (8 * 3); + shift_y = h / 2 - (8 * 3); + for (auto i = 0; i < 8; i++) { + uint8_t ftr = progmem_read_byte(&TESTCARD_FONT[0][i]); + uint8_t ftg = progmem_read_byte(&TESTCARD_FONT[1][i]); + uint8_t ftb = progmem_read_byte(&TESTCARD_FONT[2][i]); + for (auto k = 0; k < 8; k++) { + if ((ftr & (1 << k)) != 0) { + this->filled_rectangle(shift_r + (i * 6), shift_y + (k * 6), 6, 6, COLOR_OFF); + } + if ((ftg & (1 << k)) != 0) { + this->filled_rectangle(shift_g + (i * 6), shift_y + (k * 6), 6, 6, COLOR_OFF); + } + if ((ftb & (1 << k)) != 0) { + this->filled_rectangle(shift_b + (i * 6), shift_y + (k * 6), 6, 6, COLOR_OFF); + } + } + } + } + this->rectangle(0, 0, w, h, Color(127, 0, 127)); + this->filled_rectangle(0, 0, 10, 10, Color(255, 0, 255)); + this->stop_poller(); +} + DisplayPage::DisplayPage(display_writer_t writer) : writer_(std::move(writer)) {} void DisplayPage::show() { this->parent_->show_page(this); } void DisplayPage::show_next() { this->next_->show(); } diff --git a/esphome/components/display/display.h b/esphome/components/display/display.h index a30ba976b4..4ee7ef93cb 100644 --- a/esphome/components/display/display.h +++ b/esphome/components/display/display.h @@ -631,6 +631,9 @@ class Display : public PollingComponent { */ bool clip(int x, int y); + void test_card(); + void show_test_card() { this->show_test_card_ = true; } + protected: bool clamp_x_(int x, int w, int &min_x, int &max_x); bool clamp_y_(int y, int h, int &min_y, int &max_y); @@ -659,6 +662,7 @@ class Display : public PollingComponent { std::vector on_page_change_triggers_; bool auto_clear_enabled_{true}; std::vector clipping_rectangle_; + bool show_test_card_{false}; }; class DisplayPage { From cd91c7050c00dc8d7051f7870715dc4d8abdd537 Mon Sep 17 00:00:00 2001 From: polyfloyd Date: Fri, 26 Apr 2024 10:44:58 +0200 Subject: [PATCH 1338/2101] waveshare_epaper: Add 2.90in-dke (#6492) Co-authored-by: The_Niz --- .../components/waveshare_epaper/display.py | 4 + .../waveshare_epaper/waveshare_epaper.cpp | 125 ++++++++++++++++++ .../waveshare_epaper/waveshare_epaper.h | 24 ++++ .../waveshare_epaper/test.esp32.yaml | 18 +++ 4 files changed, 171 insertions(+) diff --git a/esphome/components/waveshare_epaper/display.py b/esphome/components/waveshare_epaper/display.py index dc43cbf5a7..bba60efc0a 100644 --- a/esphome/components/waveshare_epaper/display.py +++ b/esphome/components/waveshare_epaper/display.py @@ -49,6 +49,9 @@ WaveshareEPaper2P9InV2R2 = waveshare_epaper_ns.class_( "WaveshareEPaper2P9InV2R2", WaveshareEPaper ) GDEY029T94 = waveshare_epaper_ns.class_("GDEY029T94", WaveshareEPaper) +WaveshareEPaper2P9InDKE = waveshare_epaper_ns.class_( + "WaveshareEPaper2P9InDKE", WaveshareEPaper +) WaveshareEPaper4P2In = waveshare_epaper_ns.class_( "WaveshareEPaper4P2In", WaveshareEPaper ) @@ -115,6 +118,7 @@ MODELS = { "2.90in-b": ("b", WaveshareEPaper2P9InB), "2.90in-bv3": ("b", WaveshareEPaper2P9InBV3), "2.90inv2-r2": ("c", WaveshareEPaper2P9InV2R2), + "2.90in-dke": ("c", WaveshareEPaper2P9InDKE), "4.20in": ("b", WaveshareEPaper4P2In), "4.20in-bv2": ("b", WaveshareEPaper4P2InBV2), "5.83in": ("b", WaveshareEPaper5P8In), diff --git a/esphome/components/waveshare_epaper/waveshare_epaper.cpp b/esphome/components/waveshare_epaper/waveshare_epaper.cpp index cf43c4cc32..7224aa44ed 100644 --- a/esphome/components/waveshare_epaper/waveshare_epaper.cpp +++ b/esphome/components/waveshare_epaper/waveshare_epaper.cpp @@ -1127,6 +1127,131 @@ void WaveshareEPaper2P9InB::dump_config() { LOG_UPDATE_INTERVAL(this); } +// DKE 2.9 +// https://www.badge.team/docs/badges/sha2017/hardware/#e-ink-display-the-dke-group-depg0290b1 +// https://www.badge.team/docs/badges/sha2017/hardware/DEPG0290B01V3.0.pdf +static const uint8_t LUT_SIZE_DKE = 70; +static const uint8_t UPDATE_LUT_DKE[LUT_SIZE_DKE] = { + 0xA0, 0x90, 0x50, 0x0, 0x0, 0x0, 0x0, 0x50, 0x90, 0xA0, 0x0, 0x0, 0x0, 0x0, 0xA0, 0x90, 0x50, 0x0, + 0x0, 0x0, 0x0, 0x50, 0x90, 0xA0, 0x0, 0x0, 0x0, 0x0, 0x00, 0x00, 0x00, 0x0, 0x0, 0x0, 0x0, 0xF, + 0xF, 0x0, 0x0, 0x0, 0xF, 0xF, 0x0, 0x0, 0x02, 0xF, 0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +}; +static const uint8_t PART_UPDATE_LUT_DKE[LUT_SIZE_DKE] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xa0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x50, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x05, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t FULL_UPDATE_LUT_DKE[LUT_SIZE_DKE] = { + 0x90, 0x50, 0xa0, 0x50, 0x50, 0x00, 0x00, 0x00, 0x00, 0x10, 0xa0, 0xa0, 0x80, 0x00, 0x90, 0x50, 0xa0, 0x50, + 0x50, 0x00, 0x00, 0x00, 0x00, 0x10, 0xa0, 0xa0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, + 0x04, 0x00, 0x00, 0x00, 0x0b, 0x04, 0x00, 0x00, 0x00, 0x06, 0x05, 0x00, 0x00, 0x00, 0x04, 0x05, 0x00, 0x00, + 0x00, 0x01, 0x0e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +void WaveshareEPaper2P9InDKE::initialize() { + // Hardware reset + delay(10); + this->reset_pin_->digital_write(false); + delayMicroseconds(200); + this->reset_pin_->digital_write(true); + delayMicroseconds(200); + // Wait for busy low + this->wait_until_idle_(); + // Software reset + this->command(0x12); + // Wait for busy low + this->wait_until_idle_(); + // Set Analog Block Control + this->command(0x74); + this->data(0x54); + // Set Digital Block Control + this->command(0x7E); + this->data(0x3B); + // Set display size and driver output control + this->command(0x01); + // this->data(0x27); + // this->data(0x01); + // this->data(0x00); + this->data(this->get_height_internal() - 1); + this->data((this->get_height_internal() - 1) >> 8); + this->data(0x00); // ? GD = 0, SM = 0, TB = 0 + // Ram data entry mode + this->command(0x11); + this->data(0x03); + // Set Ram X address + this->command(0x44); + this->data(0x00); + this->data(0x0F); + // Set Ram Y address + this->command(0x45); + this->data(0x00); + this->data(0x00); + this->data(0x27); + this->data(0x01); + // Set border + this->command(0x3C); + // this->data(0x80); + this->data(0x01); + // Set VCOM value + this->command(0x2C); + this->data(0x26); + // Gate voltage setting + this->command(0x03); + this->data(0x17); + // Source voltage setting + this->command(0x04); + this->data(0x41); + this->data(0x00); + this->data(0x32); + // Frame setting 50hz + this->command(0x3A); + this->data(0x30); + this->command(0x3B); + this->data(0x0A); + // Load LUT + this->command(0x32); + for (uint8_t v : FULL_UPDATE_LUT_DKE) + this->data(v); +} + +void HOT WaveshareEPaper2P9InDKE::display() { + ESP_LOGI(TAG, "Performing e-paper update."); + // Set Ram X address counter + this->command(0x4e); + this->data(0); + // Set Ram Y address counter + this->command(0x4f); + this->data(0); + this->data(0); + // Load image (128/8*296) + this->command(0x24); + this->start_data_(); + this->write_array(this->buffer_, this->get_buffer_length_()); + this->end_data_(); + // Image update + this->command(0x22); + this->data(0xC7); + this->command(0x20); + // Wait for busy low + this->wait_until_idle_(); + // Enter deep sleep mode + this->command(0x10); + this->data(0x01); +} +int WaveshareEPaper2P9InDKE::get_width_internal() { return 128; } +int WaveshareEPaper2P9InDKE::get_height_internal() { return 296; } +void WaveshareEPaper2P9InDKE::dump_config() { + LOG_DISPLAY("", "Waveshare E-Paper", this); + ESP_LOGCONFIG(TAG, " Model: 2.9in DKE"); + LOG_PIN(" Reset Pin: ", this->reset_pin_); + LOG_PIN(" DC Pin: ", this->dc_pin_); + LOG_PIN(" Busy Pin: ", this->busy_pin_); + LOG_UPDATE_INTERVAL(this); +} +void WaveshareEPaper2P9InDKE::set_full_update_every(uint32_t full_update_every) { + this->full_update_every_ = full_update_every; +} + // ======================================================== // 2.90in Type B (LUT from OTP) // Datasheet: diff --git a/esphome/components/waveshare_epaper/waveshare_epaper.h b/esphome/components/waveshare_epaper/waveshare_epaper.h index ffc099ca56..3c4470c30c 100644 --- a/esphome/components/waveshare_epaper/waveshare_epaper.h +++ b/esphome/components/waveshare_epaper/waveshare_epaper.h @@ -373,6 +373,30 @@ class WaveshareEPaper2P9InV2R2 : public WaveshareEPaper { void reset_(); }; +class WaveshareEPaper2P9InDKE : public WaveshareEPaper { + public: + void initialize() override; + + void display() override; + + void dump_config() override; + + void deep_sleep() override { + // COMMAND DEEP SLEEP + this->command(0x10); + this->data(0x01); + } + + void set_full_update_every(uint32_t full_update_every); + + protected: + uint32_t full_update_every_{30}; + uint32_t at_update_{0}; + int get_width_internal() override; + + int get_height_internal() override; +}; + class WaveshareEPaper4P2In : public WaveshareEPaper { public: void initialize() override; diff --git a/tests/components/waveshare_epaper/test.esp32.yaml b/tests/components/waveshare_epaper/test.esp32.yaml index cc6c665e7d..2f06c5c51b 100644 --- a/tests/components/waveshare_epaper/test.esp32.yaml +++ b/tests/components/waveshare_epaper/test.esp32.yaml @@ -83,6 +83,24 @@ display: full_update_every: 30 lambda: |- it.rectangle(0, 0, it.get_width(), it.get_height()); + - platform: waveshare_epaper + model: 2.90in-dke + spi_id: spi_id_1 + cs_pin: + allow_other_uses: true + number: GPIO25 + dc_pin: + allow_other_uses: true + number: GPIO26 + busy_pin: + allow_other_uses: true + number: GPIO27 + reset_pin: + allow_other_uses: true + number: GPIO32 + full_update_every: 1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); - platform: waveshare_epaper model: 2.70in-b spi_id: spi_id_1 From 9bfb36f58bcdaff1d5b62a2ea303d45a10af291e Mon Sep 17 00:00:00 2001 From: Alex Boyd Date: Fri, 26 Apr 2024 05:41:43 -0600 Subject: [PATCH 1339/2101] Extract core comments from #6241 (#6643) --- esphome/automation.py | 10 ++++++++++ esphome/config_validation.py | 2 +- esphome/core/component.h | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/esphome/automation.py b/esphome/automation.py index 8475858a9c..b25ffa5abe 100644 --- a/esphome/automation.py +++ b/esphome/automation.py @@ -18,10 +18,20 @@ from esphome.util import Registry def maybe_simple_id(*validators): + """Allow a raw ID to be specified in place of a config block. + If the value that's being validated is a dictionary, it's passed as-is to the specified validators. Otherwise, it's + wrapped in a dict that looks like ``{"id": }``, and that dict is then handed off to the specified validators. + """ return maybe_conf(CONF_ID, *validators) def maybe_conf(conf, *validators): + """Allow a raw value to be specified in place of a config block. + If the value that's being validated is a dictionary, it's passed as-is to the specified validators. Otherwise, it's + wrapped in a dict that looks like ``{: }``, and that dict is then handed off to the specified + validators. + (This is a general case of ``maybe_simple_id`` that allows the wrapping key to be something other than ``id``.) + """ validator = cv.All(*validators) @schema_extractor("maybe") diff --git a/esphome/config_validation.py b/esphome/config_validation.py index bc58979f33..198b44f38d 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -304,7 +304,7 @@ def string(value): """Validate that a configuration value is a string. If not, automatically converts to a string. Note that this can be lossy, for example the input value 60.00 (float) will be turned into - "60.0" (string). For values where this could be a problem `string_string` has to be used. + "60.0" (string). For values where this could be a problem `string_strict` has to be used. """ check_not_templatable(value) if isinstance(value, (dict, list)): diff --git a/esphome/core/component.h b/esphome/core/component.h index 4f244e5fcb..e6ffe96d1e 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -85,7 +85,7 @@ class Component { /** priority of setup(). higher -> executed earlier * - * Defaults to 0. + * Defaults to setup_priority::DATA, i.e. 600. * * @return The setup priority of this component */ From 76c55992aeee8fb416417efa0a9a33a1b5e27b25 Mon Sep 17 00:00:00 2001 From: tronikos Date: Sat, 27 Apr 2024 18:22:41 -0700 Subject: [PATCH 1340/2101] Revert #6458 (#6650) Reading the z-axis register is required. --- esphome/components/qmc5883l/qmc5883l.cpp | 46 ++++++++---------------- 1 file changed, 15 insertions(+), 31 deletions(-) diff --git a/esphome/components/qmc5883l/qmc5883l.cpp b/esphome/components/qmc5883l/qmc5883l.cpp index 4946ad1b77..8541b41ff7 100644 --- a/esphome/components/qmc5883l/qmc5883l.cpp +++ b/esphome/components/qmc5883l/qmc5883l.cpp @@ -77,8 +77,17 @@ void QMC5883LComponent::dump_config() { float QMC5883LComponent::get_setup_priority() const { return setup_priority::DATA; } void QMC5883LComponent::update() { uint8_t status = false; - if (ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_DEBUG) - this->read_byte(QMC5883L_REGISTER_STATUS, &status); + this->read_byte(QMC5883L_REGISTER_STATUS, &status); + + // Always request X,Y,Z regardless if there are sensors for them + // to avoid https://github.com/esphome/issues/issues/5731 + uint16_t raw_x, raw_y, raw_z; + if (!this->read_byte_16_(QMC5883L_REGISTER_DATA_X_LSB, &raw_x) || + !this->read_byte_16_(QMC5883L_REGISTER_DATA_Y_LSB, &raw_y) || + !this->read_byte_16_(QMC5883L_REGISTER_DATA_Z_LSB, &raw_z)) { + this->status_set_warning(); + return; + } float mg_per_bit; switch (this->range_) { @@ -93,36 +102,11 @@ void QMC5883LComponent::update() { } // in µT - float x = NAN, y = NAN, z = NAN; - if (this->x_sensor_ != nullptr || this->heading_sensor_ != nullptr) { - uint16_t raw_x; - if (!this->read_byte_16_(QMC5883L_REGISTER_DATA_X_LSB, &raw_x)) { - this->status_set_warning(); - return; - } - x = int16_t(raw_x) * mg_per_bit * 0.1f; - } - if (this->y_sensor_ != nullptr || this->heading_sensor_ != nullptr) { - uint16_t raw_y; - if (!this->read_byte_16_(QMC5883L_REGISTER_DATA_Y_LSB, &raw_y)) { - this->status_set_warning(); - return; - } - y = int16_t(raw_y) * mg_per_bit * 0.1f; - } - if (this->z_sensor_ != nullptr) { - uint16_t raw_z; - if (!this->read_byte_16_(QMC5883L_REGISTER_DATA_Z_LSB, &raw_z)) { - this->status_set_warning(); - return; - } - z = int16_t(raw_z) * mg_per_bit * 0.1f; - } + const float x = int16_t(raw_x) * mg_per_bit * 0.1f; + const float y = int16_t(raw_y) * mg_per_bit * 0.1f; + const float z = int16_t(raw_z) * mg_per_bit * 0.1f; - float heading = NAN; - if (this->heading_sensor_ != nullptr) { - heading = atan2f(0.0f - x, y) * 180.0f / M_PI; - } + float heading = atan2f(0.0f - x, y) * 180.0f / M_PI; float temp = NAN; if (this->temperature_sensor_ != nullptr) { From 0ef7781bb34f0b7f636942e16a0e638acdf597c5 Mon Sep 17 00:00:00 2001 From: optimusprimespace <62800678+optimusprimespace@users.noreply.github.com> Date: Sun, 28 Apr 2024 21:22:14 +0200 Subject: [PATCH 1341/2101] [hm3301] Updated the AQI based on the airnow document (#6004) --- esphome/components/hm3301/aqi_calculator.h | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/esphome/components/hm3301/aqi_calculator.h b/esphome/components/hm3301/aqi_calculator.h index 6c830f9bad..c1b47826a2 100644 --- a/esphome/components/hm3301/aqi_calculator.h +++ b/esphome/components/hm3301/aqi_calculator.h @@ -1,6 +1,7 @@ #pragma once #include "abstract_aqi_calculator.h" +// https://www.airnow.gov/sites/default/files/2020-05/aqi-technical-assistance-document-sept2018.pdf namespace esphome { namespace hm3301 { @@ -15,14 +16,16 @@ class AQICalculator : public AbstractAQICalculator { } protected: - static const int AMOUNT_OF_LEVELS = 6; + static const int AMOUNT_OF_LEVELS = 7; - int index_grid_[AMOUNT_OF_LEVELS][2] = {{0, 51}, {51, 100}, {101, 150}, {151, 200}, {201, 300}, {301, 500}}; + int index_grid_[AMOUNT_OF_LEVELS][2] = {{0, 50}, {51, 100}, {101, 150}, {151, 200}, + {201, 300}, {301, 400}, {401, 500}}; - int pm2_5_calculation_grid_[AMOUNT_OF_LEVELS][2] = {{0, 12}, {13, 35}, {36, 55}, {56, 150}, {151, 250}, {251, 500}}; + int pm2_5_calculation_grid_[AMOUNT_OF_LEVELS][2] = {{0, 12}, {13, 35}, {36, 55}, {56, 150}, + {151, 250}, {251, 350}, {351, 500}}; - int pm10_0_calculation_grid_[AMOUNT_OF_LEVELS][2] = {{0, 54}, {55, 154}, {155, 254}, - {255, 354}, {355, 424}, {425, 604}}; + int pm10_0_calculation_grid_[AMOUNT_OF_LEVELS][2] = {{0, 54}, {55, 154}, {155, 254}, {255, 354}, + {355, 424}, {425, 504}, {505, 604}}; int calculate_index_(uint16_t value, int array[AMOUNT_OF_LEVELS][2]) { int grid_index = get_grid_index_(value, array); From a700ae481d24ab9cb7c8ffb1b018967a25523823 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 29 Apr 2024 07:33:52 +1200 Subject: [PATCH 1342/2101] Fix command line substitutions without any yaml substitutions (#6644) --- esphome/components/substitutions/__init__.py | 2 +- esphome/config.py | 4 ++-- script/test_build_components | 4 ++-- tests/test_build_components/build_components_base.bk72xx.yaml | 4 ---- .../build_components_base.esp32-ard.yaml | 4 ---- .../build_components_base.esp32-c3-ard.yaml | 4 ---- .../build_components_base.esp32-c3-idf.yaml | 4 ---- .../build_components_base.esp32-idf.yaml | 4 ---- .../build_components_base.esp32-s2-ard.yaml | 4 ---- .../build_components_base.esp32-s2-idf.yaml | 4 ---- .../build_components_base.esp32-s3-ard.yaml | 4 ---- .../build_components_base.esp32-s3-idf.yaml | 4 ---- .../test_build_components/build_components_base.esp8266.yaml | 4 ---- tests/test_build_components/build_components_base.host.yaml | 4 ---- tests/test_build_components/build_components_base.rp2040.yaml | 4 ---- 15 files changed, 5 insertions(+), 53 deletions(-) diff --git a/esphome/components/substitutions/__init__.py b/esphome/components/substitutions/__init__.py index ef368015b1..2d3a79ccae 100644 --- a/esphome/components/substitutions/__init__.py +++ b/esphome/components/substitutions/__init__.py @@ -116,7 +116,7 @@ def do_substitution_pass(config, command_line_substitutions, ignore_missing=Fals if CONF_SUBSTITUTIONS not in config and not command_line_substitutions: return - substitutions = config[CONF_SUBSTITUTIONS] + substitutions = config.get(CONF_SUBSTITUTIONS) if substitutions is None: substitutions = command_line_substitutions elif command_line_substitutions: diff --git a/esphome/config.py b/esphome/config.py index 1f6867eb59..73aa7077e0 100644 --- a/esphome/config.py +++ b/esphome/config.py @@ -756,11 +756,11 @@ def validate_config( CORE.raw_config = config # 1. Load substitutions - if CONF_SUBSTITUTIONS in config: + if CONF_SUBSTITUTIONS in config or command_line_substitutions: from esphome.components import substitutions result[CONF_SUBSTITUTIONS] = { - **config[CONF_SUBSTITUTIONS], + **config.get(CONF_SUBSTITUTIONS, {}), **command_line_substitutions, } result.add_output_path([CONF_SUBSTITUTIONS], CONF_SUBSTITUTIONS) diff --git a/script/test_build_components b/script/test_build_components index 2396353198..4d91256572 100755 --- a/script/test_build_components +++ b/script/test_build_components @@ -37,9 +37,9 @@ start_esphome() { # Start esphome process echo "> [$target_component] [$test_name] [$target_platform]" - echo "esphome -s component_name $target_component -s test_name $test_name -s target_platform $target_platform $esphome_command $component_test_file" + echo "esphome -s component_name $target_component -s component_dir ../../components/$target_component -s test_name $test_name -s target_platform $target_platform $esphome_command $component_test_file" # TODO: Validate escape of Command line substitution value - esphome -s component_name $target_component -s test_name $test_name -s target_platform $target_platform $esphome_command $component_test_file + esphome -s component_name $target_component -s component_dir ../../components/$target_component -s test_name $test_name -s target_platform $target_platform $esphome_command $component_test_file } # Find all test yaml files. diff --git a/tests/test_build_components/build_components_base.bk72xx.yaml b/tests/test_build_components/build_components_base.bk72xx.yaml index d74cc651eb..9fd9431826 100644 --- a/tests/test_build_components/build_components_base.bk72xx.yaml +++ b/tests/test_build_components/build_components_base.bk72xx.yaml @@ -12,8 +12,4 @@ packages: component_under_test: !include file: $component_test_file vars: - component_name: $component_name - test_name: $test_name - target_platform: $target_platform component_test_file: $component_test_file - component_dir: "../../components/$component_name" diff --git a/tests/test_build_components/build_components_base.esp32-ard.yaml b/tests/test_build_components/build_components_base.esp32-ard.yaml index e345adcafc..31b7067acc 100644 --- a/tests/test_build_components/build_components_base.esp32-ard.yaml +++ b/tests/test_build_components/build_components_base.esp32-ard.yaml @@ -14,8 +14,4 @@ packages: component_under_test: !include file: $component_test_file vars: - component_name: $component_name - test_name: $test_name - target_platform: $target_platform component_test_file: $component_test_file - component_dir: "../../components/$component_name" diff --git a/tests/test_build_components/build_components_base.esp32-c3-ard.yaml b/tests/test_build_components/build_components_base.esp32-c3-ard.yaml index 136ee62d4b..8aad447693 100644 --- a/tests/test_build_components/build_components_base.esp32-c3-ard.yaml +++ b/tests/test_build_components/build_components_base.esp32-c3-ard.yaml @@ -14,8 +14,4 @@ packages: component_under_test: !include file: $component_test_file vars: - component_name: $component_name - test_name: $test_name - target_platform: $target_platform component_test_file: $component_test_file - component_dir: "../../components/$component_name" diff --git a/tests/test_build_components/build_components_base.esp32-c3-idf.yaml b/tests/test_build_components/build_components_base.esp32-c3-idf.yaml index 4e809dd7ce..18584497f4 100644 --- a/tests/test_build_components/build_components_base.esp32-c3-idf.yaml +++ b/tests/test_build_components/build_components_base.esp32-c3-idf.yaml @@ -14,8 +14,4 @@ packages: component_under_test: !include file: $component_test_file vars: - component_name: $component_name - test_name: $test_name - target_platform: $target_platform component_test_file: $component_test_file - component_dir: "../../components/$component_name" diff --git a/tests/test_build_components/build_components_base.esp32-idf.yaml b/tests/test_build_components/build_components_base.esp32-idf.yaml index 3c4532a958..a62a995e68 100644 --- a/tests/test_build_components/build_components_base.esp32-idf.yaml +++ b/tests/test_build_components/build_components_base.esp32-idf.yaml @@ -14,8 +14,4 @@ packages: component_under_test: !include file: $component_test_file vars: - component_name: $component_name - test_name: $test_name - target_platform: $target_platform component_test_file: $component_test_file - component_dir: "../../components/$component_name" diff --git a/tests/test_build_components/build_components_base.esp32-s2-ard.yaml b/tests/test_build_components/build_components_base.esp32-s2-ard.yaml index db62cdff6a..b8f2639127 100644 --- a/tests/test_build_components/build_components_base.esp32-s2-ard.yaml +++ b/tests/test_build_components/build_components_base.esp32-s2-ard.yaml @@ -15,8 +15,4 @@ packages: component_under_test: !include file: $component_test_file vars: - component_name: $component_name - test_name: $test_name - target_platform: $target_platform component_test_file: $component_test_file - component_dir: "../../components/$component_name" diff --git a/tests/test_build_components/build_components_base.esp32-s2-idf.yaml b/tests/test_build_components/build_components_base.esp32-s2-idf.yaml index 19fb657d8b..62f0f4f7bc 100644 --- a/tests/test_build_components/build_components_base.esp32-s2-idf.yaml +++ b/tests/test_build_components/build_components_base.esp32-s2-idf.yaml @@ -15,8 +15,4 @@ packages: component_under_test: !include file: $component_test_file vars: - component_name: $component_name - test_name: $test_name - target_platform: $target_platform component_test_file: $component_test_file - component_dir: "../../components/$component_name" diff --git a/tests/test_build_components/build_components_base.esp32-s3-ard.yaml b/tests/test_build_components/build_components_base.esp32-s3-ard.yaml index 39e12de08c..25cad038b6 100644 --- a/tests/test_build_components/build_components_base.esp32-s3-ard.yaml +++ b/tests/test_build_components/build_components_base.esp32-s3-ard.yaml @@ -15,8 +15,4 @@ packages: component_under_test: !include file: $component_test_file vars: - component_name: $component_name - test_name: $test_name - target_platform: $target_platform component_test_file: $component_test_file - component_dir: "../../components/$component_name" diff --git a/tests/test_build_components/build_components_base.esp32-s3-idf.yaml b/tests/test_build_components/build_components_base.esp32-s3-idf.yaml index 95c73f917e..b1d08fcdf8 100644 --- a/tests/test_build_components/build_components_base.esp32-s3-idf.yaml +++ b/tests/test_build_components/build_components_base.esp32-s3-idf.yaml @@ -15,8 +15,4 @@ packages: component_under_test: !include file: $component_test_file vars: - component_name: $component_name - test_name: $test_name - target_platform: $target_platform component_test_file: $component_test_file - component_dir: "../../components/$component_name" diff --git a/tests/test_build_components/build_components_base.esp8266.yaml b/tests/test_build_components/build_components_base.esp8266.yaml index 0019298ef0..ecf9acd2ba 100644 --- a/tests/test_build_components/build_components_base.esp8266.yaml +++ b/tests/test_build_components/build_components_base.esp8266.yaml @@ -12,8 +12,4 @@ packages: component_under_test: !include file: $component_test_file vars: - component_name: $component_name - test_name: $test_name - target_platform: $target_platform component_test_file: $component_test_file - component_dir: "../../components/$component_name" diff --git a/tests/test_build_components/build_components_base.host.yaml b/tests/test_build_components/build_components_base.host.yaml index ec7570d99a..5492cfddd2 100644 --- a/tests/test_build_components/build_components_base.host.yaml +++ b/tests/test_build_components/build_components_base.host.yaml @@ -12,8 +12,4 @@ packages: component_under_test: !include file: $component_test_file vars: - component_name: $component_name - test_name: $test_name - target_platform: $target_platform component_test_file: $component_test_file - component_dir: "../../components/$component_name" diff --git a/tests/test_build_components/build_components_base.rp2040.yaml b/tests/test_build_components/build_components_base.rp2040.yaml index cb1cb6359b..335642374b 100644 --- a/tests/test_build_components/build_components_base.rp2040.yaml +++ b/tests/test_build_components/build_components_base.rp2040.yaml @@ -15,8 +15,4 @@ packages: component_under_test: !include file: $component_test_file vars: - component_name: $component_name - test_name: $test_name - target_platform: $target_platform component_test_file: $component_test_file - component_dir: "../../components/$component_name" From 8334934e0825884946f0e6a18b461d015c080c54 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Sun, 28 Apr 2024 14:44:40 -0500 Subject: [PATCH 1343/2101] Allow platform dependencies (#6623) --- esphome/config.py | 28 +++++++++++++++++++++++++--- script/list-components.py | 8 ++++++-- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/esphome/config.py b/esphome/config.py index 73aa7077e0..36a81f677b 100644 --- a/esphome/config.py +++ b/esphome/config.py @@ -374,7 +374,10 @@ class LoadValidationStep(ConfigValidationStep): path + [CONF_ID], ) continue - result.add_str_error("No platform specified! See 'platform' key.", path) + result.add_str_error( + f"'{self.domain}' requires a 'platform' key but it was not specified.", + path, + ) continue # Remove temp output path and construct new one result.remove_output_path(path, p_domain) @@ -449,9 +452,28 @@ class MetadataValidationStep(ConfigValidationStep): success = True for dependency in self.comp.dependencies: - if dependency not in result: + dependency_parts = dependency.split(".") + if len(dependency_parts) > 2: result.add_str_error( - f"Component {self.domain} requires component {dependency}", + "Dependencies must be specified as a single component or in component.platform format only", + self.path, + ) + return + component_dep = dependency_parts[0] + platform_dep = dependency_parts[-1] + if component_dep not in result: + result.add_str_error( + f"Component {self.domain} requires component {component_dep}", + self.path, + ) + success = False + elif component_dep != platform_dep and ( + not isinstance(platform_list := result.get(component_dep), list) + or not any(CONF_PLATFORM in p for p in platform_list) + or not any(p[CONF_PLATFORM] == platform_dep for p in platform_list) + ): + result.add_str_error( + f"Component {self.domain} requires 'platform: {platform_dep}' in component '{component_dep}'", self.path, ) success = False diff --git a/script/list-components.py b/script/list-components.py index 8e2d47c6b3..5b5fa5811f 100755 --- a/script/list-components.py +++ b/script/list-components.py @@ -69,7 +69,9 @@ def create_components_graph(): sys.exit(1) for dependency in comp.dependencies: - add_item_to_components_graph(components_graph, dependency, name) + add_item_to_components_graph( + components_graph, dependency.split(".")[0], name + ) for target_config in TARGET_CONFIGURATIONS: CORE.data[KEY_CORE] = target_config @@ -87,7 +89,9 @@ def create_components_graph(): add_item_to_components_graph(components_graph, platform_name, name) for dependency in platform.dependencies: - add_item_to_components_graph(components_graph, dependency, name) + add_item_to_components_graph( + components_graph, dependency.split(".")[0], name + ) for target_config in TARGET_CONFIGURATIONS: CORE.data[KEY_CORE] = target_config From 5142d294f5204819fd6b5a858971b11a463620c3 Mon Sep 17 00:00:00 2001 From: Lucas Hartmann Date: Sun, 28 Apr 2024 16:47:15 -0300 Subject: [PATCH 1344/2101] [light] Add transition_length to strobe effect. (#6595) --- esphome/components/light/base_light_effects.h | 3 ++- esphome/components/light/effects.py | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/esphome/components/light/base_light_effects.h b/esphome/components/light/base_light_effects.h index c62ca43ca1..f7829a3f44 100644 --- a/esphome/components/light/base_light_effects.h +++ b/esphome/components/light/base_light_effects.h @@ -150,6 +150,7 @@ class AutomationLightEffect : public LightEffect { struct StrobeLightEffectColor { LightColorValues color; uint32_t duration; + uint32_t transition_length; }; class StrobeLightEffect : public LightEffect { @@ -174,7 +175,7 @@ class StrobeLightEffect : public LightEffect { } call.set_publish(false); call.set_save(false); - call.set_transition_length_if_supported(0); + call.set_transition_length_if_supported(this->colors_[this->at_color_].transition_length); call.perform(); this->last_switch_ = now; } diff --git a/esphome/components/light/effects.py b/esphome/components/light/effects.py index 5093ace949..be50f63321 100644 --- a/esphome/components/light/effects.py +++ b/esphome/components/light/effects.py @@ -266,6 +266,9 @@ async def random_effect_to_code(config, effect_id): cv.Required( CONF_DURATION ): cv.positive_time_period_milliseconds, + cv.Optional( + CONF_TRANSITION_LENGTH, default="0s" + ): cv.positive_time_period_milliseconds, } ), cv.has_at_least_one_key( @@ -310,6 +313,7 @@ async def strobe_effect_to_code(config, effect_id): ), ), ("duration", color[CONF_DURATION]), + ("transition_length", color[CONF_TRANSITION_LENGTH]), ) ) cg.add(var.set_colors(colors)) From 8b6a35845250deee6021fcd993467023f35d7f49 Mon Sep 17 00:00:00 2001 From: chiahsing Date: Mon, 29 Apr 2024 03:49:27 +0800 Subject: [PATCH 1345/2101] Fixed the issue that graph draws out of the boundary. (#6651) --- esphome/components/graph/graph.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/esphome/components/graph/graph.cpp b/esphome/components/graph/graph.cpp index 1178af911d..09f7557714 100644 --- a/esphome/components/graph/graph.cpp +++ b/esphome/components/graph/graph.cpp @@ -177,22 +177,26 @@ void Graph::draw(Display *buff, uint16_t x_offset, uint16_t y_offset, Color colo bool b = (trace->get_line_type() & bit) == bit; if (b) { int16_t y = (int16_t) roundf((this->height_ - 1) * (1.0 - v)) - thick / 2 + y_offset; + auto draw_pixel_at = [&buff, c, y_offset, this](int16_t x, int16_t y) { + if (y >= y_offset && y < y_offset + this->height_) + buff->draw_pixel_at(x, y, c); + }; if (!continuous || !has_prev || !prev_b || (abs(y - prev_y) <= thick)) { for (int16_t t = 0; t < thick; t++) { - buff->draw_pixel_at(x, y + t, c); + draw_pixel_at(x, y + t); } } else { int16_t mid_y = (y + prev_y + thick) / 2; if (y > prev_y) { for (int16_t t = prev_y + thick; t <= mid_y; t++) - buff->draw_pixel_at(x + 1, t, c); + draw_pixel_at(x + 1, t); for (int16_t t = mid_y + 1; t < y + thick; t++) - buff->draw_pixel_at(x, t, c); + draw_pixel_at(x, t); } else { for (int16_t t = prev_y - 1; t >= mid_y; t--) - buff->draw_pixel_at(x + 1, t, c); + draw_pixel_at(x + 1, t); for (int16_t t = mid_y - 1; t >= y; t--) - buff->draw_pixel_at(x, t, c); + draw_pixel_at(x, t); } } prev_y = y; From 9ea442f3286ecb62b72f93133afb9f9a69d44fa2 Mon Sep 17 00:00:00 2001 From: Ulrich Date: Sun, 28 Apr 2024 21:56:13 +0200 Subject: [PATCH 1346/2101] Fix upload command. MQTT user and password is missing from configuration. #5093 (#5766) Co-authored-by: ulrich Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/__main__.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/esphome/__main__.py b/esphome/__main__.py index dcd2dddb4b..b461dda4e7 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -768,7 +768,9 @@ def parse_args(argv): ) parser_upload = subparsers.add_parser( - "upload", help="Validate the configuration and upload the latest binary." + "upload", + help="Validate the configuration and upload the latest binary.", + parents=[mqtt_options], ) parser_upload.add_argument( "configuration", help="Your YAML configuration file(s).", nargs="+" From e7c1ddb4525031c90df0e76414cae81577d9d953 Mon Sep 17 00:00:00 2001 From: Matt Quigley Date: Sun, 28 Apr 2024 14:57:11 -0500 Subject: [PATCH 1347/2101] patch esphome cli to skip mqtt based device discovery if --device option is specified (#6371) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/__main__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/esphome/__main__.py b/esphome/__main__.py index b461dda4e7..54c1aa112a 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -343,9 +343,10 @@ def upload_program(config, args, host): password = ota_conf.get(CONF_PASSWORD, "") if ( - not is_ip_address(CORE.address) + not is_ip_address(CORE.address) # pylint: disable=too-many-boolean-expressions and (get_port_type(host) == "MQTT" or config[CONF_MDNS][CONF_DISABLED]) and CONF_MQTT in config + and (not args.device or args.device == "MQTT") ): from esphome import mqtt From 80a0b5b1b109b424b85b5b00d5af84cec482c7bd Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 29 Apr 2024 12:10:12 +1200 Subject: [PATCH 1348/2101] [i2s_audio.microphone] Fixing adc bug (#6654) --- .../microphone/i2s_audio_microphone.cpp | 65 +++++++++++++++++-- 1 file changed, 58 insertions(+), 7 deletions(-) diff --git a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp index 602d537bcb..1475df0975 100644 --- a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +++ b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp @@ -61,28 +61,57 @@ void I2SAudioMicrophone::start_() { .bits_per_chan = I2S_BITS_PER_CHAN_DEFAULT, }; + esp_err_t err; + #if SOC_I2S_SUPPORTS_ADC if (this->adc_) { config.mode = (i2s_mode_t) (config.mode | I2S_MODE_ADC_BUILT_IN); - i2s_driver_install(this->parent_->get_port(), &config, 0, nullptr); + err = i2s_driver_install(this->parent_->get_port(), &config, 0, nullptr); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Error installing I2S driver: %s", esp_err_to_name(err)); + this->status_set_error(); + return; + } + + err = i2s_set_adc_mode(ADC_UNIT_1, this->adc_channel_); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Error setting ADC mode: %s", esp_err_to_name(err)); + this->status_set_error(); + return; + } + err = i2s_adc_enable(this->parent_->get_port()); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Error enabling ADC: %s", esp_err_to_name(err)); + this->status_set_error(); + return; + } - i2s_set_adc_mode(ADC_UNIT_1, this->adc_channel_); - i2s_adc_enable(this->parent_->get_port()); } else #endif { if (this->pdm_) config.mode = (i2s_mode_t) (config.mode | I2S_MODE_PDM); - i2s_driver_install(this->parent_->get_port(), &config, 0, nullptr); + err = i2s_driver_install(this->parent_->get_port(), &config, 0, nullptr); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Error installing I2S driver: %s", esp_err_to_name(err)); + this->status_set_error(); + return; + } i2s_pin_config_t pin_config = this->parent_->get_pin_config(); pin_config.data_in_num = this->din_pin_; - i2s_set_pin(this->parent_->get_port(), &pin_config); + err = i2s_set_pin(this->parent_->get_port(), &pin_config); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Error setting I2S pin: %s", esp_err_to_name(err)); + this->status_set_error(); + return; + } } this->state_ = microphone::STATE_RUNNING; this->high_freq_.start(); + this->status_clear_error(); } void I2SAudioMicrophone::stop() { @@ -96,11 +125,33 @@ void I2SAudioMicrophone::stop() { } void I2SAudioMicrophone::stop_() { - i2s_stop(this->parent_->get_port()); - i2s_driver_uninstall(this->parent_->get_port()); + esp_err_t err; +#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)); + this->status_set_error(); + return; + } + } +#endif + err = i2s_stop(this->parent_->get_port()); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Error stopping I2S microphone: %s", esp_err_to_name(err)); + this->status_set_error(); + return; + } + err = i2s_driver_uninstall(this->parent_->get_port()); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Error uninstalling I2S driver: %s", esp_err_to_name(err)); + this->status_set_error(); + return; + } this->parent_->unlock(); this->state_ = microphone::STATE_STOPPED; this->high_freq_.stop(); + this->status_clear_error(); } size_t I2SAudioMicrophone::read(int16_t *buf, size_t len) { From c007593f729d96c34566d6c36a5fb9b817cbc692 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Mon, 29 Apr 2024 13:53:08 +1000 Subject: [PATCH 1349/2101] Fix for #4866 - inconsistent arguments (#6639) --- esphome/components/binary_sensor/automation.cpp | 6 +++--- esphome/core/helpers.cpp | 2 +- tests/components/host/test.host.yaml | 15 +++++++++++++++ 3 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 tests/components/host/test.host.yaml diff --git a/esphome/components/binary_sensor/automation.cpp b/esphome/components/binary_sensor/automation.cpp index bfec882e07..7ac201b2db 100644 --- a/esphome/components/binary_sensor/automation.cpp +++ b/esphome/components/binary_sensor/automation.cpp @@ -51,15 +51,15 @@ void binary_sensor::MultiClickTrigger::on_state_(bool state) { MultiClickTriggerEvent evt = this->timing_[*this->at_index_]; if (evt.max_length != 4294967294UL) { - ESP_LOGV(TAG, "A i=%u min=%" PRIu32 " max=%" PRIu32, *this->at_index_, evt.min_length, evt.max_length); // NOLINT + 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()) { - ESP_LOGV(TAG, "B i=%u min=%" PRIu32, *this->at_index_, evt.min_length); // NOLINT + ESP_LOGV(TAG, "B i=%zu min=%" PRIu32, *this->at_index_, evt.min_length); // NOLINT this->cancel_timeout("is_not_valid"); this->schedule_is_valid_(evt.min_length); } else { - ESP_LOGV(TAG, "C i=%u min=%" PRIu32, *this->at_index_, evt.min_length); // NOLINT + 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_(); }); diff --git a/esphome/core/helpers.cpp b/esphome/core/helpers.cpp index 4368576301..fdc0eed774 100644 --- a/esphome/core/helpers.cpp +++ b/esphome/core/helpers.cpp @@ -437,7 +437,7 @@ static inline bool is_base64(char c) { return (isalnum(c) || (c == '+') || (c == std::string base64_encode(const std::vector &buf) { return base64_encode(buf.data(), buf.size()); } -std::string base64_encode(const char *buf, unsigned int buf_len) { +std::string base64_encode(const uint8_t *buf, size_t buf_len) { std::string ret; int i = 0; int j = 0; diff --git a/tests/components/host/test.host.yaml b/tests/components/host/test.host.yaml new file mode 100644 index 0000000000..3d14c190a6 --- /dev/null +++ b/tests/components/host/test.host.yaml @@ -0,0 +1,15 @@ +time: + - platform: sntp + id: esptime + timezone: Australia/Sydney + +logger: + level: VERBOSE + logs: + lvgl: INFO + display: DEBUG + sensor: INFO + vnc: DEBUG + +host: + mac_address: "62:23:45:AF:B3:DD" From 73bb4aa4d5428cd4d1034d8dd7ad9800903d632f Mon Sep 17 00:00:00 2001 From: Anton Sergunov Date: Mon, 29 Apr 2024 16:40:03 +0600 Subject: [PATCH 1350/2101] [template/text] Fix lambda config (#6655) Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> --- esphome/components/template/text/__init__.py | 2 +- tests/component_tests/text/test_text.py | 14 ++++++++++++++ tests/component_tests/text/test_text.yaml | 12 ++++++++++++ tests/components/template/common.yaml | 11 +++++++++++ 4 files changed, 38 insertions(+), 1 deletion(-) diff --git a/esphome/components/template/text/__init__.py b/esphome/components/template/text/__init__.py index 0f228a3c6b..f73b240197 100644 --- a/esphome/components/template/text/__init__.py +++ b/esphome/components/template/text/__init__.py @@ -28,7 +28,7 @@ def validate(config): raise cv.Invalid("optimistic cannot be used with lambda") if CONF_INITIAL_VALUE in config: raise cv.Invalid("initial_value cannot be used with lambda") - if CONF_RESTORE_VALUE in config: + if config[CONF_RESTORE_VALUE]: raise cv.Invalid("restore_value cannot be used with lambda") elif CONF_INITIAL_VALUE not in config: config[CONF_INITIAL_VALUE] = "" diff --git a/tests/component_tests/text/test_text.py b/tests/component_tests/text/test_text.py index 43f4ef2592..51fcb3d382 100644 --- a/tests/component_tests/text/test_text.py +++ b/tests/component_tests/text/test_text.py @@ -54,3 +54,17 @@ def test_text_config_value_mode_set(generate_main): # Then assert "it_1->traits.set_mode(text::TEXT_MODE_TEXT);" in main_cpp assert "it_3->traits.set_mode(text::TEXT_MODE_PASSWORD);" in main_cpp + + +def test_text_config_lamda_is_set(generate_main): + """ + Test if lambda is set for lambda mode + """ + # Given + + # When + main_cpp = generate_main("tests/component_tests/text/test_text.yaml") + + # Then + assert "it_4->set_template([=]() -> optional {" in main_cpp + assert 'return std::string{"Hello"};' in main_cpp diff --git a/tests/component_tests/text/test_text.yaml b/tests/component_tests/text/test_text.yaml index d0fdf5303f..d81c909f9d 100644 --- a/tests/component_tests/text/test_text.yaml +++ b/tests/component_tests/text/test_text.yaml @@ -31,3 +31,15 @@ text: optimistic: true internal: true max_length: 255 + + - platform: template + name: "test 4 key" + id: "it_4" + mode: text + set_action: + - then: + - logger.log: + format: Template text set to %s + args: ["x.c_str()"] + lambda: | + return std::string{"Hello"}; diff --git a/tests/components/template/common.yaml b/tests/components/template/common.yaml index ba7167157b..2b91225b5a 100644 --- a/tests/components/template/common.yaml +++ b/tests/components/template/common.yaml @@ -149,6 +149,17 @@ text: min_length: 0 max_length: 100 mode: text + - platform: template + name: "Template text lambda" + mode: text + update_interval: 1s + lambda: | + return std::string{"Hello!"}; + set_action: + then: + - logger.log: + format: Template Text set to %s + args: ["x.c_str()"] alarm_control_panel: - platform: template From 47c262832be69f7cd69ae93fde87c3e7931368eb Mon Sep 17 00:00:00 2001 From: Peter Zich Date: Mon, 29 Apr 2024 12:24:13 -0700 Subject: [PATCH 1351/2101] web_server: Add support for v3 local server_index (#6563) --- esphome/components/web_server/server_index.h | 605 --- .../components/web_server/server_index_v2.h | 633 +++ .../components/web_server/server_index_v3.h | 3995 +++++++++++++++++ esphome/components/web_server/web_server.cpp | 6 +- 4 files changed, 4633 insertions(+), 606 deletions(-) delete mode 100644 esphome/components/web_server/server_index.h create mode 100644 esphome/components/web_server/server_index_v2.h create mode 100644 esphome/components/web_server/server_index_v3.h diff --git a/esphome/components/web_server/server_index.h b/esphome/components/web_server/server_index.h deleted file mode 100644 index 180dffab67..0000000000 --- a/esphome/components/web_server/server_index.h +++ /dev/null @@ -1,605 +0,0 @@ -#pragma once -// Generated from https://github.com/esphome/esphome-webserver -#include "esphome/core/hal.h" -namespace esphome { - -namespace web_server { - -const uint8_t INDEX_GZ[] PROGMEM = { - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc5, 0x7d, 0xd9, 0x76, 0xe3, 0xc6, 0x92, 0xe0, 0xf3, - 0x9c, 0x33, 0x7f, 0x30, 0x2f, 0x10, 0x4a, 0xad, 0x02, 0xae, 0x40, 0x88, 0xa4, 0x6a, 0x33, 0x28, 0x90, 0x57, 0xb5, - 0xd8, 0x55, 0x76, 0x6d, 0x2e, 0xa9, 0xec, 0x6b, 0xcb, 0xb4, 0x04, 0x91, 0x49, 0x11, 0x2e, 0x10, 0xa0, 0x81, 0xa4, - 0x16, 0x53, 0xe8, 0x33, 0x4f, 0xf3, 0xd4, 0xe7, 0xcc, 0xd6, 0x0f, 0xfd, 0x30, 0x7d, 0xba, 0x1f, 0xe6, 0x23, 0xe6, - 0xb9, 0x3f, 0xe5, 0xfe, 0xc0, 0xf4, 0x27, 0x4c, 0x44, 0xe4, 0x82, 0x04, 0x17, 0x49, 0x5e, 0xba, 0xe7, 0xd8, 0x2a, - 0x12, 0xb9, 0x46, 0x44, 0x46, 0xc6, 0x96, 0x91, 0xe0, 0xde, 0xc6, 0x30, 0x1b, 0xf0, 0xab, 0x29, 0xb3, 0xc6, 0x7c, - 0x92, 0x74, 0xf7, 0xe4, 0xbf, 0x2c, 0x1a, 0x76, 0xf7, 0x92, 0x38, 0xfd, 0x64, 0xe5, 0x2c, 0x09, 0xe3, 0x41, 0x96, - 0x5a, 0xe3, 0x9c, 0x8d, 0xc2, 0x61, 0xc4, 0xa3, 0x20, 0x9e, 0x44, 0x67, 0xcc, 0xda, 0xe9, 0xee, 0x4d, 0x18, 0x8f, - 0xac, 0xc1, 0x38, 0xca, 0x0b, 0xc6, 0xc3, 0x8f, 0x87, 0x9f, 0x37, 0x9e, 0x74, 0xf7, 0x8a, 0x41, 0x1e, 0x4f, 0xb9, - 0x85, 0x43, 0x86, 0x93, 0x6c, 0x38, 0x4b, 0x58, 0xf7, 0x3c, 0xca, 0xad, 0x17, 0x3c, 0x7c, 0x77, 0xfa, 0x13, 0x1b, - 0x70, 0x7f, 0xc8, 0x46, 0x71, 0xca, 0xde, 0xe7, 0xd9, 0x94, 0xe5, 0xfc, 0xca, 0x3b, 0x58, 0x5d, 0x11, 0xb3, 0xc2, - 0x7b, 0xa6, 0xab, 0xce, 0x18, 0x7f, 0x77, 0x91, 0xaa, 0x3e, 0xcf, 0x99, 0x98, 0x24, 0xcb, 0x0b, 0xaf, 0x58, 0xd3, - 0xe6, 0xe0, 0x6a, 0x72, 0x9a, 0x25, 0x85, 0xf7, 0x49, 0xd7, 0x4f, 0xf3, 0x8c, 0x67, 0x08, 0x96, 0x3f, 0x8e, 0x0a, - 0xa3, 0xa5, 0xf7, 0x6e, 0x45, 0x93, 0xa9, 0xac, 0x7c, 0x55, 0xbc, 0x48, 0x67, 0x13, 0x96, 0x47, 0xa7, 0x09, 0xf3, - 0x72, 0x1e, 0x3a, 0xdc, 0x63, 0x5e, 0xec, 0x86, 0x5d, 0x66, 0xc5, 0xa9, 0xc5, 0x7b, 0x2f, 0x38, 0x95, 0xcc, 0x99, - 0x6e, 0x15, 0x6c, 0x34, 0x3d, 0x20, 0xd7, 0x28, 0x3e, 0x9b, 0xe9, 0xe7, 0x8b, 0x3c, 0xe6, 0xea, 0xfb, 0x79, 0x94, - 0xcc, 0x58, 0x10, 0x97, 0x6e, 0xc0, 0x8f, 0x58, 0x3f, 0x8c, 0xbd, 0x4f, 0x34, 0x28, 0x0c, 0x39, 0x1f, 0x65, 0xb9, - 0x83, 0xb4, 0x8a, 0x71, 0x6c, 0x76, 0x7d, 0xed, 0xb0, 0x70, 0x5e, 0xba, 0xee, 0x27, 0xee, 0x0f, 0xa2, 0x24, 0x71, - 0x70, 0xe2, 0xad, 0xad, 0x1c, 0x67, 0x8c, 0x3d, 0x76, 0x14, 0xf7, 0xdd, 0x4e, 0x3c, 0x72, 0x0a, 0xee, 0x56, 0xfd, - 0xb2, 0x91, 0x55, 0x70, 0x87, 0xb9, 0xee, 0xbb, 0xf5, 0x7d, 0x72, 0xc6, 0x67, 0x39, 0xc0, 0x5e, 0x7a, 0xef, 0xd4, - 0xcc, 0x07, 0x58, 0xff, 0x8c, 0x3a, 0x76, 0x00, 0xf6, 0x82, 0x5b, 0x9f, 0x87, 0x17, 0x71, 0x3a, 0xcc, 0x2e, 0xfc, - 0x83, 0x71, 0x04, 0x1f, 0x1f, 0xb2, 0x8c, 0x6f, 0x6d, 0x39, 0xe7, 0x59, 0x3c, 0xb4, 0x9a, 0x61, 0x68, 0x56, 0x5e, - 0x3d, 0x3b, 0x38, 0xb8, 0xbe, 0x5e, 0x28, 0xf0, 0xd3, 0x88, 0xc7, 0xe7, 0x4c, 0x74, 0x06, 0x00, 0x6c, 0xf8, 0x9c, - 0x72, 0x36, 0x3c, 0xe0, 0x57, 0x09, 0x94, 0x32, 0xc6, 0x0b, 0x1b, 0x70, 0x7c, 0x9e, 0x0d, 0x80, 0x6c, 0xa9, 0x41, - 0x78, 0x68, 0x9a, 0xb3, 0x69, 0x12, 0x0d, 0x18, 0xd6, 0xc3, 0x48, 0x55, 0x8f, 0xaa, 0x91, 0xf7, 0x6d, 0x28, 0x96, - 0xd7, 0x71, 0xbd, 0x94, 0x87, 0x29, 0xbb, 0xb0, 0xde, 0x44, 0xd3, 0xce, 0x20, 0x89, 0x8a, 0xc2, 0xca, 0xf8, 0x9c, - 0x50, 0xc8, 0x67, 0x03, 0x60, 0x10, 0x42, 0x70, 0x0e, 0x64, 0xe2, 0xe3, 0xb8, 0xf0, 0x8f, 0x37, 0x07, 0x45, 0xf1, - 0x81, 0x15, 0xb3, 0x84, 0x6f, 0x86, 0xb0, 0x16, 0x6c, 0x23, 0x0c, 0xbf, 0x75, 0xf9, 0x38, 0xcf, 0x2e, 0xac, 0x17, - 0x79, 0x0e, 0xcd, 0x6d, 0x98, 0x52, 0x34, 0xb0, 0xe2, 0xc2, 0x4a, 0x33, 0x6e, 0xe9, 0xc1, 0x70, 0x01, 0x7d, 0xeb, - 0x63, 0xc1, 0xac, 0x93, 0x59, 0x5a, 0x44, 0x23, 0x06, 0x4d, 0x4f, 0xac, 0x2c, 0xb7, 0x4e, 0x60, 0xd0, 0x13, 0x58, - 0xb2, 0x82, 0xc3, 0xae, 0xf1, 0x6d, 0xb7, 0x43, 0x73, 0x41, 0xe1, 0x21, 0xbb, 0xe4, 0x21, 0x2f, 0x81, 0x31, 0x61, - 0x55, 0x14, 0x1a, 0x8e, 0x3b, 0x4f, 0xa0, 0x00, 0xc0, 0x26, 0x96, 0x75, 0xcc, 0xc6, 0x7a, 0x71, 0x3e, 0xdf, 0xda, - 0xd2, 0xb4, 0x46, 0xc2, 0x43, 0xdb, 0x62, 0xa1, 0xad, 0x27, 0x10, 0xaf, 0x91, 0xc8, 0xf5, 0xb8, 0x2f, 0xc9, 0x77, - 0x70, 0x95, 0x0e, 0xea, 0x63, 0x43, 0x65, 0xc9, 0xb3, 0x03, 0x9e, 0xc7, 0xe9, 0x19, 0x00, 0xa1, 0xd8, 0xc0, 0x68, - 0x52, 0x96, 0x62, 0xf1, 0xdf, 0x03, 0xd4, 0x61, 0x17, 0x47, 0xcf, 0xb8, 0x63, 0x17, 0xd4, 0xc3, 0x06, 0x40, 0x80, - 0xf4, 0xc0, 0x60, 0xbc, 0xc7, 0x03, 0xbe, 0x6d, 0xdb, 0xde, 0xb7, 0xae, 0x77, 0x81, 0x1c, 0xe4, 0xfb, 0x3e, 0xb1, - 0xaf, 0xe8, 0x1c, 0x87, 0x2d, 0x04, 0xda, 0x4f, 0x58, 0x7a, 0xc6, 0xc7, 0x3d, 0x7e, 0xd4, 0xec, 0x07, 0x0c, 0xa0, - 0x1a, 0xce, 0x06, 0xcc, 0x41, 0x7e, 0xf4, 0x0a, 0xdc, 0x3e, 0xdb, 0x0e, 0x4c, 0x81, 0x0b, 0xb3, 0x41, 0x38, 0xd6, - 0x96, 0xc6, 0x55, 0xb0, 0x29, 0xc0, 0x90, 0xcf, 0x6d, 0xd8, 0x61, 0xa7, 0x2c, 0x37, 0xe0, 0xd0, 0xcd, 0x3a, 0xb5, - 0x15, 0x9c, 0xc1, 0x0a, 0x41, 0x3f, 0x6b, 0x34, 0x4b, 0x07, 0x3c, 0x06, 0xc1, 0x65, 0x6f, 0x03, 0xb8, 0x62, 0xe5, - 0xf4, 0xc2, 0xd9, 0x6e, 0xe9, 0x3a, 0xb1, 0xbb, 0xcd, 0x8f, 0x8a, 0xed, 0x56, 0xdf, 0x43, 0x28, 0x35, 0xf1, 0x25, - 0xe2, 0x31, 0x20, 0x58, 0x7a, 0x1f, 0xb9, 0xde, 0x9e, 0x9f, 0xf7, 0xb8, 0xbf, 0xcc, 0xc7, 0x21, 0xf3, 0x27, 0xd1, - 0x14, 0xb1, 0xe1, 0xc4, 0x03, 0x51, 0x3a, 0x40, 0xe8, 0x6a, 0xeb, 0x82, 0x14, 0xf3, 0x2b, 0x16, 0x70, 0x81, 0x20, - 0xb0, 0x67, 0x5f, 0x44, 0x83, 0x31, 0x6c, 0xf1, 0x8a, 0x70, 0x43, 0xb5, 0x1d, 0x06, 0x39, 0x8b, 0x38, 0x7b, 0x91, - 0x30, 0x7c, 0xc2, 0x15, 0x80, 0x9e, 0xb6, 0xeb, 0x15, 0x6a, 0xdf, 0x25, 0x31, 0x7f, 0x9b, 0xc1, 0x3c, 0x1d, 0xc1, - 0x24, 0xc0, 0xc5, 0xc5, 0xd6, 0x56, 0x8c, 0x2c, 0xb2, 0xcf, 0x61, 0xb5, 0x4e, 0x67, 0x9c, 0x01, 0xbd, 0xb0, 0x85, - 0x0d, 0xd4, 0xf6, 0x62, 0x9f, 0x03, 0x11, 0x9f, 0x65, 0x29, 0x87, 0xe1, 0x00, 0x5e, 0xcd, 0x41, 0x7e, 0x34, 0x9d, - 0xb2, 0x74, 0xf8, 0x6c, 0x1c, 0x27, 0x43, 0xa0, 0x46, 0x09, 0xf8, 0x26, 0x3c, 0x04, 0x3c, 0x01, 0x99, 0xe0, 0x66, - 0x8c, 0x68, 0xf9, 0x90, 0x91, 0x59, 0x68, 0xdb, 0x1d, 0x94, 0x40, 0x12, 0x0b, 0x94, 0x41, 0xb4, 0x70, 0x1f, 0x40, - 0xf4, 0x17, 0x2e, 0xdb, 0x0e, 0x63, 0xbd, 0x8c, 0x92, 0xc0, 0xef, 0x51, 0xd2, 0x00, 0xfd, 0x81, 0x10, 0xbc, 0x83, - 0x82, 0xeb, 0x4b, 0x29, 0x75, 0x22, 0xae, 0x30, 0x04, 0x02, 0x0c, 0x50, 0x82, 0x48, 0x1a, 0xbc, 0xcf, 0x92, 0xab, - 0x51, 0x9c, 0x24, 0x07, 0xb3, 0xe9, 0x34, 0xcb, 0xb9, 0xf7, 0x55, 0x38, 0xe7, 0x59, 0x85, 0x2b, 0x6d, 0xf2, 0xe2, - 0x22, 0xe6, 0x48, 0x50, 0x77, 0x3e, 0x88, 0x60, 0xa9, 0x9f, 0x66, 0x59, 0xc2, 0xa2, 0x14, 0xd0, 0xe0, 0x3d, 0xdb, - 0x0e, 0xd2, 0x59, 0x92, 0x74, 0x4e, 0x61, 0xd8, 0x4f, 0x1d, 0xaa, 0x16, 0x12, 0x3f, 0xa0, 0xef, 0xfb, 0x79, 0x1e, - 0x5d, 0x41, 0x43, 0x6c, 0x03, 0xec, 0x05, 0xab, 0xf5, 0xe5, 0xc1, 0xbb, 0xb7, 0xbe, 0x60, 0xfc, 0x78, 0x74, 0x05, - 0x80, 0x96, 0x95, 0xd4, 0x1c, 0xe5, 0xd9, 0x64, 0x61, 0x6a, 0xa4, 0x43, 0x1c, 0xf2, 0xce, 0x1a, 0x10, 0x62, 0x1a, - 0x19, 0x56, 0x89, 0x9b, 0x10, 0xbc, 0x25, 0x7e, 0x96, 0x95, 0xb8, 0x07, 0x7a, 0xf8, 0x25, 0x10, 0xc5, 0x30, 0xe5, - 0x2d, 0xd0, 0xe6, 0x57, 0xf3, 0x38, 0x24, 0x38, 0xa7, 0xa8, 0x7f, 0x11, 0xc6, 0x41, 0x04, 0xb3, 0xcf, 0xc5, 0x80, - 0xa5, 0x82, 0x38, 0x2e, 0x4b, 0x6f, 0xac, 0x99, 0x18, 0x25, 0x1e, 0x0a, 0x14, 0x16, 0x86, 0xa0, 0x60, 0x38, 0x3c, - 0xb8, 0xde, 0xd7, 0xe1, 0x3c, 0x52, 0xf8, 0xa0, 0x86, 0xc2, 0xfd, 0x15, 0x08, 0x39, 0x81, 0x9a, 0xec, 0x1c, 0xf4, - 0x20, 0xc0, 0xf9, 0x95, 0x07, 0xfa, 0x3f, 0x41, 0x28, 0x36, 0x5a, 0x1e, 0x68, 0xd0, 0x67, 0xe3, 0x28, 0x3d, 0x63, - 0xc3, 0x60, 0xcc, 0x4b, 0x29, 0x79, 0xf7, 0x2d, 0x58, 0x63, 0x60, 0xa7, 0xc2, 0x7a, 0x79, 0xf8, 0xe6, 0xb5, 0x5c, - 0xb9, 0x9a, 0x30, 0x86, 0x45, 0x9a, 0x81, 0x5a, 0x05, 0xb1, 0x2d, 0xc5, 0xf1, 0x0b, 0x2d, 0xbd, 0x45, 0x49, 0x5c, - 0x7c, 0x9c, 0x82, 0x89, 0xc1, 0xde, 0xc3, 0x30, 0x30, 0x7d, 0x08, 0x53, 0x51, 0x39, 0xcc, 0x27, 0x2a, 0x86, 0xba, - 0x08, 0x3a, 0x0b, 0x4c, 0xc5, 0x63, 0xe6, 0xb8, 0x25, 0xb0, 0x2a, 0x8f, 0x07, 0x56, 0x34, 0x1c, 0xbe, 0x4a, 0x63, - 0x1e, 0x47, 0x49, 0xfc, 0x0b, 0x51, 0x72, 0x8e, 0x3c, 0xc6, 0x3a, 0x72, 0x11, 0x00, 0x77, 0xea, 0x91, 0xb8, 0x4a, - 0xc8, 0x6e, 0x10, 0x31, 0x84, 0xb4, 0x4c, 0xc2, 0xa3, 0xbe, 0x04, 0x2f, 0xf1, 0xa7, 0xb3, 0x62, 0x8c, 0x84, 0x95, - 0x03, 0xa3, 0x20, 0xcf, 0x4e, 0x0b, 0x96, 0x9f, 0xb3, 0xa1, 0xe6, 0x80, 0x02, 0xb0, 0xa2, 0xe6, 0x60, 0xbc, 0xd0, - 0x8c, 0x8e, 0xd2, 0xa1, 0x1c, 0x86, 0xea, 0x98, 0x62, 0x96, 0x49, 0x66, 0xd6, 0x16, 0x8e, 0x96, 0x02, 0x8e, 0x30, - 0x2a, 0xa4, 0x24, 0x28, 0x42, 0x85, 0xe1, 0x18, 0xa4, 0x10, 0x73, 0x6b, 0xdb, 0x5c, 0x69, 0xb2, 0x17, 0x33, 0x52, - 0x09, 0x05, 0x74, 0x84, 0x8d, 0x4c, 0x90, 0x16, 0x2e, 0xec, 0x2a, 0x90, 0xf2, 0x12, 0x5c, 0x21, 0x45, 0x94, 0x99, - 0x83, 0x0c, 0x10, 0x7e, 0x4d, 0xba, 0x90, 0xf9, 0xd8, 0x82, 0x21, 0x1b, 0xf8, 0x7a, 0xe5, 0x81, 0xb0, 0x12, 0xef, - 0x0a, 0x11, 0x6f, 0x0d, 0xd8, 0xa4, 0x8b, 0x00, 0x30, 0x6f, 0x83, 0xf9, 0x69, 0xb6, 0x3f, 0x18, 0xb0, 0xa2, 0xc8, - 0xf2, 0xad, 0xad, 0x0d, 0x6a, 0xbf, 0xce, 0xd0, 0x02, 0x4a, 0xba, 0x5a, 0xd6, 0xd9, 0x05, 0x69, 0x70, 0x53, 0xad, - 0x28, 0x9d, 0x1e, 0xd8, 0xc7, 0xc7, 0x20, 0xb3, 0x3d, 0x49, 0x06, 0xa0, 0xfa, 0xb2, 0xe1, 0x27, 0xec, 0x99, 0x3a, - 0x65, 0x56, 0xda, 0x97, 0x4e, 0x1d, 0x24, 0x0f, 0x86, 0x75, 0x4b, 0x63, 0x41, 0x57, 0x0e, 0x8d, 0xab, 0x21, 0x15, - 0xe4, 0xfc, 0x8c, 0x54, 0xb6, 0xb1, 0x8c, 0x60, 0xb5, 0x95, 0x1e, 0x91, 0x5e, 0x61, 0x93, 0x13, 0xa0, 0x47, 0xbc, - 0xdf, 0x91, 0xf5, 0x61, 0x21, 0x28, 0x97, 0xb3, 0x9f, 0x67, 0xac, 0xe0, 0x82, 0x75, 0x61, 0xdc, 0x1c, 0xc6, 0x2d, - 0x97, 0xac, 0xc3, 0x9a, 0xed, 0xb8, 0x0a, 0xb6, 0x77, 0x53, 0xd4, 0x63, 0x05, 0x72, 0xf2, 0xcd, 0xec, 0x44, 0xf6, - 0x84, 0x7b, 0x7d, 0xfd, 0xb5, 0x1a, 0xa4, 0x5a, 0x4a, 0x6d, 0x03, 0x2d, 0xac, 0x89, 0xad, 0x9a, 0x0c, 0x6d, 0x57, - 0x2a, 0xd4, 0x8d, 0x56, 0xa7, 0xc6, 0x07, 0xb0, 0xe7, 0x9a, 0x9a, 0xa5, 0x2b, 0x63, 0xfb, 0xbd, 0xa2, 0xe9, 0x3b, - 0x31, 0x32, 0x59, 0xa3, 0xfc, 0x76, 0xee, 0x51, 0x3b, 0x1e, 0xda, 0x2e, 0xd5, 0x55, 0x82, 0x61, 0x56, 0x17, 0x0c, - 0x8b, 0x50, 0x4f, 0x75, 0x17, 0x5b, 0x33, 0x15, 0x0f, 0xd5, 0x5a, 0x2b, 0x07, 0x82, 0x85, 0x47, 0x60, 0x9c, 0xac, - 0xf4, 0x0f, 0xde, 0x46, 0x13, 0x86, 0x14, 0xf5, 0xd6, 0x35, 0x90, 0x0e, 0x04, 0x34, 0xe9, 0x2f, 0xaa, 0x37, 0xe6, - 0x0a, 0xab, 0xa9, 0xbe, 0xbf, 0x62, 0xb0, 0x22, 0xc0, 0xbe, 0x2e, 0x57, 0x2c, 0x11, 0xe9, 0x4d, 0xc9, 0xce, 0x8a, - 0x3e, 0xa2, 0x4c, 0xac, 0x09, 0x29, 0x78, 0x40, 0x1e, 0x96, 0x7f, 0x61, 0xe1, 0x54, 0x2b, 0x85, 0x23, 0x43, 0x99, - 0x02, 0x74, 0x26, 0x25, 0x00, 0xe2, 0x92, 0x3e, 0x6b, 0x1b, 0x0b, 0xc9, 0x76, 0x80, 0x7c, 0xe0, 0x8f, 0x92, 0x88, - 0x3b, 0xad, 0x9d, 0xa6, 0x0b, 0x7c, 0x08, 0x42, 0x1c, 0x74, 0x04, 0x98, 0xf7, 0x15, 0x2a, 0x1c, 0x51, 0x89, 0x5d, - 0xe6, 0x83, 0x51, 0x34, 0x8e, 0x47, 0xdc, 0x49, 0x90, 0x79, 0xdc, 0x92, 0x25, 0xa0, 0x64, 0xf4, 0xbe, 0x02, 0x65, - 0xc1, 0x84, 0x74, 0x11, 0xd5, 0x4a, 0xa0, 0x31, 0x05, 0x29, 0x49, 0x29, 0xd2, 0x82, 0x0a, 0x02, 0x43, 0xa8, 0x74, - 0x14, 0x47, 0x81, 0x7e, 0x8b, 0x7b, 0x62, 0xd0, 0x60, 0xc9, 0xa2, 0x8c, 0x7b, 0xf1, 0x72, 0x21, 0xa8, 0x61, 0x9f, - 0x67, 0xaf, 0xb3, 0x0b, 0x96, 0x3f, 0x8b, 0x10, 0xf6, 0x40, 0x74, 0x2f, 0x41, 0xd2, 0x93, 0x40, 0xe7, 0x1d, 0xc5, - 0x2b, 0xe7, 0x84, 0x34, 0x2c, 0xc4, 0x24, 0x46, 0x45, 0x08, 0x76, 0x0b, 0xd1, 0x3e, 0xc5, 0x2d, 0x45, 0x7b, 0x0f, - 0x55, 0x09, 0xd7, 0xbc, 0xb5, 0xff, 0xba, 0xce, 0x5b, 0x30, 0xc2, 0x54, 0x71, 0x6b, 0x7d, 0xc7, 0x82, 0x7b, 0x21, - 0x74, 0xb3, 0x23, 0x79, 0xcb, 0x50, 0x66, 0xa0, 0x3f, 0xae, 0xaf, 0x2b, 0x23, 0x1d, 0x94, 0xa9, 0x96, 0xe6, 0x08, - 0x81, 0xd8, 0x12, 0x6e, 0x09, 0xca, 0x08, 0x0d, 0xaf, 0x3c, 0x4b, 0x12, 0x43, 0x17, 0x79, 0x71, 0xc7, 0x59, 0x50, - 0x47, 0x00, 0xc5, 0xa4, 0xa6, 0x91, 0x7a, 0x2c, 0xd0, 0x15, 0xa8, 0x94, 0x94, 0x36, 0xf2, 0xaa, 0xb5, 0x11, 0x10, - 0xa7, 0x43, 0x96, 0x0b, 0x07, 0x4d, 0xea, 0x50, 0x98, 0x30, 0x05, 0x86, 0x66, 0x43, 0xf4, 0x1c, 0x24, 0x02, 0x60, - 0x9e, 0xf8, 0xe3, 0xac, 0xe0, 0xba, 0xce, 0x84, 0x3e, 0xbe, 0xbe, 0x8e, 0x85, 0xbf, 0x88, 0x0c, 0x90, 0xb3, 0x49, - 0x76, 0xce, 0x56, 0x40, 0xdd, 0x51, 0x83, 0x99, 0x20, 0x1b, 0xc3, 0x80, 0x12, 0x05, 0xd5, 0x32, 0x4d, 0x62, 0xb0, - 0xf4, 0x75, 0x03, 0x1f, 0x0c, 0x3a, 0x76, 0x89, 0x32, 0xc2, 0xed, 0x76, 0xbb, 0x4d, 0xaf, 0xe5, 0x96, 0x82, 0xe0, - 0xf3, 0x25, 0x8a, 0xde, 0xa0, 0x1f, 0xa5, 0x09, 0xbe, 0x4a, 0x16, 0x30, 0xd7, 0x50, 0x8a, 0xc2, 0x4f, 0x62, 0x9e, - 0x14, 0xc4, 0xae, 0x37, 0x84, 0x41, 0x39, 0x53, 0x82, 0x1b, 0x4d, 0x5c, 0xb1, 0x6d, 0x3f, 0x68, 0xb2, 0x69, 0x76, - 0x52, 0x3b, 0x4c, 0x2d, 0x8c, 0x5c, 0xf3, 0x42, 0x7b, 0xc0, 0xe6, 0xf2, 0x90, 0x4d, 0x8f, 0xd5, 0xc0, 0xeb, 0x00, - 0xa1, 0xf0, 0x74, 0x9d, 0x25, 0x94, 0xaa, 0xce, 0x52, 0x88, 0xeb, 0x0d, 0xf4, 0x51, 0x81, 0xb9, 0x8a, 0x04, 0x07, - 0x52, 0x20, 0x30, 0xf4, 0xc8, 0xc4, 0x7a, 0x3d, 0x83, 0xe5, 0x39, 0x8d, 0x06, 0x9f, 0x34, 0xb8, 0x15, 0xef, 0x2d, - 0xb2, 0x81, 0xb3, 0x50, 0x12, 0x1a, 0xe2, 0xca, 0xc4, 0x5b, 0x49, 0xe8, 0xda, 0x46, 0x01, 0x87, 0x6c, 0x89, 0xed, - 0x17, 0x17, 0x7a, 0x91, 0xdb, 0x25, 0x7b, 0x28, 0xff, 0xa9, 0xe2, 0x92, 0xf5, 0x2c, 0xc7, 0x94, 0x34, 0x60, 0x8a, - 0xf1, 0x60, 0x69, 0x16, 0x20, 0x01, 0xbe, 0x2b, 0x87, 0x71, 0xb1, 0x9e, 0x04, 0x7f, 0x28, 0x98, 0xcf, 0x8d, 0x99, - 0x6e, 0x85, 0x54, 0x4b, 0x38, 0x69, 0x06, 0x6b, 0xd0, 0xa4, 0xf1, 0xa0, 0x44, 0xcd, 0x57, 0x68, 0xa8, 0x10, 0xc7, - 0x9f, 0x89, 0x2a, 0x34, 0xc1, 0x10, 0x8c, 0xc2, 0xcb, 0x25, 0xc3, 0xa5, 0xcb, 0xa2, 0x45, 0xca, 0xd4, 0x98, 0x54, - 0xaa, 0x66, 0xb9, 0x14, 0x0c, 0x2c, 0xda, 0xad, 0xbe, 0xb4, 0xc4, 0x95, 0xc8, 0xcd, 0x42, 0x2d, 0x4c, 0x72, 0xe5, - 0x4d, 0x38, 0x05, 0xfa, 0x5d, 0xca, 0x7a, 0x37, 0xf1, 0x29, 0x14, 0x3e, 0x85, 0x6f, 0xf8, 0x50, 0x26, 0x6f, 0xe7, - 0x3d, 0x30, 0xf7, 0x6b, 0x95, 0x68, 0x9f, 0xfa, 0x28, 0x98, 0x5d, 0x2d, 0x74, 0x41, 0xa0, 0x48, 0x36, 0xc9, 0x7a, - 0x92, 0xdf, 0x50, 0x6c, 0x54, 0x9e, 0x51, 0xea, 0x8a, 0x0d, 0x52, 0xf3, 0x4a, 0x53, 0x2f, 0x73, 0x17, 0xec, 0xf7, - 0xb2, 0x94, 0x74, 0x62, 0x82, 0x32, 0xb1, 0x77, 0x13, 0x6d, 0xbc, 0x2c, 0x4c, 0x85, 0xf5, 0x2b, 0x8c, 0x9d, 0x1a, - 0x85, 0x32, 0x29, 0x02, 0x71, 0x6c, 0x7c, 0xac, 0x2c, 0x83, 0xd4, 0x5f, 0x61, 0x4f, 0x01, 0x28, 0x09, 0x2c, 0xbe, - 0xa6, 0x92, 0x17, 0x85, 0x75, 0x3a, 0x6e, 0x10, 0x1d, 0x2b, 0x11, 0x5a, 0x13, 0xf9, 0x5a, 0x9f, 0xc5, 0x7e, 0xcd, - 0x25, 0x34, 0x29, 0x59, 0xf4, 0x8a, 0xc0, 0x56, 0x81, 0x88, 0x4a, 0xb7, 0x25, 0xbd, 0x84, 0x1c, 0xd2, 0x65, 0xa2, - 0xd7, 0x46, 0x32, 0x68, 0x9d, 0x09, 0x89, 0x96, 0xf5, 0xc3, 0x08, 0xc5, 0x86, 0x58, 0x8b, 0x25, 0x42, 0x2e, 0xda, - 0x9b, 0xc4, 0x8a, 0xe8, 0x9c, 0x16, 0x68, 0xc2, 0x99, 0x3a, 0xdd, 0x71, 0x00, 0x1d, 0x10, 0xfb, 0x4b, 0xac, 0xb7, - 0xd2, 0xec, 0x74, 0xfd, 0xca, 0xe1, 0xbb, 0xbe, 0x1e, 0x73, 0xd7, 0x91, 0x06, 0x2f, 0xac, 0x59, 0x4f, 0xc9, 0xde, - 0xfd, 0xd7, 0xd8, 0x8a, 0xec, 0xcf, 0xaa, 0xa4, 0xf2, 0x14, 0x6a, 0x9c, 0x5b, 0x5f, 0xa7, 0x5a, 0x68, 0x51, 0x55, - 0x1c, 0x18, 0x52, 0xfd, 0x40, 0x29, 0xec, 0x0a, 0xe5, 0x03, 0x39, 0x74, 0xec, 0xba, 0x6e, 0x50, 0x90, 0xf3, 0xb2, - 0xb1, 0xca, 0x85, 0xdc, 0xda, 0x32, 0x7d, 0xa6, 0x73, 0x3d, 0xfc, 0x33, 0x07, 0x95, 0x73, 0x71, 0x95, 0x92, 0x05, - 0xf3, 0x4c, 0xa9, 0xa3, 0x25, 0x07, 0xb4, 0xd9, 0x41, 0x4f, 0x3b, 0xba, 0x88, 0x62, 0x6e, 0xe9, 0x51, 0x84, 0xa7, - 0x8d, 0xf2, 0x49, 0x1a, 0x1d, 0x80, 0x17, 0x9a, 0x90, 0xe4, 0x84, 0x9b, 0xb6, 0x68, 0x31, 0x18, 0x33, 0x0c, 0x81, - 0x2b, 0x7b, 0xc2, 0x94, 0x3d, 0x1b, 0x88, 0xb7, 0x1c, 0x78, 0x35, 0xec, 0xe5, 0x62, 0xf7, 0x9a, 0xf9, 0x0f, 0x6b, - 0x04, 0xb2, 0x6d, 0xa2, 0xea, 0xca, 0x85, 0x67, 0x29, 0x22, 0x31, 0xc2, 0xb6, 0x6a, 0x6c, 0x69, 0xeb, 0x77, 0x16, - 0xdc, 0xeb, 0xca, 0x31, 0xaf, 0x29, 0xd5, 0x05, 0x3d, 0xac, 0xdc, 0x1c, 0x6e, 0x3a, 0xf2, 0x62, 0x05, 0xdd, 0x8e, - 0x08, 0x0a, 0x81, 0x13, 0xa1, 0xec, 0x41, 0xcd, 0x0d, 0x44, 0x4a, 0xa6, 0xb4, 0x6a, 0x36, 0x4b, 0x86, 0x12, 0x58, - 0x70, 0x61, 0x99, 0xe4, 0xa3, 0x8b, 0x38, 0x49, 0xaa, 0xd2, 0x3f, 0x54, 0xc0, 0x8b, 0x61, 0x6f, 0x13, 0xed, 0x02, - 0xa3, 0x99, 0x02, 0xc1, 0xd5, 0x46, 0xd8, 0x47, 0xc7, 0xad, 0xd6, 0x5d, 0x44, 0x1c, 0x99, 0x19, 0x8d, 0xf8, 0x88, - 0x36, 0x64, 0xc9, 0x34, 0x6b, 0xef, 0xbf, 0xc0, 0x90, 0x9a, 0x81, 0x0f, 0xaa, 0x33, 0x2a, 0xfe, 0x55, 0xf6, 0xd4, - 0xaf, 0x44, 0xef, 0x56, 0xd5, 0xb5, 0x18, 0x50, 0x51, 0x81, 0x0f, 0x33, 0xc4, 0xd2, 0x54, 0x81, 0x80, 0x5c, 0x0f, - 0xeb, 0x70, 0xb7, 0x46, 0x1a, 0x2c, 0x28, 0x05, 0xd6, 0x5a, 0xd9, 0xbd, 0xbe, 0x2d, 0x98, 0x43, 0xa1, 0x70, 0xd1, - 0xff, 0x59, 0x36, 0x99, 0xa2, 0x65, 0xb6, 0xc0, 0xd4, 0xd0, 0xe0, 0xe3, 0x42, 0x7d, 0xb9, 0xa2, 0xac, 0xd6, 0x87, - 0x76, 0x64, 0x8d, 0x9f, 0xb4, 0xa3, 0x0c, 0x0e, 0xd5, 0x4c, 0x17, 0xd5, 0xed, 0xe6, 0x45, 0x11, 0xb3, 0x8a, 0xc7, - 0x7d, 0xd2, 0xdb, 0xda, 0x9a, 0xf4, 0x34, 0x0d, 0x48, 0x26, 0x49, 0x86, 0x37, 0x19, 0xa0, 0xac, 0x88, 0x33, 0x2f, - 0x17, 0xc8, 0x37, 0x2f, 0x4b, 0x5c, 0xbf, 0xef, 0x3b, 0xfb, 0x35, 0xcf, 0xda, 0xdb, 0x5f, 0xef, 0x22, 0x57, 0x75, - 0xd2, 0x83, 0x3c, 0xea, 0x43, 0xd1, 0x92, 0x4d, 0x19, 0xce, 0x27, 0xd9, 0x90, 0x05, 0x36, 0x74, 0x4f, 0xed, 0x52, - 0x6e, 0x9a, 0x08, 0x36, 0x07, 0xf8, 0x7f, 0xf3, 0x0f, 0xf5, 0x48, 0x6a, 0xb0, 0x0f, 0x2c, 0xa0, 0xcd, 0x85, 0x2f, - 0xc3, 0xb3, 0x24, 0x3b, 0x8d, 0x92, 0x43, 0xa1, 0xc0, 0x6b, 0x2d, 0xbf, 0x01, 0x97, 0x91, 0x2c, 0x56, 0x43, 0x49, - 0x7d, 0xd9, 0xfb, 0x32, 0xb8, 0xbd, 0x47, 0xe5, 0xad, 0xd8, 0x2d, 0xbf, 0xe9, 0xb7, 0x6c, 0x15, 0x11, 0xfb, 0xc9, - 0x9c, 0x0e, 0x34, 0x4e, 0x01, 0x94, 0x39, 0x04, 0x4d, 0x56, 0x78, 0x03, 0x1e, 0xfe, 0xd4, 0xfb, 0x49, 0xb9, 0xd4, - 0x19, 0xb8, 0x10, 0xe0, 0xe4, 0x27, 0x31, 0x6f, 0xe0, 0x79, 0xa4, 0xed, 0xcd, 0x45, 0x05, 0xc6, 0x15, 0x29, 0x2e, - 0x5d, 0x2a, 0x6f, 0xd0, 0x3b, 0x0e, 0x4f, 0xa0, 0xd9, 0xe6, 0xe6, 0xdc, 0x79, 0x13, 0xf1, 0xb1, 0x9f, 0x47, 0xe9, - 0x30, 0x9b, 0x38, 0xee, 0xb6, 0x6d, 0xbb, 0x7e, 0x41, 0x9e, 0xc8, 0x67, 0x6e, 0xb9, 0x79, 0xe2, 0x0d, 0x79, 0x68, - 0xf7, 0xec, 0xed, 0x63, 0xef, 0x90, 0x87, 0x27, 0x7b, 0x9b, 0xf3, 0x21, 0x2f, 0xbb, 0x27, 0xde, 0xa5, 0x8e, 0xb9, - 0x7b, 0xef, 0x51, 0xca, 0x40, 0xaf, 0xb0, 0x7b, 0x29, 0xc1, 0x00, 0x76, 0xa3, 0xf8, 0x3b, 0x48, 0xb9, 0x8f, 0x74, - 0x20, 0x22, 0xe3, 0xb4, 0xd7, 0xd7, 0x76, 0x46, 0x11, 0x03, 0x7b, 0x43, 0x3b, 0xab, 0x5b, 0x5b, 0x95, 0x9a, 0xaf, - 0x4a, 0xbd, 0x19, 0x0f, 0x6b, 0x9e, 0xba, 0xf7, 0x92, 0x8e, 0x56, 0xea, 0x1b, 0x79, 0x26, 0x82, 0x36, 0xcb, 0x76, - 0x82, 0x63, 0x6c, 0xf1, 0xd5, 0xdb, 0xfa, 0x48, 0x44, 0x29, 0xfc, 0x18, 0xac, 0x97, 0x08, 0xd4, 0x37, 0x38, 0x38, - 0xde, 0x61, 0xb8, 0xb3, 0xe7, 0xf4, 0x02, 0x67, 0xa3, 0xd1, 0xb8, 0xfe, 0x61, 0xe7, 0xe8, 0xc7, 0xa8, 0xf1, 0xcb, - 0x7e, 0xe3, 0xfb, 0xbe, 0x7b, 0xed, 0xfc, 0xb0, 0xd3, 0x3b, 0x92, 0x4f, 0x47, 0x3f, 0x76, 0x7f, 0x28, 0xfa, 0x7f, - 0x12, 0x85, 0x9b, 0xae, 0xbb, 0x73, 0xe6, 0x4d, 0x79, 0xb8, 0xd3, 0x68, 0x74, 0xe1, 0xdb, 0x19, 0x7c, 0xc3, 0xcf, - 0x53, 0xf8, 0xb8, 0x3e, 0xb2, 0xfe, 0xc3, 0x0f, 0xe9, 0x7f, 0xfc, 0x21, 0xef, 0xe3, 0x98, 0x47, 0x3f, 0xfe, 0x50, - 0xd8, 0xf7, 0xbb, 0xe1, 0x4e, 0x7f, 0xdb, 0x75, 0x74, 0xcd, 0x9f, 0xc2, 0xea, 0x2b, 0xb4, 0x3a, 0xfa, 0x51, 0x3e, - 0xd9, 0xf7, 0x4f, 0xf6, 0xba, 0x61, 0xff, 0xda, 0xb1, 0xaf, 0xef, 0xbb, 0xd7, 0xae, 0x7b, 0xbd, 0x89, 0xf3, 0x9c, - 0xc3, 0xe8, 0xf7, 0xe1, 0x73, 0x04, 0x9f, 0x36, 0x7c, 0x6e, 0xc2, 0xe7, 0x8f, 0xd0, 0x4d, 0xc4, 0xdf, 0xae, 0x29, - 0x16, 0x72, 0x8d, 0x07, 0x16, 0x11, 0xac, 0x82, 0xbb, 0xb9, 0x13, 0x7b, 0x13, 0x22, 0x1a, 0xec, 0x43, 0xdf, 0xf7, - 0x31, 0x4c, 0xea, 0xcc, 0x8f, 0x37, 0x61, 0xd1, 0x91, 0x73, 0x36, 0x03, 0xee, 0x89, 0xc8, 0x41, 0x11, 0x30, 0x71, - 0xb6, 0x5a, 0xe0, 0xe1, 0xaa, 0x37, 0x0c, 0x27, 0xdc, 0x01, 0xa3, 0xe0, 0x03, 0xc7, 0x2f, 0x6d, 0xd7, 0x7b, 0x21, - 0xcf, 0x0c, 0x71, 0x9f, 0x0b, 0xd6, 0x4a, 0x33, 0x61, 0xd2, 0xd8, 0xae, 0x37, 0x5d, 0x51, 0x09, 0xdb, 0x3a, 0x3d, - 0x83, 0xba, 0x63, 0x11, 0xa3, 0xfe, 0x96, 0x45, 0x9f, 0x70, 0x4b, 0xbe, 0x35, 0x0e, 0x81, 0x97, 0x2c, 0xf9, 0x45, - 0xa3, 0xd1, 0xb0, 0x11, 0x85, 0x3b, 0xf6, 0x94, 0xc1, 0x0c, 0x4b, 0x26, 0x22, 0x23, 0xa5, 0x29, 0x2c, 0x5b, 0x98, - 0xfc, 0x7d, 0x94, 0xf3, 0xcd, 0xca, 0xb0, 0x0d, 0xeb, 0x96, 0xec, 0x82, 0xa5, 0x7f, 0x87, 0x29, 0xd0, 0xb4, 0xa4, - 0xf3, 0x0f, 0x73, 0xfc, 0x30, 0x23, 0xb4, 0x3e, 0x38, 0x0c, 0x3c, 0xf4, 0x02, 0xe4, 0x8e, 0xe8, 0xe7, 0xbc, 0x47, - 0x35, 0x06, 0xff, 0xcb, 0x30, 0x83, 0x27, 0xe6, 0xc3, 0x10, 0xcd, 0xbc, 0xd4, 0xc1, 0xad, 0x0c, 0xc5, 0xfd, 0x2b, - 0xdc, 0x19, 0x59, 0xe9, 0x1d, 0x84, 0x6a, 0xc7, 0x1c, 0xe6, 0x8c, 0x7d, 0x1b, 0x25, 0x9f, 0x58, 0xee, 0x5c, 0x7a, - 0xad, 0xf6, 0x67, 0xd4, 0xd9, 0x43, 0xdb, 0xec, 0x4d, 0x75, 0x8c, 0xa6, 0xcd, 0x02, 0x79, 0x44, 0xd8, 0x68, 0x79, - 0x28, 0x31, 0x88, 0x04, 0xb9, 0x97, 0x86, 0x6d, 0xe2, 0x70, 0x7b, 0xaf, 0x38, 0x3f, 0xeb, 0xda, 0x81, 0x6d, 0x83, - 0xc5, 0x7f, 0x48, 0x61, 0x2b, 0x61, 0x58, 0x34, 0x3b, 0x6c, 0x2f, 0xee, 0xb0, 0xed, 0xed, 0x2a, 0xe0, 0x84, 0x07, - 0xe9, 0xd4, 0x3d, 0xf1, 0x22, 0x6f, 0x1c, 0xc2, 0x80, 0x03, 0x68, 0x86, 0x5d, 0x3a, 0x83, 0xbd, 0x58, 0x4e, 0x03, - 0xb2, 0x3e, 0xf3, 0x93, 0xa8, 0xe0, 0xaf, 0x30, 0x1e, 0x11, 0x0e, 0xc0, 0xd8, 0xcf, 0x7c, 0x76, 0xc9, 0x06, 0xca, - 0xce, 0x00, 0x42, 0x45, 0x6e, 0xc7, 0x1d, 0x84, 0x46, 0x33, 0x98, 0x3b, 0x0c, 0x0f, 0x7b, 0x36, 0xec, 0x25, 0xd8, - 0x95, 0x61, 0x74, 0xd4, 0xea, 0xf7, 0xb2, 0x70, 0xca, 0x03, 0x4d, 0x5b, 0x59, 0x74, 0x56, 0x2b, 0x6a, 0xf7, 0x7b, - 0xce, 0x26, 0x18, 0xe9, 0x60, 0x8b, 0x3b, 0xf8, 0x84, 0x11, 0x8a, 0x3c, 0xfc, 0xc0, 0xce, 0x5e, 0x5c, 0x4e, 0x1d, - 0x7b, 0x6f, 0xc7, 0xde, 0xc6, 0x52, 0xcf, 0x06, 0xf6, 0x02, 0x0a, 0x86, 0xa7, 0xae, 0xd9, 0x79, 0xb7, 0x8f, 0xa0, - 0x62, 0x21, 0x4e, 0x7e, 0xda, 0xb3, 0xbb, 0x62, 0xea, 0x26, 0x0c, 0x9a, 0xc9, 0xe5, 0xc7, 0x15, 0x3d, 0x24, 0x54, - 0x55, 0x57, 0x05, 0x1d, 0x94, 0xb5, 0x03, 0x67, 0x6c, 0x22, 0xd1, 0xc0, 0xc9, 0x24, 0x15, 0xc0, 0xe1, 0xc1, 0x66, - 0x30, 0xa9, 0xd1, 0x6d, 0xb7, 0xdf, 0x3b, 0x0d, 0xee, 0xdb, 0xf7, 0xd5, 0xc3, 0x08, 0x90, 0xe1, 0x62, 0xfa, 0x11, - 0x48, 0x3b, 0xfc, 0x3c, 0xe7, 0x80, 0xe4, 0x29, 0x15, 0x4d, 0x65, 0xd1, 0x19, 0x16, 0x1d, 0x06, 0x08, 0xaa, 0x97, - 0x6b, 0xeb, 0x4f, 0xac, 0xc9, 0x30, 0x24, 0xd8, 0xc1, 0x16, 0x3a, 0x62, 0xdb, 0xad, 0x3e, 0x9e, 0x37, 0xe4, 0xbc, - 0xf8, 0x36, 0xe6, 0xa0, 0x12, 0x76, 0xba, 0xb6, 0xdb, 0xb3, 0x2d, 0x5c, 0xda, 0x4e, 0xba, 0x1d, 0x0a, 0x0a, 0xc7, - 0xdb, 0x87, 0x3c, 0x18, 0x77, 0xc3, 0x66, 0xcf, 0x29, 0x64, 0xb8, 0x11, 0xcf, 0x2d, 0x85, 0x04, 0x6f, 0x7a, 0x63, - 0x10, 0xe8, 0xc8, 0xb9, 0x9b, 0xf6, 0xb6, 0x2a, 0x84, 0xa2, 0xe3, 0xed, 0xa1, 0x1b, 0xc4, 0xf0, 0xe1, 0x34, 0x90, - 0x69, 0xc6, 0xba, 0xaf, 0xd2, 0xcc, 0xcc, 0x0d, 0x86, 0xca, 0x22, 0x4f, 0xc2, 0x74, 0xdb, 0xc1, 0x08, 0x2d, 0x48, - 0xda, 0xbd, 0x1e, 0xc0, 0xb0, 0xed, 0x28, 0x4e, 0xdb, 0x51, 0xac, 0xa6, 0xec, 0xf3, 0x23, 0xbd, 0x1c, 0x03, 0xde, - 0x1b, 0xa8, 0xf3, 0x58, 0xd4, 0x3e, 0x00, 0x56, 0x90, 0x78, 0x45, 0x5f, 0x9d, 0x79, 0xbd, 0xac, 0x9d, 0x6f, 0xcd, - 0x95, 0x28, 0xe2, 0x9e, 0x21, 0xa1, 0x58, 0xa9, 0xdd, 0x30, 0x61, 0x6e, 0x4f, 0x91, 0x18, 0x9a, 0xe5, 0x43, 0xd8, - 0x63, 0xa1, 0x0a, 0xb0, 0x67, 0xe6, 0xb6, 0x48, 0xc2, 0xaa, 0xb9, 0x77, 0x04, 0xac, 0xdd, 0x0f, 0xdf, 0x08, 0x77, - 0xaa, 0xa3, 0xa2, 0xf9, 0x2c, 0x09, 0x5f, 0x2e, 0x1c, 0x17, 0x47, 0x78, 0x22, 0x74, 0xe0, 0x0f, 0x66, 0x39, 0xc8, - 0x03, 0xfe, 0x16, 0x2c, 0x83, 0x50, 0x36, 0x45, 0x47, 0x0f, 0x8f, 0x80, 0x3d, 0x42, 0x7c, 0x21, 0x6c, 0x6e, 0x54, - 0xa3, 0x45, 0x49, 0xc6, 0x0b, 0x1d, 0x0c, 0x77, 0x98, 0x74, 0xed, 0x51, 0x30, 0xc8, 0x13, 0x63, 0x07, 0xcf, 0xfc, - 0xfd, 0x01, 0x56, 0xe3, 0x04, 0x85, 0x5b, 0xd2, 0x6e, 0xab, 0xc4, 0xdf, 0x81, 0x9f, 0x82, 0x04, 0xc7, 0x3a, 0xf0, - 0xb3, 0xb6, 0xb6, 0x12, 0x89, 0xd4, 0x5e, 0xd6, 0xa1, 0x93, 0x08, 0x8c, 0x07, 0x17, 0x7e, 0x0a, 0xd5, 0x48, 0x22, - 0x2a, 0x22, 0x0b, 0xd4, 0x3c, 0x55, 0xab, 0xe0, 0x3b, 0x32, 0x23, 0xf0, 0x8c, 0x92, 0x5c, 0xd0, 0x50, 0xd4, 0x8d, - 0x45, 0x2c, 0xdf, 0x75, 0xe9, 0x68, 0x0b, 0x0f, 0x20, 0x05, 0xa3, 0x09, 0x86, 0x71, 0x29, 0x28, 0x59, 0xf1, 0xdf, - 0xb1, 0x11, 0x2b, 0x1f, 0x1f, 0xa5, 0xdb, 0xdb, 0x7d, 0x71, 0x6e, 0x41, 0x8c, 0xc3, 0x8c, 0xe8, 0x6a, 0x5c, 0x01, - 0x50, 0x9f, 0xce, 0x89, 0xeb, 0x81, 0x69, 0xc5, 0x9a, 0x2e, 0xc5, 0x3e, 0x39, 0xcc, 0x00, 0x14, 0xdc, 0x71, 0x8e, - 0xfc, 0xde, 0x9f, 0xfb, 0xe0, 0x1e, 0xfb, 0x7f, 0x72, 0x77, 0x94, 0xa0, 0xe9, 0xc8, 0x33, 0xc5, 0x39, 0x9d, 0xb1, - 0xb6, 0x3c, 0x8a, 0x8d, 0x06, 0x20, 0xf5, 0x00, 0x03, 0xd0, 0xe6, 0x20, 0x13, 0x2a, 0x0e, 0x42, 0x8e, 0x0a, 0x6c, - 0x1f, 0x37, 0x3f, 0xc3, 0x9d, 0xfd, 0x9c, 0x07, 0x60, 0xc1, 0xa8, 0xa7, 0xd7, 0xf0, 0xf4, 0x67, 0xfd, 0xf4, 0x13, - 0x0f, 0x7e, 0x29, 0x65, 0xe8, 0xbe, 0x36, 0xc5, 0x23, 0x35, 0x45, 0x29, 0x96, 0xc8, 0xa0, 0x21, 0x77, 0x97, 0x63, - 0x36, 0xcc, 0x2d, 0x81, 0x18, 0x4a, 0x74, 0x81, 0x8d, 0x16, 0x9d, 0x21, 0x71, 0x5d, 0x93, 0x14, 0x46, 0x2e, 0x81, - 0x89, 0x70, 0xc5, 0xb7, 0x48, 0x4f, 0xd6, 0x6d, 0xba, 0xf3, 0x5a, 0x5b, 0xb2, 0xef, 0xd8, 0x64, 0xca, 0xaf, 0x0e, - 0x48, 0xd1, 0x07, 0x32, 0x6d, 0x40, 0x9c, 0x9d, 0x37, 0x3b, 0xf1, 0x1e, 0xeb, 0xc4, 0x20, 0xd5, 0x0b, 0xc5, 0x62, - 0xb8, 0x57, 0xbd, 0xf7, 0x18, 0xa5, 0x34, 0x99, 0xc9, 0xab, 0xa1, 0xd7, 0x96, 0xe8, 0x6d, 0x6f, 0x03, 0x82, 0x1d, - 0xa3, 0x2b, 0x13, 0x5d, 0xcb, 0x52, 0xd0, 0x04, 0x20, 0x7a, 0x52, 0x67, 0x39, 0xe2, 0x38, 0xcc, 0x66, 0x83, 0xe2, - 0x21, 0x77, 0x57, 0x8e, 0x8a, 0x63, 0x62, 0x77, 0x99, 0xb0, 0x03, 0x98, 0x11, 0x97, 0x37, 0x5a, 0x22, 0x3a, 0x2c, - 0xfa, 0xeb, 0xf8, 0xf6, 0xb1, 0xc7, 0xb7, 0x5b, 0x2e, 0x68, 0x90, 0xda, 0x58, 0x8f, 0xab, 0xb1, 0xa0, 0x3e, 0x3c, - 0xd6, 0x54, 0x2a, 0xf3, 0xed, 0xed, 0xb2, 0x7e, 0x54, 0xab, 0x76, 0x70, 0xed, 0x34, 0xe5, 0x72, 0x31, 0x1b, 0x84, - 0x03, 0x11, 0x13, 0x28, 0xd0, 0xd2, 0xca, 0x8a, 0x01, 0x86, 0x94, 0xe5, 0x28, 0x9f, 0x42, 0xee, 0xc5, 0x65, 0xa9, - 0x53, 0x5f, 0x9e, 0xc9, 0xa0, 0x23, 0x9e, 0x7a, 0x92, 0xb1, 0x02, 0xac, 0xe6, 0x65, 0x5e, 0x42, 0x4b, 0x04, 0x98, - 0xbf, 0x50, 0x39, 0x34, 0xc2, 0x02, 0x89, 0x42, 0xc3, 0x2c, 0x51, 0xc6, 0x67, 0x1e, 0xc6, 0xa0, 0xed, 0x9f, 0xd5, - 0x62, 0x5f, 0xb9, 0x32, 0x3a, 0xf2, 0xa3, 0xa2, 0x1f, 0x50, 0xfd, 0x4c, 0x4a, 0xb0, 0x71, 0xf8, 0x11, 0xd8, 0xa8, - 0x72, 0x3c, 0x49, 0x10, 0x3e, 0x8f, 0x73, 0x46, 0x9e, 0xc2, 0xa6, 0x84, 0x59, 0x9a, 0xb6, 0x91, 0x6a, 0x17, 0x99, - 0x41, 0x28, 0x17, 0xe6, 0x1f, 0x1b, 0x67, 0x17, 0x69, 0xb8, 0xd4, 0x1a, 0xcc, 0x8f, 0x77, 0x26, 0x40, 0xe9, 0xf5, - 0x75, 0x2a, 0x7c, 0xdc, 0x88, 0xec, 0x0d, 0x5d, 0x31, 0xee, 0x29, 0xa4, 0x02, 0x27, 0x22, 0x8b, 0x87, 0xce, 0x50, - 0x68, 0x84, 0x43, 0x3a, 0x45, 0x2e, 0x5c, 0x63, 0xd3, 0x17, 0x3d, 0xed, 0x1b, 0x65, 0xa1, 0x93, 0x80, 0x10, 0x10, - 0xb8, 0x1b, 0xd6, 0x54, 0xd6, 0xcb, 0x82, 0x84, 0x4a, 0xd1, 0xcf, 0x01, 0xfc, 0xc3, 0x48, 0x52, 0x00, 0xec, 0x87, - 0x6a, 0xa4, 0x88, 0xb2, 0x2c, 0x70, 0x01, 0x68, 0xae, 0x03, 0x5c, 0x09, 0x5f, 0x18, 0xa8, 0x30, 0x3d, 0xcd, 0xca, - 0x4a, 0xa1, 0x44, 0x9e, 0xae, 0x48, 0x59, 0x23, 0x99, 0x7c, 0x8e, 0x0e, 0x9f, 0xf2, 0xae, 0xdf, 0x4a, 0x3c, 0x74, - 0xc1, 0x73, 0x58, 0x56, 0xf5, 0xfd, 0x4d, 0xc8, 0xc8, 0xb9, 0x06, 0x5d, 0x21, 0x85, 0xfe, 0x92, 0x93, 0xbc, 0xff, - 0xc6, 0xaf, 0x6a, 0xa9, 0x31, 0x94, 0x7d, 0x5c, 0xd5, 0x0c, 0xcb, 0xcb, 0x69, 0x15, 0xa6, 0x20, 0xe0, 0xe6, 0x2c, - 0x09, 0xe6, 0x52, 0x43, 0x80, 0x85, 0xed, 0x91, 0x56, 0x0a, 0x8a, 0x52, 0x87, 0x77, 0x9e, 0x83, 0x15, 0x60, 0x1c, - 0x6a, 0xa9, 0x64, 0x1a, 0x49, 0x7c, 0xa9, 0x44, 0x81, 0x29, 0x0f, 0x06, 0xe0, 0xa7, 0x2e, 0x9e, 0x74, 0x5d, 0xba, - 0x7e, 0x3c, 0xc1, 0xd4, 0x1e, 0x02, 0x3d, 0xf6, 0x36, 0xc0, 0x94, 0xa8, 0xeb, 0xb0, 0x9c, 0x38, 0x34, 0xad, 0x69, - 0x16, 0x30, 0x63, 0x9a, 0xa0, 0x25, 0x9b, 0x60, 0xcb, 0x15, 0x60, 0x1f, 0x89, 0xed, 0x59, 0xad, 0x80, 0xd0, 0x35, - 0x68, 0x60, 0xc8, 0x5d, 0x2a, 0xb4, 0x30, 0xeb, 0xb4, 0xa9, 0x08, 0xf7, 0x67, 0x8f, 0x49, 0x2b, 0x38, 0xf5, 0x52, - 0x1a, 0xf8, 0x20, 0x3e, 0x4d, 0x30, 0xf1, 0x05, 0xb1, 0x02, 0x3b, 0x38, 0x68, 0x2d, 0x36, 0x05, 0x4e, 0xc5, 0x45, - 0x4a, 0x61, 0x59, 0x51, 0x6a, 0xc3, 0x87, 0x14, 0xd9, 0xba, 0xcb, 0x23, 0xdd, 0x85, 0x58, 0x00, 0x3b, 0xfd, 0xc2, - 0xa1, 0x83, 0xac, 0x97, 0x01, 0x83, 0x73, 0xad, 0x71, 0x10, 0xf8, 0xed, 0xed, 0xa4, 0x5f, 0x66, 0x48, 0xb9, 0x25, - 0x56, 0x17, 0x90, 0xe3, 0x76, 0x58, 0xc0, 0x1d, 0x84, 0xa5, 0xb2, 0xc7, 0xf3, 0x72, 0x82, 0xcb, 0xa5, 0x2c, 0xe4, - 0xc5, 0x74, 0x2c, 0x9a, 0xcf, 0xad, 0x34, 0x9b, 0x8e, 0xb7, 0xe2, 0x83, 0x82, 0xbf, 0xe7, 0xc4, 0xd2, 0xaa, 0xa7, - 0xd4, 0x0a, 0x8f, 0x32, 0xb7, 0x64, 0x9d, 0x92, 0x5a, 0x6d, 0x37, 0x50, 0x8d, 0xf0, 0x34, 0x0d, 0x1b, 0x81, 0x10, - 0x13, 0x5c, 0xfc, 0x61, 0x91, 0x89, 0x69, 0x6f, 0x09, 0xa9, 0x23, 0xec, 0x1e, 0xca, 0x09, 0x6e, 0x6b, 0x9e, 0x7d, - 0x19, 0x4e, 0xd7, 0x33, 0xf7, 0xbe, 0xc1, 0xdc, 0x4f, 0x43, 0x66, 0x30, 0x7a, 0x2c, 0x13, 0x7e, 0x64, 0xec, 0xa3, - 0x50, 0x55, 0xcf, 0xce, 0xc2, 0x4a, 0x64, 0x89, 0x6f, 0xc6, 0x51, 0x87, 0x71, 0x2a, 0x5a, 0x13, 0x64, 0xd7, 0xd7, - 0xb9, 0xb9, 0x17, 0x28, 0x68, 0xea, 0xb1, 0x7a, 0x9c, 0xb6, 0x62, 0x67, 0x23, 0x12, 0xb9, 0xff, 0xa6, 0x16, 0x89, - 0xac, 0xf8, 0x1c, 0x47, 0x5a, 0x73, 0x90, 0xfb, 0xec, 0x6c, 0x79, 0x93, 0x0a, 0xdd, 0xa2, 0xd1, 0x36, 0xf6, 0xa8, - 0x3e, 0x90, 0xd4, 0x33, 0x2a, 0xb0, 0xaa, 0xb1, 0xb7, 0xb6, 0x5a, 0x22, 0xdd, 0x52, 0x29, 0x36, 0x0c, 0x69, 0x85, - 0xcc, 0x18, 0x05, 0x83, 0x92, 0x22, 0x03, 0x35, 0xca, 0xd7, 0x08, 0x86, 0x7d, 0x6a, 0x00, 0x8a, 0x73, 0x75, 0xf5, - 0xd3, 0x52, 0xb2, 0x85, 0x80, 0x04, 0x64, 0x13, 0x8a, 0x35, 0x62, 0x66, 0xe4, 0x93, 0x8f, 0xc0, 0x79, 0x3d, 0x8e, - 0x8e, 0x01, 0xc8, 0x60, 0xb1, 0xe9, 0xc1, 0xc4, 0xb6, 0x89, 0x28, 0xfa, 0x6c, 0xe0, 0x25, 0x00, 0x3b, 0xad, 0x42, - 0xa3, 0x1f, 0xaa, 0x14, 0x30, 0x64, 0x03, 0x37, 0xe0, 0x55, 0x58, 0x6e, 0xff, 0x25, 0xb4, 0x83, 0xc7, 0x17, 0xb2, - 0xf9, 0x26, 0xe6, 0x09, 0x56, 0xb1, 0x3b, 0xbf, 0xb2, 0xac, 0xc5, 0xb9, 0xd3, 0xe1, 0x42, 0xbd, 0xa2, 0x84, 0xa8, - 0x3d, 0xc0, 0xda, 0x97, 0x9c, 0x60, 0xc4, 0xe7, 0x37, 0x94, 0x75, 0xa8, 0xc6, 0x2d, 0xf7, 0x35, 0x5a, 0x84, 0xe9, - 0x32, 0x69, 0x0c, 0x4a, 0xd6, 0xfd, 0x64, 0xc4, 0xbd, 0x3c, 0x10, 0xb1, 0xe0, 0x0a, 0x47, 0x23, 0x6c, 0xbe, 0x80, - 0x24, 0x7d, 0xdb, 0xa7, 0x03, 0xf6, 0xcd, 0xc5, 0x5e, 0x40, 0x99, 0x8f, 0x15, 0xa9, 0x24, 0xa4, 0x34, 0xbb, 0x21, - 0x92, 0x84, 0xb5, 0x22, 0x4f, 0x9d, 0x0f, 0x1c, 0xed, 0x73, 0x2b, 0x89, 0x60, 0x04, 0x27, 0x71, 0xba, 0xf2, 0x70, - 0x51, 0x80, 0xab, 0xe8, 0x88, 0xe9, 0x9b, 0xa0, 0xfc, 0x06, 0xb9, 0xbd, 0x94, 0x5c, 0x5b, 0x68, 0x18, 0x9e, 0x21, - 0xc1, 0xaa, 0x48, 0x04, 0x3a, 0x0a, 0x80, 0xe3, 0x4a, 0xcf, 0x03, 0x4c, 0xf8, 0xda, 0xde, 0x04, 0x80, 0x44, 0x56, - 0x90, 0xb3, 0x14, 0xe8, 0x06, 0x2c, 0x57, 0xc7, 0xa9, 0x51, 0x91, 0xb8, 0xb8, 0x31, 0x5d, 0xdd, 0xd2, 0x9f, 0xa0, - 0xe5, 0x4c, 0x86, 0x98, 0x0e, 0x82, 0x80, 0x4c, 0x7d, 0xca, 0x9d, 0x9c, 0xa6, 0x13, 0xd6, 0xe7, 0xd4, 0xa9, 0x4d, - 0xdd, 0xe1, 0xd4, 0xcd, 0x93, 0xd4, 0x62, 0x75, 0xda, 0x94, 0x12, 0x31, 0x29, 0x31, 0x8f, 0x65, 0x2a, 0xb6, 0x12, - 0x77, 0x6e, 0x7d, 0xa3, 0x85, 0xb4, 0xd1, 0x8e, 0x65, 0x0e, 0xb6, 0x96, 0xf7, 0x42, 0xb4, 0xbf, 0x24, 0xc2, 0xb3, - 0x12, 0x19, 0x6b, 0x3e, 0xe3, 0x8e, 0x89, 0x60, 0xf5, 0x60, 0x2a, 0xf2, 0x0f, 0x8e, 0x4e, 0xb3, 0x37, 0xe8, 0x41, - 0xea, 0x0d, 0x24, 0x66, 0x4d, 0x7c, 0xe7, 0xd2, 0x50, 0x47, 0x08, 0x54, 0x46, 0xb5, 0x4c, 0xc7, 0x89, 0xa5, 0xe2, - 0x92, 0x7c, 0xf5, 0x5e, 0x1f, 0xe7, 0x1b, 0xdf, 0x17, 0x56, 0x23, 0x88, 0xc1, 0x5b, 0x28, 0xfa, 0x9e, 0x14, 0xe1, - 0x39, 0x2c, 0xcf, 0xf6, 0x76, 0xa7, 0xd8, 0x63, 0x55, 0x88, 0xa4, 0x82, 0x31, 0xc6, 0x8c, 0x62, 0xdc, 0x13, 0x35, - 0xb5, 0x88, 0xc4, 0x96, 0xad, 0xc3, 0x02, 0x0f, 0x00, 0xa0, 0xa5, 0x29, 0xbd, 0xcc, 0xb6, 0xea, 0x3c, 0x97, 0xf0, - 0x31, 0xf2, 0x50, 0x64, 0xe3, 0xf7, 0x6b, 0x32, 0x50, 0x10, 0xee, 0x8d, 0x96, 0x87, 0x89, 0x71, 0xb0, 0x8a, 0x42, - 0x16, 0xe8, 0x0d, 0xda, 0xa9, 0x12, 0xa1, 0xb8, 0x39, 0x59, 0x87, 0x1b, 0x4e, 0x2a, 0xd8, 0x42, 0x25, 0x2c, 0x95, - 0x16, 0xf8, 0xd5, 0x46, 0x58, 0x3c, 0x65, 0xdc, 0x7f, 0x53, 0xe1, 0x0c, 0xfa, 0x83, 0x7b, 0xcb, 0x8c, 0xfa, 0x7e, - 0xe9, 0x44, 0xa6, 0x02, 0x13, 0x37, 0xb3, 0xd4, 0x7e, 0xbf, 0xac, 0xd2, 0x7e, 0x5e, 0x2e, 0xf7, 0x39, 0x69, 0xbe, - 0xd6, 0x1d, 0x34, 0x9f, 0x0c, 0xf7, 0x2b, 0xe5, 0x87, 0x16, 0x46, 0x4d, 0xf9, 0xd5, 0x97, 0x34, 0xcc, 0x3d, 0x15, - 0xde, 0xea, 0xb6, 0x51, 0xe8, 0xa2, 0x3e, 0x07, 0x43, 0x48, 0x7f, 0x05, 0xd7, 0xd0, 0xe0, 0x41, 0x91, 0x2c, 0x16, - 0x6b, 0x17, 0xc4, 0xf5, 0x31, 0xa7, 0xda, 0xa1, 0x8c, 0x31, 0xe2, 0x69, 0xc9, 0x41, 0x92, 0xc1, 0xc1, 0xf8, 0x0d, - 0x0c, 0x88, 0x49, 0x49, 0x48, 0x87, 0xd0, 0x59, 0x99, 0x89, 0xa8, 0xdc, 0xc5, 0xdb, 0x8d, 0xcb, 0x9a, 0x42, 0x11, - 0x76, 0x82, 0x99, 0x4a, 0xa9, 0x20, 0x90, 0x26, 0xdf, 0x46, 0xab, 0x16, 0x0c, 0x05, 0xd1, 0x60, 0x28, 0x20, 0x0f, - 0xd3, 0x55, 0xc2, 0x8d, 0x8f, 0xe2, 0xe0, 0x79, 0x85, 0x1a, 0xf1, 0x52, 0x83, 0xaf, 0x61, 0xf3, 0xd7, 0x44, 0x49, - 0x11, 0x72, 0x11, 0x7b, 0x05, 0x9f, 0x08, 0xd9, 0x94, 0x87, 0x39, 0xd0, 0x0f, 0xed, 0xca, 0x4e, 0xb6, 0x97, 0x57, - 0x2e, 0x2d, 0x1a, 0x5b, 0x89, 0x9a, 0xb5, 0x38, 0x8a, 0xb7, 0xb3, 0x3e, 0x4c, 0x4d, 0x09, 0x04, 0xa4, 0xa9, 0x9c, - 0xa4, 0x9a, 0xf7, 0x28, 0xeb, 0x03, 0x48, 0xb0, 0xfb, 0x09, 0x2c, 0xf4, 0x9b, 0x12, 0x13, 0x2c, 0xaa, 0xc6, 0x6e, - 0x53, 0xd0, 0x9a, 0x53, 0xd2, 0x7c, 0x53, 0x84, 0x70, 0x5b, 0x59, 0xcf, 0x98, 0x1d, 0x60, 0xdb, 0xee, 0x76, 0x7e, - 0x94, 0x6d, 0xb7, 0xfa, 0x86, 0xe0, 0xc2, 0xe3, 0xff, 0xa4, 0xc4, 0x34, 0x90, 0x42, 0xea, 0xc6, 0x4f, 0xa8, 0xc3, - 0x3e, 0x91, 0x3a, 0x11, 0x03, 0x9a, 0xab, 0xb1, 0xe8, 0xdc, 0x6b, 0x8e, 0x92, 0xcb, 0xaa, 0xda, 0xd5, 0x12, 0x34, - 0x74, 0x23, 0x19, 0x13, 0xc5, 0x3c, 0x27, 0x00, 0x46, 0xb1, 0xf9, 0x73, 0xae, 0x93, 0xbc, 0x7f, 0x59, 0x99, 0xda, - 0xed, 0xfb, 0x7e, 0x94, 0x9f, 0xd1, 0x91, 0x8a, 0xca, 0xe6, 0x24, 0xe6, 0xdf, 0x95, 0x60, 0x1a, 0x13, 0x1f, 0xe9, - 0xb9, 0xfa, 0xa1, 0x00, 0x5f, 0xd9, 0x50, 0x6a, 0xb6, 0xd7, 0xbf, 0x75, 0xb6, 0x07, 0x72, 0x36, 0xc1, 0x02, 0x0b, - 0x74, 0x59, 0x83, 0x2f, 0x60, 0x19, 0xdc, 0x91, 0x7e, 0x0a, 0xbe, 0x9f, 0xd6, 0xc1, 0x67, 0xec, 0x7f, 0x01, 0x68, - 0x55, 0x60, 0x40, 0xf9, 0x70, 0xd1, 0xb0, 0x12, 0xe2, 0x12, 0x15, 0x66, 0x15, 0xe7, 0x8f, 0xeb, 0xbc, 0x6e, 0x5a, - 0x96, 0x18, 0x94, 0x9f, 0xba, 0x86, 0x1b, 0xdf, 0x59, 0xc8, 0x1f, 0xdf, 0x7f, 0x09, 0xba, 0x9d, 0x48, 0xbb, 0xb5, - 0x55, 0x6c, 0x90, 0x85, 0x86, 0xf7, 0xc2, 0xa6, 0xd0, 0x16, 0x2f, 0x02, 0x14, 0xea, 0x3b, 0x16, 0xe3, 0x6d, 0x11, - 0x2a, 0xc3, 0x2f, 0x58, 0x30, 0x05, 0x0c, 0xc1, 0x63, 0xa7, 0x32, 0xf9, 0x1d, 0x36, 0x9a, 0x62, 0xd7, 0x42, 0x18, - 0x7c, 0x39, 0xa8, 0x4a, 0xc9, 0x8b, 0x75, 0xb2, 0xbd, 0x38, 0x87, 0xef, 0xaf, 0xe3, 0x02, 0xa8, 0x83, 0xe8, 0x6b, - 0x2a, 0x8b, 0x0d, 0xe4, 0xe2, 0xa6, 0xac, 0xf5, 0x8a, 0x86, 0xc3, 0x1b, 0xbb, 0xf0, 0xba, 0x02, 0x1f, 0x47, 0xe9, - 0x30, 0x11, 0x93, 0x98, 0x49, 0x95, 0x2b, 0x72, 0x6d, 0x74, 0x2f, 0x6d, 0xd1, 0xbc, 0x14, 0x12, 0xbc, 0x22, 0xf0, - 0x82, 0xd0, 0x57, 0xfa, 0x72, 0xb5, 0x81, 0x82, 0x47, 0xed, 0x8b, 0x8b, 0x60, 0x62, 0xe2, 0x71, 0x43, 0x6a, 0xfa, - 0x75, 0x38, 0xb5, 0xb2, 0x58, 0x72, 0xf8, 0x75, 0xce, 0xd8, 0x82, 0x02, 0x20, 0x3e, 0x79, 0xb4, 0xde, 0x4d, 0x7a, - 0xa3, 0xb4, 0x83, 0xd2, 0x08, 0xf1, 0x5d, 0x85, 0xaf, 0x3b, 0x57, 0x7c, 0xe5, 0xaa, 0x7b, 0x5f, 0x57, 0xdc, 0xb8, - 0x60, 0xf4, 0x92, 0x4f, 0x92, 0x85, 0x6b, 0x37, 0x74, 0x57, 0xe7, 0x3b, 0xef, 0x0b, 0x99, 0xb7, 0x70, 0x05, 0x76, - 0xfe, 0x15, 0x77, 0x5e, 0x7a, 0x1f, 0x8c, 0x13, 0xe5, 0xef, 0xcd, 0x23, 0x5e, 0x39, 0xcc, 0xaa, 0x93, 0xe4, 0xef, - 0x7b, 0xdf, 0x07, 0xeb, 0x5b, 0x1a, 0x27, 0xc8, 0x6d, 0x75, 0x82, 0x4c, 0x94, 0x1b, 0xe9, 0x0d, 0xb7, 0x7f, 0x57, - 0x81, 0x20, 0x4e, 0xc5, 0xf4, 0x51, 0x39, 0xae, 0x1f, 0x2d, 0x50, 0xa9, 0x88, 0xf8, 0x5c, 0xe5, 0xae, 0xac, 0x4d, - 0x0d, 0xf5, 0x98, 0x4e, 0x66, 0xa1, 0x69, 0x56, 0xe4, 0x52, 0x2e, 0x7a, 0x8c, 0x5c, 0xb3, 0x53, 0x6d, 0x7e, 0x77, - 0xed, 0x21, 0x1d, 0xc7, 0xfb, 0x9e, 0xb5, 0x5a, 0x70, 0xbf, 0xab, 0x28, 0xbc, 0xeb, 0xc5, 0x46, 0x2a, 0x43, 0xcd, - 0x7a, 0x14, 0x7d, 0x1c, 0x77, 0x31, 0x97, 0x47, 0xd9, 0x9f, 0x35, 0x00, 0x4c, 0x47, 0x58, 0x74, 0x37, 0x3d, 0x63, - 0x4f, 0xa0, 0xa7, 0x27, 0x32, 0x48, 0xf4, 0x56, 0xe7, 0xab, 0x56, 0x89, 0xa5, 0x2b, 0x08, 0xec, 0xde, 0x90, 0xb1, - 0x2a, 0x69, 0xb7, 0x5c, 0xbf, 0x9c, 0xe7, 0xf3, 0x9c, 0x2f, 0xe5, 0xf9, 0xd4, 0x2c, 0xba, 0x8d, 0xa6, 0x7b, 0x73, - 0x6a, 0xa8, 0x98, 0x6b, 0x75, 0x93, 0xdf, 0x30, 0x5d, 0x0b, 0x43, 0x2d, 0x82, 0xcc, 0x6a, 0x57, 0xbd, 0x28, 0xcb, - 0x51, 0x3d, 0x93, 0x63, 0x24, 0x7c, 0x53, 0xe9, 0x0e, 0xd1, 0x0d, 0x53, 0x35, 0xd3, 0x77, 0x0b, 0xdb, 0x42, 0xb6, - 0x79, 0x79, 0x35, 0xcc, 0x81, 0xd2, 0x72, 0x7f, 0x99, 0x30, 0x7c, 0x77, 0x7d, 0xfd, 0x9d, 0x90, 0x53, 0x55, 0x47, - 0x6f, 0xfe, 0x5a, 0xf7, 0x0c, 0x46, 0xa5, 0x72, 0x22, 0x4e, 0xf9, 0xea, 0xc1, 0x17, 0x77, 0xaf, 0x80, 0xe5, 0x14, - 0xb0, 0x3b, 0xe5, 0xce, 0xc2, 0x50, 0xd5, 0x06, 0xfe, 0x62, 0xf5, 0x60, 0xab, 0xf6, 0xf0, 0x17, 0xbd, 0x2f, 0x82, - 0x1b, 0x1b, 0x1b, 0xdb, 0x78, 0xb7, 0x96, 0x08, 0xf2, 0x16, 0x0f, 0xf4, 0xf1, 0xea, 0xa3, 0xa0, 0xe5, 0x0a, 0xb1, - 0xcd, 0x7a, 0x0e, 0x85, 0xad, 0x41, 0xbe, 0x49, 0x99, 0x34, 0x98, 0x15, 0x3c, 0x9b, 0xc8, 0x19, 0x0a, 0x79, 0xcd, - 0xc7, 0x41, 0xdb, 0x11, 0xfe, 0x0f, 0x9c, 0xda, 0xf1, 0xf2, 0xfc, 0x13, 0xf4, 0x01, 0x4f, 0x57, 0x4a, 0x53, 0x8a, - 0x53, 0xaa, 0xa0, 0xce, 0x72, 0x9d, 0x07, 0x23, 0xc5, 0xc5, 0x18, 0x16, 0x17, 0x5c, 0x96, 0x1b, 0x67, 0x23, 0xa7, - 0xbf, 0xc4, 0xab, 0x8b, 0x74, 0xf9, 0x48, 0x64, 0xab, 0x96, 0xde, 0x2b, 0x7d, 0xba, 0x6d, 0x4f, 0x18, 0x1f, 0x67, - 0x43, 0x3a, 0x98, 0xf1, 0x71, 0x22, 0xbc, 0x3e, 0x31, 0xd4, 0x77, 0x8b, 0xc0, 0x74, 0x73, 0x6c, 0xf2, 0xc3, 0xf1, - 0x7a, 0xb3, 0x59, 0xe3, 0xf6, 0xde, 0x39, 0x9f, 0x9c, 0x79, 0x89, 0x11, 0x95, 0xb9, 0x86, 0x07, 0xb4, 0x42, 0xbc, - 0x78, 0xcf, 0x04, 0xc6, 0x65, 0x57, 0x24, 0xb5, 0xdd, 0x40, 0xe0, 0x62, 0x8f, 0x62, 0x96, 0x0c, 0x6d, 0x0f, 0xca, - 0x03, 0x7d, 0x31, 0x9a, 0x6e, 0x01, 0xd3, 0xf2, 0xda, 0xd9, 0x45, 0x6a, 0x7b, 0xd5, 0x54, 0x01, 0xcc, 0x92, 0xe5, - 0xf1, 0x19, 0xb2, 0xee, 0x57, 0xd0, 0x45, 0x0c, 0x18, 0x1b, 0x57, 0xe6, 0xdc, 0xf9, 0xaa, 0x15, 0xf1, 0x8d, 0x26, - 0xd2, 0xa4, 0x3e, 0xa2, 0xbe, 0xfd, 0xb0, 0x56, 0x57, 0x39, 0x48, 0xe0, 0x1e, 0x79, 0x77, 0xc4, 0xa5, 0xa3, 0xcf, - 0x2c, 0x36, 0xab, 0xf4, 0x2d, 0x75, 0x2d, 0x6e, 0x31, 0xec, 0x15, 0xf7, 0xc0, 0xfe, 0xc0, 0xb8, 0x45, 0x2c, 0xe2, - 0xed, 0xac, 0x96, 0xc2, 0xba, 0x30, 0x47, 0x8e, 0xb1, 0xf6, 0xe0, 0x15, 0xaf, 0xd6, 0x0c, 0xcc, 0x30, 0xe3, 0x8c, - 0xe4, 0x8d, 0x71, 0xaf, 0x6a, 0xd3, 0x91, 0xab, 0x00, 0xa2, 0x6f, 0x4e, 0x97, 0xe4, 0xf0, 0x4a, 0x96, 0xab, 0xce, - 0x90, 0x7f, 0x86, 0x75, 0xd6, 0x8b, 0x13, 0x70, 0x93, 0xa6, 0xac, 0xc4, 0xc4, 0x14, 0x71, 0xb9, 0x59, 0xc6, 0x3c, - 0x4d, 0x9f, 0x45, 0x3b, 0x38, 0x85, 0x91, 0xc0, 0x11, 0xfb, 0xc6, 0x32, 0x2c, 0x26, 0x6c, 0xc4, 0x44, 0x1a, 0x95, - 0x52, 0xc2, 0x7a, 0x72, 0xa9, 0x25, 0x7f, 0x99, 0xcb, 0xab, 0x2f, 0xb7, 0x09, 0x0e, 0x28, 0x6a, 0x60, 0x39, 0x34, - 0x8e, 0x5b, 0x06, 0x12, 0xb1, 0x18, 0x10, 0xa3, 0x56, 0xe5, 0x72, 0x32, 0xaa, 0x93, 0xfa, 0x0a, 0xb9, 0x50, 0x91, - 0x07, 0xb7, 0x04, 0x4a, 0xfe, 0x02, 0x53, 0x07, 0xd3, 0x52, 0xbb, 0x69, 0xb1, 0x49, 0xf2, 0x8e, 0x19, 0x90, 0x5c, - 0x7d, 0x0d, 0x0f, 0x8d, 0x5f, 0x86, 0x37, 0x14, 0x3d, 0x1d, 0x23, 0xe4, 0xb4, 0x34, 0xe6, 0xd2, 0x7f, 0x23, 0xcf, - 0xbe, 0x24, 0x60, 0x3f, 0x83, 0x98, 0x32, 0x70, 0x89, 0x8d, 0x0b, 0x92, 0xf2, 0x5a, 0x9e, 0xb2, 0xfb, 0x16, 0x94, - 0xef, 0x92, 0x49, 0x57, 0xa9, 0xac, 0x35, 0x56, 0xdd, 0xcf, 0x33, 0x96, 0x5f, 0x1d, 0x30, 0xcc, 0x4d, 0x46, 0x83, - 0x6c, 0xc9, 0xcc, 0xa6, 0xfc, 0x6a, 0xef, 0xc6, 0xb7, 0x3c, 0x94, 0x74, 0xa8, 0x56, 0xe9, 0xe6, 0xa5, 0x1b, 0x8e, - 0xf1, 0xc2, 0x0d, 0xc7, 0xb8, 0x43, 0xe7, 0xca, 0x15, 0xa9, 0x75, 0xfe, 0xfb, 0x52, 0xf8, 0x49, 0xec, 0xb5, 0xbe, - 0xde, 0x75, 0xfd, 0x95, 0xe9, 0xe9, 0x37, 0xa0, 0x6a, 0x64, 0x09, 0xdd, 0x84, 0x2a, 0x26, 0x23, 0x51, 0x62, 0xba, - 0x4a, 0x79, 0xd4, 0xd7, 0x88, 0x0b, 0x10, 0x37, 0x94, 0xbf, 0xf8, 0x97, 0xf0, 0xe2, 0x24, 0x40, 0x23, 0x6a, 0x3e, - 0xca, 0x52, 0xde, 0x18, 0x45, 0x93, 0x38, 0xb9, 0x0a, 0x66, 0x71, 0x63, 0x92, 0xa5, 0x59, 0x31, 0x05, 0xae, 0xf4, - 0x8a, 0x2b, 0xb0, 0xe1, 0x27, 0x8d, 0x59, 0xec, 0xbd, 0x64, 0xc9, 0x39, 0xe3, 0xf1, 0x20, 0xf2, 0xec, 0xfd, 0x1c, - 0xc4, 0x83, 0xf5, 0x36, 0xca, 0xf3, 0xec, 0xc2, 0xf6, 0x3e, 0x64, 0xa7, 0xc0, 0xb4, 0xde, 0xbb, 0xcb, 0xab, 0x33, - 0x96, 0x7a, 0x1f, 0x4f, 0x67, 0x29, 0x9f, 0x79, 0x45, 0x94, 0x16, 0x8d, 0x82, 0xe5, 0xf1, 0x08, 0xd4, 0x44, 0x92, - 0xe5, 0x0d, 0xcc, 0x7f, 0x9e, 0xb0, 0x20, 0x89, 0xcf, 0xc6, 0xdc, 0x1a, 0x46, 0xf9, 0xa7, 0x4e, 0xa3, 0x31, 0xcd, - 0xe3, 0x49, 0x94, 0x5f, 0x35, 0xa8, 0x45, 0x70, 0xaf, 0xb9, 0x1b, 0x7d, 0x36, 0x7a, 0xd0, 0xe1, 0x39, 0xf4, 0x8d, - 0x91, 0x8a, 0x01, 0x08, 0x1f, 0x6b, 0xf7, 0x61, 0x73, 0x52, 0x6c, 0x88, 0x13, 0xa5, 0x28, 0xe5, 0xe5, 0x89, 0x77, - 0x01, 0xb6, 0xed, 0x89, 0x7f, 0xca, 0x53, 0x0f, 0x7c, 0x39, 0x9e, 0xa5, 0xf3, 0xc1, 0x2c, 0x2f, 0x60, 0x80, 0x69, - 0x16, 0xa7, 0x9c, 0xe5, 0x9d, 0xd3, 0x2c, 0x07, 0xb2, 0x35, 0xf2, 0x68, 0x18, 0xcf, 0x8a, 0xe0, 0xc1, 0xf4, 0xb2, - 0x83, 0xb6, 0xc2, 0x59, 0x9e, 0xcd, 0xd2, 0xa1, 0x9c, 0x2b, 0x4e, 0x61, 0x63, 0xc4, 0xdc, 0xac, 0xa0, 0x37, 0xa1, - 0x00, 0x7c, 0x29, 0x8b, 0xf2, 0xc6, 0x19, 0x76, 0x46, 0x43, 0xbf, 0x39, 0x64, 0x67, 0x5e, 0x7e, 0x76, 0x1a, 0x39, - 0xad, 0xf6, 0x63, 0x4f, 0xfd, 0xf9, 0x0f, 0x5d, 0x30, 0xdc, 0x57, 0x16, 0xb7, 0x9a, 0xcd, 0xbf, 0x71, 0x3b, 0x0b, - 0xb3, 0x10, 0x40, 0x41, 0x6b, 0x7a, 0x69, 0x15, 0x59, 0x02, 0xeb, 0xb3, 0xaa, 0x67, 0x67, 0x0a, 0x7e, 0x53, 0x9c, - 0x9e, 0x05, 0xed, 0xe9, 0x65, 0x89, 0xd8, 0x05, 0x22, 0x21, 0x53, 0x22, 0x29, 0x9f, 0xe6, 0xbf, 0x15, 0xe2, 0x27, - 0xab, 0x21, 0x6e, 0x2b, 0x88, 0x2b, 0xaa, 0x37, 0x86, 0xb0, 0x0f, 0x88, 0xfc, 0xad, 0x42, 0x00, 0x32, 0x06, 0x27, - 0x30, 0x57, 0x70, 0xd0, 0xc3, 0x6f, 0x06, 0xa3, 0xbd, 0x1a, 0x8c, 0x27, 0xb7, 0x81, 0x91, 0xa7, 0xc3, 0x79, 0x7d, - 0x5d, 0x5b, 0xe0, 0x9c, 0x76, 0xc6, 0x0c, 0xf9, 0x29, 0x68, 0xe3, 0xf7, 0x8b, 0x78, 0xc8, 0xc7, 0xe2, 0x2b, 0xb1, - 0xf3, 0x85, 0xa8, 0x7b, 0xd8, 0x6c, 0x8a, 0xe7, 0x02, 0x14, 0x5a, 0xd0, 0xf2, 0xb1, 0x01, 0x30, 0xd1, 0xe7, 0xeb, - 0x5e, 0x62, 0xf3, 0xed, 0xad, 0x6f, 0xaa, 0xf1, 0xb8, 0xca, 0x1b, 0x14, 0x2a, 0x42, 0xbd, 0xb3, 0x05, 0x33, 0xde, - 0x8a, 0x6e, 0x4b, 0x1f, 0x54, 0xf5, 0xbe, 0xe5, 0xa4, 0xf5, 0x02, 0xe6, 0x99, 0xb9, 0x40, 0x9d, 0xac, 0x8b, 0x21, - 0xa9, 0x46, 0xc3, 0x05, 0xbd, 0xc1, 0x31, 0x84, 0x44, 0x07, 0x82, 0x4e, 0xd1, 0xcb, 0xe9, 0x9d, 0x1a, 0xa9, 0x1b, - 0xe4, 0x4e, 0xea, 0xc2, 0x96, 0x4f, 0xb5, 0x5c, 0x2f, 0xb6, 0xb6, 0xc0, 0xcb, 0xfe, 0x9c, 0xcb, 0x06, 0x20, 0xbd, - 0x2b, 0x49, 0x6b, 0xbc, 0x87, 0x44, 0xb9, 0x7c, 0xd9, 0x80, 0x28, 0x07, 0xbe, 0x3e, 0x1f, 0xa3, 0xdf, 0xad, 0xaf, - 0xae, 0x1b, 0x29, 0x35, 0x3b, 0xb6, 0xdb, 0xe3, 0x3a, 0x2b, 0x0b, 0xb3, 0xcf, 0x78, 0x89, 0xa3, 0x7c, 0xc9, 0x43, - 0x1c, 0xd1, 0x7b, 0x15, 0x0a, 0x37, 0x4d, 0x39, 0x69, 0xa3, 0xbb, 0x3a, 0x69, 0xf0, 0x35, 0xa6, 0xcc, 0x67, 0x15, - 0x27, 0x07, 0x37, 0xe6, 0x78, 0x20, 0xae, 0x20, 0x16, 0x55, 0x96, 0x7d, 0x44, 0xd0, 0x0b, 0xbf, 0x0b, 0x94, 0x14, - 0x46, 0x2e, 0xbf, 0xe2, 0xbf, 0xc3, 0xe3, 0x70, 0x34, 0xfa, 0x45, 0x36, 0xcb, 0x07, 0x78, 0x39, 0x60, 0x45, 0x28, - 0xc2, 0x26, 0x4b, 0xc0, 0xf6, 0xb8, 0x56, 0x40, 0x0c, 0xf3, 0x2c, 0xcc, 0xb7, 0x2f, 0x30, 0x3a, 0x9d, 0x11, 0x97, - 0x1f, 0x64, 0xf8, 0x45, 0xa1, 0x84, 0x3a, 0x75, 0x48, 0x89, 0x78, 0x74, 0x31, 0xd4, 0x9f, 0xa5, 0x31, 0x88, 0xe0, - 0xe3, 0x78, 0x48, 0x17, 0x62, 0xe2, 0x21, 0x9d, 0x90, 0x34, 0x28, 0x23, 0x0a, 0x43, 0xee, 0x50, 0x20, 0x17, 0x06, - 0xbf, 0xcb, 0x0c, 0x1b, 0xbb, 0x61, 0xe3, 0x29, 0x87, 0xa1, 0xc3, 0x87, 0xd9, 0x24, 0x8a, 0xd3, 0x00, 0x5f, 0x5c, - 0xe2, 0xe9, 0x11, 0x03, 0xec, 0xe2, 0xc1, 0xa7, 0x5a, 0xa3, 0x96, 0xeb, 0xff, 0x04, 0x02, 0x8e, 0xfa, 0x63, 0x32, - 0x0b, 0x91, 0x55, 0x10, 0x31, 0x54, 0x64, 0xde, 0x57, 0x7a, 0xde, 0x33, 0xab, 0x55, 0xcc, 0xb4, 0xbe, 0x0e, 0xcd, - 0x85, 0xe5, 0xd2, 0x67, 0xd8, 0xf5, 0x52, 0x10, 0xac, 0x5c, 0xe7, 0xd1, 0x53, 0x10, 0x67, 0x8f, 0xd1, 0x47, 0xaf, - 0xd1, 0x0a, 0x5a, 0xda, 0x2f, 0xaf, 0x5d, 0xb5, 0x15, 0x89, 0x3a, 0xf2, 0xba, 0x26, 0xe1, 0xa1, 0xbf, 0x0b, 0x5c, - 0xab, 0x67, 0x8d, 0xaf, 0x27, 0x37, 0x1d, 0x46, 0xa7, 0xce, 0x52, 0xa7, 0x06, 0x04, 0x1d, 0x74, 0xac, 0x99, 0xca, - 0x2d, 0x2b, 0xbc, 0xb5, 0xf1, 0x67, 0x0b, 0xcd, 0x89, 0xaf, 0x1e, 0x90, 0x33, 0xd2, 0x2b, 0x9e, 0x56, 0xf0, 0x5d, - 0x29, 0x09, 0xb2, 0x78, 0x21, 0x7f, 0xa1, 0x99, 0x00, 0xe5, 0x4a, 0x1f, 0x64, 0x2f, 0xd4, 0x8a, 0x47, 0x26, 0x22, - 0xde, 0xab, 0x9b, 0x50, 0xd6, 0xd8, 0x32, 0x5c, 0xe8, 0x8b, 0x16, 0x5c, 0xc1, 0x8f, 0x06, 0xd3, 0x88, 0xe1, 0xbd, - 0x94, 0x93, 0xcd, 0xf9, 0x97, 0xbc, 0xdc, 0xd9, 0x9c, 0xab, 0x86, 0xe2, 0x7b, 0x3c, 0xc4, 0x4f, 0x06, 0xf2, 0x6b, - 0x2e, 0xac, 0xc7, 0xc0, 0x7e, 0xff, 0xee, 0xe0, 0xd0, 0xf6, 0x4e, 0xb3, 0xe1, 0x55, 0x60, 0xc3, 0xee, 0x64, 0x76, - 0xe9, 0xfa, 0x7c, 0xcc, 0x52, 0x47, 0xb1, 0x78, 0x96, 0x30, 0x90, 0x08, 0x67, 0xe2, 0xb2, 0xe3, 0xa2, 0xe7, 0x3b, - 0x3c, 0xd9, 0xa3, 0xb7, 0x21, 0x75, 0xf7, 0xb8, 0x78, 0x51, 0x18, 0xcf, 0xf1, 0x6b, 0x17, 0x63, 0xff, 0x7b, 0x3b, - 0xf0, 0x05, 0x1f, 0x0e, 0x70, 0xcf, 0xd0, 0xd3, 0xe6, 0x7c, 0x89, 0x93, 0x7a, 0x38, 0xc4, 0xb8, 0x2b, 0x50, 0x28, - 0xa8, 0xd5, 0x49, 0x30, 0x3c, 0x39, 0x29, 0xe1, 0x2b, 0x8c, 0xb5, 0xa3, 0xc6, 0x45, 0x08, 0x55, 0x7f, 0xcd, 0x5d, - 0xf2, 0x75, 0x3b, 0x38, 0x04, 0xce, 0x3b, 0xc4, 0x06, 0xc4, 0x5d, 0xd8, 0x7b, 0xa8, 0x4b, 0x68, 0xd3, 0x8a, 0xa2, - 0x75, 0x10, 0x88, 0x86, 0x15, 0xd3, 0x8b, 0x10, 0x61, 0xb5, 0xba, 0x0a, 0xa4, 0xa1, 0x09, 0xdd, 0x89, 0x8b, 0x9f, - 0x04, 0x19, 0x7c, 0x12, 0x1d, 0x4e, 0xcc, 0x37, 0x84, 0x88, 0xcb, 0xfc, 0x9a, 0x5a, 0x47, 0x7f, 0x01, 0xdb, 0xc3, - 0xbb, 0x38, 0xa1, 0x96, 0x4a, 0x1d, 0xa1, 0x9d, 0x84, 0x6a, 0xbb, 0xa9, 0xec, 0x0e, 0xd0, 0xfd, 0x49, 0x34, 0x2d, - 0x58, 0xa0, 0xbe, 0x48, 0xcd, 0x84, 0x0a, 0x6e, 0xd9, 0x14, 0x90, 0x79, 0x31, 0xcf, 0xd0, 0x60, 0x58, 0xb6, 0x53, - 0x40, 0xf4, 0x39, 0x8d, 0xc6, 0xa0, 0x71, 0x7a, 0xe6, 0x96, 0x7c, 0x3c, 0x37, 0xf5, 0xda, 0x23, 0xd0, 0x6b, 0x98, - 0x93, 0xd7, 0x00, 0x4f, 0xed, 0x2c, 0x0d, 0x12, 0x36, 0xe2, 0x25, 0xc7, 0x4b, 0x5f, 0x73, 0x65, 0x48, 0xf8, 0xed, - 0x87, 0xa0, 0xeb, 0x2c, 0x1f, 0xff, 0xbd, 0x79, 0x62, 0xe8, 0x18, 0xa4, 0xa0, 0x9b, 0x28, 0x0b, 0x14, 0x33, 0xec, - 0x01, 0x5c, 0xf3, 0x79, 0x6e, 0x4c, 0x34, 0x60, 0x68, 0x64, 0x95, 0x1c, 0x64, 0xf2, 0xd8, 0xe3, 0xb9, 0xd9, 0x2e, - 0x75, 0xe7, 0x4b, 0x18, 0x2c, 0xeb, 0xfa, 0x5d, 0xb7, 0x2c, 0xc8, 0x64, 0x5d, 0x6e, 0xac, 0x0c, 0xa6, 0xfa, 0xd3, - 0x12, 0xf9, 0x0c, 0xd3, 0xae, 0x14, 0xc1, 0xd2, 0xb9, 0xe8, 0x71, 0x17, 0x62, 0xd6, 0x8c, 0x4e, 0xcf, 0xec, 0xe1, - 0x96, 0x71, 0x3a, 0x9d, 0xf1, 0x23, 0x0a, 0xd4, 0xe6, 0x78, 0x9d, 0xa0, 0x3f, 0x17, 0x73, 0x83, 0x17, 0x3c, 0x70, - 0x10, 0x00, 0xab, 0x61, 0x3d, 0x01, 0x6a, 0xba, 0xca, 0xf0, 0xf0, 0x1f, 0x23, 0x71, 0x4b, 0x9f, 0x5a, 0xaf, 0xa0, - 0xd2, 0x09, 0x58, 0xdd, 0x1d, 0xce, 0x9d, 0xa3, 0x37, 0x8e, 0xdb, 0xf7, 0x5e, 0x19, 0x2f, 0x2f, 0xb1, 0xd5, 0x1e, - 0xb0, 0x3d, 0xa4, 0xf7, 0xca, 0x26, 0x26, 0x93, 0x53, 0xb3, 0x57, 0x21, 0x36, 0x7c, 0xeb, 0xd8, 0xac, 0x98, 0x36, - 0x84, 0x48, 0x6a, 0x10, 0x33, 0xda, 0xd8, 0x55, 0x05, 0x56, 0xbf, 0xe2, 0x73, 0x92, 0x36, 0x5c, 0xbf, 0x29, 0xe4, - 0x88, 0xf7, 0xcd, 0x5b, 0x2d, 0xb5, 0x80, 0x3a, 0xd4, 0xb9, 0x86, 0xe4, 0x83, 0x47, 0xf9, 0xd6, 0x1b, 0x25, 0x37, - 0x4e, 0xf6, 0xeb, 0x92, 0x0c, 0xf6, 0x59, 0xa9, 0xdf, 0xa8, 0x06, 0x5a, 0x18, 0xe7, 0x87, 0x8d, 0x24, 0xf7, 0xdd, - 0x53, 0xb2, 0x12, 0x55, 0x1c, 0x9c, 0xae, 0x2c, 0xaa, 0x13, 0x0d, 0xa1, 0x50, 0x63, 0x3c, 0x77, 0xad, 0x25, 0xdd, - 0x76, 0x2a, 0x59, 0x24, 0x6c, 0x4c, 0x8b, 0xf0, 0x08, 0x6d, 0x30, 0xfa, 0x6c, 0xeb, 0xcf, 0x03, 0x50, 0x7f, 0x9f, - 0x42, 0x7b, 0x73, 0xee, 0xb8, 0xab, 0xef, 0xcd, 0x29, 0xcf, 0x50, 0x49, 0x61, 0x23, 0x63, 0xb1, 0x26, 0x5c, 0xd1, - 0x41, 0xb5, 0xbb, 0x28, 0x3e, 0xf7, 0x76, 0xc4, 0x44, 0xb0, 0xdb, 0x8f, 0xe5, 0x8b, 0x9e, 0xb8, 0x29, 0x12, 0x91, - 0xbc, 0xa2, 0xdc, 0x22, 0x36, 0x09, 0xed, 0x5b, 0x79, 0xc7, 0xb6, 0x84, 0x94, 0x42, 0x40, 0x95, 0xc0, 0x02, 0xe0, - 0x75, 0x19, 0x93, 0xb0, 0xc7, 0x92, 0x0c, 0x36, 0xce, 0x05, 0x8a, 0x00, 0x03, 0x47, 0x3c, 0x8a, 0x13, 0xd1, 0x45, - 0x06, 0xf6, 0x94, 0x03, 0xa8, 0x31, 0xc2, 0x23, 0xf5, 0x3a, 0x2e, 0x75, 0x12, 0x12, 0x66, 0x7b, 0x3b, 0x15, 0xdc, - 0x84, 0x19, 0xed, 0x32, 0xf3, 0x00, 0xab, 0xc2, 0x50, 0xd4, 0x01, 0x71, 0xe9, 0xda, 0x0c, 0x02, 0x58, 0xa8, 0x60, - 0x87, 0x97, 0xaa, 0x2b, 0x2c, 0x02, 0x96, 0x1c, 0x13, 0x85, 0xc1, 0xc8, 0x63, 0x5c, 0x13, 0x36, 0x17, 0xd9, 0x8f, - 0x0a, 0xda, 0x74, 0x09, 0xda, 0xb4, 0x0e, 0xed, 0x09, 0x12, 0xbd, 0xb7, 0x39, 0x8f, 0xcb, 0x10, 0xbe, 0xa5, 0x83, - 0x6c, 0xc8, 0x3e, 0x7e, 0x78, 0x85, 0x77, 0x00, 0xa1, 0x3d, 0x38, 0x0b, 0x99, 0x5b, 0x9e, 0xc8, 0xc5, 0x31, 0x75, - 0x82, 0xd8, 0xdb, 0x16, 0xcd, 0x45, 0x74, 0x05, 0x8a, 0xf6, 0x04, 0xe4, 0x6c, 0x48, 0x05, 0x61, 0x98, 0x53, 0x2f, - 0x0e, 0x4b, 0x2a, 0x5a, 0x0b, 0x99, 0x2e, 0x1a, 0x21, 0x11, 0x68, 0x67, 0x56, 0x34, 0xc0, 0x9c, 0x59, 0x93, 0x0e, - 0xc3, 0xf8, 0x5c, 0x73, 0x1b, 0x5d, 0x20, 0xea, 0xee, 0x01, 0x43, 0xb3, 0x04, 0xc6, 0xcc, 0xaf, 0xaf, 0x9b, 0x30, - 0x94, 0x78, 0xb4, 0xf6, 0x48, 0x36, 0x88, 0x77, 0x61, 0xc2, 0xcc, 0x2d, 0x4c, 0x4f, 0xc2, 0xab, 0x7a, 0x3d, 0x95, - 0x6f, 0x13, 0xc8, 0x01, 0x00, 0x46, 0x3a, 0xea, 0x27, 0x3e, 0xd0, 0xe6, 0x0d, 0x94, 0xc6, 0xc3, 0xe5, 0x32, 0xb0, - 0x4a, 0xa7, 0x58, 0x9a, 0x5d, 0x5f, 0xb7, 0xe0, 0x71, 0x12, 0xa7, 0xf8, 0x04, 0x33, 0xd3, 0x0d, 0x38, 0x78, 0x04, - 0xd3, 0x1c, 0xd8, 0x16, 0x6a, 0xa2, 0x4b, 0xac, 0x49, 0x55, 0x4d, 0x74, 0x09, 0xf2, 0x48, 0x54, 0x69, 0xf2, 0x14, - 0xc8, 0x70, 0xff, 0x1f, 0x16, 0x34, 0x93, 0x8b, 0x67, 0x69, 0xd2, 0x01, 0x98, 0x20, 0x2d, 0x35, 0xf1, 0xf6, 0x76, - 0x80, 0xcc, 0xb0, 0x18, 0xd2, 0xfa, 0x91, 0x3b, 0xae, 0x7a, 0x8f, 0x91, 0x90, 0x64, 0x6e, 0x2d, 0x0d, 0x81, 0x8a, - 0xd0, 0x1a, 0x04, 0xdf, 0x62, 0x78, 0x4c, 0x9b, 0x03, 0xf4, 0xbc, 0xd4, 0xfe, 0x0b, 0xb2, 0xa6, 0xea, 0xe0, 0xd9, - 0x7f, 0xfd, 0xc7, 0xbf, 0xb3, 0x3d, 0xb1, 0xb9, 0xb2, 0xd1, 0x08, 0x4c, 0x65, 0xeb, 0x0e, 0x7d, 0xfe, 0xd7, 0xdf, - 0xff, 0xdf, 0xff, 0xf3, 0x5f, 0x75, 0xb7, 0x14, 0x7a, 0x9d, 0xc8, 0x83, 0x3f, 0x25, 0x1d, 0x0c, 0x30, 0x15, 0x1a, - 0xa3, 0x28, 0x5d, 0x87, 0xc3, 0x91, 0x89, 0x43, 0x31, 0x65, 0x6c, 0xe8, 0xd9, 0x96, 0xed, 0x2d, 0x95, 0x1e, 0x27, - 0xec, 0x9c, 0xc9, 0xb7, 0x9e, 0xad, 0x9a, 0x6a, 0x45, 0x8f, 0x01, 0x28, 0x34, 0x2e, 0xcf, 0x3f, 0x25, 0x6f, 0x9b, - 0xa8, 0x48, 0xa9, 0x52, 0xeb, 0x87, 0xb4, 0xab, 0x8b, 0x0b, 0xcf, 0x36, 0xa6, 0x5f, 0x0b, 0x57, 0x6f, 0x4d, 0x79, - 0xd0, 0xf4, 0x9a, 0xeb, 0x20, 0xf3, 0xc0, 0x8f, 0xb4, 0xed, 0xbe, 0xa2, 0x11, 0x85, 0x7b, 0xcc, 0x0b, 0xec, 0xeb, - 0x68, 0x75, 0x2b, 0xf6, 0xa7, 0x39, 0x0e, 0x95, 0xb2, 0xa2, 0xb8, 0x05, 0x79, 0x58, 0x3e, 0xcf, 0xae, 0x5a, 0xdb, - 0x6b, 0x46, 0x01, 0x14, 0xda, 0x0f, 0x1f, 0x0a, 0x70, 0x3d, 0x47, 0xbb, 0x90, 0x66, 0x63, 0x36, 0x1a, 0x81, 0x10, - 0x29, 0xdc, 0x2a, 0x1f, 0x74, 0x14, 0x27, 0x1c, 0xcf, 0xb3, 0xc3, 0xae, 0xfd, 0x16, 0x36, 0x06, 0x5e, 0x0f, 0x75, - 0xa5, 0x5f, 0xaf, 0x32, 0xfd, 0x94, 0xd0, 0x5d, 0x0d, 0x97, 0x18, 0xb2, 0x0e, 0x93, 0x9c, 0xe6, 0xfa, 0x5a, 0xf9, - 0xcb, 0xb5, 0xf2, 0x3a, 0x39, 0x33, 0x72, 0x88, 0x57, 0xef, 0x9b, 0xbb, 0xec, 0x8e, 0x7f, 0xfd, 0xa7, 0xbf, 0xff, - 0x6f, 0x00, 0x06, 0x8e, 0x73, 0xb7, 0xad, 0x01, 0x1d, 0xfe, 0x27, 0x74, 0x98, 0xa5, 0x77, 0xef, 0xf2, 0xd7, 0xff, - 0xf2, 0xdf, 0xa1, 0x07, 0x5d, 0x60, 0x86, 0x7d, 0xa4, 0x40, 0x1f, 0x60, 0xd8, 0xe8, 0x77, 0xc1, 0x5e, 0x1b, 0xf7, - 0x2e, 0x70, 0xfc, 0x03, 0xa2, 0x5a, 0xf0, 0x6c, 0x7a, 0x57, 0xb8, 0x11, 0xd3, 0x41, 0x92, 0x15, 0xcc, 0x04, 0x5c, - 0x58, 0x0a, 0xbf, 0x0f, 0x72, 0x82, 0x64, 0x0a, 0x12, 0xb4, 0xb0, 0xcc, 0xa1, 0x25, 0xaf, 0xdc, 0x28, 0x08, 0x57, - 0x32, 0x54, 0xc1, 0x38, 0x91, 0x82, 0xac, 0xb9, 0x1a, 0xd3, 0x88, 0xb2, 0x25, 0x5e, 0x22, 0xe9, 0xae, 0x25, 0x97, - 0xd0, 0x58, 0xb7, 0xcc, 0xbb, 0x62, 0x7f, 0x89, 0x69, 0xc5, 0x99, 0xd7, 0xf2, 0xf0, 0xb5, 0x12, 0x50, 0x5d, 0xc7, - 0x2b, 0x4a, 0xa3, 0xcb, 0x15, 0xa5, 0xa8, 0x04, 0x35, 0x6c, 0x60, 0xed, 0x4d, 0xc4, 0x4b, 0x2f, 0xf4, 0xeb, 0x2e, - 0x6a, 0xd0, 0x91, 0x2a, 0xc3, 0x53, 0xfc, 0xfa, 0x2b, 0x00, 0xe4, 0x50, 0x42, 0xad, 0x1d, 0xe3, 0xbd, 0x1a, 0xbc, - 0x45, 0x3d, 0xcb, 0x19, 0xec, 0x99, 0x0b, 0xf3, 0x68, 0xfe, 0xe6, 0xc6, 0x63, 0x10, 0x0f, 0x3d, 0xb0, 0x27, 0xf5, - 0xaa, 0xde, 0x38, 0x6e, 0xf9, 0x2f, 0xff, 0xec, 0xfb, 0xff, 0xf2, 0xcf, 0xb7, 0x36, 0xc5, 0x51, 0xc1, 0x65, 0xe7, - 0xd5, 0xb0, 0xeb, 0xa9, 0xbb, 0x7a, 0xa6, 0x3a, 0xb9, 0x57, 0xb7, 0x59, 0xa2, 0x3f, 0xd6, 0x2f, 0x91, 0x7f, 0xa9, - 0x50, 0x50, 0xdf, 0xfa, 0x2d, 0x80, 0x21, 0x5e, 0xb7, 0x42, 0x86, 0x8d, 0x7e, 0x17, 0x68, 0x27, 0x6e, 0x70, 0xa7, - 0x15, 0xf9, 0xed, 0x14, 0xbe, 0x0d, 0x87, 0xdf, 0x09, 0xbe, 0x48, 0x07, 0x06, 0xd0, 0x4e, 0xd4, 0x8d, 0xa9, 0x5a, - 0x57, 0xbc, 0x74, 0xd9, 0x5b, 0x2a, 0x91, 0x6a, 0x25, 0x68, 0xba, 0xdd, 0xe6, 0xd6, 0x96, 0x83, 0xdd, 0xdf, 0xe0, - 0x9b, 0x21, 0xf6, 0x4e, 0x73, 0x15, 0x03, 0xb9, 0x41, 0x34, 0xe0, 0x10, 0x75, 0xac, 0x68, 0xd0, 0x25, 0xb9, 0x80, - 0xa5, 0x98, 0x61, 0x8a, 0x60, 0x7a, 0x60, 0x0e, 0x0b, 0x7b, 0xed, 0x99, 0x70, 0x6c, 0x82, 0x45, 0xd6, 0x96, 0x0e, - 0x4f, 0x8d, 0xe8, 0x9e, 0x75, 0x48, 0xf4, 0xa2, 0xc6, 0xac, 0xb2, 0x97, 0xc9, 0x4b, 0x44, 0x03, 0xf1, 0x44, 0xbc, - 0x2b, 0xe3, 0xeb, 0x75, 0xf1, 0xf6, 0xef, 0x6f, 0x8f, 0xb7, 0xc7, 0x77, 0x8c, 0xb7, 0x7f, 0xff, 0x07, 0xc7, 0xdb, - 0xbf, 0x36, 0xe3, 0xed, 0xb8, 0x88, 0x3f, 0xdf, 0x29, 0x26, 0xae, 0x22, 0x95, 0xd9, 0x45, 0x11, 0xb6, 0xa4, 0xa5, - 0x04, 0x8e, 0x34, 0x06, 0xc4, 0xff, 0xed, 0xe3, 0xdb, 0x30, 0xd1, 0x42, 0x74, 0x9b, 0xc2, 0xd9, 0x92, 0x07, 0x99, - 0x0a, 0x26, 0x37, 0x75, 0xee, 0x77, 0xe3, 0x81, 0xba, 0xec, 0x0a, 0x2e, 0x8c, 0xab, 0x0f, 0x04, 0xda, 0x2a, 0xdc, - 0x1c, 0xd0, 0xdb, 0xaa, 0x75, 0xc7, 0xf6, 0xb6, 0x4a, 0x3a, 0x36, 0x47, 0xe8, 0xa8, 0xb3, 0x64, 0x71, 0x53, 0x72, - 0x6e, 0xff, 0xa7, 0xa3, 0x56, 0x67, 0xb7, 0x35, 0x81, 0xde, 0xc0, 0x87, 0xf0, 0xd4, 0xec, 0xec, 0xee, 0xe2, 0xd3, - 0x85, 0x7a, 0x6a, 0xe3, 0x53, 0xac, 0x9e, 0x1e, 0xe2, 0xd3, 0x40, 0x3d, 0x3d, 0xc2, 0xa7, 0xa1, 0x7a, 0x7a, 0x8c, - 0x4f, 0xe7, 0x76, 0x79, 0xc4, 0x34, 0x70, 0x8f, 0xdd, 0xbe, 0x27, 0x4c, 0x51, 0x55, 0xf6, 0xd8, 0x6b, 0x61, 0x40, - 0x3b, 0x3a, 0x0b, 0x62, 0x4f, 0x38, 0xd4, 0x41, 0xe1, 0x5d, 0x8c, 0x59, 0x1a, 0x50, 0x4e, 0xf4, 0x73, 0x7c, 0x5b, - 0x10, 0xd8, 0xc0, 0x87, 0xf1, 0x84, 0xa9, 0xd7, 0xa6, 0x2b, 0xac, 0x41, 0x25, 0x1f, 0x35, 0xfb, 0x65, 0x47, 0xaf, - 0x93, 0x88, 0x84, 0xab, 0xf4, 0x4e, 0x5a, 0xb9, 0xaa, 0x4e, 0x4c, 0xd7, 0xd0, 0x2b, 0xbc, 0x26, 0xa8, 0x6a, 0xf8, - 0x95, 0x23, 0x90, 0xcd, 0x8d, 0x4b, 0x70, 0x2c, 0x57, 0x06, 0x5a, 0x11, 0x22, 0x1d, 0x68, 0x25, 0x9c, 0xf4, 0xd3, - 0x61, 0x74, 0xa6, 0xbf, 0xbf, 0x01, 0xdb, 0x21, 0x3a, 0x93, 0x2d, 0xd7, 0x07, 0x56, 0x09, 0x44, 0x33, 0xa8, 0xaa, - 0x80, 0x40, 0xc7, 0x13, 0x97, 0x06, 0xc3, 0x04, 0x32, 0x56, 0x8a, 0xd4, 0xa9, 0x87, 0x59, 0x69, 0xfa, 0x7a, 0x11, - 0x50, 0xb4, 0x2a, 0xd8, 0x03, 0x13, 0x86, 0x4a, 0x05, 0x85, 0xa1, 0x02, 0x0b, 0x44, 0xf5, 0x9a, 0x70, 0xaa, 0x72, - 0xfd, 0xd6, 0x07, 0x55, 0x2d, 0x15, 0x4f, 0x35, 0xcf, 0xa0, 0xf5, 0x01, 0xf4, 0x72, 0x14, 0xef, 0x5e, 0x6b, 0x80, - 0xff, 0xc9, 0x18, 0xe1, 0xbd, 0xd1, 0x68, 0x74, 0x63, 0x7c, 0xf5, 0xde, 0x70, 0xc4, 0xda, 0xec, 0x61, 0x07, 0xcf, - 0x27, 0x1b, 0x32, 0x6a, 0xd7, 0x2a, 0x89, 0x76, 0xf3, 0xbb, 0x35, 0xc6, 0x00, 0x1f, 0x1f, 0xcf, 0xef, 0x1e, 0x6b, - 0x2d, 0x81, 0x2a, 0xf3, 0x09, 0x48, 0xc5, 0x38, 0x0d, 0x9a, 0xa5, 0x7f, 0x2e, 0x83, 0x93, 0xf7, 0x9e, 0x3c, 0x79, - 0x52, 0xfa, 0x43, 0xf5, 0xd4, 0x1c, 0x0e, 0x4b, 0x7f, 0x30, 0xd7, 0x68, 0x34, 0x9b, 0xa3, 0x51, 0xe9, 0xc7, 0xaa, - 0x60, 0xb7, 0x3d, 0x18, 0xee, 0xb6, 0x4b, 0xff, 0xc2, 0x68, 0x51, 0xfa, 0x4c, 0x3e, 0xe5, 0x6c, 0x58, 0x3b, 0xe4, - 0x7c, 0x0c, 0xde, 0xb6, 0x2f, 0x18, 0x6d, 0x8e, 0x86, 0xb6, 0xf8, 0x1a, 0x44, 0x33, 0x9e, 0xa1, 0x00, 0xee, 0x00, - 0x9f, 0x1f, 0x6d, 0xca, 0x6b, 0xcc, 0xe2, 0xad, 0xe4, 0x25, 0x6c, 0xa1, 0x9f, 0xcd, 0x60, 0x23, 0x32, 0x33, 0x05, - 0x19, 0x63, 0x15, 0x8b, 0xac, 0x55, 0x23, 0x67, 0x51, 0xf5, 0xcf, 0x61, 0x5c, 0xc5, 0x20, 0x51, 0xda, 0x60, 0x4b, - 0x91, 0x8c, 0xf3, 0xdd, 0x3a, 0x19, 0xff, 0xc5, 0xed, 0x32, 0xfe, 0xea, 0x6e, 0x22, 0xfe, 0x8b, 0x3f, 0x58, 0xc4, - 0x7f, 0x67, 0x8a, 0x78, 0x21, 0xc4, 0xf6, 0x79, 0x68, 0x0f, 0xc6, 0x6c, 0xf0, 0xe9, 0x34, 0xbb, 0x6c, 0xe0, 0x96, - 0xc8, 0x6d, 0x92, 0x9e, 0x93, 0xdf, 0x7a, 0x20, 0xaa, 0x06, 0x33, 0x5e, 0x71, 0x4e, 0x4a, 0xf2, 0x5d, 0x1a, 0xda, - 0xef, 0x94, 0xfd, 0x2e, 0x4a, 0x46, 0x23, 0x28, 0x1a, 0x8d, 0x6c, 0x75, 0x79, 0x03, 0xc4, 0x16, 0xb5, 0x7a, 0x5b, - 0x2b, 0xa1, 0x56, 0x9f, 0x7f, 0x6e, 0x96, 0x99, 0x05, 0x32, 0x64, 0x69, 0x86, 0x27, 0x65, 0xcd, 0x30, 0x2e, 0x70, - 0xab, 0xe1, 0x9b, 0xd7, 0x97, 0x5e, 0x69, 0x25, 0x02, 0xab, 0xcb, 0x00, 0x57, 0xf1, 0x55, 0xe3, 0xed, 0xa9, 0x55, - 0x84, 0x15, 0x16, 0x54, 0x66, 0xd6, 0x3d, 0xbd, 0x7a, 0x35, 0x74, 0xf6, 0xb9, 0x5b, 0xc6, 0xc5, 0xbb, 0x74, 0x21, - 0x63, 0x59, 0xc0, 0x18, 0x86, 0x26, 0x5a, 0x25, 0xcf, 0xce, 0xce, 0x92, 0xe5, 0x1c, 0x58, 0xd1, 0xbd, 0x57, 0xc3, - 0x37, 0x30, 0x3b, 0x4a, 0x5d, 0x46, 0x3f, 0x99, 0x21, 0x52, 0xfb, 0x28, 0x27, 0x5b, 0x1d, 0xed, 0xce, 0xa5, 0xfc, - 0x97, 0x49, 0x5f, 0x8c, 0x0e, 0x51, 0x69, 0xe0, 0x61, 0x59, 0xca, 0xcc, 0x5a, 0x20, 0xc4, 0x14, 0xdf, 0xff, 0x26, - 0x7a, 0xc6, 0xb7, 0x89, 0xf0, 0xe2, 0xc2, 0x88, 0x0b, 0xd6, 0x96, 0xab, 0x54, 0x81, 0x41, 0x11, 0xdd, 0xdb, 0xc7, - 0x10, 0xa5, 0x88, 0x11, 0x2a, 0x22, 0xda, 0x56, 0x8f, 0xbe, 0xca, 0x88, 0x65, 0x85, 0x21, 0x06, 0x33, 0xf5, 0x82, - 0xa8, 0x2a, 0x55, 0x50, 0x9a, 0x81, 0x6f, 0xaa, 0x11, 0xd4, 0xa2, 0x30, 0x1b, 0xc0, 0x9e, 0x0a, 0x31, 0x0a, 0xd3, - 0x90, 0x3c, 0xd8, 0x9c, 0x57, 0x2b, 0x0f, 0x5d, 0x25, 0xd8, 0x82, 0x79, 0x41, 0x06, 0x63, 0x87, 0xae, 0x55, 0x03, - 0x3d, 0x5d, 0x8a, 0xce, 0xdd, 0x7c, 0xee, 0x75, 0xe2, 0x17, 0x17, 0x1e, 0xfc, 0x59, 0x7f, 0x9a, 0x83, 0xd0, 0x39, - 0xfd, 0x14, 0xf3, 0x06, 0x8f, 0xa6, 0x0d, 0xb4, 0xee, 0x29, 0xc8, 0x23, 0xa5, 0x33, 0xe5, 0x6f, 0x88, 0x7b, 0x96, - 0x9d, 0x59, 0x81, 0xc7, 0x63, 0x64, 0xa3, 0x06, 0x69, 0x96, 0xb2, 0x4e, 0x3d, 0x4f, 0xc7, 0x3c, 0x6d, 0x51, 0xc4, - 0xea, 0xcf, 0x33, 0x3c, 0x4e, 0xe3, 0x57, 0x41, 0x53, 0x4a, 0xf5, 0xa6, 0x3a, 0x6a, 0x69, 0xae, 0x6c, 0x1f, 0x48, - 0xda, 0x6e, 0x93, 0xf2, 0xca, 0x97, 0x8f, 0x94, 0xd6, 0x1d, 0x09, 0xdd, 0x96, 0xb5, 0x82, 0xc1, 0x21, 0xf5, 0x67, - 0xa4, 0xfb, 0x2c, 0x16, 0x53, 0xd6, 0xca, 0x5d, 0x20, 0x0b, 0xa2, 0x11, 0xbe, 0x96, 0xf4, 0x2e, 0x2d, 0x4f, 0x29, - 0x65, 0x7c, 0x8e, 0x5a, 0x26, 0x68, 0x3d, 0x99, 0x5e, 0xde, 0x7d, 0xf8, 0x9b, 0xd1, 0x2f, 0x25, 0x8d, 0xd4, 0xcd, - 0x7f, 0xdb, 0xee, 0xe0, 0x3e, 0x48, 0xa2, 0xab, 0x20, 0x4e, 0x49, 0xe5, 0x9d, 0x62, 0x94, 0xa7, 0x33, 0xcd, 0x64, - 0xfa, 0x55, 0xce, 0x12, 0xfa, 0xed, 0x1f, 0xb9, 0x14, 0xbb, 0x8f, 0xa6, 0x97, 0x6a, 0x35, 0x5a, 0x0b, 0x69, 0x55, - 0x7f, 0x68, 0xf6, 0xd4, 0xfa, 0x74, 0xad, 0x7a, 0x06, 0xd0, 0x43, 0x80, 0x41, 0xe8, 0xd9, 0x46, 0x2e, 0xa0, 0x6a, - 0x42, 0x89, 0x91, 0x3f, 0x56, 0x0d, 0x64, 0xf9, 0xbb, 0x20, 0xb9, 0xa3, 0x82, 0x75, 0xf0, 0xfd, 0xb0, 0xf1, 0x20, - 0x4a, 0xa4, 0x2e, 0x9f, 0xc4, 0xc3, 0x61, 0xc2, 0x3a, 0x4a, 0x5d, 0x5b, 0xad, 0x47, 0x98, 0x7e, 0x65, 0x2e, 0x59, - 0x7d, 0x55, 0x0c, 0xe2, 0x69, 0x3a, 0x45, 0xa7, 0x60, 0x3e, 0xe0, 0x4b, 0x5e, 0x57, 0x92, 0x53, 0xe6, 0x25, 0x35, - 0x2b, 0xe2, 0xd1, 0xf7, 0x3a, 0x2e, 0x0f, 0xc1, 0x76, 0xa1, 0x05, 0x6f, 0x76, 0x78, 0x36, 0x0d, 0x1a, 0xbb, 0x75, - 0x44, 0xb0, 0x4a, 0xa3, 0xe0, 0xad, 0x40, 0xcb, 0x43, 0x65, 0x25, 0x04, 0xb4, 0xe5, 0xb7, 0x64, 0x19, 0x0d, 0x80, - 0x2f, 0x12, 0xd5, 0x45, 0x65, 0x1d, 0x99, 0x7f, 0x9b, 0xdd, 0xf2, 0xd9, 0xea, 0xdd, 0xf2, 0x99, 0xda, 0x2d, 0x37, - 0x73, 0xec, 0xbd, 0x51, 0x0b, 0xff, 0xeb, 0x54, 0x08, 0xc1, 0xaa, 0x00, 0x39, 0x2c, 0x34, 0xd3, 0x1a, 0x6d, 0xf8, - 0x87, 0x86, 0xc6, 0x18, 0x74, 0x13, 0xf3, 0xc9, 0xbc, 0xa6, 0x85, 0x85, 0xf8, 0xd7, 0xac, 0x55, 0xb5, 0x1e, 0x60, - 0x1d, 0xf6, 0x7a, 0xb8, 0x5c, 0xd7, 0xbe, 0x79, 0xd3, 0x82, 0xbc, 0xe2, 0x4e, 0xa0, 0x84, 0x31, 0x78, 0x0e, 0xd1, - 0xe9, 0x29, 0x94, 0x8e, 0xb2, 0xc1, 0xac, 0xf8, 0x5b, 0x09, 0xbf, 0x24, 0xe2, 0x8d, 0x5b, 0x7a, 0x61, 0x1c, 0xd5, - 0x55, 0xe4, 0xf2, 0xa9, 0x11, 0xe6, 0x7a, 0x9d, 0x82, 0x02, 0x18, 0x93, 0x39, 0x6d, 0xff, 0xc1, 0x8a, 0x4d, 0xf0, - 0xef, 0xb2, 0x36, 0x2b, 0x91, 0xf9, 0xbd, 0xc4, 0xb8, 0x91, 0x08, 0xbf, 0x8a, 0x06, 0xe6, 0x1a, 0x36, 0x9f, 0xac, - 0x06, 0xf7, 0x48, 0xcd, 0xd4, 0x57, 0x4a, 0x41, 0xea, 0x1d, 0x30, 0x4a, 0xa3, 0x59, 0xc2, 0x6f, 0x1e, 0x75, 0x1d, - 0x67, 0x2c, 0x8d, 0x7a, 0x83, 0x40, 0xaf, 0xda, 0xde, 0x51, 0x4a, 0xdf, 0xfb, 0xec, 0x01, 0xfe, 0x27, 0xd2, 0x05, - 0xae, 0x2a, 0x53, 0x5d, 0xb8, 0xaa, 0x68, 0xaa, 0x4f, 0x6a, 0xb6, 0xb8, 0xd0, 0xe0, 0x64, 0x8e, 0xdf, 0xb5, 0x35, - 0x1a, 0x95, 0x77, 0x6a, 0x2e, 0x8d, 0xac, 0x5f, 0xd5, 0xfa, 0xd7, 0x0d, 0x7e, 0xc7, 0xb6, 0x03, 0x61, 0xb8, 0xd6, - 0xdb, 0xca, 0xdf, 0x61, 0x5a, 0x6a, 0xac, 0x28, 0x4e, 0xed, 0x27, 0xe1, 0x95, 0xf6, 0x50, 0xc4, 0xb9, 0x12, 0x3a, - 0x29, 0x13, 0xe1, 0xa4, 0xfc, 0x85, 0x87, 0xf7, 0xf1, 0x85, 0x84, 0xd6, 0xe5, 0x24, 0x49, 0xc1, 0x48, 0x1a, 0x73, - 0x3e, 0x0d, 0x76, 0x76, 0x2e, 0x2e, 0x2e, 0xfc, 0x8b, 0x5d, 0x3f, 0xcb, 0xcf, 0x76, 0xda, 0xcd, 0x66, 0x13, 0xdf, - 0x23, 0x67, 0x5b, 0xe7, 0x31, 0xbb, 0x78, 0x0a, 0x76, 0xb0, 0xfd, 0xd8, 0x7a, 0x62, 0x3d, 0xde, 0xb5, 0x1e, 0x3e, - 0xb2, 0x2d, 0x12, 0xe7, 0x50, 0xb2, 0x6b, 0x5b, 0x42, 0x9c, 0x87, 0x36, 0x14, 0x77, 0xf7, 0xce, 0x94, 0x45, 0x86, - 0xf7, 0x74, 0x84, 0xbd, 0x03, 0xce, 0x41, 0xf6, 0x89, 0xd5, 0x37, 0xae, 0x28, 0x6b, 0x48, 0xa5, 0xa0, 0x1e, 0x71, - 0xf7, 0x0e, 0xa2, 0x69, 0x40, 0x4c, 0x61, 0x16, 0x62, 0x0c, 0x46, 0x94, 0xd2, 0x14, 0x68, 0x65, 0x9e, 0xc2, 0x37, - 0x4c, 0xec, 0xb4, 0xe0, 0xfb, 0x9b, 0xf6, 0x63, 0xd0, 0x58, 0xe7, 0x8d, 0x07, 0x83, 0x66, 0xa3, 0x65, 0xb5, 0x1a, - 0x6d, 0xff, 0xb1, 0xd5, 0x16, 0xff, 0x82, 0xc4, 0xdb, 0xb5, 0x5a, 0xf0, 0x6d, 0xd7, 0x82, 0xe7, 0xf3, 0x07, 0xe2, - 0x00, 0x3a, 0xb2, 0x77, 0xba, 0x7b, 0xf8, 0xb3, 0x6a, 0x80, 0xd4, 0x67, 0xb6, 0xf8, 0x21, 0x48, 0xfb, 0x9e, 0x59, - 0xda, 0x7a, 0xb2, 0xb2, 0xb8, 0xfd, 0x78, 0x65, 0xf1, 0xee, 0xa3, 0x95, 0xc5, 0x0f, 0x1e, 0xd6, 0x8b, 0x77, 0xce, - 0x44, 0x95, 0xde, 0xe5, 0xa1, 0x3d, 0x89, 0x60, 0xd9, 0x2f, 0x9d, 0x16, 0xc0, 0xd9, 0xb4, 0x1a, 0xf8, 0xf1, 0xb8, - 0xed, 0xea, 0x5e, 0xa7, 0xd8, 0x4b, 0x63, 0xf9, 0xf8, 0x09, 0x60, 0xf9, 0xb2, 0xfd, 0x68, 0x80, 0xed, 0x08, 0x51, - 0xf8, 0x3b, 0xdf, 0x7d, 0x32, 0x00, 0xf9, 0x6e, 0xe1, 0x1f, 0xfc, 0x37, 0x7e, 0xd8, 0x1e, 0x88, 0x87, 0x26, 0xd6, - 0x7f, 0xd3, 0x7a, 0x5c, 0x40, 0x53, 0xfc, 0xef, 0x17, 0x6d, 0x10, 0xa3, 0x39, 0x6e, 0x8e, 0xfb, 0x00, 0x68, 0xf4, - 0x64, 0xdc, 0xf6, 0x3f, 0x3b, 0x7f, 0xec, 0x3f, 0x19, 0xb7, 0x1e, 0x7f, 0x23, 0x9e, 0x12, 0xa0, 0xe0, 0x67, 0xf8, - 0xf7, 0xcd, 0x6e, 0x13, 0xbc, 0x4b, 0xff, 0xc9, 0xf9, 0xae, 0xbf, 0x9b, 0x34, 0x1e, 0xf9, 0x4f, 0xf0, 0xaf, 0x1a, - 0x6e, 0x9c, 0x4d, 0x98, 0x6d, 0xe1, 0x7a, 0x2f, 0x78, 0x5b, 0xe6, 0x1c, 0xed, 0x07, 0xd6, 0xc3, 0x07, 0x2f, 0x9f, - 0xc0, 0x1a, 0x8d, 0x5b, 0x6d, 0xf8, 0x77, 0xdd, 0xd7, 0x6f, 0x90, 0xf0, 0x72, 0xe0, 0x88, 0x61, 0x86, 0xbd, 0x22, - 0x1c, 0xbd, 0xd3, 0xf0, 0xbe, 0x07, 0x0e, 0xd4, 0x6a, 0xef, 0x9a, 0xb1, 0xdb, 0x23, 0xa8, 0xec, 0x6e, 0xee, 0x35, - 0x63, 0x7f, 0xac, 0x7b, 0xcd, 0xd9, 0x42, 0x04, 0xf5, 0x92, 0x2f, 0x79, 0xd1, 0x8b, 0xae, 0xd7, 0x07, 0xee, 0x1c, - 0xfd, 0x85, 0xf7, 0xf1, 0x36, 0x09, 0xb4, 0x8e, 0x99, 0x19, 0x6c, 0xc8, 0x70, 0x23, 0xe3, 0x8f, 0x2b, 0xd2, 0xdd, - 0x9f, 0x75, 0x04, 0xc9, 0x6f, 0x27, 0xc8, 0x37, 0x77, 0xa3, 0x47, 0xfe, 0x07, 0xd3, 0xa3, 0x30, 0xe9, 0x51, 0x0b, - 0xe7, 0x92, 0x3b, 0x4b, 0xee, 0xe8, 0x01, 0x3d, 0x3b, 0x98, 0x84, 0xbd, 0x6d, 0xef, 0x30, 0x2c, 0x2a, 0x6c, 0x71, - 0x88, 0xf0, 0xf4, 0xd7, 0xc4, 0x9f, 0xc5, 0x8d, 0x8b, 0xd0, 0x96, 0xbe, 0xff, 0x14, 0xdf, 0xdb, 0xad, 0x1e, 0xce, - 0xc5, 0xad, 0xbe, 0x90, 0xae, 0xe4, 0x3e, 0xd4, 0x71, 0x03, 0xbc, 0x04, 0x13, 0xce, 0x33, 0x1e, 0xe1, 0x0f, 0xc3, - 0x01, 0xb9, 0xe9, 0x27, 0xe4, 0x62, 0x9e, 0x30, 0x3c, 0x24, 0x1f, 0x88, 0x77, 0x28, 0xc3, 0x57, 0x79, 0xdd, 0x16, - 0x6f, 0x71, 0x7c, 0x8d, 0x37, 0x50, 0x54, 0x60, 0x7a, 0x82, 0x2e, 0xf5, 0x1b, 0x36, 0x8c, 0x23, 0xc7, 0x76, 0xa6, - 0xb0, 0x91, 0x61, 0x96, 0x46, 0xed, 0xfa, 0x07, 0xdd, 0xfc, 0x70, 0x6d, 0xf5, 0xeb, 0x64, 0x39, 0xbe, 0xed, 0x31, - 0x3c, 0x92, 0x41, 0x2d, 0x5b, 0x9a, 0xf9, 0x30, 0xbe, 0x2a, 0xc9, 0x51, 0xa2, 0x57, 0xa6, 0x81, 0x2d, 0x6c, 0x83, - 0x96, 0xdf, 0x06, 0x5f, 0x81, 0x8a, 0xf1, 0xed, 0x79, 0xdf, 0x39, 0x8d, 0x5d, 0xb0, 0x5d, 0x8c, 0x6e, 0x7a, 0xa0, - 0xbe, 0xfe, 0xb1, 0x2b, 0xfd, 0x83, 0x8c, 0xf5, 0x3b, 0x33, 0xb6, 0xe0, 0x88, 0x7b, 0x02, 0x77, 0x5b, 0xbc, 0xa5, - 0x84, 0xa8, 0x47, 0x77, 0x46, 0xa1, 0xcc, 0x31, 0x7f, 0x98, 0x4f, 0xbc, 0x9d, 0x4f, 0xfc, 0x06, 0x67, 0x59, 0x35, - 0xe1, 0xee, 0x9c, 0x02, 0xef, 0x98, 0x64, 0x8c, 0x57, 0x75, 0x31, 0x0e, 0x1b, 0x1a, 0x34, 0xc5, 0x67, 0xb7, 0x46, - 0x64, 0xee, 0x69, 0x80, 0x88, 0xc0, 0xa1, 0xfc, 0xac, 0x8a, 0xd5, 0x17, 0x19, 0x5d, 0x01, 0xb7, 0x1d, 0x7f, 0xf9, - 0x88, 0x3e, 0x96, 0x62, 0x37, 0xe2, 0xec, 0x60, 0xa1, 0xb4, 0x1a, 0xaa, 0x8a, 0xd1, 0x14, 0x4f, 0xaf, 0x0e, 0xe5, - 0x6b, 0x3f, 0x6c, 0x0c, 0x81, 0x52, 0xe8, 0xbb, 0x7a, 0xe5, 0xe0, 0x36, 0xa8, 0x46, 0xfa, 0x21, 0x60, 0xca, 0x60, - 0x42, 0xed, 0x87, 0xb7, 0x6e, 0x2c, 0xe9, 0xf3, 0x84, 0xb6, 0xd0, 0x7d, 0x43, 0x76, 0x1e, 0x0f, 0xa4, 0x0a, 0xf3, - 0x2c, 0x79, 0x5b, 0xb0, 0x41, 0x4b, 0x13, 0xb6, 0x3c, 0xe1, 0xf5, 0xc3, 0x03, 0xea, 0xe3, 0x30, 0xcd, 0xec, 0xee, - 0xfd, 0xce, 0x3a, 0xe2, 0xe3, 0xaf, 0x12, 0x1f, 0x81, 0x97, 0xf9, 0xb7, 0xe1, 0x7d, 0xfc, 0x5d, 0xe2, 0xfb, 0x7d, - 0xdb, 0xf5, 0x49, 0x01, 0xdc, 0xaf, 0x7e, 0x9c, 0x18, 0xa5, 0xdf, 0x36, 0xe8, 0x6a, 0xef, 0xae, 0x4a, 0x5b, 0x2a, - 0xe8, 0xf6, 0xc3, 0x4a, 0x41, 0xc3, 0x77, 0x43, 0x22, 0x83, 0xb2, 0x68, 0xfb, 0x0f, 0x0d, 0xb1, 0x7f, 0xde, 0xc0, - 0xcf, 0x9a, 0xe0, 0x7f, 0x00, 0x0d, 0x94, 0xe4, 0x7f, 0x0d, 0xcd, 0x77, 0x85, 0x92, 0x81, 0x7e, 0xdf, 0x93, 0x58, - 0x96, 0x22, 0xb9, 0xb6, 0x0d, 0x56, 0x9c, 0xc6, 0x88, 0x6c, 0x2c, 0xdb, 0x73, 0xf4, 0x2f, 0x1e, 0xc9, 0x5d, 0x29, - 0xe3, 0x40, 0xcf, 0xa1, 0xaf, 0xa3, 0xdf, 0xe4, 0xbf, 0xaa, 0xce, 0xab, 0x49, 0x89, 0x15, 0x53, 0xe0, 0xbe, 0x5e, - 0x38, 0xf1, 0xe9, 0x88, 0x2b, 0x0c, 0xfa, 0x55, 0x40, 0xeb, 0x19, 0x5a, 0xde, 0x75, 0x70, 0x0d, 0x11, 0xc1, 0xe8, - 0x6d, 0xc3, 0x34, 0xc9, 0xab, 0x61, 0xb9, 0x38, 0x3f, 0xa6, 0x83, 0xe5, 0x99, 0x71, 0xa7, 0x50, 0x46, 0xef, 0x30, - 0x59, 0x74, 0x18, 0xe7, 0xf4, 0x62, 0x04, 0x05, 0x7a, 0x2d, 0x02, 0x58, 0x51, 0x89, 0xa4, 0x04, 0x2b, 0x7a, 0x36, - 0x16, 0xd9, 0x81, 0x4d, 0xe1, 0x23, 0xdb, 0x7c, 0xdd, 0xbe, 0x79, 0x73, 0x9d, 0x38, 0x99, 0x12, 0xbb, 0x71, 0xaf, - 0x22, 0x7d, 0x6c, 0x90, 0xb6, 0x6b, 0x77, 0x09, 0xd9, 0x60, 0x88, 0x6b, 0xf5, 0xfb, 0x72, 0xa6, 0x00, 0xb2, 0x4d, - 0x42, 0xeb, 0x71, 0x89, 0x84, 0xae, 0xa4, 0xd3, 0x29, 0x8b, 0xb8, 0x1f, 0xa5, 0x22, 0x0b, 0xc1, 0x10, 0x53, 0x5e, - 0x8b, 0xed, 0xba, 0x25, 0xc8, 0x46, 0x23, 0x6f, 0x42, 0xee, 0x6e, 0x28, 0x54, 0x17, 0x3d, 0x18, 0xaf, 0xe5, 0xb3, - 0x8e, 0xdb, 0xdd, 0x77, 0x87, 0xfb, 0x96, 0xd8, 0x94, 0x7b, 0x3b, 0xf0, 0xb8, 0x47, 0xfe, 0xb8, 0x48, 0xde, 0x0f, - 0x45, 0xf2, 0xbe, 0x25, 0x6f, 0x71, 0x50, 0x86, 0xe3, 0x8e, 0x40, 0xdb, 0xb6, 0x58, 0x3a, 0x10, 0x81, 0xc4, 0x09, - 0xf8, 0x2c, 0x31, 0xbe, 0xa2, 0x71, 0x07, 0xbb, 0x36, 0x70, 0xc1, 0x80, 0x9b, 0x45, 0xd4, 0x51, 0xd9, 0x35, 0x3c, - 0x55, 0x61, 0x47, 0xb0, 0x46, 0x98, 0xca, 0x40, 0x94, 0x43, 0xe9, 0xe4, 0xc5, 0xe5, 0xd6, 0xc5, 0xec, 0x74, 0x02, - 0x72, 0x52, 0xe5, 0x10, 0x7e, 0x94, 0x1d, 0xf6, 0x68, 0xaa, 0xee, 0x49, 0x29, 0xe3, 0xa2, 0xea, 0xf5, 0xf9, 0x0b, - 0x3f, 0x35, 0x2c, 0xb0, 0x97, 0x7a, 0x01, 0xb3, 0xf0, 0xc7, 0xbb, 0x5d, 0x1d, 0x89, 0x34, 0xeb, 0x4a, 0x40, 0x7d, - 0xb7, 0x7b, 0x12, 0x4c, 0xe5, 0x78, 0xaf, 0xb3, 0xa5, 0x9f, 0x2d, 0xd6, 0x72, 0xb2, 0x47, 0xd9, 0xa9, 0xe2, 0x6a, - 0x93, 0x04, 0x18, 0x56, 0x10, 0x60, 0x92, 0x26, 0x80, 0x45, 0xe7, 0xaa, 0xf6, 0xc3, 0xa6, 0x4a, 0x78, 0x85, 0x32, - 0xdc, 0x90, 0xa2, 0x8b, 0x31, 0x49, 0x2d, 0x98, 0x3b, 0x6e, 0x75, 0xf7, 0x22, 0x69, 0x5c, 0xa2, 0xf0, 0x28, 0x40, - 0x7a, 0x40, 0x67, 0xb4, 0xe0, 0xfc, 0x38, 0xdb, 0xb9, 0x60, 0xa7, 0x8d, 0x68, 0x1a, 0x57, 0x91, 0x53, 0x34, 0x35, - 0xf4, 0x94, 0x59, 0x35, 0x13, 0x7e, 0x8d, 0x16, 0x90, 0x24, 0xc1, 0x5d, 0xca, 0xb0, 0x2c, 0x59, 0xe8, 0xc0, 0x42, - 0x40, 0x61, 0x92, 0xeb, 0x2a, 0x7c, 0x2b, 0x35, 0x6e, 0x69, 0x77, 0xff, 0xfa, 0x8f, 0xff, 0x5b, 0x46, 0x64, 0x81, - 0x2a, 0x2d, 0x35, 0xd6, 0x02, 0xa1, 0xcb, 0x3d, 0xba, 0xb5, 0xa2, 0x8f, 0x10, 0xd9, 0x25, 0xb8, 0xf6, 0xf1, 0xb0, - 0x31, 0x8e, 0x92, 0x11, 0x00, 0xb6, 0x96, 0x40, 0x66, 0x52, 0xb8, 0x84, 0xba, 0x5e, 0x84, 0x2c, 0xf8, 0x9b, 0xd2, - 0x9b, 0x55, 0x96, 0x2c, 0xed, 0x56, 0x33, 0xd9, 0xb9, 0xda, 0x50, 0xb5, 0x84, 0x67, 0xf5, 0xdb, 0x7d, 0x4a, 0xa8, - 0xd5, 0xf2, 0x9c, 0xa1, 0xa5, 0x3e, 0x02, 0xf9, 0xd7, 0x7f, 0xfa, 0xbb, 0xff, 0xa1, 0x1e, 0xf1, 0x64, 0xe3, 0xaf, - 0xff, 0xf0, 0x9f, 0x31, 0x1b, 0xd3, 0xd2, 0xa7, 0x1f, 0x24, 0x27, 0xac, 0xea, 0xe8, 0x43, 0x08, 0x0c, 0x0b, 0x53, - 0x9d, 0x26, 0x20, 0x06, 0xe3, 0x41, 0x3d, 0xf3, 0xf9, 0x80, 0x26, 0xa4, 0xcd, 0x26, 0xa1, 0xa3, 0x4d, 0x5b, 0x56, - 0x3c, 0x52, 0x23, 0x39, 0xf1, 0x22, 0x54, 0x22, 0xbd, 0xef, 0x74, 0xfb, 0xc3, 0xd7, 0xab, 0x31, 0x57, 0xf1, 0x3e, - 0x2c, 0x29, 0xab, 0x72, 0x0b, 0x03, 0xf1, 0x73, 0x7c, 0x0c, 0xda, 0x46, 0x31, 0x2d, 0x5e, 0xad, 0x4f, 0xe7, 0xa7, - 0x19, 0xc0, 0x3f, 0x42, 0x8a, 0x8b, 0xa8, 0x22, 0x9d, 0x79, 0x36, 0xd0, 0xe6, 0x4b, 0xae, 0x4a, 0x1a, 0x45, 0x38, - 0x8a, 0x0f, 0x9e, 0xfc, 0x4d, 0xf9, 0xe7, 0x09, 0x5a, 0x56, 0x96, 0x33, 0x89, 0x2e, 0xa5, 0xfb, 0xf8, 0xa8, 0xd9, - 0x9c, 0x5e, 0xba, 0xf3, 0x6a, 0x06, 0x6f, 0xdd, 0x64, 0x14, 0x89, 0x34, 0x07, 0xa4, 0xc3, 0x52, 0x1d, 0xf4, 0x04, - 0x8f, 0xa9, 0x89, 0x31, 0xb2, 0xb2, 0xfc, 0xd3, 0x9c, 0xe2, 0x6e, 0xf1, 0x2f, 0x78, 0xa8, 0x29, 0x43, 0x94, 0x50, - 0x62, 0x60, 0x31, 0x37, 0x7a, 0xb5, 0x45, 0xaf, 0x71, 0x6b, 0xf9, 0xea, 0x83, 0x79, 0x28, 0x6b, 0x1e, 0xa7, 0x3e, - 0xc0, 0x03, 0xd2, 0x71, 0xcb, 0x1b, 0xb7, 0xe7, 0x7a, 0x78, 0xce, 0xb3, 0x89, 0x79, 0x0a, 0xcb, 0x22, 0x36, 0x60, - 0x23, 0x15, 0xda, 0x95, 0xf5, 0xe2, 0x84, 0xb5, 0x1c, 0xef, 0xae, 0x98, 0x4b, 0x82, 0x44, 0xa7, 0xaf, 0x00, 0xcf, - 0x3d, 0xdc, 0x80, 0x40, 0xff, 0x2c, 0xe2, 0x01, 0xf1, 0x6b, 0xc7, 0x3c, 0xcb, 0x8d, 0x50, 0xca, 0x64, 0x73, 0x03, - 0x9e, 0x8e, 0x68, 0x8a, 0x41, 0xd6, 0xfa, 0xd5, 0x93, 0xd2, 0xa7, 0xee, 0xe6, 0x50, 0x22, 0x46, 0xf3, 0x8d, 0x3c, - 0x22, 0x7d, 0x5a, 0x0b, 0x6e, 0x48, 0x15, 0xd3, 0x76, 0xbd, 0x95, 0xf5, 0x42, 0x53, 0x8b, 0xda, 0x6f, 0xb8, 0x63, - 0x13, 0x98, 0xf6, 0x62, 0x2b, 0x2a, 0xc4, 0x56, 0x4f, 0xc3, 0x6f, 0xb4, 0xeb, 0x13, 0x4d, 0xa7, 0xd4, 0xd0, 0x05, - 0x26, 0x26, 0x83, 0x15, 0x65, 0x07, 0x1d, 0xff, 0x8b, 0xd3, 0x76, 0xd9, 0x46, 0x6e, 0x04, 0xf1, 0x4d, 0x9e, 0xc3, - 0xe3, 0xaf, 0xae, 0x74, 0xff, 0x1f, 0x1c, 0x1d, 0xa5, 0x5f, 0x1b, 0x82, 0x00, 0x00}; - -} // namespace web_server -} // namespace esphome diff --git a/esphome/components/web_server/server_index_v2.h b/esphome/components/web_server/server_index_v2.h new file mode 100644 index 0000000000..21beecfff7 --- /dev/null +++ b/esphome/components/web_server/server_index_v2.h @@ -0,0 +1,633 @@ +#pragma once +// Generated from https://github.com/esphome/esphome-webserver +#ifdef USE_WEBSERVER_LOCAL +#if USE_WEBSERVER_VERSION == 2 +#include "esphome/core/hal.h" +namespace esphome { + +namespace web_server { + +const uint8_t INDEX_GZ[] PROGMEM = { + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc5, 0x7d, 0xd9, 0x92, 0xdb, 0x46, 0xb6, 0xe0, 0xf3, + 0xdc, 0xaf, 0x40, 0xc1, 0xd5, 0x25, 0x64, 0x33, 0x89, 0x22, 0x59, 0xda, 0x0c, 0x56, 0x92, 0x5d, 0x2a, 0xc9, 0x2d, + 0xbb, 0xb5, 0xd8, 0x2a, 0xc9, 0x6e, 0x9b, 0x66, 0x57, 0xa1, 0x88, 0x24, 0x99, 0x16, 0x88, 0xa4, 0x13, 0xc9, 0x5a, + 0x4c, 0xe2, 0xc6, 0x7c, 0xc0, 0x44, 0x4c, 0xc4, 0x3c, 0xcd, 0xcb, 0xc4, 0xdc, 0x87, 0xf9, 0x88, 0x79, 0xbe, 0x9f, + 0x72, 0x7f, 0x60, 0xe6, 0x13, 0x26, 0x4e, 0x2e, 0x40, 0x82, 0x4b, 0xa9, 0xbc, 0xdc, 0x3b, 0xa1, 0x90, 0x44, 0xe4, + 0x7a, 0xf2, 0xe4, 0xc9, 0xb3, 0x27, 0x70, 0xbc, 0x97, 0xf0, 0x91, 0xbc, 0x9d, 0x53, 0x6f, 0x2a, 0x67, 0x69, 0xef, + 0xd8, 0xfc, 0x4b, 0xe3, 0xa4, 0x77, 0x9c, 0xb2, 0xec, 0xa3, 0x27, 0x68, 0x4a, 0xd8, 0x88, 0x67, 0xde, 0x54, 0xd0, + 0x31, 0x49, 0x62, 0x19, 0x47, 0x6c, 0x16, 0x4f, 0xa8, 0x77, 0xd8, 0x3b, 0x9e, 0x51, 0x19, 0x7b, 0xa3, 0x69, 0x2c, + 0x72, 0x2a, 0xc9, 0x87, 0xf7, 0x5f, 0x34, 0x9f, 0xf6, 0x8e, 0xf3, 0x91, 0x60, 0x73, 0xe9, 0xc1, 0x90, 0x64, 0xc6, + 0x93, 0x45, 0x4a, 0x7b, 0x87, 0x87, 0xd7, 0xd7, 0xd7, 0xe1, 0x4f, 0xf9, 0x3f, 0x8d, 0x78, 0x96, 0x4b, 0xef, 0x15, + 0xb9, 0x66, 0x59, 0xc2, 0xaf, 0x31, 0x95, 0xe4, 0x55, 0x78, 0x36, 0x8d, 0x13, 0x7e, 0xfd, 0x8e, 0x73, 0x79, 0x70, + 0x10, 0xe8, 0xc7, 0xdb, 0xd3, 0xb3, 0x33, 0x42, 0xc8, 0x15, 0x67, 0x89, 0xd7, 0x5a, 0xad, 0xaa, 0xc2, 0x30, 0x8b, + 0x25, 0xbb, 0xa2, 0xba, 0x0b, 0x3a, 0x38, 0xf0, 0xe3, 0x84, 0xcf, 0x25, 0x4d, 0xce, 0xe4, 0x6d, 0x4a, 0xcf, 0xa6, + 0x94, 0xca, 0xdc, 0x67, 0x99, 0xf7, 0x9c, 0x8f, 0x16, 0x33, 0x9a, 0xc9, 0x70, 0x2e, 0xb8, 0xe4, 0x00, 0xc9, 0xc1, + 0x81, 0x2f, 0xe8, 0x3c, 0x8d, 0x47, 0x14, 0xea, 0x4f, 0xcf, 0xce, 0xaa, 0x1e, 0x55, 0x23, 0xcc, 0x24, 0x39, 0xbb, + 0x9d, 0x5d, 0xf2, 0x34, 0x40, 0x38, 0x95, 0x24, 0xa3, 0xd7, 0xde, 0x77, 0x34, 0xfe, 0xf8, 0x3a, 0x9e, 0x77, 0x47, + 0x69, 0x9c, 0xe7, 0xde, 0xa5, 0x5c, 0xaa, 0x25, 0x88, 0xc5, 0x48, 0x72, 0x11, 0x48, 0x4c, 0x31, 0x43, 0x4b, 0x36, + 0x0e, 0xe4, 0x94, 0xe5, 0xe1, 0xf9, 0xfe, 0x28, 0xcf, 0xdf, 0xd1, 0x7c, 0x91, 0xca, 0x7d, 0xb2, 0xd7, 0xc2, 0x6c, + 0x8f, 0x10, 0x26, 0x91, 0x9c, 0x0a, 0x7e, 0xed, 0xbd, 0x10, 0x82, 0x8b, 0xc0, 0x3f, 0x3d, 0x3b, 0xd3, 0x2d, 0x3c, + 0x96, 0x7b, 0x19, 0x97, 0x5e, 0x39, 0x5e, 0x7c, 0x99, 0xd2, 0xd0, 0xfb, 0x90, 0x53, 0xef, 0x62, 0x91, 0xe5, 0xf1, + 0x98, 0x9e, 0x9e, 0x9d, 0x5d, 0x78, 0x5c, 0x78, 0x17, 0xa3, 0x3c, 0xbf, 0xf0, 0x58, 0x96, 0x4b, 0x1a, 0x27, 0xa1, + 0x8f, 0xba, 0x6a, 0xb2, 0x51, 0x9e, 0xbf, 0xa7, 0x37, 0x92, 0x48, 0xac, 0x1e, 0x25, 0xa1, 0xc5, 0x84, 0x4a, 0x2f, + 0x2f, 0xd7, 0x15, 0xa0, 0x65, 0x4a, 0xa5, 0x27, 0x89, 0xaa, 0xe7, 0x5d, 0x8d, 0x7b, 0xaa, 0x1f, 0x65, 0x97, 0x8d, + 0x03, 0x2a, 0x0f, 0x0e, 0x64, 0x89, 0x67, 0xa4, 0x97, 0xe6, 0x31, 0x42, 0xf7, 0x6c, 0xd9, 0xc1, 0x01, 0x0d, 0x53, + 0x9a, 0x4d, 0xe4, 0x94, 0x10, 0xd2, 0xee, 0xb2, 0x83, 0x83, 0x40, 0x92, 0x54, 0x86, 0x13, 0x2a, 0x03, 0x8a, 0x10, + 0xae, 0x7a, 0x1f, 0x1c, 0x04, 0x1a, 0x09, 0x9c, 0x68, 0xc4, 0xd5, 0x70, 0x8c, 0x42, 0x83, 0xfd, 0xb3, 0xdb, 0x6c, + 0x14, 0xb8, 0xf0, 0x23, 0xcc, 0x0e, 0x0e, 0x52, 0x19, 0xe6, 0x30, 0x22, 0x96, 0x08, 0x15, 0x82, 0xca, 0x85, 0xc8, + 0x3c, 0x59, 0x48, 0x7e, 0x26, 0x05, 0xcb, 0x26, 0x01, 0x5a, 0xda, 0x32, 0xa7, 0x63, 0x51, 0x68, 0x70, 0xbf, 0x96, + 0x44, 0x90, 0x1e, 0xcc, 0x78, 0x29, 0x03, 0xd8, 0x45, 0x3e, 0xf6, 0x04, 0x21, 0x7e, 0xae, 0xfa, 0xfa, 0x7d, 0x11, + 0x89, 0x86, 0xef, 0x63, 0x0d, 0x25, 0x66, 0x12, 0xe1, 0x8f, 0x24, 0x10, 0x38, 0x0c, 0x43, 0x89, 0x48, 0x6f, 0x69, + 0xb1, 0x22, 0x9c, 0x75, 0xf6, 0xc5, 0xa0, 0x35, 0x8c, 0x64, 0x28, 0x68, 0xb2, 0x18, 0xd1, 0x20, 0x60, 0x38, 0xc7, + 0x19, 0x22, 0x3d, 0xd6, 0x08, 0x38, 0xe9, 0xc1, 0x76, 0xf3, 0xfa, 0x5e, 0x13, 0xb2, 0xd7, 0x42, 0x06, 0x46, 0x6e, + 0x01, 0x04, 0x0c, 0x1b, 0x78, 0x38, 0x21, 0x7e, 0xb6, 0x98, 0x5d, 0x52, 0xe1, 0x97, 0xcd, 0xba, 0x35, 0xb2, 0x58, + 0xe4, 0xd4, 0x1b, 0xe5, 0xb9, 0x37, 0x5e, 0x64, 0x23, 0xc9, 0x78, 0xe6, 0xf9, 0x0d, 0xde, 0xf0, 0x35, 0x39, 0x94, + 0xd4, 0xe0, 0xa3, 0x02, 0x05, 0x39, 0x6a, 0x88, 0x41, 0xd6, 0x68, 0x0f, 0x31, 0x40, 0x89, 0xba, 0x66, 0x3c, 0x83, + 0x00, 0x8a, 0x05, 0xac, 0xb1, 0xc0, 0x1f, 0x24, 0xac, 0x52, 0x2d, 0x91, 0xca, 0xbe, 0x08, 0x37, 0x0f, 0x0a, 0x91, + 0xe1, 0x2c, 0x9e, 0x07, 0x94, 0xf4, 0xa8, 0x22, 0xae, 0x38, 0x1b, 0x01, 0xac, 0xb5, 0x7d, 0xeb, 0xd3, 0x88, 0x86, + 0x15, 0x49, 0xa1, 0x48, 0x86, 0x63, 0x2e, 0x5e, 0xc4, 0xa3, 0x29, 0xf4, 0x2b, 0x09, 0x26, 0xb1, 0xe7, 0x6d, 0x24, + 0x68, 0x2c, 0xe9, 0x8b, 0x94, 0xc2, 0x53, 0xe0, 0xab, 0x9e, 0x3e, 0xc2, 0x39, 0x79, 0x15, 0xa6, 0x4c, 0xbe, 0xe1, + 0xd9, 0x88, 0x76, 0x73, 0x87, 0xba, 0x18, 0xec, 0xfb, 0x89, 0x94, 0x82, 0x5d, 0x2e, 0x24, 0x0d, 0xfc, 0x0c, 0x5a, + 0xf8, 0x38, 0x47, 0x98, 0x85, 0x92, 0xde, 0xc8, 0x53, 0x9e, 0x49, 0x9a, 0x49, 0x42, 0x2d, 0x52, 0xb1, 0x08, 0xe3, + 0xf9, 0x9c, 0x66, 0xc9, 0xe9, 0x94, 0xa5, 0x49, 0xc0, 0x50, 0x81, 0x0a, 0x1c, 0x4b, 0x02, 0x6b, 0x24, 0x3d, 0x11, + 0xc1, 0x3f, 0xbb, 0x57, 0x13, 0x48, 0xd2, 0x53, 0x87, 0x82, 0x12, 0xdf, 0xef, 0x8e, 0xb9, 0x08, 0xcc, 0x0a, 0x3c, + 0x3e, 0xf6, 0x24, 0xcc, 0xf1, 0x6e, 0x91, 0xd2, 0x1c, 0xd1, 0x06, 0x61, 0xe5, 0x36, 0x1a, 0x04, 0x7f, 0x0d, 0x14, + 0x5f, 0xa0, 0x40, 0xa0, 0x48, 0x74, 0xaf, 0x62, 0xe1, 0x7d, 0x61, 0x4e, 0xd4, 0x4f, 0x96, 0x9b, 0x4d, 0x25, 0xf9, + 0x29, 0x94, 0x62, 0x91, 0x4b, 0x9a, 0xbc, 0xbf, 0x9d, 0xd3, 0x1c, 0xbf, 0x94, 0x64, 0x2a, 0xfb, 0x53, 0x19, 0xd2, + 0xd9, 0x5c, 0xde, 0x9e, 0x29, 0xc6, 0x18, 0xf9, 0x3e, 0x1e, 0x41, 0x4b, 0x41, 0xe3, 0x11, 0x30, 0x33, 0x83, 0xad, + 0xaf, 0x79, 0x7a, 0x3b, 0x66, 0x69, 0x7a, 0xb6, 0x98, 0xcf, 0xb9, 0x90, 0xf8, 0xaf, 0x64, 0x29, 0x79, 0x85, 0x1a, + 0xd8, 0xcb, 0x65, 0x7e, 0xcd, 0xe4, 0x68, 0x1a, 0x48, 0xb4, 0x1c, 0xc5, 0x39, 0xf5, 0x9e, 0x71, 0x9e, 0xd2, 0x38, + 0x8b, 0x04, 0x11, 0xfd, 0x97, 0x32, 0xca, 0x16, 0x69, 0xda, 0xbd, 0x14, 0x34, 0xfe, 0xd8, 0x55, 0xd5, 0x6f, 0x2f, + 0x7f, 0xa2, 0x23, 0x19, 0xa9, 0xdf, 0x27, 0x42, 0xc4, 0xb7, 0xd0, 0x90, 0x10, 0x68, 0xd6, 0x17, 0xd1, 0x57, 0x67, + 0x6f, 0xdf, 0x84, 0xfa, 0x90, 0xb0, 0xf1, 0x6d, 0x20, 0xca, 0x83, 0x27, 0x0a, 0x3c, 0x16, 0x7c, 0xb6, 0x36, 0xb5, + 0xc6, 0x9a, 0xe8, 0xee, 0x00, 0x81, 0x12, 0xb1, 0xa7, 0x87, 0x76, 0x21, 0x78, 0xa3, 0x68, 0x1e, 0x2a, 0x89, 0x99, + 0x17, 0xfe, 0x89, 0x74, 0x71, 0x20, 0xd0, 0xdd, 0xd0, 0x4a, 0x71, 0xbb, 0xa4, 0x44, 0xc1, 0x39, 0x07, 0x09, 0x03, + 0x30, 0x8e, 0x62, 0x39, 0x9a, 0x2e, 0xa9, 0x1a, 0xac, 0xb0, 0x10, 0xd3, 0xa2, 0xc0, 0xd7, 0x25, 0xbd, 0xcb, 0x3d, + 0x42, 0x84, 0x62, 0x54, 0x44, 0xae, 0x56, 0x82, 0x10, 0x81, 0xf0, 0x77, 0x64, 0x19, 0xdb, 0xf5, 0x44, 0x7b, 0x2d, + 0x0c, 0xe7, 0x32, 0xd2, 0xdc, 0x05, 0x8f, 0x78, 0x76, 0x45, 0x85, 0xa4, 0x22, 0xfa, 0x2b, 0x16, 0x74, 0x9c, 0x02, + 0x14, 0x7b, 0x6d, 0x3c, 0x8d, 0xf3, 0xd3, 0x69, 0x9c, 0x4d, 0x68, 0x12, 0x5d, 0xcb, 0x02, 0xff, 0x9d, 0xf8, 0x63, + 0x96, 0xc5, 0x29, 0xfb, 0x85, 0x26, 0xbe, 0x91, 0x06, 0x27, 0x1e, 0xbd, 0x91, 0x34, 0x4b, 0x72, 0xef, 0xe5, 0xfb, + 0xd7, 0xaf, 0xcc, 0x3e, 0xd6, 0x04, 0x04, 0x5a, 0xe6, 0x8b, 0x39, 0x15, 0x01, 0xc2, 0x46, 0x40, 0xbc, 0x60, 0x8a, + 0x39, 0xbe, 0x8e, 0xe7, 0xba, 0x84, 0xe5, 0x1f, 0xe6, 0x49, 0x2c, 0xe9, 0xd7, 0x34, 0x4b, 0x58, 0x36, 0x21, 0x7b, + 0x6d, 0x5d, 0x3e, 0x8d, 0x4d, 0x45, 0x52, 0x16, 0x9d, 0xef, 0xbf, 0x48, 0xd5, 0xba, 0xcb, 0xc7, 0x45, 0x80, 0x8a, + 0x5c, 0xc6, 0x92, 0x8d, 0xbc, 0x38, 0x49, 0xbe, 0xcc, 0x98, 0x64, 0x0a, 0x40, 0x01, 0xdb, 0x03, 0x24, 0x4a, 0xb5, + 0xa8, 0xb0, 0x80, 0x07, 0x08, 0x07, 0x81, 0x11, 0x00, 0x53, 0x64, 0xf6, 0xeb, 0xe0, 0xa0, 0x62, 0xf7, 0x7d, 0x1a, + 0xe9, 0x4a, 0x32, 0x18, 0xa2, 0x70, 0xbe, 0xc8, 0x61, 0xa3, 0xed, 0x14, 0x20, 0x5d, 0xf8, 0x65, 0x4e, 0xc5, 0x15, + 0x4d, 0x4a, 0xe2, 0xc8, 0x03, 0xb4, 0x5c, 0x9b, 0xc3, 0x1c, 0x0b, 0x49, 0x06, 0xc3, 0xae, 0xcb, 0xb7, 0xa9, 0xa1, + 0x73, 0xc1, 0xe7, 0x54, 0x48, 0x46, 0xf3, 0x92, 0x95, 0x04, 0x20, 0x45, 0x4b, 0x76, 0x92, 0x13, 0xbb, 0xbe, 0x79, + 0xc0, 0x30, 0x45, 0x35, 0x86, 0x61, 0x05, 0xed, 0x8b, 0x2b, 0x25, 0x31, 0x72, 0xcc, 0x10, 0x96, 0x1a, 0xd2, 0x1c, + 0xa1, 0x02, 0x61, 0x69, 0xc1, 0xd5, 0xac, 0xc8, 0xcc, 0x76, 0x0b, 0xa2, 0x9a, 0x7c, 0xa7, 0x44, 0x35, 0x30, 0xb4, + 0x58, 0xd2, 0x83, 0x83, 0x80, 0x86, 0x25, 0x51, 0x90, 0xbd, 0xb6, 0xd9, 0x23, 0x07, 0x59, 0x3b, 0xc0, 0x86, 0x89, + 0x25, 0xa6, 0x08, 0xef, 0xd1, 0x30, 0xe3, 0x27, 0xa3, 0x11, 0xcd, 0x73, 0x2e, 0x0e, 0x0e, 0xf6, 0x54, 0xfb, 0x52, + 0x9b, 0x80, 0x3d, 0x7c, 0x7b, 0x9d, 0x55, 0x10, 0xa0, 0x4a, 0xc2, 0x1a, 0xb9, 0x20, 0x41, 0x4e, 0x29, 0x85, 0xc3, + 0xef, 0x5b, 0xc5, 0x23, 0xf2, 0xcf, 0xcf, 0xfd, 0x86, 0xc4, 0x06, 0x0d, 0x13, 0x6a, 0xa7, 0xbe, 0x7d, 0x4e, 0xb5, + 0x6a, 0xa5, 0x14, 0x8f, 0x0d, 0xcc, 0xe8, 0xf3, 0x13, 0x26, 0x74, 0xcc, 0x32, 0x67, 0xd9, 0x35, 0x90, 0xb0, 0xc4, + 0x39, 0x2a, 0x9c, 0x0d, 0xdd, 0x3a, 0xb4, 0xd2, 0x69, 0xf4, 0xce, 0x2d, 0x27, 0x4a, 0x8f, 0x70, 0xb6, 0x71, 0x40, + 0x87, 0x05, 0x56, 0xa8, 0xb7, 0xab, 0xc9, 0x14, 0xa0, 0x03, 0x39, 0xec, 0x9a, 0x7a, 0x92, 0x6b, 0xcc, 0x09, 0xfa, + 0xf3, 0x82, 0xe6, 0x52, 0xd3, 0x71, 0x20, 0x71, 0x86, 0x19, 0x2a, 0xe0, 0xb8, 0x8d, 0xd9, 0x64, 0x21, 0x40, 0xdd, + 0x81, 0xa3, 0x48, 0xb3, 0xc5, 0x8c, 0xda, 0xa7, 0x6d, 0xb0, 0xbd, 0x9d, 0x83, 0x40, 0xcc, 0x81, 0xa6, 0xef, 0x26, + 0x27, 0x80, 0x55, 0xa2, 0xd5, 0xea, 0x3b, 0x3b, 0x48, 0xb5, 0x95, 0xa5, 0x8a, 0xb6, 0xb6, 0x27, 0x7f, 0x47, 0x46, + 0x1e, 0xef, 0xb5, 0x35, 0xf4, 0x7f, 0x1f, 0x92, 0xbd, 0x56, 0x49, 0xc1, 0x06, 0xa7, 0x1a, 0x18, 0x8d, 0xc2, 0xb7, + 0x7a, 0x20, 0xa4, 0xa4, 0x7b, 0x8d, 0x58, 0xc2, 0xe9, 0x06, 0x9d, 0x4e, 0xc9, 0x00, 0xf4, 0x8c, 0x70, 0x3a, 0xdc, + 0x45, 0x4c, 0x96, 0x1b, 0x04, 0x72, 0xb3, 0xae, 0x62, 0x1a, 0x57, 0x75, 0xa6, 0xb1, 0xb6, 0x08, 0x7f, 0x5e, 0x76, + 0xf1, 0x4b, 0x1a, 0x33, 0xc7, 0xbc, 0xaa, 0xc2, 0x4c, 0x01, 0x53, 0x2d, 0xc9, 0x19, 0xe2, 0x4d, 0x3c, 0xa3, 0x79, + 0x40, 0x11, 0xde, 0xd5, 0x40, 0x13, 0x27, 0x34, 0x19, 0x3a, 0x62, 0x33, 0x07, 0xb1, 0xc9, 0x90, 0xd6, 0xca, 0xea, + 0xc7, 0x2d, 0xc7, 0x74, 0x90, 0x0f, 0x2b, 0x65, 0xce, 0x59, 0xbc, 0x92, 0xc7, 0x86, 0xba, 0x2d, 0xfe, 0x74, 0x99, + 0x46, 0x9a, 0x52, 0x1a, 0x72, 0x84, 0xf7, 0x5a, 0xeb, 0xfb, 0x68, 0x5b, 0x55, 0x6b, 0x1c, 0x0c, 0x61, 0x1f, 0x94, + 0xb8, 0x08, 0x59, 0xae, 0xfe, 0xaf, 0x9d, 0x33, 0x40, 0xdb, 0x19, 0x90, 0x45, 0x38, 0x4e, 0x63, 0x19, 0xb4, 0x0f, + 0x5b, 0xa0, 0x89, 0x5e, 0x51, 0x90, 0x26, 0x08, 0x6d, 0x2e, 0x85, 0x86, 0x8b, 0x2c, 0x9f, 0xb2, 0xb1, 0x0c, 0x62, + 0xa9, 0x18, 0x0a, 0x4d, 0x73, 0xea, 0xc9, 0x9a, 0x3e, 0xac, 0x98, 0x4d, 0x0c, 0xa4, 0x56, 0x2a, 0x5f, 0xd4, 0x42, + 0xaa, 0x98, 0x16, 0xf0, 0x86, 0x4a, 0x97, 0xae, 0x78, 0x8c, 0x6d, 0xcd, 0x40, 0x5f, 0x6c, 0xf7, 0xf5, 0x88, 0x91, + 0x61, 0x05, 0xcc, 0x51, 0x59, 0x59, 0xe4, 0xf2, 0x07, 0x53, 0x28, 0x43, 0xc9, 0x5f, 0xf1, 0x6b, 0x2a, 0x4e, 0x63, + 0x00, 0x3e, 0xd2, 0xdd, 0x0b, 0x2d, 0x06, 0x14, 0xb7, 0x97, 0x5d, 0x4b, 0x2f, 0xe7, 0x6a, 0xe1, 0x5f, 0x0b, 0x3e, + 0x63, 0x39, 0x05, 0x4d, 0x4d, 0xe3, 0x3f, 0x83, 0x53, 0xa6, 0x8e, 0x23, 0x88, 0x1a, 0x5a, 0xd2, 0xd7, 0xc9, 0xab, + 0x3a, 0x7d, 0x9d, 0xef, 0xbf, 0x98, 0x58, 0xf6, 0x57, 0x3f, 0xc4, 0x08, 0x07, 0xc6, 0x9e, 0x70, 0xa4, 0x5c, 0x38, + 0x45, 0x46, 0xbc, 0xaf, 0x56, 0xd2, 0x31, 0xdb, 0x6a, 0xba, 0x22, 0xd5, 0xc7, 0x06, 0x15, 0x71, 0x92, 0x80, 0x56, + 0x27, 0x78, 0x9a, 0x3a, 0x82, 0x0a, 0xb3, 0x6e, 0x29, 0x9a, 0xce, 0xf7, 0x5f, 0x9c, 0xdd, 0x25, 0x9d, 0xa0, 0xde, + 0x15, 0x50, 0x16, 0xd0, 0x2c, 0xa1, 0x02, 0xcc, 0x48, 0x67, 0xb7, 0x8c, 0x8c, 0x3d, 0xe5, 0x59, 0x46, 0x47, 0x92, + 0x26, 0x60, 0xa5, 0x30, 0x22, 0xc3, 0x29, 0xcf, 0x65, 0x59, 0x58, 0x41, 0xcf, 0x1c, 0xe8, 0x59, 0x38, 0x8a, 0xd3, + 0x34, 0xd0, 0x16, 0xc9, 0x8c, 0x5f, 0xd1, 0x2d, 0x50, 0x77, 0x6b, 0x20, 0x97, 0xc3, 0x50, 0x67, 0x18, 0x1a, 0xe6, + 0xf3, 0x94, 0x8d, 0x68, 0x29, 0xb8, 0xce, 0x42, 0x96, 0x25, 0xf4, 0x06, 0xf8, 0x08, 0xea, 0xf5, 0x7a, 0x2d, 0xdc, + 0x46, 0x85, 0x46, 0xf8, 0x72, 0x03, 0xb1, 0x77, 0x88, 0x4c, 0x20, 0x32, 0xd2, 0x5b, 0x6e, 0xe3, 0x07, 0x14, 0x39, + 0x72, 0x92, 0x59, 0xcb, 0x4a, 0xf3, 0x66, 0x84, 0x13, 0x9a, 0x52, 0x49, 0x2d, 0x2f, 0x07, 0xfd, 0x59, 0x1f, 0xdd, + 0x77, 0x25, 0xfe, 0x4a, 0x72, 0xb2, 0xa7, 0xcc, 0xee, 0x79, 0x5e, 0x5a, 0xea, 0xd5, 0xf6, 0x54, 0xd8, 0xee, 0x4b, + 0xbd, 0x3d, 0xb1, 0x94, 0xf1, 0x68, 0xaa, 0x4d, 0xf4, 0x60, 0x63, 0x49, 0xd5, 0x18, 0x86, 0xaf, 0x97, 0x87, 0xe8, + 0x83, 0x05, 0x73, 0x1b, 0x0a, 0xce, 0x0c, 0x53, 0xa0, 0x60, 0xf5, 0xe9, 0x6d, 0x3b, 0x8d, 0xd3, 0xf4, 0x32, 0x1e, + 0x7d, 0xac, 0x53, 0x7f, 0x45, 0x06, 0x64, 0x9d, 0x1b, 0x3b, 0x55, 0x0e, 0xcb, 0x72, 0xd7, 0x6d, 0xb9, 0x74, 0xed, + 0xa0, 0x04, 0x7b, 0xad, 0x8a, 0xec, 0xeb, 0x1b, 0xbd, 0x93, 0xda, 0x15, 0x44, 0xcc, 0xac, 0x2c, 0x00, 0x2e, 0xf0, + 0x49, 0x8a, 0xb3, 0xfc, 0xc0, 0xd0, 0x1d, 0xd8, 0x1a, 0xc5, 0x1a, 0x20, 0x12, 0x2d, 0x8b, 0x84, 0xe5, 0xbb, 0x31, + 0xf0, 0x87, 0x40, 0xf9, 0xdc, 0x99, 0xe1, 0xbe, 0x80, 0x96, 0x3c, 0xce, 0xa8, 0xcc, 0x25, 0x64, 0x46, 0x9b, 0xb0, + 0x8c, 0xe6, 0x6f, 0xa0, 0xb9, 0x28, 0x7a, 0x7f, 0xab, 0xab, 0x40, 0x27, 0x03, 0x28, 0xf2, 0xae, 0xab, 0x4c, 0xd4, + 0x28, 0xc0, 0xf0, 0x54, 0xa6, 0x44, 0x6e, 0x56, 0x33, 0x1e, 0x8d, 0xba, 0xae, 0xed, 0x6f, 0xc3, 0x72, 0x39, 0x09, + 0x82, 0x20, 0x07, 0xfb, 0xcd, 0xea, 0xf5, 0xd5, 0x22, 0xf2, 0x8d, 0x45, 0xe4, 0xa1, 0x63, 0x64, 0xa1, 0x8a, 0x96, + 0x9d, 0xee, 0xd1, 0x5f, 0x91, 0xdb, 0x08, 0x94, 0xd5, 0x10, 0xf8, 0x33, 0x2a, 0xd9, 0x6d, 0x4a, 0x24, 0xe6, 0xc6, + 0xc0, 0x31, 0x94, 0x06, 0x0c, 0xa3, 0xea, 0x92, 0x21, 0x7d, 0x34, 0x6a, 0xc6, 0x6e, 0x86, 0x39, 0x5a, 0xd3, 0xec, + 0x8b, 0xc2, 0xe0, 0x88, 0x22, 0xb3, 0x37, 0x35, 0x95, 0xd8, 0xc1, 0x0a, 0xce, 0x88, 0x51, 0x83, 0xb5, 0xd6, 0xb3, + 0x8e, 0x9b, 0x72, 0x5c, 0x38, 0xa8, 0x15, 0x6a, 0x6a, 0xfa, 0xa4, 0x55, 0xac, 0x32, 0x84, 0xa7, 0x56, 0x23, 0xe5, + 0xd5, 0xba, 0x09, 0xf1, 0xad, 0x37, 0xc2, 0xef, 0x2f, 0x6b, 0x26, 0x61, 0xe4, 0x34, 0x2b, 0x22, 0x60, 0xa9, 0x7c, + 0x1b, 0xba, 0xb7, 0xd1, 0x4c, 0x6d, 0x1c, 0x07, 0xe1, 0xdc, 0x45, 0xb8, 0x83, 0xd9, 0x4c, 0x73, 0xae, 0x6c, 0x48, + 0xa6, 0xf5, 0xbe, 0x01, 0xc5, 0x5c, 0xef, 0xc3, 0x06, 0x12, 0xd7, 0x15, 0x4f, 0x45, 0x82, 0x60, 0xc0, 0xe6, 0xa0, + 0xdc, 0xb9, 0xf2, 0x21, 0x00, 0xd8, 0xd9, 0x6a, 0xb5, 0x41, 0x74, 0x5b, 0xf5, 0x4f, 0x14, 0x56, 0x46, 0xe1, 0x6a, + 0x75, 0x2d, 0x51, 0x60, 0x34, 0x5f, 0x4c, 0x51, 0xdf, 0x72, 0xdc, 0x93, 0x57, 0xd0, 0x4a, 0x29, 0xa2, 0x55, 0x49, + 0x69, 0x32, 0xd4, 0x69, 0xb6, 0xbe, 0x4f, 0xd2, 0x61, 0xdb, 0xa7, 0x1b, 0xdc, 0x4b, 0x15, 0x1a, 0x31, 0x5d, 0x2d, + 0xf9, 0xd4, 0x0c, 0xcd, 0x10, 0x42, 0x51, 0xae, 0xac, 0x98, 0xbd, 0x6d, 0x86, 0xe5, 0xc1, 0x41, 0xee, 0x0c, 0x74, + 0x5e, 0xb2, 0x89, 0x9f, 0x02, 0x10, 0xc9, 0xf9, 0x6d, 0xa6, 0x74, 0x97, 0x9f, 0xac, 0x10, 0xda, 0x30, 0x4b, 0x5b, + 0x5d, 0xb0, 0xc6, 0xe3, 0xeb, 0x98, 0x49, 0xaf, 0x1c, 0x45, 0x5b, 0xe3, 0x01, 0x45, 0x4b, 0xa3, 0x6a, 0x84, 0x82, + 0x82, 0xf2, 0x08, 0x3c, 0xc1, 0xaa, 0xd0, 0x9a, 0xee, 0x47, 0x53, 0x0a, 0x8e, 0x60, 0xab, 0x45, 0x94, 0x76, 0xe1, + 0x9e, 0x91, 0x22, 0x66, 0xe0, 0xed, 0xb0, 0x17, 0xeb, 0xdd, 0x6b, 0x76, 0xc0, 0x9c, 0x8a, 0x31, 0x17, 0x33, 0x5b, + 0x57, 0xac, 0x3d, 0x1b, 0xce, 0xc8, 0xc6, 0xc1, 0xd6, 0xb1, 0x8d, 0xfa, 0xdf, 0x5d, 0x33, 0xba, 0x2b, 0x73, 0xbd, + 0x26, 0x4a, 0x4b, 0xe9, 0xab, 0xfd, 0x81, 0x96, 0x32, 0x73, 0xd7, 0xbc, 0x37, 0xce, 0xd4, 0xae, 0x76, 0x98, 0xec, + 0xb5, 0xbb, 0xa5, 0xcd, 0x67, 0xa9, 0xa1, 0xab, 0x1d, 0x1b, 0x46, 0xa4, 0xf2, 0x45, 0x9a, 0x18, 0x60, 0x19, 0xc2, + 0xd4, 0xd0, 0xd1, 0x35, 0x4b, 0xd3, 0xaa, 0xf4, 0xd7, 0xf0, 0xf5, 0xdc, 0xf0, 0xf5, 0xcc, 0xf2, 0x75, 0xe0, 0x14, + 0xc0, 0xd7, 0xf5, 0x70, 0x55, 0xf7, 0x6c, 0xe3, 0x74, 0x66, 0x9a, 0xa3, 0xe7, 0xca, 0x8e, 0x86, 0xf9, 0x16, 0x16, + 0x02, 0x54, 0x6a, 0x5e, 0x1f, 0x03, 0xe3, 0x84, 0x01, 0x03, 0x50, 0xbb, 0x30, 0xa9, 0xeb, 0xa2, 0xf8, 0x18, 0x20, + 0x9c, 0x17, 0xb4, 0xa4, 0xec, 0x93, 0x17, 0xe0, 0xa4, 0x73, 0x96, 0x03, 0x42, 0x4c, 0x15, 0xff, 0x2a, 0x25, 0xca, + 0xae, 0x8e, 0x99, 0xd5, 0xe5, 0x76, 0x75, 0xc0, 0xe9, 0xab, 0xd5, 0x25, 0x77, 0xf3, 0x7a, 0xb5, 0x3c, 0x56, 0x2e, + 0xaf, 0xda, 0xef, 0xd5, 0x2a, 0x58, 0x2b, 0x01, 0xff, 0xbd, 0x31, 0x51, 0x44, 0x39, 0x3a, 0xf0, 0x00, 0x17, 0x33, + 0x50, 0x50, 0xe8, 0x45, 0x97, 0x22, 0xee, 0xd5, 0xa7, 0x1c, 0x3c, 0xca, 0x4d, 0xaf, 0xfb, 0x9f, 0xf2, 0xd9, 0x1c, + 0xb4, 0xb1, 0x35, 0x92, 0x9e, 0x50, 0x33, 0x61, 0x55, 0x5f, 0x6c, 0x29, 0xab, 0xf5, 0x51, 0xe7, 0xb1, 0x46, 0x4d, + 0xa5, 0xbd, 0xbc, 0xd7, 0x2a, 0x16, 0x65, 0x51, 0xc9, 0x38, 0xb6, 0x39, 0x55, 0x4e, 0xd7, 0x5d, 0x32, 0xb6, 0xe2, + 0x6d, 0xc0, 0x34, 0x1f, 0x66, 0xc0, 0xeb, 0x1c, 0xf6, 0x63, 0xc9, 0xdd, 0xdd, 0xff, 0xa2, 0x42, 0xce, 0xb2, 0x58, + 0x43, 0xdf, 0xb2, 0x28, 0x4e, 0xb4, 0x91, 0x8d, 0x4f, 0x76, 0x5b, 0xc3, 0x55, 0x9d, 0x31, 0x16, 0x07, 0x43, 0x7c, + 0xb2, 0xa9, 0x3a, 0x92, 0xe5, 0x8c, 0x27, 0x34, 0xf2, 0xf9, 0x9c, 0x66, 0x7e, 0x01, 0x5e, 0x55, 0xb3, 0xf7, 0x23, + 0x19, 0x2c, 0xdf, 0xd5, 0xdd, 0xab, 0xd1, 0x49, 0x01, 0xde, 0xaf, 0x2f, 0x36, 0x1d, 0xaf, 0xdf, 0x52, 0x91, 0x2b, + 0x45, 0xb4, 0xd4, 0x69, 0xbf, 0xa8, 0xc4, 0xd2, 0x17, 0xd1, 0xce, 0xf6, 0x95, 0x09, 0xe2, 0xb7, 0xc3, 0xc7, 0xe1, + 0x91, 0x8f, 0x94, 0x5b, 0xf8, 0x2b, 0x73, 0xe0, 0x9f, 0x5b, 0xb7, 0xf0, 0x0b, 0xf2, 0xbc, 0xee, 0x15, 0x4e, 0x24, + 0x79, 0xd1, 0x7f, 0x61, 0x2d, 0x66, 0x9e, 0xb2, 0xd1, 0x6d, 0xe0, 0xa7, 0x4c, 0x36, 0x21, 0xf4, 0xe6, 0xe3, 0xa5, + 0xae, 0x00, 0x97, 0xa2, 0x72, 0x67, 0x17, 0xd6, 0xd6, 0xc3, 0x52, 0x12, 0x7f, 0x3f, 0x65, 0x72, 0xdf, 0xc7, 0x33, + 0x72, 0x01, 0x3f, 0xf6, 0x97, 0xc1, 0xeb, 0x58, 0x4e, 0x43, 0x11, 0x67, 0x09, 0x9f, 0x05, 0xa8, 0xe1, 0xfb, 0x28, + 0xcc, 0x95, 0xbd, 0xf1, 0x39, 0x2a, 0xf6, 0x2f, 0xf0, 0x8d, 0x24, 0x7e, 0xdf, 0x6f, 0xcc, 0xf0, 0x1b, 0x49, 0x2e, + 0x8e, 0xf7, 0x97, 0x37, 0xb2, 0xe8, 0x5d, 0xe0, 0x9b, 0xd2, 0x63, 0x8f, 0xbf, 0x26, 0x01, 0x22, 0xbd, 0x1b, 0x03, + 0xcd, 0x29, 0x9f, 0x69, 0xcf, 0xbd, 0x8f, 0xf0, 0x07, 0x88, 0xab, 0x88, 0x8a, 0xdb, 0x98, 0xd0, 0xca, 0x1e, 0xf1, + 0xb9, 0x72, 0x11, 0xf8, 0x07, 0x07, 0x4e, 0x59, 0xa9, 0x2a, 0xe0, 0x13, 0x49, 0x6a, 0x06, 0x39, 0x7e, 0xaf, 0x22, + 0x34, 0x27, 0x32, 0x10, 0xc8, 0x0e, 0x13, 0x58, 0x3f, 0xb4, 0x39, 0x9a, 0x62, 0xa0, 0x3d, 0x0c, 0x21, 0x93, 0x54, + 0xc4, 0x92, 0x8b, 0x21, 0x72, 0xd5, 0x0f, 0xfc, 0x37, 0x72, 0x31, 0xf0, 0xfe, 0xd3, 0x3f, 0xfd, 0x38, 0xfe, 0x51, + 0x0c, 0x2f, 0xf0, 0x5b, 0x72, 0x78, 0x1c, 0xf4, 0xa3, 0x60, 0xaf, 0xd9, 0x5c, 0xfd, 0x78, 0x38, 0xf8, 0x47, 0xdc, + 0xfc, 0xe5, 0xa4, 0xf9, 0xc3, 0x10, 0xad, 0x82, 0x1f, 0x0f, 0xfb, 0x03, 0xf3, 0x34, 0xf8, 0x47, 0xef, 0xc7, 0x7c, + 0xf8, 0x67, 0x5d, 0xb8, 0x8f, 0xd0, 0xe1, 0x04, 0x2f, 0x24, 0x39, 0x6c, 0x36, 0x7b, 0x87, 0x13, 0x3c, 0x97, 0xe4, + 0x10, 0xfe, 0xbf, 0x24, 0xef, 0xe8, 0xe4, 0xc5, 0xcd, 0x3c, 0xb8, 0xe8, 0xad, 0xf6, 0x97, 0x7f, 0x2b, 0x60, 0xd4, + 0xc1, 0x3f, 0x7e, 0xfc, 0x31, 0xf7, 0x1f, 0xf4, 0xc8, 0xe1, 0xb0, 0x81, 0x02, 0x28, 0xfd, 0x33, 0x51, 0xff, 0x06, + 0xfd, 0x68, 0xf0, 0x0f, 0x03, 0x85, 0xff, 0xe0, 0xc7, 0x8b, 0xe3, 0x1e, 0x19, 0xae, 0x02, 0x7f, 0xf5, 0x00, 0xad, + 0x10, 0x5a, 0xed, 0xa3, 0x0b, 0xec, 0x4f, 0x7c, 0x84, 0x27, 0x92, 0x1c, 0x3e, 0x38, 0x9c, 0xe0, 0x2b, 0x49, 0x0e, + 0xfd, 0xc3, 0x09, 0x7e, 0x21, 0xc9, 0xe1, 0x3f, 0x82, 0x7e, 0xa4, 0x3d, 0x6c, 0x2b, 0xe5, 0xde, 0x58, 0x41, 0x70, + 0x23, 0x16, 0x34, 0x5e, 0x49, 0x26, 0x53, 0x8a, 0xf6, 0x0f, 0x19, 0x3e, 0x53, 0x68, 0x0a, 0x24, 0x38, 0x61, 0xc0, + 0xb6, 0x0b, 0x96, 0xe7, 0xb0, 0xd9, 0x40, 0x33, 0xfb, 0x91, 0xc0, 0xda, 0x0f, 0x90, 0x47, 0x12, 0x5f, 0xc5, 0xe9, + 0x82, 0xe6, 0x11, 0x2d, 0x10, 0x1e, 0x91, 0x33, 0x19, 0xb4, 0x11, 0x7e, 0x27, 0xe1, 0x47, 0x07, 0xe1, 0x33, 0x13, + 0xc0, 0x84, 0x83, 0xac, 0x89, 0x2a, 0xe3, 0x5a, 0x63, 0xf1, 0x11, 0x9e, 0x6f, 0xa9, 0x94, 0x53, 0xf0, 0x2e, 0x20, + 0x3c, 0xae, 0x85, 0x3b, 0xf1, 0x35, 0xb1, 0x24, 0xf1, 0x5e, 0x50, 0xfa, 0x5d, 0x9c, 0x7e, 0xa4, 0x22, 0xb8, 0xc1, + 0xed, 0xce, 0xe7, 0x58, 0xb9, 0xa0, 0xf7, 0xda, 0xa8, 0x5b, 0xc6, 0xaa, 0x4e, 0xa5, 0x8e, 0x11, 0x80, 0x90, 0xad, + 0xfb, 0x62, 0x60, 0xc7, 0xf7, 0xc4, 0x86, 0xc3, 0x4a, 0xc4, 0xd7, 0x3e, 0xaa, 0xc7, 0x45, 0x59, 0x76, 0x15, 0xa7, + 0x2c, 0xf1, 0x24, 0x9d, 0xcd, 0xd3, 0x58, 0x52, 0xcf, 0xac, 0xd7, 0x8b, 0x61, 0x20, 0xbf, 0x54, 0x19, 0x12, 0xc7, + 0xe0, 0x4c, 0x6c, 0xc0, 0x09, 0xce, 0x4a, 0x00, 0xd1, 0x29, 0xa3, 0x76, 0xbc, 0xae, 0x82, 0x5f, 0xeb, 0xf1, 0xbd, + 0x66, 0x1b, 0x1c, 0x61, 0x43, 0x25, 0x9e, 0x73, 0x9c, 0x11, 0x10, 0xa2, 0x9d, 0xbe, 0x7f, 0x9c, 0x5f, 0x4d, 0x7a, + 0x3e, 0xc4, 0x66, 0x38, 0x79, 0xab, 0xfc, 0x42, 0xd0, 0x60, 0x4a, 0x5a, 0xdd, 0xe9, 0x31, 0xed, 0x4e, 0x1b, 0x0d, + 0xab, 0x43, 0xa7, 0x44, 0x0c, 0xa6, 0xba, 0x7b, 0x8c, 0x13, 0xbc, 0x20, 0xcd, 0x36, 0x9e, 0x90, 0x96, 0xea, 0xd2, + 0x9d, 0x1c, 0xa7, 0x66, 0x9a, 0x83, 0x83, 0x80, 0x87, 0x69, 0x9c, 0xcb, 0x2f, 0xc1, 0xd8, 0x27, 0x13, 0x9c, 0x10, + 0x1e, 0xd2, 0x1b, 0x3a, 0x0a, 0x52, 0x84, 0x13, 0xc3, 0x69, 0x50, 0x17, 0x4d, 0x88, 0xd3, 0x0c, 0x8c, 0x08, 0xf2, + 0xb6, 0x9f, 0x0c, 0xda, 0x43, 0x42, 0x88, 0xbf, 0xd7, 0x6c, 0xfa, 0x7d, 0x4e, 0x16, 0x32, 0x82, 0x12, 0x47, 0x55, + 0x26, 0x73, 0x28, 0xea, 0x38, 0x45, 0xc1, 0x0b, 0x19, 0x4a, 0x9a, 0xcb, 0x00, 0x8a, 0xc1, 0xfc, 0xcf, 0x2d, 0x61, + 0xfb, 0xc7, 0x87, 0x7e, 0x03, 0x4a, 0x15, 0x71, 0x22, 0xcc, 0xc9, 0x25, 0x8a, 0x92, 0xc1, 0xd1, 0xd0, 0xe5, 0xff, + 0xaa, 0x10, 0x26, 0xbf, 0xec, 0x27, 0x83, 0x96, 0x9a, 0xbc, 0xe7, 0xf7, 0x03, 0x4e, 0x72, 0xad, 0xa0, 0xf5, 0xf3, + 0xe8, 0xad, 0x5a, 0x2a, 0x8a, 0x0c, 0x70, 0x66, 0xde, 0x05, 0x69, 0x76, 0xa2, 0x60, 0xe1, 0x2e, 0xa2, 0x09, 0x93, + 0x19, 0x2c, 0xe0, 0x98, 0x40, 0x7b, 0xcc, 0x09, 0xcc, 0x58, 0x75, 0xbb, 0x8c, 0xcc, 0xf3, 0x03, 0xff, 0x41, 0xff, + 0x4a, 0x46, 0x13, 0xa9, 0xa7, 0xbf, 0x92, 0xab, 0x15, 0xfc, 0x3f, 0x91, 0x7d, 0x4e, 0x2e, 0x55, 0xd1, 0xc2, 0x14, + 0xcd, 0xa1, 0xe8, 0x6d, 0x04, 0xa0, 0xe2, 0xbc, 0x54, 0xb2, 0xf4, 0x9e, 0x5c, 0x11, 0x05, 0xfb, 0xc1, 0x81, 0x18, + 0x4c, 0x1b, 0xed, 0x21, 0xf8, 0xf7, 0x85, 0xcc, 0xbf, 0x63, 0x72, 0x1a, 0xf8, 0x87, 0x3d, 0x1f, 0xf5, 0x7d, 0x0f, + 0xb6, 0xb6, 0x9b, 0x35, 0x88, 0xc6, 0x70, 0xda, 0x78, 0x23, 0xa3, 0x45, 0x8f, 0xb4, 0xfa, 0x01, 0x33, 0xfe, 0x3c, + 0x84, 0x53, 0xc3, 0x38, 0x5b, 0x78, 0x81, 0x1a, 0x52, 0x36, 0xec, 0xf3, 0x02, 0x35, 0x66, 0x8d, 0x2b, 0x14, 0xa5, + 0x8d, 0x59, 0x23, 0x58, 0x10, 0x42, 0x9a, 0x9d, 0xb2, 0x9b, 0x95, 0x7e, 0x53, 0x14, 0x5d, 0x59, 0x67, 0xe7, 0x40, + 0x1d, 0x87, 0xac, 0x11, 0x88, 0x01, 0x1d, 0xae, 0x56, 0xfe, 0x71, 0xbf, 0xe7, 0xa3, 0x46, 0x60, 0x09, 0xed, 0xd0, + 0x52, 0x1a, 0x42, 0x98, 0x0d, 0x0b, 0x13, 0x4a, 0x7a, 0x59, 0x0b, 0x1b, 0x2d, 0xab, 0xc3, 0xee, 0xf0, 0x00, 0x5a, + 0x94, 0x76, 0x8c, 0xd6, 0x57, 0xe7, 0xb0, 0x4c, 0x4b, 0xcc, 0x19, 0x69, 0x61, 0x4e, 0xac, 0xef, 0x7a, 0x4a, 0x64, + 0x45, 0xf0, 0x29, 0xa9, 0x9a, 0xe3, 0x41, 0x8c, 0x93, 0x21, 0x79, 0xad, 0xed, 0x91, 0xae, 0xf5, 0x8b, 0xd3, 0x94, + 0xbc, 0x5c, 0x8b, 0xde, 0xc6, 0x10, 0x5b, 0xb9, 0x0e, 0x47, 0x0b, 0x21, 0x68, 0x26, 0xdf, 0xf0, 0xc4, 0xa8, 0x69, + 0x34, 0x05, 0x4b, 0x09, 0xc2, 0xb2, 0x18, 0x74, 0xb4, 0x8e, 0x3d, 0x19, 0x8b, 0x8d, 0xea, 0x09, 0x59, 0x68, 0xf5, + 0x49, 0x05, 0x6b, 0xbb, 0x13, 0x63, 0x17, 0x07, 0x08, 0x2f, 0x4c, 0x14, 0x37, 0x08, 0xc3, 0x70, 0x12, 0x8e, 0xa0, + 0x1a, 0x26, 0xc8, 0x51, 0xa1, 0xce, 0x51, 0x90, 0x93, 0xeb, 0x30, 0xa3, 0x37, 0x6a, 0xd6, 0x00, 0x55, 0x92, 0xd9, + 0x1e, 0xaf, 0xe3, 0x69, 0x57, 0xb1, 0x9b, 0x3c, 0xcc, 0x78, 0x42, 0x01, 0x3d, 0x10, 0xb7, 0x37, 0x45, 0xd3, 0x38, + 0x77, 0xe3, 0x53, 0x15, 0x7c, 0x03, 0xd7, 0x79, 0x3d, 0x01, 0x8f, 0xaf, 0xd2, 0xb5, 0xca, 0xc6, 0xda, 0x0d, 0x8e, + 0x10, 0x1b, 0x07, 0x93, 0x10, 0xe2, 0x7a, 0x8a, 0x84, 0x24, 0x98, 0x72, 0x13, 0x97, 0xa8, 0x66, 0xe5, 0x98, 0x57, + 0x24, 0x19, 0xf0, 0x46, 0x43, 0x79, 0xa1, 0x17, 0x9a, 0x24, 0x26, 0x08, 0x5f, 0x95, 0x67, 0xcb, 0xb6, 0x7b, 0x2b, + 0x49, 0x7d, 0xaa, 0xe0, 0xaa, 0xee, 0xce, 0x6d, 0x48, 0x89, 0x94, 0xa7, 0x50, 0x06, 0x33, 0x84, 0x9f, 0x91, 0xc3, + 0x60, 0x10, 0xf6, 0xff, 0x32, 0x44, 0xfd, 0x20, 0xfc, 0x33, 0x3a, 0xd4, 0x9c, 0xe3, 0x0a, 0x75, 0x53, 0x3d, 0xc7, + 0x52, 0xc5, 0x2f, 0xdb, 0x58, 0x79, 0x12, 0xa3, 0x0c, 0x67, 0xf1, 0x8c, 0x46, 0xcf, 0xe0, 0x90, 0x5b, 0xc2, 0x79, + 0x2b, 0x31, 0x50, 0x52, 0xf4, 0xcc, 0xf0, 0x92, 0xd0, 0xef, 0xbf, 0x92, 0xe5, 0x53, 0xdf, 0xef, 0x3f, 0xaf, 0x9e, + 0xfe, 0xe2, 0xf7, 0x7f, 0x91, 0xd1, 0xcf, 0x85, 0xf1, 0x76, 0xd7, 0xe6, 0x78, 0x6c, 0xe7, 0x28, 0xf4, 0xd6, 0x38, + 0xb8, 0x5b, 0xa0, 0x4d, 0x47, 0xc7, 0x04, 0x15, 0x6c, 0x5c, 0x32, 0xa3, 0x3c, 0x94, 0xf1, 0x04, 0x90, 0xea, 0xec, + 0x41, 0xee, 0xc6, 0xf5, 0xab, 0x15, 0x03, 0xa9, 0x58, 0x7a, 0x05, 0x64, 0x4e, 0x7a, 0x2d, 0xb4, 0xac, 0xb5, 0x55, + 0x3a, 0x53, 0x3d, 0x8e, 0x5e, 0xf2, 0xe9, 0x2b, 0xd2, 0xea, 0x5e, 0x1d, 0x4f, 0xba, 0x57, 0x8d, 0x06, 0xca, 0x2d, + 0x69, 0x2d, 0x06, 0x57, 0x43, 0xfc, 0x35, 0x38, 0xf5, 0x5c, 0x5a, 0xc2, 0xb5, 0xe5, 0x75, 0xcc, 0xf2, 0x1a, 0x8d, + 0xac, 0x40, 0x5d, 0xa7, 0xeb, 0x44, 0x77, 0x2d, 0x0a, 0x8d, 0x93, 0x75, 0x52, 0x7b, 0x8a, 0x54, 0x09, 0x24, 0x43, + 0x11, 0x42, 0x6e, 0x24, 0xda, 0x3a, 0x2a, 0x8c, 0x09, 0xdd, 0xd5, 0x99, 0x05, 0xf6, 0xa9, 0xa5, 0x44, 0x00, 0x58, + 0x80, 0xae, 0xa5, 0x27, 0x78, 0x86, 0x17, 0x8d, 0xb6, 0x22, 0xf3, 0x66, 0xbb, 0x5b, 0x1f, 0xeb, 0x49, 0x35, 0x16, + 0x5e, 0x34, 0xc8, 0xac, 0xc4, 0x52, 0x91, 0x35, 0x1a, 0x45, 0x3d, 0xd8, 0x69, 0x4f, 0x6e, 0x2d, 0x00, 0x71, 0xb3, + 0x9e, 0x94, 0x61, 0x25, 0x6c, 0x25, 0x53, 0x59, 0xc8, 0xb2, 0x8c, 0x0a, 0x90, 0xa2, 0x44, 0x62, 0x56, 0x14, 0x95, + 0x64, 0x07, 0x31, 0x8a, 0x29, 0x11, 0xc0, 0x79, 0x94, 0xdd, 0x85, 0x33, 0xcc, 0xf1, 0x54, 0xf1, 0x0d, 0x42, 0xc8, + 0x99, 0x4d, 0x67, 0x91, 0x8a, 0x07, 0xa5, 0x84, 0x39, 0x32, 0x29, 0x27, 0x34, 0x3c, 0xdf, 0x3f, 0xe5, 0x77, 0xda, + 0x64, 0x03, 0x36, 0x8c, 0x54, 0xb3, 0xd4, 0x70, 0xae, 0x98, 0x7c, 0x08, 0x24, 0x2a, 0xa3, 0x23, 0xa1, 0x62, 0x80, + 0xcf, 0x99, 0xa0, 0x4a, 0x07, 0xdf, 0xb7, 0x76, 0x5f, 0x5a, 0x57, 0x20, 0x53, 0xd7, 0x7b, 0x03, 0x88, 0x8c, 0xc1, + 0xb9, 0x93, 0x91, 0x8d, 0x66, 0xe7, 0xfb, 0x27, 0x6f, 0xb7, 0xd9, 0xc0, 0xab, 0x95, 0xb1, 0x7e, 0x95, 0x6e, 0x83, + 0xe3, 0x0a, 0xd2, 0xd4, 0xfc, 0x88, 0x82, 0x54, 0xa9, 0x48, 0x71, 0x20, 0x80, 0x8a, 0xce, 0xf7, 0x4f, 0xde, 0x07, + 0x42, 0xf9, 0x96, 0x10, 0x76, 0x97, 0x1d, 0x70, 0x12, 0x4c, 0x09, 0x45, 0x7a, 0xed, 0x25, 0xeb, 0xe2, 0x8e, 0x00, + 0x8f, 0xa6, 0xaa, 0x12, 0x2c, 0x88, 0x01, 0x1b, 0x92, 0xd4, 0x60, 0x80, 0xa4, 0x08, 0xa7, 0x35, 0xbb, 0x8c, 0xc0, + 0x06, 0xa8, 0xb9, 0xce, 0x60, 0x27, 0x42, 0xad, 0xfa, 0x21, 0x9c, 0xaa, 0x59, 0x65, 0xa1, 0x85, 0xc7, 0xb3, 0x8d, + 0xac, 0xb4, 0xca, 0x1c, 0xfd, 0x16, 0x6c, 0x27, 0xfb, 0xf0, 0x86, 0x58, 0x4b, 0xc2, 0x14, 0x3c, 0xb7, 0xe9, 0x63, + 0xe7, 0xfb, 0x27, 0xaf, 0x4d, 0x06, 0xd9, 0x3c, 0xb6, 0xfc, 0x7e, 0xc3, 0xc4, 0x3c, 0x79, 0x1d, 0x56, 0xb5, 0xaa, + 0xf1, 0xf9, 0xfe, 0xc9, 0x87, 0x6d, 0xcd, 0xa0, 0xbc, 0x58, 0x54, 0x36, 0xbe, 0x82, 0x6f, 0x49, 0xd3, 0x68, 0x69, + 0x84, 0x43, 0xc4, 0x0a, 0xac, 0x04, 0x52, 0x94, 0x17, 0xa5, 0x6b, 0xe4, 0x39, 0xce, 0x88, 0x0a, 0x03, 0xd5, 0x77, + 0xcd, 0xa8, 0x79, 0x8c, 0x67, 0x67, 0x23, 0x3e, 0xa7, 0x3b, 0x62, 0x43, 0x37, 0x28, 0x64, 0x33, 0x48, 0x9d, 0x51, + 0xa0, 0x33, 0xbc, 0xd7, 0x42, 0xdd, 0xba, 0xf8, 0xca, 0x14, 0x91, 0xf2, 0x9a, 0x6c, 0xc1, 0x53, 0xd2, 0xc2, 0x29, + 0x69, 0xe1, 0x98, 0xe4, 0x83, 0x96, 0x16, 0x10, 0xdd, 0xb8, 0x1c, 0x57, 0x8b, 0x19, 0xc8, 0x0a, 0x33, 0xa7, 0x55, + 0x0b, 0xe0, 0xa4, 0x1b, 0x2b, 0xdf, 0xa3, 0x92, 0xe9, 0x89, 0x22, 0x8b, 0xf7, 0x01, 0xc7, 0x5c, 0x0d, 0x7c, 0xc6, + 0x2e, 0x53, 0x48, 0x2c, 0x81, 0x55, 0x61, 0x89, 0xa2, 0xb2, 0x69, 0xdb, 0x34, 0x8d, 0x43, 0xb5, 0x4f, 0x1c, 0xc7, + 0x21, 0x70, 0x6e, 0x1c, 0x9b, 0x3c, 0x9c, 0x7c, 0xb3, 0xcb, 0xe3, 0x83, 0x83, 0x40, 0x77, 0xfa, 0x52, 0x06, 0xdc, + 0xd6, 0x57, 0x91, 0xbb, 0x6f, 0x35, 0xaf, 0x48, 0x90, 0x82, 0xbf, 0xd1, 0x48, 0x87, 0x05, 0x84, 0xa1, 0x83, 0xb8, + 0x8e, 0x41, 0x0b, 0xbc, 0xd2, 0xf5, 0xea, 0xcb, 0x6f, 0x34, 0xca, 0x28, 0x6d, 0x1d, 0x5b, 0x37, 0x38, 0x2b, 0xae, + 0x82, 0x32, 0xf5, 0xa7, 0xb5, 0x91, 0x2f, 0x65, 0x41, 0x40, 0xcc, 0xa5, 0x59, 0x66, 0x17, 0xe3, 0x1c, 0x09, 0x06, + 0xed, 0xbe, 0x34, 0x59, 0x0b, 0x58, 0x65, 0x57, 0x99, 0x46, 0x96, 0x9d, 0x75, 0x50, 0x64, 0x1b, 0x41, 0x54, 0x0a, + 0x1a, 0x35, 0x0a, 0x43, 0xde, 0xef, 0x37, 0x73, 0x2e, 0x71, 0x8e, 0x8c, 0x93, 0x4b, 0x41, 0xa1, 0x90, 0xd5, 0x29, + 0x91, 0xf2, 0x92, 0xcc, 0x77, 0x93, 0xfc, 0x89, 0x43, 0xf2, 0xcf, 0x08, 0x75, 0xc8, 0x5f, 0xbb, 0x38, 0x42, 0x6e, + 0x9c, 0x0b, 0xb9, 0xad, 0x3a, 0x9d, 0x13, 0x70, 0xa2, 0xd5, 0x31, 0x5a, 0x0b, 0x2b, 0xee, 0x60, 0x28, 0xee, 0x09, + 0x51, 0x6e, 0x48, 0x6c, 0x63, 0xc0, 0x41, 0x15, 0x54, 0x83, 0xa9, 0xb7, 0xf9, 0xf4, 0x5c, 0x0e, 0x78, 0xf2, 0xe1, + 0xee, 0x78, 0xe8, 0xe9, 0x7c, 0xf3, 0xe4, 0x3a, 0xb9, 0x9f, 0xb0, 0x6a, 0xe7, 0xe0, 0xd6, 0x33, 0x41, 0x61, 0xfe, + 0x32, 0x8e, 0x5d, 0x67, 0x3e, 0x6b, 0x87, 0xd0, 0xca, 0x3f, 0x80, 0xb6, 0xdd, 0x56, 0x2d, 0xa8, 0x33, 0x2c, 0xf0, + 0x23, 0x9d, 0x81, 0x1a, 0x8b, 0x1d, 0xec, 0xe3, 0x44, 0x35, 0xa0, 0x59, 0xb2, 0xbd, 0xfa, 0x59, 0x61, 0xc8, 0x44, + 0x83, 0x86, 0x96, 0xc0, 0xff, 0x34, 0xc9, 0x03, 0xdd, 0x28, 0xb9, 0x00, 0x08, 0x9a, 0x2b, 0x3c, 0x55, 0x08, 0xf3, + 0xfd, 0xca, 0xfb, 0xfe, 0x72, 0x8f, 0x90, 0x79, 0xe5, 0x7d, 0x7c, 0x57, 0xa5, 0x5e, 0x01, 0x59, 0xa0, 0x08, 0xcc, + 0xc7, 0xb2, 0x40, 0x87, 0x2f, 0xcf, 0x6c, 0x73, 0x65, 0x42, 0x86, 0x95, 0xc6, 0xed, 0x84, 0x36, 0x95, 0x5b, 0x4e, + 0xd7, 0x5b, 0x34, 0xac, 0xd5, 0xee, 0x43, 0xed, 0x7b, 0xa9, 0x60, 0x84, 0xe7, 0xf7, 0xaa, 0xb5, 0x1d, 0xb7, 0xf8, + 0xb8, 0x9e, 0xbf, 0xb2, 0xb6, 0x29, 0x21, 0xcb, 0x72, 0x2a, 0xe4, 0x33, 0x3a, 0xe6, 0x02, 0x62, 0x16, 0x25, 0x4e, + 0x50, 0xb1, 0xef, 0xf8, 0xed, 0xd4, 0xfa, 0x9c, 0x40, 0xc1, 0xda, 0x02, 0xd5, 0xaf, 0x8f, 0x2a, 0x68, 0x7d, 0xbe, + 0xde, 0x6b, 0x7e, 0x70, 0xf0, 0xa1, 0x42, 0x93, 0x81, 0x52, 0x41, 0xe1, 0x30, 0x2d, 0xad, 0xd2, 0x98, 0x48, 0xee, + 0x7e, 0x50, 0x3a, 0x01, 0x2c, 0xc3, 0x70, 0x79, 0xcf, 0x4b, 0x22, 0x8b, 0xc9, 0x3a, 0x8b, 0x37, 0xce, 0x09, 0xe6, + 0x1a, 0x2e, 0xc0, 0xe1, 0xc1, 0xd4, 0xd6, 0xde, 0xa2, 0xbc, 0x4a, 0x86, 0x2d, 0x61, 0x38, 0x05, 0x64, 0x05, 0xca, + 0x0c, 0x71, 0x28, 0x70, 0xab, 0x59, 0x72, 0x0a, 0x7a, 0xe5, 0x14, 0xe7, 0xe1, 0x14, 0xd2, 0x5f, 0x6b, 0x47, 0x16, + 0x21, 0xac, 0x13, 0x73, 0x9c, 0x54, 0x82, 0x93, 0x97, 0xdb, 0x5c, 0xca, 0x96, 0xa8, 0xa9, 0x92, 0x3a, 0xaa, 0x05, + 0x2a, 0x3b, 0x84, 0x57, 0x01, 0x33, 0x8a, 0x9b, 0x8d, 0x9b, 0x01, 0x03, 0x7e, 0x26, 0x03, 0x1d, 0x8c, 0x02, 0x99, + 0xc1, 0xc3, 0x45, 0x50, 0x9b, 0xba, 0xcb, 0x55, 0x37, 0x6c, 0x10, 0x37, 0x75, 0xd1, 0xc4, 0x55, 0x5c, 0xef, 0xb4, + 0xe2, 0xa5, 0x63, 0x9d, 0x41, 0x2d, 0x2d, 0x17, 0xac, 0x12, 0x49, 0x9c, 0xe5, 0x8f, 0x75, 0x52, 0x74, 0xd9, 0x08, + 0x53, 0x05, 0xc6, 0x4b, 0xb5, 0x07, 0xb4, 0x00, 0xfa, 0x5a, 0x9e, 0x48, 0x67, 0x47, 0xad, 0x13, 0x5b, 0xcd, 0xe9, + 0x48, 0xfd, 0x77, 0x90, 0xea, 0xb2, 0x7e, 0xe6, 0x5f, 0x2a, 0x59, 0xc8, 0x70, 0x5e, 0x63, 0xec, 0x99, 0x62, 0xec, + 0x08, 0xf4, 0x34, 0x9b, 0xf8, 0xdd, 0x37, 0x19, 0x2f, 0xcc, 0x48, 0x39, 0x43, 0x62, 0x5f, 0x97, 0xd1, 0x72, 0xe7, + 0xf7, 0xda, 0x6e, 0x44, 0x8c, 0x40, 0x16, 0x10, 0x36, 0x9c, 0x3d, 0x43, 0x38, 0x6f, 0x34, 0xba, 0xf9, 0x31, 0xad, + 0x9c, 0x24, 0x15, 0x8c, 0x0c, 0x02, 0xba, 0x40, 0xf0, 0x35, 0x19, 0x0a, 0x21, 0x7f, 0x9b, 0x99, 0x9d, 0x83, 0xaf, + 0xfd, 0xe4, 0x5d, 0xe0, 0x72, 0x35, 0xb7, 0x6d, 0x19, 0x34, 0x85, 0xf5, 0x04, 0x55, 0xc0, 0xe5, 0xeb, 0xbb, 0x13, + 0x3c, 0x00, 0xee, 0xbd, 0x36, 0x86, 0x54, 0x34, 0xd4, 0x95, 0x9a, 0x25, 0x94, 0xa7, 0xaf, 0x8b, 0xaa, 0xac, 0x44, + 0x77, 0xb2, 0xae, 0xac, 0x8c, 0x59, 0x49, 0xf2, 0xa2, 0xc8, 0x69, 0x15, 0xde, 0x5f, 0x4b, 0xbf, 0x54, 0xc2, 0x65, + 0xd3, 0xdb, 0x7e, 0x3a, 0x27, 0x12, 0x3b, 0x84, 0xfa, 0xf5, 0xae, 0xd8, 0x47, 0x05, 0x26, 0x9c, 0x6b, 0x23, 0x14, + 0x7f, 0xde, 0x26, 0x14, 0x71, 0x66, 0x8e, 0xbc, 0x12, 0x88, 0xed, 0x7b, 0x08, 0x44, 0xe3, 0x66, 0xb7, 0x32, 0x11, + 0xd4, 0x91, 0x9a, 0x4c, 0xac, 0x6f, 0x29, 0xc9, 0x30, 0x33, 0xbb, 0xd1, 0xeb, 0xac, 0x56, 0x6c, 0xd0, 0x02, 0x37, + 0x92, 0xef, 0xc3, 0xcf, 0xb6, 0xfe, 0xe9, 0x70, 0x62, 0xed, 0x06, 0x0e, 0x58, 0x69, 0xb2, 0xa0, 0x10, 0x12, 0x9c, + 0x03, 0x95, 0x94, 0xa5, 0x68, 0xda, 0x50, 0x90, 0x21, 0x70, 0xc2, 0xca, 0x30, 0x13, 0x40, 0xac, 0x64, 0x85, 0x31, + 0x20, 0x83, 0xad, 0xb9, 0x7f, 0xd6, 0xbc, 0xfc, 0xb4, 0x26, 0x5a, 0x93, 0x2b, 0x5a, 0x7d, 0xa8, 0xe5, 0x1b, 0x18, + 0x08, 0x8c, 0x7e, 0xb8, 0xa7, 0x4c, 0xd0, 0x4a, 0x94, 0x23, 0x57, 0x0e, 0xe1, 0x16, 0x38, 0xd1, 0xf6, 0x3e, 0xe8, + 0x08, 0xef, 0x16, 0x69, 0x82, 0xb9, 0x43, 0xd7, 0x2f, 0x89, 0xac, 0xb1, 0x92, 0x29, 0x31, 0x96, 0x12, 0x8e, 0x15, + 0x99, 0x4a, 0x92, 0x0d, 0x5a, 0x43, 0x50, 0x40, 0xbb, 0xe9, 0x71, 0x56, 0x99, 0xc0, 0x69, 0xa3, 0x81, 0x62, 0x3b, + 0xeb, 0x74, 0xc0, 0x1a, 0xe9, 0x10, 0x53, 0x9c, 0x6a, 0xc3, 0xe4, 0xec, 0xe0, 0x20, 0x88, 0xab, 0x79, 0x07, 0xe9, + 0x10, 0x61, 0xbe, 0x5a, 0x05, 0x0a, 0xac, 0x18, 0xad, 0x56, 0xb1, 0x0b, 0x96, 0xaa, 0x86, 0x6e, 0xf3, 0xbe, 0x24, + 0x73, 0x25, 0x00, 0xe7, 0x00, 0x61, 0x83, 0x04, 0xb1, 0x71, 0xef, 0xc5, 0xe0, 0x8e, 0x6a, 0x64, 0x83, 0xb4, 0xd1, + 0x1e, 0x3a, 0x8c, 0x6b, 0x90, 0x0e, 0x49, 0x5c, 0xf0, 0x83, 0x83, 0xbd, 0xdc, 0x88, 0xc8, 0x9f, 0x40, 0x94, 0xfd, + 0xa4, 0x24, 0x8b, 0x1e, 0xd0, 0xdd, 0x8d, 0x75, 0x67, 0x40, 0x49, 0x51, 0x66, 0x5b, 0x6d, 0xbb, 0x5a, 0x16, 0x44, + 0xd9, 0x08, 0x9b, 0x60, 0x70, 0x1f, 0x2c, 0xfb, 0x92, 0xcc, 0x5f, 0xc9, 0x32, 0xc7, 0xfa, 0xe7, 0xad, 0x99, 0xd5, + 0x61, 0x18, 0xc6, 0x62, 0xa2, 0x62, 0x19, 0x36, 0x0c, 0xab, 0x88, 0xff, 0xc8, 0x80, 0xe9, 0x4c, 0x3c, 0x28, 0xe7, + 0x1a, 0x12, 0x0d, 0xbe, 0x55, 0x6d, 0xec, 0x5d, 0x92, 0x9f, 0xb6, 0x7a, 0x19, 0x34, 0x24, 0xcf, 0x7f, 0x2b, 0x24, + 0x0f, 0x0d, 0x24, 0x9a, 0x3c, 0xd6, 0x70, 0xb6, 0x03, 0x17, 0x3f, 0xc9, 0x35, 0x9c, 0xed, 0xc6, 0xad, 0xc5, 0xd4, + 0x2f, 0xbb, 0xe0, 0x73, 0x78, 0x83, 0x06, 0xb4, 0x2a, 0x70, 0xa0, 0x7c, 0xb4, 0xae, 0x7b, 0x69, 0x56, 0x0a, 0xc2, + 0x54, 0x92, 0x80, 0xd5, 0x0f, 0x40, 0xa5, 0x8d, 0x3a, 0x86, 0x2f, 0x8b, 0xe6, 0xc8, 0x71, 0x09, 0xd4, 0x53, 0x57, + 0x80, 0x9c, 0x8c, 0xb7, 0x7d, 0x7e, 0x70, 0x00, 0xb6, 0x01, 0x28, 0x71, 0xe1, 0x28, 0x9e, 0xcb, 0x85, 0x00, 0x55, + 0x2a, 0xb7, 0xbf, 0xa1, 0x18, 0x6e, 0x81, 0xa8, 0x32, 0xf8, 0x01, 0x05, 0xf3, 0x38, 0xcf, 0xd9, 0x95, 0x2e, 0x33, + 0xbf, 0x31, 0x27, 0x96, 0x94, 0x73, 0xad, 0x13, 0x66, 0xa8, 0x9b, 0x19, 0x3a, 0xad, 0xa3, 0xed, 0xc5, 0x15, 0xcd, + 0xe4, 0x2b, 0x96, 0x4b, 0x9a, 0xc1, 0xf2, 0x2b, 0x8a, 0x83, 0x15, 0xe5, 0x08, 0x0e, 0x6c, 0xad, 0x57, 0x9c, 0x24, + 0x77, 0x76, 0x91, 0x75, 0x1d, 0x68, 0x1a, 0x67, 0x49, 0xaa, 0x27, 0x71, 0xf3, 0x19, 0x6d, 0x0e, 0x67, 0xd9, 0xd2, + 0xcd, 0xa7, 0xa9, 0x94, 0x0d, 0xc5, 0xdd, 0x03, 0x46, 0xac, 0x24, 0xb0, 0xd2, 0xf3, 0x4e, 0xad, 0x05, 0x22, 0xde, + 0x3b, 0x36, 0xc1, 0x5d, 0x09, 0x96, 0x0e, 0x47, 0x0d, 0xeb, 0x70, 0x5a, 0xba, 0xf9, 0x72, 0xeb, 0x95, 0xb6, 0x6d, + 0xc2, 0x41, 0xd1, 0xc9, 0xe3, 0xdd, 0x96, 0xd5, 0x6b, 0x2b, 0x39, 0xac, 0xb4, 0x60, 0xf7, 0x65, 0xcc, 0x68, 0x69, + 0xc9, 0x0b, 0xd9, 0xa3, 0xb8, 0x2f, 0xc9, 0x73, 0xb8, 0x33, 0xf4, 0x52, 0xce, 0xd2, 0xb5, 0xab, 0x31, 0xdd, 0xfd, + 0x52, 0xfb, 0xdf, 0x97, 0xc1, 0x4b, 0xfc, 0x1e, 0x02, 0xbb, 0x5f, 0x55, 0xcd, 0x37, 0x03, 0xba, 0x5f, 0x55, 0x08, + 0xfa, 0x2a, 0xda, 0x68, 0xe7, 0x04, 0x72, 0x3b, 0xe1, 0xd3, 0xb0, 0xe5, 0x5b, 0x6d, 0xe9, 0x67, 0x1d, 0x46, 0xd2, + 0x99, 0x96, 0xea, 0x3c, 0xe0, 0x2a, 0x4f, 0x0d, 0xf2, 0xe5, 0xea, 0x16, 0x12, 0x35, 0x19, 0x86, 0x5a, 0x87, 0xdf, + 0xb5, 0x3d, 0x46, 0xc6, 0x64, 0xda, 0xce, 0xf8, 0x3a, 0x16, 0x72, 0x1f, 0x4e, 0x19, 0xdf, 0xb8, 0x87, 0x37, 0x25, + 0xe0, 0x41, 0xbb, 0xdf, 0x14, 0x8e, 0xb1, 0x9d, 0xeb, 0x7b, 0x40, 0xee, 0xf8, 0x84, 0x5b, 0xdd, 0xad, 0x6e, 0x65, + 0x7c, 0x0d, 0xf6, 0x3f, 0xc2, 0x53, 0x7b, 0x39, 0x8e, 0x1a, 0x0e, 0x4c, 0xa3, 0x65, 0x51, 0x3a, 0x05, 0xb8, 0x56, + 0xde, 0x04, 0xc2, 0xbc, 0x50, 0x01, 0xee, 0x1f, 0xf0, 0x37, 0x86, 0x25, 0x8e, 0x4b, 0x8e, 0x73, 0x72, 0x5f, 0x8e, + 0xa8, 0xc1, 0x2f, 0xe3, 0xf7, 0x40, 0xc7, 0x8a, 0x42, 0x0b, 0x4b, 0x45, 0xcf, 0xb9, 0x59, 0xc8, 0xce, 0xb4, 0x54, + 0x4c, 0xcb, 0x94, 0x1a, 0x35, 0xcd, 0x96, 0x3c, 0x4e, 0x6b, 0x65, 0xcb, 0xf2, 0x54, 0xd5, 0xe6, 0x45, 0x3b, 0xb0, + 0x58, 0x85, 0x16, 0x57, 0xab, 0xa0, 0x8e, 0x6a, 0xc2, 0x9c, 0x48, 0x06, 0xc2, 0xcc, 0xc9, 0xa8, 0xa8, 0x69, 0xd6, + 0xba, 0x4f, 0x80, 0xd6, 0x13, 0x8a, 0xac, 0x6e, 0x5e, 0x83, 0xc3, 0x75, 0x21, 0xe8, 0xee, 0xae, 0x4f, 0x01, 0xeb, + 0xd5, 0x95, 0x13, 0x39, 0x18, 0xfa, 0xb9, 0x4c, 0x95, 0xad, 0x72, 0x5a, 0xb7, 0xe0, 0x17, 0xdd, 0x91, 0x2c, 0x6b, + 0x50, 0xb7, 0x59, 0xef, 0x24, 0x1b, 0x3d, 0xe7, 0xbb, 0x92, 0x8d, 0x6a, 0xda, 0xee, 0x5e, 0x0b, 0xdd, 0x9d, 0x96, + 0xaa, 0xe7, 0xda, 0xde, 0xe4, 0x37, 0x4c, 0xd7, 0x06, 0xda, 0xd4, 0x68, 0xb6, 0x5c, 0xe5, 0xac, 0x28, 0xc6, 0xe5, + 0x65, 0x02, 0x95, 0xbb, 0x33, 0xd6, 0xf4, 0x6f, 0xac, 0x46, 0x75, 0x1d, 0x37, 0xf8, 0x81, 0x4c, 0x52, 0x7e, 0x19, + 0xa7, 0xef, 0x61, 0xbe, 0xaa, 0xf2, 0xe5, 0x6d, 0x22, 0x62, 0x49, 0x0d, 0x77, 0xa9, 0x60, 0xf8, 0xc1, 0x81, 0xe1, + 0x07, 0xcd, 0xa7, 0xab, 0xfe, 0x78, 0xf9, 0xaa, 0x1c, 0x20, 0x1a, 0x17, 0x96, 0x65, 0x9c, 0xcb, 0xed, 0x73, 0xac, + 0xb3, 0xb0, 0xf3, 0x92, 0x85, 0x9d, 0xcb, 0x60, 0x7d, 0xa8, 0x20, 0xf8, 0x66, 0xfb, 0x28, 0x9b, 0x9c, 0xed, 0x9b, + 0xea, 0xe0, 0x7f, 0x13, 0xdd, 0xd9, 0xc7, 0xe1, 0x72, 0x47, 0xe1, 0x91, 0x4a, 0x57, 0xd1, 0x20, 0xbf, 0x83, 0xb4, + 0x03, 0x49, 0x7a, 0xce, 0x9d, 0x83, 0x4a, 0x4e, 0xd9, 0x44, 0xa0, 0x60, 0xb4, 0xc8, 0x25, 0x9f, 0x99, 0x31, 0x73, + 0x73, 0xcd, 0x48, 0x55, 0x82, 0x2b, 0x5a, 0x45, 0xdb, 0xa3, 0xfa, 0x45, 0xae, 0xe5, 0x47, 0x96, 0x25, 0x51, 0x8e, + 0x8d, 0x14, 0xc9, 0xa3, 0xac, 0x20, 0x36, 0xd9, 0x78, 0xb3, 0x0e, 0x8f, 0x59, 0xc6, 0xf2, 0x29, 0x15, 0x01, 0x47, + 0xcb, 0x5d, 0x93, 0x71, 0x08, 0xc8, 0xe8, 0xc9, 0xf0, 0xb7, 0xd5, 0x85, 0xbf, 0x10, 0x46, 0x03, 0x3f, 0xd0, 0x8c, + 0xca, 0x29, 0x4f, 0x20, 0x31, 0x25, 0x4c, 0xca, 0x1b, 0x4d, 0x07, 0x07, 0x7b, 0x81, 0xaf, 0xdc, 0x12, 0x70, 0xf5, + 0xdb, 0xad, 0x41, 0xfd, 0x25, 0x5c, 0xcf, 0xa9, 0xa6, 0xa6, 0x68, 0x49, 0xd7, 0x6f, 0xb2, 0xc8, 0xf0, 0x23, 0xbd, + 0xc5, 0x02, 0x15, 0x45, 0xa4, 0xa1, 0xf6, 0xc7, 0x8c, 0xa6, 0x89, 0x8f, 0x3f, 0xd2, 0xdb, 0xa8, 0xbc, 0x2d, 0xae, + 0x2e, 0x37, 0xab, 0x0d, 0xf4, 0xf9, 0x75, 0xe6, 0xe3, 0x6a, 0x92, 0x68, 0x59, 0x60, 0x2e, 0xd8, 0x04, 0x88, 0xf3, + 0x6f, 0xf4, 0x36, 0xd2, 0xe3, 0x31, 0xe7, 0xb2, 0x1e, 0x5a, 0x5a, 0xd4, 0x87, 0x4e, 0xb1, 0xbb, 0x0d, 0xc6, 0xa0, + 0x18, 0xa8, 0xbe, 0x43, 0x52, 0x6b, 0x57, 0x99, 0x87, 0x08, 0x15, 0xf7, 0x5d, 0x0a, 0xfe, 0xc2, 0x15, 0x6d, 0xb2, + 0x96, 0xfa, 0xba, 0xd6, 0x89, 0x42, 0x87, 0x2a, 0xd7, 0xe3, 0x3c, 0x10, 0xf6, 0xd4, 0x99, 0x3b, 0x08, 0x8e, 0x23, + 0xec, 0x0b, 0x69, 0x06, 0x8d, 0xbe, 0xd5, 0x29, 0x21, 0x55, 0x24, 0xe9, 0x75, 0xd5, 0xcf, 0x3b, 0x0f, 0x00, 0xef, + 0x90, 0xd2, 0x12, 0xab, 0xeb, 0x98, 0x85, 0x4d, 0x17, 0xfd, 0x4e, 0x92, 0x60, 0x69, 0x97, 0x10, 0x09, 0x17, 0x8b, + 0xb2, 0x00, 0x2a, 0x34, 0xf4, 0xa5, 0x33, 0x00, 0xd9, 0x38, 0x60, 0x1b, 0x52, 0x33, 0x53, 0x52, 0x33, 0x74, 0x30, + 0xbe, 0x43, 0x4a, 0x52, 0x85, 0x0c, 0xa5, 0x44, 0x2a, 0xa1, 0x67, 0x36, 0xd7, 0x90, 0x90, 0xbb, 0xa1, 0xe5, 0xf5, + 0x39, 0xbd, 0xe7, 0x59, 0x0d, 0xac, 0x40, 0x8d, 0x83, 0x8a, 0x08, 0x96, 0x44, 0x75, 0x83, 0xc2, 0xba, 0x73, 0x84, + 0xcd, 0x6f, 0x0d, 0x78, 0x68, 0x97, 0x45, 0x2c, 0x4a, 0x82, 0x29, 0x5a, 0x8a, 0x60, 0x8a, 0x33, 0xc8, 0x47, 0xe4, + 0x45, 0x09, 0x3f, 0x75, 0x77, 0xa3, 0x96, 0xad, 0xbc, 0xfd, 0x8a, 0x1f, 0x28, 0xf3, 0x12, 0x72, 0x34, 0xb1, 0xb0, + 0x3c, 0x45, 0x04, 0xea, 0xae, 0x9d, 0xb3, 0x6d, 0x5f, 0x99, 0x14, 0x1d, 0x03, 0xd8, 0x77, 0x32, 0x58, 0x3a, 0xab, + 0x70, 0xef, 0x72, 0x9b, 0x2b, 0x7f, 0x26, 0xd8, 0x57, 0x25, 0x91, 0x06, 0x39, 0x59, 0x93, 0x38, 0x77, 0xe7, 0x5a, + 0xfe, 0xbc, 0xa0, 0xe2, 0xf6, 0x8c, 0x42, 0xae, 0x33, 0x87, 0xbb, 0xbe, 0xd5, 0x36, 0x54, 0x79, 0xea, 0xfd, 0x4c, + 0x29, 0x2b, 0x45, 0xfd, 0x12, 0xe0, 0xfa, 0x15, 0xc1, 0x42, 0x45, 0x1b, 0x1d, 0x47, 0x8c, 0x3e, 0x2d, 0x74, 0xe7, + 0xe5, 0x49, 0xda, 0x65, 0xe0, 0x5f, 0xab, 0x30, 0x6d, 0x82, 0x05, 0x98, 0xbb, 0x17, 0x52, 0x07, 0xf9, 0x70, 0xdd, + 0x2b, 0x03, 0x45, 0x10, 0xbe, 0xcb, 0x76, 0x2f, 0x75, 0x5b, 0xd6, 0xec, 0xee, 0xa5, 0xd6, 0x82, 0x7e, 0x2a, 0xe5, + 0x07, 0x9b, 0x79, 0xca, 0xcb, 0xcb, 0xac, 0x28, 0x50, 0x01, 0xe0, 0x7d, 0xdf, 0x0d, 0x82, 0xef, 0x4d, 0xd2, 0x60, + 0x08, 0xb1, 0xd8, 0xb3, 0x94, 0x5b, 0x26, 0x5e, 0xcd, 0xff, 0xfd, 0xc6, 0xfc, 0xdf, 0x3b, 0x57, 0x4e, 0xc1, 0x34, + 0x9a, 0x64, 0x34, 0xb1, 0xac, 0x13, 0x69, 0x02, 0x54, 0x7a, 0x5b, 0x2e, 0xc9, 0xc7, 0x8b, 0x08, 0x34, 0xae, 0xe5, + 0x98, 0x67, 0xb2, 0x39, 0x8e, 0x67, 0x2c, 0xbd, 0x8d, 0x16, 0xac, 0x39, 0xe3, 0x19, 0xcf, 0xe7, 0xf1, 0x88, 0xe2, + 0xfc, 0x36, 0x97, 0x74, 0xd6, 0x5c, 0x30, 0xfc, 0x92, 0xa6, 0x57, 0x54, 0xb2, 0x51, 0x8c, 0xfd, 0x13, 0xc1, 0xe2, + 0xd4, 0x7b, 0x13, 0x0b, 0xc1, 0xaf, 0x7d, 0xfc, 0x8e, 0x5f, 0x72, 0xc9, 0xf1, 0xdb, 0x9b, 0xdb, 0x09, 0xcd, 0xf0, + 0x87, 0xcb, 0x45, 0x26, 0x17, 0x38, 0x8f, 0xb3, 0xbc, 0x99, 0x53, 0xc1, 0xc6, 0xdd, 0x11, 0x4f, 0xb9, 0x68, 0x42, + 0xca, 0xf6, 0x8c, 0x46, 0x29, 0x9b, 0x4c, 0xa5, 0x97, 0xc4, 0xe2, 0x63, 0xb7, 0xd9, 0x9c, 0x0b, 0x36, 0x8b, 0xc5, + 0x6d, 0x53, 0xb5, 0x88, 0x3e, 0x6b, 0x1d, 0xc5, 0x9f, 0x8f, 0x1f, 0x76, 0xa5, 0x88, 0xb3, 0x9c, 0xc1, 0x36, 0x45, + 0x71, 0x9a, 0x7a, 0x47, 0x8f, 0x5a, 0xb3, 0x7c, 0x4f, 0x07, 0xf2, 0xe2, 0x4c, 0x16, 0x17, 0xf8, 0x23, 0xc0, 0x1d, + 0x5e, 0xca, 0x0c, 0x5f, 0x2e, 0xa4, 0xe4, 0xd9, 0x72, 0xb4, 0x10, 0x39, 0x17, 0xd1, 0x9c, 0xb3, 0x4c, 0x52, 0xd1, + 0xbd, 0xe4, 0x22, 0xa1, 0xa2, 0x29, 0xe2, 0x84, 0x2d, 0xf2, 0xe8, 0xe1, 0xfc, 0xa6, 0x0b, 0x9a, 0xc5, 0x44, 0xf0, + 0x45, 0x96, 0x98, 0xb9, 0x58, 0x36, 0xa5, 0x82, 0x49, 0xb7, 0x42, 0xbd, 0xc2, 0x24, 0x4a, 0x59, 0x46, 0x63, 0xd1, + 0x9c, 0x40, 0x67, 0x30, 0x8b, 0x5a, 0x09, 0x9d, 0x60, 0x31, 0xb9, 0x8c, 0x83, 0x76, 0xe7, 0x09, 0xb6, 0x7f, 0xc3, + 0x47, 0xc8, 0x6b, 0x6d, 0x2f, 0x6e, 0xb7, 0x5a, 0x7f, 0x42, 0xdd, 0xb5, 0x59, 0x14, 0x40, 0x51, 0x7b, 0x7e, 0xe3, + 0xe5, 0x1c, 0x72, 0xda, 0xb6, 0xf5, 0xec, 0xce, 0xe3, 0x04, 0x12, 0x82, 0xa3, 0xce, 0xfc, 0xa6, 0x80, 0xd5, 0x45, + 0x3a, 0xc9, 0xd4, 0x2c, 0xd2, 0x3c, 0x2d, 0x7f, 0x2b, 0xc4, 0x4f, 0xb7, 0x43, 0xdc, 0xb1, 0x10, 0x57, 0x58, 0x6f, + 0x26, 0x0b, 0xa1, 0x62, 0xab, 0x51, 0x3b, 0xd7, 0x80, 0x4c, 0xf9, 0x15, 0x15, 0x16, 0x0e, 0xf5, 0xf0, 0x9b, 0xc1, + 0xe8, 0x6c, 0x07, 0xe3, 0xe9, 0xa7, 0xc0, 0x10, 0x59, 0xb2, 0xac, 0xef, 0x6b, 0x5b, 0xd0, 0x59, 0x77, 0x4a, 0x81, + 0x9e, 0xa2, 0x0e, 0xfc, 0xbe, 0x66, 0x89, 0x9c, 0xea, 0x9f, 0x8a, 0x9c, 0xaf, 0x75, 0xdd, 0xa3, 0x56, 0x4b, 0x3f, + 0xe7, 0xec, 0x17, 0x1a, 0xb5, 0x43, 0x68, 0x50, 0x5c, 0xe0, 0xbf, 0x95, 0x97, 0x79, 0xeb, 0xdc, 0x13, 0xff, 0xe0, + 0xde, 0xf2, 0x75, 0x92, 0x14, 0xab, 0x1b, 0xd1, 0x58, 0x58, 0x59, 0xa9, 0x85, 0x0f, 0xb8, 0xed, 0xd4, 0x79, 0x22, + 0xac, 0x57, 0xde, 0xe2, 0x64, 0xfd, 0x1f, 0x74, 0xde, 0x45, 0x04, 0x91, 0x0e, 0x27, 0xd9, 0x90, 0x77, 0xb3, 0x1e, + 0x69, 0x75, 0xb3, 0x66, 0x13, 0x05, 0x9c, 0x88, 0x41, 0x66, 0xd2, 0xf3, 0x02, 0xd6, 0xe7, 0xca, 0xd8, 0xce, 0x51, + 0xc4, 0xe1, 0xaa, 0xe9, 0x6a, 0x55, 0x85, 0x01, 0x98, 0xba, 0xae, 0xf1, 0x37, 0x69, 0x1a, 0xe0, 0xdc, 0xe1, 0xe4, + 0x99, 0x7d, 0xb1, 0x8b, 0xb0, 0xbc, 0x22, 0xe5, 0x23, 0x85, 0xb9, 0x70, 0x1e, 0xcb, 0x29, 0x78, 0x29, 0x4a, 0xf1, + 0x53, 0x25, 0x31, 0xf9, 0x87, 0x3e, 0xea, 0x8b, 0x32, 0xc3, 0x0d, 0x32, 0xf9, 0x44, 0x01, 0xa3, 0x7c, 0x23, 0x09, + 0x8c, 0x88, 0x7f, 0x21, 0xda, 0xa6, 0xb3, 0x16, 0xdd, 0xf8, 0xbe, 0x16, 0x1d, 0xcd, 0x24, 0x53, 0xb9, 0xdb, 0x36, + 0xe2, 0x30, 0x8d, 0xf3, 0xf3, 0x91, 0xbe, 0x2b, 0x99, 0x57, 0x37, 0x03, 0x62, 0x05, 0xbd, 0x36, 0xd2, 0xa8, 0x50, + 0xf6, 0xe8, 0xf7, 0x72, 0xa7, 0x7d, 0x22, 0xee, 0xb2, 0x4f, 0xca, 0x85, 0xe7, 0x7c, 0x21, 0x46, 0x10, 0x8e, 0x34, + 0x52, 0x6f, 0xd3, 0x71, 0xe3, 0x2b, 0x15, 0xc3, 0xc7, 0xd2, 0xc9, 0x04, 0x95, 0x98, 0xb9, 0x2f, 0x95, 0xa0, 0x2a, + 0xe4, 0xa5, 0xef, 0x6b, 0x18, 0x11, 0x67, 0x97, 0x04, 0x32, 0x3b, 0x51, 0x49, 0x8d, 0x41, 0x46, 0x7a, 0x59, 0xb8, + 0xc8, 0xd8, 0xcf, 0x0b, 0x7a, 0xce, 0x40, 0xd7, 0x64, 0x21, 0x4b, 0x54, 0xac, 0x09, 0x64, 0x5f, 0xb3, 0x0d, 0xc1, + 0x0b, 0x96, 0xe8, 0x8d, 0xc9, 0x54, 0xa5, 0xc9, 0x6d, 0xf2, 0x9b, 0x3e, 0xf8, 0x8b, 0x41, 0x3b, 0x60, 0x38, 0xe1, + 0xb3, 0x98, 0x65, 0x91, 0x72, 0xf9, 0x96, 0x83, 0x45, 0xd0, 0x1a, 0xb3, 0x24, 0xca, 0xcc, 0xf6, 0xb4, 0x51, 0xf8, + 0x13, 0x67, 0x99, 0xea, 0x5a, 0x74, 0xb9, 0x42, 0xa8, 0x46, 0x1f, 0xb1, 0x08, 0x3e, 0xd1, 0x72, 0x8d, 0x23, 0xec, + 0x56, 0x97, 0xd7, 0xce, 0x6b, 0x3b, 0xd0, 0x5a, 0xdb, 0x28, 0x6d, 0x04, 0xf0, 0xf5, 0xd2, 0x9c, 0x0b, 0x19, 0x04, + 0x53, 0x9c, 0x22, 0xd2, 0x9b, 0x2a, 0x67, 0xd7, 0x71, 0xaa, 0xfe, 0xeb, 0x37, 0xdb, 0x51, 0xbb, 0x34, 0xdf, 0x6b, + 0xb7, 0x81, 0x75, 0x72, 0x94, 0xb9, 0x51, 0xaa, 0x96, 0x51, 0xfe, 0xd6, 0x4b, 0xad, 0x9e, 0xcb, 0xe5, 0x62, 0x73, + 0xdc, 0xb4, 0xa8, 0x0a, 0x6a, 0x40, 0xa8, 0x60, 0xd1, 0x8e, 0xa9, 0x50, 0x51, 0xad, 0xbb, 0x54, 0x25, 0x2f, 0xb4, + 0x88, 0x3e, 0xdf, 0x5f, 0x0a, 0x33, 0x63, 0x71, 0xc1, 0xac, 0x93, 0xa9, 0x4e, 0x72, 0x85, 0xc1, 0x88, 0xa3, 0x87, + 0x6e, 0x6b, 0xa6, 0x61, 0xb9, 0x25, 0x62, 0x2b, 0xdd, 0x86, 0xfa, 0x91, 0x0a, 0x52, 0x85, 0xbb, 0x36, 0x06, 0x80, + 0x5c, 0xbd, 0x6d, 0x80, 0x81, 0xd9, 0x9a, 0x4b, 0xbb, 0x04, 0xd0, 0xc6, 0xc6, 0x14, 0x2e, 0xd2, 0x5c, 0xec, 0x2f, + 0xbf, 0x91, 0xc5, 0xa1, 0xd3, 0x54, 0xfd, 0x66, 0x09, 0xfc, 0x0f, 0x12, 0x70, 0xa9, 0x95, 0xd2, 0xc8, 0xff, 0xfa, + 0xed, 0xd9, 0x7b, 0x1f, 0x5f, 0xf2, 0xe4, 0x36, 0xf2, 0xa5, 0x58, 0x50, 0xbf, 0x40, 0xa1, 0x9c, 0xd2, 0xac, 0x7c, + 0x19, 0x0f, 0x4f, 0x69, 0x98, 0xf2, 0x89, 0xbe, 0x94, 0xb9, 0x6e, 0x24, 0x8f, 0x2e, 0x8e, 0xd5, 0x4b, 0xa6, 0x7a, + 0xc7, 0x52, 0xbf, 0xde, 0x4b, 0x0a, 0xf8, 0xd9, 0x83, 0x10, 0xca, 0xf1, 0xa1, 0x9c, 0xaa, 0x87, 0x33, 0x38, 0x30, + 0xea, 0x69, 0x7f, 0xb9, 0x41, 0x4c, 0x7d, 0x18, 0x62, 0xda, 0xd3, 0x4b, 0xc8, 0x55, 0xab, 0x8b, 0x68, 0x74, 0x71, + 0x51, 0x1c, 0x1f, 0xc2, 0x58, 0x87, 0x76, 0x5c, 0x80, 0xd0, 0xf6, 0x2f, 0x09, 0x0c, 0x5e, 0x36, 0x24, 0x48, 0x0f, + 0x86, 0x80, 0x79, 0x93, 0x1e, 0x2c, 0x12, 0x08, 0x0c, 0x7a, 0x27, 0x65, 0x89, 0x3a, 0xb1, 0xba, 0x68, 0x17, 0x04, + 0xba, 0x61, 0x45, 0xf7, 0xda, 0x9b, 0x5a, 0xed, 0xaf, 0x05, 0x29, 0x71, 0xa1, 0xbb, 0x40, 0xf0, 0xbf, 0x82, 0xec, + 0xf8, 0x50, 0xe3, 0xe1, 0xc2, 0x7d, 0xb5, 0x89, 0x7e, 0xed, 0x40, 0x89, 0xad, 0x41, 0x2e, 0xf1, 0x47, 0x89, 0x3f, + 0x5e, 0xa8, 0xa6, 0x56, 0x18, 0x81, 0x96, 0x04, 0x42, 0xbb, 0x65, 0xb5, 0x8e, 0x11, 0x4f, 0xd3, 0x78, 0x9e, 0xd3, + 0xc8, 0xfe, 0x30, 0x72, 0x09, 0xc4, 0xdb, 0xa6, 0x22, 0x60, 0xd2, 0x6b, 0x4e, 0x41, 0x5d, 0xd8, 0xd4, 0x52, 0xae, + 0x62, 0x11, 0x34, 0x9b, 0xa3, 0xe6, 0xe5, 0x04, 0x15, 0x72, 0xba, 0x74, 0xa5, 0xda, 0xe3, 0x56, 0xab, 0x0b, 0xb9, + 0x90, 0xcd, 0x38, 0x65, 0x93, 0x2c, 0x4a, 0xe9, 0x58, 0x16, 0x12, 0x6e, 0xa9, 0x2d, 0xad, 0x1a, 0x11, 0x76, 0x1e, + 0x09, 0x3a, 0xf3, 0x42, 0xf8, 0xf7, 0xee, 0x89, 0x0b, 0x99, 0x44, 0x99, 0x9c, 0x36, 0x55, 0xd6, 0x2d, 0xdc, 0x19, + 0x90, 0xd3, 0xda, 0xf3, 0xd2, 0x99, 0x68, 0x44, 0x41, 0xc5, 0x2a, 0xa4, 0xf0, 0xe4, 0x14, 0x4b, 0xe1, 0xb6, 0xcb, + 0xd0, 0x72, 0x63, 0x05, 0x9b, 0x92, 0xfe, 0x08, 0x15, 0xb9, 0x52, 0x8c, 0x37, 0x1b, 0x5b, 0x75, 0xa9, 0xfe, 0xb4, + 0x81, 0x3e, 0x47, 0xb1, 0x2b, 0xb4, 0x63, 0x79, 0xa9, 0x7b, 0xdc, 0x07, 0x99, 0x35, 0x95, 0x13, 0xbb, 0x3d, 0x50, + 0xc1, 0xb2, 0xf9, 0x42, 0x0e, 0x94, 0x53, 0x5b, 0xc0, 0x05, 0x89, 0x21, 0x76, 0x4a, 0x00, 0x07, 0xc3, 0xa5, 0x06, + 0x66, 0x14, 0xa7, 0xa3, 0x00, 0x20, 0xf2, 0x9a, 0xde, 0x53, 0x41, 0x67, 0xa8, 0x3b, 0x63, 0x59, 0x53, 0xd7, 0x3d, + 0x72, 0xd4, 0x92, 0xf0, 0x09, 0x3c, 0x15, 0xa1, 0x1a, 0x0d, 0xab, 0xdc, 0xd5, 0x2d, 0xb8, 0xbc, 0x18, 0x16, 0x45, + 0x57, 0xc8, 0x60, 0xf0, 0x3a, 0x40, 0x43, 0xfc, 0x8b, 0xf3, 0x72, 0x16, 0xdf, 0x1e, 0x15, 0x1f, 0x77, 0xd0, 0x8e, + 0x26, 0xee, 0x59, 0x50, 0xcd, 0x7e, 0x21, 0xd0, 0xf0, 0x5d, 0xe0, 0xd3, 0x7c, 0xde, 0xd4, 0xbc, 0xab, 0xa9, 0x48, + 0xd6, 0x87, 0xae, 0xc8, 0x78, 0x6a, 0xbf, 0x97, 0x4b, 0xc5, 0x96, 0xcc, 0x25, 0x0d, 0xed, 0x4c, 0x18, 0x96, 0x97, + 0x7a, 0xcc, 0xb3, 0x7b, 0x8d, 0x07, 0xd5, 0xf8, 0xc9, 0xc5, 0x49, 0x9d, 0xc7, 0x01, 0x5f, 0x2a, 0x5f, 0x60, 0x17, + 0xa7, 0x29, 0x4c, 0x78, 0x61, 0xd5, 0x17, 0xf7, 0xa5, 0x1f, 0x03, 0x39, 0x0c, 0x50, 0x61, 0xce, 0xe9, 0x33, 0xa5, + 0x52, 0x3a, 0x6f, 0xcd, 0xdb, 0x93, 0x36, 0x58, 0xa4, 0xa5, 0x2f, 0x83, 0x70, 0x77, 0x2d, 0x2f, 0xba, 0x5b, 0xf1, + 0x2e, 0xad, 0x90, 0x7a, 0x6a, 0x41, 0xc4, 0x17, 0x59, 0xe2, 0x7b, 0x7f, 0x19, 0xa5, 0x6c, 0xf4, 0x91, 0xf8, 0xfb, + 0xcb, 0x00, 0x6d, 0x5e, 0x7b, 0x54, 0x5c, 0xc1, 0x32, 0x6c, 0x54, 0x77, 0xa4, 0x67, 0xa1, 0xc3, 0x8b, 0xf5, 0x5b, + 0x71, 0xfc, 0xde, 0xfe, 0x12, 0x18, 0x8f, 0x9e, 0xa7, 0x77, 0x51, 0x9c, 0x57, 0xef, 0xba, 0xaa, 0xa0, 0x00, 0x34, + 0xeb, 0x72, 0x4f, 0x11, 0x15, 0xf1, 0x3f, 0x49, 0x69, 0xbe, 0xa7, 0x99, 0x1a, 0xc0, 0x29, 0x0d, 0x7f, 0xf3, 0xbd, + 0xbf, 0x94, 0x65, 0xb4, 0xf4, 0x68, 0xa8, 0x94, 0x0c, 0xe2, 0xc3, 0x5c, 0x60, 0xc6, 0x86, 0x09, 0x95, 0x31, 0x4b, + 0x75, 0x97, 0xae, 0x35, 0xc0, 0xd7, 0x56, 0xb4, 0x5a, 0xe5, 0xf5, 0xb5, 0xb0, 0x3a, 0x06, 0xd5, 0xca, 0x8e, 0x0f, + 0x2b, 0xb8, 0xd5, 0xca, 0xd4, 0x99, 0x74, 0x43, 0x83, 0xd5, 0x0a, 0x75, 0x9d, 0xf7, 0x97, 0x91, 0xba, 0x36, 0x04, + 0x00, 0x72, 0x03, 0x20, 0x04, 0xad, 0xf5, 0xb5, 0x98, 0x20, 0x25, 0x3c, 0x94, 0xb1, 0x98, 0x50, 0xb9, 0x86, 0xd8, + 0x54, 0xe7, 0xa8, 0x76, 0x6d, 0x80, 0x7a, 0x03, 0xda, 0xb8, 0x0e, 0xed, 0x05, 0x20, 0xbd, 0xbf, 0xbf, 0x64, 0x05, + 0xd9, 0x5f, 0xd2, 0x6c, 0xc4, 0x13, 0xfa, 0xe1, 0xdd, 0x97, 0x70, 0xc9, 0x91, 0x67, 0x60, 0x58, 0x4c, 0x11, 0x08, + 0x4e, 0xb5, 0x39, 0x5a, 0x84, 0x70, 0x25, 0x42, 0x34, 0x27, 0xf0, 0xd4, 0x5c, 0x0a, 0xc4, 0xc2, 0xf7, 0xfa, 0x1a, + 0x72, 0x9a, 0x68, 0x98, 0x49, 0xa6, 0x7a, 0xf1, 0xe2, 0xf8, 0x50, 0xb7, 0xd6, 0x22, 0x40, 0x37, 0x02, 0x24, 0xa8, + 0x73, 0x5a, 0xe1, 0x00, 0xf2, 0x9a, 0x5d, 0x3c, 0x24, 0xec, 0xaa, 0x24, 0x36, 0x75, 0x81, 0xaa, 0x77, 0x9c, 0xc6, + 0x97, 0x34, 0xed, 0xed, 0x2f, 0xb3, 0xd5, 0xaa, 0x55, 0x1c, 0x1f, 0xea, 0x47, 0xef, 0x58, 0xf1, 0x0d, 0xfd, 0xc2, + 0x4b, 0xb5, 0xc5, 0x70, 0x2b, 0x11, 0xb2, 0x3d, 0x6d, 0x9a, 0x53, 0x64, 0x06, 0x28, 0x7c, 0x4f, 0x25, 0x58, 0xa8, + 0x46, 0xa5, 0x42, 0x54, 0xf8, 0x1e, 0x4b, 0x36, 0xcb, 0x72, 0x49, 0xe7, 0x50, 0x3a, 0x5d, 0xad, 0xda, 0x85, 0xef, + 0xcd, 0x58, 0x06, 0x4f, 0xd9, 0x6a, 0xa5, 0x2e, 0xfc, 0xcd, 0x58, 0x16, 0xb4, 0x80, 0x6c, 0x7d, 0x6f, 0x16, 0xdf, + 0xa8, 0x05, 0xdb, 0x9a, 0xf8, 0x26, 0x68, 0x9b, 0xaa, 0xb0, 0xc4, 0x4f, 0x0e, 0x14, 0x57, 0xed, 0x68, 0x6a, 0x76, + 0x34, 0xc1, 0x0b, 0x7d, 0x95, 0x89, 0x04, 0x09, 0x49, 0xb7, 0xef, 0x68, 0x62, 0x77, 0x74, 0xb1, 0x63, 0x47, 0x17, + 0x77, 0xec, 0x68, 0x6c, 0x76, 0xcf, 0x2b, 0x71, 0xc7, 0x57, 0xab, 0x76, 0xab, 0xc2, 0xde, 0xf1, 0x61, 0xc2, 0xae, + 0x60, 0x37, 0x40, 0xcd, 0x93, 0x6c, 0x46, 0xb7, 0x13, 0x65, 0x1d, 0xc5, 0xf4, 0x57, 0x61, 0xb2, 0x44, 0x42, 0x56, + 0x47, 0x82, 0x4b, 0xd6, 0x65, 0xc8, 0xed, 0x8f, 0x24, 0x6c, 0x06, 0x68, 0xc8, 0x01, 0x0d, 0x53, 0x83, 0x86, 0x8b, + 0xe2, 0x1c, 0x24, 0x82, 0x5a, 0xcd, 0xbd, 0x28, 0x0f, 0x5a, 0xfb, 0xbd, 0xdd, 0x14, 0x06, 0xc1, 0xf0, 0x6b, 0x2e, + 0x12, 0x3f, 0xd2, 0x4d, 0x7f, 0x15, 0x62, 0x66, 0x2c, 0x33, 0xa9, 0x55, 0x3b, 0x29, 0xab, 0xaa, 0x77, 0xe9, 0xab, + 0xf3, 0xe8, 0x91, 0x6e, 0x31, 0x8f, 0xa5, 0xa4, 0x22, 0x33, 0x74, 0xea, 0xfb, 0x2e, 0xb6, 0xff, 0x7f, 0x91, 0xdc, + 0x16, 0x26, 0x12, 0x5b, 0x26, 0x62, 0xa9, 0xcd, 0x68, 0xe7, 0x86, 0xc1, 0x6b, 0x59, 0xb4, 0x57, 0xa9, 0xab, 0xb7, + 0xc8, 0xb5, 0x10, 0x74, 0x11, 0x18, 0x2c, 0x8b, 0x19, 0x4d, 0xce, 0x15, 0x37, 0xee, 0x8f, 0x2e, 0x8c, 0x76, 0xba, + 0x26, 0xdb, 0xaa, 0x0e, 0xd8, 0xff, 0x71, 0xd1, 0x79, 0xf2, 0xf0, 0xd4, 0xc7, 0x9a, 0xa1, 0xf3, 0xf1, 0xd8, 0x47, + 0x85, 0x77, 0xbf, 0x6e, 0xed, 0x87, 0x3f, 0x2e, 0xbe, 0x78, 0xd1, 0xfa, 0xa2, 0xec, 0x9c, 0xf9, 0xa8, 0xb8, 0x30, + 0xc1, 0x7c, 0x2b, 0x97, 0x1c, 0x78, 0xed, 0x8a, 0xc6, 0x71, 0xb6, 0x7b, 0x39, 0x03, 0x77, 0x39, 0xf9, 0x9c, 0xd2, + 0x04, 0xfb, 0x9e, 0x8f, 0x37, 0x4a, 0xcf, 0x53, 0x7a, 0x45, 0xed, 0x6b, 0x06, 0xb7, 0x4c, 0xb6, 0xa5, 0xc7, 0x88, + 0x2f, 0x32, 0x69, 0xb2, 0x1a, 0x0c, 0x5f, 0x75, 0x96, 0x74, 0xa1, 0xd6, 0xe0, 0x1a, 0x04, 0xb7, 0x5a, 0xa8, 0xd5, + 0x45, 0x55, 0x71, 0x81, 0x7d, 0x07, 0x80, 0x9d, 0x90, 0xf5, 0x77, 0x94, 0x47, 0x2d, 0xdc, 0xda, 0x05, 0x1b, 0x6e, + 0xa3, 0xc8, 0xf7, 0x87, 0x16, 0x4f, 0xca, 0x31, 0x59, 0x7b, 0x3b, 0xc4, 0x4e, 0x7c, 0x7d, 0x12, 0x03, 0x97, 0x02, + 0x06, 0xcb, 0x68, 0x9e, 0xef, 0x44, 0x40, 0xb9, 0x89, 0xd8, 0xaf, 0x5a, 0xfb, 0x3b, 0x46, 0xc1, 0x2d, 0x0c, 0x07, + 0x4c, 0x01, 0x5c, 0x86, 0x47, 0x4d, 0x2b, 0x3a, 0x1e, 0xd3, 0x51, 0xe9, 0xd7, 0x85, 0x40, 0xd7, 0x98, 0xa5, 0x12, + 0xe2, 0x3d, 0x2a, 0x10, 0xe3, 0xbf, 0xe1, 0x19, 0xf5, 0x91, 0x4d, 0xdd, 0x34, 0xf0, 0x1b, 0x61, 0xbf, 0x1d, 0x1e, + 0x3d, 0x62, 0x1d, 0x16, 0x33, 0xcb, 0x6a, 0x65, 0x7d, 0x3a, 0xb5, 0xf2, 0x3a, 0x22, 0xb9, 0x72, 0xda, 0xec, 0x3a, + 0x40, 0xf7, 0x3b, 0x26, 0xcb, 0xf6, 0x17, 0x8f, 0xda, 0xad, 0xc2, 0xc7, 0x3e, 0x0c, 0x77, 0xdf, 0x53, 0xa2, 0x7a, + 0x1d, 0x41, 0xaf, 0x45, 0xf6, 0x6b, 0xfa, 0x75, 0xda, 0x9f, 0xb7, 0x7d, 0xac, 0xdf, 0x1a, 0x80, 0x8a, 0x92, 0x19, + 0x8c, 0xc0, 0xd3, 0xf9, 0xbb, 0x97, 0x52, 0x1f, 0xfc, 0x7e, 0xf0, 0x3c, 0x6e, 0xb7, 0x7c, 0xec, 0xe7, 0x92, 0xcf, + 0x7f, 0xc5, 0x12, 0x8e, 0x7c, 0xec, 0x8f, 0x52, 0x9e, 0x53, 0x77, 0x0d, 0x5a, 0x77, 0xfd, 0xfd, 0x8b, 0xd0, 0x10, + 0xcd, 0x05, 0xcd, 0x73, 0xcf, 0x1d, 0xdf, 0x90, 0xd2, 0x27, 0x18, 0xe6, 0x56, 0x8a, 0xcb, 0xa9, 0x54, 0x78, 0xd1, + 0x17, 0xfa, 0x5d, 0xaa, 0xd2, 0x65, 0x1b, 0xc4, 0xa6, 0x44, 0x40, 0xc9, 0xd8, 0xb4, 0x2a, 0xf5, 0xc9, 0x99, 0xb7, + 0x1c, 0x3d, 0x3d, 0xb1, 0x0e, 0x00, 0x6f, 0x4e, 0x50, 0x2b, 0x99, 0xb1, 0xec, 0x7c, 0x4b, 0x69, 0x7c, 0xb3, 0xa5, + 0x14, 0xf4, 0xb3, 0x12, 0x3a, 0xf3, 0xae, 0x99, 0x4f, 0x63, 0xbd, 0xd2, 0x72, 0x5c, 0x10, 0x13, 0xe5, 0xa4, 0xfc, + 0x04, 0xa4, 0xce, 0x36, 0xa8, 0x11, 0x7e, 0xfb, 0x74, 0x50, 0xf2, 0xab, 0xa6, 0xa3, 0x37, 0x9f, 0xde, 0x73, 0x47, + 0xaf, 0xf9, 0x1d, 0xd8, 0x37, 0xf7, 0xc6, 0xd7, 0xd1, 0xbf, 0xa5, 0xd8, 0xa8, 0x1e, 0xe5, 0x16, 0x8c, 0x52, 0x36, + 0xab, 0x76, 0x61, 0x13, 0x4c, 0xa5, 0x74, 0x40, 0xf2, 0x90, 0x3b, 0x88, 0xd6, 0x3e, 0xce, 0xe1, 0x4a, 0x24, 0xbc, + 0x77, 0x62, 0x21, 0xe8, 0x79, 0xca, 0xaf, 0xd7, 0xdf, 0xa3, 0xb5, 0xbb, 0xf1, 0x94, 0x4d, 0xa6, 0xce, 0x3d, 0x27, + 0x4a, 0x4a, 0xd4, 0xdf, 0x39, 0x41, 0xf1, 0xaf, 0xff, 0x12, 0x86, 0xff, 0xfa, 0x2f, 0x9f, 0x6c, 0x0a, 0xc3, 0x17, + 0x17, 0x58, 0x56, 0xc3, 0xee, 0x26, 0xf0, 0xed, 0x33, 0xd5, 0x71, 0xbe, 0xbd, 0xcd, 0xc6, 0x26, 0x40, 0xfd, 0xc6, + 0x16, 0x6c, 0x14, 0xea, 0x03, 0xe0, 0xfd, 0x16, 0xc0, 0x60, 0x5d, 0x9f, 0x84, 0x0c, 0x1a, 0xfd, 0x2e, 0xd0, 0x2e, + 0x50, 0x74, 0xaf, 0x1d, 0xf9, 0xed, 0x18, 0xfe, 0xd4, 0x1a, 0x7e, 0x27, 0xf8, 0xc6, 0x1f, 0x30, 0xba, 0xb8, 0x28, + 0x13, 0xda, 0xdc, 0xae, 0x70, 0x61, 0xbe, 0xbf, 0x51, 0x62, 0x64, 0x7f, 0xd4, 0x42, 0x3d, 0x75, 0x1d, 0x8f, 0x8c, + 0x2e, 0x5e, 0xc3, 0x5b, 0x72, 0x8e, 0x2f, 0x85, 0x75, 0xa8, 0xde, 0xc1, 0x9f, 0x61, 0x88, 0xfa, 0xaa, 0xd4, 0xa0, + 0x1b, 0xcc, 0x19, 0x4a, 0x41, 0xe1, 0x07, 0x30, 0xf1, 0xe8, 0xc2, 0x58, 0x77, 0xa7, 0xda, 0xed, 0x11, 0xad, 0x93, + 0xb6, 0x71, 0x87, 0xd4, 0x90, 0x8e, 0xbd, 0xf7, 0x0a, 0x5f, 0xaa, 0x31, 0xad, 0xac, 0x69, 0xe5, 0x5a, 0x02, 0x55, + 0xfe, 0xa2, 0x50, 0x61, 0xf1, 0xbf, 0xee, 0x8a, 0xdc, 0xfd, 0xfd, 0xd3, 0x91, 0x3b, 0x7e, 0xaf, 0xc8, 0xdd, 0xdf, + 0xff, 0xf0, 0xc8, 0xdd, 0x5f, 0xdd, 0xc8, 0x1d, 0x6c, 0xe2, 0x97, 0xf7, 0x8a, 0xae, 0xd9, 0xc8, 0x07, 0xbf, 0xce, + 0x49, 0xdb, 0x68, 0xb2, 0x29, 0x9f, 0x40, 0x68, 0xed, 0xdf, 0x3f, 0x52, 0x96, 0xf2, 0x89, 0x1b, 0x27, 0x83, 0xb7, + 0xa4, 0x42, 0x60, 0xac, 0x6b, 0x23, 0x5a, 0x26, 0x36, 0xd5, 0x2a, 0x6f, 0x80, 0x34, 0x1f, 0xda, 0x37, 0x16, 0xf8, + 0x51, 0xf9, 0xd6, 0xa1, 0x16, 0xee, 0xd8, 0xe8, 0x55, 0xa4, 0x02, 0x5f, 0x65, 0xc7, 0x4e, 0xc3, 0x5e, 0x6f, 0x70, + 0x47, 0xe8, 0xda, 0xb7, 0xaa, 0xe8, 0xdb, 0xee, 0x4b, 0xff, 0xc7, 0x9b, 0xf6, 0xb3, 0x41, 0xbb, 0x7b, 0xd4, 0x9e, + 0xf9, 0x91, 0x0f, 0x52, 0x4a, 0x15, 0xb4, 0xba, 0x47, 0x47, 0x50, 0x70, 0xed, 0x14, 0x74, 0xa0, 0x80, 0x39, 0x05, + 0x8f, 0xa0, 0x60, 0xe4, 0x14, 0x3c, 0x86, 0x82, 0xc4, 0x29, 0x78, 0x02, 0x05, 0x57, 0x7e, 0x31, 0x60, 0x25, 0xb8, + 0x4f, 0xd0, 0x10, 0x6b, 0xe3, 0xc1, 0x96, 0x3d, 0xc1, 0x6d, 0x08, 0x99, 0xc5, 0x13, 0x95, 0xe9, 0x03, 0x0e, 0xb8, + 0x88, 0xe3, 0xeb, 0x29, 0xcd, 0x22, 0x08, 0x5a, 0x3e, 0x57, 0x32, 0x26, 0x94, 0xfc, 0x3d, 0x9b, 0x51, 0xfb, 0x7d, + 0x0a, 0x8b, 0x07, 0xcf, 0x47, 0x83, 0xd6, 0xb0, 0xe8, 0x96, 0x3b, 0xa7, 0x63, 0x6d, 0x26, 0xeb, 0x43, 0xef, 0x65, + 0x55, 0xa7, 0xa7, 0x6b, 0x96, 0x7b, 0xbe, 0x23, 0x66, 0xe3, 0x78, 0x03, 0xc6, 0x29, 0xbf, 0x6e, 0xde, 0xf8, 0xbd, + 0xed, 0x71, 0x1c, 0x80, 0xa8, 0x8c, 0xe3, 0xa8, 0x35, 0x95, 0x4f, 0xef, 0xe3, 0x49, 0xf9, 0xfb, 0x35, 0xcd, 0xf3, + 0x78, 0x62, 0x5a, 0xee, 0x8e, 0xdb, 0x28, 0x10, 0xdd, 0x98, 0x8d, 0x05, 0x02, 0x62, 0x2f, 0xb0, 0x59, 0x60, 0x4e, + 0x9b, 0x50, 0x0c, 0x60, 0xa7, 0x1e, 0xc5, 0x51, 0xd3, 0xd7, 0x8b, 0x64, 0x3c, 0xa9, 0x0a, 0x8e, 0xe7, 0x82, 0xaa, + 0x52, 0x8d, 0xe1, 0xe2, 0xf8, 0x10, 0x0a, 0x74, 0xf5, 0x8e, 0x68, 0x8d, 0xb5, 0xdd, 0x77, 0xc7, 0x6c, 0x3c, 0x1b, + 0xad, 0x71, 0xf3, 0x5b, 0xca, 0xe4, 0x96, 0xcd, 0x18, 0xc1, 0x67, 0xed, 0x11, 0xfc, 0x31, 0x11, 0x88, 0xcf, 0xc6, + 0xe3, 0xf1, 0x9d, 0xd1, 0x9b, 0xcf, 0x92, 0x31, 0xed, 0xd0, 0x47, 0x5d, 0xc8, 0x7d, 0x68, 0x1a, 0x9f, 0x7f, 0xbb, + 0x50, 0xb8, 0x5b, 0xde, 0xaf, 0x31, 0x84, 0x07, 0xe4, 0x74, 0x79, 0xff, 0x48, 0x4e, 0x31, 0x17, 0x74, 0x39, 0x8b, + 0xc5, 0x84, 0x65, 0x51, 0xab, 0x08, 0xaf, 0x4c, 0xe8, 0xe3, 0xb3, 0xa7, 0x4f, 0x9f, 0x16, 0x61, 0x62, 0x9f, 0x5a, + 0x49, 0x52, 0x84, 0xa3, 0x65, 0xb9, 0x8c, 0x56, 0x6b, 0x3c, 0x2e, 0x42, 0x66, 0x0b, 0x8e, 0x3a, 0xa3, 0xe4, 0xa8, + 0x53, 0x84, 0xd7, 0x4e, 0x8b, 0x22, 0xa4, 0xe6, 0x49, 0xd0, 0xa4, 0x96, 0x40, 0xf1, 0xa4, 0xd5, 0x2a, 0x42, 0x4d, + 0x68, 0x4b, 0xb0, 0x88, 0xf4, 0xcf, 0x28, 0x5e, 0x48, 0x0e, 0x2c, 0xb9, 0xcb, 0x65, 0x30, 0x38, 0x37, 0x2f, 0xa7, + 0xd0, 0x1f, 0x72, 0x28, 0xd0, 0x10, 0x7f, 0xe9, 0x06, 0x29, 0x80, 0x98, 0x55, 0x70, 0x82, 0xdb, 0x18, 0x46, 0xad, + 0x1a, 0x28, 0x4b, 0x55, 0x7f, 0x49, 0x78, 0x15, 0xbb, 0x00, 0xfe, 0x03, 0x2d, 0xf5, 0x5b, 0xd4, 0x24, 0xdd, 0xc1, + 0xf5, 0x29, 0xfd, 0x24, 0xd7, 0xbf, 0xbd, 0x0f, 0xd3, 0xa7, 0xf4, 0x8f, 0x66, 0xfa, 0xe6, 0x55, 0xa3, 0x9a, 0xe9, + 0x6b, 0xb6, 0x36, 0x93, 0xc4, 0x1f, 0x4d, 0xe9, 0xe8, 0xe3, 0x25, 0xbf, 0x69, 0xc2, 0x91, 0x10, 0xbe, 0xe2, 0xa7, + 0xfb, 0xbf, 0x35, 0xd9, 0xc2, 0x0e, 0xe6, 0x7c, 0x07, 0x42, 0x89, 0xcd, 0xb7, 0x19, 0xf1, 0xdf, 0x5a, 0xb3, 0x4a, + 0x97, 0x8c, 0xc7, 0xc4, 0x7f, 0x3b, 0x1e, 0xfb, 0xf6, 0x8a, 0x5d, 0x2c, 0xa9, 0x6a, 0xf5, 0xa6, 0x56, 0xa2, 0x5a, + 0x7d, 0xf1, 0x85, 0x5b, 0xe6, 0x16, 0x98, 0x10, 0x87, 0x1b, 0xce, 0x30, 0x35, 0x09, 0xcb, 0xe1, 0xa8, 0xc1, 0xe7, + 0x29, 0xea, 0xef, 0xf8, 0x13, 0xb5, 0xd7, 0x31, 0x97, 0x00, 0x6f, 0x79, 0x87, 0xf4, 0xfa, 0xfd, 0xf2, 0x09, 0xb5, + 0xe9, 0x6e, 0xcf, 0x6e, 0xbf, 0x4c, 0x82, 0x99, 0x44, 0x05, 0xcb, 0xdf, 0x66, 0x6b, 0x77, 0x47, 0x34, 0x8c, 0x84, + 0xb8, 0xcb, 0x2a, 0x24, 0x9f, 0x4c, 0x52, 0xf8, 0x40, 0xc8, 0xb2, 0xf6, 0xde, 0x51, 0xdd, 0xbd, 0x5f, 0x5b, 0x6f, + 0xe4, 0x76, 0x34, 0x6f, 0xe9, 0x54, 0xdf, 0x2b, 0xd2, 0x39, 0xc7, 0x57, 0xe6, 0xc3, 0x35, 0xca, 0x22, 0x5b, 0x1a, + 0xfe, 0xbf, 0xd4, 0x99, 0xaa, 0x12, 0xb2, 0x34, 0xf4, 0xc0, 0x49, 0x51, 0x98, 0x1c, 0xff, 0x84, 0xe5, 0x73, 0x78, + 0x1f, 0xa6, 0xee, 0x49, 0x3f, 0xc5, 0xc2, 0xf3, 0x6b, 0x27, 0x8e, 0x50, 0xdb, 0xae, 0xc2, 0x06, 0x12, 0xb4, 0xab, + 0x76, 0x26, 0x0b, 0xdf, 0x78, 0x7c, 0x2d, 0x12, 0x7d, 0x4f, 0xe3, 0x53, 0x47, 0x38, 0x9c, 0x15, 0x82, 0xab, 0xbf, + 0xdc, 0x10, 0x5b, 0x65, 0x0b, 0x0a, 0x37, 0x4e, 0xa6, 0x6a, 0x34, 0xb6, 0x94, 0x57, 0x3e, 0x9f, 0xc7, 0x99, 0x66, + 0xa3, 0xc4, 0xd7, 0xfc, 0x60, 0x7f, 0x59, 0xed, 0x7c, 0xe1, 0x5b, 0xb0, 0x35, 0xf1, 0xf6, 0x8e, 0x0f, 0xa1, 0x43, + 0xcf, 0xab, 0x81, 0x9e, 0x6d, 0x38, 0xf3, 0x3f, 0x11, 0x56, 0xbf, 0x08, 0xf3, 0x6b, 0x1c, 0xe6, 0xd7, 0xde, 0x9f, + 0x97, 0xcd, 0x6b, 0x7a, 0xf9, 0x91, 0xc9, 0xa6, 0x8c, 0xe7, 0x4d, 0x50, 0xf8, 0x95, 0x5f, 0xce, 0xb0, 0x67, 0x95, + 0x1c, 0xa6, 0x6f, 0xc8, 0x77, 0x17, 0x39, 0x44, 0xdf, 0x95, 0xda, 0x1a, 0x65, 0x3c, 0xa3, 0xdd, 0x7a, 0x12, 0xa0, + 0x1b, 0xcc, 0xb5, 0xd8, 0x1a, 0x2e, 0x39, 0x44, 0xeb, 0xe5, 0x6d, 0xd4, 0x32, 0x6c, 0xbd, 0x65, 0x23, 0xb5, 0xad, + 0xad, 0xed, 0x23, 0x83, 0xdc, 0x86, 0x92, 0x5e, 0x62, 0x33, 0x62, 0xbd, 0x2b, 0xe2, 0xfc, 0xa9, 0x94, 0x38, 0xf0, + 0xe6, 0xd9, 0xbf, 0x4e, 0x2e, 0xe1, 0x7a, 0xb1, 0x4a, 0x89, 0xbb, 0x0f, 0x64, 0x51, 0x3c, 0x96, 0x54, 0xe0, 0xfb, + 0xb4, 0xbc, 0x54, 0xb7, 0x57, 0x96, 0x20, 0x66, 0xa2, 0xf6, 0xd3, 0xf9, 0xcd, 0xfd, 0x87, 0xbf, 0x7b, 0xf9, 0x85, + 0xc1, 0x91, 0x7d, 0x9b, 0x8b, 0xef, 0x77, 0xe1, 0x20, 0xa4, 0xf1, 0x6d, 0xc4, 0x32, 0x25, 0xf3, 0x2e, 0xc1, 0x25, + 0xd7, 0x9d, 0x73, 0x93, 0xdb, 0x29, 0x68, 0xaa, 0x3e, 0xdd, 0x66, 0xb6, 0xe2, 0xe8, 0xf1, 0xfc, 0xc6, 0xee, 0x46, + 0x7b, 0x2d, 0x67, 0xf3, 0x0f, 0x4d, 0xcd, 0xdc, 0x9d, 0x0b, 0x5a, 0x4f, 0x2f, 0x7c, 0x34, 0xbf, 0xe9, 0x6a, 0x41, + 0xdb, 0x14, 0x1a, 0xaa, 0xd6, 0xfc, 0xc6, 0x4d, 0x4e, 0xad, 0x06, 0xf2, 0xc2, 0xa3, 0xdc, 0xa3, 0x71, 0x4e, 0xbb, + 0xf0, 0xbe, 0x6a, 0x36, 0x8a, 0x53, 0x23, 0xcc, 0x67, 0x2c, 0x49, 0x52, 0xda, 0xb5, 0xf2, 0xda, 0x6b, 0x3f, 0x86, + 0xdc, 0x4e, 0x77, 0xcb, 0xea, 0xbb, 0xe2, 0x20, 0xaf, 0xc4, 0x53, 0x7c, 0x99, 0xf3, 0x14, 0x3e, 0x16, 0xb1, 0x15, + 0x9d, 0x26, 0xe9, 0xb1, 0x55, 0x21, 0x4f, 0xfd, 0xae, 0xaf, 0xe5, 0x51, 0xeb, 0x4f, 0x5d, 0xb5, 0xe1, 0xad, 0xae, + 0xe4, 0xf3, 0xa8, 0x79, 0x54, 0x5f, 0x08, 0x54, 0x95, 0x4b, 0xc0, 0x5b, 0x96, 0x85, 0x41, 0x5a, 0x69, 0x3e, 0xed, + 0x85, 0x6d, 0x53, 0xa6, 0x06, 0x80, 0x17, 0x2b, 0x97, 0x45, 0x45, 0x7d, 0x31, 0xff, 0x3e, 0xa7, 0xe5, 0xf3, 0xed, + 0xa7, 0xe5, 0x73, 0x7b, 0x5a, 0xee, 0xa6, 0xd8, 0xcf, 0xc6, 0x6d, 0xf8, 0xd3, 0xad, 0x16, 0x14, 0xb5, 0xbc, 0xa3, + 0xf9, 0x8d, 0x07, 0x7a, 0x5a, 0xb3, 0x33, 0xbf, 0xd1, 0xa9, 0xb9, 0x10, 0x36, 0x68, 0x41, 0xb2, 0x2a, 0x6e, 0x79, + 0x50, 0x08, 0x7f, 0x5b, 0xb5, 0xaa, 0xf6, 0x43, 0xa8, 0x83, 0x5e, 0x8f, 0x36, 0xeb, 0x3a, 0x77, 0x1f, 0xda, 0x28, + 0xe3, 0x32, 0x88, 0x2c, 0x37, 0x46, 0xa1, 0x8c, 0x2f, 0x2f, 0x69, 0x12, 0x8d, 0xf9, 0x68, 0x91, 0xff, 0xb3, 0x81, + 0xdf, 0x20, 0xf1, 0xce, 0x23, 0xbd, 0x36, 0x8e, 0xed, 0xaa, 0x13, 0x85, 0xed, 0x08, 0xcb, 0x72, 0x9f, 0xa2, 0x7c, + 0x14, 0xa7, 0x34, 0xe8, 0x84, 0x0f, 0xb7, 0x1c, 0x82, 0xff, 0x90, 0xbd, 0xd9, 0xba, 0x98, 0xdf, 0x8b, 0x8c, 0x3b, + 0x91, 0xf0, 0xab, 0x70, 0xe0, 0xee, 0x61, 0xeb, 0xe9, 0x76, 0x70, 0x07, 0x76, 0xa6, 0xa1, 0x15, 0x0a, 0x46, 0xee, + 0x24, 0x74, 0x1c, 0x2f, 0x52, 0x79, 0xf7, 0xa8, 0xbb, 0x28, 0x63, 0x63, 0xd4, 0x3b, 0x18, 0x7a, 0xd5, 0xf6, 0x9e, + 0x5c, 0xfa, 0xb3, 0xcf, 0x1f, 0xc2, 0x1f, 0x9d, 0x67, 0x74, 0x5b, 0xe9, 0xea, 0xda, 0x56, 0x05, 0x5d, 0x7d, 0xbf, + 0xa6, 0x8c, 0x6b, 0x11, 0xae, 0xf4, 0xf1, 0xfb, 0xb6, 0x06, 0xad, 0xf2, 0x5e, 0xcd, 0x8d, 0x96, 0xf5, 0xab, 0x5a, + 0xff, 0xba, 0xc1, 0xef, 0xd9, 0x76, 0xa4, 0x35, 0xd7, 0x7a, 0x5b, 0xf3, 0xed, 0xba, 0x8d, 0xc6, 0x16, 0xe3, 0xaa, + 0xfd, 0x3e, 0xb9, 0x2d, 0x4d, 0x14, 0x1d, 0x08, 0x04, 0x2b, 0x65, 0x5f, 0x5b, 0x29, 0x8c, 0x92, 0x07, 0xf0, 0xe6, + 0x58, 0xef, 0x66, 0x96, 0x66, 0x39, 0xf1, 0xa7, 0x52, 0xce, 0x23, 0xfd, 0xb1, 0xd3, 0xeb, 0xa3, 0x90, 0x8b, 0xc9, + 0x61, 0xa7, 0xd5, 0x6a, 0xc1, 0x1b, 0x3f, 0x7d, 0xef, 0x8a, 0xd1, 0xeb, 0x67, 0xfc, 0x86, 0xf8, 0x4f, 0xbc, 0xa7, + 0xde, 0x93, 0x23, 0xef, 0xd1, 0x63, 0xdf, 0x53, 0xec, 0x9c, 0xf8, 0x4f, 0x8e, 0x7c, 0x4f, 0xb3, 0x73, 0xe2, 0x3f, + 0x7a, 0xec, 0xf7, 0x8e, 0x27, 0x56, 0x25, 0x83, 0x2b, 0x83, 0x5a, 0xdf, 0xc9, 0xa5, 0xe0, 0x1f, 0x69, 0xfd, 0xe0, + 0xea, 0x32, 0x93, 0x89, 0xd6, 0xb1, 0x8f, 0x70, 0x7a, 0x47, 0xf1, 0x3c, 0x52, 0x44, 0xe1, 0x16, 0x82, 0x5b, 0x46, + 0x97, 0xaa, 0x29, 0x40, 0xcd, 0xbc, 0xf4, 0x7b, 0xc7, 0x90, 0x35, 0xee, 0x25, 0xc4, 0x7f, 0xdd, 0x79, 0xe2, 0xb5, + 0x1f, 0x5f, 0x35, 0x1f, 0x8e, 0x5a, 0xcd, 0xb6, 0xd7, 0x6e, 0x76, 0xc2, 0x27, 0x5e, 0x47, 0xff, 0xeb, 0xb5, 0xbc, + 0x23, 0xaf, 0x1d, 0x3e, 0xf1, 0x8e, 0xbc, 0x4e, 0xf8, 0xe4, 0xea, 0xa1, 0x4e, 0x27, 0x88, 0xfd, 0xc3, 0xde, 0x31, + 0x7c, 0xb8, 0xf2, 0x86, 0xf8, 0x9f, 0xfb, 0xfa, 0xf3, 0xb0, 0xfe, 0x67, 0x6e, 0x69, 0xfb, 0xe9, 0xd6, 0xe2, 0xce, + 0x93, 0xad, 0xc5, 0x47, 0x8f, 0xb7, 0x16, 0x3f, 0x7c, 0x54, 0x2f, 0x3e, 0x9c, 0xe8, 0xaa, 0xf2, 0x94, 0x13, 0x7f, + 0x16, 0x4b, 0xc1, 0x6e, 0x82, 0xb6, 0xd7, 0xf2, 0x5a, 0x5e, 0x13, 0xfe, 0x7b, 0xd2, 0x41, 0x65, 0xaf, 0x4b, 0xe8, + 0x55, 0xae, 0xf2, 0xc9, 0x53, 0xaf, 0xfd, 0xf8, 0x65, 0xe7, 0xf1, 0x08, 0xda, 0xa9, 0x85, 0xb6, 0xbd, 0xf6, 0xd5, + 0xd1, 0xd3, 0x51, 0xcb, 0x83, 0x8e, 0x6d, 0xf8, 0x33, 0x7d, 0xd4, 0x19, 0xe9, 0x87, 0x16, 0xd4, 0x7f, 0xdb, 0x7e, + 0x92, 0xb7, 0x9a, 0x6d, 0xf8, 0xf3, 0x4b, 0xa9, 0x11, 0x83, 0x3e, 0xee, 0x8e, 0xfb, 0xb0, 0xe5, 0x1d, 0x3d, 0x9d, + 0x76, 0xc2, 0xcf, 0xaf, 0x9e, 0x84, 0x4f, 0xa7, 0xed, 0x27, 0xdf, 0xea, 0xa7, 0xb4, 0xd9, 0x09, 0x3f, 0x87, 0xbf, + 0xdf, 0x1e, 0xb5, 0xa6, 0xcd, 0x76, 0xf8, 0xf4, 0xea, 0x28, 0x3c, 0x4a, 0x9b, 0x8f, 0xc3, 0xa7, 0xf0, 0xb7, 0x1a, + 0x6e, 0xca, 0x67, 0xd4, 0xf7, 0x60, 0xbf, 0xd7, 0xcc, 0x2d, 0x77, 0x8e, 0xce, 0x43, 0xef, 0xd1, 0xc3, 0x97, 0x4f, + 0xaf, 0x9a, 0x0f, 0xa7, 0xed, 0xce, 0x55, 0x73, 0xe7, 0xcf, 0x6f, 0x01, 0xf1, 0x66, 0xe0, 0x98, 0xc2, 0xf5, 0x1d, + 0x8b, 0x38, 0xf5, 0xf6, 0xd9, 0x07, 0x38, 0xdf, 0x65, 0x5e, 0x8b, 0x4f, 0x9b, 0xd7, 0x19, 0xbd, 0x8f, 0x7d, 0x2d, + 0xfe, 0x70, 0xfb, 0x3a, 0xa7, 0x6b, 0x4e, 0xd5, 0x5b, 0xb9, 0x61, 0x46, 0xaf, 0xdb, 0x5e, 0xef, 0x64, 0x30, 0x60, + 0xf0, 0x95, 0xa3, 0xa2, 0x7b, 0x0b, 0x2f, 0xb8, 0x76, 0xbd, 0x0d, 0x1c, 0x0e, 0xf2, 0xad, 0xd4, 0x27, 0x99, 0xef, + 0x42, 0x48, 0xfa, 0x69, 0x84, 0x7c, 0x7b, 0x1f, 0x7c, 0xa4, 0x7f, 0x38, 0x3e, 0xb8, 0x8b, 0x8f, 0x9a, 0x9f, 0x57, + 0xd9, 0xb3, 0xca, 0x1e, 0x3d, 0x53, 0xcf, 0x01, 0xdc, 0xf0, 0x68, 0xf8, 0x87, 0x14, 0x8a, 0x72, 0x5f, 0xc7, 0x15, + 0xde, 0xfc, 0x1a, 0x97, 0xb4, 0xbe, 0xce, 0x45, 0x7c, 0x63, 0xfc, 0xcf, 0xe1, 0x4b, 0x06, 0xf6, 0xe1, 0x4a, 0x5f, + 0x30, 0x26, 0x7e, 0x27, 0x6c, 0x85, 0xad, 0xd2, 0x71, 0x00, 0x57, 0xf8, 0xc8, 0x92, 0xcb, 0x18, 0x3e, 0xa6, 0x99, + 0xf2, 0x89, 0xfa, 0xec, 0x26, 0xbc, 0xec, 0x5c, 0x7d, 0x00, 0x55, 0xbf, 0x67, 0x3e, 0xf2, 0x7d, 0x73, 0xf1, 0x1f, + 0xae, 0x88, 0x7d, 0x03, 0xd7, 0xe8, 0xac, 0xc7, 0x7a, 0x06, 0x36, 0xf5, 0x6b, 0x9a, 0xb0, 0x38, 0xf0, 0x83, 0xb9, + 0xa0, 0x63, 0x2a, 0xf2, 0x66, 0xed, 0x6e, 0x99, 0xba, 0x56, 0x86, 0x7c, 0xfb, 0xd9, 0x46, 0x01, 0x2f, 0xef, 0x25, + 0x03, 0xe3, 0xd5, 0xf2, 0x8d, 0x9a, 0xef, 0x17, 0xd8, 0x96, 0x08, 0xe0, 0xe8, 0x95, 0x6a, 0xe0, 0x6b, 0xdd, 0xa0, + 0x1d, 0x76, 0x1e, 0x21, 0xcd, 0x4b, 0xe0, 0xa5, 0xa8, 0xdf, 0x07, 0xcd, 0xa3, 0xd6, 0x9f, 0x90, 0xd3, 0xad, 0x1c, + 0x68, 0x68, 0x9c, 0x3a, 0xa2, 0xfa, 0xdc, 0x6d, 0xfd, 0xe2, 0x9f, 0xaf, 0x29, 0xe2, 0x33, 0xbd, 0x76, 0x78, 0xbd, + 0xaa, 0x89, 0x1f, 0xea, 0xeb, 0xeb, 0x63, 0x36, 0x09, 0xdc, 0x8f, 0x99, 0xea, 0x97, 0xae, 0xaa, 0x6f, 0x20, 0xa3, + 0xa2, 0x6a, 0x22, 0xd0, 0x52, 0xf9, 0xe2, 0x59, 0xe6, 0x89, 0xd5, 0x2a, 0x10, 0xe0, 0x88, 0x25, 0x0e, 0x4e, 0xe1, + 0x19, 0xd5, 0x90, 0x2c, 0x70, 0x09, 0x90, 0x42, 0x30, 0x11, 0xfa, 0xff, 0xaa, 0xd8, 0xfe, 0x30, 0xee, 0x95, 0x30, + 0x8d, 0xb3, 0x09, 0x50, 0x61, 0x9c, 0x4d, 0x36, 0x9c, 0x37, 0x3a, 0x9c, 0xb0, 0x56, 0x5a, 0x0d, 0x55, 0x39, 0x69, + 0xf2, 0x67, 0xb7, 0xef, 0xcd, 0xdb, 0x99, 0x7c, 0xf0, 0x81, 0x2a, 0xdf, 0x77, 0xf5, 0x26, 0xd9, 0x06, 0x79, 0xa0, + 0x3f, 0x0f, 0xae, 0xf2, 0xd1, 0x40, 0xfa, 0xc1, 0x95, 0x3e, 0xcf, 0xd8, 0x3c, 0xc4, 0xd7, 0xb2, 0x2f, 0xa1, 0x57, + 0x6c, 0x64, 0x44, 0x18, 0xf6, 0xcc, 0xb5, 0xe6, 0xa6, 0xda, 0x1a, 0xd2, 0xc6, 0xda, 0xea, 0x1f, 0xc5, 0x2a, 0xbf, + 0x98, 0x64, 0xdc, 0xef, 0x3d, 0x28, 0xbf, 0xcd, 0xb8, 0x6b, 0x13, 0xe0, 0x9b, 0xe5, 0x03, 0x41, 0xd3, 0x7f, 0x26, + 0x0f, 0xe0, 0xab, 0xe5, 0x0f, 0x86, 0xf0, 0xc1, 0xec, 0x50, 0x89, 0x82, 0x07, 0xd5, 0xc7, 0xcb, 0x81, 0x0f, 0x36, + 0x6e, 0x66, 0x29, 0xbe, 0xaf, 0xf8, 0x36, 0xa2, 0xba, 0xf3, 0xa8, 0x12, 0xd5, 0x9d, 0x47, 0xae, 0xf4, 0x6c, 0x7b, + 0xed, 0x4e, 0xf8, 0xc8, 0x11, 0x00, 0x57, 0x4d, 0xf8, 0xbf, 0x26, 0x02, 0x1e, 0x86, 0x8f, 0x4a, 0x19, 0xf0, 0xaa, + 0xdd, 0x09, 0x8f, 0xb4, 0xb8, 0xe9, 0x84, 0x8f, 0x7e, 0x50, 0x0c, 0x5a, 0x33, 0xe7, 0xfa, 0x81, 0xd8, 0x12, 0xaa, + 0xd1, 0x49, 0x75, 0x3e, 0x0e, 0xca, 0x2f, 0xc0, 0x99, 0xf3, 0x69, 0x5c, 0x42, 0xcf, 0x63, 0x01, 0x9f, 0xe1, 0xa8, + 0x9f, 0xdd, 0x5a, 0x1d, 0xae, 0xf1, 0x8b, 0x2d, 0x53, 0xc0, 0x09, 0xf7, 0xb1, 0x7b, 0x2f, 0x18, 0x2e, 0xd5, 0xaa, + 0x97, 0x16, 0xdb, 0x77, 0xb7, 0xed, 0x26, 0x6d, 0xdd, 0xd0, 0xbe, 0x1f, 0x4e, 0x31, 0x0b, 0xa6, 0x5e, 0x10, 0xaf, + 0x26, 0xf9, 0x32, 0x29, 0xd6, 0xe7, 0x87, 0xdc, 0x3e, 0xc1, 0x9d, 0xab, 0xd1, 0xb4, 0x4a, 0x3f, 0x4f, 0x18, 0x5c, + 0x66, 0x2f, 0x0a, 0x0b, 0x7a, 0xcd, 0x19, 0x58, 0x61, 0x49, 0xf1, 0x0b, 0x9a, 0xf7, 0x7d, 0x28, 0xf2, 0x23, 0x5f, + 0x39, 0x92, 0xfc, 0xf2, 0x53, 0x24, 0x25, 0x61, 0x57, 0x05, 0x58, 0x5d, 0x21, 0x81, 0x53, 0x0b, 0xf8, 0xf1, 0xd1, + 0xc1, 0xc1, 0xce, 0xf3, 0xa2, 0xb4, 0x31, 0x58, 0x6b, 0xf5, 0x09, 0x03, 0x97, 0x15, 0xf9, 0x2e, 0xa2, 0xcb, 0x71, + 0x15, 0x0a, 0x91, 0xc1, 0xd3, 0x25, 0x8d, 0x65, 0x18, 0x67, 0x3a, 0x45, 0xc1, 0x61, 0x58, 0xb8, 0x4d, 0x8f, 0x50, + 0xc1, 0x65, 0xec, 0x7c, 0xa3, 0xd4, 0x9c, 0x73, 0x2e, 0x63, 0x7b, 0xd1, 0x2f, 0x93, 0xb5, 0x4c, 0xf8, 0x69, 0xa7, + 0xf7, 0xf6, 0xfd, 0x89, 0xa7, 0x8f, 0xe7, 0xf1, 0xe1, 0xb4, 0xd3, 0x3b, 0x56, 0x96, 0xb9, 0xbe, 0x26, 0x44, 0xf4, + 0x35, 0x21, 0xcf, 0x5c, 0x19, 0x83, 0x78, 0x4d, 0x71, 0xa8, 0x97, 0xed, 0x7b, 0x34, 0x1b, 0x69, 0x9f, 0xe2, 0x6c, + 0x91, 0x4a, 0x06, 0x2f, 0xe0, 0x3d, 0x84, 0xae, 0x4d, 0xd8, 0xb0, 0x32, 0xcf, 0xd4, 0x6a, 0x38, 0x32, 0xb3, 0x1e, + 0xc8, 0x31, 0x4b, 0xa9, 0xcd, 0x2c, 0x35, 0x43, 0x95, 0x79, 0xcf, 0x9b, 0xad, 0xf3, 0xc5, 0xe5, 0x8c, 0xc9, 0x32, + 0x15, 0xf4, 0x83, 0xe9, 0x70, 0xac, 0xa6, 0xea, 0x5d, 0x14, 0xc6, 0x45, 0x6a, 0x3f, 0x36, 0xb2, 0xf6, 0x79, 0x77, + 0xbd, 0x7a, 0x23, 0x21, 0xe0, 0xbe, 0xcf, 0xf4, 0xa8, 0x57, 0x3a, 0x25, 0xdd, 0xba, 0xe2, 0xf8, 0x70, 0x7a, 0xd4, + 0xbb, 0x88, 0xe6, 0x66, 0xbc, 0x57, 0x7c, 0xe3, 0x53, 0xf1, 0x25, 0xc7, 0xec, 0xab, 0xc4, 0x76, 0x7d, 0x83, 0xd2, + 0x00, 0x3c, 0xe2, 0xa9, 0xdf, 0x3b, 0x36, 0xca, 0x80, 0xa7, 0x82, 0xae, 0xfe, 0xa3, 0x96, 0xcd, 0x95, 0x4f, 0xb9, + 0xd2, 0x96, 0x74, 0x17, 0x67, 0x92, 0x9a, 0x5f, 0x77, 0xda, 0xee, 0x1d, 0xc7, 0x46, 0xcd, 0x04, 0xe6, 0x91, 0x47, + 0x87, 0xd0, 0x19, 0x74, 0xb9, 0x90, 0xf1, 0xc3, 0x6b, 0x7a, 0xd9, 0x8c, 0xe7, 0xac, 0x72, 0xa2, 0x82, 0xd2, 0x51, + 0x4e, 0xc9, 0xab, 0x99, 0xe0, 0x67, 0xbc, 0xb6, 0x48, 0xc5, 0xc2, 0x0b, 0xe3, 0xa1, 0x55, 0xba, 0x3a, 0x8d, 0xa5, + 0xef, 0x69, 0x0e, 0x6f, 0x3d, 0xb9, 0x46, 0xf6, 0x16, 0x7e, 0xef, 0xdf, 0xfe, 0xc7, 0xff, 0x32, 0xce, 0xd9, 0xe3, + 0xc3, 0x69, 0xdb, 0x8e, 0xb5, 0x86, 0xe8, 0xe2, 0x18, 0xae, 0x97, 0x55, 0xd1, 0x44, 0x7a, 0xd3, 0x9c, 0x08, 0x96, + 0x34, 0xa7, 0x71, 0x3a, 0xf6, 0x7b, 0xbb, 0x11, 0xe4, 0xde, 0x2b, 0x31, 0x50, 0xd7, 0x8b, 0x80, 0x04, 0x7f, 0xd3, + 0xcd, 0x08, 0x9b, 0x60, 0xaf, 0x4e, 0xab, 0x7b, 0x4f, 0xa2, 0x3a, 0x50, 0xb5, 0xbb, 0x12, 0xc2, 0x7c, 0x93, 0xc8, + 0x30, 0x35, 0x51, 0xbb, 0x22, 0x51, 0xf8, 0x5e, 0x19, 0x0d, 0xf9, 0xbf, 0xff, 0xf3, 0xbf, 0xfc, 0x37, 0xfb, 0x08, + 0x41, 0x8e, 0x7f, 0xfb, 0xef, 0xff, 0xf9, 0xff, 0xfc, 0xef, 0xff, 0x0a, 0x69, 0xf5, 0x26, 0x10, 0xa2, 0xf8, 0x84, + 0x57, 0x45, 0x41, 0x34, 0xc3, 0xf0, 0x20, 0x19, 0x6d, 0xc6, 0x72, 0xc9, 0x46, 0xf5, 0x4b, 0x13, 0x67, 0x6a, 0x42, + 0x75, 0xd8, 0x0c, 0x74, 0xea, 0xd0, 0x16, 0x15, 0x8d, 0xd4, 0x50, 0xae, 0x68, 0xb1, 0x38, 0x3e, 0x04, 0x7c, 0xdf, + 0xef, 0x9e, 0x59, 0x58, 0x6e, 0xc7, 0xd2, 0xba, 0xfe, 0xa0, 0xa4, 0xa8, 0xca, 0x3d, 0x70, 0xca, 0x2f, 0xe1, 0x31, + 0xea, 0x38, 0xc5, 0x6a, 0xf7, 0x6a, 0x7d, 0xba, 0x3f, 0x2d, 0x72, 0xc9, 0xc6, 0x80, 0x72, 0xed, 0x60, 0x54, 0xf1, + 0xcf, 0x26, 0xa8, 0x7f, 0xe9, 0x6d, 0xa1, 0x46, 0xd1, 0x36, 0xe3, 0xc3, 0xa7, 0x7f, 0x2a, 0xfe, 0x32, 0x03, 0x25, + 0xcb, 0x0b, 0x66, 0xf1, 0x8d, 0xb1, 0x24, 0x1f, 0xb7, 0x5a, 0xf3, 0x1b, 0xb4, 0xac, 0x66, 0xc0, 0xbb, 0x26, 0x53, + 0x4e, 0x49, 0x77, 0x40, 0x15, 0x38, 0x2d, 0xfd, 0x9f, 0x2d, 0x0f, 0x9c, 0xa8, 0x5e, 0xab, 0x28, 0xfe, 0xbc, 0x54, + 0x2e, 0x38, 0xf6, 0x0b, 0x04, 0x38, 0x8d, 0xb7, 0xf2, 0x92, 0xbb, 0x8b, 0x5b, 0x3a, 0xbd, 0x3a, 0xba, 0xd7, 0xb4, + 0xbd, 0x79, 0x7d, 0xca, 0x0d, 0xd0, 0xba, 0xa1, 0xd5, 0x87, 0x10, 0x2c, 0x9d, 0xb6, 0xf1, 0xb4, 0xb3, 0x2c, 0x87, + 0x97, 0x92, 0xcf, 0xdc, 0x88, 0x2c, 0x8d, 0xe9, 0x88, 0x8e, 0xad, 0x97, 0xd7, 0xd4, 0xeb, 0x68, 0x6b, 0x31, 0x3d, + 0xda, 0x32, 0x97, 0x01, 0x49, 0x45, 0x62, 0xbd, 0x56, 0xf1, 0x19, 0x9c, 0xc0, 0xe5, 0x38, 0xe5, 0xb1, 0x8c, 0x14, + 0xc1, 0x76, 0xdd, 0xb8, 0x6e, 0x0c, 0x6c, 0x86, 0x2f, 0x1d, 0x78, 0xba, 0xba, 0x29, 0xf8, 0x5b, 0xeb, 0x97, 0xdc, + 0x8a, 0x50, 0x75, 0x77, 0x87, 0xd2, 0xee, 0x9a, 0x6f, 0x4d, 0xb8, 0xf4, 0x4d, 0xcd, 0xcf, 0x61, 0x64, 0x4c, 0x07, + 0x6d, 0xaf, 0xd7, 0xa2, 0x5a, 0xd7, 0x7e, 0x25, 0x03, 0x5f, 0x81, 0xe9, 0xaf, 0xb7, 0x52, 0x85, 0xd0, 0xea, 0x0d, + 0xf9, 0xb6, 0xb4, 0x82, 0xe2, 0xf9, 0x5c, 0x35, 0x44, 0xdd, 0xe3, 0x43, 0xad, 0xbc, 0x02, 0xf7, 0x50, 0xb9, 0x00, + 0x3a, 0xf4, 0x6e, 0x1a, 0x99, 0xa3, 0xa0, 0x7f, 0x99, 0xa0, 0x3c, 0x7c, 0xac, 0xaa, 0xf7, 0xff, 0x00, 0xbb, 0x9f, + 0x49, 0x8d, 0x3d, 0x86, 0x00, 0x00}; + +} // namespace web_server +} // namespace esphome +#endif +#endif diff --git a/esphome/components/web_server/server_index_v3.h b/esphome/components/web_server/server_index_v3.h new file mode 100644 index 0000000000..49de0cfab6 --- /dev/null +++ b/esphome/components/web_server/server_index_v3.h @@ -0,0 +1,3995 @@ +#pragma once +// Generated from https://github.com/esphome/esphome-webserver +#ifdef USE_WEBSERVER_LOCAL +#if USE_WEBSERVER_VERSION == 3 +#include "esphome/core/hal.h" +namespace esphome { + +namespace web_server { + +const uint8_t INDEX_GZ[] PROGMEM = { + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xcc, 0xbd, 0xeb, 0x7a, 0x1b, 0xb7, 0xb2, 0x20, 0xfa, + 0xfb, 0xcc, 0x53, 0x48, 0xbd, 0x1d, 0xa5, 0x21, 0x82, 0x2d, 0x92, 0xba, 0x58, 0x6e, 0x0a, 0xe2, 0xf8, 0x1a, 0x3b, + 0x71, 0x6c, 0xc7, 0x72, 0xec, 0xd8, 0x0c, 0xb7, 0x02, 0x36, 0x41, 0x12, 0x71, 0x13, 0x60, 0x1a, 0xa0, 0x25, 0x99, + 0xe4, 0xbb, 0x9f, 0xaf, 0x70, 0xe9, 0x46, 0x93, 0xb4, 0xd7, 0x5a, 0x73, 0x66, 0xce, 0x37, 0x3b, 0x7b, 0x59, 0x6c, + 0xdc, 0x51, 0x28, 0x14, 0xaa, 0x0a, 0x55, 0x85, 0x8b, 0xfd, 0x91, 0xcc, 0xf4, 0xdd, 0x9c, 0xed, 0x4d, 0xf5, 0x2c, + 0xbf, 0xbc, 0x70, 0xff, 0x32, 0x3a, 0xba, 0xbc, 0xc8, 0xb9, 0xf8, 0xbc, 0x57, 0xb0, 0x9c, 0xf0, 0x4c, 0x8a, 0xbd, + 0x69, 0xc1, 0xc6, 0x64, 0x44, 0x35, 0x4d, 0xf9, 0x8c, 0x4e, 0xd8, 0xde, 0xd1, 0xe5, 0xc5, 0x8c, 0x69, 0xba, 0x97, + 0x4d, 0x69, 0xa1, 0x98, 0x26, 0xbf, 0xbf, 0x7b, 0xd6, 0x3c, 0xbf, 0xbc, 0x50, 0x59, 0xc1, 0xe7, 0x7a, 0x0f, 0x9a, + 0x24, 0x33, 0x39, 0x5a, 0xe4, 0xec, 0xf2, 0xe8, 0xe8, 0xe6, 0xe6, 0x26, 0xf9, 0x5b, 0xfd, 0x8f, 0x2f, 0xb4, 0xd8, + 0xfb, 0xa5, 0x20, 0xaf, 0x87, 0x7f, 0xb3, 0x4c, 0x27, 0x23, 0x36, 0xe6, 0x82, 0xbd, 0x29, 0xe4, 0x9c, 0x15, 0xfa, + 0xae, 0x0b, 0x99, 0x3f, 0x15, 0x24, 0xe6, 0x58, 0x63, 0x86, 0xc8, 0xa5, 0xde, 0xe3, 0x62, 0x8f, 0xf7, 0x7e, 0x29, + 0x4c, 0xca, 0x92, 0x89, 0xc5, 0x8c, 0x15, 0x74, 0x98, 0xb3, 0x74, 0xbf, 0x85, 0x33, 0x29, 0xc6, 0x7c, 0xb2, 0x28, + 0xbf, 0x6f, 0x0a, 0xae, 0xfd, 0xef, 0x2f, 0x34, 0x5f, 0xb0, 0x94, 0xad, 0x51, 0xca, 0xfb, 0x7a, 0x40, 0x98, 0x69, + 0xf9, 0x73, 0xd5, 0x70, 0xfc, 0x93, 0x69, 0xf2, 0x6e, 0xce, 0xe4, 0x78, 0x4f, 0xef, 0x93, 0x48, 0xdd, 0xcd, 0x86, + 0x32, 0x8f, 0x7a, 0xba, 0x11, 0x45, 0x29, 0x94, 0xc1, 0x0c, 0x75, 0x33, 0x29, 0x94, 0xde, 0x13, 0x9c, 0xdc, 0x70, + 0x31, 0x92, 0x37, 0xf8, 0x46, 0x10, 0xc1, 0x93, 0xab, 0x29, 0x1d, 0xc9, 0x9b, 0xb7, 0x52, 0xea, 0x83, 0x83, 0xd8, + 0x7d, 0xdf, 0x3d, 0xbe, 0xba, 0x22, 0x84, 0x7c, 0x91, 0x7c, 0xb4, 0xd7, 0x5a, 0xad, 0x82, 0xd4, 0x44, 0x50, 0xcd, + 0xbf, 0x30, 0x5b, 0x09, 0x1d, 0x1c, 0x44, 0x74, 0x24, 0xe7, 0x9a, 0x8d, 0xae, 0xf4, 0x5d, 0xce, 0xae, 0xa6, 0x8c, + 0x69, 0x15, 0x71, 0xb1, 0xf7, 0x44, 0x66, 0x8b, 0x19, 0x13, 0x3a, 0x99, 0x17, 0x52, 0x4b, 0x18, 0xd8, 0xc1, 0x41, + 0x54, 0xb0, 0x79, 0x4e, 0x33, 0x06, 0xf9, 0x8f, 0xaf, 0xae, 0xaa, 0x1a, 0x55, 0x21, 0xfc, 0x59, 0x90, 0x2b, 0x33, + 0xf4, 0x18, 0xe1, 0x0f, 0x82, 0x08, 0x76, 0xb3, 0xf7, 0x81, 0xd1, 0xcf, 0xbf, 0xd2, 0x79, 0x37, 0xcb, 0xa9, 0x52, + 0x7b, 0xcf, 0xe4, 0xd2, 0x4c, 0xa3, 0x58, 0x64, 0x5a, 0x16, 0xb1, 0xc6, 0x0c, 0x0b, 0xb4, 0xe4, 0xe3, 0x58, 0x4f, + 0xb9, 0x4a, 0xae, 0xef, 0x65, 0x4a, 0xbd, 0x65, 0x6a, 0x91, 0xeb, 0x7b, 0x64, 0xbf, 0x85, 0xc5, 0x3e, 0x21, 0x9f, + 0x05, 0xd2, 0xd3, 0x42, 0xde, 0xec, 0x3d, 0x2d, 0x0a, 0x59, 0xc4, 0xd1, 0xe3, 0xab, 0x2b, 0x5b, 0x62, 0x8f, 0xab, + 0x3d, 0x21, 0xf5, 0x5e, 0xd9, 0x1e, 0x40, 0x3b, 0xd9, 0xfb, 0x5d, 0xb1, 0xbd, 0xbf, 0x16, 0x42, 0xd1, 0x31, 0x7b, + 0x7c, 0x75, 0xf5, 0xd7, 0x9e, 0x2c, 0xf6, 0xfe, 0xca, 0x94, 0xfa, 0x6b, 0x8f, 0x0b, 0xa5, 0x19, 0x1d, 0x25, 0x11, + 0xea, 0x9a, 0xce, 0x32, 0xa5, 0xde, 0xb1, 0x5b, 0x4d, 0x34, 0x36, 0x9f, 0x9a, 0xb0, 0xf5, 0x84, 0xe9, 0x3d, 0x55, + 0xce, 0x2b, 0x46, 0xcb, 0x9c, 0xe9, 0x3d, 0x4d, 0x4c, 0xbe, 0x74, 0xf0, 0x67, 0xf6, 0x53, 0x77, 0xf9, 0x38, 0xbe, + 0x11, 0x07, 0x07, 0xba, 0x04, 0x34, 0x5a, 0xba, 0x15, 0x22, 0x6c, 0xdf, 0xa7, 0x1d, 0x1c, 0xb0, 0x24, 0x67, 0x62, + 0xa2, 0xa7, 0x84, 0x90, 0x76, 0x57, 0x1c, 0x1c, 0xc4, 0x9a, 0x7c, 0x10, 0xc9, 0x84, 0xe9, 0x98, 0x21, 0x84, 0xab, + 0xda, 0x07, 0x07, 0xb1, 0x05, 0x82, 0x24, 0xda, 0x00, 0xae, 0x06, 0x63, 0x94, 0x38, 0xe8, 0x5f, 0xdd, 0x89, 0x2c, + 0x0e, 0xc7, 0x8f, 0xb0, 0x38, 0x38, 0xf8, 0x20, 0x12, 0x05, 0x2d, 0x62, 0x8d, 0xd0, 0xba, 0x60, 0x7a, 0x51, 0x88, + 0x3d, 0xbd, 0xd6, 0xf2, 0x4a, 0x17, 0x5c, 0x4c, 0x62, 0xb4, 0xf4, 0x69, 0x41, 0xc5, 0xf5, 0xda, 0x0e, 0xf7, 0xb7, + 0x82, 0x70, 0x72, 0x09, 0x3d, 0x3e, 0x93, 0xb1, 0xc3, 0x41, 0x4e, 0x48, 0xa4, 0x4c, 0xdd, 0xa8, 0xc7, 0x53, 0xde, + 0x88, 0x22, 0x6c, 0x47, 0x89, 0x3f, 0x0b, 0x84, 0xb9, 0x06, 0xd4, 0x4d, 0x92, 0x44, 0x23, 0x72, 0xb9, 0xf4, 0x60, + 0xe1, 0xc1, 0x44, 0x7b, 0xbc, 0xdf, 0x1a, 0xa4, 0x3a, 0x29, 0xd8, 0x68, 0x91, 0xb1, 0x38, 0x16, 0x58, 0x61, 0x89, + 0xc8, 0xa5, 0x68, 0xc4, 0x05, 0xb9, 0x84, 0xf5, 0x2e, 0xea, 0x8b, 0x4d, 0xc8, 0x7e, 0x0b, 0xb9, 0x41, 0x16, 0x7e, + 0x84, 0x00, 0x62, 0x37, 0xa0, 0x82, 0x90, 0x48, 0x2c, 0x66, 0x43, 0x56, 0x44, 0x65, 0xb1, 0x6e, 0x0d, 0x2f, 0x16, + 0x8a, 0xed, 0x65, 0x4a, 0xed, 0x8d, 0x17, 0x22, 0xd3, 0x5c, 0x8a, 0xbd, 0xa8, 0x51, 0x34, 0x22, 0x8b, 0x0f, 0x25, + 0x3a, 0x44, 0x68, 0x8d, 0x62, 0x85, 0x1a, 0xbc, 0x2f, 0x1b, 0xed, 0x01, 0x86, 0x51, 0xa2, 0xae, 0x6b, 0xcf, 0x41, + 0x80, 0x61, 0x0e, 0x93, 0x5c, 0xe3, 0x4f, 0x76, 0xe7, 0xc3, 0x14, 0x6f, 0x44, 0x8f, 0x27, 0xdb, 0x3b, 0x85, 0xe8, + 0x64, 0x46, 0xe7, 0x31, 0x23, 0x97, 0xcc, 0x60, 0x17, 0x15, 0x19, 0x8c, 0xb5, 0xb6, 0x70, 0x3d, 0x96, 0xb2, 0xa4, + 0xc2, 0x29, 0x94, 0xea, 0x64, 0x2c, 0x8b, 0xa7, 0x34, 0x9b, 0x42, 0xbd, 0x12, 0x63, 0x46, 0x7e, 0xc3, 0x65, 0x05, + 0xa3, 0x9a, 0x3d, 0xcd, 0x19, 0x7c, 0xc5, 0x91, 0xa9, 0x19, 0x21, 0xac, 0x60, 0xab, 0xe7, 0x5c, 0xbf, 0x92, 0x22, + 0x63, 0x5d, 0x15, 0xe0, 0x97, 0x59, 0xf9, 0x87, 0x5a, 0x17, 0x7c, 0xb8, 0xd0, 0x2c, 0x8e, 0x04, 0x94, 0x88, 0xb0, + 0x42, 0x58, 0x24, 0x9a, 0xdd, 0xea, 0xc7, 0x52, 0x68, 0x26, 0x34, 0x61, 0x1e, 0xaa, 0x98, 0x27, 0x74, 0x3e, 0x67, + 0x62, 0xf4, 0x78, 0xca, 0xf3, 0x51, 0x2c, 0xd0, 0x1a, 0xad, 0xf1, 0xef, 0x82, 0xc0, 0x24, 0xc9, 0x25, 0x4f, 0xe1, + 0x9f, 0x6f, 0x4f, 0x27, 0xd6, 0xe4, 0xd2, 0x6c, 0x0b, 0x46, 0xa2, 0xa8, 0x3b, 0x96, 0x45, 0xec, 0xa6, 0xb0, 0x07, + 0xa4, 0x0b, 0xfa, 0x78, 0xbb, 0xc8, 0x99, 0x42, 0xac, 0x41, 0x44, 0xb9, 0x8e, 0x0e, 0xc2, 0xbf, 0x15, 0x31, 0x83, + 0x05, 0xe0, 0x28, 0xe5, 0x86, 0x04, 0xbe, 0xe4, 0x6e, 0x53, 0x8d, 0x4a, 0xa2, 0xf6, 0x51, 0x90, 0x11, 0x4f, 0x74, + 0xb1, 0x50, 0x9a, 0x8d, 0xde, 0xdd, 0xcd, 0x99, 0xc2, 0x3f, 0x17, 0xe4, 0xa3, 0xe8, 0x7d, 0x14, 0x09, 0x9b, 0xcd, + 0xf5, 0xdd, 0x95, 0xa1, 0xe6, 0x69, 0x14, 0xe1, 0x7f, 0x4c, 0xd1, 0x82, 0xd1, 0x0c, 0x48, 0x9a, 0x03, 0xd9, 0x1b, + 0x99, 0xdf, 0x8d, 0x79, 0x9e, 0x5f, 0x2d, 0xe6, 0x73, 0x59, 0x68, 0xac, 0x05, 0x59, 0x6a, 0x59, 0xc1, 0x07, 0x56, + 0x74, 0xa9, 0x6e, 0xb8, 0xce, 0xa6, 0xb1, 0x46, 0xcb, 0x8c, 0x2a, 0xb6, 0xf7, 0x48, 0xca, 0x9c, 0x51, 0x91, 0x72, + 0xc2, 0x7b, 0x3f, 0x17, 0xa9, 0x58, 0xe4, 0x79, 0x77, 0x58, 0x30, 0xfa, 0xb9, 0x6b, 0xb2, 0xed, 0xe1, 0x90, 0x9a, + 0xdf, 0x0f, 0x8b, 0x82, 0xde, 0x41, 0x41, 0x42, 0xa0, 0x58, 0x8f, 0xa7, 0x3f, 0x5f, 0xbd, 0x7e, 0x95, 0xd8, 0xbd, + 0xc2, 0xc7, 0x77, 0x31, 0x2f, 0xf7, 0x1f, 0x5f, 0xe3, 0x71, 0x21, 0x67, 0x1b, 0x5d, 0x5b, 0xd0, 0xf1, 0xee, 0x37, + 0x86, 0xc0, 0x08, 0xdf, 0xb7, 0x4d, 0x87, 0x23, 0x78, 0x65, 0x30, 0x1f, 0x32, 0x89, 0xeb, 0x17, 0xfe, 0x49, 0x6d, + 0x72, 0xcc, 0xd1, 0xf7, 0x47, 0xab, 0x8b, 0xbb, 0x25, 0x23, 0x66, 0x9c, 0x73, 0x38, 0x18, 0x61, 0x8c, 0x19, 0xd5, + 0xd9, 0x74, 0xc9, 0x4c, 0x63, 0x6b, 0x3f, 0x62, 0xb6, 0x5e, 0xe3, 0xaf, 0xd2, 0x63, 0xbd, 0xde, 0x27, 0x84, 0x1b, + 0x7a, 0x45, 0xf4, 0x6a, 0xc5, 0x09, 0xe1, 0x08, 0xbf, 0xe5, 0x64, 0x49, 0xfd, 0x84, 0xe0, 0x64, 0x83, 0xed, 0x99, + 0x5a, 0x2a, 0x03, 0x27, 0xe0, 0x17, 0x56, 0x68, 0x56, 0xa4, 0x5a, 0xe0, 0x82, 0x8d, 0x73, 0x18, 0xc7, 0x7e, 0x1b, + 0x4f, 0xa9, 0x7a, 0x3c, 0xa5, 0x62, 0xc2, 0x46, 0xe9, 0x57, 0xb9, 0xc6, 0x4c, 0x90, 0x68, 0xcc, 0x05, 0xcd, 0xf9, + 0x57, 0x36, 0x8a, 0xdc, 0xb9, 0xf0, 0x48, 0xef, 0xb1, 0x5b, 0xcd, 0xc4, 0x48, 0xed, 0x3d, 0x7f, 0xf7, 0xeb, 0x4b, + 0xb7, 0x98, 0xb5, 0xb3, 0x02, 0x2d, 0xd5, 0x62, 0xce, 0x8a, 0x18, 0x61, 0x77, 0x56, 0x3c, 0xe5, 0x86, 0x4e, 0xfe, + 0x4a, 0xe7, 0x36, 0x85, 0xab, 0xdf, 0xe7, 0x23, 0xaa, 0xd9, 0x1b, 0x26, 0x46, 0x5c, 0x4c, 0xc8, 0x7e, 0xdb, 0xa6, + 0x4f, 0xa9, 0xcb, 0x18, 0x95, 0x49, 0xd7, 0xf7, 0x9e, 0xe6, 0x66, 0xee, 0xe5, 0xe7, 0x22, 0x46, 0x6b, 0xa5, 0xa9, + 0xe6, 0xd9, 0x1e, 0x1d, 0x8d, 0x5e, 0x08, 0xae, 0xb9, 0x19, 0x61, 0x01, 0x4b, 0x04, 0xb8, 0xca, 0xec, 0xa9, 0xe1, + 0x47, 0x1e, 0x23, 0x1c, 0xc7, 0xee, 0x2c, 0x98, 0x22, 0xb7, 0x66, 0x07, 0x07, 0x15, 0xe5, 0xef, 0xb1, 0xd4, 0x66, + 0x92, 0xfe, 0x00, 0x25, 0xf3, 0x85, 0x82, 0xc5, 0xf6, 0x5d, 0xc0, 0x41, 0x23, 0x87, 0x8a, 0x15, 0x5f, 0xd8, 0xa8, + 0x44, 0x10, 0x15, 0xa3, 0xe5, 0x46, 0x1f, 0x6e, 0x7b, 0x68, 0xd2, 0x1f, 0x74, 0x43, 0x12, 0xce, 0x1c, 0xb2, 0x5b, + 0x4e, 0x85, 0x33, 0x55, 0x12, 0x95, 0x18, 0x0e, 0xd4, 0x92, 0xb0, 0x28, 0xe2, 0xe7, 0x37, 0x8f, 0x05, 0xf0, 0x10, + 0x21, 0xe5, 0xf0, 0x67, 0xee, 0xd3, 0x2f, 0xe6, 0xf0, 0x50, 0x58, 0x20, 0xac, 0xed, 0x48, 0x15, 0x42, 0x6b, 0x84, + 0xb5, 0x1f, 0xae, 0x25, 0x4a, 0x9e, 0x2f, 0x82, 0x53, 0x9b, 0xbc, 0xe5, 0xe6, 0xd8, 0x06, 0xda, 0x46, 0x35, 0x3b, + 0x38, 0x88, 0x59, 0x52, 0x22, 0x06, 0xd9, 0x6f, 0xbb, 0x45, 0x0a, 0xa0, 0xf5, 0x8d, 0x71, 0x43, 0xcf, 0x86, 0xc1, + 0xd9, 0x67, 0x89, 0x90, 0x0f, 0xb3, 0x8c, 0x29, 0x25, 0x8b, 0x83, 0x83, 0x7d, 0x53, 0xbe, 0xe4, 0x2c, 0x60, 0x11, + 0x5f, 0xdf, 0x88, 0x6a, 0x08, 0xa8, 0x3a, 0x6d, 0x3d, 0xdf, 0x44, 0x2a, 0xbe, 0xc9, 0x33, 0x21, 0x69, 0x74, 0x7d, + 0x1d, 0x35, 0x34, 0x76, 0x70, 0x98, 0x30, 0xdf, 0xf5, 0xdd, 0x13, 0x66, 0xd9, 0x42, 0xc3, 0x84, 0x6c, 0x81, 0x66, + 0x27, 0x3f, 0x18, 0xd7, 0x87, 0x84, 0x35, 0x56, 0x68, 0x1d, 0xac, 0xe8, 0xce, 0xa6, 0x0d, 0x7f, 0x63, 0x97, 0x6e, + 0x39, 0x31, 0x3c, 0x45, 0xb0, 0x8e, 0x7d, 0x36, 0x58, 0x63, 0x03, 0x7b, 0x3f, 0x1b, 0x69, 0x06, 0xda, 0xd7, 0x83, + 0xae, 0xcb, 0x27, 0xca, 0x42, 0xae, 0x60, 0xff, 0x2c, 0x98, 0xd2, 0x16, 0x91, 0x63, 0x8d, 0x25, 0x86, 0x33, 0x6a, + 0x93, 0xe9, 0xac, 0xb1, 0xa4, 0xbb, 0xc6, 0xf6, 0x7a, 0x0e, 0x67, 0xa3, 0x02, 0xa4, 0xfe, 0x3e, 0x3e, 0xc1, 0x58, + 0x35, 0x5a, 0xad, 0xde, 0x72, 0xdf, 0x4a, 0xb5, 0x96, 0x25, 0xbf, 0xb6, 0xb1, 0x28, 0x4c, 0x20, 0x77, 0x38, 0xef, + 0xb7, 0xdd, 0xf8, 0xc5, 0x80, 0xec, 0xb7, 0x4a, 0x2c, 0x76, 0x60, 0xb5, 0xe3, 0xb1, 0x50, 0x7c, 0x6d, 0x9b, 0x42, + 0xe6, 0xac, 0xaf, 0xe1, 0x4b, 0x32, 0xdd, 0xc2, 0xd5, 0x29, 0xe9, 0x03, 0xd7, 0x91, 0x4c, 0x07, 0xdf, 0xc2, 0x27, + 0x4f, 0x11, 0x62, 0xbd, 0x9d, 0x57, 0x11, 0x8e, 0x2f, 0x75, 0xc2, 0xb1, 0x31, 0x8d, 0x68, 0x5e, 0x56, 0x89, 0x4a, + 0x34, 0x73, 0x5b, 0xbd, 0xca, 0xc2, 0xc2, 0x0c, 0xa6, 0x9a, 0x52, 0xd0, 0xc4, 0x2b, 0x3a, 0x63, 0x2a, 0x66, 0x08, + 0x7f, 0xab, 0x80, 0xc5, 0x4f, 0x28, 0x32, 0x08, 0xce, 0x50, 0x05, 0x67, 0x28, 0xb0, 0xbb, 0xc0, 0xa4, 0xd5, 0xb7, + 0x9c, 0xc2, 0xac, 0xaf, 0x06, 0x15, 0x6f, 0x17, 0x4c, 0xde, 0x1c, 0xce, 0x0e, 0xc1, 0x3d, 0xfc, 0x6c, 0x9a, 0x05, + 0x9a, 0x61, 0x21, 0x14, 0xc2, 0xfb, 0xad, 0xcd, 0x95, 0xf4, 0xa5, 0xaa, 0x39, 0xf6, 0x07, 0xb0, 0x0e, 0xe6, 0xd8, + 0x48, 0xb8, 0x32, 0x7f, 0x6b, 0x5b, 0x0d, 0xc0, 0x76, 0x05, 0x98, 0x91, 0x8c, 0x73, 0xaa, 0xe3, 0xf6, 0x51, 0x0b, + 0x18, 0xd3, 0x2f, 0x0c, 0x4e, 0x15, 0x84, 0xb6, 0xa7, 0xc2, 0x92, 0x85, 0x50, 0x53, 0x3e, 0xd6, 0xf1, 0xef, 0xc2, + 0x10, 0x15, 0x96, 0x2b, 0x06, 0x12, 0x4e, 0xc0, 0x1e, 0x1b, 0x82, 0xf3, 0xbb, 0x80, 0x7e, 0xba, 0xe5, 0x41, 0xe4, + 0x46, 0x6a, 0x08, 0x17, 0x90, 0x87, 0x8a, 0xb5, 0xae, 0xc8, 0x4c, 0xc9, 0xb8, 0x01, 0xf7, 0xd8, 0xee, 0xd9, 0x16, + 0x53, 0x47, 0x0d, 0x44, 0xc0, 0xc1, 0x8a, 0x34, 0x24, 0x11, 0x2e, 0x51, 0x27, 0x5a, 0xbe, 0x94, 0x37, 0xac, 0x78, + 0x4c, 0x61, 0xf0, 0xa9, 0xad, 0xbe, 0xb6, 0x47, 0x81, 0xa1, 0xf8, 0xba, 0xeb, 0xf1, 0xe5, 0xda, 0x4c, 0xfc, 0x4d, + 0x21, 0x67, 0x5c, 0x31, 0xe0, 0xdb, 0x2c, 0xfc, 0x05, 0x6c, 0x34, 0xb3, 0x23, 0xe1, 0xb8, 0x61, 0x25, 0x7e, 0x3d, + 0x7c, 0x59, 0xc7, 0xaf, 0xeb, 0x7b, 0x4f, 0x27, 0x9e, 0x02, 0xd6, 0xf7, 0x31, 0xc2, 0xb1, 0x13, 0x2f, 0x82, 0x93, + 0x2e, 0x99, 0x22, 0x77, 0xcc, 0xaf, 0x56, 0x3a, 0x10, 0xe3, 0x6a, 0x9c, 0x23, 0xb3, 0xdb, 0x06, 0xad, 0xe9, 0x68, + 0x04, 0x2c, 0x5e, 0x21, 0xf3, 0x3c, 0x38, 0xac, 0xb0, 0xe8, 0x96, 0xc7, 0xd3, 0xf5, 0xbd, 0xa7, 0x57, 0xdf, 0x3b, + 0xa1, 0x20, 0x3f, 0x3c, 0xa4, 0xfc, 0x40, 0xc5, 0x88, 0x15, 0x20, 0x57, 0x06, 0xab, 0xe5, 0xce, 0xd9, 0xc7, 0x52, + 0x08, 0x96, 0x69, 0x36, 0x02, 0xa1, 0x45, 0x10, 0x9d, 0x4c, 0xa5, 0xd2, 0x65, 0x62, 0x35, 0x7a, 0x11, 0x0a, 0xa1, + 0x49, 0x46, 0xf3, 0x3c, 0xb6, 0x02, 0xca, 0x4c, 0x7e, 0x61, 0x3b, 0x46, 0xdd, 0xad, 0x0d, 0xb9, 0x6c, 0x86, 0x05, + 0xcd, 0xb0, 0x44, 0xcd, 0x73, 0x9e, 0xb1, 0xf2, 0xf0, 0xba, 0x4a, 0xb8, 0x18, 0xb1, 0x5b, 0xa0, 0x23, 0xe8, 0xf2, + 0xf2, 0xb2, 0x85, 0xdb, 0x68, 0x6d, 0x01, 0xbe, 0xdc, 0x02, 0xec, 0x77, 0x8e, 0x4d, 0x2b, 0x88, 0x2f, 0x77, 0x92, + 0x35, 0x14, 0x9c, 0x95, 0xdc, 0x0b, 0x5a, 0x96, 0x3c, 0x23, 0x3c, 0x62, 0x39, 0xd3, 0xcc, 0x93, 0x73, 0x60, 0xa6, + 0xed, 0xd6, 0x7d, 0x5b, 0xc2, 0xaf, 0x44, 0x27, 0xbf, 0xcb, 0xfc, 0x9a, 0xab, 0x52, 0x74, 0xaf, 0x96, 0xa7, 0x82, + 0x76, 0x4f, 0xdb, 0xe5, 0xa1, 0x5a, 0xd3, 0x6c, 0x6a, 0x25, 0xf6, 0x78, 0x6b, 0x4a, 0x55, 0x1b, 0x8e, 0xb4, 0x97, + 0x9b, 0xe8, 0x53, 0xe1, 0x86, 0xb9, 0x0b, 0x04, 0x57, 0x8e, 0x28, 0x30, 0x10, 0x02, 0xed, 0xb2, 0x3d, 0xa6, 0x79, + 0x3e, 0xa4, 0xd9, 0xe7, 0x3a, 0xf6, 0x57, 0x68, 0x40, 0x36, 0xa9, 0x71, 0x90, 0x15, 0x90, 0xac, 0x70, 0xde, 0x9e, + 0x4a, 0xd7, 0x36, 0x4a, 0xbc, 0xdf, 0xaa, 0xd0, 0xbe, 0xbe, 0xd0, 0xdf, 0xc4, 0x76, 0x33, 0x22, 0xe1, 0x66, 0x16, + 0x03, 0x15, 0xf8, 0x97, 0x18, 0xe7, 0xe9, 0x81, 0xc3, 0x3b, 0x10, 0x3c, 0xd6, 0x1b, 0x03, 0xd1, 0x68, 0xb9, 0x1e, + 0x71, 0xf5, 0x6d, 0x08, 0xfc, 0x6f, 0x19, 0xe5, 0x93, 0xa0, 0x87, 0x7f, 0x77, 0xa0, 0x25, 0x8d, 0x73, 0x8c, 0x73, + 0x39, 0x32, 0xc7, 0x50, 0x78, 0x42, 0xf3, 0x0b, 0x30, 0x2f, 0x06, 0xdf, 0x5f, 0xdb, 0x2c, 0xc3, 0x97, 0xc1, 0x30, + 0x54, 0x37, 0x64, 0x28, 0x6a, 0x28, 0xe0, 0x88, 0xaa, 0x30, 0x67, 0xae, 0xac, 0x89, 0x92, 0x8e, 0x6b, 0xb7, 0xe2, + 0xb8, 0xa3, 0xb9, 0x05, 0x89, 0xe3, 0x58, 0x81, 0x34, 0xe7, 0xf9, 0xfb, 0x6a, 0x16, 0x6a, 0x6b, 0x16, 0x2a, 0x09, + 0xa4, 0x2d, 0x54, 0x21, 0x73, 0x50, 0x3d, 0xd5, 0x02, 0x85, 0xa5, 0x80, 0x65, 0x4d, 0x80, 0x42, 0xa3, 0x92, 0xe0, + 0xe6, 0x44, 0xe3, 0xc2, 0x89, 0x3a, 0x0e, 0xd7, 0x80, 0x64, 0x54, 0x55, 0x24, 0xb2, 0x9b, 0xa3, 0x26, 0xfb, 0x4a, + 0x5c, 0xa0, 0x0d, 0xfe, 0x7e, 0xbd, 0x76, 0x50, 0x62, 0xc8, 0xad, 0x4e, 0x8d, 0x31, 0x0e, 0xc0, 0x82, 0x25, 0x71, + 0xcc, 0xb0, 0x65, 0x7d, 0x36, 0x81, 0x53, 0xb6, 0xbb, 0x4f, 0x88, 0xac, 0x60, 0x53, 0x63, 0x2a, 0x3d, 0x77, 0x25, + 0x11, 0xa6, 0x9e, 0x2d, 0x2d, 0xaa, 0x89, 0x13, 0x12, 0x79, 0xed, 0x44, 0xd4, 0x5b, 0xd6, 0x84, 0xc3, 0x34, 0x28, + 0xb6, 0x4e, 0x81, 0xa8, 0x16, 0xbb, 0xe0, 0xbd, 0x0b, 0x6b, 0x6a, 0xed, 0x04, 0x10, 0x2f, 0x6a, 0x10, 0x0f, 0x40, + 0x2b, 0x2d, 0xf1, 0x92, 0x03, 0x42, 0xeb, 0x95, 0x63, 0x86, 0x0b, 0xbb, 0x10, 0x5b, 0x50, 0xdc, 0x64, 0x3f, 0x0d, + 0x16, 0x82, 0x2c, 0xab, 0x80, 0xbf, 0x0b, 0x8f, 0x88, 0x18, 0x06, 0x2f, 0x56, 0xab, 0x2d, 0xb4, 0xdb, 0xc9, 0x85, + 0xa2, 0xa4, 0x92, 0x0e, 0x57, 0xab, 0xaf, 0x12, 0xc5, 0x8e, 0xff, 0xc5, 0x0c, 0xf5, 0x3c, 0xd1, 0x7d, 0xf8, 0x12, + 0x4a, 0x19, 0x76, 0xb4, 0x4a, 0x29, 0x05, 0x87, 0x3a, 0xd6, 0xd6, 0x17, 0x4a, 0x07, 0x94, 0xfb, 0xf1, 0x16, 0x01, + 0x33, 0x89, 0xee, 0xa4, 0xae, 0xa6, 0xfc, 0xd8, 0x35, 0x2d, 0x10, 0x42, 0xa9, 0x32, 0xb2, 0xcc, 0xfe, 0x2e, 0xf9, + 0xf2, 0xe0, 0x40, 0x05, 0x0d, 0x5d, 0x97, 0x94, 0xe2, 0xef, 0x18, 0x4e, 0x65, 0x75, 0x27, 0x0c, 0xfb, 0xf2, 0xb7, + 0x3f, 0x87, 0xb6, 0xa4, 0xd3, 0x56, 0x17, 0x04, 0x73, 0x7a, 0x43, 0xb9, 0xde, 0x2b, 0x5b, 0xb1, 0x82, 0x79, 0xcc, + 0xd0, 0xd2, 0x71, 0x1b, 0x49, 0xc1, 0x80, 0x7f, 0x04, 0xb2, 0xe0, 0xb9, 0x68, 0x8b, 0xf8, 0xd9, 0x94, 0x81, 0x2a, + 0xdb, 0x33, 0x12, 0xa5, 0x78, 0xb8, 0xef, 0x0e, 0x12, 0xd7, 0xf0, 0xee, 0xb1, 0xaf, 0x37, 0xab, 0xd7, 0xa4, 0x81, + 0x39, 0x2b, 0xc6, 0xb2, 0x98, 0xf9, 0xbc, 0xf5, 0xc6, 0xb7, 0x23, 0x8e, 0x7c, 0x1c, 0xef, 0x6c, 0xdb, 0x89, 0x00, + 0xdd, 0x0d, 0xd9, 0xbb, 0x92, 0xda, 0x6b, 0xa7, 0x69, 0x79, 0x00, 0x5b, 0x05, 0xa1, 0xc7, 0x4c, 0x15, 0x4a, 0xf9, + 0x4e, 0xbd, 0xda, 0xb5, 0xba, 0x93, 0xfd, 0x76, 0xb7, 0x94, 0xfc, 0x3c, 0x36, 0x74, 0xad, 0x8e, 0xc3, 0x9d, 0xaa, + 0x72, 0x91, 0x8f, 0xdc, 0x60, 0x05, 0xc2, 0xcc, 0xe1, 0xd1, 0x0d, 0xcf, 0xf3, 0x2a, 0xf5, 0x3f, 0x21, 0xed, 0xca, + 0x91, 0x76, 0xe9, 0x49, 0x3b, 0x90, 0x0a, 0x20, 0xed, 0xb6, 0xb9, 0xaa, 0xba, 0xdc, 0xda, 0x9e, 0xd2, 0x12, 0x75, + 0x65, 0xc4, 0x69, 0xe8, 0x6f, 0xe1, 0x47, 0x80, 0x4a, 0xe6, 0xeb, 0x73, 0xec, 0xf4, 0x31, 0x20, 0x06, 0x5a, 0x9d, + 0x26, 0x0b, 0x35, 0x15, 0x9f, 0x63, 0x84, 0xd5, 0x9a, 0x95, 0x98, 0xfd, 0xf0, 0x29, 0x28, 0xed, 0x82, 0xe9, 0xc0, + 0x39, 0x66, 0x92, 0xff, 0x23, 0x3e, 0xca, 0xcf, 0x4e, 0xb8, 0xd9, 0x29, 0x3f, 0x3b, 0xa0, 0xf5, 0xd5, 0xec, 0x46, + 0xdf, 0xa7, 0xf6, 0x66, 0x7a, 0xa2, 0x9c, 0x5e, 0xb5, 0xde, 0xab, 0x55, 0xbc, 0x91, 0x02, 0x1a, 0x7d, 0x27, 0xa5, + 0x14, 0x65, 0xeb, 0x40, 0x03, 0x42, 0xc8, 0x40, 0xc2, 0xda, 0x4e, 0xba, 0x3c, 0xe5, 0x5e, 0xfe, 0x2b, 0x3d, 0x8f, + 0x51, 0xdc, 0xdb, 0xfa, 0x8f, 0xe5, 0x6c, 0x0e, 0x0c, 0xd9, 0x06, 0x4a, 0x4f, 0x98, 0xeb, 0xb0, 0xca, 0x5f, 0xef, + 0x48, 0xab, 0xd5, 0x31, 0xfb, 0xb1, 0x86, 0x4d, 0xa5, 0xd4, 0xbc, 0xdf, 0x5a, 0x2f, 0xca, 0xa4, 0x92, 0x70, 0xec, + 0xd2, 0xad, 0x3c, 0xde, 0xd4, 0xcc, 0xf8, 0x8c, 0xd7, 0xb1, 0xb0, 0x74, 0x58, 0x00, 0xad, 0x0b, 0xc8, 0x8f, 0x47, + 0xf7, 0x70, 0xfd, 0xd7, 0x15, 0x70, 0x96, 0xeb, 0x0d, 0xf0, 0x2d, 0xd7, 0xeb, 0x47, 0xda, 0x49, 0xda, 0xf8, 0xd1, + 0x0e, 0xb9, 0xb7, 0x84, 0x5e, 0x95, 0xe9, 0x64, 0xc6, 0xfe, 0x00, 0xd2, 0xb6, 0x58, 0x48, 0xb2, 0x9c, 0xc9, 0x11, + 0x4b, 0x23, 0x39, 0x67, 0x22, 0x5a, 0x83, 0x9e, 0xd5, 0x21, 0xc0, 0x3f, 0x22, 0x5e, 0xbe, 0xad, 0xeb, 0x5b, 0xd3, + 0x47, 0x7a, 0x0d, 0xaa, 0xb0, 0x97, 0x7c, 0x87, 0x32, 0xf6, 0x3d, 0x2b, 0x94, 0xe1, 0x49, 0x4b, 0xf6, 0xf6, 0x25, + 0xaf, 0x0e, 0xa8, 0x97, 0x3c, 0xfd, 0x76, 0x95, 0x4a, 0x20, 0x89, 0xda, 0xc9, 0x59, 0x72, 0x1c, 0x21, 0xa3, 0x31, + 0x7e, 0xe6, 0x35, 0xc6, 0x8b, 0x52, 0x63, 0xfc, 0x5c, 0x93, 0xc5, 0x86, 0xc6, 0xf8, 0x0f, 0x41, 0x9e, 0xeb, 0xde, + 0x73, 0xaf, 0x4d, 0x7f, 0x23, 0x73, 0x9e, 0xdd, 0xc5, 0x51, 0xce, 0x75, 0x13, 0x6e, 0x13, 0x23, 0xbc, 0xb4, 0x19, + 0xa0, 0x6a, 0x34, 0xfa, 0xee, 0xb5, 0x97, 0xff, 0xb0, 0x10, 0x24, 0xba, 0x97, 0x73, 0x7d, 0x2f, 0xc2, 0x53, 0x4d, + 0xfe, 0x82, 0x5f, 0xf7, 0x96, 0xf1, 0xaf, 0x54, 0x4f, 0x93, 0x82, 0x8a, 0x91, 0x9c, 0xc5, 0xa8, 0x11, 0x45, 0x28, + 0x51, 0x46, 0x08, 0x79, 0x80, 0xd6, 0xf7, 0xfe, 0xc2, 0xaf, 0x24, 0x89, 0x7a, 0x51, 0x63, 0xaa, 0xb1, 0xa6, 0xe4, + 0xaf, 0x8b, 0x7b, 0xcb, 0x57, 0x72, 0x7d, 0xf9, 0x17, 0x7e, 0xaa, 0x4b, 0xb5, 0x3e, 0xbe, 0x65, 0x24, 0x46, 0xe4, + 0xf2, 0xa9, 0x1f, 0xd2, 0x63, 0x39, 0xb3, 0x0a, 0xfe, 0x08, 0xe1, 0x2f, 0xa0, 0xd7, 0xbd, 0xe4, 0x15, 0x11, 0x72, + 0x77, 0x30, 0xfb, 0x24, 0x92, 0x46, 0x79, 0x10, 0x1d, 0x1c, 0x04, 0x69, 0x25, 0x0b, 0x81, 0xff, 0x96, 0xa4, 0x26, + 0xaa, 0x63, 0x46, 0xa1, 0xa5, 0xbf, 0x65, 0xcc, 0x91, 0x6f, 0x26, 0xf6, 0x9a, 0x6a, 0xb7, 0x63, 0x79, 0xdf, 0xea, + 0x1e, 0x12, 0xae, 0x59, 0x41, 0xb5, 0x2c, 0x06, 0x28, 0x64, 0x4b, 0xf0, 0x57, 0x4e, 0xfe, 0xea, 0xef, 0xfd, 0x3f, + 0xff, 0xe3, 0xcf, 0xf1, 0x9f, 0xc5, 0xe0, 0x2f, 0x2c, 0x18, 0x39, 0xba, 0x88, 0x7b, 0x69, 0xbc, 0xdf, 0x6c, 0xae, + 0xfe, 0x3c, 0xea, 0xff, 0x37, 0x6d, 0x7e, 0x7d, 0xd8, 0xfc, 0x34, 0x40, 0xab, 0xf8, 0xcf, 0xa3, 0x5e, 0xdf, 0x7d, + 0xf5, 0xff, 0xfb, 0xf2, 0x4f, 0x35, 0x38, 0xb4, 0x89, 0xf7, 0x10, 0x3a, 0x9a, 0xe0, 0x5f, 0x04, 0x39, 0x6a, 0x36, + 0x2f, 0x8f, 0x26, 0xf8, 0x27, 0x41, 0x8e, 0xe0, 0xef, 0x9d, 0x26, 0x6f, 0xd9, 0xe4, 0xe9, 0xed, 0x3c, 0xfe, 0xeb, + 0x72, 0x75, 0x6f, 0xf9, 0x95, 0xaf, 0xa1, 0xdd, 0xfe, 0x7f, 0xff, 0xf9, 0xa7, 0x8a, 0x7e, 0xbc, 0x24, 0x47, 0x83, + 0x06, 0x8a, 0x4d, 0xf2, 0x21, 0xb1, 0x7f, 0xe2, 0x5e, 0xda, 0xff, 0x6f, 0x37, 0x94, 0xe8, 0xc7, 0x3f, 0xff, 0xba, + 0xb8, 0x24, 0x83, 0x55, 0x1c, 0xad, 0x7e, 0x44, 0x2b, 0x84, 0x56, 0xf7, 0xd0, 0x5f, 0x38, 0x9a, 0x44, 0x08, 0xff, + 0x26, 0xc8, 0xd1, 0x8f, 0x47, 0x13, 0xfc, 0x49, 0x90, 0xa3, 0xe8, 0x68, 0x82, 0xdf, 0x4b, 0x72, 0xf4, 0xdf, 0x71, + 0x2f, 0xb5, 0x4a, 0xb8, 0x95, 0x51, 0x7f, 0xac, 0xe0, 0x26, 0x84, 0x16, 0x8c, 0xae, 0x34, 0xd7, 0x39, 0x43, 0xf7, + 0x8e, 0x38, 0x7e, 0x24, 0x01, 0x58, 0xb1, 0x06, 0x25, 0x8d, 0xb9, 0x84, 0x5d, 0x5e, 0xc3, 0xc2, 0x03, 0x06, 0xdd, + 0x4b, 0x39, 0xb6, 0x7a, 0x02, 0x95, 0x6a, 0x7b, 0x7b, 0xab, 0xe0, 0xfa, 0x16, 0x3f, 0x26, 0x8f, 0x64, 0xdc, 0x46, + 0x98, 0x53, 0xf8, 0xd1, 0x41, 0xf8, 0x83, 0x76, 0x17, 0x9e, 0xb0, 0xcd, 0x2d, 0x86, 0x09, 0x69, 0xf9, 0x99, 0x08, + 0xe1, 0x97, 0x3b, 0x32, 0xf5, 0x14, 0xd4, 0x0f, 0x08, 0xff, 0x5c, 0xbb, 0x1e, 0xc5, 0x8f, 0x35, 0x29, 0x91, 0xe3, + 0x5d, 0xc1, 0xd8, 0x07, 0x9a, 0x7f, 0x66, 0x45, 0xfc, 0x54, 0xe3, 0x76, 0xe7, 0x01, 0x36, 0xaa, 0xea, 0xfd, 0x36, + 0xea, 0x96, 0xb7, 0x5b, 0xcf, 0xa5, 0xbd, 0x4f, 0x80, 0x53, 0xb8, 0xae, 0xaf, 0x81, 0xb5, 0xdf, 0xe7, 0x5b, 0x4a, + 0xad, 0x82, 0xde, 0x44, 0xa8, 0x7e, 0x95, 0xca, 0xc5, 0x17, 0x9a, 0xf3, 0xd1, 0x9e, 0x66, 0xb3, 0x79, 0x4e, 0x35, + 0xdb, 0x73, 0x73, 0xde, 0xa3, 0xd0, 0x50, 0x54, 0xf2, 0x14, 0x7f, 0x88, 0x6a, 0xd3, 0xfe, 0x21, 0x92, 0x6a, 0xef, + 0xc4, 0x70, 0x9f, 0xe5, 0xf8, 0x12, 0x41, 0xcb, 0xeb, 0xb2, 0xcd, 0x1b, 0xc1, 0x66, 0x1b, 0x94, 0x65, 0x03, 0x73, + 0x7e, 0x2b, 0x0c, 0xf7, 0x9b, 0x84, 0x74, 0x7a, 0xd1, 0x85, 0xfa, 0x32, 0xb9, 0x8c, 0xe0, 0x26, 0xa7, 0x20, 0x82, + 0x19, 0xe5, 0x11, 0x94, 0xa0, 0xa4, 0xd5, 0xa5, 0x17, 0xac, 0x4b, 0x1b, 0x0d, 0xcf, 0x66, 0x67, 0x84, 0xf7, 0xa9, + 0xad, 0x9f, 0xe3, 0x29, 0x1e, 0x91, 0x66, 0x1b, 0x2f, 0x48, 0xcb, 0x54, 0xe9, 0x2e, 0x2e, 0x32, 0xd7, 0xcf, 0xc1, + 0x41, 0x5c, 0x24, 0x39, 0x55, 0xfa, 0x05, 0x68, 0x04, 0xc8, 0x02, 0x4f, 0x49, 0x91, 0xb0, 0x5b, 0x96, 0xc5, 0x19, + 0xc2, 0x53, 0x47, 0x83, 0x50, 0x17, 0x2d, 0x48, 0x50, 0x0c, 0xe4, 0x0c, 0x22, 0x58, 0x6f, 0xda, 0x6f, 0x0f, 0x08, + 0x21, 0xd1, 0x7e, 0xb3, 0x19, 0xf5, 0x0a, 0xf2, 0x8b, 0x48, 0x21, 0x25, 0x60, 0xa7, 0xc9, 0x4f, 0x90, 0xd4, 0x09, + 0x92, 0xe2, 0xf7, 0x32, 0xd1, 0x4c, 0xe9, 0x18, 0x92, 0x41, 0x49, 0xa0, 0x3c, 0x86, 0x47, 0x17, 0x47, 0x51, 0x03, + 0x52, 0x0d, 0x8a, 0x22, 0x5c, 0x90, 0x3b, 0x8d, 0xd2, 0x69, 0xff, 0x78, 0x10, 0x9e, 0x11, 0x36, 0x15, 0xfa, 0xbf, + 0xd3, 0xbd, 0x69, 0xbf, 0x65, 0xfa, 0xbf, 0x8c, 0x7a, 0x71, 0x41, 0x94, 0x65, 0xe3, 0x7a, 0x2a, 0x15, 0xcc, 0xcc, + 0x17, 0xa5, 0x6e, 0x80, 0xae, 0xef, 0x11, 0x69, 0x76, 0xd2, 0x78, 0x14, 0xce, 0xa4, 0x09, 0x1d, 0x3a, 0x50, 0xe0, + 0x9c, 0x40, 0x79, 0x5c, 0x10, 0xe8, 0xb4, 0xaa, 0x76, 0xa7, 0x53, 0x97, 0xf0, 0x63, 0xf4, 0x63, 0xef, 0x93, 0x48, + 0x7f, 0x13, 0x76, 0x04, 0x9f, 0xc4, 0x6a, 0x05, 0x7f, 0x7f, 0x13, 0x3d, 0x18, 0x96, 0x49, 0xfb, 0xc5, 0xa5, 0xfd, + 0x04, 0x69, 0x82, 0xa5, 0x66, 0xc0, 0x58, 0x95, 0xfc, 0x98, 0x5d, 0x9c, 0x31, 0xb1, 0x33, 0x38, 0x38, 0xe0, 0x7d, + 0xda, 0x68, 0x0f, 0xe0, 0x46, 0xa0, 0xd0, 0xea, 0x03, 0xd7, 0xd3, 0x38, 0x3a, 0xba, 0x8c, 0x50, 0x2f, 0xda, 0x83, + 0x55, 0xee, 0xca, 0x06, 0x71, 0xb0, 0xce, 0x1a, 0x9a, 0xa6, 0xa3, 0x4b, 0xd2, 0xea, 0xc5, 0xc2, 0x12, 0xf9, 0x1c, + 0xe1, 0xcc, 0xd1, 0xd4, 0x16, 0x1e, 0xa1, 0x86, 0x10, 0x0d, 0xff, 0x3d, 0x42, 0x8d, 0xa9, 0x6e, 0x8c, 0x51, 0x9a, + 0xc1, 0xdf, 0x78, 0x44, 0x08, 0x69, 0x76, 0xca, 0x8a, 0xfe, 0xb0, 0xa4, 0x28, 0x1d, 0x7b, 0xf5, 0x68, 0xdf, 0x6c, + 0x0e, 0xd9, 0x88, 0x79, 0x9f, 0x0d, 0x56, 0xab, 0xe8, 0xa2, 0x77, 0x19, 0xa1, 0x46, 0xec, 0xd1, 0xee, 0xc8, 0xe3, + 0x1d, 0x42, 0x58, 0x0c, 0xd6, 0xee, 0x06, 0xea, 0x86, 0xd5, 0x6e, 0x9b, 0x96, 0xd5, 0xfe, 0x0f, 0xc8, 0x02, 0x5b, + 0x97, 0x72, 0x8f, 0xe5, 0x6f, 0xe7, 0x30, 0x55, 0x8f, 0xdb, 0x92, 0xb4, 0x70, 0x41, 0xbc, 0xba, 0x9b, 0x12, 0x5d, + 0xe1, 0x7f, 0x46, 0xaa, 0xe2, 0xb8, 0x9f, 0xe3, 0xe9, 0x80, 0x08, 0x6a, 0xe4, 0x97, 0xae, 0x57, 0xa6, 0xb3, 0x9c, + 0xdc, 0xb0, 0x8d, 0xfb, 0xdf, 0x1c, 0xee, 0x64, 0x1e, 0xeb, 0x24, 0x5b, 0x14, 0x05, 0x13, 0xfa, 0x95, 0x1c, 0x39, + 0xc6, 0x8e, 0xe5, 0x20, 0x5b, 0xc1, 0xc5, 0x2e, 0x06, 0xae, 0xae, 0xe3, 0x77, 0xca, 0x68, 0x2b, 0x7b, 0x41, 0x46, + 0x96, 0xe1, 0x32, 0xd7, 0xbd, 0xdd, 0x85, 0x13, 0xa5, 0x63, 0x84, 0x47, 0xee, 0x1e, 0x38, 0x4e, 0x92, 0x64, 0x91, + 0x64, 0x90, 0x0d, 0x1d, 0x28, 0xb4, 0x36, 0xfb, 0x2a, 0x56, 0xe4, 0xb1, 0x4e, 0x04, 0xbb, 0x35, 0xdd, 0xc6, 0xa8, + 0x3a, 0xc4, 0xfd, 0x7e, 0xbb, 0xa0, 0x5d, 0x43, 0x80, 0x54, 0x22, 0xe4, 0x88, 0x01, 0x84, 0xe0, 0xee, 0xdf, 0x25, + 0x4d, 0xa9, 0x0a, 0x6f, 0xb6, 0xaa, 0x01, 0xf6, 0x43, 0x95, 0xf7, 0x02, 0xf4, 0xc4, 0x86, 0x3d, 0x2b, 0x0b, 0x5b, + 0xe5, 0x39, 0x42, 0x7c, 0x1c, 0x2f, 0x12, 0xb8, 0x11, 0x34, 0x98, 0x24, 0x04, 0x5a, 0xad, 0x16, 0x21, 0x6e, 0x4d, + 0x2b, 0xc5, 0xf4, 0x98, 0x4c, 0xfb, 0x45, 0xa3, 0x61, 0x94, 0xd7, 0x23, 0x8b, 0x17, 0x0b, 0x84, 0xc7, 0xe5, 0x5e, + 0xf3, 0xe5, 0xe6, 0xa4, 0xde, 0x55, 0x3c, 0xae, 0x2b, 0x81, 0x1b, 0x42, 0x20, 0xa3, 0x5f, 0xd4, 0xd0, 0x3a, 0x9e, + 0x90, 0xa3, 0xb8, 0x9f, 0xf4, 0xfe, 0xe7, 0x00, 0xf5, 0xe2, 0xe4, 0x10, 0x1d, 0x59, 0x5a, 0x32, 0x46, 0xdd, 0xcc, + 0xf6, 0xb1, 0x34, 0xb7, 0x9f, 0x6d, 0x6c, 0x14, 0x90, 0xa9, 0xc4, 0x82, 0xce, 0x58, 0x3a, 0x81, 0x5d, 0xef, 0x91, + 0x67, 0x8e, 0x01, 0x99, 0xd2, 0x89, 0xa3, 0x2d, 0x49, 0xd4, 0x93, 0xb4, 0xfc, 0xea, 0x45, 0x3d, 0x5a, 0x7d, 0xfd, + 0xcf, 0xa8, 0x97, 0xd1, 0xf4, 0x31, 0x5f, 0x3b, 0x25, 0x79, 0xad, 0x8f, 0x33, 0xdf, 0xc7, 0xda, 0x2e, 0x4e, 0x00, + 0xbc, 0x11, 0xda, 0xd6, 0x8e, 0x2c, 0xd0, 0x9a, 0x8f, 0x4b, 0xea, 0xa4, 0x12, 0x4d, 0x27, 0x00, 0xd5, 0x60, 0x11, + 0x54, 0x68, 0x1b, 0x10, 0x4c, 0x19, 0xb0, 0xc5, 0x23, 0x2d, 0x40, 0x73, 0x71, 0xd9, 0x42, 0xcb, 0x5a, 0x61, 0xc7, + 0x59, 0xd5, 0xef, 0xe2, 0x4b, 0xe2, 0x3d, 0x06, 0xaa, 0x7c, 0xb1, 0xe8, 0x8e, 0x1b, 0x0d, 0xa4, 0x3c, 0x7e, 0x8d, + 0xfa, 0xe3, 0x01, 0xbe, 0x05, 0x14, 0xc2, 0x35, 0x8c, 0xc2, 0xb5, 0x39, 0x76, 0xdc, 0x1c, 0x1b, 0x0d, 0xb9, 0x46, + 0xdd, 0xa0, 0xf2, 0xc2, 0x55, 0x5e, 0xaf, 0x2d, 0x64, 0x36, 0x31, 0xee, 0x1c, 0x99, 0x14, 0x30, 0x04, 0x23, 0x84, + 0xbc, 0x92, 0x68, 0x67, 0xb3, 0xd0, 0x28, 0x54, 0x37, 0xbb, 0x17, 0x28, 0xaa, 0x3d, 0x3d, 0x62, 0x80, 0x05, 0x54, + 0x2d, 0xd5, 0xc8, 0x53, 0x8d, 0x47, 0x8d, 0xb6, 0x41, 0xf7, 0x66, 0xbb, 0x5b, 0x6f, 0xec, 0x7e, 0xd5, 0x18, 0x1e, + 0x35, 0xc8, 0xb4, 0xda, 0xe1, 0x6b, 0xd9, 0x68, 0xac, 0xeb, 0xf7, 0xa5, 0x7e, 0x13, 0xd7, 0xee, 0x2f, 0x9e, 0x6e, + 0x99, 0x78, 0xf8, 0xd3, 0xb7, 0x3a, 0x6f, 0x45, 0xc2, 0x85, 0x60, 0x05, 0x9c, 0xb0, 0x44, 0x63, 0xb1, 0x5e, 0x97, + 0xa7, 0xfe, 0xef, 0xda, 0xda, 0x8c, 0x11, 0x0e, 0x74, 0xc8, 0x48, 0x6d, 0x58, 0xe2, 0x02, 0x53, 0x43, 0x45, 0x08, + 0x21, 0x1f, 0xb4, 0x37, 0x8f, 0xd1, 0x86, 0x24, 0x65, 0x24, 0x38, 0xbb, 0x63, 0x45, 0x58, 0x72, 0x7d, 0xef, 0xb1, + 0xfc, 0xae, 0x48, 0xd7, 0x17, 0x83, 0xd4, 0x14, 0xcb, 0x1d, 0x21, 0xcb, 0xc9, 0x17, 0x90, 0x73, 0xca, 0x0b, 0x96, + 0xc4, 0x10, 0xc4, 0x27, 0xbc, 0x60, 0x86, 0x71, 0xbf, 0xe7, 0xe5, 0xc6, 0xac, 0xce, 0x69, 0x66, 0xa1, 0xf6, 0x07, + 0xa0, 0x99, 0x83, 0x72, 0x48, 0x92, 0xad, 0x62, 0xd7, 0xf7, 0x1e, 0xbe, 0xde, 0x25, 0x43, 0xaf, 0x56, 0x4e, 0x7a, + 0xce, 0x80, 0xf5, 0xc1, 0x79, 0x35, 0xd4, 0xcc, 0xfd, 0x48, 0xe3, 0xcc, 0x30, 0x51, 0x79, 0xcc, 0x01, 0x99, 0xae, + 0xef, 0x3d, 0x7c, 0x17, 0x73, 0xa3, 0x9b, 0x42, 0x38, 0x9c, 0x77, 0x5c, 0x90, 0x98, 0x12, 0x86, 0xec, 0xe4, 0x4b, + 0x3a, 0x56, 0x04, 0xa7, 0x7b, 0x4a, 0x4d, 0x26, 0x88, 0x1d, 0x7d, 0x31, 0x20, 0x99, 0x03, 0x01, 0xc9, 0x10, 0xce, + 0x6a, 0x72, 0x1d, 0x31, 0x6b, 0x60, 0x3a, 0xbb, 0x82, 0xc5, 0x48, 0x2c, 0x7b, 0x88, 0x70, 0x66, 0xba, 0xd5, 0x6b, + 0x7b, 0x9c, 0x28, 0xba, 0x69, 0xe8, 0x56, 0xc9, 0xb3, 0xef, 0x41, 0xf0, 0xf2, 0x1f, 0xaf, 0x5c, 0xdb, 0x65, 0xc2, + 0x13, 0x6f, 0x91, 0x76, 0x7d, 0xef, 0xe1, 0xaf, 0xce, 0x28, 0x6d, 0x4e, 0x3d, 0xf9, 0xdf, 0x92, 0x51, 0x1f, 0xfe, + 0x9a, 0x54, 0xb9, 0xa6, 0xf0, 0xf5, 0xbd, 0x87, 0xbf, 0xef, 0x2a, 0x06, 0xe9, 0xeb, 0x45, 0xa5, 0x24, 0x30, 0xe3, + 0x5b, 0xb2, 0x3c, 0x5d, 0xba, 0xb3, 0x22, 0x15, 0x6b, 0x6c, 0x4e, 0xa8, 0x54, 0xad, 0x4b, 0xdd, 0xca, 0x13, 0x2c, + 0x89, 0xb9, 0x4a, 0xaa, 0x2f, 0x9b, 0x43, 0x63, 0x2e, 0xc5, 0x55, 0x26, 0xe7, 0xec, 0x1b, 0xf7, 0x4b, 0x4f, 0x35, + 0x4a, 0xf8, 0x0c, 0x0c, 0x71, 0xcc, 0xd8, 0x05, 0xde, 0x6f, 0xa1, 0xee, 0xc6, 0x79, 0x26, 0x0d, 0xa2, 0x16, 0xf5, + 0xc3, 0x06, 0x53, 0xd2, 0xc2, 0x19, 0x69, 0xe1, 0x9c, 0xa8, 0x7e, 0xcb, 0x9e, 0x18, 0xdd, 0xbc, 0x6c, 0xda, 0x9e, + 0x3b, 0xb0, 0xdd, 0x73, 0xbb, 0x6f, 0xed, 0xa1, 0x3c, 0xed, 0xe6, 0x46, 0x7f, 0x69, 0x0e, 0xfa, 0xa9, 0x41, 0x8d, + 0x27, 0x2c, 0x2e, 0x70, 0x61, 0x5a, 0xbe, 0xe2, 0xc3, 0x1c, 0xec, 0x54, 0x60, 0x66, 0x58, 0xa3, 0xb4, 0x2c, 0xdb, + 0x76, 0x65, 0xf3, 0xc4, 0xac, 0x55, 0x81, 0xf3, 0x04, 0x48, 0x39, 0xce, 0x9d, 0x5d, 0x8f, 0xda, 0xae, 0x72, 0x76, + 0x70, 0x10, 0xbb, 0x4a, 0x34, 0x2e, 0x7c, 0x7e, 0x75, 0x03, 0xf8, 0xde, 0x52, 0x8d, 0x29, 0x32, 0x13, 0x68, 0x34, + 0xb2, 0xc1, 0x9a, 0xee, 0x13, 0x12, 0xe7, 0x75, 0x28, 0xfa, 0xd1, 0x1b, 0x66, 0x70, 0x03, 0x00, 0x8d, 0x46, 0x79, + 0xdd, 0xbb, 0x01, 0xb1, 0xa7, 0x1a, 0xcb, 0xf5, 0x97, 0xb8, 0xb4, 0x26, 0x6a, 0x6d, 0xd9, 0x61, 0xf9, 0x51, 0x20, + 0x11, 0xe2, 0xae, 0xf0, 0xf3, 0x09, 0xb6, 0x86, 0x80, 0x72, 0x2f, 0x9c, 0x0d, 0x04, 0x36, 0x56, 0x5b, 0xae, 0x90, + 0x27, 0x6d, 0x1d, 0x94, 0xfa, 0x42, 0x70, 0xc1, 0x05, 0x85, 0x1a, 0x6b, 0x87, 0xe5, 0x4f, 0xd8, 0xb6, 0x39, 0x27, + 0x56, 0xc8, 0x69, 0xcb, 0xcc, 0x30, 0x0c, 0xc0, 0x3a, 0x25, 0x60, 0x9e, 0x93, 0x97, 0xdf, 0x46, 0xfd, 0x87, 0x01, + 0xea, 0x3f, 0x22, 0x2c, 0xd8, 0x06, 0x56, 0x57, 0x92, 0x48, 0xa7, 0xa0, 0x50, 0x3e, 0xeb, 0xf1, 0x9c, 0x80, 0x36, + 0xae, 0x0e, 0xd5, 0xda, 0x15, 0xe5, 0x37, 0x28, 0x4b, 0xb8, 0x53, 0x8c, 0x3e, 0x13, 0xfb, 0xfb, 0xe4, 0xb8, 0xba, + 0xa0, 0x83, 0xae, 0x77, 0x29, 0x07, 0x43, 0x52, 0xf8, 0xf0, 0xf7, 0xef, 0xdf, 0xad, 0x3e, 0x9e, 0x6f, 0xef, 0xe0, + 0xc0, 0xac, 0x14, 0x66, 0x1d, 0x6c, 0xe0, 0xba, 0x91, 0x29, 0xf4, 0x5f, 0xde, 0x89, 0xd7, 0xa9, 0xd0, 0xc6, 0x66, + 0xf4, 0xc7, 0x21, 0x8c, 0xb6, 0xdd, 0x36, 0x25, 0x58, 0xd0, 0x2c, 0xd0, 0x25, 0x6b, 0xdc, 0x4a, 0x8b, 0x6f, 0x90, + 0x91, 0x87, 0xa6, 0x00, 0x13, 0xa3, 0xdd, 0xd9, 0x8f, 0xd6, 0x0e, 0x4f, 0xec, 0xd0, 0xd0, 0xd2, 0x10, 0x42, 0x8b, + 0xf7, 0x80, 0x39, 0xf6, 0x88, 0x00, 0x10, 0xbd, 0x34, 0x90, 0xaa, 0x40, 0x16, 0x45, 0x95, 0x22, 0xff, 0xf9, 0x3e, + 0x21, 0x2f, 0x2b, 0x45, 0xe6, 0xdb, 0xca, 0x98, 0x0b, 0x10, 0x03, 0xa5, 0x70, 0x91, 0x50, 0x26, 0xd8, 0xcb, 0xd0, + 0x0f, 0xda, 0x97, 0x37, 0xd2, 0x66, 0x52, 0x71, 0xe3, 0xc1, 0x4d, 0xa9, 0x51, 0xf1, 0xd9, 0x7c, 0x0f, 0x89, 0x8d, + 0xdc, 0x7b, 0x90, 0xcb, 0xa8, 0x19, 0x24, 0x7c, 0xbf, 0x33, 0xa5, 0x7d, 0xbb, 0xeb, 0xcf, 0x9b, 0x16, 0x31, 0x1b, + 0xeb, 0x92, 0x70, 0xa1, 0x58, 0xa1, 0x1f, 0xb1, 0xb1, 0x2c, 0xe0, 0xfe, 0xa3, 0x04, 0x0b, 0x5a, 0xdf, 0x0b, 0x74, + 0x80, 0x66, 0x82, 0xc1, 0xa5, 0xc3, 0xc6, 0x0c, 0xcd, 0xaf, 0xcf, 0xe6, 0x0e, 0xfc, 0x7a, 0xb3, 0xd6, 0xcb, 0x83, + 0x83, 0x2f, 0xac, 0x02, 0x94, 0x1b, 0xa6, 0x19, 0x46, 0x40, 0xbc, 0x2c, 0x97, 0xe3, 0x6e, 0x86, 0xef, 0xc5, 0x95, + 0xca, 0xc0, 0x13, 0x8e, 0x90, 0x08, 0x3d, 0x27, 0x7a, 0x3d, 0xd9, 0xa4, 0xf7, 0x4e, 0x9b, 0x21, 0x42, 0xb1, 0x06, + 0xc8, 0x3d, 0xc8, 0xe5, 0x56, 0xc9, 0xa4, 0x2a, 0x5b, 0xdb, 0x72, 0x10, 0x8f, 0x01, 0x5c, 0xb1, 0x11, 0x52, 0x02, + 0x34, 0xdc, 0x2d, 0xb4, 0x3c, 0x97, 0xc0, 0xfe, 0x63, 0x95, 0x80, 0x48, 0x8b, 0x6a, 0x1b, 0x17, 0x21, 0x6c, 0x4d, + 0x7d, 0x02, 0xe3, 0x84, 0x87, 0xcf, 0x77, 0x69, 0xa8, 0x3d, 0x6a, 0x33, 0x73, 0x06, 0x41, 0x09, 0x89, 0xca, 0x0a, + 0xc9, 0x97, 0x58, 0x38, 0x6e, 0xce, 0xdf, 0xc3, 0x01, 0x29, 0x56, 0x34, 0xb6, 0x77, 0x5b, 0x70, 0x7c, 0x14, 0xc9, + 0x22, 0xae, 0x75, 0xdd, 0x2d, 0x4c, 0x35, 0xec, 0x40, 0x47, 0x43, 0x38, 0x15, 0xe6, 0x9e, 0xf0, 0x71, 0x45, 0x52, + 0x7f, 0xb6, 0x26, 0xda, 0xda, 0x13, 0xc3, 0xca, 0x34, 0x25, 0x98, 0xff, 0xcf, 0xd6, 0xea, 0xba, 0x2c, 0x84, 0x99, + 0x19, 0xc6, 0x8d, 0x5d, 0x05, 0xb6, 0x06, 0x1c, 0x5b, 0xfe, 0x2d, 0x83, 0x45, 0xf5, 0x4a, 0x71, 0xd3, 0x69, 0xc0, + 0x04, 0xbc, 0x05, 0xeb, 0x99, 0xcd, 0xad, 0xff, 0xdc, 0x1c, 0x8c, 0x02, 0xab, 0x1a, 0x81, 0x97, 0x86, 0xc0, 0x23, + 0x60, 0xdc, 0xbc, 0x69, 0x79, 0xcf, 0x19, 0xd1, 0x08, 0x7f, 0xe2, 0x39, 0x3c, 0xb3, 0x2c, 0xf7, 0xd6, 0xc7, 0xc6, + 0x8a, 0xa4, 0x82, 0x80, 0x6d, 0x11, 0x76, 0x44, 0x5e, 0x22, 0xac, 0x1a, 0x8d, 0xae, 0xba, 0x60, 0x95, 0x56, 0xa5, + 0x1a, 0xa6, 0x80, 0x5b, 0x62, 0xc0, 0xfb, 0xda, 0x89, 0x0a, 0x86, 0x04, 0xde, 0xfa, 0x5b, 0x81, 0xfa, 0xfe, 0xe1, + 0xdb, 0x38, 0xa4, 0x6f, 0x61, 0xd9, 0xf2, 0x22, 0x16, 0xa6, 0x14, 0x57, 0x77, 0x38, 0x6f, 0xbe, 0x6f, 0x36, 0x02, + 0xe3, 0xde, 0x6f, 0x63, 0xb0, 0x71, 0x43, 0x5d, 0x6d, 0x49, 0x43, 0xb9, 0x09, 0xbb, 0xa8, 0xb2, 0x77, 0x0c, 0x3b, + 0xeb, 0xea, 0x4a, 0xda, 0xd5, 0x44, 0xad, 0xd7, 0x8a, 0x55, 0x46, 0x03, 0x1b, 0x86, 0x9d, 0xe6, 0x98, 0xd9, 0x56, + 0xe0, 0x3f, 0x9e, 0x13, 0x8d, 0x03, 0x64, 0x7d, 0xf3, 0xad, 0xeb, 0x94, 0x6a, 0x98, 0xb0, 0xbd, 0xdd, 0xf9, 0xf8, + 0x98, 0xef, 0x3a, 0x1f, 0xb1, 0x74, 0x5b, 0xdf, 0x9c, 0x8d, 0xed, 0x7f, 0xe3, 0x6c, 0x74, 0x6a, 0x7b, 0x7f, 0x3c, + 0x02, 0x77, 0x52, 0x3b, 0x1e, 0xeb, 0x6b, 0x4a, 0x24, 0x16, 0x6e, 0x39, 0x2e, 0x3b, 0xab, 0x95, 0xe8, 0xb7, 0x40, + 0xed, 0x14, 0x45, 0xf0, 0xb3, 0x6d, 0x7f, 0x06, 0x24, 0xd9, 0xea, 0x90, 0x63, 0x51, 0x8a, 0x32, 0x28, 0x01, 0x03, + 0xea, 0xd8, 0xd8, 0x7a, 0x19, 0xc4, 0x76, 0x38, 0xe4, 0xb0, 0x9c, 0x88, 0xf2, 0xea, 0x0a, 0x46, 0x6c, 0x8e, 0x0d, + 0x27, 0x60, 0xc6, 0x3b, 0xad, 0x0a, 0xbd, 0xf8, 0xf9, 0xaf, 0x99, 0xd3, 0xda, 0x11, 0x63, 0x39, 0x89, 0x9a, 0x15, + 0x83, 0x1b, 0x81, 0x63, 0x18, 0xf7, 0x8d, 0x84, 0x5a, 0x9d, 0xea, 0xa8, 0x76, 0x24, 0xe1, 0x16, 0xa8, 0xdd, 0xf6, + 0xcd, 0xb9, 0xb4, 0x5a, 0xed, 0x3c, 0x58, 0x70, 0x11, 0xe0, 0xf6, 0x73, 0xa2, 0x6b, 0x24, 0x85, 0x12, 0x27, 0x41, + 0xe1, 0xdc, 0xa0, 0xaa, 0x26, 0xb2, 0xdf, 0x1a, 0x00, 0x4f, 0xda, 0xcd, 0x2e, 0x64, 0x25, 0x24, 0x67, 0x8d, 0x06, + 0xca, 0xcb, 0x8e, 0x69, 0x5f, 0x34, 0xb2, 0x01, 0x66, 0x38, 0xb3, 0x02, 0x0b, 0x9c, 0x5e, 0x71, 0x5e, 0x75, 0xdd, + 0xcf, 0x06, 0x08, 0x17, 0xab, 0x55, 0x6c, 0x87, 0x96, 0xa3, 0xd5, 0x2a, 0x0f, 0x87, 0x66, 0xf2, 0xa1, 0xe2, 0xcb, + 0x9e, 0x26, 0x2f, 0xcd, 0x79, 0xf8, 0x12, 0x06, 0xd9, 0x20, 0x71, 0xee, 0x54, 0x82, 0x39, 0x68, 0xae, 0x1a, 0xb2, + 0x9f, 0x35, 0xda, 0x83, 0x80, 0x86, 0xf5, 0xb3, 0x01, 0xc9, 0xd7, 0x60, 0x39, 0xab, 0xdc, 0x81, 0xf9, 0x37, 0x1c, + 0x6c, 0x7f, 0x9b, 0x73, 0xc6, 0x36, 0x18, 0xae, 0xc9, 0xa6, 0xca, 0xa0, 0xc4, 0x2b, 0xb7, 0xb8, 0xbe, 0x5c, 0xcd, + 0xc0, 0xa2, 0x2c, 0x84, 0xdd, 0x35, 0x73, 0x0f, 0x84, 0xff, 0x12, 0xdb, 0x25, 0x2d, 0x8d, 0xb8, 0x37, 0x10, 0xdf, + 0xdb, 0x6e, 0x27, 0x49, 0x42, 0x8b, 0x89, 0xb9, 0x12, 0xf1, 0x37, 0xbc, 0x66, 0x0f, 0x1c, 0xbb, 0x71, 0x06, 0x3d, + 0xf7, 0xcb, 0xce, 0x06, 0xc4, 0x8e, 0xdf, 0x33, 0x3b, 0xde, 0x71, 0xa5, 0xa0, 0xbb, 0x75, 0x11, 0x76, 0x30, 0xf4, + 0x7f, 0x79, 0x30, 0x27, 0x6e, 0x30, 0x16, 0x4d, 0x36, 0xe0, 0xf6, 0x0d, 0x78, 0x14, 0x74, 0x03, 0x6e, 0xdf, 0x86, + 0xaf, 0x87, 0x56, 0xf6, 0xcd, 0x01, 0x06, 0x64, 0xc2, 0x8e, 0xb4, 0x4a, 0x08, 0x86, 0x79, 0xba, 0xc9, 0x91, 0x59, + 0xb2, 0x0a, 0x87, 0xab, 0x26, 0xb1, 0xd8, 0xd8, 0x0b, 0x15, 0x93, 0x1a, 0x08, 0xc6, 0x22, 0x7d, 0x89, 0x42, 0xa5, + 0x41, 0xdd, 0x38, 0x06, 0xb0, 0xca, 0x69, 0xeb, 0x5f, 0x1e, 0x1c, 0x80, 0xd0, 0x00, 0xac, 0x5d, 0x92, 0xd1, 0xb9, + 0x5e, 0x14, 0xc0, 0x5f, 0x29, 0xff, 0x1b, 0x92, 0xc1, 0xed, 0xc4, 0xa4, 0xc1, 0x0f, 0x48, 0x98, 0x53, 0xa5, 0xf8, + 0x17, 0x9b, 0xe6, 0x7e, 0xe3, 0x82, 0x78, 0x8c, 0x56, 0x96, 0x53, 0x94, 0xa8, 0x2b, 0x1d, 0xba, 0xd6, 0x21, 0xf7, + 0xf4, 0x0b, 0x13, 0xfa, 0x25, 0x57, 0x9a, 0x09, 0x00, 0x40, 0x85, 0x78, 0x30, 0x25, 0x85, 0x60, 0xeb, 0xd6, 0x6a, + 0xd1, 0xd1, 0xe8, 0xbb, 0x55, 0x74, 0x9d, 0x2d, 0x9a, 0x52, 0x31, 0xca, 0x6d, 0x27, 0xa1, 0xcd, 0xa4, 0xb7, 0x13, + 0x2d, 0x4b, 0x86, 0x16, 0x3b, 0x15, 0xfb, 0x61, 0x68, 0x7d, 0x2c, 0x88, 0x3f, 0x17, 0xfc, 0x59, 0xfa, 0x5d, 0x3e, + 0x06, 0xae, 0xd4, 0xbf, 0xb1, 0x0a, 0xe1, 0x4c, 0xb0, 0x0e, 0xc8, 0x6b, 0x52, 0x1f, 0xa7, 0x47, 0x9d, 0x7c, 0x4b, + 0xb9, 0x50, 0x1a, 0x85, 0x6d, 0x9c, 0x14, 0x06, 0x53, 0xce, 0xbe, 0x2d, 0x71, 0xfd, 0xea, 0x8f, 0x11, 0x7f, 0x74, + 0x88, 0x7f, 0x97, 0x4a, 0xa3, 0x65, 0x89, 0x60, 0xc8, 0xef, 0x48, 0xad, 0xe0, 0x2a, 0x36, 0xe7, 0xfa, 0xb9, 0x9e, + 0xe5, 0x1b, 0x9e, 0x38, 0x5d, 0xad, 0x4a, 0xa9, 0x40, 0xc5, 0x37, 0x0c, 0x3f, 0x61, 0x70, 0x6f, 0xfc, 0x8c, 0x07, + 0x55, 0xb6, 0xef, 0x8b, 0x9f, 0x05, 0xf7, 0xc5, 0xcf, 0x78, 0xba, 0x5d, 0x34, 0xb8, 0x27, 0xee, 0x24, 0xe7, 0x49, + 0x2b, 0xf2, 0x7c, 0xd4, 0x94, 0x56, 0xfe, 0x95, 0x76, 0x6b, 0xe0, 0xca, 0x26, 0x0e, 0x8c, 0xf3, 0xea, 0x22, 0x14, + 0x73, 0xe6, 0x8c, 0x96, 0xc3, 0xff, 0xd6, 0x3a, 0xb9, 0x93, 0x47, 0x5a, 0x29, 0xe4, 0x0d, 0x2d, 0xf4, 0x3d, 0xd8, + 0x70, 0xc5, 0x96, 0x0f, 0x20, 0x25, 0xa0, 0x6c, 0xfb, 0xf7, 0xba, 0x08, 0xc4, 0x71, 0x65, 0x9d, 0x8f, 0xc2, 0xf6, + 0x49, 0x51, 0x72, 0x75, 0x75, 0x21, 0xe4, 0xd6, 0x68, 0x09, 0x10, 0xa6, 0xde, 0x35, 0x8f, 0x39, 0x9a, 0xcc, 0xd2, + 0xe5, 0xba, 0x54, 0x1d, 0x14, 0x96, 0xab, 0xe3, 0x08, 0x17, 0x6b, 0x73, 0x83, 0xfe, 0x8a, 0xe3, 0xbf, 0xb9, 0xa3, + 0x91, 0x9f, 0x4a, 0x0a, 0xf4, 0x68, 0xb7, 0xaf, 0xcd, 0x0e, 0x12, 0x69, 0xe7, 0x50, 0x5a, 0x0a, 0x00, 0x56, 0x1b, + 0x7c, 0x5d, 0x7b, 0x9c, 0x7a, 0x22, 0xdd, 0x6c, 0xbe, 0x69, 0x08, 0x8b, 0x59, 0x69, 0xc1, 0x63, 0xba, 0xd9, 0x61, + 0x39, 0xea, 0x65, 0x71, 0x5d, 0xee, 0xb1, 0x5a, 0xbf, 0xe8, 0x1b, 0xa0, 0xac, 0x0c, 0xd1, 0x56, 0xab, 0xb8, 0x0e, + 0x6f, 0x22, 0x82, 0x6b, 0x10, 0x84, 0x45, 0x60, 0xc0, 0x51, 0x63, 0xbc, 0x6d, 0x9d, 0x18, 0x6d, 0xda, 0x2f, 0x79, + 0xd6, 0xbd, 0x36, 0x8e, 0x50, 0xd1, 0x60, 0xab, 0x87, 0x9a, 0x07, 0x6c, 0x67, 0x57, 0x76, 0x14, 0x40, 0x68, 0x4a, + 0xbd, 0x71, 0x6e, 0x65, 0x45, 0xbb, 0x03, 0xbe, 0xe8, 0x3b, 0xe6, 0xb9, 0x0e, 0x74, 0xdb, 0xf9, 0x81, 0x6d, 0xd3, + 0x13, 0xf9, 0x2d, 0xdb, 0xa6, 0x1a, 0x27, 0xbc, 0xdf, 0x42, 0xdf, 0x37, 0x84, 0xb5, 0x7d, 0xed, 0x2e, 0xf2, 0xbf, + 0xd0, 0x5d, 0x1b, 0xd0, 0xd3, 0x82, 0xd9, 0xd3, 0x98, 0x0f, 0x7a, 0xbd, 0xfe, 0x54, 0xfa, 0x2f, 0x18, 0x5b, 0xa1, + 0x4f, 0x76, 0x17, 0x38, 0xb1, 0xd2, 0x38, 0x04, 0xc7, 0xaf, 0x38, 0x99, 0xe4, 0x72, 0x48, 0xf3, 0x77, 0xd0, 0x63, + 0x95, 0xfb, 0xfc, 0x6e, 0x54, 0x50, 0xcd, 0x1c, 0xad, 0xa9, 0x46, 0xf1, 0x8a, 0x07, 0xc3, 0x78, 0xc5, 0x2d, 0xe5, + 0xae, 0x5a, 0xc0, 0xcb, 0x97, 0x65, 0x13, 0xe9, 0xa7, 0x75, 0x29, 0x83, 0xa9, 0xdd, 0xbd, 0x6c, 0x92, 0x34, 0x56, + 0x92, 0x34, 0xa6, 0xe2, 0xcd, 0xa6, 0xe2, 0xf8, 0xef, 0x6f, 0x0c, 0x76, 0x9b, 0xcc, 0xfd, 0x1d, 0x90, 0xb9, 0xbf, + 0x79, 0xfa, 0xdd, 0x5a, 0x01, 0xc5, 0x3b, 0x4e, 0x8e, 0x8d, 0x65, 0x8c, 0x1d, 0xf5, 0x5b, 0x0d, 0x06, 0x0d, 0x9a, + 0x5c, 0x06, 0xde, 0x0e, 0xd5, 0xe9, 0xe5, 0xed, 0x8f, 0xe2, 0x6c, 0xa1, 0xb4, 0x9c, 0xb9, 0x46, 0x95, 0xf3, 0x71, + 0x32, 0x99, 0xa0, 0xc0, 0x36, 0x77, 0xf8, 0x69, 0xdd, 0x8d, 0x6c, 0xf9, 0x99, 0x8b, 0x51, 0xaa, 0xb0, 0x3b, 0x5b, + 0x54, 0x2a, 0xd7, 0xc4, 0x9b, 0x39, 0x6f, 0xe7, 0xe1, 0x31, 0x17, 0x5c, 0x4d, 0x59, 0x11, 0x17, 0x68, 0xf9, 0xad, + 0xce, 0x0a, 0xb8, 0xcd, 0xb1, 0x9d, 0xe1, 0x51, 0x69, 0x39, 0xa0, 0x13, 0x68, 0x0d, 0x74, 0x46, 0x33, 0xa6, 0xa7, + 0x72, 0x04, 0x86, 0x2f, 0xc9, 0xa8, 0x74, 0xa7, 0x3a, 0x38, 0xd8, 0x8f, 0x23, 0xa3, 0xbf, 0x00, 0x1f, 0xf4, 0x30, + 0x07, 0xf5, 0x96, 0xe0, 0x18, 0x54, 0x75, 0xcd, 0xd0, 0x92, 0x6d, 0xfa, 0xd0, 0xe8, 0xe4, 0x33, 0xbb, 0xc3, 0x1c, + 0xad, 0xd7, 0xa9, 0x1d, 0x75, 0x34, 0xe6, 0x2c, 0x1f, 0x45, 0xf8, 0x33, 0xbb, 0x4b, 0x4b, 0xb7, 0x75, 0xe3, 0x65, + 0x6d, 0x16, 0x31, 0x92, 0x37, 0x22, 0xc2, 0x55, 0x27, 0xe9, 0x72, 0x8d, 0x65, 0xc1, 0x27, 0x80, 0xa3, 0xbf, 0xb0, + 0xbb, 0xd4, 0xb5, 0x17, 0xb8, 0x0a, 0xa2, 0xa5, 0x07, 0x7d, 0x12, 0x24, 0x87, 0xcb, 0xe0, 0x04, 0x8e, 0xbe, 0xa9, + 0x3b, 0x20, 0xb5, 0x72, 0x95, 0x08, 0x89, 0xd0, 0xfa, 0xdf, 0x9d, 0x0a, 0x5e, 0x84, 0xe7, 0x9c, 0xae, 0x59, 0xdc, + 0x6e, 0x54, 0x62, 0x50, 0xa1, 0xb2, 0x20, 0xf9, 0x18, 0x73, 0xbf, 0xfb, 0x9c, 0xf7, 0x43, 0xa0, 0x33, 0x5b, 0x50, + 0xd7, 0x68, 0x3a, 0x32, 0xbf, 0x50, 0x75, 0x07, 0x35, 0xd3, 0x55, 0xc5, 0xbd, 0x8f, 0x31, 0x00, 0x1e, 0xac, 0x65, + 0xa8, 0x71, 0x08, 0x5d, 0x7b, 0x33, 0xd5, 0x31, 0x25, 0xf1, 0xd2, 0xcf, 0x21, 0xe5, 0x21, 0x18, 0xf5, 0x1a, 0xd0, + 0xd0, 0x21, 0x98, 0xb5, 0x3c, 0xe4, 0xe3, 0x58, 0x6c, 0x9d, 0xa1, 0xd2, 0x9c, 0xa1, 0x49, 0x00, 0xf2, 0x6f, 0x9c, + 0x99, 0xcc, 0x40, 0xc3, 0xf0, 0x96, 0xe6, 0x00, 0x74, 0xab, 0xeb, 0x70, 0x28, 0x5c, 0xd1, 0xd2, 0x79, 0xcf, 0x2e, + 0xba, 0xac, 0x0d, 0x2b, 0x36, 0xed, 0xa0, 0x75, 0x0a, 0x53, 0x62, 0xb6, 0xc0, 0xda, 0xeb, 0x7d, 0xb8, 0xb7, 0xab, + 0x8d, 0x8b, 0xc4, 0x4f, 0x8b, 0x78, 0x98, 0xc4, 0x14, 0x2d, 0x79, 0x4c, 0xb1, 0x04, 0x3b, 0xc8, 0x62, 0x5d, 0x8e, + 0x9f, 0x85, 0xcb, 0x51, 0xb3, 0x92, 0xde, 0xed, 0x60, 0x08, 0x5c, 0xbe, 0x06, 0xdb, 0x50, 0xcc, 0x3d, 0x61, 0xe1, + 0xb1, 0xf1, 0xf4, 0x0b, 0xd6, 0x6d, 0x6e, 0x17, 0xc4, 0xaf, 0xc0, 0x98, 0xc6, 0xcb, 0x60, 0x16, 0xa1, 0x53, 0xb9, + 0x73, 0x38, 0x74, 0xd7, 0x84, 0x95, 0xf1, 0x6a, 0xac, 0xc8, 0xc6, 0xd1, 0xf3, 0x7d, 0x1b, 0xcf, 0x7f, 0x16, 0xac, + 0xb8, 0xbb, 0x62, 0x60, 0x63, 0x2d, 0xc1, 0xdd, 0xb8, 0x5a, 0x86, 0xca, 0x40, 0xbe, 0x27, 0x0d, 0xeb, 0xb2, 0xc6, + 0xdf, 0x8d, 0x8a, 0xb1, 0x36, 0xf7, 0x94, 0x81, 0xb6, 0xc6, 0x6e, 0x17, 0xf6, 0x4d, 0xd7, 0x4d, 0xd6, 0x35, 0x8a, + 0xb8, 0x0a, 0xd2, 0xee, 0x6e, 0x01, 0x17, 0xa1, 0x3f, 0x6c, 0x5f, 0x0d, 0x36, 0x55, 0x37, 0x90, 0x04, 0xd7, 0x7e, + 0xf2, 0xdb, 0x53, 0xdd, 0x65, 0xad, 0xfb, 0xed, 0xa9, 0xd6, 0x2e, 0x0b, 0x8d, 0x21, 0x11, 0x76, 0xfd, 0x94, 0xfe, + 0xd3, 0x62, 0xbd, 0x46, 0x6b, 0x18, 0xde, 0x7b, 0xde, 0x8d, 0xe3, 0xf7, 0xde, 0x42, 0x31, 0x81, 0x8b, 0xdc, 0xab, + 0x5c, 0x7a, 0x42, 0x5e, 0x8d, 0xe0, 0x3d, 0xdf, 0x1a, 0xc2, 0x7b, 0x1e, 0x38, 0xbd, 0x82, 0xd4, 0x34, 0x11, 0x6c, + 0xe4, 0xe9, 0x27, 0xb2, 0x48, 0x68, 0xf8, 0xb8, 0xd7, 0x9c, 0x70, 0xfd, 0x57, 0x0a, 0xfc, 0x17, 0x1e, 0x2e, 0xb4, + 0x96, 0x02, 0x73, 0x31, 0x5f, 0x68, 0xac, 0xcc, 0xe8, 0x97, 0x63, 0x29, 0x74, 0x73, 0x4c, 0x67, 0x3c, 0xbf, 0x4b, + 0x17, 0xbc, 0x39, 0x93, 0x42, 0xaa, 0x39, 0xcd, 0x18, 0x56, 0x77, 0x4a, 0xb3, 0x59, 0x73, 0xc1, 0xf1, 0x73, 0x96, + 0x7f, 0x61, 0x9a, 0x67, 0x14, 0xbf, 0x95, 0x43, 0xa9, 0x25, 0x7e, 0x7d, 0x7b, 0x37, 0x61, 0x02, 0xff, 0x3e, 0x5c, + 0x08, 0xbd, 0xc0, 0x8a, 0x0a, 0xd5, 0x54, 0xac, 0xe0, 0xe3, 0x6e, 0xb3, 0x39, 0x2f, 0xf8, 0x8c, 0x16, 0x77, 0xcd, + 0x4c, 0xe6, 0xb2, 0x48, 0xff, 0xab, 0x75, 0x4c, 0x1f, 0x8c, 0x4f, 0xba, 0xba, 0xa0, 0x42, 0x71, 0x58, 0x98, 0x94, + 0xe6, 0xf9, 0xde, 0xf1, 0x69, 0x6b, 0xa6, 0xf6, 0xed, 0x85, 0x1f, 0x15, 0x7a, 0xfd, 0x17, 0xfe, 0x20, 0x61, 0x94, + 0xc9, 0x50, 0x0b, 0x37, 0xc8, 0x65, 0xb6, 0x28, 0x94, 0x2c, 0xd2, 0xb9, 0xe4, 0x42, 0xb3, 0xa2, 0x3b, 0x94, 0xc5, + 0x88, 0x15, 0xcd, 0x82, 0x8e, 0xf8, 0x42, 0xa5, 0x27, 0xf3, 0xdb, 0x6e, 0xbd, 0x07, 0x9b, 0x9f, 0x0a, 0x29, 0x58, + 0x17, 0xf8, 0x8d, 0x49, 0x21, 0x17, 0x62, 0xe4, 0x86, 0xb1, 0x10, 0x8a, 0xe9, 0xee, 0x9c, 0x8e, 0xc0, 0x0e, 0x38, + 0x3d, 0x9f, 0xdf, 0x76, 0xcd, 0xac, 0x6f, 0x18, 0x9f, 0x4c, 0x75, 0x7a, 0xda, 0x6a, 0xd9, 0x6f, 0xc5, 0xbf, 0xb2, + 0xb4, 0xdd, 0x49, 0x3a, 0xa7, 0xf3, 0x5b, 0xe0, 0xe0, 0x35, 0x2b, 0x9a, 0x00, 0x0b, 0xa8, 0xd4, 0x4e, 0x5a, 0x0f, + 0x8e, 0xef, 0x43, 0x06, 0xd8, 0x38, 0x34, 0xcd, 0x84, 0xc0, 0xd8, 0x3d, 0x5d, 0xcc, 0xe7, 0xac, 0x00, 0x2f, 0xfa, + 0xee, 0x8c, 0x16, 0x13, 0x2e, 0x9a, 0x85, 0x69, 0xb4, 0x79, 0x3e, 0xbf, 0x5d, 0xc3, 0x7c, 0x52, 0x6b, 0xb6, 0xea, + 0xa6, 0xe5, 0xbe, 0x96, 0xc1, 0x10, 0x4d, 0x4c, 0x9a, 0xb4, 0x98, 0x0c, 0x69, 0xdc, 0xee, 0xdc, 0xc7, 0xfe, 0x7f, + 0x49, 0x07, 0x05, 0x60, 0x6b, 0x8e, 0x16, 0x85, 0xb9, 0x45, 0x4d, 0xdb, 0xca, 0x36, 0x3b, 0x95, 0x5f, 0x58, 0xe1, + 0x5b, 0x35, 0x1f, 0xcb, 0xad, 0x79, 0xff, 0x27, 0x8d, 0xfe, 0x85, 0x27, 0x14, 0xd6, 0xc0, 0x20, 0x47, 0xdf, 0xc8, + 0x83, 0x30, 0xd3, 0xc1, 0xf2, 0x86, 0x8f, 0xf4, 0x34, 0x6d, 0xb7, 0x5a, 0x3f, 0x54, 0x2b, 0xd6, 0x9d, 0x5a, 0xd0, + 0xb5, 0x0b, 0x36, 0xab, 0xad, 0xe3, 0x8c, 0x96, 0xd8, 0xb6, 0x9c, 0x4b, 0xb7, 0xe4, 0x05, 0xcb, 0x4d, 0x34, 0x99, + 0xb5, 0x43, 0xb9, 0xad, 0x71, 0x72, 0x31, 0x65, 0x05, 0xd7, 0xdd, 0xfa, 0x57, 0xd5, 0xf1, 0xf6, 0xea, 0xaf, 0xad, + 0x1c, 0xba, 0xb4, 0x35, 0xdc, 0xa5, 0xe7, 0x63, 0xf8, 0xd8, 0x5e, 0xfd, 0x2f, 0xb4, 0x88, 0x37, 0x10, 0x13, 0x87, + 0x35, 0xd0, 0x3a, 0x98, 0x73, 0x01, 0x26, 0x99, 0x03, 0xfc, 0x0d, 0x28, 0x64, 0x34, 0xcf, 0x62, 0x18, 0xd1, 0x5e, + 0x73, 0xef, 0xb8, 0x60, 0x33, 0xe4, 0x01, 0x91, 0xdc, 0x3f, 0x2d, 0xd8, 0x6c, 0x9d, 0x98, 0xea, 0x4b, 0x83, 0x22, + 0x34, 0xe7, 0x13, 0x91, 0x66, 0x0c, 0xd0, 0x77, 0x9d, 0x30, 0xa1, 0xb9, 0xbe, 0x6b, 0x16, 0xf2, 0x66, 0x39, 0xe2, + 0x6a, 0x9e, 0xd3, 0xbb, 0x74, 0x9c, 0xb3, 0xdb, 0xae, 0x29, 0xd5, 0xe4, 0x9a, 0xcd, 0x94, 0x2b, 0xdb, 0x85, 0xf4, + 0xe6, 0xc8, 0x9a, 0x4d, 0x00, 0xf4, 0xe4, 0xcd, 0xe6, 0xfe, 0x49, 0x8e, 0xd5, 0x1e, 0xa3, 0x8a, 0x35, 0xe5, 0x42, + 0xef, 0xb5, 0x54, 0x77, 0xc6, 0x45, 0xd3, 0x0d, 0xe4, 0xa4, 0x35, 0xbf, 0xed, 0x6e, 0x43, 0x3e, 0xe8, 0x3f, 0x61, + 0xb7, 0x73, 0x2a, 0x46, 0x6c, 0xb4, 0x0c, 0xaa, 0x75, 0xa0, 0x5e, 0x58, 0x2a, 0x15, 0x7a, 0xda, 0x34, 0xb6, 0x5e, + 0x71, 0x47, 0xa0, 0x6f, 0xa0, 0xd6, 0x83, 0x16, 0xb6, 0xff, 0x9f, 0xb4, 0x51, 0x58, 0x79, 0x0f, 0xc2, 0x2e, 0xf1, + 0xf1, 0x5d, 0x13, 0xfe, 0x2e, 0xc1, 0xb7, 0x88, 0x67, 0x34, 0x77, 0x10, 0x99, 0xf1, 0xd1, 0x28, 0xaf, 0x8d, 0xe8, + 0x32, 0xe8, 0xac, 0x8d, 0x96, 0x30, 0xff, 0xb4, 0xb5, 0xd7, 0xda, 0x33, 0x73, 0x71, 0xdb, 0xfc, 0xe4, 0xe4, 0xfe, + 0xf1, 0x03, 0xd6, 0xcd, 0xb9, 0x60, 0xb5, 0xa9, 0x7e, 0x17, 0xd4, 0x61, 0xc3, 0x1d, 0xd7, 0x70, 0x7b, 0xaf, 0xbd, + 0x77, 0xd2, 0xfa, 0xc1, 0xef, 0xd6, 0x9c, 0x8d, 0x75, 0xda, 0x3e, 0x9b, 0xdf, 0xd6, 0xb7, 0xef, 0xb9, 0x6f, 0xfa, + 0xa6, 0xa0, 0xf3, 0x54, 0x48, 0xf8, 0xd3, 0x85, 0x4d, 0x36, 0xce, 0xe5, 0x4d, 0x3a, 0xe5, 0xa3, 0x11, 0x13, 0xb6, + 0x40, 0x99, 0xc8, 0xf2, 0x9c, 0xcf, 0x15, 0xb7, 0xab, 0xe1, 0x70, 0xf7, 0x74, 0x03, 0xaa, 0xe1, 0x80, 0x8e, 0x83, + 0x01, 0x9d, 0x56, 0x03, 0xaa, 0xfa, 0x0f, 0x47, 0xd8, 0xd9, 0x98, 0xab, 0x29, 0xd5, 0xad, 0x61, 0xd2, 0xdf, 0x0b, + 0xa5, 0x01, 0xe6, 0xde, 0x48, 0xc3, 0x50, 0xf1, 0xe6, 0x90, 0xe9, 0x1b, 0xc6, 0xc4, 0xb7, 0x07, 0x71, 0x99, 0x4a, + 0x91, 0xdf, 0xd9, 0xcf, 0x65, 0xd8, 0x25, 0x5d, 0x68, 0xb9, 0x4e, 0x86, 0x5c, 0xd0, 0xe2, 0xee, 0x5a, 0x31, 0xa1, + 0x64, 0x71, 0x2d, 0xc7, 0xe3, 0xe5, 0xb7, 0x48, 0xcb, 0x7d, 0xb4, 0x4e, 0x14, 0x17, 0x93, 0x9c, 0x59, 0xa2, 0x64, + 0x10, 0xc1, 0x11, 0x73, 0xdb, 0xae, 0x69, 0xb2, 0x36, 0xe8, 0x70, 0xe7, 0x99, 0x76, 0x07, 0x69, 0xda, 0xbc, 0x61, + 0xc3, 0xcf, 0x5c, 0x5b, 0x3c, 0x6b, 0xaa, 0x1b, 0xf0, 0x78, 0x31, 0xcb, 0x30, 0x67, 0xc5, 0xd2, 0xd3, 0xf0, 0x56, + 0x8d, 0xea, 0x5c, 0x09, 0x73, 0x7a, 0x68, 0x3a, 0x6c, 0x42, 0xfc, 0x2f, 0x56, 0x94, 0x7b, 0x8c, 0x0b, 0x83, 0x31, + 0x06, 0x40, 0x9b, 0xbb, 0x24, 0x3c, 0x03, 0x4e, 0x5a, 0x2d, 0x7f, 0x3e, 0x34, 0x6d, 0x9d, 0xb4, 0x9d, 0x9c, 0xb2, + 0xd9, 0xae, 0xfd, 0x59, 0x27, 0x46, 0xed, 0xce, 0xfc, 0x76, 0xcf, 0xfc, 0xd3, 0xda, 0x6b, 0x6d, 0x13, 0x9f, 0x6d, + 0x38, 0x1d, 0x23, 0xbf, 0xb2, 0x5a, 0xce, 0xd3, 0x36, 0x9b, 0x75, 0x17, 0x0a, 0x0e, 0x1a, 0x43, 0x1b, 0xcd, 0x01, + 0xb6, 0x36, 0x33, 0x81, 0x75, 0xa4, 0x5c, 0x00, 0x5d, 0xb7, 0x67, 0x1b, 0xf4, 0xa1, 0x24, 0x18, 0x62, 0xef, 0x6c, + 0xb4, 0x3e, 0xac, 0xd6, 0x5e, 0x35, 0x30, 0xf8, 0x67, 0xfd, 0x57, 0xc5, 0x19, 0xbe, 0x60, 0x01, 0x67, 0xce, 0x1b, + 0xc9, 0xe9, 0xaa, 0xe5, 0xb8, 0xf1, 0x91, 0xae, 0x84, 0x04, 0xe3, 0xcb, 0x30, 0xa3, 0xb7, 0xd6, 0xa9, 0x61, 0xc6, + 0x05, 0x98, 0x4c, 0x21, 0xac, 0x03, 0xe3, 0xf2, 0x69, 0xd8, 0xd0, 0x48, 0xc7, 0xd0, 0xf0, 0x61, 0x27, 0x39, 0x3d, + 0x45, 0xb8, 0x85, 0x3b, 0xa7, 0xa7, 0x81, 0x34, 0x30, 0xd6, 0xbb, 0x8a, 0xee, 0x2a, 0xa9, 0x76, 0x94, 0x3c, 0x32, + 0x8d, 0x1e, 0xb5, 0x5b, 0x2d, 0x6c, 0x1c, 0xb7, 0xcb, 0xc2, 0x5c, 0xed, 0x68, 0xb6, 0xdd, 0x6a, 0x41, 0xb3, 0xf0, + 0xc7, 0xcd, 0xeb, 0x17, 0xb2, 0x6c, 0xa5, 0x2d, 0xdc, 0x4e, 0xdb, 0xb8, 0x93, 0x76, 0xf0, 0x71, 0x7a, 0x8c, 0x4f, + 0xd2, 0x13, 0x7c, 0x9a, 0x9e, 0xe2, 0xb3, 0xf4, 0x0c, 0xdf, 0x4f, 0xef, 0xe3, 0xf3, 0xf4, 0x1c, 0x3f, 0x48, 0x1f, + 0xe0, 0x87, 0x69, 0xbb, 0x85, 0x1f, 0xa5, 0xed, 0x36, 0x7e, 0x9c, 0xb6, 0x3b, 0xf8, 0x49, 0xda, 0x3e, 0xc6, 0x4f, + 0xd3, 0xf6, 0x09, 0x7e, 0x96, 0xb6, 0x4f, 0x31, 0x85, 0xdc, 0x21, 0xe4, 0x66, 0x90, 0x3b, 0x82, 0x5c, 0x06, 0xb9, + 0xe3, 0xb4, 0x7d, 0xba, 0xc6, 0xca, 0x06, 0x7b, 0x88, 0x5a, 0xed, 0xce, 0xf1, 0xc9, 0xe9, 0xd9, 0xfd, 0xf3, 0x07, + 0x0f, 0x1f, 0x3d, 0x7e, 0xf2, 0xf4, 0x59, 0x34, 0xc0, 0x43, 0xe3, 0x73, 0xa1, 0x44, 0x9f, 0x1f, 0xb4, 0x4f, 0x07, + 0xf8, 0xda, 0x7f, 0xc6, 0xfc, 0xa0, 0x73, 0xd2, 0x42, 0x97, 0x97, 0x27, 0x83, 0x46, 0x99, 0xfb, 0xde, 0xb8, 0x7a, + 0x54, 0x59, 0x84, 0x90, 0x18, 0x72, 0x10, 0xbe, 0x33, 0xf5, 0xde, 0xb3, 0x98, 0x27, 0x05, 0x3a, 0x38, 0x30, 0x3f, + 0x26, 0xfe, 0xc7, 0xd0, 0xff, 0xa0, 0xc1, 0x22, 0xdd, 0xd2, 0xd8, 0xf9, 0xfa, 0xea, 0xd2, 0xd2, 0xbe, 0x34, 0x62, + 0xd9, 0xe3, 0xce, 0x9c, 0xfc, 0xbf, 0x22, 0x6b, 0x2e, 0x42, 0x4e, 0xac, 0x4a, 0xe6, 0xb4, 0xc7, 0xc8, 0xb2, 0x48, + 0x3b, 0xa7, 0xa7, 0x07, 0xbf, 0xf4, 0x79, 0xbf, 0x3d, 0x18, 0x1c, 0xb6, 0xef, 0xe3, 0x49, 0x99, 0xd0, 0xb1, 0x09, + 0xc3, 0x32, 0xe1, 0xd8, 0x26, 0xd0, 0xd4, 0xd6, 0x86, 0xa4, 0x13, 0x93, 0x04, 0x25, 0xd6, 0xa9, 0x69, 0xfb, 0xbe, + 0x6d, 0xfb, 0x01, 0xd8, 0x31, 0x99, 0xe6, 0x5d, 0xd3, 0x17, 0x17, 0x27, 0x2b, 0xd7, 0x28, 0x9e, 0xa4, 0xae, 0x35, + 0x9f, 0x78, 0x32, 0x18, 0xe0, 0xa1, 0x49, 0x3c, 0xad, 0x12, 0xcf, 0x06, 0x03, 0xd7, 0xd5, 0x03, 0xd3, 0xd5, 0xfd, + 0x2a, 0xeb, 0x7c, 0x30, 0x30, 0x5d, 0x22, 0xe7, 0xb5, 0xae, 0xf4, 0xde, 0x97, 0x52, 0x73, 0xc0, 0x2f, 0x3a, 0xa7, + 0xa7, 0x3d, 0xc0, 0x30, 0x63, 0x8d, 0xea, 0x61, 0x74, 0x13, 0xc0, 0xe8, 0x0e, 0x7e, 0xf7, 0x86, 0x34, 0xbd, 0xa6, + 0x25, 0x90, 0x7a, 0xd1, 0x7f, 0x45, 0x0d, 0x6d, 0x60, 0x6e, 0xfe, 0x4c, 0xec, 0x9f, 0x21, 0x6a, 0x7c, 0xa1, 0x00, + 0x6e, 0xd0, 0x85, 0x78, 0x65, 0xa6, 0xe9, 0xf1, 0x33, 0x05, 0xe7, 0x92, 0xa9, 0xca, 0x69, 0x6f, 0x35, 0xbd, 0x19, + 0xae, 0xa6, 0xea, 0x0b, 0xfa, 0x33, 0xfe, 0x53, 0x1d, 0xc6, 0xfd, 0x66, 0x23, 0x61, 0x7f, 0x8e, 0xc0, 0x8b, 0xa5, + 0x97, 0x8e, 0xd8, 0x04, 0xf5, 0xfa, 0x7f, 0x2a, 0x3c, 0x68, 0x04, 0x19, 0x3f, 0x6c, 0xa7, 0x80, 0x8f, 0xcb, 0x66, + 0x62, 0xfc, 0x03, 0xea, 0xa1, 0xde, 0x9f, 0xea, 0xf0, 0x4f, 0x74, 0xef, 0xa8, 0x9a, 0xcb, 0xef, 0xd2, 0x6d, 0xe1, + 0x2a, 0xf0, 0xcd, 0x61, 0xb9, 0x85, 0x19, 0x6e, 0x37, 0x19, 0x84, 0x09, 0x03, 0x27, 0x68, 0x12, 0xcb, 0x06, 0x3f, + 0x3a, 0x6e, 0xa1, 0x1f, 0xda, 0x1d, 0x10, 0xeb, 0x9b, 0xe2, 0x70, 0x7b, 0xd3, 0x17, 0xcd, 0x63, 0xfc, 0xa0, 0x59, + 0xe0, 0x36, 0xc2, 0xcd, 0xb6, 0xd7, 0xb7, 0xf6, 0x55, 0xdc, 0x42, 0x58, 0xc5, 0xe7, 0xf0, 0xcf, 0x09, 0x1a, 0x54, + 0x1b, 0xf2, 0x8a, 0x6e, 0xf6, 0x0e, 0x1e, 0x9b, 0x24, 0x56, 0x0d, 0x7e, 0x74, 0xd6, 0x42, 0x3f, 0x9c, 0x99, 0x8e, + 0xd8, 0xa1, 0xde, 0xd1, 0x95, 0xc4, 0x27, 0x4d, 0x09, 0x1d, 0xb5, 0xca, 0x7e, 0x44, 0x7c, 0x8a, 0xb0, 0x88, 0x8f, + 0xe1, 0x9f, 0x76, 0xd8, 0xcf, 0xaf, 0x5b, 0xfd, 0x98, 0x79, 0xb7, 0x71, 0x72, 0x6a, 0x1d, 0x40, 0x95, 0xbd, 0x8d, + 0x6d, 0xb0, 0xcb, 0xb6, 0xb9, 0x46, 0x6a, 0x1f, 0xc1, 0x07, 0xc2, 0xfa, 0x90, 0x28, 0xcc, 0x0e, 0xc1, 0x73, 0x14, + 0x0c, 0x26, 0xd4, 0xc5, 0x71, 0x57, 0x35, 0x1a, 0x48, 0xf4, 0xd5, 0xe0, 0x90, 0xb4, 0x9b, 0xba, 0xc9, 0x30, 0xfc, + 0x6e, 0x90, 0x32, 0x1c, 0x99, 0xa8, 0x7a, 0x7d, 0xec, 0x7a, 0xb5, 0x77, 0xce, 0x1e, 0x3b, 0x08, 0x21, 0xaa, 0x17, + 0xeb, 0x26, 0x43, 0x47, 0xa2, 0x11, 0xeb, 0x0b, 0xd6, 0x3b, 0x4b, 0x5b, 0xc8, 0x60, 0xa7, 0xea, 0xc5, 0xac, 0xc9, + 0x21, 0xbd, 0x93, 0xc6, 0xbc, 0xa9, 0xe1, 0xd7, 0x49, 0x30, 0x0b, 0x01, 0x78, 0x57, 0xf9, 0xc1, 0x14, 0x47, 0x9d, + 0xd3, 0x53, 0x2c, 0x08, 0x4f, 0x26, 0xe6, 0x97, 0x22, 0x3c, 0x19, 0x9a, 0x5f, 0x92, 0x94, 0xf0, 0xb2, 0xbd, 0xe3, + 0x82, 0x04, 0xab, 0x6a, 0x52, 0x28, 0x2c, 0x68, 0x81, 0x8e, 0x3a, 0xfe, 0x42, 0x1a, 0x4f, 0xfd, 0x1c, 0x40, 0x00, + 0x2f, 0x8c, 0x2d, 0xa2, 0x6c, 0x16, 0x38, 0x27, 0xf4, 0x32, 0x39, 0xed, 0x4d, 0x8f, 0xe2, 0x4e, 0x53, 0x36, 0x0b, + 0x94, 0x4e, 0x8f, 0x4c, 0x4d, 0x9c, 0x91, 0xc7, 0xd4, 0xb6, 0x86, 0xa7, 0x70, 0x8b, 0x98, 0x91, 0xec, 0xf0, 0xac, + 0xd5, 0x48, 0x4e, 0x11, 0xee, 0x67, 0xab, 0x16, 0xce, 0x57, 0xab, 0x16, 0xa6, 0xc1, 0x32, 0x3c, 0x16, 0x1e, 0x20, + 0xa5, 0x8e, 0x68, 0x33, 0x2a, 0x4c, 0x8f, 0xc7, 0x1a, 0x6e, 0xc4, 0x35, 0xf8, 0x99, 0x68, 0xf0, 0x80, 0x49, 0xb9, + 0xbb, 0x8a, 0x42, 0x26, 0x2e, 0xde, 0x38, 0xd4, 0x1a, 0xbd, 0x16, 0x7e, 0x5d, 0xbd, 0x4d, 0xa3, 0x88, 0x7f, 0x97, + 0xd8, 0xa6, 0x05, 0xc5, 0xe8, 0x76, 0xb1, 0x5f, 0xe9, 0x56, 0xb1, 0x37, 0x3b, 0x8a, 0x5d, 0x6d, 0x17, 0xfb, 0x28, + 0x03, 0x1d, 0x17, 0xff, 0xe1, 0xf8, 0xac, 0xd5, 0x38, 0x06, 0x64, 0x3d, 0x3e, 0x6b, 0x55, 0x85, 0xee, 0xd1, 0x6a, + 0xad, 0x34, 0xf9, 0x4c, 0xad, 0x95, 0x3f, 0xf7, 0xee, 0xc6, 0x66, 0xe1, 0xac, 0xb3, 0x73, 0xe9, 0xd9, 0xdc, 0x3f, + 0x05, 0x2b, 0x0a, 0x61, 0xa8, 0x9d, 0xee, 0x9f, 0x0d, 0x7a, 0x53, 0x16, 0x37, 0x20, 0x15, 0xa5, 0x63, 0xed, 0x7e, + 0xa1, 0xf2, 0x32, 0xf5, 0xa3, 0x84, 0xa4, 0xce, 0x00, 0x61, 0x49, 0x1a, 0xba, 0x7f, 0x3c, 0x30, 0xe7, 0x5d, 0x01, + 0xbf, 0x4f, 0xcc, 0xef, 0x52, 0x95, 0xe1, 0x5c, 0x01, 0xa6, 0x37, 0xc3, 0xa8, 0x27, 0xc8, 0x6b, 0x1a, 0x1b, 0xeb, + 0x6e, 0x94, 0x96, 0x19, 0xea, 0x0b, 0x64, 0xbc, 0x29, 0x33, 0x04, 0x79, 0x2d, 0xdc, 0x6f, 0xbc, 0x2c, 0x52, 0xb0, + 0xf4, 0xc0, 0x93, 0x14, 0xac, 0x3c, 0xf0, 0x30, 0x15, 0xe0, 0x89, 0x40, 0x53, 0x16, 0xd8, 0x8f, 0x3f, 0x74, 0xba, + 0x23, 0x73, 0xdf, 0x49, 0x0c, 0x96, 0x76, 0x19, 0x9c, 0x14, 0x1f, 0x65, 0x0c, 0x7f, 0x1b, 0x1a, 0x61, 0x06, 0x6d, + 0x32, 0x84, 0x79, 0x52, 0x10, 0x48, 0xc3, 0x3c, 0x99, 0x10, 0x06, 0x4d, 0xf2, 0x64, 0x48, 0x58, 0xbf, 0x13, 0xa0, + 0xc9, 0x53, 0x03, 0x3b, 0x00, 0x0e, 0xaf, 0x5f, 0x21, 0x6b, 0xdb, 0x38, 0xdc, 0x4d, 0x43, 0x13, 0x82, 0x70, 0x15, + 0xc3, 0x2c, 0x60, 0x73, 0x9a, 0x9f, 0x9d, 0x2a, 0xf0, 0x22, 0x4f, 0xa8, 0xa1, 0xde, 0x7f, 0x01, 0x59, 0x8d, 0xef, + 0x2d, 0xd9, 0x1a, 0xef, 0xdd, 0x5b, 0x8a, 0xf5, 0x0f, 0xf0, 0x47, 0xb9, 0x3f, 0xda, 0x9c, 0x7e, 0x6b, 0xf4, 0x57, + 0x0a, 0xc5, 0x76, 0x94, 0x42, 0x7f, 0x79, 0x47, 0x34, 0x45, 0x96, 0xb7, 0x69, 0x34, 0xa2, 0xc5, 0xe7, 0x08, 0x7f, + 0x4a, 0xa3, 0x1c, 0x18, 0xc1, 0x08, 0x7f, 0x4c, 0xa3, 0x82, 0x45, 0xf8, 0x8f, 0x34, 0x1a, 0xe6, 0x8b, 0x08, 0x7f, + 0x48, 0xa3, 0x49, 0x11, 0xe1, 0xf7, 0xa0, 0x26, 0x1c, 0xf1, 0xc5, 0x2c, 0xc2, 0xbf, 0xa7, 0x91, 0x32, 0x76, 0xf8, + 0xf8, 0x61, 0x1a, 0x31, 0x16, 0xe1, 0x77, 0x69, 0x24, 0xf3, 0x08, 0x5f, 0xa5, 0x91, 0x2c, 0x22, 0xfc, 0x28, 0x8d, + 0x0a, 0x1a, 0xe1, 0xc7, 0x69, 0x04, 0x85, 0x26, 0x11, 0x7e, 0x92, 0x46, 0xd0, 0xb2, 0x8a, 0xf0, 0xdb, 0x34, 0xe2, + 0x22, 0xc2, 0xbf, 0xa5, 0x91, 0x5e, 0x14, 0xff, 0x2c, 0x24, 0x57, 0x11, 0x7e, 0x9a, 0x46, 0x53, 0x1e, 0xe1, 0x37, + 0x69, 0x54, 0xc8, 0x08, 0xbf, 0x4e, 0x23, 0x9a, 0x47, 0xf8, 0x55, 0x1a, 0xe5, 0x2c, 0xc2, 0xbf, 0xa6, 0xd1, 0x88, + 0x45, 0xf8, 0x65, 0x1a, 0xdd, 0xb1, 0x3c, 0x97, 0x11, 0x7e, 0x96, 0x46, 0x4c, 0x44, 0xf8, 0x97, 0x34, 0xca, 0xa6, + 0x11, 0xfe, 0x29, 0x8d, 0x68, 0xf1, 0x59, 0x45, 0xf8, 0x79, 0x1a, 0x31, 0x1a, 0xe1, 0x17, 0xb6, 0xa3, 0x49, 0x84, + 0x7f, 0x4e, 0xa3, 0x9b, 0x69, 0xb4, 0xc6, 0x4a, 0x91, 0xe5, 0x6b, 0x9e, 0xb1, 0x3f, 0x58, 0x1a, 0x8d, 0x5b, 0xe3, + 0xf3, 0xf1, 0x38, 0xc2, 0x54, 0x68, 0xfe, 0xcf, 0x82, 0xdd, 0x3c, 0xd5, 0x90, 0x48, 0xd9, 0x70, 0x74, 0x3f, 0xc2, + 0xf4, 0x9f, 0x05, 0x4d, 0xa3, 0xf1, 0xd8, 0x14, 0xf8, 0x67, 0x41, 0x67, 0xb4, 0x78, 0xcb, 0xd2, 0xe8, 0xfe, 0x78, + 0x3c, 0x1e, 0x9d, 0x44, 0x98, 0x7e, 0x5d, 0x7c, 0x34, 0x2d, 0x98, 0x02, 0x43, 0xc6, 0x27, 0x50, 0xf7, 0x74, 0x7c, + 0x3a, 0xca, 0x22, 0x3c, 0xe4, 0xea, 0x9f, 0x05, 0x7c, 0x8f, 0xd9, 0x49, 0x76, 0x12, 0xe1, 0x61, 0x4e, 0xb3, 0xcf, + 0x69, 0xd4, 0x32, 0xbf, 0xc4, 0x2f, 0x6c, 0xf4, 0x7a, 0x26, 0x8d, 0x12, 0x7d, 0xcc, 0x86, 0xd9, 0x28, 0xc2, 0x66, + 0x30, 0x63, 0xf8, 0xfb, 0x85, 0xbf, 0x63, 0x3a, 0x8d, 0xce, 0x69, 0x67, 0xc8, 0x3a, 0x11, 0x1e, 0xbe, 0xb9, 0x11, + 0x69, 0x44, 0x4f, 0x3b, 0xb4, 0x43, 0x23, 0x3c, 0x5c, 0x14, 0xf9, 0xdd, 0x8d, 0x94, 0x23, 0x00, 0xc2, 0xf0, 0xfc, + 0xfc, 0x7e, 0x84, 0x33, 0xfa, 0xab, 0x86, 0xda, 0xa7, 0xe3, 0x07, 0x8c, 0xb6, 0x22, 0xfc, 0x0b, 0x2d, 0xf4, 0xc7, + 0x85, 0x72, 0x03, 0x6d, 0x41, 0x8a, 0xcc, 0xde, 0x81, 0x82, 0x39, 0x1a, 0x75, 0xce, 0x1e, 0xb4, 0x59, 0x84, 0xb3, + 0xab, 0xd7, 0xd0, 0xdb, 0xfd, 0xf1, 0x69, 0x0b, 0x3e, 0x04, 0x48, 0x6a, 0xac, 0x80, 0x46, 0xce, 0x4e, 0x1e, 0x9c, + 0xb2, 0x91, 0x49, 0x54, 0x3c, 0xff, 0x6c, 0x66, 0x7f, 0x0e, 0xf3, 0xc9, 0x0a, 0x3e, 0x53, 0x52, 0xa4, 0xd1, 0x28, + 0x6b, 0x9f, 0x1c, 0x43, 0xc2, 0x1d, 0x15, 0x1e, 0x38, 0xb7, 0x50, 0xf5, 0x7c, 0x18, 0xe1, 0x5b, 0x9b, 0x7a, 0x3e, + 0x34, 0x1f, 0x93, 0x77, 0xbf, 0x8a, 0x37, 0xa3, 0x34, 0x1a, 0x9e, 0x9f, 0x9f, 0xb5, 0x20, 0xe1, 0x03, 0xbd, 0x4b, + 0x23, 0xfa, 0x00, 0xfe, 0x83, 0xec, 0x8f, 0xcf, 0xa0, 0x43, 0x18, 0xe1, 0xed, 0xe4, 0x63, 0x98, 0xf3, 0x79, 0x4a, + 0x3f, 0xf3, 0x34, 0x1a, 0x8e, 0x86, 0xf7, 0xcf, 0xa0, 0xde, 0x8c, 0x4e, 0x9e, 0x69, 0x0a, 0xed, 0xb6, 0x5a, 0xa6, + 0xe5, 0x77, 0xfc, 0x0b, 0x33, 0xd5, 0x4f, 0x4f, 0xcf, 0x86, 0x1d, 0x18, 0xc1, 0x15, 0xa8, 0x18, 0x60, 0x3c, 0xe7, + 0x99, 0x69, 0xf0, 0x2a, 0x7b, 0x3a, 0x4a, 0xa3, 0x07, 0x0f, 0x8e, 0x3b, 0x59, 0x16, 0xe1, 0xdb, 0x8f, 0x23, 0x5b, + 0xdb, 0xe4, 0x29, 0x80, 0x7d, 0x1a, 0xb1, 0x07, 0x0f, 0xce, 0xee, 0x53, 0xf8, 0x7e, 0x6e, 0xda, 0x3a, 0x1f, 0x0f, + 0xb3, 0x73, 0x68, 0xeb, 0x77, 0x98, 0xce, 0xc9, 0xf9, 0xf1, 0xc8, 0xf4, 0xf5, 0xbb, 0x19, 0x75, 0x67, 0x7c, 0x32, + 0x3e, 0x31, 0x99, 0x66, 0xa8, 0xe5, 0xe7, 0x6f, 0x2c, 0x8d, 0x32, 0x36, 0x6a, 0x47, 0xf8, 0xd6, 0x2d, 0xdc, 0x83, + 0x93, 0x56, 0x6b, 0x74, 0x1c, 0xe1, 0xd1, 0xc3, 0xf9, 0xfc, 0xad, 0x81, 0x60, 0xfb, 0xe4, 0x81, 0xfd, 0x56, 0x9f, + 0xef, 0xa0, 0xe9, 0xa1, 0x01, 0xda, 0x88, 0xcf, 0x4c, 0xcb, 0x67, 0x0f, 0xe0, 0x3f, 0xf3, 0x6d, 0x9a, 0x2e, 0xbf, + 0xe5, 0x68, 0x62, 0x17, 0xa5, 0xcd, 0x1e, 0xb4, 0xa0, 0xc6, 0x98, 0x7f, 0x1c, 0x16, 0x1c, 0xd0, 0x68, 0xd8, 0x81, + 0xff, 0x8b, 0xf0, 0x38, 0xbf, 0x7a, 0xed, 0x70, 0x76, 0x3c, 0xa6, 0xe3, 0x56, 0x84, 0xc7, 0xf2, 0xa3, 0xd2, 0x1f, + 0x1e, 0x8a, 0x34, 0xea, 0x74, 0xce, 0x87, 0xa6, 0xcc, 0xe2, 0x17, 0xc5, 0x0d, 0x1e, 0xb7, 0x4c, 0x2b, 0x13, 0xfa, + 0x56, 0x0d, 0xaf, 0x24, 0xac, 0x24, 0xfc, 0x17, 0xe1, 0x09, 0xe8, 0xa5, 0x5c, 0x2b, 0xe7, 0x76, 0x3b, 0x4c, 0xde, + 0x19, 0xd4, 0x1c, 0xdd, 0x07, 0x78, 0xf9, 0x65, 0x1c, 0x51, 0x7a, 0xda, 0x69, 0x45, 0xd8, 0x8c, 0xfa, 0xbc, 0x05, + 0xff, 0x45, 0xd8, 0x42, 0xce, 0xc0, 0x75, 0xf2, 0xf1, 0xd9, 0xcb, 0x9b, 0x34, 0xa2, 0xa3, 0xf1, 0x18, 0x96, 0xc4, + 0x4c, 0xc6, 0x17, 0x9b, 0x4a, 0xc1, 0xee, 0x7e, 0xbd, 0x71, 0xdb, 0xc5, 0x24, 0x68, 0x07, 0x9d, 0xb3, 0x07, 0xc3, + 0x93, 0x08, 0xbf, 0x1d, 0x71, 0x2a, 0x60, 0x95, 0xb2, 0xd1, 0x69, 0x76, 0x9a, 0x99, 0x84, 0x89, 0x4c, 0xa3, 0x13, + 0x58, 0xf2, 0x4e, 0x84, 0xf9, 0x97, 0xab, 0x3b, 0x8b, 0x6e, 0x50, 0xdb, 0x21, 0xc8, 0xb8, 0xc5, 0xce, 0xce, 0xb3, + 0x08, 0xe7, 0xf4, 0xcb, 0xb3, 0x5f, 0x8b, 0x34, 0x62, 0x67, 0xec, 0x6c, 0x4c, 0xfd, 0xf7, 0x1f, 0x6a, 0x6a, 0x6a, + 0xb4, 0xc6, 0xa7, 0x90, 0x74, 0x23, 0xcc, 0x58, 0xef, 0x67, 0x63, 0x83, 0x21, 0xaf, 0x66, 0x52, 0x64, 0x4f, 0xc7, + 0x63, 0x69, 0xb1, 0x98, 0xc2, 0x26, 0xfc, 0x04, 0xd0, 0xa6, 0xa3, 0xd1, 0x39, 0x3b, 0x8b, 0xf0, 0x27, 0xbb, 0x4b, + 0xdc, 0x04, 0x3e, 0x59, 0xcc, 0x66, 0x6e, 0xb7, 0x7f, 0xb2, 0x40, 0x81, 0xf9, 0x8e, 0xe9, 0x98, 0x8e, 0x3a, 0x11, + 0xfe, 0x64, 0xe0, 0x32, 0x3a, 0x86, 0xff, 0xa0, 0x00, 0x74, 0xf6, 0xa0, 0xc5, 0xd8, 0x83, 0x96, 0xf9, 0x0a, 0xf3, + 0xdc, 0xcc, 0x87, 0x67, 0x59, 0x3b, 0xc2, 0x9f, 0x1c, 0x3a, 0x8e, 0xc7, 0xb4, 0x05, 0xe8, 0xf8, 0xc9, 0xa1, 0x63, + 0xa7, 0x35, 0xec, 0x50, 0xf3, 0x6d, 0xb1, 0xe6, 0xfc, 0x7e, 0xc6, 0x60, 0x72, 0x9f, 0x2c, 0x42, 0xde, 0xbf, 0x7f, + 0x7e, 0xfe, 0xe0, 0x01, 0x7c, 0x9a, 0xb6, 0xcb, 0x4f, 0xa5, 0x1f, 0xe6, 0x06, 0xc9, 0x5a, 0xd9, 0x09, 0xd0, 0xc9, + 0x4f, 0x66, 0x8c, 0xe3, 0xf1, 0x98, 0xb5, 0x22, 0x9c, 0xf3, 0x19, 0xb3, 0x98, 0x60, 0x7f, 0x9b, 0x8e, 0x8e, 0x3b, + 0xd9, 0xe8, 0xb8, 0x13, 0xe1, 0xfc, 0xed, 0x33, 0x33, 0x9b, 0x16, 0xcc, 0xde, 0x6f, 0x39, 0x8f, 0x35, 0x33, 0xfa, + 0x06, 0x06, 0x09, 0x2b, 0x0d, 0x95, 0xdf, 0x07, 0xf4, 0xf0, 0xec, 0x2c, 0x1b, 0xc1, 0x40, 0xdf, 0x43, 0xb7, 0x00, + 0xc6, 0xf7, 0x76, 0xf3, 0x0d, 0xe9, 0xe9, 0x29, 0x4c, 0xf7, 0xfd, 0x7c, 0x51, 0xcc, 0x5f, 0xa5, 0xd1, 0x83, 0xe3, + 0xfb, 0xad, 0xd1, 0x30, 0xc2, 0xef, 0xdd, 0x04, 0x8f, 0xb3, 0xe1, 0xf1, 0xfd, 0x76, 0x84, 0xdf, 0x9b, 0xfd, 0x76, + 0x7f, 0x78, 0x76, 0x0e, 0xe7, 0xc6, 0x7b, 0x35, 0x2f, 0xde, 0x4e, 0x4c, 0x81, 0x31, 0x7d, 0x00, 0xcd, 0xfe, 0x66, + 0x76, 0xe3, 0xa8, 0x0d, 0x1b, 0xf9, 0xbd, 0xd9, 0x64, 0x06, 0x4f, 0xee, 0xb7, 0x4f, 0xcf, 0x4f, 0x23, 0x3c, 0xe3, + 0x23, 0x01, 0x04, 0xde, 0x6c, 0x94, 0x07, 0xed, 0x07, 0xf7, 0x5b, 0x11, 0x9e, 0xbd, 0xd5, 0xd9, 0x47, 0x3a, 0x33, + 0xd4, 0x78, 0x0c, 0x30, 0x9b, 0x71, 0xa5, 0xef, 0xde, 0x28, 0x47, 0x8f, 0x59, 0x3b, 0xc2, 0x33, 0x99, 0x65, 0x54, + 0xbd, 0xb5, 0x09, 0xc3, 0xd3, 0x08, 0x0b, 0xfa, 0x85, 0xfe, 0x2d, 0xfd, 0x66, 0x1a, 0x31, 0x3a, 0x32, 0x69, 0x06, + 0x87, 0x23, 0xfc, 0x6e, 0x04, 0xd7, 0x60, 0x69, 0x34, 0x1e, 0x8d, 0x4f, 0x01, 0x3c, 0x40, 0x80, 0x2c, 0x76, 0x03, + 0x34, 0xe0, 0x6b, 0xf4, 0x68, 0x98, 0x46, 0x67, 0xc3, 0x73, 0xd6, 0x39, 0x8e, 0x70, 0x49, 0x8d, 0xe8, 0x29, 0xe4, + 0x9b, 0xcf, 0x8f, 0x66, 0x4b, 0x9d, 0xd8, 0x04, 0x03, 0xa0, 0x11, 0xbd, 0xdf, 0x1a, 0x9d, 0x45, 0x78, 0xfe, 0x9a, + 0xf9, 0x3d, 0xc6, 0x18, 0x3b, 0x07, 0x58, 0x42, 0x92, 0x41, 0xa0, 0xf3, 0xf1, 0xf0, 0xc1, 0xb9, 0xf9, 0x06, 0x30, + 0xd0, 0x31, 0x63, 0x00, 0xa4, 0xf9, 0x6b, 0x56, 0x02, 0x62, 0x34, 0xbc, 0xdf, 0x02, 0xfa, 0x32, 0xa7, 0x73, 0x7a, + 0x47, 0x6f, 0x9e, 0xce, 0xcd, 0x9c, 0xc6, 0xa3, 0xd3, 0x08, 0xcf, 0x9f, 0xff, 0x32, 0x5f, 0x8c, 0xc7, 0x66, 0x42, + 0x74, 0xf8, 0x20, 0xc2, 0x73, 0x56, 0x2c, 0x60, 0x8d, 0xce, 0x4f, 0x8f, 0xc7, 0x11, 0x76, 0x68, 0x98, 0xb5, 0xb2, + 0x21, 0xdc, 0xf3, 0x2d, 0x66, 0x69, 0x34, 0x1a, 0xd1, 0xd6, 0x08, 0x6e, 0xfd, 0xe4, 0xcd, 0xaf, 0x85, 0x45, 0x23, + 0x66, 0xf0, 0xc1, 0xad, 0x21, 0xcc, 0x17, 0xe0, 0xf1, 0x71, 0xc8, 0xb2, 0x8c, 0xba, 0xc4, 0xb3, 0xb3, 0xe3, 0x63, + 0xc0, 0x3d, 0x3b, 0x43, 0x8b, 0x20, 0x6f, 0xd4, 0xdd, 0xb0, 0x90, 0x70, 0x74, 0x01, 0x51, 0x05, 0xb2, 0xfa, 0xe6, + 0xee, 0xb5, 0xa1, 0xab, 0xed, 0xb3, 0x07, 0xb0, 0x00, 0x8a, 0x8e, 0x46, 0xaf, 0xec, 0xe1, 0x76, 0x3e, 0x3c, 0x39, + 0x6d, 0x1f, 0x47, 0xd8, 0x6f, 0x04, 0x7a, 0xde, 0xba, 0xdf, 0x81, 0x12, 0x62, 0x74, 0x67, 0x4b, 0x8c, 0x4f, 0xe8, + 0xc9, 0x59, 0x2b, 0xc2, 0x7e, 0x6b, 0xb0, 0xf3, 0xe1, 0xe9, 0x7d, 0xf8, 0x54, 0x53, 0x96, 0xe7, 0x06, 0xbf, 0x4f, + 0x01, 0x2e, 0x8a, 0x3f, 0x13, 0x34, 0x8d, 0x68, 0xeb, 0xb4, 0xd3, 0x19, 0xc1, 0x67, 0xfe, 0x85, 0x15, 0x69, 0x94, + 0xb5, 0xe0, 0xbf, 0x08, 0x07, 0x3b, 0x89, 0x0d, 0x23, 0x6c, 0xf0, 0xee, 0x8c, 0x9e, 0x9a, 0xbd, 0xef, 0x76, 0x55, + 0xeb, 0xbc, 0x05, 0x1b, 0xd6, 0x6d, 0x2a, 0xf7, 0xa5, 0x84, 0xbc, 0x71, 0x24, 0x96, 0x46, 0x38, 0x40, 0xd0, 0xf1, + 0xfd, 0x71, 0x84, 0xfd, 0x8e, 0x3b, 0x39, 0x3b, 0xef, 0x00, 0x29, 0xd3, 0x40, 0x28, 0x46, 0x9d, 0xe1, 0x09, 0x90, + 0x26, 0xcd, 0x5e, 0x5b, 0x3c, 0x89, 0xb0, 0x7e, 0xaa, 0xf4, 0xab, 0x34, 0x1a, 0x9d, 0x0f, 0xc7, 0xa3, 0xf3, 0x08, + 0x6b, 0x39, 0xa3, 0x5a, 0x1a, 0x0a, 0x78, 0x7c, 0x72, 0x3f, 0xc2, 0x06, 0xcd, 0x5b, 0xac, 0x35, 0x6a, 0x45, 0xd8, + 0x1d, 0x25, 0x8c, 0x9d, 0x77, 0x60, 0x5a, 0x3f, 0x3f, 0xd7, 0x80, 0xcb, 0x23, 0x36, 0x3c, 0x8e, 0x70, 0x49, 0xef, + 0x0d, 0x21, 0x82, 0x2f, 0x35, 0x93, 0x9f, 0x1d, 0xeb, 0x01, 0xa4, 0xce, 0x6f, 0x78, 0x58, 0x86, 0x97, 0x37, 0x16, + 0x8d, 0xa8, 0xd9, 0xe2, 0xc1, 0x3d, 0xe8, 0x13, 0x1a, 0x7b, 0xb6, 0x9d, 0x93, 0xe5, 0x1a, 0x97, 0xe1, 0x45, 0x3f, + 0xb3, 0x3b, 0x15, 0x2b, 0x65, 0x38, 0xd9, 0x20, 0x05, 0x5c, 0x00, 0x9c, 0x41, 0xbd, 0xf3, 0x99, 0x04, 0x41, 0x52, + 0x90, 0x56, 0x57, 0x5c, 0x78, 0x3f, 0xce, 0xae, 0x80, 0xa0, 0x03, 0x90, 0x5e, 0x10, 0x4a, 0x34, 0xc4, 0x66, 0xb1, + 0xc2, 0xa4, 0x37, 0x6f, 0x37, 0x32, 0xa5, 0xb4, 0x06, 0xf3, 0x94, 0x50, 0x1f, 0x95, 0x1d, 0x2e, 0x69, 0x21, 0x6e, + 0x11, 0xea, 0x4a, 0x62, 0x62, 0x2c, 0xbf, 0x10, 0x3a, 0x56, 0xaa, 0x5f, 0x0c, 0x70, 0xfb, 0x0c, 0x61, 0x88, 0x5e, + 0x40, 0xfa, 0xf2, 0xf2, 0xb2, 0x7d, 0x76, 0x60, 0x84, 0xbe, 0xcb, 0xcb, 0x73, 0xfb, 0x03, 0xfe, 0x1d, 0x54, 0x11, + 0xa3, 0x61, 0x7c, 0x8f, 0x58, 0xa0, 0xd1, 0x33, 0xfc, 0xf5, 0x23, 0xb6, 0x5a, 0xc5, 0x8f, 0x18, 0x81, 0x19, 0xe3, + 0x47, 0x2c, 0x31, 0xb7, 0x06, 0xd6, 0x37, 0x85, 0xf4, 0x41, 0x73, 0xd6, 0xc2, 0x10, 0xc7, 0xdc, 0x73, 0xde, 0x8f, + 0x58, 0x9f, 0xd7, 0xfd, 0x9a, 0xab, 0xe0, 0xc1, 0x07, 0x07, 0xcb, 0x22, 0xd5, 0x56, 0x4c, 0xd0, 0x56, 0x4c, 0xd0, + 0x56, 0x4c, 0xd0, 0x55, 0xf8, 0xf6, 0x93, 0x1e, 0x48, 0x29, 0x46, 0xd9, 0xe2, 0x78, 0xea, 0x77, 0xa0, 0xf6, 0x00, + 0xed, 0x64, 0xaf, 0x52, 0x76, 0x94, 0xba, 0x8a, 0x9d, 0x0a, 0x8c, 0x9d, 0x89, 0x4e, 0xdb, 0x71, 0xf4, 0xef, 0xa8, + 0x3b, 0x5e, 0xd6, 0xc4, 0xb2, 0x77, 0x3b, 0xc5, 0x32, 0x58, 0x49, 0x23, 0x9a, 0xed, 0xdb, 0x48, 0x18, 0xba, 0x7f, + 0xdf, 0x08, 0x66, 0x55, 0x78, 0xb6, 0x06, 0x24, 0x75, 0x41, 0x0a, 0x39, 0x37, 0x52, 0x5a, 0x81, 0xd2, 0x91, 0x8e, + 0x0b, 0xd0, 0x50, 0x7a, 0x05, 0x65, 0x19, 0x45, 0xb4, 0x61, 0x00, 0xa2, 0xac, 0x8c, 0x66, 0x65, 0xb5, 0x53, 0x10, + 0x5d, 0x40, 0x13, 0x66, 0x24, 0x16, 0x68, 0x40, 0x98, 0x06, 0x84, 0xab, 0x0c, 0xe2, 0x8c, 0xcb, 0x3e, 0x31, 0xd9, + 0xca, 0x64, 0xab, 0x32, 0x5b, 0xfa, 0x6c, 0x2b, 0x24, 0x4a, 0x93, 0x2d, 0xcb, 0x6c, 0x90, 0xd9, 0xf0, 0x24, 0x55, + 0x78, 0x98, 0x4a, 0x2b, 0xaa, 0x55, 0xb2, 0xd5, 0x5b, 0x1a, 0x6a, 0x73, 0x0f, 0x0e, 0xe2, 0x52, 0x4e, 0x32, 0x6a, + 0xe2, 0x7b, 0x4b, 0x9e, 0x14, 0x46, 0x06, 0xe2, 0xc9, 0xc4, 0xfd, 0x1d, 0xae, 0x37, 0x65, 0xa5, 0x62, 0x32, 0xfc, + 0x46, 0x49, 0xf4, 0x97, 0x57, 0xa2, 0x3e, 0xe2, 0x26, 0xfe, 0xcc, 0x05, 0x49, 0x5a, 0xad, 0xe3, 0xf6, 0x71, 0xeb, + 0xbc, 0xc7, 0x0f, 0xdb, 0x9d, 0xe4, 0x41, 0x27, 0x35, 0x8a, 0x88, 0xb9, 0xbc, 0x01, 0x05, 0xcc, 0x51, 0x27, 0x39, + 0x41, 0x87, 0xed, 0xa4, 0x75, 0x7a, 0xda, 0x84, 0x7f, 0xf0, 0x7b, 0x5d, 0x56, 0x3b, 0x69, 0x9d, 0x9c, 0xf6, 0xf8, + 0xd1, 0x46, 0xa5, 0x98, 0x37, 0xa0, 0x20, 0x3a, 0x32, 0x95, 0x30, 0xd4, 0xaf, 0x96, 0xf7, 0xd9, 0x96, 0x9e, 0xe7, + 0xbd, 0x8e, 0x95, 0x55, 0xc5, 0x01, 0x54, 0xfd, 0xd7, 0xc4, 0x00, 0xd1, 0x7f, 0x0d, 0xcb, 0x18, 0xb1, 0xcb, 0x02, + 0x44, 0xed, 0x47, 0x3c, 0x16, 0x0d, 0x76, 0x18, 0xdb, 0x7c, 0x0d, 0x75, 0x9b, 0x10, 0xb7, 0x0d, 0x4f, 0x5c, 0xae, + 0x0a, 0x73, 0x27, 0x08, 0x35, 0x15, 0xe4, 0x0e, 0x5d, 0xae, 0x0c, 0x73, 0x87, 0x08, 0x35, 0x25, 0xe4, 0xd2, 0x94, + 0x27, 0x14, 0x72, 0x74, 0x42, 0x9b, 0x06, 0x92, 0xd5, 0xa2, 0x3c, 0x67, 0x7e, 0xd8, 0x7c, 0x0c, 0xcb, 0x63, 0x08, + 0x8a, 0x13, 0xa4, 0x05, 0xbc, 0xed, 0x51, 0x6a, 0x73, 0x5a, 0xb8, 0x54, 0xe3, 0x40, 0x46, 0x03, 0xfe, 0x39, 0x64, + 0xe6, 0xc1, 0x87, 0x56, 0xef, 0xf8, 0xac, 0x95, 0xb6, 0xc1, 0x49, 0x19, 0x64, 0x6d, 0x61, 0x65, 0x6d, 0xe1, 0x65, + 0x6d, 0xe1, 0x65, 0x6d, 0x10, 0xe0, 0x83, 0xbe, 0xff, 0x91, 0x35, 0xc3, 0x0f, 0x5e, 0x5a, 0x91, 0x58, 0x33, 0x81, + 0x58, 0xaf, 0x56, 0xcb, 0x35, 0xd8, 0xf8, 0x94, 0x35, 0xa4, 0xaa, 0xd4, 0x9f, 0xcb, 0x22, 0x6d, 0xe1, 0x49, 0x0a, + 0x5a, 0xee, 0x16, 0xa6, 0x66, 0x73, 0x7b, 0xaa, 0xb0, 0x19, 0x3f, 0xa6, 0xe7, 0xd5, 0xc9, 0x97, 0xe4, 0xd8, 0x68, + 0x8f, 0x97, 0x45, 0xca, 0x2d, 0xcd, 0xe0, 0x96, 0x66, 0x70, 0x4b, 0x33, 0xa0, 0x11, 0x5c, 0x16, 0x36, 0x65, 0x13, + 0x4a, 0xe0, 0x4a, 0xa0, 0x7f, 0x3c, 0x80, 0xf0, 0x79, 0xb1, 0x26, 0x66, 0xd4, 0x1b, 0x9d, 0xb7, 0x21, 0x5c, 0x98, + 0x2d, 0xa9, 0x13, 0x6a, 0xbc, 0xa6, 0xcb, 0x31, 0x7f, 0xad, 0xa1, 0x7d, 0x02, 0x6f, 0xb9, 0x3c, 0xd4, 0x71, 0x0b, + 0x8c, 0x26, 0xa2, 0x22, 0xea, 0x19, 0xb2, 0x90, 0x1a, 0x9d, 0x8d, 0x33, 0x86, 0xfe, 0xbc, 0xe1, 0x83, 0x6a, 0x29, + 0x41, 0xf8, 0x82, 0xc1, 0x67, 0x56, 0x39, 0xc5, 0x97, 0xb6, 0x9e, 0xce, 0x50, 0xcb, 0x1e, 0x09, 0x5d, 0x30, 0xd8, + 0xf6, 0xd1, 0x96, 0x7a, 0x82, 0x48, 0x65, 0xdc, 0x05, 0x49, 0x15, 0x2f, 0x18, 0xdc, 0x67, 0xc9, 0x2d, 0x35, 0xce, + 0x24, 0x2f, 0xec, 0x9f, 0xaf, 0x34, 0xf0, 0xb6, 0x2b, 0x26, 0x43, 0xef, 0xa4, 0x7a, 0x6d, 0xa2, 0xea, 0x90, 0xfd, + 0x7d, 0x6b, 0x4b, 0x6d, 0xbe, 0x36, 0x8d, 0xa9, 0x4d, 0xa2, 0xc9, 0x86, 0x1d, 0xea, 0xd7, 0xe8, 0x1f, 0xef, 0x2b, + 0x56, 0x4c, 0x86, 0x28, 0xa0, 0xd9, 0x06, 0xac, 0xaa, 0x02, 0x96, 0x72, 0xf5, 0x4a, 0x17, 0x42, 0xe8, 0xdd, 0x8c, + 0x79, 0x5d, 0x4c, 0x86, 0x3b, 0x1f, 0xfd, 0xb0, 0x3d, 0xf6, 0xde, 0xd2, 0xa0, 0x07, 0xaf, 0xda, 0x9e, 0xb2, 0xdb, + 0xef, 0xd5, 0xb9, 0xd9, 0x59, 0x47, 0xe5, 0xdf, 0xab, 0xf3, 0x74, 0x57, 0x9d, 0x19, 0xbf, 0x8d, 0xfd, 0xde, 0xd1, + 0x81, 0x1a, 0xdb, 0x18, 0xe8, 0x4c, 0x86, 0x10, 0xa5, 0x1d, 0xfe, 0xda, 0x58, 0x2a, 0x5d, 0x4f, 0xc2, 0x61, 0x15, + 0x64, 0x2f, 0x39, 0x4d, 0x19, 0xa6, 0xa4, 0x73, 0x58, 0x98, 0x68, 0x2a, 0x22, 0xa1, 0x4d, 0x95, 0x50, 0x9c, 0x93, + 0x38, 0xa6, 0x87, 0x19, 0xc4, 0x84, 0x69, 0xf7, 0x68, 0x1a, 0xd3, 0x46, 0x86, 0x8e, 0xe2, 0x76, 0x83, 0x1e, 0x66, + 0x08, 0x35, 0xda, 0xa0, 0x33, 0x95, 0xa4, 0xdd, 0xcc, 0x21, 0x4a, 0xa4, 0x21, 0xc5, 0xf9, 0xa1, 0x48, 0x8a, 0x86, + 0x3c, 0x54, 0x49, 0xd1, 0x48, 0x4e, 0xb1, 0x48, 0x26, 0x65, 0xf2, 0xc4, 0x24, 0x4f, 0x6c, 0xf2, 0xb0, 0x4c, 0x1e, + 0x9a, 0xe4, 0xa1, 0x4d, 0xa6, 0xa4, 0x38, 0x14, 0x09, 0x6d, 0xc4, 0xed, 0x66, 0x81, 0x0e, 0x61, 0x04, 0x7e, 0xf4, + 0x44, 0x84, 0xc1, 0xb9, 0xd7, 0xc6, 0xba, 0x65, 0x2e, 0x73, 0x17, 0x2e, 0xb3, 0x02, 0x52, 0xe9, 0x72, 0x04, 0x75, + 0x9e, 0x05, 0x60, 0xc2, 0xda, 0xfe, 0xf1, 0xc1, 0xe0, 0xd6, 0x59, 0x2e, 0x45, 0xe0, 0x52, 0x05, 0x56, 0xe0, 0x9f, + 0x9d, 0x23, 0x09, 0x40, 0x75, 0x4d, 0xf3, 0xf9, 0x94, 0x6e, 0xf9, 0xad, 0x16, 0x93, 0xa1, 0xdb, 0x59, 0x65, 0x33, + 0x8c, 0x16, 0x36, 0xc8, 0x72, 0xdd, 0xc3, 0x10, 0x40, 0xed, 0xbd, 0x1a, 0x13, 0x6a, 0x94, 0xe4, 0xb6, 0xc6, 0xa4, + 0x60, 0x77, 0x2a, 0xa3, 0x39, 0x8b, 0xab, 0x03, 0xb8, 0x1a, 0x26, 0x23, 0x2f, 0xc0, 0x16, 0xbd, 0x38, 0x4c, 0x8e, + 0x1b, 0x3a, 0x99, 0x1c, 0x26, 0xa7, 0x0f, 0x1a, 0x3a, 0x19, 0x1e, 0x26, 0xed, 0x76, 0x85, 0xb3, 0x49, 0x41, 0x74, + 0x32, 0x21, 0x1a, 0x34, 0x86, 0xb6, 0x51, 0x39, 0xa7, 0x60, 0x5c, 0xf5, 0x6f, 0x0c, 0xa3, 0xe1, 0x86, 0x21, 0xd8, + 0xc4, 0xc6, 0x9b, 0xdc, 0x1a, 0x43, 0xd8, 0x4d, 0xe7, 0xf4, 0xb4, 0xa9, 0x93, 0x02, 0x6b, 0xbb, 0x92, 0x4d, 0x9d, + 0x4c, 0xb0, 0xb6, 0xcb, 0xd7, 0xd4, 0xc9, 0xd0, 0x36, 0x65, 0x74, 0x80, 0x4c, 0x04, 0xc0, 0x7a, 0xce, 0x02, 0xc8, + 0x77, 0xbc, 0x7b, 0xc8, 0x1a, 0xb4, 0x86, 0xdf, 0x2b, 0xd7, 0xf4, 0x05, 0x15, 0xd5, 0x60, 0x64, 0xc3, 0xbe, 0x55, + 0xb4, 0x5d, 0x35, 0xc9, 0xfe, 0x75, 0xd9, 0xb2, 0xd9, 0x42, 0xea, 0x7a, 0xc1, 0x87, 0x35, 0x0c, 0x71, 0xa5, 0xdc, + 0xc1, 0xfd, 0x8a, 0x92, 0x18, 0xa2, 0xca, 0x99, 0x53, 0x88, 0x13, 0xaf, 0x47, 0x86, 0x24, 0xde, 0x68, 0xac, 0x51, + 0x1c, 0x9c, 0xb7, 0x4f, 0x43, 0xaa, 0xba, 0x15, 0x6a, 0x8e, 0x90, 0x68, 0x21, 0xac, 0x31, 0xe2, 0x28, 0x0a, 0x58, + 0x10, 0xa7, 0xdd, 0xad, 0x1d, 0x10, 0x07, 0x07, 0x9b, 0xe7, 0x85, 0x0f, 0xfa, 0xbf, 0x15, 0xe8, 0xbf, 0xb2, 0x64, + 0xf3, 0x4f, 0x11, 0x59, 0x1b, 0x57, 0x1e, 0x20, 0x8a, 0x0f, 0xfa, 0x74, 0xdf, 0x50, 0xf8, 0x7e, 0x15, 0xf1, 0xce, + 0xe5, 0x34, 0xcf, 0x4c, 0x86, 0xe9, 0x6b, 0x10, 0x8c, 0xed, 0x4d, 0x38, 0xa1, 0xd2, 0x4a, 0xef, 0x5f, 0x76, 0x1c, + 0x74, 0xe2, 0x9e, 0x4a, 0x09, 0x1b, 0xfd, 0x3b, 0xb4, 0x89, 0xad, 0x60, 0xe3, 0xbc, 0xa1, 0x57, 0xab, 0xda, 0xc3, + 0x38, 0xf6, 0xf9, 0x15, 0x74, 0x70, 0xc0, 0xd5, 0x33, 0x30, 0xe3, 0x65, 0x71, 0x23, 0x3c, 0x7c, 0xff, 0xa9, 0x9d, + 0xd6, 0x7f, 0x9b, 0x73, 0x35, 0x0d, 0x0e, 0xba, 0x87, 0xb5, 0xfc, 0x9d, 0x2b, 0xd1, 0xd3, 0x29, 0x77, 0x6b, 0xfd, + 0x77, 0x65, 0x24, 0xbd, 0xf5, 0x44, 0xd3, 0xc1, 0x01, 0xaf, 0x02, 0x25, 0x45, 0x3f, 0x44, 0xa8, 0x67, 0x64, 0x90, + 0x67, 0xb9, 0xa4, 0x70, 0x23, 0x0a, 0x57, 0x0c, 0x69, 0x83, 0x1f, 0x69, 0xfc, 0x87, 0xfc, 0xff, 0xd4, 0xc8, 0xa1, + 0x4e, 0x1b, 0x3c, 0x10, 0xc0, 0x42, 0x56, 0xa8, 0x0a, 0x51, 0x68, 0x20, 0x1d, 0xda, 0x3c, 0xa3, 0xf2, 0x30, 0xa7, + 0xf3, 0x79, 0x7e, 0x67, 0x5e, 0xa9, 0x0a, 0x38, 0xaa, 0xea, 0xa2, 0xc9, 0xc5, 0x87, 0xc3, 0x05, 0xf0, 0xf4, 0x80, + 0x7b, 0xc8, 0xf8, 0x77, 0x96, 0x97, 0xdb, 0x02, 0x81, 0x64, 0xa6, 0x88, 0x6c, 0xb6, 0xbb, 0xea, 0x12, 0xe4, 0xb2, + 0x66, 0x13, 0x69, 0x17, 0x36, 0x1b, 0x73, 0x90, 0xc9, 0x94, 0xf5, 0xe1, 0xdc, 0xb3, 0x05, 0x41, 0x72, 0x93, 0x46, + 0x64, 0xdb, 0x5d, 0x8a, 0x8f, 0x63, 0x40, 0x23, 0x64, 0x05, 0xbe, 0x50, 0x58, 0xe4, 0xc0, 0x75, 0x16, 0xbe, 0xe3, + 0x6f, 0xb4, 0x54, 0xf4, 0xd5, 0x60, 0x80, 0x0b, 0xf3, 0x30, 0x43, 0x39, 0x9f, 0x42, 0x05, 0x0f, 0xfd, 0x04, 0x22, + 0x0a, 0x5f, 0xad, 0xf6, 0xe1, 0x1d, 0x1d, 0xd7, 0x26, 0x38, 0x7d, 0xba, 0x9f, 0xd5, 0x9b, 0x19, 0x30, 0x0e, 0x46, + 0x5a, 0xe6, 0xa2, 0xd0, 0xc9, 0x9b, 0xec, 0x42, 0x74, 0x1b, 0x0d, 0x66, 0x42, 0x1c, 0x11, 0x88, 0x67, 0x06, 0x1e, + 0x79, 0xf0, 0xc7, 0x46, 0x2d, 0x52, 0xcc, 0xc6, 0x7e, 0x83, 0xa0, 0xd4, 0xb5, 0x84, 0xd5, 0x4a, 0xd9, 0xd8, 0x22, + 0x26, 0xc7, 0x46, 0x19, 0x29, 0xfb, 0x29, 0x83, 0x98, 0x56, 0x66, 0x1c, 0xdc, 0x6d, 0xf5, 0xb7, 0xd5, 0x7e, 0xde, + 0xe3, 0xf6, 0x1a, 0x8f, 0x1b, 0x8f, 0x7d, 0x03, 0xa8, 0xe5, 0xc6, 0x06, 0xb7, 0x16, 0xe6, 0xb1, 0x35, 0x87, 0x65, + 0x9b, 0x10, 0x14, 0xa5, 0x87, 0xba, 0xbd, 0xb9, 0xf5, 0x11, 0xfb, 0x94, 0x99, 0x93, 0x42, 0xba, 0x0f, 0x72, 0xf4, + 0x80, 0x40, 0xe7, 0xf6, 0x67, 0x45, 0x17, 0x2a, 0x99, 0xb8, 0x1c, 0xe3, 0x2f, 0xc1, 0x6d, 0x5e, 0x3f, 0xba, 0xbe, + 0x36, 0x9b, 0xfc, 0xfa, 0x3a, 0xc2, 0xa1, 0x59, 0x77, 0x14, 0xf0, 0x82, 0xd1, 0xa0, 0x0c, 0xea, 0x64, 0x36, 0x7e, + 0xb3, 0x5d, 0x35, 0xf6, 0x9e, 0x56, 0x78, 0x07, 0xcb, 0x63, 0x1a, 0xdf, 0x72, 0x83, 0xec, 0x73, 0x80, 0x37, 0xeb, + 0xf3, 0x41, 0xf7, 0x4d, 0xac, 0xd0, 0xc1, 0xc1, 0x9b, 0x58, 0xa2, 0xde, 0x15, 0x33, 0x77, 0x6e, 0xe0, 0x07, 0xdd, + 0xe7, 0x66, 0xf8, 0x32, 0x40, 0x80, 0x2b, 0xb6, 0x29, 0xd9, 0xbc, 0x35, 0x51, 0x27, 0x52, 0x88, 0x6a, 0x0d, 0xb1, + 0x75, 0x1d, 0x48, 0xa0, 0xd7, 0x37, 0x21, 0xb4, 0xbb, 0x8c, 0x30, 0x60, 0xe1, 0x4b, 0x2f, 0x35, 0x96, 0xcc, 0x58, + 0x31, 0x61, 0xc5, 0x6a, 0xf5, 0x9e, 0x5a, 0xcf, 0xb3, 0x8d, 0x20, 0x89, 0xaa, 0xdb, 0x68, 0x50, 0x33, 0x7e, 0x10, + 0x1f, 0xe8, 0x00, 0xef, 0xbf, 0x89, 0x0b, 0x84, 0xc0, 0xc2, 0x88, 0x8b, 0x85, 0xf7, 0xb2, 0xca, 0x6a, 0xeb, 0x52, + 0xa0, 0xb2, 0x91, 0x9c, 0xb4, 0xf0, 0x94, 0x64, 0xe5, 0x1a, 0x5d, 0x4c, 0xbb, 0x8d, 0x46, 0x8e, 0x64, 0x9c, 0xf5, + 0xf3, 0x01, 0xe6, 0xb8, 0x80, 0xcb, 0xd4, 0xed, 0x75, 0x98, 0xb3, 0x1a, 0xe5, 0x72, 0xf3, 0x5d, 0xda, 0xb1, 0xa6, + 0x8f, 0xe8, 0x3a, 0x00, 0xc6, 0x23, 0x1a, 0x10, 0x89, 0x5d, 0x40, 0x16, 0x16, 0xc8, 0xca, 0x03, 0x59, 0x18, 0x20, + 0x2b, 0xd4, 0x9b, 0x43, 0xb8, 0x20, 0x85, 0xd2, 0x2d, 0x8a, 0x5e, 0x0f, 0x6c, 0xe9, 0x9c, 0x26, 0x30, 0x37, 0xb1, + 0x15, 0xdc, 0x72, 0x80, 0x03, 0x85, 0xf3, 0xc3, 0x53, 0x64, 0x19, 0x45, 0x26, 0xc6, 0x2b, 0xbe, 0x35, 0x7f, 0x92, + 0x5b, 0x7c, 0x67, 0x7f, 0xdc, 0x05, 0xca, 0xa4, 0xe7, 0x35, 0x6d, 0x03, 0x77, 0x11, 0xd1, 0xa2, 0x24, 0x02, 0xb4, + 0x76, 0xe1, 0xfd, 0x44, 0xfd, 0xc5, 0x33, 0x65, 0x03, 0x31, 0x88, 0x06, 0x51, 0x58, 0x04, 0xa4, 0xf3, 0xcf, 0x3f, + 0x23, 0xd4, 0x13, 0x10, 0x47, 0xc7, 0x9d, 0x6c, 0xcd, 0x36, 0x6a, 0x44, 0x49, 0x94, 0xc6, 0x3e, 0x4c, 0x03, 0xec, + 0x8c, 0x28, 0x0a, 0x5e, 0x3b, 0x29, 0x87, 0xf1, 0xa1, 0x36, 0x0c, 0x33, 0xa8, 0x2a, 0xf0, 0xc4, 0xe5, 0x72, 0x33, + 0xcc, 0x8f, 0x81, 0xaa, 0x30, 0x31, 0x56, 0x90, 0x7d, 0x02, 0x8c, 0x11, 0x76, 0x70, 0xc0, 0xfa, 0x62, 0x10, 0xbc, + 0xe9, 0x55, 0x5d, 0x87, 0xeb, 0x70, 0xe1, 0x62, 0x0a, 0x71, 0xd6, 0x57, 0x2b, 0xfb, 0x97, 0x7c, 0x30, 0xd2, 0x0c, + 0x3c, 0xce, 0x16, 0x9c, 0xb1, 0x62, 0xb7, 0x2c, 0x96, 0x68, 0xf9, 0x3b, 0x98, 0xed, 0xb9, 0xa8, 0x79, 0xdc, 0x4d, + 0xb5, 0xed, 0xa1, 0x3e, 0x37, 0x1a, 0x85, 0x20, 0x66, 0x6d, 0x75, 0xa4, 0xe1, 0xb9, 0x0e, 0xf3, 0x6a, 0xb1, 0x67, + 0x33, 0x55, 0x86, 0x10, 0x85, 0x23, 0x25, 0x01, 0xbb, 0x6d, 0x43, 0x27, 0xe1, 0x47, 0x9d, 0x4a, 0x3a, 0x16, 0x12, + 0xa0, 0xc0, 0x91, 0xb9, 0x9c, 0x37, 0x21, 0xe2, 0x19, 0xda, 0x41, 0xe4, 0x02, 0x13, 0x9a, 0xba, 0x6c, 0xe9, 0x62, + 0x39, 0x45, 0x33, 0xb9, 0x50, 0x6c, 0x31, 0x87, 0xf3, 0xbd, 0x4c, 0xcb, 0x72, 0x9e, 0x7d, 0xae, 0xa7, 0x80, 0xfd, + 0xe5, 0xad, 0x9e, 0x31, 0xb1, 0x88, 0xdc, 0x3c, 0xbf, 0x5a, 0x71, 0xff, 0xcd, 0x0b, 0xfc, 0x88, 0x74, 0x0e, 0xbf, + 0xe2, 0x8f, 0x94, 0x3c, 0x6a, 0x7c, 0xc5, 0x13, 0x4e, 0x2c, 0x6f, 0x90, 0xbc, 0x79, 0x7d, 0xf5, 0xe2, 0xdd, 0x8b, + 0xf7, 0x4f, 0xaf, 0x5f, 0xbc, 0x7a, 0xf6, 0xe2, 0xd5, 0x8b, 0x77, 0x1f, 0xf1, 0x3f, 0x94, 0x7c, 0x3d, 0x6a, 0x9f, + 0xb7, 0xf0, 0x07, 0xf2, 0xf5, 0xa8, 0x83, 0x6f, 0x35, 0xf9, 0x7a, 0x74, 0x82, 0x73, 0x45, 0xbe, 0x1e, 0x76, 0x8e, + 0x8e, 0xf1, 0x42, 0xdb, 0x26, 0x73, 0x39, 0x69, 0xb7, 0xf0, 0x3f, 0xee, 0x0b, 0xc4, 0xfb, 0x6a, 0x16, 0x13, 0xb6, + 0x61, 0xfc, 0x60, 0xca, 0xd0, 0xa1, 0x32, 0x86, 0x28, 0x17, 0x01, 0x3a, 0x4d, 0x55, 0x88, 0x4e, 0x36, 0x88, 0x31, + 0xd8, 0x30, 0x02, 0x5a, 0x71, 0xe2, 0xda, 0xe1, 0x47, 0x6d, 0x76, 0x0c, 0xf4, 0x89, 0x97, 0xc2, 0x71, 0xa9, 0xc2, + 0x69, 0x3b, 0x2d, 0xc6, 0x38, 0x97, 0xb2, 0x88, 0x17, 0xc0, 0x08, 0x18, 0xad, 0x05, 0x3f, 0x2a, 0xa3, 0x25, 0x89, + 0x0b, 0xd2, 0xee, 0xb5, 0x53, 0x71, 0x41, 0x3a, 0xbd, 0x0e, 0xfc, 0x39, 0xed, 0x9d, 0xa6, 0xed, 0x16, 0x3a, 0x0c, + 0xc6, 0xf1, 0x47, 0x0d, 0xad, 0xfb, 0x03, 0xec, 0xba, 0x50, 0xff, 0x14, 0xda, 0xab, 0xf4, 0x84, 0x53, 0xc7, 0xb6, + 0xbb, 0xe2, 0x82, 0x19, 0x3d, 0x2c, 0xff, 0x01, 0x50, 0xdb, 0x38, 0x74, 0x94, 0x1b, 0xc7, 0xfd, 0xe2, 0x47, 0x02, + 0xd5, 0x42, 0xb2, 0xc4, 0x6c, 0xd5, 0x42, 0xc0, 0x34, 0x9a, 0x6c, 0x30, 0x07, 0x4a, 0x94, 0x2c, 0xb4, 0x0f, 0x2b, + 0xaf, 0x9a, 0x12, 0x25, 0x73, 0x39, 0x8f, 0x6b, 0xaa, 0x86, 0x5f, 0x03, 0x33, 0xc7, 0x7d, 0xae, 0x5e, 0xd1, 0x57, + 0x71, 0x8d, 0xe7, 0x09, 0x59, 0xbb, 0x70, 0x5b, 0xfc, 0xe2, 0xac, 0x28, 0x6a, 0xe0, 0x2a, 0x01, 0xeb, 0x47, 0xd5, + 0xd4, 0x17, 0xf0, 0x7e, 0x1e, 0x6b, 0xe8, 0x4b, 0x12, 0x50, 0xcf, 0x9f, 0x4a, 0x33, 0xae, 0x52, 0x19, 0xed, 0x15, + 0xd1, 0xc6, 0x2c, 0xc8, 0x2b, 0xa2, 0x2f, 0x94, 0x01, 0x82, 0x24, 0xbc, 0x2f, 0x06, 0x70, 0xe0, 0xdb, 0x01, 0x4a, + 0x43, 0xe7, 0x40, 0xad, 0x54, 0x99, 0x09, 0x99, 0x4f, 0x13, 0x1c, 0x00, 0x34, 0x4f, 0x95, 0x0a, 0xca, 0x7c, 0x62, + 0x89, 0x82, 0xa1, 0xff, 0x16, 0x6e, 0x80, 0xc3, 0xd8, 0xa0, 0x62, 0x90, 0x7d, 0x4f, 0xd4, 0xf3, 0xdb, 0xe7, 0xad, + 0xa3, 0xaf, 0x41, 0xfe, 0x48, 0x79, 0x7b, 0x8f, 0xbf, 0x03, 0x4a, 0x6e, 0xc3, 0x59, 0xb5, 0xb1, 0x8f, 0x44, 0xd6, + 0x0d, 0x01, 0x72, 0xa8, 0xd1, 0x91, 0x79, 0x4a, 0xb0, 0x8b, 0xf4, 0x21, 0x69, 0xb7, 0x20, 0x7c, 0xd8, 0x0e, 0xca, + 0xf7, 0xd3, 0x06, 0x4c, 0x75, 0x72, 0xdb, 0x04, 0x5a, 0x0d, 0xaf, 0x0b, 0xdd, 0x35, 0x79, 0x72, 0x87, 0x55, 0x80, + 0x33, 0xec, 0x90, 0x35, 0xc4, 0xa1, 0x40, 0x2e, 0xec, 0xaa, 0xdd, 0x00, 0x9a, 0x8a, 0x8e, 0x7d, 0xe5, 0xce, 0x1b, + 0x47, 0x5d, 0x34, 0x93, 0xd3, 0xc3, 0xaf, 0x07, 0x07, 0xb1, 0x6c, 0x90, 0x47, 0x08, 0x2f, 0x29, 0x58, 0x31, 0x83, + 0xd7, 0x17, 0xb7, 0x4c, 0x7c, 0xaa, 0x02, 0xea, 0xb8, 0x50, 0xb5, 0x63, 0xad, 0xea, 0xac, 0xdc, 0x0d, 0x7e, 0x4c, + 0x1d, 0xd4, 0x08, 0xd2, 0xec, 0xe8, 0x3a, 0x35, 0x28, 0xd7, 0x5c, 0xb4, 0x60, 0x5b, 0x36, 0x3e, 0x52, 0xf4, 0xc3, + 0xa3, 0xe6, 0xd7, 0x60, 0xc2, 0x35, 0xd3, 0xa4, 0x47, 0x8d, 0x47, 0xe8, 0x87, 0x47, 0x81, 0x93, 0x1d, 0xaf, 0xd8, + 0x13, 0xcf, 0x8d, 0xfc, 0x64, 0xb9, 0xd2, 0x9f, 0x40, 0xb2, 0x2f, 0xc8, 0x4f, 0x80, 0xe5, 0x94, 0xfc, 0x14, 0xcb, + 0x26, 0x04, 0x1f, 0x24, 0x3f, 0xc5, 0x05, 0xfc, 0xc8, 0xc9, 0x4f, 0x31, 0x60, 0x3b, 0x9e, 0x9a, 0x1f, 0x45, 0x09, + 0x0c, 0x70, 0xec, 0x92, 0xd6, 0xbf, 0xab, 0x58, 0xad, 0xc4, 0xc1, 0x81, 0xb4, 0xbf, 0xe8, 0x65, 0x76, 0x70, 0x90, + 0x5f, 0x4c, 0xab, 0xbe, 0x99, 0xde, 0x45, 0x5f, 0x0c, 0x42, 0xe1, 0xc0, 0x34, 0x8d, 0x87, 0x33, 0xfe, 0x14, 0x52, + 0x56, 0xd3, 0x40, 0xf3, 0xb8, 0x73, 0xff, 0xec, 0x1c, 0xc3, 0xbf, 0xf7, 0x83, 0x82, 0x3f, 0x97, 0x7c, 0x17, 0x69, + 0xb3, 0xe6, 0x59, 0x85, 0x6c, 0x97, 0x01, 0x3e, 0x63, 0x86, 0x9a, 0xe2, 0xe0, 0x80, 0x5f, 0x04, 0xb8, 0x8c, 0x19, + 0x6a, 0x04, 0x16, 0x7b, 0x0f, 0x4b, 0x7b, 0x32, 0xc3, 0x35, 0xc1, 0xb3, 0xb2, 0xbc, 0x5f, 0x0c, 0x2e, 0xb4, 0xa3, + 0x26, 0x61, 0xf0, 0x69, 0x45, 0x5a, 0x6e, 0x93, 0x75, 0x45, 0x53, 0x5d, 0xb6, 0xbb, 0x48, 0x12, 0xd5, 0x10, 0x97, + 0x97, 0x6d, 0x0c, 0x2a, 0xf9, 0x9e, 0x22, 0x32, 0x15, 0xc4, 0x3b, 0xc8, 0x2d, 0x73, 0x99, 0x2a, 0x3c, 0xe5, 0xa9, + 0xf0, 0x72, 0xf6, 0x6b, 0x6f, 0x3d, 0x6d, 0x5c, 0x16, 0x4d, 0xcf, 0x0c, 0x8b, 0x9e, 0x2a, 0x5d, 0xed, 0x60, 0x93, + 0xaa, 0x01, 0xbc, 0xda, 0x57, 0x62, 0x1e, 0xb3, 0xfe, 0x65, 0x0c, 0xa2, 0x22, 0xab, 0x46, 0x1b, 0x32, 0xe1, 0x73, + 0x9d, 0x2a, 0x18, 0xa8, 0x29, 0x7c, 0x01, 0x64, 0x2a, 0xab, 0x0c, 0xb3, 0x7d, 0xc3, 0x50, 0x40, 0x40, 0x81, 0x4b, + 0xc2, 0x02, 0x09, 0x1e, 0x6e, 0x3f, 0x02, 0xc2, 0x51, 0x27, 0x17, 0x76, 0x72, 0x17, 0x0a, 0xba, 0x13, 0x83, 0x0b, + 0xdd, 0x45, 0xa2, 0xd1, 0x70, 0xdc, 0xf6, 0xa5, 0x30, 0x83, 0x68, 0xb6, 0x07, 0x97, 0xac, 0x8b, 0x54, 0xb3, 0x59, + 0x1a, 0x40, 0x5e, 0xb6, 0x56, 0x2b, 0x75, 0xe1, 0x1b, 0xe9, 0xf9, 0x73, 0xdc, 0xf0, 0x5d, 0x5e, 0xf0, 0xfc, 0x4d, + 0x92, 0x7e, 0x04, 0x54, 0x15, 0xf8, 0x6c, 0x39, 0x8f, 0x70, 0x64, 0x1e, 0x74, 0x83, 0xbf, 0xe6, 0x21, 0xae, 0x08, + 0x47, 0xee, 0x8d, 0xb7, 0x68, 0x50, 0x0d, 0x96, 0x67, 0x65, 0x78, 0x72, 0x9e, 0x5c, 0x03, 0xe3, 0xa0, 0xff, 0x56, + 0x68, 0x59, 0xfd, 0x4e, 0x72, 0x17, 0xa8, 0x43, 0xf9, 0x67, 0xc7, 0xdc, 0xa8, 0xd6, 0xbb, 0x5d, 0x23, 0x39, 0x8e, + 0x7c, 0x55, 0x08, 0xdf, 0xff, 0x9d, 0x77, 0x0f, 0xdb, 0xee, 0xb9, 0xed, 0x65, 0xd9, 0x03, 0x70, 0xde, 0xeb, 0x35, + 0xc2, 0xbf, 0xc9, 0x9d, 0x6f, 0xef, 0x46, 0xd7, 0x52, 0x3c, 0xa1, 0x9a, 0x46, 0x8d, 0x37, 0xc6, 0xf0, 0xcd, 0xca, + 0x59, 0xdd, 0x6f, 0x8d, 0x83, 0xfd, 0x5b, 0xdd, 0x43, 0xe8, 0x84, 0xda, 0x33, 0x41, 0x56, 0xf6, 0x35, 0x01, 0x33, + 0x64, 0x60, 0xfa, 0xb6, 0x03, 0x1e, 0x7e, 0x8c, 0x14, 0x1c, 0x7a, 0x2d, 0x9f, 0x44, 0x21, 0x26, 0x69, 0xcd, 0x8d, + 0x18, 0x52, 0x6c, 0x1f, 0xc6, 0xe5, 0x74, 0x8d, 0x42, 0xae, 0x7b, 0xac, 0xea, 0xc4, 0xb4, 0xea, 0xc6, 0x48, 0x1d, + 0x6c, 0x93, 0x05, 0x67, 0x55, 0xef, 0x46, 0x42, 0xa9, 0x5e, 0x54, 0x33, 0xaf, 0x62, 0x36, 0xdb, 0xe6, 0x99, 0x61, + 0xfb, 0xee, 0x9a, 0x02, 0x43, 0xde, 0xfd, 0x32, 0x5c, 0xd4, 0x25, 0x1c, 0xbb, 0x71, 0x00, 0x59, 0x49, 0x2e, 0x97, + 0xee, 0x4d, 0x34, 0xde, 0x97, 0x83, 0x75, 0xf9, 0x42, 0x5a, 0x80, 0x07, 0xd5, 0x48, 0x45, 0x16, 0x72, 0x06, 0xfe, + 0x79, 0xc1, 0x9a, 0x7e, 0x88, 0x7f, 0x85, 0x03, 0xbe, 0x42, 0xd2, 0xd4, 0xaa, 0x9f, 0xe0, 0xe5, 0x22, 0x50, 0x78, + 0xdb, 0xba, 0x9f, 0x64, 0xe8, 0x22, 0x5a, 0xd7, 0xa9, 0x58, 0x2f, 0xcc, 0xba, 0x62, 0xa5, 0x2c, 0x1c, 0x1c, 0x77, + 0x31, 0x5a, 0xa7, 0xce, 0x63, 0xd3, 0x3d, 0x77, 0xf4, 0x50, 0xf0, 0x99, 0x71, 0xa4, 0x7b, 0x56, 0x40, 0xfc, 0xaa, + 0x50, 0x9f, 0xf6, 0xb3, 0x0c, 0xdf, 0xf3, 0xed, 0xc3, 0x3d, 0x61, 0xc9, 0x73, 0x96, 0x6f, 0x50, 0xc3, 0x02, 0x29, + 0xa0, 0x50, 0x0a, 0x8b, 0xd5, 0x2a, 0x16, 0x26, 0xaa, 0x81, 0x0b, 0x6a, 0xeb, 0x5e, 0xaf, 0x30, 0xfa, 0x3b, 0xa8, + 0x8b, 0xbd, 0x7a, 0xc4, 0x98, 0xb0, 0xa2, 0xf0, 0xd2, 0x49, 0x65, 0x41, 0x5f, 0xbb, 0xfa, 0x10, 0xd5, 0x94, 0x7b, + 0xb1, 0xd1, 0xf7, 0xbe, 0xe3, 0x33, 0x26, 0x17, 0xf0, 0x6c, 0x10, 0x66, 0x44, 0x31, 0xed, 0xbf, 0x81, 0x82, 0xc0, + 0xdb, 0x33, 0x3c, 0xc4, 0x47, 0xe0, 0xab, 0x3c, 0xad, 0x93, 0x99, 0x7f, 0x8c, 0x22, 0x32, 0xc1, 0x22, 0xa3, 0x5e, + 0x04, 0x5e, 0x43, 0x20, 0x42, 0x11, 0x12, 0x31, 0x31, 0x8a, 0x7a, 0x91, 0x71, 0x52, 0x8a, 0xc0, 0x6a, 0x0c, 0x94, + 0xdc, 0x11, 0x9e, 0xab, 0x8a, 0x88, 0x85, 0x35, 0x75, 0x50, 0x89, 0xa5, 0xc6, 0x4c, 0xfb, 0xa8, 0x53, 0x81, 0xb0, + 0xc8, 0x36, 0x05, 0x65, 0xbd, 0xa1, 0x2e, 0xc0, 0x92, 0x18, 0xd3, 0x5b, 0x9e, 0x5c, 0x03, 0x37, 0xc7, 0x46, 0xae, + 0xe8, 0x92, 0x5f, 0x81, 0x7a, 0x3a, 0x2d, 0xf0, 0xb5, 0x61, 0xd8, 0x46, 0x29, 0x5d, 0x13, 0x8e, 0x33, 0x52, 0x24, + 0xf4, 0x16, 0xa2, 0x3a, 0xcc, 0xb8, 0x48, 0x73, 0x3c, 0xa3, 0xb7, 0xe9, 0x14, 0xcf, 0xb8, 0x78, 0x62, 0x97, 0x3d, + 0x1d, 0x41, 0x92, 0xff, 0x58, 0xac, 0x89, 0x79, 0x94, 0xea, 0x77, 0xc5, 0x8a, 0x47, 0xc0, 0xab, 0xa8, 0x18, 0x75, + 0x47, 0xc6, 0xa6, 0x9c, 0xe9, 0xca, 0x78, 0xfd, 0xb5, 0x8e, 0x29, 0xce, 0x70, 0x8e, 0x92, 0x5c, 0x62, 0xd6, 0x13, + 0xe9, 0x6b, 0x88, 0xe8, 0x9c, 0x61, 0xfb, 0xa0, 0x15, 0xbf, 0x65, 0xf9, 0x33, 0x59, 0xbc, 0x37, 0x5b, 0x3e, 0x47, + 0x50, 0x08, 0x5c, 0x54, 0x44, 0x13, 0x6e, 0xf7, 0x16, 0x3d, 0x59, 0x35, 0x45, 0x6f, 0x6d, 0x53, 0x6e, 0x88, 0x53, + 0x08, 0x85, 0x9b, 0x4c, 0x79, 0xa3, 0x8d, 0x59, 0xaf, 0xf5, 0x9d, 0x46, 0xa7, 0xa8, 0x2c, 0x89, 0x30, 0xac, 0x55, + 0x53, 0xa5, 0x92, 0x88, 0xa6, 0x72, 0x12, 0xde, 0xd2, 0x00, 0x3b, 0x55, 0x38, 0x93, 0x0b, 0xa1, 0x53, 0x19, 0xe0, + 0x0d, 0xad, 0x36, 0xd7, 0xf2, 0xd6, 0x42, 0x4c, 0xe3, 0x3b, 0xfb, 0x83, 0xe1, 0x6b, 0xa3, 0xe2, 0x7f, 0x0b, 0x86, + 0x3d, 0x2a, 0x15, 0x00, 0x3f, 0x30, 0x9c, 0x05, 0xc8, 0x59, 0x7e, 0xf2, 0x16, 0xc0, 0x67, 0x59, 0xc8, 0x3b, 0x48, + 0x65, 0x26, 0xf5, 0x0e, 0x52, 0x19, 0xa4, 0x1a, 0x5f, 0xee, 0x7d, 0x51, 0x29, 0x8b, 0xc2, 0x06, 0x89, 0xc2, 0xa5, + 0x3a, 0x58, 0x12, 0x91, 0x40, 0xbb, 0x46, 0x94, 0x9b, 0x71, 0x01, 0x41, 0xfd, 0xa0, 0x71, 0xfb, 0x4d, 0x6f, 0xe1, + 0xfb, 0xce, 0xe6, 0x33, 0x9f, 0x7f, 0x67, 0xf3, 0x4d, 0x47, 0x1e, 0xe3, 0xeb, 0xb7, 0x9d, 0xc6, 0x32, 0x5e, 0x3a, + 0xac, 0xfd, 0x50, 0x3e, 0xa1, 0xd2, 0x32, 0x4f, 0x55, 0x93, 0x36, 0x9e, 0x04, 0x48, 0xd9, 0xac, 0x78, 0xb8, 0x0e, + 0x6e, 0xb7, 0x0e, 0x63, 0xde, 0x24, 0x6d, 0x84, 0x0e, 0x9d, 0x70, 0x25, 0x62, 0x23, 0x39, 0x1d, 0x3e, 0x3a, 0x82, + 0xbb, 0x97, 0x99, 0xda, 0xf0, 0x95, 0xb2, 0xd5, 0x9a, 0xed, 0xd6, 0x21, 0xdf, 0x59, 0xa5, 0xd1, 0xc6, 0x33, 0x46, + 0x96, 0xe0, 0x5c, 0x46, 0x0b, 0xab, 0x6a, 0x00, 0x27, 0xce, 0x17, 0xe2, 0xb7, 0x05, 0x1d, 0x99, 0xef, 0x43, 0x9b, + 0xf2, 0x7a, 0xa1, 0x7d, 0x52, 0x93, 0xc3, 0x20, 0x3a, 0xc8, 0x95, 0x0c, 0x72, 0x62, 0x7e, 0x44, 0x92, 0x53, 0x74, + 0xd1, 0xee, 0x25, 0xa7, 0x87, 0xfc, 0x90, 0xa7, 0xc0, 0xc3, 0xc6, 0x4d, 0x5f, 0xa1, 0xd9, 0xf6, 0x75, 0x1e, 0x2f, + 0x86, 0x3c, 0x73, 0xcd, 0x57, 0x1d, 0x94, 0xa9, 0x76, 0x8e, 0x90, 0x05, 0x28, 0xe6, 0x7b, 0x09, 0xb2, 0xeb, 0xdd, + 0x1c, 0xf2, 0x14, 0xfa, 0x81, 0x5a, 0x1d, 0x5b, 0xab, 0x1c, 0xdc, 0x6f, 0x0b, 0x40, 0x30, 0xdf, 0x51, 0x6d, 0x2e, + 0x36, 0xbd, 0x19, 0x57, 0x9d, 0x1d, 0xf2, 0x6a, 0x84, 0x61, 0x99, 0xed, 0xfe, 0xfc, 0xd4, 0xaa, 0x2e, 0x0f, 0x03, + 0x88, 0xfc, 0xb6, 0xe0, 0x22, 0xec, 0x34, 0xec, 0xd6, 0xe5, 0x84, 0x9d, 0xd6, 0x67, 0x19, 0x14, 0xd9, 0xee, 0x75, + 0x6b, 0xa6, 0xf5, 0xd9, 0x5e, 0x81, 0x8f, 0x20, 0x4c, 0xca, 0xac, 0x74, 0x06, 0x57, 0xe8, 0x87, 0x1f, 0x90, 0x6b, + 0xfd, 0xf5, 0x42, 0xfb, 0xfc, 0x12, 0x11, 0x20, 0xbb, 0xea, 0xba, 0xac, 0x0e, 0x7d, 0x94, 0x4d, 0x7c, 0x3d, 0xe4, + 0xc1, 0xca, 0x3d, 0xbd, 0x9d, 0xcb, 0xd4, 0xe3, 0x6b, 0xaf, 0x95, 0x6e, 0x21, 0x27, 0x10, 0x0f, 0xd7, 0x5d, 0x58, + 0x16, 0xe4, 0xec, 0xe6, 0x16, 0x4a, 0x86, 0x13, 0xf7, 0xa5, 0x3f, 0x30, 0x7b, 0xdd, 0xc0, 0x2f, 0x92, 0x53, 0x98, + 0xfa, 0x66, 0x0f, 0x87, 0x1d, 0xe8, 0xc3, 0xc0, 0x61, 0xb3, 0x41, 0x9f, 0x59, 0x41, 0xe4, 0x31, 0x2f, 0x2c, 0x9e, + 0x5d, 0x92, 0x76, 0x8f, 0xa7, 0x6e, 0x33, 0x19, 0xd1, 0xa8, 0xdd, 0xe4, 0xc1, 0xcc, 0x00, 0xbf, 0x5c, 0xd9, 0xb0, + 0x88, 0x5f, 0xa7, 0x00, 0x4a, 0xbe, 0x58, 0xb5, 0x3e, 0x15, 0xbc, 0xea, 0x0d, 0xa7, 0x9b, 0xe9, 0x7e, 0xdd, 0xe0, + 0x76, 0xd7, 0xc3, 0x13, 0x9e, 0x40, 0xb1, 0x68, 0xed, 0x27, 0x3e, 0x01, 0x0e, 0x28, 0x69, 0xdd, 0x3f, 0x05, 0x17, + 0xca, 0x12, 0x96, 0xdb, 0xe5, 0x66, 0x5b, 0xe5, 0x2c, 0x1c, 0x6d, 0xc9, 0x80, 0x3b, 0xd8, 0x84, 0x28, 0x74, 0x70, + 0xd8, 0xc1, 0x49, 0xbb, 0xdd, 0x39, 0xc5, 0xc9, 0xc9, 0x29, 0x0c, 0xb4, 0x91, 0x9c, 0x1e, 0xce, 0x94, 0x05, 0x60, + 0x90, 0xb3, 0x76, 0xed, 0x3e, 0x82, 0x70, 0x49, 0xa1, 0x78, 0xcd, 0x0f, 0xe3, 0xb8, 0x9d, 0xdc, 0x6f, 0xb5, 0x4f, + 0xcf, 0x1b, 0x00, 0xa0, 0xa6, 0xfb, 0x70, 0x35, 0x5e, 0x2f, 0x74, 0xbd, 0x4a, 0x89, 0xf0, 0xf5, 0x6a, 0x0d, 0x5f, + 0xad, 0xd1, 0x5e, 0x57, 0x53, 0xf0, 0x55, 0x9d, 0x70, 0x6e, 0x8b, 0x78, 0xa5, 0x4d, 0xb8, 0x2d, 0x62, 0x3b, 0x90, + 0x18, 0xa4, 0xf3, 0xe4, 0xb4, 0x73, 0x8a, 0xec, 0x58, 0xb4, 0xc3, 0x8f, 0x72, 0x9f, 0x6c, 0x15, 0x69, 0x68, 0x40, + 0x92, 0x72, 0x76, 0x72, 0x01, 0x12, 0x35, 0x27, 0x97, 0xed, 0xe6, 0x8c, 0x25, 0x7e, 0x02, 0x26, 0x15, 0x96, 0xb3, + 0x5c, 0x05, 0x97, 0x14, 0x00, 0xe2, 0x02, 0x8c, 0x8b, 0xee, 0x9f, 0xf6, 0xee, 0x27, 0xa7, 0x67, 0x1d, 0x4b, 0xf4, + 0xf8, 0x45, 0xa7, 0x96, 0x66, 0xa6, 0x9e, 0x9c, 0x9a, 0x34, 0xe8, 0x3a, 0xb9, 0x7f, 0x0a, 0x65, 0x5c, 0x4a, 0x58, + 0x0a, 0xc2, 0x3c, 0x54, 0xc5, 0x20, 0xb6, 0x43, 0x5a, 0xcb, 0x3d, 0xab, 0x65, 0x9f, 0x9f, 0x1c, 0xdf, 0x3f, 0x0d, + 0xa1, 0x56, 0xce, 0xc2, 0x2c, 0xb4, 0x9b, 0x88, 0x9f, 0x1d, 0x2c, 0x2d, 0x3a, 0x4c, 0x4e, 0xd3, 0xad, 0x09, 0xda, + 0x4d, 0x73, 0x68, 0x70, 0x20, 0x50, 0x38, 0x3e, 0x15, 0x4e, 0x5f, 0x12, 0xdc, 0x8f, 0x55, 0x86, 0x26, 0xa1, 0xc2, + 0xd9, 0xdf, 0x53, 0x06, 0x2f, 0x39, 0x86, 0x57, 0x95, 0x8f, 0xa9, 0xf8, 0x42, 0xd5, 0x1b, 0x0a, 0xb1, 0x2b, 0xc4, + 0x20, 0x72, 0x91, 0xb5, 0xeb, 0xb9, 0x3f, 0x81, 0x8b, 0x30, 0x13, 0x70, 0xa1, 0xe9, 0x95, 0xa0, 0x15, 0x2f, 0x30, + 0x0c, 0x1d, 0x6a, 0xcd, 0xb0, 0x7a, 0x3c, 0x75, 0x26, 0x05, 0xa1, 0x6e, 0xeb, 0x39, 0xff, 0x5e, 0xb9, 0xa4, 0xbc, + 0xca, 0x4e, 0x4e, 0x51, 0xe2, 0x2e, 0xcb, 0x93, 0x36, 0x4a, 0x02, 0x13, 0x12, 0x77, 0x24, 0x67, 0x19, 0xe9, 0x47, + 0xb7, 0x11, 0x8e, 0xee, 0x22, 0x1c, 0x59, 0x1f, 0xe6, 0x0f, 0xe0, 0x3c, 0x1f, 0xe1, 0xc8, 0xba, 0x32, 0x47, 0x38, + 0xd2, 0x4c, 0x40, 0x48, 0xab, 0x68, 0x80, 0x73, 0x28, 0x6d, 0x3c, 0xab, 0xcb, 0xd2, 0x8f, 0xfd, 0x57, 0xe9, 0x7a, + 0x6d, 0x53, 0x02, 0x29, 0x73, 0x6a, 0x76, 0xa8, 0x7d, 0x92, 0x39, 0xa2, 0x9e, 0x59, 0x8f, 0x30, 0x08, 0x20, 0xf4, + 0xce, 0x3f, 0xe9, 0x56, 0x45, 0xc3, 0x60, 0xc7, 0xb0, 0xd2, 0xe0, 0x67, 0x1e, 0x85, 0x67, 0x58, 0x84, 0xc7, 0xc2, + 0x17, 0x06, 0xb1, 0xc2, 0xff, 0xce, 0xa5, 0x9c, 0xfb, 0xdf, 0x5a, 0x96, 0xbf, 0xe0, 0x21, 0x10, 0x67, 0xd1, 0x02, + 0x96, 0x5b, 0x36, 0xf8, 0xce, 0x90, 0xd5, 0x47, 0x70, 0x3d, 0x76, 0x01, 0xd2, 0x40, 0x22, 0xbc, 0x36, 0x02, 0x95, + 0x97, 0x0f, 0xaf, 0x6d, 0xb0, 0x1e, 0xf3, 0x09, 0xd1, 0xba, 0x20, 0x20, 0xaf, 0x84, 0x0b, 0x8d, 0x49, 0xc1, 0x94, + 0x8a, 0x6c, 0x14, 0xbb, 0x48, 0x0a, 0xff, 0x2c, 0xa1, 0x4f, 0x19, 0x8b, 0xc8, 0x74, 0x58, 0x9f, 0xad, 0x15, 0x87, + 0x73, 0x59, 0xa8, 0xd4, 0xbe, 0x51, 0xe2, 0xc1, 0x58, 0x3d, 0x55, 0x9f, 0xe6, 0xd9, 0x1a, 0xdb, 0x3b, 0xec, 0xb2, + 0x90, 0xbb, 0xd2, 0x0e, 0x4b, 0x65, 0xd9, 0xfa, 0x5b, 0x13, 0x52, 0xb5, 0x19, 0x05, 0x13, 0xad, 0x06, 0x54, 0x85, + 0xb2, 0x80, 0xc2, 0x36, 0x1c, 0x4a, 0xba, 0x2c, 0x4b, 0xa6, 0xcb, 0x72, 0x19, 0x4e, 0x5a, 0xad, 0xf5, 0x1a, 0x17, + 0xcc, 0x84, 0x65, 0xd9, 0x59, 0x02, 0xf2, 0xd5, 0x54, 0xde, 0x04, 0xb9, 0x2a, 0x2d, 0x67, 0x69, 0x96, 0x28, 0x0a, + 0x8c, 0x60, 0xa3, 0x35, 0xfe, 0xc2, 0x15, 0x07, 0x78, 0xba, 0xd9, 0x0d, 0xa5, 0xcc, 0x19, 0x85, 0xe8, 0x5d, 0x41, + 0x93, 0x6b, 0x3c, 0xe5, 0x23, 0xb6, 0xbb, 0x4d, 0x30, 0x63, 0xfe, 0xf7, 0x5a, 0xf4, 0x08, 0x64, 0xd9, 0x3d, 0x83, + 0x3a, 0xb0, 0x88, 0x2b, 0xe8, 0x20, 0x94, 0xc1, 0x47, 0x21, 0x6e, 0xe6, 0xf4, 0x4e, 0x2e, 0x34, 0xc0, 0x65, 0xa1, + 0xe5, 0x1b, 0x17, 0xeb, 0x60, 0xbf, 0x85, 0x7d, 0xd8, 0x83, 0x25, 0x84, 0x0c, 0x68, 0x61, 0x1b, 0x23, 0xa2, 0x85, + 0x87, 0x52, 0x6b, 0x39, 0x4b, 0x5b, 0xd8, 0x04, 0x6c, 0x68, 0xad, 0xcb, 0xa8, 0x5a, 0xd7, 0xe5, 0x63, 0x8e, 0xd5, + 0x26, 0x58, 0x38, 0xe9, 0x50, 0x13, 0x1d, 0xdc, 0x1e, 0x32, 0xc2, 0x1b, 0x3f, 0x5f, 0xbd, 0x7e, 0xe5, 0x62, 0x26, + 0xf3, 0x31, 0xb8, 0x6c, 0x3a, 0xd5, 0xd8, 0xb5, 0x79, 0x05, 0x29, 0xae, 0x14, 0xa5, 0x56, 0x38, 0x85, 0x96, 0x5f, + 0x08, 0x9d, 0x27, 0xf6, 0xf2, 0xe2, 0x99, 0x2c, 0x66, 0xd4, 0xde, 0x18, 0xe1, 0x6b, 0xe5, 0x9e, 0x3d, 0x37, 0x2f, + 0xab, 0x54, 0x93, 0x7c, 0xb7, 0x79, 0x15, 0xb1, 0xc8, 0x8c, 0xfc, 0x0a, 0xda, 0x00, 0x53, 0xb9, 0x7c, 0xb5, 0xb6, + 0x20, 0x2e, 0xf2, 0x7c, 0x40, 0x5e, 0xde, 0x5a, 0xea, 0x12, 0x45, 0x0d, 0x6e, 0xf0, 0x93, 0x15, 0x3c, 0x0b, 0xae, + 0x0b, 0x0d, 0x7b, 0xe4, 0xc4, 0x8b, 0xa8, 0x15, 0xd5, 0x5f, 0x7d, 0x35, 0xaa, 0x04, 0x1f, 0xb5, 0x34, 0xc9, 0x25, + 0x88, 0x1e, 0xe5, 0x03, 0x73, 0x1c, 0x44, 0x13, 0x7f, 0xf7, 0x7c, 0xd9, 0xf6, 0x74, 0x36, 0xaf, 0xd4, 0x89, 0xe5, + 0x95, 0x09, 0x78, 0x38, 0xda, 0x27, 0x5c, 0x10, 0x0e, 0x12, 0x59, 0xa9, 0x3d, 0xf4, 0xb9, 0xa8, 0x1b, 0xe7, 0x17, + 0x6d, 0xd6, 0x3c, 0x59, 0xad, 0xf2, 0xcb, 0x36, 0x6b, 0x9f, 0xda, 0x07, 0xdf, 0x22, 0x95, 0x01, 0xcd, 0xe5, 0x63, + 0x9e, 0x45, 0xa0, 0x9d, 0x1d, 0x67, 0x26, 0x9c, 0x82, 0x0f, 0x51, 0x4c, 0x16, 0xba, 0xea, 0x4b, 0x82, 0x71, 0x29, + 0xb1, 0x7a, 0xfc, 0x02, 0xf5, 0xda, 0xe9, 0xb6, 0xab, 0x74, 0xb3, 0x7d, 0x18, 0x5c, 0xb8, 0x14, 0x08, 0x77, 0x20, + 0xe4, 0x01, 0xe8, 0x77, 0x97, 0x02, 0x4c, 0x83, 0x00, 0x95, 0x15, 0x88, 0xb4, 0x7c, 0xb6, 0x98, 0x3d, 0x2b, 0xa8, + 0x59, 0x86, 0x27, 0x7c, 0xc2, 0xb5, 0x4a, 0x29, 0x48, 0xb7, 0xbb, 0xd2, 0xd7, 0xbb, 0x25, 0xa8, 0xac, 0x16, 0xf9, + 0x35, 0xd1, 0x3c, 0xfb, 0xac, 0xdc, 0xc2, 0x21, 0x6c, 0x56, 0x56, 0xe0, 0x0c, 0xad, 0x71, 0x2e, 0x27, 0xb4, 0xe0, + 0x7a, 0x3a, 0xfb, 0xb7, 0x56, 0x87, 0xf5, 0xf5, 0xc0, 0x5c, 0x58, 0x01, 0x48, 0xa8, 0x18, 0xad, 0x56, 0xfc, 0xe8, + 0xfb, 0xf7, 0x49, 0xde, 0x27, 0xbc, 0x8d, 0x3b, 0xf8, 0x18, 0x9f, 0xe2, 0x76, 0x0b, 0xb7, 0x4f, 0xe1, 0xea, 0x3e, + 0xcb, 0x17, 0x23, 0xa6, 0x62, 0x78, 0xf9, 0x4b, 0x5f, 0x26, 0xe7, 0x87, 0x65, 0xbc, 0x7b, 0x5d, 0x24, 0x0e, 0x5d, + 0x82, 0xb0, 0xeb, 0x2e, 0x5e, 0x5d, 0x14, 0x85, 0xc1, 0xd2, 0xc6, 0xa1, 0xea, 0xa4, 0xd4, 0x2f, 0x5c, 0x1e, 0xf7, + 0xc0, 0x9e, 0xdb, 0xae, 0x6c, 0x13, 0xcc, 0xbe, 0xed, 0xcf, 0xb4, 0xfa, 0xd9, 0xd4, 0x25, 0x62, 0x78, 0xe8, 0x55, + 0xe8, 0x81, 0x2e, 0x49, 0xfb, 0xe0, 0x00, 0xac, 0x8e, 0x82, 0xd9, 0x70, 0x1b, 0xfd, 0x80, 0x37, 0x6b, 0x69, 0x10, + 0xac, 0x00, 0x8c, 0x3b, 0xdf, 0x70, 0xb2, 0xb4, 0xb0, 0xd5, 0x40, 0x85, 0x75, 0x11, 0x46, 0x74, 0x0b, 0x49, 0x85, + 0x11, 0xa2, 0xe1, 0x08, 0x73, 0x91, 0x4e, 0xf6, 0x5b, 0x58, 0x8e, 0xc7, 0x8a, 0x69, 0x38, 0x3a, 0x0a, 0xf6, 0x85, + 0x15, 0xca, 0x9c, 0x22, 0x43, 0x36, 0xe1, 0xe2, 0xa1, 0xfe, 0xc4, 0x0a, 0x69, 0x3e, 0x8d, 0x06, 0x23, 0x8d, 0xcc, + 0x2a, 0x46, 0x38, 0xcb, 0xf9, 0x1c, 0xaa, 0x4e, 0x0a, 0x70, 0xfa, 0x81, 0xbf, 0x7c, 0x94, 0x86, 0x6d, 0x02, 0xf9, + 0xfa, 0x60, 0x83, 0xd9, 0xe0, 0x51, 0x41, 0x6f, 0x5e, 0x8b, 0xc7, 0xb0, 0xa3, 0x1e, 0x16, 0x8c, 0x42, 0x36, 0x24, + 0xbd, 0x83, 0xa6, 0xe0, 0x03, 0xda, 0x7c, 0x69, 0x00, 0x97, 0x9e, 0x9b, 0x0f, 0x5b, 0xd1, 0x47, 0x0d, 0x4c, 0xca, + 0xb6, 0x4c, 0xa6, 0x39, 0xa5, 0xab, 0x4c, 0x1b, 0x97, 0xa9, 0x9c, 0xc2, 0x1a, 0xbb, 0xa8, 0x27, 0xe1, 0x60, 0x46, + 0x54, 0x4d, 0xd3, 0xfe, 0xc0, 0xfc, 0x7d, 0x6d, 0x4b, 0xb6, 0xb0, 0x0b, 0xb5, 0xb3, 0xc6, 0xe6, 0xc9, 0xce, 0xa0, + 0x7c, 0x1b, 0xc3, 0x3d, 0x2c, 0xbc, 0x1b, 0x59, 0x23, 0x9f, 0x27, 0x9e, 0x6c, 0x9e, 0xac, 0xd7, 0x66, 0x20, 0x2a, + 0x05, 0x3d, 0xd0, 0x5b, 0xbf, 0x6d, 0x5a, 0xb0, 0x3d, 0xca, 0xaf, 0xd3, 0x16, 0x9e, 0x71, 0x78, 0x06, 0xd3, 0xb7, + 0x77, 0xa5, 0x0b, 0xf9, 0xd9, 0x81, 0xa4, 0x15, 0xa4, 0xd8, 0xe9, 0x04, 0x9d, 0x1d, 0xe3, 0x60, 0xe4, 0x40, 0xcf, + 0xaf, 0x3e, 0x5b, 0x58, 0xfb, 0xdf, 0x6f, 0xca, 0x82, 0x39, 0x1d, 0xb2, 0xbc, 0x9c, 0x50, 0xe6, 0xcf, 0xcf, 0x37, + 0x3c, 0xa9, 0x50, 0xc1, 0xbd, 0x1f, 0x05, 0x7b, 0xda, 0x86, 0x98, 0x9c, 0xd1, 0xbf, 0xed, 0x0f, 0x1b, 0x11, 0xa8, + 0xd4, 0xb2, 0x65, 0x85, 0x54, 0xea, 0xa1, 0x4d, 0xb3, 0x47, 0x0f, 0x1c, 0x91, 0x2f, 0xa1, 0x0b, 0xe0, 0xf5, 0x47, + 0x85, 0x9c, 0x1b, 0x44, 0x70, 0xbf, 0xdd, 0xb8, 0x8d, 0xaf, 0x00, 0x78, 0x3b, 0xec, 0x55, 0xff, 0xb4, 0x80, 0xfd, + 0x8d, 0xca, 0x92, 0x7e, 0xbc, 0x1d, 0x7b, 0xfc, 0x17, 0x12, 0xe2, 0x95, 0x5b, 0x3c, 0x4c, 0x1c, 0x3a, 0x95, 0xac, + 0x59, 0xf9, 0x73, 0xab, 0x24, 0x60, 0x58, 0xbd, 0x60, 0xc8, 0xc6, 0x6d, 0x15, 0xb7, 0x99, 0xff, 0x41, 0x05, 0x83, + 0x05, 0xdf, 0x1a, 0x49, 0xc5, 0xb2, 0xf8, 0xed, 0x53, 0xe7, 0xbf, 0xea, 0x1c, 0xd7, 0xbe, 0xae, 0xbd, 0x51, 0x39, + 0x34, 0xf1, 0x81, 0x23, 0x74, 0x70, 0xb0, 0x91, 0x41, 0xc7, 0x00, 0x78, 0xe4, 0xd8, 0x2f, 0xbf, 0x7c, 0x9e, 0x1d, + 0x33, 0x9a, 0xc7, 0x22, 0x0a, 0x99, 0x3b, 0xcf, 0xcd, 0xd9, 0x89, 0x3c, 0xa1, 0x6a, 0xea, 0x0b, 0x03, 0x1c, 0x1f, + 0x6d, 0xa5, 0x02, 0xbe, 0x47, 0xeb, 0x1d, 0x13, 0xd8, 0xe0, 0xb7, 0xec, 0xa4, 0x76, 0x15, 0xf4, 0x0b, 0xb4, 0xdc, + 0xc5, 0x54, 0x6e, 0x2c, 0x70, 0xb4, 0x39, 0x91, 0x9d, 0x43, 0xdf, 0xa8, 0x53, 0xb2, 0x1e, 0x4f, 0x76, 0x1b, 0x7d, + 0x49, 0xb1, 0x2b, 0xb9, 0xa2, 0x6d, 0x43, 0x56, 0xbd, 0x53, 0xab, 0x2b, 0x53, 0xa7, 0xea, 0x9a, 0xb7, 0xb2, 0xb4, + 0x29, 0xed, 0x92, 0xec, 0xdd, 0x16, 0x0b, 0xaf, 0xc2, 0x1b, 0x8d, 0xf2, 0x22, 0x14, 0xec, 0xb1, 0xc4, 0xa0, 0xcb, + 0x09, 0x5c, 0x2f, 0xac, 0x56, 0x31, 0xfc, 0xd9, 0x35, 0x86, 0x5d, 0xa6, 0x4b, 0x1f, 0xf8, 0x06, 0xbf, 0x12, 0x84, + 0xca, 0x75, 0x76, 0x90, 0x60, 0xdd, 0xe5, 0x06, 0x0d, 0xc7, 0x89, 0xff, 0x82, 0x87, 0x9a, 0xb5, 0x77, 0x39, 0x98, + 0x64, 0xdf, 0x78, 0xdc, 0xad, 0x64, 0x2d, 0x6b, 0x71, 0xd6, 0x37, 0x24, 0x18, 0x62, 0x37, 0xa5, 0x73, 0xdc, 0x4a, + 0xda, 0x28, 0x72, 0xc5, 0x2a, 0xf4, 0xff, 0x56, 0x91, 0xcc, 0x66, 0xfe, 0xd7, 0xd9, 0xd9, 0x99, 0x4b, 0x71, 0x36, + 0x7f, 0xca, 0x78, 0xc0, 0x99, 0x04, 0xf6, 0x85, 0x67, 0xcc, 0xe8, 0x90, 0xdf, 0xc2, 0x50, 0x88, 0x20, 0x97, 0xc2, + 0xb1, 0x4b, 0xf0, 0xce, 0x20, 0x50, 0x1e, 0x60, 0xff, 0x9e, 0x6c, 0x94, 0xf3, 0x0f, 0x15, 0xf9, 0x40, 0xbe, 0x65, + 0x83, 0xec, 0x8b, 0xf9, 0xec, 0x5b, 0x33, 0x19, 0x88, 0xcd, 0x1f, 0x61, 0xfb, 0xdb, 0xb0, 0xb4, 0xce, 0x52, 0x06, + 0x47, 0x5a, 0x2e, 0xb2, 0xa9, 0xd5, 0xfc, 0xbb, 0x0f, 0x53, 0xd6, 0x3d, 0x72, 0x03, 0x41, 0xb9, 0xc8, 0xd2, 0xc5, + 0xa3, 0x8c, 0x7e, 0x2c, 0x43, 0x4f, 0xee, 0xbd, 0x62, 0x0b, 0xf6, 0x23, 0xde, 0xab, 0x52, 0xe0, 0xe3, 0x61, 0xc1, + 0x69, 0xfe, 0x23, 0xde, 0xab, 0x42, 0x50, 0x82, 0x2b, 0xa4, 0x89, 0xe2, 0x88, 0xcd, 0x83, 0xce, 0x69, 0x24, 0x80, + 0x82, 0xe6, 0x91, 0x39, 0xc8, 0x9e, 0xbb, 0xa8, 0x85, 0x49, 0x07, 0xbb, 0xb8, 0x5f, 0x36, 0x16, 0xa9, 0x0d, 0xe1, + 0x0d, 0x91, 0xdc, 0xca, 0xd9, 0x98, 0xaf, 0x47, 0x1b, 0x0b, 0x62, 0x94, 0xc9, 0xe4, 0xf2, 0x39, 0x8f, 0xb7, 0x16, + 0x0b, 0x85, 0xd5, 0x82, 0x05, 0xaa, 0x55, 0xa9, 0xd2, 0xc3, 0xe2, 0xdb, 0x05, 0xb3, 0xa0, 0x88, 0xd9, 0x7a, 0x0f, + 0x6f, 0xb9, 0x22, 0x20, 0x25, 0xbb, 0x24, 0x78, 0x93, 0xdb, 0x60, 0xaa, 0x7f, 0x82, 0x1d, 0x08, 0x3d, 0x53, 0x3a, + 0xc2, 0x26, 0x4f, 0x41, 0x24, 0xb1, 0xfd, 0x16, 0x76, 0xac, 0xd1, 0x0b, 0xe1, 0x85, 0x14, 0x38, 0x57, 0x4d, 0x13, + 0x33, 0xca, 0x4d, 0x74, 0xb1, 0x87, 0x6a, 0xce, 0x32, 0x6d, 0x11, 0x60, 0xdf, 0xa1, 0xa1, 0x14, 0xcf, 0x0d, 0x28, + 0xcc, 0x63, 0xd2, 0x2e, 0xe5, 0x31, 0x2c, 0x5e, 0x90, 0x02, 0x44, 0x8d, 0x8b, 0x49, 0x59, 0x67, 0x9e, 0x2f, 0x26, + 0x5c, 0x54, 0xc8, 0x50, 0x30, 0x35, 0x97, 0x02, 0xde, 0x72, 0x28, 0x8b, 0x18, 0x3a, 0x54, 0xc3, 0x77, 0x4b, 0xc2, + 0xca, 0x3a, 0xe6, 0x98, 0xe2, 0xa2, 0xaa, 0x01, 0xcc, 0xc5, 0xc3, 0xf0, 0xd1, 0x77, 0xf5, 0x5a, 0xbc, 0x93, 0xf3, + 0x2a, 0xdf, 0xd3, 0x38, 0x1f, 0x32, 0xdd, 0xd9, 0x0d, 0xa3, 0xb5, 0x79, 0x6e, 0x29, 0xd8, 0xbe, 0x1f, 0x78, 0xf5, + 0x04, 0xd9, 0xda, 0x3c, 0xd8, 0x54, 0x66, 0x0d, 0x59, 0xf9, 0x3a, 0x41, 0xd5, 0x5e, 0xbd, 0xaa, 0x14, 0xb6, 0x22, + 0x40, 0xa5, 0xe0, 0xa3, 0xad, 0xfc, 0x27, 0xda, 0xe6, 0xdb, 0x73, 0xa8, 0x0c, 0x0f, 0xe4, 0xc9, 0x50, 0xd5, 0x03, + 0x2e, 0xca, 0x0f, 0x01, 0x2c, 0x7e, 0x64, 0x22, 0xd7, 0xee, 0xba, 0x40, 0xe6, 0x4c, 0xc5, 0x12, 0x2f, 0xfb, 0x74, + 0x90, 0x5a, 0x79, 0x28, 0x95, 0x60, 0xdb, 0x73, 0x53, 0x70, 0xed, 0x43, 0xe4, 0xe2, 0x3e, 0x1b, 0xa4, 0xcb, 0x7a, + 0x18, 0x5d, 0x1b, 0xc8, 0xd7, 0x9b, 0x73, 0x9a, 0xb8, 0xb3, 0x74, 0x80, 0x73, 0x02, 0xb6, 0xc7, 0x9e, 0x3d, 0x7d, + 0x13, 0x67, 0xa8, 0x57, 0xe7, 0xf0, 0x97, 0x6b, 0x9c, 0xe3, 0x0c, 0xa5, 0x0f, 0x63, 0xb8, 0xc0, 0x5a, 0x63, 0x00, + 0x5f, 0x66, 0x49, 0x15, 0x78, 0xa4, 0x66, 0x46, 0x62, 0x75, 0x17, 0x81, 0x68, 0xa9, 0xc3, 0xdb, 0x71, 0xe6, 0x03, + 0x51, 0x1b, 0xee, 0xf5, 0x99, 0x11, 0x0e, 0x27, 0x59, 0x5c, 0x3b, 0x67, 0x38, 0xb9, 0xdc, 0xe7, 0xb5, 0x13, 0x13, + 0xac, 0xbd, 0xc3, 0x53, 0x05, 0xf4, 0x68, 0x70, 0xaa, 0x58, 0x1a, 0x02, 0x31, 0x13, 0xc0, 0x9b, 0x39, 0x3c, 0xda, + 0x02, 0x9c, 0x8f, 0xd6, 0x38, 0xf8, 0x4a, 0x6b, 0x5d, 0x6d, 0x2a, 0x51, 0xd6, 0x6b, 0xdc, 0x9f, 0x66, 0x78, 0x94, + 0xe1, 0x79, 0x36, 0x08, 0x8e, 0x9b, 0x59, 0x16, 0x9a, 0x74, 0xad, 0x56, 0x4f, 0x9d, 0x19, 0x21, 0xb2, 0x3f, 0x2d, + 0xfd, 0x41, 0x3d, 0x40, 0xf8, 0x14, 0xb2, 0x80, 0x96, 0xf4, 0xdc, 0xdf, 0x86, 0x7d, 0xa7, 0x1a, 0x35, 0x62, 0x9e, + 0x58, 0x32, 0xd2, 0xf3, 0x3f, 0xca, 0x2c, 0xdb, 0x5a, 0x23, 0x9a, 0xdf, 0xee, 0x45, 0x0d, 0xdf, 0x5e, 0xa0, 0x65, + 0x2b, 0xcd, 0x76, 0x00, 0x51, 0xac, 0x71, 0x92, 0x0e, 0xd6, 0x48, 0xae, 0x56, 0xb1, 0x4d, 0x21, 0x3c, 0x99, 0x31, + 0xaa, 0x16, 0x85, 0x79, 0xba, 0x2d, 0x56, 0x28, 0x31, 0xfc, 0x2e, 0x76, 0x36, 0xa2, 0xf0, 0x52, 0x9a, 0x04, 0xc3, + 0x8d, 0x58, 0x10, 0x59, 0x13, 0xb9, 0x87, 0x59, 0x65, 0x19, 0x24, 0x88, 0x30, 0x22, 0xbf, 0xbd, 0x2e, 0x15, 0xf6, + 0x71, 0x38, 0xfb, 0xc7, 0xf8, 0x02, 0xc2, 0xcd, 0xdb, 0x84, 0x16, 0x43, 0x3a, 0x01, 0x36, 0x16, 0xe2, 0x10, 0x6e, + 0x25, 0xac, 0x56, 0xfd, 0x41, 0x57, 0x18, 0xf2, 0xec, 0x9e, 0xae, 0x2b, 0x1b, 0xda, 0xdd, 0x00, 0x5c, 0x75, 0x5b, + 0x6a, 0xae, 0x8d, 0xee, 0x87, 0x9a, 0xd7, 0xb5, 0xb8, 0x4b, 0x72, 0x0f, 0x64, 0x54, 0x6f, 0x60, 0xd7, 0x2c, 0xc0, + 0x4d, 0xe8, 0x2a, 0x3c, 0xc2, 0x0b, 0x6b, 0xc3, 0x69, 0x9e, 0x52, 0xa2, 0xe6, 0x05, 0x25, 0x78, 0xb8, 0x99, 0xb0, + 0x7e, 0x36, 0xc0, 0x23, 0x1f, 0x68, 0x7b, 0xff, 0x6d, 0x3c, 0x42, 0xa8, 0x20, 0x06, 0xa6, 0xd6, 0x65, 0x7b, 0x54, + 0xd9, 0xed, 0x9b, 0x4c, 0xc3, 0x30, 0x18, 0x23, 0xe6, 0x51, 0x68, 0xc4, 0x9c, 0x37, 0x1a, 0x68, 0x41, 0x46, 0x60, + 0xc4, 0xbc, 0x08, 0x5a, 0x5b, 0xd8, 0x67, 0x36, 0x83, 0xf6, 0x16, 0x08, 0x75, 0x39, 0xd0, 0x34, 0x0d, 0x0f, 0x6a, + 0x54, 0x0f, 0x9a, 0xfb, 0xe7, 0x9d, 0x8e, 0x3a, 0xa0, 0x48, 0x18, 0x5f, 0xfa, 0x49, 0x58, 0xd7, 0x70, 0x3b, 0xee, + 0xb1, 0x19, 0xb7, 0xb3, 0x6d, 0x50, 0x7d, 0xd9, 0xcf, 0x06, 0x83, 0xae, 0xf4, 0x56, 0x12, 0x2d, 0x3c, 0xae, 0x9e, + 0xe0, 0xa8, 0x16, 0xef, 0x8b, 0xde, 0xbc, 0xf2, 0xe6, 0xfe, 0x65, 0xcf, 0xcd, 0xf3, 0x18, 0x38, 0xa0, 0x7d, 0xb8, + 0x1f, 0xaa, 0xe2, 0x83, 0x1d, 0x75, 0x20, 0x0a, 0x5a, 0xda, 0xaa, 0x09, 0xa4, 0xd6, 0xcc, 0x2e, 0xd6, 0x4d, 0x85, + 0x0e, 0x05, 0x84, 0x21, 0x53, 0x55, 0x77, 0x77, 0x2a, 0x50, 0x0d, 0x71, 0x38, 0xf5, 0x1f, 0x5b, 0x23, 0xd6, 0x38, + 0xea, 0x8c, 0x22, 0x63, 0x24, 0x69, 0x97, 0x0f, 0x5e, 0xdd, 0x01, 0x2b, 0x01, 0x1f, 0xfd, 0xd8, 0x24, 0x19, 0x43, + 0x82, 0xb7, 0x2c, 0xd3, 0x86, 0x0f, 0xe1, 0x0e, 0x41, 0x79, 0x62, 0x63, 0x6d, 0xba, 0x4a, 0x16, 0x72, 0x55, 0x97, + 0xd7, 0x01, 0x7a, 0xde, 0x95, 0xbf, 0xb1, 0xe1, 0xc8, 0x82, 0x81, 0x65, 0x5b, 0xfb, 0x04, 0x3c, 0xf2, 0x71, 0x85, + 0x20, 0x7e, 0x29, 0x74, 0x62, 0x22, 0x45, 0x5f, 0xc1, 0x06, 0xc5, 0x73, 0x70, 0x10, 0x74, 0x12, 0x1c, 0x06, 0xef, + 0x32, 0xab, 0x49, 0x36, 0xb8, 0x35, 0x23, 0xf1, 0x7c, 0xb5, 0x6a, 0xa1, 0xc3, 0x7f, 0xcc, 0x63, 0xc8, 0xe3, 0x52, + 0xe1, 0x3e, 0xae, 0x14, 0xee, 0x60, 0x09, 0x48, 0xc6, 0x81, 0xae, 0x1d, 0xcb, 0x50, 0x8d, 0x0e, 0x71, 0xba, 0x5f, + 0x40, 0xd4, 0x66, 0x77, 0x2c, 0x81, 0x9e, 0x7d, 0xab, 0x80, 0xd5, 0xb5, 0x97, 0x25, 0x90, 0x11, 0xdc, 0xfd, 0x26, + 0x30, 0x2a, 0x44, 0xe3, 0xf3, 0x67, 0xde, 0x53, 0xe0, 0x89, 0xf3, 0xe7, 0x9a, 0x19, 0xd6, 0xbd, 0xa0, 0x37, 0xa6, + 0xf9, 0x78, 0x8c, 0x9b, 0x63, 0x0b, 0xce, 0xa3, 0x0e, 0xfc, 0xb4, 0x10, 0x3d, 0xea, 0x60, 0x97, 0x8a, 0xc7, 0x25, + 0x90, 0x43, 0xf4, 0x74, 0x06, 0x52, 0xc0, 0x4a, 0xc7, 0x56, 0x8b, 0x34, 0x41, 0xab, 0xd5, 0xe4, 0x82, 0xb4, 0x10, + 0x5a, 0xaa, 0x1b, 0xae, 0xb3, 0x29, 0xf8, 0x48, 0x83, 0x62, 0xe0, 0x0d, 0xd5, 0xd3, 0x18, 0xe1, 0x31, 0x5a, 0x8e, + 0xd8, 0x98, 0x2e, 0x72, 0x9d, 0xaa, 0x1e, 0x4f, 0x6c, 0x28, 0x5b, 0x66, 0x23, 0xc1, 0x1d, 0x75, 0xf0, 0xc4, 0xf0, + 0x97, 0x8f, 0x8c, 0x39, 0x48, 0x91, 0x99, 0xe4, 0x89, 0x49, 0xc0, 0x3c, 0xc9, 0x72, 0xa9, 0x98, 0x6d, 0xa6, 0x6b, + 0x6d, 0xcb, 0x21, 0x18, 0x76, 0xa4, 0x0b, 0x6e, 0xac, 0x28, 0xa3, 0x74, 0x4a, 0x54, 0x4f, 0x1d, 0x75, 0xd2, 0x09, + 0xe6, 0x09, 0x70, 0x7a, 0xef, 0x64, 0xcc, 0x1a, 0xe5, 0xad, 0xe8, 0x0c, 0x1d, 0x4e, 0xb1, 0xa8, 0x2e, 0x51, 0x67, + 0xe8, 0x70, 0x82, 0xf0, 0xac, 0x41, 0x72, 0x05, 0x1e, 0xc3, 0x5c, 0xfc, 0x1f, 0x29, 0xff, 0xcd, 0x61, 0x43, 0xd0, + 0xe5, 0xb7, 0xb0, 0x53, 0xd8, 0x28, 0x4a, 0x73, 0x02, 0x5e, 0x8b, 0xed, 0x33, 0x9c, 0x91, 0x49, 0x33, 0xf7, 0x01, + 0xf7, 0x4c, 0x2b, 0x8d, 0x5b, 0x8d, 0x0e, 0x33, 0x3c, 0xda, 0x4c, 0x8a, 0xcd, 0x5c, 0x9b, 0x79, 0x9a, 0xc1, 0xf9, + 0x5e, 0x8d, 0xc2, 0x95, 0x5f, 0x6c, 0x26, 0x85, 0xe5, 0x1d, 0x70, 0x9b, 0x23, 0x2c, 0x9a, 0x14, 0xe7, 0x78, 0xd6, + 0xfc, 0x8a, 0x67, 0xcd, 0x0f, 0x65, 0x46, 0x63, 0x81, 0x05, 0x04, 0xef, 0x83, 0x44, 0x3c, 0xab, 0x92, 0x47, 0x58, + 0x34, 0x4c, 0x79, 0x3c, 0x6b, 0x54, 0xa5, 0x9b, 0x0b, 0x2c, 0x1a, 0xa6, 0x74, 0xe3, 0x03, 0x9e, 0x35, 0xbe, 0xfe, + 0x8b, 0x49, 0x47, 0x29, 0xa0, 0xcb, 0x1c, 0x2d, 0x33, 0x3b, 0xc4, 0xab, 0xdf, 0xde, 0xbe, 0x6b, 0x5f, 0x77, 0x0e, + 0x27, 0xd8, 0xaf, 0x5f, 0x66, 0x70, 0x2c, 0xd3, 0x31, 0x6b, 0x02, 0x44, 0x33, 0xdc, 0x39, 0x9c, 0xe2, 0xce, 0x61, + 0xe6, 0x9a, 0x5a, 0xcf, 0x1a, 0xe4, 0x56, 0x87, 0x50, 0xd4, 0x51, 0x1a, 0xc2, 0xc7, 0x4f, 0x36, 0x9d, 0xa0, 0x1a, + 0x28, 0xd1, 0xe1, 0xa4, 0x06, 0x2a, 0xf8, 0x5e, 0xd4, 0xbe, 0xab, 0x7a, 0x15, 0x06, 0x59, 0x28, 0xa1, 0x70, 0xcd, + 0x0d, 0x78, 0x6a, 0x29, 0x06, 0x32, 0x61, 0x8a, 0x05, 0xca, 0x77, 0x40, 0x61, 0x94, 0x27, 0x66, 0xe8, 0xc1, 0x74, + 0x4c, 0xe2, 0xff, 0xcf, 0x93, 0x29, 0x87, 0x5e, 0x6e, 0x99, 0xad, 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, + 0x3f, 0xac, 0xa0, 0xfb, 0x62, 0xab, 0xfb, 0xc2, 0x74, 0x1f, 0x36, 0x6d, 0x54, 0x39, 0x69, 0x55, 0xc9, 0x92, 0xff, + 0x3a, 0xdd, 0xda, 0x02, 0x8d, 0xa8, 0xd1, 0xb3, 0x49, 0xd8, 0xe0, 0x7e, 0x3b, 0xdd, 0x81, 0xcc, 0x6b, 0x6e, 0xdf, + 0xe6, 0x84, 0xc3, 0x37, 0xb8, 0x53, 0xbd, 0x6c, 0x81, 0xf7, 0xa6, 0x32, 0xfa, 0xca, 0x38, 0xb4, 0x1c, 0x2c, 0x36, + 0x4d, 0xb9, 0x8d, 0xb1, 0x74, 0x72, 0x8a, 0x8d, 0x2b, 0x22, 0x54, 0xba, 0xbd, 0x04, 0xa5, 0xf8, 0x58, 0x37, 0x99, + 0xf9, 0xba, 0xd0, 0x89, 0xb9, 0x84, 0x6a, 0x98, 0xcf, 0xbb, 0x4b, 0x9d, 0x68, 0x39, 0xb7, 0x79, 0x77, 0x17, 0xd0, + 0x27, 0x68, 0x58, 0x1b, 0x81, 0xdd, 0x3e, 0x2b, 0x9c, 0x7e, 0xa7, 0x3a, 0x04, 0xc3, 0x03, 0xc8, 0x91, 0x16, 0xdb, + 0x07, 0x36, 0xad, 0x61, 0xd7, 0x45, 0xb3, 0x4c, 0xb4, 0xad, 0x36, 0x4d, 0xae, 0xdd, 0xc3, 0x7c, 0x1e, 0xf2, 0x14, + 0xbc, 0xb0, 0xfa, 0xf1, 0x1d, 0xec, 0xc6, 0x6d, 0x8d, 0x91, 0xa8, 0x2b, 0x99, 0x4a, 0xe8, 0x27, 0xb7, 0x98, 0x25, + 0x77, 0xc6, 0x8b, 0x51, 0x19, 0x7f, 0x1f, 0x13, 0xa9, 0x3e, 0xaa, 0x24, 0x39, 0xb0, 0xec, 0x6f, 0xb0, 0xe4, 0x16, + 0xcc, 0x13, 0xcb, 0x6a, 0x12, 0xeb, 0xe4, 0x2e, 0x58, 0x44, 0x69, 0x1a, 0x59, 0x1b, 0x06, 0xd4, 0x34, 0x63, 0xd5, + 0x83, 0xfb, 0x10, 0xe8, 0xa1, 0x57, 0x96, 0xd2, 0xae, 0xb3, 0xb4, 0xd6, 0xbd, 0x36, 0xdd, 0x6f, 0x0e, 0x28, 0xe0, + 0x0b, 0x03, 0xae, 0xe9, 0x5f, 0x4d, 0x22, 0x19, 0xb2, 0xaf, 0x9c, 0x15, 0x8f, 0x17, 0x85, 0xc1, 0x34, 0xd1, 0xd3, + 0x49, 0x36, 0x6f, 0x83, 0xa9, 0x5e, 0x36, 0xef, 0xdc, 0x62, 0xf7, 0x7d, 0x67, 0xbf, 0xef, 0xb0, 0xe8, 0x31, 0x93, + 0x91, 0x32, 0x53, 0xcc, 0x7f, 0xdf, 0xd9, 0xef, 0x3b, 0xbc, 0x3d, 0x98, 0x1b, 0x7f, 0xa1, 0x58, 0xb2, 0x33, 0x5c, + 0x82, 0x09, 0x79, 0xc0, 0xdd, 0xd4, 0xb2, 0x4c, 0x10, 0xd8, 0x5a, 0x02, 0xc4, 0xf9, 0x7c, 0x1a, 0x57, 0xbc, 0x1a, + 0x02, 0xee, 0xd3, 0xbb, 0xb6, 0x57, 0xa9, 0xc0, 0x63, 0x82, 0x46, 0xc4, 0xc4, 0xb6, 0x31, 0xef, 0x6a, 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, 0x79, 0x13, 0x79, 0xec, 0x0b, 0xb3, 0x9f, + 0x99, 0x9e, 0x16, 0x72, 0x31, 0x99, 0x82, 0x0f, 0x2d, 0xb0, 0x0c, 0x85, 0xa9, 0x57, 0xd9, 0xfa, 0xd7, 0x24, 0x37, + 0x01, 0x14, 0x4e, 0x37, 0x65, 0x42, 0x33, 0xbd, 0xa0, 0xb9, 0xb1, 0x24, 0xe5, 0x62, 0xf2, 0x48, 0xde, 0xbe, 0x04, + 0xec, 0xa6, 0x44, 0x37, 0x76, 0xe4, 0xbd, 0x85, 0x1d, 0x80, 0x33, 0xc2, 0x76, 0x55, 0x7c, 0xa8, 0x40, 0xe7, 0x8f, + 0x73, 0xc2, 0x76, 0x55, 0x7d, 0xc2, 0x6c, 0xf6, 0x94, 0x6c, 0x0c, 0xb7, 0x17, 0x67, 0x8d, 0x1c, 0x1d, 0x75, 0xd2, + 0xbc, 0xeb, 0x89, 0x81, 0x05, 0x68, 0x00, 0xdc, 0xad, 0xed, 0x59, 0xde, 0xdd, 0x10, 0xd0, 0xbb, 0x64, 0xd2, 0x5e, + 0x97, 0x9b, 0x94, 0xd5, 0xaa, 0x53, 0x51, 0xc1, 0x02, 0x4f, 0x83, 0xbd, 0x40, 0xed, 0xd7, 0x0e, 0x8a, 0x73, 0x95, + 0x6d, 0x9a, 0x9e, 0x97, 0x7d, 0x77, 0x77, 0x2c, 0x32, 0xb6, 0x69, 0x6f, 0x77, 0x10, 0x09, 0xcb, 0x09, 0xeb, 0x80, + 0x13, 0xae, 0x6a, 0x07, 0x04, 0xe8, 0x3a, 0x10, 0xb9, 0xb1, 0x24, 0xcb, 0x75, 0x65, 0x74, 0x1f, 0xf8, 0xdd, 0x52, + 0x22, 0xdd, 0x68, 0x4b, 0x82, 0xe9, 0x13, 0x8c, 0x9a, 0xce, 0x3c, 0x8a, 0x5c, 0x7b, 0xef, 0x77, 0x53, 0xb4, 0xf5, + 0xaf, 0x0f, 0x63, 0xb3, 0x3d, 0x4c, 0x0c, 0x65, 0x10, 0x03, 0xbd, 0x8f, 0x78, 0xb7, 0xd1, 0xc8, 0x10, 0x28, 0x64, + 0xb2, 0x01, 0x96, 0x89, 0xd7, 0xa2, 0x1f, 0x1c, 0x18, 0x78, 0x54, 0x09, 0x08, 0x53, 0x10, 0x42, 0xc2, 0xae, 0x0d, + 0xc2, 0x86, 0xcb, 0x55, 0xcb, 0x85, 0x8d, 0x54, 0x1b, 0x3a, 0xf8, 0x7f, 0x85, 0xcb, 0x56, 0xcf, 0x2c, 0x17, 0xc5, + 0xe0, 0x66, 0x6e, 0xc0, 0x22, 0x41, 0x7a, 0xb4, 0xd9, 0x1e, 0x8a, 0xbb, 0x73, 0xb1, 0xd9, 0x10, 0x90, 0x98, 0xc3, + 0x04, 0x45, 0xc3, 0xb9, 0x31, 0xc6, 0x2a, 0xa9, 0xb4, 0xac, 0x35, 0x89, 0x39, 0xf0, 0xa5, 0x0b, 0xd7, 0x7d, 0x79, + 0x9b, 0x32, 0x7c, 0x97, 0x0a, 0x7c, 0x03, 0x9e, 0x34, 0xa9, 0xc4, 0xee, 0xf1, 0x82, 0x62, 0x4d, 0x74, 0xd7, 0xb3, + 0xb7, 0x05, 0xac, 0xb3, 0xd9, 0x23, 0x22, 0xf8, 0x5d, 0xfd, 0x6a, 0x83, 0xef, 0x16, 0xfe, 0x0a, 0xd6, 0xcf, 0xc1, + 0x49, 0x8a, 0x45, 0x43, 0x36, 0x0b, 0x77, 0x64, 0x40, 0xb9, 0x8a, 0x5f, 0x0e, 0x53, 0xb7, 0x8a, 0xe1, 0xda, 0xc7, + 0x57, 0xfc, 0x61, 0xa3, 0xdd, 0x86, 0x2a, 0x8b, 0xdb, 0xbd, 0x29, 0x1a, 0xb2, 0x6a, 0x7a, 0x47, 0xe6, 0x46, 0x4a, + 0xfd, 0xeb, 0x03, 0x6e, 0x6d, 0xb5, 0xef, 0xa7, 0xf9, 0xd6, 0xa3, 0x73, 0xd5, 0xb4, 0x4f, 0xad, 0x15, 0xc1, 0xc1, + 0xcf, 0x16, 0x6e, 0x6e, 0x0d, 0x38, 0x80, 0x9f, 0xbf, 0xa3, 0x79, 0x9c, 0x41, 0x74, 0x7a, 0xab, 0x19, 0x5f, 0xc5, + 0x7f, 0x8e, 0x1a, 0x71, 0x2f, 0xfd, 0x33, 0xf9, 0x73, 0xd4, 0x40, 0x3d, 0x14, 0xcf, 0x6f, 0x57, 0x6c, 0xb6, 0x82, + 0x60, 0x6b, 0xf7, 0x8e, 0xf0, 0xeb, 0xb0, 0x24, 0xd7, 0x34, 0xe7, 0xd9, 0xca, 0x3d, 0x45, 0xb7, 0x72, 0xef, 0xf4, + 0xac, 0xcc, 0xeb, 0x4a, 0xab, 0x58, 0x0e, 0x73, 0x08, 0x2c, 0x1c, 0xef, 0x35, 0x7b, 0xfd, 0x56, 0xf3, 0xc1, 0xc0, + 0xfe, 0x6b, 0x22, 0xdc, 0xa3, 0x5a, 0xc4, 0xb6, 0x37, 0x1b, 0x5b, 0x3f, 0x06, 0xc3, 0x0e, 0x08, 0x05, 0x0e, 0x72, + 0xe9, 0xe3, 0x0c, 0x59, 0xdf, 0x93, 0xd5, 0x8a, 0xb9, 0x68, 0xd6, 0x4e, 0x83, 0x5f, 0xc6, 0x66, 0x3a, 0x6c, 0x27, + 0x9d, 0xae, 0x17, 0x63, 0x49, 0x03, 0x22, 0x4d, 0x63, 0x06, 0x81, 0xa4, 0x96, 0x86, 0xc3, 0x9a, 0xdf, 0x46, 0x69, + 0x75, 0x7f, 0x04, 0x29, 0x3f, 0x44, 0x29, 0x3f, 0x22, 0x10, 0x40, 0xdb, 0x32, 0x47, 0x65, 0x43, 0xde, 0x77, 0xe9, + 0x9e, 0x71, 0x66, 0x68, 0xf0, 0xd5, 0xaa, 0x55, 0x0d, 0x53, 0x14, 0xf5, 0x61, 0x2e, 0xd7, 0x58, 0x90, 0x37, 0xa0, + 0x6b, 0x56, 0x44, 0xf4, 0x42, 0x57, 0x79, 0x78, 0x89, 0x17, 0x4b, 0x02, 0x4e, 0xfa, 0x3d, 0xd1, 0x2b, 0xc8, 0xe5, + 0xc3, 0x18, 0x7c, 0xcc, 0x30, 0xef, 0xeb, 0x7e, 0x31, 0x18, 0xa0, 0xd4, 0x39, 0x9d, 0xa5, 0x26, 0xe2, 0x4a, 0xe0, + 0x97, 0x5c, 0x80, 0x5f, 0xb2, 0x42, 0xac, 0x5f, 0x0c, 0xc8, 0xbd, 0x2c, 0x96, 0xe0, 0x94, 0xbf, 0xc3, 0xe7, 0xf1, + 0x61, 0x68, 0x60, 0x6a, 0x86, 0x65, 0x2e, 0xb2, 0xc1, 0x62, 0xce, 0x5a, 0x02, 0xc1, 0xcd, 0x80, 0xbb, 0xd4, 0x86, + 0x44, 0x63, 0x0d, 0x14, 0xdd, 0x46, 0xa1, 0x99, 0xd1, 0xd3, 0xad, 0x36, 0xfa, 0x91, 0xc3, 0x0b, 0x73, 0x0d, 0x63, + 0x11, 0xc8, 0x5c, 0xae, 0x7a, 0xec, 0x2f, 0x3f, 0x6c, 0x56, 0x18, 0xbc, 0xc2, 0x98, 0xec, 0x94, 0x56, 0x89, 0x66, + 0x7c, 0x95, 0x27, 0x8e, 0x21, 0xc8, 0xc4, 0x52, 0xe9, 0x86, 0x63, 0xe2, 0x4a, 0xfa, 0x4c, 0x0c, 0xd9, 0x6e, 0x78, + 0x66, 0x2e, 0x74, 0xb3, 0xfd, 0xc3, 0xb9, 0x9d, 0x73, 0xc2, 0x8d, 0x56, 0xd2, 0x68, 0xa3, 0x9e, 0x19, 0xaa, 0xea, + 0x82, 0xf9, 0x3d, 0x74, 0x5a, 0x5a, 0xec, 0x5c, 0xbd, 0xbb, 0xe1, 0xbb, 0x70, 0x65, 0xfc, 0x2d, 0x56, 0x85, 0x56, + 0x64, 0xb8, 0xdd, 0x42, 0xde, 0x9c, 0xe9, 0xa1, 0x57, 0xe4, 0x42, 0x75, 0xf8, 0x8b, 0xba, 0xc2, 0x3c, 0x15, 0x19, + 0x35, 0x84, 0x47, 0xbf, 0xd7, 0x19, 0x28, 0xff, 0x60, 0x62, 0x32, 0x67, 0xc9, 0x0d, 0x2d, 0x44, 0xfc, 0xe3, 0x0b, + 0x61, 0x62, 0x55, 0xed, 0xc1, 0x40, 0xf6, 0x4c, 0xc5, 0x3d, 0xb8, 0x35, 0xe1, 0x63, 0xce, 0x46, 0xe9, 0x5e, 0xf4, + 0x63, 0x43, 0x34, 0x7e, 0x8c, 0x7e, 0x04, 0x77, 0x67, 0xf7, 0x2e, 0x61, 0x19, 0x17, 0xc2, 0xdf, 0x63, 0x3d, 0x2c, + 0x55, 0xca, 0x58, 0x7b, 0xdd, 0x72, 0x78, 0x21, 0xf5, 0x26, 0x8b, 0x1f, 0x3a, 0x62, 0x6d, 0x53, 0xb0, 0x0e, 0x29, + 0x29, 0x3c, 0xbb, 0x62, 0x6e, 0xb5, 0x98, 0xbb, 0xd4, 0x12, 0xfe, 0xfa, 0xea, 0x61, 0xa9, 0x82, 0x86, 0x83, 0xd0, + 0x95, 0xb6, 0x90, 0x00, 0x03, 0x97, 0xd2, 0xa7, 0xd3, 0x9d, 0x49, 0x64, 0x96, 0xc5, 0xf0, 0xee, 0x41, 0x05, 0xf3, + 0xdf, 0xd9, 0x46, 0x58, 0x15, 0xb8, 0x5c, 0xa9, 0xa2, 0x5e, 0x4a, 0x02, 0x01, 0xe8, 0x4b, 0xef, 0x41, 0x79, 0x51, + 0x74, 0x1b, 0x0d, 0x09, 0x5a, 0x58, 0x6a, 0xae, 0x55, 0x31, 0xdd, 0x0f, 0xdf, 0xd3, 0x0b, 0x3e, 0xbc, 0x43, 0xda, + 0xc6, 0xa3, 0x96, 0x94, 0x50, 0xbb, 0x83, 0xf6, 0xc1, 0x2a, 0x3b, 0x28, 0xff, 0x36, 0xa6, 0xc8, 0xe6, 0xf7, 0xd9, + 0x0f, 0xd4, 0x75, 0x38, 0x70, 0x05, 0xab, 0x5e, 0xca, 0x28, 0x18, 0xc2, 0x3e, 0x60, 0x1f, 0x8b, 0x24, 0xa3, 0xd9, + 0x94, 0x81, 0xba, 0xdf, 0x16, 0xad, 0xe6, 0xf6, 0xa4, 0xee, 0x37, 0x64, 0x9c, 0x7d, 0x84, 0x71, 0xf6, 0x51, 0xe0, + 0xc5, 0x22, 0xc9, 0x1f, 0x32, 0xd6, 0x38, 0x56, 0x4d, 0x81, 0x8e, 0x3a, 0xc0, 0x9d, 0x81, 0x03, 0x0f, 0xd8, 0xa2, + 0x1c, 0x1c, 0x50, 0x67, 0x71, 0x4f, 0x1b, 0x99, 0xf7, 0xf6, 0x84, 0xda, 0x45, 0x2c, 0x70, 0xb3, 0x66, 0xa6, 0x05, + 0xad, 0x15, 0xc6, 0x79, 0x3c, 0xe0, 0x6d, 0x9e, 0xd5, 0xe2, 0x27, 0x6c, 0x58, 0x53, 0xd5, 0x6f, 0xa0, 0x39, 0xaa, + 0x05, 0xb9, 0x79, 0x62, 0xbc, 0x55, 0x49, 0x3f, 0x8a, 0x06, 0x96, 0x53, 0x21, 0x86, 0x64, 0xf4, 0x5b, 0x83, 0xe0, + 0x56, 0x7b, 0xb5, 0xe2, 0x1e, 0xf1, 0x45, 0xcd, 0x5b, 0xcd, 0xdc, 0x02, 0xd0, 0x22, 0x8e, 0xca, 0x7b, 0x93, 0x08, + 0xbc, 0x6f, 0xcb, 0x08, 0x69, 0xcb, 0xbe, 0x7d, 0x34, 0xb1, 0x54, 0x6c, 0xbe, 0xa3, 0x93, 0x41, 0x1a, 0xd9, 0x11, + 0x45, 0xf8, 0xba, 0x84, 0x24, 0x5c, 0x25, 0x5d, 0xab, 0x4c, 0xce, 0x99, 0x4a, 0x39, 0xbe, 0x2e, 0xa4, 0xd4, 0x57, + 0xf6, 0x4b, 0xe2, 0xea, 0x4e, 0x46, 0xe0, 0xeb, 0x09, 0xd3, 0xef, 0x68, 0x31, 0x61, 0xe0, 0x57, 0xe4, 0x6f, 0xc7, + 0x52, 0x4a, 0x2e, 0x9f, 0x88, 0xb8, 0x4f, 0x31, 0xbc, 0xf8, 0x39, 0xc0, 0xda, 0x84, 0x40, 0x29, 0x71, 0x11, 0x2e, + 0x88, 0xde, 0x14, 0xf2, 0xf6, 0x2e, 0x2e, 0xb0, 0x73, 0x00, 0x2c, 0x9d, 0x26, 0x01, 0xfe, 0xe5, 0x63, 0x3e, 0x56, + 0x63, 0x4e, 0x8d, 0xae, 0xdf, 0xfd, 0x4e, 0xae, 0x81, 0xde, 0x96, 0x8e, 0x82, 0xfd, 0xd6, 0x00, 0x72, 0xe1, 0x2e, + 0x0c, 0x2e, 0xbe, 0xc2, 0xda, 0xb2, 0x30, 0xde, 0x58, 0x00, 0xbd, 0xbf, 0x33, 0xb0, 0x60, 0xc3, 0x1c, 0x53, 0x78, + 0x2e, 0x75, 0xc2, 0x74, 0x10, 0x15, 0xe4, 0x49, 0xf9, 0x20, 0x66, 0xad, 0xf6, 0x5b, 0x36, 0x86, 0x3b, 0x8c, 0xe4, + 0xdb, 0x85, 0x13, 0x07, 0x1e, 0x90, 0x69, 0x32, 0xdb, 0xec, 0x1b, 0x1f, 0x79, 0xe4, 0xf5, 0x38, 0xde, 0xd5, 0x52, + 0x98, 0x6f, 0x56, 0x74, 0x8d, 0x21, 0x14, 0x45, 0xd8, 0xef, 0x17, 0x15, 0x53, 0x54, 0x19, 0xb4, 0x41, 0xc3, 0xf2, + 0x46, 0xfc, 0x02, 0x67, 0x0c, 0xad, 0x17, 0xb2, 0x77, 0x74, 0xd6, 0xe1, 0xcc, 0x61, 0xc6, 0x94, 0xc0, 0xa8, 0xb4, + 0x2c, 0xe8, 0x04, 0x1c, 0x9d, 0xab, 0x0f, 0xa2, 0xe2, 0xea, 0x58, 0x01, 0x78, 0x92, 0x29, 0xfc, 0x93, 0x6f, 0x82, + 0x75, 0xbf, 0x55, 0x33, 0x4c, 0xfd, 0x45, 0x6f, 0xbb, 0x96, 0x2f, 0x43, 0x1c, 0x69, 0x63, 0x08, 0xad, 0x73, 0x7b, + 0x07, 0x28, 0xe2, 0x82, 0x5e, 0xa4, 0x1a, 0x5f, 0xab, 0xc5, 0xd0, 0xac, 0xaf, 0x71, 0x1d, 0xd3, 0x06, 0x51, 0xac, + 0xbb, 0x26, 0xbe, 0xae, 0xde, 0x1f, 0x55, 0xa9, 0x82, 0x33, 0x48, 0x20, 0xac, 0xca, 0xcb, 0x86, 0x54, 0x92, 0x4b, + 0xd3, 0xa9, 0x34, 0x9d, 0x56, 0x08, 0xe5, 0xd2, 0x93, 0xf2, 0xfe, 0x15, 0x42, 0x18, 0x98, 0x32, 0x3b, 0xb0, 0x4a, + 0x6d, 0x61, 0x15, 0xbc, 0x7a, 0xb1, 0x81, 0x55, 0x12, 0x8e, 0xe7, 0x12, 0x8d, 0x8a, 0x0a, 0x87, 0x0c, 0xe9, 0x0b, + 0xb1, 0x08, 0x12, 0x00, 0x8b, 0xde, 0x65, 0x2e, 0xef, 0x7b, 0x38, 0x14, 0xf6, 0x24, 0x93, 0x70, 0xba, 0x09, 0xcd, + 0xe1, 0x61, 0x5a, 0xd5, 0xf3, 0x08, 0x01, 0x4b, 0xcf, 0x31, 0x3c, 0x48, 0xfc, 0xfd, 0x87, 0x50, 0x9d, 0x05, 0x79, + 0xfa, 0x2f, 0x51, 0x12, 0x1a, 0xfb, 0xcf, 0xf1, 0xd0, 0x21, 0x61, 0x38, 0xf0, 0xcd, 0x11, 0x56, 0x38, 0xb8, 0x55, + 0xc4, 0x67, 0x70, 0x87, 0x8f, 0x75, 0xe8, 0x01, 0x60, 0x09, 0xc5, 0x21, 0xc8, 0x37, 0x50, 0xcc, 0xe0, 0x80, 0x26, + 0xcb, 0xf0, 0x02, 0x17, 0xac, 0x16, 0xca, 0xfb, 0xdb, 0x96, 0x97, 0xd2, 0x6a, 0x97, 0xbc, 0xc6, 0x1c, 0xa8, 0xfc, + 0x0c, 0x2f, 0x7c, 0x85, 0x79, 0x29, 0xd9, 0x7d, 0xe1, 0x6b, 0x07, 0xf4, 0x14, 0x02, 0x46, 0xba, 0xdf, 0x6b, 0xc2, + 0x3d, 0x45, 0x2f, 0x73, 0x71, 0xd8, 0x76, 0xd0, 0xbd, 0xc0, 0x5c, 0x5d, 0x55, 0x59, 0x73, 0x30, 0x85, 0x06, 0x07, + 0x55, 0x38, 0x23, 0x30, 0x57, 0x2f, 0xca, 0x82, 0x73, 0x10, 0xef, 0x7b, 0xc2, 0xe4, 0x94, 0xd1, 0x00, 0x5e, 0x64, + 0xe5, 0xa3, 0x53, 0x3d, 0x0e, 0x2e, 0xe3, 0x86, 0x4d, 0x7c, 0x21, 0x7c, 0x2a, 0xb0, 0x92, 0xd6, 0x38, 0x34, 0xa2, + 0x23, 0x3a, 0x07, 0xb3, 0x0d, 0xa0, 0xe0, 0xee, 0x7c, 0xd8, 0x58, 0xa8, 0xe0, 0x31, 0xd8, 0xda, 0xdb, 0xcd, 0x84, + 0x38, 0x93, 0xa6, 0xe0, 0x6e, 0xdb, 0x20, 0x83, 0x37, 0xbf, 0xfd, 0xb7, 0xc2, 0x22, 0xc1, 0x80, 0x4a, 0x4d, 0x12, + 0x84, 0x27, 0x28, 0x8d, 0x74, 0x2b, 0x37, 0x13, 0x48, 0x27, 0xa2, 0x66, 0xd4, 0xbd, 0x71, 0xbe, 0x3a, 0x6a, 0x20, + 0x2a, 0x6a, 0xa0, 0x02, 0x6a, 0x20, 0xeb, 0xdb, 0xbf, 0x80, 0x85, 0xb0, 0x11, 0xaa, 0x44, 0x10, 0x10, 0x61, 0xae, + 0x0d, 0x1f, 0x50, 0x24, 0x21, 0xe4, 0x0d, 0xa0, 0x62, 0x4a, 0x5e, 0x82, 0xd1, 0x38, 0xbc, 0xde, 0x03, 0xee, 0x97, + 0x96, 0x61, 0xf0, 0x9c, 0x82, 0xc9, 0x7f, 0xeb, 0xf3, 0xa1, 0x7a, 0xb9, 0x3a, 0x08, 0xe1, 0x17, 0x10, 0x2b, 0xc2, + 0xf1, 0x17, 0xbf, 0x00, 0xd9, 0x54, 0x58, 0x1e, 0x1c, 0x48, 0x10, 0xf8, 0x21, 0x8a, 0x70, 0xc0, 0x33, 0xbc, 0xcc, + 0x36, 0x88, 0x9e, 0x9f, 0x95, 0xaa, 0x66, 0x25, 0x83, 0x59, 0x15, 0x9e, 0xc6, 0xd1, 0x35, 0x61, 0x20, 0xb8, 0x50, + 0xbb, 0x6f, 0x10, 0x02, 0x65, 0xcb, 0x8d, 0xa1, 0x4b, 0x4f, 0xc1, 0x7c, 0x34, 0x8e, 0xde, 0x32, 0x78, 0xd2, 0xd6, + 0x98, 0xfc, 0x33, 0x6d, 0x1e, 0xb8, 0x4f, 0xf7, 0xa2, 0x46, 0xe0, 0xa4, 0x4e, 0x51, 0xf2, 0xb7, 0xe4, 0x22, 0x8e, + 0x9a, 0x97, 0x11, 0x6a, 0xc0, 0xbf, 0x0d, 0x8e, 0xba, 0x34, 0xa1, 0xa3, 0x91, 0x0f, 0x7e, 0x93, 0x11, 0xb3, 0xc9, + 0x56, 0x2b, 0x51, 0x11, 0xf4, 0xc4, 0x6e, 0x30, 0x60, 0x25, 0x5e, 0x00, 0xfb, 0x60, 0x39, 0x58, 0xf2, 0x4e, 0xc4, + 0xca, 0x9f, 0x52, 0x18, 0xac, 0x9e, 0x33, 0x84, 0x70, 0x16, 0xc4, 0x6c, 0xfc, 0xcf, 0x67, 0x1a, 0xae, 0x9f, 0x9f, + 0xaf, 0x63, 0x44, 0xa4, 0x0f, 0x22, 0x57, 0x63, 0x47, 0x44, 0x10, 0xb6, 0x4c, 0xf7, 0x5d, 0x99, 0x1f, 0xbc, 0x75, + 0xf5, 0xc0, 0x86, 0x8b, 0x03, 0x03, 0x6a, 0x14, 0x18, 0xad, 0xe0, 0x9c, 0x94, 0x03, 0x07, 0x25, 0x84, 0x66, 0x45, + 0x3c, 0x25, 0x97, 0x10, 0x09, 0x2f, 0x43, 0x5d, 0x30, 0x2c, 0x08, 0x24, 0xa8, 0x29, 0x48, 0x50, 0x99, 0xaf, 0x3d, + 0x82, 0x59, 0xe7, 0x66, 0xb6, 0x53, 0xd4, 0x75, 0x41, 0x7e, 0x7e, 0xd1, 0xf1, 0x08, 0x58, 0xda, 0x83, 0x83, 0x02, + 0x22, 0x88, 0x01, 0x05, 0x2f, 0x25, 0xc0, 0x40, 0x03, 0x5e, 0x6c, 0x68, 0xc0, 0xe7, 0xda, 0x78, 0x1d, 0x18, 0x5b, + 0x9f, 0x32, 0xc8, 0xc5, 0xb3, 0x6a, 0x4f, 0x13, 0x42, 0xf6, 0x5b, 0x3d, 0x9d, 0x6e, 0x47, 0x48, 0xec, 0x7d, 0xd4, + 0x26, 0xd0, 0x98, 0x23, 0xdd, 0xd5, 0xc6, 0xfc, 0x5a, 0xd3, 0x23, 0x56, 0x93, 0x90, 0x2e, 0x48, 0x97, 0xe7, 0xd3, + 0x9e, 0xc1, 0x15, 0xab, 0x34, 0x72, 0x70, 0x01, 0xfa, 0x6c, 0x40, 0x80, 0x02, 0x95, 0xa6, 0x12, 0x45, 0x11, 0x17, + 0x49, 0xc9, 0x86, 0x61, 0x06, 0x61, 0x0a, 0xab, 0x95, 0xa0, 0x1b, 0x6b, 0x00, 0xbc, 0x33, 0xb3, 0x7f, 0x4a, 0x1f, + 0x6c, 0xba, 0xf6, 0xe6, 0x11, 0x40, 0x40, 0xf6, 0xdb, 0x25, 0xbb, 0x2e, 0x36, 0x2a, 0xb3, 0xb0, 0x96, 0xb1, 0x95, + 0xdb, 0xf6, 0x18, 0x7b, 0x27, 0xb6, 0xf9, 0x04, 0x08, 0x51, 0x5b, 0x32, 0x8d, 0x10, 0x21, 0xb1, 0x88, 0x75, 0x6d, + 0xc8, 0x46, 0x1b, 0xda, 0x37, 0x4f, 0xc2, 0x43, 0xec, 0x03, 0x50, 0xbc, 0x39, 0x2e, 0xc1, 0x21, 0xbc, 0xf0, 0x08, + 0x7f, 0x0b, 0x2c, 0x52, 0x81, 0x19, 0x96, 0xab, 0x15, 0xd4, 0xf3, 0x78, 0x9f, 0x6d, 0x06, 0x27, 0x95, 0x1b, 0x63, + 0x97, 0x76, 0xe2, 0x71, 0xd9, 0x84, 0xc4, 0x19, 0xf4, 0xeb, 0x2b, 0xa2, 0xde, 0x7e, 0x3b, 0x7d, 0xe2, 0xdf, 0x2b, + 0x73, 0x3b, 0x10, 0x1b, 0xd6, 0x1b, 0xac, 0x3e, 0x80, 0x96, 0xbf, 0xca, 0xfc, 0x43, 0x65, 0xc1, 0x4d, 0x82, 0xda, + 0x5c, 0xc4, 0x2e, 0xeb, 0x22, 0x46, 0x6a, 0x8b, 0xbb, 0x43, 0x88, 0x7f, 0xb5, 0x15, 0xc5, 0x80, 0x27, 0x15, 0xff, + 0x1c, 0xa3, 0x2e, 0x84, 0xa2, 0xb6, 0x1e, 0x36, 0x40, 0x69, 0x97, 0xeb, 0x4a, 0x8c, 0x0c, 0x09, 0xe4, 0x5b, 0x17, + 0x5e, 0xd0, 0x9c, 0x44, 0x0a, 0xe4, 0xe4, 0x20, 0x2a, 0x69, 0xb6, 0x21, 0xcc, 0x75, 0xb7, 0x70, 0xcc, 0x5c, 0x6d, + 0xd0, 0x22, 0x7e, 0x01, 0xec, 0x0c, 0x37, 0x92, 0xa5, 0x03, 0x9f, 0xaa, 0x81, 0xcf, 0xaf, 0xb9, 0xa1, 0x28, 0x0a, + 0xf5, 0xde, 0xd9, 0x47, 0xe6, 0xe0, 0x77, 0x1a, 0x88, 0x8f, 0xd4, 0xe9, 0x48, 0x36, 0x42, 0xad, 0x39, 0x3b, 0x5e, + 0xb6, 0x19, 0x61, 0x50, 0xd8, 0xe8, 0x7d, 0x15, 0xb2, 0x8a, 0x9d, 0x9d, 0x8a, 0x60, 0x4e, 0x5f, 0x54, 0xe5, 0x9c, + 0xca, 0x2d, 0xa3, 0x5a, 0x6a, 0x1a, 0x20, 0xc2, 0x95, 0x4f, 0x24, 0xef, 0x33, 0x13, 0xfe, 0xc1, 0x60, 0x5c, 0x3d, + 0x52, 0xf8, 0xfb, 0x5d, 0xb1, 0x43, 0xb6, 0xa3, 0xc3, 0x6d, 0x04, 0xcd, 0x0b, 0x15, 0x3c, 0xe0, 0xa8, 0x64, 0x09, + 0x91, 0x22, 0x97, 0xfb, 0xaa, 0x66, 0xca, 0x76, 0x1d, 0x21, 0x84, 0xb4, 0xc7, 0x59, 0x37, 0xb4, 0x7a, 0xe8, 0x91, + 0x2a, 0xca, 0xe1, 0x16, 0xcd, 0x75, 0x01, 0x2a, 0x8c, 0x40, 0xba, 0xfc, 0xcc, 0xee, 0x52, 0x09, 0xd1, 0xcb, 0xd7, + 0x2e, 0x84, 0xb1, 0xb3, 0xb2, 0xc4, 0x85, 0x19, 0xb5, 0x0d, 0xa3, 0xeb, 0x36, 0x86, 0xb3, 0x81, 0x31, 0xd3, 0xa0, + 0xa4, 0x05, 0xa1, 0xae, 0xbb, 0xf4, 0x22, 0x33, 0x81, 0x1e, 0x73, 0x42, 0x1b, 0x0c, 0x4f, 0x89, 0x06, 0xcb, 0xa6, + 0x02, 0x2c, 0xf8, 0x96, 0x45, 0x6a, 0x6d, 0x36, 0x59, 0xfc, 0x51, 0xc7, 0xe6, 0x69, 0xbf, 0xbc, 0x62, 0x9e, 0x0b, + 0x47, 0xdd, 0x9e, 0x67, 0x3e, 0x1e, 0xdd, 0xd3, 0x37, 0x57, 0x2f, 0x5e, 0xbe, 0x7e, 0xb5, 0x5a, 0xb5, 0x59, 0xb3, + 0x7d, 0x82, 0x7f, 0xd2, 0x65, 0x3c, 0xd8, 0x32, 0x0a, 0xd0, 0xc1, 0xc1, 0x3e, 0x37, 0x2e, 0x3c, 0x9f, 0xf9, 0x1c, + 0xe2, 0x06, 0xe9, 0x01, 0xce, 0x8a, 0x32, 0x26, 0xc8, 0x6d, 0xd4, 0x8b, 0xee, 0x22, 0x50, 0x42, 0x55, 0xe4, 0xef, + 0xc3, 0xe6, 0xec, 0xf7, 0x20, 0x30, 0x11, 0xd4, 0x87, 0x08, 0x20, 0x10, 0xaf, 0x14, 0x17, 0x84, 0xf9, 0x04, 0x88, + 0xe2, 0xbd, 0x00, 0xce, 0xd4, 0x44, 0xad, 0x5a, 0xa8, 0xb8, 0x00, 0x92, 0x68, 0xc3, 0x51, 0xd2, 0x23, 0x13, 0xc0, + 0x1b, 0x82, 0x52, 0xda, 0x5f, 0xdd, 0xdc, 0xb9, 0x4b, 0xe5, 0xa8, 0xd7, 0x4a, 0x73, 0x3c, 0x75, 0x9f, 0x53, 0xf8, + 0x9c, 0x76, 0xfd, 0xe9, 0x20, 0x0e, 0x73, 0xbc, 0x20, 0xe2, 0xd0, 0x3f, 0x8b, 0xb8, 0x9c, 0x17, 0xec, 0x0b, 0x97, + 0x0b, 0x95, 0x2e, 0x6f, 0x53, 0x99, 0xdc, 0x36, 0x47, 0x87, 0x71, 0x91, 0xdc, 0x36, 0x55, 0x72, 0x8b, 0xf0, 0x5d, + 0x2a, 0x93, 0x3b, 0x9b, 0x72, 0xd7, 0x54, 0x70, 0xf3, 0x85, 0x05, 0x1c, 0x8a, 0xb6, 0x68, 0x63, 0xb1, 0x59, 0xd4, + 0xa6, 0xb8, 0xa2, 0x01, 0x06, 0xff, 0xbe, 0x63, 0xe3, 0x87, 0xe1, 0x4b, 0x70, 0x69, 0xd2, 0x44, 0x7e, 0x02, 0xe9, + 0xa7, 0x55, 0x19, 0xb8, 0x4f, 0x49, 0xab, 0x3b, 0xbd, 0x10, 0xcd, 0x76, 0xb7, 0xd1, 0x98, 0xc2, 0xde, 0xcd, 0x48, + 0xee, 0x8b, 0x4d, 0x1b, 0x26, 0xbe, 0xce, 0x7e, 0xb6, 0x5a, 0xed, 0xe7, 0xc8, 0x6c, 0xb8, 0x09, 0x8b, 0x75, 0x7f, + 0x3a, 0xc0, 0x2d, 0xfc, 0x3c, 0x43, 0x68, 0xc9, 0xfa, 0xd3, 0x01, 0x61, 0xfd, 0x69, 0xa3, 0x3d, 0xb0, 0x86, 0x76, + 0x66, 0x2b, 0xae, 0x21, 0x84, 0xe6, 0x74, 0x70, 0x64, 0x4a, 0x4a, 0x97, 0x6f, 0xbf, 0x68, 0x15, 0xd0, 0x4f, 0xd5, + 0x82, 0x97, 0x49, 0xdc, 0x81, 0xbe, 0xe8, 0x85, 0x7d, 0xba, 0xb5, 0x20, 0xc7, 0x47, 0x95, 0xab, 0x3d, 0x45, 0xd8, + 0xf4, 0xa4, 0x0e, 0x8b, 0x43, 0xd3, 0x8c, 0xeb, 0x52, 0xba, 0xef, 0x50, 0x33, 0xf2, 0xd1, 0xc1, 0x02, 0x10, 0xa4, + 0x82, 0x47, 0x56, 0xb8, 0x70, 0x4a, 0x21, 0x5c, 0x1c, 0x54, 0xb6, 0x60, 0x92, 0x93, 0x56, 0x37, 0x37, 0x96, 0xfe, + 0xb9, 0x8b, 0x68, 0x4a, 0x31, 0x25, 0x99, 0x2f, 0x99, 0x1b, 0xb0, 0xd0, 0x4d, 0xca, 0x33, 0x05, 0xbd, 0xd2, 0x00, + 0x8f, 0x08, 0xc4, 0x43, 0xea, 0x16, 0xc6, 0xc0, 0x2b, 0x9e, 0x36, 0x8b, 0x3e, 0x1b, 0xa0, 0xa3, 0x63, 0x4c, 0xfb, + 0x7f, 0x65, 0xf3, 0x36, 0x3c, 0x16, 0xf8, 0xd7, 0x80, 0x4c, 0x9b, 0xb2, 0x4c, 0x10, 0x90, 0x30, 0x6a, 0xca, 0x43, + 0xd8, 0x4b, 0x08, 0x67, 0xb6, 0x62, 0xd6, 0x67, 0x83, 0xe6, 0xb4, 0xac, 0xd8, 0xf1, 0x15, 0x1b, 0xb2, 0x4c, 0xb0, + 0x15, 0x1b, 0xae, 0x62, 0xf8, 0x3a, 0x83, 0x01, 0x41, 0x08, 0x00, 0x06, 0x00, 0xd0, 0x28, 0x88, 0xe6, 0x8b, 0x15, + 0xf1, 0x9b, 0xdd, 0xde, 0xe3, 0xb7, 0xc0, 0x02, 0xad, 0xb6, 0xff, 0x77, 0xa1, 0x0c, 0xd8, 0x53, 0x16, 0x26, 0x66, + 0x6e, 0x61, 0x55, 0x74, 0x00, 0x95, 0x12, 0x61, 0x0a, 0x03, 0x99, 0xfd, 0xcc, 0x40, 0x2d, 0xd0, 0x1a, 0xe4, 0x7d, + 0x3d, 0x68, 0x66, 0x70, 0xc4, 0xc0, 0x3b, 0x34, 0x64, 0x6a, 0x8c, 0x09, 0xe3, 0x1c, 0xa6, 0x98, 0x19, 0xf0, 0x4c, + 0xd3, 0xd6, 0x5a, 0x1a, 0x59, 0xae, 0x97, 0xf7, 0xfe, 0xd1, 0xb1, 0xea, 0x17, 0xcd, 0xf6, 0x00, 0xed, 0x13, 0x62, + 0x3f, 0x06, 0xb0, 0xc9, 0x5c, 0x6a, 0xc3, 0x7c, 0x1f, 0x75, 0x52, 0xfb, 0x09, 0x7f, 0x06, 0x6b, 0xb3, 0x03, 0x40, + 0x47, 0x86, 0xcd, 0xfa, 0xcb, 0x9a, 0xca, 0xeb, 0xe3, 0xce, 0x28, 0x95, 0xbb, 0xde, 0x9d, 0x0e, 0x34, 0xc5, 0xa1, + 0xb7, 0x1e, 0x2e, 0x1f, 0xea, 0x21, 0x60, 0xc6, 0x60, 0x6e, 0x99, 0xd1, 0xf7, 0x42, 0x24, 0x17, 0x44, 0x62, 0x69, + 0xb0, 0x86, 0xc1, 0xde, 0x3a, 0x38, 0x30, 0xd5, 0x58, 0x03, 0x9e, 0x27, 0x45, 0x20, 0x18, 0xf8, 0x08, 0xca, 0x80, + 0x26, 0xca, 0xdc, 0x86, 0x93, 0x8f, 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, 0xdd, 0xcd, 0x74, + 0xca, 0x66, 0x3a, 0xdb, 0xcd, 0x84, 0x9a, 0x99, 0x6f, 0x59, 0x45, 0x9a, 0x93, 0x35, 0x51, 0x73, 0x2a, 0x7e, 0xa2, + 0x73, 0xd0, 0x8e, 0x72, 0x7b, 0xaf, 0x0a, 0x27, 0x57, 0x4e, 0x2e, 0xf7, 0x73, 0x43, 0x5c, 0x91, 0xb9, 0x50, 0x87, + 0x00, 0x2f, 0x2f, 0xca, 0xc7, 0x07, 0xb8, 0x14, 0xbf, 0xca, 0x91, 0x8b, 0x72, 0x2a, 0xa4, 0x96, 0x82, 0x45, 0xc8, + 0xa0, 0xaa, 0x8b, 0x81, 0xbd, 0xb4, 0x7b, 0x4f, 0xf4, 0x78, 0xbf, 0x8a, 0x98, 0x37, 0x30, 0xcf, 0x7d, 0x7c, 0x4f, + 0x53, 0xec, 0xd4, 0xc4, 0x19, 0xf9, 0x90, 0xc5, 0x39, 0xc8, 0x66, 0xfd, 0xea, 0xb5, 0xdf, 0x46, 0x1b, 0x17, 0xcd, + 0x58, 0xf4, 0xcc, 0x13, 0x27, 0x3f, 0x14, 0xc6, 0x38, 0xc0, 0x3a, 0xfa, 0x23, 0x4c, 0x2d, 0xd8, 0xb3, 0xc4, 0x53, + 0xe8, 0xe4, 0xd6, 0xa6, 0xdd, 0x85, 0x69, 0x77, 0x26, 0xad, 0x03, 0xe5, 0x80, 0x34, 0xbb, 0x32, 0x9d, 0x3b, 0xff, + 0x7d, 0x07, 0x2f, 0xdd, 0xae, 0x21, 0x12, 0xf7, 0xfc, 0x91, 0x31, 0x86, 0x78, 0x03, 0x36, 0xa2, 0xea, 0xe0, 0xe0, + 0x0f, 0xe7, 0x7d, 0x5b, 0xc9, 0x7d, 0xdf, 0x0a, 0x07, 0xb6, 0xc1, 0x54, 0xba, 0xbc, 0x91, 0xcc, 0x16, 0x60, 0xd7, + 0xb9, 0xff, 0x8d, 0x78, 0xf8, 0x22, 0x64, 0x5a, 0xac, 0xab, 0xf8, 0x2b, 0x39, 0x2a, 0x3d, 0x44, 0x35, 0x44, 0x20, + 0xad, 0xac, 0x4b, 0x43, 0xd3, 0xd1, 0xab, 0x29, 0x1d, 0xc9, 0x9b, 0xb7, 0x52, 0xea, 0x81, 0x7d, 0x91, 0x5b, 0x27, + 0xf0, 0x68, 0x61, 0x8d, 0xa1, 0xb9, 0x2b, 0xbd, 0x93, 0x6c, 0x40, 0xd4, 0xfa, 0xb8, 0x43, 0x49, 0x24, 0x16, 0xd5, + 0x5d, 0x08, 0x87, 0xbb, 0x10, 0xcc, 0xcb, 0xa0, 0x6d, 0x10, 0xbb, 0xdd, 0x05, 0x6d, 0x03, 0xa7, 0x6e, 0x1b, 0xb8, + 0x3d, 0x18, 0x2c, 0xec, 0x7d, 0x78, 0x39, 0x96, 0x63, 0xe1, 0xaf, 0xc9, 0xec, 0x03, 0x40, 0xa0, 0xf6, 0x61, 0xc5, + 0x13, 0x07, 0x82, 0xc4, 0x19, 0x8e, 0xbe, 0xe7, 0xec, 0xc6, 0x5a, 0x0e, 0xcf, 0xe6, 0x0b, 0xcd, 0x46, 0xe6, 0x8e, + 0x1a, 0x54, 0x7c, 0x75, 0x3f, 0xaf, 0x9f, 0xb2, 0x9a, 0x6e, 0xfc, 0x1e, 0x84, 0x91, 0x70, 0xca, 0x0e, 0xa3, 0x90, + 0xb0, 0xc1, 0xac, 0xca, 0x78, 0x6d, 0xbf, 0x41, 0xbc, 0x07, 0x6d, 0xc2, 0x09, 0x16, 0xb5, 0x0b, 0xaa, 0x08, 0xdb, + 0x78, 0x63, 0x41, 0x94, 0x87, 0x37, 0x5b, 0x46, 0xd3, 0xcb, 0x35, 0x04, 0x3a, 0xee, 0x45, 0xcd, 0xa8, 0xc1, 0x52, + 0x17, 0x94, 0xd9, 0x47, 0x18, 0x57, 0x17, 0x27, 0x26, 0x4e, 0x7b, 0xa9, 0x57, 0xff, 0x2d, 0x03, 0x03, 0x7c, 0x01, + 0x5e, 0x62, 0x61, 0x74, 0xd7, 0xbe, 0x6e, 0x40, 0x7d, 0xd9, 0x60, 0x03, 0xb4, 0x5a, 0xb5, 0xca, 0x67, 0xa0, 0xdc, + 0x35, 0x97, 0xb0, 0xd7, 0x5c, 0xc2, 0x5d, 0x73, 0x09, 0x7f, 0xcd, 0x25, 0xcc, 0x35, 0x97, 0xf0, 0xd7, 0x5c, 0x1e, + 0x84, 0x9f, 0x82, 0x38, 0x8e, 0x31, 0x87, 0xb8, 0x8a, 0xda, 0x46, 0xc6, 0x83, 0x0b, 0xcf, 0x7d, 0x96, 0xa8, 0x72, + 0xf9, 0xc3, 0x18, 0x72, 0x5b, 0xb6, 0x12, 0xc6, 0x6d, 0x8a, 0x29, 0x88, 0x9c, 0x7e, 0x70, 0x50, 0xba, 0x3b, 0x83, + 0x8f, 0x7a, 0xca, 0xf1, 0xd2, 0x3a, 0xd1, 0xfe, 0x01, 0x3a, 0x79, 0xf3, 0xeb, 0x63, 0x2a, 0xd7, 0x44, 0x38, 0x93, + 0xfb, 0xfd, 0xb6, 0xa7, 0x14, 0x9f, 0x32, 0x13, 0x9e, 0x9c, 0x27, 0xda, 0x88, 0x20, 0x08, 0x51, 0xa2, 0x70, 0x46, + 0xa4, 0xdd, 0xef, 0xde, 0x15, 0xde, 0xa8, 0xa2, 0xbc, 0x59, 0xc9, 0xe3, 0x1c, 0x9c, 0xd8, 0x8d, 0x15, 0x06, 0xea, + 0x82, 0x0b, 0x41, 0x66, 0x12, 0xfe, 0x68, 0xe6, 0x96, 0x9c, 0x65, 0x65, 0xd2, 0xc7, 0x66, 0x6e, 0x08, 0x58, 0x41, + 0xf6, 0x3d, 0xcc, 0x96, 0xb7, 0x29, 0xc5, 0x77, 0x69, 0x86, 0x87, 0xf2, 0x36, 0x2d, 0x42, 0x5b, 0x10, 0x7f, 0xf1, + 0x37, 0x8e, 0x23, 0x41, 0xc1, 0xdf, 0x27, 0xe2, 0x62, 0x8f, 0x6f, 0x78, 0x01, 0x2e, 0x33, 0x63, 0x51, 0x9d, 0x32, + 0xfc, 0x0d, 0x4b, 0x78, 0x08, 0x4e, 0xa6, 0xb1, 0x22, 0xf7, 0x38, 0xb0, 0x13, 0x92, 0x80, 0xc3, 0xd5, 0xed, 0x15, + 0xff, 0x0a, 0x17, 0x5f, 0xa5, 0xb3, 0x65, 0x73, 0x28, 0x6f, 0x23, 0x5c, 0x90, 0x37, 0xf0, 0xfa, 0xd6, 0xff, 0xcb, + 0xde, 0xdb, 0x36, 0xb7, 0x6d, 0x64, 0xeb, 0xa2, 0x7f, 0x45, 0x62, 0xd9, 0x0c, 0x60, 0x36, 0x29, 0xca, 0xe7, 0xcc, + 0x54, 0x5d, 0x50, 0x6d, 0x96, 0x63, 0xc7, 0x13, 0x67, 0x22, 0xdb, 0x63, 0x79, 0x32, 0xc9, 0xb0, 0x78, 0x19, 0x08, + 0x68, 0x0a, 0x70, 0x40, 0x80, 0x01, 0x40, 0x89, 0x34, 0x89, 0xff, 0x7e, 0x6a, 0xad, 0xd5, 0xaf, 0x20, 0x28, 0x7b, + 0xf6, 0x3e, 0xfb, 0xd3, 0xbd, 0x5f, 0x6c, 0xb1, 0xd1, 0x68, 0xf4, 0x7b, 0xaf, 0x5e, 0x2f, 0xcf, 0xd3, 0x93, 0xb1, + 0xba, 0x3d, 0x70, 0xd6, 0xa5, 0x14, 0x1d, 0x6f, 0x8a, 0xc3, 0xdb, 0xf3, 0xd9, 0x7e, 0x1b, 0x44, 0x6c, 0x17, 0x64, + 0x58, 0xeb, 0xa4, 0xe1, 0x3f, 0xd1, 0xd6, 0xc1, 0x62, 0x84, 0xfd, 0x5f, 0xd6, 0x03, 0x2f, 0x21, 0x35, 0x14, 0xb8, + 0x18, 0x6c, 0x38, 0x5a, 0xdb, 0x65, 0x1a, 0xb8, 0xa9, 0x41, 0xaf, 0xef, 0x29, 0x44, 0x79, 0xc9, 0x68, 0x6e, 0x04, + 0xeb, 0xc6, 0x90, 0x8b, 0xc3, 0x71, 0xb3, 0x1c, 0xf2, 0x92, 0xa6, 0xd3, 0x20, 0x94, 0xee, 0x2c, 0x6b, 0x48, 0xa2, + 0xec, 0x83, 0x50, 0xbb, 0xb6, 0xec, 0xb7, 0x81, 0xed, 0xcb, 0x1f, 0x0d, 0x63, 0xff, 0x62, 0xf9, 0x4c, 0x48, 0x17, + 0xf1, 0x1c, 0x04, 0x51, 0xfb, 0x79, 0x36, 0xdc, 0xf8, 0x17, 0xeb, 0x67, 0x42, 0xf9, 0x8d, 0xe7, 0xb6, 0x1c, 0x52, + 0x67, 0x2d, 0x7c, 0x61, 0x3c, 0x3c, 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, 0x01, 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, 0xee, 0x52, 0xa6, 0xcb, 0x80, 0x4b, 0xfa, 0x5d, 0xaa, 0x94, 0xc2, 0x7f, 0x22, 0x00, 0x9d, 0x83, 0x7b, 0x7c, + 0x39, 0x06, 0xd2, 0x0c, 0x0b, 0xbf, 0x35, 0x3b, 0xbe, 0x26, 0xe1, 0x36, 0x09, 0x2e, 0x06, 0x38, 0x47, 0x57, 0x61, + 0x79, 0x97, 0x42, 0x04, 0x55, 0x09, 0xf5, 0xad, 0x4c, 0x83, 0xd2, 0x56, 0x83, 0xb0, 0x26, 0xa1, 0xce, 0x24, 0x1b, + 0x95, 0xb6, 0x1b, 0x85, 0xd9, 0x22, 0xae, 0x67, 0x84, 0x35, 0x67, 0x33, 0xd5, 0xc0, 0xa4, 0xe1, 0xb8, 0x69, 0xb4, + 0x16, 0x15, 0x6a, 0x0a, 0xf3, 0x1a, 0x57, 0x95, 0xaa, 0xee, 0xe6, 0xd4, 0x52, 0x5a, 0xb6, 0x57, 0xdd, 0x24, 0x1b, + 0x72, 0x19, 0xca, 0x30, 0xd8, 0xc8, 0x11, 0x4c, 0x20, 0x49, 0xce, 0xfc, 0x8d, 0xfc, 0x43, 0x6d, 0xba, 0x16, 0x30, + 0xc7, 0x98, 0x65, 0xc3, 0x82, 0x5e, 0x81, 0x7b, 0xa0, 0x95, 0x9e, 0x4f, 0xb3, 0x8b, 0x3c, 0x48, 0x86, 0x85, 0x5e, + 0x36, 0x19, 0xff, 0x53, 0x18, 0x69, 0x32, 0x63, 0x25, 0x8b, 0x6c, 0x57, 0xa7, 0xc4, 0x79, 0x9c, 0xc0, 0xf6, 0x68, + 0x7a, 0xcb, 0xf7, 0x19, 0x44, 0x05, 0x81, 0x82, 0x19, 0xf3, 0x65, 0x17, 0xcf, 0x7d, 0x9f, 0x59, 0xa6, 0xee, 0xc3, + 0xc1, 0x98, 0xb1, 0xfd, 0x7e, 0x3f, 0xef, 0xf7, 0xd5, 0x7c, 0xeb, 0xf7, 0x93, 0x17, 0xe6, 0x6f, 0x0f, 0x18, 0x14, + 0xe4, 0x44, 0x34, 0x15, 0x22, 0xf8, 0x87, 0xe4, 0x19, 0x92, 0xd1, 0x1d, 0xf7, 0xb9, 0xe5, 0x6c, 0x59, 0x1d, 0x81, + 0x60, 0x1e, 0x0e, 0x97, 0x0a, 0xec, 0x5a, 0xa2, 0x48, 0xc8, 0xf2, 0x9f, 0x81, 0xf1, 0xcc, 0x7d, 0x80, 0x25, 0x03, + 0x10, 0xb6, 0xca, 0xd3, 0xf5, 0x9e, 0xaf, 0x82, 0x77, 0x3a, 0xde, 0x35, 0x56, 0x64, 0x20, 0x6e, 0x81, 0x8d, 0x58, + 0x6b, 0x0f, 0xc8, 0x99, 0x02, 0x1c, 0x2f, 0x0e, 0x87, 0x73, 0xf9, 0x4b, 0x37, 0x5b, 0x27, 0x50, 0x29, 0x70, 0x7b, + 0x74, 0x72, 0xf0, 0xdf, 0x81, 0x66, 0x50, 0x0e, 0xf3, 0x7a, 0xfb, 0x3b, 0x73, 0xf2, 0xd3, 0x53, 0xfc, 0x13, 0x1e, + 0xa2, 0xd3, 0x6f, 0xf7, 0xe6, 0x0f, 0x8a, 0xca, 0xc3, 0x41, 0x2d, 0xfe, 0x73, 0xce, 0x2b, 0xf8, 0x85, 0x6f, 0x02, + 0xb3, 0xc9, 0xd4, 0x3b, 0xf9, 0x26, 0xcf, 0x99, 0x7a, 0x8d, 0x57, 0x4c, 0xbe, 0xc3, 0xe1, 0x5c, 0x8c, 0xea, 0xed, + 0xc8, 0x89, 0x76, 0xca, 0x31, 0x0e, 0x06, 0xff, 0x45, 0xb4, 0x4d, 0x08, 0x30, 0xa4, 0x6e, 0x49, 0x33, 0x1b, 0x57, + 0x96, 0x78, 0x96, 0xce, 0x2f, 0x27, 0x75, 0xb9, 0xd3, 0x8a, 0xa7, 0x3d, 0xb0, 0xb8, 0xad, 0xc1, 0x0b, 0xe0, 0xde, + 0x62, 0xeb, 0x4a, 0xc1, 0xe1, 0x02, 0xe2, 0x14, 0x27, 0x20, 0x82, 0xf6, 0xfb, 0x12, 0xef, 0x15, 0xf4, 0x49, 0x3f, + 0x40, 0x30, 0xe4, 0xcf, 0x12, 0x70, 0xd7, 0xeb, 0xd5, 0x18, 0xdf, 0x4b, 0x21, 0xb8, 0x3e, 0xd3, 0x00, 0xb4, 0xe0, + 0x77, 0xf9, 0x58, 0x4e, 0xbf, 0x89, 0xc0, 0xb3, 0x65, 0x6f, 0xa2, 0xdc, 0x6d, 0x78, 0xda, 0x3f, 0x5a, 0x08, 0xc0, + 0x52, 0x3c, 0x53, 0x82, 0x05, 0x39, 0xc5, 0x5c, 0xfc, 0xbf, 0xe0, 0x23, 0xe6, 0x7b, 0xd2, 0x45, 0x6c, 0xbd, 0x7d, + 0x72, 0x61, 0x20, 0x81, 0xa6, 0x03, 0xf0, 0xe3, 0x55, 0x40, 0x57, 0xc6, 0xcf, 0xcf, 0xb2, 0x1e, 0xeb, 0xe3, 0x3f, + 0x05, 0xf7, 0xe9, 0x67, 0x0a, 0x1f, 0x1d, 0x8e, 0xab, 0x74, 0xb4, 0xa3, 0x14, 0x44, 0x47, 0xb7, 0xcf, 0xa7, 0x3c, + 0xfb, 0xa6, 0x02, 0x72, 0xcb, 0x51, 0x7b, 0x2a, 0x00, 0x8b, 0x2d, 0x1d, 0x81, 0x4f, 0xb3, 0x7c, 0x42, 0xbe, 0xd7, + 0x53, 0x71, 0x75, 0xa9, 0xd3, 0xc5, 0x8b, 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, 0x75, 0x8d, 0x82, 0x95, 0x80, 0x33, 0xed, 0x1a, 0x0c, 0x36, 0xb0, + 0x6e, 0x59, 0x06, 0x7f, 0xc3, 0x35, 0x4d, 0xe0, 0x86, 0x45, 0xd6, 0x7b, 0x83, 0xad, 0x74, 0x0d, 0x8e, 0x96, 0x89, + 0x73, 0x29, 0xc9, 0xca, 0x16, 0x19, 0x57, 0x8f, 0x42, 0xaa, 0xa6, 0xfb, 0x5b, 0x51, 0x3f, 0x08, 0x91, 0x07, 0xab, + 0x94, 0x45, 0xc5, 0x0a, 0x64, 0xf6, 0xe0, 0x1f, 0x21, 0x23, 0x47, 0x39, 0x70, 0x14, 0xfa, 0x5b, 0x13, 0xe8, 0x3c, + 0x3f, 0x85, 0x3a, 0x8f, 0x04, 0x5b, 0xa9, 0x87, 0xc2, 0xca, 0x0b, 0x88, 0x0e, 0xb6, 0x30, 0x56, 0x79, 0x12, 0x2a, + 0x36, 0x65, 0x22, 0x8f, 0x83, 0x5a, 0x02, 0xc6, 0x0a, 0x82, 0x39, 0xcb, 0xa5, 0x0b, 0x52, 0xd5, 0xe8, 0x61, 0x91, + 0xb9, 0x9f, 0x0a, 0xca, 0xff, 0x54, 0xe5, 0x84, 0xeb, 0xcb, 0x10, 0xe0, 0x68, 0x9f, 0x82, 0x28, 0x31, 0xd6, 0x2f, + 0x5a, 0xbc, 0x93, 0x99, 0xb3, 0xa9, 0xed, 0x25, 0xc8, 0xd8, 0x0e, 0xbf, 0x42, 0x68, 0xb5, 0x50, 0x64, 0xd1, 0x70, + 0xc1, 0x74, 0x7b, 0x4a, 0xab, 0xee, 0x61, 0xc3, 0xb3, 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, 0x69, + 0x34, 0x9f, 0xe5, 0x73, 0x1f, 0x15, 0x17, 0x93, 0xc1, 0x60, 0xe3, 0x67, 0xc3, 0x21, 0x4b, 0x86, 0xc3, 0x49, 0xf6, + 0x14, 0x5e, 0x7b, 0xca, 0x23, 0xb5, 0xa4, 0x92, 0xab, 0x0c, 0xf6, 0xf7, 0x01, 0x8f, 0x7c, 0xd6, 0xf9, 0x69, 0xd9, + 0x74, 0xe9, 0x7e, 0x66, 0xc7, 0x5d, 0xe8, 0x0e, 0xb0, 0xf1, 0xb6, 0x41, 0x47, 0xfe, 0xf5, 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, 0x07, 0xf7, 0x85, 0x15, 0x05, + 0xfe, 0xdf, 0xb2, 0x05, 0xbb, 0x97, 0xc7, 0xc0, 0x35, 0x3a, 0x26, 0xc1, 0x05, 0xe2, 0x9e, 0xdd, 0x82, 0x1d, 0x16, + 0xfe, 0x82, 0xeb, 0xe4, 0x98, 0xed, 0xf0, 0x51, 0xe8, 0x15, 0xec, 0xd6, 0x27, 0xa0, 0x5d, 0xb0, 0x35, 0x40, 0x36, + 0xb6, 0xc5, 0x47, 0x77, 0x87, 0xc3, 0xb5, 0xe7, 0xb3, 0x07, 0xfc, 0x71, 0x7e, 0x77, 0x38, 0xec, 0x3c, 0xa3, 0xde, + 0xbb, 0xe1, 0x09, 0x7b, 0xcf, 0x93, 0xc9, 0xcd, 0x15, 0x8f, 0x27, 0x83, 0xc1, 0x8d, 0xbf, 0xe0, 0xf5, 0xec, 0x06, + 0xb4, 0x03, 0xe7, 0x0b, 0xa9, 0x6b, 0xf6, 0x6e, 0x79, 0xe6, 0x2d, 0x70, 0x6c, 0x6e, 0xe1, 0xe8, 0xed, 0xf7, 0xbd, + 0x3b, 0x1e, 0x79, 0xb7, 0xa4, 0x62, 0x5a, 0x71, 0xc5, 0xf1, 0xb6, 0xc5, 0xfd, 0x74, 0xc5, 0x43, 0x78, 0x84, 0x55, + 0x99, 0xde, 0x04, 0xef, 0x7d, 0xb6, 0xd2, 0x2c, 0x70, 0x0f, 0x98, 0x63, 0x4d, 0x76, 0x42, 0x33, 0xf1, 0x57, 0xd8, + 0x3f, 0x37, 0xaa, 0x7f, 0x68, 0xfe, 0x97, 0xba, 0x9f, 0xc0, 0xed, 0x8b, 0x2c, 0x48, 0xec, 0x3d, 0xbf, 0x61, 0xf7, + 0xdc, 0xb0, 0xcd, 0x9e, 0x99, 0xb2, 0x4f, 0x94, 0x1a, 0x3f, 0x52, 0xea, 0xda, 0x32, 0xac, 0x64, 0xee, 0xbe, 0x8c, + 0xc0, 0xe1, 0x80, 0xfc, 0x74, 0x87, 0x38, 0x08, 0xad, 0x9b, 0xac, 0xe6, 0x8a, 0x72, 0x2e, 0xb4, 0x65, 0xe6, 0xe5, + 0xc0, 0x62, 0x96, 0x52, 0x68, 0x2c, 0x00, 0x10, 0x4c, 0x0a, 0xad, 0xbd, 0x97, 0x01, 0xe4, 0x04, 0x0d, 0x7f, 0x6c, + 0xae, 0x8a, 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, 0xa7, + 0xbc, 0x66, 0x82, 0xc8, 0x36, 0x2a, 0x7f, 0x52, 0xbc, 0x40, 0x32, 0x82, 0xe2, 0x69, 0xad, 0x32, 0x16, 0x86, 0x79, + 0xa0, 0x80, 0xbc, 0x7b, 0x77, 0xea, 0x5b, 0xfb, 0x63, 0xc7, 0x9e, 0xad, 0x55, 0xa8, 0x85, 0x9a, 0xc2, 0x25, 0x87, + 0xe8, 0x0a, 0x32, 0x50, 0xc8, 0x78, 0xf2, 0x7a, 0x70, 0x39, 0x89, 0xae, 0xb8, 0x40, 0x67, 0x7c, 0x7d, 0xd3, 0x4d, + 0x67, 0xd1, 0xd3, 0x6a, 0x3e, 0x21, 0x25, 0xd9, 0xe1, 0x90, 0x8d, 0xaa, 0xba, 0x58, 0x4f, 0x43, 0xf9, 0xd3, 0x43, + 0xf0, 0xf5, 0x82, 0x7a, 0x4d, 0x56, 0xa9, 0x7e, 0x4a, 0x95, 0xf2, 0xa2, 0xe1, 0xa5, 0xff, 0xb4, 0x92, 0xfb, 0x1e, + 0x90, 0xd6, 0xf2, 0x92, 0xcb, 0xf7, 0x23, 0xc4, 0x18, 0xf1, 0x03, 0xaf, 0xe4, 0x11, 0x0b, 0xd5, 0x14, 0xae, 0x79, + 0x84, 0x20, 0x6f, 0x99, 0x0e, 0xfe, 0xd6, 0x13, 0xa7, 0xfb, 0x13, 0xa5, 0x5d, 0x7c, 0x61, 0x51, 0xf7, 0x64, 0x6d, + 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, 0xf9, 0xb0, 0xe1, 0x11, 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, 0xfb, 0xb9, 0x80, 0x20, 0x88, 0x92, 0x78, 0x7c, 0xc0, 0xfb, 0xb2, 0x1a, 0x6a, 0x94, 0x7c, 0x2c, + 0x1b, 0xa9, 0xf4, 0x4a, 0xf4, 0x77, 0x63, 0x2e, 0x31, 0xe0, 0x75, 0xd5, 0x16, 0x14, 0xce, 0xf3, 0xc3, 0xe1, 0x3c, + 0x1f, 0x19, 0xcf, 0x32, 0x50, 0xad, 0x4c, 0xeb, 0x20, 0x36, 0xf3, 0xc5, 0xc2, 0x5f, 0xec, 0x9c, 0x44, 0x44, 0x41, + 0x60, 0x47, 0xc2, 0x83, 0x48, 0xfd, 0xaa, 0xf2, 0x74, 0xa7, 0xfa, 0x6c, 0xbf, 0xb0, 0x89, 0xf4, 0x82, 0x92, 0xc9, + 0x27, 0xc1, 0x5e, 0xf5, 0x77, 0x10, 0x36, 0x84, 0x37, 0xaf, 0x7a, 0x9d, 0x65, 0x6a, 0x56, 0x82, 0x84, 0x19, 0x73, + 0x04, 0x8f, 0xc3, 0x4e, 0x63, 0x1b, 0x1e, 0x5b, 0x70, 0x74, 0xde, 0x9a, 0xdd, 0xb1, 0x15, 0xbb, 0x55, 0x75, 0x5a, + 0xf0, 0x70, 0x3a, 0xbc, 0x0c, 0x70, 0xf5, 0xad, 0xcf, 0x39, 0xbf, 0xa3, 0x13, 0x6c, 0x3d, 0xe0, 0xd1, 0x44, 0xcc, + 0xd6, 0x4f, 0x23, 0xb5, 0x78, 0xd6, 0x43, 0xbe, 0xa0, 0xf5, 0x27, 0x66, 0x77, 0x26, 0xf9, 0x6e, 0xc0, 0x17, 0x93, + 0xf5, 0xd3, 0x08, 0x5e, 0x7d, 0x0a, 0x56, 0x8c, 0xcc, 0x99, 0x65, 0xeb, 0xa7, 0x11, 0x8e, 0xd9, 0xdd, 0xd3, 0x88, + 0x46, 0x6d, 0x25, 0xf7, 0xa5, 0xdb, 0x06, 0x84, 0x95, 0x5b, 0x16, 0xc3, 0x6b, 0x20, 0x9e, 0x69, 0x23, 0xe9, 0x5a, + 0x1a, 0x7a, 0x63, 0x1e, 0x4e, 0xe3, 0x60, 0x4d, 0xad, 0x90, 0x67, 0x86, 0x98, 0xc5, 0x4f, 0xa3, 0x39, 0x5b, 0x61, + 0x45, 0x36, 0x3c, 0x1e, 0x5c, 0x4e, 0x36, 0x57, 0x7c, 0x0d, 0xe4, 0x67, 0x93, 0x8d, 0xd9, 0xa2, 0x6e, 0xb9, 0x98, + 0x6d, 0x9e, 0x46, 0xf3, 0xc9, 0x0a, 0x7a, 0xd6, 0x1e, 0x30, 0xef, 0x0d, 0x88, 0x50, 0x12, 0x52, 0x53, 0x6e, 0x7a, + 0x3d, 0xb6, 0x1e, 0x07, 0x77, 0x6c, 0x7d, 0x19, 0xdc, 0xb2, 0xf5, 0x18, 0x88, 0x38, 0xa8, 0xdf, 0xbd, 0x0d, 0x2c, + 0xbe, 0x88, 0xad, 0x2f, 0x4d, 0xda, 0xe6, 0x69, 0xc4, 0xdc, 0xc1, 0x69, 0xe0, 0x82, 0xb5, 0xc9, 0xbc, 0x15, 0x83, + 0x4b, 0xc8, 0xd2, 0x8b, 0xd9, 0x66, 0x78, 0xc9, 0xd6, 0x23, 0x9c, 0xea, 0x89, 0xcf, 0xee, 0xf8, 0x2d, 0x4b, 0xf8, + 0xaa, 0x89, 0xaf, 0x36, 0xa0, 0x11, 0x3d, 0xca, 0xa0, 0xaf, 0xa0, 0x66, 0xe6, 0xbc, 0xb2, 0x30, 0x2a, 0xf7, 0x2d, + 0x38, 0xa0, 0x20, 0x6d, 0x03, 0x04, 0x49, 0x3c, 0xbb, 0x57, 0xe1, 0xfa, 0x46, 0x0a, 0x03, 0x6e, 0x02, 0x33, 0x60, + 0x60, 0xfa, 0x19, 0xfc, 0xb0, 0xd2, 0x25, 0x42, 0x9c, 0xfd, 0x94, 0x92, 0x64, 0x9e, 0x9f, 0x8a, 0x34, 0x77, 0x0b, + 0xd7, 0x29, 0xcc, 0x8a, 0x02, 0xd5, 0x4f, 0x49, 0x69, 0x60, 0xa1, 0x12, 0x99, 0x4a, 0xc1, 0x2f, 0x9b, 0xf3, 0x28, + 0x3b, 0x46, 0xe7, 0x3a, 0xbf, 0x9c, 0x38, 0xa7, 0x93, 0xbe, 0xff, 0xc0, 0x31, 0x6c, 0x21, 0x03, 0x17, 0xfe, 0xd4, + 0x13, 0xc6, 0xa9, 0x15, 0x88, 0xa9, 0xe4, 0xd9, 0x53, 0xf8, 0x4c, 0x68, 0x75, 0x74, 0xe1, 0xfb, 0x41, 0xa1, 0x4d, + 0xd2, 0x2d, 0x48, 0x52, 0xf0, 0x14, 0x3d, 0xe7, 0xbc, 0x0d, 0x54, 0x8a, 0x11, 0x2d, 0x88, 0xb4, 0xb5, 0xcc, 0x1c, + 0xa4, 0x2d, 0xcd, 0x77, 0x4d, 0xfc, 0x1c, 0x16, 0x70, 0x11, 0x2d, 0x6c, 0x0d, 0x8f, 0xaa, 0x58, 0xb9, 0x37, 0x79, + 0x8e, 0x70, 0x46, 0x97, 0x32, 0x01, 0x70, 0xbd, 0x5f, 0x87, 0xb5, 0xc2, 0x2b, 0x6a, 0x16, 0x79, 0x51, 0xd3, 0x27, + 0x5b, 0xe0, 0x3e, 0x16, 0x25, 0x0a, 0x9c, 0xb5, 0x60, 0xc0, 0x56, 0x58, 0xb2, 0x93, 0xc2, 0xa6, 0x68, 0x09, 0xbd, + 0x3d, 0x7e, 0x3a, 0xa8, 0x99, 0x0c, 0xa0, 0x09, 0xa0, 0xf1, 0xf8, 0x17, 0x80, 0x9a, 0xde, 0xd4, 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, 0x83, 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, 0x8b, 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, 0xb5, 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, 0x4e, 0x6e, 0x61, 0xcb, 0x4c, + 0x56, 0xf3, 0x7d, 0xc5, 0x1d, 0x94, 0x6f, 0xb6, 0xce, 0xf8, 0x5e, 0x22, 0x7b, 0xb7, 0x81, 0x12, 0x5e, 0x8c, 0xfe, + 0x82, 0xf4, 0xdb, 0x0c, 0xe3, 0x94, 0xdb, 0x4a, 0x5a, 0x80, 0xd3, 0x3f, 0x1c, 0xde, 0x57, 0x18, 0x34, 0x38, 0xc2, + 0x38, 0xb2, 0x7e, 0xff, 0xb6, 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, 0x9f, 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, 0x3a, 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, 0xeb, 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, 0x4f, 0x9f, + 0x03, 0x69, 0x59, 0xbf, 0x1f, 0xbd, 0xb8, 0x9c, 0x3e, 0x1f, 0x46, 0x01, 0x38, 0x76, 0xd9, 0xcb, 0xcb, 0x98, 0xaf, + 0x2e, 0x99, 0x65, 0x0a, 0x8b, 0x7c, 0x33, 0xa0, 0xba, 0x64, 0xb5, 0x74, 0xbd, 0x02, 0x2c, 0x5d, 0x7e, 0xf3, 0x10, + 0xa6, 0x06, 0x34, 0xb2, 0xe6, 0xee, 0x34, 0xd7, 0x02, 0xa5, 0x9e, 0xf7, 0x33, 0x43, 0xbe, 0x2e, 0x83, 0xae, 0x20, + 0xdd, 0xf3, 0x88, 0xf4, 0x72, 0x2f, 0x9d, 0xee, 0xf7, 0xa5, 0x00, 0x4b, 0x7d, 0x29, 0x3e, 0x83, 0xc2, 0xa2, 0xf1, + 0x8d, 0x00, 0x6d, 0x0d, 0xd5, 0xb4, 0x57, 0x8a, 0xaa, 0x17, 0xf4, 0x4a, 0xf1, 0xb9, 0xa7, 0x87, 0xca, 0x7c, 0x59, + 0x3a, 0xfa, 0x9f, 0x50, 0x73, 0xc1, 0x09, 0x31, 0x13, 0x73, 0x00, 0x95, 0xa0, 0x8d, 0x6f, 0x75, 0xb4, 0xf1, 0xa9, + 0x5e, 0xc5, 0x4d, 0x9f, 0xd7, 0xd6, 0x32, 0x27, 0x84, 0x4d, 0xf7, 0x12, 0xa0, 0x22, 0xaf, 0x84, 0x47, 0xb0, 0xfc, + 0xf2, 0x87, 0x3c, 0x5d, 0x21, 0x5a, 0xc7, 0x3d, 0xcb, 0x5c, 0x1a, 0xfb, 0x37, 0x06, 0xd3, 0xd7, 0xb7, 0xdb, 0x22, + 0x3f, 0x35, 0x31, 0x61, 0x3d, 0x56, 0xf4, 0xcd, 0xbb, 0x70, 0x25, 0x50, 0xe0, 0x50, 0x22, 0xb1, 0x4d, 0x15, 0x8a, + 0x78, 0x90, 0xf4, 0xe9, 0xa2, 0xf5, 0x69, 0x80, 0xa9, 0xb5, 0x1c, 0x98, 0x43, 0xb8, 0x8a, 0x0b, 0x1f, 0x3d, 0x7d, + 0x8b, 0x59, 0x38, 0x9f, 0x78, 0x1f, 0xbd, 0x62, 0x64, 0x3e, 0xee, 0xa3, 0x52, 0x49, 0xff, 0x3c, 0x1c, 0x66, 0xd5, + 0xdc, 0x77, 0xe8, 0x23, 0x3d, 0x54, 0xb9, 0xa0, 0xec, 0x8d, 0x31, 0x89, 0x40, 0x69, 0x8c, 0xf7, 0x71, 0x70, 0x9c, + 0xf7, 0x69, 0x00, 0xa9, 0x7d, 0xe2, 0x3d, 0x29, 0x39, 0x3c, 0xe7, 0x98, 0x13, 0x4a, 0x2b, 0xc2, 0x2a, 0xbe, 0xc8, + 0x50, 0xae, 0x3b, 0xa5, 0x60, 0x92, 0x43, 0x82, 0xe1, 0xaf, 0x9a, 0x37, 0xb1, 0x02, 0x61, 0xd7, 0xcc, 0xab, 0xd1, + 0x93, 0x2a, 0x09, 0x4b, 0x01, 0x47, 0x65, 0xe6, 0x19, 0xf6, 0x86, 0x27, 0x86, 0x91, 0x83, 0xe5, 0xfe, 0xa8, 0x4e, + 0x44, 0xee, 0xd1, 0x05, 0x46, 0x65, 0xe1, 0x79, 0x43, 0x57, 0x1a, 0x54, 0x92, 0x1d, 0x7f, 0xc5, 0x35, 0xa0, 0xb6, + 0xc6, 0x88, 0xa1, 0x80, 0x51, 0xf0, 0xda, 0xfe, 0x10, 0xb2, 0x28, 0x5b, 0xbf, 0xc1, 0x31, 0x9f, 0x95, 0xdc, 0xf5, + 0x0e, 0x67, 0xa1, 0x25, 0xe4, 0xc9, 0x1d, 0x83, 0x34, 0x8d, 0xa5, 0x11, 0x70, 0x22, 0x92, 0x6d, 0x2c, 0x85, 0x23, + 0x80, 0x80, 0x40, 0x37, 0x65, 0x86, 0x31, 0x1d, 0x8c, 0x3c, 0x4f, 0x7a, 0xc6, 0x7b, 0x15, 0x9e, 0x42, 0x9a, 0x6c, + 0x5f, 0xcf, 0xdf, 0x1b, 0x41, 0x56, 0x6e, 0x39, 0xc7, 0xc3, 0xe2, 0x1b, 0x67, 0x5f, 0xe5, 0xe4, 0x29, 0x66, 0x19, + 0xe9, 0x9d, 0x62, 0x5e, 0xc0, 0x9f, 0xca, 0x52, 0x9f, 0xa3, 0xf4, 0x96, 0xf9, 0x64, 0x15, 0x49, 0x97, 0xde, 0xa6, + 0xdf, 0x8f, 0x47, 0xea, 0x50, 0xf3, 0xf7, 0xf1, 0x48, 0x9e, 0x61, 0x1b, 0x96, 0xb0, 0xd0, 0x2a, 0x18, 0x03, 0x48, + 0x62, 0x23, 0xa2, 0xc1, 0x68, 0x6f, 0x0e, 0x87, 0xf3, 0x8d, 0x39, 0x4b, 0xf6, 0xe0, 0xfa, 0xca, 0x13, 0xf3, 0x0e, + 0x7c, 0x99, 0xc7, 0x04, 0x11, 0x9b, 0x79, 0x1b, 0x56, 0x83, 0x07, 0x3b, 0xb8, 0x3e, 0x62, 0x8b, 0x62, 0xad, 0x63, + 0xa9, 0xac, 0x83, 0xd3, 0x3a, 0x36, 0xcd, 0x48, 0x29, 0xb2, 0xcf, 0xb1, 0xbf, 0x77, 0x83, 0xab, 0x6b, 0x63, 0x50, + 0x6b, 0xdc, 0x61, 0xee, 0x9c, 0x0a, 0xa8, 0xc7, 0x74, 0x05, 0xd5, 0xb3, 0x9c, 0x7c, 0xf9, 0xad, 0x9d, 0x03, 0x82, + 0x46, 0x20, 0x70, 0xd1, 0x40, 0xab, 0x76, 0x29, 0xe7, 0x5d, 0x40, 0x88, 0x6f, 0x52, 0xd0, 0xa7, 0x33, 0xd8, 0xc4, + 0xe6, 0x13, 0x88, 0x45, 0xd3, 0x7d, 0xae, 0x35, 0xf3, 0xc5, 0x88, 0x76, 0x66, 0xdd, 0x2d, 0x72, 0xab, 0x85, 0x48, + 0x46, 0xcf, 0x36, 0x13, 0x2e, 0x3a, 0x94, 0x33, 0x12, 0x30, 0x41, 0x6b, 0x2b, 0x25, 0x9f, 0xeb, 0x5e, 0x27, 0x68, + 0x0f, 0x24, 0xad, 0xfb, 0x37, 0x8b, 0xce, 0x28, 0x39, 0xb9, 0xde, 0xe4, 0x0c, 0x52, 0xb0, 0x60, 0x7b, 0x99, 0x13, + 0x6e, 0x80, 0x4f, 0x6c, 0x96, 0x9c, 0xa6, 0x41, 0x1e, 0x0b, 0xe3, 0x91, 0xd7, 0xe6, 0x97, 0x05, 0x74, 0x28, 0x59, + 0x34, 0x42, 0x3c, 0xc0, 0xce, 0x21, 0xb9, 0x2a, 0x50, 0x37, 0x0d, 0x74, 0xe5, 0xca, 0x99, 0x62, 0x0a, 0x5c, 0x08, + 0x05, 0x51, 0x3b, 0x3a, 0x89, 0xca, 0x79, 0x9f, 0x54, 0x97, 0xf9, 0xb4, 0x90, 0xa6, 0x81, 0x7c, 0x5a, 0x39, 0xe6, + 0x81, 0x9d, 0x6d, 0x5c, 0x13, 0x18, 0xe8, 0xd4, 0xbe, 0x16, 0xe5, 0x1c, 0xab, 0x88, 0xde, 0xe7, 0x1f, 0x2a, 0x7b, + 0xfa, 0x20, 0xc2, 0x46, 0x05, 0x1a, 0x4b, 0x89, 0xb1, 0x91, 0xe3, 0xdf, 0x12, 0x65, 0x43, 0x86, 0x80, 0x10, 0xd2, + 0x46, 0x4e, 0x3f, 0xac, 0x2f, 0x6f, 0x33, 0xed, 0xff, 0x49, 0xe2, 0xb7, 0xc1, 0x5e, 0x4e, 0xfd, 0xa9, 0x47, 0x3c, + 0x5e, 0x6b, 0xf4, 0x98, 0x92, 0x6e, 0x83, 0x3c, 0x55, 0x9e, 0x82, 0x64, 0xc2, 0x58, 0x42, 0xb0, 0x28, 0x17, 0x3c, + 0xe7, 0x15, 0x97, 0x70, 0x1f, 0xb5, 0xac, 0x88, 0x50, 0x95, 0xc8, 0xe9, 0xf3, 0x15, 0xf0, 0x4c, 0x40, 0xa0, 0x63, + 0x8c, 0x34, 0xaa, 0xe0, 0x4b, 0x60, 0xac, 0x03, 0x65, 0xa7, 0x19, 0x09, 0x2e, 0xbb, 0x37, 0x48, 0x94, 0xfa, 0x9a, + 0x94, 0xa4, 0xd7, 0xa2, 0xc6, 0x2b, 0xb1, 0x8a, 0x48, 0x20, 0x43, 0x0d, 0x11, 0xab, 0xea, 0xa9, 0x7b, 0x55, 0x4c, + 0x06, 0x83, 0xca, 0x97, 0xd3, 0x13, 0x6f, 0x68, 0xa8, 0xbc, 0xeb, 0x8a, 0x76, 0x7a, 0xa2, 0x95, 0xf2, 0x16, 0xd2, + 0x12, 0x34, 0x0d, 0x23, 0xcd, 0xa1, 0xd4, 0x95, 0x74, 0x37, 0x06, 0xf1, 0x25, 0x13, 0x3d, 0xdb, 0xa9, 0x1d, 0xa5, + 0x2d, 0x69, 0x0f, 0x21, 0x3d, 0x77, 0xc9, 0xc7, 0x2c, 0xe4, 0xea, 0x4e, 0x39, 0x29, 0xaf, 0x42, 0x74, 0x72, 0xdf, + 0x63, 0x48, 0x04, 0xfa, 0x9c, 0x63, 0x58, 0x17, 0x0d, 0x75, 0x0e, 0x2b, 0xc4, 0x6c, 0xa1, 0x84, 0xf9, 0x92, 0xf1, + 0x54, 0x32, 0x68, 0x00, 0x64, 0xc0, 0x67, 0x2f, 0x03, 0xcb, 0x5f, 0x41, 0xfc, 0x68, 0xe3, 0xc3, 0xe1, 0xcf, 0x9a, + 0x42, 0x6c, 0xff, 0x84, 0xcd, 0x10, 0x1e, 0xd5, 0x03, 0x9e, 0xf9, 0x26, 0x4e, 0xd0, 0x0a, 0x48, 0xca, 0xec, 0x68, + 0x22, 0x7b, 0xd5, 0x43, 0x38, 0x95, 0x15, 0xa8, 0xa3, 0xac, 0xb3, 0x12, 0x7e, 0x84, 0xa9, 0x6e, 0x25, 0xd6, 0x02, + 0x6d, 0xae, 0x56, 0xac, 0x05, 0x70, 0xe0, 0xe7, 0x10, 0x3c, 0x91, 0xcf, 0xc1, 0xc5, 0xa0, 0x00, 0x9f, 0x03, 0xe0, + 0x45, 0xee, 0xc2, 0x83, 0x79, 0x64, 0x59, 0x8d, 0x30, 0x1c, 0x55, 0xc4, 0xfa, 0x35, 0xdb, 0x91, 0x0f, 0xdc, 0x8e, + 0xf1, 0xb9, 0xf6, 0x58, 0xb2, 0x1c, 0x8c, 0x32, 0xf7, 0x6a, 0x89, 0x9e, 0x37, 0x69, 0xdc, 0x8c, 0x9e, 0xec, 0x6b, + 0xf9, 0xbf, 0xa0, 0x97, 0x41, 0x7f, 0x0b, 0xb7, 0xbc, 0xe6, 0x77, 0x0b, 0x22, 0xcd, 0xf4, 0x0a, 0x22, 0x65, 0xd4, + 0x88, 0x8c, 0x21, 0x6c, 0x52, 0xdd, 0xdc, 0x26, 0xd5, 0x85, 0x80, 0xa7, 0x23, 0x52, 0x5d, 0x0b, 0x69, 0x23, 0x9f, + 0xd6, 0x81, 0x8c, 0x45, 0x7a, 0xf7, 0xc3, 0xdf, 0x5e, 0x7e, 0x7a, 0xfb, 0xcb, 0x0f, 0x8b, 0xb7, 0xef, 0xde, 0xbc, + 0x7d, 0xf7, 0xf6, 0xd3, 0x6f, 0x04, 0xe1, 0x31, 0x15, 0x2a, 0xc3, 0x87, 0xf7, 0x37, 0x6f, 0x9d, 0x0c, 0xb6, 0x37, + 0x43, 0xd6, 0xbe, 0x91, 0x83, 0x21, 0x10, 0xd9, 0x20, 0x64, 0x90, 0x9d, 0xda, 0xf6, 0x67, 0x62, 0x8e, 0xb1, 0x77, + 0x02, 0x93, 0x2d, 0xe0, 0x1c, 0xcb, 0xbc, 0x64, 0x44, 0xae, 0x0a, 0xad, 0x1f, 0xd0, 0x82, 0x6b, 0x70, 0x91, 0x49, + 0xf3, 0xbb, 0x5f, 0x08, 0x62, 0x9f, 0x56, 0x52, 0xee, 0xab, 0x6d, 0xcd, 0xf3, 0xed, 0xfd, 0x5e, 0xc2, 0xf9, 0xcf, + 0xa5, 0x11, 0xb5, 0x00, 0x07, 0xe0, 0x73, 0xf8, 0xe3, 0x4a, 0x5b, 0xd2, 0x64, 0x16, 0xed, 0x67, 0x0c, 0x41, 0x97, + 0x06, 0x1f, 0xc4, 0x1e, 0x79, 0xa9, 0x4f, 0x16, 0x12, 0xb8, 0x23, 0x86, 0x4f, 0x2b, 0x82, 0x5e, 0x31, 0xa2, 0xb8, + 0xe4, 0x0a, 0x95, 0x52, 0xf2, 0x6f, 0x94, 0x5d, 0x54, 0xc8, 0x59, 0xc1, 0xee, 0x15, 0x39, 0x32, 0x7e, 0x10, 0x4c, + 0x7c, 0x39, 0xb8, 0xff, 0x12, 0xef, 0x70, 0xa6, 0x38, 0x92, 0x13, 0xfe, 0x90, 0x61, 0x60, 0x7f, 0x0e, 0x3e, 0xaf, + 0x0e, 0xf3, 0xf2, 0x46, 0x9f, 0x72, 0x4b, 0x3e, 0x9e, 0x2c, 0xaf, 0xc0, 0x60, 0xbf, 0x54, 0xcd, 0x5d, 0xf3, 0x7a, + 0xb6, 0x9c, 0xb3, 0xfd, 0x2c, 0x9a, 0x07, 0x77, 0x6c, 0x96, 0xcd, 0x83, 0x55, 0xc3, 0xd7, 0xec, 0x96, 0xaf, 0xad, + 0xaa, 0xad, 0xed, 0xaa, 0x4d, 0x36, 0xfc, 0x16, 0x24, 0x84, 0x9b, 0xcc, 0x03, 0xde, 0xe3, 0x3b, 0x9f, 0x6d, 0x40, + 0xa2, 0x5d, 0xb1, 0x0d, 0x5c, 0xc4, 0xd6, 0xfc, 0x87, 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, 0x7d, 0x5a, 0x6d, 0xc2, + 0x0c, 0x3d, 0xcb, 0xe1, 0xa3, 0xad, 0x14, 0xfc, 0xf4, 0x02, 0xbf, 0x64, 0x47, 0x6d, 0xa5, 0x6d, 0xbb, 0x2a, 0xb1, + 0x15, 0xb4, 0x28, 0xb2, 0x5a, 0xe1, 0x81, 0x39, 0x7f, 0x01, 0x0b, 0x18, 0x7b, 0x8e, 0x73, 0x5e, 0xfb, 0x23, 0x64, + 0xbc, 0x77, 0x00, 0xd0, 0x32, 0xc7, 0x01, 0x1e, 0xb1, 0x62, 0x14, 0x0d, 0xde, 0xf9, 0xa5, 0xb2, 0x5a, 0x69, 0x4e, + 0x42, 0xdb, 0x88, 0x55, 0xcb, 0x91, 0xaa, 0x19, 0x91, 0x3e, 0x48, 0xcf, 0xfb, 0x1e, 0x51, 0x0d, 0xf6, 0x64, 0x5e, + 0x07, 0xf6, 0xe9, 0x55, 0x6b, 0x55, 0x77, 0x7e, 0x4f, 0x95, 0x2e, 0x39, 0xb2, 0xe5, 0xa7, 0xcb, 0xf0, 0x41, 0xfd, + 0x29, 0xb9, 0x3e, 0x14, 0x38, 0xc2, 0x63, 0x15, 0x70, 0xbe, 0x5e, 0x89, 0x76, 0x27, 0xc2, 0xae, 0x5c, 0x02, 0x42, + 0x7c, 0x49, 0xd3, 0x1c, 0x8f, 0x23, 0x9a, 0x88, 0xb0, 0x89, 0xd1, 0x5f, 0xd8, 0x7d, 0x28, 0xb1, 0x9c, 0xe7, 0x1a, + 0x94, 0x5c, 0x32, 0x78, 0x4f, 0xda, 0x6b, 0xd0, 0x2c, 0xaf, 0x4a, 0x4d, 0x26, 0x72, 0x50, 0x3e, 0x1c, 0x0a, 0xd8, + 0x4b, 0x8d, 0x9f, 0x26, 0xfc, 0x84, 0xe5, 0xad, 0xbd, 0x35, 0xa5, 0xa8, 0xa4, 0x01, 0x2a, 0xf0, 0x31, 0x83, 0xff, + 0xdd, 0x19, 0x62, 0xc1, 0x14, 0x1d, 0x3f, 0x9c, 0x89, 0xb9, 0xf5, 0xdc, 0x2a, 0xeb, 0x28, 0x5b, 0xa3, 0x9c, 0x80, + 0x7f, 0x4b, 0x75, 0x9c, 0x24, 0xc2, 0xa9, 0xf7, 0x88, 0x8b, 0xba, 0x97, 0x43, 0xd4, 0x0d, 0x7b, 0x5b, 0xe9, 0x60, + 0xcb, 0x69, 0x1a, 0x1c, 0x89, 0x5f, 0xa9, 0xcf, 0xde, 0x67, 0x16, 0x8f, 0x3a, 0xb2, 0x11, 0x25, 0x69, 0x1c, 0x8b, + 0x1c, 0xb6, 0xf7, 0x85, 0xdc, 0xff, 0xfb, 0x7d, 0x08, 0x27, 0xad, 0x82, 0xa4, 0xf4, 0x04, 0x22, 0xc2, 0xd1, 0xe1, + 0x47, 0x84, 0x27, 0x52, 0x55, 0xf8, 0xa4, 0x3e, 0x71, 0x63, 0x76, 0x2f, 0xcc, 0x51, 0xbd, 0x05, 0x18, 0xc6, 0x7a, + 0x6b, 0x11, 0x92, 0x68, 0xa5, 0x19, 0x6d, 0x3d, 0x20, 0x46, 0xbc, 0x5f, 0x5b, 0x64, 0x30, 0xd6, 0x96, 0x44, 0x02, + 0xf8, 0x1d, 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, 0xeb, 0xa3, 0x74, 0x92, 0x58, 0xdf, + 0x77, 0x95, 0x0a, 0x36, 0x9b, 0x1b, 0xd4, 0x97, 0x1d, 0x25, 0xbf, 0x02, 0x27, 0x1d, 0x27, 0x59, 0xe4, 0x20, 0x6a, + 0x51, 0x39, 0x37, 0x49, 0x58, 0xda, 0xd5, 0xa9, 0x36, 0xeb, 0x75, 0x51, 0xd6, 0xd5, 0x6b, 0x11, 0x29, 0x7a, 0x1f, + 0xf5, 0xe8, 0x89, 0x84, 0x54, 0x68, 0x55, 0x6a, 0x97, 0x47, 0xe0, 0xb6, 0xa9, 0x15, 0xdb, 0x72, 0x09, 0x4b, 0xd4, + 0xf8, 0x4f, 0xd0, 0x47, 0xb9, 0x78, 0x90, 0x01, 0x1a, 0x1d, 0x4f, 0xcd, 0x5b, 0x8f, 0xbc, 0x72, 0x94, 0x5f, 0x5a, + 0x6d, 0xd2, 0x2f, 0x80, 0xcc, 0x68, 0xff, 0x68, 0x29, 0x81, 0xcc, 0xc0, 0x4c, 0x5a, 0x1a, 0x12, 0x39, 0x8a, 0x59, + 0x9a, 0xff, 0x81, 0x2b, 0xb6, 0x42, 0xa4, 0x61, 0x35, 0xf7, 0xf8, 0xcb, 0xca, 0xab, 0xe5, 0x5a, 0x66, 0x9a, 0x9b, + 0x25, 0x8e, 0x15, 0x8b, 0x8b, 0x7a, 0x5d, 0x89, 0x2c, 0x10, 0xe2, 0x08, 0xd3, 0x58, 0x4f, 0xbd, 0x51, 0x5a, 0x7d, + 0x40, 0x42, 0x99, 0x1f, 0xb0, 0xb7, 0x63, 0xaf, 0x07, 0x59, 0x88, 0x63, 0xcb, 0xc1, 0x66, 0xeb, 0x7d, 0x2a, 0x53, + 0x11, 0x9f, 0xd5, 0xc5, 0xd9, 0xa6, 0x12, 0x67, 0x75, 0x22, 0xce, 0xbe, 0x83, 0x9c, 0xdf, 0x9d, 0x51, 0xd1, 0x67, + 0x0f, 0x69, 0x9d, 0x14, 0x9b, 0x9a, 0x9e, 0xbc, 0xc1, 0x32, 0xbe, 0x3b, 0x23, 0xae, 0x9a, 0x33, 0x1a, 0xc9, 0x78, + 0x74, 0xf6, 0x21, 0x03, 0x92, 0xd7, 0xb3, 0x74, 0x05, 0x83, 0x77, 0x16, 0xe6, 0xf1, 0x59, 0x29, 0xee, 0xc0, 0xe2, + 0x54, 0x76, 0xbe, 0x07, 0x19, 0x56, 0xe1, 0x1f, 0xe2, 0x0c, 0xa0, 0x5d, 0xcf, 0xd2, 0xfa, 0x2c, 0xad, 0xce, 0xf2, + 0xa2, 0x3e, 0x53, 0x52, 0x38, 0x84, 0xf1, 0xc3, 0x7b, 0xfa, 0xca, 0x2e, 0x6f, 0xb3, 0xb8, 0xcb, 0x22, 0x7f, 0x8a, + 0x5e, 0x45, 0xc4, 0xa4, 0x51, 0x09, 0xaf, 0xdd, 0xdf, 0x36, 0xf7, 0x0f, 0xaf, 0x1b, 0xbb, 0x9f, 0xdd, 0x31, 0xa2, + 0x0b, 0xea, 0xf1, 0x4a, 0x52, 0x2a, 0x28, 0x20, 0x70, 0xa2, 0x59, 0xe3, 0xc1, 0x1d, 0x07, 0xbc, 0x1a, 0xd8, 0x92, + 0xad, 0x7d, 0xfe, 0x22, 0x96, 0x61, 0xda, 0x9b, 0x00, 0xff, 0x2a, 0x7b, 0xd3, 0x75, 0xb0, 0xc4, 0xfb, 0x16, 0xb2, + 0x0d, 0xbd, 0x7d, 0xcd, 0x5f, 0x7a, 0xb9, 0xfa, 0x9b, 0xfd, 0x13, 0x80, 0x30, 0x20, 0x66, 0xd5, 0x47, 0x13, 0xf7, + 0xce, 0xca, 0xb2, 0x73, 0xb2, 0xec, 0x7a, 0xe8, 0xd7, 0x24, 0x46, 0xa5, 0x95, 0xa5, 0x74, 0xb2, 0x94, 0x90, 0x05, + 0x7c, 0x62, 0x34, 0xb5, 0x11, 0x40, 0xd8, 0x8e, 0x52, 0xf9, 0x42, 0xe5, 0x45, 0x14, 0xce, 0x09, 0x9e, 0x27, 0x62, + 0x74, 0x6f, 0x25, 0x03, 0x86, 0x43, 0x08, 0xe6, 0xa0, 0x2d, 0xf6, 0x86, 0x6e, 0x22, 0xfe, 0x7a, 0x53, 0x94, 0x6f, + 0x63, 0xf2, 0x29, 0xd8, 0x9d, 0x7c, 0x5c, 0xc2, 0xe3, 0xf2, 0xe4, 0xe3, 0x10, 0x3d, 0x12, 0x4e, 0x3e, 0x06, 0xdf, + 0x23, 0x39, 0xaf, 0xbb, 0x1e, 0x27, 0xc8, 0x2d, 0xa4, 0xfb, 0xdb, 0x31, 0x09, 0xd0, 0xbc, 0x86, 0xe5, 0xa8, 0xa9, + 0xb8, 0x66, 0x66, 0x8c, 0xe7, 0x8d, 0xde, 0x1f, 0x3b, 0xde, 0x32, 0x85, 0x62, 0x16, 0xf3, 0x1a, 0x7e, 0xcf, 0xaa, + 0x40, 0xdd, 0xf5, 0x36, 0xc9, 0x2d, 0xb3, 0x7a, 0x8e, 0x76, 0xdf, 0xf7, 0x75, 0x22, 0xa8, 0xfd, 0x1d, 0xf6, 0x3c, + 0xb3, 0xde, 0x55, 0x31, 0x70, 0xa9, 0x92, 0x1d, 0x32, 0x55, 0x4d, 0x0f, 0x54, 0x4a, 0x83, 0xa7, 0x97, 0xd6, 0xe5, + 0x4b, 0xa5, 0x8d, 0x3c, 0xd3, 0xfc, 0x06, 0xf0, 0x62, 0xea, 0xb2, 0xd8, 0x7d, 0x75, 0x5f, 0xc1, 0x6d, 0xbc, 0xdf, + 0x5f, 0x56, 0x9e, 0xf9, 0x89, 0x0b, 0xc0, 0xde, 0x54, 0x68, 0x9d, 0x40, 0xa9, 0x61, 0x1d, 0xbe, 0x4a, 0x44, 0xf4, + 0x47, 0xbb, 0x5c, 0x67, 0xae, 0x03, 0x46, 0x14, 0xf1, 0xdb, 0x78, 0xf4, 0x07, 0x28, 0xae, 0x8d, 0x3d, 0x20, 0xac, + 0x43, 0x42, 0x9f, 0x11, 0x80, 0xd4, 0x63, 0x8e, 0x12, 0xd0, 0xac, 0x68, 0xee, 0x98, 0xfc, 0x5c, 0x5f, 0x29, 0xfd, + 0xfd, 0xb2, 0xf2, 0xc8, 0x9c, 0xd2, 0x36, 0xd3, 0x58, 0xad, 0xa9, 0x04, 0xc2, 0x2b, 0x2a, 0x59, 0x85, 0xcf, 0xe6, + 0x8d, 0xe8, 0xf7, 0xe5, 0x11, 0x9e, 0x56, 0x3f, 0x6c, 0x31, 0xbe, 0x15, 0x10, 0x8d, 0x04, 0x40, 0x3f, 0x01, 0xcc, + 0x8b, 0x6c, 0x66, 0xf7, 0x71, 0x40, 0x95, 0x12, 0x4d, 0xe3, 0x6c, 0x9e, 0xdf, 0xd2, 0x9b, 0xb2, 0x83, 0x4e, 0x9d, + 0x2a, 0x70, 0xc1, 0x55, 0xc9, 0x78, 0x65, 0x3d, 0x91, 0xcf, 0x6f, 0x6e, 0x37, 0x69, 0x16, 0xbf, 0x2f, 0xff, 0x89, + 0x63, 0xab, 0xeb, 0xf0, 0xc8, 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, 0x4d, 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, 0x1e, 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, 0x45, 0x85, 0x3a, 0x27, 0x96, 0xf1, 0x1a, 0x80, 0xb5, 0x73, 0xd5, 0xcf, + 0xb3, 0x1a, 0x3c, 0x69, 0x88, 0xcf, 0xc7, 0x68, 0x7b, 0x65, 0x73, 0x50, 0x6d, 0xa7, 0xb3, 0xf2, 0x8a, 0xe9, 0x72, + 0x60, 0xdc, 0x37, 0xbc, 0xa2, 0x38, 0xc3, 0x8f, 0x1e, 0x6c, 0x71, 0xfe, 0x74, 0x43, 0xed, 0xc7, 0xdc, 0xa8, 0x87, + 0x81, 0xd6, 0x82, 0x37, 0x05, 0xb1, 0xfe, 0x7e, 0xe8, 0xc8, 0xf6, 0x5e, 0x8b, 0x8c, 0x26, 0x9f, 0xfd, 0xfc, 0x43, + 0x99, 0xae, 0x52, 0xb8, 0x2f, 0x39, 0x59, 0x34, 0xf3, 0x10, 0xd8, 0x1b, 0x62, 0xb8, 0x3e, 0x2a, 0x3c, 0xa2, 0xac, + 0xdf, 0x87, 0xdf, 0x57, 0x19, 0x98, 0x62, 0xe0, 0xba, 0x42, 0x30, 0x1e, 0x02, 0x41, 0x3c, 0x4c, 0xa3, 0x93, 0x41, + 0x0d, 0xda, 0xf0, 0x0d, 0x40, 0x66, 0x80, 0x47, 0xe6, 0xd2, 0x23, 0xe0, 0x2e, 0x70, 0xed, 0xc9, 0x78, 0xec, 0x4f, + 0x4c, 0x43, 0xa3, 0xa6, 0x34, 0xd3, 0x73, 0xe3, 0x37, 0x1d, 0xd5, 0x72, 0xed, 0xfc, 0xc7, 0x97, 0xfc, 0x06, 0xbd, + 0xa0, 0xe5, 0xe5, 0x3e, 0x52, 0x97, 0xfb, 0x8c, 0xe2, 0x32, 0x91, 0x1c, 0x16, 0xc4, 0xb2, 0x84, 0x03, 0x8f, 0x51, + 0xc9, 0x62, 0x4b, 0x8f, 0x55, 0xd1, 0xf2, 0x45, 0xb9, 0x41, 0x3a, 0x74, 0x42, 0xb0, 0x44, 0x05, 0xc1, 0x12, 0x18, + 0x17, 0xb1, 0xe6, 0x9b, 0x41, 0xce, 0xe2, 0xd9, 0x66, 0xce, 0x91, 0xb0, 0x2e, 0x39, 0x1c, 0x0a, 0x09, 0x36, 0x93, + 0xcd, 0xd6, 0x73, 0xb6, 0xf6, 0x19, 0x28, 0x01, 0x4a, 0x99, 0x26, 0x28, 0x4d, 0x2b, 0xb6, 0xe2, 0xa6, 0x35, 0x58, + 0xad, 0xa6, 0x6c, 0x55, 0x53, 0x76, 0x4e, 0x53, 0x8e, 0x2a, 0x28, 0x39, 0xa1, 0x14, 0x65, 0x18, 0xc0, 0x88, 0x4d, + 0xa2, 0xab, 0x0c, 0x7d, 0xbc, 0x13, 0x1e, 0x41, 0x15, 0x11, 0xf9, 0x84, 0x21, 0x04, 0x26, 0xa2, 0xb8, 0x50, 0x85, + 0x62, 0x80, 0x8c, 0x48, 0x20, 0x98, 0xa8, 0xd4, 0x29, 0x30, 0x1f, 0x4d, 0x15, 0xc3, 0xa6, 0x3d, 0x51, 0xbe, 0xa5, + 0x8e, 0x7b, 0x94, 0x6d, 0xfe, 0x2e, 0x76, 0x41, 0x88, 0xdc, 0x8d, 0x3b, 0xf5, 0x33, 0xe2, 0xbd, 0xdd, 0x11, 0xc6, + 0x4f, 0x76, 0xdc, 0x22, 0x5c, 0x11, 0x6c, 0xa9, 0xe6, 0x10, 0x8b, 0x79, 0x35, 0x49, 0x50, 0xcb, 0x92, 0xf8, 0x1b, + 0x9e, 0x0c, 0x72, 0xb6, 0x04, 0x0f, 0xda, 0x39, 0xcb, 0x00, 0x7f, 0xc5, 0x6a, 0xd1, 0x6f, 0xb5, 0xb7, 0x04, 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, 0x8f, 0xbd, 0x04, 0x3b, 0x07, 0xbc, 0x81, 0xb4, 0x81, + 0x37, 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, 0x22, 0x01, + 0xc0, 0xa4, 0xce, 0x81, 0x38, 0x33, 0xc1, 0x2e, 0x4d, 0x22, 0xcb, 0xc7, 0x30, 0xbf, 0x13, 0x6f, 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, 0x52, 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, 0xd7, 0x90, 0x74, 0x6c, + 0xe0, 0xb4, 0xfa, 0x14, 0x7c, 0x90, 0xe4, 0x60, 0xa2, 0x0e, 0x5e, 0xee, 0x2f, 0xfd, 0x3e, 0x6c, 0xd9, 0xb9, 0x94, + 0xea, 0x58, 0xa9, 0xb7, 0x6d, 0xed, 0x07, 0xd1, 0x16, 0x1c, 0x59, 0xc4, 0xdf, 0x67, 0x88, 0x08, 0x66, 0x06, 0x11, + 0x76, 0x2d, 0xd4, 0xdd, 0x9e, 0x52, 0xcb, 0xa2, 0xde, 0xf6, 0x94, 0x52, 0xb7, 0x61, 0xf8, 0x6e, 0x82, 0x99, 0xe2, + 0x86, 0xff, 0x91, 0x79, 0xa1, 0xde, 0x78, 0x2c, 0x0a, 0x74, 0xcf, 0xdf, 0x2f, 0x79, 0x35, 0xdb, 0x28, 0x13, 0xe6, + 0x1d, 0x5f, 0xce, 0x42, 0xd9, 0xd5, 0xd2, 0xb8, 0xf3, 0xd9, 0x5b, 0xaa, 0xf9, 0xe0, 0x1f, 0x0e, 0x09, 0xc4, 0x1b, + 0xc5, 0x57, 0x77, 0x8d, 0xdc, 0xba, 0x26, 0x9b, 0xab, 0x12, 0x50, 0xbf, 0xcf, 0xd7, 0xb8, 0xdf, 0x62, 0xfd, 0xbb, + 0xa7, 0x41, 0xc6, 0x6a, 0x86, 0x2b, 0xa6, 0xf0, 0x29, 0x00, 0x0c, 0x0e, 0xa7, 0x82, 0xb4, 0xc0, 0x1b, 0x5e, 0x0e, + 0x2f, 0x27, 0x1b, 0x32, 0xe9, 0x6e, 0x7c, 0xe4, 0xce, 0x02, 0x55, 0xef, 0x37, 0x14, 0x27, 0x0d, 0x12, 0x8d, 0xbd, + 0x06, 0x5f, 0x66, 0x19, 0xe5, 0xa2, 0x89, 0xfb, 0x98, 0x7c, 0xa5, 0x07, 0x30, 0x57, 0xa1, 0x04, 0x88, 0x7e, 0x63, + 0x59, 0x6c, 0x44, 0xdb, 0x62, 0x03, 0x4b, 0xa9, 0x9a, 0xeb, 0xd5, 0xf4, 0xd9, 0x2b, 0xd1, 0xbc, 0x8f, 0x66, 0x9c, + 0xd2, 0x68, 0xc0, 0x71, 0x1a, 0x85, 0xdb, 0xf7, 0xf7, 0xa2, 0x5c, 0x66, 0x60, 0xc9, 0x56, 0xe1, 0x14, 0x97, 0x8d, + 0x3a, 0x23, 0x5e, 0xe6, 0xb1, 0x02, 0xe8, 0x78, 0x4c, 0x00, 0x54, 0x17, 0x04, 0x54, 0x44, 0x4b, 0xe9, 0xad, 0xd0, + 0x62, 0xa1, 0xde, 0x70, 0x94, 0xc2, 0x1f, 0xe9, 0xcf, 0x83, 0x7c, 0x0a, 0x40, 0xec, 0xfa, 0x38, 0x7a, 0x53, 0x94, + 0xf4, 0xa9, 0x62, 0x96, 0xcb, 0xc1, 0x04, 0x76, 0x75, 0x22, 0x43, 0xad, 0x20, 0x6f, 0xd5, 0x95, 0xb7, 0x32, 0x79, + 0x1b, 0xe3, 0x94, 0xfc, 0xc8, 0x4d, 0xc7, 0x1a, 0x31, 0xf0, 0xca, 0xd3, 0x3a, 0x4d, 0x90, 0x26, 0x17, 0xc0, 0x30, + 0xc4, 0xb7, 0x99, 0xf7, 0xd2, 0x73, 0xa4, 0x2a, 0x48, 0x66, 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, 0xcb, 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, 0xb5, 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, 0x17, 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, 0x57, 0x99, 0xbe, 0x85, 0x98, 0x28, 0xa7, 0x1a, 0x21, 0x71, 0xa5, 0x24, 0x11, 0x1f, + 0x2f, 0x5a, 0x56, 0x8c, 0xca, 0xf0, 0x81, 0x57, 0xaa, 0x7c, 0x75, 0xaa, 0xf2, 0x62, 0xa4, 0x6d, 0x09, 0xbc, 0x26, + 0xff, 0x10, 0xb9, 0xe6, 0xad, 0xaf, 0xbb, 0xca, 0xd0, 0x6b, 0x59, 0x81, 0x8e, 0x60, 0x2b, 0x4b, 0xc9, 0x01, 0x9f, + 0x54, 0x77, 0xd5, 0xaa, 0xf5, 0x39, 0x65, 0x1b, 0xe1, 0x26, 0xbf, 0x8e, 0x1d, 0x1c, 0x29, 0xbf, 0xc1, 0x73, 0x01, + 0xec, 0x35, 0x60, 0x6f, 0xce, 0x59, 0xd1, 0x3c, 0x3a, 0xa4, 0x6d, 0x81, 0x46, 0x66, 0x6e, 0xe7, 0xea, 0xbe, 0x2d, + 0x8f, 0xd2, 0x18, 0x22, 0xd3, 0x1e, 0x99, 0x0e, 0x36, 0xa3, 0xfc, 0xb7, 0x94, 0xdf, 0x2a, 0x1c, 0x03, 0xdf, 0x4e, + 0xbd, 0x03, 0xa8, 0x7a, 0xda, 0x20, 0x63, 0xcd, 0x30, 0xb4, 0xb2, 0xcb, 0xa5, 0xd0, 0x12, 0xb4, 0xd4, 0x4d, 0x10, + 0x9c, 0x1f, 0x11, 0xe5, 0x08, 0x40, 0x17, 0x29, 0x60, 0x82, 0x9f, 0xd2, 0x76, 0xf7, 0xfb, 0xeb, 0xd4, 0x23, 0xf7, + 0xae, 0x50, 0xa3, 0x84, 0x12, 0x8c, 0xfd, 0x44, 0x63, 0x06, 0x1d, 0x5d, 0x91, 0x13, 0x9e, 0xb5, 0x3a, 0xac, 0xeb, + 0xa6, 0x0c, 0xca, 0xe2, 0x98, 0x57, 0xd3, 0xd9, 0xef, 0x4f, 0xf6, 0x75, 0x83, 0x2c, 0xe4, 0xbf, 0xb3, 0x1e, 0x92, + 0x41, 0xf7, 0x20, 0x14, 0xa2, 0x37, 0x0f, 0x66, 0xf8, 0x1f, 0xdb, 0xf0, 0xec, 0x1b, 0x6e, 0xd4, 0x09, 0x60, 0x8e, + 0xb8, 0x5e, 0x7a, 0x8a, 0xb6, 0x1e, 0x6e, 0x81, 0x6c, 0x8d, 0x97, 0xb7, 0xf6, 0x1a, 0xc8, 0x29, 0x8e, 0xff, 0x8e, + 0x67, 0x6a, 0x65, 0x83, 0x9f, 0x9e, 0xb2, 0x1d, 0x78, 0x78, 0x11, 0x02, 0x8a, 0x61, 0xd9, 0xf8, 0x3b, 0xcb, 0x71, + 0x46, 0xff, 0xcd, 0x23, 0x86, 0xc1, 0x22, 0xf2, 0xe3, 0xcb, 0x52, 0x88, 0x2f, 0xc2, 0x7b, 0x5b, 0x79, 0x77, 0xe4, + 0x94, 0x79, 0xa7, 0x87, 0xd1, 0x75, 0x49, 0xfa, 0x26, 0xf9, 0xd8, 0x1a, 0xb6, 0xdf, 0xb5, 0xfb, 0xcd, 0x10, 0x41, + 0x08, 0xe5, 0xf8, 0x39, 0xa3, 0x13, 0x1a, 0x1f, 0x56, 0xb3, 0xd3, 0xeb, 0xf7, 0xce, 0xf1, 0x82, 0xad, 0xd1, 0x00, + 0x8f, 0x87, 0x2e, 0xe6, 0x89, 0x1a, 0x3a, 0x5d, 0xd7, 0xce, 0xc1, 0x03, 0x83, 0x2c, 0x4f, 0xbe, 0x61, 0x58, 0x62, + 0x7f, 0x12, 0xf1, 0xa4, 0xad, 0xda, 0xd8, 0x1c, 0xa9, 0x36, 0x6a, 0x06, 0x7e, 0xf0, 0x0a, 0x0a, 0x8c, 0x2e, 0x48, + 0x2b, 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, 0x6f, 0xa9, 0x57, 0xfb, 0x32, 0x66, 0x85, 0x7a, 0x7d, 0x61, 0xda, 0xf5, 0x5a, 0x5a, 0x14, 0x50, + 0x71, 0xdb, 0xaa, 0xed, 0x91, 0x9c, 0xff, 0xf8, 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, 0x6f, + 0xa9, 0x57, 0xb5, 0xa9, 0xea, 0xc1, 0x1b, 0x2f, 0x70, 0xf6, 0x4e, 0x6b, 0x01, 0x01, 0x14, 0xb6, 0x96, 0xe5, 0xe0, + 0xdc, 0xed, 0xaa, 0x96, 0x8a, 0x32, 0xea, 0xf7, 0xcf, 0x7f, 0x4b, 0x51, 0x11, 0x7b, 0xaa, 0x38, 0x65, 0xfd, 0x76, + 0xcb, 0x5c, 0x54, 0x96, 0xbc, 0x41, 0x15, 0xad, 0xd5, 0x51, 0x53, 0xb9, 0x6e, 0xae, 0x5a, 0x32, 0x41, 0x8c, 0xee, + 0xd3, 0xb5, 0xce, 0x9d, 0x7a, 0xef, 0x55, 0x1c, 0x31, 0x10, 0xdc, 0x74, 0x8f, 0x0f, 0x0e, 0x42, 0xa3, 0xa2, 0x5c, + 0x70, 0xa3, 0xb4, 0xaa, 0xa4, 0x14, 0xf2, 0x56, 0x45, 0x73, 0xa6, 0x8f, 0x00, 0x88, 0x00, 0xab, 0x44, 0xfd, 0x1f, + 0xbe, 0x34, 0xc6, 0x83, 0x07, 0xbe, 0x26, 0xd7, 0xb1, 0xf5, 0xfe, 0x69, 0x8d, 0xb4, 0xda, 0x38, 0x26, 0xb5, 0xea, + 0x65, 0xab, 0x78, 0xd9, 0xbd, 0x4e, 0xc5, 0xe0, 0xf9, 0xff, 0xdc, 0x07, 0xa8, 0x11, 0x2d, 0x65, 0x70, 0xeb, 0x6a, + 0x80, 0xc6, 0x87, 0x63, 0xe1, 0x1b, 0x3f, 0x64, 0x9c, 0x0f, 0x66, 0xe8, 0xa8, 0x36, 0x07, 0x07, 0x04, 0x47, 0x75, + 0x8f, 0xc6, 0x84, 0x59, 0x38, 0xf7, 0x20, 0x50, 0x7d, 0xe2, 0x3e, 0xe3, 0xda, 0x0b, 0xda, 0x04, 0x3e, 0x59, 0xd7, + 0x35, 0x45, 0x80, 0x8b, 0xd8, 0x98, 0x88, 0x21, 0x2e, 0x9b, 0x44, 0xea, 0x9b, 0x31, 0x28, 0x00, 0x8a, 0x17, 0x15, + 0xc9, 0xa5, 0x8b, 0x34, 0xaf, 0x44, 0x59, 0xeb, 0x66, 0x54, 0xac, 0x18, 0x02, 0xc0, 0x43, 0x50, 0x5c, 0x55, 0x66, + 0x42, 0x23, 0x36, 0x90, 0xca, 0x52, 0xb0, 0x6a, 0x58, 0xf8, 0x4d, 0xfb, 0x4d, 0x72, 0xd2, 0x3b, 0x1f, 0xb7, 0xce, + 0x1d, 0xfb, 0xde, 0x51, 0x48, 0x69, 0x0f, 0xc5, 0x04, 0x41, 0xf0, 0xd3, 0x3a, 0x9c, 0x3f, 0xe3, 0x2f, 0x08, 0x4c, + 0x45, 0x36, 0x63, 0xc0, 0x41, 0x88, 0xc8, 0x8c, 0xdf, 0x73, 0xf8, 0x82, 0x97, 0x93, 0x70, 0x38, 0xf4, 0x41, 0x1f, + 0xca, 0xb3, 0x59, 0x38, 0x14, 0x73, 0xe9, 0xbd, 0x0e, 0xd6, 0xba, 0x90, 0xd7, 0x93, 0x10, 0xd1, 0x42, 0x43, 0x1f, + 0x9c, 0xd7, 0x5d, 0x73, 0x84, 0x25, 0x00, 0x4d, 0x1c, 0x7d, 0x59, 0xbf, 0x1f, 0x79, 0xda, 0xd0, 0x22, 0xc5, 0x45, + 0xa3, 0xcc, 0x66, 0xb9, 0xec, 0x84, 0x8d, 0x6b, 0xb7, 0x40, 0x28, 0x1e, 0xa6, 0x2d, 0x54, 0xad, 0xa7, 0x7a, 0x3d, + 0x37, 0xed, 0xbe, 0x7b, 0x54, 0xad, 0x72, 0xa4, 0xb3, 0x36, 0x5d, 0xa9, 0xd5, 0x2d, 0xa3, 0x6a, 0x9d, 0xa5, 0x11, + 0x55, 0x6e, 0x92, 0xbb, 0x46, 0x2d, 0xf8, 0x64, 0x43, 0x97, 0x29, 0x3b, 0x5b, 0x83, 0x13, 0x47, 0x9e, 0x4b, 0x6e, + 0xf9, 0xee, 0xbc, 0xa2, 0xbb, 0x53, 0xed, 0x5b, 0x80, 0x7b, 0x33, 0x6c, 0xc8, 0x9c, 0xd7, 0xd8, 0x69, 0x10, 0x26, + 0x81, 0x1f, 0xb1, 0x8f, 0x19, 0xb2, 0xc1, 0x80, 0x8e, 0x42, 0xfa, 0x5f, 0x5b, 0xe6, 0x48, 0xc0, 0xe4, 0xaf, 0xe7, + 0x7e, 0xb3, 0x28, 0x72, 0x58, 0x8c, 0x1f, 0x36, 0x18, 0x69, 0xac, 0xd6, 0x60, 0x58, 0xde, 0x21, 0xf2, 0xa7, 0x76, + 0xc7, 0x34, 0xd5, 0xf1, 0x66, 0xbd, 0xd6, 0xfc, 0xea, 0xe9, 0x53, 0x5d, 0x9f, 0xff, 0xf6, 0xfd, 0x65, 0x58, 0x33, + 0xfb, 0x43, 0x10, 0x4a, 0xbb, 0x77, 0x8b, 0x73, 0x47, 0xa2, 0x77, 0xac, 0x34, 0xb3, 0x4b, 0xbb, 0x64, 0x97, 0xa6, + 0xb4, 0x1b, 0x72, 0xbd, 0xfa, 0x4a, 0x79, 0x63, 0xe7, 0x15, 0xd3, 0xfd, 0x7b, 0xa1, 0x77, 0x94, 0x53, 0x35, 0x81, + 0x88, 0x26, 0xed, 0x48, 0xdc, 0xee, 0x95, 0xe1, 0xf3, 0x49, 0xde, 0x2e, 0xe1, 0xa8, 0x6b, 0x58, 0x6e, 0xbe, 0xfd, + 0xcf, 0xbc, 0xea, 0xac, 0x70, 0xfb, 0xa5, 0x31, 0x6b, 0x7f, 0x0a, 0xe2, 0xaa, 0xfe, 0xf0, 0x9e, 0xd4, 0x4c, 0xc9, + 0xff, 0x55, 0x8f, 0x81, 0xab, 0x9f, 0x4c, 0x3b, 0xba, 0xa7, 0x10, 0x36, 0x98, 0xfd, 0xfc, 0xf8, 0xa1, 0x05, 0xab, + 0xea, 0x02, 0x45, 0x72, 0x00, 0x9d, 0xbb, 0x64, 0x84, 0xf7, 0x3b, 0xc6, 0xb9, 0x7f, 0xf5, 0xbd, 0x9a, 0x1c, 0x21, + 0xa2, 0x5d, 0x84, 0x03, 0x80, 0xb8, 0xd3, 0x54, 0xd6, 0xa1, 0x06, 0xe8, 0x03, 0x02, 0xeb, 0xd0, 0xb7, 0x19, 0xc0, + 0x41, 0x1f, 0x6d, 0x9e, 0x45, 0x20, 0xaf, 0x7b, 0xf7, 0xec, 0x9a, 0xed, 0x7c, 0xfe, 0x62, 0x95, 0x7a, 0xf7, 0xe8, + 0x10, 0x7c, 0x3e, 0xf6, 0xa7, 0x97, 0x81, 0xc1, 0x85, 0x66, 0xd7, 0xcf, 0x04, 0xdb, 0xb1, 0xdd, 0x33, 0x44, 0x2a, + 0xea, 0xce, 0x3f, 0xbc, 0x34, 0xd1, 0xf3, 0xce, 0x0b, 0x77, 0x7c, 0x09, 0xe0, 0x81, 0x2c, 0x06, 0x14, 0x9f, 0xa5, + 0xf7, 0x2f, 0x96, 0x80, 0x9a, 0xfc, 0x96, 0xaf, 0xbd, 0x2f, 0x94, 0xba, 0x80, 0x3f, 0x07, 0x94, 0x3e, 0xc9, 0xb9, + 0x77, 0x37, 0xbc, 0xf5, 0x2f, 0x9e, 0x83, 0xf3, 0xc4, 0x6a, 0xb8, 0x80, 0xbf, 0x0a, 0x3e, 0xf4, 0xee, 0x06, 0x98, + 0x58, 0xf2, 0xa1, 0xb7, 0x1a, 0x40, 0xaa, 0xc2, 0x85, 0xc4, 0xd8, 0x87, 0x5f, 0x83, 0x9c, 0xe1, 0x1f, 0xbf, 0x69, + 0x0c, 0xd6, 0x5f, 0x83, 0x42, 0xa3, 0xb1, 0x96, 0x2a, 0x64, 0x29, 0x16, 0x67, 0x02, 0x6c, 0xc2, 0x71, 0xb7, 0x2f, + 0x56, 0xb5, 0x59, 0x0b, 0xfa, 0xf3, 0x11, 0xdf, 0xa3, 0xb1, 0xba, 0x2a, 0xe7, 0xa2, 0xfc, 0x88, 0xf4, 0xa9, 0x8e, + 0x8f, 0x51, 0xb1, 0xa9, 0xbb, 0xd3, 0xa9, 0x56, 0x1d, 0x69, 0xbf, 0x29, 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, 0x2f, 0x06, 0xb9, 0x0c, 0x8d, 0xf9, 0x80, 0x6c, 0x18, 0xca, 0x87, 0x16, 0x19, 0x12, 0x22, 0xde, 0x43, + 0x25, 0x60, 0xdb, 0x82, 0x32, 0x29, 0xe0, 0x2c, 0x1a, 0xfc, 0x56, 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, 0x1f, 0xae, 0xf2, 0x4f, 0xd1, 0x52, 0x0f, 0xff, 0x9f, 0x31, 0x85, 0xd2, + 0xbf, 0x4a, 0xcb, 0x68, 0xb3, 0x5a, 0x8a, 0x52, 0xe4, 0x91, 0x38, 0xf9, 0x5a, 0x64, 0xe7, 0xf2, 0x9d, 0x4f, 0xa1, + 0x5f, 0x00, 0x5a, 0xf6, 0x09, 0x32, 0xfa, 0x7b, 0x26, 0xf8, 0xf0, 0x7b, 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, 0x7b, 0x83, 0x90, 0xe2, 0xf9, 0x03, 0x5b, 0xad, 0x8b, 0x8b, 0xc4, 0x2b, 0x64, + 0xa2, 0x05, 0xb1, 0x14, 0x81, 0x19, 0x2f, 0x34, 0x8d, 0x30, 0x41, 0x99, 0x12, 0x2c, 0x5a, 0xa3, 0x43, 0xfb, 0xc3, + 0x12, 0x76, 0x8f, 0x31, 0x02, 0x04, 0xaa, 0x4c, 0x9f, 0xc3, 0xd6, 0x84, 0xd9, 0xd4, 0xc5, 0x06, 0x68, 0xab, 0x18, + 0x1a, 0x84, 0xb5, 0x21, 0xe6, 0x63, 0x9a, 0xdf, 0xfd, 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, 0xee, 0x1a, 0xfe, 0x21, 0xf3, 0x62, 0x96, 0x80, 0x7e, 0x77, 0xc5, 0x55, 0x83, 0xa0, 0x19, 0x1b, 0x76, + 0x0b, 0xbf, 0x25, 0xd6, 0x6e, 0xe9, 0x5f, 0x2c, 0xd9, 0xc2, 0xf4, 0x81, 0x6e, 0x1d, 0x60, 0x19, 0x51, 0x93, 0xef, + 0x91, 0x77, 0xd3, 0x59, 0x51, 0xb8, 0x3d, 0xb1, 0x85, 0xcf, 0xae, 0xcd, 0x9b, 0xf7, 0xcf, 0x22, 0xc8, 0xbd, 0xe3, + 0xde, 0xfd, 0xf0, 0xda, 0xbf, 0xd0, 0x2d, 0x90, 0x93, 0x59, 0xce, 0x40, 0xea, 0x88, 0x4f, 0x10, 0xad, 0xec, 0x29, + 0xdf, 0x09, 0xb9, 0xb3, 0xad, 0x9f, 0xdd, 0xbb, 0xdb, 0xda, 0xdd, 0xb3, 0x7b, 0x56, 0x8d, 0x28, 0x56, 0x9c, 0xa6, + 0x48, 0x98, 0x45, 0x1b, 0xe0, 0xa9, 0x97, 0xef, 0x77, 0xec, 0x98, 0xc3, 0xdd, 0xb3, 0x8e, 0x8e, 0x97, 0x73, 0xc0, + 0xee, 0xfe, 0xa3, 0x4d, 0xd8, 0x58, 0xe9, 0x5a, 0x85, 0x0e, 0x77, 0xcf, 0x32, 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, 0x2b, 0x2e, 0xbe, 0x3f, 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, 0x9c, 0xc5, 0x90, 0x08, 0xb0, 0xdd, 0xa1, 0x62, 0x5b, 0xb8, 0x78, + 0xce, 0x36, 0xbc, 0xe8, 0xf7, 0x33, 0xd5, 0x29, 0x64, 0xdd, 0x59, 0xf2, 0x8d, 0x6a, 0x8e, 0x35, 0xd4, 0x6c, 0x6d, + 0x92, 0xad, 0x71, 0x6e, 0x2b, 0x3e, 0xee, 0xda, 0x8a, 0x8f, 0x95, 0xb5, 0x2e, 0xdd, 0xeb, 0x3d, 0xaa, 0x0b, 0x60, + 0xeb, 0xbf, 0x3d, 0x5e, 0xb9, 0x9e, 0xcf, 0x08, 0xe0, 0x6b, 0xc1, 0xc7, 0x93, 0x05, 0x7a, 0x95, 0x2c, 0xfc, 0xdb, + 0x81, 0x1a, 0x7f, 0xa7, 0x73, 0x17, 0x00, 0x5d, 0x49, 0x79, 0x05, 0xe4, 0x1d, 0xe4, 0x98, 0x5b, 0x76, 0xe5, 0xfd, + 0xc9, 0x77, 0xd8, 0x35, 0xaf, 0x67, 0x8b, 0x39, 0xdb, 0x81, 0x53, 0x41, 0x32, 0xb0, 0x97, 0x15, 0xdb, 0x05, 0xb1, + 0x9d, 0xf0, 0x1b, 0x01, 0x53, 0xbe, 0x84, 0x20, 0xae, 0xe0, 0x16, 0xe2, 0xf0, 0xe4, 0x9f, 0x83, 0xfb, 0xd6, 0x66, + 0x7d, 0xcf, 0xac, 0xce, 0x09, 0xd6, 0xcc, 0xea, 0xc1, 0x60, 0xd9, 0x4c, 0x56, 0xfd, 0xbe, 0xb7, 0xd3, 0x8e, 0x4f, + 0x77, 0x52, 0x27, 0x76, 0x5a, 0xab, 0xb5, 0x60, 0xd7, 0x52, 0xeb, 0x62, 0x0c, 0x3d, 0x40, 0xfc, 0x74, 0x3b, 0xe0, + 0xf7, 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, 0xc7, 0x6c, 0xc7, 0xb8, + 0xf9, 0xe9, 0xe5, 0x0f, 0x4e, 0x58, 0xb2, 0x62, 0xb5, 0x3f, 0xfd, 0xfe, 0x99, 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, 0x99, 0xfa, 0xc0, 0x88, 0x25, 0x81, 0xda, 0x5e, + 0x66, 0xe9, 0x1d, 0xa8, 0xf0, 0x7b, 0xb8, 0x9a, 0x88, 0xfd, 0xdc, 0x92, 0xa2, 0x22, 0x1b, 0xe9, 0x0d, 0xad, 0xc1, + 0x23, 0xb4, 0xa6, 0x7c, 0xef, 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, 0xd7, 0x24, 0x61, 0x4f, 0x0c, + 0x3a, 0x85, 0xaa, 0xdc, 0xee, 0x8e, 0xb6, 0xc0, 0x75, 0xcc, 0x52, 0xf4, 0xd2, 0x16, 0xb9, 0x5b, 0xfe, 0xdd, 0x73, + 0x45, 0xce, 0x7e, 0x09, 0x08, 0x4e, 0xcd, 0x57, 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, 0xe6, 0x2e, 0xc9, 0x37, 0xe0, + 0xcc, 0x40, 0xa9, 0x96, 0x7e, 0xe0, 0x58, 0x2d, 0xa0, 0xc2, 0xc1, 0xec, 0xa4, 0x5e, 0x58, 0x46, 0x3d, 0xa6, 0xcf, + 0xcf, 0x60, 0xef, 0x08, 0x09, 0x80, 0xfb, 0x65, 0x1f, 0x90, 0x80, 0x87, 0xce, 0xec, 0x80, 0x70, 0xc2, 0x2c, 0xaa, + 0x02, 0x89, 0xe4, 0x48, 0x3f, 0x7b, 0xcc, 0x44, 0xf2, 0x07, 0xb3, 0x9e, 0x73, 0x4a, 0xf4, 0x58, 0x4f, 0x1d, 0x21, + 0x3d, 0xd6, 0xb3, 0x8e, 0x88, 0x1e, 0xeb, 0x59, 0xc7, 0x47, 0x8f, 0xf5, 0xcc, 0xb1, 0xd3, 0x83, 0xc0, 0x04, 0x88, + 0x3c, 0x60, 0x3d, 0x9a, 0x4c, 0x3d, 0xc5, 0x3d, 0x40, 0x34, 0x08, 0xac, 0x27, 0x85, 0xf3, 0x1e, 0x20, 0x8f, 0x91, + 0x58, 0x1d, 0xf4, 0xfe, 0x32, 0x7e, 0xda, 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, + 0x07, 0x51, 0xf3, 0xb4, 0xd5, 0x56, 0xc1, 0xfe, 0x0e, 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, 0x1f, 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, 0x7f, 0x95, 0xa5, 0xc6, 0x39, 0x32, 0x97, 0xeb, 0xbb, 0x2e, 0xee, 0xee, 0x68, 0x9b, 0xb0, 0x0a, 0x11, + 0xea, 0xb6, 0xa1, 0x72, 0x29, 0xcc, 0xc6, 0xa6, 0x69, 0x80, 0x2f, 0x14, 0x95, 0x4a, 0x55, 0x6a, 0x2b, 0x95, 0x9c, + 0xf0, 0xae, 0xaf, 0x6a, 0x91, 0xba, 0x22, 0xd8, 0xc6, 0x0c, 0xf5, 0x50, 0x6e, 0xd4, 0xd8, 0xd7, 0x1d, 0xab, 0xf4, + 0x0e, 0x13, 0xe4, 0x8c, 0xbc, 0xc8, 0xc1, 0x45, 0x49, 0x41, 0xe6, 0x6a, 0x08, 0xf3, 0x47, 0x0d, 0x9f, 0x16, 0x96, + 0x7b, 0x28, 0x01, 0xb3, 0xa3, 0x86, 0x97, 0x11, 0x02, 0x11, 0x97, 0xca, 0xbe, 0x62, 0xe2, 0xf7, 0x14, 0xcc, 0x92, + 0x09, 0xdd, 0x8b, 0x58, 0x18, 0xa1, 0x8d, 0x4f, 0x92, 0x64, 0xea, 0x69, 0x0a, 0x6e, 0xe4, 0x32, 0xcc, 0xd1, 0x08, + 0x2d, 0xf9, 0xc8, 0x81, 0xf4, 0xb5, 0x9c, 0x4a, 0xf0, 0x11, 0x75, 0x0a, 0x38, 0x9e, 0x9f, 0x17, 0xd6, 0x4f, 0x96, + 0x4b, 0xcc, 0x65, 0x6d, 0xfe, 0xcb, 0x8e, 0x8e, 0xc1, 0x2e, 0x4f, 0x13, 0xc7, 0xd5, 0x7f, 0x54, 0x25, 0xc5, 0xc3, + 0xcf, 0x69, 0x0e, 0x28, 0x82, 0x99, 0x3d, 0xc5, 0xf8, 0xd8, 0x67, 0x99, 0x02, 0xfe, 0x76, 0xbd, 0xb5, 0x64, 0x62, + 0x97, 0xb4, 0x9b, 0x2b, 0xe3, 0x97, 0xda, 0xb0, 0xe3, 0xe0, 0xdc, 0x00, 0x14, 0x67, 0x8d, 0x0e, 0xcb, 0x6b, 0xdd, + 0xb6, 0x2a, 0x54, 0xa0, 0xd6, 0xff, 0xd9, 0x2d, 0x4c, 0x79, 0x9b, 0x97, 0xca, 0xdb, 0x3c, 0x34, 0x01, 0x02, 0x91, + 0x19, 0xf2, 0xac, 0xe9, 0x98, 0x24, 0xee, 0x1d, 0x29, 0x69, 0xdf, 0x91, 0xe2, 0x47, 0xef, 0x48, 0xc8, 0xb7, 0x84, + 0x8e, 0xec, 0x4b, 0x4e, 0x4e, 0xa0, 0xcc, 0x60, 0x2f, 0xaf, 0x99, 0xec, 0x1f, 0xd0, 0x5e, 0x38, 0x97, 0xe5, 0x15, + 0xbf, 0x16, 0xde, 0xda, 0x9f, 0xae, 0x4f, 0xbb, 0xaa, 0xde, 0x7e, 0x65, 0x66, 0x1e, 0x0e, 0xc5, 0xe1, 0x50, 0x99, + 0xa0, 0xdd, 0x05, 0x17, 0x83, 0x9c, 0xdd, 0xbb, 0xf1, 0xf1, 0xd7, 0x1c, 0x45, 0x6c, 0xa5, 0x3c, 0x92, 0x2e, 0x54, + 0x62, 0x78, 0x69, 0xe0, 0x61, 0x76, 0x7c, 0x3c, 0xd9, 0x5d, 0xdd, 0x4f, 0x06, 0x83, 0x9d, 0xea, 0xdb, 0x2d, 0xaf, + 0x67, 0xbb, 0x39, 0x7b, 0xe0, 0xb7, 0xd3, 0x6d, 0xb0, 0x6f, 0x60, 0xdb, 0xdd, 0x5d, 0x89, 0xc3, 0x61, 0xf7, 0x82, + 0x2f, 0xfc, 0xfd, 0x03, 0x02, 0x3a, 0xf3, 0xf3, 0x71, 0x1b, 0xe3, 0xe7, 0xa6, 0xed, 0xaa, 0xb5, 0x03, 0x78, 0xfa, + 0x1f, 0xbc, 0x9b, 0xd9, 0x72, 0xee, 0xb3, 0x27, 0xfc, 0x01, 0xfc, 0xf3, 0x71, 0x93, 0x44, 0xea, 0x13, 0xed, 0x32, + 0x79, 0x03, 0x0e, 0xe4, 0x3b, 0x9f, 0xbd, 0xe5, 0x0f, 0xb3, 0xe5, 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, 0x76, 0xc3, + 0x22, 0x3f, 0x80, 0x0f, 0xb2, 0x9d, 0x3f, 0x91, 0x35, 0xa5, 0xfb, 0xc5, 0x13, 0xff, 0x70, 0xa0, 0xbf, 0xde, 0xfa, + 0x87, 0xc3, 0x7b, 0xf6, 0x80, 0xe0, 0xe8, 0x7c, 0x07, 0xfd, 0xa3, 0x6f, 0x1d, 0x50, 0x95, 0xe1, 0xf5, 0x6c, 0x33, + 0xf7, 0x5f, 0xac, 0xd8, 0x1d, 0x70, 0xa1, 0x28, 0x2f, 0xb4, 0x1b, 0xf6, 0x80, 0x5e, 0x67, 0xe4, 0x44, 0x34, 0xdb, + 0xcd, 0x7d, 0x16, 0xe3, 0x73, 0x75, 0x5f, 0x4c, 0xbe, 0x7a, 0x5f, 0xdc, 0xb1, 0x6d, 0xf7, 0x7d, 0x51, 0xbe, 0xe9, + 0xae, 0x9f, 0x2d, 0xdb, 0xb1, 0x07, 0x98, 0x61, 0xd7, 0xfc, 0xa6, 0x39, 0x76, 0x8c, 0xfd, 0xea, 0x8d, 0x11, 0x40, + 0x99, 0x2d, 0x58, 0x2c, 0x38, 0x28, 0xd5, 0xaa, 0x6d, 0x49, 0xe4, 0x95, 0x0e, 0x54, 0x9b, 0x11, 0xdc, 0x57, 0x0b, + 0x39, 0xf3, 0xcc, 0x40, 0xdf, 0x56, 0x88, 0x16, 0x0e, 0x1b, 0xf0, 0x57, 0xda, 0x3a, 0xc6, 0x30, 0xcd, 0x6a, 0xa6, + 0x6d, 0x51, 0x97, 0xdf, 0xf6, 0x9e, 0xc9, 0x6f, 0x64, 0x60, 0x0b, 0x91, 0x14, 0x8e, 0xe3, 0x8b, 0xe7, 0x27, 0xfc, + 0x57, 0x2d, 0x8f, 0x5a, 0xed, 0x17, 0x4a, 0x7d, 0xfa, 0x8a, 0x8e, 0x68, 0xe2, 0x5e, 0xb4, 0x65, 0x58, 0xa3, 0xac, + 0xa9, 0xa5, 0xc3, 0x30, 0xae, 0x61, 0x5f, 0x1e, 0x38, 0xf4, 0x1d, 0x10, 0x68, 0xab, 0x54, 0x0a, 0xb4, 0x70, 0x0c, + 0xa3, 0x30, 0x0b, 0x29, 0x8f, 0x0b, 0xb3, 0x94, 0xf7, 0x58, 0xa0, 0xc5, 0xad, 0xba, 0xc7, 0xd4, 0x76, 0x0b, 0x22, + 0xac, 0xde, 0x32, 0xce, 0x2f, 0x1b, 0x55, 0xb8, 0x2d, 0x40, 0x51, 0x04, 0x65, 0xb0, 0x27, 0xb9, 0x6d, 0xa1, 0xa4, + 0xd9, 0x28, 0xac, 0xc5, 0x5d, 0x51, 0xee, 0x7a, 0x0d, 0x5b, 0xe0, 0x05, 0x55, 0x3f, 0x21, 0x6c, 0xcb, 0x9e, 0x75, + 0x28, 0x17, 0xe9, 0x7f, 0x64, 0xe9, 0xf9, 0x76, 0x6b, 0xce, 0xff, 0xf4, 0x15, 0x7d, 0x54, 0xfe, 0xe7, 0x97, 0xf4, + 0x93, 0xc1, 0x32, 0x72, 0x4a, 0x7d, 0x1f, 0x8d, 0x6e, 0xd3, 0x9c, 0x30, 0xb6, 0x7c, 0xfd, 0xf4, 0x1b, 0x64, 0x0a, + 0x92, 0x43, 0x29, 0x55, 0x39, 0xd9, 0x43, 0x5f, 0x78, 0xdd, 0x87, 0x99, 0x60, 0x00, 0xc2, 0x6b, 0xb4, 0xa9, 0x26, + 0x4c, 0xe2, 0xd1, 0x15, 0xfc, 0xdf, 0x08, 0x62, 0xd0, 0x3e, 0x51, 0xd4, 0xb1, 0x6d, 0xa4, 0xeb, 0xb6, 0x73, 0x90, + 0xdc, 0xa9, 0x2b, 0x7f, 0x54, 0x4e, 0xfe, 0x13, 0x0d, 0x91, 0x57, 0x5c, 0x21, 0x56, 0x16, 0x5c, 0x62, 0x31, 0x54, + 0xa4, 0x00, 0xd7, 0x10, 0x44, 0xca, 0xa2, 0xa4, 0x70, 0xcb, 0x41, 0x55, 0x04, 0x60, 0x5c, 0xad, 0x8e, 0x3a, 0x11, + 0x3e, 0x6e, 0xad, 0x45, 0x08, 0x56, 0x34, 0x6a, 0x65, 0xad, 0xc0, 0x17, 0xa4, 0x2f, 0x1d, 0x0a, 0x62, 0x7a, 0x14, + 0x52, 0x55, 0x3a, 0x14, 0x48, 0x73, 0xa8, 0xf8, 0xc6, 0x60, 0xa3, 0xa8, 0x48, 0xcf, 0x5f, 0x9a, 0x94, 0x5c, 0x1a, + 0x33, 0x3e, 0x88, 0x32, 0x12, 0x79, 0x1d, 0xde, 0x89, 0x69, 0x81, 0x7c, 0xa3, 0xc7, 0x0f, 0x82, 0x4b, 0x78, 0x37, + 0xe4, 0x5e, 0x01, 0xb6, 0x04, 0xec, 0x00, 0xf7, 0xca, 0x8c, 0x72, 0x9d, 0xd6, 0xf5, 0x5b, 0xeb, 0xa1, 0x18, 0x86, + 0xcf, 0x2c, 0x81, 0xed, 0x68, 0x1d, 0x1d, 0xe9, 0xe1, 0xc3, 0xff, 0xba, 0xaa, 0x39, 0xea, 0x54, 0x2e, 0x67, 0xc7, + 0x13, 0x96, 0x22, 0x66, 0xd0, 0xfd, 0x75, 0xfb, 0x4a, 0x00, 0xdd, 0x2e, 0x8b, 0x79, 0x36, 0xda, 0xc9, 0xbf, 0xa5, + 0x1b, 0x2b, 0x4a, 0x9b, 0x78, 0x97, 0xf5, 0xc6, 0xfe, 0x70, 0xf4, 0x97, 0x67, 0x5f, 0x26, 0x84, 0xaa, 0xb3, 0x61, + 0x6b, 0x1d, 0xe7, 0xf2, 0xbf, 0xfe, 0x3a, 0x26, 0x2b, 0x08, 0x0a, 0xc2, 0xb2, 0x53, 0x4c, 0x54, 0x30, 0x8a, 0x14, + 0x6b, 0x3e, 0x9e, 0xac, 0x51, 0x27, 0xbc, 0xf6, 0x97, 0x5a, 0x27, 0x4c, 0x8c, 0xac, 0x54, 0xfe, 0x9a, 0x55, 0xec, + 0x4e, 0x65, 0x16, 0x90, 0x79, 0x90, 0x4f, 0xd6, 0x46, 0x83, 0xb9, 0xe2, 0xf5, 0x6c, 0x3d, 0x97, 0xca, 0x67, 0x30, + 0xe5, 0x2c, 0x07, 0x27, 0x4b, 0x61, 0xf7, 0x24, 0x50, 0xb4, 0x66, 0xe8, 0xda, 0x9f, 0x62, 0xab, 0x5e, 0xa7, 0x55, + 0x0d, 0xf0, 0x80, 0x10, 0x03, 0x43, 0xed, 0xd5, 0xc2, 0x43, 0x6b, 0x01, 0xac, 0xfd, 0x51, 0xe9, 0x07, 0xe3, 0xc9, + 0x92, 0x2f, 0x90, 0x7f, 0x39, 0x72, 0xd4, 0xee, 0xfd, 0xbe, 0x77, 0x0f, 0x52, 0x70, 0xe4, 0x5a, 0x28, 0x90, 0x08, + 0x68, 0xc1, 0x37, 0xbe, 0xf2, 0xc1, 0xb8, 0x46, 0x6d, 0x35, 0x28, 0xa8, 0x1d, 0xdd, 0xf2, 0xd8, 0xd1, 0x3b, 0xdf, + 0x9f, 0xd0, 0x57, 0x2f, 0xb4, 0x70, 0xfc, 0x95, 0x33, 0x72, 0xcd, 0x56, 0x1d, 0x72, 0x44, 0x33, 0xe9, 0x10, 0x22, + 0x56, 0x6c, 0xcd, 0xae, 0x49, 0xe5, 0xdc, 0x39, 0x64, 0xa7, 0x8f, 0x50, 0xa5, 0xd7, 0x7a, 0x7c, 0x3b, 0x51, 0xba, + 0xdb, 0xe3, 0xdd, 0xe4, 0x5b, 0x36, 0x11, 0x31, 0x18, 0xd0, 0x06, 0xe1, 0x8c, 0xac, 0x43, 0xa4, 0xd2, 0x01, 0x42, + 0xe0, 0x98, 0x80, 0xa6, 0xff, 0xf8, 0x9a, 0x44, 0x01, 0x47, 0xda, 0x08, 0x59, 0xcb, 0x0e, 0x87, 0x1c, 0x34, 0xca, + 0xcd, 0x1f, 0x5e, 0xa1, 0x4e, 0x73, 0x60, 0x9e, 0x2e, 0x61, 0xcf, 0xc1, 0x23, 0xbd, 0x38, 0x3e, 0xd2, 0xff, 0x3b, + 0x9a, 0xa8, 0xf1, 0x7f, 0xae, 0x89, 0x52, 0x5a, 0x24, 0x47, 0xb5, 0xf4, 0x4d, 0xea, 0x28, 0xb8, 0xc8, 0x3b, 0x6a, + 0x21, 0x7b, 0x96, 0x8d, 0x1b, 0xd5, 0xbc, 0xff, 0x5f, 0x2b, 0xf3, 0xff, 0x35, 0xad, 0x0c, 0x53, 0xb2, 0x63, 0xa9, + 0x66, 0x1e, 0x68, 0x15, 0xc3, 0xec, 0x67, 0x92, 0x10, 0x19, 0x2e, 0x0d, 0xf8, 0x51, 0x05, 0xfb, 0x38, 0xad, 0xd6, + 0x59, 0xb8, 0x43, 0x25, 0xea, 0xad, 0xb8, 0x4b, 0xf3, 0x97, 0xf5, 0xbf, 0x45, 0x59, 0xc0, 0xd4, 0xbe, 0x2b, 0xd3, + 0x38, 0x20, 0x0b, 0x7f, 0x16, 0x96, 0x38, 0xb9, 0xb1, 0x8d, 0x3f, 0xcb, 0xf1, 0xb4, 0x5f, 0x75, 0x66, 0x1e, 0x48, + 0xa0, 0x06, 0xe2, 0x8f, 0x9c, 0xcb, 0xca, 0xe2, 0x01, 0xa1, 0x9b, 0x7f, 0x28, 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, 0xa7, 0xb1, 0x88, 0x47, 0x3d, 0x45, 0xc9, 0xf2, 0x26, 0x77, 0xe5, 0x5c, 0x7f, + 0xff, 0x07, 0x05, 0xb0, 0x1b, 0x30, 0xdb, 0x16, 0xd8, 0x01, 0x40, 0x82, 0x02, 0xd9, 0x42, 0x9d, 0x46, 0x67, 0x6a, + 0xa9, 0xc0, 0x7b, 0xae, 0x07, 0xf8, 0x9b, 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, 0xb7, 0x53, 0x45, 0x1e, 0x1f, 0xa5, 0x21, 0xaf, + 0xc0, 0x93, 0x8c, 0x23, 0x49, 0x94, 0x08, 0xde, 0xe4, 0x8d, 0x19, 0x87, 0x97, 0x6d, 0xca, 0xa9, 0xbd, 0x59, 0x2f, + 0x00, 0xe7, 0x09, 0xda, 0x32, 0xc0, 0x58, 0xc0, 0xe0, 0x5c, 0x88, 0x25, 0x4f, 0x11, 0xfc, 0xd2, 0x89, 0x14, 0xc6, + 0x5d, 0x0e, 0xc3, 0x3c, 0x28, 0x7a, 0x97, 0xd4, 0x1f, 0xfd, 0x3e, 0x6a, 0x93, 0xc1, 0x10, 0x54, 0x02, 0xa8, 0xac, + 0x1b, 0x24, 0x06, 0x56, 0xa5, 0x85, 0xc4, 0x25, 0xc4, 0xcb, 0x7c, 0x35, 0xad, 0xa3, 0xe0, 0x7d, 0x3d, 0x21, 0x84, + 0x13, 0x8c, 0x0f, 0x71, 0x03, 0x04, 0x0c, 0x56, 0x71, 0x81, 0x41, 0xf2, 0x5c, 0xa2, 0xfb, 0xe3, 0xf9, 0x8e, 0x01, + 0xae, 0x9c, 0xf7, 0x54, 0xbb, 0x7a, 0x60, 0x2f, 0x57, 0xe9, 0x92, 0x11, 0xc2, 0x8a, 0xff, 0x8b, 0xc8, 0xfb, 0x76, + 0x98, 0x80, 0xda, 0x46, 0xfe, 0x18, 0x24, 0xe6, 0x32, 0x51, 0x04, 0xf1, 0x28, 0x2b, 0x58, 0x92, 0x06, 0x9b, 0x51, + 0x92, 0x82, 0x46, 0x13, 0x63, 0xc8, 0x54, 0x68, 0x87, 0xa4, 0xd1, 0x6c, 0x4c, 0xf6, 0x31, 0xe4, 0x35, 0x5c, 0x2c, + 0x16, 0x78, 0xdf, 0xcf, 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, 0xcb, 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, 0x86, 0xd2, 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, 0xb3, 0xac, 0xc9, 0x5c, 0xbc, 0x2e, 0x1e, 0xbc, + 0x82, 0x3d, 0xf7, 0x07, 0xfa, 0x57, 0xc9, 0x9e, 0xfb, 0x36, 0x93, 0xeb, 0x9f, 0x69, 0xd7, 0x68, 0xcc, 0x74, 0xbc, + 0x76, 0x05, 0x56, 0x68, 0x80, 0xfc, 0x82, 0x1d, 0xed, 0x6d, 0x0e, 0x02, 0x01, 0xba, 0x97, 0xe0, 0x28, 0x0a, 0x88, + 0x9a, 0x56, 0x95, 0x47, 0xa7, 0x7b, 0x7f, 0x8f, 0x6f, 0x94, 0x80, 0x4d, 0x9e, 0x5a, 0xf7, 0x96, 0xb1, 0x7f, 0x38, + 0x40, 0x08, 0xbd, 0x9c, 0x7e, 0xa3, 0x2d, 0xab, 0x47, 0x3b, 0x96, 0xfb, 0x86, 0x51, 0x4f, 0xc1, 0x18, 0x86, 0x2e, + 0xac, 0x62, 0x24, 0xcf, 0x80, 0xac, 0xf1, 0x1b, 0x44, 0x17, 0xb0, 0xe8, 0xf5, 0x5e, 0x1f, 0xd1, 0x20, 0x02, 0x2a, + 0xbd, 0xe6, 0x2f, 0x45, 0x3e, 0x57, 0x85, 0xe8, 0xbd, 0xb7, 0x76, 0xde, 0xcc, 0x48, 0x96, 0x49, 0x23, 0xd5, 0x6e, + 0x65, 0xb1, 0xae, 0xbc, 0xd9, 0x09, 0xe9, 0x62, 0x8e, 0xa1, 0x32, 0x78, 0x1c, 0x80, 0xd2, 0xf3, 0x6f, 0xa1, 0x57, + 0x32, 0x64, 0x9a, 0x25, 0x9a, 0xd9, 0x5d, 0xe3, 0x4f, 0x56, 0xa9, 0x17, 0x23, 0x62, 0x36, 0xb0, 0x85, 0xb8, 0x2d, + 0x2a, 0xdd, 0x16, 0x85, 0xb2, 0x45, 0x91, 0x3e, 0xd4, 0xce, 0x74, 0x67, 0x16, 0x3e, 0xab, 0x4c, 0xfb, 0xde, 0x66, + 0x66, 0x6c, 0x80, 0xb6, 0x8b, 0xf0, 0x0d, 0x74, 0xa0, 0x42, 0xc8, 0x7f, 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, 0x5f, 0x53, + 0xb7, 0x67, 0xe5, 0x64, 0x2f, 0x3a, 0x27, 0xfb, 0x74, 0x36, 0x0f, 0x04, 0x97, 0x3b, 0xf7, 0x79, 0x3e, 0xd5, 0xd3, + 0xae, 0xf2, 0x83, 0xd6, 0x10, 0x99, 0x2f, 0x7c, 0xaa, 0xba, 0xd7, 0x15, 0x2c, 0x60, 0x09, 0xee, 0xd6, 0x4b, 0xf3, + 0x5f, 0xb1, 0xfb, 0x7b, 0x41, 0x2f, 0xcd, 0x7f, 0xa3, 0x3f, 0x29, 0x80, 0x03, 0xd0, 0x98, 0xda, 0x2d, 0xf0, 0x10, + 0x43, 0x05, 0x85, 0xbb, 0x59, 0x39, 0xf7, 0x6a, 0x80, 0xc3, 0x24, 0x7d, 0x43, 0xab, 0x57, 0x5a, 0xec, 0x7a, 0x99, + 0xec, 0x15, 0xe0, 0xa1, 0x0a, 0x79, 0x78, 0x38, 0x44, 0x1d, 0xc3, 0x0e, 0xea, 0x08, 0x18, 0xf6, 0x10, 0x1a, 0x5b, + 0xe0, 0xf9, 0xf8, 0x29, 0xe3, 0x7b, 0x01, 0x6a, 0x23, 0x84, 0xc7, 0xab, 0x45, 0x19, 0x62, 0xcb, 0xde, 0x22, 0x95, + 0xd4, 0xcf, 0x02, 0x51, 0x46, 0xab, 0x80, 0xb6, 0xda, 0x63, 0x96, 0xc6, 0x1b, 0x08, 0x15, 0x4b, 0x7d, 0x0c, 0xa1, + 0x81, 0xc3, 0xef, 0x70, 0x00, 0x09, 0xbe, 0xe4, 0x9a, 0x6c, 0xee, 0x6d, 0x7e, 0x4f, 0xfb, 0xfc, 0xe1, 0x70, 0x7e, + 0x89, 0xa0, 0x74, 0x29, 0x7c, 0xa4, 0x12, 0x51, 0x3d, 0xc5, 0x4d, 0x09, 0xd9, 0x2c, 0x59, 0xe9, 0x07, 0xbf, 0xaa, + 0x5f, 0x00, 0x20, 0x0b, 0x81, 0x36, 0x91, 0xd9, 0x9f, 0xce, 0x54, 0x74, 0x01, 0x70, 0x88, 0x3f, 0x7e, 0x82, 0xe8, + 0x1b, 0x5a, 0xa6, 0xe5, 0xe3, 0x84, 0x87, 0xa0, 0xb5, 0x25, 0x9d, 0x44, 0xac, 0x14, 0xd8, 0x10, 0x09, 0xdf, 0xef, + 0x9f, 0xc7, 0x92, 0x0e, 0x34, 0x6a, 0x75, 0x6f, 0xdc, 0xea, 0x5e, 0xf9, 0xba, 0xee, 0xe4, 0xc6, 0x07, 0x45, 0xfb, + 0x6c, 0xde, 0xa8, 0x7c, 0xdf, 0xd6, 0x39, 0xbb, 0xd3, 0xbd, 0x23, 0xe7, 0xc4, 0xb7, 0xf7, 0x10, 0x8a, 0x1e, 0x9a, + 0x22, 0xcb, 0x92, 0x30, 0xa0, 0xb5, 0x76, 0xed, 0x59, 0x46, 0x07, 0xaf, 0x7d, 0x43, 0x88, 0xc8, 0x53, 0x7c, 0x12, + 0x72, 0x8b, 0xe3, 0x83, 0x02, 0xfd, 0x33, 0xe3, 0xcf, 0x9c, 0xf8, 0x61, 0xab, 0x5f, 0x00, 0xe7, 0xa6, 0x7b, 0xef, + 0x4e, 0xcc, 0x7a, 0x0c, 0xa5, 0x6c, 0xfc, 0xdf, 0xef, 0x13, 0x59, 0xa0, 0xd3, 0x11, 0x0d, 0x03, 0xc1, 0x5d, 0x54, + 0xff, 0xf7, 0x8a, 0xd7, 0x3d, 0x6b, 0x75, 0xbe, 0xfc, 0xd4, 0xe9, 0x49, 0xaf, 0x5e, 0xc6, 0x3d, 0xa0, 0x42, 0x07, + 0x08, 0xe7, 0x75, 0xbf, 0x61, 0xbb, 0x6f, 0x7e, 0x79, 0x77, 0xf4, 0x32, 0xb0, 0x49, 0x91, 0xd8, 0x56, 0xf2, 0x59, + 0x0f, 0x14, 0x7e, 0x3d, 0xd6, 0xab, 0x8b, 0x75, 0x8f, 0xf5, 0x50, 0x0b, 0x88, 0x1e, 0x16, 0xa0, 0xfe, 0xeb, 0xd9, + 0xa7, 0xa1, 0x70, 0x90, 0x8d, 0x53, 0x05, 0x8a, 0x2c, 0xf8, 0x0b, 0x31, 0x5a, 0x17, 0x04, 0x88, 0x6c, 0x09, 0x69, + 0xd5, 0xc9, 0xec, 0x71, 0xa9, 0x25, 0x19, 0x7c, 0x13, 0x90, 0xd9, 0x81, 0x95, 0x13, 0x94, 0x8e, 0x5b, 0x03, 0xae, + 0x6c, 0xf1, 0x68, 0xb7, 0x3f, 0x0d, 0xb2, 0xb3, 0xe6, 0xa4, 0xd1, 0x3e, 0xec, 0xd3, 0x3c, 0x40, 0x20, 0x92, 0xa9, + 0x08, 0x72, 0xcd, 0xbd, 0x25, 0x7d, 0x74, 0x38, 0xe7, 0x85, 0xfc, 0x73, 0x2a, 0x75, 0x88, 0x43, 0x89, 0x35, 0x10, + 0xa8, 0x3c, 0x43, 0x95, 0xc3, 0x06, 0x39, 0xfe, 0xd9, 0x91, 0xcc, 0x24, 0x26, 0x8b, 0xdc, 0xad, 0x99, 0x0a, 0x3f, + 0x10, 0x7c, 0xcc, 0x72, 0x0e, 0x5c, 0x60, 0xb3, 0xb9, 0xaf, 0xa6, 0xb8, 0xb8, 0x02, 0x7f, 0x4c, 0xe1, 0x57, 0x3c, + 0x85, 0x9d, 0x76, 0xbf, 0x2e, 0xaa, 0x14, 0x75, 0x1b, 0x85, 0x45, 0x25, 0x0b, 0xa6, 0x35, 0xa4, 0x89, 0x0e, 0xa3, + 0x3f, 0xc8, 0x19, 0x28, 0x08, 0xf9, 0x65, 0xd3, 0x00, 0x23, 0x95, 0x5c, 0x1e, 0x54, 0x49, 0xe0, 0x05, 0xd8, 0x06, + 0x15, 0x5b, 0x17, 0x10, 0x64, 0x9b, 0x14, 0x65, 0xfa, 0xa5, 0xc8, 0xeb, 0x30, 0x0b, 0xaa, 0x51, 0x5a, 0xfd, 0xa8, + 0x7f, 0x02, 0xf3, 0x36, 0x15, 0xa3, 0x5a, 0xc5, 0xe4, 0x37, 0xfa, 0xfd, 0x62, 0xd0, 0xfa, 0x90, 0xc1, 0x47, 0xaf, + 0x4d, 0x83, 0x3f, 0x3a, 0x0d, 0x76, 0x98, 0x68, 0x04, 0x40, 0x32, 0xa7, 0x96, 0x3c, 0x14, 0xfd, 0x11, 0xe4, 0x58, + 0xa3, 0xca, 0x29, 0x18, 0xac, 0xff, 0x78, 0xb4, 0x03, 0x53, 0x2f, 0x8e, 0xb6, 0x64, 0x07, 0xad, 0x7c, 0x03, 0xdc, + 0xaf, 0x91, 0x2d, 0x66, 0x39, 0x40, 0xb3, 0xd7, 0x88, 0x8c, 0x4f, 0x5e, 0x00, 0x63, 0xb6, 0xce, 0xc2, 0x48, 0xc4, + 0xc1, 0x58, 0x35, 0x66, 0xcc, 0xc0, 0xc0, 0x05, 0xba, 0x96, 0x49, 0x49, 0x1a, 0xd2, 0xc1, 0x80, 0x95, 0xb2, 0x85, + 0x03, 0x5e, 0x34, 0xc7, 0xed, 0x78, 0xd3, 0xa2, 0xf1, 0xc0, 0x76, 0xb1, 0xfd, 0xfd, 0xf7, 0xc5, 0xf6, 0x3a, 0xdc, + 0x92, 0x5e, 0x21, 0x67, 0x09, 0xfd, 0xfc, 0x51, 0xf6, 0x59, 0xc3, 0xc9, 0xa9, 0xd0, 0x0c, 0x2d, 0x45, 0x42, 0x29, + 0xde, 0xe9, 0x49, 0x81, 0xb1, 0x8c, 0x85, 0xbf, 0x07, 0xce, 0xe9, 0x42, 0x11, 0xb9, 0x03, 0xc7, 0xf1, 0x0d, 0x54, + 0x30, 0x6a, 0x38, 0x78, 0x19, 0xc3, 0xb6, 0x28, 0x66, 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, + 0xe5, 0x41, 0x04, 0x90, 0xcf, 0xe1, 0x7d, 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, 0x8b, 0x33, 0xd8, 0x38, + 0xd7, 0x99, 0xe0, 0xc0, 0x8b, 0xa4, 0xd6, 0x6b, 0xc6, 0x5f, 0x64, 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, 0xfe, 0x5c, 0x49, 0x1c, 0x5a, 0x16, 0xc9, 0xbf, 0x77, 0x3d, + 0x7d, 0x85, 0xd4, 0x9d, 0x2c, 0x90, 0x19, 0xe3, 0x65, 0x1e, 0x7f, 0x02, 0xc2, 0x6c, 0xd0, 0x46, 0x45, 0x21, 0x84, + 0x6c, 0x10, 0x83, 0xc6, 0xcb, 0x3c, 0xfe, 0x5e, 0xd1, 0x78, 0xc8, 0x47, 0x91, 0xaf, 0xfe, 0x2a, 0xf5, 0x5f, 0xa1, + 0xcf, 0x4c, 0xf0, 0x08, 0xd5, 0x44, 0xff, 0xee, 0xf9, 0xec, 0x1e, 0xd4, 0x86, 0x51, 0x98, 0x99, 0xf2, 0x2b, 0xdf, + 0x14, 0x67, 0xaf, 0xbf, 0xa2, 0xab, 0x6c, 0xeb, 0x7e, 0xf4, 0xf1, 0x88, 0xc0, 0xda, 0x18, 0x5d, 0x71, 0x63, 0x00, + 0x39, 0x4c, 0xde, 0xaf, 0x28, 0x2d, 0x87, 0x34, 0x08, 0x1d, 0x34, 0x04, 0xbd, 0x92, 0xe8, 0x03, 0x89, 0x45, 0x8c, + 0xe1, 0x85, 0x78, 0x46, 0x6a, 0x32, 0xd1, 0x10, 0xaf, 0x88, 0xfd, 0x10, 0x2d, 0x39, 0x35, 0xd1, 0x8d, 0x30, 0xc5, + 0x40, 0x62, 0x67, 0x90, 0x9c, 0x24, 0xb5, 0xf2, 0x8b, 0x67, 0x92, 0xb0, 0xc4, 0xce, 0x43, 0x0c, 0x26, 0xb5, 0x74, + 0xa7, 0x37, 0x55, 0x7a, 0x77, 0xa4, 0xe5, 0xa0, 0x7d, 0x00, 0x76, 0x29, 0xe9, 0xfd, 0x93, 0x42, 0x11, 0x1f, 0xc2, + 0x38, 0x86, 0xf0, 0x2d, 0xa2, 0xba, 0x02, 0xe7, 0x5a, 0x81, 0xc6, 0x6a, 0xe0, 0xa1, 0x99, 0x55, 0xf3, 0x21, 0xa7, + 0x9f, 0x4a, 0xcb, 0x1f, 0x23, 0x1a, 0x1b, 0xad, 0x9b, 0xc3, 0x61, 0x4f, 0xab, 0x5e, 0x3a, 0x07, 0x5d, 0x36, 0x93, + 0x98, 0xb8, 0x81, 0x74, 0xfd, 0xe8, 0x37, 0x13, 0xf6, 0x22, 0x2a, 0xe4, 0x52, 0x08, 0x0a, 0x5a, 0x1d, 0x08, 0x1c, + 0x0a, 0x6f, 0x51, 0xe6, 0x8b, 0x98, 0x36, 0x10, 0x06, 0x9f, 0x1f, 0xc8, 0xcf, 0x37, 0x05, 0xa9, 0xd8, 0xb1, 0xae, + 0xfd, 0xfe, 0xa6, 0xf4, 0x00, 0x4f, 0xce, 0x24, 0x79, 0xda, 0x0c, 0x61, 0x45, 0x00, 0x8d, 0x59, 0x4d, 0x16, 0x27, + 0x5c, 0x99, 0xc3, 0x8f, 0x95, 0x57, 0xb2, 0x94, 0xa9, 0xf3, 0x54, 0x2f, 0x80, 0xa8, 0xe3, 0x0d, 0x5a, 0x91, 0xfa, + 0x15, 0x3a, 0x7b, 0xcd, 0x4a, 0xc8, 0x78, 0x78, 0xce, 0x79, 0x3a, 0x7a, 0x60, 0x09, 0x8f, 0xf0, 0xaf, 0x64, 0xa2, + 0x0f, 0xbf, 0x07, 0x0e, 0x37, 0xe3, 0x84, 0x47, 0x6e, 0xb3, 0xf7, 0x55, 0xb8, 0x82, 0x9b, 0x69, 0x01, 0x48, 0x6e, + 0x41, 0xd2, 0x04, 0x94, 0x90, 0xc8, 0x84, 0xcc, 0x9a, 0x92, 0x9f, 0x5b, 0xda, 0x06, 0x6b, 0x98, 0x74, 0x1e, 0xf0, + 0xa2, 0xd5, 0x47, 0xab, 0x89, 0x76, 0x99, 0xe5, 0xf3, 0x21, 0xce, 0x50, 0xcd, 0x71, 0x77, 0x06, 0x3f, 0x07, 0xbc, + 0x62, 0x55, 0x93, 0x8e, 0x76, 0x03, 0x2e, 0x3c, 0xb9, 0xce, 0xd3, 0xd1, 0x16, 0x7f, 0xc9, 0xfd, 0x01, 0xa0, 0x83, + 0xa9, 0x4b, 0xe0, 0x4f, 0xd5, 0x56, 0x53, 0xa9, 0x5f, 0x5a, 0xfb, 0x75, 0xdd, 0x59, 0xad, 0xdc, 0xb3, 0x2e, 0x43, + 0x7b, 0x64, 0xc8, 0x19, 0x33, 0xe0, 0xcf, 0x19, 0x4b, 0xfe, 0x9c, 0xb1, 0xe2, 0xcf, 0x19, 0x37, 0x46, 0x06, 0x50, + 0x82, 0x7b, 0xc9, 0x5f, 0xec, 0x11, 0x33, 0xc4, 0x6a, 0x50, 0x09, 0xac, 0x2c, 0xe5, 0xdc, 0x47, 0x4e, 0x31, 0xe5, + 0x94, 0xe1, 0xa5, 0xd3, 0x99, 0x3b, 0x90, 0xf3, 0x60, 0xe6, 0x0e, 0x93, 0xb3, 0x3e, 0xc5, 0xb1, 0x34, 0x26, 0x45, + 0x05, 0xe9, 0x9c, 0x0e, 0x37, 0xaf, 0x8e, 0xf3, 0x84, 0x65, 0x7c, 0xdc, 0x3e, 0x53, 0x20, 0xc4, 0x16, 0xcf, 0x90, + 0x48, 0xa9, 0x9a, 0xe5, 0x36, 0x7f, 0x38, 0xd4, 0xa3, 0x07, 0xbd, 0xd3, 0xc3, 0xaf, 0x84, 0xfd, 0x92, 0x79, 0xf6, + 0x09, 0x02, 0x98, 0x24, 0xf2, 0x4c, 0xc2, 0xd1, 0x8f, 0xe5, 0xe8, 0x6f, 0x1a, 0xfe, 0x2e, 0x43, 0x75, 0x77, 0x08, + 0x4c, 0x6c, 0xd9, 0x81, 0x43, 0x70, 0xba, 0xaa, 0x44, 0x02, 0x0e, 0x36, 0x1b, 0x16, 0xe9, 0x3d, 0x1e, 0xe2, 0x7c, + 0x50, 0xf8, 0x08, 0x0d, 0x33, 0x7a, 0xbf, 0xbf, 0x11, 0x5e, 0x25, 0x5b, 0x79, 0x38, 0x24, 0xd6, 0x5d, 0xd8, 0xd1, + 0xc7, 0xd1, 0x1e, 0x25, 0xd4, 0x7e, 0x54, 0xeb, 0x4d, 0xa5, 0x1e, 0xe4, 0x66, 0x17, 0x12, 0x83, 0x8a, 0xa5, 0xfa, + 0xf4, 0x4a, 0xf5, 0xa1, 0x66, 0x9d, 0xdf, 0xd5, 0x71, 0x9f, 0x8a, 0xd1, 0x5a, 0x4e, 0x08, 0x70, 0x1d, 0x24, 0x1a, + 0x1d, 0x00, 0xe3, 0x6c, 0xb3, 0xe5, 0xa5, 0xb6, 0x4e, 0x94, 0x8e, 0xe3, 0x5c, 0x1f, 0xc7, 0x87, 0x83, 0x14, 0x33, + 0x2e, 0x8f, 0xc4, 0x8c, 0xcb, 0x06, 0xe0, 0xcd, 0x3a, 0x0f, 0xea, 0xc3, 0xe1, 0x92, 0x2e, 0x45, 0xa6, 0xb3, 0x8d, + 0xf2, 0xb3, 0x1e, 0x3d, 0x3c, 0x4b, 0xd0, 0xdc, 0x5b, 0x61, 0xef, 0x45, 0xb2, 0x3d, 0x93, 0x75, 0xea, 0x65, 0xe4, + 0xd3, 0x0b, 0xf7, 0xec, 0x92, 0xab, 0x1f, 0x56, 0x5f, 0x4f, 0x7f, 0x15, 0x5e, 0xc4, 0x2a, 0xda, 0xad, 0x4b, 0x26, + 0xec, 0x2d, 0xa5, 0x92, 0x56, 0x79, 0xf9, 0x74, 0xe3, 0x07, 0x98, 0x99, 0xf6, 0xf4, 0x41, 0x36, 0xa2, 0xfa, 0xb3, + 0x12, 0xb5, 0x32, 0x4c, 0x16, 0xce, 0x4b, 0xa6, 0x9e, 0x0c, 0x78, 0xcc, 0x4a, 0x1e, 0xc9, 0x4e, 0x6f, 0x0c, 0x82, + 0x00, 0xd6, 0x39, 0x69, 0xd5, 0x19, 0x47, 0xa3, 0x55, 0xe5, 0xe2, 0x74, 0x95, 0x0b, 0x0c, 0xb7, 0x5b, 0xb3, 0x8d, + 0xaa, 0xb3, 0xdc, 0xd4, 0x2a, 0xe5, 0x3b, 0x80, 0x8f, 0x65, 0x95, 0x0b, 0x3a, 0xa6, 0x4c, 0x9d, 0x37, 0x10, 0x8c, + 0xad, 0x6a, 0x5c, 0x38, 0x35, 0x2e, 0x78, 0x44, 0xed, 0x6e, 0x9a, 0x7a, 0xb4, 0x05, 0x96, 0xd2, 0xd1, 0x8e, 0x97, + 0xa8, 0x52, 0xf8, 0xbb, 0xe0, 0xfb, 0x30, 0x8e, 0xbf, 0x2f, 0xb6, 0xea, 0x40, 0xbc, 0x2d, 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, 0x09, 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, 0x58, 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, 0x1f, 0x55, 0x36, 0x76, 0x07, 0xe4, 0x90, 0x64, 0xb2, 0xb8, 0x1b, 0xdd, + 0x8a, 0x65, 0x51, 0x8a, 0x9f, 0xb1, 0x1e, 0xae, 0xd9, 0xc2, 0x7d, 0x06, 0x84, 0xf6, 0x13, 0xa5, 0xbd, 0x89, 0x34, + 0x41, 0xf7, 0x1d, 0x5b, 0x01, 0xc8, 0x00, 0x8a, 0xba, 0xda, 0xad, 0xcf, 0xf9, 0x39, 0x92, 0x66, 0x38, 0x8c, 0x6e, + 0x9f, 0xde, 0x05, 0x77, 0x83, 0x4b, 0xd4, 0x4a, 0x5f, 0xb2, 0xb8, 0x85, 0x41, 0xb5, 0x37, 0x4b, 0x38, 0xa8, 0x99, + 0xb5, 0x36, 0x02, 0xc1, 0x64, 0x0f, 0x05, 0x15, 0x73, 0x05, 0xfb, 0xa0, 0x60, 0x2d, 0x79, 0x1d, 0x1c, 0x6e, 0xed, + 0xcb, 0x4a, 0x71, 0xf1, 0xfc, 0x22, 0x69, 0x5d, 0x58, 0xca, 0x8b, 0xe7, 0x0d, 0x18, 0x5c, 0x8e, 0xb0, 0xa9, 0x2a, + 0x7f, 0xb2, 0x01, 0xd0, 0xad, 0x90, 0x22, 0x5e, 0x94, 0xc2, 0xb6, 0x95, 0xcf, 0x9c, 0xb0, 0xc1, 0x86, 0x3d, 0xc0, + 0xbd, 0x32, 0x28, 0x19, 0x5c, 0x88, 0x71, 0xbb, 0xd9, 0x05, 0xb8, 0x82, 0xa1, 0x30, 0xb6, 0xe6, 0x6f, 0x32, 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, 0x7c, 0xce, 0xbc, 0xa5, 0xcf, 0xde, 0x54, 0x32, 0x5a, 0x93, 0x44, + 0x79, 0xf5, 0x70, 0x09, 0x72, 0xc3, 0x72, 0xf4, 0xc0, 0x96, 0x20, 0x4e, 0x2c, 0x47, 0x09, 0x65, 0x74, 0x85, 0x7b, + 0x95, 0xd9, 0x32, 0x11, 0x48, 0x71, 0x60, 0x29, 0xe5, 0xde, 0x62, 0x1d, 0x2c, 0x71, 0x7f, 0x22, 0xb9, 0x80, 0x92, + 0x07, 0x50, 0xae, 0x14, 0x10, 0xf0, 0xe9, 0x00, 0xca, 0x97, 0xf2, 0x22, 0xfc, 0x89, 0x13, 0x35, 0x58, 0x8e, 0x1e, + 0x1a, 0xf6, 0xa3, 0x17, 0x5a, 0xf6, 0x87, 0x3b, 0xad, 0x69, 0x58, 0xf1, 0x3b, 0x98, 0x16, 0x13, 0xb7, 0x2f, 0x57, + 0x76, 0x55, 0x7c, 0xb6, 0x52, 0x67, 0x37, 0x35, 0x24, 0x61, 0x5f, 0x91, 0x55, 0x80, 0x83, 0x55, 0x11, 0xf7, 0x2c, + 0xcb, 0x7d, 0x18, 0xfd, 0xb9, 0x49, 0x4b, 0x61, 0xa1, 0x4a, 0xfa, 0xfb, 0xa6, 0x14, 0x48, 0x65, 0xa2, 0x13, 0x2d, + 0x04, 0x57, 0x60, 0x10, 0xb8, 0x17, 0x79, 0x0d, 0x80, 0x31, 0xe0, 0x52, 0xa0, 0x2c, 0xdb, 0x12, 0x42, 0xaa, 0xfb, + 0x19, 0xa8, 0xed, 0xc4, 0x7d, 0x1a, 0x91, 0xb5, 0x10, 0x7d, 0x15, 0x8c, 0x99, 0xf3, 0x52, 0xba, 0xc5, 0xa6, 0xab, + 0xcd, 0xea, 0x06, 0x9d, 0x4b, 0x5b, 0x6e, 0x7e, 0xc2, 0x16, 0x6b, 0x05, 0xca, 0x26, 0x24, 0x6d, 0xe7, 0x3c, 0x47, + 0xd9, 0x84, 0x96, 0xf6, 0x9e, 0x7a, 0x54, 0xa8, 0x4e, 0xb6, 0x5e, 0xaa, 0xa6, 0x16, 0x61, 0xb5, 0xb8, 0xa8, 0xfc, + 0x00, 0x74, 0x53, 0x69, 0xf5, 0xb2, 0xae, 0xd1, 0x14, 0x6a, 0xb5, 0x70, 0xdc, 0x68, 0x67, 0xd3, 0x65, 0x7a, 0x87, + 0x38, 0xab, 0xd2, 0x0e, 0xfd, 0x7d, 0xa6, 0x5d, 0x2f, 0x3b, 0xfa, 0xcd, 0xb8, 0xba, 0xc0, 0x85, 0xd8, 0x80, 0xcf, + 0xb9, 0xbf, 0xbc, 0xde, 0xf3, 0xb8, 0xe7, 0x1f, 0x0e, 0xc8, 0x9e, 0xd4, 0xfe, 0x50, 0x7d, 0xec, 0x0a, 0x86, 0x2c, + 0x8c, 0x52, 0x7f, 0x91, 0xf2, 0xde, 0x13, 0x1c, 0xf7, 0xcf, 0x55, 0x8f, 0xfd, 0x98, 0xf1, 0x7d, 0x5d, 0x6c, 0xa2, + 0x84, 0xa2, 0x1a, 0x7a, 0xab, 0x62, 0x53, 0x89, 0xb8, 0x78, 0xc8, 0x7b, 0x0c, 0x93, 0x61, 0x2c, 0x64, 0x2a, 0xfc, + 0x29, 0x53, 0xc1, 0x23, 0x84, 0x12, 0x37, 0xeb, 0x1e, 0x69, 0x37, 0x21, 0x4e, 0xa9, 0x16, 0xa5, 0x4c, 0xc6, 0xbf, + 0xf5, 0x13, 0x28, 0xcf, 0x29, 0x5a, 0xa6, 0x1f, 0x15, 0x2e, 0xd3, 0x37, 0xeb, 0xe3, 0xd2, 0x33, 0x11, 0xea, 0xcc, + 0xc5, 0xa6, 0xd6, 0xe9, 0x18, 0x3b, 0xa5, 0x53, 0x1b, 0xf6, 0xa5, 0x52, 0x5c, 0x56, 0x14, 0xfe, 0x8d, 0x44, 0x56, + 0x3d, 0x23, 0x8e, 0xff, 0x2b, 0x6b, 0x9f, 0x61, 0x15, 0xf8, 0x65, 0x20, 0xef, 0x17, 0x00, 0x1f, 0xd7, 0x75, 0x99, + 0xde, 0x6e, 0x80, 0x36, 0x84, 0x86, 0xbf, 0xe7, 0x23, 0x03, 0xa6, 0xfb, 0x08, 0x67, 0x48, 0x0f, 0x75, 0xce, 0xe9, + 0xac, 0x4c, 0xe7, 0x5c, 0x85, 0xb5, 0x04, 0x7b, 0x39, 0x69, 0x72, 0xb9, 0x2e, 0x41, 0xcd, 0x04, 0x6e, 0x1f, 0xda, + 0x23, 0x42, 0xa8, 0x4d, 0x59, 0x4d, 0x2f, 0xa1, 0xe6, 0x9d, 0x9c, 0x76, 0x34, 0x29, 0xc1, 0x55, 0x43, 0x67, 0xe5, + 0xfa, 0xaf, 0xc3, 0xa1, 0x77, 0x9b, 0x15, 0xd1, 0x1f, 0x3d, 0xf4, 0x77, 0xdc, 0xde, 0xa4, 0x5f, 0x20, 0x5a, 0xc6, + 0xfa, 0x1b, 0x32, 0xa0, 0xe3, 0xc9, 0xf0, 0xb6, 0xd8, 0xf6, 0xd8, 0x17, 0xd4, 0x60, 0xe9, 0xeb, 0xc7, 0x1f, 0x20, + 0xa1, 0xea, 0xda, 0x17, 0x16, 0x4f, 0x98, 0xa7, 0x44, 0xdb, 0xc2, 0x87, 0xb0, 0xd0, 0x2f, 0x10, 0x19, 0x09, 0xe1, + 0xa6, 0xb2, 0x7b, 0x94, 0xb4, 0x0b, 0x7d, 0xe9, 0x6b, 0xd9, 0x57, 0xbe, 0x73, 0x01, 0xb0, 0xb2, 0xcf, 0x6d, 0xb8, + 0x27, 0xfd, 0x29, 0xd5, 0x87, 0xed, 0x6f, 0xc9, 0x02, 0x0a, 0x2d, 0xac, 0xa7, 0x72, 0x76, 0xae, 0x4b, 0x9e, 0x66, + 0xd3, 0xfd, 0x1a, 0xf6, 0xa8, 0x7b, 0xf4, 0x9a, 0x0a, 0xce, 0x2f, 0xcd, 0xe8, 0xfd, 0xd3, 0x50, 0xa8, 0x8e, 0x3a, + 0x77, 0x90, 0x75, 0x69, 0x5d, 0x72, 0x7e, 0xb3, 0x72, 0x47, 0x61, 0x7e, 0x1f, 0x82, 0x67, 0x58, 0xf7, 0xee, 0xe2, + 0xbc, 0xf7, 0x67, 0x6b, 0x8e, 0xfc, 0x98, 0xcd, 0x52, 0xc4, 0x22, 0x99, 0x83, 0xd5, 0x0f, 0xfd, 0x3c, 0xf6, 0xdb, + 0x20, 0x87, 0xe3, 0xa6, 0x01, 0x1d, 0x36, 0x64, 0xd6, 0xbe, 0x44, 0xe0, 0x54, 0x23, 0x48, 0x53, 0x13, 0xd4, 0x2c, + 0x0f, 0x91, 0xd8, 0x2e, 0x65, 0xdb, 0x20, 0xd7, 0x5d, 0x30, 0xcd, 0x91, 0xf6, 0x0c, 0xde, 0x37, 0x69, 0x92, 0x0a, + 0xcd, 0x22, 0x6d, 0x95, 0x8c, 0x7f, 0x47, 0xda, 0x4c, 0xc9, 0x1e, 0x5b, 0x03, 0xef, 0x25, 0x28, 0x27, 0xc3, 0x14, + 0xc3, 0x77, 0x7c, 0xbd, 0xf3, 0x98, 0x7b, 0xce, 0x31, 0xdb, 0xa4, 0xec, 0x08, 0x26, 0xc9, 0xc6, 0x37, 0x14, 0x6f, + 0xf8, 0xfe, 0xb6, 0x12, 0x25, 0x80, 0x5e, 0x16, 0xfc, 0x85, 0xb4, 0xb9, 0x42, 0xb7, 0xbb, 0x77, 0x94, 0xc2, 0x2f, + 0x79, 0x79, 0x38, 0x6c, 0x53, 0x2f, 0x84, 0xce, 0x17, 0xf1, 0x3b, 0x30, 0x87, 0x31, 0xc4, 0x66, 0x04, 0x08, 0x73, + 0x7c, 0x40, 0x1d, 0xac, 0x1f, 0x01, 0x68, 0x9c, 0x40, 0x01, 0x46, 0x5f, 0x6d, 0x0b, 0xfa, 0x96, 0x17, 0x17, 0x11, + 0xa2, 0x46, 0x01, 0x26, 0x4a, 0x9a, 0xc5, 0x30, 0x1c, 0xe8, 0xfc, 0xbe, 0xb9, 0xad, 0x4b, 0x81, 0x43, 0xef, 0x58, + 0x86, 0xff, 0xfe, 0x3f, 0xd6, 0x96, 0x56, 0x95, 0xed, 0xd6, 0x38, 0xcd, 0xfc, 0x6f, 0xb7, 0x85, 0xbe, 0xff, 0x4a, + 0x28, 0x9e, 0x77, 0xbc, 0x6e, 0xbf, 0x83, 0xe8, 0x7d, 0xdd, 0xca, 0xbb, 0x52, 0xbb, 0x61, 0xa6, 0xfc, 0x21, 0xcd, + 0xe3, 0xe2, 0x61, 0x14, 0xb7, 0x8e, 0xbc, 0x49, 0x7a, 0xce, 0xf9, 0xbb, 0xaa, 0xdf, 0xf7, 0xde, 0x01, 0x19, 0xef, + 0x2b, 0x61, 0x1c, 0x31, 0x89, 0x83, 0x6f, 0x2f, 0x46, 0xd1, 0xa6, 0x84, 0x0d, 0xb9, 0x7d, 0x5a, 0x82, 0x66, 0xa6, + 0xdf, 0x47, 0x89, 0xd2, 0x9a, 0xef, 0x7f, 0x93, 0xf3, 0xfd, 0x95, 0x90, 0x37, 0x2b, 0xf9, 0xe1, 0xa3, 0x15, 0x06, + 0xbe, 0xc7, 0xe9, 0x17, 0xd1, 0x63, 0x77, 0xa5, 0x0f, 0xdf, 0x95, 0x96, 0x3e, 0xab, 0xa8, 0x7f, 0xa0, 0xa2, 0xe6, + 0x95, 0x18, 0x11, 0xf1, 0x20, 0x68, 0x67, 0xdb, 0xa5, 0x76, 0x2d, 0x41, 0xbb, 0x60, 0x53, 0xd8, 0xbf, 0x1f, 0x1d, + 0xf2, 0x7e, 0xff, 0x63, 0xee, 0xb5, 0x78, 0xdd, 0x75, 0x68, 0xca, 0x4f, 0x85, 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, 0x11, 0xeb, 0xa6, 0xa7, 0x55, 0x68, 0xf9, 0x1a, 0x82, 0x75, 0x91, 0x65, 0x1c, 0xc5, + 0x4c, 0x00, 0xb0, 0xf9, 0x08, 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, + 0x7b, 0xaa, 0x7a, 0x44, 0xa0, 0x57, 0x65, 0x5a, 0x45, 0x45, 0x9e, 0x8b, 0x08, 0x11, 0xaa, 0xa5, 0x73, 0x38, 0xf4, + 0x63, 0xbf, 0x8f, 0x03, 0x61, 0x5e, 0xfc, 0xe9, 0xb1, 0xae, 0xfc, 0xa9, 0xc0, 0xb5, 0x92, 0x02, 0xa7, 0xa2, 0x46, + 0x88, 0x10, 0xde, 0x9f, 0xc0, 0xb3, 0x9a, 0xfa, 0x7e, 0x63, 0x99, 0xe8, 0xfe, 0x99, 0x01, 0xe5, 0x0f, 0xc8, 0xd7, + 0x95, 0x14, 0x67, 0xea, 0xe4, 0x31, 0x71, 0xc6, 0x01, 0x88, 0xf9, 0xba, 0x44, 0xa3, 0xb1, 0xff, 0x01, 0x09, 0x86, + 0xea, 0x07, 0x3b, 0xdd, 0xd4, 0xfb, 0x57, 0x26, 0x71, 0x14, 0x7d, 0xda, 0x26, 0x8f, 0x25, 0x4b, 0xa3, 0x85, 0xa3, + 0xf7, 0x88, 0x61, 0x1c, 0x4e, 0xe7, 0x63, 0x92, 0x6d, 0x4c, 0x56, 0x01, 0xa4, 0x93, 0x99, 0x3a, 0xa6, 0xd4, 0xd1, + 0x38, 0xd7, 0x0b, 0xaa, 0xd0, 0x63, 0x5d, 0xf2, 0x1c, 0xac, 0x27, 0x3f, 0x78, 0xa5, 0x3f, 0x15, 0x72, 0x0e, 0x1b, + 0x89, 0xa0, 0xf0, 0x03, 0x5c, 0x0d, 0x56, 0x0a, 0x18, 0x4c, 0x7d, 0x0b, 0x5f, 0x13, 0xcf, 0x51, 0xf0, 0x28, 0xec, + 0x62, 0x6c, 0xad, 0x7c, 0xe7, 0x93, 0x82, 0x72, 0xcf, 0x8a, 0x39, 0xaf, 0x80, 0x73, 0x19, 0x14, 0xc2, 0x74, 0x3c, + 0xcb, 0xff, 0x99, 0xe4, 0xf5, 0xc4, 0x86, 0x00, 0x19, 0xfc, 0x29, 0x71, 0x5a, 0xba, 0x43, 0x77, 0x1e, 0x7a, 0x16, + 0x71, 0xd8, 0xe8, 0xc9, 0xba, 0x2c, 0xb6, 0x29, 0xea, 0x25, 0xcc, 0x0f, 0xe4, 0xe7, 0x2d, 0xf9, 0x3e, 0x44, 0xf1, + 0x36, 0xf8, 0x35, 0x63, 0xb1, 0xc0, 0xbf, 0xfe, 0x9e, 0x31, 0x9a, 0x68, 0xc1, 0xbf, 0xb3, 0x06, 0x89, 0x8a, 0x7f, + 0xca, 0x26, 0x00, 0xeb, 0xc8, 0xd5, 0x87, 0x4f, 0x89, 0xf1, 0xd6, 0x6c, 0x78, 0xe4, 0x9b, 0x15, 0xe8, 0xd4, 0xe7, + 0xee, 0xca, 0xf6, 0x54, 0x35, 0xfe, 0x9e, 0xea, 0x6a, 0xa4, 0xaa, 0x1a, 0x7f, 0x4f, 0xa9, 0x1a, 0xbf, 0x65, 0x14, + 0xbf, 0x53, 0xf9, 0x0c, 0x99, 0x93, 0x4d, 0x4c, 0xd2, 0xe9, 0x7b, 0xc3, 0x89, 0x5d, 0xf6, 0xab, 0xb7, 0x89, 0xcc, + 0x44, 0x0a, 0xb9, 0x37, 0x00, 0x6d, 0xbf, 0xcb, 0x0d, 0xa7, 0xc4, 0xf9, 0xb9, 0x87, 0x2b, 0x36, 0xad, 0x5e, 0xd1, + 0x82, 0x05, 0x36, 0x2f, 0xb3, 0x3c, 0x45, 0x02, 0xdb, 0xa6, 0xcc, 0xfa, 0x73, 0xee, 0x01, 0x04, 0x33, 0xa9, 0x09, + 0x00, 0x69, 0x21, 0x2a, 0x85, 0xc8, 0x5f, 0xe1, 0xac, 0x3e, 0xe7, 0xbd, 0x4d, 0x1e, 0x13, 0x69, 0x75, 0xaf, 0xdf, + 0x4f, 0xcf, 0xd2, 0x9c, 0x82, 0x1a, 0x8e, 0xb3, 0x4e, 0xbf, 0xcf, 0x82, 0x3a, 0x91, 0xab, 0xf4, 0x1f, 0x6e, 0x90, + 0x97, 0xf1, 0x7d, 0xdd, 0xf6, 0xfc, 0x89, 0xfa, 0x7b, 0x67, 0xfd, 0x6d, 0x81, 0xe0, 0x4e, 0x8e, 0xfd, 0x64, 0x55, + 0xca, 0x13, 0xe3, 0xd2, 0xde, 0xf3, 0x9b, 0xba, 0x28, 0xb2, 0x3a, 0x5d, 0x7f, 0x90, 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, 0xe8, 0x40, 0xbd, 0xb4, 0xd2, 0x3e, 0x82, 0x6e, + 0x05, 0x7a, 0x50, 0x0f, 0x7d, 0x9a, 0xb4, 0x2f, 0x24, 0xea, 0xf6, 0x56, 0xa7, 0xd1, 0x1f, 0x15, 0x5c, 0x4e, 0x61, + 0x72, 0xb8, 0xa1, 0x4f, 0xab, 0x70, 0xfb, 0x09, 0x9e, 0xfe, 0x0c, 0x94, 0x5b, 0x87, 0x43, 0x0e, 0x62, 0x0b, 0xb8, + 0x79, 0xac, 0xc2, 0xcf, 0x45, 0x29, 0x23, 0xea, 0xe3, 0x69, 0x01, 0xda, 0xbb, 0x00, 0x1d, 0xb0, 0x34, 0x88, 0x57, + 0x48, 0x9e, 0xb3, 0x11, 0xc0, 0xb2, 0x03, 0xcb, 0x59, 0xc6, 0x29, 0xcc, 0xb3, 0x7c, 0xa1, 0x56, 0xda, 0x59, 0x99, + 0x78, 0x35, 0xcb, 0xc0, 0x59, 0xe0, 0xa2, 0xf2, 0x59, 0xa6, 0x55, 0x4f, 0x55, 0x82, 0x3e, 0xaf, 0xe4, 0x04, 0x57, + 0x82, 0x93, 0x0d, 0xc8, 0x2f, 0x40, 0x92, 0xa6, 0x94, 0x35, 0xe5, 0x8b, 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, 0x3f, + 0x78, 0x4b, 0x7f, 0x3a, 0x0e, 0xc2, 0x21, 0x72, 0x43, 0xc5, 0x1c, 0xd8, 0xd3, 0x80, 0xc5, 0x26, 0xbe, 0xda, 0x4c, + 0xe2, 0xc1, 0xc0, 0xd7, 0x19, 0x8b, 0x59, 0x0c, 0x34, 0xc8, 0xf1, 0xe0, 0x72, 0xae, 0x4f, 0x08, 0xfd, 0x30, 0xa2, + 0x72, 0x54, 0xa0, 0x73, 0x10, 0x0d, 0x96, 0x80, 0xa7, 0xde, 0xca, 0x06, 0x49, 0xc6, 0x24, 0x93, 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, 0x3f, 0xcb, 0x07, 0x8e, 0x3b, 0x2a, 0x69, + 0x08, 0x0c, 0xde, 0x1e, 0xba, 0x9b, 0x19, 0x1a, 0xea, 0xa4, 0x7d, 0x18, 0x87, 0x72, 0x88, 0x55, 0x2b, 0x2e, 0xa4, + 0x37, 0x82, 0x6f, 0x17, 0x8a, 0xb1, 0x6c, 0xec, 0xd2, 0x50, 0x14, 0xfe, 0x0a, 0x60, 0x87, 0xda, 0x5f, 0xa9, 0xe4, + 0x63, 0x64, 0x54, 0xd3, 0x40, 0xc7, 0x00, 0x2c, 0x59, 0x9a, 0x48, 0xaa, 0x48, 0x23, 0xf1, 0x47, 0x66, 0xac, 0xa3, + 0xa6, 0xeb, 0x0b, 0xa6, 0xaa, 0x45, 0xd2, 0xed, 0x4c, 0x62, 0x39, 0x91, 0xa4, 0xb6, 0xfb, 0x88, 0x18, 0x0c, 0x7c, + 0xb0, 0x11, 0xd3, 0x4c, 0x84, 0x23, 0x1e, 0x95, 0xc8, 0xa2, 0xcb, 0x6f, 0xa3, 0x4c, 0xda, 0xbe, 0xac, 0xc8, 0x16, + 0x04, 0xd3, 0x93, 0xe8, 0x83, 0x24, 0xe5, 0x54, 0x24, 0xd2, 0x8c, 0x10, 0xe0, 0xc7, 0x93, 0xf2, 0x4a, 0x7f, 0x0e, + 0x9a, 0x56, 0x82, 0x97, 0x0c, 0x92, 0x47, 0xe2, 0x67, 0x52, 0x30, 0x8b, 0xb1, 0x6a, 0x30, 0xc0, 0x72, 0xaa, 0x67, + 0x8e, 0x49, 0xfa, 0x6f, 0x9d, 0x4e, 0xd8, 0x2f, 0xbd, 0xdc, 0xd6, 0xf2, 0xa6, 0xb9, 0xf7, 0xd2, 0xab, 0x58, 0xaa, + 0x61, 0x19, 0xf4, 0x5f, 0x13, 0xed, 0x82, 0xad, 0x2d, 0x63, 0xc2, 0xaa, 0x1f, 0x40, 0xda, 0x23, 0x5d, 0x5e, 0x35, + 0xcc, 0x99, 0xe0, 0xd1, 0x85, 0x35, 0x0f, 0xa2, 0x0b, 0xe1, 0x23, 0x97, 0xdd, 0x24, 0xb9, 0x1a, 0x4f, 0xfc, 0x70, + 0x30, 0x50, 0x00, 0xb4, 0xb4, 0x4e, 0x8a, 0x41, 0xf8, 0x4c, 0xc8, 0x81, 0x34, 0x3a, 0xaa, 0x02, 0x2c, 0x96, 0xd9, + 0x55, 0x39, 0xc9, 0x06, 0x03, 0x1f, 0xc4, 0xc6, 0xc4, 0x6e, 0x68, 0x36, 0xf7, 0xd9, 0x89, 0x82, 0xac, 0x36, 0x87, + 0xad, 0x99, 0x6e, 0x81, 0x01, 0xc0, 0x20, 0x22, 0x58, 0xee, 0x73, 0x23, 0x1f, 0x51, 0xa7, 0xa7, 0x30, 0x02, 0x82, + 0x5f, 0x4e, 0x04, 0x22, 0x17, 0x09, 0xd4, 0x03, 0xcc, 0x04, 0x98, 0x51, 0xc5, 0xf0, 0x12, 0xd8, 0xc5, 0x73, 0xf3, + 0x8a, 0x41, 0xff, 0xa2, 0x49, 0x96, 0x68, 0x2a, 0x71, 0x34, 0x46, 0x4e, 0xa5, 0x31, 0x32, 0x20, 0x76, 0x71, 0xfc, + 0x7b, 0x4a, 0x8f, 0x82, 0x94, 0x7d, 0xae, 0x0c, 0x71, 0x38, 0x8a, 0xaf, 0x60, 0xd5, 0x38, 0x1c, 0x6a, 0xf3, 0x7a, + 0x3a, 0xab, 0xe7, 0x03, 0x11, 0xc0, 0x7f, 0x43, 0xc1, 0x7e, 0xd1, 0x54, 0xe4, 0x06, 0xa9, 0xf3, 0x70, 0x48, 0x41, + 0x3e, 0xd5, 0x4d, 0xfe, 0xbe, 0x72, 0xf7, 0xd3, 0xd9, 0xdc, 0x9a, 0xa3, 0x17, 0x35, 0xae, 0x5b, 0xab, 0x1b, 0x0a, + 0x89, 0xd6, 0x34, 0x29, 0xae, 0xaa, 0x49, 0x31, 0xe0, 0xb9, 0x2f, 0x54, 0x17, 0x5b, 0x23, 0x58, 0xf8, 0x73, 0x0b, + 0x84, 0xc9, 0xb8, 0x17, 0x1f, 0x2d, 0xe4, 0x94, 0x76, 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, 0xf3, 0x20, 0xe3, 0x5e, 0x34, 0xec, 0xf8, 0x02, 0xec, 0xd5, 0x17, 0xcf, + 0x59, 0x34, 0xe0, 0xd5, 0x55, 0x3d, 0xcd, 0x82, 0x61, 0xc6, 0xa2, 0xab, 0x62, 0x08, 0x3e, 0xb4, 0x2f, 0xca, 0x41, + 0xe8, 0xfb, 0x66, 0xe7, 0xd0, 0xdd, 0x90, 0xc8, 0x23, 0xec, 0x47, 0x70, 0xdb, 0xd5, 0x12, 0x33, 0x98, 0x6c, 0xee, + 0x22, 0x66, 0xb0, 0xe5, 0x2f, 0x9e, 0x1b, 0x2e, 0xa1, 0xea, 0x85, 0xd4, 0x6c, 0x14, 0x68, 0x4e, 0xae, 0xd0, 0x9c, + 0xac, 0x84, 0x5a, 0xf2, 0x49, 0x85, 0x13, 0x76, 0x3e, 0xc9, 0x95, 0xdd, 0x68, 0x8c, 0x81, 0x8b, 0xf6, 0xdc, 0x16, + 0x46, 0x66, 0x3a, 0x4b, 0xd1, 0x80, 0x85, 0x67, 0xe2, 0x94, 0xc6, 0x80, 0xf6, 0xe5, 0xc0, 0xd2, 0x86, 0xfc, 0x28, + 0x67, 0x06, 0xda, 0x86, 0x94, 0x46, 0xcd, 0xc0, 0x9f, 0xa9, 0x09, 0xf3, 0x2b, 0x58, 0x89, 0x20, 0xaa, 0x0b, 0x30, + 0x49, 0x72, 0x32, 0x1a, 0x29, 0x2b, 0x91, 0x9c, 0x03, 0xde, 0x47, 0xf0, 0x64, 0x11, 0xdb, 0xda, 0x9f, 0xd2, 0xff, + 0xea, 0xf0, 0xb9, 0xf4, 0x9f, 0x09, 0x60, 0x21, 0x97, 0x06, 0x91, 0x81, 0xc2, 0x21, 0x35, 0x95, 0x88, 0x13, 0xc7, + 0x33, 0xf0, 0x0d, 0x5c, 0xa0, 0x29, 0xa0, 0x3f, 0xa8, 0x19, 0x45, 0x64, 0xe1, 0xaf, 0x9e, 0xdd, 0xd4, 0x8d, 0x9e, + 0x67, 0xce, 0x6b, 0xd0, 0xcc, 0x40, 0x48, 0x8f, 0x53, 0xf5, 0x36, 0x24, 0x3a, 0x2f, 0x2f, 0xf5, 0xcb, 0x84, 0x48, + 0x56, 0x44, 0x9e, 0xbe, 0xcf, 0xc1, 0x3c, 0xa2, 0x08, 0x1d, 0x5c, 0x99, 0x87, 0xc3, 0xb9, 0xa0, 0xf0, 0x1d, 0xe5, + 0xf9, 0x80, 0xd3, 0x2c, 0x4a, 0x40, 0x1b, 0xc8, 0x72, 0x53, 0xe6, 0x3a, 0x69, 0x99, 0xba, 0xf7, 0x60, 0x25, 0xa8, + 0xd0, 0xcd, 0x29, 0x28, 0x94, 0x91, 0xa0, 0x94, 0x56, 0x83, 0x50, 0xaa, 0xc3, 0x22, 0x88, 0x1c, 0xb2, 0x10, 0x70, + 0x33, 0x15, 0x8d, 0x96, 0x34, 0x3c, 0xc2, 0xb9, 0x81, 0x42, 0x00, 0x12, 0x7b, 0xaa, 0x28, 0xe3, 0x72, 0x08, 0xf8, + 0x28, 0xe1, 0x10, 0x67, 0x4d, 0xda, 0xf2, 0x1c, 0xc4, 0xb1, 0x5c, 0xf2, 0x75, 0x85, 0x60, 0x10, 0xa1, 0xcf, 0x90, + 0x3f, 0x59, 0xce, 0xbf, 0x5b, 0x87, 0x69, 0x47, 0xf8, 0xb0, 0xab, 0x2d, 0xb8, 0x98, 0xdd, 0xce, 0x27, 0x10, 0xdf, + 0x72, 0x3b, 0x3f, 0xc6, 0x10, 0x59, 0xf8, 0x83, 0xbb, 0xa1, 0xe4, 0x8a, 0x42, 0x97, 0xf5, 0x88, 0x14, 0xd9, 0xd3, + 0x35, 0x47, 0x10, 0x1c, 0x68, 0xd5, 0x20, 0x43, 0x23, 0xf1, 0xc5, 0x73, 0xc8, 0x1a, 0xac, 0xf9, 0xe7, 0x8a, 0x9c, + 0xd5, 0xfd, 0xc9, 0x06, 0xaa, 0x49, 0x26, 0x6b, 0x45, 0xe5, 0xfc, 0xf5, 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, 0xff, 0x15, 0xfc, 0x4b, 0x85, 0x2c, 0xd5, 0x69, 0x9d, 0x89, + 0x5f, 0x83, 0x25, 0xc3, 0x3f, 0x7e, 0x0b, 0xd6, 0x80, 0x25, 0x40, 0x96, 0xbb, 0x8d, 0x8d, 0xd6, 0x2b, 0xaf, 0x10, + 0x5f, 0x6a, 0x7d, 0xd1, 0x6f, 0xdd, 0x26, 0x6a, 0x05, 0x18, 0xa1, 0xd0, 0x22, 0xc0, 0x56, 0x0f, 0xdc, 0x53, 0xf0, + 0x03, 0x31, 0x9c, 0x6b, 0xd2, 0x9a, 0x3a, 0xe1, 0x75, 0x36, 0x8e, 0x44, 0x54, 0x6f, 0xe1, 0xe2, 0x5e, 0x6f, 0x2d, + 0xfe, 0x46, 0x05, 0x02, 0x20, 0x8b, 0x29, 0xd6, 0xce, 0x1b, 0xd2, 0x2b, 0xc3, 0x4e, 0x42, 0xef, 0x0d, 0x3b, 0x81, + 0xbc, 0x38, 0xec, 0x14, 0xba, 0x44, 0xdb, 0x29, 0x52, 0x13, 0x6d, 0x27, 0x2d, 0x56, 0x61, 0x09, 0xc1, 0xaf, 0xda, + 0x5b, 0x47, 0xd9, 0xbe, 0xc8, 0x12, 0xa6, 0x2d, 0x60, 0x94, 0x5b, 0xf5, 0x99, 0x53, 0xc4, 0x4a, 0xd9, 0x3b, 0x9d, + 0x54, 0xb9, 0x8b, 0x7c, 0x6a, 0x35, 0x45, 0x26, 0x7f, 0x7f, 0xdc, 0x22, 0xf9, 0xe4, 0xe7, 0x76, 0xc3, 0x64, 0xfa, + 0xc7, 0xa3, 0x2f, 0xa0, 0x2b, 0xb2, 0xd3, 0x27, 0x10, 0x90, 0xa9, 0xa0, 0x5a, 0xdd, 0x2a, 0xa6, 0x79, 0xbb, 0xca, + 0x6e, 0x2f, 0x94, 0x18, 0x4e, 0x67, 0x27, 0xe1, 0xd1, 0x66, 0xc8, 0xc0, 0x21, 0x08, 0x14, 0x42, 0x45, 0x31, 0x3c, + 0x02, 0xb5, 0x46, 0xf2, 0x01, 0x7e, 0xb4, 0x3b, 0x15, 0x44, 0x6a, 0x37, 0x15, 0x37, 0x4e, 0x6e, 0xba, 0x5e, 0x0a, + 0xd4, 0x3a, 0x25, 0x2b, 0x80, 0x12, 0xa2, 0xfe, 0x24, 0xb6, 0xf5, 0x2b, 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, 0x75, 0xbb, 0xe9, 0x98, 0xd8, 0xea, 0x9f, 0x45, 0xb5, 0xb9, 0x83, 0x8a, 0x88, 0xf8, 0x28, 0xbb, 0x79, 0xd2, + 0x7e, 0x07, 0x7b, 0xac, 0xd5, 0x20, 0xb2, 0xcf, 0xe0, 0x2a, 0xd7, 0x69, 0x91, 0xdb, 0x32, 0x38, 0xff, 0xf0, 0x6a, + 0x57, 0x61, 0x93, 0x63, 0x5d, 0x5d, 0xcd, 0x54, 0x27, 0x15, 0x1b, 0x18, 0x6b, 0x5a, 0x4b, 0x35, 0x8f, 0x21, 0xe9, + 0xae, 0x2c, 0xce, 0xaa, 0xa4, 0x9b, 0x9e, 0x1b, 0x67, 0x0a, 0x31, 0x70, 0xb6, 0x1a, 0x2d, 0x67, 0x18, 0xa2, 0xeb, + 0xc3, 0x2c, 0xf1, 0x5b, 0x3d, 0xe5, 0x3e, 0x0f, 0xb7, 0x7e, 0x57, 0x2f, 0x38, 0x99, 0xec, 0x27, 0xc7, 0xb9, 0xdb, + 0x45, 0xda, 0x4f, 0x7c, 0x1b, 0xe6, 0x5f, 0xdf, 0x20, 0xee, 0x44, 0xfd, 0xcf, 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, 0x7f, 0x7a, 0x35, 0x3b, 0x15, 0x54, 0x06, 0x6e, 0xc6, 0x7f, 0x7a, 0x82, 0x9d, 0xc2, 0x5a, + 0x01, 0x59, 0xe1, 0x4f, 0x2f, 0x7f, 0xe4, 0xfd, 0x8a, 0xff, 0xe9, 0x55, 0x8f, 0xbc, 0x8f, 0x38, 0x2f, 0x7f, 0x22, + 0xa9, 0x13, 0xa2, 0xba, 0xfc, 0x49, 0x98, 0x62, 0xab, 0x34, 0x7f, 0x4d, 0x0a, 0x9f, 0xe0, 0x33, 0xf0, 0x1d, 0xae, + 0xc2, 0xad, 0xf9, 0x0d, 0x1e, 0x3b, 0x16, 0xdb, 0x2e, 0xf5, 0x05, 0x94, 0x23, 0xb0, 0x88, 0xdc, 0x7e, 0xbb, 0xb2, + 0x5f, 0x2d, 0x8c, 0x32, 0xc6, 0xee, 0x4b, 0x56, 0xa2, 0x74, 0xd6, 0xef, 0x17, 0x52, 0x30, 0xb2, 0x0b, 0x6b, 0xb4, + 0x47, 0xa9, 0x7a, 0xf5, 0x3a, 0xac, 0xa3, 0x24, 0xcd, 0xef, 0x64, 0xf4, 0x91, 0x0c, 0x3b, 0xd2, 0x57, 0x52, 0xa2, + 0xbd, 0x56, 0x61, 0x39, 0x9a, 0xfd, 0xba, 0xe4, 0x40, 0x79, 0xdd, 0x0a, 0xca, 0x57, 0x4d, 0x00, 0xbd, 0x52, 0xed, + 0x33, 0xd0, 0x0a, 0x0a, 0x4b, 0xe5, 0xc1, 0x4a, 0x9c, 0x8b, 0x3e, 0x2b, 0x0e, 0x07, 0x75, 0x31, 0x24, 0x14, 0xa8, + 0x12, 0x27, 0xa1, 0x11, 0xcf, 0xe1, 0x42, 0x28, 0x5e, 0xe4, 0x18, 0x5b, 0x91, 0x03, 0x07, 0x32, 0xfc, 0x80, 0xc0, + 0x7b, 0xd9, 0xbf, 0x82, 0xc1, 0x30, 0xc1, 0x8d, 0x8c, 0x3a, 0x39, 0x67, 0x7f, 0x62, 0x60, 0x06, 0xf5, 0xa4, 0x76, + 0x9f, 0xdd, 0xab, 0xc0, 0x5e, 0x38, 0x03, 0xda, 0xbb, 0x31, 0xfa, 0x59, 0x15, 0x6b, 0x27, 0xfd, 0x53, 0xb1, 0x86, + 0x64, 0x3a, 0x2c, 0x8e, 0xb6, 0x69, 0x78, 0x24, 0x4f, 0x8e, 0xe3, 0x4d, 0xff, 0x70, 0x18, 0xe3, 0xc7, 0x51, 0x7e, + 0x6d, 0x01, 0xaf, 0xe2, 0x16, 0xd2, 0x58, 0xa4, 0xe8, 0x1d, 0x88, 0x39, 0x14, 0xbd, 0x64, 0xbf, 0x65, 0xbc, 0x9c, + 0x08, 0x4a, 0x49, 0x62, 0xc3, 0x3b, 0xd2, 0xd3, 0xb4, 0x1e, 0x6d, 0x65, 0xc0, 0x7e, 0x3d, 0xda, 0xd1, 0x5f, 0xa0, + 0x78, 0xb4, 0xf0, 0x97, 0xf4, 0x77, 0x71, 0x37, 0xf7, 0x9c, 0x6f, 0x1a, 0xdf, 0x11, 0x17, 0x28, 0xd6, 0xec, 0xfe, + 0x9a, 0x96, 0xce, 0x3a, 0x10, 0x1c, 0xf0, 0x16, 0xbb, 0x68, 0xdf, 0x6f, 0x5c, 0xa7, 0xa7, 0xfd, 0xb7, 0x6e, 0x8d, + 0xf2, 0xbd, 0x7f, 0x4a, 0x94, 0x83, 0xfd, 0x6b, 0x17, 0xcd, 0xdf, 0x7e, 0xca, 0x90, 0x54, 0x68, 0x6e, 0xb0, 0x9d, + 0x6c, 0x11, 0xd6, 0xc6, 0x38, 0xa8, 0xd8, 0x5d, 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, 0x5f, 0x11, 0x3e, 0xd4, 0x4e, 0x4a, 0x87, 0xf2, 0x57, 0xcf, 0xd9, + 0xff, 0xec, 0xb0, 0xa6, 0xa6, 0xdc, 0x00, 0x66, 0xce, 0x4a, 0xe4, 0x15, 0x42, 0xa7, 0xc8, 0xef, 0x55, 0x5d, 0x89, + 0xe1, 0xb2, 0x16, 0x65, 0x67, 0x76, 0xeb, 0x44, 0xef, 0x9c, 0x82, 0x5a, 0x2a, 0x1b, 0xe4, 0x24, 0xd5, 0xe6, 0x23, + 0x6b, 0x05, 0x25, 0xea, 0x1a, 0x05, 0x8e, 0x4f, 0xb9, 0x76, 0xff, 0xef, 0x9c, 0x09, 0x6a, 0xb6, 0x51, 0xdd, 0x5f, + 0xeb, 0xa7, 0xaa, 0x26, 0xb1, 0x00, 0x97, 0x93, 0x34, 0xef, 0x78, 0x84, 0xd5, 0x3f, 0x4e, 0x96, 0x22, 0xd0, 0xeb, + 0x88, 0x76, 0x25, 0x20, 0x41, 0x3b, 0x39, 0x0b, 0x15, 0x81, 0x02, 0x7d, 0xfd, 0xfb, 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, 0x0a, 0xb9, 0x41, 0x44, 0xd3, 0xef, 0x25, 0xaa, 0x1d, + 0x29, 0x90, 0x43, 0xc9, 0x4f, 0x88, 0xbf, 0x64, 0x6d, 0x8c, 0xfb, 0xa5, 0x53, 0xed, 0x57, 0x0a, 0xc1, 0xfd, 0x67, + 0x5b, 0x6c, 0x54, 0x79, 0xa2, 0x47, 0x9f, 0x62, 0xfd, 0x4f, 0x16, 0x50, 0xaa, 0xfb, 0x36, 0x38, 0x15, 0x8f, 0xc2, + 0x4d, 0x5d, 0xdc, 0x20, 0xb4, 0x40, 0x39, 0xaa, 0x8a, 0x4d, 0x19, 0x11, 0x27, 0xec, 0xa6, 0x2e, 0x7a, 0x9a, 0x03, + 0x9d, 0x3a, 0x2c, 0x4d, 0xe4, 0x89, 0xd0, 0x6e, 0x41, 0xf7, 0x34, 0xc7, 0x4a, 0xbc, 0x94, 0xa5, 0x83, 0xac, 0x13, + 0x69, 0x42, 0xe5, 0xae, 0xae, 0x3a, 0x2a, 0x95, 0xba, 0xe1, 0x4d, 0xaa, 0x19, 0x7f, 0x97, 0xe6, 0x4f, 0x2c, 0xfb, + 0x4d, 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, 0xb1, 0x28, 0xfe, 0xa8, 0xf4, 0x1d, 0x81, 0x8e, 0xee, 0xbc, 0xa8, 0xd3, 0xe5, 0xee, 0x03, 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, 0xbc, 0xc2, 0xfd, 0xa5, 0x22, 0x17, 0xfb, 0xce, 0x19, + 0xdd, 0x99, 0x59, 0xf7, 0xaa, 0xc2, 0xd5, 0x82, 0x5c, 0x1d, 0xd8, 0x5a, 0x76, 0x71, 0xb8, 0x61, 0x11, 0x05, 0x08, + 0xc4, 0xf4, 0x4a, 0xad, 0xfd, 0x11, 0x0d, 0x42, 0x3e, 0x18, 0xf8, 0x05, 0x06, 0xab, 0x02, 0x85, 0x0f, 0x14, 0xc9, + 0x5f, 0x7b, 0x02, 0x76, 0xf1, 0x0c, 0xd0, 0xad, 0xd8, 0xac, 0x18, 0x21, 0x42, 0x26, 0xcb, 0x59, 0x4d, 0x67, 0x90, + 0x4f, 0x7d, 0xf1, 0x8d, 0xad, 0x3a, 0x9d, 0xb7, 0x35, 0x55, 0x4e, 0x1d, 0x0a, 0xdd, 0xdd, 0xd4, 0x9d, 0x5b, 0x17, + 0x79, 0xea, 0x10, 0x72, 0xa5, 0x62, 0x25, 0xa6, 0xa1, 0xe6, 0x49, 0x9a, 0x51, 0x7f, 0xb1, 0xf7, 0x7b, 0x8d, 0xc2, + 0x29, 0x7f, 0x3a, 0x06, 0x55, 0xb8, 0xaa, 0x21, 0x8e, 0xa5, 0x2a, 0x1e, 0xd9, 0x20, 0xd0, 0xbc, 0xba, 0x55, 0x49, + 0x13, 0x32, 0xb9, 0x11, 0x3e, 0x35, 0x29, 0xe5, 0x69, 0xda, 0xa4, 0x95, 0x22, 0x75, 0xf0, 0x41, 0x9d, 0x6a, 0x3c, + 0x37, 0xab, 0x17, 0x00, 0x66, 0x9c, 0x5f, 0xf1, 0x4b, 0xc5, 0x65, 0xd4, 0x56, 0x66, 0xd2, 0xfe, 0xe4, 0x68, 0x6c, + 0xd4, 0xe5, 0xb4, 0x51, 0x46, 0x58, 0x29, 0xcd, 0x49, 0xb1, 0x1c, 0xcf, 0x3f, 0x60, 0xb0, 0xe6, 0x09, 0xec, 0x60, + 0xa2, 0x52, 0xde, 0x47, 0x40, 0x7c, 0x9d, 0xa4, 0x77, 0x09, 0xa4, 0x48, 0xff, 0xd2, 0x25, 0x77, 0x19, 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, 0xbe, 0x08, 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, 0xac, 0x3c, 0xe8, 0xff, 0x3a, 0x13, 0x96, 0xda, 0x4f, 0x4f, 0x07, 0x50, 0xc1, 0xfb, 0x8a, 0xb7, 0x11, 0xf1, + 0x7d, 0xe2, 0x67, 0xf1, 0x60, 0xf3, 0x6c, 0x03, 0xd6, 0xba, 0x27, 0xb9, 0xb1, 0xae, 0x12, 0x36, 0x10, 0xf0, 0x35, + 0x8a, 0xda, 0xf3, 0xda, 0xed, 0x1e, 0xfc, 0xd5, 0xbf, 0x08, 0x19, 0x30, 0x71, 0xfa, 0x3e, 0x73, 0xb2, 0x46, 0x17, + 0x99, 0x4c, 0x1f, 0x3a, 0xe9, 0x1b, 0x9d, 0xee, 0x3b, 0xe1, 0x1f, 0x15, 0xb3, 0xf8, 0x70, 0x4b, 0x5f, 0x69, 0x52, + 0xdc, 0x01, 0x2b, 0x9b, 0x47, 0x05, 0xa1, 0xce, 0x45, 0xf4, 0x95, 0x29, 0xdf, 0x12, 0x6a, 0xf6, 0x8d, 0x25, 0xa5, + 0x74, 0xaf, 0xa1, 0x37, 0x69, 0xad, 0xdf, 0x46, 0x09, 0xc6, 0x44, 0xc7, 0x93, 0x97, 0xf1, 0x58, 0x79, 0x1f, 0x8f, + 0x1b, 0xa9, 0x90, 0x07, 0x20, 0x02, 0x15, 0xe3, 0x4f, 0x57, 0x9e, 0x9c, 0xf4, 0xc2, 0x78, 0x15, 0x4a, 0x41, 0x61, + 0x40, 0x57, 0x20, 0x05, 0x3c, 0x6a, 0x4f, 0x74, 0x16, 0x76, 0x09, 0xf7, 0xe8, 0x26, 0x60, 0xac, 0xcf, 0x3f, 0x02, + 0x9a, 0xbb, 0x70, 0x87, 0x17, 0x03, 0xd4, 0xa6, 0x5e, 0xdd, 0x7d, 0x5c, 0xab, 0x73, 0x38, 0x04, 0x07, 0xab, 0x41, + 0x04, 0xa7, 0xf3, 0xa9, 0xa3, 0x59, 0x16, 0xa0, 0x72, 0xb2, 0xdc, 0xc8, 0x9b, 0x47, 0x8b, 0x5e, 0xdd, 0xf7, 0x96, + 0x69, 0x59, 0xd5, 0x41, 0xc6, 0xb2, 0xb0, 0x02, 0x5c, 0x1d, 0x5a, 0x3f, 0x08, 0x97, 0x85, 0xf3, 0x07, 0x42, 0x10, + 0xbb, 0x57, 0xdb, 0x92, 0xe7, 0x6a, 0x0e, 0x3f, 0x7b, 0xce, 0xd6, 0x5c, 0xa2, 0x4e, 0x3a, 0x13, 0x01, 0x88, 0x3d, + 0x35, 0xab, 0xe8, 0x1a, 0x48, 0xea, 0x34, 0xab, 0xe8, 0x9a, 0x9a, 0x6d, 0x8c, 0x03, 0xf9, 0x68, 0x95, 0x02, 0xf6, + 0xdd, 0x74, 0x1c, 0xac, 0x9e, 0xc5, 0xf2, 0x3a, 0x74, 0xf7, 0x6c, 0xa3, 0x7c, 0x06, 0x75, 0xab, 0x8d, 0x31, 0xb1, + 0xdd, 0x7c, 0x39, 0xd7, 0x6f, 0x07, 0x4b, 0xdf, 0x0e, 0x9a, 0x73, 0xca, 0xbe, 0xd3, 0x65, 0xaf, 0xec, 0xb2, 0xa9, + 0xe7, 0x8e, 0x8a, 0x56, 0x63, 0x40, 0x6f, 0x60, 0xc1, 0xfa, 0x5c, 0xa4, 0xd9, 0xaa, 0x54, 0x25, 0xe0, 0x85, 0xb1, + 0x62, 0x77, 0x7e, 0x23, 0x33, 0x24, 0x61, 0x1e, 0x67, 0xe2, 0x9a, 0xee, 0xb5, 0x30, 0x39, 0x8e, 0x45, 0x32, 0x25, + 0x74, 0x4a, 0x77, 0xb6, 0xa1, 0x73, 0x15, 0x46, 0x11, 0xad, 0x95, 0x54, 0x1a, 0x09, 0x4c, 0xcd, 0x00, 0x25, 0x73, + 0x05, 0x4e, 0xe9, 0x72, 0xff, 0x3b, 0x12, 0xe3, 0xcc, 0x17, 0x25, 0x33, 0xa0, 0x5b, 0x7e, 0x5d, 0xac, 0x5b, 0x29, + 0x32, 0xc2, 0xbc, 0x39, 0x6e, 0xaf, 0xeb, 0x43, 0x20, 0x57, 0xcb, 0x1e, 0x45, 0xe3, 0xa0, 0xd0, 0xe1, 0x52, 0x25, + 0xc0, 0xbe, 0x48, 0xfc, 0x8c, 0xb0, 0xa5, 0x3d, 0x90, 0xdb, 0xa3, 0x33, 0x61, 0xce, 0x39, 0x29, 0xcb, 0xce, 0xa5, + 0x19, 0x5c, 0x4e, 0x5c, 0x09, 0x2e, 0xd2, 0xdb, 0xf6, 0x34, 0x69, 0x69, 0xfb, 0xd8, 0x70, 0x8e, 0x86, 0xb6, 0x41, + 0x77, 0xec, 0x0f, 0xcd, 0xc5, 0x22, 0xb6, 0x2e, 0x16, 0xc3, 0xce, 0xec, 0x47, 0x8b, 0x05, 0xc8, 0x01, 0xe0, 0xa8, + 0xdb, 0xf0, 0x31, 0x5b, 0x02, 0xa7, 0xd5, 0x34, 0x9b, 0x7a, 0x1b, 0x5e, 0x3d, 0x53, 0x3d, 0xbd, 0xe4, 0xf9, 0x33, + 0x61, 0xc6, 0x62, 0xc3, 0xf3, 0x67, 0xd6, 0x91, 0x53, 0x3d, 0x13, 0x4a, 0xb4, 0x2e, 0xa0, 0x19, 0x78, 0x4d, 0x01, + 0x23, 0x96, 0x4c, 0xa6, 0x54, 0x91, 0xc7, 0xbd, 0xe9, 0x46, 0x0d, 0x5e, 0x50, 0x38, 0x04, 0x52, 0x3a, 0xfd, 0xe2, + 0x39, 0xd3, 0xef, 0x5d, 0x3c, 0xef, 0x90, 0xb5, 0x0d, 0xd3, 0xe5, 0x66, 0x98, 0x0c, 0x4a, 0xff, 0x99, 0x99, 0x18, + 0x17, 0xd6, 0x24, 0x01, 0xc4, 0xbf, 0xb1, 0xdf, 0x21, 0x85, 0x9b, 0xf7, 0x97, 0xc3, 0xf8, 0x91, 0xf7, 0x63, 0x64, + 0x4f, 0xd2, 0x0c, 0xb1, 0x66, 0x52, 0x21, 0x77, 0x5f, 0xad, 0x7f, 0x4c, 0xec, 0x26, 0x7b, 0x60, 0x01, 0x88, 0xad, + 0x69, 0xab, 0x5b, 0xde, 0xef, 0x7b, 0xa6, 0x08, 0xf0, 0x83, 0xf2, 0x8f, 0xee, 0x0c, 0xc9, 0xa0, 0xec, 0xba, 0x21, + 0xc4, 0x83, 0xb2, 0x69, 0xda, 0xeb, 0x6d, 0xef, 0xcc, 0x63, 0x75, 0x9d, 0x76, 0x16, 0x57, 0x8b, 0x0c, 0xd2, 0xea, + 0x43, 0x76, 0x9c, 0xd9, 0x67, 0x47, 0x4b, 0xa5, 0xfb, 0x7d, 0x88, 0x88, 0x3b, 0xca, 0xda, 0x7e, 0xbb, 0x05, 0xd7, + 0x70, 0x34, 0x08, 0x5d, 0xd9, 0xdb, 0x65, 0xb4, 0x71, 0x21, 0x8e, 0x7b, 0xa6, 0xf3, 0x05, 0x5f, 0x1e, 0xa5, 0x9d, + 0x07, 0xa7, 0x7a, 0xa2, 0xcf, 0x4d, 0x77, 0x95, 0xc9, 0xb5, 0x0e, 0xab, 0x31, 0xa8, 0xcd, 0xc2, 0x16, 0xee, 0xc2, + 0x36, 0x3a, 0x68, 0xed, 0xcb, 0x82, 0x7f, 0xca, 0x00, 0x7c, 0xe9, 0xd9, 0xb2, 0xed, 0x35, 0x69, 0xf5, 0x46, 0x46, + 0x21, 0xb6, 0xb4, 0xbd, 0xfa, 0x74, 0x94, 0x8f, 0x9b, 0x13, 0x8a, 0x0b, 0x39, 0xca, 0x8f, 0x5e, 0x43, 0xd4, 0xb5, + 0xae, 0xe3, 0x62, 0xd1, 0xe1, 0xc6, 0x55, 0xb7, 0xdd, 0xb8, 0x7e, 0x40, 0xbc, 0x35, 0xda, 0xa4, 0x50, 0x2b, 0x63, + 0x47, 0xf0, 0xb2, 0x7c, 0x38, 0x64, 0x62, 0x38, 0x94, 0x90, 0xa9, 0x8f, 0xdd, 0x1b, 0x9a, 0xf6, 0xf9, 0x69, 0xeb, + 0x47, 0x2c, 0x35, 0x8e, 0x62, 0xc3, 0x3b, 0x7d, 0xe7, 0xb1, 0x35, 0xae, 0xe4, 0xcb, 0x60, 0xb6, 0x2b, 0xa8, 0xb6, + 0xc6, 0x1b, 0xf6, 0x72, 0xfe, 0x7d, 0x25, 0x95, 0xfc, 0xed, 0xcf, 0x70, 0x0d, 0x6f, 0x6d, 0xe9, 0xa0, 0xa9, 0x66, + 0x39, 0xcb, 0xf5, 0xbd, 0xe0, 0xf8, 0xe3, 0xee, 0x15, 0xc1, 0xe0, 0xf7, 0x74, 0x14, 0xe4, 0x62, 0xa9, 0xd6, 0x80, + 0x82, 0x74, 0x64, 0xc7, 0x54, 0x16, 0x18, 0x06, 0xf0, 0x86, 0x0c, 0x90, 0xc7, 0x14, 0xee, 0x86, 0x0a, 0x2f, 0xfc, + 0xa5, 0x22, 0xbb, 0x04, 0xb6, 0x35, 0xe3, 0x63, 0x86, 0x3b, 0x08, 0xf9, 0x47, 0xb0, 0x3b, 0xb6, 0x62, 0xb7, 0x6c, + 0xc1, 0x90, 0x6c, 0x1c, 0x87, 0x31, 0xe6, 0xe3, 0x49, 0x7c, 0x25, 0x26, 0xf1, 0x80, 0x47, 0xe8, 0x18, 0xb1, 0xe6, + 0xf5, 0x2c, 0x96, 0x03, 0xc8, 0xee, 0xb8, 0xd2, 0x01, 0x21, 0x34, 0x36, 0xb4, 0xe4, 0x4d, 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, 0xdd, 0x45, 0x88, 0xf4, 0xb6, 0xe0, 0x77, 0x96, 0xa7, 0x0b, 0xbb, 0xe7, 0xd7, + 0x7c, 0xcc, 0xce, 0x7f, 0xf0, 0x20, 0x72, 0xf6, 0xfc, 0x23, 0xa0, 0x21, 0xde, 0xf3, 0xdb, 0xd4, 0xab, 0xd8, 0x2d, + 0x51, 0x10, 0xde, 0x82, 0x33, 0xd0, 0x3d, 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, 0xff, 0xc1, 0xdb, 0x51, 0xb9, 0xf0, 0x9f, 0xd7, 0x59, 0xf2, 0xce, 0x67, 0xd7, 0x03, 0xbe, 0x00, 0xbc, 0x25, + 0x74, 0xe0, 0xba, 0xf7, 0x99, 0xc4, 0x6b, 0xbb, 0xd6, 0xd7, 0x08, 0x24, 0xf2, 0x05, 0x60, 0xc4, 0xc4, 0xfc, 0xbe, + 0x86, 0x08, 0x8c, 0x04, 0x7c, 0x5b, 0xb5, 0x47, 0xfc, 0x96, 0x1b, 0xc0, 0xaf, 0xcc, 0x67, 0x0f, 0x3c, 0xd4, 0x3f, + 0x13, 0x9f, 0xdd, 0xf0, 0xf7, 0xfc, 0x85, 0x27, 0x25, 0xe9, 0x72, 0xf6, 0x7e, 0x0e, 0xd7, 0x43, 0x29, 0x4f, 0x87, + 0xf4, 0xb3, 0x31, 0x18, 0x40, 0x28, 0x64, 0xde, 0x78, 0xc0, 0x9a, 0x14, 0xe2, 0x5f, 0xc0, 0xb7, 0xa3, 0x84, 0xcd, + 0x1b, 0x6f, 0xeb, 0x6b, 0x79, 0xf3, 0xc6, 0x7b, 0xf0, 0x29, 0x0a, 0xb0, 0x0a, 0x4a, 0x59, 0x60, 0x15, 0x84, 0x8d, + 0x36, 0xc2, 0x18, 0xb8, 0x7a, 0xd7, 0x18, 0xea, 0x7a, 0x8e, 0xd8, 0xb6, 0xd2, 0x77, 0xe1, 0x3b, 0xc8, 0x80, 0x0f, + 0xde, 0x14, 0x25, 0xd1, 0xe7, 0xd4, 0x14, 0x49, 0xeb, 0x9e, 0xfb, 0xad, 0x75, 0x47, 0x6b, 0x4a, 0x7d, 0xe4, 0x6a, + 0x7c, 0x38, 0xd4, 0x2f, 0x84, 0x16, 0x09, 0xa6, 0xa0, 0x71, 0x0d, 0xda, 0x02, 0x04, 0x7d, 0x1e, 0x20, 0x6b, 0x49, + 0xb1, 0xe0, 0xdb, 0x5f, 0x21, 0x06, 0xaf, 0x4c, 0xef, 0x5c, 0xae, 0x32, 0x12, 0xb6, 0x17, 0x7e, 0x39, 0xac, 0xfd, + 0x89, 0x53, 0x0b, 0x4b, 0xab, 0x39, 0xa8, 0x9f, 0xd9, 0x72, 0x9c, 0xaa, 0xda, 0xbf, 0x25, 0x49, 0xb5, 0xab, 0xb4, + 0x9c, 0xde, 0xdb, 0x37, 0x5d, 0x26, 0xd8, 0xd8, 0x0f, 0xa8, 0x3a, 0xb2, 0x1a, 0x76, 0x5f, 0xa8, 0x2f, 0x7a, 0x4a, + 0x26, 0x34, 0x1f, 0x55, 0x34, 0xcf, 0xee, 0x37, 0x3b, 0xea, 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, 0x17, 0xe3, 0x69, 0x4d, 0x2c, 0xa9, 0x5d, 0x81, 0x31, 0x7a, 0x5c, 0x15, 0xb5, 0x4f, 0xfd, 0x02, 0x42, 0x91, + 0x6a, 0xcd, 0x1c, 0x6b, 0xdc, 0x18, 0x11, 0x77, 0x58, 0xb9, 0x76, 0x6a, 0xaf, 0x03, 0xb0, 0xbc, 0x1a, 0x17, 0x84, + 0x4d, 0x72, 0xec, 0x5c, 0xc0, 0x6a, 0x34, 0xa4, 0xda, 0x0d, 0xb7, 0x5e, 0x76, 0x7e, 0xf3, 0x38, 0xb1, 0xb5, 0x11, + 0x6e, 0x29, 0xa0, 0x8c, 0xf2, 0x1b, 0xcb, 0x09, 0xbb, 0x53, 0xbd, 0x23, 0x55, 0x3b, 0xe2, 0xc4, 0x05, 0x2c, 0x37, + 0x3c, 0xb5, 0xfa, 0x26, 0x06, 0x27, 0x42, 0xd5, 0x4a, 0xc7, 0x6b, 0x3f, 0xe2, 0x7e, 0x75, 0x5f, 0xf7, 0x4a, 0xf0, + 0x93, 0x90, 0xd7, 0x6f, 0x79, 0x07, 0x80, 0x15, 0x1f, 0xf2, 0x62, 0x5a, 0x38, 0x5a, 0x97, 0x41, 0x19, 0x20, 0x42, + 0x33, 0x00, 0x3a, 0xb9, 0x3a, 0x88, 0xd2, 0xc0, 0x15, 0x77, 0x88, 0xf0, 0xd3, 0xe8, 0x59, 0xfe, 0x22, 0x7c, 0x56, + 0x4d, 0xc3, 0x8b, 0x3c, 0x88, 0x2e, 0xaa, 0x20, 0x7a, 0x56, 0x5d, 0x85, 0xcf, 0xf2, 0x69, 0x74, 0x91, 0x07, 0xe1, + 0x45, 0xd5, 0xd8, 0x77, 0xed, 0xee, 0x9e, 0x90, 0xb7, 0x5d, 0xfd, 0x91, 0x73, 0x65, 0x4f, 0x99, 0x9e, 0x9f, 0xd7, + 0x7a, 0xa5, 0x76, 0x9b, 0xeb, 0x35, 0x6a, 0xa6, 0x3e, 0xca, 0xfe, 0x66, 0x1b, 0x0b, 0x8f, 0xe6, 0x10, 0xfa, 0x8c, + 0xb4, 0x98, 0x7b, 0x9c, 0xeb, 0xcd, 0x9e, 0x14, 0x06, 0x46, 0x4c, 0x2a, 0x19, 0x39, 0xbd, 0xc0, 0x45, 0xa8, 0x42, + 0x0c, 0x6b, 0xe9, 0x6a, 0x9f, 0x75, 0xe9, 0x0d, 0xd4, 0x35, 0xc5, 0xbe, 0x86, 0x0c, 0xbc, 0x68, 0x7a, 0x19, 0x8c, + 0x01, 0x39, 0x02, 0xef, 0xf8, 0x6c, 0x09, 0x07, 0xe6, 0x1a, 0xa0, 0x6f, 0x1e, 0xf5, 0x75, 0xb9, 0xe3, 0x6b, 0xd5, + 0x37, 0xd3, 0xf5, 0x48, 0x29, 0x3f, 0x56, 0xfc, 0xee, 0xe2, 0x39, 0xbb, 0xe5, 0x1a, 0x15, 0xe5, 0x17, 0xbd, 0x58, + 0xef, 0x81, 0xab, 0xee, 0x17, 0xb8, 0xcd, 0xe2, 0xb1, 0x2b, 0x0f, 0x58, 0xb6, 0x65, 0x0f, 0xec, 0x86, 0xbd, 0x67, + 0x4f, 0xd8, 0x5b, 0xf6, 0x8e, 0xfd, 0x84, 0xaa, 0x0d, 0x25, 0xe4, 0xf9, 0x0b, 0x7e, 0x2b, 0x4d, 0x8f, 0x12, 0x95, + 0xec, 0xc1, 0x36, 0xd3, 0x0c, 0x37, 0xec, 0x3d, 0x5f, 0x0c, 0x57, 0xec, 0x2d, 0x64, 0x43, 0x99, 0x78, 0xb0, 0x62, + 0x3f, 0x71, 0x05, 0x62, 0xa6, 0xcf, 0xc2, 0xd2, 0x12, 0x15, 0x4d, 0x99, 0x28, 0x43, 0xbf, 0xe5, 0xf8, 0x22, 0xfb, + 0x09, 0x8b, 0x90, 0x9f, 0x19, 0xae, 0xd8, 0x03, 0x5f, 0x0c, 0x56, 0xec, 0xbd, 0x36, 0x10, 0x0d, 0x36, 0x6e, 0x69, + 0x84, 0x64, 0xa5, 0xcb, 0x92, 0xd2, 0xf4, 0xd6, 0xbe, 0x06, 0x6e, 0xd8, 0x0d, 0xd6, 0xee, 0x09, 0x16, 0x8d, 0x02, + 0xff, 0x60, 0xc5, 0xde, 0x71, 0x09, 0xa0, 0xe6, 0x96, 0x27, 0xbd, 0x42, 0x75, 0x81, 0x74, 0x3f, 0x78, 0xc2, 0xe9, + 0x45, 0xf6, 0x0e, 0xcb, 0xa0, 0xaf, 0x0c, 0x57, 0x6c, 0x8b, 0xb5, 0xbb, 0x31, 0x96, 0x2d, 0xab, 0x7a, 0x12, 0x11, + 0x18, 0x05, 0x95, 0xd2, 0xf2, 0x6f, 0xc4, 0xb2, 0xa9, 0x9b, 0x06, 0xb5, 0xa1, 0x3f, 0x1f, 0x8c, 0xfe, 0xe2, 0xeb, + 0x77, 0x3f, 0x78, 0xa5, 0xbe, 0xf6, 0xfe, 0xe2, 0xb8, 0x56, 0x96, 0xe8, 0x5a, 0xf9, 0x2b, 0x2f, 0x67, 0xbf, 0xcc, + 0x27, 0xba, 0x96, 0xb4, 0xc3, 0x90, 0xaf, 0xe9, 0xec, 0x97, 0x0e, 0x67, 0xcb, 0x5f, 0x7d, 0xbf, 0x31, 0x5d, 0xac, + 0x3e, 0xab, 0x7b, 0xf7, 0x61, 0xb0, 0x69, 0x9c, 0x7a, 0xef, 0x4e, 0xd7, 0x1b, 0x9b, 0x59, 0x6b, 0xcf, 0xcc, 0xff, + 0xe1, 0x4a, 0x6f, 0x71, 0xe8, 0x6e, 0xf8, 0x76, 0xb8, 0xb1, 0x47, 0x41, 0x7e, 0x5f, 0x2a, 0x8d, 0xb3, 0x9a, 0xbf, + 0xf4, 0x3a, 0xa5, 0x58, 0x40, 0x34, 0xfa, 0x64, 0x24, 0xa1, 0x4b, 0x66, 0xe2, 0x19, 0xe2, 0x8b, 0x0c, 0x90, 0xb9, + 0x40, 0x34, 0xbb, 0xe7, 0xe3, 0xc9, 0xfd, 0x55, 0x3c, 0xb9, 0x1f, 0xf0, 0x4f, 0xa6, 0x05, 0xed, 0xc5, 0x76, 0xef, + 0xb3, 0x5f, 0x79, 0x61, 0x2f, 0xc7, 0x5f, 0x7c, 0xf6, 0x45, 0xb8, 0x2b, 0xf4, 0x17, 0x9f, 0xbd, 0x13, 0xfc, 0xd7, + 0x91, 0x26, 0xca, 0x60, 0xef, 0x6a, 0xfe, 0xeb, 0x08, 0x19, 0x3f, 0xd8, 0x67, 0xc1, 0xbf, 0x80, 0xef, 0x77, 0x95, + 0xa0, 0x55, 0xfc, 0x73, 0xad, 0x7e, 0xbe, 0x97, 0x71, 0x39, 0xf0, 0x26, 0xb4, 0x82, 0xde, 0xbc, 0xad, 0xe5, 0x4f, + 0xe2, 0xe1, 0x48, 0xd5, 0x53, 0xc3, 0x3f, 0x8b, 0xc5, 0x2c, 0xea, 0xa3, 0x74, 0x2a, 0x6f, 0x72, 0xcd, 0x33, 0x69, + 0x5d, 0xbe, 0x87, 0x50, 0xe0, 0x6b, 0x1b, 0xa2, 0x60, 0xc7, 0x71, 0x23, 0xb8, 0x66, 0xef, 0x84, 0xcf, 0xb2, 0xe9, + 0x96, 0xdf, 0xf0, 0x27, 0xfc, 0x1d, 0xdf, 0x05, 0x0f, 0xfc, 0x3d, 0x7f, 0xcb, 0x7f, 0xe2, 0x3b, 0xb6, 0x94, 0x68, + 0xa7, 0xf5, 0xf6, 0x32, 0xd8, 0xb2, 0x7a, 0x77, 0x19, 0x3c, 0xb0, 0x7a, 0xfb, 0x3c, 0xb8, 0x61, 0xf5, 0xee, 0x79, + 0xf0, 0x9e, 0x6d, 0x2f, 0x83, 0x27, 0x6c, 0x77, 0x19, 0xbc, 0x65, 0xdb, 0xe7, 0xc1, 0x3b, 0xb6, 0x7b, 0x1e, 0xfc, + 0x24, 0x31, 0x1e, 0xde, 0x09, 0xc9, 0x71, 0xf2, 0xae, 0x66, 0x86, 0x4f, 0x37, 0xf8, 0x2c, 0xac, 0x5f, 0x54, 0xc7, + 0xe0, 0x73, 0xcd, 0x74, 0x8b, 0x03, 0x21, 0x98, 0x6e, 0x6f, 0x70, 0x4b, 0x4f, 0x4c, 0xab, 0x82, 0x54, 0xb0, 0xae, + 0x76, 0x06, 0x8b, 0xba, 0x69, 0x9d, 0xc9, 0x8e, 0x5f, 0x62, 0xdc, 0xe1, 0x97, 0xb8, 0x60, 0xcb, 0xa6, 0xd3, 0x49, + 0xe7, 0xf4, 0x49, 0xa0, 0x37, 0x7f, 0xbd, 0xeb, 0x57, 0xd2, 0x77, 0xa6, 0x68, 0x78, 0xae, 0xb4, 0xc6, 0xad, 0x9d, + 0x3e, 0xb4, 0x76, 0x7a, 0x26, 0x55, 0x68, 0x11, 0x8b, 0xca, 0xa2, 0xaa, 0x90, 0x49, 0x3c, 0xc8, 0xb4, 0x3e, 0x2d, + 0x61, 0xa4, 0xc8, 0x04, 0x34, 0xfa, 0x82, 0x8e, 0x81, 0x9c, 0x2c, 0x0a, 0x6c, 0xc9, 0x37, 0x83, 0x84, 0xad, 0x79, + 0x3c, 0x1d, 0x26, 0xc1, 0x92, 0xdd, 0xf1, 0x61, 0xb7, 0x40, 0xb0, 0x52, 0x01, 0x4c, 0xfa, 0xe2, 0xd4, 0xde, 0xd7, + 0x79, 0x6f, 0x95, 0xc6, 0x71, 0x26, 0x50, 0xd9, 0x56, 0xe9, 0x0d, 0x7e, 0xeb, 0xec, 0xe7, 0x6b, 0xb5, 0xbf, 0x83, + 0xa4, 0xf0, 0x2b, 0x30, 0xec, 0x10, 0xe1, 0x1d, 0x54, 0x18, 0x79, 0x96, 0xcc, 0xa2, 0xaf, 0xec, 0x2d, 0x7d, 0x6b, + 0xb6, 0xe9, 0xff, 0xb4, 0x08, 0xda, 0xc7, 0x65, 0xe7, 0x7f, 0x32, 0xaf, 0xfe, 0xd6, 0xf1, 0xea, 0xc6, 0x9f, 0x3c, + 0xf0, 0x4f, 0x18, 0x96, 0x80, 0x89, 0x6c, 0xc7, 0x3f, 0x8d, 0xb6, 0x8d, 0x53, 0x9e, 0xdc, 0xc7, 0xff, 0xaf, 0x14, + 0x68, 0xef, 0xe4, 0x95, 0xbd, 0x23, 0x6e, 0x79, 0xc7, 0x3e, 0xbe, 0xb4, 0x36, 0x44, 0x03, 0x4d, 0xf2, 0x89, 0xbb, + 0xd1, 0xd0, 0xb0, 0x21, 0xfe, 0xc2, 0xab, 0xd9, 0xa7, 0xf9, 0x64, 0xcb, 0x8f, 0xb7, 0xc3, 0x4f, 0x1d, 0xdb, 0xe1, + 0x2f, 0xfe, 0x60, 0xd9, 0x7c, 0xad, 0x57, 0x3b, 0xb7, 0x71, 0xa7, 0xd2, 0x3b, 0x7e, 0xbc, 0x89, 0x0f, 0xff, 0xe3, + 0x4a, 0xef, 0xbe, 0xb9, 0xd2, 0x76, 0x95, 0xbb, 0x3b, 0xdf, 0x74, 0x7c, 0x23, 0x6b, 0x8d, 0x71, 0x66, 0x46, 0xb3, + 0xf8, 0x13, 0xcd, 0xd2, 0x20, 0xb2, 0x14, 0x8a, 0x3f, 0x99, 0x69, 0xa7, 0xee, 0x54, 0x59, 0xdd, 0x2d, 0xdf, 0xe2, + 0x1e, 0x7f, 0xcb, 0xc7, 0x6c, 0x61, 0x3c, 0x35, 0x6f, 0xaf, 0x16, 0x93, 0xc1, 0xe0, 0xd6, 0xdf, 0xdf, 0xf3, 0x70, + 0x76, 0x3b, 0x67, 0xd7, 0xfc, 0x9e, 0x16, 0xd3, 0x44, 0x35, 0xbd, 0x78, 0x4c, 0xf0, 0xba, 0xf5, 0xfd, 0x89, 0xc5, + 0xff, 0x6a, 0x5f, 0x34, 0x6f, 0xfd, 0x81, 0xb4, 0x46, 0xcb, 0x5d, 0xfd, 0xfd, 0xe3, 0x8a, 0x89, 0x5b, 0x10, 0x2f, + 0xde, 0xdb, 0x9a, 0x86, 0xb7, 0xfc, 0xa3, 0x77, 0xed, 0x4f, 0xaf, 0x75, 0xcc, 0xcd, 0x44, 0x1d, 0x49, 0x6f, 0x2f, + 0x9e, 0xb3, 0x5f, 0xf9, 0x27, 0x79, 0x9c, 0x7c, 0x11, 0x72, 0xd2, 0xde, 0x20, 0x77, 0x13, 0x9d, 0x12, 0xef, 0xdc, + 0x44, 0xc2, 0x82, 0x40, 0x18, 0x8e, 0x9a, 0x3f, 0x4c, 0xca, 0xa9, 0xb7, 0x03, 0x6e, 0x57, 0x6e, 0xeb, 0x9f, 0x6f, + 0x39, 0xe7, 0x8b, 0xe1, 0xe5, 0xf4, 0x5d, 0xb7, 0x4b, 0x8f, 0x8a, 0x66, 0x53, 0x81, 0x6e, 0xb7, 0x18, 0x7b, 0x75, + 0x32, 0xb3, 0xcc, 0x25, 0x5f, 0x7a, 0x57, 0x9b, 0x99, 0xc7, 0xf4, 0x7e, 0x33, 0xcd, 0x90, 0xc8, 0x17, 0x08, 0x99, + 0x0e, 0x87, 0xbb, 0x73, 0x2c, 0x8f, 0x0f, 0xdf, 0x3e, 0x7b, 0x32, 0x78, 0x82, 0x91, 0x5b, 0x56, 0x34, 0xc8, 0x3b, + 0x3e, 0xcc, 0xea, 0xd6, 0x6d, 0xe3, 0xe2, 0xf9, 0xf0, 0x17, 0xc8, 0x1b, 0x74, 0x3d, 0x34, 0x45, 0xb4, 0xca, 0xef, + 0x28, 0xfa, 0x44, 0xc9, 0x41, 0xc7, 0x13, 0xa8, 0x1d, 0x52, 0xe0, 0xbe, 0x7b, 0xc6, 0x41, 0xbf, 0x81, 0xa5, 0xf6, + 0xfb, 0xe7, 0x9f, 0x88, 0x47, 0x1a, 0xc6, 0xfb, 0xfb, 0x30, 0xfa, 0x23, 0x2e, 0x8b, 0x35, 0x9c, 0xae, 0x03, 0xf8, + 0xdc, 0x33, 0x7d, 0xfb, 0xba, 0xf3, 0x7d, 0x3f, 0xf0, 0xb6, 0xfc, 0x86, 0xbd, 0xe3, 0xde, 0xe5, 0xf0, 0xad, 0xff, + 0xec, 0x09, 0x88, 0x4e, 0x30, 0x2e, 0x9f, 0x31, 0x12, 0xb6, 0xa3, 0x18, 0xb5, 0x0a, 0x3f, 0xd7, 0x10, 0xa2, 0xf5, + 0x09, 0x19, 0xbb, 0x20, 0xfd, 0x83, 0x02, 0xf4, 0x13, 0x02, 0xab, 0x49, 0x6a, 0x14, 0x98, 0xc4, 0xb7, 0x35, 0x24, + 0x90, 0x82, 0x05, 0x42, 0x6f, 0xa0, 0xf8, 0x54, 0xf0, 0x77, 0xc3, 0xcf, 0x24, 0xf9, 0x2d, 0x6a, 0x3e, 0x86, 0xbf, + 0x61, 0x68, 0x26, 0xd5, 0x43, 0x5a, 0x47, 0x89, 0xf7, 0x93, 0xbf, 0x8f, 0xc2, 0x4a, 0xa8, 0x63, 0x21, 0x48, 0xc5, + 0x90, 0x0b, 0x71, 0xf1, 0x7c, 0x72, 0x5b, 0x8a, 0xf0, 0x8f, 0x09, 0x3e, 0x93, 0x0b, 0x4d, 0x3e, 0xa3, 0x27, 0x8d, + 0x7c, 0xff, 0x41, 0xbe, 0x2f, 0x3b, 0x35, 0x58, 0xd4, 0x43, 0x7e, 0x5b, 0xbb, 0xef, 0xcb, 0x29, 0x41, 0x8f, 0xec, + 0x07, 0x34, 0x05, 0x03, 0x35, 0x01, 0x29, 0x43, 0x70, 0x0b, 0x57, 0x7d, 0x4f, 0x15, 0xe4, 0xcb, 0xef, 0x7d, 0x16, + 0x32, 0x5c, 0x65, 0x41, 0x48, 0x72, 0xa9, 0x90, 0xc2, 0xc6, 0x6d, 0x3d, 0xf8, 0xac, 0x31, 0x49, 0x24, 0xe4, 0x94, + 0x80, 0x24, 0x69, 0x6f, 0x20, 0x49, 0xc4, 0xf4, 0x1f, 0xae, 0x93, 0xa6, 0x59, 0x49, 0xe9, 0x86, 0x38, 0x55, 0xaf, + 0x91, 0xe6, 0x2c, 0x78, 0xcf, 0x60, 0xe9, 0x48, 0xb1, 0xe2, 0x9d, 0x31, 0x18, 0xeb, 0x60, 0xa1, 0x3b, 0x59, 0xdc, + 0xaf, 0x92, 0x30, 0x8d, 0x44, 0x95, 0x2f, 0x42, 0xfe, 0xfc, 0x97, 0x12, 0x7f, 0xf4, 0x96, 0x06, 0x22, 0x10, 0xfc, + 0x00, 0xad, 0x07, 0xac, 0xf1, 0xe0, 0x27, 0x56, 0x97, 0x61, 0x5e, 0x65, 0x54, 0xde, 0x6c, 0xc7, 0xb6, 0x73, 0xa6, + 0xaa, 0x16, 0x7c, 0x16, 0x86, 0x16, 0xed, 0x6c, 0xd5, 0x9c, 0xdc, 0xe6, 0x0d, 0xbe, 0x33, 0x49, 0x22, 0xb5, 0x94, + 0x44, 0xda, 0xea, 0xfa, 0x74, 0xe9, 0x75, 0x8b, 0x0a, 0x1a, 0x23, 0x40, 0x2f, 0x49, 0x77, 0x95, 0x4f, 0x28, 0x5e, + 0x59, 0x0d, 0xab, 0xe1, 0xa5, 0x43, 0x11, 0xc6, 0xda, 0x9b, 0x2b, 0x79, 0x76, 0x07, 0xd6, 0x23, 0xb4, 0x76, 0x55, + 0xea, 0x10, 0xb6, 0x9f, 0xe8, 0x3d, 0xa7, 0x52, 0x7f, 0x03, 0xaa, 0xc0, 0xa9, 0xa3, 0xa1, 0x3e, 0x6a, 0xa7, 0x90, + 0xed, 0xdc, 0x5b, 0x12, 0x54, 0xae, 0xe4, 0xa6, 0x4a, 0x8b, 0x52, 0xca, 0x94, 0xaf, 0x65, 0xb6, 0xb2, 0xfb, 0x64, + 0x00, 0xf1, 0x6c, 0x50, 0x20, 0xb9, 0xa8, 0xad, 0xe6, 0x20, 0x7d, 0x34, 0x4b, 0x1c, 0x6b, 0x07, 0x85, 0x97, 0x55, + 0x60, 0xe6, 0x32, 0x97, 0xcb, 0x41, 0xc1, 0x72, 0xbd, 0xd5, 0x4c, 0x33, 0xd5, 0x17, 0xb9, 0xbd, 0xcd, 0x78, 0x99, + 0xfe, 0x9b, 0x25, 0x03, 0x1e, 0x5d, 0x3c, 0xf7, 0x03, 0x48, 0x93, 0xbc, 0x0e, 0x90, 0x04, 0x9b, 0x83, 0x5d, 0xec, + 0x30, 0x6c, 0x15, 0x2b, 0x7b, 0xf2, 0x74, 0xb9, 0x43, 0x53, 0x2e, 0x61, 0x24, 0x27, 0xe6, 0x52, 0xea, 0xfb, 0x92, + 0xea, 0x86, 0x82, 0x93, 0x4d, 0x13, 0x50, 0x0a, 0x68, 0xb7, 0xe0, 0xbf, 0xf0, 0xa9, 0xa1, 0xd3, 0x02, 0x2c, 0xb5, + 0xdd, 0x80, 0xff, 0x42, 0xbf, 0xd8, 0x3e, 0xa2, 0x7e, 0x60, 0x1e, 0xec, 0xcd, 0xda, 0xca, 0x18, 0x10, 0x91, 0xb8, + 0x82, 0x3c, 0x12, 0xfc, 0xa0, 0xd8, 0xd3, 0x65, 0xe2, 0xc0, 0x99, 0xe2, 0x62, 0x29, 0xb5, 0x99, 0x79, 0xed, 0xb7, + 0xd4, 0xc4, 0x9b, 0x28, 0x89, 0x0a, 0xdb, 0x21, 0x8d, 0x5e, 0x52, 0xc6, 0x54, 0xc1, 0x86, 0xe8, 0xbe, 0x6e, 0x82, + 0x29, 0xf0, 0xa6, 0xaa, 0x02, 0x22, 0xd4, 0x5e, 0x64, 0x79, 0x7e, 0xd3, 0x05, 0x56, 0x17, 0x7c, 0x6c, 0x4c, 0xb3, + 0x0b, 0x56, 0x72, 0x35, 0x93, 0x3e, 0xf3, 0x76, 0xa0, 0x85, 0xbc, 0xcb, 0xcb, 0xa2, 0x15, 0xba, 0x1e, 0x44, 0x0b, + 0x7f, 0xaf, 0x39, 0x1e, 0x3d, 0xdb, 0x56, 0x53, 0x9b, 0x7d, 0xad, 0xc5, 0x02, 0x19, 0x88, 0x86, 0xbe, 0x90, 0x33, + 0x0a, 0x77, 0x95, 0xe6, 0x6a, 0xb5, 0xaf, 0xca, 0x20, 0x81, 0x89, 0x20, 0x6b, 0x59, 0x78, 0x8f, 0xee, 0xd5, 0x23, + 0xcd, 0x2b, 0x09, 0x9e, 0xb9, 0xf8, 0x0b, 0x00, 0xa1, 0x3c, 0x49, 0xc8, 0x01, 0x39, 0x80, 0xbf, 0xa5, 0x28, 0x95, + 0x06, 0xf8, 0x67, 0x75, 0x39, 0xb6, 0xf5, 0xfd, 0x9d, 0x56, 0x31, 0xb8, 0xfe, 0x7c, 0xdd, 0xf5, 0xac, 0x1d, 0xe2, + 0x5c, 0xd9, 0xea, 0xb5, 0x65, 0x9a, 0xc7, 0x48, 0x5d, 0x03, 0x70, 0x27, 0xd2, 0x23, 0x10, 0xc9, 0x4c, 0x34, 0xc8, + 0xd9, 0x0b, 0x3e, 0x9e, 0x8a, 0xc7, 0xa4, 0xbd, 0xca, 0xf7, 0xcd, 0x85, 0x3e, 0x18, 0x63, 0xdf, 0x82, 0x06, 0xf1, + 0xd1, 0x6a, 0x6b, 0x05, 0x62, 0xbd, 0x55, 0xea, 0x43, 0x37, 0x46, 0x41, 0x07, 0x8f, 0xb8, 0x91, 0x0b, 0x8e, 0xed, + 0xae, 0xad, 0xa7, 0xf4, 0x15, 0x80, 0xb9, 0x0e, 0x54, 0x32, 0x0c, 0x52, 0xe7, 0x89, 0xc2, 0x24, 0x3f, 0x4f, 0x48, + 0x42, 0x44, 0x75, 0xb6, 0x1c, 0xa5, 0xdc, 0xb4, 0x80, 0xcb, 0x8c, 0x0c, 0x30, 0x9b, 0x34, 0xeb, 0x27, 0x97, 0x2f, + 0x41, 0x2a, 0x0d, 0x11, 0xdc, 0xb0, 0xbd, 0x64, 0x74, 0xeb, 0xa8, 0x1b, 0x54, 0x49, 0xe6, 0xfa, 0xcd, 0xed, 0x2c, + 0x52, 0xe6, 0xcd, 0x47, 0x18, 0x6b, 0xf2, 0x21, 0xac, 0x13, 0xfc, 0x36, 0x40, 0x25, 0x7d, 0x2a, 0xbc, 0x68, 0x04, + 0x10, 0xea, 0x3b, 0x55, 0xc6, 0xa7, 0xc2, 0xcb, 0x46, 0x5b, 0x96, 0x51, 0x0a, 0xd5, 0x05, 0xb3, 0x5b, 0xd3, 0x85, + 0xe8, 0x56, 0xd5, 0x40, 0x1b, 0xb8, 0x76, 0x1d, 0x28, 0xa0, 0xa1, 0xda, 0x95, 0x1b, 0x16, 0x80, 0xd5, 0x4c, 0x04, + 0x86, 0xcb, 0xbf, 0xcf, 0x5f, 0xa9, 0x18, 0x9e, 0x7e, 0x3f, 0xf4, 0xf6, 0xdb, 0x20, 0x1a, 0x6d, 0x2f, 0xd9, 0x2e, + 0x88, 0x46, 0xbb, 0xcb, 0x86, 0xd1, 0xef, 0xe7, 0xf4, 0xfb, 0x79, 0x03, 0x3a, 0x12, 0x61, 0xc2, 0xec, 0xf5, 0x1b, + 0xb5, 0x7c, 0xa5, 0xd6, 0xef, 0xd4, 0xf2, 0xa5, 0x1a, 0xde, 0xda, 0x93, 0x44, 0x10, 0x59, 0xaa, 0x9a, 0x07, 0x49, + 0x91, 0x6a, 0xe9, 0x72, 0x8c, 0x16, 0x23, 0x6a, 0x29, 0x6b, 0x8e, 0x75, 0x22, 0xed, 0x1c, 0x94, 0x0c, 0x70, 0xb4, + 0xb8, 0xaa, 0x31, 0xdd, 0xac, 0x68, 0x09, 0xc4, 0x08, 0x2b, 0xdb, 0x72, 0x71, 0x93, 0xfa, 0xe8, 0x9c, 0x7c, 0xdb, + 0x2a, 0xe5, 0xdb, 0x56, 0xf0, 0xfc, 0x2b, 0x0a, 0xe5, 0x92, 0x6b, 0xd7, 0xb2, 0x69, 0xa1, 0x14, 0xca, 0xb8, 0x06, + 0x5b, 0xfb, 0x26, 0x30, 0x64, 0x3e, 0x52, 0xd4, 0xd8, 0x5e, 0x34, 0xca, 0x21, 0xc8, 0xd6, 0xc1, 0xa8, 0x53, 0x16, + 0x2c, 0xbe, 0xdd, 0x21, 0x03, 0x19, 0xe8, 0xa8, 0x6a, 0xe3, 0xd5, 0xce, 0x4a, 0x7f, 0x58, 0x5e, 0x3c, 0x67, 0x89, + 0x95, 0x4e, 0x7e, 0x53, 0xa1, 0x3f, 0x08, 0xd1, 0x37, 0x65, 0xc3, 0xc1, 0x8b, 0x2e, 0xb6, 0x32, 0x20, 0xde, 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, 0xf3, 0x28, 0xd4, + 0x2c, 0x4f, 0x00, 0x0b, 0x5e, 0x98, 0x19, 0x2e, 0xcc, 0x0c, 0xc7, 0x21, 0x35, 0x4e, 0x0f, 0x7a, 0xaf, 0x73, 0xcf, + 0x2d, 0x77, 0xa3, 0xd3, 0x30, 0x6f, 0x47, 0x1b, 0xcc, 0xf1, 0x41, 0x38, 0x81, 0xf8, 0xc0, 0x12, 0x01, 0x7a, 0x34, + 0xac, 0x8e, 0x1a, 0x2a, 0x47, 0xf1, 0x65, 0x01, 0x48, 0x96, 0x04, 0x20, 0xb9, 0x57, 0xe3, 0x5c, 0x5a, 0x7e, 0x5d, + 0x25, 0x21, 0x47, 0x64, 0xbc, 0x94, 0x76, 0xf7, 0x84, 0x97, 0x23, 0x23, 0x34, 0x4f, 0x16, 0xa9, 0x97, 0xb3, 0x8c, + 0x8d, 0x11, 0xb8, 0x28, 0xf4, 0x9b, 0xaa, 0xdf, 0x4f, 0x4b, 0x2f, 0xa7, 0x76, 0x7e, 0x02, 0x7f, 0xcb, 0x53, 0x67, + 0x91, 0x23, 0xe4, 0xd5, 0xc8, 0x24, 0x2c, 0x2f, 0x95, 0x7a, 0xfa, 0x12, 0x66, 0x50, 0x77, 0x6f, 0x14, 0x80, 0x6b, + 0x91, 0x4b, 0xa7, 0xda, 0x12, 0xae, 0x4c, 0xb9, 0xc1, 0x3e, 0x0f, 0x79, 0x4e, 0x42, 0xa8, 0x44, 0x1e, 0x29, 0xac, + 0xfb, 0xf6, 0xc5, 0xf3, 0x89, 0xeb, 0xc3, 0x62, 0xa3, 0x11, 0x1c, 0x0e, 0x00, 0x73, 0x30, 0xf5, 0xa2, 0x01, 0x2f, + 0xd5, 0x9c, 0xf9, 0xe8, 0xe5, 0x84, 0x8d, 0x01, 0x6a, 0x8a, 0x81, 0x53, 0xd6, 0x33, 0xf9, 0xc8, 0xf8, 0x96, 0xf9, + 0x7e, 0x80, 0xef, 0xd6, 0x85, 0x84, 0x7c, 0x50, 0xa8, 0x04, 0x99, 0x42, 0x25, 0x48, 0x0c, 0x2a, 0x41, 0x6c, 0x50, + 0x09, 0x36, 0x0d, 0x5f, 0x4b, 0xe5, 0x6d, 0x04, 0x1c, 0x11, 0x3e, 0xf4, 0x2c, 0x6c, 0xac, 0x50, 0x3c, 0x1b, 0xb3, + 0x31, 0x2b, 0xd4, 0xce, 0x93, 0xcb, 0xa9, 0xd8, 0x59, 0x8c, 0x75, 0x13, 0x59, 0x26, 0x5e, 0x48, 0xd0, 0x71, 0xce, + 0x85, 0x44, 0x5d, 0xfd, 0xdc, 0x7b, 0x49, 0xc6, 0x92, 0x79, 0x43, 0xa3, 0x06, 0xf3, 0xb2, 0xeb, 0x00, 0xa6, 0x25, + 0xdf, 0x16, 0x34, 0x98, 0x4e, 0x95, 0x47, 0xa4, 0x49, 0x50, 0x3b, 0x97, 0x49, 0x91, 0x13, 0xc2, 0x24, 0xe8, 0x95, + 0xe0, 0x37, 0x12, 0xda, 0xff, 0xab, 0x9e, 0xef, 0x80, 0xc1, 0x44, 0xab, 0xe4, 0x0b, 0x58, 0x2d, 0x73, 0xfe, 0x52, + 0x7a, 0x62, 0x23, 0xfe, 0x62, 0x99, 0xc6, 0xa3, 0x2f, 0x6c, 0x88, 0x78, 0x56, 0x2f, 0xd1, 0xb4, 0x04, 0x75, 0x80, + 0x47, 0xf4, 0xd7, 0xe8, 0x8b, 0xe1, 0x4d, 0xe9, 0x6a, 0xa4, 0xae, 0xd9, 0x39, 0xe7, 0x5f, 0x6a, 0x43, 0x84, 0x8c, + 0x69, 0x53, 0x20, 0x19, 0x10, 0x48, 0x32, 0x10, 0x00, 0x98, 0x9a, 0xce, 0xec, 0x15, 0x40, 0x34, 0x10, 0xc0, 0xe3, + 0xbc, 0xe3, 0xf1, 0x23, 0xfd, 0x55, 0x1c, 0xf7, 0x4e, 0xd3, 0xb0, 0xfd, 0x17, 0xa0, 0x29, 0x86, 0x72, 0x3c, 0xdf, + 0x29, 0x48, 0xf6, 0x28, 0x65, 0xe9, 0xaa, 0x89, 0xec, 0x50, 0xac, 0x4f, 0x73, 0xca, 0x42, 0xda, 0x96, 0x63, 0xb4, + 0xc5, 0xfa, 0x31, 0xf2, 0xde, 0xdc, 0xa8, 0xc8, 0x07, 0x3d, 0xb8, 0xbd, 0xbd, 0x7d, 0xdd, 0x63, 0x36, 0xc9, 0x8a, + 0x45, 0xae, 0x22, 0x4e, 0x9c, 0xd6, 0x21, 0x07, 0x0c, 0xc8, 0x49, 0x08, 0x4c, 0x63, 0x5c, 0x2a, 0xd0, 0x41, 0xc9, + 0x72, 0x5e, 0x03, 0xb5, 0x2c, 0x22, 0x6b, 0x80, 0xa8, 0xa6, 0xf9, 0x57, 0x0d, 0xf9, 0x49, 0xd5, 0x9c, 0x52, 0xa8, + 0x7d, 0xc5, 0xc3, 0xea, 0xf4, 0x89, 0x55, 0x9b, 0x18, 0xeb, 0x5f, 0x6b, 0x4f, 0xd0, 0x56, 0xd2, 0x40, 0x7c, 0xe7, + 0xeb, 0xf4, 0x8e, 0x42, 0x77, 0x9c, 0x99, 0x78, 0xaa, 0x02, 0x63, 0xdf, 0xda, 0x11, 0x14, 0x0e, 0x4d, 0xd7, 0x01, + 0x87, 0x69, 0x74, 0xc2, 0xe2, 0x9f, 0xd2, 0x71, 0xf2, 0xa2, 0x56, 0x88, 0x24, 0xff, 0x10, 0x2e, 0x0c, 0x89, 0x05, + 0x79, 0x49, 0xa8, 0x23, 0x32, 0x62, 0x35, 0x2a, 0xd6, 0x42, 0x45, 0xc5, 0x29, 0x1e, 0x6f, 0x15, 0x14, 0x97, 0xa2, + 0x54, 0x29, 0x15, 0xb9, 0x51, 0x29, 0x20, 0x96, 0x0d, 0xbc, 0x5b, 0xc0, 0x01, 0x10, 0x74, 0x96, 0xbb, 0xb5, 0xed, + 0x6e, 0x23, 0xf3, 0x99, 0x69, 0x9e, 0x56, 0x1f, 0xd4, 0xdf, 0xef, 0x97, 0x18, 0x5b, 0xe3, 0xe9, 0xef, 0xdb, 0xb4, + 0xe0, 0xe6, 0x6f, 0x18, 0xa2, 0x3b, 0x40, 0xc4, 0x2c, 0xed, 0xa1, 0x90, 0x05, 0x13, 0x96, 0xa1, 0x2a, 0x4f, 0x39, + 0xea, 0xe5, 0x93, 0x5b, 0x80, 0x50, 0x43, 0xbf, 0x36, 0x3a, 0xd5, 0x55, 0x09, 0xc2, 0xf7, 0x5d, 0xa1, 0x1e, 0x9b, + 0x03, 0x9e, 0x0c, 0x80, 0xbf, 0x22, 0xaf, 0xf5, 0xd8, 0xfe, 0x41, 0x6f, 0xd4, 0x1b, 0x20, 0x88, 0xce, 0x79, 0xe1, + 0x1f, 0x71, 0xae, 0x53, 0x7f, 0xc6, 0x85, 0x20, 0xbe, 0xf5, 0x24, 0xbc, 0x17, 0x67, 0x69, 0x1c, 0x9c, 0xf5, 0x06, + 0xe6, 0x22, 0x50, 0x9c, 0xa5, 0xf9, 0x19, 0x88, 0xe5, 0x88, 0x89, 0x58, 0xb3, 0x3b, 0x80, 0x09, 0x2c, 0x75, 0x1c, + 0xb2, 0xea, 0xd8, 0x7e, 0xff, 0xcd, 0xc8, 0x90, 0xa5, 0x23, 0x0c, 0x8c, 0xfe, 0x5d, 0x81, 0x00, 0x05, 0xcb, 0xcc, + 0xf6, 0x60, 0xd2, 0xd5, 0x9e, 0xd5, 0xf3, 0x66, 0x93, 0x77, 0xf5, 0x8e, 0xd5, 0xb4, 0x9c, 0x9a, 0x56, 0x59, 0x4d, + 0x9b, 0xe4, 0x50, 0x33, 0xd1, 0xef, 0x6b, 0x50, 0xd4, 0x7c, 0x0e, 0x60, 0x6c, 0x98, 0xfc, 0x66, 0x56, 0xcd, 0xfb, + 0x7d, 0x4f, 0x3e, 0x82, 0x5f, 0xc8, 0x56, 0xe6, 0xd6, 0x58, 0x3e, 0x7d, 0x4d, 0x24, 0x66, 0x06, 0xe6, 0xe8, 0xee, + 0x08, 0xdf, 0xeb, 0x46, 0x78, 0x1d, 0x73, 0x85, 0xcd, 0xc4, 0xf4, 0x0d, 0x0c, 0x9e, 0x27, 0x7c, 0x70, 0x91, 0xa3, + 0xbf, 0x91, 0xc3, 0x4c, 0x61, 0x41, 0xce, 0xfd, 0xc9, 0x1b, 0xc4, 0x4b, 0x46, 0x78, 0x07, 0x9d, 0x4e, 0x78, 0x90, + 0xfd, 0xfe, 0x0a, 0x3a, 0xb3, 0x95, 0x4a, 0xd9, 0xaa, 0xa8, 0x4c, 0xd7, 0x75, 0x51, 0x56, 0xd0, 0xb1, 0xf4, 0xf3, + 0x56, 0xc8, 0xcc, 0xfa, 0x99, 0x05, 0xf7, 0xb4, 0x92, 0x00, 0x53, 0xb6, 0x6d, 0xa2, 0x36, 0xf0, 0xb2, 0x2e, 0x3e, + 0x17, 0x78, 0x74, 0xd6, 0x5e, 0x6f, 0x84, 0xda, 0xe7, 0x7c, 0xb4, 0x2e, 0xd6, 0x1e, 0xf8, 0xc1, 0xcc, 0xd2, 0xb9, + 0x22, 0xce, 0xc8, 0xfd, 0xd1, 0xe7, 0x22, 0xcd, 0x29, 0x0f, 0x70, 0x1f, 0x8a, 0xb9, 0xfd, 0x16, 0x48, 0x3f, 0xf4, + 0x16, 0xc8, 0x3e, 0x3a, 0xe7, 0xe4, 0x0d, 0x20, 0xd2, 0x21, 0x0c, 0x6e, 0x45, 0x82, 0x8e, 0x55, 0xc3, 0x5b, 0x0b, + 0xec, 0xb4, 0x97, 0xc6, 0xbd, 0x34, 0x3f, 0x4b, 0xfb, 0x7d, 0x83, 0x9a, 0x99, 0x22, 0x1c, 0x3c, 0xce, 0xc8, 0x45, + 0xd2, 0x82, 0x2d, 0xa5, 0xfd, 0x57, 0x03, 0x47, 0x10, 0xf2, 0xf7, 0x3f, 0x84, 0xf7, 0x04, 0x20, 0x36, 0x69, 0x03, + 0xae, 0x7a, 0x4c, 0x47, 0x63, 0x4b, 0xa2, 0x56, 0x9d, 0x0d, 0x90, 0x38, 0x55, 0x5a, 0x4f, 0xb9, 0x59, 0x53, 0x18, + 0xa4, 0xca, 0x42, 0xfd, 0xc6, 0x7a, 0x32, 0x59, 0xe5, 0x22, 0x23, 0x8e, 0xca, 0xf4, 0xa5, 0x66, 0x04, 0xd3, 0xa5, + 0x9f, 0x2f, 0x60, 0xc9, 0xc6, 0x1f, 0x71, 0xf2, 0x96, 0x80, 0x63, 0x3b, 0x6b, 0x57, 0xd5, 0x2e, 0xc7, 0xad, 0xdd, + 0x1c, 0xe0, 0x7b, 0xbd, 0xd1, 0x68, 0xa4, 0x9d, 0xe3, 0x04, 0x0c, 0x55, 0x4f, 0x2d, 0x85, 0x1e, 0xab, 0x15, 0xa0, + 0x6e, 0x47, 0x2e, 0xb3, 0x64, 0x30, 0x5f, 0x18, 0xc7, 0xaf, 0xcc, 0x47, 0x1f, 0x2f, 0x95, 0xb5, 0xeb, 0x88, 0xaf, + 0xff, 0x20, 0xab, 0xf5, 0x2d, 0xef, 0xaa, 0x26, 0xe0, 0x8b, 0x2a, 0xa0, 0xf4, 0x1b, 0xde, 0x93, 0xbd, 0x8b, 0xaf, + 0xdd, 0x60, 0x97, 0x7c, 0xcb, 0x5b, 0xd4, 0x79, 0xbe, 0x72, 0x70, 0xa3, 0x4a, 0xb7, 0xf7, 0x92, 0x05, 0xae, 0xbd, + 0xa3, 0xa6, 0xb1, 0x9e, 0xf9, 0xd1, 0xc3, 0x22, 0x64, 0x3b, 0x1f, 0x7b, 0x5f, 0x35, 0x4f, 0xcf, 0x1a, 0x7a, 0x93, + 0x1a, 0xfa, 0xd8, 0x8b, 0xb2, 0x7d, 0x6a, 0x1a, 0xd1, 0x6b, 0xd8, 0xd0, 0xc7, 0xde, 0x92, 0x93, 0x43, 0x22, 0xc0, + 0xa9, 0x31, 0x7f, 0x7c, 0x38, 0x9d, 0xe1, 0xef, 0x18, 0x50, 0x09, 0xc4, 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, 0x24, 0x77, 0xa5, 0x37, 0xb0, 0x02, 0x69, 0x5b, 0x54, 0x1f, 0xca, + 0xa5, 0xb7, 0x53, 0x87, 0x76, 0xe5, 0x4f, 0xf2, 0xc3, 0xa1, 0x18, 0x99, 0x63, 0x1c, 0xc0, 0x4d, 0x0a, 0x25, 0x47, + 0xc9, 0x5a, 0x82, 0xe8, 0x94, 0xc6, 0x53, 0x59, 0xaf, 0xad, 0x88, 0xbc, 0x1a, 0x71, 0x1e, 0x82, 0x1f, 0x3d, 0x50, + 0x8b, 0xbf, 0xd0, 0x82, 0xd8, 0x63, 0x9f, 0x2a, 0xa5, 0x17, 0xbc, 0x2a, 0x20, 0x44, 0xec, 0xef, 0x06, 0xda, 0x41, + 0x09, 0x0e, 0x25, 0xdc, 0x07, 0x84, 0x85, 0x7e, 0xed, 0xe5, 0x33, 0x19, 0xa3, 0xdc, 0x1b, 0x54, 0x73, 0x06, 0x30, + 0x95, 0x3e, 0x03, 0xbf, 0x4b, 0x80, 0x3a, 0xc5, 0xa7, 0xe8, 0x54, 0x6f, 0x1e, 0x36, 0x5d, 0x9f, 0x96, 0x28, 0x8a, + 0xe8, 0xce, 0xcf, 0xc7, 0x80, 0xd8, 0xd9, 0xb5, 0x19, 0x69, 0xd7, 0x7e, 0x83, 0x06, 0x2b, 0x25, 0x89, 0x76, 0x4e, + 0x09, 0xbb, 0x9d, 0x8f, 0x6c, 0xe9, 0x47, 0x29, 0x10, 0x73, 0xc7, 0x89, 0x44, 0xf6, 0x60, 0x23, 0x27, 0x70, 0x8b, + 0xf6, 0x8e, 0x0e, 0x40, 0xe5, 0x46, 0x41, 0x7e, 0x35, 0x47, 0x72, 0xc7, 0x77, 0xbd, 0xef, 0x06, 0xf5, 0xe0, 0xbb, + 0xde, 0x59, 0x4a, 0x72, 0x47, 0x78, 0xa6, 0xa6, 0x84, 0x88, 0xcf, 0xbe, 0x1b, 0xe4, 0x03, 0x3c, 0x4b, 0xb4, 0x48, + 0x8b, 0x84, 0x6a, 0x75, 0x8d, 0x9b, 0xf0, 0x22, 0x91, 0xdc, 0x43, 0xbb, 0xce, 0x23, 0x62, 0x01, 0xc8, 0x58, 0x7c, + 0x36, 0x6f, 0x28, 0xd4, 0xdd, 0xc4, 0x6c, 0xd1, 0x5d, 0x16, 0xfb, 0xfd, 0x6d, 0x9e, 0xd6, 0x3d, 0x1d, 0x1f, 0x83, + 0x2f, 0x48, 0x35, 0x01, 0x1e, 0xed, 0xaf, 0xcd, 0xf1, 0xea, 0xd5, 0xe6, 0x48, 0x59, 0xa8, 0x12, 0xf5, 0x5b, 0xac, + 0x66, 0x3d, 0x84, 0xe1, 0xce, 0x32, 0x63, 0x6d, 0x2f, 0x78, 0x25, 0x67, 0x55, 0x6c, 0x97, 0xe3, 0x2b, 0x96, 0xda, + 0x4a, 0xa2, 0x72, 0xb4, 0x1e, 0x6b, 0x53, 0x8c, 0xfc, 0x4a, 0x21, 0x51, 0x16, 0x1d, 0x5b, 0x0b, 0x05, 0xc4, 0x0b, + 0xd0, 0x97, 0xec, 0x4c, 0x03, 0xac, 0x37, 0x7a, 0x15, 0x11, 0x5a, 0x3e, 0x52, 0xe1, 0x4d, 0x6e, 0xaa, 0xcc, 0xca, + 0x66, 0xd1, 0xee, 0xa7, 0x8a, 0x57, 0x08, 0x56, 0x6f, 0xd4, 0x1e, 0x05, 0xa8, 0x3d, 0xb4, 0x50, 0x06, 0x90, 0xd2, + 0x34, 0x03, 0x40, 0x06, 0x00, 0x99, 0x2a, 0xe2, 0x33, 0x01, 0x2a, 0x6d, 0x75, 0xa3, 0xc0, 0x89, 0xf4, 0x1a, 0x68, + 0x16, 0x58, 0xe9, 0x23, 0x05, 0x19, 0x2c, 0xb6, 0x08, 0xc0, 0xca, 0x91, 0x33, 0x4c, 0x63, 0xc8, 0x36, 0x9a, 0xb8, + 0x24, 0xcd, 0xef, 0xc3, 0x2c, 0x95, 0x78, 0x12, 0x3f, 0xc8, 0x1a, 0x23, 0x00, 0x90, 0xbe, 0x4f, 0x2f, 0x8a, 0x2c, + 0x26, 0x1c, 0x38, 0xeb, 0xa9, 0x83, 0xa2, 0x26, 0xe7, 0x5a, 0xd3, 0xea, 0x59, 0x6d, 0xf2, 0x90, 0x05, 0x3a, 0x7b, + 0x30, 0x26, 0xb5, 0x7c, 0xcf, 0x23, 0xfb, 0x2b, 0xc7, 0x33, 0xc2, 0x77, 0xdd, 0xc1, 0xa9, 0xff, 0x6e, 0x6a, 0x60, + 0x62, 0x4a, 0x00, 0x36, 0x06, 0x47, 0x13, 0xe2, 0x77, 0x3a, 0x26, 0x53, 0x9b, 0x14, 0x81, 0xc0, 0x43, 0xf0, 0x0a, + 0x9e, 0x1b, 0x2e, 0xb7, 0xdc, 0xd8, 0x59, 0xe4, 0x69, 0x02, 0x70, 0xe2, 0x05, 0xdf, 0x02, 0x1c, 0xa7, 0x5e, 0x15, + 0xb2, 0x67, 0xcf, 0xc5, 0x74, 0x36, 0x0f, 0x1e, 0x12, 0xda, 0xbf, 0x98, 0xf0, 0x9b, 0xee, 0x2a, 0xb9, 0x32, 0xb5, + 0xee, 0x4d, 0x74, 0x95, 0xcb, 0x9d, 0x3e, 0xad, 0x38, 0x86, 0x39, 0x83, 0x55, 0x40, 0xce, 0xd9, 0x90, 0xbf, 0x38, + 0x07, 0xc0, 0x96, 0x95, 0xf0, 0x22, 0xfe, 0x22, 0x94, 0xd5, 0x02, 0xb8, 0x47, 0xce, 0x23, 0xf3, 0xcb, 0x57, 0xdb, + 0xa1, 0x9c, 0x53, 0x14, 0xc6, 0x72, 0x6a, 0x5a, 0x52, 0x9c, 0x0e, 0x3d, 0x05, 0x93, 0xa9, 0x2d, 0x7f, 0x6f, 0x13, + 0x97, 0xd9, 0x9b, 0x49, 0x38, 0x5f, 0x47, 0xb6, 0xad, 0x55, 0xf7, 0xd0, 0x0d, 0xc1, 0xa0, 0x8f, 0x11, 0xb4, 0x6c, + 0xae, 0xef, 0xd6, 0x83, 0x81, 0xc2, 0xf6, 0xad, 0xe9, 0xa6, 0x45, 0xa7, 0x38, 0xe0, 0xcc, 0x5a, 0xd7, 0xa8, 0x54, + 0x15, 0x87, 0x5e, 0xf2, 0x6e, 0x59, 0x95, 0x5d, 0x96, 0x5e, 0x08, 0x52, 0xa3, 0xae, 0x22, 0x44, 0x4a, 0xc5, 0x0e, + 0xef, 0xc9, 0xaf, 0x81, 0x89, 0x67, 0x56, 0x8e, 0xd2, 0x78, 0x0e, 0x30, 0x41, 0x0a, 0x7d, 0x53, 0x7e, 0x05, 0xb8, + 0xa1, 0x8b, 0x28, 0xcc, 0xde, 0xc6, 0x55, 0x50, 0x5b, 0x4d, 0xbf, 0x77, 0x70, 0x62, 0xcf, 0xeb, 0x7e, 0x3f, 0x25, + 0x1a, 0x3f, 0x0c, 0xbd, 0xc0, 0xbf, 0xc7, 0xd3, 0x7d, 0x13, 0xa4, 0xe6, 0x95, 0x07, 0x78, 0x45, 0x97, 0x5b, 0x9b, + 0x72, 0x45, 0xe3, 0x62, 0x5e, 0x23, 0x22, 0x7c, 0xea, 0x28, 0xb6, 0xdb, 0xfc, 0x38, 0xb5, 0x31, 0x18, 0x84, 0x70, + 0xdf, 0xca, 0xf8, 0x7d, 0xe2, 0xe5, 0xb3, 0x68, 0x0e, 0x8a, 0xd2, 0x4c, 0x93, 0x84, 0x14, 0xd2, 0x4b, 0x80, 0x3e, + 0x1a, 0x84, 0x5a, 0x5d, 0xf9, 0x47, 0xe2, 0xa5, 0x6a, 0x5a, 0x9b, 0xa7, 0x58, 0xa3, 0x40, 0xcc, 0xa2, 0x79, 0xc3, + 0x32, 0x3a, 0x24, 0xd5, 0xe5, 0xd2, 0x34, 0xe3, 0x0f, 0xab, 0x19, 0xaa, 0x15, 0x47, 0x4d, 0x50, 0xa3, 0x74, 0x03, + 0x17, 0xc0, 0xbf, 0xd3, 0x1d, 0x47, 0x35, 0x8a, 0x14, 0x0d, 0xf8, 0x04, 0x81, 0x61, 0xcd, 0xe6, 0x09, 0x6b, 0x4d, + 0x5d, 0x33, 0xfa, 0x7d, 0x19, 0x27, 0x64, 0x92, 0x90, 0x9c, 0x0f, 0x97, 0xeb, 0x47, 0x52, 0x5d, 0x00, 0xa9, 0x72, + 0xc5, 0x66, 0xbd, 0xde, 0x1c, 0x30, 0x7a, 0x61, 0xfd, 0xc2, 0xc6, 0x15, 0x9c, 0x5f, 0x12, 0xe6, 0xae, 0xfa, 0x11, + 0x66, 0x19, 0x54, 0x01, 0x69, 0x7e, 0x2c, 0x78, 0xf3, 0xdc, 0x05, 0xa2, 0x7e, 0x33, 0x52, 0x17, 0x94, 0x59, 0x3a, + 0xb7, 0x88, 0x40, 0xc0, 0x6b, 0x58, 0x3d, 0x81, 0x64, 0x5f, 0x3e, 0xf6, 0x69, 0x46, 0x81, 0xea, 0x08, 0x40, 0xd9, + 0xac, 0x1f, 0xc2, 0xfe, 0x01, 0xe1, 0x84, 0xfa, 0x9b, 0x37, 0x72, 0xd6, 0x90, 0x3c, 0x90, 0x6a, 0xc2, 0x63, 0x38, + 0x35, 0x16, 0xf8, 0xd2, 0xa2, 0x37, 0x15, 0xbc, 0x26, 0x38, 0xee, 0x05, 0x5a, 0xfb, 0x16, 0x70, 0x84, 0x08, 0x2e, + 0x43, 0x13, 0xa7, 0xbd, 0x5d, 0x2f, 0x40, 0x42, 0x73, 0x0b, 0xe7, 0xfa, 0xda, 0x05, 0x2d, 0x4e, 0x91, 0x93, 0x45, + 0x17, 0x18, 0xe8, 0x82, 0xcc, 0x1b, 0xff, 0xaa, 0x60, 0xe5, 0x02, 0x64, 0x2f, 0x15, 0x2b, 0x89, 0xd8, 0x76, 0xea, + 0x8f, 0x52, 0xd9, 0x6f, 0xcf, 0xac, 0x09, 0xfc, 0x2a, 0xb1, 0x5f, 0x22, 0x93, 0x6f, 0x7a, 0x6c, 0xf2, 0x95, 0xb1, + 0xd0, 0xa9, 0x65, 0x70, 0x4e, 0x8f, 0x0c, 0xce, 0xbd, 0x9d, 0x55, 0x9b, 0x10, 0x86, 0x82, 0x24, 0xd0, 0x74, 0xe9, + 0x61, 0xdd, 0xf4, 0xe7, 0x27, 0x2d, 0x7e, 0xad, 0xda, 0xb7, 0xee, 0xc7, 0x21, 0x76, 0xf1, 0xab, 0xc4, 0x33, 0xec, + 0xa3, 0x3e, 0x70, 0x80, 0xc9, 0x88, 0x89, 0xcb, 0x7e, 0x1f, 0x0a, 0x9b, 0x8d, 0xe7, 0xa3, 0xba, 0xf8, 0xb9, 0x78, + 0x00, 0x28, 0x87, 0x0a, 0xec, 0x72, 0x28, 0x43, 0x19, 0xb1, 0xa9, 0x2d, 0xf7, 0xfc, 0xfe, 0x2a, 0xcc, 0x41, 0xde, + 0xd1, 0x98, 0x38, 0x67, 0x20, 0x86, 0xc1, 0xd7, 0xbf, 0x7b, 0xb2, 0x4f, 0x9b, 0xef, 0xce, 0xe0, 0xbb, 0xa3, 0xb3, + 0x0f, 0xc8, 0x71, 0x73, 0xb6, 0x2e, 0x8b, 0xfb, 0x34, 0x16, 0x67, 0xdf, 0x41, 0xea, 0x77, 0x67, 0x45, 0x79, 0xf6, + 0x9d, 0xaa, 0xcc, 0x77, 0x67, 0xb4, 0xe0, 0x46, 0xbf, 0x5b, 0x13, 0xef, 0x9f, 0x95, 0xa6, 0x3d, 0x5b, 0x42, 0x38, + 0x96, 0x56, 0x3f, 0x82, 0x12, 0x51, 0x91, 0xa2, 0xca, 0x50, 0x56, 0x6b, 0xc7, 0x79, 0x9f, 0x68, 0x78, 0x6c, 0x9a, + 0x90, 0xb8, 0x5a, 0xc2, 0x3a, 0xd4, 0xb3, 0xd3, 0x26, 0xd9, 0x71, 0x1e, 0xa8, 0x03, 0x22, 0xe7, 0x2f, 0xf2, 0xd1, + 0x96, 0xbe, 0x06, 0xdf, 0x3a, 0x1c, 0xf2, 0xd1, 0xce, 0xfc, 0xf4, 0xc9, 0x5a, 0x29, 0x83, 0x8d, 0x14, 0xa3, 0x10, + 0x12, 0xc5, 0x6d, 0x7b, 0x0c, 0x80, 0xff, 0xfd, 0xc3, 0x81, 0x7e, 0xef, 0xe4, 0x6f, 0xb5, 0x5b, 0x5a, 0xf5, 0xfc, + 0xd0, 0x22, 0xcc, 0x78, 0x5d, 0x1b, 0x76, 0xb6, 0xbd, 0x04, 0x94, 0xde, 0x37, 0x0d, 0x6a, 0x8a, 0xe8, 0x27, 0xac, + 0x26, 0x56, 0x71, 0x58, 0x90, 0x12, 0x87, 0x18, 0x8e, 0xd1, 0x0e, 0x3d, 0x4e, 0x17, 0x35, 0x4f, 0xee, 0x3b, 0x64, + 0xdc, 0xfa, 0x3e, 0x20, 0xb9, 0x14, 0xce, 0x3f, 0x78, 0xa1, 0xc1, 0x44, 0x2f, 0xf2, 0xaa, 0xc8, 0xc4, 0x48, 0xd0, + 0x28, 0xbf, 0x25, 0x71, 0xe6, 0x0c, 0x6b, 0x71, 0xa6, 0x10, 0xc2, 0x42, 0x42, 0xe5, 0x2e, 0x4a, 0x4a, 0x0f, 0xce, + 0x9e, 0xec, 0xcb, 0xe6, 0x77, 0xc2, 0x84, 0x18, 0x2d, 0x80, 0x06, 0x67, 0xd7, 0x2e, 0xef, 0x21, 0x2c, 0x73, 0xef, + 0xf7, 0xb7, 0x77, 0x79, 0x01, 0x71, 0x99, 0x67, 0x52, 0xb1, 0x5a, 0x9e, 0x01, 0x4d, 0x9e, 0x88, 0xcf, 0xc2, 0x4a, + 0x4e, 0x83, 0xaa, 0xa3, 0x58, 0xbd, 0x8d, 0xe7, 0x1e, 0xf0, 0x7a, 0xbf, 0x4f, 0x80, 0xc0, 0xdd, 0x67, 0x6f, 0x94, + 0x5b, 0x2a, 0xe9, 0x91, 0xe7, 0x18, 0x22, 0x99, 0x00, 0xaf, 0x33, 0x04, 0x47, 0x0a, 0xab, 0xe7, 0x26, 0xc8, 0x3f, + 0xbe, 0x3e, 0xa1, 0xf8, 0xa2, 0x79, 0x14, 0x35, 0x2c, 0x64, 0x09, 0x1c, 0x0f, 0xc9, 0x2c, 0x9b, 0x23, 0x35, 0x79, + 0xda, 0x9e, 0x22, 0x1d, 0x9d, 0x58, 0xe2, 0xb7, 0x35, 0xa9, 0x5e, 0xa4, 0xc2, 0x2e, 0x69, 0x67, 0x2b, 0x73, 0x2f, + 0x84, 0xa1, 0x4a, 0xb8, 0xf7, 0xba, 0x9e, 0x85, 0x72, 0x53, 0xb4, 0x2a, 0x66, 0x0f, 0x53, 0x62, 0x86, 0x29, 0xd6, + 0x5f, 0xd8, 0xf0, 0x9b, 0xc4, 0x8b, 0xc1, 0x70, 0xbd, 0xe4, 0xe5, 0x6c, 0x63, 0x16, 0xc2, 0xe1, 0xb0, 0x99, 0x14, + 0xb3, 0x25, 0xc4, 0xb6, 0x2e, 0xe7, 0x87, 0x43, 0x57, 0xcb, 0xd6, 0xc2, 0x83, 0x87, 0xaa, 0x85, 0x9b, 0x86, 0xe5, + 0xf0, 0x33, 0x99, 0xc5, 0xd8, 0xbe, 0xc6, 0x67, 0xf6, 0xe7, 0x8b, 0xee, 0x59, 0x82, 0x8c, 0x1b, 0x6b, 0xe0, 0x1a, + 0x9b, 0xb5, 0x3b, 0x5c, 0x8d, 0x80, 0xe4, 0x71, 0x37, 0xfa, 0xbb, 0xb2, 0x93, 0x9c, 0x04, 0x09, 0xa3, 0x15, 0xc2, + 0xef, 0xbe, 0xf1, 0x27, 0x5a, 0xec, 0x41, 0xbb, 0x8d, 0x2d, 0x21, 0xaa, 0x69, 0xcf, 0xe5, 0x4a, 0xb1, 0x34, 0x6f, + 0xa5, 0x0d, 0x99, 0x0f, 0xeb, 0x73, 0xdf, 0xc8, 0x81, 0x82, 0x31, 0xe2, 0xa9, 0x75, 0x10, 0xcd, 0xe6, 0xc0, 0x7d, + 0x81, 0xe6, 0x11, 0x9e, 0x5a, 0x90, 0xa0, 0xcc, 0xda, 0xb0, 0x9f, 0x24, 0x27, 0xcb, 0xe3, 0xf0, 0x2d, 0xfc, 0xcb, + 0x67, 0xd8, 0x24, 0xa6, 0x28, 0x1e, 0x7f, 0xab, 0x14, 0xff, 0x1d, 0x5b, 0x10, 0xc1, 0xda, 0x8d, 0xa8, 0x0d, 0x7f, + 0xc3, 0xbf, 0x85, 0x7d, 0x84, 0xfd, 0x86, 0x26, 0x08, 0x03, 0x58, 0x7f, 0x26, 0x10, 0x17, 0x16, 0x82, 0x04, 0x7f, + 0xab, 0x24, 0xff, 0x9c, 0xf0, 0xd9, 0xa2, 0x04, 0xb2, 0x3a, 0x8c, 0xe2, 0x13, 0x8a, 0x89, 0x42, 0x18, 0x6e, 0x09, + 0xbd, 0xa3, 0xff, 0x46, 0x94, 0x64, 0x93, 0xdc, 0x8a, 0xf5, 0x40, 0x26, 0x49, 0x30, 0xc1, 0xca, 0x0b, 0xe5, 0x4b, + 0xf7, 0x42, 0xa9, 0xb5, 0x16, 0xb4, 0x7e, 0xf9, 0x93, 0xc4, 0x33, 0xa0, 0x7b, 0x20, 0x63, 0xd0, 0x6d, 0x44, 0x35, + 0xc9, 0x31, 0x7d, 0x94, 0xce, 0x33, 0x50, 0x01, 0x9d, 0xad, 0xb3, 0xb0, 0x5e, 0x16, 0xe5, 0xaa, 0x15, 0x1e, 0x2a, + 0x4b, 0x1f, 0xa9, 0xc7, 0x98, 0x17, 0xe6, 0xc9, 0x89, 0x7c, 0xf0, 0x08, 0xd0, 0xf0, 0x28, 0x4f, 0xab, 0x8e, 0xd2, + 0xfa, 0x81, 0x65, 0xc0, 0x08, 0x9c, 0x28, 0x03, 0x1e, 0x61, 0x19, 0x98, 0xa7, 0x5d, 0x86, 0x1a, 0xc4, 0x1a, 0x55, + 0x57, 0x6a, 0x83, 0x39, 0x51, 0x94, 0x7c, 0x8a, 0xa5, 0x15, 0xc6, 0xd0, 0xd4, 0x95, 0x47, 0xd6, 0x4b, 0x4e, 0xd8, + 0x93, 0xdd, 0x40, 0xba, 0x85, 0x8d, 0x02, 0x17, 0x74, 0x2d, 0x4b, 0x94, 0x8b, 0x6e, 0x19, 0x51, 0x26, 0x42, 0xea, + 0x67, 0x0f, 0x67, 0x5a, 0xed, 0x37, 0x76, 0xd2, 0xbe, 0x3d, 0x52, 0xf4, 0x82, 0x81, 0xf8, 0xb4, 0x47, 0x4a, 0x3d, + 0x6b, 0xe4, 0x32, 0xb0, 0xa5, 0x4b, 0x55, 0xcf, 0x7f, 0x83, 0xf2, 0x1d, 0xcc, 0x8c, 0xb3, 0xd9, 0xef, 0x7a, 0x73, + 0x7b, 0xb2, 0xaf, 0x9b, 0xdf, 0x59, 0xaf, 0x07, 0x5b, 0x83, 0x4c, 0x7c, 0xa9, 0xa8, 0xa7, 0xac, 0x42, 0xac, 0xc8, + 0xec, 0x7f, 0x0b, 0xef, 0x77, 0x78, 0x6b, 0x84, 0x66, 0x65, 0x3c, 0xcc, 0x47, 0x4f, 0xf6, 0xa2, 0xf9, 0xbd, 0xb3, + 0x6c, 0x2b, 0x57, 0x25, 0xb3, 0xfd, 0x7e, 0x94, 0x34, 0x67, 0x8f, 0xd7, 0x48, 0xea, 0x00, 0x1f, 0xaf, 0xcf, 0xf0, + 0x91, 0x4a, 0x28, 0xb5, 0xa0, 0xaa, 0x41, 0xeb, 0x63, 0xbf, 0xb7, 0x9e, 0xd3, 0xc7, 0x8f, 0xe5, 0x74, 0x4b, 0x8a, + 0x30, 0x7e, 0x60, 0x30, 0x65, 0x27, 0x4e, 0x5d, 0xf2, 0x66, 0x48, 0xef, 0xba, 0x55, 0x52, 0x97, 0x3d, 0x4a, 0x04, + 0xa1, 0x0e, 0xd6, 0x2f, 0xf6, 0x43, 0x98, 0xd9, 0xa2, 0x3f, 0x6c, 0x56, 0x73, 0x42, 0x41, 0x04, 0x88, 0x56, 0x79, + 0x1f, 0x38, 0x26, 0x09, 0xb3, 0xe6, 0x86, 0x74, 0xeb, 0xcd, 0x95, 0xf6, 0x4a, 0x0a, 0xe8, 0xe7, 0x20, 0x73, 0xfb, + 0xe8, 0x96, 0xab, 0x96, 0x79, 0x2e, 0x6d, 0x39, 0x60, 0xd1, 0x42, 0x74, 0x66, 0xe7, 0xd2, 0xe1, 0xe0, 0x3f, 0xa8, + 0x2b, 0x51, 0x45, 0x04, 0x1d, 0x45, 0x0b, 0x46, 0xab, 0x55, 0xbb, 0x9c, 0x6c, 0x2a, 0x64, 0x4b, 0x22, 0x9c, 0x28, + 0xd9, 0x2b, 0xa1, 0x3e, 0xca, 0xd5, 0x9e, 0x69, 0x88, 0x3f, 0x13, 0xb0, 0x69, 0x83, 0xbf, 0x05, 0xee, 0x65, 0x70, + 0x66, 0xda, 0xa7, 0x61, 0x04, 0x44, 0xe6, 0x10, 0xec, 0xe7, 0x77, 0x3d, 0xa8, 0xe0, 0x41, 0x47, 0xfa, 0xeb, 0x7a, + 0x56, 0xe0, 0x99, 0x7b, 0xe2, 0xf9, 0x9b, 0x13, 0xe9, 0x45, 0x0e, 0x0f, 0x34, 0xf7, 0x61, 0xc6, 0x5f, 0x96, 0x65, + 0xb8, 0x1b, 0x2d, 0xcb, 0x62, 0xe5, 0x45, 0x7a, 0x1f, 0xcf, 0xa4, 0x18, 0x48, 0x74, 0x98, 0x19, 0x5d, 0xc5, 0x3a, + 0xce, 0x61, 0xdc, 0xdb, 0x93, 0xb0, 0x42, 0xfb, 0x67, 0x89, 0xbd, 0x2e, 0x00, 0xc0, 0x21, 0x6b, 0xd0, 0x0a, 0xef, + 0x74, 0x7b, 0xbb, 0xc7, 0x25, 0x25, 0x8a, 0x1b, 0x35, 0x3f, 0xab, 0xa1, 0x65, 0x82, 0x5a, 0x66, 0xdd, 0xc9, 0x64, + 0x8a, 0x24, 0xf0, 0x6d, 0xd8, 0x1b, 0x56, 0xe4, 0xf3, 0x46, 0x6e, 0x0f, 0xef, 0xc2, 0x95, 0x88, 0xb5, 0x05, 0x9d, + 0x74, 0x64, 0x1c, 0xee, 0x85, 0xe6, 0x46, 0xba, 0x7f, 0x52, 0x25, 0x61, 0x29, 0x62, 0xb8, 0x05, 0xb2, 0xbd, 0xda, + 0x56, 0x82, 0x12, 0x48, 0x60, 0x3f, 0x94, 0x62, 0x99, 0x6e, 0x05, 0x80, 0x39, 0xf0, 0x3f, 0x25, 0x0c, 0xa1, 0xbb, + 0xf3, 0x10, 0xaf, 0x1a, 0x79, 0xdf, 0x20, 0x04, 0xfb, 0x6b, 0x90, 0xd3, 0x80, 0x41, 0xa4, 0x18, 0xc9, 0x82, 0x81, + 0x04, 0x20, 0xe7, 0x6b, 0x30, 0xc9, 0x4d, 0x73, 0xcf, 0x0f, 0x72, 0xdd, 0xc1, 0xb4, 0x0f, 0xba, 0x17, 0xd7, 0x9a, + 0xe5, 0xe0, 0x15, 0x13, 0xf1, 0xbf, 0xd7, 0x5e, 0xc9, 0x72, 0x96, 0xf9, 0x8d, 0xb9, 0xe8, 0x64, 0x70, 0xd5, 0x10, + 0x7e, 0x31, 0xcb, 0xe6, 0x3c, 0x9a, 0x65, 0x3a, 0xd4, 0xbf, 0x68, 0x8e, 0x4a, 0x01, 0x0c, 0x75, 0xbc, 0x00, 0x6b, + 0xbc, 0x2b, 0xdd, 0xb4, 0xe2, 0x91, 0xc6, 0x18, 0x05, 0x15, 0x3a, 0x08, 0xfd, 0xbd, 0x06, 0x78, 0x0d, 0x26, 0xb9, + 0x11, 0x2a, 0x1f, 0x5c, 0xd0, 0x0d, 0xdd, 0x72, 0xe5, 0x12, 0xd4, 0xa4, 0x6a, 0xf9, 0xe5, 0x08, 0xf5, 0xae, 0x96, + 0x5c, 0xaa, 0xcd, 0xa7, 0x46, 0x59, 0x23, 0xc8, 0xe4, 0x28, 0xfd, 0x3e, 0xe5, 0xc2, 0xad, 0x8c, 0xc9, 0xfa, 0x70, + 0xf0, 0x0a, 0x6e, 0x6a, 0xfc, 0x3a, 0x27, 0x16, 0x51, 0x7b, 0x48, 0x84, 0xad, 0xdd, 0x0a, 0xdd, 0x7b, 0xdc, 0x28, + 0xcd, 0xa3, 0x6c, 0x13, 0x8b, 0xca, 0xeb, 0x25, 0x60, 0x2d, 0xee, 0x01, 0x19, 0x2a, 0x2d, 0xfd, 0x8a, 0x15, 0x00, + 0x19, 0x20, 0x85, 0x8d, 0x1f, 0x90, 0xf6, 0xea, 0x83, 0x97, 0xfa, 0xfd, 0xbe, 0x31, 0xe5, 0xbf, 0x7f, 0xc8, 0x81, + 0x99, 0x50, 0x94, 0xf5, 0x0e, 0x26, 0x10, 0x5c, 0x3b, 0x49, 0x7b, 0x56, 0xf3, 0x17, 0xeb, 0xda, 0x03, 0x52, 0x2b, + 0xdf, 0x62, 0xae, 0x7a, 0x6d, 0x5f, 0x6c, 0xf6, 0x69, 0x75, 0x63, 0x34, 0x0e, 0x82, 0xa5, 0xd5, 0x5b, 0xad, 0x72, + 0xc8, 0x1b, 0x5e, 0x81, 0x48, 0x65, 0x5d, 0x5d, 0x2b, 0xe7, 0xea, 0x5a, 0x70, 0x24, 0x90, 0x2d, 0x79, 0x0e, 0xff, + 0x85, 0xdc, 0x2b, 0x0f, 0x87, 0xc2, 0xef, 0xf7, 0xd3, 0x19, 0x69, 0x65, 0x81, 0x32, 0x6d, 0x5d, 0x7b, 0xa1, 0x7f, + 0x38, 0xfc, 0x00, 0x5e, 0x23, 0xfe, 0xe1, 0x50, 0xf6, 0xfb, 0x1f, 0xcd, 0x4d, 0xe6, 0x7c, 0xac, 0x94, 0xb2, 0x97, + 0xa8, 0x74, 0x7f, 0x9b, 0xf0, 0xde, 0xff, 0x1e, 0xfd, 0xef, 0xd1, 0x65, 0x4f, 0x05, 0x80, 0x25, 0x7c, 0x86, 0x37, + 0x74, 0xa6, 0x2e, 0xe7, 0x4c, 0xba, 0xbb, 0x2b, 0x3f, 0xf4, 0x9e, 0xc6, 0x87, 0xef, 0xcd, 0x4d, 0x1b, 0x7f, 0xad, + 0x8e, 0x34, 0x09, 0x1d, 0x17, 0xfd, 0xc3, 0xe1, 0x53, 0xa2, 0xf5, 0x69, 0xa9, 0xd2, 0xa7, 0x29, 0xf0, 0x24, 0xc3, + 0x86, 0xeb, 0x16, 0xa6, 0xa3, 0xf9, 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, 0x5b, 0xe5, 0x0a, 0xde, 0xda, + 0xe3, 0xdd, 0x60, 0x44, 0xa9, 0x23, 0x7d, 0xd2, 0x86, 0xd0, 0x25, 0x95, 0xfc, 0x47, 0x91, 0xc7, 0x18, 0xb3, 0xf1, + 0x9a, 0xc8, 0x3e, 0x8b, 0xfc, 0x55, 0x01, 0x80, 0x45, 0x80, 0x80, 0x9c, 0xce, 0x1d, 0x49, 0xfc, 0xe7, 0xe4, 0xdb, + 0x3f, 0xa6, 0x4b, 0xfb, 0x50, 0x16, 0x77, 0xa5, 0xa8, 0xaa, 0xa3, 0xd2, 0x76, 0xb6, 0x5c, 0x0f, 0xf4, 0xa1, 0xfd, + 0xbe, 0xa4, 0x0f, 0x4d, 0x31, 0x14, 0x05, 0x6e, 0x8d, 0xbd, 0x69, 0xca, 0x15, 0x4d, 0xf5, 0xc8, 0x58, 0x3f, 0xbf, + 0xdf, 0xbd, 0x8d, 0xbd, 0xd4, 0x0f, 0x52, 0x10, 0x84, 0x35, 0x7e, 0x52, 0x8a, 0x24, 0x70, 0x3e, 0xc3, 0x54, 0xe2, + 0xd3, 0xa5, 0x54, 0xf9, 0xc3, 0x48, 0xf3, 0x61, 0x0a, 0x7a, 0xd9, 0x7f, 0x54, 0x30, 0xff, 0x75, 0x7b, 0xb0, 0x3e, + 0xad, 0xcb, 0x34, 0xaa, 0x88, 0x2a, 0x2f, 0x4c, 0xb5, 0x09, 0x44, 0xf0, 0x17, 0xc2, 0x22, 0xf9, 0xf5, 0xc9, 0x91, + 0xa0, 0x31, 0x93, 0xe5, 0xe3, 0x91, 0xfb, 0x85, 0x7d, 0xe5, 0x3a, 0x9e, 0xff, 0xb9, 0x99, 0xff, 0x03, 0x74, 0x86, + 0x2c, 0x5e, 0x70, 0xcb, 0x60, 0x81, 0xb3, 0x5f, 0xba, 0x7a, 0xc0, 0xdf, 0xcc, 0x13, 0x2f, 0x80, 0x83, 0xf9, 0x05, + 0xba, 0x2a, 0xa6, 0xb3, 0x62, 0x00, 0x04, 0xb6, 0x7e, 0x63, 0xcd, 0x89, 0x37, 0x16, 0xcf, 0x95, 0x5c, 0x10, 0xfa, + 0xba, 0x0a, 0xb3, 0x71, 0x55, 0x6c, 0x2a, 0x51, 0x6c, 0xea, 0x1e, 0xa9, 0x65, 0xf3, 0x69, 0x6d, 0x2b, 0x64, 0x7f, + 0x12, 0x2d, 0xda, 0x2e, 0x43, 0x35, 0x19, 0x65, 0xe9, 0x7a, 0x0a, 0xa4, 0x7a, 0x01, 0x9c, 0x45, 0xe6, 0x95, 0x2f, + 0xce, 0x1e, 0xb0, 0x45, 0xe3, 0x29, 0x30, 0xa2, 0xd2, 0x1f, 0x79, 0x63, 0x74, 0x7a, 0xa2, 0xdf, 0xcf, 0xa7, 0x14, + 0xf2, 0xf5, 0x13, 0x60, 0x72, 0xd5, 0x72, 0x01, 0xfa, 0x32, 0xd4, 0x41, 0x25, 0x4a, 0xad, 0x18, 0x46, 0x2c, 0xfc, + 0x24, 0x90, 0xbd, 0x99, 0x82, 0x9a, 0x55, 0x94, 0x84, 0x4a, 0x54, 0x4a, 0xb6, 0x26, 0xa8, 0xa5, 0xf7, 0x45, 0x51, + 0xef, 0x2b, 0x70, 0x94, 0x8c, 0xb4, 0x59, 0x4e, 0x99, 0x71, 0x51, 0xe6, 0xa2, 0x1f, 0xec, 0xdf, 0x95, 0xe7, 0x37, + 0x32, 0x9f, 0xe5, 0xbe, 0xa3, 0x73, 0xda, 0x8e, 0x0b, 0x94, 0xb9, 0xe5, 0xb4, 0xd5, 0x92, 0xc7, 0xe4, 0x3d, 0x0b, + 0xb6, 0xfd, 0x97, 0x09, 0xf2, 0x2a, 0xc2, 0x7c, 0x42, 0x95, 0xcd, 0x3f, 0x20, 0xcc, 0x16, 0x07, 0xf6, 0xd8, 0x85, + 0x89, 0x48, 0x6f, 0xc1, 0x92, 0x18, 0x66, 0xa5, 0x08, 0xe3, 0x1d, 0x78, 0xff, 0x6c, 0x2a, 0x31, 0x3a, 0x43, 0x27, + 0xf7, 0xb3, 0x87, 0xb4, 0x4e, 0xce, 0xde, 0xbe, 0x3e, 0xfb, 0xae, 0x37, 0x28, 0x46, 0x69, 0x3c, 0xe8, 0x7d, 0x77, + 0xb6, 0xda, 0x00, 0x44, 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, 0x74, 0x7b, 0x22, 0xed, 0xaa, 0x74, 0x05, 0x84, 0x1e, + 0x00, 0x27, 0x5d, 0xf9, 0xf3, 0x70, 0x10, 0x09, 0x84, 0x5a, 0x30, 0x27, 0xd3, 0x88, 0x6e, 0x48, 0xaf, 0xb0, 0xcf, + 0xc0, 0x2c, 0xa4, 0x34, 0x0f, 0x6e, 0xae, 0x16, 0x2d, 0x77, 0xc5, 0xca, 0x51, 0x58, 0xad, 0x45, 0x54, 0x23, 0xd5, + 0x31, 0x38, 0xef, 0x40, 0x04, 0x80, 0x62, 0x04, 0xcf, 0x78, 0xd4, 0xef, 0x47, 0x2a, 0x28, 0x27, 0xa1, 0x5f, 0x14, + 0xfa, 0xa5, 0x31, 0x28, 0x63, 0xfe, 0x2e, 0xd4, 0xc4, 0x00, 0xf5, 0x96, 0x87, 0x8a, 0x23, 0x00, 0x97, 0x73, 0xc4, + 0x8c, 0xf3, 0x1e, 0x77, 0xd1, 0x38, 0x15, 0xef, 0x84, 0xba, 0x0e, 0x96, 0x0a, 0x75, 0xde, 0xd4, 0x47, 0x7a, 0x4e, + 0x9a, 0x04, 0x0d, 0xe2, 0x06, 0x1e, 0xaf, 0x86, 0x80, 0x6a, 0x25, 0xa4, 0xde, 0x42, 0xa7, 0x54, 0x75, 0x08, 0xac, + 0x01, 0x2e, 0x51, 0xd8, 0x56, 0x98, 0x1c, 0xd1, 0xa6, 0x2c, 0x45, 0x7e, 0xc4, 0x06, 0xed, 0x92, 0x91, 0xa9, 0x83, + 0xcb, 0xe5, 0x72, 0x22, 0xea, 0x5f, 0xf3, 0x2d, 0x80, 0xf3, 0x42, 0x7e, 0x6b, 0x37, 0x5b, 0x26, 0xd9, 0xae, 0x2b, + 0xc3, 0x59, 0x52, 0x8a, 0x6a, 0x5d, 0xe4, 0x55, 0x7a, 0x2f, 0x7e, 0xd6, 0x0f, 0x5d, 0x02, 0x29, 0xf4, 0x23, 0xbd, + 0x6e, 0x37, 0x47, 0xaa, 0x71, 0x74, 0x39, 0xb6, 0xa7, 0xd2, 0x4e, 0xf6, 0xaa, 0xc5, 0x9b, 0x2d, 0x73, 0x25, 0x69, + 0x1c, 0x8b, 0xfc, 0x6d, 0x1e, 0xa7, 0x91, 0x95, 0x1c, 0xfe, 0x1f, 0xde, 0xbe, 0x85, 0xbb, 0x6d, 0x1b, 0x5b, 0xf7, + 0xaf, 0x58, 0xbc, 0xa9, 0x4a, 0x44, 0x90, 0x2c, 0x39, 0x49, 0x67, 0x4a, 0x19, 0xd6, 0x71, 0xf3, 0x68, 0xd3, 0x36, + 0x71, 0x1a, 0xa7, 0x9d, 0xce, 0xe8, 0xea, 0xb8, 0x34, 0x09, 0x5b, 0x6c, 0x68, 0x40, 0x25, 0x29, 0x3f, 0x22, 0xf1, + 0xbf, 0xdf, 0xb5, 0x37, 0x9e, 0xa4, 0x68, 0x27, 0x33, 0xf7, 0xdc, 0xbb, 0xb2, 0x56, 0x2c, 0x82, 0x20, 0xde, 0xd8, + 0xd8, 0xd8, 0x8f, 0x6f, 0xeb, 0x00, 0xd5, 0x2e, 0xf2, 0x95, 0x8b, 0x8d, 0xfc, 0x22, 0x2b, 0x31, 0x60, 0x70, 0xa3, + 0x51, 0xad, 0x50, 0x53, 0x26, 0xf0, 0x85, 0x7c, 0x8f, 0x11, 0xb7, 0x59, 0x99, 0x00, 0xc3, 0x8f, 0x89, 0xfa, 0x92, + 0x9e, 0x42, 0x94, 0x07, 0x15, 0x8f, 0xfb, 0x05, 0x47, 0xc4, 0x6b, 0xab, 0x32, 0x07, 0x26, 0x5b, 0xab, 0x20, 0x11, + 0xec, 0x2e, 0x9b, 0xeb, 0x45, 0xb4, 0x50, 0x77, 0xa1, 0x5e, 0xbc, 0xdd, 0xf6, 0x12, 0x45, 0x07, 0x9c, 0xfc, 0x34, + 0x78, 0x15, 0x67, 0x39, 0x4f, 0xf7, 0x2a, 0xb9, 0xa7, 0x36, 0xd4, 0x9e, 0x72, 0xe6, 0x80, 0x9d, 0xf7, 0x75, 0xb5, + 0xa7, 0xd7, 0xf4, 0x9e, 0x6e, 0xe7, 0x1e, 0x5c, 0x30, 0x70, 0xe7, 0x5e, 0x66, 0xd7, 0x5c, 0xec, 0x81, 0x32, 0xd0, + 0x1a, 0x0f, 0xd4, 0xa2, 0x1a, 0xa9, 0x89, 0xd1, 0x81, 0xab, 0x13, 0x7d, 0x30, 0x07, 0xf4, 0x7b, 0x88, 0x15, 0xde, + 0x7a, 0xbb, 0xd2, 0x07, 0x6d, 0x40, 0x7f, 0x5e, 0x9a, 0x3e, 0xe8, 0x68, 0xf1, 0x2a, 0x24, 0x70, 0x63, 0x48, 0x35, + 0x52, 0xab, 0x91, 0x55, 0xa0, 0x78, 0xc3, 0x5b, 0xbc, 0x3b, 0xd7, 0x92, 0x8d, 0xf7, 0x12, 0x81, 0xbd, 0x32, 0x51, + 0xc5, 0x99, 0x38, 0xf6, 0x52, 0x79, 0xad, 0x9d, 0x64, 0x84, 0xf1, 0x2d, 0x2b, 0xa9, 0xbf, 0x43, 0xcc, 0x2d, 0xd2, + 0x1c, 0x06, 0x2f, 0xc3, 0x8a, 0xcc, 0x78, 0xbf, 0x2f, 0x67, 0x32, 0x2a, 0x67, 0x62, 0xbf, 0x8c, 0x14, 0x42, 0xdb, + 0x7d, 0x22, 0xa0, 0x07, 0x25, 0x40, 0xbe, 0x00, 0xa8, 0x7a, 0x48, 0xf8, 0xf3, 0x90, 0xd4, 0xa7, 0x53, 0xe8, 0x53, + 0x68, 0xeb, 0x15, 0xaf, 0xa0, 0xaa, 0x6e, 0x8c, 0x6c, 0xa3, 0x82, 0x16, 0x8f, 0xe5, 0x59, 0x6d, 0x18, 0x9b, 0x53, + 0xeb, 0x5d, 0x6f, 0x36, 0x98, 0xb2, 0xb9, 0x50, 0xab, 0x30, 0x24, 0xd1, 0x4d, 0xe9, 0x85, 0x0f, 0xb1, 0x58, 0x59, + 0xad, 0xcd, 0x6f, 0x62, 0x7f, 0x64, 0x22, 0xc5, 0xfd, 0x6c, 0x89, 0x73, 0x17, 0x8f, 0xe7, 0x55, 0x5f, 0x6b, 0x69, + 0x91, 0x69, 0xf3, 0x9d, 0xbe, 0x0c, 0x69, 0x2a, 0x6a, 0x48, 0xa3, 0xce, 0x0c, 0xba, 0x6f, 0x97, 0x57, 0x54, 0x23, + 0x4c, 0x80, 0x57, 0x3a, 0x83, 0x6e, 0x34, 0x1e, 0x88, 0xa2, 0x1a, 0x15, 0x6b, 0x21, 0x10, 0x6d, 0x18, 0x72, 0xcc, + 0x2c, 0x21, 0xc9, 0x3e, 0xf1, 0xef, 0x54, 0x70, 0x85, 0x22, 0xbe, 0x31, 0x70, 0xde, 0x95, 0xf5, 0xec, 0xae, 0x23, + 0x3f, 0x27, 0x16, 0x56, 0xfb, 0x0f, 0xcd, 0xa3, 0xd6, 0x38, 0x0b, 0x68, 0x6b, 0x5a, 0xdd, 0x70, 0xb8, 0x47, 0x75, + 0x2c, 0x4a, 0x03, 0x48, 0xec, 0x91, 0xe5, 0xa2, 0x75, 0xcc, 0xa0, 0x01, 0xfd, 0x6d, 0x76, 0xb5, 0xbe, 0x42, 0xd4, + 0xb6, 0x12, 0x59, 0x27, 0xa9, 0xfc, 0x4b, 0xda, 0xa3, 0xae, 0xed, 0xa9, 0xfc, 0x6f, 0xdb, 0x54, 0x39, 0xb4, 0x40, + 0xf2, 0xd8, 0xcd, 0x59, 0xa0, 0x3a, 0x12, 0x44, 0x81, 0xda, 0x7a, 0xc1, 0xd4, 0x3b, 0x65, 0x8a, 0x0e, 0xe4, 0xe7, + 0xc2, 0x9c, 0x61, 0x5f, 0x70, 0xc4, 0x98, 0xa5, 0x12, 0x83, 0xa9, 0x8f, 0x31, 0xaa, 0x69, 0xad, 0x00, 0x5d, 0x3f, + 0xdd, 0xc0, 0x9f, 0xa8, 0xa8, 0xd1, 0x50, 0x6b, 0x24, 0x85, 0xa2, 0x89, 0x0a, 0x3a, 0x96, 0x16, 0x3a, 0x98, 0x42, + 0x27, 0x91, 0xb0, 0x04, 0x34, 0x4c, 0x88, 0x4e, 0x2a, 0xf0, 0xd6, 0x00, 0xce, 0x7c, 0x5c, 0x94, 0xeb, 0x42, 0x1b, + 0xcc, 0xfd, 0x10, 0x5f, 0xf3, 0xd7, 0x2f, 0x9c, 0x51, 0x7d, 0xcb, 0x5a, 0xdf, 0xd3, 0x82, 0xfc, 0x10, 0x72, 0x8a, + 0x0e, 0x4c, 0xec, 0x68, 0x83, 0xc6, 0x18, 0x65, 0xad, 0x43, 0x5d, 0x9c, 0xe8, 0xf8, 0x2b, 0xda, 0x04, 0xef, 0x01, + 0x4f, 0x11, 0x6d, 0x78, 0x28, 0x8c, 0x55, 0x35, 0x3e, 0x95, 0xac, 0xa5, 0x07, 0x2b, 0x78, 0xba, 0x4e, 0x78, 0x08, + 0x7a, 0x24, 0xc2, 0x8e, 0xc2, 0x62, 0x1e, 0x2f, 0xe0, 0x38, 0x29, 0x08, 0xa8, 0x1d, 0xf4, 0x15, 0x7c, 0xbe, 0x40, + 0xf7, 0x57, 0x89, 0x1e, 0x60, 0x68, 0x41, 0xdc, 0x0c, 0x7d, 0x3a, 0xba, 0x8a, 0x57, 0x0d, 0x15, 0x09, 0x9f, 0x17, + 0x60, 0x3b, 0xa4, 0xd4, 0x53, 0xa0, 0x85, 0x4a, 0x94, 0x7e, 0x18, 0xf8, 0x0e, 0x0d, 0x7c, 0xad, 0x75, 0x80, 0x86, + 0x7e, 0xc6, 0x34, 0xb5, 0xce, 0x50, 0xf9, 0xcc, 0xbb, 0x67, 0x46, 0xcb, 0x99, 0x05, 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, 0xe3, 0x50, 0x69, 0x73, 0x20, 0xbe, 0x11, 0x1a, 0xf7, 0x4f, + 0xc3, 0xd8, 0x6a, 0x8a, 0xad, 0xdd, 0xdb, 0x76, 0xfb, 0x7b, 0xe9, 0xa5, 0xd3, 0x9c, 0xf4, 0x18, 0xfb, 0xbd, 0x0c, + 0x8b, 0x91, 0xed, 0x08, 0x81, 0x25, 0xe7, 0x7d, 0xea, 0xbf, 0xa2, 0xe5, 0x3c, 0x01, 0xd3, 0x11, 0x1d, 0x21, 0x17, + 0x28, 0x3b, 0x46, 0x71, 0x07, 0x06, 0x57, 0xf4, 0xfb, 0x60, 0x95, 0x61, 0x2e, 0x24, 0x4b, 0x92, 0x32, 0x78, 0x9e, + 0x7a, 0x18, 0xf0, 0x6b, 0xa6, 0xcc, 0x5d, 0x94, 0xf5, 0xe9, 0x92, 0x4c, 0x53, 0x64, 0x20, 0xd6, 0xe1, 0x26, 0x4b, + 0xa3, 0x44, 0x89, 0xc8, 0x96, 0xe8, 0x1f, 0x69, 0x28, 0x96, 0x0e, 0xd7, 0x8b, 0x54, 0x89, 0x50, 0x31, 0x4f, 0xf1, + 0xa4, 0x4e, 0xeb, 0x74, 0x84, 0xf1, 0x26, 0x41, 0x29, 0x57, 0xc3, 0x40, 0x95, 0x54, 0x2f, 0x85, 0x4d, 0xb1, 0xdd, + 0xea, 0x8b, 0x95, 0x98, 0xc7, 0x0b, 0x7c, 0x29, 0x70, 0x14, 0x7f, 0xe2, 0x5e, 0xac, 0x29, 0xb5, 0x3d, 0xa8, 0x1d, + 0x51, 0x42, 0x7f, 0xe2, 0x70, 0x91, 0xf8, 0x4e, 0xea, 0xb8, 0x7f, 0x68, 0x11, 0x72, 0xa6, 0x0e, 0x52, 0xc3, 0x0d, + 0xed, 0x08, 0xff, 0x0d, 0xd7, 0x67, 0x9c, 0xd1, 0x9b, 0x6a, 0x46, 0x8d, 0xdf, 0xeb, 0xe1, 0x19, 0xa3, 0x3e, 0x1b, + 0x38, 0xac, 0x10, 0x85, 0x36, 0xec, 0xa8, 0x54, 0xa2, 0x85, 0xa1, 0x54, 0x7f, 0x09, 0x15, 0x47, 0xdc, 0x99, 0x51, + 0x96, 0x8c, 0x4f, 0xcb, 0x43, 0x31, 0x1d, 0x0c, 0x4a, 0x52, 0x19, 0x0b, 0x3d, 0xb8, 0x1e, 0x78, 0xfe, 0x3d, 0x70, + 0x0b, 0xf1, 0xe0, 0x90, 0xc5, 0x90, 0x1b, 0x70, 0xfc, 0x16, 0x27, 0x57, 0x8d, 0x4a, 0x15, 0xbc, 0x9a, 0xa8, 0x16, + 0xfc, 0x54, 0x86, 0x01, 0xfa, 0x24, 0x05, 0x60, 0x32, 0x98, 0xf2, 0x5b, 0x90, 0x28, 0x9d, 0xa9, 0x1b, 0xd2, 0xaf, + 0xa2, 0xe0, 0x17, 0xbc, 0xe0, 0x22, 0x71, 0x05, 0x58, 0xde, 0xc1, 0xf6, 0x3a, 0xaa, 0xa8, 0x02, 0xe2, 0x35, 0x3d, + 0x8e, 0xb8, 0xf1, 0xfe, 0x33, 0x3d, 0xb6, 0x40, 0xad, 0xd6, 0xb1, 0xc1, 0x67, 0x8e, 0xc1, 0x05, 0x5d, 0x4b, 0x6c, + 0x0d, 0xd5, 0xb0, 0x22, 0x30, 0x70, 0x01, 0x07, 0x61, 0x89, 0xe2, 0xd8, 0x4a, 0x5e, 0x91, 0x86, 0x94, 0xf6, 0x81, + 0xe1, 0x68, 0x93, 0x1c, 0xdf, 0x66, 0xd9, 0x4d, 0xe0, 0x7c, 0xd1, 0x39, 0x69, 0x26, 0x96, 0x0d, 0xde, 0xe7, 0xcd, + 0xf9, 0x75, 0xff, 0x90, 0x50, 0x15, 0xec, 0x86, 0xb7, 0x83, 0xdd, 0x38, 0xe1, 0xd7, 0x5c, 0x2c, 0x74, 0x7c, 0x16, + 0x73, 0xc9, 0xf2, 0x5b, 0xeb, 0xdd, 0x92, 0xa4, 0x56, 0x40, 0xfb, 0x2c, 0x0b, 0x6a, 0x22, 0x00, 0xdd, 0x0f, 0x7f, + 0x81, 0xd0, 0x19, 0xfe, 0xf6, 0x18, 0x5c, 0x91, 0xc2, 0x7b, 0x87, 0x40, 0x58, 0xd3, 0xcd, 0x9d, 0xda, 0x80, 0x2f, + 0xc6, 0xfd, 0x19, 0x53, 0x4f, 0xbf, 0xcd, 0xe4, 0xae, 0xae, 0xdb, 0x23, 0xcb, 0xf0, 0x11, 0xae, 0x14, 0x00, 0xcb, + 0x84, 0xbf, 0x18, 0x5b, 0x52, 0x7d, 0x02, 0x70, 0x6a, 0x3a, 0xa2, 0x4f, 0x10, 0x18, 0x38, 0x25, 0x5a, 0x8c, 0xae, + 0x95, 0x23, 0x9a, 0x41, 0x5a, 0xd3, 0xad, 0x30, 0xde, 0x7a, 0xd0, 0x42, 0xcf, 0x34, 0x9c, 0xf8, 0x0f, 0x9a, 0x79, + 0x55, 0x40, 0x00, 0xad, 0x8c, 0xe0, 0xad, 0xf5, 0xd1, 0x1c, 0x21, 0x3e, 0x61, 0x49, 0x34, 0x61, 0xf1, 0x4c, 0xf1, + 0x63, 0x42, 0x37, 0x4d, 0x6d, 0xd3, 0x07, 0xa4, 0xbf, 0xb8, 0x66, 0xfd, 0x94, 0x65, 0xed, 0xdb, 0x43, 0xc5, 0x8b, + 0x69, 0x33, 0xf8, 0x61, 0xa2, 0x8a, 0xf1, 0xbf, 0xa8, 0x7c, 0xa9, 0x15, 0xc0, 0x30, 0x77, 0xd5, 0xd3, 0xef, 0x37, + 0xb3, 0xe5, 0x40, 0xa8, 0xfc, 0xce, 0x20, 0xe9, 0xd3, 0xf1, 0xfc, 0xc0, 0x26, 0x51, 0x5b, 0xe8, 0xf9, 0xe3, 0x52, + 0x37, 0xa1, 0xf2, 0xda, 0xd4, 0x88, 0x56, 0xc8, 0x50, 0xd9, 0x3a, 0x60, 0x7d, 0xff, 0x10, 0xee, 0x2e, 0x6a, 0x1a, + 0x6a, 0xdd, 0x73, 0xd7, 0xa2, 0xe0, 0xc4, 0x1f, 0x60, 0x2c, 0x2e, 0x24, 0xb5, 0x0e, 0xc2, 0xa4, 0x1f, 0x2d, 0x4e, + 0x72, 0xa3, 0xae, 0x4e, 0xce, 0x14, 0xf3, 0x04, 0x2e, 0xaa, 0x65, 0xdb, 0x5f, 0x51, 0xa9, 0x4b, 0xb9, 0xbd, 0xa2, + 0x34, 0x3d, 0xa4, 0xed, 0x55, 0x9c, 0xb7, 0x05, 0x17, 0xfc, 0x0b, 0x05, 0x17, 0xd6, 0xc1, 0xba, 0xe3, 0x4e, 0xd9, + 0x13, 0x9e, 0x28, 0xd3, 0xda, 0xe0, 0xae, 0x1b, 0x8c, 0x89, 0xb1, 0xdf, 0x5d, 0xf2, 0xe4, 0x23, 0xb2, 0xe0, 0xdf, + 0x65, 0x02, 0x3c, 0x93, 0xdd, 0x2b, 0x95, 0xff, 0x07, 0xff, 0x6a, 0x6b, 0xdf, 0x59, 0xf3, 0x4f, 0xcf, 0x7a, 0xb8, + 0x73, 0x98, 0xfc, 0x00, 0x9d, 0x01, 0xdd, 0x5c, 0xc9, 0x94, 0x03, 0x32, 0x80, 0xb5, 0x48, 0x46, 0x03, 0x3e, 0xb4, + 0xb2, 0x6c, 0xfb, 0x4e, 0xab, 0x0b, 0xc2, 0xbd, 0x04, 0x6e, 0x7a, 0x7f, 0x6d, 0x66, 0xe6, 0x74, 0xad, 0x44, 0xd3, + 0xa5, 0xb1, 0xb5, 0x2c, 0x55, 0xc0, 0xee, 0xf7, 0x9e, 0x64, 0xd3, 0xfc, 0x70, 0x39, 0xcd, 0x2d, 0x75, 0xdb, 0xb8, + 0x65, 0x03, 0x40, 0x88, 0x5d, 0x6b, 0x2b, 0x07, 0x90, 0xdc, 0x1e, 0x84, 0xf0, 0xb5, 0x22, 0xf4, 0x54, 0x89, 0xd0, + 0xa7, 0x69, 0xb3, 0x0f, 0x76, 0x55, 0xad, 0x1b, 0x71, 0x8e, 0x06, 0xa9, 0x66, 0xe4, 0x4f, 0xae, 0x79, 0x71, 0x91, + 0xcb, 0x1b, 0xc0, 0x40, 0x26, 0xb5, 0x51, 0x58, 0x5e, 0x81, 0x3b, 0x3f, 0x3a, 0x8e, 0x33, 0x31, 0xca, 0x31, 0x58, + 0x2b, 0xc2, 0x23, 0xeb, 0xc4, 0x19, 0x80, 0x20, 0xfb, 0x93, 0xa6, 0xe3, 0xb9, 0x16, 0x18, 0xd3, 0x17, 0xb8, 0xab, + 0x9c, 0x1d, 0x6d, 0x72, 0xbb, 0xe8, 0x9b, 0x33, 0xac, 0x3b, 0x52, 0x5a, 0x1b, 0x8b, 0xae, 0x3b, 0x58, 0x6b, 0x06, + 0x6d, 0x11, 0x4a, 0x3e, 0xe4, 0x4e, 0xda, 0x4f, 0x01, 0x0d, 0xce, 0xb2, 0xf4, 0xd6, 0x5a, 0xe5, 0x6f, 0xb4, 0x10, + 0x27, 0x8a, 0xa9, 0x13, 0xdf, 0x44, 0x89, 0x3e, 0x3f, 0x13, 0xe3, 0x06, 0x02, 0xa9, 0x3f, 0x60, 0x50, 0x8d, 0x22, + 0x4c, 0xe0, 0x3a, 0x10, 0xc5, 0xf6, 0x44, 0x6d, 0x2c, 0x47, 0xd0, 0x09, 0x21, 0xde, 0x41, 0x19, 0xc6, 0xea, 0xe2, + 0x40, 0x1b, 0x2c, 0x7d, 0xdd, 0x5a, 0xe7, 0x86, 0x50, 0x18, 0x27, 0x30, 0xc5, 0x20, 0xa9, 0xb3, 0xce, 0x32, 0x41, + 0x95, 0x1d, 0x93, 0xce, 0xfb, 0x00, 0xdd, 0x5d, 0x8b, 0xa6, 0xf8, 0xba, 0x73, 0x07, 0xdd, 0xc7, 0xf5, 0x6b, 0x2d, + 0x72, 0x83, 0x3f, 0x6f, 0x89, 0xb0, 0x08, 0x9c, 0xb5, 0x26, 0x5f, 0x35, 0xc2, 0x81, 0x29, 0xc9, 0x34, 0xec, 0x25, + 0xca, 0xa6, 0x7b, 0xbb, 0xed, 0xf5, 0xee, 0x15, 0x71, 0xf5, 0x18, 0xab, 0xbc, 0x9b, 0xb9, 0xbd, 0x53, 0xad, 0xc5, + 0xee, 0x4d, 0xdb, 0x4f, 0xb1, 0xa3, 0xd6, 0xda, 0xed, 0x86, 0x13, 0x6a, 0xc8, 0xb7, 0xa2, 0x4a, 0xab, 0xd3, 0x8d, + 0x41, 0x3b, 0xc4, 0xb3, 0x16, 0x19, 0xdc, 0x28, 0x5f, 0x38, 0xa1, 0x93, 0x8a, 0xb3, 0xea, 0xd4, 0x05, 0x9b, 0x2b, + 0x5e, 0x2d, 0x65, 0x1a, 0x09, 0x8a, 0x36, 0xe7, 0x51, 0x49, 0x13, 0xb9, 0x16, 0x55, 0x24, 0x6b, 0xd4, 0x8b, 0x5a, + 0x8d, 0x01, 0x02, 0x32, 0x9d, 0x35, 0x3d, 0xa8, 0x82, 0xd9, 0x50, 0x46, 0x72, 0xfa, 0x1e, 0x2c, 0xed, 0x91, 0x63, + 0xad, 0xef, 0xab, 0xb3, 0xc5, 0xb7, 0x7a, 0x42, 0x30, 0x85, 0xd9, 0x03, 0x61, 0xe0, 0x9a, 0xc6, 0x90, 0xd3, 0x2e, + 0x71, 0x59, 0xd3, 0x2d, 0xe1, 0x1e, 0x6e, 0x57, 0xb2, 0x23, 0x37, 0x4f, 0x9a, 0x9b, 0x2b, 0xd8, 0x51, 0x31, 0x1f, + 0x83, 0xf6, 0x4b, 0xaa, 0x6b, 0x97, 0xe6, 0xd6, 0xe3, 0x41, 0x40, 0x83, 0x41, 0x61, 0xf8, 0xd7, 0x89, 0xf1, 0xf0, + 0xa4, 0x01, 0x41, 0x52, 0x2e, 0xc2, 0xb1, 0x6f, 0x44, 0x3f, 0x99, 0xca, 0x43, 0x8e, 0x16, 0xef, 0xd0, 0xea, 0x04, + 0xa2, 0x78, 0x89, 0x50, 0x12, 0xa3, 0x2a, 0x34, 0x22, 0x28, 0x4f, 0xcb, 0x5f, 0xaa, 0xea, 0x10, 0x50, 0x48, 0xfb, + 0x8a, 0x42, 0xd9, 0x26, 0x31, 0x34, 0xc3, 0x2f, 0xe7, 0x93, 0x85, 0x9e, 0x81, 0x81, 0x9c, 0x1f, 0x2c, 0xf4, 0x2c, + 0x0c, 0xe4, 0xfc, 0xc9, 0xa2, 0x76, 0xeb, 0x40, 0x13, 0x10, 0xcf, 0x85, 0xa3, 0x93, 0xd2, 0xaa, 0x6c, 0x01, 0xdd, + 0x3c, 0x44, 0xd0, 0x7f, 0xb2, 0x87, 0xa0, 0x93, 0x0b, 0xed, 0xc8, 0x0d, 0x68, 0x3b, 0x0e, 0x81, 0xbd, 0x62, 0x52, + 0x61, 0x02, 0x10, 0x1d, 0xb2, 0x31, 0x18, 0x62, 0xab, 0x0f, 0x0e, 0xd9, 0x78, 0xea, 0x93, 0x20, 0x60, 0x74, 0x7f, + 0x30, 0x90, 0xe0, 0xb7, 0x78, 0x95, 0x3e, 0xda, 0x08, 0x74, 0xd3, 0x77, 0x77, 0x43, 0xef, 0xe2, 0x0a, 0x4e, 0xd5, + 0xee, 0x9e, 0x84, 0x6e, 0x32, 0xed, 0x00, 0xbd, 0x86, 0xb8, 0x21, 0xbf, 0x32, 0x1a, 0x8d, 0x6c, 0x4a, 0x48, 0x88, + 0xe1, 0x1c, 0x9a, 0x39, 0x2d, 0x97, 0xaf, 0x6e, 0x3d, 0x1b, 0x90, 0x61, 0xa6, 0xb7, 0x4c, 0xd6, 0x0f, 0x50, 0x56, + 0x3d, 0x86, 0x76, 0xe8, 0x3d, 0x72, 0xfc, 0xf0, 0xe0, 0x9b, 0x8c, 0x9f, 0x39, 0x5c, 0x7b, 0x38, 0x17, 0xbe, 0xcb, + 0x9a, 0x91, 0x39, 0x74, 0x9e, 0x7d, 0x1c, 0xef, 0x61, 0x9c, 0x7c, 0x9e, 0x85, 0xf2, 0xc6, 0x6b, 0xfa, 0x1f, 0x95, + 0xde, 0xec, 0x70, 0xc8, 0xe9, 0x0a, 0x56, 0xdc, 0xac, 0x0a, 0x0d, 0x3f, 0x8b, 0xbc, 0x71, 0xc4, 0x6b, 0x12, 0x55, + 0xdd, 0xe7, 0xbd, 0x0d, 0x53, 0xda, 0x31, 0x0e, 0x00, 0x4e, 0xd4, 0xaa, 0x61, 0x57, 0x1a, 0xd7, 0xea, 0x20, 0x86, + 0xa1, 0x84, 0xad, 0x12, 0x47, 0x42, 0xf9, 0x1b, 0x80, 0xb0, 0x18, 0x8a, 0xe3, 0xad, 0x61, 0x7d, 0x80, 0xfd, 0xd0, + 0x05, 0x9a, 0xe6, 0x94, 0x6a, 0x06, 0x00, 0x49, 0xc0, 0x1f, 0x3d, 0xdd, 0x34, 0x54, 0xb6, 0x79, 0x1e, 0x5a, 0x56, + 0x57, 0xf0, 0x40, 0x4f, 0x5d, 0xc9, 0xc0, 0xb8, 0xaa, 0x63, 0x6f, 0x73, 0x7f, 0x7b, 0xb4, 0x8a, 0x7c, 0x67, 0x93, + 0xda, 0x66, 0x55, 0x68, 0xec, 0xe3, 0x09, 0x3d, 0x9d, 0x00, 0xad, 0xd7, 0x96, 0x8a, 0xf6, 0xfb, 0x28, 0x46, 0x8d, + 0x0b, 0x05, 0x56, 0x61, 0x22, 0xc1, 0x21, 0xc2, 0x08, 0xa1, 0xdf, 0x97, 0xe1, 0xc6, 0x17, 0x64, 0x10, 0x0d, 0xd7, + 0xa2, 0xe3, 0x0f, 0x39, 0x5e, 0xb4, 0x2d, 0x55, 0x35, 0x27, 0x4d, 0x5b, 0x02, 0x6f, 0xc2, 0x01, 0xb6, 0xf3, 0x4f, + 0x1b, 0x22, 0x57, 0xe1, 0xa2, 0x84, 0xef, 0x88, 0x6b, 0x41, 0x74, 0x53, 0x9b, 0x7a, 0x1b, 0x76, 0x88, 0x8e, 0xa6, + 0x78, 0x74, 0xc8, 0x3d, 0x77, 0xcf, 0x6d, 0x11, 0xdf, 0x7c, 0x86, 0xdc, 0x35, 0x9d, 0xbd, 0x14, 0x61, 0x50, 0xb7, + 0x6c, 0xa0, 0x58, 0x87, 0x4e, 0x50, 0x80, 0x51, 0x5b, 0x3e, 0x01, 0x1d, 0x1b, 0x0c, 0x2a, 0x82, 0x4f, 0x0a, 0xdb, + 0xa6, 0x41, 0xfe, 0x88, 0x77, 0x43, 0x87, 0xd7, 0x96, 0x3c, 0x10, 0xaf, 0xb0, 0xcf, 0x94, 0x70, 0xff, 0x82, 0x82, + 0xee, 0x28, 0x2f, 0x57, 0x85, 0xab, 0xd2, 0x00, 0x54, 0xd9, 0xf1, 0x5c, 0x6b, 0x4a, 0x5a, 0xc0, 0x4a, 0x49, 0xdd, + 0xf9, 0x4d, 0x44, 0xdc, 0x92, 0xa9, 0x98, 0xad, 0xba, 0x51, 0xe5, 0xa1, 0x44, 0x91, 0x8e, 0x3d, 0xdb, 0x39, 0x58, + 0x03, 0xe0, 0x29, 0x6c, 0x2f, 0xce, 0xb0, 0xa0, 0x8c, 0xcb, 0x96, 0xb9, 0x04, 0x8a, 0xfa, 0x61, 0x9c, 0x97, 0x1d, + 0x5f, 0xee, 0x8e, 0xb6, 0xf7, 0xd0, 0x1b, 0xb1, 0x31, 0x5e, 0x5f, 0x46, 0x4d, 0xbf, 0x78, 0x86, 0x2b, 0x4b, 0x41, + 0x1e, 0x68, 0xaa, 0x47, 0x18, 0x1d, 0x02, 0xd3, 0x94, 0x1f, 0xb1, 0xf1, 0x74, 0x38, 0x34, 0x64, 0xd0, 0x6b, 0x26, + 0xc6, 0xff, 0xfa, 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, 0x58, 0x12, 0xa3, 0x10, 0xbf, 0x38, + 0x55, 0xb6, 0x13, 0x42, 0x05, 0xc4, 0x43, 0xd7, 0xba, 0x71, 0x24, 0x55, 0xec, 0x49, 0xa1, 0xf1, 0xd4, 0x70, 0xdf, + 0x0b, 0x1d, 0xb3, 0x0e, 0xb3, 0xb8, 0xcd, 0x1a, 0x49, 0x8d, 0x71, 0x2a, 0x4c, 0x70, 0x4a, 0xb9, 0x8a, 0x04, 0x46, + 0xc7, 0xb3, 0x85, 0x41, 0x54, 0x49, 0x4c, 0x32, 0xb6, 0x16, 0xc2, 0xc4, 0xae, 0x73, 0x85, 0x69, 0xea, 0x22, 0xf5, + 0x9b, 0x81, 0xc9, 0x82, 0x86, 0xfc, 0x1e, 0x8d, 0xd6, 0x54, 0x4d, 0x01, 0x86, 0x71, 0x94, 0x6a, 0xfc, 0x5b, 0x84, + 0xda, 0x0c, 0x03, 0x00, 0xdb, 0xbc, 0x93, 0x99, 0xa8, 0x5e, 0x0b, 0x84, 0x40, 0x73, 0xf6, 0x53, 0x45, 0xb5, 0x33, + 0x0b, 0x46, 0xd1, 0x6e, 0xaf, 0x7c, 0x3e, 0x70, 0x42, 0x79, 0xac, 0x2e, 0x50, 0xaf, 0x64, 0xf1, 0x46, 0xa6, 0xbc, + 0x15, 0x17, 0x73, 0x4f, 0xb2, 0x0f, 0xf9, 0x08, 0xce, 0x2b, 0x74, 0x2a, 0x37, 0xdb, 0x44, 0x99, 0x25, 0x49, 0xc6, + 0x02, 0x63, 0xf3, 0x12, 0xcc, 0xa4, 0x66, 0xc6, 0xf0, 0x6b, 0x08, 0x2e, 0xb6, 0x73, 0x12, 0x6e, 0xee, 0xe7, 0x81, + 0x21, 0x34, 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, 0xe1, 0xce, 0x7f, 0x50, 0x58, + 0x83, 0xca, 0x88, 0xcb, 0x88, 0xf2, 0xcc, 0x81, 0x6e, 0x9a, 0x14, 0x71, 0x7a, 0xb6, 0x8a, 0x8b, 0x92, 0xa7, 0x50, + 0xa9, 0xa6, 0x6e, 0x51, 0x6f, 0x02, 0xf6, 0x86, 0x48, 0x92, 0xac, 0xa5, 0xb1, 0x15, 0xbb, 0x34, 0x48, 0xcf, 0xbd, + 0x61, 0x96, 0x5e, 0x55, 0x68, 0x48, 0x4b, 0xbd, 0xb3, 0x50, 0xc9, 0xfc, 0x15, 0xff, 0x19, 0xd4, 0x0a, 0x74, 0xb4, + 0x49, 0x31, 0x9e, 0x03, 0x23, 0xbe, 0x1b, 0xc1, 0xea, 0x01, 0xe2, 0xa2, 0x09, 0x4a, 0xbd, 0x23, 0x76, 0xfc, 0xdc, + 0xe4, 0xe1, 0x5d, 0xc8, 0x39, 0x83, 0x4f, 0x1f, 0x66, 0x89, 0x5a, 0xeb, 0x48, 0x8c, 0xd4, 0x0c, 0xa0, 0xe9, 0xa0, + 0xcc, 0x79, 0x2c, 0x82, 0x59, 0xcf, 0x24, 0x46, 0x3d, 0xae, 0x7f, 0x81, 0x86, 0xda, 0x6f, 0x56, 0x96, 0x67, 0xd5, + 0xdd, 0x97, 0x70, 0x60, 0x53, 0x5b, 0x41, 0x8f, 0xd7, 0x95, 0xbc, 0xbc, 0x54, 0xdd, 0xf6, 0x0b, 0x31, 0x72, 0xba, + 0xc6, 0xb5, 0x74, 0x5e, 0x2d, 0x58, 0xaf, 0x3b, 0xdd, 0x2c, 0xee, 0x66, 0x19, 0x0d, 0x84, 0xb5, 0x9d, 0x4f, 0x34, + 0x7f, 0xd6, 0x6c, 0xbb, 0x8f, 0xb7, 0x20, 0x66, 0x01, 0x00, 0xa4, 0x07, 0x51, 0xb0, 0xcc, 0x52, 0x1e, 0x50, 0x79, + 0x1f, 0x47, 0x59, 0x28, 0xbd, 0x9c, 0x65, 0xfc, 0xb4, 0x69, 0xac, 0x75, 0x56, 0x28, 0x43, 0x6b, 0xa3, 0x3b, 0x5d, + 0x65, 0x88, 0xed, 0x27, 0x71, 0xb6, 0x00, 0xf7, 0xc7, 0x0c, 0x85, 0x86, 0xce, 0x32, 0xd2, 0x44, 0xc3, 0x77, 0xdd, + 0x33, 0xc8, 0x28, 0x4e, 0xd6, 0x79, 0x25, 0xdd, 0xe8, 0xb3, 0x36, 0x12, 0xe6, 0x1e, 0xa2, 0x5f, 0xc5, 0xe0, 0x51, + 0xee, 0xf3, 0xda, 0xe8, 0x64, 0x5a, 0x46, 0xda, 0x9d, 0x9f, 0xd4, 0xcb, 0x2c, 0xd5, 0x3a, 0x6c, 0x9f, 0x61, 0x6f, + 0x8d, 0x49, 0x6f, 0x42, 0x6a, 0x18, 0x89, 0xcf, 0x67, 0xd4, 0x08, 0x01, 0x6d, 0x39, 0xfe, 0x0e, 0x9f, 0x61, 0x68, + 0x0a, 0x2c, 0x55, 0xdc, 0xc2, 0x6e, 0xf8, 0x9a, 0x4f, 0x56, 0x2d, 0x00, 0x11, 0xac, 0x7c, 0xbd, 0x8b, 0x57, 0x42, + 0x7d, 0xa6, 0xcd, 0x00, 0x90, 0x05, 0xa5, 0xdc, 0xf1, 0x53, 0x2a, 0x1d, 0x2c, 0x51, 0xb4, 0xbd, 0x9c, 0xbe, 0xd1, + 0xb1, 0xf1, 0x43, 0x7a, 0x2e, 0x60, 0xbb, 0x90, 0xdf, 0xba, 0x57, 0x2f, 0x51, 0x91, 0xda, 0x36, 0xeb, 0x01, 0xbe, + 0xdc, 0xa0, 0x49, 0x18, 0x41, 0x99, 0x32, 0x05, 0x30, 0xb8, 0xa9, 0x46, 0xc1, 0xa4, 0xd5, 0x48, 0xd8, 0x52, 0x4f, + 0xb2, 0xdc, 0xf4, 0xc1, 0xa9, 0xee, 0x11, 0xf4, 0x68, 0x87, 0x93, 0x96, 0xfd, 0x5a, 0xc1, 0xd1, 0xc9, 0xd5, 0x10, + 0x35, 0xf3, 0x5e, 0xdb, 0x91, 0x21, 0xe5, 0x32, 0x0c, 0x04, 0x53, 0x8e, 0x79, 0x7a, 0x6c, 0x3d, 0x23, 0xa2, 0x07, + 0xce, 0x3e, 0xd3, 0xad, 0xba, 0x92, 0x80, 0xe8, 0xf8, 0xcd, 0xd3, 0xd7, 0x57, 0xf1, 0xa5, 0x41, 0x51, 0x6a, 0x58, + 0xc4, 0x28, 0xd3, 0xbe, 0x4a, 0xc2, 0xe0, 0xfd, 0xfa, 0xfe, 0x67, 0x95, 0xa5, 0xf6, 0x7b, 0xb0, 0xb1, 0xa2, 0xaa, + 0x5f, 0x4b, 0x5e, 0x34, 0x05, 0x58, 0xf7, 0x59, 0xa2, 0x40, 0xee, 0xf7, 0x36, 0xcd, 0x7c, 0x13, 0x35, 0x6e, 0x36, + 0xac, 0x37, 0xae, 0xdb, 0xa5, 0xb6, 0x64, 0x47, 0x56, 0x22, 0x67, 0x16, 0x83, 0x19, 0x3f, 0x2a, 0x0c, 0x4a, 0xc3, + 0x06, 0x55, 0xa9, 0xf8, 0xbd, 0x11, 0xc1, 0xa9, 0x63, 0x55, 0x61, 0x4c, 0x03, 0x66, 0x5b, 0x51, 0x6b, 0x50, 0x07, + 0xa5, 0xb4, 0x35, 0x51, 0xd8, 0x7e, 0x67, 0x05, 0x35, 0xbf, 0xff, 0x69, 0x0c, 0xf9, 0x9a, 0x52, 0x50, 0x49, 0xc0, + 0xce, 0xa0, 0xd1, 0x53, 0x25, 0x0c, 0xa4, 0x20, 0x78, 0x02, 0x94, 0x2f, 0xa2, 0xc6, 0x6a, 0xb7, 0xaf, 0x4e, 0x8d, + 0xd1, 0x16, 0x10, 0x5a, 0x48, 0x8f, 0x2e, 0xfb, 0xb8, 0x8d, 0x75, 0x20, 0xf1, 0xe0, 0x04, 0xdb, 0xb9, 0xba, 0x46, + 0x23, 0xa1, 0xf9, 0x43, 0xa3, 0x01, 0xaf, 0x69, 0x05, 0x0a, 0xf5, 0x1c, 0x47, 0x43, 0x67, 0x87, 0x14, 0x44, 0x6c, + 0xd0, 0xc2, 0xbe, 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, 0x82, 0x61, 0x0b, 0xbf, + 0x39, 0x35, 0x05, 0x60, 0xc3, 0x63, 0x5d, 0x96, 0x6f, 0xd4, 0x44, 0x66, 0x71, 0x48, 0x22, 0x90, 0x6c, 0x37, 0x37, + 0xb7, 0x11, 0x6c, 0x7b, 0x0b, 0xb5, 0xa1, 0xfe, 0xf2, 0xb6, 0xfb, 0x3d, 0xc3, 0xcb, 0x3d, 0xb9, 0x77, 0xd3, 0x86, + 0xf2, 0x87, 0xfb, 0x57, 0xc9, 0xff, 0x55, 0x25, 0xf7, 0x5b, 0x65, 0xd6, 0x6d, 0xf1, 0x7e, 0xd7, 0x71, 0xcb, 0x31, + 0x1a, 0x04, 0xd6, 0x14, 0x18, 0x48, 0x4f, 0x1a, 0xd3, 0x44, 0x87, 0x54, 0x66, 0xcc, 0xe0, 0xd1, 0x05, 0x68, 0x0e, + 0xd3, 0x79, 0x1e, 0x03, 0x70, 0x80, 0x7f, 0xe4, 0x11, 0xea, 0x9f, 0xce, 0xf3, 0xe0, 0x2c, 0x18, 0x94, 0x83, 0x40, + 0x7f, 0xe2, 0x9a, 0x13, 0x2c, 0x40, 0xe7, 0x16, 0x33, 0x08, 0x36, 0x69, 0xcd, 0x1c, 0xe2, 0xc3, 0x64, 0x3a, 0x18, + 0xc4, 0x64, 0x03, 0x20, 0x7d, 0xf1, 0xc2, 0x3a, 0x07, 0x15, 0x7a, 0x41, 0xb6, 0xea, 0x2e, 0x9a, 0x15, 0x7b, 0xd5, + 0x4e, 0xf3, 0x7e, 0x3f, 0x9f, 0x97, 0x83, 0xa0, 0x51, 0x61, 0x61, 0xbc, 0xff, 0x68, 0xf3, 0x4b, 0xa3, 0x93, 0x26, + 0x18, 0xa6, 0xf6, 0x18, 0xd5, 0x2b, 0x9e, 0x66, 0xb4, 0x71, 0x3b, 0x56, 0xca, 0x17, 0x10, 0xc5, 0x03, 0x43, 0xd6, + 0xca, 0xbb, 0x73, 0xf0, 0xba, 0xdc, 0x78, 0x73, 0x44, 0x01, 0x76, 0x53, 0x18, 0x27, 0x35, 0x17, 0x5d, 0xd4, 0xc4, + 0x33, 0xd8, 0xe9, 0xea, 0xad, 0x44, 0xab, 0xf1, 0x5e, 0xbc, 0x6b, 0x36, 0xfe, 0x56, 0xee, 0xe9, 0x32, 0xf7, 0x2e, + 0x00, 0x71, 0x76, 0x2f, 0xae, 0xf6, 0xb0, 0xd4, 0xbd, 0x60, 0x60, 0x91, 0x43, 0xda, 0xd5, 0xea, 0xa1, 0x88, 0xd4, + 0x79, 0x0c, 0x06, 0x4c, 0xa6, 0x21, 0x35, 0x99, 0xf6, 0x0a, 0x05, 0x69, 0x63, 0xad, 0x05, 0xb4, 0xe1, 0xb0, 0xd8, + 0xb1, 0x1b, 0x76, 0xa7, 0x5b, 0x87, 0x42, 0x09, 0xa3, 0x57, 0xd7, 0xcd, 0x43, 0xad, 0xe1, 0x89, 0xa0, 0x07, 0xd5, + 0x68, 0x3f, 0x3d, 0x94, 0x27, 0xed, 0xb1, 0x00, 0x17, 0x3d, 0x7c, 0xf9, 0x52, 0xe0, 0x45, 0x7b, 0x07, 0x79, 0xce, + 0x7c, 0xaa, 0x7c, 0x10, 0x1b, 0x6e, 0x19, 0x3e, 0xb4, 0x8f, 0x6f, 0x05, 0x32, 0xa9, 0x3b, 0x9a, 0xda, 0xda, 0x1d, + 0x8d, 0x63, 0x02, 0xfd, 0xa6, 0x1c, 0xa5, 0x4c, 0x4c, 0x2d, 0x4b, 0x76, 0xd4, 0xcb, 0x95, 0x37, 0x54, 0xca, 0x8e, + 0x96, 0x6d, 0xce, 0x2f, 0x6d, 0x24, 0xf4, 0xfb, 0xda, 0x1d, 0x08, 0xdf, 0xa8, 0xf5, 0x86, 0xbc, 0x6c, 0x88, 0x58, + 0x0e, 0x31, 0x03, 0xc7, 0x0b, 0xa9, 0x5c, 0xbb, 0x8b, 0xa6, 0xaa, 0x6e, 0x67, 0x2b, 0x17, 0xb4, 0xc4, 0x5b, 0x29, + 0xb0, 0x8a, 0xd4, 0xe9, 0xf5, 0x54, 0xe2, 0x7d, 0x1f, 0xc5, 0xf6, 0x23, 0x60, 0x1b, 0x1b, 0x47, 0x63, 0xe3, 0x16, + 0xb1, 0xc1, 0x57, 0x51, 0x45, 0x0b, 0x0e, 0x10, 0xdc, 0x6d, 0x49, 0x2d, 0xcd, 0x1c, 0xe2, 0xbe, 0xe2, 0x01, 0xda, + 0x77, 0x71, 0xc4, 0xa9, 0x00, 0xdb, 0xba, 0xd6, 0x39, 0xab, 0xe5, 0x80, 0xcd, 0x44, 0xcf, 0x3f, 0xad, 0x1a, 0x89, + 0x18, 0x56, 0xd9, 0x48, 0x59, 0xa1, 0x3d, 0x28, 0x5d, 0xc2, 0xc5, 0x17, 0xe0, 0x65, 0xfb, 0x7e, 0x65, 0xf7, 0xd9, + 0x12, 0xfb, 0x87, 0x79, 0xd5, 0x04, 0x8f, 0xbc, 0xc6, 0xdb, 0x7b, 0x98, 0xf8, 0x52, 0x29, 0x84, 0x57, 0x29, 0x0d, + 0x25, 0x00, 0x83, 0x24, 0xa8, 0xe1, 0x4a, 0xdb, 0x66, 0x90, 0xca, 0x18, 0x76, 0xb7, 0x7a, 0xab, 0xff, 0xd3, 0x2a, + 0x5c, 0x54, 0xb2, 0x18, 0x93, 0x40, 0xe7, 0x54, 0xcb, 0x4d, 0x4c, 0xc1, 0xb3, 0x5d, 0x72, 0x04, 0x0a, 0x3b, 0x01, + 0xdc, 0x50, 0xc2, 0x7e, 0xc5, 0xdb, 0x50, 0xce, 0x5e, 0x59, 0xc9, 0x93, 0xdb, 0x97, 0x54, 0xd0, 0x84, 0x4c, 0x85, + 0xdd, 0xbf, 0xad, 0x0d, 0xfb, 0x22, 0x94, 0x23, 0x29, 0x70, 0x71, 0xd0, 0x39, 0x80, 0xfd, 0x41, 0x2e, 0x63, 0xf3, + 0x99, 0xf4, 0xfb, 0xea, 0xfd, 0xf3, 0x3c, 0x4b, 0x3e, 0xee, 0xbc, 0x37, 0x3c, 0xcd, 0x92, 0x01, 0x95, 0x88, 0xa9, + 0x75, 0x55, 0x0c, 0x97, 0xda, 0xc5, 0xb8, 0x41, 0x32, 0xe2, 0x7b, 0xa9, 0x43, 0x8c, 0x18, 0x5f, 0x64, 0x87, 0xa4, + 0xe4, 0x74, 0x59, 0x77, 0xf6, 0x5c, 0x8b, 0x66, 0xd0, 0x18, 0x6e, 0xc7, 0x7b, 0x49, 0xaf, 0x00, 0x15, 0x15, 0xba, + 0x67, 0x81, 0x6b, 0x78, 0x73, 0x49, 0x34, 0xb6, 0xf4, 0xb4, 0x25, 0x1a, 0xb8, 0x57, 0x26, 0x24, 0xd5, 0xc6, 0x01, + 0x16, 0xb1, 0xae, 0x3f, 0x86, 0x12, 0x80, 0x5a, 0x0d, 0xd2, 0x2b, 0x7d, 0x45, 0xa8, 0x4a, 0x42, 0x30, 0x3a, 0x91, + 0xf0, 0x32, 0xa0, 0x71, 0x66, 0x12, 0x2d, 0x6c, 0x70, 0x40, 0x5f, 0x54, 0x26, 0xd1, 0xd8, 0x90, 0x07, 0xb4, 0xb2, + 0x69, 0x00, 0x83, 0x0f, 0x92, 0x24, 0xfa, 0x7a, 0x69, 0x92, 0x40, 0x50, 0x82, 0xf2, 0x0d, 0xfa, 0x4b, 0xe9, 0xf9, + 0x58, 0xfe, 0xcb, 0x3b, 0x94, 0x7e, 0x08, 0x25, 0xc8, 0x14, 0x75, 0xc5, 0x34, 0x63, 0x47, 0x59, 0xb7, 0x31, 0x89, + 0xe7, 0x69, 0x77, 0x5b, 0x28, 0x97, 0x2e, 0xf0, 0x2b, 0xcb, 0x10, 0xc7, 0xfa, 0x79, 0xbc, 0x62, 0xc7, 0x21, 0xd7, + 0x78, 0xe9, 0xcf, 0xe3, 0x15, 0xce, 0x10, 0xad, 0x5a, 0x09, 0x44, 0xf9, 0xaf, 0xda, 0xc0, 0x21, 0xee, 0x13, 0x0c, + 0x72, 0x51, 0x79, 0x0f, 0x04, 0xf2, 0xb6, 0x82, 0x88, 0x34, 0xb3, 0xeb, 0x30, 0x22, 0xd5, 0x4e, 0x92, 0xf9, 0xf2, + 0x47, 0x99, 0x09, 0xef, 0x1b, 0x78, 0x6c, 0x36, 0xcb, 0xa6, 0x98, 0x2f, 0x54, 0x30, 0x07, 0xf7, 0x89, 0x8a, 0x4b, + 0x51, 0xf9, 0x4f, 0xd8, 0x05, 0x2f, 0xc6, 0x83, 0xd7, 0x6b, 0x04, 0xd8, 0xaf, 0xfc, 0x27, 0x6f, 0xcc, 0xde, 0x5a, + 0x37, 0xbe, 0xcc, 0x44, 0x7c, 0xe0, 0xa3, 0x5b, 0xca, 0x47, 0x77, 0x5e, 0xa6, 0x3f, 0x1b, 0x50, 0x22, 0xa3, 0xb2, + 0xe2, 0xab, 0x15, 0x4f, 0x67, 0xb7, 0x49, 0x94, 0x8d, 0x2a, 0x2e, 0x60, 0x7a, 0xc1, 0xf1, 0x2e, 0x59, 0x9f, 0x67, + 0xc9, 0x6b, 0x88, 0x3d, 0xb0, 0x92, 0x0a, 0x8b, 0x1f, 0x96, 0x99, 0x5a, 0xcc, 0x42, 0x56, 0x52, 0xf0, 0x60, 0x76, + 0x9d, 0x44, 0x6f, 0x97, 0x1e, 0x92, 0x9a, 0x99, 0xb2, 0x4d, 0xed, 0x08, 0xb5, 0xf1, 0x75, 0xa4, 0x1b, 0x6d, 0x01, + 0x00, 0xf7, 0x6c, 0x91, 0x46, 0x92, 0x89, 0xe1, 0xa4, 0x66, 0xdc, 0xa4, 0x17, 0x98, 0x1a, 0xd7, 0xac, 0xa2, 0x89, + 0xb3, 0x90, 0x01, 0xbd, 0x3f, 0xe0, 0xe5, 0xe0, 0x73, 0x06, 0xf7, 0x1f, 0xb4, 0x06, 0x2e, 0x0f, 0x8b, 0x7e, 0x5f, + 0x1e, 0x16, 0xdb, 0x6d, 0x79, 0x14, 0xf7, 0xfb, 0xf2, 0x28, 0x36, 0xfc, 0x83, 0x52, 0x6c, 0x1b, 0x73, 0x83, 0x84, + 0xe6, 0x12, 0xa2, 0x16, 0x8d, 0xe0, 0x0f, 0xcd, 0x72, 0x2e, 0xa2, 0xfc, 0x30, 0xe9, 0xf7, 0x7b, 0xcb, 0x99, 0x18, + 0xe4, 0xc3, 0x24, 0xca, 0x87, 0x89, 0xe7, 0x84, 0xf8, 0x9b, 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, 0x5d, 0x84, 0x25, + 0x96, 0x42, 0x97, 0xec, 0xcf, 0x25, 0xf0, 0x44, 0x39, 0xaf, 0x36, 0xc0, 0xc0, 0x46, 0x78, 0xe7, 0x30, 0xe1, 0x24, + 0xd6, 0x35, 0xa0, 0x9d, 0x6e, 0x6a, 0x7a, 0x41, 0x57, 0xf4, 0x12, 0xf9, 0xd9, 0x0b, 0x30, 0x58, 0x3a, 0x64, 0xf9, + 0x74, 0x30, 0xb8, 0x20, 0x2b, 0x56, 0xce, 0xc3, 0x78, 0x10, 0xae, 0x67, 0xf9, 0xf0, 0x22, 0xba, 0x20, 0xe4, 0xab, + 0x62, 0x41, 0x7b, 0xab, 0x51, 0xf9, 0x31, 0x83, 0xe0, 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, 0x86, 0xe8, + 0xb6, 0xc7, 0x49, 0x02, 0x8e, 0xc9, 0xae, 0xf8, 0x68, 0xac, 0x0a, 0xef, 0xfa, 0x8e, 0xd0, 0x5e, 0x2f, 0x71, 0x83, + 0xf4, 0x5d, 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, 0xde, 0xc0, 0x81, 0x3d, 0x08, 0xf3, 0x59, 0x3c, 0x7c, 0x13, 0xbd, + 0x21, 0xe4, 0x2b, 0x49, 0xaf, 0xd5, 0xa5, 0x0c, 0xc2, 0x20, 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, 0xdd, 0x11, 0xb0, 0xf0, 0x1a, 0x4f, 0xd7, 0x87, + 0x2c, 0x9e, 0x0e, 0x06, 0x6b, 0xa4, 0xea, 0x2a, 0xf7, 0x9a, 0x2c, 0xe8, 0x05, 0x4e, 0x04, 0x01, 0x86, 0x3e, 0x13, + 0x6b, 0x43, 0xc3, 0xdf, 0x30, 0xf8, 0xf8, 0x8e, 0x5d, 0x8c, 0xee, 0xe8, 0x2d, 0x7b, 0xb3, 0x1d, 0x4f, 0x81, 0x99, + 0x5a, 0xcd, 0xc2, 0xbb, 0xc3, 0xcb, 0xd9, 0x25, 0xbb, 0x8b, 0xee, 0x8e, 0xa0, 0xa1, 0x57, 0xec, 0x0e, 0x01, 0x97, + 0xd2, 0xc7, 0xcb, 0xc1, 0x1b, 0xb2, 0x3f, 0x18, 0xa4, 0x24, 0x0a, 0xaf, 0x43, 0xaf, 0x95, 0x6f, 0xe8, 0x1d, 0xa1, + 0x2b, 0x76, 0x8b, 0xa3, 0x71, 0xc9, 0xf0, 0x83, 0x73, 0x76, 0x57, 0x5f, 0x87, 0xde, 0x6e, 0x4e, 0x44, 0x27, 0x88, + 0x11, 0xfa, 0x1a, 0x38, 0x9a, 0xe5, 0xc2, 0x4c, 0xc0, 0x93, 0xb9, 0xc8, 0x68, 0x51, 0x68, 0x06, 0xe2, 0xac, 0x04, + 0xc4, 0x92, 0xa8, 0xfb, 0xcd, 0x46, 0x67, 0xb0, 0x9c, 0xfb, 0xfd, 0x5e, 0x65, 0xe8, 0x01, 0x22, 0x67, 0x76, 0xd2, + 0x83, 0x9e, 0x4f, 0x0f, 0xf0, 0x13, 0xbd, 0x6a, 0x10, 0x27, 0xf3, 0xbb, 0x65, 0xf4, 0x9b, 0x47, 0x1f, 0x7e, 0xe8, + 0xa6, 0x3c, 0x22, 0xff, 0xf7, 0x29, 0x4f, 0x99, 0x47, 0x6f, 0x2a, 0x0f, 0x04, 0xcf, 0x5b, 0x93, 0x4a, 0x23, 0x51, + 0x8d, 0xce, 0x56, 0x31, 0x68, 0x23, 0x51, 0xdb, 0xa0, 0x9f, 0xd0, 0xc2, 0x0a, 0x22, 0xe4, 0x1c, 0xbc, 0x00, 0x83, + 0x54, 0x08, 0x95, 0xa3, 0x16, 0x25, 0x1a, 0x82, 0xe4, 0xb2, 0xe4, 0x2a, 0x7c, 0x0e, 0xa1, 0xea, 0xf4, 0x71, 0x26, + 0xc2, 0x86, 0x1e, 0x87, 0x3e, 0x00, 0xfc, 0xaf, 0x3b, 0xe4, 0xa2, 0xe4, 0x97, 0x78, 0x36, 0xb7, 0x09, 0x46, 0xc1, + 0x12, 0xd1, 0x0c, 0x6d, 0x83, 0xd8, 0x8f, 0x25, 0xc1, 0x7a, 0x24, 0x8d, 0x47, 0xa5, 0x39, 0x22, 0xfc, 0x28, 0x3e, + 0x8a, 0x9e, 0xc6, 0x86, 0x44, 0x72, 0x24, 0x91, 0x7c, 0x00, 0x84, 0x93, 0xa0, 0xbf, 0xb8, 0x6b, 0xb2, 0x6b, 0x21, + 0x31, 0xe8, 0x4f, 0x4b, 0xa6, 0x65, 0xf7, 0xaa, 0xc7, 0xbe, 0x22, 0xc8, 0x1d, 0xd3, 0x7f, 0x79, 0x7d, 0xf8, 0xe7, + 0x12, 0x67, 0xd0, 0x7a, 0xbe, 0xa8, 0xce, 0xcc, 0xbc, 0xc1, 0x8d, 0xbc, 0x2e, 0x6b, 0xd7, 0xe5, 0x0b, 0xbe, 0xc7, + 0x6f, 0x2b, 0x2e, 0xd2, 0x72, 0xef, 0x97, 0xaa, 0x8d, 0xe7, 0x54, 0xae, 0x57, 0x2e, 0xce, 0x8a, 0x32, 0x4e, 0xf5, + 0xa4, 0x2e, 0xc6, 0x1a, 0xb6, 0xe1, 0xf7, 0x88, 0xba, 0x92, 0x96, 0xa3, 0xa7, 0x94, 0xab, 0x66, 0xca, 0xc5, 0x3a, + 0xcf, 0x7f, 0xde, 0x49, 0xc5, 0x29, 0x6e, 0xa6, 0x20, 0x55, 0x6a, 0xb9, 0x80, 0xea, 0x39, 0x6a, 0xb9, 0x5b, 0x9a, + 0x1d, 0xe0, 0xdc, 0x36, 0xd5, 0xc7, 0xca, 0xec, 0xc2, 0x4b, 0x6e, 0xdc, 0x9f, 0x4c, 0x19, 0x16, 0x8c, 0x42, 0x9b, + 0x55, 0x57, 0xda, 0xbe, 0xd0, 0x3a, 0x0d, 0xc3, 0x95, 0x1f, 0x2f, 0x20, 0x5d, 0xc0, 0x38, 0x5e, 0x94, 0x4c, 0x8c, + 0xdb, 0xa3, 0xb7, 0x82, 0xf8, 0x92, 0xad, 0x40, 0xc0, 0x5c, 0xc3, 0xdb, 0x75, 0x1d, 0x6d, 0xf7, 0xc4, 0x29, 0xa3, + 0x72, 0x15, 0x8b, 0xef, 0xe3, 0x95, 0x81, 0x4c, 0x56, 0xc7, 0x63, 0x63, 0x4c, 0xa7, 0x3f, 0x25, 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, 0x9e, 0x31, 0x57, 0x08, 0x56, 0xaa, 0xec, 0xf6, + 0x9d, 0x1a, 0x53, 0x31, 0x83, 0x29, 0xb6, 0x9d, 0xc5, 0xa4, 0x5b, 0xf9, 0xa7, 0x9d, 0xfb, 0x65, 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, 0x59, 0x49, 0xbe, 0x2b, 0x8d, 0xb9, 0xf4, + 0xa9, 0xd2, 0xc4, 0x70, 0xb2, 0x18, 0x71, 0x91, 0x2e, 0xea, 0xcc, 0xae, 0x85, 0xcf, 0x78, 0x19, 0xce, 0xf9, 0xc2, + 0xe8, 0xa6, 0x74, 0xe9, 0x05, 0x8b, 0x75, 0xa7, 0x37, 0x2b, 0x8d, 0x95, 0x12, 0x71, 0x6b, 0x96, 0x09, 0x94, 0xa5, + 0xac, 0x95, 0xf0, 0xa6, 0x68, 0xd9, 0x4a, 0x1a, 0x79, 0xcf, 0x1c, 0xdc, 0xc7, 0x7e, 0x40, 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, 0x26, 0x56, 0x0a, 0xd8, 0x0b, 0xbc, 0xbc, 0xe1, 0x99, 0xaa, 0x69, 0xd9, 0xa5, 0xe2, 0x00, 0xe3, 0xf3, + 0x32, 0x0c, 0xcb, 0xe1, 0x05, 0x58, 0x4b, 0xec, 0x87, 0xab, 0x39, 0x5f, 0xa8, 0xdf, 0x10, 0x70, 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, 0x9e, 0xaa, 0x99, 0x69, 0xc9, 0x7f, 0x12, 0xb5, 0xa1, 0x89, + 0xbe, 0xc1, 0x2a, 0xf2, 0x87, 0xc7, 0x47, 0x97, 0x40, 0xc6, 0xce, 0xae, 0x64, 0xe6, 0x43, 0xdf, 0x47, 0x06, 0xf7, + 0xdc, 0x94, 0x33, 0xae, 0x82, 0x44, 0x19, 0xb8, 0x7b, 0x35, 0x4b, 0xc6, 0x5a, 0x84, 0xef, 0x1e, 0x15, 0x45, 0x9f, + 0x49, 0xd3, 0x80, 0xee, 0x23, 0xc1, 0x1c, 0xe8, 0xbd, 0x42, 0x87, 0xcb, 0x6a, 0x9b, 0x09, 0xf8, 0x8b, 0x04, 0xf9, + 0xad, 0xd0, 0xab, 0x1a, 0x83, 0x2a, 0xda, 0x45, 0x2c, 0xfd, 0xfb, 0x88, 0x1f, 0x65, 0xf3, 0x2f, 0x73, 0x8f, 0x57, + 0x12, 0x06, 0x3f, 0xa4, 0x66, 0x93, 0xcc, 0xdb, 0x2b, 0xf6, 0x3d, 0x74, 0xd4, 0xa3, 0xd6, 0x78, 0x5f, 0xbd, 0xe0, + 0x14, 0x62, 0x94, 0x50, 0x74, 0x12, 0x0c, 0xe0, 0x76, 0x09, 0x29, 0xee, 0x06, 0xbb, 0x69, 0x5e, 0xf3, 0xa2, 0xe0, + 0x7c, 0x5d, 0x55, 0x81, 0x1f, 0xd0, 0x70, 0xbe, 0xd8, 0x0d, 0x61, 0x38, 0xa6, 0xad, 0x6b, 0x18, 0x84, 0x19, 0xc3, + 0x48, 0x08, 0x5e, 0xff, 0xa2, 0x27, 0x34, 0x89, 0x57, 0xdf, 0xf1, 0x4f, 0x19, 0x2f, 0x14, 0x91, 0x06, 0x11, 0x52, + 0x37, 0xf1, 0x8d, 0x4c, 0x93, 0x02, 0x0a, 0x01, 0x46, 0x01, 0x95, 0xd8, 0xd0, 0x54, 0xfc, 0xad, 0x16, 0x1f, 0xfc, + 0xd4, 0x74, 0x3c, 0x1a, 0xd7, 0xad, 0xce, 0xa8, 0xa0, 0x33, 0xd0, 0xa3, 0x56, 0xd4, 0xd3, 0xa0, 0x95, 0x60, 0x1a, + 0x69, 0xde, 0xba, 0x87, 0xc0, 0x2b, 0xd3, 0xe2, 0x9d, 0x07, 0x74, 0x73, 0xe6, 0x83, 0x27, 0x8f, 0xe9, 0x99, 0x43, + 0x4f, 0xae, 0xd8, 0x51, 0xd5, 0x43, 0xed, 0xbd, 0x19, 0xa1, 0xa0, 0xdf, 0xc7, 0x14, 0xe8, 0x46, 0x50, 0x7b, 0x57, + 0xf7, 0x1f, 0xcb, 0x5d, 0x0e, 0xdf, 0x71, 0x96, 0x1b, 0xc0, 0x52, 0x91, 0xb5, 0x02, 0x8f, 0x02, 0xd4, 0xa5, 0x32, + 0x84, 0x2d, 0xe6, 0x70, 0xa8, 0xec, 0x56, 0xad, 0x86, 0x92, 0x1c, 0x96, 0x23, 0x70, 0x08, 0x5d, 0x97, 0x83, 0x72, + 0xb4, 0xcc, 0xaa, 0xf7, 0xf8, 0x5b, 0xb3, 0x0e, 0x49, 0x76, 0x1f, 0xeb, 0xc0, 0x2d, 0xeb, 0x30, 0xfd, 0x68, 0x90, + 0x02, 0xd0, 0x64, 0x23, 0x70, 0x09, 0xc0, 0x7b, 0xfb, 0x8f, 0x08, 0xb5, 0x32, 0xbd, 0x97, 0xb1, 0x50, 0xdf, 0x37, + 0x92, 0xa0, 0x84, 0x66, 0x42, 0xe5, 0x58, 0x0a, 0xde, 0x79, 0xa4, 0x73, 0x52, 0x67, 0xe2, 0x3d, 0x88, 0xd3, 0xc2, + 0x07, 0xf6, 0x16, 0x04, 0xe7, 0x2c, 0xe8, 0x1d, 0xde, 0x66, 0xb5, 0xd4, 0x46, 0x0f, 0x14, 0xc0, 0xef, 0x06, 0x77, + 0x08, 0xf2, 0xd5, 0x18, 0xae, 0x95, 0xbc, 0x09, 0xf9, 0xb0, 0xa0, 0x07, 0x64, 0x60, 0x9f, 0xc5, 0x30, 0xa6, 0x07, + 0xe4, 0xd0, 0x3e, 0x4b, 0x37, 0x80, 0x03, 0xa9, 0x47, 0x95, 0x1e, 0x40, 0x83, 0x7e, 0xb7, 0x2d, 0xb2, 0x24, 0xeb, + 0xc7, 0xd2, 0x28, 0x62, 0xa0, 0x4a, 0x10, 0x51, 0x8b, 0x7f, 0x3e, 0x98, 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, 0xbd, 0xc9, 0xe0, 0xc0, 0xc8, 0xf0, + 0xa5, 0xb7, 0x7f, 0xe1, 0x6b, 0x2d, 0xdd, 0x13, 0x83, 0x92, 0x3c, 0x3e, 0x50, 0xf4, 0xef, 0x5e, 0x59, 0xf9, 0xd4, + 0x4e, 0xff, 0x76, 0x6b, 0xd6, 0xe7, 0xe1, 0x68, 0xb2, 0xdd, 0xf6, 0xb4, 0x81, 0x2b, 0xd5, 0x2a, 0x04, 0xec, 0x42, + 0x49, 0xf6, 0x0f, 0x20, 0x2a, 0x42, 0x33, 0xee, 0x66, 0xd9, 0x90, 0xc8, 0xf8, 0x71, 0x3a, 0xcb, 0x86, 0x60, 0x87, + 0x7b, 0x51, 0x89, 0xcb, 0x51, 0x6b, 0x83, 0xd3, 0xb3, 0x24, 0x84, 0x50, 0x0e, 0x58, 0xd9, 0xad, 0xfa, 0x73, 0xa7, + 0xcc, 0x84, 0xd4, 0x64, 0x75, 0x3b, 0xa5, 0x7b, 0x98, 0xe6, 0x7b, 0x66, 0x04, 0x07, 0xdc, 0xdb, 0x5f, 0xf5, 0xc7, + 0x30, 0xc9, 0x34, 0x39, 0x45, 0xf2, 0x8b, 0xf4, 0x14, 0x92, 0x76, 0xe8, 0xa9, 0x22, 0x80, 0x13, 0x6a, 0x3f, 0x86, + 0xdf, 0x30, 0xee, 0xdf, 0x35, 0x5f, 0xbb, 0xa9, 0x88, 0x9e, 0x52, 0x2c, 0x53, 0x93, 0xd3, 0x24, 0x2b, 0x12, 0x88, + 0xda, 0xa8, 0x9a, 0x11, 0x3d, 0x71, 0x31, 0x1f, 0x15, 0xe1, 0xf3, 0x6a, 0xfd, 0x9f, 0x21, 0x7c, 0x46, 0xe1, 0x06, + 0x70, 0x79, 0xc5, 0xe5, 0x79, 0xf8, 0xec, 0x29, 0xdd, 0x9b, 0x7c, 0x73, 0x40, 0xf7, 0x0e, 0x9e, 0x3c, 0x23, 0x00, + 0x8b, 0x76, 0x79, 0x1e, 0x1e, 0x3c, 0x7b, 0x46, 0xf7, 0xbe, 0xfd, 0x96, 0xee, 0x4d, 0x9e, 0x1c, 0x34, 0xd2, 0x26, + 0xcf, 0xbe, 0xa5, 0x7b, 0xdf, 0x3c, 0x6d, 0xa4, 0x1d, 0x8c, 0x9f, 0xd1, 0xbd, 0xbf, 0x7f, 0x63, 0xd2, 0xfe, 0x06, + 0xd9, 0xbe, 0x3d, 0xc0, 0xff, 0x4c, 0xda, 0xe4, 0xd9, 0x13, 0xba, 0x37, 0x19, 0x43, 0x25, 0xcf, 0x5c, 0x25, 0xe3, + 0x09, 0x7c, 0xfc, 0x04, 0xfe, 0xfb, 0x1b, 0x09, 0x16, 0xb4, 0x92, 0x2c, 0x17, 0xa8, 0x3f, 0x43, 0x11, 0x27, 0xaa, + 0x26, 0x12, 0x1e, 0x62, 0x66, 0xf5, 0x4d, 0x1c, 0x06, 0xc4, 0xa5, 0x43, 0x41, 0x74, 0x6f, 0x3c, 0x7a, 0x46, 0x02, + 0x1f, 0x9e, 0xee, 0xc6, 0x07, 0x19, 0xcb, 0xc5, 0x3c, 0xfb, 0x2a, 0x37, 0xb1, 0x15, 0x3c, 0x00, 0xab, 0x8f, 0x7e, + 0xae, 0x4a, 0xce, 0xb3, 0xaf, 0x2a, 0xb9, 0x9b, 0xeb, 0xf7, 0x16, 0xa0, 0xbc, 0xbf, 0x6a, 0xd9, 0x4d, 0xa1, 0x42, + 0xa7, 0xb5, 0x46, 0x9f, 0x7d, 0xc4, 0xf4, 0xc1, 0xc0, 0xbb, 0x61, 0xff, 0xb4, 0x53, 0x4e, 0xeb, 0x1b, 0x8d, 0x42, + 0x8d, 0xca, 0x43, 0xc2, 0x8e, 0xa0, 0xe8, 0xc1, 0x00, 0x78, 0x02, 0x0f, 0xf7, 0xed, 0xdf, 0x2c, 0xe3, 0x63, 0x47, + 0x19, 0xbf, 0xa0, 0x0c, 0x01, 0x8d, 0x7a, 0x98, 0xdd, 0xf4, 0xb0, 0xd1, 0xad, 0x5e, 0xb2, 0x54, 0x27, 0x53, 0xd3, + 0x33, 0xd8, 0xd7, 0xba, 0x96, 0x7b, 0x46, 0x14, 0x2d, 0x2f, 0xf6, 0x52, 0x3e, 0xab, 0xd8, 0x4f, 0x4b, 0x54, 0x6f, + 0x45, 0x8d, 0x37, 0x32, 0x9b, 0x55, 0xec, 0x7b, 0xf3, 0x06, 0xb8, 0x19, 0xf6, 0xbb, 0x7a, 0xf2, 0x03, 0x67, 0x70, + 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, 0x5c, 0xd9, 0xff, 0x6a, 0xc8, 0x4b, 0x50, 0xb8, 0xd5, 0x2c, 0x6f, + 0xa7, 0x30, 0x84, 0x10, 0xfc, 0x71, 0xc9, 0x00, 0x70, 0x20, 0xc0, 0x60, 0xac, 0x65, 0x40, 0xcd, 0x96, 0x8f, 0x36, + 0x5c, 0xa9, 0x27, 0x81, 0x33, 0xb8, 0x90, 0x45, 0xc2, 0x4f, 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, 0xb0, 0x05, 0x91, 0x21, + 0x78, 0xb8, 0xfd, 0x6b, 0xa9, 0x02, 0x47, 0xf5, 0xfb, 0x5c, 0xfa, 0x6e, 0x4f, 0xc6, 0x8e, 0x1c, 0xa7, 0x7e, 0x2a, + 0x1c, 0xfc, 0x37, 0xa9, 0x6b, 0x63, 0xb9, 0x92, 0x32, 0xcb, 0xb2, 0xb0, 0xa3, 0x50, 0xcb, 0x3d, 0x2a, 0x0f, 0x92, + 0x2f, 0xe4, 0x10, 0xc9, 0x02, 0xa3, 0x50, 0x90, 0xe1, 0x84, 0x8a, 0xd1, 0x5a, 0x94, 0xcb, 0xec, 0xa2, 0x0a, 0x37, + 0x4a, 0xa1, 0xcc, 0x29, 0xfa, 0x76, 0x83, 0x03, 0x09, 0x89, 0xb2, 0xf2, 0x6d, 0xfc, 0x36, 0x44, 0xb0, 0x3a, 0xae, + 0x6d, 0xa1, 0xb8, 0xb7, 0x3f, 0x79, 0xda, 0xc5, 0x1f, 0x19, 0x17, 0x50, 0x17, 0x8b, 0x69, 0x38, 0xb1, 0xb1, 0x6f, + 0xdc, 0x17, 0x56, 0xd3, 0x03, 0x50, 0xdf, 0xa5, 0x12, 0x23, 0xa8, 0xaf, 0x8c, 0x7d, 0x6c, 0x8f, 0x31, 0x39, 0x83, + 0x58, 0xc3, 0x2a, 0x67, 0xa6, 0xfa, 0x46, 0xd8, 0x11, 0x00, 0x37, 0x42, 0x6b, 0x14, 0x04, 0x1e, 0xaf, 0x42, 0x3c, + 0x2f, 0x55, 0xf8, 0xd6, 0x8c, 0xd0, 0x31, 0x78, 0x53, 0xd9, 0x46, 0x66, 0xd2, 0x17, 0x0c, 0x9a, 0x63, 0x5b, 0x47, + 0x61, 0xb5, 0x95, 0x65, 0x47, 0x00, 0x37, 0x90, 0x1d, 0x9a, 0x8b, 0xe7, 0xac, 0x9a, 0x67, 0x8b, 0xc8, 0x04, 0x05, + 0x5c, 0x0a, 0xcb, 0xa0, 0x7d, 0xba, 0x47, 0xb6, 0xe3, 0x10, 0xba, 0xe1, 0x3e, 0x82, 0xf1, 0xb4, 0x9b, 0x82, 0x15, + 0x44, 0x23, 0xc4, 0xc3, 0x8c, 0x59, 0x7c, 0xaf, 0x34, 0xe5, 0xa9, 0x6a, 0x09, 0x04, 0x8e, 0x42, 0xa8, 0x8b, 0x5d, + 0xa3, 0x04, 0x97, 0xa9, 0x11, 0xcc, 0x60, 0xc7, 0x8e, 0xd4, 0x76, 0xc9, 0x39, 0x1d, 0xaa, 0x29, 0x2d, 0xf5, 0x94, + 0x6a, 0x5f, 0x43, 0x31, 0x2f, 0xd1, 0x43, 0x0f, 0x5c, 0x0f, 0xb4, 0x43, 0x5e, 0x49, 0x27, 0x26, 0x82, 0x4e, 0xab, + 0x4d, 0xd8, 0xb9, 0x91, 0x6e, 0x59, 0x8d, 0xbc, 0x63, 0x68, 0x76, 0xc4, 0x4b, 0x3f, 0x50, 0x17, 0x40, 0x84, 0xdc, + 0xdb, 0x22, 0x73, 0x44, 0xb3, 0xac, 0x7c, 0x05, 0x65, 0x71, 0xc4, 0xd6, 0x15, 0x70, 0x2d, 0x05, 0x93, 0x4b, 0x1e, + 0xf1, 0x14, 0x11, 0x01, 0x8f, 0x95, 0x76, 0x7d, 0xa7, 0x25, 0x84, 0x66, 0x29, 0x10, 0x37, 0x17, 0xc5, 0xb9, 0xb6, + 0x81, 0x2c, 0x80, 0xbe, 0xfd, 0x9c, 0x5d, 0x79, 0xe1, 0x60, 0x37, 0x57, 0x99, 0x78, 0xc1, 0x2f, 0x32, 0xc1, 0x53, + 0x04, 0xbb, 0xba, 0x35, 0x0f, 0xdc, 0xb1, 0x6d, 0x60, 0xf9, 0xf6, 0x1d, 0x2c, 0x98, 0x32, 0xd4, 0x4a, 0x89, 0x4c, + 0x44, 0x02, 0x32, 0xfb, 0xcc, 0xdd, 0x9b, 0x4c, 0xbc, 0x89, 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, 0x0e, 0xbf, 0xc4, 0x50, 0x2b, 0xe3, 0x7e, 0x1f, 0x24, 0x66, 0xd2, 0x36, 0x65, 0x26, 0x23, 0xa9, 0xd1, 0x42, + 0x2a, 0xca, 0x07, 0x13, 0xb2, 0xbb, 0x52, 0x2d, 0x23, 0x6a, 0xbf, 0x0a, 0xc5, 0x6c, 0x1c, 0x4d, 0x08, 0x9d, 0x74, + 0xac, 0x77, 0xd3, 0x5a, 0xc8, 0x34, 0x7a, 0x16, 0x79, 0x3e, 0x9d, 0x05, 0xab, 0xa6, 0xc5, 0x21, 0xe3, 0xd3, 0x62, + 0x30, 0x20, 0xda, 0xa5, 0x70, 0x83, 0xf5, 0x80, 0x29, 0x8d, 0x8b, 0xb7, 0x66, 0x5a, 0xfd, 0x4a, 0xaa, 0x90, 0xf4, + 0x9e, 0x01, 0x49, 0x26, 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, 0xde, 0xc6, 0x6f, 0x23, 0x7b, 0x59, 0xd0, 0x45, 0xbe, 0x40, 0x21, 0x6b, 0x1e, 0x86, 0xd5, 0xb0, 0x3d, + 0x88, 0x64, 0xbf, 0x3d, 0x09, 0x8d, 0xc6, 0xc0, 0x02, 0xd9, 0xa1, 0x11, 0xb8, 0x08, 0xad, 0xfc, 0xed, 0x10, 0x5c, + 0xb8, 0x2c, 0x22, 0xcb, 0x50, 0xc7, 0x6f, 0x6a, 0x37, 0x41, 0xf5, 0x0a, 0x9d, 0xa6, 0xb0, 0x2a, 0x65, 0x92, 0x0f, + 0xbf, 0x5e, 0xc9, 0x02, 0x33, 0x79, 0x5d, 0xf6, 0xe8, 0x6b, 0xbb, 0xbd, 0x03, 0x53, 0xb0, 0xee, 0x93, 0xf7, 0xf5, + 0xe3, 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, 0xa3, 0x4c, + 0xd6, 0xfe, 0xd5, 0x5d, 0xa4, 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, 0x86, 0x85, 0x57, 0xc3, + 0x4b, 0xb2, 0x1f, 0xa6, 0x83, 0x89, 0x12, 0x8c, 0xdd, 0xb1, 0x65, 0x19, 0xaa, 0xc4, 0xd5, 0xfe, 0x05, 0x79, 0x7c, + 0x41, 0x6f, 0xe9, 0x0d, 0x3d, 0xa5, 0x27, 0x40, 0xf8, 0xef, 0x0e, 0x27, 0x7c, 0x38, 0x79, 0xda, 0xef, 0xf7, 0xce, + 0xfb, 0xfd, 0xde, 0x99, 0x31, 0xa0, 0xd0, 0xbb, 0xe8, 0xb2, 0xa6, 0xfa, 0xd7, 0x55, 0xbd, 0x98, 0x9e, 0xa8, 0x8d, + 0x9b, 0xf0, 0x2c, 0x0f, 0xaf, 0xf6, 0xef, 0xc8, 0x10, 0x1f, 0x2f, 0x72, 0x29, 0x8b, 0xf0, 0x72, 0xff, 0x8e, 0xd0, + 0x93, 0x23, 0xd0, 0x9b, 0x62, 0x7d, 0x27, 0x8f, 0xef, 0x74, 0x6d, 0x84, 0xbe, 0x0c, 0x13, 0xd8, 0x26, 0xb7, 0xcc, + 0xde, 0xb5, 0x27, 0x63, 0x88, 0x65, 0x72, 0xe7, 0x95, 0x77, 0xf7, 0xf8, 0x96, 0xec, 0xdf, 0x82, 0xa7, 0xa8, 0x25, + 0x7f, 0xb3, 0xf0, 0x86, 0xb5, 0x6a, 0x78, 0x7c, 0x47, 0x4f, 0x5b, 0x8d, 0x78, 0x7c, 0x47, 0xa2, 0xf0, 0x86, 0x5d, + 0xd2, 0x53, 0x76, 0x45, 0xe8, 0x79, 0xbf, 0x7f, 0xd6, 0xef, 0xcb, 0x7e, 0xff, 0xa7, 0x38, 0x0c, 0xe3, 0x61, 0x41, + 0xf6, 0x25, 0xbd, 0xdb, 0x9f, 0xf0, 0x27, 0x64, 0x16, 0xea, 0xe6, 0xab, 0x05, 0x67, 0x55, 0xde, 0x2a, 0xd7, 0x1d, + 0x05, 0x6b, 0x85, 0x3b, 0xa6, 0x9e, 0x4e, 0xe8, 0x0d, 0x2b, 0xe8, 0x29, 0x8b, 0x49, 0x74, 0x0d, 0xad, 0x38, 0x9f, + 0x15, 0xd1, 0x0d, 0x3d, 0x65, 0x67, 0xb3, 0x38, 0x3a, 0xa5, 0x27, 0x2c, 0x1f, 0x4e, 0x20, 0xef, 0xe9, 0xf0, 0x86, + 0xec, 0x9f, 0x90, 0x28, 0x3c, 0xd1, 0xbf, 0xef, 0xe8, 0x25, 0x0f, 0x4f, 0xa8, 0x57, 0xcd, 0x09, 0x31, 0xd5, 0x37, + 0x6a, 0x3f, 0x21, 0x91, 0x3f, 0x98, 0x27, 0xd6, 0x9e, 0xe6, 0x91, 0xa3, 0x8d, 0x69, 0x19, 0x82, 0xbe, 0xb9, 0x0c, + 0x6f, 0x08, 0x99, 0x36, 0xc7, 0x0e, 0x06, 0x74, 0xf6, 0x28, 0x4a, 0x08, 0xbd, 0xf1, 0x4b, 0xbd, 0xc1, 0x31, 0x34, + 0x23, 0xa4, 0xd2, 0x4e, 0x31, 0x0d, 0xd7, 0xc1, 0x6b, 0x0d, 0xd6, 0x71, 0xde, 0xef, 0x87, 0xeb, 0x7e, 0x1f, 0x22, + 0xdd, 0x17, 0x33, 0x13, 0xdb, 0xcd, 0x91, 0x4d, 0x7a, 0x03, 0xda, 0xff, 0xd7, 0x83, 0x01, 0x74, 0xc6, 0x2b, 0x29, + 0xbc, 0x19, 0xbc, 0x7e, 0x7c, 0x47, 0x54, 0x1d, 0x05, 0x15, 0x32, 0x2c, 0xe8, 0x1b, 0x9a, 0x01, 0xe0, 0xd7, 0xeb, + 0xc1, 0x80, 0x44, 0xe6, 0x33, 0x32, 0x7d, 0x7d, 0x78, 0x32, 0x1d, 0x0c, 0x5e, 0x9b, 0x6d, 0xf2, 0x96, 0xdd, 0x53, + 0x0a, 0xac, 0xbf, 0xb3, 0x7e, 0xff, 0xed, 0x51, 0x4c, 0xce, 0x0b, 0x1e, 0x7f, 0x9c, 0x36, 0xdb, 0xf2, 0xd6, 0x45, + 0x55, 0x3b, 0xeb, 0xf7, 0xd7, 0xfd, 0xfe, 0x29, 0x60, 0x17, 0xcd, 0x9c, 0xaf, 0x27, 0x48, 0x5b, 0xe6, 0x8e, 0x22, + 0x69, 0x92, 0x43, 0x63, 0x68, 0x5b, 0xac, 0xda, 0x36, 0xeb, 0xc8, 0xc0, 0xe2, 0xa8, 0x59, 0x51, 0x5c, 0x93, 0x28, + 0xec, 0x9d, 0x6d, 0xb7, 0xa7, 0x8c, 0xb1, 0x98, 0x80, 0xf4, 0xc3, 0x7f, 0x7d, 0x5a, 0x37, 0x62, 0x88, 0x09, 0x89, + 0xcc, 0xe6, 0x66, 0x69, 0x0f, 0x81, 0x88, 0xc3, 0xa6, 0x7f, 0x6f, 0xee, 0xe5, 0xa2, 0x76, 0x7c, 0xeb, 0x2f, 0x00, + 0x42, 0x24, 0x59, 0xc8, 0x67, 0x38, 0x06, 0x65, 0x06, 0x40, 0xe6, 0x91, 0x9a, 0x79, 0x09, 0x20, 0xc0, 0x64, 0xbb, + 0x1d, 0x8d, 0xc7, 0x13, 0x5a, 0xb0, 0xd1, 0xdf, 0x9e, 0x3d, 0xae, 0x1e, 0x87, 0x41, 0x30, 0xc8, 0x48, 0x4b, 0x4f, + 0x61, 0x17, 0x6b, 0xb5, 0x0f, 0x46, 0xf0, 0x9a, 0x7d, 0xbc, 0xce, 0xbe, 0x98, 0x7d, 0x44, 0xc2, 0xda, 0x60, 0x1c, + 0xb9, 0x48, 0x5b, 0x7a, 0xbb, 0x7b, 0x18, 0x4c, 0x2e, 0xd2, 0xcf, 0xb0, 0x9d, 0x3e, 0xff, 0xe6, 0xc1, 0x78, 0xc2, + 0xc1, 0xe8, 0x2e, 0x0a, 0xfa, 0x4c, 0xdb, 0x6e, 0x2b, 0xff, 0x12, 0xf8, 0x16, 0x53, 0x41, 0xc7, 0x66, 0x59, 0xb8, + 0x41, 0x45, 0xd4, 0xd1, 0x32, 0xa8, 0x6a, 0x65, 0x3b, 0x07, 0xd4, 0x12, 0xab, 0x32, 0x71, 0x0b, 0x0c, 0x43, 0x86, + 0xba, 0xdc, 0xe3, 0xea, 0x5f, 0xbc, 0x90, 0x06, 0x3e, 0xc3, 0x89, 0x08, 0x3d, 0x6e, 0x8d, 0xfb, 0xdc, 0x9a, 0xf8, + 0x0c, 0xb7, 0x56, 0x22, 0x89, 0x35, 0xb0, 0xa4, 0xe6, 0x72, 0x94, 0xb0, 0xa3, 0x92, 0xf1, 0x59, 0x19, 0x25, 0x34, + 0x86, 0x07, 0xc9, 0xc4, 0x4c, 0x46, 0x09, 0xda, 0x27, 0xba, 0x08, 0x83, 0x7f, 0x01, 0x66, 0x3f, 0xcd, 0xe1, 0xaf, + 0x24, 0xd3, 0xe4, 0x10, 0x02, 0x42, 0x1c, 0x8e, 0x67, 0x71, 0x38, 0x26, 0x51, 0x72, 0x04, 0x4f, 0xf0, 0x5f, 0x11, + 0x8e, 0x49, 0xad, 0xef, 0x30, 0x52, 0x5d, 0x6e, 0x13, 0x06, 0x70, 0x65, 0xe3, 0xd9, 0x24, 0xb2, 0xd2, 0x5d, 0xf9, + 0x78, 0x34, 0x7e, 0x46, 0xa6, 0x71, 0x28, 0x07, 0x09, 0xa1, 0xe0, 0xdd, 0x1b, 0x96, 0xc3, 0x44, 0xc3, 0xb3, 0x01, + 0x9b, 0x57, 0x3a, 0x36, 0x4f, 0xc2, 0x09, 0x08, 0xc3, 0x84, 0x1c, 0xeb, 0x3d, 0x48, 0x29, 0xfa, 0x3c, 0xc7, 0x7e, + 0xea, 0x23, 0x08, 0xb3, 0xa3, 0x96, 0x8a, 0xaf, 0x00, 0xe8, 0x12, 0x07, 0x87, 0xda, 0x33, 0x5f, 0xcc, 0xc2, 0xd2, + 0xa3, 0x52, 0xa6, 0xba, 0x7d, 0xd1, 0xa0, 0xfc, 0xa6, 0x41, 0xfb, 0x82, 0x0c, 0x26, 0xb4, 0x3c, 0x9a, 0xf0, 0x27, + 0x10, 0xc0, 0xa3, 0x11, 0xf1, 0x4b, 0xe1, 0xc4, 0x40, 0x78, 0x15, 0x64, 0xa0, 0xd2, 0x5a, 0x35, 0x66, 0x64, 0x2b, + 0xde, 0x83, 0x30, 0x29, 0x7b, 0x37, 0x72, 0x9d, 0xa7, 0x10, 0x15, 0x6c, 0x9d, 0x57, 0x7b, 0x97, 0x60, 0xc9, 0x1e, + 0x57, 0x10, 0x27, 0x6c, 0xbd, 0x02, 0xec, 0xdc, 0x47, 0x9b, 0xb2, 0xde, 0x53, 0xdf, 0xed, 0x61, 0xcb, 0xe1, 0x55, + 0x25, 0xf7, 0x26, 0xe3, 0xf1, 0x78, 0xf4, 0x07, 0x1c, 0x1d, 0x40, 0x68, 0x49, 0x64, 0xf8, 0x64, 0x80, 0xc6, 0x5d, + 0x57, 0xdc, 0x1b, 0x17, 0x8a, 0xb2, 0xd2, 0xc9, 0x84, 0x80, 0xf8, 0xd9, 0xf4, 0x0d, 0xf6, 0x15, 0xd7, 0xf1, 0x4f, + 0x76, 0x3f, 0x31, 0x2b, 0x5a, 0xad, 0xd4, 0xd1, 0xbb, 0x93, 0xd3, 0xd7, 0x1f, 0x5e, 0xff, 0xf6, 0xf2, 0xec, 0xf5, + 0xdb, 0x57, 0xaf, 0xdf, 0xbe, 0xfe, 0xf0, 0xcf, 0x07, 0x18, 0x6c, 0xdf, 0x56, 0xc4, 0x8e, 0xbd, 0x77, 0x8f, 0xf1, + 0x6a, 0xf1, 0x85, 0xb3, 0x07, 0xee, 0x16, 0x0b, 0xb0, 0x09, 0x86, 0x5b, 0x10, 0x54, 0x33, 0x1a, 0x95, 0xbe, 0x27, + 0x20, 0xa3, 0x51, 0x21, 0x1b, 0x0f, 0x2b, 0xb6, 0x42, 0x2e, 0xde, 0x31, 0x1c, 0x7c, 0x64, 0x7f, 0x2b, 0xce, 0x84, + 0xdb, 0xd1, 0xd6, 0xac, 0x08, 0xf8, 0x7c, 0xad, 0x45, 0xe5, 0x71, 0x21, 0x6a, 0x6f, 0xdb, 0xe7, 0x90, 0x50, 0x8f, + 0xc8, 0x75, 0xf0, 0xbe, 0x0d, 0xb2, 0xc7, 0x47, 0xde, 0x93, 0xf2, 0x0c, 0xf5, 0x39, 0x1a, 0x3e, 0x6a, 0x3c, 0xa3, + 0x13, 0x73, 0x6d, 0x74, 0xa8, 0x67, 0x05, 0xec, 0x6f, 0x25, 0xc6, 0x86, 0x68, 0x0f, 0x29, 0x62, 0x7d, 0x38, 0xdd, + 0xef, 0xee, 0xcd, 0xe8, 0x7b, 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, 0xf7, 0x5c, 0x29, 0x9a, 0xb7, 0x2e, 0xb0, 0x07, 0x6a, 0x5e, 0xc7, 0x4b, 0x16, 0x02, 0x36, 0xe3, + 0xbe, 0x5d, 0x24, 0xce, 0xef, 0x9d, 0x4e, 0xc8, 0xfe, 0xc1, 0x94, 0x0f, 0x59, 0x49, 0xc5, 0x80, 0x95, 0xf5, 0x0e, + 0x35, 0xe7, 0x6d, 0x42, 0x2e, 0x76, 0x69, 0xb8, 0x18, 0xf2, 0x87, 0x2e, 0x49, 0x1f, 0x78, 0xc3, 0xa1, 0xda, 0x36, + 0x17, 0x43, 0x9a, 0x72, 0xba, 0x4b, 0x65, 0x40, 0x88, 0x74, 0x15, 0x57, 0xa4, 0xd6, 0x47, 0x55, 0xea, 0x24, 0x1d, + 0xd7, 0xd9, 0xe6, 0x33, 0x97, 0x6c, 0x75, 0xbb, 0xf6, 0xaf, 0xd5, 0xed, 0x0b, 0x33, 0x90, 0xbf, 0x3f, 0x11, 0xd5, + 0xc4, 0x40, 0x74, 0x01, 0x15, 0xfc, 0x13, 0xbc, 0x3c, 0x79, 0xa4, 0x15, 0xa0, 0xf7, 0x9d, 0x1d, 0x5d, 0x7b, 0xbc, + 0x31, 0x8b, 0xad, 0x25, 0xce, 0x59, 0xe5, 0x3b, 0xcb, 0xab, 0xb2, 0x15, 0xba, 0x8e, 0x60, 0xbf, 0x84, 0x1d, 0x7d, + 0xf7, 0xb6, 0x01, 0x10, 0xa5, 0xb0, 0x72, 0x67, 0xbf, 0xf0, 0xce, 0x7e, 0x61, 0xcf, 0x7e, 0xbb, 0x09, 0x94, 0x0f, + 0x2b, 0xb4, 0xec, 0x95, 0x14, 0x95, 0x69, 0xf2, 0xb8, 0xa9, 0xcb, 0x42, 0x5a, 0xcc, 0xf7, 0x2d, 0xed, 0x7a, 0x3a, + 0xa6, 0x12, 0xd5, 0x23, 0x3f, 0x60, 0xab, 0xf6, 0x4b, 0xf2, 0xf0, 0x3d, 0xf3, 0x7f, 0xf6, 0x06, 0x79, 0xdf, 0xdd, + 0xee, 0xff, 0xe6, 0x42, 0x07, 0xb7, 0xb5, 0x54, 0x78, 0xea, 0xea, 0xb8, 0xc0, 0xbb, 0x5a, 0xfa, 0xf0, 0x5d, 0xed, + 0x5d, 0xa6, 0x97, 0x5d, 0x05, 0xa8, 0x41, 0x62, 0x7d, 0xc5, 0x8b, 0x2c, 0xa9, 0xad, 0x42, 0xe3, 0x84, 0x43, 0x68, + 0x0f, 0xef, 0xe0, 0x02, 0x39, 0x2c, 0x21, 0xf4, 0x63, 0x65, 0x04, 0x80, 0x3e, 0x8b, 0x7d, 0xc2, 0xc3, 0x8c, 0x0c, + 0x7c, 0x89, 0x5f, 0x29, 0x7d, 0x71, 0xf1, 0xfe, 0x4e, 0x66, 0x82, 0x5e, 0x25, 0x36, 0xbb, 0x94, 0xed, 0x98, 0x1f, + 0xfe, 0x17, 0x18, 0x0d, 0xc2, 0x6b, 0x4b, 0xb6, 0x2f, 0x3a, 0x66, 0xb9, 0x82, 0xa3, 0xb6, 0x74, 0x65, 0x96, 0xad, + 0xeb, 0x67, 0x35, 0xcc, 0xf4, 0x99, 0x72, 0x02, 0xb2, 0x2f, 0xe4, 0xee, 0xa7, 0xba, 0x62, 0x41, 0x8e, 0x26, 0xe3, + 0x29, 0x11, 0x83, 0x41, 0x2b, 0xf9, 0x10, 0x93, 0x87, 0xc3, 0x1d, 0xe6, 0x52, 0xe8, 0x7e, 0x78, 0x7d, 0x80, 0xfa, + 0x1a, 0x5b, 0x92, 0x6c, 0x2a, 0xf6, 0x17, 0x98, 0xc5, 0x02, 0x71, 0x74, 0xf0, 0x8b, 0xf3, 0x05, 0x80, 0x2c, 0xc3, + 0x32, 0xd3, 0xc2, 0xa2, 0x32, 0x55, 0x3e, 0xb2, 0x05, 0x93, 0x87, 0xe3, 0x99, 0xdf, 0x73, 0xc7, 0xe0, 0x10, 0x12, + 0x4d, 0xac, 0xf1, 0x8b, 0x9f, 0x05, 0xe3, 0x38, 0x94, 0x47, 0xb2, 0xf1, 0x5d, 0x49, 0xa2, 0xb1, 0x31, 0x55, 0xd6, + 0x57, 0x89, 0x6a, 0x98, 0x90, 0xc7, 0x05, 0xd9, 0x2f, 0xe8, 0xd2, 0x1f, 0x4b, 0x4c, 0xdf, 0x8f, 0xf7, 0x27, 0x63, + 0xf2, 0x38, 0x7e, 0x3c, 0x31, 0x70, 0xc3, 0x7e, 0x8e, 0x7c, 0xb8, 0x24, 0xfb, 0xcd, 0x2a, 0xc1, 0x14, 0xd5, 0xf4, + 0xcc, 0xaf, 0x24, 0x19, 0x2c, 0x07, 0xe9, 0xe3, 0x56, 0x5e, 0xac, 0x55, 0x8f, 0xf7, 0xfa, 0x90, 0x4f, 0x89, 0x68, + 0xdc, 0x18, 0xd6, 0xf4, 0x2a, 0xfe, 0x53, 0x16, 0x51, 0x29, 0x01, 0x91, 0x10, 0xd4, 0xdb, 0xd9, 0x45, 0x96, 0xc4, + 0x22, 0x8d, 0xd2, 0x9a, 0xd0, 0xf4, 0x88, 0x4d, 0xc6, 0xb3, 0x94, 0xa5, 0x87, 0x93, 0x67, 0xb3, 0xc9, 0xb3, 0xe8, + 0x60, 0x1c, 0xa5, 0x83, 0x01, 0x24, 0x1f, 0x8c, 0xc1, 0xc5, 0x0e, 0x7e, 0xb3, 0x03, 0x18, 0xba, 0x23, 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, 0x0b, 0xf9, 0xff, 0xe3, 0x86, 0x71, 0xdf, 0x5d, 0xc2, 0x2c, + 0xae, 0xeb, 0x6c, 0xb4, 0x2a, 0x64, 0x25, 0xe1, 0x36, 0xa1, 0x44, 0x61, 0xa3, 0x78, 0xb5, 0xca, 0xb5, 0x8b, 0xd8, + 0xbc, 0xa2, 0x00, 0xee, 0x02, 0x71, 0x8a, 0x81, 0x85, 0x36, 0x06, 0x72, 0x9f, 0x78, 0x21, 0x99, 0x55, 0xfb, 0x98, + 0x7b, 0xe4, 0x9f, 0x21, 0x18, 0xa3, 0x8a, 0xa3, 0xf1, 0x4c, 0x61, 0x5d, 0x7c, 0x4e, 0xde, 0xfb, 0x6f, 0x1c, 0x45, + 0xf6, 0x68, 0x06, 0x3d, 0x41, 0xe4, 0x3c, 0xe2, 0xec, 0xc9, 0xe4, 0x65, 0xe0, 0x7e, 0x06, 0x2b, 0xfd, 0x75, 0xb7, + 0x19, 0x6b, 0xdb, 0xa3, 0x7b, 0x61, 0x84, 0xa2, 0x9f, 0xf0, 0x9d, 0xa9, 0x17, 0x70, 0x09, 0xd5, 0xc0, 0xae, 0x2f, + 0x2f, 0x79, 0x09, 0x20, 0x42, 0x99, 0xe8, 0xf7, 0x7b, 0x7f, 0x1a, 0x68, 0xd2, 0x92, 0x17, 0x6f, 0x32, 0x61, 0x9d, + 0x71, 0xa0, 0xa9, 0x40, 0xfd, 0x3f, 0x56, 0xf6, 0x99, 0x8e, 0xc9, 0xcc, 0x7f, 0x1c, 0x4e, 0x48, 0xd4, 0x7c, 0x4d, + 0x3e, 0x73, 0x9a, 0x7e, 0xe6, 0x8a, 0xf6, 0x1f, 0xc8, 0xcc, 0x0d, 0x87, 0x0c, 0xf5, 0x97, 0x8e, 0x79, 0x32, 0x7a, + 0x9d, 0x98, 0x1d, 0x09, 0x56, 0xcd, 0x20, 0x0a, 0x7b, 0x01, 0x0f, 0xea, 0x5a, 0x16, 0x4f, 0x61, 0xf6, 0x41, 0x8d, + 0x28, 0x0e, 0xd9, 0x78, 0x16, 0xca, 0x70, 0x02, 0xf6, 0xbd, 0x93, 0x31, 0xdc, 0x07, 0x64, 0xf8, 0xb1, 0x0a, 0xb1, + 0x73, 0x90, 0xf6, 0xb1, 0x42, 0xc5, 0x04, 0x40, 0x04, 0x42, 0xde, 0x7e, 0x5f, 0xaa, 0x24, 0x7c, 0x5d, 0x62, 0x4a, + 0xa1, 0x3e, 0xf8, 0x4f, 0xa4, 0xea, 0x8e, 0xe9, 0x57, 0xeb, 0xc7, 0x9f, 0x09, 0xc5, 0xa7, 0xbb, 0x94, 0xf8, 0x16, + 0x82, 0x3b, 0x4b, 0xd0, 0x41, 0x54, 0x68, 0xc6, 0xf6, 0x30, 0xbf, 0x2b, 0xee, 0xe7, 0x77, 0xc5, 0xff, 0x3b, 0x7e, + 0x57, 0x3c, 0xc4, 0x18, 0x56, 0x16, 0x1a, 0x7e, 0x16, 0x8c, 0x83, 0xe8, 0x3f, 0xe7, 0x13, 0xef, 0xe5, 0xa9, 0xaf, + 0x32, 0x31, 0xbd, 0x87, 0x69, 0xf6, 0x09, 0x0a, 0xc2, 0x2a, 0xee, 0xd2, 0x93, 0x75, 0x65, 0x6f, 0xad, 0x64, 0x88, + 0x79, 0x1e, 0x60, 0x8d, 0xc2, 0xca, 0x03, 0xba, 0x47, 0xd5, 0x06, 0x71, 0x22, 0x78, 0x18, 0x33, 0x2b, 0x7d, 0xdf, + 0x6e, 0x8d, 0x0a, 0xf3, 0x41, 0x2e, 0x0a, 0xb2, 0x9b, 0x8f, 0x67, 0xe3, 0x28, 0xc4, 0x06, 0xfc, 0xc7, 0x8c, 0x55, + 0x43, 0x36, 0xdf, 0xc9, 0x48, 0xed, 0x98, 0x3c, 0x4d, 0x76, 0x49, 0xef, 0x80, 0x77, 0xc8, 0xcf, 0xeb, 0x8f, 0x61, + 0x21, 0x0d, 0xbf, 0x25, 0x2f, 0xe3, 0x22, 0xab, 0x96, 0x57, 0x59, 0x82, 0x4c, 0x17, 0xbc, 0xf8, 0x62, 0xa6, 0xcb, + 0xfb, 0x58, 0x1f, 0x30, 0x9e, 0x52, 0xbc, 0x6e, 0x88, 0xd2, 0xd7, 0x2d, 0xcf, 0x0a, 0x75, 0x79, 0x52, 0x31, 0xdb, + 0xb3, 0x12, 0x9c, 0x4e, 0xc1, 0x04, 0x5f, 0xff, 0x74, 0xbd, 0x8f, 0x01, 0x17, 0x14, 0x6a, 0x4e, 0x0b, 0xb9, 0x32, + 0x58, 0x4e, 0x16, 0xba, 0x13, 0x30, 0x43, 0xa5, 0xc0, 0x0b, 0x14, 0xfc, 0x45, 0x03, 0x23, 0xfa, 0xca, 0xfd, 0x26, + 0x03, 0x83, 0x74, 0x69, 0x4e, 0x84, 0xb1, 0xe3, 0x76, 0x8a, 0xb4, 0x15, 0xe5, 0x8c, 0xb3, 0xf7, 0xea, 0x4a, 0x01, + 0x06, 0x78, 0x9b, 0x9b, 0xe8, 0x3c, 0x41, 0xaf, 0x05, 0xa5, 0xf3, 0x06, 0xee, 0x66, 0x19, 0x19, 0xe1, 0xe2, 0xe3, + 0xca, 0x63, 0xc1, 0x3d, 0xfb, 0x85, 0x58, 0x1a, 0xcd, 0x34, 0x18, 0xb3, 0x79, 0xc1, 0x02, 0x85, 0x0a, 0x14, 0x58, + 0xce, 0xb4, 0xa5, 0x69, 0x35, 0xe4, 0xfb, 0x07, 0x68, 0x6d, 0x5a, 0x0d, 0xf8, 0xfe, 0x41, 0x1d, 0x65, 0x87, 0x90, + 0xe5, 0xc8, 0xcf, 0xa0, 0x5e, 0xd7, 0x91, 0x49, 0x31, 0xd9, 0xfd, 0xfa, 0x52, 0x7f, 0x54, 0x37, 0xe0, 0xfa, 0x01, + 0x08, 0x60, 0x03, 0x70, 0x08, 0x54, 0x83, 0xa5, 0x11, 0xc1, 0xa2, 0x4c, 0xa1, 0x7d, 0x0d, 0xbd, 0x37, 0x1a, 0xfe, + 0x0b, 0xdc, 0x45, 0xe4, 0xca, 0xff, 0x04, 0x81, 0xbf, 0xa2, 0x4c, 0x2b, 0x53, 0xfc, 0x4f, 0xb4, 0x7a, 0x85, 0x72, + 0xd6, 0xb4, 0xe6, 0x83, 0x68, 0x4d, 0x84, 0x6a, 0xc6, 0x10, 0xfc, 0x5b, 0x59, 0xa6, 0x2d, 0x55, 0x95, 0xfa, 0xd0, + 0x78, 0xad, 0x15, 0xce, 0xf2, 0x71, 0xe4, 0xbd, 0xc6, 0xd0, 0xb1, 0x89, 0xb3, 0x94, 0x53, 0xa9, 0xb3, 0x4f, 0xfb, + 0x32, 0x72, 0x80, 0xd3, 0x09, 0x1b, 0x4f, 0x93, 0x43, 0x39, 0x4d, 0x1c, 0x64, 0x7e, 0xce, 0x30, 0xb2, 0xaa, 0x01, + 0x61, 0x51, 0x36, 0x94, 0xb6, 0x00, 0x93, 0x9c, 0x10, 0x32, 0xc5, 0x50, 0x14, 0xf9, 0x48, 0xf7, 0xc3, 0x7a, 0xb3, + 0xba, 0x2f, 0xde, 0x69, 0x80, 0xd3, 0x30, 0x81, 0x40, 0xe0, 0x45, 0x7c, 0x93, 0x89, 0x4b, 0xf0, 0x18, 0x1e, 0xc0, + 0x97, 0xe0, 0x26, 0x97, 0xb2, 0xdf, 0xab, 0x30, 0xc7, 0xb5, 0x05, 0x0c, 0x1a, 0xac, 0x1e, 0x44, 0x87, 0x4b, 0x69, + 0xb3, 0xab, 0x00, 0xb1, 0x31, 0x85, 0x58, 0x16, 0x6c, 0x6d, 0xd9, 0xb3, 0xef, 0x55, 0xd3, 0xd0, 0x3a, 0xe1, 0x58, + 0x5c, 0xe6, 0x10, 0x45, 0x65, 0x10, 0x83, 0x3b, 0x92, 0xc7, 0xe7, 0x3d, 0x12, 0xe1, 0x05, 0x01, 0xb7, 0xb2, 0x58, + 0x86, 0x2b, 0xba, 0x1c, 0xdd, 0xd2, 0xf5, 0xe8, 0x86, 0x8e, 0xe9, 0xe4, 0xef, 0x63, 0xb0, 0xc8, 0xd6, 0xa9, 0x77, + 0x74, 0x3d, 0x5a, 0xd2, 0x6f, 0xc7, 0xf4, 0xe0, 0x6f, 0x60, 0xc2, 0x87, 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, 0xae, 0xf8, 0x55, 0xc9, 0x52, + 0xd8, 0x16, 0xb0, 0x7c, 0x3d, 0xaf, 0xa8, 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, 0x8e, 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, 0xca, 0xd3, 0xf6, + 0x75, 0xb0, 0xb1, 0xaa, 0xe8, 0x86, 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, 0xbe, 0x87, 0x88, 0xca, 0x50, 0xde, 0xe0, 0x1f, 0x18, 0x3c, 0x99, 0xad, 0xd2, 0x30, + 0x19, 0xdd, 0xd1, 0x78, 0xb4, 0x44, 0x38, 0x18, 0xb6, 0x4e, 0x15, 0xde, 0xfa, 0x05, 0xa4, 0xdf, 0xd2, 0x78, 0x74, + 0x43, 0x53, 0x6b, 0x73, 0x6a, 0xa0, 0xae, 0x7a, 0x63, 0x7a, 0x1b, 0xc1, 0xeb, 0xbb, 0x68, 0x49, 0x61, 0x2b, 0x1d, + 0xe7, 0xd9, 0xa5, 0x88, 0x52, 0x8a, 0x08, 0x84, 0x6b, 0x44, 0x0e, 0x5c, 0x6a, 0xb4, 0xc1, 0xf5, 0x00, 0xca, 0xd0, + 0x70, 0x81, 0xcb, 0x41, 0x3c, 0x5a, 0x7a, 0x64, 0x6a, 0xa9, 0x2f, 0xb2, 0x08, 0x1f, 0xed, 0x6c, 0xb4, 0x14, 0xcf, + 0x88, 0x85, 0x71, 0x05, 0x43, 0xa8, 0x0b, 0x2b, 0x4d, 0x41, 0xd2, 0x05, 0x8e, 0xec, 0x85, 0x45, 0x15, 0x6e, 0xc0, + 0xb4, 0xe8, 0x0e, 0xcc, 0xa3, 0x40, 0xe1, 0xe0, 0x12, 0xa4, 0x9f, 0x50, 0xb6, 0x73, 0x94, 0x26, 0x87, 0x37, 0x41, + 0xe9, 0xce, 0x04, 0x21, 0xed, 0xea, 0x26, 0x5b, 0xd2, 0x37, 0xd8, 0xde, 0xa1, 0x53, 0x51, 0x41, 0xf5, 0xb9, 0x05, + 0x93, 0x25, 0x1b, 0x84, 0x2d, 0x61, 0x7a, 0xa6, 0xd7, 0x80, 0x3d, 0xbd, 0x7f, 0xb0, 0x33, 0xdf, 0xc5, 0xec, 0xd3, + 0x7e, 0x19, 0x8d, 0x95, 0x05, 0x6f, 0x6e, 0x89, 0xdd, 0x92, 0x8d, 0xa7, 0xcb, 0xc3, 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, + 0x96, 0x69, 0x98, 0xe2, 0x22, 0x30, 0x29, 0xfd, 0x7e, 0x98, 0xb3, 0x94, 0x78, 0xd0, 0xa1, 0xee, 0xd4, 0x4e, 0x7d, + 0x21, 0x08, 0xf0, 0x48, 0xea, 0x1c, 0x9b, 0xfc, 0x7d, 0x3c, 0x0b, 0xd4, 0x40, 0x04, 0x51, 0x76, 0x88, 0x8f, 0x18, + 0xb8, 0x28, 0xd2, 0x71, 0x3b, 0x5d, 0x11, 0x17, 0xbb, 0xc7, 0x2c, 0xc4, 0x49, 0xc2, 0x5c, 0xb3, 0x6c, 0xc8, 0xaa, + 0x08, 0x13, 0x74, 0x61, 0x60, 0x96, 0x37, 0x64, 0xd5, 0xfe, 0x01, 0x44, 0x6a, 0xb5, 0x65, 0xac, 0xba, 0xca, 0xf8, + 0x16, 0x80, 0xac, 0x19, 0x63, 0x07, 0x7f, 0x1b, 0xcf, 0xd4, 0x37, 0x51, 0xc8, 0x8f, 0x0e, 0xfe, 0x06, 0xc9, 0x87, + 0xdf, 0x22, 0x33, 0x07, 0xc9, 0x8d, 0x82, 0x2e, 0x9b, 0xb3, 0xae, 0xa1, 0x34, 0x71, 0xed, 0x95, 0x7a, 0xed, 0x49, + 0xb3, 0xf6, 0x0a, 0x74, 0xa7, 0x36, 0xbc, 0x87, 0xb2, 0x9d, 0x05, 0x13, 0x74, 0x34, 0xbb, 0x03, 0x1d, 0xbc, 0x53, + 0x04, 0xbd, 0x4c, 0x42, 0xe3, 0x11, 0xaa, 0x8c, 0x7a, 0x61, 0x47, 0x76, 0xb3, 0x2e, 0x99, 0x67, 0xc0, 0x1c, 0xdb, + 0x73, 0x48, 0x0c, 0x73, 0x75, 0x50, 0xa7, 0xac, 0x1c, 0xe6, 0x78, 0x00, 0xaf, 0x99, 0x1c, 0x8a, 0x41, 0xae, 0x51, + 0xbe, 0x2f, 0x58, 0x31, 0x2c, 0x07, 0xb9, 0xe6, 0x66, 0xa6, 0xcd, 0xd8, 0xb4, 0x89, 0x0e, 0xcf, 0xbc, 0x62, 0x47, + 0xab, 0x1e, 0xf0, 0xb1, 0xe0, 0xc9, 0xec, 0x7b, 0x3e, 0xbe, 0x01, 0x4e, 0x66, 0x73, 0x1b, 0x2d, 0xe9, 0x5d, 0x94, + 0xd2, 0x9b, 0x68, 0x4d, 0x97, 0xd1, 0x85, 0x31, 0x31, 0x4e, 0x6a, 0x38, 0x07, 0xa0, 0x55, 0x00, 0x89, 0xa7, 0x7e, + 0xbd, 0xe7, 0x49, 0x15, 0x2e, 0x69, 0x0a, 0x6e, 0xc3, 0xbe, 0x7d, 0xe6, 0x95, 0x2f, 0x91, 0xda, 0x20, 0xc6, 0x9a, + 0x35, 0x54, 0xdc, 0x78, 0xeb, 0x3e, 0x12, 0x35, 0xec, 0x5c, 0x17, 0x9b, 0xa8, 0x1a, 0x4e, 0xa6, 0x25, 0x20, 0xb6, + 0x96, 0xc3, 0xa1, 0x3b, 0x42, 0x76, 0x8f, 0x1f, 0x1d, 0xe8, 0xb9, 0x27, 0x2d, 0xb6, 0x6d, 0xcb, 0x1f, 0x18, 0xc2, + 0x94, 0x7e, 0xfe, 0xc8, 0x07, 0xc4, 0x8a, 0x4b, 0x38, 0x1b, 0x81, 0x3a, 0x5a, 0xa1, 0xd3, 0xef, 0x55, 0x58, 0xe8, + 0x03, 0x7c, 0x73, 0x1b, 0x25, 0xf4, 0x2e, 0xca, 0x3d, 0xb2, 0xb6, 0xac, 0x99, 0x9c, 0x9e, 0x65, 0x21, 0x6f, 0x1f, + 0xe8, 0xe5, 0x02, 0x40, 0xb4, 0x06, 0xb1, 0x2f, 0x75, 0x3d, 0x00, 0xa7, 0x21, 0x34, 0x09, 0x8d, 0xe0, 0xaa, 0x82, + 0x30, 0x02, 0xae, 0x24, 0xfc, 0x0d, 0x26, 0x2a, 0xf0, 0x05, 0xb8, 0xc8, 0xa4, 0x69, 0xce, 0x83, 0xda, 0x1f, 0xc9, + 0xd3, 0xa2, 0xed, 0xed, 0x0a, 0xa3, 0x09, 0xc6, 0x9e, 0x68, 0x9f, 0x47, 0xca, 0x51, 0x5c, 0x24, 0x61, 0x36, 0xba, + 0x55, 0xe7, 0x39, 0xcd, 0x46, 0x77, 0xfa, 0x57, 0x45, 0xc7, 0xf4, 0x3b, 0x1d, 0xd0, 0x46, 0x49, 0xdf, 0x3a, 0xce, + 0x06, 0xb4, 0x5e, 0x2c, 0x8d, 0xff, 0xb5, 0x1c, 0xdd, 0x52, 0x39, 0xba, 0xf3, 0x2d, 0xa9, 0x26, 0xd3, 0xe2, 0x50, + 0xa0, 0x21, 0x55, 0xe7, 0xf7, 0x05, 0xf0, 0x73, 0xa5, 0xf1, 0x9d, 0x36, 0xdf, 0x7b, 0xed, 0x3f, 0xef, 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, 0xcb, 0xed, 0x56, 0xc5, 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, 0x5c, 0xd7, 0xcf, 0xda, 0xd4, 0xe8, 0x15, 0x58, 0xf8, + 0x6e, 0x94, 0x79, 0x24, 0xb7, 0x08, 0xa9, 0x0a, 0xac, 0xd4, 0x2d, 0x24, 0x98, 0x7f, 0x25, 0x67, 0xab, 0x32, 0x5f, + 0x3d, 0xf2, 0xa0, 0x9c, 0x4d, 0x4f, 0x7f, 0x43, 0x82, 0x76, 0xd7, 0x91, 0xe6, 0xf1, 0x16, 0x1d, 0x3e, 0xbb, 0xd6, + 0x12, 0x73, 0x27, 0x51, 0xf1, 0x7c, 0x0a, 0xd8, 0xea, 0x45, 0x76, 0xa5, 0x7c, 0xac, 0x76, 0x71, 0xfc, 0xcc, 0xf9, + 0x13, 0x57, 0xe1, 0x5a, 0x34, 0x94, 0x20, 0xe0, 0xcd, 0x61, 0xec, 0x0a, 0x55, 0x40, 0x43, 0x73, 0x03, 0xc7, 0xb9, + 0x1a, 0x56, 0x9a, 0x80, 0x69, 0x29, 0x8f, 0x0e, 0x70, 0x68, 0xf2, 0xa8, 0xdd, 0x34, 0xac, 0x0c, 0x5d, 0x6b, 0xf4, + 0xb9, 0xad, 0x74, 0xc6, 0x9b, 0x0d, 0xdf, 0x3f, 0x18, 0x54, 0xf8, 0x93, 0x34, 0x47, 0xa3, 0x9d, 0x1b, 0xee, 0x34, + 0x02, 0x33, 0x57, 0x72, 0x45, 0x76, 0x47, 0xc9, 0xcb, 0xef, 0xe9, 0x85, 0x05, 0xf4, 0xe7, 0x3f, 0x17, 0x13, 0x4e, + 0x5a, 0x62, 0x42, 0xb4, 0x74, 0xd0, 0xa2, 0x83, 0x1d, 0xe5, 0x95, 0x7d, 0x89, 0x97, 0xce, 0xf1, 0xbf, 0xaf, 0xc7, + 0xda, 0x55, 0x20, 0xb4, 0x3a, 0xb9, 0xdf, 0x9e, 0x2c, 0x10, 0x35, 0xa0, 0x9a, 0x5d, 0x95, 0xa3, 0x4c, 0x3b, 0x2b, + 0xb2, 0x69, 0xc8, 0x5c, 0x77, 0xb3, 0x34, 0x6c, 0x26, 0x3b, 0x16, 0x96, 0x19, 0x06, 0x6b, 0xa7, 0x8a, 0x3e, 0x07, + 0x2d, 0x3f, 0x82, 0x17, 0x4d, 0xe5, 0x99, 0xcf, 0x66, 0x19, 0xf1, 0x02, 0x9d, 0x73, 0x2a, 0x16, 0x4d, 0xe9, 0x58, + 0xb9, 0xdd, 0x96, 0x68, 0x2c, 0x51, 0x46, 0x41, 0x50, 0xdb, 0x20, 0xec, 0xba, 0x74, 0x4f, 0xfa, 0xb4, 0x8b, 0x4f, + 0x2b, 0xd0, 0xf7, 0xf8, 0x3e, 0x03, 0x89, 0xa9, 0x27, 0x79, 0xa8, 0x1a, 0xcd, 0xd1, 0xc9, 0xb3, 0x38, 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, 0x07, 0xd4, 0xa9, 0x8b, 0x75, 0x1b, 0x50, 0xb2, 0xe4, 0xdd, 0x3a, 0x3d, 0xb1, 0xd2, 0x77, 0xfb, + 0xe1, 0xce, 0x3c, 0x6a, 0x76, 0x77, 0xbb, 0x9d, 0x90, 0xb6, 0x7d, 0x30, 0xde, 0x97, 0xb0, 0x10, 0xe7, 0x1d, 0xb6, + 0xf7, 0x7d, 0x58, 0x3d, 0xe6, 0x83, 0x5f, 0x70, 0x9c, 0x61, 0xf4, 0x33, 0x65, 0xe8, 0xf3, 0xaa, 0x90, 0x57, 0xaa, + 0x53, 0xbe, 0xd0, 0xad, 0x65, 0xea, 0xfd, 0x36, 0x7e, 0xdb, 0x0a, 0x10, 0xe3, 0x75, 0xc5, 0x4a, 0xf1, 0x86, 0x56, + 0x18, 0xd7, 0xc0, 0x6d, 0x72, 0xa8, 0xa5, 0x5a, 0x20, 0xea, 0xf2, 0x93, 0xc7, 0x3c, 0x32, 0xea, 0x4c, 0xf8, 0xee, + 0x31, 0xf7, 0xa5, 0x6b, 0xbb, 0x4d, 0xfc, 0x5c, 0xd3, 0xf6, 0x77, 0x07, 0xba, 0xa3, 0x75, 0x0f, 0x37, 0xcf, 0xe6, + 0xe7, 0x91, 0xf9, 0x62, 0x80, 0xcd, 0xda, 0x65, 0x5c, 0x76, 0x0c, 0xf7, 0xbd, 0xe9, 0xc1, 0x58, 0x40, 0x20, 0x31, + 0x43, 0x2f, 0x03, 0x17, 0xb8, 0xc0, 0x5d, 0x61, 0xc0, 0x10, 0xd7, 0xb4, 0xe4, 0x4c, 0x5b, 0xd9, 0xfa, 0xc8, 0xdb, + 0xa8, 0x10, 0xac, 0xeb, 0x8e, 0x9b, 0x24, 0x87, 0xe0, 0x84, 0x2d, 0xf7, 0xbe, 0xf6, 0xda, 0x19, 0xfe, 0x63, 0x20, + 0x9c, 0x5b, 0xa2, 0x67, 0xd4, 0xf6, 0x58, 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, 0xde, 0xbf, 0xe6, 0x38, 0x71, 0x96, 0xc2, 0xf6, 0xc3, 0x87, 0x0b, 0x76, 0x4d, 0x00, 0x83, 0x16, 0x93, 0x05, + 0x4a, 0x50, 0xc9, 0x5a, 0xd5, 0x6e, 0xa7, 0xc4, 0x2f, 0xf7, 0x8b, 0x2e, 0xb3, 0x9d, 0xc7, 0xaf, 0x9b, 0xb4, 0xcf, + 0x7c, 0x8e, 0x7e, 0x98, 0xdf, 0x59, 0x27, 0x25, 0x67, 0x18, 0xd7, 0xf2, 0xff, 0xab, 0xe8, 0x65, 0x91, 0xa5, 0xd1, + 0xc6, 0xf0, 0x60, 0x36, 0xd4, 0xa6, 0x0f, 0x8d, 0x51, 0xb9, 0x65, 0xa3, 0x88, 0x68, 0x75, 0x0b, 0x82, 0x19, 0xc5, + 0x7d, 0x89, 0x36, 0xaf, 0x54, 0x59, 0x78, 0x87, 0xcf, 0x6c, 0xf4, 0x86, 0xed, 0x09, 0xa1, 0x7c, 0xf7, 0xb4, 0x30, + 0xab, 0x96, 0x8a, 0x06, 0xdb, 0x25, 0xbc, 0x8b, 0x51, 0xa5, 0x9f, 0x30, 0xd9, 0xb2, 0x60, 0xaa, 0xff, 0xdf, 0x17, + 0x59, 0xda, 0xa6, 0xe8, 0xc0, 0x74, 0x36, 0x7d, 0x3a, 0xe9, 0x06, 0xd7, 0x19, 0xb0, 0x88, 0x60, 0x4b, 0x85, 0xe3, + 0x51, 0x6a, 0x37, 0x48, 0x98, 0x08, 0x6e, 0xa2, 0x5e, 0x76, 0xb4, 0x4c, 0xc9, 0xaa, 0x80, 0xe7, 0x57, 0xae, 0x32, + 0x1d, 0x47, 0x43, 0xbf, 0x7f, 0x95, 0x9a, 0xd0, 0xaf, 0xd4, 0x4b, 0x55, 0x9c, 0x87, 0x51, 0x75, 0xa8, 0x30, 0x46, + 0x4b, 0x9a, 0xc2, 0x31, 0x98, 0x5d, 0x84, 0x29, 0x5e, 0xce, 0x36, 0x09, 0xfb, 0x82, 0x81, 0x5c, 0x6a, 0x83, 0x7a, + 0x4d, 0x89, 0xd6, 0xac, 0xbd, 0x99, 0x53, 0x42, 0x2f, 0x58, 0xe9, 0xdf, 0x85, 0xd6, 0x20, 0x50, 0x94, 0xcd, 0x94, + 0xe9, 0xb9, 0x6e, 0xe7, 0x05, 0x4d, 0x68, 0x41, 0x57, 0xa4, 0x06, 0x7d, 0xaf, 0x93, 0xb3, 0xa3, 0x93, 0x9d, 0x99, + 0xf5, 0x98, 0x15, 0xc3, 0xc9, 0x34, 0x86, 0x6b, 0x5a, 0xec, 0xae, 0x69, 0xcb, 0xe6, 0x8d, 0xab, 0xb1, 0x71, 0x1a, + 0xb4, 0x0b, 0xa4, 0x6d, 0x9a, 0xdb, 0x4f, 0x3d, 0x6e, 0x7f, 0x5d, 0xb3, 0xe5, 0xb4, 0xb7, 0xde, 0x6e, 0x7b, 0x29, + 0xd8, 0x88, 0x7a, 0x7c, 0xfc, 0x5a, 0x49, 0xd7, 0x2d, 0x97, 0x9f, 0xc2, 0xb3, 0xc7, 0xd7, 0x2f, 0x7d, 0x70, 0x39, + 0x5a, 0xb5, 0xb9, 0xfb, 0xe5, 0x2e, 0xb2, 0xdc, 0x17, 0x0d, 0x2d, 0xd7, 0x33, 0xd4, 0x24, 0xcf, 0x46, 0x7b, 0x87, + 0x5a, 0xb0, 0x9c, 0x75, 0x13, 0x9e, 0x18, 0xec, 0xd8, 0xab, 0xc6, 0xe6, 0xa8, 0xcc, 0x25, 0xab, 0x41, 0x02, 0x7d, + 0x92, 0x67, 0x9a, 0xfe, 0x41, 0x86, 0xf9, 0xe8, 0x96, 0xe6, 0x80, 0x2b, 0x56, 0xd9, 0x4b, 0x06, 0xa9, 0xab, 0xf6, + 0x12, 0x57, 0xbe, 0xc2, 0x21, 0xd9, 0xe0, 0x93, 0x61, 0xaa, 0x3e, 0xbb, 0xe4, 0xc1, 0xff, 0xdb, 0xaa, 0x55, 0x7a, + 0x6e, 0x92, 0x1b, 0x8e, 0x7f, 0x9d, 0xb4, 0x7d, 0x4c, 0x0c, 0x12, 0xf0, 0xd4, 0x2e, 0x86, 0x6a, 0x54, 0x15, 0xb1, + 0x28, 0x73, 0x13, 0x73, 0xec, 0xde, 0xae, 0xa1, 0x83, 0x32, 0xf8, 0x75, 0xc3, 0x27, 0xe6, 0x0e, 0x6c, 0x05, 0x3a, + 0x3a, 0xd1, 0x5c, 0x86, 0x99, 0xb9, 0x0c, 0xd3, 0xae, 0xad, 0x02, 0xc3, 0xab, 0xb6, 0x4a, 0xa2, 0x5c, 0x8d, 0x7a, + 0xdc, 0xcc, 0x52, 0xb3, 0x17, 0x79, 0xf7, 0x9a, 0xf4, 0x24, 0xfe, 0x74, 0xe9, 0xc9, 0xeb, 0x61, 0x40, 0xe4, 0x97, + 0x2c, 0x0d, 0xd7, 0x28, 0x08, 0x4e, 0xad, 0x76, 0x20, 0xcd, 0x47, 0x80, 0xcc, 0x8f, 0xd3, 0xf0, 0x9d, 0x16, 0xe7, + 0x90, 0x8d, 0xd2, 0x38, 0xb1, 0xa5, 0x51, 0x0f, 0xc1, 0x9d, 0xf7, 0x8a, 0xc7, 0x10, 0xf8, 0xf0, 0x03, 0x6e, 0x06, + 0x15, 0xdd, 0x96, 0x98, 0x28, 0x6d, 0x1e, 0x75, 0xcb, 0x47, 0x0d, 0xa1, 0x92, 0x95, 0xe1, 0xc5, 0xd0, 0xde, 0x1d, + 0x81, 0x51, 0xe5, 0x04, 0x32, 0xc3, 0x62, 0xff, 0x60, 0x98, 0x2a, 0x41, 0xd1, 0x50, 0x0e, 0x97, 0x28, 0x07, 0xc4, + 0x24, 0x10, 0x18, 0x15, 0x83, 0x54, 0x57, 0xa6, 0x5e, 0x0c, 0x52, 0x7d, 0xab, 0x22, 0xf5, 0x59, 0x16, 0x56, 0x54, + 0xb7, 0x88, 0x8e, 0xe9, 0x50, 0xd2, 0xa5, 0xd9, 0xa9, 0xb9, 0x96, 0x5e, 0xa8, 0xe5, 0xf8, 0x5c, 0xa7, 0xc1, 0x28, + 0x9e, 0xba, 0x14, 0xfd, 0x56, 0xed, 0x67, 0xff, 0x2d, 0xa6, 0xd4, 0x88, 0x4d, 0xed, 0x2d, 0x62, 0x58, 0xb5, 0x1f, + 0xb2, 0x2a, 0x07, 0xed, 0x2e, 0x28, 0x1b, 0x2b, 0xe3, 0x3c, 0xdf, 0x08, 0x66, 0x0e, 0xda, 0xc6, 0xaa, 0xe9, 0x43, + 0x6f, 0xc4, 0xa8, 0xbd, 0x31, 0xd5, 0xb8, 0x27, 0xf0, 0xd3, 0x06, 0x4d, 0xf7, 0x22, 0xcf, 0x51, 0x8f, 0xbc, 0xfb, + 0x9f, 0x39, 0xb2, 0x33, 0xf9, 0x2c, 0x96, 0x49, 0xdd, 0x3e, 0x26, 0xc1, 0x42, 0xd5, 0x31, 0xba, 0x70, 0x23, 0x53, + 0xda, 0xcf, 0x9d, 0xe9, 0x47, 0x3c, 0x93, 0x87, 0xed, 0xd0, 0xa8, 0x2f, 0x0d, 0x6b, 0x49, 0x11, 0xf5, 0x05, 0xbd, + 0x35, 0xd5, 0xd1, 0x01, 0xf5, 0x3a, 0x02, 0xab, 0x2b, 0xda, 0xa0, 0x06, 0x60, 0x32, 0xae, 0x6d, 0x6d, 0x3e, 0x07, + 0x53, 0x5b, 0x55, 0xc1, 0x33, 0xba, 0x2b, 0x94, 0xee, 0x4d, 0xea, 0xba, 0x35, 0xc4, 0x16, 0x30, 0x20, 0x70, 0xa3, + 0xa7, 0xa6, 0x3f, 0x68, 0xa2, 0x02, 0xd0, 0xa0, 0x71, 0x3b, 0xd3, 0x39, 0x12, 0xfd, 0x4e, 0x6d, 0xda, 0x66, 0xaa, + 0x57, 0x95, 0x0f, 0xa0, 0xe2, 0xcf, 0xd2, 0xd9, 0x85, 0x19, 0xb1, 0x00, 0xc6, 0x3d, 0x70, 0xa6, 0x7a, 0xc7, 0x19, + 0x58, 0x4f, 0xe4, 0x79, 0x56, 0xf2, 0x44, 0x0a, 0x98, 0x11, 0x79, 0x75, 0x25, 0x05, 0x0c, 0x83, 0x1a, 0x00, 0xb4, + 0x68, 0x2e, 0xa3, 0x09, 0x7f, 0x52, 0xd3, 0xfb, 0xf2, 0xf0, 0x27, 0x3a, 0xd7, 0x37, 0xe3, 0x1a, 0x0c, 0x95, 0xd7, + 0x15, 0xdf, 0xc9, 0xf4, 0x0d, 0x7f, 0xea, 0x65, 0x5a, 0xca, 0x75, 0xb1, 0x93, 0xe5, 0xc9, 0x37, 0xfc, 0x99, 0xce, + 0x73, 0xf0, 0xb4, 0xa6, 0x69, 0x7c, 0xb7, 0x93, 0xe5, 0xef, 0xdf, 0x3c, 0xb5, 0x79, 0x9e, 0x8c, 0x6b, 0x7a, 0xc3, + 0xf9, 0x47, 0x97, 0x69, 0xa2, 0xab, 0x1a, 0x3f, 0xfd, 0xbb, 0xcd, 0xf5, 0xb4, 0xa6, 0x57, 0x52, 0x54, 0xcb, 0x9d, + 0xa2, 0x0e, 0xbe, 0x39, 0xf8, 0x3b, 0xff, 0xc6, 0x74, 0xef, 0xa0, 0xa6, 0x7f, 0xad, 0xe3, 0xa2, 0xe2, 0xc5, 0x4e, + 0x71, 0x7f, 0xfb, 0xfb, 0xdf, 0x9f, 0xda, 0x8c, 0x4f, 0x6b, 0x7a, 0xc7, 0xe3, 0x8e, 0xb6, 0x4f, 0x9e, 0x3d, 0xe5, + 0x7f, 0xab, 0x6b, 0xfa, 0x2b, 0xf3, 0x83, 0xa3, 0x1e, 0x67, 0x9e, 0x1e, 0x3e, 0x91, 0x4d, 0xd4, 0x80, 0xa1, 0x87, + 0x06, 0x90, 0x4b, 0xab, 0xa6, 0xb9, 0xc7, 0x2b, 0x17, 0xdc, 0xbe, 0xcf, 0xe2, 0x34, 0x5e, 0xc1, 0x41, 0xb0, 0x41, + 0xe3, 0xac, 0x02, 0x38, 0x55, 0xe0, 0x3d, 0xa3, 0x92, 0x66, 0xa5, 0xfc, 0x07, 0xe7, 0x1f, 0x61, 0xd0, 0x10, 0xd2, + 0x46, 0x45, 0x06, 0x3a, 0x59, 0xe9, 0xc8, 0x46, 0xe8, 0xbf, 0xd9, 0x8c, 0x83, 0xe3, 0xc3, 0xe8, 0xf5, 0xfb, 0x61, + 0xc1, 0x44, 0x58, 0x10, 0x42, 0xff, 0x0c, 0x0b, 0x70, 0x28, 0x29, 0x98, 0x97, 0xcf, 0xf8, 0x9e, 0x6b, 0xa3, 0xb0, + 0x10, 0x44, 0x77, 0x91, 0x7d, 0x40, 0xd5, 0xa3, 0xef, 0xd0, 0x0d, 0xf1, 0xb2, 0xc2, 0x82, 0xa1, 0x55, 0x0d, 0xcc, + 0x10, 0x14, 0xff, 0x86, 0x87, 0x12, 0x7c, 0xe2, 0x01, 0x3e, 0x7a, 0x4c, 0x66, 0x5c, 0x5d, 0x6b, 0x4f, 0x2e, 0xc2, + 0x82, 0x06, 0xba, 0xed, 0x10, 0x74, 0x20, 0xf2, 0x5f, 0x80, 0xa7, 0xc0, 0xc0, 0x87, 0x85, 0x5d, 0xca, 0x5d, 0x7f, + 0xf5, 0x5f, 0x0d, 0xeb, 0xe8, 0xc2, 0x8f, 0xfe, 0x6a, 0x5d, 0xd8, 0x33, 0x32, 0x95, 0x87, 0xe5, 0x70, 0x32, 0x1d, + 0x0c, 0xa4, 0x8b, 0xe3, 0x76, 0x9c, 0xcd, 0x7f, 0x9d, 0xcb, 0xc5, 0x02, 0x75, 0xdf, 0x38, 0xaf, 0x33, 0xfd, 0x37, + 0xd2, 0xce, 0x07, 0x6f, 0x8e, 0x7f, 0x3f, 0x3b, 0x3d, 0x7e, 0x05, 0xce, 0x07, 0x1f, 0x5e, 0x7e, 0xff, 0xf2, 0xbd, + 0x0a, 0xee, 0xae, 0xe6, 0xbc, 0xdf, 0x77, 0x52, 0x9f, 0x90, 0x0f, 0x2b, 0xb2, 0x1f, 0xc6, 0x8f, 0x0b, 0x65, 0xf4, + 0x40, 0x0e, 0x99, 0x85, 0x42, 0x86, 0x2a, 0x6a, 0xfb, 0xbb, 0x1c, 0x4e, 0x3c, 0x30, 0x8b, 0xbb, 0x86, 0x08, 0xd7, + 0x6f, 0xb9, 0x0d, 0xb2, 0x26, 0x8f, 0xbc, 0x7e, 0x70, 0x32, 0x95, 0x8e, 0x2d, 0x2c, 0x18, 0x94, 0x0d, 0x6d, 0x3a, + 0xce, 0xe6, 0xc5, 0xc2, 0xb6, 0xcb, 0x2d, 0x90, 0x51, 0x9a, 0x5d, 0x5c, 0x84, 0x0a, 0xba, 0xfa, 0x08, 0x34, 0x00, + 0xa6, 0x51, 0x85, 0x6b, 0x11, 0x9f, 0xf9, 0xe5, 0x47, 0x63, 0xaf, 0x79, 0xb7, 0xa8, 0x7b, 0x32, 0xcd, 0xaa, 0x1a, + 0x03, 0x3a, 0x98, 0x50, 0xee, 0x06, 0xdd, 0x04, 0x93, 0x51, 0x6d, 0xf9, 0x75, 0x5e, 0x2d, 0x4c, 0x73, 0xdc, 0x30, + 0x54, 0x5e, 0xc9, 0x6b, 0xd9, 0x40, 0x64, 0x20, 0x19, 0x86, 0x3d, 0x1a, 0xa3, 0x48, 0x7d, 0x6f, 0xd7, 0x3b, 0x7e, + 0x93, 0x4b, 0x88, 0xa6, 0x98, 0x81, 0x74, 0xfe, 0x58, 0x28, 0xe7, 0x72, 0xc9, 0xf8, 0x5c, 0x2c, 0x8e, 0xc0, 0xed, + 0x7c, 0x2e, 0x16, 0x11, 0x06, 0xe5, 0xcb, 0x20, 0x56, 0x09, 0xd8, 0xbd, 0x38, 0x08, 0xdf, 0x4e, 0x68, 0x03, 0xbb, + 0x81, 0x24, 0x1b, 0x94, 0x76, 0xa5, 0x21, 0xca, 0x9d, 0xf2, 0x68, 0x83, 0xc8, 0x43, 0xac, 0x9a, 0x57, 0x6d, 0x4f, + 0x36, 0x73, 0x31, 0xc1, 0x55, 0x16, 0x33, 0x39, 0x8d, 0x0f, 0x59, 0x31, 0x8d, 0xa1, 0x94, 0x38, 0x4d, 0xc3, 0x98, + 0x4e, 0xa8, 0x20, 0x24, 0x61, 0x7c, 0x1e, 0x2f, 0x68, 0x82, 0x52, 0x82, 0x10, 0x42, 0x7e, 0x8c, 0xd0, 0x36, 0x07, + 0x96, 0xbc, 0xdd, 0x7e, 0x9e, 0x7e, 0x6e, 0xc7, 0x70, 0x19, 0x15, 0xa1, 0x1b, 0x74, 0xd6, 0xf0, 0x6f, 0x44, 0x05, + 0x8d, 0xb1, 0x62, 0x08, 0x02, 0x5e, 0x60, 0x54, 0xc2, 0x82, 0xc4, 0xac, 0x82, 0x28, 0x02, 0xe5, 0x3c, 0x5e, 0xb0, + 0x82, 0x36, 0x6d, 0x4e, 0x63, 0x6d, 0x12, 0xd4, 0x73, 0x58, 0x6a, 0x7b, 0x52, 0xa9, 0x10, 0x7b, 0x7c, 0x26, 0xa2, + 0x6b, 0x6d, 0x68, 0x00, 0x28, 0x50, 0x4a, 0x2e, 0x7e, 0xf3, 0xe5, 0x1e, 0x6e, 0x0a, 0xfa, 0x9f, 0x6d, 0x4c, 0xb4, + 0xb3, 0x5c, 0x1d, 0x7a, 0xf3, 0x05, 0x8d, 0xf3, 0x1c, 0x42, 0xb1, 0x19, 0x04, 0x72, 0x91, 0x55, 0x10, 0xd1, 0xe2, + 0x2e, 0x30, 0x21, 0xe1, 0xa0, 0x4d, 0xbf, 0x42, 0x6a, 0x43, 0x4c, 0xae, 0x3c, 0x31, 0xb0, 0xdb, 0x2a, 0x41, 0xc0, + 0x91, 0x9e, 0x67, 0x9f, 0x9a, 0x18, 0x6b, 0x9a, 0x9a, 0x99, 0x78, 0x1b, 0x0a, 0xd1, 0xa0, 0x05, 0xd1, 0x0c, 0xde, + 0x3f, 0x57, 0x1c, 0xaf, 0x3a, 0xf0, 0x03, 0xde, 0xb9, 0x38, 0xf3, 0x6a, 0xe6, 0x11, 0x39, 0xf5, 0x51, 0x8e, 0xe8, + 0x97, 0x3c, 0xac, 0x46, 0x3a, 0x19, 0x63, 0x25, 0x71, 0xd0, 0xdb, 0x60, 0xc1, 0x9c, 0xd0, 0x15, 0x0f, 0x2d, 0x1f, + 0xff, 0x0a, 0x99, 0x8c, 0x92, 0x1a, 0x2b, 0xba, 0xd2, 0x62, 0xc4, 0x79, 0x0d, 0xb3, 0x34, 0x59, 0xd1, 0xc5, 0x42, + 0x93, 0x66, 0xa1, 0x4c, 0x03, 0x7c, 0x02, 0x2d, 0x46, 0xee, 0xa1, 0xa6, 0x0d, 0x84, 0x86, 0xdd, 0x21, 0xe0, 0x23, + 0xf7, 0xd0, 0xe1, 0xff, 0xe7, 0xd9, 0x05, 0x22, 0xed, 0xcd, 0x4d, 0x64, 0x3c, 0x52, 0x37, 0x70, 0x50, 0x8c, 0x8f, + 0x7d, 0x33, 0xf1, 0x0b, 0x67, 0xf4, 0x21, 0xa9, 0x7c, 0x87, 0x0f, 0x96, 0x3f, 0xde, 0xd4, 0xcc, 0xca, 0x08, 0xd6, + 0xc3, 0x76, 0x8b, 0x0b, 0xa2, 0xed, 0x02, 0x48, 0x3d, 0xe3, 0xd5, 0xc2, 0x37, 0x5e, 0x8d, 0xef, 0x31, 0x5e, 0x75, + 0x67, 0x6a, 0x98, 0x93, 0x0d, 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, 0x6e, + 0xb7, 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, 0x5f, 0xc4, 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, 0x21, 0xbb, 0xe2, 0x65, 0x15, 0x5f, 0xad, 0x8c, 0x25, 0x31, + 0x67, 0xf7, 0xb9, 0xed, 0x51, 0x61, 0x5e, 0xbd, 0x7d, 0xf9, 0xfd, 0x71, 0xe3, 0xd5, 0x2e, 0xe2, 0x68, 0x08, 0xb6, + 0x15, 0x63, 0x8c, 0xde, 0xe2, 0xd3, 0x60, 0xa2, 0x5c, 0x23, 0xd0, 0xbb, 0x14, 0xf4, 0xdb, 0x5f, 0xea, 0x09, 0x78, + 0xc5, 0xf5, 0xf2, 0x4b, 0x3e, 0x02, 0x96, 0xa8, 0xd0, 0xb3, 0xc2, 0xdc, 0xac, 0xcc, 0xee, 0xed, 0x56, 0x64, 0xa6, + 0x5d, 0x69, 0x64, 0x20, 0x5e, 0x6d, 0x87, 0xb1, 0x70, 0xe9, 0x9a, 0x6e, 0x07, 0xbb, 0x5a, 0x7a, 0x96, 0xc8, 0xdb, + 0x6d, 0x09, 0x1d, 0xb2, 0x03, 0xee, 0xbd, 0x8c, 0x6f, 0xe1, 0x65, 0xe9, 0x75, 0xb3, 0x19, 0x3c, 0x01, 0xcc, 0x84, + 0x0b, 0x67, 0x59, 0x1c, 0x33, 0x9e, 0x84, 0x2a, 0x36, 0x57, 0x43, 0xe4, 0xad, 0x08, 0xad, 0xd9, 0x5f, 0xa1, 0x18, + 0x81, 0xdd, 0xc9, 0xe9, 0xc7, 0x6c, 0x35, 0x5b, 0x02, 0x6a, 0xfe, 0x55, 0x26, 0x80, 0xe6, 0xda, 0xb5, 0x60, 0x9b, + 0x42, 0x9b, 0xeb, 0xfa, 0x79, 0xbc, 0x8a, 0x13, 0x50, 0xdd, 0x80, 0xb7, 0xc8, 0x9d, 0x16, 0x5d, 0x19, 0x74, 0x51, + 0xfa, 0x40, 0x39, 0x96, 0x14, 0x3a, 0xfa, 0xde, 0x13, 0xea, 0xdc, 0x33, 0x80, 0x4b, 0x1a, 0x35, 0x4f, 0xb5, 0x94, + 0xb1, 0x00, 0x58, 0xe8, 0x60, 0xa6, 0xc8, 0x56, 0x74, 0x6b, 0x30, 0x29, 0xe0, 0xad, 0x01, 0xfe, 0x10, 0x59, 0xa5, + 0xee, 0x8a, 0x65, 0x58, 0x7a, 0xf6, 0xd7, 0xfd, 0x7e, 0xec, 0xd9, 0x5f, 0x5f, 0x68, 0x5a, 0x17, 0xb7, 0x1b, 0x40, + 0x6a, 0x0c, 0x20, 0x72, 0xac, 0x07, 0xc2, 0x44, 0x14, 0x6b, 0xfa, 0xfe, 0x1d, 0x9b, 0x2c, 0x0a, 0x84, 0x7e, 0xa7, + 0x5e, 0x4f, 0x4a, 0x02, 0x3a, 0xb5, 0x8a, 0x1d, 0x0d, 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, + 0xfb, 0xbf, 0x99, 0x2c, 0x08, 0x6a, 0xae, 0xfc, 0x40, 0x8e, 0x3b, 0x99, 0x1a, 0x7b, 0xaa, 0x51, 0x83, 0x60, 0x32, + 0x82, 0xc0, 0x70, 0xc3, 0x2f, 0xf8, 0xf8, 0x60, 0x41, 0x40, 0x45, 0x66, 0xcd, 0x42, 0xcc, 0x8b, 0xc3, 0x27, 0x80, + 0x1a, 0x33, 0x3a, 0x78, 0x06, 0xa0, 0xb0, 0x10, 0x10, 0x7d, 0x0c, 0x32, 0x5a, 0x01, 0xbf, 0x85, 0xfa, 0xdd, 0x3a, + 0xf1, 0x7d, 0xe8, 0x57, 0x41, 0x2f, 0x62, 0x60, 0x38, 0xa2, 0xc9, 0x7e, 0xc8, 0x07, 0x93, 0x01, 0x68, 0x4b, 0xbc, + 0xdd, 0xd7, 0xd2, 0x8a, 0x9b, 0xd3, 0xa5, 0xd3, 0xfd, 0x93, 0x36, 0x41, 0x12, 0xa9, 0x64, 0xa5, 0x22, 0x06, 0x10, + 0xca, 0x52, 0x6d, 0x93, 0x25, 0x58, 0x56, 0x98, 0x25, 0xcd, 0x0d, 0x4a, 0xe2, 0xee, 0x66, 0xe0, 0x18, 0x35, 0xeb, + 0x38, 0x2c, 0x5b, 0x6e, 0xd4, 0x00, 0x9f, 0x93, 0xb0, 0xc2, 0xde, 0x70, 0x66, 0xd2, 0x3b, 0xd3, 0xe1, 0xea, 0x98, + 0xb3, 0x37, 0x1c, 0xc1, 0x38, 0x12, 0xbc, 0xf1, 0xd0, 0x25, 0xd3, 0x50, 0x91, 0x29, 0xe3, 0x60, 0xda, 0x03, 0xdc, + 0x7b, 0x0e, 0xc6, 0x61, 0x6c, 0x50, 0x59, 0x52, 0x9f, 0x7a, 0x77, 0x21, 0x10, 0xa4, 0xb5, 0x5e, 0xe6, 0x33, 0x3c, + 0x3d, 0x23, 0x94, 0xfd, 0x21, 0x87, 0x2f, 0xc0, 0x8e, 0x82, 0x1c, 0x4d, 0xf8, 0xb3, 0xc7, 0xbb, 0x81, 0xaa, 0xf8, + 0x20, 0xd8, 0x8b, 0x45, 0xba, 0x17, 0x0c, 0x04, 0xfc, 0x2a, 0xf8, 0x5e, 0x25, 0xe5, 0xde, 0x45, 0x5c, 0xec, 0xc5, + 0xab, 0xb8, 0xa8, 0xf6, 0x6e, 0xb2, 0x6a, 0xb9, 0x67, 0x3a, 0x04, 0xd0, 0xbc, 0xc1, 0x20, 0x1e, 0x04, 0x7b, 0xc1, + 0xa0, 0x30, 0x53, 0xbb, 0x62, 0x65, 0xe3, 0x38, 0x33, 0x21, 0xca, 0x82, 0x66, 0x80, 0xb0, 0xc6, 0x69, 0x00, 0x7c, + 0xea, 0x9a, 0xa5, 0xf4, 0x02, 0xc3, 0x0d, 0x88, 0xe9, 0x1a, 0xfa, 0x00, 0x3c, 0xf2, 0x9a, 0xc6, 0xb0, 0x04, 0x2e, + 0x06, 0x03, 0xb2, 0x86, 0xc8, 0x05, 0x6b, 0x6a, 0x83, 0x38, 0x84, 0x6b, 0x65, 0xa7, 0xbd, 0x0b, 0xcc, 0xb4, 0xdd, + 0x02, 0xa2, 0xf2, 0x84, 0xf4, 0xfb, 0xf6, 0x1b, 0xea, 0x5f, 0xb0, 0x97, 0x60, 0x7f, 0x55, 0x54, 0x61, 0x22, 0x95, + 0xe6, 0xfb, 0x92, 0x1d, 0x0d, 0x54, 0xc4, 0xe1, 0x1d, 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, 0xaf, 0x34, 0xbb, 0xf4, 0x30, 0x90, 0x32, + 0x6e, 0x0f, 0x2d, 0x61, 0xd2, 0xf2, 0x22, 0xbc, 0xf7, 0x9a, 0x9b, 0xdc, 0x8b, 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, 0xcf, 0x74, 0x17, 0x80, 0xd1, 0x2f, 0x66, 0x69, 0xb4, 0xbc, 0xd7, 0xcc, 0x02, 0xc9, 0x33, 0xf4, 0x5d, + 0x07, 0xdb, 0x1b, 0xfb, 0x20, 0xe5, 0xfc, 0x50, 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, 0x3f, 0x91, 0x6f, 0x72, 0x07, 0x5d, 0x2e, 0xc7, + 0x9a, 0xb7, 0x1c, 0x80, 0x8a, 0x7e, 0xa4, 0xa8, 0xee, 0x17, 0x38, 0xc2, 0x3c, 0x58, 0xb7, 0xf9, 0x64, 0xdf, 0x14, + 0x38, 0x44, 0x9e, 0xb4, 0xd1, 0x14, 0xd0, 0xbd, 0x8b, 0xc7, 0x5d, 0xfd, 0xb6, 0x74, 0x17, 0x28, 0xd1, 0x4e, 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, + 0xeb, 0x33, 0x8e, 0xa2, 0x1f, 0xa3, 0x46, 0xbe, 0x89, 0xc4, 0x63, 0x39, 0x88, 0x1f, 0x17, 0x74, 0x19, 0x89, 0xc7, + 0xc5, 0x20, 0x7e, 0x2c, 0xeb, 0x7a, 0xf7, 0x5c, 0xb9, 0xbf, 0x8f, 0xc8, 0xb3, 0xee, 0xec, 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, 0xfd, 0x62, 0x74, 0xe3, 0xbb, 0xeb, 0xef, 0x17, 0xa3, 0x25, 0x19, 0x4e, 0xcc, 0xe4, 0xc7, 0x47, 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, 0xdf, 0xab, 0x76, 0xb4, 0x69, 0x6f, 0xe2, 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, 0x4d, 0xd9, 0xfc, 0x2a, 0xda, 0xe7, 0xc8, 0x48, + 0xd9, 0x26, 0x23, 0x15, 0x18, 0x61, 0x4a, 0x91, 0xc4, 0x55, 0x08, 0x81, 0xec, 0xbf, 0xa4, 0xb8, 0x16, 0x4b, 0xef, + 0x35, 0x08, 0x13, 0x6c, 0x17, 0xb4, 0x5f, 0xdd, 0xce, 0x6d, 0xa5, 0xc5, 0x1e, 0xa9, 0xef, 0x73, 0x67, 0xbb, 0xa2, + 0xc9, 0xdf, 0x97, 0x0d, 0x68, 0x03, 0x88, 0xf2, 0xbe, 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, 0x80, + 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, 0x53, 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, 0x11, 0xcb, 0xe6, 0x62, 0x31, 0x5a, 0x49, 0x08, 0x1b, 0x7c, 0xc8, 0xb2, 0x79, 0xa9, + 0x1f, 0x42, 0x5f, 0x58, 0x7a, 0x02, 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, 0x23, 0xd4, + 0xfe, 0x7e, 0x1e, 0xc5, 0x5a, 0x2e, 0xb9, 0x72, 0x7e, 0xf1, 0x37, 0x9f, 0xb1, 0xd7, 0x3d, 0xc3, 0x60, 0x01, 0xce, + 0xd2, 0xf6, 0x2a, 0x13, 0xef, 0x64, 0x2b, 0x38, 0x0e, 0x66, 0x51, 0x0e, 0xab, 0x9e, 0x1c, 0xd1, 0x5c, 0xe4, 0xda, + 0xbb, 0x08, 0x91, 0x83, 0xcc, 0x1e, 0x03, 0xec, 0x46, 0xf8, 0x3a, 0xb4, 0x36, 0xb7, 0xba, 0x42, 0xfc, 0x8d, 0x12, + 0x89, 0x9f, 0xa5, 0xfc, 0xb8, 0x5e, 0xa9, 0x5c, 0x95, 0xc1, 0x63, 0xd5, 0xcd, 0xe0, 0x99, 0xf6, 0x3d, 0xd6, 0xfe, + 0xad, 0xed, 0xe6, 0x78, 0xef, 0xc1, 0x83, 0xd6, 0xff, 0xd6, 0x93, 0x10, 0xda, 0x2b, 0x27, 0xa9, 0x3b, 0x6a, 0xf4, + 0xcc, 0x64, 0x8d, 0xa8, 0x84, 0xa9, 0xdd, 0xa9, 0x1c, 0x03, 0x35, 0x1d, 0xc0, 0xb5, 0x44, 0x4d, 0xd0, 0x93, 0x82, + 0x8d, 0xe1, 0x88, 0xb3, 0x38, 0x68, 0x87, 0x31, 0x8a, 0x97, 0x73, 0x25, 0x5e, 0xce, 0x8f, 0x18, 0x07, 0x68, 0x2d, + 0x40, 0xaa, 0xd7, 0xb0, 0x9f, 0xb9, 0x82, 0x05, 0x36, 0x77, 0xbe, 0x03, 0x0b, 0x64, 0x88, 0x93, 0xcd, 0x71, 0xb2, + 0xc7, 0xb5, 0x9e, 0x7b, 0x81, 0x8f, 0x93, 0x7a, 0xe1, 0xd5, 0x55, 0xb6, 0xeb, 0x5a, 0xb2, 0x72, 0x5e, 0x0c, 0x26, + 0x10, 0x94, 0xa5, 0x9c, 0x17, 0xc3, 0xc9, 0x82, 0xe6, 0xf0, 0x63, 0xd1, 0x40, 0x87, 0x58, 0x0e, 0x12, 0xb8, 0x74, + 0xf6, 0x18, 0xf0, 0x86, 0x52, 0x8b, 0xbb, 0xb1, 0x8e, 0x1c, 0xeb, 0x28, 0xf6, 0xc3, 0x18, 0x70, 0x65, 0x9d, 0xc0, + 0xfb, 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, 0x1d, 0x95, 0x43, + 0x2d, 0x84, 0xeb, 0x5a, 0x78, 0x1d, 0xa7, 0x65, 0x0c, 0x2e, 0xd2, 0xda, 0x36, 0xf1, 0x1e, 0xba, 0xee, 0xf9, 0x31, + 0xb7, 0x3a, 0x46, 0x5b, 0x48, 0xbf, 0x1d, 0x9d, 0xde, 0x73, 0x18, 0x80, 0xa6, 0x07, 0xb3, 0xaa, 0x7d, 0x26, 0x71, + 0x73, 0xda, 0x09, 0x42, 0x22, 0x10, 0x45, 0xe9, 0x8c, 0x30, 0xfd, 0x3b, 0xcd, 0x65, 0x15, 0xad, 0x1e, 0xe4, 0x99, + 0x43, 0x9e, 0x85, 0xde, 0xf6, 0xa0, 0x55, 0x73, 0x37, 0x18, 0x27, 0x6e, 0xb7, 0x77, 0xfe, 0xdf, 0xb2, 0xae, 0xad, + 0xd6, 0x88, 0xc7, 0xed, 0xea, 0x07, 0x8d, 0xbd, 0xda, 0x53, 0x31, 0x60, 0x56, 0xd2, 0x3b, 0xa3, 0x4a, 0x5e, 0x64, + 0xbc, 0xc4, 0x93, 0x6a, 0xd5, 0xf0, 0xf1, 0xbe, 0xc9, 0x46, 0xe6, 0x81, 0x4c, 0x01, 0xf1, 0xfc, 0x26, 0x35, 0xea, + 0xe3, 0x14, 0x25, 0xe0, 0xef, 0x74, 0x7c, 0x23, 0xfa, 0xd1, 0xbe, 0xb8, 0xe4, 0xd5, 0xc9, 0x8d, 0x30, 0x2f, 0x5e, + 0x58, 0x9d, 0x3f, 0x7d, 0x53, 0xf8, 0xd0, 0xe1, 0xa8, 0xbd, 0x83, 0x22, 0x4b, 0x26, 0x8e, 0x26, 0x46, 0xd6, 0x26, + 0x66, 0x1f, 0x15, 0x5c, 0x4c, 0x54, 0xa1, 0x67, 0x9d, 0x3d, 0x61, 0x0a, 0xd0, 0x37, 0x8e, 0x51, 0xc9, 0x18, 0x16, + 0x0c, 0xd4, 0x69, 0x4a, 0x88, 0x1e, 0x8a, 0x19, 0xc6, 0x2b, 0x06, 0x50, 0x98, 0x42, 0x81, 0x28, 0x3a, 0xfb, 0x70, + 0xa0, 0x09, 0xfd, 0xfe, 0x4d, 0xaa, 0x33, 0xd0, 0xb2, 0x9e, 0x4a, 0x10, 0xd5, 0x41, 0xb4, 0x55, 0x5e, 0x84, 0x3f, + 0x2e, 0x69, 0x99, 0xd1, 0xa5, 0xa0, 0xa9, 0xa0, 0x49, 0x46, 0x2f, 0xb8, 0x12, 0x15, 0x5f, 0x08, 0xa6, 0x68, 0xbb, + 0x21, 0xec, 0xff, 0x6a, 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, 0x9d, 0xae, 0xcf, 0x9f, 0xcb, 0xab, 0x95, 0x14, 0x5c, 0x54, 0x0a, 0xa2, 0xdf, 0xe0, 0xbe, 0x9b, 0xb8, + 0xea, 0xac, 0x59, 0x2b, 0x7d, 0xe8, 0x5b, 0x9f, 0xb5, 0x71, 0x5f, 0x18, 0x1c, 0x83, 0x9d, 0x8f, 0x88, 0x81, 0x34, + 0xa8, 0x74, 0x8b, 0x43, 0x13, 0xa0, 0x4b, 0x87, 0x14, 0xb2, 0x64, 0x2a, 0x53, 0x25, 0xa8, 0xf8, 0xc6, 0xef, 0xa5, + 0xac, 0x46, 0x7f, 0xad, 0x79, 0x71, 0x77, 0xca, 0x73, 0x8e, 0x63, 0x14, 0x24, 0xb1, 0xb8, 0x8e, 0xcb, 0x80, 0xf8, + 0x96, 0x57, 0xc1, 0x41, 0x6a, 0xc2, 0xc6, 0xec, 0x54, 0x8d, 0x5a, 0x2f, 0x89, 0xbe, 0x32, 0xca, 0x37, 0x06, 0x43, + 0x13, 0x51, 0x05, 0x7d, 0xaf, 0xd5, 0x3d, 0xad, 0x6e, 0x58, 0x40, 0xfc, 0xb9, 0xd2, 0x0b, 0xb5, 0x5e, 0x37, 0x63, + 0x6e, 0x98, 0x08, 0x41, 0xa3, 0x27, 0xf5, 0xa2, 0xf6, 0xdc, 0xd2, 0x54, 0x64, 0xdc, 0x68, 0x93, 0xf3, 0x4b, 0x90, + 0xf1, 0x39, 0x73, 0xa1, 0x49, 0x5d, 0x53, 0x05, 0x55, 0x18, 0x6d, 0x6e, 0x1b, 0xe9, 0xf4, 0x0e, 0xdc, 0xd9, 0x8c, + 0xd9, 0x91, 0x76, 0x69, 0xac, 0x69, 0xc1, 0xcb, 0x95, 0x14, 0x25, 0x84, 0x71, 0xee, 0x8d, 0xe9, 0x55, 0x9c, 0x89, + 0x2a, 0xce, 0xc4, 0x71, 0xb9, 0xe2, 0x49, 0xf5, 0x1e, 0x6e, 0x71, 0xca, 0xea, 0xa6, 0x2e, 0xe1, 0x4a, 0x97, 0xec, + 0x61, 0x30, 0x35, 0x15, 0xf7, 0xd8, 0x19, 0x5c, 0x54, 0x7f, 0x44, 0x4b, 0x89, 0xb1, 0x50, 0x75, 0xf1, 0xf1, 0x79, + 0x29, 0xf3, 0x75, 0x05, 0xda, 0xdd, 0x8b, 0x2a, 0x3a, 0x78, 0xba, 0xba, 0x9d, 0xaa, 0x1b, 0x4c, 0xf4, 0xf4, 0x60, + 0x75, 0xdb, 0xcb, 0xae, 0x56, 0xb2, 0xa8, 0x62, 0x51, 0x4d, 0x15, 0x22, 0x59, 0x12, 0xe7, 0x49, 0x38, 0x19, 0x8f, + 0xbf, 0xda, 0x1b, 0xee, 0x41, 0x06, 0x32, 0xfd, 0x34, 0x54, 0x2e, 0x47, 0xc3, 0xc9, 0x78, 0x3c, 0x95, 0xea, 0x6e, + 0x17, 0x8d, 0x26, 0x35, 0xd6, 0x33, 0x4c, 0xf4, 0xcc, 0x8c, 0xf8, 0xed, 0x2a, 0x16, 0x29, 0xc4, 0xaf, 0xd3, 0xc5, + 0x1f, 0x3c, 0x1d, 0x37, 0xca, 0xb7, 0x9f, 0x3e, 0xab, 0xff, 0xa8, 0x4d, 0x58, 0x6b, 0xd3, 0xee, 0xe7, 0x7f, 0x1c, + 0xaa, 0xf9, 0x3e, 0x3a, 0xdc, 0xd7, 0x3f, 0xfe, 0xa8, 0xeb, 0xe9, 0x9b, 0x22, 0x9c, 0xff, 0x33, 0x54, 0xf3, 0x79, + 0x5c, 0x14, 0xf1, 0x5d, 0x0d, 0x91, 0x3c, 0x85, 0xf3, 0x26, 0xa1, 0xde, 0x36, 0xa0, 0x07, 0x64, 0x7a, 0x21, 0x18, + 0x7c, 0xf3, 0xbe, 0x0a, 0x03, 0x5e, 0xae, 0x86, 0x5c, 0x54, 0x59, 0x75, 0x37, 0xc4, 0x3c, 0x01, 0x7e, 0x6a, 0x78, + 0xb3, 0xe7, 0x85, 0x21, 0x36, 0x17, 0x05, 0xe7, 0x9f, 0x78, 0xa8, 0x8c, 0xa3, 0xc7, 0x68, 0x1c, 0x3d, 0xa6, 0x6a, + 0x30, 0x26, 0xdf, 0x50, 0xdd, 0x99, 0xc9, 0x37, 0x60, 0x82, 0x94, 0xb5, 0xbf, 0x51, 0xc6, 0x89, 0xd1, 0x98, 0x5e, + 0xbf, 0xca, 0xb3, 0x15, 0x30, 0xc1, 0x4b, 0xfd, 0xa3, 0x26, 0xf4, 0x3d, 0x6f, 0x67, 0x1f, 0x8d, 0x46, 0xcf, 0x0b, + 0x3a, 0x1a, 0x8d, 0x3e, 0x66, 0x35, 0xa1, 0x2b, 0xd1, 0xf1, 0xfe, 0x3d, 0xa7, 0xe7, 0x32, 0xbd, 0x8b, 0x82, 0x80, + 0x2e, 0xb3, 0x34, 0xe5, 0x42, 0x95, 0x75, 0x9a, 0xb6, 0xf3, 0xaa, 0x16, 0x22, 0xf0, 0x8f, 0x6e, 0x23, 0x42, 0x10, + 0x11, 0x7a, 0xb2, 0xd3, 0xb3, 0xd1, 0x68, 0x74, 0x9a, 0x9a, 0x6a, 0x1d, 0x43, 0xfe, 0x06, 0xcd, 0x07, 0x9c, 0x5d, + 0x3e, 0x58, 0xdf, 0x98, 0x68, 0x27, 0xfb, 0xff, 0x3d, 0x9c, 0xcd, 0xc7, 0xc3, 0x6f, 0x47, 0x8b, 0xc7, 0xfb, 0x34, + 0x08, 0x7c, 0xd0, 0xea, 0x50, 0x5b, 0x73, 0x4c, 0xcb, 0xc3, 0xf1, 0x94, 0x94, 0x03, 0xf6, 0xd4, 0xfa, 0xd2, 0x7c, + 0xf5, 0x14, 0x90, 0x48, 0x51, 0x84, 0x1a, 0x38, 0xe9, 0x1f, 0x5e, 0x45, 0x5e, 0x0b, 0xc0, 0x47, 0xb3, 0x91, 0x0c, + 0x8c, 0x16, 0x70, 0x1c, 0x41, 0x79, 0xb5, 0x35, 0x8d, 0xe8, 0x31, 0x96, 0x99, 0xa8, 0xa0, 0xe3, 0x69, 0x79, 0x93, + 0x55, 0xc9, 0x12, 0x03, 0x1b, 0xc5, 0x25, 0x0f, 0xbe, 0x0a, 0xa2, 0x92, 0x1d, 0x3c, 0x9b, 0x2a, 0x78, 0x5f, 0x4c, + 0x4a, 0xf9, 0x25, 0x24, 0x7e, 0x3b, 0x46, 0x08, 0x54, 0xa2, 0x3d, 0x16, 0xb1, 0xc6, 0x57, 0xb9, 0x8c, 0xc1, 0x83, + 0xb3, 0xd4, 0x3c, 0x8b, 0x3d, 0x09, 0xac, 0xfd, 0x45, 0xab, 0x39, 0x12, 0x9a, 0x13, 0x4a, 0x26, 0xf7, 0x4b, 0x2a, + 0xbf, 0x9a, 0xa0, 0x57, 0x10, 0xb8, 0x55, 0x47, 0x70, 0xdc, 0x59, 0xcb, 0x06, 0xbd, 0x7c, 0x52, 0xb6, 0x3f, 0xff, + 0xdf, 0x25, 0x5d, 0x0c, 0xf6, 0xdd, 0xd0, 0x9c, 0x68, 0xf7, 0xd5, 0x0a, 0x19, 0xa5, 0x2a, 0x7c, 0x9e, 0x12, 0x6b, + 0x7c, 0xca, 0xd9, 0xd1, 0xc6, 0x74, 0x67, 0x54, 0x15, 0xd9, 0x55, 0x48, 0x74, 0xaf, 0x1c, 0x28, 0x66, 0x10, 0x65, + 0x23, 0x5c, 0x3f, 0x60, 0x2d, 0xe2, 0x75, 0xf2, 0x9a, 0x17, 0x55, 0x96, 0xa8, 0xf7, 0xd7, 0x8d, 0xf7, 0x40, 0x0d, + 0x54, 0x83, 0xde, 0x15, 0x0c, 0xe6, 0xf9, 0xa4, 0x00, 0xd0, 0xce, 0x92, 0x17, 0xd7, 0xdc, 0xa7, 0x1b, 0x41, 0x50, + 0xbb, 0x66, 0x5e, 0x36, 0x82, 0x4d, 0xc0, 0x57, 0xef, 0x0a, 0xc0, 0xdc, 0x08, 0x41, 0x6a, 0x0a, 0xa1, 0x70, 0xe0, + 0x02, 0x5f, 0x55, 0x45, 0x76, 0xbe, 0xae, 0x38, 0x06, 0xfb, 0xf0, 0xe2, 0x26, 0x2a, 0x27, 0x3c, 0x1e, 0x06, 0xf8, + 0x23, 0xa0, 0x2a, 0xe0, 0x86, 0xf1, 0xb0, 0x83, 0x17, 0xea, 0x97, 0x7b, 0xa3, 0xf6, 0x08, 0x7b, 0x93, 0x86, 0x10, + 0x5c, 0x07, 0x1f, 0x02, 0x58, 0x52, 0x84, 0x9e, 0xe0, 0xa9, 0x1a, 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, 0x28, 0xef, + 0xf4, 0xc4, 0xb8, 0x30, 0x7d, 0x1c, 0x22, 0xbf, 0xbc, 0x2b, 0x54, 0xe8, 0x17, 0xbe, 0x00, 0xf0, 0x2b, 0xb8, 0xdd, + 0xef, 0xc6, 0x77, 0x51, 0xd9, 0xcf, 0x38, 0xdb, 0xff, 0xef, 0x79, 0x3c, 0xfc, 0x34, 0x1e, 0x7e, 0xbb, 0x18, 0x84, + 0x43, 0xfb, 0x93, 0x3c, 0x7e, 0xb4, 0x4f, 0x5f, 0x71, 0xcb, 0x95, 0xc0, 0xc2, 0x6f, 0x04, 0xb7, 0x51, 0x2b, 0x21, + 0x88, 0x02, 0xbc, 0x51, 0xb8, 0xd5, 0x38, 0x01, 0x80, 0xbf, 0xe0, 0xbf, 0x02, 0x34, 0x12, 0x72, 0x17, 0x0d, 0xd0, + 0x0f, 0xa8, 0xdf, 0x47, 0x4f, 0x1a, 0x06, 0x72, 0x20, 0x9e, 0x50, 0x31, 0x50, 0x88, 0x2e, 0x63, 0xa2, 0x60, 0x7f, + 0x6d, 0xf6, 0xed, 0xb6, 0xd7, 0x96, 0xfc, 0xe0, 0x97, 0x7e, 0xa6, 0x89, 0x99, 0x77, 0xb8, 0xa1, 0xac, 0xe4, 0x2a, + 0x44, 0x6c, 0x3c, 0xfd, 0x2b, 0x67, 0x10, 0x6b, 0xf2, 0x3a, 0x03, 0x1f, 0x06, 0xfb, 0xc5, 0x78, 0x06, 0x6c, 0x03, + 0xdc, 0x71, 0x0a, 0x7e, 0x91, 0x81, 0x5b, 0xb3, 0x88, 0xf1, 0x82, 0x6d, 0x97, 0x44, 0xbf, 0xdf, 0xcb, 0xb3, 0x30, + 0xd7, 0x38, 0xcb, 0x79, 0x6d, 0xc4, 0xee, 0xa8, 0x13, 0x06, 0x71, 0xbb, 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, 0xb8, 0x2e, 0xb3, 0x5e, 0x2f, 0x0c, 0xd1, 0xa1, 0x11, 0x4b, 0xc5, + 0xda, 0x20, 0xbc, 0x8f, 0x49, 0x18, 0x5d, 0x81, 0xac, 0x2e, 0x3c, 0xe3, 0x04, 0xf9, 0x32, 0x30, 0x59, 0x53, 0xd5, + 0x7a, 0x39, 0xe1, 0xb1, 0x91, 0x2f, 0x1b, 0x41, 0x83, 0xbc, 0xa4, 0xa8, 0x37, 0x71, 0x3b, 0xf6, 0x51, 0x0b, 0xa9, + 0x71, 0x53, 0x4f, 0x7b, 0x9a, 0x54, 0xf4, 0x58, 0xaf, 0x52, 0xbf, 0xc0, 0xb2, 0xc0, 0x92, 0x0f, 0x42, 0x7b, 0x9a, + 0x56, 0x60, 0x86, 0x6b, 0x9b, 0xc1, 0xd0, 0x0f, 0x87, 0xb6, 0x08, 0x9d, 0x51, 0xdb, 0x12, 0xc2, 0xb6, 0x0d, 0xc2, + 0xca, 0x7b, 0x22, 0x5f, 0x3d, 0xf5, 0x18, 0xe1, 0x90, 0x9b, 0xcd, 0x2c, 0x1a, 0x18, 0xe6, 0x57, 0xb2, 0xd9, 0x3c, + 0xdd, 0x5c, 0x2f, 0x2a, 0xa6, 0x80, 0xed, 0xb6, 0x12, 0x04, 0xff, 0x7e, 0xcc, 0x66, 0xf8, 0x37, 0xeb, 0xf7, 0x7b, + 0x21, 0xfe, 0xe2, 0x18, 0xbc, 0x67, 0x2e, 0x16, 0xec, 0x23, 0xc8, 0x54, 0x48, 0x84, 0xa9, 0xca, 0xf8, 0x8d, 0x55, + 0x60, 0x01, 0x67, 0x3e, 0x50, 0xb9, 0x30, 0x93, 0xbd, 0xbc, 0xb8, 0x86, 0x1c, 0xb7, 0xc6, 0x29, 0x1b, 0x65, 0x89, + 0x72, 0x5d, 0xc8, 0x46, 0x71, 0x9e, 0xc5, 0x25, 0x2f, 0xb7, 0x5b, 0x7d, 0x38, 0x26, 0x05, 0x07, 0xf6, 0x54, 0x51, + 0xa9, 0x92, 0x75, 0xa4, 0xba, 0xf1, 0x97, 0x61, 0x81, 0xfb, 0x94, 0xcf, 0x0b, 0x43, 0x23, 0xf6, 0xe0, 0xf2, 0xce, + 0xd4, 0xad, 0xb4, 0x17, 0x16, 0xd0, 0xbc, 0x92, 0x90, 0x0d, 0xa6, 0x7a, 0x16, 0xad, 0x31, 0x13, 0xf3, 0x62, 0x01, + 0x61, 0x64, 0x8a, 0x05, 0xd8, 0x4c, 0x71, 0x01, 0x5e, 0x24, 0x31, 0xc0, 0xc4, 0xc5, 0x64, 0x0a, 0xf1, 0xcc, 0x55, + 0x39, 0xf1, 0xc2, 0xdc, 0x2f, 0x13, 0x87, 0x94, 0x01, 0xaf, 0x6a, 0x83, 0x26, 0x66, 0x1b, 0x8e, 0x3a, 0x41, 0x4e, + 0x4c, 0x7e, 0x3f, 0x55, 0x10, 0xe2, 0x4e, 0x1c, 0x09, 0x97, 0x15, 0xdb, 0x85, 0x97, 0x1d, 0x88, 0x31, 0x6a, 0x70, + 0xca, 0xcf, 0x0c, 0x8e, 0xc6, 0xe0, 0xdc, 0x78, 0x27, 0x48, 0x11, 0xc6, 0x64, 0x23, 0xd9, 0x95, 0x0c, 0xc5, 0x3c, + 0x5e, 0x80, 0xb2, 0x2e, 0x5e, 0x80, 0x65, 0x8d, 0x31, 0xc0, 0x04, 0x79, 0x15, 0xf7, 0x42, 0x3f, 0x51, 0x5c, 0x21, + 0xd2, 0xb3, 0x72, 0x7d, 0x54, 0xb4, 0x43, 0x5f, 0xe0, 0xf5, 0x5e, 0x99, 0xe3, 0x66, 0x3d, 0x16, 0x48, 0x6c, 0x08, + 0x18, 0x1b, 0xe9, 0x34, 0xd5, 0x5a, 0xf7, 0xc6, 0xcc, 0x03, 0x9f, 0x66, 0x23, 0x21, 0xab, 0xb3, 0x0b, 0x10, 0xa1, + 0xf8, 0x68, 0xf0, 0xc8, 0x2f, 0xe2, 0xce, 0x32, 0x6f, 0x6d, 0x8b, 0x4a, 0x76, 0xb4, 0x01, 0x90, 0x3e, 0x1d, 0x2d, + 0x4a, 0xc9, 0x29, 0x4a, 0x52, 0xbb, 0x4d, 0x01, 0x2b, 0xc9, 0x5f, 0xc0, 0x10, 0x6c, 0x6c, 0x4f, 0x38, 0x9d, 0x22, + 0xc4, 0x27, 0x9a, 0x22, 0xb2, 0x62, 0x58, 0x52, 0x1c, 0xdb, 0x12, 0x51, 0x3f, 0x6d, 0x59, 0x76, 0x30, 0x4c, 0x54, + 0xdc, 0x17, 0xa9, 0x47, 0x89, 0x82, 0x80, 0xea, 0x21, 0x07, 0x89, 0xad, 0x6d, 0x20, 0x3c, 0x20, 0x8f, 0xe8, 0x8d, + 0xf5, 0xf7, 0x59, 0xe7, 0xd9, 0x85, 0xe6, 0xa8, 0x5c, 0xef, 0x0a, 0x33, 0x46, 0x78, 0x92, 0x19, 0x98, 0x7c, 0xef, + 0x3c, 0x33, 0x6a, 0x8a, 0x9e, 0x87, 0x4f, 0x76, 0x8c, 0x11, 0xe9, 0xee, 0x19, 0x74, 0x13, 0xbc, 0xaa, 0xc3, 0x46, + 0xbb, 0x52, 0x10, 0x12, 0xa6, 0x16, 0x4d, 0xcc, 0x7a, 0xd6, 0x80, 0x7a, 0xbb, 0xed, 0xe9, 0xb9, 0xba, 0x7f, 0xee, + 0xb6, 0xdb, 0x1e, 0x76, 0xeb, 0x45, 0xda, 0x6d, 0x05, 0x5e, 0xa9, 0x0f, 0xda, 0xe3, 0xcf, 0xdd, 0xf8, 0x73, 0x83, + 0xe4, 0x51, 0x3a, 0x9a, 0x69, 0xeb, 0x83, 0x70, 0xb8, 0xe9, 0x5d, 0xa3, 0x49, 0xdf, 0x67, 0xa1, 0xa4, 0x2b, 0xd1, + 0xa8, 0xae, 0x76, 0x26, 0x95, 0x0f, 0xae, 0xff, 0x87, 0x57, 0x01, 0x1e, 0x71, 0x6a, 0x67, 0xdf, 0xdb, 0xa0, 0xa2, + 0xd1, 0x16, 0x8e, 0x14, 0xa1, 0x07, 0x24, 0xe1, 0xbe, 0x96, 0xb5, 0xb8, 0xcd, 0xd3, 0xec, 0x61, 0xfa, 0xf4, 0x3a, + 0xf5, 0xad, 0xee, 0xdd, 0x32, 0xcb, 0xcc, 0x81, 0x57, 0x51, 0x1c, 0xd0, 0xa8, 0x8b, 0xf6, 0x5d, 0x65, 0x65, 0x09, + 0x5e, 0x1e, 0x70, 0x7d, 0x3e, 0xe5, 0x3e, 0xdc, 0xdc, 0x65, 0xd5, 0xdc, 0xa4, 0xa7, 0xd9, 0x3c, 0x5b, 0x6c, 0xb7, + 0x21, 0xfe, 0xed, 0x6a, 0x91, 0xa3, 0xc9, 0x73, 0xd0, 0xe1, 0x61, 0xe4, 0x1e, 0xa6, 0x1b, 0xe7, 0x6d, 0xfe, 0x4f, + 0xa2, 0xe1, 0x24, 0x70, 0x0c, 0xf4, 0x62, 0xf6, 0x08, 0x64, 0x30, 0xc6, 0xa9, 0x5f, 0xcc, 0xf4, 0x9a, 0x81, 0xe8, + 0x5b, 0x22, 0x02, 0x1c, 0x5d, 0x6c, 0x24, 0x1a, 0x59, 0x70, 0x52, 0x13, 0xb0, 0xd8, 0xb4, 0xe5, 0x7d, 0xb0, 0xb4, + 0xad, 0x2a, 0xee, 0xbc, 0x25, 0xcd, 0x71, 0x1d, 0x38, 0xdb, 0x7e, 0x33, 0xc4, 0xa6, 0xec, 0x6a, 0x81, 0xdc, 0x2f, + 0xaf, 0x69, 0x6f, 0x5c, 0x27, 0x30, 0x6b, 0x9b, 0xda, 0x32, 0x7e, 0xb6, 0xf4, 0x9f, 0xf5, 0xe0, 0x2a, 0xe3, 0xa7, + 0xb9, 0xb1, 0x4a, 0xb0, 0xfb, 0xc6, 0xf3, 0x1d, 0x80, 0x70, 0x6c, 0x3e, 0x3d, 0x3e, 0xcd, 0x3c, 0x7a, 0x0c, 0x44, + 0xc7, 0x7c, 0x54, 0xba, 0x8f, 0xec, 0xee, 0xf5, 0x03, 0xe0, 0xcd, 0xab, 0x76, 0x41, 0xf3, 0x72, 0x01, 0x81, 0x44, + 0xbd, 0xf2, 0x0a, 0xcb, 0x67, 0xc6, 0xec, 0x12, 0xc8, 0x50, 0x41, 0xc0, 0x26, 0xa9, 0xeb, 0x5c, 0x88, 0x55, 0x87, + 0x95, 0xf9, 0x48, 0xc2, 0x8e, 0x42, 0x34, 0xe7, 0x0c, 0x66, 0xc1, 0x7f, 0x05, 0x83, 0x72, 0x10, 0x44, 0x41, 0x14, + 0x04, 0x64, 0x50, 0xc0, 0x2f, 0xc4, 0x19, 0x23, 0x18, 0xa3, 0x04, 0x3a, 0xfc, 0x8e, 0x33, 0x9f, 0x11, 0x79, 0xd9, + 0x08, 0x63, 0xe9, 0x06, 0xe0, 0x5c, 0xca, 0x9c, 0xc7, 0xe8, 0x63, 0xf1, 0x8e, 0xb3, 0x8c, 0xd0, 0x77, 0xde, 0xa9, + 0xfc, 0x88, 0x37, 0x82, 0xdb, 0xed, 0x0e, 0xdb, 0x2b, 0x1e, 0x66, 0xb4, 0x37, 0xa6, 0xef, 0x38, 0x89, 0xb2, 0x86, + 0xf3, 0x30, 0x87, 0x9e, 0x55, 0x96, 0xb5, 0xa2, 0x86, 0xdc, 0xa0, 0x58, 0x17, 0x59, 0x26, 0x27, 0xc3, 0x55, 0x73, + 0x2a, 0x70, 0xdd, 0xd9, 0xf5, 0x02, 0x92, 0x32, 0xa1, 0x59, 0x3a, 0x1b, 0xbe, 0xda, 0xb6, 0xec, 0x45, 0xeb, 0x14, + 0xf2, 0x1a, 0xa2, 0xa2, 0x1f, 0x3a, 0x02, 0x6a, 0x68, 0xc5, 0x65, 0x05, 0x2e, 0xbb, 0xa6, 0x3d, 0xdc, 0xb4, 0xc7, + 0x34, 0xe3, 0x03, 0xc4, 0x88, 0xe3, 0xd8, 0x32, 0xb0, 0x9b, 0x70, 0x78, 0x36, 0xce, 0xf7, 0x65, 0x97, 0xde, 0xba, + 0x5a, 0x3c, 0xc2, 0xda, 0xf3, 0x56, 0x48, 0x08, 0x90, 0x96, 0xa6, 0xd2, 0xed, 0x36, 0x08, 0x60, 0x80, 0xfb, 0xfd, + 0x1e, 0x70, 0xad, 0x86, 0x9d, 0x34, 0xb7, 0x66, 0x4b, 0xec, 0x15, 0x85, 0xc7, 0x40, 0x94, 0x9a, 0xff, 0x0c, 0x02, + 0x8a, 0xe7, 0x6e, 0x08, 0xf6, 0x95, 0xec, 0x68, 0x53, 0xf4, 0xfb, 0x2f, 0x0a, 0x7c, 0x40, 0x39, 0x28, 0x88, 0x75, + 0x75, 0xdc, 0x0a, 0xc3, 0x3e, 0xa9, 0x0f, 0x71, 0x2c, 0xf2, 0x2c, 0x74, 0x84, 0xa5, 0x32, 0x84, 0x85, 0x2b, 0x46, + 0x3a, 0x88, 0x83, 0x9a, 0x74, 0x0e, 0x56, 0xe5, 0x82, 0x0d, 0xf7, 0x7a, 0x9f, 0x00, 0x16, 0x3c, 0xf3, 0x86, 0xe5, + 0xbd, 0x07, 0x00, 0xd6, 0xeb, 0xe1, 0x42, 0x71, 0x2f, 0x5f, 0x35, 0xd0, 0x27, 0xf1, 0xa5, 0x65, 0xd7, 0x67, 0x5a, + 0x56, 0x32, 0x1a, 0x8d, 0xaa, 0x5a, 0x49, 0x3e, 0x1c, 0x79, 0x69, 0xa1, 0x56, 0xca, 0x38, 0xe5, 0x29, 0x58, 0x7a, + 0x1b, 0x4a, 0x37, 0x5f, 0xd0, 0x15, 0x17, 0xa9, 0xfa, 0xe9, 0xa1, 0x4d, 0x36, 0x88, 0x6b, 0xd6, 0xd4, 0x59, 0xd8, + 0xe1, 0x87, 0x80, 0x8f, 0xf6, 0x61, 0xe6, 0xd2, 0x35, 0x2c, 0x2d, 0x88, 0x23, 0xe3, 0x82, 0x87, 0x2e, 0x0f, 0x60, + 0xfd, 0x99, 0x43, 0x12, 0x3f, 0x85, 0x9f, 0x33, 0x93, 0xd6, 0xf1, 0x19, 0xce, 0x66, 0x54, 0xaa, 0x1b, 0x41, 0xfb, + 0x35, 0x24, 0x12, 0x83, 0x6c, 0xdc, 0x60, 0x28, 0x5a, 0x77, 0x1b, 0xb8, 0xf2, 0x5b, 0x7a, 0xe7, 0xd3, 0x20, 0xc0, + 0xb6, 0xc6, 0x62, 0x00, 0x30, 0x14, 0x7f, 0xa0, 0xaa, 0xc6, 0x5c, 0x51, 0x4c, 0xc3, 0x54, 0xa2, 0xbd, 0xe3, 0xb8, + 0x8e, 0x1a, 0x57, 0x59, 0xc1, 0x4a, 0x6b, 0xcb, 0xeb, 0xde, 0xd2, 0xc2, 0x96, 0x80, 0x6a, 0x30, 0xdc, 0x09, 0xe0, + 0x33, 0x22, 0xd5, 0x81, 0x20, 0xbb, 0x0f, 0x0e, 0x9a, 0xb3, 0x04, 0xcf, 0xc3, 0x10, 0xfe, 0xc0, 0xc2, 0x81, 0x65, + 0xa9, 0xfa, 0xb9, 0x9c, 0xc6, 0x70, 0xee, 0xe6, 0x6a, 0x87, 0xcf, 0x96, 0xa0, 0xc8, 0x53, 0x73, 0x6a, 0x2e, 0x5f, + 0x79, 0x63, 0xbf, 0xc7, 0x04, 0xf3, 0x98, 0xd9, 0x86, 0xdf, 0x7a, 0xba, 0xad, 0x2f, 0xac, 0x1b, 0x38, 0x69, 0x2f, + 0x9c, 0xf6, 0x62, 0xbb, 0x34, 0x10, 0x77, 0x75, 0x43, 0x88, 0xf0, 0x5a, 0x13, 0x8b, 0xac, 0x21, 0xd3, 0xb1, 0xd8, + 0x18, 0xaa, 0x4d, 0xc5, 0x73, 0xad, 0x10, 0x2f, 0xa7, 0xea, 0xc2, 0xd4, 0x4a, 0x65, 0xc2, 0x20, 0xcc, 0x94, 0xb0, + 0xa8, 0x32, 0xf0, 0xd9, 0xaf, 0x90, 0xe2, 0xda, 0x7a, 0xde, 0xe2, 0xf2, 0xcd, 0x4c, 0x9b, 0xed, 0xa7, 0xaf, 0xf2, + 0xf8, 0x72, 0xbb, 0x0d, 0xbb, 0x5f, 0x80, 0xf9, 0x65, 0xa9, 0x34, 0x6a, 0xe0, 0xf4, 0x10, 0xa2, 0x9f, 0xf3, 0x3d, + 0x39, 0x27, 0x8e, 0x93, 0x6b, 0x37, 0x6f, 0xb6, 0x93, 0x62, 0x04, 0x16, 0x70, 0xe2, 0x22, 0x1d, 0x68, 0xa9, 0xe0, + 0xb4, 0x65, 0xbc, 0xb7, 0xe9, 0x1d, 0xa5, 0xc2, 0xab, 0x85, 0x26, 0x21, 0x95, 0xbb, 0x97, 0xd8, 0x51, 0x03, 0xce, + 0x49, 0xdd, 0x41, 0xc0, 0x49, 0x4d, 0x37, 0xd6, 0x2a, 0x4e, 0x4d, 0x82, 0xf7, 0x4a, 0x0f, 0x5d, 0xa2, 0x9d, 0xb8, + 0xdd, 0xb6, 0x2a, 0x5b, 0xa8, 0x8f, 0x7b, 0x39, 0x4b, 0xd4, 0xf1, 0x80, 0x42, 0x17, 0x75, 0x34, 0xe4, 0x0b, 0x52, + 0xe8, 0x95, 0xa3, 0x55, 0xab, 0xbb, 0x92, 0x81, 0x52, 0xad, 0x82, 0xbc, 0x26, 0xd6, 0x5d, 0x2b, 0x6b, 0x2c, 0xae, + 0x9c, 0x90, 0xc2, 0x26, 0x7c, 0x69, 0x29, 0x16, 0x56, 0xb0, 0x37, 0xa6, 0xbe, 0x70, 0x89, 0xd0, 0x76, 0xb7, 0x21, + 0x26, 0x19, 0xac, 0x9b, 0xed, 0xf6, 0x75, 0x11, 0xce, 0xb3, 0x05, 0x95, 0xa3, 0x2c, 0x45, 0x08, 0x31, 0xe3, 0xa1, + 0x6b, 0xbb, 0x60, 0x26, 0x86, 0xba, 0xf6, 0x78, 0x49, 0xa6, 0x58, 0x9b, 0x24, 0x47, 0xf1, 0xb9, 0x2c, 0xd4, 0x5a, + 0x23, 0x04, 0x0f, 0xf7, 0x3f, 0x53, 0x88, 0xe1, 0x66, 0xd6, 0xdd, 0x6f, 0x3b, 0x37, 0xc4, 0x3f, 0x21, 0x90, 0x40, + 0xc9, 0x5e, 0x17, 0xa3, 0xf3, 0x4c, 0xa4, 0xb8, 0x53, 0x55, 0x54, 0x5c, 0xb5, 0x0e, 0x9a, 0x2d, 0xb7, 0xf7, 0x62, + 0x4b, 0x14, 0x20, 0xae, 0xb1, 0xd0, 0x8c, 0x67, 0xe5, 0x2c, 0x45, 0x32, 0x8a, 0x0d, 0x89, 0x4a, 0x2f, 0x2a, 0xba, + 0xcf, 0xd3, 0x98, 0x1e, 0xba, 0x35, 0x08, 0xae, 0x9a, 0x3b, 0x1b, 0x69, 0xbe, 0x20, 0x44, 0x4d, 0x80, 0x84, 0x8d, + 0x6a, 0x4e, 0xad, 0x4b, 0xf1, 0x30, 0xab, 0x7c, 0xa6, 0x0f, 0xe2, 0x4b, 0x01, 0x3c, 0xac, 0xb7, 0xbd, 0xaf, 0x84, + 0xc7, 0xda, 0xe0, 0xdb, 0xed, 0xf6, 0x52, 0xcc, 0x83, 0xc0, 0x63, 0x34, 0xbf, 0x53, 0x12, 0xf3, 0xde, 0x98, 0xc2, + 0x8a, 0xf7, 0x5d, 0xda, 0xba, 0x49, 0xad, 0xb5, 0x40, 0xdd, 0xe1, 0xfa, 0x80, 0xe7, 0x29, 0x71, 0xb4, 0xa3, 0x72, + 0x2a, 0xad, 0xae, 0x1c, 0xbb, 0x22, 0x30, 0x30, 0xf4, 0x0f, 0x29, 0xdb, 0x80, 0x39, 0x1e, 0x58, 0xdb, 0xa0, 0x9f, + 0x92, 0xd2, 0xc2, 0x8c, 0xd1, 0x98, 0x45, 0xae, 0xab, 0xe8, 0x80, 0xeb, 0xe8, 0xed, 0x3c, 0xfa, 0xdb, 0xb3, 0x31, + 0x2d, 0x62, 0x91, 0xca, 0x2b, 0x50, 0x41, 0x80, 0x32, 0x04, 0x0d, 0xff, 0x35, 0x35, 0x00, 0x0d, 0x82, 0x1b, 0x80, + 0x7f, 0x74, 0x3a, 0x0d, 0xda, 0x9a, 0x7c, 0x4c, 0x52, 0x55, 0xe4, 0xac, 0x0d, 0x65, 0xa6, 0x92, 0x43, 0xf2, 0xb8, + 0x04, 0x3c, 0x47, 0x6c, 0x96, 0xb2, 0xb9, 0x50, 0x9b, 0x4d, 0xbd, 0x56, 0xec, 0xc8, 0x6d, 0xa3, 0x68, 0xb3, 0x16, + 0xb5, 0x9d, 0xc4, 0x7c, 0x31, 0xbd, 0xb5, 0xc2, 0xc0, 0xa9, 0x69, 0xcd, 0xcd, 0x0e, 0x74, 0x9a, 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, 0x0d, 0x69, 0xaa, 0xd0, 0xa3, 0x03, 0xbd, 0x1d, 0x02, 0x9a, 0xb3, 0x31, + 0x5d, 0xd2, 0x14, 0x2f, 0xd0, 0x74, 0x0d, 0x66, 0x29, 0x17, 0xd0, 0xd7, 0x6e, 0x9f, 0xe4, 0x0b, 0xd5, 0x13, 0xe1, + 0x2d, 0x51, 0xf0, 0xe5, 0x48, 0xc1, 0x2b, 0x2b, 0xe7, 0xb1, 0x99, 0x43, 0xc0, 0x63, 0x51, 0x25, 0x7a, 0x27, 0xc5, + 0x25, 0x28, 0x53, 0xe1, 0x08, 0x34, 0x55, 0x23, 0x96, 0x70, 0x80, 0xdb, 0x8b, 0xa7, 0x01, 0xa1, 0x20, 0xd5, 0x5d, + 0xdb, 0x15, 0x79, 0xcb, 0x8e, 0x36, 0xb7, 0x60, 0x16, 0x5b, 0xad, 0xcb, 0xd6, 0x57, 0x36, 0xd9, 0x7d, 0x5c, 0x13, + 0x6c, 0xbb, 0xb7, 0x41, 0xc2, 0x5b, 0x7a, 0x43, 0x36, 0x37, 0xfd, 0x7e, 0x08, 0xfd, 0x21, 0x54, 0x77, 0xe8, 0xb6, + 0xb3, 0x43, 0xb7, 0x3e, 0xf3, 0x6b, 0xf5, 0x7c, 0xca, 0x1b, 0xe2, 0x03, 0x9a, 0x68, 0xd1, 0x55, 0x7c, 0x07, 0x9b, + 0x3a, 0xaa, 0xa8, 0xaa, 0x3c, 0x4a, 0x28, 0xa8, 0x80, 0x33, 0x5e, 0x9e, 0x72, 0x8c, 0x6d, 0xaa, 0x9f, 0xde, 0x69, + 0x5e, 0x6d, 0x6d, 0xd6, 0x66, 0xb9, 0x3e, 0x07, 0x8b, 0x80, 0x73, 0x1e, 0x5d, 0x69, 0x5a, 0x72, 0xe9, 0x31, 0xf5, + 0x67, 0x38, 0x2a, 0xc1, 0x45, 0x9c, 0xe5, 0x3c, 0x0d, 0xe8, 0x45, 0xb3, 0xff, 0xa1, 0xb6, 0x95, 0x5a, 0x36, 0xce, + 0xdc, 0xeb, 0x90, 0x6c, 0xfe, 0xc7, 0x06, 0xea, 0x4d, 0x88, 0x11, 0x51, 0xcd, 0x82, 0x3e, 0x61, 0x10, 0x1b, 0x33, + 0x28, 0xd7, 0x49, 0xc2, 0xcb, 0x32, 0x30, 0x4a, 0xad, 0x35, 0x5b, 0x9b, 0xf3, 0xec, 0x11, 0x3b, 0x7a, 0xd4, 0x63, + 0xec, 0x96, 0xd0, 0x44, 0xeb, 0x84, 0x4c, 0x8d, 0x91, 0xa7, 0x05, 0xd2, 0x1d, 0x8a, 0xb2, 0x8b, 0xf0, 0x04, 0x85, + 0x2c, 0xed, 0x7d, 0x6e, 0x4e, 0x64, 0xf5, 0x8d, 0x36, 0xba, 0x88, 0x54, 0x22, 0xc8, 0xc6, 0x6f, 0x10, 0xb0, 0x17, + 0x9a, 0x1d, 0x90, 0xcd, 0x92, 0x9d, 0xd2, 0x33, 0x6b, 0x02, 0x03, 0xaf, 0x4f, 0x54, 0xa2, 0x19, 0x65, 0x45, 0x74, + 0x95, 0x91, 0xcb, 0x5d, 0x48, 0xa2, 0xb3, 0x90, 0xf8, 0xb9, 0x61, 0x69, 0x5d, 0x87, 0x28, 0x66, 0x36, 0x1b, 0x5e, + 0x75, 0xf7, 0x51, 0x63, 0x5b, 0x19, 0x9f, 0xea, 0x5b, 0x9b, 0x46, 0xa6, 0xd0, 0xd7, 0xe1, 0xa4, 0xdf, 0x87, 0xbf, + 0x9a, 0x7e, 0xe0, 0x2d, 0x05, 0x7f, 0xb1, 0x47, 0xa4, 0x4e, 0x58, 0x00, 0x70, 0x84, 0x39, 0xaf, 0x9a, 0x13, 0xf8, + 0x88, 0x1d, 0x6d, 0x1e, 0x85, 0xa7, 0x8d, 0x99, 0xbb, 0x0b, 0xf1, 0x52, 0x95, 0xf4, 0xbc, 0x79, 0x32, 0x03, 0xb1, + 0x0a, 0xcd, 0x7e, 0xbd, 0x65, 0x56, 0x9f, 0x00, 0x44, 0xea, 0xd6, 0x3a, 0x94, 0xe2, 0xc7, 0xa6, 0xcb, 0x64, 0x93, + 0xb2, 0x36, 0x13, 0xa5, 0x54, 0x24, 0xcd, 0x45, 0x00, 0xfd, 0x86, 0xe1, 0xa8, 0x01, 0xde, 0x5b, 0x8f, 0xbd, 0x19, + 0x1a, 0x6f, 0x4c, 0x0d, 0x3d, 0xdb, 0xe8, 0xe5, 0xed, 0x28, 0x84, 0x19, 0x8b, 0xe8, 0xd6, 0x1d, 0x8b, 0xe1, 0x29, + 0x3d, 0x81, 0x0a, 0xdf, 0x84, 0x18, 0x4d, 0x97, 0xd4, 0xf5, 0x74, 0xad, 0xb6, 0xd2, 0x0d, 0xa1, 0x39, 0x46, 0xf1, + 0xf1, 0xda, 0x76, 0x47, 0x8d, 0xd0, 0x9e, 0x50, 0x1e, 0xde, 0xd2, 0x8a, 0xde, 0x58, 0x16, 0xc1, 0xc9, 0x8f, 0xbd, + 0xfc, 0x84, 0x9e, 0x7b, 0x02, 0x93, 0xa2, 0xad, 0x01, 0xfc, 0x01, 0xf5, 0xc3, 0x59, 0x3d, 0xb5, 0x52, 0x0e, 0x4f, + 0xe1, 0x4b, 0x36, 0x20, 0x57, 0xd0, 0x8b, 0x35, 0x66, 0x47, 0x31, 0xe8, 0xa0, 0x76, 0x76, 0x87, 0x37, 0x29, 0x65, + 0x88, 0xd6, 0x77, 0x0e, 0xe2, 0xe9, 0x1f, 0xa0, 0xe9, 0x83, 0xb4, 0x30, 0xa5, 0x6b, 0x14, 0xf0, 0x80, 0xbe, 0xa9, + 0xdf, 0xcf, 0xf1, 0xb9, 0xf6, 0x2c, 0xb1, 0xb0, 0xc7, 0x4b, 0x42, 0x97, 0x5e, 0xdc, 0x28, 0x90, 0x36, 0x3b, 0x56, + 0x01, 0x58, 0x91, 0x04, 0x1a, 0x91, 0x80, 0xa5, 0x8e, 0x27, 0x2e, 0xdb, 0xa0, 0x01, 0x49, 0x54, 0x52, 0xc8, 0x12, + 0x49, 0xe0, 0x87, 0x11, 0x84, 0x28, 0x8a, 0x41, 0xdc, 0xab, 0x97, 0x57, 0x5c, 0x53, 0x03, 0x4e, 0x14, 0xc1, 0x04, + 0xeb, 0x74, 0x0a, 0xc4, 0x56, 0xac, 0x57, 0xe0, 0x79, 0xe9, 0x38, 0x71, 0x64, 0x09, 0xd0, 0x20, 0xcd, 0x97, 0x4e, + 0xbb, 0xe5, 0xed, 0x89, 0x96, 0x2a, 0x36, 0xf7, 0x5e, 0x2c, 0x2c, 0xf7, 0x58, 0xf9, 0xdb, 0x81, 0xf6, 0xc2, 0x6a, + 0x47, 0x44, 0x0d, 0x56, 0x76, 0x6d, 0xbb, 0x36, 0x94, 0x86, 0xea, 0x5e, 0x39, 0x26, 0xa0, 0xa2, 0xab, 0xb8, 0x5a, + 0x46, 0xd9, 0x08, 0xfe, 0x6c, 0xb7, 0xc1, 0x7e, 0x00, 0x16, 0x90, 0xbf, 0xbe, 0xff, 0x39, 0xc2, 0xf0, 0x4c, 0xbf, + 0xbe, 0xff, 0x79, 0xbb, 0x7d, 0x36, 0x1e, 0x1b, 0xae, 0xc0, 0xa9, 0x75, 0x80, 0x3f, 0x30, 0x6c, 0x83, 0x5d, 0xb2, + 0xdb, 0xed, 0x33, 0xe0, 0x20, 0x14, 0xdb, 0x60, 0x76, 0xb1, 0x72, 0xe4, 0x52, 0xac, 0x86, 0xde, 0x91, 0x80, 0x55, + 0xb7, 0xc3, 0x52, 0xec, 0x52, 0x1f, 0x15, 0x82, 0x51, 0x2f, 0xfa, 0x97, 0x9d, 0x02, 0x4b, 0x0a, 0xa6, 0xab, 0xc1, + 0xb2, 0xaa, 0x56, 0x65, 0xb4, 0xbf, 0x1f, 0xaf, 0xb2, 0x51, 0x99, 0xc1, 0x36, 0x2f, 0xaf, 0x2f, 0x01, 0x50, 0x21, + 0xa0, 0x8d, 0x77, 0x6b, 0x91, 0x99, 0x17, 0x0b, 0xba, 0xcc, 0x70, 0x4d, 0x82, 0xd9, 0x41, 0xce, 0xad, 0x6e, 0x72, + 0x4a, 0xec, 0x03, 0xd8, 0x1c, 0x6e, 0xb7, 0x0d, 0x7e, 0xe1, 0x68, 0xf4, 0x6c, 0xb6, 0xcc, 0xb4, 0x41, 0x27, 0x37, + 0xfb, 0x9f, 0x44, 0x5e, 0x1a, 0x2a, 0x3e, 0xc9, 0xf4, 0x65, 0x06, 0x7c, 0x1e, 0x7b, 0x2b, 0x42, 0x9f, 0xe5, 0x6a, + 0xb4, 0x06, 0xd8, 0xd8, 0xec, 0xe2, 0x6e, 0x94, 0x72, 0x88, 0x48, 0x11, 0x58, 0x75, 0xcd, 0x32, 0x23, 0xbe, 0x4d, + 0xc5, 0x5d, 0x4b, 0x15, 0xf6, 0x56, 0x78, 0xce, 0x2a, 0xdc, 0x38, 0xca, 0xf4, 0x26, 0x51, 0xf8, 0x12, 0x85, 0xa8, + 0x1c, 0x8d, 0xe9, 0x9c, 0x40, 0x2a, 0xf3, 0x98, 0x50, 0xcc, 0xe1, 0xde, 0xfd, 0x9a, 0x3a, 0x73, 0x19, 0x5f, 0xb8, + 0xf7, 0xd2, 0x97, 0x99, 0xdc, 0x4a, 0x00, 0x45, 0x52, 0xb5, 0xff, 0xf2, 0x19, 0xa9, 0xf1, 0x3f, 0x53, 0xad, 0x01, + 0xe8, 0xfd, 0x02, 0x35, 0x39, 0x82, 0x80, 0xad, 0x98, 0xfa, 0x68, 0xfa, 0x56, 0x32, 0xff, 0x01, 0x75, 0x3b, 0x82, + 0x6d, 0x54, 0xfc, 0x9c, 0xa8, 0xa2, 0x05, 0x4f, 0xd7, 0x22, 0x8d, 0x45, 0x72, 0x17, 0xf1, 0x7a, 0x8a, 0x25, 0x31, + 0x1b, 0x21, 0xeb, 0x97, 0x66, 0x17, 0x7e, 0x2e, 0x1a, 0x26, 0xe0, 0xb4, 0xf4, 0xb7, 0x95, 0xb7, 0x99, 0x2c, 0xe3, + 0x8c, 0x4c, 0xb9, 0x42, 0xec, 0xb6, 0xfa, 0x1e, 0x73, 0x82, 0x3f, 0x3d, 0x78, 0x4a, 0xe8, 0xad, 0x9c, 0x96, 0x08, + 0x4a, 0x27, 0x52, 0xeb, 0xaa, 0x89, 0xfd, 0x9a, 0x42, 0x14, 0x07, 0xc1, 0x20, 0x74, 0xa7, 0x69, 0x9f, 0xe2, 0xfb, + 0x6c, 0xd9, 0x6f, 0x4d, 0xd9, 0x92, 0x6c, 0x04, 0x74, 0x4c, 0x3a, 0x6f, 0x4f, 0x6f, 0xcf, 0xce, 0xbc, 0xdf, 0xa0, + 0x09, 0x07, 0xd5, 0x0d, 0xb4, 0xab, 0x20, 0xd3, 0x18, 0xc5, 0x66, 0x31, 0xd6, 0x6e, 0x4d, 0x44, 0x10, 0x74, 0xba, + 0x9c, 0x85, 0xed, 0x76, 0x42, 0x7c, 0x09, 0x24, 0x50, 0xe0, 0xca, 0x45, 0x39, 0x09, 0x89, 0xba, 0x90, 0xe9, 0xc9, + 0xba, 0x96, 0x2c, 0xd0, 0x6b, 0xec, 0x20, 0xa0, 0xc7, 0xdc, 0x3e, 0x05, 0xf4, 0x7d, 0xc1, 0x8e, 0xf9, 0x20, 0x18, + 0x62, 0x7c, 0xd5, 0x80, 0xde, 0x48, 0xf5, 0x08, 0x1e, 0xc2, 0xc0, 0x72, 0xd1, 0x57, 0x05, 0x43, 0x58, 0xa1, 0xbf, + 0x52, 0x36, 0xf9, 0xe6, 0xef, 0x6e, 0x7e, 0xcf, 0xb5, 0x98, 0x1d, 0x84, 0xe2, 0xf6, 0x7a, 0x02, 0xc4, 0xaf, 0xe2, + 0x57, 0x60, 0x5d, 0xad, 0x25, 0xde, 0x6e, 0x7a, 0xfe, 0x14, 0xbe, 0x1c, 0xdd, 0x7e, 0x52, 0x9a, 0x4f, 0x20, 0x48, + 0x8d, 0x93, 0x94, 0xbb, 0xef, 0x3e, 0x4a, 0x57, 0x11, 0x8c, 0x16, 0x20, 0xd6, 0xdd, 0x5b, 0xc9, 0x59, 0x53, 0xf8, + 0x8f, 0x75, 0xbe, 0xc7, 0xd8, 0x21, 0xf2, 0x14, 0xa7, 0xbf, 0x01, 0x86, 0x7d, 0xe7, 0xdf, 0xca, 0xac, 0x21, 0xd1, + 0xb9, 0xfa, 0x08, 0xe8, 0xff, 0x58, 0x8f, 0xdf, 0x31, 0x4a, 0xfa, 0x92, 0x38, 0x47, 0xb8, 0x22, 0x5e, 0xa2, 0xa9, + 0x5e, 0x6f, 0x5c, 0xd3, 0x4f, 0x85, 0x79, 0xa1, 0x15, 0x1c, 0xf6, 0xad, 0x51, 0x78, 0xe0, 0x99, 0xf7, 0x9b, 0x68, + 0x08, 0xba, 0x7f, 0xc7, 0xbd, 0xf1, 0x9b, 0x60, 0x19, 0xde, 0x94, 0xb3, 0xcc, 0xdc, 0xe1, 0x6e, 0x32, 0x91, 0xca, + 0x1b, 0xc6, 0x82, 0xb5, 0x50, 0xe6, 0xab, 0x69, 0x30, 0xdb, 0xd4, 0x91, 0x4a, 0x76, 0xdf, 0xbf, 0x6d, 0x9c, 0xb0, + 0xd9, 0x20, 0x38, 0xad, 0x64, 0x11, 0x5f, 0xf2, 0x60, 0xaa, 0x55, 0x14, 0x59, 0xd6, 0xef, 0x67, 0x80, 0x0c, 0xe3, + 0xb4, 0x77, 0xf0, 0x64, 0xa9, 0x99, 0x09, 0x71, 0x6d, 0x75, 0x16, 0xf0, 0xd6, 0x8c, 0xe6, 0x71, 0x05, 0xbb, 0xcc, + 0x57, 0x52, 0xfc, 0xd9, 0x92, 0x64, 0x63, 0xfd, 0x0d, 0x19, 0xb6, 0x95, 0xcf, 0x9c, 0x03, 0xc6, 0xcc, 0x8d, 0x54, + 0x41, 0xee, 0x7a, 0xc0, 0x08, 0x21, 0x11, 0x10, 0xce, 0x62, 0xe2, 0x4e, 0x98, 0xf0, 0x8f, 0x2e, 0x30, 0x4e, 0x8c, + 0x81, 0x71, 0x3e, 0xca, 0x90, 0xd3, 0x63, 0x3e, 0x48, 0x1a, 0xb3, 0xf5, 0xa7, 0x2a, 0x91, 0x5e, 0x4b, 0x42, 0xcf, + 0xe0, 0xf7, 0xb8, 0xc5, 0x03, 0x35, 0x82, 0x53, 0xba, 0x9b, 0xd3, 0xfe, 0xab, 0x82, 0x0c, 0xff, 0x02, 0xef, 0xae, + 0xd8, 0x5e, 0x96, 0x13, 0x58, 0xdc, 0xb1, 0x57, 0x3c, 0xcd, 0x55, 0x8b, 0x13, 0xe2, 0x11, 0x8b, 0xdc, 0x27, 0x16, + 0x30, 0xa2, 0x86, 0xd1, 0xf8, 0xf1, 0xf4, 0xe4, 0xad, 0xc6, 0x6c, 0xca, 0xfd, 0x0f, 0x60, 0x44, 0xb5, 0xb4, 0xdd, + 0x0e, 0xf8, 0x72, 0x84, 0x06, 0xdb, 0xa9, 0x1b, 0xec, 0x7e, 0xdf, 0xa4, 0x1d, 0x95, 0x5e, 0x36, 0x27, 0x06, 0xdd, + 0x51, 0xda, 0x2c, 0x95, 0x41, 0x6d, 0x57, 0xe1, 0x68, 0x3e, 0x6b, 0xc4, 0xaa, 0xde, 0x87, 0xe1, 0x92, 0xc6, 0x56, + 0x56, 0x6e, 0x77, 0x13, 0x8e, 0x6c, 0x02, 0x5c, 0x9f, 0x82, 0xb2, 0x6a, 0xce, 0x41, 0x0b, 0x3a, 0x13, 0x38, 0xa2, + 0xed, 0x36, 0x84, 0x08, 0x1c, 0xc5, 0x70, 0x32, 0x0b, 0x8b, 0xe1, 0x50, 0x0d, 0x7c, 0x41, 0x48, 0xf4, 0xa9, 0x98, + 0x67, 0x0b, 0x85, 0xd8, 0xe3, 0xef, 0xa4, 0xdf, 0x0a, 0xc5, 0x29, 0xf7, 0x7e, 0x13, 0x64, 0xf3, 0x7b, 0x8a, 0x31, + 0x07, 0x9d, 0x66, 0x33, 0x03, 0x09, 0xeb, 0x71, 0x45, 0xd4, 0x3a, 0xb2, 0xb3, 0x01, 0xaa, 0x58, 0x34, 0x85, 0x05, + 0x75, 0x8b, 0x27, 0xd6, 0x33, 0x7a, 0x0f, 0x2a, 0x41, 0x54, 0x0b, 0x76, 0x63, 0xb8, 0xd6, 0x3e, 0x89, 0x50, 0x52, + 0x4e, 0x9a, 0xcc, 0x8c, 0x15, 0x0d, 0x16, 0x20, 0x24, 0x8d, 0xcb, 0xea, 0x8d, 0x4c, 0xb3, 0x8b, 0x0c, 0x10, 0x13, + 0x9c, 0xff, 0x9c, 0x6c, 0xbc, 0x79, 0xae, 0xe6, 0xa5, 0x2b, 0x71, 0x66, 0x61, 0x3e, 0xba, 0xde, 0xd2, 0x82, 0x44, + 0x05, 0xd0, 0x28, 0x5f, 0xcb, 0xf3, 0xd3, 0x8e, 0x55, 0xc8, 0xee, 0x87, 0x53, 0x65, 0x3b, 0xc4, 0x8f, 0x58, 0x45, + 0xbc, 0xd3, 0xba, 0x52, 0x22, 0x8d, 0x8e, 0xb6, 0x01, 0x31, 0x6c, 0xd9, 0xb7, 0xa8, 0xe1, 0x83, 0x30, 0x83, 0x4e, + 0xf2, 0x83, 0x9e, 0xd1, 0xb1, 0x35, 0x90, 0xf4, 0xb5, 0x08, 0xbe, 0x46, 0x47, 0x3a, 0x51, 0xa6, 0x91, 0x98, 0x42, + 0xa2, 0x5f, 0x2f, 0xb4, 0xc6, 0x32, 0xca, 0xbe, 0x22, 0xff, 0x7b, 0xdd, 0xbd, 0xdf, 0xc4, 0x76, 0x0b, 0x93, 0xec, + 0x79, 0x5c, 0xc1, 0xa6, 0x46, 0xad, 0x10, 0xce, 0xce, 0x71, 0x85, 0xda, 0xb1, 0x5e, 0x58, 0x02, 0x79, 0x00, 0x5b, + 0x91, 0x06, 0x65, 0x90, 0xec, 0x53, 0x31, 0x17, 0x0b, 0x27, 0xca, 0x91, 0x0a, 0xef, 0x4b, 0x8e, 0x52, 0x0e, 0x57, + 0xb1, 0xb0, 0x60, 0xc8, 0xaf, 0x8e, 0x2e, 0x0a, 0x79, 0x05, 0x92, 0x12, 0xc3, 0x50, 0x59, 0x5e, 0x17, 0x57, 0x6d, + 0x49, 0x68, 0xef, 0x0c, 0x40, 0x58, 0x0a, 0x10, 0xbc, 0x34, 0x6a, 0x88, 0xd9, 0x46, 0xed, 0xae, 0xe8, 0x5e, 0x72, + 0x40, 0x9d, 0xee, 0xda, 0xad, 0x37, 0x65, 0x9b, 0x6d, 0xc5, 0x85, 0x7f, 0x42, 0xe9, 0xc7, 0x7c, 0x50, 0xf8, 0x54, + 0x02, 0x37, 0xbe, 0xda, 0x64, 0xd9, 0xc5, 0x1d, 0x2e, 0xfd, 0xaa, 0x31, 0x7e, 0xfd, 0x7e, 0x4f, 0x2d, 0x84, 0x46, + 0x2a, 0x30, 0xdf, 0x3e, 0x33, 0x55, 0x19, 0x4d, 0xa9, 0xbd, 0x04, 0x57, 0xce, 0x7e, 0x04, 0x15, 0x71, 0x5d, 0x91, + 0xc9, 0xd4, 0x00, 0xed, 0x79, 0x59, 0xe1, 0x56, 0x16, 0xe0, 0xb1, 0x13, 0x90, 0xed, 0x96, 0x87, 0x81, 0x3e, 0x74, + 0x02, 0x7f, 0x4b, 0x9e, 0x22, 0xb3, 0x66, 0x1f, 0x7f, 0xd1, 0x82, 0x7f, 0x6c, 0xc1, 0xcf, 0x28, 0xee, 0xb4, 0x32, + 0xff, 0x56, 0x5a, 0xb7, 0xb8, 0x7f, 0x27, 0xd3, 0x84, 0xa2, 0x32, 0xa1, 0xf6, 0x2b, 0xfd, 0x97, 0x09, 0x96, 0xa4, + 0xb2, 0x7f, 0x90, 0xf0, 0xc1, 0xac, 0xf1, 0xc4, 0x1a, 0x4f, 0x86, 0xd3, 0xad, 0x34, 0x0c, 0x01, 0x0a, 0xfd, 0xbc, + 0xcc, 0x15, 0xd5, 0xcf, 0xbf, 0xac, 0xf9, 0x9a, 0x37, 0x5b, 0x6c, 0x93, 0x1e, 0x68, 0xb0, 0x97, 0x47, 0x53, 0x0a, + 0x27, 0x51, 0xe7, 0x46, 0xa2, 0x2e, 0x6a, 0x96, 0xa1, 0x3a, 0xc1, 0xab, 0x79, 0xaa, 0x87, 0xbd, 0x99, 0x88, 0xd6, + 0x4a, 0xca, 0x12, 0x03, 0xd6, 0x3a, 0xf2, 0x90, 0xdc, 0xad, 0x75, 0xdc, 0x69, 0xa8, 0x4b, 0x53, 0x28, 0x01, 0x56, + 0xb8, 0x00, 0x47, 0xd0, 0xcf, 0x45, 0xc8, 0xe1, 0x9a, 0xaa, 0xf4, 0x0b, 0x9a, 0x92, 0x27, 0x9e, 0xa2, 0x56, 0x2b, + 0xd2, 0xed, 0x47, 0x39, 0x76, 0xc3, 0x37, 0x4e, 0xc8, 0x89, 0x11, 0xfa, 0xbb, 0x63, 0x29, 0x67, 0x68, 0xf1, 0xa0, + 0x4e, 0xb0, 0x5e, 0xde, 0x52, 0xa0, 0x98, 0xa3, 0xcb, 0xaa, 0x6b, 0x5e, 0xa3, 0xed, 0xcb, 0xb2, 0xdf, 0xcf, 0x6d, + 0x3d, 0x29, 0x3b, 0xda, 0x2c, 0xcd, 0x3e, 0x44, 0xc5, 0x14, 0xee, 0xfa, 0x44, 0xf3, 0x57, 0xa1, 0xbe, 0x6a, 0xcb, + 0x9c, 0x8f, 0x38, 0xe2, 0x62, 0xe4, 0xa4, 0xfe, 0x45, 0x4d, 0xbd, 0x12, 0xf7, 0xab, 0x4a, 0xbe, 0x13, 0xc6, 0x8a, + 0xd1, 0x01, 0xf5, 0xa7, 0x4a, 0xe5, 0xfd, 0xb2, 0x00, 0xb8, 0x27, 0xc1, 0x3e, 0x81, 0x7d, 0x85, 0x46, 0xf8, 0x6d, + 0x09, 0xf8, 0x37, 0x8a, 0x1b, 0xb0, 0x0a, 0x0c, 0x30, 0x9a, 0x6c, 0xcf, 0x69, 0x02, 0x07, 0x9c, 0xd0, 0x2a, 0x0a, + 0x2a, 0xcc, 0xd0, 0x50, 0x5b, 0x18, 0x3d, 0x45, 0x19, 0xb7, 0xca, 0xec, 0xdd, 0x18, 0x3b, 0x2d, 0xf0, 0x1a, 0xfe, + 0x7c, 0x5e, 0xe8, 0x61, 0xa3, 0x0e, 0xd2, 0xa3, 0x93, 0x98, 0xfe, 0xb8, 0x85, 0x93, 0x9b, 0x85, 0xb3, 0xac, 0x59, + 0x02, 0xdd, 0x81, 0x0b, 0x62, 0xdc, 0xef, 0xe7, 0x70, 0x64, 0x9a, 0x91, 0x2f, 0x58, 0x4e, 0x63, 0xb6, 0xa4, 0xda, + 0xd3, 0xee, 0xb2, 0x0a, 0x73, 0xba, 0xb4, 0x32, 0xde, 0x94, 0x81, 0xca, 0x68, 0xbb, 0x0d, 0xe1, 0x4f, 0xb7, 0xb5, + 0x4b, 0x3a, 0x5f, 0x42, 0x06, 0xf8, 0x03, 0x12, 0x51, 0xc4, 0xbe, 0xfe, 0xb7, 0x1a, 0xa7, 0xf4, 0x44, 0x69, 0xcd, + 0x12, 0xba, 0x66, 0xba, 0x7e, 0x7a, 0xc1, 0xd6, 0x8d, 0xa5, 0xb0, 0xdd, 0x86, 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, 0xf9, 0x50, 0x99, 0xaf, 0x8d, 0x47, 0xdc, 0xbf, 0xd2, 0x30, 0x31, 0x45, 0xa2, 0x42, 0x74, 0xf6, + 0x1b, 0xc8, 0x72, 0x04, 0xe0, 0x58, 0x9e, 0xca, 0x9a, 0xfe, 0x98, 0x42, 0x1c, 0x74, 0x68, 0xd0, 0xbb, 0x42, 0x5e, + 0x65, 0x25, 0x0f, 0xf1, 0x9e, 0xe0, 0x69, 0x46, 0xef, 0x37, 0xf8, 0xd0, 0xd6, 0x1e, 0x3d, 0x41, 0x36, 0x9e, 0x72, + 0xbf, 0xfe, 0x4e, 0x84, 0x73, 0x88, 0x56, 0xb9, 0xa0, 0x5a, 0x5d, 0xed, 0x00, 0xa8, 0x3c, 0xdb, 0xab, 0x47, 0x70, + 0xba, 0xe9, 0xeb, 0x5b, 0x15, 0x3a, 0x73, 0x00, 0x69, 0x0f, 0xc9, 0xba, 0xe6, 0x7a, 0x07, 0xb8, 0x23, 0xb1, 0x5a, + 0x03, 0x8d, 0x75, 0x5b, 0xb3, 0xd3, 0x1e, 0xc5, 0x63, 0x22, 0x33, 0x63, 0x91, 0x62, 0xcc, 0xdd, 0x3a, 0x2d, 0x8a, + 0x36, 0x68, 0x86, 0xb0, 0x7b, 0xd7, 0xe1, 0xeb, 0x56, 0x84, 0xf5, 0xfb, 0x6d, 0x5f, 0x60, 0x34, 0x8c, 0xb9, 0x76, + 0xcf, 0x33, 0x74, 0xc3, 0x06, 0xdb, 0xc8, 0x79, 0x88, 0x7c, 0x98, 0xa9, 0x03, 0x51, 0xd6, 0xd6, 0x80, 0xed, 0x11, + 0xd7, 0x9b, 0x56, 0xf1, 0xf3, 0x2a, 0xe6, 0x6c, 0xcf, 0x1a, 0xa7, 0xb4, 0xbe, 0xc6, 0x35, 0xc7, 0x55, 0x21, 0xa2, + 0xb6, 0x9e, 0xf1, 0x30, 0xec, 0x7c, 0x81, 0x3b, 0xb3, 0xc2, 0xe0, 0x45, 0x58, 0x2a, 0xd9, 0xa9, 0x5c, 0x7f, 0x0e, + 0x5b, 0x1c, 0xa4, 0xf2, 0xa5, 0xd7, 0xdf, 0x7f, 0xf9, 0xe2, 0x0b, 0x74, 0x53, 0x73, 0x7e, 0x04, 0x41, 0x26, 0xd0, + 0x21, 0x4b, 0xa9, 0x1e, 0xbf, 0x2b, 0x80, 0xda, 0xc3, 0x3c, 0x7c, 0x57, 0x30, 0x11, 0x5f, 0x67, 0x97, 0x71, 0x25, + 0x8b, 0xd1, 0x35, 0x17, 0xa9, 0x2c, 0xac, 0xd4, 0x38, 0x38, 0x5e, 0xad, 0x72, 0x1e, 0x80, 0xa9, 0xbc, 0x65, 0x94, + 0x6d, 0x65, 0x99, 0x1e, 0x5c, 0x2d, 0x4f, 0xaf, 0xb4, 0xe8, 0xbc, 0xbc, 0xbe, 0x0c, 0x22, 0xfc, 0x75, 0x6e, 0x7e, + 0x5c, 0xc5, 0xe5, 0xc7, 0x20, 0xb2, 0x36, 0x75, 0xe6, 0x07, 0x4a, 0xe5, 0xc1, 0x7f, 0x0a, 0x64, 0xba, 0xdf, 0x15, + 0x60, 0x99, 0x6d, 0x2b, 0x3e, 0x8c, 0xb1, 0xd6, 0xe1, 0x84, 0xcc, 0x54, 0x89, 0xde, 0xbb, 0x64, 0x5d, 0x80, 0xb5, + 0x9f, 0xc2, 0x32, 0x56, 0xb9, 0x66, 0x58, 0x99, 0xaa, 0xc8, 0xcc, 0xca, 0x9a, 0xed, 0x87, 0xd6, 0x89, 0x66, 0x8e, + 0xde, 0x02, 0xfa, 0x81, 0xec, 0x5f, 0xd2, 0x72, 0xcd, 0x3c, 0x1f, 0x9b, 0xc6, 0xeb, 0x47, 0xfb, 0x97, 0x6e, 0xc1, + 0xde, 0xda, 0x3b, 0x39, 0x0a, 0x13, 0xc1, 0xb3, 0xd6, 0x8c, 0x2f, 0xf2, 0xac, 0x80, 0x95, 0x33, 0x19, 0x8f, 0xa9, + 0xb7, 0xb4, 0x5a, 0x37, 0x47, 0x87, 0xe4, 0x9a, 0x3d, 0xae, 0x1e, 0x73, 0xb2, 0xcf, 0x5b, 0xa6, 0xb6, 0x6d, 0xeb, + 0x38, 0x4f, 0x93, 0xaf, 0x4c, 0xf7, 0xc5, 0xda, 0x46, 0x44, 0x57, 0xce, 0x7d, 0xce, 0x2b, 0xb8, 0xf5, 0x4d, 0x69, + 0xe8, 0xb5, 0x04, 0x20, 0x3a, 0x6d, 0xc0, 0x5f, 0xb0, 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, 0xb1, 0xbb, 0xca, 0xa5, 0x13, 0xf5, + 0x5b, 0x26, 0x5c, 0xb9, 0x12, 0x04, 0x64, 0x5a, 0xb0, 0x5e, 0x61, 0x76, 0x91, 0x5c, 0x03, 0x21, 0x03, 0xc3, 0xd7, + 0x60, 0x2d, 0x4a, 0x6e, 0xac, 0x60, 0xbd, 0x7b, 0xbe, 0x4e, 0x10, 0x52, 0xf0, 0xc0, 0x4d, 0xd0, 0x0f, 0xad, 0x9b, + 0xb7, 0xa3, 0x44, 0x19, 0xc4, 0xe3, 0xd6, 0x4e, 0x39, 0x48, 0x20, 0x00, 0xf7, 0x54, 0x85, 0xe0, 0x50, 0x20, 0xeb, + 0xe0, 0x6a, 0xc6, 0x11, 0x5c, 0x5d, 0x39, 0x73, 0x71, 0x03, 0xb0, 0xae, 0xfc, 0xb9, 0x6c, 0x70, 0x61, 0x3d, 0xa2, + 0xca, 0x9c, 0x71, 0x8a, 0x41, 0x8c, 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, 0x20, 0x0a, 0xb5, 0x01, 0x43, 0xe0, 0x90, 0xf8, 0x83, 0x41, 0xa8, 0xf1, 0x4e, 0x06, 0x2a, 0x20, 0x16, + 0xf1, 0x78, 0x6c, 0xc4, 0xcd, 0x0a, 0xc7, 0x43, 0x0c, 0x7e, 0xd5, 0x7c, 0x41, 0x02, 0x42, 0x4d, 0x69, 0xe8, 0xf2, + 0x18, 0x0e, 0x27, 0x7b, 0x13, 0x48, 0xc5, 0xcc, 0x4c, 0x15, 0xc6, 0xc6, 0x24, 0x82, 0x78, 0xa7, 0x9d, 0xf5, 0x42, + 0xb9, 0xdd, 0x35, 0x1a, 0xc8, 0x95, 0xc1, 0x17, 0x55, 0x3c, 0xd9, 0x1b, 0x76, 0x55, 0x8c, 0xa3, 0x70, 0x6d, 0x94, + 0x6f, 0x67, 0x87, 0x00, 0x5e, 0x7b, 0x36, 0xf4, 0xe5, 0x12, 0x67, 0xfb, 0x4f, 0xc9, 0xe3, 0xa7, 0x84, 0x9e, 0xb1, + 0xb3, 0xaf, 0x9e, 0xd2, 0x33, 0x45, 0x4e, 0xf6, 0x26, 0xd1, 0x35, 0xb3, 0x98, 0x2f, 0x07, 0xaa, 0x09, 0xf4, 0x72, + 0xb4, 0x16, 0x6a, 0x81, 0x69, 0x87, 0xa6, 0xf0, 0xdb, 0xf1, 0x5e, 0x30, 0xb8, 0x6e, 0x37, 0xfd, 0xba, 0xdd, 0x56, + 0xcf, 0xab, 0x6b, 0xef, 0x20, 0xda, 0x2d, 0x66, 0xf2, 0xf7, 0xf1, 0x9e, 0x9b, 0x03, 0xac, 0xef, 0xe1, 0x31, 0x31, + 0x4d, 0xda, 0x19, 0x15, 0xbf, 0xa6, 0x27, 0xd8, 0x87, 0x66, 0x91, 0x1d, 0x7d, 0x18, 0xfe, 0x5b, 0x9d, 0xa8, 0xcf, + 0xbe, 0x3a, 0x00, 0x72, 0x04, 0x32, 0x50, 0x2c, 0x11, 0xcc, 0x70, 0xa0, 0x29, 0xa0, 0x20, 0xd3, 0xe3, 0x4e, 0xf5, + 0xf0, 0xab, 0x51, 0x53, 0x33, 0x72, 0x0d, 0x53, 0x83, 0x6d, 0xc1, 0x0f, 0x54, 0x37, 0xf4, 0x37, 0x1a, 0xdd, 0x48, + 0x3b, 0x99, 0x99, 0x97, 0xd4, 0xc6, 0x75, 0xbb, 0x86, 0x00, 0xc6, 0x0e, 0x5e, 0x50, 0xb2, 0xaf, 0x0f, 0x2f, 0xf7, + 0x70, 0x15, 0x01, 0x4a, 0x16, 0x0b, 0xbe, 0x1e, 0x5c, 0xea, 0xcd, 0xbd, 0x17, 0x90, 0xc1, 0xd7, 0xc1, 0xd1, 0xd7, + 0x03, 0x39, 0x08, 0x0e, 0xf7, 0x2f, 0x8f, 0x02, 0x67, 0xdc, 0x0f, 0x21, 0x1e, 0x55, 0x45, 0x31, 0x13, 0xa6, 0x8a, + 0xc4, 0xd6, 0x9e, 0xdb, 0x7a, 0x95, 0xf1, 0x19, 0x4d, 0xa7, 0x16, 0xf9, 0x3b, 0x4c, 0x59, 0x6c, 0x7e, 0x07, 0x13, + 0x7e, 0x15, 0x44, 0x2e, 0x08, 0xea, 0x2c, 0x8f, 0x62, 0xba, 0x64, 0xb7, 0x22, 0x4c, 0x69, 0xb2, 0x9f, 0x13, 0x12, + 0x85, 0x4b, 0x05, 0x9e, 0xa7, 0x5e, 0x27, 0x10, 0xc7, 0xd5, 0x7d, 0x7e, 0x2b, 0xc2, 0x25, 0xcd, 0xf7, 0x13, 0xd2, + 0x2a, 0xc2, 0x45, 0x64, 0xd9, 0xd4, 0xf4, 0x82, 0x85, 0x2b, 0x7a, 0x09, 0xcc, 0x94, 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, 0xed, 0x4d, 0x6c, 0x4e, 0xf6, 0x32, 0x5a, 0x2b, 0x97, 0x55, 0xcb, 0x90, 0x14, 0x6b, 0x86, + 0xfc, 0x3d, 0x4a, 0x4e, 0xad, 0xc0, 0x93, 0x5d, 0xf0, 0x2a, 0x59, 0xfa, 0x07, 0x95, 0xb5, 0x1a, 0xb0, 0xc7, 0x88, + 0x65, 0xa1, 0x70, 0xec, 0xdf, 0x64, 0xac, 0x58, 0xfb, 0x02, 0x8d, 0x18, 0xb9, 0xb7, 0x37, 0x19, 0xf3, 0x62, 0xae, + 0x26, 0x6b, 0x2f, 0x54, 0x9d, 0x97, 0x9e, 0xb7, 0x78, 0x2f, 0xa7, 0xd4, 0x30, 0x12, 0xd1, 0xbd, 0xb1, 0x32, 0xa3, + 0x54, 0x89, 0x5a, 0x83, 0x46, 0x04, 0x1b, 0xbb, 0xe0, 0x97, 0xe0, 0x84, 0xca, 0x3d, 0x75, 0xb6, 0x6f, 0xa7, 0x54, + 0x7a, 0xc0, 0xb2, 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, + 0x24, 0x77, 0xb9, 0x6e, 0x05, 0xc9, 0x7d, 0x3a, 0x7e, 0xaa, 0x07, 0x3a, 0x5d, 0x6b, 0xc7, 0x43, 0x9f, 0xdf, 0x46, + 0x7c, 0x6d, 0xdd, 0x7b, 0xaa, 0xb5, 0x0a, 0x65, 0xa0, 0xc5, 0x8a, 0xca, 0x95, 0x5a, 0xd2, 0xfb, 0x5d, 0x04, 0xc0, + 0x22, 0x36, 0x66, 0xe3, 0x5d, 0xdb, 0xac, 0x10, 0x34, 0xba, 0xec, 0x68, 0x13, 0x0f, 0x58, 0xa2, 0x5b, 0x3b, 0x98, + 0xd0, 0xf8, 0x88, 0x95, 0xfd, 0x7e, 0x7e, 0x04, 0xf4, 0x54, 0x1b, 0x31, 0x15, 0x70, 0xe4, 0x7f, 0x69, 0x45, 0xa6, + 0x28, 0xb0, 0x59, 0x53, 0x77, 0x6b, 0x2c, 0x23, 0xd1, 0x97, 0x29, 0x5d, 0x9e, 0xf0, 0x0c, 0x98, 0xd6, 0xeb, 0x96, + 0xe3, 0xca, 0xae, 0xe2, 0xc8, 0x53, 0x61, 0x59, 0x71, 0x5e, 0x85, 0xe3, 0xad, 0xc7, 0x37, 0xd8, 0x37, 0x6c, 0xda, + 0x85, 0x3f, 0x84, 0xb0, 0x10, 0xde, 0x64, 0x70, 0x1b, 0xd1, 0x76, 0x12, 0xa8, 0xbc, 0x31, 0xd7, 0x09, 0x65, 0x73, + 0xbb, 0x5e, 0x7b, 0x06, 0xe9, 0xc4, 0x1c, 0x28, 0xd5, 0x08, 0x5a, 0xa3, 0x59, 0x50, 0x35, 0xe2, 0x91, 0xe3, 0xe1, + 0x9d, 0x41, 0xac, 0x96, 0x2f, 0x69, 0x2a, 0x45, 0x03, 0x30, 0x2e, 0x80, 0xcb, 0xd3, 0xaf, 0xef, 0x7f, 0x3e, 0xe5, + 0x71, 0x91, 0x2c, 0xdf, 0xc5, 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, 0xdd, 0x07, 0x20, 0x4f, 0xe3, 0x42, 0x1a, 0x49, 0x5d, 0x88, 0x31, 0x17, 0xf1, 0xba, 0x3e, 0x1e, 0x37, + 0xba, 0x5e, 0xb2, 0x67, 0xe3, 0x27, 0xd3, 0x37, 0x59, 0x98, 0x0d, 0x04, 0x19, 0x55, 0x4b, 0x2e, 0x5a, 0xa6, 0x9c, + 0xca, 0x24, 0x00, 0x7d, 0x3c, 0x7b, 0x8c, 0x1d, 0x8c, 0xc7, 0x64, 0xd3, 0x16, 0x0f, 0xf0, 0x70, 0xb9, 0x0e, 0x0b, + 0x32, 0xd3, 0x75, 0x44, 0x81, 0xe0, 0xb7, 0x55, 0x00, 0x48, 0x8e, 0xb6, 0x2a, 0xc3, 0xa5, 0xb1, 0x67, 0xe3, 0x09, + 0x95, 0xd8, 0xed, 0x90, 0xd4, 0x5e, 0x85, 0x6e, 0xe6, 0xa5, 0xef, 0x51, 0x24, 0x8d, 0xcb, 0xd2, 0x4e, 0xa5, 0x52, + 0xed, 0x99, 0x99, 0xeb, 0x1a, 0xc4, 0x60, 0x08, 0x75, 0xdd, 0xa5, 0x57, 0xf7, 0x6e, 0x73, 0xad, 0xd9, 0x0e, 0x78, + 0xaf, 0x41, 0x33, 0x94, 0xbc, 0xc5, 0xbc, 0x75, 0x45, 0xd4, 0x74, 0xb5, 0x06, 0xb3, 0x62, 0x94, 0x2d, 0x45, 0xe9, + 0x9a, 0x82, 0x52, 0x30, 0xba, 0x58, 0x7b, 0x0b, 0xf7, 0x8d, 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, 0xc7, + 0x15, 0x39, 0x06, 0x47, 0x2f, 0x93, 0xd3, 0x50, 0xe0, 0x1f, 0x33, 0x05, 0x62, 0x3a, 0x54, 0xf7, 0x1b, 0xdc, 0xfc, + 0xff, 0x28, 0x58, 0xe0, 0xf1, 0xad, 0x97, 0xb8, 0x8d, 0xfe, 0x51, 0xf8, 0xb4, 0xf4, 0xb9, 0xf4, 0x5d, 0x5d, 0x3c, + 0x69, 0x6f, 0x36, 0x4a, 0x96, 0x59, 0x9e, 0xbe, 0x95, 0x29, 0x07, 0x91, 0x19, 0x5a, 0x83, 0xb2, 0x23, 0xd1, 0xb8, + 0xe1, 0x81, 0x11, 0x63, 0xe3, 0xc6, 0xf7, 0x63, 0x06, 0xb2, 0x61, 0xb0, 0xfa, 0x66, 0xa9, 0x4c, 0xd6, 0x57, 0x80, + 0x29, 0xa2, 0xe4, 0x27, 0x2f, 0x73, 0x0e, 0x4f, 0xa1, 0xbe, 0x7e, 0x81, 0xdb, 0x5c, 0xe9, 0xfb, 0x9c, 0xff, 0x98, + 0xd1, 0x1f, 0x11, 0xe8, 0x24, 0x5e, 0x81, 0xdc, 0xe3, 0x39, 0xd4, 0x8d, 0x30, 0xb5, 0x1c, 0x83, 0x03, 0x21, 0x1a, + 0x88, 0xa8, 0x58, 0xa0, 0xa0, 0x2e, 0x0c, 0xb0, 0x86, 0xba, 0x60, 0x0e, 0xcf, 0x73, 0x99, 0x7c, 0x9c, 0x1a, 0x9f, + 0xf9, 0x61, 0x8c, 0x31, 0x93, 0x83, 0x41, 0x58, 0xcd, 0x82, 0xe1, 0x78, 0x34, 0x39, 0x78, 0x06, 0xe7, 0x76, 0x30, + 0x0e, 0xc8, 0x20, 0xa8, 0xcb, 0x55, 0x2c, 0x68, 0x79, 0x7d, 0x69, 0xcb, 0xc0, 0x8f, 0xeb, 0x60, 0xf0, 0x8f, 0xc2, + 0x53, 0xbc, 0x83, 0xe6, 0xe4, 0x4c, 0x86, 0x60, 0x63, 0xbf, 0x26, 0x20, 0x29, 0xeb, 0x69, 0x7e, 0x52, 0x1f, 0x6e, + 0x4c, 0x69, 0xff, 0xcc, 0xe1, 0x05, 0x87, 0x1d, 0x12, 0x28, 0x90, 0xc6, 0xd3, 0x6c, 0xf4, 0x5a, 0x29, 0x72, 0xdf, + 0x15, 0x1c, 0xee, 0xcc, 0x3d, 0x67, 0x7a, 0xe4, 0x14, 0x12, 0xcd, 0x2c, 0xe0, 0x46, 0xfe, 0x5a, 0x5c, 0xc7, 0x79, + 0x96, 0xee, 0x35, 0xdf, 0xec, 0x95, 0x77, 0xa2, 0x8a, 0x6f, 0x47, 0x81, 0xb1, 0x26, 0xe4, 0xbe, 0xea, 0x09, 0xd0, + 0x13, 0x60, 0x0b, 0x80, 0x01, 0xf1, 0x8e, 0x99, 0xc9, 0x8c, 0x47, 0xe0, 0x11, 0xd8, 0xf4, 0x81, 0x2c, 0xee, 0x9c, + 0x4b, 0x92, 0xbf, 0x99, 0x4a, 0x7b, 0xd5, 0x2b, 0x77, 0x0a, 0xb2, 0x5e, 0x6d, 0xe5, 0xae, 0x5b, 0x9f, 0x7d, 0xd3, + 0xe1, 0x15, 0x78, 0x2e, 0xc1, 0x2d, 0xb2, 0xdf, 0x6f, 0x0a, 0x2a, 0x85, 0x51, 0x11, 0xef, 0x24, 0xd7, 0xe8, 0xdf, + 0xee, 0x8d, 0x8d, 0x22, 0xb9, 0xe5, 0xc3, 0x03, 0xa8, 0x33, 0x79, 0x57, 0xdc, 0xce, 0x21, 0x6a, 0xeb, 0x6e, 0x3c, + 0xb0, 0xda, 0xa0, 0x5d, 0xd6, 0x1c, 0xc1, 0x85, 0x17, 0x7b, 0x19, 0x8c, 0x05, 0xce, 0xca, 0x48, 0xa9, 0x71, 0x0d, + 0xa9, 0x05, 0x9f, 0xe4, 0xe9, 0x3d, 0x64, 0xa9, 0x27, 0x41, 0x91, 0xe3, 0x59, 0x0c, 0x99, 0xc6, 0xdb, 0xc0, 0xe3, + 0x77, 0x32, 0x04, 0x69, 0xda, 0x76, 0xdb, 0x1c, 0x81, 0xb2, 0x7b, 0x60, 0x4a, 0x52, 0xd7, 0xc6, 0xd4, 0x40, 0x43, + 0xed, 0xa1, 0x46, 0x2a, 0xe2, 0xec, 0xe8, 0x0d, 0xe8, 0x10, 0xc1, 0xf7, 0x3b, 0xcd, 0xca, 0x8e, 0x17, 0x13, 0x82, + 0x27, 0xef, 0xcb, 0xdb, 0xac, 0xac, 0xca, 0xe8, 0x7d, 0x8a, 0x86, 0x50, 0x89, 0x14, 0xd1, 0x2b, 0x88, 0xa7, 0x57, + 0xe2, 0xef, 0x32, 0xfa, 0x39, 0xa5, 0x71, 0x9a, 0x62, 0xfa, 0x8b, 0x02, 0x7e, 0x3e, 0x07, 0x54, 0x47, 0xdc, 0x09, + 0xd1, 0xb9, 0x04, 0x7b, 0x35, 0x88, 0x66, 0x55, 0x71, 0xc0, 0xd0, 0x8c, 0x6e, 0x05, 0x45, 0x8c, 0x36, 0xcc, 0xfe, + 0x43, 0x81, 0x42, 0x21, 0x55, 0xcc, 0x77, 0xc2, 0x3e, 0x44, 0x3f, 0x62, 0x91, 0xc7, 0xef, 0x5e, 0x9b, 0x21, 0x8d, + 0xee, 0x24, 0xd5, 0x5b, 0x1b, 0x8f, 0x2d, 0x0c, 0x5c, 0x16, 0x5d, 0xae, 0xe9, 0x59, 0xbc, 0xca, 0xa2, 0x0d, 0xe0, + 0x4f, 0xbc, 0x7b, 0xfd, 0x5c, 0x59, 0x98, 0xbc, 0xc8, 0x40, 0x71, 0x70, 0xfc, 0xee, 0xf5, 0x1b, 0x99, 0xae, 0x73, + 0x1e, 0x9d, 0x49, 0x24, 0xad, 0xc7, 0xef, 0x5e, 0xff, 0x82, 0xe6, 0x5e, 0x3f, 0x17, 0xf0, 0xfe, 0x15, 0xf0, 0x96, + 0x51, 0xbc, 0x86, 0x3e, 0xa9, 0xdf, 0xc9, 0x1a, 0x3b, 0xe5, 0xd5, 0x5a, 0x46, 0xbf, 0xa6, 0xb5, 0x27, 0xad, 0xfa, + 0x67, 0xe1, 0x53, 0x3b, 0x4f, 0xc0, 0x73, 0x9b, 0x67, 0xe2, 0x63, 0x64, 0x45, 0x3b, 0x41, 0xf4, 0xf5, 0xde, 0xed, + 0x55, 0x2e, 0xca, 0x08, 0x5f, 0x30, 0xb4, 0x0b, 0x8a, 0xf6, 0xf7, 0x6f, 0x6e, 0x6e, 0x46, 0x37, 0x4f, 0x46, 0xb2, + 0xb8, 0xdc, 0x9f, 0x7c, 0xfb, 0xed, 0xb7, 0xfb, 0xf8, 0x36, 0xf8, 0xba, 0xed, 0xf6, 0x5e, 0x11, 0x3e, 0x60, 0x01, + 0x22, 0x54, 0x7f, 0x0d, 0x57, 0x14, 0xd0, 0xc2, 0x0d, 0xbe, 0x0e, 0xbe, 0xd6, 0x87, 0xce, 0xd7, 0x87, 0xe5, 0xf5, + 0xa5, 0x2a, 0xbf, 0xab, 0xe4, 0x83, 0xf1, 0x78, 0xbc, 0x0f, 0x12, 0xa8, 0xaf, 0x07, 0x7c, 0x10, 0x1c, 0x05, 0x83, + 0x0c, 0x2e, 0x34, 0xe5, 0xf5, 0xe5, 0x51, 0xe0, 0x99, 0xe6, 0x36, 0x58, 0x44, 0x07, 0xe2, 0x12, 0xec, 0x5f, 0xd2, + 0xe0, 0xeb, 0x80, 0xb8, 0x94, 0xaf, 0x20, 0xe5, 0xab, 0x83, 0x67, 0x7e, 0xda, 0xff, 0x52, 0x69, 0x4f, 0xfc, 0xb4, + 0x43, 0x4c, 0x7b, 0xf2, 0xdc, 0x4f, 0x3b, 0x52, 0x69, 0x2f, 0xfd, 0xb4, 0xff, 0x5d, 0x0e, 0x20, 0x75, 0xcf, 0xb7, + 0xfe, 0x3b, 0xf7, 0x5a, 0x83, 0xa7, 0x50, 0x94, 0x5d, 0xc5, 0x97, 0x1c, 0x1a, 0x3d, 0xb8, 0xbd, 0xca, 0x69, 0x30, + 0xc0, 0xf6, 0x7a, 0x26, 0x21, 0xde, 0x07, 0x5f, 0xaf, 0x8b, 0x3c, 0x0c, 0xbe, 0x1e, 0x60, 0x21, 0x83, 0xaf, 0x03, + 0xf2, 0xb5, 0x31, 0x90, 0x11, 0x6c, 0x13, 0xb8, 0x50, 0xa4, 0x43, 0x1b, 0x20, 0xcc, 0x97, 0xc6, 0xd5, 0xf4, 0xaf, + 0xa2, 0x3b, 0x1b, 0xde, 0x12, 0x95, 0x9b, 0x6e, 0x50, 0xd3, 0x13, 0xf0, 0x4e, 0x80, 0x46, 0x45, 0xc1, 0x75, 0x5c, + 0x84, 0xc3, 0x61, 0x79, 0x7d, 0x49, 0xc0, 0x2e, 0x73, 0xc5, 0xe3, 0x2a, 0x0a, 0x84, 0x1c, 0xaa, 0x9f, 0x81, 0x8a, + 0x7c, 0x15, 0x20, 0x20, 0x12, 0xfc, 0x17, 0xd4, 0xf4, 0x9d, 0x64, 0x9b, 0x60, 0x78, 0xc3, 0xcf, 0x3f, 0x66, 0xd5, + 0x50, 0x89, 0x16, 0xaf, 0x05, 0x85, 0x1f, 0xf0, 0xd7, 0x55, 0x1d, 0xfd, 0x05, 0x6e, 0xdc, 0x4d, 0x0d, 0xfb, 0x3b, + 0xe9, 0x58, 0xd4, 0x77, 0x72, 0x9e, 0x2d, 0xa6, 0xad, 0x03, 0xfd, 0x44, 0x92, 0x6a, 0x9e, 0x0d, 0x82, 0x61, 0x30, + 0xe0, 0x0b, 0x76, 0x22, 0xe7, 0xdc, 0x33, 0x9f, 0x7a, 0x24, 0xfd, 0x69, 0x9e, 0x65, 0x03, 0xf0, 0x4d, 0x41, 0x7e, + 0x64, 0xff, 0xbf, 0xe7, 0x43, 0x14, 0x1e, 0x0e, 0x1e, 0xed, 0x93, 0x59, 0xb0, 0xba, 0x45, 0x8f, 0xce, 0x28, 0xc8, + 0xc4, 0x92, 0x17, 0x59, 0xe5, 0x2d, 0x95, 0xbb, 0x75, 0xdb, 0xcb, 0xe3, 0xde, 0xb3, 0x79, 0x15, 0x8b, 0x40, 0x9d, + 0x73, 0xa0, 0x78, 0x43, 0xd9, 0x53, 0xd9, 0x94, 0x90, 0x6a, 0x43, 0xde, 0xb0, 0x1c, 0xb0, 0xe0, 0xb0, 0x37, 0x1c, + 0xee, 0x05, 0x03, 0xa7, 0xce, 0x1d, 0x04, 0x7b, 0xc3, 0xe1, 0x51, 0xe0, 0xee, 0x43, 0xd9, 0xc8, 0xdd, 0x19, 0x69, + 0xc1, 0xfe, 0x59, 0x84, 0x25, 0x05, 0xf1, 0x98, 0xd4, 0xe2, 0x2f, 0x0d, 0x2e, 0x33, 0x00, 0xe8, 0x23, 0x25, 0x01, + 0x33, 0xb0, 0x32, 0x03, 0x08, 0xcd, 0x4d, 0x63, 0x76, 0x06, 0xcc, 0x23, 0x70, 0xcc, 0x23, 0x64, 0x1c, 0x00, 0xb1, + 0x24, 0xc0, 0xb9, 0x0b, 0xa2, 0x58, 0x17, 0xf2, 0x08, 0x40, 0xef, 0xf1, 0x27, 0x31, 0xa5, 0x60, 0x92, 0x8e, 0x55, + 0x08, 0x82, 0x38, 0x3e, 0xbb, 0x16, 0xad, 0xc9, 0x59, 0xa2, 0x83, 0x19, 0x49, 0x80, 0x0d, 0x31, 0xb0, 0x73, 0x70, + 0x3f, 0x07, 0xa5, 0x87, 0xd5, 0x3b, 0x21, 0x17, 0x7c, 0xc7, 0x3d, 0xd9, 0x2c, 0x5c, 0x3d, 0xe1, 0x20, 0xb8, 0xe3, + 0x9a, 0x05, 0x18, 0x55, 0xc5, 0xba, 0xac, 0x78, 0xfa, 0xe1, 0x6e, 0x05, 0xb1, 0xef, 0x70, 0x40, 0xdf, 0xc9, 0x3c, + 0x4b, 0xee, 0x42, 0x67, 0xcf, 0xb5, 0x51, 0xe9, 0x3f, 0x7c, 0x78, 0xf3, 0x73, 0x04, 0x22, 0xc7, 0xda, 0x50, 0xfa, + 0x3b, 0x8e, 0x67, 0x93, 0x1f, 0xe1, 0xc9, 0xdf, 0xd8, 0x77, 0xdc, 0x9e, 0x1e, 0xfd, 0x3e, 0xd4, 0x4d, 0xef, 0xf8, + 0xec, 0x8e, 0x8f, 0x5c, 0x71, 0xa8, 0xae, 0x70, 0x5f, 0xdf, 0xac, 0x7d, 0x23, 0xa4, 0x87, 0xe7, 0x99, 0xf2, 0xc6, + 0xfc, 0x68, 0x07, 0xc3, 0x20, 0x98, 0x6a, 0xa1, 0x24, 0x44, 0xdd, 0x60, 0x4a, 0xc0, 0x10, 0xed, 0xe9, 0x65, 0x35, + 0x45, 0xce, 0x4d, 0x8d, 0x2c, 0xbc, 0x1f, 0x30, 0x2d, 0x74, 0x68, 0xe4, 0x50, 0x7e, 0x70, 0x38, 0x61, 0xcc, 0xc2, + 0x6f, 0x95, 0x30, 0xfd, 0x6a, 0x51, 0x39, 0x07, 0xd1, 0x3d, 0x30, 0xc6, 0x15, 0xbc, 0x80, 0xae, 0xb0, 0xeb, 0xb5, + 0x8a, 0x8a, 0x81, 0xe0, 0x71, 0xc8, 0x01, 0x7a, 0xd8, 0x05, 0x2d, 0x2b, 0x4b, 0x75, 0xab, 0x72, 0x96, 0x2a, 0xea, + 0x32, 0x94, 0x95, 0xb1, 0xc2, 0x7c, 0x2f, 0xd9, 0x0f, 0x05, 0x7a, 0x96, 0x4f, 0x45, 0x17, 0xbc, 0x10, 0x4a, 0xb0, + 0x5c, 0xd7, 0x3b, 0x11, 0x88, 0x3a, 0x3f, 0xf4, 0xae, 0xfa, 0x1a, 0xc7, 0x8e, 0xa7, 0x6f, 0x64, 0xca, 0xb5, 0x09, + 0x85, 0xe6, 0xf3, 0xa5, 0xaf, 0x98, 0x28, 0xd8, 0x0d, 0xf4, 0xab, 0x6d, 0xa3, 0xcf, 0xee, 0xd6, 0x7a, 0x33, 0x28, + 0xd1, 0x31, 0xaf, 0x51, 0x70, 0xad, 0x14, 0x0a, 0x46, 0x7b, 0x1b, 0x7f, 0x86, 0x23, 0xb7, 0xba, 0x3d, 0xf4, 0x7e, + 0xab, 0xe2, 0xcb, 0xb7, 0xe8, 0xdb, 0x69, 0x7f, 0x8e, 0x2a, 0xf9, 0xeb, 0x6a, 0x05, 0x3e, 0x54, 0x10, 0x59, 0xc4, + 0xe2, 0xd2, 0x42, 0x3d, 0xa7, 0xef, 0x8e, 0xdf, 0x82, 0x1f, 0x25, 0xfe, 0xfe, 0xed, 0xfb, 0xa0, 0x26, 0xd3, 0x78, + 0x56, 0x98, 0x0f, 0x6d, 0x0e, 0x08, 0x4d, 0xe2, 0xd2, 0xec, 0xfb, 0x59, 0xdc, 0x64, 0xdf, 0x35, 0x5b, 0x4f, 0x8b, + 0x26, 0x92, 0x94, 0xe1, 0xf6, 0xc1, 0x80, 0x40, 0x1f, 0x20, 0x8a, 0xb3, 0x2f, 0x68, 0x0c, 0x69, 0x3e, 0xb3, 0xef, + 0x47, 0xc4, 0x7b, 0xb9, 0x13, 0x42, 0x8c, 0x2b, 0x2c, 0x1a, 0x3d, 0xe4, 0x33, 0x1e, 0x29, 0xc3, 0xa2, 0xf7, 0x98, + 0x40, 0x9c, 0xe1, 0xb4, 0x7a, 0x8f, 0x98, 0xc7, 0x78, 0x37, 0xd0, 0xb2, 0x87, 0x28, 0xa3, 0x2e, 0x7b, 0xc3, 0xe2, + 0xfb, 0xe3, 0x3a, 0xcc, 0xac, 0xe5, 0xe5, 0x10, 0xfe, 0x06, 0xda, 0x00, 0x9c, 0x72, 0x64, 0xf9, 0x2a, 0xb3, 0xd1, + 0xd5, 0x12, 0xd3, 0x9b, 0x08, 0x62, 0xf1, 0xe8, 0x74, 0x58, 0xbb, 0x3a, 0x55, 0xef, 0x6a, 0xe7, 0x33, 0xd1, 0xab, + 0x40, 0x2b, 0xd7, 0xb6, 0xc7, 0x43, 0xb8, 0x4b, 0x2d, 0xad, 0xb0, 0x11, 0xe5, 0x5c, 0x3c, 0xdd, 0x39, 0x36, 0x27, + 0xa0, 0xc1, 0x95, 0x4c, 0x01, 0x38, 0x4b, 0xab, 0xd1, 0xa8, 0x11, 0xf6, 0x59, 0x39, 0x9f, 0xc3, 0xd6, 0x42, 0x3c, + 0x2d, 0x00, 0xc3, 0x6d, 0x62, 0x50, 0xf2, 0x6e, 0x0c, 0xca, 0xe9, 0x47, 0x05, 0x6f, 0x1d, 0x9c, 0x95, 0xcb, 0x38, + 0x95, 0x37, 0x80, 0xc5, 0x18, 0xf8, 0xa9, 0x58, 0xaa, 0x97, 0x90, 0x2c, 0x79, 0xf2, 0x11, 0xad, 0x36, 0xd2, 0x00, + 0xb8, 0xca, 0xa9, 0xb1, 0xdc, 0x53, 0x20, 0xa1, 0xae, 0x14, 0x95, 0x10, 0x57, 0x55, 0x9c, 0x2c, 0x4f, 0x31, 0x35, + 0xdc, 0x40, 0x2f, 0xa2, 0x40, 0xae, 0xb8, 0x00, 0x92, 0x9e, 0xb3, 0x7f, 0x65, 0x1a, 0x6b, 0xfc, 0xb9, 0x44, 0x01, + 0x93, 0x46, 0x0d, 0xc6, 0x4a, 0xd9, 0x4b, 0x69, 0xa2, 0xbd, 0x05, 0x41, 0xed, 0x5e, 0xfe, 0x05, 0x75, 0x3f, 0x87, + 0x56, 0x84, 0x0d, 0x30, 0x44, 0x79, 0x8e, 0x3b, 0x34, 0xb5, 0x4b, 0xce, 0x03, 0x46, 0x74, 0xde, 0x67, 0xb5, 0xdd, + 0xea, 0xcf, 0x97, 0x80, 0x6d, 0x9a, 0x1a, 0x9f, 0xc2, 0x30, 0x21, 0x26, 0x36, 0xb0, 0x55, 0x56, 0xda, 0x0d, 0x65, + 0xda, 0x49, 0x97, 0xcc, 0x6b, 0xe1, 0x34, 0xef, 0x31, 0xb6, 0x1c, 0xa9, 0xdc, 0xfd, 0x7e, 0x68, 0x7e, 0xb2, 0x9c, + 0x3e, 0xd7, 0x21, 0x9b, 0xbd, 0xf1, 0xa0, 0x39, 0xd1, 0xea, 0xaa, 0x8e, 0x7e, 0x40, 0x07, 0x60, 0xa6, 0x2d, 0x40, + 0xa6, 0x0b, 0x36, 0xed, 0x2b, 0x51, 0x71, 0x49, 0xc2, 0x52, 0x49, 0x60, 0x67, 0x37, 0x25, 0x3b, 0x9b, 0x80, 0x78, + 0x86, 0xbb, 0x9e, 0x16, 0x3b, 0x21, 0x4d, 0x78, 0x8b, 0xbd, 0x04, 0x44, 0x1d, 0xaa, 0xba, 0x84, 0x6c, 0x8c, 0xa1, + 0x8b, 0x7f, 0x51, 0x0a, 0x13, 0xd6, 0x32, 0xa9, 0x4a, 0x4c, 0x10, 0xa4, 0x72, 0xb7, 0x45, 0x60, 0x89, 0x82, 0x1d, + 0xc0, 0xde, 0xbb, 0x51, 0x37, 0xa3, 0xa6, 0xaa, 0x53, 0x2f, 0xc1, 0xc7, 0x69, 0xd6, 0x55, 0x90, 0x59, 0xd8, 0x55, + 0xb1, 0xe6, 0x81, 0x8e, 0x4d, 0xa5, 0x8c, 0x89, 0xbb, 0xb4, 0xc8, 0x10, 0x0f, 0x18, 0x63, 0xe9, 0x42, 0x20, 0xdf, + 0x6c, 0x77, 0xdc, 0xf4, 0x04, 0xa1, 0x9f, 0xb0, 0xa1, 0x04, 0x6e, 0x3a, 0xdb, 0x53, 0xd3, 0xcc, 0x07, 0x44, 0x1c, + 0x06, 0x14, 0x48, 0x36, 0x0e, 0x69, 0x8e, 0xf4, 0x05, 0x49, 0x13, 0x06, 0x86, 0x56, 0x3c, 0x27, 0xc8, 0x8a, 0x42, + 0xcf, 0xd6, 0x55, 0x1b, 0xe7, 0xca, 0x30, 0x47, 0x4b, 0x4e, 0x85, 0xcf, 0x09, 0x32, 0xb1, 0x7b, 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, 0x68, 0x18, 0x62, 0xb7, 0x3f, 0xc1, 0x7e, 0xad, 0x9d, 0xd6, 0x65, 0x8a, 0xe5, 0x65, 0x0a, + 0xd1, 0x5e, 0xc8, 0xfc, 0x46, 0x91, 0xe8, 0x4e, 0x11, 0x86, 0x84, 0x75, 0x94, 0x3d, 0x69, 0x53, 0x03, 0xe8, 0xa9, + 0x17, 0xf0, 0xbc, 0x73, 0x2d, 0xc3, 0x2e, 0xd2, 0xfd, 0x55, 0xc1, 0xa7, 0x74, 0x83, 0x20, 0x45, 0x6f, 0x52, 0x30, + 0xe7, 0xf5, 0x28, 0xa9, 0x37, 0xa7, 0x2d, 0x33, 0xaa, 0x8e, 0x8a, 0x90, 0x72, 0x82, 0xff, 0xe4, 0xa5, 0xd4, 0xc4, + 0x26, 0x4c, 0xf0, 0xc0, 0x87, 0x79, 0x86, 0x0d, 0xbc, 0xdd, 0xbe, 0x4b, 0xc3, 0xa4, 0xcd, 0x36, 0xa4, 0x20, 0xad, + 0x30, 0x71, 0x31, 0xa0, 0xb2, 0xd7, 0xb8, 0x5f, 0xb0, 0x9d, 0x34, 0x05, 0x0f, 0xc2, 0x46, 0x03, 0x13, 0xb7, 0xba, + 0xf8, 0x3a, 0x4c, 0x68, 0xb8, 0xa4, 0xda, 0xd9, 0x49, 0x4b, 0x9a, 0xdb, 0xeb, 0xf2, 0xc2, 0xf6, 0x41, 0xc7, 0x0e, + 0xeb, 0x1a, 0x1e, 0x68, 0x5e, 0xb3, 0x8b, 0x2b, 0xa6, 0x69, 0xa2, 0xb1, 0x1e, 0x52, 0x96, 0x1c, 0xeb, 0x7a, 0xba, + 0xc2, 0xd5, 0x32, 0xd3, 0xc0, 0xee, 0x12, 0x2f, 0xf4, 0x80, 0x87, 0x1d, 0xae, 0x48, 0x74, 0x81, 0xcd, 0x66, 0xab, + 0x9a, 0x4c, 0xf3, 0xfb, 0xb2, 0xe5, 0x26, 0x20, 0x9c, 0xa5, 0xbe, 0xb9, 0x4f, 0x8e, 0x35, 0x6d, 0xf3, 0x93, 0x00, + 0xc7, 0xdb, 0x2b, 0x20, 0xe9, 0x58, 0x82, 0x2e, 0xbe, 0xa5, 0x3f, 0x88, 0xd4, 0x4c, 0x05, 0xbd, 0x77, 0xbe, 0x48, + 0xdd, 0xfc, 0x02, 0x6c, 0xa3, 0x36, 0xc6, 0x34, 0x2b, 0x5b, 0x87, 0x89, 0xb2, 0xb0, 0x46, 0x16, 0x72, 0x09, 0x3e, + 0x98, 0xbb, 0x4d, 0x9d, 0x1e, 0x77, 0x10, 0x61, 0xbf, 0x8b, 0x1e, 0x8f, 0x30, 0x56, 0xac, 0x41, 0x62, 0x58, 0x85, + 0x35, 0x6d, 0x2e, 0x87, 0x28, 0xa7, 0x66, 0xc9, 0x44, 0x4b, 0xea, 0x53, 0x8a, 0x28, 0x05, 0x73, 0xe3, 0x69, 0xd9, + 0x30, 0x25, 0x44, 0xc8, 0x0a, 0xe9, 0x80, 0x6a, 0x2d, 0xb4, 0x54, 0x13, 0xf4, 0x3a, 0xf4, 0xb2, 0xd0, 0x98, 0x82, + 0xe8, 0x23, 0x32, 0xdc, 0x88, 0x23, 0xa3, 0xbb, 0x63, 0x14, 0x13, 0x08, 0x55, 0xed, 0xe5, 0x85, 0xd5, 0xa7, 0x65, + 0x5b, 0x1d, 0xc4, 0x15, 0x22, 0xdf, 0x77, 0x13, 0xd4, 0x18, 0x05, 0x6d, 0x4e, 0x37, 0xfa, 0x6b, 0x11, 0xfa, 0x76, + 0xe1, 0xd8, 0x8d, 0x82, 0x48, 0x88, 0xc0, 0xea, 0x35, 0x15, 0x03, 0xb2, 0xce, 0x63, 0x17, 0xa1, 0x49, 0x77, 0x0b, + 0x51, 0xde, 0xa8, 0xac, 0x3f, 0xae, 0x43, 0xb2, 0xdd, 0x62, 0x59, 0xe0, 0xcb, 0x7e, 0xba, 0xbe, 0x07, 0xf2, 0xfb, + 0xcd, 0xfa, 0xb3, 0x90, 0xdf, 0xaf, 0xb3, 0x2f, 0x81, 0xfc, 0x7e, 0xb3, 0xfe, 0x9f, 0x86, 0xfc, 0x3e, 0x5d, 0x7b, + 0x90, 0xdf, 0x6a, 0x30, 0x7e, 0x2f, 0x58, 0x70, 0xf2, 0x36, 0xa0, 0x2f, 0x24, 0x0b, 0x4e, 0x5e, 0xbd, 0xf2, 0x8d, + 0x40, 0x84, 0x46, 0xae, 0x37, 0xb2, 0x60, 0xc4, 0x6d, 0x81, 0x57, 0xa8, 0x75, 0xf2, 0x81, 0x8a, 0x32, 0x00, 0x5e, + 0x2f, 0xff, 0x91, 0x55, 0xcb, 0x30, 0xd8, 0x0f, 0xc8, 0xcc, 0x41, 0x82, 0x0e, 0x27, 0x70, 0x7b, 0x43, 0x23, 0xcb, + 0xea, 0x8b, 0xe0, 0xc3, 0x47, 0xa3, 0x51, 0x5c, 0x5c, 0xe2, 0xa5, 0xce, 0x6c, 0x24, 0x04, 0x3c, 0xce, 0x78, 0x69, + 0x43, 0x44, 0x2c, 0xe3, 0xf2, 0x4c, 0xc7, 0x66, 0x29, 0xed, 0x56, 0x84, 0x88, 0xf3, 0x67, 0x80, 0x53, 0x6f, 0xf7, + 0x66, 0x8c, 0xfd, 0x50, 0x1c, 0xb1, 0x0e, 0x20, 0xfb, 0x7c, 0xad, 0xdf, 0x9d, 0xc7, 0x25, 0x7f, 0x17, 0x57, 0x4b, + 0x06, 0xbd, 0x84, 0xbb, 0x88, 0xe0, 0x49, 0xe5, 0xb1, 0x4d, 0x0a, 0xa8, 0x3c, 0xd3, 0x40, 0xe5, 0x1d, 0xef, 0x69, + 0x68, 0x87, 0x45, 0xfb, 0x00, 0x1b, 0xe9, 0x72, 0x06, 0x46, 0x8b, 0x2f, 0xaf, 0xb9, 0xa8, 0x7e, 0x06, 0x3c, 0x75, + 0xc1, 0x0b, 0xb8, 0x25, 0x20, 0x17, 0xdb, 0x70, 0x42, 0xa0, 0xc2, 0xf7, 0xec, 0x50, 0x51, 0x63, 0x8c, 0x68, 0xa2, + 0xd1, 0x6f, 0xbc, 0x09, 0xa1, 0x77, 0x27, 0xe8, 0x8a, 0x30, 0x12, 0xde, 0x5f, 0x6b, 0x7e, 0x96, 0x81, 0xf9, 0xbc, + 0x00, 0x28, 0x0d, 0x84, 0x43, 0x65, 0x4a, 0x6e, 0x81, 0x09, 0x1b, 0x63, 0xae, 0x94, 0xa5, 0x1e, 0x52, 0x29, 0x55, + 0x70, 0xba, 0x82, 0xa6, 0x12, 0x70, 0xb8, 0x23, 0x09, 0x60, 0xa6, 0xb6, 0x30, 0x88, 0x6e, 0x9b, 0xd2, 0x2c, 0x8d, + 0x9c, 0x22, 0xcd, 0xe1, 0x93, 0x52, 0x05, 0x3a, 0x7d, 0x96, 0xc4, 0x15, 0xbf, 0x94, 0x05, 0x84, 0xc2, 0x6d, 0xa5, + 0x50, 0xa4, 0xdf, 0x67, 0x62, 0x7d, 0xc5, 0x8b, 0x2c, 0x39, 0x5b, 0x66, 0x65, 0x05, 0xf9, 0xe6, 0xfa, 0xf4, 0x5b, + 0xd4, 0xd3, 0x02, 0xe7, 0x4d, 0x4d, 0x0a, 0x33, 0xf3, 0x78, 0xac, 0x76, 0x3a, 0xa8, 0x57, 0xbd, 0xd7, 0x06, 0xfb, + 0xbd, 0x39, 0xd1, 0xe3, 0xd6, 0x7a, 0xb0, 0x9a, 0xd4, 0x66, 0xaa, 0x82, 0x38, 0x02, 0xea, 0xc0, 0x8e, 0xe2, 0x76, + 0x33, 0x0f, 0x93, 0x76, 0xca, 0x76, 0xbb, 0x93, 0x09, 0x0e, 0xee, 0x56, 0x12, 0xdc, 0x12, 0x61, 0xc5, 0x1f, 0x2a, + 0x08, 0x96, 0xd9, 0x70, 0x12, 0x99, 0x70, 0xac, 0x05, 0xff, 0x6b, 0xcd, 0x0d, 0x16, 0x7c, 0xa8, 0x1d, 0xf2, 0x9c, + 0xe4, 0x5c, 0x0f, 0x80, 0x67, 0xc3, 0xa6, 0x67, 0x67, 0x0e, 0xf6, 0x53, 0x7e, 0xcb, 0x21, 0x60, 0x4b, 0xe7, 0x28, + 0x2e, 0xa6, 0xda, 0x9a, 0xd7, 0xb0, 0x12, 0xf4, 0xcb, 0xbe, 0xd3, 0x38, 0xb5, 0x09, 0x0f, 0x87, 0xcf, 0xc6, 0xa4, + 0xd6, 0xa6, 0xe5, 0x38, 0xcf, 0xf6, 0xb7, 0x5a, 0x0b, 0xee, 0xd9, 0xae, 0x07, 0xda, 0x74, 0x0a, 0x68, 0xd7, 0x48, + 0xc5, 0x3d, 0xdd, 0xaf, 0x49, 0xed, 0xe6, 0xd5, 0x0a, 0x7a, 0xfe, 0x50, 0x87, 0xcb, 0xd9, 0xa3, 0x4d, 0xa6, 0xab, + 0xac, 0xff, 0xc8, 0x6c, 0x58, 0xb8, 0xc6, 0x46, 0xad, 0xf5, 0x8c, 0xfb, 0xa8, 0x6c, 0x1d, 0xd9, 0xf4, 0x0c, 0xb1, + 0xac, 0x73, 0xb7, 0x8f, 0xd4, 0x23, 0x57, 0x51, 0xb2, 0xba, 0xb3, 0xf0, 0x5b, 0x9e, 0x84, 0x5d, 0x0d, 0x53, 0x8c, + 0xb8, 0xe9, 0x02, 0x02, 0x55, 0x82, 0xf8, 0x3d, 0xfc, 0xe3, 0xd1, 0xa6, 0x49, 0x3d, 0xea, 0x7d, 0xef, 0x33, 0xfc, + 0x9d, 0xa5, 0xf0, 0xb7, 0xaa, 0xff, 0xa0, 0x9b, 0x2b, 0x5e, 0x2d, 0x65, 0x1a, 0x05, 0xef, 0x4e, 0x4e, 0x3f, 0x04, + 0x1a, 0x00, 0x1d, 0xaf, 0x01, 0x46, 0xf1, 0x6b, 0xa0, 0x96, 0x40, 0x11, 0x92, 0xcb, 0x4b, 0xc4, 0x00, 0xd4, 0x20, + 0xf2, 0xa7, 0x4b, 0x79, 0x73, 0x9c, 0xe7, 0x3e, 0xaf, 0x6a, 0xe8, 0x9b, 0x66, 0xdf, 0x1a, 0xc4, 0x21, 0x04, 0x91, + 0xdb, 0x28, 0x2b, 0xcf, 0xb4, 0x92, 0x24, 0x3d, 0x3b, 0xbf, 0x3b, 0xd3, 0x82, 0x18, 0x0b, 0xc2, 0xf8, 0xfc, 0x8f, + 0xc3, 0x34, 0xbb, 0xde, 0x43, 0x22, 0xcc, 0x02, 0xb0, 0x60, 0xcf, 0xf9, 0xf9, 0xba, 0xaa, 0xa4, 0x18, 0x16, 0xf2, + 0x26, 0x38, 0x3a, 0x54, 0x0f, 0x26, 0x43, 0xac, 0x1e, 0x83, 0xbd, 0xff, 0x4a, 0xf2, 0x2c, 0xf9, 0xc8, 0x82, 0x47, + 0x9b, 0x8c, 0x1d, 0xb5, 0x48, 0xed, 0xb8, 0x0e, 0x8e, 0xa0, 0xad, 0x7b, 0xc7, 0x79, 0x7e, 0xb8, 0xaf, 0xbe, 0x38, + 0x3a, 0xdc, 0x4f, 0xb3, 0xeb, 0x23, 0x0f, 0x0f, 0xdf, 0x99, 0xb7, 0x22, 0xf2, 0x98, 0xbb, 0xbe, 0x82, 0x1f, 0x6b, + 0xc2, 0x43, 0x7b, 0xe0, 0x83, 0xd0, 0xc4, 0x44, 0x13, 0x41, 0x41, 0x4b, 0x18, 0xc3, 0xf1, 0xb6, 0xdd, 0x86, 0xd6, + 0xf6, 0x26, 0xf1, 0x80, 0x69, 0x0a, 0x60, 0x08, 0x30, 0x0b, 0x4d, 0x08, 0x4d, 0x6a, 0x12, 0x1a, 0xf8, 0x9c, 0x98, + 0xd0, 0xa2, 0xa6, 0x40, 0xf1, 0xdf, 0xc4, 0x2b, 0x23, 0x6b, 0xd2, 0x77, 0x77, 0xd3, 0xfa, 0x59, 0x63, 0x1c, 0xa3, + 0xf6, 0xa8, 0x1a, 0x40, 0xab, 0x5e, 0x79, 0xdf, 0xc0, 0x82, 0x78, 0x31, 0xac, 0x68, 0xd0, 0x22, 0x15, 0x20, 0x1e, + 0xf4, 0xa5, 0x5a, 0x9c, 0x86, 0xf3, 0x92, 0xca, 0x05, 0x61, 0x47, 0xe1, 0x06, 0xb9, 0xdb, 0x52, 0x11, 0xcb, 0x48, + 0xd6, 0x0e, 0x5d, 0x52, 0xcd, 0xce, 0xd1, 0xa3, 0x8d, 0x40, 0x40, 0xc3, 0x92, 0x1d, 0x35, 0xe7, 0xab, 0x8a, 0xcf, + 0x87, 0x4b, 0x0e, 0x6e, 0x30, 0xc1, 0xde, 0x7f, 0xa5, 0xe7, 0xb9, 0x9d, 0x14, 0xb5, 0x22, 0x97, 0xb1, 0x48, 0x73, + 0xfe, 0x21, 0x3e, 0xff, 0x01, 0xf3, 0xbc, 0x38, 0xcf, 0x9f, 0x43, 0x86, 0x3a, 0x38, 0x7a, 0xb4, 0x49, 0xaa, 0xd1, + 0xcb, 0xb7, 0x1f, 0x5e, 0x7f, 0xf8, 0xe7, 0xd9, 0xf3, 0xe3, 0x0f, 0x2f, 0xbf, 0x3f, 0x79, 0xff, 0xfa, 0xe5, 0xe9, + 0xdc, 0xfa, 0x9d, 0x2a, 0x38, 0x33, 0xb2, 0xd8, 0x6e, 0x5d, 0xbe, 0x5f, 0xdf, 0xbe, 0x78, 0xf9, 0xea, 0xf5, 0xdb, + 0x97, 0x2f, 0x6a, 0x35, 0x97, 0xed, 0x86, 0xc0, 0x0e, 0x8d, 0x33, 0xc1, 0x0b, 0x28, 0x5e, 0x07, 0x55, 0xc4, 0x66, + 0x6b, 0x14, 0xbe, 0x66, 0xd3, 0x75, 0xc0, 0x02, 0x58, 0x64, 0x7b, 0x7a, 0xb3, 0x40, 0xc3, 0xa5, 0xd9, 0x38, 0xfe, + 0x12, 0xf3, 0x7b, 0xf3, 0x12, 0xbf, 0x7b, 0x2f, 0x6f, 0x4c, 0x57, 0xf4, 0x08, 0x29, 0x80, 0xad, 0xd9, 0xf3, 0x3f, + 0x0e, 0x7d, 0xa1, 0x16, 0xde, 0xfc, 0x55, 0xb9, 0xf0, 0xab, 0x0e, 0xf6, 0xb4, 0x81, 0x5d, 0x00, 0xf1, 0x21, 0x82, + 0xa3, 0xc3, 0x7d, 0x3f, 0xf7, 0xd1, 0x1f, 0xd1, 0xcf, 0x5e, 0xe7, 0xb0, 0x54, 0x18, 0x87, 0x66, 0xda, 0xce, 0x21, + 0x04, 0x11, 0x8c, 0xdc, 0x31, 0xa5, 0x56, 0x90, 0x21, 0x57, 0x92, 0x44, 0x76, 0x12, 0x95, 0xe1, 0x88, 0x29, 0xed, + 0x0f, 0xfd, 0xd7, 0xf5, 0x19, 0x2f, 0xe2, 0x5c, 0x94, 0xb2, 0x08, 0xa0, 0x1f, 0xed, 0xb0, 0x0e, 0x7b, 0x5e, 0xf8, + 0x14, 0xec, 0x51, 0x27, 0x79, 0x87, 0x11, 0xd9, 0x6f, 0x7f, 0xea, 0x75, 0xec, 0x0f, 0xe2, 0x7e, 0xec, 0xe9, 0xce, + 0xb4, 0xc8, 0x8b, 0x6d, 0xe0, 0xfd, 0xe1, 0x37, 0xe6, 0x27, 0x19, 0xfd, 0x87, 0xa4, 0x97, 0x31, 0xbd, 0x8a, 0xe9, + 0xa9, 0x58, 0xd4, 0x9d, 0xb3, 0x63, 0x43, 0xbb, 0x50, 0x3e, 0x0d, 0x01, 0x20, 0x42, 0xb3, 0xed, 0x9a, 0x99, 0xcd, + 0x46, 0x5a, 0xa5, 0xf5, 0x21, 0x2e, 0x2e, 0xb9, 0x89, 0xa8, 0x62, 0xde, 0x56, 0x7a, 0x54, 0x88, 0x37, 0x2c, 0x80, + 0x9e, 0xd2, 0xd3, 0x9a, 0xff, 0x6c, 0x94, 0x54, 0x45, 0xfe, 0x13, 0xbf, 0x03, 0xe6, 0xaa, 0xac, 0xe4, 0x0a, 0x58, + 0xea, 0xf8, 0x52, 0x8b, 0x48, 0x68, 0xc8, 0xbf, 0xac, 0xba, 0xed, 0x96, 0x8f, 0x70, 0x49, 0x02, 0x5f, 0x36, 0xaa, + 0xe4, 0xe5, 0x65, 0xce, 0xc3, 0xc0, 0xc4, 0xf8, 0x08, 0xa8, 0xad, 0x66, 0xf6, 0x7f, 0x8a, 0x3b, 0xda, 0xe5, 0xb6, + 0x6d, 0xe4, 0xff, 0x7b, 0x0a, 0x86, 0xc9, 0xa5, 0x62, 0x42, 0xd2, 0xa4, 0x64, 0xd9, 0x8e, 0x64, 0xd9, 0x6d, 0x93, + 0x74, 0xce, 0x1d, 0xb7, 0xe9, 0x24, 0xbe, 0xcc, 0x5d, 0x5d, 0x8f, 0x45, 0x51, 0x90, 0xc4, 0x0b, 0x45, 0x6a, 0x48, + 0xca, 0x96, 0xab, 0xf2, 0x9e, 0xa5, 0xcf, 0x72, 0x4f, 0x76, 0xb3, 0xbb, 0x00, 0x08, 0x7e, 0xe8, 0xc3, 0x4d, 0x7a, + 0x37, 0x3d, 0x5f, 0x44, 0x10, 0x00, 0x81, 0x05, 0xb0, 0xbb, 0xd8, 0xcf, 0x27, 0x8e, 0x08, 0xac, 0x69, 0xe4, 0x9b, + 0x8e, 0x96, 0x98, 0x31, 0x93, 0x91, 0xe7, 0x88, 0xc1, 0x44, 0x11, 0xea, 0x1d, 0x6a, 0x21, 0xf8, 0xba, 0x14, 0x47, + 0xd7, 0x1a, 0xc7, 0xcb, 0x51, 0xc8, 0x2c, 0xdc, 0xee, 0xf0, 0xc9, 0xf5, 0x68, 0x39, 0x1a, 0x41, 0x32, 0x95, 0x27, + 0x8e, 0x09, 0xe1, 0x61, 0xe2, 0x14, 0xaf, 0x6d, 0xb9, 0xd1, 0x87, 0x49, 0xd9, 0x59, 0x75, 0xf8, 0x60, 0xd2, 0x01, + 0x12, 0x19, 0xfa, 0x40, 0x06, 0x57, 0xb4, 0x86, 0x53, 0x3b, 0xd0, 0x3f, 0xc0, 0xee, 0x4b, 0xf5, 0x7e, 0xd3, 0xd1, + 0x1f, 0x5c, 0xeb, 0x1f, 0x10, 0xc6, 0x98, 0x64, 0xf8, 0x35, 0xed, 0x5e, 0xdd, 0xd4, 0x49, 0x37, 0xbd, 0xc4, 0x74, + 0x03, 0x20, 0x9b, 0x7d, 0x13, 0x78, 0xd3, 0x28, 0x4e, 0xb3, 0xc0, 0xd7, 0x6f, 0xfa, 0x17, 0x41, 0xeb, 0x7a, 0x9e, + 0xb5, 0x8c, 0x1b, 0xd3, 0xcf, 0xd4, 0x4c, 0x25, 0x02, 0x61, 0x62, 0xa2, 0x92, 0x4d, 0x95, 0xd4, 0x13, 0xb4, 0xb5, + 0xa2, 0x40, 0xcd, 0x58, 0xc9, 0xcf, 0x06, 0x50, 0xaf, 0x92, 0xf6, 0x04, 0xf3, 0x37, 0xe9, 0xd8, 0xd2, 0xe8, 0xd3, + 0x85, 0xe2, 0xf5, 0x72, 0x8d, 0xa4, 0x3c, 0x2b, 0xa8, 0x25, 0x86, 0xea, 0x15, 0xfe, 0x2d, 0xf4, 0xfc, 0x44, 0xb5, + 0xcd, 0x2c, 0xd1, 0xdd, 0xe1, 0x37, 0x65, 0xbe, 0x00, 0xe8, 0x37, 0x18, 0x46, 0x44, 0x71, 0xa6, 0x41, 0xfc, 0x19, + 0xf8, 0xe2, 0xb0, 0x6a, 0xcb, 0xc5, 0x7b, 0x6d, 0x19, 0x39, 0x47, 0x06, 0xdf, 0x22, 0xf1, 0x6b, 0xf1, 0x28, 0x64, + 0xa5, 0x40, 0x13, 0xc4, 0xd3, 0x47, 0xb0, 0x80, 0x59, 0x7c, 0x19, 0xdf, 0x57, 0xd5, 0x15, 0xaf, 0x87, 0xbb, 0x69, + 0x2f, 0x12, 0x40, 0xd8, 0x6f, 0x22, 0xf9, 0x5e, 0x8b, 0xe7, 0x0f, 0x15, 0x8c, 0x4e, 0xe5, 0x4c, 0xa1, 0x7d, 0x86, + 0xe0, 0x61, 0x32, 0x30, 0xe7, 0x42, 0x5a, 0x00, 0x28, 0x89, 0x93, 0xe9, 0x61, 0x7e, 0x2b, 0x32, 0x1c, 0x8b, 0xfc, + 0xc2, 0x0a, 0x71, 0x06, 0xec, 0x1a, 0x2d, 0x96, 0x19, 0x46, 0xc4, 0x85, 0x01, 0xb0, 0x5c, 0xd7, 0x30, 0xc2, 0x26, + 0x60, 0xe9, 0x82, 0x4d, 0xcc, 0x75, 0x2d, 0x18, 0xd7, 0xcb, 0x88, 0xe7, 0x05, 0xdc, 0x85, 0xe8, 0x1d, 0xc5, 0x49, + 0xf0, 0x98, 0xf0, 0x59, 0xf8, 0x66, 0x11, 0x4d, 0xbe, 0xe5, 0xa3, 0xda, 0xa5, 0x01, 0x31, 0xf8, 0x84, 0xf8, 0xfa, + 0xad, 0xb0, 0x71, 0xae, 0x10, 0x24, 0xb3, 0x34, 0xcb, 0xe1, 0xb3, 0x75, 0x94, 0x9f, 0x3f, 0x5b, 0xa7, 0xf9, 0xe0, + 0xd9, 0xda, 0x03, 0x46, 0x2e, 0xd7, 0x61, 0x9e, 0x85, 0x3b, 0x4d, 0x31, 0x3b, 0xd8, 0x53, 0x54, 0xae, 0xa1, 0x3e, + 0x7d, 0xc0, 0xb5, 0xe6, 0x8b, 0x24, 0x98, 0x7b, 0xc9, 0x03, 0x29, 0xd9, 0x4d, 0x55, 0x13, 0x6f, 0xe8, 0x1a, 0xa1, + 0x75, 0x9a, 0x2e, 0x61, 0x78, 0x5d, 0xfb, 0x5a, 0x96, 0x31, 0x3e, 0x39, 0xa9, 0x69, 0x84, 0x6f, 0xdd, 0xea, 0x2f, + 0x99, 0x3d, 0x66, 0x99, 0x17, 0x84, 0xd4, 0xa4, 0x2f, 0x52, 0xc8, 0xd7, 0x66, 0x93, 0x96, 0x67, 0x13, 0x95, 0x77, + 0x0b, 0x4e, 0x86, 0x10, 0x3e, 0x8d, 0x1b, 0x67, 0x86, 0xa9, 0xa5, 0x9a, 0xd7, 0x8f, 0xde, 0xfd, 0x4f, 0xa1, 0xcf, + 0x00, 0xfa, 0x11, 0x40, 0x9f, 0x45, 0x7e, 0x3c, 0x66, 0x7f, 0x7f, 0x7f, 0x21, 0x73, 0x59, 0x81, 0x58, 0x66, 0xc8, + 0xb7, 0x61, 0x8a, 0xdc, 0x42, 0x82, 0x9c, 0x02, 0x65, 0x9d, 0x2a, 0x76, 0x4c, 0x92, 0xeb, 0xda, 0x39, 0x8d, 0x9d, + 0x8d, 0x69, 0xd4, 0x83, 0x18, 0x5b, 0x25, 0xf9, 0xe9, 0x01, 0xd5, 0x26, 0xda, 0x46, 0x95, 0x00, 0x0c, 0x09, 0xcc, + 0xb0, 0x80, 0x02, 0xa4, 0xdd, 0x1c, 0xb8, 0xc5, 0xf5, 0xc1, 0x9e, 0xa3, 0xf0, 0xdb, 0x3d, 0x2f, 0x33, 0x26, 0xd8, + 0x4a, 0x3f, 0x3b, 0xc5, 0x44, 0x5a, 0x40, 0x9d, 0x21, 0xf4, 0xc6, 0xe9, 0x01, 0x3d, 0x6a, 0x95, 0xfd, 0x5f, 0x74, + 0x22, 0x2e, 0x72, 0x3d, 0xde, 0xc1, 0xa3, 0x0e, 0x06, 0xe4, 0x6d, 0x87, 0x52, 0x2f, 0xd7, 0xb5, 0x39, 0x67, 0x84, + 0x78, 0x8c, 0x1f, 0x08, 0x00, 0xe0, 0xc0, 0x49, 0xd5, 0xb5, 0xb9, 0xb7, 0xc2, 0x99, 0x8b, 0x37, 0xde, 0xaa, 0xe5, + 0xf2, 0x57, 0xb6, 0x04, 0x54, 0x5a, 0x3e, 0x5a, 0x3e, 0x5f, 0x5c, 0xb0, 0xee, 0x17, 0x42, 0xdb, 0xd6, 0x0c, 0xb5, + 0xa6, 0x0d, 0x8b, 0x3b, 0x13, 0x8b, 0x3b, 0xde, 0xb0, 0xb8, 0xe3, 0x2d, 0x8b, 0x1b, 0xf2, 0x85, 0xd4, 0x24, 0xe8, + 0x12, 0xf4, 0xd8, 0x92, 0xc0, 0xe3, 0x6c, 0x45, 0x8f, 0x9f, 0x33, 0x84, 0x93, 0x95, 0x86, 0x60, 0xb1, 0xb4, 0x01, + 0x56, 0x4d, 0x70, 0x51, 0x00, 0xa1, 0xa2, 0x94, 0xb4, 0x74, 0xe8, 0xc4, 0xb4, 0x21, 0x2f, 0x66, 0x2b, 0xac, 0x4e, + 0x17, 0x36, 0x29, 0xe5, 0xfc, 0x6e, 0xcd, 0x36, 0x4c, 0x74, 0xb6, 0x65, 0xa2, 0x7e, 0xe9, 0xe4, 0xf2, 0x59, 0xd3, + 0x19, 0x54, 0xe7, 0x04, 0x5b, 0x10, 0x8c, 0x38, 0x71, 0xc7, 0x94, 0xb7, 0xe1, 0x66, 0x84, 0xaa, 0x6c, 0xa8, 0x85, + 0x97, 0xa6, 0xf7, 0x71, 0x02, 0x5a, 0x10, 0xe8, 0xe6, 0x71, 0x3b, 0x6a, 0x1e, 0x44, 0x3c, 0xc0, 0xca, 0xc6, 0xbd, + 0x54, 0xbc, 0x57, 0x77, 0x54, 0xbb, 0xdb, 0xa5, 0x1a, 0x0b, 0x2f, 0xcb, 0x58, 0x82, 0x30, 0xf7, 0x20, 0x12, 0x77, + 0x0d, 0xd8, 0xff, 0x97, 0x4d, 0xd6, 0x80, 0x41, 0x42, 0xa3, 0xc0, 0xe9, 0x88, 0x9f, 0x17, 0xc0, 0x47, 0x25, 0x82, + 0xe8, 0x2a, 0xb1, 0xda, 0x12, 0x09, 0xf7, 0x1f, 0xf1, 0xb0, 0xb6, 0x12, 0xc5, 0x9b, 0xc8, 0x3d, 0x32, 0xec, 0x85, + 0x37, 0xfe, 0x00, 0xba, 0xb6, 0x56, 0xdb, 0x04, 0xbb, 0x59, 0x35, 0x32, 0x5b, 0x42, 0x8c, 0x9d, 0x5f, 0xa0, 0x48, + 0xc4, 0x91, 0xdc, 0x2a, 0x09, 0x1c, 0x1a, 0x3d, 0x6b, 0x72, 0xb3, 0x6e, 0xe7, 0x07, 0xd3, 0xc0, 0xa8, 0xe1, 0x4c, + 0x40, 0x6c, 0xe1, 0xe0, 0x4c, 0xde, 0xaf, 0x42, 0xd3, 0x3d, 0x32, 0x40, 0x18, 0x7b, 0x0d, 0x29, 0x46, 0x1d, 0x71, + 0x79, 0x1d, 0x26, 0x40, 0xa2, 0xae, 0x9d, 0x9b, 0xfc, 0xf9, 0x14, 0x7f, 0xb9, 0x37, 0xf9, 0xf3, 0x11, 0xfe, 0x6a, + 0xdf, 0x60, 0x32, 0xb9, 0x86, 0x4b, 0xbb, 0x32, 0x67, 0xfd, 0xac, 0xb4, 0x9d, 0xc8, 0x24, 0xec, 0xf1, 0x04, 0xfa, + 0xe9, 0xb3, 0x75, 0x0a, 0x4e, 0x90, 0xea, 0x1c, 0x22, 0x3b, 0x31, 0xf2, 0xc6, 0xf2, 0xe9, 0x86, 0xf2, 0x91, 0xf1, + 0x3f, 0xa6, 0xf2, 0xb8, 0x4b, 0xe2, 0x82, 0xa2, 0x94, 0x45, 0x0e, 0xb7, 0xa3, 0x20, 0xf2, 0x92, 0x87, 0x5b, 0xba, + 0x4a, 0xb4, 0x04, 0x9f, 0x2e, 0x45, 0x29, 0xc4, 0x4a, 0x96, 0x35, 0x50, 0x99, 0x22, 0x73, 0x7d, 0xe0, 0x64, 0x7e, + 0xf0, 0x8f, 0x44, 0x61, 0xd1, 0x4a, 0x97, 0x4d, 0xbe, 0x20, 0xa5, 0x0f, 0xdd, 0x3e, 0x5b, 0xb7, 0x58, 0xbd, 0x9b, + 0xca, 0x6c, 0x2b, 0x3c, 0x20, 0x2c, 0x0f, 0x5e, 0x5c, 0xe7, 0xe3, 0xa0, 0x87, 0x2a, 0xa6, 0x51, 0xbc, 0xb2, 0x9e, + 0xad, 0xb3, 0x73, 0x7d, 0xee, 0x25, 0x9f, 0xd8, 0xd8, 0xf2, 0x83, 0xc4, 0x0f, 0x99, 0xde, 0xd3, 0x47, 0xa1, 0x17, + 0x7d, 0xe2, 0x8f, 0x56, 0xbc, 0xcc, 0x50, 0x69, 0xbc, 0xf3, 0x9e, 0x2b, 0x60, 0x42, 0xe2, 0x39, 0x64, 0x4c, 0x1b, + 0xa0, 0xa0, 0xbd, 0x96, 0xc2, 0xad, 0x82, 0x29, 0x2c, 0x6a, 0x99, 0x60, 0xf3, 0x08, 0x7a, 0x6c, 0x70, 0x22, 0x35, + 0x75, 0x5c, 0x2f, 0xdd, 0x54, 0xa7, 0x4a, 0x82, 0x49, 0x99, 0x05, 0xf1, 0x16, 0x7b, 0xf8, 0xe3, 0x9f, 0xa3, 0xfc, + 0xd4, 0xfb, 0x7f, 0x8e, 0x73, 0x78, 0x9b, 0x3f, 0xa8, 0x36, 0xf6, 0xd2, 0x74, 0x39, 0x67, 0x63, 0xd2, 0x97, 0x9d, + 0x17, 0x43, 0x29, 0x33, 0xf2, 0xea, 0x70, 0x7e, 0x59, 0xb6, 0x8f, 0x0f, 0x5f, 0x83, 0x1e, 0x1f, 0x38, 0xba, 0x78, + 0x32, 0xd1, 0x8b, 0x2b, 0xf5, 0x8e, 0x66, 0xee, 0xe1, 0x2f, 0xcb, 0xef, 0xde, 0x3a, 0xdf, 0xc9, 0xc6, 0x91, 0x6e, + 0xe4, 0x43, 0xa1, 0x94, 0xe4, 0x8c, 0xa9, 0x32, 0x5e, 0x31, 0xa3, 0x89, 0x17, 0x6d, 0x9e, 0xce, 0x75, 0x69, 0x97, + 0x2d, 0x18, 0x1b, 0x83, 0xbd, 0xaa, 0x59, 0x2b, 0xbd, 0x0d, 0xd9, 0x1d, 0x93, 0x0a, 0xcf, 0xfa, 0xc7, 0x1a, 0x5a, + 0x60, 0x44, 0x36, 0xae, 0x48, 0xe5, 0x6c, 0x95, 0x32, 0xa5, 0x21, 0xce, 0x81, 0xcf, 0x5c, 0xdd, 0xe5, 0x95, 0x5d, + 0x3d, 0x34, 0x75, 0x65, 0x00, 0x1b, 0x47, 0x76, 0xbe, 0xa1, 0xbc, 0x87, 0xe9, 0x98, 0x9b, 0xc7, 0x66, 0xba, 0x46, + 0x0f, 0x22, 0x58, 0x73, 0x38, 0x85, 0xb0, 0xf9, 0x5b, 0x85, 0xf4, 0x61, 0x13, 0xc4, 0x9a, 0x64, 0x52, 0xba, 0x90, + 0xf1, 0x34, 0x2e, 0x84, 0x56, 0x9e, 0xe6, 0x08, 0x73, 0x9a, 0x46, 0x2c, 0x4d, 0x37, 0x42, 0x47, 0xae, 0xb0, 0xa9, + 0x17, 0xb5, 0xcb, 0x93, 0x2f, 0xca, 0x4d, 0xc7, 0x04, 0x0a, 0x8c, 0xb3, 0xa9, 0x7e, 0x0b, 0xd1, 0xf9, 0xed, 0x9c, + 0x9b, 0x6c, 0x24, 0xd3, 0x91, 0xce, 0xd5, 0xe9, 0x9b, 0xde, 0xdf, 0xeb, 0x7c, 0x50, 0x25, 0xb2, 0xd8, 0x38, 0xb4, + 0x56, 0x09, 0xd5, 0xd5, 0x44, 0x31, 0xd8, 0x81, 0x18, 0x53, 0x05, 0x9f, 0xb1, 0xc9, 0x84, 0xf9, 0x59, 0x6a, 0x08, + 0xc1, 0x8c, 0x0c, 0xa0, 0x0a, 0x8e, 0x33, 0x4f, 0x06, 0xfa, 0x8f, 0xe0, 0x46, 0x2e, 0xe2, 0x0c, 0xf1, 0x01, 0x89, + 0x1b, 0x4a, 0x33, 0x98, 0xa8, 0xc7, 0x32, 0x88, 0xf8, 0x57, 0x20, 0x3f, 0x76, 0x43, 0x39, 0x0e, 0x8d, 0xe3, 0xfb, + 0x62, 0x13, 0xc4, 0xd2, 0xb0, 0x63, 0x3b, 0xb6, 0xd9, 0x76, 0x56, 0xd7, 0xee, 0x77, 0x5d, 0xd7, 0xc9, 0x75, 0x13, + 0xdc, 0x97, 0x3e, 0xed, 0x7b, 0xc2, 0xb1, 0x55, 0x07, 0x5a, 0x2d, 0xa3, 0xc7, 0xb4, 0x6b, 0xbb, 0xaf, 0x5c, 0xdd, + 0x24, 0xab, 0x31, 0x05, 0x91, 0xf9, 0xf1, 0x1d, 0x4b, 0x3e, 0x7b, 0x2a, 0xe5, 0xce, 0xf7, 0x1b, 0xcf, 0x91, 0xeb, + 0x00, 0xc6, 0xcd, 0xe2, 0xc5, 0x23, 0xa6, 0xd0, 0xd1, 0x4d, 0xdd, 0x0f, 0xe3, 0x94, 0xa9, 0x73, 0x20, 0x01, 0xc3, + 0x67, 0x4e, 0xe2, 0xa7, 0xf7, 0x6f, 0x3f, 0x7c, 0xd0, 0x4d, 0x4c, 0x86, 0x99, 0xaa, 0xbd, 0xf3, 0x0d, 0xb5, 0x03, + 0xd5, 0x37, 0xee, 0x3b, 0x22, 0x27, 0x74, 0x85, 0x2c, 0xef, 0x39, 0x2a, 0xab, 0x6d, 0x39, 0x4e, 0x66, 0xf8, 0x97, + 0xe9, 0xde, 0xb7, 0xd7, 0xbc, 0x1a, 0x70, 0xc3, 0x76, 0x5a, 0x56, 0x2a, 0x99, 0x07, 0xd1, 0x6d, 0x43, 0xa9, 0xb7, + 0x6a, 0x28, 0x85, 0x8b, 0x53, 0x0d, 0x57, 0x2d, 0xe3, 0xb9, 0x42, 0x8a, 0x21, 0x97, 0xf1, 0x2e, 0x70, 0x29, 0xd7, + 0x97, 0xcf, 0x18, 0x34, 0x0f, 0x66, 0x5e, 0x1d, 0x75, 0x43, 0x31, 0xbf, 0x73, 0x48, 0xd8, 0xfa, 0x21, 0xd8, 0xbc, + 0x31, 0x55, 0xe3, 0x55, 0x66, 0xd3, 0xa4, 0xc5, 0xaa, 0xd2, 0x09, 0xb1, 0x93, 0xb7, 0x19, 0x9b, 0x2f, 0x58, 0xe2, + 0x65, 0xcb, 0x84, 0xdd, 0x86, 0xf1, 0xfd, 0x93, 0xc2, 0xa2, 0x7c, 0x47, 0xe5, 0x59, 0x30, 0x9d, 0xc9, 0xda, 0xe7, + 0x2d, 0x36, 0x90, 0x0b, 0xb8, 0xf5, 0x03, 0xf9, 0x7f, 0x7e, 0xb7, 0xed, 0xff, 0xfc, 0xbe, 0xb3, 0x2a, 0x74, 0x9f, + 0x0f, 0xcd, 0x6c, 0xb0, 0xc7, 0xbe, 0x68, 0xfe, 0x52, 0x19, 0xe6, 0xcd, 0x75, 0x6a, 0x8b, 0x00, 0xef, 0x6b, 0x4b, + 0x50, 0x2b, 0x2c, 0xef, 0x9b, 0x47, 0x0d, 0x0c, 0xe6, 0xb5, 0x73, 0x64, 0x50, 0xe9, 0xb3, 0x86, 0x36, 0x34, 0x7a, + 0x7b, 0xad, 0xc8, 0x1f, 0x87, 0xf0, 0xae, 0x39, 0x7c, 0xe6, 0xf0, 0xb9, 0x14, 0xf0, 0xf5, 0x70, 0x28, 0xd3, 0xab, + 0xa9, 0x4d, 0xc1, 0xca, 0xfd, 0xbc, 0x56, 0xc2, 0x89, 0x67, 0xcf, 0x31, 0xc8, 0xfd, 0x7c, 0xf0, 0x7a, 0x88, 0xf6, + 0x58, 0xa7, 0xa3, 0xa4, 0x60, 0x56, 0x36, 0xa2, 0x36, 0xb2, 0xa7, 0xae, 0x75, 0x5a, 0xc3, 0x6b, 0x50, 0x8a, 0x39, + 0xb7, 0xf2, 0xa1, 0x61, 0xbe, 0x1e, 0x72, 0x31, 0x0e, 0x37, 0x01, 0xed, 0x55, 0xb7, 0x36, 0x17, 0x82, 0x96, 0x80, + 0x6e, 0x6a, 0xa4, 0x5b, 0xc1, 0xca, 0xac, 0x90, 0x9a, 0xa1, 0xf0, 0x1c, 0x6e, 0xf0, 0xc3, 0x1c, 0x53, 0x7e, 0xbc, + 0xdb, 0x64, 0x26, 0xf5, 0xd3, 0x6e, 0x33, 0xa9, 0xab, 0xbd, 0xcc, 0xa4, 0x7e, 0xfa, 0xe2, 0x66, 0x52, 0xef, 0x54, + 0x33, 0x29, 0x58, 0xc4, 0xb7, 0x6c, 0x2f, 0xdb, 0x25, 0x61, 0x11, 0x11, 0xdf, 0xa7, 0x03, 0x97, 0xf3, 0xaf, 0xa9, + 0x3f, 0x63, 0x70, 0x27, 0xe7, 0xab, 0x12, 0xc6, 0x53, 0xb0, 0x63, 0xfa, 0xf3, 0x2d, 0x8e, 0xc2, 0x78, 0xaa, 0xda, + 0x1b, 0x45, 0x3c, 0xe8, 0x69, 0x11, 0xc8, 0x88, 0x6c, 0x7c, 0x1c, 0x53, 0x84, 0x3d, 0xb2, 0x0e, 0x0d, 0x25, 0xb1, + 0xb3, 0x34, 0xe0, 0x6a, 0x0b, 0x2b, 0xa0, 0x1e, 0x1a, 0x10, 0xc9, 0x86, 0xed, 0x97, 0x22, 0xbc, 0x83, 0xda, 0x83, + 0x34, 0x94, 0xa5, 0x50, 0x09, 0x6b, 0xfd, 0x97, 0x95, 0xfb, 0xed, 0xb5, 0xdb, 0xef, 0xb8, 0xe0, 0x9f, 0x0c, 0x37, + 0x3a, 0x2c, 0x70, 0xfa, 0x9d, 0x0e, 0x14, 0xdc, 0x2b, 0x05, 0x6d, 0x28, 0x08, 0x94, 0x82, 0x2e, 0x14, 0xf8, 0x4a, + 0xc1, 0x11, 0x14, 0x8c, 0x95, 0x82, 0x63, 0x28, 0xb8, 0xd3, 0xf3, 0xeb, 0x48, 0x0e, 0xf7, 0xd8, 0xb8, 0x31, 0xe9, + 0x06, 0x21, 0xca, 0x8e, 0x4d, 0x17, 0x0c, 0x87, 0xbc, 0x69, 0x2f, 0x36, 0x49, 0x98, 0xd7, 0x4b, 0xcc, 0xfb, 0x19, + 0xa3, 0x58, 0xc9, 0x6f, 0x90, 0xe6, 0xd8, 0x59, 0x0c, 0xa6, 0xc3, 0x22, 0x06, 0x81, 0x80, 0x83, 0xa6, 0x1b, 0x20, + 0xa0, 0xe9, 0xcb, 0x95, 0x13, 0x71, 0x1c, 0x94, 0xb5, 0x2c, 0xde, 0xd1, 0xe7, 0x2c, 0xb9, 0x05, 0x0a, 0x6b, 0x8e, + 0x96, 0x2a, 0x04, 0xfc, 0x12, 0x3a, 0xfd, 0x37, 0x6c, 0xb4, 0x9c, 0x6a, 0x97, 0xf1, 0x74, 0xa7, 0x7a, 0x5e, 0x7d, + 0x05, 0xa3, 0xd4, 0x49, 0xd9, 0x61, 0x89, 0x6d, 0xc9, 0xbf, 0x45, 0x8f, 0x79, 0xb9, 0x7e, 0x06, 0x63, 0xd3, 0x32, + 0x32, 0x0e, 0x81, 0xef, 0x00, 0x8c, 0x14, 0xfd, 0xf8, 0x25, 0xc0, 0x59, 0x79, 0xbe, 0xf2, 0x94, 0xf1, 0x9c, 0xfd, + 0xc0, 0xd2, 0xd4, 0x9b, 0x8a, 0xfa, 0xf5, 0x71, 0x82, 0x41, 0x8c, 0xbc, 0x7f, 0x21, 0x00, 0x41, 0x72, 0x16, 0xd4, + 0xec, 0x1e, 0x92, 0xf8, 0x5e, 0x03, 0xcb, 0x1a, 0xd8, 0x50, 0x85, 0x0d, 0x40, 0x60, 0xc3, 0x12, 0x96, 0xb5, 0xf5, + 0x70, 0xf8, 0xef, 0x58, 0x58, 0x2d, 0xcc, 0xbc, 0x69, 0xb5, 0x88, 0xf6, 0x41, 0xae, 0x8e, 0x4d, 0x2a, 0xcb, 0x4b, + 0x85, 0x9f, 0xa3, 0xfd, 0x0d, 0xe3, 0xe9, 0x9f, 0xaa, 0xfa, 0xdd, 0xa2, 0xb2, 0xff, 0x10, 0x99, 0x41, 0x36, 0xb4, + 0x11, 0xc6, 0x9a, 0x0d, 0x20, 0xec, 0x45, 0xd9, 0xcc, 0x42, 0xef, 0xaa, 0x56, 0x3b, 0x32, 0x4c, 0x1b, 0xd7, 0x76, + 0x5d, 0xf5, 0x29, 0xed, 0x25, 0xd3, 0x91, 0xd7, 0x72, 0xdb, 0xc7, 0xa6, 0xf8, 0xb3, 0x9d, 0xae, 0x91, 0x63, 0x0f, + 0xda, 0x38, 0xb8, 0x5b, 0x4f, 0xe2, 0x28, 0xb3, 0x26, 0xde, 0x3c, 0x08, 0x1f, 0x7a, 0xf3, 0x38, 0x8a, 0xd3, 0x85, + 0xe7, 0xb3, 0x3e, 0x79, 0xd0, 0x81, 0x2b, 0x69, 0x1f, 0xa3, 0x15, 0x70, 0x87, 0x39, 0xd7, 0x6e, 0x27, 0x6c, 0x4e, + 0xad, 0x65, 0x30, 0x82, 0x49, 0xc8, 0x56, 0x39, 0xff, 0x7c, 0xa9, 0x32, 0x55, 0xc5, 0x2d, 0x47, 0x2d, 0x80, 0x23, + 0xe5, 0x91, 0x0e, 0x20, 0xbe, 0x4f, 0x7f, 0xe1, 0x8d, 0x31, 0x38, 0x9f, 0xdd, 0xee, 0x26, 0x6c, 0xae, 0xd9, 0xdd, + 0x8d, 0x9d, 0x27, 0xf1, 0xfd, 0x19, 0x8c, 0x16, 0x1b, 0x5b, 0x29, 0x0b, 0x27, 0xf8, 0xc6, 0x42, 0xe7, 0x0a, 0xd1, + 0x8f, 0x85, 0x17, 0x71, 0xe8, 0x8d, 0xcd, 0xfb, 0xf0, 0xba, 0xd7, 0xd6, 0x9c, 0xfe, 0x3c, 0x88, 0x2c, 0x9a, 0xce, + 0xb1, 0xb3, 0x50, 0xfa, 0x52, 0xe1, 0x67, 0xac, 0xb1, 0xba, 0xab, 0x39, 0x7d, 0xb8, 0xac, 0x4d, 0xc2, 0xf8, 0xbe, + 0x37, 0x0b, 0xc6, 0x63, 0x16, 0xf5, 0x71, 0xcc, 0xb2, 0x90, 0x85, 0x61, 0xb0, 0x48, 0x83, 0xb4, 0x3f, 0xf7, 0x56, + 0xbc, 0xd7, 0xc3, 0x4d, 0xbd, 0x76, 0x78, 0xaf, 0x9d, 0xbd, 0x7b, 0x55, 0xba, 0x01, 0x47, 0x0e, 0xea, 0x87, 0x0f, + 0xad, 0xab, 0x39, 0x95, 0x79, 0xee, 0xdd, 0xeb, 0x22, 0x61, 0xeb, 0xb9, 0x97, 0x4c, 0x83, 0xa8, 0xe7, 0xe4, 0xf6, + 0xdd, 0x9a, 0x36, 0xc6, 0xd3, 0x93, 0x93, 0x93, 0xdc, 0x1e, 0x8b, 0x27, 0x67, 0x3c, 0xce, 0x6d, 0x5f, 0x3c, 0x4d, + 0x26, 0x8e, 0x33, 0x99, 0xe4, 0x76, 0x20, 0x0a, 0x3a, 0x6d, 0x7f, 0xdc, 0x69, 0xe7, 0xf6, 0xbd, 0x52, 0x23, 0xb7, + 0x19, 0x7f, 0x4a, 0xd8, 0xb8, 0x8f, 0x1b, 0xe9, 0x9e, 0x96, 0xfe, 0xd8, 0x71, 0x72, 0xc4, 0x00, 0xd7, 0x25, 0xdc, + 0x84, 0x82, 0x9d, 0x9b, 0xf5, 0xde, 0x35, 0xb5, 0xe2, 0x73, 0xbe, 0xdf, 0x58, 0x6f, 0xec, 0x25, 0x9f, 0x6e, 0x34, + 0x65, 0x16, 0x9e, 0x47, 0xd5, 0xd6, 0x02, 0x0c, 0xd6, 0xaa, 0x07, 0x51, 0xab, 0xfa, 0xa3, 0x38, 0x81, 0x33, 0x9b, + 0x78, 0xe3, 0x60, 0x99, 0xf6, 0xdc, 0xf6, 0x62, 0x25, 0x8a, 0xf8, 0x5e, 0x2f, 0x0a, 0xf0, 0xec, 0xf5, 0xd2, 0x38, + 0x0c, 0xc6, 0xa2, 0x68, 0xd3, 0x59, 0x72, 0xdb, 0x46, 0x1f, 0x7d, 0xb6, 0x03, 0x8c, 0x3c, 0xe0, 0x85, 0xa1, 0x66, + 0x77, 0x52, 0x8d, 0x79, 0x29, 0xca, 0x73, 0x35, 0x27, 0x25, 0xb8, 0xa0, 0x7f, 0xb6, 0x7b, 0xb8, 0x58, 0xc9, 0x3d, + 0xef, 0x1e, 0x2d, 0x56, 0xf9, 0xd7, 0x73, 0x36, 0x0e, 0x3c, 0xad, 0x55, 0xec, 0x26, 0xd7, 0x01, 0x99, 0xaf, 0xb1, + 0xde, 0xb0, 0x4d, 0xc5, 0xb1, 0x80, 0xe8, 0x7e, 0x4f, 0x82, 0xf9, 0x22, 0x4e, 0x32, 0x2f, 0xca, 0xf2, 0x7c, 0x78, + 0x93, 0xe7, 0xfd, 0xab, 0xa0, 0x75, 0xfd, 0xcf, 0x16, 0xd1, 0x69, 0xd2, 0x91, 0xe4, 0xc6, 0x8d, 0xf9, 0x96, 0xa9, + 0xf6, 0x18, 0x40, 0xc6, 0xd0, 0x16, 0x43, 0xad, 0x4c, 0x54, 0xb2, 0x5e, 0x99, 0x80, 0x2c, 0xab, 0x93, 0x7d, 0x47, + 0xb9, 0x0a, 0x52, 0x20, 0xa8, 0xf0, 0x96, 0x0d, 0xae, 0x14, 0xdb, 0x0e, 0x60, 0x56, 0xb0, 0x32, 0x99, 0xd6, 0x3f, + 0xdb, 0xc4, 0x33, 0x7e, 0xb3, 0x9b, 0x67, 0xfc, 0x39, 0xdb, 0x87, 0x67, 0xfc, 0xe6, 0x8b, 0xf3, 0x8c, 0xcf, 0xea, + 0xa6, 0xf5, 0x17, 0xf1, 0x40, 0x97, 0x12, 0x7d, 0x20, 0x4d, 0x09, 0x05, 0xad, 0xb9, 0xf8, 0xc3, 0x96, 0xf0, 0xa2, + 0x37, 0x4a, 0xc3, 0x46, 0x94, 0x1b, 0x84, 0xaf, 0xef, 0xa2, 0xc1, 0x3f, 0x12, 0xf5, 0x79, 0x32, 0x19, 0xbc, 0x89, + 0x95, 0x02, 0xf9, 0xc4, 0x4d, 0x1d, 0x4a, 0x01, 0x06, 0xe8, 0x8d, 0xb0, 0x70, 0xc4, 0x14, 0x0c, 0xe0, 0x9f, 0x4c, + 0x16, 0xbd, 0x63, 0x69, 0xd9, 0xd5, 0x2f, 0x0f, 0xa1, 0x25, 0xcd, 0x29, 0x85, 0x17, 0x4a, 0x4d, 0x94, 0x38, 0x65, + 0x19, 0x77, 0x1b, 0xfd, 0xf6, 0xe1, 0x62, 0xdc, 0xba, 0x88, 0x8d, 0x3c, 0x48, 0xdf, 0x55, 0x7d, 0x40, 0xb8, 0xae, + 0x65, 0xa0, 0x4e, 0x27, 0xe7, 0xd6, 0x59, 0x6a, 0x8e, 0x65, 0x78, 0x4d, 0xcd, 0xcf, 0x4b, 0x33, 0xed, 0xa9, 0x0d, + 0x79, 0xae, 0xa7, 0x1a, 0x31, 0xe6, 0x06, 0xf8, 0x6b, 0xce, 0x01, 0x62, 0xfa, 0x2a, 0x74, 0x9d, 0x1d, 0x53, 0xf3, + 0x60, 0x9c, 0xe7, 0x46, 0x5f, 0x00, 0x42, 0x21, 0xb4, 0x6c, 0x17, 0x13, 0x97, 0xde, 0x4b, 0x0b, 0x02, 0xae, 0x91, + 0x23, 0x75, 0xdb, 0x05, 0xa8, 0xaf, 0xb9, 0x72, 0x8e, 0xc3, 0x4c, 0xd7, 0x08, 0x7c, 0x64, 0xd6, 0xa0, 0x4c, 0x08, + 0xd4, 0xfa, 0x12, 0xfe, 0xe2, 0x95, 0x28, 0xa8, 0xdb, 0x47, 0x12, 0x70, 0x50, 0xff, 0x0e, 0x8e, 0xee, 0x44, 0xfe, + 0xb9, 0x0e, 0xb0, 0xc7, 0xeb, 0xe0, 0x43, 0xae, 0x4b, 0xde, 0x0f, 0xb7, 0xdf, 0xd9, 0xe9, 0x01, 0x34, 0x38, 0xab, + 0xa8, 0xe9, 0x77, 0x58, 0xff, 0x01, 0x2b, 0x91, 0xde, 0x9b, 0x76, 0x7a, 0xaf, 0xbd, 0x58, 0x8b, 0x20, 0x11, 0x99, + 0xb7, 0xb0, 0xe0, 0x8a, 0x8f, 0xb8, 0x97, 0x63, 0x3c, 0x25, 0x1e, 0x45, 0x7f, 0x99, 0x02, 0x6e, 0xc4, 0x8b, 0x2a, + 0xe2, 0x9f, 0xbe, 0xbf, 0x4c, 0xd2, 0x38, 0xe9, 0x2d, 0xe2, 0x20, 0xca, 0x58, 0x92, 0x23, 0xa8, 0xae, 0x11, 0x3e, + 0x02, 0x3c, 0x37, 0xeb, 0x78, 0xe1, 0xf9, 0x41, 0xf6, 0xd0, 0x73, 0x38, 0x4b, 0xe1, 0xf4, 0x39, 0x77, 0xe0, 0x34, + 0xd6, 0xef, 0x71, 0x68, 0xbe, 0x44, 0xc6, 0x2f, 0xa9, 0xb3, 0x33, 0xea, 0x36, 0xef, 0x2b, 0x6f, 0x29, 0x4c, 0x06, + 0xb0, 0x1f, 0x5e, 0x62, 0x4d, 0x01, 0xcb, 0xc3, 0x52, 0x3b, 0x63, 0x36, 0x35, 0x11, 0x6b, 0x83, 0x5c, 0x5e, 0xfc, + 0xd9, 0x5d, 0x43, 0x73, 0x9a, 0x8b, 0x81, 0xe3, 0x31, 0xf6, 0x19, 0x59, 0xcf, 0x83, 0xa4, 0x52, 0xe6, 0x3e, 0x35, + 0x47, 0x6c, 0x12, 0x27, 0x8c, 0x42, 0xaa, 0xba, 0x27, 0x8b, 0xd5, 0xfe, 0xdd, 0x6f, 0x9f, 0x7e, 0x73, 0x3f, 0x51, + 0x9c, 0xb5, 0x44, 0x67, 0xc6, 0x8e, 0xde, 0xea, 0xf4, 0x0c, 0x58, 0x43, 0x82, 0xbc, 0x4f, 0xd1, 0xab, 0x7a, 0xba, + 0xde, 0x6f, 0x8c, 0x5c, 0xb5, 0x88, 0x39, 0xcd, 0x4b, 0x58, 0xe8, 0x65, 0xc1, 0x9d, 0xe0, 0x19, 0x3b, 0x47, 0x8b, + 0x95, 0x58, 0x63, 0x24, 0x78, 0x8f, 0x58, 0xa4, 0xca, 0x50, 0xc4, 0x22, 0x55, 0x8b, 0x71, 0x91, 0xfa, 0xb5, 0xd9, + 0x88, 0x60, 0x0e, 0x15, 0x4a, 0xdf, 0x5d, 0xac, 0x54, 0x12, 0x5d, 0x34, 0x93, 0x94, 0xba, 0x1a, 0x85, 0x6b, 0x1e, + 0x8c, 0xc7, 0x21, 0xcb, 0x4b, 0x0b, 0x5d, 0x5e, 0x4b, 0x05, 0x38, 0x12, 0x0e, 0xde, 0x28, 0x8d, 0xc3, 0x65, 0xc6, + 0x9a, 0xc1, 0x45, 0xc0, 0x69, 0x3b, 0x05, 0x70, 0xf0, 0x77, 0x79, 0xac, 0x5d, 0x60, 0xb7, 0x61, 0x9b, 0x38, 0x7d, + 0x08, 0xba, 0x6b, 0x75, 0xca, 0x43, 0x87, 0x57, 0x72, 0xd0, 0x66, 0xc3, 0x44, 0x4c, 0x20, 0x4b, 0x84, 0xbd, 0x35, + 0xdb, 0xe5, 0x65, 0x32, 0xf0, 0xa8, 0x2c, 0xca, 0xcb, 0x93, 0xf9, 0x73, 0xce, 0xd8, 0xab, 0xe6, 0x33, 0xf6, 0x4a, + 0x9c, 0xb1, 0xed, 0x3b, 0xf3, 0xe9, 0xc4, 0x85, 0xff, 0xfa, 0xc5, 0x84, 0x7a, 0x8e, 0xd6, 0x59, 0xac, 0x34, 0x77, + 0xb1, 0xd2, 0xac, 0xf6, 0x62, 0xa5, 0x61, 0xd7, 0x68, 0x7f, 0x61, 0xda, 0x6d, 0xc3, 0x74, 0x34, 0x28, 0x84, 0x3f, + 0xa7, 0xf4, 0xca, 0x3d, 0x84, 0x77, 0xd0, 0xaa, 0x5b, 0x7f, 0xd7, 0xde, 0x7e, 0xd4, 0xe9, 0x2c, 0x09, 0xa4, 0x6d, + 0xd8, 0x99, 0x37, 0x1a, 0xb1, 0x71, 0x6f, 0x12, 0xfb, 0xcb, 0xf4, 0xdf, 0x7c, 0xfc, 0x1c, 0x88, 0x5b, 0x11, 0x41, + 0xa5, 0x1f, 0xd1, 0x14, 0x14, 0x25, 0x77, 0x4c, 0xf4, 0xb0, 0x96, 0xeb, 0xd4, 0xa3, 0x08, 0xc1, 0x6d, 0xfb, 0xb0, + 0x61, 0x93, 0x37, 0x03, 0xfa, 0x4f, 0x5b, 0xa5, 0xcd, 0x28, 0xe6, 0x33, 0xc0, 0xb2, 0x15, 0x1c, 0x8f, 0x87, 0x06, + 0x5f, 0x4d, 0xe7, 0xa4, 0x79, 0xb8, 0xd7, 0xe2, 0x4b, 0x37, 0x82, 0xa8, 0x70, 0xba, 0xc5, 0x9d, 0x3e, 0xb6, 0xf7, + 0xba, 0x69, 0x8f, 0xd4, 0x7a, 0xdd, 0x42, 0x10, 0x8a, 0xba, 0x7b, 0x62, 0xf9, 0xa7, 0xaf, 0x0e, 0xe1, 0x3f, 0xe2, + 0xea, 0x7f, 0xce, 0x9a, 0x18, 0xf5, 0x8b, 0xb2, 0x95, 0x35, 0xb1, 0x4a, 0xc8, 0x88, 0xef, 0x5f, 0x7f, 0x32, 0x79, + 0x5c, 0x83, 0xbd, 0x6b, 0x93, 0xe9, 0x52, 0xb5, 0xf6, 0xb7, 0x71, 0x0c, 0xd9, 0x2b, 0xeb, 0xd5, 0x05, 0x78, 0xc8, + 0x90, 0x3c, 0x1b, 0x40, 0x23, 0x71, 0x8f, 0x20, 0x2d, 0xbe, 0x8e, 0x6d, 0xe8, 0x2a, 0xf1, 0x76, 0xd3, 0x55, 0xe2, + 0xcd, 0xee, 0xab, 0xc4, 0xf7, 0x7b, 0x5d, 0x25, 0xde, 0x7c, 0xf1, 0xab, 0xc4, 0xdb, 0xfa, 0x55, 0xe2, 0x2a, 0x16, + 0xd6, 0xaa, 0xe6, 0xc5, 0x92, 0xff, 0xfc, 0x48, 0x4a, 0xb9, 0xcb, 0x78, 0xd0, 0x75, 0x28, 0xea, 0xef, 0xd5, 0x1f, + 0xbe, 0x58, 0xe0, 0x46, 0x7c, 0x8f, 0xe6, 0x5b, 0xc5, 0xd5, 0x82, 0x63, 0x76, 0xfc, 0x8e, 0x52, 0x1c, 0xc6, 0xd1, + 0xf4, 0x27, 0x50, 0xca, 0x82, 0x38, 0x30, 0x51, 0x5e, 0x04, 0xe9, 0x4f, 0xf1, 0x62, 0xb9, 0xb8, 0x80, 0xbe, 0x3e, + 0x06, 0x69, 0x30, 0x0a, 0x99, 0x74, 0xc6, 0x25, 0x73, 0x33, 0x2e, 0x13, 0x07, 0xfb, 0x4e, 0xf1, 0xd3, 0x5b, 0x89, + 0x9f, 0x68, 0x01, 0xca, 0x7f, 0x93, 0x1d, 0x9b, 0xde, 0x7c, 0x11, 0x11, 0x4a, 0x40, 0x65, 0xd0, 0x8f, 0xbf, 0x8c, + 0x5c, 0xc5, 0x46, 0xc3, 0x2c, 0x85, 0xbd, 0xc3, 0xc6, 0x7e, 0x58, 0xed, 0x52, 0xb3, 0x34, 0x4c, 0x19, 0x85, 0xaa, + 0x2e, 0x86, 0x9f, 0xc7, 0xcb, 0x94, 0x8d, 0xe3, 0xfb, 0x48, 0x37, 0x23, 0x69, 0xc0, 0x0f, 0x1a, 0x4e, 0xd9, 0x06, + 0xf3, 0x27, 0x7e, 0x40, 0x46, 0x39, 0x4e, 0x5a, 0x3a, 0xa4, 0xef, 0x5c, 0x2e, 0x2c, 0x52, 0x35, 0x5b, 0x38, 0x45, + 0x5d, 0x26, 0xfa, 0x79, 0xd2, 0x6a, 0xc5, 0x83, 0xc7, 0xb5, 0x14, 0xa6, 0x1a, 0xb1, 0xcd, 0xa5, 0xc2, 0x69, 0x2b, + 0x12, 0xc2, 0x45, 0x11, 0x0a, 0xa2, 0x61, 0xe1, 0xf8, 0x1b, 0x72, 0x0b, 0x2d, 0xde, 0x42, 0x20, 0x8d, 0x7c, 0xc9, + 0xd7, 0x83, 0x07, 0x46, 0xa0, 0xc7, 0xd7, 0x0a, 0x18, 0xdf, 0xdd, 0xb1, 0x24, 0xf4, 0x1e, 0x5a, 0x46, 0x1e, 0x47, + 0x3f, 0x00, 0x00, 0xde, 0xc4, 0xf7, 0x91, 0x5a, 0x01, 0xf3, 0x95, 0x34, 0xec, 0xa5, 0xc6, 0x10, 0x1e, 0xe0, 0x14, + 0xa2, 0x8c, 0x00, 0x32, 0xc5, 0x4e, 0xd9, 0x3f, 0x4c, 0xfa, 0xf7, 0x9f, 0x46, 0x6e, 0x5e, 0xc6, 0xf2, 0x43, 0x7f, + 0x5f, 0xec, 0xf1, 0x99, 0xe7, 0xcf, 0x9f, 0x6c, 0x9e, 0x76, 0x39, 0x43, 0x79, 0x43, 0x6b, 0x63, 0xe3, 0x29, 0x80, + 0x51, 0x5c, 0xc5, 0x4b, 0x7f, 0x86, 0x86, 0xa5, 0x5f, 0x6e, 0xbe, 0x19, 0xf4, 0x89, 0x89, 0x3a, 0xe5, 0xd4, 0x2b, + 0x45, 0x05, 0x14, 0xf0, 0xfb, 0x6f, 0x21, 0x06, 0xe5, 0xff, 0x11, 0x0c, 0xf5, 0x5d, 0xc3, 0x6f, 0xf1, 0xc1, 0xe3, + 0x36, 0x6f, 0x1f, 0xf2, 0x49, 0xf2, 0xe8, 0x0e, 0x42, 0xb9, 0xd6, 0x8c, 0x64, 0xf2, 0x2a, 0xd0, 0xd4, 0x48, 0x6a, + 0x9b, 0x82, 0xc4, 0x89, 0xaf, 0x30, 0x9b, 0xae, 0xe9, 0xdc, 0xac, 0xdf, 0x64, 0x1c, 0x5b, 0x55, 0x90, 0x0c, 0x37, + 0x79, 0x60, 0x88, 0xbe, 0xaa, 0xef, 0xe6, 0x41, 0x64, 0x62, 0x20, 0xf4, 0xfa, 0x1b, 0x6f, 0x05, 0xa1, 0x80, 0x01, + 0xb9, 0x55, 0x5f, 0x41, 0xa1, 0xa9, 0xfa, 0xa4, 0x41, 0xb6, 0x23, 0xbd, 0x11, 0x12, 0x42, 0x8b, 0x37, 0xfc, 0x8b, + 0xa6, 0x69, 0x9a, 0xbc, 0x46, 0x68, 0xf2, 0x1e, 0x81, 0xe5, 0x78, 0x1d, 0x00, 0x6d, 0x49, 0xbe, 0x58, 0x51, 0x09, + 0xdc, 0x0c, 0x50, 0x27, 0x2b, 0x0a, 0x78, 0xb4, 0xbb, 0xae, 0x23, 0x0a, 0xc4, 0x85, 0x1e, 0x22, 0x95, 0x79, 0x09, + 0x04, 0xc5, 0xed, 0x69, 0x78, 0x61, 0xc7, 0xb7, 0x5c, 0x12, 0xac, 0x39, 0xf4, 0x38, 0xec, 0xb3, 0xe6, 0xb0, 0x68, + 0x91, 0x82, 0x05, 0x41, 0xeb, 0x50, 0x89, 0x72, 0x6c, 0xb2, 0x06, 0xdc, 0x88, 0xf7, 0xa2, 0x55, 0x36, 0x67, 0xd1, + 0x52, 0xc7, 0xb4, 0x48, 0x18, 0xa6, 0x0e, 0xea, 0xbc, 0x21, 0x66, 0x0b, 0xb0, 0x4d, 0x73, 0xcb, 0x19, 0xd1, 0xc2, + 0x94, 0xa3, 0x54, 0xcf, 0xf4, 0xb9, 0x62, 0x33, 0xe5, 0xb8, 0xad, 0x4a, 0x21, 0xf8, 0x92, 0xc6, 0x55, 0x27, 0x29, + 0xb2, 0x3c, 0x86, 0x3e, 0x28, 0x40, 0x04, 0x17, 0x17, 0x09, 0xb0, 0xb7, 0xbc, 0xea, 0xa2, 0x49, 0x8d, 0x8c, 0x57, + 0x11, 0x14, 0x25, 0x46, 0xbd, 0x1b, 0x3e, 0x4e, 0x88, 0xcd, 0xb3, 0xb1, 0x1f, 0xbf, 0xd6, 0xcf, 0x86, 0x49, 0x7f, + 0x62, 0x0f, 0x44, 0x48, 0x08, 0x54, 0x9f, 0xd8, 0x03, 0xd8, 0xfe, 0xbd, 0x05, 0x69, 0x8a, 0xbe, 0x05, 0x5d, 0x9b, + 0x10, 0xed, 0xde, 0x87, 0x78, 0x4d, 0x5b, 0x0e, 0x90, 0x93, 0x6f, 0xc1, 0xe2, 0x08, 0x62, 0x48, 0x6c, 0x2c, 0x0e, + 0x31, 0x37, 0xa9, 0x6f, 0x35, 0xc2, 0xd8, 0x6a, 0x38, 0x1a, 0xc6, 0x0b, 0xd7, 0x71, 0x0e, 0x6a, 0xf5, 0x41, 0x90, + 0xdd, 0x54, 0xdb, 0x30, 0xb3, 0x81, 0xeb, 0x58, 0xc1, 0x0b, 0xbb, 0xdd, 0xaf, 0xd1, 0x68, 0x25, 0x9c, 0xe2, 0x10, + 0xc5, 0x5f, 0x67, 0xcf, 0xd6, 0xad, 0xda, 0x81, 0x34, 0xaa, 0x26, 0xea, 0x38, 0xb6, 0x9c, 0xcb, 0xbf, 0x86, 0x75, + 0xd2, 0x4f, 0xc1, 0x1c, 0x29, 0xb5, 0xc7, 0x10, 0x02, 0x02, 0xb7, 0xe0, 0x18, 0xfd, 0x55, 0x7b, 0xa9, 0xb5, 0xe8, + 0xf8, 0x18, 0xc6, 0x50, 0x66, 0x8c, 0x16, 0x1e, 0x5c, 0x6a, 0x07, 0x95, 0x2f, 0xa6, 0x55, 0x0c, 0xc7, 0x43, 0x8f, + 0xb2, 0x42, 0xa3, 0xb7, 0x95, 0x5b, 0xc0, 0xfe, 0x37, 0x90, 0x4f, 0x7b, 0x04, 0x3e, 0xff, 0x50, 0x03, 0xc2, 0x87, + 0xef, 0xec, 0x70, 0xb9, 0x28, 0x77, 0x57, 0x26, 0x92, 0xfb, 0x77, 0x86, 0x44, 0x07, 0x75, 0x68, 0xb2, 0xbf, 0x66, + 0x72, 0xf7, 0xc8, 0x2e, 0x59, 0x34, 0x2e, 0x77, 0x58, 0xa1, 0x5f, 0xfb, 0x77, 0x57, 0xc2, 0x28, 0x10, 0x57, 0x3f, + 0x6e, 0xc0, 0x28, 0x79, 0x1c, 0xe1, 0xe6, 0xa7, 0xe3, 0x16, 0xec, 0xc5, 0xc5, 0x60, 0x03, 0x0a, 0x8a, 0x25, 0x9b, + 0x29, 0x42, 0x71, 0x08, 0xde, 0x8c, 0x2e, 0xb7, 0x2d, 0xc1, 0x88, 0x6e, 0xdc, 0x89, 0x99, 0xb0, 0x29, 0x2c, 0xda, + 0x04, 0x3c, 0x1c, 0xe3, 0xbe, 0x52, 0xeb, 0x60, 0xb7, 0xd4, 0x3a, 0xdb, 0x25, 0xb5, 0x26, 0xef, 0xa5, 0xfb, 0xc4, + 0x5b, 0x28, 0xfe, 0x6f, 0x82, 0x39, 0x57, 0xdd, 0xe0, 0x4a, 0xa2, 0x6e, 0x74, 0x76, 0x12, 0xad, 0x6a, 0xbd, 0x91, + 0x95, 0x20, 0x8a, 0xbf, 0x95, 0x0b, 0x8a, 0x50, 0xa8, 0xab, 0xb2, 0xf1, 0xab, 0x42, 0x36, 0x4e, 0xb7, 0x9a, 0xc2, + 0x71, 0x45, 0x70, 0xff, 0x8a, 0x4b, 0x98, 0xbc, 0x1d, 0x14, 0xae, 0x61, 0xc5, 0x48, 0x15, 0x6f, 0xa7, 0xe2, 0xa2, + 0xa1, 0xb8, 0xd0, 0x89, 0x5b, 0x46, 0xd9, 0x93, 0xae, 0x5c, 0xb5, 0x70, 0xa9, 0x2b, 0xca, 0x41, 0xea, 0x8e, 0x43, + 0x96, 0xc5, 0xea, 0xb6, 0x29, 0xbb, 0xbb, 0xa8, 0xaf, 0x95, 0x4d, 0x22, 0xfd, 0x52, 0x08, 0xc0, 0x42, 0x4c, 0x5f, + 0xd1, 0x6b, 0x4b, 0x1b, 0x08, 0x1c, 0x64, 0x83, 0x13, 0xdd, 0x6e, 0xe9, 0x3c, 0xa5, 0x0c, 0x28, 0xb4, 0xf0, 0xaa, + 0x0c, 0x02, 0xe1, 0x7b, 0xb3, 0x6e, 0xa0, 0xf2, 0x48, 0xe4, 0x39, 0x7d, 0x07, 0xf1, 0xa2, 0xe6, 0xa8, 0x8a, 0x7c, + 0x3c, 0x99, 0x16, 0x99, 0xe7, 0x62, 0xd5, 0x7a, 0xa7, 0x24, 0xc4, 0x59, 0x73, 0x4f, 0x94, 0xb2, 0x8c, 0x9e, 0xd7, + 0xe8, 0x89, 0xef, 0xf2, 0xad, 0x93, 0x2c, 0x23, 0x0c, 0xef, 0x6e, 0x65, 0x89, 0xe7, 0x7f, 0x52, 0x86, 0x2c, 0xe4, + 0x9c, 0x20, 0x03, 0x2e, 0x6b, 0x0a, 0xfa, 0x1e, 0x46, 0x43, 0x64, 0x3d, 0xbb, 0x9d, 0x2a, 0xd2, 0x97, 0xde, 0x53, + 0xa7, 0xe3, 0xbd, 0x9a, 0x1c, 0x56, 0x84, 0xa2, 0xed, 0x6e, 0x59, 0x64, 0xbe, 0x61, 0x1c, 0xd9, 0x6c, 0x39, 0x1f, + 0xad, 0x55, 0xd9, 0xaa, 0x22, 0x72, 0xad, 0x8b, 0x59, 0xd5, 0xcf, 0x4e, 0x26, 0x93, 0xb2, 0xa0, 0xd1, 0xd1, 0x0e, + 0x51, 0x58, 0xf8, 0xd4, 0x71, 0x9c, 0xea, 0xd8, 0xb7, 0x83, 0xdd, 0x42, 0xb9, 0xed, 0x49, 0xe3, 0x88, 0x11, 0xb6, + 0xbb, 0xe0, 0x57, 0x07, 0x47, 0x6e, 0x17, 0x27, 0xbb, 0x64, 0x16, 0xd1, 0x27, 0x63, 0x88, 0x20, 0x63, 0xf3, 0xb4, + 0xe7, 0x33, 0xd4, 0xc1, 0xd8, 0xca, 0x81, 0x46, 0xc3, 0x01, 0x6b, 0x0a, 0xa6, 0x22, 0xae, 0xd8, 0x15, 0x8e, 0x86, + 0xf2, 0xf0, 0x9a, 0xf0, 0x5e, 0x7c, 0x04, 0x0f, 0xca, 0xba, 0x2e, 0xd3, 0xc6, 0x69, 0x75, 0x9d, 0xbf, 0x96, 0xea, + 0x69, 0x40, 0x00, 0xd7, 0x42, 0xa1, 0x4d, 0xf2, 0x59, 0xfc, 0x7f, 0x29, 0xff, 0x7f, 0xb5, 0x58, 0x95, 0xed, 0x47, + 0x4e, 0x40, 0xa2, 0x5d, 0x9c, 0x16, 0x1a, 0x75, 0xd3, 0x1e, 0x90, 0x56, 0x06, 0x13, 0x55, 0x81, 0x0e, 0x4a, 0xfa, + 0x52, 0x0e, 0x8c, 0x06, 0xf1, 0x3b, 0x72, 0xcc, 0xb0, 0xc4, 0x85, 0x08, 0xb1, 0xc8, 0xe0, 0x06, 0x73, 0x30, 0x5f, + 0x9e, 0xa0, 0xfe, 0xa0, 0xb4, 0x27, 0x40, 0x1b, 0x5f, 0x9b, 0xdb, 0x5e, 0xe2, 0xfe, 0xaa, 0x5e, 0x4b, 0x74, 0x0c, + 0x20, 0x73, 0xe1, 0x10, 0xa2, 0x21, 0x81, 0x56, 0xd9, 0xdc, 0x34, 0x4a, 0xf9, 0x56, 0xd5, 0xb3, 0x89, 0x81, 0x61, + 0x77, 0xcd, 0x55, 0xa8, 0x6f, 0xa1, 0x2d, 0x80, 0xc9, 0xf2, 0xed, 0x87, 0xcf, 0x16, 0x2c, 0xb1, 0xba, 0x1f, 0x5d, + 0x5c, 0x72, 0xdc, 0xbf, 0x16, 0xd2, 0xce, 0x94, 0xce, 0x3f, 0xca, 0x17, 0xbf, 0x6f, 0x14, 0xe8, 0x5d, 0x95, 0x24, + 0x74, 0xdc, 0x5a, 0xbc, 0x6d, 0xec, 0x55, 0x7b, 0x1e, 0x44, 0xfb, 0xd7, 0xf5, 0x56, 0x7b, 0xd7, 0x05, 0x82, 0xb1, + 0x77, 0x65, 0xa0, 0x38, 0x64, 0xb9, 0x90, 0x0d, 0xbe, 0x57, 0x04, 0x8a, 0xaa, 0x93, 0xaf, 0x8e, 0xad, 0x88, 0xcb, + 0xbf, 0x5a, 0x02, 0xf3, 0xb9, 0x57, 0x8e, 0x03, 0x4d, 0xa4, 0x29, 0xd3, 0x8f, 0xb5, 0x13, 0xed, 0xb8, 0xa3, 0x1d, + 0x39, 0x3a, 0xdd, 0xc2, 0x06, 0x7a, 0xb7, 0x5d, 0x78, 0xef, 0x1d, 0x3a, 0xfa, 0xd9, 0xe9, 0x54, 0x10, 0x89, 0x49, + 0x10, 0x86, 0x84, 0x2a, 0xd2, 0x2c, 0x89, 0x3f, 0xb1, 0xb2, 0x9a, 0x85, 0xca, 0xb8, 0x11, 0x48, 0x5b, 0x3c, 0xc2, + 0xd9, 0xf1, 0xbd, 0x45, 0x0f, 0xcf, 0x86, 0x5a, 0x08, 0x06, 0x9c, 0x54, 0x8a, 0x9f, 0x00, 0x1a, 0x3c, 0xd2, 0xcf, + 0x4e, 0x21, 0x8a, 0x9f, 0x36, 0x1e, 0xe8, 0x3f, 0xb4, 0x8f, 0x35, 0xb7, 0x7b, 0x67, 0x75, 0x7c, 0xc7, 0x72, 0xed, + 0x43, 0xcd, 0xb1, 0x8f, 0xac, 0xb6, 0x7d, 0xac, 0xb5, 0xed, 0x2e, 0xfc, 0xeb, 0xbb, 0xf6, 0x2b, 0xcd, 0x81, 0x27, + 0xcd, 0xb5, 0x3b, 0xf8, 0x6f, 0xdb, 0x3e, 0xbe, 0xeb, 0x10, 0xa5, 0xf7, 0x74, 0x31, 0xe4, 0xca, 0x28, 0xc0, 0x09, + 0x44, 0x3f, 0x38, 0x3b, 0x5d, 0xa6, 0x4c, 0x5b, 0x0d, 0xf4, 0x57, 0xba, 0x36, 0x4b, 0xd8, 0x64, 0xa0, 0x3f, 0xf5, + 0x94, 0x52, 0xf7, 0xa4, 0xb1, 0xb8, 0x7d, 0xdc, 0x58, 0xdc, 0x39, 0x6a, 0x2c, 0x3e, 0xec, 0x96, 0x8b, 0x0f, 0xa6, + 0xf4, 0x4a, 0x49, 0xa2, 0x37, 0xf7, 0xb2, 0x24, 0x58, 0xb5, 0x5c, 0x0d, 0xd0, 0xb5, 0x05, 0xff, 0x1c, 0xb7, 0x0d, + 0xd9, 0x6a, 0x04, 0xad, 0x24, 0x34, 0x8e, 0x4f, 0x34, 0xf7, 0xe8, 0x6f, 0xed, 0x23, 0x1f, 0xea, 0x41, 0xca, 0x47, + 0xf8, 0xbb, 0xeb, 0x9c, 0xf8, 0x8e, 0x06, 0x0d, 0x5d, 0xf8, 0x6f, 0xd6, 0x6d, 0xfb, 0xf4, 0xe0, 0xc0, 0xfb, 0x8f, + 0xee, 0x71, 0xea, 0x58, 0x2e, 0xfc, 0xf7, 0xab, 0x54, 0xb9, 0x83, 0xc2, 0x5f, 0xed, 0xf7, 0xd0, 0xd1, 0x3a, 0x27, + 0xb3, 0xb6, 0xfd, 0xea, 0xee, 0xd8, 0x3e, 0x99, 0xb9, 0xc7, 0x1f, 0xe9, 0x29, 0xb4, 0xda, 0xf6, 0x2b, 0xf8, 0xfb, + 0xd8, 0x71, 0x66, 0x96, 0x6b, 0x9f, 0xdc, 0x75, 0xec, 0x4e, 0x68, 0x1d, 0xd9, 0x27, 0xf0, 0xf7, 0x2b, 0x80, 0x17, + 0xe0, 0xca, 0x73, 0x74, 0x6a, 0xb0, 0x31, 0x2a, 0xf6, 0x1b, 0xea, 0x47, 0xda, 0x87, 0x5a, 0xf7, 0xf0, 0x6f, 0x27, + 0x77, 0xd6, 0xe1, 0xcc, 0x6d, 0xdf, 0x59, 0x1b, 0x7f, 0x7e, 0x04, 0xc8, 0x6f, 0x5f, 0x38, 0x00, 0x23, 0x26, 0xe5, + 0xf8, 0xcb, 0xd0, 0xbc, 0xdc, 0x24, 0x46, 0x7f, 0xbf, 0x5b, 0x8c, 0xfe, 0xdd, 0x72, 0x1f, 0x31, 0xfa, 0xfb, 0x2f, + 0x2e, 0x46, 0xbf, 0xac, 0x5a, 0x71, 0xbf, 0xaf, 0x06, 0x0f, 0xff, 0x79, 0x5d, 0x65, 0x92, 0x03, 0xaf, 0x75, 0x7d, + 0xb5, 0xbc, 0x81, 0xb8, 0x3a, 0xef, 0xe3, 0xc1, 0x77, 0xcb, 0x92, 0x89, 0x52, 0x0c, 0x18, 0xe0, 0x7d, 0x4c, 0x18, + 0xe0, 0xd7, 0xe5, 0x00, 0xec, 0x22, 0x38, 0xd5, 0x0c, 0xc6, 0xd6, 0xcc, 0x0b, 0x27, 0x92, 0xe2, 0x42, 0x49, 0x1f, + 0x8b, 0xc1, 0x66, 0x1e, 0x88, 0x09, 0x28, 0x6b, 0x96, 0xf3, 0x28, 0xed, 0x1d, 0x39, 0x80, 0xe6, 0xdb, 0x93, 0x24, + 0xaf, 0x34, 0xb6, 0x45, 0x24, 0xa2, 0x5b, 0x6e, 0xd3, 0xbf, 0xf1, 0x3d, 0x9a, 0xac, 0x35, 0xf7, 0xee, 0xd6, 0xfb, + 0xd5, 0xc0, 0x16, 0x44, 0x98, 0xf4, 0x01, 0xb3, 0xd1, 0xf4, 0xbe, 0x6c, 0x38, 0x56, 0x31, 0x15, 0xdc, 0x3c, 0x52, + 0x18, 0x49, 0xb5, 0xbd, 0x5b, 0x36, 0x3c, 0xdb, 0x35, 0xcd, 0x86, 0xcf, 0x97, 0x9a, 0x6f, 0xb1, 0x7a, 0x93, 0x1d, + 0x57, 0x41, 0x55, 0x49, 0x7d, 0xd5, 0x08, 0x90, 0x82, 0xf7, 0x2c, 0x4c, 0xe3, 0x0a, 0xc6, 0xc7, 0xd1, 0x90, 0x1a, + 0x3b, 0xca, 0xbb, 0x52, 0x9f, 0xaa, 0x39, 0xdd, 0x8b, 0x35, 0xf2, 0x83, 0xc1, 0xaf, 0xc0, 0xd8, 0x70, 0x7a, 0x3c, + 0x8a, 0x55, 0x38, 0xaf, 0x95, 0x7e, 0x89, 0xd5, 0xce, 0x67, 0xee, 0xba, 0xce, 0xda, 0x6c, 0x34, 0xa4, 0x75, 0xd9, + 0x5c, 0xd0, 0x68, 0xfc, 0x3c, 0x99, 0xad, 0xe6, 0x64, 0x5a, 0x8c, 0x96, 0xb9, 0xdb, 0x3a, 0x13, 0xf5, 0x9e, 0xc2, + 0x26, 0x36, 0xf9, 0x83, 0xea, 0x25, 0xbe, 0x9e, 0x40, 0x9a, 0xe2, 0x1e, 0x32, 0x11, 0x0a, 0x07, 0xd5, 0x46, 0x1b, + 0xdb, 0xfe, 0x16, 0xf3, 0x0f, 0xb5, 0x63, 0xde, 0x09, 0xda, 0xea, 0x6e, 0xb3, 0x18, 0x91, 0xae, 0x0d, 0xeb, 0x92, + 0x02, 0xd5, 0xed, 0x1e, 0x9b, 0xee, 0x91, 0x69, 0x1f, 0x77, 0x8d, 0x5c, 0x1c, 0x38, 0xb5, 0xcb, 0x12, 0x40, 0xc0, + 0x64, 0x57, 0x0e, 0x33, 0x88, 0x82, 0x2c, 0xf0, 0xc2, 0x1c, 0x50, 0x7d, 0x99, 0xe7, 0xfd, 0xd7, 0x32, 0xcd, 0x60, + 0x8e, 0x82, 0x25, 0x43, 0x73, 0x65, 0x6b, 0xc4, 0xb2, 0x7b, 0xc6, 0xa2, 0x0d, 0xaa, 0xdc, 0xaa, 0xf5, 0xf3, 0x9f, + 0x67, 0x0b, 0x9a, 0x93, 0x9d, 0xc5, 0x28, 0x8b, 0xf8, 0xfe, 0x10, 0xa6, 0xba, 0xf9, 0xd0, 0xfc, 0x71, 0x13, 0xc2, + 0xfd, 0xd7, 0x6e, 0x84, 0x9b, 0xb1, 0x7d, 0x10, 0xee, 0xbf, 0xbe, 0x38, 0xc2, 0xfd, 0x51, 0x45, 0xb8, 0x25, 0x4f, + 0x95, 0x42, 0x26, 0xfa, 0x01, 0x9f, 0x5b, 0x10, 0x75, 0xf7, 0xa5, 0x7e, 0x40, 0xec, 0xa5, 0xae, 0x64, 0x43, 0xfd, + 0x58, 0x4a, 0xef, 0x82, 0x57, 0x76, 0x0c, 0x3f, 0x4a, 0xa9, 0x24, 0x20, 0x53, 0xa8, 0xcc, 0x79, 0x0d, 0x7d, 0x5e, + 0x44, 0x59, 0x68, 0xbf, 0xe7, 0xd7, 0x12, 0x50, 0x41, 0x7c, 0x17, 0x27, 0x73, 0x0f, 0x43, 0xaf, 0xe9, 0x98, 0x16, + 0x0e, 0x1e, 0x1c, 0xf0, 0x8e, 0xf2, 0xe3, 0x68, 0x2c, 0xe5, 0xe8, 0x6c, 0x70, 0x4d, 0xfc, 0xa0, 0xfe, 0xc0, 0xbc, + 0x44, 0x37, 0xe9, 0x35, 0x2c, 0xee, 0x8b, 0x8e, 0xf3, 0xa2, 0x7d, 0xf8, 0xe2, 0xc8, 0x81, 0xff, 0xb9, 0xac, 0x93, + 0x9b, 0xbc, 0xe2, 0x3c, 0x8e, 0x20, 0x33, 0x85, 0xa8, 0xb9, 0xa9, 0xda, 0x3d, 0x63, 0x9f, 0x8a, 0x5a, 0xc7, 0xcd, + 0x95, 0xc6, 0xde, 0x43, 0x51, 0xa7, 0xb1, 0xc6, 0x2c, 0x5e, 0x2a, 0xc3, 0x6a, 0x18, 0x4d, 0x10, 0x2d, 0x41, 0x32, + 0xa4, 0xd4, 0x50, 0x5f, 0xf3, 0xe9, 0x16, 0xf3, 0x62, 0x9d, 0xfc, 0xa6, 0x48, 0x7f, 0x23, 0xd2, 0x70, 0xec, 0x84, + 0x20, 0x17, 0xaa, 0x3b, 0x18, 0x3c, 0x1b, 0x13, 0xc0, 0x68, 0x90, 0x7c, 0xae, 0xc8, 0x71, 0x8e, 0x0b, 0x94, 0x25, + 0xcb, 0xc8, 0xa7, 0x34, 0xe6, 0xde, 0x28, 0x6d, 0x05, 0x07, 0x10, 0x97, 0x13, 0x3f, 0x6c, 0xe0, 0xaa, 0x79, 0x67, + 0x4e, 0x91, 0x2b, 0x20, 0x15, 0xab, 0xe2, 0xbd, 0xc8, 0xcc, 0x84, 0x32, 0x8c, 0xe2, 0xd2, 0x5a, 0x03, 0xef, 0x85, + 0x6c, 0xf8, 0x22, 0x33, 0x21, 0xcb, 0x27, 0x2c, 0xf7, 0xf3, 0xe7, 0x54, 0x0b, 0xf2, 0xee, 0xd1, 0xb4, 0xce, 0x7d, + 0x99, 0xab, 0x4b, 0xd7, 0xbc, 0x69, 0xac, 0x63, 0xae, 0xae, 0x9e, 0x6f, 0xc6, 0x2f, 0x5f, 0x9e, 0x0d, 0x5c, 0x83, + 0x67, 0x8d, 0x2c, 0xa5, 0x38, 0xba, 0xdc, 0x4f, 0x35, 0x6e, 0x34, 0x3a, 0x6d, 0x2d, 0x82, 0x68, 0x2a, 0x34, 0xd3, + 0x12, 0x7b, 0x41, 0xca, 0x01, 0x52, 0x81, 0x79, 0x42, 0x45, 0x2d, 0xea, 0xdc, 0xb1, 0x04, 0x32, 0x5e, 0x0e, 0xf4, + 0x8e, 0xed, 0xd8, 0x8e, 0x2e, 0x1b, 0x4e, 0x82, 0xe9, 0x60, 0x1d, 0x67, 0x1e, 0x24, 0x6f, 0x09, 0xe3, 0x29, 0x78, + 0x7e, 0x64, 0x41, 0x16, 0x42, 0x26, 0x10, 0x70, 0x01, 0x99, 0xd3, 0xad, 0x31, 0xe7, 0xf6, 0xb8, 0x5e, 0xf2, 0x09, + 0xb3, 0xc1, 0x09, 0xa7, 0x2f, 0x8c, 0x3f, 0xf3, 0x03, 0x10, 0xc3, 0x96, 0xde, 0x82, 0x5c, 0x84, 0x2c, 0x49, 0x2d, + 0xd5, 0xbe, 0xbd, 0xa7, 0x41, 0x1b, 0xc8, 0x13, 0x8e, 0x1d, 0x4c, 0x12, 0x6f, 0x0e, 0x41, 0xb3, 0xd7, 0xb9, 0xc9, + 0x31, 0xad, 0xce, 0x51, 0xad, 0xe6, 0xbe, 0x3a, 0x32, 0xb5, 0xb6, 0x6b, 0x6a, 0x0e, 0xa0, 0x5b, 0x3d, 0x37, 0xd7, + 0xf9, 0x4d, 0x7f, 0x97, 0x8a, 0x8e, 0xf0, 0xcb, 0x53, 0x9a, 0x07, 0x29, 0xe7, 0xb8, 0xf0, 0x33, 0xa3, 0xd0, 0x81, + 0x2d, 0x25, 0x9c, 0x75, 0x40, 0x62, 0xfa, 0x2b, 0xb6, 0xca, 0x0c, 0xcc, 0x94, 0xc1, 0xab, 0x04, 0xc6, 0x1a, 0x5d, + 0xd3, 0x82, 0x48, 0x0b, 0x7e, 0xfb, 0xad, 0x15, 0x80, 0xf9, 0xfd, 0x40, 0x81, 0x0f, 0x3c, 0x1b, 0x25, 0x80, 0x05, + 0x85, 0x62, 0x09, 0x81, 0x05, 0xbe, 0x31, 0xf0, 0x6f, 0x51, 0x2c, 0x7e, 0x70, 0xc5, 0x9e, 0x1d, 0x7a, 0xd1, 0x14, + 0x50, 0x9a, 0x17, 0x4d, 0x6b, 0x06, 0x04, 0xe4, 0x5d, 0x57, 0x29, 0x2d, 0xba, 0x2a, 0x94, 0xfb, 0xe9, 0xb7, 0x0f, + 0x57, 0x94, 0x09, 0x08, 0xb2, 0x4e, 0x7b, 0x63, 0x74, 0x05, 0x2b, 0x74, 0x0f, 0x2f, 0x07, 0x5f, 0x9d, 0xce, 0x59, + 0xe6, 0x91, 0xe0, 0x12, 0xae, 0x78, 0xc0, 0x0e, 0x68, 0xbe, 0xc8, 0xe2, 0x49, 0x17, 0xbc, 0x31, 0xbb, 0x0b, 0x7c, + 0x7e, 0x4f, 0x33, 0x35, 0x4e, 0xa7, 0x2c, 0xb4, 0x51, 0x1a, 0xb8, 0x26, 0x99, 0xc8, 0xfa, 0x1e, 0x06, 0x18, 0x1c, + 0x44, 0xb1, 0x7e, 0xf6, 0x95, 0xf4, 0x26, 0xda, 0xb4, 0x08, 0x90, 0x8e, 0xef, 0x3a, 0x61, 0xe1, 0xbf, 0x07, 0x5f, + 0x01, 0xe1, 0xfe, 0xea, 0x46, 0x37, 0xfa, 0x99, 0x8d, 0xf7, 0x98, 0xaf, 0x1a, 0xd2, 0xd2, 0xe1, 0x1d, 0x95, 0x5f, + 0x36, 0x3b, 0xca, 0x65, 0x13, 0x7e, 0xef, 0xbe, 0xba, 0x9e, 0x9d, 0x22, 0x41, 0x3b, 0x83, 0xdb, 0xc5, 0xba, 0x74, + 0xe7, 0x74, 0xfb, 0x78, 0x41, 0x1d, 0x85, 0x9e, 0xff, 0x49, 0xdc, 0x50, 0xd5, 0x87, 0x7d, 0xee, 0xa2, 0x92, 0xb3, + 0x6b, 0xdc, 0xcb, 0xb8, 0x95, 0xd7, 0xf8, 0x65, 0xfc, 0xd4, 0xfd, 0x2c, 0xc8, 0xe4, 0x65, 0x18, 0x1f, 0x72, 0xd0, + 0xe6, 0xe0, 0xf8, 0x8a, 0xeb, 0x0f, 0x5c, 0x50, 0xdd, 0x93, 0xbf, 0x75, 0xef, 0x5c, 0x67, 0xd6, 0x76, 0x6d, 0xb8, + 0xe6, 0xcc, 0x3a, 0xf6, 0x71, 0x68, 0x75, 0xec, 0x63, 0xf8, 0xfb, 0x08, 0x57, 0x2f, 0xab, 0x6d, 0x1f, 0x7e, 0x74, + 0xdb, 0xa1, 0x75, 0x62, 0x1f, 0xc3, 0xdf, 0x25, 0xb5, 0xfa, 0x19, 0x2f, 0x3d, 0x70, 0xe1, 0xf9, 0xaa, 0x84, 0x05, + 0x94, 0xdf, 0x52, 0x8b, 0x60, 0x96, 0xc8, 0x5b, 0x83, 0x26, 0x02, 0x50, 0x86, 0x6e, 0x8a, 0x80, 0x80, 0x51, 0xbf, + 0x05, 0x79, 0xb2, 0x31, 0xc2, 0xbb, 0x30, 0xc8, 0x88, 0x8a, 0x9c, 0xef, 0x9b, 0x8f, 0x11, 0x6f, 0xd3, 0x1c, 0x6a, + 0x5b, 0xa4, 0x0e, 0x22, 0xd5, 0xc5, 0xdf, 0x17, 0x18, 0x45, 0x47, 0x04, 0x07, 0x57, 0xb0, 0x52, 0x91, 0xbe, 0x2e, + 0xdf, 0x3d, 0x70, 0xf4, 0x1b, 0x65, 0x32, 0x7d, 0xca, 0x17, 0xed, 0x9b, 0xab, 0x33, 0x64, 0xef, 0x7f, 0xb4, 0x1f, + 0xcc, 0x1a, 0x4a, 0xfd, 0x88, 0x38, 0x9e, 0xe3, 0x20, 0x91, 0xc3, 0x53, 0x50, 0xb4, 0xdb, 0x1c, 0xa3, 0xdc, 0x80, + 0x3c, 0x13, 0x17, 0xc0, 0x25, 0xdf, 0x79, 0xa1, 0x62, 0x7a, 0xa1, 0xb4, 0x7c, 0x22, 0x31, 0xff, 0xf3, 0xe7, 0xc5, + 0xe0, 0xac, 0xca, 0xb8, 0x4f, 0xdd, 0x2e, 0x90, 0xdd, 0x2e, 0xeb, 0x6c, 0xb5, 0x02, 0xda, 0x1d, 0x08, 0xb6, 0x08, + 0x1d, 0x29, 0x34, 0xfd, 0x42, 0xc7, 0xb8, 0xd1, 0x14, 0xa9, 0xa6, 0x61, 0x84, 0x10, 0xba, 0x95, 0xab, 0x8e, 0x6e, + 0xf4, 0x23, 0xa1, 0x30, 0x8b, 0xb6, 0x04, 0xbf, 0xe5, 0x77, 0x31, 0x1d, 0x40, 0xb3, 0x65, 0x1e, 0x3b, 0x5c, 0x1a, + 0xff, 0xdf, 0x93, 0x40, 0xf7, 0x22, 0xd0, 0xf0, 0x55, 0x4e, 0x6b, 0xc9, 0xdd, 0x44, 0xd2, 0x55, 0x22, 0xa8, 0x2c, + 0x3d, 0xd7, 0xa1, 0x08, 0x12, 0x10, 0x61, 0xce, 0x31, 0x69, 0xde, 0x24, 0xa9, 0x45, 0x51, 0x60, 0x06, 0x10, 0xfd, + 0xb9, 0x25, 0x5c, 0x9d, 0x8c, 0xe7, 0xcf, 0x37, 0x12, 0x21, 0x52, 0x27, 0xab, 0xa9, 0x17, 0x75, 0x15, 0xbf, 0xe9, + 0x2a, 0x8a, 0x91, 0xfd, 0x22, 0xd6, 0x10, 0x56, 0x59, 0xb4, 0xf7, 0xf0, 0xe7, 0x88, 0x79, 0x99, 0xcd, 0xf5, 0x20, + 0x2d, 0x85, 0xb8, 0x9b, 0x2e, 0xeb, 0x80, 0x3d, 0x16, 0x0f, 0xb6, 0xc5, 0x23, 0xcb, 0x3d, 0x5b, 0x7f, 0x5c, 0x72, + 0x3f, 0x64, 0xe8, 0xe3, 0x37, 0xa7, 0x08, 0x9e, 0xf2, 0x2e, 0xf3, 0x28, 0xc2, 0x86, 0x4a, 0x72, 0xe3, 0xcc, 0x13, + 0x89, 0x3e, 0x80, 0x2f, 0xef, 0x37, 0x2a, 0x0c, 0x15, 0x5f, 0xe5, 0xb3, 0x77, 0x57, 0xdf, 0x68, 0x7c, 0xff, 0x93, + 0x7e, 0x0b, 0x2f, 0x32, 0x14, 0xef, 0x7e, 0x40, 0xf1, 0xee, 0x35, 0x9e, 0xe7, 0x01, 0xa2, 0xc6, 0xe7, 0x07, 0x04, + 0x41, 0x5d, 0x63, 0x91, 0x4f, 0x5a, 0xbf, 0xf9, 0x32, 0xcc, 0x82, 0x85, 0x97, 0x64, 0x07, 0xd0, 0xd4, 0x02, 0x24, + 0xa7, 0x6f, 0xf2, 0x60, 0x26, 0xc5, 0xa1, 0x10, 0xaa, 0x65, 0x91, 0xd0, 0x1c, 0x4e, 0x82, 0x50, 0x2a, 0x0e, 0xc5, + 0x07, 0x3c, 0xdf, 0x67, 0x8b, 0x6c, 0xa0, 0x7b, 0x0b, 0xc8, 0x7b, 0x80, 0x91, 0x8c, 0x0f, 0x62, 0x3f, 0x63, 0x99, + 0x95, 0x66, 0x09, 0xf3, 0xe6, 0xba, 0x0c, 0xeb, 0x59, 0xef, 0x2f, 0x5d, 0x8e, 0xe6, 0x41, 0x26, 0x23, 0xe3, 0xd1, + 0x04, 0x41, 0x85, 0x07, 0x43, 0x3c, 0x1b, 0xe6, 0x1c, 0x84, 0x97, 0xf1, 0xb4, 0xb2, 0xa3, 0x0a, 0xce, 0xe5, 0x1c, + 0xa3, 0xae, 0xf2, 0x58, 0xf7, 0x63, 0xf4, 0xc8, 0xb9, 0xe5, 0x5e, 0xd7, 0x32, 0x80, 0x9f, 0x7e, 0x76, 0xca, 0xaf, + 0xb7, 0x1a, 0x06, 0x0a, 0xd0, 0xbb, 0x0e, 0xc4, 0x95, 0xdd, 0xe4, 0x8f, 0x7d, 0xc0, 0x2b, 0x03, 0x69, 0xa2, 0x9e, + 0x31, 0xc2, 0x37, 0x8d, 0xe5, 0x0a, 0x18, 0xa1, 0x92, 0x8a, 0x77, 0xe6, 0x9e, 0x49, 0x07, 0x20, 0x1c, 0x15, 0xf2, + 0x4a, 0xbf, 0xfd, 0xf6, 0x7a, 0xf8, 0x9f, 0xdf, 0x21, 0x0c, 0xf9, 0xcc, 0x15, 0x5e, 0xd0, 0xd7, 0x6a, 0x2d, 0xce, + 0x7d, 0x9a, 0x43, 0x54, 0xef, 0xb3, 0xb1, 0x08, 0x0b, 0x22, 0xb6, 0x56, 0x3e, 0xbc, 0x11, 0xa1, 0x9e, 0x20, 0xd5, + 0x80, 0x21, 0x7c, 0xb5, 0x87, 0xb0, 0xbc, 0x43, 0x11, 0x22, 0x40, 0xfb, 0x65, 0xf5, 0xed, 0x31, 0xa4, 0xcd, 0xad, + 0x65, 0x00, 0x50, 0x06, 0x88, 0x7b, 0xe8, 0xec, 0xd4, 0xe3, 0xc2, 0x57, 0x60, 0x3f, 0xd2, 0xde, 0x01, 0x4c, 0x73, + 0x16, 0xcf, 0x99, 0x1d, 0xc4, 0x07, 0xf7, 0x6c, 0x64, 0x79, 0x8b, 0x80, 0xe4, 0xcb, 0x28, 0x77, 0xd3, 0x88, 0xf3, + 0x93, 0x0a, 0x5a, 0xe2, 0xaf, 0xf3, 0x02, 0x94, 0x71, 0x01, 0x28, 0xf8, 0xe9, 0x9d, 0x95, 0xa3, 0xf5, 0xd9, 0x22, + 0x36, 0x7c, 0x19, 0xcb, 0x9f, 0x53, 0xd0, 0x3d, 0x11, 0x5f, 0xaf, 0x78, 0xb0, 0xe2, 0xc9, 0x44, 0x8d, 0xb0, 0x67, + 0x97, 0xbf, 0x2f, 0xa1, 0x52, 0xec, 0xd9, 0x78, 0x41, 0x5f, 0xaa, 0x7f, 0x42, 0xfe, 0x84, 0xf4, 0xb5, 0x3c, 0x18, + 0x23, 0x9c, 0xe7, 0x5a, 0xa4, 0x3e, 0x09, 0x92, 0xa7, 0x54, 0x89, 0x23, 0x8a, 0x6a, 0x0c, 0xe8, 0x0d, 0xac, 0xc9, + 0x93, 0xc1, 0x80, 0xf0, 0x58, 0x15, 0x9d, 0x01, 0x94, 0x1a, 0xe2, 0xe4, 0xc3, 0x64, 0x33, 0x68, 0x68, 0x91, 0x07, + 0x17, 0x36, 0xaa, 0x4e, 0xa7, 0x3e, 0xc6, 0x03, 0x4f, 0xec, 0xaf, 0xd2, 0x0e, 0x84, 0x9d, 0xc5, 0x17, 0x16, 0x10, + 0xb8, 0xe8, 0xa7, 0x82, 0xc7, 0xb5, 0xaf, 0x09, 0x65, 0x5b, 0xa1, 0xf7, 0x10, 0x2b, 0x9a, 0x75, 0xee, 0x64, 0x7f, + 0x89, 0xa5, 0x57, 0xc2, 0xb9, 0xad, 0x76, 0x92, 0x64, 0xac, 0xf1, 0xfa, 0x69, 0x52, 0x83, 0x83, 0xef, 0x3a, 0x4c, + 0x6a, 0xdd, 0xf2, 0x64, 0x10, 0x3b, 0xe6, 0xc5, 0x41, 0x2b, 0xbd, 0xc4, 0x73, 0x9f, 0x9f, 0x1e, 0xc0, 0xfc, 0x20, + 0x30, 0x40, 0x89, 0x33, 0x0a, 0x0c, 0x88, 0x3e, 0xe0, 0xa5, 0x64, 0x1d, 0x70, 0x31, 0x16, 0x4c, 0x1d, 0xde, 0x1c, + 0x65, 0x28, 0xd0, 0x52, 0x95, 0x3a, 0xb3, 0xe2, 0x34, 0x73, 0x79, 0xbb, 0x63, 0xf3, 0xff, 0xba, 0xc4, 0xc0, 0xfc, + 0x79, 0x3f, 0x63, 0xc2, 0xef, 0xf6, 0x32, 0xdb, 0xe0, 0x9a, 0xbb, 0xa9, 0x0a, 0x31, 0xac, 0x5b, 0x2a, 0x14, 0xfb, + 0x78, 0x5b, 0xad, 0x82, 0x35, 0x92, 0xd5, 0x16, 0x5e, 0x4b, 0x7f, 0x8a, 0x3b, 0xbe, 0x56, 0x1b, 0x4b, 0xa1, 0xde, + 0x65, 0x36, 0x80, 0xaa, 0x42, 0xd8, 0xee, 0x2d, 0x16, 0x54, 0xd9, 0xe8, 0x9f, 0x1e, 0xd0, 0xbd, 0xf3, 0x8c, 0x76, + 0xd8, 0xd9, 0x29, 0x58, 0x17, 0xd2, 0xa2, 0x7b, 0x8b, 0x05, 0x5f, 0x52, 0xfa, 0x45, 0x6f, 0x0e, 0x66, 0xd9, 0x3c, + 0x3c, 0xfb, 0x2f, 0x85, 0x07, 0xd6, 0xc5, 0xa2, 0x59, 0x03, 0x00}; + +} // namespace web_server +} // namespace esphome +#endif +#endif diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index 6a7b4121f0..d72307991f 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -27,7 +27,11 @@ #endif #ifdef USE_WEBSERVER_LOCAL -#include "server_index.h" +#if USE_WEBSERVER_VERSION == 2 +#include "server_index_v2.h" +#elif USE_WEBSERVER_VERSION == 3 +#include "server_index_v3.h" +#endif #endif namespace esphome { From 989a64bdcf9ae9a1b0723d77b20ba6c26d74d89d Mon Sep 17 00:00:00 2001 From: esphomebot Date: Tue, 30 Apr 2024 09:45:03 +1200 Subject: [PATCH 1352/2101] Update webserver local assets to 20240429-211523 (#6657) --- .../components/captive_portal/captive_index.h | 196 +-- .../components/web_server/server_index_v2.h | 1237 +++++++++-------- .../components/web_server/server_index_v3.h | 725 +++++----- 3 files changed, 1083 insertions(+), 1075 deletions(-) diff --git a/esphome/components/captive_portal/captive_index.h b/esphome/components/captive_portal/captive_index.h index d262a89b09..8835762fb3 100644 --- a/esphome/components/captive_portal/captive_index.h +++ b/esphome/components/captive_portal/captive_index.h @@ -1,106 +1,108 @@ #pragma once // Generated from https://github.com/esphome/esphome-webserver -#include "esphome/core/hal.h" -namespace esphome { +#include "esphome/core/hal.h" + +namespace esphome { namespace captive_portal { const uint8_t INDEX_GZ[] PROGMEM = { - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xdd, 0x58, 0x69, 0x6f, 0xdc, 0x36, 0x1a, 0xfe, 0xde, - 0x5f, 0xc1, 0x2a, 0x49, 0x47, 0xd3, 0x58, 0xd4, 0x35, 0x9a, 0x53, 0x9a, 0xc2, 0xf1, 0xa6, 0x68, 0x81, 0xa4, 0x0d, - 0x60, 0xb7, 0xfd, 0x10, 0x04, 0x30, 0x47, 0xa2, 0x46, 0x8c, 0x25, 0x4a, 0x2b, 0x72, 0xae, 0x0c, 0x66, 0x7f, 0xfb, - 0xbe, 0x24, 0x35, 0xe3, 0xb1, 0x37, 0x5e, 0x6c, 0x8a, 0x2d, 0x8a, 0xd6, 0x71, 0x68, 0x1e, 0xef, 0xf9, 0x88, 0xef, - 0x21, 0xc5, 0x5f, 0x67, 0x75, 0x2a, 0x77, 0x0d, 0x45, 0x85, 0xac, 0xca, 0x79, 0xac, 0x46, 0x54, 0x12, 0xbe, 0x4c, - 0x28, 0x87, 0x15, 0x25, 0xd9, 0x3c, 0xae, 0xa8, 0x24, 0x28, 0x2d, 0x48, 0x2b, 0xa8, 0x4c, 0x7e, 0xb9, 0xf9, 0xde, - 0x19, 0x23, 0x77, 0x1e, 0x97, 0x8c, 0xdf, 0xa1, 0x96, 0x96, 0x09, 0x4b, 0x6b, 0x8e, 0x8a, 0x96, 0xe6, 0x49, 0x46, - 0x24, 0x99, 0xb2, 0x8a, 0x2c, 0xa9, 0x22, 0xd0, 0x6c, 0x9c, 0x54, 0x34, 0x59, 0x33, 0xba, 0x69, 0xea, 0x56, 0x22, - 0xa0, 0x94, 0x94, 0xcb, 0xc4, 0xda, 0xb0, 0x4c, 0x16, 0x49, 0x46, 0xd7, 0x2c, 0xa5, 0x8e, 0x5e, 0x5c, 0x30, 0xce, - 0x24, 0x23, 0xa5, 0x23, 0x52, 0x52, 0xd2, 0xc4, 0xbf, 0x58, 0x09, 0xda, 0xea, 0x05, 0x59, 0xc0, 0x9a, 0xd7, 0x16, - 0x88, 0x14, 0x69, 0xcb, 0x1a, 0x89, 0x94, 0xbd, 0x49, 0x55, 0x67, 0xab, 0x92, 0xce, 0x5d, 0x97, 0x08, 0xb0, 0x4b, - 0xb8, 0x8c, 0x67, 0x74, 0x8b, 0x87, 0x61, 0x98, 0x06, 0x64, 0x94, 0xe3, 0x8f, 0xe2, 0x2b, 0xf0, 0x6c, 0x55, 0x81, - 0x3a, 0x5c, 0xd6, 0x29, 0x91, 0xac, 0xe6, 0x58, 0x50, 0xd2, 0xa6, 0x45, 0x92, 0x24, 0xd6, 0x77, 0x82, 0xac, 0xa9, - 0xf5, 0xcd, 0x37, 0xf6, 0x89, 0x68, 0x49, 0xe5, 0xeb, 0x92, 0xaa, 0xa9, 0x78, 0xb5, 0xbb, 0x21, 0xcb, 0x9f, 0xc0, - 0x72, 0xdb, 0x22, 0x82, 0x65, 0xd4, 0xea, 0xbf, 0xf7, 0x3e, 0x60, 0x21, 0x77, 0x25, 0xc5, 0x19, 0x13, 0x4d, 0x49, - 0x76, 0x89, 0xb5, 0x00, 0xa9, 0x77, 0x56, 0x7f, 0x96, 0xaf, 0x78, 0xaa, 0x84, 0x23, 0x61, 0xd3, 0xfe, 0xbe, 0xa4, - 0x60, 0x5e, 0xf2, 0x96, 0xc8, 0x02, 0x57, 0x64, 0x6b, 0x9b, 0x09, 0xe3, 0x76, 0xf0, 0xad, 0x4d, 0x5f, 0xfa, 0x9e, - 0xd7, 0xbf, 0xd0, 0x83, 0xd7, 0x77, 0xe1, 0xef, 0xac, 0xa5, 0x72, 0xd5, 0x72, 0x44, 0xec, 0xdb, 0xb8, 0x01, 0x4a, - 0x94, 0x25, 0x56, 0xe5, 0x07, 0xd8, 0xf3, 0xc6, 0xc8, 0x9f, 0xe0, 0x20, 0x72, 0x7c, 0x1f, 0x87, 0x8e, 0x1f, 0xa5, - 0x23, 0x27, 0x42, 0xfe, 0x00, 0x86, 0x20, 0xc0, 0x11, 0xf2, 0x3e, 0x59, 0x28, 0x67, 0x65, 0x99, 0x58, 0xbc, 0xe6, - 0xd4, 0x42, 0x42, 0xb6, 0xf5, 0x1d, 0x4d, 0xac, 0x74, 0xd5, 0xb6, 0x60, 0xff, 0x55, 0x5d, 0xd6, 0x2d, 0xc0, 0xf5, - 0x15, 0x7a, 0xf0, 0xf3, 0xc5, 0x2a, 0x64, 0x4b, 0xb8, 0xc8, 0xeb, 0xb6, 0x4a, 0x2c, 0xfd, 0x50, 0xec, 0xe7, 0x7b, - 0x79, 0x40, 0x6a, 0xe8, 0x9f, 0x1d, 0x3a, 0x75, 0xcb, 0x96, 0x8c, 0x27, 0x96, 0x1f, 0x20, 0x7f, 0x0c, 0x6a, 0x6f, - 0xfb, 0x87, 0x13, 0x26, 0x44, 0x61, 0xd2, 0x79, 0x59, 0xdb, 0xef, 0x6f, 0x63, 0xb1, 0x5e, 0xa2, 0x6d, 0x55, 0x72, - 0x91, 0x58, 0x85, 0x94, 0xcd, 0xd4, 0x75, 0x37, 0x9b, 0x0d, 0xde, 0x84, 0xb8, 0x6e, 0x97, 0x6e, 0xe0, 0x79, 0x9e, - 0x0b, 0x14, 0x16, 0x32, 0xf7, 0xc3, 0x0a, 0x06, 0x16, 0x2a, 0x28, 0x5b, 0x16, 0x52, 0xcf, 0xe7, 0xcf, 0xf7, 0xf4, - 0x10, 0x2b, 0x8a, 0xf9, 0xed, 0x87, 0x33, 0x2d, 0xec, 0x4c, 0x0b, 0xfd, 0xee, 0x0c, 0xcd, 0xde, 0x5b, 0x65, 0xd4, - 0x88, 0x04, 0x28, 0x40, 0x9e, 0xfe, 0x17, 0x38, 0x6a, 0xde, 0xad, 0x9c, 0x47, 0x2b, 0x74, 0xb6, 0x82, 0xbf, 0x80, - 0x5f, 0x50, 0x0d, 0x9d, 0xc9, 0x89, 0xdd, 0x57, 0xc7, 0x6b, 0xdf, 0xbb, 0xdf, 0x50, 0x3c, 0x3f, 0x0c, 0xcf, 0xd7, - 0x4e, 0xf0, 0xab, 0x22, 0x50, 0xd8, 0x9f, 0x98, 0x9c, 0xa0, 0xf0, 0x7f, 0x1d, 0x92, 0x08, 0x45, 0xdd, 0x4e, 0xe4, - 0xa8, 0xf9, 0x69, 0xa5, 0x34, 0xa1, 0x68, 0x0d, 0x54, 0x95, 0x33, 0x74, 0x22, 0x12, 0xa2, 0xb0, 0x33, 0x09, 0x66, - 0xb0, 0x3d, 0x04, 0xe6, 0xb3, 0x3d, 0x27, 0xfc, 0xd4, 0x53, 0x30, 0x4f, 0x2d, 0xeb, 0x1e, 0x83, 0xfa, 0x1c, 0x03, - 0xfc, 0xb1, 0x86, 0x3b, 0x67, 0x59, 0x80, 0x11, 0x95, 0x69, 0x61, 0x5b, 0x2e, 0x44, 0x5e, 0xce, 0x96, 0x10, 0x15, - 0x35, 0xb7, 0xfa, 0x58, 0x16, 0x94, 0xdb, 0x47, 0x56, 0xc5, 0x48, 0xf5, 0x89, 0xfd, 0xf8, 0x44, 0xf6, 0xf7, 0xa7, - 0xf8, 0x90, 0x4c, 0x42, 0x1c, 0x4a, 0xac, 0x22, 0xfa, 0xe2, 0xb4, 0xbb, 0xa8, 0xb3, 0xdd, 0x13, 0xa1, 0x53, 0xf8, - 0x26, 0x6e, 0x18, 0xe7, 0xb4, 0xbd, 0xa1, 0x5b, 0x78, 0x86, 0x6f, 0x2f, 0xaf, 0xd0, 0x65, 0x96, 0xb5, 0x54, 0x88, - 0x29, 0xb2, 0x5e, 0x4a, 0x88, 0x91, 0xf4, 0x7f, 0x97, 0xe5, 0x3f, 0x90, 0xf5, 0x1b, 0xfb, 0x9e, 0xa1, 0x9f, 0xa8, - 0xdc, 0xd4, 0xed, 0x5d, 0x27, 0x4d, 0x99, 0x36, 0x53, 0x11, 0xd8, 0x82, 0x9d, 0xa4, 0x11, 0x58, 0x94, 0x90, 0x5f, - 0x6c, 0xbf, 0x0f, 0x7a, 0x9a, 0x7b, 0xaf, 0xf8, 0x11, 0xa8, 0xdb, 0x38, 0x63, 0x6b, 0x94, 0x96, 0x90, 0x41, 0x20, - 0x94, 0x8c, 0x28, 0x0b, 0x75, 0x61, 0x53, 0xf3, 0x14, 0xb8, 0xef, 0x12, 0xeb, 0x33, 0x19, 0xe2, 0xd5, 0xee, 0xc7, - 0xcc, 0xee, 0x09, 0xc8, 0x0d, 0xbd, 0x3e, 0x5e, 0x93, 0x72, 0x45, 0x51, 0x82, 0x64, 0xc1, 0xc4, 0xbd, 0x81, 0xb3, - 0x27, 0xd9, 0x1a, 0x71, 0x07, 0x5c, 0x39, 0x1c, 0x0b, 0xbb, 0x6f, 0x1d, 0xa3, 0x34, 0x26, 0x26, 0x87, 0x5a, 0xcf, - 0xac, 0x47, 0x16, 0x39, 0x25, 0xcd, 0xa5, 0x75, 0x1f, 0xcd, 0xcf, 0xf7, 0xc2, 0xe6, 0xb8, 0x05, 0xed, 0xfd, 0xc3, - 0x69, 0x33, 0x16, 0x0d, 0xe1, 0x8f, 0x19, 0x95, 0x81, 0x2a, 0x68, 0x20, 0xf1, 0xc1, 0x4c, 0x45, 0x0e, 0x10, 0x9d, - 0x14, 0xba, 0xe4, 0x38, 0x7d, 0xbe, 0x67, 0x20, 0x51, 0xe5, 0xb3, 0x93, 0xc4, 0xd8, 0x05, 0x68, 0xe6, 0xb7, 0x87, - 0xfe, 0xbd, 0x1f, 0xff, 0x5c, 0xd1, 0x76, 0x77, 0x4d, 0x4b, 0x9a, 0xca, 0xba, 0xb5, 0xad, 0x67, 0xa0, 0x05, 0xae, - 0x92, 0x76, 0xf8, 0x87, 0x9b, 0xb7, 0x6f, 0x92, 0xda, 0x6e, 0xfb, 0x17, 0x4f, 0x51, 0xab, 0x6a, 0xf1, 0x1e, 0xaa, - 0xc5, 0xbf, 0x92, 0x9e, 0xaa, 0x17, 0xbd, 0x0f, 0xc0, 0xaa, 0xfd, 0xbd, 0xbd, 0x2f, 0x1a, 0x2a, 0xb0, 0x5f, 0x42, - 0x72, 0xb8, 0x50, 0x1e, 0x3a, 0xc3, 0xa8, 0x7f, 0x00, 0xfd, 0x60, 0x01, 0xd8, 0xad, 0xf3, 0x3e, 0xe4, 0x7f, 0x95, - 0x82, 0xe7, 0xdf, 0xee, 0x17, 0xf5, 0xd6, 0x11, 0xec, 0x13, 0xe3, 0xcb, 0x29, 0xe3, 0x05, 0x6d, 0x99, 0x3c, 0x80, - 0xb9, 0x50, 0x42, 0x9a, 0x95, 0xdc, 0x37, 0x24, 0xcb, 0xd4, 0x49, 0xd4, 0x6c, 0x67, 0x39, 0x14, 0x1c, 0x45, 0x49, - 0xa7, 0x3e, 0xad, 0x0e, 0xe6, 0x5c, 0xe7, 0x96, 0xe9, 0x24, 0x7a, 0x71, 0x50, 0x17, 0x6e, 0x2f, 0xe1, 0x61, 0x39, - 0xa4, 0x64, 0x4b, 0x3e, 0x4d, 0xc1, 0x70, 0xda, 0x1a, 0xa6, 0x9c, 0x54, 0xac, 0xdc, 0x4d, 0x05, 0x64, 0x39, 0x07, - 0x2a, 0x11, 0xcb, 0x0f, 0x8b, 0x95, 0x94, 0x35, 0x07, 0xdd, 0x6d, 0x46, 0xdb, 0xa9, 0x37, 0x33, 0x13, 0xa7, 0x25, - 0x19, 0x5b, 0x89, 0x29, 0x0e, 0x5b, 0x5a, 0xcd, 0x16, 0x24, 0xbd, 0x5b, 0xb6, 0xf5, 0x8a, 0x67, 0x4e, 0xaa, 0xb2, - 0xf0, 0xf4, 0x99, 0x9f, 0x93, 0x90, 0xa6, 0xb3, 0x6e, 0x95, 0xe7, 0xf9, 0x0c, 0xa0, 0xa0, 0x8e, 0xc9, 0x6a, 0xd3, - 0x00, 0x0f, 0x14, 0xdb, 0x99, 0x99, 0x38, 0x50, 0x1b, 0xc6, 0x46, 0x28, 0x11, 0x2f, 0x66, 0x47, 0x77, 0xbc, 0x19, - 0xa4, 0x77, 0x01, 0x42, 0x1a, 0x88, 0x6d, 0x30, 0xf3, 0x50, 0x11, 0xc6, 0xcf, 0xad, 0x57, 0xd7, 0x64, 0xd6, 0x95, - 0x27, 0x80, 0x45, 0xab, 0xd1, 0x45, 0x6a, 0x06, 0x05, 0xc8, 0x14, 0xd9, 0x69, 0x30, 0xf4, 0x9a, 0xed, 0x01, 0x77, - 0x17, 0x64, 0x7f, 0xa4, 0xce, 0x4b, 0xba, 0x9d, 0x7d, 0x5c, 0x09, 0xc9, 0xf2, 0x9d, 0xd3, 0x15, 0xe9, 0x29, 0x5c, - 0x16, 0x28, 0xce, 0x0b, 0x20, 0xa5, 0x94, 0xcf, 0xb4, 0x0e, 0x87, 0x49, 0x5a, 0x89, 0x0e, 0xa7, 0x93, 0x18, 0x7d, - 0x41, 0x1f, 0xca, 0xfa, 0x6f, 0xd4, 0xea, 0x2e, 0xee, 0x2b, 0xd2, 0x42, 0xd1, 0x70, 0x16, 0x35, 0x60, 0x5a, 0x4d, - 0x9d, 0x11, 0x3c, 0xab, 0x6e, 0x4b, 0x09, 0x03, 0xcf, 0xc1, 0x4c, 0x5d, 0x7b, 0x8f, 0x78, 0xfb, 0xcd, 0x16, 0x89, - 0xba, 0x64, 0x59, 0x47, 0xa7, 0x49, 0x90, 0x77, 0x82, 0xc7, 0x87, 0xc7, 0x8d, 0xd4, 0xde, 0x11, 0xea, 0x41, 0x3e, - 0x26, 0xbe, 0xf7, 0x99, 0x27, 0x92, 0xe5, 0x79, 0xb0, 0xc8, 0x4f, 0x48, 0xa9, 0x12, 0x7a, 0x60, 0xdd, 0xad, 0x08, - 0x06, 0x20, 0xe0, 0xf8, 0x6c, 0x60, 0x7e, 0x60, 0x3a, 0x2c, 0xf6, 0x67, 0x52, 0xf4, 0x55, 0x9d, 0xae, 0xda, 0xd2, - 0xb6, 0x3e, 0x73, 0x75, 0x5f, 0x84, 0x57, 0xf7, 0x25, 0xae, 0xf7, 0x74, 0x89, 0xeb, 0x21, 0xd5, 0x14, 0xbd, 0xaa, - 0xb7, 0x49, 0x4f, 0x17, 0x9b, 0x01, 0xfc, 0xf6, 0x5e, 0x84, 0xaf, 0x81, 0xff, 0xff, 0x52, 0xbb, 0x7e, 0x77, 0xe1, - 0xfa, 0x82, 0xaa, 0xf5, 0x85, 0x15, 0xcb, 0x78, 0xa7, 0x9c, 0x87, 0x19, 0x94, 0x26, 0x86, 0x05, 0x5b, 0xfa, 0x7f, - 0x04, 0xb4, 0xff, 0x89, 0x63, 0x78, 0xe9, 0x8f, 0xf1, 0x04, 0xe9, 0xc1, 0x40, 0x84, 0xc3, 0x31, 0x1a, 0x5d, 0x0d, - 0xf0, 0xc0, 0x47, 0xaa, 0x1d, 0x1a, 0xa2, 0x11, 0x1e, 0x03, 0xc1, 0x10, 0x87, 0x23, 0xd8, 0x40, 0x81, 0x8f, 0xa3, - 0x37, 0x41, 0x88, 0x87, 0x11, 0x50, 0x05, 0x1e, 0x0e, 0x03, 0x64, 0x68, 0x87, 0x38, 0x00, 0x71, 0x8a, 0x24, 0xac, - 0x00, 0xe8, 0x34, 0xc4, 0xde, 0x08, 0xc4, 0x0d, 0xb1, 0x37, 0xc1, 0xe3, 0x21, 0x1a, 0xe3, 0x11, 0x40, 0x87, 0x07, - 0x51, 0xe9, 0x44, 0xd8, 0x87, 0xed, 0x70, 0x48, 0xc6, 0x78, 0x10, 0x22, 0x3d, 0x18, 0x38, 0x46, 0x20, 0xc2, 0xc1, - 0x9e, 0xff, 0x26, 0xc4, 0xc1, 0x08, 0xf4, 0x0e, 0x06, 0x97, 0x20, 0x76, 0x32, 0x40, 0x66, 0x34, 0xf0, 0x82, 0x82, - 0xe8, 0x29, 0xd0, 0x82, 0xbf, 0x2f, 0x68, 0x00, 0x89, 0x8f, 0x42, 0x3c, 0x81, 0xd8, 0xf5, 0x15, 0xbf, 0x19, 0x0d, - 0x6e, 0xbe, 0x8f, 0xbc, 0xdf, 0x8d, 0x59, 0xf8, 0xf7, 0xc5, 0xcc, 0x57, 0x08, 0xc0, 0x14, 0x74, 0x83, 0x1c, 0xa4, - 0x07, 0xa3, 0x1b, 0x98, 0xc7, 0x57, 0x13, 0x34, 0x06, 0xae, 0xe1, 0x18, 0x4d, 0x50, 0xa4, 0xd0, 0x05, 0xf6, 0x81, - 0x61, 0x72, 0x80, 0xe9, 0x0b, 0x61, 0x1c, 0xfc, 0x85, 0x61, 0x7c, 0xca, 0xa7, 0xbf, 0xb0, 0x4b, 0x7f, 0x46, 0x0a, - 0x82, 0x76, 0x4c, 0xb7, 0x61, 0xb1, 0x6b, 0x3e, 0x0f, 0xa8, 0x2e, 0x0a, 0xde, 0xf6, 0xa1, 0x1b, 0x99, 0xc7, 0x85, - 0x8f, 0x58, 0x96, 0x40, 0x57, 0x3f, 0x3f, 0x6b, 0xf5, 0x81, 0xd0, 0x3f, 0x1e, 0xc1, 0xec, 0x41, 0xe3, 0x6e, 0xce, - 0x74, 0xa5, 0x9f, 0xdf, 0x14, 0x14, 0xbd, 0xbe, 0x7e, 0x07, 0x2f, 0x7f, 0x65, 0x89, 0x78, 0xbd, 0x81, 0x77, 0xcc, - 0x1d, 0x92, 0xb5, 0xfa, 0x6a, 0xc0, 0xa1, 0x8d, 0x54, 0x53, 0x78, 0x3d, 0x41, 0x5d, 0x1f, 0x81, 0x31, 0x8e, 0x17, - 0xed, 0xfc, 0x5d, 0x49, 0x89, 0xa0, 0x68, 0xc9, 0xd6, 0x14, 0x31, 0x09, 0x2d, 0x42, 0x45, 0x91, 0x64, 0x6a, 0x38, - 0x31, 0x6a, 0x3a, 0x68, 0x77, 0xb5, 0x12, 0xd3, 0x28, 0x83, 0x25, 0x20, 0x66, 0xde, 0x75, 0xc4, 0x71, 0x11, 0x1a, - 0xab, 0xae, 0xa9, 0x94, 0xd0, 0x4c, 0x28, 0xab, 0xc2, 0x79, 0xac, 0xde, 0x6e, 0x11, 0xd1, 0xef, 0x0c, 0x89, 0xbb, - 0x61, 0x39, 0x53, 0xdf, 0x0c, 0xe6, 0xb1, 0xee, 0x22, 0x95, 0x04, 0xd5, 0xc8, 0x98, 0x0f, 0x1c, 0x7a, 0x56, 0x52, - 0xbe, 0x84, 0x97, 0x56, 0x78, 0x4c, 0xd0, 0x57, 0xa4, 0xb4, 0xa8, 0x4b, 0xe8, 0x5b, 0x92, 0xeb, 0xeb, 0x1f, 0xff, - 0xa1, 0xbe, 0x86, 0x28, 0x13, 0x4e, 0x9c, 0xf0, 0x0a, 0x60, 0x18, 0xd5, 0xa4, 0xe3, 0x1b, 0x0e, 0xcc, 0x77, 0x8d, - 0x06, 0x5a, 0x78, 0xf0, 0x2f, 0x7b, 0x20, 0xe5, 0xdd, 0x71, 0xb3, 0x93, 0xa4, 0xff, 0xeb, 0x7e, 0xd4, 0x30, 0x89, - 0xd5, 0xa2, 0x62, 0x72, 0x7e, 0x0d, 0x06, 0xc6, 0xae, 0x39, 0x00, 0xe7, 0x94, 0x03, 0x86, 0xb6, 0xe8, 0x78, 0x00, - 0xec, 0x9f, 0x6f, 0x2e, 0xd1, 0x2f, 0x0d, 0x5c, 0x6e, 0x6a, 0xb0, 0xd7, 0x5e, 0x56, 0x54, 0x16, 0x75, 0x96, 0xbc, - 0xfb, 0xf9, 0xfa, 0xe6, 0xe4, 0xf1, 0x4a, 0x13, 0x21, 0xca, 0x53, 0xf3, 0xbd, 0x65, 0x55, 0x4a, 0xd6, 0x90, 0x56, - 0x6a, 0xb1, 0x8e, 0x8a, 0x8e, 0xa3, 0x47, 0xfa, 0x3c, 0x67, 0x25, 0x35, 0x4e, 0x75, 0x8c, 0xee, 0x1c, 0x7d, 0xce, - 0xc6, 0xa3, 0xee, 0x47, 0x56, 0xba, 0xe6, 0x02, 0xb9, 0xe6, 0x36, 0xb9, 0xfa, 0x6b, 0xd4, 0xbf, 0x01, 0x14, 0xee, + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xdd, 0x58, 0x6d, 0x6f, 0xdb, 0x38, 0x12, 0xfe, 0xde, + 0x5f, 0x31, 0xa7, 0x36, 0x6b, 0x6b, 0x1b, 0x51, 0x22, 0xe5, 0xb7, 0xd8, 0x92, 0x16, 0x69, 0xae, 0x8b, 0x5d, 0xa0, + 0xdd, 0x2d, 0x90, 0x6c, 0xef, 0x43, 0x51, 0x20, 0xb4, 0x34, 0xb2, 0xd8, 0x48, 0xa4, 0x4e, 0xa4, 0x5f, 0x52, 0xc3, + 0xf7, 0xdb, 0x0f, 0x94, 0x6c, 0xc7, 0xe9, 0x35, 0x87, 0xeb, 0xe2, 0x0e, 0x87, 0xdd, 0x18, 0x21, 0x86, 0xe4, 0xcc, + 0x70, 0xe6, 0xf1, 0x0c, 0x67, 0xcc, 0xe8, 0x2f, 0x99, 0x4a, 0xcd, 0x7d, 0x8d, 0x50, 0x98, 0xaa, 0x4c, 0x22, 0x3b, + 0x42, 0xc9, 0xe5, 0x22, 0x46, 0x99, 0x44, 0x05, 0xf2, 0x2c, 0x89, 0x2a, 0x34, 0x1c, 0xd2, 0x82, 0x37, 0x1a, 0x4d, + 0xfc, 0xdb, 0xcd, 0x8f, 0xde, 0x04, 0xfc, 0x24, 0x2a, 0x85, 0xbc, 0x83, 0x06, 0xcb, 0x58, 0xa4, 0x4a, 0x42, 0xd1, + 0x60, 0x1e, 0x67, 0xdc, 0xf0, 0xa9, 0xa8, 0xf8, 0x02, 0x2d, 0x43, 0x2b, 0x26, 0x79, 0x85, 0xf1, 0x4a, 0xe0, 0xba, + 0x56, 0x8d, 0x81, 0x54, 0x49, 0x83, 0xd2, 0xc4, 0xce, 0x5a, 0x64, 0xa6, 0x88, 0x33, 0x5c, 0x89, 0x14, 0xbd, 0x76, + 0x72, 0x2e, 0xa4, 0x30, 0x82, 0x97, 0x9e, 0x4e, 0x79, 0x89, 0x31, 0x3d, 0x5f, 0x6a, 0x6c, 0xda, 0x09, 0x9f, 0x97, + 0x18, 0x4b, 0xe5, 0xf8, 0x49, 0xa4, 0xd3, 0x46, 0xd4, 0x06, 0xac, 0xbd, 0x71, 0xa5, 0xb2, 0x65, 0x89, 0x89, 0xef, + 0x73, 0xad, 0xd1, 0x68, 0x5f, 0xc8, 0x0c, 0x37, 0x64, 0x14, 0x86, 0x29, 0xe3, 0xe3, 0x9c, 0x7c, 0xd2, 0xcf, 0x32, + 0x95, 0x2e, 0x2b, 0x94, 0x86, 0x94, 0x2a, 0xe5, 0x46, 0x28, 0x49, 0x34, 0xf2, 0x26, 0x2d, 0xe2, 0x38, 0x76, 0x7e, + 0xd0, 0x7c, 0x85, 0xce, 0x77, 0xdf, 0xf5, 0x8f, 0x4c, 0x0b, 0x34, 0xaf, 0x4b, 0xb4, 0xa4, 0x7e, 0x75, 0x7f, 0xc3, + 0x17, 0xbf, 0xf0, 0x0a, 0xfb, 0x0e, 0xd7, 0x22, 0x43, 0xc7, 0xfd, 0x10, 0x7c, 0x24, 0xda, 0xdc, 0x97, 0x48, 0x32, + 0xa1, 0xeb, 0x92, 0xdf, 0xc7, 0xce, 0xbc, 0x54, 0xe9, 0x9d, 0xe3, 0xce, 0xf2, 0xa5, 0x4c, 0xad, 0x72, 0xd0, 0x7d, + 0x74, 0xb7, 0x25, 0x1a, 0x30, 0xf1, 0x5b, 0x6e, 0x0a, 0x52, 0xf1, 0x4d, 0xbf, 0x23, 0x84, 0xec, 0xb3, 0xef, 0xfb, + 0xf8, 0x92, 0x06, 0x81, 0x7b, 0xde, 0x0e, 0x81, 0xeb, 0xd3, 0x20, 0x98, 0x35, 0x68, 0x96, 0x8d, 0x04, 0xde, 0xbf, + 0x8d, 0x6a, 0x6e, 0x0a, 0xc8, 0x62, 0xa7, 0xa2, 0x8c, 0x04, 0xc1, 0x04, 0xe8, 0x05, 0x61, 0x43, 0x8f, 0x52, 0x12, + 0x7a, 0x74, 0x98, 0x8e, 0xbd, 0x21, 0xd0, 0x81, 0x37, 0x04, 0xc6, 0xc8, 0x10, 0x82, 0xcf, 0x0e, 0xe4, 0xa2, 0x2c, + 0x63, 0x47, 0x2a, 0x89, 0x0e, 0x68, 0xd3, 0xa8, 0x3b, 0x8c, 0x9d, 0x74, 0xd9, 0x34, 0x28, 0xcd, 0x95, 0x2a, 0x55, + 0xe3, 0xf8, 0xc9, 0x33, 0x78, 0xf4, 0xf7, 0xcd, 0x47, 0x98, 0x86, 0x4b, 0x9d, 0xab, 0xa6, 0x8a, 0x9d, 0xf6, 0x4b, + 0xe9, 0xbf, 0xd8, 0x9a, 0x1d, 0xd8, 0xc1, 0x3d, 0xd9, 0xf4, 0x54, 0x23, 0x16, 0x42, 0xc6, 0x0e, 0x65, 0x40, 0x27, + 0x8e, 0x9f, 0xdc, 0xba, 0xbb, 0x23, 0x26, 0xdc, 0x62, 0xb2, 0xf7, 0x52, 0xf5, 0x3f, 0xdc, 0x46, 0x7a, 0xb5, 0x80, + 0x4d, 0x55, 0x4a, 0x1d, 0x3b, 0x85, 0x31, 0xf5, 0xd4, 0xf7, 0xd7, 0xeb, 0x35, 0x59, 0x87, 0x44, 0x35, 0x0b, 0x9f, + 0x05, 0x41, 0xe0, 0xeb, 0xd5, 0xc2, 0x81, 0x2e, 0x3e, 0x1c, 0x36, 0x70, 0xa0, 0x40, 0xb1, 0x28, 0x4c, 0x4b, 0x27, + 0x2f, 0xb6, 0xb8, 0x8b, 0x2c, 0x47, 0x72, 0xfb, 0xf1, 0xe4, 0x14, 0x71, 0x72, 0x0a, 0xfe, 0x70, 0x82, 0x66, 0xef, + 0xad, 0x35, 0x6a, 0xcc, 0x19, 0x30, 0x08, 0xda, 0x0f, 0xf3, 0x2c, 0xbd, 0x9f, 0x79, 0x5f, 0xcc, 0xe0, 0x64, 0x06, + 0x0c, 0x9e, 0x01, 0xb0, 0x6a, 0xe4, 0x5d, 0x1c, 0xc5, 0xa9, 0xdd, 0x5e, 0xd1, 0xe0, 0x61, 0xc1, 0xca, 0xfc, 0x34, + 0x3a, 0x9d, 0x7b, 0xec, 0xbd, 0x65, 0xb0, 0xd8, 0x1f, 0x85, 0x3c, 0x56, 0xd0, 0xf7, 0x23, 0x3e, 0x84, 0xe1, 0x7e, + 0x65, 0xe8, 0x59, 0xfa, 0x38, 0xb3, 0x27, 0xc1, 0x70, 0xc5, 0x0a, 0x5a, 0x79, 0x23, 0x6f, 0xc8, 0x43, 0x08, 0xf7, + 0x26, 0x85, 0x10, 0xae, 0x58, 0x31, 0x7a, 0x3f, 0x3a, 0x5d, 0xf3, 0xc2, 0xcf, 0x3d, 0x0b, 0xf3, 0xd4, 0x71, 0x1e, + 0x30, 0x50, 0xa7, 0x18, 0x90, 0x4f, 0x4a, 0xc8, 0xbe, 0xe3, 0xb8, 0xbb, 0x1c, 0x4d, 0x5a, 0xf4, 0x1d, 0x3f, 0x55, + 0x32, 0x17, 0x0b, 0xf2, 0x49, 0x2b, 0xe9, 0xb8, 0xc4, 0x14, 0x28, 0xfb, 0x07, 0x51, 0x2b, 0x88, 0xed, 0x4e, 0xff, + 0xcb, 0x1d, 0xe3, 0x6e, 0x8f, 0xf9, 0x61, 0x84, 0x29, 0x31, 0x36, 0xc4, 0x66, 0xf4, 0xf9, 0x71, 0x75, 0xae, 0xb2, + 0xfb, 0x27, 0x52, 0xa7, 0xa0, 0x5d, 0xde, 0x08, 0x29, 0xb1, 0xb9, 0xc1, 0x8d, 0x89, 0x9d, 0xb7, 0x97, 0x57, 0x70, + 0x99, 0x65, 0x0d, 0x6a, 0x3d, 0x05, 0xe7, 0xa5, 0x21, 0x15, 0x4f, 0xff, 0x73, 0x5d, 0xf4, 0x91, 0xae, 0xbf, 0x89, + 0x1f, 0x05, 0xfc, 0x82, 0x66, 0xad, 0x9a, 0xbb, 0xbd, 0x36, 0x6b, 0xda, 0xcc, 0x66, 0x60, 0x13, 0x1b, 0xc2, 0x6b, + 0x4d, 0x74, 0x29, 0x52, 0xec, 0x53, 0x97, 0x54, 0xbc, 0x7e, 0xf0, 0x4a, 0x1e, 0x80, 0xba, 0x8d, 0x32, 0xb1, 0x82, + 0xb4, 0xe4, 0x5a, 0xc7, 0x8e, 0xec, 0x54, 0x39, 0xb0, 0x4f, 0x1b, 0x25, 0xd3, 0x52, 0xa4, 0x77, 0xb1, 0xf3, 0x95, + 0x1b, 0xe2, 0xd5, 0xfd, 0xcf, 0x59, 0xbf, 0xa7, 0xb5, 0xc8, 0x7a, 0x2e, 0x59, 0xf1, 0x72, 0x89, 0x10, 0x83, 0x29, + 0x84, 0x7e, 0x30, 0x70, 0xf6, 0xa4, 0x58, 0xad, 0xef, 0x7a, 0x2e, 0xc9, 0x55, 0xba, 0xd4, 0x7d, 0xd7, 0x39, 0x64, + 0x69, 0xc4, 0xbb, 0x3b, 0xd4, 0x79, 0xee, 0x7c, 0x61, 0x91, 0x57, 0x62, 0x6e, 0x9c, 0x87, 0x6c, 0x7e, 0xb1, 0xd5, + 0x7d, 0x49, 0x1a, 0xad, 0x85, 0xbb, 0x3b, 0x2e, 0x46, 0xba, 0xe6, 0xf2, 0x4b, 0x41, 0x6b, 0xa0, 0x4d, 0x1a, 0x49, + 0x2c, 0x65, 0x33, 0xa7, 0xe6, 0xf2, 0x78, 0xa0, 0xcf, 0x0f, 0xe4, 0x8b, 0xad, 0xe8, 0x4b, 0x7b, 0x4b, 0xde, 0x1d, + 0x35, 0x46, 0x7e, 0x26, 0x56, 0xc9, 0xed, 0xce, 0x7d, 0xf0, 0xe3, 0xef, 0x4b, 0x6c, 0xee, 0xaf, 0xb1, 0xc4, 0xd4, + 0xa8, 0xa6, 0xef, 0x3c, 0x97, 0x68, 0x1c, 0xb7, 0x73, 0xf8, 0xa7, 0x9b, 0xb7, 0x6f, 0x62, 0xd5, 0x6f, 0xdc, 0xf3, + 0xa7, 0xb8, 0x6d, 0xb5, 0xf8, 0xd0, 0x60, 0xf9, 0x8f, 0xb8, 0x67, 0xeb, 0x45, 0xef, 0xa3, 0xe3, 0x92, 0xd6, 0xdf, + 0xdb, 0x87, 0xa2, 0x61, 0x13, 0xfb, 0xe5, 0xa6, 0x2a, 0xcf, 0xad, 0x87, 0xde, 0x68, 0xe8, 0xee, 0x6e, 0x77, 0xee, + 0xce, 0x9d, 0x45, 0x7e, 0x77, 0xef, 0x27, 0x51, 0x7b, 0x05, 0x27, 0xdf, 0x6f, 0xe7, 0x6a, 0xe3, 0x69, 0xf1, 0x59, + 0xc8, 0xc5, 0x54, 0xc8, 0x02, 0x1b, 0x61, 0x76, 0x99, 0x58, 0x9d, 0x0b, 0x59, 0x2f, 0xcd, 0xb6, 0xe6, 0x59, 0x66, + 0x77, 0x86, 0xf5, 0x66, 0x96, 0x2b, 0x69, 0x2c, 0x27, 0x4e, 0x29, 0x56, 0xbb, 0x6e, 0xbf, 0xbd, 0x5b, 0xa6, 0x17, + 0xc3, 0xb3, 0x9d, 0x0d, 0xb8, 0xad, 0xc1, 0x8d, 0xf1, 0x78, 0x29, 0x16, 0x72, 0x9a, 0xa2, 0x34, 0xd8, 0x74, 0x42, + 0x39, 0xaf, 0x44, 0x79, 0x3f, 0xd5, 0x5c, 0x6a, 0x4f, 0x63, 0x23, 0xf2, 0xdd, 0x7c, 0x69, 0x8c, 0x92, 0xdb, 0xb9, + 0x6a, 0x32, 0x6c, 0xa6, 0xc1, 0xac, 0x23, 0xbc, 0x86, 0x67, 0x62, 0xa9, 0xa7, 0x24, 0x6c, 0xb0, 0x9a, 0xcd, 0x79, + 0x7a, 0xb7, 0x68, 0xd4, 0x52, 0x66, 0x5e, 0x6a, 0x6f, 0xe1, 0xe9, 0x73, 0x9a, 0xf3, 0x10, 0xd3, 0xd9, 0x7e, 0x96, + 0xe7, 0xf9, 0xac, 0x14, 0x12, 0xbd, 0xee, 0x56, 0x9b, 0x32, 0x32, 0xb0, 0x62, 0x27, 0x66, 0x12, 0x66, 0x17, 0x3a, + 0x1b, 0x69, 0x10, 0x9c, 0xcd, 0x0e, 0xee, 0x04, 0xb3, 0x74, 0xd9, 0x68, 0xd5, 0x4c, 0x6b, 0x25, 0xac, 0x99, 0xbb, + 0x8a, 0x0b, 0x79, 0x6a, 0xbd, 0x0d, 0x93, 0xd9, 0xbe, 0x3c, 0x4d, 0x85, 0x6c, 0x8f, 0x69, 0x8b, 0xd4, 0xac, 0x12, + 0xb2, 0x2b, 0xb2, 0x53, 0x36, 0x0a, 0xea, 0xcd, 0x8e, 0xec, 0x03, 0x64, 0x7b, 0xe0, 0xce, 0x4b, 0xdc, 0xcc, 0x3e, + 0x2d, 0xb5, 0x11, 0xf9, 0xbd, 0xb7, 0x2f, 0xd2, 0x53, 0x5d, 0xf3, 0x14, 0xbd, 0x39, 0x9a, 0x35, 0xa2, 0x9c, 0xb5, + 0x67, 0x78, 0xc2, 0x60, 0xa5, 0xf7, 0x38, 0x1d, 0xd5, 0xb4, 0x01, 0xfa, 0x58, 0xd7, 0xbf, 0xe3, 0xb6, 0xb1, 0xb8, + 0xad, 0x78, 0xb3, 0x10, 0xd2, 0x9b, 0x2b, 0x63, 0x54, 0x35, 0xf5, 0xc6, 0xf5, 0x66, 0xb6, 0x5f, 0xb2, 0xca, 0xa6, + 0xd4, 0x9a, 0xd9, 0xd6, 0xde, 0x03, 0xde, 0xb4, 0xde, 0x80, 0x56, 0xa5, 0xc8, 0xf6, 0x7c, 0x2d, 0x0b, 0x04, 0x47, + 0x78, 0xe8, 0xb0, 0xde, 0x80, 0x5d, 0x3b, 0x40, 0x3d, 0xc8, 0x27, 0x9c, 0x06, 0x5f, 0xf9, 0x46, 0xb2, 0x3c, 0x67, + 0xf3, 0xfc, 0x88, 0x94, 0x2d, 0xa1, 0x3b, 0xb1, 0x8f, 0x0a, 0x36, 0xa8, 0x37, 0xb3, 0xc3, 0x77, 0x33, 0xa8, 0x37, + 0x3b, 0xd1, 0xa6, 0xc5, 0xf6, 0x44, 0x4b, 0x1b, 0xaa, 0xd3, 0x65, 0x53, 0xf6, 0x9d, 0xaf, 0x84, 0xee, 0x59, 0x78, + 0xf5, 0x50, 0xe2, 0x7a, 0x4f, 0x97, 0xb8, 0x1e, 0xd8, 0xa6, 0xe8, 0x95, 0xda, 0xc4, 0xbd, 0xb6, 0xd8, 0x0c, 0x80, + 0x0d, 0x7a, 0x67, 0xe1, 0xeb, 0xb3, 0xf0, 0xea, 0xbf, 0x52, 0xbb, 0x7e, 0x77, 0xe1, 0xfa, 0x86, 0xaa, 0xf5, 0x8d, + 0x15, 0xab, 0xf3, 0xce, 0x3a, 0x7f, 0x16, 0xbe, 0x76, 0xdc, 0x9d, 0x20, 0x5a, 0x2c, 0xe8, 0xff, 0x02, 0xda, 0x7f, + 0xc5, 0x31, 0xbc, 0xa4, 0x13, 0x72, 0x01, 0xed, 0xd0, 0x41, 0x44, 0xc2, 0x09, 0x8c, 0xaf, 0x06, 0x64, 0x40, 0xc1, + 0xb6, 0x43, 0x23, 0x18, 0x93, 0xc9, 0x05, 0xd0, 0x11, 0x09, 0xc7, 0x40, 0x19, 0x30, 0x4a, 0x86, 0x6f, 0x58, 0x48, + 0x46, 0x43, 0x18, 0x5f, 0xb1, 0x80, 0x84, 0x0c, 0x3a, 0xde, 0x11, 0x61, 0x0c, 0x42, 0xcb, 0x12, 0x56, 0x01, 0xb0, + 0x34, 0x24, 0xc1, 0x18, 0x02, 0x18, 0x91, 0xe0, 0x82, 0x4c, 0x46, 0x30, 0x21, 0x63, 0x0a, 0x8c, 0x0c, 0x86, 0xa5, + 0x37, 0x24, 0x14, 0x46, 0x24, 0x1c, 0xf1, 0x09, 0x19, 0x84, 0xd0, 0x0e, 0x1d, 0x1c, 0x63, 0xc2, 0x98, 0x47, 0x02, + 0xfa, 0x26, 0x24, 0x6c, 0x0c, 0x63, 0x32, 0x18, 0x5c, 0xd2, 0x11, 0xb9, 0x18, 0x40, 0x37, 0x76, 0xf0, 0x52, 0x06, + 0xc3, 0xa7, 0x40, 0x63, 0x7f, 0x5e, 0xd0, 0x42, 0xc2, 0x28, 0x84, 0xe4, 0x62, 0xc2, 0x6d, 0x5f, 0xca, 0xa0, 0x1b, + 0x3b, 0xdc, 0x28, 0x85, 0xe0, 0x77, 0x63, 0x16, 0xfe, 0x79, 0x31, 0xa3, 0x16, 0x01, 0x46, 0x06, 0xe1, 0x25, 0x0d, + 0xc9, 0x08, 0xda, 0xa1, 0x3b, 0x9b, 0x32, 0x98, 0x5c, 0x5d, 0xc0, 0x04, 0x46, 0x64, 0x34, 0x81, 0x0b, 0x18, 0x5a, + 0x74, 0x2f, 0xc8, 0x64, 0xd0, 0x09, 0x79, 0x8c, 0x7c, 0x2b, 0x8c, 0x83, 0x3f, 0x30, 0x8c, 0x4f, 0xf9, 0xf4, 0x07, + 0x76, 0xe9, 0xff, 0x71, 0x05, 0x45, 0x7e, 0xd7, 0x86, 0x45, 0x7e, 0xf7, 0x3c, 0x60, 0xbb, 0xa8, 0x24, 0xb2, 0xdd, + 0x48, 0x12, 0x15, 0x14, 0x44, 0x16, 0x57, 0x3c, 0x4d, 0x4e, 0x5a, 0xfd, 0xc8, 0x2f, 0xe8, 0x61, 0xab, 0xa0, 0xc9, + 0xa3, 0xc6, 0xbd, 0xdb, 0x6b, 0x2b, 0x7d, 0x72, 0x53, 0x20, 0xbc, 0xbe, 0x7e, 0x07, 0x6b, 0x51, 0x96, 0x20, 0xd5, + 0x1a, 0x4c, 0x73, 0x0f, 0x46, 0xd9, 0x57, 0x03, 0x89, 0xa9, 0xb1, 0xa4, 0x29, 0x10, 0xf6, 0x7d, 0x04, 0x21, 0x24, + 0x9a, 0x37, 0xc9, 0xbb, 0x12, 0xb9, 0x46, 0x58, 0x88, 0x15, 0x82, 0x30, 0xa0, 0x55, 0x85, 0x60, 0x84, 0x1d, 0x8e, + 0x82, 0x2d, 0x5f, 0xe4, 0x77, 0x87, 0x74, 0x8d, 0xb2, 0xc8, 0x62, 0x89, 0x26, 0xd9, 0x77, 0xc4, 0x51, 0x11, 0x76, + 0x56, 0x5d, 0xa3, 0x31, 0x42, 0x2e, 0xac, 0x55, 0x61, 0x12, 0xd9, 0x5f, 0xb7, 0xc0, 0xdb, 0xdf, 0x0c, 0xb1, 0xbf, + 0x16, 0xb9, 0xb0, 0x6f, 0x06, 0x49, 0xd4, 0x76, 0x91, 0x56, 0x83, 0x6d, 0x64, 0xba, 0x07, 0x8e, 0x96, 0x2a, 0x51, + 0x2e, 0x4c, 0x11, 0x87, 0x0c, 0xea, 0x92, 0xa7, 0x58, 0xa8, 0x32, 0xc3, 0x26, 0xbe, 0xbe, 0xfe, 0xf9, 0xaf, 0xf6, + 0x35, 0xc4, 0x9a, 0x70, 0x94, 0xac, 0xf5, 0x5d, 0x27, 0x68, 0x89, 0xbd, 0xdc, 0x68, 0xd0, 0xbd, 0x6b, 0xd4, 0x5c, + 0xeb, 0xb5, 0x6a, 0xb2, 0x47, 0x5a, 0xde, 0x1d, 0x16, 0xf7, 0x9a, 0xda, 0xff, 0xb6, 0x1f, 0xed, 0x84, 0xf4, 0x72, + 0x5e, 0x09, 0x93, 0x5c, 0xf3, 0x15, 0x46, 0x7e, 0xb7, 0x91, 0x44, 0xbe, 0x75, 0xa0, 0xe3, 0x2d, 0xf6, 0x32, 0x05, + 0x4d, 0x7e, 0xbd, 0xb9, 0x84, 0xdf, 0xea, 0x8c, 0x1b, 0xec, 0xb0, 0x6f, 0xbd, 0xac, 0xd0, 0x14, 0x2a, 0x8b, 0xdf, + 0xfd, 0x7a, 0x7d, 0x73, 0xf4, 0x78, 0xd9, 0x32, 0x01, 0xca, 0xb4, 0x7b, 0x6f, 0x59, 0x96, 0x46, 0xd4, 0xbc, 0x31, + 0xad, 0x5a, 0xcf, 0x66, 0xc7, 0xc1, 0xa3, 0x76, 0x3f, 0x17, 0x25, 0x76, 0x4e, 0xed, 0x05, 0xfd, 0x04, 0xbe, 0x66, + 0xe3, 0xe1, 0xec, 0x2f, 0xac, 0xf4, 0xbb, 0x00, 0xf2, 0xbb, 0x68, 0xf2, 0xdb, 0xd7, 0xa8, 0x7f, 0x02, 0x14, 0xee, 0xbc, 0x64, 0x9d, 0x12, 0x00, 0x00}; } // namespace captive_portal diff --git a/esphome/components/web_server/server_index_v2.h b/esphome/components/web_server/server_index_v2.h index 21beecfff7..31c2d1fd85 100644 --- a/esphome/components/web_server/server_index_v2.h +++ b/esphome/components/web_server/server_index_v2.h @@ -1,633 +1,636 @@ #pragma once // Generated from https://github.com/esphome/esphome-webserver + #ifdef USE_WEBSERVER_LOCAL #if USE_WEBSERVER_VERSION == 2 -#include "esphome/core/hal.h" -namespace esphome { +#include "esphome/core/hal.h" + +namespace esphome { namespace web_server { const uint8_t INDEX_GZ[] PROGMEM = { - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc5, 0x7d, 0xd9, 0x92, 0xdb, 0x46, 0xb6, 0xe0, 0xf3, + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xcd, 0x7d, 0xd9, 0x92, 0xdb, 0x46, 0xb6, 0xe0, 0xf3, 0xdc, 0xaf, 0x40, 0xc1, 0xd5, 0x25, 0x64, 0x33, 0x89, 0x22, 0x59, 0xda, 0x0c, 0x56, 0x92, 0x5d, 0x2a, 0xc9, 0x2d, 0xbb, 0xb5, 0xd8, 0x2a, 0xc9, 0x6e, 0x9b, 0x66, 0x57, 0xa1, 0x88, 0x24, 0x99, 0x16, 0x88, 0xa4, 0x13, 0xc9, 0x5a, 0x4c, 0xe2, 0xc6, 0x7c, 0xc0, 0x44, 0x4c, 0xc4, 0x3c, 0xcd, 0xcb, 0xc4, 0xdc, 0x87, 0xf9, 0x88, 0x79, 0xbe, 0x9f, - 0x72, 0x7f, 0x60, 0xe6, 0x13, 0x26, 0x4e, 0x2e, 0x40, 0x82, 0x4b, 0xa9, 0xbc, 0xdc, 0x3b, 0xa1, 0x90, 0x44, 0xe4, - 0x7a, 0xf2, 0xe4, 0xc9, 0xb3, 0x27, 0x70, 0xbc, 0x97, 0xf0, 0x91, 0xbc, 0x9d, 0x53, 0x6f, 0x2a, 0x67, 0x69, 0xef, - 0xd8, 0xfc, 0x4b, 0xe3, 0xa4, 0x77, 0x9c, 0xb2, 0xec, 0xa3, 0x27, 0x68, 0x4a, 0xd8, 0x88, 0x67, 0xde, 0x54, 0xd0, - 0x31, 0x49, 0x62, 0x19, 0x47, 0x6c, 0x16, 0x4f, 0xa8, 0x77, 0xd8, 0x3b, 0x9e, 0x51, 0x19, 0x7b, 0xa3, 0x69, 0x2c, - 0x72, 0x2a, 0xc9, 0x87, 0xf7, 0x5f, 0x34, 0x9f, 0xf6, 0x8e, 0xf3, 0x91, 0x60, 0x73, 0xe9, 0xc1, 0x90, 0x64, 0xc6, - 0x93, 0x45, 0x4a, 0x7b, 0x87, 0x87, 0xd7, 0xd7, 0xd7, 0xe1, 0x4f, 0xf9, 0x3f, 0x8d, 0x78, 0x96, 0x4b, 0xef, 0x15, - 0xb9, 0x66, 0x59, 0xc2, 0xaf, 0x31, 0x95, 0xe4, 0x55, 0x78, 0x36, 0x8d, 0x13, 0x7e, 0xfd, 0x8e, 0x73, 0x79, 0x70, - 0x10, 0xe8, 0xc7, 0xdb, 0xd3, 0xb3, 0x33, 0x42, 0xc8, 0x15, 0x67, 0x89, 0xd7, 0x5a, 0xad, 0xaa, 0xc2, 0x30, 0x8b, - 0x25, 0xbb, 0xa2, 0xba, 0x0b, 0x3a, 0x38, 0xf0, 0xe3, 0x84, 0xcf, 0x25, 0x4d, 0xce, 0xe4, 0x6d, 0x4a, 0xcf, 0xa6, - 0x94, 0xca, 0xdc, 0x67, 0x99, 0xf7, 0x9c, 0x8f, 0x16, 0x33, 0x9a, 0xc9, 0x70, 0x2e, 0xb8, 0xe4, 0x00, 0xc9, 0xc1, - 0x81, 0x2f, 0xe8, 0x3c, 0x8d, 0x47, 0x14, 0xea, 0x4f, 0xcf, 0xce, 0xaa, 0x1e, 0x55, 0x23, 0xcc, 0x24, 0x39, 0xbb, - 0x9d, 0x5d, 0xf2, 0x34, 0x40, 0x38, 0x95, 0x24, 0xa3, 0xd7, 0xde, 0x77, 0x34, 0xfe, 0xf8, 0x3a, 0x9e, 0x77, 0x47, - 0x69, 0x9c, 0xe7, 0xde, 0xa5, 0x5c, 0xaa, 0x25, 0x88, 0xc5, 0x48, 0x72, 0x11, 0x48, 0x4c, 0x31, 0x43, 0x4b, 0x36, - 0x0e, 0xe4, 0x94, 0xe5, 0xe1, 0xf9, 0xfe, 0x28, 0xcf, 0xdf, 0xd1, 0x7c, 0x91, 0xca, 0x7d, 0xb2, 0xd7, 0xc2, 0x6c, - 0x8f, 0x10, 0x26, 0x91, 0x9c, 0x0a, 0x7e, 0xed, 0xbd, 0x10, 0x82, 0x8b, 0xc0, 0x3f, 0x3d, 0x3b, 0xd3, 0x2d, 0x3c, - 0x96, 0x7b, 0x19, 0x97, 0x5e, 0x39, 0x5e, 0x7c, 0x99, 0xd2, 0xd0, 0xfb, 0x90, 0x53, 0xef, 0x62, 0x91, 0xe5, 0xf1, - 0x98, 0x9e, 0x9e, 0x9d, 0x5d, 0x78, 0x5c, 0x78, 0x17, 0xa3, 0x3c, 0xbf, 0xf0, 0x58, 0x96, 0x4b, 0x1a, 0x27, 0xa1, - 0x8f, 0xba, 0x6a, 0xb2, 0x51, 0x9e, 0xbf, 0xa7, 0x37, 0x92, 0x48, 0xac, 0x1e, 0x25, 0xa1, 0xc5, 0x84, 0x4a, 0x2f, - 0x2f, 0xd7, 0x15, 0xa0, 0x65, 0x4a, 0xa5, 0x27, 0x89, 0xaa, 0xe7, 0x5d, 0x8d, 0x7b, 0xaa, 0x1f, 0x65, 0x97, 0x8d, - 0x03, 0x2a, 0x0f, 0x0e, 0x64, 0x89, 0x67, 0xa4, 0x97, 0xe6, 0x31, 0x42, 0xf7, 0x6c, 0xd9, 0xc1, 0x01, 0x0d, 0x53, - 0x9a, 0x4d, 0xe4, 0x94, 0x10, 0xd2, 0xee, 0xb2, 0x83, 0x83, 0x40, 0x92, 0x54, 0x86, 0x13, 0x2a, 0x03, 0x8a, 0x10, - 0xae, 0x7a, 0x1f, 0x1c, 0x04, 0x1a, 0x09, 0x9c, 0x68, 0xc4, 0xd5, 0x70, 0x8c, 0x42, 0x83, 0xfd, 0xb3, 0xdb, 0x6c, - 0x14, 0xb8, 0xf0, 0x23, 0xcc, 0x0e, 0x0e, 0x52, 0x19, 0xe6, 0x30, 0x22, 0x96, 0x08, 0x15, 0x82, 0xca, 0x85, 0xc8, - 0x3c, 0x59, 0x48, 0x7e, 0x26, 0x05, 0xcb, 0x26, 0x01, 0x5a, 0xda, 0x32, 0xa7, 0x63, 0x51, 0x68, 0x70, 0xbf, 0x96, - 0x44, 0x90, 0x1e, 0xcc, 0x78, 0x29, 0x03, 0xd8, 0x45, 0x3e, 0xf6, 0x04, 0x21, 0x7e, 0xae, 0xfa, 0xfa, 0x7d, 0x11, - 0x89, 0x86, 0xef, 0x63, 0x0d, 0x25, 0x66, 0x12, 0xe1, 0x8f, 0x24, 0x10, 0x38, 0x0c, 0x43, 0x89, 0x48, 0x6f, 0x69, - 0xb1, 0x22, 0x9c, 0x75, 0xf6, 0xc5, 0xa0, 0x35, 0x8c, 0x64, 0x28, 0x68, 0xb2, 0x18, 0xd1, 0x20, 0x60, 0x38, 0xc7, - 0x19, 0x22, 0x3d, 0xd6, 0x08, 0x38, 0xe9, 0xc1, 0x76, 0xf3, 0xfa, 0x5e, 0x13, 0xb2, 0xd7, 0x42, 0x06, 0x46, 0x6e, - 0x01, 0x04, 0x0c, 0x1b, 0x78, 0x38, 0x21, 0x7e, 0xb6, 0x98, 0x5d, 0x52, 0xe1, 0x97, 0xcd, 0xba, 0x35, 0xb2, 0x58, - 0xe4, 0xd4, 0x1b, 0xe5, 0xb9, 0x37, 0x5e, 0x64, 0x23, 0xc9, 0x78, 0xe6, 0xf9, 0x0d, 0xde, 0xf0, 0x35, 0x39, 0x94, - 0xd4, 0xe0, 0xa3, 0x02, 0x05, 0x39, 0x6a, 0x88, 0x41, 0xd6, 0x68, 0x0f, 0x31, 0x40, 0x89, 0xba, 0x66, 0x3c, 0x83, - 0x00, 0x8a, 0x05, 0xac, 0xb1, 0xc0, 0x1f, 0x24, 0xac, 0x52, 0x2d, 0x91, 0xca, 0xbe, 0x08, 0x37, 0x0f, 0x0a, 0x91, - 0xe1, 0x2c, 0x9e, 0x07, 0x94, 0xf4, 0xa8, 0x22, 0xae, 0x38, 0x1b, 0x01, 0xac, 0xb5, 0x7d, 0xeb, 0xd3, 0x88, 0x86, - 0x15, 0x49, 0xa1, 0x48, 0x86, 0x63, 0x2e, 0x5e, 0xc4, 0xa3, 0x29, 0xf4, 0x2b, 0x09, 0x26, 0xb1, 0xe7, 0x6d, 0x24, - 0x68, 0x2c, 0xe9, 0x8b, 0x94, 0xc2, 0x53, 0xe0, 0xab, 0x9e, 0x3e, 0xc2, 0x39, 0x79, 0x15, 0xa6, 0x4c, 0xbe, 0xe1, - 0xd9, 0x88, 0x76, 0x73, 0x87, 0xba, 0x18, 0xec, 0xfb, 0x89, 0x94, 0x82, 0x5d, 0x2e, 0x24, 0x0d, 0xfc, 0x0c, 0x5a, - 0xf8, 0x38, 0x47, 0x98, 0x85, 0x92, 0xde, 0xc8, 0x53, 0x9e, 0x49, 0x9a, 0x49, 0x42, 0x2d, 0x52, 0xb1, 0x08, 0xe3, - 0xf9, 0x9c, 0x66, 0xc9, 0xe9, 0x94, 0xa5, 0x49, 0xc0, 0x50, 0x81, 0x0a, 0x1c, 0x4b, 0x02, 0x6b, 0x24, 0x3d, 0x11, - 0xc1, 0x3f, 0xbb, 0x57, 0x13, 0x48, 0xd2, 0x53, 0x87, 0x82, 0x12, 0xdf, 0xef, 0x8e, 0xb9, 0x08, 0xcc, 0x0a, 0x3c, - 0x3e, 0xf6, 0x24, 0xcc, 0xf1, 0x6e, 0x91, 0xd2, 0x1c, 0xd1, 0x06, 0x61, 0xe5, 0x36, 0x1a, 0x04, 0x7f, 0x0d, 0x14, - 0x5f, 0xa0, 0x40, 0xa0, 0x48, 0x74, 0xaf, 0x62, 0xe1, 0x7d, 0x61, 0x4e, 0xd4, 0x4f, 0x96, 0x9b, 0x4d, 0x25, 0xf9, - 0x29, 0x94, 0x62, 0x91, 0x4b, 0x9a, 0xbc, 0xbf, 0x9d, 0xd3, 0x1c, 0xbf, 0x94, 0x64, 0x2a, 0xfb, 0x53, 0x19, 0xd2, - 0xd9, 0x5c, 0xde, 0x9e, 0x29, 0xc6, 0x18, 0xf9, 0x3e, 0x1e, 0x41, 0x4b, 0x41, 0xe3, 0x11, 0x30, 0x33, 0x83, 0xad, - 0xaf, 0x79, 0x7a, 0x3b, 0x66, 0x69, 0x7a, 0xb6, 0x98, 0xcf, 0xb9, 0x90, 0xf8, 0xaf, 0x64, 0x29, 0x79, 0x85, 0x1a, - 0xd8, 0xcb, 0x65, 0x7e, 0xcd, 0xe4, 0x68, 0x1a, 0x48, 0xb4, 0x1c, 0xc5, 0x39, 0xf5, 0x9e, 0x71, 0x9e, 0xd2, 0x38, - 0x8b, 0x04, 0x11, 0xfd, 0x97, 0x32, 0xca, 0x16, 0x69, 0xda, 0xbd, 0x14, 0x34, 0xfe, 0xd8, 0x55, 0xd5, 0x6f, 0x2f, - 0x7f, 0xa2, 0x23, 0x19, 0xa9, 0xdf, 0x27, 0x42, 0xc4, 0xb7, 0xd0, 0x90, 0x10, 0x68, 0xd6, 0x17, 0xd1, 0x57, 0x67, - 0x6f, 0xdf, 0x84, 0xfa, 0x90, 0xb0, 0xf1, 0x6d, 0x20, 0xca, 0x83, 0x27, 0x0a, 0x3c, 0x16, 0x7c, 0xb6, 0x36, 0xb5, - 0xc6, 0x9a, 0xe8, 0xee, 0x00, 0x81, 0x12, 0xb1, 0xa7, 0x87, 0x76, 0x21, 0x78, 0xa3, 0x68, 0x1e, 0x2a, 0x89, 0x99, - 0x17, 0xfe, 0x89, 0x74, 0x71, 0x20, 0xd0, 0xdd, 0xd0, 0x4a, 0x71, 0xbb, 0xa4, 0x44, 0xc1, 0x39, 0x07, 0x09, 0x03, - 0x30, 0x8e, 0x62, 0x39, 0x9a, 0x2e, 0xa9, 0x1a, 0xac, 0xb0, 0x10, 0xd3, 0xa2, 0xc0, 0xd7, 0x25, 0xbd, 0xcb, 0x3d, - 0x42, 0x84, 0x62, 0x54, 0x44, 0xae, 0x56, 0x82, 0x10, 0x81, 0xf0, 0x77, 0x64, 0x19, 0xdb, 0xf5, 0x44, 0x7b, 0x2d, - 0x0c, 0xe7, 0x32, 0xd2, 0xdc, 0x05, 0x8f, 0x78, 0x76, 0x45, 0x85, 0xa4, 0x22, 0xfa, 0x2b, 0x16, 0x74, 0x9c, 0x02, - 0x14, 0x7b, 0x6d, 0x3c, 0x8d, 0xf3, 0xd3, 0x69, 0x9c, 0x4d, 0x68, 0x12, 0x5d, 0xcb, 0x02, 0xff, 0x9d, 0xf8, 0x63, - 0x96, 0xc5, 0x29, 0xfb, 0x85, 0x26, 0xbe, 0x91, 0x06, 0x27, 0x1e, 0xbd, 0x91, 0x34, 0x4b, 0x72, 0xef, 0xe5, 0xfb, - 0xd7, 0xaf, 0xcc, 0x3e, 0xd6, 0x04, 0x04, 0x5a, 0xe6, 0x8b, 0x39, 0x15, 0x01, 0xc2, 0x46, 0x40, 0xbc, 0x60, 0x8a, - 0x39, 0xbe, 0x8e, 0xe7, 0xba, 0x84, 0xe5, 0x1f, 0xe6, 0x49, 0x2c, 0xe9, 0xd7, 0x34, 0x4b, 0x58, 0x36, 0x21, 0x7b, - 0x6d, 0x5d, 0x3e, 0x8d, 0x4d, 0x45, 0x52, 0x16, 0x9d, 0xef, 0xbf, 0x48, 0xd5, 0xba, 0xcb, 0xc7, 0x45, 0x80, 0x8a, - 0x5c, 0xc6, 0x92, 0x8d, 0xbc, 0x38, 0x49, 0xbe, 0xcc, 0x98, 0x64, 0x0a, 0x40, 0x01, 0xdb, 0x03, 0x24, 0x4a, 0xb5, - 0xa8, 0xb0, 0x80, 0x07, 0x08, 0x07, 0x81, 0x11, 0x00, 0x53, 0x64, 0xf6, 0xeb, 0xe0, 0xa0, 0x62, 0xf7, 0x7d, 0x1a, - 0xe9, 0x4a, 0x32, 0x18, 0xa2, 0x70, 0xbe, 0xc8, 0x61, 0xa3, 0xed, 0x14, 0x20, 0x5d, 0xf8, 0x65, 0x4e, 0xc5, 0x15, - 0x4d, 0x4a, 0xe2, 0xc8, 0x03, 0xb4, 0x5c, 0x9b, 0xc3, 0x1c, 0x0b, 0x49, 0x06, 0xc3, 0xae, 0xcb, 0xb7, 0xa9, 0xa1, - 0x73, 0xc1, 0xe7, 0x54, 0x48, 0x46, 0xf3, 0x92, 0x95, 0x04, 0x20, 0x45, 0x4b, 0x76, 0x92, 0x13, 0xbb, 0xbe, 0x79, - 0xc0, 0x30, 0x45, 0x35, 0x86, 0x61, 0x05, 0xed, 0x8b, 0x2b, 0x25, 0x31, 0x72, 0xcc, 0x10, 0x96, 0x1a, 0xd2, 0x1c, - 0xa1, 0x02, 0x61, 0x69, 0xc1, 0xd5, 0xac, 0xc8, 0xcc, 0x76, 0x0b, 0xa2, 0x9a, 0x7c, 0xa7, 0x44, 0x35, 0x30, 0xb4, - 0x58, 0xd2, 0x83, 0x83, 0x80, 0x86, 0x25, 0x51, 0x90, 0xbd, 0xb6, 0xd9, 0x23, 0x07, 0x59, 0x3b, 0xc0, 0x86, 0x89, - 0x25, 0xa6, 0x08, 0xef, 0xd1, 0x30, 0xe3, 0x27, 0xa3, 0x11, 0xcd, 0x73, 0x2e, 0x0e, 0x0e, 0xf6, 0x54, 0xfb, 0x52, - 0x9b, 0x80, 0x3d, 0x7c, 0x7b, 0x9d, 0x55, 0x10, 0xa0, 0x4a, 0xc2, 0x1a, 0xb9, 0x20, 0x41, 0x4e, 0x29, 0x85, 0xc3, - 0xef, 0x5b, 0xc5, 0x23, 0xf2, 0xcf, 0xcf, 0xfd, 0x86, 0xc4, 0x06, 0x0d, 0x13, 0x6a, 0xa7, 0xbe, 0x7d, 0x4e, 0xb5, - 0x6a, 0xa5, 0x14, 0x8f, 0x0d, 0xcc, 0xe8, 0xf3, 0x13, 0x26, 0x74, 0xcc, 0x32, 0x67, 0xd9, 0x35, 0x90, 0xb0, 0xc4, - 0x39, 0x2a, 0x9c, 0x0d, 0xdd, 0x3a, 0xb4, 0xd2, 0x69, 0xf4, 0xce, 0x2d, 0x27, 0x4a, 0x8f, 0x70, 0xb6, 0x71, 0x40, - 0x87, 0x05, 0x56, 0xa8, 0xb7, 0xab, 0xc9, 0x14, 0xa0, 0x03, 0x39, 0xec, 0x9a, 0x7a, 0x92, 0x6b, 0xcc, 0x09, 0xfa, - 0xf3, 0x82, 0xe6, 0x52, 0xd3, 0x71, 0x20, 0x71, 0x86, 0x19, 0x2a, 0xe0, 0xb8, 0x8d, 0xd9, 0x64, 0x21, 0x40, 0xdd, - 0x81, 0xa3, 0x48, 0xb3, 0xc5, 0x8c, 0xda, 0xa7, 0x6d, 0xb0, 0xbd, 0x9d, 0x83, 0x40, 0xcc, 0x81, 0xa6, 0xef, 0x26, - 0x27, 0x80, 0x55, 0xa2, 0xd5, 0xea, 0x3b, 0x3b, 0x48, 0xb5, 0x95, 0xa5, 0x8a, 0xb6, 0xb6, 0x27, 0x7f, 0x47, 0x46, - 0x1e, 0xef, 0xb5, 0x35, 0xf4, 0x7f, 0x1f, 0x92, 0xbd, 0x56, 0x49, 0xc1, 0x06, 0xa7, 0x1a, 0x18, 0x8d, 0xc2, 0xb7, - 0x7a, 0x20, 0xa4, 0xa4, 0x7b, 0x8d, 0x58, 0xc2, 0xe9, 0x06, 0x9d, 0x4e, 0xc9, 0x00, 0xf4, 0x8c, 0x70, 0x3a, 0xdc, - 0x45, 0x4c, 0x96, 0x1b, 0x04, 0x72, 0xb3, 0xae, 0x62, 0x1a, 0x57, 0x75, 0xa6, 0xb1, 0xb6, 0x08, 0x7f, 0x5e, 0x76, - 0xf1, 0x4b, 0x1a, 0x33, 0xc7, 0xbc, 0xaa, 0xc2, 0x4c, 0x01, 0x53, 0x2d, 0xc9, 0x19, 0xe2, 0x4d, 0x3c, 0xa3, 0x79, - 0x40, 0x11, 0xde, 0xd5, 0x40, 0x13, 0x27, 0x34, 0x19, 0x3a, 0x62, 0x33, 0x07, 0xb1, 0xc9, 0x90, 0xd6, 0xca, 0xea, - 0xc7, 0x2d, 0xc7, 0x74, 0x90, 0x0f, 0x2b, 0x65, 0xce, 0x59, 0xbc, 0x92, 0xc7, 0x86, 0xba, 0x2d, 0xfe, 0x74, 0x99, - 0x46, 0x9a, 0x52, 0x1a, 0x72, 0x84, 0xf7, 0x5a, 0xeb, 0xfb, 0x68, 0x5b, 0x55, 0x6b, 0x1c, 0x0c, 0x61, 0x1f, 0x94, - 0xb8, 0x08, 0x59, 0xae, 0xfe, 0xaf, 0x9d, 0x33, 0x40, 0xdb, 0x19, 0x90, 0x45, 0x38, 0x4e, 0x63, 0x19, 0xb4, 0x0f, - 0x5b, 0xa0, 0x89, 0x5e, 0x51, 0x90, 0x26, 0x08, 0x6d, 0x2e, 0x85, 0x86, 0x8b, 0x2c, 0x9f, 0xb2, 0xb1, 0x0c, 0x62, - 0xa9, 0x18, 0x0a, 0x4d, 0x73, 0xea, 0xc9, 0x9a, 0x3e, 0xac, 0x98, 0x4d, 0x0c, 0xa4, 0x56, 0x2a, 0x5f, 0xd4, 0x42, - 0xaa, 0x98, 0x16, 0xf0, 0x86, 0x4a, 0x97, 0xae, 0x78, 0x8c, 0x6d, 0xcd, 0x40, 0x5f, 0x6c, 0xf7, 0xf5, 0x88, 0x91, - 0x61, 0x05, 0xcc, 0x51, 0x59, 0x59, 0xe4, 0xf2, 0x07, 0x53, 0x28, 0x43, 0xc9, 0x5f, 0xf1, 0x6b, 0x2a, 0x4e, 0x63, - 0x00, 0x3e, 0xd2, 0xdd, 0x0b, 0x2d, 0x06, 0x14, 0xb7, 0x97, 0x5d, 0x4b, 0x2f, 0xe7, 0x6a, 0xe1, 0x5f, 0x0b, 0x3e, - 0x63, 0x39, 0x05, 0x4d, 0x4d, 0xe3, 0x3f, 0x83, 0x53, 0xa6, 0x8e, 0x23, 0x88, 0x1a, 0x5a, 0xd2, 0xd7, 0xc9, 0xab, - 0x3a, 0x7d, 0x9d, 0xef, 0xbf, 0x98, 0x58, 0xf6, 0x57, 0x3f, 0xc4, 0x08, 0x07, 0xc6, 0x9e, 0x70, 0xa4, 0x5c, 0x38, - 0x45, 0x46, 0xbc, 0xaf, 0x56, 0xd2, 0x31, 0xdb, 0x6a, 0xba, 0x22, 0xd5, 0xc7, 0x06, 0x15, 0x71, 0x92, 0x80, 0x56, - 0x27, 0x78, 0x9a, 0x3a, 0x82, 0x0a, 0xb3, 0x6e, 0x29, 0x9a, 0xce, 0xf7, 0x5f, 0x9c, 0xdd, 0x25, 0x9d, 0xa0, 0xde, - 0x15, 0x50, 0x16, 0xd0, 0x2c, 0xa1, 0x02, 0xcc, 0x48, 0x67, 0xb7, 0x8c, 0x8c, 0x3d, 0xe5, 0x59, 0x46, 0x47, 0x92, - 0x26, 0x60, 0xa5, 0x30, 0x22, 0xc3, 0x29, 0xcf, 0x65, 0x59, 0x58, 0x41, 0xcf, 0x1c, 0xe8, 0x59, 0x38, 0x8a, 0xd3, - 0x34, 0xd0, 0x16, 0xc9, 0x8c, 0x5f, 0xd1, 0x2d, 0x50, 0x77, 0x6b, 0x20, 0x97, 0xc3, 0x50, 0x67, 0x18, 0x1a, 0xe6, - 0xf3, 0x94, 0x8d, 0x68, 0x29, 0xb8, 0xce, 0x42, 0x96, 0x25, 0xf4, 0x06, 0xf8, 0x08, 0xea, 0xf5, 0x7a, 0x2d, 0xdc, - 0x46, 0x85, 0x46, 0xf8, 0x72, 0x03, 0xb1, 0x77, 0x88, 0x4c, 0x20, 0x32, 0xd2, 0x5b, 0x6e, 0xe3, 0x07, 0x14, 0x39, - 0x72, 0x92, 0x59, 0xcb, 0x4a, 0xf3, 0x66, 0x84, 0x13, 0x9a, 0x52, 0x49, 0x2d, 0x2f, 0x07, 0xfd, 0x59, 0x1f, 0xdd, - 0x77, 0x25, 0xfe, 0x4a, 0x72, 0xb2, 0xa7, 0xcc, 0xee, 0x79, 0x5e, 0x5a, 0xea, 0xd5, 0xf6, 0x54, 0xd8, 0xee, 0x4b, - 0xbd, 0x3d, 0xb1, 0x94, 0xf1, 0x68, 0xaa, 0x4d, 0xf4, 0x60, 0x63, 0x49, 0xd5, 0x18, 0x86, 0xaf, 0x97, 0x87, 0xe8, - 0x83, 0x05, 0x73, 0x1b, 0x0a, 0xce, 0x0c, 0x53, 0xa0, 0x60, 0xf5, 0xe9, 0x6d, 0x3b, 0x8d, 0xd3, 0xf4, 0x32, 0x1e, - 0x7d, 0xac, 0x53, 0x7f, 0x45, 0x06, 0x64, 0x9d, 0x1b, 0x3b, 0x55, 0x0e, 0xcb, 0x72, 0xd7, 0x6d, 0xb9, 0x74, 0xed, - 0xa0, 0x04, 0x7b, 0xad, 0x8a, 0xec, 0xeb, 0x1b, 0xbd, 0x93, 0xda, 0x15, 0x44, 0xcc, 0xac, 0x2c, 0x00, 0x2e, 0xf0, - 0x49, 0x8a, 0xb3, 0xfc, 0xc0, 0xd0, 0x1d, 0xd8, 0x1a, 0xc5, 0x1a, 0x20, 0x12, 0x2d, 0x8b, 0x84, 0xe5, 0xbb, 0x31, - 0xf0, 0x87, 0x40, 0xf9, 0xdc, 0x99, 0xe1, 0xbe, 0x80, 0x96, 0x3c, 0xce, 0xa8, 0xcc, 0x25, 0x64, 0x46, 0x9b, 0xb0, - 0x8c, 0xe6, 0x6f, 0xa0, 0xb9, 0x28, 0x7a, 0x7f, 0xab, 0xab, 0x40, 0x27, 0x03, 0x28, 0xf2, 0xae, 0xab, 0x4c, 0xd4, - 0x28, 0xc0, 0xf0, 0x54, 0xa6, 0x44, 0x6e, 0x56, 0x33, 0x1e, 0x8d, 0xba, 0xae, 0xed, 0x6f, 0xc3, 0x72, 0x39, 0x09, - 0x82, 0x20, 0x07, 0xfb, 0xcd, 0xea, 0xf5, 0xd5, 0x22, 0xf2, 0x8d, 0x45, 0xe4, 0xa1, 0x63, 0x64, 0xa1, 0x8a, 0x96, - 0x9d, 0xee, 0xd1, 0x5f, 0x91, 0xdb, 0x08, 0x94, 0xd5, 0x10, 0xf8, 0x33, 0x2a, 0xd9, 0x6d, 0x4a, 0x24, 0xe6, 0xc6, - 0xc0, 0x31, 0x94, 0x06, 0x0c, 0xa3, 0xea, 0x92, 0x21, 0x7d, 0x34, 0x6a, 0xc6, 0x6e, 0x86, 0x39, 0x5a, 0xd3, 0xec, - 0x8b, 0xc2, 0xe0, 0x88, 0x22, 0xb3, 0x37, 0x35, 0x95, 0xd8, 0xc1, 0x0a, 0xce, 0x88, 0x51, 0x83, 0xb5, 0xd6, 0xb3, - 0x8e, 0x9b, 0x72, 0x5c, 0x38, 0xa8, 0x15, 0x6a, 0x6a, 0xfa, 0xa4, 0x55, 0xac, 0x32, 0x84, 0xa7, 0x56, 0x23, 0xe5, - 0xd5, 0xba, 0x09, 0xf1, 0xad, 0x37, 0xc2, 0xef, 0x2f, 0x6b, 0x26, 0x61, 0xe4, 0x34, 0x2b, 0x22, 0x60, 0xa9, 0x7c, - 0x1b, 0xba, 0xb7, 0xd1, 0x4c, 0x6d, 0x1c, 0x07, 0xe1, 0xdc, 0x45, 0xb8, 0x83, 0xd9, 0x4c, 0x73, 0xae, 0x6c, 0x48, - 0xa6, 0xf5, 0xbe, 0x01, 0xc5, 0x5c, 0xef, 0xc3, 0x06, 0x12, 0xd7, 0x15, 0x4f, 0x45, 0x82, 0x60, 0xc0, 0xe6, 0xa0, - 0xdc, 0xb9, 0xf2, 0x21, 0x00, 0xd8, 0xd9, 0x6a, 0xb5, 0x41, 0x74, 0x5b, 0xf5, 0x4f, 0x14, 0x56, 0x46, 0xe1, 0x6a, - 0x75, 0x2d, 0x51, 0x60, 0x34, 0x5f, 0x4c, 0x51, 0xdf, 0x72, 0xdc, 0x93, 0x57, 0xd0, 0x4a, 0x29, 0xa2, 0x55, 0x49, - 0x69, 0x32, 0xd4, 0x69, 0xb6, 0xbe, 0x4f, 0xd2, 0x61, 0xdb, 0xa7, 0x1b, 0xdc, 0x4b, 0x15, 0x1a, 0x31, 0x5d, 0x2d, - 0xf9, 0xd4, 0x0c, 0xcd, 0x10, 0x42, 0x51, 0xae, 0xac, 0x98, 0xbd, 0x6d, 0x86, 0xe5, 0xc1, 0x41, 0xee, 0x0c, 0x74, - 0x5e, 0xb2, 0x89, 0x9f, 0x02, 0x10, 0xc9, 0xf9, 0x6d, 0xa6, 0x74, 0x97, 0x9f, 0xac, 0x10, 0xda, 0x30, 0x4b, 0x5b, - 0x5d, 0xb0, 0xc6, 0xe3, 0xeb, 0x98, 0x49, 0xaf, 0x1c, 0x45, 0x5b, 0xe3, 0x01, 0x45, 0x4b, 0xa3, 0x6a, 0x84, 0x82, - 0x82, 0xf2, 0x08, 0x3c, 0xc1, 0xaa, 0xd0, 0x9a, 0xee, 0x47, 0x53, 0x0a, 0x8e, 0x60, 0xab, 0x45, 0x94, 0x76, 0xe1, - 0x9e, 0x91, 0x22, 0x66, 0xe0, 0xed, 0xb0, 0x17, 0xeb, 0xdd, 0x6b, 0x76, 0xc0, 0x9c, 0x8a, 0x31, 0x17, 0x33, 0x5b, - 0x57, 0xac, 0x3d, 0x1b, 0xce, 0xc8, 0xc6, 0xc1, 0xd6, 0xb1, 0x8d, 0xfa, 0xdf, 0x5d, 0x33, 0xba, 0x2b, 0x73, 0xbd, - 0x26, 0x4a, 0x4b, 0xe9, 0xab, 0xfd, 0x81, 0x96, 0x32, 0x73, 0xd7, 0xbc, 0x37, 0xce, 0xd4, 0xae, 0x76, 0x98, 0xec, - 0xb5, 0xbb, 0xa5, 0xcd, 0x67, 0xa9, 0xa1, 0xab, 0x1d, 0x1b, 0x46, 0xa4, 0xf2, 0x45, 0x9a, 0x18, 0x60, 0x19, 0xc2, - 0xd4, 0xd0, 0xd1, 0x35, 0x4b, 0xd3, 0xaa, 0xf4, 0xd7, 0xf0, 0xf5, 0xdc, 0xf0, 0xf5, 0xcc, 0xf2, 0x75, 0xe0, 0x14, - 0xc0, 0xd7, 0xf5, 0x70, 0x55, 0xf7, 0x6c, 0xe3, 0x74, 0x66, 0x9a, 0xa3, 0xe7, 0xca, 0x8e, 0x86, 0xf9, 0x16, 0x16, - 0x02, 0x54, 0x6a, 0x5e, 0x1f, 0x03, 0xe3, 0x84, 0x01, 0x03, 0x50, 0xbb, 0x30, 0xa9, 0xeb, 0xa2, 0xf8, 0x18, 0x20, - 0x9c, 0x17, 0xb4, 0xa4, 0xec, 0x93, 0x17, 0xe0, 0xa4, 0x73, 0x96, 0x03, 0x42, 0x4c, 0x15, 0xff, 0x2a, 0x25, 0xca, - 0xae, 0x8e, 0x99, 0xd5, 0xe5, 0x76, 0x75, 0xc0, 0xe9, 0xab, 0xd5, 0x25, 0x77, 0xf3, 0x7a, 0xb5, 0x3c, 0x56, 0x2e, - 0xaf, 0xda, 0xef, 0xd5, 0x2a, 0x58, 0x2b, 0x01, 0xff, 0xbd, 0x31, 0x51, 0x44, 0x39, 0x3a, 0xf0, 0x00, 0x17, 0x33, - 0x50, 0x50, 0xe8, 0x45, 0x97, 0x22, 0xee, 0xd5, 0xa7, 0x1c, 0x3c, 0xca, 0x4d, 0xaf, 0xfb, 0x9f, 0xf2, 0xd9, 0x1c, - 0xb4, 0xb1, 0x35, 0x92, 0x9e, 0x50, 0x33, 0x61, 0x55, 0x5f, 0x6c, 0x29, 0xab, 0xf5, 0x51, 0xe7, 0xb1, 0x46, 0x4d, - 0xa5, 0xbd, 0xbc, 0xd7, 0x2a, 0x16, 0x65, 0x51, 0xc9, 0x38, 0xb6, 0x39, 0x55, 0x4e, 0xd7, 0x5d, 0x32, 0xb6, 0xe2, - 0x6d, 0xc0, 0x34, 0x1f, 0x66, 0xc0, 0xeb, 0x1c, 0xf6, 0x63, 0xc9, 0xdd, 0xdd, 0xff, 0xa2, 0x42, 0xce, 0xb2, 0x58, - 0x43, 0xdf, 0xb2, 0x28, 0x4e, 0xb4, 0x91, 0x8d, 0x4f, 0x76, 0x5b, 0xc3, 0x55, 0x9d, 0x31, 0x16, 0x07, 0x43, 0x7c, - 0xb2, 0xa9, 0x3a, 0x92, 0xe5, 0x8c, 0x27, 0x34, 0xf2, 0xf9, 0x9c, 0x66, 0x7e, 0x01, 0x5e, 0x55, 0xb3, 0xf7, 0x23, - 0x19, 0x2c, 0xdf, 0xd5, 0xdd, 0xab, 0xd1, 0x49, 0x01, 0xde, 0xaf, 0x2f, 0x36, 0x1d, 0xaf, 0xdf, 0x52, 0x91, 0x2b, - 0x45, 0xb4, 0xd4, 0x69, 0xbf, 0xa8, 0xc4, 0xd2, 0x17, 0xd1, 0xce, 0xf6, 0x95, 0x09, 0xe2, 0xb7, 0xc3, 0xc7, 0xe1, - 0x91, 0x8f, 0x94, 0x5b, 0xf8, 0x2b, 0x73, 0xe0, 0x9f, 0x5b, 0xb7, 0xf0, 0x0b, 0xf2, 0xbc, 0xee, 0x15, 0x4e, 0x24, - 0x79, 0xd1, 0x7f, 0x61, 0x2d, 0x66, 0x9e, 0xb2, 0xd1, 0x6d, 0xe0, 0xa7, 0x4c, 0x36, 0x21, 0xf4, 0xe6, 0xe3, 0xa5, - 0xae, 0x00, 0x97, 0xa2, 0x72, 0x67, 0x17, 0xd6, 0xd6, 0xc3, 0x52, 0x12, 0x7f, 0x3f, 0x65, 0x72, 0xdf, 0xc7, 0x33, - 0x72, 0x01, 0x3f, 0xf6, 0x97, 0xc1, 0xeb, 0x58, 0x4e, 0x43, 0x11, 0x67, 0x09, 0x9f, 0x05, 0xa8, 0xe1, 0xfb, 0x28, - 0xcc, 0x95, 0xbd, 0xf1, 0x39, 0x2a, 0xf6, 0x2f, 0xf0, 0x8d, 0x24, 0x7e, 0xdf, 0x6f, 0xcc, 0xf0, 0x1b, 0x49, 0x2e, - 0x8e, 0xf7, 0x97, 0x37, 0xb2, 0xe8, 0x5d, 0xe0, 0x9b, 0xd2, 0x63, 0x8f, 0xbf, 0x26, 0x01, 0x22, 0xbd, 0x1b, 0x03, - 0xcd, 0x29, 0x9f, 0x69, 0xcf, 0xbd, 0x8f, 0xf0, 0x07, 0x88, 0xab, 0x88, 0x8a, 0xdb, 0x98, 0xd0, 0xca, 0x1e, 0xf1, - 0xb9, 0x72, 0x11, 0xf8, 0x07, 0x07, 0x4e, 0x59, 0xa9, 0x2a, 0xe0, 0x13, 0x49, 0x6a, 0x06, 0x39, 0x7e, 0xaf, 0x22, - 0x34, 0x27, 0x32, 0x10, 0xc8, 0x0e, 0x13, 0x58, 0x3f, 0xb4, 0x39, 0x9a, 0x62, 0xa0, 0x3d, 0x0c, 0x21, 0x93, 0x54, - 0xc4, 0x92, 0x8b, 0x21, 0x72, 0xd5, 0x0f, 0xfc, 0x37, 0x72, 0x31, 0xf0, 0xfe, 0xd3, 0x3f, 0xfd, 0x38, 0xfe, 0x51, - 0x0c, 0x2f, 0xf0, 0x5b, 0x72, 0x78, 0x1c, 0xf4, 0xa3, 0x60, 0xaf, 0xd9, 0x5c, 0xfd, 0x78, 0x38, 0xf8, 0x47, 0xdc, - 0xfc, 0xe5, 0xa4, 0xf9, 0xc3, 0x10, 0xad, 0x82, 0x1f, 0x0f, 0xfb, 0x03, 0xf3, 0x34, 0xf8, 0x47, 0xef, 0xc7, 0x7c, - 0xf8, 0x67, 0x5d, 0xb8, 0x8f, 0xd0, 0xe1, 0x04, 0x2f, 0x24, 0x39, 0x6c, 0x36, 0x7b, 0x87, 0x13, 0x3c, 0x97, 0xe4, - 0x10, 0xfe, 0xbf, 0x24, 0xef, 0xe8, 0xe4, 0xc5, 0xcd, 0x3c, 0xb8, 0xe8, 0xad, 0xf6, 0x97, 0x7f, 0x2b, 0x60, 0xd4, - 0xc1, 0x3f, 0x7e, 0xfc, 0x31, 0xf7, 0x1f, 0xf4, 0xc8, 0xe1, 0xb0, 0x81, 0x02, 0x28, 0xfd, 0x33, 0x51, 0xff, 0x06, - 0xfd, 0x68, 0xf0, 0x0f, 0x03, 0x85, 0xff, 0xe0, 0xc7, 0x8b, 0xe3, 0x1e, 0x19, 0xae, 0x02, 0x7f, 0xf5, 0x00, 0xad, - 0x10, 0x5a, 0xed, 0xa3, 0x0b, 0xec, 0x4f, 0x7c, 0x84, 0x27, 0x92, 0x1c, 0x3e, 0x38, 0x9c, 0xe0, 0x2b, 0x49, 0x0e, - 0xfd, 0xc3, 0x09, 0x7e, 0x21, 0xc9, 0xe1, 0x3f, 0x82, 0x7e, 0xa4, 0x3d, 0x6c, 0x2b, 0xe5, 0xde, 0x58, 0x41, 0x70, - 0x23, 0x16, 0x34, 0x5e, 0x49, 0x26, 0x53, 0x8a, 0xf6, 0x0f, 0x19, 0x3e, 0x53, 0x68, 0x0a, 0x24, 0x38, 0x61, 0xc0, - 0xb6, 0x0b, 0x96, 0xe7, 0xb0, 0xd9, 0x40, 0x33, 0xfb, 0x91, 0xc0, 0xda, 0x0f, 0x90, 0x47, 0x12, 0x5f, 0xc5, 0xe9, - 0x82, 0xe6, 0x11, 0x2d, 0x10, 0x1e, 0x91, 0x33, 0x19, 0xb4, 0x11, 0x7e, 0x27, 0xe1, 0x47, 0x07, 0xe1, 0x33, 0x13, - 0xc0, 0x84, 0x83, 0xac, 0x89, 0x2a, 0xe3, 0x5a, 0x63, 0xf1, 0x11, 0x9e, 0x6f, 0xa9, 0x94, 0x53, 0xf0, 0x2e, 0x20, - 0x3c, 0xae, 0x85, 0x3b, 0xf1, 0x35, 0xb1, 0x24, 0xf1, 0x5e, 0x50, 0xfa, 0x5d, 0x9c, 0x7e, 0xa4, 0x22, 0xb8, 0xc1, - 0xed, 0xce, 0xe7, 0x58, 0xb9, 0xa0, 0xf7, 0xda, 0xa8, 0x5b, 0xc6, 0xaa, 0x4e, 0xa5, 0x8e, 0x11, 0x80, 0x90, 0xad, - 0xfb, 0x62, 0x60, 0xc7, 0xf7, 0xc4, 0x86, 0xc3, 0x4a, 0xc4, 0xd7, 0x3e, 0xaa, 0xc7, 0x45, 0x59, 0x76, 0x15, 0xa7, - 0x2c, 0xf1, 0x24, 0x9d, 0xcd, 0xd3, 0x58, 0x52, 0xcf, 0xac, 0xd7, 0x8b, 0x61, 0x20, 0xbf, 0x54, 0x19, 0x12, 0xc7, - 0xe0, 0x4c, 0x6c, 0xc0, 0x09, 0xce, 0x4a, 0x00, 0xd1, 0x29, 0xa3, 0x76, 0xbc, 0xae, 0x82, 0x5f, 0xeb, 0xf1, 0xbd, - 0x66, 0x1b, 0x1c, 0x61, 0x43, 0x25, 0x9e, 0x73, 0x9c, 0x11, 0x10, 0xa2, 0x9d, 0xbe, 0x7f, 0x9c, 0x5f, 0x4d, 0x7a, - 0x3e, 0xc4, 0x66, 0x38, 0x79, 0xab, 0xfc, 0x42, 0xd0, 0x60, 0x4a, 0x5a, 0xdd, 0xe9, 0x31, 0xed, 0x4e, 0x1b, 0x0d, - 0xab, 0x43, 0xa7, 0x44, 0x0c, 0xa6, 0xba, 0x7b, 0x8c, 0x13, 0xbc, 0x20, 0xcd, 0x36, 0x9e, 0x90, 0x96, 0xea, 0xd2, - 0x9d, 0x1c, 0xa7, 0x66, 0x9a, 0x83, 0x83, 0x80, 0x87, 0x69, 0x9c, 0xcb, 0x2f, 0xc1, 0xd8, 0x27, 0x13, 0x9c, 0x10, - 0x1e, 0xd2, 0x1b, 0x3a, 0x0a, 0x52, 0x84, 0x13, 0xc3, 0x69, 0x50, 0x17, 0x4d, 0x88, 0xd3, 0x0c, 0x8c, 0x08, 0xf2, - 0xb6, 0x9f, 0x0c, 0xda, 0x43, 0x42, 0x88, 0xbf, 0xd7, 0x6c, 0xfa, 0x7d, 0x4e, 0x16, 0x32, 0x82, 0x12, 0x47, 0x55, - 0x26, 0x73, 0x28, 0xea, 0x38, 0x45, 0xc1, 0x0b, 0x19, 0x4a, 0x9a, 0xcb, 0x00, 0x8a, 0xc1, 0xfc, 0xcf, 0x2d, 0x61, - 0xfb, 0xc7, 0x87, 0x7e, 0x03, 0x4a, 0x15, 0x71, 0x22, 0xcc, 0xc9, 0x25, 0x8a, 0x92, 0xc1, 0xd1, 0xd0, 0xe5, 0xff, - 0xaa, 0x10, 0x26, 0xbf, 0xec, 0x27, 0x83, 0x96, 0x9a, 0xbc, 0xe7, 0xf7, 0x03, 0x4e, 0x72, 0xad, 0xa0, 0xf5, 0xf3, - 0xe8, 0xad, 0x5a, 0x2a, 0x8a, 0x0c, 0x70, 0x66, 0xde, 0x05, 0x69, 0x76, 0xa2, 0x60, 0xe1, 0x2e, 0xa2, 0x09, 0x93, - 0x19, 0x2c, 0xe0, 0x98, 0x40, 0x7b, 0xcc, 0x09, 0xcc, 0x58, 0x75, 0xbb, 0x8c, 0xcc, 0xf3, 0x03, 0xff, 0x41, 0xff, - 0x4a, 0x46, 0x13, 0xa9, 0xa7, 0xbf, 0x92, 0xab, 0x15, 0xfc, 0x3f, 0x91, 0x7d, 0x4e, 0x2e, 0x55, 0xd1, 0xc2, 0x14, - 0xcd, 0xa1, 0xe8, 0x6d, 0x04, 0xa0, 0xe2, 0xbc, 0x54, 0xb2, 0xf4, 0x9e, 0x5c, 0x11, 0x05, 0xfb, 0xc1, 0x81, 0x18, - 0x4c, 0x1b, 0xed, 0x21, 0xf8, 0xf7, 0x85, 0xcc, 0xbf, 0x63, 0x72, 0x1a, 0xf8, 0x87, 0x3d, 0x1f, 0xf5, 0x7d, 0x0f, - 0xb6, 0xb6, 0x9b, 0x35, 0x88, 0xc6, 0x70, 0xda, 0x78, 0x23, 0xa3, 0x45, 0x8f, 0xb4, 0xfa, 0x01, 0x33, 0xfe, 0x3c, - 0x84, 0x53, 0xc3, 0x38, 0x5b, 0x78, 0x81, 0x1a, 0x52, 0x36, 0xec, 0xf3, 0x02, 0x35, 0x66, 0x8d, 0x2b, 0x14, 0xa5, - 0x8d, 0x59, 0x23, 0x58, 0x10, 0x42, 0x9a, 0x9d, 0xb2, 0x9b, 0x95, 0x7e, 0x53, 0x14, 0x5d, 0x59, 0x67, 0xe7, 0x40, - 0x1d, 0x87, 0xac, 0x11, 0x88, 0x01, 0x1d, 0xae, 0x56, 0xfe, 0x71, 0xbf, 0xe7, 0xa3, 0x46, 0x60, 0x09, 0xed, 0xd0, - 0x52, 0x1a, 0x42, 0x98, 0x0d, 0x0b, 0x13, 0x4a, 0x7a, 0x59, 0x0b, 0x1b, 0x2d, 0xab, 0xc3, 0xee, 0xf0, 0x00, 0x5a, - 0x94, 0x76, 0x8c, 0xd6, 0x57, 0xe7, 0xb0, 0x4c, 0x4b, 0xcc, 0x19, 0x69, 0x61, 0x4e, 0xac, 0xef, 0x7a, 0x4a, 0x64, - 0x45, 0xf0, 0x29, 0xa9, 0x9a, 0xe3, 0x41, 0x8c, 0x93, 0x21, 0x79, 0xad, 0xed, 0x91, 0xae, 0xf5, 0x8b, 0xd3, 0x94, - 0xbc, 0x5c, 0x8b, 0xde, 0xc6, 0x10, 0x5b, 0xb9, 0x0e, 0x47, 0x0b, 0x21, 0x68, 0x26, 0xdf, 0xf0, 0xc4, 0xa8, 0x69, - 0x34, 0x05, 0x4b, 0x09, 0xc2, 0xb2, 0x18, 0x74, 0xb4, 0x8e, 0x3d, 0x19, 0x8b, 0x8d, 0xea, 0x09, 0x59, 0x68, 0xf5, - 0x49, 0x05, 0x6b, 0xbb, 0x13, 0x63, 0x17, 0x07, 0x08, 0x2f, 0x4c, 0x14, 0x37, 0x08, 0xc3, 0x70, 0x12, 0x8e, 0xa0, - 0x1a, 0x26, 0xc8, 0x51, 0xa1, 0xce, 0x51, 0x90, 0x93, 0xeb, 0x30, 0xa3, 0x37, 0x6a, 0xd6, 0x00, 0x55, 0x92, 0xd9, - 0x1e, 0xaf, 0xe3, 0x69, 0x57, 0xb1, 0x9b, 0x3c, 0xcc, 0x78, 0x42, 0x01, 0x3d, 0x10, 0xb7, 0x37, 0x45, 0xd3, 0x38, - 0x77, 0xe3, 0x53, 0x15, 0x7c, 0x03, 0xd7, 0x79, 0x3d, 0x01, 0x8f, 0xaf, 0xd2, 0xb5, 0xca, 0xc6, 0xda, 0x0d, 0x8e, - 0x10, 0x1b, 0x07, 0x93, 0x10, 0xe2, 0x7a, 0x8a, 0x84, 0x24, 0x98, 0x72, 0x13, 0x97, 0xa8, 0x66, 0xe5, 0x98, 0x57, - 0x24, 0x19, 0xf0, 0x46, 0x43, 0x79, 0xa1, 0x17, 0x9a, 0x24, 0x26, 0x08, 0x5f, 0x95, 0x67, 0xcb, 0xb6, 0x7b, 0x2b, - 0x49, 0x7d, 0xaa, 0xe0, 0xaa, 0xee, 0xce, 0x6d, 0x48, 0x89, 0x94, 0xa7, 0x50, 0x06, 0x33, 0x84, 0x9f, 0x91, 0xc3, - 0x60, 0x10, 0xf6, 0xff, 0x32, 0x44, 0xfd, 0x20, 0xfc, 0x33, 0x3a, 0xd4, 0x9c, 0xe3, 0x0a, 0x75, 0x53, 0x3d, 0xc7, - 0x52, 0xc5, 0x2f, 0xdb, 0x58, 0x79, 0x12, 0xa3, 0x0c, 0x67, 0xf1, 0x8c, 0x46, 0xcf, 0xe0, 0x90, 0x5b, 0xc2, 0x79, - 0x2b, 0x31, 0x50, 0x52, 0xf4, 0xcc, 0xf0, 0x92, 0xd0, 0xef, 0xbf, 0x92, 0xe5, 0x53, 0xdf, 0xef, 0x3f, 0xaf, 0x9e, - 0xfe, 0xe2, 0xf7, 0x7f, 0x91, 0xd1, 0xcf, 0x85, 0xf1, 0x76, 0xd7, 0xe6, 0x78, 0x6c, 0xe7, 0x28, 0xf4, 0xd6, 0x38, - 0xb8, 0x5b, 0xa0, 0x4d, 0x47, 0xc7, 0x04, 0x15, 0x6c, 0x5c, 0x32, 0xa3, 0x3c, 0x94, 0xf1, 0x04, 0x90, 0xea, 0xec, - 0x41, 0xee, 0xc6, 0xf5, 0xab, 0x15, 0x03, 0xa9, 0x58, 0x7a, 0x05, 0x64, 0x4e, 0x7a, 0x2d, 0xb4, 0xac, 0xb5, 0x55, - 0x3a, 0x53, 0x3d, 0x8e, 0x5e, 0xf2, 0xe9, 0x2b, 0xd2, 0xea, 0x5e, 0x1d, 0x4f, 0xba, 0x57, 0x8d, 0x06, 0xca, 0x2d, - 0x69, 0x2d, 0x06, 0x57, 0x43, 0xfc, 0x35, 0x38, 0xf5, 0x5c, 0x5a, 0xc2, 0xb5, 0xe5, 0x75, 0xcc, 0xf2, 0x1a, 0x8d, - 0xac, 0x40, 0x5d, 0xa7, 0xeb, 0x44, 0x77, 0x2d, 0x0a, 0x8d, 0x93, 0x75, 0x52, 0x7b, 0x8a, 0x54, 0x09, 0x24, 0x43, - 0x11, 0x42, 0x6e, 0x24, 0xda, 0x3a, 0x2a, 0x8c, 0x09, 0xdd, 0xd5, 0x99, 0x05, 0xf6, 0xa9, 0xa5, 0x44, 0x00, 0x58, - 0x80, 0xae, 0xa5, 0x27, 0x78, 0x86, 0x17, 0x8d, 0xb6, 0x22, 0xf3, 0x66, 0xbb, 0x5b, 0x1f, 0xeb, 0x49, 0x35, 0x16, - 0x5e, 0x34, 0xc8, 0xac, 0xc4, 0x52, 0x91, 0x35, 0x1a, 0x45, 0x3d, 0xd8, 0x69, 0x4f, 0x6e, 0x2d, 0x00, 0x71, 0xb3, - 0x9e, 0x94, 0x61, 0x25, 0x6c, 0x25, 0x53, 0x59, 0xc8, 0xb2, 0x8c, 0x0a, 0x90, 0xa2, 0x44, 0x62, 0x56, 0x14, 0x95, - 0x64, 0x07, 0x31, 0x8a, 0x29, 0x11, 0xc0, 0x79, 0x94, 0xdd, 0x85, 0x33, 0xcc, 0xf1, 0x54, 0xf1, 0x0d, 0x42, 0xc8, - 0x99, 0x4d, 0x67, 0x91, 0x8a, 0x07, 0xa5, 0x84, 0x39, 0x32, 0x29, 0x27, 0x34, 0x3c, 0xdf, 0x3f, 0xe5, 0x77, 0xda, - 0x64, 0x03, 0x36, 0x8c, 0x54, 0xb3, 0xd4, 0x70, 0xae, 0x98, 0x7c, 0x08, 0x24, 0x2a, 0xa3, 0x23, 0xa1, 0x62, 0x80, - 0xcf, 0x99, 0xa0, 0x4a, 0x07, 0xdf, 0xb7, 0x76, 0x5f, 0x5a, 0x57, 0x20, 0x53, 0xd7, 0x7b, 0x03, 0x88, 0x8c, 0xc1, - 0xb9, 0x93, 0x91, 0x8d, 0x66, 0xe7, 0xfb, 0x27, 0x6f, 0xb7, 0xd9, 0xc0, 0xab, 0x95, 0xb1, 0x7e, 0x95, 0x6e, 0x83, - 0xe3, 0x0a, 0xd2, 0xd4, 0xfc, 0x88, 0x82, 0x54, 0xa9, 0x48, 0x71, 0x20, 0x80, 0x8a, 0xce, 0xf7, 0x4f, 0xde, 0x07, - 0x42, 0xf9, 0x96, 0x10, 0x76, 0x97, 0x1d, 0x70, 0x12, 0x4c, 0x09, 0x45, 0x7a, 0xed, 0x25, 0xeb, 0xe2, 0x8e, 0x00, - 0x8f, 0xa6, 0xaa, 0x12, 0x2c, 0x88, 0x01, 0x1b, 0x92, 0xd4, 0x60, 0x80, 0xa4, 0x08, 0xa7, 0x35, 0xbb, 0x8c, 0xc0, - 0x06, 0xa8, 0xb9, 0xce, 0x60, 0x27, 0x42, 0xad, 0xfa, 0x21, 0x9c, 0xaa, 0x59, 0x65, 0xa1, 0x85, 0xc7, 0xb3, 0x8d, - 0xac, 0xb4, 0xca, 0x1c, 0xfd, 0x16, 0x6c, 0x27, 0xfb, 0xf0, 0x86, 0x58, 0x4b, 0xc2, 0x14, 0x3c, 0xb7, 0xe9, 0x63, - 0xe7, 0xfb, 0x27, 0xaf, 0x4d, 0x06, 0xd9, 0x3c, 0xb6, 0xfc, 0x7e, 0xc3, 0xc4, 0x3c, 0x79, 0x1d, 0x56, 0xb5, 0xaa, - 0xf1, 0xf9, 0xfe, 0xc9, 0x87, 0x6d, 0xcd, 0xa0, 0xbc, 0x58, 0x54, 0x36, 0xbe, 0x82, 0x6f, 0x49, 0xd3, 0x68, 0x69, - 0x84, 0x43, 0xc4, 0x0a, 0xac, 0x04, 0x52, 0x94, 0x17, 0xa5, 0x6b, 0xe4, 0x39, 0xce, 0x88, 0x0a, 0x03, 0xd5, 0x77, - 0xcd, 0xa8, 0x79, 0x8c, 0x67, 0x67, 0x23, 0x3e, 0xa7, 0x3b, 0x62, 0x43, 0x37, 0x28, 0x64, 0x33, 0x48, 0x9d, 0x51, - 0xa0, 0x33, 0xbc, 0xd7, 0x42, 0xdd, 0xba, 0xf8, 0xca, 0x14, 0x91, 0xf2, 0x9a, 0x6c, 0xc1, 0x53, 0xd2, 0xc2, 0x29, - 0x69, 0xe1, 0x98, 0xe4, 0x83, 0x96, 0x16, 0x10, 0xdd, 0xb8, 0x1c, 0x57, 0x8b, 0x19, 0xc8, 0x0a, 0x33, 0xa7, 0x55, - 0x0b, 0xe0, 0xa4, 0x1b, 0x2b, 0xdf, 0xa3, 0x92, 0xe9, 0x89, 0x22, 0x8b, 0xf7, 0x01, 0xc7, 0x5c, 0x0d, 0x7c, 0xc6, - 0x2e, 0x53, 0x48, 0x2c, 0x81, 0x55, 0x61, 0x89, 0xa2, 0xb2, 0x69, 0xdb, 0x34, 0x8d, 0x43, 0xb5, 0x4f, 0x1c, 0xc7, - 0x21, 0x70, 0x6e, 0x1c, 0x9b, 0x3c, 0x9c, 0x7c, 0xb3, 0xcb, 0xe3, 0x83, 0x83, 0x40, 0x77, 0xfa, 0x52, 0x06, 0xdc, - 0xd6, 0x57, 0x91, 0xbb, 0x6f, 0x35, 0xaf, 0x48, 0x90, 0x82, 0xbf, 0xd1, 0x48, 0x87, 0x05, 0x84, 0xa1, 0x83, 0xb8, - 0x8e, 0x41, 0x0b, 0xbc, 0xd2, 0xf5, 0xea, 0xcb, 0x6f, 0x34, 0xca, 0x28, 0x6d, 0x1d, 0x5b, 0x37, 0x38, 0x2b, 0xae, - 0x82, 0x32, 0xf5, 0xa7, 0xb5, 0x91, 0x2f, 0x65, 0x41, 0x40, 0xcc, 0xa5, 0x59, 0x66, 0x17, 0xe3, 0x1c, 0x09, 0x06, - 0xed, 0xbe, 0x34, 0x59, 0x0b, 0x58, 0x65, 0x57, 0x99, 0x46, 0x96, 0x9d, 0x75, 0x50, 0x64, 0x1b, 0x41, 0x54, 0x0a, - 0x1a, 0x35, 0x0a, 0x43, 0xde, 0xef, 0x37, 0x73, 0x2e, 0x71, 0x8e, 0x8c, 0x93, 0x4b, 0x41, 0xa1, 0x90, 0xd5, 0x29, - 0x91, 0xf2, 0x92, 0xcc, 0x77, 0x93, 0xfc, 0x89, 0x43, 0xf2, 0xcf, 0x08, 0x75, 0xc8, 0x5f, 0xbb, 0x38, 0x42, 0x6e, - 0x9c, 0x0b, 0xb9, 0xad, 0x3a, 0x9d, 0x13, 0x70, 0xa2, 0xd5, 0x31, 0x5a, 0x0b, 0x2b, 0xee, 0x60, 0x28, 0xee, 0x09, - 0x51, 0x6e, 0x48, 0x6c, 0x63, 0xc0, 0x41, 0x15, 0x54, 0x83, 0xa9, 0xb7, 0xf9, 0xf4, 0x5c, 0x0e, 0x78, 0xf2, 0xe1, - 0xee, 0x78, 0xe8, 0xe9, 0x7c, 0xf3, 0xe4, 0x3a, 0xb9, 0x9f, 0xb0, 0x6a, 0xe7, 0xe0, 0xd6, 0x33, 0x41, 0x61, 0xfe, - 0x32, 0x8e, 0x5d, 0x67, 0x3e, 0x6b, 0x87, 0xd0, 0xca, 0x3f, 0x80, 0xb6, 0xdd, 0x56, 0x2d, 0xa8, 0x33, 0x2c, 0xf0, - 0x23, 0x9d, 0x81, 0x1a, 0x8b, 0x1d, 0xec, 0xe3, 0x44, 0x35, 0xa0, 0x59, 0xb2, 0xbd, 0xfa, 0x59, 0x61, 0xc8, 0x44, - 0x83, 0x86, 0x96, 0xc0, 0xff, 0x34, 0xc9, 0x03, 0xdd, 0x28, 0xb9, 0x00, 0x08, 0x9a, 0x2b, 0x3c, 0x55, 0x08, 0xf3, - 0xfd, 0xca, 0xfb, 0xfe, 0x72, 0x8f, 0x90, 0x79, 0xe5, 0x7d, 0x7c, 0x57, 0xa5, 0x5e, 0x01, 0x59, 0xa0, 0x08, 0xcc, - 0xc7, 0xb2, 0x40, 0x87, 0x2f, 0xcf, 0x6c, 0x73, 0x65, 0x42, 0x86, 0x95, 0xc6, 0xed, 0x84, 0x36, 0x95, 0x5b, 0x4e, - 0xd7, 0x5b, 0x34, 0xac, 0xd5, 0xee, 0x43, 0xed, 0x7b, 0xa9, 0x60, 0x84, 0xe7, 0xf7, 0xaa, 0xb5, 0x1d, 0xb7, 0xf8, - 0xb8, 0x9e, 0xbf, 0xb2, 0xb6, 0x29, 0x21, 0xcb, 0x72, 0x2a, 0xe4, 0x33, 0x3a, 0xe6, 0x02, 0x62, 0x16, 0x25, 0x4e, - 0x50, 0xb1, 0xef, 0xf8, 0xed, 0xd4, 0xfa, 0x9c, 0x40, 0xc1, 0xda, 0x02, 0xd5, 0xaf, 0x8f, 0x2a, 0x68, 0x7d, 0xbe, - 0xde, 0x6b, 0x7e, 0x70, 0xf0, 0xa1, 0x42, 0x93, 0x81, 0x52, 0x41, 0xe1, 0x30, 0x2d, 0xad, 0xd2, 0x98, 0x48, 0xee, - 0x7e, 0x50, 0x3a, 0x01, 0x2c, 0xc3, 0x70, 0x79, 0xcf, 0x4b, 0x22, 0x8b, 0xc9, 0x3a, 0x8b, 0x37, 0xce, 0x09, 0xe6, - 0x1a, 0x2e, 0xc0, 0xe1, 0xc1, 0xd4, 0xd6, 0xde, 0xa2, 0xbc, 0x4a, 0x86, 0x2d, 0x61, 0x38, 0x05, 0x64, 0x05, 0xca, - 0x0c, 0x71, 0x28, 0x70, 0xab, 0x59, 0x72, 0x0a, 0x7a, 0xe5, 0x14, 0xe7, 0xe1, 0x14, 0xd2, 0x5f, 0x6b, 0x47, 0x16, - 0x21, 0xac, 0x13, 0x73, 0x9c, 0x54, 0x82, 0x93, 0x97, 0xdb, 0x5c, 0xca, 0x96, 0xa8, 0xa9, 0x92, 0x3a, 0xaa, 0x05, - 0x2a, 0x3b, 0x84, 0x57, 0x01, 0x33, 0x8a, 0x9b, 0x8d, 0x9b, 0x01, 0x03, 0x7e, 0x26, 0x03, 0x1d, 0x8c, 0x02, 0x99, - 0xc1, 0xc3, 0x45, 0x50, 0x9b, 0xba, 0xcb, 0x55, 0x37, 0x6c, 0x10, 0x37, 0x75, 0xd1, 0xc4, 0x55, 0x5c, 0xef, 0xb4, - 0xe2, 0xa5, 0x63, 0x9d, 0x41, 0x2d, 0x2d, 0x17, 0xac, 0x12, 0x49, 0x9c, 0xe5, 0x8f, 0x75, 0x52, 0x74, 0xd9, 0x08, - 0x53, 0x05, 0xc6, 0x4b, 0xb5, 0x07, 0xb4, 0x00, 0xfa, 0x5a, 0x9e, 0x48, 0x67, 0x47, 0xad, 0x13, 0x5b, 0xcd, 0xe9, - 0x48, 0xfd, 0x77, 0x90, 0xea, 0xb2, 0x7e, 0xe6, 0x5f, 0x2a, 0x59, 0xc8, 0x70, 0x5e, 0x63, 0xec, 0x99, 0x62, 0xec, - 0x08, 0xf4, 0x34, 0x9b, 0xf8, 0xdd, 0x37, 0x19, 0x2f, 0xcc, 0x48, 0x39, 0x43, 0x62, 0x5f, 0x97, 0xd1, 0x72, 0xe7, - 0xf7, 0xda, 0x6e, 0x44, 0x8c, 0x40, 0x16, 0x10, 0x36, 0x9c, 0x3d, 0x43, 0x38, 0x6f, 0x34, 0xba, 0xf9, 0x31, 0xad, - 0x9c, 0x24, 0x15, 0x8c, 0x0c, 0x02, 0xba, 0x40, 0xf0, 0x35, 0x19, 0x0a, 0x21, 0x7f, 0x9b, 0x99, 0x9d, 0x83, 0xaf, - 0xfd, 0xe4, 0x5d, 0xe0, 0x72, 0x35, 0xb7, 0x6d, 0x19, 0x34, 0x85, 0xf5, 0x04, 0x55, 0xc0, 0xe5, 0xeb, 0xbb, 0x13, - 0x3c, 0x00, 0xee, 0xbd, 0x36, 0x86, 0x54, 0x34, 0xd4, 0x95, 0x9a, 0x25, 0x94, 0xa7, 0xaf, 0x8b, 0xaa, 0xac, 0x44, - 0x77, 0xb2, 0xae, 0xac, 0x8c, 0x59, 0x49, 0xf2, 0xa2, 0xc8, 0x69, 0x15, 0xde, 0x5f, 0x4b, 0xbf, 0x54, 0xc2, 0x65, - 0xd3, 0xdb, 0x7e, 0x3a, 0x27, 0x12, 0x3b, 0x84, 0xfa, 0xf5, 0xae, 0xd8, 0x47, 0x05, 0x26, 0x9c, 0x6b, 0x23, 0x14, - 0x7f, 0xde, 0x26, 0x14, 0x71, 0x66, 0x8e, 0xbc, 0x12, 0x88, 0xed, 0x7b, 0x08, 0x44, 0xe3, 0x66, 0xb7, 0x32, 0x11, - 0xd4, 0x91, 0x9a, 0x4c, 0xac, 0x6f, 0x29, 0xc9, 0x30, 0x33, 0xbb, 0xd1, 0xeb, 0xac, 0x56, 0x6c, 0xd0, 0x02, 0x37, - 0x92, 0xef, 0xc3, 0xcf, 0xb6, 0xfe, 0xe9, 0x70, 0x62, 0xed, 0x06, 0x0e, 0x58, 0x69, 0xb2, 0xa0, 0x10, 0x12, 0x9c, - 0x03, 0x95, 0x94, 0xa5, 0x68, 0xda, 0x50, 0x90, 0x21, 0x70, 0xc2, 0xca, 0x30, 0x13, 0x40, 0xac, 0x64, 0x85, 0x31, - 0x20, 0x83, 0xad, 0xb9, 0x7f, 0xd6, 0xbc, 0xfc, 0xb4, 0x26, 0x5a, 0x93, 0x2b, 0x5a, 0x7d, 0xa8, 0xe5, 0x1b, 0x18, - 0x08, 0x8c, 0x7e, 0xb8, 0xa7, 0x4c, 0xd0, 0x4a, 0x94, 0x23, 0x57, 0x0e, 0xe1, 0x16, 0x38, 0xd1, 0xf6, 0x3e, 0xe8, - 0x08, 0xef, 0x16, 0x69, 0x82, 0xb9, 0x43, 0xd7, 0x2f, 0x89, 0xac, 0xb1, 0x92, 0x29, 0x31, 0x96, 0x12, 0x8e, 0x15, - 0x99, 0x4a, 0x92, 0x0d, 0x5a, 0x43, 0x50, 0x40, 0xbb, 0xe9, 0x71, 0x56, 0x99, 0xc0, 0x69, 0xa3, 0x81, 0x62, 0x3b, - 0xeb, 0x74, 0xc0, 0x1a, 0xe9, 0x10, 0x53, 0x9c, 0x6a, 0xc3, 0xe4, 0xec, 0xe0, 0x20, 0x88, 0xab, 0x79, 0x07, 0xe9, - 0x10, 0x61, 0xbe, 0x5a, 0x05, 0x0a, 0xac, 0x18, 0xad, 0x56, 0xb1, 0x0b, 0x96, 0xaa, 0x86, 0x6e, 0xf3, 0xbe, 0x24, - 0x73, 0x25, 0x00, 0xe7, 0x00, 0x61, 0x83, 0x04, 0xb1, 0x71, 0xef, 0xc5, 0xe0, 0x8e, 0x6a, 0x64, 0x83, 0xb4, 0xd1, - 0x1e, 0x3a, 0x8c, 0x6b, 0x90, 0x0e, 0x49, 0x5c, 0xf0, 0x83, 0x83, 0xbd, 0xdc, 0x88, 0xc8, 0x9f, 0x40, 0x94, 0xfd, - 0xa4, 0x24, 0x8b, 0x1e, 0xd0, 0xdd, 0x8d, 0x75, 0x67, 0x40, 0x49, 0x51, 0x66, 0x5b, 0x6d, 0xbb, 0x5a, 0x16, 0x44, - 0xd9, 0x08, 0x9b, 0x60, 0x70, 0x1f, 0x2c, 0xfb, 0x92, 0xcc, 0x5f, 0xc9, 0x32, 0xc7, 0xfa, 0xe7, 0xad, 0x99, 0xd5, - 0x61, 0x18, 0xc6, 0x62, 0xa2, 0x62, 0x19, 0x36, 0x0c, 0xab, 0x88, 0xff, 0xc8, 0x80, 0xe9, 0x4c, 0x3c, 0x28, 0xe7, - 0x1a, 0x12, 0x0d, 0xbe, 0x55, 0x6d, 0xec, 0x5d, 0x92, 0x9f, 0xb6, 0x7a, 0x19, 0x34, 0x24, 0xcf, 0x7f, 0x2b, 0x24, - 0x0f, 0x0d, 0x24, 0x9a, 0x3c, 0xd6, 0x70, 0xb6, 0x03, 0x17, 0x3f, 0xc9, 0x35, 0x9c, 0xed, 0xc6, 0xad, 0xc5, 0xd4, - 0x2f, 0xbb, 0xe0, 0x73, 0x78, 0x83, 0x06, 0xb4, 0x2a, 0x70, 0xa0, 0x7c, 0xb4, 0xae, 0x7b, 0x69, 0x56, 0x0a, 0xc2, - 0x54, 0x92, 0x80, 0xd5, 0x0f, 0x40, 0xa5, 0x8d, 0x3a, 0x86, 0x2f, 0x8b, 0xe6, 0xc8, 0x71, 0x09, 0xd4, 0x53, 0x57, - 0x80, 0x9c, 0x8c, 0xb7, 0x7d, 0x7e, 0x70, 0x00, 0xb6, 0x01, 0x28, 0x71, 0xe1, 0x28, 0x9e, 0xcb, 0x85, 0x00, 0x55, - 0x2a, 0xb7, 0xbf, 0xa1, 0x18, 0x6e, 0x81, 0xa8, 0x32, 0xf8, 0x01, 0x05, 0xf3, 0x38, 0xcf, 0xd9, 0x95, 0x2e, 0x33, - 0xbf, 0x31, 0x27, 0x96, 0x94, 0x73, 0xad, 0x13, 0x66, 0xa8, 0x9b, 0x19, 0x3a, 0xad, 0xa3, 0xed, 0xc5, 0x15, 0xcd, - 0xe4, 0x2b, 0x96, 0x4b, 0x9a, 0xc1, 0xf2, 0x2b, 0x8a, 0x83, 0x15, 0xe5, 0x08, 0x0e, 0x6c, 0xad, 0x57, 0x9c, 0x24, - 0x77, 0x76, 0x91, 0x75, 0x1d, 0x68, 0x1a, 0x67, 0x49, 0xaa, 0x27, 0x71, 0xf3, 0x19, 0x6d, 0x0e, 0x67, 0xd9, 0xd2, - 0xcd, 0xa7, 0xa9, 0x94, 0x0d, 0xc5, 0xdd, 0x03, 0x46, 0xac, 0x24, 0xb0, 0xd2, 0xf3, 0x4e, 0xad, 0x05, 0x22, 0xde, - 0x3b, 0x36, 0xc1, 0x5d, 0x09, 0x96, 0x0e, 0x47, 0x0d, 0xeb, 0x70, 0x5a, 0xba, 0xf9, 0x72, 0xeb, 0x95, 0xb6, 0x6d, - 0xc2, 0x41, 0xd1, 0xc9, 0xe3, 0xdd, 0x96, 0xd5, 0x6b, 0x2b, 0x39, 0xac, 0xb4, 0x60, 0xf7, 0x65, 0xcc, 0x68, 0x69, - 0xc9, 0x0b, 0xd9, 0xa3, 0xb8, 0x2f, 0xc9, 0x73, 0xb8, 0x33, 0xf4, 0x52, 0xce, 0xd2, 0xb5, 0xab, 0x31, 0xdd, 0xfd, - 0x52, 0xfb, 0xdf, 0x97, 0xc1, 0x4b, 0xfc, 0x1e, 0x02, 0xbb, 0x5f, 0x55, 0xcd, 0x37, 0x03, 0xba, 0x5f, 0x55, 0x08, - 0xfa, 0x2a, 0xda, 0x68, 0xe7, 0x04, 0x72, 0x3b, 0xe1, 0xd3, 0xb0, 0xe5, 0x5b, 0x6d, 0xe9, 0x67, 0x1d, 0x46, 0xd2, - 0x99, 0x96, 0xea, 0x3c, 0xe0, 0x2a, 0x4f, 0x0d, 0xf2, 0xe5, 0xea, 0x16, 0x12, 0x35, 0x19, 0x86, 0x5a, 0x87, 0xdf, - 0xb5, 0x3d, 0x46, 0xc6, 0x64, 0xda, 0xce, 0xf8, 0x3a, 0x16, 0x72, 0x1f, 0x4e, 0x19, 0xdf, 0xb8, 0x87, 0x37, 0x25, - 0xe0, 0x41, 0xbb, 0xdf, 0x14, 0x8e, 0xb1, 0x9d, 0xeb, 0x7b, 0x40, 0xee, 0xf8, 0x84, 0x5b, 0xdd, 0xad, 0x6e, 0x65, - 0x7c, 0x0d, 0xf6, 0x3f, 0xc2, 0x53, 0x7b, 0x39, 0x8e, 0x1a, 0x0e, 0x4c, 0xa3, 0x65, 0x51, 0x3a, 0x05, 0xb8, 0x56, - 0xde, 0x04, 0xc2, 0xbc, 0x50, 0x01, 0xee, 0x1f, 0xf0, 0x37, 0x86, 0x25, 0x8e, 0x4b, 0x8e, 0x73, 0x72, 0x5f, 0x8e, - 0xa8, 0xc1, 0x2f, 0xe3, 0xf7, 0x40, 0xc7, 0x8a, 0x42, 0x0b, 0x4b, 0x45, 0xcf, 0xb9, 0x59, 0xc8, 0xce, 0xb4, 0x54, - 0x4c, 0xcb, 0x94, 0x1a, 0x35, 0xcd, 0x96, 0x3c, 0x4e, 0x6b, 0x65, 0xcb, 0xf2, 0x54, 0xd5, 0xe6, 0x45, 0x3b, 0xb0, - 0x58, 0x85, 0x16, 0x57, 0xab, 0xa0, 0x8e, 0x6a, 0xc2, 0x9c, 0x48, 0x06, 0xc2, 0xcc, 0xc9, 0xa8, 0xa8, 0x69, 0xd6, - 0xba, 0x4f, 0x80, 0xd6, 0x13, 0x8a, 0xac, 0x6e, 0x5e, 0x83, 0xc3, 0x75, 0x21, 0xe8, 0xee, 0xae, 0x4f, 0x01, 0xeb, - 0xd5, 0x95, 0x13, 0x39, 0x18, 0xfa, 0xb9, 0x4c, 0x95, 0xad, 0x72, 0x5a, 0xb7, 0xe0, 0x17, 0xdd, 0x91, 0x2c, 0x6b, - 0x50, 0xb7, 0x59, 0xef, 0x24, 0x1b, 0x3d, 0xe7, 0xbb, 0x92, 0x8d, 0x6a, 0xda, 0xee, 0x5e, 0x0b, 0xdd, 0x9d, 0x96, - 0xaa, 0xe7, 0xda, 0xde, 0xe4, 0x37, 0x4c, 0xd7, 0x06, 0xda, 0xd4, 0x68, 0xb6, 0x5c, 0xe5, 0xac, 0x28, 0xc6, 0xe5, - 0x65, 0x02, 0x95, 0xbb, 0x33, 0xd6, 0xf4, 0x6f, 0xac, 0x46, 0x75, 0x1d, 0x37, 0xf8, 0x81, 0x4c, 0x52, 0x7e, 0x19, - 0xa7, 0xef, 0x61, 0xbe, 0xaa, 0xf2, 0xe5, 0x6d, 0x22, 0x62, 0x49, 0x0d, 0x77, 0xa9, 0x60, 0xf8, 0xc1, 0x81, 0xe1, - 0x07, 0xcd, 0xa7, 0xab, 0xfe, 0x78, 0xf9, 0xaa, 0x1c, 0x20, 0x1a, 0x17, 0x96, 0x65, 0x9c, 0xcb, 0xed, 0x73, 0xac, - 0xb3, 0xb0, 0xf3, 0x92, 0x85, 0x9d, 0xcb, 0x60, 0x7d, 0xa8, 0x20, 0xf8, 0x66, 0xfb, 0x28, 0x9b, 0x9c, 0xed, 0x9b, - 0xea, 0xe0, 0x7f, 0x13, 0xdd, 0xd9, 0xc7, 0xe1, 0x72, 0x47, 0xe1, 0x91, 0x4a, 0x57, 0xd1, 0x20, 0xbf, 0x83, 0xb4, - 0x03, 0x49, 0x7a, 0xce, 0x9d, 0x83, 0x4a, 0x4e, 0xd9, 0x44, 0xa0, 0x60, 0xb4, 0xc8, 0x25, 0x9f, 0x99, 0x31, 0x73, - 0x73, 0xcd, 0x48, 0x55, 0x82, 0x2b, 0x5a, 0x45, 0xdb, 0xa3, 0xfa, 0x45, 0xae, 0xe5, 0x47, 0x96, 0x25, 0x51, 0x8e, - 0x8d, 0x14, 0xc9, 0xa3, 0xac, 0x20, 0x36, 0xd9, 0x78, 0xb3, 0x0e, 0x8f, 0x59, 0xc6, 0xf2, 0x29, 0x15, 0x01, 0x47, - 0xcb, 0x5d, 0x93, 0x71, 0x08, 0xc8, 0xe8, 0xc9, 0xf0, 0xb7, 0xd5, 0x85, 0xbf, 0x10, 0x46, 0x03, 0x3f, 0xd0, 0x8c, - 0xca, 0x29, 0x4f, 0x20, 0x31, 0x25, 0x4c, 0xca, 0x1b, 0x4d, 0x07, 0x07, 0x7b, 0x81, 0xaf, 0xdc, 0x12, 0x70, 0xf5, - 0xdb, 0xad, 0x41, 0xfd, 0x25, 0x5c, 0xcf, 0xa9, 0xa6, 0xa6, 0x68, 0x49, 0xd7, 0x6f, 0xb2, 0xc8, 0xf0, 0x23, 0xbd, - 0xc5, 0x02, 0x15, 0x45, 0xa4, 0xa1, 0xf6, 0xc7, 0x8c, 0xa6, 0x89, 0x8f, 0x3f, 0xd2, 0xdb, 0xa8, 0xbc, 0x2d, 0xae, - 0x2e, 0x37, 0xab, 0x0d, 0xf4, 0xf9, 0x75, 0xe6, 0xe3, 0x6a, 0x92, 0x68, 0x59, 0x60, 0x2e, 0xd8, 0x04, 0x88, 0xf3, - 0x6f, 0xf4, 0x36, 0xd2, 0xe3, 0x31, 0xe7, 0xb2, 0x1e, 0x5a, 0x5a, 0xd4, 0x87, 0x4e, 0xb1, 0xbb, 0x0d, 0xc6, 0xa0, - 0x18, 0xa8, 0xbe, 0x43, 0x52, 0x6b, 0x57, 0x99, 0x87, 0x08, 0x15, 0xf7, 0x5d, 0x0a, 0xfe, 0xc2, 0x15, 0x6d, 0xb2, - 0x96, 0xfa, 0xba, 0xd6, 0x89, 0x42, 0x87, 0x2a, 0xd7, 0xe3, 0x3c, 0x10, 0xf6, 0xd4, 0x99, 0x3b, 0x08, 0x8e, 0x23, - 0xec, 0x0b, 0x69, 0x06, 0x8d, 0xbe, 0xd5, 0x29, 0x21, 0x55, 0x24, 0xe9, 0x75, 0xd5, 0xcf, 0x3b, 0x0f, 0x00, 0xef, - 0x90, 0xd2, 0x12, 0xab, 0xeb, 0x98, 0x85, 0x4d, 0x17, 0xfd, 0x4e, 0x92, 0x60, 0x69, 0x97, 0x10, 0x09, 0x17, 0x8b, - 0xb2, 0x00, 0x2a, 0x34, 0xf4, 0xa5, 0x33, 0x00, 0xd9, 0x38, 0x60, 0x1b, 0x52, 0x33, 0x53, 0x52, 0x33, 0x74, 0x30, - 0xbe, 0x43, 0x4a, 0x52, 0x85, 0x0c, 0xa5, 0x44, 0x2a, 0xa1, 0x67, 0x36, 0xd7, 0x90, 0x90, 0xbb, 0xa1, 0xe5, 0xf5, - 0x39, 0xbd, 0xe7, 0x59, 0x0d, 0xac, 0x40, 0x8d, 0x83, 0x8a, 0x08, 0x96, 0x44, 0x75, 0x83, 0xc2, 0xba, 0x73, 0x84, - 0xcd, 0x6f, 0x0d, 0x78, 0x68, 0x97, 0x45, 0x2c, 0x4a, 0x82, 0x29, 0x5a, 0x8a, 0x60, 0x8a, 0x33, 0xc8, 0x47, 0xe4, - 0x45, 0x09, 0x3f, 0x75, 0x77, 0xa3, 0x96, 0xad, 0xbc, 0xfd, 0x8a, 0x1f, 0x28, 0xf3, 0x12, 0x72, 0x34, 0xb1, 0xb0, - 0x3c, 0x45, 0x04, 0xea, 0xae, 0x9d, 0xb3, 0x6d, 0x5f, 0x99, 0x14, 0x1d, 0x03, 0xd8, 0x77, 0x32, 0x58, 0x3a, 0xab, - 0x70, 0xef, 0x72, 0x9b, 0x2b, 0x7f, 0x26, 0xd8, 0x57, 0x25, 0x91, 0x06, 0x39, 0x59, 0x93, 0x38, 0x77, 0xe7, 0x5a, - 0xfe, 0xbc, 0xa0, 0xe2, 0xf6, 0x8c, 0x42, 0xae, 0x33, 0x87, 0xbb, 0xbe, 0xd5, 0x36, 0x54, 0x79, 0xea, 0xfd, 0x4c, - 0x29, 0x2b, 0x45, 0xfd, 0x12, 0xe0, 0xfa, 0x15, 0xc1, 0x42, 0x45, 0x1b, 0x1d, 0x47, 0x8c, 0x3e, 0x2d, 0x74, 0xe7, - 0xe5, 0x49, 0xda, 0x65, 0xe0, 0x5f, 0xab, 0x30, 0x6d, 0x82, 0x05, 0x98, 0xbb, 0x17, 0x52, 0x07, 0xf9, 0x70, 0xdd, - 0x2b, 0x03, 0x45, 0x10, 0xbe, 0xcb, 0x76, 0x2f, 0x75, 0x5b, 0xd6, 0xec, 0xee, 0xa5, 0xd6, 0x82, 0x7e, 0x2a, 0xe5, - 0x07, 0x9b, 0x79, 0xca, 0xcb, 0xcb, 0xac, 0x28, 0x50, 0x01, 0xe0, 0x7d, 0xdf, 0x0d, 0x82, 0xef, 0x4d, 0xd2, 0x60, - 0x08, 0xb1, 0xd8, 0xb3, 0x94, 0x5b, 0x26, 0x5e, 0xcd, 0xff, 0xfd, 0xc6, 0xfc, 0xdf, 0x3b, 0x57, 0x4e, 0xc1, 0x34, - 0x9a, 0x64, 0x34, 0xb1, 0xac, 0x13, 0x69, 0x02, 0x54, 0x7a, 0x5b, 0x2e, 0xc9, 0xc7, 0x8b, 0x08, 0x34, 0xae, 0xe5, - 0x98, 0x67, 0xb2, 0x39, 0x8e, 0x67, 0x2c, 0xbd, 0x8d, 0x16, 0xac, 0x39, 0xe3, 0x19, 0xcf, 0xe7, 0xf1, 0x88, 0xe2, - 0xfc, 0x36, 0x97, 0x74, 0xd6, 0x5c, 0x30, 0xfc, 0x92, 0xa6, 0x57, 0x54, 0xb2, 0x51, 0x8c, 0xfd, 0x13, 0xc1, 0xe2, - 0xd4, 0x7b, 0x13, 0x0b, 0xc1, 0xaf, 0x7d, 0xfc, 0x8e, 0x5f, 0x72, 0xc9, 0xf1, 0xdb, 0x9b, 0xdb, 0x09, 0xcd, 0xf0, - 0x87, 0xcb, 0x45, 0x26, 0x17, 0x38, 0x8f, 0xb3, 0xbc, 0x99, 0x53, 0xc1, 0xc6, 0xdd, 0x11, 0x4f, 0xb9, 0x68, 0x42, - 0xca, 0xf6, 0x8c, 0x46, 0x29, 0x9b, 0x4c, 0xa5, 0x97, 0xc4, 0xe2, 0x63, 0xb7, 0xd9, 0x9c, 0x0b, 0x36, 0x8b, 0xc5, - 0x6d, 0x53, 0xb5, 0x88, 0x3e, 0x6b, 0x1d, 0xc5, 0x9f, 0x8f, 0x1f, 0x76, 0xa5, 0x88, 0xb3, 0x9c, 0xc1, 0x36, 0x45, - 0x71, 0x9a, 0x7a, 0x47, 0x8f, 0x5a, 0xb3, 0x7c, 0x4f, 0x07, 0xf2, 0xe2, 0x4c, 0x16, 0x17, 0xf8, 0x23, 0xc0, 0x1d, - 0x5e, 0xca, 0x0c, 0x5f, 0x2e, 0xa4, 0xe4, 0xd9, 0x72, 0xb4, 0x10, 0x39, 0x17, 0xd1, 0x9c, 0xb3, 0x4c, 0x52, 0xd1, - 0xbd, 0xe4, 0x22, 0xa1, 0xa2, 0x29, 0xe2, 0x84, 0x2d, 0xf2, 0xe8, 0xe1, 0xfc, 0xa6, 0x0b, 0x9a, 0xc5, 0x44, 0xf0, - 0x45, 0x96, 0x98, 0xb9, 0x58, 0x36, 0xa5, 0x82, 0x49, 0xb7, 0x42, 0xbd, 0xc2, 0x24, 0x4a, 0x59, 0x46, 0x63, 0xd1, - 0x9c, 0x40, 0x67, 0x30, 0x8b, 0x5a, 0x09, 0x9d, 0x60, 0x31, 0xb9, 0x8c, 0x83, 0x76, 0xe7, 0x09, 0xb6, 0x7f, 0xc3, - 0x47, 0xc8, 0x6b, 0x6d, 0x2f, 0x6e, 0xb7, 0x5a, 0x7f, 0x42, 0xdd, 0xb5, 0x59, 0x14, 0x40, 0x51, 0x7b, 0x7e, 0xe3, - 0xe5, 0x1c, 0x72, 0xda, 0xb6, 0xf5, 0xec, 0xce, 0xe3, 0x04, 0x12, 0x82, 0xa3, 0xce, 0xfc, 0xa6, 0x80, 0xd5, 0x45, - 0x3a, 0xc9, 0xd4, 0x2c, 0xd2, 0x3c, 0x2d, 0x7f, 0x2b, 0xc4, 0x4f, 0xb7, 0x43, 0xdc, 0xb1, 0x10, 0x57, 0x58, 0x6f, - 0x26, 0x0b, 0xa1, 0x62, 0xab, 0x51, 0x3b, 0xd7, 0x80, 0x4c, 0xf9, 0x15, 0x15, 0x16, 0x0e, 0xf5, 0xf0, 0x9b, 0xc1, - 0xe8, 0x6c, 0x07, 0xe3, 0xe9, 0xa7, 0xc0, 0x10, 0x59, 0xb2, 0xac, 0xef, 0x6b, 0x5b, 0xd0, 0x59, 0x77, 0x4a, 0x81, - 0x9e, 0xa2, 0x0e, 0xfc, 0xbe, 0x66, 0x89, 0x9c, 0xea, 0x9f, 0x8a, 0x9c, 0xaf, 0x75, 0xdd, 0xa3, 0x56, 0x4b, 0x3f, - 0xe7, 0xec, 0x17, 0x1a, 0xb5, 0x43, 0x68, 0x50, 0x5c, 0xe0, 0xbf, 0x95, 0x97, 0x79, 0xeb, 0xdc, 0x13, 0xff, 0xe0, - 0xde, 0xf2, 0x75, 0x92, 0x14, 0xab, 0x1b, 0xd1, 0x58, 0x58, 0x59, 0xa9, 0x85, 0x0f, 0xb8, 0xed, 0xd4, 0x79, 0x22, - 0xac, 0x57, 0xde, 0xe2, 0x64, 0xfd, 0x1f, 0x74, 0xde, 0x45, 0x04, 0x91, 0x0e, 0x27, 0xd9, 0x90, 0x77, 0xb3, 0x1e, - 0x69, 0x75, 0xb3, 0x66, 0x13, 0x05, 0x9c, 0x88, 0x41, 0x66, 0xd2, 0xf3, 0x02, 0xd6, 0xe7, 0xca, 0xd8, 0xce, 0x51, - 0xc4, 0xe1, 0xaa, 0xe9, 0x6a, 0x55, 0x85, 0x01, 0x98, 0xba, 0xae, 0xf1, 0x37, 0x69, 0x1a, 0xe0, 0xdc, 0xe1, 0xe4, - 0x99, 0x7d, 0xb1, 0x8b, 0xb0, 0xbc, 0x22, 0xe5, 0x23, 0x85, 0xb9, 0x70, 0x1e, 0xcb, 0x29, 0x78, 0x29, 0x4a, 0xf1, - 0x53, 0x25, 0x31, 0xf9, 0x87, 0x3e, 0xea, 0x8b, 0x32, 0xc3, 0x0d, 0x32, 0xf9, 0x44, 0x01, 0xa3, 0x7c, 0x23, 0x09, - 0x8c, 0x88, 0x7f, 0x21, 0xda, 0xa6, 0xb3, 0x16, 0xdd, 0xf8, 0xbe, 0x16, 0x1d, 0xcd, 0x24, 0x53, 0xb9, 0xdb, 0x36, - 0xe2, 0x30, 0x8d, 0xf3, 0xf3, 0x91, 0xbe, 0x2b, 0x99, 0x57, 0x37, 0x03, 0x62, 0x05, 0xbd, 0x36, 0xd2, 0xa8, 0x50, - 0xf6, 0xe8, 0xf7, 0x72, 0xa7, 0x7d, 0x22, 0xee, 0xb2, 0x4f, 0xca, 0x85, 0xe7, 0x7c, 0x21, 0x46, 0x10, 0x8e, 0x34, - 0x52, 0x6f, 0xd3, 0x71, 0xe3, 0x2b, 0x15, 0xc3, 0xc7, 0xd2, 0xc9, 0x04, 0x95, 0x98, 0xb9, 0x2f, 0x95, 0xa0, 0x2a, - 0xe4, 0xa5, 0xef, 0x6b, 0x18, 0x11, 0x67, 0x97, 0x04, 0x32, 0x3b, 0x51, 0x49, 0x8d, 0x41, 0x46, 0x7a, 0x59, 0xb8, - 0xc8, 0xd8, 0xcf, 0x0b, 0x7a, 0xce, 0x40, 0xd7, 0x64, 0x21, 0x4b, 0x54, 0xac, 0x09, 0x64, 0x5f, 0xb3, 0x0d, 0xc1, - 0x0b, 0x96, 0xe8, 0x8d, 0xc9, 0x54, 0xa5, 0xc9, 0x6d, 0xf2, 0x9b, 0x3e, 0xf8, 0x8b, 0x41, 0x3b, 0x60, 0x38, 0xe1, - 0xb3, 0x98, 0x65, 0x91, 0x72, 0xf9, 0x96, 0x83, 0x45, 0xd0, 0x1a, 0xb3, 0x24, 0xca, 0xcc, 0xf6, 0xb4, 0x51, 0xf8, - 0x13, 0x67, 0x99, 0xea, 0x5a, 0x74, 0xb9, 0x42, 0xa8, 0x46, 0x1f, 0xb1, 0x08, 0x3e, 0xd1, 0x72, 0x8d, 0x23, 0xec, - 0x56, 0x97, 0xd7, 0xce, 0x6b, 0x3b, 0xd0, 0x5a, 0xdb, 0x28, 0x6d, 0x04, 0xf0, 0xf5, 0xd2, 0x9c, 0x0b, 0x19, 0x04, - 0x53, 0x9c, 0x22, 0xd2, 0x9b, 0x2a, 0x67, 0xd7, 0x71, 0xaa, 0xfe, 0xeb, 0x37, 0xdb, 0x51, 0xbb, 0x34, 0xdf, 0x6b, - 0xb7, 0x81, 0x75, 0x72, 0x94, 0xb9, 0x51, 0xaa, 0x96, 0x51, 0xfe, 0xd6, 0x4b, 0xad, 0x9e, 0xcb, 0xe5, 0x62, 0x73, - 0xdc, 0xb4, 0xa8, 0x0a, 0x6a, 0x40, 0xa8, 0x60, 0xd1, 0x8e, 0xa9, 0x50, 0x51, 0xad, 0xbb, 0x54, 0x25, 0x2f, 0xb4, - 0x88, 0x3e, 0xdf, 0x5f, 0x0a, 0x33, 0x63, 0x71, 0xc1, 0xac, 0x93, 0xa9, 0x4e, 0x72, 0x85, 0xc1, 0x88, 0xa3, 0x87, - 0x6e, 0x6b, 0xa6, 0x61, 0xb9, 0x25, 0x62, 0x2b, 0xdd, 0x86, 0xfa, 0x91, 0x0a, 0x52, 0x85, 0xbb, 0x36, 0x06, 0x80, - 0x5c, 0xbd, 0x6d, 0x80, 0x81, 0xd9, 0x9a, 0x4b, 0xbb, 0x04, 0xd0, 0xc6, 0xc6, 0x14, 0x2e, 0xd2, 0x5c, 0xec, 0x2f, - 0xbf, 0x91, 0xc5, 0xa1, 0xd3, 0x54, 0xfd, 0x66, 0x09, 0xfc, 0x0f, 0x12, 0x70, 0xa9, 0x95, 0xd2, 0xc8, 0xff, 0xfa, - 0xed, 0xd9, 0x7b, 0x1f, 0x5f, 0xf2, 0xe4, 0x36, 0xf2, 0xa5, 0x58, 0x50, 0xbf, 0x40, 0xa1, 0x9c, 0xd2, 0xac, 0x7c, - 0x19, 0x0f, 0x4f, 0x69, 0x98, 0xf2, 0x89, 0xbe, 0x94, 0xb9, 0x6e, 0x24, 0x8f, 0x2e, 0x8e, 0xd5, 0x4b, 0xa6, 0x7a, - 0xc7, 0x52, 0xbf, 0xde, 0x4b, 0x0a, 0xf8, 0xd9, 0x83, 0x10, 0xca, 0xf1, 0xa1, 0x9c, 0xaa, 0x87, 0x33, 0x38, 0x30, - 0xea, 0x69, 0x7f, 0xb9, 0x41, 0x4c, 0x7d, 0x18, 0x62, 0xda, 0xd3, 0x4b, 0xc8, 0x55, 0xab, 0x8b, 0x68, 0x74, 0x71, - 0x51, 0x1c, 0x1f, 0xc2, 0x58, 0x87, 0x76, 0x5c, 0x80, 0xd0, 0xf6, 0x2f, 0x09, 0x0c, 0x5e, 0x36, 0x24, 0x48, 0x0f, - 0x86, 0x80, 0x79, 0x93, 0x1e, 0x2c, 0x12, 0x08, 0x0c, 0x7a, 0x27, 0x65, 0x89, 0x3a, 0xb1, 0xba, 0x68, 0x17, 0x04, - 0xba, 0x61, 0x45, 0xf7, 0xda, 0x9b, 0x5a, 0xed, 0xaf, 0x05, 0x29, 0x71, 0xa1, 0xbb, 0x40, 0xf0, 0xbf, 0x82, 0xec, - 0xf8, 0x50, 0xe3, 0xe1, 0xc2, 0x7d, 0xb5, 0x89, 0x7e, 0xed, 0x40, 0x89, 0xad, 0x41, 0x2e, 0xf1, 0x47, 0x89, 0x3f, - 0x5e, 0xa8, 0xa6, 0x56, 0x18, 0x81, 0x96, 0x04, 0x42, 0xbb, 0x65, 0xb5, 0x8e, 0x11, 0x4f, 0xd3, 0x78, 0x9e, 0xd3, - 0xc8, 0xfe, 0x30, 0x72, 0x09, 0xc4, 0xdb, 0xa6, 0x22, 0x60, 0xd2, 0x6b, 0x4e, 0x41, 0x5d, 0xd8, 0xd4, 0x52, 0xae, - 0x62, 0x11, 0x34, 0x9b, 0xa3, 0xe6, 0xe5, 0x04, 0x15, 0x72, 0xba, 0x74, 0xa5, 0xda, 0xe3, 0x56, 0xab, 0x0b, 0xb9, - 0x90, 0xcd, 0x38, 0x65, 0x93, 0x2c, 0x4a, 0xe9, 0x58, 0x16, 0x12, 0x6e, 0xa9, 0x2d, 0xad, 0x1a, 0x11, 0x76, 0x1e, - 0x09, 0x3a, 0xf3, 0x42, 0xf8, 0xf7, 0xee, 0x89, 0x0b, 0x99, 0x44, 0x99, 0x9c, 0x36, 0x55, 0xd6, 0x2d, 0xdc, 0x19, - 0x90, 0xd3, 0xda, 0xf3, 0xd2, 0x99, 0x68, 0x44, 0x41, 0xc5, 0x2a, 0xa4, 0xf0, 0xe4, 0x14, 0x4b, 0xe1, 0xb6, 0xcb, - 0xd0, 0x72, 0x63, 0x05, 0x9b, 0x92, 0xfe, 0x08, 0x15, 0xb9, 0x52, 0x8c, 0x37, 0x1b, 0x5b, 0x75, 0xa9, 0xfe, 0xb4, - 0x81, 0x3e, 0x47, 0xb1, 0x2b, 0xb4, 0x63, 0x79, 0xa9, 0x7b, 0xdc, 0x07, 0x99, 0x35, 0x95, 0x13, 0xbb, 0x3d, 0x50, - 0xc1, 0xb2, 0xf9, 0x42, 0x0e, 0x94, 0x53, 0x5b, 0xc0, 0x05, 0x89, 0x21, 0x76, 0x4a, 0x00, 0x07, 0xc3, 0xa5, 0x06, - 0x66, 0x14, 0xa7, 0xa3, 0x00, 0x20, 0xf2, 0x9a, 0xde, 0x53, 0x41, 0x67, 0xa8, 0x3b, 0x63, 0x59, 0x53, 0xd7, 0x3d, - 0x72, 0xd4, 0x92, 0xf0, 0x09, 0x3c, 0x15, 0xa1, 0x1a, 0x0d, 0xab, 0xdc, 0xd5, 0x2d, 0xb8, 0xbc, 0x18, 0x16, 0x45, - 0x57, 0xc8, 0x60, 0xf0, 0x3a, 0x40, 0x43, 0xfc, 0x8b, 0xf3, 0x72, 0x16, 0xdf, 0x1e, 0x15, 0x1f, 0x77, 0xd0, 0x8e, - 0x26, 0xee, 0x59, 0x50, 0xcd, 0x7e, 0x21, 0xd0, 0xf0, 0x5d, 0xe0, 0xd3, 0x7c, 0xde, 0xd4, 0xbc, 0xab, 0xa9, 0x48, - 0xd6, 0x87, 0xae, 0xc8, 0x78, 0x6a, 0xbf, 0x97, 0x4b, 0xc5, 0x96, 0xcc, 0x25, 0x0d, 0xed, 0x4c, 0x18, 0x96, 0x97, - 0x7a, 0xcc, 0xb3, 0x7b, 0x8d, 0x07, 0xd5, 0xf8, 0xc9, 0xc5, 0x49, 0x9d, 0xc7, 0x01, 0x5f, 0x2a, 0x5f, 0x60, 0x17, - 0xa7, 0x29, 0x4c, 0x78, 0x61, 0xd5, 0x17, 0xf7, 0xa5, 0x1f, 0x03, 0x39, 0x0c, 0x50, 0x61, 0xce, 0xe9, 0x33, 0xa5, - 0x52, 0x3a, 0x6f, 0xcd, 0xdb, 0x93, 0x36, 0x58, 0xa4, 0xa5, 0x2f, 0x83, 0x70, 0x77, 0x2d, 0x2f, 0xba, 0x5b, 0xf1, - 0x2e, 0xad, 0x90, 0x7a, 0x6a, 0x41, 0xc4, 0x17, 0x59, 0xe2, 0x7b, 0x7f, 0x19, 0xa5, 0x6c, 0xf4, 0x91, 0xf8, 0xfb, - 0xcb, 0x00, 0x6d, 0x5e, 0x7b, 0x54, 0x5c, 0xc1, 0x32, 0x6c, 0x54, 0x77, 0xa4, 0x67, 0xa1, 0xc3, 0x8b, 0xf5, 0x5b, - 0x71, 0xfc, 0xde, 0xfe, 0x12, 0x18, 0x8f, 0x9e, 0xa7, 0x77, 0x51, 0x9c, 0x57, 0xef, 0xba, 0xaa, 0xa0, 0x00, 0x34, - 0xeb, 0x72, 0x4f, 0x11, 0x15, 0xf1, 0x3f, 0x49, 0x69, 0xbe, 0xa7, 0x99, 0x1a, 0xc0, 0x29, 0x0d, 0x7f, 0xf3, 0xbd, - 0xbf, 0x94, 0x65, 0xb4, 0xf4, 0x68, 0xa8, 0x94, 0x0c, 0xe2, 0xc3, 0x5c, 0x60, 0xc6, 0x86, 0x09, 0x95, 0x31, 0x4b, - 0x75, 0x97, 0xae, 0x35, 0xc0, 0xd7, 0x56, 0xb4, 0x5a, 0xe5, 0xf5, 0xb5, 0xb0, 0x3a, 0x06, 0xd5, 0xca, 0x8e, 0x0f, - 0x2b, 0xb8, 0xd5, 0xca, 0xd4, 0x99, 0x74, 0x43, 0x83, 0xd5, 0x0a, 0x75, 0x9d, 0xf7, 0x97, 0x91, 0xba, 0x36, 0x04, - 0x00, 0x72, 0x03, 0x20, 0x04, 0xad, 0xf5, 0xb5, 0x98, 0x20, 0x25, 0x3c, 0x94, 0xb1, 0x98, 0x50, 0xb9, 0x86, 0xd8, - 0x54, 0xe7, 0xa8, 0x76, 0x6d, 0x80, 0x7a, 0x03, 0xda, 0xb8, 0x0e, 0xed, 0x05, 0x20, 0xbd, 0xbf, 0xbf, 0x64, 0x05, - 0xd9, 0x5f, 0xd2, 0x6c, 0xc4, 0x13, 0xfa, 0xe1, 0xdd, 0x97, 0x70, 0xc9, 0x91, 0x67, 0x60, 0x58, 0x4c, 0x11, 0x08, - 0x4e, 0xb5, 0x39, 0x5a, 0x84, 0x70, 0x25, 0x42, 0x34, 0x27, 0xf0, 0xd4, 0x5c, 0x0a, 0xc4, 0xc2, 0xf7, 0xfa, 0x1a, - 0x72, 0x9a, 0x68, 0x98, 0x49, 0xa6, 0x7a, 0xf1, 0xe2, 0xf8, 0x50, 0xb7, 0xd6, 0x22, 0x40, 0x37, 0x02, 0x24, 0xa8, - 0x73, 0x5a, 0xe1, 0x00, 0xf2, 0x9a, 0x5d, 0x3c, 0x24, 0xec, 0xaa, 0x24, 0x36, 0x75, 0x81, 0xaa, 0x77, 0x9c, 0xc6, - 0x97, 0x34, 0xed, 0xed, 0x2f, 0xb3, 0xd5, 0xaa, 0x55, 0x1c, 0x1f, 0xea, 0x47, 0xef, 0x58, 0xf1, 0x0d, 0xfd, 0xc2, - 0x4b, 0xb5, 0xc5, 0x70, 0x2b, 0x11, 0xb2, 0x3d, 0x6d, 0x9a, 0x53, 0x64, 0x06, 0x28, 0x7c, 0x4f, 0x25, 0x58, 0xa8, - 0x46, 0xa5, 0x42, 0x54, 0xf8, 0x1e, 0x4b, 0x36, 0xcb, 0x72, 0x49, 0xe7, 0x50, 0x3a, 0x5d, 0xad, 0xda, 0x85, 0xef, - 0xcd, 0x58, 0x06, 0x4f, 0xd9, 0x6a, 0xa5, 0x2e, 0xfc, 0xcd, 0x58, 0x16, 0xb4, 0x80, 0x6c, 0x7d, 0x6f, 0x16, 0xdf, - 0xa8, 0x05, 0xdb, 0x9a, 0xf8, 0x26, 0x68, 0x9b, 0xaa, 0xb0, 0xc4, 0x4f, 0x0e, 0x14, 0x57, 0xed, 0x68, 0x6a, 0x76, - 0x34, 0xc1, 0x0b, 0x7d, 0x95, 0x89, 0x04, 0x09, 0x49, 0xb7, 0xef, 0x68, 0x62, 0x77, 0x74, 0xb1, 0x63, 0x47, 0x17, - 0x77, 0xec, 0x68, 0x6c, 0x76, 0xcf, 0x2b, 0x71, 0xc7, 0x57, 0xab, 0x76, 0xab, 0xc2, 0xde, 0xf1, 0x61, 0xc2, 0xae, - 0x60, 0x37, 0x40, 0xcd, 0x93, 0x6c, 0x46, 0xb7, 0x13, 0x65, 0x1d, 0xc5, 0xf4, 0x57, 0x61, 0xb2, 0x44, 0x42, 0x56, - 0x47, 0x82, 0x4b, 0xd6, 0x65, 0xc8, 0xed, 0x8f, 0x24, 0x6c, 0x06, 0x68, 0xc8, 0x01, 0x0d, 0x53, 0x83, 0x86, 0x8b, - 0xe2, 0x1c, 0x24, 0x82, 0x5a, 0xcd, 0xbd, 0x28, 0x0f, 0x5a, 0xfb, 0xbd, 0xdd, 0x14, 0x06, 0xc1, 0xf0, 0x6b, 0x2e, - 0x12, 0x3f, 0xd2, 0x4d, 0x7f, 0x15, 0x62, 0x66, 0x2c, 0x33, 0xa9, 0x55, 0x3b, 0x29, 0xab, 0xaa, 0x77, 0xe9, 0xab, - 0xf3, 0xe8, 0x91, 0x6e, 0x31, 0x8f, 0xa5, 0xa4, 0x22, 0x33, 0x74, 0xea, 0xfb, 0x2e, 0xb6, 0xff, 0x7f, 0x91, 0xdc, - 0x16, 0x26, 0x12, 0x5b, 0x26, 0x62, 0xa9, 0xcd, 0x68, 0xe7, 0x86, 0xc1, 0x6b, 0x59, 0xb4, 0x57, 0xa9, 0xab, 0xb7, - 0xc8, 0xb5, 0x10, 0x74, 0x11, 0x18, 0x2c, 0x8b, 0x19, 0x4d, 0xce, 0x15, 0x37, 0xee, 0x8f, 0x2e, 0x8c, 0x76, 0xba, - 0x26, 0xdb, 0xaa, 0x0e, 0xd8, 0xff, 0x71, 0xd1, 0x79, 0xf2, 0xf0, 0xd4, 0xc7, 0x9a, 0xa1, 0xf3, 0xf1, 0xd8, 0x47, - 0x85, 0x77, 0xbf, 0x6e, 0xed, 0x87, 0x3f, 0x2e, 0xbe, 0x78, 0xd1, 0xfa, 0xa2, 0xec, 0x9c, 0xf9, 0xa8, 0xb8, 0x30, - 0xc1, 0x7c, 0x2b, 0x97, 0x1c, 0x78, 0xed, 0x8a, 0xc6, 0x71, 0xb6, 0x7b, 0x39, 0x03, 0x77, 0x39, 0xf9, 0x9c, 0xd2, - 0x04, 0xfb, 0x9e, 0x8f, 0x37, 0x4a, 0xcf, 0x53, 0x7a, 0x45, 0xed, 0x6b, 0x06, 0xb7, 0x4c, 0xb6, 0xa5, 0xc7, 0x88, - 0x2f, 0x32, 0x69, 0xb2, 0x1a, 0x0c, 0x5f, 0x75, 0x96, 0x74, 0xa1, 0xd6, 0xe0, 0x1a, 0x04, 0xb7, 0x5a, 0xa8, 0xd5, - 0x45, 0x55, 0x71, 0x81, 0x7d, 0x07, 0x80, 0x9d, 0x90, 0xf5, 0x77, 0x94, 0x47, 0x2d, 0xdc, 0xda, 0x05, 0x1b, 0x6e, - 0xa3, 0xc8, 0xf7, 0x87, 0x16, 0x4f, 0xca, 0x31, 0x59, 0x7b, 0x3b, 0xc4, 0x4e, 0x7c, 0x7d, 0x12, 0x03, 0x97, 0x02, - 0x06, 0xcb, 0x68, 0x9e, 0xef, 0x44, 0x40, 0xb9, 0x89, 0xd8, 0xaf, 0x5a, 0xfb, 0x3b, 0x46, 0xc1, 0x2d, 0x0c, 0x07, - 0x4c, 0x01, 0x5c, 0x86, 0x47, 0x4d, 0x2b, 0x3a, 0x1e, 0xd3, 0x51, 0xe9, 0xd7, 0x85, 0x40, 0xd7, 0x98, 0xa5, 0x12, - 0xe2, 0x3d, 0x2a, 0x10, 0xe3, 0xbf, 0xe1, 0x19, 0xf5, 0x91, 0x4d, 0xdd, 0x34, 0xf0, 0x1b, 0x61, 0xbf, 0x1d, 0x1e, - 0x3d, 0x62, 0x1d, 0x16, 0x33, 0xcb, 0x6a, 0x65, 0x7d, 0x3a, 0xb5, 0xf2, 0x3a, 0x22, 0xb9, 0x72, 0xda, 0xec, 0x3a, - 0x40, 0xf7, 0x3b, 0x26, 0xcb, 0xf6, 0x17, 0x8f, 0xda, 0xad, 0xc2, 0xc7, 0x3e, 0x0c, 0x77, 0xdf, 0x53, 0xa2, 0x7a, - 0x1d, 0x41, 0xaf, 0x45, 0xf6, 0x6b, 0xfa, 0x75, 0xda, 0x9f, 0xb7, 0x7d, 0xac, 0xdf, 0x1a, 0x80, 0x8a, 0x92, 0x19, - 0x8c, 0xc0, 0xd3, 0xf9, 0xbb, 0x97, 0x52, 0x1f, 0xfc, 0x7e, 0xf0, 0x3c, 0x6e, 0xb7, 0x7c, 0xec, 0xe7, 0x92, 0xcf, - 0x7f, 0xc5, 0x12, 0x8e, 0x7c, 0xec, 0x8f, 0x52, 0x9e, 0x53, 0x77, 0x0d, 0x5a, 0x77, 0xfd, 0xfd, 0x8b, 0xd0, 0x10, - 0xcd, 0x05, 0xcd, 0x73, 0xcf, 0x1d, 0xdf, 0x90, 0xd2, 0x27, 0x18, 0xe6, 0x56, 0x8a, 0xcb, 0xa9, 0x54, 0x78, 0xd1, - 0x17, 0xfa, 0x5d, 0xaa, 0xd2, 0x65, 0x1b, 0xc4, 0xa6, 0x44, 0x40, 0xc9, 0xd8, 0xb4, 0x2a, 0xf5, 0xc9, 0x99, 0xb7, - 0x1c, 0x3d, 0x3d, 0xb1, 0x0e, 0x00, 0x6f, 0x4e, 0x50, 0x2b, 0x99, 0xb1, 0xec, 0x7c, 0x4b, 0x69, 0x7c, 0xb3, 0xa5, - 0x14, 0xf4, 0xb3, 0x12, 0x3a, 0xf3, 0xae, 0x99, 0x4f, 0x63, 0xbd, 0xd2, 0x72, 0x5c, 0x10, 0x13, 0xe5, 0xa4, 0xfc, - 0x04, 0xa4, 0xce, 0x36, 0xa8, 0x11, 0x7e, 0xfb, 0x74, 0x50, 0xf2, 0xab, 0xa6, 0xa3, 0x37, 0x9f, 0xde, 0x73, 0x47, - 0xaf, 0xf9, 0x1d, 0xd8, 0x37, 0xf7, 0xc6, 0xd7, 0xd1, 0xbf, 0xa5, 0xd8, 0xa8, 0x1e, 0xe5, 0x16, 0x8c, 0x52, 0x36, - 0xab, 0x76, 0x61, 0x13, 0x4c, 0xa5, 0x74, 0x40, 0xf2, 0x90, 0x3b, 0x88, 0xd6, 0x3e, 0xce, 0xe1, 0x4a, 0x24, 0xbc, - 0x77, 0x62, 0x21, 0xe8, 0x79, 0xca, 0xaf, 0xd7, 0xdf, 0xa3, 0xb5, 0xbb, 0xf1, 0x94, 0x4d, 0xa6, 0xce, 0x3d, 0x27, - 0x4a, 0x4a, 0xd4, 0xdf, 0x39, 0x41, 0xf1, 0xaf, 0xff, 0x12, 0x86, 0xff, 0xfa, 0x2f, 0x9f, 0x6c, 0x0a, 0xc3, 0x17, - 0x17, 0x58, 0x56, 0xc3, 0xee, 0x26, 0xf0, 0xed, 0x33, 0xd5, 0x71, 0xbe, 0xbd, 0xcd, 0xc6, 0x26, 0x40, 0xfd, 0xc6, - 0x16, 0x6c, 0x14, 0xea, 0x03, 0xe0, 0xfd, 0x16, 0xc0, 0x60, 0x5d, 0x9f, 0x84, 0x0c, 0x1a, 0xfd, 0x2e, 0xd0, 0x2e, - 0x50, 0x74, 0xaf, 0x1d, 0xf9, 0xed, 0x18, 0xfe, 0xd4, 0x1a, 0x7e, 0x27, 0xf8, 0xc6, 0x1f, 0x30, 0xba, 0xb8, 0x28, - 0x13, 0xda, 0xdc, 0xae, 0x70, 0x61, 0xbe, 0xbf, 0x51, 0x62, 0x64, 0x7f, 0xd4, 0x42, 0x3d, 0x75, 0x1d, 0x8f, 0x8c, - 0x2e, 0x5e, 0xc3, 0x5b, 0x72, 0x8e, 0x2f, 0x85, 0x75, 0xa8, 0xde, 0xc1, 0x9f, 0x61, 0x88, 0xfa, 0xaa, 0xd4, 0xa0, - 0x1b, 0xcc, 0x19, 0x4a, 0x41, 0xe1, 0x07, 0x30, 0xf1, 0xe8, 0xc2, 0x58, 0x77, 0xa7, 0xda, 0xed, 0x11, 0xad, 0x93, - 0xb6, 0x71, 0x87, 0xd4, 0x90, 0x8e, 0xbd, 0xf7, 0x0a, 0x5f, 0xaa, 0x31, 0xad, 0xac, 0x69, 0xe5, 0x5a, 0x02, 0x55, - 0xfe, 0xa2, 0x50, 0x61, 0xf1, 0xbf, 0xee, 0x8a, 0xdc, 0xfd, 0xfd, 0xd3, 0x91, 0x3b, 0x7e, 0xaf, 0xc8, 0xdd, 0xdf, - 0xff, 0xf0, 0xc8, 0xdd, 0x5f, 0xdd, 0xc8, 0x1d, 0x6c, 0xe2, 0x97, 0xf7, 0x8a, 0xae, 0xd9, 0xc8, 0x07, 0xbf, 0xce, - 0x49, 0xdb, 0x68, 0xb2, 0x29, 0x9f, 0x40, 0x68, 0xed, 0xdf, 0x3f, 0x52, 0x96, 0xf2, 0x89, 0x1b, 0x27, 0x83, 0xb7, - 0xa4, 0x42, 0x60, 0xac, 0x6b, 0x23, 0x5a, 0x26, 0x36, 0xd5, 0x2a, 0x6f, 0x80, 0x34, 0x1f, 0xda, 0x37, 0x16, 0xf8, - 0x51, 0xf9, 0xd6, 0xa1, 0x16, 0xee, 0xd8, 0xe8, 0x55, 0xa4, 0x02, 0x5f, 0x65, 0xc7, 0x4e, 0xc3, 0x5e, 0x6f, 0x70, - 0x47, 0xe8, 0xda, 0xb7, 0xaa, 0xe8, 0xdb, 0xee, 0x4b, 0xff, 0xc7, 0x9b, 0xf6, 0xb3, 0x41, 0xbb, 0x7b, 0xd4, 0x9e, - 0xf9, 0x91, 0x0f, 0x52, 0x4a, 0x15, 0xb4, 0xba, 0x47, 0x47, 0x50, 0x70, 0xed, 0x14, 0x74, 0xa0, 0x80, 0x39, 0x05, - 0x8f, 0xa0, 0x60, 0xe4, 0x14, 0x3c, 0x86, 0x82, 0xc4, 0x29, 0x78, 0x02, 0x05, 0x57, 0x7e, 0x31, 0x60, 0x25, 0xb8, - 0x4f, 0xd0, 0x10, 0x6b, 0xe3, 0xc1, 0x96, 0x3d, 0xc1, 0x6d, 0x08, 0x99, 0xc5, 0x13, 0x95, 0xe9, 0x03, 0x0e, 0xb8, - 0x88, 0xe3, 0xeb, 0x29, 0xcd, 0x22, 0x08, 0x5a, 0x3e, 0x57, 0x32, 0x26, 0x94, 0xfc, 0x3d, 0x9b, 0x51, 0xfb, 0x7d, - 0x0a, 0x8b, 0x07, 0xcf, 0x47, 0x83, 0xd6, 0xb0, 0xe8, 0x96, 0x3b, 0xa7, 0x63, 0x6d, 0x26, 0xeb, 0x43, 0xef, 0x65, - 0x55, 0xa7, 0xa7, 0x6b, 0x96, 0x7b, 0xbe, 0x23, 0x66, 0xe3, 0x78, 0x03, 0xc6, 0x29, 0xbf, 0x6e, 0xde, 0xf8, 0xbd, - 0xed, 0x71, 0x1c, 0x80, 0xa8, 0x8c, 0xe3, 0xa8, 0x35, 0x95, 0x4f, 0xef, 0xe3, 0x49, 0xf9, 0xfb, 0x35, 0xcd, 0xf3, - 0x78, 0x62, 0x5a, 0xee, 0x8e, 0xdb, 0x28, 0x10, 0xdd, 0x98, 0x8d, 0x05, 0x02, 0x62, 0x2f, 0xb0, 0x59, 0x60, 0x4e, - 0x9b, 0x50, 0x0c, 0x60, 0xa7, 0x1e, 0xc5, 0x51, 0xd3, 0xd7, 0x8b, 0x64, 0x3c, 0xa9, 0x0a, 0x8e, 0xe7, 0x82, 0xaa, - 0x52, 0x8d, 0xe1, 0xe2, 0xf8, 0x10, 0x0a, 0x74, 0xf5, 0x8e, 0x68, 0x8d, 0xb5, 0xdd, 0x77, 0xc7, 0x6c, 0x3c, 0x1b, - 0xad, 0x71, 0xf3, 0x5b, 0xca, 0xe4, 0x96, 0xcd, 0x18, 0xc1, 0x67, 0xed, 0x11, 0xfc, 0x31, 0x11, 0x88, 0xcf, 0xc6, - 0xe3, 0xf1, 0x9d, 0xd1, 0x9b, 0xcf, 0x92, 0x31, 0xed, 0xd0, 0x47, 0x5d, 0xc8, 0x7d, 0x68, 0x1a, 0x9f, 0x7f, 0xbb, - 0x50, 0xb8, 0x5b, 0xde, 0xaf, 0x31, 0x84, 0x07, 0xe4, 0x74, 0x79, 0xff, 0x48, 0x4e, 0x31, 0x17, 0x74, 0x39, 0x8b, - 0xc5, 0x84, 0x65, 0x51, 0xab, 0x08, 0xaf, 0x4c, 0xe8, 0xe3, 0xb3, 0xa7, 0x4f, 0x9f, 0x16, 0x61, 0x62, 0x9f, 0x5a, - 0x49, 0x52, 0x84, 0xa3, 0x65, 0xb9, 0x8c, 0x56, 0x6b, 0x3c, 0x2e, 0x42, 0x66, 0x0b, 0x8e, 0x3a, 0xa3, 0xe4, 0xa8, - 0x53, 0x84, 0xd7, 0x4e, 0x8b, 0x22, 0xa4, 0xe6, 0x49, 0xd0, 0xa4, 0x96, 0x40, 0xf1, 0xa4, 0xd5, 0x2a, 0x42, 0x4d, - 0x68, 0x4b, 0xb0, 0x88, 0xf4, 0xcf, 0x28, 0x5e, 0x48, 0x0e, 0x2c, 0xb9, 0xcb, 0x65, 0x30, 0x38, 0x37, 0x2f, 0xa7, - 0xd0, 0x1f, 0x72, 0x28, 0xd0, 0x10, 0x7f, 0xe9, 0x06, 0x29, 0x80, 0x98, 0x55, 0x70, 0x82, 0xdb, 0x18, 0x46, 0xad, - 0x1a, 0x28, 0x4b, 0x55, 0x7f, 0x49, 0x78, 0x15, 0xbb, 0x00, 0xfe, 0x03, 0x2d, 0xf5, 0x5b, 0xd4, 0x24, 0xdd, 0xc1, - 0xf5, 0x29, 0xfd, 0x24, 0xd7, 0xbf, 0xbd, 0x0f, 0xd3, 0xa7, 0xf4, 0x8f, 0x66, 0xfa, 0xe6, 0x55, 0xa3, 0x9a, 0xe9, - 0x6b, 0xb6, 0x36, 0x93, 0xc4, 0x1f, 0x4d, 0xe9, 0xe8, 0xe3, 0x25, 0xbf, 0x69, 0xc2, 0x91, 0x10, 0xbe, 0xe2, 0xa7, - 0xfb, 0xbf, 0x35, 0xd9, 0xc2, 0x0e, 0xe6, 0x7c, 0x07, 0x42, 0x89, 0xcd, 0xb7, 0x19, 0xf1, 0xdf, 0x5a, 0xb3, 0x4a, - 0x97, 0x8c, 0xc7, 0xc4, 0x7f, 0x3b, 0x1e, 0xfb, 0xf6, 0x8a, 0x5d, 0x2c, 0xa9, 0x6a, 0xf5, 0xa6, 0x56, 0xa2, 0x5a, - 0x7d, 0xf1, 0x85, 0x5b, 0xe6, 0x16, 0x98, 0x10, 0x87, 0x1b, 0xce, 0x30, 0x35, 0x09, 0xcb, 0xe1, 0xa8, 0xc1, 0xe7, - 0x29, 0xea, 0xef, 0xf8, 0x13, 0xb5, 0xd7, 0x31, 0x97, 0x00, 0x6f, 0x79, 0x87, 0xf4, 0xfa, 0xfd, 0xf2, 0x09, 0xb5, - 0xe9, 0x6e, 0xcf, 0x6e, 0xbf, 0x4c, 0x82, 0x99, 0x44, 0x05, 0xcb, 0xdf, 0x66, 0x6b, 0x77, 0x47, 0x34, 0x8c, 0x84, - 0xb8, 0xcb, 0x2a, 0x24, 0x9f, 0x4c, 0x52, 0xf8, 0x40, 0xc8, 0xb2, 0xf6, 0xde, 0x51, 0xdd, 0xbd, 0x5f, 0x5b, 0x6f, - 0xe4, 0x76, 0x34, 0x6f, 0xe9, 0x54, 0xdf, 0x2b, 0xd2, 0x39, 0xc7, 0x57, 0xe6, 0xc3, 0x35, 0xca, 0x22, 0x5b, 0x1a, - 0xfe, 0xbf, 0xd4, 0x99, 0xaa, 0x12, 0xb2, 0x34, 0xf4, 0xc0, 0x49, 0x51, 0x98, 0x1c, 0xff, 0x84, 0xe5, 0x73, 0x78, - 0x1f, 0xa6, 0xee, 0x49, 0x3f, 0xc5, 0xc2, 0xf3, 0x6b, 0x27, 0x8e, 0x50, 0xdb, 0xae, 0xc2, 0x06, 0x12, 0xb4, 0xab, - 0x76, 0x26, 0x0b, 0xdf, 0x78, 0x7c, 0x2d, 0x12, 0x7d, 0x4f, 0xe3, 0x53, 0x47, 0x38, 0x9c, 0x15, 0x82, 0xab, 0xbf, - 0xdc, 0x10, 0x5b, 0x65, 0x0b, 0x0a, 0x37, 0x4e, 0xa6, 0x6a, 0x34, 0xb6, 0x94, 0x57, 0x3e, 0x9f, 0xc7, 0x99, 0x66, - 0xa3, 0xc4, 0xd7, 0xfc, 0x60, 0x7f, 0x59, 0xed, 0x7c, 0xe1, 0x5b, 0xb0, 0x35, 0xf1, 0xf6, 0x8e, 0x0f, 0xa1, 0x43, - 0xcf, 0xab, 0x81, 0x9e, 0x6d, 0x38, 0xf3, 0x3f, 0x11, 0x56, 0xbf, 0x08, 0xf3, 0x6b, 0x1c, 0xe6, 0xd7, 0xde, 0x9f, - 0x97, 0xcd, 0x6b, 0x7a, 0xf9, 0x91, 0xc9, 0xa6, 0x8c, 0xe7, 0x4d, 0x50, 0xf8, 0x95, 0x5f, 0xce, 0xb0, 0x67, 0x95, - 0x1c, 0xa6, 0x6f, 0xc8, 0x77, 0x17, 0x39, 0x44, 0xdf, 0x95, 0xda, 0x1a, 0x65, 0x3c, 0xa3, 0xdd, 0x7a, 0x12, 0xa0, - 0x1b, 0xcc, 0xb5, 0xd8, 0x1a, 0x2e, 0x39, 0x44, 0xeb, 0xe5, 0x6d, 0xd4, 0x32, 0x6c, 0xbd, 0x65, 0x23, 0xb5, 0xad, - 0xad, 0xed, 0x23, 0x83, 0xdc, 0x86, 0x92, 0x5e, 0x62, 0x33, 0x62, 0xbd, 0x2b, 0xe2, 0xfc, 0xa9, 0x94, 0x38, 0xf0, - 0xe6, 0xd9, 0xbf, 0x4e, 0x2e, 0xe1, 0x7a, 0xb1, 0x4a, 0x89, 0xbb, 0x0f, 0x64, 0x51, 0x3c, 0x96, 0x54, 0xe0, 0xfb, - 0xb4, 0xbc, 0x54, 0xb7, 0x57, 0x96, 0x20, 0x66, 0xa2, 0xf6, 0xd3, 0xf9, 0xcd, 0xfd, 0x87, 0xbf, 0x7b, 0xf9, 0x85, - 0xc1, 0x91, 0x7d, 0x9b, 0x8b, 0xef, 0x77, 0xe1, 0x20, 0xa4, 0xf1, 0x6d, 0xc4, 0x32, 0x25, 0xf3, 0x2e, 0xc1, 0x25, - 0xd7, 0x9d, 0x73, 0x93, 0xdb, 0x29, 0x68, 0xaa, 0x3e, 0xdd, 0x66, 0xb6, 0xe2, 0xe8, 0xf1, 0xfc, 0xc6, 0xee, 0x46, - 0x7b, 0x2d, 0x67, 0xf3, 0x0f, 0x4d, 0xcd, 0xdc, 0x9d, 0x0b, 0x5a, 0x4f, 0x2f, 0x7c, 0x34, 0xbf, 0xe9, 0x6a, 0x41, - 0xdb, 0x14, 0x1a, 0xaa, 0xd6, 0xfc, 0xc6, 0x4d, 0x4e, 0xad, 0x06, 0xf2, 0xc2, 0xa3, 0xdc, 0xa3, 0x71, 0x4e, 0xbb, - 0xf0, 0xbe, 0x6a, 0x36, 0x8a, 0x53, 0x23, 0xcc, 0x67, 0x2c, 0x49, 0x52, 0xda, 0xb5, 0xf2, 0xda, 0x6b, 0x3f, 0x86, - 0xdc, 0x4e, 0x77, 0xcb, 0xea, 0xbb, 0xe2, 0x20, 0xaf, 0xc4, 0x53, 0x7c, 0x99, 0xf3, 0x14, 0x3e, 0x16, 0xb1, 0x15, - 0x9d, 0x26, 0xe9, 0xb1, 0x55, 0x21, 0x4f, 0xfd, 0xae, 0xaf, 0xe5, 0x51, 0xeb, 0x4f, 0x5d, 0xb5, 0xe1, 0xad, 0xae, - 0xe4, 0xf3, 0xa8, 0x79, 0x54, 0x5f, 0x08, 0x54, 0x95, 0x4b, 0xc0, 0x5b, 0x96, 0x85, 0x41, 0x5a, 0x69, 0x3e, 0xed, - 0x85, 0x6d, 0x53, 0xa6, 0x06, 0x80, 0x17, 0x2b, 0x97, 0x45, 0x45, 0x7d, 0x31, 0xff, 0x3e, 0xa7, 0xe5, 0xf3, 0xed, - 0xa7, 0xe5, 0x73, 0x7b, 0x5a, 0xee, 0xa6, 0xd8, 0xcf, 0xc6, 0x6d, 0xf8, 0xd3, 0xad, 0x16, 0x14, 0xb5, 0xbc, 0xa3, - 0xf9, 0x8d, 0x07, 0x7a, 0x5a, 0xb3, 0x33, 0xbf, 0xd1, 0xa9, 0xb9, 0x10, 0x36, 0x68, 0x41, 0xb2, 0x2a, 0x6e, 0x79, - 0x50, 0x08, 0x7f, 0x5b, 0xb5, 0xaa, 0xf6, 0x43, 0xa8, 0x83, 0x5e, 0x8f, 0x36, 0xeb, 0x3a, 0x77, 0x1f, 0xda, 0x28, - 0xe3, 0x32, 0x88, 0x2c, 0x37, 0x46, 0xa1, 0x8c, 0x2f, 0x2f, 0x69, 0x12, 0x8d, 0xf9, 0x68, 0x91, 0xff, 0xb3, 0x81, - 0xdf, 0x20, 0xf1, 0xce, 0x23, 0xbd, 0x36, 0x8e, 0xed, 0xaa, 0x13, 0x85, 0xed, 0x08, 0xcb, 0x72, 0x9f, 0xa2, 0x7c, - 0x14, 0xa7, 0x34, 0xe8, 0x84, 0x0f, 0xb7, 0x1c, 0x82, 0xff, 0x90, 0xbd, 0xd9, 0xba, 0x98, 0xdf, 0x8b, 0x8c, 0x3b, - 0x91, 0xf0, 0xab, 0x70, 0xe0, 0xee, 0x61, 0xeb, 0xe9, 0x76, 0x70, 0x07, 0x76, 0xa6, 0xa1, 0x15, 0x0a, 0x46, 0xee, - 0x24, 0x74, 0x1c, 0x2f, 0x52, 0x79, 0xf7, 0xa8, 0xbb, 0x28, 0x63, 0x63, 0xd4, 0x3b, 0x18, 0x7a, 0xd5, 0xf6, 0x9e, - 0x5c, 0xfa, 0xb3, 0xcf, 0x1f, 0xc2, 0x1f, 0x9d, 0x67, 0x74, 0x5b, 0xe9, 0xea, 0xda, 0x56, 0x05, 0x5d, 0x7d, 0xbf, - 0xa6, 0x8c, 0x6b, 0x11, 0xae, 0xf4, 0xf1, 0xfb, 0xb6, 0x06, 0xad, 0xf2, 0x5e, 0xcd, 0x8d, 0x96, 0xf5, 0xab, 0x5a, - 0xff, 0xba, 0xc1, 0xef, 0xd9, 0x76, 0xa4, 0x35, 0xd7, 0x7a, 0x5b, 0xf3, 0xed, 0xba, 0x8d, 0xc6, 0x16, 0xe3, 0xaa, - 0xfd, 0x3e, 0xb9, 0x2d, 0x4d, 0x14, 0x1d, 0x08, 0x04, 0x2b, 0x65, 0x5f, 0x5b, 0x29, 0x8c, 0x92, 0x07, 0xf0, 0xe6, - 0x58, 0xef, 0x66, 0x96, 0x66, 0x39, 0xf1, 0xa7, 0x52, 0xce, 0x23, 0xfd, 0xb1, 0xd3, 0xeb, 0xa3, 0x90, 0x8b, 0xc9, - 0x61, 0xa7, 0xd5, 0x6a, 0xc1, 0x1b, 0x3f, 0x7d, 0xef, 0x8a, 0xd1, 0xeb, 0x67, 0xfc, 0x86, 0xf8, 0x4f, 0xbc, 0xa7, - 0xde, 0x93, 0x23, 0xef, 0xd1, 0x63, 0xdf, 0x53, 0xec, 0x9c, 0xf8, 0x4f, 0x8e, 0x7c, 0x4f, 0xb3, 0x73, 0xe2, 0x3f, - 0x7a, 0xec, 0xf7, 0x8e, 0x27, 0x56, 0x25, 0x83, 0x2b, 0x83, 0x5a, 0xdf, 0xc9, 0xa5, 0xe0, 0x1f, 0x69, 0xfd, 0xe0, - 0xea, 0x32, 0x93, 0x89, 0xd6, 0xb1, 0x8f, 0x70, 0x7a, 0x47, 0xf1, 0x3c, 0x52, 0x44, 0xe1, 0x16, 0x82, 0x5b, 0x46, - 0x97, 0xaa, 0x29, 0x40, 0xcd, 0xbc, 0xf4, 0x7b, 0xc7, 0x90, 0x35, 0xee, 0x25, 0xc4, 0x7f, 0xdd, 0x79, 0xe2, 0xb5, - 0x1f, 0x5f, 0x35, 0x1f, 0x8e, 0x5a, 0xcd, 0xb6, 0xd7, 0x6e, 0x76, 0xc2, 0x27, 0x5e, 0x47, 0xff, 0xeb, 0xb5, 0xbc, - 0x23, 0xaf, 0x1d, 0x3e, 0xf1, 0x8e, 0xbc, 0x4e, 0xf8, 0xe4, 0xea, 0xa1, 0x4e, 0x27, 0x88, 0xfd, 0xc3, 0xde, 0x31, - 0x7c, 0xb8, 0xf2, 0x86, 0xf8, 0x9f, 0xfb, 0xfa, 0xf3, 0xb0, 0xfe, 0x67, 0x6e, 0x69, 0xfb, 0xe9, 0xd6, 0xe2, 0xce, - 0x93, 0xad, 0xc5, 0x47, 0x8f, 0xb7, 0x16, 0x3f, 0x7c, 0x54, 0x2f, 0x3e, 0x9c, 0xe8, 0xaa, 0xf2, 0x94, 0x13, 0x7f, - 0x16, 0x4b, 0xc1, 0x6e, 0x82, 0xb6, 0xd7, 0xf2, 0x5a, 0x5e, 0x13, 0xfe, 0x7b, 0xd2, 0x41, 0x65, 0xaf, 0x4b, 0xe8, - 0x55, 0xae, 0xf2, 0xc9, 0x53, 0xaf, 0xfd, 0xf8, 0x65, 0xe7, 0xf1, 0x08, 0xda, 0xa9, 0x85, 0xb6, 0xbd, 0xf6, 0xd5, - 0xd1, 0xd3, 0x51, 0xcb, 0x83, 0x8e, 0x6d, 0xf8, 0x33, 0x7d, 0xd4, 0x19, 0xe9, 0x87, 0x16, 0xd4, 0x7f, 0xdb, 0x7e, - 0x92, 0xb7, 0x9a, 0x6d, 0xf8, 0xf3, 0x4b, 0xa9, 0x11, 0x83, 0x3e, 0xee, 0x8e, 0xfb, 0xb0, 0xe5, 0x1d, 0x3d, 0x9d, - 0x76, 0xc2, 0xcf, 0xaf, 0x9e, 0x84, 0x4f, 0xa7, 0xed, 0x27, 0xdf, 0xea, 0xa7, 0xb4, 0xd9, 0x09, 0x3f, 0x87, 0xbf, - 0xdf, 0x1e, 0xb5, 0xa6, 0xcd, 0x76, 0xf8, 0xf4, 0xea, 0x28, 0x3c, 0x4a, 0x9b, 0x8f, 0xc3, 0xa7, 0xf0, 0xb7, 0x1a, - 0x6e, 0xca, 0x67, 0xd4, 0xf7, 0x60, 0xbf, 0xd7, 0xcc, 0x2d, 0x77, 0x8e, 0xce, 0x43, 0xef, 0xd1, 0xc3, 0x97, 0x4f, - 0xaf, 0x9a, 0x0f, 0xa7, 0xed, 0xce, 0x55, 0x73, 0xe7, 0xcf, 0x6f, 0x01, 0xf1, 0x66, 0xe0, 0x98, 0xc2, 0xf5, 0x1d, - 0x8b, 0x38, 0xf5, 0xf6, 0xd9, 0x07, 0x38, 0xdf, 0x65, 0x5e, 0x8b, 0x4f, 0x9b, 0xd7, 0x19, 0xbd, 0x8f, 0x7d, 0x2d, - 0xfe, 0x70, 0xfb, 0x3a, 0xa7, 0x6b, 0x4e, 0xd5, 0x5b, 0xb9, 0x61, 0x46, 0xaf, 0xdb, 0x5e, 0xef, 0x64, 0x30, 0x60, - 0xf0, 0x95, 0xa3, 0xa2, 0x7b, 0x0b, 0x2f, 0xb8, 0x76, 0xbd, 0x0d, 0x1c, 0x0e, 0xf2, 0xad, 0xd4, 0x27, 0x99, 0xef, - 0x42, 0x48, 0xfa, 0x69, 0x84, 0x7c, 0x7b, 0x1f, 0x7c, 0xa4, 0x7f, 0x38, 0x3e, 0xb8, 0x8b, 0x8f, 0x9a, 0x9f, 0x57, - 0xd9, 0xb3, 0xca, 0x1e, 0x3d, 0x53, 0xcf, 0x01, 0xdc, 0xf0, 0x68, 0xf8, 0x87, 0x14, 0x8a, 0x72, 0x5f, 0xc7, 0x15, - 0xde, 0xfc, 0x1a, 0x97, 0xb4, 0xbe, 0xce, 0x45, 0x7c, 0x63, 0xfc, 0xcf, 0xe1, 0x4b, 0x06, 0xf6, 0xe1, 0x4a, 0x5f, - 0x30, 0x26, 0x7e, 0x27, 0x6c, 0x85, 0xad, 0xd2, 0x71, 0x00, 0x57, 0xf8, 0xc8, 0x92, 0xcb, 0x18, 0x3e, 0xa6, 0x99, - 0xf2, 0x89, 0xfa, 0xec, 0x26, 0xbc, 0xec, 0x5c, 0x7d, 0x00, 0x55, 0xbf, 0x67, 0x3e, 0xf2, 0x7d, 0x73, 0xf1, 0x1f, - 0xae, 0x88, 0x7d, 0x03, 0xd7, 0xe8, 0xac, 0xc7, 0x7a, 0x06, 0x36, 0xf5, 0x6b, 0x9a, 0xb0, 0x38, 0xf0, 0x83, 0xb9, - 0xa0, 0x63, 0x2a, 0xf2, 0x66, 0xed, 0x6e, 0x99, 0xba, 0x56, 0x86, 0x7c, 0xfb, 0xd9, 0x46, 0x01, 0x2f, 0xef, 0x25, - 0x03, 0xe3, 0xd5, 0xf2, 0x8d, 0x9a, 0xef, 0x17, 0xd8, 0x96, 0x08, 0xe0, 0xe8, 0x95, 0x6a, 0xe0, 0x6b, 0xdd, 0xa0, - 0x1d, 0x76, 0x1e, 0x21, 0xcd, 0x4b, 0xe0, 0xa5, 0xa8, 0xdf, 0x07, 0xcd, 0xa3, 0xd6, 0x9f, 0x90, 0xd3, 0xad, 0x1c, - 0x68, 0x68, 0x9c, 0x3a, 0xa2, 0xfa, 0xdc, 0x6d, 0xfd, 0xe2, 0x9f, 0xaf, 0x29, 0xe2, 0x33, 0xbd, 0x76, 0x78, 0xbd, - 0xaa, 0x89, 0x1f, 0xea, 0xeb, 0xeb, 0x63, 0x36, 0x09, 0xdc, 0x8f, 0x99, 0xea, 0x97, 0xae, 0xaa, 0x6f, 0x20, 0xa3, - 0xa2, 0x6a, 0x22, 0xd0, 0x52, 0xf9, 0xe2, 0x59, 0xe6, 0x89, 0xd5, 0x2a, 0x10, 0xe0, 0x88, 0x25, 0x0e, 0x4e, 0xe1, - 0x19, 0xd5, 0x90, 0x2c, 0x70, 0x09, 0x90, 0x42, 0x30, 0x11, 0xfa, 0xff, 0xaa, 0xd8, 0xfe, 0x30, 0xee, 0x95, 0x30, - 0x8d, 0xb3, 0x09, 0x50, 0x61, 0x9c, 0x4d, 0x36, 0x9c, 0x37, 0x3a, 0x9c, 0xb0, 0x56, 0x5a, 0x0d, 0x55, 0x39, 0x69, - 0xf2, 0x67, 0xb7, 0xef, 0xcd, 0xdb, 0x99, 0x7c, 0xf0, 0x81, 0x2a, 0xdf, 0x77, 0xf5, 0x26, 0xd9, 0x06, 0x79, 0xa0, - 0x3f, 0x0f, 0xae, 0xf2, 0xd1, 0x40, 0xfa, 0xc1, 0x95, 0x3e, 0xcf, 0xd8, 0x3c, 0xc4, 0xd7, 0xb2, 0x2f, 0xa1, 0x57, - 0x6c, 0x64, 0x44, 0x18, 0xf6, 0xcc, 0xb5, 0xe6, 0xa6, 0xda, 0x1a, 0xd2, 0xc6, 0xda, 0xea, 0x1f, 0xc5, 0x2a, 0xbf, - 0x98, 0x64, 0xdc, 0xef, 0x3d, 0x28, 0xbf, 0xcd, 0xb8, 0x6b, 0x13, 0xe0, 0x9b, 0xe5, 0x03, 0x41, 0xd3, 0x7f, 0x26, - 0x0f, 0xe0, 0xab, 0xe5, 0x0f, 0x86, 0xf0, 0xc1, 0xec, 0x50, 0x89, 0x82, 0x07, 0xd5, 0xc7, 0xcb, 0x81, 0x0f, 0x36, - 0x6e, 0x66, 0x29, 0xbe, 0xaf, 0xf8, 0x36, 0xa2, 0xba, 0xf3, 0xa8, 0x12, 0xd5, 0x9d, 0x47, 0xae, 0xf4, 0x6c, 0x7b, - 0xed, 0x4e, 0xf8, 0xc8, 0x11, 0x00, 0x57, 0x4d, 0xf8, 0xbf, 0x26, 0x02, 0x1e, 0x86, 0x8f, 0x4a, 0x19, 0xf0, 0xaa, - 0xdd, 0x09, 0x8f, 0xb4, 0xb8, 0xe9, 0x84, 0x8f, 0x7e, 0x50, 0x0c, 0x5a, 0x33, 0xe7, 0xfa, 0x81, 0xd8, 0x12, 0xaa, - 0xd1, 0x49, 0x75, 0x3e, 0x0e, 0xca, 0x2f, 0xc0, 0x99, 0xf3, 0x69, 0x5c, 0x42, 0xcf, 0x63, 0x01, 0x9f, 0xe1, 0xa8, - 0x9f, 0xdd, 0x5a, 0x1d, 0xae, 0xf1, 0x8b, 0x2d, 0x53, 0xc0, 0x09, 0xf7, 0xb1, 0x7b, 0x2f, 0x18, 0x2e, 0xd5, 0xaa, - 0x97, 0x16, 0xdb, 0x77, 0xb7, 0xed, 0x26, 0x6d, 0xdd, 0xd0, 0xbe, 0x1f, 0x4e, 0x31, 0x0b, 0xa6, 0x5e, 0x10, 0xaf, - 0x26, 0xf9, 0x32, 0x29, 0xd6, 0xe7, 0x87, 0xdc, 0x3e, 0xc1, 0x9d, 0xab, 0xd1, 0xb4, 0x4a, 0x3f, 0x4f, 0x18, 0x5c, - 0x66, 0x2f, 0x0a, 0x0b, 0x7a, 0xcd, 0x19, 0x58, 0x61, 0x49, 0xf1, 0x0b, 0x9a, 0xf7, 0x7d, 0x28, 0xf2, 0x23, 0x5f, - 0x39, 0x92, 0xfc, 0xf2, 0x53, 0x24, 0x25, 0x61, 0x57, 0x05, 0x58, 0x5d, 0x21, 0x81, 0x53, 0x0b, 0xf8, 0xf1, 0xd1, - 0xc1, 0xc1, 0xce, 0xf3, 0xa2, 0xb4, 0x31, 0x58, 0x6b, 0xf5, 0x09, 0x03, 0x97, 0x15, 0xf9, 0x2e, 0xa2, 0xcb, 0x71, - 0x15, 0x0a, 0x91, 0xc1, 0xd3, 0x25, 0x8d, 0x65, 0x18, 0x67, 0x3a, 0x45, 0xc1, 0x61, 0x58, 0xb8, 0x4d, 0x8f, 0x50, - 0xc1, 0x65, 0xec, 0x7c, 0xa3, 0xd4, 0x9c, 0x73, 0x2e, 0x63, 0x7b, 0xd1, 0x2f, 0x93, 0xb5, 0x4c, 0xf8, 0x69, 0xa7, - 0xf7, 0xf6, 0xfd, 0x89, 0xa7, 0x8f, 0xe7, 0xf1, 0xe1, 0xb4, 0xd3, 0x3b, 0x56, 0x96, 0xb9, 0xbe, 0x26, 0x44, 0xf4, - 0x35, 0x21, 0xcf, 0x5c, 0x19, 0x83, 0x78, 0x4d, 0x71, 0xa8, 0x97, 0xed, 0x7b, 0x34, 0x1b, 0x69, 0x9f, 0xe2, 0x6c, - 0x91, 0x4a, 0x06, 0x2f, 0xe0, 0x3d, 0x84, 0xae, 0x4d, 0xd8, 0xb0, 0x32, 0xcf, 0xd4, 0x6a, 0x38, 0x32, 0xb3, 0x1e, - 0xc8, 0x31, 0x4b, 0xa9, 0xcd, 0x2c, 0x35, 0x43, 0x95, 0x79, 0xcf, 0x9b, 0xad, 0xf3, 0xc5, 0xe5, 0x8c, 0xc9, 0x32, - 0x15, 0xf4, 0x83, 0xe9, 0x70, 0xac, 0xa6, 0xea, 0x5d, 0x14, 0xc6, 0x45, 0x6a, 0x3f, 0x36, 0xb2, 0xf6, 0x79, 0x77, - 0xbd, 0x7a, 0x23, 0x21, 0xe0, 0xbe, 0xcf, 0xf4, 0xa8, 0x57, 0x3a, 0x25, 0xdd, 0xba, 0xe2, 0xf8, 0x70, 0x7a, 0xd4, - 0xbb, 0x88, 0xe6, 0x66, 0xbc, 0x57, 0x7c, 0xe3, 0x53, 0xf1, 0x25, 0xc7, 0xec, 0xab, 0xc4, 0x76, 0x7d, 0x83, 0xd2, - 0x00, 0x3c, 0xe2, 0xa9, 0xdf, 0x3b, 0x36, 0xca, 0x80, 0xa7, 0x82, 0xae, 0xfe, 0xa3, 0x96, 0xcd, 0x95, 0x4f, 0xb9, - 0xd2, 0x96, 0x74, 0x17, 0x67, 0x92, 0x9a, 0x5f, 0x77, 0xda, 0xee, 0x1d, 0xc7, 0x46, 0xcd, 0x04, 0xe6, 0x91, 0x47, - 0x87, 0xd0, 0x19, 0x74, 0xb9, 0x90, 0xf1, 0xc3, 0x6b, 0x7a, 0xd9, 0x8c, 0xe7, 0xac, 0x72, 0xa2, 0x82, 0xd2, 0x51, - 0x4e, 0xc9, 0xab, 0x99, 0xe0, 0x67, 0xbc, 0xb6, 0x48, 0xc5, 0xc2, 0x0b, 0xe3, 0xa1, 0x55, 0xba, 0x3a, 0x8d, 0xa5, - 0xef, 0x69, 0x0e, 0x6f, 0x3d, 0xb9, 0x46, 0xf6, 0x16, 0x7e, 0xef, 0xdf, 0xfe, 0xc7, 0xff, 0x32, 0xce, 0xd9, 0xe3, - 0xc3, 0x69, 0xdb, 0x8e, 0xb5, 0x86, 0xe8, 0xe2, 0x18, 0xae, 0x97, 0x55, 0xd1, 0x44, 0x7a, 0xd3, 0x9c, 0x08, 0x96, - 0x34, 0xa7, 0x71, 0x3a, 0xf6, 0x7b, 0xbb, 0x11, 0xe4, 0xde, 0x2b, 0x31, 0x50, 0xd7, 0x8b, 0x80, 0x04, 0x7f, 0xd3, - 0xcd, 0x08, 0x9b, 0x60, 0xaf, 0x4e, 0xab, 0x7b, 0x4f, 0xa2, 0x3a, 0x50, 0xb5, 0xbb, 0x12, 0xc2, 0x7c, 0x93, 0xc8, - 0x30, 0x35, 0x51, 0xbb, 0x22, 0x51, 0xf8, 0x5e, 0x19, 0x0d, 0xf9, 0xbf, 0xff, 0xf3, 0xbf, 0xfc, 0x37, 0xfb, 0x08, - 0x41, 0x8e, 0x7f, 0xfb, 0xef, 0xff, 0xf9, 0xff, 0xfc, 0xef, 0xff, 0x0a, 0x69, 0xf5, 0x26, 0x10, 0xa2, 0xf8, 0x84, - 0x57, 0x45, 0x41, 0x34, 0xc3, 0xf0, 0x20, 0x19, 0x6d, 0xc6, 0x72, 0xc9, 0x46, 0xf5, 0x4b, 0x13, 0x67, 0x6a, 0x42, - 0x75, 0xd8, 0x0c, 0x74, 0xea, 0xd0, 0x16, 0x15, 0x8d, 0xd4, 0x50, 0xae, 0x68, 0xb1, 0x38, 0x3e, 0x04, 0x7c, 0xdf, - 0xef, 0x9e, 0x59, 0x58, 0x6e, 0xc7, 0xd2, 0xba, 0xfe, 0xa0, 0xa4, 0xa8, 0xca, 0x3d, 0x70, 0xca, 0x2f, 0xe1, 0x31, - 0xea, 0x38, 0xc5, 0x6a, 0xf7, 0x6a, 0x7d, 0xba, 0x3f, 0x2d, 0x72, 0xc9, 0xc6, 0x80, 0x72, 0xed, 0x60, 0x54, 0xf1, - 0xcf, 0x26, 0xa8, 0x7f, 0xe9, 0x6d, 0xa1, 0x46, 0xd1, 0x36, 0xe3, 0xc3, 0xa7, 0x7f, 0x2a, 0xfe, 0x32, 0x03, 0x25, - 0xcb, 0x0b, 0x66, 0xf1, 0x8d, 0xb1, 0x24, 0x1f, 0xb7, 0x5a, 0xf3, 0x1b, 0xb4, 0xac, 0x66, 0xc0, 0xbb, 0x26, 0x53, - 0x4e, 0x49, 0x77, 0x40, 0x15, 0x38, 0x2d, 0xfd, 0x9f, 0x2d, 0x0f, 0x9c, 0xa8, 0x5e, 0xab, 0x28, 0xfe, 0xbc, 0x54, - 0x2e, 0x38, 0xf6, 0x0b, 0x04, 0x38, 0x8d, 0xb7, 0xf2, 0x92, 0xbb, 0x8b, 0x5b, 0x3a, 0xbd, 0x3a, 0xba, 0xd7, 0xb4, - 0xbd, 0x79, 0x7d, 0xca, 0x0d, 0xd0, 0xba, 0xa1, 0xd5, 0x87, 0x10, 0x2c, 0x9d, 0xb6, 0xf1, 0xb4, 0xb3, 0x2c, 0x87, - 0x97, 0x92, 0xcf, 0xdc, 0x88, 0x2c, 0x8d, 0xe9, 0x88, 0x8e, 0xad, 0x97, 0xd7, 0xd4, 0xeb, 0x68, 0x6b, 0x31, 0x3d, - 0xda, 0x32, 0x97, 0x01, 0x49, 0x45, 0x62, 0xbd, 0x56, 0xf1, 0x19, 0x9c, 0xc0, 0xe5, 0x38, 0xe5, 0xb1, 0x8c, 0x14, - 0xc1, 0x76, 0xdd, 0xb8, 0x6e, 0x0c, 0x6c, 0x86, 0x2f, 0x1d, 0x78, 0xba, 0xba, 0x29, 0xf8, 0x5b, 0xeb, 0x97, 0xdc, - 0x8a, 0x50, 0x75, 0x77, 0x87, 0xd2, 0xee, 0x9a, 0x6f, 0x4d, 0xb8, 0xf4, 0x4d, 0xcd, 0xcf, 0x61, 0x64, 0x4c, 0x07, - 0x6d, 0xaf, 0xd7, 0xa2, 0x5a, 0xd7, 0x7e, 0x25, 0x03, 0x5f, 0x81, 0xe9, 0xaf, 0xb7, 0x52, 0x85, 0xd0, 0xea, 0x0d, - 0xf9, 0xb6, 0xb4, 0x82, 0xe2, 0xf9, 0x5c, 0x35, 0x44, 0xdd, 0xe3, 0x43, 0xad, 0xbc, 0x02, 0xf7, 0x50, 0xb9, 0x00, - 0x3a, 0xf4, 0x6e, 0x1a, 0x99, 0xa3, 0xa0, 0x7f, 0x99, 0xa0, 0x3c, 0x7c, 0xac, 0xaa, 0xf7, 0xff, 0x00, 0xbb, 0x9f, - 0x49, 0x8d, 0x3d, 0x86, 0x00, 0x00}; + 0x72, 0x7f, 0x60, 0xe6, 0x13, 0x26, 0x4e, 0x2e, 0x40, 0x82, 0x4b, 0xa9, 0xbc, 0xdc, 0x1b, 0x13, 0x0a, 0x49, 0x44, + 0xae, 0x27, 0x4f, 0x9e, 0x3c, 0x7b, 0x02, 0xc7, 0x7b, 0x09, 0x1f, 0xc9, 0xdb, 0x39, 0xf5, 0xa6, 0x72, 0x96, 0xf6, + 0x8e, 0xcd, 0xbf, 0x34, 0x4e, 0x7a, 0xc7, 0x29, 0xcb, 0x3e, 0x7a, 0x82, 0xa6, 0x84, 0x8d, 0x78, 0xe6, 0x4d, 0x05, + 0x1d, 0x93, 0x24, 0x96, 0x71, 0xc4, 0x66, 0xf1, 0x84, 0x7a, 0x87, 0xbd, 0xe3, 0x19, 0x95, 0xb1, 0x37, 0x9a, 0xc6, + 0x22, 0xa7, 0x92, 0x7c, 0x78, 0xff, 0x45, 0xf3, 0x69, 0xef, 0x38, 0x1f, 0x09, 0x36, 0x97, 0x1e, 0x0c, 0x49, 0x66, + 0x3c, 0x59, 0xa4, 0xb4, 0x77, 0x78, 0x78, 0x7d, 0x7d, 0x1d, 0xfe, 0x94, 0xff, 0xd3, 0x88, 0x67, 0xb9, 0xf4, 0x5e, + 0x91, 0x6b, 0x96, 0x25, 0xfc, 0x1a, 0x53, 0x49, 0x5e, 0x85, 0x67, 0xd3, 0x38, 0xe1, 0xd7, 0xef, 0x38, 0x97, 0x07, + 0x07, 0x81, 0x7e, 0xbc, 0x3d, 0x3d, 0x3b, 0x23, 0x84, 0x5c, 0x71, 0x96, 0x78, 0xad, 0xd5, 0xaa, 0x2a, 0x0c, 0xb3, + 0x58, 0xb2, 0x2b, 0xaa, 0xbb, 0xa0, 0x83, 0x03, 0x3f, 0x4e, 0xf8, 0x5c, 0xd2, 0xe4, 0x4c, 0xde, 0xa6, 0xf4, 0x6c, + 0x4a, 0xa9, 0xcc, 0x7d, 0x96, 0x79, 0xcf, 0xf9, 0x68, 0x31, 0xa3, 0x99, 0x0c, 0xe7, 0x82, 0x4b, 0x0e, 0x90, 0x1c, + 0x1c, 0xf8, 0x82, 0xce, 0xd3, 0x78, 0x44, 0xa1, 0xfe, 0xf4, 0xec, 0xac, 0xea, 0x51, 0x35, 0xc2, 0x4c, 0x92, 0xb3, + 0xdb, 0xd9, 0x25, 0x4f, 0x03, 0x84, 0x53, 0x49, 0x32, 0x7a, 0xed, 0x7d, 0x47, 0xe3, 0x8f, 0xaf, 0xe3, 0x79, 0x77, + 0x94, 0xc6, 0x79, 0xee, 0x5d, 0xca, 0xa5, 0x5a, 0x82, 0x58, 0x8c, 0x24, 0x17, 0x81, 0xc4, 0x14, 0x33, 0xb4, 0x64, + 0xe3, 0x40, 0x4e, 0x59, 0x1e, 0x9e, 0xef, 0x8f, 0xf2, 0xfc, 0x1d, 0xcd, 0x17, 0xa9, 0xdc, 0x27, 0x7b, 0x2d, 0xcc, + 0xf6, 0x08, 0x61, 0x12, 0xc9, 0xa9, 0xe0, 0xd7, 0xde, 0x0b, 0x21, 0xb8, 0x08, 0xfc, 0xd3, 0xb3, 0x33, 0xdd, 0xc2, + 0x63, 0xb9, 0x97, 0x71, 0xe9, 0x95, 0xe3, 0xc5, 0x97, 0x29, 0x0d, 0xbd, 0x0f, 0x39, 0xf5, 0x2e, 0x16, 0x59, 0x1e, + 0x8f, 0xe9, 0xe9, 0xd9, 0xd9, 0x85, 0xc7, 0x85, 0x77, 0x31, 0xca, 0xf3, 0x0b, 0x8f, 0x65, 0xb9, 0xa4, 0x71, 0x12, + 0xfa, 0xa8, 0xab, 0x26, 0x1b, 0xe5, 0xf9, 0x7b, 0x7a, 0x23, 0x89, 0xc4, 0xea, 0x51, 0x12, 0x5a, 0x4c, 0xa8, 0xf4, + 0xf2, 0x72, 0x5d, 0x01, 0x5a, 0xa6, 0x54, 0x7a, 0x92, 0xa8, 0x7a, 0xde, 0xd5, 0xb8, 0xa7, 0xfa, 0x51, 0x76, 0xd9, + 0x38, 0xa0, 0xf2, 0xe0, 0x40, 0x96, 0x78, 0x46, 0x7a, 0x69, 0x1e, 0x23, 0x74, 0xcf, 0x96, 0x1d, 0x1c, 0xd0, 0x30, + 0xa5, 0xd9, 0x44, 0x4e, 0x09, 0x21, 0xed, 0x2e, 0x3b, 0x38, 0x08, 0x24, 0x49, 0x65, 0x38, 0xa1, 0x32, 0xa0, 0x08, + 0xe1, 0xaa, 0xf7, 0xc1, 0x41, 0xa0, 0x91, 0xc0, 0x89, 0x46, 0x5c, 0x0d, 0xc7, 0x28, 0x34, 0xd8, 0x3f, 0xbb, 0xcd, + 0x46, 0x81, 0x0b, 0x3f, 0xc2, 0xec, 0xe0, 0x20, 0x95, 0x61, 0x0e, 0x23, 0x62, 0x89, 0x50, 0x21, 0xa8, 0x5c, 0x88, + 0xcc, 0x93, 0x85, 0xe4, 0x67, 0x52, 0xb0, 0x6c, 0x12, 0xa0, 0xa5, 0x2d, 0x73, 0x3a, 0x16, 0x85, 0x06, 0xf7, 0x6b, + 0x49, 0x04, 0xe9, 0xc1, 0x8c, 0x97, 0x32, 0x80, 0x5d, 0xe4, 0x63, 0x4f, 0x10, 0xe2, 0xe7, 0xaa, 0xaf, 0xdf, 0x17, + 0x91, 0x68, 0xf8, 0x3e, 0xd6, 0x50, 0x62, 0x26, 0x11, 0xfe, 0x48, 0x02, 0x81, 0xc3, 0x30, 0x94, 0x88, 0xf4, 0x96, + 0x16, 0x2b, 0xc2, 0x59, 0x67, 0x5f, 0x0c, 0x5a, 0xc3, 0x48, 0x86, 0x82, 0x26, 0x8b, 0x11, 0x0d, 0x02, 0x86, 0x73, + 0x9c, 0x21, 0xd2, 0x63, 0x8d, 0x80, 0x93, 0x1e, 0x6c, 0x37, 0xaf, 0xef, 0x35, 0x21, 0x7b, 0x2d, 0x64, 0x60, 0xe4, + 0x16, 0x40, 0xc0, 0xb0, 0x81, 0x87, 0x13, 0xe2, 0x67, 0x8b, 0xd9, 0x25, 0x15, 0x7e, 0xd9, 0xac, 0x5b, 0x23, 0x8b, + 0x45, 0x4e, 0xbd, 0x51, 0x9e, 0x7b, 0xe3, 0x45, 0x36, 0x92, 0x8c, 0x67, 0x9e, 0xdf, 0xe0, 0x0d, 0x5f, 0x93, 0x43, + 0x49, 0x0d, 0x3e, 0x2a, 0x50, 0x90, 0xa3, 0x86, 0x18, 0x64, 0x8d, 0xf6, 0x10, 0x03, 0x94, 0xa8, 0x6b, 0xc6, 0x33, + 0x08, 0xa0, 0x58, 0xc0, 0x1a, 0x0b, 0xfc, 0x41, 0xc2, 0x2a, 0xd5, 0x12, 0xa9, 0xec, 0x8b, 0x70, 0xf3, 0xa0, 0x10, + 0x19, 0xce, 0xe2, 0x79, 0x40, 0x49, 0x8f, 0x2a, 0xe2, 0x8a, 0xb3, 0x11, 0xc0, 0x5a, 0xdb, 0xb7, 0x3e, 0x8d, 0x68, + 0x58, 0x91, 0x14, 0x8a, 0x64, 0x38, 0xe6, 0xe2, 0x45, 0x3c, 0x9a, 0x42, 0xbf, 0x92, 0x60, 0x12, 0x7b, 0xde, 0x46, + 0x82, 0xc6, 0x92, 0xbe, 0x48, 0x29, 0x3c, 0x05, 0xbe, 0xea, 0xe9, 0x23, 0x9c, 0x93, 0x57, 0x61, 0xca, 0xe4, 0x1b, + 0x9e, 0x8d, 0x68, 0x37, 0x77, 0xa8, 0x8b, 0xc1, 0xbe, 0x9f, 0x48, 0x29, 0xd8, 0xe5, 0x42, 0xd2, 0xc0, 0xcf, 0xa0, + 0x85, 0x8f, 0x73, 0x84, 0x59, 0x28, 0xe9, 0x8d, 0x3c, 0xe5, 0x99, 0xa4, 0x99, 0x24, 0xd4, 0x22, 0x15, 0x8b, 0x30, + 0x9e, 0xcf, 0x69, 0x96, 0x9c, 0x4e, 0x59, 0x9a, 0x04, 0x0c, 0x15, 0xa8, 0xc0, 0xb1, 0x24, 0xb0, 0x46, 0xd2, 0x13, + 0x11, 0xfc, 0xb3, 0x7b, 0x35, 0x81, 0x24, 0x3d, 0x75, 0x28, 0x28, 0xf1, 0xfd, 0xee, 0x98, 0x8b, 0xc0, 0xac, 0xc0, + 0xe3, 0x63, 0x4f, 0xc2, 0x1c, 0xef, 0x16, 0x29, 0xcd, 0x11, 0x6d, 0x10, 0x56, 0x6e, 0xa3, 0x41, 0xf0, 0xd7, 0x40, + 0xf1, 0x05, 0x0a, 0x04, 0x8a, 0x44, 0xf7, 0x2a, 0x16, 0xde, 0x17, 0xe6, 0x44, 0xfd, 0x64, 0xb9, 0xd9, 0x54, 0x92, + 0x9f, 0x42, 0x29, 0x16, 0xb9, 0xa4, 0xc9, 0xfb, 0xdb, 0x39, 0xcd, 0xf1, 0x4b, 0x49, 0xa6, 0xb2, 0x3f, 0x95, 0x21, + 0x9d, 0xcd, 0xe5, 0xed, 0x99, 0x62, 0x8c, 0x91, 0xef, 0xe3, 0x11, 0xb4, 0x14, 0x34, 0x1e, 0x01, 0x33, 0x33, 0xd8, + 0xfa, 0x9a, 0xa7, 0xb7, 0x63, 0x96, 0xa6, 0x67, 0x8b, 0xf9, 0x9c, 0x0b, 0x89, 0xff, 0x4a, 0x96, 0x92, 0x57, 0xa8, + 0x81, 0xbd, 0x5c, 0xe6, 0xd7, 0x4c, 0x8e, 0xa6, 0x81, 0x44, 0xcb, 0x51, 0x9c, 0x53, 0xef, 0x19, 0xe7, 0x29, 0x8d, + 0xb3, 0x48, 0x10, 0xd1, 0x7f, 0x29, 0xa3, 0x6c, 0x91, 0xa6, 0xdd, 0x4b, 0x41, 0xe3, 0x8f, 0x5d, 0x55, 0xfd, 0xf6, + 0xf2, 0x27, 0x3a, 0x92, 0x91, 0xfa, 0x7d, 0x22, 0x44, 0x7c, 0x0b, 0x0d, 0x09, 0x81, 0x66, 0x7d, 0x11, 0x7d, 0x75, + 0xf6, 0xf6, 0x4d, 0xa8, 0x0f, 0x09, 0x1b, 0xdf, 0x06, 0xa2, 0x3c, 0x78, 0xa2, 0xc0, 0x63, 0xc1, 0x67, 0x6b, 0x53, + 0x6b, 0xac, 0x89, 0xee, 0x0e, 0x10, 0x28, 0x11, 0x7b, 0x7a, 0x68, 0x17, 0x82, 0x37, 0x8a, 0xe6, 0xa1, 0x92, 0x98, + 0x79, 0xe1, 0x9f, 0x48, 0x17, 0x07, 0x02, 0xdd, 0x0d, 0xad, 0x14, 0xb7, 0x4b, 0x4a, 0x14, 0x9c, 0x73, 0x90, 0x30, + 0x00, 0xe3, 0x28, 0x96, 0xa3, 0xe9, 0x92, 0xaa, 0xc1, 0x0a, 0x0b, 0x31, 0x2d, 0x0a, 0x7c, 0x5d, 0xd2, 0xbb, 0xdc, + 0x23, 0x44, 0x28, 0x46, 0x45, 0xe4, 0x6a, 0x25, 0x08, 0x11, 0x08, 0x7f, 0x47, 0x96, 0xb1, 0x5d, 0x4f, 0xb4, 0xd7, + 0xc2, 0x70, 0x2e, 0x23, 0xcd, 0x5d, 0xf0, 0x88, 0x67, 0x57, 0x54, 0x48, 0x2a, 0xa2, 0xbf, 0x62, 0x41, 0xc7, 0x29, + 0x40, 0xb1, 0xd7, 0xc6, 0xd3, 0x38, 0x3f, 0x9d, 0xc6, 0xd9, 0x84, 0x26, 0xd1, 0xb5, 0x2c, 0xf0, 0xdf, 0x89, 0x3f, + 0x66, 0x59, 0x9c, 0xb2, 0x5f, 0x68, 0xe2, 0x1b, 0x69, 0x70, 0xe2, 0xd1, 0x1b, 0x49, 0xb3, 0x24, 0xf7, 0x5e, 0xbe, + 0x7f, 0xfd, 0xca, 0xec, 0x63, 0x4d, 0x40, 0xa0, 0x65, 0xbe, 0x98, 0x53, 0x11, 0x20, 0x6c, 0x04, 0xc4, 0x0b, 0xa6, + 0x98, 0xe3, 0xeb, 0x78, 0xae, 0x4b, 0x58, 0xfe, 0x61, 0x9e, 0xc4, 0x92, 0x7e, 0x4d, 0xb3, 0x84, 0x65, 0x13, 0xb2, + 0xd7, 0xd6, 0xe5, 0xd3, 0xd8, 0x54, 0x24, 0x65, 0xd1, 0xf9, 0xfe, 0x8b, 0x54, 0xad, 0xbb, 0x7c, 0x5c, 0x04, 0xa8, + 0xc8, 0x65, 0x2c, 0xd9, 0xc8, 0x8b, 0x93, 0xe4, 0xcb, 0x8c, 0x49, 0xa6, 0x00, 0x14, 0xb0, 0x3d, 0x40, 0xa2, 0x54, + 0x8b, 0x0a, 0x0b, 0x78, 0x80, 0x70, 0x10, 0x18, 0x01, 0x30, 0x45, 0x66, 0xbf, 0x0e, 0x0e, 0x2a, 0x76, 0xdf, 0xa7, + 0x91, 0xae, 0x24, 0x83, 0x21, 0x0a, 0xe7, 0x8b, 0x1c, 0x36, 0xda, 0x4e, 0x01, 0xd2, 0x85, 0x5f, 0xe6, 0x54, 0x5c, + 0xd1, 0xa4, 0x24, 0x8e, 0x3c, 0x40, 0xcb, 0xb5, 0x39, 0xcc, 0xb1, 0x90, 0x64, 0x30, 0xec, 0xba, 0x7c, 0x9b, 0x1a, + 0x3a, 0x17, 0x7c, 0x4e, 0x85, 0x64, 0x34, 0x2f, 0x59, 0x49, 0x00, 0x52, 0xb4, 0x64, 0x27, 0x39, 0xb1, 0xeb, 0x9b, + 0x07, 0x0c, 0x53, 0x54, 0x63, 0x18, 0x56, 0xd0, 0xbe, 0xb8, 0x52, 0x12, 0x23, 0xc7, 0x0c, 0x61, 0xa9, 0x21, 0xcd, + 0x11, 0x2a, 0x10, 0x96, 0x16, 0x5c, 0xcd, 0x8a, 0xcc, 0x6c, 0xb7, 0x20, 0xaa, 0xc9, 0x77, 0x4a, 0x54, 0x03, 0x43, + 0x8b, 0x25, 0x3d, 0x38, 0x08, 0x68, 0x58, 0x12, 0x05, 0xd9, 0x6b, 0x9b, 0x3d, 0x72, 0x90, 0xb5, 0x03, 0x6c, 0x98, + 0x58, 0x62, 0x8a, 0xf0, 0x1e, 0x0d, 0x33, 0x7e, 0x32, 0x1a, 0xd1, 0x3c, 0xe7, 0xe2, 0xe0, 0x60, 0x4f, 0xb5, 0x2f, + 0xb5, 0x09, 0xd8, 0xc3, 0xb7, 0xd7, 0x59, 0x05, 0x01, 0xaa, 0x24, 0xac, 0x91, 0x0b, 0x12, 0xe4, 0x94, 0x52, 0x38, + 0xfc, 0xbe, 0x55, 0x3c, 0x22, 0xff, 0xfc, 0xdc, 0x6f, 0x48, 0x6c, 0xd0, 0x30, 0xa1, 0x76, 0xea, 0xdb, 0xe7, 0x54, + 0xab, 0x56, 0x4a, 0xf1, 0xd8, 0xc0, 0x8c, 0x3e, 0x3f, 0x61, 0x42, 0xc7, 0x2c, 0x73, 0x96, 0x5d, 0x03, 0x09, 0x4b, + 0x9c, 0xa3, 0xc2, 0xd9, 0xd0, 0xad, 0x43, 0x2b, 0x9d, 0x46, 0xef, 0xdc, 0x72, 0xa2, 0xf4, 0x08, 0x67, 0x1b, 0x07, + 0x74, 0x58, 0x60, 0x85, 0x7a, 0xbb, 0x9a, 0x4c, 0x01, 0x3a, 0x90, 0xc3, 0xae, 0xa9, 0x27, 0xb9, 0xc6, 0x9c, 0xa0, + 0x3f, 0x2f, 0x68, 0x2e, 0x35, 0x1d, 0x07, 0x12, 0x67, 0x98, 0xa1, 0x02, 0x8e, 0xdb, 0x98, 0x4d, 0x16, 0x02, 0xd4, + 0x1d, 0x38, 0x8a, 0x34, 0x5b, 0xcc, 0xa8, 0x7d, 0xda, 0x06, 0xdb, 0xdb, 0x39, 0x08, 0xc4, 0x1c, 0x68, 0xfa, 0x6e, + 0x72, 0x02, 0x58, 0x25, 0x5a, 0xad, 0xbe, 0xb3, 0x83, 0x54, 0x5b, 0x59, 0xaa, 0x68, 0x6b, 0x7b, 0xf2, 0x77, 0x64, + 0xe4, 0xf1, 0x5e, 0x5b, 0x43, 0xff, 0xf7, 0x21, 0xd9, 0x6b, 0x95, 0x14, 0x6c, 0x70, 0xaa, 0x81, 0xd1, 0x28, 0x7c, + 0xab, 0x07, 0x42, 0x4a, 0xba, 0xd7, 0x88, 0x25, 0x9c, 0x6e, 0xd0, 0xe9, 0x94, 0x0c, 0x40, 0xcf, 0x08, 0xa7, 0xc3, + 0x5d, 0xc4, 0x64, 0xb9, 0x41, 0x20, 0x37, 0xeb, 0x2a, 0xa6, 0x71, 0x55, 0x67, 0x1a, 0x6b, 0x8b, 0xf0, 0xe7, 0x65, + 0x17, 0xbf, 0xa4, 0x31, 0x73, 0xcc, 0xab, 0x2a, 0xcc, 0x14, 0x30, 0xd5, 0x92, 0x9c, 0x21, 0xde, 0xc4, 0x33, 0x9a, + 0x07, 0x14, 0xe1, 0x5d, 0x0d, 0x34, 0x71, 0x42, 0x93, 0xa1, 0x23, 0x36, 0x73, 0x10, 0x9b, 0x0c, 0x69, 0xad, 0xac, + 0x7e, 0xdc, 0x72, 0x4c, 0x07, 0xf9, 0xb0, 0x52, 0xe6, 0x9c, 0xc5, 0x2b, 0x79, 0x6c, 0xa8, 0xdb, 0xe2, 0x4f, 0x97, + 0x69, 0xa4, 0x29, 0xa5, 0x21, 0x47, 0x78, 0xaf, 0xb5, 0xbe, 0x8f, 0xb6, 0x55, 0xb5, 0xc6, 0xc1, 0x10, 0xf6, 0x41, + 0x89, 0x8b, 0x90, 0xe5, 0xea, 0xff, 0xda, 0x39, 0x03, 0xb4, 0x9d, 0x01, 0x59, 0x84, 0xe3, 0x34, 0x96, 0x41, 0xfb, + 0xb0, 0x05, 0x9a, 0xe8, 0x15, 0x05, 0x69, 0x82, 0xd0, 0xe6, 0x52, 0x68, 0xb8, 0xc8, 0xf2, 0x29, 0x1b, 0xcb, 0x20, + 0x96, 0x8a, 0xa1, 0xd0, 0x34, 0xa7, 0x9e, 0xac, 0xe9, 0xc3, 0x8a, 0xd9, 0xc4, 0x40, 0x6a, 0xa5, 0xf2, 0x45, 0x2d, + 0xa4, 0x8a, 0x69, 0x01, 0x6f, 0xa8, 0x74, 0xe9, 0x8a, 0xc7, 0xd8, 0xd6, 0x0c, 0xf4, 0xc5, 0x76, 0x5f, 0x8f, 0x18, + 0x19, 0x56, 0xc0, 0x1c, 0x95, 0x95, 0x45, 0x2e, 0x7f, 0x30, 0x85, 0x32, 0x94, 0xfc, 0x15, 0xbf, 0xa6, 0xe2, 0x34, + 0x06, 0xe0, 0x23, 0xdd, 0xbd, 0xd0, 0x62, 0x40, 0x71, 0x7b, 0xd9, 0xb5, 0xf4, 0x72, 0xae, 0x16, 0xfe, 0xb5, 0xe0, + 0x33, 0x96, 0x53, 0xd0, 0xd4, 0x34, 0xfe, 0x33, 0x38, 0x65, 0xea, 0x38, 0x82, 0xa8, 0xa1, 0x25, 0x7d, 0x9d, 0xbc, + 0xaa, 0xd3, 0xd7, 0xf9, 0xfe, 0x8b, 0x89, 0x65, 0x7f, 0xf5, 0x43, 0x8c, 0x70, 0x60, 0xec, 0x09, 0x47, 0xca, 0x85, + 0x53, 0x64, 0xc4, 0xfb, 0x6a, 0x25, 0x1d, 0xb3, 0xad, 0xa6, 0x2b, 0x52, 0x7d, 0x6c, 0x50, 0x11, 0x27, 0x09, 0x68, + 0x75, 0x82, 0xa7, 0xa9, 0x23, 0xa8, 0x30, 0xeb, 0x96, 0xa2, 0xe9, 0x7c, 0xff, 0xc5, 0xd9, 0x5d, 0xd2, 0x09, 0xea, + 0x5d, 0x01, 0x65, 0x01, 0xcd, 0x12, 0x2a, 0xc0, 0x8c, 0x74, 0x76, 0xcb, 0xc8, 0xd8, 0x53, 0x9e, 0x65, 0x74, 0x24, + 0x69, 0x02, 0x56, 0x0a, 0x23, 0x32, 0x9c, 0xf2, 0x5c, 0x96, 0x85, 0x15, 0xf4, 0xcc, 0x81, 0x9e, 0x85, 0xa3, 0x38, + 0x4d, 0x03, 0x6d, 0x91, 0xcc, 0xf8, 0x15, 0xdd, 0x02, 0x75, 0xb7, 0x06, 0x72, 0x39, 0x0c, 0x75, 0x86, 0xa1, 0x61, + 0x3e, 0x4f, 0xd9, 0x88, 0x96, 0x82, 0xeb, 0x2c, 0x64, 0x59, 0x42, 0x6f, 0x80, 0x8f, 0xa0, 0x5e, 0xaf, 0xd7, 0xc2, + 0x6d, 0x54, 0x68, 0x84, 0x2f, 0x37, 0x10, 0x7b, 0x87, 0xc8, 0x04, 0x22, 0x23, 0xbd, 0xe5, 0x36, 0x7e, 0x40, 0x91, + 0x23, 0x27, 0x99, 0xb5, 0xac, 0x34, 0x6f, 0x46, 0x38, 0xa1, 0x29, 0x95, 0xd4, 0xf2, 0x72, 0xd0, 0x9f, 0xf5, 0xd1, + 0x7d, 0x57, 0xe2, 0xaf, 0x24, 0x27, 0x7b, 0xca, 0xec, 0x9e, 0xe7, 0xa5, 0xa5, 0x5e, 0x6d, 0x4f, 0x85, 0xed, 0xbe, + 0xd4, 0xdb, 0x13, 0x4b, 0x19, 0x8f, 0xa6, 0xda, 0x44, 0x0f, 0x36, 0x96, 0x54, 0x8d, 0x61, 0xf8, 0x7a, 0x79, 0x88, + 0x3e, 0x58, 0x30, 0xb7, 0xa1, 0xe0, 0xcc, 0x30, 0x05, 0x0a, 0x56, 0x9f, 0xde, 0xb6, 0xd3, 0x38, 0x4d, 0x2f, 0xe3, + 0xd1, 0xc7, 0x3a, 0xf5, 0x57, 0x64, 0x40, 0xd6, 0xb9, 0xb1, 0x53, 0xe5, 0xb0, 0x2c, 0x77, 0xdd, 0x96, 0x4b, 0xd7, + 0x0e, 0x4a, 0xb0, 0xd7, 0xaa, 0xc8, 0xbe, 0xbe, 0xd1, 0x3b, 0xa9, 0x5d, 0x41, 0xc4, 0xcc, 0xca, 0x02, 0xe0, 0x02, + 0x9f, 0xa4, 0x38, 0xcb, 0x0f, 0x0c, 0xdd, 0x81, 0xad, 0x51, 0xac, 0x01, 0x22, 0xd1, 0xb2, 0x48, 0x58, 0xbe, 0x1b, + 0x03, 0x7f, 0x08, 0x94, 0xcf, 0x9d, 0x19, 0xee, 0x0b, 0x68, 0xc9, 0xe3, 0x8c, 0xca, 0x5c, 0x42, 0x66, 0xb4, 0x09, + 0xcb, 0x68, 0xfe, 0x06, 0x9a, 0x8b, 0xa2, 0xf7, 0xb7, 0xba, 0x0a, 0x74, 0x32, 0x80, 0x22, 0xef, 0xba, 0xca, 0x44, + 0x8d, 0x02, 0x0c, 0x4f, 0x65, 0x4a, 0xe4, 0x66, 0x35, 0xe3, 0xd1, 0xa8, 0xeb, 0xda, 0xfe, 0x36, 0x2c, 0x97, 0x93, + 0x20, 0x08, 0x72, 0xb0, 0xdf, 0xac, 0x5e, 0x5f, 0x2d, 0x22, 0xdf, 0x58, 0x44, 0x1e, 0x3a, 0x46, 0x16, 0xaa, 0x68, + 0xd9, 0xe9, 0x1e, 0xfd, 0x15, 0xb9, 0x8d, 0x40, 0x59, 0x0d, 0x81, 0x3f, 0xa3, 0x92, 0xdd, 0xa6, 0x44, 0x62, 0x6e, + 0x0c, 0x1c, 0x43, 0x69, 0xc0, 0x30, 0xaa, 0x2e, 0x19, 0xd2, 0x47, 0xa3, 0x66, 0xec, 0x66, 0x98, 0xa3, 0x35, 0xcd, + 0xbe, 0x28, 0x0c, 0x8e, 0x28, 0x32, 0x7b, 0x53, 0x53, 0x89, 0x1d, 0xac, 0xe0, 0x8c, 0x18, 0x35, 0x58, 0x6b, 0x3d, + 0xeb, 0xb8, 0x29, 0xc7, 0x85, 0x83, 0x5a, 0xa1, 0xa6, 0xa6, 0x4f, 0x5a, 0xc5, 0x2a, 0x43, 0x78, 0x6a, 0x35, 0x52, + 0x5e, 0xad, 0x9b, 0x10, 0xdf, 0x7a, 0x23, 0xfc, 0xfe, 0xb2, 0x66, 0x12, 0x46, 0x4e, 0xb3, 0x22, 0x02, 0x96, 0xca, + 0xb7, 0xa1, 0x7b, 0x1b, 0xcd, 0xd4, 0xc6, 0x71, 0x10, 0xce, 0x5d, 0x84, 0x3b, 0x98, 0xcd, 0x34, 0xe7, 0xca, 0x86, + 0x64, 0x5a, 0xef, 0x1b, 0x50, 0xcc, 0xf5, 0x3e, 0x6c, 0x20, 0x71, 0x5d, 0xf1, 0x54, 0x24, 0x08, 0x06, 0x6c, 0x0e, + 0xca, 0x9d, 0x2b, 0x1f, 0x02, 0x80, 0x9d, 0xad, 0x56, 0x1b, 0x44, 0xb7, 0x55, 0xff, 0x44, 0x61, 0x65, 0x14, 0xae, + 0x56, 0xd7, 0x12, 0x05, 0x46, 0xf3, 0xc5, 0x14, 0xf5, 0x2d, 0xc7, 0x3d, 0x79, 0x05, 0xad, 0x94, 0x22, 0x5a, 0x95, + 0x94, 0x26, 0x43, 0x9d, 0x66, 0xeb, 0xfb, 0x24, 0x1d, 0xb6, 0x7d, 0xba, 0xc1, 0xbd, 0x54, 0xa1, 0x11, 0xd3, 0xd5, + 0x92, 0x4f, 0xcd, 0xd0, 0x0c, 0x21, 0x14, 0xe5, 0xca, 0x8a, 0xd9, 0xdb, 0x66, 0x58, 0x1e, 0x1c, 0xe4, 0xce, 0x40, + 0xe7, 0x25, 0x9b, 0xf8, 0x29, 0x00, 0x91, 0x9c, 0xdf, 0x66, 0x4a, 0x77, 0xf9, 0xc9, 0x0a, 0xa1, 0x0d, 0xb3, 0xb4, + 0xd5, 0x05, 0x6b, 0x3c, 0xbe, 0x8e, 0x99, 0xf4, 0xca, 0x51, 0xb4, 0x35, 0x1e, 0x50, 0xb4, 0x34, 0xaa, 0x46, 0x28, + 0x28, 0x28, 0x8f, 0xc0, 0x13, 0xac, 0x0a, 0xad, 0xe9, 0x7e, 0x34, 0xa5, 0xe0, 0x08, 0xb6, 0x5a, 0x44, 0x69, 0x17, + 0xee, 0x19, 0x29, 0x62, 0x06, 0xde, 0x0e, 0x7b, 0xb1, 0xde, 0xbd, 0x66, 0x07, 0xcc, 0xa9, 0x18, 0x73, 0x31, 0xb3, + 0x75, 0xc5, 0xda, 0xb3, 0xe1, 0x8c, 0x6c, 0x1c, 0x6c, 0x1d, 0xdb, 0xa8, 0xff, 0xdd, 0x35, 0xa3, 0xbb, 0x32, 0xd7, + 0x6b, 0xa2, 0xb4, 0x94, 0xbe, 0xda, 0x1f, 0x68, 0x29, 0x33, 0x77, 0xcd, 0x7b, 0xe3, 0x4c, 0xed, 0x6a, 0x87, 0xc9, + 0x5e, 0xbb, 0x5b, 0xda, 0x7c, 0x96, 0x1a, 0xba, 0xda, 0xb1, 0x61, 0x44, 0x2a, 0x5f, 0xa4, 0x89, 0x01, 0x96, 0x21, + 0x4c, 0x0d, 0x1d, 0x5d, 0xb3, 0x34, 0xad, 0x4a, 0x7f, 0x0d, 0x5f, 0xcf, 0x0d, 0x5f, 0xcf, 0x2c, 0x5f, 0x07, 0x4e, + 0x01, 0x7c, 0x5d, 0x0f, 0x57, 0x75, 0xcf, 0x36, 0x4e, 0x67, 0xa6, 0x39, 0x7a, 0xae, 0xec, 0x68, 0x98, 0x6f, 0x61, + 0x21, 0x40, 0xa5, 0xe6, 0xf5, 0x31, 0x30, 0x4e, 0x18, 0x30, 0x00, 0xb5, 0x0b, 0x93, 0xba, 0x2e, 0x8a, 0x8f, 0x01, + 0xc2, 0x79, 0x41, 0x4b, 0xca, 0x3e, 0x79, 0x01, 0x4e, 0x3a, 0x67, 0x39, 0x20, 0xc4, 0x54, 0xf1, 0xaf, 0x52, 0xa2, + 0xec, 0xea, 0x98, 0x59, 0x5d, 0x6e, 0x57, 0x07, 0x9c, 0xbe, 0x5a, 0x5d, 0x72, 0x37, 0xaf, 0x57, 0xcb, 0x63, 0xe5, + 0xf2, 0xaa, 0xfd, 0x5e, 0xad, 0x82, 0xb5, 0x12, 0xf0, 0xdf, 0x1b, 0x13, 0x45, 0x94, 0xa3, 0x03, 0x0f, 0x70, 0x31, + 0x03, 0x05, 0x85, 0x5e, 0x74, 0x29, 0xe2, 0x5e, 0x7d, 0xca, 0xc1, 0xa3, 0xdc, 0xf4, 0xba, 0xff, 0x29, 0x9f, 0xcd, + 0x41, 0x1b, 0x5b, 0x23, 0xe9, 0x09, 0x35, 0x13, 0x56, 0xf5, 0xc5, 0x96, 0xb2, 0x5a, 0x1f, 0x75, 0x1e, 0x6b, 0xd4, + 0x54, 0xda, 0xcb, 0x7b, 0xad, 0x62, 0x51, 0x16, 0x95, 0x8c, 0x63, 0x9b, 0x53, 0xe5, 0x74, 0xdd, 0x25, 0x63, 0x2b, + 0xde, 0x06, 0x4c, 0xf3, 0x61, 0x06, 0xbc, 0xce, 0x61, 0x3f, 0x96, 0xdc, 0xdd, 0xfd, 0x2f, 0x2a, 0xe4, 0x2c, 0x8b, + 0x35, 0xf4, 0x2d, 0x8b, 0xe2, 0x44, 0x1b, 0xd9, 0xf8, 0x64, 0xb7, 0x35, 0x5c, 0xd5, 0x19, 0x63, 0x71, 0x30, 0xc4, + 0x27, 0x9b, 0xaa, 0x23, 0x59, 0xce, 0x78, 0x42, 0x23, 0x9f, 0xcf, 0x69, 0xe6, 0x17, 0xe0, 0x55, 0x35, 0x7b, 0x3f, + 0x92, 0xc1, 0xf2, 0x5d, 0xdd, 0xbd, 0x1a, 0x9d, 0x14, 0xe0, 0xfd, 0xfa, 0x62, 0xd3, 0xf1, 0xfa, 0x2d, 0x15, 0xb9, + 0x52, 0x44, 0x4b, 0x9d, 0xf6, 0x8b, 0x4a, 0x2c, 0x7d, 0x11, 0xed, 0x6c, 0x5f, 0x99, 0x20, 0x7e, 0x3b, 0x7c, 0x1c, + 0x1e, 0xf9, 0x48, 0xb9, 0x85, 0xbf, 0x32, 0x07, 0xfe, 0xb9, 0x75, 0x0b, 0xbf, 0x20, 0xcf, 0xeb, 0x5e, 0xe1, 0x44, + 0x92, 0x17, 0xfd, 0x17, 0xd6, 0x62, 0xe6, 0x29, 0x1b, 0xdd, 0x06, 0x7e, 0xca, 0x64, 0x13, 0x42, 0x6f, 0x3e, 0x5e, + 0xea, 0x0a, 0x70, 0x29, 0x2a, 0x77, 0x76, 0x61, 0x6d, 0x3d, 0x2c, 0x25, 0xf1, 0xf7, 0x53, 0x26, 0xf7, 0x7d, 0x3c, + 0x23, 0x17, 0xf0, 0x63, 0x7f, 0x19, 0xbc, 0x8e, 0xe5, 0x34, 0x14, 0x71, 0x96, 0xf0, 0x59, 0x80, 0x1a, 0xbe, 0x8f, + 0xc2, 0x5c, 0xd9, 0x1b, 0x9f, 0xa3, 0x62, 0xff, 0x02, 0xdf, 0x48, 0xe2, 0xf7, 0xfd, 0xc6, 0x0c, 0xbf, 0x91, 0xe4, + 0xe2, 0x78, 0x7f, 0x79, 0x23, 0x8b, 0xde, 0x05, 0xbe, 0x29, 0x3d, 0xf6, 0xf8, 0x6b, 0x12, 0x20, 0xd2, 0xbb, 0x31, + 0xd0, 0x9c, 0xf2, 0x99, 0xf6, 0xdc, 0xfb, 0x08, 0x7f, 0x80, 0xb8, 0x8a, 0xa8, 0xb8, 0x8d, 0x09, 0xad, 0xec, 0x11, + 0x9f, 0x2b, 0x17, 0x81, 0x7f, 0x70, 0xe0, 0x94, 0x95, 0xaa, 0x02, 0x3e, 0x91, 0xa4, 0x66, 0x90, 0xe3, 0xf7, 0x2a, + 0x42, 0x73, 0x22, 0x03, 0x81, 0xec, 0x30, 0x81, 0xf5, 0x43, 0x9b, 0xa3, 0x29, 0x06, 0xda, 0xc3, 0x10, 0x32, 0x49, + 0x45, 0x2c, 0xb9, 0x18, 0x22, 0x57, 0xfd, 0xc0, 0x7f, 0x23, 0x17, 0x03, 0xef, 0x3f, 0xfd, 0xd3, 0x8f, 0xe3, 0x1f, + 0xc5, 0xf0, 0x02, 0xbf, 0x25, 0x87, 0xc7, 0x41, 0x3f, 0x0a, 0xf6, 0x9a, 0xcd, 0xd5, 0x8f, 0x87, 0x83, 0x7f, 0xc4, + 0xcd, 0x5f, 0x4e, 0x9a, 0x3f, 0x0c, 0xd1, 0x2a, 0xf8, 0xf1, 0xb0, 0x3f, 0x30, 0x4f, 0x83, 0x7f, 0xf4, 0x7e, 0xcc, + 0x87, 0x7f, 0xd6, 0x85, 0xfb, 0x08, 0x1d, 0x4e, 0xf0, 0x42, 0x92, 0xc3, 0x66, 0xb3, 0x77, 0x38, 0xc1, 0x73, 0x49, + 0x0e, 0xe1, 0xff, 0x4b, 0xf2, 0x8e, 0x4e, 0x5e, 0xdc, 0xcc, 0x83, 0x8b, 0xde, 0x6a, 0x7f, 0xf9, 0xb7, 0x02, 0x46, + 0x1d, 0xfc, 0xe3, 0xc7, 0x1f, 0x73, 0xff, 0x41, 0x8f, 0x1c, 0x0e, 0x1b, 0x28, 0x80, 0xd2, 0x3f, 0x13, 0xf5, 0x6f, + 0xd0, 0x8f, 0x06, 0xff, 0x30, 0x50, 0xf8, 0x0f, 0x7e, 0xbc, 0x38, 0xee, 0x91, 0xe1, 0x2a, 0xf0, 0x57, 0x0f, 0xd0, + 0x0a, 0xa1, 0xd5, 0x3e, 0xba, 0xc0, 0xfe, 0xc4, 0x47, 0x78, 0x22, 0xc9, 0xe1, 0x83, 0xc3, 0x09, 0xbe, 0x92, 0xe4, + 0xd0, 0x3f, 0x9c, 0xe0, 0x17, 0x92, 0x1c, 0xfe, 0x23, 0xe8, 0x47, 0xda, 0xc3, 0xb6, 0x52, 0xee, 0x8d, 0x15, 0x04, + 0x37, 0x62, 0x41, 0xe3, 0x95, 0x64, 0x32, 0xa5, 0x68, 0xff, 0x90, 0xe1, 0x33, 0x85, 0xa6, 0x40, 0x82, 0x13, 0x06, + 0x6c, 0xbb, 0x60, 0x79, 0x0e, 0x9b, 0x0d, 0x34, 0xb3, 0x1f, 0x09, 0xac, 0xfd, 0x00, 0x79, 0x24, 0xf1, 0x55, 0x9c, + 0x2e, 0x68, 0x1e, 0xd1, 0x02, 0xe1, 0x11, 0x39, 0x93, 0x41, 0x1b, 0xe1, 0x77, 0x12, 0x7e, 0x74, 0x10, 0x3e, 0x33, + 0x01, 0x4c, 0x38, 0xc8, 0x9a, 0xa8, 0x32, 0xae, 0x35, 0x16, 0x1f, 0xe1, 0xf9, 0x96, 0x4a, 0x39, 0x05, 0xef, 0x02, + 0xc2, 0xe3, 0x5a, 0xb8, 0x13, 0x5f, 0x13, 0x4b, 0x12, 0xef, 0x05, 0xa5, 0xdf, 0xc5, 0xe9, 0x47, 0x2a, 0x82, 0x1b, + 0xdc, 0xee, 0x7c, 0x8e, 0x95, 0x0b, 0x7a, 0xaf, 0x8d, 0xba, 0x65, 0xac, 0xea, 0x54, 0xea, 0x18, 0x01, 0x08, 0xd9, + 0xba, 0x2f, 0x06, 0x76, 0x7c, 0x4f, 0x6c, 0x38, 0xac, 0x44, 0x7c, 0xed, 0xa3, 0x7a, 0x5c, 0x94, 0x65, 0x57, 0x71, + 0xca, 0x12, 0x4f, 0xd2, 0xd9, 0x3c, 0x8d, 0x25, 0xf5, 0xcc, 0x7a, 0xbd, 0x18, 0x06, 0xf2, 0x4b, 0x95, 0x21, 0x71, + 0x0c, 0xce, 0xc4, 0x06, 0x9c, 0xe0, 0xac, 0x04, 0x10, 0x9d, 0x32, 0x6a, 0xc7, 0xeb, 0x2a, 0xf8, 0xb5, 0x1e, 0xdf, + 0x6b, 0xb6, 0xc1, 0x11, 0x36, 0x54, 0xe2, 0x39, 0xc7, 0x19, 0x01, 0x21, 0xda, 0xe9, 0xfb, 0xc7, 0xf9, 0xd5, 0xa4, + 0xe7, 0x43, 0x6c, 0x86, 0x93, 0xb7, 0xca, 0x2f, 0x04, 0x0d, 0xa6, 0xa4, 0xd5, 0x9d, 0x1e, 0xd3, 0xee, 0xb4, 0xd1, + 0xb0, 0x3a, 0x74, 0x4a, 0xc4, 0x60, 0xaa, 0xbb, 0xc7, 0x38, 0xc1, 0x0b, 0xd2, 0x6c, 0xe3, 0x09, 0x69, 0xa9, 0x2e, + 0xdd, 0xc9, 0x71, 0x6a, 0xa6, 0x39, 0x38, 0x08, 0x78, 0x98, 0xc6, 0xb9, 0xfc, 0x12, 0x8c, 0x7d, 0x32, 0xc1, 0x09, + 0xe1, 0x21, 0xbd, 0xa1, 0xa3, 0x20, 0x45, 0x38, 0x31, 0x9c, 0x06, 0x75, 0xd1, 0x84, 0x38, 0xcd, 0xc0, 0x88, 0x20, + 0x6f, 0xfb, 0xc9, 0xa0, 0x3d, 0x24, 0x84, 0xf8, 0x7b, 0xcd, 0xa6, 0xdf, 0xe7, 0x64, 0x21, 0x23, 0x28, 0x71, 0x54, + 0x65, 0x32, 0x87, 0xa2, 0x8e, 0x53, 0x14, 0xbc, 0x90, 0xa1, 0xa4, 0xb9, 0x0c, 0xa0, 0x18, 0xcc, 0xff, 0xdc, 0x12, + 0xb6, 0x7f, 0x7c, 0xe8, 0x37, 0xa0, 0x54, 0x11, 0x27, 0xc2, 0x9c, 0x5c, 0xa2, 0x28, 0x19, 0x1c, 0x0d, 0x5d, 0xfe, + 0xaf, 0x0a, 0x61, 0xf2, 0xcb, 0x7e, 0x32, 0x68, 0xa9, 0xc9, 0x7b, 0x7e, 0x3f, 0xe0, 0x24, 0xd7, 0x0a, 0x5a, 0x3f, + 0x8f, 0xde, 0xaa, 0xa5, 0xa2, 0xc8, 0x00, 0x67, 0xe6, 0x5d, 0x90, 0x66, 0x27, 0x0a, 0x16, 0xee, 0x22, 0x9a, 0x30, + 0x99, 0xc1, 0x02, 0x8e, 0x09, 0xb4, 0xc7, 0x9c, 0xc0, 0x8c, 0x55, 0xb7, 0xcb, 0xc8, 0x3c, 0x3f, 0xf0, 0x1f, 0xf4, + 0xaf, 0x64, 0x34, 0x91, 0x7a, 0xfa, 0x2b, 0xb9, 0x5a, 0xc1, 0xff, 0x13, 0xd9, 0xe7, 0xe4, 0x52, 0x15, 0x2d, 0x4c, + 0xd1, 0x1c, 0x8a, 0xde, 0x46, 0x00, 0x2a, 0xce, 0x4b, 0x25, 0x4b, 0xef, 0xc9, 0x15, 0x51, 0xb0, 0x1f, 0x1c, 0x88, + 0xc1, 0xb4, 0xd1, 0x1e, 0x82, 0x7f, 0x5f, 0xc8, 0xfc, 0x3b, 0x26, 0xa7, 0x81, 0x7f, 0xd8, 0xf3, 0x51, 0xdf, 0xf7, + 0x60, 0x6b, 0xbb, 0x59, 0x83, 0x68, 0x0c, 0xa7, 0x8d, 0x37, 0x32, 0x5a, 0xf4, 0x48, 0xab, 0x1f, 0x30, 0xe3, 0xcf, + 0x43, 0x38, 0x35, 0x8c, 0xb3, 0x85, 0x17, 0xa8, 0x21, 0x65, 0xc3, 0x3e, 0x2f, 0x50, 0x63, 0xd6, 0xb8, 0x42, 0x51, + 0xda, 0x98, 0x35, 0x82, 0x05, 0x21, 0xa4, 0xd9, 0x29, 0xbb, 0x59, 0xe9, 0x37, 0x45, 0xd1, 0x95, 0x75, 0x76, 0x0e, + 0xd4, 0x71, 0xc8, 0x1a, 0x81, 0x18, 0xd0, 0xe1, 0x6a, 0xe5, 0x1f, 0xf7, 0x7b, 0x3e, 0x6a, 0x04, 0x96, 0xd0, 0x0e, + 0x2d, 0xa5, 0x21, 0x84, 0xd9, 0xb0, 0x30, 0xa1, 0xa4, 0x97, 0xb5, 0xb0, 0xd1, 0xb2, 0x3a, 0xec, 0x0e, 0x0f, 0xa0, + 0x45, 0x69, 0xc7, 0x68, 0x7d, 0x75, 0x0e, 0xcb, 0xb4, 0xc4, 0x9c, 0x91, 0x16, 0xe6, 0xc4, 0xfa, 0xae, 0xa7, 0x44, + 0x56, 0x04, 0x9f, 0x92, 0xaa, 0x39, 0x1e, 0xc4, 0x38, 0x19, 0x92, 0xd7, 0xda, 0x1e, 0xe9, 0x5a, 0xbf, 0x38, 0x4d, + 0xc9, 0xcb, 0xb5, 0xe8, 0x6d, 0x0c, 0xb1, 0x95, 0xeb, 0x70, 0xb4, 0x10, 0x82, 0x66, 0xf2, 0x0d, 0x4f, 0x8c, 0x9a, + 0x46, 0x53, 0xb0, 0x94, 0x20, 0x2c, 0x8b, 0x41, 0x47, 0xeb, 0xd8, 0x93, 0xb1, 0xd8, 0xa8, 0x9e, 0x90, 0x85, 0x56, + 0x9f, 0x54, 0xb0, 0xb6, 0x3b, 0x31, 0x76, 0x71, 0x80, 0xf0, 0xc2, 0x44, 0x71, 0x83, 0x30, 0x0c, 0x27, 0xe1, 0x08, + 0xaa, 0x61, 0x82, 0x1c, 0x15, 0xea, 0x1c, 0x05, 0x39, 0xb9, 0x0e, 0x33, 0x7a, 0xa3, 0x66, 0x0d, 0x50, 0x25, 0x99, + 0xed, 0xf1, 0x3a, 0x9e, 0x76, 0x15, 0xbb, 0xc9, 0xc3, 0x8c, 0x27, 0x14, 0xd0, 0x03, 0x71, 0x7b, 0x53, 0x34, 0x8d, + 0x73, 0x37, 0x3e, 0x55, 0xc1, 0x37, 0x70, 0x9d, 0xd7, 0x13, 0xf0, 0xf8, 0x2a, 0x5d, 0xab, 0x6c, 0xac, 0xdd, 0xe0, + 0x08, 0xb1, 0x71, 0x30, 0x09, 0x21, 0xae, 0xa7, 0x48, 0x48, 0x82, 0x29, 0x37, 0x71, 0x89, 0x6a, 0x56, 0x8e, 0x79, + 0x45, 0x92, 0x01, 0x6f, 0x34, 0x94, 0x17, 0x7a, 0xa1, 0x49, 0x62, 0x82, 0xf0, 0x55, 0x79, 0xb6, 0x6c, 0xbb, 0xb7, + 0x92, 0xd4, 0xa7, 0x0a, 0xae, 0xea, 0xee, 0xdc, 0x86, 0x94, 0x48, 0x79, 0x0a, 0x65, 0x30, 0x43, 0xf8, 0x19, 0x39, + 0x0c, 0x06, 0x61, 0xff, 0x2f, 0x43, 0xd4, 0x0f, 0xc2, 0x3f, 0xa3, 0x43, 0xcd, 0x39, 0xae, 0x50, 0x37, 0xd5, 0x73, + 0x2c, 0x55, 0xfc, 0xb2, 0x8d, 0x95, 0x27, 0x31, 0xca, 0x70, 0x16, 0xcf, 0x68, 0xf4, 0x0c, 0x0e, 0xb9, 0x25, 0x9c, + 0xb7, 0x12, 0x03, 0x25, 0x45, 0xcf, 0x0c, 0x2f, 0x09, 0xfd, 0xfe, 0x2b, 0x59, 0x3e, 0xf5, 0xfd, 0xfe, 0xf3, 0xea, + 0xe9, 0x2f, 0x7e, 0xff, 0x17, 0x19, 0xfd, 0x5c, 0x18, 0x6f, 0x77, 0x6d, 0x8e, 0xc7, 0x76, 0x8e, 0x42, 0x6f, 0x8d, + 0x83, 0xbb, 0x05, 0xda, 0x74, 0x74, 0x4c, 0x50, 0xc1, 0xc6, 0x25, 0x33, 0xca, 0x43, 0x19, 0x4f, 0x00, 0xa9, 0xce, + 0x1e, 0xe4, 0x6e, 0x5c, 0xbf, 0x5a, 0x31, 0x90, 0x8a, 0xa5, 0x57, 0x40, 0xe6, 0xa4, 0xd7, 0x42, 0xcb, 0x5a, 0x5b, + 0xa5, 0x33, 0xd5, 0xe3, 0xe8, 0x25, 0x9f, 0xbe, 0x22, 0xad, 0xee, 0xd5, 0xf1, 0xa4, 0x7b, 0xd5, 0x68, 0xa0, 0xdc, + 0x92, 0xd6, 0x62, 0x70, 0x35, 0xc4, 0x5f, 0x83, 0x53, 0xcf, 0xa5, 0x25, 0x5c, 0x5b, 0x5e, 0xc7, 0x2c, 0xaf, 0xd1, + 0xc8, 0x0a, 0xd4, 0x75, 0xba, 0x4e, 0x74, 0xd7, 0xa2, 0xd0, 0x38, 0x59, 0x27, 0xb5, 0xa7, 0x48, 0x95, 0x40, 0x32, + 0x14, 0x21, 0xe4, 0x46, 0xa2, 0xad, 0xa3, 0xc2, 0x98, 0xd0, 0x5d, 0x9d, 0x59, 0x60, 0x9f, 0x5a, 0x4a, 0x04, 0x80, + 0x05, 0xe8, 0x5a, 0x7a, 0x82, 0x67, 0x78, 0xd1, 0x68, 0x2b, 0x32, 0x6f, 0xb6, 0xbb, 0xf5, 0xb1, 0x9e, 0x54, 0x63, + 0xe1, 0x45, 0x83, 0xcc, 0x4a, 0x2c, 0x15, 0x59, 0xa3, 0x51, 0xd4, 0x83, 0x9d, 0xf6, 0xe4, 0xd6, 0x02, 0x10, 0x37, + 0xeb, 0x49, 0x19, 0x56, 0xc2, 0x56, 0x32, 0x95, 0x85, 0x2c, 0xcb, 0xa8, 0x00, 0x29, 0x4a, 0x24, 0x66, 0x45, 0x51, + 0x49, 0x76, 0x10, 0xa3, 0x98, 0x12, 0x01, 0x9c, 0x47, 0xd9, 0x5d, 0x38, 0xc3, 0x1c, 0x4f, 0x15, 0xdf, 0x20, 0x84, + 0x9c, 0xd9, 0x74, 0x16, 0xa9, 0x78, 0x50, 0x4a, 0x98, 0x23, 0x93, 0x72, 0x42, 0xc3, 0xf3, 0xfd, 0x53, 0x7e, 0xa7, + 0x4d, 0x36, 0x60, 0xc3, 0x48, 0x35, 0x4b, 0x0d, 0xe7, 0x8a, 0xc9, 0x87, 0x40, 0xa2, 0x32, 0x3a, 0x12, 0x2a, 0x06, + 0xf8, 0x9c, 0x09, 0xaa, 0x74, 0xf0, 0x7d, 0x6b, 0xf7, 0xa5, 0x75, 0x05, 0x32, 0x75, 0xbd, 0x37, 0x80, 0xc8, 0x18, + 0x9c, 0x3b, 0x19, 0xd9, 0x68, 0x76, 0xbe, 0x7f, 0xf2, 0x76, 0x9b, 0x0d, 0xbc, 0x5a, 0x19, 0xeb, 0x57, 0xe9, 0x36, + 0x38, 0xae, 0x20, 0x4d, 0xcd, 0x8f, 0x28, 0x48, 0x95, 0x8a, 0x14, 0x07, 0x02, 0xa8, 0xe8, 0x7c, 0xff, 0xe4, 0x7d, + 0x20, 0x94, 0x6f, 0x09, 0x61, 0x77, 0xd9, 0x01, 0x27, 0xc1, 0x94, 0x50, 0xa4, 0xd7, 0x5e, 0xb2, 0x2e, 0xee, 0x08, + 0xf0, 0x68, 0xaa, 0x2a, 0xc1, 0x82, 0x18, 0xb0, 0x21, 0x49, 0x0d, 0x06, 0x48, 0x8a, 0x70, 0x5a, 0xb3, 0xcb, 0x08, + 0x6c, 0x80, 0x9a, 0xeb, 0x0c, 0x76, 0x22, 0xd4, 0xaa, 0x1f, 0xc2, 0xa9, 0x9a, 0x55, 0x16, 0x5a, 0x78, 0x3c, 0xdb, + 0xc8, 0x4a, 0xab, 0xcc, 0xd1, 0x6f, 0xc1, 0x76, 0xb2, 0x0f, 0x6f, 0x88, 0xb5, 0x24, 0x4c, 0xc1, 0x73, 0x9b, 0x3e, + 0x76, 0xbe, 0x7f, 0xf2, 0xda, 0x64, 0x90, 0xcd, 0x63, 0xcb, 0xef, 0x37, 0x4c, 0xcc, 0x93, 0xd7, 0x61, 0x55, 0xab, + 0x1a, 0x9f, 0xef, 0x9f, 0x7c, 0xd8, 0xd6, 0x0c, 0xca, 0x8b, 0x45, 0x65, 0xe3, 0x2b, 0xf8, 0x96, 0x34, 0x8d, 0x96, + 0x46, 0x38, 0x44, 0xac, 0xc0, 0x4a, 0x20, 0x45, 0x79, 0x51, 0xba, 0x46, 0x9e, 0xe3, 0x8c, 0xa8, 0x30, 0x50, 0x7d, + 0xd7, 0x8c, 0x9a, 0xc7, 0x78, 0x76, 0x36, 0xe2, 0x73, 0xba, 0x23, 0x36, 0x74, 0x83, 0x42, 0x36, 0x83, 0xd4, 0x19, + 0x05, 0x3a, 0xc3, 0x7b, 0x2d, 0xd4, 0xad, 0x8b, 0xaf, 0x4c, 0x11, 0x29, 0xaf, 0xc9, 0x16, 0x3c, 0x25, 0x2d, 0x9c, + 0x92, 0x16, 0x8e, 0x49, 0x3e, 0x68, 0x69, 0x01, 0xd1, 0x8d, 0xcb, 0x71, 0xb5, 0x98, 0x81, 0xac, 0x30, 0x73, 0x5a, + 0xb5, 0x00, 0x4e, 0xba, 0xb1, 0xf2, 0x3d, 0x2a, 0x99, 0x9e, 0x28, 0xb2, 0x78, 0x1f, 0x70, 0xcc, 0xd5, 0xc0, 0x67, + 0xec, 0x32, 0x85, 0xc4, 0x12, 0x58, 0x15, 0x96, 0x28, 0x2a, 0x9b, 0xb6, 0x4d, 0xd3, 0x38, 0x54, 0xfb, 0xc4, 0x71, + 0x1c, 0x02, 0xe7, 0xc6, 0xb1, 0xc9, 0xc3, 0xc9, 0x37, 0xbb, 0x3c, 0x3e, 0x38, 0x08, 0x74, 0xa7, 0x2f, 0x65, 0xc0, + 0x6d, 0x7d, 0x15, 0xb9, 0xfb, 0x56, 0xf3, 0x8a, 0x04, 0x29, 0xf8, 0x1b, 0x8d, 0x74, 0x58, 0x40, 0x18, 0x3a, 0x88, + 0xeb, 0x18, 0xb4, 0xc0, 0x2b, 0x5d, 0xaf, 0xbe, 0xfc, 0x46, 0xa3, 0x8c, 0xd2, 0xd6, 0xb1, 0x75, 0x83, 0xb3, 0xe2, + 0x2a, 0x28, 0x53, 0x7f, 0x5a, 0x1b, 0xf9, 0x52, 0x16, 0x04, 0xc4, 0x5c, 0x9a, 0x65, 0x76, 0x31, 0xce, 0x91, 0x60, + 0xd0, 0xee, 0x4b, 0x93, 0xb5, 0x80, 0x55, 0x76, 0x95, 0x69, 0x64, 0xd9, 0x59, 0x07, 0x45, 0xb6, 0x11, 0x44, 0xa5, + 0xa0, 0x51, 0xa3, 0x30, 0xe4, 0xfd, 0x7e, 0x33, 0xe7, 0x12, 0xe7, 0xc8, 0x38, 0xb9, 0x14, 0x14, 0x0a, 0x59, 0x9d, + 0x12, 0x29, 0x2f, 0xc9, 0x7c, 0x37, 0xc9, 0x9f, 0x38, 0x24, 0xff, 0x8c, 0x50, 0x87, 0xfc, 0xb5, 0x8b, 0x23, 0xe4, + 0xc6, 0xb9, 0x90, 0xdb, 0xaa, 0xd3, 0x39, 0x01, 0x27, 0x5a, 0x1d, 0xa3, 0xb5, 0xb0, 0xe2, 0x0e, 0x86, 0xe2, 0x9e, + 0x10, 0xe5, 0x86, 0xc4, 0x36, 0x06, 0x1c, 0x54, 0x41, 0x35, 0x98, 0x7a, 0x9b, 0x4f, 0xcf, 0xe5, 0x80, 0x27, 0x1f, + 0xee, 0x8e, 0x87, 0x9e, 0xce, 0x37, 0x4f, 0xae, 0x93, 0xfb, 0x09, 0xab, 0x76, 0x0e, 0x6e, 0x3d, 0x13, 0x14, 0xe6, + 0x2f, 0xe3, 0xd8, 0x75, 0xe6, 0xb3, 0x76, 0x08, 0xad, 0xfc, 0x03, 0x68, 0xdb, 0x6d, 0xd5, 0x82, 0x3a, 0xc3, 0x02, + 0x3f, 0xd2, 0x19, 0xa8, 0xb1, 0xd8, 0xc1, 0x3e, 0x4e, 0x54, 0x03, 0x9a, 0x25, 0xdb, 0xab, 0x9f, 0x15, 0x86, 0x4c, + 0x34, 0x68, 0x68, 0x09, 0xfc, 0x4f, 0x93, 0x3c, 0xd0, 0x8d, 0x92, 0x0b, 0x80, 0xa0, 0xb9, 0xc2, 0x53, 0x85, 0x30, + 0xdf, 0xaf, 0xbc, 0xef, 0x2f, 0xf7, 0x08, 0x99, 0x57, 0xde, 0xc7, 0x77, 0x55, 0xea, 0x15, 0x90, 0x05, 0x8a, 0xc0, + 0x7c, 0x2c, 0x0b, 0x74, 0xf8, 0xf2, 0xcc, 0x36, 0x57, 0x26, 0x64, 0x58, 0x69, 0xdc, 0x4e, 0x68, 0x53, 0xb9, 0xe5, + 0x74, 0xbd, 0x45, 0xc3, 0x5a, 0xed, 0x3e, 0xd4, 0xbe, 0x97, 0x0a, 0x46, 0x78, 0x7e, 0xaf, 0x5a, 0xdb, 0x71, 0x8b, + 0x8f, 0xeb, 0xf9, 0x2b, 0x6b, 0x9b, 0x12, 0xb2, 0x2c, 0xa7, 0x42, 0x3e, 0xa3, 0x63, 0x2e, 0x20, 0x66, 0x51, 0xe2, + 0x04, 0x15, 0xfb, 0x8e, 0xdf, 0x4e, 0xad, 0xcf, 0x09, 0x14, 0xac, 0x2d, 0x50, 0xfd, 0xfa, 0xa8, 0x82, 0xd6, 0xe7, + 0xeb, 0xbd, 0xe6, 0x07, 0x07, 0x1f, 0x2a, 0x34, 0x19, 0x28, 0x15, 0x14, 0x0e, 0xd3, 0xd2, 0x2a, 0x8d, 0x89, 0xe4, + 0xee, 0x07, 0xa5, 0x13, 0xc0, 0x32, 0x0c, 0x97, 0xf7, 0xbc, 0x24, 0xb2, 0x98, 0xac, 0xb3, 0x78, 0xe3, 0x9c, 0x60, + 0xae, 0xe1, 0x02, 0x1c, 0x1e, 0x4c, 0x6d, 0xed, 0x2d, 0xca, 0xab, 0x64, 0xd8, 0x12, 0x86, 0x53, 0x40, 0x56, 0xa0, + 0xcc, 0x10, 0x87, 0x02, 0xb7, 0x9a, 0x25, 0xa7, 0xa0, 0x57, 0x4e, 0x71, 0x1e, 0x4e, 0x21, 0xfd, 0xb5, 0x76, 0x64, + 0x11, 0xc2, 0x3a, 0x31, 0xc7, 0x49, 0x25, 0x38, 0x79, 0xb9, 0xcd, 0xa5, 0x6c, 0x89, 0x9a, 0x2a, 0xa9, 0xa3, 0x5a, + 0xa0, 0xb2, 0x43, 0x78, 0x15, 0x30, 0xa3, 0xb8, 0xd9, 0xb8, 0x19, 0x30, 0xe0, 0x67, 0x32, 0xd0, 0xc1, 0x28, 0x90, + 0x19, 0x3c, 0x5c, 0x04, 0xb5, 0xa9, 0xbb, 0x5c, 0x75, 0xc3, 0x06, 0x71, 0x53, 0x17, 0x4d, 0x5c, 0xc5, 0xf5, 0x4e, + 0x2b, 0x5e, 0x3a, 0xd6, 0x19, 0xd4, 0xd2, 0x72, 0xc1, 0x2a, 0x91, 0xc4, 0x59, 0xfe, 0x58, 0x27, 0x45, 0x97, 0x8d, + 0x30, 0x55, 0x60, 0xbc, 0x54, 0x7b, 0x40, 0x0b, 0xa0, 0xaf, 0xe5, 0x89, 0x74, 0x76, 0xd4, 0x3a, 0xb1, 0xd5, 0x9c, + 0x8e, 0xd4, 0x7f, 0x07, 0xa9, 0x2e, 0xeb, 0x67, 0xfe, 0xa5, 0x92, 0x85, 0x0c, 0xe7, 0x35, 0xc6, 0x9e, 0x29, 0xc6, + 0x8e, 0x40, 0x4f, 0xb3, 0x89, 0xdf, 0x7d, 0x93, 0xf1, 0xc2, 0x8c, 0x94, 0x33, 0x24, 0xf6, 0x75, 0x19, 0x2d, 0x77, + 0x7e, 0xaf, 0xed, 0x46, 0xc4, 0x08, 0x64, 0x01, 0x61, 0xc3, 0xd9, 0x33, 0x84, 0xf3, 0x46, 0xa3, 0x9b, 0x1f, 0xd3, + 0xca, 0x49, 0x52, 0xc1, 0xc8, 0x20, 0xa0, 0x0b, 0x04, 0x5f, 0x93, 0xa1, 0x10, 0xf2, 0xb7, 0x99, 0xd9, 0x39, 0xf8, + 0xda, 0x4f, 0xde, 0x05, 0x2e, 0x57, 0x73, 0xdb, 0x96, 0x41, 0x53, 0x58, 0x4f, 0x50, 0x05, 0x5c, 0xbe, 0xbe, 0x3b, + 0xc1, 0x03, 0xe0, 0xde, 0x6b, 0x63, 0x48, 0x45, 0x43, 0x5d, 0xa9, 0x59, 0x42, 0x79, 0xfa, 0xba, 0xa8, 0xca, 0x4a, + 0x74, 0x27, 0xeb, 0xca, 0xca, 0x98, 0x95, 0x24, 0x2f, 0x8a, 0x9c, 0x56, 0xe1, 0xfd, 0xb5, 0xf4, 0x4b, 0x25, 0x5c, + 0x36, 0xbd, 0xed, 0xa7, 0x73, 0x22, 0xb1, 0x43, 0xa8, 0x5f, 0xef, 0x8a, 0x7d, 0x54, 0x60, 0xc2, 0xb9, 0x36, 0x42, + 0xf1, 0xe7, 0x6d, 0x42, 0x11, 0x67, 0xe6, 0xc8, 0x2b, 0x81, 0xd8, 0xbe, 0x87, 0x40, 0x34, 0x6e, 0x76, 0x2b, 0x13, + 0x41, 0x1d, 0xa9, 0xc9, 0xc4, 0xfa, 0x96, 0x92, 0x0c, 0x33, 0xb3, 0x1b, 0xbd, 0xce, 0x6a, 0xc5, 0x06, 0x2d, 0x70, + 0x23, 0xf9, 0x3e, 0xfc, 0x6c, 0xeb, 0x9f, 0x0e, 0x27, 0xd6, 0x6e, 0xe0, 0x80, 0x95, 0x26, 0x0b, 0x0a, 0x21, 0xc1, + 0x39, 0x50, 0x49, 0x59, 0x8a, 0xa6, 0x0d, 0x05, 0x19, 0x02, 0x27, 0xac, 0x0c, 0x33, 0x01, 0xc4, 0x4a, 0x56, 0x18, + 0x03, 0x32, 0xd8, 0x9a, 0xfb, 0x67, 0xcd, 0xcb, 0x4f, 0x6b, 0xa2, 0x35, 0xb9, 0xa2, 0xd5, 0x87, 0x5a, 0xbe, 0x81, + 0x81, 0xc0, 0xe8, 0x87, 0x7b, 0xca, 0x04, 0xad, 0x44, 0x39, 0x72, 0xe5, 0x10, 0x6e, 0x81, 0x13, 0x6d, 0xef, 0x83, + 0x8e, 0xf0, 0x6e, 0x91, 0x26, 0x98, 0x3b, 0x74, 0xfd, 0x92, 0xc8, 0x1a, 0x2b, 0x99, 0x12, 0x63, 0x29, 0xe1, 0x58, + 0x91, 0xa9, 0x24, 0xd9, 0xa0, 0x35, 0x04, 0x05, 0xb4, 0x9b, 0x1e, 0x67, 0x95, 0x09, 0x9c, 0x36, 0x1a, 0x28, 0xb6, + 0xb3, 0x4e, 0x07, 0xac, 0x91, 0x0e, 0x31, 0xc5, 0xa9, 0x36, 0x4c, 0xce, 0x0e, 0x0e, 0x82, 0xb8, 0x9a, 0x77, 0x90, + 0x0e, 0x11, 0xe6, 0xab, 0x55, 0xa0, 0xc0, 0x8a, 0xd1, 0x6a, 0x15, 0xbb, 0x60, 0xa9, 0x6a, 0xe8, 0x36, 0xef, 0x4b, + 0x32, 0x57, 0x02, 0x70, 0x0e, 0x10, 0x36, 0x48, 0x10, 0x1b, 0xf7, 0x5e, 0x0c, 0xee, 0xa8, 0x46, 0x36, 0x48, 0x1b, + 0xed, 0xa1, 0xc3, 0xb8, 0x06, 0xe9, 0x90, 0xc4, 0x05, 0x3f, 0x38, 0xd8, 0xcb, 0x8d, 0x88, 0xfc, 0x09, 0x44, 0xd9, + 0x4f, 0x4a, 0xb2, 0xe8, 0x01, 0xdd, 0xdd, 0x58, 0x77, 0x06, 0x94, 0x14, 0x65, 0xb6, 0xd5, 0xb6, 0xab, 0x65, 0x41, + 0x94, 0x8d, 0xb0, 0x09, 0x06, 0xf7, 0xc1, 0xb2, 0x2f, 0xc9, 0xfc, 0x95, 0x2c, 0x73, 0xac, 0x7f, 0xde, 0x9a, 0x59, + 0x1d, 0x86, 0x61, 0x2c, 0x26, 0x2a, 0x96, 0x61, 0xc3, 0xb0, 0x8a, 0xf8, 0x8f, 0x0c, 0x98, 0xce, 0xc4, 0x83, 0x72, + 0xae, 0x21, 0xd1, 0xe0, 0x5b, 0xd5, 0xc6, 0xde, 0x25, 0xf9, 0x69, 0xab, 0x97, 0x41, 0x43, 0xf2, 0xfc, 0xb7, 0x42, + 0xf2, 0xd0, 0x40, 0xa2, 0xc9, 0x63, 0x0d, 0x67, 0x3b, 0x70, 0xf1, 0x93, 0x5c, 0xc3, 0xd9, 0x6e, 0xdc, 0x5a, 0x4c, + 0xfd, 0xb2, 0x0b, 0x3e, 0x87, 0x37, 0x68, 0x40, 0xab, 0x02, 0x07, 0xca, 0x47, 0xeb, 0xba, 0x97, 0x66, 0xa5, 0x20, + 0x4c, 0x25, 0x09, 0x58, 0xfd, 0x00, 0x54, 0xda, 0xa8, 0x63, 0xf8, 0xb2, 0x68, 0x8e, 0x1c, 0x97, 0x40, 0x3d, 0x75, + 0x05, 0xc8, 0xc9, 0x78, 0xdb, 0xe7, 0x07, 0x07, 0x60, 0x1b, 0x80, 0x12, 0x17, 0x8e, 0xe2, 0xb9, 0x5c, 0x08, 0x50, + 0xa5, 0x72, 0xfb, 0x1b, 0x8a, 0xe1, 0x16, 0x88, 0x2a, 0x83, 0x1f, 0x50, 0x30, 0x8f, 0xf3, 0x9c, 0x5d, 0xe9, 0x32, + 0xf3, 0x1b, 0x73, 0x62, 0x49, 0x39, 0xd7, 0x3a, 0x61, 0x86, 0xba, 0x99, 0xa1, 0xd3, 0x3a, 0xda, 0x5e, 0x5c, 0xd1, + 0x4c, 0xbe, 0x62, 0xb9, 0xa4, 0x19, 0x2c, 0xbf, 0xa2, 0x38, 0x58, 0x51, 0x8e, 0xe0, 0xc0, 0xd6, 0x7a, 0xc5, 0x49, + 0x72, 0x67, 0x17, 0x59, 0xd7, 0x81, 0xa6, 0x71, 0x96, 0xa4, 0x7a, 0x12, 0x37, 0x9f, 0xd1, 0xe6, 0x70, 0x96, 0x2d, + 0xdd, 0x7c, 0x9a, 0x4a, 0xd9, 0x50, 0xdc, 0x3d, 0x60, 0xc4, 0x4a, 0x02, 0x2b, 0x3d, 0xef, 0xd4, 0x5a, 0x20, 0xe2, + 0xbd, 0x63, 0x13, 0xdc, 0x95, 0x60, 0xe9, 0x70, 0xd4, 0xb0, 0x0e, 0xa7, 0xa5, 0x9b, 0x2f, 0xb7, 0x5e, 0x69, 0xdb, + 0x26, 0x1c, 0x14, 0x9d, 0x3c, 0xde, 0x6d, 0x59, 0xbd, 0xb6, 0x92, 0xc3, 0x4a, 0x0b, 0x76, 0x5f, 0xc6, 0x8c, 0x96, + 0x96, 0xbc, 0x90, 0x3d, 0x8a, 0xfb, 0x92, 0x3c, 0x87, 0x3b, 0x43, 0x2f, 0xe5, 0x2c, 0x5d, 0xbb, 0x1a, 0xd3, 0xdd, + 0x2f, 0xb5, 0xff, 0x7d, 0x19, 0xbc, 0xc4, 0xef, 0x21, 0xb0, 0xfb, 0x55, 0xd5, 0x7c, 0x33, 0xa0, 0xfb, 0x55, 0x85, + 0xa0, 0xaf, 0xa2, 0x8d, 0x76, 0x4e, 0x20, 0xb7, 0x13, 0x3e, 0x0d, 0x5b, 0xbe, 0xd5, 0x96, 0x7e, 0xd6, 0x61, 0x24, + 0x9d, 0x69, 0xa9, 0xce, 0x03, 0xae, 0xf2, 0xd4, 0x20, 0x5f, 0xae, 0x6e, 0x21, 0x51, 0x93, 0x61, 0xa8, 0x75, 0xf8, + 0x5d, 0xdb, 0x63, 0x64, 0x4c, 0xa6, 0xed, 0x8c, 0xaf, 0x63, 0x21, 0xf7, 0xe1, 0x94, 0xf1, 0x8d, 0x7b, 0x78, 0x53, + 0x02, 0x1e, 0xb4, 0xfb, 0x4d, 0xe1, 0x18, 0xdb, 0xb9, 0xbe, 0x07, 0xe4, 0x8e, 0x4f, 0xb8, 0xd5, 0xdd, 0xea, 0x56, + 0xc6, 0xd7, 0x60, 0xff, 0x23, 0x3c, 0xb5, 0x97, 0xe3, 0xa8, 0xe1, 0xc0, 0x34, 0x5a, 0x16, 0xa5, 0x53, 0x80, 0x6b, + 0xe5, 0x4d, 0x20, 0xcc, 0x0b, 0x15, 0xe0, 0xfe, 0x01, 0x7f, 0x63, 0x58, 0xe2, 0xb8, 0xe4, 0x38, 0x27, 0xf7, 0xe5, + 0x88, 0x1a, 0xfc, 0x32, 0x7e, 0x0f, 0x74, 0xac, 0x28, 0xb4, 0xb0, 0x54, 0xf4, 0x9c, 0x9b, 0x85, 0xec, 0x4c, 0x4b, + 0xc5, 0xb4, 0x4c, 0xa9, 0x51, 0xd3, 0x6c, 0xc9, 0xe3, 0xb4, 0x56, 0xb6, 0x2c, 0x4f, 0x55, 0x6d, 0x5e, 0xb4, 0x03, + 0x8b, 0x55, 0x68, 0x71, 0xb5, 0x0a, 0xea, 0xa8, 0x26, 0xcc, 0x89, 0x64, 0x20, 0xcc, 0x9c, 0x8c, 0x8a, 0x9a, 0x66, + 0xad, 0xfb, 0x04, 0x68, 0x3d, 0xa1, 0xc8, 0xea, 0xe6, 0x35, 0x38, 0x5c, 0x17, 0x82, 0xee, 0xee, 0xfa, 0x14, 0xb0, + 0x5e, 0x5d, 0x39, 0x91, 0x83, 0xa1, 0x9f, 0xcb, 0x54, 0xd9, 0x2a, 0xa7, 0x75, 0x0b, 0x7e, 0xd1, 0x1d, 0xc9, 0xb2, + 0x06, 0x75, 0x9b, 0xf5, 0x4e, 0xb2, 0xd1, 0x73, 0xbe, 0x2b, 0xd9, 0xa8, 0xa6, 0xed, 0xee, 0xb5, 0xd0, 0xdd, 0x69, + 0xa9, 0x7a, 0xae, 0xed, 0x4d, 0x7e, 0xc3, 0x74, 0x6d, 0xa0, 0x4d, 0x8d, 0x66, 0xcb, 0x55, 0xce, 0x8a, 0x62, 0x5c, + 0x5e, 0x26, 0x50, 0xb9, 0x3b, 0x63, 0x4d, 0xff, 0xc6, 0x6a, 0x54, 0xd7, 0x71, 0x83, 0x1f, 0xc8, 0x24, 0xe5, 0x97, + 0x71, 0xfa, 0x1e, 0xe6, 0xab, 0x2a, 0x5f, 0xde, 0x26, 0x22, 0x96, 0xd4, 0x70, 0x97, 0x0a, 0x86, 0x1f, 0x1c, 0x18, + 0x7e, 0xd0, 0x7c, 0xba, 0xea, 0x8f, 0x97, 0xaf, 0xca, 0x01, 0xa2, 0x71, 0x61, 0x59, 0xc6, 0xb9, 0xdc, 0x3e, 0xc7, + 0x3a, 0x0b, 0x3b, 0x2f, 0x59, 0xd8, 0xb9, 0x0c, 0xd6, 0x87, 0x0a, 0x82, 0x6f, 0xb6, 0x8f, 0xb2, 0xc9, 0xd9, 0xbe, + 0xa9, 0x0e, 0xfe, 0x37, 0xd1, 0x9d, 0x7d, 0x1c, 0x2e, 0x77, 0x14, 0x1e, 0xa9, 0x74, 0x15, 0x0d, 0xf2, 0x3b, 0x48, + 0x3b, 0x90, 0xa4, 0xe7, 0xdc, 0x39, 0xa8, 0xe4, 0x94, 0x4d, 0x04, 0x0a, 0x46, 0x8b, 0x5c, 0xf2, 0x99, 0x19, 0x33, + 0x37, 0xd7, 0x8c, 0x54, 0x25, 0xb8, 0xa2, 0x55, 0xb4, 0x3d, 0xaa, 0x5f, 0xe4, 0x5a, 0x7e, 0x64, 0x59, 0x12, 0xe5, + 0xd8, 0x48, 0x91, 0x3c, 0xca, 0x0a, 0x62, 0x93, 0x8d, 0x37, 0xeb, 0xf0, 0x98, 0x65, 0x2c, 0x9f, 0x52, 0x11, 0x70, + 0xb4, 0xdc, 0x35, 0x19, 0x87, 0x80, 0x8c, 0x9e, 0x0c, 0x7f, 0x5b, 0x5d, 0xf8, 0x0b, 0x61, 0x34, 0xf0, 0x03, 0xcd, + 0xa8, 0x9c, 0xf2, 0x04, 0x12, 0x53, 0xc2, 0xa4, 0xbc, 0xd1, 0x74, 0x70, 0xb0, 0x17, 0xf8, 0xca, 0x2d, 0x01, 0x57, + 0xbf, 0xdd, 0x1a, 0xd4, 0x5f, 0xc2, 0xf5, 0x9c, 0x6a, 0x6a, 0x8a, 0x96, 0x74, 0xfd, 0x26, 0x8b, 0x0c, 0x3f, 0xd2, + 0x5b, 0x2c, 0x50, 0x51, 0x44, 0x1a, 0x6a, 0x7f, 0xcc, 0x68, 0x9a, 0xf8, 0xf8, 0x23, 0xbd, 0x8d, 0xca, 0xdb, 0xe2, + 0xea, 0x72, 0xb3, 0xda, 0x40, 0x9f, 0x5f, 0x67, 0x3e, 0xae, 0x26, 0x89, 0x96, 0x05, 0xe6, 0x82, 0x4d, 0x80, 0x38, + 0xff, 0x46, 0x6f, 0x23, 0x3d, 0x1e, 0x73, 0x2e, 0xeb, 0xa1, 0xa5, 0x45, 0x7d, 0xe8, 0x14, 0xbb, 0xdb, 0x60, 0x0c, + 0x8a, 0x81, 0xea, 0x3b, 0x24, 0xb5, 0x76, 0x95, 0x79, 0x88, 0x50, 0x71, 0xdf, 0xa5, 0xe0, 0x2f, 0x5c, 0xd1, 0x26, + 0x6b, 0xa9, 0xaf, 0x6b, 0x9d, 0x28, 0x74, 0xa8, 0x72, 0x3d, 0xce, 0x03, 0x61, 0x4f, 0x9d, 0xb9, 0x83, 0xe0, 0x38, + 0xc2, 0xbe, 0x90, 0x66, 0xd0, 0xe8, 0x5b, 0x9d, 0x12, 0x52, 0x45, 0x92, 0x5e, 0x57, 0xfd, 0xbc, 0xf3, 0x00, 0xf0, + 0x0e, 0x29, 0x2d, 0xb1, 0xba, 0x8e, 0x59, 0xd8, 0x74, 0xd1, 0xef, 0x24, 0x09, 0x96, 0x76, 0x09, 0x91, 0x70, 0xb1, + 0x28, 0x0b, 0xa0, 0x42, 0x43, 0x5f, 0x3a, 0x03, 0x90, 0x8d, 0x03, 0xb6, 0x21, 0x35, 0x33, 0x25, 0x35, 0x43, 0x07, + 0xe3, 0x3b, 0xa4, 0x24, 0x55, 0xc8, 0x50, 0x4a, 0xa4, 0x12, 0x7a, 0x66, 0x73, 0x0d, 0x09, 0xb9, 0x1b, 0x5a, 0x5e, + 0x9f, 0xd3, 0x7b, 0x9e, 0xd5, 0xc0, 0x0a, 0xd4, 0x38, 0xa8, 0x88, 0x60, 0x49, 0x54, 0x37, 0x28, 0xac, 0x3b, 0x47, + 0xd8, 0xfc, 0xd6, 0x80, 0x87, 0x76, 0x59, 0xc4, 0xa2, 0x24, 0x98, 0xa2, 0xa5, 0x08, 0xa6, 0x38, 0x83, 0x7c, 0x44, + 0x5e, 0x94, 0xf0, 0x53, 0x77, 0x37, 0x6a, 0xd9, 0xca, 0xdb, 0xaf, 0xf8, 0x81, 0x32, 0x2f, 0x21, 0x47, 0x13, 0x0b, + 0xcb, 0x53, 0x44, 0xa0, 0xee, 0xda, 0x39, 0xdb, 0xf6, 0x95, 0x49, 0xd1, 0x31, 0x80, 0x7d, 0x27, 0x83, 0xa5, 0xb3, + 0x0a, 0xf7, 0x2e, 0xb7, 0xb9, 0xf2, 0x67, 0x82, 0x7d, 0x55, 0x12, 0x69, 0x90, 0x93, 0x35, 0x89, 0x73, 0x77, 0xae, + 0xe5, 0xcf, 0x0b, 0x2a, 0x6e, 0xcf, 0x28, 0xe4, 0x3a, 0x73, 0xb8, 0xeb, 0x5b, 0x6d, 0x43, 0x95, 0xa7, 0xde, 0xcf, + 0x94, 0xb2, 0x52, 0xd4, 0x2f, 0x01, 0xae, 0x5f, 0x11, 0x2c, 0x54, 0xb4, 0xd1, 0x71, 0xc4, 0xe8, 0xd3, 0x42, 0x77, + 0x5e, 0x9e, 0xa4, 0x5d, 0x06, 0xfe, 0xb5, 0x0a, 0xd3, 0x26, 0x58, 0x80, 0xb9, 0x7b, 0x21, 0x75, 0x90, 0x0f, 0xd7, + 0xbd, 0x32, 0x50, 0x04, 0xe1, 0xbb, 0x6c, 0xf7, 0x52, 0xb7, 0x65, 0xcd, 0xee, 0x5e, 0x6a, 0x2d, 0xe8, 0xa7, 0x52, + 0x7e, 0xb0, 0x99, 0xa7, 0xbc, 0xbc, 0xcc, 0x8a, 0x02, 0x15, 0x00, 0xde, 0xf7, 0xdd, 0x20, 0xf8, 0xde, 0x24, 0x0d, + 0x86, 0x10, 0x8b, 0x3d, 0x4b, 0xb9, 0x65, 0xe2, 0xd5, 0xfc, 0xdf, 0x6f, 0xcc, 0xff, 0xbd, 0x73, 0xe5, 0x14, 0x4c, + 0xa3, 0x49, 0x46, 0x13, 0xcb, 0x3a, 0x91, 0x26, 0x40, 0xa5, 0xb7, 0xe5, 0x92, 0x7c, 0xbc, 0x88, 0x40, 0xe3, 0x5a, + 0x8e, 0x79, 0x26, 0x9b, 0xe3, 0x78, 0xc6, 0xd2, 0xdb, 0x68, 0xc1, 0x9a, 0x33, 0x9e, 0xf1, 0x7c, 0x1e, 0x8f, 0x28, + 0xce, 0x6f, 0x73, 0x49, 0x67, 0xcd, 0x05, 0xc3, 0x2f, 0x69, 0x7a, 0x45, 0x25, 0x1b, 0xc5, 0xd8, 0x3f, 0x11, 0x2c, + 0x4e, 0xbd, 0x37, 0xb1, 0x10, 0xfc, 0xda, 0xc7, 0xef, 0xf8, 0x25, 0x97, 0x1c, 0xbf, 0xbd, 0xb9, 0x9d, 0xd0, 0x0c, + 0x7f, 0xb8, 0x5c, 0x64, 0x72, 0x81, 0xf3, 0x38, 0xcb, 0x9b, 0x39, 0x15, 0x6c, 0xdc, 0x1d, 0xf1, 0x94, 0x8b, 0x26, + 0xa4, 0x6c, 0xcf, 0x68, 0x94, 0xb2, 0xc9, 0x54, 0x7a, 0x49, 0x2c, 0x3e, 0x76, 0x9b, 0xcd, 0xb9, 0x60, 0xb3, 0x58, + 0xdc, 0x36, 0x55, 0x8b, 0xe8, 0xb3, 0xd6, 0x51, 0xfc, 0xf9, 0xf8, 0x61, 0x57, 0x8a, 0x38, 0xcb, 0x19, 0x6c, 0x53, + 0x14, 0xa7, 0xa9, 0x77, 0xf4, 0xa8, 0x35, 0xcb, 0xf7, 0x74, 0x20, 0x2f, 0xce, 0x64, 0x71, 0x81, 0x3f, 0x02, 0xdc, + 0xe1, 0xa5, 0xcc, 0xf0, 0xe5, 0x42, 0x4a, 0x9e, 0x2d, 0x47, 0x0b, 0x91, 0x73, 0x11, 0xcd, 0x39, 0xcb, 0x24, 0x15, + 0xdd, 0x4b, 0x2e, 0x12, 0x2a, 0x9a, 0x22, 0x4e, 0xd8, 0x22, 0x8f, 0x1e, 0xce, 0x6f, 0xba, 0xa0, 0x59, 0x4c, 0x04, + 0x5f, 0x64, 0x89, 0x99, 0x8b, 0x65, 0x53, 0x2a, 0x98, 0x74, 0x2b, 0xd4, 0x2b, 0x4c, 0xa2, 0x94, 0x65, 0x34, 0x16, + 0xcd, 0x09, 0x74, 0x06, 0xb3, 0xa8, 0x95, 0xd0, 0x09, 0x16, 0x93, 0xcb, 0x38, 0x68, 0x77, 0x9e, 0x60, 0xfb, 0x37, + 0x7c, 0x84, 0xbc, 0xd6, 0xf6, 0xe2, 0x76, 0xab, 0xf5, 0x27, 0xd4, 0x5d, 0x9b, 0x45, 0x01, 0x14, 0xb5, 0xe7, 0x37, + 0x5e, 0xce, 0x21, 0xa7, 0x6d, 0x5b, 0xcf, 0xee, 0x3c, 0x4e, 0x20, 0x21, 0x38, 0xea, 0xcc, 0x6f, 0x0a, 0x58, 0x5d, + 0xa4, 0x93, 0x4c, 0xcd, 0x22, 0xcd, 0xd3, 0xf2, 0xb7, 0x42, 0xfc, 0x74, 0x3b, 0xc4, 0x1d, 0x0b, 0x71, 0x85, 0xf5, + 0x66, 0xb2, 0x10, 0x2a, 0xb6, 0x1a, 0xb5, 0x73, 0x0d, 0xc8, 0x94, 0x5f, 0x51, 0x61, 0xe1, 0x50, 0x0f, 0xbf, 0x19, + 0x8c, 0xce, 0x76, 0x30, 0x9e, 0x7e, 0x0a, 0x0c, 0x91, 0x25, 0xcb, 0xfa, 0xbe, 0xb6, 0x05, 0x9d, 0x75, 0xa7, 0x14, + 0xe8, 0x29, 0xea, 0xc0, 0xef, 0x6b, 0x96, 0xc8, 0xa9, 0xfe, 0xa9, 0xc8, 0xf9, 0x5a, 0xd7, 0x3d, 0x6a, 0xb5, 0xf4, + 0x73, 0xce, 0x7e, 0xa1, 0x51, 0x3b, 0x84, 0x06, 0xc5, 0x05, 0xfe, 0x5b, 0x79, 0x99, 0xb7, 0xce, 0x3d, 0xf1, 0x0f, + 0xee, 0x2d, 0x5f, 0x27, 0x49, 0xb1, 0xba, 0x11, 0x8d, 0x85, 0x95, 0x95, 0x5a, 0xf8, 0x80, 0xdb, 0x4e, 0x9d, 0x27, + 0xc2, 0x7a, 0xe5, 0x2d, 0x4e, 0xd6, 0xff, 0x41, 0xe7, 0x5d, 0x44, 0x10, 0xe9, 0x70, 0x92, 0x0d, 0x79, 0x37, 0xeb, + 0x91, 0x56, 0x37, 0x6b, 0x36, 0x51, 0xc0, 0x89, 0x18, 0x64, 0x26, 0x3d, 0x2f, 0x60, 0x7d, 0xae, 0x8c, 0xed, 0x1c, + 0x45, 0x1c, 0xae, 0x9a, 0xae, 0x56, 0x55, 0x18, 0x80, 0xa9, 0xeb, 0x1a, 0x7f, 0x93, 0xa6, 0x01, 0xce, 0x1d, 0x4e, + 0x9e, 0xd9, 0x17, 0xbb, 0x08, 0xcb, 0x2b, 0x52, 0x3e, 0x52, 0x98, 0x0b, 0xe7, 0xb1, 0x9c, 0x82, 0x97, 0xa2, 0x14, + 0x3f, 0x55, 0x12, 0x93, 0x7f, 0xe8, 0xa3, 0xbe, 0x28, 0x33, 0xdc, 0x20, 0x93, 0x4f, 0x14, 0x30, 0xca, 0x37, 0x92, + 0xc0, 0x88, 0xf8, 0x17, 0xa2, 0x6d, 0x3a, 0x6b, 0xd1, 0x8d, 0xef, 0x6b, 0xd1, 0xd1, 0x4c, 0x32, 0x95, 0xbb, 0x6d, + 0x23, 0x0e, 0xd3, 0x38, 0x3f, 0x1f, 0xe9, 0xbb, 0x92, 0x79, 0x75, 0x33, 0x20, 0x56, 0xd0, 0x6b, 0x23, 0x8d, 0x0a, + 0x65, 0x8f, 0x7e, 0x2f, 0x77, 0xda, 0x27, 0xe2, 0x2e, 0xfb, 0xa4, 0x5c, 0x78, 0xce, 0x17, 0x62, 0x04, 0xe1, 0x48, + 0x23, 0xf5, 0x36, 0x1d, 0x37, 0xbe, 0x52, 0x31, 0x7c, 0x2c, 0x9d, 0x4c, 0x50, 0x89, 0x99, 0xfb, 0x52, 0x09, 0xaa, + 0x42, 0x5e, 0xfa, 0xbe, 0x86, 0x11, 0x71, 0x76, 0x49, 0x20, 0xb3, 0x13, 0x95, 0xd4, 0x18, 0x64, 0xa4, 0x97, 0x85, + 0x8b, 0x8c, 0xfd, 0xbc, 0xa0, 0xe7, 0x0c, 0x74, 0x4d, 0x16, 0xb2, 0x44, 0xc5, 0x9a, 0x40, 0xf6, 0x35, 0xdb, 0x10, + 0xbc, 0x60, 0x89, 0xde, 0x98, 0x4c, 0x55, 0x9a, 0xdc, 0x26, 0xbf, 0xe9, 0x83, 0xbf, 0x18, 0xb4, 0x03, 0x86, 0x13, + 0x3e, 0x8b, 0x59, 0x16, 0x29, 0x97, 0x6f, 0x39, 0x58, 0x04, 0xad, 0x31, 0x4b, 0xa2, 0xcc, 0x6c, 0x4f, 0x1b, 0x85, + 0x3f, 0x71, 0x96, 0xa9, 0xae, 0x45, 0x97, 0x2b, 0x84, 0x6a, 0xf4, 0x11, 0x8b, 0xe0, 0x13, 0x2d, 0xd7, 0x38, 0xc2, + 0x6e, 0x75, 0x79, 0xed, 0xbc, 0xb6, 0x03, 0xad, 0xb5, 0x8d, 0xd2, 0x46, 0x00, 0x5f, 0x2f, 0xcd, 0xb9, 0x90, 0x41, + 0x30, 0xc5, 0x29, 0x22, 0xbd, 0xa9, 0x72, 0x76, 0x1d, 0xa7, 0xea, 0xbf, 0x7e, 0xb3, 0x1d, 0xb5, 0x4b, 0xf3, 0xbd, + 0x76, 0x1b, 0x58, 0x27, 0x47, 0x99, 0x1b, 0xa5, 0x6a, 0x19, 0xe5, 0x6f, 0xbd, 0xd4, 0xea, 0xb9, 0x5c, 0x2e, 0x36, + 0xc7, 0x4d, 0x8b, 0xaa, 0xa0, 0x06, 0x84, 0x0a, 0x16, 0xed, 0x98, 0x0a, 0x15, 0xd5, 0xba, 0x4b, 0x55, 0xf2, 0x42, + 0x8b, 0xe8, 0xf3, 0xfd, 0xa5, 0x30, 0x33, 0x16, 0x17, 0xcc, 0x3a, 0x99, 0xea, 0x24, 0x57, 0x18, 0x8c, 0x38, 0x7a, + 0xe8, 0xb6, 0x66, 0x1a, 0x96, 0x5b, 0x22, 0xb6, 0xd2, 0x6d, 0xa8, 0x1f, 0xa9, 0x20, 0x55, 0xb8, 0x6b, 0x63, 0x00, + 0xc8, 0xd5, 0xdb, 0x06, 0x18, 0x98, 0xad, 0xb9, 0xb4, 0x4b, 0x00, 0x6d, 0x6c, 0x4c, 0xe1, 0x22, 0xcd, 0xc5, 0xfe, + 0xf2, 0x1b, 0x59, 0x1c, 0x3a, 0x4d, 0xd5, 0x6f, 0x96, 0xc0, 0xff, 0x20, 0x01, 0x97, 0x5a, 0x29, 0x8d, 0xfc, 0xaf, + 0xdf, 0x9e, 0xbd, 0xf7, 0xf1, 0x25, 0x4f, 0x6e, 0x23, 0x5f, 0x8a, 0x05, 0xf5, 0x0b, 0x14, 0xca, 0x29, 0xcd, 0xca, + 0x97, 0xf1, 0xf0, 0x94, 0x86, 0x29, 0x9f, 0xe8, 0x4b, 0x99, 0xeb, 0x46, 0xf2, 0xe8, 0xe2, 0x58, 0xbd, 0x64, 0xaa, + 0x77, 0x2c, 0xf5, 0xeb, 0xbd, 0xa4, 0x80, 0x9f, 0x3d, 0x08, 0xa1, 0x1c, 0x1f, 0xca, 0xa9, 0x7a, 0x38, 0x83, 0x03, + 0xa3, 0x9e, 0xf6, 0x97, 0x1b, 0xc4, 0xd4, 0x87, 0x21, 0xa6, 0x3d, 0xbd, 0x84, 0x5c, 0xb5, 0xba, 0x88, 0x46, 0x17, + 0x17, 0xc5, 0xf1, 0x21, 0x8c, 0x75, 0x68, 0xc7, 0x05, 0x08, 0x6d, 0xff, 0x92, 0xc0, 0xe0, 0x65, 0x43, 0x82, 0xf4, + 0x60, 0x08, 0x98, 0x37, 0xe9, 0xc1, 0x22, 0x81, 0xc0, 0xa0, 0x77, 0x52, 0x96, 0xa8, 0x13, 0xab, 0x8b, 0x76, 0x41, + 0xa0, 0x1b, 0x56, 0x74, 0xaf, 0xbd, 0xa9, 0xd5, 0xfe, 0x5a, 0x90, 0x12, 0x17, 0xba, 0x0b, 0x04, 0xff, 0x2b, 0xc8, + 0x8e, 0x0f, 0x35, 0x1e, 0x2e, 0xdc, 0x57, 0x9b, 0xe8, 0xd7, 0x0e, 0x94, 0xd8, 0x1a, 0xe4, 0x12, 0x7f, 0x94, 0xf8, + 0xe3, 0x85, 0x6a, 0x6a, 0x85, 0x11, 0x68, 0x49, 0x20, 0xb4, 0x5b, 0x56, 0xeb, 0x18, 0xf1, 0x34, 0x8d, 0xe7, 0x39, + 0x8d, 0xec, 0x0f, 0x23, 0x97, 0x40, 0xbc, 0x6d, 0x2a, 0x02, 0x26, 0xbd, 0xe6, 0x14, 0xd4, 0x85, 0x4d, 0x2d, 0xe5, + 0x2a, 0x16, 0x41, 0xb3, 0x39, 0x6a, 0x5e, 0x4e, 0x50, 0x21, 0xa7, 0x4b, 0x57, 0xaa, 0x3d, 0x6e, 0xb5, 0xba, 0x90, + 0x0b, 0xd9, 0x8c, 0x53, 0x36, 0xc9, 0xa2, 0x94, 0x8e, 0x65, 0x21, 0xe1, 0x96, 0xda, 0xd2, 0xaa, 0x11, 0x61, 0xe7, + 0x91, 0xa0, 0x33, 0x2f, 0x84, 0x7f, 0xef, 0x9e, 0xb8, 0x90, 0x49, 0x94, 0xc9, 0x69, 0x53, 0x65, 0xdd, 0xc2, 0x9d, + 0x01, 0x39, 0xad, 0x3d, 0x2f, 0x9d, 0x89, 0x46, 0x14, 0x54, 0xac, 0x42, 0x0a, 0x4f, 0x4e, 0xb1, 0x14, 0x6e, 0xbb, + 0x0c, 0x2d, 0x37, 0x56, 0xb0, 0x29, 0xe9, 0x8f, 0x50, 0x91, 0x2b, 0xc5, 0x78, 0xb3, 0xb1, 0x55, 0x97, 0xea, 0x4f, + 0x1b, 0xe8, 0x73, 0x14, 0xbb, 0x42, 0x3b, 0x96, 0x97, 0xba, 0xc7, 0x7d, 0x90, 0x59, 0x53, 0x39, 0xb1, 0xdb, 0x03, + 0x15, 0x2c, 0x9b, 0x2f, 0xe4, 0x40, 0x39, 0xb5, 0x05, 0x5c, 0x90, 0x18, 0x62, 0xa7, 0x04, 0x70, 0x30, 0x5c, 0x6a, + 0x60, 0x46, 0x71, 0x3a, 0x0a, 0x00, 0x22, 0xaf, 0xe9, 0x3d, 0x15, 0x74, 0x86, 0xba, 0x33, 0x96, 0x35, 0x75, 0xdd, + 0x23, 0x47, 0x2d, 0x09, 0x9f, 0xc0, 0x53, 0x11, 0xaa, 0xd1, 0xb0, 0xca, 0x5d, 0xdd, 0x82, 0xcb, 0x8b, 0x61, 0x51, + 0x74, 0x85, 0x0c, 0x06, 0xaf, 0x03, 0x34, 0xc4, 0xbf, 0x38, 0x2f, 0x67, 0xf1, 0xed, 0x51, 0xf1, 0x71, 0x07, 0xed, + 0x68, 0xe2, 0x9e, 0x05, 0xd5, 0xec, 0x17, 0x02, 0x0d, 0xdf, 0x05, 0x3e, 0xcd, 0xe7, 0x4d, 0xcd, 0xbb, 0x9a, 0x8a, + 0x64, 0x7d, 0xe8, 0x8a, 0x8c, 0xa7, 0xf6, 0x7b, 0xb9, 0x54, 0x6c, 0xc9, 0x5c, 0xd2, 0xd0, 0xce, 0x84, 0x61, 0x79, + 0xa9, 0xc7, 0x3c, 0xbb, 0xd7, 0x78, 0x50, 0x8d, 0x9f, 0x5c, 0x9c, 0xd4, 0x79, 0x1c, 0xf0, 0xa5, 0xf2, 0x05, 0x76, + 0x71, 0x9a, 0xc2, 0x84, 0x17, 0x56, 0x7d, 0x71, 0x5f, 0xfa, 0x31, 0x90, 0xc3, 0x00, 0x15, 0xe6, 0x9c, 0x3e, 0x53, + 0x2a, 0xa5, 0xf3, 0xd6, 0xbc, 0x3d, 0x69, 0x83, 0x45, 0x5a, 0xfa, 0x32, 0x08, 0x77, 0xd7, 0xf2, 0xa2, 0xbb, 0x15, + 0xef, 0xd2, 0x0a, 0xa9, 0xa7, 0x16, 0x44, 0x7c, 0x91, 0x25, 0xbe, 0xf7, 0x97, 0x51, 0xca, 0x46, 0x1f, 0x89, 0xbf, + 0xbf, 0x0c, 0xd0, 0xe6, 0xb5, 0x47, 0xc5, 0x15, 0x2c, 0xc3, 0x46, 0x75, 0x47, 0x7a, 0x16, 0x3a, 0xbc, 0x58, 0xbf, + 0x15, 0xc7, 0xef, 0xed, 0x2f, 0x81, 0xf1, 0xe8, 0x79, 0x7a, 0x17, 0xc5, 0x79, 0xf5, 0xae, 0xab, 0x0a, 0x0a, 0x40, + 0xb3, 0x2e, 0xf7, 0x14, 0x51, 0x11, 0xff, 0x93, 0x94, 0xe6, 0x7b, 0x9a, 0xa9, 0x01, 0x9c, 0xd2, 0xf0, 0x37, 0xdf, + 0xfb, 0x4b, 0x59, 0x46, 0x4b, 0x8f, 0x86, 0x4a, 0xc9, 0x20, 0x3e, 0xcc, 0x05, 0x66, 0x6c, 0x98, 0x50, 0x19, 0xb3, + 0x54, 0x77, 0xe9, 0x5a, 0x03, 0x7c, 0x6d, 0x45, 0xab, 0x55, 0x5e, 0x5f, 0x0b, 0xab, 0x63, 0x50, 0xad, 0xec, 0xf8, + 0xb0, 0x82, 0x5b, 0xad, 0x4c, 0x9d, 0x49, 0x37, 0x34, 0x58, 0xad, 0x50, 0xd7, 0x79, 0x7f, 0x19, 0xa9, 0x6b, 0x43, + 0x00, 0x20, 0x37, 0x00, 0x42, 0xd0, 0x5a, 0x5f, 0x8b, 0x09, 0x52, 0xc2, 0x43, 0x19, 0x8b, 0x09, 0x95, 0x6b, 0x88, + 0x4d, 0x75, 0x8e, 0x6a, 0xd7, 0x06, 0xa8, 0x37, 0xa0, 0x8d, 0xeb, 0xd0, 0x5e, 0x00, 0xd2, 0xfb, 0xfb, 0x4b, 0x56, + 0x90, 0xfd, 0x25, 0xcd, 0x46, 0x3c, 0xa1, 0x1f, 0xde, 0x7d, 0x09, 0x97, 0x1c, 0x79, 0x06, 0x86, 0xc5, 0x14, 0x81, + 0xe0, 0x54, 0x9b, 0xa3, 0x45, 0x08, 0x57, 0x22, 0x44, 0x73, 0x02, 0x4f, 0xcd, 0xa5, 0x40, 0x2c, 0x7c, 0xaf, 0xaf, + 0x21, 0xa7, 0x89, 0x86, 0x99, 0x64, 0xaa, 0x17, 0x2f, 0x8e, 0x0f, 0x75, 0x6b, 0x2d, 0x02, 0x74, 0x23, 0x40, 0x82, + 0x3a, 0xa7, 0x15, 0x0e, 0x20, 0xaf, 0xd9, 0xc5, 0x43, 0xc2, 0xae, 0x4a, 0x62, 0x53, 0x17, 0xa8, 0x7a, 0xc7, 0x69, + 0x7c, 0x49, 0xd3, 0xde, 0xfe, 0x32, 0x5b, 0xad, 0x5a, 0xc5, 0xf1, 0xa1, 0x7e, 0xf4, 0x8e, 0x15, 0xdf, 0xd0, 0x2f, + 0xbc, 0x54, 0x5b, 0x0c, 0xb7, 0x12, 0x21, 0xdb, 0xd3, 0xa6, 0x39, 0x45, 0x66, 0x80, 0xc2, 0xf7, 0x54, 0x82, 0x85, + 0x6a, 0x54, 0x2a, 0x44, 0x85, 0xef, 0xb1, 0x64, 0xb3, 0x2c, 0x97, 0x74, 0x0e, 0xa5, 0xd3, 0xd5, 0xaa, 0x5d, 0xf8, + 0xde, 0x8c, 0x65, 0xf0, 0x94, 0xad, 0x56, 0xea, 0xc2, 0xdf, 0x8c, 0x65, 0x41, 0x0b, 0xc8, 0xd6, 0xf7, 0x66, 0xf1, + 0x8d, 0x5a, 0xb0, 0xad, 0x89, 0x6f, 0x82, 0xb6, 0xa9, 0x0a, 0x4b, 0xfc, 0xe4, 0x40, 0x71, 0xd5, 0x8e, 0xa6, 0x66, + 0x47, 0x13, 0xbc, 0xd0, 0x57, 0x99, 0x48, 0x90, 0x90, 0x74, 0xfb, 0x8e, 0x26, 0x76, 0x47, 0x17, 0x3b, 0x76, 0x74, + 0x71, 0xc7, 0x8e, 0xc6, 0x66, 0xf7, 0xbc, 0x12, 0x77, 0x7c, 0xb5, 0x6a, 0xb7, 0x2a, 0xec, 0x1d, 0x1f, 0x26, 0xec, + 0x0a, 0x76, 0x03, 0xd4, 0x3c, 0xc9, 0x66, 0x74, 0x3b, 0x51, 0xd6, 0x51, 0x4c, 0x7f, 0x15, 0x26, 0x2b, 0x2c, 0x64, + 0x75, 0x2c, 0xb8, 0x74, 0x5d, 0xc6, 0xdc, 0xfe, 0x48, 0xca, 0x66, 0x80, 0x87, 0x1c, 0xf0, 0x30, 0x35, 0x78, 0xb8, + 0x28, 0xce, 0x41, 0x24, 0xa8, 0xe5, 0xdc, 0x8b, 0xf4, 0xa0, 0xb5, 0xdf, 0xdb, 0x4d, 0x62, 0x10, 0x0d, 0xbf, 0xe6, + 0x22, 0xf1, 0x23, 0xdd, 0xf4, 0x57, 0x61, 0x66, 0xc6, 0x32, 0x93, 0x5b, 0xb5, 0x93, 0xb4, 0xaa, 0x7a, 0x97, 0xc0, + 0x3a, 0x8f, 0x1e, 0xe9, 0x16, 0xf3, 0x58, 0x4a, 0x2a, 0x32, 0x43, 0xa8, 0xbe, 0xff, 0xff, 0x05, 0xd1, 0x6d, 0x61, + 0x23, 0xb1, 0x65, 0x23, 0x96, 0xde, 0x8c, 0x7e, 0x6e, 0x58, 0xbc, 0x96, 0x46, 0x7b, 0x95, 0xc2, 0x7a, 0x8b, 0x5c, + 0x1b, 0x41, 0x17, 0x81, 0xc9, 0xb2, 0x98, 0xd1, 0xe4, 0x5c, 0xf1, 0xe3, 0xfe, 0xe8, 0xc2, 0xe8, 0xa7, 0x6b, 0xd2, + 0xad, 0xea, 0x80, 0xfd, 0x1f, 0x17, 0x9d, 0x27, 0x0f, 0x4f, 0x7d, 0xac, 0x59, 0x3a, 0x1f, 0x8f, 0x7d, 0x54, 0x78, + 0xf7, 0xeb, 0xd6, 0x7e, 0xf8, 0xe3, 0xe2, 0x8b, 0x17, 0xad, 0x2f, 0xca, 0xce, 0x99, 0x8f, 0x8a, 0x0b, 0x13, 0xce, + 0xb7, 0x92, 0xc9, 0x81, 0xd7, 0xae, 0x68, 0x1c, 0x67, 0xbb, 0x97, 0x33, 0x70, 0x97, 0x93, 0xcf, 0x29, 0x4d, 0xb0, + 0xef, 0xf9, 0x78, 0xa3, 0xf4, 0x3c, 0xa5, 0x57, 0xd4, 0xbe, 0x68, 0x70, 0xcb, 0x64, 0x5b, 0x7a, 0x8c, 0xf8, 0x22, + 0x93, 0x26, 0xaf, 0xc1, 0x70, 0x56, 0x67, 0x49, 0x17, 0x6a, 0x0d, 0xae, 0x49, 0x70, 0xab, 0xc5, 0x5a, 0x5d, 0x58, + 0x15, 0x17, 0xd8, 0x77, 0x00, 0xd8, 0x09, 0x59, 0x7f, 0x47, 0x79, 0xd4, 0xc2, 0xad, 0x5d, 0xb0, 0xe1, 0x36, 0x8a, + 0x7c, 0x7f, 0x68, 0xf1, 0xa4, 0x5c, 0x93, 0xb5, 0xf7, 0x43, 0xec, 0xc4, 0xd7, 0x27, 0x31, 0x70, 0x29, 0x60, 0xb0, + 0x8c, 0xe6, 0xf9, 0x4e, 0x04, 0x94, 0x9b, 0x88, 0xfd, 0xaa, 0xb5, 0xbf, 0x63, 0x14, 0xdc, 0xc2, 0x70, 0xc2, 0x14, + 0xc0, 0x65, 0x80, 0xd4, 0xb4, 0xa2, 0xe3, 0x31, 0x1d, 0x95, 0x9e, 0x5d, 0x08, 0x75, 0x8d, 0x59, 0x2a, 0x21, 0xe2, + 0xa3, 0x42, 0x31, 0xfe, 0x1b, 0x9e, 0x51, 0x1f, 0xd9, 0xe4, 0x4d, 0x03, 0xbf, 0x11, 0xf7, 0xdb, 0xe1, 0xd1, 0x23, + 0xd6, 0x61, 0x31, 0xb3, 0xac, 0x56, 0xd6, 0xab, 0x53, 0x2b, 0xaf, 0x23, 0x92, 0x2b, 0xb7, 0xcd, 0xae, 0x03, 0x74, + 0xbf, 0x63, 0xb2, 0x6c, 0x7f, 0xf1, 0xa8, 0xdd, 0x2a, 0x7c, 0xec, 0xc3, 0x70, 0xf7, 0x3d, 0x25, 0xaa, 0xd7, 0x11, + 0xf4, 0x5a, 0x64, 0xbf, 0xa6, 0x5f, 0xa7, 0xfd, 0x79, 0xdb, 0xc7, 0xfa, 0xbd, 0x01, 0xa8, 0x28, 0x99, 0xc1, 0x08, + 0x7c, 0x9d, 0xbf, 0x7b, 0x29, 0xf5, 0xc1, 0xef, 0x07, 0xcf, 0xe3, 0x76, 0xcb, 0xc7, 0x7e, 0x2e, 0xf9, 0xfc, 0x57, + 0x2c, 0xe1, 0xc8, 0xc7, 0xfe, 0x28, 0xe5, 0x39, 0x75, 0xd7, 0xa0, 0xb5, 0xd7, 0xdf, 0xbf, 0x08, 0x0d, 0xd1, 0x5c, + 0xd0, 0x3c, 0xf7, 0xdc, 0xf1, 0x0d, 0x29, 0x7d, 0x82, 0x61, 0x6e, 0xa5, 0xb8, 0x9c, 0x4a, 0x85, 0x17, 0x7d, 0xa5, + 0xdf, 0xa5, 0x2a, 0x5d, 0xb6, 0x41, 0x6c, 0x4a, 0x04, 0x94, 0x8c, 0x4d, 0x2b, 0x53, 0x9f, 0x9c, 0x79, 0xcb, 0xd1, + 0xd3, 0x13, 0xeb, 0x10, 0xf0, 0xe6, 0x04, 0xb5, 0x92, 0x19, 0xcb, 0xce, 0xb7, 0x94, 0xc6, 0x37, 0x5b, 0x4a, 0x41, + 0x43, 0x2b, 0xa1, 0x33, 0x6f, 0x9b, 0xf9, 0x34, 0xd6, 0x2b, 0x3d, 0xc7, 0x05, 0x31, 0x51, 0x6e, 0xca, 0x4f, 0x40, + 0xea, 0x6c, 0x83, 0x1a, 0xe1, 0xb7, 0x4f, 0x07, 0x25, 0xbf, 0x6a, 0x3a, 0x7a, 0xf3, 0xe9, 0x3d, 0x77, 0x14, 0x9b, + 0xdf, 0x81, 0x7d, 0x73, 0x73, 0x7c, 0x1d, 0xfd, 0x5b, 0x8a, 0x8d, 0xee, 0x51, 0x6e, 0xc1, 0x28, 0x65, 0xb3, 0x6a, + 0x17, 0x36, 0xc1, 0x54, 0x4a, 0x07, 0xa4, 0x0f, 0xb9, 0x83, 0x68, 0xed, 0xe3, 0x1c, 0x2e, 0x45, 0xc2, 0x9b, 0x27, + 0x16, 0x82, 0x9e, 0xa7, 0xfc, 0x7a, 0xfd, 0x4d, 0x5a, 0xbb, 0x1b, 0x4f, 0xd9, 0x64, 0xea, 0xdc, 0x74, 0xa2, 0xa4, + 0x44, 0xfd, 0x9d, 0x13, 0x14, 0xff, 0xfa, 0x2f, 0x61, 0xf8, 0xaf, 0xff, 0xf2, 0xc9, 0xa6, 0x30, 0x7c, 0x71, 0x81, + 0x65, 0x35, 0xec, 0x6e, 0x02, 0xdf, 0x3e, 0x53, 0x1d, 0xe7, 0xdb, 0xdb, 0x6c, 0x6c, 0x02, 0xd4, 0x6f, 0x6c, 0xc1, + 0x46, 0xa1, 0x3e, 0x00, 0xde, 0x6f, 0x01, 0x0c, 0xd6, 0xf5, 0x49, 0xc8, 0xa0, 0xd1, 0xef, 0x02, 0xed, 0x02, 0x45, + 0xf7, 0xda, 0x91, 0xdf, 0x8e, 0xe1, 0x4f, 0xad, 0xe1, 0x77, 0x82, 0x6f, 0x3c, 0x02, 0xa3, 0x8b, 0x8b, 0x32, 0xa5, + 0xcd, 0xed, 0x0a, 0x57, 0xe6, 0xfb, 0x1b, 0x25, 0x46, 0xf6, 0x47, 0x2d, 0xd4, 0x53, 0x17, 0xf2, 0xc8, 0xe8, 0xe2, + 0x35, 0xbc, 0x27, 0xe7, 0xf8, 0x52, 0x58, 0x97, 0xea, 0x1d, 0xfc, 0x19, 0x86, 0xa8, 0xaf, 0x4a, 0x0d, 0xba, 0xc1, + 0x9c, 0xa1, 0x14, 0x34, 0x7e, 0x00, 0x13, 0x8f, 0x2e, 0x8c, 0x7d, 0x77, 0xaa, 0x1d, 0x1f, 0xd1, 0x3a, 0x69, 0x1b, + 0x87, 0x48, 0x0d, 0xe9, 0xd8, 0x7b, 0xaf, 0xf0, 0xa5, 0x1a, 0xd3, 0xca, 0x9e, 0x56, 0xce, 0x25, 0x50, 0xe5, 0x2f, + 0x0a, 0x15, 0x18, 0xff, 0xeb, 0xae, 0xd8, 0xdd, 0xdf, 0x3f, 0x1d, 0xbb, 0xe3, 0xf7, 0x8a, 0xdd, 0xfd, 0xfd, 0x0f, + 0x8f, 0xdd, 0xfd, 0xd5, 0x8d, 0xdd, 0xc1, 0x26, 0x7e, 0x79, 0xaf, 0xf8, 0x9a, 0x8d, 0x7d, 0xf0, 0xeb, 0x9c, 0xb4, + 0x8d, 0x26, 0x9b, 0xf2, 0x09, 0x04, 0xd7, 0xfe, 0xfd, 0x63, 0x65, 0x29, 0x9f, 0xb8, 0x91, 0x32, 0x78, 0x4f, 0x2a, + 0x84, 0xc6, 0xba, 0x36, 0xa6, 0x65, 0xa2, 0x53, 0xad, 0xf2, 0x0e, 0x48, 0xf3, 0xa1, 0x7d, 0x67, 0x81, 0x1f, 0x95, + 0xef, 0x1d, 0x6a, 0xe1, 0x8e, 0x8d, 0x5f, 0x45, 0x2a, 0xf4, 0x55, 0x76, 0xec, 0x34, 0xec, 0x05, 0x07, 0x77, 0x84, + 0xae, 0x7d, 0xaf, 0x8a, 0xbe, 0xef, 0xbe, 0xf4, 0x7f, 0xbc, 0x69, 0x3f, 0x1b, 0xb4, 0xbb, 0x47, 0xed, 0x99, 0x1f, + 0xf9, 0x20, 0xa5, 0x54, 0x41, 0xab, 0x7b, 0x74, 0x04, 0x05, 0xd7, 0x4e, 0x41, 0x07, 0x0a, 0x98, 0x53, 0xf0, 0x08, + 0x0a, 0x46, 0x4e, 0xc1, 0x63, 0x28, 0x48, 0x9c, 0x82, 0x27, 0x50, 0x70, 0xe5, 0x17, 0x03, 0x56, 0x82, 0xfb, 0x04, + 0x0d, 0xb1, 0x36, 0x1e, 0x6c, 0xd9, 0x13, 0xdc, 0x86, 0xa0, 0x59, 0x3c, 0x51, 0xb9, 0x3e, 0xe0, 0x82, 0x8b, 0x38, + 0xbe, 0x9e, 0xd2, 0x2c, 0x82, 0xb0, 0xe5, 0x73, 0x25, 0x63, 0x42, 0xc9, 0xdf, 0xb3, 0x19, 0xb5, 0x5f, 0xa8, 0xb0, + 0x78, 0xf0, 0x7c, 0x34, 0x68, 0x0d, 0x8b, 0x6e, 0xb9, 0x73, 0x3a, 0xda, 0x66, 0xf2, 0x3e, 0xf4, 0x5e, 0x56, 0x75, + 0x7a, 0xba, 0x66, 0xb9, 0xe7, 0x3b, 0xa2, 0x36, 0x8e, 0x3b, 0x60, 0x9c, 0xf2, 0xeb, 0xe6, 0x8d, 0xdf, 0xdb, 0x1e, + 0xc9, 0x01, 0x88, 0xca, 0x48, 0x8e, 0x5a, 0x53, 0xf9, 0xf4, 0x3e, 0x9e, 0x94, 0xbf, 0x5f, 0xd3, 0x3c, 0x8f, 0x27, + 0xa6, 0xe5, 0xee, 0xc8, 0x8d, 0x02, 0xd1, 0x8d, 0xda, 0x58, 0x20, 0x20, 0xfa, 0x02, 0x9b, 0x05, 0xe6, 0xb4, 0x09, + 0xc6, 0x00, 0x76, 0xea, 0x71, 0x1c, 0x35, 0x7d, 0xbd, 0x48, 0xc6, 0x93, 0xaa, 0xe0, 0x78, 0x2e, 0xa8, 0x2a, 0xd5, + 0x18, 0x2e, 0x8e, 0x0f, 0xa1, 0x40, 0x57, 0xef, 0x88, 0xd7, 0x58, 0xdb, 0x7d, 0x77, 0xd4, 0xc6, 0xb3, 0xf1, 0x1a, + 0x37, 0xc3, 0xa5, 0x4c, 0x6f, 0xd9, 0x8c, 0x12, 0x7c, 0xd6, 0x1e, 0xc1, 0x1f, 0x13, 0x83, 0xf8, 0x6c, 0x3c, 0x1e, + 0xdf, 0x19, 0xbf, 0xf9, 0x2c, 0x19, 0xd3, 0x0e, 0x7d, 0xd4, 0x85, 0xec, 0x87, 0xa6, 0xf1, 0xfa, 0xb7, 0x0b, 0x85, + 0xbb, 0xe5, 0xfd, 0x1a, 0x43, 0x80, 0x40, 0x4e, 0x97, 0xf7, 0x8f, 0xe5, 0x14, 0x73, 0x41, 0x97, 0xb3, 0x58, 0x4c, + 0x58, 0x16, 0xb5, 0x8a, 0xf0, 0xca, 0x04, 0x3f, 0x3e, 0x7b, 0xfa, 0xf4, 0x69, 0x11, 0x26, 0xf6, 0xa9, 0x95, 0x24, + 0x45, 0x38, 0x5a, 0x96, 0xcb, 0x68, 0xb5, 0xc6, 0xe3, 0x22, 0x64, 0xb6, 0xe0, 0xa8, 0x33, 0x4a, 0x8e, 0x3a, 0x45, + 0x78, 0xed, 0xb4, 0x28, 0x42, 0x6a, 0x9e, 0x04, 0x4d, 0x6a, 0x29, 0x14, 0x4f, 0x5a, 0xad, 0x22, 0xd4, 0x84, 0xb6, + 0x04, 0x8b, 0x48, 0xff, 0x8c, 0xe2, 0x85, 0xe4, 0xc0, 0x92, 0xbb, 0x5c, 0x06, 0x83, 0x73, 0xf3, 0x7a, 0x0a, 0xfd, + 0x29, 0x87, 0x02, 0x0d, 0xf1, 0x97, 0x6e, 0x98, 0x02, 0x88, 0x59, 0x85, 0x27, 0xb8, 0x8d, 0x62, 0xd4, 0xaa, 0x81, + 0xb2, 0x54, 0xf5, 0x97, 0x84, 0x57, 0xd1, 0x0b, 0xe0, 0x3f, 0xd0, 0x52, 0xbf, 0x47, 0x4d, 0xd2, 0x1d, 0x5c, 0x9f, + 0xd2, 0x4f, 0x72, 0xfd, 0xdb, 0xfb, 0x30, 0x7d, 0x4a, 0xff, 0x68, 0xa6, 0x6f, 0x5e, 0x36, 0xaa, 0x99, 0xbe, 0x66, + 0x6b, 0x33, 0x49, 0xfc, 0xd1, 0x94, 0x8e, 0x3e, 0x5e, 0xf2, 0x9b, 0x26, 0x1c, 0x09, 0xe1, 0x2b, 0x7e, 0xba, 0xff, + 0x5b, 0xd3, 0x2d, 0xec, 0x60, 0xce, 0x97, 0x20, 0x94, 0xd8, 0x7c, 0x9b, 0x11, 0xff, 0xad, 0x35, 0xab, 0x74, 0xc9, + 0x78, 0x4c, 0xfc, 0xb7, 0xe3, 0xb1, 0x6f, 0x2f, 0xd9, 0xc5, 0x92, 0xaa, 0x56, 0x6f, 0x6a, 0x25, 0xaa, 0xd5, 0x17, + 0x5f, 0xb8, 0x65, 0x6e, 0x81, 0x09, 0x72, 0xb8, 0x01, 0x0d, 0x53, 0x93, 0xb0, 0x1c, 0x8e, 0x1a, 0x7c, 0xa0, 0xa2, + 0xfe, 0x96, 0x3f, 0x51, 0x7b, 0x21, 0x73, 0x09, 0xf0, 0x96, 0xb7, 0x48, 0xaf, 0xdf, 0x30, 0x9f, 0x50, 0x9b, 0xf0, + 0xf6, 0xec, 0xf6, 0xcb, 0x24, 0x98, 0x49, 0x54, 0xb0, 0xfc, 0x6d, 0xb6, 0x76, 0x7b, 0x44, 0xc3, 0x48, 0x88, 0xbb, + 0xac, 0x42, 0xf2, 0xc9, 0x24, 0x85, 0x4f, 0x84, 0x2c, 0x6b, 0x6f, 0x1e, 0xd5, 0xdd, 0xfb, 0xb5, 0xf5, 0x46, 0x6e, + 0x47, 0xf3, 0x9e, 0x4e, 0xf5, 0xc5, 0x22, 0x9d, 0x75, 0x7c, 0x65, 0x3e, 0x5d, 0xa3, 0x2c, 0xb2, 0xa5, 0xe1, 0xff, + 0x4b, 0x9d, 0xab, 0x2a, 0x21, 0x4f, 0x43, 0x0f, 0x9c, 0x14, 0x85, 0xc9, 0xf2, 0x4f, 0x58, 0x3e, 0x87, 0x37, 0x62, + 0xea, 0x9e, 0xf4, 0x53, 0x2c, 0x3c, 0xbf, 0x76, 0x22, 0x09, 0xb5, 0xed, 0x2a, 0x6c, 0x28, 0x41, 0xfb, 0x6a, 0x67, + 0xb2, 0xf0, 0x8d, 0xcb, 0xd7, 0x22, 0xd1, 0xf7, 0x34, 0x3e, 0x75, 0x8c, 0xc3, 0x59, 0x21, 0xf8, 0x5d, 0xcb, 0x0d, + 0xb1, 0x55, 0xb6, 0xa0, 0x70, 0x23, 0x65, 0xaa, 0x46, 0x63, 0x4b, 0xf9, 0xe5, 0xf3, 0x79, 0x9c, 0x69, 0x36, 0x4a, + 0x7c, 0xcd, 0x0f, 0xf6, 0x97, 0xd5, 0xce, 0x17, 0xbe, 0x05, 0x5b, 0x13, 0x6f, 0xef, 0xf8, 0x10, 0x3a, 0xf4, 0xbc, + 0x1a, 0xe8, 0xd9, 0x86, 0x3b, 0xff, 0x13, 0x81, 0xf5, 0x8b, 0x30, 0xbf, 0xc6, 0x61, 0x7e, 0xed, 0xfd, 0x79, 0xd9, + 0xbc, 0xa6, 0x97, 0x1f, 0x99, 0x6c, 0xca, 0x78, 0xde, 0x04, 0x85, 0x5f, 0xf9, 0xe5, 0x0c, 0x7b, 0x56, 0xe9, 0x61, + 0xfa, 0x8e, 0x7c, 0x77, 0x91, 0x43, 0xfc, 0x5d, 0xa9, 0xad, 0x51, 0xc6, 0x33, 0xda, 0xad, 0xa7, 0x01, 0xba, 0xe1, + 0x5c, 0x8b, 0xad, 0xe1, 0x92, 0x43, 0xbc, 0x5e, 0xde, 0x46, 0x2d, 0xc3, 0xd6, 0x5b, 0x36, 0x56, 0xdb, 0xda, 0xda, + 0x3e, 0x32, 0xc8, 0x6d, 0x28, 0xe9, 0x25, 0x36, 0x63, 0xd6, 0xbb, 0x62, 0xce, 0x9f, 0x4a, 0x8a, 0x03, 0x6f, 0x9e, + 0xfd, 0xeb, 0x64, 0x13, 0xae, 0x17, 0xab, 0xa4, 0xb8, 0xfb, 0x40, 0x16, 0xc5, 0x63, 0x49, 0x05, 0xbe, 0x4f, 0xcb, + 0x4b, 0x75, 0x7f, 0x65, 0x09, 0x62, 0x26, 0x6a, 0x3f, 0x9d, 0xdf, 0xdc, 0x7f, 0xf8, 0xbb, 0x97, 0x5f, 0x18, 0x1c, + 0xd9, 0xf7, 0xb9, 0xf8, 0x7e, 0x17, 0x0e, 0x42, 0x1a, 0xdf, 0x46, 0x2c, 0x53, 0x32, 0xef, 0x12, 0x5c, 0x72, 0xdd, + 0x39, 0x37, 0xd9, 0x9d, 0x82, 0xa6, 0xea, 0xe3, 0x6d, 0x66, 0x2b, 0x8e, 0x1e, 0xcf, 0x6f, 0xec, 0x6e, 0xb4, 0xd7, + 0xb2, 0x36, 0xff, 0xd0, 0xe4, 0xcc, 0xdd, 0xd9, 0xa0, 0xf5, 0x04, 0xc3, 0x47, 0xf3, 0x9b, 0xae, 0x16, 0xb4, 0x4d, + 0xa1, 0xa1, 0x6a, 0xcd, 0x6f, 0xdc, 0xf4, 0xd4, 0x6a, 0x20, 0x2f, 0x3c, 0xca, 0x3d, 0x1a, 0xe7, 0xb4, 0x0b, 0x6f, + 0xac, 0x66, 0xa3, 0x38, 0x35, 0xc2, 0x7c, 0xc6, 0x92, 0x24, 0xa5, 0x5d, 0x2b, 0xaf, 0xbd, 0xf6, 0x63, 0xc8, 0xee, + 0x74, 0xb7, 0xac, 0xbe, 0x2b, 0x0e, 0xf2, 0x4a, 0x3c, 0xc5, 0x97, 0x39, 0x4f, 0xe1, 0x73, 0x11, 0x5b, 0xd1, 0x69, + 0xd2, 0x1e, 0x5b, 0x15, 0xf2, 0xd4, 0xef, 0xfa, 0x5a, 0x1e, 0xb5, 0xfe, 0xd4, 0x55, 0x1b, 0xde, 0xea, 0x4a, 0x3e, + 0x8f, 0x9a, 0x47, 0xf5, 0x85, 0x40, 0x55, 0xb9, 0x04, 0xbc, 0x65, 0x59, 0x18, 0xa4, 0x95, 0xe6, 0xd3, 0x5e, 0xd8, + 0x36, 0x65, 0x6a, 0x00, 0x78, 0xb5, 0x72, 0x59, 0x54, 0xd4, 0x17, 0xf3, 0xef, 0x73, 0x5a, 0x3e, 0xdf, 0x7e, 0x5a, + 0x3e, 0xb7, 0xa7, 0xe5, 0x6e, 0x8a, 0xfd, 0x6c, 0xdc, 0x86, 0x3f, 0xdd, 0x6a, 0x41, 0x51, 0xcb, 0x3b, 0x9a, 0xdf, + 0x78, 0xa0, 0xa7, 0x35, 0x3b, 0xf3, 0x1b, 0x9d, 0x9c, 0x0b, 0x61, 0x83, 0x16, 0xa4, 0xab, 0xe2, 0x96, 0x07, 0x85, + 0xf0, 0xb7, 0x55, 0xab, 0x6a, 0x3f, 0x84, 0x3a, 0xe8, 0xf5, 0x68, 0xb3, 0xae, 0x73, 0xf7, 0xa1, 0x8d, 0x32, 0x2e, + 0x83, 0xc8, 0x72, 0x63, 0x14, 0xca, 0xf8, 0xf2, 0x92, 0x26, 0xd1, 0x98, 0x8f, 0x16, 0xf9, 0x3f, 0x1b, 0xf8, 0x0d, + 0x12, 0xef, 0x3c, 0xd2, 0x6b, 0xe3, 0xd8, 0xae, 0x3a, 0x55, 0xd8, 0x8e, 0xb0, 0x2c, 0xf7, 0x29, 0xca, 0x47, 0x71, + 0x4a, 0x83, 0x4e, 0xf8, 0x70, 0xcb, 0x21, 0xf8, 0x0f, 0xd9, 0x9b, 0xad, 0x8b, 0xf9, 0xbd, 0xc8, 0xb8, 0x13, 0x09, + 0xbf, 0x0a, 0x07, 0xee, 0x1e, 0xb6, 0x9e, 0x6e, 0x07, 0x77, 0x60, 0x67, 0x1a, 0x5a, 0xa1, 0x60, 0xe4, 0x4e, 0x42, + 0xc7, 0xf1, 0x22, 0x95, 0x77, 0x8f, 0xba, 0x8b, 0x32, 0x36, 0x46, 0xbd, 0x83, 0xa1, 0x57, 0x6d, 0xef, 0xc9, 0xa5, + 0x3f, 0xfb, 0xfc, 0x21, 0xfc, 0xd1, 0x99, 0x46, 0xb7, 0x95, 0xae, 0xae, 0x6d, 0x55, 0xd0, 0xd5, 0xf7, 0x6b, 0xca, + 0xb8, 0x16, 0xe1, 0x4a, 0x1f, 0xbf, 0x6f, 0x6b, 0xd0, 0x2a, 0xef, 0xd5, 0xdc, 0x68, 0x59, 0xbf, 0xaa, 0xf5, 0xaf, + 0x1b, 0xfc, 0x9e, 0x6d, 0x47, 0x5a, 0x73, 0xad, 0xb7, 0x35, 0x5f, 0xaf, 0xdb, 0x68, 0x6c, 0x31, 0xae, 0xda, 0xef, + 0x93, 0xdb, 0xd2, 0x44, 0xd1, 0x81, 0x40, 0xb0, 0x52, 0xf6, 0xb5, 0x95, 0xc2, 0x28, 0x79, 0x00, 0xef, 0x8e, 0xf5, + 0x6e, 0x66, 0x69, 0x96, 0x13, 0x7f, 0x2a, 0xe5, 0x3c, 0xd2, 0x9f, 0x3b, 0xbd, 0x3e, 0x0a, 0xb9, 0x98, 0x1c, 0x76, + 0x5a, 0xad, 0x16, 0xbc, 0xf3, 0xd3, 0xf7, 0xae, 0x18, 0xbd, 0x7e, 0xc6, 0x6f, 0x88, 0xff, 0xc4, 0x7b, 0xea, 0x3d, + 0x39, 0xf2, 0x1e, 0x3d, 0xf6, 0x3d, 0xc5, 0xce, 0x89, 0xff, 0xe4, 0xc8, 0xf7, 0x34, 0x3b, 0x27, 0xfe, 0xa3, 0xc7, + 0x7e, 0xef, 0x78, 0x62, 0x55, 0x32, 0xb8, 0x34, 0xa8, 0xf5, 0x9d, 0x5c, 0x0a, 0xfe, 0x91, 0xd6, 0x0f, 0xae, 0x2e, + 0x33, 0xb9, 0x68, 0x1d, 0xfb, 0x08, 0xa7, 0x77, 0x14, 0xcf, 0x23, 0x45, 0x14, 0x6e, 0x21, 0xb8, 0x65, 0x74, 0xa9, + 0x9a, 0x02, 0xd4, 0xcc, 0x4b, 0xbf, 0x77, 0x0c, 0x79, 0xe3, 0x5e, 0x42, 0xfc, 0xd7, 0x9d, 0x27, 0x5e, 0xfb, 0xf1, + 0x55, 0xf3, 0xe1, 0xa8, 0xd5, 0x6c, 0x7b, 0xed, 0x66, 0x27, 0x7c, 0xe2, 0x75, 0xf4, 0xbf, 0x5e, 0xcb, 0x3b, 0xf2, + 0xda, 0xe1, 0x13, 0xef, 0xc8, 0xeb, 0x84, 0x4f, 0xae, 0x1e, 0xea, 0x7c, 0x82, 0xd8, 0x3f, 0xec, 0x1d, 0xc3, 0xa7, + 0x2b, 0x6f, 0x88, 0xff, 0xb9, 0xaf, 0x3f, 0x10, 0xeb, 0x7f, 0xe6, 0x96, 0xb6, 0x9f, 0x6e, 0x2d, 0xee, 0x3c, 0xd9, + 0x5a, 0x7c, 0xf4, 0x78, 0x6b, 0xf1, 0xc3, 0x47, 0xf5, 0xe2, 0xc3, 0x89, 0xae, 0x2a, 0x4f, 0x39, 0xf1, 0x67, 0xb1, + 0x14, 0xec, 0x26, 0x68, 0x7b, 0x2d, 0xaf, 0xe5, 0x35, 0xe1, 0xbf, 0x27, 0x1d, 0x54, 0xf6, 0xba, 0x84, 0x5e, 0xe5, + 0x2a, 0x9f, 0x3c, 0xf5, 0xda, 0x8f, 0x5f, 0x76, 0x1e, 0x8f, 0xa0, 0x9d, 0x5a, 0x68, 0xdb, 0x6b, 0x5f, 0x1d, 0x3d, + 0x1d, 0xb5, 0x3c, 0xe8, 0xd8, 0x86, 0x3f, 0xd3, 0x47, 0x9d, 0x91, 0x7e, 0x68, 0x41, 0xfd, 0xb7, 0xed, 0x27, 0x79, + 0xab, 0xd9, 0x86, 0x3f, 0xbf, 0x94, 0x1a, 0x31, 0xe8, 0xe3, 0xee, 0xb8, 0x0f, 0x5b, 0xde, 0xd1, 0xd3, 0x69, 0x27, + 0xfc, 0xfc, 0xea, 0x49, 0xf8, 0x74, 0xda, 0x7e, 0xf2, 0xad, 0x7e, 0x4a, 0x9b, 0x9d, 0xf0, 0x73, 0xf8, 0xfb, 0xed, + 0x51, 0x6b, 0xda, 0x6c, 0x87, 0x4f, 0xaf, 0x8e, 0xc2, 0xa3, 0xb4, 0xf9, 0x38, 0x7c, 0x0a, 0x7f, 0xab, 0xe1, 0xa6, + 0x7c, 0x46, 0x7d, 0x0f, 0xf6, 0x7b, 0xcd, 0xdc, 0x72, 0xe7, 0xe8, 0x3c, 0xf4, 0x1e, 0x3d, 0x7c, 0xf9, 0xf4, 0xaa, + 0xf9, 0x70, 0xda, 0xee, 0x5c, 0x35, 0x77, 0xfe, 0xfc, 0x16, 0x10, 0x6f, 0x06, 0x8e, 0x29, 0x5c, 0xe0, 0xb1, 0x88, + 0x53, 0xef, 0x9f, 0x7d, 0x80, 0xf3, 0x5d, 0xe6, 0xb5, 0xf8, 0xb4, 0x79, 0x9d, 0xd1, 0xfb, 0xd8, 0xd7, 0xe2, 0x0f, + 0xb7, 0xaf, 0x73, 0xba, 0xe6, 0x54, 0xbd, 0x95, 0x1b, 0x66, 0xf4, 0xba, 0xed, 0xf5, 0x4e, 0x06, 0x03, 0x06, 0xdf, + 0x39, 0x2a, 0xba, 0xb7, 0xf0, 0x8a, 0x6b, 0xd7, 0xdb, 0xc0, 0xe1, 0x20, 0xdf, 0x4a, 0x7d, 0x92, 0xf9, 0x2e, 0x84, + 0xa4, 0x9f, 0x46, 0xc8, 0xb7, 0xf7, 0xc1, 0x47, 0xfa, 0x87, 0xe3, 0x83, 0xbb, 0xf8, 0xa8, 0xf9, 0x79, 0x95, 0x3d, + 0xab, 0xec, 0xd1, 0x33, 0xf5, 0x1c, 0xc0, 0x1d, 0x8f, 0x86, 0x7f, 0x48, 0xa1, 0x28, 0xf7, 0x75, 0x5c, 0xe1, 0xcd, + 0xaf, 0x71, 0x49, 0xeb, 0x0b, 0x5d, 0xc4, 0x37, 0xc6, 0xff, 0x1c, 0xbe, 0x65, 0x60, 0x1f, 0xae, 0xf4, 0x15, 0x63, + 0xe2, 0x77, 0xc2, 0x56, 0xd8, 0x2a, 0x1d, 0x07, 0x70, 0x89, 0x8f, 0x2c, 0xb9, 0x8c, 0xe1, 0x73, 0x9a, 0x29, 0x9f, + 0xa8, 0x0f, 0x6f, 0xc2, 0xeb, 0xce, 0xd5, 0x27, 0x50, 0xf5, 0x9b, 0xe6, 0x23, 0xdf, 0x37, 0x57, 0xff, 0xe1, 0x92, + 0xd8, 0x37, 0x70, 0x91, 0xce, 0x7a, 0xac, 0x67, 0x60, 0x53, 0xbf, 0xa6, 0x09, 0x8b, 0x03, 0x3f, 0x98, 0x0b, 0x3a, + 0xa6, 0x22, 0x6f, 0xd6, 0x6e, 0x97, 0xa9, 0x8b, 0x65, 0xc8, 0xb7, 0x1f, 0x6e, 0x14, 0xf0, 0xfa, 0x5e, 0x32, 0x30, + 0x5e, 0x2d, 0xdf, 0xa8, 0xf9, 0x7e, 0x81, 0x6d, 0x89, 0x00, 0x8e, 0x5e, 0xa9, 0x06, 0xbe, 0xd6, 0x0d, 0xda, 0x61, + 0xe7, 0x11, 0xd2, 0xbc, 0x04, 0x5e, 0x8b, 0xfa, 0x7d, 0xd0, 0x3c, 0x6a, 0xfd, 0x09, 0x39, 0xdd, 0xca, 0x81, 0x86, + 0xc6, 0xa9, 0x23, 0xaa, 0x0f, 0xde, 0xd6, 0xaf, 0xfe, 0xf9, 0x9a, 0x22, 0x3e, 0xd3, 0x6b, 0x87, 0x17, 0xac, 0x9a, + 0xf8, 0xa1, 0xbe, 0xc0, 0x3e, 0x66, 0x93, 0xc0, 0xfd, 0x9c, 0xa9, 0x7e, 0xed, 0xaa, 0xfa, 0x0a, 0x32, 0x2a, 0xaa, + 0x26, 0x02, 0x2d, 0x95, 0x2f, 0x9e, 0x65, 0x9e, 0x58, 0xad, 0x02, 0x01, 0x8e, 0x58, 0xe2, 0xe0, 0x14, 0x9e, 0x51, + 0x0d, 0xc9, 0x02, 0x97, 0x00, 0x29, 0x04, 0x13, 0xa1, 0xff, 0xaf, 0x8a, 0xed, 0x0f, 0xe3, 0x5e, 0x09, 0xd3, 0x38, + 0x9b, 0x00, 0x15, 0xc6, 0xd9, 0x64, 0xc3, 0x79, 0xa3, 0xc3, 0x09, 0x6b, 0xa5, 0xd5, 0x50, 0x95, 0x93, 0x26, 0x7f, + 0x76, 0xfb, 0xde, 0xbc, 0x9f, 0xc9, 0x07, 0x1f, 0xa8, 0xf2, 0x7d, 0x57, 0xef, 0x92, 0x6d, 0x90, 0x07, 0xfa, 0x03, + 0xe1, 0x2a, 0x21, 0x0d, 0xa4, 0x1f, 0x5c, 0xea, 0xf3, 0x8c, 0xcd, 0x43, 0x7c, 0x2d, 0xfb, 0x12, 0x7a, 0xc5, 0x46, + 0x46, 0x84, 0x61, 0xcf, 0x5c, 0x6c, 0x6e, 0xaa, 0xad, 0x21, 0x6d, 0xac, 0xad, 0xfe, 0x51, 0xac, 0x32, 0x8c, 0x49, + 0xc6, 0xfd, 0xde, 0x83, 0xf2, 0xeb, 0x8c, 0xbb, 0x36, 0x01, 0xbe, 0x5a, 0x3e, 0x10, 0x34, 0xfd, 0x67, 0xf2, 0x00, + 0xbe, 0x5b, 0xfe, 0x60, 0x08, 0x9f, 0xcc, 0x0e, 0x95, 0x28, 0x78, 0x50, 0x7d, 0xbe, 0x1c, 0xf8, 0x60, 0xe3, 0x66, + 0x96, 0xe2, 0xfb, 0x8a, 0x6f, 0x23, 0xaa, 0x3b, 0x8f, 0x2a, 0x51, 0xdd, 0x79, 0xe4, 0x4a, 0xcf, 0xb6, 0xd7, 0xee, + 0x84, 0x8f, 0x1c, 0x01, 0x70, 0xd5, 0x84, 0xff, 0x6b, 0x22, 0xe0, 0x61, 0xf8, 0xa8, 0x94, 0x01, 0xaf, 0xda, 0x9d, + 0xf0, 0x48, 0x8b, 0x9b, 0x4e, 0xf8, 0xe8, 0x07, 0xc5, 0xa0, 0x35, 0x73, 0xae, 0x1f, 0x88, 0x2d, 0xa1, 0x1a, 0x9d, + 0x54, 0xe7, 0xe3, 0xa0, 0xfc, 0x06, 0x9c, 0x39, 0x9f, 0xc6, 0x25, 0xf4, 0x3c, 0x16, 0xf0, 0x21, 0x8e, 0xfa, 0xd9, + 0xad, 0xd5, 0xe1, 0x1a, 0xbf, 0xd8, 0x32, 0x05, 0x9c, 0x70, 0x1f, 0xbb, 0x37, 0x83, 0xe1, 0x5a, 0xad, 0x7a, 0x6d, + 0xb1, 0x7d, 0x7b, 0xdb, 0x6e, 0xd2, 0xd6, 0x0d, 0xed, 0x1b, 0xe2, 0x14, 0xb3, 0x60, 0xea, 0x15, 0xf1, 0x6a, 0x92, + 0x2f, 0x93, 0x62, 0x7d, 0x7e, 0xc8, 0xed, 0x13, 0xdc, 0xb9, 0x1c, 0x4d, 0xab, 0x04, 0xf4, 0x84, 0xc1, 0x75, 0xf6, + 0xa2, 0xb0, 0xa0, 0xd7, 0x9c, 0x81, 0x15, 0x96, 0x14, 0xbf, 0xa0, 0x79, 0xdf, 0x87, 0x22, 0x3f, 0xf2, 0x95, 0x23, + 0xc9, 0x2f, 0x3f, 0x46, 0x52, 0x12, 0x76, 0x55, 0x80, 0xd5, 0x25, 0x12, 0x38, 0xb5, 0x80, 0x1f, 0x1f, 0x1d, 0x1c, + 0xec, 0x3c, 0x2f, 0x4a, 0x1b, 0x83, 0xb5, 0x56, 0x1f, 0x31, 0x70, 0x59, 0x91, 0xef, 0x22, 0xba, 0x1c, 0x57, 0xa1, + 0x10, 0x19, 0x3c, 0x5d, 0xd2, 0x58, 0x86, 0x71, 0xa6, 0x53, 0x14, 0x1c, 0x86, 0x85, 0xdb, 0xf4, 0x08, 0x15, 0x5c, + 0xc6, 0xce, 0x57, 0x4a, 0xcd, 0x39, 0xe7, 0x32, 0xb6, 0x57, 0xfd, 0x32, 0x59, 0xcb, 0x85, 0x9f, 0x76, 0x7a, 0x6f, + 0xdf, 0x9f, 0x78, 0xfa, 0x78, 0x1e, 0x1f, 0x4e, 0x3b, 0xbd, 0x63, 0x65, 0x99, 0xeb, 0x8b, 0x42, 0x44, 0x5f, 0x14, + 0xf2, 0xcc, 0xa5, 0x31, 0x88, 0xd7, 0x14, 0x87, 0x7a, 0xd9, 0xbe, 0x47, 0xb3, 0x91, 0xf6, 0x29, 0xce, 0x16, 0xa9, + 0x64, 0xf0, 0x0a, 0xde, 0x43, 0xe8, 0xda, 0x84, 0x0d, 0x2b, 0x13, 0x4d, 0xad, 0x86, 0x23, 0x33, 0xeb, 0x81, 0x1c, + 0xb3, 0x94, 0xda, 0xd4, 0x52, 0x33, 0x54, 0x99, 0xf9, 0xbc, 0xd9, 0x3a, 0x5f, 0x5c, 0xce, 0x98, 0xf4, 0x6d, 0x7e, + 0xf6, 0x07, 0xd3, 0xe1, 0x58, 0x4d, 0xd5, 0xbb, 0x28, 0x8c, 0x8b, 0xd4, 0x7e, 0x6e, 0x64, 0xed, 0x03, 0xef, 0x7a, + 0xf5, 0x46, 0x42, 0xc0, 0x8d, 0x9f, 0xe9, 0x51, 0xaf, 0x74, 0x4a, 0xba, 0x75, 0xc5, 0xf1, 0xe1, 0xf4, 0xa8, 0x77, + 0x11, 0xcd, 0xcd, 0x78, 0xaf, 0xf8, 0xc6, 0xc7, 0xe2, 0x4b, 0x8e, 0xd9, 0x57, 0xa9, 0xed, 0xfa, 0x0e, 0xa5, 0x01, + 0x78, 0xc4, 0x53, 0xbf, 0x77, 0x6c, 0x94, 0x01, 0x4f, 0x05, 0x5d, 0xfd, 0x47, 0x2d, 0x9b, 0x2d, 0x9f, 0x72, 0xa5, + 0x2d, 0xe9, 0x2e, 0xce, 0x24, 0x35, 0xbf, 0xee, 0xb4, 0xdd, 0x3b, 0x8e, 0x8d, 0x9a, 0x09, 0xcc, 0x23, 0x8f, 0x0e, + 0xa1, 0x33, 0xe8, 0x72, 0x21, 0xe3, 0x87, 0xd7, 0xf4, 0xb2, 0x19, 0xcf, 0x59, 0xe5, 0x44, 0x05, 0xa5, 0xa3, 0x9c, + 0x92, 0x57, 0x33, 0xc1, 0xcf, 0x78, 0x6d, 0x91, 0x8a, 0x85, 0x17, 0xc6, 0x43, 0xab, 0x74, 0x75, 0x1a, 0x4b, 0xdf, + 0xd3, 0x1c, 0xde, 0x7a, 0x72, 0x8d, 0xec, 0x2d, 0xfc, 0xde, 0xbf, 0xfd, 0x8f, 0xff, 0x65, 0x9c, 0xb3, 0xc7, 0x87, + 0xd3, 0xb6, 0x1d, 0x6b, 0x0d, 0xd1, 0xc5, 0x31, 0x5c, 0x30, 0xab, 0xa2, 0x89, 0xf4, 0xa6, 0x39, 0x11, 0x2c, 0x69, + 0x4e, 0xe3, 0x74, 0xec, 0xf7, 0x76, 0x23, 0xc8, 0xbd, 0x59, 0x62, 0xa0, 0xae, 0x17, 0x01, 0x09, 0xfe, 0xa6, 0xbb, + 0x11, 0x36, 0xc5, 0x5e, 0x9d, 0x56, 0xf7, 0xa6, 0x44, 0x75, 0xa0, 0x6a, 0xb7, 0x25, 0x84, 0xf9, 0x2a, 0x91, 0x61, + 0x6a, 0xa2, 0x76, 0x49, 0xa2, 0xf0, 0xbd, 0x32, 0x1a, 0xf2, 0x7f, 0xff, 0xe7, 0x7f, 0xf9, 0x6f, 0xf6, 0x11, 0x82, + 0x1c, 0xff, 0xf6, 0xdf, 0xff, 0xf3, 0xff, 0xf9, 0xdf, 0xff, 0x15, 0x12, 0xeb, 0x4d, 0x20, 0x44, 0xf1, 0x09, 0xaf, + 0x8a, 0x82, 0x68, 0x86, 0xe1, 0x41, 0x32, 0xda, 0x8c, 0xe5, 0x92, 0x8d, 0xea, 0xd7, 0x26, 0xce, 0xd4, 0x84, 0xea, + 0xb0, 0x19, 0xe8, 0xd4, 0xa1, 0x2d, 0x2a, 0x1a, 0xa9, 0xa1, 0x5c, 0xd1, 0x62, 0x71, 0x7c, 0x08, 0xf8, 0xbe, 0xdf, + 0x4d, 0xb3, 0xb0, 0xdc, 0x8e, 0xa5, 0x75, 0xfd, 0x41, 0x49, 0x51, 0x95, 0x7b, 0xe0, 0x94, 0x5f, 0xc2, 0x63, 0xd4, + 0x71, 0x8a, 0xd5, 0xee, 0xd5, 0xfa, 0x74, 0x7f, 0x5a, 0xe4, 0x92, 0x8d, 0x01, 0xe5, 0xda, 0xc1, 0xa8, 0xe2, 0x9f, + 0x4d, 0x50, 0xff, 0xd2, 0xdb, 0x42, 0x8d, 0xa2, 0x6d, 0xc6, 0x87, 0x4f, 0xff, 0x54, 0xfc, 0x65, 0x06, 0x4a, 0x96, + 0x17, 0xcc, 0xe2, 0x1b, 0x63, 0x49, 0x3e, 0x6e, 0xb5, 0xe6, 0x37, 0x68, 0x59, 0xcd, 0x80, 0x77, 0x4d, 0xa6, 0x9c, + 0x92, 0xee, 0x80, 0x2a, 0x70, 0x5a, 0xfa, 0x3f, 0x5b, 0x1e, 0x38, 0x51, 0xbd, 0x56, 0x51, 0xfc, 0x79, 0xa9, 0x5c, + 0x70, 0xec, 0x17, 0x08, 0x70, 0x1a, 0x6f, 0xe5, 0x25, 0x77, 0x17, 0xb7, 0x74, 0x7a, 0x75, 0x74, 0xaf, 0x69, 0x7b, + 0xf3, 0x02, 0x95, 0x1b, 0xa0, 0x75, 0x43, 0xab, 0x0f, 0x21, 0x58, 0x3a, 0x6d, 0xe3, 0x69, 0x67, 0x59, 0x0e, 0x2f, + 0x25, 0x9f, 0xb9, 0x11, 0x59, 0x1a, 0xd3, 0x11, 0x1d, 0x5b, 0x2f, 0xaf, 0xa9, 0xd7, 0xd1, 0xd6, 0x62, 0x7a, 0xb4, + 0x65, 0x2e, 0x03, 0x92, 0x8a, 0xc4, 0x7a, 0xad, 0xe2, 0x33, 0x38, 0x81, 0xcb, 0x71, 0xca, 0x63, 0x19, 0x29, 0x82, + 0xed, 0xba, 0x71, 0xdd, 0x18, 0xd8, 0x0c, 0x5f, 0x3a, 0xf0, 0x74, 0x75, 0x53, 0xf0, 0xb7, 0xd6, 0xaf, 0xb9, 0x15, + 0xa1, 0xea, 0xee, 0x0e, 0xa5, 0xdd, 0x35, 0xdf, 0x9a, 0x70, 0xe9, 0x9b, 0x9a, 0x9f, 0xc3, 0xc8, 0x98, 0x0e, 0xda, + 0x5e, 0xaf, 0x45, 0xb5, 0xae, 0xfd, 0x4a, 0x06, 0xbe, 0x02, 0xd3, 0x5f, 0x6f, 0xa5, 0x0a, 0xa1, 0xd5, 0x1b, 0xf2, + 0x6d, 0x69, 0x05, 0xc5, 0xf3, 0xb9, 0x6a, 0x88, 0xba, 0xc7, 0x87, 0x5a, 0x79, 0x05, 0xee, 0xa1, 0x72, 0x01, 0x74, + 0xe8, 0xdd, 0x34, 0x32, 0x47, 0x41, 0xff, 0x32, 0x41, 0x79, 0xf8, 0x5c, 0x55, 0xef, 0xff, 0x01, 0xb9, 0x37, 0x65, + 0xfc, 0x3f, 0x86, 0x00, 0x00}; } // namespace web_server } // namespace esphome + #endif #endif diff --git a/esphome/components/web_server/server_index_v3.h b/esphome/components/web_server/server_index_v3.h index 49de0cfab6..a7ad3ab543 100644 --- a/esphome/components/web_server/server_index_v3.h +++ b/esphome/components/web_server/server_index_v3.h @@ -1,10 +1,12 @@ #pragma once // Generated from https://github.com/esphome/esphome-webserver + #ifdef USE_WEBSERVER_LOCAL #if USE_WEBSERVER_VERSION == 3 -#include "esphome/core/hal.h" -namespace esphome { +#include "esphome/core/hal.h" + +namespace esphome { namespace web_server { const uint8_t INDEX_GZ[] PROGMEM = { @@ -3629,367 +3631,368 @@ const uint8_t INDEX_GZ[] PROGMEM = { 0x46, 0x5a, 0xa5, 0xf5, 0x21, 0x2e, 0x2e, 0xb9, 0x89, 0xa8, 0x62, 0xde, 0x56, 0x7a, 0x54, 0x88, 0x37, 0x2c, 0x80, 0x9e, 0xd2, 0xd3, 0x9a, 0xff, 0x6c, 0x94, 0x54, 0x45, 0xfe, 0x13, 0xbf, 0x03, 0xe6, 0xaa, 0xac, 0xe4, 0x0a, 0x58, 0xea, 0xf8, 0x52, 0x8b, 0x48, 0x68, 0xc8, 0xbf, 0xac, 0xba, 0xed, 0x96, 0x8f, 0x70, 0x49, 0x02, 0x5f, 0x36, 0xaa, - 0xe4, 0xe5, 0x65, 0xce, 0xc3, 0xc0, 0xc4, 0xf8, 0x08, 0xa8, 0xad, 0x66, 0xf6, 0x7f, 0x8a, 0x3b, 0xda, 0xe5, 0xb6, - 0x6d, 0xe4, 0xff, 0x7b, 0x0a, 0x86, 0xc9, 0xa5, 0x62, 0x42, 0xd2, 0xa4, 0x64, 0xd9, 0x8e, 0x64, 0xd9, 0x6d, 0x93, - 0x74, 0xce, 0x1d, 0xb7, 0xe9, 0x24, 0xbe, 0xcc, 0x5d, 0x5d, 0x8f, 0x45, 0x51, 0x90, 0xc4, 0x0b, 0x45, 0x6a, 0x48, - 0xca, 0x96, 0xab, 0xf2, 0x9e, 0xa5, 0xcf, 0x72, 0x4f, 0x76, 0xb3, 0xbb, 0x00, 0x08, 0x7e, 0xe8, 0xc3, 0x4d, 0x7a, - 0x37, 0x3d, 0x5f, 0x44, 0x10, 0x00, 0x81, 0x05, 0xb0, 0xbb, 0xd8, 0xcf, 0x27, 0x8e, 0x08, 0xac, 0x69, 0xe4, 0x9b, - 0x8e, 0x96, 0x98, 0x31, 0x93, 0x91, 0xe7, 0x88, 0xc1, 0x44, 0x11, 0xea, 0x1d, 0x6a, 0x21, 0xf8, 0xba, 0x14, 0x47, - 0xd7, 0x1a, 0xc7, 0xcb, 0x51, 0xc8, 0x2c, 0xdc, 0xee, 0xf0, 0xc9, 0xf5, 0x68, 0x39, 0x1a, 0x41, 0x32, 0x95, 0x27, - 0x8e, 0x09, 0xe1, 0x61, 0xe2, 0x14, 0xaf, 0x6d, 0xb9, 0xd1, 0x87, 0x49, 0xd9, 0x59, 0x75, 0xf8, 0x60, 0xd2, 0x01, - 0x12, 0x19, 0xfa, 0x40, 0x06, 0x57, 0xb4, 0x86, 0x53, 0x3b, 0xd0, 0x3f, 0xc0, 0xee, 0x4b, 0xf5, 0x7e, 0xd3, 0xd1, - 0x1f, 0x5c, 0xeb, 0x1f, 0x10, 0xc6, 0x98, 0x64, 0xf8, 0x35, 0xed, 0x5e, 0xdd, 0xd4, 0x49, 0x37, 0xbd, 0xc4, 0x74, - 0x03, 0x20, 0x9b, 0x7d, 0x13, 0x78, 0xd3, 0x28, 0x4e, 0xb3, 0xc0, 0xd7, 0x6f, 0xfa, 0x17, 0x41, 0xeb, 0x7a, 0x9e, - 0xb5, 0x8c, 0x1b, 0xd3, 0xcf, 0xd4, 0x4c, 0x25, 0x02, 0x61, 0x62, 0xa2, 0x92, 0x4d, 0x95, 0xd4, 0x13, 0xb4, 0xb5, - 0xa2, 0x40, 0xcd, 0x58, 0xc9, 0xcf, 0x06, 0x50, 0xaf, 0x92, 0xf6, 0x04, 0xf3, 0x37, 0xe9, 0xd8, 0xd2, 0xe8, 0xd3, - 0x85, 0xe2, 0xf5, 0x72, 0x8d, 0xa4, 0x3c, 0x2b, 0xa8, 0x25, 0x86, 0xea, 0x15, 0xfe, 0x2d, 0xf4, 0xfc, 0x44, 0xb5, - 0xcd, 0x2c, 0xd1, 0xdd, 0xe1, 0x37, 0x65, 0xbe, 0x00, 0xe8, 0x37, 0x18, 0x46, 0x44, 0x71, 0xa6, 0x41, 0xfc, 0x19, - 0xf8, 0xe2, 0xb0, 0x6a, 0xcb, 0xc5, 0x7b, 0x6d, 0x19, 0x39, 0x47, 0x06, 0xdf, 0x22, 0xf1, 0x6b, 0xf1, 0x28, 0x64, - 0xa5, 0x40, 0x13, 0xc4, 0xd3, 0x47, 0xb0, 0x80, 0x59, 0x7c, 0x19, 0xdf, 0x57, 0xd5, 0x15, 0xaf, 0x87, 0xbb, 0x69, - 0x2f, 0x12, 0x40, 0xd8, 0x6f, 0x22, 0xf9, 0x5e, 0x8b, 0xe7, 0x0f, 0x15, 0x8c, 0x4e, 0xe5, 0x4c, 0xa1, 0x7d, 0x86, - 0xe0, 0x61, 0x32, 0x30, 0xe7, 0x42, 0x5a, 0x00, 0x28, 0x89, 0x93, 0xe9, 0x61, 0x7e, 0x2b, 0x32, 0x1c, 0x8b, 0xfc, - 0xc2, 0x0a, 0x71, 0x06, 0xec, 0x1a, 0x2d, 0x96, 0x19, 0x46, 0xc4, 0x85, 0x01, 0xb0, 0x5c, 0xd7, 0x30, 0xc2, 0x26, - 0x60, 0xe9, 0x82, 0x4d, 0xcc, 0x75, 0x2d, 0x18, 0xd7, 0xcb, 0x88, 0xe7, 0x05, 0xdc, 0x85, 0xe8, 0x1d, 0xc5, 0x49, - 0xf0, 0x98, 0xf0, 0x59, 0xf8, 0x66, 0x11, 0x4d, 0xbe, 0xe5, 0xa3, 0xda, 0xa5, 0x01, 0x31, 0xf8, 0x84, 0xf8, 0xfa, - 0xad, 0xb0, 0x71, 0xae, 0x10, 0x24, 0xb3, 0x34, 0xcb, 0xe1, 0xb3, 0x75, 0x94, 0x9f, 0x3f, 0x5b, 0xa7, 0xf9, 0xe0, - 0xd9, 0xda, 0x03, 0x46, 0x2e, 0xd7, 0x61, 0x9e, 0x85, 0x3b, 0x4d, 0x31, 0x3b, 0xd8, 0x53, 0x54, 0xae, 0xa1, 0x3e, - 0x7d, 0xc0, 0xb5, 0xe6, 0x8b, 0x24, 0x98, 0x7b, 0xc9, 0x03, 0x29, 0xd9, 0x4d, 0x55, 0x13, 0x6f, 0xe8, 0x1a, 0xa1, - 0x75, 0x9a, 0x2e, 0x61, 0x78, 0x5d, 0xfb, 0x5a, 0x96, 0x31, 0x3e, 0x39, 0xa9, 0x69, 0x84, 0x6f, 0xdd, 0xea, 0x2f, - 0x99, 0x3d, 0x66, 0x99, 0x17, 0x84, 0xd4, 0xa4, 0x2f, 0x52, 0xc8, 0xd7, 0x66, 0x93, 0x96, 0x67, 0x13, 0x95, 0x77, - 0x0b, 0x4e, 0x86, 0x10, 0x3e, 0x8d, 0x1b, 0x67, 0x86, 0xa9, 0xa5, 0x9a, 0xd7, 0x8f, 0xde, 0xfd, 0x4f, 0xa1, 0xcf, - 0x00, 0xfa, 0x11, 0x40, 0x9f, 0x45, 0x7e, 0x3c, 0x66, 0x7f, 0x7f, 0x7f, 0x21, 0x73, 0x59, 0x81, 0x58, 0x66, 0xc8, - 0xb7, 0x61, 0x8a, 0xdc, 0x42, 0x82, 0x9c, 0x02, 0x65, 0x9d, 0x2a, 0x76, 0x4c, 0x92, 0xeb, 0xda, 0x39, 0x8d, 0x9d, - 0x8d, 0x69, 0xd4, 0x83, 0x18, 0x5b, 0x25, 0xf9, 0xe9, 0x01, 0xd5, 0x26, 0xda, 0x46, 0x95, 0x00, 0x0c, 0x09, 0xcc, - 0xb0, 0x80, 0x02, 0xa4, 0xdd, 0x1c, 0xb8, 0xc5, 0xf5, 0xc1, 0x9e, 0xa3, 0xf0, 0xdb, 0x3d, 0x2f, 0x33, 0x26, 0xd8, - 0x4a, 0x3f, 0x3b, 0xc5, 0x44, 0x5a, 0x40, 0x9d, 0x21, 0xf4, 0xc6, 0xe9, 0x01, 0x3d, 0x6a, 0x95, 0xfd, 0x5f, 0x74, - 0x22, 0x2e, 0x72, 0x3d, 0xde, 0xc1, 0xa3, 0x0e, 0x06, 0xe4, 0x6d, 0x87, 0x52, 0x2f, 0xd7, 0xb5, 0x39, 0x67, 0x84, - 0x78, 0x8c, 0x1f, 0x08, 0x00, 0xe0, 0xc0, 0x49, 0xd5, 0xb5, 0xb9, 0xb7, 0xc2, 0x99, 0x8b, 0x37, 0xde, 0xaa, 0xe5, - 0xf2, 0x57, 0xb6, 0x04, 0x54, 0x5a, 0x3e, 0x5a, 0x3e, 0x5f, 0x5c, 0xb0, 0xee, 0x17, 0x42, 0xdb, 0xd6, 0x0c, 0xb5, - 0xa6, 0x0d, 0x8b, 0x3b, 0x13, 0x8b, 0x3b, 0xde, 0xb0, 0xb8, 0xe3, 0x2d, 0x8b, 0x1b, 0xf2, 0x85, 0xd4, 0x24, 0xe8, - 0x12, 0xf4, 0xd8, 0x92, 0xc0, 0xe3, 0x6c, 0x45, 0x8f, 0x9f, 0x33, 0x84, 0x93, 0x95, 0x86, 0x60, 0xb1, 0xb4, 0x01, - 0x56, 0x4d, 0x70, 0x51, 0x00, 0xa1, 0xa2, 0x94, 0xb4, 0x74, 0xe8, 0xc4, 0xb4, 0x21, 0x2f, 0x66, 0x2b, 0xac, 0x4e, - 0x17, 0x36, 0x29, 0xe5, 0xfc, 0x6e, 0xcd, 0x36, 0x4c, 0x74, 0xb6, 0x65, 0xa2, 0x7e, 0xe9, 0xe4, 0xf2, 0x59, 0xd3, - 0x19, 0x54, 0xe7, 0x04, 0x5b, 0x10, 0x8c, 0x38, 0x71, 0xc7, 0x94, 0xb7, 0xe1, 0x66, 0x84, 0xaa, 0x6c, 0xa8, 0x85, - 0x97, 0xa6, 0xf7, 0x71, 0x02, 0x5a, 0x10, 0xe8, 0xe6, 0x71, 0x3b, 0x6a, 0x1e, 0x44, 0x3c, 0xc0, 0xca, 0xc6, 0xbd, - 0x54, 0xbc, 0x57, 0x77, 0x54, 0xbb, 0xdb, 0xa5, 0x1a, 0x0b, 0x2f, 0xcb, 0x58, 0x82, 0x30, 0xf7, 0x20, 0x12, 0x77, - 0x0d, 0xd8, 0xff, 0x97, 0x4d, 0xd6, 0x80, 0x41, 0x42, 0xa3, 0xc0, 0xe9, 0x88, 0x9f, 0x17, 0xc0, 0x47, 0x25, 0x82, - 0xe8, 0x2a, 0xb1, 0xda, 0x12, 0x09, 0xf7, 0x1f, 0xf1, 0xb0, 0xb6, 0x12, 0xc5, 0x9b, 0xc8, 0x3d, 0x32, 0xec, 0x85, - 0x37, 0xfe, 0x00, 0xba, 0xb6, 0x56, 0xdb, 0x04, 0xbb, 0x59, 0x35, 0x32, 0x5b, 0x42, 0x8c, 0x9d, 0x5f, 0xa0, 0x48, - 0xc4, 0x91, 0xdc, 0x2a, 0x09, 0x1c, 0x1a, 0x3d, 0x6b, 0x72, 0xb3, 0x6e, 0xe7, 0x07, 0xd3, 0xc0, 0xa8, 0xe1, 0x4c, - 0x40, 0x6c, 0xe1, 0xe0, 0x4c, 0xde, 0xaf, 0x42, 0xd3, 0x3d, 0x32, 0x40, 0x18, 0x7b, 0x0d, 0x29, 0x46, 0x1d, 0x71, - 0x79, 0x1d, 0x26, 0x40, 0xa2, 0xae, 0x9d, 0x9b, 0xfc, 0xf9, 0x14, 0x7f, 0xb9, 0x37, 0xf9, 0xf3, 0x11, 0xfe, 0x6a, - 0xdf, 0x60, 0x32, 0xb9, 0x86, 0x4b, 0xbb, 0x32, 0x67, 0xfd, 0xac, 0xb4, 0x9d, 0xc8, 0x24, 0xec, 0xf1, 0x04, 0xfa, - 0xe9, 0xb3, 0x75, 0x0a, 0x4e, 0x90, 0xea, 0x1c, 0x22, 0x3b, 0x31, 0xf2, 0xc6, 0xf2, 0xe9, 0x86, 0xf2, 0x91, 0xf1, - 0x3f, 0xa6, 0xf2, 0xb8, 0x4b, 0xe2, 0x82, 0xa2, 0x94, 0x45, 0x0e, 0xb7, 0xa3, 0x20, 0xf2, 0x92, 0x87, 0x5b, 0xba, - 0x4a, 0xb4, 0x04, 0x9f, 0x2e, 0x45, 0x29, 0xc4, 0x4a, 0x96, 0x35, 0x50, 0x99, 0x22, 0x73, 0x7d, 0xe0, 0x64, 0x7e, - 0xf0, 0x8f, 0x44, 0x61, 0xd1, 0x4a, 0x97, 0x4d, 0xbe, 0x20, 0xa5, 0x0f, 0xdd, 0x3e, 0x5b, 0xb7, 0x58, 0xbd, 0x9b, - 0xca, 0x6c, 0x2b, 0x3c, 0x20, 0x2c, 0x0f, 0x5e, 0x5c, 0xe7, 0xe3, 0xa0, 0x87, 0x2a, 0xa6, 0x51, 0xbc, 0xb2, 0x9e, - 0xad, 0xb3, 0x73, 0x7d, 0xee, 0x25, 0x9f, 0xd8, 0xd8, 0xf2, 0x83, 0xc4, 0x0f, 0x99, 0xde, 0xd3, 0x47, 0xa1, 0x17, - 0x7d, 0xe2, 0x8f, 0x56, 0xbc, 0xcc, 0x50, 0x69, 0xbc, 0xf3, 0x9e, 0x2b, 0x60, 0x42, 0xe2, 0x39, 0x64, 0x4c, 0x1b, - 0xa0, 0xa0, 0xbd, 0x96, 0xc2, 0xad, 0x82, 0x29, 0x2c, 0x6a, 0x99, 0x60, 0xf3, 0x08, 0x7a, 0x6c, 0x70, 0x22, 0x35, - 0x75, 0x5c, 0x2f, 0xdd, 0x54, 0xa7, 0x4a, 0x82, 0x49, 0x99, 0x05, 0xf1, 0x16, 0x7b, 0xf8, 0xe3, 0x9f, 0xa3, 0xfc, - 0xd4, 0xfb, 0x7f, 0x8e, 0x73, 0x78, 0x9b, 0x3f, 0xa8, 0x36, 0xf6, 0xd2, 0x74, 0x39, 0x67, 0x63, 0xd2, 0x97, 0x9d, - 0x17, 0x43, 0x29, 0x33, 0xf2, 0xea, 0x70, 0x7e, 0x59, 0xb6, 0x8f, 0x0f, 0x5f, 0x83, 0x1e, 0x1f, 0x38, 0xba, 0x78, - 0x32, 0xd1, 0x8b, 0x2b, 0xf5, 0x8e, 0x66, 0xee, 0xe1, 0x2f, 0xcb, 0xef, 0xde, 0x3a, 0xdf, 0xc9, 0xc6, 0x91, 0x6e, - 0xe4, 0x43, 0xa1, 0x94, 0xe4, 0x8c, 0xa9, 0x32, 0x5e, 0x31, 0xa3, 0x89, 0x17, 0x6d, 0x9e, 0xce, 0x75, 0x69, 0x97, - 0x2d, 0x18, 0x1b, 0x83, 0xbd, 0xaa, 0x59, 0x2b, 0xbd, 0x0d, 0xd9, 0x1d, 0x93, 0x0a, 0xcf, 0xfa, 0xc7, 0x1a, 0x5a, - 0x60, 0x44, 0x36, 0xae, 0x48, 0xe5, 0x6c, 0x95, 0x32, 0xa5, 0x21, 0xce, 0x81, 0xcf, 0x5c, 0xdd, 0xe5, 0x95, 0x5d, - 0x3d, 0x34, 0x75, 0x65, 0x00, 0x1b, 0x47, 0x76, 0xbe, 0xa1, 0xbc, 0x87, 0xe9, 0x98, 0x9b, 0xc7, 0x66, 0xba, 0x46, - 0x0f, 0x22, 0x58, 0x73, 0x38, 0x85, 0xb0, 0xf9, 0x5b, 0x85, 0xf4, 0x61, 0x13, 0xc4, 0x9a, 0x64, 0x52, 0xba, 0x90, - 0xf1, 0x34, 0x2e, 0x84, 0x56, 0x9e, 0xe6, 0x08, 0x73, 0x9a, 0x46, 0x2c, 0x4d, 0x37, 0x42, 0x47, 0xae, 0xb0, 0xa9, - 0x17, 0xb5, 0xcb, 0x93, 0x2f, 0xca, 0x4d, 0xc7, 0x04, 0x0a, 0x8c, 0xb3, 0xa9, 0x7e, 0x0b, 0xd1, 0xf9, 0xed, 0x9c, - 0x9b, 0x6c, 0x24, 0xd3, 0x91, 0xce, 0xd5, 0xe9, 0x9b, 0xde, 0xdf, 0xeb, 0x7c, 0x50, 0x25, 0xb2, 0xd8, 0x38, 0xb4, - 0x56, 0x09, 0xd5, 0xd5, 0x44, 0x31, 0xd8, 0x81, 0x18, 0x53, 0x05, 0x9f, 0xb1, 0xc9, 0x84, 0xf9, 0x59, 0x6a, 0x08, - 0xc1, 0x8c, 0x0c, 0xa0, 0x0a, 0x8e, 0x33, 0x4f, 0x06, 0xfa, 0x8f, 0xe0, 0x46, 0x2e, 0xe2, 0x0c, 0xf1, 0x01, 0x89, - 0x1b, 0x4a, 0x33, 0x98, 0xa8, 0xc7, 0x32, 0x88, 0xf8, 0x57, 0x20, 0x3f, 0x76, 0x43, 0x39, 0x0e, 0x8d, 0xe3, 0xfb, - 0x62, 0x13, 0xc4, 0xd2, 0xb0, 0x63, 0x3b, 0xb6, 0xd9, 0x76, 0x56, 0xd7, 0xee, 0x77, 0x5d, 0xd7, 0xc9, 0x75, 0x13, - 0xdc, 0x97, 0x3e, 0xed, 0x7b, 0xc2, 0xb1, 0x55, 0x07, 0x5a, 0x2d, 0xa3, 0xc7, 0xb4, 0x6b, 0xbb, 0xaf, 0x5c, 0xdd, - 0x24, 0xab, 0x31, 0x05, 0x91, 0xf9, 0xf1, 0x1d, 0x4b, 0x3e, 0x7b, 0x2a, 0xe5, 0xce, 0xf7, 0x1b, 0xcf, 0x91, 0xeb, - 0x00, 0xc6, 0xcd, 0xe2, 0xc5, 0x23, 0xa6, 0xd0, 0xd1, 0x4d, 0xdd, 0x0f, 0xe3, 0x94, 0xa9, 0x73, 0x20, 0x01, 0xc3, - 0x67, 0x4e, 0xe2, 0xa7, 0xf7, 0x6f, 0x3f, 0x7c, 0xd0, 0x4d, 0x4c, 0x86, 0x99, 0xaa, 0xbd, 0xf3, 0x0d, 0xb5, 0x03, - 0xd5, 0x37, 0xee, 0x3b, 0x22, 0x27, 0x74, 0x85, 0x2c, 0xef, 0x39, 0x2a, 0xab, 0x6d, 0x39, 0x4e, 0x66, 0xf8, 0x97, - 0xe9, 0xde, 0xb7, 0xd7, 0xbc, 0x1a, 0x70, 0xc3, 0x76, 0x5a, 0x56, 0x2a, 0x99, 0x07, 0xd1, 0x6d, 0x43, 0xa9, 0xb7, - 0x6a, 0x28, 0x85, 0x8b, 0x53, 0x0d, 0x57, 0x2d, 0xe3, 0xb9, 0x42, 0x8a, 0x21, 0x97, 0xf1, 0x2e, 0x70, 0x29, 0xd7, - 0x97, 0xcf, 0x18, 0x34, 0x0f, 0x66, 0x5e, 0x1d, 0x75, 0x43, 0x31, 0xbf, 0x73, 0x48, 0xd8, 0xfa, 0x21, 0xd8, 0xbc, - 0x31, 0x55, 0xe3, 0x55, 0x66, 0xd3, 0xa4, 0xc5, 0xaa, 0xd2, 0x09, 0xb1, 0x93, 0xb7, 0x19, 0x9b, 0x2f, 0x58, 0xe2, - 0x65, 0xcb, 0x84, 0xdd, 0x86, 0xf1, 0xfd, 0x93, 0xc2, 0xa2, 0x7c, 0x47, 0xe5, 0x59, 0x30, 0x9d, 0xc9, 0xda, 0xe7, - 0x2d, 0x36, 0x90, 0x0b, 0xb8, 0xf5, 0x03, 0xf9, 0x7f, 0x7e, 0xb7, 0xed, 0xff, 0xfc, 0xbe, 0xb3, 0x2a, 0x74, 0x9f, - 0x0f, 0xcd, 0x6c, 0xb0, 0xc7, 0xbe, 0x68, 0xfe, 0x52, 0x19, 0xe6, 0xcd, 0x75, 0x6a, 0x8b, 0x00, 0xef, 0x6b, 0x4b, - 0x50, 0x2b, 0x2c, 0xef, 0x9b, 0x47, 0x0d, 0x0c, 0xe6, 0xb5, 0x73, 0x64, 0x50, 0xe9, 0xb3, 0x86, 0x36, 0x34, 0x7a, - 0x7b, 0xad, 0xc8, 0x1f, 0x87, 0xf0, 0xae, 0x39, 0x7c, 0xe6, 0xf0, 0xb9, 0x14, 0xf0, 0xf5, 0x70, 0x28, 0xd3, 0xab, - 0xa9, 0x4d, 0xc1, 0xca, 0xfd, 0xbc, 0x56, 0xc2, 0x89, 0x67, 0xcf, 0x31, 0xc8, 0xfd, 0x7c, 0xf0, 0x7a, 0x88, 0xf6, - 0x58, 0xa7, 0xa3, 0xa4, 0x60, 0x56, 0x36, 0xa2, 0x36, 0xb2, 0xa7, 0xae, 0x75, 0x5a, 0xc3, 0x6b, 0x50, 0x8a, 0x39, - 0xb7, 0xf2, 0xa1, 0x61, 0xbe, 0x1e, 0x72, 0x31, 0x0e, 0x37, 0x01, 0xed, 0x55, 0xb7, 0x36, 0x17, 0x82, 0x96, 0x80, - 0x6e, 0x6a, 0xa4, 0x5b, 0xc1, 0xca, 0xac, 0x90, 0x9a, 0xa1, 0xf0, 0x1c, 0x6e, 0xf0, 0xc3, 0x1c, 0x53, 0x7e, 0xbc, - 0xdb, 0x64, 0x26, 0xf5, 0xd3, 0x6e, 0x33, 0xa9, 0xab, 0xbd, 0xcc, 0xa4, 0x7e, 0xfa, 0xe2, 0x66, 0x52, 0xef, 0x54, - 0x33, 0x29, 0x58, 0xc4, 0xb7, 0x6c, 0x2f, 0xdb, 0x25, 0x61, 0x11, 0x11, 0xdf, 0xa7, 0x03, 0x97, 0xf3, 0xaf, 0xa9, - 0x3f, 0x63, 0x70, 0x27, 0xe7, 0xab, 0x12, 0xc6, 0x53, 0xb0, 0x63, 0xfa, 0xf3, 0x2d, 0x8e, 0xc2, 0x78, 0xaa, 0xda, - 0x1b, 0x45, 0x3c, 0xe8, 0x69, 0x11, 0xc8, 0x88, 0x6c, 0x7c, 0x1c, 0x53, 0x84, 0x3d, 0xb2, 0x0e, 0x0d, 0x25, 0xb1, - 0xb3, 0x34, 0xe0, 0x6a, 0x0b, 0x2b, 0xa0, 0x1e, 0x1a, 0x10, 0xc9, 0x86, 0xed, 0x97, 0x22, 0xbc, 0x83, 0xda, 0x83, - 0x34, 0x94, 0xa5, 0x50, 0x09, 0x6b, 0xfd, 0x97, 0x95, 0xfb, 0xed, 0xb5, 0xdb, 0xef, 0xb8, 0xe0, 0x9f, 0x0c, 0x37, - 0x3a, 0x2c, 0x70, 0xfa, 0x9d, 0x0e, 0x14, 0xdc, 0x2b, 0x05, 0x6d, 0x28, 0x08, 0x94, 0x82, 0x2e, 0x14, 0xf8, 0x4a, - 0xc1, 0x11, 0x14, 0x8c, 0x95, 0x82, 0x63, 0x28, 0xb8, 0xd3, 0xf3, 0xeb, 0x48, 0x0e, 0xf7, 0xd8, 0xb8, 0x31, 0xe9, - 0x06, 0x21, 0xca, 0x8e, 0x4d, 0x17, 0x0c, 0x87, 0xbc, 0x69, 0x2f, 0x36, 0x49, 0x98, 0xd7, 0x4b, 0xcc, 0xfb, 0x19, - 0xa3, 0x58, 0xc9, 0x6f, 0x90, 0xe6, 0xd8, 0x59, 0x0c, 0xa6, 0xc3, 0x22, 0x06, 0x81, 0x80, 0x83, 0xa6, 0x1b, 0x20, - 0xa0, 0xe9, 0xcb, 0x95, 0x13, 0x71, 0x1c, 0x94, 0xb5, 0x2c, 0xde, 0xd1, 0xe7, 0x2c, 0xb9, 0x05, 0x0a, 0x6b, 0x8e, - 0x96, 0x2a, 0x04, 0xfc, 0x12, 0x3a, 0xfd, 0x37, 0x6c, 0xb4, 0x9c, 0x6a, 0x97, 0xf1, 0x74, 0xa7, 0x7a, 0x5e, 0x7d, - 0x05, 0xa3, 0xd4, 0x49, 0xd9, 0x61, 0x89, 0x6d, 0xc9, 0xbf, 0x45, 0x8f, 0x79, 0xb9, 0x7e, 0x06, 0x63, 0xd3, 0x32, - 0x32, 0x0e, 0x81, 0xef, 0x00, 0x8c, 0x14, 0xfd, 0xf8, 0x25, 0xc0, 0x59, 0x79, 0xbe, 0xf2, 0x94, 0xf1, 0x9c, 0xfd, - 0xc0, 0xd2, 0xd4, 0x9b, 0x8a, 0xfa, 0xf5, 0x71, 0x82, 0x41, 0x8c, 0xbc, 0x7f, 0x21, 0x00, 0x41, 0x72, 0x16, 0xd4, - 0xec, 0x1e, 0x92, 0xf8, 0x5e, 0x03, 0xcb, 0x1a, 0xd8, 0x50, 0x85, 0x0d, 0x40, 0x60, 0xc3, 0x12, 0x96, 0xb5, 0xf5, - 0x70, 0xf8, 0xef, 0x58, 0x58, 0x2d, 0xcc, 0xbc, 0x69, 0xb5, 0x88, 0xf6, 0x41, 0xae, 0x8e, 0x4d, 0x2a, 0xcb, 0x4b, - 0x85, 0x9f, 0xa3, 0xfd, 0x0d, 0xe3, 0xe9, 0x9f, 0xaa, 0xfa, 0xdd, 0xa2, 0xb2, 0xff, 0x10, 0x99, 0x41, 0x36, 0xb4, - 0x11, 0xc6, 0x9a, 0x0d, 0x20, 0xec, 0x45, 0xd9, 0xcc, 0x42, 0xef, 0xaa, 0x56, 0x3b, 0x32, 0x4c, 0x1b, 0xd7, 0x76, - 0x5d, 0xf5, 0x29, 0xed, 0x25, 0xd3, 0x91, 0xd7, 0x72, 0xdb, 0xc7, 0xa6, 0xf8, 0xb3, 0x9d, 0xae, 0x91, 0x63, 0x0f, - 0xda, 0x38, 0xb8, 0x5b, 0x4f, 0xe2, 0x28, 0xb3, 0x26, 0xde, 0x3c, 0x08, 0x1f, 0x7a, 0xf3, 0x38, 0x8a, 0xd3, 0x85, - 0xe7, 0xb3, 0x3e, 0x79, 0xd0, 0x81, 0x2b, 0x69, 0x1f, 0xa3, 0x15, 0x70, 0x87, 0x39, 0xd7, 0x6e, 0x27, 0x6c, 0x4e, - 0xad, 0x65, 0x30, 0x82, 0x49, 0xc8, 0x56, 0x39, 0xff, 0x7c, 0xa9, 0x32, 0x55, 0xc5, 0x2d, 0x47, 0x2d, 0x80, 0x23, - 0xe5, 0x91, 0x0e, 0x20, 0xbe, 0x4f, 0x7f, 0xe1, 0x8d, 0x31, 0x38, 0x9f, 0xdd, 0xee, 0x26, 0x6c, 0xae, 0xd9, 0xdd, - 0x8d, 0x9d, 0x27, 0xf1, 0xfd, 0x19, 0x8c, 0x16, 0x1b, 0x5b, 0x29, 0x0b, 0x27, 0xf8, 0xc6, 0x42, 0xe7, 0x0a, 0xd1, - 0x8f, 0x85, 0x17, 0x71, 0xe8, 0x8d, 0xcd, 0xfb, 0xf0, 0xba, 0xd7, 0xd6, 0x9c, 0xfe, 0x3c, 0x88, 0x2c, 0x9a, 0xce, - 0xb1, 0xb3, 0x50, 0xfa, 0x52, 0xe1, 0x67, 0xac, 0xb1, 0xba, 0xab, 0x39, 0x7d, 0xb8, 0xac, 0x4d, 0xc2, 0xf8, 0xbe, - 0x37, 0x0b, 0xc6, 0x63, 0x16, 0xf5, 0x71, 0xcc, 0xb2, 0x90, 0x85, 0x61, 0xb0, 0x48, 0x83, 0xb4, 0x3f, 0xf7, 0x56, - 0xbc, 0xd7, 0xc3, 0x4d, 0xbd, 0x76, 0x78, 0xaf, 0x9d, 0xbd, 0x7b, 0x55, 0xba, 0x01, 0x47, 0x0e, 0xea, 0x87, 0x0f, - 0xad, 0xab, 0x39, 0x95, 0x79, 0xee, 0xdd, 0xeb, 0x22, 0x61, 0xeb, 0xb9, 0x97, 0x4c, 0x83, 0xa8, 0xe7, 0xe4, 0xf6, - 0xdd, 0x9a, 0x36, 0xc6, 0xd3, 0x93, 0x93, 0x93, 0xdc, 0x1e, 0x8b, 0x27, 0x67, 0x3c, 0xce, 0x6d, 0x5f, 0x3c, 0x4d, - 0x26, 0x8e, 0x33, 0x99, 0xe4, 0x76, 0x20, 0x0a, 0x3a, 0x6d, 0x7f, 0xdc, 0x69, 0xe7, 0xf6, 0xbd, 0x52, 0x23, 0xb7, - 0x19, 0x7f, 0x4a, 0xd8, 0xb8, 0x8f, 0x1b, 0xe9, 0x9e, 0x96, 0xfe, 0xd8, 0x71, 0x72, 0xc4, 0x00, 0xd7, 0x25, 0xdc, - 0x84, 0x82, 0x9d, 0x9b, 0xf5, 0xde, 0x35, 0xb5, 0xe2, 0x73, 0xbe, 0xdf, 0x58, 0x6f, 0xec, 0x25, 0x9f, 0x6e, 0x34, - 0x65, 0x16, 0x9e, 0x47, 0xd5, 0xd6, 0x02, 0x0c, 0xd6, 0xaa, 0x07, 0x51, 0xab, 0xfa, 0xa3, 0x38, 0x81, 0x33, 0x9b, - 0x78, 0xe3, 0x60, 0x99, 0xf6, 0xdc, 0xf6, 0x62, 0x25, 0x8a, 0xf8, 0x5e, 0x2f, 0x0a, 0xf0, 0xec, 0xf5, 0xd2, 0x38, - 0x0c, 0xc6, 0xa2, 0x68, 0xd3, 0x59, 0x72, 0xdb, 0x46, 0x1f, 0x7d, 0xb6, 0x03, 0x8c, 0x3c, 0xe0, 0x85, 0xa1, 0x66, - 0x77, 0x52, 0x8d, 0x79, 0x29, 0xca, 0x73, 0x35, 0x27, 0x25, 0xb8, 0xa0, 0x7f, 0xb6, 0x7b, 0xb8, 0x58, 0xc9, 0x3d, - 0xef, 0x1e, 0x2d, 0x56, 0xf9, 0xd7, 0x73, 0x36, 0x0e, 0x3c, 0xad, 0x55, 0xec, 0x26, 0xd7, 0x01, 0x99, 0xaf, 0xb1, - 0xde, 0xb0, 0x4d, 0xc5, 0xb1, 0x80, 0xe8, 0x7e, 0x4f, 0x82, 0xf9, 0x22, 0x4e, 0x32, 0x2f, 0xca, 0xf2, 0x7c, 0x78, - 0x93, 0xe7, 0xfd, 0xab, 0xa0, 0x75, 0xfd, 0xcf, 0x16, 0xd1, 0x69, 0xd2, 0x91, 0xe4, 0xc6, 0x8d, 0xf9, 0x96, 0xa9, - 0xf6, 0x18, 0x40, 0xc6, 0xd0, 0x16, 0x43, 0xad, 0x4c, 0x54, 0xb2, 0x5e, 0x99, 0x80, 0x2c, 0xab, 0x93, 0x7d, 0x47, - 0xb9, 0x0a, 0x52, 0x20, 0xa8, 0xf0, 0x96, 0x0d, 0xae, 0x14, 0xdb, 0x0e, 0x60, 0x56, 0xb0, 0x32, 0x99, 0xd6, 0x3f, - 0xdb, 0xc4, 0x33, 0x7e, 0xb3, 0x9b, 0x67, 0xfc, 0x39, 0xdb, 0x87, 0x67, 0xfc, 0xe6, 0x8b, 0xf3, 0x8c, 0xcf, 0xea, - 0xa6, 0xf5, 0x17, 0xf1, 0x40, 0x97, 0x12, 0x7d, 0x20, 0x4d, 0x09, 0x05, 0xad, 0xb9, 0xf8, 0xc3, 0x96, 0xf0, 0xa2, - 0x37, 0x4a, 0xc3, 0x46, 0x94, 0x1b, 0x84, 0xaf, 0xef, 0xa2, 0xc1, 0x3f, 0x12, 0xf5, 0x79, 0x32, 0x19, 0xbc, 0x89, - 0x95, 0x02, 0xf9, 0xc4, 0x4d, 0x1d, 0x4a, 0x01, 0x06, 0xe8, 0x8d, 0xb0, 0x70, 0xc4, 0x14, 0x0c, 0xe0, 0x9f, 0x4c, - 0x16, 0xbd, 0x63, 0x69, 0xd9, 0xd5, 0x2f, 0x0f, 0xa1, 0x25, 0xcd, 0x29, 0x85, 0x17, 0x4a, 0x4d, 0x94, 0x38, 0x65, - 0x19, 0x77, 0x1b, 0xfd, 0xf6, 0xe1, 0x62, 0xdc, 0xba, 0x88, 0x8d, 0x3c, 0x48, 0xdf, 0x55, 0x7d, 0x40, 0xb8, 0xae, - 0x65, 0xa0, 0x4e, 0x27, 0xe7, 0xd6, 0x59, 0x6a, 0x8e, 0x65, 0x78, 0x4d, 0xcd, 0xcf, 0x4b, 0x33, 0xed, 0xa9, 0x0d, - 0x79, 0xae, 0xa7, 0x1a, 0x31, 0xe6, 0x06, 0xf8, 0x6b, 0xce, 0x01, 0x62, 0xfa, 0x2a, 0x74, 0x9d, 0x1d, 0x53, 0xf3, - 0x60, 0x9c, 0xe7, 0x46, 0x5f, 0x00, 0x42, 0x21, 0xb4, 0x6c, 0x17, 0x13, 0x97, 0xde, 0x4b, 0x0b, 0x02, 0xae, 0x91, - 0x23, 0x75, 0xdb, 0x05, 0xa8, 0xaf, 0xb9, 0x72, 0x8e, 0xc3, 0x4c, 0xd7, 0x08, 0x7c, 0x64, 0xd6, 0xa0, 0x4c, 0x08, - 0xd4, 0xfa, 0x12, 0xfe, 0xe2, 0x95, 0x28, 0xa8, 0xdb, 0x47, 0x12, 0x70, 0x50, 0xff, 0x0e, 0x8e, 0xee, 0x44, 0xfe, - 0xb9, 0x0e, 0xb0, 0xc7, 0xeb, 0xe0, 0x43, 0xae, 0x4b, 0xde, 0x0f, 0xb7, 0xdf, 0xd9, 0xe9, 0x01, 0x34, 0x38, 0xab, - 0xa8, 0xe9, 0x77, 0x58, 0xff, 0x01, 0x2b, 0x91, 0xde, 0x9b, 0x76, 0x7a, 0xaf, 0xbd, 0x58, 0x8b, 0x20, 0x11, 0x99, - 0xb7, 0xb0, 0xe0, 0x8a, 0x8f, 0xb8, 0x97, 0x63, 0x3c, 0x25, 0x1e, 0x45, 0x7f, 0x99, 0x02, 0x6e, 0xc4, 0x8b, 0x2a, - 0xe2, 0x9f, 0xbe, 0xbf, 0x4c, 0xd2, 0x38, 0xe9, 0x2d, 0xe2, 0x20, 0xca, 0x58, 0x92, 0x23, 0xa8, 0xae, 0x11, 0x3e, - 0x02, 0x3c, 0x37, 0xeb, 0x78, 0xe1, 0xf9, 0x41, 0xf6, 0xd0, 0x73, 0x38, 0x4b, 0xe1, 0xf4, 0x39, 0x77, 0xe0, 0x34, - 0xd6, 0xef, 0x71, 0x68, 0xbe, 0x44, 0xc6, 0x2f, 0xa9, 0xb3, 0x33, 0xea, 0x36, 0xef, 0x2b, 0x6f, 0x29, 0x4c, 0x06, - 0xb0, 0x1f, 0x5e, 0x62, 0x4d, 0x01, 0xcb, 0xc3, 0x52, 0x3b, 0x63, 0x36, 0x35, 0x11, 0x6b, 0x83, 0x5c, 0x5e, 0xfc, - 0xd9, 0x5d, 0x43, 0x73, 0x9a, 0x8b, 0x81, 0xe3, 0x31, 0xf6, 0x19, 0x59, 0xcf, 0x83, 0xa4, 0x52, 0xe6, 0x3e, 0x35, - 0x47, 0x6c, 0x12, 0x27, 0x8c, 0x42, 0xaa, 0xba, 0x27, 0x8b, 0xd5, 0xfe, 0xdd, 0x6f, 0x9f, 0x7e, 0x73, 0x3f, 0x51, - 0x9c, 0xb5, 0x44, 0x67, 0xc6, 0x8e, 0xde, 0xea, 0xf4, 0x0c, 0x58, 0x43, 0x82, 0xbc, 0x4f, 0xd1, 0xab, 0x7a, 0xba, - 0xde, 0x6f, 0x8c, 0x5c, 0xb5, 0x88, 0x39, 0xcd, 0x4b, 0x58, 0xe8, 0x65, 0xc1, 0x9d, 0xe0, 0x19, 0x3b, 0x47, 0x8b, - 0x95, 0x58, 0x63, 0x24, 0x78, 0x8f, 0x58, 0xa4, 0xca, 0x50, 0xc4, 0x22, 0x55, 0x8b, 0x71, 0x91, 0xfa, 0xb5, 0xd9, - 0x88, 0x60, 0x0e, 0x15, 0x4a, 0xdf, 0x5d, 0xac, 0x54, 0x12, 0x5d, 0x34, 0x93, 0x94, 0xba, 0x1a, 0x85, 0x6b, 0x1e, - 0x8c, 0xc7, 0x21, 0xcb, 0x4b, 0x0b, 0x5d, 0x5e, 0x4b, 0x05, 0x38, 0x12, 0x0e, 0xde, 0x28, 0x8d, 0xc3, 0x65, 0xc6, - 0x9a, 0xc1, 0x45, 0xc0, 0x69, 0x3b, 0x05, 0x70, 0xf0, 0x77, 0x79, 0xac, 0x5d, 0x60, 0xb7, 0x61, 0x9b, 0x38, 0x7d, - 0x08, 0xba, 0x6b, 0x75, 0xca, 0x43, 0x87, 0x57, 0x72, 0xd0, 0x66, 0xc3, 0x44, 0x4c, 0x20, 0x4b, 0x84, 0xbd, 0x35, - 0xdb, 0xe5, 0x65, 0x32, 0xf0, 0xa8, 0x2c, 0xca, 0xcb, 0x93, 0xf9, 0x73, 0xce, 0xd8, 0xab, 0xe6, 0x33, 0xf6, 0x4a, - 0x9c, 0xb1, 0xed, 0x3b, 0xf3, 0xe9, 0xc4, 0x85, 0xff, 0xfa, 0xc5, 0x84, 0x7a, 0x8e, 0xd6, 0x59, 0xac, 0x34, 0x77, - 0xb1, 0xd2, 0xac, 0xf6, 0x62, 0xa5, 0x61, 0xd7, 0x68, 0x7f, 0x61, 0xda, 0x6d, 0xc3, 0x74, 0x34, 0x28, 0x84, 0x3f, - 0xa7, 0xf4, 0xca, 0x3d, 0x84, 0x77, 0xd0, 0xaa, 0x5b, 0x7f, 0xd7, 0xde, 0x7e, 0xd4, 0xe9, 0x2c, 0x09, 0xa4, 0x6d, - 0xd8, 0x99, 0x37, 0x1a, 0xb1, 0x71, 0x6f, 0x12, 0xfb, 0xcb, 0xf4, 0xdf, 0x7c, 0xfc, 0x1c, 0x88, 0x5b, 0x11, 0x41, - 0xa5, 0x1f, 0xd1, 0x14, 0x14, 0x25, 0x77, 0x4c, 0xf4, 0xb0, 0x96, 0xeb, 0xd4, 0xa3, 0x08, 0xc1, 0x6d, 0xfb, 0xb0, - 0x61, 0x93, 0x37, 0x03, 0xfa, 0x4f, 0x5b, 0xa5, 0xcd, 0x28, 0xe6, 0x33, 0xc0, 0xb2, 0x15, 0x1c, 0x8f, 0x87, 0x06, - 0x5f, 0x4d, 0xe7, 0xa4, 0x79, 0xb8, 0xd7, 0xe2, 0x4b, 0x37, 0x82, 0xa8, 0x70, 0xba, 0xc5, 0x9d, 0x3e, 0xb6, 0xf7, - 0xba, 0x69, 0x8f, 0xd4, 0x7a, 0xdd, 0x42, 0x10, 0x8a, 0xba, 0x7b, 0x62, 0xf9, 0xa7, 0xaf, 0x0e, 0xe1, 0x3f, 0xe2, - 0xea, 0x7f, 0xce, 0x9a, 0x18, 0xf5, 0x8b, 0xb2, 0x95, 0x35, 0xb1, 0x4a, 0xc8, 0x88, 0xef, 0x5f, 0x7f, 0x32, 0x79, - 0x5c, 0x83, 0xbd, 0x6b, 0x93, 0xe9, 0x52, 0xb5, 0xf6, 0xb7, 0x71, 0x0c, 0xd9, 0x2b, 0xeb, 0xd5, 0x05, 0x78, 0xc8, - 0x90, 0x3c, 0x1b, 0x40, 0x23, 0x71, 0x8f, 0x20, 0x2d, 0xbe, 0x8e, 0x6d, 0xe8, 0x2a, 0xf1, 0x76, 0xd3, 0x55, 0xe2, - 0xcd, 0xee, 0xab, 0xc4, 0xf7, 0x7b, 0x5d, 0x25, 0xde, 0x7c, 0xf1, 0xab, 0xc4, 0xdb, 0xfa, 0x55, 0xe2, 0x2a, 0x16, - 0xd6, 0xaa, 0xe6, 0xc5, 0x92, 0xff, 0xfc, 0x48, 0x4a, 0xb9, 0xcb, 0x78, 0xd0, 0x75, 0x28, 0xea, 0xef, 0xd5, 0x1f, - 0xbe, 0x58, 0xe0, 0x46, 0x7c, 0x8f, 0xe6, 0x5b, 0xc5, 0xd5, 0x82, 0x63, 0x76, 0xfc, 0x8e, 0x52, 0x1c, 0xc6, 0xd1, - 0xf4, 0x27, 0x50, 0xca, 0x82, 0x38, 0x30, 0x51, 0x5e, 0x04, 0xe9, 0x4f, 0xf1, 0x62, 0xb9, 0xb8, 0x80, 0xbe, 0x3e, - 0x06, 0x69, 0x30, 0x0a, 0x99, 0x74, 0xc6, 0x25, 0x73, 0x33, 0x2e, 0x13, 0x07, 0xfb, 0x4e, 0xf1, 0xd3, 0x5b, 0x89, - 0x9f, 0x68, 0x01, 0xca, 0x7f, 0x93, 0x1d, 0x9b, 0xde, 0x7c, 0x11, 0x11, 0x4a, 0x40, 0x65, 0xd0, 0x8f, 0xbf, 0x8c, - 0x5c, 0xc5, 0x46, 0xc3, 0x2c, 0x85, 0xbd, 0xc3, 0xc6, 0x7e, 0x58, 0xed, 0x52, 0xb3, 0x34, 0x4c, 0x19, 0x85, 0xaa, - 0x2e, 0x86, 0x9f, 0xc7, 0xcb, 0x94, 0x8d, 0xe3, 0xfb, 0x48, 0x37, 0x23, 0x69, 0xc0, 0x0f, 0x1a, 0x4e, 0xd9, 0x06, - 0xf3, 0x27, 0x7e, 0x40, 0x46, 0x39, 0x4e, 0x5a, 0x3a, 0xa4, 0xef, 0x5c, 0x2e, 0x2c, 0x52, 0x35, 0x5b, 0x38, 0x45, - 0x5d, 0x26, 0xfa, 0x79, 0xd2, 0x6a, 0xc5, 0x83, 0xc7, 0xb5, 0x14, 0xa6, 0x1a, 0xb1, 0xcd, 0xa5, 0xc2, 0x69, 0x2b, - 0x12, 0xc2, 0x45, 0x11, 0x0a, 0xa2, 0x61, 0xe1, 0xf8, 0x1b, 0x72, 0x0b, 0x2d, 0xde, 0x42, 0x20, 0x8d, 0x7c, 0xc9, - 0xd7, 0x83, 0x07, 0x46, 0xa0, 0xc7, 0xd7, 0x0a, 0x18, 0xdf, 0xdd, 0xb1, 0x24, 0xf4, 0x1e, 0x5a, 0x46, 0x1e, 0x47, - 0x3f, 0x00, 0x00, 0xde, 0xc4, 0xf7, 0x91, 0x5a, 0x01, 0xf3, 0x95, 0x34, 0xec, 0xa5, 0xc6, 0x10, 0x1e, 0xe0, 0x14, - 0xa2, 0x8c, 0x00, 0x32, 0xc5, 0x4e, 0xd9, 0x3f, 0x4c, 0xfa, 0xf7, 0x9f, 0x46, 0x6e, 0x5e, 0xc6, 0xf2, 0x43, 0x7f, - 0x5f, 0xec, 0xf1, 0x99, 0xe7, 0xcf, 0x9f, 0x6c, 0x9e, 0x76, 0x39, 0x43, 0x79, 0x43, 0x6b, 0x63, 0xe3, 0x29, 0x80, - 0x51, 0x5c, 0xc5, 0x4b, 0x7f, 0x86, 0x86, 0xa5, 0x5f, 0x6e, 0xbe, 0x19, 0xf4, 0x89, 0x89, 0x3a, 0xe5, 0xd4, 0x2b, - 0x45, 0x05, 0x14, 0xf0, 0xfb, 0x6f, 0x21, 0x06, 0xe5, 0xff, 0x11, 0x0c, 0xf5, 0x5d, 0xc3, 0x6f, 0xf1, 0xc1, 0xe3, - 0x36, 0x6f, 0x1f, 0xf2, 0x49, 0xf2, 0xe8, 0x0e, 0x42, 0xb9, 0xd6, 0x8c, 0x64, 0xf2, 0x2a, 0xd0, 0xd4, 0x48, 0x6a, - 0x9b, 0x82, 0xc4, 0x89, 0xaf, 0x30, 0x9b, 0xae, 0xe9, 0xdc, 0xac, 0xdf, 0x64, 0x1c, 0x5b, 0x55, 0x90, 0x0c, 0x37, - 0x79, 0x60, 0x88, 0xbe, 0xaa, 0xef, 0xe6, 0x41, 0x64, 0x62, 0x20, 0xf4, 0xfa, 0x1b, 0x6f, 0x05, 0xa1, 0x80, 0x01, - 0xb9, 0x55, 0x5f, 0x41, 0xa1, 0xa9, 0xfa, 0xa4, 0x41, 0xb6, 0x23, 0xbd, 0x11, 0x12, 0x42, 0x8b, 0x37, 0xfc, 0x8b, - 0xa6, 0x69, 0x9a, 0xbc, 0x46, 0x68, 0xf2, 0x1e, 0x81, 0xe5, 0x78, 0x1d, 0x00, 0x6d, 0x49, 0xbe, 0x58, 0x51, 0x09, - 0xdc, 0x0c, 0x50, 0x27, 0x2b, 0x0a, 0x78, 0xb4, 0xbb, 0xae, 0x23, 0x0a, 0xc4, 0x85, 0x1e, 0x22, 0x95, 0x79, 0x09, - 0x04, 0xc5, 0xed, 0x69, 0x78, 0x61, 0xc7, 0xb7, 0x5c, 0x12, 0xac, 0x39, 0xf4, 0x38, 0xec, 0xb3, 0xe6, 0xb0, 0x68, - 0x91, 0x82, 0x05, 0x41, 0xeb, 0x50, 0x89, 0x72, 0x6c, 0xb2, 0x06, 0xdc, 0x88, 0xf7, 0xa2, 0x55, 0x36, 0x67, 0xd1, - 0x52, 0xc7, 0xb4, 0x48, 0x18, 0xa6, 0x0e, 0xea, 0xbc, 0x21, 0x66, 0x0b, 0xb0, 0x4d, 0x73, 0xcb, 0x19, 0xd1, 0xc2, - 0x94, 0xa3, 0x54, 0xcf, 0xf4, 0xb9, 0x62, 0x33, 0xe5, 0xb8, 0xad, 0x4a, 0x21, 0xf8, 0x92, 0xc6, 0x55, 0x27, 0x29, - 0xb2, 0x3c, 0x86, 0x3e, 0x28, 0x40, 0x04, 0x17, 0x17, 0x09, 0xb0, 0xb7, 0xbc, 0xea, 0xa2, 0x49, 0x8d, 0x8c, 0x57, - 0x11, 0x14, 0x25, 0x46, 0xbd, 0x1b, 0x3e, 0x4e, 0x88, 0xcd, 0xb3, 0xb1, 0x1f, 0xbf, 0xd6, 0xcf, 0x86, 0x49, 0x7f, - 0x62, 0x0f, 0x44, 0x48, 0x08, 0x54, 0x9f, 0xd8, 0x03, 0xd8, 0xfe, 0xbd, 0x05, 0x69, 0x8a, 0xbe, 0x05, 0x5d, 0x9b, - 0x10, 0xed, 0xde, 0x87, 0x78, 0x4d, 0x5b, 0x0e, 0x90, 0x93, 0x6f, 0xc1, 0xe2, 0x08, 0x62, 0x48, 0x6c, 0x2c, 0x0e, - 0x31, 0x37, 0xa9, 0x6f, 0x35, 0xc2, 0xd8, 0x6a, 0x38, 0x1a, 0xc6, 0x0b, 0xd7, 0x71, 0x0e, 0x6a, 0xf5, 0x41, 0x90, - 0xdd, 0x54, 0xdb, 0x30, 0xb3, 0x81, 0xeb, 0x58, 0xc1, 0x0b, 0xbb, 0xdd, 0xaf, 0xd1, 0x68, 0x25, 0x9c, 0xe2, 0x10, - 0xc5, 0x5f, 0x67, 0xcf, 0xd6, 0xad, 0xda, 0x81, 0x34, 0xaa, 0x26, 0xea, 0x38, 0xb6, 0x9c, 0xcb, 0xbf, 0x86, 0x75, - 0xd2, 0x4f, 0xc1, 0x1c, 0x29, 0xb5, 0xc7, 0x10, 0x02, 0x02, 0xb7, 0xe0, 0x18, 0xfd, 0x55, 0x7b, 0xa9, 0xb5, 0xe8, - 0xf8, 0x18, 0xc6, 0x50, 0x66, 0x8c, 0x16, 0x1e, 0x5c, 0x6a, 0x07, 0x95, 0x2f, 0xa6, 0x55, 0x0c, 0xc7, 0x43, 0x8f, - 0xb2, 0x42, 0xa3, 0xb7, 0x95, 0x5b, 0xc0, 0xfe, 0x37, 0x90, 0x4f, 0x7b, 0x04, 0x3e, 0xff, 0x50, 0x03, 0xc2, 0x87, - 0xef, 0xec, 0x70, 0xb9, 0x28, 0x77, 0x57, 0x26, 0x92, 0xfb, 0x77, 0x86, 0x44, 0x07, 0x75, 0x68, 0xb2, 0xbf, 0x66, - 0x72, 0xf7, 0xc8, 0x2e, 0x59, 0x34, 0x2e, 0x77, 0x58, 0xa1, 0x5f, 0xfb, 0x77, 0x57, 0xc2, 0x28, 0x10, 0x57, 0x3f, - 0x6e, 0xc0, 0x28, 0x79, 0x1c, 0xe1, 0xe6, 0xa7, 0xe3, 0x16, 0xec, 0xc5, 0xc5, 0x60, 0x03, 0x0a, 0x8a, 0x25, 0x9b, - 0x29, 0x42, 0x71, 0x08, 0xde, 0x8c, 0x2e, 0xb7, 0x2d, 0xc1, 0x88, 0x6e, 0xdc, 0x89, 0x99, 0xb0, 0x29, 0x2c, 0xda, - 0x04, 0x3c, 0x1c, 0xe3, 0xbe, 0x52, 0xeb, 0x60, 0xb7, 0xd4, 0x3a, 0xdb, 0x25, 0xb5, 0x26, 0xef, 0xa5, 0xfb, 0xc4, - 0x5b, 0x28, 0xfe, 0x6f, 0x82, 0x39, 0x57, 0xdd, 0xe0, 0x4a, 0xa2, 0x6e, 0x74, 0x76, 0x12, 0xad, 0x6a, 0xbd, 0x91, - 0x95, 0x20, 0x8a, 0xbf, 0x95, 0x0b, 0x8a, 0x50, 0xa8, 0xab, 0xb2, 0xf1, 0xab, 0x42, 0x36, 0x4e, 0xb7, 0x9a, 0xc2, - 0x71, 0x45, 0x70, 0xff, 0x8a, 0x4b, 0x98, 0xbc, 0x1d, 0x14, 0xae, 0x61, 0xc5, 0x48, 0x15, 0x6f, 0xa7, 0xe2, 0xa2, - 0xa1, 0xb8, 0xd0, 0x89, 0x5b, 0x46, 0xd9, 0x93, 0xae, 0x5c, 0xb5, 0x70, 0xa9, 0x2b, 0xca, 0x41, 0xea, 0x8e, 0x43, - 0x96, 0xc5, 0xea, 0xb6, 0x29, 0xbb, 0xbb, 0xa8, 0xaf, 0x95, 0x4d, 0x22, 0xfd, 0x52, 0x08, 0xc0, 0x42, 0x4c, 0x5f, - 0xd1, 0x6b, 0x4b, 0x1b, 0x08, 0x1c, 0x64, 0x83, 0x13, 0xdd, 0x6e, 0xe9, 0x3c, 0xa5, 0x0c, 0x28, 0xb4, 0xf0, 0xaa, - 0x0c, 0x02, 0xe1, 0x7b, 0xb3, 0x6e, 0xa0, 0xf2, 0x48, 0xe4, 0x39, 0x7d, 0x07, 0xf1, 0xa2, 0xe6, 0xa8, 0x8a, 0x7c, - 0x3c, 0x99, 0x16, 0x99, 0xe7, 0x62, 0xd5, 0x7a, 0xa7, 0x24, 0xc4, 0x59, 0x73, 0x4f, 0x94, 0xb2, 0x8c, 0x9e, 0xd7, - 0xe8, 0x89, 0xef, 0xf2, 0xad, 0x93, 0x2c, 0x23, 0x0c, 0xef, 0x6e, 0x65, 0x89, 0xe7, 0x7f, 0x52, 0x86, 0x2c, 0xe4, - 0x9c, 0x20, 0x03, 0x2e, 0x6b, 0x0a, 0xfa, 0x1e, 0x46, 0x43, 0x64, 0x3d, 0xbb, 0x9d, 0x2a, 0xd2, 0x97, 0xde, 0x53, - 0xa7, 0xe3, 0xbd, 0x9a, 0x1c, 0x56, 0x84, 0xa2, 0xed, 0x6e, 0x59, 0x64, 0xbe, 0x61, 0x1c, 0xd9, 0x6c, 0x39, 0x1f, - 0xad, 0x55, 0xd9, 0xaa, 0x22, 0x72, 0xad, 0x8b, 0x59, 0xd5, 0xcf, 0x4e, 0x26, 0x93, 0xb2, 0xa0, 0xd1, 0xd1, 0x0e, - 0x51, 0x58, 0xf8, 0xd4, 0x71, 0x9c, 0xea, 0xd8, 0xb7, 0x83, 0xdd, 0x42, 0xb9, 0xed, 0x49, 0xe3, 0x88, 0x11, 0xb6, - 0xbb, 0xe0, 0x57, 0x07, 0x47, 0x6e, 0x17, 0x27, 0xbb, 0x64, 0x16, 0xd1, 0x27, 0x63, 0x88, 0x20, 0x63, 0xf3, 0xb4, - 0xe7, 0x33, 0xd4, 0xc1, 0xd8, 0xca, 0x81, 0x46, 0xc3, 0x01, 0x6b, 0x0a, 0xa6, 0x22, 0xae, 0xd8, 0x15, 0x8e, 0x86, - 0xf2, 0xf0, 0x9a, 0xf0, 0x5e, 0x7c, 0x04, 0x0f, 0xca, 0xba, 0x2e, 0xd3, 0xc6, 0x69, 0x75, 0x9d, 0xbf, 0x96, 0xea, - 0x69, 0x40, 0x00, 0xd7, 0x42, 0xa1, 0x4d, 0xf2, 0x59, 0xfc, 0x7f, 0x29, 0xff, 0x7f, 0xb5, 0x58, 0x95, 0xed, 0x47, - 0x4e, 0x40, 0xa2, 0x5d, 0x9c, 0x16, 0x1a, 0x75, 0xd3, 0x1e, 0x90, 0x56, 0x06, 0x13, 0x55, 0x81, 0x0e, 0x4a, 0xfa, - 0x52, 0x0e, 0x8c, 0x06, 0xf1, 0x3b, 0x72, 0xcc, 0xb0, 0xc4, 0x85, 0x08, 0xb1, 0xc8, 0xe0, 0x06, 0x73, 0x30, 0x5f, - 0x9e, 0xa0, 0xfe, 0xa0, 0xb4, 0x27, 0x40, 0x1b, 0x5f, 0x9b, 0xdb, 0x5e, 0xe2, 0xfe, 0xaa, 0x5e, 0x4b, 0x74, 0x0c, - 0x20, 0x73, 0xe1, 0x10, 0xa2, 0x21, 0x81, 0x56, 0xd9, 0xdc, 0x34, 0x4a, 0xf9, 0x56, 0xd5, 0xb3, 0x89, 0x81, 0x61, - 0x77, 0xcd, 0x55, 0xa8, 0x6f, 0xa1, 0x2d, 0x80, 0xc9, 0xf2, 0xed, 0x87, 0xcf, 0x16, 0x2c, 0xb1, 0xba, 0x1f, 0x5d, - 0x5c, 0x72, 0xdc, 0xbf, 0x16, 0xd2, 0xce, 0x94, 0xce, 0x3f, 0xca, 0x17, 0xbf, 0x6f, 0x14, 0xe8, 0x5d, 0x95, 0x24, - 0x74, 0xdc, 0x5a, 0xbc, 0x6d, 0xec, 0x55, 0x7b, 0x1e, 0x44, 0xfb, 0xd7, 0xf5, 0x56, 0x7b, 0xd7, 0x05, 0x82, 0xb1, - 0x77, 0x65, 0xa0, 0x38, 0x64, 0xb9, 0x90, 0x0d, 0xbe, 0x57, 0x04, 0x8a, 0xaa, 0x93, 0xaf, 0x8e, 0xad, 0x88, 0xcb, - 0xbf, 0x5a, 0x02, 0xf3, 0xb9, 0x57, 0x8e, 0x03, 0x4d, 0xa4, 0x29, 0xd3, 0x8f, 0xb5, 0x13, 0xed, 0xb8, 0xa3, 0x1d, - 0x39, 0x3a, 0xdd, 0xc2, 0x06, 0x7a, 0xb7, 0x5d, 0x78, 0xef, 0x1d, 0x3a, 0xfa, 0xd9, 0xe9, 0x54, 0x10, 0x89, 0x49, - 0x10, 0x86, 0x84, 0x2a, 0xd2, 0x2c, 0x89, 0x3f, 0xb1, 0xb2, 0x9a, 0x85, 0xca, 0xb8, 0x11, 0x48, 0x5b, 0x3c, 0xc2, - 0xd9, 0xf1, 0xbd, 0x45, 0x0f, 0xcf, 0x86, 0x5a, 0x08, 0x06, 0x9c, 0x54, 0x8a, 0x9f, 0x00, 0x1a, 0x3c, 0xd2, 0xcf, - 0x4e, 0x21, 0x8a, 0x9f, 0x36, 0x1e, 0xe8, 0x3f, 0xb4, 0x8f, 0x35, 0xb7, 0x7b, 0x67, 0x75, 0x7c, 0xc7, 0x72, 0xed, - 0x43, 0xcd, 0xb1, 0x8f, 0xac, 0xb6, 0x7d, 0xac, 0xb5, 0xed, 0x2e, 0xfc, 0xeb, 0xbb, 0xf6, 0x2b, 0xcd, 0x81, 0x27, - 0xcd, 0xb5, 0x3b, 0xf8, 0x6f, 0xdb, 0x3e, 0xbe, 0xeb, 0x10, 0xa5, 0xf7, 0x74, 0x31, 0xe4, 0xca, 0x28, 0xc0, 0x09, - 0x44, 0x3f, 0x38, 0x3b, 0x5d, 0xa6, 0x4c, 0x5b, 0x0d, 0xf4, 0x57, 0xba, 0x36, 0x4b, 0xd8, 0x64, 0xa0, 0x3f, 0xf5, - 0x94, 0x52, 0xf7, 0xa4, 0xb1, 0xb8, 0x7d, 0xdc, 0x58, 0xdc, 0x39, 0x6a, 0x2c, 0x3e, 0xec, 0x96, 0x8b, 0x0f, 0xa6, - 0xf4, 0x4a, 0x49, 0xa2, 0x37, 0xf7, 0xb2, 0x24, 0x58, 0xb5, 0x5c, 0x0d, 0xd0, 0xb5, 0x05, 0xff, 0x1c, 0xb7, 0x0d, - 0xd9, 0x6a, 0x04, 0xad, 0x24, 0x34, 0x8e, 0x4f, 0x34, 0xf7, 0xe8, 0x6f, 0xed, 0x23, 0x1f, 0xea, 0x41, 0xca, 0x47, - 0xf8, 0xbb, 0xeb, 0x9c, 0xf8, 0x8e, 0x06, 0x0d, 0x5d, 0xf8, 0x6f, 0xd6, 0x6d, 0xfb, 0xf4, 0xe0, 0xc0, 0xfb, 0x8f, - 0xee, 0x71, 0xea, 0x58, 0x2e, 0xfc, 0xf7, 0xab, 0x54, 0xb9, 0x83, 0xc2, 0x5f, 0xed, 0xf7, 0xd0, 0xd1, 0x3a, 0x27, - 0xb3, 0xb6, 0xfd, 0xea, 0xee, 0xd8, 0x3e, 0x99, 0xb9, 0xc7, 0x1f, 0xe9, 0x29, 0xb4, 0xda, 0xf6, 0x2b, 0xf8, 0xfb, - 0xd8, 0x71, 0x66, 0x96, 0x6b, 0x9f, 0xdc, 0x75, 0xec, 0x4e, 0x68, 0x1d, 0xd9, 0x27, 0xf0, 0xf7, 0x2b, 0x80, 0x17, - 0xe0, 0xca, 0x73, 0x74, 0x6a, 0xb0, 0x31, 0x2a, 0xf6, 0x1b, 0xea, 0x47, 0xda, 0x87, 0x5a, 0xf7, 0xf0, 0x6f, 0x27, - 0x77, 0xd6, 0xe1, 0xcc, 0x6d, 0xdf, 0x59, 0x1b, 0x7f, 0x7e, 0x04, 0xc8, 0x6f, 0x5f, 0x38, 0x00, 0x23, 0x26, 0xe5, - 0xf8, 0xcb, 0xd0, 0xbc, 0xdc, 0x24, 0x46, 0x7f, 0xbf, 0x5b, 0x8c, 0xfe, 0xdd, 0x72, 0x1f, 0x31, 0xfa, 0xfb, 0x2f, - 0x2e, 0x46, 0xbf, 0xac, 0x5a, 0x71, 0xbf, 0xaf, 0x06, 0x0f, 0xff, 0x79, 0x5d, 0x65, 0x92, 0x03, 0xaf, 0x75, 0x7d, - 0xb5, 0xbc, 0x81, 0xb8, 0x3a, 0xef, 0xe3, 0xc1, 0x77, 0xcb, 0x92, 0x89, 0x52, 0x0c, 0x18, 0xe0, 0x7d, 0x4c, 0x18, - 0xe0, 0xd7, 0xe5, 0x00, 0xec, 0x22, 0x38, 0xd5, 0x0c, 0xc6, 0xd6, 0xcc, 0x0b, 0x27, 0x92, 0xe2, 0x42, 0x49, 0x1f, - 0x8b, 0xc1, 0x66, 0x1e, 0x88, 0x09, 0x28, 0x6b, 0x96, 0xf3, 0x28, 0xed, 0x1d, 0x39, 0x80, 0xe6, 0xdb, 0x93, 0x24, - 0xaf, 0x34, 0xb6, 0x45, 0x24, 0xa2, 0x5b, 0x6e, 0xd3, 0xbf, 0xf1, 0x3d, 0x9a, 0xac, 0x35, 0xf7, 0xee, 0xd6, 0xfb, - 0xd5, 0xc0, 0x16, 0x44, 0x98, 0xf4, 0x01, 0xb3, 0xd1, 0xf4, 0xbe, 0x6c, 0x38, 0x56, 0x31, 0x15, 0xdc, 0x3c, 0x52, - 0x18, 0x49, 0xb5, 0xbd, 0x5b, 0x36, 0x3c, 0xdb, 0x35, 0xcd, 0x86, 0xcf, 0x97, 0x9a, 0x6f, 0xb1, 0x7a, 0x93, 0x1d, - 0x57, 0x41, 0x55, 0x49, 0x7d, 0xd5, 0x08, 0x90, 0x82, 0xf7, 0x2c, 0x4c, 0xe3, 0x0a, 0xc6, 0xc7, 0xd1, 0x90, 0x1a, - 0x3b, 0xca, 0xbb, 0x52, 0x9f, 0xaa, 0x39, 0xdd, 0x8b, 0x35, 0xf2, 0x83, 0xc1, 0xaf, 0xc0, 0xd8, 0x70, 0x7a, 0x3c, - 0x8a, 0x55, 0x38, 0xaf, 0x95, 0x7e, 0x89, 0xd5, 0xce, 0x67, 0xee, 0xba, 0xce, 0xda, 0x6c, 0x34, 0xa4, 0x75, 0xd9, - 0x5c, 0xd0, 0x68, 0xfc, 0x3c, 0x99, 0xad, 0xe6, 0x64, 0x5a, 0x8c, 0x96, 0xb9, 0xdb, 0x3a, 0x13, 0xf5, 0x9e, 0xc2, - 0x26, 0x36, 0xf9, 0x83, 0xea, 0x25, 0xbe, 0x9e, 0x40, 0x9a, 0xe2, 0x1e, 0x32, 0x11, 0x0a, 0x07, 0xd5, 0x46, 0x1b, - 0xdb, 0xfe, 0x16, 0xf3, 0x0f, 0xb5, 0x63, 0xde, 0x09, 0xda, 0xea, 0x6e, 0xb3, 0x18, 0x91, 0xae, 0x0d, 0xeb, 0x92, - 0x02, 0xd5, 0xed, 0x1e, 0x9b, 0xee, 0x91, 0x69, 0x1f, 0x77, 0x8d, 0x5c, 0x1c, 0x38, 0xb5, 0xcb, 0x12, 0x40, 0xc0, - 0x64, 0x57, 0x0e, 0x33, 0x88, 0x82, 0x2c, 0xf0, 0xc2, 0x1c, 0x50, 0x7d, 0x99, 0xe7, 0xfd, 0xd7, 0x32, 0xcd, 0x60, - 0x8e, 0x82, 0x25, 0x43, 0x73, 0x65, 0x6b, 0xc4, 0xb2, 0x7b, 0xc6, 0xa2, 0x0d, 0xaa, 0xdc, 0xaa, 0xf5, 0xf3, 0x9f, - 0x67, 0x0b, 0x9a, 0x93, 0x9d, 0xc5, 0x28, 0x8b, 0xf8, 0xfe, 0x10, 0xa6, 0xba, 0xf9, 0xd0, 0xfc, 0x71, 0x13, 0xc2, - 0xfd, 0xd7, 0x6e, 0x84, 0x9b, 0xb1, 0x7d, 0x10, 0xee, 0xbf, 0xbe, 0x38, 0xc2, 0xfd, 0x51, 0x45, 0xb8, 0x25, 0x4f, - 0x95, 0x42, 0x26, 0xfa, 0x01, 0x9f, 0x5b, 0x10, 0x75, 0xf7, 0xa5, 0x7e, 0x40, 0xec, 0xa5, 0xae, 0x64, 0x43, 0xfd, - 0x58, 0x4a, 0xef, 0x82, 0x57, 0x76, 0x0c, 0x3f, 0x4a, 0xa9, 0x24, 0x20, 0x53, 0xa8, 0xcc, 0x79, 0x0d, 0x7d, 0x5e, - 0x44, 0x59, 0x68, 0xbf, 0xe7, 0xd7, 0x12, 0x50, 0x41, 0x7c, 0x17, 0x27, 0x73, 0x0f, 0x43, 0xaf, 0xe9, 0x98, 0x16, - 0x0e, 0x1e, 0x1c, 0xf0, 0x8e, 0xf2, 0xe3, 0x68, 0x2c, 0xe5, 0xe8, 0x6c, 0x70, 0x4d, 0xfc, 0xa0, 0xfe, 0xc0, 0xbc, - 0x44, 0x37, 0xe9, 0x35, 0x2c, 0xee, 0x8b, 0x8e, 0xf3, 0xa2, 0x7d, 0xf8, 0xe2, 0xc8, 0x81, 0xff, 0xb9, 0xac, 0x93, - 0x9b, 0xbc, 0xe2, 0x3c, 0x8e, 0x20, 0x33, 0x85, 0xa8, 0xb9, 0xa9, 0xda, 0x3d, 0x63, 0x9f, 0x8a, 0x5a, 0xc7, 0xcd, - 0x95, 0xc6, 0xde, 0x43, 0x51, 0xa7, 0xb1, 0xc6, 0x2c, 0x5e, 0x2a, 0xc3, 0x6a, 0x18, 0x4d, 0x10, 0x2d, 0x41, 0x32, - 0xa4, 0xd4, 0x50, 0x5f, 0xf3, 0xe9, 0x16, 0xf3, 0x62, 0x9d, 0xfc, 0xa6, 0x48, 0x7f, 0x23, 0xd2, 0x70, 0xec, 0x84, - 0x20, 0x17, 0xaa, 0x3b, 0x18, 0x3c, 0x1b, 0x13, 0xc0, 0x68, 0x90, 0x7c, 0xae, 0xc8, 0x71, 0x8e, 0x0b, 0x94, 0x25, - 0xcb, 0xc8, 0xa7, 0x34, 0xe6, 0xde, 0x28, 0x6d, 0x05, 0x07, 0x10, 0x97, 0x13, 0x3f, 0x6c, 0xe0, 0xaa, 0x79, 0x67, - 0x4e, 0x91, 0x2b, 0x20, 0x15, 0xab, 0xe2, 0xbd, 0xc8, 0xcc, 0x84, 0x32, 0x8c, 0xe2, 0xd2, 0x5a, 0x03, 0xef, 0x85, - 0x6c, 0xf8, 0x22, 0x33, 0x21, 0xcb, 0x27, 0x2c, 0xf7, 0xf3, 0xe7, 0x54, 0x0b, 0xf2, 0xee, 0xd1, 0xb4, 0xce, 0x7d, - 0x99, 0xab, 0x4b, 0xd7, 0xbc, 0x69, 0xac, 0x63, 0xae, 0xae, 0x9e, 0x6f, 0xc6, 0x2f, 0x5f, 0x9e, 0x0d, 0x5c, 0x83, - 0x67, 0x8d, 0x2c, 0xa5, 0x38, 0xba, 0xdc, 0x4f, 0x35, 0x6e, 0x34, 0x3a, 0x6d, 0x2d, 0x82, 0x68, 0x2a, 0x34, 0xd3, - 0x12, 0x7b, 0x41, 0xca, 0x01, 0x52, 0x81, 0x79, 0x42, 0x45, 0x2d, 0xea, 0xdc, 0xb1, 0x04, 0x32, 0x5e, 0x0e, 0xf4, - 0x8e, 0xed, 0xd8, 0x8e, 0x2e, 0x1b, 0x4e, 0x82, 0xe9, 0x60, 0x1d, 0x67, 0x1e, 0x24, 0x6f, 0x09, 0xe3, 0x29, 0x78, - 0x7e, 0x64, 0x41, 0x16, 0x42, 0x26, 0x10, 0x70, 0x01, 0x99, 0xd3, 0xad, 0x31, 0xe7, 0xf6, 0xb8, 0x5e, 0xf2, 0x09, - 0xb3, 0xc1, 0x09, 0xa7, 0x2f, 0x8c, 0x3f, 0xf3, 0x03, 0x10, 0xc3, 0x96, 0xde, 0x82, 0x5c, 0x84, 0x2c, 0x49, 0x2d, - 0xd5, 0xbe, 0xbd, 0xa7, 0x41, 0x1b, 0xc8, 0x13, 0x8e, 0x1d, 0x4c, 0x12, 0x6f, 0x0e, 0x41, 0xb3, 0xd7, 0xb9, 0xc9, - 0x31, 0xad, 0xce, 0x51, 0xad, 0xe6, 0xbe, 0x3a, 0x32, 0xb5, 0xb6, 0x6b, 0x6a, 0x0e, 0xa0, 0x5b, 0x3d, 0x37, 0xd7, - 0xf9, 0x4d, 0x7f, 0x97, 0x8a, 0x8e, 0xf0, 0xcb, 0x53, 0x9a, 0x07, 0x29, 0xe7, 0xb8, 0xf0, 0x33, 0xa3, 0xd0, 0x81, - 0x2d, 0x25, 0x9c, 0x75, 0x40, 0x62, 0xfa, 0x2b, 0xb6, 0xca, 0x0c, 0xcc, 0x94, 0xc1, 0xab, 0x04, 0xc6, 0x1a, 0x5d, - 0xd3, 0x82, 0x48, 0x0b, 0x7e, 0xfb, 0xad, 0x15, 0x80, 0xf9, 0xfd, 0x40, 0x81, 0x0f, 0x3c, 0x1b, 0x25, 0x80, 0x05, - 0x85, 0x62, 0x09, 0x81, 0x05, 0xbe, 0x31, 0xf0, 0x6f, 0x51, 0x2c, 0x7e, 0x70, 0xc5, 0x9e, 0x1d, 0x7a, 0xd1, 0x14, - 0x50, 0x9a, 0x17, 0x4d, 0x6b, 0x06, 0x04, 0xe4, 0x5d, 0x57, 0x29, 0x2d, 0xba, 0x2a, 0x94, 0xfb, 0xe9, 0xb7, 0x0f, - 0x57, 0x94, 0x09, 0x08, 0xb2, 0x4e, 0x7b, 0x63, 0x74, 0x05, 0x2b, 0x74, 0x0f, 0x2f, 0x07, 0x5f, 0x9d, 0xce, 0x59, - 0xe6, 0x91, 0xe0, 0x12, 0xae, 0x78, 0xc0, 0x0e, 0x68, 0xbe, 0xc8, 0xe2, 0x49, 0x17, 0xbc, 0x31, 0xbb, 0x0b, 0x7c, - 0x7e, 0x4f, 0x33, 0x35, 0x4e, 0xa7, 0x2c, 0xb4, 0x51, 0x1a, 0xb8, 0x26, 0x99, 0xc8, 0xfa, 0x1e, 0x06, 0x18, 0x1c, - 0x44, 0xb1, 0x7e, 0xf6, 0x95, 0xf4, 0x26, 0xda, 0xb4, 0x08, 0x90, 0x8e, 0xef, 0x3a, 0x61, 0xe1, 0xbf, 0x07, 0x5f, - 0x01, 0xe1, 0xfe, 0xea, 0x46, 0x37, 0xfa, 0x99, 0x8d, 0xf7, 0x98, 0xaf, 0x1a, 0xd2, 0xd2, 0xe1, 0x1d, 0x95, 0x5f, - 0x36, 0x3b, 0xca, 0x65, 0x13, 0x7e, 0xef, 0xbe, 0xba, 0x9e, 0x9d, 0x22, 0x41, 0x3b, 0x83, 0xdb, 0xc5, 0xba, 0x74, - 0xe7, 0x74, 0xfb, 0x78, 0x41, 0x1d, 0x85, 0x9e, 0xff, 0x49, 0xdc, 0x50, 0xd5, 0x87, 0x7d, 0xee, 0xa2, 0x92, 0xb3, - 0x6b, 0xdc, 0xcb, 0xb8, 0x95, 0xd7, 0xf8, 0x65, 0xfc, 0xd4, 0xfd, 0x2c, 0xc8, 0xe4, 0x65, 0x18, 0x1f, 0x72, 0xd0, - 0xe6, 0xe0, 0xf8, 0x8a, 0xeb, 0x0f, 0x5c, 0x50, 0xdd, 0x93, 0xbf, 0x75, 0xef, 0x5c, 0x67, 0xd6, 0x76, 0x6d, 0xb8, - 0xe6, 0xcc, 0x3a, 0xf6, 0x71, 0x68, 0x75, 0xec, 0x63, 0xf8, 0xfb, 0x08, 0x57, 0x2f, 0xab, 0x6d, 0x1f, 0x7e, 0x74, - 0xdb, 0xa1, 0x75, 0x62, 0x1f, 0xc3, 0xdf, 0x25, 0xb5, 0xfa, 0x19, 0x2f, 0x3d, 0x70, 0xe1, 0xf9, 0xaa, 0x84, 0x05, - 0x94, 0xdf, 0x52, 0x8b, 0x60, 0x96, 0xc8, 0x5b, 0x83, 0x26, 0x02, 0x50, 0x86, 0x6e, 0x8a, 0x80, 0x80, 0x51, 0xbf, - 0x05, 0x79, 0xb2, 0x31, 0xc2, 0xbb, 0x30, 0xc8, 0x88, 0x8a, 0x9c, 0xef, 0x9b, 0x8f, 0x11, 0x6f, 0xd3, 0x1c, 0x6a, - 0x5b, 0xa4, 0x0e, 0x22, 0xd5, 0xc5, 0xdf, 0x17, 0x18, 0x45, 0x47, 0x04, 0x07, 0x57, 0xb0, 0x52, 0x91, 0xbe, 0x2e, - 0xdf, 0x3d, 0x70, 0xf4, 0x1b, 0x65, 0x32, 0x7d, 0xca, 0x17, 0xed, 0x9b, 0xab, 0x33, 0x64, 0xef, 0x7f, 0xb4, 0x1f, - 0xcc, 0x1a, 0x4a, 0xfd, 0x88, 0x38, 0x9e, 0xe3, 0x20, 0x91, 0xc3, 0x53, 0x50, 0xb4, 0xdb, 0x1c, 0xa3, 0xdc, 0x80, - 0x3c, 0x13, 0x17, 0xc0, 0x25, 0xdf, 0x79, 0xa1, 0x62, 0x7a, 0xa1, 0xb4, 0x7c, 0x22, 0x31, 0xff, 0xf3, 0xe7, 0xc5, - 0xe0, 0xac, 0xca, 0xb8, 0x4f, 0xdd, 0x2e, 0x90, 0xdd, 0x2e, 0xeb, 0x6c, 0xb5, 0x02, 0xda, 0x1d, 0x08, 0xb6, 0x08, - 0x1d, 0x29, 0x34, 0xfd, 0x42, 0xc7, 0xb8, 0xd1, 0x14, 0xa9, 0xa6, 0x61, 0x84, 0x10, 0xba, 0x95, 0xab, 0x8e, 0x6e, - 0xf4, 0x23, 0xa1, 0x30, 0x8b, 0xb6, 0x04, 0xbf, 0xe5, 0x77, 0x31, 0x1d, 0x40, 0xb3, 0x65, 0x1e, 0x3b, 0x5c, 0x1a, - 0xff, 0xdf, 0x93, 0x40, 0xf7, 0x22, 0xd0, 0xf0, 0x55, 0x4e, 0x6b, 0xc9, 0xdd, 0x44, 0xd2, 0x55, 0x22, 0xa8, 0x2c, - 0x3d, 0xd7, 0xa1, 0x08, 0x12, 0x10, 0x61, 0xce, 0x31, 0x69, 0xde, 0x24, 0xa9, 0x45, 0x51, 0x60, 0x06, 0x10, 0xfd, - 0xb9, 0x25, 0x5c, 0x9d, 0x8c, 0xe7, 0xcf, 0x37, 0x12, 0x21, 0x52, 0x27, 0xab, 0xa9, 0x17, 0x75, 0x15, 0xbf, 0xe9, - 0x2a, 0x8a, 0x91, 0xfd, 0x22, 0xd6, 0x10, 0x56, 0x59, 0xb4, 0xf7, 0xf0, 0xe7, 0x88, 0x79, 0x99, 0xcd, 0xf5, 0x20, - 0x2d, 0x85, 0xb8, 0x9b, 0x2e, 0xeb, 0x80, 0x3d, 0x16, 0x0f, 0xb6, 0xc5, 0x23, 0xcb, 0x3d, 0x5b, 0x7f, 0x5c, 0x72, - 0x3f, 0x64, 0xe8, 0xe3, 0x37, 0xa7, 0x08, 0x9e, 0xf2, 0x2e, 0xf3, 0x28, 0xc2, 0x86, 0x4a, 0x72, 0xe3, 0xcc, 0x13, - 0x89, 0x3e, 0x80, 0x2f, 0xef, 0x37, 0x2a, 0x0c, 0x15, 0x5f, 0xe5, 0xb3, 0x77, 0x57, 0xdf, 0x68, 0x7c, 0xff, 0x93, - 0x7e, 0x0b, 0x2f, 0x32, 0x14, 0xef, 0x7e, 0x40, 0xf1, 0xee, 0x35, 0x9e, 0xe7, 0x01, 0xa2, 0xc6, 0xe7, 0x07, 0x04, - 0x41, 0x5d, 0x63, 0x91, 0x4f, 0x5a, 0xbf, 0xf9, 0x32, 0xcc, 0x82, 0x85, 0x97, 0x64, 0x07, 0xd0, 0xd4, 0x02, 0x24, - 0xa7, 0x6f, 0xf2, 0x60, 0x26, 0xc5, 0xa1, 0x10, 0xaa, 0x65, 0x91, 0xd0, 0x1c, 0x4e, 0x82, 0x50, 0x2a, 0x0e, 0xc5, - 0x07, 0x3c, 0xdf, 0x67, 0x8b, 0x6c, 0xa0, 0x7b, 0x0b, 0xc8, 0x7b, 0x80, 0x91, 0x8c, 0x0f, 0x62, 0x3f, 0x63, 0x99, - 0x95, 0x66, 0x09, 0xf3, 0xe6, 0xba, 0x0c, 0xeb, 0x59, 0xef, 0x2f, 0x5d, 0x8e, 0xe6, 0x41, 0x26, 0x23, 0xe3, 0xd1, - 0x04, 0x41, 0x85, 0x07, 0x43, 0x3c, 0x1b, 0xe6, 0x1c, 0x84, 0x97, 0xf1, 0xb4, 0xb2, 0xa3, 0x0a, 0xce, 0xe5, 0x1c, - 0xa3, 0xae, 0xf2, 0x58, 0xf7, 0x63, 0xf4, 0xc8, 0xb9, 0xe5, 0x5e, 0xd7, 0x32, 0x80, 0x9f, 0x7e, 0x76, 0xca, 0xaf, - 0xb7, 0x1a, 0x06, 0x0a, 0xd0, 0xbb, 0x0e, 0xc4, 0x95, 0xdd, 0xe4, 0x8f, 0x7d, 0xc0, 0x2b, 0x03, 0x69, 0xa2, 0x9e, - 0x31, 0xc2, 0x37, 0x8d, 0xe5, 0x0a, 0x18, 0xa1, 0x92, 0x8a, 0x77, 0xe6, 0x9e, 0x49, 0x07, 0x20, 0x1c, 0x15, 0xf2, - 0x4a, 0xbf, 0xfd, 0xf6, 0x7a, 0xf8, 0x9f, 0xdf, 0x21, 0x0c, 0xf9, 0xcc, 0x15, 0x5e, 0xd0, 0xd7, 0x6a, 0x2d, 0xce, - 0x7d, 0x9a, 0x43, 0x54, 0xef, 0xb3, 0xb1, 0x08, 0x0b, 0x22, 0xb6, 0x56, 0x3e, 0xbc, 0x11, 0xa1, 0x9e, 0x20, 0xd5, - 0x80, 0x21, 0x7c, 0xb5, 0x87, 0xb0, 0xbc, 0x43, 0x11, 0x22, 0x40, 0xfb, 0x65, 0xf5, 0xed, 0x31, 0xa4, 0xcd, 0xad, - 0x65, 0x00, 0x50, 0x06, 0x88, 0x7b, 0xe8, 0xec, 0xd4, 0xe3, 0xc2, 0x57, 0x60, 0x3f, 0xd2, 0xde, 0x01, 0x4c, 0x73, - 0x16, 0xcf, 0x99, 0x1d, 0xc4, 0x07, 0xf7, 0x6c, 0x64, 0x79, 0x8b, 0x80, 0xe4, 0xcb, 0x28, 0x77, 0xd3, 0x88, 0xf3, - 0x93, 0x0a, 0x5a, 0xe2, 0xaf, 0xf3, 0x02, 0x94, 0x71, 0x01, 0x28, 0xf8, 0xe9, 0x9d, 0x95, 0xa3, 0xf5, 0xd9, 0x22, - 0x36, 0x7c, 0x19, 0xcb, 0x9f, 0x53, 0xd0, 0x3d, 0x11, 0x5f, 0xaf, 0x78, 0xb0, 0xe2, 0xc9, 0x44, 0x8d, 0xb0, 0x67, - 0x97, 0xbf, 0x2f, 0xa1, 0x52, 0xec, 0xd9, 0x78, 0x41, 0x5f, 0xaa, 0x7f, 0x42, 0xfe, 0x84, 0xf4, 0xb5, 0x3c, 0x18, - 0x23, 0x9c, 0xe7, 0x5a, 0xa4, 0x3e, 0x09, 0x92, 0xa7, 0x54, 0x89, 0x23, 0x8a, 0x6a, 0x0c, 0xe8, 0x0d, 0xac, 0xc9, - 0x93, 0xc1, 0x80, 0xf0, 0x58, 0x15, 0x9d, 0x01, 0x94, 0x1a, 0xe2, 0xe4, 0xc3, 0x64, 0x33, 0x68, 0x68, 0x91, 0x07, - 0x17, 0x36, 0xaa, 0x4e, 0xa7, 0x3e, 0xc6, 0x03, 0x4f, 0xec, 0xaf, 0xd2, 0x0e, 0x84, 0x9d, 0xc5, 0x17, 0x16, 0x10, - 0xb8, 0xe8, 0xa7, 0x82, 0xc7, 0xb5, 0xaf, 0x09, 0x65, 0x5b, 0xa1, 0xf7, 0x10, 0x2b, 0x9a, 0x75, 0xee, 0x64, 0x7f, - 0x89, 0xa5, 0x57, 0xc2, 0xb9, 0xad, 0x76, 0x92, 0x64, 0xac, 0xf1, 0xfa, 0x69, 0x52, 0x83, 0x83, 0xef, 0x3a, 0x4c, - 0x6a, 0xdd, 0xf2, 0x64, 0x10, 0x3b, 0xe6, 0xc5, 0x41, 0x2b, 0xbd, 0xc4, 0x73, 0x9f, 0x9f, 0x1e, 0xc0, 0xfc, 0x20, - 0x30, 0x40, 0x89, 0x33, 0x0a, 0x0c, 0x88, 0x3e, 0xe0, 0xa5, 0x64, 0x1d, 0x70, 0x31, 0x16, 0x4c, 0x1d, 0xde, 0x1c, - 0x65, 0x28, 0xd0, 0x52, 0x95, 0x3a, 0xb3, 0xe2, 0x34, 0x73, 0x79, 0xbb, 0x63, 0xf3, 0xff, 0xba, 0xc4, 0xc0, 0xfc, - 0x79, 0x3f, 0x63, 0xc2, 0xef, 0xf6, 0x32, 0xdb, 0xe0, 0x9a, 0xbb, 0xa9, 0x0a, 0x31, 0xac, 0x5b, 0x2a, 0x14, 0xfb, - 0x78, 0x5b, 0xad, 0x82, 0x35, 0x92, 0xd5, 0x16, 0x5e, 0x4b, 0x7f, 0x8a, 0x3b, 0xbe, 0x56, 0x1b, 0x4b, 0xa1, 0xde, - 0x65, 0x36, 0x80, 0xaa, 0x42, 0xd8, 0xee, 0x2d, 0x16, 0x54, 0xd9, 0xe8, 0x9f, 0x1e, 0xd0, 0xbd, 0xf3, 0x8c, 0x76, - 0xd8, 0xd9, 0x29, 0x58, 0x17, 0xd2, 0xa2, 0x7b, 0x8b, 0x05, 0x5f, 0x52, 0xfa, 0x45, 0x6f, 0x0e, 0x66, 0xd9, 0x3c, - 0x3c, 0xfb, 0x2f, 0x85, 0x07, 0xd6, 0xc5, 0xa2, 0x59, 0x03, 0x00}; + 0xe4, 0xe5, 0x65, 0xce, 0xc3, 0xc0, 0xc4, 0xf8, 0x08, 0xa8, 0xad, 0x66, 0xf6, 0x7f, 0x9a, 0x7b, 0xfa, 0xe5, 0xb6, + 0x6d, 0xe4, 0xff, 0xbf, 0xa7, 0x60, 0x98, 0x5c, 0x2a, 0x26, 0x24, 0x4d, 0x4a, 0x96, 0xed, 0x48, 0x96, 0xdd, 0x36, + 0x49, 0xe7, 0xdc, 0x71, 0x9b, 0x4e, 0xe2, 0xcb, 0xdc, 0xd5, 0xf5, 0x58, 0x14, 0x05, 0x49, 0xbc, 0x50, 0xa4, 0x86, + 0xa4, 0x6c, 0xb9, 0x2a, 0xef, 0x59, 0xfa, 0x2c, 0xf7, 0x64, 0xbf, 0xd9, 0x5d, 0x00, 0x04, 0x3f, 0xf4, 0xe1, 0x26, + 0xbd, 0xfb, 0x4d, 0xcf, 0x17, 0x11, 0x04, 0x40, 0x60, 0x01, 0x2c, 0xf6, 0x7b, 0x9f, 0x38, 0x22, 0xb0, 0xa6, 0x91, + 0x6f, 0x3a, 0x5a, 0x62, 0xc6, 0x4c, 0x46, 0x9e, 0x23, 0x02, 0x13, 0x45, 0xa8, 0x77, 0xa8, 0x85, 0xe0, 0xeb, 0x52, + 0x1c, 0x5d, 0x6b, 0x1c, 0x2f, 0x47, 0x21, 0xb3, 0x70, 0xbb, 0xc3, 0x27, 0xd7, 0xa3, 0xe5, 0x68, 0x04, 0xc9, 0x54, + 0x9e, 0x38, 0x26, 0x84, 0x87, 0x89, 0x53, 0x64, 0xdb, 0x72, 0xa3, 0x0f, 0x93, 0xb2, 0xb3, 0xea, 0xf0, 0xc1, 0xa4, + 0x03, 0x24, 0x32, 0xf4, 0x81, 0x0c, 0x58, 0xb4, 0x86, 0x53, 0x3b, 0xd0, 0x3f, 0xc0, 0xee, 0x4b, 0xf5, 0x7e, 0xd3, + 0xd1, 0x1f, 0x5c, 0xeb, 0x1f, 0x10, 0xc6, 0x98, 0x64, 0xf8, 0x35, 0xed, 0x5e, 0xdd, 0xd4, 0x49, 0x37, 0xbd, 0xc4, + 0x74, 0x03, 0x20, 0x9b, 0x7d, 0x13, 0x78, 0xd3, 0x28, 0x4e, 0xb3, 0xc0, 0xd7, 0x6f, 0xfa, 0x17, 0x41, 0xeb, 0x7a, + 0x9e, 0xb5, 0x8c, 0x1b, 0xd3, 0xcf, 0xd4, 0x4c, 0x25, 0x02, 0x61, 0x62, 0xa2, 0x92, 0x4d, 0x95, 0xd4, 0x13, 0xb4, + 0xb5, 0xa2, 0x40, 0xcd, 0x58, 0xc9, 0xcf, 0x06, 0x50, 0xaf, 0x92, 0xf6, 0x04, 0xf3, 0x37, 0xe9, 0xd8, 0xd2, 0xe8, + 0x13, 0x43, 0xf1, 0x7a, 0xb9, 0xc6, 0xab, 0x3c, 0x2b, 0x6e, 0x4b, 0x0c, 0xd5, 0x2b, 0xfc, 0x5b, 0xe8, 0xf9, 0x89, + 0x6a, 0x9b, 0x59, 0xba, 0x77, 0x87, 0xdf, 0x94, 0xe9, 0x02, 0xb8, 0xbf, 0xc1, 0x30, 0x22, 0x8a, 0x33, 0x0d, 0xe2, + 0xcf, 0xc0, 0x17, 0x87, 0x55, 0x5b, 0x2e, 0xde, 0x6b, 0xcb, 0xc8, 0x39, 0x32, 0xf8, 0x16, 0x2f, 0xbf, 0x16, 0x8f, + 0x42, 0x56, 0x0a, 0x34, 0x41, 0x34, 0x7d, 0x04, 0x0b, 0x98, 0xc5, 0x97, 0xf1, 0x7d, 0x55, 0x5d, 0xf1, 0x7a, 0xb8, + 0xfb, 0xee, 0xc5, 0x0b, 0x10, 0xf6, 0x9b, 0x48, 0xbe, 0xd7, 0xe2, 0xf9, 0x43, 0x05, 0xa1, 0x53, 0x39, 0x53, 0x68, + 0x9f, 0x21, 0x68, 0x98, 0x0c, 0xcc, 0xb9, 0xf0, 0x2e, 0x00, 0x94, 0xc4, 0xaf, 0xe9, 0x61, 0x7e, 0x2b, 0x32, 0x1c, + 0x8b, 0xfc, 0xc2, 0xca, 0xe5, 0x0c, 0xd8, 0x35, 0x5a, 0x2c, 0x33, 0x8c, 0x88, 0x0b, 0x03, 0x60, 0xb9, 0xae, 0x61, + 0x84, 0x4d, 0xc0, 0xd2, 0x05, 0x99, 0x98, 0xeb, 0x5a, 0x30, 0xae, 0x97, 0x71, 0xa2, 0x17, 0x90, 0x17, 0xe2, 0x77, + 0x94, 0x27, 0xc1, 0x63, 0xc2, 0xa7, 0xe1, 0x9b, 0x45, 0x38, 0xf9, 0x96, 0x8f, 0x7a, 0x97, 0x06, 0xcc, 0xe0, 0x53, + 0x3f, 0xfd, 0x56, 0xd8, 0x38, 0x59, 0x88, 0x92, 0x59, 0x9a, 0xe6, 0xf0, 0xd9, 0x3a, 0xca, 0xcf, 0x9f, 0xad, 0xd3, + 0x7c, 0xf0, 0x6c, 0xed, 0x01, 0x25, 0x97, 0xeb, 0x30, 0xd1, 0xc2, 0x9f, 0xa6, 0x98, 0x1e, 0x6c, 0x2a, 0x2a, 0xd7, + 0x50, 0xa1, 0x3e, 0xe0, 0x6a, 0xf3, 0x45, 0x12, 0xcc, 0xbd, 0xe4, 0x81, 0xb4, 0xec, 0xa6, 0xaa, 0x8a, 0x37, 0x74, + 0x8d, 0xf0, 0x3a, 0xcd, 0x97, 0x50, 0xbc, 0xae, 0x7d, 0x2d, 0xcb, 0x18, 0x9f, 0x9c, 0x54, 0x35, 0xc2, 0xb7, 0x6e, + 0xf5, 0x97, 0xcc, 0x1e, 0xb3, 0xcc, 0x0b, 0x42, 0x6a, 0xd2, 0x17, 0x39, 0xe4, 0x6b, 0xb3, 0x49, 0xcb, 0xb3, 0x89, + 0xca, 0xdb, 0x05, 0x27, 0x43, 0x18, 0x9f, 0xc6, 0x8d, 0x33, 0xc3, 0xdc, 0x52, 0xcd, 0x0b, 0x48, 0xef, 0xfe, 0xab, + 0xd0, 0x67, 0x00, 0xfd, 0x08, 0xa0, 0xcf, 0x22, 0x3f, 0x1e, 0xb3, 0xbf, 0xbf, 0xbf, 0x90, 0xc9, 0xac, 0x40, 0x2e, + 0x33, 0xe4, 0xfb, 0x30, 0x45, 0x72, 0x21, 0x41, 0x52, 0x81, 0xd2, 0x4e, 0x69, 0x72, 0xc7, 0x24, 0xb9, 0xae, 0x9d, + 0xd3, 0xd8, 0xd9, 0x98, 0x46, 0x3d, 0x88, 0xb1, 0x55, 0x92, 0x9f, 0x1e, 0x50, 0x6d, 0xba, 0xdc, 0xa8, 0x12, 0x80, + 0x21, 0x81, 0x19, 0x16, 0x50, 0x80, 0xbc, 0x9b, 0x03, 0xb7, 0xe0, 0x1f, 0xec, 0x39, 0x4a, 0xbf, 0xdd, 0xf3, 0x32, + 0x65, 0x82, 0xad, 0xf4, 0xb3, 0x53, 0xcc, 0xa4, 0x05, 0xd7, 0x33, 0xc4, 0xde, 0x38, 0x3d, 0xa0, 0x47, 0xad, 0x72, + 0x00, 0x8a, 0x4e, 0x04, 0x27, 0xd7, 0xe3, 0x1d, 0x3c, 0xea, 0x64, 0x40, 0xe2, 0x76, 0x28, 0xf5, 0x72, 0x5d, 0x9b, + 0x73, 0x4a, 0x88, 0x07, 0xf9, 0x81, 0x08, 0x00, 0x0e, 0x1c, 0x55, 0x5d, 0x9b, 0x7b, 0x2b, 0x9c, 0xb9, 0x78, 0xe3, + 0xad, 0x5a, 0x2e, 0x7f, 0x55, 0x1c, 0xad, 0xb4, 0x7c, 0xb4, 0x7c, 0xbe, 0xb8, 0x60, 0xde, 0x2f, 0xa4, 0xb6, 0xad, + 0x19, 0xaa, 0x4d, 0x1b, 0x16, 0x77, 0x26, 0x16, 0x77, 0xbc, 0x61, 0x71, 0xc7, 0x5b, 0x16, 0x37, 0xe4, 0x0b, 0xa9, + 0x49, 0xd0, 0x25, 0xe8, 0xb2, 0x25, 0x81, 0xc7, 0xe9, 0x8a, 0x1e, 0x3f, 0x67, 0x08, 0x27, 0x2b, 0x0d, 0xc1, 0x64, + 0x69, 0x03, 0xac, 0x9a, 0xe0, 0xa2, 0x00, 0xa2, 0x3e, 0x71, 0x79, 0xea, 0xc4, 0xbc, 0x21, 0x33, 0x66, 0x2b, 0xac, + 0xce, 0x17, 0x76, 0x29, 0x65, 0xfd, 0x6e, 0xcd, 0x36, 0xcc, 0x74, 0xb6, 0x65, 0xa6, 0x7e, 0xe9, 0xe8, 0xf2, 0x69, + 0xd3, 0x21, 0x54, 0x27, 0x05, 0x7b, 0x10, 0xcc, 0x38, 0x71, 0xcb, 0x94, 0xf7, 0xe1, 0x66, 0x94, 0xaa, 0xec, 0xa8, + 0x85, 0x97, 0xa6, 0xf7, 0x71, 0x02, 0x7a, 0x10, 0xe8, 0xe6, 0x71, 0x5b, 0x6a, 0x1e, 0x44, 0x3c, 0xc4, 0xca, 0xc6, + 0xcd, 0x54, 0xbc, 0x57, 0xb7, 0x54, 0xbb, 0xdb, 0xa5, 0x1a, 0x0b, 0x2f, 0xcb, 0x58, 0x82, 0x40, 0xf7, 0x20, 0x16, + 0x77, 0xae, 0x6b, 0xff, 0x0f, 0x76, 0x59, 0x03, 0x0a, 0x09, 0x8d, 0x02, 0xa9, 0x23, 0x82, 0x5e, 0x00, 0x25, 0x95, + 0x88, 0x6b, 0x57, 0x89, 0xd6, 0x96, 0x48, 0xb8, 0xff, 0x88, 0xa7, 0xb5, 0x95, 0x28, 0xfe, 0x44, 0xee, 0x91, 0x61, + 0x2f, 0xbc, 0xf1, 0x07, 0xd0, 0xb6, 0xb5, 0xda, 0x26, 0x58, 0xce, 0xaa, 0xb1, 0xd9, 0x12, 0x22, 0xed, 0xfc, 0x02, + 0x47, 0x22, 0x92, 0xe4, 0x76, 0x49, 0xe0, 0xd2, 0xe8, 0x59, 0x93, 0x9b, 0x75, 0x3b, 0x3f, 0x98, 0x06, 0x46, 0x0d, + 0x69, 0x02, 0x66, 0x0b, 0x07, 0x67, 0x92, 0xc3, 0x0a, 0x4d, 0xf7, 0xc8, 0x00, 0x71, 0xec, 0x35, 0x24, 0x19, 0x75, + 0x04, 0xfb, 0x3a, 0x4c, 0xe0, 0x8e, 0xba, 0x76, 0x6e, 0xf2, 0xe7, 0x53, 0xfc, 0xe5, 0xde, 0xe4, 0xcf, 0x47, 0xf8, + 0xab, 0x7d, 0x83, 0xe9, 0xe4, 0x1a, 0xd8, 0x76, 0x65, 0xce, 0xfa, 0x59, 0x69, 0x3b, 0x91, 0x51, 0xd8, 0x23, 0x76, + 0x0d, 0x5f, 0xe0, 0xa7, 0xcf, 0xd6, 0x29, 0xb8, 0x41, 0xaa, 0x73, 0x88, 0xec, 0xc4, 0xc8, 0x1b, 0xcb, 0xa7, 0x1b, + 0xca, 0x47, 0xc6, 0x7f, 0xf9, 0x9a, 0xc7, 0x5d, 0x12, 0x17, 0x57, 0x4a, 0x59, 0xe8, 0x70, 0x3b, 0x0a, 0x22, 0x2f, + 0x79, 0xb8, 0x25, 0x66, 0xa2, 0x25, 0x28, 0x75, 0x29, 0x4c, 0x21, 0x62, 0xb2, 0xac, 0x83, 0xca, 0x14, 0xa9, 0xeb, + 0x03, 0xbf, 0xe7, 0x07, 0xff, 0x48, 0x14, 0x22, 0xad, 0xc4, 0x6e, 0xf2, 0x05, 0x29, 0x7d, 0xe8, 0xf6, 0xd9, 0xba, + 0xc5, 0xea, 0xdd, 0x54, 0x66, 0x5b, 0xa1, 0x02, 0x61, 0x79, 0x90, 0x75, 0x9d, 0x8f, 0x83, 0x1e, 0x2a, 0x99, 0x46, + 0xf1, 0xca, 0x7a, 0xb6, 0xce, 0xce, 0xf5, 0xb9, 0x97, 0x7c, 0x62, 0x63, 0xcb, 0x0f, 0x12, 0x3f, 0x64, 0x7a, 0x4f, + 0x1f, 0x85, 0x5e, 0xf4, 0x89, 0x3f, 0x5a, 0xf1, 0x32, 0x43, 0xb5, 0xf1, 0x4e, 0x4e, 0x57, 0xc0, 0x84, 0x04, 0x74, + 0x48, 0x9a, 0x36, 0x40, 0x41, 0x7b, 0x2d, 0xc5, 0x5b, 0x05, 0x59, 0x58, 0xd4, 0x32, 0xc1, 0xea, 0x11, 0x34, 0xd9, + 0xe0, 0x46, 0x6a, 0xea, 0xb8, 0x5e, 0xba, 0xa9, 0x4e, 0x95, 0x44, 0x93, 0x32, 0x0f, 0xe2, 0x2d, 0xf6, 0xf0, 0xc7, + 0x3f, 0x47, 0x19, 0xaa, 0xf7, 0xff, 0x1c, 0x27, 0xf1, 0x36, 0x7f, 0x50, 0x6d, 0xec, 0xa5, 0xe9, 0x72, 0xce, 0xc6, + 0xa4, 0x31, 0x3b, 0x2f, 0x86, 0x52, 0x26, 0xe5, 0xd5, 0xe1, 0xfc, 0xb2, 0x6c, 0x1f, 0x1f, 0xbe, 0x06, 0x4d, 0x3e, + 0x90, 0x74, 0xf1, 0x64, 0xa2, 0x17, 0x4c, 0xf5, 0x8e, 0x66, 0xee, 0xe1, 0x2f, 0xcb, 0xef, 0xde, 0x3a, 0xdf, 0xc9, + 0xc6, 0x91, 0x6e, 0xe4, 0x43, 0xa1, 0x96, 0xe4, 0x94, 0xa9, 0x32, 0x5e, 0x31, 0xa3, 0x89, 0x17, 0x6d, 0x9e, 0xce, + 0x75, 0x69, 0x97, 0x2d, 0x18, 0x1b, 0x83, 0xc5, 0xaa, 0x59, 0x2b, 0xbd, 0x0d, 0xd9, 0x1d, 0x93, 0x2a, 0xcf, 0xfa, + 0xc7, 0x1a, 0x5a, 0x60, 0x4c, 0x36, 0xae, 0x4a, 0xe5, 0x74, 0x95, 0x32, 0xa5, 0x21, 0xce, 0x81, 0xcf, 0x5c, 0xdd, + 0xe5, 0x95, 0x5d, 0x3d, 0x34, 0x75, 0x65, 0x00, 0x1b, 0x47, 0x76, 0xbe, 0xa1, 0xbc, 0x87, 0x09, 0x99, 0x9b, 0xc7, + 0x66, 0xba, 0x46, 0x0f, 0x62, 0x58, 0x73, 0x38, 0x85, 0xb0, 0xf9, 0x5b, 0x85, 0xfc, 0x61, 0x13, 0xc4, 0x9a, 0xa4, + 0x52, 0x3a, 0x89, 0x3b, 0x84, 0x15, 0x20, 0x9a, 0xc3, 0x0a, 0xc1, 0x4f, 0xe3, 0xda, 0x68, 0xe5, 0x99, 0x8f, 0x30, + 0xd1, 0x69, 0xc4, 0xd2, 0x74, 0x23, 0xc0, 0xe4, 0xa2, 0x9b, 0x7a, 0x51, 0xbb, 0x0c, 0x8f, 0xa2, 0xdc, 0x74, 0x4c, + 0xb8, 0x94, 0x71, 0x82, 0xd5, 0x6f, 0x21, 0x86, 0xbf, 0x9d, 0x73, 0x3b, 0x8e, 0x64, 0x3a, 0xd2, 0xb9, 0x8e, 0x7d, + 0xd3, 0xfb, 0x7b, 0x9d, 0x0f, 0xaa, 0x74, 0x53, 0x36, 0x0e, 0xad, 0x55, 0xc2, 0x7e, 0x35, 0xf9, 0x0c, 0x76, 0x20, + 0xc6, 0x54, 0x41, 0x71, 0x6c, 0x32, 0x61, 0x7e, 0x96, 0x1a, 0x42, 0x5a, 0x23, 0xa3, 0xaa, 0x82, 0x37, 0xcd, 0x93, + 0x81, 0xfe, 0x23, 0xf8, 0x96, 0x8b, 0xe0, 0x43, 0x7c, 0x40, 0x82, 0x6b, 0x69, 0x06, 0x13, 0xf5, 0x58, 0x06, 0x11, + 0xff, 0x0a, 0x24, 0xcd, 0x6e, 0x28, 0xc7, 0xa1, 0xf1, 0x2b, 0xa0, 0xd8, 0x17, 0xb1, 0xb4, 0xf6, 0xd8, 0x8e, 0x80, + 0xb6, 0x1d, 0xdf, 0xb5, 0xfb, 0x5d, 0xd7, 0x75, 0x72, 0xdd, 0x04, 0x9f, 0xa6, 0x4f, 0xfb, 0x1e, 0x7a, 0x6c, 0xd5, + 0x81, 0x56, 0xcb, 0xe8, 0x31, 0xed, 0xda, 0xee, 0x2b, 0x57, 0x37, 0xc9, 0x94, 0x4c, 0xc1, 0x6d, 0x7e, 0x7c, 0xc7, + 0x92, 0xcf, 0x9e, 0x4a, 0xb9, 0xf3, 0xfd, 0xc6, 0x73, 0xe4, 0x3a, 0x80, 0x84, 0xb3, 0x78, 0xf1, 0x88, 0x29, 0x74, + 0x74, 0x53, 0xf7, 0xc3, 0x38, 0x65, 0xea, 0x1c, 0x48, 0xea, 0xf0, 0x99, 0x93, 0xf8, 0xe9, 0xfd, 0xdb, 0x0f, 0x1f, + 0x74, 0x13, 0x33, 0x64, 0xa6, 0x6a, 0xef, 0x7c, 0x43, 0xed, 0xc0, 0xfe, 0x8d, 0xfb, 0x8e, 0x6e, 0x18, 0x62, 0x2b, + 0xcb, 0x7b, 0x8e, 0xca, 0x6a, 0x5b, 0x8e, 0xdf, 0x3c, 0xfc, 0xcb, 0xc4, 0x0b, 0xee, 0x35, 0xaf, 0x06, 0xdc, 0xb0, + 0xfd, 0x7a, 0x2b, 0x95, 0xcc, 0x83, 0xe8, 0xb6, 0xa1, 0xd4, 0x5b, 0x35, 0x94, 0x02, 0x33, 0x55, 0xc3, 0x55, 0xcb, + 0x78, 0xae, 0xdc, 0xce, 0x90, 0xe0, 0x78, 0x17, 0xb8, 0x14, 0x8e, 0xe6, 0x33, 0x06, 0xcd, 0x23, 0x9c, 0x57, 0x47, + 0xdd, 0x50, 0xcc, 0xd9, 0x10, 0x09, 0x5b, 0x3f, 0x04, 0x43, 0x38, 0xa6, 0xaa, 0xc1, 0xca, 0x94, 0x9b, 0x34, 0x63, + 0x55, 0x3a, 0x21, 0x0a, 0xf3, 0x36, 0x63, 0xf3, 0x05, 0x4b, 0xbc, 0x6c, 0x99, 0xb0, 0xdb, 0x30, 0xbe, 0x7f, 0x52, + 0x98, 0x99, 0xef, 0xa8, 0x3c, 0x0b, 0xa6, 0x33, 0x59, 0xfb, 0xbc, 0xc5, 0x06, 0x72, 0x01, 0xb7, 0x7e, 0x20, 0xff, + 0xcf, 0xef, 0xb6, 0xfd, 0x9f, 0xdf, 0x77, 0x56, 0x85, 0xee, 0xf3, 0xa1, 0x99, 0x0d, 0xf6, 0xd8, 0x17, 0xcd, 0x5f, + 0x2a, 0xc3, 0xbc, 0xb9, 0x4e, 0x6d, 0x11, 0xe0, 0x7d, 0x6d, 0x09, 0x6a, 0x85, 0xe5, 0x7d, 0xf3, 0xa8, 0x81, 0xc1, + 0xbc, 0x76, 0x8e, 0x0c, 0x2a, 0x7d, 0xd6, 0xd0, 0x86, 0x46, 0x6f, 0xaf, 0x15, 0xf9, 0xe3, 0x10, 0xde, 0x35, 0x87, + 0xcf, 0x1c, 0x3e, 0x97, 0x0c, 0xbe, 0x1e, 0x0e, 0x65, 0xce, 0x35, 0xb5, 0x29, 0x98, 0xbe, 0x9f, 0xd7, 0x4a, 0xf8, + 0xe5, 0xd9, 0x73, 0x0c, 0xf2, 0x49, 0x1f, 0xbc, 0x1e, 0xa2, 0x91, 0xd6, 0xe9, 0x28, 0x29, 0x88, 0x95, 0x8d, 0xa8, + 0x8d, 0x8c, 0xac, 0x6b, 0x9d, 0xd6, 0xf0, 0x1a, 0x94, 0x62, 0x22, 0xae, 0x7c, 0x68, 0x98, 0xaf, 0x87, 0x5c, 0xb4, + 0xc3, 0xed, 0x42, 0x7b, 0xd5, 0xad, 0xcd, 0x05, 0xa3, 0x25, 0xa0, 0x9b, 0x1a, 0x29, 0x5c, 0xb0, 0x32, 0x2b, 0x24, + 0x69, 0x28, 0x51, 0x07, 0xa6, 0x7e, 0x98, 0x63, 0x1e, 0x90, 0x77, 0x9b, 0x6c, 0xa7, 0x7e, 0xda, 0x6d, 0x3b, 0x75, + 0xb5, 0x97, 0xed, 0xd4, 0x4f, 0x5f, 0xdc, 0x76, 0xea, 0x9d, 0x6a, 0x3b, 0x05, 0x8b, 0xf8, 0x96, 0xed, 0x65, 0xd0, + 0x24, 0xcc, 0x24, 0xe2, 0xfb, 0x74, 0xe0, 0x72, 0x92, 0x36, 0xf5, 0x67, 0x0c, 0xd8, 0x74, 0xbe, 0x2a, 0x61, 0x3c, + 0x05, 0xe3, 0xa6, 0x3f, 0xdf, 0x0c, 0x29, 0x8c, 0xa7, 0xaa, 0x11, 0x52, 0xc4, 0x23, 0xa1, 0x16, 0xd1, 0x8d, 0xc8, + 0xf0, 0xc7, 0x31, 0x45, 0x2c, 0x24, 0xeb, 0xd0, 0x50, 0xb2, 0x3d, 0x4b, 0xab, 0xae, 0xb6, 0x30, 0x0d, 0xea, 0xa1, + 0x55, 0x91, 0x6c, 0xd8, 0x7e, 0x29, 0x62, 0x3e, 0xa8, 0x3d, 0x48, 0xeb, 0x59, 0x8a, 0x9f, 0xb0, 0xd6, 0x7f, 0x59, + 0xb9, 0xdf, 0x5e, 0xbb, 0xfd, 0x8e, 0x0b, 0x4e, 0xcb, 0xc0, 0xe4, 0x61, 0x81, 0xd3, 0xef, 0x74, 0xa0, 0xe0, 0x5e, + 0x29, 0x68, 0x43, 0x41, 0xa0, 0x14, 0x74, 0xa1, 0xc0, 0x57, 0x0a, 0x8e, 0xa0, 0x60, 0xac, 0x14, 0x1c, 0x43, 0xc1, + 0x9d, 0x9e, 0x5f, 0x47, 0x72, 0xb8, 0xc7, 0xc6, 0x8d, 0x49, 0x4c, 0x85, 0x28, 0x3b, 0x36, 0x5d, 0xb0, 0x26, 0xf2, + 0xa6, 0xbd, 0xd8, 0x24, 0xf9, 0x5e, 0x2f, 0x31, 0xef, 0x67, 0x8c, 0x02, 0x28, 0xbf, 0xc1, 0x3b, 0xc7, 0xce, 0x62, + 0xb0, 0x27, 0x16, 0x81, 0x09, 0x04, 0x1c, 0x34, 0xdd, 0x00, 0x99, 0x4d, 0x5f, 0xae, 0x9c, 0x08, 0xee, 0xa0, 0xac, + 0x65, 0xf1, 0x8e, 0x3e, 0x67, 0xc9, 0x2d, 0x50, 0x98, 0x78, 0xb4, 0x54, 0xb9, 0xe0, 0x97, 0x50, 0xf4, 0xbf, 0x61, + 0xa3, 0xe5, 0x54, 0xbb, 0x8c, 0xa7, 0x3b, 0x75, 0xf6, 0xea, 0x2b, 0x18, 0xa5, 0x4e, 0x0a, 0x10, 0x4b, 0x6c, 0x4b, + 0xfe, 0x2d, 0x7a, 0xcc, 0xcb, 0xf5, 0x33, 0x18, 0x9b, 0x96, 0x91, 0xc5, 0x08, 0x7c, 0x07, 0x60, 0xa4, 0x28, 0xcd, + 0x2f, 0x01, 0xce, 0xca, 0xf3, 0x95, 0xa7, 0x8c, 0xe7, 0xec, 0x07, 0x96, 0xa6, 0xde, 0x54, 0xd4, 0xaf, 0x8f, 0x13, + 0xac, 0x64, 0x24, 0xff, 0x85, 0x00, 0x04, 0x61, 0x5a, 0x50, 0x33, 0x86, 0x48, 0xe2, 0x7b, 0x0d, 0xcc, 0x6d, 0x60, + 0x43, 0x15, 0x86, 0x01, 0x81, 0x0d, 0x4b, 0x58, 0x56, 0xe1, 0xc3, 0xe1, 0xbf, 0x63, 0x61, 0xb5, 0x30, 0xf3, 0xa6, + 0xd5, 0x22, 0xda, 0x07, 0xb9, 0x3a, 0x36, 0xa9, 0x41, 0x2f, 0x15, 0x7e, 0x8e, 0x4a, 0x38, 0x8c, 0xa7, 0x7f, 0xaa, + 0x3e, 0x78, 0x8b, 0x1e, 0xff, 0x43, 0x64, 0x06, 0xd9, 0xd0, 0x46, 0x18, 0x6b, 0x36, 0x80, 0xb0, 0x17, 0x65, 0x33, + 0x0b, 0x5d, 0xae, 0x5a, 0xed, 0xc8, 0x30, 0x6d, 0x5c, 0xdb, 0x75, 0xd5, 0xd1, 0xb4, 0x97, 0x4c, 0x47, 0x5e, 0xcb, + 0x6d, 0x1f, 0x9b, 0xe2, 0xcf, 0x76, 0xba, 0x46, 0x8e, 0x3d, 0x68, 0xe3, 0xe0, 0x6e, 0x3d, 0x89, 0xa3, 0xcc, 0x9a, + 0x78, 0xf3, 0x20, 0x7c, 0xe8, 0xcd, 0xe3, 0x28, 0x4e, 0x17, 0x9e, 0xcf, 0xfa, 0x05, 0x43, 0xdd, 0xc7, 0x10, 0x06, + 0xdc, 0x8b, 0xce, 0xb5, 0xdb, 0x09, 0x9b, 0x53, 0x6b, 0x19, 0xa1, 0x60, 0x12, 0xb2, 0x55, 0xce, 0x3f, 0x5f, 0xaa, + 0x4c, 0x55, 0x71, 0xcb, 0x51, 0x0b, 0xa0, 0x48, 0x79, 0xf8, 0x03, 0x08, 0xfa, 0xd3, 0x5f, 0x78, 0x63, 0x8c, 0xd8, + 0x67, 0xb7, 0xbb, 0x09, 0x9b, 0x6b, 0x76, 0x77, 0x63, 0xe7, 0x49, 0x7c, 0x7f, 0x06, 0xa3, 0xc5, 0xc6, 0x56, 0xca, + 0xc2, 0x09, 0xbe, 0xb1, 0xd0, 0xe3, 0x42, 0xf4, 0x63, 0x21, 0x23, 0x0e, 0xbd, 0xb1, 0x79, 0x1f, 0x5e, 0xf7, 0xda, + 0x9a, 0xd3, 0x9f, 0x07, 0x91, 0x45, 0xd3, 0x39, 0x76, 0x16, 0x4a, 0x5f, 0x2a, 0xfc, 0x8c, 0x35, 0x56, 0x77, 0x35, + 0xa7, 0x0f, 0xcc, 0xda, 0x24, 0x8c, 0xef, 0x7b, 0xb3, 0x60, 0x3c, 0x66, 0x51, 0x1f, 0xc7, 0x2c, 0x0b, 0x59, 0x18, + 0x06, 0x8b, 0x34, 0x48, 0xfb, 0x73, 0x6f, 0xc5, 0x7b, 0x3d, 0xdc, 0xd4, 0x6b, 0x87, 0xf7, 0xda, 0xd9, 0xbb, 0x57, + 0xa5, 0x1b, 0xf0, 0xee, 0xa0, 0x7e, 0xf8, 0xd0, 0xba, 0x9a, 0x53, 0x99, 0xe7, 0xde, 0xbd, 0x2e, 0x12, 0xb6, 0x9e, + 0x7b, 0xc9, 0x34, 0x88, 0x7a, 0x4e, 0x6e, 0xdf, 0xad, 0x69, 0x63, 0x3c, 0x3d, 0x39, 0x39, 0xc9, 0xed, 0xb1, 0x78, + 0x72, 0xc6, 0xe3, 0xdc, 0xf6, 0xc5, 0xd3, 0x64, 0xe2, 0x38, 0x93, 0x49, 0x6e, 0x07, 0xa2, 0xa0, 0xd3, 0xf6, 0xc7, + 0x9d, 0x76, 0x6e, 0xdf, 0x2b, 0x35, 0x72, 0x9b, 0xf1, 0xa7, 0x84, 0x8d, 0xfb, 0xb8, 0x91, 0xee, 0x69, 0xe9, 0x8f, + 0x1d, 0x27, 0x47, 0x0c, 0x70, 0x5d, 0xc2, 0x4d, 0x28, 0xeb, 0xb9, 0x59, 0xef, 0x5d, 0x53, 0x2b, 0x3e, 0xe7, 0xfb, + 0x8d, 0xf5, 0xc6, 0x5e, 0xf2, 0xe9, 0x46, 0x53, 0x66, 0xe1, 0x79, 0x54, 0x6d, 0x2d, 0xc0, 0x60, 0xad, 0x7a, 0x10, + 0xca, 0xaa, 0x3f, 0x8a, 0x13, 0x38, 0xb3, 0x89, 0x37, 0x0e, 0x96, 0x69, 0xcf, 0x6d, 0x2f, 0x56, 0xa2, 0x88, 0xef, + 0xf5, 0xa2, 0x00, 0xcf, 0x5e, 0x2f, 0x8d, 0xc3, 0x60, 0x2c, 0x8a, 0x36, 0x9d, 0x25, 0xb7, 0x6d, 0xf4, 0xd1, 0x91, + 0x3b, 0xc0, 0x70, 0x04, 0x5e, 0x18, 0x6a, 0x76, 0x27, 0xd5, 0x98, 0x97, 0xa2, 0x88, 0x57, 0x73, 0x52, 0x82, 0x0b, + 0x3a, 0x6d, 0xbb, 0x87, 0x8b, 0x95, 0xdc, 0xf3, 0xee, 0xd1, 0x62, 0x95, 0x7f, 0x3d, 0x67, 0xe3, 0xc0, 0xd3, 0x5a, + 0xc5, 0x6e, 0x72, 0x1d, 0x10, 0x03, 0x1b, 0xeb, 0x0d, 0xdb, 0x54, 0x1c, 0x0b, 0x08, 0xf9, 0xf7, 0x24, 0x98, 0x2f, + 0xe2, 0x24, 0xf3, 0xa2, 0x2c, 0xcf, 0x87, 0x37, 0x79, 0xde, 0xbf, 0x0a, 0x5a, 0xd7, 0xff, 0x6c, 0xd1, 0x3d, 0x4d, + 0x6a, 0x93, 0xdc, 0xb8, 0x31, 0xdf, 0x32, 0xd5, 0x48, 0x03, 0xae, 0x31, 0x34, 0xd0, 0x50, 0x2b, 0xd3, 0x2d, 0x59, + 0xaf, 0x4c, 0x40, 0x96, 0xd5, 0xc9, 0xe8, 0xa3, 0x5c, 0x05, 0x6f, 0x20, 0xa8, 0xf0, 0x96, 0x0d, 0xae, 0x14, 0x83, + 0x0f, 0x20, 0x56, 0xb0, 0x32, 0xd9, 0xdb, 0x3f, 0xdb, 0x44, 0x33, 0x7e, 0xb3, 0x9b, 0x66, 0xfc, 0x39, 0xdb, 0x87, + 0x66, 0xfc, 0xe6, 0x8b, 0xd3, 0x8c, 0xcf, 0xea, 0xf6, 0xf6, 0x17, 0xf1, 0x40, 0x97, 0x42, 0x7e, 0xb8, 0x9a, 0x12, + 0x8a, 0x64, 0x73, 0xf1, 0x87, 0xcd, 0xe3, 0x45, 0x6f, 0x94, 0x9b, 0x8d, 0x6e, 0x6e, 0x90, 0xc7, 0xbe, 0x8b, 0x06, + 0xff, 0x48, 0xd4, 0xe7, 0xc9, 0x64, 0xf0, 0x26, 0x56, 0x0a, 0xe4, 0x13, 0x37, 0x7f, 0x28, 0x45, 0x1d, 0xa0, 0x37, + 0xc2, 0xec, 0x11, 0xf3, 0x32, 0x80, 0xd3, 0x32, 0x99, 0xf9, 0x8e, 0xa5, 0xb9, 0x57, 0xbf, 0x3c, 0x84, 0x96, 0xb4, + 0xb1, 0x14, 0xae, 0x29, 0x35, 0x51, 0xe2, 0x94, 0x65, 0xdc, 0x97, 0xf4, 0xdb, 0x87, 0x8b, 0x71, 0xeb, 0x22, 0x36, + 0xf2, 0x20, 0x7d, 0x57, 0x75, 0x0c, 0xe1, 0xea, 0x97, 0x81, 0x3a, 0x9d, 0x9c, 0x9b, 0x6c, 0xa9, 0x89, 0x97, 0xe1, + 0x35, 0x35, 0x3f, 0x2f, 0xcd, 0xb4, 0xa7, 0x36, 0xe4, 0x09, 0xa0, 0x6a, 0x97, 0x31, 0xb7, 0xca, 0x5f, 0x73, 0x0a, + 0x10, 0x73, 0x5a, 0xa1, 0x3f, 0xed, 0x98, 0x9a, 0x07, 0xe3, 0x3c, 0x37, 0xfa, 0x02, 0x10, 0xca, 0x45, 0xcb, 0x76, + 0x11, 0x71, 0xe9, 0xbd, 0xb4, 0x2a, 0xe0, 0x4a, 0x3a, 0xd2, 0xc0, 0x5d, 0x80, 0x4a, 0x9b, 0xeb, 0xeb, 0x38, 0xcc, + 0x74, 0x8d, 0xc0, 0x47, 0xa6, 0x0e, 0xca, 0x84, 0x40, 0xe3, 0x2d, 0xe1, 0x2f, 0x5e, 0x89, 0x82, 0xba, 0xd1, 0x24, + 0x01, 0x07, 0x75, 0xf2, 0xe0, 0xfd, 0x2e, 0xe4, 0xda, 0x84, 0x76, 0x78, 0x1d, 0x7c, 0xc8, 0x75, 0x49, 0xfb, 0xe1, + 0xf6, 0x3b, 0x3b, 0x3d, 0x80, 0x06, 0x67, 0x15, 0xd5, 0xfd, 0x0e, 0x93, 0x40, 0x20, 0x25, 0xd2, 0x7b, 0xd3, 0x4e, + 0xef, 0xb5, 0x17, 0x6b, 0x11, 0x39, 0x22, 0xf3, 0x16, 0x16, 0xb0, 0xf8, 0x88, 0x7b, 0x39, 0xc6, 0x53, 0x82, 0x54, + 0xf4, 0x97, 0x29, 0xe0, 0x46, 0x64, 0x54, 0x11, 0xff, 0xf4, 0xfd, 0x65, 0x92, 0xc6, 0x49, 0x6f, 0x11, 0x07, 0x51, + 0xc6, 0x92, 0x1c, 0x41, 0x75, 0x8d, 0xf0, 0x11, 0xe0, 0xb9, 0x59, 0xc7, 0x0b, 0xcf, 0x0f, 0xb2, 0x87, 0x9e, 0xc3, + 0x49, 0x0a, 0xa7, 0xcf, 0xa9, 0x03, 0xa7, 0xb1, 0x7e, 0x8f, 0x43, 0xf3, 0x25, 0x12, 0x7e, 0x49, 0x9d, 0x9c, 0x51, + 0xb7, 0x79, 0x5f, 0x79, 0x4b, 0xb1, 0x33, 0x80, 0xfc, 0xf0, 0x12, 0x6b, 0x0a, 0x58, 0x1e, 0x96, 0xda, 0x19, 0xb3, + 0xa9, 0x89, 0x58, 0x1b, 0xe4, 0xf2, 0xe2, 0xcf, 0xee, 0x1a, 0x9a, 0xd3, 0x5c, 0x0c, 0x14, 0x8f, 0xb1, 0xcf, 0xc8, + 0x7a, 0x1e, 0x64, 0x9a, 0x32, 0xf7, 0xa9, 0x39, 0x62, 0x93, 0x38, 0x61, 0x14, 0x67, 0xd5, 0x3d, 0x59, 0xac, 0xf6, + 0xef, 0x7e, 0xfb, 0xf4, 0x9b, 0xfb, 0x89, 0xe2, 0xac, 0x25, 0x3a, 0x33, 0x76, 0xf4, 0x56, 0xbf, 0xcf, 0x80, 0x34, + 0x24, 0xc8, 0xfb, 0x14, 0xd2, 0xaa, 0xa7, 0xeb, 0xfd, 0xc6, 0x70, 0x56, 0x8b, 0x98, 0xdf, 0x79, 0x09, 0x0b, 0xbd, + 0x2c, 0xb8, 0x13, 0x34, 0x63, 0xe7, 0x68, 0xb1, 0x12, 0x6b, 0x8c, 0x17, 0xde, 0x23, 0x16, 0xa9, 0x32, 0x14, 0xb1, + 0x48, 0xd5, 0x62, 0x5c, 0xa4, 0x7e, 0x6d, 0x36, 0x22, 0xc2, 0x43, 0xe5, 0xa6, 0xef, 0x2e, 0x56, 0xea, 0x15, 0x5d, + 0x34, 0x93, 0x37, 0x75, 0x35, 0x34, 0xd7, 0x3c, 0x18, 0x8f, 0x43, 0x96, 0x97, 0x16, 0xba, 0xbc, 0x96, 0x0a, 0x70, + 0x24, 0x1c, 0xbc, 0x51, 0x1a, 0x87, 0xcb, 0x8c, 0x35, 0x83, 0x8b, 0x80, 0xd3, 0x76, 0x0a, 0xe0, 0xe0, 0xef, 0xf2, + 0x58, 0xbb, 0x40, 0x6e, 0xc3, 0x36, 0x71, 0xfa, 0x10, 0x89, 0xd7, 0xea, 0x94, 0x87, 0x0e, 0xaf, 0xe4, 0xa0, 0xcd, + 0x86, 0x89, 0x98, 0x70, 0x2d, 0x11, 0xf6, 0xd6, 0x6c, 0x97, 0x97, 0xc9, 0x68, 0xa4, 0xb2, 0x28, 0x2f, 0x4f, 0xe6, + 0xcf, 0x39, 0x63, 0xaf, 0x9a, 0xcf, 0xd8, 0x2b, 0x71, 0xc6, 0xb6, 0xef, 0xcc, 0xa7, 0x13, 0x17, 0xfe, 0xeb, 0x17, + 0x13, 0xea, 0x39, 0x5a, 0x67, 0xb1, 0xd2, 0xdc, 0xc5, 0x4a, 0xb3, 0xda, 0x8b, 0x95, 0x86, 0x5d, 0xa3, 0x49, 0x86, + 0x69, 0xb7, 0x0d, 0xd3, 0xd1, 0xa0, 0x10, 0xfe, 0x9c, 0xd2, 0x2b, 0xf7, 0x10, 0xde, 0x41, 0xab, 0x6e, 0xfd, 0x5d, + 0x7b, 0xfb, 0x51, 0xa7, 0xb3, 0x24, 0x90, 0xb6, 0x61, 0x67, 0xde, 0x68, 0xc4, 0xc6, 0xbd, 0x49, 0xec, 0x2f, 0xd3, + 0x7f, 0xf3, 0xf1, 0x73, 0x20, 0x6e, 0x45, 0x04, 0x95, 0x7e, 0x44, 0x53, 0x50, 0x94, 0xdc, 0x31, 0xd1, 0xc3, 0x5a, + 0xae, 0x53, 0x8f, 0xc2, 0x06, 0xb7, 0xed, 0xc3, 0x86, 0x4d, 0xde, 0x0c, 0xe8, 0x3f, 0x6d, 0x95, 0x36, 0xa3, 0x98, + 0xcf, 0x00, 0xcb, 0x56, 0x70, 0x3c, 0x1e, 0x1a, 0x7c, 0x35, 0x9d, 0x93, 0xe6, 0xe1, 0x5e, 0x8b, 0x2f, 0xdd, 0x88, + 0x4b, 0x85, 0xdf, 0x5b, 0xdc, 0x13, 0x64, 0x7b, 0xaf, 0x9b, 0xf6, 0x48, 0xad, 0xd7, 0x2d, 0x17, 0x42, 0x51, 0x77, + 0x4f, 0x2c, 0xff, 0xf4, 0xd5, 0x21, 0xfc, 0x47, 0x54, 0xfd, 0xcf, 0x59, 0x13, 0xa1, 0x7e, 0x51, 0x36, 0xbd, 0x26, + 0x52, 0x09, 0x09, 0xf1, 0xfd, 0xeb, 0x4f, 0x26, 0x8f, 0x6b, 0xb0, 0x77, 0x6d, 0xb2, 0x66, 0xaa, 0xd6, 0xfe, 0x36, + 0x8e, 0x21, 0xa5, 0x65, 0xbd, 0xba, 0x00, 0x0f, 0x59, 0x97, 0x67, 0x03, 0x68, 0x24, 0xf8, 0x08, 0xd2, 0xe2, 0xeb, + 0xd8, 0x86, 0x58, 0x89, 0xb7, 0x9b, 0x58, 0x89, 0x37, 0xbb, 0x59, 0x89, 0xef, 0xf7, 0x62, 0x25, 0xde, 0x7c, 0x71, + 0x56, 0xe2, 0x6d, 0x9d, 0x95, 0xb8, 0x8a, 0x85, 0x05, 0xab, 0x79, 0xb1, 0xe4, 0x3f, 0x3f, 0x92, 0x52, 0xee, 0x32, + 0x1e, 0x74, 0x1d, 0x0a, 0x05, 0x7c, 0xf5, 0x87, 0x19, 0x0b, 0xdc, 0x88, 0xef, 0xd1, 0xa2, 0xab, 0x60, 0x2d, 0x38, + 0x66, 0xc7, 0xef, 0x28, 0xc5, 0x61, 0x1c, 0x4d, 0x7f, 0x02, 0xa5, 0x2c, 0x88, 0x03, 0x13, 0xe5, 0x45, 0x90, 0xfe, + 0x14, 0x2f, 0x96, 0x8b, 0x0b, 0xe8, 0xeb, 0x63, 0x90, 0x06, 0xa3, 0x90, 0x49, 0x0f, 0x5d, 0xb2, 0x40, 0xe3, 0x32, + 0x71, 0xb0, 0xf9, 0x14, 0x3f, 0xbd, 0x95, 0xf8, 0x89, 0x56, 0xa1, 0xfc, 0x37, 0x99, 0xb6, 0xe9, 0xcd, 0x8c, 0x88, + 0x50, 0x02, 0x2a, 0x83, 0x7e, 0x3c, 0x33, 0x72, 0x15, 0x1b, 0x0d, 0xb3, 0x14, 0xf6, 0x0e, 0x1b, 0xfb, 0x61, 0x35, + 0xa6, 0x66, 0x69, 0x98, 0x32, 0x34, 0x55, 0x5d, 0x0c, 0x3f, 0x8f, 0x97, 0x29, 0x1b, 0xc7, 0xf7, 0x91, 0x6e, 0x46, + 0xd2, 0xaa, 0x1f, 0x34, 0x9c, 0xb2, 0x0d, 0x26, 0x55, 0xfc, 0x80, 0x84, 0x72, 0x9c, 0xb4, 0x74, 0xc8, 0xe9, 0xb9, + 0x5c, 0x58, 0xa4, 0x6a, 0xb6, 0x70, 0x8a, 0xba, 0xcc, 0xfe, 0xf3, 0xa4, 0xd5, 0x8a, 0x07, 0x8f, 0x6b, 0x29, 0x4c, + 0x35, 0x62, 0x9b, 0x4b, 0x85, 0xd3, 0x56, 0x24, 0x84, 0x8b, 0x22, 0x3e, 0x44, 0xc3, 0xc2, 0xf1, 0x37, 0xe4, 0x2b, + 0x5a, 0xbc, 0x85, 0xe8, 0x1a, 0xf9, 0x92, 0xaf, 0x07, 0x8f, 0x96, 0x40, 0x8f, 0xaf, 0x15, 0x30, 0xbe, 0xbb, 0x63, + 0x49, 0xe8, 0x3d, 0xb4, 0x8c, 0x3c, 0x8e, 0x7e, 0x00, 0x00, 0xbc, 0x89, 0xef, 0x23, 0xb5, 0x02, 0x26, 0x31, 0x69, + 0xd8, 0x4b, 0x8d, 0x71, 0x3d, 0xc0, 0x53, 0x44, 0x19, 0x01, 0xa4, 0x8f, 0x9d, 0xb2, 0x7f, 0x98, 0xf4, 0xef, 0x3f, + 0x8d, 0xdc, 0xbc, 0x8c, 0xe5, 0x87, 0xfe, 0xbe, 0xd8, 0xe3, 0x33, 0xcf, 0x9f, 0x3f, 0xd9, 0x3c, 0xed, 0x72, 0xda, + 0xf2, 0x86, 0xd6, 0xc6, 0xc6, 0x53, 0x00, 0xa3, 0xb8, 0x8a, 0x97, 0xfe, 0x0c, 0x6d, 0x4d, 0xbf, 0xdc, 0x7c, 0x33, + 0xe8, 0x13, 0xb3, 0x77, 0xca, 0xa9, 0x57, 0x8a, 0x0a, 0x28, 0xe0, 0xf7, 0xdf, 0x42, 0x60, 0xca, 0xff, 0x21, 0x18, + 0xea, 0xbb, 0x86, 0x73, 0xf1, 0xc1, 0xe3, 0x36, 0x6f, 0x1f, 0x92, 0x4c, 0xf2, 0x90, 0x0f, 0x42, 0xb9, 0xd6, 0x8c, + 0x64, 0xf2, 0x2a, 0xd0, 0xd4, 0xf0, 0x6a, 0x9b, 0x22, 0xc7, 0x89, 0xaf, 0x30, 0x9b, 0xd8, 0x74, 0x6e, 0xea, 0x6f, + 0x32, 0x8e, 0xad, 0x2a, 0x48, 0x86, 0x9b, 0x3c, 0x30, 0x44, 0x5f, 0xd5, 0x77, 0xf3, 0x20, 0x32, 0x31, 0x3a, 0x7a, + 0xfd, 0x8d, 0xb7, 0x82, 0xf8, 0xc0, 0x80, 0xdc, 0xaa, 0xaf, 0xa0, 0xd0, 0x54, 0x1d, 0xd5, 0x20, 0x05, 0x92, 0xde, + 0x08, 0x09, 0xa1, 0xc5, 0x1b, 0xfe, 0x45, 0xd3, 0x34, 0x4d, 0xb2, 0x11, 0x9a, 0xe4, 0x23, 0xb0, 0x1c, 0xd9, 0x01, + 0xd0, 0x96, 0xe4, 0x8b, 0x15, 0x95, 0x00, 0x67, 0x80, 0x3a, 0x59, 0x51, 0xc0, 0x43, 0xe0, 0x75, 0x1d, 0x51, 0x20, + 0x18, 0x7a, 0x08, 0x5f, 0xe6, 0x25, 0x10, 0x29, 0xb7, 0xa7, 0x21, 0xc3, 0x8e, 0x6f, 0xb9, 0x24, 0x58, 0x73, 0xe8, + 0x71, 0xd8, 0x67, 0xcd, 0xb1, 0xd2, 0x22, 0x05, 0x0b, 0x82, 0xd6, 0xa1, 0x12, 0xfa, 0xd8, 0x64, 0x0d, 0xb8, 0x11, + 0xf9, 0xa2, 0x55, 0x36, 0x67, 0xd1, 0x52, 0xc7, 0x5c, 0x49, 0x18, 0xbb, 0x0e, 0xea, 0xbc, 0x21, 0x62, 0x0b, 0xb0, + 0x4d, 0x73, 0xcb, 0x19, 0xdd, 0x85, 0x29, 0x47, 0xa9, 0x9e, 0xe9, 0x73, 0xc5, 0x66, 0xca, 0x71, 0x5b, 0xf5, 0x86, + 0xe0, 0x4b, 0x1a, 0x57, 0x3d, 0xa7, 0xc8, 0x18, 0x19, 0xfa, 0xa0, 0xa8, 0x11, 0x5c, 0x5c, 0x24, 0xc0, 0xde, 0xf2, + 0xaa, 0x8b, 0x26, 0x35, 0x32, 0x5e, 0x45, 0x50, 0x94, 0x18, 0xf5, 0x6e, 0xf8, 0x38, 0x21, 0x60, 0xcf, 0xc6, 0x7e, + 0xfc, 0x5a, 0x3f, 0x1b, 0x26, 0xfd, 0x89, 0x3d, 0xd0, 0x45, 0x42, 0xa0, 0xfa, 0xc4, 0x1e, 0xc0, 0xf6, 0xef, 0x2d, + 0x48, 0x53, 0xf4, 0x2d, 0xe8, 0xda, 0x84, 0x10, 0xf8, 0x3e, 0x04, 0x71, 0xda, 0x72, 0x80, 0x9c, 0x7c, 0x0b, 0x16, + 0x47, 0x10, 0x43, 0xb6, 0x63, 0x71, 0x88, 0xb9, 0x95, 0x7d, 0xab, 0x11, 0xc6, 0x56, 0xc3, 0xd1, 0x30, 0x5e, 0xb8, + 0x8e, 0x73, 0x50, 0xab, 0x0f, 0x82, 0xec, 0xa6, 0xda, 0x86, 0x99, 0x0d, 0x5c, 0xc7, 0x0a, 0x5e, 0xd8, 0xed, 0x7e, + 0xed, 0x8e, 0x56, 0x62, 0x2c, 0x0e, 0x51, 0xfc, 0x75, 0xf6, 0x6c, 0xdd, 0xaa, 0x1d, 0x48, 0xa3, 0x6a, 0xb5, 0x8e, + 0x63, 0xcb, 0xb9, 0xfc, 0x6b, 0x58, 0xbf, 0xfa, 0x29, 0xc2, 0x23, 0xe5, 0xfb, 0x18, 0x42, 0x94, 0xe0, 0x16, 0x1c, + 0xa3, 0xbf, 0x6a, 0x2f, 0xb5, 0x16, 0x1d, 0x1f, 0xc3, 0x18, 0xca, 0x34, 0xd2, 0xc2, 0xab, 0x4b, 0xed, 0xa0, 0xf2, + 0xc5, 0xb4, 0x8a, 0xe1, 0x78, 0x3c, 0x52, 0x56, 0x68, 0xf4, 0xb6, 0x52, 0x0b, 0xd8, 0xff, 0x86, 0xeb, 0xd3, 0x1e, + 0x41, 0x20, 0x00, 0xa8, 0x01, 0x31, 0xc5, 0x77, 0x76, 0xb8, 0x5c, 0x94, 0xbb, 0x2b, 0x5f, 0x92, 0xfb, 0x77, 0x86, + 0x97, 0x0e, 0xea, 0xd0, 0x64, 0x7f, 0xcd, 0xd7, 0xdd, 0x23, 0xbb, 0x64, 0xd1, 0xb8, 0xdc, 0x61, 0xe5, 0xfe, 0xda, + 0xbf, 0xbb, 0x12, 0x46, 0x81, 0x60, 0xfb, 0x71, 0x03, 0x46, 0xc9, 0xe3, 0x08, 0x37, 0x3f, 0x1d, 0xb7, 0x60, 0x2f, + 0x2a, 0x06, 0x1b, 0x50, 0xa4, 0x2c, 0xd9, 0x4c, 0x11, 0x8a, 0x43, 0x44, 0x67, 0xf4, 0xc3, 0x6d, 0x09, 0x42, 0x74, + 0xe3, 0x4e, 0xcc, 0x84, 0x4d, 0x61, 0xd1, 0x26, 0xe0, 0x31, 0x1a, 0xf7, 0x95, 0x5a, 0x07, 0xbb, 0xa5, 0xd6, 0xd9, + 0x2e, 0xa9, 0x35, 0x39, 0x34, 0xdd, 0x27, 0xde, 0x42, 0xf1, 0x89, 0x13, 0xc4, 0xb9, 0xea, 0x1a, 0x57, 0x12, 0x75, + 0xa3, 0xff, 0x93, 0x68, 0x55, 0xeb, 0x8d, 0xac, 0x04, 0x51, 0xfc, 0xad, 0x30, 0x28, 0x42, 0xa1, 0xae, 0xca, 0xc6, + 0xaf, 0x0a, 0xd9, 0x38, 0x71, 0x35, 0x85, 0x2f, 0x8b, 0xa0, 0xfe, 0x15, 0x37, 0x31, 0xc9, 0x1d, 0x14, 0xee, 0x62, + 0xc5, 0x48, 0x15, 0x07, 0xa8, 0x82, 0xd1, 0x50, 0xdc, 0xea, 0x04, 0x97, 0x51, 0xf6, 0xae, 0x2b, 0x57, 0x2d, 0xbc, + 0xcd, 0x8a, 0x72, 0x90, 0xba, 0xe3, 0x90, 0x65, 0xb1, 0xba, 0x6d, 0xca, 0x1e, 0x30, 0xea, 0x6b, 0x65, 0x93, 0x48, + 0x57, 0x15, 0x02, 0xb0, 0x10, 0xd3, 0x57, 0xf4, 0xda, 0xd2, 0x06, 0x02, 0x07, 0xd9, 0xe0, 0x58, 0xb7, 0x5b, 0x3a, + 0x4f, 0x79, 0x04, 0x0a, 0x2d, 0xbc, 0x2a, 0x83, 0x40, 0xf8, 0xde, 0xac, 0x1b, 0x6e, 0x79, 0xbc, 0xe4, 0xf9, 0xfd, + 0x0e, 0xe2, 0x45, 0xcd, 0x51, 0x15, 0xf9, 0x78, 0x32, 0x2d, 0x32, 0xcf, 0xc5, 0xaa, 0xf5, 0x4e, 0x49, 0x88, 0xb3, + 0xe6, 0xce, 0x29, 0x65, 0x19, 0x3d, 0xaf, 0xd1, 0x13, 0xdf, 0xe5, 0x5b, 0x27, 0x59, 0x46, 0x18, 0xf3, 0xdd, 0xca, + 0x12, 0xcf, 0xff, 0xa4, 0x0c, 0x59, 0xc8, 0x39, 0x41, 0x06, 0x5c, 0xd6, 0x14, 0xf4, 0x3d, 0x0c, 0x91, 0xc8, 0x7a, + 0x76, 0x3b, 0x55, 0xa4, 0x2f, 0xbd, 0xa7, 0x4e, 0xc7, 0x7b, 0x35, 0x39, 0xac, 0x08, 0x45, 0xdb, 0xdd, 0xb2, 0xc8, + 0x7c, 0xc3, 0x38, 0xb2, 0xd9, 0x72, 0x3e, 0x5a, 0xab, 0xb2, 0x55, 0x45, 0xe4, 0x5a, 0x17, 0xb3, 0xaa, 0x9f, 0x9d, + 0x4c, 0x26, 0x65, 0x41, 0xa3, 0xa3, 0x1d, 0xa2, 0xb0, 0xf0, 0xa9, 0xe3, 0x38, 0xd5, 0xb1, 0x6f, 0x07, 0xbb, 0x85, + 0x72, 0xdb, 0x93, 0xc6, 0x11, 0x23, 0x6c, 0x77, 0xc1, 0xaf, 0x0e, 0x8e, 0xdc, 0x2e, 0x4e, 0x76, 0xc9, 0x2c, 0xa2, + 0x4f, 0xc6, 0x10, 0x41, 0xc6, 0xe6, 0x69, 0xcf, 0x67, 0xa8, 0x83, 0xb1, 0x95, 0x03, 0x8d, 0x86, 0x03, 0xd6, 0x14, + 0x4c, 0x45, 0x5c, 0xb1, 0x2b, 0x1c, 0x0d, 0xe5, 0xe1, 0x35, 0xe1, 0xbd, 0xf8, 0x08, 0x1e, 0x94, 0x75, 0x5d, 0xa6, + 0x8d, 0xd3, 0xea, 0x3a, 0x7f, 0x2d, 0xd5, 0xd3, 0xe0, 0x02, 0x5c, 0x0b, 0x85, 0x36, 0xc9, 0x67, 0xf1, 0xff, 0xa5, + 0xfc, 0xff, 0xd5, 0x62, 0x55, 0xb6, 0x1f, 0x39, 0x01, 0x89, 0x76, 0x71, 0x5a, 0x68, 0xd4, 0x4d, 0x7b, 0x40, 0x5a, + 0x19, 0x4c, 0x54, 0x05, 0x3a, 0x28, 0xe9, 0x4b, 0x89, 0x31, 0x1a, 0xc4, 0xef, 0x48, 0x31, 0xc3, 0x12, 0x17, 0x22, + 0xc4, 0x22, 0xad, 0x1b, 0xcc, 0xc1, 0x7c, 0x79, 0x82, 0xfa, 0x83, 0xd2, 0x9e, 0x00, 0x6d, 0x7c, 0x6d, 0x6e, 0x7b, + 0x89, 0xfb, 0xab, 0x7a, 0x2d, 0xd1, 0x31, 0x80, 0xcc, 0x85, 0x43, 0x88, 0x86, 0x04, 0x5a, 0x65, 0x73, 0xd3, 0x28, + 0xe5, 0x5b, 0x55, 0xcf, 0x26, 0x06, 0x86, 0xdd, 0x35, 0x57, 0xa1, 0xbe, 0x85, 0xb6, 0x00, 0x26, 0xcb, 0xb7, 0x1f, + 0x3e, 0x5b, 0xb0, 0xc4, 0xea, 0x7e, 0x74, 0x71, 0xc9, 0x71, 0xff, 0x5a, 0x78, 0x77, 0xa6, 0x74, 0xfe, 0x51, 0xbe, + 0xf8, 0x7d, 0xa3, 0x40, 0xef, 0xaa, 0x24, 0xa1, 0xe3, 0xd6, 0xe2, 0x6d, 0x63, 0xaf, 0xda, 0xf3, 0x20, 0xda, 0xbf, + 0xae, 0xb7, 0xda, 0xbb, 0x2e, 0x5c, 0x18, 0x7b, 0x57, 0x86, 0x1b, 0x87, 0x2c, 0x17, 0xb2, 0xc1, 0xf7, 0x8a, 0x40, + 0x51, 0xf5, 0xfb, 0xd5, 0xb1, 0x15, 0x51, 0xf9, 0x57, 0x4b, 0x20, 0x3e, 0xf7, 0x4a, 0x7c, 0xa0, 0x89, 0xdc, 0x65, + 0xfa, 0xb1, 0x76, 0xa2, 0x1d, 0x77, 0xb4, 0x23, 0x47, 0x27, 0x2e, 0x6c, 0xa0, 0x77, 0xdb, 0x85, 0x43, 0xdf, 0xa1, + 0xa3, 0x9f, 0x9d, 0x4e, 0xc5, 0x25, 0x31, 0x09, 0xc2, 0x90, 0x50, 0x45, 0x9a, 0x25, 0xf1, 0x27, 0x56, 0x56, 0xb3, + 0x50, 0x19, 0x37, 0x02, 0x69, 0x8b, 0x47, 0x38, 0x3b, 0xbe, 0xb7, 0xe8, 0xe1, 0xd9, 0x50, 0x0b, 0xc1, 0x80, 0x93, + 0x4a, 0xf1, 0x13, 0x70, 0x07, 0x8f, 0xf4, 0xb3, 0x53, 0x08, 0xed, 0xa7, 0x8d, 0x07, 0xfa, 0x0f, 0xed, 0x63, 0xcd, + 0xed, 0xde, 0x59, 0x1d, 0xdf, 0xb1, 0x5c, 0xfb, 0x50, 0x73, 0xec, 0x23, 0xab, 0x6d, 0x1f, 0x6b, 0x6d, 0xbb, 0x0b, + 0xff, 0xfa, 0xae, 0xfd, 0x4a, 0x73, 0xe0, 0x49, 0x73, 0xed, 0x0e, 0xfe, 0xdb, 0xb6, 0x8f, 0xef, 0x3a, 0x74, 0xd3, + 0x7b, 0xd2, 0xad, 0xaa, 0x32, 0x0a, 0x70, 0x02, 0xd1, 0x0f, 0xce, 0x4e, 0x97, 0x29, 0xd3, 0x56, 0x03, 0xfd, 0x95, + 0xae, 0xcd, 0x12, 0x36, 0x19, 0xe8, 0x4f, 0x3d, 0xa5, 0xd4, 0x3d, 0x69, 0x2c, 0x6e, 0x1f, 0x37, 0x16, 0x77, 0x8e, + 0x1a, 0x8b, 0x0f, 0xbb, 0xe5, 0xe2, 0x83, 0x29, 0xbd, 0x52, 0x32, 0xeb, 0xcd, 0xbd, 0x2c, 0x09, 0x56, 0x2d, 0x57, + 0x03, 0x74, 0x6d, 0xc1, 0x3f, 0xc7, 0x6d, 0x43, 0xb6, 0x1a, 0x41, 0x2b, 0x09, 0x8d, 0xe3, 0x13, 0xcd, 0x3d, 0xfa, + 0x5b, 0xfb, 0xc8, 0x87, 0x7a, 0x90, 0x07, 0x12, 0xfe, 0xee, 0x3a, 0x27, 0xbe, 0xa3, 0x41, 0x43, 0x17, 0xfe, 0x9b, + 0x75, 0xdb, 0x3e, 0x3d, 0x38, 0xf0, 0xfe, 0xa3, 0x7b, 0x9c, 0x3a, 0x96, 0x0b, 0xff, 0xfd, 0x2a, 0x55, 0xee, 0xa0, + 0xf0, 0x57, 0xfb, 0x3d, 0x74, 0xb4, 0xce, 0xc9, 0xac, 0x6d, 0xbf, 0xba, 0x3b, 0xb6, 0x4f, 0x66, 0xee, 0xf1, 0x47, + 0x7a, 0x0a, 0xad, 0xb6, 0xfd, 0x0a, 0xfe, 0x3e, 0x76, 0x9c, 0x99, 0xe5, 0xda, 0x27, 0x77, 0x1d, 0xbb, 0x13, 0x5a, + 0x47, 0xf6, 0x09, 0xfc, 0xfd, 0x0a, 0xe0, 0x05, 0xb8, 0xf2, 0xc4, 0x9d, 0x1a, 0x6c, 0x8c, 0x8a, 0xfd, 0x86, 0xfa, + 0x91, 0xf6, 0xa1, 0xd6, 0x3d, 0xfc, 0xdb, 0xc9, 0x9d, 0x75, 0x38, 0x73, 0xdb, 0x77, 0xd6, 0xc6, 0x9f, 0x1f, 0x01, + 0xf2, 0xdb, 0x17, 0x0e, 0xc0, 0x88, 0x99, 0x3a, 0xfe, 0x32, 0x34, 0x2f, 0x37, 0x89, 0xd1, 0xdf, 0xef, 0x16, 0xa3, + 0x7f, 0xb7, 0xdc, 0x47, 0x8c, 0xfe, 0xfe, 0x8b, 0x8b, 0xd1, 0x2f, 0xab, 0x56, 0xdc, 0xef, 0xab, 0x11, 0xc5, 0x7f, + 0x5e, 0x57, 0x89, 0xe4, 0xc0, 0x6b, 0x5d, 0x5f, 0x2d, 0x6f, 0x20, 0xd8, 0xce, 0xfb, 0x78, 0xf0, 0xdd, 0xb2, 0x64, + 0xa2, 0x14, 0x03, 0x06, 0x78, 0x1f, 0x13, 0x06, 0xf8, 0x75, 0x39, 0x00, 0xbb, 0x08, 0x7e, 0x6b, 0x06, 0x63, 0x6b, + 0xe6, 0x85, 0x13, 0x79, 0xe3, 0x42, 0x49, 0x1f, 0x8b, 0xc1, 0x66, 0x1e, 0x2e, 0x13, 0x50, 0xd6, 0x2c, 0xe7, 0x51, + 0xda, 0x3b, 0x72, 0x00, 0xcd, 0xb7, 0x27, 0x49, 0x5e, 0x69, 0x6c, 0x8b, 0xf0, 0x44, 0xb7, 0xdc, 0xa6, 0x7f, 0xe3, + 0x7b, 0x34, 0x59, 0x6b, 0xee, 0xdd, 0xad, 0xf7, 0xab, 0x81, 0x2d, 0x88, 0x30, 0xe9, 0x03, 0x62, 0xa3, 0xe9, 0x7d, + 0xd9, 0x70, 0xac, 0x62, 0x2a, 0xb8, 0x79, 0xa4, 0x30, 0x92, 0x6a, 0x7b, 0xb7, 0x6c, 0x78, 0xb6, 0x6b, 0x9a, 0x0d, + 0x9f, 0x2f, 0x35, 0xdf, 0x62, 0xf5, 0x26, 0x3b, 0xae, 0x82, 0xaa, 0x92, 0x0f, 0xab, 0x11, 0x20, 0x05, 0xed, 0x59, + 0x98, 0xc6, 0x15, 0x84, 0x8f, 0xa3, 0xe1, 0x6d, 0xec, 0x28, 0xef, 0x4a, 0x7d, 0xaa, 0xe6, 0x74, 0x2f, 0xd6, 0x48, + 0x0f, 0x06, 0xbf, 0x02, 0x61, 0xc3, 0xef, 0xe3, 0x51, 0xac, 0xc2, 0x79, 0xad, 0xf4, 0x4b, 0xa4, 0x76, 0x3e, 0x73, + 0xd7, 0x75, 0xd2, 0x66, 0xa3, 0x21, 0xad, 0xcb, 0xe6, 0xe2, 0x8e, 0xc6, 0xcf, 0x93, 0xd9, 0x6a, 0x4e, 0xa6, 0xc5, + 0x68, 0x99, 0xbb, 0xad, 0x33, 0x51, 0xef, 0x29, 0x6c, 0x62, 0x93, 0x3f, 0xa8, 0x8e, 0xe3, 0xeb, 0x09, 0xe4, 0x2e, + 0xee, 0x21, 0x11, 0xa1, 0x50, 0x50, 0x6d, 0xb4, 0xb1, 0xed, 0x6f, 0x31, 0xff, 0x50, 0x3b, 0xe6, 0x9d, 0xa0, 0xad, + 0xee, 0x36, 0x8b, 0x11, 0xe9, 0xda, 0xb0, 0x2e, 0x29, 0x50, 0xdd, 0xee, 0xb1, 0xe9, 0x1e, 0x99, 0xf6, 0x71, 0xd7, + 0xc8, 0xc5, 0x81, 0x53, 0xbb, 0x2c, 0x01, 0x04, 0x4c, 0x76, 0xe5, 0x30, 0x83, 0x28, 0xc8, 0x02, 0x2f, 0xcc, 0x01, + 0xd5, 0x97, 0x69, 0xde, 0x7f, 0x2d, 0xd3, 0x0c, 0xe6, 0x28, 0x48, 0x32, 0x34, 0x57, 0xb6, 0x46, 0x2c, 0xbb, 0x67, + 0x2c, 0xda, 0xa0, 0xca, 0xad, 0x5a, 0x3f, 0xff, 0x79, 0xb6, 0xa0, 0x39, 0xd9, 0x59, 0x8c, 0xb2, 0x88, 0xef, 0x0f, + 0x61, 0xaa, 0x9b, 0x0f, 0xcd, 0x1f, 0x37, 0x21, 0xdc, 0x7f, 0xed, 0x46, 0xb8, 0x19, 0xdb, 0x07, 0xe1, 0xfe, 0xeb, + 0x8b, 0x23, 0xdc, 0x1f, 0x55, 0x84, 0x5b, 0xf2, 0x54, 0x29, 0x64, 0xa2, 0x1f, 0xf0, 0xb9, 0x05, 0xa1, 0x78, 0x5f, + 0xea, 0x07, 0x44, 0x5e, 0xea, 0x4a, 0x8a, 0xd4, 0x8f, 0xa5, 0x9c, 0x2f, 0xc8, 0xb2, 0x63, 0x4c, 0x52, 0xca, 0x2f, + 0x01, 0xe9, 0x43, 0x65, 0x22, 0x6c, 0xe8, 0xf3, 0x22, 0xca, 0x42, 0xfb, 0x3d, 0x67, 0x4b, 0x40, 0x05, 0xf1, 0x5d, + 0x9c, 0xcc, 0x3d, 0x8c, 0xc7, 0xa6, 0x63, 0xae, 0x38, 0x78, 0x70, 0xc0, 0x3b, 0xca, 0x8f, 0xa3, 0xb1, 0x94, 0xa3, + 0xb3, 0xc1, 0x35, 0xd1, 0x83, 0xfa, 0x03, 0xf3, 0x12, 0xdd, 0xa4, 0xd7, 0xb0, 0xb8, 0x2f, 0x3a, 0xce, 0x8b, 0xf6, + 0xe1, 0x8b, 0x23, 0x07, 0xfe, 0xe7, 0xb2, 0x4e, 0x6e, 0xf2, 0x8a, 0xf3, 0x38, 0x82, 0x74, 0x15, 0xa2, 0xe6, 0xa6, + 0x6a, 0xf7, 0x8c, 0x7d, 0x2a, 0x6a, 0x1d, 0x37, 0x57, 0x1a, 0x7b, 0x0f, 0x45, 0x9d, 0xc6, 0x1a, 0xb3, 0x78, 0xa9, + 0x0c, 0xab, 0x61, 0x34, 0x41, 0xb4, 0x04, 0xc9, 0x90, 0x52, 0x43, 0x7d, 0xcd, 0xa7, 0x5b, 0xcc, 0x8b, 0x75, 0xf2, + 0x9b, 0x22, 0x27, 0x8e, 0xc8, 0xcd, 0xb1, 0x13, 0x82, 0x5c, 0xa8, 0xee, 0x60, 0x44, 0x6d, 0xcc, 0x0a, 0xa3, 0x41, + 0x46, 0xba, 0x22, 0xf1, 0x39, 0x2e, 0x50, 0x96, 0x2c, 0x23, 0x9f, 0x72, 0x9b, 0x7b, 0xa3, 0xb4, 0x15, 0x1c, 0x40, + 0xb0, 0x4e, 0xfc, 0xb0, 0x81, 0xab, 0xe6, 0x9d, 0x39, 0x45, 0x02, 0x81, 0x54, 0xac, 0x8a, 0xf7, 0x22, 0x33, 0x13, + 0x4a, 0x3b, 0x8a, 0x4b, 0x6b, 0x0d, 0xbc, 0x17, 0xb2, 0xe1, 0x8b, 0xcc, 0x84, 0xd4, 0x9f, 0xb0, 0xdc, 0xcf, 0x9f, + 0x53, 0x2d, 0x48, 0xc6, 0x47, 0xd3, 0x3a, 0xf7, 0x65, 0x02, 0x2f, 0x5d, 0xf3, 0xa6, 0xb1, 0x8e, 0x09, 0xbc, 0x7a, + 0xbe, 0x19, 0xbf, 0x7c, 0x79, 0x36, 0x70, 0x0d, 0x9e, 0x4a, 0xb2, 0x94, 0xf7, 0xe8, 0x72, 0x3f, 0xd5, 0xb8, 0xd1, + 0xe8, 0xb4, 0xb5, 0x08, 0xa2, 0xa9, 0xd0, 0x4c, 0x4b, 0xec, 0x05, 0x79, 0x08, 0x48, 0x05, 0xe6, 0x09, 0x15, 0xb5, + 0xa8, 0x73, 0xc7, 0x12, 0x48, 0x83, 0x39, 0xd0, 0x3b, 0xb6, 0x63, 0x3b, 0xba, 0x6c, 0x38, 0x09, 0xa6, 0x83, 0x75, + 0x9c, 0x79, 0x90, 0xd1, 0x25, 0x8c, 0xa7, 0xe0, 0xf9, 0x91, 0x05, 0x59, 0x08, 0xe9, 0x41, 0xc0, 0x05, 0x64, 0x4e, + 0x5c, 0x63, 0xce, 0xed, 0x71, 0xbd, 0xe4, 0x13, 0xa6, 0x88, 0x13, 0x4e, 0x5f, 0x18, 0x92, 0xe6, 0x07, 0xb8, 0x0c, + 0x5b, 0x7a, 0x0b, 0x12, 0x14, 0xb2, 0x24, 0xb5, 0x54, 0xfb, 0xf6, 0x9e, 0x06, 0x6d, 0x20, 0x79, 0x38, 0x76, 0x30, + 0x49, 0xbc, 0x39, 0x44, 0xd2, 0x5e, 0xe7, 0x26, 0xc7, 0xb4, 0x3a, 0x47, 0xb5, 0x9a, 0xfb, 0xea, 0xc8, 0xd4, 0xda, + 0xae, 0xa9, 0x39, 0x80, 0x6e, 0xf5, 0xdc, 0x5c, 0xe7, 0x37, 0xfd, 0x5d, 0x2a, 0x3a, 0xc2, 0x2f, 0x4f, 0x69, 0x1e, + 0xa4, 0x9c, 0xe3, 0xc2, 0xcf, 0x8c, 0xe2, 0x09, 0xb6, 0x94, 0x18, 0xd7, 0x01, 0x89, 0xe9, 0xaf, 0xd8, 0x2a, 0x33, + 0x30, 0x7d, 0x06, 0xaf, 0x12, 0x18, 0x6b, 0x74, 0x4d, 0x0b, 0x22, 0x2d, 0xf8, 0xed, 0xb7, 0x56, 0x00, 0xe6, 0xf7, + 0x03, 0x05, 0x3e, 0xf0, 0x6c, 0x94, 0x00, 0x16, 0x14, 0x8a, 0x25, 0x04, 0x16, 0xf8, 0xc6, 0xc0, 0xbf, 0x45, 0xb1, + 0xf8, 0xc1, 0x15, 0x7b, 0x76, 0xe8, 0x45, 0x53, 0x40, 0x69, 0x5e, 0x34, 0xad, 0x19, 0x10, 0x90, 0x77, 0x5d, 0xa5, + 0xb4, 0xe8, 0xaa, 0x50, 0xee, 0xa7, 0xdf, 0x3e, 0x5c, 0x51, 0x7a, 0x20, 0x48, 0x45, 0xed, 0x8d, 0xd1, 0x15, 0xac, + 0xd0, 0x3d, 0xbc, 0x1c, 0x7c, 0x75, 0x3a, 0x67, 0x99, 0x47, 0x82, 0x4b, 0x60, 0xf1, 0x80, 0x1c, 0xd0, 0x7c, 0x91, + 0xda, 0x93, 0x18, 0xbc, 0x31, 0xbb, 0x0b, 0x7c, 0xce, 0xa7, 0x99, 0x1a, 0xbf, 0xa7, 0x2c, 0xb4, 0x51, 0x1a, 0xb8, + 0x26, 0x99, 0xc8, 0xfa, 0x1e, 0x46, 0x1d, 0x1c, 0x44, 0xb1, 0x7e, 0xf6, 0x95, 0xf4, 0x26, 0xda, 0xb4, 0x08, 0x90, + 0xa3, 0xef, 0x3a, 0x61, 0xe1, 0xbf, 0x07, 0x5f, 0xc1, 0xc5, 0xfd, 0xd5, 0x8d, 0x6e, 0xf4, 0x33, 0x1b, 0xf9, 0x98, + 0xaf, 0x1a, 0x72, 0xd5, 0x21, 0x8f, 0xca, 0x99, 0xcd, 0x8e, 0xc2, 0x6c, 0xc2, 0xef, 0xdd, 0xac, 0xeb, 0xd9, 0x29, + 0x5e, 0x68, 0x67, 0xc0, 0x5d, 0xac, 0x4b, 0x3c, 0xa7, 0xdb, 0x47, 0x06, 0x75, 0x14, 0x7a, 0xfe, 0x27, 0xc1, 0xa1, + 0xaa, 0x0f, 0xfb, 0xf0, 0xa2, 0x92, 0xb2, 0x6b, 0xdc, 0xcb, 0xb8, 0x95, 0xd7, 0xf8, 0x65, 0xfc, 0xd4, 0xfd, 0x2c, + 0xc8, 0x24, 0x33, 0x8c, 0x0f, 0x39, 0x68, 0x73, 0x70, 0x7c, 0x05, 0xfb, 0x03, 0x0c, 0xaa, 0x7b, 0xf2, 0xb7, 0xee, + 0x9d, 0xeb, 0xcc, 0xda, 0xae, 0x0d, 0x6c, 0xce, 0xac, 0x63, 0x1f, 0x87, 0x56, 0xc7, 0x3e, 0x86, 0xbf, 0x8f, 0xc0, + 0x7a, 0x59, 0x6d, 0xfb, 0xf0, 0xa3, 0xdb, 0x0e, 0xad, 0x13, 0xfb, 0x18, 0xfe, 0x2e, 0xa9, 0xd5, 0xcf, 0xc8, 0xf4, + 0x00, 0xc3, 0xf3, 0x55, 0x09, 0x0b, 0x28, 0xbf, 0xa5, 0x16, 0xc1, 0x2c, 0x5d, 0x6f, 0x0d, 0x9a, 0x08, 0x40, 0x19, + 0xba, 0x29, 0x82, 0x04, 0x46, 0xfd, 0x16, 0x24, 0xcf, 0xc6, 0xb0, 0xef, 0xc2, 0x20, 0x23, 0x2a, 0x12, 0xc1, 0x6f, + 0x3e, 0x46, 0xbc, 0x4d, 0x73, 0xfc, 0x6d, 0x91, 0x4f, 0x88, 0x54, 0x17, 0x7f, 0x5f, 0x60, 0x60, 0x1d, 0x11, 0x31, + 0x5c, 0xc1, 0x4a, 0x45, 0x4e, 0xbb, 0x7c, 0xf7, 0xc0, 0xd1, 0x6f, 0x94, 0xc9, 0x9c, 0x2a, 0x5f, 0xb4, 0x6f, 0xae, + 0xce, 0x90, 0xbd, 0xff, 0xd1, 0x7e, 0x30, 0x95, 0x28, 0xf5, 0x23, 0x82, 0x7b, 0x8e, 0x83, 0x44, 0x0e, 0x4f, 0x41, + 0xd1, 0x6e, 0x73, 0xe0, 0x72, 0x03, 0x92, 0x4f, 0x5c, 0x00, 0x95, 0x7c, 0xe7, 0x85, 0x8a, 0xe9, 0x85, 0xd2, 0xf2, + 0x89, 0xc4, 0xfc, 0xcf, 0x9f, 0x17, 0x83, 0xb3, 0x2a, 0xe3, 0x3e, 0x75, 0xbb, 0x70, 0xed, 0x76, 0x59, 0x67, 0xab, + 0x15, 0xd0, 0xee, 0xe8, 0xb0, 0x45, 0x38, 0x49, 0xa1, 0xe9, 0x17, 0x3a, 0xc6, 0x8d, 0xa6, 0x48, 0x35, 0x0d, 0x23, + 0xc4, 0xd5, 0xad, 0xb0, 0x3a, 0xba, 0xd1, 0x8f, 0x84, 0xc2, 0x2c, 0xda, 0x12, 0x11, 0x97, 0xf3, 0x62, 0x3a, 0x80, + 0x66, 0xcb, 0x3c, 0x76, 0xb8, 0x34, 0xfe, 0xaf, 0x27, 0x81, 0xee, 0x45, 0xa0, 0xe1, 0xab, 0x9c, 0xd6, 0x92, 0xbb, + 0x89, 0xbc, 0x57, 0xe9, 0x42, 0x65, 0xe9, 0xb9, 0x0e, 0x45, 0x90, 0x95, 0x08, 0x13, 0x91, 0x49, 0xf3, 0x26, 0x79, + 0x5b, 0x14, 0x05, 0x66, 0x00, 0x21, 0xa1, 0x5b, 0xc2, 0xd5, 0xc9, 0x78, 0xfe, 0x7c, 0xe3, 0x25, 0x44, 0xea, 0x64, + 0x35, 0x1f, 0xa3, 0xae, 0xe2, 0x37, 0x5d, 0x45, 0x31, 0xb2, 0x5f, 0xc4, 0x1a, 0xc2, 0x2a, 0x8b, 0xf6, 0x1e, 0xfe, + 0x1c, 0x31, 0x2f, 0xb3, 0xb9, 0x1e, 0xa4, 0xa5, 0x5c, 0xee, 0xa6, 0xcb, 0x3a, 0x60, 0x8f, 0xc5, 0xe3, 0x6f, 0xf1, + 0x60, 0x73, 0xcf, 0xd6, 0x1f, 0x97, 0xdc, 0x0f, 0x19, 0xfa, 0xf8, 0xcd, 0x29, 0x82, 0xa7, 0xbc, 0xcb, 0x3c, 0x8a, + 0xb0, 0xa1, 0x5e, 0xb9, 0x71, 0xe6, 0x89, 0xec, 0x1f, 0x40, 0x97, 0xf7, 0x1b, 0x15, 0x86, 0x8a, 0xaf, 0xf2, 0xd9, + 0xbb, 0xab, 0x6f, 0x34, 0xbe, 0xff, 0x49, 0xbf, 0x85, 0x8c, 0x0c, 0x05, 0xc1, 0x1f, 0x50, 0x10, 0x7c, 0x8d, 0x27, + 0x7f, 0x80, 0x50, 0xf2, 0xf9, 0x01, 0x41, 0x50, 0xd7, 0x58, 0xe4, 0x93, 0xd6, 0x6f, 0xbe, 0x0c, 0xb3, 0x60, 0xe1, + 0x25, 0xd9, 0x01, 0x34, 0xb5, 0x00, 0xc9, 0xe9, 0x9b, 0x3c, 0x98, 0x49, 0x71, 0x28, 0x84, 0x6a, 0x59, 0x24, 0x34, + 0x87, 0x93, 0x20, 0x94, 0x8a, 0x43, 0xf1, 0x01, 0xcf, 0xf7, 0xd9, 0x22, 0x1b, 0xe8, 0xde, 0x02, 0x92, 0x21, 0x60, + 0x78, 0xe3, 0x83, 0xd8, 0xcf, 0x58, 0x66, 0xa5, 0x59, 0xc2, 0xbc, 0xb9, 0x2e, 0x43, 0x7d, 0xd6, 0xfb, 0x4b, 0x97, + 0xa3, 0x79, 0x90, 0xc9, 0x60, 0x79, 0x34, 0x41, 0x50, 0xe1, 0xc1, 0x10, 0xcf, 0x86, 0x39, 0x07, 0xe1, 0x65, 0x3c, + 0xad, 0xec, 0xa8, 0x82, 0x72, 0x39, 0xc7, 0x48, 0xac, 0x3c, 0x00, 0xfe, 0x18, 0x3d, 0x72, 0x6e, 0xb9, 0xd7, 0xb5, + 0x8c, 0xe9, 0xa7, 0x9f, 0x9d, 0x72, 0xf6, 0x56, 0xc3, 0x40, 0x01, 0x7a, 0xd7, 0x81, 0x58, 0xb3, 0x9b, 0xfc, 0xb1, + 0x0f, 0x78, 0x65, 0xb8, 0x9a, 0xa8, 0x67, 0x0c, 0xfb, 0x4d, 0x63, 0xb9, 0x02, 0x42, 0xa8, 0xa4, 0xe2, 0x9d, 0xb9, + 0x67, 0xd2, 0x01, 0x08, 0x47, 0x85, 0xb4, 0xd2, 0x6f, 0xbf, 0xbd, 0x1e, 0xfe, 0xe7, 0x77, 0x88, 0x4d, 0x3e, 0x73, + 0x85, 0x17, 0xf4, 0xb5, 0x5a, 0x8b, 0x53, 0x9f, 0xe6, 0x10, 0xd5, 0xfb, 0x6c, 0x2c, 0xc2, 0x82, 0x88, 0xad, 0x95, + 0x0f, 0x6f, 0x44, 0xa8, 0x27, 0xc8, 0x3f, 0x60, 0x08, 0x5f, 0xed, 0x21, 0x2c, 0xef, 0x50, 0x84, 0x08, 0xd0, 0x7e, + 0x59, 0x7d, 0x7b, 0x0c, 0xb9, 0x74, 0x6b, 0x69, 0x01, 0x94, 0x01, 0xe2, 0x1e, 0x3a, 0x3b, 0xf5, 0xb8, 0xf0, 0x15, + 0xc8, 0x8f, 0xb4, 0x77, 0x00, 0xd3, 0x9c, 0xc5, 0x73, 0x66, 0x07, 0xf1, 0xc1, 0x3d, 0x1b, 0x59, 0xde, 0x22, 0x20, + 0xf9, 0x32, 0xca, 0xdd, 0x34, 0xa2, 0xfc, 0xa4, 0x82, 0x96, 0xe8, 0xeb, 0xbc, 0x00, 0x65, 0x5c, 0x00, 0x0a, 0x7e, + 0x7a, 0x67, 0xe5, 0x00, 0x7e, 0xb6, 0x08, 0x18, 0x5f, 0xc6, 0xf2, 0xe7, 0x14, 0x87, 0x4f, 0x84, 0xdc, 0x2b, 0x1e, + 0xac, 0x78, 0x32, 0x51, 0x83, 0xee, 0xd9, 0xe5, 0xef, 0x4b, 0xa8, 0x14, 0x7b, 0x36, 0x5e, 0xd0, 0x97, 0xea, 0x9f, + 0x90, 0x3f, 0x21, 0xa7, 0x2d, 0x8f, 0xcf, 0x08, 0xe7, 0xb9, 0x16, 0xbc, 0x4f, 0x82, 0xe4, 0x29, 0x55, 0xe2, 0x88, + 0xa2, 0x1a, 0x18, 0x7a, 0x03, 0x69, 0xf2, 0x64, 0x30, 0x20, 0x3c, 0x56, 0x45, 0x67, 0x00, 0xa5, 0x86, 0xe0, 0xf9, + 0x30, 0xd9, 0x0c, 0x1a, 0x5a, 0xe4, 0xc1, 0x85, 0x8d, 0xaa, 0xd3, 0xa9, 0x8f, 0xf1, 0xc0, 0x13, 0xfb, 0xab, 0xb4, + 0x03, 0x61, 0x67, 0xf1, 0x85, 0x05, 0x04, 0x2e, 0xfa, 0xa9, 0xe0, 0x71, 0xed, 0x6b, 0x42, 0xd9, 0x56, 0xe8, 0x3d, + 0xc4, 0x8a, 0x66, 0x9d, 0x3b, 0xd9, 0x5f, 0x62, 0xe9, 0x95, 0x70, 0x6e, 0xab, 0x9d, 0x24, 0x19, 0x80, 0xbc, 0x7e, + 0x9a, 0xd4, 0x88, 0xe1, 0xbb, 0x0e, 0x93, 0x5a, 0xb7, 0x3c, 0x19, 0xc4, 0x8e, 0x79, 0x71, 0xd0, 0x4a, 0x2f, 0xf1, + 0xdc, 0xe7, 0xa7, 0x07, 0x30, 0x3f, 0x08, 0x0c, 0x50, 0xa2, 0x8c, 0x02, 0x03, 0xa2, 0x0f, 0x78, 0x29, 0x59, 0x07, + 0x5c, 0x8c, 0x05, 0x51, 0x87, 0x9c, 0xa3, 0x8c, 0x0e, 0x5a, 0xaa, 0x52, 0x27, 0x56, 0x9c, 0x66, 0x2a, 0x6f, 0x77, + 0xc0, 0xfe, 0x5f, 0x97, 0x18, 0xad, 0x3f, 0xef, 0x67, 0x4c, 0xf8, 0xdd, 0x5e, 0x66, 0x1b, 0x5c, 0x73, 0x37, 0x55, + 0x21, 0x82, 0x75, 0x4b, 0x85, 0x62, 0x1f, 0x6f, 0xab, 0x55, 0x90, 0x46, 0xb2, 0xda, 0xc2, 0x6b, 0xe9, 0x4f, 0x71, + 0xc7, 0xd7, 0x6a, 0x63, 0x29, 0xd4, 0xbb, 0xcc, 0x06, 0x50, 0x55, 0x08, 0xdb, 0xbd, 0xc5, 0x82, 0x2a, 0x1b, 0xfd, + 0xd3, 0x03, 0xe2, 0x3b, 0xcf, 0x68, 0x87, 0x9d, 0x9d, 0x82, 0x75, 0x21, 0x2d, 0xba, 0xb7, 0x58, 0xf0, 0x25, 0xa5, + 0x5f, 0xf4, 0xe6, 0x60, 0x96, 0xcd, 0xc3, 0xb3, 0xff, 0x03, 0x30, 0x11, 0x13, 0xf1, 0xb7, 0x59, 0x03, 0x00}; } // namespace web_server } // namespace esphome + #endif #endif From 05fbb260eea1d0f873e095aa10efdcdd8eb1e0dd Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Tue, 30 Apr 2024 00:09:35 +0200 Subject: [PATCH 1353/2101] [nextion] Exit reparse before update TFT (#6589) --- esphome/components/nextion/nextion.h | 6 +++++- esphome/components/nextion/nextion_upload_arduino.cpp | 11 ++++++++++- esphome/components/nextion/nextion_upload_idf.cpp | 11 ++++++++++- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/esphome/components/nextion/nextion.h b/esphome/components/nextion/nextion.h index a8f0ea8ba9..833db675fc 100644 --- a/esphome/components/nextion/nextion.h +++ b/esphome/components/nextion/nextion.h @@ -993,9 +993,13 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe /** * Upload the tft file and soft reset Nextion + * @param exit_reparse If true, the function exits reparse mode before uploading the TFT file. This parameter + * defaults to true, ensuring that the display is ready to receive and apply the new TFT file without needing + * to manually reset or reconfigure. Exiting reparse mode is recommended for most upload scenarios to ensure + * the display properly processes the uploaded file command. * @return bool True: Transfer completed successfuly, False: Transfer failed. */ - bool upload_tft(); + bool upload_tft(bool exit_reparse = true); void dump_config() override; diff --git a/esphome/components/nextion/nextion_upload_arduino.cpp b/esphome/components/nextion/nextion_upload_arduino.cpp index e3d0903d09..4f8df67006 100644 --- a/esphome/components/nextion/nextion_upload_arduino.cpp +++ b/esphome/components/nextion/nextion_upload_arduino.cpp @@ -141,8 +141,9 @@ int Nextion::upload_by_chunks_(HTTPClient *http, int range_start) { return range_end + 1; } -bool Nextion::upload_tft() { +bool Nextion::upload_tft(bool exit_reparse) { ESP_LOGD(TAG, "Nextion TFT upload requested"); + ESP_LOGD(TAG, "Exit reparse: %s", YESNO(exit_reparse)); ESP_LOGD(TAG, "URL: %s", this->tft_url_.c_str()); if (this->is_updating_) { @@ -157,6 +158,14 @@ bool Nextion::upload_tft() { this->is_updating_ = true; + if (exit_reparse) { + ESP_LOGD(TAG, "Exiting Nextion reparse mode"); + if (!this->set_protocol_reparse_mode(false)) { + ESP_LOGW(TAG, "Failed to request Nextion to exit reparse mode"); + return false; + } + } + HTTPClient http; http.setTimeout(15000); // Yes 15 seconds.... Helps 8266s along bool begin_status = false; diff --git a/esphome/components/nextion/nextion_upload_idf.cpp b/esphome/components/nextion/nextion_upload_idf.cpp index 14b1b6cfaf..d08f970551 100644 --- a/esphome/components/nextion/nextion_upload_idf.cpp +++ b/esphome/components/nextion/nextion_upload_idf.cpp @@ -160,8 +160,9 @@ int Nextion::upload_range(const std::string &url, int range_start) { return range_end + 1; } -bool Nextion::upload_tft() { +bool Nextion::upload_tft(bool exit_reparse) { ESP_LOGD(TAG, "Nextion TFT upload requested"); + ESP_LOGD(TAG, "Exit reparse: %s", YESNO(exit_reparse)); ESP_LOGD(TAG, "url: %s", this->tft_url_.c_str()); if (this->is_updating_) { @@ -176,6 +177,14 @@ bool Nextion::upload_tft() { this->is_updating_ = true; + if (exit_reparse) { + ESP_LOGD(TAG, "Exiting Nextion reparse mode"); + if (!this->set_protocol_reparse_mode(false)) { + ESP_LOGW(TAG, "Failed to request Nextion to exit reparse mode"); + return false; + } + } + // Define the configuration for the HTTP client ESP_LOGV(TAG, "Establishing connection to HTTP server"); ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); From 33e9881830fa13b53c8a4314c91c9817747cdab1 Mon Sep 17 00:00:00 2001 From: mrtoy-me <118446898+mrtoy-me@users.noreply.github.com> Date: Tue, 23 Apr 2024 09:16:55 +1000 Subject: [PATCH 1354/2101] Fix SHT3xd fails sometimes in 2024.4.0 (#6592) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/sht3xd/sht3xd.cpp | 34 +++++++++++++++++++++++----- esphome/components/sht3xd/sht3xd.h | 7 ++++++ 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/esphome/components/sht3xd/sht3xd.cpp b/esphome/components/sht3xd/sht3xd.cpp index 888e954c6b..ffaf5db322 100644 --- a/esphome/components/sht3xd/sht3xd.cpp +++ b/esphome/components/sht3xd/sht3xd.cpp @@ -6,9 +6,14 @@ namespace sht3xd { static const char *const TAG = "sht3xd"; -// use read serial number register with clock stretching disabled as per other SHT3XD_COMMAND registers -// which provides support for SHT85 sensor -// SHT85 does not support clock stretching and uses same registers as SHT3xd with clock stretching disabled +// https://sensirion.com/media/documents/E5762713/63D103C2/Sensirion_electronic_identification_code_SHT3x.pdf +// indicates two possible read serial number registers either with clock stretching enabled or disabled. +// Other SHT3XD_COMMAND registers use the clock stretching disabled register. +// 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. + +static const uint16_t SHT3XD_COMMAND_READ_SERIAL_NUMBER_CLOCK_STRETCHING = 0x3780; static const uint16_t SHT3XD_COMMAND_READ_SERIAL_NUMBER = 0x3682; static const uint16_t SHT3XD_COMMAND_READ_STATUS = 0xF32D; @@ -22,13 +27,19 @@ static const uint16_t SHT3XD_COMMAND_FETCH_DATA = 0xE000; void SHT3XDComponent::setup() { ESP_LOGCONFIG(TAG, "Setting up SHT3xD..."); uint16_t raw_serial_number[2]; - if (!this->get_register(SHT3XD_COMMAND_READ_SERIAL_NUMBER, raw_serial_number, 2)) { - this->mark_failed(); - return; + 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; + } } + 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(); return; } @@ -36,10 +47,21 @@ void SHT3XDComponent::setup() { 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, " Setup successful"); ESP_LOGD(TAG, " Serial Number: 0x%08" PRIX32, this->serial_number_); ESP_LOGD(TAG, " Heater Enabled: %s", this->heater_enabled_ ? "true" : "false"); diff --git a/esphome/components/sht3xd/sht3xd.h b/esphome/components/sht3xd/sht3xd.h index d1a3360e69..74f155121b 100644 --- a/esphome/components/sht3xd/sht3xd.h +++ b/esphome/components/sht3xd/sht3xd.h @@ -22,6 +22,13 @@ 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 5838af646b5523ab51721f09306a5242a475115d Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Mon, 22 Apr 2024 23:43:11 -0700 Subject: [PATCH 1355/2101] allow defaults with no include vars (#6613) --- esphome/yaml_util.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/esphome/yaml_util.py b/esphome/yaml_util.py index c7aa78201f..06bfd8b217 100644 --- a/esphome/yaml_util.py +++ b/esphome/yaml_util.py @@ -321,8 +321,9 @@ class ESPHomeLoaderMixin: file, vars = node.value, None result = _load_yaml_internal(self._rel_path(file)) - if vars: - result = substitute_vars(result, vars) + if not vars: + vars = {} + result = substitute_vars(result, vars) return result @_add_data_ref From 9832fa4d76f75acb679360c2215eba0921e871e6 Mon Sep 17 00:00:00 2001 From: tronikos Date: Sat, 27 Apr 2024 18:22:41 -0700 Subject: [PATCH 1356/2101] Revert #6458 (#6650) Reading the z-axis register is required. --- esphome/components/qmc5883l/qmc5883l.cpp | 46 ++++++++---------------- 1 file changed, 15 insertions(+), 31 deletions(-) diff --git a/esphome/components/qmc5883l/qmc5883l.cpp b/esphome/components/qmc5883l/qmc5883l.cpp index 4946ad1b77..8541b41ff7 100644 --- a/esphome/components/qmc5883l/qmc5883l.cpp +++ b/esphome/components/qmc5883l/qmc5883l.cpp @@ -77,8 +77,17 @@ void QMC5883LComponent::dump_config() { float QMC5883LComponent::get_setup_priority() const { return setup_priority::DATA; } void QMC5883LComponent::update() { uint8_t status = false; - if (ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_DEBUG) - this->read_byte(QMC5883L_REGISTER_STATUS, &status); + this->read_byte(QMC5883L_REGISTER_STATUS, &status); + + // Always request X,Y,Z regardless if there are sensors for them + // to avoid https://github.com/esphome/issues/issues/5731 + uint16_t raw_x, raw_y, raw_z; + if (!this->read_byte_16_(QMC5883L_REGISTER_DATA_X_LSB, &raw_x) || + !this->read_byte_16_(QMC5883L_REGISTER_DATA_Y_LSB, &raw_y) || + !this->read_byte_16_(QMC5883L_REGISTER_DATA_Z_LSB, &raw_z)) { + this->status_set_warning(); + return; + } float mg_per_bit; switch (this->range_) { @@ -93,36 +102,11 @@ void QMC5883LComponent::update() { } // in µT - float x = NAN, y = NAN, z = NAN; - if (this->x_sensor_ != nullptr || this->heading_sensor_ != nullptr) { - uint16_t raw_x; - if (!this->read_byte_16_(QMC5883L_REGISTER_DATA_X_LSB, &raw_x)) { - this->status_set_warning(); - return; - } - x = int16_t(raw_x) * mg_per_bit * 0.1f; - } - if (this->y_sensor_ != nullptr || this->heading_sensor_ != nullptr) { - uint16_t raw_y; - if (!this->read_byte_16_(QMC5883L_REGISTER_DATA_Y_LSB, &raw_y)) { - this->status_set_warning(); - return; - } - y = int16_t(raw_y) * mg_per_bit * 0.1f; - } - if (this->z_sensor_ != nullptr) { - uint16_t raw_z; - if (!this->read_byte_16_(QMC5883L_REGISTER_DATA_Z_LSB, &raw_z)) { - this->status_set_warning(); - return; - } - z = int16_t(raw_z) * mg_per_bit * 0.1f; - } + const float x = int16_t(raw_x) * mg_per_bit * 0.1f; + const float y = int16_t(raw_y) * mg_per_bit * 0.1f; + const float z = int16_t(raw_z) * mg_per_bit * 0.1f; - float heading = NAN; - if (this->heading_sensor_ != nullptr) { - heading = atan2f(0.0f - x, y) * 180.0f / M_PI; - } + float heading = atan2f(0.0f - x, y) * 180.0f / M_PI; float temp = NAN; if (this->temperature_sensor_ != nullptr) { From 4936cbec0d8428ebab0f939c83863d4810848d20 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 29 Apr 2024 12:10:12 +1200 Subject: [PATCH 1357/2101] [i2s_audio.microphone] Fixing adc bug (#6654) --- .../microphone/i2s_audio_microphone.cpp | 65 +++++++++++++++++-- 1 file changed, 58 insertions(+), 7 deletions(-) diff --git a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp index 602d537bcb..1475df0975 100644 --- a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +++ b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp @@ -61,28 +61,57 @@ void I2SAudioMicrophone::start_() { .bits_per_chan = I2S_BITS_PER_CHAN_DEFAULT, }; + esp_err_t err; + #if SOC_I2S_SUPPORTS_ADC if (this->adc_) { config.mode = (i2s_mode_t) (config.mode | I2S_MODE_ADC_BUILT_IN); - i2s_driver_install(this->parent_->get_port(), &config, 0, nullptr); + err = i2s_driver_install(this->parent_->get_port(), &config, 0, nullptr); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Error installing I2S driver: %s", esp_err_to_name(err)); + this->status_set_error(); + return; + } + + err = i2s_set_adc_mode(ADC_UNIT_1, this->adc_channel_); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Error setting ADC mode: %s", esp_err_to_name(err)); + this->status_set_error(); + return; + } + err = i2s_adc_enable(this->parent_->get_port()); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Error enabling ADC: %s", esp_err_to_name(err)); + this->status_set_error(); + return; + } - i2s_set_adc_mode(ADC_UNIT_1, this->adc_channel_); - i2s_adc_enable(this->parent_->get_port()); } else #endif { if (this->pdm_) config.mode = (i2s_mode_t) (config.mode | I2S_MODE_PDM); - i2s_driver_install(this->parent_->get_port(), &config, 0, nullptr); + err = i2s_driver_install(this->parent_->get_port(), &config, 0, nullptr); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Error installing I2S driver: %s", esp_err_to_name(err)); + this->status_set_error(); + return; + } i2s_pin_config_t pin_config = this->parent_->get_pin_config(); pin_config.data_in_num = this->din_pin_; - i2s_set_pin(this->parent_->get_port(), &pin_config); + err = i2s_set_pin(this->parent_->get_port(), &pin_config); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Error setting I2S pin: %s", esp_err_to_name(err)); + this->status_set_error(); + return; + } } this->state_ = microphone::STATE_RUNNING; this->high_freq_.start(); + this->status_clear_error(); } void I2SAudioMicrophone::stop() { @@ -96,11 +125,33 @@ void I2SAudioMicrophone::stop() { } void I2SAudioMicrophone::stop_() { - i2s_stop(this->parent_->get_port()); - i2s_driver_uninstall(this->parent_->get_port()); + esp_err_t err; +#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)); + this->status_set_error(); + return; + } + } +#endif + err = i2s_stop(this->parent_->get_port()); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Error stopping I2S microphone: %s", esp_err_to_name(err)); + this->status_set_error(); + return; + } + err = i2s_driver_uninstall(this->parent_->get_port()); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Error uninstalling I2S driver: %s", esp_err_to_name(err)); + this->status_set_error(); + return; + } this->parent_->unlock(); this->state_ = microphone::STATE_STOPPED; this->high_freq_.stop(); + this->status_clear_error(); } size_t I2SAudioMicrophone::read(int16_t *buf, size_t len) { From 516971a255407aac9878ad4e790621126858d5fd Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 30 Apr 2024 15:47:40 +1200 Subject: [PATCH 1358/2101] Bump version to 2024.4.2 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 69949dc086..f11345527e 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.4.1" +__version__ = "2024.4.2" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 74fd52e05fdc6f63ef64ada77f8a7b8d63de8c45 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Tue, 30 Apr 2024 11:29:57 +0200 Subject: [PATCH 1359/2101] [nextion] Set alternative TFT update baud rate (#6587) --- esphome/components/nextion/nextion.h | 16 +++++++++-- .../nextion/nextion_upload_arduino.cpp | 27 +++++++++++++++++-- .../components/nextion/nextion_upload_idf.cpp | 27 +++++++++++++++++-- 3 files changed, 64 insertions(+), 6 deletions(-) diff --git a/esphome/components/nextion/nextion.h b/esphome/components/nextion/nextion.h index 833db675fc..b6a6204cd4 100644 --- a/esphome/components/nextion/nextion.h +++ b/esphome/components/nextion/nextion.h @@ -992,14 +992,26 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe #endif /** - * Upload the tft file and soft reset Nextion + * @brief Uploads the TFT file to the Nextion display. + * + * This function initiates the upload of a TFT file to the Nextion display. Users can specify a target baud rate for + * the transfer. If the provided baud rate is not supported by Nextion, the function defaults to using the current + * baud rate set for the display. If no baud rate is specified (or if 0 is passed), the current baud rate is used. + * + * Supported baud rates are: 2400, 4800, 9600, 19200, 31250, 38400, 57600, 115200, 230400, 250000, 256000, 512000 + * and 921600. Selecting a baud rate supported by both the Nextion display and the host hardware is essential for + * ensuring a successful upload process. + * + * @param baud_rate The desired baud rate for the TFT file transfer, specified as an unsigned 32-bit integer. + * If the specified baud rate is not supported, or if 0 is passed, the function will use the current baud rate. + * The default value is 0, which implies using the current baud rate. * @param exit_reparse If true, the function exits reparse mode before uploading the TFT file. This parameter * defaults to true, ensuring that the display is ready to receive and apply the new TFT file without needing * to manually reset or reconfigure. Exiting reparse mode is recommended for most upload scenarios to ensure * the display properly processes the uploaded file command. * @return bool True: Transfer completed successfuly, False: Transfer failed. */ - bool upload_tft(bool exit_reparse = true); + bool upload_tft(uint32_t baud_rate = 0, bool exit_reparse = true); void dump_config() override; diff --git a/esphome/components/nextion/nextion_upload_arduino.cpp b/esphome/components/nextion/nextion_upload_arduino.cpp index 4f8df67006..6e7c8b9563 100644 --- a/esphome/components/nextion/nextion_upload_arduino.cpp +++ b/esphome/components/nextion/nextion_upload_arduino.cpp @@ -141,7 +141,7 @@ int Nextion::upload_by_chunks_(HTTPClient *http, int range_start) { return range_end + 1; } -bool Nextion::upload_tft(bool exit_reparse) { +bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { ESP_LOGD(TAG, "Nextion TFT upload requested"); ESP_LOGD(TAG, "Exit reparse: %s", YESNO(exit_reparse)); ESP_LOGD(TAG, "URL: %s", this->tft_url_.c_str()); @@ -166,6 +166,15 @@ bool Nextion::upload_tft(bool exit_reparse) { } } + // Check if baud rate is supported + this->original_baud_rate_ = this->parent_->get_baud_rate(); + static const std::vector SUPPORTED_BAUD_RATES = {2400, 4800, 9600, 19200, 31250, 38400, 57600, + 115200, 230400, 250000, 256000, 512000, 921600}; + if (std::find(SUPPORTED_BAUD_RATES.begin(), SUPPORTED_BAUD_RATES.end(), baud_rate) == SUPPORTED_BAUD_RATES.end()) { + baud_rate = this->original_baud_rate_; + } + ESP_LOGD(TAG, "Baud rate: %" PRIu32, baud_rate); + HTTPClient http; http.setTimeout(15000); // Yes 15 seconds.... Helps 8266s along bool begin_status = false; @@ -244,7 +253,7 @@ bool Nextion::upload_tft(bool exit_reparse) { // Tells the Nextion the content length of the tft file and baud rate it will be sent at // Once the Nextion accepts the command it will wait until the file is successfully uploaded // If it fails for any reason a power cycle of the display will be needed - sprintf(command, "whmi-wris %d,%d,1", this->content_length_, this->parent_->get_baud_rate()); + sprintf(command, "whmi-wris %d,%d,1", this->content_length_, baud_rate); // Clear serial receive buffer uint8_t d; @@ -254,6 +263,12 @@ bool Nextion::upload_tft(bool exit_reparse) { this->send_command_(command); + if (baud_rate != this->original_baud_rate_) { + ESP_LOGD(TAG, "Changing baud rate from %" PRIu32 " to %" PRIu32 " bps", this->original_baud_rate_, baud_rate); + this->parent_->set_baud_rate(baud_rate); + this->parent_->load_settings(); + } + App.feed_wdt(); std::string response; @@ -335,6 +350,14 @@ bool Nextion::upload_tft(bool exit_reparse) { bool Nextion::upload_end_(bool successful) { this->is_updating_ = false; + + uint32_t baud_rate = this->parent_->get_baud_rate(); + if (baud_rate != this->original_baud_rate_) { + ESP_LOGD(TAG, "Changing baud rate back from %" PRIu32 " to %" PRIu32 " bps", baud_rate, this->original_baud_rate_); + this->parent_->set_baud_rate(this->original_baud_rate_); + this->parent_->load_settings(); + } + ESP_LOGD(TAG, "Restarting Nextion"); this->soft_reset(); if (successful) { diff --git a/esphome/components/nextion/nextion_upload_idf.cpp b/esphome/components/nextion/nextion_upload_idf.cpp index d08f970551..163b497d3b 100644 --- a/esphome/components/nextion/nextion_upload_idf.cpp +++ b/esphome/components/nextion/nextion_upload_idf.cpp @@ -160,7 +160,7 @@ int Nextion::upload_range(const std::string &url, int range_start) { return range_end + 1; } -bool Nextion::upload_tft(bool exit_reparse) { +bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { ESP_LOGD(TAG, "Nextion TFT upload requested"); ESP_LOGD(TAG, "Exit reparse: %s", YESNO(exit_reparse)); ESP_LOGD(TAG, "url: %s", this->tft_url_.c_str()); @@ -185,6 +185,15 @@ bool Nextion::upload_tft(bool exit_reparse) { } } + // Check if baud rate is supported + this->original_baud_rate_ = this->parent_->get_baud_rate(); + static const std::vector SUPPORTED_BAUD_RATES = {2400, 4800, 9600, 19200, 31250, 38400, 57600, + 115200, 230400, 250000, 256000, 512000, 921600}; + if (std::find(SUPPORTED_BAUD_RATES.begin(), SUPPORTED_BAUD_RATES.end(), baud_rate) == SUPPORTED_BAUD_RATES.end()) { + baud_rate = this->original_baud_rate_; + } + ESP_LOGD(TAG, "Baud rate: %" PRIu32, baud_rate); + // Define the configuration for the HTTP client ESP_LOGV(TAG, "Establishing connection to HTTP server"); ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); @@ -254,7 +263,7 @@ bool Nextion::upload_tft(bool exit_reparse) { // Tells the Nextion the content length of the tft file and baud rate it will be sent at // Once the Nextion accepts the command it will wait until the file is successfully uploaded // If it fails for any reason a power cycle of the display will be needed - sprintf(command, "whmi-wris %d,%" PRIu32 ",1", this->content_length_, this->parent_->get_baud_rate()); + sprintf(command, "whmi-wris %d,%" PRIu32 ",1", this->content_length_, baud_rate); // Clear serial receive buffer ESP_LOGV(TAG, "Clear serial receive buffer"); @@ -268,6 +277,12 @@ bool Nextion::upload_tft(bool exit_reparse) { ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); this->send_command_(command); + if (baud_rate != this->original_baud_rate_) { + ESP_LOGD(TAG, "Changing baud rate from %" PRIu32 " to %" PRIu32 " bps", this->original_baud_rate_, baud_rate); + this->parent_->set_baud_rate(baud_rate); + this->parent_->load_settings(); + } + std::string response; ESP_LOGV(TAG, "Waiting for upgrade response"); this->recv_ret_string_(response, 5000, true); // This can take some time to return @@ -308,6 +323,14 @@ bool Nextion::upload_tft(bool exit_reparse) { bool Nextion::upload_end(bool successful) { this->is_updating_ = false; + + uint32_t baud_rate = this->parent_->get_baud_rate(); + if (baud_rate != this->original_baud_rate_) { + ESP_LOGD(TAG, "Changing baud rate back from %" PRIu32 " to %" PRIu32 " bps", baud_rate, this->original_baud_rate_); + this->parent_->set_baud_rate(this->original_baud_rate_); + this->parent_->load_settings(); + } + ESP_LOGD(TAG, "Restarting Nextion"); this->soft_reset(); vTaskDelay(pdMS_TO_TICKS(1500)); // NOLINT From 6fe328ef2bb9d50efe612d2176df8f562b8bd1a5 Mon Sep 17 00:00:00 2001 From: Anton Sergunov Date: Tue, 30 Apr 2024 16:35:41 +0600 Subject: [PATCH 1360/2101] [TM1637] Let turn off the display (#6656) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/tm1637/tm1637.cpp | 2 +- esphome/components/tm1637/tm1637.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/esphome/components/tm1637/tm1637.cpp b/esphome/components/tm1637/tm1637.cpp index 8d7630bd1d..2f2d4b707a 100644 --- a/esphome/components/tm1637/tm1637.cpp +++ b/esphome/components/tm1637/tm1637.cpp @@ -225,7 +225,7 @@ void TM1637Display::display() { // Write display CTRL CMND + brightness this->start_(); - this->send_byte_(TM1637_CMD_CTRL + ((this->intensity_ & 0x7) | 0x08)); + this->send_byte_(TM1637_CMD_CTRL + ((this->intensity_ & 0x7) | (this->on_ ? 0x08 : 0x00))); this->stop_(); } bool TM1637Display::send_byte_(uint8_t b) { diff --git a/esphome/components/tm1637/tm1637.h b/esphome/components/tm1637/tm1637.h index aba0071b12..d44680c623 100644 --- a/esphome/components/tm1637/tm1637.h +++ b/esphome/components/tm1637/tm1637.h @@ -49,6 +49,7 @@ class TM1637Display : public PollingComponent { 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; } + void set_on(bool on) { this->on_ = on; } void display(); @@ -76,6 +77,7 @@ class TM1637Display : public PollingComponent { uint8_t intensity_; uint8_t length_; bool inverted_; + bool on_{true}; optional writer_{}; uint8_t buffer_[6] = {0}; #ifdef USE_BINARY_SENSOR From c299dff124937f4a2253956f72bac77f6c4c79ee Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Tue, 30 Apr 2024 23:43:49 +0200 Subject: [PATCH 1361/2101] [nextion] Use persistent http connection for TFT upload (Arduino) (#6582) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/nextion/nextion.h | 40 +- .../nextion/nextion_upload_arduino.cpp | 397 +++++++++--------- 2 files changed, 213 insertions(+), 224 deletions(-) diff --git a/esphome/components/nextion/nextion.h b/esphome/components/nextion/nextion.h index b6a6204cd4..7938af0ea5 100644 --- a/esphome/components/nextion/nextion.h +++ b/esphome/components/nextion/nextion.h @@ -976,6 +976,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * @return Whether the send was successful. */ bool send_command(const char *command); + /** * Manually send a raw formatted command to the display. * @param format The printf-style command format, like "vis %s,0" @@ -989,7 +990,6 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * Set the tft file URL. https seems problematic with arduino.. */ void set_tft_url(const std::string &tft_url) { this->tft_url_ = tft_url; } -#endif /** * @brief Uploads the TFT file to the Nextion display. @@ -1013,6 +1013,8 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe */ bool upload_tft(uint32_t baud_rate = 0, bool exit_reparse = true); +#endif + void dump_config() override; /** @@ -1134,6 +1136,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe void all_components_send_state_(bool force_update = false); uint64_t comok_sent_ = 0; bool remove_from_q_(bool report_empty = true); + /** * @brief * Sends commands ignoring of the Nextion has been setup. @@ -1175,20 +1178,16 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe void check_pending_waveform_(); #ifdef USE_NEXTION_TFT_UPLOAD - uint32_t content_length_ = 0; - int tft_size_ = 0; - uint32_t original_baud_rate_ = 0; - bool upload_first_chunk_sent_ = false; - - std::string tft_url_; - uint8_t *transfer_buffer_{nullptr}; - size_t transfer_buffer_size_; - #ifdef USE_ESP8266 WiFiClient *wifi_client_{nullptr}; BearSSL::WiFiClientSecure *wifi_client_secure_{nullptr}; WiFiClient *get_wifi_client_(); #endif + std::string tft_url_; + uint32_t content_length_ = 0; + int tft_size_ = 0; + uint32_t original_baud_rate_ = 0; + bool upload_first_chunk_sent_ = false; #ifdef ARDUINO /** @@ -1198,18 +1197,8 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * @param int range_start Position of next byte to transfer. * @return position of last byte transferred, -1 for failure. */ - int upload_by_chunks_(HTTPClient *http, int range_start); + int upload_by_chunks_(HTTPClient &http_client, uint32_t &range_start); - bool upload_with_range_(uint32_t range_start, uint32_t range_end); - - /** - * start update tft file to nextion. - * - * @param const uint8_t *file_buf - * @param size_t buf_size - * @return true if success, false for failure. - */ - bool upload_from_buffer_(const uint8_t *file_buf, size_t buf_size); /** * Ends the upload process, restart Nextion and, if successful, * restarts ESP @@ -1217,6 +1206,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * @return bool True: Transfer completed successfuly, False: Transfer failed. */ bool upload_end_(bool successful); + #elif defined(USE_ESP_IDF) /** * will request 4096 bytes chunks from the web server @@ -1226,6 +1216,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * @return position of last byte transferred, -1 for failure. */ int upload_range(const std::string &url, int range_start); + /** * Ends the upload process, restart Nextion and, if successful, * restarts ESP @@ -1233,7 +1224,12 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * @return bool True: Transfer completed successfuly, False: Transfer failed. */ bool upload_end(bool successful); -#endif // ARDUINO vs ESP-IDF +#endif // ARDUINO vs USE_ESP_IDF + /** + * Returns the ESP Free Heap memory. This is framework independent. + * @return Free Heap in bytes. + */ + uint32_t get_free_heap_(); #endif // USE_NEXTION_TFT_UPLOAD diff --git a/esphome/components/nextion/nextion_upload_arduino.cpp b/esphome/components/nextion/nextion_upload_arduino.cpp index 6e7c8b9563..b199db91b7 100644 --- a/esphome/components/nextion/nextion_upload_arduino.cpp +++ b/esphome/components/nextion/nextion_upload_arduino.cpp @@ -1,13 +1,14 @@ #include "nextion.h" -#ifdef ARDUINO #ifdef USE_NEXTION_TFT_UPLOAD +#ifdef ARDUINO #include "esphome/core/application.h" #include "esphome/core/defines.h" #include "esphome/core/util.h" #include "esphome/core/log.h" #include "esphome/components/network/util.h" +#include #ifdef USE_ESP32 #include @@ -20,124 +21,132 @@ static const char *const TAG = "nextion.upload.arduino"; // Followed guide // https://unofficialnextion.com/t/nextion-upload-protocol-v1-2-the-fast-one/1044/2 -int Nextion::upload_by_chunks_(HTTPClient *http, int range_start) { - int range_end = 0; +inline uint32_t Nextion::get_free_heap_() { +#if defined(USE_ESP32) + return heap_caps_get_free_size(MALLOC_CAP_INTERNAL); +#elif defined(USE_ESP8266) + return EspClass::getFreeHeap(); +#endif // USE_ESP32 vs USE_ESP8266 +} - if (range_start == 0 && this->transfer_buffer_size_ > 16384) { // Start small at the first run in case of a big skip - range_end = 16384 - 1; - } else { - range_end = range_start + this->transfer_buffer_size_ - 1; +int Nextion::upload_by_chunks_(HTTPClient &http_client, uint32_t &range_start) { + uint32_t range_size = this->tft_size_ - range_start; + ESP_LOGV(TAG, "Free heap: %" PRIu32, this->get_free_heap_()); + 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, range_end); + ESP_LOGD(TAG, "Range size: %" PRIu32, range_size); + ESP_LOGE(TAG, "Invalid range"); + return -1; } - if (range_end > this->tft_size_) - range_end = this->tft_size_; - -#ifdef USE_ESP8266 -#if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 7, 0) - http->setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); -#elif USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 6, 0) - http->setFollowRedirects(true); -#endif -#if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 6, 0) - http->setRedirectLimit(3); -#endif -#endif // USE_ESP8266 - - char range_header[64]; - sprintf(range_header, "bytes=%d-%d", range_start, range_end); - - ESP_LOGD(TAG, "Requesting range: %s", range_header); - - int tries = 1; - int code = 0; - bool begin_status = false; - while (tries <= 5) { -#ifdef USE_ESP32 - begin_status = http->begin(this->tft_url_.c_str()); -#endif -#ifdef USE_ESP8266 - begin_status = http->begin(*this->get_wifi_client_(), this->tft_url_.c_str()); -#endif - - ++tries; - if (!begin_status) { - ESP_LOGD(TAG, "upload_by_chunks_: connection failed"); - delay(500); // NOLINT - continue; - } - - http->addHeader("Range", range_header); - - code = http->GET(); - if (code == 200 || code == 206) { - break; - } - ESP_LOGW(TAG, "HTTP Request failed; URL: %s; Error: %s, retries(%d/5)", this->tft_url_.c_str(), - HTTPClient::errorToString(code).c_str(), tries); - http->end(); - App.feed_wdt(); - delay(500); // NOLINT + char range_header[32]; + sprintf(range_header, "bytes=%" PRIu32 "-%" PRIu32, range_start, range_end); + ESP_LOGV(TAG, "Requesting 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) { + ESP_LOGW(TAG, "HTTP Request failed; Error: %s", HTTPClient::errorToString(code).c_str()); + return -1; } - if (tries > 5) { + // Allocate the buffer dynamically + ExternalRAMAllocator allocator(ExternalRAMAllocator::ALLOW_FAILURE); + uint8_t *buffer = allocator.allocate(4096); + if (!buffer) { + ESP_LOGE(TAG, "Failed to allocate upload buffer"); return -1; } std::string recv_string; - size_t size = 0; - int fetched = 0; - int range = range_end - range_start; - - while (fetched < range) { - size = http->getStreamPtr()->available(); - if (!size) { - App.feed_wdt(); - delay(0); - continue; - } - int c = http->getStreamPtr()->readBytes( - &this->transfer_buffer_[fetched], ((size > this->transfer_buffer_size_) ? this->transfer_buffer_size_ : size)); - fetched += c; - } - http->end(); - ESP_LOGN(TAG, "Fetched %d of %d bytes", fetched, this->content_length_); - - // upload fetched segments to the display in 4KB chunks - int write_len; - for (int i = 0; i < range; i += 4096) { + while (true) { App.feed_wdt(); - write_len = this->content_length_ < 4096 ? this->content_length_ : 4096; - this->write_array(&this->transfer_buffer_[i], write_len); - this->content_length_ -= write_len; - ESP_LOGD(TAG, "Uploaded %0.2f %%; %d bytes remaining", - 100.0 * (this->tft_size_ - this->content_length_) / this->tft_size_, this->content_length_); - - if (!this->upload_first_chunk_sent_) { - this->upload_first_chunk_sent_ = true; - delay(500); // NOLINT - } - - this->recv_ret_string_(recv_string, 4096, true); - if (recv_string[0] != 0x05) { // 0x05 == "ok" - ESP_LOGD(TAG, "recv_string [%s]", - format_hex_pretty(reinterpret_cast(recv_string.data()), recv_string.size()).c_str()); - } - - // handle partial upload request - if (recv_string[0] == 0x08 && recv_string.size() == 5) { - uint32_t result = 0; - for (int j = 0; j < 4; ++j) { - result += static_cast(recv_string[j + 1]) << (8 * j); - } - if (result > 0) { - ESP_LOGD(TAG, "Nextion reported new range %d", result); - this->content_length_ = this->tft_size_ - result; - return result; + const uint16_t buffer_size = + this->content_length_ < 4096 ? this->content_length_ : 4096; // Limits buffer to the remaining data + ESP_LOGV(TAG, "Fetching %" PRIu16 " bytes from HTTP", buffer_size); + uint16_t read_len = 0; + int partial_read_len = 0; + const uint32_t start_time = millis(); + while (read_len < buffer_size && millis() - start_time < 5000) { + if (http_client.getStreamPtr()->available() > 0) { + partial_read_len = + http_client.getStreamPtr()->readBytes(reinterpret_cast(buffer) + read_len, buffer_size - read_len); + read_len += partial_read_len; + if (partial_read_len > 0) { + App.feed_wdt(); + delay(2); + } } } - recv_string.clear(); + if (read_len != buffer_size) { + // Did not receive the full package within the timeout period + ESP_LOGE(TAG, "Failed to read full package, received only %" PRIu16 " of %" PRIu16 " bytes", read_len, + buffer_size); + // Deallocate buffer + allocator.deallocate(buffer, 4096); + buffer = nullptr; + return -1; + } + ESP_LOGV(TAG, "%d bytes fetched, writing it to UART", read_len); + if (read_len > 0) { + 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->content_length_ -= read_len; + const float upload_percentage = 100.0f * (this->tft_size_ - this->content_length_) / this->tft_size_; +#if defined(USE_ESP32) && defined(USE_PSRAM) + ESP_LOGD( + TAG, + "Uploaded %0.2f%%, remaining %" PRIu32 " bytes, free heap: %" PRIu32 " (DRAM) + %" PRIu32 " (PSRAM) bytes", + upload_percentage, this->content_length_, static_cast(heap_caps_get_free_size(MALLOC_CAP_INTERNAL)), + static_cast(heap_caps_get_free_size(MALLOC_CAP_SPIRAM))); +#else + ESP_LOGD(TAG, "Uploaded %0.2f%%, remaining %" PRIu32 " bytes, free heap: %" PRIu32 " bytes", upload_percentage, + this->content_length_, this->get_free_heap_()); +#endif + upload_first_chunk_sent_ = true; + if (recv_string[0] == 0x08 && recv_string.size() == 5) { // handle partial upload request + ESP_LOGD(TAG, "recv_string [%s]", + format_hex_pretty(reinterpret_cast(recv_string.data()), recv_string.size()).c_str()); + uint32_t result = 0; + for (int j = 0; j < 4; ++j) { + result += static_cast(recv_string[j + 1]) << (8 * j); + } + if (result > 0) { + ESP_LOGI(TAG, "Nextion reported new range %" PRIu32, result); + this->content_length_ = this->tft_size_ - result; + range_start = result; + } else { + range_start = range_end + 1; + } + // Deallocate buffer + allocator.deallocate(buffer, 4096); + buffer = nullptr; + return range_end + 1; + } else if (recv_string[0] != 0x05 and recv_string[0] != 0x08) { // 0x05 == "ok" + ESP_LOGE(TAG, "Invalid response from Nextion: [%s]", + format_hex_pretty(reinterpret_cast(recv_string.data()), recv_string.size()).c_str()); + // Deallocate buffer + allocator.deallocate(buffer, 4096); + buffer = nullptr; + return -1; + } + + recv_string.clear(); + } else if (read_len == 0) { + ESP_LOGV(TAG, "End of HTTP response reached"); + break; // Exit the loop if there is no more data to read + } else { + ESP_LOGE(TAG, "Failed to read from HTTP client, error code: %d", read_len); + break; // Exit the loop on error + } } - + range_start = range_end + 1; + // Deallocate buffer + allocator.deallocate(buffer, 4096); + buffer = nullptr; return range_end + 1; } @@ -147,12 +156,12 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { ESP_LOGD(TAG, "URL: %s", this->tft_url_.c_str()); if (this->is_updating_) { - ESP_LOGD(TAG, "Currently updating"); + ESP_LOGW(TAG, "Currently uploading"); return false; } if (!network::is_connected()) { - ESP_LOGD(TAG, "network is not connected"); + ESP_LOGE(TAG, "Network is not connected"); return false; } @@ -175,43 +184,42 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { } ESP_LOGD(TAG, "Baud rate: %" PRIu32, baud_rate); - HTTPClient http; - http.setTimeout(15000); // Yes 15 seconds.... Helps 8266s along + // Define the configuration for the HTTP client + ESP_LOGV(TAG, "Initializing HTTP client"); + ESP_LOGV(TAG, "Free heap: %" PRIu32, this->get_free_heap_()); + HTTPClient http_client; + http_client.setTimeout(15000); // Yes 15 seconds.... Helps 8266s along + bool begin_status = false; #ifdef USE_ESP32 - begin_status = http.begin(this->tft_url_.c_str()); + begin_status = http_client.begin(this->tft_url_.c_str()); #endif #ifdef USE_ESP8266 #if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 7, 0) - http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); + http_client.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); #elif USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 6, 0) - http.setFollowRedirects(true); + http_client.setFollowRedirects(true); #endif #if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 6, 0) - http.setRedirectLimit(3); + http_client.setRedirectLimit(3); #endif - begin_status = http.begin(*this->get_wifi_client_(), this->tft_url_.c_str()); -#endif - + begin_status = http_client.begin(*this->get_wifi_client_(), this->tft_url_.c_str()); +#endif // USE_ESP8266 if (!begin_status) { this->is_updating_ = false; ESP_LOGD(TAG, "Connection failed"); - ExternalRAMAllocator allocator(ExternalRAMAllocator::ALLOW_FAILURE); - allocator.deallocate(this->transfer_buffer_, this->transfer_buffer_size_); return false; } else { ESP_LOGD(TAG, "Connected"); } - - http.addHeader("Range", "bytes=0-255"); + http_client.addHeader("Range", "bytes=0-255"); const char *header_names[] = {"Content-Range"}; - http.collectHeaders(header_names, 1); + http_client.collectHeaders(header_names, 1); ESP_LOGD(TAG, "Requesting URL: %s", this->tft_url_.c_str()); - - http.setReuse(true); + http_client.setReuse(true); // try up to 5 times. DNS sometimes needs a second try or so int tries = 1; - int code = http.GET(); + int code = http_client.GET(); delay(100); // NOLINT App.feed_wdt(); @@ -221,34 +229,41 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { delay(250); // NOLINT App.feed_wdt(); - code = http.GET(); + code = http_client.GET(); ++tries; } - if ((code != 200 && code != 206) || tries > 5) { + if (code != 200 and code != 206) { return this->upload_end_(false); } - String content_range_string = http.header("Content-Range"); + String content_range_string = http_client.header("Content-Range"); content_range_string.remove(0, 12); - this->content_length_ = content_range_string.toInt(); - this->tft_size_ = content_length_; - http.end(); + this->tft_size_ = content_range_string.toInt(); - if (this->content_length_ < 4096) { - ESP_LOGE(TAG, "Failed to get file size"); + ESP_LOGD(TAG, "TFT file size: %zu bytes", this->tft_size_); + if (this->tft_size_ < 4096) { + ESP_LOGE(TAG, "File size check failed."); + ESP_LOGD(TAG, "Close HTTP connection"); + http_client.end(); + ESP_LOGV(TAG, "Connection closed"); return this->upload_end_(false); + } else { + ESP_LOGV(TAG, "File size check passed. Proceeding..."); } + this->content_length_ = this->tft_size_; - ESP_LOGD(TAG, "Updating Nextion %s...", this->device_model_.c_str()); - // The Nextion will ignore the update command if it is sleeping + ESP_LOGD(TAG, "Uploading Nextion"); + // The Nextion will ignore the upload command if it is sleeping + ESP_LOGV(TAG, "Wake-up Nextion"); + this->ignore_is_setup_ = true; this->send_command_("sleep=0"); - this->set_backlight_brightness(1.0); + this->send_command_("dim=100"); delay(250); // NOLINT + ESP_LOGV(TAG, "Free heap: %" PRIu32, this->get_free_heap_()); App.feed_wdt(); - char command[128]; // Tells the Nextion the content length of the tft file and baud rate it will be sent at // Once the Nextion accepts the command it will wait until the file is successfully uploaded @@ -256,11 +271,12 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { sprintf(command, "whmi-wris %d,%d,1", this->content_length_, baud_rate); // Clear serial receive buffer - uint8_t d; - while (this->available()) { - this->read_byte(&d); - }; + ESP_LOGV(TAG, "Clear serial receive buffer"); + this->reset_(false); + delay(250); // NOLINT + ESP_LOGV(TAG, "Free heap: %" PRIu32, this->get_free_heap_()); + ESP_LOGV(TAG, "Send upload instruction: %s", command); this->send_command_(command); if (baud_rate != this->original_baud_rate_) { @@ -272,84 +288,60 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { App.feed_wdt(); std::string response; - ESP_LOGD(TAG, "Waiting for upgrade response"); - this->recv_ret_string_(response, 2000, true); // This can take some time to return + ESP_LOGV(TAG, "Waiting for upgrade response"); + this->recv_ret_string_(response, 5000, true); // This can take some time to return // The Nextion display will, if it's ready to accept data, send a 0x05 byte. - ESP_LOGD(TAG, "Upgrade response is [%s] - %zu bytes", + ESP_LOGD(TAG, "Upgrade response is [%s] - %zu byte(s)", format_hex_pretty(reinterpret_cast(response.data()), response.size()).c_str(), response.length()); - - for (size_t i = 0; i < response.length(); i++) { - ESP_LOGD(TAG, "Available %d : 0x%02X", i, response[i]); - } + ESP_LOGV(TAG, "Free heap: %" PRIu32, this->get_free_heap_()); if (response.find(0x05) != std::string::npos) { - ESP_LOGD(TAG, "preparation for tft update done"); + ESP_LOGV(TAG, "Preparation for TFT upload done"); } else { - ESP_LOGD(TAG, "preparation for tft update failed %d \"%s\"", response[0], response.c_str()); + ESP_LOGE(TAG, "Preparation for TFT upload failed %d \"%s\"", response[0], response.c_str()); + ESP_LOGD(TAG, "Close HTTP connection"); + http_client.end(); + ESP_LOGV(TAG, "Connection closed"); return this->upload_end_(false); } - // Nextion wants 4096 bytes at a time. Make chunk_size a multiple of 4096 -#ifdef USE_ESP32 - uint32_t chunk_size = 8192; - if (heap_caps_get_free_size(MALLOC_CAP_SPIRAM) > 0) { - chunk_size = this->content_length_; - } else { - if (ESP.getFreeHeap() > 81920) { // Ensure some FreeHeap to other things and limit chunk size - chunk_size = ESP.getFreeHeap() - 65536; - chunk_size = int(chunk_size / 4096) * 4096; - chunk_size = chunk_size > 65536 ? 65536 : chunk_size; - } else if (ESP.getFreeHeap() < 32768) { - chunk_size = 4096; - } - } -#else - // NOLINTNEXTLINE(readability-static-accessed-through-instance) - uint32_t chunk_size = ESP.getFreeHeap() < 16384 ? 4096 : 8192; -#endif + ESP_LOGD(TAG, "Uploading TFT to Nextion:"); + ESP_LOGD(TAG, " URL: %s", this->tft_url_.c_str()); + ESP_LOGD(TAG, " File size: %d bytes", this->content_length_); + ESP_LOGD(TAG, " Free heap: %" PRIu32, this->get_free_heap_()); - if (this->transfer_buffer_ == nullptr) { - ExternalRAMAllocator allocator(ExternalRAMAllocator::ALLOW_FAILURE); - // NOLINTNEXTLINE(readability-static-accessed-through-instance) - ESP_LOGD(TAG, "Allocating buffer size %d, Heap size is %u", chunk_size, ESP.getFreeHeap()); - this->transfer_buffer_ = allocator.allocate(chunk_size); - if (this->transfer_buffer_ == nullptr) { // Try a smaller size - ESP_LOGD(TAG, "Could not allocate buffer size: %d trying 4096 instead", chunk_size); - chunk_size = 4096; - ESP_LOGD(TAG, "Allocating %d buffer", chunk_size); - this->transfer_buffer_ = allocator.allocate(chunk_size); + // Proceed with the content download as before - if (!this->transfer_buffer_) - return this->upload_end_(false); - } + ESP_LOGV(TAG, "Starting transfer by chunks loop"); - this->transfer_buffer_size_ = chunk_size; - } - - // NOLINTNEXTLINE(readability-static-accessed-through-instance) - ESP_LOGD(TAG, "Updating tft from \"%s\" with a file size of %d using %zu chunksize, Heap Size %d", - this->tft_url_.c_str(), this->content_length_, this->transfer_buffer_size_, ESP.getFreeHeap()); - - int result = 0; + uint32_t position = 0; while (this->content_length_ > 0) { - result = this->upload_by_chunks_(&http, result); - if (result < 0) { - ESP_LOGD(TAG, "Error updating Nextion!"); + int upload_result = upload_by_chunks_(http_client, position); + if (upload_result < 0) { + ESP_LOGE(TAG, "Error uploading TFT to Nextion!"); + ESP_LOGD(TAG, "Close HTTP connection"); + http_client.end(); + ESP_LOGV(TAG, "Connection closed"); return this->upload_end_(false); } App.feed_wdt(); - // NOLINTNEXTLINE(readability-static-accessed-through-instance) - ESP_LOGD(TAG, "Heap Size %d, Bytes left %d", ESP.getFreeHeap(), this->content_length_); + ESP_LOGV(TAG, "Free heap: %" PRIu32 ", Bytes left: %" PRIu32, this->get_free_heap_(), this->content_length_); } - ESP_LOGD(TAG, "Successfully updated Nextion!"); - return this->upload_end_(true); + ESP_LOGD(TAG, "Successfully uploaded TFT to Nextion!"); + + ESP_LOGD(TAG, "Close HTTP connection"); + http_client.end(); + ESP_LOGV(TAG, "Connection closed"); + return upload_end_(true); } bool Nextion::upload_end_(bool successful) { + ESP_LOGD(TAG, "Nextion TFT upload finished: %s", YESNO(successful)); this->is_updating_ = false; + this->ignore_is_setup_ = false; uint32_t baud_rate = this->parent_->get_baud_rate(); if (baud_rate != this->original_baud_rate_) { @@ -358,12 +350,12 @@ bool Nextion::upload_end_(bool successful) { this->parent_->load_settings(); } - ESP_LOGD(TAG, "Restarting Nextion"); - this->soft_reset(); if (successful) { + ESP_LOGD(TAG, "Restarting ESPHome"); delay(1500); // NOLINT - ESP_LOGD(TAG, "Restarting esphome"); - ESP.restart(); // NOLINT(readability-static-accessed-through-instance) + arch_restart(); + } else { + ESP_LOGE(TAG, "Nextion TFT upload failed"); } return successful; } @@ -386,9 +378,10 @@ WiFiClient *Nextion::get_wifi_client_() { } return this->wifi_client_; } -#endif +#endif // USE_ESP8266 + } // namespace nextion } // namespace esphome -#endif // USE_NEXTION_TFT_UPLOAD #endif // ARDUINO +#endif // USE_NEXTION_TFT_UPLOAD From c69cdec0521147ec3d1a594c9c5121cab9710c33 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Tue, 30 Apr 2024 23:49:20 -0500 Subject: [PATCH 1362/2101] Extend MQTT tests (#6648) --- esphome/components/mqtt/__init__.py | 7 +- tests/components/mqtt/common.yaml | 428 +++++++++++++++++++ tests/components/mqtt/test.bk72xx.yaml | 2 + tests/components/mqtt/test.esp32-c3-idf.yaml | 18 +- tests/components/mqtt/test.esp32-c3.yaml | 17 +- tests/components/mqtt/test.esp32-idf.yaml | 18 +- tests/components/mqtt/test.esp32.yaml | 17 +- tests/components/mqtt/test.esp8266.yaml | 17 +- 8 files changed, 446 insertions(+), 78 deletions(-) create mode 100644 tests/components/mqtt/common.yaml create mode 100644 tests/components/mqtt/test.bk72xx.yaml diff --git a/esphome/components/mqtt/__init__.py b/esphome/components/mqtt/__init__.py index 064362c619..31cbb2cf97 100644 --- a/esphome/components/mqtt/__init__.py +++ b/esphome/components/mqtt/__init__.py @@ -54,7 +54,12 @@ from esphome.components.esp32 import add_idf_sdkconfig_option DEPENDENCIES = ["network"] -AUTO_LOAD = ["json"] + +def AUTO_LOAD(): + if CORE.is_esp8266 or CORE.is_libretiny: + return ["async_tcp", "json"] + return ["json"] + CONF_IDF_SEND_ASYNC = "idf_send_async" CONF_SKIP_CERT_CN_CHECK = "skip_cert_cn_check" diff --git a/tests/components/mqtt/common.yaml b/tests/components/mqtt/common.yaml new file mode 100644 index 0000000000..a2a751df63 --- /dev/null +++ b/tests/components/mqtt/common.yaml @@ -0,0 +1,428 @@ +wifi: + ssid: MySSID + password: password1 + +time: + - platform: sntp + +mqtt: + broker: "192.168.178.84" + port: 1883 + username: debug + password: debug + client_id: someclient + use_abbreviations: false + discovery: true + discovery_retain: false + discovery_prefix: discovery + discovery_unique_id_generator: legacy + topic_prefix: helloworld + log_topic: + topic: helloworld/hi + level: INFO + birth_message: + will_message: + shutdown_message: + topic: topic/to/send/to + payload: hi + qos: 2 + retain: true + keepalive: 60s + reboot_timeout: 60s + on_message: + - topic: my/custom/topic + qos: 0 + then: + - lambda: >- + ESP_LOGD("main", "Got message %s", x.c_str()); + - topic: bedroom/ota_mode + then: + - logger.log: Got bedroom/ota_mode + - topic: livingroom/ota_mode + then: + - logger.log: Got livingroom/ota_mode + on_json_message: + topic: the/topic + then: + - if: + condition: + - wifi.connected: + - mqtt.connected: + then: + - logger.log: on_json_message + on_connect: + - mqtt.publish: + topic: some/topic + payload: Hello + on_disconnect: + - mqtt.publish: + topic: some/topic + payload: Good-bye + +binary_sensor: + - platform: template + id: some_binary_sensor + name: Garage Door Open + state_topic: some/topic/binary_sensor + qos: 2 + lambda: |- + if (id(template_sens).state > 30) { + // Garage Door is open. + return true; + } else { + // Garage Door is closed. + return false; + } + on_state: + - mqtt.publish: + topic: some/topic/binary_sensor + payload: Hello + qos: 2 + retain: true + +button: + - platform: template + name: "Template Button" + state_topic: some/topic/button + qos: 2 + on_press: + - mqtt.publish: + topic: some/topic/button + payload: Hello + qos: 2 + retain: true + +climate: + - platform: thermostat + name: Test Thermostat + sensor: template_sens + humidity_sensor: template_sens + action_state_topic: some/topicaction_state + current_temperature_state_topic: some/topiccurrent_temperature_state + current_humidity_state_topic: some/topiccurrent_humidity_state + fan_mode_state_topic: some/topicfan_mode_state + fan_mode_command_topic: some/topicfan_mode_command + mode_state_topic: some/topicmode_state + mode_command_topic: some/topicmode_command + preset_state_topic: some/topicpreset_state + preset_command_topic: some/topicpreset_command + swing_mode_state_topic: some/topicswing_mode_state + swing_mode_command_topic: some/topicswing_mode_command + target_temperature_state_topic: some/topictarget_temperature_state + target_temperature_command_topic: some/topictarget_temperature_command + target_temperature_high_state_topic: some/topictarget_temperature_high_state + target_temperature_high_command_topic: some/topictarget_temperature_high_command + target_temperature_low_state_topic: some/topictarget_temperature_low_state + target_temperature_low_command_topic: some/topictarget_temperature_low_command + target_humidity_state_topic: some/topictarget_humidity_state + target_humidity_command_topic: some/topictarget_humidity_command + preset: + - name: Default Preset + default_target_temperature_low: 18°C + default_target_temperature_high: 24°C + - name: Away + default_target_temperature_low: 16°C + default_target_temperature_high: 20°C + idle_action: + - logger.log: idle_action + cool_action: + - logger.log: cool_action + supplemental_cooling_action: + - logger.log: supplemental_cooling_action + heat_action: + - logger.log: heat_action + supplemental_heating_action: + - logger.log: supplemental_heating_action + dry_action: + - logger.log: dry_action + fan_only_action: + - logger.log: fan_only_action + auto_mode: + - logger.log: auto_mode + off_mode: + - logger.log: off_mode + heat_mode: + - logger.log: heat_mode + cool_mode: + - logger.log: cool_mode + dry_mode: + - logger.log: dry_mode + fan_only_mode: + - logger.log: fan_only_mode + fan_mode_auto_action: + - logger.log: fan_mode_auto_action + fan_mode_on_action: + - logger.log: fan_mode_on_action + fan_mode_off_action: + - logger.log: fan_mode_off_action + fan_mode_low_action: + - logger.log: fan_mode_low_action + fan_mode_medium_action: + - logger.log: fan_mode_medium_action + fan_mode_high_action: + - logger.log: fan_mode_high_action + fan_mode_middle_action: + - logger.log: fan_mode_middle_action + fan_mode_focus_action: + - logger.log: fan_mode_focus_action + fan_mode_diffuse_action: + - logger.log: fan_mode_diffuse_action + fan_mode_quiet_action: + - logger.log: fan_mode_quiet_action + swing_off_action: + - logger.log: swing_off_action + swing_horizontal_action: + - logger.log: swing_horizontal_action + swing_vertical_action: + - logger.log: swing_vertical_action + swing_both_action: + - logger.log: swing_both_action + startup_delay: true + supplemental_cooling_delta: 2.0 + cool_deadband: 0.5 + cool_overrun: 0.5 + min_cooling_off_time: 300s + min_cooling_run_time: 300s + max_cooling_run_time: 600s + supplemental_heating_delta: 2.0 + heat_deadband: 0.5 + heat_overrun: 0.5 + min_heating_off_time: 300s + min_heating_run_time: 300s + max_heating_run_time: 600s + min_fanning_off_time: 30s + min_fanning_run_time: 30s + min_fan_mode_switching_time: 15s + min_idle_time: 30s + set_point_minimum_differential: 0.5 + fan_only_action_uses_fan_mode_timer: true + fan_only_cooling: true + fan_with_cooling: true + fan_with_heating: true + +cover: + - platform: template + name: Template Cover + state_topic: some/topic/cover + qos: 2 + lambda: |- + if (id(some_binary_sensor).state) { + return COVER_OPEN; + } else { + return COVER_CLOSED; + } + open_action: + - logger.log: open_action + close_action: + - logger.log: close_action + stop_action: + - logger.log: stop_action + optimistic: true + +datetime: + - platform: template + name: Date + id: test_date + type: date + state_topic: some/topic/date + qos: 2 + set_action: + - logger.log: "set_value" + on_value: + - logger.log: + format: "Date: %04d-%02d-%02d" + args: + - x.year + - x.month + - x.day_of_month + - platform: template + name: Time + id: test_time + type: time + state_topic: some/topic/time + qos: 2 + set_action: + - logger.log: "set_value" + on_value: + - logger.log: + format: "Time: %02d:%02d:%02d" + args: + - x.hour + - x.minute + - x.second + - platform: template + name: DateTime + id: test_datetime + type: datetime + state_topic: some/topic/datetime + qos: 2 + set_action: + - logger.log: set_value + on_value: + - logger.log: + format: "DateTime: %04d-%02d-%02d %02d:%02d:%02d" + args: + - x.year + - x.month + - x.day_of_month + - x.hour + - x.minute + - x.second + +event: + - platform: template + name: Template Event + state_topic: some/topic/event + qos: 2 + event_types: + - "custom_event_1" + - "custom_event_2" + +fan: + - platform: template + name: Template Fan + state_topic: some/topic/fan + qos: 2 + on_state: + - logger.log: on_state + on_speed_set: + - logger.log: on_speed_set + +light: + - platform: binary + name: Desk Lamp + output: light_output + state_topic: some/topic/light + qos: 2 + +output: + - id: light_output + platform: gpio + pin: 0 + +lock: + - platform: template + name: "Template Lock" + state_topic: some/topic/lock + qos: 2 + lambda: |- + if (id(some_binary_sensor).state) { + return LOCK_STATE_LOCKED; + } else { + return LOCK_STATE_UNLOCKED; + } + lock_action: + - logger.log: lock_action + unlock_action: + - logger.log: unlock_action + open_action: + - logger.log: open_action + +number: + - platform: template + name: "Template number" + state_topic: some/topic/number + qos: 2 + optimistic: true + min_value: 0 + max_value: 100 + step: 1 + +select: + - platform: template + name: "Template select" + state_topic: some/topic/select + qos: 2 + optimistic: true + options: + - one + - two + - three + initial_option: two + +sensor: + - platform: template + name: Template Sensor + id: template_sens + lambda: |- + if (id(some_binary_sensor).state) { + return 42.0; + } else { + return 0.0; + } + update_interval: 60s + on_value: + - mqtt.publish: + topic: some/topic/sensor + payload: Hello + qos: 2 + retain: true + - platform: mqtt_subscribe + name: MQTT Subscribe Sensor + topic: mqtt/topic + id: the_sensor + qos: 2 + on_value: + - mqtt.publish_json: + topic: the/topic + payload: |- + root["key"] = id(template_sens).state; + root["greeting"] = "Hello World"; + +switch: + - platform: template + name: Template Switch + state_topic: some/topic/switch + qos: 2 + lambda: |- + if (id(some_binary_sensor).state) { + return true; + } else { + return false; + } + turn_on_action: + - logger.log: turn_on_action + turn_off_action: + - logger.log: turn_off_action + +text_sensor: + - platform: template + name: Template Text Sensor + id: tts_text + state_topic: some/topic/text_sensor + qos: 2 + - platform: mqtt_subscribe + name: MQTT Subscribe Text + topic: some/topic/text_sensor + qos: 2 + on_value: + - text_sensor.template.publish: + id: tts_text + state: Hello World + - text_sensor.template.publish: + id: tts_text + state: |- + return "Hello World2"; + +text: + - platform: template + name: Template Text + optimistic: true + min_length: 0 + max_length: 100 + mode: text + state_topic: some/topic/text + qos: 2 + +valve: + - platform: template + name: Template Valve + state_topic: some/topic/valve + qos: 2 + optimistic: true + lambda: |- + if (id(some_binary_sensor).state) { + return VALVE_OPEN; + } else { + return VALVE_CLOSED; + } diff --git a/tests/components/mqtt/test.bk72xx.yaml b/tests/components/mqtt/test.bk72xx.yaml new file mode 100644 index 0000000000..25cb37a0b4 --- /dev/null +++ b/tests/components/mqtt/test.bk72xx.yaml @@ -0,0 +1,2 @@ +packages: + common: !include common.yaml diff --git a/tests/components/mqtt/test.esp32-c3-idf.yaml b/tests/components/mqtt/test.esp32-c3-idf.yaml index 7702ed5610..25cb37a0b4 100644 --- a/tests/components/mqtt/test.esp32-c3-idf.yaml +++ b/tests/components/mqtt/test.esp32-c3-idf.yaml @@ -1,16 +1,2 @@ -wifi: - ssid: MySSID - password: password1 - -mqtt: - broker: test.mosquitto.org - port: 1883 - discovery: true - discovery_prefix: homeassistant - idf_send_async: false - log_topic: - on_message: - topic: testing/sensor/testing_sensor/state - qos: 0 - then: - - logger.log: Mqtt Test +packages: + common: !include common.yaml diff --git a/tests/components/mqtt/test.esp32-c3.yaml b/tests/components/mqtt/test.esp32-c3.yaml index 692d504d6d..25cb37a0b4 100644 --- a/tests/components/mqtt/test.esp32-c3.yaml +++ b/tests/components/mqtt/test.esp32-c3.yaml @@ -1,15 +1,2 @@ -wifi: - ssid: MySSID - password: password1 - -mqtt: - broker: test.mosquitto.org - port: 1883 - discovery: true - discovery_prefix: homeassistant - log_topic: - on_message: - topic: testing/sensor/testing_sensor/state - qos: 0 - then: - - logger.log: Mqtt Test +packages: + common: !include common.yaml diff --git a/tests/components/mqtt/test.esp32-idf.yaml b/tests/components/mqtt/test.esp32-idf.yaml index 7702ed5610..25cb37a0b4 100644 --- a/tests/components/mqtt/test.esp32-idf.yaml +++ b/tests/components/mqtt/test.esp32-idf.yaml @@ -1,16 +1,2 @@ -wifi: - ssid: MySSID - password: password1 - -mqtt: - broker: test.mosquitto.org - port: 1883 - discovery: true - discovery_prefix: homeassistant - idf_send_async: false - log_topic: - on_message: - topic: testing/sensor/testing_sensor/state - qos: 0 - then: - - logger.log: Mqtt Test +packages: + common: !include common.yaml diff --git a/tests/components/mqtt/test.esp32.yaml b/tests/components/mqtt/test.esp32.yaml index 692d504d6d..25cb37a0b4 100644 --- a/tests/components/mqtt/test.esp32.yaml +++ b/tests/components/mqtt/test.esp32.yaml @@ -1,15 +1,2 @@ -wifi: - ssid: MySSID - password: password1 - -mqtt: - broker: test.mosquitto.org - port: 1883 - discovery: true - discovery_prefix: homeassistant - log_topic: - on_message: - topic: testing/sensor/testing_sensor/state - qos: 0 - then: - - logger.log: Mqtt Test +packages: + common: !include common.yaml diff --git a/tests/components/mqtt/test.esp8266.yaml b/tests/components/mqtt/test.esp8266.yaml index 692d504d6d..25cb37a0b4 100644 --- a/tests/components/mqtt/test.esp8266.yaml +++ b/tests/components/mqtt/test.esp8266.yaml @@ -1,15 +1,2 @@ -wifi: - ssid: MySSID - password: password1 - -mqtt: - broker: test.mosquitto.org - port: 1883 - discovery: true - discovery_prefix: homeassistant - log_topic: - on_message: - topic: testing/sensor/testing_sensor/state - qos: 0 - then: - - logger.log: Mqtt Test +packages: + common: !include common.yaml From 5ddad2647605b28da208029e7959aa12701904bd Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Wed, 1 May 2024 14:17:11 -0500 Subject: [PATCH 1363/2101] Extend and consolidate `script` tests (#6663) --- tests/components/script/common.yaml | 55 +++++++++++++++++++ tests/components/script/test.bk72xx.yaml | 1 + .../components/script/test.esp32-c3-idf.yaml | 27 +-------- tests/components/script/test.esp32-c3.yaml | 27 +-------- tests/components/script/test.esp32-idf.yaml | 27 +-------- tests/components/script/test.esp32.yaml | 27 +-------- tests/components/script/test.esp8266.yaml | 27 +-------- tests/components/script/test.rp2040.yaml | 27 +-------- 8 files changed, 62 insertions(+), 156 deletions(-) create mode 100644 tests/components/script/common.yaml create mode 100644 tests/components/script/test.bk72xx.yaml diff --git a/tests/components/script/common.yaml b/tests/components/script/common.yaml new file mode 100644 index 0000000000..bfd5d0e7ff --- /dev/null +++ b/tests/components/script/common.yaml @@ -0,0 +1,55 @@ +esphome: + on_boot: + then: + - script.execute: my_script + - script.execute: + id: my_script_with_params + prefix: "Test" + param2: 0 + param3: true + - script.wait: my_script + - script.stop: my_script + - if: + condition: + - script.is_running: my_script + then: + - logger.log: my_script is running + +script: + - id: my_script + mode: single + then: + - lambda: 'ESP_LOGD("main", "Hello World!");' + - id: my_script_queued + mode: queued + max_runs: 2 + then: + - lambda: 'ESP_LOGD("main", "Hello World!");' + - id: my_script_parallel + mode: parallel + max_runs: 2 + then: + - lambda: 'ESP_LOGD("main", "Hello World!");' + - id: my_script_restart + mode: restart + then: + - lambda: 'ESP_LOGD("main", "Hello World!");' + - id: my_script_with_params + parameters: + prefix: string + param2: uint8_t + param3: bool + then: + - lambda: 'ESP_LOGD(prefix.c_str(), "Hello World! %u %u", param2, param3);' + - if: + condition: + for: + time: !lambda "return param2;" + condition: + script.is_running: my_script + then: + - lambda: 'ESP_LOGD("main", "API has stayed connected for at least %u minutes", param2);' + - repeat: + count: 5 + then: + - logger.log: looping! diff --git a/tests/components/script/test.bk72xx.yaml b/tests/components/script/test.bk72xx.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/script/test.bk72xx.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/script/test.esp32-c3-idf.yaml b/tests/components/script/test.esp32-c3-idf.yaml index 3872c690ff..dade44d145 100644 --- a/tests/components/script/test.esp32-c3-idf.yaml +++ b/tests/components/script/test.esp32-c3-idf.yaml @@ -1,26 +1 @@ -script: - - id: my_script - mode: single - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_queued - mode: queued - max_runs: 2 - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_parallel - mode: parallel - max_runs: 2 - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_restart - mode: restart - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_with_params - parameters: - prefix: string - param2: int - param3: bool - then: - - lambda: 'ESP_LOGD("main", (prefix + " Hello World!" + to_string(param2) + " " + to_string(param3)).c_str());' +<<: !include common.yaml diff --git a/tests/components/script/test.esp32-c3.yaml b/tests/components/script/test.esp32-c3.yaml index 3872c690ff..dade44d145 100644 --- a/tests/components/script/test.esp32-c3.yaml +++ b/tests/components/script/test.esp32-c3.yaml @@ -1,26 +1 @@ -script: - - id: my_script - mode: single - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_queued - mode: queued - max_runs: 2 - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_parallel - mode: parallel - max_runs: 2 - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_restart - mode: restart - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_with_params - parameters: - prefix: string - param2: int - param3: bool - then: - - lambda: 'ESP_LOGD("main", (prefix + " Hello World!" + to_string(param2) + " " + to_string(param3)).c_str());' +<<: !include common.yaml diff --git a/tests/components/script/test.esp32-idf.yaml b/tests/components/script/test.esp32-idf.yaml index 3872c690ff..dade44d145 100644 --- a/tests/components/script/test.esp32-idf.yaml +++ b/tests/components/script/test.esp32-idf.yaml @@ -1,26 +1 @@ -script: - - id: my_script - mode: single - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_queued - mode: queued - max_runs: 2 - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_parallel - mode: parallel - max_runs: 2 - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_restart - mode: restart - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_with_params - parameters: - prefix: string - param2: int - param3: bool - then: - - lambda: 'ESP_LOGD("main", (prefix + " Hello World!" + to_string(param2) + " " + to_string(param3)).c_str());' +<<: !include common.yaml diff --git a/tests/components/script/test.esp32.yaml b/tests/components/script/test.esp32.yaml index 3872c690ff..dade44d145 100644 --- a/tests/components/script/test.esp32.yaml +++ b/tests/components/script/test.esp32.yaml @@ -1,26 +1 @@ -script: - - id: my_script - mode: single - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_queued - mode: queued - max_runs: 2 - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_parallel - mode: parallel - max_runs: 2 - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_restart - mode: restart - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_with_params - parameters: - prefix: string - param2: int - param3: bool - then: - - lambda: 'ESP_LOGD("main", (prefix + " Hello World!" + to_string(param2) + " " + to_string(param3)).c_str());' +<<: !include common.yaml diff --git a/tests/components/script/test.esp8266.yaml b/tests/components/script/test.esp8266.yaml index ce0e40e7ee..dade44d145 100644 --- a/tests/components/script/test.esp8266.yaml +++ b/tests/components/script/test.esp8266.yaml @@ -1,26 +1 @@ -script: - - id: my_script - mode: single - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_queued - mode: queued - max_runs: 2 - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_parallel - mode: parallel - max_runs: 2 - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_restart - mode: restart - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_with_params - parameters: - prefix: string - param2: int - param3: bool - then: - - lambda: 'ESP_LOGD(prefix.c_str(), "Hello World! %i %i", param2, param3);' +<<: !include common.yaml diff --git a/tests/components/script/test.rp2040.yaml b/tests/components/script/test.rp2040.yaml index 3872c690ff..dade44d145 100644 --- a/tests/components/script/test.rp2040.yaml +++ b/tests/components/script/test.rp2040.yaml @@ -1,26 +1 @@ -script: - - id: my_script - mode: single - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_queued - mode: queued - max_runs: 2 - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_parallel - mode: parallel - max_runs: 2 - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_restart - mode: restart - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_with_params - parameters: - prefix: string - param2: int - param3: bool - then: - - lambda: 'ESP_LOGD("main", (prefix + " Hello World!" + to_string(param2) + " " + to_string(param3)).c_str());' +<<: !include common.yaml From a4a23d73b32b0b485ccfbd8209b787a6785d5dd9 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Thu, 2 May 2024 00:05:37 +0200 Subject: [PATCH 1364/2101] [nextion] Use persistent http connection for TFT upload (ESP-IDF) (#6576) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- CODEOWNERS | 2 +- esphome/components/nextion/display.py | 2 +- esphome/components/nextion/nextion.h | 37 +- .../components/nextion/nextion_upload_idf.cpp | 395 +++++++++--------- esphome/core/defines.h | 2 +- 5 files changed, 225 insertions(+), 213 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index a60a5c3099..d0e920fe1d 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -242,7 +242,7 @@ esphome/components/mpl3115a2/* @kbickar esphome/components/mpu6886/* @fabaff esphome/components/ms8607/* @e28eta esphome/components/network/* @esphome/core -esphome/components/nextion/* @senexcrenshaw +esphome/components/nextion/* @edwardtfn @senexcrenshaw esphome/components/nextion/binary_sensor/* @senexcrenshaw esphome/components/nextion/sensor/* @senexcrenshaw esphome/components/nextion/switch/* @senexcrenshaw diff --git a/esphome/components/nextion/display.py b/esphome/components/nextion/display.py index 6487c12f36..ce45d25e7b 100644 --- a/esphome/components/nextion/display.py +++ b/esphome/components/nextion/display.py @@ -25,7 +25,7 @@ from .base_component import ( CONF_EXIT_REPARSE_ON_START, ) -CODEOWNERS = ["@senexcrenshaw"] +CODEOWNERS = ["@senexcrenshaw", "@edwardtfn"] DEPENDENCIES = ["uart"] AUTO_LOAD = ["binary_sensor", "switch", "sensor", "text_sensor"] diff --git a/esphome/components/nextion/nextion.h b/esphome/components/nextion/nextion.h index 7938af0ea5..6435e2b4e2 100644 --- a/esphome/components/nextion/nextion.h +++ b/esphome/components/nextion/nextion.h @@ -1013,7 +1013,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe */ bool upload_tft(uint32_t baud_rate = 0, bool exit_reparse = true); -#endif +#endif // USE_NEXTION_TFT_UPLOAD void dump_config() override; @@ -1142,6 +1142,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * Sends commands ignoring of the Nextion has been setup. */ bool ignore_is_setup_ = false; + bool nextion_reports_is_setup_ = false; uint8_t nextion_event_; @@ -1182,7 +1183,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe WiFiClient *wifi_client_{nullptr}; BearSSL::WiFiClientSecure *wifi_client_secure_{nullptr}; WiFiClient *get_wifi_client_(); -#endif +#endif // USE_ESP8266 std::string tft_url_; uint32_t content_length_ = 0; int tft_size_ = 0; @@ -1193,11 +1194,21 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe /** * will request chunk_size chunks from the web server * and send each to the nextion - * @param HTTPClient http HTTP client handler. + * @param HTTPClient http_client HTTP client handler. * @param int range_start Position of next byte to transfer. * @return position of last byte transferred, -1 for failure. */ int upload_by_chunks_(HTTPClient &http_client, uint32_t &range_start); +#elif defined(USE_ESP_IDF) + /** + * will request 4096 bytes chunks from the web server + * and send each to Nextion + * @param esp_http_client_handle_t http_client HTTP client handler. + * @param int range_start Position of next byte to transfer. + * @return position of last byte transferred, -1 for failure. + */ + int upload_by_chunks_(esp_http_client_handle_t http_client, uint32_t &range_start); +#endif // ARDUINO vs USE_ESP_IDF /** * Ends the upload process, restart Nextion and, if successful, @@ -1207,24 +1218,6 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe */ bool upload_end_(bool successful); -#elif defined(USE_ESP_IDF) - /** - * will request 4096 bytes chunks from the web server - * and send each to Nextion - * @param std::string url Full url for download. - * @param int range_start Position of next byte to transfer. - * @return position of last byte transferred, -1 for failure. - */ - int upload_range(const std::string &url, int range_start); - - /** - * Ends the upload process, restart Nextion and, if successful, - * restarts ESP - * @param bool url successful True: Transfer completed successfuly, False: Transfer failed. - * @return bool True: Transfer completed successfuly, False: Transfer failed. - */ - bool upload_end(bool successful); -#endif // ARDUINO vs USE_ESP_IDF /** * Returns the ESP Free Heap memory. This is framework independent. * @return Free Heap in bytes. @@ -1260,7 +1253,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe #ifdef NEXTION_PROTOCOL_LOG void print_queue_members_(); -#endif +#endif // NEXTION_PROTOCOL_LOG void reset_(bool reset_nextion = true); std::string command_data_; diff --git a/esphome/components/nextion/nextion_upload_idf.cpp b/esphome/components/nextion/nextion_upload_idf.cpp index 163b497d3b..448b6fc0ff 100644 --- a/esphome/components/nextion/nextion_upload_idf.cpp +++ b/esphome/components/nextion/nextion_upload_idf.cpp @@ -1,17 +1,16 @@ #include "nextion.h" -#ifdef USE_ESP_IDF #ifdef USE_NEXTION_TFT_UPLOAD +#ifdef USE_ESP_IDF #include "esphome/core/application.h" #include "esphome/core/defines.h" #include "esphome/core/util.h" #include "esphome/core/log.h" #include "esphome/components/network/util.h" - +#include #include #include -#include namespace esphome { namespace nextion { @@ -20,153 +19,147 @@ static const char *const TAG = "nextion.upload.idf"; // Followed guide // https://unofficialnextion.com/t/nextion-upload-protocol-v1-2-the-fast-one/1044/2 -int Nextion::upload_range(const std::string &url, int range_start) { - ESP_LOGVV(TAG, "url: %s", url.c_str()); - uint range_size = this->tft_size_ - range_start; - ESP_LOGVV(TAG, "tft_size_: %i", this->tft_size_); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - int range_end = (range_start == 0) ? std::min(this->tft_size_, 16383) : this->tft_size_; +int Nextion::upload_by_chunks_(esp_http_client_handle_t http_client, uint32_t &range_start) { + uint32_t range_size = this->tft_size_ - range_start; + ESP_LOGV(TAG, "Free heap: %" PRIu32, esp_get_free_heap_size()); + 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, range_end); + ESP_LOGD(TAG, "Range size: %" PRIu32, range_size); ESP_LOGE(TAG, "Invalid range"); - ESP_LOGD(TAG, "Range start: %i", range_start); - ESP_LOGD(TAG, "Range end: %i", range_end); - ESP_LOGD(TAG, "Range size: %i", range_size); return -1; } - esp_http_client_config_t config = { - .url = url.c_str(), - .cert_pem = nullptr, - .disable_auto_redirect = false, - .max_redirection_count = 10, - }; - esp_http_client_handle_t client = esp_http_client_init(&config); - - char range_header[64]; - sprintf(range_header, "bytes=%d-%d", range_start, range_end); + char range_header[32]; + sprintf(range_header, "bytes=%" PRIu32 "-%" PRIu32, range_start, range_end); ESP_LOGV(TAG, "Requesting range: %s", range_header); - esp_http_client_set_header(client, "Range", range_header); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - - ESP_LOGV(TAG, "Opening http connetion"); + esp_http_client_set_header(http_client, "Range", range_header); + ESP_LOGV(TAG, "Opening HTTP connetion"); esp_err_t err; - if ((err = esp_http_client_open(client, 0)) != ESP_OK) { + if ((err = esp_http_client_open(http_client, 0)) != ESP_OK) { ESP_LOGE(TAG, "Failed to open HTTP connection: %s", esp_err_to_name(err)); - esp_http_client_cleanup(client); return -1; } ESP_LOGV(TAG, "Fetch content length"); - int content_length = esp_http_client_fetch_headers(client); - ESP_LOGV(TAG, "content_length = %d", content_length); - if (content_length <= 0) { - ESP_LOGE(TAG, "Failed to get content length: %d", content_length); - esp_http_client_cleanup(client); + const int chunk_size = esp_http_client_fetch_headers(http_client); + ESP_LOGV(TAG, "content_length = %d", chunk_size); + if (chunk_size <= 0) { + ESP_LOGE(TAG, "Failed to get chunk's content length: %d", chunk_size); return -1; } - int total_read_len = 0, read_len; - - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - ESP_LOGV(TAG, "Allocate buffer"); - uint8_t *buffer = new uint8_t[4096]; - std::string recv_string; - if (buffer == nullptr) { - ESP_LOGE(TAG, "Failed to allocate memory for buffer"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - } else { - ESP_LOGV(TAG, "Memory for buffer allocated successfully"); - - while (true) { - App.feed_wdt(); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - int read_len = esp_http_client_read(client, reinterpret_cast(buffer), 4096); - ESP_LOGVV(TAG, "Read %d bytes from HTTP client, writing to UART", read_len); - if (read_len > 0) { - this->write_array(buffer, read_len); - ESP_LOGVV(TAG, "Write to UART successful"); - this->recv_ret_string_(recv_string, 5000, true); - this->content_length_ -= read_len; - ESP_LOGD(TAG, "Uploaded %0.2f %%, remaining %d bytes, heap is %" PRIu32 " bytes", - 100.0 * (this->tft_size_ - this->content_length_) / this->tft_size_, this->content_length_, - esp_get_free_heap_size()); - - if (recv_string[0] == 0x08 && recv_string.size() == 5) { // handle partial upload request - ESP_LOGD( - TAG, "recv_string [%s]", - format_hex_pretty(reinterpret_cast(recv_string.data()), recv_string.size()).c_str()); - uint32_t result = 0; - for (int j = 0; j < 4; ++j) { - result += static_cast(recv_string[j + 1]) << (8 * j); - } - if (result > 0) { - ESP_LOGI(TAG, "Nextion reported new range %" PRIu32, result); - this->content_length_ = this->tft_size_ - result; - // Deallocate the buffer when done - ESP_LOGV(TAG, "Deallocate buffer"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - delete[] buffer; - ESP_LOGVV(TAG, "Memory for buffer deallocated"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - ESP_LOGV(TAG, "Close http client"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - esp_http_client_close(client); - esp_http_client_cleanup(client); - ESP_LOGVV(TAG, "Client closed"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - return result; - } - } else if (recv_string[0] != 0x05) { // 0x05 == "ok" - ESP_LOGE( - TAG, "Invalid response from Nextion: [%s]", - format_hex_pretty(reinterpret_cast(recv_string.data()), recv_string.size()).c_str()); - ESP_LOGV(TAG, "Deallocate buffer"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - delete[] buffer; - ESP_LOGVV(TAG, "Memory for buffer deallocated"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - ESP_LOGV(TAG, "Close http client"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - esp_http_client_close(client); - esp_http_client_cleanup(client); - ESP_LOGVV(TAG, "Client closed"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - return -1; - } - - recv_string.clear(); - } else if (read_len == 0) { - ESP_LOGV(TAG, "End of HTTP response reached"); - break; // Exit the loop if there is no more data to read - } else { - ESP_LOGE(TAG, "Failed to read from HTTP client, error code: %d", read_len); - break; // Exit the loop on error - } - } - - // Deallocate the buffer when done - ESP_LOGV(TAG, "Deallocate buffer"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - delete[] buffer; - ESP_LOGVV(TAG, "Memory for buffer deallocated"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); + // Allocate the buffer dynamically + ExternalRAMAllocator allocator(ExternalRAMAllocator::ALLOW_FAILURE); + uint8_t *buffer = allocator.allocate(4096); + if (!buffer) { + ESP_LOGE(TAG, "Failed to allocate upload buffer"); + return -1; } - ESP_LOGV(TAG, "Close http client"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - esp_http_client_close(client); - esp_http_client_cleanup(client); - ESP_LOGVV(TAG, "Client closed"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); + + std::string recv_string; + while (true) { + App.feed_wdt(); + const uint16_t buffer_size = + this->content_length_ < 4096 ? this->content_length_ : 4096; // Limits buffer to the remaining data + ESP_LOGV(TAG, "Fetching %" PRIu16 " bytes from HTTP", buffer_size); + uint16_t read_len = 0; + int partial_read_len = 0; + uint8_t retries = 0; + // Attempt to read the chunk with retries. + while (retries < 5 && read_len < buffer_size) { + partial_read_len = + esp_http_client_read(http_client, reinterpret_cast(buffer) + read_len, buffer_size - read_len); + if (partial_read_len > 0) { + read_len += partial_read_len; // Accumulate the total read length. + // Reset retries on successful read. + retries = 0; + } else { + // If no data was read, increment retries. + retries++; + vTaskDelay(pdMS_TO_TICKS(2)); // NOLINT + } + App.feed_wdt(); // Feed the watchdog timer. + } + if (read_len != buffer_size) { + // Did not receive the full package within the timeout period + ESP_LOGE(TAG, "Failed to read full package, received only %" PRIu16 " of %" PRIu16 " bytes", read_len, + buffer_size); + // Deallocate buffer + allocator.deallocate(buffer, 4096); + buffer = nullptr; + return -1; + } + ESP_LOGV(TAG, "%d bytes fetched, writing it to UART", read_len); + if (read_len > 0) { + 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->content_length_ -= read_len; + const float upload_percentage = 100.0f * (this->tft_size_ - this->content_length_) / this->tft_size_; +#ifdef USE_PSRAM + ESP_LOGD( + TAG, + "Uploaded %0.2f%%, remaining %" PRIu32 " bytes, free heap: %" PRIu32 " (DRAM) + %" PRIu32 " (PSRAM) bytes", + upload_percentage, this->content_length_, static_cast(heap_caps_get_free_size(MALLOC_CAP_INTERNAL)), + static_cast(heap_caps_get_free_size(MALLOC_CAP_SPIRAM))); +#else + ESP_LOGD(TAG, "Uploaded %0.2f%%, remaining %" PRIu32 " bytes, free heap: %" PRIu32 " bytes", upload_percentage, + this->content_length_, static_cast(esp_get_free_heap_size())); +#endif + upload_first_chunk_sent_ = true; + if (recv_string[0] == 0x08 && recv_string.size() == 5) { // handle partial upload request + ESP_LOGD(TAG, "recv_string [%s]", + format_hex_pretty(reinterpret_cast(recv_string.data()), recv_string.size()).c_str()); + uint32_t result = 0; + for (int j = 0; j < 4; ++j) { + result += static_cast(recv_string[j + 1]) << (8 * j); + } + if (result > 0) { + ESP_LOGI(TAG, "Nextion reported new range %" PRIu32, result); + this->content_length_ = this->tft_size_ - result; + range_start = result; + } else { + range_start = range_end + 1; + } + // Deallocate buffer + allocator.deallocate(buffer, 4096); + buffer = nullptr; + return range_end + 1; + } else if (recv_string[0] != 0x05 and recv_string[0] != 0x08) { // 0x05 == "ok" + ESP_LOGE(TAG, "Invalid response from Nextion: [%s]", + format_hex_pretty(reinterpret_cast(recv_string.data()), recv_string.size()).c_str()); + // Deallocate buffer + allocator.deallocate(buffer, 4096); + buffer = nullptr; + return -1; + } + + recv_string.clear(); + } else if (read_len == 0) { + ESP_LOGV(TAG, "End of HTTP response reached"); + break; // Exit the loop if there is no more data to read + } else { + ESP_LOGE(TAG, "Failed to read from HTTP client, error code: %" PRIu16, read_len); + break; // Exit the loop on error + } + } + range_start = range_end + 1; + // Deallocate buffer + allocator.deallocate(buffer, 4096); + buffer = nullptr; return range_end + 1; } bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { ESP_LOGD(TAG, "Nextion TFT upload requested"); ESP_LOGD(TAG, "Exit reparse: %s", YESNO(exit_reparse)); - ESP_LOGD(TAG, "url: %s", this->tft_url_.c_str()); + ESP_LOGD(TAG, "URL: %s", this->tft_url_.c_str()); if (this->is_updating_) { - ESP_LOGW(TAG, "Currently updating"); + ESP_LOGW(TAG, "Currently uploading"); return false; } @@ -195,8 +188,8 @@ 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, "Establishing connection to HTTP server"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); + ESP_LOGV(TAG, "Initializing HTTP client"); + ESP_LOGV(TAG, "Free heap: %" PRIu32, esp_get_free_heap_size()); esp_http_client_config_t config = { .url = this->tft_url_.c_str(), .cert_pem = nullptr, @@ -205,58 +198,62 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { .disable_auto_redirect = false, .max_redirection_count = 10, }; - // Initialize the HTTP client with the configuration - ESP_LOGV(TAG, "Initializing HTTP client"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - esp_http_client_handle_t http = esp_http_client_init(&config); - if (!http) { + esp_http_client_handle_t http_client = esp_http_client_init(&config); + if (!http_client) { ESP_LOGE(TAG, "Failed to initialize HTTP client."); - return this->upload_end(false); + return this->upload_end_(false); + } + + esp_err_t err = esp_http_client_set_header(http_client, "Connection", "keep-alive"); + if (err != ESP_OK) { + ESP_LOGE(TAG, "HTTP set header failed: %s", esp_err_to_name(err)); + esp_http_client_cleanup(http_client); + return this->upload_end_(false); } // Perform the HTTP request ESP_LOGV(TAG, "Check if the client could connect"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - esp_err_t err = esp_http_client_perform(http); + ESP_LOGV(TAG, "Free heap: %" PRIu32, esp_get_free_heap_size()); + err = esp_http_client_perform(http_client); if (err != ESP_OK) { ESP_LOGE(TAG, "HTTP request failed: %s", esp_err_to_name(err)); - esp_http_client_cleanup(http); - return this->upload_end(false); + esp_http_client_cleanup(http_client); + return this->upload_end_(false); } // Check the HTTP Status Code ESP_LOGV(TAG, "Check the HTTP Status Code"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - int status_code = esp_http_client_get_status_code(http); - ESP_LOGV(TAG, "HTTP Status Code: %d", status_code); - size_t tft_file_size = esp_http_client_get_content_length(http); - ESP_LOGD(TAG, "TFT file size: %zu", tft_file_size); + ESP_LOGV(TAG, "Free 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) { + return this->upload_end_(false); + } - ESP_LOGD(TAG, "Close HTTP connection"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - esp_http_client_close(http); - esp_http_client_cleanup(http); - ESP_LOGVV(TAG, "Connection closed"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); + this->tft_size_ = esp_http_client_get_content_length(http_client); - if (tft_file_size < 4096) { - ESP_LOGE(TAG, "File size check failed. Size: %zu", tft_file_size); - return this->upload_end(false); + ESP_LOGD(TAG, "TFT file size: %zu bytes", this->tft_size_); + if (this->tft_size_ < 4096 || this->tft_size_ > 134217728) { + ESP_LOGE(TAG, "File size check failed."); + ESP_LOGD(TAG, "Close HTTP connection"); + esp_http_client_close(http_client); + esp_http_client_cleanup(http_client); + ESP_LOGV(TAG, "Connection closed"); + return this->upload_end_(false); } else { ESP_LOGV(TAG, "File size check passed. Proceeding..."); } - this->content_length_ = tft_file_size; - this->tft_size_ = tft_file_size; + this->content_length_ = this->tft_size_; - ESP_LOGD(TAG, "Updating Nextion"); + ESP_LOGD(TAG, "Uploading Nextion"); - // The Nextion will ignore the update command if it is sleeping + // The Nextion will ignore the upload command if it is sleeping ESP_LOGV(TAG, "Wake-up Nextion"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); + this->ignore_is_setup_ = true; this->send_command_("sleep=0"); - this->set_backlight_brightness(1.0); + this->send_command_("dim=100"); vTaskDelay(pdMS_TO_TICKS(250)); // NOLINT + ESP_LOGV(TAG, "Free heap: %" PRIu32, esp_get_free_heap_size()); App.feed_wdt(); char command[128]; @@ -267,14 +264,11 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { // Clear serial receive buffer ESP_LOGV(TAG, "Clear serial receive buffer"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - uint8_t d; - while (this->available()) { - this->read_byte(&d); - }; + this->reset_(false); + vTaskDelay(pdMS_TO_TICKS(250)); // NOLINT + ESP_LOGV(TAG, "Free heap: %" PRIu32, esp_get_free_heap_size()); - ESP_LOGV(TAG, "Send update instruction: %s", command); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); + ESP_LOGV(TAG, "Send upload instruction: %s", command); this->send_command_(command); if (baud_rate != this->original_baud_rate_) { @@ -288,41 +282,66 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { this->recv_ret_string_(response, 5000, true); // This can take some time to return // The Nextion display will, if it's ready to accept data, send a 0x05 byte. - ESP_LOGD(TAG, "Upgrade response is [%s] - %zu bytes", + ESP_LOGD(TAG, "Upgrade response is [%s] - %zu byte(s)", format_hex_pretty(reinterpret_cast(response.data()), response.size()).c_str(), response.length()); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); + ESP_LOGV(TAG, "Free heap: %" PRIu32, esp_get_free_heap_size()); if (response.find(0x05) != std::string::npos) { - ESP_LOGV(TAG, "Preparation for tft update done"); + ESP_LOGV(TAG, "Preparation for TFT upload done"); } else { - ESP_LOGE(TAG, "Preparation for tft update failed %d \"%s\"", response[0], response.c_str()); - return this->upload_end(false); + ESP_LOGE(TAG, "Preparation for TFT upload failed %d \"%s\"", response[0], response.c_str()); + ESP_LOGD(TAG, "Close HTTP connection"); + esp_http_client_close(http_client); + esp_http_client_cleanup(http_client); + ESP_LOGV(TAG, "Connection closed"); + return this->upload_end_(false); } - ESP_LOGD(TAG, "Updating tft from \"%s\" with a file size of %d, Heap Size %" PRIu32, this->tft_url_.c_str(), - content_length_, esp_get_free_heap_size()); + ESP_LOGV(TAG, "Change the method to GET before starting the download"); + esp_err_t set_method_result = esp_http_client_set_method(http_client, HTTP_METHOD_GET); + if (set_method_result != ESP_OK) { + ESP_LOGE(TAG, "Failed to set HTTP method to GET: %s", esp_err_to_name(set_method_result)); + return this->upload_end_(false); + } + + ESP_LOGD(TAG, "Uploading TFT to Nextion:"); + ESP_LOGD(TAG, " URL: %s", this->tft_url_.c_str()); + ESP_LOGD(TAG, " File size: %" PRIu32 " bytes", this->content_length_); + ESP_LOGD(TAG, " Free heap: %" PRIu32, esp_get_free_heap_size()); + + // Proceed with the content download as before ESP_LOGV(TAG, "Starting transfer by chunks loop"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - int result = 0; - while (content_length_ > 0) { - result = upload_range(this->tft_url_.c_str(), result); - if (result < 0) { - ESP_LOGE(TAG, "Error updating Nextion!"); - return this->upload_end(false); + + uint32_t position = 0; + while (this->content_length_ > 0) { + int upload_result = upload_by_chunks_(http_client, position); + if (upload_result < 0) { + ESP_LOGE(TAG, "Error uploading TFT to Nextion!"); + ESP_LOGD(TAG, "Close HTTP connection"); + esp_http_client_close(http_client); + esp_http_client_cleanup(http_client); + ESP_LOGV(TAG, "Connection closed"); + return this->upload_end_(false); } App.feed_wdt(); - ESP_LOGV(TAG, "Heap Size %" PRIu32 ", Bytes left %d", esp_get_free_heap_size(), content_length_); + ESP_LOGV(TAG, "Free heap: %" PRIu32 ", Bytes left: %" PRIu32, esp_get_free_heap_size(), this->content_length_); } - ESP_LOGD(TAG, "Successfully updated Nextion!"); + ESP_LOGD(TAG, "Successfully uploaded TFT to Nextion!"); - return upload_end(true); + ESP_LOGD(TAG, "Close HTTP connection"); + esp_http_client_close(http_client); + esp_http_client_cleanup(http_client); + ESP_LOGV(TAG, "Connection closed"); + return this->upload_end_(true); } -bool Nextion::upload_end(bool successful) { +bool Nextion::upload_end_(bool successful) { + ESP_LOGD(TAG, "Nextion TFT upload finished: %s", YESNO(successful)); this->is_updating_ = false; + this->ignore_is_setup_ = false; uint32_t baud_rate = this->parent_->get_baud_rate(); if (baud_rate != this->original_baud_rate_) { @@ -331,12 +350,12 @@ bool Nextion::upload_end(bool successful) { this->parent_->load_settings(); } - ESP_LOGD(TAG, "Restarting Nextion"); - this->soft_reset(); - vTaskDelay(pdMS_TO_TICKS(1500)); // NOLINT if (successful) { ESP_LOGD(TAG, "Restarting ESPHome"); - esp_restart(); // NOLINT(readability-static-accessed-through-instance) + delay(1500); // NOLINT + arch_restart(); + } else { + ESP_LOGE(TAG, "Nextion TFT upload failed"); } return successful; } @@ -344,5 +363,5 @@ bool Nextion::upload_end(bool successful) { } // namespace nextion } // namespace esphome -#endif // USE_NEXTION_TFT_UPLOAD #endif // USE_ESP_IDF +#endif // USE_NEXTION_TFT_UPLOAD diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 619a956071..b09373bcde 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -35,6 +35,7 @@ #define USE_MDNS #define USE_MEDIA_PLAYER #define USE_MQTT +#define USE_NEXTION_TFT_UPLOAD #define USE_NUMBER #define USE_DATETIME #define USE_DATETIME_DATE @@ -64,7 +65,6 @@ // Arduino-specific feature flags #ifdef USE_ARDUINO #define USE_CAPTIVE_PORTAL -#define USE_NEXTION_TFT_UPLOAD #define USE_PROMETHEUS #define USE_WEBSERVER #define USE_WEBSERVER_PORT 80 // NOLINT From 539c369eea0c07a89d0b0fbc877d3b14fe17fbdc Mon Sep 17 00:00:00 2001 From: tronikos Date: Wed, 1 May 2024 17:39:15 -0700 Subject: [PATCH 1365/2101] Add a function to return the loop_interval (#6666) --- esphome/core/application.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/core/application.h b/esphome/core/application.h index 7487780412..c4c745b687 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -222,6 +222,8 @@ class Application { */ void set_loop_interval(uint32_t loop_interval) { this->loop_interval_ = loop_interval; } + uint32_t get_loop_interval() const { return this->loop_interval_; } + void schedule_dump_config() { this->dump_config_at_ = 0; } void feed_wdt(); From 1b9a30e921f129f5c9aa3dd1032387722a7babc9 Mon Sep 17 00:00:00 2001 From: Mat931 <49403702+Mat931@users.noreply.github.com> Date: Thu, 2 May 2024 01:21:57 +0000 Subject: [PATCH 1366/2101] Remote receiver improvements (#4642) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- .../components/remote_base/remote_base.cpp | 6 +- esphome/components/remote_base/remote_base.h | 45 +++++++++-- .../components/remote_receiver/__init__.py | 75 +++++++++++++++++-- .../remote_receiver/remote_receiver.h | 6 +- .../remote_receiver/remote_receiver_esp32.cpp | 16 ++-- .../remote_receiver_esp8266.cpp | 3 +- .../remote_receiver_libretiny.cpp | 3 +- 7 files changed, 125 insertions(+), 29 deletions(-) diff --git a/esphome/components/remote_base/remote_base.cpp b/esphome/components/remote_base/remote_base.cpp index 0e9cef8cca..fdfd0b43cc 100644 --- a/esphome/components/remote_base/remote_base.cpp +++ b/esphome/components/remote_base/remote_base.cpp @@ -108,18 +108,18 @@ void RemoteReceiverBase::register_dumper(RemoteReceiverDumperBase *dumper) { void RemoteReceiverBase::call_listeners_() { for (auto *listener : this->listeners_) - listener->on_receive(RemoteReceiveData(this->temp_, this->tolerance_)); + listener->on_receive(RemoteReceiveData(this->temp_, this->tolerance_, this->tolerance_mode_)); } void RemoteReceiverBase::call_dumpers_() { bool success = false; for (auto *dumper : this->dumpers_) { - if (dumper->dump(RemoteReceiveData(this->temp_, this->tolerance_))) + if (dumper->dump(RemoteReceiveData(this->temp_, this->tolerance_, this->tolerance_mode_))) success = true; } if (!success) { for (auto *dumper : this->secondary_dumpers_) - dumper->dump(RemoteReceiveData(this->temp_, this->tolerance_)); + dumper->dump(RemoteReceiveData(this->temp_, this->tolerance_, this->tolerance_mode_)); } } diff --git a/esphome/components/remote_base/remote_base.h b/esphome/components/remote_base/remote_base.h index b2a4b543ea..c31127735a 100644 --- a/esphome/components/remote_base/remote_base.h +++ b/esphome/components/remote_base/remote_base.h @@ -15,6 +15,11 @@ namespace esphome { namespace remote_base { +enum ToleranceMode : uint8_t { + TOLERANCE_MODE_PERCENTAGE = 0, + TOLERANCE_MODE_TIME = 1, +}; + using RawTimings = std::vector; class RemoteTransmitData { @@ -42,8 +47,8 @@ class RemoteTransmitData { class RemoteReceiveData { public: - explicit RemoteReceiveData(const RawTimings &data, uint8_t tolerance) - : data_(data), index_(0), tolerance_(tolerance) {} + explicit RemoteReceiveData(const RawTimings &data, uint32_t tolerance, ToleranceMode tolerance_mode) + : data_(data), index_(0), tolerance_(tolerance), tolerance_mode_(tolerance_mode) {} const RawTimings &get_raw_data() const { return this->data_; } uint32_t get_index() const { return index_; } @@ -65,13 +70,35 @@ class RemoteReceiveData { void advance(uint32_t amount = 1) { this->index_ += amount; } void reset() { this->index_ = 0; } + void set_tolerance(uint32_t tolerance, ToleranceMode tolerance_mode) { + this->tolerance_ = tolerance; + this->tolerance_mode_ = tolerance_mode; + } + uint32_t get_tolerance() { return tolerance_; } + ToleranceMode get_tolerance_mode() { return this->tolerance_mode_; } + protected: - int32_t lower_bound_(uint32_t length) const { return int32_t(100 - this->tolerance_) * length / 100U; } - int32_t upper_bound_(uint32_t length) const { return int32_t(100 + this->tolerance_) * length / 100U; } + int32_t lower_bound_(uint32_t length) const { + if (this->tolerance_mode_ == TOLERANCE_MODE_TIME) { + return int32_t(length - this->tolerance_); + } else if (this->tolerance_mode_ == TOLERANCE_MODE_PERCENTAGE) { + return int32_t(100 - this->tolerance_) * length / 100U; + } + return 0; + } + int32_t upper_bound_(uint32_t length) const { + if (this->tolerance_mode_ == TOLERANCE_MODE_TIME) { + return int32_t(length + this->tolerance_); + } else if (this->tolerance_mode_ == TOLERANCE_MODE_PERCENTAGE) { + return int32_t(100 + this->tolerance_) * length / 100U; + } + return 0; + } const RawTimings &data_; uint32_t index_; - uint8_t tolerance_; + uint32_t tolerance_; + ToleranceMode tolerance_mode_; }; class RemoteComponentBase { @@ -162,7 +189,10 @@ class RemoteReceiverBase : public RemoteComponentBase { RemoteReceiverBase(InternalGPIOPin *pin) : RemoteComponentBase(pin) {} void register_listener(RemoteReceiverListener *listener) { this->listeners_.push_back(listener); } void register_dumper(RemoteReceiverDumperBase *dumper); - void set_tolerance(uint8_t tolerance) { tolerance_ = tolerance; } + void set_tolerance(uint32_t tolerance, ToleranceMode tolerance_mode) { + this->tolerance_ = tolerance; + this->tolerance_mode_ = tolerance_mode; + } protected: void call_listeners_(); @@ -176,7 +206,8 @@ class RemoteReceiverBase : public RemoteComponentBase { std::vector dumpers_; std::vector secondary_dumpers_; RawTimings temp_; - uint8_t tolerance_; + uint32_t tolerance_{25}; + ToleranceMode tolerance_mode_{TOLERANCE_MODE_PERCENTAGE}; }; class RemoteReceiverBinarySensorBase : public binary_sensor::BinarySensorInitiallyOff, diff --git a/esphome/components/remote_receiver/__init__.py b/esphome/components/remote_receiver/__init__.py index 6a68c8b254..6fe20153f4 100644 --- a/esphome/components/remote_receiver/__init__.py +++ b/esphome/components/remote_receiver/__init__.py @@ -10,17 +10,69 @@ from esphome.const import ( CONF_IDLE, CONF_PIN, CONF_TOLERANCE, + CONF_TYPE, CONF_MEMORY_BLOCKS, CONF_RMT_CHANNEL, + CONF_VALUE, ) from esphome.core import CORE, TimePeriod +CONF_CLOCK_DIVIDER = "clock_divider" + AUTO_LOAD = ["remote_base"] remote_receiver_ns = cg.esphome_ns.namespace("remote_receiver") +remote_base_ns = cg.esphome_ns.namespace("remote_base") + +ToleranceMode = remote_base_ns.enum("ToleranceMode") + +TYPE_PERCENTAGE = "percentage" +TYPE_TIME = "time" + +TOLERANCE_MODE = { + TYPE_PERCENTAGE: ToleranceMode.TOLERANCE_MODE_PERCENTAGE, + TYPE_TIME: ToleranceMode.TOLERANCE_MODE_TIME, +} + +TOLERANCE_SCHEMA = cv.typed_schema( + { + TYPE_PERCENTAGE: cv.Schema( + {cv.Required(CONF_VALUE): cv.All(cv.percentage_int, cv.uint32_t)} + ), + TYPE_TIME: cv.Schema( + { + cv.Required(CONF_VALUE): cv.All( + cv.positive_time_period_microseconds, + cv.Range(max=TimePeriod(microseconds=4294967295)), + ) + } + ), + }, + lower=True, + enum=TOLERANCE_MODE, +) + RemoteReceiverComponent = remote_receiver_ns.class_( "RemoteReceiverComponent", remote_base.RemoteReceiverBase, cg.Component ) + +def validate_tolerance(value): + if isinstance(value, dict): + return TOLERANCE_SCHEMA(value) + + if "%" in str(value): + type_ = TYPE_PERCENTAGE + else: + type_ = TYPE_TIME + + return TOLERANCE_SCHEMA( + { + CONF_VALUE: value, + CONF_TYPE: type_, + } + ) + + MULTI_CONF = True CONFIG_SCHEMA = remote_base.validate_triggers( cv.Schema( @@ -28,9 +80,7 @@ CONFIG_SCHEMA = remote_base.validate_triggers( cv.GenerateID(): cv.declare_id(RemoteReceiverComponent), cv.Required(CONF_PIN): cv.All(pins.internal_gpio_input_pin_schema), cv.Optional(CONF_DUMP, default=[]): remote_base.validate_dumpers, - cv.Optional(CONF_TOLERANCE, default=25): cv.All( - cv.percentage_int, cv.Range(min=0) - ), + cv.Optional(CONF_TOLERANCE, default="25%"): validate_tolerance, cv.SplitDefault( CONF_BUFFER_SIZE, esp32="10000b", @@ -40,11 +90,15 @@ CONFIG_SCHEMA = remote_base.validate_triggers( ): cv.validate_bytes, cv.Optional(CONF_FILTER, default="50us"): cv.All( cv.positive_time_period_microseconds, - cv.Range(max=TimePeriod(microseconds=255)), + cv.Range(max=TimePeriod(microseconds=4294967295)), + ), + cv.SplitDefault(CONF_CLOCK_DIVIDER, esp32=80): cv.All( + cv.only_on_esp32, cv.Range(min=1, max=255) + ), + cv.Optional(CONF_IDLE, default="10ms"): cv.All( + cv.positive_time_period_microseconds, + cv.Range(max=TimePeriod(microseconds=4294967295)), ), - cv.Optional( - CONF_IDLE, default="10ms" - ): cv.positive_time_period_microseconds, cv.Optional(CONF_MEMORY_BLOCKS, default=3): cv.Range(min=1, max=8), cv.Optional(CONF_RMT_CHANNEL): esp32_rmt.validate_rmt_channel(tx=False), } @@ -61,6 +115,7 @@ async def to_code(config): ) else: var = cg.new_Pvariable(config[CONF_ID], pin, config[CONF_MEMORY_BLOCKS]) + cg.add(var.set_clock_divider(config[CONF_CLOCK_DIVIDER])) else: var = cg.new_Pvariable(config[CONF_ID], pin) @@ -73,7 +128,11 @@ async def to_code(config): cg.add(var.register_listener(trigger)) await cg.register_component(var, config) - cg.add(var.set_tolerance(config[CONF_TOLERANCE])) + cg.add( + var.set_tolerance( + config[CONF_TOLERANCE][CONF_VALUE], config[CONF_TOLERANCE][CONF_TYPE] + ) + ) cg.add(var.set_buffer_size(config[CONF_BUFFER_SIZE])) cg.add(var.set_filter_us(config[CONF_FILTER])) cg.add(var.set_idle_us(config[CONF_IDLE])) diff --git a/esphome/components/remote_receiver/remote_receiver.h b/esphome/components/remote_receiver/remote_receiver.h index f29145a59e..a1db671e5c 100644 --- a/esphome/components/remote_receiver/remote_receiver.h +++ b/esphome/components/remote_receiver/remote_receiver.h @@ -22,7 +22,7 @@ struct RemoteReceiverComponentStore { uint32_t buffer_read_at{0}; bool overflow{false}; uint32_t buffer_size{1000}; - uint8_t filter_us{10}; + uint32_t filter_us{10}; ISRInternalGPIOPin pin; }; #endif @@ -50,7 +50,7 @@ class RemoteReceiverComponent : public remote_base::RemoteReceiverBase, float get_setup_priority() const override { return setup_priority::DATA; } void set_buffer_size(uint32_t buffer_size) { this->buffer_size_ = buffer_size; } - void set_filter_us(uint8_t filter_us) { this->filter_us_ = filter_us; } + void set_filter_us(uint32_t filter_us) { this->filter_us_ = filter_us; } void set_idle_us(uint32_t idle_us) { this->idle_us_ = idle_us; } protected: @@ -66,7 +66,7 @@ class RemoteReceiverComponent : public remote_base::RemoteReceiverBase, #endif uint32_t buffer_size_{}; - uint8_t filter_us_{10}; + uint32_t filter_us_{10}; uint32_t idle_us_{10000}; }; diff --git a/esphome/components/remote_receiver/remote_receiver_esp32.cpp b/esphome/components/remote_receiver/remote_receiver_esp32.cpp index d19ab695e1..c0bfb0222f 100644 --- a/esphome/components/remote_receiver/remote_receiver_esp32.cpp +++ b/esphome/components/remote_receiver/remote_receiver_esp32.cpp @@ -20,9 +20,11 @@ void RemoteReceiverComponent::setup() { rmt.rx_config.filter_en = false; } else { rmt.rx_config.filter_en = true; - rmt.rx_config.filter_ticks_thresh = this->from_microseconds_(this->filter_us_); + rmt.rx_config.filter_ticks_thresh = static_cast( + std::min(this->from_microseconds_(this->filter_us_) * this->clock_divider_, (uint32_t) 255)); } - rmt.rx_config.idle_threshold = this->from_microseconds_(this->idle_us_); + rmt.rx_config.idle_threshold = + static_cast(std::min(this->from_microseconds_(this->idle_us_), (uint32_t) 65535)); esp_err_t error = rmt_config(&rmt); if (error != ESP_OK) { @@ -60,8 +62,9 @@ void RemoteReceiverComponent::dump_config() { ESP_LOGCONFIG(TAG, " Channel: %d", this->channel_); ESP_LOGCONFIG(TAG, " RMT memory blocks: %d", this->mem_block_num_); ESP_LOGCONFIG(TAG, " Clock divider: %u", this->clock_divider_); - ESP_LOGCONFIG(TAG, " Tolerance: %u%%", this->tolerance_); - ESP_LOGCONFIG(TAG, " Filter out pulses shorter than: %u us", this->filter_us_); + ESP_LOGCONFIG(TAG, " Tolerance: %" PRIu32 "%s", this->tolerance_, + (this->tolerance_mode_ == remote_base::TOLERANCE_MODE_TIME) ? " us" : "%"); + ESP_LOGCONFIG(TAG, " Filter out pulses shorter than: %" PRIu32 " us", this->filter_us_); ESP_LOGCONFIG(TAG, " Signal is done after %" PRIu32 " us of no changes", this->idle_us_); if (this->is_failed()) { ESP_LOGE(TAG, "Configuring RMT driver failed: %s", esp_err_to_name(this->error_code_)); @@ -88,6 +91,7 @@ void RemoteReceiverComponent::decode_rmt_(rmt_item32_t *item, size_t len) { this->temp_.clear(); int32_t multiplier = this->pin_->is_inverted() ? -1 : 1; size_t item_count = len / sizeof(rmt_item32_t); + uint32_t filter_ticks = this->from_microseconds_(this->filter_us_); ESP_LOGVV(TAG, "START:"); for (size_t i = 0; i < item_count; i++) { @@ -112,7 +116,7 @@ void RemoteReceiverComponent::decode_rmt_(rmt_item32_t *item, size_t len) { for (size_t i = 0; i < item_count; i++) { if (item[i].duration0 == 0u) { // Do nothing - } else if (bool(item[i].level0) == prev_level) { + } else if ((bool(item[i].level0) == prev_level) || (item[i].duration0 < filter_ticks)) { prev_length += item[i].duration0; } else { if (prev_length > 0) { @@ -128,7 +132,7 @@ void RemoteReceiverComponent::decode_rmt_(rmt_item32_t *item, size_t len) { if (item[i].duration1 == 0u) { // Do nothing - } else if (bool(item[i].level1) == prev_level) { + } else if ((bool(item[i].level1) == prev_level) || (item[i].duration1 < filter_ticks)) { prev_length += item[i].duration1; } else { if (prev_length > 0) { diff --git a/esphome/components/remote_receiver/remote_receiver_esp8266.cpp b/esphome/components/remote_receiver/remote_receiver_esp8266.cpp index 8700fcf0bb..c92a134bd8 100644 --- a/esphome/components/remote_receiver/remote_receiver_esp8266.cpp +++ b/esphome/components/remote_receiver/remote_receiver_esp8266.cpp @@ -64,7 +64,8 @@ void RemoteReceiverComponent::dump_config() { "invert the signal using 'inverted: True' in the pin schema!"); } ESP_LOGCONFIG(TAG, " Buffer Size: %u", this->buffer_size_); - ESP_LOGCONFIG(TAG, " Tolerance: %u%%", this->tolerance_); + ESP_LOGCONFIG(TAG, " Tolerance: %u%s", this->tolerance_, + (this->tolerance_mode_ == remote_base::TOLERANCE_MODE_TIME) ? " us" : "%"); ESP_LOGCONFIG(TAG, " Filter out pulses shorter than: %u us", this->filter_us_); ESP_LOGCONFIG(TAG, " Signal is done after %u us of no changes", this->idle_us_); } diff --git a/esphome/components/remote_receiver/remote_receiver_libretiny.cpp b/esphome/components/remote_receiver/remote_receiver_libretiny.cpp index ac85b6b520..bfc29b4211 100644 --- a/esphome/components/remote_receiver/remote_receiver_libretiny.cpp +++ b/esphome/components/remote_receiver/remote_receiver_libretiny.cpp @@ -64,7 +64,8 @@ void RemoteReceiverComponent::dump_config() { "invert the signal using 'inverted: True' in the pin schema!"); } ESP_LOGCONFIG(TAG, " Buffer Size: %u", this->buffer_size_); - ESP_LOGCONFIG(TAG, " Tolerance: %u%%", this->tolerance_); + ESP_LOGCONFIG(TAG, " Tolerance: %u%s", this->tolerance_, + (this->tolerance_mode_ == remote_base::TOLERANCE_MODE_TIME) ? " us" : "%"); ESP_LOGCONFIG(TAG, " Filter out pulses shorter than: %u us", this->filter_us_); ESP_LOGCONFIG(TAG, " Signal is done after %u us of no changes", this->idle_us_); } From bc65e6e914ea29da8bbb02ca5f5f3d948823dbd7 Mon Sep 17 00:00:00 2001 From: tronikos Date: Wed, 1 May 2024 18:24:18 -0700 Subject: [PATCH 1367/2101] Make fast update intervals in qmc5883l work (#6647) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/qmc5883l/qmc5883l.cpp | 5 +++++ esphome/components/qmc5883l/qmc5883l.h | 1 + 2 files changed, 6 insertions(+) diff --git a/esphome/components/qmc5883l/qmc5883l.cpp b/esphome/components/qmc5883l/qmc5883l.cpp index 8541b41ff7..49a67d4e09 100644 --- a/esphome/components/qmc5883l/qmc5883l.cpp +++ b/esphome/components/qmc5883l/qmc5883l.cpp @@ -1,4 +1,5 @@ #include "qmc5883l.h" +#include "esphome/core/application.h" #include "esphome/core/log.h" #include "esphome/core/hal.h" #include @@ -59,6 +60,10 @@ void QMC5883LComponent::setup() { this->mark_failed(); return; } + + if (this->get_update_interval() < App.get_loop_interval()) { + high_freq_.start(); + } } void QMC5883LComponent::dump_config() { ESP_LOGCONFIG(TAG, "QMC5883L:"); diff --git a/esphome/components/qmc5883l/qmc5883l.h b/esphome/components/qmc5883l/qmc5883l.h index b0c0af40d2..dd2008d453 100644 --- a/esphome/components/qmc5883l/qmc5883l.h +++ b/esphome/components/qmc5883l/qmc5883l.h @@ -56,6 +56,7 @@ class QMC5883LComponent : public PollingComponent, public i2c::I2CDevice { COMMUNICATION_FAILED, } error_code_; bool read_byte_16_(uint8_t a_register, uint16_t *data); + HighFrequencyLoopRequester high_freq_; }; } // namespace qmc5883l From c7c0d97a5ecbaa235636ba9e527f8c9ff7b4c4b0 Mon Sep 17 00:00:00 2001 From: Anton Viktorov Date: Thu, 2 May 2024 03:49:01 +0200 Subject: [PATCH 1368/2101] SPI and I2C for BMP390 and BMP380 (#6652) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- CODEOWNERS | 5 +- esphome/components/bmp3xx/sensor.py | 105 +----------------- esphome/components/bmp3xx_base/__init__.py | 95 ++++++++++++++++ .../bmp3xx_base.cpp} | 7 +- .../bmp3xx.h => bmp3xx_base/bmp3xx_base.h} | 15 ++- esphome/components/bmp3xx_i2c/__init__.py | 0 esphome/components/bmp3xx_i2c/bmp3xx_i2c.cpp | 29 +++++ esphome/components/bmp3xx_i2c/bmp3xx_i2c.h | 17 +++ esphome/components/bmp3xx_i2c/sensor.py | 22 ++++ esphome/components/bmp3xx_spi/__init__.py | 0 esphome/components/bmp3xx_spi/bmp3xx_spi.cpp | 57 ++++++++++ esphome/components/bmp3xx_spi/bmp3xx_spi.h | 19 ++++ esphome/components/bmp3xx_spi/sensor.py | 22 ++++ .../components/bmp3xx/test.esp32-c3-idf.yaml | 14 --- tests/components/bmp3xx/test.esp32-c3.yaml | 14 --- tests/components/bmp3xx/test.esp32.yaml | 14 --- tests/components/bmp3xx/test.esp8266.yaml | 14 --- tests/components/bmp3xx/test.rp2040.yaml | 14 --- .../common.yaml} | 7 +- .../bmp3xx_i2c/test.esp32-c3-idf.yaml | 5 + .../components/bmp3xx_i2c/test.esp32-c3.yaml | 5 + .../components/bmp3xx_i2c/test.esp32-idf.yaml | 5 + tests/components/bmp3xx_i2c/test.esp32.yaml | 5 + tests/components/bmp3xx_i2c/test.esp8266.yaml | 5 + tests/components/bmp3xx_i2c/test.rp2040.yaml | 5 + tests/components/bmp3xx_spi/common.yaml | 16 +++ .../bmp3xx_spi/test.esp32-c3-idf.yaml | 7 ++ .../components/bmp3xx_spi/test.esp32-c3.yaml | 7 ++ .../components/bmp3xx_spi/test.esp32-idf.yaml | 7 ++ tests/components/bmp3xx_spi/test.esp32.yaml | 7 ++ tests/components/bmp3xx_spi/test.esp8266.yaml | 7 ++ tests/components/bmp3xx_spi/test.rp2040.yaml | 7 ++ tests/test11.5.yaml | 9 -- tests/test5.yaml | 9 -- 34 files changed, 375 insertions(+), 201 deletions(-) create mode 100644 esphome/components/bmp3xx_base/__init__.py rename esphome/components/{bmp3xx/bmp3xx.cpp => bmp3xx_base/bmp3xx_base.cpp} (99%) rename esphome/components/{bmp3xx/bmp3xx.h => bmp3xx_base/bmp3xx_base.h} (94%) create mode 100644 esphome/components/bmp3xx_i2c/__init__.py create mode 100644 esphome/components/bmp3xx_i2c/bmp3xx_i2c.cpp create mode 100644 esphome/components/bmp3xx_i2c/bmp3xx_i2c.h create mode 100644 esphome/components/bmp3xx_i2c/sensor.py create mode 100644 esphome/components/bmp3xx_spi/__init__.py create mode 100644 esphome/components/bmp3xx_spi/bmp3xx_spi.cpp create mode 100644 esphome/components/bmp3xx_spi/bmp3xx_spi.h create mode 100644 esphome/components/bmp3xx_spi/sensor.py delete mode 100644 tests/components/bmp3xx/test.esp32-c3-idf.yaml delete mode 100644 tests/components/bmp3xx/test.esp32-c3.yaml delete mode 100644 tests/components/bmp3xx/test.esp32.yaml delete mode 100644 tests/components/bmp3xx/test.esp8266.yaml delete mode 100644 tests/components/bmp3xx/test.rp2040.yaml rename tests/components/{bmp3xx/test.esp32-idf.yaml => bmp3xx_i2c/common.yaml} (66%) create mode 100644 tests/components/bmp3xx_i2c/test.esp32-c3-idf.yaml create mode 100644 tests/components/bmp3xx_i2c/test.esp32-c3.yaml create mode 100644 tests/components/bmp3xx_i2c/test.esp32-idf.yaml create mode 100644 tests/components/bmp3xx_i2c/test.esp32.yaml create mode 100644 tests/components/bmp3xx_i2c/test.esp8266.yaml create mode 100644 tests/components/bmp3xx_i2c/test.rp2040.yaml create mode 100644 tests/components/bmp3xx_spi/common.yaml create mode 100644 tests/components/bmp3xx_spi/test.esp32-c3-idf.yaml create mode 100644 tests/components/bmp3xx_spi/test.esp32-c3.yaml create mode 100644 tests/components/bmp3xx_spi/test.esp32-idf.yaml create mode 100644 tests/components/bmp3xx_spi/test.esp32.yaml create mode 100644 tests/components/bmp3xx_spi/test.esp8266.yaml create mode 100644 tests/components/bmp3xx_spi/test.rp2040.yaml diff --git a/CODEOWNERS b/CODEOWNERS index d0e920fe1d..c630db7948 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -63,7 +63,10 @@ esphome/components/bme280_base/* @esphome/core esphome/components/bme280_spi/* @apbodrov esphome/components/bme680_bsec/* @trvrnrth esphome/components/bmi160/* @flaviut -esphome/components/bmp3xx/* @martgras +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/bp1658cj/* @Cossid esphome/components/bp5758d/* @Cossid diff --git a/esphome/components/bmp3xx/sensor.py b/esphome/components/bmp3xx/sensor.py index 6f90173c7b..89753768c3 100644 --- a/esphome/components/bmp3xx/sensor.py +++ b/esphome/components/bmp3xx/sensor.py @@ -1,102 +1,7 @@ -import esphome.codegen as cg import esphome.config_validation as cv -from esphome.components import i2c, sensor -from esphome.const import ( - CONF_ID, - CONF_IIR_FILTER, - CONF_OVERSAMPLING, - CONF_PRESSURE, - CONF_TEMPERATURE, - DEVICE_CLASS_PRESSURE, - DEVICE_CLASS_TEMPERATURE, - STATE_CLASS_MEASUREMENT, - UNIT_CELSIUS, - UNIT_HECTOPASCAL, + +CODEOWNERS = ["@latonita"] + +CONFIG_SCHEMA = CONFIG_SCHEMA = cv.invalid( + "The bmp3xx sensor component has been renamed to bmp3xx_i2c." ) - -CODEOWNERS = ["@martgras"] -DEPENDENCIES = ["i2c"] - -bmp3xx_ns = cg.esphome_ns.namespace("bmp3xx") -Oversampling = bmp3xx_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, -} - -IIRFilter = bmp3xx_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, -} - -BMP3XXComponent = bmp3xx_ns.class_( - "BMP3XXComponent", cg.PollingComponent, i2c.I2CDevice -) - -CONFIG_SCHEMA = ( - cv.Schema( - { - cv.GenerateID(): cv.declare_id(BMP3XXComponent), - 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="2X"): cv.enum( - OVERSAMPLING_OPTIONS, upper=True - ), - } - ), - cv.Optional(CONF_PRESSURE): sensor.sensor_schema( - unit_of_measurement=UNIT_HECTOPASCAL, - accuracy_decimals=1, - device_class=DEVICE_CLASS_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(0x77)) -) - - -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) - cg.add(var.set_iir_filter_config(config[CONF_IIR_FILTER])) - 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] - ) - ) - - 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])) diff --git a/esphome/components/bmp3xx_base/__init__.py b/esphome/components/bmp3xx_base/__init__.py new file mode 100644 index 0000000000..589d170907 --- /dev/null +++ b/esphome/components/bmp3xx_base/__init__.py @@ -0,0 +1,95 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import sensor +from esphome.const import ( + CONF_ID, + CONF_IIR_FILTER, + CONF_OVERSAMPLING, + CONF_PRESSURE, + CONF_TEMPERATURE, + DEVICE_CLASS_PRESSURE, + DEVICE_CLASS_TEMPERATURE, + STATE_CLASS_MEASUREMENT, + UNIT_CELSIUS, + UNIT_HECTOPASCAL, +) + +CODEOWNERS = ["@martgras", "@latonita"] + +bmp3xx_ns = cg.esphome_ns.namespace("bmp3xx_base") +Oversampling = bmp3xx_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, +} + +IIRFilter = bmp3xx_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, +} + + +CONFIG_SCHEMA_BASE = cv.Schema( + { + 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="2X"): cv.enum( + OVERSAMPLING_OPTIONS, upper=True + ), + } + ), + cv.Optional(CONF_PRESSURE): sensor.sensor_schema( + unit_of_measurement=UNIT_HECTOPASCAL, + accuracy_decimals=1, + device_class=DEVICE_CLASS_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) + + cg.add(var.set_iir_filter_config(config[CONF_IIR_FILTER])) + 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] + ) + ) + + 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])) + + return var diff --git a/esphome/components/bmp3xx/bmp3xx.cpp b/esphome/components/bmp3xx_base/bmp3xx_base.cpp similarity index 99% rename from esphome/components/bmp3xx/bmp3xx.cpp rename to esphome/components/bmp3xx_base/bmp3xx_base.cpp index de28fd76ff..75b6812f81 100644 --- a/esphome/components/bmp3xx/bmp3xx.cpp +++ b/esphome/components/bmp3xx_base/bmp3xx_base.cpp @@ -5,13 +5,13 @@ http://github.com/MartinL1/BMP388_DEV */ -#include "bmp3xx.h" +#include "bmp3xx_base.h" #include "esphome/core/log.h" #include "esphome/core/hal.h" #include namespace esphome { -namespace bmp3xx { +namespace bmp3xx_base { static const char *const TAG = "bmp3xx.sensor"; @@ -150,7 +150,6 @@ void BMP3XXComponent::setup() { void BMP3XXComponent::dump_config() { ESP_LOGCONFIG(TAG, "BMP3XX:"); ESP_LOGCONFIG(TAG, " Type: %s (0x%X)", LOG_STR_ARG(chip_type_to_str(this->chip_id_.reg)), this->chip_id_.reg); - LOG_I2C_DEVICE(this); switch (this->error_code_) { case NONE: break; @@ -386,5 +385,5 @@ float BMP3XXComponent::bmp388_compensate_pressure_(float uncomp_press, float t_l return partial_out1 + partial_out2 + partial_data4; } -} // namespace bmp3xx +} // namespace bmp3xx_base } // namespace esphome diff --git a/esphome/components/bmp3xx/bmp3xx.h b/esphome/components/bmp3xx_base/bmp3xx_base.h similarity index 94% rename from esphome/components/bmp3xx/bmp3xx.h rename to esphome/components/bmp3xx_base/bmp3xx_base.h index d3b15f601d..50f92e04c1 100644 --- a/esphome/components/bmp3xx/bmp3xx.h +++ b/esphome/components/bmp3xx_base/bmp3xx_base.h @@ -9,10 +9,9 @@ #include "esphome/core/component.h" #include "esphome/components/sensor/sensor.h" -#include "esphome/components/i2c/i2c.h" namespace esphome { -namespace bmp3xx { +namespace bmp3xx_base { static const uint8_t BMP388_ID = 0x50; // The BMP388 device ID static const uint8_t BMP390_ID = 0x60; // The BMP390 device ID @@ -69,8 +68,8 @@ enum IIRFilter { IIR_FILTER_128 = 0x07 }; -/// This class implements support for the BMP3XX Temperature+Pressure i2c sensor. -class BMP3XXComponent : public PollingComponent, public i2c::I2CDevice { +/// This class implements support for the BMP3XX Temperature+Pressure sensor. +class BMP3XXComponent : public PollingComponent { public: void setup() override; void dump_config() override; @@ -231,7 +230,13 @@ class BMP3XXComponent : public PollingComponent, public i2c::I2CDevice { float bmp388_compensate_temperature_(float uncomp_temp); // Bosch pressure compensation function float bmp388_compensate_pressure_(float uncomp_press, float t_lin); + + // interface specific functions + virtual bool read_byte(uint8_t a_register, uint8_t *data) = 0; + virtual bool write_byte(uint8_t a_register, uint8_t data) = 0; + virtual bool read_bytes(uint8_t a_register, uint8_t *data, size_t len) = 0; + virtual bool write_bytes(uint8_t a_register, uint8_t *data, size_t len) = 0; }; -} // namespace bmp3xx +} // namespace bmp3xx_base } // namespace esphome diff --git a/esphome/components/bmp3xx_i2c/__init__.py b/esphome/components/bmp3xx_i2c/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/bmp3xx_i2c/bmp3xx_i2c.cpp b/esphome/components/bmp3xx_i2c/bmp3xx_i2c.cpp new file mode 100644 index 0000000000..7531090185 --- /dev/null +++ b/esphome/components/bmp3xx_i2c/bmp3xx_i2c.cpp @@ -0,0 +1,29 @@ +#include "esphome/components/i2c/i2c.h" +#include "bmp3xx_i2c.h" +#include + +namespace esphome { +namespace bmp3xx_i2c { + +static const char *const TAG = "bmp3xx_i2c.sensor"; + +bool BMP3XXI2CComponent::read_byte(uint8_t a_register, uint8_t *data) { + return I2CDevice::read_byte(a_register, data); +}; +bool BMP3XXI2CComponent::write_byte(uint8_t a_register, uint8_t data) { + return I2CDevice::write_byte(a_register, data); +}; +bool BMP3XXI2CComponent::read_bytes(uint8_t a_register, uint8_t *data, size_t len) { + return I2CDevice::read_bytes(a_register, data, len); +}; +bool BMP3XXI2CComponent::write_bytes(uint8_t a_register, uint8_t *data, size_t len) { + return I2CDevice::write_bytes(a_register, data, len); +}; + +void BMP3XXI2CComponent::dump_config() { + LOG_I2C_DEVICE(this); + BMP3XXComponent::dump_config(); +} + +} // namespace bmp3xx_i2c +} // namespace esphome diff --git a/esphome/components/bmp3xx_i2c/bmp3xx_i2c.h b/esphome/components/bmp3xx_i2c/bmp3xx_i2c.h new file mode 100644 index 0000000000..d8b95cf843 --- /dev/null +++ b/esphome/components/bmp3xx_i2c/bmp3xx_i2c.h @@ -0,0 +1,17 @@ +#pragma once +#include "esphome/components/i2c/i2c.h" +#include "esphome/components/bmp3xx_base/bmp3xx_base.h" + +namespace esphome { +namespace bmp3xx_i2c { + +class BMP3XXI2CComponent : public bmp3xx_base::BMP3XXComponent, public i2c::I2CDevice { + bool read_byte(uint8_t a_register, uint8_t *data) override; + bool write_byte(uint8_t a_register, uint8_t data) override; + bool read_bytes(uint8_t a_register, uint8_t *data, size_t len) override; + bool write_bytes(uint8_t a_register, uint8_t *data, size_t len) override; + void dump_config() override; +}; + +} // namespace bmp3xx_i2c +} // namespace esphome diff --git a/esphome/components/bmp3xx_i2c/sensor.py b/esphome/components/bmp3xx_i2c/sensor.py new file mode 100644 index 0000000000..ae59d29e89 --- /dev/null +++ b/esphome/components/bmp3xx_i2c/sensor.py @@ -0,0 +1,22 @@ +import esphome.codegen as cg +from esphome.components import i2c +from ..bmp3xx_base import to_code_base, cv, CONFIG_SCHEMA_BASE + +AUTO_LOAD = ["bmp3xx_base"] +CODEOWNERS = ["@latonita"] +DEPENDENCIES = ["i2c"] + +bmp3xx_ns = cg.esphome_ns.namespace("bmp3xx_i2c") + +BMP3XXI2CComponent = bmp3xx_ns.class_( + "BMP3XXI2CComponent", cg.PollingComponent, i2c.I2CDevice +) + +CONFIG_SCHEMA = CONFIG_SCHEMA_BASE.extend( + i2c.i2c_device_schema(default_address=0x77) +).extend({cv.GenerateID(): cv.declare_id(BMP3XXI2CComponent)}) + + +async def to_code(config): + var = await to_code_base(config) + await i2c.register_i2c_device(var, config) diff --git a/esphome/components/bmp3xx_spi/__init__.py b/esphome/components/bmp3xx_spi/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/bmp3xx_spi/bmp3xx_spi.cpp b/esphome/components/bmp3xx_spi/bmp3xx_spi.cpp new file mode 100644 index 0000000000..2084530125 --- /dev/null +++ b/esphome/components/bmp3xx_spi/bmp3xx_spi.cpp @@ -0,0 +1,57 @@ +#include "bmp3xx_spi.h" +#include + +namespace esphome { +namespace bmp3xx_spi { + +static const char *const TAG = "bmp3xx_spi.sensor"; + +uint8_t set_bit(uint8_t num, int position) { + int mask = 1 << position; + return num | mask; +} + +uint8_t clear_bit(uint8_t num, int position) { + int mask = 1 << position; + return num & ~mask; +} + +void BMP3XXSPIComponent::setup() { + this->spi_setup(); + BMP3XXComponent::setup(); +} + +bool BMP3XXSPIComponent::read_byte(uint8_t a_register, uint8_t *data) { + this->enable(); + this->transfer_byte(set_bit(a_register, 7)); + *data = this->transfer_byte(0); + this->disable(); + return true; +} + +bool BMP3XXSPIComponent::write_byte(uint8_t a_register, uint8_t data) { + this->enable(); + this->transfer_byte(clear_bit(a_register, 7)); + this->transfer_byte(data); + this->disable(); + return true; +} + +bool BMP3XXSPIComponent::read_bytes(uint8_t a_register, uint8_t *data, size_t len) { + this->enable(); + this->transfer_byte(set_bit(a_register, 7)); + this->read_array(data, len); + this->disable(); + return true; +} + +bool BMP3XXSPIComponent::write_bytes(uint8_t a_register, uint8_t *data, size_t len) { + this->enable(); + this->transfer_byte(clear_bit(a_register, 7)); + this->transfer_array(data, len); + this->disable(); + return true; +} + +} // namespace bmp3xx_spi +} // namespace esphome diff --git a/esphome/components/bmp3xx_spi/bmp3xx_spi.h b/esphome/components/bmp3xx_spi/bmp3xx_spi.h new file mode 100644 index 0000000000..2183994abe --- /dev/null +++ b/esphome/components/bmp3xx_spi/bmp3xx_spi.h @@ -0,0 +1,19 @@ +#pragma once +#include "esphome/components/bmp3xx_base/bmp3xx_base.h" +#include "esphome/components/spi/spi.h" + +namespace esphome { +namespace bmp3xx_spi { + +class BMP3XXSPIComponent : public bmp3xx_base::BMP3XXComponent, + public spi::SPIDevice { + void setup() override; + bool read_byte(uint8_t a_register, uint8_t *data) override; + bool write_byte(uint8_t a_register, uint8_t data) override; + bool read_bytes(uint8_t a_register, uint8_t *data, size_t len) override; + bool write_bytes(uint8_t a_register, uint8_t *data, size_t len) override; +}; + +} // namespace bmp3xx_spi +} // namespace esphome diff --git a/esphome/components/bmp3xx_spi/sensor.py b/esphome/components/bmp3xx_spi/sensor.py new file mode 100644 index 0000000000..3d1acd3c1b --- /dev/null +++ b/esphome/components/bmp3xx_spi/sensor.py @@ -0,0 +1,22 @@ +import esphome.codegen as cg +from esphome.components import spi +from ..bmp3xx_base import to_code_base, cv, CONFIG_SCHEMA_BASE + +AUTO_LOAD = ["bmp3xx_base"] +CODEOWNERS = ["@latonita"] +DEPENDENCIES = ["spi"] + +bmp3xx_ns = cg.esphome_ns.namespace("bmp3xx_spi") + +BMP3XXSPIComponent = bmp3xx_ns.class_( + "BMP3XXSPIComponent", cg.PollingComponent, spi.SPIDevice +) + +CONFIG_SCHEMA = CONFIG_SCHEMA_BASE.extend(spi.spi_device_schema()).extend( + {cv.GenerateID(): cv.declare_id(BMP3XXSPIComponent)} +) + + +async def to_code(config): + var = await to_code_base(config) + await spi.register_spi_device(var, config) diff --git a/tests/components/bmp3xx/test.esp32-c3-idf.yaml b/tests/components/bmp3xx/test.esp32-c3-idf.yaml deleted file mode 100644 index 3b244eccf9..0000000000 --- a/tests/components/bmp3xx/test.esp32-c3-idf.yaml +++ /dev/null @@ -1,14 +0,0 @@ -i2c: - - id: i2c_bmp3xx - scl: 5 - sda: 4 - -sensor: - - platform: bmp3xx - address: 0x77 - temperature: - name: BMP Temperature - oversampling: 16x - pressure: - name: BMP Pressure - iir_filter: 2X diff --git a/tests/components/bmp3xx/test.esp32-c3.yaml b/tests/components/bmp3xx/test.esp32-c3.yaml deleted file mode 100644 index 3b244eccf9..0000000000 --- a/tests/components/bmp3xx/test.esp32-c3.yaml +++ /dev/null @@ -1,14 +0,0 @@ -i2c: - - id: i2c_bmp3xx - scl: 5 - sda: 4 - -sensor: - - platform: bmp3xx - address: 0x77 - temperature: - name: BMP Temperature - oversampling: 16x - pressure: - name: BMP Pressure - iir_filter: 2X diff --git a/tests/components/bmp3xx/test.esp32.yaml b/tests/components/bmp3xx/test.esp32.yaml deleted file mode 100644 index 677ed8a22d..0000000000 --- a/tests/components/bmp3xx/test.esp32.yaml +++ /dev/null @@ -1,14 +0,0 @@ -i2c: - - id: i2c_bmp3xx - scl: 16 - sda: 17 - -sensor: - - platform: bmp3xx - address: 0x77 - temperature: - name: BMP Temperature - oversampling: 16x - pressure: - name: BMP Pressure - iir_filter: 2X diff --git a/tests/components/bmp3xx/test.esp8266.yaml b/tests/components/bmp3xx/test.esp8266.yaml deleted file mode 100644 index 3b244eccf9..0000000000 --- a/tests/components/bmp3xx/test.esp8266.yaml +++ /dev/null @@ -1,14 +0,0 @@ -i2c: - - id: i2c_bmp3xx - scl: 5 - sda: 4 - -sensor: - - platform: bmp3xx - address: 0x77 - temperature: - name: BMP Temperature - oversampling: 16x - pressure: - name: BMP Pressure - iir_filter: 2X diff --git a/tests/components/bmp3xx/test.rp2040.yaml b/tests/components/bmp3xx/test.rp2040.yaml deleted file mode 100644 index 3b244eccf9..0000000000 --- a/tests/components/bmp3xx/test.rp2040.yaml +++ /dev/null @@ -1,14 +0,0 @@ -i2c: - - id: i2c_bmp3xx - scl: 5 - sda: 4 - -sensor: - - platform: bmp3xx - address: 0x77 - temperature: - name: BMP Temperature - oversampling: 16x - pressure: - name: BMP Pressure - iir_filter: 2X diff --git a/tests/components/bmp3xx/test.esp32-idf.yaml b/tests/components/bmp3xx_i2c/common.yaml similarity index 66% rename from tests/components/bmp3xx/test.esp32-idf.yaml rename to tests/components/bmp3xx_i2c/common.yaml index 677ed8a22d..6641b7a1b8 100644 --- a/tests/components/bmp3xx/test.esp32-idf.yaml +++ b/tests/components/bmp3xx_i2c/common.yaml @@ -1,10 +1,11 @@ i2c: - id: i2c_bmp3xx - scl: 16 - sda: 17 + scl: ${scl_pin} + sda: ${sda_pin} sensor: - - platform: bmp3xx + - platform: bmp3xx_i2c + i2c_id: i2c_bmp3xx address: 0x77 temperature: name: BMP Temperature diff --git a/tests/components/bmp3xx_i2c/test.esp32-c3-idf.yaml b/tests/components/bmp3xx_i2c/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/bmp3xx_i2c/test.esp32-c3-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/bmp3xx_i2c/test.esp32-c3.yaml b/tests/components/bmp3xx_i2c/test.esp32-c3.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/bmp3xx_i2c/test.esp32-c3.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/bmp3xx_i2c/test.esp32-idf.yaml b/tests/components/bmp3xx_i2c/test.esp32-idf.yaml new file mode 100644 index 0000000000..63c3bd6afd --- /dev/null +++ b/tests/components/bmp3xx_i2c/test.esp32-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO16 + sda_pin: GPIO17 + +<<: !include common.yaml diff --git a/tests/components/bmp3xx_i2c/test.esp32.yaml b/tests/components/bmp3xx_i2c/test.esp32.yaml new file mode 100644 index 0000000000..63c3bd6afd --- /dev/null +++ b/tests/components/bmp3xx_i2c/test.esp32.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO16 + sda_pin: GPIO17 + +<<: !include common.yaml diff --git a/tests/components/bmp3xx_i2c/test.esp8266.yaml b/tests/components/bmp3xx_i2c/test.esp8266.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/bmp3xx_i2c/test.esp8266.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/bmp3xx_i2c/test.rp2040.yaml b/tests/components/bmp3xx_i2c/test.rp2040.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/bmp3xx_i2c/test.rp2040.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/bmp3xx_spi/common.yaml b/tests/components/bmp3xx_spi/common.yaml new file mode 100644 index 0000000000..8d5f897661 --- /dev/null +++ b/tests/components/bmp3xx_spi/common.yaml @@ -0,0 +1,16 @@ +spi: + - id: spi_bmp3xx + clk_pin: ${clk_pin} + mosi_pin: ${mosi_pin} + miso_pin: ${miso_pin} + +sensor: + - platform: bmp3xx_spi + spi_id: spi_bmp3xx + cs_pin: ${cs_pin} + temperature: + name: BMP Temperature + oversampling: 16x + pressure: + name: BMP Pressure + iir_filter: 2X diff --git a/tests/components/bmp3xx_spi/test.esp32-c3-idf.yaml b/tests/components/bmp3xx_spi/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..2415ba5dc6 --- /dev/null +++ b/tests/components/bmp3xx_spi/test.esp32-c3-idf.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO6 + mosi_pin: GPIO7 + miso_pin: GPIO5 + cs_pin: GPIO8 + +<<: !include common.yaml diff --git a/tests/components/bmp3xx_spi/test.esp32-c3.yaml b/tests/components/bmp3xx_spi/test.esp32-c3.yaml new file mode 100644 index 0000000000..2415ba5dc6 --- /dev/null +++ b/tests/components/bmp3xx_spi/test.esp32-c3.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO6 + mosi_pin: GPIO7 + miso_pin: GPIO5 + cs_pin: GPIO8 + +<<: !include common.yaml diff --git a/tests/components/bmp3xx_spi/test.esp32-idf.yaml b/tests/components/bmp3xx_spi/test.esp32-idf.yaml new file mode 100644 index 0000000000..54e027a614 --- /dev/null +++ b/tests/components/bmp3xx_spi/test.esp32-idf.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO16 + mosi_pin: GPIO17 + miso_pin: GPIO15 + cs_pin: GPIO5 + +<<: !include common.yaml diff --git a/tests/components/bmp3xx_spi/test.esp32.yaml b/tests/components/bmp3xx_spi/test.esp32.yaml new file mode 100644 index 0000000000..54e027a614 --- /dev/null +++ b/tests/components/bmp3xx_spi/test.esp32.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO16 + mosi_pin: GPIO17 + miso_pin: GPIO15 + cs_pin: GPIO5 + +<<: !include common.yaml diff --git a/tests/components/bmp3xx_spi/test.esp8266.yaml b/tests/components/bmp3xx_spi/test.esp8266.yaml new file mode 100644 index 0000000000..dbd158d030 --- /dev/null +++ b/tests/components/bmp3xx_spi/test.esp8266.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO14 + mosi_pin: GPIO13 + miso_pin: GPIO12 + cs_pin: GPIO15 + +<<: !include common.yaml diff --git a/tests/components/bmp3xx_spi/test.rp2040.yaml b/tests/components/bmp3xx_spi/test.rp2040.yaml new file mode 100644 index 0000000000..f6c3f1eeca --- /dev/null +++ b/tests/components/bmp3xx_spi/test.rp2040.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO2 + mosi_pin: GPIO3 + miso_pin: GPIO4 + cs_pin: GPIO5 + +<<: !include common.yaml diff --git a/tests/test11.5.yaml b/tests/test11.5.yaml index ef260d79c0..13de7f1929 100644 --- a/tests/test11.5.yaml +++ b/tests/test11.5.yaml @@ -498,15 +498,6 @@ sensor: co2: name: CO2 Sensor - - platform: bmp3xx - temperature: - name: BMP Temperature - oversampling: 16x - pressure: - name: BMP Pressure - address: 0x77 - iir_filter: 2X - - platform: sen5x id: sen54 temperature: diff --git a/tests/test5.yaml b/tests/test5.yaml index 81615b24b0..afd3359098 100644 --- a/tests/test5.yaml +++ b/tests/test5.yaml @@ -474,15 +474,6 @@ sensor: co2: name: CO2 Sensor - - platform: bmp3xx - temperature: - name: BMP Temperature - oversampling: 16x - pressure: - name: BMP Pressure - address: 0x77 - iir_filter: 2X - - platform: ms8607 temperature: name: Temperature From ccbf5148aac29dade376483084bf7c092f613e35 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Sun, 5 May 2024 17:32:47 +1200 Subject: [PATCH 1369/2101] Set "CONF_" CI counter to fail on 3 or more definitions (#6668) --- esphome/components/ade7880/sensor.py | 2 +- esphome/components/ade7953_base/__init__.py | 2 +- esphome/components/at581x/__init__.py | 1 - esphome/components/bl0940/sensor.py | 2 +- esphome/components/bme680_bsec/__init__.py | 3 +-- esphome/components/cs5460a/sensor.py | 2 +- esphome/components/daikin_brc/climate.py | 3 +-- .../components/dfrobot_sen0395/__init__.py | 4 +--- esphome/components/emc2101/sensor/__init__.py | 2 +- esphome/components/ens160/sensor.py | 2 +- esphome/components/esp32_ble/__init__.py | 3 +-- esphome/components/esp32_camera/__init__.py | 2 +- .../graphical_display_menu/__init__.py | 3 +-- esphome/components/haier/climate.py | 4 ++-- esphome/components/haier/sensor/__init__.py | 2 +- esphome/components/hmc5883l/sensor.py | 2 +- esphome/components/inkplate6/display.py | 2 +- esphome/components/kmeteriso/sensor.py | 2 +- esphome/components/ld2410/binary_sensor.py | 6 +++--- esphome/components/ld2410/button/__init__.py | 4 ++-- .../ld2420/binary_sensor/__init__.py | 3 +-- esphome/components/ld2420/button/__init__.py | 2 +- esphome/components/mcp3008/sensor/__init__.py | 2 +- esphome/components/mcp3204/__init__.py | 3 +-- esphome/components/midea/climate.py | 2 +- esphome/components/midea_ir/climate.py | 3 +-- esphome/components/mmc5603/sensor.py | 3 +-- esphome/components/pn532/__init__.py | 9 ++++++-- esphome/components/pn7150/__init__.py | 4 ++-- esphome/components/pn7160/__init__.py | 4 ++-- esphome/components/power_supply/__init__.py | 10 ++++++--- esphome/components/qmc5883l/sensor.py | 3 +-- esphome/components/resistance/sensor.py | 2 +- esphome/components/rpi_dpi_rgb/display.py | 4 ++-- esphome/components/scd30/sensor.py | 2 +- esphome/components/scd4x/sensor.py | 2 +- esphome/components/script/__init__.py | 3 +-- .../seeed_mr24hpc1/binary_sensor.py | 2 +- .../seeed_mr24hpc1/button/__init__.py | 2 +- .../seeed_mr24hpc1/number/__init__.py | 2 +- esphome/components/sgp30/sensor.py | 2 +- esphome/components/sgp4x/sensor.py | 2 +- esphome/components/sim800l/__init__.py | 2 +- esphome/components/sn74hc595/__init__.py | 2 +- esphome/components/st7701s/display.py | 4 ++-- esphome/components/tlc5947/__init__.py | 2 +- esphome/components/touchscreen/__init__.py | 2 +- esphome/components/whynter/climate.py | 3 +-- esphome/components/wifi/__init__.py | 2 +- esphome/components/wireguard/__init__.py | 2 ++ esphome/components/wireguard/binary_sensor.py | 3 +-- esphome/components/wireguard/sensor.py | 3 +-- esphome/components/wireguard/text_sensor.py | 4 +--- esphome/const.py | 21 +++++++++++++++++++ script/ci-custom.py | 2 +- 55 files changed, 95 insertions(+), 81 deletions(-) diff --git a/esphome/components/ade7880/sensor.py b/esphome/components/ade7880/sensor.py index 42a2b0d3fc..e075adb04c 100644 --- a/esphome/components/ade7880/sensor.py +++ b/esphome/components/ade7880/sensor.py @@ -19,6 +19,7 @@ from esphome.const import ( CONF_RESET_PIN, CONF_REVERSE_ACTIVE_ENERGY, CONF_VOLTAGE, + CONF_VOLTAGE_GAIN, DEVICE_CLASS_APPARENT_POWER, DEVICE_CLASS_CURRENT, DEVICE_CLASS_ENERGY, @@ -47,7 +48,6 @@ CONF_CURRENT_GAIN = "current_gain" CONF_IRQ0_PIN = "irq0_pin" CONF_IRQ1_PIN = "irq1_pin" CONF_POWER_GAIN = "power_gain" -CONF_VOLTAGE_GAIN = "voltage_gain" CONF_NEUTRAL = "neutral" diff --git a/esphome/components/ade7953_base/__init__.py b/esphome/components/ade7953_base/__init__.py index 28014ef142..af3f629ca8 100644 --- a/esphome/components/ade7953_base/__init__.py +++ b/esphome/components/ade7953_base/__init__.py @@ -6,6 +6,7 @@ from esphome.const import ( CONF_IRQ_PIN, CONF_VOLTAGE, CONF_FREQUENCY, + CONF_VOLTAGE_GAIN, DEVICE_CLASS_CURRENT, DEVICE_CLASS_APPARENT_POWER, DEVICE_CLASS_POWER, @@ -36,7 +37,6 @@ CONF_POWER_FACTOR_B = "power_factor_b" CONF_VOLTAGE_PGA_GAIN = "voltage_pga_gain" CONF_CURRENT_PGA_GAIN_A = "current_pga_gain_a" CONF_CURRENT_PGA_GAIN_B = "current_pga_gain_b" -CONF_VOLTAGE_GAIN = "voltage_gain" CONF_CURRENT_GAIN_A = "current_gain_a" CONF_CURRENT_GAIN_B = "current_gain_b" CONF_ACTIVE_POWER_GAIN_A = "active_power_gain_a" diff --git a/esphome/components/at581x/__init__.py b/esphome/components/at581x/__init__.py index 2860d21f6c..e636510a4b 100644 --- a/esphome/components/at581x/__init__.py +++ b/esphome/components/at581x/__init__.py @@ -22,7 +22,6 @@ CONF_AT581X_ID = "at581x_id" CONF_SENSING_DISTANCE = "sensing_distance" -CONF_SENSITIVITY = "sensitivity" CONF_POWERON_SELFCHECK_TIME = "poweron_selfcheck_time" CONF_PROTECT_TIME = "protect_time" CONF_TRIGGER_BASE = "trigger_base" diff --git a/esphome/components/bl0940/sensor.py b/esphome/components/bl0940/sensor.py index fc2b04f976..5cb1472d76 100644 --- a/esphome/components/bl0940/sensor.py +++ b/esphome/components/bl0940/sensor.py @@ -6,6 +6,7 @@ from esphome.const import ( CONF_ENERGY, CONF_EXTERNAL_TEMPERATURE, CONF_ID, + CONF_INTERNAL_TEMPERATURE, CONF_POWER, CONF_VOLTAGE, DEVICE_CLASS_CURRENT, @@ -24,7 +25,6 @@ from esphome.const import ( DEPENDENCIES = ["uart"] -CONF_INTERNAL_TEMPERATURE = "internal_temperature" bl0940_ns = cg.esphome_ns.namespace("bl0940") BL0940 = bl0940_ns.class_("BL0940", cg.PollingComponent, uart.UARTDevice) diff --git a/esphome/components/bme680_bsec/__init__.py b/esphome/components/bme680_bsec/__init__.py index 15c17f4064..62ab50b8f7 100644 --- a/esphome/components/bme680_bsec/__init__.py +++ b/esphome/components/bme680_bsec/__init__.py @@ -1,7 +1,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import i2c, esp32 -from esphome.const import CONF_ID +from esphome.const import CONF_ID, CONF_TEMPERATURE_OFFSET CODEOWNERS = ["@trvrnrth"] DEPENDENCIES = ["i2c"] @@ -9,7 +9,6 @@ AUTO_LOAD = ["sensor", "text_sensor"] MULTI_CONF = True CONF_BME680_BSEC_ID = "bme680_bsec_id" -CONF_TEMPERATURE_OFFSET = "temperature_offset" CONF_IAQ_MODE = "iaq_mode" CONF_SUPPLY_VOLTAGE = "supply_voltage" CONF_SAMPLE_RATE = "sample_rate" diff --git a/esphome/components/cs5460a/sensor.py b/esphome/components/cs5460a/sensor.py index c27fc5fc3c..d8219e1df1 100644 --- a/esphome/components/cs5460a/sensor.py +++ b/esphome/components/cs5460a/sensor.py @@ -6,6 +6,7 @@ from esphome.const import ( CONF_ID, CONF_POWER, CONF_VOLTAGE, + CONF_VOLTAGE_GAIN, UNIT_VOLT, UNIT_AMPERE, UNIT_WATT, @@ -33,7 +34,6 @@ CONF_SAMPLES = "samples" CONF_PHASE_OFFSET = "phase_offset" CONF_PGA_GAIN = "pga_gain" CONF_CURRENT_GAIN = "current_gain" -CONF_VOLTAGE_GAIN = "voltage_gain" CONF_CURRENT_HPF = "current_hpf" CONF_VOLTAGE_HPF = "voltage_hpf" CONF_PULSE_ENERGY = "pulse_energy" diff --git a/esphome/components/daikin_brc/climate.py b/esphome/components/daikin_brc/climate.py index 3468b6533c..7a5bd9b14d 100644 --- a/esphome/components/daikin_brc/climate.py +++ b/esphome/components/daikin_brc/climate.py @@ -1,14 +1,13 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import climate_ir -from esphome.const import CONF_ID +from esphome.const import CONF_ID, CONF_USE_FAHRENHEIT AUTO_LOAD = ["climate_ir"] daikin_brc_ns = cg.esphome_ns.namespace("daikin_brc") DaikinBrcClimate = daikin_brc_ns.class_("DaikinBrcClimate", climate_ir.ClimateIR) -CONF_USE_FAHRENHEIT = "use_fahrenheit" CONFIG_SCHEMA = climate_ir.CLIMATE_IR_WITH_RECEIVER_SCHEMA.extend( { diff --git a/esphome/components/dfrobot_sen0395/__init__.py b/esphome/components/dfrobot_sen0395/__init__.py index 2197ee5ef8..39787ca66b 100644 --- a/esphome/components/dfrobot_sen0395/__init__.py +++ b/esphome/components/dfrobot_sen0395/__init__.py @@ -2,7 +2,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation from esphome.automation import maybe_simple_id -from esphome.const import CONF_ID +from esphome.const import CONF_FACTORY_RESET, CONF_ID, CONF_SENSITIVITY from esphome.components import uart CODEOWNERS = ["@niklasweber"] @@ -28,8 +28,6 @@ CONF_DELAY_AFTER_DETECT = "delay_after_detect" CONF_DELAY_AFTER_DISAPPEAR = "delay_after_disappear" CONF_DETECTION_SEGMENTS = "detection_segments" CONF_OUTPUT_LATENCY = "output_latency" -CONF_FACTORY_RESET = "factory_reset" -CONF_SENSITIVITY = "sensitivity" CONFIG_SCHEMA = cv.All( cv.Schema( diff --git a/esphome/components/emc2101/sensor/__init__.py b/esphome/components/emc2101/sensor/__init__.py index 9f3fbdce00..10ea3dfae6 100644 --- a/esphome/components/emc2101/sensor/__init__.py +++ b/esphome/components/emc2101/sensor/__init__.py @@ -4,6 +4,7 @@ from esphome.components import sensor from esphome.const import ( CONF_EXTERNAL_TEMPERATURE, CONF_ID, + CONF_INTERNAL_TEMPERATURE, CONF_SPEED, DEVICE_CLASS_TEMPERATURE, STATE_CLASS_MEASUREMENT, @@ -16,7 +17,6 @@ from .. import EMC2101_COMPONENT_SCHEMA, CONF_EMC2101_ID, emc2101_ns DEPENDENCIES = ["emc2101"] -CONF_INTERNAL_TEMPERATURE = "internal_temperature" CONF_DUTY_CYCLE = "duty_cycle" EMC2101Sensor = emc2101_ns.class_("EMC2101Sensor", cg.PollingComponent) diff --git a/esphome/components/ens160/sensor.py b/esphome/components/ens160/sensor.py index 393b63bae1..6572c4e397 100644 --- a/esphome/components/ens160/sensor.py +++ b/esphome/components/ens160/sensor.py @@ -2,6 +2,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import i2c, sensor from esphome.const import ( + CONF_COMPENSATION, CONF_ECO2, CONF_HUMIDITY, CONF_ID, @@ -27,7 +28,6 @@ ENS160Component = ens160_ns.class_( ) CONF_AQI = "aqi" -CONF_COMPENSATION = "compensation" UNIT_INDEX = "index" CONFIG_SCHEMA = ( diff --git a/esphome/components/esp32_ble/__init__.py b/esphome/components/esp32_ble/__init__.py index 088a3b6d1e..d88161e3e0 100644 --- a/esphome/components/esp32_ble/__init__.py +++ b/esphome/components/esp32_ble/__init__.py @@ -1,7 +1,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation -from esphome.const import CONF_ID +from esphome.const import CONF_ENABLE_ON_BOOT, CONF_ID from esphome.core import CORE from esphome.components.esp32 import add_idf_sdkconfig_option, get_esp32_variant, const @@ -11,7 +11,6 @@ CONFLICTS_WITH = ["esp32_ble_beacon"] CONF_BLE_ID = "ble_id" CONF_IO_CAPABILITY = "io_capability" -CONF_ENABLE_ON_BOOT = "enable_on_boot" NO_BLUETOOTH_VARIANTS = [const.VARIANT_ESP32S2] diff --git a/esphome/components/esp32_camera/__init__.py b/esphome/components/esp32_camera/__init__.py index ee8a889f4c..462900d401 100644 --- a/esphome/components/esp32_camera/__init__.py +++ b/esphome/components/esp32_camera/__init__.py @@ -14,6 +14,7 @@ from esphome.const import ( CONF_BRIGHTNESS, CONF_CONTRAST, CONF_TRIGGER_ID, + CONF_VSYNC_PIN, ) from esphome.core import CORE from esphome.components.esp32 import add_idf_sdkconfig_option @@ -112,7 +113,6 @@ ENUM_SPECIAL_EFFECT = { } # pin assignment -CONF_VSYNC_PIN = "vsync_pin" CONF_HREF_PIN = "href_pin" CONF_PIXEL_CLOCK_PIN = "pixel_clock_pin" CONF_EXTERNAL_CLOCK = "external_clock" diff --git a/esphome/components/graphical_display_menu/__init__.py b/esphome/components/graphical_display_menu/__init__.py index 3849449523..1b3ed7f8cd 100644 --- a/esphome/components/graphical_display_menu/__init__.py +++ b/esphome/components/graphical_display_menu/__init__.py @@ -1,7 +1,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import display, font, color -from esphome.const import CONF_ID, CONF_TRIGGER_ID +from esphome.const import CONF_DISPLAY, CONF_ID, CONF_TRIGGER_ID from esphome import automation, core from esphome.components.display_menu_base import ( @@ -10,7 +10,6 @@ from esphome.components.display_menu_base import ( display_menu_to_code, ) -CONF_DISPLAY = "display" CONF_FONT = "font" CONF_MENU_ITEM_VALUE = "menu_item_value" CONF_FOREGROUND_COLOR = "foreground_color" diff --git a/esphome/components/haier/climate.py b/esphome/components/haier/climate.py index a700be8be2..b16244fd90 100644 --- a/esphome/components/haier/climate.py +++ b/esphome/components/haier/climate.py @@ -6,12 +6,14 @@ from esphome.components import uart, climate, logger from esphome import automation from esphome.const import ( CONF_BEEPER, + CONF_DISPLAY, CONF_ID, CONF_LEVEL, CONF_LOGGER, CONF_LOGS, CONF_MAX_TEMPERATURE, CONF_MIN_TEMPERATURE, + CONF_OUTDOOR_TEMPERATURE, CONF_PROTOCOL, CONF_SUPPORTED_MODES, CONF_SUPPORTED_PRESETS, @@ -43,11 +45,9 @@ CONF_ALTERNATIVE_SWING_CONTROL = "alternative_swing_control" CONF_ANSWER_TIMEOUT = "answer_timeout" CONF_CONTROL_METHOD = "control_method" CONF_CONTROL_PACKET_SIZE = "control_packet_size" -CONF_DISPLAY = "display" CONF_HORIZONTAL_AIRFLOW = "horizontal_airflow" CONF_ON_ALARM_START = "on_alarm_start" CONF_ON_ALARM_END = "on_alarm_end" -CONF_OUTDOOR_TEMPERATURE = "outdoor_temperature" CONF_VERTICAL_AIRFLOW = "vertical_airflow" CONF_WIFI_SIGNAL = "wifi_signal" diff --git a/esphome/components/haier/sensor/__init__.py b/esphome/components/haier/sensor/__init__.py index 9a4965493d..01f997baa5 100644 --- a/esphome/components/haier/sensor/__init__.py +++ b/esphome/components/haier/sensor/__init__.py @@ -2,6 +2,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import sensor from esphome.const import ( + CONF_OUTDOOR_TEMPERATURE, CONF_POWER, CONF_HUMIDITY, DEVICE_CLASS_CURRENT, @@ -41,7 +42,6 @@ CONF_OUTDOOR_COIL_TEMPERATURE = "outdoor_coil_temperature" CONF_OUTDOOR_DEFROST_TEMPERATURE = "outdoor_defrost_temperature" CONF_OUTDOOR_IN_AIR_TEMPERATURE = "outdoor_in_air_temperature" CONF_OUTDOOR_OUT_AIR_TEMPERATURE = "outdoor_out_air_temperature" -CONF_OUTDOOR_TEMPERATURE = "outdoor_temperature" # Additional icons ICON_SNOWFLAKE_THERMOMETER = "mdi:snowflake-thermometer" diff --git a/esphome/components/hmc5883l/sensor.py b/esphome/components/hmc5883l/sensor.py index 7edd13965e..f2decea150 100644 --- a/esphome/components/hmc5883l/sensor.py +++ b/esphome/components/hmc5883l/sensor.py @@ -6,6 +6,7 @@ from esphome.const import ( CONF_FIELD_STRENGTH_X, CONF_FIELD_STRENGTH_Y, CONF_FIELD_STRENGTH_Z, + CONF_HEADING, CONF_ID, CONF_OVERSAMPLING, CONF_RANGE, @@ -21,7 +22,6 @@ DEPENDENCIES = ["i2c"] hmc5883l_ns = cg.esphome_ns.namespace("hmc5883l") -CONF_HEADING = "heading" HMC5883LComponent = hmc5883l_ns.class_( "HMC5883LComponent", cg.PollingComponent, i2c.I2CDevice diff --git a/esphome/components/inkplate6/display.py b/esphome/components/inkplate6/display.py index bcd9580448..58a146d2fd 100644 --- a/esphome/components/inkplate6/display.py +++ b/esphome/components/inkplate6/display.py @@ -7,6 +7,7 @@ from esphome.const import ( CONF_ID, CONF_LAMBDA, CONF_MODEL, + CONF_OE_PIN, CONF_PAGES, CONF_WAKEUP_PIN, ) @@ -29,7 +30,6 @@ CONF_GREYSCALE = "greyscale" CONF_GMOD_PIN = "gmod_pin" CONF_GPIO0_ENABLE_PIN = "gpio0_enable_pin" CONF_LE_PIN = "le_pin" -CONF_OE_PIN = "oe_pin" CONF_PARTIAL_UPDATING = "partial_updating" CONF_POWERUP_PIN = "powerup_pin" CONF_SPH_PIN = "sph_pin" diff --git a/esphome/components/kmeteriso/sensor.py b/esphome/components/kmeteriso/sensor.py index e730e446ae..082a055701 100644 --- a/esphome/components/kmeteriso/sensor.py +++ b/esphome/components/kmeteriso/sensor.py @@ -3,6 +3,7 @@ import esphome.config_validation as cv from esphome.components import i2c, sensor from esphome.const import ( CONF_ID, + CONF_INTERNAL_TEMPERATURE, CONF_TEMPERATURE, DEVICE_CLASS_TEMPERATURE, STATE_CLASS_MEASUREMENT, @@ -10,7 +11,6 @@ from esphome.const import ( ENTITY_CATEGORY_DIAGNOSTIC, ) -CONF_INTERNAL_TEMPERATURE = "internal_temperature" DEPENDENCIES = ["i2c"] kmeteriso_ns = cg.esphome_ns.namespace("kmeteriso") diff --git a/esphome/components/ld2410/binary_sensor.py b/esphome/components/ld2410/binary_sensor.py index 3057480d25..e00ab93be2 100644 --- a/esphome/components/ld2410/binary_sensor.py +++ b/esphome/components/ld2410/binary_sensor.py @@ -8,13 +8,13 @@ from esphome.const import ( ENTITY_CATEGORY_DIAGNOSTIC, ICON_MOTION_SENSOR, ICON_ACCOUNT, + CONF_HAS_TARGET, + CONF_HAS_MOVING_TARGET, + CONF_HAS_STILL_TARGET, ) from . import CONF_LD2410_ID, LD2410Component DEPENDENCIES = ["ld2410"] -CONF_HAS_TARGET = "has_target" -CONF_HAS_MOVING_TARGET = "has_moving_target" -CONF_HAS_STILL_TARGET = "has_still_target" CONF_OUT_PIN_PRESENCE_STATUS = "out_pin_presence_status" CONFIG_SCHEMA = { diff --git a/esphome/components/ld2410/button/__init__.py b/esphome/components/ld2410/button/__init__.py index 3567114c2c..34b18e8bdd 100644 --- a/esphome/components/ld2410/button/__init__.py +++ b/esphome/components/ld2410/button/__init__.py @@ -2,6 +2,8 @@ import esphome.codegen as cg from esphome.components import button import esphome.config_validation as cv from esphome.const import ( + CONF_FACTORY_RESET, + CONF_RESTART, DEVICE_CLASS_RESTART, ENTITY_CATEGORY_DIAGNOSTIC, ENTITY_CATEGORY_CONFIG, @@ -15,8 +17,6 @@ QueryButton = ld2410_ns.class_("QueryButton", button.Button) ResetButton = ld2410_ns.class_("ResetButton", button.Button) RestartButton = ld2410_ns.class_("RestartButton", button.Button) -CONF_FACTORY_RESET = "factory_reset" -CONF_RESTART = "restart" CONF_QUERY_PARAMS = "query_params" CONFIG_SCHEMA = { diff --git a/esphome/components/ld2420/binary_sensor/__init__.py b/esphome/components/ld2420/binary_sensor/__init__.py index f94e4d969f..43e22d0348 100644 --- a/esphome/components/ld2420/binary_sensor/__init__.py +++ b/esphome/components/ld2420/binary_sensor/__init__.py @@ -1,14 +1,13 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import binary_sensor -from esphome.const import CONF_ID, DEVICE_CLASS_OCCUPANCY +from esphome.const import CONF_ID, DEVICE_CLASS_OCCUPANCY, CONF_HAS_TARGET from .. import ld2420_ns, LD2420Component, CONF_LD2420_ID LD2420BinarySensor = ld2420_ns.class_( "LD2420BinarySensor", binary_sensor.BinarySensor, cg.Component ) -CONF_HAS_TARGET = "has_target" CONFIG_SCHEMA = cv.All( cv.COMPONENT_SCHEMA.extend( diff --git a/esphome/components/ld2420/button/__init__.py b/esphome/components/ld2420/button/__init__.py index 675e041dd4..df774ad7bc 100644 --- a/esphome/components/ld2420/button/__init__.py +++ b/esphome/components/ld2420/button/__init__.py @@ -2,6 +2,7 @@ import esphome.codegen as cg from esphome.components import button import esphome.config_validation as cv from esphome.const import ( + CONF_FACTORY_RESET, DEVICE_CLASS_RESTART, ENTITY_CATEGORY_DIAGNOSTIC, ENTITY_CATEGORY_CONFIG, @@ -19,7 +20,6 @@ LD2420FactoryResetButton = ld2420_ns.class_("LD2420FactoryResetButton", button.B CONF_APPLY_CONFIG = "apply_config" CONF_REVERT_CONFIG = "revert_config" CONF_RESTART_MODULE = "restart_module" -CONF_FACTORY_RESET = "factory_reset" CONFIG_SCHEMA = { diff --git a/esphome/components/mcp3008/sensor/__init__.py b/esphome/components/mcp3008/sensor/__init__.py index c56965d517..8ae00ef29e 100644 --- a/esphome/components/mcp3008/sensor/__init__.py +++ b/esphome/components/mcp3008/sensor/__init__.py @@ -4,6 +4,7 @@ from esphome.components import sensor, voltage_sampler from esphome.const import ( CONF_ID, CONF_NUMBER, + CONF_REFERENCE_VOLTAGE, UNIT_VOLT, STATE_CLASS_MEASUREMENT, DEVICE_CLASS_VOLTAGE, @@ -22,7 +23,6 @@ MCP3008Sensor = mcp3008_ns.class_( voltage_sampler.VoltageSampler, cg.Parented.template(MCP3008), ) -CONF_REFERENCE_VOLTAGE = "reference_voltage" CONF_MCP3008_ID = "mcp3008_id" CONFIG_SCHEMA = ( diff --git a/esphome/components/mcp3204/__init__.py b/esphome/components/mcp3204/__init__.py index 0536166e56..98129fc389 100644 --- a/esphome/components/mcp3204/__init__.py +++ b/esphome/components/mcp3204/__init__.py @@ -1,7 +1,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import spi -from esphome.const import CONF_ID +from esphome.const import CONF_ID, CONF_REFERENCE_VOLTAGE DEPENDENCIES = ["spi"] MULTI_CONF = True @@ -10,7 +10,6 @@ CODEOWNERS = ["@rsumner"] mcp3204_ns = cg.esphome_ns.namespace("mcp3204") MCP3204 = mcp3204_ns.class_("MCP3204", cg.Component, spi.SPIDevice) -CONF_REFERENCE_VOLTAGE = "reference_voltage" CONFIG_SCHEMA = cv.Schema( { diff --git a/esphome/components/midea/climate.py b/esphome/components/midea/climate.py index 074ab8abb2..83540a061a 100644 --- a/esphome/components/midea/climate.py +++ b/esphome/components/midea/climate.py @@ -11,6 +11,7 @@ from esphome.const import ( CONF_CUSTOM_PRESETS, CONF_ID, CONF_NUM_ATTEMPTS, + CONF_OUTDOOR_TEMPERATURE, CONF_PERIOD, CONF_SUPPORTED_MODES, CONF_SUPPORTED_PRESETS, @@ -37,7 +38,6 @@ from esphome.components.climate import ( CODEOWNERS = ["@dudanov"] DEPENDENCIES = ["climate", "uart"] AUTO_LOAD = ["sensor"] -CONF_OUTDOOR_TEMPERATURE = "outdoor_temperature" CONF_POWER_USAGE = "power_usage" CONF_HUMIDITY_SETPOINT = "humidity_setpoint" midea_ac_ns = cg.esphome_ns.namespace("midea").namespace("ac") diff --git a/esphome/components/midea_ir/climate.py b/esphome/components/midea_ir/climate.py index 140e4ee4e0..8fea6b192b 100644 --- a/esphome/components/midea_ir/climate.py +++ b/esphome/components/midea_ir/climate.py @@ -1,7 +1,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import climate_ir -from esphome.const import CONF_ID +from esphome.const import CONF_ID, CONF_USE_FAHRENHEIT AUTO_LOAD = ["climate_ir", "coolix"] CODEOWNERS = ["@dudanov"] @@ -9,7 +9,6 @@ CODEOWNERS = ["@dudanov"] midea_ir_ns = cg.esphome_ns.namespace("midea_ir") MideaIR = midea_ir_ns.class_("MideaIR", climate_ir.ClimateIR) -CONF_USE_FAHRENHEIT = "use_fahrenheit" CONFIG_SCHEMA = climate_ir.CLIMATE_IR_WITH_RECEIVER_SCHEMA.extend( { diff --git a/esphome/components/mmc5603/sensor.py b/esphome/components/mmc5603/sensor.py index db4e5cbf26..cf16132470 100644 --- a/esphome/components/mmc5603/sensor.py +++ b/esphome/components/mmc5603/sensor.py @@ -6,6 +6,7 @@ from esphome.const import ( CONF_FIELD_STRENGTH_X, CONF_FIELD_STRENGTH_Y, CONF_FIELD_STRENGTH_Z, + CONF_HEADING, CONF_ID, ICON_MAGNET, STATE_CLASS_MEASUREMENT, @@ -19,8 +20,6 @@ DEPENDENCIES = ["i2c"] mmc5603_ns = cg.esphome_ns.namespace("mmc5603") -CONF_HEADING = "heading" - MMC5603Component = mmc5603_ns.class_( "MMC5603Component", cg.PollingComponent, i2c.I2CDevice ) diff --git a/esphome/components/pn532/__init__.py b/esphome/components/pn532/__init__.py index 2f120bc983..cdcaf4267c 100644 --- a/esphome/components/pn532/__init__.py +++ b/esphome/components/pn532/__init__.py @@ -2,14 +2,19 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation from esphome.components import nfc -from esphome.const import CONF_ID, CONF_ON_TAG_REMOVED, CONF_ON_TAG, CONF_TRIGGER_ID +from esphome.const import ( + CONF_ID, + CONF_ON_FINISHED_WRITE, + CONF_ON_TAG_REMOVED, + CONF_ON_TAG, + CONF_TRIGGER_ID, +) CODEOWNERS = ["@OttoWinter", "@jesserockz"] AUTO_LOAD = ["binary_sensor", "nfc"] MULTI_CONF = True CONF_PN532_ID = "pn532_id" -CONF_ON_FINISHED_WRITE = "on_finished_write" pn532_ns = cg.esphome_ns.namespace("pn532") PN532 = pn532_ns.class_("PN532", cg.PollingComponent) diff --git a/esphome/components/pn7150/__init__.py b/esphome/components/pn7150/__init__.py index a136028011..e3589ea449 100644 --- a/esphome/components/pn7150/__init__.py +++ b/esphome/components/pn7150/__init__.py @@ -6,6 +6,8 @@ from esphome.components import nfc from esphome.const import ( CONF_ID, CONF_IRQ_PIN, + CONF_MESSAGE, + CONF_ON_FINISHED_WRITE, CONF_ON_TAG_REMOVED, CONF_ON_TAG, CONF_TRIGGER_ID, @@ -18,8 +20,6 @@ CONF_EMULATION_MESSAGE = "emulation_message" CONF_EMULATION_OFF = "emulation_off" CONF_EMULATION_ON = "emulation_on" CONF_INCLUDE_ANDROID_APP_RECORD = "include_android_app_record" -CONF_MESSAGE = "message" -CONF_ON_FINISHED_WRITE = "on_finished_write" CONF_ON_EMULATED_TAG_SCAN = "on_emulated_tag_scan" CONF_PN7150_ID = "pn7150_id" CONF_POLLING_OFF = "polling_off" diff --git a/esphome/components/pn7160/__init__.py b/esphome/components/pn7160/__init__.py index 1639041b9e..b102b38f98 100644 --- a/esphome/components/pn7160/__init__.py +++ b/esphome/components/pn7160/__init__.py @@ -6,6 +6,8 @@ from esphome.components import nfc from esphome.const import ( CONF_ID, CONF_IRQ_PIN, + CONF_MESSAGE, + CONF_ON_FINISHED_WRITE, CONF_ON_TAG_REMOVED, CONF_ON_TAG, CONF_TRIGGER_ID, @@ -19,8 +21,6 @@ CONF_EMULATION_MESSAGE = "emulation_message" CONF_EMULATION_OFF = "emulation_off" CONF_EMULATION_ON = "emulation_on" CONF_INCLUDE_ANDROID_APP_RECORD = "include_android_app_record" -CONF_MESSAGE = "message" -CONF_ON_FINISHED_WRITE = "on_finished_write" CONF_ON_EMULATED_TAG_SCAN = "on_emulated_tag_scan" CONF_PN7160_ID = "pn7160_id" CONF_POLLING_OFF = "polling_off" diff --git a/esphome/components/power_supply/__init__.py b/esphome/components/power_supply/__init__.py index 6735eddff3..01b541e4b5 100644 --- a/esphome/components/power_supply/__init__.py +++ b/esphome/components/power_supply/__init__.py @@ -1,15 +1,19 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import pins -from esphome.const import CONF_ENABLE_TIME, CONF_ID, CONF_KEEP_ON_TIME, CONF_PIN +from esphome.const import ( + CONF_ENABLE_ON_BOOT, + CONF_ENABLE_TIME, + CONF_ID, + CONF_KEEP_ON_TIME, + CONF_PIN, +) CODEOWNERS = ["@esphome/core"] power_supply_ns = cg.esphome_ns.namespace("power_supply") PowerSupply = power_supply_ns.class_("PowerSupply", cg.Component) MULTI_CONF = True -CONF_ENABLE_ON_BOOT = "enable_on_boot" - CONFIG_SCHEMA = cv.Schema( { cv.Required(CONF_ID): cv.declare_id(PowerSupply), diff --git a/esphome/components/qmc5883l/sensor.py b/esphome/components/qmc5883l/sensor.py index 24e1019507..341c0c3f8a 100644 --- a/esphome/components/qmc5883l/sensor.py +++ b/esphome/components/qmc5883l/sensor.py @@ -6,6 +6,7 @@ from esphome.const import ( CONF_FIELD_STRENGTH_X, CONF_FIELD_STRENGTH_Y, CONF_FIELD_STRENGTH_Z, + CONF_HEADING, CONF_TEMPERATURE, CONF_ID, CONF_OVERSAMPLING, @@ -24,8 +25,6 @@ DEPENDENCIES = ["i2c"] qmc5883l_ns = cg.esphome_ns.namespace("qmc5883l") -CONF_HEADING = "heading" - QMC5883LComponent = qmc5883l_ns.class_( "QMC5883LComponent", cg.PollingComponent, i2c.I2CDevice ) diff --git a/esphome/components/resistance/sensor.py b/esphome/components/resistance/sensor.py index a84b439497..ce4459fc6d 100644 --- a/esphome/components/resistance/sensor.py +++ b/esphome/components/resistance/sensor.py @@ -2,6 +2,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import sensor, resistance_sampler from esphome.const import ( + CONF_REFERENCE_VOLTAGE, CONF_SENSOR, STATE_CLASS_MEASUREMENT, UNIT_OHM, @@ -18,7 +19,6 @@ ResistanceSensor = resistance_ns.class_( resistance_sampler.ResistanceSampler, ) -CONF_REFERENCE_VOLTAGE = "reference_voltage" CONF_CONFIGURATION = "configuration" CONF_RESISTOR = "resistor" diff --git a/esphome/components/rpi_dpi_rgb/display.py b/esphome/components/rpi_dpi_rgb/display.py index 0cde16e0fb..969b9db78e 100644 --- a/esphome/components/rpi_dpi_rgb/display.py +++ b/esphome/components/rpi_dpi_rgb/display.py @@ -3,11 +3,13 @@ import esphome.config_validation as cv from esphome import pins from esphome.components import display from esphome.const import ( + CONF_HSYNC_PIN, CONF_RESET_PIN, CONF_DATA_PINS, CONF_ID, CONF_IGNORE_STRAPPING_WARNING, CONF_DIMENSIONS, + CONF_VSYNC_PIN, CONF_WIDTH, CONF_HEIGHT, CONF_LAMBDA, @@ -29,8 +31,6 @@ DEPENDENCIES = ["esp32"] CONF_DE_PIN = "de_pin" CONF_PCLK_PIN = "pclk_pin" -CONF_HSYNC_PIN = "hsync_pin" -CONF_VSYNC_PIN = "vsync_pin" CONF_HSYNC_FRONT_PORCH = "hsync_front_porch" CONF_HSYNC_PULSE_WIDTH = "hsync_pulse_width" diff --git a/esphome/components/scd30/sensor.py b/esphome/components/scd30/sensor.py index f72b43fd37..a900c51a58 100644 --- a/esphome/components/scd30/sensor.py +++ b/esphome/components/scd30/sensor.py @@ -8,6 +8,7 @@ from esphome.const import ( CONF_HUMIDITY, CONF_TEMPERATURE, CONF_CO2, + CONF_TEMPERATURE_OFFSET, CONF_UPDATE_INTERVAL, CONF_VALUE, DEVICE_CLASS_CARBON_DIOXIDE, @@ -36,7 +37,6 @@ ForceRecalibrationWithReference = scd30_ns.class_( CONF_AUTOMATIC_SELF_CALIBRATION = "automatic_self_calibration" CONF_ALTITUDE_COMPENSATION = "altitude_compensation" CONF_AMBIENT_PRESSURE_COMPENSATION = "ambient_pressure_compensation" -CONF_TEMPERATURE_OFFSET = "temperature_offset" CONFIG_SCHEMA = ( diff --git a/esphome/components/scd4x/sensor.py b/esphome/components/scd4x/sensor.py index 4c94d4257f..13027b6f88 100644 --- a/esphome/components/scd4x/sensor.py +++ b/esphome/components/scd4x/sensor.py @@ -10,6 +10,7 @@ from esphome.const import ( CONF_CO2, CONF_HUMIDITY, CONF_TEMPERATURE, + CONF_TEMPERATURE_OFFSET, CONF_VALUE, DEVICE_CLASS_CARBON_DIOXIDE, DEVICE_CLASS_HUMIDITY, @@ -52,7 +53,6 @@ CONF_AMBIENT_PRESSURE_COMPENSATION = "ambient_pressure_compensation" CONF_AMBIENT_PRESSURE_COMPENSATION_SOURCE = "ambient_pressure_compensation_source" CONF_AUTOMATIC_SELF_CALIBRATION = "automatic_self_calibration" CONF_MEASUREMENT_MODE = "measurement_mode" -CONF_TEMPERATURE_OFFSET = "temperature_offset" CONFIG_SCHEMA = ( diff --git a/esphome/components/script/__init__.py b/esphome/components/script/__init__.py index 78b23e7b5e..483357f85b 100644 --- a/esphome/components/script/__init__.py +++ b/esphome/components/script/__init__.py @@ -2,7 +2,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation from esphome.automation import maybe_simple_id -from esphome.const import CONF_ID, CONF_MODE, CONF_PARAMETERS +from esphome.const import CONF_ID, CONF_MODE, CONF_PARAMETERS, CONF_RESTART from esphome.core import CORE, EsphomeError CODEOWNERS = ["@esphome/core"] @@ -19,7 +19,6 @@ ParallelScript = script_ns.class_("ParallelScript", Script) CONF_SCRIPT = "script" CONF_SINGLE = "single" -CONF_RESTART = "restart" CONF_QUEUED = "queued" CONF_PARALLEL = "parallel" CONF_MAX_RUNS = "max_runs" diff --git a/esphome/components/seeed_mr24hpc1/binary_sensor.py b/esphome/components/seeed_mr24hpc1/binary_sensor.py index e3e54d03f9..003db9f4a3 100644 --- a/esphome/components/seeed_mr24hpc1/binary_sensor.py +++ b/esphome/components/seeed_mr24hpc1/binary_sensor.py @@ -3,10 +3,10 @@ from esphome.components import binary_sensor import esphome.config_validation as cv from esphome.const import ( DEVICE_CLASS_OCCUPANCY, + CONF_HAS_TARGET, ) from . import CONF_MR24HPC1_ID, MR24HPC1Component -CONF_HAS_TARGET = "has_target" CONFIG_SCHEMA = { cv.GenerateID(CONF_MR24HPC1_ID): cv.use_id(MR24HPC1Component), diff --git a/esphome/components/seeed_mr24hpc1/button/__init__.py b/esphome/components/seeed_mr24hpc1/button/__init__.py index 0a0e7a1865..59372e4100 100644 --- a/esphome/components/seeed_mr24hpc1/button/__init__.py +++ b/esphome/components/seeed_mr24hpc1/button/__init__.py @@ -2,6 +2,7 @@ import esphome.codegen as cg from esphome.components import button import esphome.config_validation as cv from esphome.const import ( + CONF_RESTART, DEVICE_CLASS_RESTART, ENTITY_CATEGORY_CONFIG, ICON_RESTART_ALERT, @@ -11,7 +12,6 @@ from .. import CONF_MR24HPC1_ID, MR24HPC1Component, mr24hpc1_ns RestartButton = mr24hpc1_ns.class_("RestartButton", button.Button) CustomSetEndButton = mr24hpc1_ns.class_("CustomSetEndButton", button.Button) -CONF_RESTART = "restart" CONF_CUSTOM_SET_END = "custom_set_end" CONFIG_SCHEMA = { diff --git a/esphome/components/seeed_mr24hpc1/number/__init__.py b/esphome/components/seeed_mr24hpc1/number/__init__.py index d9dfcb19a5..2055fc548c 100644 --- a/esphome/components/seeed_mr24hpc1/number/__init__.py +++ b/esphome/components/seeed_mr24hpc1/number/__init__.py @@ -2,6 +2,7 @@ import esphome.codegen as cg from esphome.components import number import esphome.config_validation as cv from esphome.const import ( + CONF_SENSITIVITY, ENTITY_CATEGORY_CONFIG, ) from .. import CONF_MR24HPC1_ID, MR24HPC1Component, mr24hpc1_ns @@ -14,7 +15,6 @@ MotionTriggerTimeNumber = mr24hpc1_ns.class_("MotionTriggerTimeNumber", number.N MotionToRestTimeNumber = mr24hpc1_ns.class_("MotionToRestTimeNumber", number.Number) CustomUnmanTimeNumber = mr24hpc1_ns.class_("CustomUnmanTimeNumber", number.Number) -CONF_SENSITIVITY = "sensitivity" CONF_CUSTOM_MODE = "custom_mode" CONF_EXISTENCE_THRESHOLD = "existence_threshold" CONF_MOTION_THRESHOLD = "motion_threshold" diff --git a/esphome/components/sgp30/sensor.py b/esphome/components/sgp30/sensor.py index 6f8ed42d25..13e859cc09 100644 --- a/esphome/components/sgp30/sensor.py +++ b/esphome/components/sgp30/sensor.py @@ -3,6 +3,7 @@ import esphome.config_validation as cv from esphome.components import i2c, sensor, sensirion_common from esphome.const import ( + CONF_COMPENSATION, CONF_ID, CONF_BASELINE, CONF_ECO2, @@ -30,7 +31,6 @@ SGP30Component = sgp30_ns.class_( CONF_ECO2_BASELINE = "eco2_baseline" CONF_TVOC_BASELINE = "tvoc_baseline" CONF_UPTIME = "uptime" -CONF_COMPENSATION = "compensation" CONF_HUMIDITY_SOURCE = "humidity_source" diff --git a/esphome/components/sgp4x/sensor.py b/esphome/components/sgp4x/sensor.py index 3d24f6c409..b7cec542bf 100644 --- a/esphome/components/sgp4x/sensor.py +++ b/esphome/components/sgp4x/sensor.py @@ -2,6 +2,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import i2c, sensor, sensirion_common from esphome.const import ( + CONF_COMPENSATION, CONF_ID, CONF_STORE_BASELINE, CONF_TEMPERATURE_SOURCE, @@ -23,7 +24,6 @@ SGP4xComponent = sgp4x_ns.class_( ) CONF_ALGORITHM_TUNING = "algorithm_tuning" -CONF_COMPENSATION = "compensation" CONF_GAIN_FACTOR = "gain_factor" CONF_GATING_MAX_DURATION_MINUTES = "gating_max_duration_minutes" CONF_HUMIDITY_SOURCE = "humidity_source" diff --git a/esphome/components/sim800l/__init__.py b/esphome/components/sim800l/__init__.py index 698e3cda9e..faa6cefe27 100644 --- a/esphome/components/sim800l/__init__.py +++ b/esphome/components/sim800l/__init__.py @@ -3,6 +3,7 @@ import esphome.config_validation as cv from esphome import automation from esphome.const import ( CONF_ID, + CONF_MESSAGE, CONF_TRIGGER_ID, ) from esphome.components import uart @@ -52,7 +53,6 @@ CONF_ON_INCOMING_CALL = "on_incoming_call" CONF_ON_CALL_CONNECTED = "on_call_connected" CONF_ON_CALL_DISCONNECTED = "on_call_disconnected" CONF_RECIPIENT = "recipient" -CONF_MESSAGE = "message" CONF_USSD = "ussd" CONFIG_SCHEMA = cv.All( diff --git a/esphome/components/sn74hc595/__init__.py b/esphome/components/sn74hc595/__init__.py index e0cd5e70ad..2fd49f6824 100644 --- a/esphome/components/sn74hc595/__init__.py +++ b/esphome/components/sn74hc595/__init__.py @@ -8,6 +8,7 @@ from esphome.const import ( CONF_INVERTED, CONF_DATA_PIN, CONF_CLOCK_PIN, + CONF_OE_PIN, CONF_OUTPUT, CONF_TYPE, ) @@ -30,7 +31,6 @@ SN74HC595GPIOPin = sn74hc595_ns.class_( CONF_SN74HC595 = "sn74hc595" CONF_LATCH_PIN = "latch_pin" -CONF_OE_PIN = "oe_pin" CONF_SR_COUNT = "sr_count" TYPE_GPIO = "gpio" diff --git a/esphome/components/st7701s/display.py b/esphome/components/st7701s/display.py index e33eeb89ae..516d770f8b 100644 --- a/esphome/components/st7701s/display.py +++ b/esphome/components/st7701s/display.py @@ -7,10 +7,12 @@ from esphome.components import ( ) from esphome.const import ( CONF_DC_PIN, + CONF_HSYNC_PIN, CONF_RESET_PIN, CONF_DATA_PINS, CONF_ID, CONF_DIMENSIONS, + CONF_VSYNC_PIN, CONF_WIDTH, CONF_HEIGHT, CONF_LAMBDA, @@ -44,8 +46,6 @@ from .init_sequences import ( CONF_INIT_SEQUENCE = "init_sequence" CONF_DE_PIN = "de_pin" CONF_PCLK_PIN = "pclk_pin" -CONF_HSYNC_PIN = "hsync_pin" -CONF_VSYNC_PIN = "vsync_pin" CONF_HSYNC_PULSE_WIDTH = "hsync_pulse_width" CONF_HSYNC_BACK_PORCH = "hsync_back_porch" diff --git a/esphome/components/tlc5947/__init__.py b/esphome/components/tlc5947/__init__.py index 8a4bd5e0ce..528d690fab 100644 --- a/esphome/components/tlc5947/__init__.py +++ b/esphome/components/tlc5947/__init__.py @@ -9,10 +9,10 @@ from esphome.const import ( CONF_DATA_PIN, CONF_ID, CONF_NUM_CHIPS, + CONF_OE_PIN, ) CONF_LAT_PIN = "lat_pin" -CONF_OE_PIN = "oe_pin" CODEOWNERS = ["@rnauber"] diff --git a/esphome/components/touchscreen/__init__.py b/esphome/components/touchscreen/__init__.py index 400ba7d5ad..b2d3f60d2b 100644 --- a/esphome/components/touchscreen/__init__.py +++ b/esphome/components/touchscreen/__init__.py @@ -5,6 +5,7 @@ from esphome.components import display from esphome import automation from esphome.const import ( + CONF_DISPLAY, CONF_ON_TOUCH, CONF_ON_RELEASE, CONF_ON_UPDATE, @@ -31,7 +32,6 @@ TouchPoints_t = cg.std_vector.template(TouchPoint) TouchPoints_t_const_ref = TouchPoints_t.operator("ref").operator("const") TouchListener = touchscreen_ns.class_("TouchListener") -CONF_DISPLAY = "display" CONF_TOUCHSCREEN_ID = "touchscreen_id" CONF_REPORT_INTERVAL = "report_interval" # not used yet: CONF_TOUCH_TIMEOUT = "touch_timeout" diff --git a/esphome/components/whynter/climate.py b/esphome/components/whynter/climate.py index b9dc5868bc..1d576344e6 100644 --- a/esphome/components/whynter/climate.py +++ b/esphome/components/whynter/climate.py @@ -1,14 +1,13 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import climate_ir -from esphome.const import CONF_ID +from esphome.const import CONF_ID, CONF_USE_FAHRENHEIT AUTO_LOAD = ["climate_ir"] whynter_ns = cg.esphome_ns.namespace("whynter") Whynter = whynter_ns.class_("Whynter", climate_ir.ClimateIR) -CONF_USE_FAHRENHEIT = "use_fahrenheit" CONFIG_SCHEMA = climate_ir.CLIMATE_IR_WITH_RECEIVER_SCHEMA.extend( { diff --git a/esphome/components/wifi/__init__.py b/esphome/components/wifi/__init__.py index 32c9d07046..e0a17e9a2a 100644 --- a/esphome/components/wifi/__init__.py +++ b/esphome/components/wifi/__init__.py @@ -11,6 +11,7 @@ from esphome.const import ( CONF_DNS2, CONF_DOMAIN, CONF_ENABLE_BTM, + CONF_ENABLE_ON_BOOT, CONF_ENABLE_RRM, CONF_FAST_CONNECT, CONF_GATEWAY, @@ -268,7 +269,6 @@ def _validate(config): CONF_OUTPUT_POWER = "output_power" CONF_PASSIVE_SCAN = "passive_scan" -CONF_ENABLE_ON_BOOT = "enable_on_boot" CONFIG_SCHEMA = cv.All( cv.Schema( { diff --git a/esphome/components/wireguard/__init__.py b/esphome/components/wireguard/__init__.py index 2d68cd001e..7612c7d964 100644 --- a/esphome/components/wireguard/__init__.py +++ b/esphome/components/wireguard/__init__.py @@ -22,6 +22,8 @@ CONF_PEER_ALLOWED_IPS = "peer_allowed_ips" CONF_PEER_PERSISTENT_KEEPALIVE = "peer_persistent_keepalive" CONF_REQUIRE_CONNECTION_TO_PROCEED = "require_connection_to_proceed" +CONF_WIREGUARD_ID = "wireguard_id" + DEPENDENCIES = ["time"] CODEOWNERS = ["@lhoracek", "@droscy", "@thomas0bernard"] diff --git a/esphome/components/wireguard/binary_sensor.py b/esphome/components/wireguard/binary_sensor.py index bf60aaa1d6..7344558659 100644 --- a/esphome/components/wireguard/binary_sensor.py +++ b/esphome/components/wireguard/binary_sensor.py @@ -7,9 +7,8 @@ from esphome.const import ( ENTITY_CATEGORY_DIAGNOSTIC, ) -from . import Wireguard +from . import CONF_WIREGUARD_ID, Wireguard -CONF_WIREGUARD_ID = "wireguard_id" CONF_ENABLED = "enabled" DEPENDENCIES = ["wireguard"] diff --git a/esphome/components/wireguard/sensor.py b/esphome/components/wireguard/sensor.py index 78cb619701..85703d24b3 100644 --- a/esphome/components/wireguard/sensor.py +++ b/esphome/components/wireguard/sensor.py @@ -6,9 +6,8 @@ from esphome.const import ( ENTITY_CATEGORY_DIAGNOSTIC, ) -from . import Wireguard +from . import CONF_WIREGUARD_ID, Wireguard -CONF_WIREGUARD_ID = "wireguard_id" CONF_LATEST_HANDSHAKE = "latest_handshake" DEPENDENCIES = ["wireguard"] diff --git a/esphome/components/wireguard/text_sensor.py b/esphome/components/wireguard/text_sensor.py index 3b05f6173e..51614a1a28 100644 --- a/esphome/components/wireguard/text_sensor.py +++ b/esphome/components/wireguard/text_sensor.py @@ -6,9 +6,7 @@ from esphome.const import ( ENTITY_CATEGORY_DIAGNOSTIC, ) -from . import Wireguard - -CONF_WIREGUARD_ID = "wireguard_id" +from . import CONF_WIREGUARD_ID, Wireguard DEPENDENCIES = ["wireguard"] diff --git a/esphome/const.py b/esphome/const.py index 324b32e847..1a8f9a06e1 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -141,6 +141,7 @@ CONF_COMMAND_RETAIN = "command_retain" CONF_COMMAND_TOPIC = "command_topic" CONF_COMMENT = "comment" CONF_COMMIT = "commit" +CONF_COMPENSATION = "compensation" CONF_COMPILE_PROCESS_LIMIT = "compile_process_limit" CONF_COMPONENT_ID = "component_id" CONF_COMPONENTS = "components" @@ -216,6 +217,7 @@ CONF_DISCOVERY_OBJECT_ID_GENERATOR = "discovery_object_id_generator" CONF_DISCOVERY_PREFIX = "discovery_prefix" CONF_DISCOVERY_RETAIN = "discovery_retain" CONF_DISCOVERY_UNIQUE_ID_GENERATOR = "discovery_unique_id_generator" +CONF_DISPLAY = "display" CONF_DISTANCE = "distance" CONF_DITHER = "dither" CONF_DIV_RATIO = "div_ratio" @@ -239,6 +241,7 @@ CONF_EFFECTS = "effects" CONF_ELSE = "else" CONF_ENABLE_BTM = "enable_btm" CONF_ENABLE_IPV6 = "enable_ipv6" +CONF_ENABLE_ON_BOOT = "enable_on_boot" CONF_ENABLE_PIN = "enable_pin" CONF_ENABLE_PRIVATE_NETWORK_ACCESS = "enable_private_network_access" CONF_ENABLE_RRM = "enable_rrm" @@ -261,6 +264,7 @@ CONF_EXTERNAL_CLOCK_INPUT = "external_clock_input" CONF_EXTERNAL_COMPONENTS = "external_components" CONF_EXTERNAL_TEMPERATURE = "external_temperature" CONF_EXTERNAL_VCC = "external_vcc" +CONF_FACTORY_RESET = "factory_reset" CONF_FALLING_EDGE = "falling_edge" CONF_FAMILY = "family" CONF_FAN_MODE = "fan_mode" @@ -323,7 +327,11 @@ CONF_GYROSCOPE_X = "gyroscope_x" CONF_GYROSCOPE_Y = "gyroscope_y" CONF_GYROSCOPE_Z = "gyroscope_z" CONF_HARDWARE_UART = "hardware_uart" +CONF_HAS_MOVING_TARGET = "has_moving_target" +CONF_HAS_STILL_TARGET = "has_still_target" +CONF_HAS_TARGET = "has_target" CONF_HEAD = "head" +CONF_HEADING = "heading" CONF_HEARTBEAT = "heartbeat" CONF_HEAT_ACTION = "heat_action" CONF_HEAT_DEADBAND = "heat_deadband" @@ -337,6 +345,7 @@ CONF_HIGH = "high" CONF_HIGH_VOLTAGE_REFERENCE = "high_voltage_reference" CONF_HOUR = "hour" CONF_HOURS = "hours" +CONF_HSYNC_PIN = "hsync_pin" CONF_HUMIDITY = "humidity" CONF_HUMIDITY_SENSOR = "humidity_sensor" CONF_HYSTERESIS = "hysteresis" @@ -377,6 +386,7 @@ CONF_INTERLOCK = "interlock" CONF_INTERNAL = "internal" CONF_INTERNAL_FILTER = "internal_filter" CONF_INTERNAL_FILTER_MODE = "internal_filter_mode" +CONF_INTERNAL_TEMPERATURE = "internal_temperature" CONF_INTERRUPT = "interrupt" CONF_INTERRUPT_PIN = "interrupt_pin" CONF_INTERVAL = "interval" @@ -446,6 +456,7 @@ CONF_MEASUREMENT_SEQUENCE_NUMBER = "measurement_sequence_number" CONF_MEDIA_PLAYER = "media_player" CONF_MEDIUM = "medium" CONF_MEMORY_BLOCKS = "memory_blocks" +CONF_MESSAGE = "message" CONF_METHOD = "method" CONF_MICROPHONE = "microphone" CONF_MIN_BRIGHTNESS = "min_brightness" @@ -499,6 +510,7 @@ CONF_NUM_LEDS = "num_leds" CONF_NUM_SCANS = "num_scans" CONF_NUMBER = "number" CONF_NUMBER_DATAPOINT = "number_datapoint" +CONF_OE_PIN = "oe_pin" CONF_OFF_MODE = "off_mode" CONF_OFF_SPEED_CYCLE = "off_speed_cycle" CONF_OFFSET = "offset" @@ -526,6 +538,7 @@ CONF_ON_FINGER_SCAN_MATCHED = "on_finger_scan_matched" CONF_ON_FINGER_SCAN_MISPLACED = "on_finger_scan_misplaced" CONF_ON_FINGER_SCAN_START = "on_finger_scan_start" CONF_ON_FINGER_SCAN_UNMATCHED = "on_finger_scan_unmatched" +CONF_ON_FINISHED_WRITE = "on_finished_write" CONF_ON_JSON_MESSAGE = "on_json_message" CONF_ON_LOCK = "on_lock" CONF_ON_LOOP = "on_loop" @@ -568,6 +581,7 @@ CONF_OSCILLATION_COMMAND_TOPIC = "oscillation_command_topic" CONF_OSCILLATION_OUTPUT = "oscillation_output" CONF_OSCILLATION_STATE_TOPIC = "oscillation_state_topic" CONF_OTA = "ota" +CONF_OUTDOOR_TEMPERATURE = "outdoor_temperature" CONF_OUTPUT = "output" CONF_OUTPUT_ID = "output_id" CONF_OUTPUTS = "outputs" @@ -666,6 +680,7 @@ CONF_RED = "red" CONF_REF = "ref" CONF_REFERENCE_RESISTANCE = "reference_resistance" CONF_REFERENCE_TEMPERATURE = "reference_temperature" +CONF_REFERENCE_VOLTAGE = "reference_voltage" CONF_REFRESH = "refresh" CONF_RELABEL = "relabel" CONF_REPEAT = "repeat" @@ -674,6 +689,7 @@ CONF_RESET_DURATION = "reset_duration" CONF_RESET_PIN = "reset_pin" CONF_RESIZE = "resize" CONF_RESOLUTION = "resolution" +CONF_RESTART = "restart" CONF_RESTORE = "restore" CONF_RESTORE_MODE = "restore_mode" CONF_RESTORE_STATE = "restore_state" @@ -711,6 +727,7 @@ CONF_SEL_PIN = "sel_pin" CONF_SEND_EVERY = "send_every" CONF_SEND_FIRST_AT = "send_first_at" CONF_SENSING_PIN = "sensing_pin" +CONF_SENSITIVITY = "sensitivity" CONF_SENSOR = "sensor" CONF_SENSOR_DATAPOINT = "sensor_datapoint" CONF_SENSOR_ID = "sensor_id" @@ -804,6 +821,7 @@ CONF_TARGET_TEMPERATURE_LOW_COMMAND_TOPIC = "target_temperature_low_command_topi CONF_TARGET_TEMPERATURE_LOW_STATE_TOPIC = "target_temperature_low_state_topic" CONF_TARGET_TEMPERATURE_STATE_TOPIC = "target_temperature_state_topic" CONF_TEMPERATURE = "temperature" +CONF_TEMPERATURE_OFFSET = "temperature_offset" CONF_TEMPERATURE_SOURCE = "temperature_source" CONF_TEMPERATURE_STEP = "temperature_step" CONF_TEXT_SENSORS = "text_sensors" @@ -852,6 +870,7 @@ CONF_UPDATE_ON_BOOT = "update_on_boot" CONF_URL = "url" CONF_USE_ABBREVIATIONS = "use_abbreviations" CONF_USE_ADDRESS = "use_address" +CONF_USE_FAHRENHEIT = "use_fahrenheit" CONF_USERNAME = "username" CONF_UUID = "uuid" CONF_VALIDITY_PERIOD = "validity_period" @@ -865,7 +884,9 @@ CONF_VISUAL = "visual" CONF_VOLTAGE = "voltage" CONF_VOLTAGE_ATTENUATION = "voltage_attenuation" CONF_VOLTAGE_DIVIDER = "voltage_divider" +CONF_VOLTAGE_GAIN = "voltage_gain" CONF_VOLUME = "volume" +CONF_VSYNC_PIN = "vsync_pin" CONF_WAIT_TIME = "wait_time" CONF_WAIT_UNTIL = "wait_until" CONF_WAKEUP_PIN = "wakeup_pin" diff --git a/script/ci-custom.py b/script/ci-custom.py index abe004dba3..704962fa97 100755 --- a/script/ci-custom.py +++ b/script/ci-custom.py @@ -476,7 +476,7 @@ def lint_no_byte_datatype(fname, match): def lint_constants_usage(): errs = [] for constant, uses in CONSTANTS_USES.items(): - if len(uses) < 4: + if len(uses) < 3: continue errs.append( f"Constant {highlight(constant)} is defined in {len(uses)} files. Please move all definitions of the " From f1584205afcaf4863446f140d19f87e1f8192e4e Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Sun, 5 May 2024 21:52:47 +0200 Subject: [PATCH 1370/2101] [core] Rename ALWAYS_INLINE to ESPHOME_ALWAYS_INLINE (#6636) --- esphome/components/display/rect.h | 4 +- .../components/light/esp_color_correction.h | 20 +++---- esphome/components/light/esp_hsv_color.h | 8 +-- esphome/core/color.h | 52 ++++++++++--------- esphome/core/helpers.h | 2 +- 5 files changed, 44 insertions(+), 42 deletions(-) diff --git a/esphome/components/display/rect.h b/esphome/components/display/rect.h index a728ddd132..f55c2fe201 100644 --- a/esphome/components/display/rect.h +++ b/esphome/components/display/rect.h @@ -15,11 +15,11 @@ class Rect { int16_t h; ///< Height of region Rect() : x(VALUE_NO_SET), y(VALUE_NO_SET), w(VALUE_NO_SET), h(VALUE_NO_SET) {} // NOLINT - inline Rect(int16_t x, int16_t y, int16_t w, int16_t h) ALWAYS_INLINE : x(x), y(y), w(w), h(h) {} + inline Rect(int16_t x, int16_t y, int16_t w, int16_t h) ESPHOME_ALWAYS_INLINE : x(x), y(y), w(w), h(h) {} inline int16_t x2() const { return this->x + this->w; }; ///< X coordinate of corner inline int16_t y2() const { return this->y + this->h; }; ///< Y coordinate of corner - inline bool is_set() const ALWAYS_INLINE { return (this->h != VALUE_NO_SET) && (this->w != VALUE_NO_SET); } + inline bool is_set() const ESPHOME_ALWAYS_INLINE { return (this->h != VALUE_NO_SET) && (this->w != VALUE_NO_SET); } void expand(int16_t horizontal, int16_t vertical); diff --git a/esphome/components/light/esp_color_correction.h b/esphome/components/light/esp_color_correction.h index 8788246cfc..eedd71ab27 100644 --- a/esphome/components/light/esp_color_correction.h +++ b/esphome/components/light/esp_color_correction.h @@ -11,54 +11,54 @@ class ESPColorCorrection { 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); - inline Color color_correct(Color color) const ALWAYS_INLINE { + 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), this->color_correct_blue(color.blue), this->color_correct_white(color.white)); } - inline uint8_t color_correct_red(uint8_t red) const ALWAYS_INLINE { + inline uint8_t color_correct_red(uint8_t red) const ESPHOME_ALWAYS_INLINE { uint8_t res = esp_scale8(esp_scale8(red, this->max_brightness_.red), this->local_brightness_); return this->gamma_table_[res]; } - inline uint8_t color_correct_green(uint8_t green) const ALWAYS_INLINE { + inline uint8_t color_correct_green(uint8_t green) const ESPHOME_ALWAYS_INLINE { uint8_t res = esp_scale8(esp_scale8(green, this->max_brightness_.green), this->local_brightness_); return this->gamma_table_[res]; } - inline uint8_t color_correct_blue(uint8_t blue) const ALWAYS_INLINE { + inline uint8_t color_correct_blue(uint8_t blue) const ESPHOME_ALWAYS_INLINE { uint8_t res = esp_scale8(esp_scale8(blue, this->max_brightness_.blue), this->local_brightness_); return this->gamma_table_[res]; } - inline uint8_t color_correct_white(uint8_t white) const ALWAYS_INLINE { + inline uint8_t color_correct_white(uint8_t white) const ESPHOME_ALWAYS_INLINE { uint8_t res = esp_scale8(esp_scale8(white, this->max_brightness_.white), this->local_brightness_); return this->gamma_table_[res]; } - inline Color color_uncorrect(Color color) const ALWAYS_INLINE { + inline Color color_uncorrect(Color color) const ESPHOME_ALWAYS_INLINE { // uncorrected = corrected^(1/gamma) / (max_brightness * local_brightness) return Color(this->color_uncorrect_red(color.red), this->color_uncorrect_green(color.green), this->color_uncorrect_blue(color.blue), this->color_uncorrect_white(color.white)); } - inline uint8_t color_uncorrect_red(uint8_t red) const ALWAYS_INLINE { + 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; uint8_t res = ((uncorrected / this->max_brightness_.red) * 255UL) / this->local_brightness_; return res; } - inline uint8_t color_uncorrect_green(uint8_t green) const ALWAYS_INLINE { + 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; uint8_t res = ((uncorrected / this->max_brightness_.green) * 255UL) / this->local_brightness_; return res; } - inline uint8_t color_uncorrect_blue(uint8_t blue) const ALWAYS_INLINE { + 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; uint8_t res = ((uncorrected / this->max_brightness_.blue) * 255UL) / this->local_brightness_; return res; } - inline uint8_t color_uncorrect_white(uint8_t white) const ALWAYS_INLINE { + 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; diff --git a/esphome/components/light/esp_hsv_color.h b/esphome/components/light/esp_hsv_color.h index e0aa388875..39f5e55707 100644 --- a/esphome/components/light/esp_hsv_color.h +++ b/esphome/components/light/esp_hsv_color.h @@ -24,11 +24,11 @@ struct ESPHSVColor { }; uint8_t raw[3]; }; - inline ESPHSVColor() ALWAYS_INLINE : h(0), s(0), v(0) { // NOLINT + inline ESPHSVColor() ESPHOME_ALWAYS_INLINE : h(0), s(0), v(0) { // NOLINT } - inline ESPHSVColor(uint8_t hue, uint8_t saturation, uint8_t value) ALWAYS_INLINE : hue(hue), - saturation(saturation), - value(value) {} + inline ESPHSVColor(uint8_t hue, uint8_t saturation, uint8_t value) ESPHOME_ALWAYS_INLINE : hue(hue), + saturation(saturation), + value(value) {} Color to_rgb() const; }; diff --git a/esphome/core/color.h b/esphome/core/color.h index fb72973017..8965d9fc83 100644 --- a/esphome/core/color.h +++ b/esphome/core/color.h @@ -31,19 +31,19 @@ struct Color { uint32_t raw_32; }; - inline Color() ALWAYS_INLINE : r(0), g(0), b(0), w(0) {} // NOLINT - inline Color(uint8_t red, uint8_t green, uint8_t blue) ALWAYS_INLINE : r(red), g(green), b(blue), w(0) {} + inline Color() ESPHOME_ALWAYS_INLINE : r(0), g(0), b(0), w(0) {} // NOLINT + inline Color(uint8_t red, uint8_t green, uint8_t blue) ESPHOME_ALWAYS_INLINE : r(red), g(green), b(blue), w(0) {} - inline Color(uint8_t red, uint8_t green, uint8_t blue, uint8_t white) ALWAYS_INLINE : r(red), - g(green), - b(blue), - w(white) {} - inline explicit Color(uint32_t colorcode) ALWAYS_INLINE : r((colorcode >> 16) & 0xFF), - g((colorcode >> 8) & 0xFF), - b((colorcode >> 0) & 0xFF), - w((colorcode >> 24) & 0xFF) {} + inline Color(uint8_t red, uint8_t green, uint8_t blue, uint8_t white) ESPHOME_ALWAYS_INLINE : r(red), + g(green), + b(blue), + w(white) {} + inline explicit Color(uint32_t colorcode) ESPHOME_ALWAYS_INLINE : r((colorcode >> 16) & 0xFF), + g((colorcode >> 8) & 0xFF), + b((colorcode >> 0) & 0xFF), + w((colorcode >> 24) & 0xFF) {} - inline bool is_on() ALWAYS_INLINE { return this->raw_32 != 0; } + inline bool is_on() ESPHOME_ALWAYS_INLINE { return this->raw_32 != 0; } inline bool operator==(const Color &rhs) { // NOLINT return this->raw_32 == rhs.raw_32; @@ -57,31 +57,33 @@ struct Color { inline bool operator!=(uint32_t colorcode) { // NOLINT return this->raw_32 != colorcode; } - inline uint8_t &operator[](uint8_t x) ALWAYS_INLINE { return this->raw[x]; } - inline Color operator*(uint8_t scale) const ALWAYS_INLINE { + inline uint8_t &operator[](uint8_t x) ESPHOME_ALWAYS_INLINE { return this->raw[x]; } + inline Color operator*(uint8_t scale) const ESPHOME_ALWAYS_INLINE { return Color(esp_scale8(this->red, scale), esp_scale8(this->green, scale), esp_scale8(this->blue, scale), esp_scale8(this->white, scale)); } - inline Color operator~() const ALWAYS_INLINE { return Color(255 - this->red, 255 - this->green, 255 - this->blue); } - inline Color &operator*=(uint8_t scale) ALWAYS_INLINE { + inline Color operator~() const ESPHOME_ALWAYS_INLINE { + return Color(255 - this->red, 255 - this->green, 255 - this->blue); + } + inline Color &operator*=(uint8_t scale) ESPHOME_ALWAYS_INLINE { this->red = esp_scale8(this->red, scale); this->green = esp_scale8(this->green, scale); this->blue = esp_scale8(this->blue, scale); this->white = esp_scale8(this->white, scale); return *this; } - inline Color operator*(const Color &scale) const ALWAYS_INLINE { + inline Color operator*(const Color &scale) const ESPHOME_ALWAYS_INLINE { return Color(esp_scale8(this->red, scale.red), esp_scale8(this->green, scale.green), esp_scale8(this->blue, scale.blue), esp_scale8(this->white, scale.white)); } - inline Color &operator*=(const Color &scale) ALWAYS_INLINE { + inline Color &operator*=(const Color &scale) ESPHOME_ALWAYS_INLINE { this->red = esp_scale8(this->red, scale.red); this->green = esp_scale8(this->green, scale.green); this->blue = esp_scale8(this->blue, scale.blue); this->white = esp_scale8(this->white, scale.white); return *this; } - inline Color operator+(const Color &add) const ALWAYS_INLINE { + inline Color operator+(const Color &add) const ESPHOME_ALWAYS_INLINE { Color ret; if (uint8_t(add.r + this->r) < this->r) ret.r = 255; @@ -101,10 +103,10 @@ struct Color { ret.w = this->w + add.w; return ret; } - inline Color &operator+=(const Color &add) ALWAYS_INLINE { return *this = (*this) + add; } - inline Color operator+(uint8_t add) const ALWAYS_INLINE { return (*this) + Color(add, add, add, add); } - inline Color &operator+=(uint8_t add) ALWAYS_INLINE { return *this = (*this) + add; } - inline Color operator-(const Color &subtract) const ALWAYS_INLINE { + inline Color &operator+=(const Color &add) ESPHOME_ALWAYS_INLINE { return *this = (*this) + add; } + inline Color operator+(uint8_t add) const ESPHOME_ALWAYS_INLINE { return (*this) + Color(add, add, add, add); } + inline Color &operator+=(uint8_t add) ESPHOME_ALWAYS_INLINE { return *this = (*this) + add; } + inline Color operator-(const Color &subtract) const ESPHOME_ALWAYS_INLINE { Color ret; if (subtract.r > this->r) ret.r = 0; @@ -124,11 +126,11 @@ struct Color { ret.w = this->w - subtract.w; return ret; } - inline Color &operator-=(const Color &subtract) ALWAYS_INLINE { return *this = (*this) - subtract; } - inline Color operator-(uint8_t subtract) const ALWAYS_INLINE { + inline Color &operator-=(const Color &subtract) ESPHOME_ALWAYS_INLINE { return *this = (*this) - subtract; } + inline Color operator-(uint8_t subtract) const ESPHOME_ALWAYS_INLINE { return (*this) - Color(subtract, subtract, subtract, subtract); } - inline Color &operator-=(uint8_t subtract) ALWAYS_INLINE { return *this = (*this) - subtract; } + inline Color &operator-=(uint8_t subtract) ESPHOME_ALWAYS_INLINE { return *this = (*this) - subtract; } static Color random_color() { uint32_t rand = random_uint32(); uint8_t w = rand >> 24; diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index b2d72b0fab..809e7d6767 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -24,7 +24,7 @@ #define HOT __attribute__((hot)) #define ESPDEPRECATED(msg, when) __attribute__((deprecated(msg))) -#define ALWAYS_INLINE __attribute__((always_inline)) +#define ESPHOME_ALWAYS_INLINE __attribute__((always_inline)) #define PACKED __attribute__((packed)) // Various functions can be constexpr in C++14, but not in C++11 (because their body isn't just a return statement). From 8796a4c1a7b0446f77aa439692a2ca0aab6648ee Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Mon, 6 May 2024 00:10:49 +0200 Subject: [PATCH 1371/2101] print task name if logger is called from other than main thread (#6630) --- esphome/components/logger/logger.cpp | 21 ++++++++++++++++++++- esphome/components/logger/logger.h | 1 + 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/esphome/components/logger/logger.cpp b/esphome/components/logger/logger.cpp index 166fe2693d..dac08fbbce 100644 --- a/esphome/components/logger/logger.cpp +++ b/esphome/components/logger/logger.cpp @@ -39,7 +39,23 @@ void Logger::write_header_(int level, const char *tag, int line) { const char *color = LOG_LEVEL_COLORS[level]; const char *letter = LOG_LEVEL_LETTERS[level]; - this->printf_to_buffer_("%s[%s][%s:%03u]: ", color, letter, tag, line); +#if defined(USE_ESP32) || defined(USE_LIBRETINY) + TaskHandle_t current_task = xTaskGetCurrentTaskHandle(); +#else + void *current_task = nullptr; +#endif + if (current_task == main_task_) { + this->printf_to_buffer_("%s[%s][%s:%03u]: ", color, letter, tag, line); + } else { + const char *thread_name = ""; +#if defined(USE_ESP32) + thread_name = pcTaskGetName(current_task); +#elif defined(USE_LIBRETINY) + thread_name = pcTaskGetTaskName(current_task); +#endif + this->printf_to_buffer_("%s[%s][%s:%03u]%s[%s]%s: ", color, letter, tag, line, + ESPHOME_LOG_BOLD(ESPHOME_LOG_COLOR_RED), thread_name, color); + } } void HOT Logger::log_vprintf_(int level, const char *tag, int line, const char *format, va_list args) { // NOLINT @@ -127,6 +143,9 @@ void HOT Logger::log_message_(int level, const char *tag, int offset) { 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 +#if defined(USE_ESP32) || defined(USE_LIBRETINY) + this->main_task_ = xTaskGetCurrentTaskHandle(); +#endif } #ifdef USE_LOGGER_USB_CDC diff --git a/esphome/components/logger/logger.h b/esphome/components/logger/logger.h index f6c1574ffb..b55cfb0771 100644 --- a/esphome/components/logger/logger.h +++ b/esphome/components/logger/logger.h @@ -167,6 +167,7 @@ class Logger : public Component { CallbackManager log_callback_{}; /// Prevents recursive log calls, if true a log message is already being processed. bool recursion_guard_ = false; + void *main_task_ = nullptr; }; extern Logger *global_logger; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) From f78397c77e4403f510d7b02bd3b5a0f54b5b284d Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Mon, 6 May 2024 00:12:09 +0200 Subject: [PATCH 1372/2101] Fix recent definitions into `defines.h` (#6667) Co-authored-by: Keith Burzinski --- esphome/core/defines.h | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/esphome/core/defines.h b/esphome/core/defines.h index b09373bcde..c2ad0f641c 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -15,18 +15,23 @@ #define ESPHOME_VARIANT "ESP32" // Feature flags +#define USE_ALARM_CONTROL_PANEL #define USE_API #define USE_API_NOISE #define USE_API_PLAINTEXT -#define USE_ALARM_CONTROL_PANEL #define USE_BINARY_SENSOR #define USE_BUTTON #define USE_CLIMATE #define USE_COVER +#define USE_DATETIME +#define USE_DATETIME_DATE +#define USE_DATETIME_DATETIME +#define USE_DATETIME_TIME #define USE_DEEP_SLEEP #define USE_EVENT #define USE_FAN #define USE_GRAPH +#define USE_GRAPHICAL_DISPLAY_MENU #define USE_HOMEASSISTANT_TIME #define USE_JSON #define USE_LIGHT @@ -37,10 +42,6 @@ #define USE_MQTT #define USE_NEXTION_TFT_UPLOAD #define USE_NUMBER -#define USE_DATETIME -#define USE_DATETIME_DATE -#define USE_DATETIME_TIME -#define USE_DATETIME_DATETIME #define USE_OTA #define USE_OTA_PASSWORD #define USE_OTA_STATE_CALLBACK @@ -60,7 +61,6 @@ #define USE_VALVE #define USE_WIFI #define USE_WIFI_AP -#define USE_GRAPHICAL_DISPLAY_MENU // Arduino-specific feature flags #ifdef USE_ARDUINO @@ -78,17 +78,19 @@ // ESP32-specific feature flags #ifdef USE_ESP32 +#define USE_BLUETOOTH_PROXY +#define USE_ESP32_BLE #define USE_ESP32_BLE_CLIENT #define USE_ESP32_BLE_SERVER #define USE_ESP32_CAMERA #define USE_IMPROV -#define USE_SOCKET_IMPL_BSD_SOCKETS -#define USE_WIFI_11KV_SUPPORT -#define USE_BLUETOOTH_PROXY -#define USE_VOICE_ASSISTANT #define USE_MICROPHONE +#define USE_PSRAM +#define USE_SOCKET_IMPL_BSD_SOCKETS #define USE_SPEAKER #define USE_SPI +#define USE_VOICE_ASSISTANT +#define USE_WIFI_11KV_SUPPORT #ifdef USE_ARDUINO #define USE_ARDUINO_VERSION_CODE VERSION_CODE(2, 0, 5) From 833d31ef7a0fdef1c434ec1d188b13a9e74d0091 Mon Sep 17 00:00:00 2001 From: mkmer Date: Sun, 5 May 2024 18:48:09 -0400 Subject: [PATCH 1373/2101] Add fast update to HMC5883L (#6669) --- esphome/components/hmc5883l/hmc5883l.cpp | 5 +++++ esphome/components/hmc5883l/hmc5883l.h | 1 + 2 files changed, 6 insertions(+) diff --git a/esphome/components/hmc5883l/hmc5883l.cpp b/esphome/components/hmc5883l/hmc5883l.cpp index de3903d7e2..24f4b3f8f1 100644 --- a/esphome/components/hmc5883l/hmc5883l.cpp +++ b/esphome/components/hmc5883l/hmc5883l.cpp @@ -1,5 +1,6 @@ #include "hmc5883l.h" #include "esphome/core/log.h" +#include "esphome/core/application.h" namespace esphome { namespace hmc5883l { @@ -31,6 +32,10 @@ void HMC5883LComponent::setup() { return; } + if (this->get_update_interval() < App.get_loop_interval()) { + high_freq_.start(); + } + if (id[0] != 0x48 || id[1] != 0x34 || id[2] != 0x33) { this->error_code_ = ID_REGISTERS; this->mark_failed(); diff --git a/esphome/components/hmc5883l/hmc5883l.h b/esphome/components/hmc5883l/hmc5883l.h index 3481f45dc8..06fba2af9d 100644 --- a/esphome/components/hmc5883l/hmc5883l.h +++ b/esphome/components/hmc5883l/hmc5883l.h @@ -63,6 +63,7 @@ class HMC5883LComponent : public PollingComponent, public i2c::I2CDevice { COMMUNICATION_FAILED, ID_REGISTERS, } error_code_; + HighFrequencyLoopRequester high_freq_; }; } // namespace hmc5883l From 599dbf27e068e4c69ad60b78ec11c5e46bb32992 Mon Sep 17 00:00:00 2001 From: Anton Viktorov Date: Mon, 6 May 2024 04:19:25 +0200 Subject: [PATCH 1374/2101] Minor tidy up of BME280 code (#6672) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/bme280_base/__init__.py | 107 ++++++++++++++++++ esphome/components/bme280_base/sensor.py | 106 ----------------- esphome/components/bme280_i2c/sensor.py | 8 +- esphome/components/bme280_spi/__init__.py | 1 - esphome/components/bme280_spi/bme280_spi.cpp | 29 +++-- esphome/components/bme280_spi/sensor.py | 13 +-- tests/components/bme280_i2c/common.yaml | 19 ++++ .../bme280_i2c/test.esp32-c3-idf.yaml | 21 +--- .../components/bme280_i2c/test.esp32-c3.yaml | 21 +--- .../components/bme280_i2c/test.esp32-idf.yaml | 21 +--- tests/components/bme280_i2c/test.esp32.yaml | 21 +--- tests/components/bme280_i2c/test.esp8266.yaml | 21 +--- tests/components/bme280_i2c/test.rp2040.yaml | 21 +--- tests/components/bme280_spi/common.yaml | 20 ++++ .../bme280_spi/test.esp32-c3-idf.yaml | 24 +--- .../components/bme280_spi/test.esp32-c3.yaml | 24 +--- .../components/bme280_spi/test.esp32-idf.yaml | 24 +--- tests/components/bme280_spi/test.esp32.yaml | 24 +--- tests/components/bme280_spi/test.esp8266.yaml | 24 +--- tests/components/bme280_spi/test.rp2040.yaml | 24 +--- tests/test1.yaml | 29 ----- 21 files changed, 231 insertions(+), 371 deletions(-) delete mode 100644 esphome/components/bme280_base/sensor.py create mode 100644 tests/components/bme280_i2c/common.yaml create mode 100644 tests/components/bme280_spi/common.yaml diff --git a/esphome/components/bme280_base/__init__.py b/esphome/components/bme280_base/__init__.py index f70ffa9520..6a5f7e1127 100644 --- a/esphome/components/bme280_base/__init__.py +++ b/esphome/components/bme280_base/__init__.py @@ -1 +1,108 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import sensor +from esphome.const import ( + CONF_HUMIDITY, + CONF_ID, + CONF_IIR_FILTER, + CONF_OVERSAMPLING, + CONF_PRESSURE, + CONF_TEMPERATURE, + DEVICE_CLASS_HUMIDITY, + DEVICE_CLASS_PRESSURE, + DEVICE_CLASS_TEMPERATURE, + STATE_CLASS_MEASUREMENT, + UNIT_CELSIUS, + UNIT_HECTOPASCAL, + UNIT_PERCENT, +) + CODEOWNERS = ["@esphome/core"] + +bme280_ns = cg.esphome_ns.namespace("bme280_base") +BME280Oversampling = bme280_ns.enum("BME280Oversampling") +OVERSAMPLING_OPTIONS = { + "NONE": BME280Oversampling.BME280_OVERSAMPLING_NONE, + "1X": BME280Oversampling.BME280_OVERSAMPLING_1X, + "2X": BME280Oversampling.BME280_OVERSAMPLING_2X, + "4X": BME280Oversampling.BME280_OVERSAMPLING_4X, + "8X": BME280Oversampling.BME280_OVERSAMPLING_8X, + "16X": BME280Oversampling.BME280_OVERSAMPLING_16X, +} + +BME280IIRFilter = bme280_ns.enum("BME280IIRFilter") +IIR_FILTER_OPTIONS = { + "OFF": BME280IIRFilter.BME280_IIR_FILTER_OFF, + "2X": BME280IIRFilter.BME280_IIR_FILTER_2X, + "4X": BME280IIRFilter.BME280_IIR_FILTER_4X, + "8X": BME280IIRFilter.BME280_IIR_FILTER_8X, + "16X": BME280IIRFilter.BME280_IIR_FILTER_16X, +} + +CONFIG_SCHEMA_BASE = cv.Schema( + { + 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="16X"): cv.enum( + OVERSAMPLING_OPTIONS, upper=True + ), + } + ), + cv.Optional(CONF_PRESSURE): sensor.sensor_schema( + unit_of_measurement=UNIT_HECTOPASCAL, + accuracy_decimals=1, + device_class=DEVICE_CLASS_PRESSURE, + state_class=STATE_CLASS_MEASUREMENT, + ).extend( + { + cv.Optional(CONF_OVERSAMPLING, default="16X"): cv.enum( + OVERSAMPLING_OPTIONS, upper=True + ), + } + ), + cv.Optional(CONF_HUMIDITY): sensor.sensor_schema( + unit_of_measurement=UNIT_PERCENT, + accuracy_decimals=1, + device_class=DEVICE_CLASS_HUMIDITY, + 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(temperature_config[CONF_OVERSAMPLING])) + + 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(pressure_config[CONF_OVERSAMPLING])) + + 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_humidity_oversampling(humidity_config[CONF_OVERSAMPLING])) + + cg.add(var.set_iir_filter(config[CONF_IIR_FILTER])) + + return var diff --git a/esphome/components/bme280_base/sensor.py b/esphome/components/bme280_base/sensor.py deleted file mode 100644 index 3a745ed348..0000000000 --- a/esphome/components/bme280_base/sensor.py +++ /dev/null @@ -1,106 +0,0 @@ -import esphome.codegen as cg -import esphome.config_validation as cv -from esphome.components import sensor -from esphome.const import ( - CONF_HUMIDITY, - CONF_ID, - CONF_IIR_FILTER, - CONF_OVERSAMPLING, - CONF_PRESSURE, - CONF_TEMPERATURE, - DEVICE_CLASS_HUMIDITY, - DEVICE_CLASS_PRESSURE, - DEVICE_CLASS_TEMPERATURE, - STATE_CLASS_MEASUREMENT, - UNIT_CELSIUS, - UNIT_HECTOPASCAL, - UNIT_PERCENT, -) - -bme280_ns = cg.esphome_ns.namespace("bme280_base") -BME280Oversampling = bme280_ns.enum("BME280Oversampling") -OVERSAMPLING_OPTIONS = { - "NONE": BME280Oversampling.BME280_OVERSAMPLING_NONE, - "1X": BME280Oversampling.BME280_OVERSAMPLING_1X, - "2X": BME280Oversampling.BME280_OVERSAMPLING_2X, - "4X": BME280Oversampling.BME280_OVERSAMPLING_4X, - "8X": BME280Oversampling.BME280_OVERSAMPLING_8X, - "16X": BME280Oversampling.BME280_OVERSAMPLING_16X, -} - -BME280IIRFilter = bme280_ns.enum("BME280IIRFilter") -IIR_FILTER_OPTIONS = { - "OFF": BME280IIRFilter.BME280_IIR_FILTER_OFF, - "2X": BME280IIRFilter.BME280_IIR_FILTER_2X, - "4X": BME280IIRFilter.BME280_IIR_FILTER_4X, - "8X": BME280IIRFilter.BME280_IIR_FILTER_8X, - "16X": BME280IIRFilter.BME280_IIR_FILTER_16X, -} - -CONFIG_SCHEMA_BASE = cv.Schema( - { - 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="16X"): cv.enum( - OVERSAMPLING_OPTIONS, upper=True - ), - } - ), - cv.Optional(CONF_PRESSURE): sensor.sensor_schema( - unit_of_measurement=UNIT_HECTOPASCAL, - accuracy_decimals=1, - device_class=DEVICE_CLASS_PRESSURE, - state_class=STATE_CLASS_MEASUREMENT, - ).extend( - { - cv.Optional(CONF_OVERSAMPLING, default="16X"): cv.enum( - OVERSAMPLING_OPTIONS, upper=True - ), - } - ), - cv.Optional(CONF_HUMIDITY): sensor.sensor_schema( - unit_of_measurement=UNIT_PERCENT, - accuracy_decimals=1, - device_class=DEVICE_CLASS_HUMIDITY, - 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(config, func=None): - var = cg.new_Pvariable(config[CONF_ID]) - await cg.register_component(var, config) - if func is not None: - await func(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(temperature_config[CONF_OVERSAMPLING])) - - 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(pressure_config[CONF_OVERSAMPLING])) - - 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_humidity_oversampling(humidity_config[CONF_OVERSAMPLING])) - - cg.add(var.set_iir_filter(config[CONF_IIR_FILTER])) diff --git a/esphome/components/bme280_i2c/sensor.py b/esphome/components/bme280_i2c/sensor.py index 489c52969d..f3007ebaac 100644 --- a/esphome/components/bme280_i2c/sensor.py +++ b/esphome/components/bme280_i2c/sensor.py @@ -1,9 +1,10 @@ import esphome.codegen as cg +import esphome.config_validation as cv from esphome.components import i2c -from ..bme280_base.sensor import to_code as to_code_base, cv, CONFIG_SCHEMA_BASE +from ..bme280_base import to_code_base, CONFIG_SCHEMA_BASE -DEPENDENCIES = ["i2c"] AUTO_LOAD = ["bme280_base"] +DEPENDENCIES = ["i2c"] bme280_ns = cg.esphome_ns.namespace("bme280_i2c") BME280I2CComponent = bme280_ns.class_( @@ -16,4 +17,5 @@ CONFIG_SCHEMA = CONFIG_SCHEMA_BASE.extend( async def to_code(config): - await to_code_base(config, func=i2c.register_i2c_device) + var = await to_code_base(config) + await i2c.register_i2c_device(var, config) diff --git a/esphome/components/bme280_spi/__init__.py b/esphome/components/bme280_spi/__init__.py index a1d33e4d7a..e69de29bb2 100644 --- a/esphome/components/bme280_spi/__init__.py +++ b/esphome/components/bme280_spi/__init__.py @@ -1 +0,0 @@ -CODEOWNERS = ["@apbodrov"] diff --git a/esphome/components/bme280_spi/bme280_spi.cpp b/esphome/components/bme280_spi/bme280_spi.cpp index 921128c8f5..c6ebfdfd0b 100644 --- a/esphome/components/bme280_spi/bme280_spi.cpp +++ b/esphome/components/bme280_spi/bme280_spi.cpp @@ -4,19 +4,19 @@ #include "bme280_spi.h" #include -int set_bit(uint8_t num, int position) { +namespace esphome { +namespace bme280_spi { + +uint8_t set_bit(uint8_t num, int position) { int mask = 1 << position; return num | mask; } -int clear_bit(uint8_t num, int position) { +uint8_t clear_bit(uint8_t num, int position) { int mask = 1 << position; return num & ~mask; } -namespace esphome { -namespace bme280_spi { - void BME280SPIComponent::setup() { this->spi_setup(); BME280Component::setup(); @@ -30,34 +30,33 @@ void BME280SPIComponent::setup() { bool BME280SPIComponent::read_byte(uint8_t a_register, uint8_t *data) { this->enable(); - // cause: *data = this->delegate_->transfer(tmp) doesnt work - this->delegate_->transfer(set_bit(a_register, 7)); - *data = this->delegate_->transfer(0); + this->transfer_byte(set_bit(a_register, 7)); + *data = this->transfer_byte(0); this->disable(); return true; } bool BME280SPIComponent::write_byte(uint8_t a_register, uint8_t data) { this->enable(); - this->delegate_->transfer(clear_bit(a_register, 7)); - this->delegate_->transfer(data); + this->transfer_byte(clear_bit(a_register, 7)); + this->transfer_byte(data); this->disable(); return true; } bool BME280SPIComponent::read_bytes(uint8_t a_register, uint8_t *data, size_t len) { this->enable(); - this->delegate_->transfer(set_bit(a_register, 7)); - this->delegate_->read_array(data, len); + this->transfer_byte(set_bit(a_register, 7)); + this->read_array(data, len); this->disable(); return true; } bool BME280SPIComponent::read_byte_16(uint8_t a_register, uint16_t *data) { this->enable(); - this->delegate_->transfer(set_bit(a_register, 7)); - ((uint8_t *) data)[1] = this->delegate_->transfer(0); - ((uint8_t *) data)[0] = this->delegate_->transfer(0); + this->transfer_byte(set_bit(a_register, 7)); + ((uint8_t *) data)[1] = this->transfer_byte(0); + ((uint8_t *) data)[0] = this->transfer_byte(0); this->disable(); return true; } diff --git a/esphome/components/bme280_spi/sensor.py b/esphome/components/bme280_spi/sensor.py index 3cfe1b3cdd..33a12318a5 100644 --- a/esphome/components/bme280_spi/sensor.py +++ b/esphome/components/bme280_spi/sensor.py @@ -1,13 +1,11 @@ import esphome.codegen as cg +import esphome.config_validation as cv from esphome.components import spi -from esphome.components.bme280_base.sensor import ( - to_code as to_code_base, - cv, - CONFIG_SCHEMA_BASE, -) +from ..bme280_base import to_code_base, CONFIG_SCHEMA_BASE -DEPENDENCIES = ["spi"] AUTO_LOAD = ["bme280_base"] +CODEOWNERS = ["@apbodrov"] +DEPENDENCIES = ["spi"] bme280_spi_ns = cg.esphome_ns.namespace("bme280_spi") @@ -21,4 +19,5 @@ CONFIG_SCHEMA = CONFIG_SCHEMA_BASE.extend(spi.spi_device_schema()).extend( async def to_code(config): - await to_code_base(config, func=spi.register_spi_device) + var = await to_code_base(config) + await spi.register_spi_device(var, config) diff --git a/tests/components/bme280_i2c/common.yaml b/tests/components/bme280_i2c/common.yaml new file mode 100644 index 0000000000..e74ce9bf6d --- /dev/null +++ b/tests/components/bme280_i2c/common.yaml @@ -0,0 +1,19 @@ +i2c: + - id: i2c_bme280 + scl: ${scl_pin} + sda: ${sda_pin} + +sensor: + - platform: bme280_i2c + i2c_id: i2c_bme280 + address: 0x76 + temperature: + id: bme280_temperature + name: BME280 Temperature + humidity: + id: bme280_humidity + name: BME280 Humidity + pressure: + id: bme280_pressure + name: BME280 Pressure + update_interval: 15s diff --git a/tests/components/bme280_i2c/test.esp32-c3-idf.yaml b/tests/components/bme280_i2c/test.esp32-c3-idf.yaml index 070c2845d9..ee2c29ca4e 100644 --- a/tests/components/bme280_i2c/test.esp32-c3-idf.yaml +++ b/tests/components/bme280_i2c/test.esp32-c3-idf.yaml @@ -1,18 +1,5 @@ -i2c: - - id: i2c_bme280 - scl: 5 - sda: 4 +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 -sensor: - - platform: bme280_i2c - address: 0x76 - temperature: - id: bme280_temperature - name: BME280 Temperature - humidity: - id: bme280_humidity - name: BME280 Humidity - pressure: - id: bme280_pressure - name: BME280 Pressure - update_interval: 15s +<<: !include common.yaml diff --git a/tests/components/bme280_i2c/test.esp32-c3.yaml b/tests/components/bme280_i2c/test.esp32-c3.yaml index 070c2845d9..ee2c29ca4e 100644 --- a/tests/components/bme280_i2c/test.esp32-c3.yaml +++ b/tests/components/bme280_i2c/test.esp32-c3.yaml @@ -1,18 +1,5 @@ -i2c: - - id: i2c_bme280 - scl: 5 - sda: 4 +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 -sensor: - - platform: bme280_i2c - address: 0x76 - temperature: - id: bme280_temperature - name: BME280 Temperature - humidity: - id: bme280_humidity - name: BME280 Humidity - pressure: - id: bme280_pressure - name: BME280 Pressure - update_interval: 15s +<<: !include common.yaml diff --git a/tests/components/bme280_i2c/test.esp32-idf.yaml b/tests/components/bme280_i2c/test.esp32-idf.yaml index e379b98874..63c3bd6afd 100644 --- a/tests/components/bme280_i2c/test.esp32-idf.yaml +++ b/tests/components/bme280_i2c/test.esp32-idf.yaml @@ -1,18 +1,5 @@ -i2c: - - id: i2c_bme280 - scl: 16 - sda: 17 +substitutions: + scl_pin: GPIO16 + sda_pin: GPIO17 -sensor: - - platform: bme280_i2c - address: 0x76 - temperature: - id: bme280_temperature - name: BME280 Temperature - humidity: - id: bme280_humidity - name: BME280 Humidity - pressure: - id: bme280_pressure - name: BME280 Pressure - update_interval: 15s +<<: !include common.yaml diff --git a/tests/components/bme280_i2c/test.esp32.yaml b/tests/components/bme280_i2c/test.esp32.yaml index e379b98874..63c3bd6afd 100644 --- a/tests/components/bme280_i2c/test.esp32.yaml +++ b/tests/components/bme280_i2c/test.esp32.yaml @@ -1,18 +1,5 @@ -i2c: - - id: i2c_bme280 - scl: 16 - sda: 17 +substitutions: + scl_pin: GPIO16 + sda_pin: GPIO17 -sensor: - - platform: bme280_i2c - address: 0x76 - temperature: - id: bme280_temperature - name: BME280 Temperature - humidity: - id: bme280_humidity - name: BME280 Humidity - pressure: - id: bme280_pressure - name: BME280 Pressure - update_interval: 15s +<<: !include common.yaml diff --git a/tests/components/bme280_i2c/test.esp8266.yaml b/tests/components/bme280_i2c/test.esp8266.yaml index 070c2845d9..ee2c29ca4e 100644 --- a/tests/components/bme280_i2c/test.esp8266.yaml +++ b/tests/components/bme280_i2c/test.esp8266.yaml @@ -1,18 +1,5 @@ -i2c: - - id: i2c_bme280 - scl: 5 - sda: 4 +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 -sensor: - - platform: bme280_i2c - address: 0x76 - temperature: - id: bme280_temperature - name: BME280 Temperature - humidity: - id: bme280_humidity - name: BME280 Humidity - pressure: - id: bme280_pressure - name: BME280 Pressure - update_interval: 15s +<<: !include common.yaml diff --git a/tests/components/bme280_i2c/test.rp2040.yaml b/tests/components/bme280_i2c/test.rp2040.yaml index 070c2845d9..ee2c29ca4e 100644 --- a/tests/components/bme280_i2c/test.rp2040.yaml +++ b/tests/components/bme280_i2c/test.rp2040.yaml @@ -1,18 +1,5 @@ -i2c: - - id: i2c_bme280 - scl: 5 - sda: 4 +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 -sensor: - - platform: bme280_i2c - address: 0x76 - temperature: - id: bme280_temperature - name: BME280 Temperature - humidity: - id: bme280_humidity - name: BME280 Humidity - pressure: - id: bme280_pressure - name: BME280 Pressure - update_interval: 15s +<<: !include common.yaml diff --git a/tests/components/bme280_spi/common.yaml b/tests/components/bme280_spi/common.yaml new file mode 100644 index 0000000000..303ecf9f73 --- /dev/null +++ b/tests/components/bme280_spi/common.yaml @@ -0,0 +1,20 @@ +spi: + - id: spi_bme280 + clk_pin: ${clk_pin} + mosi_pin: ${mosi_pin} + miso_pin: ${miso_pin} + +sensor: + - platform: bme280_spi + spi_id: spi_bme280 + cs_pin: ${cs_pin} + temperature: + id: bme280_temperature + name: BME280 Temperature + humidity: + id: bme280_humidity + name: BME280 Humidity + pressure: + id: bme280_pressure + name: BME280 Pressure + update_interval: 15s diff --git a/tests/components/bme280_spi/test.esp32-c3-idf.yaml b/tests/components/bme280_spi/test.esp32-c3-idf.yaml index 4bc7c14e6c..2415ba5dc6 100644 --- a/tests/components/bme280_spi/test.esp32-c3-idf.yaml +++ b/tests/components/bme280_spi/test.esp32-c3-idf.yaml @@ -1,19 +1,7 @@ -spi: - - id: spi_bme280 - clk_pin: 6 - mosi_pin: 7 - miso_pin: 5 +substitutions: + clk_pin: GPIO6 + mosi_pin: GPIO7 + miso_pin: GPIO5 + cs_pin: GPIO8 -sensor: - - platform: bme280_spi - cs_pin: 8 - temperature: - id: bme280_temperature - name: BME280 Temperature - humidity: - id: bme280_humidity - name: BME280 Humidity - pressure: - id: bme280_pressure - name: BME280 Pressure - update_interval: 15s +<<: !include common.yaml diff --git a/tests/components/bme280_spi/test.esp32-c3.yaml b/tests/components/bme280_spi/test.esp32-c3.yaml index 4bc7c14e6c..2415ba5dc6 100644 --- a/tests/components/bme280_spi/test.esp32-c3.yaml +++ b/tests/components/bme280_spi/test.esp32-c3.yaml @@ -1,19 +1,7 @@ -spi: - - id: spi_bme280 - clk_pin: 6 - mosi_pin: 7 - miso_pin: 5 +substitutions: + clk_pin: GPIO6 + mosi_pin: GPIO7 + miso_pin: GPIO5 + cs_pin: GPIO8 -sensor: - - platform: bme280_spi - cs_pin: 8 - temperature: - id: bme280_temperature - name: BME280 Temperature - humidity: - id: bme280_humidity - name: BME280 Humidity - pressure: - id: bme280_pressure - name: BME280 Pressure - update_interval: 15s +<<: !include common.yaml diff --git a/tests/components/bme280_spi/test.esp32-idf.yaml b/tests/components/bme280_spi/test.esp32-idf.yaml index ebb3d98213..54e027a614 100644 --- a/tests/components/bme280_spi/test.esp32-idf.yaml +++ b/tests/components/bme280_spi/test.esp32-idf.yaml @@ -1,19 +1,7 @@ -spi: - - id: spi_bme280 - clk_pin: 16 - mosi_pin: 17 - miso_pin: 15 +substitutions: + clk_pin: GPIO16 + mosi_pin: GPIO17 + miso_pin: GPIO15 + cs_pin: GPIO5 -sensor: - - platform: bme280_spi - cs_pin: 12 - temperature: - id: bme280_temperature - name: BME280 Temperature - humidity: - id: bme280_humidity - name: BME280 Humidity - pressure: - id: bme280_pressure - name: BME280 Pressure - update_interval: 15s +<<: !include common.yaml diff --git a/tests/components/bme280_spi/test.esp32.yaml b/tests/components/bme280_spi/test.esp32.yaml index ebb3d98213..54e027a614 100644 --- a/tests/components/bme280_spi/test.esp32.yaml +++ b/tests/components/bme280_spi/test.esp32.yaml @@ -1,19 +1,7 @@ -spi: - - id: spi_bme280 - clk_pin: 16 - mosi_pin: 17 - miso_pin: 15 +substitutions: + clk_pin: GPIO16 + mosi_pin: GPIO17 + miso_pin: GPIO15 + cs_pin: GPIO5 -sensor: - - platform: bme280_spi - cs_pin: 12 - temperature: - id: bme280_temperature - name: BME280 Temperature - humidity: - id: bme280_humidity - name: BME280 Humidity - pressure: - id: bme280_pressure - name: BME280 Pressure - update_interval: 15s +<<: !include common.yaml diff --git a/tests/components/bme280_spi/test.esp8266.yaml b/tests/components/bme280_spi/test.esp8266.yaml index 63013abb87..dbd158d030 100644 --- a/tests/components/bme280_spi/test.esp8266.yaml +++ b/tests/components/bme280_spi/test.esp8266.yaml @@ -1,19 +1,7 @@ -spi: - - id: spi_bme280 - clk_pin: 14 - mosi_pin: 13 - miso_pin: 12 +substitutions: + clk_pin: GPIO14 + mosi_pin: GPIO13 + miso_pin: GPIO12 + cs_pin: GPIO15 -sensor: - - platform: bme280_spi - cs_pin: 15 - temperature: - id: bme280_temperature - name: BME280 Temperature - humidity: - id: bme280_humidity - name: BME280 Humidity - pressure: - id: bme280_pressure - name: BME280 Pressure - update_interval: 15s +<<: !include common.yaml diff --git a/tests/components/bme280_spi/test.rp2040.yaml b/tests/components/bme280_spi/test.rp2040.yaml index ba5cb483c6..f6c3f1eeca 100644 --- a/tests/components/bme280_spi/test.rp2040.yaml +++ b/tests/components/bme280_spi/test.rp2040.yaml @@ -1,19 +1,7 @@ -spi: - - id: spi_bme280 - clk_pin: 2 - mosi_pin: 3 - miso_pin: 4 +substitutions: + clk_pin: GPIO2 + mosi_pin: GPIO3 + miso_pin: GPIO4 + cs_pin: GPIO5 -sensor: - - platform: bme280_spi - cs_pin: 6 - temperature: - id: bme280_temperature - name: BME280 Temperature - humidity: - id: bme280_humidity - name: BME280 Humidity - pressure: - id: bme280_pressure - name: BME280 Pressure - update_interval: 15s +<<: !include common.yaml diff --git a/tests/test1.yaml b/tests/test1.yaml index 09994afa42..79b836da4a 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -705,35 +705,6 @@ sensor: update_interval: 30s mode: low_power i2c_id: i2c_bus - - platform: bme280_i2c - temperature: - name: Outside Temperature - oversampling: 16x - pressure: - name: Outside Pressure - oversampling: none - humidity: - name: Outside Humidity - oversampling: 8x - address: 0x77 - iir_filter: 16x - update_interval: 15s - i2c_id: i2c_bus - - platform: bme280_spi - temperature: - name: Outside Temperature - oversampling: 16x - pressure: - name: Outside Pressure - oversampling: none - humidity: - name: Outside Humidity - oversampling: 8x - cs_pin: - allow_other_uses: true - number: GPIO23 - iir_filter: 16x - update_interval: 15s - platform: bme680 temperature: name: Outside Temperature From f2caaf85c89f35fb65d136f38f558da62eb442fa Mon Sep 17 00:00:00 2001 From: Tomek Wasilczyk Date: Sun, 5 May 2024 20:19:13 -0700 Subject: [PATCH 1375/2101] External components: optional configurable path for git source (#6677) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/external_components/__init__.py | 11 ++++++++++- esphome/config_validation.py | 1 + 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/esphome/components/external_components/__init__.py b/esphome/components/external_components/__init__.py index bbb703dc5c..f4432a0362 100644 --- a/esphome/components/external_components/__init__.py +++ b/esphome/components/external_components/__init__.py @@ -49,7 +49,16 @@ def _process_git_config(config: dict, refresh) -> str: password=config.get(CONF_PASSWORD), ) - if (repo_dir / "esphome" / "components").is_dir(): + if path := config.get(CONF_PATH): + if (repo_dir / path).is_dir(): + components_dir = repo_dir / path + else: + raise cv.Invalid( + "Could not find components folder for source. Please check the source contains a '" + + path + + "' folder" + ) + elif (repo_dir / "esphome" / "components").is_dir(): components_dir = repo_dir / "esphome" / "components" elif (repo_dir / "components").is_dir(): components_dir = repo_dir / "components" diff --git a/esphome/config_validation.py b/esphome/config_validation.py index 198b44f38d..3554f03836 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -2124,6 +2124,7 @@ GIT_SCHEMA = Schema( Optional(CONF_REF): git_ref, Optional(CONF_USERNAME): string, Optional(CONF_PASSWORD): string, + Optional(CONF_PATH): string, } ) LOCAL_SCHEMA = Schema( From d1758a46bd24c9631e55d500d61da7ff522627e7 Mon Sep 17 00:00:00 2001 From: Markus <974709+Links2004@users.noreply.github.com> Date: Mon, 6 May 2024 21:17:03 +0200 Subject: [PATCH 1376/2101] Use clang-apply-replacements when clang-apply-replacements-14 does not exist (#6684) --- script/clang-tidy | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/script/clang-tidy b/script/clang-tidy index 97e4ba0d48..84b02306d5 100755 --- a/script/clang-tidy +++ b/script/clang-tidy @@ -266,7 +266,12 @@ def main(): if args.fix and failed_files: print("Applying fixes ...") try: - subprocess.call(["clang-apply-replacements-14", tmpdir]) + try: + subprocess.call(["clang-apply-replacements-14", tmpdir]) + except FileNotFoundError: + subprocess.call(["clang-apply-replacements", tmpdir]) + except FileNotFoundError: + print("Error please install clang-apply-replacements-14 or clang-apply-replacements.\n", file=sys.stderr) except: print("Error applying fixes.\n", file=sys.stderr) raise From 8463f897e1a7992c87c608270394563dee6e9a66 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Mon, 6 May 2024 21:20:01 +0200 Subject: [PATCH 1377/2101] fix conflict with EMPTY macro in zephyr (#6679) --- esphome/core/automation.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/core/automation.h b/esphome/core/automation.h index 8c3da5e7e8..9b62640a0c 100644 --- a/esphome/core/automation.h +++ b/esphome/core/automation.h @@ -24,7 +24,7 @@ template struct gens<0, S...> { using type = seq; }; // NOLINT template class TemplatableValue { public: - TemplatableValue() : type_(EMPTY) {} + TemplatableValue() : type_(NONE) {} template::value, int> = 0> TemplatableValue(F value) : type_(VALUE), value_(value) {} @@ -32,13 +32,13 @@ template class TemplatableValue { template::value, int> = 0> TemplatableValue(F f) : type_(LAMBDA), f_(f) {} - bool has_value() { return this->type_ != EMPTY; } + bool has_value() { return this->type_ != NONE; } T value(X... x) { if (this->type_ == LAMBDA) { return this->f_(x...); } - // return value also when empty + // return value also when none return this->value_; } @@ -58,7 +58,7 @@ template class TemplatableValue { protected: enum { - EMPTY, + NONE, VALUE, LAMBDA, } type_; From 594769be3ca9bb082fea9c56cc8922b69a483f0e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 May 2024 09:09:04 +1200 Subject: [PATCH 1378/2101] Bump actions/checkout from 4.1.1 to 4.1.5 (#6685) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-api-proto.yml | 2 +- .github/workflows/ci-docker.yml | 2 +- .github/workflows/ci.yml | 32 +++++++++++------------ .github/workflows/release.yml | 8 +++--- .github/workflows/sync-device-classes.yml | 4 +-- .github/workflows/yaml-lint.yml | 2 +- 6 files changed, 25 insertions(+), 25 deletions(-) diff --git a/.github/workflows/ci-api-proto.yml b/.github/workflows/ci-api-proto.yml index 40766ad728..448d0fd10f 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@v4.1.1 + uses: actions/checkout@v4.1.5 - name: Set up Python uses: actions/setup-python@v5.1.0 with: diff --git a/.github/workflows/ci-docker.yml b/.github/workflows/ci-docker.yml index 6063d1e052..72a16233fb 100644 --- a/.github/workflows/ci-docker.yml +++ b/.github/workflows/ci-docker.yml @@ -40,7 +40,7 @@ jobs: arch: [amd64, armv7, aarch64] build_type: ["ha-addon", "docker", "lint"] steps: - - uses: actions/checkout@v4.1.1 + - uses: actions/checkout@v4.1.5 - name: Set up Python uses: actions/setup-python@v5.1.0 with: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fd7a45ff50..fbebc55676 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,7 +34,7 @@ jobs: cache-key: ${{ steps.cache-key.outputs.key }} steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.5 - name: Generate cache-key id: cache-key run: echo key="${{ hashFiles('requirements.txt', 'requirements_optional.txt', 'requirements_test.txt') }}" >> $GITHUB_OUTPUT @@ -66,7 +66,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.5 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -87,7 +87,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.5 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -108,7 +108,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.5 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -129,7 +129,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.5 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -150,7 +150,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.5 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -199,7 +199,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.5 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -229,7 +229,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.5 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -254,7 +254,7 @@ jobs: matrix: ${{ steps.set-matrix.outputs.matrix }} steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.5 - name: Find all YAML test files id: set-matrix run: echo "matrix=$(ls tests/test*.yaml | jq -R -s -c 'split("\n")[:-1]')" >> $GITHUB_OUTPUT @@ -271,7 +271,7 @@ jobs: file: ${{ fromJson(needs.compile-tests-list.outputs.matrix) }} steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.5 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -303,7 +303,7 @@ jobs: file: ${{ fromJson(needs.compile-tests-list.outputs.matrix) }} steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.5 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -358,7 +358,7 @@ jobs: steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.5 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -402,7 +402,7 @@ jobs: count: ${{ steps.list-components.outputs.count }} steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.5 with: # Fetch enough history so `git merge-base refs/remotes/origin/dev HEAD` works. fetch-depth: 500 @@ -450,7 +450,7 @@ jobs: run: sudo apt-get install libsodium-dev - name: Check out code from GitHub - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.5 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -476,7 +476,7 @@ jobs: matrix: ${{ steps.split.outputs.components }} steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.5 - name: Split components into 20 groups id: split run: | @@ -504,7 +504,7 @@ jobs: run: sudo apt-get install libsodium-dev - name: Check out code from GitHub - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.5 - name: Restore Python uses: ./.github/actions/restore-python with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 72b06ab4fe..6d91d00b85 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,7 +19,7 @@ jobs: tag: ${{ steps.tag.outputs.tag }} branch_build: ${{ steps.tag.outputs.branch_build }} steps: - - uses: actions/checkout@v4.1.1 + - uses: actions/checkout@v4.1.5 - name: Get tag id: tag # yamllint disable rule:line-length @@ -51,7 +51,7 @@ jobs: contents: read id-token: write steps: - - uses: actions/checkout@v4.1.1 + - uses: actions/checkout@v4.1.5 - name: Set up Python uses: actions/setup-python@v5.1.0 with: @@ -81,7 +81,7 @@ jobs: - linux/arm/v7 - linux/arm64 steps: - - uses: actions/checkout@v4.1.1 + - uses: actions/checkout@v4.1.5 - name: Set up Python uses: actions/setup-python@v5.1.0 with: @@ -159,7 +159,7 @@ jobs: - ghcr - dockerhub steps: - - uses: actions/checkout@v4.1.1 + - uses: actions/checkout@v4.1.5 - name: Download digests uses: actions/download-artifact@v3.0.2 with: diff --git a/.github/workflows/sync-device-classes.yml b/.github/workflows/sync-device-classes.yml index c9614618d5..7d67999b77 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@v4.1.1 + uses: actions/checkout@v4.1.5 - name: Checkout Home Assistant - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.5 with: repository: home-assistant/core path: lib/home-assistant diff --git a/.github/workflows/yaml-lint.yml b/.github/workflows/yaml-lint.yml index a3c1937e56..761247529b 100644 --- a/.github/workflows/yaml-lint.yml +++ b/.github/workflows/yaml-lint.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.5 - name: Run yamllint uses: frenck/action-yamllint@v1.5.0 with: From 5ee2a5f9352ded83fbd080923c44b3f98ce2d0f2 Mon Sep 17 00:00:00 2001 From: RFDarter Date: Tue, 7 May 2024 00:44:49 +0200 Subject: [PATCH 1379/2101] Fix Datetime-Datetime compiler error (#6686) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/template/datetime/template_datetime.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/template/datetime/template_datetime.h b/esphome/components/template/datetime/template_datetime.h index cb1fd01132..ef80ded89a 100644 --- a/esphome/components/template/datetime/template_datetime.h +++ b/esphome/components/template/datetime/template_datetime.h @@ -2,7 +2,7 @@ #include "esphome/core/defines.h" -#ifdef USE_DATETIME_TIME +#ifdef USE_DATETIME_DATETIME #include "esphome/components/datetime/datetime_entity.h" #include "esphome/core/automation.h" @@ -43,4 +43,4 @@ class TemplateDateTime : public datetime::DateTimeEntity, public PollingComponen } // namespace template_ } // namespace esphome -#endif // USE_DATETIME_TIME +#endif // USE_DATETIME_DATETIME From 7b0536fda35b49478e2b764997ec689b8d844175 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 7 May 2024 11:54:01 +1200 Subject: [PATCH 1380/2101] Bump esphome/ESPAsyncWebServer-esphome to 3.2.0 (#6687) --- esphome/components/web_server_base/__init__.py | 2 +- platformio.ini | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/web_server_base/__init__.py b/esphome/components/web_server_base/__init__.py index 6491446bcc..1970b5a0c5 100644 --- a/esphome/components/web_server_base/__init__.py +++ b/esphome/components/web_server_base/__init__.py @@ -37,4 +37,4 @@ async def to_code(config): cg.add_library("FS", None) cg.add_library("Update", None) # https://github.com/esphome/ESPAsyncWebServer/blob/master/library.json - cg.add_library("esphome/ESPAsyncWebServer-esphome", "3.1.0") + cg.add_library("esphome/ESPAsyncWebServer-esphome", "3.2.0") diff --git a/platformio.ini b/platformio.ini index 5fedd14086..e699057fa3 100644 --- a/platformio.ini +++ b/platformio.ini @@ -58,7 +58,7 @@ lib_deps = SPI ; spi (Arduino built-in) Wire ; i2c (Arduino built-int) heman/AsyncMqttClient-esphome@1.0.0 ; mqtt - esphome/ESPAsyncWebServer-esphome@2.1.0 ; web_server_base + esphome/ESPAsyncWebServer-esphome@3.2.0 ; web_server_base fastled/FastLED@3.3.2 ; fastled_base mikalhart/TinyGPSPlus@1.0.2 ; gps freekode/TM1651@1.0.1 ; tm1651 From 1e196bac985e44a9121c937c60b1ada4e54772a8 Mon Sep 17 00:00:00 2001 From: RFDarter Date: Tue, 7 May 2024 02:47:07 +0200 Subject: [PATCH 1381/2101] fix date_time validation (#6688) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/datetime/__init__.py | 8 +- .../components/template/datetime/__init__.py | 10 ++- esphome/config_validation.py | 75 +++++++++---------- tests/components/template/common.yaml | 3 + 4 files changed, 49 insertions(+), 47 deletions(-) diff --git a/esphome/components/datetime/__init__.py b/esphome/components/datetime/__init__.py index 639a035159..3d08e4a6d0 100644 --- a/esphome/components/datetime/__init__.py +++ b/esphome/components/datetime/__init__.py @@ -169,7 +169,7 @@ async def to_code(config): { cv.Required(CONF_ID): cv.use_id(DateEntity), cv.Required(CONF_DATE): cv.Any( - cv.returning_lambda, cv.date_time(allowed_time=False) + cv.returning_lambda, cv.date_time(date=True, time=False) ), } ), @@ -200,7 +200,7 @@ async def datetime_date_set_to_code(config, action_id, template_arg, args): { cv.Required(CONF_ID): cv.use_id(TimeEntity), cv.Required(CONF_TIME): cv.Any( - cv.returning_lambda, cv.date_time(allowed_date=False) + cv.returning_lambda, cv.date_time(date=False, time=True) ), } ), @@ -230,7 +230,9 @@ async def datetime_time_set_to_code(config, action_id, template_arg, args): cv.Schema( { cv.Required(CONF_ID): cv.use_id(DateTimeEntity), - cv.Required(CONF_DATETIME): cv.Any(cv.returning_lambda, cv.date_time()), + cv.Required(CONF_DATETIME): cv.Any( + cv.returning_lambda, cv.date_time(date=True, time=True) + ), }, ), ) diff --git a/esphome/components/template/datetime/__init__.py b/esphome/components/template/datetime/__init__.py index bf7154ef76..0c9447116f 100644 --- a/esphome/components/template/datetime/__init__.py +++ b/esphome/components/template/datetime/__init__.py @@ -72,21 +72,25 @@ CONFIG_SCHEMA = cv.All( .extend(_BASE_SCHEMA) .extend( { - cv.Optional(CONF_INITIAL_VALUE): cv.date_time(allowed_time=False), + cv.Optional(CONF_INITIAL_VALUE): cv.date_time( + date=True, time=False + ), } ), "TIME": datetime.time_schema(TemplateTime) .extend(_BASE_SCHEMA) .extend( { - cv.Optional(CONF_INITIAL_VALUE): cv.date_time(allowed_date=False), + cv.Optional(CONF_INITIAL_VALUE): cv.date_time( + date=False, time=True + ), } ), "DATETIME": datetime.datetime_schema(TemplateDateTime) .extend(_BASE_SCHEMA) .extend( { - cv.Optional(CONF_INITIAL_VALUE): cv.date_time(), + cv.Optional(CONF_INITIAL_VALUE): cv.date_time(date=True, time=True), } ), }, diff --git a/esphome/config_validation.py b/esphome/config_validation.py index 3554f03836..512f1d8f67 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -821,57 +821,50 @@ positive_not_null_time_period = All( def time_of_day(value): - return date_time(allowed_date=False, allowed_time=True)(value) + return date_time(date=False, time=True)(value) -def date_time(allowed_date: bool = True, allowed_time: bool = True): +def date_time(date: bool, time: bool): pattern_str = r"^" # Start of string - if allowed_date: + if date: + pattern_str += r"\d{4}-\d{1,2}-\d{1,2}" + if time: + pattern_str += r" " + if time: pattern_str += ( - r"(" # 1. Optional Date group - r"\d{4}-\d{1,2}-\d{1,2}" # Date - r"(?:\s(?=.+))?" # Space after date only if time is following - r")?" # End optional Date group - ) - if allowed_time: - pattern_str += ( - r"(" # 2. Optional Time group - r"(\d{1,2}:\d{2})" # 3. Hour/Minute - r"(:\d{2})?" # 4. Seconds - r"(" # 5. Optional AM/PM group - r"(\s)?" # 6. Optional Space + r"\d{1,2}:\d{2}" # Hour/Minute + r"(:\d{2})?" # 1. Seconds + r"(" # 2. Optional AM/PM group + r"(\s)?" # 3. Optional Space r"(?:AM|PM|am|pm)" # AM/PM string matching r")?" # End optional AM/PM group - r")?" # End optional Time group ) pattern_str += r"$" # End of string pattern = re.compile(pattern_str) exc_message = "" - if allowed_date: + if date: exc_message += "date" - if allowed_time: - exc_message += "/" - if allowed_time: + if time: exc_message += "time" schema = Schema({}) - if allowed_date: + if date: schema = schema.extend( { - Optional(CONF_YEAR): int_range(min=1970, max=3000), - Optional(CONF_MONTH): int_range(min=1, max=12), - Optional(CONF_DAY): int_range(min=1, max=31), + Required(CONF_YEAR): int_range(min=1970, max=3000), + Required(CONF_MONTH): int_range(min=1, max=12), + Required(CONF_DAY): int_range(min=1, max=31), } ) - if allowed_time: + if time: schema = schema.extend( { - Optional(CONF_HOUR): int_range(min=0, max=23), - Optional(CONF_MINUTE): int_range(min=0, max=59), - Optional(CONF_SECOND): int_range(min=0, max=59), + Required(CONF_HOUR): int_range(min=0, max=23), + Required(CONF_MINUTE): int_range(min=0, max=59), + Required(CONF_SECOND): int_range(min=0, max=59), } ) @@ -885,21 +878,21 @@ def date_time(allowed_date: bool = True, allowed_time: bool = True): # pylint: disable=raise-missing-from raise Invalid(f"Invalid {exc_message}: {value}") - if allowed_date: - has_date = match[1] is not None - if allowed_time: - has_time = match[2] is not None - has_seconds = match[3] is not None - has_ampm = match[4] is not None - has_ampm_space = match[5] is not None + if time: + has_seconds = match[1] is not None + has_ampm = match[2] is not None + has_ampm_space = match[3] is not None format = "" - if allowed_date and has_date: + if date: format += "%Y-%m-%d" - if allowed_time and has_time: + if time: format += " " - if allowed_time and has_time: - format += "%H:%M" + if time: + if has_ampm: + format += "%I:%M" + else: + format += "%H:%M" if has_seconds: format += ":%S" if has_ampm_space: @@ -914,12 +907,12 @@ def date_time(allowed_date: bool = True, allowed_time: bool = True): raise Invalid(f"Invalid {exc_message}: {err}") return_value = {} - if allowed_date and has_date: + if date: return_value[CONF_YEAR] = date_obj.year return_value[CONF_MONTH] = date_obj.month return_value[CONF_DAY] = date_obj.day - if allowed_time and has_time: + if time: return_value[CONF_HOUR] = date_obj.hour return_value[CONF_MINUTE] = date_obj.minute return_value[CONF_SECOND] = date_obj.second if has_seconds else 0 diff --git a/tests/components/template/common.yaml b/tests/components/template/common.yaml index 2b91225b5a..9e89424d8a 100644 --- a/tests/components/template/common.yaml +++ b/tests/components/template/common.yaml @@ -172,6 +172,7 @@ datetime: name: Date id: test_date type: date + initial_value: "2000-1-2" set_action: - logger.log: "set_value" on_value: @@ -185,6 +186,7 @@ datetime: name: Time id: test_time type: time + initial_value: "12:34:56am" set_action: - logger.log: "set_value" on_value: @@ -198,6 +200,7 @@ datetime: name: DateTime id: test_datetime type: datetime + initial_value: "2000-1-2 12:34:56" set_action: - logger.log: "set_value" on_value: From 5edf4970bde1d2d5dda2fa34c1ba062a8f3aa8a1 Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Mon, 6 May 2024 20:44:36 -0700 Subject: [PATCH 1382/2101] proceed if AP mode is set up (#6631) --- esphome/components/wifi/wifi_component.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 075e683bb5..7e245d3e86 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -694,7 +694,7 @@ void WiFiComponent::retry_connect() { } bool WiFiComponent::can_proceed() { - if (!this->has_sta() || this->state_ == WIFI_COMPONENT_STATE_DISABLED) { + if (!this->has_sta() || this->state_ == WIFI_COMPONENT_STATE_DISABLED || this->ap_setup_) { return true; } return this->is_connected(); From 829bfbdaa446e4f9e959e50754cc55b88fb60c3f Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Wed, 8 May 2024 05:26:04 +1000 Subject: [PATCH 1383/2101] Migrate some constants to core code (#6692) --- esphome/components/as5600/__init__.py | 1 - esphome/components/as5600/sensor/__init__.py | 2 +- esphome/components/display_menu_base/__init__.py | 1 - esphome/components/lcd_menu/__init__.py | 3 +-- .../components/matrix_keypad/binary_sensor/__init__.py | 5 +---- esphome/components/media_player/__init__.py | 9 +++++++-- esphome/components/sx1509/binary_sensor/__init__.py | 4 +--- esphome/components/voice_assistant/__init__.py | 2 +- esphome/const.py | 5 +++++ 9 files changed, 17 insertions(+), 15 deletions(-) diff --git a/esphome/components/as5600/__init__.py b/esphome/components/as5600/__init__.py index 1840b22768..feeae107a7 100644 --- a/esphome/components/as5600/__init__.py +++ b/esphome/components/as5600/__init__.py @@ -54,7 +54,6 @@ FAST_FILTER = { "LSB10": 7, } -CONF_ANGLE = "angle" CONF_RAW_ANGLE = "raw_angle" CONF_RAW_POSITION = "raw_position" CONF_WATCHDOG = "watchdog" diff --git a/esphome/components/as5600/sensor/__init__.py b/esphome/components/as5600/sensor/__init__.py index 589a66950a..30337ab61b 100644 --- a/esphome/components/as5600/sensor/__init__.py +++ b/esphome/components/as5600/sensor/__init__.py @@ -11,6 +11,7 @@ from esphome.const import ( CONF_MAGNITUDE, CONF_STATUS, CONF_POSITION, + CONF_ANGLE, ) from .. import as5600_ns, AS5600Component @@ -19,7 +20,6 @@ DEPENDENCIES = ["as5600"] AS5600Sensor = as5600_ns.class_("AS5600Sensor", sensor.Sensor, cg.PollingComponent) -CONF_ANGLE = "angle" CONF_RAW_ANGLE = "raw_angle" CONF_RAW_POSITION = "raw_position" CONF_WATCHDOG = "watchdog" diff --git a/esphome/components/display_menu_base/__init__.py b/esphome/components/display_menu_base/__init__.py index d7326cdc65..0c738ba838 100644 --- a/esphome/components/display_menu_base/__init__.py +++ b/esphome/components/display_menu_base/__init__.py @@ -23,7 +23,6 @@ CODEOWNERS = ["@numo68"] display_menu_base_ns = cg.esphome_ns.namespace("display_menu_base") -CONF_DISPLAY_ID = "display_id" CONF_ROTARY = "rotary" CONF_JOYSTICK = "joystick" diff --git a/esphome/components/lcd_menu/__init__.py b/esphome/components/lcd_menu/__init__.py index a356c85ba7..b57a4a0f6c 100644 --- a/esphome/components/lcd_menu/__init__.py +++ b/esphome/components/lcd_menu/__init__.py @@ -3,6 +3,7 @@ import esphome.config_validation as cv from esphome.const import ( CONF_ID, CONF_DIMENSIONS, + CONF_DISPLAY_ID, ) from esphome.core.entity_helpers import inherit_property_from from esphome.components import lcd_base @@ -18,8 +19,6 @@ AUTO_LOAD = ["display_menu_base"] lcd_menu_ns = cg.esphome_ns.namespace("lcd_menu") -CONF_DISPLAY_ID = "display_id" - CONF_MARK_SELECTED = "mark_selected" CONF_MARK_EDITING = "mark_editing" CONF_MARK_SUBMENU = "mark_submenu" diff --git a/esphome/components/matrix_keypad/binary_sensor/__init__.py b/esphome/components/matrix_keypad/binary_sensor/__init__.py index 9ad909f60a..edebf7b772 100644 --- a/esphome/components/matrix_keypad/binary_sensor/__init__.py +++ b/esphome/components/matrix_keypad/binary_sensor/__init__.py @@ -1,12 +1,9 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import binary_sensor -from esphome.const import CONF_ID, CONF_KEY +from esphome.const import CONF_ID, CONF_KEY, CONF_ROW, CONF_COL from .. import MatrixKeypad, matrix_keypad_ns, CONF_KEYPAD_ID -CONF_ROW = "row" -CONF_COL = "col" - DEPENDENCIES = ["matrix_keypad"] MatrixKeypadBinarySensor = matrix_keypad_ns.class_( diff --git a/esphome/components/media_player/__init__.py b/esphome/components/media_player/__init__.py index 86e038d76d..5db78150bb 100644 --- a/esphome/components/media_player/__init__.py +++ b/esphome/components/media_player/__init__.py @@ -3,7 +3,13 @@ import esphome.config_validation as cv import esphome.codegen as cg from esphome.automation import maybe_simple_id -from esphome.const import CONF_ID, CONF_ON_STATE, CONF_TRIGGER_ID, CONF_VOLUME +from esphome.const import ( + CONF_ID, + CONF_ON_STATE, + CONF_TRIGGER_ID, + CONF_VOLUME, + CONF_ON_IDLE, +) from esphome.core import CORE from esphome.coroutine import coroutine_with_priority from esphome.cpp_helpers import setup_entity @@ -43,7 +49,6 @@ VolumeSetAction = media_player_ns.class_( ) -CONF_ON_IDLE = "on_idle" CONF_ON_PLAY = "on_play" CONF_ON_PAUSE = "on_pause" CONF_MEDIA_URL = "media_url" diff --git a/esphome/components/sx1509/binary_sensor/__init__.py b/esphome/components/sx1509/binary_sensor/__init__.py index fa620fa202..280b5ad90c 100644 --- a/esphome/components/sx1509/binary_sensor/__init__.py +++ b/esphome/components/sx1509/binary_sensor/__init__.py @@ -1,12 +1,10 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import binary_sensor +from esphome.const import CONF_ROW, CONF_COL from .. import SX1509Component, sx1509_ns, CONF_SX1509_ID -CONF_ROW = "row" -CONF_COL = "col" - DEPENDENCIES = ["sx1509"] SX1509BinarySensor = sx1509_ns.class_("SX1509BinarySensor", binary_sensor.BinarySensor) diff --git a/esphome/components/voice_assistant/__init__.py b/esphome/components/voice_assistant/__init__.py index 17bdffd9da..3ba0c58ce4 100644 --- a/esphome/components/voice_assistant/__init__.py +++ b/esphome/components/voice_assistant/__init__.py @@ -8,6 +8,7 @@ from esphome.const import ( CONF_MEDIA_PLAYER, CONF_ON_CLIENT_CONNECTED, CONF_ON_CLIENT_DISCONNECTED, + CONF_ON_IDLE, ) from esphome import automation from esphome.automation import register_action, register_condition @@ -32,7 +33,6 @@ CONF_ON_TTS_START = "on_tts_start" CONF_ON_TTS_STREAM_START = "on_tts_stream_start" CONF_ON_TTS_STREAM_END = "on_tts_stream_end" CONF_ON_WAKE_WORD_DETECTED = "on_wake_word_detected" -CONF_ON_IDLE = "on_idle" CONF_SILENCE_DETECTION = "silence_detection" CONF_USE_WAKE_WORD = "use_wake_word" diff --git a/esphome/const.py b/esphome/const.py index 1a8f9a06e1..c0d27337d6 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -51,6 +51,7 @@ CONF_ALPHA = "alpha" CONF_ALTITUDE = "altitude" CONF_ANALOG = "analog" CONF_AND = "and" +CONF_ANGLE = "angle" CONF_AP = "ap" CONF_APPARENT_POWER = "apparent_power" CONF_ARDUINO_VERSION = "arduino_version" @@ -124,6 +125,7 @@ CONF_CLOSE_DURATION = "close_duration" CONF_CLOSE_ENDSTOP = "close_endstop" CONF_CO2 = "co2" CONF_CODE = "code" +CONF_COL = "col" CONF_COLD_WHITE = "cold_white" CONF_COLD_WHITE_COLOR_TEMPERATURE = "cold_white_color_temperature" CONF_COLOR = "color" @@ -218,6 +220,7 @@ CONF_DISCOVERY_PREFIX = "discovery_prefix" CONF_DISCOVERY_RETAIN = "discovery_retain" CONF_DISCOVERY_UNIQUE_ID_GENERATOR = "discovery_unique_id_generator" CONF_DISPLAY = "display" +CONF_DISPLAY_ID = "display_id" CONF_DISTANCE = "distance" CONF_DITHER = "dither" CONF_DIV_RATIO = "div_ratio" @@ -539,6 +542,7 @@ CONF_ON_FINGER_SCAN_MISPLACED = "on_finger_scan_misplaced" CONF_ON_FINGER_SCAN_START = "on_finger_scan_start" CONF_ON_FINGER_SCAN_UNMATCHED = "on_finger_scan_unmatched" CONF_ON_FINISHED_WRITE = "on_finished_write" +CONF_ON_IDLE = "on_idle" CONF_ON_JSON_MESSAGE = "on_json_message" CONF_ON_LOCK = "on_lock" CONF_ON_LOOP = "on_loop" @@ -702,6 +706,7 @@ CONF_RGBW = "rgbw" CONF_RISING_EDGE = "rising_edge" CONF_RMT_CHANNEL = "rmt_channel" CONF_ROTATION = "rotation" +CONF_ROW = "row" CONF_RS_PIN = "rs_pin" CONF_RTD_NOMINAL_RESISTANCE = "rtd_nominal_resistance" CONF_RTD_WIRES = "rtd_wires" From f6a3784ebac1b669f2bf0edea6743a86c12e3a85 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Tue, 7 May 2024 14:33:37 -0500 Subject: [PATCH 1384/2101] Consolidate test files where all tests are identical (#6690) --- .../components/absolute_humidity/common.yaml | 21 ++++ .../absolute_humidity/test.esp32-c3-idf.yaml | 22 +--- .../absolute_humidity/test.esp32-c3.yaml | 22 +--- .../absolute_humidity/test.esp32-idf.yaml | 22 +--- .../absolute_humidity/test.esp32.yaml | 22 +--- .../absolute_humidity/test.esp8266.yaml | 22 +--- .../absolute_humidity/test.rp2040.yaml | 22 +--- .../airthings_wave_mini/common.yaml | 22 ++++ .../test.esp32-c3-idf.yaml | 23 +--- .../airthings_wave_mini/test.esp32-c3.yaml | 23 +--- .../airthings_wave_mini/test.esp32-idf.yaml | 23 +--- .../airthings_wave_mini/test.esp32.yaml | 23 +--- .../airthings_wave_plus/common.yaml | 28 +++++ .../test.esp32-c3-idf.yaml | 29 +---- .../airthings_wave_plus/test.esp32-c3.yaml | 29 +---- .../airthings_wave_plus/test.esp32-idf.yaml | 29 +---- .../airthings_wave_plus/test.esp32.yaml | 29 +---- .../alarm_control_panel/common.yaml | 64 ++++++++++ .../test.esp32-c3-idf.yaml | 65 +--------- .../alarm_control_panel/test.esp32-c3.yaml | 65 +--------- .../alarm_control_panel/test.esp32-idf.yaml | 65 +--------- .../alarm_control_panel/test.esp32.yaml | 65 +--------- .../alarm_control_panel/test.esp8266.yaml | 65 +--------- .../alarm_control_panel/test.rp2040.yaml | 65 +--------- tests/components/alpha3/common.yaml | 17 +++ .../components/alpha3/test.esp32-c3-idf.yaml | 18 +-- tests/components/alpha3/test.esp32-c3.yaml | 18 +-- tests/components/alpha3/test.esp32-idf.yaml | 18 +-- tests/components/alpha3/test.esp32.yaml | 18 +-- tests/components/am43/common.yaml | 19 +++ tests/components/am43/test.esp32-c3-idf.yaml | 20 +-- tests/components/am43/test.esp32-c3.yaml | 20 +-- tests/components/am43/test.esp32-idf.yaml | 20 +-- tests/components/am43/test.esp32.yaml | 20 +-- tests/components/analog_threshold/common.yaml | 28 +++++ .../analog_threshold/test.esp32-c3-idf.yaml | 29 +---- .../analog_threshold/test.esp32-c3.yaml | 29 +---- .../analog_threshold/test.esp32-idf.yaml | 29 +---- .../analog_threshold/test.esp32.yaml | 29 +---- .../analog_threshold/test.esp8266.yaml | 29 +---- .../analog_threshold/test.rp2040.yaml | 29 +---- tests/components/anova/common.yaml | 11 ++ tests/components/anova/test.esp32-c3-idf.yaml | 12 +- tests/components/anova/test.esp32-c3.yaml | 12 +- tests/components/anova/test.esp32-idf.yaml | 12 +- tests/components/anova/test.esp32.yaml | 12 +- tests/components/api/common.yaml | 63 ++++++++++ tests/components/api/test.esp32-c3-idf.yaml | 64 +--------- tests/components/api/test.esp32-c3.yaml | 64 +--------- tests/components/api/test.esp32-idf.yaml | 64 +--------- tests/components/api/test.esp32.yaml | 64 +--------- tests/components/api/test.esp8266.yaml | 64 +--------- tests/components/api/test.rp2040.yaml | 64 +--------- .../components/atc_mithermometer/common.yaml | 13 ++ .../atc_mithermometer/test.esp32-c3-idf.yaml | 14 +-- .../atc_mithermometer/test.esp32-c3.yaml | 14 +-- .../atc_mithermometer/test.esp32-idf.yaml | 14 +-- .../atc_mithermometer/test.esp32.yaml | 14 +-- tests/components/b_parasite/common.yaml | 15 +++ .../b_parasite/test.esp32-c3-idf.yaml | 16 +-- .../components/b_parasite/test.esp32-c3.yaml | 16 +-- .../components/b_parasite/test.esp32-idf.yaml | 16 +-- tests/components/b_parasite/test.esp32.yaml | 16 +-- tests/components/bang_bang/common.yaml | 35 ++++++ .../bang_bang/test.esp32-c3-idf.yaml | 36 +----- tests/components/bang_bang/test.esp32-c3.yaml | 36 +----- .../components/bang_bang/test.esp32-idf.yaml | 36 +----- tests/components/bang_bang/test.esp32.yaml | 36 +----- tests/components/bang_bang/test.esp8266.yaml | 36 +----- tests/components/bang_bang/test.rp2040.yaml | 36 +----- tests/components/bedjet/common.yaml | 33 +++++ .../components/bedjet/test.esp32-c3-idf.yaml | 34 +---- tests/components/bedjet/test.esp32-c3.yaml | 34 +---- tests/components/bedjet/test.esp32-idf.yaml | 34 +---- tests/components/bedjet/test.esp32.yaml | 34 +---- .../components/binary_sensor_map/common.yaml | 61 +++++++++ .../binary_sensor_map/test.esp32-c3-idf.yaml | 62 +-------- .../binary_sensor_map/test.esp32-c3.yaml | 62 +-------- .../binary_sensor_map/test.esp32-idf.yaml | 62 +-------- .../binary_sensor_map/test.esp32.yaml | 62 +-------- .../binary_sensor_map/test.esp8266.yaml | 62 +-------- .../binary_sensor_map/test.rp2040.yaml | 62 +-------- tests/components/ble_client/common.yaml | 5 + .../ble_client/test.esp32-c3-idf.yaml | 6 +- .../components/ble_client/test.esp32-c3.yaml | 6 +- .../components/ble_client/test.esp32-idf.yaml | 6 +- tests/components/ble_client/test.esp32.yaml | 6 +- tests/components/ble_presence/common.yaml | 24 ++++ .../ble_presence/test.esp32-c3-idf.yaml | 25 +--- .../ble_presence/test.esp32-c3.yaml | 25 +--- .../ble_presence/test.esp32-idf.yaml | 25 +--- tests/components/ble_presence/test.esp32.yaml | 25 +--- tests/components/ble_rssi/common.yaml | 18 +++ .../ble_rssi/test.esp32-c3-idf.yaml | 19 +-- tests/components/ble_rssi/test.esp32-c3.yaml | 19 +-- tests/components/ble_rssi/test.esp32-idf.yaml | 19 +-- tests/components/ble_rssi/test.esp32.yaml | 19 +-- tests/components/ble_scanner/common.yaml | 5 + .../ble_scanner/test.esp32-c3-idf.yaml | 6 +- .../components/ble_scanner/test.esp32-c3.yaml | 6 +- .../ble_scanner/test.esp32-idf.yaml | 6 +- tests/components/ble_scanner/test.esp32.yaml | 6 +- tests/components/button/common.yaml | 6 + .../components/button/test.esp32-c3-idf.yaml | 7 +- tests/components/button/test.esp32-c3.yaml | 7 +- tests/components/button/test.esp32-idf.yaml | 7 +- tests/components/button/test.esp32.yaml | 7 +- tests/components/button/test.esp8266.yaml | 7 +- tests/components/button/test.rp2040.yaml | 7 +- tests/components/canbus/common.yaml | 46 +++++++ .../components/canbus/test.esp32-c3-idf.yaml | 47 +------ tests/components/canbus/test.esp32-c3.yaml | 47 +------ tests/components/canbus/test.esp32-idf.yaml | 47 +------ tests/components/canbus/test.esp32.yaml | 47 +------ tests/components/captive_portal/common.yaml | 5 + .../captive_portal/test.esp32-c3-idf.yaml | 6 +- .../captive_portal/test.esp32-c3.yaml | 6 +- .../captive_portal/test.esp32-idf.yaml | 6 +- .../components/captive_portal/test.esp32.yaml | 6 +- .../captive_portal/test.esp8266.yaml | 6 +- tests/components/color/common.yaml | 11 ++ tests/components/color/test.esp32-c3-idf.yaml | 12 +- tests/components/color/test.esp32-c3.yaml | 12 +- tests/components/color/test.esp32-idf.yaml | 12 +- tests/components/color/test.esp32.yaml | 12 +- tests/components/color/test.esp8266.yaml | 12 +- tests/components/color/test.rp2040.yaml | 12 +- tests/components/combination/common.yaml | 76 +++++++++++ .../combination/test.esp32-c3-idf.yaml | 77 +----------- .../components/combination/test.esp32-c3.yaml | 77 +----------- .../combination/test.esp32-idf.yaml | 77 +----------- tests/components/combination/test.esp32.yaml | 77 +----------- .../components/combination/test.esp8266.yaml | 77 +----------- tests/components/combination/test.rp2040.yaml | 77 +----------- tests/components/cst226/common.yaml | 24 ++++ tests/components/cst226/test.esp32-c3.yaml | 25 +--- tests/components/cst816/common.yaml | 36 ++++++ tests/components/cst816/test.esp32.yaml | 37 +----- tests/components/dallas/common.yaml | 11 ++ .../components/dallas/test.esp32-c3-idf.yaml | 12 +- tests/components/dallas/test.esp32-c3.yaml | 12 +- tests/components/dallas/test.esp32-idf.yaml | 12 +- tests/components/dallas/test.esp32.yaml | 12 +- tests/components/dallas/test.esp8266.yaml | 12 +- tests/components/dallas/test.rp2040.yaml | 12 +- tests/components/datetime/common.yaml | 3 + tests/components/datetime/test.all.yaml | 4 +- tests/components/debug/common.yaml | 1 + tests/components/debug/test.esp32-c3-idf.yaml | 2 +- tests/components/debug/test.esp32-c3.yaml | 2 +- tests/components/debug/test.esp32-idf.yaml | 2 +- tests/components/debug/test.esp32.yaml | 2 +- tests/components/debug/test.esp8266.yaml | 2 +- tests/components/debug/test.host.yaml | 2 +- tests/components/debug/test.rp2040.yaml | 2 +- tests/components/dht/common.yaml | 11 ++ tests/components/dht/test.esp32-c3-idf.yaml | 12 +- tests/components/dht/test.esp32-c3.yaml | 12 +- tests/components/dht/test.esp32-idf.yaml | 12 +- tests/components/dht/test.esp32.yaml | 12 +- tests/components/dht/test.esp8266.yaml | 12 +- tests/components/dht/test.rp2040.yaml | 12 +- tests/components/display/common.yaml | 35 ++++++ tests/components/display/test.esp32.yaml | 36 +----- tests/components/duty_cycle/common.yaml | 4 + .../duty_cycle/test.esp32-c3-idf.yaml | 5 +- .../components/duty_cycle/test.esp32-c3.yaml | 5 +- .../components/duty_cycle/test.esp32-idf.yaml | 5 +- tests/components/duty_cycle/test.esp32.yaml | 5 +- tests/components/duty_cycle/test.esp8266.yaml | 5 +- tests/components/duty_cycle/test.rp2040.yaml | 5 +- tests/components/duty_time/common.yaml | 14 +++ .../duty_time/test.esp32-c3-idf.yaml | 15 +-- tests/components/duty_time/test.esp32-c3.yaml | 15 +-- .../components/duty_time/test.esp32-idf.yaml | 15 +-- tests/components/duty_time/test.esp32.yaml | 15 +-- tests/components/duty_time/test.esp8266.yaml | 15 +-- tests/components/duty_time/test.rp2040.yaml | 15 +-- tests/components/endstop/common.yaml | 33 +++++ .../components/endstop/test.esp32-c3-idf.yaml | 34 +---- tests/components/endstop/test.esp32-c3.yaml | 34 +---- tests/components/endstop/test.esp32-idf.yaml | 34 +---- tests/components/endstop/test.esp32.yaml | 34 +---- tests/components/endstop/test.esp8266.yaml | 34 +---- tests/components/endstop/test.rp2040.yaml | 34 +---- tests/components/esp32_ble/common.yaml | 2 + .../esp32_ble/test.esp32-c3-idf.yaml | 3 +- tests/components/esp32_ble/test.esp32-c3.yaml | 3 +- .../components/esp32_ble/test.esp32-idf.yaml | 3 +- tests/components/esp32_ble/test.esp32.yaml | 3 +- tests/components/esp32_ble_beacon/common.yaml | 3 + .../esp32_ble_beacon/test.esp32-c3-idf.yaml | 4 +- .../esp32_ble_beacon/test.esp32-c3.yaml | 4 +- .../esp32_ble_beacon/test.esp32-idf.yaml | 4 +- .../esp32_ble_beacon/test.esp32.yaml | 4 +- tests/components/esp32_ble_client/common.yaml | 5 + .../esp32_ble_client/test.esp32-c3-idf.yaml | 6 +- .../esp32_ble_client/test.esp32-c3.yaml | 6 +- .../esp32_ble_client/test.esp32-idf.yaml | 6 +- .../esp32_ble_client/test.esp32.yaml | 6 +- tests/components/esp32_ble_server/common.yaml | 3 + .../esp32_ble_server/test.esp32-c3-idf.yaml | 4 +- .../esp32_ble_server/test.esp32-c3.yaml | 4 +- .../esp32_ble_server/test.esp32-idf.yaml | 4 +- .../esp32_ble_server/test.esp32.yaml | 4 +- .../components/esp32_ble_tracker/common.yaml | 41 ++++++ .../esp32_ble_tracker/test.esp32-c3-idf.yaml | 42 +------ .../esp32_ble_tracker/test.esp32-c3.yaml | 42 +------ .../esp32_ble_tracker/test.esp32-idf.yaml | 42 +------ .../esp32_ble_tracker/test.esp32.yaml | 42 +------ tests/components/esp32_camera/common.yaml | 28 +++++ .../esp32_camera/test.esp32-idf.yaml | 29 +---- tests/components/esp32_camera/test.esp32.yaml | 29 +---- .../esp32_camera_web_server/common.yaml | 34 +++++ .../test.esp32-idf.yaml | 35 +----- .../esp32_camera_web_server/test.esp32.yaml | 35 +----- tests/components/esp32_dac/common.yaml | 4 + .../components/esp32_dac/test.esp32-idf.yaml | 5 +- tests/components/esp32_dac/test.esp32.yaml | 5 +- tests/components/esp32_hall/common.yaml | 3 + .../components/esp32_hall/test.esp32-idf.yaml | 4 +- tests/components/esp32_hall/test.esp32.yaml | 4 +- tests/components/esp32_improv/common.yaml | 18 +++ .../esp32_improv/test.esp32-c3-idf.yaml | 19 +-- .../esp32_improv/test.esp32-c3.yaml | 19 +-- .../esp32_improv/test.esp32-idf.yaml | 19 +-- tests/components/esp32_improv/test.esp32.yaml | 19 +-- tests/components/esp32_touch/common.yaml | 16 +++ .../esp32_touch/test.esp32-idf.yaml | 17 +-- tests/components/esp32_touch/test.esp32.yaml | 17 +-- tests/components/esp8266_pwm/common.yaml | 8 ++ .../components/esp8266_pwm/test.esp8266.yaml | 9 +- tests/components/ethernet/common.yaml | 12 ++ tests/components/ethernet/test.esp32-idf.yaml | 13 +- tests/components/ethernet/test.esp32.yaml | 13 +- tests/components/ethernet_info/common.yaml | 19 +++ .../ethernet_info/test.esp32-idf.yaml | 20 +-- .../components/ethernet_info/test.esp32.yaml | 20 +-- tests/components/event/common.yaml | 9 ++ tests/components/event/test.esp32-c3-idf.yaml | 10 +- tests/components/event/test.esp32-c3.yaml | 10 +- tests/components/event/test.esp32-idf.yaml | 10 +- tests/components/event/test.esp32.yaml | 10 +- tests/components/event/test.esp8266.yaml | 10 +- tests/components/event/test.rp2040.yaml | 10 +- .../exposure_notifications/common.yaml | 9 ++ .../test.esp32-c3-idf.yaml | 10 +- .../exposure_notifications/test.esp32-c3.yaml | 10 +- .../test.esp32-idf.yaml | 10 +- .../exposure_notifications/test.esp32.yaml | 10 +- .../external_components/common.yaml | 6 + .../test.esp32-c3-idf.yaml | 7 +- .../external_components/test.esp32-c3.yaml | 7 +- .../external_components/test.esp32-idf.yaml | 7 +- .../external_components/test.esp32.yaml | 7 +- .../external_components/test.esp8266.yaml | 7 +- .../external_components/test.rp2040.yaml | 7 +- tests/components/factory_reset/common.yaml | 3 + .../factory_reset/test.esp32-c3-idf.yaml | 4 +- .../factory_reset/test.esp32-c3.yaml | 4 +- .../factory_reset/test.esp32-idf.yaml | 4 +- .../components/factory_reset/test.esp32.yaml | 4 +- .../factory_reset/test.esp8266.yaml | 4 +- .../components/factory_reset/test.rp2040.yaml | 4 +- .../components/fastled_clockless/common.yaml | 71 +++++++++++ .../fastled_clockless/test.esp32.yaml | 72 +---------- tests/components/fastled_spi/common.yaml | 71 +++++++++++ tests/components/fastled_spi/test.esp32.yaml | 72 +---------- tests/components/feedback/common.yaml | 39 ++++++ .../feedback/test.esp32-c3-idf.yaml | 40 +----- tests/components/feedback/test.esp32-c3.yaml | 40 +----- tests/components/feedback/test.esp32-idf.yaml | 40 +----- tests/components/feedback/test.esp32.yaml | 40 +----- tests/components/feedback/test.esp8266.yaml | 40 +----- tests/components/feedback/test.rp2040.yaml | 40 +----- tests/components/globals/common.yaml | 28 +++++ .../components/globals/test.esp32-c3-idf.yaml | 29 +---- tests/components/globals/test.esp32-c3.yaml | 29 +---- tests/components/globals/test.esp32-idf.yaml | 29 +---- tests/components/globals/test.esp32.yaml | 29 +---- tests/components/globals/test.esp8266.yaml | 29 +---- tests/components/globals/test.rp2040.yaml | 29 +---- tests/components/host/common.yaml | 15 +++ tests/components/host/test.host.yaml | 16 +-- tests/components/improv_serial/common.yaml | 5 + .../improv_serial/test.esp32-c3-idf.yaml | 6 +- .../improv_serial/test.esp32-c3.yaml | 6 +- .../improv_serial/test.esp32-idf.yaml | 6 +- .../components/improv_serial/test.esp32.yaml | 6 +- .../improv_serial/test.esp8266.yaml | 6 +- .../components/improv_serial/test.rp2040.yaml | 6 +- .../inkbird_ibsth1_mini/common.yaml | 11 ++ .../test.esp32-c3-idf.yaml | 12 +- .../inkbird_ibsth1_mini/test.esp32-c3.yaml | 12 +- .../inkbird_ibsth1_mini/test.esp32-idf.yaml | 12 +- .../inkbird_ibsth1_mini/test.esp32.yaml | 12 +- tests/components/inkplate6/common.yaml | 62 +++++++++ tests/components/inkplate6/test.esp32.yaml | 63 +--------- tests/components/interval/common.yaml | 4 + .../interval/test.esp32-c3-idf.yaml | 5 +- tests/components/interval/test.esp32-c3.yaml | 5 +- tests/components/interval/test.esp32-idf.yaml | 5 +- tests/components/interval/test.esp32.yaml | 5 +- tests/components/interval/test.esp8266.yaml | 5 +- tests/components/interval/test.rp2040.yaml | 5 +- tests/components/ledc/common.yaml | 11 ++ tests/components/ledc/test.esp32-c3-idf.yaml | 12 +- tests/components/ledc/test.esp32-c3.yaml | 12 +- tests/components/ledc/test.esp32-idf.yaml | 12 +- tests/components/ledc/test.esp32.yaml | 12 +- tests/components/lightwaverf/common.yaml | 13 ++ .../components/lightwaverf/test.esp8266.yaml | 14 +-- tests/components/lock/common.yaml | 36 ++++++ tests/components/lock/test.esp32-c3-idf.yaml | 37 +----- tests/components/lock/test.esp32-c3.yaml | 37 +----- tests/components/lock/test.esp32-idf.yaml | 37 +----- tests/components/lock/test.esp32.yaml | 37 +----- tests/components/lock/test.esp8266.yaml | 37 +----- tests/components/lock/test.rp2040.yaml | 37 +----- tests/components/logger/common.yaml | 7 ++ .../components/logger/test.esp32-c3-idf.yaml | 8 +- tests/components/logger/test.esp32-c3.yaml | 8 +- tests/components/logger/test.esp32-idf.yaml | 8 +- tests/components/logger/test.esp32.yaml | 8 +- tests/components/logger/test.esp8266.yaml | 8 +- tests/components/logger/test.rp2040.yaml | 8 +- tests/components/mdns/common.yaml | 6 + tests/components/mdns/test.esp32-c3-idf.yaml | 7 +- tests/components/mdns/test.esp32-c3.yaml | 7 +- tests/components/mdns/test.esp32-idf.yaml | 7 +- tests/components/mdns/test.esp32.yaml | 7 +- tests/components/mdns/test.esp8266.yaml | 7 +- tests/components/mdns/test.rp2040.yaml | 7 +- tests/components/media_player/common.yaml | 32 +++++ tests/components/media_player/test.esp32.yaml | 33 +---- tests/components/micro_wake_word/common.yaml | 15 +++ .../micro_wake_word/test.esp32-s3-idf.yaml | 16 +-- tests/components/midea_ir/common.yaml | 8 ++ .../midea_ir/test.esp32-c3-idf.yaml | 9 +- tests/components/midea_ir/test.esp32-c3.yaml | 9 +- tests/components/midea_ir/test.esp32-idf.yaml | 9 +- tests/components/midea_ir/test.esp32.yaml | 9 +- tests/components/midea_ir/test.esp8266.yaml | 9 +- tests/components/mitsubishi/common.yaml | 7 ++ .../mitsubishi/test.esp32-c3-idf.yaml | 8 +- .../components/mitsubishi/test.esp32-c3.yaml | 8 +- .../components/mitsubishi/test.esp32-idf.yaml | 8 +- tests/components/mitsubishi/test.esp32.yaml | 8 +- tests/components/mitsubishi/test.esp8266.yaml | 8 +- tests/components/mopeka_ble/common.yaml | 3 + .../mopeka_ble/test.esp32-c3-idf.yaml | 4 +- .../components/mopeka_ble/test.esp32-c3.yaml | 4 +- .../components/mopeka_ble/test.esp32-idf.yaml | 4 +- tests/components/mopeka_ble/test.esp32.yaml | 4 +- tests/components/mopeka_pro_check/common.yaml | 16 +++ .../mopeka_pro_check/test.esp32-c3-idf.yaml | 17 +-- .../mopeka_pro_check/test.esp32-c3.yaml | 17 +-- .../mopeka_pro_check/test.esp32-idf.yaml | 17 +-- .../mopeka_pro_check/test.esp32.yaml | 17 +-- tests/components/mopeka_std_check/common.yaml | 15 +++ .../mopeka_std_check/test.esp32-c3-idf.yaml | 16 +-- .../mopeka_std_check/test.esp32-c3.yaml | 16 +-- .../mopeka_std_check/test.esp32-idf.yaml | 16 +-- .../mopeka_std_check/test.esp32.yaml | 16 +-- tests/components/my9231/common.yaml | 26 ++++ .../components/my9231/test.esp32-c3-idf.yaml | 27 +--- tests/components/my9231/test.esp32-c3.yaml | 27 +--- tests/components/my9231/test.esp32-idf.yaml | 27 +--- tests/components/my9231/test.esp32.yaml | 27 +--- tests/components/my9231/test.esp8266.yaml | 27 +--- tests/components/my9231/test.rp2040.yaml | 27 +--- tests/components/network/common.yaml | 6 + .../components/network/test.esp32-c3-idf.yaml | 7 +- tests/components/network/test.esp32-c3.yaml | 7 +- tests/components/network/test.esp32-idf.yaml | 7 +- tests/components/network/test.esp32.yaml | 7 +- tests/components/network/test.esp8266.yaml | 7 +- tests/components/network/test.rp2040.yaml | 7 +- tests/components/noblex/common.yaml | 20 +++ .../components/noblex/test.esp32-c3-idf.yaml | 21 +--- tests/components/noblex/test.esp32-c3.yaml | 21 +--- tests/components/noblex/test.esp32-idf.yaml | 21 +--- tests/components/noblex/test.esp32.yaml | 21 +--- tests/components/noblex/test.esp8266.yaml | 21 +--- tests/components/ota/common.yaml | 30 +++++ tests/components/ota/test.esp32-c3-idf.yaml | 31 +---- tests/components/ota/test.esp32-c3.yaml | 31 +---- tests/components/ota/test.esp32-idf.yaml | 31 +---- tests/components/ota/test.esp32.yaml | 31 +---- tests/components/ota/test.esp8266.yaml | 31 +---- tests/components/ota/test.rp2040.yaml | 31 +---- tests/components/pid/common.yaml | 56 +++++++++ tests/components/pid/test.esp32-c3-idf.yaml | 57 +-------- tests/components/pid/test.esp32-c3.yaml | 57 +-------- tests/components/pid/test.esp32-idf.yaml | 57 +-------- tests/components/pid/test.esp32.yaml | 57 +-------- tests/components/pid/test.esp8266.yaml | 57 +-------- tests/components/pid/test.rp2040.yaml | 57 +-------- tests/components/power_supply/common.yaml | 6 + .../power_supply/test.esp32-c3-idf.yaml | 7 +- .../power_supply/test.esp32-c3.yaml | 7 +- .../power_supply/test.esp32-idf.yaml | 7 +- tests/components/power_supply/test.esp32.yaml | 7 +- .../components/power_supply/test.esp8266.yaml | 7 +- .../components/power_supply/test.rp2040.yaml | 7 +- tests/components/prometheus/common.yaml | 21 ++++ .../prometheus/test.esp32-c3-idf.yaml | 22 +--- .../components/prometheus/test.esp32-c3.yaml | 22 +--- .../components/prometheus/test.esp32-idf.yaml | 22 +--- tests/components/prometheus/test.esp32.yaml | 22 +--- tests/components/prometheus/test.esp8266.yaml | 22 +--- tests/components/psram/common.yaml | 3 + tests/components/psram/test.esp32-c3-idf.yaml | 4 +- tests/components/psram/test.esp32-c3.yaml | 4 +- tests/components/psram/test.esp32-idf.yaml | 4 +- tests/components/psram/test.esp32.yaml | 4 +- tests/components/pulse_counter/common.yaml | 9 ++ .../pulse_counter/test.esp32-c3-idf.yaml | 10 +- .../pulse_counter/test.esp32-c3.yaml | 10 +- .../pulse_counter/test.esp32-idf.yaml | 10 +- .../components/pulse_counter/test.esp32.yaml | 10 +- .../pulse_counter/test.esp8266.yaml | 10 +- .../components/pulse_counter/test.rp2040.yaml | 10 +- tests/components/pulse_meter/common.yaml | 13 ++ .../pulse_meter/test.esp32-c3-idf.yaml | 14 +-- .../components/pulse_meter/test.esp32-c3.yaml | 14 +-- .../pulse_meter/test.esp32-idf.yaml | 14 +-- tests/components/pulse_meter/test.esp32.yaml | 14 +-- .../components/pulse_meter/test.esp8266.yaml | 14 +-- tests/components/pulse_meter/test.rp2040.yaml | 14 +-- tests/components/pulse_width/common.yaml | 4 + .../pulse_width/test.esp32-c3-idf.yaml | 5 +- .../components/pulse_width/test.esp32-c3.yaml | 5 +- .../pulse_width/test.esp32-idf.yaml | 5 +- tests/components/pulse_width/test.esp32.yaml | 5 +- .../components/pulse_width/test.esp8266.yaml | 5 +- tests/components/pulse_width/test.rp2040.yaml | 5 +- .../components/pvvx_mithermometer/common.yaml | 44 +++++++ .../pvvx_mithermometer/test.esp32-c3-idf.yaml | 45 +------ .../pvvx_mithermometer/test.esp32-c3.yaml | 45 +------ .../pvvx_mithermometer/test.esp32-idf.yaml | 45 +------ .../pvvx_mithermometer/test.esp32.yaml | 45 +------ tests/components/qspi_amoled/common.yaml | 36 ++++++ .../qspi_amoled/test.esp32-s3-idf.yaml | 37 +----- tests/components/radon_eye_ble/common.yaml | 3 + .../radon_eye_ble/test.esp32-c3-idf.yaml | 4 +- .../radon_eye_ble/test.esp32-c3.yaml | 4 +- .../radon_eye_ble/test.esp32-idf.yaml | 4 +- .../components/radon_eye_ble/test.esp32.yaml | 4 +- tests/components/radon_eye_rd200/common.yaml | 14 +++ .../radon_eye_rd200/test.esp32-c3-idf.yaml | 15 +-- .../radon_eye_rd200/test.esp32-c3.yaml | 15 +-- .../radon_eye_rd200/test.esp32-idf.yaml | 15 +-- .../radon_eye_rd200/test.esp32.yaml | 15 +-- tests/components/restart/common.yaml | 7 ++ .../components/restart/test.esp32-c3-idf.yaml | 8 +- tests/components/restart/test.esp32-c3.yaml | 8 +- tests/components/restart/test.esp32-idf.yaml | 8 +- tests/components/restart/test.esp32.yaml | 8 +- tests/components/restart/test.esp8266.yaml | 8 +- tests/components/restart/test.rp2040.yaml | 8 +- .../rp2040_pio_led_strip/common.yaml | 18 +++ .../rp2040_pio_led_strip/test.rp2040.yaml | 19 +-- tests/components/rp2040_pwm/common.yaml | 7 ++ tests/components/rp2040_pwm/test.rp2040.yaml | 8 +- tests/components/rpi_dpi_rgb/common.yaml | 40 ++++++ .../rpi_dpi_rgb/test.esp32-s3-idf.yaml | 41 +----- tests/components/ruuvi_ble/common.yaml | 3 + .../ruuvi_ble/test.esp32-c3-idf.yaml | 4 +- tests/components/ruuvi_ble/test.esp32-c3.yaml | 4 +- .../components/ruuvi_ble/test.esp32-idf.yaml | 4 +- tests/components/ruuvi_ble/test.esp32.yaml | 4 +- tests/components/ruuvitag/common.yaml | 27 ++++ .../ruuvitag/test.esp32-c3-idf.yaml | 28 +---- tests/components/ruuvitag/test.esp32-c3.yaml | 28 +---- tests/components/ruuvitag/test.esp32-idf.yaml | 28 +---- tests/components/ruuvitag/test.esp32.yaml | 28 +---- tests/components/safe_mode/common.yaml | 13 ++ .../safe_mode/test.esp32-c3-idf.yaml | 14 +-- tests/components/safe_mode/test.esp32-c3.yaml | 14 +-- .../components/safe_mode/test.esp32-idf.yaml | 14 +-- tests/components/safe_mode/test.esp32.yaml | 14 +-- tests/components/safe_mode/test.esp8266.yaml | 14 +-- tests/components/safe_mode/test.rp2040.yaml | 14 +-- tests/components/shelly_dimmer/common.yaml | 19 +++ .../shelly_dimmer/test.esp8266.yaml | 20 +-- tests/components/shutdown/common.yaml | 7 ++ .../shutdown/test.esp32-c3-idf.yaml | 8 +- tests/components/shutdown/test.esp32-c3.yaml | 8 +- tests/components/shutdown/test.esp32-idf.yaml | 8 +- tests/components/shutdown/test.esp32.yaml | 8 +- tests/components/shutdown/test.esp8266.yaml | 8 +- tests/components/shutdown/test.rp2040.yaml | 8 +- .../components/sigma_delta_output/common.yaml | 16 +++ .../sigma_delta_output/test.esp32-c3-idf.yaml | 17 +-- .../sigma_delta_output/test.esp32-c3.yaml | 17 +-- .../sigma_delta_output/test.esp32-idf.yaml | 17 +-- .../sigma_delta_output/test.esp32.yaml | 17 +-- .../sigma_delta_output/test.esp8266.yaml | 17 +-- .../sigma_delta_output/test.rp2040.yaml | 17 +-- tests/components/slow_pwm/common.yaml | 6 + .../slow_pwm/test.esp32-c3-idf.yaml | 7 +- tests/components/slow_pwm/test.esp32-c3.yaml | 7 +- tests/components/slow_pwm/test.esp32-idf.yaml | 7 +- tests/components/slow_pwm/test.esp32.yaml | 7 +- tests/components/slow_pwm/test.esp8266.yaml | 7 +- tests/components/slow_pwm/test.rp2040.yaml | 7 +- tests/components/sm16716/common.yaml | 16 +++ .../components/sm16716/test.esp32-c3-idf.yaml | 17 +-- tests/components/sm16716/test.esp32-c3.yaml | 17 +-- tests/components/sm16716/test.esp32-idf.yaml | 17 +-- tests/components/sm16716/test.esp32.yaml | 17 +-- tests/components/sm16716/test.esp8266.yaml | 17 +-- tests/components/sm16716/test.rp2040.yaml | 17 +-- tests/components/sm2135/common.yaml | 22 ++++ .../components/sm2135/test.esp32-c3-idf.yaml | 23 +--- tests/components/sm2135/test.esp32-c3.yaml | 23 +--- tests/components/sm2135/test.esp32-idf.yaml | 23 +--- tests/components/sm2135/test.esp32.yaml | 23 +--- tests/components/sm2135/test.esp8266.yaml | 23 +--- tests/components/sm2135/test.rp2040.yaml | 23 +--- tests/components/sm2235/common.yaml | 22 ++++ .../components/sm2235/test.esp32-c3-idf.yaml | 23 +--- tests/components/sm2235/test.esp32-c3.yaml | 23 +--- tests/components/sm2235/test.esp32-idf.yaml | 23 +--- tests/components/sm2235/test.esp32.yaml | 23 +--- tests/components/sm2235/test.esp8266.yaml | 23 +--- tests/components/sm2235/test.rp2040.yaml | 23 +--- tests/components/sm2335/common.yaml | 22 ++++ .../components/sm2335/test.esp32-c3-idf.yaml | 23 +--- tests/components/sm2335/test.esp32-c3.yaml | 23 +--- tests/components/sm2335/test.esp32-idf.yaml | 23 +--- tests/components/sm2335/test.esp32.yaml | 23 +--- tests/components/sm2335/test.esp8266.yaml | 23 +--- tests/components/sm2335/test.rp2040.yaml | 23 +--- tests/components/sntp/common.yaml | 15 +++ tests/components/sntp/test.esp32-c3-idf.yaml | 16 +-- tests/components/sntp/test.esp32-c3.yaml | 16 +-- tests/components/sntp/test.esp32-idf.yaml | 16 +-- tests/components/sntp/test.esp32.yaml | 16 +-- tests/components/sntp/test.esp8266.yaml | 16 +-- tests/components/sntp/test.rp2040.yaml | 16 +-- tests/components/sprinkler/common.yaml | 83 ++++++++++++ .../sprinkler/test.esp32-c3-idf.yaml | 84 +------------ tests/components/sprinkler/test.esp32-c3.yaml | 84 +------------ .../components/sprinkler/test.esp32-idf.yaml | 84 +------------ tests/components/sprinkler/test.esp32.yaml | 84 +------------ tests/components/sprinkler/test.esp8266.yaml | 84 +------------ tests/components/sprinkler/test.rp2040.yaml | 84 +------------ tests/components/st7701s/common.yaml | 60 +++++++++ .../components/st7701s/test.esp32-s3-idf.yaml | 61 +-------- tests/components/status/common.yaml | 10 ++ .../components/status/test.esp32-c3-idf.yaml | 11 +- tests/components/status/test.esp32-c3.yaml | 11 +- tests/components/status/test.esp32-idf.yaml | 11 +- tests/components/status/test.esp32.yaml | 11 +- tests/components/status/test.esp8266.yaml | 11 +- tests/components/status/test.rp2040.yaml | 11 +- tests/components/status_led/common.yaml | 10 ++ .../status_led/test.esp32-c3-idf.yaml | 11 +- .../components/status_led/test.esp32-c3.yaml | 11 +- .../components/status_led/test.esp32-idf.yaml | 11 +- tests/components/status_led/test.esp32.yaml | 11 +- tests/components/status_led/test.esp8266.yaml | 11 +- tests/components/status_led/test.rp2040.yaml | 11 +- tests/components/stepper/common.yaml | 27 ++++ .../components/stepper/test.esp32-c3-idf.yaml | 28 +---- tests/components/stepper/test.esp32-c3.yaml | 28 +---- tests/components/stepper/test.esp32-idf.yaml | 28 +---- tests/components/stepper/test.esp32.yaml | 28 +---- tests/components/stepper/test.esp8266.yaml | 28 +---- tests/components/stepper/test.rp2040.yaml | 28 +---- tests/components/sun/common.yaml | 38 ++++++ tests/components/sun/test.esp32-c3-idf.yaml | 39 +----- tests/components/sun/test.esp32-c3.yaml | 39 +----- tests/components/sun/test.esp32-idf.yaml | 39 +----- tests/components/sun/test.esp32.yaml | 39 +----- tests/components/sun/test.esp8266.yaml | 39 +----- tests/components/sun/test.rp2040.yaml | 39 +----- tests/components/thermostat/common.yaml | 93 ++++++++++++++ .../thermostat/test.esp32-c3-idf.yaml | 94 +------------- .../components/thermostat/test.esp32-c3.yaml | 94 +------------- .../components/thermostat/test.esp32-idf.yaml | 94 +------------- tests/components/thermostat/test.esp32.yaml | 94 +------------- tests/components/thermostat/test.esp8266.yaml | 94 +------------- tests/components/thermostat/test.rp2040.yaml | 94 +------------- tests/components/time/common.yaml | 10 ++ tests/components/time/test.esp32-c3-idf.yaml | 11 +- tests/components/time/test.esp32-c3.yaml | 11 +- tests/components/time/test.esp32-idf.yaml | 11 +- tests/components/time/test.esp32.yaml | 11 +- tests/components/time/test.esp8266.yaml | 11 +- tests/components/time/test.rp2040.yaml | 11 +- tests/components/time_based/common.yaml | 12 ++ .../time_based/test.esp32-c3-idf.yaml | 13 +- .../components/time_based/test.esp32-c3.yaml | 13 +- .../components/time_based/test.esp32-idf.yaml | 13 +- tests/components/time_based/test.esp32.yaml | 13 +- tests/components/time_based/test.esp8266.yaml | 13 +- tests/components/time_based/test.rp2040.yaml | 13 +- tests/components/tm1638/common.yaml | 118 +++++++++++++++++ .../components/tm1638/test.esp32-c3-idf.yaml | 119 +----------------- tests/components/tm1638/test.esp32-c3.yaml | 119 +----------------- tests/components/tm1638/test.esp32-idf.yaml | 119 +----------------- tests/components/tm1638/test.esp32.yaml | 119 +----------------- tests/components/tm1638/test.esp8266.yaml | 119 +----------------- tests/components/tm1638/test.rp2040.yaml | 119 +----------------- tests/components/tm1651/common.yaml | 21 ++++ tests/components/tm1651/test.esp32-c3.yaml | 22 +--- tests/components/tm1651/test.esp32.yaml | 22 +--- tests/components/tm1651/test.esp8266.yaml | 22 +--- tests/components/tm1651/test.rp2040.yaml | 22 +--- tests/components/tx20/common.yaml | 7 ++ tests/components/tx20/test.esp32-c3-idf.yaml | 8 +- tests/components/tx20/test.esp32-c3.yaml | 8 +- tests/components/tx20/test.esp32-idf.yaml | 8 +- tests/components/tx20/test.esp32.yaml | 8 +- tests/components/tx20/test.esp8266.yaml | 8 +- tests/components/tx20/test.rp2040.yaml | 8 +- tests/components/ultrasonic/common.yaml | 7 ++ .../ultrasonic/test.esp32-c3-idf.yaml | 8 +- .../components/ultrasonic/test.esp32-c3.yaml | 8 +- .../components/ultrasonic/test.esp32-idf.yaml | 8 +- tests/components/ultrasonic/test.esp32.yaml | 8 +- tests/components/ultrasonic/test.esp8266.yaml | 8 +- tests/components/ultrasonic/test.rp2040.yaml | 8 +- tests/components/uptime/common.yaml | 3 + .../components/uptime/test.esp32-c3-idf.yaml | 4 +- tests/components/uptime/test.esp32-c3.yaml | 4 +- tests/components/uptime/test.esp32-idf.yaml | 4 +- tests/components/uptime/test.esp32.yaml | 4 +- tests/components/uptime/test.esp8266.yaml | 4 +- tests/components/uptime/test.rp2040.yaml | 4 +- tests/components/version/common.yaml | 3 + .../components/version/test.esp32-c3-idf.yaml | 4 +- tests/components/version/test.esp32-c3.yaml | 4 +- tests/components/version/test.esp32-idf.yaml | 4 +- tests/components/version/test.esp32.yaml | 4 +- tests/components/version/test.esp8266.yaml | 4 +- tests/components/version/test.rp2040.yaml | 4 +- tests/components/wake_on_lan/common.yaml | 9 ++ .../components/wake_on_lan/test.esp32-c3.yaml | 10 +- tests/components/wake_on_lan/test.esp32.yaml | 10 +- .../components/wake_on_lan/test.esp8266.yaml | 10 +- tests/components/wake_on_lan/test.rp2040.yaml | 10 +- tests/components/web_server/common.yaml | 7 ++ .../web_server/test.esp32-c3-idf.yaml | 8 +- .../components/web_server/test.esp32-c3.yaml | 8 +- .../components/web_server/test.esp32-idf.yaml | 8 +- tests/components/web_server/test.esp32.yaml | 8 +- tests/components/web_server/test.esp8266.yaml | 8 +- tests/components/wiegand/common.yaml | 10 ++ .../components/wiegand/test.esp32-c3-idf.yaml | 11 +- tests/components/wiegand/test.esp32-c3.yaml | 11 +- tests/components/wiegand/test.esp32-idf.yaml | 11 +- tests/components/wiegand/test.esp32.yaml | 11 +- tests/components/wiegand/test.esp8266.yaml | 11 +- tests/components/wiegand/test.rp2040.yaml | 11 +- tests/components/wifi/common.yaml | 9 ++ tests/components/wifi/test.esp32-c3-idf.yaml | 10 +- tests/components/wifi/test.esp32-c3.yaml | 10 +- tests/components/wifi/test.esp32-idf.yaml | 10 +- tests/components/wifi/test.esp32.yaml | 10 +- tests/components/wifi/test.esp8266.yaml | 10 +- tests/components/wifi/test.rp2040.yaml | 10 +- tests/components/wifi_info/common.yaml | 18 +++ .../wifi_info/test.esp32-c3-idf.yaml | 19 +-- tests/components/wifi_info/test.esp32-c3.yaml | 19 +-- .../components/wifi_info/test.esp32-idf.yaml | 19 +-- tests/components/wifi_info/test.esp32.yaml | 19 +-- tests/components/wifi_info/test.esp8266.yaml | 19 +-- tests/components/wifi_info/test.rp2040.yaml | 19 +-- tests/components/wifi_signal/common.yaml | 8 ++ .../wifi_signal/test.esp32-c3-idf.yaml | 9 +- .../components/wifi_signal/test.esp32-c3.yaml | 9 +- .../wifi_signal/test.esp32-idf.yaml | 9 +- tests/components/wifi_signal/test.esp32.yaml | 9 +- .../components/wifi_signal/test.esp8266.yaml | 9 +- tests/components/wifi_signal/test.rp2040.yaml | 9 +- tests/components/xiaomi_ble/common.yaml | 3 + .../xiaomi_ble/test.esp32-c3-idf.yaml | 4 +- .../components/xiaomi_ble/test.esp32-c3.yaml | 4 +- .../components/xiaomi_ble/test.esp32-idf.yaml | 4 +- tests/components/xiaomi_ble/test.esp32.yaml | 4 +- tests/components/xiaomi_cgd1/common.yaml | 12 ++ .../xiaomi_cgd1/test.esp32-c3-idf.yaml | 13 +- .../components/xiaomi_cgd1/test.esp32-c3.yaml | 13 +- .../xiaomi_cgd1/test.esp32-idf.yaml | 13 +- tests/components/xiaomi_cgd1/test.esp32.yaml | 13 +- tests/components/xiaomi_cgdk2/common.yaml | 12 ++ .../xiaomi_cgdk2/test.esp32-c3-idf.yaml | 13 +- .../xiaomi_cgdk2/test.esp32-c3.yaml | 13 +- .../xiaomi_cgdk2/test.esp32-idf.yaml | 13 +- tests/components/xiaomi_cgdk2/test.esp32.yaml | 13 +- tests/components/xiaomi_cgg1/common.yaml | 12 ++ .../xiaomi_cgg1/test.esp32-c3-idf.yaml | 13 +- .../components/xiaomi_cgg1/test.esp32-c3.yaml | 13 +- .../xiaomi_cgg1/test.esp32-idf.yaml | 13 +- tests/components/xiaomi_cgg1/test.esp32.yaml | 13 +- tests/components/xiaomi_cgpr1/common.yaml | 13 ++ .../xiaomi_cgpr1/test.esp32-c3-idf.yaml | 14 +-- .../xiaomi_cgpr1/test.esp32-c3.yaml | 14 +-- .../xiaomi_cgpr1/test.esp32-idf.yaml | 14 +-- tests/components/xiaomi_cgpr1/test.esp32.yaml | 14 +-- tests/components/xiaomi_gcls002/common.yaml | 13 ++ .../xiaomi_gcls002/test.esp32-c3-idf.yaml | 14 +-- .../xiaomi_gcls002/test.esp32-c3.yaml | 14 +-- .../xiaomi_gcls002/test.esp32-idf.yaml | 14 +-- .../components/xiaomi_gcls002/test.esp32.yaml | 14 +-- tests/components/xiaomi_hhccjcy01/common.yaml | 15 +++ .../xiaomi_hhccjcy01/test.esp32-c3-idf.yaml | 16 +-- .../xiaomi_hhccjcy01/test.esp32-c3.yaml | 16 +-- .../xiaomi_hhccjcy01/test.esp32-idf.yaml | 16 +-- .../xiaomi_hhccjcy01/test.esp32.yaml | 16 +-- .../components/xiaomi_hhccpot002/common.yaml | 9 ++ .../xiaomi_hhccpot002/test.esp32-c3-idf.yaml | 10 +- .../xiaomi_hhccpot002/test.esp32-c3.yaml | 10 +- .../xiaomi_hhccpot002/test.esp32-idf.yaml | 10 +- .../xiaomi_hhccpot002/test.esp32.yaml | 10 +- tests/components/xiaomi_jqjcy01ym/common.yaml | 13 ++ .../xiaomi_jqjcy01ym/test.esp32-c3-idf.yaml | 14 +-- .../xiaomi_jqjcy01ym/test.esp32-c3.yaml | 14 +-- .../xiaomi_jqjcy01ym/test.esp32-idf.yaml | 14 +-- .../xiaomi_jqjcy01ym/test.esp32.yaml | 14 +-- tests/components/xiaomi_lywsd02/common.yaml | 11 ++ .../xiaomi_lywsd02/test.esp32-c3-idf.yaml | 12 +- .../xiaomi_lywsd02/test.esp32-c3.yaml | 12 +- .../xiaomi_lywsd02/test.esp32-idf.yaml | 12 +- .../components/xiaomi_lywsd02/test.esp32.yaml | 12 +- .../components/xiaomi_lywsd03mmc/common.yaml | 12 ++ .../xiaomi_lywsd03mmc/test.esp32-c3-idf.yaml | 13 +- .../xiaomi_lywsd03mmc/test.esp32-c3.yaml | 13 +- .../xiaomi_lywsd03mmc/test.esp32-idf.yaml | 13 +- .../xiaomi_lywsd03mmc/test.esp32.yaml | 13 +- tests/components/xiaomi_lywsdcgq/common.yaml | 11 ++ .../xiaomi_lywsdcgq/test.esp32-c3-idf.yaml | 12 +- .../xiaomi_lywsdcgq/test.esp32-c3.yaml | 12 +- .../xiaomi_lywsdcgq/test.esp32-idf.yaml | 12 +- .../xiaomi_lywsdcgq/test.esp32.yaml | 12 +- tests/components/xiaomi_mhoc303/common.yaml | 11 ++ .../xiaomi_mhoc303/test.esp32-c3-idf.yaml | 12 +- .../xiaomi_mhoc303/test.esp32-c3.yaml | 12 +- .../xiaomi_mhoc303/test.esp32-idf.yaml | 12 +- .../components/xiaomi_mhoc303/test.esp32.yaml | 12 +- tests/components/xiaomi_mhoc401/common.yaml | 12 ++ .../xiaomi_mhoc401/test.esp32-c3-idf.yaml | 13 +- .../xiaomi_mhoc401/test.esp32-c3.yaml | 13 +- .../xiaomi_mhoc401/test.esp32-idf.yaml | 13 +- .../components/xiaomi_mhoc401/test.esp32.yaml | 13 +- .../xiaomi_miscale copy/common.yaml | 9 ++ .../test.esp32-c3-idf.yaml | 10 +- .../xiaomi_miscale copy/test.esp32-c3.yaml | 10 +- .../xiaomi_miscale copy/test.esp32-idf.yaml | 10 +- .../xiaomi_miscale copy/test.esp32.yaml | 10 +- tests/components/xiaomi_miscale/common.yaml | 9 ++ .../xiaomi_miscale/test.esp32-c3-idf.yaml | 10 +- .../xiaomi_miscale/test.esp32-c3.yaml | 10 +- .../xiaomi_miscale/test.esp32-idf.yaml | 10 +- .../components/xiaomi_miscale/test.esp32.yaml | 10 +- tests/components/xiaomi_mjyd02yla/common.yaml | 13 ++ .../xiaomi_mjyd02yla/test.esp32-c3-idf.yaml | 14 +-- .../xiaomi_mjyd02yla/test.esp32-c3.yaml | 14 +-- .../xiaomi_mjyd02yla/test.esp32-idf.yaml | 14 +-- .../xiaomi_mjyd02yla/test.esp32.yaml | 14 +-- tests/components/xiaomi_mue4094rt/common.yaml | 7 ++ .../xiaomi_mue4094rt/test.esp32-c3-idf.yaml | 8 +- .../xiaomi_mue4094rt/test.esp32-c3.yaml | 8 +- .../xiaomi_mue4094rt/test.esp32-idf.yaml | 8 +- .../xiaomi_mue4094rt/test.esp32.yaml | 8 +- tests/components/xiaomi_rtcgq02lm/common.yaml | 22 ++++ .../xiaomi_rtcgq02lm/test.esp32-c3-idf.yaml | 23 +--- .../xiaomi_rtcgq02lm/test.esp32-c3.yaml | 23 +--- .../xiaomi_rtcgq02lm/test.esp32-idf.yaml | 23 +--- .../xiaomi_rtcgq02lm/test.esp32.yaml | 23 +--- tests/components/xiaomi_wx08zm/common.yaml | 10 ++ .../xiaomi_wx08zm/test.esp32-c3-idf.yaml | 11 +- .../xiaomi_wx08zm/test.esp32-c3.yaml | 11 +- .../xiaomi_wx08zm/test.esp32-idf.yaml | 11 +- .../components/xiaomi_wx08zm/test.esp32.yaml | 11 +- 779 files changed, 3474 insertions(+), 12186 deletions(-) create mode 100644 tests/components/absolute_humidity/common.yaml create mode 100644 tests/components/airthings_wave_mini/common.yaml create mode 100644 tests/components/airthings_wave_plus/common.yaml create mode 100644 tests/components/alarm_control_panel/common.yaml create mode 100644 tests/components/alpha3/common.yaml create mode 100644 tests/components/am43/common.yaml create mode 100644 tests/components/analog_threshold/common.yaml create mode 100644 tests/components/anova/common.yaml create mode 100644 tests/components/api/common.yaml create mode 100644 tests/components/atc_mithermometer/common.yaml create mode 100644 tests/components/b_parasite/common.yaml create mode 100644 tests/components/bang_bang/common.yaml create mode 100644 tests/components/bedjet/common.yaml create mode 100644 tests/components/binary_sensor_map/common.yaml create mode 100644 tests/components/ble_client/common.yaml create mode 100644 tests/components/ble_presence/common.yaml create mode 100644 tests/components/ble_rssi/common.yaml create mode 100644 tests/components/ble_scanner/common.yaml create mode 100644 tests/components/button/common.yaml create mode 100644 tests/components/canbus/common.yaml create mode 100644 tests/components/captive_portal/common.yaml create mode 100644 tests/components/color/common.yaml create mode 100644 tests/components/combination/common.yaml create mode 100644 tests/components/cst226/common.yaml create mode 100644 tests/components/cst816/common.yaml create mode 100644 tests/components/dallas/common.yaml create mode 100644 tests/components/datetime/common.yaml create mode 100644 tests/components/debug/common.yaml create mode 100644 tests/components/dht/common.yaml create mode 100644 tests/components/display/common.yaml create mode 100644 tests/components/duty_cycle/common.yaml create mode 100644 tests/components/duty_time/common.yaml create mode 100644 tests/components/endstop/common.yaml create mode 100644 tests/components/esp32_ble/common.yaml create mode 100644 tests/components/esp32_ble_beacon/common.yaml create mode 100644 tests/components/esp32_ble_client/common.yaml create mode 100644 tests/components/esp32_ble_server/common.yaml create mode 100644 tests/components/esp32_ble_tracker/common.yaml create mode 100644 tests/components/esp32_camera/common.yaml create mode 100644 tests/components/esp32_camera_web_server/common.yaml create mode 100644 tests/components/esp32_dac/common.yaml create mode 100644 tests/components/esp32_hall/common.yaml create mode 100644 tests/components/esp32_improv/common.yaml create mode 100644 tests/components/esp32_touch/common.yaml create mode 100644 tests/components/esp8266_pwm/common.yaml create mode 100644 tests/components/ethernet/common.yaml create mode 100644 tests/components/ethernet_info/common.yaml create mode 100644 tests/components/event/common.yaml create mode 100644 tests/components/exposure_notifications/common.yaml create mode 100644 tests/components/external_components/common.yaml create mode 100644 tests/components/factory_reset/common.yaml create mode 100644 tests/components/fastled_clockless/common.yaml create mode 100644 tests/components/fastled_spi/common.yaml create mode 100644 tests/components/feedback/common.yaml create mode 100644 tests/components/globals/common.yaml create mode 100644 tests/components/host/common.yaml create mode 100644 tests/components/improv_serial/common.yaml create mode 100644 tests/components/inkbird_ibsth1_mini/common.yaml create mode 100644 tests/components/inkplate6/common.yaml create mode 100644 tests/components/interval/common.yaml create mode 100644 tests/components/ledc/common.yaml create mode 100644 tests/components/lightwaverf/common.yaml create mode 100644 tests/components/lock/common.yaml create mode 100644 tests/components/logger/common.yaml create mode 100644 tests/components/mdns/common.yaml create mode 100644 tests/components/media_player/common.yaml create mode 100644 tests/components/micro_wake_word/common.yaml create mode 100644 tests/components/midea_ir/common.yaml create mode 100644 tests/components/mitsubishi/common.yaml create mode 100644 tests/components/mopeka_ble/common.yaml create mode 100644 tests/components/mopeka_pro_check/common.yaml create mode 100644 tests/components/mopeka_std_check/common.yaml create mode 100644 tests/components/my9231/common.yaml create mode 100644 tests/components/network/common.yaml create mode 100644 tests/components/noblex/common.yaml create mode 100644 tests/components/ota/common.yaml create mode 100644 tests/components/pid/common.yaml create mode 100644 tests/components/power_supply/common.yaml create mode 100644 tests/components/prometheus/common.yaml create mode 100644 tests/components/psram/common.yaml create mode 100644 tests/components/pulse_counter/common.yaml create mode 100644 tests/components/pulse_meter/common.yaml create mode 100644 tests/components/pulse_width/common.yaml create mode 100644 tests/components/pvvx_mithermometer/common.yaml create mode 100644 tests/components/qspi_amoled/common.yaml create mode 100644 tests/components/radon_eye_ble/common.yaml create mode 100644 tests/components/radon_eye_rd200/common.yaml create mode 100644 tests/components/restart/common.yaml create mode 100644 tests/components/rp2040_pio_led_strip/common.yaml create mode 100644 tests/components/rp2040_pwm/common.yaml create mode 100644 tests/components/rpi_dpi_rgb/common.yaml create mode 100644 tests/components/ruuvi_ble/common.yaml create mode 100644 tests/components/ruuvitag/common.yaml create mode 100644 tests/components/safe_mode/common.yaml create mode 100644 tests/components/shelly_dimmer/common.yaml create mode 100644 tests/components/shutdown/common.yaml create mode 100644 tests/components/sigma_delta_output/common.yaml create mode 100644 tests/components/slow_pwm/common.yaml create mode 100644 tests/components/sm16716/common.yaml create mode 100644 tests/components/sm2135/common.yaml create mode 100644 tests/components/sm2235/common.yaml create mode 100644 tests/components/sm2335/common.yaml create mode 100644 tests/components/sntp/common.yaml create mode 100644 tests/components/sprinkler/common.yaml create mode 100644 tests/components/st7701s/common.yaml create mode 100644 tests/components/status/common.yaml create mode 100644 tests/components/status_led/common.yaml create mode 100644 tests/components/stepper/common.yaml create mode 100644 tests/components/sun/common.yaml create mode 100644 tests/components/thermostat/common.yaml create mode 100644 tests/components/time/common.yaml create mode 100644 tests/components/time_based/common.yaml create mode 100644 tests/components/tm1638/common.yaml create mode 100644 tests/components/tm1651/common.yaml create mode 100644 tests/components/tx20/common.yaml create mode 100644 tests/components/ultrasonic/common.yaml create mode 100644 tests/components/uptime/common.yaml create mode 100644 tests/components/version/common.yaml create mode 100644 tests/components/wake_on_lan/common.yaml create mode 100644 tests/components/web_server/common.yaml create mode 100644 tests/components/wiegand/common.yaml create mode 100644 tests/components/wifi/common.yaml create mode 100644 tests/components/wifi_info/common.yaml create mode 100644 tests/components/wifi_signal/common.yaml create mode 100644 tests/components/xiaomi_ble/common.yaml create mode 100644 tests/components/xiaomi_cgd1/common.yaml create mode 100644 tests/components/xiaomi_cgdk2/common.yaml create mode 100644 tests/components/xiaomi_cgg1/common.yaml create mode 100644 tests/components/xiaomi_cgpr1/common.yaml create mode 100644 tests/components/xiaomi_gcls002/common.yaml create mode 100644 tests/components/xiaomi_hhccjcy01/common.yaml create mode 100644 tests/components/xiaomi_hhccpot002/common.yaml create mode 100644 tests/components/xiaomi_jqjcy01ym/common.yaml create mode 100644 tests/components/xiaomi_lywsd02/common.yaml create mode 100644 tests/components/xiaomi_lywsd03mmc/common.yaml create mode 100644 tests/components/xiaomi_lywsdcgq/common.yaml create mode 100644 tests/components/xiaomi_mhoc303/common.yaml create mode 100644 tests/components/xiaomi_mhoc401/common.yaml create mode 100644 tests/components/xiaomi_miscale copy/common.yaml create mode 100644 tests/components/xiaomi_miscale/common.yaml create mode 100644 tests/components/xiaomi_mjyd02yla/common.yaml create mode 100644 tests/components/xiaomi_mue4094rt/common.yaml create mode 100644 tests/components/xiaomi_rtcgq02lm/common.yaml create mode 100644 tests/components/xiaomi_wx08zm/common.yaml diff --git a/tests/components/absolute_humidity/common.yaml b/tests/components/absolute_humidity/common.yaml new file mode 100644 index 0000000000..87a99f5206 --- /dev/null +++ b/tests/components/absolute_humidity/common.yaml @@ -0,0 +1,21 @@ +sensor: + - platform: absolute_humidity + name: Absolute Humidity + temperature: template_temperature + humidity: template_humidity + - platform: template + id: template_humidity + lambda: |- + if (millis() > 10000) { + return 0.6; + } else { + return 0.0; + } + - platform: template + id: template_temperature + lambda: |- + if (millis() > 10000) { + return 42.0; + } else { + return 0.0; + } diff --git a/tests/components/absolute_humidity/test.esp32-c3-idf.yaml b/tests/components/absolute_humidity/test.esp32-c3-idf.yaml index 87a99f5206..dade44d145 100644 --- a/tests/components/absolute_humidity/test.esp32-c3-idf.yaml +++ b/tests/components/absolute_humidity/test.esp32-c3-idf.yaml @@ -1,21 +1 @@ -sensor: - - platform: absolute_humidity - name: Absolute Humidity - temperature: template_temperature - humidity: template_humidity - - platform: template - id: template_humidity - lambda: |- - if (millis() > 10000) { - return 0.6; - } else { - return 0.0; - } - - platform: template - id: template_temperature - lambda: |- - if (millis() > 10000) { - return 42.0; - } else { - return 0.0; - } +<<: !include common.yaml diff --git a/tests/components/absolute_humidity/test.esp32-c3.yaml b/tests/components/absolute_humidity/test.esp32-c3.yaml index 87a99f5206..dade44d145 100644 --- a/tests/components/absolute_humidity/test.esp32-c3.yaml +++ b/tests/components/absolute_humidity/test.esp32-c3.yaml @@ -1,21 +1 @@ -sensor: - - platform: absolute_humidity - name: Absolute Humidity - temperature: template_temperature - humidity: template_humidity - - platform: template - id: template_humidity - lambda: |- - if (millis() > 10000) { - return 0.6; - } else { - return 0.0; - } - - platform: template - id: template_temperature - lambda: |- - if (millis() > 10000) { - return 42.0; - } else { - return 0.0; - } +<<: !include common.yaml diff --git a/tests/components/absolute_humidity/test.esp32-idf.yaml b/tests/components/absolute_humidity/test.esp32-idf.yaml index 87a99f5206..dade44d145 100644 --- a/tests/components/absolute_humidity/test.esp32-idf.yaml +++ b/tests/components/absolute_humidity/test.esp32-idf.yaml @@ -1,21 +1 @@ -sensor: - - platform: absolute_humidity - name: Absolute Humidity - temperature: template_temperature - humidity: template_humidity - - platform: template - id: template_humidity - lambda: |- - if (millis() > 10000) { - return 0.6; - } else { - return 0.0; - } - - platform: template - id: template_temperature - lambda: |- - if (millis() > 10000) { - return 42.0; - } else { - return 0.0; - } +<<: !include common.yaml diff --git a/tests/components/absolute_humidity/test.esp32.yaml b/tests/components/absolute_humidity/test.esp32.yaml index 87a99f5206..dade44d145 100644 --- a/tests/components/absolute_humidity/test.esp32.yaml +++ b/tests/components/absolute_humidity/test.esp32.yaml @@ -1,21 +1 @@ -sensor: - - platform: absolute_humidity - name: Absolute Humidity - temperature: template_temperature - humidity: template_humidity - - platform: template - id: template_humidity - lambda: |- - if (millis() > 10000) { - return 0.6; - } else { - return 0.0; - } - - platform: template - id: template_temperature - lambda: |- - if (millis() > 10000) { - return 42.0; - } else { - return 0.0; - } +<<: !include common.yaml diff --git a/tests/components/absolute_humidity/test.esp8266.yaml b/tests/components/absolute_humidity/test.esp8266.yaml index 87a99f5206..dade44d145 100644 --- a/tests/components/absolute_humidity/test.esp8266.yaml +++ b/tests/components/absolute_humidity/test.esp8266.yaml @@ -1,21 +1 @@ -sensor: - - platform: absolute_humidity - name: Absolute Humidity - temperature: template_temperature - humidity: template_humidity - - platform: template - id: template_humidity - lambda: |- - if (millis() > 10000) { - return 0.6; - } else { - return 0.0; - } - - platform: template - id: template_temperature - lambda: |- - if (millis() > 10000) { - return 42.0; - } else { - return 0.0; - } +<<: !include common.yaml diff --git a/tests/components/absolute_humidity/test.rp2040.yaml b/tests/components/absolute_humidity/test.rp2040.yaml index 87a99f5206..dade44d145 100644 --- a/tests/components/absolute_humidity/test.rp2040.yaml +++ b/tests/components/absolute_humidity/test.rp2040.yaml @@ -1,21 +1 @@ -sensor: - - platform: absolute_humidity - name: Absolute Humidity - temperature: template_temperature - humidity: template_humidity - - platform: template - id: template_humidity - lambda: |- - if (millis() > 10000) { - return 0.6; - } else { - return 0.0; - } - - platform: template - id: template_temperature - lambda: |- - if (millis() > 10000) { - return 42.0; - } else { - return 0.0; - } +<<: !include common.yaml diff --git a/tests/components/airthings_wave_mini/common.yaml b/tests/components/airthings_wave_mini/common.yaml new file mode 100644 index 0000000000..87902e6c66 --- /dev/null +++ b/tests/components/airthings_wave_mini/common.yaml @@ -0,0 +1,22 @@ +esp32_ble_tracker: + +ble_client: + - mac_address: 01:02:03:04:05:06 + id: airthingsmini01 + +sensor: + - id: airthingswm + platform: airthings_wave_mini + ble_client_id: airthingsmini01 + update_interval: 5min + battery_update_interval: 12h + temperature: + name: Wave Mini Temperature + humidity: + name: Wave Mini Humidity + pressure: + name: Wave Mini Pressure + tvoc: + name: Wave Mini VOC + battery_voltage: + name: Wave Mini Battery Voltage diff --git a/tests/components/airthings_wave_mini/test.esp32-c3-idf.yaml b/tests/components/airthings_wave_mini/test.esp32-c3-idf.yaml index 87902e6c66..dade44d145 100644 --- a/tests/components/airthings_wave_mini/test.esp32-c3-idf.yaml +++ b/tests/components/airthings_wave_mini/test.esp32-c3-idf.yaml @@ -1,22 +1 @@ -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: airthingsmini01 - -sensor: - - id: airthingswm - platform: airthings_wave_mini - ble_client_id: airthingsmini01 - update_interval: 5min - battery_update_interval: 12h - temperature: - name: Wave Mini Temperature - humidity: - name: Wave Mini Humidity - pressure: - name: Wave Mini Pressure - tvoc: - name: Wave Mini VOC - battery_voltage: - name: Wave Mini Battery Voltage +<<: !include common.yaml diff --git a/tests/components/airthings_wave_mini/test.esp32-c3.yaml b/tests/components/airthings_wave_mini/test.esp32-c3.yaml index 87902e6c66..dade44d145 100644 --- a/tests/components/airthings_wave_mini/test.esp32-c3.yaml +++ b/tests/components/airthings_wave_mini/test.esp32-c3.yaml @@ -1,22 +1 @@ -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: airthingsmini01 - -sensor: - - id: airthingswm - platform: airthings_wave_mini - ble_client_id: airthingsmini01 - update_interval: 5min - battery_update_interval: 12h - temperature: - name: Wave Mini Temperature - humidity: - name: Wave Mini Humidity - pressure: - name: Wave Mini Pressure - tvoc: - name: Wave Mini VOC - battery_voltage: - name: Wave Mini Battery Voltage +<<: !include common.yaml diff --git a/tests/components/airthings_wave_mini/test.esp32-idf.yaml b/tests/components/airthings_wave_mini/test.esp32-idf.yaml index 87902e6c66..dade44d145 100644 --- a/tests/components/airthings_wave_mini/test.esp32-idf.yaml +++ b/tests/components/airthings_wave_mini/test.esp32-idf.yaml @@ -1,22 +1 @@ -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: airthingsmini01 - -sensor: - - id: airthingswm - platform: airthings_wave_mini - ble_client_id: airthingsmini01 - update_interval: 5min - battery_update_interval: 12h - temperature: - name: Wave Mini Temperature - humidity: - name: Wave Mini Humidity - pressure: - name: Wave Mini Pressure - tvoc: - name: Wave Mini VOC - battery_voltage: - name: Wave Mini Battery Voltage +<<: !include common.yaml diff --git a/tests/components/airthings_wave_mini/test.esp32.yaml b/tests/components/airthings_wave_mini/test.esp32.yaml index 87902e6c66..dade44d145 100644 --- a/tests/components/airthings_wave_mini/test.esp32.yaml +++ b/tests/components/airthings_wave_mini/test.esp32.yaml @@ -1,22 +1 @@ -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: airthingsmini01 - -sensor: - - id: airthingswm - platform: airthings_wave_mini - ble_client_id: airthingsmini01 - update_interval: 5min - battery_update_interval: 12h - temperature: - name: Wave Mini Temperature - humidity: - name: Wave Mini Humidity - pressure: - name: Wave Mini Pressure - tvoc: - name: Wave Mini VOC - battery_voltage: - name: Wave Mini Battery Voltage +<<: !include common.yaml diff --git a/tests/components/airthings_wave_plus/common.yaml b/tests/components/airthings_wave_plus/common.yaml new file mode 100644 index 0000000000..2124fcdaec --- /dev/null +++ b/tests/components/airthings_wave_plus/common.yaml @@ -0,0 +1,28 @@ +esp32_ble_tracker: + +ble_client: + - mac_address: 01:02:03:04:05:06 + id: airthings01 + +sensor: + - id: airthingswp + platform: airthings_wave_plus + ble_client_id: airthings01 + update_interval: 5min + battery_update_interval: 12h + temperature: + name: Wave Plus Temperature + radon: + name: Wave Plus Radon + radon_long_term: + name: Wave Plus Radon Long Term + pressure: + name: Wave Plus Pressure + humidity: + name: Wave Plus Humidity + co2: + name: Wave Plus CO2 + tvoc: + name: Wave Plus VOC + battery_voltage: + name: Wave Plus Battery Voltage diff --git a/tests/components/airthings_wave_plus/test.esp32-c3-idf.yaml b/tests/components/airthings_wave_plus/test.esp32-c3-idf.yaml index 2124fcdaec..dade44d145 100644 --- a/tests/components/airthings_wave_plus/test.esp32-c3-idf.yaml +++ b/tests/components/airthings_wave_plus/test.esp32-c3-idf.yaml @@ -1,28 +1 @@ -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: airthings01 - -sensor: - - id: airthingswp - platform: airthings_wave_plus - ble_client_id: airthings01 - update_interval: 5min - battery_update_interval: 12h - temperature: - name: Wave Plus Temperature - radon: - name: Wave Plus Radon - radon_long_term: - name: Wave Plus Radon Long Term - pressure: - name: Wave Plus Pressure - humidity: - name: Wave Plus Humidity - co2: - name: Wave Plus CO2 - tvoc: - name: Wave Plus VOC - battery_voltage: - name: Wave Plus Battery Voltage +<<: !include common.yaml diff --git a/tests/components/airthings_wave_plus/test.esp32-c3.yaml b/tests/components/airthings_wave_plus/test.esp32-c3.yaml index 2124fcdaec..dade44d145 100644 --- a/tests/components/airthings_wave_plus/test.esp32-c3.yaml +++ b/tests/components/airthings_wave_plus/test.esp32-c3.yaml @@ -1,28 +1 @@ -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: airthings01 - -sensor: - - id: airthingswp - platform: airthings_wave_plus - ble_client_id: airthings01 - update_interval: 5min - battery_update_interval: 12h - temperature: - name: Wave Plus Temperature - radon: - name: Wave Plus Radon - radon_long_term: - name: Wave Plus Radon Long Term - pressure: - name: Wave Plus Pressure - humidity: - name: Wave Plus Humidity - co2: - name: Wave Plus CO2 - tvoc: - name: Wave Plus VOC - battery_voltage: - name: Wave Plus Battery Voltage +<<: !include common.yaml diff --git a/tests/components/airthings_wave_plus/test.esp32-idf.yaml b/tests/components/airthings_wave_plus/test.esp32-idf.yaml index 2124fcdaec..dade44d145 100644 --- a/tests/components/airthings_wave_plus/test.esp32-idf.yaml +++ b/tests/components/airthings_wave_plus/test.esp32-idf.yaml @@ -1,28 +1 @@ -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: airthings01 - -sensor: - - id: airthingswp - platform: airthings_wave_plus - ble_client_id: airthings01 - update_interval: 5min - battery_update_interval: 12h - temperature: - name: Wave Plus Temperature - radon: - name: Wave Plus Radon - radon_long_term: - name: Wave Plus Radon Long Term - pressure: - name: Wave Plus Pressure - humidity: - name: Wave Plus Humidity - co2: - name: Wave Plus CO2 - tvoc: - name: Wave Plus VOC - battery_voltage: - name: Wave Plus Battery Voltage +<<: !include common.yaml diff --git a/tests/components/airthings_wave_plus/test.esp32.yaml b/tests/components/airthings_wave_plus/test.esp32.yaml index 2124fcdaec..dade44d145 100644 --- a/tests/components/airthings_wave_plus/test.esp32.yaml +++ b/tests/components/airthings_wave_plus/test.esp32.yaml @@ -1,28 +1 @@ -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: airthings01 - -sensor: - - id: airthingswp - platform: airthings_wave_plus - ble_client_id: airthings01 - update_interval: 5min - battery_update_interval: 12h - temperature: - name: Wave Plus Temperature - radon: - name: Wave Plus Radon - radon_long_term: - name: Wave Plus Radon Long Term - pressure: - name: Wave Plus Pressure - humidity: - name: Wave Plus Humidity - co2: - name: Wave Plus CO2 - tvoc: - name: Wave Plus VOC - battery_voltage: - name: Wave Plus Battery Voltage +<<: !include common.yaml diff --git a/tests/components/alarm_control_panel/common.yaml b/tests/components/alarm_control_panel/common.yaml new file mode 100644 index 0000000000..218274bad4 --- /dev/null +++ b/tests/components/alarm_control_panel/common.yaml @@ -0,0 +1,64 @@ +binary_sensor: + - platform: gpio + id: bin1 + pin: 1 + +alarm_control_panel: + - platform: template + id: alarmcontrolpanel1 + name: Alarm Panel + codes: + - "1234" + requires_code_to_arm: true + arming_home_time: 1s + arming_night_time: 1s + arming_away_time: 15s + pending_time: 15s + trigger_time: 30s + binary_sensors: + - input: bin1 + bypass_armed_home: true + bypass_armed_night: true + on_state: + then: + - lambda: !lambda |- + ESP_LOGD("TEST", "State change %s", LOG_STR_ARG(alarm_control_panel_state_to_string(id(alarmcontrolpanel1)->get_state()))); + - platform: template + id: alarmcontrolpanel2 + name: Alarm Panel + codes: + - "1234" + requires_code_to_arm: true + arming_home_time: 1s + arming_night_time: 1s + arming_away_time: 15s + pending_time: 15s + trigger_time: 30s + binary_sensors: + - input: bin1 + bypass_armed_home: true + bypass_armed_night: true + on_disarmed: + then: + - logger.log: "### DISARMED ###" + on_pending: + then: + - logger.log: "### PENDING ###" + on_arming: + then: + - logger.log: "### ARMING ###" + on_armed_home: + then: + - logger.log: "### ARMED HOME ###" + on_armed_night: + then: + - logger.log: "### ARMED NIGHT ###" + on_armed_away: + then: + - logger.log: "### ARMED AWAY ###" + on_triggered: + then: + - logger.log: "### TRIGGERED ###" + on_cleared: + then: + - logger.log: "### CLEARED ###" diff --git a/tests/components/alarm_control_panel/test.esp32-c3-idf.yaml b/tests/components/alarm_control_panel/test.esp32-c3-idf.yaml index 218274bad4..dade44d145 100644 --- a/tests/components/alarm_control_panel/test.esp32-c3-idf.yaml +++ b/tests/components/alarm_control_panel/test.esp32-c3-idf.yaml @@ -1,64 +1 @@ -binary_sensor: - - platform: gpio - id: bin1 - pin: 1 - -alarm_control_panel: - - platform: template - id: alarmcontrolpanel1 - name: Alarm Panel - codes: - - "1234" - requires_code_to_arm: true - arming_home_time: 1s - arming_night_time: 1s - arming_away_time: 15s - pending_time: 15s - trigger_time: 30s - binary_sensors: - - input: bin1 - bypass_armed_home: true - bypass_armed_night: true - on_state: - then: - - lambda: !lambda |- - ESP_LOGD("TEST", "State change %s", LOG_STR_ARG(alarm_control_panel_state_to_string(id(alarmcontrolpanel1)->get_state()))); - - platform: template - id: alarmcontrolpanel2 - name: Alarm Panel - codes: - - "1234" - requires_code_to_arm: true - arming_home_time: 1s - arming_night_time: 1s - arming_away_time: 15s - pending_time: 15s - trigger_time: 30s - binary_sensors: - - input: bin1 - bypass_armed_home: true - bypass_armed_night: true - on_disarmed: - then: - - logger.log: "### DISARMED ###" - on_pending: - then: - - logger.log: "### PENDING ###" - on_arming: - then: - - logger.log: "### ARMING ###" - on_armed_home: - then: - - logger.log: "### ARMED HOME ###" - on_armed_night: - then: - - logger.log: "### ARMED NIGHT ###" - on_armed_away: - then: - - logger.log: "### ARMED AWAY ###" - on_triggered: - then: - - logger.log: "### TRIGGERED ###" - on_cleared: - then: - - logger.log: "### CLEARED ###" +<<: !include common.yaml diff --git a/tests/components/alarm_control_panel/test.esp32-c3.yaml b/tests/components/alarm_control_panel/test.esp32-c3.yaml index 218274bad4..dade44d145 100644 --- a/tests/components/alarm_control_panel/test.esp32-c3.yaml +++ b/tests/components/alarm_control_panel/test.esp32-c3.yaml @@ -1,64 +1 @@ -binary_sensor: - - platform: gpio - id: bin1 - pin: 1 - -alarm_control_panel: - - platform: template - id: alarmcontrolpanel1 - name: Alarm Panel - codes: - - "1234" - requires_code_to_arm: true - arming_home_time: 1s - arming_night_time: 1s - arming_away_time: 15s - pending_time: 15s - trigger_time: 30s - binary_sensors: - - input: bin1 - bypass_armed_home: true - bypass_armed_night: true - on_state: - then: - - lambda: !lambda |- - ESP_LOGD("TEST", "State change %s", LOG_STR_ARG(alarm_control_panel_state_to_string(id(alarmcontrolpanel1)->get_state()))); - - platform: template - id: alarmcontrolpanel2 - name: Alarm Panel - codes: - - "1234" - requires_code_to_arm: true - arming_home_time: 1s - arming_night_time: 1s - arming_away_time: 15s - pending_time: 15s - trigger_time: 30s - binary_sensors: - - input: bin1 - bypass_armed_home: true - bypass_armed_night: true - on_disarmed: - then: - - logger.log: "### DISARMED ###" - on_pending: - then: - - logger.log: "### PENDING ###" - on_arming: - then: - - logger.log: "### ARMING ###" - on_armed_home: - then: - - logger.log: "### ARMED HOME ###" - on_armed_night: - then: - - logger.log: "### ARMED NIGHT ###" - on_armed_away: - then: - - logger.log: "### ARMED AWAY ###" - on_triggered: - then: - - logger.log: "### TRIGGERED ###" - on_cleared: - then: - - logger.log: "### CLEARED ###" +<<: !include common.yaml diff --git a/tests/components/alarm_control_panel/test.esp32-idf.yaml b/tests/components/alarm_control_panel/test.esp32-idf.yaml index 218274bad4..dade44d145 100644 --- a/tests/components/alarm_control_panel/test.esp32-idf.yaml +++ b/tests/components/alarm_control_panel/test.esp32-idf.yaml @@ -1,64 +1 @@ -binary_sensor: - - platform: gpio - id: bin1 - pin: 1 - -alarm_control_panel: - - platform: template - id: alarmcontrolpanel1 - name: Alarm Panel - codes: - - "1234" - requires_code_to_arm: true - arming_home_time: 1s - arming_night_time: 1s - arming_away_time: 15s - pending_time: 15s - trigger_time: 30s - binary_sensors: - - input: bin1 - bypass_armed_home: true - bypass_armed_night: true - on_state: - then: - - lambda: !lambda |- - ESP_LOGD("TEST", "State change %s", LOG_STR_ARG(alarm_control_panel_state_to_string(id(alarmcontrolpanel1)->get_state()))); - - platform: template - id: alarmcontrolpanel2 - name: Alarm Panel - codes: - - "1234" - requires_code_to_arm: true - arming_home_time: 1s - arming_night_time: 1s - arming_away_time: 15s - pending_time: 15s - trigger_time: 30s - binary_sensors: - - input: bin1 - bypass_armed_home: true - bypass_armed_night: true - on_disarmed: - then: - - logger.log: "### DISARMED ###" - on_pending: - then: - - logger.log: "### PENDING ###" - on_arming: - then: - - logger.log: "### ARMING ###" - on_armed_home: - then: - - logger.log: "### ARMED HOME ###" - on_armed_night: - then: - - logger.log: "### ARMED NIGHT ###" - on_armed_away: - then: - - logger.log: "### ARMED AWAY ###" - on_triggered: - then: - - logger.log: "### TRIGGERED ###" - on_cleared: - then: - - logger.log: "### CLEARED ###" +<<: !include common.yaml diff --git a/tests/components/alarm_control_panel/test.esp32.yaml b/tests/components/alarm_control_panel/test.esp32.yaml index 218274bad4..dade44d145 100644 --- a/tests/components/alarm_control_panel/test.esp32.yaml +++ b/tests/components/alarm_control_panel/test.esp32.yaml @@ -1,64 +1 @@ -binary_sensor: - - platform: gpio - id: bin1 - pin: 1 - -alarm_control_panel: - - platform: template - id: alarmcontrolpanel1 - name: Alarm Panel - codes: - - "1234" - requires_code_to_arm: true - arming_home_time: 1s - arming_night_time: 1s - arming_away_time: 15s - pending_time: 15s - trigger_time: 30s - binary_sensors: - - input: bin1 - bypass_armed_home: true - bypass_armed_night: true - on_state: - then: - - lambda: !lambda |- - ESP_LOGD("TEST", "State change %s", LOG_STR_ARG(alarm_control_panel_state_to_string(id(alarmcontrolpanel1)->get_state()))); - - platform: template - id: alarmcontrolpanel2 - name: Alarm Panel - codes: - - "1234" - requires_code_to_arm: true - arming_home_time: 1s - arming_night_time: 1s - arming_away_time: 15s - pending_time: 15s - trigger_time: 30s - binary_sensors: - - input: bin1 - bypass_armed_home: true - bypass_armed_night: true - on_disarmed: - then: - - logger.log: "### DISARMED ###" - on_pending: - then: - - logger.log: "### PENDING ###" - on_arming: - then: - - logger.log: "### ARMING ###" - on_armed_home: - then: - - logger.log: "### ARMED HOME ###" - on_armed_night: - then: - - logger.log: "### ARMED NIGHT ###" - on_armed_away: - then: - - logger.log: "### ARMED AWAY ###" - on_triggered: - then: - - logger.log: "### TRIGGERED ###" - on_cleared: - then: - - logger.log: "### CLEARED ###" +<<: !include common.yaml diff --git a/tests/components/alarm_control_panel/test.esp8266.yaml b/tests/components/alarm_control_panel/test.esp8266.yaml index 218274bad4..dade44d145 100644 --- a/tests/components/alarm_control_panel/test.esp8266.yaml +++ b/tests/components/alarm_control_panel/test.esp8266.yaml @@ -1,64 +1 @@ -binary_sensor: - - platform: gpio - id: bin1 - pin: 1 - -alarm_control_panel: - - platform: template - id: alarmcontrolpanel1 - name: Alarm Panel - codes: - - "1234" - requires_code_to_arm: true - arming_home_time: 1s - arming_night_time: 1s - arming_away_time: 15s - pending_time: 15s - trigger_time: 30s - binary_sensors: - - input: bin1 - bypass_armed_home: true - bypass_armed_night: true - on_state: - then: - - lambda: !lambda |- - ESP_LOGD("TEST", "State change %s", LOG_STR_ARG(alarm_control_panel_state_to_string(id(alarmcontrolpanel1)->get_state()))); - - platform: template - id: alarmcontrolpanel2 - name: Alarm Panel - codes: - - "1234" - requires_code_to_arm: true - arming_home_time: 1s - arming_night_time: 1s - arming_away_time: 15s - pending_time: 15s - trigger_time: 30s - binary_sensors: - - input: bin1 - bypass_armed_home: true - bypass_armed_night: true - on_disarmed: - then: - - logger.log: "### DISARMED ###" - on_pending: - then: - - logger.log: "### PENDING ###" - on_arming: - then: - - logger.log: "### ARMING ###" - on_armed_home: - then: - - logger.log: "### ARMED HOME ###" - on_armed_night: - then: - - logger.log: "### ARMED NIGHT ###" - on_armed_away: - then: - - logger.log: "### ARMED AWAY ###" - on_triggered: - then: - - logger.log: "### TRIGGERED ###" - on_cleared: - then: - - logger.log: "### CLEARED ###" +<<: !include common.yaml diff --git a/tests/components/alarm_control_panel/test.rp2040.yaml b/tests/components/alarm_control_panel/test.rp2040.yaml index 218274bad4..dade44d145 100644 --- a/tests/components/alarm_control_panel/test.rp2040.yaml +++ b/tests/components/alarm_control_panel/test.rp2040.yaml @@ -1,64 +1 @@ -binary_sensor: - - platform: gpio - id: bin1 - pin: 1 - -alarm_control_panel: - - platform: template - id: alarmcontrolpanel1 - name: Alarm Panel - codes: - - "1234" - requires_code_to_arm: true - arming_home_time: 1s - arming_night_time: 1s - arming_away_time: 15s - pending_time: 15s - trigger_time: 30s - binary_sensors: - - input: bin1 - bypass_armed_home: true - bypass_armed_night: true - on_state: - then: - - lambda: !lambda |- - ESP_LOGD("TEST", "State change %s", LOG_STR_ARG(alarm_control_panel_state_to_string(id(alarmcontrolpanel1)->get_state()))); - - platform: template - id: alarmcontrolpanel2 - name: Alarm Panel - codes: - - "1234" - requires_code_to_arm: true - arming_home_time: 1s - arming_night_time: 1s - arming_away_time: 15s - pending_time: 15s - trigger_time: 30s - binary_sensors: - - input: bin1 - bypass_armed_home: true - bypass_armed_night: true - on_disarmed: - then: - - logger.log: "### DISARMED ###" - on_pending: - then: - - logger.log: "### PENDING ###" - on_arming: - then: - - logger.log: "### ARMING ###" - on_armed_home: - then: - - logger.log: "### ARMED HOME ###" - on_armed_night: - then: - - logger.log: "### ARMED NIGHT ###" - on_armed_away: - then: - - logger.log: "### ARMED AWAY ###" - on_triggered: - then: - - logger.log: "### TRIGGERED ###" - on_cleared: - then: - - logger.log: "### CLEARED ###" +<<: !include common.yaml diff --git a/tests/components/alpha3/common.yaml b/tests/components/alpha3/common.yaml new file mode 100644 index 0000000000..913f086ac4 --- /dev/null +++ b/tests/components/alpha3/common.yaml @@ -0,0 +1,17 @@ +esp32_ble_tracker: + +ble_client: + - mac_address: 01:02:03:04:05:06 + id: alpha3_blec + +sensor: + - platform: alpha3 + ble_client_id: alpha3_blec + flow: + name: "Radiator Pump Flow" + head: + name: "Radiator Pump Head" + power: + name: "Radiator Pump Power" + speed: + name: "Radiator Pump Speed" diff --git a/tests/components/alpha3/test.esp32-c3-idf.yaml b/tests/components/alpha3/test.esp32-c3-idf.yaml index 913f086ac4..dade44d145 100644 --- a/tests/components/alpha3/test.esp32-c3-idf.yaml +++ b/tests/components/alpha3/test.esp32-c3-idf.yaml @@ -1,17 +1 @@ -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: alpha3_blec - -sensor: - - platform: alpha3 - ble_client_id: alpha3_blec - flow: - name: "Radiator Pump Flow" - head: - name: "Radiator Pump Head" - power: - name: "Radiator Pump Power" - speed: - name: "Radiator Pump Speed" +<<: !include common.yaml diff --git a/tests/components/alpha3/test.esp32-c3.yaml b/tests/components/alpha3/test.esp32-c3.yaml index 913f086ac4..dade44d145 100644 --- a/tests/components/alpha3/test.esp32-c3.yaml +++ b/tests/components/alpha3/test.esp32-c3.yaml @@ -1,17 +1 @@ -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: alpha3_blec - -sensor: - - platform: alpha3 - ble_client_id: alpha3_blec - flow: - name: "Radiator Pump Flow" - head: - name: "Radiator Pump Head" - power: - name: "Radiator Pump Power" - speed: - name: "Radiator Pump Speed" +<<: !include common.yaml diff --git a/tests/components/alpha3/test.esp32-idf.yaml b/tests/components/alpha3/test.esp32-idf.yaml index 913f086ac4..dade44d145 100644 --- a/tests/components/alpha3/test.esp32-idf.yaml +++ b/tests/components/alpha3/test.esp32-idf.yaml @@ -1,17 +1 @@ -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: alpha3_blec - -sensor: - - platform: alpha3 - ble_client_id: alpha3_blec - flow: - name: "Radiator Pump Flow" - head: - name: "Radiator Pump Head" - power: - name: "Radiator Pump Power" - speed: - name: "Radiator Pump Speed" +<<: !include common.yaml diff --git a/tests/components/alpha3/test.esp32.yaml b/tests/components/alpha3/test.esp32.yaml index 913f086ac4..dade44d145 100644 --- a/tests/components/alpha3/test.esp32.yaml +++ b/tests/components/alpha3/test.esp32.yaml @@ -1,17 +1 @@ -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: alpha3_blec - -sensor: - - platform: alpha3 - ble_client_id: alpha3_blec - flow: - name: "Radiator Pump Flow" - head: - name: "Radiator Pump Head" - power: - name: "Radiator Pump Power" - speed: - name: "Radiator Pump Speed" +<<: !include common.yaml diff --git a/tests/components/am43/common.yaml b/tests/components/am43/common.yaml new file mode 100644 index 0000000000..60b7d81a55 --- /dev/null +++ b/tests/components/am43/common.yaml @@ -0,0 +1,19 @@ +esp32_ble_tracker: + +ble_client: + - mac_address: 01:02:03:04:05:06 + id: am43_blec + +cover: + - platform: am43 + name: Test AM43 Cover + id: am43_test + ble_client_id: am43_blec + +sensor: + - platform: am43 + ble_client_id: am43_blec + battery_level: + name: Kitchen blinds battery + illuminance: + name: Kitchen blinds light diff --git a/tests/components/am43/test.esp32-c3-idf.yaml b/tests/components/am43/test.esp32-c3-idf.yaml index 60b7d81a55..dade44d145 100644 --- a/tests/components/am43/test.esp32-c3-idf.yaml +++ b/tests/components/am43/test.esp32-c3-idf.yaml @@ -1,19 +1 @@ -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: am43_blec - -cover: - - platform: am43 - name: Test AM43 Cover - id: am43_test - ble_client_id: am43_blec - -sensor: - - platform: am43 - ble_client_id: am43_blec - battery_level: - name: Kitchen blinds battery - illuminance: - name: Kitchen blinds light +<<: !include common.yaml diff --git a/tests/components/am43/test.esp32-c3.yaml b/tests/components/am43/test.esp32-c3.yaml index 60b7d81a55..dade44d145 100644 --- a/tests/components/am43/test.esp32-c3.yaml +++ b/tests/components/am43/test.esp32-c3.yaml @@ -1,19 +1 @@ -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: am43_blec - -cover: - - platform: am43 - name: Test AM43 Cover - id: am43_test - ble_client_id: am43_blec - -sensor: - - platform: am43 - ble_client_id: am43_blec - battery_level: - name: Kitchen blinds battery - illuminance: - name: Kitchen blinds light +<<: !include common.yaml diff --git a/tests/components/am43/test.esp32-idf.yaml b/tests/components/am43/test.esp32-idf.yaml index 60b7d81a55..dade44d145 100644 --- a/tests/components/am43/test.esp32-idf.yaml +++ b/tests/components/am43/test.esp32-idf.yaml @@ -1,19 +1 @@ -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: am43_blec - -cover: - - platform: am43 - name: Test AM43 Cover - id: am43_test - ble_client_id: am43_blec - -sensor: - - platform: am43 - ble_client_id: am43_blec - battery_level: - name: Kitchen blinds battery - illuminance: - name: Kitchen blinds light +<<: !include common.yaml diff --git a/tests/components/am43/test.esp32.yaml b/tests/components/am43/test.esp32.yaml index 60b7d81a55..dade44d145 100644 --- a/tests/components/am43/test.esp32.yaml +++ b/tests/components/am43/test.esp32.yaml @@ -1,19 +1 @@ -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: am43_blec - -cover: - - platform: am43 - name: Test AM43 Cover - id: am43_test - ble_client_id: am43_blec - -sensor: - - platform: am43 - ble_client_id: am43_blec - battery_level: - name: Kitchen blinds battery - illuminance: - name: Kitchen blinds light +<<: !include common.yaml diff --git a/tests/components/analog_threshold/common.yaml b/tests/components/analog_threshold/common.yaml new file mode 100644 index 0000000000..b5c14dfe56 --- /dev/null +++ b/tests/components/analog_threshold/common.yaml @@ -0,0 +1,28 @@ +sensor: + - platform: template + id: template_sensor + name: Template Sensor + lambda: |- + if (millis() > 10000) { + return 42.0; + } else { + return 0.0; + } + update_interval: 15s + +binary_sensor: + - platform: analog_threshold + name: Analog Threshold 1 + sensor_id: template_sensor + threshold: + upper: 110 + lower: 90 + filters: + - delayed_on: 0s + - delayed_off: 10s + - platform: analog_threshold + name: Analog Threshold 2 + sensor_id: template_sensor + threshold: 100 + filters: + - invert: diff --git a/tests/components/analog_threshold/test.esp32-c3-idf.yaml b/tests/components/analog_threshold/test.esp32-c3-idf.yaml index b5c14dfe56..dade44d145 100644 --- a/tests/components/analog_threshold/test.esp32-c3-idf.yaml +++ b/tests/components/analog_threshold/test.esp32-c3-idf.yaml @@ -1,28 +1 @@ -sensor: - - platform: template - id: template_sensor - name: Template Sensor - lambda: |- - if (millis() > 10000) { - return 42.0; - } else { - return 0.0; - } - update_interval: 15s - -binary_sensor: - - platform: analog_threshold - name: Analog Threshold 1 - sensor_id: template_sensor - threshold: - upper: 110 - lower: 90 - filters: - - delayed_on: 0s - - delayed_off: 10s - - platform: analog_threshold - name: Analog Threshold 2 - sensor_id: template_sensor - threshold: 100 - filters: - - invert: +<<: !include common.yaml diff --git a/tests/components/analog_threshold/test.esp32-c3.yaml b/tests/components/analog_threshold/test.esp32-c3.yaml index b5c14dfe56..dade44d145 100644 --- a/tests/components/analog_threshold/test.esp32-c3.yaml +++ b/tests/components/analog_threshold/test.esp32-c3.yaml @@ -1,28 +1 @@ -sensor: - - platform: template - id: template_sensor - name: Template Sensor - lambda: |- - if (millis() > 10000) { - return 42.0; - } else { - return 0.0; - } - update_interval: 15s - -binary_sensor: - - platform: analog_threshold - name: Analog Threshold 1 - sensor_id: template_sensor - threshold: - upper: 110 - lower: 90 - filters: - - delayed_on: 0s - - delayed_off: 10s - - platform: analog_threshold - name: Analog Threshold 2 - sensor_id: template_sensor - threshold: 100 - filters: - - invert: +<<: !include common.yaml diff --git a/tests/components/analog_threshold/test.esp32-idf.yaml b/tests/components/analog_threshold/test.esp32-idf.yaml index b5c14dfe56..dade44d145 100644 --- a/tests/components/analog_threshold/test.esp32-idf.yaml +++ b/tests/components/analog_threshold/test.esp32-idf.yaml @@ -1,28 +1 @@ -sensor: - - platform: template - id: template_sensor - name: Template Sensor - lambda: |- - if (millis() > 10000) { - return 42.0; - } else { - return 0.0; - } - update_interval: 15s - -binary_sensor: - - platform: analog_threshold - name: Analog Threshold 1 - sensor_id: template_sensor - threshold: - upper: 110 - lower: 90 - filters: - - delayed_on: 0s - - delayed_off: 10s - - platform: analog_threshold - name: Analog Threshold 2 - sensor_id: template_sensor - threshold: 100 - filters: - - invert: +<<: !include common.yaml diff --git a/tests/components/analog_threshold/test.esp32.yaml b/tests/components/analog_threshold/test.esp32.yaml index b5c14dfe56..dade44d145 100644 --- a/tests/components/analog_threshold/test.esp32.yaml +++ b/tests/components/analog_threshold/test.esp32.yaml @@ -1,28 +1 @@ -sensor: - - platform: template - id: template_sensor - name: Template Sensor - lambda: |- - if (millis() > 10000) { - return 42.0; - } else { - return 0.0; - } - update_interval: 15s - -binary_sensor: - - platform: analog_threshold - name: Analog Threshold 1 - sensor_id: template_sensor - threshold: - upper: 110 - lower: 90 - filters: - - delayed_on: 0s - - delayed_off: 10s - - platform: analog_threshold - name: Analog Threshold 2 - sensor_id: template_sensor - threshold: 100 - filters: - - invert: +<<: !include common.yaml diff --git a/tests/components/analog_threshold/test.esp8266.yaml b/tests/components/analog_threshold/test.esp8266.yaml index b5c14dfe56..dade44d145 100644 --- a/tests/components/analog_threshold/test.esp8266.yaml +++ b/tests/components/analog_threshold/test.esp8266.yaml @@ -1,28 +1 @@ -sensor: - - platform: template - id: template_sensor - name: Template Sensor - lambda: |- - if (millis() > 10000) { - return 42.0; - } else { - return 0.0; - } - update_interval: 15s - -binary_sensor: - - platform: analog_threshold - name: Analog Threshold 1 - sensor_id: template_sensor - threshold: - upper: 110 - lower: 90 - filters: - - delayed_on: 0s - - delayed_off: 10s - - platform: analog_threshold - name: Analog Threshold 2 - sensor_id: template_sensor - threshold: 100 - filters: - - invert: +<<: !include common.yaml diff --git a/tests/components/analog_threshold/test.rp2040.yaml b/tests/components/analog_threshold/test.rp2040.yaml index b5c14dfe56..dade44d145 100644 --- a/tests/components/analog_threshold/test.rp2040.yaml +++ b/tests/components/analog_threshold/test.rp2040.yaml @@ -1,28 +1 @@ -sensor: - - platform: template - id: template_sensor - name: Template Sensor - lambda: |- - if (millis() > 10000) { - return 42.0; - } else { - return 0.0; - } - update_interval: 15s - -binary_sensor: - - platform: analog_threshold - name: Analog Threshold 1 - sensor_id: template_sensor - threshold: - upper: 110 - lower: 90 - filters: - - delayed_on: 0s - - delayed_off: 10s - - platform: analog_threshold - name: Analog Threshold 2 - sensor_id: template_sensor - threshold: 100 - filters: - - invert: +<<: !include common.yaml diff --git a/tests/components/anova/common.yaml b/tests/components/anova/common.yaml new file mode 100644 index 0000000000..c4162fe71e --- /dev/null +++ b/tests/components/anova/common.yaml @@ -0,0 +1,11 @@ +esp32_ble_tracker: + +ble_client: + - mac_address: 01:02:03:04:05:06 + id: anova_blec + +climate: + - platform: anova + name: Anova cooker + ble_client_id: anova_blec + unit_of_measurement: c diff --git a/tests/components/anova/test.esp32-c3-idf.yaml b/tests/components/anova/test.esp32-c3-idf.yaml index c4162fe71e..dade44d145 100644 --- a/tests/components/anova/test.esp32-c3-idf.yaml +++ b/tests/components/anova/test.esp32-c3-idf.yaml @@ -1,11 +1 @@ -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: anova_blec - -climate: - - platform: anova - name: Anova cooker - ble_client_id: anova_blec - unit_of_measurement: c +<<: !include common.yaml diff --git a/tests/components/anova/test.esp32-c3.yaml b/tests/components/anova/test.esp32-c3.yaml index c4162fe71e..dade44d145 100644 --- a/tests/components/anova/test.esp32-c3.yaml +++ b/tests/components/anova/test.esp32-c3.yaml @@ -1,11 +1 @@ -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: anova_blec - -climate: - - platform: anova - name: Anova cooker - ble_client_id: anova_blec - unit_of_measurement: c +<<: !include common.yaml diff --git a/tests/components/anova/test.esp32-idf.yaml b/tests/components/anova/test.esp32-idf.yaml index c4162fe71e..dade44d145 100644 --- a/tests/components/anova/test.esp32-idf.yaml +++ b/tests/components/anova/test.esp32-idf.yaml @@ -1,11 +1 @@ -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: anova_blec - -climate: - - platform: anova - name: Anova cooker - ble_client_id: anova_blec - unit_of_measurement: c +<<: !include common.yaml diff --git a/tests/components/anova/test.esp32.yaml b/tests/components/anova/test.esp32.yaml index c4162fe71e..dade44d145 100644 --- a/tests/components/anova/test.esp32.yaml +++ b/tests/components/anova/test.esp32.yaml @@ -1,11 +1 @@ -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: anova_blec - -climate: - - platform: anova - name: Anova cooker - ble_client_id: anova_blec - unit_of_measurement: c +<<: !include common.yaml diff --git a/tests/components/api/common.yaml b/tests/components/api/common.yaml new file mode 100644 index 0000000000..3c56811b95 --- /dev/null +++ b/tests/components/api/common.yaml @@ -0,0 +1,63 @@ +esphome: + on_boot: + then: + - homeassistant.event: + event: esphome.button_pressed + data: + message: Button was pressed + - homeassistant.service: + service: notify.html5 + data: + message: Button was pressed + - homeassistant.tag_scanned: pulse + +wifi: + ssid: MySSID + password: password1 + +api: + port: 8000 + password: pwd + reboot_timeout: 0min + encryption: + key: bOFFzzvfpg5DB94DuBGLXD/hMnhpDKgP9UQyBulwWVU= + services: + - service: hello_world + variables: + name: string + then: + - logger.log: + format: Hello World %s! + args: + - name.c_str() + - service: empty_service + then: + - logger.log: Service Called + - service: all_types + variables: + bool_: bool + int_: int + float_: float + string_: string + then: + - logger.log: Something happened + - service: array_types + variables: + bool_arr: bool[] + int_arr: int[] + float_arr: float[] + string_arr: string[] + then: + - logger.log: + # yamllint disable rule:line-length + format: "Bool: %s (%u), Int: %d (%u), Float: %f (%u), String: %s (%u)" + # yamllint enable rule:line-length + args: + - YESNO(bool_arr[0]) + - bool_arr.size() + - int_arr[0] + - int_arr.size() + - float_arr[0] + - float_arr.size() + - string_arr[0].c_str() + - string_arr.size() diff --git a/tests/components/api/test.esp32-c3-idf.yaml b/tests/components/api/test.esp32-c3-idf.yaml index 3c56811b95..dade44d145 100644 --- a/tests/components/api/test.esp32-c3-idf.yaml +++ b/tests/components/api/test.esp32-c3-idf.yaml @@ -1,63 +1 @@ -esphome: - on_boot: - then: - - homeassistant.event: - event: esphome.button_pressed - data: - message: Button was pressed - - homeassistant.service: - service: notify.html5 - data: - message: Button was pressed - - homeassistant.tag_scanned: pulse - -wifi: - ssid: MySSID - password: password1 - -api: - port: 8000 - password: pwd - reboot_timeout: 0min - encryption: - key: bOFFzzvfpg5DB94DuBGLXD/hMnhpDKgP9UQyBulwWVU= - services: - - service: hello_world - variables: - name: string - then: - - logger.log: - format: Hello World %s! - args: - - name.c_str() - - service: empty_service - then: - - logger.log: Service Called - - service: all_types - variables: - bool_: bool - int_: int - float_: float - string_: string - then: - - logger.log: Something happened - - service: array_types - variables: - bool_arr: bool[] - int_arr: int[] - float_arr: float[] - string_arr: string[] - then: - - logger.log: - # yamllint disable rule:line-length - format: "Bool: %s (%u), Int: %d (%u), Float: %f (%u), String: %s (%u)" - # yamllint enable rule:line-length - args: - - YESNO(bool_arr[0]) - - bool_arr.size() - - int_arr[0] - - int_arr.size() - - float_arr[0] - - float_arr.size() - - string_arr[0].c_str() - - string_arr.size() +<<: !include common.yaml diff --git a/tests/components/api/test.esp32-c3.yaml b/tests/components/api/test.esp32-c3.yaml index 3c56811b95..dade44d145 100644 --- a/tests/components/api/test.esp32-c3.yaml +++ b/tests/components/api/test.esp32-c3.yaml @@ -1,63 +1 @@ -esphome: - on_boot: - then: - - homeassistant.event: - event: esphome.button_pressed - data: - message: Button was pressed - - homeassistant.service: - service: notify.html5 - data: - message: Button was pressed - - homeassistant.tag_scanned: pulse - -wifi: - ssid: MySSID - password: password1 - -api: - port: 8000 - password: pwd - reboot_timeout: 0min - encryption: - key: bOFFzzvfpg5DB94DuBGLXD/hMnhpDKgP9UQyBulwWVU= - services: - - service: hello_world - variables: - name: string - then: - - logger.log: - format: Hello World %s! - args: - - name.c_str() - - service: empty_service - then: - - logger.log: Service Called - - service: all_types - variables: - bool_: bool - int_: int - float_: float - string_: string - then: - - logger.log: Something happened - - service: array_types - variables: - bool_arr: bool[] - int_arr: int[] - float_arr: float[] - string_arr: string[] - then: - - logger.log: - # yamllint disable rule:line-length - format: "Bool: %s (%u), Int: %d (%u), Float: %f (%u), String: %s (%u)" - # yamllint enable rule:line-length - args: - - YESNO(bool_arr[0]) - - bool_arr.size() - - int_arr[0] - - int_arr.size() - - float_arr[0] - - float_arr.size() - - string_arr[0].c_str() - - string_arr.size() +<<: !include common.yaml diff --git a/tests/components/api/test.esp32-idf.yaml b/tests/components/api/test.esp32-idf.yaml index 3c56811b95..dade44d145 100644 --- a/tests/components/api/test.esp32-idf.yaml +++ b/tests/components/api/test.esp32-idf.yaml @@ -1,63 +1 @@ -esphome: - on_boot: - then: - - homeassistant.event: - event: esphome.button_pressed - data: - message: Button was pressed - - homeassistant.service: - service: notify.html5 - data: - message: Button was pressed - - homeassistant.tag_scanned: pulse - -wifi: - ssid: MySSID - password: password1 - -api: - port: 8000 - password: pwd - reboot_timeout: 0min - encryption: - key: bOFFzzvfpg5DB94DuBGLXD/hMnhpDKgP9UQyBulwWVU= - services: - - service: hello_world - variables: - name: string - then: - - logger.log: - format: Hello World %s! - args: - - name.c_str() - - service: empty_service - then: - - logger.log: Service Called - - service: all_types - variables: - bool_: bool - int_: int - float_: float - string_: string - then: - - logger.log: Something happened - - service: array_types - variables: - bool_arr: bool[] - int_arr: int[] - float_arr: float[] - string_arr: string[] - then: - - logger.log: - # yamllint disable rule:line-length - format: "Bool: %s (%u), Int: %d (%u), Float: %f (%u), String: %s (%u)" - # yamllint enable rule:line-length - args: - - YESNO(bool_arr[0]) - - bool_arr.size() - - int_arr[0] - - int_arr.size() - - float_arr[0] - - float_arr.size() - - string_arr[0].c_str() - - string_arr.size() +<<: !include common.yaml diff --git a/tests/components/api/test.esp32.yaml b/tests/components/api/test.esp32.yaml index 3c56811b95..dade44d145 100644 --- a/tests/components/api/test.esp32.yaml +++ b/tests/components/api/test.esp32.yaml @@ -1,63 +1 @@ -esphome: - on_boot: - then: - - homeassistant.event: - event: esphome.button_pressed - data: - message: Button was pressed - - homeassistant.service: - service: notify.html5 - data: - message: Button was pressed - - homeassistant.tag_scanned: pulse - -wifi: - ssid: MySSID - password: password1 - -api: - port: 8000 - password: pwd - reboot_timeout: 0min - encryption: - key: bOFFzzvfpg5DB94DuBGLXD/hMnhpDKgP9UQyBulwWVU= - services: - - service: hello_world - variables: - name: string - then: - - logger.log: - format: Hello World %s! - args: - - name.c_str() - - service: empty_service - then: - - logger.log: Service Called - - service: all_types - variables: - bool_: bool - int_: int - float_: float - string_: string - then: - - logger.log: Something happened - - service: array_types - variables: - bool_arr: bool[] - int_arr: int[] - float_arr: float[] - string_arr: string[] - then: - - logger.log: - # yamllint disable rule:line-length - format: "Bool: %s (%u), Int: %d (%u), Float: %f (%u), String: %s (%u)" - # yamllint enable rule:line-length - args: - - YESNO(bool_arr[0]) - - bool_arr.size() - - int_arr[0] - - int_arr.size() - - float_arr[0] - - float_arr.size() - - string_arr[0].c_str() - - string_arr.size() +<<: !include common.yaml diff --git a/tests/components/api/test.esp8266.yaml b/tests/components/api/test.esp8266.yaml index 3c56811b95..dade44d145 100644 --- a/tests/components/api/test.esp8266.yaml +++ b/tests/components/api/test.esp8266.yaml @@ -1,63 +1 @@ -esphome: - on_boot: - then: - - homeassistant.event: - event: esphome.button_pressed - data: - message: Button was pressed - - homeassistant.service: - service: notify.html5 - data: - message: Button was pressed - - homeassistant.tag_scanned: pulse - -wifi: - ssid: MySSID - password: password1 - -api: - port: 8000 - password: pwd - reboot_timeout: 0min - encryption: - key: bOFFzzvfpg5DB94DuBGLXD/hMnhpDKgP9UQyBulwWVU= - services: - - service: hello_world - variables: - name: string - then: - - logger.log: - format: Hello World %s! - args: - - name.c_str() - - service: empty_service - then: - - logger.log: Service Called - - service: all_types - variables: - bool_: bool - int_: int - float_: float - string_: string - then: - - logger.log: Something happened - - service: array_types - variables: - bool_arr: bool[] - int_arr: int[] - float_arr: float[] - string_arr: string[] - then: - - logger.log: - # yamllint disable rule:line-length - format: "Bool: %s (%u), Int: %d (%u), Float: %f (%u), String: %s (%u)" - # yamllint enable rule:line-length - args: - - YESNO(bool_arr[0]) - - bool_arr.size() - - int_arr[0] - - int_arr.size() - - float_arr[0] - - float_arr.size() - - string_arr[0].c_str() - - string_arr.size() +<<: !include common.yaml diff --git a/tests/components/api/test.rp2040.yaml b/tests/components/api/test.rp2040.yaml index 3c56811b95..dade44d145 100644 --- a/tests/components/api/test.rp2040.yaml +++ b/tests/components/api/test.rp2040.yaml @@ -1,63 +1 @@ -esphome: - on_boot: - then: - - homeassistant.event: - event: esphome.button_pressed - data: - message: Button was pressed - - homeassistant.service: - service: notify.html5 - data: - message: Button was pressed - - homeassistant.tag_scanned: pulse - -wifi: - ssid: MySSID - password: password1 - -api: - port: 8000 - password: pwd - reboot_timeout: 0min - encryption: - key: bOFFzzvfpg5DB94DuBGLXD/hMnhpDKgP9UQyBulwWVU= - services: - - service: hello_world - variables: - name: string - then: - - logger.log: - format: Hello World %s! - args: - - name.c_str() - - service: empty_service - then: - - logger.log: Service Called - - service: all_types - variables: - bool_: bool - int_: int - float_: float - string_: string - then: - - logger.log: Something happened - - service: array_types - variables: - bool_arr: bool[] - int_arr: int[] - float_arr: float[] - string_arr: string[] - then: - - logger.log: - # yamllint disable rule:line-length - format: "Bool: %s (%u), Int: %d (%u), Float: %f (%u), String: %s (%u)" - # yamllint enable rule:line-length - args: - - YESNO(bool_arr[0]) - - bool_arr.size() - - int_arr[0] - - int_arr.size() - - float_arr[0] - - float_arr.size() - - string_arr[0].c_str() - - string_arr.size() +<<: !include common.yaml diff --git a/tests/components/atc_mithermometer/common.yaml b/tests/components/atc_mithermometer/common.yaml new file mode 100644 index 0000000000..0248090c23 --- /dev/null +++ b/tests/components/atc_mithermometer/common.yaml @@ -0,0 +1,13 @@ +esp32_ble_tracker: + +sensor: + - platform: atc_mithermometer + mac_address: A4:C1:38:4E:16:78 + temperature: + name: ATC Temperature + humidity: + name: ATC Humidity + battery_level: + name: ATC Battery-Level + battery_voltage: + name: ATC Battery-Voltage diff --git a/tests/components/atc_mithermometer/test.esp32-c3-idf.yaml b/tests/components/atc_mithermometer/test.esp32-c3-idf.yaml index 0248090c23..dade44d145 100644 --- a/tests/components/atc_mithermometer/test.esp32-c3-idf.yaml +++ b/tests/components/atc_mithermometer/test.esp32-c3-idf.yaml @@ -1,13 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: atc_mithermometer - mac_address: A4:C1:38:4E:16:78 - temperature: - name: ATC Temperature - humidity: - name: ATC Humidity - battery_level: - name: ATC Battery-Level - battery_voltage: - name: ATC Battery-Voltage +<<: !include common.yaml diff --git a/tests/components/atc_mithermometer/test.esp32-c3.yaml b/tests/components/atc_mithermometer/test.esp32-c3.yaml index 0248090c23..dade44d145 100644 --- a/tests/components/atc_mithermometer/test.esp32-c3.yaml +++ b/tests/components/atc_mithermometer/test.esp32-c3.yaml @@ -1,13 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: atc_mithermometer - mac_address: A4:C1:38:4E:16:78 - temperature: - name: ATC Temperature - humidity: - name: ATC Humidity - battery_level: - name: ATC Battery-Level - battery_voltage: - name: ATC Battery-Voltage +<<: !include common.yaml diff --git a/tests/components/atc_mithermometer/test.esp32-idf.yaml b/tests/components/atc_mithermometer/test.esp32-idf.yaml index 0248090c23..dade44d145 100644 --- a/tests/components/atc_mithermometer/test.esp32-idf.yaml +++ b/tests/components/atc_mithermometer/test.esp32-idf.yaml @@ -1,13 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: atc_mithermometer - mac_address: A4:C1:38:4E:16:78 - temperature: - name: ATC Temperature - humidity: - name: ATC Humidity - battery_level: - name: ATC Battery-Level - battery_voltage: - name: ATC Battery-Voltage +<<: !include common.yaml diff --git a/tests/components/atc_mithermometer/test.esp32.yaml b/tests/components/atc_mithermometer/test.esp32.yaml index 0248090c23..dade44d145 100644 --- a/tests/components/atc_mithermometer/test.esp32.yaml +++ b/tests/components/atc_mithermometer/test.esp32.yaml @@ -1,13 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: atc_mithermometer - mac_address: A4:C1:38:4E:16:78 - temperature: - name: ATC Temperature - humidity: - name: ATC Humidity - battery_level: - name: ATC Battery-Level - battery_voltage: - name: ATC Battery-Voltage +<<: !include common.yaml diff --git a/tests/components/b_parasite/common.yaml b/tests/components/b_parasite/common.yaml new file mode 100644 index 0000000000..262e891bb2 --- /dev/null +++ b/tests/components/b_parasite/common.yaml @@ -0,0 +1,15 @@ +esp32_ble_tracker: + +sensor: + - platform: b_parasite + mac_address: F0:CA:F0:CA:01:01 + humidity: + name: b-parasite Air Humidity + temperature: + name: b-parasite Air Temperature + moisture: + name: b-parasite Soil Moisture + battery_voltage: + name: b-parasite Battery Voltage + illuminance: + name: b-parasite Illuminance diff --git a/tests/components/b_parasite/test.esp32-c3-idf.yaml b/tests/components/b_parasite/test.esp32-c3-idf.yaml index 262e891bb2..dade44d145 100644 --- a/tests/components/b_parasite/test.esp32-c3-idf.yaml +++ b/tests/components/b_parasite/test.esp32-c3-idf.yaml @@ -1,15 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: b_parasite - mac_address: F0:CA:F0:CA:01:01 - humidity: - name: b-parasite Air Humidity - temperature: - name: b-parasite Air Temperature - moisture: - name: b-parasite Soil Moisture - battery_voltage: - name: b-parasite Battery Voltage - illuminance: - name: b-parasite Illuminance +<<: !include common.yaml diff --git a/tests/components/b_parasite/test.esp32-c3.yaml b/tests/components/b_parasite/test.esp32-c3.yaml index 262e891bb2..dade44d145 100644 --- a/tests/components/b_parasite/test.esp32-c3.yaml +++ b/tests/components/b_parasite/test.esp32-c3.yaml @@ -1,15 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: b_parasite - mac_address: F0:CA:F0:CA:01:01 - humidity: - name: b-parasite Air Humidity - temperature: - name: b-parasite Air Temperature - moisture: - name: b-parasite Soil Moisture - battery_voltage: - name: b-parasite Battery Voltage - illuminance: - name: b-parasite Illuminance +<<: !include common.yaml diff --git a/tests/components/b_parasite/test.esp32-idf.yaml b/tests/components/b_parasite/test.esp32-idf.yaml index 262e891bb2..dade44d145 100644 --- a/tests/components/b_parasite/test.esp32-idf.yaml +++ b/tests/components/b_parasite/test.esp32-idf.yaml @@ -1,15 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: b_parasite - mac_address: F0:CA:F0:CA:01:01 - humidity: - name: b-parasite Air Humidity - temperature: - name: b-parasite Air Temperature - moisture: - name: b-parasite Soil Moisture - battery_voltage: - name: b-parasite Battery Voltage - illuminance: - name: b-parasite Illuminance +<<: !include common.yaml diff --git a/tests/components/b_parasite/test.esp32.yaml b/tests/components/b_parasite/test.esp32.yaml index 262e891bb2..dade44d145 100644 --- a/tests/components/b_parasite/test.esp32.yaml +++ b/tests/components/b_parasite/test.esp32.yaml @@ -1,15 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: b_parasite - mac_address: F0:CA:F0:CA:01:01 - humidity: - name: b-parasite Air Humidity - temperature: - name: b-parasite Air Temperature - moisture: - name: b-parasite Soil Moisture - battery_voltage: - name: b-parasite Battery Voltage - illuminance: - name: b-parasite Illuminance +<<: !include common.yaml diff --git a/tests/components/bang_bang/common.yaml b/tests/components/bang_bang/common.yaml new file mode 100644 index 0000000000..5882025191 --- /dev/null +++ b/tests/components/bang_bang/common.yaml @@ -0,0 +1,35 @@ +switch: + - platform: template + id: template_switch1 + optimistic: true + - platform: template + id: template_switch2 + optimistic: true + +sensor: + - platform: template + id: template_sensor1 + lambda: |- + if (millis() > 10000) { + return 42.0; + } else { + return 0.0; + } + update_interval: 60s + +climate: + - platform: bang_bang + name: Bang Bang Climate + sensor: template_sensor1 + humidity_sensor: template_sensor1 + default_target_temperature_low: 18°C + default_target_temperature_high: 24°C + idle_action: + - switch.turn_on: template_switch1 + cool_action: + - switch.turn_on: template_switch2 + heat_action: + - switch.turn_on: template_switch1 + away_config: + default_target_temperature_low: 16°C + default_target_temperature_high: 20°C diff --git a/tests/components/bang_bang/test.esp32-c3-idf.yaml b/tests/components/bang_bang/test.esp32-c3-idf.yaml index 5882025191..dade44d145 100644 --- a/tests/components/bang_bang/test.esp32-c3-idf.yaml +++ b/tests/components/bang_bang/test.esp32-c3-idf.yaml @@ -1,35 +1 @@ -switch: - - platform: template - id: template_switch1 - optimistic: true - - platform: template - id: template_switch2 - optimistic: true - -sensor: - - platform: template - id: template_sensor1 - lambda: |- - if (millis() > 10000) { - return 42.0; - } else { - return 0.0; - } - update_interval: 60s - -climate: - - platform: bang_bang - name: Bang Bang Climate - sensor: template_sensor1 - humidity_sensor: template_sensor1 - default_target_temperature_low: 18°C - default_target_temperature_high: 24°C - idle_action: - - switch.turn_on: template_switch1 - cool_action: - - switch.turn_on: template_switch2 - heat_action: - - switch.turn_on: template_switch1 - away_config: - default_target_temperature_low: 16°C - default_target_temperature_high: 20°C +<<: !include common.yaml diff --git a/tests/components/bang_bang/test.esp32-c3.yaml b/tests/components/bang_bang/test.esp32-c3.yaml index 5882025191..dade44d145 100644 --- a/tests/components/bang_bang/test.esp32-c3.yaml +++ b/tests/components/bang_bang/test.esp32-c3.yaml @@ -1,35 +1 @@ -switch: - - platform: template - id: template_switch1 - optimistic: true - - platform: template - id: template_switch2 - optimistic: true - -sensor: - - platform: template - id: template_sensor1 - lambda: |- - if (millis() > 10000) { - return 42.0; - } else { - return 0.0; - } - update_interval: 60s - -climate: - - platform: bang_bang - name: Bang Bang Climate - sensor: template_sensor1 - humidity_sensor: template_sensor1 - default_target_temperature_low: 18°C - default_target_temperature_high: 24°C - idle_action: - - switch.turn_on: template_switch1 - cool_action: - - switch.turn_on: template_switch2 - heat_action: - - switch.turn_on: template_switch1 - away_config: - default_target_temperature_low: 16°C - default_target_temperature_high: 20°C +<<: !include common.yaml diff --git a/tests/components/bang_bang/test.esp32-idf.yaml b/tests/components/bang_bang/test.esp32-idf.yaml index 5882025191..dade44d145 100644 --- a/tests/components/bang_bang/test.esp32-idf.yaml +++ b/tests/components/bang_bang/test.esp32-idf.yaml @@ -1,35 +1 @@ -switch: - - platform: template - id: template_switch1 - optimistic: true - - platform: template - id: template_switch2 - optimistic: true - -sensor: - - platform: template - id: template_sensor1 - lambda: |- - if (millis() > 10000) { - return 42.0; - } else { - return 0.0; - } - update_interval: 60s - -climate: - - platform: bang_bang - name: Bang Bang Climate - sensor: template_sensor1 - humidity_sensor: template_sensor1 - default_target_temperature_low: 18°C - default_target_temperature_high: 24°C - idle_action: - - switch.turn_on: template_switch1 - cool_action: - - switch.turn_on: template_switch2 - heat_action: - - switch.turn_on: template_switch1 - away_config: - default_target_temperature_low: 16°C - default_target_temperature_high: 20°C +<<: !include common.yaml diff --git a/tests/components/bang_bang/test.esp32.yaml b/tests/components/bang_bang/test.esp32.yaml index 5882025191..dade44d145 100644 --- a/tests/components/bang_bang/test.esp32.yaml +++ b/tests/components/bang_bang/test.esp32.yaml @@ -1,35 +1 @@ -switch: - - platform: template - id: template_switch1 - optimistic: true - - platform: template - id: template_switch2 - optimistic: true - -sensor: - - platform: template - id: template_sensor1 - lambda: |- - if (millis() > 10000) { - return 42.0; - } else { - return 0.0; - } - update_interval: 60s - -climate: - - platform: bang_bang - name: Bang Bang Climate - sensor: template_sensor1 - humidity_sensor: template_sensor1 - default_target_temperature_low: 18°C - default_target_temperature_high: 24°C - idle_action: - - switch.turn_on: template_switch1 - cool_action: - - switch.turn_on: template_switch2 - heat_action: - - switch.turn_on: template_switch1 - away_config: - default_target_temperature_low: 16°C - default_target_temperature_high: 20°C +<<: !include common.yaml diff --git a/tests/components/bang_bang/test.esp8266.yaml b/tests/components/bang_bang/test.esp8266.yaml index 5882025191..dade44d145 100644 --- a/tests/components/bang_bang/test.esp8266.yaml +++ b/tests/components/bang_bang/test.esp8266.yaml @@ -1,35 +1 @@ -switch: - - platform: template - id: template_switch1 - optimistic: true - - platform: template - id: template_switch2 - optimistic: true - -sensor: - - platform: template - id: template_sensor1 - lambda: |- - if (millis() > 10000) { - return 42.0; - } else { - return 0.0; - } - update_interval: 60s - -climate: - - platform: bang_bang - name: Bang Bang Climate - sensor: template_sensor1 - humidity_sensor: template_sensor1 - default_target_temperature_low: 18°C - default_target_temperature_high: 24°C - idle_action: - - switch.turn_on: template_switch1 - cool_action: - - switch.turn_on: template_switch2 - heat_action: - - switch.turn_on: template_switch1 - away_config: - default_target_temperature_low: 16°C - default_target_temperature_high: 20°C +<<: !include common.yaml diff --git a/tests/components/bang_bang/test.rp2040.yaml b/tests/components/bang_bang/test.rp2040.yaml index 5882025191..dade44d145 100644 --- a/tests/components/bang_bang/test.rp2040.yaml +++ b/tests/components/bang_bang/test.rp2040.yaml @@ -1,35 +1 @@ -switch: - - platform: template - id: template_switch1 - optimistic: true - - platform: template - id: template_switch2 - optimistic: true - -sensor: - - platform: template - id: template_sensor1 - lambda: |- - if (millis() > 10000) { - return 42.0; - } else { - return 0.0; - } - update_interval: 60s - -climate: - - platform: bang_bang - name: Bang Bang Climate - sensor: template_sensor1 - humidity_sensor: template_sensor1 - default_target_temperature_low: 18°C - default_target_temperature_high: 24°C - idle_action: - - switch.turn_on: template_switch1 - cool_action: - - switch.turn_on: template_switch2 - heat_action: - - switch.turn_on: template_switch1 - away_config: - default_target_temperature_low: 16°C - default_target_temperature_high: 20°C +<<: !include common.yaml diff --git a/tests/components/bedjet/common.yaml b/tests/components/bedjet/common.yaml new file mode 100644 index 0000000000..c2be04a49a --- /dev/null +++ b/tests/components/bedjet/common.yaml @@ -0,0 +1,33 @@ +wifi: + ssid: MySSID + password: password1 + +time: + - platform: sntp + id: sntp_time + servers: + - 0.pool.ntp.org + - 1.pool.ntp.org + - 192.168.178.1 + +esp32_ble_tracker: + +ble_client: + - mac_address: 01:02:03:04:05:06 + id: bedjet_blec + +bedjet: + - id: bedjet_hub + ble_client_id: bedjet_blec + time_id: sntp_time + +climate: + - platform: bedjet + name: My Bedjet + bedjet_id: bedjet_hub + heat_mode: extended + +fan: + - platform: bedjet + name: My Bedjet fan + bedjet_id: bedjet_hub diff --git a/tests/components/bedjet/test.esp32-c3-idf.yaml b/tests/components/bedjet/test.esp32-c3-idf.yaml index c2be04a49a..dade44d145 100644 --- a/tests/components/bedjet/test.esp32-c3-idf.yaml +++ b/tests/components/bedjet/test.esp32-c3-idf.yaml @@ -1,33 +1 @@ -wifi: - ssid: MySSID - password: password1 - -time: - - platform: sntp - id: sntp_time - servers: - - 0.pool.ntp.org - - 1.pool.ntp.org - - 192.168.178.1 - -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: bedjet_blec - -bedjet: - - id: bedjet_hub - ble_client_id: bedjet_blec - time_id: sntp_time - -climate: - - platform: bedjet - name: My Bedjet - bedjet_id: bedjet_hub - heat_mode: extended - -fan: - - platform: bedjet - name: My Bedjet fan - bedjet_id: bedjet_hub +<<: !include common.yaml diff --git a/tests/components/bedjet/test.esp32-c3.yaml b/tests/components/bedjet/test.esp32-c3.yaml index c2be04a49a..dade44d145 100644 --- a/tests/components/bedjet/test.esp32-c3.yaml +++ b/tests/components/bedjet/test.esp32-c3.yaml @@ -1,33 +1 @@ -wifi: - ssid: MySSID - password: password1 - -time: - - platform: sntp - id: sntp_time - servers: - - 0.pool.ntp.org - - 1.pool.ntp.org - - 192.168.178.1 - -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: bedjet_blec - -bedjet: - - id: bedjet_hub - ble_client_id: bedjet_blec - time_id: sntp_time - -climate: - - platform: bedjet - name: My Bedjet - bedjet_id: bedjet_hub - heat_mode: extended - -fan: - - platform: bedjet - name: My Bedjet fan - bedjet_id: bedjet_hub +<<: !include common.yaml diff --git a/tests/components/bedjet/test.esp32-idf.yaml b/tests/components/bedjet/test.esp32-idf.yaml index c2be04a49a..dade44d145 100644 --- a/tests/components/bedjet/test.esp32-idf.yaml +++ b/tests/components/bedjet/test.esp32-idf.yaml @@ -1,33 +1 @@ -wifi: - ssid: MySSID - password: password1 - -time: - - platform: sntp - id: sntp_time - servers: - - 0.pool.ntp.org - - 1.pool.ntp.org - - 192.168.178.1 - -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: bedjet_blec - -bedjet: - - id: bedjet_hub - ble_client_id: bedjet_blec - time_id: sntp_time - -climate: - - platform: bedjet - name: My Bedjet - bedjet_id: bedjet_hub - heat_mode: extended - -fan: - - platform: bedjet - name: My Bedjet fan - bedjet_id: bedjet_hub +<<: !include common.yaml diff --git a/tests/components/bedjet/test.esp32.yaml b/tests/components/bedjet/test.esp32.yaml index c2be04a49a..dade44d145 100644 --- a/tests/components/bedjet/test.esp32.yaml +++ b/tests/components/bedjet/test.esp32.yaml @@ -1,33 +1 @@ -wifi: - ssid: MySSID - password: password1 - -time: - - platform: sntp - id: sntp_time - servers: - - 0.pool.ntp.org - - 1.pool.ntp.org - - 192.168.178.1 - -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: bedjet_blec - -bedjet: - - id: bedjet_hub - ble_client_id: bedjet_blec - time_id: sntp_time - -climate: - - platform: bedjet - name: My Bedjet - bedjet_id: bedjet_hub - heat_mode: extended - -fan: - - platform: bedjet - name: My Bedjet fan - bedjet_id: bedjet_hub +<<: !include common.yaml diff --git a/tests/components/binary_sensor_map/common.yaml b/tests/components/binary_sensor_map/common.yaml new file mode 100644 index 0000000000..8ffdd1f379 --- /dev/null +++ b/tests/components/binary_sensor_map/common.yaml @@ -0,0 +1,61 @@ +binary_sensor: + - platform: template + id: bin1 + lambda: |- + if (millis() > 10000) { + return true; + } else { + return false; + } + - platform: template + id: bin2 + lambda: |- + if (millis() > 20000) { + return true; + } else { + return false; + } + - platform: template + id: bin3 + lambda: |- + if (millis() > 30000) { + return true; + } else { + return false; + } + +sensor: + - platform: binary_sensor_map + name: Binary Sensor Map + type: group + channels: + - binary_sensor: bin1 + value: 10.0 + - binary_sensor: bin2 + value: 15.0 + - binary_sensor: bin3 + value: 100.0 + - platform: binary_sensor_map + name: Binary Sensor Map + type: sum + channels: + - binary_sensor: bin1 + value: 10.0 + - binary_sensor: bin2 + value: 15.0 + - binary_sensor: bin3 + value: 100.0 + - platform: binary_sensor_map + name: Binary Sensor Map + type: bayesian + prior: 0.4 + observations: + - binary_sensor: bin1 + prob_given_true: 0.9 + prob_given_false: 0.4 + - binary_sensor: bin2 + prob_given_true: 0.7 + prob_given_false: 0.05 + - binary_sensor: bin3 + prob_given_true: 0.8 + prob_given_false: 0.2 diff --git a/tests/components/binary_sensor_map/test.esp32-c3-idf.yaml b/tests/components/binary_sensor_map/test.esp32-c3-idf.yaml index 8ffdd1f379..dade44d145 100644 --- a/tests/components/binary_sensor_map/test.esp32-c3-idf.yaml +++ b/tests/components/binary_sensor_map/test.esp32-c3-idf.yaml @@ -1,61 +1 @@ -binary_sensor: - - platform: template - id: bin1 - lambda: |- - if (millis() > 10000) { - return true; - } else { - return false; - } - - platform: template - id: bin2 - lambda: |- - if (millis() > 20000) { - return true; - } else { - return false; - } - - platform: template - id: bin3 - lambda: |- - if (millis() > 30000) { - return true; - } else { - return false; - } - -sensor: - - platform: binary_sensor_map - name: Binary Sensor Map - type: group - channels: - - binary_sensor: bin1 - value: 10.0 - - binary_sensor: bin2 - value: 15.0 - - binary_sensor: bin3 - value: 100.0 - - platform: binary_sensor_map - name: Binary Sensor Map - type: sum - channels: - - binary_sensor: bin1 - value: 10.0 - - binary_sensor: bin2 - value: 15.0 - - binary_sensor: bin3 - value: 100.0 - - platform: binary_sensor_map - name: Binary Sensor Map - type: bayesian - prior: 0.4 - observations: - - binary_sensor: bin1 - prob_given_true: 0.9 - prob_given_false: 0.4 - - binary_sensor: bin2 - prob_given_true: 0.7 - prob_given_false: 0.05 - - binary_sensor: bin3 - prob_given_true: 0.8 - prob_given_false: 0.2 +<<: !include common.yaml diff --git a/tests/components/binary_sensor_map/test.esp32-c3.yaml b/tests/components/binary_sensor_map/test.esp32-c3.yaml index 8ffdd1f379..dade44d145 100644 --- a/tests/components/binary_sensor_map/test.esp32-c3.yaml +++ b/tests/components/binary_sensor_map/test.esp32-c3.yaml @@ -1,61 +1 @@ -binary_sensor: - - platform: template - id: bin1 - lambda: |- - if (millis() > 10000) { - return true; - } else { - return false; - } - - platform: template - id: bin2 - lambda: |- - if (millis() > 20000) { - return true; - } else { - return false; - } - - platform: template - id: bin3 - lambda: |- - if (millis() > 30000) { - return true; - } else { - return false; - } - -sensor: - - platform: binary_sensor_map - name: Binary Sensor Map - type: group - channels: - - binary_sensor: bin1 - value: 10.0 - - binary_sensor: bin2 - value: 15.0 - - binary_sensor: bin3 - value: 100.0 - - platform: binary_sensor_map - name: Binary Sensor Map - type: sum - channels: - - binary_sensor: bin1 - value: 10.0 - - binary_sensor: bin2 - value: 15.0 - - binary_sensor: bin3 - value: 100.0 - - platform: binary_sensor_map - name: Binary Sensor Map - type: bayesian - prior: 0.4 - observations: - - binary_sensor: bin1 - prob_given_true: 0.9 - prob_given_false: 0.4 - - binary_sensor: bin2 - prob_given_true: 0.7 - prob_given_false: 0.05 - - binary_sensor: bin3 - prob_given_true: 0.8 - prob_given_false: 0.2 +<<: !include common.yaml diff --git a/tests/components/binary_sensor_map/test.esp32-idf.yaml b/tests/components/binary_sensor_map/test.esp32-idf.yaml index 8ffdd1f379..dade44d145 100644 --- a/tests/components/binary_sensor_map/test.esp32-idf.yaml +++ b/tests/components/binary_sensor_map/test.esp32-idf.yaml @@ -1,61 +1 @@ -binary_sensor: - - platform: template - id: bin1 - lambda: |- - if (millis() > 10000) { - return true; - } else { - return false; - } - - platform: template - id: bin2 - lambda: |- - if (millis() > 20000) { - return true; - } else { - return false; - } - - platform: template - id: bin3 - lambda: |- - if (millis() > 30000) { - return true; - } else { - return false; - } - -sensor: - - platform: binary_sensor_map - name: Binary Sensor Map - type: group - channels: - - binary_sensor: bin1 - value: 10.0 - - binary_sensor: bin2 - value: 15.0 - - binary_sensor: bin3 - value: 100.0 - - platform: binary_sensor_map - name: Binary Sensor Map - type: sum - channels: - - binary_sensor: bin1 - value: 10.0 - - binary_sensor: bin2 - value: 15.0 - - binary_sensor: bin3 - value: 100.0 - - platform: binary_sensor_map - name: Binary Sensor Map - type: bayesian - prior: 0.4 - observations: - - binary_sensor: bin1 - prob_given_true: 0.9 - prob_given_false: 0.4 - - binary_sensor: bin2 - prob_given_true: 0.7 - prob_given_false: 0.05 - - binary_sensor: bin3 - prob_given_true: 0.8 - prob_given_false: 0.2 +<<: !include common.yaml diff --git a/tests/components/binary_sensor_map/test.esp32.yaml b/tests/components/binary_sensor_map/test.esp32.yaml index 8ffdd1f379..dade44d145 100644 --- a/tests/components/binary_sensor_map/test.esp32.yaml +++ b/tests/components/binary_sensor_map/test.esp32.yaml @@ -1,61 +1 @@ -binary_sensor: - - platform: template - id: bin1 - lambda: |- - if (millis() > 10000) { - return true; - } else { - return false; - } - - platform: template - id: bin2 - lambda: |- - if (millis() > 20000) { - return true; - } else { - return false; - } - - platform: template - id: bin3 - lambda: |- - if (millis() > 30000) { - return true; - } else { - return false; - } - -sensor: - - platform: binary_sensor_map - name: Binary Sensor Map - type: group - channels: - - binary_sensor: bin1 - value: 10.0 - - binary_sensor: bin2 - value: 15.0 - - binary_sensor: bin3 - value: 100.0 - - platform: binary_sensor_map - name: Binary Sensor Map - type: sum - channels: - - binary_sensor: bin1 - value: 10.0 - - binary_sensor: bin2 - value: 15.0 - - binary_sensor: bin3 - value: 100.0 - - platform: binary_sensor_map - name: Binary Sensor Map - type: bayesian - prior: 0.4 - observations: - - binary_sensor: bin1 - prob_given_true: 0.9 - prob_given_false: 0.4 - - binary_sensor: bin2 - prob_given_true: 0.7 - prob_given_false: 0.05 - - binary_sensor: bin3 - prob_given_true: 0.8 - prob_given_false: 0.2 +<<: !include common.yaml diff --git a/tests/components/binary_sensor_map/test.esp8266.yaml b/tests/components/binary_sensor_map/test.esp8266.yaml index 8ffdd1f379..dade44d145 100644 --- a/tests/components/binary_sensor_map/test.esp8266.yaml +++ b/tests/components/binary_sensor_map/test.esp8266.yaml @@ -1,61 +1 @@ -binary_sensor: - - platform: template - id: bin1 - lambda: |- - if (millis() > 10000) { - return true; - } else { - return false; - } - - platform: template - id: bin2 - lambda: |- - if (millis() > 20000) { - return true; - } else { - return false; - } - - platform: template - id: bin3 - lambda: |- - if (millis() > 30000) { - return true; - } else { - return false; - } - -sensor: - - platform: binary_sensor_map - name: Binary Sensor Map - type: group - channels: - - binary_sensor: bin1 - value: 10.0 - - binary_sensor: bin2 - value: 15.0 - - binary_sensor: bin3 - value: 100.0 - - platform: binary_sensor_map - name: Binary Sensor Map - type: sum - channels: - - binary_sensor: bin1 - value: 10.0 - - binary_sensor: bin2 - value: 15.0 - - binary_sensor: bin3 - value: 100.0 - - platform: binary_sensor_map - name: Binary Sensor Map - type: bayesian - prior: 0.4 - observations: - - binary_sensor: bin1 - prob_given_true: 0.9 - prob_given_false: 0.4 - - binary_sensor: bin2 - prob_given_true: 0.7 - prob_given_false: 0.05 - - binary_sensor: bin3 - prob_given_true: 0.8 - prob_given_false: 0.2 +<<: !include common.yaml diff --git a/tests/components/binary_sensor_map/test.rp2040.yaml b/tests/components/binary_sensor_map/test.rp2040.yaml index 8ffdd1f379..dade44d145 100644 --- a/tests/components/binary_sensor_map/test.rp2040.yaml +++ b/tests/components/binary_sensor_map/test.rp2040.yaml @@ -1,61 +1 @@ -binary_sensor: - - platform: template - id: bin1 - lambda: |- - if (millis() > 10000) { - return true; - } else { - return false; - } - - platform: template - id: bin2 - lambda: |- - if (millis() > 20000) { - return true; - } else { - return false; - } - - platform: template - id: bin3 - lambda: |- - if (millis() > 30000) { - return true; - } else { - return false; - } - -sensor: - - platform: binary_sensor_map - name: Binary Sensor Map - type: group - channels: - - binary_sensor: bin1 - value: 10.0 - - binary_sensor: bin2 - value: 15.0 - - binary_sensor: bin3 - value: 100.0 - - platform: binary_sensor_map - name: Binary Sensor Map - type: sum - channels: - - binary_sensor: bin1 - value: 10.0 - - binary_sensor: bin2 - value: 15.0 - - binary_sensor: bin3 - value: 100.0 - - platform: binary_sensor_map - name: Binary Sensor Map - type: bayesian - prior: 0.4 - observations: - - binary_sensor: bin1 - prob_given_true: 0.9 - prob_given_false: 0.4 - - binary_sensor: bin2 - prob_given_true: 0.7 - prob_given_false: 0.05 - - binary_sensor: bin3 - prob_given_true: 0.8 - prob_given_false: 0.2 +<<: !include common.yaml diff --git a/tests/components/ble_client/common.yaml b/tests/components/ble_client/common.yaml new file mode 100644 index 0000000000..b5272d01f0 --- /dev/null +++ b/tests/components/ble_client/common.yaml @@ -0,0 +1,5 @@ +esp32_ble_tracker: + +ble_client: + - mac_address: 01:02:03:04:05:06 + id: test_blec diff --git a/tests/components/ble_client/test.esp32-c3-idf.yaml b/tests/components/ble_client/test.esp32-c3-idf.yaml index b5272d01f0..dade44d145 100644 --- a/tests/components/ble_client/test.esp32-c3-idf.yaml +++ b/tests/components/ble_client/test.esp32-c3-idf.yaml @@ -1,5 +1 @@ -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: test_blec +<<: !include common.yaml diff --git a/tests/components/ble_client/test.esp32-c3.yaml b/tests/components/ble_client/test.esp32-c3.yaml index b5272d01f0..dade44d145 100644 --- a/tests/components/ble_client/test.esp32-c3.yaml +++ b/tests/components/ble_client/test.esp32-c3.yaml @@ -1,5 +1 @@ -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: test_blec +<<: !include common.yaml diff --git a/tests/components/ble_client/test.esp32-idf.yaml b/tests/components/ble_client/test.esp32-idf.yaml index b5272d01f0..dade44d145 100644 --- a/tests/components/ble_client/test.esp32-idf.yaml +++ b/tests/components/ble_client/test.esp32-idf.yaml @@ -1,5 +1 @@ -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: test_blec +<<: !include common.yaml diff --git a/tests/components/ble_client/test.esp32.yaml b/tests/components/ble_client/test.esp32.yaml index b5272d01f0..dade44d145 100644 --- a/tests/components/ble_client/test.esp32.yaml +++ b/tests/components/ble_client/test.esp32.yaml @@ -1,5 +1 @@ -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: test_blec +<<: !include common.yaml diff --git a/tests/components/ble_presence/common.yaml b/tests/components/ble_presence/common.yaml new file mode 100644 index 0000000000..6e5173eed8 --- /dev/null +++ b/tests/components/ble_presence/common.yaml @@ -0,0 +1,24 @@ +esp32_ble_tracker: + +binary_sensor: + - platform: ble_presence + mac_address: AC:37:43:77:5F:4C + name: ESP32 BLE Tracker Google Home Mini + - platform: ble_presence + service_uuid: 11aa + name: BLE Test Service 16 Presence + - platform: ble_presence + service_uuid: "11223344" + name: BLE Test Service 32 Presence + - platform: ble_presence + service_uuid: 11223344-5566-7788-99aa-bbccddeeff00 + name: BLE Test Service 128 Presence + - platform: ble_presence + ibeacon_uuid: 11223344-5566-7788-99aa-bbccddeeff00 + ibeacon_major: 100 + ibeacon_minor: 1 + name: BLE Test iBeacon Presence + - platform: ble_presence + irk: 1234567890abcdef1234567890abcdef + name: "ESP32 BLE Tracker with Identity Resolving Key" + diff --git a/tests/components/ble_presence/test.esp32-c3-idf.yaml b/tests/components/ble_presence/test.esp32-c3-idf.yaml index 6e5173eed8..dade44d145 100644 --- a/tests/components/ble_presence/test.esp32-c3-idf.yaml +++ b/tests/components/ble_presence/test.esp32-c3-idf.yaml @@ -1,24 +1 @@ -esp32_ble_tracker: - -binary_sensor: - - platform: ble_presence - mac_address: AC:37:43:77:5F:4C - name: ESP32 BLE Tracker Google Home Mini - - platform: ble_presence - service_uuid: 11aa - name: BLE Test Service 16 Presence - - platform: ble_presence - service_uuid: "11223344" - name: BLE Test Service 32 Presence - - platform: ble_presence - service_uuid: 11223344-5566-7788-99aa-bbccddeeff00 - name: BLE Test Service 128 Presence - - platform: ble_presence - ibeacon_uuid: 11223344-5566-7788-99aa-bbccddeeff00 - ibeacon_major: 100 - ibeacon_minor: 1 - name: BLE Test iBeacon Presence - - platform: ble_presence - irk: 1234567890abcdef1234567890abcdef - name: "ESP32 BLE Tracker with Identity Resolving Key" - +<<: !include common.yaml diff --git a/tests/components/ble_presence/test.esp32-c3.yaml b/tests/components/ble_presence/test.esp32-c3.yaml index 6e5173eed8..dade44d145 100644 --- a/tests/components/ble_presence/test.esp32-c3.yaml +++ b/tests/components/ble_presence/test.esp32-c3.yaml @@ -1,24 +1 @@ -esp32_ble_tracker: - -binary_sensor: - - platform: ble_presence - mac_address: AC:37:43:77:5F:4C - name: ESP32 BLE Tracker Google Home Mini - - platform: ble_presence - service_uuid: 11aa - name: BLE Test Service 16 Presence - - platform: ble_presence - service_uuid: "11223344" - name: BLE Test Service 32 Presence - - platform: ble_presence - service_uuid: 11223344-5566-7788-99aa-bbccddeeff00 - name: BLE Test Service 128 Presence - - platform: ble_presence - ibeacon_uuid: 11223344-5566-7788-99aa-bbccddeeff00 - ibeacon_major: 100 - ibeacon_minor: 1 - name: BLE Test iBeacon Presence - - platform: ble_presence - irk: 1234567890abcdef1234567890abcdef - name: "ESP32 BLE Tracker with Identity Resolving Key" - +<<: !include common.yaml diff --git a/tests/components/ble_presence/test.esp32-idf.yaml b/tests/components/ble_presence/test.esp32-idf.yaml index 6e5173eed8..dade44d145 100644 --- a/tests/components/ble_presence/test.esp32-idf.yaml +++ b/tests/components/ble_presence/test.esp32-idf.yaml @@ -1,24 +1 @@ -esp32_ble_tracker: - -binary_sensor: - - platform: ble_presence - mac_address: AC:37:43:77:5F:4C - name: ESP32 BLE Tracker Google Home Mini - - platform: ble_presence - service_uuid: 11aa - name: BLE Test Service 16 Presence - - platform: ble_presence - service_uuid: "11223344" - name: BLE Test Service 32 Presence - - platform: ble_presence - service_uuid: 11223344-5566-7788-99aa-bbccddeeff00 - name: BLE Test Service 128 Presence - - platform: ble_presence - ibeacon_uuid: 11223344-5566-7788-99aa-bbccddeeff00 - ibeacon_major: 100 - ibeacon_minor: 1 - name: BLE Test iBeacon Presence - - platform: ble_presence - irk: 1234567890abcdef1234567890abcdef - name: "ESP32 BLE Tracker with Identity Resolving Key" - +<<: !include common.yaml diff --git a/tests/components/ble_presence/test.esp32.yaml b/tests/components/ble_presence/test.esp32.yaml index 6e5173eed8..dade44d145 100644 --- a/tests/components/ble_presence/test.esp32.yaml +++ b/tests/components/ble_presence/test.esp32.yaml @@ -1,24 +1 @@ -esp32_ble_tracker: - -binary_sensor: - - platform: ble_presence - mac_address: AC:37:43:77:5F:4C - name: ESP32 BLE Tracker Google Home Mini - - platform: ble_presence - service_uuid: 11aa - name: BLE Test Service 16 Presence - - platform: ble_presence - service_uuid: "11223344" - name: BLE Test Service 32 Presence - - platform: ble_presence - service_uuid: 11223344-5566-7788-99aa-bbccddeeff00 - name: BLE Test Service 128 Presence - - platform: ble_presence - ibeacon_uuid: 11223344-5566-7788-99aa-bbccddeeff00 - ibeacon_major: 100 - ibeacon_minor: 1 - name: BLE Test iBeacon Presence - - platform: ble_presence - irk: 1234567890abcdef1234567890abcdef - name: "ESP32 BLE Tracker with Identity Resolving Key" - +<<: !include common.yaml diff --git a/tests/components/ble_rssi/common.yaml b/tests/components/ble_rssi/common.yaml new file mode 100644 index 0000000000..52e5b865c6 --- /dev/null +++ b/tests/components/ble_rssi/common.yaml @@ -0,0 +1,18 @@ +esp32_ble_tracker: + +sensor: + - platform: ble_rssi + mac_address: AC:37:43:77:5F:4C + name: BLE Google Home Mini RSSI value + - platform: ble_rssi + service_uuid: 11aa + name: BLE Test Service 16 + - platform: ble_rssi + service_uuid: "11223344" + name: BLE Test Service 32 + - platform: ble_rssi + service_uuid: 11223344-5566-7788-99aa-bbccddeeff00 + name: BLE Test Service 128 + - platform: ble_rssi + service_uuid: 11223344-5566-7788-99aa-bbccddeeff00 + name: BLE Test iBeacon UUID diff --git a/tests/components/ble_rssi/test.esp32-c3-idf.yaml b/tests/components/ble_rssi/test.esp32-c3-idf.yaml index 52e5b865c6..dade44d145 100644 --- a/tests/components/ble_rssi/test.esp32-c3-idf.yaml +++ b/tests/components/ble_rssi/test.esp32-c3-idf.yaml @@ -1,18 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: ble_rssi - mac_address: AC:37:43:77:5F:4C - name: BLE Google Home Mini RSSI value - - platform: ble_rssi - service_uuid: 11aa - name: BLE Test Service 16 - - platform: ble_rssi - service_uuid: "11223344" - name: BLE Test Service 32 - - platform: ble_rssi - service_uuid: 11223344-5566-7788-99aa-bbccddeeff00 - name: BLE Test Service 128 - - platform: ble_rssi - service_uuid: 11223344-5566-7788-99aa-bbccddeeff00 - name: BLE Test iBeacon UUID +<<: !include common.yaml diff --git a/tests/components/ble_rssi/test.esp32-c3.yaml b/tests/components/ble_rssi/test.esp32-c3.yaml index 52e5b865c6..dade44d145 100644 --- a/tests/components/ble_rssi/test.esp32-c3.yaml +++ b/tests/components/ble_rssi/test.esp32-c3.yaml @@ -1,18 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: ble_rssi - mac_address: AC:37:43:77:5F:4C - name: BLE Google Home Mini RSSI value - - platform: ble_rssi - service_uuid: 11aa - name: BLE Test Service 16 - - platform: ble_rssi - service_uuid: "11223344" - name: BLE Test Service 32 - - platform: ble_rssi - service_uuid: 11223344-5566-7788-99aa-bbccddeeff00 - name: BLE Test Service 128 - - platform: ble_rssi - service_uuid: 11223344-5566-7788-99aa-bbccddeeff00 - name: BLE Test iBeacon UUID +<<: !include common.yaml diff --git a/tests/components/ble_rssi/test.esp32-idf.yaml b/tests/components/ble_rssi/test.esp32-idf.yaml index 52e5b865c6..dade44d145 100644 --- a/tests/components/ble_rssi/test.esp32-idf.yaml +++ b/tests/components/ble_rssi/test.esp32-idf.yaml @@ -1,18 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: ble_rssi - mac_address: AC:37:43:77:5F:4C - name: BLE Google Home Mini RSSI value - - platform: ble_rssi - service_uuid: 11aa - name: BLE Test Service 16 - - platform: ble_rssi - service_uuid: "11223344" - name: BLE Test Service 32 - - platform: ble_rssi - service_uuid: 11223344-5566-7788-99aa-bbccddeeff00 - name: BLE Test Service 128 - - platform: ble_rssi - service_uuid: 11223344-5566-7788-99aa-bbccddeeff00 - name: BLE Test iBeacon UUID +<<: !include common.yaml diff --git a/tests/components/ble_rssi/test.esp32.yaml b/tests/components/ble_rssi/test.esp32.yaml index 52e5b865c6..dade44d145 100644 --- a/tests/components/ble_rssi/test.esp32.yaml +++ b/tests/components/ble_rssi/test.esp32.yaml @@ -1,18 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: ble_rssi - mac_address: AC:37:43:77:5F:4C - name: BLE Google Home Mini RSSI value - - platform: ble_rssi - service_uuid: 11aa - name: BLE Test Service 16 - - platform: ble_rssi - service_uuid: "11223344" - name: BLE Test Service 32 - - platform: ble_rssi - service_uuid: 11223344-5566-7788-99aa-bbccddeeff00 - name: BLE Test Service 128 - - platform: ble_rssi - service_uuid: 11223344-5566-7788-99aa-bbccddeeff00 - name: BLE Test iBeacon UUID +<<: !include common.yaml diff --git a/tests/components/ble_scanner/common.yaml b/tests/components/ble_scanner/common.yaml new file mode 100644 index 0000000000..935a5a5a19 --- /dev/null +++ b/tests/components/ble_scanner/common.yaml @@ -0,0 +1,5 @@ +esp32_ble_tracker: + +text_sensor: + - platform: ble_scanner + name: Scanner diff --git a/tests/components/ble_scanner/test.esp32-c3-idf.yaml b/tests/components/ble_scanner/test.esp32-c3-idf.yaml index 935a5a5a19..dade44d145 100644 --- a/tests/components/ble_scanner/test.esp32-c3-idf.yaml +++ b/tests/components/ble_scanner/test.esp32-c3-idf.yaml @@ -1,5 +1 @@ -esp32_ble_tracker: - -text_sensor: - - platform: ble_scanner - name: Scanner +<<: !include common.yaml diff --git a/tests/components/ble_scanner/test.esp32-c3.yaml b/tests/components/ble_scanner/test.esp32-c3.yaml index 935a5a5a19..dade44d145 100644 --- a/tests/components/ble_scanner/test.esp32-c3.yaml +++ b/tests/components/ble_scanner/test.esp32-c3.yaml @@ -1,5 +1 @@ -esp32_ble_tracker: - -text_sensor: - - platform: ble_scanner - name: Scanner +<<: !include common.yaml diff --git a/tests/components/ble_scanner/test.esp32-idf.yaml b/tests/components/ble_scanner/test.esp32-idf.yaml index 935a5a5a19..dade44d145 100644 --- a/tests/components/ble_scanner/test.esp32-idf.yaml +++ b/tests/components/ble_scanner/test.esp32-idf.yaml @@ -1,5 +1 @@ -esp32_ble_tracker: - -text_sensor: - - platform: ble_scanner - name: Scanner +<<: !include common.yaml diff --git a/tests/components/ble_scanner/test.esp32.yaml b/tests/components/ble_scanner/test.esp32.yaml index 935a5a5a19..dade44d145 100644 --- a/tests/components/ble_scanner/test.esp32.yaml +++ b/tests/components/ble_scanner/test.esp32.yaml @@ -1,5 +1 @@ -esp32_ble_tracker: - -text_sensor: - - platform: ble_scanner - name: Scanner +<<: !include common.yaml diff --git a/tests/components/button/common.yaml b/tests/components/button/common.yaml new file mode 100644 index 0000000000..d5978601f4 --- /dev/null +++ b/tests/components/button/common.yaml @@ -0,0 +1,6 @@ +button: + - platform: template + name: Button + id: some_button + on_press: + - logger.log: Button pressed diff --git a/tests/components/button/test.esp32-c3-idf.yaml b/tests/components/button/test.esp32-c3-idf.yaml index d5978601f4..dade44d145 100644 --- a/tests/components/button/test.esp32-c3-idf.yaml +++ b/tests/components/button/test.esp32-c3-idf.yaml @@ -1,6 +1 @@ -button: - - platform: template - name: Button - id: some_button - on_press: - - logger.log: Button pressed +<<: !include common.yaml diff --git a/tests/components/button/test.esp32-c3.yaml b/tests/components/button/test.esp32-c3.yaml index d5978601f4..dade44d145 100644 --- a/tests/components/button/test.esp32-c3.yaml +++ b/tests/components/button/test.esp32-c3.yaml @@ -1,6 +1 @@ -button: - - platform: template - name: Button - id: some_button - on_press: - - logger.log: Button pressed +<<: !include common.yaml diff --git a/tests/components/button/test.esp32-idf.yaml b/tests/components/button/test.esp32-idf.yaml index d5978601f4..dade44d145 100644 --- a/tests/components/button/test.esp32-idf.yaml +++ b/tests/components/button/test.esp32-idf.yaml @@ -1,6 +1 @@ -button: - - platform: template - name: Button - id: some_button - on_press: - - logger.log: Button pressed +<<: !include common.yaml diff --git a/tests/components/button/test.esp32.yaml b/tests/components/button/test.esp32.yaml index d5978601f4..dade44d145 100644 --- a/tests/components/button/test.esp32.yaml +++ b/tests/components/button/test.esp32.yaml @@ -1,6 +1 @@ -button: - - platform: template - name: Button - id: some_button - on_press: - - logger.log: Button pressed +<<: !include common.yaml diff --git a/tests/components/button/test.esp8266.yaml b/tests/components/button/test.esp8266.yaml index d5978601f4..dade44d145 100644 --- a/tests/components/button/test.esp8266.yaml +++ b/tests/components/button/test.esp8266.yaml @@ -1,6 +1 @@ -button: - - platform: template - name: Button - id: some_button - on_press: - - logger.log: Button pressed +<<: !include common.yaml diff --git a/tests/components/button/test.rp2040.yaml b/tests/components/button/test.rp2040.yaml index d5978601f4..dade44d145 100644 --- a/tests/components/button/test.rp2040.yaml +++ b/tests/components/button/test.rp2040.yaml @@ -1,6 +1 @@ -button: - - platform: template - name: Button - id: some_button - on_press: - - logger.log: Button pressed +<<: !include common.yaml diff --git a/tests/components/canbus/common.yaml b/tests/components/canbus/common.yaml new file mode 100644 index 0000000000..fd146cc3a3 --- /dev/null +++ b/tests/components/canbus/common.yaml @@ -0,0 +1,46 @@ +canbus: + - platform: esp32_can + id: esp32_internal_can + rx_pin: 4 + tx_pin: 5 + can_id: 4 + bit_rate: 50kbps + on_frame: + - can_id: 500 + then: + - lambda: |- + std::string b(x.begin(), x.end()); + ESP_LOGD("canid 500", "%s", b.c_str()); + - can_id: 23 + then: + - if: + condition: + lambda: "return x[0] == 0x11;" + then: + logger.log: Truth + - can_id: 0b00000000000000000000001000000 + can_id_mask: 0b11111000000000011111111000000 + use_extended_id: true + then: + - lambda: |- + auto pdo_id = can_id >> 14; + switch (pdo_id) + { + case 117: + ESP_LOGD("canbus", "exhaust_fan_duty"); + break; + case 118: + ESP_LOGD("canbus", "supply_fan_duty"); + break; + case 119: + ESP_LOGD("canbus", "supply_fan_flow"); + break; + } + +button: + - platform: template + name: Canbus Actions + on_press: + - canbus.send: "abc" + - canbus.send: [0, 1, 2] + - canbus.send: !lambda return {0, 1, 2}; diff --git a/tests/components/canbus/test.esp32-c3-idf.yaml b/tests/components/canbus/test.esp32-c3-idf.yaml index fd146cc3a3..dade44d145 100644 --- a/tests/components/canbus/test.esp32-c3-idf.yaml +++ b/tests/components/canbus/test.esp32-c3-idf.yaml @@ -1,46 +1 @@ -canbus: - - platform: esp32_can - id: esp32_internal_can - rx_pin: 4 - tx_pin: 5 - can_id: 4 - bit_rate: 50kbps - on_frame: - - can_id: 500 - then: - - lambda: |- - std::string b(x.begin(), x.end()); - ESP_LOGD("canid 500", "%s", b.c_str()); - - can_id: 23 - then: - - if: - condition: - lambda: "return x[0] == 0x11;" - then: - logger.log: Truth - - can_id: 0b00000000000000000000001000000 - can_id_mask: 0b11111000000000011111111000000 - use_extended_id: true - then: - - lambda: |- - auto pdo_id = can_id >> 14; - switch (pdo_id) - { - case 117: - ESP_LOGD("canbus", "exhaust_fan_duty"); - break; - case 118: - ESP_LOGD("canbus", "supply_fan_duty"); - break; - case 119: - ESP_LOGD("canbus", "supply_fan_flow"); - break; - } - -button: - - platform: template - name: Canbus Actions - on_press: - - canbus.send: "abc" - - canbus.send: [0, 1, 2] - - canbus.send: !lambda return {0, 1, 2}; +<<: !include common.yaml diff --git a/tests/components/canbus/test.esp32-c3.yaml b/tests/components/canbus/test.esp32-c3.yaml index fd146cc3a3..dade44d145 100644 --- a/tests/components/canbus/test.esp32-c3.yaml +++ b/tests/components/canbus/test.esp32-c3.yaml @@ -1,46 +1 @@ -canbus: - - platform: esp32_can - id: esp32_internal_can - rx_pin: 4 - tx_pin: 5 - can_id: 4 - bit_rate: 50kbps - on_frame: - - can_id: 500 - then: - - lambda: |- - std::string b(x.begin(), x.end()); - ESP_LOGD("canid 500", "%s", b.c_str()); - - can_id: 23 - then: - - if: - condition: - lambda: "return x[0] == 0x11;" - then: - logger.log: Truth - - can_id: 0b00000000000000000000001000000 - can_id_mask: 0b11111000000000011111111000000 - use_extended_id: true - then: - - lambda: |- - auto pdo_id = can_id >> 14; - switch (pdo_id) - { - case 117: - ESP_LOGD("canbus", "exhaust_fan_duty"); - break; - case 118: - ESP_LOGD("canbus", "supply_fan_duty"); - break; - case 119: - ESP_LOGD("canbus", "supply_fan_flow"); - break; - } - -button: - - platform: template - name: Canbus Actions - on_press: - - canbus.send: "abc" - - canbus.send: [0, 1, 2] - - canbus.send: !lambda return {0, 1, 2}; +<<: !include common.yaml diff --git a/tests/components/canbus/test.esp32-idf.yaml b/tests/components/canbus/test.esp32-idf.yaml index fd146cc3a3..dade44d145 100644 --- a/tests/components/canbus/test.esp32-idf.yaml +++ b/tests/components/canbus/test.esp32-idf.yaml @@ -1,46 +1 @@ -canbus: - - platform: esp32_can - id: esp32_internal_can - rx_pin: 4 - tx_pin: 5 - can_id: 4 - bit_rate: 50kbps - on_frame: - - can_id: 500 - then: - - lambda: |- - std::string b(x.begin(), x.end()); - ESP_LOGD("canid 500", "%s", b.c_str()); - - can_id: 23 - then: - - if: - condition: - lambda: "return x[0] == 0x11;" - then: - logger.log: Truth - - can_id: 0b00000000000000000000001000000 - can_id_mask: 0b11111000000000011111111000000 - use_extended_id: true - then: - - lambda: |- - auto pdo_id = can_id >> 14; - switch (pdo_id) - { - case 117: - ESP_LOGD("canbus", "exhaust_fan_duty"); - break; - case 118: - ESP_LOGD("canbus", "supply_fan_duty"); - break; - case 119: - ESP_LOGD("canbus", "supply_fan_flow"); - break; - } - -button: - - platform: template - name: Canbus Actions - on_press: - - canbus.send: "abc" - - canbus.send: [0, 1, 2] - - canbus.send: !lambda return {0, 1, 2}; +<<: !include common.yaml diff --git a/tests/components/canbus/test.esp32.yaml b/tests/components/canbus/test.esp32.yaml index fd146cc3a3..dade44d145 100644 --- a/tests/components/canbus/test.esp32.yaml +++ b/tests/components/canbus/test.esp32.yaml @@ -1,46 +1 @@ -canbus: - - platform: esp32_can - id: esp32_internal_can - rx_pin: 4 - tx_pin: 5 - can_id: 4 - bit_rate: 50kbps - on_frame: - - can_id: 500 - then: - - lambda: |- - std::string b(x.begin(), x.end()); - ESP_LOGD("canid 500", "%s", b.c_str()); - - can_id: 23 - then: - - if: - condition: - lambda: "return x[0] == 0x11;" - then: - logger.log: Truth - - can_id: 0b00000000000000000000001000000 - can_id_mask: 0b11111000000000011111111000000 - use_extended_id: true - then: - - lambda: |- - auto pdo_id = can_id >> 14; - switch (pdo_id) - { - case 117: - ESP_LOGD("canbus", "exhaust_fan_duty"); - break; - case 118: - ESP_LOGD("canbus", "supply_fan_duty"); - break; - case 119: - ESP_LOGD("canbus", "supply_fan_flow"); - break; - } - -button: - - platform: template - name: Canbus Actions - on_press: - - canbus.send: "abc" - - canbus.send: [0, 1, 2] - - canbus.send: !lambda return {0, 1, 2}; +<<: !include common.yaml diff --git a/tests/components/captive_portal/common.yaml b/tests/components/captive_portal/common.yaml new file mode 100644 index 0000000000..25bc4a887a --- /dev/null +++ b/tests/components/captive_portal/common.yaml @@ -0,0 +1,5 @@ +wifi: + ssid: MySSID + password: password1 + +captive_portal: diff --git a/tests/components/captive_portal/test.esp32-c3-idf.yaml b/tests/components/captive_portal/test.esp32-c3-idf.yaml index 25bc4a887a..dade44d145 100644 --- a/tests/components/captive_portal/test.esp32-c3-idf.yaml +++ b/tests/components/captive_portal/test.esp32-c3-idf.yaml @@ -1,5 +1 @@ -wifi: - ssid: MySSID - password: password1 - -captive_portal: +<<: !include common.yaml diff --git a/tests/components/captive_portal/test.esp32-c3.yaml b/tests/components/captive_portal/test.esp32-c3.yaml index 25bc4a887a..dade44d145 100644 --- a/tests/components/captive_portal/test.esp32-c3.yaml +++ b/tests/components/captive_portal/test.esp32-c3.yaml @@ -1,5 +1 @@ -wifi: - ssid: MySSID - password: password1 - -captive_portal: +<<: !include common.yaml diff --git a/tests/components/captive_portal/test.esp32-idf.yaml b/tests/components/captive_portal/test.esp32-idf.yaml index 25bc4a887a..dade44d145 100644 --- a/tests/components/captive_portal/test.esp32-idf.yaml +++ b/tests/components/captive_portal/test.esp32-idf.yaml @@ -1,5 +1 @@ -wifi: - ssid: MySSID - password: password1 - -captive_portal: +<<: !include common.yaml diff --git a/tests/components/captive_portal/test.esp32.yaml b/tests/components/captive_portal/test.esp32.yaml index 25bc4a887a..dade44d145 100644 --- a/tests/components/captive_portal/test.esp32.yaml +++ b/tests/components/captive_portal/test.esp32.yaml @@ -1,5 +1 @@ -wifi: - ssid: MySSID - password: password1 - -captive_portal: +<<: !include common.yaml diff --git a/tests/components/captive_portal/test.esp8266.yaml b/tests/components/captive_portal/test.esp8266.yaml index 25bc4a887a..dade44d145 100644 --- a/tests/components/captive_portal/test.esp8266.yaml +++ b/tests/components/captive_portal/test.esp8266.yaml @@ -1,5 +1 @@ -wifi: - ssid: MySSID - password: password1 - -captive_portal: +<<: !include common.yaml diff --git a/tests/components/color/common.yaml b/tests/components/color/common.yaml new file mode 100644 index 0000000000..7aa308bb63 --- /dev/null +++ b/tests/components/color/common.yaml @@ -0,0 +1,11 @@ +color: + - id: kbx_red + red: 100% + green_int: 123 + blue: 2% + - id: kbx_blue + red: 0% + green: 1% + blue: 100% + - id: kbx_green + hex: "3DEC55" diff --git a/tests/components/color/test.esp32-c3-idf.yaml b/tests/components/color/test.esp32-c3-idf.yaml index 7aa308bb63..dade44d145 100644 --- a/tests/components/color/test.esp32-c3-idf.yaml +++ b/tests/components/color/test.esp32-c3-idf.yaml @@ -1,11 +1 @@ -color: - - id: kbx_red - red: 100% - green_int: 123 - blue: 2% - - id: kbx_blue - red: 0% - green: 1% - blue: 100% - - id: kbx_green - hex: "3DEC55" +<<: !include common.yaml diff --git a/tests/components/color/test.esp32-c3.yaml b/tests/components/color/test.esp32-c3.yaml index 7aa308bb63..dade44d145 100644 --- a/tests/components/color/test.esp32-c3.yaml +++ b/tests/components/color/test.esp32-c3.yaml @@ -1,11 +1 @@ -color: - - id: kbx_red - red: 100% - green_int: 123 - blue: 2% - - id: kbx_blue - red: 0% - green: 1% - blue: 100% - - id: kbx_green - hex: "3DEC55" +<<: !include common.yaml diff --git a/tests/components/color/test.esp32-idf.yaml b/tests/components/color/test.esp32-idf.yaml index 7aa308bb63..dade44d145 100644 --- a/tests/components/color/test.esp32-idf.yaml +++ b/tests/components/color/test.esp32-idf.yaml @@ -1,11 +1 @@ -color: - - id: kbx_red - red: 100% - green_int: 123 - blue: 2% - - id: kbx_blue - red: 0% - green: 1% - blue: 100% - - id: kbx_green - hex: "3DEC55" +<<: !include common.yaml diff --git a/tests/components/color/test.esp32.yaml b/tests/components/color/test.esp32.yaml index 7aa308bb63..dade44d145 100644 --- a/tests/components/color/test.esp32.yaml +++ b/tests/components/color/test.esp32.yaml @@ -1,11 +1 @@ -color: - - id: kbx_red - red: 100% - green_int: 123 - blue: 2% - - id: kbx_blue - red: 0% - green: 1% - blue: 100% - - id: kbx_green - hex: "3DEC55" +<<: !include common.yaml diff --git a/tests/components/color/test.esp8266.yaml b/tests/components/color/test.esp8266.yaml index 7aa308bb63..dade44d145 100644 --- a/tests/components/color/test.esp8266.yaml +++ b/tests/components/color/test.esp8266.yaml @@ -1,11 +1 @@ -color: - - id: kbx_red - red: 100% - green_int: 123 - blue: 2% - - id: kbx_blue - red: 0% - green: 1% - blue: 100% - - id: kbx_green - hex: "3DEC55" +<<: !include common.yaml diff --git a/tests/components/color/test.rp2040.yaml b/tests/components/color/test.rp2040.yaml index 7aa308bb63..dade44d145 100644 --- a/tests/components/color/test.rp2040.yaml +++ b/tests/components/color/test.rp2040.yaml @@ -1,11 +1 @@ -color: - - id: kbx_red - red: 100% - green_int: 123 - blue: 2% - - id: kbx_blue - red: 0% - green: 1% - blue: 100% - - id: kbx_green - hex: "3DEC55" +<<: !include common.yaml diff --git a/tests/components/combination/common.yaml b/tests/components/combination/common.yaml new file mode 100644 index 0000000000..62246190af --- /dev/null +++ b/tests/components/combination/common.yaml @@ -0,0 +1,76 @@ +sensor: + - platform: template + id: template_temperature1 + lambda: |- + if (millis() > 10000) { + return 0.6; + } else { + return 0.0; + } + - platform: template + id: template_temperature2 + lambda: |- + if (millis() > 20000) { + return 0.8; + } else { + return 0.0; + } + - platform: combination + type: kalman + name: Kalman-filtered temperature + process_std_dev: 0.00139 + sources: + - source: template_temperature1 + error: !lambda "return 0.4 + std::abs(x - 25) * 0.023;" + - source: template_temperature2 + error: 1.5 + - platform: combination + type: linear + name: Linearly combined temperatures + sources: + - source: template_temperature1 + coeffecient: !lambda "return 0.4 + std::abs(x - 25) * 0.023;" + - source: template_temperature2 + coeffecient: 1.5 + - platform: combination + type: max + name: Max of combined temperatures + sources: + - source: template_temperature1 + - source: template_temperature2 + - platform: combination + type: mean + name: Mean of combined temperatures + sources: + - source: template_temperature1 + - source: template_temperature2 + - platform: combination + type: median + name: Median of combined temperatures + sources: + - source: template_temperature1 + - source: template_temperature2 + - platform: combination + type: min + name: Min of combined temperatures + sources: + - source: template_temperature1 + - source: template_temperature2 + - platform: combination + type: most_recently_updated + name: Most recently updated of combined temperatures + sources: + - source: template_temperature1 + - source: template_temperature2 + - platform: combination + type: range + name: Range of combined temperatures + sources: + - source: template_temperature1 + - source: template_temperature2 + - platform: combination + type: sum + name: Sum of combined temperatures + sources: + - source: template_temperature1 + - source: template_temperature2 diff --git a/tests/components/combination/test.esp32-c3-idf.yaml b/tests/components/combination/test.esp32-c3-idf.yaml index 62246190af..dade44d145 100644 --- a/tests/components/combination/test.esp32-c3-idf.yaml +++ b/tests/components/combination/test.esp32-c3-idf.yaml @@ -1,76 +1 @@ -sensor: - - platform: template - id: template_temperature1 - lambda: |- - if (millis() > 10000) { - return 0.6; - } else { - return 0.0; - } - - platform: template - id: template_temperature2 - lambda: |- - if (millis() > 20000) { - return 0.8; - } else { - return 0.0; - } - - platform: combination - type: kalman - name: Kalman-filtered temperature - process_std_dev: 0.00139 - sources: - - source: template_temperature1 - error: !lambda "return 0.4 + std::abs(x - 25) * 0.023;" - - source: template_temperature2 - error: 1.5 - - platform: combination - type: linear - name: Linearly combined temperatures - sources: - - source: template_temperature1 - coeffecient: !lambda "return 0.4 + std::abs(x - 25) * 0.023;" - - source: template_temperature2 - coeffecient: 1.5 - - platform: combination - type: max - name: Max of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 - - platform: combination - type: mean - name: Mean of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 - - platform: combination - type: median - name: Median of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 - - platform: combination - type: min - name: Min of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 - - platform: combination - type: most_recently_updated - name: Most recently updated of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 - - platform: combination - type: range - name: Range of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 - - platform: combination - type: sum - name: Sum of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 +<<: !include common.yaml diff --git a/tests/components/combination/test.esp32-c3.yaml b/tests/components/combination/test.esp32-c3.yaml index 62246190af..dade44d145 100644 --- a/tests/components/combination/test.esp32-c3.yaml +++ b/tests/components/combination/test.esp32-c3.yaml @@ -1,76 +1 @@ -sensor: - - platform: template - id: template_temperature1 - lambda: |- - if (millis() > 10000) { - return 0.6; - } else { - return 0.0; - } - - platform: template - id: template_temperature2 - lambda: |- - if (millis() > 20000) { - return 0.8; - } else { - return 0.0; - } - - platform: combination - type: kalman - name: Kalman-filtered temperature - process_std_dev: 0.00139 - sources: - - source: template_temperature1 - error: !lambda "return 0.4 + std::abs(x - 25) * 0.023;" - - source: template_temperature2 - error: 1.5 - - platform: combination - type: linear - name: Linearly combined temperatures - sources: - - source: template_temperature1 - coeffecient: !lambda "return 0.4 + std::abs(x - 25) * 0.023;" - - source: template_temperature2 - coeffecient: 1.5 - - platform: combination - type: max - name: Max of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 - - platform: combination - type: mean - name: Mean of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 - - platform: combination - type: median - name: Median of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 - - platform: combination - type: min - name: Min of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 - - platform: combination - type: most_recently_updated - name: Most recently updated of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 - - platform: combination - type: range - name: Range of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 - - platform: combination - type: sum - name: Sum of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 +<<: !include common.yaml diff --git a/tests/components/combination/test.esp32-idf.yaml b/tests/components/combination/test.esp32-idf.yaml index 62246190af..dade44d145 100644 --- a/tests/components/combination/test.esp32-idf.yaml +++ b/tests/components/combination/test.esp32-idf.yaml @@ -1,76 +1 @@ -sensor: - - platform: template - id: template_temperature1 - lambda: |- - if (millis() > 10000) { - return 0.6; - } else { - return 0.0; - } - - platform: template - id: template_temperature2 - lambda: |- - if (millis() > 20000) { - return 0.8; - } else { - return 0.0; - } - - platform: combination - type: kalman - name: Kalman-filtered temperature - process_std_dev: 0.00139 - sources: - - source: template_temperature1 - error: !lambda "return 0.4 + std::abs(x - 25) * 0.023;" - - source: template_temperature2 - error: 1.5 - - platform: combination - type: linear - name: Linearly combined temperatures - sources: - - source: template_temperature1 - coeffecient: !lambda "return 0.4 + std::abs(x - 25) * 0.023;" - - source: template_temperature2 - coeffecient: 1.5 - - platform: combination - type: max - name: Max of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 - - platform: combination - type: mean - name: Mean of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 - - platform: combination - type: median - name: Median of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 - - platform: combination - type: min - name: Min of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 - - platform: combination - type: most_recently_updated - name: Most recently updated of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 - - platform: combination - type: range - name: Range of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 - - platform: combination - type: sum - name: Sum of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 +<<: !include common.yaml diff --git a/tests/components/combination/test.esp32.yaml b/tests/components/combination/test.esp32.yaml index 62246190af..dade44d145 100644 --- a/tests/components/combination/test.esp32.yaml +++ b/tests/components/combination/test.esp32.yaml @@ -1,76 +1 @@ -sensor: - - platform: template - id: template_temperature1 - lambda: |- - if (millis() > 10000) { - return 0.6; - } else { - return 0.0; - } - - platform: template - id: template_temperature2 - lambda: |- - if (millis() > 20000) { - return 0.8; - } else { - return 0.0; - } - - platform: combination - type: kalman - name: Kalman-filtered temperature - process_std_dev: 0.00139 - sources: - - source: template_temperature1 - error: !lambda "return 0.4 + std::abs(x - 25) * 0.023;" - - source: template_temperature2 - error: 1.5 - - platform: combination - type: linear - name: Linearly combined temperatures - sources: - - source: template_temperature1 - coeffecient: !lambda "return 0.4 + std::abs(x - 25) * 0.023;" - - source: template_temperature2 - coeffecient: 1.5 - - platform: combination - type: max - name: Max of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 - - platform: combination - type: mean - name: Mean of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 - - platform: combination - type: median - name: Median of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 - - platform: combination - type: min - name: Min of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 - - platform: combination - type: most_recently_updated - name: Most recently updated of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 - - platform: combination - type: range - name: Range of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 - - platform: combination - type: sum - name: Sum of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 +<<: !include common.yaml diff --git a/tests/components/combination/test.esp8266.yaml b/tests/components/combination/test.esp8266.yaml index 62246190af..dade44d145 100644 --- a/tests/components/combination/test.esp8266.yaml +++ b/tests/components/combination/test.esp8266.yaml @@ -1,76 +1 @@ -sensor: - - platform: template - id: template_temperature1 - lambda: |- - if (millis() > 10000) { - return 0.6; - } else { - return 0.0; - } - - platform: template - id: template_temperature2 - lambda: |- - if (millis() > 20000) { - return 0.8; - } else { - return 0.0; - } - - platform: combination - type: kalman - name: Kalman-filtered temperature - process_std_dev: 0.00139 - sources: - - source: template_temperature1 - error: !lambda "return 0.4 + std::abs(x - 25) * 0.023;" - - source: template_temperature2 - error: 1.5 - - platform: combination - type: linear - name: Linearly combined temperatures - sources: - - source: template_temperature1 - coeffecient: !lambda "return 0.4 + std::abs(x - 25) * 0.023;" - - source: template_temperature2 - coeffecient: 1.5 - - platform: combination - type: max - name: Max of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 - - platform: combination - type: mean - name: Mean of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 - - platform: combination - type: median - name: Median of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 - - platform: combination - type: min - name: Min of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 - - platform: combination - type: most_recently_updated - name: Most recently updated of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 - - platform: combination - type: range - name: Range of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 - - platform: combination - type: sum - name: Sum of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 +<<: !include common.yaml diff --git a/tests/components/combination/test.rp2040.yaml b/tests/components/combination/test.rp2040.yaml index 62246190af..dade44d145 100644 --- a/tests/components/combination/test.rp2040.yaml +++ b/tests/components/combination/test.rp2040.yaml @@ -1,76 +1 @@ -sensor: - - platform: template - id: template_temperature1 - lambda: |- - if (millis() > 10000) { - return 0.6; - } else { - return 0.0; - } - - platform: template - id: template_temperature2 - lambda: |- - if (millis() > 20000) { - return 0.8; - } else { - return 0.0; - } - - platform: combination - type: kalman - name: Kalman-filtered temperature - process_std_dev: 0.00139 - sources: - - source: template_temperature1 - error: !lambda "return 0.4 + std::abs(x - 25) * 0.023;" - - source: template_temperature2 - error: 1.5 - - platform: combination - type: linear - name: Linearly combined temperatures - sources: - - source: template_temperature1 - coeffecient: !lambda "return 0.4 + std::abs(x - 25) * 0.023;" - - source: template_temperature2 - coeffecient: 1.5 - - platform: combination - type: max - name: Max of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 - - platform: combination - type: mean - name: Mean of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 - - platform: combination - type: median - name: Median of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 - - platform: combination - type: min - name: Min of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 - - platform: combination - type: most_recently_updated - name: Most recently updated of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 - - platform: combination - type: range - name: Range of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 - - platform: combination - type: sum - name: Sum of combined temperatures - sources: - - source: template_temperature1 - - source: template_temperature2 +<<: !include common.yaml diff --git a/tests/components/cst226/common.yaml b/tests/components/cst226/common.yaml new file mode 100644 index 0000000000..4cbf38ef50 --- /dev/null +++ b/tests/components/cst226/common.yaml @@ -0,0 +1,24 @@ +spi: + - id: spi_id_1 + clk_pin: GPIO7 + mosi_pin: GPIO6 + interface: any + +display: + - platform: ili9xxx + id: displ8 + model: ili9342 + cs_pin: GPIO5 + dc_pin: GPIO4 + reset_pin: + number: GPIO21 + +i2c: + scl: GPIO18 + sda: GPIO8 + +touchscreen: + - platform: cst226 + interrupt_pin: GPIO3 + reset_pin: GPIO20 + diff --git a/tests/components/cst226/test.esp32-c3.yaml b/tests/components/cst226/test.esp32-c3.yaml index 4cbf38ef50..dade44d145 100644 --- a/tests/components/cst226/test.esp32-c3.yaml +++ b/tests/components/cst226/test.esp32-c3.yaml @@ -1,24 +1 @@ -spi: - - id: spi_id_1 - clk_pin: GPIO7 - mosi_pin: GPIO6 - interface: any - -display: - - platform: ili9xxx - id: displ8 - model: ili9342 - cs_pin: GPIO5 - dc_pin: GPIO4 - reset_pin: - number: GPIO21 - -i2c: - scl: GPIO18 - sda: GPIO8 - -touchscreen: - - platform: cst226 - interrupt_pin: GPIO3 - reset_pin: GPIO20 - +<<: !include common.yaml diff --git a/tests/components/cst816/common.yaml b/tests/components/cst816/common.yaml new file mode 100644 index 0000000000..f8deea6e98 --- /dev/null +++ b/tests/components/cst816/common.yaml @@ -0,0 +1,36 @@ +touchscreen: + - platform: cst816 + id: my_touchscreen + interrupt_pin: + number: 21 + reset_pin: GPIO16 + transform: + mirror_x: false + mirror_y: false + swap_xy: false + +i2c: + sda: 3 + scl: 2 + +display: + - id: my_display + platform: ili9xxx + dimensions: 480x320 + model: ST7796 + cs_pin: 15 + dc_pin: 20 + reset_pin: 22 + transform: + swap_xy: true + mirror_x: true + mirror_y: true + auto_clear_enabled: false + +spi: + clk_pin: 14 + mosi_pin: 13 + +binary_sensor: + - platform: cst816 + name: Home Button diff --git a/tests/components/cst816/test.esp32.yaml b/tests/components/cst816/test.esp32.yaml index f8deea6e98..dade44d145 100644 --- a/tests/components/cst816/test.esp32.yaml +++ b/tests/components/cst816/test.esp32.yaml @@ -1,36 +1 @@ -touchscreen: - - platform: cst816 - id: my_touchscreen - interrupt_pin: - number: 21 - reset_pin: GPIO16 - transform: - mirror_x: false - mirror_y: false - swap_xy: false - -i2c: - sda: 3 - scl: 2 - -display: - - id: my_display - platform: ili9xxx - dimensions: 480x320 - model: ST7796 - cs_pin: 15 - dc_pin: 20 - reset_pin: 22 - transform: - swap_xy: true - mirror_x: true - mirror_y: true - auto_clear_enabled: false - -spi: - clk_pin: 14 - mosi_pin: 13 - -binary_sensor: - - platform: cst816 - name: Home Button +<<: !include common.yaml diff --git a/tests/components/dallas/common.yaml b/tests/components/dallas/common.yaml new file mode 100644 index 0000000000..7975977107 --- /dev/null +++ b/tests/components/dallas/common.yaml @@ -0,0 +1,11 @@ +dallas: + pin: 4 + +sensor: + - platform: dallas + address: 0x1C0000031EDD2A28 + name: Dallas Temperature + resolution: 9 + - platform: dallas + index: 1 + name: Dallas Temperature diff --git a/tests/components/dallas/test.esp32-c3-idf.yaml b/tests/components/dallas/test.esp32-c3-idf.yaml index 7975977107..dade44d145 100644 --- a/tests/components/dallas/test.esp32-c3-idf.yaml +++ b/tests/components/dallas/test.esp32-c3-idf.yaml @@ -1,11 +1 @@ -dallas: - pin: 4 - -sensor: - - platform: dallas - address: 0x1C0000031EDD2A28 - name: Dallas Temperature - resolution: 9 - - platform: dallas - index: 1 - name: Dallas Temperature +<<: !include common.yaml diff --git a/tests/components/dallas/test.esp32-c3.yaml b/tests/components/dallas/test.esp32-c3.yaml index 7975977107..dade44d145 100644 --- a/tests/components/dallas/test.esp32-c3.yaml +++ b/tests/components/dallas/test.esp32-c3.yaml @@ -1,11 +1 @@ -dallas: - pin: 4 - -sensor: - - platform: dallas - address: 0x1C0000031EDD2A28 - name: Dallas Temperature - resolution: 9 - - platform: dallas - index: 1 - name: Dallas Temperature +<<: !include common.yaml diff --git a/tests/components/dallas/test.esp32-idf.yaml b/tests/components/dallas/test.esp32-idf.yaml index 7975977107..dade44d145 100644 --- a/tests/components/dallas/test.esp32-idf.yaml +++ b/tests/components/dallas/test.esp32-idf.yaml @@ -1,11 +1 @@ -dallas: - pin: 4 - -sensor: - - platform: dallas - address: 0x1C0000031EDD2A28 - name: Dallas Temperature - resolution: 9 - - platform: dallas - index: 1 - name: Dallas Temperature +<<: !include common.yaml diff --git a/tests/components/dallas/test.esp32.yaml b/tests/components/dallas/test.esp32.yaml index 7975977107..dade44d145 100644 --- a/tests/components/dallas/test.esp32.yaml +++ b/tests/components/dallas/test.esp32.yaml @@ -1,11 +1 @@ -dallas: - pin: 4 - -sensor: - - platform: dallas - address: 0x1C0000031EDD2A28 - name: Dallas Temperature - resolution: 9 - - platform: dallas - index: 1 - name: Dallas Temperature +<<: !include common.yaml diff --git a/tests/components/dallas/test.esp8266.yaml b/tests/components/dallas/test.esp8266.yaml index 7975977107..dade44d145 100644 --- a/tests/components/dallas/test.esp8266.yaml +++ b/tests/components/dallas/test.esp8266.yaml @@ -1,11 +1 @@ -dallas: - pin: 4 - -sensor: - - platform: dallas - address: 0x1C0000031EDD2A28 - name: Dallas Temperature - resolution: 9 - - platform: dallas - index: 1 - name: Dallas Temperature +<<: !include common.yaml diff --git a/tests/components/dallas/test.rp2040.yaml b/tests/components/dallas/test.rp2040.yaml index 7975977107..dade44d145 100644 --- a/tests/components/dallas/test.rp2040.yaml +++ b/tests/components/dallas/test.rp2040.yaml @@ -1,11 +1 @@ -dallas: - pin: 4 - -sensor: - - platform: dallas - address: 0x1C0000031EDD2A28 - name: Dallas Temperature - resolution: 9 - - platform: dallas - index: 1 - name: Dallas Temperature +<<: !include common.yaml diff --git a/tests/components/datetime/common.yaml b/tests/components/datetime/common.yaml new file mode 100644 index 0000000000..4e26b68121 --- /dev/null +++ b/tests/components/datetime/common.yaml @@ -0,0 +1,3 @@ +datetime: + +time: diff --git a/tests/components/datetime/test.all.yaml b/tests/components/datetime/test.all.yaml index 4e26b68121..dade44d145 100644 --- a/tests/components/datetime/test.all.yaml +++ b/tests/components/datetime/test.all.yaml @@ -1,3 +1 @@ -datetime: - -time: +<<: !include common.yaml diff --git a/tests/components/debug/common.yaml b/tests/components/debug/common.yaml new file mode 100644 index 0000000000..5845beaa80 --- /dev/null +++ b/tests/components/debug/common.yaml @@ -0,0 +1 @@ +debug: diff --git a/tests/components/debug/test.esp32-c3-idf.yaml b/tests/components/debug/test.esp32-c3-idf.yaml index 5845beaa80..dade44d145 100644 --- a/tests/components/debug/test.esp32-c3-idf.yaml +++ b/tests/components/debug/test.esp32-c3-idf.yaml @@ -1 +1 @@ -debug: +<<: !include common.yaml diff --git a/tests/components/debug/test.esp32-c3.yaml b/tests/components/debug/test.esp32-c3.yaml index 5845beaa80..dade44d145 100644 --- a/tests/components/debug/test.esp32-c3.yaml +++ b/tests/components/debug/test.esp32-c3.yaml @@ -1 +1 @@ -debug: +<<: !include common.yaml diff --git a/tests/components/debug/test.esp32-idf.yaml b/tests/components/debug/test.esp32-idf.yaml index 5845beaa80..dade44d145 100644 --- a/tests/components/debug/test.esp32-idf.yaml +++ b/tests/components/debug/test.esp32-idf.yaml @@ -1 +1 @@ -debug: +<<: !include common.yaml diff --git a/tests/components/debug/test.esp32.yaml b/tests/components/debug/test.esp32.yaml index 5845beaa80..dade44d145 100644 --- a/tests/components/debug/test.esp32.yaml +++ b/tests/components/debug/test.esp32.yaml @@ -1 +1 @@ -debug: +<<: !include common.yaml diff --git a/tests/components/debug/test.esp8266.yaml b/tests/components/debug/test.esp8266.yaml index 5845beaa80..dade44d145 100644 --- a/tests/components/debug/test.esp8266.yaml +++ b/tests/components/debug/test.esp8266.yaml @@ -1 +1 @@ -debug: +<<: !include common.yaml diff --git a/tests/components/debug/test.host.yaml b/tests/components/debug/test.host.yaml index 5845beaa80..dade44d145 100644 --- a/tests/components/debug/test.host.yaml +++ b/tests/components/debug/test.host.yaml @@ -1 +1 @@ -debug: +<<: !include common.yaml diff --git a/tests/components/debug/test.rp2040.yaml b/tests/components/debug/test.rp2040.yaml index 5845beaa80..dade44d145 100644 --- a/tests/components/debug/test.rp2040.yaml +++ b/tests/components/debug/test.rp2040.yaml @@ -1 +1 @@ -debug: +<<: !include common.yaml diff --git a/tests/components/dht/common.yaml b/tests/components/dht/common.yaml new file mode 100644 index 0000000000..f134a324ca --- /dev/null +++ b/tests/components/dht/common.yaml @@ -0,0 +1,11 @@ +sensor: + - platform: dht + pin: 4 + model: AM2302 + update_interval: 15s + temperature: + id: dht_temperature + name: DHT Temperature + humidity: + id: dht_humidity + name: DHT Humidity diff --git a/tests/components/dht/test.esp32-c3-idf.yaml b/tests/components/dht/test.esp32-c3-idf.yaml index f134a324ca..dade44d145 100644 --- a/tests/components/dht/test.esp32-c3-idf.yaml +++ b/tests/components/dht/test.esp32-c3-idf.yaml @@ -1,11 +1 @@ -sensor: - - platform: dht - pin: 4 - model: AM2302 - update_interval: 15s - temperature: - id: dht_temperature - name: DHT Temperature - humidity: - id: dht_humidity - name: DHT Humidity +<<: !include common.yaml diff --git a/tests/components/dht/test.esp32-c3.yaml b/tests/components/dht/test.esp32-c3.yaml index f134a324ca..dade44d145 100644 --- a/tests/components/dht/test.esp32-c3.yaml +++ b/tests/components/dht/test.esp32-c3.yaml @@ -1,11 +1 @@ -sensor: - - platform: dht - pin: 4 - model: AM2302 - update_interval: 15s - temperature: - id: dht_temperature - name: DHT Temperature - humidity: - id: dht_humidity - name: DHT Humidity +<<: !include common.yaml diff --git a/tests/components/dht/test.esp32-idf.yaml b/tests/components/dht/test.esp32-idf.yaml index f134a324ca..dade44d145 100644 --- a/tests/components/dht/test.esp32-idf.yaml +++ b/tests/components/dht/test.esp32-idf.yaml @@ -1,11 +1 @@ -sensor: - - platform: dht - pin: 4 - model: AM2302 - update_interval: 15s - temperature: - id: dht_temperature - name: DHT Temperature - humidity: - id: dht_humidity - name: DHT Humidity +<<: !include common.yaml diff --git a/tests/components/dht/test.esp32.yaml b/tests/components/dht/test.esp32.yaml index f134a324ca..dade44d145 100644 --- a/tests/components/dht/test.esp32.yaml +++ b/tests/components/dht/test.esp32.yaml @@ -1,11 +1 @@ -sensor: - - platform: dht - pin: 4 - model: AM2302 - update_interval: 15s - temperature: - id: dht_temperature - name: DHT Temperature - humidity: - id: dht_humidity - name: DHT Humidity +<<: !include common.yaml diff --git a/tests/components/dht/test.esp8266.yaml b/tests/components/dht/test.esp8266.yaml index f134a324ca..dade44d145 100644 --- a/tests/components/dht/test.esp8266.yaml +++ b/tests/components/dht/test.esp8266.yaml @@ -1,11 +1 @@ -sensor: - - platform: dht - pin: 4 - model: AM2302 - update_interval: 15s - temperature: - id: dht_temperature - name: DHT Temperature - humidity: - id: dht_humidity - name: DHT Humidity +<<: !include common.yaml diff --git a/tests/components/dht/test.rp2040.yaml b/tests/components/dht/test.rp2040.yaml index f134a324ca..dade44d145 100644 --- a/tests/components/dht/test.rp2040.yaml +++ b/tests/components/dht/test.rp2040.yaml @@ -1,11 +1 @@ -sensor: - - platform: dht - pin: 4 - model: AM2302 - update_interval: 15s - temperature: - id: dht_temperature - name: DHT Temperature - humidity: - id: dht_humidity - name: DHT Humidity +<<: !include common.yaml diff --git a/tests/components/display/common.yaml b/tests/components/display/common.yaml new file mode 100644 index 0000000000..a22aa76780 --- /dev/null +++ b/tests/components/display/common.yaml @@ -0,0 +1,35 @@ +spi: + - id: spi_main_lcd + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +display: + - platform: ili9xxx + id: main_lcd + model: ili9342 + cs_pin: 12 + dc_pin: 13 + reset_pin: 21 + lambda: |- + // Draw an analog clock in the center of the screen + int centerX = it.get_width() / 2; + int centerY = it.get_height() / 2; + int radius = min(it.get_width(), it.get_height()) / 4; + + // Draw border + it.circle(centerX, centerY, radius); + + // Draw hour ticks + for(int h = 0; h < 12; h++) { + int hourAngle = (h * 30) - 90; + + it.line_at_angle(centerX, centerY, hourAngle, radius - 10, radius); + } + + // Draw minute ticks + for(int m = 0; m < 60; m++) { + int minuteAngle = (m * 6) - 90; + + it.line_at_angle(centerX, centerY, minuteAngle, radius - 5, radius); + } diff --git a/tests/components/display/test.esp32.yaml b/tests/components/display/test.esp32.yaml index a22aa76780..dade44d145 100644 --- a/tests/components/display/test.esp32.yaml +++ b/tests/components/display/test.esp32.yaml @@ -1,35 +1 @@ -spi: - - id: spi_main_lcd - clk_pin: 16 - mosi_pin: 17 - miso_pin: 15 - -display: - - platform: ili9xxx - id: main_lcd - model: ili9342 - cs_pin: 12 - dc_pin: 13 - reset_pin: 21 - lambda: |- - // Draw an analog clock in the center of the screen - int centerX = it.get_width() / 2; - int centerY = it.get_height() / 2; - int radius = min(it.get_width(), it.get_height()) / 4; - - // Draw border - it.circle(centerX, centerY, radius); - - // Draw hour ticks - for(int h = 0; h < 12; h++) { - int hourAngle = (h * 30) - 90; - - it.line_at_angle(centerX, centerY, hourAngle, radius - 10, radius); - } - - // Draw minute ticks - for(int m = 0; m < 60; m++) { - int minuteAngle = (m * 6) - 90; - - it.line_at_angle(centerX, centerY, minuteAngle, radius - 5, radius); - } +<<: !include common.yaml diff --git a/tests/components/duty_cycle/common.yaml b/tests/components/duty_cycle/common.yaml new file mode 100644 index 0000000000..2b7f31efbd --- /dev/null +++ b/tests/components/duty_cycle/common.yaml @@ -0,0 +1,4 @@ +sensor: + - platform: duty_cycle + pin: 4 + name: Duty Cycle Sensor diff --git a/tests/components/duty_cycle/test.esp32-c3-idf.yaml b/tests/components/duty_cycle/test.esp32-c3-idf.yaml index 2b7f31efbd..dade44d145 100644 --- a/tests/components/duty_cycle/test.esp32-c3-idf.yaml +++ b/tests/components/duty_cycle/test.esp32-c3-idf.yaml @@ -1,4 +1 @@ -sensor: - - platform: duty_cycle - pin: 4 - name: Duty Cycle Sensor +<<: !include common.yaml diff --git a/tests/components/duty_cycle/test.esp32-c3.yaml b/tests/components/duty_cycle/test.esp32-c3.yaml index 2b7f31efbd..dade44d145 100644 --- a/tests/components/duty_cycle/test.esp32-c3.yaml +++ b/tests/components/duty_cycle/test.esp32-c3.yaml @@ -1,4 +1 @@ -sensor: - - platform: duty_cycle - pin: 4 - name: Duty Cycle Sensor +<<: !include common.yaml diff --git a/tests/components/duty_cycle/test.esp32-idf.yaml b/tests/components/duty_cycle/test.esp32-idf.yaml index 2b7f31efbd..dade44d145 100644 --- a/tests/components/duty_cycle/test.esp32-idf.yaml +++ b/tests/components/duty_cycle/test.esp32-idf.yaml @@ -1,4 +1 @@ -sensor: - - platform: duty_cycle - pin: 4 - name: Duty Cycle Sensor +<<: !include common.yaml diff --git a/tests/components/duty_cycle/test.esp32.yaml b/tests/components/duty_cycle/test.esp32.yaml index 2b7f31efbd..dade44d145 100644 --- a/tests/components/duty_cycle/test.esp32.yaml +++ b/tests/components/duty_cycle/test.esp32.yaml @@ -1,4 +1 @@ -sensor: - - platform: duty_cycle - pin: 4 - name: Duty Cycle Sensor +<<: !include common.yaml diff --git a/tests/components/duty_cycle/test.esp8266.yaml b/tests/components/duty_cycle/test.esp8266.yaml index 2b7f31efbd..dade44d145 100644 --- a/tests/components/duty_cycle/test.esp8266.yaml +++ b/tests/components/duty_cycle/test.esp8266.yaml @@ -1,4 +1 @@ -sensor: - - platform: duty_cycle - pin: 4 - name: Duty Cycle Sensor +<<: !include common.yaml diff --git a/tests/components/duty_cycle/test.rp2040.yaml b/tests/components/duty_cycle/test.rp2040.yaml index 2b7f31efbd..dade44d145 100644 --- a/tests/components/duty_cycle/test.rp2040.yaml +++ b/tests/components/duty_cycle/test.rp2040.yaml @@ -1,4 +1 @@ -sensor: - - platform: duty_cycle - pin: 4 - name: Duty Cycle Sensor +<<: !include common.yaml diff --git a/tests/components/duty_time/common.yaml b/tests/components/duty_time/common.yaml new file mode 100644 index 0000000000..28fa4afd1c --- /dev/null +++ b/tests/components/duty_time/common.yaml @@ -0,0 +1,14 @@ +binary_sensor: + - platform: template + id: bin1 + lambda: |- + if (millis() > 10000) { + return true; + } else { + return false; + } + +sensor: + - platform: duty_time + name: Duty Time + sensor: bin1 diff --git a/tests/components/duty_time/test.esp32-c3-idf.yaml b/tests/components/duty_time/test.esp32-c3-idf.yaml index 28fa4afd1c..dade44d145 100644 --- a/tests/components/duty_time/test.esp32-c3-idf.yaml +++ b/tests/components/duty_time/test.esp32-c3-idf.yaml @@ -1,14 +1 @@ -binary_sensor: - - platform: template - id: bin1 - lambda: |- - if (millis() > 10000) { - return true; - } else { - return false; - } - -sensor: - - platform: duty_time - name: Duty Time - sensor: bin1 +<<: !include common.yaml diff --git a/tests/components/duty_time/test.esp32-c3.yaml b/tests/components/duty_time/test.esp32-c3.yaml index 28fa4afd1c..dade44d145 100644 --- a/tests/components/duty_time/test.esp32-c3.yaml +++ b/tests/components/duty_time/test.esp32-c3.yaml @@ -1,14 +1 @@ -binary_sensor: - - platform: template - id: bin1 - lambda: |- - if (millis() > 10000) { - return true; - } else { - return false; - } - -sensor: - - platform: duty_time - name: Duty Time - sensor: bin1 +<<: !include common.yaml diff --git a/tests/components/duty_time/test.esp32-idf.yaml b/tests/components/duty_time/test.esp32-idf.yaml index 28fa4afd1c..dade44d145 100644 --- a/tests/components/duty_time/test.esp32-idf.yaml +++ b/tests/components/duty_time/test.esp32-idf.yaml @@ -1,14 +1 @@ -binary_sensor: - - platform: template - id: bin1 - lambda: |- - if (millis() > 10000) { - return true; - } else { - return false; - } - -sensor: - - platform: duty_time - name: Duty Time - sensor: bin1 +<<: !include common.yaml diff --git a/tests/components/duty_time/test.esp32.yaml b/tests/components/duty_time/test.esp32.yaml index 28fa4afd1c..dade44d145 100644 --- a/tests/components/duty_time/test.esp32.yaml +++ b/tests/components/duty_time/test.esp32.yaml @@ -1,14 +1 @@ -binary_sensor: - - platform: template - id: bin1 - lambda: |- - if (millis() > 10000) { - return true; - } else { - return false; - } - -sensor: - - platform: duty_time - name: Duty Time - sensor: bin1 +<<: !include common.yaml diff --git a/tests/components/duty_time/test.esp8266.yaml b/tests/components/duty_time/test.esp8266.yaml index 28fa4afd1c..dade44d145 100644 --- a/tests/components/duty_time/test.esp8266.yaml +++ b/tests/components/duty_time/test.esp8266.yaml @@ -1,14 +1 @@ -binary_sensor: - - platform: template - id: bin1 - lambda: |- - if (millis() > 10000) { - return true; - } else { - return false; - } - -sensor: - - platform: duty_time - name: Duty Time - sensor: bin1 +<<: !include common.yaml diff --git a/tests/components/duty_time/test.rp2040.yaml b/tests/components/duty_time/test.rp2040.yaml index 28fa4afd1c..dade44d145 100644 --- a/tests/components/duty_time/test.rp2040.yaml +++ b/tests/components/duty_time/test.rp2040.yaml @@ -1,14 +1 @@ -binary_sensor: - - platform: template - id: bin1 - lambda: |- - if (millis() > 10000) { - return true; - } else { - return false; - } - -sensor: - - platform: duty_time - name: Duty Time - sensor: bin1 +<<: !include common.yaml diff --git a/tests/components/endstop/common.yaml b/tests/components/endstop/common.yaml new file mode 100644 index 0000000000..341fbf7260 --- /dev/null +++ b/tests/components/endstop/common.yaml @@ -0,0 +1,33 @@ +binary_sensor: + - platform: template + id: bin1 + lambda: |- + if (millis() > 10000) { + return true; + } else { + return false; + } + +switch: + - platform: template + id: template_switch1 + optimistic: true + - platform: template + id: template_switch2 + optimistic: true + +cover: + - platform: endstop + id: endstop_cover + name: Endstop Cover + stop_action: + - switch.turn_on: template_switch1 + open_endstop: bin1 + open_action: + - switch.turn_on: template_switch1 + open_duration: 5min + close_endstop: bin1 + close_action: + - switch.turn_on: template_switch2 + close_duration: 4.5min + max_duration: 10min diff --git a/tests/components/endstop/test.esp32-c3-idf.yaml b/tests/components/endstop/test.esp32-c3-idf.yaml index 341fbf7260..dade44d145 100644 --- a/tests/components/endstop/test.esp32-c3-idf.yaml +++ b/tests/components/endstop/test.esp32-c3-idf.yaml @@ -1,33 +1 @@ -binary_sensor: - - platform: template - id: bin1 - lambda: |- - if (millis() > 10000) { - return true; - } else { - return false; - } - -switch: - - platform: template - id: template_switch1 - optimistic: true - - platform: template - id: template_switch2 - optimistic: true - -cover: - - platform: endstop - id: endstop_cover - name: Endstop Cover - stop_action: - - switch.turn_on: template_switch1 - open_endstop: bin1 - open_action: - - switch.turn_on: template_switch1 - open_duration: 5min - close_endstop: bin1 - close_action: - - switch.turn_on: template_switch2 - close_duration: 4.5min - max_duration: 10min +<<: !include common.yaml diff --git a/tests/components/endstop/test.esp32-c3.yaml b/tests/components/endstop/test.esp32-c3.yaml index 341fbf7260..dade44d145 100644 --- a/tests/components/endstop/test.esp32-c3.yaml +++ b/tests/components/endstop/test.esp32-c3.yaml @@ -1,33 +1 @@ -binary_sensor: - - platform: template - id: bin1 - lambda: |- - if (millis() > 10000) { - return true; - } else { - return false; - } - -switch: - - platform: template - id: template_switch1 - optimistic: true - - platform: template - id: template_switch2 - optimistic: true - -cover: - - platform: endstop - id: endstop_cover - name: Endstop Cover - stop_action: - - switch.turn_on: template_switch1 - open_endstop: bin1 - open_action: - - switch.turn_on: template_switch1 - open_duration: 5min - close_endstop: bin1 - close_action: - - switch.turn_on: template_switch2 - close_duration: 4.5min - max_duration: 10min +<<: !include common.yaml diff --git a/tests/components/endstop/test.esp32-idf.yaml b/tests/components/endstop/test.esp32-idf.yaml index 341fbf7260..dade44d145 100644 --- a/tests/components/endstop/test.esp32-idf.yaml +++ b/tests/components/endstop/test.esp32-idf.yaml @@ -1,33 +1 @@ -binary_sensor: - - platform: template - id: bin1 - lambda: |- - if (millis() > 10000) { - return true; - } else { - return false; - } - -switch: - - platform: template - id: template_switch1 - optimistic: true - - platform: template - id: template_switch2 - optimistic: true - -cover: - - platform: endstop - id: endstop_cover - name: Endstop Cover - stop_action: - - switch.turn_on: template_switch1 - open_endstop: bin1 - open_action: - - switch.turn_on: template_switch1 - open_duration: 5min - close_endstop: bin1 - close_action: - - switch.turn_on: template_switch2 - close_duration: 4.5min - max_duration: 10min +<<: !include common.yaml diff --git a/tests/components/endstop/test.esp32.yaml b/tests/components/endstop/test.esp32.yaml index 341fbf7260..dade44d145 100644 --- a/tests/components/endstop/test.esp32.yaml +++ b/tests/components/endstop/test.esp32.yaml @@ -1,33 +1 @@ -binary_sensor: - - platform: template - id: bin1 - lambda: |- - if (millis() > 10000) { - return true; - } else { - return false; - } - -switch: - - platform: template - id: template_switch1 - optimistic: true - - platform: template - id: template_switch2 - optimistic: true - -cover: - - platform: endstop - id: endstop_cover - name: Endstop Cover - stop_action: - - switch.turn_on: template_switch1 - open_endstop: bin1 - open_action: - - switch.turn_on: template_switch1 - open_duration: 5min - close_endstop: bin1 - close_action: - - switch.turn_on: template_switch2 - close_duration: 4.5min - max_duration: 10min +<<: !include common.yaml diff --git a/tests/components/endstop/test.esp8266.yaml b/tests/components/endstop/test.esp8266.yaml index 341fbf7260..dade44d145 100644 --- a/tests/components/endstop/test.esp8266.yaml +++ b/tests/components/endstop/test.esp8266.yaml @@ -1,33 +1 @@ -binary_sensor: - - platform: template - id: bin1 - lambda: |- - if (millis() > 10000) { - return true; - } else { - return false; - } - -switch: - - platform: template - id: template_switch1 - optimistic: true - - platform: template - id: template_switch2 - optimistic: true - -cover: - - platform: endstop - id: endstop_cover - name: Endstop Cover - stop_action: - - switch.turn_on: template_switch1 - open_endstop: bin1 - open_action: - - switch.turn_on: template_switch1 - open_duration: 5min - close_endstop: bin1 - close_action: - - switch.turn_on: template_switch2 - close_duration: 4.5min - max_duration: 10min +<<: !include common.yaml diff --git a/tests/components/endstop/test.rp2040.yaml b/tests/components/endstop/test.rp2040.yaml index 341fbf7260..dade44d145 100644 --- a/tests/components/endstop/test.rp2040.yaml +++ b/tests/components/endstop/test.rp2040.yaml @@ -1,33 +1 @@ -binary_sensor: - - platform: template - id: bin1 - lambda: |- - if (millis() > 10000) { - return true; - } else { - return false; - } - -switch: - - platform: template - id: template_switch1 - optimistic: true - - platform: template - id: template_switch2 - optimistic: true - -cover: - - platform: endstop - id: endstop_cover - name: Endstop Cover - stop_action: - - switch.turn_on: template_switch1 - open_endstop: bin1 - open_action: - - switch.turn_on: template_switch1 - open_duration: 5min - close_endstop: bin1 - close_action: - - switch.turn_on: template_switch2 - close_duration: 4.5min - max_duration: 10min +<<: !include common.yaml diff --git a/tests/components/esp32_ble/common.yaml b/tests/components/esp32_ble/common.yaml new file mode 100644 index 0000000000..76b35fc8f8 --- /dev/null +++ b/tests/components/esp32_ble/common.yaml @@ -0,0 +1,2 @@ +esp32_ble: + io_capability: keyboard_only diff --git a/tests/components/esp32_ble/test.esp32-c3-idf.yaml b/tests/components/esp32_ble/test.esp32-c3-idf.yaml index 76b35fc8f8..dade44d145 100644 --- a/tests/components/esp32_ble/test.esp32-c3-idf.yaml +++ b/tests/components/esp32_ble/test.esp32-c3-idf.yaml @@ -1,2 +1 @@ -esp32_ble: - io_capability: keyboard_only +<<: !include common.yaml diff --git a/tests/components/esp32_ble/test.esp32-c3.yaml b/tests/components/esp32_ble/test.esp32-c3.yaml index 76b35fc8f8..dade44d145 100644 --- a/tests/components/esp32_ble/test.esp32-c3.yaml +++ b/tests/components/esp32_ble/test.esp32-c3.yaml @@ -1,2 +1 @@ -esp32_ble: - io_capability: keyboard_only +<<: !include common.yaml diff --git a/tests/components/esp32_ble/test.esp32-idf.yaml b/tests/components/esp32_ble/test.esp32-idf.yaml index 76b35fc8f8..dade44d145 100644 --- a/tests/components/esp32_ble/test.esp32-idf.yaml +++ b/tests/components/esp32_ble/test.esp32-idf.yaml @@ -1,2 +1 @@ -esp32_ble: - io_capability: keyboard_only +<<: !include common.yaml diff --git a/tests/components/esp32_ble/test.esp32.yaml b/tests/components/esp32_ble/test.esp32.yaml index 76b35fc8f8..dade44d145 100644 --- a/tests/components/esp32_ble/test.esp32.yaml +++ b/tests/components/esp32_ble/test.esp32.yaml @@ -1,2 +1 @@ -esp32_ble: - io_capability: keyboard_only +<<: !include common.yaml diff --git a/tests/components/esp32_ble_beacon/common.yaml b/tests/components/esp32_ble_beacon/common.yaml new file mode 100644 index 0000000000..aafb0341d7 --- /dev/null +++ b/tests/components/esp32_ble_beacon/common.yaml @@ -0,0 +1,3 @@ +esp32_ble_beacon: + type: iBeacon + uuid: 'c29ce823-e67a-4e71-bff2-abaa32e77a98' diff --git a/tests/components/esp32_ble_beacon/test.esp32-c3-idf.yaml b/tests/components/esp32_ble_beacon/test.esp32-c3-idf.yaml index aafb0341d7..dade44d145 100644 --- a/tests/components/esp32_ble_beacon/test.esp32-c3-idf.yaml +++ b/tests/components/esp32_ble_beacon/test.esp32-c3-idf.yaml @@ -1,3 +1 @@ -esp32_ble_beacon: - type: iBeacon - uuid: 'c29ce823-e67a-4e71-bff2-abaa32e77a98' +<<: !include common.yaml diff --git a/tests/components/esp32_ble_beacon/test.esp32-c3.yaml b/tests/components/esp32_ble_beacon/test.esp32-c3.yaml index aafb0341d7..dade44d145 100644 --- a/tests/components/esp32_ble_beacon/test.esp32-c3.yaml +++ b/tests/components/esp32_ble_beacon/test.esp32-c3.yaml @@ -1,3 +1 @@ -esp32_ble_beacon: - type: iBeacon - uuid: 'c29ce823-e67a-4e71-bff2-abaa32e77a98' +<<: !include common.yaml diff --git a/tests/components/esp32_ble_beacon/test.esp32-idf.yaml b/tests/components/esp32_ble_beacon/test.esp32-idf.yaml index aafb0341d7..dade44d145 100644 --- a/tests/components/esp32_ble_beacon/test.esp32-idf.yaml +++ b/tests/components/esp32_ble_beacon/test.esp32-idf.yaml @@ -1,3 +1 @@ -esp32_ble_beacon: - type: iBeacon - uuid: 'c29ce823-e67a-4e71-bff2-abaa32e77a98' +<<: !include common.yaml diff --git a/tests/components/esp32_ble_beacon/test.esp32.yaml b/tests/components/esp32_ble_beacon/test.esp32.yaml index aafb0341d7..dade44d145 100644 --- a/tests/components/esp32_ble_beacon/test.esp32.yaml +++ b/tests/components/esp32_ble_beacon/test.esp32.yaml @@ -1,3 +1 @@ -esp32_ble_beacon: - type: iBeacon - uuid: 'c29ce823-e67a-4e71-bff2-abaa32e77a98' +<<: !include common.yaml diff --git a/tests/components/esp32_ble_client/common.yaml b/tests/components/esp32_ble_client/common.yaml new file mode 100644 index 0000000000..33b7205bf2 --- /dev/null +++ b/tests/components/esp32_ble_client/common.yaml @@ -0,0 +1,5 @@ +esp32_ble_tracker: + +ble_client: + - mac_address: 01:02:03:04:05:06 + id: blec diff --git a/tests/components/esp32_ble_client/test.esp32-c3-idf.yaml b/tests/components/esp32_ble_client/test.esp32-c3-idf.yaml index 33b7205bf2..dade44d145 100644 --- a/tests/components/esp32_ble_client/test.esp32-c3-idf.yaml +++ b/tests/components/esp32_ble_client/test.esp32-c3-idf.yaml @@ -1,5 +1 @@ -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: blec +<<: !include common.yaml diff --git a/tests/components/esp32_ble_client/test.esp32-c3.yaml b/tests/components/esp32_ble_client/test.esp32-c3.yaml index 33b7205bf2..dade44d145 100644 --- a/tests/components/esp32_ble_client/test.esp32-c3.yaml +++ b/tests/components/esp32_ble_client/test.esp32-c3.yaml @@ -1,5 +1 @@ -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: blec +<<: !include common.yaml diff --git a/tests/components/esp32_ble_client/test.esp32-idf.yaml b/tests/components/esp32_ble_client/test.esp32-idf.yaml index 33b7205bf2..dade44d145 100644 --- a/tests/components/esp32_ble_client/test.esp32-idf.yaml +++ b/tests/components/esp32_ble_client/test.esp32-idf.yaml @@ -1,5 +1 @@ -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: blec +<<: !include common.yaml diff --git a/tests/components/esp32_ble_client/test.esp32.yaml b/tests/components/esp32_ble_client/test.esp32.yaml index 33b7205bf2..dade44d145 100644 --- a/tests/components/esp32_ble_client/test.esp32.yaml +++ b/tests/components/esp32_ble_client/test.esp32.yaml @@ -1,5 +1 @@ -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: blec +<<: !include common.yaml diff --git a/tests/components/esp32_ble_server/common.yaml b/tests/components/esp32_ble_server/common.yaml new file mode 100644 index 0000000000..29a5407f84 --- /dev/null +++ b/tests/components/esp32_ble_server/common.yaml @@ -0,0 +1,3 @@ +esp32_ble_server: + id: ble + manufacturer_data: [0x72, 0x4, 0x00, 0x23] diff --git a/tests/components/esp32_ble_server/test.esp32-c3-idf.yaml b/tests/components/esp32_ble_server/test.esp32-c3-idf.yaml index 29a5407f84..dade44d145 100644 --- a/tests/components/esp32_ble_server/test.esp32-c3-idf.yaml +++ b/tests/components/esp32_ble_server/test.esp32-c3-idf.yaml @@ -1,3 +1 @@ -esp32_ble_server: - id: ble - manufacturer_data: [0x72, 0x4, 0x00, 0x23] +<<: !include common.yaml diff --git a/tests/components/esp32_ble_server/test.esp32-c3.yaml b/tests/components/esp32_ble_server/test.esp32-c3.yaml index 29a5407f84..dade44d145 100644 --- a/tests/components/esp32_ble_server/test.esp32-c3.yaml +++ b/tests/components/esp32_ble_server/test.esp32-c3.yaml @@ -1,3 +1 @@ -esp32_ble_server: - id: ble - manufacturer_data: [0x72, 0x4, 0x00, 0x23] +<<: !include common.yaml diff --git a/tests/components/esp32_ble_server/test.esp32-idf.yaml b/tests/components/esp32_ble_server/test.esp32-idf.yaml index 29a5407f84..dade44d145 100644 --- a/tests/components/esp32_ble_server/test.esp32-idf.yaml +++ b/tests/components/esp32_ble_server/test.esp32-idf.yaml @@ -1,3 +1 @@ -esp32_ble_server: - id: ble - manufacturer_data: [0x72, 0x4, 0x00, 0x23] +<<: !include common.yaml diff --git a/tests/components/esp32_ble_server/test.esp32.yaml b/tests/components/esp32_ble_server/test.esp32.yaml index 29a5407f84..dade44d145 100644 --- a/tests/components/esp32_ble_server/test.esp32.yaml +++ b/tests/components/esp32_ble_server/test.esp32.yaml @@ -1,3 +1 @@ -esp32_ble_server: - id: ble - manufacturer_data: [0x72, 0x4, 0x00, 0x23] +<<: !include common.yaml diff --git a/tests/components/esp32_ble_tracker/common.yaml b/tests/components/esp32_ble_tracker/common.yaml new file mode 100644 index 0000000000..ef23635c9e --- /dev/null +++ b/tests/components/esp32_ble_tracker/common.yaml @@ -0,0 +1,41 @@ +esphome: + on_boot: + then: + - esp32_ble_tracker.start_scan + - esp32_ble_tracker.stop_scan + +esp32_ble_tracker: + on_ble_advertise: + - mac_address: + - AA:BB:CC:DD:EE:FF + - FF:EE:DD:CC:BB:AA + then: + # yamllint disable rule:line-length + - lambda: !lambda |- + ESP_LOGD("main", "The device address (%s) exists in list", x.address_str().c_str()); + # yamllint enable rule:line-length + - mac_address: AC:37:43:77:5F:4C + then: + # yamllint disable rule:line-length + - lambda: !lambda |- + ESP_LOGD("main", "The device address is %s", x.address_str().c_str()); + # yamllint enable rule:line-length + - then: + # yamllint disable rule:line-length + - lambda: !lambda |- + ESP_LOGD("main", "The device address is %s", x.address_str().c_str()); + # yamllint enable rule:line-length + on_ble_service_data_advertise: + - service_uuid: ABCD + then: + - lambda: !lambda |- + ESP_LOGD("main", "Length of service data is %i", x.size()); + on_ble_manufacturer_data_advertise: + - manufacturer_id: ABCD + then: + - lambda: !lambda |- + ESP_LOGD("main", "Length of manufacturer data is %i", x.size()); + on_scan_end: + - then: + - lambda: |- + ESP_LOGD("ble_auto", "The scan has ended!"); diff --git a/tests/components/esp32_ble_tracker/test.esp32-c3-idf.yaml b/tests/components/esp32_ble_tracker/test.esp32-c3-idf.yaml index ef23635c9e..dade44d145 100644 --- a/tests/components/esp32_ble_tracker/test.esp32-c3-idf.yaml +++ b/tests/components/esp32_ble_tracker/test.esp32-c3-idf.yaml @@ -1,41 +1 @@ -esphome: - on_boot: - then: - - esp32_ble_tracker.start_scan - - esp32_ble_tracker.stop_scan - -esp32_ble_tracker: - on_ble_advertise: - - mac_address: - - AA:BB:CC:DD:EE:FF - - FF:EE:DD:CC:BB:AA - then: - # yamllint disable rule:line-length - - lambda: !lambda |- - ESP_LOGD("main", "The device address (%s) exists in list", x.address_str().c_str()); - # yamllint enable rule:line-length - - mac_address: AC:37:43:77:5F:4C - then: - # yamllint disable rule:line-length - - lambda: !lambda |- - ESP_LOGD("main", "The device address is %s", x.address_str().c_str()); - # yamllint enable rule:line-length - - then: - # yamllint disable rule:line-length - - lambda: !lambda |- - ESP_LOGD("main", "The device address is %s", x.address_str().c_str()); - # yamllint enable rule:line-length - on_ble_service_data_advertise: - - service_uuid: ABCD - then: - - lambda: !lambda |- - ESP_LOGD("main", "Length of service data is %i", x.size()); - on_ble_manufacturer_data_advertise: - - manufacturer_id: ABCD - then: - - lambda: !lambda |- - ESP_LOGD("main", "Length of manufacturer data is %i", x.size()); - on_scan_end: - - then: - - lambda: |- - ESP_LOGD("ble_auto", "The scan has ended!"); +<<: !include common.yaml diff --git a/tests/components/esp32_ble_tracker/test.esp32-c3.yaml b/tests/components/esp32_ble_tracker/test.esp32-c3.yaml index ef23635c9e..dade44d145 100644 --- a/tests/components/esp32_ble_tracker/test.esp32-c3.yaml +++ b/tests/components/esp32_ble_tracker/test.esp32-c3.yaml @@ -1,41 +1 @@ -esphome: - on_boot: - then: - - esp32_ble_tracker.start_scan - - esp32_ble_tracker.stop_scan - -esp32_ble_tracker: - on_ble_advertise: - - mac_address: - - AA:BB:CC:DD:EE:FF - - FF:EE:DD:CC:BB:AA - then: - # yamllint disable rule:line-length - - lambda: !lambda |- - ESP_LOGD("main", "The device address (%s) exists in list", x.address_str().c_str()); - # yamllint enable rule:line-length - - mac_address: AC:37:43:77:5F:4C - then: - # yamllint disable rule:line-length - - lambda: !lambda |- - ESP_LOGD("main", "The device address is %s", x.address_str().c_str()); - # yamllint enable rule:line-length - - then: - # yamllint disable rule:line-length - - lambda: !lambda |- - ESP_LOGD("main", "The device address is %s", x.address_str().c_str()); - # yamllint enable rule:line-length - on_ble_service_data_advertise: - - service_uuid: ABCD - then: - - lambda: !lambda |- - ESP_LOGD("main", "Length of service data is %i", x.size()); - on_ble_manufacturer_data_advertise: - - manufacturer_id: ABCD - then: - - lambda: !lambda |- - ESP_LOGD("main", "Length of manufacturer data is %i", x.size()); - on_scan_end: - - then: - - lambda: |- - ESP_LOGD("ble_auto", "The scan has ended!"); +<<: !include common.yaml diff --git a/tests/components/esp32_ble_tracker/test.esp32-idf.yaml b/tests/components/esp32_ble_tracker/test.esp32-idf.yaml index ef23635c9e..dade44d145 100644 --- a/tests/components/esp32_ble_tracker/test.esp32-idf.yaml +++ b/tests/components/esp32_ble_tracker/test.esp32-idf.yaml @@ -1,41 +1 @@ -esphome: - on_boot: - then: - - esp32_ble_tracker.start_scan - - esp32_ble_tracker.stop_scan - -esp32_ble_tracker: - on_ble_advertise: - - mac_address: - - AA:BB:CC:DD:EE:FF - - FF:EE:DD:CC:BB:AA - then: - # yamllint disable rule:line-length - - lambda: !lambda |- - ESP_LOGD("main", "The device address (%s) exists in list", x.address_str().c_str()); - # yamllint enable rule:line-length - - mac_address: AC:37:43:77:5F:4C - then: - # yamllint disable rule:line-length - - lambda: !lambda |- - ESP_LOGD("main", "The device address is %s", x.address_str().c_str()); - # yamllint enable rule:line-length - - then: - # yamllint disable rule:line-length - - lambda: !lambda |- - ESP_LOGD("main", "The device address is %s", x.address_str().c_str()); - # yamllint enable rule:line-length - on_ble_service_data_advertise: - - service_uuid: ABCD - then: - - lambda: !lambda |- - ESP_LOGD("main", "Length of service data is %i", x.size()); - on_ble_manufacturer_data_advertise: - - manufacturer_id: ABCD - then: - - lambda: !lambda |- - ESP_LOGD("main", "Length of manufacturer data is %i", x.size()); - on_scan_end: - - then: - - lambda: |- - ESP_LOGD("ble_auto", "The scan has ended!"); +<<: !include common.yaml diff --git a/tests/components/esp32_ble_tracker/test.esp32.yaml b/tests/components/esp32_ble_tracker/test.esp32.yaml index ef23635c9e..dade44d145 100644 --- a/tests/components/esp32_ble_tracker/test.esp32.yaml +++ b/tests/components/esp32_ble_tracker/test.esp32.yaml @@ -1,41 +1 @@ -esphome: - on_boot: - then: - - esp32_ble_tracker.start_scan - - esp32_ble_tracker.stop_scan - -esp32_ble_tracker: - on_ble_advertise: - - mac_address: - - AA:BB:CC:DD:EE:FF - - FF:EE:DD:CC:BB:AA - then: - # yamllint disable rule:line-length - - lambda: !lambda |- - ESP_LOGD("main", "The device address (%s) exists in list", x.address_str().c_str()); - # yamllint enable rule:line-length - - mac_address: AC:37:43:77:5F:4C - then: - # yamllint disable rule:line-length - - lambda: !lambda |- - ESP_LOGD("main", "The device address is %s", x.address_str().c_str()); - # yamllint enable rule:line-length - - then: - # yamllint disable rule:line-length - - lambda: !lambda |- - ESP_LOGD("main", "The device address is %s", x.address_str().c_str()); - # yamllint enable rule:line-length - on_ble_service_data_advertise: - - service_uuid: ABCD - then: - - lambda: !lambda |- - ESP_LOGD("main", "Length of service data is %i", x.size()); - on_ble_manufacturer_data_advertise: - - manufacturer_id: ABCD - then: - - lambda: !lambda |- - ESP_LOGD("main", "Length of manufacturer data is %i", x.size()); - on_scan_end: - - then: - - lambda: |- - ESP_LOGD("ble_auto", "The scan has ended!"); +<<: !include common.yaml diff --git a/tests/components/esp32_camera/common.yaml b/tests/components/esp32_camera/common.yaml new file mode 100644 index 0000000000..2f5f792f1c --- /dev/null +++ b/tests/components/esp32_camera/common.yaml @@ -0,0 +1,28 @@ +esp32_camera: + name: ESP32 Camera + data_pins: + - number: 17 + - number: 35 + - number: 34 + - number: 5 + - number: 39 + - number: 18 + - number: 36 + - number: 19 + vsync_pin: 22 + href_pin: 26 + pixel_clock_pin: 21 + external_clock: + pin: 27 + frequency: 20MHz + i2c_pins: + sda: 25 + scl: 23 + reset_pin: 15 + power_down_pin: 1 + resolution: 640x480 + jpeg_quality: 10 + on_image: + then: + - lambda: |- + ESP_LOGD("main", "image len=%d, data=%c", image.length, image.data[0]); diff --git a/tests/components/esp32_camera/test.esp32-idf.yaml b/tests/components/esp32_camera/test.esp32-idf.yaml index 2f5f792f1c..dade44d145 100644 --- a/tests/components/esp32_camera/test.esp32-idf.yaml +++ b/tests/components/esp32_camera/test.esp32-idf.yaml @@ -1,28 +1 @@ -esp32_camera: - name: ESP32 Camera - data_pins: - - number: 17 - - number: 35 - - number: 34 - - number: 5 - - number: 39 - - number: 18 - - number: 36 - - number: 19 - vsync_pin: 22 - href_pin: 26 - pixel_clock_pin: 21 - external_clock: - pin: 27 - frequency: 20MHz - i2c_pins: - sda: 25 - scl: 23 - reset_pin: 15 - power_down_pin: 1 - resolution: 640x480 - jpeg_quality: 10 - on_image: - then: - - lambda: |- - ESP_LOGD("main", "image len=%d, data=%c", image.length, image.data[0]); +<<: !include common.yaml diff --git a/tests/components/esp32_camera/test.esp32.yaml b/tests/components/esp32_camera/test.esp32.yaml index 2f5f792f1c..dade44d145 100644 --- a/tests/components/esp32_camera/test.esp32.yaml +++ b/tests/components/esp32_camera/test.esp32.yaml @@ -1,28 +1 @@ -esp32_camera: - name: ESP32 Camera - data_pins: - - number: 17 - - number: 35 - - number: 34 - - number: 5 - - number: 39 - - number: 18 - - number: 36 - - number: 19 - vsync_pin: 22 - href_pin: 26 - pixel_clock_pin: 21 - external_clock: - pin: 27 - frequency: 20MHz - i2c_pins: - sda: 25 - scl: 23 - reset_pin: 15 - power_down_pin: 1 - resolution: 640x480 - jpeg_quality: 10 - on_image: - then: - - lambda: |- - ESP_LOGD("main", "image len=%d, data=%c", image.length, image.data[0]); +<<: !include common.yaml diff --git a/tests/components/esp32_camera_web_server/common.yaml b/tests/components/esp32_camera_web_server/common.yaml new file mode 100644 index 0000000000..5edefdf0a8 --- /dev/null +++ b/tests/components/esp32_camera_web_server/common.yaml @@ -0,0 +1,34 @@ +esp32_camera: + name: ESP32 Camera + data_pins: + - number: 17 + - number: 35 + - number: 34 + - number: 5 + - number: 39 + - number: 18 + - number: 36 + - number: 19 + vsync_pin: 22 + href_pin: 26 + pixel_clock_pin: 21 + external_clock: + pin: 27 + frequency: 20MHz + i2c_pins: + sda: 25 + scl: 23 + reset_pin: 15 + power_down_pin: 1 + resolution: 640x480 + jpeg_quality: 10 + on_image: + then: + - lambda: |- + ESP_LOGD("main", "image len=%d, data=%c", image.length, image.data[0]); + +esp32_camera_web_server: + - port: 8080 + mode: stream + - port: 8081 + mode: snapshot diff --git a/tests/components/esp32_camera_web_server/test.esp32-idf.yaml b/tests/components/esp32_camera_web_server/test.esp32-idf.yaml index 5edefdf0a8..dade44d145 100644 --- a/tests/components/esp32_camera_web_server/test.esp32-idf.yaml +++ b/tests/components/esp32_camera_web_server/test.esp32-idf.yaml @@ -1,34 +1 @@ -esp32_camera: - name: ESP32 Camera - data_pins: - - number: 17 - - number: 35 - - number: 34 - - number: 5 - - number: 39 - - number: 18 - - number: 36 - - number: 19 - vsync_pin: 22 - href_pin: 26 - pixel_clock_pin: 21 - external_clock: - pin: 27 - frequency: 20MHz - i2c_pins: - sda: 25 - scl: 23 - reset_pin: 15 - power_down_pin: 1 - resolution: 640x480 - jpeg_quality: 10 - on_image: - then: - - lambda: |- - ESP_LOGD("main", "image len=%d, data=%c", image.length, image.data[0]); - -esp32_camera_web_server: - - port: 8080 - mode: stream - - port: 8081 - mode: snapshot +<<: !include common.yaml diff --git a/tests/components/esp32_camera_web_server/test.esp32.yaml b/tests/components/esp32_camera_web_server/test.esp32.yaml index 5edefdf0a8..dade44d145 100644 --- a/tests/components/esp32_camera_web_server/test.esp32.yaml +++ b/tests/components/esp32_camera_web_server/test.esp32.yaml @@ -1,34 +1 @@ -esp32_camera: - name: ESP32 Camera - data_pins: - - number: 17 - - number: 35 - - number: 34 - - number: 5 - - number: 39 - - number: 18 - - number: 36 - - number: 19 - vsync_pin: 22 - href_pin: 26 - pixel_clock_pin: 21 - external_clock: - pin: 27 - frequency: 20MHz - i2c_pins: - sda: 25 - scl: 23 - reset_pin: 15 - power_down_pin: 1 - resolution: 640x480 - jpeg_quality: 10 - on_image: - then: - - lambda: |- - ESP_LOGD("main", "image len=%d, data=%c", image.length, image.data[0]); - -esp32_camera_web_server: - - port: 8080 - mode: stream - - port: 8081 - mode: snapshot +<<: !include common.yaml diff --git a/tests/components/esp32_dac/common.yaml b/tests/components/esp32_dac/common.yaml new file mode 100644 index 0000000000..225627f5af --- /dev/null +++ b/tests/components/esp32_dac/common.yaml @@ -0,0 +1,4 @@ +output: + - platform: esp32_dac + id: dac_output + pin: 25 diff --git a/tests/components/esp32_dac/test.esp32-idf.yaml b/tests/components/esp32_dac/test.esp32-idf.yaml index 225627f5af..dade44d145 100644 --- a/tests/components/esp32_dac/test.esp32-idf.yaml +++ b/tests/components/esp32_dac/test.esp32-idf.yaml @@ -1,4 +1 @@ -output: - - platform: esp32_dac - id: dac_output - pin: 25 +<<: !include common.yaml diff --git a/tests/components/esp32_dac/test.esp32.yaml b/tests/components/esp32_dac/test.esp32.yaml index 225627f5af..dade44d145 100644 --- a/tests/components/esp32_dac/test.esp32.yaml +++ b/tests/components/esp32_dac/test.esp32.yaml @@ -1,4 +1 @@ -output: - - platform: esp32_dac - id: dac_output - pin: 25 +<<: !include common.yaml diff --git a/tests/components/esp32_hall/common.yaml b/tests/components/esp32_hall/common.yaml new file mode 100644 index 0000000000..f8429f5aa0 --- /dev/null +++ b/tests/components/esp32_hall/common.yaml @@ -0,0 +1,3 @@ +sensor: + - platform: esp32_hall + name: ESP32 Hall Sensor diff --git a/tests/components/esp32_hall/test.esp32-idf.yaml b/tests/components/esp32_hall/test.esp32-idf.yaml index f8429f5aa0..dade44d145 100644 --- a/tests/components/esp32_hall/test.esp32-idf.yaml +++ b/tests/components/esp32_hall/test.esp32-idf.yaml @@ -1,3 +1 @@ -sensor: - - platform: esp32_hall - name: ESP32 Hall Sensor +<<: !include common.yaml diff --git a/tests/components/esp32_hall/test.esp32.yaml b/tests/components/esp32_hall/test.esp32.yaml index f8429f5aa0..dade44d145 100644 --- a/tests/components/esp32_hall/test.esp32.yaml +++ b/tests/components/esp32_hall/test.esp32.yaml @@ -1,3 +1 @@ -sensor: - - platform: esp32_hall - name: ESP32 Hall Sensor +<<: !include common.yaml diff --git a/tests/components/esp32_improv/common.yaml b/tests/components/esp32_improv/common.yaml new file mode 100644 index 0000000000..7eb3f9c0be --- /dev/null +++ b/tests/components/esp32_improv/common.yaml @@ -0,0 +1,18 @@ +wifi: + ssid: MySSID + password: password1 + +binary_sensor: + - platform: gpio + pin: 0 + id: io0_button + +output: + - platform: gpio + pin: 2 + id: built_in_led + +esp32_improv: + authorizer: io0_button + authorized_duration: 1min + status_indicator: built_in_led diff --git a/tests/components/esp32_improv/test.esp32-c3-idf.yaml b/tests/components/esp32_improv/test.esp32-c3-idf.yaml index 7eb3f9c0be..dade44d145 100644 --- a/tests/components/esp32_improv/test.esp32-c3-idf.yaml +++ b/tests/components/esp32_improv/test.esp32-c3-idf.yaml @@ -1,18 +1 @@ -wifi: - ssid: MySSID - password: password1 - -binary_sensor: - - platform: gpio - pin: 0 - id: io0_button - -output: - - platform: gpio - pin: 2 - id: built_in_led - -esp32_improv: - authorizer: io0_button - authorized_duration: 1min - status_indicator: built_in_led +<<: !include common.yaml diff --git a/tests/components/esp32_improv/test.esp32-c3.yaml b/tests/components/esp32_improv/test.esp32-c3.yaml index 7eb3f9c0be..dade44d145 100644 --- a/tests/components/esp32_improv/test.esp32-c3.yaml +++ b/tests/components/esp32_improv/test.esp32-c3.yaml @@ -1,18 +1 @@ -wifi: - ssid: MySSID - password: password1 - -binary_sensor: - - platform: gpio - pin: 0 - id: io0_button - -output: - - platform: gpio - pin: 2 - id: built_in_led - -esp32_improv: - authorizer: io0_button - authorized_duration: 1min - status_indicator: built_in_led +<<: !include common.yaml diff --git a/tests/components/esp32_improv/test.esp32-idf.yaml b/tests/components/esp32_improv/test.esp32-idf.yaml index 7eb3f9c0be..dade44d145 100644 --- a/tests/components/esp32_improv/test.esp32-idf.yaml +++ b/tests/components/esp32_improv/test.esp32-idf.yaml @@ -1,18 +1 @@ -wifi: - ssid: MySSID - password: password1 - -binary_sensor: - - platform: gpio - pin: 0 - id: io0_button - -output: - - platform: gpio - pin: 2 - id: built_in_led - -esp32_improv: - authorizer: io0_button - authorized_duration: 1min - status_indicator: built_in_led +<<: !include common.yaml diff --git a/tests/components/esp32_improv/test.esp32.yaml b/tests/components/esp32_improv/test.esp32.yaml index 7eb3f9c0be..dade44d145 100644 --- a/tests/components/esp32_improv/test.esp32.yaml +++ b/tests/components/esp32_improv/test.esp32.yaml @@ -1,18 +1 @@ -wifi: - ssid: MySSID - password: password1 - -binary_sensor: - - platform: gpio - pin: 0 - id: io0_button - -output: - - platform: gpio - pin: 2 - id: built_in_led - -esp32_improv: - authorizer: io0_button - authorized_duration: 1min - status_indicator: built_in_led +<<: !include common.yaml diff --git a/tests/components/esp32_touch/common.yaml b/tests/components/esp32_touch/common.yaml new file mode 100644 index 0000000000..691cce8d86 --- /dev/null +++ b/tests/components/esp32_touch/common.yaml @@ -0,0 +1,16 @@ +esp32_touch: + setup_mode: false + iir_filter: 10ms + sleep_duration: 27ms + measurement_duration: 8ms + low_voltage_reference: 0.5V + high_voltage_reference: 2.7V + voltage_attenuation: 1.5V + +binary_sensor: + - platform: esp32_touch + name: ESP32 Touch Pad + pin: 27 + threshold: 1000 + on_press: + - logger.log: "I'm touched!" diff --git a/tests/components/esp32_touch/test.esp32-idf.yaml b/tests/components/esp32_touch/test.esp32-idf.yaml index 691cce8d86..dade44d145 100644 --- a/tests/components/esp32_touch/test.esp32-idf.yaml +++ b/tests/components/esp32_touch/test.esp32-idf.yaml @@ -1,16 +1 @@ -esp32_touch: - setup_mode: false - iir_filter: 10ms - sleep_duration: 27ms - measurement_duration: 8ms - low_voltage_reference: 0.5V - high_voltage_reference: 2.7V - voltage_attenuation: 1.5V - -binary_sensor: - - platform: esp32_touch - name: ESP32 Touch Pad - pin: 27 - threshold: 1000 - on_press: - - logger.log: "I'm touched!" +<<: !include common.yaml diff --git a/tests/components/esp32_touch/test.esp32.yaml b/tests/components/esp32_touch/test.esp32.yaml index 691cce8d86..dade44d145 100644 --- a/tests/components/esp32_touch/test.esp32.yaml +++ b/tests/components/esp32_touch/test.esp32.yaml @@ -1,16 +1 @@ -esp32_touch: - setup_mode: false - iir_filter: 10ms - sleep_duration: 27ms - measurement_duration: 8ms - low_voltage_reference: 0.5V - high_voltage_reference: 2.7V - voltage_attenuation: 1.5V - -binary_sensor: - - platform: esp32_touch - name: ESP32 Touch Pad - pin: 27 - threshold: 1000 - on_press: - - logger.log: "I'm touched!" +<<: !include common.yaml diff --git a/tests/components/esp8266_pwm/common.yaml b/tests/components/esp8266_pwm/common.yaml new file mode 100644 index 0000000000..52b290f91b --- /dev/null +++ b/tests/components/esp8266_pwm/common.yaml @@ -0,0 +1,8 @@ +output: + - platform: esp8266_pwm + id: out + pin: 4 + frequency: 50Hz + - platform: esp8266_pwm + id: out2 + pin: 5 diff --git a/tests/components/esp8266_pwm/test.esp8266.yaml b/tests/components/esp8266_pwm/test.esp8266.yaml index 52b290f91b..dade44d145 100644 --- a/tests/components/esp8266_pwm/test.esp8266.yaml +++ b/tests/components/esp8266_pwm/test.esp8266.yaml @@ -1,8 +1 @@ -output: - - platform: esp8266_pwm - id: out - pin: 4 - frequency: 50Hz - - platform: esp8266_pwm - id: out2 - pin: 5 +<<: !include common.yaml diff --git a/tests/components/ethernet/common.yaml b/tests/components/ethernet/common.yaml new file mode 100644 index 0000000000..b9ed9cb036 --- /dev/null +++ b/tests/components/ethernet/common.yaml @@ -0,0 +1,12 @@ +ethernet: + type: LAN8720 + mdc_pin: 23 + mdio_pin: 25 + clk_mode: GPIO0_IN + phy_addr: 0 + power_pin: 26 + manual_ip: + static_ip: 192.168.178.56 + gateway: 192.168.178.1 + subnet: 255.255.255.0 + domain: .local diff --git a/tests/components/ethernet/test.esp32-idf.yaml b/tests/components/ethernet/test.esp32-idf.yaml index b9ed9cb036..dade44d145 100644 --- a/tests/components/ethernet/test.esp32-idf.yaml +++ b/tests/components/ethernet/test.esp32-idf.yaml @@ -1,12 +1 @@ -ethernet: - type: LAN8720 - mdc_pin: 23 - mdio_pin: 25 - clk_mode: GPIO0_IN - phy_addr: 0 - power_pin: 26 - manual_ip: - static_ip: 192.168.178.56 - gateway: 192.168.178.1 - subnet: 255.255.255.0 - domain: .local +<<: !include common.yaml diff --git a/tests/components/ethernet/test.esp32.yaml b/tests/components/ethernet/test.esp32.yaml index b9ed9cb036..dade44d145 100644 --- a/tests/components/ethernet/test.esp32.yaml +++ b/tests/components/ethernet/test.esp32.yaml @@ -1,12 +1 @@ -ethernet: - type: LAN8720 - mdc_pin: 23 - mdio_pin: 25 - clk_mode: GPIO0_IN - phy_addr: 0 - power_pin: 26 - manual_ip: - static_ip: 192.168.178.56 - gateway: 192.168.178.1 - subnet: 255.255.255.0 - domain: .local +<<: !include common.yaml diff --git a/tests/components/ethernet_info/common.yaml b/tests/components/ethernet_info/common.yaml new file mode 100644 index 0000000000..dade4d7ca5 --- /dev/null +++ b/tests/components/ethernet_info/common.yaml @@ -0,0 +1,19 @@ +ethernet: + type: LAN8720 + mdc_pin: 23 + mdio_pin: 25 + clk_mode: GPIO0_IN + phy_addr: 0 + power_pin: 26 + manual_ip: + static_ip: 192.168.178.56 + gateway: 192.168.178.1 + subnet: 255.255.255.0 + domain: .local + +text_sensor: + - platform: ethernet_info + ip_address: + name: IP Address + dns_address: + name: DNS Address diff --git a/tests/components/ethernet_info/test.esp32-idf.yaml b/tests/components/ethernet_info/test.esp32-idf.yaml index dade4d7ca5..dade44d145 100644 --- a/tests/components/ethernet_info/test.esp32-idf.yaml +++ b/tests/components/ethernet_info/test.esp32-idf.yaml @@ -1,19 +1 @@ -ethernet: - type: LAN8720 - mdc_pin: 23 - mdio_pin: 25 - clk_mode: GPIO0_IN - phy_addr: 0 - power_pin: 26 - manual_ip: - static_ip: 192.168.178.56 - gateway: 192.168.178.1 - subnet: 255.255.255.0 - domain: .local - -text_sensor: - - platform: ethernet_info - ip_address: - name: IP Address - dns_address: - name: DNS Address +<<: !include common.yaml diff --git a/tests/components/ethernet_info/test.esp32.yaml b/tests/components/ethernet_info/test.esp32.yaml index dade4d7ca5..dade44d145 100644 --- a/tests/components/ethernet_info/test.esp32.yaml +++ b/tests/components/ethernet_info/test.esp32.yaml @@ -1,19 +1 @@ -ethernet: - type: LAN8720 - mdc_pin: 23 - mdio_pin: 25 - clk_mode: GPIO0_IN - phy_addr: 0 - power_pin: 26 - manual_ip: - static_ip: 192.168.178.56 - gateway: 192.168.178.1 - subnet: 255.255.255.0 - domain: .local - -text_sensor: - - platform: ethernet_info - ip_address: - name: IP Address - dns_address: - name: DNS Address +<<: !include common.yaml diff --git a/tests/components/event/common.yaml b/tests/components/event/common.yaml new file mode 100644 index 0000000000..71cc19a6b0 --- /dev/null +++ b/tests/components/event/common.yaml @@ -0,0 +1,9 @@ +event: + - platform: template + name: Event + id: some_event + event_types: + - template_event_type1 + - template_event_type2 + on_event: + - logger.log: Event fired diff --git a/tests/components/event/test.esp32-c3-idf.yaml b/tests/components/event/test.esp32-c3-idf.yaml index 71cc19a6b0..dade44d145 100644 --- a/tests/components/event/test.esp32-c3-idf.yaml +++ b/tests/components/event/test.esp32-c3-idf.yaml @@ -1,9 +1 @@ -event: - - platform: template - name: Event - id: some_event - event_types: - - template_event_type1 - - template_event_type2 - on_event: - - logger.log: Event fired +<<: !include common.yaml diff --git a/tests/components/event/test.esp32-c3.yaml b/tests/components/event/test.esp32-c3.yaml index 71cc19a6b0..dade44d145 100644 --- a/tests/components/event/test.esp32-c3.yaml +++ b/tests/components/event/test.esp32-c3.yaml @@ -1,9 +1 @@ -event: - - platform: template - name: Event - id: some_event - event_types: - - template_event_type1 - - template_event_type2 - on_event: - - logger.log: Event fired +<<: !include common.yaml diff --git a/tests/components/event/test.esp32-idf.yaml b/tests/components/event/test.esp32-idf.yaml index 71cc19a6b0..dade44d145 100644 --- a/tests/components/event/test.esp32-idf.yaml +++ b/tests/components/event/test.esp32-idf.yaml @@ -1,9 +1 @@ -event: - - platform: template - name: Event - id: some_event - event_types: - - template_event_type1 - - template_event_type2 - on_event: - - logger.log: Event fired +<<: !include common.yaml diff --git a/tests/components/event/test.esp32.yaml b/tests/components/event/test.esp32.yaml index 71cc19a6b0..dade44d145 100644 --- a/tests/components/event/test.esp32.yaml +++ b/tests/components/event/test.esp32.yaml @@ -1,9 +1 @@ -event: - - platform: template - name: Event - id: some_event - event_types: - - template_event_type1 - - template_event_type2 - on_event: - - logger.log: Event fired +<<: !include common.yaml diff --git a/tests/components/event/test.esp8266.yaml b/tests/components/event/test.esp8266.yaml index 71cc19a6b0..dade44d145 100644 --- a/tests/components/event/test.esp8266.yaml +++ b/tests/components/event/test.esp8266.yaml @@ -1,9 +1 @@ -event: - - platform: template - name: Event - id: some_event - event_types: - - template_event_type1 - - template_event_type2 - on_event: - - logger.log: Event fired +<<: !include common.yaml diff --git a/tests/components/event/test.rp2040.yaml b/tests/components/event/test.rp2040.yaml index 71cc19a6b0..dade44d145 100644 --- a/tests/components/event/test.rp2040.yaml +++ b/tests/components/event/test.rp2040.yaml @@ -1,9 +1 @@ -event: - - platform: template - name: Event - id: some_event - event_types: - - template_event_type1 - - template_event_type2 - on_event: - - logger.log: Event fired +<<: !include common.yaml diff --git a/tests/components/exposure_notifications/common.yaml b/tests/components/exposure_notifications/common.yaml new file mode 100644 index 0000000000..faba5bb2d1 --- /dev/null +++ b/tests/components/exposure_notifications/common.yaml @@ -0,0 +1,9 @@ +esp32_ble_tracker: + +exposure_notifications: + on_exposure_notification: + then: + - lambda: | + ESP_LOGD("main", "Got notification:"); + ESP_LOGD("main", " RPI: %s", format_hex(x.rolling_proximity_identifier).c_str()); + ESP_LOGD("main", " RSSI: %d", x.rssi); diff --git a/tests/components/exposure_notifications/test.esp32-c3-idf.yaml b/tests/components/exposure_notifications/test.esp32-c3-idf.yaml index faba5bb2d1..dade44d145 100644 --- a/tests/components/exposure_notifications/test.esp32-c3-idf.yaml +++ b/tests/components/exposure_notifications/test.esp32-c3-idf.yaml @@ -1,9 +1 @@ -esp32_ble_tracker: - -exposure_notifications: - on_exposure_notification: - then: - - lambda: | - ESP_LOGD("main", "Got notification:"); - ESP_LOGD("main", " RPI: %s", format_hex(x.rolling_proximity_identifier).c_str()); - ESP_LOGD("main", " RSSI: %d", x.rssi); +<<: !include common.yaml diff --git a/tests/components/exposure_notifications/test.esp32-c3.yaml b/tests/components/exposure_notifications/test.esp32-c3.yaml index faba5bb2d1..dade44d145 100644 --- a/tests/components/exposure_notifications/test.esp32-c3.yaml +++ b/tests/components/exposure_notifications/test.esp32-c3.yaml @@ -1,9 +1 @@ -esp32_ble_tracker: - -exposure_notifications: - on_exposure_notification: - then: - - lambda: | - ESP_LOGD("main", "Got notification:"); - ESP_LOGD("main", " RPI: %s", format_hex(x.rolling_proximity_identifier).c_str()); - ESP_LOGD("main", " RSSI: %d", x.rssi); +<<: !include common.yaml diff --git a/tests/components/exposure_notifications/test.esp32-idf.yaml b/tests/components/exposure_notifications/test.esp32-idf.yaml index faba5bb2d1..dade44d145 100644 --- a/tests/components/exposure_notifications/test.esp32-idf.yaml +++ b/tests/components/exposure_notifications/test.esp32-idf.yaml @@ -1,9 +1 @@ -esp32_ble_tracker: - -exposure_notifications: - on_exposure_notification: - then: - - lambda: | - ESP_LOGD("main", "Got notification:"); - ESP_LOGD("main", " RPI: %s", format_hex(x.rolling_proximity_identifier).c_str()); - ESP_LOGD("main", " RSSI: %d", x.rssi); +<<: !include common.yaml diff --git a/tests/components/exposure_notifications/test.esp32.yaml b/tests/components/exposure_notifications/test.esp32.yaml index faba5bb2d1..dade44d145 100644 --- a/tests/components/exposure_notifications/test.esp32.yaml +++ b/tests/components/exposure_notifications/test.esp32.yaml @@ -1,9 +1 @@ -esp32_ble_tracker: - -exposure_notifications: - on_exposure_notification: - then: - - lambda: | - ESP_LOGD("main", "Got notification:"); - ESP_LOGD("main", " RPI: %s", format_hex(x.rolling_proximity_identifier).c_str()); - ESP_LOGD("main", " RSSI: %d", x.rssi); +<<: !include common.yaml diff --git a/tests/components/external_components/common.yaml b/tests/components/external_components/common.yaml new file mode 100644 index 0000000000..2b51267ec6 --- /dev/null +++ b/tests/components/external_components/common.yaml @@ -0,0 +1,6 @@ +external_components: + - source: github://esphome/esphome@dev + refresh: 1d + components: [bh1750] + - source: ../../../esphome/components + components: [sntp] diff --git a/tests/components/external_components/test.esp32-c3-idf.yaml b/tests/components/external_components/test.esp32-c3-idf.yaml index 2b51267ec6..dade44d145 100644 --- a/tests/components/external_components/test.esp32-c3-idf.yaml +++ b/tests/components/external_components/test.esp32-c3-idf.yaml @@ -1,6 +1 @@ -external_components: - - source: github://esphome/esphome@dev - refresh: 1d - components: [bh1750] - - source: ../../../esphome/components - components: [sntp] +<<: !include common.yaml diff --git a/tests/components/external_components/test.esp32-c3.yaml b/tests/components/external_components/test.esp32-c3.yaml index 2b51267ec6..dade44d145 100644 --- a/tests/components/external_components/test.esp32-c3.yaml +++ b/tests/components/external_components/test.esp32-c3.yaml @@ -1,6 +1 @@ -external_components: - - source: github://esphome/esphome@dev - refresh: 1d - components: [bh1750] - - source: ../../../esphome/components - components: [sntp] +<<: !include common.yaml diff --git a/tests/components/external_components/test.esp32-idf.yaml b/tests/components/external_components/test.esp32-idf.yaml index 2b51267ec6..dade44d145 100644 --- a/tests/components/external_components/test.esp32-idf.yaml +++ b/tests/components/external_components/test.esp32-idf.yaml @@ -1,6 +1 @@ -external_components: - - source: github://esphome/esphome@dev - refresh: 1d - components: [bh1750] - - source: ../../../esphome/components - components: [sntp] +<<: !include common.yaml diff --git a/tests/components/external_components/test.esp32.yaml b/tests/components/external_components/test.esp32.yaml index 2b51267ec6..dade44d145 100644 --- a/tests/components/external_components/test.esp32.yaml +++ b/tests/components/external_components/test.esp32.yaml @@ -1,6 +1 @@ -external_components: - - source: github://esphome/esphome@dev - refresh: 1d - components: [bh1750] - - source: ../../../esphome/components - components: [sntp] +<<: !include common.yaml diff --git a/tests/components/external_components/test.esp8266.yaml b/tests/components/external_components/test.esp8266.yaml index 2b51267ec6..dade44d145 100644 --- a/tests/components/external_components/test.esp8266.yaml +++ b/tests/components/external_components/test.esp8266.yaml @@ -1,6 +1 @@ -external_components: - - source: github://esphome/esphome@dev - refresh: 1d - components: [bh1750] - - source: ../../../esphome/components - components: [sntp] +<<: !include common.yaml diff --git a/tests/components/external_components/test.rp2040.yaml b/tests/components/external_components/test.rp2040.yaml index 2b51267ec6..dade44d145 100644 --- a/tests/components/external_components/test.rp2040.yaml +++ b/tests/components/external_components/test.rp2040.yaml @@ -1,6 +1 @@ -external_components: - - source: github://esphome/esphome@dev - refresh: 1d - components: [bh1750] - - source: ../../../esphome/components - components: [sntp] +<<: !include common.yaml diff --git a/tests/components/factory_reset/common.yaml b/tests/components/factory_reset/common.yaml new file mode 100644 index 0000000000..ad3abd603e --- /dev/null +++ b/tests/components/factory_reset/common.yaml @@ -0,0 +1,3 @@ +button: + - platform: factory_reset + name: Reset to Factory Default Settings diff --git a/tests/components/factory_reset/test.esp32-c3-idf.yaml b/tests/components/factory_reset/test.esp32-c3-idf.yaml index ad3abd603e..dade44d145 100644 --- a/tests/components/factory_reset/test.esp32-c3-idf.yaml +++ b/tests/components/factory_reset/test.esp32-c3-idf.yaml @@ -1,3 +1 @@ -button: - - platform: factory_reset - name: Reset to Factory Default Settings +<<: !include common.yaml diff --git a/tests/components/factory_reset/test.esp32-c3.yaml b/tests/components/factory_reset/test.esp32-c3.yaml index ad3abd603e..dade44d145 100644 --- a/tests/components/factory_reset/test.esp32-c3.yaml +++ b/tests/components/factory_reset/test.esp32-c3.yaml @@ -1,3 +1 @@ -button: - - platform: factory_reset - name: Reset to Factory Default Settings +<<: !include common.yaml diff --git a/tests/components/factory_reset/test.esp32-idf.yaml b/tests/components/factory_reset/test.esp32-idf.yaml index ad3abd603e..dade44d145 100644 --- a/tests/components/factory_reset/test.esp32-idf.yaml +++ b/tests/components/factory_reset/test.esp32-idf.yaml @@ -1,3 +1 @@ -button: - - platform: factory_reset - name: Reset to Factory Default Settings +<<: !include common.yaml diff --git a/tests/components/factory_reset/test.esp32.yaml b/tests/components/factory_reset/test.esp32.yaml index ad3abd603e..dade44d145 100644 --- a/tests/components/factory_reset/test.esp32.yaml +++ b/tests/components/factory_reset/test.esp32.yaml @@ -1,3 +1 @@ -button: - - platform: factory_reset - name: Reset to Factory Default Settings +<<: !include common.yaml diff --git a/tests/components/factory_reset/test.esp8266.yaml b/tests/components/factory_reset/test.esp8266.yaml index ad3abd603e..dade44d145 100644 --- a/tests/components/factory_reset/test.esp8266.yaml +++ b/tests/components/factory_reset/test.esp8266.yaml @@ -1,3 +1 @@ -button: - - platform: factory_reset - name: Reset to Factory Default Settings +<<: !include common.yaml diff --git a/tests/components/factory_reset/test.rp2040.yaml b/tests/components/factory_reset/test.rp2040.yaml index ad3abd603e..dade44d145 100644 --- a/tests/components/factory_reset/test.rp2040.yaml +++ b/tests/components/factory_reset/test.rp2040.yaml @@ -1,3 +1 @@ -button: - - platform: factory_reset - name: Reset to Factory Default Settings +<<: !include common.yaml diff --git a/tests/components/fastled_clockless/common.yaml b/tests/components/fastled_clockless/common.yaml new file mode 100644 index 0000000000..8b1447a17a --- /dev/null +++ b/tests/components/fastled_clockless/common.yaml @@ -0,0 +1,71 @@ +light: + - platform: fastled_clockless + id: addr1 + chipset: WS2811 + pin: 13 + num_leds: 100 + rgb_order: BRG + max_refresh_rate: 20ms + color_correct: [75%, 100%, 50%] + name: FastLED WS2811 Light + effects: + - addressable_color_wipe: + - addressable_color_wipe: + name: Color Wipe Effect With Custom Values + colors: + - red: 100% + green: 100% + blue: 100% + num_leds: 1 + - red: 0% + green: 0% + blue: 0% + num_leds: 1 + add_led_interval: 100ms + reverse: false + - addressable_scan: + - addressable_scan: + name: Scan Effect With Custom Values + move_interval: 100ms + - addressable_twinkle: + - addressable_twinkle: + name: Twinkle Effect With Custom Values + twinkle_probability: 5% + progress_interval: 4ms + - addressable_random_twinkle: + - addressable_random_twinkle: + name: Random Twinkle Effect With Custom Values + twinkle_probability: 5% + progress_interval: 32ms + - addressable_fireworks: + - addressable_fireworks: + name: Fireworks Effect With Custom Values + update_interval: 32ms + spark_probability: 10% + use_random_color: false + fade_out_rate: 120 + - addressable_flicker: + - addressable_flicker: + name: Flicker Effect With Custom Values + update_interval: 16ms + intensity: 5% + - addressable_lambda: + name: Test For Custom Lambda Effect + lambda: |- + if (initial_run) { + it[0] = current_color; + } + - automation: + name: Custom Effect + sequence: + - light.addressable_set: + id: addr1 + red: 100% + green: 100% + blue: 0% + - delay: 100ms + - light.addressable_set: + id: addr1 + red: 0% + green: 100% + blue: 0% diff --git a/tests/components/fastled_clockless/test.esp32.yaml b/tests/components/fastled_clockless/test.esp32.yaml index 8b1447a17a..dade44d145 100644 --- a/tests/components/fastled_clockless/test.esp32.yaml +++ b/tests/components/fastled_clockless/test.esp32.yaml @@ -1,71 +1 @@ -light: - - platform: fastled_clockless - id: addr1 - chipset: WS2811 - pin: 13 - num_leds: 100 - rgb_order: BRG - max_refresh_rate: 20ms - color_correct: [75%, 100%, 50%] - name: FastLED WS2811 Light - effects: - - addressable_color_wipe: - - addressable_color_wipe: - name: Color Wipe Effect With Custom Values - colors: - - red: 100% - green: 100% - blue: 100% - num_leds: 1 - - red: 0% - green: 0% - blue: 0% - num_leds: 1 - add_led_interval: 100ms - reverse: false - - addressable_scan: - - addressable_scan: - name: Scan Effect With Custom Values - move_interval: 100ms - - addressable_twinkle: - - addressable_twinkle: - name: Twinkle Effect With Custom Values - twinkle_probability: 5% - progress_interval: 4ms - - addressable_random_twinkle: - - addressable_random_twinkle: - name: Random Twinkle Effect With Custom Values - twinkle_probability: 5% - progress_interval: 32ms - - addressable_fireworks: - - addressable_fireworks: - name: Fireworks Effect With Custom Values - update_interval: 32ms - spark_probability: 10% - use_random_color: false - fade_out_rate: 120 - - addressable_flicker: - - addressable_flicker: - name: Flicker Effect With Custom Values - update_interval: 16ms - intensity: 5% - - addressable_lambda: - name: Test For Custom Lambda Effect - lambda: |- - if (initial_run) { - it[0] = current_color; - } - - automation: - name: Custom Effect - sequence: - - light.addressable_set: - id: addr1 - red: 100% - green: 100% - blue: 0% - - delay: 100ms - - light.addressable_set: - id: addr1 - red: 0% - green: 100% - blue: 0% +<<: !include common.yaml diff --git a/tests/components/fastled_spi/common.yaml b/tests/components/fastled_spi/common.yaml new file mode 100644 index 0000000000..f6f7c5553b --- /dev/null +++ b/tests/components/fastled_spi/common.yaml @@ -0,0 +1,71 @@ +light: + - platform: fastled_spi + id: addr1 + chipset: WS2801 + clock_pin: 22 + data_pin: 23 + data_rate: 2MHz + num_leds: 60 + rgb_order: BRG + name: FastLED SPI Light + effects: + - addressable_color_wipe: + - addressable_color_wipe: + name: Color Wipe Effect With Custom Values + colors: + - red: 100% + green: 100% + blue: 100% + num_leds: 1 + - red: 0% + green: 0% + blue: 0% + num_leds: 1 + add_led_interval: 100ms + reverse: false + - addressable_scan: + - addressable_scan: + name: Scan Effect With Custom Values + move_interval: 100ms + - addressable_twinkle: + - addressable_twinkle: + name: Twinkle Effect With Custom Values + twinkle_probability: 5% + progress_interval: 4ms + - addressable_random_twinkle: + - addressable_random_twinkle: + name: Random Twinkle Effect With Custom Values + twinkle_probability: 5% + progress_interval: 32ms + - addressable_fireworks: + - addressable_fireworks: + name: Fireworks Effect With Custom Values + update_interval: 32ms + spark_probability: 10% + use_random_color: false + fade_out_rate: 120 + - addressable_flicker: + - addressable_flicker: + name: Flicker Effect With Custom Values + update_interval: 16ms + intensity: 5% + - addressable_lambda: + name: Test For Custom Lambda Effect + lambda: |- + if (initial_run) { + it[0] = current_color; + } + - automation: + name: Custom Effect + sequence: + - light.addressable_set: + id: addr1 + red: 100% + green: 100% + blue: 0% + - delay: 100ms + - light.addressable_set: + id: addr1 + red: 0% + green: 100% + blue: 0% diff --git a/tests/components/fastled_spi/test.esp32.yaml b/tests/components/fastled_spi/test.esp32.yaml index f6f7c5553b..dade44d145 100644 --- a/tests/components/fastled_spi/test.esp32.yaml +++ b/tests/components/fastled_spi/test.esp32.yaml @@ -1,71 +1 @@ -light: - - platform: fastled_spi - id: addr1 - chipset: WS2801 - clock_pin: 22 - data_pin: 23 - data_rate: 2MHz - num_leds: 60 - rgb_order: BRG - name: FastLED SPI Light - effects: - - addressable_color_wipe: - - addressable_color_wipe: - name: Color Wipe Effect With Custom Values - colors: - - red: 100% - green: 100% - blue: 100% - num_leds: 1 - - red: 0% - green: 0% - blue: 0% - num_leds: 1 - add_led_interval: 100ms - reverse: false - - addressable_scan: - - addressable_scan: - name: Scan Effect With Custom Values - move_interval: 100ms - - addressable_twinkle: - - addressable_twinkle: - name: Twinkle Effect With Custom Values - twinkle_probability: 5% - progress_interval: 4ms - - addressable_random_twinkle: - - addressable_random_twinkle: - name: Random Twinkle Effect With Custom Values - twinkle_probability: 5% - progress_interval: 32ms - - addressable_fireworks: - - addressable_fireworks: - name: Fireworks Effect With Custom Values - update_interval: 32ms - spark_probability: 10% - use_random_color: false - fade_out_rate: 120 - - addressable_flicker: - - addressable_flicker: - name: Flicker Effect With Custom Values - update_interval: 16ms - intensity: 5% - - addressable_lambda: - name: Test For Custom Lambda Effect - lambda: |- - if (initial_run) { - it[0] = current_color; - } - - automation: - name: Custom Effect - sequence: - - light.addressable_set: - id: addr1 - red: 100% - green: 100% - blue: 0% - - delay: 100ms - - light.addressable_set: - id: addr1 - red: 0% - green: 100% - blue: 0% +<<: !include common.yaml diff --git a/tests/components/feedback/common.yaml b/tests/components/feedback/common.yaml new file mode 100644 index 0000000000..f93d54e8b6 --- /dev/null +++ b/tests/components/feedback/common.yaml @@ -0,0 +1,39 @@ +binary_sensor: + - platform: template + id: open_endstop_sensor + - platform: template + id: open_sensor + - platform: template + id: open_obstacle_sensor + - platform: template + id: close_endstop_sensor + - platform: template + id: close_sensor + - platform: template + id: close_obstacle_sensor + +cover: + - platform: feedback + name: Feedback Cover + id: gate + device_class: gate + infer_endstop_from_movement: false + has_built_in_endstop: false + max_duration: 30s + direction_change_wait_time: 300ms + acceleration_wait_time: 150ms + obstacle_rollback: 10% + open_duration: 22.1s + open_endstop: open_endstop_sensor + open_sensor: open_sensor + open_obstacle_sensor: open_obstacle_sensor + close_duration: 22.4s + close_endstop: close_endstop_sensor + close_sensor: close_sensor + close_obstacle_sensor: close_obstacle_sensor + open_action: + - logger.log: Open Action + close_action: + - logger.log: Close Action + stop_action: + - logger.log: Stop Action diff --git a/tests/components/feedback/test.esp32-c3-idf.yaml b/tests/components/feedback/test.esp32-c3-idf.yaml index f93d54e8b6..dade44d145 100644 --- a/tests/components/feedback/test.esp32-c3-idf.yaml +++ b/tests/components/feedback/test.esp32-c3-idf.yaml @@ -1,39 +1 @@ -binary_sensor: - - platform: template - id: open_endstop_sensor - - platform: template - id: open_sensor - - platform: template - id: open_obstacle_sensor - - platform: template - id: close_endstop_sensor - - platform: template - id: close_sensor - - platform: template - id: close_obstacle_sensor - -cover: - - platform: feedback - name: Feedback Cover - id: gate - device_class: gate - infer_endstop_from_movement: false - has_built_in_endstop: false - max_duration: 30s - direction_change_wait_time: 300ms - acceleration_wait_time: 150ms - obstacle_rollback: 10% - open_duration: 22.1s - open_endstop: open_endstop_sensor - open_sensor: open_sensor - open_obstacle_sensor: open_obstacle_sensor - close_duration: 22.4s - close_endstop: close_endstop_sensor - close_sensor: close_sensor - close_obstacle_sensor: close_obstacle_sensor - open_action: - - logger.log: Open Action - close_action: - - logger.log: Close Action - stop_action: - - logger.log: Stop Action +<<: !include common.yaml diff --git a/tests/components/feedback/test.esp32-c3.yaml b/tests/components/feedback/test.esp32-c3.yaml index f93d54e8b6..dade44d145 100644 --- a/tests/components/feedback/test.esp32-c3.yaml +++ b/tests/components/feedback/test.esp32-c3.yaml @@ -1,39 +1 @@ -binary_sensor: - - platform: template - id: open_endstop_sensor - - platform: template - id: open_sensor - - platform: template - id: open_obstacle_sensor - - platform: template - id: close_endstop_sensor - - platform: template - id: close_sensor - - platform: template - id: close_obstacle_sensor - -cover: - - platform: feedback - name: Feedback Cover - id: gate - device_class: gate - infer_endstop_from_movement: false - has_built_in_endstop: false - max_duration: 30s - direction_change_wait_time: 300ms - acceleration_wait_time: 150ms - obstacle_rollback: 10% - open_duration: 22.1s - open_endstop: open_endstop_sensor - open_sensor: open_sensor - open_obstacle_sensor: open_obstacle_sensor - close_duration: 22.4s - close_endstop: close_endstop_sensor - close_sensor: close_sensor - close_obstacle_sensor: close_obstacle_sensor - open_action: - - logger.log: Open Action - close_action: - - logger.log: Close Action - stop_action: - - logger.log: Stop Action +<<: !include common.yaml diff --git a/tests/components/feedback/test.esp32-idf.yaml b/tests/components/feedback/test.esp32-idf.yaml index f93d54e8b6..dade44d145 100644 --- a/tests/components/feedback/test.esp32-idf.yaml +++ b/tests/components/feedback/test.esp32-idf.yaml @@ -1,39 +1 @@ -binary_sensor: - - platform: template - id: open_endstop_sensor - - platform: template - id: open_sensor - - platform: template - id: open_obstacle_sensor - - platform: template - id: close_endstop_sensor - - platform: template - id: close_sensor - - platform: template - id: close_obstacle_sensor - -cover: - - platform: feedback - name: Feedback Cover - id: gate - device_class: gate - infer_endstop_from_movement: false - has_built_in_endstop: false - max_duration: 30s - direction_change_wait_time: 300ms - acceleration_wait_time: 150ms - obstacle_rollback: 10% - open_duration: 22.1s - open_endstop: open_endstop_sensor - open_sensor: open_sensor - open_obstacle_sensor: open_obstacle_sensor - close_duration: 22.4s - close_endstop: close_endstop_sensor - close_sensor: close_sensor - close_obstacle_sensor: close_obstacle_sensor - open_action: - - logger.log: Open Action - close_action: - - logger.log: Close Action - stop_action: - - logger.log: Stop Action +<<: !include common.yaml diff --git a/tests/components/feedback/test.esp32.yaml b/tests/components/feedback/test.esp32.yaml index f93d54e8b6..dade44d145 100644 --- a/tests/components/feedback/test.esp32.yaml +++ b/tests/components/feedback/test.esp32.yaml @@ -1,39 +1 @@ -binary_sensor: - - platform: template - id: open_endstop_sensor - - platform: template - id: open_sensor - - platform: template - id: open_obstacle_sensor - - platform: template - id: close_endstop_sensor - - platform: template - id: close_sensor - - platform: template - id: close_obstacle_sensor - -cover: - - platform: feedback - name: Feedback Cover - id: gate - device_class: gate - infer_endstop_from_movement: false - has_built_in_endstop: false - max_duration: 30s - direction_change_wait_time: 300ms - acceleration_wait_time: 150ms - obstacle_rollback: 10% - open_duration: 22.1s - open_endstop: open_endstop_sensor - open_sensor: open_sensor - open_obstacle_sensor: open_obstacle_sensor - close_duration: 22.4s - close_endstop: close_endstop_sensor - close_sensor: close_sensor - close_obstacle_sensor: close_obstacle_sensor - open_action: - - logger.log: Open Action - close_action: - - logger.log: Close Action - stop_action: - - logger.log: Stop Action +<<: !include common.yaml diff --git a/tests/components/feedback/test.esp8266.yaml b/tests/components/feedback/test.esp8266.yaml index f93d54e8b6..dade44d145 100644 --- a/tests/components/feedback/test.esp8266.yaml +++ b/tests/components/feedback/test.esp8266.yaml @@ -1,39 +1 @@ -binary_sensor: - - platform: template - id: open_endstop_sensor - - platform: template - id: open_sensor - - platform: template - id: open_obstacle_sensor - - platform: template - id: close_endstop_sensor - - platform: template - id: close_sensor - - platform: template - id: close_obstacle_sensor - -cover: - - platform: feedback - name: Feedback Cover - id: gate - device_class: gate - infer_endstop_from_movement: false - has_built_in_endstop: false - max_duration: 30s - direction_change_wait_time: 300ms - acceleration_wait_time: 150ms - obstacle_rollback: 10% - open_duration: 22.1s - open_endstop: open_endstop_sensor - open_sensor: open_sensor - open_obstacle_sensor: open_obstacle_sensor - close_duration: 22.4s - close_endstop: close_endstop_sensor - close_sensor: close_sensor - close_obstacle_sensor: close_obstacle_sensor - open_action: - - logger.log: Open Action - close_action: - - logger.log: Close Action - stop_action: - - logger.log: Stop Action +<<: !include common.yaml diff --git a/tests/components/feedback/test.rp2040.yaml b/tests/components/feedback/test.rp2040.yaml index f93d54e8b6..dade44d145 100644 --- a/tests/components/feedback/test.rp2040.yaml +++ b/tests/components/feedback/test.rp2040.yaml @@ -1,39 +1 @@ -binary_sensor: - - platform: template - id: open_endstop_sensor - - platform: template - id: open_sensor - - platform: template - id: open_obstacle_sensor - - platform: template - id: close_endstop_sensor - - platform: template - id: close_sensor - - platform: template - id: close_obstacle_sensor - -cover: - - platform: feedback - name: Feedback Cover - id: gate - device_class: gate - infer_endstop_from_movement: false - has_built_in_endstop: false - max_duration: 30s - direction_change_wait_time: 300ms - acceleration_wait_time: 150ms - obstacle_rollback: 10% - open_duration: 22.1s - open_endstop: open_endstop_sensor - open_sensor: open_sensor - open_obstacle_sensor: open_obstacle_sensor - close_duration: 22.4s - close_endstop: close_endstop_sensor - close_sensor: close_sensor - close_obstacle_sensor: close_obstacle_sensor - open_action: - - logger.log: Open Action - close_action: - - logger.log: Close Action - stop_action: - - logger.log: Stop Action +<<: !include common.yaml diff --git a/tests/components/globals/common.yaml b/tests/components/globals/common.yaml new file mode 100644 index 0000000000..224a91a270 --- /dev/null +++ b/tests/components/globals/common.yaml @@ -0,0 +1,28 @@ +esphome: + on_boot: + then: + - globals.set: + id: glob_int + value: "10" + +globals: + - id: glob_int + type: int + restore_value: true + initial_value: "0" + - id: glob_float + type: float + restore_value: true + initial_value: "0.0f" + - id: glob_bool + type: bool + restore_value: false + initial_value: "true" + - id: glob_string + type: std::string + restore_value: false + # initial_value: "" + - id: glob_bool_processed + type: bool + restore_value: false + initial_value: "false" diff --git a/tests/components/globals/test.esp32-c3-idf.yaml b/tests/components/globals/test.esp32-c3-idf.yaml index 224a91a270..dade44d145 100644 --- a/tests/components/globals/test.esp32-c3-idf.yaml +++ b/tests/components/globals/test.esp32-c3-idf.yaml @@ -1,28 +1 @@ -esphome: - on_boot: - then: - - globals.set: - id: glob_int - value: "10" - -globals: - - id: glob_int - type: int - restore_value: true - initial_value: "0" - - id: glob_float - type: float - restore_value: true - initial_value: "0.0f" - - id: glob_bool - type: bool - restore_value: false - initial_value: "true" - - id: glob_string - type: std::string - restore_value: false - # initial_value: "" - - id: glob_bool_processed - type: bool - restore_value: false - initial_value: "false" +<<: !include common.yaml diff --git a/tests/components/globals/test.esp32-c3.yaml b/tests/components/globals/test.esp32-c3.yaml index 224a91a270..dade44d145 100644 --- a/tests/components/globals/test.esp32-c3.yaml +++ b/tests/components/globals/test.esp32-c3.yaml @@ -1,28 +1 @@ -esphome: - on_boot: - then: - - globals.set: - id: glob_int - value: "10" - -globals: - - id: glob_int - type: int - restore_value: true - initial_value: "0" - - id: glob_float - type: float - restore_value: true - initial_value: "0.0f" - - id: glob_bool - type: bool - restore_value: false - initial_value: "true" - - id: glob_string - type: std::string - restore_value: false - # initial_value: "" - - id: glob_bool_processed - type: bool - restore_value: false - initial_value: "false" +<<: !include common.yaml diff --git a/tests/components/globals/test.esp32-idf.yaml b/tests/components/globals/test.esp32-idf.yaml index 224a91a270..dade44d145 100644 --- a/tests/components/globals/test.esp32-idf.yaml +++ b/tests/components/globals/test.esp32-idf.yaml @@ -1,28 +1 @@ -esphome: - on_boot: - then: - - globals.set: - id: glob_int - value: "10" - -globals: - - id: glob_int - type: int - restore_value: true - initial_value: "0" - - id: glob_float - type: float - restore_value: true - initial_value: "0.0f" - - id: glob_bool - type: bool - restore_value: false - initial_value: "true" - - id: glob_string - type: std::string - restore_value: false - # initial_value: "" - - id: glob_bool_processed - type: bool - restore_value: false - initial_value: "false" +<<: !include common.yaml diff --git a/tests/components/globals/test.esp32.yaml b/tests/components/globals/test.esp32.yaml index 224a91a270..dade44d145 100644 --- a/tests/components/globals/test.esp32.yaml +++ b/tests/components/globals/test.esp32.yaml @@ -1,28 +1 @@ -esphome: - on_boot: - then: - - globals.set: - id: glob_int - value: "10" - -globals: - - id: glob_int - type: int - restore_value: true - initial_value: "0" - - id: glob_float - type: float - restore_value: true - initial_value: "0.0f" - - id: glob_bool - type: bool - restore_value: false - initial_value: "true" - - id: glob_string - type: std::string - restore_value: false - # initial_value: "" - - id: glob_bool_processed - type: bool - restore_value: false - initial_value: "false" +<<: !include common.yaml diff --git a/tests/components/globals/test.esp8266.yaml b/tests/components/globals/test.esp8266.yaml index 224a91a270..dade44d145 100644 --- a/tests/components/globals/test.esp8266.yaml +++ b/tests/components/globals/test.esp8266.yaml @@ -1,28 +1 @@ -esphome: - on_boot: - then: - - globals.set: - id: glob_int - value: "10" - -globals: - - id: glob_int - type: int - restore_value: true - initial_value: "0" - - id: glob_float - type: float - restore_value: true - initial_value: "0.0f" - - id: glob_bool - type: bool - restore_value: false - initial_value: "true" - - id: glob_string - type: std::string - restore_value: false - # initial_value: "" - - id: glob_bool_processed - type: bool - restore_value: false - initial_value: "false" +<<: !include common.yaml diff --git a/tests/components/globals/test.rp2040.yaml b/tests/components/globals/test.rp2040.yaml index 224a91a270..dade44d145 100644 --- a/tests/components/globals/test.rp2040.yaml +++ b/tests/components/globals/test.rp2040.yaml @@ -1,28 +1 @@ -esphome: - on_boot: - then: - - globals.set: - id: glob_int - value: "10" - -globals: - - id: glob_int - type: int - restore_value: true - initial_value: "0" - - id: glob_float - type: float - restore_value: true - initial_value: "0.0f" - - id: glob_bool - type: bool - restore_value: false - initial_value: "true" - - id: glob_string - type: std::string - restore_value: false - # initial_value: "" - - id: glob_bool_processed - type: bool - restore_value: false - initial_value: "false" +<<: !include common.yaml diff --git a/tests/components/host/common.yaml b/tests/components/host/common.yaml new file mode 100644 index 0000000000..3d14c190a6 --- /dev/null +++ b/tests/components/host/common.yaml @@ -0,0 +1,15 @@ +time: + - platform: sntp + id: esptime + timezone: Australia/Sydney + +logger: + level: VERBOSE + logs: + lvgl: INFO + display: DEBUG + sensor: INFO + vnc: DEBUG + +host: + mac_address: "62:23:45:AF:B3:DD" diff --git a/tests/components/host/test.host.yaml b/tests/components/host/test.host.yaml index 3d14c190a6..dade44d145 100644 --- a/tests/components/host/test.host.yaml +++ b/tests/components/host/test.host.yaml @@ -1,15 +1 @@ -time: - - platform: sntp - id: esptime - timezone: Australia/Sydney - -logger: - level: VERBOSE - logs: - lvgl: INFO - display: DEBUG - sensor: INFO - vnc: DEBUG - -host: - mac_address: "62:23:45:AF:B3:DD" +<<: !include common.yaml diff --git a/tests/components/improv_serial/common.yaml b/tests/components/improv_serial/common.yaml new file mode 100644 index 0000000000..b36fe5a4a7 --- /dev/null +++ b/tests/components/improv_serial/common.yaml @@ -0,0 +1,5 @@ +wifi: + ssid: MySSID + password: password1 + +improv_serial: diff --git a/tests/components/improv_serial/test.esp32-c3-idf.yaml b/tests/components/improv_serial/test.esp32-c3-idf.yaml index b36fe5a4a7..dade44d145 100644 --- a/tests/components/improv_serial/test.esp32-c3-idf.yaml +++ b/tests/components/improv_serial/test.esp32-c3-idf.yaml @@ -1,5 +1 @@ -wifi: - ssid: MySSID - password: password1 - -improv_serial: +<<: !include common.yaml diff --git a/tests/components/improv_serial/test.esp32-c3.yaml b/tests/components/improv_serial/test.esp32-c3.yaml index b36fe5a4a7..dade44d145 100644 --- a/tests/components/improv_serial/test.esp32-c3.yaml +++ b/tests/components/improv_serial/test.esp32-c3.yaml @@ -1,5 +1 @@ -wifi: - ssid: MySSID - password: password1 - -improv_serial: +<<: !include common.yaml diff --git a/tests/components/improv_serial/test.esp32-idf.yaml b/tests/components/improv_serial/test.esp32-idf.yaml index b36fe5a4a7..dade44d145 100644 --- a/tests/components/improv_serial/test.esp32-idf.yaml +++ b/tests/components/improv_serial/test.esp32-idf.yaml @@ -1,5 +1 @@ -wifi: - ssid: MySSID - password: password1 - -improv_serial: +<<: !include common.yaml diff --git a/tests/components/improv_serial/test.esp32.yaml b/tests/components/improv_serial/test.esp32.yaml index b36fe5a4a7..dade44d145 100644 --- a/tests/components/improv_serial/test.esp32.yaml +++ b/tests/components/improv_serial/test.esp32.yaml @@ -1,5 +1 @@ -wifi: - ssid: MySSID - password: password1 - -improv_serial: +<<: !include common.yaml diff --git a/tests/components/improv_serial/test.esp8266.yaml b/tests/components/improv_serial/test.esp8266.yaml index b36fe5a4a7..dade44d145 100644 --- a/tests/components/improv_serial/test.esp8266.yaml +++ b/tests/components/improv_serial/test.esp8266.yaml @@ -1,5 +1 @@ -wifi: - ssid: MySSID - password: password1 - -improv_serial: +<<: !include common.yaml diff --git a/tests/components/improv_serial/test.rp2040.yaml b/tests/components/improv_serial/test.rp2040.yaml index b36fe5a4a7..dade44d145 100644 --- a/tests/components/improv_serial/test.rp2040.yaml +++ b/tests/components/improv_serial/test.rp2040.yaml @@ -1,5 +1 @@ -wifi: - ssid: MySSID - password: password1 - -improv_serial: +<<: !include common.yaml diff --git a/tests/components/inkbird_ibsth1_mini/common.yaml b/tests/components/inkbird_ibsth1_mini/common.yaml new file mode 100644 index 0000000000..ba46b7dbf6 --- /dev/null +++ b/tests/components/inkbird_ibsth1_mini/common.yaml @@ -0,0 +1,11 @@ +esp32_ble_tracker: + +sensor: + - platform: inkbird_ibsth1_mini + mac_address: 38:81:D7:0A:9C:11 + temperature: + name: Inkbird IBS-TH1 Temperature + humidity: + name: Inkbird IBS-TH1 Humidity + battery_level: + name: Inkbird IBS-TH1 Battery Level diff --git a/tests/components/inkbird_ibsth1_mini/test.esp32-c3-idf.yaml b/tests/components/inkbird_ibsth1_mini/test.esp32-c3-idf.yaml index ba46b7dbf6..dade44d145 100644 --- a/tests/components/inkbird_ibsth1_mini/test.esp32-c3-idf.yaml +++ b/tests/components/inkbird_ibsth1_mini/test.esp32-c3-idf.yaml @@ -1,11 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: inkbird_ibsth1_mini - mac_address: 38:81:D7:0A:9C:11 - temperature: - name: Inkbird IBS-TH1 Temperature - humidity: - name: Inkbird IBS-TH1 Humidity - battery_level: - name: Inkbird IBS-TH1 Battery Level +<<: !include common.yaml diff --git a/tests/components/inkbird_ibsth1_mini/test.esp32-c3.yaml b/tests/components/inkbird_ibsth1_mini/test.esp32-c3.yaml index ba46b7dbf6..dade44d145 100644 --- a/tests/components/inkbird_ibsth1_mini/test.esp32-c3.yaml +++ b/tests/components/inkbird_ibsth1_mini/test.esp32-c3.yaml @@ -1,11 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: inkbird_ibsth1_mini - mac_address: 38:81:D7:0A:9C:11 - temperature: - name: Inkbird IBS-TH1 Temperature - humidity: - name: Inkbird IBS-TH1 Humidity - battery_level: - name: Inkbird IBS-TH1 Battery Level +<<: !include common.yaml diff --git a/tests/components/inkbird_ibsth1_mini/test.esp32-idf.yaml b/tests/components/inkbird_ibsth1_mini/test.esp32-idf.yaml index ba46b7dbf6..dade44d145 100644 --- a/tests/components/inkbird_ibsth1_mini/test.esp32-idf.yaml +++ b/tests/components/inkbird_ibsth1_mini/test.esp32-idf.yaml @@ -1,11 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: inkbird_ibsth1_mini - mac_address: 38:81:D7:0A:9C:11 - temperature: - name: Inkbird IBS-TH1 Temperature - humidity: - name: Inkbird IBS-TH1 Humidity - battery_level: - name: Inkbird IBS-TH1 Battery Level +<<: !include common.yaml diff --git a/tests/components/inkbird_ibsth1_mini/test.esp32.yaml b/tests/components/inkbird_ibsth1_mini/test.esp32.yaml index ba46b7dbf6..dade44d145 100644 --- a/tests/components/inkbird_ibsth1_mini/test.esp32.yaml +++ b/tests/components/inkbird_ibsth1_mini/test.esp32.yaml @@ -1,11 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: inkbird_ibsth1_mini - mac_address: 38:81:D7:0A:9C:11 - temperature: - name: Inkbird IBS-TH1 Temperature - humidity: - name: Inkbird IBS-TH1 Humidity - battery_level: - name: Inkbird IBS-TH1 Battery Level +<<: !include common.yaml diff --git a/tests/components/inkplate6/common.yaml b/tests/components/inkplate6/common.yaml new file mode 100644 index 0000000000..31b14e6c73 --- /dev/null +++ b/tests/components/inkplate6/common.yaml @@ -0,0 +1,62 @@ +i2c: + - id: i2c_inkplate6 + scl: 16 + sda: 17 + +display: + - platform: inkplate6 + id: inkplate_display + greyscale: false + partial_updating: false + update_interval: 60s + display_data_0_pin: + number: 1 + allow_other_uses: true + display_data_1_pin: + number: 1 + allow_other_uses: true + display_data_2_pin: + number: 1 + allow_other_uses: true + display_data_3_pin: + number: 1 + allow_other_uses: true + display_data_5_pin: + number: 1 + allow_other_uses: true + display_data_4_pin: + number: 1 + allow_other_uses: true + display_data_6_pin: + number: 1 + allow_other_uses: true + display_data_7_pin: + number: 1 + allow_other_uses: true + ckv_pin: + number: 1 + allow_other_uses: true + sph_pin: + number: 1 + allow_other_uses: true + gmod_pin: + number: 1 + allow_other_uses: true + gpio0_enable_pin: + number: 1 + allow_other_uses: true + oe_pin: + number: 1 + allow_other_uses: true + spv_pin: + number: 1 + allow_other_uses: true + powerup_pin: + number: 1 + allow_other_uses: true + wakeup_pin: + number: 1 + allow_other_uses: true + vcom_pin: + number: 1 + allow_other_uses: true diff --git a/tests/components/inkplate6/test.esp32.yaml b/tests/components/inkplate6/test.esp32.yaml index 31b14e6c73..dade44d145 100644 --- a/tests/components/inkplate6/test.esp32.yaml +++ b/tests/components/inkplate6/test.esp32.yaml @@ -1,62 +1 @@ -i2c: - - id: i2c_inkplate6 - scl: 16 - sda: 17 - -display: - - platform: inkplate6 - id: inkplate_display - greyscale: false - partial_updating: false - update_interval: 60s - display_data_0_pin: - number: 1 - allow_other_uses: true - display_data_1_pin: - number: 1 - allow_other_uses: true - display_data_2_pin: - number: 1 - allow_other_uses: true - display_data_3_pin: - number: 1 - allow_other_uses: true - display_data_5_pin: - number: 1 - allow_other_uses: true - display_data_4_pin: - number: 1 - allow_other_uses: true - display_data_6_pin: - number: 1 - allow_other_uses: true - display_data_7_pin: - number: 1 - allow_other_uses: true - ckv_pin: - number: 1 - allow_other_uses: true - sph_pin: - number: 1 - allow_other_uses: true - gmod_pin: - number: 1 - allow_other_uses: true - gpio0_enable_pin: - number: 1 - allow_other_uses: true - oe_pin: - number: 1 - allow_other_uses: true - spv_pin: - number: 1 - allow_other_uses: true - powerup_pin: - number: 1 - allow_other_uses: true - wakeup_pin: - number: 1 - allow_other_uses: true - vcom_pin: - number: 1 - allow_other_uses: true +<<: !include common.yaml diff --git a/tests/components/interval/common.yaml b/tests/components/interval/common.yaml new file mode 100644 index 0000000000..2a3c979ae2 --- /dev/null +++ b/tests/components/interval/common.yaml @@ -0,0 +1,4 @@ +interval: + - interval: 1s + then: + - logger.log: Tick diff --git a/tests/components/interval/test.esp32-c3-idf.yaml b/tests/components/interval/test.esp32-c3-idf.yaml index 2a3c979ae2..dade44d145 100644 --- a/tests/components/interval/test.esp32-c3-idf.yaml +++ b/tests/components/interval/test.esp32-c3-idf.yaml @@ -1,4 +1 @@ -interval: - - interval: 1s - then: - - logger.log: Tick +<<: !include common.yaml diff --git a/tests/components/interval/test.esp32-c3.yaml b/tests/components/interval/test.esp32-c3.yaml index 2a3c979ae2..dade44d145 100644 --- a/tests/components/interval/test.esp32-c3.yaml +++ b/tests/components/interval/test.esp32-c3.yaml @@ -1,4 +1 @@ -interval: - - interval: 1s - then: - - logger.log: Tick +<<: !include common.yaml diff --git a/tests/components/interval/test.esp32-idf.yaml b/tests/components/interval/test.esp32-idf.yaml index 2a3c979ae2..dade44d145 100644 --- a/tests/components/interval/test.esp32-idf.yaml +++ b/tests/components/interval/test.esp32-idf.yaml @@ -1,4 +1 @@ -interval: - - interval: 1s - then: - - logger.log: Tick +<<: !include common.yaml diff --git a/tests/components/interval/test.esp32.yaml b/tests/components/interval/test.esp32.yaml index 2a3c979ae2..dade44d145 100644 --- a/tests/components/interval/test.esp32.yaml +++ b/tests/components/interval/test.esp32.yaml @@ -1,4 +1 @@ -interval: - - interval: 1s - then: - - logger.log: Tick +<<: !include common.yaml diff --git a/tests/components/interval/test.esp8266.yaml b/tests/components/interval/test.esp8266.yaml index 2a3c979ae2..dade44d145 100644 --- a/tests/components/interval/test.esp8266.yaml +++ b/tests/components/interval/test.esp8266.yaml @@ -1,4 +1 @@ -interval: - - interval: 1s - then: - - logger.log: Tick +<<: !include common.yaml diff --git a/tests/components/interval/test.rp2040.yaml b/tests/components/interval/test.rp2040.yaml index 2a3c979ae2..dade44d145 100644 --- a/tests/components/interval/test.rp2040.yaml +++ b/tests/components/interval/test.rp2040.yaml @@ -1,4 +1 @@ -interval: - - interval: 1s - then: - - logger.log: Tick +<<: !include common.yaml diff --git a/tests/components/ledc/common.yaml b/tests/components/ledc/common.yaml new file mode 100644 index 0000000000..70352b4519 --- /dev/null +++ b/tests/components/ledc/common.yaml @@ -0,0 +1,11 @@ +esphome: + on_boot: + then: + - output.ledc.set_frequency: + id: test_ledc + frequency: 100Hz + +output: + - platform: ledc + id: test_ledc + pin: 4 diff --git a/tests/components/ledc/test.esp32-c3-idf.yaml b/tests/components/ledc/test.esp32-c3-idf.yaml index 70352b4519..dade44d145 100644 --- a/tests/components/ledc/test.esp32-c3-idf.yaml +++ b/tests/components/ledc/test.esp32-c3-idf.yaml @@ -1,11 +1 @@ -esphome: - on_boot: - then: - - output.ledc.set_frequency: - id: test_ledc - frequency: 100Hz - -output: - - platform: ledc - id: test_ledc - pin: 4 +<<: !include common.yaml diff --git a/tests/components/ledc/test.esp32-c3.yaml b/tests/components/ledc/test.esp32-c3.yaml index 70352b4519..dade44d145 100644 --- a/tests/components/ledc/test.esp32-c3.yaml +++ b/tests/components/ledc/test.esp32-c3.yaml @@ -1,11 +1 @@ -esphome: - on_boot: - then: - - output.ledc.set_frequency: - id: test_ledc - frequency: 100Hz - -output: - - platform: ledc - id: test_ledc - pin: 4 +<<: !include common.yaml diff --git a/tests/components/ledc/test.esp32-idf.yaml b/tests/components/ledc/test.esp32-idf.yaml index 70352b4519..dade44d145 100644 --- a/tests/components/ledc/test.esp32-idf.yaml +++ b/tests/components/ledc/test.esp32-idf.yaml @@ -1,11 +1 @@ -esphome: - on_boot: - then: - - output.ledc.set_frequency: - id: test_ledc - frequency: 100Hz - -output: - - platform: ledc - id: test_ledc - pin: 4 +<<: !include common.yaml diff --git a/tests/components/ledc/test.esp32.yaml b/tests/components/ledc/test.esp32.yaml index 70352b4519..dade44d145 100644 --- a/tests/components/ledc/test.esp32.yaml +++ b/tests/components/ledc/test.esp32.yaml @@ -1,11 +1 @@ -esphome: - on_boot: - then: - - output.ledc.set_frequency: - id: test_ledc - frequency: 100Hz - -output: - - platform: ledc - id: test_ledc - pin: 4 +<<: !include common.yaml diff --git a/tests/components/lightwaverf/common.yaml b/tests/components/lightwaverf/common.yaml new file mode 100644 index 0000000000..7ed8000271 --- /dev/null +++ b/tests/components/lightwaverf/common.yaml @@ -0,0 +1,13 @@ +lightwaverf: + read_pin: 5 + write_pin: 4 + +button: + - platform: template + name: "Turn off sofa" + id: light_off_ceiling_sofa + on_press: + lightwaverf.send_raw: + code: [0x04, 0x00, 0x00, 0x00, 0x0f, 0x03, 0x0d, 0x09, 0x08, 0x08] + name: "Sofa" + repeat: 1 diff --git a/tests/components/lightwaverf/test.esp8266.yaml b/tests/components/lightwaverf/test.esp8266.yaml index 7ed8000271..dade44d145 100644 --- a/tests/components/lightwaverf/test.esp8266.yaml +++ b/tests/components/lightwaverf/test.esp8266.yaml @@ -1,13 +1 @@ -lightwaverf: - read_pin: 5 - write_pin: 4 - -button: - - platform: template - name: "Turn off sofa" - id: light_off_ceiling_sofa - on_press: - lightwaverf.send_raw: - code: [0x04, 0x00, 0x00, 0x00, 0x0f, 0x03, 0x0d, 0x09, 0x08, 0x08] - name: "Sofa" - repeat: 1 +<<: !include common.yaml diff --git a/tests/components/lock/common.yaml b/tests/components/lock/common.yaml new file mode 100644 index 0000000000..82297a3da4 --- /dev/null +++ b/tests/components/lock/common.yaml @@ -0,0 +1,36 @@ +esphome: + on_boot: + then: + - lock.lock: test_lock1 + - lock.unlock: test_lock1 + - lock.open: test_lock1 + +output: + - platform: gpio + id: test_binary + pin: 4 + +lock: + - platform: template + id: test_lock1 + name: Template Lock + lambda: |- + if (millis() > 10000) { + return LOCK_STATE_LOCKED; + } else { + return LOCK_STATE_UNLOCKED; + } + optimistic: true + assumed_state: false + on_unlock: + - lock.template.publish: + id: test_lock1 + state: !lambda "return LOCK_STATE_UNLOCKED;" + on_lock: + - lock.template.publish: + id: test_lock1 + state: !lambda "return LOCK_STATE_LOCKED;" + - platform: output + name: Generic Output Lock + id: test_lock2 + output: test_binary diff --git a/tests/components/lock/test.esp32-c3-idf.yaml b/tests/components/lock/test.esp32-c3-idf.yaml index 82297a3da4..dade44d145 100644 --- a/tests/components/lock/test.esp32-c3-idf.yaml +++ b/tests/components/lock/test.esp32-c3-idf.yaml @@ -1,36 +1 @@ -esphome: - on_boot: - then: - - lock.lock: test_lock1 - - lock.unlock: test_lock1 - - lock.open: test_lock1 - -output: - - platform: gpio - id: test_binary - pin: 4 - -lock: - - platform: template - id: test_lock1 - name: Template Lock - lambda: |- - if (millis() > 10000) { - return LOCK_STATE_LOCKED; - } else { - return LOCK_STATE_UNLOCKED; - } - optimistic: true - assumed_state: false - on_unlock: - - lock.template.publish: - id: test_lock1 - state: !lambda "return LOCK_STATE_UNLOCKED;" - on_lock: - - lock.template.publish: - id: test_lock1 - state: !lambda "return LOCK_STATE_LOCKED;" - - platform: output - name: Generic Output Lock - id: test_lock2 - output: test_binary +<<: !include common.yaml diff --git a/tests/components/lock/test.esp32-c3.yaml b/tests/components/lock/test.esp32-c3.yaml index 82297a3da4..dade44d145 100644 --- a/tests/components/lock/test.esp32-c3.yaml +++ b/tests/components/lock/test.esp32-c3.yaml @@ -1,36 +1 @@ -esphome: - on_boot: - then: - - lock.lock: test_lock1 - - lock.unlock: test_lock1 - - lock.open: test_lock1 - -output: - - platform: gpio - id: test_binary - pin: 4 - -lock: - - platform: template - id: test_lock1 - name: Template Lock - lambda: |- - if (millis() > 10000) { - return LOCK_STATE_LOCKED; - } else { - return LOCK_STATE_UNLOCKED; - } - optimistic: true - assumed_state: false - on_unlock: - - lock.template.publish: - id: test_lock1 - state: !lambda "return LOCK_STATE_UNLOCKED;" - on_lock: - - lock.template.publish: - id: test_lock1 - state: !lambda "return LOCK_STATE_LOCKED;" - - platform: output - name: Generic Output Lock - id: test_lock2 - output: test_binary +<<: !include common.yaml diff --git a/tests/components/lock/test.esp32-idf.yaml b/tests/components/lock/test.esp32-idf.yaml index 82297a3da4..dade44d145 100644 --- a/tests/components/lock/test.esp32-idf.yaml +++ b/tests/components/lock/test.esp32-idf.yaml @@ -1,36 +1 @@ -esphome: - on_boot: - then: - - lock.lock: test_lock1 - - lock.unlock: test_lock1 - - lock.open: test_lock1 - -output: - - platform: gpio - id: test_binary - pin: 4 - -lock: - - platform: template - id: test_lock1 - name: Template Lock - lambda: |- - if (millis() > 10000) { - return LOCK_STATE_LOCKED; - } else { - return LOCK_STATE_UNLOCKED; - } - optimistic: true - assumed_state: false - on_unlock: - - lock.template.publish: - id: test_lock1 - state: !lambda "return LOCK_STATE_UNLOCKED;" - on_lock: - - lock.template.publish: - id: test_lock1 - state: !lambda "return LOCK_STATE_LOCKED;" - - platform: output - name: Generic Output Lock - id: test_lock2 - output: test_binary +<<: !include common.yaml diff --git a/tests/components/lock/test.esp32.yaml b/tests/components/lock/test.esp32.yaml index 82297a3da4..dade44d145 100644 --- a/tests/components/lock/test.esp32.yaml +++ b/tests/components/lock/test.esp32.yaml @@ -1,36 +1 @@ -esphome: - on_boot: - then: - - lock.lock: test_lock1 - - lock.unlock: test_lock1 - - lock.open: test_lock1 - -output: - - platform: gpio - id: test_binary - pin: 4 - -lock: - - platform: template - id: test_lock1 - name: Template Lock - lambda: |- - if (millis() > 10000) { - return LOCK_STATE_LOCKED; - } else { - return LOCK_STATE_UNLOCKED; - } - optimistic: true - assumed_state: false - on_unlock: - - lock.template.publish: - id: test_lock1 - state: !lambda "return LOCK_STATE_UNLOCKED;" - on_lock: - - lock.template.publish: - id: test_lock1 - state: !lambda "return LOCK_STATE_LOCKED;" - - platform: output - name: Generic Output Lock - id: test_lock2 - output: test_binary +<<: !include common.yaml diff --git a/tests/components/lock/test.esp8266.yaml b/tests/components/lock/test.esp8266.yaml index 82297a3da4..dade44d145 100644 --- a/tests/components/lock/test.esp8266.yaml +++ b/tests/components/lock/test.esp8266.yaml @@ -1,36 +1 @@ -esphome: - on_boot: - then: - - lock.lock: test_lock1 - - lock.unlock: test_lock1 - - lock.open: test_lock1 - -output: - - platform: gpio - id: test_binary - pin: 4 - -lock: - - platform: template - id: test_lock1 - name: Template Lock - lambda: |- - if (millis() > 10000) { - return LOCK_STATE_LOCKED; - } else { - return LOCK_STATE_UNLOCKED; - } - optimistic: true - assumed_state: false - on_unlock: - - lock.template.publish: - id: test_lock1 - state: !lambda "return LOCK_STATE_UNLOCKED;" - on_lock: - - lock.template.publish: - id: test_lock1 - state: !lambda "return LOCK_STATE_LOCKED;" - - platform: output - name: Generic Output Lock - id: test_lock2 - output: test_binary +<<: !include common.yaml diff --git a/tests/components/lock/test.rp2040.yaml b/tests/components/lock/test.rp2040.yaml index 82297a3da4..dade44d145 100644 --- a/tests/components/lock/test.rp2040.yaml +++ b/tests/components/lock/test.rp2040.yaml @@ -1,36 +1 @@ -esphome: - on_boot: - then: - - lock.lock: test_lock1 - - lock.unlock: test_lock1 - - lock.open: test_lock1 - -output: - - platform: gpio - id: test_binary - pin: 4 - -lock: - - platform: template - id: test_lock1 - name: Template Lock - lambda: |- - if (millis() > 10000) { - return LOCK_STATE_LOCKED; - } else { - return LOCK_STATE_UNLOCKED; - } - optimistic: true - assumed_state: false - on_unlock: - - lock.template.publish: - id: test_lock1 - state: !lambda "return LOCK_STATE_UNLOCKED;" - on_lock: - - lock.template.publish: - id: test_lock1 - state: !lambda "return LOCK_STATE_LOCKED;" - - platform: output - name: Generic Output Lock - id: test_lock2 - output: test_binary +<<: !include common.yaml diff --git a/tests/components/logger/common.yaml b/tests/components/logger/common.yaml new file mode 100644 index 0000000000..70b485daac --- /dev/null +++ b/tests/components/logger/common.yaml @@ -0,0 +1,7 @@ +esphome: + on_boot: + then: + - logger.log: Hello world + +logger: + level: DEBUG diff --git a/tests/components/logger/test.esp32-c3-idf.yaml b/tests/components/logger/test.esp32-c3-idf.yaml index 70b485daac..dade44d145 100644 --- a/tests/components/logger/test.esp32-c3-idf.yaml +++ b/tests/components/logger/test.esp32-c3-idf.yaml @@ -1,7 +1 @@ -esphome: - on_boot: - then: - - logger.log: Hello world - -logger: - level: DEBUG +<<: !include common.yaml diff --git a/tests/components/logger/test.esp32-c3.yaml b/tests/components/logger/test.esp32-c3.yaml index 70b485daac..dade44d145 100644 --- a/tests/components/logger/test.esp32-c3.yaml +++ b/tests/components/logger/test.esp32-c3.yaml @@ -1,7 +1 @@ -esphome: - on_boot: - then: - - logger.log: Hello world - -logger: - level: DEBUG +<<: !include common.yaml diff --git a/tests/components/logger/test.esp32-idf.yaml b/tests/components/logger/test.esp32-idf.yaml index 70b485daac..dade44d145 100644 --- a/tests/components/logger/test.esp32-idf.yaml +++ b/tests/components/logger/test.esp32-idf.yaml @@ -1,7 +1 @@ -esphome: - on_boot: - then: - - logger.log: Hello world - -logger: - level: DEBUG +<<: !include common.yaml diff --git a/tests/components/logger/test.esp32.yaml b/tests/components/logger/test.esp32.yaml index 70b485daac..dade44d145 100644 --- a/tests/components/logger/test.esp32.yaml +++ b/tests/components/logger/test.esp32.yaml @@ -1,7 +1 @@ -esphome: - on_boot: - then: - - logger.log: Hello world - -logger: - level: DEBUG +<<: !include common.yaml diff --git a/tests/components/logger/test.esp8266.yaml b/tests/components/logger/test.esp8266.yaml index 70b485daac..dade44d145 100644 --- a/tests/components/logger/test.esp8266.yaml +++ b/tests/components/logger/test.esp8266.yaml @@ -1,7 +1 @@ -esphome: - on_boot: - then: - - logger.log: Hello world - -logger: - level: DEBUG +<<: !include common.yaml diff --git a/tests/components/logger/test.rp2040.yaml b/tests/components/logger/test.rp2040.yaml index 70b485daac..dade44d145 100644 --- a/tests/components/logger/test.rp2040.yaml +++ b/tests/components/logger/test.rp2040.yaml @@ -1,7 +1 @@ -esphome: - on_boot: - then: - - logger.log: Hello world - -logger: - level: DEBUG +<<: !include common.yaml diff --git a/tests/components/mdns/common.yaml b/tests/components/mdns/common.yaml new file mode 100644 index 0000000000..bc31e32783 --- /dev/null +++ b/tests/components/mdns/common.yaml @@ -0,0 +1,6 @@ +wifi: + ssid: MySSID + password: password1 + +mdns: + disabled: false diff --git a/tests/components/mdns/test.esp32-c3-idf.yaml b/tests/components/mdns/test.esp32-c3-idf.yaml index bc31e32783..dade44d145 100644 --- a/tests/components/mdns/test.esp32-c3-idf.yaml +++ b/tests/components/mdns/test.esp32-c3-idf.yaml @@ -1,6 +1 @@ -wifi: - ssid: MySSID - password: password1 - -mdns: - disabled: false +<<: !include common.yaml diff --git a/tests/components/mdns/test.esp32-c3.yaml b/tests/components/mdns/test.esp32-c3.yaml index bc31e32783..dade44d145 100644 --- a/tests/components/mdns/test.esp32-c3.yaml +++ b/tests/components/mdns/test.esp32-c3.yaml @@ -1,6 +1 @@ -wifi: - ssid: MySSID - password: password1 - -mdns: - disabled: false +<<: !include common.yaml diff --git a/tests/components/mdns/test.esp32-idf.yaml b/tests/components/mdns/test.esp32-idf.yaml index bc31e32783..dade44d145 100644 --- a/tests/components/mdns/test.esp32-idf.yaml +++ b/tests/components/mdns/test.esp32-idf.yaml @@ -1,6 +1 @@ -wifi: - ssid: MySSID - password: password1 - -mdns: - disabled: false +<<: !include common.yaml diff --git a/tests/components/mdns/test.esp32.yaml b/tests/components/mdns/test.esp32.yaml index bc31e32783..dade44d145 100644 --- a/tests/components/mdns/test.esp32.yaml +++ b/tests/components/mdns/test.esp32.yaml @@ -1,6 +1 @@ -wifi: - ssid: MySSID - password: password1 - -mdns: - disabled: false +<<: !include common.yaml diff --git a/tests/components/mdns/test.esp8266.yaml b/tests/components/mdns/test.esp8266.yaml index bc31e32783..dade44d145 100644 --- a/tests/components/mdns/test.esp8266.yaml +++ b/tests/components/mdns/test.esp8266.yaml @@ -1,6 +1 @@ -wifi: - ssid: MySSID - password: password1 - -mdns: - disabled: false +<<: !include common.yaml diff --git a/tests/components/mdns/test.rp2040.yaml b/tests/components/mdns/test.rp2040.yaml index bc31e32783..dade44d145 100644 --- a/tests/components/mdns/test.rp2040.yaml +++ b/tests/components/mdns/test.rp2040.yaml @@ -1,6 +1 @@ -wifi: - ssid: MySSID - password: password1 - -mdns: - disabled: false +<<: !include common.yaml diff --git a/tests/components/media_player/common.yaml b/tests/components/media_player/common.yaml new file mode 100644 index 0000000000..24b85cd474 --- /dev/null +++ b/tests/components/media_player/common.yaml @@ -0,0 +1,32 @@ +wifi: + ssid: MySSID + password: password1 + +i2s_audio: + i2s_lrclk_pin: 13 + i2s_bclk_pin: 14 + i2s_mclk_pin: 15 + +media_player: + - platform: i2s_audio + name: None + dac_type: external + i2s_dout_pin: 18 + mute_pin: 19 + on_state: + - media_player.play: + - media_player.play_media: http://localhost/media.mp3 + - media_player.play_media: !lambda 'return "http://localhost/media.mp3";' + on_idle: + - media_player.pause: + on_play: + - media_player.stop: + on_pause: + - media_player.toggle: + - wait_until: + media_player.is_idle: + - wait_until: + media_player.is_playing: + - media_player.volume_up: + - media_player.volume_down: + - media_player.volume_set: 50% diff --git a/tests/components/media_player/test.esp32.yaml b/tests/components/media_player/test.esp32.yaml index 24b85cd474..dade44d145 100644 --- a/tests/components/media_player/test.esp32.yaml +++ b/tests/components/media_player/test.esp32.yaml @@ -1,32 +1 @@ -wifi: - ssid: MySSID - password: password1 - -i2s_audio: - i2s_lrclk_pin: 13 - i2s_bclk_pin: 14 - i2s_mclk_pin: 15 - -media_player: - - platform: i2s_audio - name: None - dac_type: external - i2s_dout_pin: 18 - mute_pin: 19 - on_state: - - media_player.play: - - media_player.play_media: http://localhost/media.mp3 - - media_player.play_media: !lambda 'return "http://localhost/media.mp3";' - on_idle: - - media_player.pause: - on_play: - - media_player.stop: - on_pause: - - media_player.toggle: - - wait_until: - media_player.is_idle: - - wait_until: - media_player.is_playing: - - media_player.volume_up: - - media_player.volume_down: - - media_player.volume_set: 50% +<<: !include common.yaml diff --git a/tests/components/micro_wake_word/common.yaml b/tests/components/micro_wake_word/common.yaml new file mode 100644 index 0000000000..c0f3593cc6 --- /dev/null +++ b/tests/components/micro_wake_word/common.yaml @@ -0,0 +1,15 @@ +i2s_audio: + i2s_lrclk_pin: GPIO18 + i2s_bclk_pin: GPIO19 + +microphone: + - platform: i2s_audio + id: echo_microphone + i2s_din_pin: GPIO17 + adc_type: external + pdm: true + +micro_wake_word: + model: hey_jarvis + on_wake_word_detected: + - logger.log: "Wake word detected" diff --git a/tests/components/micro_wake_word/test.esp32-s3-idf.yaml b/tests/components/micro_wake_word/test.esp32-s3-idf.yaml index c0f3593cc6..dade44d145 100644 --- a/tests/components/micro_wake_word/test.esp32-s3-idf.yaml +++ b/tests/components/micro_wake_word/test.esp32-s3-idf.yaml @@ -1,15 +1 @@ -i2s_audio: - i2s_lrclk_pin: GPIO18 - i2s_bclk_pin: GPIO19 - -microphone: - - platform: i2s_audio - id: echo_microphone - i2s_din_pin: GPIO17 - adc_type: external - pdm: true - -micro_wake_word: - model: hey_jarvis - on_wake_word_detected: - - logger.log: "Wake word detected" +<<: !include common.yaml diff --git a/tests/components/midea_ir/common.yaml b/tests/components/midea_ir/common.yaml new file mode 100644 index 0000000000..e8d89cecc2 --- /dev/null +++ b/tests/components/midea_ir/common.yaml @@ -0,0 +1,8 @@ +remote_transmitter: + pin: 4 + carrier_duty_percent: 50% + +climate: + - platform: midea_ir + name: Midea IR + use_fahrenheit: true diff --git a/tests/components/midea_ir/test.esp32-c3-idf.yaml b/tests/components/midea_ir/test.esp32-c3-idf.yaml index e8d89cecc2..dade44d145 100644 --- a/tests/components/midea_ir/test.esp32-c3-idf.yaml +++ b/tests/components/midea_ir/test.esp32-c3-idf.yaml @@ -1,8 +1 @@ -remote_transmitter: - pin: 4 - carrier_duty_percent: 50% - -climate: - - platform: midea_ir - name: Midea IR - use_fahrenheit: true +<<: !include common.yaml diff --git a/tests/components/midea_ir/test.esp32-c3.yaml b/tests/components/midea_ir/test.esp32-c3.yaml index e8d89cecc2..dade44d145 100644 --- a/tests/components/midea_ir/test.esp32-c3.yaml +++ b/tests/components/midea_ir/test.esp32-c3.yaml @@ -1,8 +1 @@ -remote_transmitter: - pin: 4 - carrier_duty_percent: 50% - -climate: - - platform: midea_ir - name: Midea IR - use_fahrenheit: true +<<: !include common.yaml diff --git a/tests/components/midea_ir/test.esp32-idf.yaml b/tests/components/midea_ir/test.esp32-idf.yaml index e8d89cecc2..dade44d145 100644 --- a/tests/components/midea_ir/test.esp32-idf.yaml +++ b/tests/components/midea_ir/test.esp32-idf.yaml @@ -1,8 +1 @@ -remote_transmitter: - pin: 4 - carrier_duty_percent: 50% - -climate: - - platform: midea_ir - name: Midea IR - use_fahrenheit: true +<<: !include common.yaml diff --git a/tests/components/midea_ir/test.esp32.yaml b/tests/components/midea_ir/test.esp32.yaml index e8d89cecc2..dade44d145 100644 --- a/tests/components/midea_ir/test.esp32.yaml +++ b/tests/components/midea_ir/test.esp32.yaml @@ -1,8 +1 @@ -remote_transmitter: - pin: 4 - carrier_duty_percent: 50% - -climate: - - platform: midea_ir - name: Midea IR - use_fahrenheit: true +<<: !include common.yaml diff --git a/tests/components/midea_ir/test.esp8266.yaml b/tests/components/midea_ir/test.esp8266.yaml index e8d89cecc2..dade44d145 100644 --- a/tests/components/midea_ir/test.esp8266.yaml +++ b/tests/components/midea_ir/test.esp8266.yaml @@ -1,8 +1 @@ -remote_transmitter: - pin: 4 - carrier_duty_percent: 50% - -climate: - - platform: midea_ir - name: Midea IR - use_fahrenheit: true +<<: !include common.yaml diff --git a/tests/components/mitsubishi/common.yaml b/tests/components/mitsubishi/common.yaml new file mode 100644 index 0000000000..c0fc959c5b --- /dev/null +++ b/tests/components/mitsubishi/common.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + pin: 4 + carrier_duty_percent: 50% + +climate: + - platform: mitsubishi + name: Mitsubishi diff --git a/tests/components/mitsubishi/test.esp32-c3-idf.yaml b/tests/components/mitsubishi/test.esp32-c3-idf.yaml index c0fc959c5b..dade44d145 100644 --- a/tests/components/mitsubishi/test.esp32-c3-idf.yaml +++ b/tests/components/mitsubishi/test.esp32-c3-idf.yaml @@ -1,7 +1 @@ -remote_transmitter: - pin: 4 - carrier_duty_percent: 50% - -climate: - - platform: mitsubishi - name: Mitsubishi +<<: !include common.yaml diff --git a/tests/components/mitsubishi/test.esp32-c3.yaml b/tests/components/mitsubishi/test.esp32-c3.yaml index c0fc959c5b..dade44d145 100644 --- a/tests/components/mitsubishi/test.esp32-c3.yaml +++ b/tests/components/mitsubishi/test.esp32-c3.yaml @@ -1,7 +1 @@ -remote_transmitter: - pin: 4 - carrier_duty_percent: 50% - -climate: - - platform: mitsubishi - name: Mitsubishi +<<: !include common.yaml diff --git a/tests/components/mitsubishi/test.esp32-idf.yaml b/tests/components/mitsubishi/test.esp32-idf.yaml index c0fc959c5b..dade44d145 100644 --- a/tests/components/mitsubishi/test.esp32-idf.yaml +++ b/tests/components/mitsubishi/test.esp32-idf.yaml @@ -1,7 +1 @@ -remote_transmitter: - pin: 4 - carrier_duty_percent: 50% - -climate: - - platform: mitsubishi - name: Mitsubishi +<<: !include common.yaml diff --git a/tests/components/mitsubishi/test.esp32.yaml b/tests/components/mitsubishi/test.esp32.yaml index c0fc959c5b..dade44d145 100644 --- a/tests/components/mitsubishi/test.esp32.yaml +++ b/tests/components/mitsubishi/test.esp32.yaml @@ -1,7 +1 @@ -remote_transmitter: - pin: 4 - carrier_duty_percent: 50% - -climate: - - platform: mitsubishi - name: Mitsubishi +<<: !include common.yaml diff --git a/tests/components/mitsubishi/test.esp8266.yaml b/tests/components/mitsubishi/test.esp8266.yaml index c0fc959c5b..dade44d145 100644 --- a/tests/components/mitsubishi/test.esp8266.yaml +++ b/tests/components/mitsubishi/test.esp8266.yaml @@ -1,7 +1 @@ -remote_transmitter: - pin: 4 - carrier_duty_percent: 50% - -climate: - - platform: mitsubishi - name: Mitsubishi +<<: !include common.yaml diff --git a/tests/components/mopeka_ble/common.yaml b/tests/components/mopeka_ble/common.yaml new file mode 100644 index 0000000000..a115404f1c --- /dev/null +++ b/tests/components/mopeka_ble/common.yaml @@ -0,0 +1,3 @@ +esp32_ble_tracker: + +mopeka_ble: diff --git a/tests/components/mopeka_ble/test.esp32-c3-idf.yaml b/tests/components/mopeka_ble/test.esp32-c3-idf.yaml index a115404f1c..dade44d145 100644 --- a/tests/components/mopeka_ble/test.esp32-c3-idf.yaml +++ b/tests/components/mopeka_ble/test.esp32-c3-idf.yaml @@ -1,3 +1 @@ -esp32_ble_tracker: - -mopeka_ble: +<<: !include common.yaml diff --git a/tests/components/mopeka_ble/test.esp32-c3.yaml b/tests/components/mopeka_ble/test.esp32-c3.yaml index a115404f1c..dade44d145 100644 --- a/tests/components/mopeka_ble/test.esp32-c3.yaml +++ b/tests/components/mopeka_ble/test.esp32-c3.yaml @@ -1,3 +1 @@ -esp32_ble_tracker: - -mopeka_ble: +<<: !include common.yaml diff --git a/tests/components/mopeka_ble/test.esp32-idf.yaml b/tests/components/mopeka_ble/test.esp32-idf.yaml index a115404f1c..dade44d145 100644 --- a/tests/components/mopeka_ble/test.esp32-idf.yaml +++ b/tests/components/mopeka_ble/test.esp32-idf.yaml @@ -1,3 +1 @@ -esp32_ble_tracker: - -mopeka_ble: +<<: !include common.yaml diff --git a/tests/components/mopeka_ble/test.esp32.yaml b/tests/components/mopeka_ble/test.esp32.yaml index a115404f1c..dade44d145 100644 --- a/tests/components/mopeka_ble/test.esp32.yaml +++ b/tests/components/mopeka_ble/test.esp32.yaml @@ -1,3 +1 @@ -esp32_ble_tracker: - -mopeka_ble: +<<: !include common.yaml diff --git a/tests/components/mopeka_pro_check/common.yaml b/tests/components/mopeka_pro_check/common.yaml new file mode 100644 index 0000000000..147cbcb9de --- /dev/null +++ b/tests/components/mopeka_pro_check/common.yaml @@ -0,0 +1,16 @@ +esp32_ble_tracker: + +sensor: + - platform: mopeka_pro_check + mac_address: D3:75:F2:DC:16:91 + tank_type: CUSTOM + custom_distance_full: 40cm + custom_distance_empty: 10mm + temperature: + name: Propane test temp + level: + name: Propane test level + distance: + name: Propane test distance + battery_level: + name: Propane test battery level diff --git a/tests/components/mopeka_pro_check/test.esp32-c3-idf.yaml b/tests/components/mopeka_pro_check/test.esp32-c3-idf.yaml index 147cbcb9de..dade44d145 100644 --- a/tests/components/mopeka_pro_check/test.esp32-c3-idf.yaml +++ b/tests/components/mopeka_pro_check/test.esp32-c3-idf.yaml @@ -1,16 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: mopeka_pro_check - mac_address: D3:75:F2:DC:16:91 - tank_type: CUSTOM - custom_distance_full: 40cm - custom_distance_empty: 10mm - temperature: - name: Propane test temp - level: - name: Propane test level - distance: - name: Propane test distance - battery_level: - name: Propane test battery level +<<: !include common.yaml diff --git a/tests/components/mopeka_pro_check/test.esp32-c3.yaml b/tests/components/mopeka_pro_check/test.esp32-c3.yaml index 147cbcb9de..dade44d145 100644 --- a/tests/components/mopeka_pro_check/test.esp32-c3.yaml +++ b/tests/components/mopeka_pro_check/test.esp32-c3.yaml @@ -1,16 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: mopeka_pro_check - mac_address: D3:75:F2:DC:16:91 - tank_type: CUSTOM - custom_distance_full: 40cm - custom_distance_empty: 10mm - temperature: - name: Propane test temp - level: - name: Propane test level - distance: - name: Propane test distance - battery_level: - name: Propane test battery level +<<: !include common.yaml diff --git a/tests/components/mopeka_pro_check/test.esp32-idf.yaml b/tests/components/mopeka_pro_check/test.esp32-idf.yaml index 147cbcb9de..dade44d145 100644 --- a/tests/components/mopeka_pro_check/test.esp32-idf.yaml +++ b/tests/components/mopeka_pro_check/test.esp32-idf.yaml @@ -1,16 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: mopeka_pro_check - mac_address: D3:75:F2:DC:16:91 - tank_type: CUSTOM - custom_distance_full: 40cm - custom_distance_empty: 10mm - temperature: - name: Propane test temp - level: - name: Propane test level - distance: - name: Propane test distance - battery_level: - name: Propane test battery level +<<: !include common.yaml diff --git a/tests/components/mopeka_pro_check/test.esp32.yaml b/tests/components/mopeka_pro_check/test.esp32.yaml index 147cbcb9de..dade44d145 100644 --- a/tests/components/mopeka_pro_check/test.esp32.yaml +++ b/tests/components/mopeka_pro_check/test.esp32.yaml @@ -1,16 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: mopeka_pro_check - mac_address: D3:75:F2:DC:16:91 - tank_type: CUSTOM - custom_distance_full: 40cm - custom_distance_empty: 10mm - temperature: - name: Propane test temp - level: - name: Propane test level - distance: - name: Propane test distance - battery_level: - name: Propane test battery level +<<: !include common.yaml diff --git a/tests/components/mopeka_std_check/common.yaml b/tests/components/mopeka_std_check/common.yaml new file mode 100644 index 0000000000..383e2e2a19 --- /dev/null +++ b/tests/components/mopeka_std_check/common.yaml @@ -0,0 +1,15 @@ +esp32_ble_tracker: + +sensor: + # Example using 11kg 100% propane tank. + - platform: mopeka_std_check + mac_address: D3:75:F2:DC:16:91 + tank_type: Europe_11kg + temperature: + name: "Propane test temp" + level: + name: "Propane test level" + distance: + name: "Propane test distance" + battery_level: + name: "Propane test battery level" diff --git a/tests/components/mopeka_std_check/test.esp32-c3-idf.yaml b/tests/components/mopeka_std_check/test.esp32-c3-idf.yaml index 383e2e2a19..dade44d145 100644 --- a/tests/components/mopeka_std_check/test.esp32-c3-idf.yaml +++ b/tests/components/mopeka_std_check/test.esp32-c3-idf.yaml @@ -1,15 +1 @@ -esp32_ble_tracker: - -sensor: - # Example using 11kg 100% propane tank. - - platform: mopeka_std_check - mac_address: D3:75:F2:DC:16:91 - tank_type: Europe_11kg - temperature: - name: "Propane test temp" - level: - name: "Propane test level" - distance: - name: "Propane test distance" - battery_level: - name: "Propane test battery level" +<<: !include common.yaml diff --git a/tests/components/mopeka_std_check/test.esp32-c3.yaml b/tests/components/mopeka_std_check/test.esp32-c3.yaml index 383e2e2a19..dade44d145 100644 --- a/tests/components/mopeka_std_check/test.esp32-c3.yaml +++ b/tests/components/mopeka_std_check/test.esp32-c3.yaml @@ -1,15 +1 @@ -esp32_ble_tracker: - -sensor: - # Example using 11kg 100% propane tank. - - platform: mopeka_std_check - mac_address: D3:75:F2:DC:16:91 - tank_type: Europe_11kg - temperature: - name: "Propane test temp" - level: - name: "Propane test level" - distance: - name: "Propane test distance" - battery_level: - name: "Propane test battery level" +<<: !include common.yaml diff --git a/tests/components/mopeka_std_check/test.esp32-idf.yaml b/tests/components/mopeka_std_check/test.esp32-idf.yaml index 383e2e2a19..dade44d145 100644 --- a/tests/components/mopeka_std_check/test.esp32-idf.yaml +++ b/tests/components/mopeka_std_check/test.esp32-idf.yaml @@ -1,15 +1 @@ -esp32_ble_tracker: - -sensor: - # Example using 11kg 100% propane tank. - - platform: mopeka_std_check - mac_address: D3:75:F2:DC:16:91 - tank_type: Europe_11kg - temperature: - name: "Propane test temp" - level: - name: "Propane test level" - distance: - name: "Propane test distance" - battery_level: - name: "Propane test battery level" +<<: !include common.yaml diff --git a/tests/components/mopeka_std_check/test.esp32.yaml b/tests/components/mopeka_std_check/test.esp32.yaml index 383e2e2a19..dade44d145 100644 --- a/tests/components/mopeka_std_check/test.esp32.yaml +++ b/tests/components/mopeka_std_check/test.esp32.yaml @@ -1,15 +1 @@ -esp32_ble_tracker: - -sensor: - # Example using 11kg 100% propane tank. - - platform: mopeka_std_check - mac_address: D3:75:F2:DC:16:91 - tank_type: Europe_11kg - temperature: - name: "Propane test temp" - level: - name: "Propane test level" - distance: - name: "Propane test distance" - battery_level: - name: "Propane test battery level" +<<: !include common.yaml diff --git a/tests/components/my9231/common.yaml b/tests/components/my9231/common.yaml new file mode 100644 index 0000000000..3f2e81ef98 --- /dev/null +++ b/tests/components/my9231/common.yaml @@ -0,0 +1,26 @@ +my9231: + clock_pin: 5 + data_pin: 4 + num_channels: 6 + num_chips: 2 + bit_depth: 16 + +output: + - platform: my9231 + id: my_0 + channel: 0 + - platform: my9231 + id: my_1 + channel: 1 + - platform: my9231 + id: my_2 + channel: 2 + - platform: my9231 + id: my_3 + channel: 3 + - platform: my9231 + id: my_4 + channel: 4 + - platform: my9231 + id: my_5 + channel: 5 diff --git a/tests/components/my9231/test.esp32-c3-idf.yaml b/tests/components/my9231/test.esp32-c3-idf.yaml index 3f2e81ef98..dade44d145 100644 --- a/tests/components/my9231/test.esp32-c3-idf.yaml +++ b/tests/components/my9231/test.esp32-c3-idf.yaml @@ -1,26 +1 @@ -my9231: - clock_pin: 5 - data_pin: 4 - num_channels: 6 - num_chips: 2 - bit_depth: 16 - -output: - - platform: my9231 - id: my_0 - channel: 0 - - platform: my9231 - id: my_1 - channel: 1 - - platform: my9231 - id: my_2 - channel: 2 - - platform: my9231 - id: my_3 - channel: 3 - - platform: my9231 - id: my_4 - channel: 4 - - platform: my9231 - id: my_5 - channel: 5 +<<: !include common.yaml diff --git a/tests/components/my9231/test.esp32-c3.yaml b/tests/components/my9231/test.esp32-c3.yaml index 3f2e81ef98..dade44d145 100644 --- a/tests/components/my9231/test.esp32-c3.yaml +++ b/tests/components/my9231/test.esp32-c3.yaml @@ -1,26 +1 @@ -my9231: - clock_pin: 5 - data_pin: 4 - num_channels: 6 - num_chips: 2 - bit_depth: 16 - -output: - - platform: my9231 - id: my_0 - channel: 0 - - platform: my9231 - id: my_1 - channel: 1 - - platform: my9231 - id: my_2 - channel: 2 - - platform: my9231 - id: my_3 - channel: 3 - - platform: my9231 - id: my_4 - channel: 4 - - platform: my9231 - id: my_5 - channel: 5 +<<: !include common.yaml diff --git a/tests/components/my9231/test.esp32-idf.yaml b/tests/components/my9231/test.esp32-idf.yaml index 3f2e81ef98..dade44d145 100644 --- a/tests/components/my9231/test.esp32-idf.yaml +++ b/tests/components/my9231/test.esp32-idf.yaml @@ -1,26 +1 @@ -my9231: - clock_pin: 5 - data_pin: 4 - num_channels: 6 - num_chips: 2 - bit_depth: 16 - -output: - - platform: my9231 - id: my_0 - channel: 0 - - platform: my9231 - id: my_1 - channel: 1 - - platform: my9231 - id: my_2 - channel: 2 - - platform: my9231 - id: my_3 - channel: 3 - - platform: my9231 - id: my_4 - channel: 4 - - platform: my9231 - id: my_5 - channel: 5 +<<: !include common.yaml diff --git a/tests/components/my9231/test.esp32.yaml b/tests/components/my9231/test.esp32.yaml index 3f2e81ef98..dade44d145 100644 --- a/tests/components/my9231/test.esp32.yaml +++ b/tests/components/my9231/test.esp32.yaml @@ -1,26 +1 @@ -my9231: - clock_pin: 5 - data_pin: 4 - num_channels: 6 - num_chips: 2 - bit_depth: 16 - -output: - - platform: my9231 - id: my_0 - channel: 0 - - platform: my9231 - id: my_1 - channel: 1 - - platform: my9231 - id: my_2 - channel: 2 - - platform: my9231 - id: my_3 - channel: 3 - - platform: my9231 - id: my_4 - channel: 4 - - platform: my9231 - id: my_5 - channel: 5 +<<: !include common.yaml diff --git a/tests/components/my9231/test.esp8266.yaml b/tests/components/my9231/test.esp8266.yaml index 3f2e81ef98..dade44d145 100644 --- a/tests/components/my9231/test.esp8266.yaml +++ b/tests/components/my9231/test.esp8266.yaml @@ -1,26 +1 @@ -my9231: - clock_pin: 5 - data_pin: 4 - num_channels: 6 - num_chips: 2 - bit_depth: 16 - -output: - - platform: my9231 - id: my_0 - channel: 0 - - platform: my9231 - id: my_1 - channel: 1 - - platform: my9231 - id: my_2 - channel: 2 - - platform: my9231 - id: my_3 - channel: 3 - - platform: my9231 - id: my_4 - channel: 4 - - platform: my9231 - id: my_5 - channel: 5 +<<: !include common.yaml diff --git a/tests/components/my9231/test.rp2040.yaml b/tests/components/my9231/test.rp2040.yaml index 3f2e81ef98..dade44d145 100644 --- a/tests/components/my9231/test.rp2040.yaml +++ b/tests/components/my9231/test.rp2040.yaml @@ -1,26 +1 @@ -my9231: - clock_pin: 5 - data_pin: 4 - num_channels: 6 - num_chips: 2 - bit_depth: 16 - -output: - - platform: my9231 - id: my_0 - channel: 0 - - platform: my9231 - id: my_1 - channel: 1 - - platform: my9231 - id: my_2 - channel: 2 - - platform: my9231 - id: my_3 - channel: 3 - - platform: my9231 - id: my_4 - channel: 4 - - platform: my9231 - id: my_5 - channel: 5 +<<: !include common.yaml diff --git a/tests/components/network/common.yaml b/tests/components/network/common.yaml new file mode 100644 index 0000000000..147afd1e81 --- /dev/null +++ b/tests/components/network/common.yaml @@ -0,0 +1,6 @@ +wifi: + ssid: MySSID + password: password1 + +network: + enable_ipv6: true diff --git a/tests/components/network/test.esp32-c3-idf.yaml b/tests/components/network/test.esp32-c3-idf.yaml index 147afd1e81..dade44d145 100644 --- a/tests/components/network/test.esp32-c3-idf.yaml +++ b/tests/components/network/test.esp32-c3-idf.yaml @@ -1,6 +1 @@ -wifi: - ssid: MySSID - password: password1 - -network: - enable_ipv6: true +<<: !include common.yaml diff --git a/tests/components/network/test.esp32-c3.yaml b/tests/components/network/test.esp32-c3.yaml index 147afd1e81..dade44d145 100644 --- a/tests/components/network/test.esp32-c3.yaml +++ b/tests/components/network/test.esp32-c3.yaml @@ -1,6 +1 @@ -wifi: - ssid: MySSID - password: password1 - -network: - enable_ipv6: true +<<: !include common.yaml diff --git a/tests/components/network/test.esp32-idf.yaml b/tests/components/network/test.esp32-idf.yaml index 147afd1e81..dade44d145 100644 --- a/tests/components/network/test.esp32-idf.yaml +++ b/tests/components/network/test.esp32-idf.yaml @@ -1,6 +1 @@ -wifi: - ssid: MySSID - password: password1 - -network: - enable_ipv6: true +<<: !include common.yaml diff --git a/tests/components/network/test.esp32.yaml b/tests/components/network/test.esp32.yaml index 147afd1e81..dade44d145 100644 --- a/tests/components/network/test.esp32.yaml +++ b/tests/components/network/test.esp32.yaml @@ -1,6 +1 @@ -wifi: - ssid: MySSID - password: password1 - -network: - enable_ipv6: true +<<: !include common.yaml diff --git a/tests/components/network/test.esp8266.yaml b/tests/components/network/test.esp8266.yaml index 147afd1e81..dade44d145 100644 --- a/tests/components/network/test.esp8266.yaml +++ b/tests/components/network/test.esp8266.yaml @@ -1,6 +1 @@ -wifi: - ssid: MySSID - password: password1 - -network: - enable_ipv6: true +<<: !include common.yaml diff --git a/tests/components/network/test.rp2040.yaml b/tests/components/network/test.rp2040.yaml index 147afd1e81..dade44d145 100644 --- a/tests/components/network/test.rp2040.yaml +++ b/tests/components/network/test.rp2040.yaml @@ -1,6 +1 @@ -wifi: - ssid: MySSID - password: password1 - -network: - enable_ipv6: true +<<: !include common.yaml diff --git a/tests/components/noblex/common.yaml b/tests/components/noblex/common.yaml new file mode 100644 index 0000000000..f5e471a9a7 --- /dev/null +++ b/tests/components/noblex/common.yaml @@ -0,0 +1,20 @@ +remote_receiver: + id: rcvr + pin: 4 + dump: all + +remote_transmitter: + pin: 2 + carrier_duty_percent: 50% + +sensor: + - platform: template + id: noblex_ac_sensor + lambda: "return 21;" + +climate: + - platform: noblex + name: AC Living + id: noblex_ac + sensor: noblex_ac_sensor + receiver_id: rcvr diff --git a/tests/components/noblex/test.esp32-c3-idf.yaml b/tests/components/noblex/test.esp32-c3-idf.yaml index f5e471a9a7..dade44d145 100644 --- a/tests/components/noblex/test.esp32-c3-idf.yaml +++ b/tests/components/noblex/test.esp32-c3-idf.yaml @@ -1,20 +1 @@ -remote_receiver: - id: rcvr - pin: 4 - dump: all - -remote_transmitter: - pin: 2 - carrier_duty_percent: 50% - -sensor: - - platform: template - id: noblex_ac_sensor - lambda: "return 21;" - -climate: - - platform: noblex - name: AC Living - id: noblex_ac - sensor: noblex_ac_sensor - receiver_id: rcvr +<<: !include common.yaml diff --git a/tests/components/noblex/test.esp32-c3.yaml b/tests/components/noblex/test.esp32-c3.yaml index f5e471a9a7..dade44d145 100644 --- a/tests/components/noblex/test.esp32-c3.yaml +++ b/tests/components/noblex/test.esp32-c3.yaml @@ -1,20 +1 @@ -remote_receiver: - id: rcvr - pin: 4 - dump: all - -remote_transmitter: - pin: 2 - carrier_duty_percent: 50% - -sensor: - - platform: template - id: noblex_ac_sensor - lambda: "return 21;" - -climate: - - platform: noblex - name: AC Living - id: noblex_ac - sensor: noblex_ac_sensor - receiver_id: rcvr +<<: !include common.yaml diff --git a/tests/components/noblex/test.esp32-idf.yaml b/tests/components/noblex/test.esp32-idf.yaml index f5e471a9a7..dade44d145 100644 --- a/tests/components/noblex/test.esp32-idf.yaml +++ b/tests/components/noblex/test.esp32-idf.yaml @@ -1,20 +1 @@ -remote_receiver: - id: rcvr - pin: 4 - dump: all - -remote_transmitter: - pin: 2 - carrier_duty_percent: 50% - -sensor: - - platform: template - id: noblex_ac_sensor - lambda: "return 21;" - -climate: - - platform: noblex - name: AC Living - id: noblex_ac - sensor: noblex_ac_sensor - receiver_id: rcvr +<<: !include common.yaml diff --git a/tests/components/noblex/test.esp32.yaml b/tests/components/noblex/test.esp32.yaml index f5e471a9a7..dade44d145 100644 --- a/tests/components/noblex/test.esp32.yaml +++ b/tests/components/noblex/test.esp32.yaml @@ -1,20 +1 @@ -remote_receiver: - id: rcvr - pin: 4 - dump: all - -remote_transmitter: - pin: 2 - carrier_duty_percent: 50% - -sensor: - - platform: template - id: noblex_ac_sensor - lambda: "return 21;" - -climate: - - platform: noblex - name: AC Living - id: noblex_ac - sensor: noblex_ac_sensor - receiver_id: rcvr +<<: !include common.yaml diff --git a/tests/components/noblex/test.esp8266.yaml b/tests/components/noblex/test.esp8266.yaml index f5e471a9a7..dade44d145 100644 --- a/tests/components/noblex/test.esp8266.yaml +++ b/tests/components/noblex/test.esp8266.yaml @@ -1,20 +1 @@ -remote_receiver: - id: rcvr - pin: 4 - dump: all - -remote_transmitter: - pin: 2 - carrier_duty_percent: 50% - -sensor: - - platform: template - id: noblex_ac_sensor - lambda: "return 21;" - -climate: - - platform: noblex - name: AC Living - id: noblex_ac - sensor: noblex_ac_sensor - receiver_id: rcvr +<<: !include common.yaml diff --git a/tests/components/ota/common.yaml b/tests/components/ota/common.yaml new file mode 100644 index 0000000000..367454995f --- /dev/null +++ b/tests/components/ota/common.yaml @@ -0,0 +1,30 @@ +wifi: + ssid: MySSID + password: password1 + +ota: + safe_mode: true + password: "superlongpasswordthatnoonewillknow" + port: 3286 + reboot_timeout: 2min + num_attempts: 5 + 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); diff --git a/tests/components/ota/test.esp32-c3-idf.yaml b/tests/components/ota/test.esp32-c3-idf.yaml index 367454995f..dade44d145 100644 --- a/tests/components/ota/test.esp32-c3-idf.yaml +++ b/tests/components/ota/test.esp32-c3-idf.yaml @@ -1,30 +1 @@ -wifi: - ssid: MySSID - password: password1 - -ota: - safe_mode: true - password: "superlongpasswordthatnoonewillknow" - port: 3286 - reboot_timeout: 2min - num_attempts: 5 - 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); +<<: !include common.yaml diff --git a/tests/components/ota/test.esp32-c3.yaml b/tests/components/ota/test.esp32-c3.yaml index 367454995f..dade44d145 100644 --- a/tests/components/ota/test.esp32-c3.yaml +++ b/tests/components/ota/test.esp32-c3.yaml @@ -1,30 +1 @@ -wifi: - ssid: MySSID - password: password1 - -ota: - safe_mode: true - password: "superlongpasswordthatnoonewillknow" - port: 3286 - reboot_timeout: 2min - num_attempts: 5 - 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); +<<: !include common.yaml diff --git a/tests/components/ota/test.esp32-idf.yaml b/tests/components/ota/test.esp32-idf.yaml index 367454995f..dade44d145 100644 --- a/tests/components/ota/test.esp32-idf.yaml +++ b/tests/components/ota/test.esp32-idf.yaml @@ -1,30 +1 @@ -wifi: - ssid: MySSID - password: password1 - -ota: - safe_mode: true - password: "superlongpasswordthatnoonewillknow" - port: 3286 - reboot_timeout: 2min - num_attempts: 5 - 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); +<<: !include common.yaml diff --git a/tests/components/ota/test.esp32.yaml b/tests/components/ota/test.esp32.yaml index 367454995f..dade44d145 100644 --- a/tests/components/ota/test.esp32.yaml +++ b/tests/components/ota/test.esp32.yaml @@ -1,30 +1 @@ -wifi: - ssid: MySSID - password: password1 - -ota: - safe_mode: true - password: "superlongpasswordthatnoonewillknow" - port: 3286 - reboot_timeout: 2min - num_attempts: 5 - 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); +<<: !include common.yaml diff --git a/tests/components/ota/test.esp8266.yaml b/tests/components/ota/test.esp8266.yaml index 367454995f..dade44d145 100644 --- a/tests/components/ota/test.esp8266.yaml +++ b/tests/components/ota/test.esp8266.yaml @@ -1,30 +1 @@ -wifi: - ssid: MySSID - password: password1 - -ota: - safe_mode: true - password: "superlongpasswordthatnoonewillknow" - port: 3286 - reboot_timeout: 2min - num_attempts: 5 - 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); +<<: !include common.yaml diff --git a/tests/components/ota/test.rp2040.yaml b/tests/components/ota/test.rp2040.yaml index 367454995f..dade44d145 100644 --- a/tests/components/ota/test.rp2040.yaml +++ b/tests/components/ota/test.rp2040.yaml @@ -1,30 +1 @@ -wifi: - ssid: MySSID - password: password1 - -ota: - safe_mode: true - password: "superlongpasswordthatnoonewillknow" - port: 3286 - reboot_timeout: 2min - num_attempts: 5 - 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); +<<: !include common.yaml diff --git a/tests/components/pid/common.yaml b/tests/components/pid/common.yaml new file mode 100644 index 0000000000..5f7762872f --- /dev/null +++ b/tests/components/pid/common.yaml @@ -0,0 +1,56 @@ +esphome: + on_boot: + then: + - climate.pid.autotune: pid_climate + - climate.pid.autotune: + id: pid_climate + noiseband: 0.25 + positive_output: 25% + negative_output: -25% + - climate.pid.set_control_parameters: + id: pid_climate + kp: 0.0 + ki: 0.0 + kd: 0.0 + - climate.pid.reset_integral_term: pid_climate + +output: + - platform: slow_pwm + pin: 4 + id: pid_slow_pwm + period: 15s + restart_cycle_on_state_change: false + +sensor: + - platform: template + id: template_sensor1 + lambda: |- + if (millis() > 10000) { + return 42.0; + } else { + return 0.0; + } + update_interval: 60s + +climate: + - platform: pid + id: pid_climate + name: PID Climate Controller + sensor: template_sensor1 + humidity_sensor: template_sensor1 + default_target_temperature: 21°C + heat_output: pid_slow_pwm + control_parameters: + kp: 0.0 + ki: 0.0 + kd: 0.0 + max_integral: 0.0 + output_averaging_samples: 1 + derivative_averaging_samples: 1 + deadband_parameters: + threshold_high: 0.4 + threshold_low: -2.0 + kp_multiplier: 0.0 + ki_multiplier: 0.0 + kd_multiplier: 0.0 + deadband_output_averaging_samples: 1 diff --git a/tests/components/pid/test.esp32-c3-idf.yaml b/tests/components/pid/test.esp32-c3-idf.yaml index 5f7762872f..dade44d145 100644 --- a/tests/components/pid/test.esp32-c3-idf.yaml +++ b/tests/components/pid/test.esp32-c3-idf.yaml @@ -1,56 +1 @@ -esphome: - on_boot: - then: - - climate.pid.autotune: pid_climate - - climate.pid.autotune: - id: pid_climate - noiseband: 0.25 - positive_output: 25% - negative_output: -25% - - climate.pid.set_control_parameters: - id: pid_climate - kp: 0.0 - ki: 0.0 - kd: 0.0 - - climate.pid.reset_integral_term: pid_climate - -output: - - platform: slow_pwm - pin: 4 - id: pid_slow_pwm - period: 15s - restart_cycle_on_state_change: false - -sensor: - - platform: template - id: template_sensor1 - lambda: |- - if (millis() > 10000) { - return 42.0; - } else { - return 0.0; - } - update_interval: 60s - -climate: - - platform: pid - id: pid_climate - name: PID Climate Controller - sensor: template_sensor1 - humidity_sensor: template_sensor1 - default_target_temperature: 21°C - heat_output: pid_slow_pwm - control_parameters: - kp: 0.0 - ki: 0.0 - kd: 0.0 - max_integral: 0.0 - output_averaging_samples: 1 - derivative_averaging_samples: 1 - deadband_parameters: - threshold_high: 0.4 - threshold_low: -2.0 - kp_multiplier: 0.0 - ki_multiplier: 0.0 - kd_multiplier: 0.0 - deadband_output_averaging_samples: 1 +<<: !include common.yaml diff --git a/tests/components/pid/test.esp32-c3.yaml b/tests/components/pid/test.esp32-c3.yaml index 5f7762872f..dade44d145 100644 --- a/tests/components/pid/test.esp32-c3.yaml +++ b/tests/components/pid/test.esp32-c3.yaml @@ -1,56 +1 @@ -esphome: - on_boot: - then: - - climate.pid.autotune: pid_climate - - climate.pid.autotune: - id: pid_climate - noiseband: 0.25 - positive_output: 25% - negative_output: -25% - - climate.pid.set_control_parameters: - id: pid_climate - kp: 0.0 - ki: 0.0 - kd: 0.0 - - climate.pid.reset_integral_term: pid_climate - -output: - - platform: slow_pwm - pin: 4 - id: pid_slow_pwm - period: 15s - restart_cycle_on_state_change: false - -sensor: - - platform: template - id: template_sensor1 - lambda: |- - if (millis() > 10000) { - return 42.0; - } else { - return 0.0; - } - update_interval: 60s - -climate: - - platform: pid - id: pid_climate - name: PID Climate Controller - sensor: template_sensor1 - humidity_sensor: template_sensor1 - default_target_temperature: 21°C - heat_output: pid_slow_pwm - control_parameters: - kp: 0.0 - ki: 0.0 - kd: 0.0 - max_integral: 0.0 - output_averaging_samples: 1 - derivative_averaging_samples: 1 - deadband_parameters: - threshold_high: 0.4 - threshold_low: -2.0 - kp_multiplier: 0.0 - ki_multiplier: 0.0 - kd_multiplier: 0.0 - deadband_output_averaging_samples: 1 +<<: !include common.yaml diff --git a/tests/components/pid/test.esp32-idf.yaml b/tests/components/pid/test.esp32-idf.yaml index 5f7762872f..dade44d145 100644 --- a/tests/components/pid/test.esp32-idf.yaml +++ b/tests/components/pid/test.esp32-idf.yaml @@ -1,56 +1 @@ -esphome: - on_boot: - then: - - climate.pid.autotune: pid_climate - - climate.pid.autotune: - id: pid_climate - noiseband: 0.25 - positive_output: 25% - negative_output: -25% - - climate.pid.set_control_parameters: - id: pid_climate - kp: 0.0 - ki: 0.0 - kd: 0.0 - - climate.pid.reset_integral_term: pid_climate - -output: - - platform: slow_pwm - pin: 4 - id: pid_slow_pwm - period: 15s - restart_cycle_on_state_change: false - -sensor: - - platform: template - id: template_sensor1 - lambda: |- - if (millis() > 10000) { - return 42.0; - } else { - return 0.0; - } - update_interval: 60s - -climate: - - platform: pid - id: pid_climate - name: PID Climate Controller - sensor: template_sensor1 - humidity_sensor: template_sensor1 - default_target_temperature: 21°C - heat_output: pid_slow_pwm - control_parameters: - kp: 0.0 - ki: 0.0 - kd: 0.0 - max_integral: 0.0 - output_averaging_samples: 1 - derivative_averaging_samples: 1 - deadband_parameters: - threshold_high: 0.4 - threshold_low: -2.0 - kp_multiplier: 0.0 - ki_multiplier: 0.0 - kd_multiplier: 0.0 - deadband_output_averaging_samples: 1 +<<: !include common.yaml diff --git a/tests/components/pid/test.esp32.yaml b/tests/components/pid/test.esp32.yaml index 5f7762872f..dade44d145 100644 --- a/tests/components/pid/test.esp32.yaml +++ b/tests/components/pid/test.esp32.yaml @@ -1,56 +1 @@ -esphome: - on_boot: - then: - - climate.pid.autotune: pid_climate - - climate.pid.autotune: - id: pid_climate - noiseband: 0.25 - positive_output: 25% - negative_output: -25% - - climate.pid.set_control_parameters: - id: pid_climate - kp: 0.0 - ki: 0.0 - kd: 0.0 - - climate.pid.reset_integral_term: pid_climate - -output: - - platform: slow_pwm - pin: 4 - id: pid_slow_pwm - period: 15s - restart_cycle_on_state_change: false - -sensor: - - platform: template - id: template_sensor1 - lambda: |- - if (millis() > 10000) { - return 42.0; - } else { - return 0.0; - } - update_interval: 60s - -climate: - - platform: pid - id: pid_climate - name: PID Climate Controller - sensor: template_sensor1 - humidity_sensor: template_sensor1 - default_target_temperature: 21°C - heat_output: pid_slow_pwm - control_parameters: - kp: 0.0 - ki: 0.0 - kd: 0.0 - max_integral: 0.0 - output_averaging_samples: 1 - derivative_averaging_samples: 1 - deadband_parameters: - threshold_high: 0.4 - threshold_low: -2.0 - kp_multiplier: 0.0 - ki_multiplier: 0.0 - kd_multiplier: 0.0 - deadband_output_averaging_samples: 1 +<<: !include common.yaml diff --git a/tests/components/pid/test.esp8266.yaml b/tests/components/pid/test.esp8266.yaml index 5f7762872f..dade44d145 100644 --- a/tests/components/pid/test.esp8266.yaml +++ b/tests/components/pid/test.esp8266.yaml @@ -1,56 +1 @@ -esphome: - on_boot: - then: - - climate.pid.autotune: pid_climate - - climate.pid.autotune: - id: pid_climate - noiseband: 0.25 - positive_output: 25% - negative_output: -25% - - climate.pid.set_control_parameters: - id: pid_climate - kp: 0.0 - ki: 0.0 - kd: 0.0 - - climate.pid.reset_integral_term: pid_climate - -output: - - platform: slow_pwm - pin: 4 - id: pid_slow_pwm - period: 15s - restart_cycle_on_state_change: false - -sensor: - - platform: template - id: template_sensor1 - lambda: |- - if (millis() > 10000) { - return 42.0; - } else { - return 0.0; - } - update_interval: 60s - -climate: - - platform: pid - id: pid_climate - name: PID Climate Controller - sensor: template_sensor1 - humidity_sensor: template_sensor1 - default_target_temperature: 21°C - heat_output: pid_slow_pwm - control_parameters: - kp: 0.0 - ki: 0.0 - kd: 0.0 - max_integral: 0.0 - output_averaging_samples: 1 - derivative_averaging_samples: 1 - deadband_parameters: - threshold_high: 0.4 - threshold_low: -2.0 - kp_multiplier: 0.0 - ki_multiplier: 0.0 - kd_multiplier: 0.0 - deadband_output_averaging_samples: 1 +<<: !include common.yaml diff --git a/tests/components/pid/test.rp2040.yaml b/tests/components/pid/test.rp2040.yaml index 5f7762872f..dade44d145 100644 --- a/tests/components/pid/test.rp2040.yaml +++ b/tests/components/pid/test.rp2040.yaml @@ -1,56 +1 @@ -esphome: - on_boot: - then: - - climate.pid.autotune: pid_climate - - climate.pid.autotune: - id: pid_climate - noiseband: 0.25 - positive_output: 25% - negative_output: -25% - - climate.pid.set_control_parameters: - id: pid_climate - kp: 0.0 - ki: 0.0 - kd: 0.0 - - climate.pid.reset_integral_term: pid_climate - -output: - - platform: slow_pwm - pin: 4 - id: pid_slow_pwm - period: 15s - restart_cycle_on_state_change: false - -sensor: - - platform: template - id: template_sensor1 - lambda: |- - if (millis() > 10000) { - return 42.0; - } else { - return 0.0; - } - update_interval: 60s - -climate: - - platform: pid - id: pid_climate - name: PID Climate Controller - sensor: template_sensor1 - humidity_sensor: template_sensor1 - default_target_temperature: 21°C - heat_output: pid_slow_pwm - control_parameters: - kp: 0.0 - ki: 0.0 - kd: 0.0 - max_integral: 0.0 - output_averaging_samples: 1 - derivative_averaging_samples: 1 - deadband_parameters: - threshold_high: 0.4 - threshold_low: -2.0 - kp_multiplier: 0.0 - ki_multiplier: 0.0 - kd_multiplier: 0.0 - deadband_output_averaging_samples: 1 +<<: !include common.yaml diff --git a/tests/components/power_supply/common.yaml b/tests/components/power_supply/common.yaml new file mode 100644 index 0000000000..3fefc4d425 --- /dev/null +++ b/tests/components/power_supply/common.yaml @@ -0,0 +1,6 @@ +power_supply: + - id: atx_power_supply + enable_time: 20ms + keep_on_time: 10s + enable_on_boot: true + pin: 4 diff --git a/tests/components/power_supply/test.esp32-c3-idf.yaml b/tests/components/power_supply/test.esp32-c3-idf.yaml index 3fefc4d425..dade44d145 100644 --- a/tests/components/power_supply/test.esp32-c3-idf.yaml +++ b/tests/components/power_supply/test.esp32-c3-idf.yaml @@ -1,6 +1 @@ -power_supply: - - id: atx_power_supply - enable_time: 20ms - keep_on_time: 10s - enable_on_boot: true - pin: 4 +<<: !include common.yaml diff --git a/tests/components/power_supply/test.esp32-c3.yaml b/tests/components/power_supply/test.esp32-c3.yaml index 3fefc4d425..dade44d145 100644 --- a/tests/components/power_supply/test.esp32-c3.yaml +++ b/tests/components/power_supply/test.esp32-c3.yaml @@ -1,6 +1 @@ -power_supply: - - id: atx_power_supply - enable_time: 20ms - keep_on_time: 10s - enable_on_boot: true - pin: 4 +<<: !include common.yaml diff --git a/tests/components/power_supply/test.esp32-idf.yaml b/tests/components/power_supply/test.esp32-idf.yaml index 3fefc4d425..dade44d145 100644 --- a/tests/components/power_supply/test.esp32-idf.yaml +++ b/tests/components/power_supply/test.esp32-idf.yaml @@ -1,6 +1 @@ -power_supply: - - id: atx_power_supply - enable_time: 20ms - keep_on_time: 10s - enable_on_boot: true - pin: 4 +<<: !include common.yaml diff --git a/tests/components/power_supply/test.esp32.yaml b/tests/components/power_supply/test.esp32.yaml index 3fefc4d425..dade44d145 100644 --- a/tests/components/power_supply/test.esp32.yaml +++ b/tests/components/power_supply/test.esp32.yaml @@ -1,6 +1 @@ -power_supply: - - id: atx_power_supply - enable_time: 20ms - keep_on_time: 10s - enable_on_boot: true - pin: 4 +<<: !include common.yaml diff --git a/tests/components/power_supply/test.esp8266.yaml b/tests/components/power_supply/test.esp8266.yaml index 3fefc4d425..dade44d145 100644 --- a/tests/components/power_supply/test.esp8266.yaml +++ b/tests/components/power_supply/test.esp8266.yaml @@ -1,6 +1 @@ -power_supply: - - id: atx_power_supply - enable_time: 20ms - keep_on_time: 10s - enable_on_boot: true - pin: 4 +<<: !include common.yaml diff --git a/tests/components/power_supply/test.rp2040.yaml b/tests/components/power_supply/test.rp2040.yaml index 3fefc4d425..dade44d145 100644 --- a/tests/components/power_supply/test.rp2040.yaml +++ b/tests/components/power_supply/test.rp2040.yaml @@ -1,6 +1 @@ -power_supply: - - id: atx_power_supply - enable_time: 20ms - keep_on_time: 10s - enable_on_boot: true - pin: 4 +<<: !include common.yaml diff --git a/tests/components/prometheus/common.yaml b/tests/components/prometheus/common.yaml new file mode 100644 index 0000000000..c8ce17da88 --- /dev/null +++ b/tests/components/prometheus/common.yaml @@ -0,0 +1,21 @@ +wifi: + ssid: MySSID + password: password1 + +sensor: + - platform: template + id: template_sensor1 + lambda: |- + if (millis() > 10000) { + return 42.0; + } else { + return 0.0; + } + update_interval: 60s + +prometheus: + include_internal: true + relabel: + template_sensor1: + id: hellow_world + name: Hello World diff --git a/tests/components/prometheus/test.esp32-c3-idf.yaml b/tests/components/prometheus/test.esp32-c3-idf.yaml index c8ce17da88..dade44d145 100644 --- a/tests/components/prometheus/test.esp32-c3-idf.yaml +++ b/tests/components/prometheus/test.esp32-c3-idf.yaml @@ -1,21 +1 @@ -wifi: - ssid: MySSID - password: password1 - -sensor: - - platform: template - id: template_sensor1 - lambda: |- - if (millis() > 10000) { - return 42.0; - } else { - return 0.0; - } - update_interval: 60s - -prometheus: - include_internal: true - relabel: - template_sensor1: - id: hellow_world - name: Hello World +<<: !include common.yaml diff --git a/tests/components/prometheus/test.esp32-c3.yaml b/tests/components/prometheus/test.esp32-c3.yaml index c8ce17da88..dade44d145 100644 --- a/tests/components/prometheus/test.esp32-c3.yaml +++ b/tests/components/prometheus/test.esp32-c3.yaml @@ -1,21 +1 @@ -wifi: - ssid: MySSID - password: password1 - -sensor: - - platform: template - id: template_sensor1 - lambda: |- - if (millis() > 10000) { - return 42.0; - } else { - return 0.0; - } - update_interval: 60s - -prometheus: - include_internal: true - relabel: - template_sensor1: - id: hellow_world - name: Hello World +<<: !include common.yaml diff --git a/tests/components/prometheus/test.esp32-idf.yaml b/tests/components/prometheus/test.esp32-idf.yaml index c8ce17da88..dade44d145 100644 --- a/tests/components/prometheus/test.esp32-idf.yaml +++ b/tests/components/prometheus/test.esp32-idf.yaml @@ -1,21 +1 @@ -wifi: - ssid: MySSID - password: password1 - -sensor: - - platform: template - id: template_sensor1 - lambda: |- - if (millis() > 10000) { - return 42.0; - } else { - return 0.0; - } - update_interval: 60s - -prometheus: - include_internal: true - relabel: - template_sensor1: - id: hellow_world - name: Hello World +<<: !include common.yaml diff --git a/tests/components/prometheus/test.esp32.yaml b/tests/components/prometheus/test.esp32.yaml index c8ce17da88..dade44d145 100644 --- a/tests/components/prometheus/test.esp32.yaml +++ b/tests/components/prometheus/test.esp32.yaml @@ -1,21 +1 @@ -wifi: - ssid: MySSID - password: password1 - -sensor: - - platform: template - id: template_sensor1 - lambda: |- - if (millis() > 10000) { - return 42.0; - } else { - return 0.0; - } - update_interval: 60s - -prometheus: - include_internal: true - relabel: - template_sensor1: - id: hellow_world - name: Hello World +<<: !include common.yaml diff --git a/tests/components/prometheus/test.esp8266.yaml b/tests/components/prometheus/test.esp8266.yaml index c8ce17da88..dade44d145 100644 --- a/tests/components/prometheus/test.esp8266.yaml +++ b/tests/components/prometheus/test.esp8266.yaml @@ -1,21 +1 @@ -wifi: - ssid: MySSID - password: password1 - -sensor: - - platform: template - id: template_sensor1 - lambda: |- - if (millis() > 10000) { - return 42.0; - } else { - return 0.0; - } - update_interval: 60s - -prometheus: - include_internal: true - relabel: - template_sensor1: - id: hellow_world - name: Hello World +<<: !include common.yaml diff --git a/tests/components/psram/common.yaml b/tests/components/psram/common.yaml new file mode 100644 index 0000000000..cfd39f77fe --- /dev/null +++ b/tests/components/psram/common.yaml @@ -0,0 +1,3 @@ +psram: + mode: octal + speed: 80MHz diff --git a/tests/components/psram/test.esp32-c3-idf.yaml b/tests/components/psram/test.esp32-c3-idf.yaml index cfd39f77fe..dade44d145 100644 --- a/tests/components/psram/test.esp32-c3-idf.yaml +++ b/tests/components/psram/test.esp32-c3-idf.yaml @@ -1,3 +1 @@ -psram: - mode: octal - speed: 80MHz +<<: !include common.yaml diff --git a/tests/components/psram/test.esp32-c3.yaml b/tests/components/psram/test.esp32-c3.yaml index cfd39f77fe..dade44d145 100644 --- a/tests/components/psram/test.esp32-c3.yaml +++ b/tests/components/psram/test.esp32-c3.yaml @@ -1,3 +1 @@ -psram: - mode: octal - speed: 80MHz +<<: !include common.yaml diff --git a/tests/components/psram/test.esp32-idf.yaml b/tests/components/psram/test.esp32-idf.yaml index cfd39f77fe..dade44d145 100644 --- a/tests/components/psram/test.esp32-idf.yaml +++ b/tests/components/psram/test.esp32-idf.yaml @@ -1,3 +1 @@ -psram: - mode: octal - speed: 80MHz +<<: !include common.yaml diff --git a/tests/components/psram/test.esp32.yaml b/tests/components/psram/test.esp32.yaml index cfd39f77fe..dade44d145 100644 --- a/tests/components/psram/test.esp32.yaml +++ b/tests/components/psram/test.esp32.yaml @@ -1,3 +1 @@ -psram: - mode: octal - speed: 80MHz +<<: !include common.yaml diff --git a/tests/components/pulse_counter/common.yaml b/tests/components/pulse_counter/common.yaml new file mode 100644 index 0000000000..556b43ee6f --- /dev/null +++ b/tests/components/pulse_counter/common.yaml @@ -0,0 +1,9 @@ +sensor: + - platform: pulse_counter + name: Pulse Counter + pin: 4 + count_mode: + rising_edge: INCREMENT + falling_edge: DECREMENT + internal_filter: 13us + update_interval: 15s diff --git a/tests/components/pulse_counter/test.esp32-c3-idf.yaml b/tests/components/pulse_counter/test.esp32-c3-idf.yaml index 556b43ee6f..dade44d145 100644 --- a/tests/components/pulse_counter/test.esp32-c3-idf.yaml +++ b/tests/components/pulse_counter/test.esp32-c3-idf.yaml @@ -1,9 +1 @@ -sensor: - - platform: pulse_counter - name: Pulse Counter - pin: 4 - count_mode: - rising_edge: INCREMENT - falling_edge: DECREMENT - internal_filter: 13us - update_interval: 15s +<<: !include common.yaml diff --git a/tests/components/pulse_counter/test.esp32-c3.yaml b/tests/components/pulse_counter/test.esp32-c3.yaml index 556b43ee6f..dade44d145 100644 --- a/tests/components/pulse_counter/test.esp32-c3.yaml +++ b/tests/components/pulse_counter/test.esp32-c3.yaml @@ -1,9 +1 @@ -sensor: - - platform: pulse_counter - name: Pulse Counter - pin: 4 - count_mode: - rising_edge: INCREMENT - falling_edge: DECREMENT - internal_filter: 13us - update_interval: 15s +<<: !include common.yaml diff --git a/tests/components/pulse_counter/test.esp32-idf.yaml b/tests/components/pulse_counter/test.esp32-idf.yaml index 556b43ee6f..dade44d145 100644 --- a/tests/components/pulse_counter/test.esp32-idf.yaml +++ b/tests/components/pulse_counter/test.esp32-idf.yaml @@ -1,9 +1 @@ -sensor: - - platform: pulse_counter - name: Pulse Counter - pin: 4 - count_mode: - rising_edge: INCREMENT - falling_edge: DECREMENT - internal_filter: 13us - update_interval: 15s +<<: !include common.yaml diff --git a/tests/components/pulse_counter/test.esp32.yaml b/tests/components/pulse_counter/test.esp32.yaml index 556b43ee6f..dade44d145 100644 --- a/tests/components/pulse_counter/test.esp32.yaml +++ b/tests/components/pulse_counter/test.esp32.yaml @@ -1,9 +1 @@ -sensor: - - platform: pulse_counter - name: Pulse Counter - pin: 4 - count_mode: - rising_edge: INCREMENT - falling_edge: DECREMENT - internal_filter: 13us - update_interval: 15s +<<: !include common.yaml diff --git a/tests/components/pulse_counter/test.esp8266.yaml b/tests/components/pulse_counter/test.esp8266.yaml index 556b43ee6f..dade44d145 100644 --- a/tests/components/pulse_counter/test.esp8266.yaml +++ b/tests/components/pulse_counter/test.esp8266.yaml @@ -1,9 +1 @@ -sensor: - - platform: pulse_counter - name: Pulse Counter - pin: 4 - count_mode: - rising_edge: INCREMENT - falling_edge: DECREMENT - internal_filter: 13us - update_interval: 15s +<<: !include common.yaml diff --git a/tests/components/pulse_counter/test.rp2040.yaml b/tests/components/pulse_counter/test.rp2040.yaml index 556b43ee6f..dade44d145 100644 --- a/tests/components/pulse_counter/test.rp2040.yaml +++ b/tests/components/pulse_counter/test.rp2040.yaml @@ -1,9 +1 @@ -sensor: - - platform: pulse_counter - name: Pulse Counter - pin: 4 - count_mode: - rising_edge: INCREMENT - falling_edge: DECREMENT - internal_filter: 13us - update_interval: 15s +<<: !include common.yaml diff --git a/tests/components/pulse_meter/common.yaml b/tests/components/pulse_meter/common.yaml new file mode 100644 index 0000000000..a83ec478bb --- /dev/null +++ b/tests/components/pulse_meter/common.yaml @@ -0,0 +1,13 @@ +sensor: + - platform: pulse_meter + id: pulse_meter_sensor + name: Pulse Meter + pin: 4 + internal_filter: 100ms + timeout: 2 min + on_value: + - pulse_meter.set_total_pulses: + id: pulse_meter_sensor + value: 12345 + total: + name: Pulse Meter Total diff --git a/tests/components/pulse_meter/test.esp32-c3-idf.yaml b/tests/components/pulse_meter/test.esp32-c3-idf.yaml index a83ec478bb..dade44d145 100644 --- a/tests/components/pulse_meter/test.esp32-c3-idf.yaml +++ b/tests/components/pulse_meter/test.esp32-c3-idf.yaml @@ -1,13 +1 @@ -sensor: - - platform: pulse_meter - id: pulse_meter_sensor - name: Pulse Meter - pin: 4 - internal_filter: 100ms - timeout: 2 min - on_value: - - pulse_meter.set_total_pulses: - id: pulse_meter_sensor - value: 12345 - total: - name: Pulse Meter Total +<<: !include common.yaml diff --git a/tests/components/pulse_meter/test.esp32-c3.yaml b/tests/components/pulse_meter/test.esp32-c3.yaml index a83ec478bb..dade44d145 100644 --- a/tests/components/pulse_meter/test.esp32-c3.yaml +++ b/tests/components/pulse_meter/test.esp32-c3.yaml @@ -1,13 +1 @@ -sensor: - - platform: pulse_meter - id: pulse_meter_sensor - name: Pulse Meter - pin: 4 - internal_filter: 100ms - timeout: 2 min - on_value: - - pulse_meter.set_total_pulses: - id: pulse_meter_sensor - value: 12345 - total: - name: Pulse Meter Total +<<: !include common.yaml diff --git a/tests/components/pulse_meter/test.esp32-idf.yaml b/tests/components/pulse_meter/test.esp32-idf.yaml index a83ec478bb..dade44d145 100644 --- a/tests/components/pulse_meter/test.esp32-idf.yaml +++ b/tests/components/pulse_meter/test.esp32-idf.yaml @@ -1,13 +1 @@ -sensor: - - platform: pulse_meter - id: pulse_meter_sensor - name: Pulse Meter - pin: 4 - internal_filter: 100ms - timeout: 2 min - on_value: - - pulse_meter.set_total_pulses: - id: pulse_meter_sensor - value: 12345 - total: - name: Pulse Meter Total +<<: !include common.yaml diff --git a/tests/components/pulse_meter/test.esp32.yaml b/tests/components/pulse_meter/test.esp32.yaml index a83ec478bb..dade44d145 100644 --- a/tests/components/pulse_meter/test.esp32.yaml +++ b/tests/components/pulse_meter/test.esp32.yaml @@ -1,13 +1 @@ -sensor: - - platform: pulse_meter - id: pulse_meter_sensor - name: Pulse Meter - pin: 4 - internal_filter: 100ms - timeout: 2 min - on_value: - - pulse_meter.set_total_pulses: - id: pulse_meter_sensor - value: 12345 - total: - name: Pulse Meter Total +<<: !include common.yaml diff --git a/tests/components/pulse_meter/test.esp8266.yaml b/tests/components/pulse_meter/test.esp8266.yaml index a83ec478bb..dade44d145 100644 --- a/tests/components/pulse_meter/test.esp8266.yaml +++ b/tests/components/pulse_meter/test.esp8266.yaml @@ -1,13 +1 @@ -sensor: - - platform: pulse_meter - id: pulse_meter_sensor - name: Pulse Meter - pin: 4 - internal_filter: 100ms - timeout: 2 min - on_value: - - pulse_meter.set_total_pulses: - id: pulse_meter_sensor - value: 12345 - total: - name: Pulse Meter Total +<<: !include common.yaml diff --git a/tests/components/pulse_meter/test.rp2040.yaml b/tests/components/pulse_meter/test.rp2040.yaml index a83ec478bb..dade44d145 100644 --- a/tests/components/pulse_meter/test.rp2040.yaml +++ b/tests/components/pulse_meter/test.rp2040.yaml @@ -1,13 +1 @@ -sensor: - - platform: pulse_meter - id: pulse_meter_sensor - name: Pulse Meter - pin: 4 - internal_filter: 100ms - timeout: 2 min - on_value: - - pulse_meter.set_total_pulses: - id: pulse_meter_sensor - value: 12345 - total: - name: Pulse Meter Total +<<: !include common.yaml diff --git a/tests/components/pulse_width/common.yaml b/tests/components/pulse_width/common.yaml new file mode 100644 index 0000000000..fbda7cda28 --- /dev/null +++ b/tests/components/pulse_width/common.yaml @@ -0,0 +1,4 @@ +sensor: + - platform: pulse_width + name: Pulse Width + pin: 4 diff --git a/tests/components/pulse_width/test.esp32-c3-idf.yaml b/tests/components/pulse_width/test.esp32-c3-idf.yaml index fbda7cda28..dade44d145 100644 --- a/tests/components/pulse_width/test.esp32-c3-idf.yaml +++ b/tests/components/pulse_width/test.esp32-c3-idf.yaml @@ -1,4 +1 @@ -sensor: - - platform: pulse_width - name: Pulse Width - pin: 4 +<<: !include common.yaml diff --git a/tests/components/pulse_width/test.esp32-c3.yaml b/tests/components/pulse_width/test.esp32-c3.yaml index fbda7cda28..dade44d145 100644 --- a/tests/components/pulse_width/test.esp32-c3.yaml +++ b/tests/components/pulse_width/test.esp32-c3.yaml @@ -1,4 +1 @@ -sensor: - - platform: pulse_width - name: Pulse Width - pin: 4 +<<: !include common.yaml diff --git a/tests/components/pulse_width/test.esp32-idf.yaml b/tests/components/pulse_width/test.esp32-idf.yaml index fbda7cda28..dade44d145 100644 --- a/tests/components/pulse_width/test.esp32-idf.yaml +++ b/tests/components/pulse_width/test.esp32-idf.yaml @@ -1,4 +1 @@ -sensor: - - platform: pulse_width - name: Pulse Width - pin: 4 +<<: !include common.yaml diff --git a/tests/components/pulse_width/test.esp32.yaml b/tests/components/pulse_width/test.esp32.yaml index fbda7cda28..dade44d145 100644 --- a/tests/components/pulse_width/test.esp32.yaml +++ b/tests/components/pulse_width/test.esp32.yaml @@ -1,4 +1 @@ -sensor: - - platform: pulse_width - name: Pulse Width - pin: 4 +<<: !include common.yaml diff --git a/tests/components/pulse_width/test.esp8266.yaml b/tests/components/pulse_width/test.esp8266.yaml index fbda7cda28..dade44d145 100644 --- a/tests/components/pulse_width/test.esp8266.yaml +++ b/tests/components/pulse_width/test.esp8266.yaml @@ -1,4 +1 @@ -sensor: - - platform: pulse_width - name: Pulse Width - pin: 4 +<<: !include common.yaml diff --git a/tests/components/pulse_width/test.rp2040.yaml b/tests/components/pulse_width/test.rp2040.yaml index fbda7cda28..dade44d145 100644 --- a/tests/components/pulse_width/test.rp2040.yaml +++ b/tests/components/pulse_width/test.rp2040.yaml @@ -1,4 +1 @@ -sensor: - - platform: pulse_width - name: Pulse Width - pin: 4 +<<: !include common.yaml diff --git a/tests/components/pvvx_mithermometer/common.yaml b/tests/components/pvvx_mithermometer/common.yaml new file mode 100644 index 0000000000..972f23122c --- /dev/null +++ b/tests/components/pvvx_mithermometer/common.yaml @@ -0,0 +1,44 @@ +wifi: + ssid: MySSID + password: password1 + +esp32_ble_tracker: + +ble_client: + - mac_address: 01:02:03:04:05:06 + id: pvvx_ble_display + +display: + - platform: pvvx_mithermometer + ble_client_id: pvvx_ble_display + time_id: sntp_time + disconnect_delay: 3s + update_interval: 10min + validity_period: 20min + lambda: |- + it.print_bignum(188.8); + it.print_unit(pvvx_mithermometer::UNIT_DEG_E); + it.print_smallnum(88); + it.print_percent(true); + it.print_happy(true); + it.print_sad(true); + it.print_bracket(true); + it.print_battery(true); + +sensor: + - platform: pvvx_mithermometer + mac_address: A4:C1:38:4E:16:78 + temperature: + name: PVVX Temperature + humidity: + name: PVVX Humidity + battery_level: + name: PVVX Battery-Level + battery_voltage: + name: PVVX Battery-Voltage + +time: + - platform: sntp + id: sntp_time + servers: + - 0.pool.ntp.org diff --git a/tests/components/pvvx_mithermometer/test.esp32-c3-idf.yaml b/tests/components/pvvx_mithermometer/test.esp32-c3-idf.yaml index 972f23122c..dade44d145 100644 --- a/tests/components/pvvx_mithermometer/test.esp32-c3-idf.yaml +++ b/tests/components/pvvx_mithermometer/test.esp32-c3-idf.yaml @@ -1,44 +1 @@ -wifi: - ssid: MySSID - password: password1 - -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: pvvx_ble_display - -display: - - platform: pvvx_mithermometer - ble_client_id: pvvx_ble_display - time_id: sntp_time - disconnect_delay: 3s - update_interval: 10min - validity_period: 20min - lambda: |- - it.print_bignum(188.8); - it.print_unit(pvvx_mithermometer::UNIT_DEG_E); - it.print_smallnum(88); - it.print_percent(true); - it.print_happy(true); - it.print_sad(true); - it.print_bracket(true); - it.print_battery(true); - -sensor: - - platform: pvvx_mithermometer - mac_address: A4:C1:38:4E:16:78 - temperature: - name: PVVX Temperature - humidity: - name: PVVX Humidity - battery_level: - name: PVVX Battery-Level - battery_voltage: - name: PVVX Battery-Voltage - -time: - - platform: sntp - id: sntp_time - servers: - - 0.pool.ntp.org +<<: !include common.yaml diff --git a/tests/components/pvvx_mithermometer/test.esp32-c3.yaml b/tests/components/pvvx_mithermometer/test.esp32-c3.yaml index 972f23122c..dade44d145 100644 --- a/tests/components/pvvx_mithermometer/test.esp32-c3.yaml +++ b/tests/components/pvvx_mithermometer/test.esp32-c3.yaml @@ -1,44 +1 @@ -wifi: - ssid: MySSID - password: password1 - -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: pvvx_ble_display - -display: - - platform: pvvx_mithermometer - ble_client_id: pvvx_ble_display - time_id: sntp_time - disconnect_delay: 3s - update_interval: 10min - validity_period: 20min - lambda: |- - it.print_bignum(188.8); - it.print_unit(pvvx_mithermometer::UNIT_DEG_E); - it.print_smallnum(88); - it.print_percent(true); - it.print_happy(true); - it.print_sad(true); - it.print_bracket(true); - it.print_battery(true); - -sensor: - - platform: pvvx_mithermometer - mac_address: A4:C1:38:4E:16:78 - temperature: - name: PVVX Temperature - humidity: - name: PVVX Humidity - battery_level: - name: PVVX Battery-Level - battery_voltage: - name: PVVX Battery-Voltage - -time: - - platform: sntp - id: sntp_time - servers: - - 0.pool.ntp.org +<<: !include common.yaml diff --git a/tests/components/pvvx_mithermometer/test.esp32-idf.yaml b/tests/components/pvvx_mithermometer/test.esp32-idf.yaml index 972f23122c..dade44d145 100644 --- a/tests/components/pvvx_mithermometer/test.esp32-idf.yaml +++ b/tests/components/pvvx_mithermometer/test.esp32-idf.yaml @@ -1,44 +1 @@ -wifi: - ssid: MySSID - password: password1 - -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: pvvx_ble_display - -display: - - platform: pvvx_mithermometer - ble_client_id: pvvx_ble_display - time_id: sntp_time - disconnect_delay: 3s - update_interval: 10min - validity_period: 20min - lambda: |- - it.print_bignum(188.8); - it.print_unit(pvvx_mithermometer::UNIT_DEG_E); - it.print_smallnum(88); - it.print_percent(true); - it.print_happy(true); - it.print_sad(true); - it.print_bracket(true); - it.print_battery(true); - -sensor: - - platform: pvvx_mithermometer - mac_address: A4:C1:38:4E:16:78 - temperature: - name: PVVX Temperature - humidity: - name: PVVX Humidity - battery_level: - name: PVVX Battery-Level - battery_voltage: - name: PVVX Battery-Voltage - -time: - - platform: sntp - id: sntp_time - servers: - - 0.pool.ntp.org +<<: !include common.yaml diff --git a/tests/components/pvvx_mithermometer/test.esp32.yaml b/tests/components/pvvx_mithermometer/test.esp32.yaml index 972f23122c..dade44d145 100644 --- a/tests/components/pvvx_mithermometer/test.esp32.yaml +++ b/tests/components/pvvx_mithermometer/test.esp32.yaml @@ -1,44 +1 @@ -wifi: - ssid: MySSID - password: password1 - -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: pvvx_ble_display - -display: - - platform: pvvx_mithermometer - ble_client_id: pvvx_ble_display - time_id: sntp_time - disconnect_delay: 3s - update_interval: 10min - validity_period: 20min - lambda: |- - it.print_bignum(188.8); - it.print_unit(pvvx_mithermometer::UNIT_DEG_E); - it.print_smallnum(88); - it.print_percent(true); - it.print_happy(true); - it.print_sad(true); - it.print_bracket(true); - it.print_battery(true); - -sensor: - - platform: pvvx_mithermometer - mac_address: A4:C1:38:4E:16:78 - temperature: - name: PVVX Temperature - humidity: - name: PVVX Humidity - battery_level: - name: PVVX Battery-Level - battery_voltage: - name: PVVX Battery-Voltage - -time: - - platform: sntp - id: sntp_time - servers: - - 0.pool.ntp.org +<<: !include common.yaml diff --git a/tests/components/qspi_amoled/common.yaml b/tests/components/qspi_amoled/common.yaml new file mode 100644 index 0000000000..01d1a63bcb --- /dev/null +++ b/tests/components/qspi_amoled/common.yaml @@ -0,0 +1,36 @@ +spi: + id: quad_spi + clk_pin: 15 + type: quad + data_pins: [14, 10, 16, 12] + +display: + - platform: qspi_amoled + model: RM690B0 + data_rate: 80MHz + spi_mode: mode0 + dimensions: + width: 450 + height: 600 + offset_width: 16 + color_order: rgb + invert_colors: false + brightness: 255 + cs_pin: 11 + reset_pin: 13 + enable_pin: 9 + + - platform: qspi_amoled + model: RM67162 + id: main_lcd + dimensions: + height: 240 + width: 536 + transform: + mirror_x: true + swap_xy: true + color_order: rgb + brightness: 255 + cs_pin: 6 + reset_pin: 17 + enable_pin: 38 diff --git a/tests/components/qspi_amoled/test.esp32-s3-idf.yaml b/tests/components/qspi_amoled/test.esp32-s3-idf.yaml index 01d1a63bcb..dade44d145 100644 --- a/tests/components/qspi_amoled/test.esp32-s3-idf.yaml +++ b/tests/components/qspi_amoled/test.esp32-s3-idf.yaml @@ -1,36 +1 @@ -spi: - id: quad_spi - clk_pin: 15 - type: quad - data_pins: [14, 10, 16, 12] - -display: - - platform: qspi_amoled - model: RM690B0 - data_rate: 80MHz - spi_mode: mode0 - dimensions: - width: 450 - height: 600 - offset_width: 16 - color_order: rgb - invert_colors: false - brightness: 255 - cs_pin: 11 - reset_pin: 13 - enable_pin: 9 - - - platform: qspi_amoled - model: RM67162 - id: main_lcd - dimensions: - height: 240 - width: 536 - transform: - mirror_x: true - swap_xy: true - color_order: rgb - brightness: 255 - cs_pin: 6 - reset_pin: 17 - enable_pin: 38 +<<: !include common.yaml diff --git a/tests/components/radon_eye_ble/common.yaml b/tests/components/radon_eye_ble/common.yaml new file mode 100644 index 0000000000..85638d5c0e --- /dev/null +++ b/tests/components/radon_eye_ble/common.yaml @@ -0,0 +1,3 @@ +esp32_ble_tracker: + +radon_eye_ble: diff --git a/tests/components/radon_eye_ble/test.esp32-c3-idf.yaml b/tests/components/radon_eye_ble/test.esp32-c3-idf.yaml index 85638d5c0e..dade44d145 100644 --- a/tests/components/radon_eye_ble/test.esp32-c3-idf.yaml +++ b/tests/components/radon_eye_ble/test.esp32-c3-idf.yaml @@ -1,3 +1 @@ -esp32_ble_tracker: - -radon_eye_ble: +<<: !include common.yaml diff --git a/tests/components/radon_eye_ble/test.esp32-c3.yaml b/tests/components/radon_eye_ble/test.esp32-c3.yaml index 85638d5c0e..dade44d145 100644 --- a/tests/components/radon_eye_ble/test.esp32-c3.yaml +++ b/tests/components/radon_eye_ble/test.esp32-c3.yaml @@ -1,3 +1 @@ -esp32_ble_tracker: - -radon_eye_ble: +<<: !include common.yaml diff --git a/tests/components/radon_eye_ble/test.esp32-idf.yaml b/tests/components/radon_eye_ble/test.esp32-idf.yaml index 85638d5c0e..dade44d145 100644 --- a/tests/components/radon_eye_ble/test.esp32-idf.yaml +++ b/tests/components/radon_eye_ble/test.esp32-idf.yaml @@ -1,3 +1 @@ -esp32_ble_tracker: - -radon_eye_ble: +<<: !include common.yaml diff --git a/tests/components/radon_eye_ble/test.esp32.yaml b/tests/components/radon_eye_ble/test.esp32.yaml index 85638d5c0e..dade44d145 100644 --- a/tests/components/radon_eye_ble/test.esp32.yaml +++ b/tests/components/radon_eye_ble/test.esp32.yaml @@ -1,3 +1 @@ -esp32_ble_tracker: - -radon_eye_ble: +<<: !include common.yaml diff --git a/tests/components/radon_eye_rd200/common.yaml b/tests/components/radon_eye_rd200/common.yaml new file mode 100644 index 0000000000..d06979be6f --- /dev/null +++ b/tests/components/radon_eye_rd200/common.yaml @@ -0,0 +1,14 @@ +esp32_ble_tracker: + +ble_client: + - mac_address: 01:02:03:04:05:06 + id: radon_eye_blec + +sensor: + - platform: radon_eye_rd200 + ble_client_id: radon_eye_blec + radon: + name: RD200 Radon + radon_long_term: + name: RD200 Radon Long Term + update_interval: 10min diff --git a/tests/components/radon_eye_rd200/test.esp32-c3-idf.yaml b/tests/components/radon_eye_rd200/test.esp32-c3-idf.yaml index d06979be6f..dade44d145 100644 --- a/tests/components/radon_eye_rd200/test.esp32-c3-idf.yaml +++ b/tests/components/radon_eye_rd200/test.esp32-c3-idf.yaml @@ -1,14 +1 @@ -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: radon_eye_blec - -sensor: - - platform: radon_eye_rd200 - ble_client_id: radon_eye_blec - radon: - name: RD200 Radon - radon_long_term: - name: RD200 Radon Long Term - update_interval: 10min +<<: !include common.yaml diff --git a/tests/components/radon_eye_rd200/test.esp32-c3.yaml b/tests/components/radon_eye_rd200/test.esp32-c3.yaml index d06979be6f..dade44d145 100644 --- a/tests/components/radon_eye_rd200/test.esp32-c3.yaml +++ b/tests/components/radon_eye_rd200/test.esp32-c3.yaml @@ -1,14 +1 @@ -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: radon_eye_blec - -sensor: - - platform: radon_eye_rd200 - ble_client_id: radon_eye_blec - radon: - name: RD200 Radon - radon_long_term: - name: RD200 Radon Long Term - update_interval: 10min +<<: !include common.yaml diff --git a/tests/components/radon_eye_rd200/test.esp32-idf.yaml b/tests/components/radon_eye_rd200/test.esp32-idf.yaml index d06979be6f..dade44d145 100644 --- a/tests/components/radon_eye_rd200/test.esp32-idf.yaml +++ b/tests/components/radon_eye_rd200/test.esp32-idf.yaml @@ -1,14 +1 @@ -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: radon_eye_blec - -sensor: - - platform: radon_eye_rd200 - ble_client_id: radon_eye_blec - radon: - name: RD200 Radon - radon_long_term: - name: RD200 Radon Long Term - update_interval: 10min +<<: !include common.yaml diff --git a/tests/components/radon_eye_rd200/test.esp32.yaml b/tests/components/radon_eye_rd200/test.esp32.yaml index d06979be6f..dade44d145 100644 --- a/tests/components/radon_eye_rd200/test.esp32.yaml +++ b/tests/components/radon_eye_rd200/test.esp32.yaml @@ -1,14 +1 @@ -esp32_ble_tracker: - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: radon_eye_blec - -sensor: - - platform: radon_eye_rd200 - ble_client_id: radon_eye_blec - radon: - name: RD200 Radon - radon_long_term: - name: RD200 Radon Long Term - update_interval: 10min +<<: !include common.yaml diff --git a/tests/components/restart/common.yaml b/tests/components/restart/common.yaml new file mode 100644 index 0000000000..f0d25809ac --- /dev/null +++ b/tests/components/restart/common.yaml @@ -0,0 +1,7 @@ +button: + - platform: restart + name: Restart Button + +switch: + - platform: restart + name: Restart Switch diff --git a/tests/components/restart/test.esp32-c3-idf.yaml b/tests/components/restart/test.esp32-c3-idf.yaml index f0d25809ac..dade44d145 100644 --- a/tests/components/restart/test.esp32-c3-idf.yaml +++ b/tests/components/restart/test.esp32-c3-idf.yaml @@ -1,7 +1 @@ -button: - - platform: restart - name: Restart Button - -switch: - - platform: restart - name: Restart Switch +<<: !include common.yaml diff --git a/tests/components/restart/test.esp32-c3.yaml b/tests/components/restart/test.esp32-c3.yaml index f0d25809ac..dade44d145 100644 --- a/tests/components/restart/test.esp32-c3.yaml +++ b/tests/components/restart/test.esp32-c3.yaml @@ -1,7 +1 @@ -button: - - platform: restart - name: Restart Button - -switch: - - platform: restart - name: Restart Switch +<<: !include common.yaml diff --git a/tests/components/restart/test.esp32-idf.yaml b/tests/components/restart/test.esp32-idf.yaml index f0d25809ac..dade44d145 100644 --- a/tests/components/restart/test.esp32-idf.yaml +++ b/tests/components/restart/test.esp32-idf.yaml @@ -1,7 +1 @@ -button: - - platform: restart - name: Restart Button - -switch: - - platform: restart - name: Restart Switch +<<: !include common.yaml diff --git a/tests/components/restart/test.esp32.yaml b/tests/components/restart/test.esp32.yaml index f0d25809ac..dade44d145 100644 --- a/tests/components/restart/test.esp32.yaml +++ b/tests/components/restart/test.esp32.yaml @@ -1,7 +1 @@ -button: - - platform: restart - name: Restart Button - -switch: - - platform: restart - name: Restart Switch +<<: !include common.yaml diff --git a/tests/components/restart/test.esp8266.yaml b/tests/components/restart/test.esp8266.yaml index f0d25809ac..dade44d145 100644 --- a/tests/components/restart/test.esp8266.yaml +++ b/tests/components/restart/test.esp8266.yaml @@ -1,7 +1 @@ -button: - - platform: restart - name: Restart Button - -switch: - - platform: restart - name: Restart Switch +<<: !include common.yaml diff --git a/tests/components/restart/test.rp2040.yaml b/tests/components/restart/test.rp2040.yaml index f0d25809ac..dade44d145 100644 --- a/tests/components/restart/test.rp2040.yaml +++ b/tests/components/restart/test.rp2040.yaml @@ -1,7 +1 @@ -button: - - platform: restart - name: Restart Button - -switch: - - platform: restart - name: Restart Switch +<<: !include common.yaml diff --git a/tests/components/rp2040_pio_led_strip/common.yaml b/tests/components/rp2040_pio_led_strip/common.yaml new file mode 100644 index 0000000000..b9b1436cdb --- /dev/null +++ b/tests/components/rp2040_pio_led_strip/common.yaml @@ -0,0 +1,18 @@ +light: + - platform: rp2040_pio_led_strip + id: led_strip + pin: 4 + num_leds: 60 + pio: 0 + rgb_order: GRB + chipset: WS2812 + - platform: rp2040_pio_led_strip + id: led_strip_custom_timings + pin: 5 + num_leds: 60 + pio: 1 + rgb_order: GRB + bit0_high: .1us + bit0_low: 1.2us + bit1_high: .69us + bit1_low: .4us diff --git a/tests/components/rp2040_pio_led_strip/test.rp2040.yaml b/tests/components/rp2040_pio_led_strip/test.rp2040.yaml index b9b1436cdb..dade44d145 100644 --- a/tests/components/rp2040_pio_led_strip/test.rp2040.yaml +++ b/tests/components/rp2040_pio_led_strip/test.rp2040.yaml @@ -1,18 +1 @@ -light: - - platform: rp2040_pio_led_strip - id: led_strip - pin: 4 - num_leds: 60 - pio: 0 - rgb_order: GRB - chipset: WS2812 - - platform: rp2040_pio_led_strip - id: led_strip_custom_timings - pin: 5 - num_leds: 60 - pio: 1 - rgb_order: GRB - bit0_high: .1us - bit0_low: 1.2us - bit1_high: .69us - bit1_low: .4us +<<: !include common.yaml diff --git a/tests/components/rp2040_pwm/common.yaml b/tests/components/rp2040_pwm/common.yaml new file mode 100644 index 0000000000..45c039106f --- /dev/null +++ b/tests/components/rp2040_pwm/common.yaml @@ -0,0 +1,7 @@ +output: + - platform: rp2040_pwm + id: light_output_1 + pin: 2 + - platform: rp2040_pwm + id: light_output_2 + pin: 3 diff --git a/tests/components/rp2040_pwm/test.rp2040.yaml b/tests/components/rp2040_pwm/test.rp2040.yaml index 45c039106f..dade44d145 100644 --- a/tests/components/rp2040_pwm/test.rp2040.yaml +++ b/tests/components/rp2040_pwm/test.rp2040.yaml @@ -1,7 +1 @@ -output: - - platform: rp2040_pwm - id: light_output_1 - pin: 2 - - platform: rp2040_pwm - id: light_output_2 - pin: 3 +<<: !include common.yaml diff --git a/tests/components/rpi_dpi_rgb/common.yaml b/tests/components/rpi_dpi_rgb/common.yaml new file mode 100644 index 0000000000..9ce2d9b9fd --- /dev/null +++ b/tests/components/rpi_dpi_rgb/common.yaml @@ -0,0 +1,40 @@ +psram: + mode: octal + speed: 80MHz +display: + - platform: rpi_dpi_rgb + update_interval: never + auto_clear_enabled: false + id: rpi_display + color_order: RGB + rotation: 90 + dimensions: + width: 800 + height: 480 + de_pin: + number: 40 + hsync_pin: 39 + vsync_pin: 41 + pclk_pin: 42 + data_pins: + red: + - number: 45 # r1 + ignore_strapping_warning: true + - 48 # r2 + - 47 # r3 + - 21 # r4 + - number: 14 # r5 + ignore_strapping_warning: false + green: + - 5 # g0 + - 6 # g1 + - 7 # g2 + - 15 # g3 + - 16 # g4 + - 4 # g5 + blue: + - 8 # b1 + - 3 # b2 + - 46 # b3 + - 9 # b4 + - 1 # b5 diff --git a/tests/components/rpi_dpi_rgb/test.esp32-s3-idf.yaml b/tests/components/rpi_dpi_rgb/test.esp32-s3-idf.yaml index 9ce2d9b9fd..dade44d145 100644 --- a/tests/components/rpi_dpi_rgb/test.esp32-s3-idf.yaml +++ b/tests/components/rpi_dpi_rgb/test.esp32-s3-idf.yaml @@ -1,40 +1 @@ -psram: - mode: octal - speed: 80MHz -display: - - platform: rpi_dpi_rgb - update_interval: never - auto_clear_enabled: false - id: rpi_display - color_order: RGB - rotation: 90 - dimensions: - width: 800 - height: 480 - de_pin: - number: 40 - hsync_pin: 39 - vsync_pin: 41 - pclk_pin: 42 - data_pins: - red: - - number: 45 # r1 - ignore_strapping_warning: true - - 48 # r2 - - 47 # r3 - - 21 # r4 - - number: 14 # r5 - ignore_strapping_warning: false - green: - - 5 # g0 - - 6 # g1 - - 7 # g2 - - 15 # g3 - - 16 # g4 - - 4 # g5 - blue: - - 8 # b1 - - 3 # b2 - - 46 # b3 - - 9 # b4 - - 1 # b5 +<<: !include common.yaml diff --git a/tests/components/ruuvi_ble/common.yaml b/tests/components/ruuvi_ble/common.yaml new file mode 100644 index 0000000000..1f155fd8e1 --- /dev/null +++ b/tests/components/ruuvi_ble/common.yaml @@ -0,0 +1,3 @@ +esp32_ble_tracker: + +ruuvi_ble: diff --git a/tests/components/ruuvi_ble/test.esp32-c3-idf.yaml b/tests/components/ruuvi_ble/test.esp32-c3-idf.yaml index 1f155fd8e1..dade44d145 100644 --- a/tests/components/ruuvi_ble/test.esp32-c3-idf.yaml +++ b/tests/components/ruuvi_ble/test.esp32-c3-idf.yaml @@ -1,3 +1 @@ -esp32_ble_tracker: - -ruuvi_ble: +<<: !include common.yaml diff --git a/tests/components/ruuvi_ble/test.esp32-c3.yaml b/tests/components/ruuvi_ble/test.esp32-c3.yaml index 1f155fd8e1..dade44d145 100644 --- a/tests/components/ruuvi_ble/test.esp32-c3.yaml +++ b/tests/components/ruuvi_ble/test.esp32-c3.yaml @@ -1,3 +1 @@ -esp32_ble_tracker: - -ruuvi_ble: +<<: !include common.yaml diff --git a/tests/components/ruuvi_ble/test.esp32-idf.yaml b/tests/components/ruuvi_ble/test.esp32-idf.yaml index 1f155fd8e1..dade44d145 100644 --- a/tests/components/ruuvi_ble/test.esp32-idf.yaml +++ b/tests/components/ruuvi_ble/test.esp32-idf.yaml @@ -1,3 +1 @@ -esp32_ble_tracker: - -ruuvi_ble: +<<: !include common.yaml diff --git a/tests/components/ruuvi_ble/test.esp32.yaml b/tests/components/ruuvi_ble/test.esp32.yaml index 1f155fd8e1..dade44d145 100644 --- a/tests/components/ruuvi_ble/test.esp32.yaml +++ b/tests/components/ruuvi_ble/test.esp32.yaml @@ -1,3 +1 @@ -esp32_ble_tracker: - -ruuvi_ble: +<<: !include common.yaml diff --git a/tests/components/ruuvitag/common.yaml b/tests/components/ruuvitag/common.yaml new file mode 100644 index 0000000000..7990617710 --- /dev/null +++ b/tests/components/ruuvitag/common.yaml @@ -0,0 +1,27 @@ +esp32_ble_tracker: + +sensor: + - platform: ruuvitag + mac_address: FF:56:D3:2F:7D:E8 + humidity: + name: RuuviTag Humidity + temperature: + name: RuuviTag Temperature + pressure: + name: RuuviTag Pressure + acceleration: + name: RuuviTag Acceleration + acceleration_x: + name: RuuviTag Acceleration X + acceleration_y: + name: RuuviTag Acceleration Y + acceleration_z: + name: RuuviTag Acceleration Z + battery_voltage: + name: RuuviTag Battery Voltage + tx_power: + name: RuuviTag TX Power + movement_counter: + name: RuuviTag Movement Counter + measurement_sequence_number: + name: RuuviTag Measurement Sequence Number diff --git a/tests/components/ruuvitag/test.esp32-c3-idf.yaml b/tests/components/ruuvitag/test.esp32-c3-idf.yaml index 7990617710..dade44d145 100644 --- a/tests/components/ruuvitag/test.esp32-c3-idf.yaml +++ b/tests/components/ruuvitag/test.esp32-c3-idf.yaml @@ -1,27 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: ruuvitag - mac_address: FF:56:D3:2F:7D:E8 - humidity: - name: RuuviTag Humidity - temperature: - name: RuuviTag Temperature - pressure: - name: RuuviTag Pressure - acceleration: - name: RuuviTag Acceleration - acceleration_x: - name: RuuviTag Acceleration X - acceleration_y: - name: RuuviTag Acceleration Y - acceleration_z: - name: RuuviTag Acceleration Z - battery_voltage: - name: RuuviTag Battery Voltage - tx_power: - name: RuuviTag TX Power - movement_counter: - name: RuuviTag Movement Counter - measurement_sequence_number: - name: RuuviTag Measurement Sequence Number +<<: !include common.yaml diff --git a/tests/components/ruuvitag/test.esp32-c3.yaml b/tests/components/ruuvitag/test.esp32-c3.yaml index 7990617710..dade44d145 100644 --- a/tests/components/ruuvitag/test.esp32-c3.yaml +++ b/tests/components/ruuvitag/test.esp32-c3.yaml @@ -1,27 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: ruuvitag - mac_address: FF:56:D3:2F:7D:E8 - humidity: - name: RuuviTag Humidity - temperature: - name: RuuviTag Temperature - pressure: - name: RuuviTag Pressure - acceleration: - name: RuuviTag Acceleration - acceleration_x: - name: RuuviTag Acceleration X - acceleration_y: - name: RuuviTag Acceleration Y - acceleration_z: - name: RuuviTag Acceleration Z - battery_voltage: - name: RuuviTag Battery Voltage - tx_power: - name: RuuviTag TX Power - movement_counter: - name: RuuviTag Movement Counter - measurement_sequence_number: - name: RuuviTag Measurement Sequence Number +<<: !include common.yaml diff --git a/tests/components/ruuvitag/test.esp32-idf.yaml b/tests/components/ruuvitag/test.esp32-idf.yaml index 7990617710..dade44d145 100644 --- a/tests/components/ruuvitag/test.esp32-idf.yaml +++ b/tests/components/ruuvitag/test.esp32-idf.yaml @@ -1,27 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: ruuvitag - mac_address: FF:56:D3:2F:7D:E8 - humidity: - name: RuuviTag Humidity - temperature: - name: RuuviTag Temperature - pressure: - name: RuuviTag Pressure - acceleration: - name: RuuviTag Acceleration - acceleration_x: - name: RuuviTag Acceleration X - acceleration_y: - name: RuuviTag Acceleration Y - acceleration_z: - name: RuuviTag Acceleration Z - battery_voltage: - name: RuuviTag Battery Voltage - tx_power: - name: RuuviTag TX Power - movement_counter: - name: RuuviTag Movement Counter - measurement_sequence_number: - name: RuuviTag Measurement Sequence Number +<<: !include common.yaml diff --git a/tests/components/ruuvitag/test.esp32.yaml b/tests/components/ruuvitag/test.esp32.yaml index 7990617710..dade44d145 100644 --- a/tests/components/ruuvitag/test.esp32.yaml +++ b/tests/components/ruuvitag/test.esp32.yaml @@ -1,27 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: ruuvitag - mac_address: FF:56:D3:2F:7D:E8 - humidity: - name: RuuviTag Humidity - temperature: - name: RuuviTag Temperature - pressure: - name: RuuviTag Pressure - acceleration: - name: RuuviTag Acceleration - acceleration_x: - name: RuuviTag Acceleration X - acceleration_y: - name: RuuviTag Acceleration Y - acceleration_z: - name: RuuviTag Acceleration Z - battery_voltage: - name: RuuviTag Battery Voltage - tx_power: - name: RuuviTag TX Power - movement_counter: - name: RuuviTag Movement Counter - measurement_sequence_number: - name: RuuviTag Measurement Sequence Number +<<: !include common.yaml diff --git a/tests/components/safe_mode/common.yaml b/tests/components/safe_mode/common.yaml new file mode 100644 index 0000000000..df0abd9aec --- /dev/null +++ b/tests/components/safe_mode/common.yaml @@ -0,0 +1,13 @@ +wifi: + ssid: MySSID + password: password1 + +ota: + +button: + - platform: safe_mode + name: Safe Mode Button + +switch: + - platform: safe_mode + name: Safe Mode Switch diff --git a/tests/components/safe_mode/test.esp32-c3-idf.yaml b/tests/components/safe_mode/test.esp32-c3-idf.yaml index df0abd9aec..dade44d145 100644 --- a/tests/components/safe_mode/test.esp32-c3-idf.yaml +++ b/tests/components/safe_mode/test.esp32-c3-idf.yaml @@ -1,13 +1 @@ -wifi: - ssid: MySSID - password: password1 - -ota: - -button: - - platform: safe_mode - name: Safe Mode Button - -switch: - - platform: safe_mode - name: Safe Mode Switch +<<: !include common.yaml diff --git a/tests/components/safe_mode/test.esp32-c3.yaml b/tests/components/safe_mode/test.esp32-c3.yaml index df0abd9aec..dade44d145 100644 --- a/tests/components/safe_mode/test.esp32-c3.yaml +++ b/tests/components/safe_mode/test.esp32-c3.yaml @@ -1,13 +1 @@ -wifi: - ssid: MySSID - password: password1 - -ota: - -button: - - platform: safe_mode - name: Safe Mode Button - -switch: - - platform: safe_mode - name: Safe Mode Switch +<<: !include common.yaml diff --git a/tests/components/safe_mode/test.esp32-idf.yaml b/tests/components/safe_mode/test.esp32-idf.yaml index df0abd9aec..dade44d145 100644 --- a/tests/components/safe_mode/test.esp32-idf.yaml +++ b/tests/components/safe_mode/test.esp32-idf.yaml @@ -1,13 +1 @@ -wifi: - ssid: MySSID - password: password1 - -ota: - -button: - - platform: safe_mode - name: Safe Mode Button - -switch: - - platform: safe_mode - name: Safe Mode Switch +<<: !include common.yaml diff --git a/tests/components/safe_mode/test.esp32.yaml b/tests/components/safe_mode/test.esp32.yaml index df0abd9aec..dade44d145 100644 --- a/tests/components/safe_mode/test.esp32.yaml +++ b/tests/components/safe_mode/test.esp32.yaml @@ -1,13 +1 @@ -wifi: - ssid: MySSID - password: password1 - -ota: - -button: - - platform: safe_mode - name: Safe Mode Button - -switch: - - platform: safe_mode - name: Safe Mode Switch +<<: !include common.yaml diff --git a/tests/components/safe_mode/test.esp8266.yaml b/tests/components/safe_mode/test.esp8266.yaml index df0abd9aec..dade44d145 100644 --- a/tests/components/safe_mode/test.esp8266.yaml +++ b/tests/components/safe_mode/test.esp8266.yaml @@ -1,13 +1 @@ -wifi: - ssid: MySSID - password: password1 - -ota: - -button: - - platform: safe_mode - name: Safe Mode Button - -switch: - - platform: safe_mode - name: Safe Mode Switch +<<: !include common.yaml diff --git a/tests/components/safe_mode/test.rp2040.yaml b/tests/components/safe_mode/test.rp2040.yaml index df0abd9aec..dade44d145 100644 --- a/tests/components/safe_mode/test.rp2040.yaml +++ b/tests/components/safe_mode/test.rp2040.yaml @@ -1,13 +1 @@ -wifi: - ssid: MySSID - password: password1 - -ota: - -button: - - platform: safe_mode - name: Safe Mode Button - -switch: - - platform: safe_mode - name: Safe Mode Switch +<<: !include common.yaml diff --git a/tests/components/shelly_dimmer/common.yaml b/tests/components/shelly_dimmer/common.yaml new file mode 100644 index 0000000000..3acd0260d5 --- /dev/null +++ b/tests/components/shelly_dimmer/common.yaml @@ -0,0 +1,19 @@ +uart: + - id: uart_shelly_dimmer + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + +light: + - platform: shelly_dimmer + name: Shelly Dimmer Light + power: + name: Shelly Dimmer Power + voltage: + name: Shelly Dimmer Voltage + current: + name: Shelly Dimmer Current + max_brightness: 500 + firmware: "51.6" + nrst_pin: 13 + boot0_pin: 14 diff --git a/tests/components/shelly_dimmer/test.esp8266.yaml b/tests/components/shelly_dimmer/test.esp8266.yaml index 3acd0260d5..dade44d145 100644 --- a/tests/components/shelly_dimmer/test.esp8266.yaml +++ b/tests/components/shelly_dimmer/test.esp8266.yaml @@ -1,19 +1 @@ -uart: - - id: uart_shelly_dimmer - tx_pin: 4 - rx_pin: 5 - baud_rate: 9600 - -light: - - platform: shelly_dimmer - name: Shelly Dimmer Light - power: - name: Shelly Dimmer Power - voltage: - name: Shelly Dimmer Voltage - current: - name: Shelly Dimmer Current - max_brightness: 500 - firmware: "51.6" - nrst_pin: 13 - boot0_pin: 14 +<<: !include common.yaml diff --git a/tests/components/shutdown/common.yaml b/tests/components/shutdown/common.yaml new file mode 100644 index 0000000000..f47e7da85d --- /dev/null +++ b/tests/components/shutdown/common.yaml @@ -0,0 +1,7 @@ +button: + - platform: shutdown + name: Shutdown Button + +switch: + - platform: shutdown + name: Shutdown Switch diff --git a/tests/components/shutdown/test.esp32-c3-idf.yaml b/tests/components/shutdown/test.esp32-c3-idf.yaml index f47e7da85d..dade44d145 100644 --- a/tests/components/shutdown/test.esp32-c3-idf.yaml +++ b/tests/components/shutdown/test.esp32-c3-idf.yaml @@ -1,7 +1 @@ -button: - - platform: shutdown - name: Shutdown Button - -switch: - - platform: shutdown - name: Shutdown Switch +<<: !include common.yaml diff --git a/tests/components/shutdown/test.esp32-c3.yaml b/tests/components/shutdown/test.esp32-c3.yaml index f47e7da85d..dade44d145 100644 --- a/tests/components/shutdown/test.esp32-c3.yaml +++ b/tests/components/shutdown/test.esp32-c3.yaml @@ -1,7 +1 @@ -button: - - platform: shutdown - name: Shutdown Button - -switch: - - platform: shutdown - name: Shutdown Switch +<<: !include common.yaml diff --git a/tests/components/shutdown/test.esp32-idf.yaml b/tests/components/shutdown/test.esp32-idf.yaml index f47e7da85d..dade44d145 100644 --- a/tests/components/shutdown/test.esp32-idf.yaml +++ b/tests/components/shutdown/test.esp32-idf.yaml @@ -1,7 +1 @@ -button: - - platform: shutdown - name: Shutdown Button - -switch: - - platform: shutdown - name: Shutdown Switch +<<: !include common.yaml diff --git a/tests/components/shutdown/test.esp32.yaml b/tests/components/shutdown/test.esp32.yaml index f47e7da85d..dade44d145 100644 --- a/tests/components/shutdown/test.esp32.yaml +++ b/tests/components/shutdown/test.esp32.yaml @@ -1,7 +1 @@ -button: - - platform: shutdown - name: Shutdown Button - -switch: - - platform: shutdown - name: Shutdown Switch +<<: !include common.yaml diff --git a/tests/components/shutdown/test.esp8266.yaml b/tests/components/shutdown/test.esp8266.yaml index f47e7da85d..dade44d145 100644 --- a/tests/components/shutdown/test.esp8266.yaml +++ b/tests/components/shutdown/test.esp8266.yaml @@ -1,7 +1 @@ -button: - - platform: shutdown - name: Shutdown Button - -switch: - - platform: shutdown - name: Shutdown Switch +<<: !include common.yaml diff --git a/tests/components/shutdown/test.rp2040.yaml b/tests/components/shutdown/test.rp2040.yaml index f47e7da85d..dade44d145 100644 --- a/tests/components/shutdown/test.rp2040.yaml +++ b/tests/components/shutdown/test.rp2040.yaml @@ -1,7 +1 @@ -button: - - platform: shutdown - name: Shutdown Button - -switch: - - platform: shutdown - name: Shutdown Switch +<<: !include common.yaml diff --git a/tests/components/sigma_delta_output/common.yaml b/tests/components/sigma_delta_output/common.yaml new file mode 100644 index 0000000000..2a9a5d2c3b --- /dev/null +++ b/tests/components/sigma_delta_output/common.yaml @@ -0,0 +1,16 @@ +output: + - platform: sigma_delta_output + id: sddac + pin: 4 + turn_on_action: + then: + - logger.log: "Turned on" + turn_off_action: + then: + - logger.log: "Turned off" + state_change_action: + then: + - logger.log: + format: "Changed state: %d" + args: ["state"] + update_interval: 60s diff --git a/tests/components/sigma_delta_output/test.esp32-c3-idf.yaml b/tests/components/sigma_delta_output/test.esp32-c3-idf.yaml index 2a9a5d2c3b..dade44d145 100644 --- a/tests/components/sigma_delta_output/test.esp32-c3-idf.yaml +++ b/tests/components/sigma_delta_output/test.esp32-c3-idf.yaml @@ -1,16 +1 @@ -output: - - platform: sigma_delta_output - id: sddac - pin: 4 - turn_on_action: - then: - - logger.log: "Turned on" - turn_off_action: - then: - - logger.log: "Turned off" - state_change_action: - then: - - logger.log: - format: "Changed state: %d" - args: ["state"] - update_interval: 60s +<<: !include common.yaml diff --git a/tests/components/sigma_delta_output/test.esp32-c3.yaml b/tests/components/sigma_delta_output/test.esp32-c3.yaml index 2a9a5d2c3b..dade44d145 100644 --- a/tests/components/sigma_delta_output/test.esp32-c3.yaml +++ b/tests/components/sigma_delta_output/test.esp32-c3.yaml @@ -1,16 +1 @@ -output: - - platform: sigma_delta_output - id: sddac - pin: 4 - turn_on_action: - then: - - logger.log: "Turned on" - turn_off_action: - then: - - logger.log: "Turned off" - state_change_action: - then: - - logger.log: - format: "Changed state: %d" - args: ["state"] - update_interval: 60s +<<: !include common.yaml diff --git a/tests/components/sigma_delta_output/test.esp32-idf.yaml b/tests/components/sigma_delta_output/test.esp32-idf.yaml index 2a9a5d2c3b..dade44d145 100644 --- a/tests/components/sigma_delta_output/test.esp32-idf.yaml +++ b/tests/components/sigma_delta_output/test.esp32-idf.yaml @@ -1,16 +1 @@ -output: - - platform: sigma_delta_output - id: sddac - pin: 4 - turn_on_action: - then: - - logger.log: "Turned on" - turn_off_action: - then: - - logger.log: "Turned off" - state_change_action: - then: - - logger.log: - format: "Changed state: %d" - args: ["state"] - update_interval: 60s +<<: !include common.yaml diff --git a/tests/components/sigma_delta_output/test.esp32.yaml b/tests/components/sigma_delta_output/test.esp32.yaml index 2a9a5d2c3b..dade44d145 100644 --- a/tests/components/sigma_delta_output/test.esp32.yaml +++ b/tests/components/sigma_delta_output/test.esp32.yaml @@ -1,16 +1 @@ -output: - - platform: sigma_delta_output - id: sddac - pin: 4 - turn_on_action: - then: - - logger.log: "Turned on" - turn_off_action: - then: - - logger.log: "Turned off" - state_change_action: - then: - - logger.log: - format: "Changed state: %d" - args: ["state"] - update_interval: 60s +<<: !include common.yaml diff --git a/tests/components/sigma_delta_output/test.esp8266.yaml b/tests/components/sigma_delta_output/test.esp8266.yaml index 2a9a5d2c3b..dade44d145 100644 --- a/tests/components/sigma_delta_output/test.esp8266.yaml +++ b/tests/components/sigma_delta_output/test.esp8266.yaml @@ -1,16 +1 @@ -output: - - platform: sigma_delta_output - id: sddac - pin: 4 - turn_on_action: - then: - - logger.log: "Turned on" - turn_off_action: - then: - - logger.log: "Turned off" - state_change_action: - then: - - logger.log: - format: "Changed state: %d" - args: ["state"] - update_interval: 60s +<<: !include common.yaml diff --git a/tests/components/sigma_delta_output/test.rp2040.yaml b/tests/components/sigma_delta_output/test.rp2040.yaml index 2a9a5d2c3b..dade44d145 100644 --- a/tests/components/sigma_delta_output/test.rp2040.yaml +++ b/tests/components/sigma_delta_output/test.rp2040.yaml @@ -1,16 +1 @@ -output: - - platform: sigma_delta_output - id: sddac - pin: 4 - turn_on_action: - then: - - logger.log: "Turned on" - turn_off_action: - then: - - logger.log: "Turned off" - state_change_action: - then: - - logger.log: - format: "Changed state: %d" - args: ["state"] - update_interval: 60s +<<: !include common.yaml diff --git a/tests/components/slow_pwm/common.yaml b/tests/components/slow_pwm/common.yaml new file mode 100644 index 0000000000..6bfb2f8ac5 --- /dev/null +++ b/tests/components/slow_pwm/common.yaml @@ -0,0 +1,6 @@ +output: + - platform: slow_pwm + id: test_slow_pwm + pin: 4 + period: 15s + restart_cycle_on_state_change: false diff --git a/tests/components/slow_pwm/test.esp32-c3-idf.yaml b/tests/components/slow_pwm/test.esp32-c3-idf.yaml index 6bfb2f8ac5..dade44d145 100644 --- a/tests/components/slow_pwm/test.esp32-c3-idf.yaml +++ b/tests/components/slow_pwm/test.esp32-c3-idf.yaml @@ -1,6 +1 @@ -output: - - platform: slow_pwm - id: test_slow_pwm - pin: 4 - period: 15s - restart_cycle_on_state_change: false +<<: !include common.yaml diff --git a/tests/components/slow_pwm/test.esp32-c3.yaml b/tests/components/slow_pwm/test.esp32-c3.yaml index 6bfb2f8ac5..dade44d145 100644 --- a/tests/components/slow_pwm/test.esp32-c3.yaml +++ b/tests/components/slow_pwm/test.esp32-c3.yaml @@ -1,6 +1 @@ -output: - - platform: slow_pwm - id: test_slow_pwm - pin: 4 - period: 15s - restart_cycle_on_state_change: false +<<: !include common.yaml diff --git a/tests/components/slow_pwm/test.esp32-idf.yaml b/tests/components/slow_pwm/test.esp32-idf.yaml index 6bfb2f8ac5..dade44d145 100644 --- a/tests/components/slow_pwm/test.esp32-idf.yaml +++ b/tests/components/slow_pwm/test.esp32-idf.yaml @@ -1,6 +1 @@ -output: - - platform: slow_pwm - id: test_slow_pwm - pin: 4 - period: 15s - restart_cycle_on_state_change: false +<<: !include common.yaml diff --git a/tests/components/slow_pwm/test.esp32.yaml b/tests/components/slow_pwm/test.esp32.yaml index 6bfb2f8ac5..dade44d145 100644 --- a/tests/components/slow_pwm/test.esp32.yaml +++ b/tests/components/slow_pwm/test.esp32.yaml @@ -1,6 +1 @@ -output: - - platform: slow_pwm - id: test_slow_pwm - pin: 4 - period: 15s - restart_cycle_on_state_change: false +<<: !include common.yaml diff --git a/tests/components/slow_pwm/test.esp8266.yaml b/tests/components/slow_pwm/test.esp8266.yaml index 6bfb2f8ac5..dade44d145 100644 --- a/tests/components/slow_pwm/test.esp8266.yaml +++ b/tests/components/slow_pwm/test.esp8266.yaml @@ -1,6 +1 @@ -output: - - platform: slow_pwm - id: test_slow_pwm - pin: 4 - period: 15s - restart_cycle_on_state_change: false +<<: !include common.yaml diff --git a/tests/components/slow_pwm/test.rp2040.yaml b/tests/components/slow_pwm/test.rp2040.yaml index 6bfb2f8ac5..dade44d145 100644 --- a/tests/components/slow_pwm/test.rp2040.yaml +++ b/tests/components/slow_pwm/test.rp2040.yaml @@ -1,6 +1 @@ -output: - - platform: slow_pwm - id: test_slow_pwm - pin: 4 - period: 15s - restart_cycle_on_state_change: false +<<: !include common.yaml diff --git a/tests/components/sm16716/common.yaml b/tests/components/sm16716/common.yaml new file mode 100644 index 0000000000..3bf2712f4e --- /dev/null +++ b/tests/components/sm16716/common.yaml @@ -0,0 +1,16 @@ +sm16716: + clock_pin: 4 + data_pin: 5 + num_channels: 3 + num_chips: 1 + +output: + - platform: sm16716 + id: sm16716_red + channel: 1 + - platform: sm16716 + id: sm16716_green + channel: 0 + - platform: sm16716 + id: sm16716_blue + channel: 2 diff --git a/tests/components/sm16716/test.esp32-c3-idf.yaml b/tests/components/sm16716/test.esp32-c3-idf.yaml index 3bf2712f4e..dade44d145 100644 --- a/tests/components/sm16716/test.esp32-c3-idf.yaml +++ b/tests/components/sm16716/test.esp32-c3-idf.yaml @@ -1,16 +1 @@ -sm16716: - clock_pin: 4 - data_pin: 5 - num_channels: 3 - num_chips: 1 - -output: - - platform: sm16716 - id: sm16716_red - channel: 1 - - platform: sm16716 - id: sm16716_green - channel: 0 - - platform: sm16716 - id: sm16716_blue - channel: 2 +<<: !include common.yaml diff --git a/tests/components/sm16716/test.esp32-c3.yaml b/tests/components/sm16716/test.esp32-c3.yaml index 3bf2712f4e..dade44d145 100644 --- a/tests/components/sm16716/test.esp32-c3.yaml +++ b/tests/components/sm16716/test.esp32-c3.yaml @@ -1,16 +1 @@ -sm16716: - clock_pin: 4 - data_pin: 5 - num_channels: 3 - num_chips: 1 - -output: - - platform: sm16716 - id: sm16716_red - channel: 1 - - platform: sm16716 - id: sm16716_green - channel: 0 - - platform: sm16716 - id: sm16716_blue - channel: 2 +<<: !include common.yaml diff --git a/tests/components/sm16716/test.esp32-idf.yaml b/tests/components/sm16716/test.esp32-idf.yaml index 3bf2712f4e..dade44d145 100644 --- a/tests/components/sm16716/test.esp32-idf.yaml +++ b/tests/components/sm16716/test.esp32-idf.yaml @@ -1,16 +1 @@ -sm16716: - clock_pin: 4 - data_pin: 5 - num_channels: 3 - num_chips: 1 - -output: - - platform: sm16716 - id: sm16716_red - channel: 1 - - platform: sm16716 - id: sm16716_green - channel: 0 - - platform: sm16716 - id: sm16716_blue - channel: 2 +<<: !include common.yaml diff --git a/tests/components/sm16716/test.esp32.yaml b/tests/components/sm16716/test.esp32.yaml index 3bf2712f4e..dade44d145 100644 --- a/tests/components/sm16716/test.esp32.yaml +++ b/tests/components/sm16716/test.esp32.yaml @@ -1,16 +1 @@ -sm16716: - clock_pin: 4 - data_pin: 5 - num_channels: 3 - num_chips: 1 - -output: - - platform: sm16716 - id: sm16716_red - channel: 1 - - platform: sm16716 - id: sm16716_green - channel: 0 - - platform: sm16716 - id: sm16716_blue - channel: 2 +<<: !include common.yaml diff --git a/tests/components/sm16716/test.esp8266.yaml b/tests/components/sm16716/test.esp8266.yaml index 3bf2712f4e..dade44d145 100644 --- a/tests/components/sm16716/test.esp8266.yaml +++ b/tests/components/sm16716/test.esp8266.yaml @@ -1,16 +1 @@ -sm16716: - clock_pin: 4 - data_pin: 5 - num_channels: 3 - num_chips: 1 - -output: - - platform: sm16716 - id: sm16716_red - channel: 1 - - platform: sm16716 - id: sm16716_green - channel: 0 - - platform: sm16716 - id: sm16716_blue - channel: 2 +<<: !include common.yaml diff --git a/tests/components/sm16716/test.rp2040.yaml b/tests/components/sm16716/test.rp2040.yaml index 3bf2712f4e..dade44d145 100644 --- a/tests/components/sm16716/test.rp2040.yaml +++ b/tests/components/sm16716/test.rp2040.yaml @@ -1,16 +1 @@ -sm16716: - clock_pin: 4 - data_pin: 5 - num_channels: 3 - num_chips: 1 - -output: - - platform: sm16716 - id: sm16716_red - channel: 1 - - platform: sm16716 - id: sm16716_green - channel: 0 - - platform: sm16716 - id: sm16716_blue - channel: 2 +<<: !include common.yaml diff --git a/tests/components/sm2135/common.yaml b/tests/components/sm2135/common.yaml new file mode 100644 index 0000000000..9a0de60839 --- /dev/null +++ b/tests/components/sm2135/common.yaml @@ -0,0 +1,22 @@ +sm2135: + clock_pin: 4 + data_pin: 5 + rgb_current: 20mA + cw_current: 60mA + +output: + - platform: sm2135 + id: sm2135_0 + channel: 0 + - platform: sm2135 + id: sm2135_1 + channel: 1 + - platform: sm2135 + id: sm2135_2 + channel: 2 + - platform: sm2135 + id: sm2135_3 + channel: 3 + - platform: sm2135 + id: sm2135_4 + channel: 4 diff --git a/tests/components/sm2135/test.esp32-c3-idf.yaml b/tests/components/sm2135/test.esp32-c3-idf.yaml index 9a0de60839..dade44d145 100644 --- a/tests/components/sm2135/test.esp32-c3-idf.yaml +++ b/tests/components/sm2135/test.esp32-c3-idf.yaml @@ -1,22 +1 @@ -sm2135: - clock_pin: 4 - data_pin: 5 - rgb_current: 20mA - cw_current: 60mA - -output: - - platform: sm2135 - id: sm2135_0 - channel: 0 - - platform: sm2135 - id: sm2135_1 - channel: 1 - - platform: sm2135 - id: sm2135_2 - channel: 2 - - platform: sm2135 - id: sm2135_3 - channel: 3 - - platform: sm2135 - id: sm2135_4 - channel: 4 +<<: !include common.yaml diff --git a/tests/components/sm2135/test.esp32-c3.yaml b/tests/components/sm2135/test.esp32-c3.yaml index 9a0de60839..dade44d145 100644 --- a/tests/components/sm2135/test.esp32-c3.yaml +++ b/tests/components/sm2135/test.esp32-c3.yaml @@ -1,22 +1 @@ -sm2135: - clock_pin: 4 - data_pin: 5 - rgb_current: 20mA - cw_current: 60mA - -output: - - platform: sm2135 - id: sm2135_0 - channel: 0 - - platform: sm2135 - id: sm2135_1 - channel: 1 - - platform: sm2135 - id: sm2135_2 - channel: 2 - - platform: sm2135 - id: sm2135_3 - channel: 3 - - platform: sm2135 - id: sm2135_4 - channel: 4 +<<: !include common.yaml diff --git a/tests/components/sm2135/test.esp32-idf.yaml b/tests/components/sm2135/test.esp32-idf.yaml index 9a0de60839..dade44d145 100644 --- a/tests/components/sm2135/test.esp32-idf.yaml +++ b/tests/components/sm2135/test.esp32-idf.yaml @@ -1,22 +1 @@ -sm2135: - clock_pin: 4 - data_pin: 5 - rgb_current: 20mA - cw_current: 60mA - -output: - - platform: sm2135 - id: sm2135_0 - channel: 0 - - platform: sm2135 - id: sm2135_1 - channel: 1 - - platform: sm2135 - id: sm2135_2 - channel: 2 - - platform: sm2135 - id: sm2135_3 - channel: 3 - - platform: sm2135 - id: sm2135_4 - channel: 4 +<<: !include common.yaml diff --git a/tests/components/sm2135/test.esp32.yaml b/tests/components/sm2135/test.esp32.yaml index 9a0de60839..dade44d145 100644 --- a/tests/components/sm2135/test.esp32.yaml +++ b/tests/components/sm2135/test.esp32.yaml @@ -1,22 +1 @@ -sm2135: - clock_pin: 4 - data_pin: 5 - rgb_current: 20mA - cw_current: 60mA - -output: - - platform: sm2135 - id: sm2135_0 - channel: 0 - - platform: sm2135 - id: sm2135_1 - channel: 1 - - platform: sm2135 - id: sm2135_2 - channel: 2 - - platform: sm2135 - id: sm2135_3 - channel: 3 - - platform: sm2135 - id: sm2135_4 - channel: 4 +<<: !include common.yaml diff --git a/tests/components/sm2135/test.esp8266.yaml b/tests/components/sm2135/test.esp8266.yaml index 9a0de60839..dade44d145 100644 --- a/tests/components/sm2135/test.esp8266.yaml +++ b/tests/components/sm2135/test.esp8266.yaml @@ -1,22 +1 @@ -sm2135: - clock_pin: 4 - data_pin: 5 - rgb_current: 20mA - cw_current: 60mA - -output: - - platform: sm2135 - id: sm2135_0 - channel: 0 - - platform: sm2135 - id: sm2135_1 - channel: 1 - - platform: sm2135 - id: sm2135_2 - channel: 2 - - platform: sm2135 - id: sm2135_3 - channel: 3 - - platform: sm2135 - id: sm2135_4 - channel: 4 +<<: !include common.yaml diff --git a/tests/components/sm2135/test.rp2040.yaml b/tests/components/sm2135/test.rp2040.yaml index 9a0de60839..dade44d145 100644 --- a/tests/components/sm2135/test.rp2040.yaml +++ b/tests/components/sm2135/test.rp2040.yaml @@ -1,22 +1 @@ -sm2135: - clock_pin: 4 - data_pin: 5 - rgb_current: 20mA - cw_current: 60mA - -output: - - platform: sm2135 - id: sm2135_0 - channel: 0 - - platform: sm2135 - id: sm2135_1 - channel: 1 - - platform: sm2135 - id: sm2135_2 - channel: 2 - - platform: sm2135 - id: sm2135_3 - channel: 3 - - platform: sm2135 - id: sm2135_4 - channel: 4 +<<: !include common.yaml diff --git a/tests/components/sm2235/common.yaml b/tests/components/sm2235/common.yaml new file mode 100644 index 0000000000..043d43d6f1 --- /dev/null +++ b/tests/components/sm2235/common.yaml @@ -0,0 +1,22 @@ +sm2235: + clock_pin: 4 + data_pin: 5 + max_power_color_channels: 9 + max_power_white_channels: 9 + +output: + - platform: sm2235 + id: sm2235_red + channel: 1 + - platform: sm2235 + id: sm2235_green + channel: 0 + - platform: sm2235 + id: sm2235_blue + channel: 2 + - platform: sm2235 + id: sm2235_coldwhite + channel: 4 + - platform: sm2235 + id: sm2235_warmwhite + channel: 3 diff --git a/tests/components/sm2235/test.esp32-c3-idf.yaml b/tests/components/sm2235/test.esp32-c3-idf.yaml index 043d43d6f1..dade44d145 100644 --- a/tests/components/sm2235/test.esp32-c3-idf.yaml +++ b/tests/components/sm2235/test.esp32-c3-idf.yaml @@ -1,22 +1 @@ -sm2235: - clock_pin: 4 - data_pin: 5 - max_power_color_channels: 9 - max_power_white_channels: 9 - -output: - - platform: sm2235 - id: sm2235_red - channel: 1 - - platform: sm2235 - id: sm2235_green - channel: 0 - - platform: sm2235 - id: sm2235_blue - channel: 2 - - platform: sm2235 - id: sm2235_coldwhite - channel: 4 - - platform: sm2235 - id: sm2235_warmwhite - channel: 3 +<<: !include common.yaml diff --git a/tests/components/sm2235/test.esp32-c3.yaml b/tests/components/sm2235/test.esp32-c3.yaml index 043d43d6f1..dade44d145 100644 --- a/tests/components/sm2235/test.esp32-c3.yaml +++ b/tests/components/sm2235/test.esp32-c3.yaml @@ -1,22 +1 @@ -sm2235: - clock_pin: 4 - data_pin: 5 - max_power_color_channels: 9 - max_power_white_channels: 9 - -output: - - platform: sm2235 - id: sm2235_red - channel: 1 - - platform: sm2235 - id: sm2235_green - channel: 0 - - platform: sm2235 - id: sm2235_blue - channel: 2 - - platform: sm2235 - id: sm2235_coldwhite - channel: 4 - - platform: sm2235 - id: sm2235_warmwhite - channel: 3 +<<: !include common.yaml diff --git a/tests/components/sm2235/test.esp32-idf.yaml b/tests/components/sm2235/test.esp32-idf.yaml index 043d43d6f1..dade44d145 100644 --- a/tests/components/sm2235/test.esp32-idf.yaml +++ b/tests/components/sm2235/test.esp32-idf.yaml @@ -1,22 +1 @@ -sm2235: - clock_pin: 4 - data_pin: 5 - max_power_color_channels: 9 - max_power_white_channels: 9 - -output: - - platform: sm2235 - id: sm2235_red - channel: 1 - - platform: sm2235 - id: sm2235_green - channel: 0 - - platform: sm2235 - id: sm2235_blue - channel: 2 - - platform: sm2235 - id: sm2235_coldwhite - channel: 4 - - platform: sm2235 - id: sm2235_warmwhite - channel: 3 +<<: !include common.yaml diff --git a/tests/components/sm2235/test.esp32.yaml b/tests/components/sm2235/test.esp32.yaml index 043d43d6f1..dade44d145 100644 --- a/tests/components/sm2235/test.esp32.yaml +++ b/tests/components/sm2235/test.esp32.yaml @@ -1,22 +1 @@ -sm2235: - clock_pin: 4 - data_pin: 5 - max_power_color_channels: 9 - max_power_white_channels: 9 - -output: - - platform: sm2235 - id: sm2235_red - channel: 1 - - platform: sm2235 - id: sm2235_green - channel: 0 - - platform: sm2235 - id: sm2235_blue - channel: 2 - - platform: sm2235 - id: sm2235_coldwhite - channel: 4 - - platform: sm2235 - id: sm2235_warmwhite - channel: 3 +<<: !include common.yaml diff --git a/tests/components/sm2235/test.esp8266.yaml b/tests/components/sm2235/test.esp8266.yaml index 043d43d6f1..dade44d145 100644 --- a/tests/components/sm2235/test.esp8266.yaml +++ b/tests/components/sm2235/test.esp8266.yaml @@ -1,22 +1 @@ -sm2235: - clock_pin: 4 - data_pin: 5 - max_power_color_channels: 9 - max_power_white_channels: 9 - -output: - - platform: sm2235 - id: sm2235_red - channel: 1 - - platform: sm2235 - id: sm2235_green - channel: 0 - - platform: sm2235 - id: sm2235_blue - channel: 2 - - platform: sm2235 - id: sm2235_coldwhite - channel: 4 - - platform: sm2235 - id: sm2235_warmwhite - channel: 3 +<<: !include common.yaml diff --git a/tests/components/sm2235/test.rp2040.yaml b/tests/components/sm2235/test.rp2040.yaml index 043d43d6f1..dade44d145 100644 --- a/tests/components/sm2235/test.rp2040.yaml +++ b/tests/components/sm2235/test.rp2040.yaml @@ -1,22 +1 @@ -sm2235: - clock_pin: 4 - data_pin: 5 - max_power_color_channels: 9 - max_power_white_channels: 9 - -output: - - platform: sm2235 - id: sm2235_red - channel: 1 - - platform: sm2235 - id: sm2235_green - channel: 0 - - platform: sm2235 - id: sm2235_blue - channel: 2 - - platform: sm2235 - id: sm2235_coldwhite - channel: 4 - - platform: sm2235 - id: sm2235_warmwhite - channel: 3 +<<: !include common.yaml diff --git a/tests/components/sm2335/common.yaml b/tests/components/sm2335/common.yaml new file mode 100644 index 0000000000..a5b2aedeb5 --- /dev/null +++ b/tests/components/sm2335/common.yaml @@ -0,0 +1,22 @@ +sm2335: + clock_pin: 4 + data_pin: 5 + max_power_color_channels: 9 + max_power_white_channels: 9 + +output: + - platform: sm2335 + id: sm2335_red + channel: 1 + - platform: sm2335 + id: sm2335_green + channel: 0 + - platform: sm2335 + id: sm2335_blue + channel: 2 + - platform: sm2335 + id: sm2335_coldwhite + channel: 4 + - platform: sm2335 + id: sm2335_warmwhite + channel: 3 diff --git a/tests/components/sm2335/test.esp32-c3-idf.yaml b/tests/components/sm2335/test.esp32-c3-idf.yaml index a5b2aedeb5..dade44d145 100644 --- a/tests/components/sm2335/test.esp32-c3-idf.yaml +++ b/tests/components/sm2335/test.esp32-c3-idf.yaml @@ -1,22 +1 @@ -sm2335: - clock_pin: 4 - data_pin: 5 - max_power_color_channels: 9 - max_power_white_channels: 9 - -output: - - platform: sm2335 - id: sm2335_red - channel: 1 - - platform: sm2335 - id: sm2335_green - channel: 0 - - platform: sm2335 - id: sm2335_blue - channel: 2 - - platform: sm2335 - id: sm2335_coldwhite - channel: 4 - - platform: sm2335 - id: sm2335_warmwhite - channel: 3 +<<: !include common.yaml diff --git a/tests/components/sm2335/test.esp32-c3.yaml b/tests/components/sm2335/test.esp32-c3.yaml index a5b2aedeb5..dade44d145 100644 --- a/tests/components/sm2335/test.esp32-c3.yaml +++ b/tests/components/sm2335/test.esp32-c3.yaml @@ -1,22 +1 @@ -sm2335: - clock_pin: 4 - data_pin: 5 - max_power_color_channels: 9 - max_power_white_channels: 9 - -output: - - platform: sm2335 - id: sm2335_red - channel: 1 - - platform: sm2335 - id: sm2335_green - channel: 0 - - platform: sm2335 - id: sm2335_blue - channel: 2 - - platform: sm2335 - id: sm2335_coldwhite - channel: 4 - - platform: sm2335 - id: sm2335_warmwhite - channel: 3 +<<: !include common.yaml diff --git a/tests/components/sm2335/test.esp32-idf.yaml b/tests/components/sm2335/test.esp32-idf.yaml index a5b2aedeb5..dade44d145 100644 --- a/tests/components/sm2335/test.esp32-idf.yaml +++ b/tests/components/sm2335/test.esp32-idf.yaml @@ -1,22 +1 @@ -sm2335: - clock_pin: 4 - data_pin: 5 - max_power_color_channels: 9 - max_power_white_channels: 9 - -output: - - platform: sm2335 - id: sm2335_red - channel: 1 - - platform: sm2335 - id: sm2335_green - channel: 0 - - platform: sm2335 - id: sm2335_blue - channel: 2 - - platform: sm2335 - id: sm2335_coldwhite - channel: 4 - - platform: sm2335 - id: sm2335_warmwhite - channel: 3 +<<: !include common.yaml diff --git a/tests/components/sm2335/test.esp32.yaml b/tests/components/sm2335/test.esp32.yaml index a5b2aedeb5..dade44d145 100644 --- a/tests/components/sm2335/test.esp32.yaml +++ b/tests/components/sm2335/test.esp32.yaml @@ -1,22 +1 @@ -sm2335: - clock_pin: 4 - data_pin: 5 - max_power_color_channels: 9 - max_power_white_channels: 9 - -output: - - platform: sm2335 - id: sm2335_red - channel: 1 - - platform: sm2335 - id: sm2335_green - channel: 0 - - platform: sm2335 - id: sm2335_blue - channel: 2 - - platform: sm2335 - id: sm2335_coldwhite - channel: 4 - - platform: sm2335 - id: sm2335_warmwhite - channel: 3 +<<: !include common.yaml diff --git a/tests/components/sm2335/test.esp8266.yaml b/tests/components/sm2335/test.esp8266.yaml index a5b2aedeb5..dade44d145 100644 --- a/tests/components/sm2335/test.esp8266.yaml +++ b/tests/components/sm2335/test.esp8266.yaml @@ -1,22 +1 @@ -sm2335: - clock_pin: 4 - data_pin: 5 - max_power_color_channels: 9 - max_power_white_channels: 9 - -output: - - platform: sm2335 - id: sm2335_red - channel: 1 - - platform: sm2335 - id: sm2335_green - channel: 0 - - platform: sm2335 - id: sm2335_blue - channel: 2 - - platform: sm2335 - id: sm2335_coldwhite - channel: 4 - - platform: sm2335 - id: sm2335_warmwhite - channel: 3 +<<: !include common.yaml diff --git a/tests/components/sm2335/test.rp2040.yaml b/tests/components/sm2335/test.rp2040.yaml index a5b2aedeb5..dade44d145 100644 --- a/tests/components/sm2335/test.rp2040.yaml +++ b/tests/components/sm2335/test.rp2040.yaml @@ -1,22 +1 @@ -sm2335: - clock_pin: 4 - data_pin: 5 - max_power_color_channels: 9 - max_power_white_channels: 9 - -output: - - platform: sm2335 - id: sm2335_red - channel: 1 - - platform: sm2335 - id: sm2335_green - channel: 0 - - platform: sm2335 - id: sm2335_blue - channel: 2 - - platform: sm2335 - id: sm2335_coldwhite - channel: 4 - - platform: sm2335 - id: sm2335_warmwhite - channel: 3 +<<: !include common.yaml diff --git a/tests/components/sntp/common.yaml b/tests/components/sntp/common.yaml new file mode 100644 index 0000000000..3e9e465296 --- /dev/null +++ b/tests/components/sntp/common.yaml @@ -0,0 +1,15 @@ +wifi: + ssid: MySSID + password: password1 + +time: + - platform: sntp + id: sntp_time + servers: + - 0.pool.ntp.org + - 1.pool.ntp.org + - 192.168.178.1 + on_time: + cron: "/30 0-30,30/5 * ? JAN-DEC MON,SAT-SUN,TUE-FRI" + then: + - lambda: 'ESP_LOGD("main", "time");' diff --git a/tests/components/sntp/test.esp32-c3-idf.yaml b/tests/components/sntp/test.esp32-c3-idf.yaml index 3e9e465296..dade44d145 100644 --- a/tests/components/sntp/test.esp32-c3-idf.yaml +++ b/tests/components/sntp/test.esp32-c3-idf.yaml @@ -1,15 +1 @@ -wifi: - ssid: MySSID - password: password1 - -time: - - platform: sntp - id: sntp_time - servers: - - 0.pool.ntp.org - - 1.pool.ntp.org - - 192.168.178.1 - on_time: - cron: "/30 0-30,30/5 * ? JAN-DEC MON,SAT-SUN,TUE-FRI" - then: - - lambda: 'ESP_LOGD("main", "time");' +<<: !include common.yaml diff --git a/tests/components/sntp/test.esp32-c3.yaml b/tests/components/sntp/test.esp32-c3.yaml index 3e9e465296..dade44d145 100644 --- a/tests/components/sntp/test.esp32-c3.yaml +++ b/tests/components/sntp/test.esp32-c3.yaml @@ -1,15 +1 @@ -wifi: - ssid: MySSID - password: password1 - -time: - - platform: sntp - id: sntp_time - servers: - - 0.pool.ntp.org - - 1.pool.ntp.org - - 192.168.178.1 - on_time: - cron: "/30 0-30,30/5 * ? JAN-DEC MON,SAT-SUN,TUE-FRI" - then: - - lambda: 'ESP_LOGD("main", "time");' +<<: !include common.yaml diff --git a/tests/components/sntp/test.esp32-idf.yaml b/tests/components/sntp/test.esp32-idf.yaml index 3e9e465296..dade44d145 100644 --- a/tests/components/sntp/test.esp32-idf.yaml +++ b/tests/components/sntp/test.esp32-idf.yaml @@ -1,15 +1 @@ -wifi: - ssid: MySSID - password: password1 - -time: - - platform: sntp - id: sntp_time - servers: - - 0.pool.ntp.org - - 1.pool.ntp.org - - 192.168.178.1 - on_time: - cron: "/30 0-30,30/5 * ? JAN-DEC MON,SAT-SUN,TUE-FRI" - then: - - lambda: 'ESP_LOGD("main", "time");' +<<: !include common.yaml diff --git a/tests/components/sntp/test.esp32.yaml b/tests/components/sntp/test.esp32.yaml index 3e9e465296..dade44d145 100644 --- a/tests/components/sntp/test.esp32.yaml +++ b/tests/components/sntp/test.esp32.yaml @@ -1,15 +1 @@ -wifi: - ssid: MySSID - password: password1 - -time: - - platform: sntp - id: sntp_time - servers: - - 0.pool.ntp.org - - 1.pool.ntp.org - - 192.168.178.1 - on_time: - cron: "/30 0-30,30/5 * ? JAN-DEC MON,SAT-SUN,TUE-FRI" - then: - - lambda: 'ESP_LOGD("main", "time");' +<<: !include common.yaml diff --git a/tests/components/sntp/test.esp8266.yaml b/tests/components/sntp/test.esp8266.yaml index 3e9e465296..dade44d145 100644 --- a/tests/components/sntp/test.esp8266.yaml +++ b/tests/components/sntp/test.esp8266.yaml @@ -1,15 +1 @@ -wifi: - ssid: MySSID - password: password1 - -time: - - platform: sntp - id: sntp_time - servers: - - 0.pool.ntp.org - - 1.pool.ntp.org - - 192.168.178.1 - on_time: - cron: "/30 0-30,30/5 * ? JAN-DEC MON,SAT-SUN,TUE-FRI" - then: - - lambda: 'ESP_LOGD("main", "time");' +<<: !include common.yaml diff --git a/tests/components/sntp/test.rp2040.yaml b/tests/components/sntp/test.rp2040.yaml index 3e9e465296..dade44d145 100644 --- a/tests/components/sntp/test.rp2040.yaml +++ b/tests/components/sntp/test.rp2040.yaml @@ -1,15 +1 @@ -wifi: - ssid: MySSID - password: password1 - -time: - - platform: sntp - id: sntp_time - servers: - - 0.pool.ntp.org - - 1.pool.ntp.org - - 192.168.178.1 - on_time: - cron: "/30 0-30,30/5 * ? JAN-DEC MON,SAT-SUN,TUE-FRI" - then: - - lambda: 'ESP_LOGD("main", "time");' +<<: !include common.yaml diff --git a/tests/components/sprinkler/common.yaml b/tests/components/sprinkler/common.yaml new file mode 100644 index 0000000000..f099f77729 --- /dev/null +++ b/tests/components/sprinkler/common.yaml @@ -0,0 +1,83 @@ +esphome: + on_boot: + then: + - sprinkler.start_full_cycle: yard_sprinkler_ctrlr + - sprinkler.start_from_queue: yard_sprinkler_ctrlr + - sprinkler.start_single_valve: + id: yard_sprinkler_ctrlr + valve_number: 0 + run_duration: 600s + - sprinkler.shutdown: yard_sprinkler_ctrlr + - sprinkler.next_valve: yard_sprinkler_ctrlr + - sprinkler.previous_valve: yard_sprinkler_ctrlr + - sprinkler.pause: yard_sprinkler_ctrlr + - sprinkler.resume: yard_sprinkler_ctrlr + - sprinkler.resume_or_start_full_cycle: yard_sprinkler_ctrlr + - sprinkler.queue_valve: + id: yard_sprinkler_ctrlr + valve_number: 2 + run_duration: 900s + - sprinkler.clear_queued_valves: yard_sprinkler_ctrlr + - sprinkler.set_multiplier: + id: yard_sprinkler_ctrlr + multiplier: 1.5 + - sprinkler.set_repeat: + id: yard_sprinkler_ctrlr + repeat: 2 + - sprinkler.set_divider: + id: yard_sprinkler_ctrlr + divider: 2 + - sprinkler.set_valve_run_duration: + id: yard_sprinkler_ctrlr + valve_number: 0 + run_duration: 600s + +switch: + - platform: template + id: switch1 + optimistic: true + - platform: template + id: switch2 + optimistic: true + +sprinkler: + - id: yard_sprinkler_ctrlr + main_switch: Yard Sprinklers + auto_advance_switch: Yard Sprinklers Auto Advance + reverse_switch: Yard Sprinklers Reverse + pump_start_pump_delay: 2s + pump_stop_valve_delay: 4s + pump_switch_off_during_valve_open_delay: true + valve_open_delay: 5s + valves: + - valve_switch: Yard Valve 0 + enable_switch: Enable Yard Valve 0 + pump_switch_id: switch1 + run_duration: 10s + valve_switch_id: switch2 + - valve_switch: Yard Valve 1 + enable_switch: Enable Yard Valve 1 + pump_switch_id: switch1 + run_duration: 10s + valve_switch_id: switch2 + - valve_switch: Yard Valve 2 + enable_switch: Enable Yard Valve 2 + pump_switch_id: switch1 + run_duration: 10s + valve_switch_id: switch2 + - id: garden_sprinkler_ctrlr + main_switch: Garden Sprinklers + auto_advance_switch: Garden Sprinklers Auto Advance + reverse_switch: Garden Sprinklers Reverse + valve_overlap: 5s + valves: + - valve_switch: Garden Valve 0 + enable_switch: Enable Garden Valve 0 + pump_switch_id: switch1 + run_duration: 10s + valve_switch_id: switch2 + - valve_switch: Garden Valve 1 + enable_switch: Enable Garden Valve 1 + pump_switch_id: switch1 + run_duration: 10s + valve_switch_id: switch2 diff --git a/tests/components/sprinkler/test.esp32-c3-idf.yaml b/tests/components/sprinkler/test.esp32-c3-idf.yaml index f099f77729..dade44d145 100644 --- a/tests/components/sprinkler/test.esp32-c3-idf.yaml +++ b/tests/components/sprinkler/test.esp32-c3-idf.yaml @@ -1,83 +1 @@ -esphome: - on_boot: - then: - - sprinkler.start_full_cycle: yard_sprinkler_ctrlr - - sprinkler.start_from_queue: yard_sprinkler_ctrlr - - sprinkler.start_single_valve: - id: yard_sprinkler_ctrlr - valve_number: 0 - run_duration: 600s - - sprinkler.shutdown: yard_sprinkler_ctrlr - - sprinkler.next_valve: yard_sprinkler_ctrlr - - sprinkler.previous_valve: yard_sprinkler_ctrlr - - sprinkler.pause: yard_sprinkler_ctrlr - - sprinkler.resume: yard_sprinkler_ctrlr - - sprinkler.resume_or_start_full_cycle: yard_sprinkler_ctrlr - - sprinkler.queue_valve: - id: yard_sprinkler_ctrlr - valve_number: 2 - run_duration: 900s - - sprinkler.clear_queued_valves: yard_sprinkler_ctrlr - - sprinkler.set_multiplier: - id: yard_sprinkler_ctrlr - multiplier: 1.5 - - sprinkler.set_repeat: - id: yard_sprinkler_ctrlr - repeat: 2 - - sprinkler.set_divider: - id: yard_sprinkler_ctrlr - divider: 2 - - sprinkler.set_valve_run_duration: - id: yard_sprinkler_ctrlr - valve_number: 0 - run_duration: 600s - -switch: - - platform: template - id: switch1 - optimistic: true - - platform: template - id: switch2 - optimistic: true - -sprinkler: - - id: yard_sprinkler_ctrlr - main_switch: Yard Sprinklers - auto_advance_switch: Yard Sprinklers Auto Advance - reverse_switch: Yard Sprinklers Reverse - pump_start_pump_delay: 2s - pump_stop_valve_delay: 4s - pump_switch_off_during_valve_open_delay: true - valve_open_delay: 5s - valves: - - valve_switch: Yard Valve 0 - enable_switch: Enable Yard Valve 0 - pump_switch_id: switch1 - run_duration: 10s - valve_switch_id: switch2 - - valve_switch: Yard Valve 1 - enable_switch: Enable Yard Valve 1 - pump_switch_id: switch1 - run_duration: 10s - valve_switch_id: switch2 - - valve_switch: Yard Valve 2 - enable_switch: Enable Yard Valve 2 - pump_switch_id: switch1 - run_duration: 10s - valve_switch_id: switch2 - - id: garden_sprinkler_ctrlr - main_switch: Garden Sprinklers - auto_advance_switch: Garden Sprinklers Auto Advance - reverse_switch: Garden Sprinklers Reverse - valve_overlap: 5s - valves: - - valve_switch: Garden Valve 0 - enable_switch: Enable Garden Valve 0 - pump_switch_id: switch1 - run_duration: 10s - valve_switch_id: switch2 - - valve_switch: Garden Valve 1 - enable_switch: Enable Garden Valve 1 - pump_switch_id: switch1 - run_duration: 10s - valve_switch_id: switch2 +<<: !include common.yaml diff --git a/tests/components/sprinkler/test.esp32-c3.yaml b/tests/components/sprinkler/test.esp32-c3.yaml index f099f77729..dade44d145 100644 --- a/tests/components/sprinkler/test.esp32-c3.yaml +++ b/tests/components/sprinkler/test.esp32-c3.yaml @@ -1,83 +1 @@ -esphome: - on_boot: - then: - - sprinkler.start_full_cycle: yard_sprinkler_ctrlr - - sprinkler.start_from_queue: yard_sprinkler_ctrlr - - sprinkler.start_single_valve: - id: yard_sprinkler_ctrlr - valve_number: 0 - run_duration: 600s - - sprinkler.shutdown: yard_sprinkler_ctrlr - - sprinkler.next_valve: yard_sprinkler_ctrlr - - sprinkler.previous_valve: yard_sprinkler_ctrlr - - sprinkler.pause: yard_sprinkler_ctrlr - - sprinkler.resume: yard_sprinkler_ctrlr - - sprinkler.resume_or_start_full_cycle: yard_sprinkler_ctrlr - - sprinkler.queue_valve: - id: yard_sprinkler_ctrlr - valve_number: 2 - run_duration: 900s - - sprinkler.clear_queued_valves: yard_sprinkler_ctrlr - - sprinkler.set_multiplier: - id: yard_sprinkler_ctrlr - multiplier: 1.5 - - sprinkler.set_repeat: - id: yard_sprinkler_ctrlr - repeat: 2 - - sprinkler.set_divider: - id: yard_sprinkler_ctrlr - divider: 2 - - sprinkler.set_valve_run_duration: - id: yard_sprinkler_ctrlr - valve_number: 0 - run_duration: 600s - -switch: - - platform: template - id: switch1 - optimistic: true - - platform: template - id: switch2 - optimistic: true - -sprinkler: - - id: yard_sprinkler_ctrlr - main_switch: Yard Sprinklers - auto_advance_switch: Yard Sprinklers Auto Advance - reverse_switch: Yard Sprinklers Reverse - pump_start_pump_delay: 2s - pump_stop_valve_delay: 4s - pump_switch_off_during_valve_open_delay: true - valve_open_delay: 5s - valves: - - valve_switch: Yard Valve 0 - enable_switch: Enable Yard Valve 0 - pump_switch_id: switch1 - run_duration: 10s - valve_switch_id: switch2 - - valve_switch: Yard Valve 1 - enable_switch: Enable Yard Valve 1 - pump_switch_id: switch1 - run_duration: 10s - valve_switch_id: switch2 - - valve_switch: Yard Valve 2 - enable_switch: Enable Yard Valve 2 - pump_switch_id: switch1 - run_duration: 10s - valve_switch_id: switch2 - - id: garden_sprinkler_ctrlr - main_switch: Garden Sprinklers - auto_advance_switch: Garden Sprinklers Auto Advance - reverse_switch: Garden Sprinklers Reverse - valve_overlap: 5s - valves: - - valve_switch: Garden Valve 0 - enable_switch: Enable Garden Valve 0 - pump_switch_id: switch1 - run_duration: 10s - valve_switch_id: switch2 - - valve_switch: Garden Valve 1 - enable_switch: Enable Garden Valve 1 - pump_switch_id: switch1 - run_duration: 10s - valve_switch_id: switch2 +<<: !include common.yaml diff --git a/tests/components/sprinkler/test.esp32-idf.yaml b/tests/components/sprinkler/test.esp32-idf.yaml index f099f77729..dade44d145 100644 --- a/tests/components/sprinkler/test.esp32-idf.yaml +++ b/tests/components/sprinkler/test.esp32-idf.yaml @@ -1,83 +1 @@ -esphome: - on_boot: - then: - - sprinkler.start_full_cycle: yard_sprinkler_ctrlr - - sprinkler.start_from_queue: yard_sprinkler_ctrlr - - sprinkler.start_single_valve: - id: yard_sprinkler_ctrlr - valve_number: 0 - run_duration: 600s - - sprinkler.shutdown: yard_sprinkler_ctrlr - - sprinkler.next_valve: yard_sprinkler_ctrlr - - sprinkler.previous_valve: yard_sprinkler_ctrlr - - sprinkler.pause: yard_sprinkler_ctrlr - - sprinkler.resume: yard_sprinkler_ctrlr - - sprinkler.resume_or_start_full_cycle: yard_sprinkler_ctrlr - - sprinkler.queue_valve: - id: yard_sprinkler_ctrlr - valve_number: 2 - run_duration: 900s - - sprinkler.clear_queued_valves: yard_sprinkler_ctrlr - - sprinkler.set_multiplier: - id: yard_sprinkler_ctrlr - multiplier: 1.5 - - sprinkler.set_repeat: - id: yard_sprinkler_ctrlr - repeat: 2 - - sprinkler.set_divider: - id: yard_sprinkler_ctrlr - divider: 2 - - sprinkler.set_valve_run_duration: - id: yard_sprinkler_ctrlr - valve_number: 0 - run_duration: 600s - -switch: - - platform: template - id: switch1 - optimistic: true - - platform: template - id: switch2 - optimistic: true - -sprinkler: - - id: yard_sprinkler_ctrlr - main_switch: Yard Sprinklers - auto_advance_switch: Yard Sprinklers Auto Advance - reverse_switch: Yard Sprinklers Reverse - pump_start_pump_delay: 2s - pump_stop_valve_delay: 4s - pump_switch_off_during_valve_open_delay: true - valve_open_delay: 5s - valves: - - valve_switch: Yard Valve 0 - enable_switch: Enable Yard Valve 0 - pump_switch_id: switch1 - run_duration: 10s - valve_switch_id: switch2 - - valve_switch: Yard Valve 1 - enable_switch: Enable Yard Valve 1 - pump_switch_id: switch1 - run_duration: 10s - valve_switch_id: switch2 - - valve_switch: Yard Valve 2 - enable_switch: Enable Yard Valve 2 - pump_switch_id: switch1 - run_duration: 10s - valve_switch_id: switch2 - - id: garden_sprinkler_ctrlr - main_switch: Garden Sprinklers - auto_advance_switch: Garden Sprinklers Auto Advance - reverse_switch: Garden Sprinklers Reverse - valve_overlap: 5s - valves: - - valve_switch: Garden Valve 0 - enable_switch: Enable Garden Valve 0 - pump_switch_id: switch1 - run_duration: 10s - valve_switch_id: switch2 - - valve_switch: Garden Valve 1 - enable_switch: Enable Garden Valve 1 - pump_switch_id: switch1 - run_duration: 10s - valve_switch_id: switch2 +<<: !include common.yaml diff --git a/tests/components/sprinkler/test.esp32.yaml b/tests/components/sprinkler/test.esp32.yaml index f099f77729..dade44d145 100644 --- a/tests/components/sprinkler/test.esp32.yaml +++ b/tests/components/sprinkler/test.esp32.yaml @@ -1,83 +1 @@ -esphome: - on_boot: - then: - - sprinkler.start_full_cycle: yard_sprinkler_ctrlr - - sprinkler.start_from_queue: yard_sprinkler_ctrlr - - sprinkler.start_single_valve: - id: yard_sprinkler_ctrlr - valve_number: 0 - run_duration: 600s - - sprinkler.shutdown: yard_sprinkler_ctrlr - - sprinkler.next_valve: yard_sprinkler_ctrlr - - sprinkler.previous_valve: yard_sprinkler_ctrlr - - sprinkler.pause: yard_sprinkler_ctrlr - - sprinkler.resume: yard_sprinkler_ctrlr - - sprinkler.resume_or_start_full_cycle: yard_sprinkler_ctrlr - - sprinkler.queue_valve: - id: yard_sprinkler_ctrlr - valve_number: 2 - run_duration: 900s - - sprinkler.clear_queued_valves: yard_sprinkler_ctrlr - - sprinkler.set_multiplier: - id: yard_sprinkler_ctrlr - multiplier: 1.5 - - sprinkler.set_repeat: - id: yard_sprinkler_ctrlr - repeat: 2 - - sprinkler.set_divider: - id: yard_sprinkler_ctrlr - divider: 2 - - sprinkler.set_valve_run_duration: - id: yard_sprinkler_ctrlr - valve_number: 0 - run_duration: 600s - -switch: - - platform: template - id: switch1 - optimistic: true - - platform: template - id: switch2 - optimistic: true - -sprinkler: - - id: yard_sprinkler_ctrlr - main_switch: Yard Sprinklers - auto_advance_switch: Yard Sprinklers Auto Advance - reverse_switch: Yard Sprinklers Reverse - pump_start_pump_delay: 2s - pump_stop_valve_delay: 4s - pump_switch_off_during_valve_open_delay: true - valve_open_delay: 5s - valves: - - valve_switch: Yard Valve 0 - enable_switch: Enable Yard Valve 0 - pump_switch_id: switch1 - run_duration: 10s - valve_switch_id: switch2 - - valve_switch: Yard Valve 1 - enable_switch: Enable Yard Valve 1 - pump_switch_id: switch1 - run_duration: 10s - valve_switch_id: switch2 - - valve_switch: Yard Valve 2 - enable_switch: Enable Yard Valve 2 - pump_switch_id: switch1 - run_duration: 10s - valve_switch_id: switch2 - - id: garden_sprinkler_ctrlr - main_switch: Garden Sprinklers - auto_advance_switch: Garden Sprinklers Auto Advance - reverse_switch: Garden Sprinklers Reverse - valve_overlap: 5s - valves: - - valve_switch: Garden Valve 0 - enable_switch: Enable Garden Valve 0 - pump_switch_id: switch1 - run_duration: 10s - valve_switch_id: switch2 - - valve_switch: Garden Valve 1 - enable_switch: Enable Garden Valve 1 - pump_switch_id: switch1 - run_duration: 10s - valve_switch_id: switch2 +<<: !include common.yaml diff --git a/tests/components/sprinkler/test.esp8266.yaml b/tests/components/sprinkler/test.esp8266.yaml index f099f77729..dade44d145 100644 --- a/tests/components/sprinkler/test.esp8266.yaml +++ b/tests/components/sprinkler/test.esp8266.yaml @@ -1,83 +1 @@ -esphome: - on_boot: - then: - - sprinkler.start_full_cycle: yard_sprinkler_ctrlr - - sprinkler.start_from_queue: yard_sprinkler_ctrlr - - sprinkler.start_single_valve: - id: yard_sprinkler_ctrlr - valve_number: 0 - run_duration: 600s - - sprinkler.shutdown: yard_sprinkler_ctrlr - - sprinkler.next_valve: yard_sprinkler_ctrlr - - sprinkler.previous_valve: yard_sprinkler_ctrlr - - sprinkler.pause: yard_sprinkler_ctrlr - - sprinkler.resume: yard_sprinkler_ctrlr - - sprinkler.resume_or_start_full_cycle: yard_sprinkler_ctrlr - - sprinkler.queue_valve: - id: yard_sprinkler_ctrlr - valve_number: 2 - run_duration: 900s - - sprinkler.clear_queued_valves: yard_sprinkler_ctrlr - - sprinkler.set_multiplier: - id: yard_sprinkler_ctrlr - multiplier: 1.5 - - sprinkler.set_repeat: - id: yard_sprinkler_ctrlr - repeat: 2 - - sprinkler.set_divider: - id: yard_sprinkler_ctrlr - divider: 2 - - sprinkler.set_valve_run_duration: - id: yard_sprinkler_ctrlr - valve_number: 0 - run_duration: 600s - -switch: - - platform: template - id: switch1 - optimistic: true - - platform: template - id: switch2 - optimistic: true - -sprinkler: - - id: yard_sprinkler_ctrlr - main_switch: Yard Sprinklers - auto_advance_switch: Yard Sprinklers Auto Advance - reverse_switch: Yard Sprinklers Reverse - pump_start_pump_delay: 2s - pump_stop_valve_delay: 4s - pump_switch_off_during_valve_open_delay: true - valve_open_delay: 5s - valves: - - valve_switch: Yard Valve 0 - enable_switch: Enable Yard Valve 0 - pump_switch_id: switch1 - run_duration: 10s - valve_switch_id: switch2 - - valve_switch: Yard Valve 1 - enable_switch: Enable Yard Valve 1 - pump_switch_id: switch1 - run_duration: 10s - valve_switch_id: switch2 - - valve_switch: Yard Valve 2 - enable_switch: Enable Yard Valve 2 - pump_switch_id: switch1 - run_duration: 10s - valve_switch_id: switch2 - - id: garden_sprinkler_ctrlr - main_switch: Garden Sprinklers - auto_advance_switch: Garden Sprinklers Auto Advance - reverse_switch: Garden Sprinklers Reverse - valve_overlap: 5s - valves: - - valve_switch: Garden Valve 0 - enable_switch: Enable Garden Valve 0 - pump_switch_id: switch1 - run_duration: 10s - valve_switch_id: switch2 - - valve_switch: Garden Valve 1 - enable_switch: Enable Garden Valve 1 - pump_switch_id: switch1 - run_duration: 10s - valve_switch_id: switch2 +<<: !include common.yaml diff --git a/tests/components/sprinkler/test.rp2040.yaml b/tests/components/sprinkler/test.rp2040.yaml index f099f77729..dade44d145 100644 --- a/tests/components/sprinkler/test.rp2040.yaml +++ b/tests/components/sprinkler/test.rp2040.yaml @@ -1,83 +1 @@ -esphome: - on_boot: - then: - - sprinkler.start_full_cycle: yard_sprinkler_ctrlr - - sprinkler.start_from_queue: yard_sprinkler_ctrlr - - sprinkler.start_single_valve: - id: yard_sprinkler_ctrlr - valve_number: 0 - run_duration: 600s - - sprinkler.shutdown: yard_sprinkler_ctrlr - - sprinkler.next_valve: yard_sprinkler_ctrlr - - sprinkler.previous_valve: yard_sprinkler_ctrlr - - sprinkler.pause: yard_sprinkler_ctrlr - - sprinkler.resume: yard_sprinkler_ctrlr - - sprinkler.resume_or_start_full_cycle: yard_sprinkler_ctrlr - - sprinkler.queue_valve: - id: yard_sprinkler_ctrlr - valve_number: 2 - run_duration: 900s - - sprinkler.clear_queued_valves: yard_sprinkler_ctrlr - - sprinkler.set_multiplier: - id: yard_sprinkler_ctrlr - multiplier: 1.5 - - sprinkler.set_repeat: - id: yard_sprinkler_ctrlr - repeat: 2 - - sprinkler.set_divider: - id: yard_sprinkler_ctrlr - divider: 2 - - sprinkler.set_valve_run_duration: - id: yard_sprinkler_ctrlr - valve_number: 0 - run_duration: 600s - -switch: - - platform: template - id: switch1 - optimistic: true - - platform: template - id: switch2 - optimistic: true - -sprinkler: - - id: yard_sprinkler_ctrlr - main_switch: Yard Sprinklers - auto_advance_switch: Yard Sprinklers Auto Advance - reverse_switch: Yard Sprinklers Reverse - pump_start_pump_delay: 2s - pump_stop_valve_delay: 4s - pump_switch_off_during_valve_open_delay: true - valve_open_delay: 5s - valves: - - valve_switch: Yard Valve 0 - enable_switch: Enable Yard Valve 0 - pump_switch_id: switch1 - run_duration: 10s - valve_switch_id: switch2 - - valve_switch: Yard Valve 1 - enable_switch: Enable Yard Valve 1 - pump_switch_id: switch1 - run_duration: 10s - valve_switch_id: switch2 - - valve_switch: Yard Valve 2 - enable_switch: Enable Yard Valve 2 - pump_switch_id: switch1 - run_duration: 10s - valve_switch_id: switch2 - - id: garden_sprinkler_ctrlr - main_switch: Garden Sprinklers - auto_advance_switch: Garden Sprinklers Auto Advance - reverse_switch: Garden Sprinklers Reverse - valve_overlap: 5s - valves: - - valve_switch: Garden Valve 0 - enable_switch: Enable Garden Valve 0 - pump_switch_id: switch1 - run_duration: 10s - valve_switch_id: switch2 - - valve_switch: Garden Valve 1 - enable_switch: Enable Garden Valve 1 - pump_switch_id: switch1 - run_duration: 10s - valve_switch_id: switch2 +<<: !include common.yaml diff --git a/tests/components/st7701s/common.yaml b/tests/components/st7701s/common.yaml new file mode 100644 index 0000000000..497df8c8ce --- /dev/null +++ b/tests/components/st7701s/common.yaml @@ -0,0 +1,60 @@ +psram: + mode: octal + speed: 80MHz +spi: + - id: lcd_spi + clk_pin: 41 + mosi_pin: 48 + +i2c: + sda: 39 + scl: 40 + scan: false + id: bus_a + +pca9554: + - id: p_c_a + pin_count: 16 + address: 0x20 + +display: + - platform: st7701s + spi_mode: MODE3 + color_order: RGB + dimensions: + width: 480 + height: 480 + invert_colors: true + transform: + mirror_x: true + mirror_y: true + cs_pin: + pca9554: p_c_a + number: 4 + reset_pin: + pca9554: p_c_a + number: 5 + de_pin: 18 + hsync_pin: 16 + vsync_pin: 17 + pclk_pin: 21 + init_sequence: 1 + data_pins: + - number: 0 + ignore_strapping_warning: true + - 1 + - 2 + - 3 + - number: 4 + ignore_strapping_warning: false + - 5 + - 6 + - 7 + - 8 + - 9 + - 10 + - 11 + - 12 + - 13 + - 14 + - 15 diff --git a/tests/components/st7701s/test.esp32-s3-idf.yaml b/tests/components/st7701s/test.esp32-s3-idf.yaml index 497df8c8ce..dade44d145 100644 --- a/tests/components/st7701s/test.esp32-s3-idf.yaml +++ b/tests/components/st7701s/test.esp32-s3-idf.yaml @@ -1,60 +1 @@ -psram: - mode: octal - speed: 80MHz -spi: - - id: lcd_spi - clk_pin: 41 - mosi_pin: 48 - -i2c: - sda: 39 - scl: 40 - scan: false - id: bus_a - -pca9554: - - id: p_c_a - pin_count: 16 - address: 0x20 - -display: - - platform: st7701s - spi_mode: MODE3 - color_order: RGB - dimensions: - width: 480 - height: 480 - invert_colors: true - transform: - mirror_x: true - mirror_y: true - cs_pin: - pca9554: p_c_a - number: 4 - reset_pin: - pca9554: p_c_a - number: 5 - de_pin: 18 - hsync_pin: 16 - vsync_pin: 17 - pclk_pin: 21 - init_sequence: 1 - data_pins: - - number: 0 - ignore_strapping_warning: true - - 1 - - 2 - - 3 - - number: 4 - ignore_strapping_warning: false - - 5 - - 6 - - 7 - - 8 - - 9 - - 10 - - 11 - - 12 - - 13 - - 14 - - 15 +<<: !include common.yaml diff --git a/tests/components/status/common.yaml b/tests/components/status/common.yaml new file mode 100644 index 0000000000..c14157566b --- /dev/null +++ b/tests/components/status/common.yaml @@ -0,0 +1,10 @@ +wifi: + ssid: MySSID + password: password1 + +api: + +binary_sensor: + - platform: status + id: node_status + name: Node Status diff --git a/tests/components/status/test.esp32-c3-idf.yaml b/tests/components/status/test.esp32-c3-idf.yaml index c14157566b..dade44d145 100644 --- a/tests/components/status/test.esp32-c3-idf.yaml +++ b/tests/components/status/test.esp32-c3-idf.yaml @@ -1,10 +1 @@ -wifi: - ssid: MySSID - password: password1 - -api: - -binary_sensor: - - platform: status - id: node_status - name: Node Status +<<: !include common.yaml diff --git a/tests/components/status/test.esp32-c3.yaml b/tests/components/status/test.esp32-c3.yaml index c14157566b..dade44d145 100644 --- a/tests/components/status/test.esp32-c3.yaml +++ b/tests/components/status/test.esp32-c3.yaml @@ -1,10 +1 @@ -wifi: - ssid: MySSID - password: password1 - -api: - -binary_sensor: - - platform: status - id: node_status - name: Node Status +<<: !include common.yaml diff --git a/tests/components/status/test.esp32-idf.yaml b/tests/components/status/test.esp32-idf.yaml index c14157566b..dade44d145 100644 --- a/tests/components/status/test.esp32-idf.yaml +++ b/tests/components/status/test.esp32-idf.yaml @@ -1,10 +1 @@ -wifi: - ssid: MySSID - password: password1 - -api: - -binary_sensor: - - platform: status - id: node_status - name: Node Status +<<: !include common.yaml diff --git a/tests/components/status/test.esp32.yaml b/tests/components/status/test.esp32.yaml index c14157566b..dade44d145 100644 --- a/tests/components/status/test.esp32.yaml +++ b/tests/components/status/test.esp32.yaml @@ -1,10 +1 @@ -wifi: - ssid: MySSID - password: password1 - -api: - -binary_sensor: - - platform: status - id: node_status - name: Node Status +<<: !include common.yaml diff --git a/tests/components/status/test.esp8266.yaml b/tests/components/status/test.esp8266.yaml index c14157566b..dade44d145 100644 --- a/tests/components/status/test.esp8266.yaml +++ b/tests/components/status/test.esp8266.yaml @@ -1,10 +1 @@ -wifi: - ssid: MySSID - password: password1 - -api: - -binary_sensor: - - platform: status - id: node_status - name: Node Status +<<: !include common.yaml diff --git a/tests/components/status/test.rp2040.yaml b/tests/components/status/test.rp2040.yaml index c14157566b..dade44d145 100644 --- a/tests/components/status/test.rp2040.yaml +++ b/tests/components/status/test.rp2040.yaml @@ -1,10 +1 @@ -wifi: - ssid: MySSID - password: password1 - -api: - -binary_sensor: - - platform: status - id: node_status - name: Node Status +<<: !include common.yaml diff --git a/tests/components/status_led/common.yaml b/tests/components/status_led/common.yaml new file mode 100644 index 0000000000..ec66c219d3 --- /dev/null +++ b/tests/components/status_led/common.yaml @@ -0,0 +1,10 @@ +wifi: + ssid: MySSID + password: password1 + +api: + +light: + - platform: status_led + name: Switch State + pin: 4 diff --git a/tests/components/status_led/test.esp32-c3-idf.yaml b/tests/components/status_led/test.esp32-c3-idf.yaml index ec66c219d3..dade44d145 100644 --- a/tests/components/status_led/test.esp32-c3-idf.yaml +++ b/tests/components/status_led/test.esp32-c3-idf.yaml @@ -1,10 +1 @@ -wifi: - ssid: MySSID - password: password1 - -api: - -light: - - platform: status_led - name: Switch State - pin: 4 +<<: !include common.yaml diff --git a/tests/components/status_led/test.esp32-c3.yaml b/tests/components/status_led/test.esp32-c3.yaml index ec66c219d3..dade44d145 100644 --- a/tests/components/status_led/test.esp32-c3.yaml +++ b/tests/components/status_led/test.esp32-c3.yaml @@ -1,10 +1 @@ -wifi: - ssid: MySSID - password: password1 - -api: - -light: - - platform: status_led - name: Switch State - pin: 4 +<<: !include common.yaml diff --git a/tests/components/status_led/test.esp32-idf.yaml b/tests/components/status_led/test.esp32-idf.yaml index ec66c219d3..dade44d145 100644 --- a/tests/components/status_led/test.esp32-idf.yaml +++ b/tests/components/status_led/test.esp32-idf.yaml @@ -1,10 +1 @@ -wifi: - ssid: MySSID - password: password1 - -api: - -light: - - platform: status_led - name: Switch State - pin: 4 +<<: !include common.yaml diff --git a/tests/components/status_led/test.esp32.yaml b/tests/components/status_led/test.esp32.yaml index ec66c219d3..dade44d145 100644 --- a/tests/components/status_led/test.esp32.yaml +++ b/tests/components/status_led/test.esp32.yaml @@ -1,10 +1 @@ -wifi: - ssid: MySSID - password: password1 - -api: - -light: - - platform: status_led - name: Switch State - pin: 4 +<<: !include common.yaml diff --git a/tests/components/status_led/test.esp8266.yaml b/tests/components/status_led/test.esp8266.yaml index ec66c219d3..dade44d145 100644 --- a/tests/components/status_led/test.esp8266.yaml +++ b/tests/components/status_led/test.esp8266.yaml @@ -1,10 +1 @@ -wifi: - ssid: MySSID - password: password1 - -api: - -light: - - platform: status_led - name: Switch State - pin: 4 +<<: !include common.yaml diff --git a/tests/components/status_led/test.rp2040.yaml b/tests/components/status_led/test.rp2040.yaml index ec66c219d3..dade44d145 100644 --- a/tests/components/status_led/test.rp2040.yaml +++ b/tests/components/status_led/test.rp2040.yaml @@ -1,10 +1 @@ -wifi: - ssid: MySSID - password: password1 - -api: - -light: - - platform: status_led - name: Switch State - pin: 4 +<<: !include common.yaml diff --git a/tests/components/stepper/common.yaml b/tests/components/stepper/common.yaml new file mode 100644 index 0000000000..fcf5759618 --- /dev/null +++ b/tests/components/stepper/common.yaml @@ -0,0 +1,27 @@ +stepper: + - platform: a4988 + id: test_stepper + step_pin: 3 + dir_pin: 4 + sleep_pin: 5 + max_speed: 250 steps/s + acceleration: 100 steps/s^2 + deceleration: 200 steps/s^2 + +switch: + - platform: template + name: Stepper Switch + assumed_state: true + turn_on_action: + - stepper.set_target: + id: test_stepper + target: !lambda |- + static int32_t i = 0; + i += 1000; + if (i > 5000) { + i = -5000; + } + return i; + - stepper.report_position: + id: test_stepper + position: 0 diff --git a/tests/components/stepper/test.esp32-c3-idf.yaml b/tests/components/stepper/test.esp32-c3-idf.yaml index fcf5759618..dade44d145 100644 --- a/tests/components/stepper/test.esp32-c3-idf.yaml +++ b/tests/components/stepper/test.esp32-c3-idf.yaml @@ -1,27 +1 @@ -stepper: - - platform: a4988 - id: test_stepper - step_pin: 3 - dir_pin: 4 - sleep_pin: 5 - max_speed: 250 steps/s - acceleration: 100 steps/s^2 - deceleration: 200 steps/s^2 - -switch: - - platform: template - name: Stepper Switch - assumed_state: true - turn_on_action: - - stepper.set_target: - id: test_stepper - target: !lambda |- - static int32_t i = 0; - i += 1000; - if (i > 5000) { - i = -5000; - } - return i; - - stepper.report_position: - id: test_stepper - position: 0 +<<: !include common.yaml diff --git a/tests/components/stepper/test.esp32-c3.yaml b/tests/components/stepper/test.esp32-c3.yaml index fcf5759618..dade44d145 100644 --- a/tests/components/stepper/test.esp32-c3.yaml +++ b/tests/components/stepper/test.esp32-c3.yaml @@ -1,27 +1 @@ -stepper: - - platform: a4988 - id: test_stepper - step_pin: 3 - dir_pin: 4 - sleep_pin: 5 - max_speed: 250 steps/s - acceleration: 100 steps/s^2 - deceleration: 200 steps/s^2 - -switch: - - platform: template - name: Stepper Switch - assumed_state: true - turn_on_action: - - stepper.set_target: - id: test_stepper - target: !lambda |- - static int32_t i = 0; - i += 1000; - if (i > 5000) { - i = -5000; - } - return i; - - stepper.report_position: - id: test_stepper - position: 0 +<<: !include common.yaml diff --git a/tests/components/stepper/test.esp32-idf.yaml b/tests/components/stepper/test.esp32-idf.yaml index fcf5759618..dade44d145 100644 --- a/tests/components/stepper/test.esp32-idf.yaml +++ b/tests/components/stepper/test.esp32-idf.yaml @@ -1,27 +1 @@ -stepper: - - platform: a4988 - id: test_stepper - step_pin: 3 - dir_pin: 4 - sleep_pin: 5 - max_speed: 250 steps/s - acceleration: 100 steps/s^2 - deceleration: 200 steps/s^2 - -switch: - - platform: template - name: Stepper Switch - assumed_state: true - turn_on_action: - - stepper.set_target: - id: test_stepper - target: !lambda |- - static int32_t i = 0; - i += 1000; - if (i > 5000) { - i = -5000; - } - return i; - - stepper.report_position: - id: test_stepper - position: 0 +<<: !include common.yaml diff --git a/tests/components/stepper/test.esp32.yaml b/tests/components/stepper/test.esp32.yaml index fcf5759618..dade44d145 100644 --- a/tests/components/stepper/test.esp32.yaml +++ b/tests/components/stepper/test.esp32.yaml @@ -1,27 +1 @@ -stepper: - - platform: a4988 - id: test_stepper - step_pin: 3 - dir_pin: 4 - sleep_pin: 5 - max_speed: 250 steps/s - acceleration: 100 steps/s^2 - deceleration: 200 steps/s^2 - -switch: - - platform: template - name: Stepper Switch - assumed_state: true - turn_on_action: - - stepper.set_target: - id: test_stepper - target: !lambda |- - static int32_t i = 0; - i += 1000; - if (i > 5000) { - i = -5000; - } - return i; - - stepper.report_position: - id: test_stepper - position: 0 +<<: !include common.yaml diff --git a/tests/components/stepper/test.esp8266.yaml b/tests/components/stepper/test.esp8266.yaml index fcf5759618..dade44d145 100644 --- a/tests/components/stepper/test.esp8266.yaml +++ b/tests/components/stepper/test.esp8266.yaml @@ -1,27 +1 @@ -stepper: - - platform: a4988 - id: test_stepper - step_pin: 3 - dir_pin: 4 - sleep_pin: 5 - max_speed: 250 steps/s - acceleration: 100 steps/s^2 - deceleration: 200 steps/s^2 - -switch: - - platform: template - name: Stepper Switch - assumed_state: true - turn_on_action: - - stepper.set_target: - id: test_stepper - target: !lambda |- - static int32_t i = 0; - i += 1000; - if (i > 5000) { - i = -5000; - } - return i; - - stepper.report_position: - id: test_stepper - position: 0 +<<: !include common.yaml diff --git a/tests/components/stepper/test.rp2040.yaml b/tests/components/stepper/test.rp2040.yaml index fcf5759618..dade44d145 100644 --- a/tests/components/stepper/test.rp2040.yaml +++ b/tests/components/stepper/test.rp2040.yaml @@ -1,27 +1 @@ -stepper: - - platform: a4988 - id: test_stepper - step_pin: 3 - dir_pin: 4 - sleep_pin: 5 - max_speed: 250 steps/s - acceleration: 100 steps/s^2 - deceleration: 200 steps/s^2 - -switch: - - platform: template - name: Stepper Switch - assumed_state: true - turn_on_action: - - stepper.set_target: - id: test_stepper - target: !lambda |- - static int32_t i = 0; - i += 1000; - if (i > 5000) { - i = -5000; - } - return i; - - stepper.report_position: - id: test_stepper - position: 0 +<<: !include common.yaml diff --git a/tests/components/sun/common.yaml b/tests/components/sun/common.yaml new file mode 100644 index 0000000000..e0157424a0 --- /dev/null +++ b/tests/components/sun/common.yaml @@ -0,0 +1,38 @@ +wifi: + ssid: MySSID + password: password1 + +api: + +time: + - platform: homeassistant + id: homeassistant_time + +sun: + latitude: 48.8584° + longitude: 2.2945° + on_sunrise: + - then: + - logger.log: Good morning + - elevation: 5° + then: + - logger.log: Good morning again + on_sunset: + - then: + - logger.log: Good evening + +sensor: + - platform: sun + name: Sun Elevation + type: elevation + - platform: sun + name: Sun Azimuth + type: azimuth + +text_sensor: + - platform: sun + name: Sun Next Sunrise + type: sunrise + - platform: sun + name: Sun Next Sunset + type: sunset diff --git a/tests/components/sun/test.esp32-c3-idf.yaml b/tests/components/sun/test.esp32-c3-idf.yaml index e0157424a0..dade44d145 100644 --- a/tests/components/sun/test.esp32-c3-idf.yaml +++ b/tests/components/sun/test.esp32-c3-idf.yaml @@ -1,38 +1 @@ -wifi: - ssid: MySSID - password: password1 - -api: - -time: - - platform: homeassistant - id: homeassistant_time - -sun: - latitude: 48.8584° - longitude: 2.2945° - on_sunrise: - - then: - - logger.log: Good morning - - elevation: 5° - then: - - logger.log: Good morning again - on_sunset: - - then: - - logger.log: Good evening - -sensor: - - platform: sun - name: Sun Elevation - type: elevation - - platform: sun - name: Sun Azimuth - type: azimuth - -text_sensor: - - platform: sun - name: Sun Next Sunrise - type: sunrise - - platform: sun - name: Sun Next Sunset - type: sunset +<<: !include common.yaml diff --git a/tests/components/sun/test.esp32-c3.yaml b/tests/components/sun/test.esp32-c3.yaml index e0157424a0..dade44d145 100644 --- a/tests/components/sun/test.esp32-c3.yaml +++ b/tests/components/sun/test.esp32-c3.yaml @@ -1,38 +1 @@ -wifi: - ssid: MySSID - password: password1 - -api: - -time: - - platform: homeassistant - id: homeassistant_time - -sun: - latitude: 48.8584° - longitude: 2.2945° - on_sunrise: - - then: - - logger.log: Good morning - - elevation: 5° - then: - - logger.log: Good morning again - on_sunset: - - then: - - logger.log: Good evening - -sensor: - - platform: sun - name: Sun Elevation - type: elevation - - platform: sun - name: Sun Azimuth - type: azimuth - -text_sensor: - - platform: sun - name: Sun Next Sunrise - type: sunrise - - platform: sun - name: Sun Next Sunset - type: sunset +<<: !include common.yaml diff --git a/tests/components/sun/test.esp32-idf.yaml b/tests/components/sun/test.esp32-idf.yaml index e0157424a0..dade44d145 100644 --- a/tests/components/sun/test.esp32-idf.yaml +++ b/tests/components/sun/test.esp32-idf.yaml @@ -1,38 +1 @@ -wifi: - ssid: MySSID - password: password1 - -api: - -time: - - platform: homeassistant - id: homeassistant_time - -sun: - latitude: 48.8584° - longitude: 2.2945° - on_sunrise: - - then: - - logger.log: Good morning - - elevation: 5° - then: - - logger.log: Good morning again - on_sunset: - - then: - - logger.log: Good evening - -sensor: - - platform: sun - name: Sun Elevation - type: elevation - - platform: sun - name: Sun Azimuth - type: azimuth - -text_sensor: - - platform: sun - name: Sun Next Sunrise - type: sunrise - - platform: sun - name: Sun Next Sunset - type: sunset +<<: !include common.yaml diff --git a/tests/components/sun/test.esp32.yaml b/tests/components/sun/test.esp32.yaml index e0157424a0..dade44d145 100644 --- a/tests/components/sun/test.esp32.yaml +++ b/tests/components/sun/test.esp32.yaml @@ -1,38 +1 @@ -wifi: - ssid: MySSID - password: password1 - -api: - -time: - - platform: homeassistant - id: homeassistant_time - -sun: - latitude: 48.8584° - longitude: 2.2945° - on_sunrise: - - then: - - logger.log: Good morning - - elevation: 5° - then: - - logger.log: Good morning again - on_sunset: - - then: - - logger.log: Good evening - -sensor: - - platform: sun - name: Sun Elevation - type: elevation - - platform: sun - name: Sun Azimuth - type: azimuth - -text_sensor: - - platform: sun - name: Sun Next Sunrise - type: sunrise - - platform: sun - name: Sun Next Sunset - type: sunset +<<: !include common.yaml diff --git a/tests/components/sun/test.esp8266.yaml b/tests/components/sun/test.esp8266.yaml index e0157424a0..dade44d145 100644 --- a/tests/components/sun/test.esp8266.yaml +++ b/tests/components/sun/test.esp8266.yaml @@ -1,38 +1 @@ -wifi: - ssid: MySSID - password: password1 - -api: - -time: - - platform: homeassistant - id: homeassistant_time - -sun: - latitude: 48.8584° - longitude: 2.2945° - on_sunrise: - - then: - - logger.log: Good morning - - elevation: 5° - then: - - logger.log: Good morning again - on_sunset: - - then: - - logger.log: Good evening - -sensor: - - platform: sun - name: Sun Elevation - type: elevation - - platform: sun - name: Sun Azimuth - type: azimuth - -text_sensor: - - platform: sun - name: Sun Next Sunrise - type: sunrise - - platform: sun - name: Sun Next Sunset - type: sunset +<<: !include common.yaml diff --git a/tests/components/sun/test.rp2040.yaml b/tests/components/sun/test.rp2040.yaml index e0157424a0..dade44d145 100644 --- a/tests/components/sun/test.rp2040.yaml +++ b/tests/components/sun/test.rp2040.yaml @@ -1,38 +1 @@ -wifi: - ssid: MySSID - password: password1 - -api: - -time: - - platform: homeassistant - id: homeassistant_time - -sun: - latitude: 48.8584° - longitude: 2.2945° - on_sunrise: - - then: - - logger.log: Good morning - - elevation: 5° - then: - - logger.log: Good morning again - on_sunset: - - then: - - logger.log: Good evening - -sensor: - - platform: sun - name: Sun Elevation - type: elevation - - platform: sun - name: Sun Azimuth - type: azimuth - -text_sensor: - - platform: sun - name: Sun Next Sunrise - type: sunrise - - platform: sun - name: Sun Next Sunset - type: sunset +<<: !include common.yaml diff --git a/tests/components/thermostat/common.yaml b/tests/components/thermostat/common.yaml new file mode 100644 index 0000000000..d630a93efc --- /dev/null +++ b/tests/components/thermostat/common.yaml @@ -0,0 +1,93 @@ +sensor: + - platform: template + id: thermostat_sensor + lambda: "return 21;" + +climate: + - platform: thermostat + name: Test Thermostat + sensor: thermostat_sensor + humidity_sensor: thermostat_sensor + preset: + - name: Default Preset + default_target_temperature_low: 18°C + default_target_temperature_high: 24°C + - name: Away + default_target_temperature_low: 16°C + default_target_temperature_high: 20°C + idle_action: + - logger.log: idle_action + cool_action: + - logger.log: cool_action + supplemental_cooling_action: + - logger.log: supplemental_cooling_action + heat_action: + - logger.log: heat_action + supplemental_heating_action: + - logger.log: supplemental_heating_action + dry_action: + - logger.log: dry_action + fan_only_action: + - logger.log: fan_only_action + auto_mode: + - logger.log: auto_mode + off_mode: + - logger.log: off_mode + heat_mode: + - logger.log: heat_mode + cool_mode: + - logger.log: cool_mode + dry_mode: + - logger.log: dry_mode + fan_only_mode: + - logger.log: fan_only_mode + fan_mode_auto_action: + - logger.log: fan_mode_auto_action + fan_mode_on_action: + - logger.log: fan_mode_on_action + fan_mode_off_action: + - logger.log: fan_mode_off_action + fan_mode_low_action: + - logger.log: fan_mode_low_action + fan_mode_medium_action: + - logger.log: fan_mode_medium_action + fan_mode_high_action: + - logger.log: fan_mode_high_action + fan_mode_middle_action: + - logger.log: fan_mode_middle_action + fan_mode_focus_action: + - logger.log: fan_mode_focus_action + fan_mode_diffuse_action: + - logger.log: fan_mode_diffuse_action + fan_mode_quiet_action: + - logger.log: fan_mode_quiet_action + swing_off_action: + - logger.log: swing_off_action + swing_horizontal_action: + - logger.log: swing_horizontal_action + swing_vertical_action: + - logger.log: swing_vertical_action + swing_both_action: + - logger.log: swing_both_action + startup_delay: true + supplemental_cooling_delta: 2.0 + cool_deadband: 0.5 + cool_overrun: 0.5 + min_cooling_off_time: 300s + min_cooling_run_time: 300s + max_cooling_run_time: 600s + supplemental_heating_delta: 2.0 + heat_deadband: 0.5 + heat_overrun: 0.5 + min_heating_off_time: 300s + min_heating_run_time: 300s + max_heating_run_time: 600s + min_fanning_off_time: 30s + min_fanning_run_time: 30s + min_fan_mode_switching_time: 15s + min_idle_time: 30s + set_point_minimum_differential: 0.5 + fan_only_action_uses_fan_mode_timer: true + fan_only_cooling: true + fan_with_cooling: true + fan_with_heating: true diff --git a/tests/components/thermostat/test.esp32-c3-idf.yaml b/tests/components/thermostat/test.esp32-c3-idf.yaml index d630a93efc..dade44d145 100644 --- a/tests/components/thermostat/test.esp32-c3-idf.yaml +++ b/tests/components/thermostat/test.esp32-c3-idf.yaml @@ -1,93 +1 @@ -sensor: - - platform: template - id: thermostat_sensor - lambda: "return 21;" - -climate: - - platform: thermostat - name: Test Thermostat - sensor: thermostat_sensor - humidity_sensor: thermostat_sensor - preset: - - name: Default Preset - default_target_temperature_low: 18°C - default_target_temperature_high: 24°C - - name: Away - default_target_temperature_low: 16°C - default_target_temperature_high: 20°C - idle_action: - - logger.log: idle_action - cool_action: - - logger.log: cool_action - supplemental_cooling_action: - - logger.log: supplemental_cooling_action - heat_action: - - logger.log: heat_action - supplemental_heating_action: - - logger.log: supplemental_heating_action - dry_action: - - logger.log: dry_action - fan_only_action: - - logger.log: fan_only_action - auto_mode: - - logger.log: auto_mode - off_mode: - - logger.log: off_mode - heat_mode: - - logger.log: heat_mode - cool_mode: - - logger.log: cool_mode - dry_mode: - - logger.log: dry_mode - fan_only_mode: - - logger.log: fan_only_mode - fan_mode_auto_action: - - logger.log: fan_mode_auto_action - fan_mode_on_action: - - logger.log: fan_mode_on_action - fan_mode_off_action: - - logger.log: fan_mode_off_action - fan_mode_low_action: - - logger.log: fan_mode_low_action - fan_mode_medium_action: - - logger.log: fan_mode_medium_action - fan_mode_high_action: - - logger.log: fan_mode_high_action - fan_mode_middle_action: - - logger.log: fan_mode_middle_action - fan_mode_focus_action: - - logger.log: fan_mode_focus_action - fan_mode_diffuse_action: - - logger.log: fan_mode_diffuse_action - fan_mode_quiet_action: - - logger.log: fan_mode_quiet_action - swing_off_action: - - logger.log: swing_off_action - swing_horizontal_action: - - logger.log: swing_horizontal_action - swing_vertical_action: - - logger.log: swing_vertical_action - swing_both_action: - - logger.log: swing_both_action - startup_delay: true - supplemental_cooling_delta: 2.0 - cool_deadband: 0.5 - cool_overrun: 0.5 - min_cooling_off_time: 300s - min_cooling_run_time: 300s - max_cooling_run_time: 600s - supplemental_heating_delta: 2.0 - heat_deadband: 0.5 - heat_overrun: 0.5 - min_heating_off_time: 300s - min_heating_run_time: 300s - max_heating_run_time: 600s - min_fanning_off_time: 30s - min_fanning_run_time: 30s - min_fan_mode_switching_time: 15s - min_idle_time: 30s - set_point_minimum_differential: 0.5 - fan_only_action_uses_fan_mode_timer: true - fan_only_cooling: true - fan_with_cooling: true - fan_with_heating: true +<<: !include common.yaml diff --git a/tests/components/thermostat/test.esp32-c3.yaml b/tests/components/thermostat/test.esp32-c3.yaml index d630a93efc..dade44d145 100644 --- a/tests/components/thermostat/test.esp32-c3.yaml +++ b/tests/components/thermostat/test.esp32-c3.yaml @@ -1,93 +1 @@ -sensor: - - platform: template - id: thermostat_sensor - lambda: "return 21;" - -climate: - - platform: thermostat - name: Test Thermostat - sensor: thermostat_sensor - humidity_sensor: thermostat_sensor - preset: - - name: Default Preset - default_target_temperature_low: 18°C - default_target_temperature_high: 24°C - - name: Away - default_target_temperature_low: 16°C - default_target_temperature_high: 20°C - idle_action: - - logger.log: idle_action - cool_action: - - logger.log: cool_action - supplemental_cooling_action: - - logger.log: supplemental_cooling_action - heat_action: - - logger.log: heat_action - supplemental_heating_action: - - logger.log: supplemental_heating_action - dry_action: - - logger.log: dry_action - fan_only_action: - - logger.log: fan_only_action - auto_mode: - - logger.log: auto_mode - off_mode: - - logger.log: off_mode - heat_mode: - - logger.log: heat_mode - cool_mode: - - logger.log: cool_mode - dry_mode: - - logger.log: dry_mode - fan_only_mode: - - logger.log: fan_only_mode - fan_mode_auto_action: - - logger.log: fan_mode_auto_action - fan_mode_on_action: - - logger.log: fan_mode_on_action - fan_mode_off_action: - - logger.log: fan_mode_off_action - fan_mode_low_action: - - logger.log: fan_mode_low_action - fan_mode_medium_action: - - logger.log: fan_mode_medium_action - fan_mode_high_action: - - logger.log: fan_mode_high_action - fan_mode_middle_action: - - logger.log: fan_mode_middle_action - fan_mode_focus_action: - - logger.log: fan_mode_focus_action - fan_mode_diffuse_action: - - logger.log: fan_mode_diffuse_action - fan_mode_quiet_action: - - logger.log: fan_mode_quiet_action - swing_off_action: - - logger.log: swing_off_action - swing_horizontal_action: - - logger.log: swing_horizontal_action - swing_vertical_action: - - logger.log: swing_vertical_action - swing_both_action: - - logger.log: swing_both_action - startup_delay: true - supplemental_cooling_delta: 2.0 - cool_deadband: 0.5 - cool_overrun: 0.5 - min_cooling_off_time: 300s - min_cooling_run_time: 300s - max_cooling_run_time: 600s - supplemental_heating_delta: 2.0 - heat_deadband: 0.5 - heat_overrun: 0.5 - min_heating_off_time: 300s - min_heating_run_time: 300s - max_heating_run_time: 600s - min_fanning_off_time: 30s - min_fanning_run_time: 30s - min_fan_mode_switching_time: 15s - min_idle_time: 30s - set_point_minimum_differential: 0.5 - fan_only_action_uses_fan_mode_timer: true - fan_only_cooling: true - fan_with_cooling: true - fan_with_heating: true +<<: !include common.yaml diff --git a/tests/components/thermostat/test.esp32-idf.yaml b/tests/components/thermostat/test.esp32-idf.yaml index d630a93efc..dade44d145 100644 --- a/tests/components/thermostat/test.esp32-idf.yaml +++ b/tests/components/thermostat/test.esp32-idf.yaml @@ -1,93 +1 @@ -sensor: - - platform: template - id: thermostat_sensor - lambda: "return 21;" - -climate: - - platform: thermostat - name: Test Thermostat - sensor: thermostat_sensor - humidity_sensor: thermostat_sensor - preset: - - name: Default Preset - default_target_temperature_low: 18°C - default_target_temperature_high: 24°C - - name: Away - default_target_temperature_low: 16°C - default_target_temperature_high: 20°C - idle_action: - - logger.log: idle_action - cool_action: - - logger.log: cool_action - supplemental_cooling_action: - - logger.log: supplemental_cooling_action - heat_action: - - logger.log: heat_action - supplemental_heating_action: - - logger.log: supplemental_heating_action - dry_action: - - logger.log: dry_action - fan_only_action: - - logger.log: fan_only_action - auto_mode: - - logger.log: auto_mode - off_mode: - - logger.log: off_mode - heat_mode: - - logger.log: heat_mode - cool_mode: - - logger.log: cool_mode - dry_mode: - - logger.log: dry_mode - fan_only_mode: - - logger.log: fan_only_mode - fan_mode_auto_action: - - logger.log: fan_mode_auto_action - fan_mode_on_action: - - logger.log: fan_mode_on_action - fan_mode_off_action: - - logger.log: fan_mode_off_action - fan_mode_low_action: - - logger.log: fan_mode_low_action - fan_mode_medium_action: - - logger.log: fan_mode_medium_action - fan_mode_high_action: - - logger.log: fan_mode_high_action - fan_mode_middle_action: - - logger.log: fan_mode_middle_action - fan_mode_focus_action: - - logger.log: fan_mode_focus_action - fan_mode_diffuse_action: - - logger.log: fan_mode_diffuse_action - fan_mode_quiet_action: - - logger.log: fan_mode_quiet_action - swing_off_action: - - logger.log: swing_off_action - swing_horizontal_action: - - logger.log: swing_horizontal_action - swing_vertical_action: - - logger.log: swing_vertical_action - swing_both_action: - - logger.log: swing_both_action - startup_delay: true - supplemental_cooling_delta: 2.0 - cool_deadband: 0.5 - cool_overrun: 0.5 - min_cooling_off_time: 300s - min_cooling_run_time: 300s - max_cooling_run_time: 600s - supplemental_heating_delta: 2.0 - heat_deadband: 0.5 - heat_overrun: 0.5 - min_heating_off_time: 300s - min_heating_run_time: 300s - max_heating_run_time: 600s - min_fanning_off_time: 30s - min_fanning_run_time: 30s - min_fan_mode_switching_time: 15s - min_idle_time: 30s - set_point_minimum_differential: 0.5 - fan_only_action_uses_fan_mode_timer: true - fan_only_cooling: true - fan_with_cooling: true - fan_with_heating: true +<<: !include common.yaml diff --git a/tests/components/thermostat/test.esp32.yaml b/tests/components/thermostat/test.esp32.yaml index d630a93efc..dade44d145 100644 --- a/tests/components/thermostat/test.esp32.yaml +++ b/tests/components/thermostat/test.esp32.yaml @@ -1,93 +1 @@ -sensor: - - platform: template - id: thermostat_sensor - lambda: "return 21;" - -climate: - - platform: thermostat - name: Test Thermostat - sensor: thermostat_sensor - humidity_sensor: thermostat_sensor - preset: - - name: Default Preset - default_target_temperature_low: 18°C - default_target_temperature_high: 24°C - - name: Away - default_target_temperature_low: 16°C - default_target_temperature_high: 20°C - idle_action: - - logger.log: idle_action - cool_action: - - logger.log: cool_action - supplemental_cooling_action: - - logger.log: supplemental_cooling_action - heat_action: - - logger.log: heat_action - supplemental_heating_action: - - logger.log: supplemental_heating_action - dry_action: - - logger.log: dry_action - fan_only_action: - - logger.log: fan_only_action - auto_mode: - - logger.log: auto_mode - off_mode: - - logger.log: off_mode - heat_mode: - - logger.log: heat_mode - cool_mode: - - logger.log: cool_mode - dry_mode: - - logger.log: dry_mode - fan_only_mode: - - logger.log: fan_only_mode - fan_mode_auto_action: - - logger.log: fan_mode_auto_action - fan_mode_on_action: - - logger.log: fan_mode_on_action - fan_mode_off_action: - - logger.log: fan_mode_off_action - fan_mode_low_action: - - logger.log: fan_mode_low_action - fan_mode_medium_action: - - logger.log: fan_mode_medium_action - fan_mode_high_action: - - logger.log: fan_mode_high_action - fan_mode_middle_action: - - logger.log: fan_mode_middle_action - fan_mode_focus_action: - - logger.log: fan_mode_focus_action - fan_mode_diffuse_action: - - logger.log: fan_mode_diffuse_action - fan_mode_quiet_action: - - logger.log: fan_mode_quiet_action - swing_off_action: - - logger.log: swing_off_action - swing_horizontal_action: - - logger.log: swing_horizontal_action - swing_vertical_action: - - logger.log: swing_vertical_action - swing_both_action: - - logger.log: swing_both_action - startup_delay: true - supplemental_cooling_delta: 2.0 - cool_deadband: 0.5 - cool_overrun: 0.5 - min_cooling_off_time: 300s - min_cooling_run_time: 300s - max_cooling_run_time: 600s - supplemental_heating_delta: 2.0 - heat_deadband: 0.5 - heat_overrun: 0.5 - min_heating_off_time: 300s - min_heating_run_time: 300s - max_heating_run_time: 600s - min_fanning_off_time: 30s - min_fanning_run_time: 30s - min_fan_mode_switching_time: 15s - min_idle_time: 30s - set_point_minimum_differential: 0.5 - fan_only_action_uses_fan_mode_timer: true - fan_only_cooling: true - fan_with_cooling: true - fan_with_heating: true +<<: !include common.yaml diff --git a/tests/components/thermostat/test.esp8266.yaml b/tests/components/thermostat/test.esp8266.yaml index d630a93efc..dade44d145 100644 --- a/tests/components/thermostat/test.esp8266.yaml +++ b/tests/components/thermostat/test.esp8266.yaml @@ -1,93 +1 @@ -sensor: - - platform: template - id: thermostat_sensor - lambda: "return 21;" - -climate: - - platform: thermostat - name: Test Thermostat - sensor: thermostat_sensor - humidity_sensor: thermostat_sensor - preset: - - name: Default Preset - default_target_temperature_low: 18°C - default_target_temperature_high: 24°C - - name: Away - default_target_temperature_low: 16°C - default_target_temperature_high: 20°C - idle_action: - - logger.log: idle_action - cool_action: - - logger.log: cool_action - supplemental_cooling_action: - - logger.log: supplemental_cooling_action - heat_action: - - logger.log: heat_action - supplemental_heating_action: - - logger.log: supplemental_heating_action - dry_action: - - logger.log: dry_action - fan_only_action: - - logger.log: fan_only_action - auto_mode: - - logger.log: auto_mode - off_mode: - - logger.log: off_mode - heat_mode: - - logger.log: heat_mode - cool_mode: - - logger.log: cool_mode - dry_mode: - - logger.log: dry_mode - fan_only_mode: - - logger.log: fan_only_mode - fan_mode_auto_action: - - logger.log: fan_mode_auto_action - fan_mode_on_action: - - logger.log: fan_mode_on_action - fan_mode_off_action: - - logger.log: fan_mode_off_action - fan_mode_low_action: - - logger.log: fan_mode_low_action - fan_mode_medium_action: - - logger.log: fan_mode_medium_action - fan_mode_high_action: - - logger.log: fan_mode_high_action - fan_mode_middle_action: - - logger.log: fan_mode_middle_action - fan_mode_focus_action: - - logger.log: fan_mode_focus_action - fan_mode_diffuse_action: - - logger.log: fan_mode_diffuse_action - fan_mode_quiet_action: - - logger.log: fan_mode_quiet_action - swing_off_action: - - logger.log: swing_off_action - swing_horizontal_action: - - logger.log: swing_horizontal_action - swing_vertical_action: - - logger.log: swing_vertical_action - swing_both_action: - - logger.log: swing_both_action - startup_delay: true - supplemental_cooling_delta: 2.0 - cool_deadband: 0.5 - cool_overrun: 0.5 - min_cooling_off_time: 300s - min_cooling_run_time: 300s - max_cooling_run_time: 600s - supplemental_heating_delta: 2.0 - heat_deadband: 0.5 - heat_overrun: 0.5 - min_heating_off_time: 300s - min_heating_run_time: 300s - max_heating_run_time: 600s - min_fanning_off_time: 30s - min_fanning_run_time: 30s - min_fan_mode_switching_time: 15s - min_idle_time: 30s - set_point_minimum_differential: 0.5 - fan_only_action_uses_fan_mode_timer: true - fan_only_cooling: true - fan_with_cooling: true - fan_with_heating: true +<<: !include common.yaml diff --git a/tests/components/thermostat/test.rp2040.yaml b/tests/components/thermostat/test.rp2040.yaml index d630a93efc..dade44d145 100644 --- a/tests/components/thermostat/test.rp2040.yaml +++ b/tests/components/thermostat/test.rp2040.yaml @@ -1,93 +1 @@ -sensor: - - platform: template - id: thermostat_sensor - lambda: "return 21;" - -climate: - - platform: thermostat - name: Test Thermostat - sensor: thermostat_sensor - humidity_sensor: thermostat_sensor - preset: - - name: Default Preset - default_target_temperature_low: 18°C - default_target_temperature_high: 24°C - - name: Away - default_target_temperature_low: 16°C - default_target_temperature_high: 20°C - idle_action: - - logger.log: idle_action - cool_action: - - logger.log: cool_action - supplemental_cooling_action: - - logger.log: supplemental_cooling_action - heat_action: - - logger.log: heat_action - supplemental_heating_action: - - logger.log: supplemental_heating_action - dry_action: - - logger.log: dry_action - fan_only_action: - - logger.log: fan_only_action - auto_mode: - - logger.log: auto_mode - off_mode: - - logger.log: off_mode - heat_mode: - - logger.log: heat_mode - cool_mode: - - logger.log: cool_mode - dry_mode: - - logger.log: dry_mode - fan_only_mode: - - logger.log: fan_only_mode - fan_mode_auto_action: - - logger.log: fan_mode_auto_action - fan_mode_on_action: - - logger.log: fan_mode_on_action - fan_mode_off_action: - - logger.log: fan_mode_off_action - fan_mode_low_action: - - logger.log: fan_mode_low_action - fan_mode_medium_action: - - logger.log: fan_mode_medium_action - fan_mode_high_action: - - logger.log: fan_mode_high_action - fan_mode_middle_action: - - logger.log: fan_mode_middle_action - fan_mode_focus_action: - - logger.log: fan_mode_focus_action - fan_mode_diffuse_action: - - logger.log: fan_mode_diffuse_action - fan_mode_quiet_action: - - logger.log: fan_mode_quiet_action - swing_off_action: - - logger.log: swing_off_action - swing_horizontal_action: - - logger.log: swing_horizontal_action - swing_vertical_action: - - logger.log: swing_vertical_action - swing_both_action: - - logger.log: swing_both_action - startup_delay: true - supplemental_cooling_delta: 2.0 - cool_deadband: 0.5 - cool_overrun: 0.5 - min_cooling_off_time: 300s - min_cooling_run_time: 300s - max_cooling_run_time: 600s - supplemental_heating_delta: 2.0 - heat_deadband: 0.5 - heat_overrun: 0.5 - min_heating_off_time: 300s - min_heating_run_time: 300s - max_heating_run_time: 600s - min_fanning_off_time: 30s - min_fanning_run_time: 30s - min_fan_mode_switching_time: 15s - min_idle_time: 30s - set_point_minimum_differential: 0.5 - fan_only_action_uses_fan_mode_timer: true - fan_only_cooling: true - fan_with_cooling: true - fan_with_heating: true +<<: !include common.yaml diff --git a/tests/components/time/common.yaml b/tests/components/time/common.yaml new file mode 100644 index 0000000000..465be045db --- /dev/null +++ b/tests/components/time/common.yaml @@ -0,0 +1,10 @@ +wifi: + ssid: MySSID + password: password1 + +api: + +time: + - platform: homeassistant + - platform: sntp + id: sntp_time diff --git a/tests/components/time/test.esp32-c3-idf.yaml b/tests/components/time/test.esp32-c3-idf.yaml index 465be045db..dade44d145 100644 --- a/tests/components/time/test.esp32-c3-idf.yaml +++ b/tests/components/time/test.esp32-c3-idf.yaml @@ -1,10 +1 @@ -wifi: - ssid: MySSID - password: password1 - -api: - -time: - - platform: homeassistant - - platform: sntp - id: sntp_time +<<: !include common.yaml diff --git a/tests/components/time/test.esp32-c3.yaml b/tests/components/time/test.esp32-c3.yaml index 465be045db..dade44d145 100644 --- a/tests/components/time/test.esp32-c3.yaml +++ b/tests/components/time/test.esp32-c3.yaml @@ -1,10 +1 @@ -wifi: - ssid: MySSID - password: password1 - -api: - -time: - - platform: homeassistant - - platform: sntp - id: sntp_time +<<: !include common.yaml diff --git a/tests/components/time/test.esp32-idf.yaml b/tests/components/time/test.esp32-idf.yaml index 465be045db..dade44d145 100644 --- a/tests/components/time/test.esp32-idf.yaml +++ b/tests/components/time/test.esp32-idf.yaml @@ -1,10 +1 @@ -wifi: - ssid: MySSID - password: password1 - -api: - -time: - - platform: homeassistant - - platform: sntp - id: sntp_time +<<: !include common.yaml diff --git a/tests/components/time/test.esp32.yaml b/tests/components/time/test.esp32.yaml index 465be045db..dade44d145 100644 --- a/tests/components/time/test.esp32.yaml +++ b/tests/components/time/test.esp32.yaml @@ -1,10 +1 @@ -wifi: - ssid: MySSID - password: password1 - -api: - -time: - - platform: homeassistant - - platform: sntp - id: sntp_time +<<: !include common.yaml diff --git a/tests/components/time/test.esp8266.yaml b/tests/components/time/test.esp8266.yaml index 465be045db..dade44d145 100644 --- a/tests/components/time/test.esp8266.yaml +++ b/tests/components/time/test.esp8266.yaml @@ -1,10 +1 @@ -wifi: - ssid: MySSID - password: password1 - -api: - -time: - - platform: homeassistant - - platform: sntp - id: sntp_time +<<: !include common.yaml diff --git a/tests/components/time/test.rp2040.yaml b/tests/components/time/test.rp2040.yaml index 465be045db..dade44d145 100644 --- a/tests/components/time/test.rp2040.yaml +++ b/tests/components/time/test.rp2040.yaml @@ -1,10 +1 @@ -wifi: - ssid: MySSID - password: password1 - -api: - -time: - - platform: homeassistant - - platform: sntp - id: sntp_time +<<: !include common.yaml diff --git a/tests/components/time_based/common.yaml b/tests/components/time_based/common.yaml new file mode 100644 index 0000000000..48c86de90f --- /dev/null +++ b/tests/components/time_based/common.yaml @@ -0,0 +1,12 @@ +cover: + - platform: time_based + name: Time Based Cover + id: time_based_cover + stop_action: + - logger.log: stop_action + open_action: + - logger.log: open_action + open_duration: 5min + close_action: + - logger.log: close_action + close_duration: 4.5min diff --git a/tests/components/time_based/test.esp32-c3-idf.yaml b/tests/components/time_based/test.esp32-c3-idf.yaml index 48c86de90f..dade44d145 100644 --- a/tests/components/time_based/test.esp32-c3-idf.yaml +++ b/tests/components/time_based/test.esp32-c3-idf.yaml @@ -1,12 +1 @@ -cover: - - platform: time_based - name: Time Based Cover - id: time_based_cover - stop_action: - - logger.log: stop_action - open_action: - - logger.log: open_action - open_duration: 5min - close_action: - - logger.log: close_action - close_duration: 4.5min +<<: !include common.yaml diff --git a/tests/components/time_based/test.esp32-c3.yaml b/tests/components/time_based/test.esp32-c3.yaml index 48c86de90f..dade44d145 100644 --- a/tests/components/time_based/test.esp32-c3.yaml +++ b/tests/components/time_based/test.esp32-c3.yaml @@ -1,12 +1 @@ -cover: - - platform: time_based - name: Time Based Cover - id: time_based_cover - stop_action: - - logger.log: stop_action - open_action: - - logger.log: open_action - open_duration: 5min - close_action: - - logger.log: close_action - close_duration: 4.5min +<<: !include common.yaml diff --git a/tests/components/time_based/test.esp32-idf.yaml b/tests/components/time_based/test.esp32-idf.yaml index 48c86de90f..dade44d145 100644 --- a/tests/components/time_based/test.esp32-idf.yaml +++ b/tests/components/time_based/test.esp32-idf.yaml @@ -1,12 +1 @@ -cover: - - platform: time_based - name: Time Based Cover - id: time_based_cover - stop_action: - - logger.log: stop_action - open_action: - - logger.log: open_action - open_duration: 5min - close_action: - - logger.log: close_action - close_duration: 4.5min +<<: !include common.yaml diff --git a/tests/components/time_based/test.esp32.yaml b/tests/components/time_based/test.esp32.yaml index 48c86de90f..dade44d145 100644 --- a/tests/components/time_based/test.esp32.yaml +++ b/tests/components/time_based/test.esp32.yaml @@ -1,12 +1 @@ -cover: - - platform: time_based - name: Time Based Cover - id: time_based_cover - stop_action: - - logger.log: stop_action - open_action: - - logger.log: open_action - open_duration: 5min - close_action: - - logger.log: close_action - close_duration: 4.5min +<<: !include common.yaml diff --git a/tests/components/time_based/test.esp8266.yaml b/tests/components/time_based/test.esp8266.yaml index 48c86de90f..dade44d145 100644 --- a/tests/components/time_based/test.esp8266.yaml +++ b/tests/components/time_based/test.esp8266.yaml @@ -1,12 +1 @@ -cover: - - platform: time_based - name: Time Based Cover - id: time_based_cover - stop_action: - - logger.log: stop_action - open_action: - - logger.log: open_action - open_duration: 5min - close_action: - - logger.log: close_action - close_duration: 4.5min +<<: !include common.yaml diff --git a/tests/components/time_based/test.rp2040.yaml b/tests/components/time_based/test.rp2040.yaml index 48c86de90f..dade44d145 100644 --- a/tests/components/time_based/test.rp2040.yaml +++ b/tests/components/time_based/test.rp2040.yaml @@ -1,12 +1 @@ -cover: - - platform: time_based - name: Time Based Cover - id: time_based_cover - stop_action: - - logger.log: stop_action - open_action: - - logger.log: open_action - open_duration: 5min - close_action: - - logger.log: close_action - close_duration: 4.5min +<<: !include common.yaml diff --git a/tests/components/tm1638/common.yaml b/tests/components/tm1638/common.yaml new file mode 100644 index 0000000000..b0c5cef528 --- /dev/null +++ b/tests/components/tm1638/common.yaml @@ -0,0 +1,118 @@ +display: + - platform: tm1638 + id: tm1638_display + stb_pin: 2 + clk_pin: 5 + dio_pin: 4 + update_interval: 5s + intensity: 5 + lambda: |- + it.print("81818181"); + +binary_sensor: + - platform: tm1638 + id: Button0 + key: 0 + filters: + - delayed_on: 10ms + on_press: + then: + - switch.turn_on: Led0 + on_release: + then: + - switch.turn_off: Led0 + - platform: tm1638 + id: Button1 + key: 1 + on_press: + then: + - switch.turn_on: Led1 + on_release: + then: + - switch.turn_off: Led1 + - platform: tm1638 + id: Button2 + key: 2 + on_press: + then: + - switch.turn_on: Led2 + on_release: + then: + - switch.turn_off: Led2 + - platform: tm1638 + id: Button3 + key: 3 + on_press: + then: + - switch.turn_on: Led3 + on_release: + then: + - switch.turn_off: Led3 + - platform: tm1638 + id: Button4 + key: 4 + on_press: + then: + - output.turn_on: Led4 + on_release: + then: + - output.turn_off: Led4 + - platform: tm1638 + id: Button5 + key: 5 + on_press: + then: + - output.turn_on: Led5 + on_release: + then: + - output.turn_off: Led5 + - platform: tm1638 + id: Button6 + key: 6 + on_press: + then: + - output.turn_on: Led6 + on_release: + then: + - output.turn_off: Led6 + - platform: tm1638 + id: Button7 + key: 7 + on_press: + then: + - output.turn_on: Led7 + on_release: + then: + - output.turn_off: Led7 + +switch: + - platform: tm1638 + id: Led0 + led: 0 + name: TM1638Led0 + - platform: tm1638 + id: Led1 + led: 1 + name: TM1638Led1 + - platform: tm1638 + id: Led2 + led: 2 + name: TM1638Led2 + - platform: tm1638 + id: Led3 + led: 3 + name: TM1638Led3 + +output: + - platform: tm1638 + id: Led4 + led: 4 + - platform: tm1638 + id: Led5 + led: 5 + - platform: tm1638 + id: Led6 + led: 6 + - platform: tm1638 + id: Led7 + led: 7 diff --git a/tests/components/tm1638/test.esp32-c3-idf.yaml b/tests/components/tm1638/test.esp32-c3-idf.yaml index b0c5cef528..dade44d145 100644 --- a/tests/components/tm1638/test.esp32-c3-idf.yaml +++ b/tests/components/tm1638/test.esp32-c3-idf.yaml @@ -1,118 +1 @@ -display: - - platform: tm1638 - id: tm1638_display - stb_pin: 2 - clk_pin: 5 - dio_pin: 4 - update_interval: 5s - intensity: 5 - lambda: |- - it.print("81818181"); - -binary_sensor: - - platform: tm1638 - id: Button0 - key: 0 - filters: - - delayed_on: 10ms - on_press: - then: - - switch.turn_on: Led0 - on_release: - then: - - switch.turn_off: Led0 - - platform: tm1638 - id: Button1 - key: 1 - on_press: - then: - - switch.turn_on: Led1 - on_release: - then: - - switch.turn_off: Led1 - - platform: tm1638 - id: Button2 - key: 2 - on_press: - then: - - switch.turn_on: Led2 - on_release: - then: - - switch.turn_off: Led2 - - platform: tm1638 - id: Button3 - key: 3 - on_press: - then: - - switch.turn_on: Led3 - on_release: - then: - - switch.turn_off: Led3 - - platform: tm1638 - id: Button4 - key: 4 - on_press: - then: - - output.turn_on: Led4 - on_release: - then: - - output.turn_off: Led4 - - platform: tm1638 - id: Button5 - key: 5 - on_press: - then: - - output.turn_on: Led5 - on_release: - then: - - output.turn_off: Led5 - - platform: tm1638 - id: Button6 - key: 6 - on_press: - then: - - output.turn_on: Led6 - on_release: - then: - - output.turn_off: Led6 - - platform: tm1638 - id: Button7 - key: 7 - on_press: - then: - - output.turn_on: Led7 - on_release: - then: - - output.turn_off: Led7 - -switch: - - platform: tm1638 - id: Led0 - led: 0 - name: TM1638Led0 - - platform: tm1638 - id: Led1 - led: 1 - name: TM1638Led1 - - platform: tm1638 - id: Led2 - led: 2 - name: TM1638Led2 - - platform: tm1638 - id: Led3 - led: 3 - name: TM1638Led3 - -output: - - platform: tm1638 - id: Led4 - led: 4 - - platform: tm1638 - id: Led5 - led: 5 - - platform: tm1638 - id: Led6 - led: 6 - - platform: tm1638 - id: Led7 - led: 7 +<<: !include common.yaml diff --git a/tests/components/tm1638/test.esp32-c3.yaml b/tests/components/tm1638/test.esp32-c3.yaml index b0c5cef528..dade44d145 100644 --- a/tests/components/tm1638/test.esp32-c3.yaml +++ b/tests/components/tm1638/test.esp32-c3.yaml @@ -1,118 +1 @@ -display: - - platform: tm1638 - id: tm1638_display - stb_pin: 2 - clk_pin: 5 - dio_pin: 4 - update_interval: 5s - intensity: 5 - lambda: |- - it.print("81818181"); - -binary_sensor: - - platform: tm1638 - id: Button0 - key: 0 - filters: - - delayed_on: 10ms - on_press: - then: - - switch.turn_on: Led0 - on_release: - then: - - switch.turn_off: Led0 - - platform: tm1638 - id: Button1 - key: 1 - on_press: - then: - - switch.turn_on: Led1 - on_release: - then: - - switch.turn_off: Led1 - - platform: tm1638 - id: Button2 - key: 2 - on_press: - then: - - switch.turn_on: Led2 - on_release: - then: - - switch.turn_off: Led2 - - platform: tm1638 - id: Button3 - key: 3 - on_press: - then: - - switch.turn_on: Led3 - on_release: - then: - - switch.turn_off: Led3 - - platform: tm1638 - id: Button4 - key: 4 - on_press: - then: - - output.turn_on: Led4 - on_release: - then: - - output.turn_off: Led4 - - platform: tm1638 - id: Button5 - key: 5 - on_press: - then: - - output.turn_on: Led5 - on_release: - then: - - output.turn_off: Led5 - - platform: tm1638 - id: Button6 - key: 6 - on_press: - then: - - output.turn_on: Led6 - on_release: - then: - - output.turn_off: Led6 - - platform: tm1638 - id: Button7 - key: 7 - on_press: - then: - - output.turn_on: Led7 - on_release: - then: - - output.turn_off: Led7 - -switch: - - platform: tm1638 - id: Led0 - led: 0 - name: TM1638Led0 - - platform: tm1638 - id: Led1 - led: 1 - name: TM1638Led1 - - platform: tm1638 - id: Led2 - led: 2 - name: TM1638Led2 - - platform: tm1638 - id: Led3 - led: 3 - name: TM1638Led3 - -output: - - platform: tm1638 - id: Led4 - led: 4 - - platform: tm1638 - id: Led5 - led: 5 - - platform: tm1638 - id: Led6 - led: 6 - - platform: tm1638 - id: Led7 - led: 7 +<<: !include common.yaml diff --git a/tests/components/tm1638/test.esp32-idf.yaml b/tests/components/tm1638/test.esp32-idf.yaml index b0c5cef528..dade44d145 100644 --- a/tests/components/tm1638/test.esp32-idf.yaml +++ b/tests/components/tm1638/test.esp32-idf.yaml @@ -1,118 +1 @@ -display: - - platform: tm1638 - id: tm1638_display - stb_pin: 2 - clk_pin: 5 - dio_pin: 4 - update_interval: 5s - intensity: 5 - lambda: |- - it.print("81818181"); - -binary_sensor: - - platform: tm1638 - id: Button0 - key: 0 - filters: - - delayed_on: 10ms - on_press: - then: - - switch.turn_on: Led0 - on_release: - then: - - switch.turn_off: Led0 - - platform: tm1638 - id: Button1 - key: 1 - on_press: - then: - - switch.turn_on: Led1 - on_release: - then: - - switch.turn_off: Led1 - - platform: tm1638 - id: Button2 - key: 2 - on_press: - then: - - switch.turn_on: Led2 - on_release: - then: - - switch.turn_off: Led2 - - platform: tm1638 - id: Button3 - key: 3 - on_press: - then: - - switch.turn_on: Led3 - on_release: - then: - - switch.turn_off: Led3 - - platform: tm1638 - id: Button4 - key: 4 - on_press: - then: - - output.turn_on: Led4 - on_release: - then: - - output.turn_off: Led4 - - platform: tm1638 - id: Button5 - key: 5 - on_press: - then: - - output.turn_on: Led5 - on_release: - then: - - output.turn_off: Led5 - - platform: tm1638 - id: Button6 - key: 6 - on_press: - then: - - output.turn_on: Led6 - on_release: - then: - - output.turn_off: Led6 - - platform: tm1638 - id: Button7 - key: 7 - on_press: - then: - - output.turn_on: Led7 - on_release: - then: - - output.turn_off: Led7 - -switch: - - platform: tm1638 - id: Led0 - led: 0 - name: TM1638Led0 - - platform: tm1638 - id: Led1 - led: 1 - name: TM1638Led1 - - platform: tm1638 - id: Led2 - led: 2 - name: TM1638Led2 - - platform: tm1638 - id: Led3 - led: 3 - name: TM1638Led3 - -output: - - platform: tm1638 - id: Led4 - led: 4 - - platform: tm1638 - id: Led5 - led: 5 - - platform: tm1638 - id: Led6 - led: 6 - - platform: tm1638 - id: Led7 - led: 7 +<<: !include common.yaml diff --git a/tests/components/tm1638/test.esp32.yaml b/tests/components/tm1638/test.esp32.yaml index b0c5cef528..dade44d145 100644 --- a/tests/components/tm1638/test.esp32.yaml +++ b/tests/components/tm1638/test.esp32.yaml @@ -1,118 +1 @@ -display: - - platform: tm1638 - id: tm1638_display - stb_pin: 2 - clk_pin: 5 - dio_pin: 4 - update_interval: 5s - intensity: 5 - lambda: |- - it.print("81818181"); - -binary_sensor: - - platform: tm1638 - id: Button0 - key: 0 - filters: - - delayed_on: 10ms - on_press: - then: - - switch.turn_on: Led0 - on_release: - then: - - switch.turn_off: Led0 - - platform: tm1638 - id: Button1 - key: 1 - on_press: - then: - - switch.turn_on: Led1 - on_release: - then: - - switch.turn_off: Led1 - - platform: tm1638 - id: Button2 - key: 2 - on_press: - then: - - switch.turn_on: Led2 - on_release: - then: - - switch.turn_off: Led2 - - platform: tm1638 - id: Button3 - key: 3 - on_press: - then: - - switch.turn_on: Led3 - on_release: - then: - - switch.turn_off: Led3 - - platform: tm1638 - id: Button4 - key: 4 - on_press: - then: - - output.turn_on: Led4 - on_release: - then: - - output.turn_off: Led4 - - platform: tm1638 - id: Button5 - key: 5 - on_press: - then: - - output.turn_on: Led5 - on_release: - then: - - output.turn_off: Led5 - - platform: tm1638 - id: Button6 - key: 6 - on_press: - then: - - output.turn_on: Led6 - on_release: - then: - - output.turn_off: Led6 - - platform: tm1638 - id: Button7 - key: 7 - on_press: - then: - - output.turn_on: Led7 - on_release: - then: - - output.turn_off: Led7 - -switch: - - platform: tm1638 - id: Led0 - led: 0 - name: TM1638Led0 - - platform: tm1638 - id: Led1 - led: 1 - name: TM1638Led1 - - platform: tm1638 - id: Led2 - led: 2 - name: TM1638Led2 - - platform: tm1638 - id: Led3 - led: 3 - name: TM1638Led3 - -output: - - platform: tm1638 - id: Led4 - led: 4 - - platform: tm1638 - id: Led5 - led: 5 - - platform: tm1638 - id: Led6 - led: 6 - - platform: tm1638 - id: Led7 - led: 7 +<<: !include common.yaml diff --git a/tests/components/tm1638/test.esp8266.yaml b/tests/components/tm1638/test.esp8266.yaml index b0c5cef528..dade44d145 100644 --- a/tests/components/tm1638/test.esp8266.yaml +++ b/tests/components/tm1638/test.esp8266.yaml @@ -1,118 +1 @@ -display: - - platform: tm1638 - id: tm1638_display - stb_pin: 2 - clk_pin: 5 - dio_pin: 4 - update_interval: 5s - intensity: 5 - lambda: |- - it.print("81818181"); - -binary_sensor: - - platform: tm1638 - id: Button0 - key: 0 - filters: - - delayed_on: 10ms - on_press: - then: - - switch.turn_on: Led0 - on_release: - then: - - switch.turn_off: Led0 - - platform: tm1638 - id: Button1 - key: 1 - on_press: - then: - - switch.turn_on: Led1 - on_release: - then: - - switch.turn_off: Led1 - - platform: tm1638 - id: Button2 - key: 2 - on_press: - then: - - switch.turn_on: Led2 - on_release: - then: - - switch.turn_off: Led2 - - platform: tm1638 - id: Button3 - key: 3 - on_press: - then: - - switch.turn_on: Led3 - on_release: - then: - - switch.turn_off: Led3 - - platform: tm1638 - id: Button4 - key: 4 - on_press: - then: - - output.turn_on: Led4 - on_release: - then: - - output.turn_off: Led4 - - platform: tm1638 - id: Button5 - key: 5 - on_press: - then: - - output.turn_on: Led5 - on_release: - then: - - output.turn_off: Led5 - - platform: tm1638 - id: Button6 - key: 6 - on_press: - then: - - output.turn_on: Led6 - on_release: - then: - - output.turn_off: Led6 - - platform: tm1638 - id: Button7 - key: 7 - on_press: - then: - - output.turn_on: Led7 - on_release: - then: - - output.turn_off: Led7 - -switch: - - platform: tm1638 - id: Led0 - led: 0 - name: TM1638Led0 - - platform: tm1638 - id: Led1 - led: 1 - name: TM1638Led1 - - platform: tm1638 - id: Led2 - led: 2 - name: TM1638Led2 - - platform: tm1638 - id: Led3 - led: 3 - name: TM1638Led3 - -output: - - platform: tm1638 - id: Led4 - led: 4 - - platform: tm1638 - id: Led5 - led: 5 - - platform: tm1638 - id: Led6 - led: 6 - - platform: tm1638 - id: Led7 - led: 7 +<<: !include common.yaml diff --git a/tests/components/tm1638/test.rp2040.yaml b/tests/components/tm1638/test.rp2040.yaml index b0c5cef528..dade44d145 100644 --- a/tests/components/tm1638/test.rp2040.yaml +++ b/tests/components/tm1638/test.rp2040.yaml @@ -1,118 +1 @@ -display: - - platform: tm1638 - id: tm1638_display - stb_pin: 2 - clk_pin: 5 - dio_pin: 4 - update_interval: 5s - intensity: 5 - lambda: |- - it.print("81818181"); - -binary_sensor: - - platform: tm1638 - id: Button0 - key: 0 - filters: - - delayed_on: 10ms - on_press: - then: - - switch.turn_on: Led0 - on_release: - then: - - switch.turn_off: Led0 - - platform: tm1638 - id: Button1 - key: 1 - on_press: - then: - - switch.turn_on: Led1 - on_release: - then: - - switch.turn_off: Led1 - - platform: tm1638 - id: Button2 - key: 2 - on_press: - then: - - switch.turn_on: Led2 - on_release: - then: - - switch.turn_off: Led2 - - platform: tm1638 - id: Button3 - key: 3 - on_press: - then: - - switch.turn_on: Led3 - on_release: - then: - - switch.turn_off: Led3 - - platform: tm1638 - id: Button4 - key: 4 - on_press: - then: - - output.turn_on: Led4 - on_release: - then: - - output.turn_off: Led4 - - platform: tm1638 - id: Button5 - key: 5 - on_press: - then: - - output.turn_on: Led5 - on_release: - then: - - output.turn_off: Led5 - - platform: tm1638 - id: Button6 - key: 6 - on_press: - then: - - output.turn_on: Led6 - on_release: - then: - - output.turn_off: Led6 - - platform: tm1638 - id: Button7 - key: 7 - on_press: - then: - - output.turn_on: Led7 - on_release: - then: - - output.turn_off: Led7 - -switch: - - platform: tm1638 - id: Led0 - led: 0 - name: TM1638Led0 - - platform: tm1638 - id: Led1 - led: 1 - name: TM1638Led1 - - platform: tm1638 - id: Led2 - led: 2 - name: TM1638Led2 - - platform: tm1638 - id: Led3 - led: 3 - name: TM1638Led3 - -output: - - platform: tm1638 - id: Led4 - led: 4 - - platform: tm1638 - id: Led5 - led: 5 - - platform: tm1638 - id: Led6 - led: 6 - - platform: tm1638 - id: Led7 - led: 7 +<<: !include common.yaml diff --git a/tests/components/tm1651/common.yaml b/tests/components/tm1651/common.yaml new file mode 100644 index 0000000000..667648f4d6 --- /dev/null +++ b/tests/components/tm1651/common.yaml @@ -0,0 +1,21 @@ +tm1651: + id: tm1651_battery + clk_pin: 5 + dio_pin: 4 + +esphome: + on_boot: + then: + - tm1651.set_level_percent: + id: tm1651_battery + level_percent: 50 + - tm1651.set_level: + id: tm1651_battery + level: 5 + - tm1651.set_brightness: + id: tm1651_battery + brightness: 2 + - tm1651.turn_on: + id: tm1651_battery + - tm1651.turn_off: + id: tm1651_battery diff --git a/tests/components/tm1651/test.esp32-c3.yaml b/tests/components/tm1651/test.esp32-c3.yaml index 667648f4d6..dade44d145 100644 --- a/tests/components/tm1651/test.esp32-c3.yaml +++ b/tests/components/tm1651/test.esp32-c3.yaml @@ -1,21 +1 @@ -tm1651: - id: tm1651_battery - clk_pin: 5 - dio_pin: 4 - -esphome: - on_boot: - then: - - tm1651.set_level_percent: - id: tm1651_battery - level_percent: 50 - - tm1651.set_level: - id: tm1651_battery - level: 5 - - tm1651.set_brightness: - id: tm1651_battery - brightness: 2 - - tm1651.turn_on: - id: tm1651_battery - - tm1651.turn_off: - id: tm1651_battery +<<: !include common.yaml diff --git a/tests/components/tm1651/test.esp32.yaml b/tests/components/tm1651/test.esp32.yaml index 667648f4d6..dade44d145 100644 --- a/tests/components/tm1651/test.esp32.yaml +++ b/tests/components/tm1651/test.esp32.yaml @@ -1,21 +1 @@ -tm1651: - id: tm1651_battery - clk_pin: 5 - dio_pin: 4 - -esphome: - on_boot: - then: - - tm1651.set_level_percent: - id: tm1651_battery - level_percent: 50 - - tm1651.set_level: - id: tm1651_battery - level: 5 - - tm1651.set_brightness: - id: tm1651_battery - brightness: 2 - - tm1651.turn_on: - id: tm1651_battery - - tm1651.turn_off: - id: tm1651_battery +<<: !include common.yaml diff --git a/tests/components/tm1651/test.esp8266.yaml b/tests/components/tm1651/test.esp8266.yaml index 667648f4d6..dade44d145 100644 --- a/tests/components/tm1651/test.esp8266.yaml +++ b/tests/components/tm1651/test.esp8266.yaml @@ -1,21 +1 @@ -tm1651: - id: tm1651_battery - clk_pin: 5 - dio_pin: 4 - -esphome: - on_boot: - then: - - tm1651.set_level_percent: - id: tm1651_battery - level_percent: 50 - - tm1651.set_level: - id: tm1651_battery - level: 5 - - tm1651.set_brightness: - id: tm1651_battery - brightness: 2 - - tm1651.turn_on: - id: tm1651_battery - - tm1651.turn_off: - id: tm1651_battery +<<: !include common.yaml diff --git a/tests/components/tm1651/test.rp2040.yaml b/tests/components/tm1651/test.rp2040.yaml index 667648f4d6..dade44d145 100644 --- a/tests/components/tm1651/test.rp2040.yaml +++ b/tests/components/tm1651/test.rp2040.yaml @@ -1,21 +1 @@ -tm1651: - id: tm1651_battery - clk_pin: 5 - dio_pin: 4 - -esphome: - on_boot: - then: - - tm1651.set_level_percent: - id: tm1651_battery - level_percent: 50 - - tm1651.set_level: - id: tm1651_battery - level: 5 - - tm1651.set_brightness: - id: tm1651_battery - brightness: 2 - - tm1651.turn_on: - id: tm1651_battery - - tm1651.turn_off: - id: tm1651_battery +<<: !include common.yaml diff --git a/tests/components/tx20/common.yaml b/tests/components/tx20/common.yaml new file mode 100644 index 0000000000..d826059320 --- /dev/null +++ b/tests/components/tx20/common.yaml @@ -0,0 +1,7 @@ +sensor: + - platform: tx20 + wind_speed: + name: Windspeed + wind_direction_degrees: + name: Winddirection Degrees + pin: 4 diff --git a/tests/components/tx20/test.esp32-c3-idf.yaml b/tests/components/tx20/test.esp32-c3-idf.yaml index d826059320..dade44d145 100644 --- a/tests/components/tx20/test.esp32-c3-idf.yaml +++ b/tests/components/tx20/test.esp32-c3-idf.yaml @@ -1,7 +1 @@ -sensor: - - platform: tx20 - wind_speed: - name: Windspeed - wind_direction_degrees: - name: Winddirection Degrees - pin: 4 +<<: !include common.yaml diff --git a/tests/components/tx20/test.esp32-c3.yaml b/tests/components/tx20/test.esp32-c3.yaml index d826059320..dade44d145 100644 --- a/tests/components/tx20/test.esp32-c3.yaml +++ b/tests/components/tx20/test.esp32-c3.yaml @@ -1,7 +1 @@ -sensor: - - platform: tx20 - wind_speed: - name: Windspeed - wind_direction_degrees: - name: Winddirection Degrees - pin: 4 +<<: !include common.yaml diff --git a/tests/components/tx20/test.esp32-idf.yaml b/tests/components/tx20/test.esp32-idf.yaml index d826059320..dade44d145 100644 --- a/tests/components/tx20/test.esp32-idf.yaml +++ b/tests/components/tx20/test.esp32-idf.yaml @@ -1,7 +1 @@ -sensor: - - platform: tx20 - wind_speed: - name: Windspeed - wind_direction_degrees: - name: Winddirection Degrees - pin: 4 +<<: !include common.yaml diff --git a/tests/components/tx20/test.esp32.yaml b/tests/components/tx20/test.esp32.yaml index d826059320..dade44d145 100644 --- a/tests/components/tx20/test.esp32.yaml +++ b/tests/components/tx20/test.esp32.yaml @@ -1,7 +1 @@ -sensor: - - platform: tx20 - wind_speed: - name: Windspeed - wind_direction_degrees: - name: Winddirection Degrees - pin: 4 +<<: !include common.yaml diff --git a/tests/components/tx20/test.esp8266.yaml b/tests/components/tx20/test.esp8266.yaml index d826059320..dade44d145 100644 --- a/tests/components/tx20/test.esp8266.yaml +++ b/tests/components/tx20/test.esp8266.yaml @@ -1,7 +1 @@ -sensor: - - platform: tx20 - wind_speed: - name: Windspeed - wind_direction_degrees: - name: Winddirection Degrees - pin: 4 +<<: !include common.yaml diff --git a/tests/components/tx20/test.rp2040.yaml b/tests/components/tx20/test.rp2040.yaml index d826059320..dade44d145 100644 --- a/tests/components/tx20/test.rp2040.yaml +++ b/tests/components/tx20/test.rp2040.yaml @@ -1,7 +1 @@ -sensor: - - platform: tx20 - wind_speed: - name: Windspeed - wind_direction_degrees: - name: Winddirection Degrees - pin: 4 +<<: !include common.yaml diff --git a/tests/components/ultrasonic/common.yaml b/tests/components/ultrasonic/common.yaml new file mode 100644 index 0000000000..f1f673d918 --- /dev/null +++ b/tests/components/ultrasonic/common.yaml @@ -0,0 +1,7 @@ +sensor: + - platform: ultrasonic + id: ultrasonic_sensor1 + name: Ultrasonic Sensor + echo_pin: 4 + trigger_pin: 5 + timeout: 5.5m diff --git a/tests/components/ultrasonic/test.esp32-c3-idf.yaml b/tests/components/ultrasonic/test.esp32-c3-idf.yaml index f1f673d918..dade44d145 100644 --- a/tests/components/ultrasonic/test.esp32-c3-idf.yaml +++ b/tests/components/ultrasonic/test.esp32-c3-idf.yaml @@ -1,7 +1 @@ -sensor: - - platform: ultrasonic - id: ultrasonic_sensor1 - name: Ultrasonic Sensor - echo_pin: 4 - trigger_pin: 5 - timeout: 5.5m +<<: !include common.yaml diff --git a/tests/components/ultrasonic/test.esp32-c3.yaml b/tests/components/ultrasonic/test.esp32-c3.yaml index f1f673d918..dade44d145 100644 --- a/tests/components/ultrasonic/test.esp32-c3.yaml +++ b/tests/components/ultrasonic/test.esp32-c3.yaml @@ -1,7 +1 @@ -sensor: - - platform: ultrasonic - id: ultrasonic_sensor1 - name: Ultrasonic Sensor - echo_pin: 4 - trigger_pin: 5 - timeout: 5.5m +<<: !include common.yaml diff --git a/tests/components/ultrasonic/test.esp32-idf.yaml b/tests/components/ultrasonic/test.esp32-idf.yaml index f1f673d918..dade44d145 100644 --- a/tests/components/ultrasonic/test.esp32-idf.yaml +++ b/tests/components/ultrasonic/test.esp32-idf.yaml @@ -1,7 +1 @@ -sensor: - - platform: ultrasonic - id: ultrasonic_sensor1 - name: Ultrasonic Sensor - echo_pin: 4 - trigger_pin: 5 - timeout: 5.5m +<<: !include common.yaml diff --git a/tests/components/ultrasonic/test.esp32.yaml b/tests/components/ultrasonic/test.esp32.yaml index f1f673d918..dade44d145 100644 --- a/tests/components/ultrasonic/test.esp32.yaml +++ b/tests/components/ultrasonic/test.esp32.yaml @@ -1,7 +1 @@ -sensor: - - platform: ultrasonic - id: ultrasonic_sensor1 - name: Ultrasonic Sensor - echo_pin: 4 - trigger_pin: 5 - timeout: 5.5m +<<: !include common.yaml diff --git a/tests/components/ultrasonic/test.esp8266.yaml b/tests/components/ultrasonic/test.esp8266.yaml index f1f673d918..dade44d145 100644 --- a/tests/components/ultrasonic/test.esp8266.yaml +++ b/tests/components/ultrasonic/test.esp8266.yaml @@ -1,7 +1 @@ -sensor: - - platform: ultrasonic - id: ultrasonic_sensor1 - name: Ultrasonic Sensor - echo_pin: 4 - trigger_pin: 5 - timeout: 5.5m +<<: !include common.yaml diff --git a/tests/components/ultrasonic/test.rp2040.yaml b/tests/components/ultrasonic/test.rp2040.yaml index f1f673d918..dade44d145 100644 --- a/tests/components/ultrasonic/test.rp2040.yaml +++ b/tests/components/ultrasonic/test.rp2040.yaml @@ -1,7 +1 @@ -sensor: - - platform: ultrasonic - id: ultrasonic_sensor1 - name: Ultrasonic Sensor - echo_pin: 4 - trigger_pin: 5 - timeout: 5.5m +<<: !include common.yaml diff --git a/tests/components/uptime/common.yaml b/tests/components/uptime/common.yaml new file mode 100644 index 0000000000..872a0e7402 --- /dev/null +++ b/tests/components/uptime/common.yaml @@ -0,0 +1,3 @@ +sensor: + - platform: uptime + name: Uptime Sensor diff --git a/tests/components/uptime/test.esp32-c3-idf.yaml b/tests/components/uptime/test.esp32-c3-idf.yaml index 872a0e7402..dade44d145 100644 --- a/tests/components/uptime/test.esp32-c3-idf.yaml +++ b/tests/components/uptime/test.esp32-c3-idf.yaml @@ -1,3 +1 @@ -sensor: - - platform: uptime - name: Uptime Sensor +<<: !include common.yaml diff --git a/tests/components/uptime/test.esp32-c3.yaml b/tests/components/uptime/test.esp32-c3.yaml index 872a0e7402..dade44d145 100644 --- a/tests/components/uptime/test.esp32-c3.yaml +++ b/tests/components/uptime/test.esp32-c3.yaml @@ -1,3 +1 @@ -sensor: - - platform: uptime - name: Uptime Sensor +<<: !include common.yaml diff --git a/tests/components/uptime/test.esp32-idf.yaml b/tests/components/uptime/test.esp32-idf.yaml index 872a0e7402..dade44d145 100644 --- a/tests/components/uptime/test.esp32-idf.yaml +++ b/tests/components/uptime/test.esp32-idf.yaml @@ -1,3 +1 @@ -sensor: - - platform: uptime - name: Uptime Sensor +<<: !include common.yaml diff --git a/tests/components/uptime/test.esp32.yaml b/tests/components/uptime/test.esp32.yaml index 872a0e7402..dade44d145 100644 --- a/tests/components/uptime/test.esp32.yaml +++ b/tests/components/uptime/test.esp32.yaml @@ -1,3 +1 @@ -sensor: - - platform: uptime - name: Uptime Sensor +<<: !include common.yaml diff --git a/tests/components/uptime/test.esp8266.yaml b/tests/components/uptime/test.esp8266.yaml index 872a0e7402..dade44d145 100644 --- a/tests/components/uptime/test.esp8266.yaml +++ b/tests/components/uptime/test.esp8266.yaml @@ -1,3 +1 @@ -sensor: - - platform: uptime - name: Uptime Sensor +<<: !include common.yaml diff --git a/tests/components/uptime/test.rp2040.yaml b/tests/components/uptime/test.rp2040.yaml index 872a0e7402..dade44d145 100644 --- a/tests/components/uptime/test.rp2040.yaml +++ b/tests/components/uptime/test.rp2040.yaml @@ -1,3 +1 @@ -sensor: - - platform: uptime - name: Uptime Sensor +<<: !include common.yaml diff --git a/tests/components/version/common.yaml b/tests/components/version/common.yaml new file mode 100644 index 0000000000..7713afc37c --- /dev/null +++ b/tests/components/version/common.yaml @@ -0,0 +1,3 @@ +text_sensor: + - platform: version + name: "ESPHome Version" diff --git a/tests/components/version/test.esp32-c3-idf.yaml b/tests/components/version/test.esp32-c3-idf.yaml index 7713afc37c..dade44d145 100644 --- a/tests/components/version/test.esp32-c3-idf.yaml +++ b/tests/components/version/test.esp32-c3-idf.yaml @@ -1,3 +1 @@ -text_sensor: - - platform: version - name: "ESPHome Version" +<<: !include common.yaml diff --git a/tests/components/version/test.esp32-c3.yaml b/tests/components/version/test.esp32-c3.yaml index 7713afc37c..dade44d145 100644 --- a/tests/components/version/test.esp32-c3.yaml +++ b/tests/components/version/test.esp32-c3.yaml @@ -1,3 +1 @@ -text_sensor: - - platform: version - name: "ESPHome Version" +<<: !include common.yaml diff --git a/tests/components/version/test.esp32-idf.yaml b/tests/components/version/test.esp32-idf.yaml index 7713afc37c..dade44d145 100644 --- a/tests/components/version/test.esp32-idf.yaml +++ b/tests/components/version/test.esp32-idf.yaml @@ -1,3 +1 @@ -text_sensor: - - platform: version - name: "ESPHome Version" +<<: !include common.yaml diff --git a/tests/components/version/test.esp32.yaml b/tests/components/version/test.esp32.yaml index 7713afc37c..dade44d145 100644 --- a/tests/components/version/test.esp32.yaml +++ b/tests/components/version/test.esp32.yaml @@ -1,3 +1 @@ -text_sensor: - - platform: version - name: "ESPHome Version" +<<: !include common.yaml diff --git a/tests/components/version/test.esp8266.yaml b/tests/components/version/test.esp8266.yaml index 7713afc37c..dade44d145 100644 --- a/tests/components/version/test.esp8266.yaml +++ b/tests/components/version/test.esp8266.yaml @@ -1,3 +1 @@ -text_sensor: - - platform: version - name: "ESPHome Version" +<<: !include common.yaml diff --git a/tests/components/version/test.rp2040.yaml b/tests/components/version/test.rp2040.yaml index 7713afc37c..dade44d145 100644 --- a/tests/components/version/test.rp2040.yaml +++ b/tests/components/version/test.rp2040.yaml @@ -1,3 +1 @@ -text_sensor: - - platform: version - name: "ESPHome Version" +<<: !include common.yaml diff --git a/tests/components/wake_on_lan/common.yaml b/tests/components/wake_on_lan/common.yaml new file mode 100644 index 0000000000..6a5351b624 --- /dev/null +++ b/tests/components/wake_on_lan/common.yaml @@ -0,0 +1,9 @@ +wifi: + ssid: MySSID + password: password1 + +button: + - platform: wake_on_lan + id: wol_1 + name: wol_test_1 + target_mac_address: 12:34:56:78:90:ab diff --git a/tests/components/wake_on_lan/test.esp32-c3.yaml b/tests/components/wake_on_lan/test.esp32-c3.yaml index 6a5351b624..dade44d145 100644 --- a/tests/components/wake_on_lan/test.esp32-c3.yaml +++ b/tests/components/wake_on_lan/test.esp32-c3.yaml @@ -1,9 +1 @@ -wifi: - ssid: MySSID - password: password1 - -button: - - platform: wake_on_lan - id: wol_1 - name: wol_test_1 - target_mac_address: 12:34:56:78:90:ab +<<: !include common.yaml diff --git a/tests/components/wake_on_lan/test.esp32.yaml b/tests/components/wake_on_lan/test.esp32.yaml index 6a5351b624..dade44d145 100644 --- a/tests/components/wake_on_lan/test.esp32.yaml +++ b/tests/components/wake_on_lan/test.esp32.yaml @@ -1,9 +1 @@ -wifi: - ssid: MySSID - password: password1 - -button: - - platform: wake_on_lan - id: wol_1 - name: wol_test_1 - target_mac_address: 12:34:56:78:90:ab +<<: !include common.yaml diff --git a/tests/components/wake_on_lan/test.esp8266.yaml b/tests/components/wake_on_lan/test.esp8266.yaml index 6a5351b624..dade44d145 100644 --- a/tests/components/wake_on_lan/test.esp8266.yaml +++ b/tests/components/wake_on_lan/test.esp8266.yaml @@ -1,9 +1 @@ -wifi: - ssid: MySSID - password: password1 - -button: - - platform: wake_on_lan - id: wol_1 - name: wol_test_1 - target_mac_address: 12:34:56:78:90:ab +<<: !include common.yaml diff --git a/tests/components/wake_on_lan/test.rp2040.yaml b/tests/components/wake_on_lan/test.rp2040.yaml index 6a5351b624..dade44d145 100644 --- a/tests/components/wake_on_lan/test.rp2040.yaml +++ b/tests/components/wake_on_lan/test.rp2040.yaml @@ -1,9 +1 @@ -wifi: - ssid: MySSID - password: password1 - -button: - - platform: wake_on_lan - id: wol_1 - name: wol_test_1 - target_mac_address: 12:34:56:78:90:ab +<<: !include common.yaml diff --git a/tests/components/web_server/common.yaml b/tests/components/web_server/common.yaml new file mode 100644 index 0000000000..94388726c3 --- /dev/null +++ b/tests/components/web_server/common.yaml @@ -0,0 +1,7 @@ +wifi: + ssid: MySSID + password: password1 + +web_server: + port: 8080 + version: 2 diff --git a/tests/components/web_server/test.esp32-c3-idf.yaml b/tests/components/web_server/test.esp32-c3-idf.yaml index 94388726c3..dade44d145 100644 --- a/tests/components/web_server/test.esp32-c3-idf.yaml +++ b/tests/components/web_server/test.esp32-c3-idf.yaml @@ -1,7 +1 @@ -wifi: - ssid: MySSID - password: password1 - -web_server: - port: 8080 - version: 2 +<<: !include common.yaml diff --git a/tests/components/web_server/test.esp32-c3.yaml b/tests/components/web_server/test.esp32-c3.yaml index 94388726c3..dade44d145 100644 --- a/tests/components/web_server/test.esp32-c3.yaml +++ b/tests/components/web_server/test.esp32-c3.yaml @@ -1,7 +1 @@ -wifi: - ssid: MySSID - password: password1 - -web_server: - port: 8080 - version: 2 +<<: !include common.yaml diff --git a/tests/components/web_server/test.esp32-idf.yaml b/tests/components/web_server/test.esp32-idf.yaml index 94388726c3..dade44d145 100644 --- a/tests/components/web_server/test.esp32-idf.yaml +++ b/tests/components/web_server/test.esp32-idf.yaml @@ -1,7 +1 @@ -wifi: - ssid: MySSID - password: password1 - -web_server: - port: 8080 - version: 2 +<<: !include common.yaml diff --git a/tests/components/web_server/test.esp32.yaml b/tests/components/web_server/test.esp32.yaml index 94388726c3..dade44d145 100644 --- a/tests/components/web_server/test.esp32.yaml +++ b/tests/components/web_server/test.esp32.yaml @@ -1,7 +1 @@ -wifi: - ssid: MySSID - password: password1 - -web_server: - port: 8080 - version: 2 +<<: !include common.yaml diff --git a/tests/components/web_server/test.esp8266.yaml b/tests/components/web_server/test.esp8266.yaml index 94388726c3..dade44d145 100644 --- a/tests/components/web_server/test.esp8266.yaml +++ b/tests/components/web_server/test.esp8266.yaml @@ -1,7 +1 @@ -wifi: - ssid: MySSID - password: password1 - -web_server: - port: 8080 - version: 2 +<<: !include common.yaml diff --git a/tests/components/wiegand/common.yaml b/tests/components/wiegand/common.yaml new file mode 100644 index 0000000000..4e15a44b89 --- /dev/null +++ b/tests/components/wiegand/common.yaml @@ -0,0 +1,10 @@ +wiegand: + - id: test_wiegand + d0: 5 + d1: 4 + on_key: + - lambda: ESP_LOGI("KEY", "Received key %d", x); + on_tag: + - lambda: ESP_LOGI("TAG", "Received tag %s", x.c_str()); + on_raw: + - lambda: ESP_LOGI("RAW", "Received raw %d bits, value %llx", bits, value); diff --git a/tests/components/wiegand/test.esp32-c3-idf.yaml b/tests/components/wiegand/test.esp32-c3-idf.yaml index 4e15a44b89..dade44d145 100644 --- a/tests/components/wiegand/test.esp32-c3-idf.yaml +++ b/tests/components/wiegand/test.esp32-c3-idf.yaml @@ -1,10 +1 @@ -wiegand: - - id: test_wiegand - d0: 5 - d1: 4 - on_key: - - lambda: ESP_LOGI("KEY", "Received key %d", x); - on_tag: - - lambda: ESP_LOGI("TAG", "Received tag %s", x.c_str()); - on_raw: - - lambda: ESP_LOGI("RAW", "Received raw %d bits, value %llx", bits, value); +<<: !include common.yaml diff --git a/tests/components/wiegand/test.esp32-c3.yaml b/tests/components/wiegand/test.esp32-c3.yaml index 4e15a44b89..dade44d145 100644 --- a/tests/components/wiegand/test.esp32-c3.yaml +++ b/tests/components/wiegand/test.esp32-c3.yaml @@ -1,10 +1 @@ -wiegand: - - id: test_wiegand - d0: 5 - d1: 4 - on_key: - - lambda: ESP_LOGI("KEY", "Received key %d", x); - on_tag: - - lambda: ESP_LOGI("TAG", "Received tag %s", x.c_str()); - on_raw: - - lambda: ESP_LOGI("RAW", "Received raw %d bits, value %llx", bits, value); +<<: !include common.yaml diff --git a/tests/components/wiegand/test.esp32-idf.yaml b/tests/components/wiegand/test.esp32-idf.yaml index 4e15a44b89..dade44d145 100644 --- a/tests/components/wiegand/test.esp32-idf.yaml +++ b/tests/components/wiegand/test.esp32-idf.yaml @@ -1,10 +1 @@ -wiegand: - - id: test_wiegand - d0: 5 - d1: 4 - on_key: - - lambda: ESP_LOGI("KEY", "Received key %d", x); - on_tag: - - lambda: ESP_LOGI("TAG", "Received tag %s", x.c_str()); - on_raw: - - lambda: ESP_LOGI("RAW", "Received raw %d bits, value %llx", bits, value); +<<: !include common.yaml diff --git a/tests/components/wiegand/test.esp32.yaml b/tests/components/wiegand/test.esp32.yaml index 4e15a44b89..dade44d145 100644 --- a/tests/components/wiegand/test.esp32.yaml +++ b/tests/components/wiegand/test.esp32.yaml @@ -1,10 +1 @@ -wiegand: - - id: test_wiegand - d0: 5 - d1: 4 - on_key: - - lambda: ESP_LOGI("KEY", "Received key %d", x); - on_tag: - - lambda: ESP_LOGI("TAG", "Received tag %s", x.c_str()); - on_raw: - - lambda: ESP_LOGI("RAW", "Received raw %d bits, value %llx", bits, value); +<<: !include common.yaml diff --git a/tests/components/wiegand/test.esp8266.yaml b/tests/components/wiegand/test.esp8266.yaml index 4e15a44b89..dade44d145 100644 --- a/tests/components/wiegand/test.esp8266.yaml +++ b/tests/components/wiegand/test.esp8266.yaml @@ -1,10 +1 @@ -wiegand: - - id: test_wiegand - d0: 5 - d1: 4 - on_key: - - lambda: ESP_LOGI("KEY", "Received key %d", x); - on_tag: - - lambda: ESP_LOGI("TAG", "Received tag %s", x.c_str()); - on_raw: - - lambda: ESP_LOGI("RAW", "Received raw %d bits, value %llx", bits, value); +<<: !include common.yaml diff --git a/tests/components/wiegand/test.rp2040.yaml b/tests/components/wiegand/test.rp2040.yaml index 4e15a44b89..dade44d145 100644 --- a/tests/components/wiegand/test.rp2040.yaml +++ b/tests/components/wiegand/test.rp2040.yaml @@ -1,10 +1 @@ -wiegand: - - id: test_wiegand - d0: 5 - d1: 4 - on_key: - - lambda: ESP_LOGI("KEY", "Received key %d", x); - on_tag: - - lambda: ESP_LOGI("TAG", "Received tag %s", x.c_str()); - on_raw: - - lambda: ESP_LOGI("RAW", "Received raw %d bits, value %llx", bits, value); +<<: !include common.yaml diff --git a/tests/components/wifi/common.yaml b/tests/components/wifi/common.yaml new file mode 100644 index 0000000000..003f6347be --- /dev/null +++ b/tests/components/wifi/common.yaml @@ -0,0 +1,9 @@ +esphome: + on_boot: + then: + - wifi.disable + - wifi.enable + +wifi: + ssid: MySSID + password: password1 diff --git a/tests/components/wifi/test.esp32-c3-idf.yaml b/tests/components/wifi/test.esp32-c3-idf.yaml index 003f6347be..dade44d145 100644 --- a/tests/components/wifi/test.esp32-c3-idf.yaml +++ b/tests/components/wifi/test.esp32-c3-idf.yaml @@ -1,9 +1 @@ -esphome: - on_boot: - then: - - wifi.disable - - wifi.enable - -wifi: - ssid: MySSID - password: password1 +<<: !include common.yaml diff --git a/tests/components/wifi/test.esp32-c3.yaml b/tests/components/wifi/test.esp32-c3.yaml index 003f6347be..dade44d145 100644 --- a/tests/components/wifi/test.esp32-c3.yaml +++ b/tests/components/wifi/test.esp32-c3.yaml @@ -1,9 +1 @@ -esphome: - on_boot: - then: - - wifi.disable - - wifi.enable - -wifi: - ssid: MySSID - password: password1 +<<: !include common.yaml diff --git a/tests/components/wifi/test.esp32-idf.yaml b/tests/components/wifi/test.esp32-idf.yaml index 003f6347be..dade44d145 100644 --- a/tests/components/wifi/test.esp32-idf.yaml +++ b/tests/components/wifi/test.esp32-idf.yaml @@ -1,9 +1 @@ -esphome: - on_boot: - then: - - wifi.disable - - wifi.enable - -wifi: - ssid: MySSID - password: password1 +<<: !include common.yaml diff --git a/tests/components/wifi/test.esp32.yaml b/tests/components/wifi/test.esp32.yaml index 003f6347be..dade44d145 100644 --- a/tests/components/wifi/test.esp32.yaml +++ b/tests/components/wifi/test.esp32.yaml @@ -1,9 +1 @@ -esphome: - on_boot: - then: - - wifi.disable - - wifi.enable - -wifi: - ssid: MySSID - password: password1 +<<: !include common.yaml diff --git a/tests/components/wifi/test.esp8266.yaml b/tests/components/wifi/test.esp8266.yaml index 003f6347be..dade44d145 100644 --- a/tests/components/wifi/test.esp8266.yaml +++ b/tests/components/wifi/test.esp8266.yaml @@ -1,9 +1 @@ -esphome: - on_boot: - then: - - wifi.disable - - wifi.enable - -wifi: - ssid: MySSID - password: password1 +<<: !include common.yaml diff --git a/tests/components/wifi/test.rp2040.yaml b/tests/components/wifi/test.rp2040.yaml index 003f6347be..dade44d145 100644 --- a/tests/components/wifi/test.rp2040.yaml +++ b/tests/components/wifi/test.rp2040.yaml @@ -1,9 +1 @@ -esphome: - on_boot: - then: - - wifi.disable - - wifi.enable - -wifi: - ssid: MySSID - password: password1 +<<: !include common.yaml diff --git a/tests/components/wifi_info/common.yaml b/tests/components/wifi_info/common.yaml new file mode 100644 index 0000000000..cf5ea563ba --- /dev/null +++ b/tests/components/wifi_info/common.yaml @@ -0,0 +1,18 @@ +wifi: + ssid: MySSID + password: password1 + +text_sensor: + - platform: wifi_info + scan_results: + name: Scan Results + ip_address: + name: IP Address + ssid: + name: SSID + bssid: + name: BSSID + mac_address: + name: Mac Address + dns_address: + name: DNS ADdress diff --git a/tests/components/wifi_info/test.esp32-c3-idf.yaml b/tests/components/wifi_info/test.esp32-c3-idf.yaml index cf5ea563ba..dade44d145 100644 --- a/tests/components/wifi_info/test.esp32-c3-idf.yaml +++ b/tests/components/wifi_info/test.esp32-c3-idf.yaml @@ -1,18 +1 @@ -wifi: - ssid: MySSID - password: password1 - -text_sensor: - - platform: wifi_info - scan_results: - name: Scan Results - ip_address: - name: IP Address - ssid: - name: SSID - bssid: - name: BSSID - mac_address: - name: Mac Address - dns_address: - name: DNS ADdress +<<: !include common.yaml diff --git a/tests/components/wifi_info/test.esp32-c3.yaml b/tests/components/wifi_info/test.esp32-c3.yaml index cf5ea563ba..dade44d145 100644 --- a/tests/components/wifi_info/test.esp32-c3.yaml +++ b/tests/components/wifi_info/test.esp32-c3.yaml @@ -1,18 +1 @@ -wifi: - ssid: MySSID - password: password1 - -text_sensor: - - platform: wifi_info - scan_results: - name: Scan Results - ip_address: - name: IP Address - ssid: - name: SSID - bssid: - name: BSSID - mac_address: - name: Mac Address - dns_address: - name: DNS ADdress +<<: !include common.yaml diff --git a/tests/components/wifi_info/test.esp32-idf.yaml b/tests/components/wifi_info/test.esp32-idf.yaml index cf5ea563ba..dade44d145 100644 --- a/tests/components/wifi_info/test.esp32-idf.yaml +++ b/tests/components/wifi_info/test.esp32-idf.yaml @@ -1,18 +1 @@ -wifi: - ssid: MySSID - password: password1 - -text_sensor: - - platform: wifi_info - scan_results: - name: Scan Results - ip_address: - name: IP Address - ssid: - name: SSID - bssid: - name: BSSID - mac_address: - name: Mac Address - dns_address: - name: DNS ADdress +<<: !include common.yaml diff --git a/tests/components/wifi_info/test.esp32.yaml b/tests/components/wifi_info/test.esp32.yaml index cf5ea563ba..dade44d145 100644 --- a/tests/components/wifi_info/test.esp32.yaml +++ b/tests/components/wifi_info/test.esp32.yaml @@ -1,18 +1 @@ -wifi: - ssid: MySSID - password: password1 - -text_sensor: - - platform: wifi_info - scan_results: - name: Scan Results - ip_address: - name: IP Address - ssid: - name: SSID - bssid: - name: BSSID - mac_address: - name: Mac Address - dns_address: - name: DNS ADdress +<<: !include common.yaml diff --git a/tests/components/wifi_info/test.esp8266.yaml b/tests/components/wifi_info/test.esp8266.yaml index cf5ea563ba..dade44d145 100644 --- a/tests/components/wifi_info/test.esp8266.yaml +++ b/tests/components/wifi_info/test.esp8266.yaml @@ -1,18 +1 @@ -wifi: - ssid: MySSID - password: password1 - -text_sensor: - - platform: wifi_info - scan_results: - name: Scan Results - ip_address: - name: IP Address - ssid: - name: SSID - bssid: - name: BSSID - mac_address: - name: Mac Address - dns_address: - name: DNS ADdress +<<: !include common.yaml diff --git a/tests/components/wifi_info/test.rp2040.yaml b/tests/components/wifi_info/test.rp2040.yaml index cf5ea563ba..dade44d145 100644 --- a/tests/components/wifi_info/test.rp2040.yaml +++ b/tests/components/wifi_info/test.rp2040.yaml @@ -1,18 +1 @@ -wifi: - ssid: MySSID - password: password1 - -text_sensor: - - platform: wifi_info - scan_results: - name: Scan Results - ip_address: - name: IP Address - ssid: - name: SSID - bssid: - name: BSSID - mac_address: - name: Mac Address - dns_address: - name: DNS ADdress +<<: !include common.yaml diff --git a/tests/components/wifi_signal/common.yaml b/tests/components/wifi_signal/common.yaml new file mode 100644 index 0000000000..58d1cab244 --- /dev/null +++ b/tests/components/wifi_signal/common.yaml @@ -0,0 +1,8 @@ +wifi: + ssid: MySSID + password: password1 + +sensor: + - platform: wifi_signal + name: WiFi Signal Sensor + update_interval: 15s diff --git a/tests/components/wifi_signal/test.esp32-c3-idf.yaml b/tests/components/wifi_signal/test.esp32-c3-idf.yaml index 58d1cab244..dade44d145 100644 --- a/tests/components/wifi_signal/test.esp32-c3-idf.yaml +++ b/tests/components/wifi_signal/test.esp32-c3-idf.yaml @@ -1,8 +1 @@ -wifi: - ssid: MySSID - password: password1 - -sensor: - - platform: wifi_signal - name: WiFi Signal Sensor - update_interval: 15s +<<: !include common.yaml diff --git a/tests/components/wifi_signal/test.esp32-c3.yaml b/tests/components/wifi_signal/test.esp32-c3.yaml index 58d1cab244..dade44d145 100644 --- a/tests/components/wifi_signal/test.esp32-c3.yaml +++ b/tests/components/wifi_signal/test.esp32-c3.yaml @@ -1,8 +1 @@ -wifi: - ssid: MySSID - password: password1 - -sensor: - - platform: wifi_signal - name: WiFi Signal Sensor - update_interval: 15s +<<: !include common.yaml diff --git a/tests/components/wifi_signal/test.esp32-idf.yaml b/tests/components/wifi_signal/test.esp32-idf.yaml index 58d1cab244..dade44d145 100644 --- a/tests/components/wifi_signal/test.esp32-idf.yaml +++ b/tests/components/wifi_signal/test.esp32-idf.yaml @@ -1,8 +1 @@ -wifi: - ssid: MySSID - password: password1 - -sensor: - - platform: wifi_signal - name: WiFi Signal Sensor - update_interval: 15s +<<: !include common.yaml diff --git a/tests/components/wifi_signal/test.esp32.yaml b/tests/components/wifi_signal/test.esp32.yaml index 58d1cab244..dade44d145 100644 --- a/tests/components/wifi_signal/test.esp32.yaml +++ b/tests/components/wifi_signal/test.esp32.yaml @@ -1,8 +1 @@ -wifi: - ssid: MySSID - password: password1 - -sensor: - - platform: wifi_signal - name: WiFi Signal Sensor - update_interval: 15s +<<: !include common.yaml diff --git a/tests/components/wifi_signal/test.esp8266.yaml b/tests/components/wifi_signal/test.esp8266.yaml index 58d1cab244..dade44d145 100644 --- a/tests/components/wifi_signal/test.esp8266.yaml +++ b/tests/components/wifi_signal/test.esp8266.yaml @@ -1,8 +1 @@ -wifi: - ssid: MySSID - password: password1 - -sensor: - - platform: wifi_signal - name: WiFi Signal Sensor - update_interval: 15s +<<: !include common.yaml diff --git a/tests/components/wifi_signal/test.rp2040.yaml b/tests/components/wifi_signal/test.rp2040.yaml index 58d1cab244..dade44d145 100644 --- a/tests/components/wifi_signal/test.rp2040.yaml +++ b/tests/components/wifi_signal/test.rp2040.yaml @@ -1,8 +1 @@ -wifi: - ssid: MySSID - password: password1 - -sensor: - - platform: wifi_signal - name: WiFi Signal Sensor - update_interval: 15s +<<: !include common.yaml diff --git a/tests/components/xiaomi_ble/common.yaml b/tests/components/xiaomi_ble/common.yaml new file mode 100644 index 0000000000..9d10393177 --- /dev/null +++ b/tests/components/xiaomi_ble/common.yaml @@ -0,0 +1,3 @@ +esp32_ble_tracker: + +xiaomi_ble: diff --git a/tests/components/xiaomi_ble/test.esp32-c3-idf.yaml b/tests/components/xiaomi_ble/test.esp32-c3-idf.yaml index 9d10393177..dade44d145 100644 --- a/tests/components/xiaomi_ble/test.esp32-c3-idf.yaml +++ b/tests/components/xiaomi_ble/test.esp32-c3-idf.yaml @@ -1,3 +1 @@ -esp32_ble_tracker: - -xiaomi_ble: +<<: !include common.yaml diff --git a/tests/components/xiaomi_ble/test.esp32-c3.yaml b/tests/components/xiaomi_ble/test.esp32-c3.yaml index 9d10393177..dade44d145 100644 --- a/tests/components/xiaomi_ble/test.esp32-c3.yaml +++ b/tests/components/xiaomi_ble/test.esp32-c3.yaml @@ -1,3 +1 @@ -esp32_ble_tracker: - -xiaomi_ble: +<<: !include common.yaml diff --git a/tests/components/xiaomi_ble/test.esp32-idf.yaml b/tests/components/xiaomi_ble/test.esp32-idf.yaml index 9d10393177..dade44d145 100644 --- a/tests/components/xiaomi_ble/test.esp32-idf.yaml +++ b/tests/components/xiaomi_ble/test.esp32-idf.yaml @@ -1,3 +1 @@ -esp32_ble_tracker: - -xiaomi_ble: +<<: !include common.yaml diff --git a/tests/components/xiaomi_ble/test.esp32.yaml b/tests/components/xiaomi_ble/test.esp32.yaml index 9d10393177..dade44d145 100644 --- a/tests/components/xiaomi_ble/test.esp32.yaml +++ b/tests/components/xiaomi_ble/test.esp32.yaml @@ -1,3 +1 @@ -esp32_ble_tracker: - -xiaomi_ble: +<<: !include common.yaml diff --git a/tests/components/xiaomi_cgd1/common.yaml b/tests/components/xiaomi_cgd1/common.yaml new file mode 100644 index 0000000000..94ed09e8f2 --- /dev/null +++ b/tests/components/xiaomi_cgd1/common.yaml @@ -0,0 +1,12 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_cgd1 + mac_address: A4:C1:38:D1:61:7D + bindkey: c99d2313182473b38001086febf781bd + temperature: + name: Xiaomi CGD1 Temperature + humidity: + name: Xiaomi CGD1 Humidity + battery_level: + name: Xiaomi CGD1 Battery Level diff --git a/tests/components/xiaomi_cgd1/test.esp32-c3-idf.yaml b/tests/components/xiaomi_cgd1/test.esp32-c3-idf.yaml index 94ed09e8f2..dade44d145 100644 --- a/tests/components/xiaomi_cgd1/test.esp32-c3-idf.yaml +++ b/tests/components/xiaomi_cgd1/test.esp32-c3-idf.yaml @@ -1,12 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_cgd1 - mac_address: A4:C1:38:D1:61:7D - bindkey: c99d2313182473b38001086febf781bd - temperature: - name: Xiaomi CGD1 Temperature - humidity: - name: Xiaomi CGD1 Humidity - battery_level: - name: Xiaomi CGD1 Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_cgd1/test.esp32-c3.yaml b/tests/components/xiaomi_cgd1/test.esp32-c3.yaml index 94ed09e8f2..dade44d145 100644 --- a/tests/components/xiaomi_cgd1/test.esp32-c3.yaml +++ b/tests/components/xiaomi_cgd1/test.esp32-c3.yaml @@ -1,12 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_cgd1 - mac_address: A4:C1:38:D1:61:7D - bindkey: c99d2313182473b38001086febf781bd - temperature: - name: Xiaomi CGD1 Temperature - humidity: - name: Xiaomi CGD1 Humidity - battery_level: - name: Xiaomi CGD1 Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_cgd1/test.esp32-idf.yaml b/tests/components/xiaomi_cgd1/test.esp32-idf.yaml index 94ed09e8f2..dade44d145 100644 --- a/tests/components/xiaomi_cgd1/test.esp32-idf.yaml +++ b/tests/components/xiaomi_cgd1/test.esp32-idf.yaml @@ -1,12 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_cgd1 - mac_address: A4:C1:38:D1:61:7D - bindkey: c99d2313182473b38001086febf781bd - temperature: - name: Xiaomi CGD1 Temperature - humidity: - name: Xiaomi CGD1 Humidity - battery_level: - name: Xiaomi CGD1 Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_cgd1/test.esp32.yaml b/tests/components/xiaomi_cgd1/test.esp32.yaml index 94ed09e8f2..dade44d145 100644 --- a/tests/components/xiaomi_cgd1/test.esp32.yaml +++ b/tests/components/xiaomi_cgd1/test.esp32.yaml @@ -1,12 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_cgd1 - mac_address: A4:C1:38:D1:61:7D - bindkey: c99d2313182473b38001086febf781bd - temperature: - name: Xiaomi CGD1 Temperature - humidity: - name: Xiaomi CGD1 Humidity - battery_level: - name: Xiaomi CGD1 Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_cgdk2/common.yaml b/tests/components/xiaomi_cgdk2/common.yaml new file mode 100644 index 0000000000..dddca56222 --- /dev/null +++ b/tests/components/xiaomi_cgdk2/common.yaml @@ -0,0 +1,12 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_cgdk2 + mac_address: A4:C1:38:D1:61:7D + bindkey: c99d2313182473b38001086febf781bd + temperature: + name: Xiaomi CGD1 Temperature + humidity: + name: Xiaomi CGD1 Humidity + battery_level: + name: Xiaomi CGD1 Battery Level diff --git a/tests/components/xiaomi_cgdk2/test.esp32-c3-idf.yaml b/tests/components/xiaomi_cgdk2/test.esp32-c3-idf.yaml index dddca56222..dade44d145 100644 --- a/tests/components/xiaomi_cgdk2/test.esp32-c3-idf.yaml +++ b/tests/components/xiaomi_cgdk2/test.esp32-c3-idf.yaml @@ -1,12 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_cgdk2 - mac_address: A4:C1:38:D1:61:7D - bindkey: c99d2313182473b38001086febf781bd - temperature: - name: Xiaomi CGD1 Temperature - humidity: - name: Xiaomi CGD1 Humidity - battery_level: - name: Xiaomi CGD1 Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_cgdk2/test.esp32-c3.yaml b/tests/components/xiaomi_cgdk2/test.esp32-c3.yaml index dddca56222..dade44d145 100644 --- a/tests/components/xiaomi_cgdk2/test.esp32-c3.yaml +++ b/tests/components/xiaomi_cgdk2/test.esp32-c3.yaml @@ -1,12 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_cgdk2 - mac_address: A4:C1:38:D1:61:7D - bindkey: c99d2313182473b38001086febf781bd - temperature: - name: Xiaomi CGD1 Temperature - humidity: - name: Xiaomi CGD1 Humidity - battery_level: - name: Xiaomi CGD1 Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_cgdk2/test.esp32-idf.yaml b/tests/components/xiaomi_cgdk2/test.esp32-idf.yaml index dddca56222..dade44d145 100644 --- a/tests/components/xiaomi_cgdk2/test.esp32-idf.yaml +++ b/tests/components/xiaomi_cgdk2/test.esp32-idf.yaml @@ -1,12 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_cgdk2 - mac_address: A4:C1:38:D1:61:7D - bindkey: c99d2313182473b38001086febf781bd - temperature: - name: Xiaomi CGD1 Temperature - humidity: - name: Xiaomi CGD1 Humidity - battery_level: - name: Xiaomi CGD1 Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_cgdk2/test.esp32.yaml b/tests/components/xiaomi_cgdk2/test.esp32.yaml index dddca56222..dade44d145 100644 --- a/tests/components/xiaomi_cgdk2/test.esp32.yaml +++ b/tests/components/xiaomi_cgdk2/test.esp32.yaml @@ -1,12 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_cgdk2 - mac_address: A4:C1:38:D1:61:7D - bindkey: c99d2313182473b38001086febf781bd - temperature: - name: Xiaomi CGD1 Temperature - humidity: - name: Xiaomi CGD1 Humidity - battery_level: - name: Xiaomi CGD1 Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_cgg1/common.yaml b/tests/components/xiaomi_cgg1/common.yaml new file mode 100644 index 0000000000..170aebfbde --- /dev/null +++ b/tests/components/xiaomi_cgg1/common.yaml @@ -0,0 +1,12 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_cgg1 + mac_address: A4:C1:38:D1:61:7D + bindkey: c99d2313182473b38001086febf781bd + temperature: + name: Xiaomi CGD1 Temperature + humidity: + name: Xiaomi CGD1 Humidity + battery_level: + name: Xiaomi CGD1 Battery Level diff --git a/tests/components/xiaomi_cgg1/test.esp32-c3-idf.yaml b/tests/components/xiaomi_cgg1/test.esp32-c3-idf.yaml index 170aebfbde..dade44d145 100644 --- a/tests/components/xiaomi_cgg1/test.esp32-c3-idf.yaml +++ b/tests/components/xiaomi_cgg1/test.esp32-c3-idf.yaml @@ -1,12 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_cgg1 - mac_address: A4:C1:38:D1:61:7D - bindkey: c99d2313182473b38001086febf781bd - temperature: - name: Xiaomi CGD1 Temperature - humidity: - name: Xiaomi CGD1 Humidity - battery_level: - name: Xiaomi CGD1 Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_cgg1/test.esp32-c3.yaml b/tests/components/xiaomi_cgg1/test.esp32-c3.yaml index 170aebfbde..dade44d145 100644 --- a/tests/components/xiaomi_cgg1/test.esp32-c3.yaml +++ b/tests/components/xiaomi_cgg1/test.esp32-c3.yaml @@ -1,12 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_cgg1 - mac_address: A4:C1:38:D1:61:7D - bindkey: c99d2313182473b38001086febf781bd - temperature: - name: Xiaomi CGD1 Temperature - humidity: - name: Xiaomi CGD1 Humidity - battery_level: - name: Xiaomi CGD1 Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_cgg1/test.esp32-idf.yaml b/tests/components/xiaomi_cgg1/test.esp32-idf.yaml index 170aebfbde..dade44d145 100644 --- a/tests/components/xiaomi_cgg1/test.esp32-idf.yaml +++ b/tests/components/xiaomi_cgg1/test.esp32-idf.yaml @@ -1,12 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_cgg1 - mac_address: A4:C1:38:D1:61:7D - bindkey: c99d2313182473b38001086febf781bd - temperature: - name: Xiaomi CGD1 Temperature - humidity: - name: Xiaomi CGD1 Humidity - battery_level: - name: Xiaomi CGD1 Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_cgg1/test.esp32.yaml b/tests/components/xiaomi_cgg1/test.esp32.yaml index 170aebfbde..dade44d145 100644 --- a/tests/components/xiaomi_cgg1/test.esp32.yaml +++ b/tests/components/xiaomi_cgg1/test.esp32.yaml @@ -1,12 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_cgg1 - mac_address: A4:C1:38:D1:61:7D - bindkey: c99d2313182473b38001086febf781bd - temperature: - name: Xiaomi CGD1 Temperature - humidity: - name: Xiaomi CGD1 Humidity - battery_level: - name: Xiaomi CGD1 Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_cgpr1/common.yaml b/tests/components/xiaomi_cgpr1/common.yaml new file mode 100644 index 0000000000..48082a886c --- /dev/null +++ b/tests/components/xiaomi_cgpr1/common.yaml @@ -0,0 +1,13 @@ +esp32_ble_tracker: + +binary_sensor: + - platform: xiaomi_cgpr1 + name: CGPR1 Motion + mac_address: "12:34:56:12:34:56" + bindkey: 48403ebe2d385db8d0c187f81e62cb64 + battery_level: + name: CGPR1 battery Level + idle_time: + name: CGPR1 Idle Time + illuminance: + name: CGPR1 Illuminance diff --git a/tests/components/xiaomi_cgpr1/test.esp32-c3-idf.yaml b/tests/components/xiaomi_cgpr1/test.esp32-c3-idf.yaml index 48082a886c..dade44d145 100644 --- a/tests/components/xiaomi_cgpr1/test.esp32-c3-idf.yaml +++ b/tests/components/xiaomi_cgpr1/test.esp32-c3-idf.yaml @@ -1,13 +1 @@ -esp32_ble_tracker: - -binary_sensor: - - platform: xiaomi_cgpr1 - name: CGPR1 Motion - mac_address: "12:34:56:12:34:56" - bindkey: 48403ebe2d385db8d0c187f81e62cb64 - battery_level: - name: CGPR1 battery Level - idle_time: - name: CGPR1 Idle Time - illuminance: - name: CGPR1 Illuminance +<<: !include common.yaml diff --git a/tests/components/xiaomi_cgpr1/test.esp32-c3.yaml b/tests/components/xiaomi_cgpr1/test.esp32-c3.yaml index 48082a886c..dade44d145 100644 --- a/tests/components/xiaomi_cgpr1/test.esp32-c3.yaml +++ b/tests/components/xiaomi_cgpr1/test.esp32-c3.yaml @@ -1,13 +1 @@ -esp32_ble_tracker: - -binary_sensor: - - platform: xiaomi_cgpr1 - name: CGPR1 Motion - mac_address: "12:34:56:12:34:56" - bindkey: 48403ebe2d385db8d0c187f81e62cb64 - battery_level: - name: CGPR1 battery Level - idle_time: - name: CGPR1 Idle Time - illuminance: - name: CGPR1 Illuminance +<<: !include common.yaml diff --git a/tests/components/xiaomi_cgpr1/test.esp32-idf.yaml b/tests/components/xiaomi_cgpr1/test.esp32-idf.yaml index 48082a886c..dade44d145 100644 --- a/tests/components/xiaomi_cgpr1/test.esp32-idf.yaml +++ b/tests/components/xiaomi_cgpr1/test.esp32-idf.yaml @@ -1,13 +1 @@ -esp32_ble_tracker: - -binary_sensor: - - platform: xiaomi_cgpr1 - name: CGPR1 Motion - mac_address: "12:34:56:12:34:56" - bindkey: 48403ebe2d385db8d0c187f81e62cb64 - battery_level: - name: CGPR1 battery Level - idle_time: - name: CGPR1 Idle Time - illuminance: - name: CGPR1 Illuminance +<<: !include common.yaml diff --git a/tests/components/xiaomi_cgpr1/test.esp32.yaml b/tests/components/xiaomi_cgpr1/test.esp32.yaml index 48082a886c..dade44d145 100644 --- a/tests/components/xiaomi_cgpr1/test.esp32.yaml +++ b/tests/components/xiaomi_cgpr1/test.esp32.yaml @@ -1,13 +1 @@ -esp32_ble_tracker: - -binary_sensor: - - platform: xiaomi_cgpr1 - name: CGPR1 Motion - mac_address: "12:34:56:12:34:56" - bindkey: 48403ebe2d385db8d0c187f81e62cb64 - battery_level: - name: CGPR1 battery Level - idle_time: - name: CGPR1 Idle Time - illuminance: - name: CGPR1 Illuminance +<<: !include common.yaml diff --git a/tests/components/xiaomi_gcls002/common.yaml b/tests/components/xiaomi_gcls002/common.yaml new file mode 100644 index 0000000000..32990708cc --- /dev/null +++ b/tests/components/xiaomi_gcls002/common.yaml @@ -0,0 +1,13 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_gcls002 + mac_address: 94:2B:FF:5C:91:61 + temperature: + name: GCLS02 Temperature + moisture: + name: GCLS02 Moisture + conductivity: + name: GCLS02 Soil Conductivity + illuminance: + name: GCLS02 Illuminance diff --git a/tests/components/xiaomi_gcls002/test.esp32-c3-idf.yaml b/tests/components/xiaomi_gcls002/test.esp32-c3-idf.yaml index 32990708cc..dade44d145 100644 --- a/tests/components/xiaomi_gcls002/test.esp32-c3-idf.yaml +++ b/tests/components/xiaomi_gcls002/test.esp32-c3-idf.yaml @@ -1,13 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_gcls002 - mac_address: 94:2B:FF:5C:91:61 - temperature: - name: GCLS02 Temperature - moisture: - name: GCLS02 Moisture - conductivity: - name: GCLS02 Soil Conductivity - illuminance: - name: GCLS02 Illuminance +<<: !include common.yaml diff --git a/tests/components/xiaomi_gcls002/test.esp32-c3.yaml b/tests/components/xiaomi_gcls002/test.esp32-c3.yaml index 32990708cc..dade44d145 100644 --- a/tests/components/xiaomi_gcls002/test.esp32-c3.yaml +++ b/tests/components/xiaomi_gcls002/test.esp32-c3.yaml @@ -1,13 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_gcls002 - mac_address: 94:2B:FF:5C:91:61 - temperature: - name: GCLS02 Temperature - moisture: - name: GCLS02 Moisture - conductivity: - name: GCLS02 Soil Conductivity - illuminance: - name: GCLS02 Illuminance +<<: !include common.yaml diff --git a/tests/components/xiaomi_gcls002/test.esp32-idf.yaml b/tests/components/xiaomi_gcls002/test.esp32-idf.yaml index 32990708cc..dade44d145 100644 --- a/tests/components/xiaomi_gcls002/test.esp32-idf.yaml +++ b/tests/components/xiaomi_gcls002/test.esp32-idf.yaml @@ -1,13 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_gcls002 - mac_address: 94:2B:FF:5C:91:61 - temperature: - name: GCLS02 Temperature - moisture: - name: GCLS02 Moisture - conductivity: - name: GCLS02 Soil Conductivity - illuminance: - name: GCLS02 Illuminance +<<: !include common.yaml diff --git a/tests/components/xiaomi_gcls002/test.esp32.yaml b/tests/components/xiaomi_gcls002/test.esp32.yaml index 32990708cc..dade44d145 100644 --- a/tests/components/xiaomi_gcls002/test.esp32.yaml +++ b/tests/components/xiaomi_gcls002/test.esp32.yaml @@ -1,13 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_gcls002 - mac_address: 94:2B:FF:5C:91:61 - temperature: - name: GCLS02 Temperature - moisture: - name: GCLS02 Moisture - conductivity: - name: GCLS02 Soil Conductivity - illuminance: - name: GCLS02 Illuminance +<<: !include common.yaml diff --git a/tests/components/xiaomi_hhccjcy01/common.yaml b/tests/components/xiaomi_hhccjcy01/common.yaml new file mode 100644 index 0000000000..0def909488 --- /dev/null +++ b/tests/components/xiaomi_hhccjcy01/common.yaml @@ -0,0 +1,15 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_hhccjcy01 + mac_address: 94:2B:FF:5C:91:61 + temperature: + name: Xiaomi HHCCJCY01 Temperature + moisture: + name: Xiaomi HHCCJCY01 Moisture + illuminance: + name: Xiaomi HHCCJCY01 Illuminance + conductivity: + name: Xiaomi HHCCJCY01 Soil Conductivity + battery_level: + name: Xiaomi HHCCJCY01 Battery Level diff --git a/tests/components/xiaomi_hhccjcy01/test.esp32-c3-idf.yaml b/tests/components/xiaomi_hhccjcy01/test.esp32-c3-idf.yaml index 0def909488..dade44d145 100644 --- a/tests/components/xiaomi_hhccjcy01/test.esp32-c3-idf.yaml +++ b/tests/components/xiaomi_hhccjcy01/test.esp32-c3-idf.yaml @@ -1,15 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_hhccjcy01 - mac_address: 94:2B:FF:5C:91:61 - temperature: - name: Xiaomi HHCCJCY01 Temperature - moisture: - name: Xiaomi HHCCJCY01 Moisture - illuminance: - name: Xiaomi HHCCJCY01 Illuminance - conductivity: - name: Xiaomi HHCCJCY01 Soil Conductivity - battery_level: - name: Xiaomi HHCCJCY01 Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_hhccjcy01/test.esp32-c3.yaml b/tests/components/xiaomi_hhccjcy01/test.esp32-c3.yaml index 0def909488..dade44d145 100644 --- a/tests/components/xiaomi_hhccjcy01/test.esp32-c3.yaml +++ b/tests/components/xiaomi_hhccjcy01/test.esp32-c3.yaml @@ -1,15 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_hhccjcy01 - mac_address: 94:2B:FF:5C:91:61 - temperature: - name: Xiaomi HHCCJCY01 Temperature - moisture: - name: Xiaomi HHCCJCY01 Moisture - illuminance: - name: Xiaomi HHCCJCY01 Illuminance - conductivity: - name: Xiaomi HHCCJCY01 Soil Conductivity - battery_level: - name: Xiaomi HHCCJCY01 Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_hhccjcy01/test.esp32-idf.yaml b/tests/components/xiaomi_hhccjcy01/test.esp32-idf.yaml index 0def909488..dade44d145 100644 --- a/tests/components/xiaomi_hhccjcy01/test.esp32-idf.yaml +++ b/tests/components/xiaomi_hhccjcy01/test.esp32-idf.yaml @@ -1,15 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_hhccjcy01 - mac_address: 94:2B:FF:5C:91:61 - temperature: - name: Xiaomi HHCCJCY01 Temperature - moisture: - name: Xiaomi HHCCJCY01 Moisture - illuminance: - name: Xiaomi HHCCJCY01 Illuminance - conductivity: - name: Xiaomi HHCCJCY01 Soil Conductivity - battery_level: - name: Xiaomi HHCCJCY01 Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_hhccjcy01/test.esp32.yaml b/tests/components/xiaomi_hhccjcy01/test.esp32.yaml index 0def909488..dade44d145 100644 --- a/tests/components/xiaomi_hhccjcy01/test.esp32.yaml +++ b/tests/components/xiaomi_hhccjcy01/test.esp32.yaml @@ -1,15 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_hhccjcy01 - mac_address: 94:2B:FF:5C:91:61 - temperature: - name: Xiaomi HHCCJCY01 Temperature - moisture: - name: Xiaomi HHCCJCY01 Moisture - illuminance: - name: Xiaomi HHCCJCY01 Illuminance - conductivity: - name: Xiaomi HHCCJCY01 Soil Conductivity - battery_level: - name: Xiaomi HHCCJCY01 Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_hhccpot002/common.yaml b/tests/components/xiaomi_hhccpot002/common.yaml new file mode 100644 index 0000000000..2e5fa14620 --- /dev/null +++ b/tests/components/xiaomi_hhccpot002/common.yaml @@ -0,0 +1,9 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_hhccpot002 + mac_address: 94:2B:FF:5C:91:61 + moisture: + name: HHCCPOT002 Moisture + conductivity: + name: HHCCPOT002 Soil Conductivity diff --git a/tests/components/xiaomi_hhccpot002/test.esp32-c3-idf.yaml b/tests/components/xiaomi_hhccpot002/test.esp32-c3-idf.yaml index 2e5fa14620..dade44d145 100644 --- a/tests/components/xiaomi_hhccpot002/test.esp32-c3-idf.yaml +++ b/tests/components/xiaomi_hhccpot002/test.esp32-c3-idf.yaml @@ -1,9 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_hhccpot002 - mac_address: 94:2B:FF:5C:91:61 - moisture: - name: HHCCPOT002 Moisture - conductivity: - name: HHCCPOT002 Soil Conductivity +<<: !include common.yaml diff --git a/tests/components/xiaomi_hhccpot002/test.esp32-c3.yaml b/tests/components/xiaomi_hhccpot002/test.esp32-c3.yaml index 2e5fa14620..dade44d145 100644 --- a/tests/components/xiaomi_hhccpot002/test.esp32-c3.yaml +++ b/tests/components/xiaomi_hhccpot002/test.esp32-c3.yaml @@ -1,9 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_hhccpot002 - mac_address: 94:2B:FF:5C:91:61 - moisture: - name: HHCCPOT002 Moisture - conductivity: - name: HHCCPOT002 Soil Conductivity +<<: !include common.yaml diff --git a/tests/components/xiaomi_hhccpot002/test.esp32-idf.yaml b/tests/components/xiaomi_hhccpot002/test.esp32-idf.yaml index 2e5fa14620..dade44d145 100644 --- a/tests/components/xiaomi_hhccpot002/test.esp32-idf.yaml +++ b/tests/components/xiaomi_hhccpot002/test.esp32-idf.yaml @@ -1,9 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_hhccpot002 - mac_address: 94:2B:FF:5C:91:61 - moisture: - name: HHCCPOT002 Moisture - conductivity: - name: HHCCPOT002 Soil Conductivity +<<: !include common.yaml diff --git a/tests/components/xiaomi_hhccpot002/test.esp32.yaml b/tests/components/xiaomi_hhccpot002/test.esp32.yaml index 2e5fa14620..dade44d145 100644 --- a/tests/components/xiaomi_hhccpot002/test.esp32.yaml +++ b/tests/components/xiaomi_hhccpot002/test.esp32.yaml @@ -1,9 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_hhccpot002 - mac_address: 94:2B:FF:5C:91:61 - moisture: - name: HHCCPOT002 Moisture - conductivity: - name: HHCCPOT002 Soil Conductivity +<<: !include common.yaml diff --git a/tests/components/xiaomi_jqjcy01ym/common.yaml b/tests/components/xiaomi_jqjcy01ym/common.yaml new file mode 100644 index 0000000000..54c4b33dcd --- /dev/null +++ b/tests/components/xiaomi_jqjcy01ym/common.yaml @@ -0,0 +1,13 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_jqjcy01ym + mac_address: 7A:80:8E:19:36:BA + temperature: + name: JQJCY01YM Temperature + humidity: + name: JQJCY01YM Humidity + formaldehyde: + name: JQJCY01YM Formaldehyde + battery_level: + name: JQJCY01YM Battery Level diff --git a/tests/components/xiaomi_jqjcy01ym/test.esp32-c3-idf.yaml b/tests/components/xiaomi_jqjcy01ym/test.esp32-c3-idf.yaml index 54c4b33dcd..dade44d145 100644 --- a/tests/components/xiaomi_jqjcy01ym/test.esp32-c3-idf.yaml +++ b/tests/components/xiaomi_jqjcy01ym/test.esp32-c3-idf.yaml @@ -1,13 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_jqjcy01ym - mac_address: 7A:80:8E:19:36:BA - temperature: - name: JQJCY01YM Temperature - humidity: - name: JQJCY01YM Humidity - formaldehyde: - name: JQJCY01YM Formaldehyde - battery_level: - name: JQJCY01YM Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_jqjcy01ym/test.esp32-c3.yaml b/tests/components/xiaomi_jqjcy01ym/test.esp32-c3.yaml index 54c4b33dcd..dade44d145 100644 --- a/tests/components/xiaomi_jqjcy01ym/test.esp32-c3.yaml +++ b/tests/components/xiaomi_jqjcy01ym/test.esp32-c3.yaml @@ -1,13 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_jqjcy01ym - mac_address: 7A:80:8E:19:36:BA - temperature: - name: JQJCY01YM Temperature - humidity: - name: JQJCY01YM Humidity - formaldehyde: - name: JQJCY01YM Formaldehyde - battery_level: - name: JQJCY01YM Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_jqjcy01ym/test.esp32-idf.yaml b/tests/components/xiaomi_jqjcy01ym/test.esp32-idf.yaml index 54c4b33dcd..dade44d145 100644 --- a/tests/components/xiaomi_jqjcy01ym/test.esp32-idf.yaml +++ b/tests/components/xiaomi_jqjcy01ym/test.esp32-idf.yaml @@ -1,13 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_jqjcy01ym - mac_address: 7A:80:8E:19:36:BA - temperature: - name: JQJCY01YM Temperature - humidity: - name: JQJCY01YM Humidity - formaldehyde: - name: JQJCY01YM Formaldehyde - battery_level: - name: JQJCY01YM Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_jqjcy01ym/test.esp32.yaml b/tests/components/xiaomi_jqjcy01ym/test.esp32.yaml index 54c4b33dcd..dade44d145 100644 --- a/tests/components/xiaomi_jqjcy01ym/test.esp32.yaml +++ b/tests/components/xiaomi_jqjcy01ym/test.esp32.yaml @@ -1,13 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_jqjcy01ym - mac_address: 7A:80:8E:19:36:BA - temperature: - name: JQJCY01YM Temperature - humidity: - name: JQJCY01YM Humidity - formaldehyde: - name: JQJCY01YM Formaldehyde - battery_level: - name: JQJCY01YM Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_lywsd02/common.yaml b/tests/components/xiaomi_lywsd02/common.yaml new file mode 100644 index 0000000000..3e40ab8d70 --- /dev/null +++ b/tests/components/xiaomi_lywsd02/common.yaml @@ -0,0 +1,11 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_lywsd02 + mac_address: 3F:5B:7D:82:58:4E + temperature: + name: Xiaomi LYWSD02 Temperature + humidity: + name: Xiaomi LYWSD02 Humidity + battery_level: + name: Xiaomi LYWSD02 Battery Level diff --git a/tests/components/xiaomi_lywsd02/test.esp32-c3-idf.yaml b/tests/components/xiaomi_lywsd02/test.esp32-c3-idf.yaml index 3e40ab8d70..dade44d145 100644 --- a/tests/components/xiaomi_lywsd02/test.esp32-c3-idf.yaml +++ b/tests/components/xiaomi_lywsd02/test.esp32-c3-idf.yaml @@ -1,11 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_lywsd02 - mac_address: 3F:5B:7D:82:58:4E - temperature: - name: Xiaomi LYWSD02 Temperature - humidity: - name: Xiaomi LYWSD02 Humidity - battery_level: - name: Xiaomi LYWSD02 Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_lywsd02/test.esp32-c3.yaml b/tests/components/xiaomi_lywsd02/test.esp32-c3.yaml index 3e40ab8d70..dade44d145 100644 --- a/tests/components/xiaomi_lywsd02/test.esp32-c3.yaml +++ b/tests/components/xiaomi_lywsd02/test.esp32-c3.yaml @@ -1,11 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_lywsd02 - mac_address: 3F:5B:7D:82:58:4E - temperature: - name: Xiaomi LYWSD02 Temperature - humidity: - name: Xiaomi LYWSD02 Humidity - battery_level: - name: Xiaomi LYWSD02 Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_lywsd02/test.esp32-idf.yaml b/tests/components/xiaomi_lywsd02/test.esp32-idf.yaml index 3e40ab8d70..dade44d145 100644 --- a/tests/components/xiaomi_lywsd02/test.esp32-idf.yaml +++ b/tests/components/xiaomi_lywsd02/test.esp32-idf.yaml @@ -1,11 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_lywsd02 - mac_address: 3F:5B:7D:82:58:4E - temperature: - name: Xiaomi LYWSD02 Temperature - humidity: - name: Xiaomi LYWSD02 Humidity - battery_level: - name: Xiaomi LYWSD02 Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_lywsd02/test.esp32.yaml b/tests/components/xiaomi_lywsd02/test.esp32.yaml index 3e40ab8d70..dade44d145 100644 --- a/tests/components/xiaomi_lywsd02/test.esp32.yaml +++ b/tests/components/xiaomi_lywsd02/test.esp32.yaml @@ -1,11 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_lywsd02 - mac_address: 3F:5B:7D:82:58:4E - temperature: - name: Xiaomi LYWSD02 Temperature - humidity: - name: Xiaomi LYWSD02 Humidity - battery_level: - name: Xiaomi LYWSD02 Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_lywsd03mmc/common.yaml b/tests/components/xiaomi_lywsd03mmc/common.yaml new file mode 100644 index 0000000000..d10a859c56 --- /dev/null +++ b/tests/components/xiaomi_lywsd03mmc/common.yaml @@ -0,0 +1,12 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_lywsd03mmc + mac_address: A4:C1:38:4E:16:78 + bindkey: e9efaa6873f9f9c87a5e75a5f814801c + temperature: + name: Xiaomi LYWSD03MMC Temperature + humidity: + name: Xiaomi LYWSD03MMC Humidity + battery_level: + name: Xiaomi LYWSD03MMC Battery Level diff --git a/tests/components/xiaomi_lywsd03mmc/test.esp32-c3-idf.yaml b/tests/components/xiaomi_lywsd03mmc/test.esp32-c3-idf.yaml index d10a859c56..dade44d145 100644 --- a/tests/components/xiaomi_lywsd03mmc/test.esp32-c3-idf.yaml +++ b/tests/components/xiaomi_lywsd03mmc/test.esp32-c3-idf.yaml @@ -1,12 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_lywsd03mmc - mac_address: A4:C1:38:4E:16:78 - bindkey: e9efaa6873f9f9c87a5e75a5f814801c - temperature: - name: Xiaomi LYWSD03MMC Temperature - humidity: - name: Xiaomi LYWSD03MMC Humidity - battery_level: - name: Xiaomi LYWSD03MMC Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_lywsd03mmc/test.esp32-c3.yaml b/tests/components/xiaomi_lywsd03mmc/test.esp32-c3.yaml index d10a859c56..dade44d145 100644 --- a/tests/components/xiaomi_lywsd03mmc/test.esp32-c3.yaml +++ b/tests/components/xiaomi_lywsd03mmc/test.esp32-c3.yaml @@ -1,12 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_lywsd03mmc - mac_address: A4:C1:38:4E:16:78 - bindkey: e9efaa6873f9f9c87a5e75a5f814801c - temperature: - name: Xiaomi LYWSD03MMC Temperature - humidity: - name: Xiaomi LYWSD03MMC Humidity - battery_level: - name: Xiaomi LYWSD03MMC Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_lywsd03mmc/test.esp32-idf.yaml b/tests/components/xiaomi_lywsd03mmc/test.esp32-idf.yaml index d10a859c56..dade44d145 100644 --- a/tests/components/xiaomi_lywsd03mmc/test.esp32-idf.yaml +++ b/tests/components/xiaomi_lywsd03mmc/test.esp32-idf.yaml @@ -1,12 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_lywsd03mmc - mac_address: A4:C1:38:4E:16:78 - bindkey: e9efaa6873f9f9c87a5e75a5f814801c - temperature: - name: Xiaomi LYWSD03MMC Temperature - humidity: - name: Xiaomi LYWSD03MMC Humidity - battery_level: - name: Xiaomi LYWSD03MMC Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_lywsd03mmc/test.esp32.yaml b/tests/components/xiaomi_lywsd03mmc/test.esp32.yaml index d10a859c56..dade44d145 100644 --- a/tests/components/xiaomi_lywsd03mmc/test.esp32.yaml +++ b/tests/components/xiaomi_lywsd03mmc/test.esp32.yaml @@ -1,12 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_lywsd03mmc - mac_address: A4:C1:38:4E:16:78 - bindkey: e9efaa6873f9f9c87a5e75a5f814801c - temperature: - name: Xiaomi LYWSD03MMC Temperature - humidity: - name: Xiaomi LYWSD03MMC Humidity - battery_level: - name: Xiaomi LYWSD03MMC Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_lywsdcgq/common.yaml b/tests/components/xiaomi_lywsdcgq/common.yaml new file mode 100644 index 0000000000..d8422b4c0c --- /dev/null +++ b/tests/components/xiaomi_lywsdcgq/common.yaml @@ -0,0 +1,11 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_lywsdcgq + mac_address: 7A:80:8E:19:36:BA + temperature: + name: Xiaomi LYWSDCGQ Temperature + humidity: + name: Xiaomi LYWSDCGQ Humidity + battery_level: + name: Xiaomi LYWSDCGQ Battery Level diff --git a/tests/components/xiaomi_lywsdcgq/test.esp32-c3-idf.yaml b/tests/components/xiaomi_lywsdcgq/test.esp32-c3-idf.yaml index d8422b4c0c..dade44d145 100644 --- a/tests/components/xiaomi_lywsdcgq/test.esp32-c3-idf.yaml +++ b/tests/components/xiaomi_lywsdcgq/test.esp32-c3-idf.yaml @@ -1,11 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_lywsdcgq - mac_address: 7A:80:8E:19:36:BA - temperature: - name: Xiaomi LYWSDCGQ Temperature - humidity: - name: Xiaomi LYWSDCGQ Humidity - battery_level: - name: Xiaomi LYWSDCGQ Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_lywsdcgq/test.esp32-c3.yaml b/tests/components/xiaomi_lywsdcgq/test.esp32-c3.yaml index d8422b4c0c..dade44d145 100644 --- a/tests/components/xiaomi_lywsdcgq/test.esp32-c3.yaml +++ b/tests/components/xiaomi_lywsdcgq/test.esp32-c3.yaml @@ -1,11 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_lywsdcgq - mac_address: 7A:80:8E:19:36:BA - temperature: - name: Xiaomi LYWSDCGQ Temperature - humidity: - name: Xiaomi LYWSDCGQ Humidity - battery_level: - name: Xiaomi LYWSDCGQ Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_lywsdcgq/test.esp32-idf.yaml b/tests/components/xiaomi_lywsdcgq/test.esp32-idf.yaml index d8422b4c0c..dade44d145 100644 --- a/tests/components/xiaomi_lywsdcgq/test.esp32-idf.yaml +++ b/tests/components/xiaomi_lywsdcgq/test.esp32-idf.yaml @@ -1,11 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_lywsdcgq - mac_address: 7A:80:8E:19:36:BA - temperature: - name: Xiaomi LYWSDCGQ Temperature - humidity: - name: Xiaomi LYWSDCGQ Humidity - battery_level: - name: Xiaomi LYWSDCGQ Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_lywsdcgq/test.esp32.yaml b/tests/components/xiaomi_lywsdcgq/test.esp32.yaml index d8422b4c0c..dade44d145 100644 --- a/tests/components/xiaomi_lywsdcgq/test.esp32.yaml +++ b/tests/components/xiaomi_lywsdcgq/test.esp32.yaml @@ -1,11 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_lywsdcgq - mac_address: 7A:80:8E:19:36:BA - temperature: - name: Xiaomi LYWSDCGQ Temperature - humidity: - name: Xiaomi LYWSDCGQ Humidity - battery_level: - name: Xiaomi LYWSDCGQ Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_mhoc303/common.yaml b/tests/components/xiaomi_mhoc303/common.yaml new file mode 100644 index 0000000000..e4353d3c6a --- /dev/null +++ b/tests/components/xiaomi_mhoc303/common.yaml @@ -0,0 +1,11 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_mhoc303 + mac_address: E7:50:59:32:A0:1C + temperature: + name: MHO-C303 Temperature + humidity: + name: MHO-C303 Humidity + battery_level: + name: MHO-C303 Battery Level diff --git a/tests/components/xiaomi_mhoc303/test.esp32-c3-idf.yaml b/tests/components/xiaomi_mhoc303/test.esp32-c3-idf.yaml index e4353d3c6a..dade44d145 100644 --- a/tests/components/xiaomi_mhoc303/test.esp32-c3-idf.yaml +++ b/tests/components/xiaomi_mhoc303/test.esp32-c3-idf.yaml @@ -1,11 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_mhoc303 - mac_address: E7:50:59:32:A0:1C - temperature: - name: MHO-C303 Temperature - humidity: - name: MHO-C303 Humidity - battery_level: - name: MHO-C303 Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_mhoc303/test.esp32-c3.yaml b/tests/components/xiaomi_mhoc303/test.esp32-c3.yaml index e4353d3c6a..dade44d145 100644 --- a/tests/components/xiaomi_mhoc303/test.esp32-c3.yaml +++ b/tests/components/xiaomi_mhoc303/test.esp32-c3.yaml @@ -1,11 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_mhoc303 - mac_address: E7:50:59:32:A0:1C - temperature: - name: MHO-C303 Temperature - humidity: - name: MHO-C303 Humidity - battery_level: - name: MHO-C303 Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_mhoc303/test.esp32-idf.yaml b/tests/components/xiaomi_mhoc303/test.esp32-idf.yaml index e4353d3c6a..dade44d145 100644 --- a/tests/components/xiaomi_mhoc303/test.esp32-idf.yaml +++ b/tests/components/xiaomi_mhoc303/test.esp32-idf.yaml @@ -1,11 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_mhoc303 - mac_address: E7:50:59:32:A0:1C - temperature: - name: MHO-C303 Temperature - humidity: - name: MHO-C303 Humidity - battery_level: - name: MHO-C303 Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_mhoc303/test.esp32.yaml b/tests/components/xiaomi_mhoc303/test.esp32.yaml index e4353d3c6a..dade44d145 100644 --- a/tests/components/xiaomi_mhoc303/test.esp32.yaml +++ b/tests/components/xiaomi_mhoc303/test.esp32.yaml @@ -1,11 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_mhoc303 - mac_address: E7:50:59:32:A0:1C - temperature: - name: MHO-C303 Temperature - humidity: - name: MHO-C303 Humidity - battery_level: - name: MHO-C303 Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_mhoc401/common.yaml b/tests/components/xiaomi_mhoc401/common.yaml new file mode 100644 index 0000000000..ae378f5604 --- /dev/null +++ b/tests/components/xiaomi_mhoc401/common.yaml @@ -0,0 +1,12 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_mhoc401 + mac_address: E7:50:59:32:A0:1C + bindkey: "eef418daf699a0c188f3bfd17e4565d9" + temperature: + name: MHO-C303 Temperature + humidity: + name: MHO-C303 Humidity + battery_level: + name: MHO-C303 Battery Level diff --git a/tests/components/xiaomi_mhoc401/test.esp32-c3-idf.yaml b/tests/components/xiaomi_mhoc401/test.esp32-c3-idf.yaml index ae378f5604..dade44d145 100644 --- a/tests/components/xiaomi_mhoc401/test.esp32-c3-idf.yaml +++ b/tests/components/xiaomi_mhoc401/test.esp32-c3-idf.yaml @@ -1,12 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_mhoc401 - mac_address: E7:50:59:32:A0:1C - bindkey: "eef418daf699a0c188f3bfd17e4565d9" - temperature: - name: MHO-C303 Temperature - humidity: - name: MHO-C303 Humidity - battery_level: - name: MHO-C303 Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_mhoc401/test.esp32-c3.yaml b/tests/components/xiaomi_mhoc401/test.esp32-c3.yaml index ae378f5604..dade44d145 100644 --- a/tests/components/xiaomi_mhoc401/test.esp32-c3.yaml +++ b/tests/components/xiaomi_mhoc401/test.esp32-c3.yaml @@ -1,12 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_mhoc401 - mac_address: E7:50:59:32:A0:1C - bindkey: "eef418daf699a0c188f3bfd17e4565d9" - temperature: - name: MHO-C303 Temperature - humidity: - name: MHO-C303 Humidity - battery_level: - name: MHO-C303 Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_mhoc401/test.esp32-idf.yaml b/tests/components/xiaomi_mhoc401/test.esp32-idf.yaml index ae378f5604..dade44d145 100644 --- a/tests/components/xiaomi_mhoc401/test.esp32-idf.yaml +++ b/tests/components/xiaomi_mhoc401/test.esp32-idf.yaml @@ -1,12 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_mhoc401 - mac_address: E7:50:59:32:A0:1C - bindkey: "eef418daf699a0c188f3bfd17e4565d9" - temperature: - name: MHO-C303 Temperature - humidity: - name: MHO-C303 Humidity - battery_level: - name: MHO-C303 Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_mhoc401/test.esp32.yaml b/tests/components/xiaomi_mhoc401/test.esp32.yaml index ae378f5604..dade44d145 100644 --- a/tests/components/xiaomi_mhoc401/test.esp32.yaml +++ b/tests/components/xiaomi_mhoc401/test.esp32.yaml @@ -1,12 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_mhoc401 - mac_address: E7:50:59:32:A0:1C - bindkey: "eef418daf699a0c188f3bfd17e4565d9" - temperature: - name: MHO-C303 Temperature - humidity: - name: MHO-C303 Humidity - battery_level: - name: MHO-C303 Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_miscale copy/common.yaml b/tests/components/xiaomi_miscale copy/common.yaml new file mode 100644 index 0000000000..89f32ad199 --- /dev/null +++ b/tests/components/xiaomi_miscale copy/common.yaml @@ -0,0 +1,9 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_miscale + mac_address: '5C:CA:D3:70:D4:A2' + weight: + name: "Xiaomi Mi Scale Weight" + impedance: + name: "Xiaomi Mi Scale Impedance" diff --git a/tests/components/xiaomi_miscale copy/test.esp32-c3-idf.yaml b/tests/components/xiaomi_miscale copy/test.esp32-c3-idf.yaml index 89f32ad199..dade44d145 100644 --- a/tests/components/xiaomi_miscale copy/test.esp32-c3-idf.yaml +++ b/tests/components/xiaomi_miscale copy/test.esp32-c3-idf.yaml @@ -1,9 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_miscale - mac_address: '5C:CA:D3:70:D4:A2' - weight: - name: "Xiaomi Mi Scale Weight" - impedance: - name: "Xiaomi Mi Scale Impedance" +<<: !include common.yaml diff --git a/tests/components/xiaomi_miscale copy/test.esp32-c3.yaml b/tests/components/xiaomi_miscale copy/test.esp32-c3.yaml index 89f32ad199..dade44d145 100644 --- a/tests/components/xiaomi_miscale copy/test.esp32-c3.yaml +++ b/tests/components/xiaomi_miscale copy/test.esp32-c3.yaml @@ -1,9 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_miscale - mac_address: '5C:CA:D3:70:D4:A2' - weight: - name: "Xiaomi Mi Scale Weight" - impedance: - name: "Xiaomi Mi Scale Impedance" +<<: !include common.yaml diff --git a/tests/components/xiaomi_miscale copy/test.esp32-idf.yaml b/tests/components/xiaomi_miscale copy/test.esp32-idf.yaml index 89f32ad199..dade44d145 100644 --- a/tests/components/xiaomi_miscale copy/test.esp32-idf.yaml +++ b/tests/components/xiaomi_miscale copy/test.esp32-idf.yaml @@ -1,9 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_miscale - mac_address: '5C:CA:D3:70:D4:A2' - weight: - name: "Xiaomi Mi Scale Weight" - impedance: - name: "Xiaomi Mi Scale Impedance" +<<: !include common.yaml diff --git a/tests/components/xiaomi_miscale copy/test.esp32.yaml b/tests/components/xiaomi_miscale copy/test.esp32.yaml index 89f32ad199..dade44d145 100644 --- a/tests/components/xiaomi_miscale copy/test.esp32.yaml +++ b/tests/components/xiaomi_miscale copy/test.esp32.yaml @@ -1,9 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_miscale - mac_address: '5C:CA:D3:70:D4:A2' - weight: - name: "Xiaomi Mi Scale Weight" - impedance: - name: "Xiaomi Mi Scale Impedance" +<<: !include common.yaml diff --git a/tests/components/xiaomi_miscale/common.yaml b/tests/components/xiaomi_miscale/common.yaml new file mode 100644 index 0000000000..89f32ad199 --- /dev/null +++ b/tests/components/xiaomi_miscale/common.yaml @@ -0,0 +1,9 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_miscale + mac_address: '5C:CA:D3:70:D4:A2' + weight: + name: "Xiaomi Mi Scale Weight" + impedance: + name: "Xiaomi Mi Scale Impedance" diff --git a/tests/components/xiaomi_miscale/test.esp32-c3-idf.yaml b/tests/components/xiaomi_miscale/test.esp32-c3-idf.yaml index 89f32ad199..dade44d145 100644 --- a/tests/components/xiaomi_miscale/test.esp32-c3-idf.yaml +++ b/tests/components/xiaomi_miscale/test.esp32-c3-idf.yaml @@ -1,9 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_miscale - mac_address: '5C:CA:D3:70:D4:A2' - weight: - name: "Xiaomi Mi Scale Weight" - impedance: - name: "Xiaomi Mi Scale Impedance" +<<: !include common.yaml diff --git a/tests/components/xiaomi_miscale/test.esp32-c3.yaml b/tests/components/xiaomi_miscale/test.esp32-c3.yaml index 89f32ad199..dade44d145 100644 --- a/tests/components/xiaomi_miscale/test.esp32-c3.yaml +++ b/tests/components/xiaomi_miscale/test.esp32-c3.yaml @@ -1,9 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_miscale - mac_address: '5C:CA:D3:70:D4:A2' - weight: - name: "Xiaomi Mi Scale Weight" - impedance: - name: "Xiaomi Mi Scale Impedance" +<<: !include common.yaml diff --git a/tests/components/xiaomi_miscale/test.esp32-idf.yaml b/tests/components/xiaomi_miscale/test.esp32-idf.yaml index 89f32ad199..dade44d145 100644 --- a/tests/components/xiaomi_miscale/test.esp32-idf.yaml +++ b/tests/components/xiaomi_miscale/test.esp32-idf.yaml @@ -1,9 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_miscale - mac_address: '5C:CA:D3:70:D4:A2' - weight: - name: "Xiaomi Mi Scale Weight" - impedance: - name: "Xiaomi Mi Scale Impedance" +<<: !include common.yaml diff --git a/tests/components/xiaomi_miscale/test.esp32.yaml b/tests/components/xiaomi_miscale/test.esp32.yaml index 89f32ad199..dade44d145 100644 --- a/tests/components/xiaomi_miscale/test.esp32.yaml +++ b/tests/components/xiaomi_miscale/test.esp32.yaml @@ -1,9 +1 @@ -esp32_ble_tracker: - -sensor: - - platform: xiaomi_miscale - mac_address: '5C:CA:D3:70:D4:A2' - weight: - name: "Xiaomi Mi Scale Weight" - impedance: - name: "Xiaomi Mi Scale Impedance" +<<: !include common.yaml diff --git a/tests/components/xiaomi_mjyd02yla/common.yaml b/tests/components/xiaomi_mjyd02yla/common.yaml new file mode 100644 index 0000000000..dffcef84c4 --- /dev/null +++ b/tests/components/xiaomi_mjyd02yla/common.yaml @@ -0,0 +1,13 @@ +esp32_ble_tracker: + +binary_sensor: + - platform: xiaomi_mjyd02yla + name: MJYD02YL-A Motion + mac_address: 50:EC:50:CD:32:02 + bindkey: 48403ebe2d385db8d0c187f81e62cb64 + idle_time: + name: MJYD02YL-A Idle Time + light: + name: MJYD02YL-A Light Status + battery_level: + name: MJYD02YL-A Battery Level diff --git a/tests/components/xiaomi_mjyd02yla/test.esp32-c3-idf.yaml b/tests/components/xiaomi_mjyd02yla/test.esp32-c3-idf.yaml index dffcef84c4..dade44d145 100644 --- a/tests/components/xiaomi_mjyd02yla/test.esp32-c3-idf.yaml +++ b/tests/components/xiaomi_mjyd02yla/test.esp32-c3-idf.yaml @@ -1,13 +1 @@ -esp32_ble_tracker: - -binary_sensor: - - platform: xiaomi_mjyd02yla - name: MJYD02YL-A Motion - mac_address: 50:EC:50:CD:32:02 - bindkey: 48403ebe2d385db8d0c187f81e62cb64 - idle_time: - name: MJYD02YL-A Idle Time - light: - name: MJYD02YL-A Light Status - battery_level: - name: MJYD02YL-A Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_mjyd02yla/test.esp32-c3.yaml b/tests/components/xiaomi_mjyd02yla/test.esp32-c3.yaml index dffcef84c4..dade44d145 100644 --- a/tests/components/xiaomi_mjyd02yla/test.esp32-c3.yaml +++ b/tests/components/xiaomi_mjyd02yla/test.esp32-c3.yaml @@ -1,13 +1 @@ -esp32_ble_tracker: - -binary_sensor: - - platform: xiaomi_mjyd02yla - name: MJYD02YL-A Motion - mac_address: 50:EC:50:CD:32:02 - bindkey: 48403ebe2d385db8d0c187f81e62cb64 - idle_time: - name: MJYD02YL-A Idle Time - light: - name: MJYD02YL-A Light Status - battery_level: - name: MJYD02YL-A Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_mjyd02yla/test.esp32-idf.yaml b/tests/components/xiaomi_mjyd02yla/test.esp32-idf.yaml index dffcef84c4..dade44d145 100644 --- a/tests/components/xiaomi_mjyd02yla/test.esp32-idf.yaml +++ b/tests/components/xiaomi_mjyd02yla/test.esp32-idf.yaml @@ -1,13 +1 @@ -esp32_ble_tracker: - -binary_sensor: - - platform: xiaomi_mjyd02yla - name: MJYD02YL-A Motion - mac_address: 50:EC:50:CD:32:02 - bindkey: 48403ebe2d385db8d0c187f81e62cb64 - idle_time: - name: MJYD02YL-A Idle Time - light: - name: MJYD02YL-A Light Status - battery_level: - name: MJYD02YL-A Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_mjyd02yla/test.esp32.yaml b/tests/components/xiaomi_mjyd02yla/test.esp32.yaml index dffcef84c4..dade44d145 100644 --- a/tests/components/xiaomi_mjyd02yla/test.esp32.yaml +++ b/tests/components/xiaomi_mjyd02yla/test.esp32.yaml @@ -1,13 +1 @@ -esp32_ble_tracker: - -binary_sensor: - - platform: xiaomi_mjyd02yla - name: MJYD02YL-A Motion - mac_address: 50:EC:50:CD:32:02 - bindkey: 48403ebe2d385db8d0c187f81e62cb64 - idle_time: - name: MJYD02YL-A Idle Time - light: - name: MJYD02YL-A Light Status - battery_level: - name: MJYD02YL-A Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_mue4094rt/common.yaml b/tests/components/xiaomi_mue4094rt/common.yaml new file mode 100644 index 0000000000..4f0e5ccbae --- /dev/null +++ b/tests/components/xiaomi_mue4094rt/common.yaml @@ -0,0 +1,7 @@ +esp32_ble_tracker: + +binary_sensor: + - platform: xiaomi_mue4094rt + name: MUE4094RT Motion + mac_address: 7A:80:8E:19:36:BA + timeout: 5s diff --git a/tests/components/xiaomi_mue4094rt/test.esp32-c3-idf.yaml b/tests/components/xiaomi_mue4094rt/test.esp32-c3-idf.yaml index 4f0e5ccbae..dade44d145 100644 --- a/tests/components/xiaomi_mue4094rt/test.esp32-c3-idf.yaml +++ b/tests/components/xiaomi_mue4094rt/test.esp32-c3-idf.yaml @@ -1,7 +1 @@ -esp32_ble_tracker: - -binary_sensor: - - platform: xiaomi_mue4094rt - name: MUE4094RT Motion - mac_address: 7A:80:8E:19:36:BA - timeout: 5s +<<: !include common.yaml diff --git a/tests/components/xiaomi_mue4094rt/test.esp32-c3.yaml b/tests/components/xiaomi_mue4094rt/test.esp32-c3.yaml index 4f0e5ccbae..dade44d145 100644 --- a/tests/components/xiaomi_mue4094rt/test.esp32-c3.yaml +++ b/tests/components/xiaomi_mue4094rt/test.esp32-c3.yaml @@ -1,7 +1 @@ -esp32_ble_tracker: - -binary_sensor: - - platform: xiaomi_mue4094rt - name: MUE4094RT Motion - mac_address: 7A:80:8E:19:36:BA - timeout: 5s +<<: !include common.yaml diff --git a/tests/components/xiaomi_mue4094rt/test.esp32-idf.yaml b/tests/components/xiaomi_mue4094rt/test.esp32-idf.yaml index 4f0e5ccbae..dade44d145 100644 --- a/tests/components/xiaomi_mue4094rt/test.esp32-idf.yaml +++ b/tests/components/xiaomi_mue4094rt/test.esp32-idf.yaml @@ -1,7 +1 @@ -esp32_ble_tracker: - -binary_sensor: - - platform: xiaomi_mue4094rt - name: MUE4094RT Motion - mac_address: 7A:80:8E:19:36:BA - timeout: 5s +<<: !include common.yaml diff --git a/tests/components/xiaomi_mue4094rt/test.esp32.yaml b/tests/components/xiaomi_mue4094rt/test.esp32.yaml index 4f0e5ccbae..dade44d145 100644 --- a/tests/components/xiaomi_mue4094rt/test.esp32.yaml +++ b/tests/components/xiaomi_mue4094rt/test.esp32.yaml @@ -1,7 +1 @@ -esp32_ble_tracker: - -binary_sensor: - - platform: xiaomi_mue4094rt - name: MUE4094RT Motion - mac_address: 7A:80:8E:19:36:BA - timeout: 5s +<<: !include common.yaml diff --git a/tests/components/xiaomi_rtcgq02lm/common.yaml b/tests/components/xiaomi_rtcgq02lm/common.yaml new file mode 100644 index 0000000000..a2e0c66ba5 --- /dev/null +++ b/tests/components/xiaomi_rtcgq02lm/common.yaml @@ -0,0 +1,22 @@ +esp32_ble_tracker: + +xiaomi_rtcgq02lm: + - id: motion_rtcgq02lm + mac_address: 01:02:03:04:05:06 + bindkey: "48403ebe2d385db8d0c187f81e62cb64" + +binary_sensor: + - platform: xiaomi_rtcgq02lm + id: motion_rtcgq02lm + motion: + name: Mi Motion Sensor 2 + light: + name: Mi Motion Sensor 2 Light + button: + name: Mi Motion Sensor 2 Button + +sensor: + - platform: xiaomi_rtcgq02lm + id: motion_rtcgq02lm + battery_level: + name: Mi Motion Sensor 2 Battery level diff --git a/tests/components/xiaomi_rtcgq02lm/test.esp32-c3-idf.yaml b/tests/components/xiaomi_rtcgq02lm/test.esp32-c3-idf.yaml index a2e0c66ba5..dade44d145 100644 --- a/tests/components/xiaomi_rtcgq02lm/test.esp32-c3-idf.yaml +++ b/tests/components/xiaomi_rtcgq02lm/test.esp32-c3-idf.yaml @@ -1,22 +1 @@ -esp32_ble_tracker: - -xiaomi_rtcgq02lm: - - id: motion_rtcgq02lm - mac_address: 01:02:03:04:05:06 - bindkey: "48403ebe2d385db8d0c187f81e62cb64" - -binary_sensor: - - platform: xiaomi_rtcgq02lm - id: motion_rtcgq02lm - motion: - name: Mi Motion Sensor 2 - light: - name: Mi Motion Sensor 2 Light - button: - name: Mi Motion Sensor 2 Button - -sensor: - - platform: xiaomi_rtcgq02lm - id: motion_rtcgq02lm - battery_level: - name: Mi Motion Sensor 2 Battery level +<<: !include common.yaml diff --git a/tests/components/xiaomi_rtcgq02lm/test.esp32-c3.yaml b/tests/components/xiaomi_rtcgq02lm/test.esp32-c3.yaml index a2e0c66ba5..dade44d145 100644 --- a/tests/components/xiaomi_rtcgq02lm/test.esp32-c3.yaml +++ b/tests/components/xiaomi_rtcgq02lm/test.esp32-c3.yaml @@ -1,22 +1 @@ -esp32_ble_tracker: - -xiaomi_rtcgq02lm: - - id: motion_rtcgq02lm - mac_address: 01:02:03:04:05:06 - bindkey: "48403ebe2d385db8d0c187f81e62cb64" - -binary_sensor: - - platform: xiaomi_rtcgq02lm - id: motion_rtcgq02lm - motion: - name: Mi Motion Sensor 2 - light: - name: Mi Motion Sensor 2 Light - button: - name: Mi Motion Sensor 2 Button - -sensor: - - platform: xiaomi_rtcgq02lm - id: motion_rtcgq02lm - battery_level: - name: Mi Motion Sensor 2 Battery level +<<: !include common.yaml diff --git a/tests/components/xiaomi_rtcgq02lm/test.esp32-idf.yaml b/tests/components/xiaomi_rtcgq02lm/test.esp32-idf.yaml index a2e0c66ba5..dade44d145 100644 --- a/tests/components/xiaomi_rtcgq02lm/test.esp32-idf.yaml +++ b/tests/components/xiaomi_rtcgq02lm/test.esp32-idf.yaml @@ -1,22 +1 @@ -esp32_ble_tracker: - -xiaomi_rtcgq02lm: - - id: motion_rtcgq02lm - mac_address: 01:02:03:04:05:06 - bindkey: "48403ebe2d385db8d0c187f81e62cb64" - -binary_sensor: - - platform: xiaomi_rtcgq02lm - id: motion_rtcgq02lm - motion: - name: Mi Motion Sensor 2 - light: - name: Mi Motion Sensor 2 Light - button: - name: Mi Motion Sensor 2 Button - -sensor: - - platform: xiaomi_rtcgq02lm - id: motion_rtcgq02lm - battery_level: - name: Mi Motion Sensor 2 Battery level +<<: !include common.yaml diff --git a/tests/components/xiaomi_rtcgq02lm/test.esp32.yaml b/tests/components/xiaomi_rtcgq02lm/test.esp32.yaml index a2e0c66ba5..dade44d145 100644 --- a/tests/components/xiaomi_rtcgq02lm/test.esp32.yaml +++ b/tests/components/xiaomi_rtcgq02lm/test.esp32.yaml @@ -1,22 +1 @@ -esp32_ble_tracker: - -xiaomi_rtcgq02lm: - - id: motion_rtcgq02lm - mac_address: 01:02:03:04:05:06 - bindkey: "48403ebe2d385db8d0c187f81e62cb64" - -binary_sensor: - - platform: xiaomi_rtcgq02lm - id: motion_rtcgq02lm - motion: - name: Mi Motion Sensor 2 - light: - name: Mi Motion Sensor 2 Light - button: - name: Mi Motion Sensor 2 Button - -sensor: - - platform: xiaomi_rtcgq02lm - id: motion_rtcgq02lm - battery_level: - name: Mi Motion Sensor 2 Battery level +<<: !include common.yaml diff --git a/tests/components/xiaomi_wx08zm/common.yaml b/tests/components/xiaomi_wx08zm/common.yaml new file mode 100644 index 0000000000..3e83ad3e95 --- /dev/null +++ b/tests/components/xiaomi_wx08zm/common.yaml @@ -0,0 +1,10 @@ +esp32_ble_tracker: + +binary_sensor: + - platform: xiaomi_wx08zm + name: WX08ZM Activation State + mac_address: 74:a3:4a:b5:07:34 + tablet: + name: WX08ZM Tablet Resource + battery_level: + name: WX08ZM Battery Level diff --git a/tests/components/xiaomi_wx08zm/test.esp32-c3-idf.yaml b/tests/components/xiaomi_wx08zm/test.esp32-c3-idf.yaml index 3e83ad3e95..dade44d145 100644 --- a/tests/components/xiaomi_wx08zm/test.esp32-c3-idf.yaml +++ b/tests/components/xiaomi_wx08zm/test.esp32-c3-idf.yaml @@ -1,10 +1 @@ -esp32_ble_tracker: - -binary_sensor: - - platform: xiaomi_wx08zm - name: WX08ZM Activation State - mac_address: 74:a3:4a:b5:07:34 - tablet: - name: WX08ZM Tablet Resource - battery_level: - name: WX08ZM Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_wx08zm/test.esp32-c3.yaml b/tests/components/xiaomi_wx08zm/test.esp32-c3.yaml index 3e83ad3e95..dade44d145 100644 --- a/tests/components/xiaomi_wx08zm/test.esp32-c3.yaml +++ b/tests/components/xiaomi_wx08zm/test.esp32-c3.yaml @@ -1,10 +1 @@ -esp32_ble_tracker: - -binary_sensor: - - platform: xiaomi_wx08zm - name: WX08ZM Activation State - mac_address: 74:a3:4a:b5:07:34 - tablet: - name: WX08ZM Tablet Resource - battery_level: - name: WX08ZM Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_wx08zm/test.esp32-idf.yaml b/tests/components/xiaomi_wx08zm/test.esp32-idf.yaml index 3e83ad3e95..dade44d145 100644 --- a/tests/components/xiaomi_wx08zm/test.esp32-idf.yaml +++ b/tests/components/xiaomi_wx08zm/test.esp32-idf.yaml @@ -1,10 +1 @@ -esp32_ble_tracker: - -binary_sensor: - - platform: xiaomi_wx08zm - name: WX08ZM Activation State - mac_address: 74:a3:4a:b5:07:34 - tablet: - name: WX08ZM Tablet Resource - battery_level: - name: WX08ZM Battery Level +<<: !include common.yaml diff --git a/tests/components/xiaomi_wx08zm/test.esp32.yaml b/tests/components/xiaomi_wx08zm/test.esp32.yaml index 3e83ad3e95..dade44d145 100644 --- a/tests/components/xiaomi_wx08zm/test.esp32.yaml +++ b/tests/components/xiaomi_wx08zm/test.esp32.yaml @@ -1,10 +1 @@ -esp32_ble_tracker: - -binary_sensor: - - platform: xiaomi_wx08zm - name: WX08ZM Activation State - mac_address: 74:a3:4a:b5:07:34 - tablet: - name: WX08ZM Tablet Resource - battery_level: - name: WX08ZM Battery Level +<<: !include common.yaml From b545d5723672f14aacfa839f91f8333df27fa83d Mon Sep 17 00:00:00 2001 From: Trent Houliston Date: Wed, 8 May 2024 08:13:15 +1000 Subject: [PATCH 1385/2101] Make `pulse_meter` PULSE filter report the pulse as soon as it can (#6014) --- .../components/pulse_meter/pulse_filter.md | 61 ++++++++++++++++ .../pulse_meter/pulse_meter_sensor.cpp | 73 +++++++++++-------- .../pulse_meter/pulse_meter_sensor.h | 20 ++++- 3 files changed, 121 insertions(+), 33 deletions(-) create mode 100644 esphome/components/pulse_meter/pulse_filter.md diff --git a/esphome/components/pulse_meter/pulse_filter.md b/esphome/components/pulse_meter/pulse_filter.md new file mode 100644 index 0000000000..240c479d54 --- /dev/null +++ b/esphome/components/pulse_meter/pulse_filter.md @@ -0,0 +1,61 @@ +# PULSE Filter + +The PULSE filter filters noisy pulses by ensuring that the pulse is in a steady state for at least `filter_length` before allowing the state change to occur. +It counts the pulse time from the rising edge that stayed high for at least `filter_length`, so noise before this won't be considered the start of a pulse. +It then must see a low pulse that is at least `filter_length` long before a subsequent rising edge is considered a new pulse start. + +It's operation should be the same as delayed_on_off from the Binary Sensor component. + +There are three moving parts in the algorithm that are used to determine the state of the filter. + +1. The time between interrupts, measured from the last interrupt, this is compared to filter_length to determine if the pulse has been in a steady state for long enough. +2. A latch variable that is set true when a high pulse is long enough to be considered a valid pulse and is reset when a low pulse is long enough to allow for another pulse to begin. +3. The previous and current state of the pin used to determine if the pulse is rising or falling. + +## Ghost interrupts + +Observations from the devices show that even though the interrupt should trigger on every rising or falling edge, sometimes interrupts show the same state twice in a row. +The current theory is an interprets occurs, but then the pin changing back faster than the ISR can be called and read the value, meaning it sees the same state twice in a row. +The algorithm interprets these when it sees them as two edges in a row, so will potentially reset a pulse if + +## Pulse Filter Truth table + +The following is all of the possible states of the filter along with the new inputs. +It also shows a diagram of a possible series of interrupts that would cause the filter to enter that state. +It then has the action that the filter should take and a description of what is happening. + +Diagram legend + +- `/` rising edge +- `\` falling edge +- `‾` high steady state of at least `filter_length` +- `_` low steady state of at least `filter_length` +- `¦` ghost interrupt + +| Length | Latch | From | To | Diagram | Action | Description | +| ------ | ----- | ---- | --- | ------- | ------------------ | ---------------------------------------------------------------------------------------------------- | +| T | 1 | 0 | 0 | `‾\_¦ ` | Reset | `filter_length` low, reset the latch | +| T | 1 | 0 | 1 | `‾\_/ ` | Reset, Rising Edge | `filter_length` low, reset the latch, rising edge could be a new pulse | +| T | 1 | 1 | 0 | `‾\/‾\` | - | Already latched from a previous `filter_length` high | +| T | 1 | 1 | 1 | `‾\/‾¦` | - | Already latched from a previous `filter_length` high | +| T | 0 | 1 | 1 | `_/‾¦` | Set and Publish | `filter_length` high, set the latch and publish the pulse | +| T | 0 | 1 | 0 | `_/‾\ ` | Set and Publish | `filter_length` high, set the latch and publish the pulse | +| T | 0 | 0 | 1 | `_/\_/` | Rising Edge | Already unlatched from a previous `filter_length` low | +| T | 0 | 0 | 0 | `_/\_¦` | - | Already unlatched from a previous `filter_length` low | +| F | 1 | 0 | 0 | `‾\¦ ` | - | Low was not long enough to reset the latch | +| F | 1 | 0 | 1 | `‾\/ ` | - | Low was not long enough to reset the latch | +| F | 1 | 1 | 0 | `‾\/\ ` | - | Low was not long enough to reset the latch | +| F | 1 | 1 | 1 | `‾¦ ` | - | Ghost of 0 length definitely was not long was not long enough to reset the latch | +| F | 0 | 1 | 1 | `_/¦ ` | Rising Edge | High was not long enough to set the latch, but the second half of the ghost can be a new rising edge | +| F | 0 | 1 | 0 | `_/\ ` | - | High was not long enough to set the latch | +| F | 0 | 0 | 1 | `_/\/ ` | Rising Edge | High was not long enough to set the latch, but this may be a rising edge | +| F | 0 | 0 | 0 | `_¦ ` | - | Ghost of 0 length definitely was not long was not long enough to set the latch | + +## Startup + +On startup the filter should not consider whatever state it is in as valid so it does not count a strange pulse. +There are two possible starting configurations, either the pin is high or the pin is low. +If the pin is high, the subsequent falling edge should not count as a pulse as we never saw the rising edge. +Therefore we start in the latched state. +If the pin is low, the subsequent rising edge can be counted as the first pulse. +Therefore we start in the unlatched state. diff --git a/esphome/components/pulse_meter/pulse_meter_sensor.cpp b/esphome/components/pulse_meter/pulse_meter_sensor.cpp index 14f8e508b5..530425563c 100644 --- a/esphome/components/pulse_meter/pulse_meter_sensor.cpp +++ b/esphome/components/pulse_meter/pulse_meter_sensor.cpp @@ -24,11 +24,16 @@ void PulseMeterSensor::setup() { if (this->filter_mode_ == FILTER_EDGE) { this->pin_->attach_interrupt(PulseMeterSensor::edge_intr, this, gpio::INTERRUPT_RISING_EDGE); } else if (this->filter_mode_ == FILTER_PULSE) { + // Set the pin value to the current value to avoid a false edge + this->pulse_state_.last_pin_val_ = this->isr_pin_.digital_read(); + this->pulse_state_.latched_ = this->pulse_state_.last_pin_val_; this->pin_->attach_interrupt(PulseMeterSensor::pulse_intr, this, gpio::INTERRUPT_ANY_EDGE); } } void PulseMeterSensor::loop() { + const uint32_t now = micros(); + // Reset the count in get before we pass it back to the ISR as set this->get_->count_ = 0; @@ -38,6 +43,20 @@ void PulseMeterSensor::loop() { this->set_ = this->get_; this->get_ = temp; + // If an edge was peeked, repay the debt + if (this->peeked_edge_ && this->get_->count_ > 0) { + this->peeked_edge_ = false; + this->get_->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_) { + this->peeked_edge_ = true; + this->get_->last_detected_edge_us_ = this->get_->last_rising_edge_us_; + this->get_->count_++; + } + // Check if we detected a pulse this loop if (this->get_->count_ > 0) { // Keep a running total of pulses if a total sensor is configured @@ -64,7 +83,6 @@ void PulseMeterSensor::loop() { } // No detected edges this loop else { - const uint32_t now = micros(); const uint32_t time_since_valid_edge_us = now - this->last_processed_edge_us_; switch (this->meter_state_) { @@ -102,11 +120,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_; - if ((now - sensor->last_edge_candidate_us_) >= sensor->filter_us_) { - sensor->last_edge_candidate_us_ = now; - sensor->set_->last_detected_edge_us_ = now; - sensor->set_->count_++; + 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_++; } } @@ -115,33 +136,27 @@ 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_; - // A pulse occurred faster than we can detect - if (sensor->last_pin_val_ == pin_val) { - // If we haven't reached the filter length yet we need to reset our last_intr_ to now - // otherwise we can consider this noise as the "pulse" was certainly less than filter_us_ - if (now - sensor->last_intr_ < sensor->filter_us_) { - sensor->last_intr_ = now; - } - } else { - // Check if the last interrupt was long enough in the past - if (now - sensor->last_intr_ > sensor->filter_us_) { - // High pulse of filter length now falling (therefore last_intr_ was the rising edge) - if (!sensor->in_pulse_ && sensor->last_pin_val_) { - sensor->last_edge_candidate_us_ = sensor->last_intr_; - sensor->in_pulse_ = true; - } - // Low pulse of filter length now rising (therefore last_intr_ was the falling edge) - else if (sensor->in_pulse_ && !sensor->last_pin_val_) { - sensor->set_->last_detected_edge_us_ = sensor->last_edge_candidate_us_; - sensor->set_->count_++; - sensor->in_pulse_ = false; - } - } + // Filter length has passed since the last interrupt + const bool length = now - state.last_intr_ >= sensor->filter_us_; - sensor->last_intr_ = now; - sensor->last_pin_val_ = pin_val; + if (length && state.latched_ && !state.last_pin_val_) { // Long enough low edge + state.latched_ = false; + } else if (length && !state.latched_ && state.last_pin_val_) { // Long enough high edge + state.latched_ = true; + set.last_detected_edge_us_ = state.last_intr_; + set.count_++; } + + // 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_intr_ = now; + state.last_pin_val_ = pin_val; } } // namespace pulse_meter diff --git a/esphome/components/pulse_meter/pulse_meter_sensor.h b/esphome/components/pulse_meter/pulse_meter_sensor.h index 1cd02e3ca2..76c4a35f03 100644 --- a/esphome/components/pulse_meter/pulse_meter_sensor.h +++ b/esphome/components/pulse_meter/pulse_meter_sensor.h @@ -43,6 +43,7 @@ class PulseMeterSensor : public sensor::Sensor, public Component { // Variables used in the loop enum class MeterState { INITIAL, RUNNING, TIMED_OUT }; MeterState meter_state_ = MeterState::INITIAL; + bool peeked_edge_ = false; uint32_t total_pulses_ = 0; uint32_t last_processed_edge_us_ = 0; @@ -53,6 +54,7 @@ class PulseMeterSensor : public sensor::Sensor, public Component { // (except for resetting the values) struct State { uint32_t last_detected_edge_us_ = 0; + uint32_t last_rising_edge_us_ = 0; uint32_t count_ = 0; }; State state_[2]; @@ -61,10 +63,20 @@ class PulseMeterSensor : public sensor::Sensor, public Component { // Only use these variables in the ISR ISRInternalGPIOPin isr_pin_; - uint32_t last_edge_candidate_us_ = 0; - uint32_t last_intr_ = 0; - bool in_pulse_ = false; - bool last_pin_val_ = false; + + /// Filter state for edge mode + struct EdgeState { + uint32_t last_sent_edge_us_ = 0; + }; + EdgeState edge_state_{}; + + /// Filter state for pulse mode + struct PulseState { + uint32_t last_intr_ = 0; + bool latched_ = false; + bool last_pin_val_ = false; + }; + PulseState pulse_state_{}; }; } // namespace pulse_meter From d9fca585a2972d4d4d041d87c9ee1bc4a41b925c Mon Sep 17 00:00:00 2001 From: esphomebot Date: Wed, 8 May 2024 11:57:03 +1200 Subject: [PATCH 1386/2101] Update webserver local assets to 20240507-231331 (#6696) --- .../components/web_server/server_index_v3.h | 7968 +++++++++-------- 1 file changed, 3993 insertions(+), 3975 deletions(-) diff --git a/esphome/components/web_server/server_index_v3.h b/esphome/components/web_server/server_index_v3.h index a7ad3ab543..66cd9de47a 100644 --- a/esphome/components/web_server/server_index_v3.h +++ b/esphome/components/web_server/server_index_v3.h @@ -10,3986 +10,4004 @@ namespace esphome { namespace web_server { const uint8_t INDEX_GZ[] PROGMEM = { - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xcc, 0xbd, 0xeb, 0x7a, 0x1b, 0xb7, 0xb2, 0x20, 0xfa, - 0xfb, 0xcc, 0x53, 0x48, 0xbd, 0x1d, 0xa5, 0x21, 0x82, 0x2d, 0x92, 0xba, 0x58, 0x6e, 0x0a, 0xe2, 0xf8, 0x1a, 0x3b, - 0x71, 0x6c, 0xc7, 0x72, 0xec, 0xd8, 0x0c, 0xb7, 0x02, 0x36, 0x41, 0x12, 0x71, 0x13, 0x60, 0x1a, 0xa0, 0x25, 0x99, - 0xe4, 0xbb, 0x9f, 0xaf, 0x70, 0xe9, 0x46, 0x93, 0xb4, 0xd7, 0x5a, 0x73, 0x66, 0xce, 0x37, 0x3b, 0x7b, 0x59, 0x6c, - 0xdc, 0x51, 0x28, 0x14, 0xaa, 0x0a, 0x55, 0x85, 0x8b, 0xfd, 0x91, 0xcc, 0xf4, 0xdd, 0x9c, 0xed, 0x4d, 0xf5, 0x2c, - 0xbf, 0xbc, 0x70, 0xff, 0x32, 0x3a, 0xba, 0xbc, 0xc8, 0xb9, 0xf8, 0xbc, 0x57, 0xb0, 0x9c, 0xf0, 0x4c, 0x8a, 0xbd, - 0x69, 0xc1, 0xc6, 0x64, 0x44, 0x35, 0x4d, 0xf9, 0x8c, 0x4e, 0xd8, 0xde, 0xd1, 0xe5, 0xc5, 0x8c, 0x69, 0xba, 0x97, - 0x4d, 0x69, 0xa1, 0x98, 0x26, 0xbf, 0xbf, 0x7b, 0xd6, 0x3c, 0xbf, 0xbc, 0x50, 0x59, 0xc1, 0xe7, 0x7a, 0x0f, 0x9a, - 0x24, 0x33, 0x39, 0x5a, 0xe4, 0xec, 0xf2, 0xe8, 0xe8, 0xe6, 0xe6, 0x26, 0xf9, 0x5b, 0xfd, 0x8f, 0x2f, 0xb4, 0xd8, - 0xfb, 0xa5, 0x20, 0xaf, 0x87, 0x7f, 0xb3, 0x4c, 0x27, 0x23, 0x36, 0xe6, 0x82, 0xbd, 0x29, 0xe4, 0x9c, 0x15, 0xfa, - 0xae, 0x0b, 0x99, 0x3f, 0x15, 0x24, 0xe6, 0x58, 0x63, 0x86, 0xc8, 0xa5, 0xde, 0xe3, 0x62, 0x8f, 0xf7, 0x7e, 0x29, - 0x4c, 0xca, 0x92, 0x89, 0xc5, 0x8c, 0x15, 0x74, 0x98, 0xb3, 0x74, 0xbf, 0x85, 0x33, 0x29, 0xc6, 0x7c, 0xb2, 0x28, - 0xbf, 0x6f, 0x0a, 0xae, 0xfd, 0xef, 0x2f, 0x34, 0x5f, 0xb0, 0x94, 0xad, 0x51, 0xca, 0xfb, 0x7a, 0x40, 0x98, 0x69, - 0xf9, 0x73, 0xd5, 0x70, 0xfc, 0x93, 0x69, 0xf2, 0x6e, 0xce, 0xe4, 0x78, 0x4f, 0xef, 0x93, 0x48, 0xdd, 0xcd, 0x86, - 0x32, 0x8f, 0x7a, 0xba, 0x11, 0x45, 0x29, 0x94, 0xc1, 0x0c, 0x75, 0x33, 0x29, 0x94, 0xde, 0x13, 0x9c, 0xdc, 0x70, - 0x31, 0x92, 0x37, 0xf8, 0x46, 0x10, 0xc1, 0x93, 0xab, 0x29, 0x1d, 0xc9, 0x9b, 0xb7, 0x52, 0xea, 0x83, 0x83, 0xd8, - 0x7d, 0xdf, 0x3d, 0xbe, 0xba, 0x22, 0x84, 0x7c, 0x91, 0x7c, 0xb4, 0xd7, 0x5a, 0xad, 0x82, 0xd4, 0x44, 0x50, 0xcd, - 0xbf, 0x30, 0x5b, 0x09, 0x1d, 0x1c, 0x44, 0x74, 0x24, 0xe7, 0x9a, 0x8d, 0xae, 0xf4, 0x5d, 0xce, 0xae, 0xa6, 0x8c, - 0x69, 0x15, 0x71, 0xb1, 0xf7, 0x44, 0x66, 0x8b, 0x19, 0x13, 0x3a, 0x99, 0x17, 0x52, 0x4b, 0x18, 0xd8, 0xc1, 0x41, - 0x54, 0xb0, 0x79, 0x4e, 0x33, 0x06, 0xf9, 0x8f, 0xaf, 0xae, 0xaa, 0x1a, 0x55, 0x21, 0xfc, 0x59, 0x90, 0x2b, 0x33, - 0xf4, 0x18, 0xe1, 0x0f, 0x82, 0x08, 0x76, 0xb3, 0xf7, 0x81, 0xd1, 0xcf, 0xbf, 0xd2, 0x79, 0x37, 0xcb, 0xa9, 0x52, - 0x7b, 0xcf, 0xe4, 0xd2, 0x4c, 0xa3, 0x58, 0x64, 0x5a, 0x16, 0xb1, 0xc6, 0x0c, 0x0b, 0xb4, 0xe4, 0xe3, 0x58, 0x4f, - 0xb9, 0x4a, 0xae, 0xef, 0x65, 0x4a, 0xbd, 0x65, 0x6a, 0x91, 0xeb, 0x7b, 0x64, 0xbf, 0x85, 0xc5, 0x3e, 0x21, 0x9f, - 0x05, 0xd2, 0xd3, 0x42, 0xde, 0xec, 0x3d, 0x2d, 0x0a, 0x59, 0xc4, 0xd1, 0xe3, 0xab, 0x2b, 0x5b, 0x62, 0x8f, 0xab, - 0x3d, 0x21, 0xf5, 0x5e, 0xd9, 0x1e, 0x40, 0x3b, 0xd9, 0xfb, 0x5d, 0xb1, 0xbd, 0xbf, 0x16, 0x42, 0xd1, 0x31, 0x7b, - 0x7c, 0x75, 0xf5, 0xd7, 0x9e, 0x2c, 0xf6, 0xfe, 0xca, 0x94, 0xfa, 0x6b, 0x8f, 0x0b, 0xa5, 0x19, 0x1d, 0x25, 0x11, - 0xea, 0x9a, 0xce, 0x32, 0xa5, 0xde, 0xb1, 0x5b, 0x4d, 0x34, 0x36, 0x9f, 0x9a, 0xb0, 0xf5, 0x84, 0xe9, 0x3d, 0x55, - 0xce, 0x2b, 0x46, 0xcb, 0x9c, 0xe9, 0x3d, 0x4d, 0x4c, 0xbe, 0x74, 0xf0, 0x67, 0xf6, 0x53, 0x77, 0xf9, 0x38, 0xbe, - 0x11, 0x07, 0x07, 0xba, 0x04, 0x34, 0x5a, 0xba, 0x15, 0x22, 0x6c, 0xdf, 0xa7, 0x1d, 0x1c, 0xb0, 0x24, 0x67, 0x62, - 0xa2, 0xa7, 0x84, 0x90, 0x76, 0x57, 0x1c, 0x1c, 0xc4, 0x9a, 0x7c, 0x10, 0xc9, 0x84, 0xe9, 0x98, 0x21, 0x84, 0xab, - 0xda, 0x07, 0x07, 0xb1, 0x05, 0x82, 0x24, 0xda, 0x00, 0xae, 0x06, 0x63, 0x94, 0x38, 0xe8, 0x5f, 0xdd, 0x89, 0x2c, - 0x0e, 0xc7, 0x8f, 0xb0, 0x38, 0x38, 0xf8, 0x20, 0x12, 0x05, 0x2d, 0x62, 0x8d, 0xd0, 0xba, 0x60, 0x7a, 0x51, 0x88, - 0x3d, 0xbd, 0xd6, 0xf2, 0x4a, 0x17, 0x5c, 0x4c, 0x62, 0xb4, 0xf4, 0x69, 0x41, 0xc5, 0xf5, 0xda, 0x0e, 0xf7, 0xb7, - 0x82, 0x70, 0x72, 0x09, 0x3d, 0x3e, 0x93, 0xb1, 0xc3, 0x41, 0x4e, 0x48, 0xa4, 0x4c, 0xdd, 0xa8, 0xc7, 0x53, 0xde, - 0x88, 0x22, 0x6c, 0x47, 0x89, 0x3f, 0x0b, 0x84, 0xb9, 0x06, 0xd4, 0x4d, 0x92, 0x44, 0x23, 0x72, 0xb9, 0xf4, 0x60, - 0xe1, 0xc1, 0x44, 0x7b, 0xbc, 0xdf, 0x1a, 0xa4, 0x3a, 0x29, 0xd8, 0x68, 0x91, 0xb1, 0x38, 0x16, 0x58, 0x61, 0x89, - 0xc8, 0xa5, 0x68, 0xc4, 0x05, 0xb9, 0x84, 0xf5, 0x2e, 0xea, 0x8b, 0x4d, 0xc8, 0x7e, 0x0b, 0xb9, 0x41, 0x16, 0x7e, - 0x84, 0x00, 0x62, 0x37, 0xa0, 0x82, 0x90, 0x48, 0x2c, 0x66, 0x43, 0x56, 0x44, 0x65, 0xb1, 0x6e, 0x0d, 0x2f, 0x16, - 0x8a, 0xed, 0x65, 0x4a, 0xed, 0x8d, 0x17, 0x22, 0xd3, 0x5c, 0x8a, 0xbd, 0xa8, 0x51, 0x34, 0x22, 0x8b, 0x0f, 0x25, - 0x3a, 0x44, 0x68, 0x8d, 0x62, 0x85, 0x1a, 0xbc, 0x2f, 0x1b, 0xed, 0x01, 0x86, 0x51, 0xa2, 0xae, 0x6b, 0xcf, 0x41, - 0x80, 0x61, 0x0e, 0x93, 0x5c, 0xe3, 0x4f, 0x76, 0xe7, 0xc3, 0x14, 0x6f, 0x44, 0x8f, 0x27, 0xdb, 0x3b, 0x85, 0xe8, - 0x64, 0x46, 0xe7, 0x31, 0x23, 0x97, 0xcc, 0x60, 0x17, 0x15, 0x19, 0x8c, 0xb5, 0xb6, 0x70, 0x3d, 0x96, 0xb2, 0xa4, - 0xc2, 0x29, 0x94, 0xea, 0x64, 0x2c, 0x8b, 0xa7, 0x34, 0x9b, 0x42, 0xbd, 0x12, 0x63, 0x46, 0x7e, 0xc3, 0x65, 0x05, - 0xa3, 0x9a, 0x3d, 0xcd, 0x19, 0x7c, 0xc5, 0x91, 0xa9, 0x19, 0x21, 0xac, 0x60, 0xab, 0xe7, 0x5c, 0xbf, 0x92, 0x22, - 0x63, 0x5d, 0x15, 0xe0, 0x97, 0x59, 0xf9, 0x87, 0x5a, 0x17, 0x7c, 0xb8, 0xd0, 0x2c, 0x8e, 0x04, 0x94, 0x88, 0xb0, - 0x42, 0x58, 0x24, 0x9a, 0xdd, 0xea, 0xc7, 0x52, 0x68, 0x26, 0x34, 0x61, 0x1e, 0xaa, 0x98, 0x27, 0x74, 0x3e, 0x67, - 0x62, 0xf4, 0x78, 0xca, 0xf3, 0x51, 0x2c, 0xd0, 0x1a, 0xad, 0xf1, 0xef, 0x82, 0xc0, 0x24, 0xc9, 0x25, 0x4f, 0xe1, - 0x9f, 0x6f, 0x4f, 0x27, 0xd6, 0xe4, 0xd2, 0x6c, 0x0b, 0x46, 0xa2, 0xa8, 0x3b, 0x96, 0x45, 0xec, 0xa6, 0xb0, 0x07, - 0xa4, 0x0b, 0xfa, 0x78, 0xbb, 0xc8, 0x99, 0x42, 0xac, 0x41, 0x44, 0xb9, 0x8e, 0x0e, 0xc2, 0xbf, 0x15, 0x31, 0x83, - 0x05, 0xe0, 0x28, 0xe5, 0x86, 0x04, 0xbe, 0xe4, 0x6e, 0x53, 0x8d, 0x4a, 0xa2, 0xf6, 0x51, 0x90, 0x11, 0x4f, 0x74, - 0xb1, 0x50, 0x9a, 0x8d, 0xde, 0xdd, 0xcd, 0x99, 0xc2, 0x3f, 0x17, 0xe4, 0xa3, 0xe8, 0x7d, 0x14, 0x09, 0x9b, 0xcd, - 0xf5, 0xdd, 0x95, 0xa1, 0xe6, 0x69, 0x14, 0xe1, 0x7f, 0x4c, 0xd1, 0x82, 0xd1, 0x0c, 0x48, 0x9a, 0x03, 0xd9, 0x1b, - 0x99, 0xdf, 0x8d, 0x79, 0x9e, 0x5f, 0x2d, 0xe6, 0x73, 0x59, 0x68, 0xac, 0x05, 0x59, 0x6a, 0x59, 0xc1, 0x07, 0x56, - 0x74, 0xa9, 0x6e, 0xb8, 0xce, 0xa6, 0xb1, 0x46, 0xcb, 0x8c, 0x2a, 0xb6, 0xf7, 0x48, 0xca, 0x9c, 0x51, 0x91, 0x72, - 0xc2, 0x7b, 0x3f, 0x17, 0xa9, 0x58, 0xe4, 0x79, 0x77, 0x58, 0x30, 0xfa, 0xb9, 0x6b, 0xb2, 0xed, 0xe1, 0x90, 0x9a, - 0xdf, 0x0f, 0x8b, 0x82, 0xde, 0x41, 0x41, 0x42, 0xa0, 0x58, 0x8f, 0xa7, 0x3f, 0x5f, 0xbd, 0x7e, 0x95, 0xd8, 0xbd, - 0xc2, 0xc7, 0x77, 0x31, 0x2f, 0xf7, 0x1f, 0x5f, 0xe3, 0x71, 0x21, 0x67, 0x1b, 0x5d, 0x5b, 0xd0, 0xf1, 0xee, 0x37, - 0x86, 0xc0, 0x08, 0xdf, 0xb7, 0x4d, 0x87, 0x23, 0x78, 0x65, 0x30, 0x1f, 0x32, 0x89, 0xeb, 0x17, 0xfe, 0x49, 0x6d, - 0x72, 0xcc, 0xd1, 0xf7, 0x47, 0xab, 0x8b, 0xbb, 0x25, 0x23, 0x66, 0x9c, 0x73, 0x38, 0x18, 0x61, 0x8c, 0x19, 0xd5, - 0xd9, 0x74, 0xc9, 0x4c, 0x63, 0x6b, 0x3f, 0x62, 0xb6, 0x5e, 0xe3, 0xaf, 0xd2, 0x63, 0xbd, 0xde, 0x27, 0x84, 0x1b, - 0x7a, 0x45, 0xf4, 0x6a, 0xc5, 0x09, 0xe1, 0x08, 0xbf, 0xe5, 0x64, 0x49, 0xfd, 0x84, 0xe0, 0x64, 0x83, 0xed, 0x99, - 0x5a, 0x2a, 0x03, 0x27, 0xe0, 0x17, 0x56, 0x68, 0x56, 0xa4, 0x5a, 0xe0, 0x82, 0x8d, 0x73, 0x18, 0xc7, 0x7e, 0x1b, - 0x4f, 0xa9, 0x7a, 0x3c, 0xa5, 0x62, 0xc2, 0x46, 0xe9, 0x57, 0xb9, 0xc6, 0x4c, 0x90, 0x68, 0xcc, 0x05, 0xcd, 0xf9, - 0x57, 0x36, 0x8a, 0xdc, 0xb9, 0xf0, 0x48, 0xef, 0xb1, 0x5b, 0xcd, 0xc4, 0x48, 0xed, 0x3d, 0x7f, 0xf7, 0xeb, 0x4b, - 0xb7, 0x98, 0xb5, 0xb3, 0x02, 0x2d, 0xd5, 0x62, 0xce, 0x8a, 0x18, 0x61, 0x77, 0x56, 0x3c, 0xe5, 0x86, 0x4e, 0xfe, - 0x4a, 0xe7, 0x36, 0x85, 0xab, 0xdf, 0xe7, 0x23, 0xaa, 0xd9, 0x1b, 0x26, 0x46, 0x5c, 0x4c, 0xc8, 0x7e, 0xdb, 0xa6, - 0x4f, 0xa9, 0xcb, 0x18, 0x95, 0x49, 0xd7, 0xf7, 0x9e, 0xe6, 0x66, 0xee, 0xe5, 0xe7, 0x22, 0x46, 0x6b, 0xa5, 0xa9, - 0xe6, 0xd9, 0x1e, 0x1d, 0x8d, 0x5e, 0x08, 0xae, 0xb9, 0x19, 0x61, 0x01, 0x4b, 0x04, 0xb8, 0xca, 0xec, 0xa9, 0xe1, - 0x47, 0x1e, 0x23, 0x1c, 0xc7, 0xee, 0x2c, 0x98, 0x22, 0xb7, 0x66, 0x07, 0x07, 0x15, 0xe5, 0xef, 0xb1, 0xd4, 0x66, - 0x92, 0xfe, 0x00, 0x25, 0xf3, 0x85, 0x82, 0xc5, 0xf6, 0x5d, 0xc0, 0x41, 0x23, 0x87, 0x8a, 0x15, 0x5f, 0xd8, 0xa8, - 0x44, 0x10, 0x15, 0xa3, 0xe5, 0x46, 0x1f, 0x6e, 0x7b, 0x68, 0xd2, 0x1f, 0x74, 0x43, 0x12, 0xce, 0x1c, 0xb2, 0x5b, - 0x4e, 0x85, 0x33, 0x55, 0x12, 0x95, 0x18, 0x0e, 0xd4, 0x92, 0xb0, 0x28, 0xe2, 0xe7, 0x37, 0x8f, 0x05, 0xf0, 0x10, - 0x21, 0xe5, 0xf0, 0x67, 0xee, 0xd3, 0x2f, 0xe6, 0xf0, 0x50, 0x58, 0x20, 0xac, 0xed, 0x48, 0x15, 0x42, 0x6b, 0x84, - 0xb5, 0x1f, 0xae, 0x25, 0x4a, 0x9e, 0x2f, 0x82, 0x53, 0x9b, 0xbc, 0xe5, 0xe6, 0xd8, 0x06, 0xda, 0x46, 0x35, 0x3b, - 0x38, 0x88, 0x59, 0x52, 0x22, 0x06, 0xd9, 0x6f, 0xbb, 0x45, 0x0a, 0xa0, 0xf5, 0x8d, 0x71, 0x43, 0xcf, 0x86, 0xc1, - 0xd9, 0x67, 0x89, 0x90, 0x0f, 0xb3, 0x8c, 0x29, 0x25, 0x8b, 0x83, 0x83, 0x7d, 0x53, 0xbe, 0xe4, 0x2c, 0x60, 0x11, - 0x5f, 0xdf, 0x88, 0x6a, 0x08, 0xa8, 0x3a, 0x6d, 0x3d, 0xdf, 0x44, 0x2a, 0xbe, 0xc9, 0x33, 0x21, 0x69, 0x74, 0x7d, - 0x1d, 0x35, 0x34, 0x76, 0x70, 0x98, 0x30, 0xdf, 0xf5, 0xdd, 0x13, 0x66, 0xd9, 0x42, 0xc3, 0x84, 0x6c, 0x81, 0x66, - 0x27, 0x3f, 0x18, 0xd7, 0x87, 0x84, 0x35, 0x56, 0x68, 0x1d, 0xac, 0xe8, 0xce, 0xa6, 0x0d, 0x7f, 0x63, 0x97, 0x6e, - 0x39, 0x31, 0x3c, 0x45, 0xb0, 0x8e, 0x7d, 0x36, 0x58, 0x63, 0x03, 0x7b, 0x3f, 0x1b, 0x69, 0x06, 0xda, 0xd7, 0x83, - 0xae, 0xcb, 0x27, 0xca, 0x42, 0xae, 0x60, 0xff, 0x2c, 0x98, 0xd2, 0x16, 0x91, 0x63, 0x8d, 0x25, 0x86, 0x33, 0x6a, - 0x93, 0xe9, 0xac, 0xb1, 0xa4, 0xbb, 0xc6, 0xf6, 0x7a, 0x0e, 0x67, 0xa3, 0x02, 0xa4, 0xfe, 0x3e, 0x3e, 0xc1, 0x58, - 0x35, 0x5a, 0xad, 0xde, 0x72, 0xdf, 0x4a, 0xb5, 0x96, 0x25, 0xbf, 0xb6, 0xb1, 0x28, 0x4c, 0x20, 0x77, 0x38, 0xef, - 0xb7, 0xdd, 0xf8, 0xc5, 0x80, 0xec, 0xb7, 0x4a, 0x2c, 0x76, 0x60, 0xb5, 0xe3, 0xb1, 0x50, 0x7c, 0x6d, 0x9b, 0x42, - 0xe6, 0xac, 0xaf, 0xe1, 0x4b, 0x32, 0xdd, 0xc2, 0xd5, 0x29, 0xe9, 0x03, 0xd7, 0x91, 0x4c, 0x07, 0xdf, 0xc2, 0x27, - 0x4f, 0x11, 0x62, 0xbd, 0x9d, 0x57, 0x11, 0x8e, 0x2f, 0x75, 0xc2, 0xb1, 0x31, 0x8d, 0x68, 0x5e, 0x56, 0x89, 0x4a, - 0x34, 0x73, 0x5b, 0xbd, 0xca, 0xc2, 0xc2, 0x0c, 0xa6, 0x9a, 0x52, 0xd0, 0xc4, 0x2b, 0x3a, 0x63, 0x2a, 0x66, 0x08, - 0x7f, 0xab, 0x80, 0xc5, 0x4f, 0x28, 0x32, 0x08, 0xce, 0x50, 0x05, 0x67, 0x28, 0xb0, 0xbb, 0xc0, 0xa4, 0xd5, 0xb7, - 0x9c, 0xc2, 0xac, 0xaf, 0x06, 0x15, 0x6f, 0x17, 0x4c, 0xde, 0x1c, 0xce, 0x0e, 0xc1, 0x3d, 0xfc, 0x6c, 0x9a, 0x05, - 0x9a, 0x61, 0x21, 0x14, 0xc2, 0xfb, 0xad, 0xcd, 0x95, 0xf4, 0xa5, 0xaa, 0x39, 0xf6, 0x07, 0xb0, 0x0e, 0xe6, 0xd8, - 0x48, 0xb8, 0x32, 0x7f, 0x6b, 0x5b, 0x0d, 0xc0, 0x76, 0x05, 0x98, 0x91, 0x8c, 0x73, 0xaa, 0xe3, 0xf6, 0x51, 0x0b, - 0x18, 0xd3, 0x2f, 0x0c, 0x4e, 0x15, 0x84, 0xb6, 0xa7, 0xc2, 0x92, 0x85, 0x50, 0x53, 0x3e, 0xd6, 0xf1, 0xef, 0xc2, - 0x10, 0x15, 0x96, 0x2b, 0x06, 0x12, 0x4e, 0xc0, 0x1e, 0x1b, 0x82, 0xf3, 0xbb, 0x80, 0x7e, 0xba, 0xe5, 0x41, 0xe4, - 0x46, 0x6a, 0x08, 0x17, 0x90, 0x87, 0x8a, 0xb5, 0xae, 0xc8, 0x4c, 0xc9, 0xb8, 0x01, 0xf7, 0xd8, 0xee, 0xd9, 0x16, - 0x53, 0x47, 0x0d, 0x44, 0xc0, 0xc1, 0x8a, 0x34, 0x24, 0x11, 0x2e, 0x51, 0x27, 0x5a, 0xbe, 0x94, 0x37, 0xac, 0x78, - 0x4c, 0x61, 0xf0, 0xa9, 0xad, 0xbe, 0xb6, 0x47, 0x81, 0xa1, 0xf8, 0xba, 0xeb, 0xf1, 0xe5, 0xda, 0x4c, 0xfc, 0x4d, - 0x21, 0x67, 0x5c, 0x31, 0xe0, 0xdb, 0x2c, 0xfc, 0x05, 0x6c, 0x34, 0xb3, 0x23, 0xe1, 0xb8, 0x61, 0x25, 0x7e, 0x3d, - 0x7c, 0x59, 0xc7, 0xaf, 0xeb, 0x7b, 0x4f, 0x27, 0x9e, 0x02, 0xd6, 0xf7, 0x31, 0xc2, 0xb1, 0x13, 0x2f, 0x82, 0x93, - 0x2e, 0x99, 0x22, 0x77, 0xcc, 0xaf, 0x56, 0x3a, 0x10, 0xe3, 0x6a, 0x9c, 0x23, 0xb3, 0xdb, 0x06, 0xad, 0xe9, 0x68, - 0x04, 0x2c, 0x5e, 0x21, 0xf3, 0x3c, 0x38, 0xac, 0xb0, 0xe8, 0x96, 0xc7, 0xd3, 0xf5, 0xbd, 0xa7, 0x57, 0xdf, 0x3b, - 0xa1, 0x20, 0x3f, 0x3c, 0xa4, 0xfc, 0x40, 0xc5, 0x88, 0x15, 0x20, 0x57, 0x06, 0xab, 0xe5, 0xce, 0xd9, 0xc7, 0x52, - 0x08, 0x96, 0x69, 0x36, 0x02, 0xa1, 0x45, 0x10, 0x9d, 0x4c, 0xa5, 0xd2, 0x65, 0x62, 0x35, 0x7a, 0x11, 0x0a, 0xa1, - 0x49, 0x46, 0xf3, 0x3c, 0xb6, 0x02, 0xca, 0x4c, 0x7e, 0x61, 0x3b, 0x46, 0xdd, 0xad, 0x0d, 0xb9, 0x6c, 0x86, 0x05, - 0xcd, 0xb0, 0x44, 0xcd, 0x73, 0x9e, 0xb1, 0xf2, 0xf0, 0xba, 0x4a, 0xb8, 0x18, 0xb1, 0x5b, 0xa0, 0x23, 0xe8, 0xf2, - 0xf2, 0xb2, 0x85, 0xdb, 0x68, 0x6d, 0x01, 0xbe, 0xdc, 0x02, 0xec, 0x77, 0x8e, 0x4d, 0x2b, 0x88, 0x2f, 0x77, 0x92, - 0x35, 0x14, 0x9c, 0x95, 0xdc, 0x0b, 0x5a, 0x96, 0x3c, 0x23, 0x3c, 0x62, 0x39, 0xd3, 0xcc, 0x93, 0x73, 0x60, 0xa6, - 0xed, 0xd6, 0x7d, 0x5b, 0xc2, 0xaf, 0x44, 0x27, 0xbf, 0xcb, 0xfc, 0x9a, 0xab, 0x52, 0x74, 0xaf, 0x96, 0xa7, 0x82, - 0x76, 0x4f, 0xdb, 0xe5, 0xa1, 0x5a, 0xd3, 0x6c, 0x6a, 0x25, 0xf6, 0x78, 0x6b, 0x4a, 0x55, 0x1b, 0x8e, 0xb4, 0x97, - 0x9b, 0xe8, 0x53, 0xe1, 0x86, 0xb9, 0x0b, 0x04, 0x57, 0x8e, 0x28, 0x30, 0x10, 0x02, 0xed, 0xb2, 0x3d, 0xa6, 0x79, - 0x3e, 0xa4, 0xd9, 0xe7, 0x3a, 0xf6, 0x57, 0x68, 0x40, 0x36, 0xa9, 0x71, 0x90, 0x15, 0x90, 0xac, 0x70, 0xde, 0x9e, - 0x4a, 0xd7, 0x36, 0x4a, 0xbc, 0xdf, 0xaa, 0xd0, 0xbe, 0xbe, 0xd0, 0xdf, 0xc4, 0x76, 0x33, 0x22, 0xe1, 0x66, 0x16, - 0x03, 0x15, 0xf8, 0x97, 0x18, 0xe7, 0xe9, 0x81, 0xc3, 0x3b, 0x10, 0x3c, 0xd6, 0x1b, 0x03, 0xd1, 0x68, 0xb9, 0x1e, - 0x71, 0xf5, 0x6d, 0x08, 0xfc, 0x6f, 0x19, 0xe5, 0x93, 0xa0, 0x87, 0x7f, 0x77, 0xa0, 0x25, 0x8d, 0x73, 0x8c, 0x73, - 0x39, 0x32, 0xc7, 0x50, 0x78, 0x42, 0xf3, 0x0b, 0x30, 0x2f, 0x06, 0xdf, 0x5f, 0xdb, 0x2c, 0xc3, 0x97, 0xc1, 0x30, - 0x54, 0x37, 0x64, 0x28, 0x6a, 0x28, 0xe0, 0x88, 0xaa, 0x30, 0x67, 0xae, 0xac, 0x89, 0x92, 0x8e, 0x6b, 0xb7, 0xe2, - 0xb8, 0xa3, 0xb9, 0x05, 0x89, 0xe3, 0x58, 0x81, 0x34, 0xe7, 0xf9, 0xfb, 0x6a, 0x16, 0x6a, 0x6b, 0x16, 0x2a, 0x09, - 0xa4, 0x2d, 0x54, 0x21, 0x73, 0x50, 0x3d, 0xd5, 0x02, 0x85, 0xa5, 0x80, 0x65, 0x4d, 0x80, 0x42, 0xa3, 0x92, 0xe0, - 0xe6, 0x44, 0xe3, 0xc2, 0x89, 0x3a, 0x0e, 0xd7, 0x80, 0x64, 0x54, 0x55, 0x24, 0xb2, 0x9b, 0xa3, 0x26, 0xfb, 0x4a, - 0x5c, 0xa0, 0x0d, 0xfe, 0x7e, 0xbd, 0x76, 0x50, 0x62, 0xc8, 0xad, 0x4e, 0x8d, 0x31, 0x0e, 0xc0, 0x82, 0x25, 0x71, - 0xcc, 0xb0, 0x65, 0x7d, 0x36, 0x81, 0x53, 0xb6, 0xbb, 0x4f, 0x88, 0xac, 0x60, 0x53, 0x63, 0x2a, 0x3d, 0x77, 0x25, - 0x11, 0xa6, 0x9e, 0x2d, 0x2d, 0xaa, 0x89, 0x13, 0x12, 0x79, 0xed, 0x44, 0xd4, 0x5b, 0xd6, 0x84, 0xc3, 0x34, 0x28, - 0xb6, 0x4e, 0x81, 0xa8, 0x16, 0xbb, 0xe0, 0xbd, 0x0b, 0x6b, 0x6a, 0xed, 0x04, 0x10, 0x2f, 0x6a, 0x10, 0x0f, 0x40, - 0x2b, 0x2d, 0xf1, 0x92, 0x03, 0x42, 0xeb, 0x95, 0x63, 0x86, 0x0b, 0xbb, 0x10, 0x5b, 0x50, 0xdc, 0x64, 0x3f, 0x0d, - 0x16, 0x82, 0x2c, 0xab, 0x80, 0xbf, 0x0b, 0x8f, 0x88, 0x18, 0x06, 0x2f, 0x56, 0xab, 0x2d, 0xb4, 0xdb, 0xc9, 0x85, - 0xa2, 0xa4, 0x92, 0x0e, 0x57, 0xab, 0xaf, 0x12, 0xc5, 0x8e, 0xff, 0xc5, 0x0c, 0xf5, 0x3c, 0xd1, 0x7d, 0xf8, 0x12, - 0x4a, 0x19, 0x76, 0xb4, 0x4a, 0x29, 0x05, 0x87, 0x3a, 0xd6, 0xd6, 0x17, 0x4a, 0x07, 0x94, 0xfb, 0xf1, 0x16, 0x01, - 0x33, 0x89, 0xee, 0xa4, 0xae, 0xa6, 0xfc, 0xd8, 0x35, 0x2d, 0x10, 0x42, 0xa9, 0x32, 0xb2, 0xcc, 0xfe, 0x2e, 0xf9, - 0xf2, 0xe0, 0x40, 0x05, 0x0d, 0x5d, 0x97, 0x94, 0xe2, 0xef, 0x18, 0x4e, 0x65, 0x75, 0x27, 0x0c, 0xfb, 0xf2, 0xb7, - 0x3f, 0x87, 0xb6, 0xa4, 0xd3, 0x56, 0x17, 0x04, 0x73, 0x7a, 0x43, 0xb9, 0xde, 0x2b, 0x5b, 0xb1, 0x82, 0x79, 0xcc, - 0xd0, 0xd2, 0x71, 0x1b, 0x49, 0xc1, 0x80, 0x7f, 0x04, 0xb2, 0xe0, 0xb9, 0x68, 0x8b, 0xf8, 0xd9, 0x94, 0x81, 0x2a, - 0xdb, 0x33, 0x12, 0xa5, 0x78, 0xb8, 0xef, 0x0e, 0x12, 0xd7, 0xf0, 0xee, 0xb1, 0xaf, 0x37, 0xab, 0xd7, 0xa4, 0x81, - 0x39, 0x2b, 0xc6, 0xb2, 0x98, 0xf9, 0xbc, 0xf5, 0xc6, 0xb7, 0x23, 0x8e, 0x7c, 0x1c, 0xef, 0x6c, 0xdb, 0x89, 0x00, - 0xdd, 0x0d, 0xd9, 0xbb, 0x92, 0xda, 0x6b, 0xa7, 0x69, 0x79, 0x00, 0x5b, 0x05, 0xa1, 0xc7, 0x4c, 0x15, 0x4a, 0xf9, - 0x4e, 0xbd, 0xda, 0xb5, 0xba, 0x93, 0xfd, 0x76, 0xb7, 0x94, 0xfc, 0x3c, 0x36, 0x74, 0xad, 0x8e, 0xc3, 0x9d, 0xaa, - 0x72, 0x91, 0x8f, 0xdc, 0x60, 0x05, 0xc2, 0xcc, 0xe1, 0xd1, 0x0d, 0xcf, 0xf3, 0x2a, 0xf5, 0x3f, 0x21, 0xed, 0xca, - 0x91, 0x76, 0xe9, 0x49, 0x3b, 0x90, 0x0a, 0x20, 0xed, 0xb6, 0xb9, 0xaa, 0xba, 0xdc, 0xda, 0x9e, 0xd2, 0x12, 0x75, - 0x65, 0xc4, 0x69, 0xe8, 0x6f, 0xe1, 0x47, 0x80, 0x4a, 0xe6, 0xeb, 0x73, 0xec, 0xf4, 0x31, 0x20, 0x06, 0x5a, 0x9d, - 0x26, 0x0b, 0x35, 0x15, 0x9f, 0x63, 0x84, 0xd5, 0x9a, 0x95, 0x98, 0xfd, 0xf0, 0x29, 0x28, 0xed, 0x82, 0xe9, 0xc0, - 0x39, 0x66, 0x92, 0xff, 0x23, 0x3e, 0xca, 0xcf, 0x4e, 0xb8, 0xd9, 0x29, 0x3f, 0x3b, 0xa0, 0xf5, 0xd5, 0xec, 0x46, - 0xdf, 0xa7, 0xf6, 0x66, 0x7a, 0xa2, 0x9c, 0x5e, 0xb5, 0xde, 0xab, 0x55, 0xbc, 0x91, 0x02, 0x1a, 0x7d, 0x27, 0xa5, - 0x14, 0x65, 0xeb, 0x40, 0x03, 0x42, 0xc8, 0x40, 0xc2, 0xda, 0x4e, 0xba, 0x3c, 0xe5, 0x5e, 0xfe, 0x2b, 0x3d, 0x8f, - 0x51, 0xdc, 0xdb, 0xfa, 0x8f, 0xe5, 0x6c, 0x0e, 0x0c, 0xd9, 0x06, 0x4a, 0x4f, 0x98, 0xeb, 0xb0, 0xca, 0x5f, 0xef, - 0x48, 0xab, 0xd5, 0x31, 0xfb, 0xb1, 0x86, 0x4d, 0xa5, 0xd4, 0xbc, 0xdf, 0x5a, 0x2f, 0xca, 0xa4, 0x92, 0x70, 0xec, - 0xd2, 0xad, 0x3c, 0xde, 0xd4, 0xcc, 0xf8, 0x8c, 0xd7, 0xb1, 0xb0, 0x74, 0x58, 0x00, 0xad, 0x0b, 0xc8, 0x8f, 0x47, - 0xf7, 0x70, 0xfd, 0xd7, 0x15, 0x70, 0x96, 0xeb, 0x0d, 0xf0, 0x2d, 0xd7, 0xeb, 0x47, 0xda, 0x49, 0xda, 0xf8, 0xd1, - 0x0e, 0xb9, 0xb7, 0x84, 0x5e, 0x95, 0xe9, 0x64, 0xc6, 0xfe, 0x00, 0xd2, 0xb6, 0x58, 0x48, 0xb2, 0x9c, 0xc9, 0x11, - 0x4b, 0x23, 0x39, 0x67, 0x22, 0x5a, 0x83, 0x9e, 0xd5, 0x21, 0xc0, 0x3f, 0x22, 0x5e, 0xbe, 0xad, 0xeb, 0x5b, 0xd3, - 0x47, 0x7a, 0x0d, 0xaa, 0xb0, 0x97, 0x7c, 0x87, 0x32, 0xf6, 0x3d, 0x2b, 0x94, 0xe1, 0x49, 0x4b, 0xf6, 0xf6, 0x25, - 0xaf, 0x0e, 0xa8, 0x97, 0x3c, 0xfd, 0x76, 0x95, 0x4a, 0x20, 0x89, 0xda, 0xc9, 0x59, 0x72, 0x1c, 0x21, 0xa3, 0x31, - 0x7e, 0xe6, 0x35, 0xc6, 0x8b, 0x52, 0x63, 0xfc, 0x5c, 0x93, 0xc5, 0x86, 0xc6, 0xf8, 0x0f, 0x41, 0x9e, 0xeb, 0xde, - 0x73, 0xaf, 0x4d, 0x7f, 0x23, 0x73, 0x9e, 0xdd, 0xc5, 0x51, 0xce, 0x75, 0x13, 0x6e, 0x13, 0x23, 0xbc, 0xb4, 0x19, - 0xa0, 0x6a, 0x34, 0xfa, 0xee, 0xb5, 0x97, 0xff, 0xb0, 0x10, 0x24, 0xba, 0x97, 0x73, 0x7d, 0x2f, 0xc2, 0x53, 0x4d, - 0xfe, 0x82, 0x5f, 0xf7, 0x96, 0xf1, 0xaf, 0x54, 0x4f, 0x93, 0x82, 0x8a, 0x91, 0x9c, 0xc5, 0xa8, 0x11, 0x45, 0x28, - 0x51, 0x46, 0x08, 0x79, 0x80, 0xd6, 0xf7, 0xfe, 0xc2, 0xaf, 0x24, 0x89, 0x7a, 0x51, 0x63, 0xaa, 0xb1, 0xa6, 0xe4, - 0xaf, 0x8b, 0x7b, 0xcb, 0x57, 0x72, 0x7d, 0xf9, 0x17, 0x7e, 0xaa, 0x4b, 0xb5, 0x3e, 0xbe, 0x65, 0x24, 0x46, 0xe4, - 0xf2, 0xa9, 0x1f, 0xd2, 0x63, 0x39, 0xb3, 0x0a, 0xfe, 0x08, 0xe1, 0x2f, 0xa0, 0xd7, 0xbd, 0xe4, 0x15, 0x11, 0x72, - 0x77, 0x30, 0xfb, 0x24, 0x92, 0x46, 0x79, 0x10, 0x1d, 0x1c, 0x04, 0x69, 0x25, 0x0b, 0x81, 0xff, 0x96, 0xa4, 0x26, - 0xaa, 0x63, 0x46, 0xa1, 0xa5, 0xbf, 0x65, 0xcc, 0x91, 0x6f, 0x26, 0xf6, 0x9a, 0x6a, 0xb7, 0x63, 0x79, 0xdf, 0xea, - 0x1e, 0x12, 0xae, 0x59, 0x41, 0xb5, 0x2c, 0x06, 0x28, 0x64, 0x4b, 0xf0, 0x57, 0x4e, 0xfe, 0xea, 0xef, 0xfd, 0x3f, - 0xff, 0xe3, 0xcf, 0xf1, 0x9f, 0xc5, 0xe0, 0x2f, 0x2c, 0x18, 0x39, 0xba, 0x88, 0x7b, 0x69, 0xbc, 0xdf, 0x6c, 0xae, - 0xfe, 0x3c, 0xea, 0xff, 0x37, 0x6d, 0x7e, 0x7d, 0xd8, 0xfc, 0x34, 0x40, 0xab, 0xf8, 0xcf, 0xa3, 0x5e, 0xdf, 0x7d, - 0xf5, 0xff, 0xfb, 0xf2, 0x4f, 0x35, 0x38, 0xb4, 0x89, 0xf7, 0x10, 0x3a, 0x9a, 0xe0, 0x5f, 0x04, 0x39, 0x6a, 0x36, - 0x2f, 0x8f, 0x26, 0xf8, 0x27, 0x41, 0x8e, 0xe0, 0xef, 0x9d, 0x26, 0x6f, 0xd9, 0xe4, 0xe9, 0xed, 0x3c, 0xfe, 0xeb, - 0x72, 0x75, 0x6f, 0xf9, 0x95, 0xaf, 0xa1, 0xdd, 0xfe, 0x7f, 0xff, 0xf9, 0xa7, 0x8a, 0x7e, 0xbc, 0x24, 0x47, 0x83, - 0x06, 0x8a, 0x4d, 0xf2, 0x21, 0xb1, 0x7f, 0xe2, 0x5e, 0xda, 0xff, 0x6f, 0x37, 0x94, 0xe8, 0xc7, 0x3f, 0xff, 0xba, - 0xb8, 0x24, 0x83, 0x55, 0x1c, 0xad, 0x7e, 0x44, 0x2b, 0x84, 0x56, 0xf7, 0xd0, 0x5f, 0x38, 0x9a, 0x44, 0x08, 0xff, - 0x26, 0xc8, 0xd1, 0x8f, 0x47, 0x13, 0xfc, 0x49, 0x90, 0xa3, 0xe8, 0x68, 0x82, 0xdf, 0x4b, 0x72, 0xf4, 0xdf, 0x71, - 0x2f, 0xb5, 0x4a, 0xb8, 0x95, 0x51, 0x7f, 0xac, 0xe0, 0x26, 0x84, 0x16, 0x8c, 0xae, 0x34, 0xd7, 0x39, 0x43, 0xf7, - 0x8e, 0x38, 0x7e, 0x24, 0x01, 0x58, 0xb1, 0x06, 0x25, 0x8d, 0xb9, 0x84, 0x5d, 0x5e, 0xc3, 0xc2, 0x03, 0x06, 0xdd, - 0x4b, 0x39, 0xb6, 0x7a, 0x02, 0x95, 0x6a, 0x7b, 0x7b, 0xab, 0xe0, 0xfa, 0x16, 0x3f, 0x26, 0x8f, 0x64, 0xdc, 0x46, - 0x98, 0x53, 0xf8, 0xd1, 0x41, 0xf8, 0x83, 0x76, 0x17, 0x9e, 0xb0, 0xcd, 0x2d, 0x86, 0x09, 0x69, 0xf9, 0x99, 0x08, - 0xe1, 0x97, 0x3b, 0x32, 0xf5, 0x14, 0xd4, 0x0f, 0x08, 0xff, 0x5c, 0xbb, 0x1e, 0xc5, 0x8f, 0x35, 0x29, 0x91, 0xe3, - 0x5d, 0xc1, 0xd8, 0x07, 0x9a, 0x7f, 0x66, 0x45, 0xfc, 0x54, 0xe3, 0x76, 0xe7, 0x01, 0x36, 0xaa, 0xea, 0xfd, 0x36, - 0xea, 0x96, 0xb7, 0x5b, 0xcf, 0xa5, 0xbd, 0x4f, 0x80, 0x53, 0xb8, 0xae, 0xaf, 0x81, 0xb5, 0xdf, 0xe7, 0x5b, 0x4a, - 0xad, 0x82, 0xde, 0x44, 0xa8, 0x7e, 0x95, 0xca, 0xc5, 0x17, 0x9a, 0xf3, 0xd1, 0x9e, 0x66, 0xb3, 0x79, 0x4e, 0x35, - 0xdb, 0x73, 0x73, 0xde, 0xa3, 0xd0, 0x50, 0x54, 0xf2, 0x14, 0x7f, 0x88, 0x6a, 0xd3, 0xfe, 0x21, 0x92, 0x6a, 0xef, - 0xc4, 0x70, 0x9f, 0xe5, 0xf8, 0x12, 0x41, 0xcb, 0xeb, 0xb2, 0xcd, 0x1b, 0xc1, 0x66, 0x1b, 0x94, 0x65, 0x03, 0x73, - 0x7e, 0x2b, 0x0c, 0xf7, 0x9b, 0x84, 0x74, 0x7a, 0xd1, 0x85, 0xfa, 0x32, 0xb9, 0x8c, 0xe0, 0x26, 0xa7, 0x20, 0x82, - 0x19, 0xe5, 0x11, 0x94, 0xa0, 0xa4, 0xd5, 0xa5, 0x17, 0xac, 0x4b, 0x1b, 0x0d, 0xcf, 0x66, 0x67, 0x84, 0xf7, 0xa9, - 0xad, 0x9f, 0xe3, 0x29, 0x1e, 0x91, 0x66, 0x1b, 0x2f, 0x48, 0xcb, 0x54, 0xe9, 0x2e, 0x2e, 0x32, 0xd7, 0xcf, 0xc1, - 0x41, 0x5c, 0x24, 0x39, 0x55, 0xfa, 0x05, 0x68, 0x04, 0xc8, 0x02, 0x4f, 0x49, 0x91, 0xb0, 0x5b, 0x96, 0xc5, 0x19, - 0xc2, 0x53, 0x47, 0x83, 0x50, 0x17, 0x2d, 0x48, 0x50, 0x0c, 0xe4, 0x0c, 0x22, 0x58, 0x6f, 0xda, 0x6f, 0x0f, 0x08, - 0x21, 0xd1, 0x7e, 0xb3, 0x19, 0xf5, 0x0a, 0xf2, 0x8b, 0x48, 0x21, 0x25, 0x60, 0xa7, 0xc9, 0x4f, 0x90, 0xd4, 0x09, - 0x92, 0xe2, 0xf7, 0x32, 0xd1, 0x4c, 0xe9, 0x18, 0x92, 0x41, 0x49, 0xa0, 0x3c, 0x86, 0x47, 0x17, 0x47, 0x51, 0x03, - 0x52, 0x0d, 0x8a, 0x22, 0x5c, 0x90, 0x3b, 0x8d, 0xd2, 0x69, 0xff, 0x78, 0x10, 0x9e, 0x11, 0x36, 0x15, 0xfa, 0xbf, - 0xd3, 0xbd, 0x69, 0xbf, 0x65, 0xfa, 0xbf, 0x8c, 0x7a, 0x71, 0x41, 0x94, 0x65, 0xe3, 0x7a, 0x2a, 0x15, 0xcc, 0xcc, - 0x17, 0xa5, 0x6e, 0x80, 0xae, 0xef, 0x11, 0x69, 0x76, 0xd2, 0x78, 0x14, 0xce, 0xa4, 0x09, 0x1d, 0x3a, 0x50, 0xe0, - 0x9c, 0x40, 0x79, 0x5c, 0x10, 0xe8, 0xb4, 0xaa, 0x76, 0xa7, 0x53, 0x97, 0xf0, 0x63, 0xf4, 0x63, 0xef, 0x93, 0x48, - 0x7f, 0x13, 0x76, 0x04, 0x9f, 0xc4, 0x6a, 0x05, 0x7f, 0x7f, 0x13, 0x3d, 0x18, 0x96, 0x49, 0xfb, 0xc5, 0xa5, 0xfd, - 0x04, 0x69, 0x82, 0xa5, 0x66, 0xc0, 0x58, 0x95, 0xfc, 0x98, 0x5d, 0x9c, 0x31, 0xb1, 0x33, 0x38, 0x38, 0xe0, 0x7d, - 0xda, 0x68, 0x0f, 0xe0, 0x46, 0xa0, 0xd0, 0xea, 0x03, 0xd7, 0xd3, 0x38, 0x3a, 0xba, 0x8c, 0x50, 0x2f, 0xda, 0x83, - 0x55, 0xee, 0xca, 0x06, 0x71, 0xb0, 0xce, 0x1a, 0x9a, 0xa6, 0xa3, 0x4b, 0xd2, 0xea, 0xc5, 0xc2, 0x12, 0xf9, 0x1c, - 0xe1, 0xcc, 0xd1, 0xd4, 0x16, 0x1e, 0xa1, 0x86, 0x10, 0x0d, 0xff, 0x3d, 0x42, 0x8d, 0xa9, 0x6e, 0x8c, 0x51, 0x9a, - 0xc1, 0xdf, 0x78, 0x44, 0x08, 0x69, 0x76, 0xca, 0x8a, 0xfe, 0xb0, 0xa4, 0x28, 0x1d, 0x7b, 0xf5, 0x68, 0xdf, 0x6c, - 0x0e, 0xd9, 0x88, 0x79, 0x9f, 0x0d, 0x56, 0xab, 0xe8, 0xa2, 0x77, 0x19, 0xa1, 0x46, 0xec, 0xd1, 0xee, 0xc8, 0xe3, - 0x1d, 0x42, 0x58, 0x0c, 0xd6, 0xee, 0x06, 0xea, 0x86, 0xd5, 0x6e, 0x9b, 0x96, 0xd5, 0xfe, 0x0f, 0xc8, 0x02, 0x5b, - 0x97, 0x72, 0x8f, 0xe5, 0x6f, 0xe7, 0x30, 0x55, 0x8f, 0xdb, 0x92, 0xb4, 0x70, 0x41, 0xbc, 0xba, 0x9b, 0x12, 0x5d, - 0xe1, 0x7f, 0x46, 0xaa, 0xe2, 0xb8, 0x9f, 0xe3, 0xe9, 0x80, 0x08, 0x6a, 0xe4, 0x97, 0xae, 0x57, 0xa6, 0xb3, 0x9c, - 0xdc, 0xb0, 0x8d, 0xfb, 0xdf, 0x1c, 0xee, 0x64, 0x1e, 0xeb, 0x24, 0x5b, 0x14, 0x05, 0x13, 0xfa, 0x95, 0x1c, 0x39, - 0xc6, 0x8e, 0xe5, 0x20, 0x5b, 0xc1, 0xc5, 0x2e, 0x06, 0xae, 0xae, 0xe3, 0x77, 0xca, 0x68, 0x2b, 0x7b, 0x41, 0x46, - 0x96, 0xe1, 0x32, 0xd7, 0xbd, 0xdd, 0x85, 0x13, 0xa5, 0x63, 0x84, 0x47, 0xee, 0x1e, 0x38, 0x4e, 0x92, 0x64, 0x91, - 0x64, 0x90, 0x0d, 0x1d, 0x28, 0xb4, 0x36, 0xfb, 0x2a, 0x56, 0xe4, 0xb1, 0x4e, 0x04, 0xbb, 0x35, 0xdd, 0xc6, 0xa8, - 0x3a, 0xc4, 0xfd, 0x7e, 0xbb, 0xa0, 0x5d, 0x43, 0x80, 0x54, 0x22, 0xe4, 0x88, 0x01, 0x84, 0xe0, 0xee, 0xdf, 0x25, - 0x4d, 0xa9, 0x0a, 0x6f, 0xb6, 0xaa, 0x01, 0xf6, 0x43, 0x95, 0xf7, 0x02, 0xf4, 0xc4, 0x86, 0x3d, 0x2b, 0x0b, 0x5b, - 0xe5, 0x39, 0x42, 0x7c, 0x1c, 0x2f, 0x12, 0xb8, 0x11, 0x34, 0x98, 0x24, 0x04, 0x5a, 0xad, 0x16, 0x21, 0x6e, 0x4d, - 0x2b, 0xc5, 0xf4, 0x98, 0x4c, 0xfb, 0x45, 0xa3, 0x61, 0x94, 0xd7, 0x23, 0x8b, 0x17, 0x0b, 0x84, 0xc7, 0xe5, 0x5e, - 0xf3, 0xe5, 0xe6, 0xa4, 0xde, 0x55, 0x3c, 0xae, 0x2b, 0x81, 0x1b, 0x42, 0x20, 0xa3, 0x5f, 0xd4, 0xd0, 0x3a, 0x9e, - 0x90, 0xa3, 0xb8, 0x9f, 0xf4, 0xfe, 0xe7, 0x00, 0xf5, 0xe2, 0xe4, 0x10, 0x1d, 0x59, 0x5a, 0x32, 0x46, 0xdd, 0xcc, - 0xf6, 0xb1, 0x34, 0xb7, 0x9f, 0x6d, 0x6c, 0x14, 0x90, 0xa9, 0xc4, 0x82, 0xce, 0x58, 0x3a, 0x81, 0x5d, 0xef, 0x91, - 0x67, 0x8e, 0x01, 0x99, 0xd2, 0x89, 0xa3, 0x2d, 0x49, 0xd4, 0x93, 0xb4, 0xfc, 0xea, 0x45, 0x3d, 0x5a, 0x7d, 0xfd, - 0xcf, 0xa8, 0x97, 0xd1, 0xf4, 0x31, 0x5f, 0x3b, 0x25, 0x79, 0xad, 0x8f, 0x33, 0xdf, 0xc7, 0xda, 0x2e, 0x4e, 0x00, - 0xbc, 0x11, 0xda, 0xd6, 0x8e, 0x2c, 0xd0, 0x9a, 0x8f, 0x4b, 0xea, 0xa4, 0x12, 0x4d, 0x27, 0x00, 0xd5, 0x60, 0x11, - 0x54, 0x68, 0x1b, 0x10, 0x4c, 0x19, 0xb0, 0xc5, 0x23, 0x2d, 0x40, 0x73, 0x71, 0xd9, 0x42, 0xcb, 0x5a, 0x61, 0xc7, - 0x59, 0xd5, 0xef, 0xe2, 0x4b, 0xe2, 0x3d, 0x06, 0xaa, 0x7c, 0xb1, 0xe8, 0x8e, 0x1b, 0x0d, 0xa4, 0x3c, 0x7e, 0x8d, - 0xfa, 0xe3, 0x01, 0xbe, 0x05, 0x14, 0xc2, 0x35, 0x8c, 0xc2, 0xb5, 0x39, 0x76, 0xdc, 0x1c, 0x1b, 0x0d, 0xb9, 0x46, - 0xdd, 0xa0, 0xf2, 0xc2, 0x55, 0x5e, 0xaf, 0x2d, 0x64, 0x36, 0x31, 0xee, 0x1c, 0x99, 0x14, 0x30, 0x04, 0x23, 0x84, - 0xbc, 0x92, 0x68, 0x67, 0xb3, 0xd0, 0x28, 0x54, 0x37, 0xbb, 0x17, 0x28, 0xaa, 0x3d, 0x3d, 0x62, 0x80, 0x05, 0x54, - 0x2d, 0xd5, 0xc8, 0x53, 0x8d, 0x47, 0x8d, 0xb6, 0x41, 0xf7, 0x66, 0xbb, 0x5b, 0x6f, 0xec, 0x7e, 0xd5, 0x18, 0x1e, - 0x35, 0xc8, 0xb4, 0xda, 0xe1, 0x6b, 0xd9, 0x68, 0xac, 0xeb, 0xf7, 0xa5, 0x7e, 0x13, 0xd7, 0xee, 0x2f, 0x9e, 0x6e, - 0x99, 0x78, 0xf8, 0xd3, 0xb7, 0x3a, 0x6f, 0x45, 0xc2, 0x85, 0x60, 0x05, 0x9c, 0xb0, 0x44, 0x63, 0xb1, 0x5e, 0x97, - 0xa7, 0xfe, 0xef, 0xda, 0xda, 0x8c, 0x11, 0x0e, 0x74, 0xc8, 0x48, 0x6d, 0x58, 0xe2, 0x02, 0x53, 0x43, 0x45, 0x08, - 0x21, 0x1f, 0xb4, 0x37, 0x8f, 0xd1, 0x86, 0x24, 0x65, 0x24, 0x38, 0xbb, 0x63, 0x45, 0x58, 0x72, 0x7d, 0xef, 0xb1, - 0xfc, 0xae, 0x48, 0xd7, 0x17, 0x83, 0xd4, 0x14, 0xcb, 0x1d, 0x21, 0xcb, 0xc9, 0x17, 0x90, 0x73, 0xca, 0x0b, 0x96, - 0xc4, 0x10, 0xc4, 0x27, 0xbc, 0x60, 0x86, 0x71, 0xbf, 0xe7, 0xe5, 0xc6, 0xac, 0xce, 0x69, 0x66, 0xa1, 0xf6, 0x07, - 0xa0, 0x99, 0x83, 0x72, 0x48, 0x92, 0xad, 0x62, 0xd7, 0xf7, 0x1e, 0xbe, 0xde, 0x25, 0x43, 0xaf, 0x56, 0x4e, 0x7a, - 0xce, 0x80, 0xf5, 0xc1, 0x79, 0x35, 0xd4, 0xcc, 0xfd, 0x48, 0xe3, 0xcc, 0x30, 0x51, 0x79, 0xcc, 0x01, 0x99, 0xae, - 0xef, 0x3d, 0x7c, 0x17, 0x73, 0xa3, 0x9b, 0x42, 0x38, 0x9c, 0x77, 0x5c, 0x90, 0x98, 0x12, 0x86, 0xec, 0xe4, 0x4b, - 0x3a, 0x56, 0x04, 0xa7, 0x7b, 0x4a, 0x4d, 0x26, 0x88, 0x1d, 0x7d, 0x31, 0x20, 0x99, 0x03, 0x01, 0xc9, 0x10, 0xce, - 0x6a, 0x72, 0x1d, 0x31, 0x6b, 0x60, 0x3a, 0xbb, 0x82, 0xc5, 0x48, 0x2c, 0x7b, 0x88, 0x70, 0x66, 0xba, 0xd5, 0x6b, - 0x7b, 0x9c, 0x28, 0xba, 0x69, 0xe8, 0x56, 0xc9, 0xb3, 0xef, 0x41, 0xf0, 0xf2, 0x1f, 0xaf, 0x5c, 0xdb, 0x65, 0xc2, - 0x13, 0x6f, 0x91, 0x76, 0x7d, 0xef, 0xe1, 0xaf, 0xce, 0x28, 0x6d, 0x4e, 0x3d, 0xf9, 0xdf, 0x92, 0x51, 0x1f, 0xfe, - 0x9a, 0x54, 0xb9, 0xa6, 0xf0, 0xf5, 0xbd, 0x87, 0xbf, 0xef, 0x2a, 0x06, 0xe9, 0xeb, 0x45, 0xa5, 0x24, 0x30, 0xe3, - 0x5b, 0xb2, 0x3c, 0x5d, 0xba, 0xb3, 0x22, 0x15, 0x6b, 0x6c, 0x4e, 0xa8, 0x54, 0xad, 0x4b, 0xdd, 0xca, 0x13, 0x2c, - 0x89, 0xb9, 0x4a, 0xaa, 0x2f, 0x9b, 0x43, 0x63, 0x2e, 0xc5, 0x55, 0x26, 0xe7, 0xec, 0x1b, 0xf7, 0x4b, 0x4f, 0x35, - 0x4a, 0xf8, 0x0c, 0x0c, 0x71, 0xcc, 0xd8, 0x05, 0xde, 0x6f, 0xa1, 0xee, 0xc6, 0x79, 0x26, 0x0d, 0xa2, 0x16, 0xf5, - 0xc3, 0x06, 0x53, 0xd2, 0xc2, 0x19, 0x69, 0xe1, 0x9c, 0xa8, 0x7e, 0xcb, 0x9e, 0x18, 0xdd, 0xbc, 0x6c, 0xda, 0x9e, - 0x3b, 0xb0, 0xdd, 0x73, 0xbb, 0x6f, 0xed, 0xa1, 0x3c, 0xed, 0xe6, 0x46, 0x7f, 0x69, 0x0e, 0xfa, 0xa9, 0x41, 0x8d, - 0x27, 0x2c, 0x2e, 0x70, 0x61, 0x5a, 0xbe, 0xe2, 0xc3, 0x1c, 0xec, 0x54, 0x60, 0x66, 0x58, 0xa3, 0xb4, 0x2c, 0xdb, - 0x76, 0x65, 0xf3, 0xc4, 0xac, 0x55, 0x81, 0xf3, 0x04, 0x48, 0x39, 0xce, 0x9d, 0x5d, 0x8f, 0xda, 0xae, 0x72, 0x76, - 0x70, 0x10, 0xbb, 0x4a, 0x34, 0x2e, 0x7c, 0x7e, 0x75, 0x03, 0xf8, 0xde, 0x52, 0x8d, 0x29, 0x32, 0x13, 0x68, 0x34, - 0xb2, 0xc1, 0x9a, 0xee, 0x13, 0x12, 0xe7, 0x75, 0x28, 0xfa, 0xd1, 0x1b, 0x66, 0x70, 0x03, 0x00, 0x8d, 0x46, 0x79, - 0xdd, 0xbb, 0x01, 0xb1, 0xa7, 0x1a, 0xcb, 0xf5, 0x97, 0xb8, 0xb4, 0x26, 0x6a, 0x6d, 0xd9, 0x61, 0xf9, 0x51, 0x20, - 0x11, 0xe2, 0xae, 0xf0, 0xf3, 0x09, 0xb6, 0x86, 0x80, 0x72, 0x2f, 0x9c, 0x0d, 0x04, 0x36, 0x56, 0x5b, 0xae, 0x90, - 0x27, 0x6d, 0x1d, 0x94, 0xfa, 0x42, 0x70, 0xc1, 0x05, 0x85, 0x1a, 0x6b, 0x87, 0xe5, 0x4f, 0xd8, 0xb6, 0x39, 0x27, - 0x56, 0xc8, 0x69, 0xcb, 0xcc, 0x30, 0x0c, 0xc0, 0x3a, 0x25, 0x60, 0x9e, 0x93, 0x97, 0xdf, 0x46, 0xfd, 0x87, 0x01, - 0xea, 0x3f, 0x22, 0x2c, 0xd8, 0x06, 0x56, 0x57, 0x92, 0x48, 0xa7, 0xa0, 0x50, 0x3e, 0xeb, 0xf1, 0x9c, 0x80, 0x36, - 0xae, 0x0e, 0xd5, 0xda, 0x15, 0xe5, 0x37, 0x28, 0x4b, 0xb8, 0x53, 0x8c, 0x3e, 0x13, 0xfb, 0xfb, 0xe4, 0xb8, 0xba, - 0xa0, 0x83, 0xae, 0x77, 0x29, 0x07, 0x43, 0x52, 0xf8, 0xf0, 0xf7, 0xef, 0xdf, 0xad, 0x3e, 0x9e, 0x6f, 0xef, 0xe0, - 0xc0, 0xac, 0x14, 0x66, 0x1d, 0x6c, 0xe0, 0xba, 0x91, 0x29, 0xf4, 0x5f, 0xde, 0x89, 0xd7, 0xa9, 0xd0, 0xc6, 0x66, - 0xf4, 0xc7, 0x21, 0x8c, 0xb6, 0xdd, 0x36, 0x25, 0x58, 0xd0, 0x2c, 0xd0, 0x25, 0x6b, 0xdc, 0x4a, 0x8b, 0x6f, 0x90, - 0x91, 0x87, 0xa6, 0x00, 0x13, 0xa3, 0xdd, 0xd9, 0x8f, 0xd6, 0x0e, 0x4f, 0xec, 0xd0, 0xd0, 0xd2, 0x10, 0x42, 0x8b, - 0xf7, 0x80, 0x39, 0xf6, 0x88, 0x00, 0x10, 0xbd, 0x34, 0x90, 0xaa, 0x40, 0x16, 0x45, 0x95, 0x22, 0xff, 0xf9, 0x3e, - 0x21, 0x2f, 0x2b, 0x45, 0xe6, 0xdb, 0xca, 0x98, 0x0b, 0x10, 0x03, 0xa5, 0x70, 0x91, 0x50, 0x26, 0xd8, 0xcb, 0xd0, - 0x0f, 0xda, 0x97, 0x37, 0xd2, 0x66, 0x52, 0x71, 0xe3, 0xc1, 0x4d, 0xa9, 0x51, 0xf1, 0xd9, 0x7c, 0x0f, 0x89, 0x8d, - 0xdc, 0x7b, 0x90, 0xcb, 0xa8, 0x19, 0x24, 0x7c, 0xbf, 0x33, 0xa5, 0x7d, 0xbb, 0xeb, 0xcf, 0x9b, 0x16, 0x31, 0x1b, - 0xeb, 0x92, 0x70, 0xa1, 0x58, 0xa1, 0x1f, 0xb1, 0xb1, 0x2c, 0xe0, 0xfe, 0xa3, 0x04, 0x0b, 0x5a, 0xdf, 0x0b, 0x74, - 0x80, 0x66, 0x82, 0xc1, 0xa5, 0xc3, 0xc6, 0x0c, 0xcd, 0xaf, 0xcf, 0xe6, 0x0e, 0xfc, 0x7a, 0xb3, 0xd6, 0xcb, 0x83, - 0x83, 0x2f, 0xac, 0x02, 0x94, 0x1b, 0xa6, 0x19, 0x46, 0x40, 0xbc, 0x2c, 0x97, 0xe3, 0x6e, 0x86, 0xef, 0xc5, 0x95, - 0xca, 0xc0, 0x13, 0x8e, 0x90, 0x08, 0x3d, 0x27, 0x7a, 0x3d, 0xd9, 0xa4, 0xf7, 0x4e, 0x9b, 0x21, 0x42, 0xb1, 0x06, - 0xc8, 0x3d, 0xc8, 0xe5, 0x56, 0xc9, 0xa4, 0x2a, 0x5b, 0xdb, 0x72, 0x10, 0x8f, 0x01, 0x5c, 0xb1, 0x11, 0x52, 0x02, - 0x34, 0xdc, 0x2d, 0xb4, 0x3c, 0x97, 0xc0, 0xfe, 0x63, 0x95, 0x80, 0x48, 0x8b, 0x6a, 0x1b, 0x17, 0x21, 0x6c, 0x4d, - 0x7d, 0x02, 0xe3, 0x84, 0x87, 0xcf, 0x77, 0x69, 0xa8, 0x3d, 0x6a, 0x33, 0x73, 0x06, 0x41, 0x09, 0x89, 0xca, 0x0a, - 0xc9, 0x97, 0x58, 0x38, 0x6e, 0xce, 0xdf, 0xc3, 0x01, 0x29, 0x56, 0x34, 0xb6, 0x77, 0x5b, 0x70, 0x7c, 0x14, 0xc9, - 0x22, 0xae, 0x75, 0xdd, 0x2d, 0x4c, 0x35, 0xec, 0x40, 0x47, 0x43, 0x38, 0x15, 0xe6, 0x9e, 0xf0, 0x71, 0x45, 0x52, - 0x7f, 0xb6, 0x26, 0xda, 0xda, 0x13, 0xc3, 0xca, 0x34, 0x25, 0x98, 0xff, 0xcf, 0xd6, 0xea, 0xba, 0x2c, 0x84, 0x99, - 0x19, 0xc6, 0x8d, 0x5d, 0x05, 0xb6, 0x06, 0x1c, 0x5b, 0xfe, 0x2d, 0x83, 0x45, 0xf5, 0x4a, 0x71, 0xd3, 0x69, 0xc0, - 0x04, 0xbc, 0x05, 0xeb, 0x99, 0xcd, 0xad, 0xff, 0xdc, 0x1c, 0x8c, 0x02, 0xab, 0x1a, 0x81, 0x97, 0x86, 0xc0, 0x23, - 0x60, 0xdc, 0xbc, 0x69, 0x79, 0xcf, 0x19, 0xd1, 0x08, 0x7f, 0xe2, 0x39, 0x3c, 0xb3, 0x2c, 0xf7, 0xd6, 0xc7, 0xc6, - 0x8a, 0xa4, 0x82, 0x80, 0x6d, 0x11, 0x76, 0x44, 0x5e, 0x22, 0xac, 0x1a, 0x8d, 0xae, 0xba, 0x60, 0x95, 0x56, 0xa5, - 0x1a, 0xa6, 0x80, 0x5b, 0x62, 0xc0, 0xfb, 0xda, 0x89, 0x0a, 0x86, 0x04, 0xde, 0xfa, 0x5b, 0x81, 0xfa, 0xfe, 0xe1, - 0xdb, 0x38, 0xa4, 0x6f, 0x61, 0xd9, 0xf2, 0x22, 0x16, 0xa6, 0x14, 0x57, 0x77, 0x38, 0x6f, 0xbe, 0x6f, 0x36, 0x02, - 0xe3, 0xde, 0x6f, 0x63, 0xb0, 0x71, 0x43, 0x5d, 0x6d, 0x49, 0x43, 0xb9, 0x09, 0xbb, 0xa8, 0xb2, 0x77, 0x0c, 0x3b, - 0xeb, 0xea, 0x4a, 0xda, 0xd5, 0x44, 0xad, 0xd7, 0x8a, 0x55, 0x46, 0x03, 0x1b, 0x86, 0x9d, 0xe6, 0x98, 0xd9, 0x56, - 0xe0, 0x3f, 0x9e, 0x13, 0x8d, 0x03, 0x64, 0x7d, 0xf3, 0xad, 0xeb, 0x94, 0x6a, 0x98, 0xb0, 0xbd, 0xdd, 0xf9, 0xf8, - 0x98, 0xef, 0x3a, 0x1f, 0xb1, 0x74, 0x5b, 0xdf, 0x9c, 0x8d, 0xed, 0x7f, 0xe3, 0x6c, 0x74, 0x6a, 0x7b, 0x7f, 0x3c, - 0x02, 0x77, 0x52, 0x3b, 0x1e, 0xeb, 0x6b, 0x4a, 0x24, 0x16, 0x6e, 0x39, 0x2e, 0x3b, 0xab, 0x95, 0xe8, 0xb7, 0x40, - 0xed, 0x14, 0x45, 0xf0, 0xb3, 0x6d, 0x7f, 0x06, 0x24, 0xd9, 0xea, 0x90, 0x63, 0x51, 0x8a, 0x32, 0x28, 0x01, 0x03, - 0xea, 0xd8, 0xd8, 0x7a, 0x19, 0xc4, 0x76, 0x38, 0xe4, 0xb0, 0x9c, 0x88, 0xf2, 0xea, 0x0a, 0x46, 0x6c, 0x8e, 0x0d, - 0x27, 0x60, 0xc6, 0x3b, 0xad, 0x0a, 0xbd, 0xf8, 0xf9, 0xaf, 0x99, 0xd3, 0xda, 0x11, 0x63, 0x39, 0x89, 0x9a, 0x15, - 0x83, 0x1b, 0x81, 0x63, 0x18, 0xf7, 0x8d, 0x84, 0x5a, 0x9d, 0xea, 0xa8, 0x76, 0x24, 0xe1, 0x16, 0xa8, 0xdd, 0xf6, - 0xcd, 0xb9, 0xb4, 0x5a, 0xed, 0x3c, 0x58, 0x70, 0x11, 0xe0, 0xf6, 0x73, 0xa2, 0x6b, 0x24, 0x85, 0x12, 0x27, 0x41, - 0xe1, 0xdc, 0xa0, 0xaa, 0x26, 0xb2, 0xdf, 0x1a, 0x00, 0x4f, 0xda, 0xcd, 0x2e, 0x64, 0x25, 0x24, 0x67, 0x8d, 0x06, - 0xca, 0xcb, 0x8e, 0x69, 0x5f, 0x34, 0xb2, 0x01, 0x66, 0x38, 0xb3, 0x02, 0x0b, 0x9c, 0x5e, 0x71, 0x5e, 0x75, 0xdd, - 0xcf, 0x06, 0x08, 0x17, 0xab, 0x55, 0x6c, 0x87, 0x96, 0xa3, 0xd5, 0x2a, 0x0f, 0x87, 0x66, 0xf2, 0xa1, 0xe2, 0xcb, - 0x9e, 0x26, 0x2f, 0xcd, 0x79, 0xf8, 0x12, 0x06, 0xd9, 0x20, 0x71, 0xee, 0x54, 0x82, 0x39, 0x68, 0xae, 0x1a, 0xb2, - 0x9f, 0x35, 0xda, 0x83, 0x80, 0x86, 0xf5, 0xb3, 0x01, 0xc9, 0xd7, 0x60, 0x39, 0xab, 0xdc, 0x81, 0xf9, 0x37, 0x1c, - 0x6c, 0x7f, 0x9b, 0x73, 0xc6, 0x36, 0x18, 0xae, 0xc9, 0xa6, 0xca, 0xa0, 0xc4, 0x2b, 0xb7, 0xb8, 0xbe, 0x5c, 0xcd, - 0xc0, 0xa2, 0x2c, 0x84, 0xdd, 0x35, 0x73, 0x0f, 0x84, 0xff, 0x12, 0xdb, 0x25, 0x2d, 0x8d, 0xb8, 0x37, 0x10, 0xdf, - 0xdb, 0x6e, 0x27, 0x49, 0x42, 0x8b, 0x89, 0xb9, 0x12, 0xf1, 0x37, 0xbc, 0x66, 0x0f, 0x1c, 0xbb, 0x71, 0x06, 0x3d, - 0xf7, 0xcb, 0xce, 0x06, 0xc4, 0x8e, 0xdf, 0x33, 0x3b, 0xde, 0x71, 0xa5, 0xa0, 0xbb, 0x75, 0x11, 0x76, 0x30, 0xf4, - 0x7f, 0x79, 0x30, 0x27, 0x6e, 0x30, 0x16, 0x4d, 0x36, 0xe0, 0xf6, 0x0d, 0x78, 0x14, 0x74, 0x03, 0x6e, 0xdf, 0x86, - 0xaf, 0x87, 0x56, 0xf6, 0xcd, 0x01, 0x06, 0x64, 0xc2, 0x8e, 0xb4, 0x4a, 0x08, 0x86, 0x79, 0xba, 0xc9, 0x91, 0x59, - 0xb2, 0x0a, 0x87, 0xab, 0x26, 0xb1, 0xd8, 0xd8, 0x0b, 0x15, 0x93, 0x1a, 0x08, 0xc6, 0x22, 0x7d, 0x89, 0x42, 0xa5, - 0x41, 0xdd, 0x38, 0x06, 0xb0, 0xca, 0x69, 0xeb, 0x5f, 0x1e, 0x1c, 0x80, 0xd0, 0x00, 0xac, 0x5d, 0x92, 0xd1, 0xb9, - 0x5e, 0x14, 0xc0, 0x5f, 0x29, 0xff, 0x1b, 0x92, 0xc1, 0xed, 0xc4, 0xa4, 0xc1, 0x0f, 0x48, 0x98, 0x53, 0xa5, 0xf8, - 0x17, 0x9b, 0xe6, 0x7e, 0xe3, 0x82, 0x78, 0x8c, 0x56, 0x96, 0x53, 0x94, 0xa8, 0x2b, 0x1d, 0xba, 0xd6, 0x21, 0xf7, - 0xf4, 0x0b, 0x13, 0xfa, 0x25, 0x57, 0x9a, 0x09, 0x00, 0x40, 0x85, 0x78, 0x30, 0x25, 0x85, 0x60, 0xeb, 0xd6, 0x6a, - 0xd1, 0xd1, 0xe8, 0xbb, 0x55, 0x74, 0x9d, 0x2d, 0x9a, 0x52, 0x31, 0xca, 0x6d, 0x27, 0xa1, 0xcd, 0xa4, 0xb7, 0x13, - 0x2d, 0x4b, 0x86, 0x16, 0x3b, 0x15, 0xfb, 0x61, 0x68, 0x7d, 0x2c, 0x88, 0x3f, 0x17, 0xfc, 0x59, 0xfa, 0x5d, 0x3e, - 0x06, 0xae, 0xd4, 0xbf, 0xb1, 0x0a, 0xe1, 0x4c, 0xb0, 0x0e, 0xc8, 0x6b, 0x52, 0x1f, 0xa7, 0x47, 0x9d, 0x7c, 0x4b, - 0xb9, 0x50, 0x1a, 0x85, 0x6d, 0x9c, 0x14, 0x06, 0x53, 0xce, 0xbe, 0x2d, 0x71, 0xfd, 0xea, 0x8f, 0x11, 0x7f, 0x74, - 0x88, 0x7f, 0x97, 0x4a, 0xa3, 0x65, 0x89, 0x60, 0xc8, 0xef, 0x48, 0xad, 0xe0, 0x2a, 0x36, 0xe7, 0xfa, 0xb9, 0x9e, - 0xe5, 0x1b, 0x9e, 0x38, 0x5d, 0xad, 0x4a, 0xa9, 0x40, 0xc5, 0x37, 0x0c, 0x3f, 0x61, 0x70, 0x6f, 0xfc, 0x8c, 0x07, - 0x55, 0xb6, 0xef, 0x8b, 0x9f, 0x05, 0xf7, 0xc5, 0xcf, 0x78, 0xba, 0x5d, 0x34, 0xb8, 0x27, 0xee, 0x24, 0xe7, 0x49, - 0x2b, 0xf2, 0x7c, 0xd4, 0x94, 0x56, 0xfe, 0x95, 0x76, 0x6b, 0xe0, 0xca, 0x26, 0x0e, 0x8c, 0xf3, 0xea, 0x22, 0x14, - 0x73, 0xe6, 0x8c, 0x96, 0xc3, 0xff, 0xd6, 0x3a, 0xb9, 0x93, 0x47, 0x5a, 0x29, 0xe4, 0x0d, 0x2d, 0xf4, 0x3d, 0xd8, - 0x70, 0xc5, 0x96, 0x0f, 0x20, 0x25, 0xa0, 0x6c, 0xfb, 0xf7, 0xba, 0x08, 0xc4, 0x71, 0x65, 0x9d, 0x8f, 0xc2, 0xf6, - 0x49, 0x51, 0x72, 0x75, 0x75, 0x21, 0xe4, 0xd6, 0x68, 0x09, 0x10, 0xa6, 0xde, 0x35, 0x8f, 0x39, 0x9a, 0xcc, 0xd2, - 0xe5, 0xba, 0x54, 0x1d, 0x14, 0x96, 0xab, 0xe3, 0x08, 0x17, 0x6b, 0x73, 0x83, 0xfe, 0x8a, 0xe3, 0xbf, 0xb9, 0xa3, - 0x91, 0x9f, 0x4a, 0x0a, 0xf4, 0x68, 0xb7, 0xaf, 0xcd, 0x0e, 0x12, 0x69, 0xe7, 0x50, 0x5a, 0x0a, 0x00, 0x56, 0x1b, - 0x7c, 0x5d, 0x7b, 0x9c, 0x7a, 0x22, 0xdd, 0x6c, 0xbe, 0x69, 0x08, 0x8b, 0x59, 0x69, 0xc1, 0x63, 0xba, 0xd9, 0x61, - 0x39, 0xea, 0x65, 0x71, 0x5d, 0xee, 0xb1, 0x5a, 0xbf, 0xe8, 0x1b, 0xa0, 0xac, 0x0c, 0xd1, 0x56, 0xab, 0xb8, 0x0e, - 0x6f, 0x22, 0x82, 0x6b, 0x10, 0x84, 0x45, 0x60, 0xc0, 0x51, 0x63, 0xbc, 0x6d, 0x9d, 0x18, 0x6d, 0xda, 0x2f, 0x79, - 0xd6, 0xbd, 0x36, 0x8e, 0x50, 0xd1, 0x60, 0xab, 0x87, 0x9a, 0x07, 0x6c, 0x67, 0x57, 0x76, 0x14, 0x40, 0x68, 0x4a, - 0xbd, 0x71, 0x6e, 0x65, 0x45, 0xbb, 0x03, 0xbe, 0xe8, 0x3b, 0xe6, 0xb9, 0x0e, 0x74, 0xdb, 0xf9, 0x81, 0x6d, 0xd3, - 0x13, 0xf9, 0x2d, 0xdb, 0xa6, 0x1a, 0x27, 0xbc, 0xdf, 0x42, 0xdf, 0x37, 0x84, 0xb5, 0x7d, 0xed, 0x2e, 0xf2, 0xbf, - 0xd0, 0x5d, 0x1b, 0xd0, 0xd3, 0x82, 0xd9, 0xd3, 0x98, 0x0f, 0x7a, 0xbd, 0xfe, 0x54, 0xfa, 0x2f, 0x18, 0x5b, 0xa1, - 0x4f, 0x76, 0x17, 0x38, 0xb1, 0xd2, 0x38, 0x04, 0xc7, 0xaf, 0x38, 0x99, 0xe4, 0x72, 0x48, 0xf3, 0x77, 0xd0, 0x63, - 0x95, 0xfb, 0xfc, 0x6e, 0x54, 0x50, 0xcd, 0x1c, 0xad, 0xa9, 0x46, 0xf1, 0x8a, 0x07, 0xc3, 0x78, 0xc5, 0x2d, 0xe5, - 0xae, 0x5a, 0xc0, 0xcb, 0x97, 0x65, 0x13, 0xe9, 0xa7, 0x75, 0x29, 0x83, 0xa9, 0xdd, 0xbd, 0x6c, 0x92, 0x34, 0x56, - 0x92, 0x34, 0xa6, 0xe2, 0xcd, 0xa6, 0xe2, 0xf8, 0xef, 0x6f, 0x0c, 0x76, 0x9b, 0xcc, 0xfd, 0x1d, 0x90, 0xb9, 0xbf, - 0x79, 0xfa, 0xdd, 0x5a, 0x01, 0xc5, 0x3b, 0x4e, 0x8e, 0x8d, 0x65, 0x8c, 0x1d, 0xf5, 0x5b, 0x0d, 0x06, 0x0d, 0x9a, - 0x5c, 0x06, 0xde, 0x0e, 0xd5, 0xe9, 0xe5, 0xed, 0x8f, 0xe2, 0x6c, 0xa1, 0xb4, 0x9c, 0xb9, 0x46, 0x95, 0xf3, 0x71, - 0x32, 0x99, 0xa0, 0xc0, 0x36, 0x77, 0xf8, 0x69, 0xdd, 0x8d, 0x6c, 0xf9, 0x99, 0x8b, 0x51, 0xaa, 0xb0, 0x3b, 0x5b, - 0x54, 0x2a, 0xd7, 0xc4, 0x9b, 0x39, 0x6f, 0xe7, 0xe1, 0x31, 0x17, 0x5c, 0x4d, 0x59, 0x11, 0x17, 0x68, 0xf9, 0xad, - 0xce, 0x0a, 0xb8, 0xcd, 0xb1, 0x9d, 0xe1, 0x51, 0x69, 0x39, 0xa0, 0x13, 0x68, 0x0d, 0x74, 0x46, 0x33, 0xa6, 0xa7, - 0x72, 0x04, 0x86, 0x2f, 0xc9, 0xa8, 0x74, 0xa7, 0x3a, 0x38, 0xd8, 0x8f, 0x23, 0xa3, 0xbf, 0x00, 0x1f, 0xf4, 0x30, - 0x07, 0xf5, 0x96, 0xe0, 0x18, 0x54, 0x75, 0xcd, 0xd0, 0x92, 0x6d, 0xfa, 0xd0, 0xe8, 0xe4, 0x33, 0xbb, 0xc3, 0x1c, - 0xad, 0xd7, 0xa9, 0x1d, 0x75, 0x34, 0xe6, 0x2c, 0x1f, 0x45, 0xf8, 0x33, 0xbb, 0x4b, 0x4b, 0xb7, 0x75, 0xe3, 0x65, - 0x6d, 0x16, 0x31, 0x92, 0x37, 0x22, 0xc2, 0x55, 0x27, 0xe9, 0x72, 0x8d, 0x65, 0xc1, 0x27, 0x80, 0xa3, 0xbf, 0xb0, - 0xbb, 0xd4, 0xb5, 0x17, 0xb8, 0x0a, 0xa2, 0xa5, 0x07, 0x7d, 0x12, 0x24, 0x87, 0xcb, 0xe0, 0x04, 0x8e, 0xbe, 0xa9, - 0x3b, 0x20, 0xb5, 0x72, 0x95, 0x08, 0x89, 0xd0, 0xfa, 0xdf, 0x9d, 0x0a, 0x5e, 0x84, 0xe7, 0x9c, 0xae, 0x59, 0xdc, - 0x6e, 0x54, 0x62, 0x50, 0xa1, 0xb2, 0x20, 0xf9, 0x18, 0x73, 0xbf, 0xfb, 0x9c, 0xf7, 0x43, 0xa0, 0x33, 0x5b, 0x50, - 0xd7, 0x68, 0x3a, 0x32, 0xbf, 0x50, 0x75, 0x07, 0x35, 0xd3, 0x55, 0xc5, 0xbd, 0x8f, 0x31, 0x00, 0x1e, 0xac, 0x65, - 0xa8, 0x71, 0x08, 0x5d, 0x7b, 0x33, 0xd5, 0x31, 0x25, 0xf1, 0xd2, 0xcf, 0x21, 0xe5, 0x21, 0x18, 0xf5, 0x1a, 0xd0, - 0xd0, 0x21, 0x98, 0xb5, 0x3c, 0xe4, 0xe3, 0x58, 0x6c, 0x9d, 0xa1, 0xd2, 0x9c, 0xa1, 0x49, 0x00, 0xf2, 0x6f, 0x9c, - 0x99, 0xcc, 0x40, 0xc3, 0xf0, 0x96, 0xe6, 0x00, 0x74, 0xab, 0xeb, 0x70, 0x28, 0x5c, 0xd1, 0xd2, 0x79, 0xcf, 0x2e, - 0xba, 0xac, 0x0d, 0x2b, 0x36, 0xed, 0xa0, 0x75, 0x0a, 0x53, 0x62, 0xb6, 0xc0, 0xda, 0xeb, 0x7d, 0xb8, 0xb7, 0xab, - 0x8d, 0x8b, 0xc4, 0x4f, 0x8b, 0x78, 0x98, 0xc4, 0x14, 0x2d, 0x79, 0x4c, 0xb1, 0x04, 0x3b, 0xc8, 0x62, 0x5d, 0x8e, - 0x9f, 0x85, 0xcb, 0x51, 0xb3, 0x92, 0xde, 0xed, 0x60, 0x08, 0x5c, 0xbe, 0x06, 0xdb, 0x50, 0xcc, 0x3d, 0x61, 0xe1, - 0xb1, 0xf1, 0xf4, 0x0b, 0xd6, 0x6d, 0x6e, 0x17, 0xc4, 0xaf, 0xc0, 0x98, 0xc6, 0xcb, 0x60, 0x16, 0xa1, 0x53, 0xb9, - 0x73, 0x38, 0x74, 0xd7, 0x84, 0x95, 0xf1, 0x6a, 0xac, 0xc8, 0xc6, 0xd1, 0xf3, 0x7d, 0x1b, 0xcf, 0x7f, 0x16, 0xac, - 0xb8, 0xbb, 0x62, 0x60, 0x63, 0x2d, 0xc1, 0xdd, 0xb8, 0x5a, 0x86, 0xca, 0x40, 0xbe, 0x27, 0x0d, 0xeb, 0xb2, 0xc6, - 0xdf, 0x8d, 0x8a, 0xb1, 0x36, 0xf7, 0x94, 0x81, 0xb6, 0xc6, 0x6e, 0x17, 0xf6, 0x4d, 0xd7, 0x4d, 0xd6, 0x35, 0x8a, - 0xb8, 0x0a, 0xd2, 0xee, 0x6e, 0x01, 0x17, 0xa1, 0x3f, 0x6c, 0x5f, 0x0d, 0x36, 0x55, 0x37, 0x90, 0x04, 0xd7, 0x7e, - 0xf2, 0xdb, 0x53, 0xdd, 0x65, 0xad, 0xfb, 0xed, 0xa9, 0xd6, 0x2e, 0x0b, 0x8d, 0x21, 0x11, 0x76, 0xfd, 0x94, 0xfe, - 0xd3, 0x62, 0xbd, 0x46, 0x6b, 0x18, 0xde, 0x7b, 0xde, 0x8d, 0xe3, 0xf7, 0xde, 0x42, 0x31, 0x81, 0x8b, 0xdc, 0xab, - 0x5c, 0x7a, 0x42, 0x5e, 0x8d, 0xe0, 0x3d, 0xdf, 0x1a, 0xc2, 0x7b, 0x1e, 0x38, 0xbd, 0x82, 0xd4, 0x34, 0x11, 0x6c, - 0xe4, 0xe9, 0x27, 0xb2, 0x48, 0x68, 0xf8, 0xb8, 0xd7, 0x9c, 0x70, 0xfd, 0x57, 0x0a, 0xfc, 0x17, 0x1e, 0x2e, 0xb4, - 0x96, 0x02, 0x73, 0x31, 0x5f, 0x68, 0xac, 0xcc, 0xe8, 0x97, 0x63, 0x29, 0x74, 0x73, 0x4c, 0x67, 0x3c, 0xbf, 0x4b, - 0x17, 0xbc, 0x39, 0x93, 0x42, 0xaa, 0x39, 0xcd, 0x18, 0x56, 0x77, 0x4a, 0xb3, 0x59, 0x73, 0xc1, 0xf1, 0x73, 0x96, - 0x7f, 0x61, 0x9a, 0x67, 0x14, 0xbf, 0x95, 0x43, 0xa9, 0x25, 0x7e, 0x7d, 0x7b, 0x37, 0x61, 0x02, 0xff, 0x3e, 0x5c, - 0x08, 0xbd, 0xc0, 0x8a, 0x0a, 0xd5, 0x54, 0xac, 0xe0, 0xe3, 0x6e, 0xb3, 0x39, 0x2f, 0xf8, 0x8c, 0x16, 0x77, 0xcd, - 0x4c, 0xe6, 0xb2, 0x48, 0xff, 0xab, 0x75, 0x4c, 0x1f, 0x8c, 0x4f, 0xba, 0xba, 0xa0, 0x42, 0x71, 0x58, 0x98, 0x94, - 0xe6, 0xf9, 0xde, 0xf1, 0x69, 0x6b, 0xa6, 0xf6, 0xed, 0x85, 0x1f, 0x15, 0x7a, 0xfd, 0x17, 0xfe, 0x20, 0x61, 0x94, - 0xc9, 0x50, 0x0b, 0x37, 0xc8, 0x65, 0xb6, 0x28, 0x94, 0x2c, 0xd2, 0xb9, 0xe4, 0x42, 0xb3, 0xa2, 0x3b, 0x94, 0xc5, - 0x88, 0x15, 0xcd, 0x82, 0x8e, 0xf8, 0x42, 0xa5, 0x27, 0xf3, 0xdb, 0x6e, 0xbd, 0x07, 0x9b, 0x9f, 0x0a, 0x29, 0x58, - 0x17, 0xf8, 0x8d, 0x49, 0x21, 0x17, 0x62, 0xe4, 0x86, 0xb1, 0x10, 0x8a, 0xe9, 0xee, 0x9c, 0x8e, 0xc0, 0x0e, 0x38, - 0x3d, 0x9f, 0xdf, 0x76, 0xcd, 0xac, 0x6f, 0x18, 0x9f, 0x4c, 0x75, 0x7a, 0xda, 0x6a, 0xd9, 0x6f, 0xc5, 0xbf, 0xb2, - 0xb4, 0xdd, 0x49, 0x3a, 0xa7, 0xf3, 0x5b, 0xe0, 0xe0, 0x35, 0x2b, 0x9a, 0x00, 0x0b, 0xa8, 0xd4, 0x4e, 0x5a, 0x0f, - 0x8e, 0xef, 0x43, 0x06, 0xd8, 0x38, 0x34, 0xcd, 0x84, 0xc0, 0xd8, 0x3d, 0x5d, 0xcc, 0xe7, 0xac, 0x00, 0x2f, 0xfa, - 0xee, 0x8c, 0x16, 0x13, 0x2e, 0x9a, 0x85, 0x69, 0xb4, 0x79, 0x3e, 0xbf, 0x5d, 0xc3, 0x7c, 0x52, 0x6b, 0xb6, 0xea, - 0xa6, 0xe5, 0xbe, 0x96, 0xc1, 0x10, 0x4d, 0x4c, 0x9a, 0xb4, 0x98, 0x0c, 0x69, 0xdc, 0xee, 0xdc, 0xc7, 0xfe, 0x7f, - 0x49, 0x07, 0x05, 0x60, 0x6b, 0x8e, 0x16, 0x85, 0xb9, 0x45, 0x4d, 0xdb, 0xca, 0x36, 0x3b, 0x95, 0x5f, 0x58, 0xe1, - 0x5b, 0x35, 0x1f, 0xcb, 0xad, 0x79, 0xff, 0x27, 0x8d, 0xfe, 0x85, 0x27, 0x14, 0xd6, 0xc0, 0x20, 0x47, 0xdf, 0xc8, - 0x83, 0x30, 0xd3, 0xc1, 0xf2, 0x86, 0x8f, 0xf4, 0x34, 0x6d, 0xb7, 0x5a, 0x3f, 0x54, 0x2b, 0xd6, 0x9d, 0x5a, 0xd0, - 0xb5, 0x0b, 0x36, 0xab, 0xad, 0xe3, 0x8c, 0x96, 0xd8, 0xb6, 0x9c, 0x4b, 0xb7, 0xe4, 0x05, 0xcb, 0x4d, 0x34, 0x99, - 0xb5, 0x43, 0xb9, 0xad, 0x71, 0x72, 0x31, 0x65, 0x05, 0xd7, 0xdd, 0xfa, 0x57, 0xd5, 0xf1, 0xf6, 0xea, 0xaf, 0xad, - 0x1c, 0xba, 0xb4, 0x35, 0xdc, 0xa5, 0xe7, 0x63, 0xf8, 0xd8, 0x5e, 0xfd, 0x2f, 0xb4, 0x88, 0x37, 0x10, 0x13, 0x87, - 0x35, 0xd0, 0x3a, 0x98, 0x73, 0x01, 0x26, 0x99, 0x03, 0xfc, 0x0d, 0x28, 0x64, 0x34, 0xcf, 0x62, 0x18, 0xd1, 0x5e, - 0x73, 0xef, 0xb8, 0x60, 0x33, 0xe4, 0x01, 0x91, 0xdc, 0x3f, 0x2d, 0xd8, 0x6c, 0x9d, 0x98, 0xea, 0x4b, 0x83, 0x22, - 0x34, 0xe7, 0x13, 0x91, 0x66, 0x0c, 0xd0, 0x77, 0x9d, 0x30, 0xa1, 0xb9, 0xbe, 0x6b, 0x16, 0xf2, 0x66, 0x39, 0xe2, - 0x6a, 0x9e, 0xd3, 0xbb, 0x74, 0x9c, 0xb3, 0xdb, 0xae, 0x29, 0xd5, 0xe4, 0x9a, 0xcd, 0x94, 0x2b, 0xdb, 0x85, 0xf4, - 0xe6, 0xc8, 0x9a, 0x4d, 0x00, 0xf4, 0xe4, 0xcd, 0xe6, 0xfe, 0x49, 0x8e, 0xd5, 0x1e, 0xa3, 0x8a, 0x35, 0xe5, 0x42, - 0xef, 0xb5, 0x54, 0x77, 0xc6, 0x45, 0xd3, 0x0d, 0xe4, 0xa4, 0x35, 0xbf, 0xed, 0x6e, 0x43, 0x3e, 0xe8, 0x3f, 0x61, - 0xb7, 0x73, 0x2a, 0x46, 0x6c, 0xb4, 0x0c, 0xaa, 0x75, 0xa0, 0x5e, 0x58, 0x2a, 0x15, 0x7a, 0xda, 0x34, 0xb6, 0x5e, - 0x71, 0x47, 0xa0, 0x6f, 0xa0, 0xd6, 0x83, 0x16, 0xb6, 0xff, 0x9f, 0xb4, 0x51, 0x58, 0x79, 0x0f, 0xc2, 0x2e, 0xf1, - 0xf1, 0x5d, 0x13, 0xfe, 0x2e, 0xc1, 0xb7, 0x88, 0x67, 0x34, 0x77, 0x10, 0x99, 0xf1, 0xd1, 0x28, 0xaf, 0x8d, 0xe8, - 0x32, 0xe8, 0xac, 0x8d, 0x96, 0x30, 0xff, 0xb4, 0xb5, 0xd7, 0xda, 0x33, 0x73, 0x71, 0xdb, 0xfc, 0xe4, 0xe4, 0xfe, - 0xf1, 0x03, 0xd6, 0xcd, 0xb9, 0x60, 0xb5, 0xa9, 0x7e, 0x17, 0xd4, 0x61, 0xc3, 0x1d, 0xd7, 0x70, 0x7b, 0xaf, 0xbd, - 0x77, 0xd2, 0xfa, 0xc1, 0xef, 0xd6, 0x9c, 0x8d, 0x75, 0xda, 0x3e, 0x9b, 0xdf, 0xd6, 0xb7, 0xef, 0xb9, 0x6f, 0xfa, - 0xa6, 0xa0, 0xf3, 0x54, 0x48, 0xf8, 0xd3, 0x85, 0x4d, 0x36, 0xce, 0xe5, 0x4d, 0x3a, 0xe5, 0xa3, 0x11, 0x13, 0xb6, - 0x40, 0x99, 0xc8, 0xf2, 0x9c, 0xcf, 0x15, 0xb7, 0xab, 0xe1, 0x70, 0xf7, 0x74, 0x03, 0xaa, 0xe1, 0x80, 0x8e, 0x83, - 0x01, 0x9d, 0x56, 0x03, 0xaa, 0xfa, 0x0f, 0x47, 0xd8, 0xd9, 0x98, 0xab, 0x29, 0xd5, 0xad, 0x61, 0xd2, 0xdf, 0x0b, - 0xa5, 0x01, 0xe6, 0xde, 0x48, 0xc3, 0x50, 0xf1, 0xe6, 0x90, 0xe9, 0x1b, 0xc6, 0xc4, 0xb7, 0x07, 0x71, 0x99, 0x4a, - 0x91, 0xdf, 0xd9, 0xcf, 0x65, 0xd8, 0x25, 0x5d, 0x68, 0xb9, 0x4e, 0x86, 0x5c, 0xd0, 0xe2, 0xee, 0x5a, 0x31, 0xa1, - 0x64, 0x71, 0x2d, 0xc7, 0xe3, 0xe5, 0xb7, 0x48, 0xcb, 0x7d, 0xb4, 0x4e, 0x14, 0x17, 0x93, 0x9c, 0x59, 0xa2, 0x64, - 0x10, 0xc1, 0x11, 0x73, 0xdb, 0xae, 0x69, 0xb2, 0x36, 0xe8, 0x70, 0xe7, 0x99, 0x76, 0x07, 0x69, 0xda, 0xbc, 0x61, - 0xc3, 0xcf, 0x5c, 0x5b, 0x3c, 0x6b, 0xaa, 0x1b, 0xf0, 0x78, 0x31, 0xcb, 0x30, 0x67, 0xc5, 0xd2, 0xd3, 0xf0, 0x56, - 0x8d, 0xea, 0x5c, 0x09, 0x73, 0x7a, 0x68, 0x3a, 0x6c, 0x42, 0xfc, 0x2f, 0x56, 0x94, 0x7b, 0x8c, 0x0b, 0x83, 0x31, - 0x06, 0x40, 0x9b, 0xbb, 0x24, 0x3c, 0x03, 0x4e, 0x5a, 0x2d, 0x7f, 0x3e, 0x34, 0x6d, 0x9d, 0xb4, 0x9d, 0x9c, 0xb2, - 0xd9, 0xae, 0xfd, 0x59, 0x27, 0x46, 0xed, 0xce, 0xfc, 0x76, 0xcf, 0xfc, 0xd3, 0xda, 0x6b, 0x6d, 0x13, 0x9f, 0x6d, - 0x38, 0x1d, 0x23, 0xbf, 0xb2, 0x5a, 0xce, 0xd3, 0x36, 0x9b, 0x75, 0x17, 0x0a, 0x0e, 0x1a, 0x43, 0x1b, 0xcd, 0x01, - 0xb6, 0x36, 0x33, 0x81, 0x75, 0xa4, 0x5c, 0x00, 0x5d, 0xb7, 0x67, 0x1b, 0xf4, 0xa1, 0x24, 0x18, 0x62, 0xef, 0x6c, - 0xb4, 0x3e, 0xac, 0xd6, 0x5e, 0x35, 0x30, 0xf8, 0x67, 0xfd, 0x57, 0xc5, 0x19, 0xbe, 0x60, 0x01, 0x67, 0xce, 0x1b, - 0xc9, 0xe9, 0xaa, 0xe5, 0xb8, 0xf1, 0x91, 0xae, 0x84, 0x04, 0xe3, 0xcb, 0x30, 0xa3, 0xb7, 0xd6, 0xa9, 0x61, 0xc6, - 0x05, 0x98, 0x4c, 0x21, 0xac, 0x03, 0xe3, 0xf2, 0x69, 0xd8, 0xd0, 0x48, 0xc7, 0xd0, 0xf0, 0x61, 0x27, 0x39, 0x3d, - 0x45, 0xb8, 0x85, 0x3b, 0xa7, 0xa7, 0x81, 0x34, 0x30, 0xd6, 0xbb, 0x8a, 0xee, 0x2a, 0xa9, 0x76, 0x94, 0x3c, 0x32, - 0x8d, 0x1e, 0xb5, 0x5b, 0x2d, 0x6c, 0x1c, 0xb7, 0xcb, 0xc2, 0x5c, 0xed, 0x68, 0xb6, 0xdd, 0x6a, 0x41, 0xb3, 0xf0, - 0xc7, 0xcd, 0xeb, 0x17, 0xb2, 0x6c, 0xa5, 0x2d, 0xdc, 0x4e, 0xdb, 0xb8, 0x93, 0x76, 0xf0, 0x71, 0x7a, 0x8c, 0x4f, - 0xd2, 0x13, 0x7c, 0x9a, 0x9e, 0xe2, 0xb3, 0xf4, 0x0c, 0xdf, 0x4f, 0xef, 0xe3, 0xf3, 0xf4, 0x1c, 0x3f, 0x48, 0x1f, - 0xe0, 0x87, 0x69, 0xbb, 0x85, 0x1f, 0xa5, 0xed, 0x36, 0x7e, 0x9c, 0xb6, 0x3b, 0xf8, 0x49, 0xda, 0x3e, 0xc6, 0x4f, - 0xd3, 0xf6, 0x09, 0x7e, 0x96, 0xb6, 0x4f, 0x31, 0x85, 0xdc, 0x21, 0xe4, 0x66, 0x90, 0x3b, 0x82, 0x5c, 0x06, 0xb9, - 0xe3, 0xb4, 0x7d, 0xba, 0xc6, 0xca, 0x06, 0x7b, 0x88, 0x5a, 0xed, 0xce, 0xf1, 0xc9, 0xe9, 0xd9, 0xfd, 0xf3, 0x07, - 0x0f, 0x1f, 0x3d, 0x7e, 0xf2, 0xf4, 0x59, 0x34, 0xc0, 0x43, 0xe3, 0x73, 0xa1, 0x44, 0x9f, 0x1f, 0xb4, 0x4f, 0x07, - 0xf8, 0xda, 0x7f, 0xc6, 0xfc, 0xa0, 0x73, 0xd2, 0x42, 0x97, 0x97, 0x27, 0x83, 0x46, 0x99, 0xfb, 0xde, 0xb8, 0x7a, - 0x54, 0x59, 0x84, 0x90, 0x18, 0x72, 0x10, 0xbe, 0x33, 0xf5, 0xde, 0xb3, 0x98, 0x27, 0x05, 0x3a, 0x38, 0x30, 0x3f, - 0x26, 0xfe, 0xc7, 0xd0, 0xff, 0xa0, 0xc1, 0x22, 0xdd, 0xd2, 0xd8, 0xf9, 0xfa, 0xea, 0xd2, 0xd2, 0xbe, 0x34, 0x62, - 0xd9, 0xe3, 0xce, 0x9c, 0xfc, 0xbf, 0x22, 0x6b, 0x2e, 0x42, 0x4e, 0xac, 0x4a, 0xe6, 0xb4, 0xc7, 0xc8, 0xb2, 0x48, - 0x3b, 0xa7, 0xa7, 0x07, 0xbf, 0xf4, 0x79, 0xbf, 0x3d, 0x18, 0x1c, 0xb6, 0xef, 0xe3, 0x49, 0x99, 0xd0, 0xb1, 0x09, - 0xc3, 0x32, 0xe1, 0xd8, 0x26, 0xd0, 0xd4, 0xd6, 0x86, 0xa4, 0x13, 0x93, 0x04, 0x25, 0xd6, 0xa9, 0x69, 0xfb, 0xbe, - 0x6d, 0xfb, 0x01, 0xd8, 0x31, 0x99, 0xe6, 0x5d, 0xd3, 0x17, 0x17, 0x27, 0x2b, 0xd7, 0x28, 0x9e, 0xa4, 0xae, 0x35, - 0x9f, 0x78, 0x32, 0x18, 0xe0, 0xa1, 0x49, 0x3c, 0xad, 0x12, 0xcf, 0x06, 0x03, 0xd7, 0xd5, 0x03, 0xd3, 0xd5, 0xfd, - 0x2a, 0xeb, 0x7c, 0x30, 0x30, 0x5d, 0x22, 0xe7, 0xb5, 0xae, 0xf4, 0xde, 0x97, 0x52, 0x73, 0xc0, 0x2f, 0x3a, 0xa7, - 0xa7, 0x3d, 0xc0, 0x30, 0x63, 0x8d, 0xea, 0x61, 0x74, 0x13, 0xc0, 0xe8, 0x0e, 0x7e, 0xf7, 0x86, 0x34, 0xbd, 0xa6, - 0x25, 0x90, 0x7a, 0xd1, 0x7f, 0x45, 0x0d, 0x6d, 0x60, 0x6e, 0xfe, 0x4c, 0xec, 0x9f, 0x21, 0x6a, 0x7c, 0xa1, 0x00, - 0x6e, 0xd0, 0x85, 0x78, 0x65, 0xa6, 0xe9, 0xf1, 0x33, 0x05, 0xe7, 0x92, 0xa9, 0xca, 0x69, 0x6f, 0x35, 0xbd, 0x19, - 0xae, 0xa6, 0xea, 0x0b, 0xfa, 0x33, 0xfe, 0x53, 0x1d, 0xc6, 0xfd, 0x66, 0x23, 0x61, 0x7f, 0x8e, 0xc0, 0x8b, 0xa5, - 0x97, 0x8e, 0xd8, 0x04, 0xf5, 0xfa, 0x7f, 0x2a, 0x3c, 0x68, 0x04, 0x19, 0x3f, 0x6c, 0xa7, 0x80, 0x8f, 0xcb, 0x66, - 0x62, 0xfc, 0x03, 0xea, 0xa1, 0xde, 0x9f, 0xea, 0xf0, 0x4f, 0x74, 0xef, 0xa8, 0x9a, 0xcb, 0xef, 0xd2, 0x6d, 0xe1, - 0x2a, 0xf0, 0xcd, 0x61, 0xb9, 0x85, 0x19, 0x6e, 0x37, 0x19, 0x84, 0x09, 0x03, 0x27, 0x68, 0x12, 0xcb, 0x06, 0x3f, - 0x3a, 0x6e, 0xa1, 0x1f, 0xda, 0x1d, 0x10, 0xeb, 0x9b, 0xe2, 0x70, 0x7b, 0xd3, 0x17, 0xcd, 0x63, 0xfc, 0xa0, 0x59, - 0xe0, 0x36, 0xc2, 0xcd, 0xb6, 0xd7, 0xb7, 0xf6, 0x55, 0xdc, 0x42, 0x58, 0xc5, 0xe7, 0xf0, 0xcf, 0x09, 0x1a, 0x54, - 0x1b, 0xf2, 0x8a, 0x6e, 0xf6, 0x0e, 0x1e, 0x9b, 0x24, 0x56, 0x0d, 0x7e, 0x74, 0xd6, 0x42, 0x3f, 0x9c, 0x99, 0x8e, - 0xd8, 0xa1, 0xde, 0xd1, 0x95, 0xc4, 0x27, 0x4d, 0x09, 0x1d, 0xb5, 0xca, 0x7e, 0x44, 0x7c, 0x8a, 0xb0, 0x88, 0x8f, - 0xe1, 0x9f, 0x76, 0xd8, 0xcf, 0xaf, 0x5b, 0xfd, 0x98, 0x79, 0xb7, 0x71, 0x72, 0x6a, 0x1d, 0x40, 0x95, 0xbd, 0x8d, - 0x6d, 0xb0, 0xcb, 0xb6, 0xb9, 0x46, 0x6a, 0x1f, 0xc1, 0x07, 0xc2, 0xfa, 0x90, 0x28, 0xcc, 0x0e, 0xc1, 0x73, 0x14, - 0x0c, 0x26, 0xd4, 0xc5, 0x71, 0x57, 0x35, 0x1a, 0x48, 0xf4, 0xd5, 0xe0, 0x90, 0xb4, 0x9b, 0xba, 0xc9, 0x30, 0xfc, - 0x6e, 0x90, 0x32, 0x1c, 0x99, 0xa8, 0x7a, 0x7d, 0xec, 0x7a, 0xb5, 0x77, 0xce, 0x1e, 0x3b, 0x08, 0x21, 0xaa, 0x17, - 0xeb, 0x26, 0x43, 0x47, 0xa2, 0x11, 0xeb, 0x0b, 0xd6, 0x3b, 0x4b, 0x5b, 0xc8, 0x60, 0xa7, 0xea, 0xc5, 0xac, 0xc9, - 0x21, 0xbd, 0x93, 0xc6, 0xbc, 0xa9, 0xe1, 0xd7, 0x49, 0x30, 0x0b, 0x01, 0x78, 0x57, 0xf9, 0xc1, 0x14, 0x47, 0x9d, - 0xd3, 0x53, 0x2c, 0x08, 0x4f, 0x26, 0xe6, 0x97, 0x22, 0x3c, 0x19, 0x9a, 0x5f, 0x92, 0x94, 0xf0, 0xb2, 0xbd, 0xe3, - 0x82, 0x04, 0xab, 0x6a, 0x52, 0x28, 0x2c, 0x68, 0x81, 0x8e, 0x3a, 0xfe, 0x42, 0x1a, 0x4f, 0xfd, 0x1c, 0x40, 0x00, - 0x2f, 0x8c, 0x2d, 0xa2, 0x6c, 0x16, 0x38, 0x27, 0xf4, 0x32, 0x39, 0xed, 0x4d, 0x8f, 0xe2, 0x4e, 0x53, 0x36, 0x0b, - 0x94, 0x4e, 0x8f, 0x4c, 0x4d, 0x9c, 0x91, 0xc7, 0xd4, 0xb6, 0x86, 0xa7, 0x70, 0x8b, 0x98, 0x91, 0xec, 0xf0, 0xac, - 0xd5, 0x48, 0x4e, 0x11, 0xee, 0x67, 0xab, 0x16, 0xce, 0x57, 0xab, 0x16, 0xa6, 0xc1, 0x32, 0x3c, 0x16, 0x1e, 0x20, - 0xa5, 0x8e, 0x68, 0x33, 0x2a, 0x4c, 0x8f, 0xc7, 0x1a, 0x6e, 0xc4, 0x35, 0xf8, 0x99, 0x68, 0xf0, 0x80, 0x49, 0xb9, - 0xbb, 0x8a, 0x42, 0x26, 0x2e, 0xde, 0x38, 0xd4, 0x1a, 0xbd, 0x16, 0x7e, 0x5d, 0xbd, 0x4d, 0xa3, 0x88, 0x7f, 0x97, - 0xd8, 0xa6, 0x05, 0xc5, 0xe8, 0x76, 0xb1, 0x5f, 0xe9, 0x56, 0xb1, 0x37, 0x3b, 0x8a, 0x5d, 0x6d, 0x17, 0xfb, 0x28, - 0x03, 0x1d, 0x17, 0xff, 0xe1, 0xf8, 0xac, 0xd5, 0x38, 0x06, 0x64, 0x3d, 0x3e, 0x6b, 0x55, 0x85, 0xee, 0xd1, 0x6a, - 0xad, 0x34, 0xf9, 0x4c, 0xad, 0x95, 0x3f, 0xf7, 0xee, 0xc6, 0x66, 0xe1, 0xac, 0xb3, 0x73, 0xe9, 0xd9, 0xdc, 0x3f, - 0x05, 0x2b, 0x0a, 0x61, 0xa8, 0x9d, 0xee, 0x9f, 0x0d, 0x7a, 0x53, 0x16, 0x37, 0x20, 0x15, 0xa5, 0x63, 0xed, 0x7e, - 0xa1, 0xf2, 0x32, 0xf5, 0xa3, 0x84, 0xa4, 0xce, 0x00, 0x61, 0x49, 0x1a, 0xba, 0x7f, 0x3c, 0x30, 0xe7, 0x5d, 0x01, - 0xbf, 0x4f, 0xcc, 0xef, 0x52, 0x95, 0xe1, 0x5c, 0x01, 0xa6, 0x37, 0xc3, 0xa8, 0x27, 0xc8, 0x6b, 0x1a, 0x1b, 0xeb, - 0x6e, 0x94, 0x96, 0x19, 0xea, 0x0b, 0x64, 0xbc, 0x29, 0x33, 0x04, 0x79, 0x2d, 0xdc, 0x6f, 0xbc, 0x2c, 0x52, 0xb0, - 0xf4, 0xc0, 0x93, 0x14, 0xac, 0x3c, 0xf0, 0x30, 0x15, 0xe0, 0x89, 0x40, 0x53, 0x16, 0xd8, 0x8f, 0x3f, 0x74, 0xba, - 0x23, 0x73, 0xdf, 0x49, 0x0c, 0x96, 0x76, 0x19, 0x9c, 0x14, 0x1f, 0x65, 0x0c, 0x7f, 0x1b, 0x1a, 0x61, 0x06, 0x6d, - 0x32, 0x84, 0x79, 0x52, 0x10, 0x48, 0xc3, 0x3c, 0x99, 0x10, 0x06, 0x4d, 0xf2, 0x64, 0x48, 0x58, 0xbf, 0x13, 0xa0, - 0xc9, 0x53, 0x03, 0x3b, 0x00, 0x0e, 0xaf, 0x5f, 0x21, 0x6b, 0xdb, 0x38, 0xdc, 0x4d, 0x43, 0x13, 0x82, 0x70, 0x15, - 0xc3, 0x2c, 0x60, 0x73, 0x9a, 0x9f, 0x9d, 0x2a, 0xf0, 0x22, 0x4f, 0xa8, 0xa1, 0xde, 0x7f, 0x01, 0x59, 0x8d, 0xef, - 0x2d, 0xd9, 0x1a, 0xef, 0xdd, 0x5b, 0x8a, 0xf5, 0x0f, 0xf0, 0x47, 0xb9, 0x3f, 0xda, 0x9c, 0x7e, 0x6b, 0xf4, 0x57, - 0x0a, 0xc5, 0x76, 0x94, 0x42, 0x7f, 0x79, 0x47, 0x34, 0x45, 0x96, 0xb7, 0x69, 0x34, 0xa2, 0xc5, 0xe7, 0x08, 0x7f, - 0x4a, 0xa3, 0x1c, 0x18, 0xc1, 0x08, 0x7f, 0x4c, 0xa3, 0x82, 0x45, 0xf8, 0x8f, 0x34, 0x1a, 0xe6, 0x8b, 0x08, 0x7f, - 0x48, 0xa3, 0x49, 0x11, 0xe1, 0xf7, 0xa0, 0x26, 0x1c, 0xf1, 0xc5, 0x2c, 0xc2, 0xbf, 0xa7, 0x91, 0x32, 0x76, 0xf8, - 0xf8, 0x61, 0x1a, 0x31, 0x16, 0xe1, 0x77, 0x69, 0x24, 0xf3, 0x08, 0x5f, 0xa5, 0x91, 0x2c, 0x22, 0xfc, 0x28, 0x8d, - 0x0a, 0x1a, 0xe1, 0xc7, 0x69, 0x04, 0x85, 0x26, 0x11, 0x7e, 0x92, 0x46, 0xd0, 0xb2, 0x8a, 0xf0, 0xdb, 0x34, 0xe2, - 0x22, 0xc2, 0xbf, 0xa5, 0x91, 0x5e, 0x14, 0xff, 0x2c, 0x24, 0x57, 0x11, 0x7e, 0x9a, 0x46, 0x53, 0x1e, 0xe1, 0x37, - 0x69, 0x54, 0xc8, 0x08, 0xbf, 0x4e, 0x23, 0x9a, 0x47, 0xf8, 0x55, 0x1a, 0xe5, 0x2c, 0xc2, 0xbf, 0xa6, 0xd1, 0x88, - 0x45, 0xf8, 0x65, 0x1a, 0xdd, 0xb1, 0x3c, 0x97, 0x11, 0x7e, 0x96, 0x46, 0x4c, 0x44, 0xf8, 0x97, 0x34, 0xca, 0xa6, - 0x11, 0xfe, 0x29, 0x8d, 0x68, 0xf1, 0x59, 0x45, 0xf8, 0x79, 0x1a, 0x31, 0x1a, 0xe1, 0x17, 0xb6, 0xa3, 0x49, 0x84, - 0x7f, 0x4e, 0xa3, 0x9b, 0x69, 0xb4, 0xc6, 0x4a, 0x91, 0xe5, 0x6b, 0x9e, 0xb1, 0x3f, 0x58, 0x1a, 0x8d, 0x5b, 0xe3, - 0xf3, 0xf1, 0x38, 0xc2, 0x54, 0x68, 0xfe, 0xcf, 0x82, 0xdd, 0x3c, 0xd5, 0x90, 0x48, 0xd9, 0x70, 0x74, 0x3f, 0xc2, - 0xf4, 0x9f, 0x05, 0x4d, 0xa3, 0xf1, 0xd8, 0x14, 0xf8, 0x67, 0x41, 0x67, 0xb4, 0x78, 0xcb, 0xd2, 0xe8, 0xfe, 0x78, - 0x3c, 0x1e, 0x9d, 0x44, 0x98, 0x7e, 0x5d, 0x7c, 0x34, 0x2d, 0x98, 0x02, 0x43, 0xc6, 0x27, 0x50, 0xf7, 0x74, 0x7c, - 0x3a, 0xca, 0x22, 0x3c, 0xe4, 0xea, 0x9f, 0x05, 0x7c, 0x8f, 0xd9, 0x49, 0x76, 0x12, 0xe1, 0x61, 0x4e, 0xb3, 0xcf, - 0x69, 0xd4, 0x32, 0xbf, 0xc4, 0x2f, 0x6c, 0xf4, 0x7a, 0x26, 0x8d, 0x12, 0x7d, 0xcc, 0x86, 0xd9, 0x28, 0xc2, 0x66, - 0x30, 0x63, 0xf8, 0xfb, 0x85, 0xbf, 0x63, 0x3a, 0x8d, 0xce, 0x69, 0x67, 0xc8, 0x3a, 0x11, 0x1e, 0xbe, 0xb9, 0x11, - 0x69, 0x44, 0x4f, 0x3b, 0xb4, 0x43, 0x23, 0x3c, 0x5c, 0x14, 0xf9, 0xdd, 0x8d, 0x94, 0x23, 0x00, 0xc2, 0xf0, 0xfc, - 0xfc, 0x7e, 0x84, 0x33, 0xfa, 0xab, 0x86, 0xda, 0xa7, 0xe3, 0x07, 0x8c, 0xb6, 0x22, 0xfc, 0x0b, 0x2d, 0xf4, 0xc7, - 0x85, 0x72, 0x03, 0x6d, 0x41, 0x8a, 0xcc, 0xde, 0x81, 0x82, 0x39, 0x1a, 0x75, 0xce, 0x1e, 0xb4, 0x59, 0x84, 0xb3, - 0xab, 0xd7, 0xd0, 0xdb, 0xfd, 0xf1, 0x69, 0x0b, 0x3e, 0x04, 0x48, 0x6a, 0xac, 0x80, 0x46, 0xce, 0x4e, 0x1e, 0x9c, - 0xb2, 0x91, 0x49, 0x54, 0x3c, 0xff, 0x6c, 0x66, 0x7f, 0x0e, 0xf3, 0xc9, 0x0a, 0x3e, 0x53, 0x52, 0xa4, 0xd1, 0x28, - 0x6b, 0x9f, 0x1c, 0x43, 0xc2, 0x1d, 0x15, 0x1e, 0x38, 0xb7, 0x50, 0xf5, 0x7c, 0x18, 0xe1, 0x5b, 0x9b, 0x7a, 0x3e, - 0x34, 0x1f, 0x93, 0x77, 0xbf, 0x8a, 0x37, 0xa3, 0x34, 0x1a, 0x9e, 0x9f, 0x9f, 0xb5, 0x20, 0xe1, 0x03, 0xbd, 0x4b, - 0x23, 0xfa, 0x00, 0xfe, 0x83, 0xec, 0x8f, 0xcf, 0xa0, 0x43, 0x18, 0xe1, 0xed, 0xe4, 0x63, 0x98, 0xf3, 0x79, 0x4a, - 0x3f, 0xf3, 0x34, 0x1a, 0x8e, 0x86, 0xf7, 0xcf, 0xa0, 0xde, 0x8c, 0x4e, 0x9e, 0x69, 0x0a, 0xed, 0xb6, 0x5a, 0xa6, - 0xe5, 0x77, 0xfc, 0x0b, 0x33, 0xd5, 0x4f, 0x4f, 0xcf, 0x86, 0x1d, 0x18, 0xc1, 0x15, 0xa8, 0x18, 0x60, 0x3c, 0xe7, - 0x99, 0x69, 0xf0, 0x2a, 0x7b, 0x3a, 0x4a, 0xa3, 0x07, 0x0f, 0x8e, 0x3b, 0x59, 0x16, 0xe1, 0xdb, 0x8f, 0x23, 0x5b, - 0xdb, 0xe4, 0x29, 0x80, 0x7d, 0x1a, 0xb1, 0x07, 0x0f, 0xce, 0xee, 0x53, 0xf8, 0x7e, 0x6e, 0xda, 0x3a, 0x1f, 0x0f, - 0xb3, 0x73, 0x68, 0xeb, 0x77, 0x98, 0xce, 0xc9, 0xf9, 0xf1, 0xc8, 0xf4, 0xf5, 0xbb, 0x19, 0x75, 0x67, 0x7c, 0x32, - 0x3e, 0x31, 0x99, 0x66, 0xa8, 0xe5, 0xe7, 0x6f, 0x2c, 0x8d, 0x32, 0x36, 0x6a, 0x47, 0xf8, 0xd6, 0x2d, 0xdc, 0x83, - 0x93, 0x56, 0x6b, 0x74, 0x1c, 0xe1, 0xd1, 0xc3, 0xf9, 0xfc, 0xad, 0x81, 0x60, 0xfb, 0xe4, 0x81, 0xfd, 0x56, 0x9f, - 0xef, 0xa0, 0xe9, 0xa1, 0x01, 0xda, 0x88, 0xcf, 0x4c, 0xcb, 0x67, 0x0f, 0xe0, 0x3f, 0xf3, 0x6d, 0x9a, 0x2e, 0xbf, - 0xe5, 0x68, 0x62, 0x17, 0xa5, 0xcd, 0x1e, 0xb4, 0xa0, 0xc6, 0x98, 0x7f, 0x1c, 0x16, 0x1c, 0xd0, 0x68, 0xd8, 0x81, - 0xff, 0x8b, 0xf0, 0x38, 0xbf, 0x7a, 0xed, 0x70, 0x76, 0x3c, 0xa6, 0xe3, 0x56, 0x84, 0xc7, 0xf2, 0xa3, 0xd2, 0x1f, - 0x1e, 0x8a, 0x34, 0xea, 0x74, 0xce, 0x87, 0xa6, 0xcc, 0xe2, 0x17, 0xc5, 0x0d, 0x1e, 0xb7, 0x4c, 0x2b, 0x13, 0xfa, - 0x56, 0x0d, 0xaf, 0x24, 0xac, 0x24, 0xfc, 0x17, 0xe1, 0x09, 0xe8, 0xa5, 0x5c, 0x2b, 0xe7, 0x76, 0x3b, 0x4c, 0xde, - 0x19, 0xd4, 0x1c, 0xdd, 0x07, 0x78, 0xf9, 0x65, 0x1c, 0x51, 0x7a, 0xda, 0x69, 0x45, 0xd8, 0x8c, 0xfa, 0xbc, 0x05, - 0xff, 0x45, 0xd8, 0x42, 0xce, 0xc0, 0x75, 0xf2, 0xf1, 0xd9, 0xcb, 0x9b, 0x34, 0xa2, 0xa3, 0xf1, 0x18, 0x96, 0xc4, - 0x4c, 0xc6, 0x17, 0x9b, 0x4a, 0xc1, 0xee, 0x7e, 0xbd, 0x71, 0xdb, 0xc5, 0x24, 0x68, 0x07, 0x9d, 0xb3, 0x07, 0xc3, - 0x93, 0x08, 0xbf, 0x1d, 0x71, 0x2a, 0x60, 0x95, 0xb2, 0xd1, 0x69, 0x76, 0x9a, 0x99, 0x84, 0x89, 0x4c, 0xa3, 0x13, - 0x58, 0xf2, 0x4e, 0x84, 0xf9, 0x97, 0xab, 0x3b, 0x8b, 0x6e, 0x50, 0xdb, 0x21, 0xc8, 0xb8, 0xc5, 0xce, 0xce, 0xb3, - 0x08, 0xe7, 0xf4, 0xcb, 0xb3, 0x5f, 0x8b, 0x34, 0x62, 0x67, 0xec, 0x6c, 0x4c, 0xfd, 0xf7, 0x1f, 0x6a, 0x6a, 0x6a, - 0xb4, 0xc6, 0xa7, 0x90, 0x74, 0x23, 0xcc, 0x58, 0xef, 0x67, 0x63, 0x83, 0x21, 0xaf, 0x66, 0x52, 0x64, 0x4f, 0xc7, - 0x63, 0x69, 0xb1, 0x98, 0xc2, 0x26, 0xfc, 0x04, 0xd0, 0xa6, 0xa3, 0xd1, 0x39, 0x3b, 0x8b, 0xf0, 0x27, 0xbb, 0x4b, - 0xdc, 0x04, 0x3e, 0x59, 0xcc, 0x66, 0x6e, 0xb7, 0x7f, 0xb2, 0x40, 0x81, 0xf9, 0x8e, 0xe9, 0x98, 0x8e, 0x3a, 0x11, - 0xfe, 0x64, 0xe0, 0x32, 0x3a, 0x86, 0xff, 0xa0, 0x00, 0x74, 0xf6, 0xa0, 0xc5, 0xd8, 0x83, 0x96, 0xf9, 0x0a, 0xf3, - 0xdc, 0xcc, 0x87, 0x67, 0x59, 0x3b, 0xc2, 0x9f, 0x1c, 0x3a, 0x8e, 0xc7, 0xb4, 0x05, 0xe8, 0xf8, 0xc9, 0xa1, 0x63, - 0xa7, 0x35, 0xec, 0x50, 0xf3, 0x6d, 0xb1, 0xe6, 0xfc, 0x7e, 0xc6, 0x60, 0x72, 0x9f, 0x2c, 0x42, 0xde, 0xbf, 0x7f, - 0x7e, 0xfe, 0xe0, 0x01, 0x7c, 0x9a, 0xb6, 0xcb, 0x4f, 0xa5, 0x1f, 0xe6, 0x06, 0xc9, 0x5a, 0xd9, 0x09, 0xd0, 0xc9, - 0x4f, 0x66, 0x8c, 0xe3, 0xf1, 0x98, 0xb5, 0x22, 0x9c, 0xf3, 0x19, 0xb3, 0x98, 0x60, 0x7f, 0x9b, 0x8e, 0x8e, 0x3b, - 0xd9, 0xe8, 0xb8, 0x13, 0xe1, 0xfc, 0xed, 0x33, 0x33, 0x9b, 0x16, 0xcc, 0xde, 0x6f, 0x39, 0x8f, 0x35, 0x33, 0xfa, - 0x06, 0x06, 0x09, 0x2b, 0x0d, 0x95, 0xdf, 0x07, 0xf4, 0xf0, 0xec, 0x2c, 0x1b, 0xc1, 0x40, 0xdf, 0x43, 0xb7, 0x00, - 0xc6, 0xf7, 0x76, 0xf3, 0x0d, 0xe9, 0xe9, 0x29, 0x4c, 0xf7, 0xfd, 0x7c, 0x51, 0xcc, 0x5f, 0xa5, 0xd1, 0x83, 0xe3, - 0xfb, 0xad, 0xd1, 0x30, 0xc2, 0xef, 0xdd, 0x04, 0x8f, 0xb3, 0xe1, 0xf1, 0xfd, 0x76, 0x84, 0xdf, 0x9b, 0xfd, 0x76, - 0x7f, 0x78, 0x76, 0x0e, 0xe7, 0xc6, 0x7b, 0x35, 0x2f, 0xde, 0x4e, 0x4c, 0x81, 0x31, 0x7d, 0x00, 0xcd, 0xfe, 0x66, - 0x76, 0xe3, 0xa8, 0x0d, 0x1b, 0xf9, 0xbd, 0xd9, 0x64, 0x06, 0x4f, 0xee, 0xb7, 0x4f, 0xcf, 0x4f, 0x23, 0x3c, 0xe3, - 0x23, 0x01, 0x04, 0xde, 0x6c, 0x94, 0x07, 0xed, 0x07, 0xf7, 0x5b, 0x11, 0x9e, 0xbd, 0xd5, 0xd9, 0x47, 0x3a, 0x33, - 0xd4, 0x78, 0x0c, 0x30, 0x9b, 0x71, 0xa5, 0xef, 0xde, 0x28, 0x47, 0x8f, 0x59, 0x3b, 0xc2, 0x33, 0x99, 0x65, 0x54, - 0xbd, 0xb5, 0x09, 0xc3, 0xd3, 0x08, 0x0b, 0xfa, 0x85, 0xfe, 0x2d, 0xfd, 0x66, 0x1a, 0x31, 0x3a, 0x32, 0x69, 0x06, - 0x87, 0x23, 0xfc, 0x6e, 0x04, 0xd7, 0x60, 0x69, 0x34, 0x1e, 0x8d, 0x4f, 0x01, 0x3c, 0x40, 0x80, 0x2c, 0x76, 0x03, - 0x34, 0xe0, 0x6b, 0xf4, 0x68, 0x98, 0x46, 0x67, 0xc3, 0x73, 0xd6, 0x39, 0x8e, 0x70, 0x49, 0x8d, 0xe8, 0x29, 0xe4, - 0x9b, 0xcf, 0x8f, 0x66, 0x4b, 0x9d, 0xd8, 0x04, 0x03, 0xa0, 0x11, 0xbd, 0xdf, 0x1a, 0x9d, 0x45, 0x78, 0xfe, 0x9a, - 0xf9, 0x3d, 0xc6, 0x18, 0x3b, 0x07, 0x58, 0x42, 0x92, 0x41, 0xa0, 0xf3, 0xf1, 0xf0, 0xc1, 0xb9, 0xf9, 0x06, 0x30, - 0xd0, 0x31, 0x63, 0x00, 0xa4, 0xf9, 0x6b, 0x56, 0x02, 0x62, 0x34, 0xbc, 0xdf, 0x02, 0xfa, 0x32, 0xa7, 0x73, 0x7a, - 0x47, 0x6f, 0x9e, 0xce, 0xcd, 0x9c, 0xc6, 0xa3, 0xd3, 0x08, 0xcf, 0x9f, 0xff, 0x32, 0x5f, 0x8c, 0xc7, 0x66, 0x42, - 0x74, 0xf8, 0x20, 0xc2, 0x73, 0x56, 0x2c, 0x60, 0x8d, 0xce, 0x4f, 0x8f, 0xc7, 0x11, 0x76, 0x68, 0x98, 0xb5, 0xb2, - 0x21, 0xdc, 0xf3, 0x2d, 0x66, 0x69, 0x34, 0x1a, 0xd1, 0xd6, 0x08, 0x6e, 0xfd, 0xe4, 0xcd, 0xaf, 0x85, 0x45, 0x23, - 0x66, 0xf0, 0xc1, 0xad, 0x21, 0xcc, 0x17, 0xe0, 0xf1, 0x71, 0xc8, 0xb2, 0x8c, 0xba, 0xc4, 0xb3, 0xb3, 0xe3, 0x63, - 0xc0, 0x3d, 0x3b, 0x43, 0x8b, 0x20, 0x6f, 0xd4, 0xdd, 0xb0, 0x90, 0x70, 0x74, 0x01, 0x51, 0x05, 0xb2, 0xfa, 0xe6, - 0xee, 0xb5, 0xa1, 0xab, 0xed, 0xb3, 0x07, 0xb0, 0x00, 0x8a, 0x8e, 0x46, 0xaf, 0xec, 0xe1, 0x76, 0x3e, 0x3c, 0x39, - 0x6d, 0x1f, 0x47, 0xd8, 0x6f, 0x04, 0x7a, 0xde, 0xba, 0xdf, 0x81, 0x12, 0x62, 0x74, 0x67, 0x4b, 0x8c, 0x4f, 0xe8, - 0xc9, 0x59, 0x2b, 0xc2, 0x7e, 0x6b, 0xb0, 0xf3, 0xe1, 0xe9, 0x7d, 0xf8, 0x54, 0x53, 0x96, 0xe7, 0x06, 0xbf, 0x4f, - 0x01, 0x2e, 0x8a, 0x3f, 0x13, 0x34, 0x8d, 0x68, 0xeb, 0xb4, 0xd3, 0x19, 0xc1, 0x67, 0xfe, 0x85, 0x15, 0x69, 0x94, - 0xb5, 0xe0, 0xbf, 0x08, 0x07, 0x3b, 0x89, 0x0d, 0x23, 0x6c, 0xf0, 0xee, 0x8c, 0x9e, 0x9a, 0xbd, 0xef, 0x76, 0x55, - 0xeb, 0xbc, 0x05, 0x1b, 0xd6, 0x6d, 0x2a, 0xf7, 0xa5, 0x84, 0xbc, 0x71, 0x24, 0x96, 0x46, 0x38, 0x40, 0xd0, 0xf1, - 0xfd, 0x71, 0x84, 0xfd, 0x8e, 0x3b, 0x39, 0x3b, 0xef, 0x00, 0x29, 0xd3, 0x40, 0x28, 0x46, 0x9d, 0xe1, 0x09, 0x90, - 0x26, 0xcd, 0x5e, 0x5b, 0x3c, 0x89, 0xb0, 0x7e, 0xaa, 0xf4, 0xab, 0x34, 0x1a, 0x9d, 0x0f, 0xc7, 0xa3, 0xf3, 0x08, - 0x6b, 0x39, 0xa3, 0x5a, 0x1a, 0x0a, 0x78, 0x7c, 0x72, 0x3f, 0xc2, 0x06, 0xcd, 0x5b, 0xac, 0x35, 0x6a, 0x45, 0xd8, - 0x1d, 0x25, 0x8c, 0x9d, 0x77, 0x60, 0x5a, 0x3f, 0x3f, 0xd7, 0x80, 0xcb, 0x23, 0x36, 0x3c, 0x8e, 0x70, 0x49, 0xef, - 0x0d, 0x21, 0x82, 0x2f, 0x35, 0x93, 0x9f, 0x1d, 0xeb, 0x01, 0xa4, 0xce, 0x6f, 0x78, 0x58, 0x86, 0x97, 0x37, 0x16, - 0x8d, 0xa8, 0xd9, 0xe2, 0xc1, 0x3d, 0xe8, 0x13, 0x1a, 0x7b, 0xb6, 0x9d, 0x93, 0xe5, 0x1a, 0x97, 0xe1, 0x45, 0x3f, - 0xb3, 0x3b, 0x15, 0x2b, 0x65, 0x38, 0xd9, 0x20, 0x05, 0x5c, 0x00, 0x9c, 0x41, 0xbd, 0xf3, 0x99, 0x04, 0x41, 0x52, - 0x90, 0x56, 0x57, 0x5c, 0x78, 0x3f, 0xce, 0xae, 0x80, 0xa0, 0x03, 0x90, 0x5e, 0x10, 0x4a, 0x34, 0xc4, 0x66, 0xb1, - 0xc2, 0xa4, 0x37, 0x6f, 0x37, 0x32, 0xa5, 0xb4, 0x06, 0xf3, 0x94, 0x50, 0x1f, 0x95, 0x1d, 0x2e, 0x69, 0x21, 0x6e, - 0x11, 0xea, 0x4a, 0x62, 0x62, 0x2c, 0xbf, 0x10, 0x3a, 0x56, 0xaa, 0x5f, 0x0c, 0x70, 0xfb, 0x0c, 0x61, 0x88, 0x5e, - 0x40, 0xfa, 0xf2, 0xf2, 0xb2, 0x7d, 0x76, 0x60, 0x84, 0xbe, 0xcb, 0xcb, 0x73, 0xfb, 0x03, 0xfe, 0x1d, 0x54, 0x11, - 0xa3, 0x61, 0x7c, 0x8f, 0x58, 0xa0, 0xd1, 0x33, 0xfc, 0xf5, 0x23, 0xb6, 0x5a, 0xc5, 0x8f, 0x18, 0x81, 0x19, 0xe3, - 0x47, 0x2c, 0x31, 0xb7, 0x06, 0xd6, 0x37, 0x85, 0xf4, 0x41, 0x73, 0xd6, 0xc2, 0x10, 0xc7, 0xdc, 0x73, 0xde, 0x8f, - 0x58, 0x9f, 0xd7, 0xfd, 0x9a, 0xab, 0xe0, 0xc1, 0x07, 0x07, 0xcb, 0x22, 0xd5, 0x56, 0x4c, 0xd0, 0x56, 0x4c, 0xd0, - 0x56, 0x4c, 0xd0, 0x55, 0xf8, 0xf6, 0x93, 0x1e, 0x48, 0x29, 0x46, 0xd9, 0xe2, 0x78, 0xea, 0x77, 0xa0, 0xf6, 0x00, - 0xed, 0x64, 0xaf, 0x52, 0x76, 0x94, 0xba, 0x8a, 0x9d, 0x0a, 0x8c, 0x9d, 0x89, 0x4e, 0xdb, 0x71, 0xf4, 0xef, 0xa8, - 0x3b, 0x5e, 0xd6, 0xc4, 0xb2, 0x77, 0x3b, 0xc5, 0x32, 0x58, 0x49, 0x23, 0x9a, 0xed, 0xdb, 0x48, 0x18, 0xba, 0x7f, - 0xdf, 0x08, 0x66, 0x55, 0x78, 0xb6, 0x06, 0x24, 0x75, 0x41, 0x0a, 0x39, 0x37, 0x52, 0x5a, 0x81, 0xd2, 0x91, 0x8e, - 0x0b, 0xd0, 0x50, 0x7a, 0x05, 0x65, 0x19, 0x45, 0xb4, 0x61, 0x00, 0xa2, 0xac, 0x8c, 0x66, 0x65, 0xb5, 0x53, 0x10, - 0x5d, 0x40, 0x13, 0x66, 0x24, 0x16, 0x68, 0x40, 0x98, 0x06, 0x84, 0xab, 0x0c, 0xe2, 0x8c, 0xcb, 0x3e, 0x31, 0xd9, - 0xca, 0x64, 0xab, 0x32, 0x5b, 0xfa, 0x6c, 0x2b, 0x24, 0x4a, 0x93, 0x2d, 0xcb, 0x6c, 0x90, 0xd9, 0xf0, 0x24, 0x55, - 0x78, 0x98, 0x4a, 0x2b, 0xaa, 0x55, 0xb2, 0xd5, 0x5b, 0x1a, 0x6a, 0x73, 0x0f, 0x0e, 0xe2, 0x52, 0x4e, 0x32, 0x6a, - 0xe2, 0x7b, 0x4b, 0x9e, 0x14, 0x46, 0x06, 0xe2, 0xc9, 0xc4, 0xfd, 0x1d, 0xae, 0x37, 0x65, 0xa5, 0x62, 0x32, 0xfc, - 0x46, 0x49, 0xf4, 0x97, 0x57, 0xa2, 0x3e, 0xe2, 0x26, 0xfe, 0xcc, 0x05, 0x49, 0x5a, 0xad, 0xe3, 0xf6, 0x71, 0xeb, - 0xbc, 0xc7, 0x0f, 0xdb, 0x9d, 0xe4, 0x41, 0x27, 0x35, 0x8a, 0x88, 0xb9, 0xbc, 0x01, 0x05, 0xcc, 0x51, 0x27, 0x39, - 0x41, 0x87, 0xed, 0xa4, 0x75, 0x7a, 0xda, 0x84, 0x7f, 0xf0, 0x7b, 0x5d, 0x56, 0x3b, 0x69, 0x9d, 0x9c, 0xf6, 0xf8, - 0xd1, 0x46, 0xa5, 0x98, 0x37, 0xa0, 0x20, 0x3a, 0x32, 0x95, 0x30, 0xd4, 0xaf, 0x96, 0xf7, 0xd9, 0x96, 0x9e, 0xe7, - 0xbd, 0x8e, 0x95, 0x55, 0xc5, 0x01, 0x54, 0xfd, 0xd7, 0xc4, 0x00, 0xd1, 0x7f, 0x0d, 0xcb, 0x18, 0xb1, 0xcb, 0x02, - 0x44, 0xed, 0x47, 0x3c, 0x16, 0x0d, 0x76, 0x18, 0xdb, 0x7c, 0x0d, 0x75, 0x9b, 0x10, 0xb7, 0x0d, 0x4f, 0x5c, 0xae, - 0x0a, 0x73, 0x27, 0x08, 0x35, 0x15, 0xe4, 0x0e, 0x5d, 0xae, 0x0c, 0x73, 0x87, 0x08, 0x35, 0x25, 0xe4, 0xd2, 0x94, - 0x27, 0x14, 0x72, 0x74, 0x42, 0x9b, 0x06, 0x92, 0xd5, 0xa2, 0x3c, 0x67, 0x7e, 0xd8, 0x7c, 0x0c, 0xcb, 0x63, 0x08, - 0x8a, 0x13, 0xa4, 0x05, 0xbc, 0xed, 0x51, 0x6a, 0x73, 0x5a, 0xb8, 0x54, 0xe3, 0x40, 0x46, 0x03, 0xfe, 0x39, 0x64, - 0xe6, 0xc1, 0x87, 0x56, 0xef, 0xf8, 0xac, 0x95, 0xb6, 0xc1, 0x49, 0x19, 0x64, 0x6d, 0x61, 0x65, 0x6d, 0xe1, 0x65, - 0x6d, 0xe1, 0x65, 0x6d, 0x10, 0xe0, 0x83, 0xbe, 0xff, 0x91, 0x35, 0xc3, 0x0f, 0x5e, 0x5a, 0x91, 0x58, 0x33, 0x81, - 0x58, 0xaf, 0x56, 0xcb, 0x35, 0xd8, 0xf8, 0x94, 0x35, 0xa4, 0xaa, 0xd4, 0x9f, 0xcb, 0x22, 0x6d, 0xe1, 0x49, 0x0a, - 0x5a, 0xee, 0x16, 0xa6, 0x66, 0x73, 0x7b, 0xaa, 0xb0, 0x19, 0x3f, 0xa6, 0xe7, 0xd5, 0xc9, 0x97, 0xe4, 0xd8, 0x68, - 0x8f, 0x97, 0x45, 0xca, 0x2d, 0xcd, 0xe0, 0x96, 0x66, 0x70, 0x4b, 0x33, 0xa0, 0x11, 0x5c, 0x16, 0x36, 0x65, 0x13, - 0x4a, 0xe0, 0x4a, 0xa0, 0x7f, 0x3c, 0x80, 0xf0, 0x79, 0xb1, 0x26, 0x66, 0xd4, 0x1b, 0x9d, 0xb7, 0x21, 0x5c, 0x98, - 0x2d, 0xa9, 0x13, 0x6a, 0xbc, 0xa6, 0xcb, 0x31, 0x7f, 0xad, 0xa1, 0x7d, 0x02, 0x6f, 0xb9, 0x3c, 0xd4, 0x71, 0x0b, - 0x8c, 0x26, 0xa2, 0x22, 0xea, 0x19, 0xb2, 0x90, 0x1a, 0x9d, 0x8d, 0x33, 0x86, 0xfe, 0xbc, 0xe1, 0x83, 0x6a, 0x29, - 0x41, 0xf8, 0x82, 0xc1, 0x67, 0x56, 0x39, 0xc5, 0x97, 0xb6, 0x9e, 0xce, 0x50, 0xcb, 0x1e, 0x09, 0x5d, 0x30, 0xd8, - 0xf6, 0xd1, 0x96, 0x7a, 0x82, 0x48, 0x65, 0xdc, 0x05, 0x49, 0x15, 0x2f, 0x18, 0xdc, 0x67, 0xc9, 0x2d, 0x35, 0xce, - 0x24, 0x2f, 0xec, 0x9f, 0xaf, 0x34, 0xf0, 0xb6, 0x2b, 0x26, 0x43, 0xef, 0xa4, 0x7a, 0x6d, 0xa2, 0xea, 0x90, 0xfd, - 0x7d, 0x6b, 0x4b, 0x6d, 0xbe, 0x36, 0x8d, 0xa9, 0x4d, 0xa2, 0xc9, 0x86, 0x1d, 0xea, 0xd7, 0xe8, 0x1f, 0xef, 0x2b, - 0x56, 0x4c, 0x86, 0x28, 0xa0, 0xd9, 0x06, 0xac, 0xaa, 0x02, 0x96, 0x72, 0xf5, 0x4a, 0x17, 0x42, 0xe8, 0xdd, 0x8c, - 0x79, 0x5d, 0x4c, 0x86, 0x3b, 0x1f, 0xfd, 0xb0, 0x3d, 0xf6, 0xde, 0xd2, 0xa0, 0x07, 0xaf, 0xda, 0x9e, 0xb2, 0xdb, - 0xef, 0xd5, 0xb9, 0xd9, 0x59, 0x47, 0xe5, 0xdf, 0xab, 0xf3, 0x74, 0x57, 0x9d, 0x19, 0xbf, 0x8d, 0xfd, 0xde, 0xd1, - 0x81, 0x1a, 0xdb, 0x18, 0xe8, 0x4c, 0x86, 0x10, 0xa5, 0x1d, 0xfe, 0xda, 0x58, 0x2a, 0x5d, 0x4f, 0xc2, 0x61, 0x15, - 0x64, 0x2f, 0x39, 0x4d, 0x19, 0xa6, 0xa4, 0x73, 0x58, 0x98, 0x68, 0x2a, 0x22, 0xa1, 0x4d, 0x95, 0x50, 0x9c, 0x93, - 0x38, 0xa6, 0x87, 0x19, 0xc4, 0x84, 0x69, 0xf7, 0x68, 0x1a, 0xd3, 0x46, 0x86, 0x8e, 0xe2, 0x76, 0x83, 0x1e, 0x66, - 0x08, 0x35, 0xda, 0xa0, 0x33, 0x95, 0xa4, 0xdd, 0xcc, 0x21, 0x4a, 0xa4, 0x21, 0xc5, 0xf9, 0xa1, 0x48, 0x8a, 0x86, - 0x3c, 0x54, 0x49, 0xd1, 0x48, 0x4e, 0xb1, 0x48, 0x26, 0x65, 0xf2, 0xc4, 0x24, 0x4f, 0x6c, 0xf2, 0xb0, 0x4c, 0x1e, - 0x9a, 0xe4, 0xa1, 0x4d, 0xa6, 0xa4, 0x38, 0x14, 0x09, 0x6d, 0xc4, 0xed, 0x66, 0x81, 0x0e, 0x61, 0x04, 0x7e, 0xf4, - 0x44, 0x84, 0xc1, 0xb9, 0xd7, 0xc6, 0xba, 0x65, 0x2e, 0x73, 0x17, 0x2e, 0xb3, 0x02, 0x52, 0xe9, 0x72, 0x04, 0x75, - 0x9e, 0x05, 0x60, 0xc2, 0xda, 0xfe, 0xf1, 0xc1, 0xe0, 0xd6, 0x59, 0x2e, 0x45, 0xe0, 0x52, 0x05, 0x56, 0xe0, 0x9f, - 0x9d, 0x23, 0x09, 0x40, 0x75, 0x4d, 0xf3, 0xf9, 0x94, 0x6e, 0xf9, 0xad, 0x16, 0x93, 0xa1, 0xdb, 0x59, 0x65, 0x33, - 0x8c, 0x16, 0x36, 0xc8, 0x72, 0xdd, 0xc3, 0x10, 0x40, 0xed, 0xbd, 0x1a, 0x13, 0x6a, 0x94, 0xe4, 0xb6, 0xc6, 0xa4, - 0x60, 0x77, 0x2a, 0xa3, 0x39, 0x8b, 0xab, 0x03, 0xb8, 0x1a, 0x26, 0x23, 0x2f, 0xc0, 0x16, 0xbd, 0x38, 0x4c, 0x8e, - 0x1b, 0x3a, 0x99, 0x1c, 0x26, 0xa7, 0x0f, 0x1a, 0x3a, 0x19, 0x1e, 0x26, 0xed, 0x76, 0x85, 0xb3, 0x49, 0x41, 0x74, - 0x32, 0x21, 0x1a, 0x34, 0x86, 0xb6, 0x51, 0x39, 0xa7, 0x60, 0x5c, 0xf5, 0x6f, 0x0c, 0xa3, 0xe1, 0x86, 0x21, 0xd8, - 0xc4, 0xc6, 0x9b, 0xdc, 0x1a, 0x43, 0xd8, 0x4d, 0xe7, 0xf4, 0xb4, 0xa9, 0x93, 0x02, 0x6b, 0xbb, 0x92, 0x4d, 0x9d, - 0x4c, 0xb0, 0xb6, 0xcb, 0xd7, 0xd4, 0xc9, 0xd0, 0x36, 0x65, 0x74, 0x80, 0x4c, 0x04, 0xc0, 0x7a, 0xce, 0x02, 0xc8, - 0x77, 0xbc, 0x7b, 0xc8, 0x1a, 0xb4, 0x86, 0xdf, 0x2b, 0xd7, 0xf4, 0x05, 0x15, 0xd5, 0x60, 0x64, 0xc3, 0xbe, 0x55, - 0xb4, 0x5d, 0x35, 0xc9, 0xfe, 0x75, 0xd9, 0xb2, 0xd9, 0x42, 0xea, 0x7a, 0xc1, 0x87, 0x35, 0x0c, 0x71, 0xa5, 0xdc, - 0xc1, 0xfd, 0x8a, 0x92, 0x18, 0xa2, 0xca, 0x99, 0x53, 0x88, 0x13, 0xaf, 0x47, 0x86, 0x24, 0xde, 0x68, 0xac, 0x51, - 0x1c, 0x9c, 0xb7, 0x4f, 0x43, 0xaa, 0xba, 0x15, 0x6a, 0x8e, 0x90, 0x68, 0x21, 0xac, 0x31, 0xe2, 0x28, 0x0a, 0x58, - 0x10, 0xa7, 0xdd, 0xad, 0x1d, 0x10, 0x07, 0x07, 0x9b, 0xe7, 0x85, 0x0f, 0xfa, 0xbf, 0x15, 0xe8, 0xbf, 0xb2, 0x64, - 0xf3, 0x4f, 0x11, 0x59, 0x1b, 0x57, 0x1e, 0x20, 0x8a, 0x0f, 0xfa, 0x74, 0xdf, 0x50, 0xf8, 0x7e, 0x15, 0xf1, 0xce, - 0xe5, 0x34, 0xcf, 0x4c, 0x86, 0xe9, 0x6b, 0x10, 0x8c, 0xed, 0x4d, 0x38, 0xa1, 0xd2, 0x4a, 0xef, 0x5f, 0x76, 0x1c, - 0x74, 0xe2, 0x9e, 0x4a, 0x09, 0x1b, 0xfd, 0x3b, 0xb4, 0x89, 0xad, 0x60, 0xe3, 0xbc, 0xa1, 0x57, 0xab, 0xda, 0xc3, - 0x38, 0xf6, 0xf9, 0x15, 0x74, 0x70, 0xc0, 0xd5, 0x33, 0x30, 0xe3, 0x65, 0x71, 0x23, 0x3c, 0x7c, 0xff, 0xa9, 0x9d, - 0xd6, 0x7f, 0x9b, 0x73, 0x35, 0x0d, 0x0e, 0xba, 0x87, 0xb5, 0xfc, 0x9d, 0x2b, 0xd1, 0xd3, 0x29, 0x77, 0x6b, 0xfd, - 0x77, 0x65, 0x24, 0xbd, 0xf5, 0x44, 0xd3, 0xc1, 0x01, 0xaf, 0x02, 0x25, 0x45, 0x3f, 0x44, 0xa8, 0x67, 0x64, 0x90, - 0x67, 0xb9, 0xa4, 0x70, 0x23, 0x0a, 0x57, 0x0c, 0x69, 0x83, 0x1f, 0x69, 0xfc, 0x87, 0xfc, 0xff, 0xd4, 0xc8, 0xa1, - 0x4e, 0x1b, 0x3c, 0x10, 0xc0, 0x42, 0x56, 0xa8, 0x0a, 0x51, 0x68, 0x20, 0x1d, 0xda, 0x3c, 0xa3, 0xf2, 0x30, 0xa7, - 0xf3, 0x79, 0x7e, 0x67, 0x5e, 0xa9, 0x0a, 0x38, 0xaa, 0xea, 0xa2, 0xc9, 0xc5, 0x87, 0xc3, 0x05, 0xf0, 0xf4, 0x80, - 0x7b, 0xc8, 0xf8, 0x77, 0x96, 0x97, 0xdb, 0x02, 0x81, 0x64, 0xa6, 0x88, 0x6c, 0xb6, 0xbb, 0xea, 0x12, 0xe4, 0xb2, - 0x66, 0x13, 0x69, 0x17, 0x36, 0x1b, 0x73, 0x90, 0xc9, 0x94, 0xf5, 0xe1, 0xdc, 0xb3, 0x05, 0x41, 0x72, 0x93, 0x46, - 0x64, 0xdb, 0x5d, 0x8a, 0x8f, 0x63, 0x40, 0x23, 0x64, 0x05, 0xbe, 0x50, 0x58, 0xe4, 0xc0, 0x75, 0x16, 0xbe, 0xe3, - 0x6f, 0xb4, 0x54, 0xf4, 0xd5, 0x60, 0x80, 0x0b, 0xf3, 0x30, 0x43, 0x39, 0x9f, 0x42, 0x05, 0x0f, 0xfd, 0x04, 0x22, - 0x0a, 0x5f, 0xad, 0xf6, 0xe1, 0x1d, 0x1d, 0xd7, 0x26, 0x38, 0x7d, 0xba, 0x9f, 0xd5, 0x9b, 0x19, 0x30, 0x0e, 0x46, - 0x5a, 0xe6, 0xa2, 0xd0, 0xc9, 0x9b, 0xec, 0x42, 0x74, 0x1b, 0x0d, 0x66, 0x42, 0x1c, 0x11, 0x88, 0x67, 0x06, 0x1e, - 0x79, 0xf0, 0xc7, 0x46, 0x2d, 0x52, 0xcc, 0xc6, 0x7e, 0x83, 0xa0, 0xd4, 0xb5, 0x84, 0xd5, 0x4a, 0xd9, 0xd8, 0x22, - 0x26, 0xc7, 0x46, 0x19, 0x29, 0xfb, 0x29, 0x83, 0x98, 0x56, 0x66, 0x1c, 0xdc, 0x6d, 0xf5, 0xb7, 0xd5, 0x7e, 0xde, - 0xe3, 0xf6, 0x1a, 0x8f, 0x1b, 0x8f, 0x7d, 0x03, 0xa8, 0xe5, 0xc6, 0x06, 0xb7, 0x16, 0xe6, 0xb1, 0x35, 0x87, 0x65, - 0x9b, 0x10, 0x14, 0xa5, 0x87, 0xba, 0xbd, 0xb9, 0xf5, 0x11, 0xfb, 0x94, 0x99, 0x93, 0x42, 0xba, 0x0f, 0x72, 0xf4, - 0x80, 0x40, 0xe7, 0xf6, 0x67, 0x45, 0x17, 0x2a, 0x99, 0xb8, 0x1c, 0xe3, 0x2f, 0xc1, 0x6d, 0x5e, 0x3f, 0xba, 0xbe, - 0x36, 0x9b, 0xfc, 0xfa, 0x3a, 0xc2, 0xa1, 0x59, 0x77, 0x14, 0xf0, 0x82, 0xd1, 0xa0, 0x0c, 0xea, 0x64, 0x36, 0x7e, - 0xb3, 0x5d, 0x35, 0xf6, 0x9e, 0x56, 0x78, 0x07, 0xcb, 0x63, 0x1a, 0xdf, 0x72, 0x83, 0xec, 0x73, 0x80, 0x37, 0xeb, - 0xf3, 0x41, 0xf7, 0x4d, 0xac, 0xd0, 0xc1, 0xc1, 0x9b, 0x58, 0xa2, 0xde, 0x15, 0x33, 0x77, 0x6e, 0xe0, 0x07, 0xdd, - 0xe7, 0x66, 0xf8, 0x32, 0x40, 0x80, 0x2b, 0xb6, 0x29, 0xd9, 0xbc, 0x35, 0x51, 0x27, 0x52, 0x88, 0x6a, 0x0d, 0xb1, - 0x75, 0x1d, 0x48, 0xa0, 0xd7, 0x37, 0x21, 0xb4, 0xbb, 0x8c, 0x30, 0x60, 0xe1, 0x4b, 0x2f, 0x35, 0x96, 0xcc, 0x58, - 0x31, 0x61, 0xc5, 0x6a, 0xf5, 0x9e, 0x5a, 0xcf, 0xb3, 0x8d, 0x20, 0x89, 0xaa, 0xdb, 0x68, 0x50, 0x33, 0x7e, 0x10, - 0x1f, 0xe8, 0x00, 0xef, 0xbf, 0x89, 0x0b, 0x84, 0xc0, 0xc2, 0x88, 0x8b, 0x85, 0xf7, 0xb2, 0xca, 0x6a, 0xeb, 0x52, - 0xa0, 0xb2, 0x91, 0x9c, 0xb4, 0xf0, 0x94, 0x64, 0xe5, 0x1a, 0x5d, 0x4c, 0xbb, 0x8d, 0x46, 0x8e, 0x64, 0x9c, 0xf5, - 0xf3, 0x01, 0xe6, 0xb8, 0x80, 0xcb, 0xd4, 0xed, 0x75, 0x98, 0xb3, 0x1a, 0xe5, 0x72, 0xf3, 0x5d, 0xda, 0xb1, 0xa6, - 0x8f, 0xe8, 0x3a, 0x00, 0xc6, 0x23, 0x1a, 0x10, 0x89, 0x5d, 0x40, 0x16, 0x16, 0xc8, 0xca, 0x03, 0x59, 0x18, 0x20, - 0x2b, 0xd4, 0x9b, 0x43, 0xb8, 0x20, 0x85, 0xd2, 0x2d, 0x8a, 0x5e, 0x0f, 0x6c, 0xe9, 0x9c, 0x26, 0x30, 0x37, 0xb1, - 0x15, 0xdc, 0x72, 0x80, 0x03, 0x85, 0xf3, 0xc3, 0x53, 0x64, 0x19, 0x45, 0x26, 0xc6, 0x2b, 0xbe, 0x35, 0x7f, 0x92, - 0x5b, 0x7c, 0x67, 0x7f, 0xdc, 0x05, 0xca, 0xa4, 0xe7, 0x35, 0x6d, 0x03, 0x77, 0x11, 0xd1, 0xa2, 0x24, 0x02, 0xb4, - 0x76, 0xe1, 0xfd, 0x44, 0xfd, 0xc5, 0x33, 0x65, 0x03, 0x31, 0x88, 0x06, 0x51, 0x58, 0x04, 0xa4, 0xf3, 0xcf, 0x3f, - 0x23, 0xd4, 0x13, 0x10, 0x47, 0xc7, 0x9d, 0x6c, 0xcd, 0x36, 0x6a, 0x44, 0x49, 0x94, 0xc6, 0x3e, 0x4c, 0x03, 0xec, - 0x8c, 0x28, 0x0a, 0x5e, 0x3b, 0x29, 0x87, 0xf1, 0xa1, 0x36, 0x0c, 0x33, 0xa8, 0x2a, 0xf0, 0xc4, 0xe5, 0x72, 0x33, - 0xcc, 0x8f, 0x81, 0xaa, 0x30, 0x31, 0x56, 0x90, 0x7d, 0x02, 0x8c, 0x11, 0x76, 0x70, 0xc0, 0xfa, 0x62, 0x10, 0xbc, - 0xe9, 0x55, 0x5d, 0x87, 0xeb, 0x70, 0xe1, 0x62, 0x0a, 0x71, 0xd6, 0x57, 0x2b, 0xfb, 0x97, 0x7c, 0x30, 0xd2, 0x0c, - 0x3c, 0xce, 0x16, 0x9c, 0xb1, 0x62, 0xb7, 0x2c, 0x96, 0x68, 0xf9, 0x3b, 0x98, 0xed, 0xb9, 0xa8, 0x79, 0xdc, 0x4d, - 0xb5, 0xed, 0xa1, 0x3e, 0x37, 0x1a, 0x85, 0x20, 0x66, 0x6d, 0x75, 0xa4, 0xe1, 0xb9, 0x0e, 0xf3, 0x6a, 0xb1, 0x67, - 0x33, 0x55, 0x86, 0x10, 0x85, 0x23, 0x25, 0x01, 0xbb, 0x6d, 0x43, 0x27, 0xe1, 0x47, 0x9d, 0x4a, 0x3a, 0x16, 0x12, - 0xa0, 0xc0, 0x91, 0xb9, 0x9c, 0x37, 0x21, 0xe2, 0x19, 0xda, 0x41, 0xe4, 0x02, 0x13, 0x9a, 0xba, 0x6c, 0xe9, 0x62, - 0x39, 0x45, 0x33, 0xb9, 0x50, 0x6c, 0x31, 0x87, 0xf3, 0xbd, 0x4c, 0xcb, 0x72, 0x9e, 0x7d, 0xae, 0xa7, 0x80, 0xfd, - 0xe5, 0xad, 0x9e, 0x31, 0xb1, 0x88, 0xdc, 0x3c, 0xbf, 0x5a, 0x71, 0xff, 0xcd, 0x0b, 0xfc, 0x88, 0x74, 0x0e, 0xbf, - 0xe2, 0x8f, 0x94, 0x3c, 0x6a, 0x7c, 0xc5, 0x13, 0x4e, 0x2c, 0x6f, 0x90, 0xbc, 0x79, 0x7d, 0xf5, 0xe2, 0xdd, 0x8b, - 0xf7, 0x4f, 0xaf, 0x5f, 0xbc, 0x7a, 0xf6, 0xe2, 0xd5, 0x8b, 0x77, 0x1f, 0xf1, 0x3f, 0x94, 0x7c, 0x3d, 0x6a, 0x9f, - 0xb7, 0xf0, 0x07, 0xf2, 0xf5, 0xa8, 0x83, 0x6f, 0x35, 0xf9, 0x7a, 0x74, 0x82, 0x73, 0x45, 0xbe, 0x1e, 0x76, 0x8e, - 0x8e, 0xf1, 0x42, 0xdb, 0x26, 0x73, 0x39, 0x69, 0xb7, 0xf0, 0x3f, 0xee, 0x0b, 0xc4, 0xfb, 0x6a, 0x16, 0x13, 0xb6, - 0x61, 0xfc, 0x60, 0xca, 0xd0, 0xa1, 0x32, 0x86, 0x28, 0x17, 0x01, 0x3a, 0x4d, 0x55, 0x88, 0x4e, 0x36, 0x88, 0x31, - 0xd8, 0x30, 0x02, 0x5a, 0x71, 0xe2, 0xda, 0xe1, 0x47, 0x6d, 0x76, 0x0c, 0xf4, 0x89, 0x97, 0xc2, 0x71, 0xa9, 0xc2, - 0x69, 0x3b, 0x2d, 0xc6, 0x38, 0x97, 0xb2, 0x88, 0x17, 0xc0, 0x08, 0x18, 0xad, 0x05, 0x3f, 0x2a, 0xa3, 0x25, 0x89, - 0x0b, 0xd2, 0xee, 0xb5, 0x53, 0x71, 0x41, 0x3a, 0xbd, 0x0e, 0xfc, 0x39, 0xed, 0x9d, 0xa6, 0xed, 0x16, 0x3a, 0x0c, - 0xc6, 0xf1, 0x47, 0x0d, 0xad, 0xfb, 0x03, 0xec, 0xba, 0x50, 0xff, 0x14, 0xda, 0xab, 0xf4, 0x84, 0x53, 0xc7, 0xb6, - 0xbb, 0xe2, 0x82, 0x19, 0x3d, 0x2c, 0xff, 0x01, 0x50, 0xdb, 0x38, 0x74, 0x94, 0x1b, 0xc7, 0xfd, 0xe2, 0x47, 0x02, - 0xd5, 0x42, 0xb2, 0xc4, 0x6c, 0xd5, 0x42, 0xc0, 0x34, 0x9a, 0x6c, 0x30, 0x07, 0x4a, 0x94, 0x2c, 0xb4, 0x0f, 0x2b, - 0xaf, 0x9a, 0x12, 0x25, 0x73, 0x39, 0x8f, 0x6b, 0xaa, 0x86, 0x5f, 0x03, 0x33, 0xc7, 0x7d, 0xae, 0x5e, 0xd1, 0x57, - 0x71, 0x8d, 0xe7, 0x09, 0x59, 0xbb, 0x70, 0x5b, 0xfc, 0xe2, 0xac, 0x28, 0x6a, 0xe0, 0x2a, 0x01, 0xeb, 0x47, 0xd5, - 0xd4, 0x17, 0xf0, 0x7e, 0x1e, 0x6b, 0xe8, 0x4b, 0x12, 0x50, 0xcf, 0x9f, 0x4a, 0x33, 0xae, 0x52, 0x19, 0xed, 0x15, - 0xd1, 0xc6, 0x2c, 0xc8, 0x2b, 0xa2, 0x2f, 0x94, 0x01, 0x82, 0x24, 0xbc, 0x2f, 0x06, 0x70, 0xe0, 0xdb, 0x01, 0x4a, - 0x43, 0xe7, 0x40, 0xad, 0x54, 0x99, 0x09, 0x99, 0x4f, 0x13, 0x1c, 0x00, 0x34, 0x4f, 0x95, 0x0a, 0xca, 0x7c, 0x62, - 0x89, 0x82, 0xa1, 0xff, 0x16, 0x6e, 0x80, 0xc3, 0xd8, 0xa0, 0x62, 0x90, 0x7d, 0x4f, 0xd4, 0xf3, 0xdb, 0xe7, 0xad, - 0xa3, 0xaf, 0x41, 0xfe, 0x48, 0x79, 0x7b, 0x8f, 0xbf, 0x03, 0x4a, 0x6e, 0xc3, 0x59, 0xb5, 0xb1, 0x8f, 0x44, 0xd6, - 0x0d, 0x01, 0x72, 0xa8, 0xd1, 0x91, 0x79, 0x4a, 0xb0, 0x8b, 0xf4, 0x21, 0x69, 0xb7, 0x20, 0x7c, 0xd8, 0x0e, 0xca, - 0xf7, 0xd3, 0x06, 0x4c, 0x75, 0x72, 0xdb, 0x04, 0x5a, 0x0d, 0xaf, 0x0b, 0xdd, 0x35, 0x79, 0x72, 0x87, 0x55, 0x80, - 0x33, 0xec, 0x90, 0x35, 0xc4, 0xa1, 0x40, 0x2e, 0xec, 0xaa, 0xdd, 0x00, 0x9a, 0x8a, 0x8e, 0x7d, 0xe5, 0xce, 0x1b, - 0x47, 0x5d, 0x34, 0x93, 0xd3, 0xc3, 0xaf, 0x07, 0x07, 0xb1, 0x6c, 0x90, 0x47, 0x08, 0x2f, 0x29, 0x58, 0x31, 0x83, - 0xd7, 0x17, 0xb7, 0x4c, 0x7c, 0xaa, 0x02, 0xea, 0xb8, 0x50, 0xb5, 0x63, 0xad, 0xea, 0xac, 0xdc, 0x0d, 0x7e, 0x4c, - 0x1d, 0xd4, 0x08, 0xd2, 0xec, 0xe8, 0x3a, 0x35, 0x28, 0xd7, 0x5c, 0xb4, 0x60, 0x5b, 0x36, 0x3e, 0x52, 0xf4, 0xc3, - 0xa3, 0xe6, 0xd7, 0x60, 0xc2, 0x35, 0xd3, 0xa4, 0x47, 0x8d, 0x47, 0xe8, 0x87, 0x47, 0x81, 0x93, 0x1d, 0xaf, 0xd8, - 0x13, 0xcf, 0x8d, 0xfc, 0x64, 0xb9, 0xd2, 0x9f, 0x40, 0xb2, 0x2f, 0xc8, 0x4f, 0x80, 0xe5, 0x94, 0xfc, 0x14, 0xcb, - 0x26, 0x04, 0x1f, 0x24, 0x3f, 0xc5, 0x05, 0xfc, 0xc8, 0xc9, 0x4f, 0x31, 0x60, 0x3b, 0x9e, 0x9a, 0x1f, 0x45, 0x09, - 0x0c, 0x70, 0xec, 0x92, 0xd6, 0xbf, 0xab, 0x58, 0xad, 0xc4, 0xc1, 0x81, 0xb4, 0xbf, 0xe8, 0x65, 0x76, 0x70, 0x90, - 0x5f, 0x4c, 0xab, 0xbe, 0x99, 0xde, 0x45, 0x5f, 0x0c, 0x42, 0xe1, 0xc0, 0x34, 0x8d, 0x87, 0x33, 0xfe, 0x14, 0x52, - 0x56, 0xd3, 0x40, 0xf3, 0xb8, 0x73, 0xff, 0xec, 0x1c, 0xc3, 0xbf, 0xf7, 0x83, 0x82, 0x3f, 0x97, 0x7c, 0x17, 0x69, - 0xb3, 0xe6, 0x59, 0x85, 0x6c, 0x97, 0x01, 0x3e, 0x63, 0x86, 0x9a, 0xe2, 0xe0, 0x80, 0x5f, 0x04, 0xb8, 0x8c, 0x19, - 0x6a, 0x04, 0x16, 0x7b, 0x0f, 0x4b, 0x7b, 0x32, 0xc3, 0x35, 0xc1, 0xb3, 0xb2, 0xbc, 0x5f, 0x0c, 0x2e, 0xb4, 0xa3, - 0x26, 0x61, 0xf0, 0x69, 0x45, 0x5a, 0x6e, 0x93, 0x75, 0x45, 0x53, 0x5d, 0xb6, 0xbb, 0x48, 0x12, 0xd5, 0x10, 0x97, - 0x97, 0x6d, 0x0c, 0x2a, 0xf9, 0x9e, 0x22, 0x32, 0x15, 0xc4, 0x3b, 0xc8, 0x2d, 0x73, 0x99, 0x2a, 0x3c, 0xe5, 0xa9, - 0xf0, 0x72, 0xf6, 0x6b, 0x6f, 0x3d, 0x6d, 0x5c, 0x16, 0x4d, 0xcf, 0x0c, 0x8b, 0x9e, 0x2a, 0x5d, 0xed, 0x60, 0x93, - 0xaa, 0x01, 0xbc, 0xda, 0x57, 0x62, 0x1e, 0xb3, 0xfe, 0x65, 0x0c, 0xa2, 0x22, 0xab, 0x46, 0x1b, 0x32, 0xe1, 0x73, - 0x9d, 0x2a, 0x18, 0xa8, 0x29, 0x7c, 0x01, 0x64, 0x2a, 0xab, 0x0c, 0xb3, 0x7d, 0xc3, 0x50, 0x40, 0x40, 0x81, 0x4b, - 0xc2, 0x02, 0x09, 0x1e, 0x6e, 0x3f, 0x02, 0xc2, 0x51, 0x27, 0x17, 0x76, 0x72, 0x17, 0x0a, 0xba, 0x13, 0x83, 0x0b, - 0xdd, 0x45, 0xa2, 0xd1, 0x70, 0xdc, 0xf6, 0xa5, 0x30, 0x83, 0x68, 0xb6, 0x07, 0x97, 0xac, 0x8b, 0x54, 0xb3, 0x59, - 0x1a, 0x40, 0x5e, 0xb6, 0x56, 0x2b, 0x75, 0xe1, 0x1b, 0xe9, 0xf9, 0x73, 0xdc, 0xf0, 0x5d, 0x5e, 0xf0, 0xfc, 0x4d, - 0x92, 0x7e, 0x04, 0x54, 0x15, 0xf8, 0x6c, 0x39, 0x8f, 0x70, 0x64, 0x1e, 0x74, 0x83, 0xbf, 0xe6, 0x21, 0xae, 0x08, - 0x47, 0xee, 0x8d, 0xb7, 0x68, 0x50, 0x0d, 0x96, 0x67, 0x65, 0x78, 0x72, 0x9e, 0x5c, 0x03, 0xe3, 0xa0, 0xff, 0x56, - 0x68, 0x59, 0xfd, 0x4e, 0x72, 0x17, 0xa8, 0x43, 0xf9, 0x67, 0xc7, 0xdc, 0xa8, 0xd6, 0xbb, 0x5d, 0x23, 0x39, 0x8e, - 0x7c, 0x55, 0x08, 0xdf, 0xff, 0x9d, 0x77, 0x0f, 0xdb, 0xee, 0xb9, 0xed, 0x65, 0xd9, 0x03, 0x70, 0xde, 0xeb, 0x35, - 0xc2, 0xbf, 0xc9, 0x9d, 0x6f, 0xef, 0x46, 0xd7, 0x52, 0x3c, 0xa1, 0x9a, 0x46, 0x8d, 0x37, 0xc6, 0xf0, 0xcd, 0xca, - 0x59, 0xdd, 0x6f, 0x8d, 0x83, 0xfd, 0x5b, 0xdd, 0x43, 0xe8, 0x84, 0xda, 0x33, 0x41, 0x56, 0xf6, 0x35, 0x01, 0x33, - 0x64, 0x60, 0xfa, 0xb6, 0x03, 0x1e, 0x7e, 0x8c, 0x14, 0x1c, 0x7a, 0x2d, 0x9f, 0x44, 0x21, 0x26, 0x69, 0xcd, 0x8d, - 0x18, 0x52, 0x6c, 0x1f, 0xc6, 0xe5, 0x74, 0x8d, 0x42, 0xae, 0x7b, 0xac, 0xea, 0xc4, 0xb4, 0xea, 0xc6, 0x48, 0x1d, - 0x6c, 0x93, 0x05, 0x67, 0x55, 0xef, 0x46, 0x42, 0xa9, 0x5e, 0x54, 0x33, 0xaf, 0x62, 0x36, 0xdb, 0xe6, 0x99, 0x61, - 0xfb, 0xee, 0x9a, 0x02, 0x43, 0xde, 0xfd, 0x32, 0x5c, 0xd4, 0x25, 0x1c, 0xbb, 0x71, 0x00, 0x59, 0x49, 0x2e, 0x97, - 0xee, 0x4d, 0x34, 0xde, 0x97, 0x83, 0x75, 0xf9, 0x42, 0x5a, 0x80, 0x07, 0xd5, 0x48, 0x45, 0x16, 0x72, 0x06, 0xfe, - 0x79, 0xc1, 0x9a, 0x7e, 0x88, 0x7f, 0x85, 0x03, 0xbe, 0x42, 0xd2, 0xd4, 0xaa, 0x9f, 0xe0, 0xe5, 0x22, 0x50, 0x78, - 0xdb, 0xba, 0x9f, 0x64, 0xe8, 0x22, 0x5a, 0xd7, 0xa9, 0x58, 0x2f, 0xcc, 0xba, 0x62, 0xa5, 0x2c, 0x1c, 0x1c, 0x77, - 0x31, 0x5a, 0xa7, 0xce, 0x63, 0xd3, 0x3d, 0x77, 0xf4, 0x50, 0xf0, 0x99, 0x71, 0xa4, 0x7b, 0x56, 0x40, 0xfc, 0xaa, - 0x50, 0x9f, 0xf6, 0xb3, 0x0c, 0xdf, 0xf3, 0xed, 0xc3, 0x3d, 0x61, 0xc9, 0x73, 0x96, 0x6f, 0x50, 0xc3, 0x02, 0x29, - 0xa0, 0x50, 0x0a, 0x8b, 0xd5, 0x2a, 0x16, 0x26, 0xaa, 0x81, 0x0b, 0x6a, 0xeb, 0x5e, 0xaf, 0x30, 0xfa, 0x3b, 0xa8, - 0x8b, 0xbd, 0x7a, 0xc4, 0x98, 0xb0, 0xa2, 0xf0, 0xd2, 0x49, 0x65, 0x41, 0x5f, 0xbb, 0xfa, 0x10, 0xd5, 0x94, 0x7b, - 0xb1, 0xd1, 0xf7, 0xbe, 0xe3, 0x33, 0x26, 0x17, 0xf0, 0x6c, 0x10, 0x66, 0x44, 0x31, 0xed, 0xbf, 0x81, 0x82, 0xc0, - 0xdb, 0x33, 0x3c, 0xc4, 0x47, 0xe0, 0xab, 0x3c, 0xad, 0x93, 0x99, 0x7f, 0x8c, 0x22, 0x32, 0xc1, 0x22, 0xa3, 0x5e, - 0x04, 0x5e, 0x43, 0x20, 0x42, 0x11, 0x12, 0x31, 0x31, 0x8a, 0x7a, 0x91, 0x71, 0x52, 0x8a, 0xc0, 0x6a, 0x0c, 0x94, - 0xdc, 0x11, 0x9e, 0xab, 0x8a, 0x88, 0x85, 0x35, 0x75, 0x50, 0x89, 0xa5, 0xc6, 0x4c, 0xfb, 0xa8, 0x53, 0x81, 0xb0, - 0xc8, 0x36, 0x05, 0x65, 0xbd, 0xa1, 0x2e, 0xc0, 0x92, 0x18, 0xd3, 0x5b, 0x9e, 0x5c, 0x03, 0x37, 0xc7, 0x46, 0xae, - 0xe8, 0x92, 0x5f, 0x81, 0x7a, 0x3a, 0x2d, 0xf0, 0xb5, 0x61, 0xd8, 0x46, 0x29, 0x5d, 0x13, 0x8e, 0x33, 0x52, 0x24, - 0xf4, 0x16, 0xa2, 0x3a, 0xcc, 0xb8, 0x48, 0x73, 0x3c, 0xa3, 0xb7, 0xe9, 0x14, 0xcf, 0xb8, 0x78, 0x62, 0x97, 0x3d, - 0x1d, 0x41, 0x92, 0xff, 0x58, 0xac, 0x89, 0x79, 0x94, 0xea, 0x77, 0xc5, 0x8a, 0x47, 0xc0, 0xab, 0xa8, 0x18, 0x75, - 0x47, 0xc6, 0xa6, 0x9c, 0xe9, 0xca, 0x78, 0xfd, 0xb5, 0x8e, 0x29, 0xce, 0x70, 0x8e, 0x92, 0x5c, 0x62, 0xd6, 0x13, - 0xe9, 0x6b, 0x88, 0xe8, 0x9c, 0x61, 0xfb, 0xa0, 0x15, 0xbf, 0x65, 0xf9, 0x33, 0x59, 0xbc, 0x37, 0x5b, 0x3e, 0x47, - 0x50, 0x08, 0x5c, 0x54, 0x44, 0x13, 0x6e, 0xf7, 0x16, 0x3d, 0x59, 0x35, 0x45, 0x6f, 0x6d, 0x53, 0x6e, 0x88, 0x53, - 0x08, 0x85, 0x9b, 0x4c, 0x79, 0xa3, 0x8d, 0x59, 0xaf, 0xf5, 0x9d, 0x46, 0xa7, 0xa8, 0x2c, 0x89, 0x30, 0xac, 0x55, - 0x53, 0xa5, 0x92, 0x88, 0xa6, 0x72, 0x12, 0xde, 0xd2, 0x00, 0x3b, 0x55, 0x38, 0x93, 0x0b, 0xa1, 0x53, 0x19, 0xe0, - 0x0d, 0xad, 0x36, 0xd7, 0xf2, 0xd6, 0x42, 0x4c, 0xe3, 0x3b, 0xfb, 0x83, 0xe1, 0x6b, 0xa3, 0xe2, 0x7f, 0x0b, 0x86, - 0x3d, 0x2a, 0x15, 0x00, 0x3f, 0x30, 0x9c, 0x05, 0xc8, 0x59, 0x7e, 0xf2, 0x16, 0xc0, 0x67, 0x59, 0xc8, 0x3b, 0x48, - 0x65, 0x26, 0xf5, 0x0e, 0x52, 0x19, 0xa4, 0x1a, 0x5f, 0xee, 0x7d, 0x51, 0x29, 0x8b, 0xc2, 0x06, 0x89, 0xc2, 0xa5, - 0x3a, 0x58, 0x12, 0x91, 0x40, 0xbb, 0x46, 0x94, 0x9b, 0x71, 0x01, 0x41, 0xfd, 0xa0, 0x71, 0xfb, 0x4d, 0x6f, 0xe1, - 0xfb, 0xce, 0xe6, 0x33, 0x9f, 0x7f, 0x67, 0xf3, 0x4d, 0x47, 0x1e, 0xe3, 0xeb, 0xb7, 0x9d, 0xc6, 0x32, 0x5e, 0x3a, - 0xac, 0xfd, 0x50, 0x3e, 0xa1, 0xd2, 0x32, 0x4f, 0x55, 0x93, 0x36, 0x9e, 0x04, 0x48, 0xd9, 0xac, 0x78, 0xb8, 0x0e, - 0x6e, 0xb7, 0x0e, 0x63, 0xde, 0x24, 0x6d, 0x84, 0x0e, 0x9d, 0x70, 0x25, 0x62, 0x23, 0x39, 0x1d, 0x3e, 0x3a, 0x82, - 0xbb, 0x97, 0x99, 0xda, 0xf0, 0x95, 0xb2, 0xd5, 0x9a, 0xed, 0xd6, 0x21, 0xdf, 0x59, 0xa5, 0xd1, 0xc6, 0x33, 0x46, - 0x96, 0xe0, 0x5c, 0x46, 0x0b, 0xab, 0x6a, 0x00, 0x27, 0xce, 0x17, 0xe2, 0xb7, 0x05, 0x1d, 0x99, 0xef, 0x43, 0x9b, - 0xf2, 0x7a, 0xa1, 0x7d, 0x52, 0x93, 0xc3, 0x20, 0x3a, 0xc8, 0x95, 0x0c, 0x72, 0x62, 0x7e, 0x44, 0x92, 0x53, 0x74, - 0xd1, 0xee, 0x25, 0xa7, 0x87, 0xfc, 0x90, 0xa7, 0xc0, 0xc3, 0xc6, 0x4d, 0x5f, 0xa1, 0xd9, 0xf6, 0x75, 0x1e, 0x2f, - 0x86, 0x3c, 0x73, 0xcd, 0x57, 0x1d, 0x94, 0xa9, 0x76, 0x8e, 0x90, 0x05, 0x28, 0xe6, 0x7b, 0x09, 0xb2, 0xeb, 0xdd, - 0x1c, 0xf2, 0x14, 0xfa, 0x81, 0x5a, 0x1d, 0x5b, 0xab, 0x1c, 0xdc, 0x6f, 0x0b, 0x40, 0x30, 0xdf, 0x51, 0x6d, 0x2e, - 0x36, 0xbd, 0x19, 0x57, 0x9d, 0x1d, 0xf2, 0x6a, 0x84, 0x61, 0x99, 0xed, 0xfe, 0xfc, 0xd4, 0xaa, 0x2e, 0x0f, 0x03, - 0x88, 0xfc, 0xb6, 0xe0, 0x22, 0xec, 0x34, 0xec, 0xd6, 0xe5, 0x84, 0x9d, 0xd6, 0x67, 0x19, 0x14, 0xd9, 0xee, 0x75, - 0x6b, 0xa6, 0xf5, 0xd9, 0x5e, 0x81, 0x8f, 0x20, 0x4c, 0xca, 0xac, 0x74, 0x06, 0x57, 0xe8, 0x87, 0x1f, 0x90, 0x6b, - 0xfd, 0xf5, 0x42, 0xfb, 0xfc, 0x12, 0x11, 0x20, 0xbb, 0xea, 0xba, 0xac, 0x0e, 0x7d, 0x94, 0x4d, 0x7c, 0x3d, 0xe4, - 0xc1, 0xca, 0x3d, 0xbd, 0x9d, 0xcb, 0xd4, 0xe3, 0x6b, 0xaf, 0x95, 0x6e, 0x21, 0x27, 0x10, 0x0f, 0xd7, 0x5d, 0x58, - 0x16, 0xe4, 0xec, 0xe6, 0x16, 0x4a, 0x86, 0x13, 0xf7, 0xa5, 0x3f, 0x30, 0x7b, 0xdd, 0xc0, 0x2f, 0x92, 0x53, 0x98, - 0xfa, 0x66, 0x0f, 0x87, 0x1d, 0xe8, 0xc3, 0xc0, 0x61, 0xb3, 0x41, 0x9f, 0x59, 0x41, 0xe4, 0x31, 0x2f, 0x2c, 0x9e, - 0x5d, 0x92, 0x76, 0x8f, 0xa7, 0x6e, 0x33, 0x19, 0xd1, 0xa8, 0xdd, 0xe4, 0xc1, 0xcc, 0x00, 0xbf, 0x5c, 0xd9, 0xb0, - 0x88, 0x5f, 0xa7, 0x00, 0x4a, 0xbe, 0x58, 0xb5, 0x3e, 0x15, 0xbc, 0xea, 0x0d, 0xa7, 0x9b, 0xe9, 0x7e, 0xdd, 0xe0, - 0x76, 0xd7, 0xc3, 0x13, 0x9e, 0x40, 0xb1, 0x68, 0xed, 0x27, 0x3e, 0x01, 0x0e, 0x28, 0x69, 0xdd, 0x3f, 0x05, 0x17, - 0xca, 0x12, 0x96, 0xdb, 0xe5, 0x66, 0x5b, 0xe5, 0x2c, 0x1c, 0x6d, 0xc9, 0x80, 0x3b, 0xd8, 0x84, 0x28, 0x74, 0x70, - 0xd8, 0xc1, 0x49, 0xbb, 0xdd, 0x39, 0xc5, 0xc9, 0xc9, 0x29, 0x0c, 0xb4, 0x91, 0x9c, 0x1e, 0xce, 0x94, 0x05, 0x60, - 0x90, 0xb3, 0x76, 0xed, 0x3e, 0x82, 0x70, 0x49, 0xa1, 0x78, 0xcd, 0x0f, 0xe3, 0xb8, 0x9d, 0xdc, 0x6f, 0xb5, 0x4f, - 0xcf, 0x1b, 0x00, 0xa0, 0xa6, 0xfb, 0x70, 0x35, 0x5e, 0x2f, 0x74, 0xbd, 0x4a, 0x89, 0xf0, 0xf5, 0x6a, 0x0d, 0x5f, - 0xad, 0xd1, 0x5e, 0x57, 0x53, 0xf0, 0x55, 0x9d, 0x70, 0x6e, 0x8b, 0x78, 0xa5, 0x4d, 0xb8, 0x2d, 0x62, 0x3b, 0x90, - 0x18, 0xa4, 0xf3, 0xe4, 0xb4, 0x73, 0x8a, 0xec, 0x58, 0xb4, 0xc3, 0x8f, 0x72, 0x9f, 0x6c, 0x15, 0x69, 0x68, 0x40, - 0x92, 0x72, 0x76, 0x72, 0x01, 0x12, 0x35, 0x27, 0x97, 0xed, 0xe6, 0x8c, 0x25, 0x7e, 0x02, 0x26, 0x15, 0x96, 0xb3, - 0x5c, 0x05, 0x97, 0x14, 0x00, 0xe2, 0x02, 0x8c, 0x8b, 0xee, 0x9f, 0xf6, 0xee, 0x27, 0xa7, 0x67, 0x1d, 0x4b, 0xf4, - 0xf8, 0x45, 0xa7, 0x96, 0x66, 0xa6, 0x9e, 0x9c, 0x9a, 0x34, 0xe8, 0x3a, 0xb9, 0x7f, 0x0a, 0x65, 0x5c, 0x4a, 0x58, - 0x0a, 0xc2, 0x3c, 0x54, 0xc5, 0x20, 0xb6, 0x43, 0x5a, 0xcb, 0x3d, 0xab, 0x65, 0x9f, 0x9f, 0x1c, 0xdf, 0x3f, 0x0d, - 0xa1, 0x56, 0xce, 0xc2, 0x2c, 0xb4, 0x9b, 0x88, 0x9f, 0x1d, 0x2c, 0x2d, 0x3a, 0x4c, 0x4e, 0xd3, 0xad, 0x09, 0xda, - 0x4d, 0x73, 0x68, 0x70, 0x20, 0x50, 0x38, 0x3e, 0x15, 0x4e, 0x5f, 0x12, 0xdc, 0x8f, 0x55, 0x86, 0x26, 0xa1, 0xc2, - 0xd9, 0xdf, 0x53, 0x06, 0x2f, 0x39, 0x86, 0x57, 0x95, 0x8f, 0xa9, 0xf8, 0x42, 0xd5, 0x1b, 0x0a, 0xb1, 0x2b, 0xc4, - 0x20, 0x72, 0x91, 0xb5, 0xeb, 0xb9, 0x3f, 0x81, 0x8b, 0x30, 0x13, 0x70, 0xa1, 0xe9, 0x95, 0xa0, 0x15, 0x2f, 0x30, - 0x0c, 0x1d, 0x6a, 0xcd, 0xb0, 0x7a, 0x3c, 0x75, 0x26, 0x05, 0xa1, 0x6e, 0xeb, 0x39, 0xff, 0x5e, 0xb9, 0xa4, 0xbc, - 0xca, 0x4e, 0x4e, 0x51, 0xe2, 0x2e, 0xcb, 0x93, 0x36, 0x4a, 0x02, 0x13, 0x12, 0x77, 0x24, 0x67, 0x19, 0xe9, 0x47, - 0xb7, 0x11, 0x8e, 0xee, 0x22, 0x1c, 0x59, 0x1f, 0xe6, 0x0f, 0xe0, 0x3c, 0x1f, 0xe1, 0xc8, 0xba, 0x32, 0x47, 0x38, - 0xd2, 0x4c, 0x40, 0x48, 0xab, 0x68, 0x80, 0x73, 0x28, 0x6d, 0x3c, 0xab, 0xcb, 0xd2, 0x8f, 0xfd, 0x57, 0xe9, 0x7a, - 0x6d, 0x53, 0x02, 0x29, 0x73, 0x6a, 0x76, 0xa8, 0x7d, 0x92, 0x39, 0xa2, 0x9e, 0x59, 0x8f, 0x30, 0x08, 0x20, 0xf4, - 0xce, 0x3f, 0xe9, 0x56, 0x45, 0xc3, 0x60, 0xc7, 0xb0, 0xd2, 0xe0, 0x67, 0x1e, 0x85, 0x67, 0x58, 0x84, 0xc7, 0xc2, - 0x17, 0x06, 0xb1, 0xc2, 0xff, 0xce, 0xa5, 0x9c, 0xfb, 0xdf, 0x5a, 0x96, 0xbf, 0xe0, 0x21, 0x10, 0x67, 0xd1, 0x02, - 0x96, 0x5b, 0x36, 0xf8, 0xce, 0x90, 0xd5, 0x47, 0x70, 0x3d, 0x76, 0x01, 0xd2, 0x40, 0x22, 0xbc, 0x36, 0x02, 0x95, - 0x97, 0x0f, 0xaf, 0x6d, 0xb0, 0x1e, 0xf3, 0x09, 0xd1, 0xba, 0x20, 0x20, 0xaf, 0x84, 0x0b, 0x8d, 0x49, 0xc1, 0x94, - 0x8a, 0x6c, 0x14, 0xbb, 0x48, 0x0a, 0xff, 0x2c, 0xa1, 0x4f, 0x19, 0x8b, 0xc8, 0x74, 0x58, 0x9f, 0xad, 0x15, 0x87, - 0x73, 0x59, 0xa8, 0xd4, 0xbe, 0x51, 0xe2, 0xc1, 0x58, 0x3d, 0x55, 0x9f, 0xe6, 0xd9, 0x1a, 0xdb, 0x3b, 0xec, 0xb2, - 0x90, 0xbb, 0xd2, 0x0e, 0x4b, 0x65, 0xd9, 0xfa, 0x5b, 0x13, 0x52, 0xb5, 0x19, 0x05, 0x13, 0xad, 0x06, 0x54, 0x85, - 0xb2, 0x80, 0xc2, 0x36, 0x1c, 0x4a, 0xba, 0x2c, 0x4b, 0xa6, 0xcb, 0x72, 0x19, 0x4e, 0x5a, 0xad, 0xf5, 0x1a, 0x17, - 0xcc, 0x84, 0x65, 0xd9, 0x59, 0x02, 0xf2, 0xd5, 0x54, 0xde, 0x04, 0xb9, 0x2a, 0x2d, 0x67, 0x69, 0x96, 0x28, 0x0a, - 0x8c, 0x60, 0xa3, 0x35, 0xfe, 0xc2, 0x15, 0x07, 0x78, 0xba, 0xd9, 0x0d, 0xa5, 0xcc, 0x19, 0x85, 0xe8, 0x5d, 0x41, - 0x93, 0x6b, 0x3c, 0xe5, 0x23, 0xb6, 0xbb, 0x4d, 0x30, 0x63, 0xfe, 0xf7, 0x5a, 0xf4, 0x08, 0x64, 0xd9, 0x3d, 0x83, - 0x3a, 0xb0, 0x88, 0x2b, 0xe8, 0x20, 0x94, 0xc1, 0x47, 0x21, 0x6e, 0xe6, 0xf4, 0x4e, 0x2e, 0x34, 0xc0, 0x65, 0xa1, - 0xe5, 0x1b, 0x17, 0xeb, 0x60, 0xbf, 0x85, 0x7d, 0xd8, 0x83, 0x25, 0x84, 0x0c, 0x68, 0x61, 0x1b, 0x23, 0xa2, 0x85, - 0x87, 0x52, 0x6b, 0x39, 0x4b, 0x5b, 0xd8, 0x04, 0x6c, 0x68, 0xad, 0xcb, 0xa8, 0x5a, 0xd7, 0xe5, 0x63, 0x8e, 0xd5, - 0x26, 0x58, 0x38, 0xe9, 0x50, 0x13, 0x1d, 0xdc, 0x1e, 0x32, 0xc2, 0x1b, 0x3f, 0x5f, 0xbd, 0x7e, 0xe5, 0x62, 0x26, - 0xf3, 0x31, 0xb8, 0x6c, 0x3a, 0xd5, 0xd8, 0xb5, 0x79, 0x05, 0x29, 0xae, 0x14, 0xa5, 0x56, 0x38, 0x85, 0x96, 0x5f, - 0x08, 0x9d, 0x27, 0xf6, 0xf2, 0xe2, 0x99, 0x2c, 0x66, 0xd4, 0xde, 0x18, 0xe1, 0x6b, 0xe5, 0x9e, 0x3d, 0x37, 0x2f, - 0xab, 0x54, 0x93, 0x7c, 0xb7, 0x79, 0x15, 0xb1, 0xc8, 0x8c, 0xfc, 0x0a, 0xda, 0x00, 0x53, 0xb9, 0x7c, 0xb5, 0xb6, - 0x20, 0x2e, 0xf2, 0x7c, 0x40, 0x5e, 0xde, 0x5a, 0xea, 0x12, 0x45, 0x0d, 0x6e, 0xf0, 0x93, 0x15, 0x3c, 0x0b, 0xae, - 0x0b, 0x0d, 0x7b, 0xe4, 0xc4, 0x8b, 0xa8, 0x15, 0xd5, 0x5f, 0x7d, 0x35, 0xaa, 0x04, 0x1f, 0xb5, 0x34, 0xc9, 0x25, - 0x88, 0x1e, 0xe5, 0x03, 0x73, 0x1c, 0x44, 0x13, 0x7f, 0xf7, 0x7c, 0xd9, 0xf6, 0x74, 0x36, 0xaf, 0xd4, 0x89, 0xe5, - 0x95, 0x09, 0x78, 0x38, 0xda, 0x27, 0x5c, 0x10, 0x0e, 0x12, 0x59, 0xa9, 0x3d, 0xf4, 0xb9, 0xa8, 0x1b, 0xe7, 0x17, - 0x6d, 0xd6, 0x3c, 0x59, 0xad, 0xf2, 0xcb, 0x36, 0x6b, 0x9f, 0xda, 0x07, 0xdf, 0x22, 0x95, 0x01, 0xcd, 0xe5, 0x63, - 0x9e, 0x45, 0xa0, 0x9d, 0x1d, 0x67, 0x26, 0x9c, 0x82, 0x0f, 0x51, 0x4c, 0x16, 0xba, 0xea, 0x4b, 0x82, 0x71, 0x29, - 0xb1, 0x7a, 0xfc, 0x02, 0xf5, 0xda, 0xe9, 0xb6, 0xab, 0x74, 0xb3, 0x7d, 0x18, 0x5c, 0xb8, 0x14, 0x08, 0x77, 0x20, - 0xe4, 0x01, 0xe8, 0x77, 0x97, 0x02, 0x4c, 0x83, 0x00, 0x95, 0x15, 0x88, 0xb4, 0x7c, 0xb6, 0x98, 0x3d, 0x2b, 0xa8, - 0x59, 0x86, 0x27, 0x7c, 0xc2, 0xb5, 0x4a, 0x29, 0x48, 0xb7, 0xbb, 0xd2, 0xd7, 0xbb, 0x25, 0xa8, 0xac, 0x16, 0xf9, - 0x35, 0xd1, 0x3c, 0xfb, 0xac, 0xdc, 0xc2, 0x21, 0x6c, 0x56, 0x56, 0xe0, 0x0c, 0xad, 0x71, 0x2e, 0x27, 0xb4, 0xe0, - 0x7a, 0x3a, 0xfb, 0xb7, 0x56, 0x87, 0xf5, 0xf5, 0xc0, 0x5c, 0x58, 0x01, 0x48, 0xa8, 0x18, 0xad, 0x56, 0xfc, 0xe8, - 0xfb, 0xf7, 0x49, 0xde, 0x27, 0xbc, 0x8d, 0x3b, 0xf8, 0x18, 0x9f, 0xe2, 0x76, 0x0b, 0xb7, 0x4f, 0xe1, 0xea, 0x3e, - 0xcb, 0x17, 0x23, 0xa6, 0x62, 0x78, 0xf9, 0x4b, 0x5f, 0x26, 0xe7, 0x87, 0x65, 0xbc, 0x7b, 0x5d, 0x24, 0x0e, 0x5d, - 0x82, 0xb0, 0xeb, 0x2e, 0x5e, 0x5d, 0x14, 0x85, 0xc1, 0xd2, 0xc6, 0xa1, 0xea, 0xa4, 0xd4, 0x2f, 0x5c, 0x1e, 0xf7, - 0xc0, 0x9e, 0xdb, 0xae, 0x6c, 0x13, 0xcc, 0xbe, 0xed, 0xcf, 0xb4, 0xfa, 0xd9, 0xd4, 0x25, 0x62, 0x78, 0xe8, 0x55, - 0xe8, 0x81, 0x2e, 0x49, 0xfb, 0xe0, 0x00, 0xac, 0x8e, 0x82, 0xd9, 0x70, 0x1b, 0xfd, 0x80, 0x37, 0x6b, 0x69, 0x10, - 0xac, 0x00, 0x8c, 0x3b, 0xdf, 0x70, 0xb2, 0xb4, 0xb0, 0xd5, 0x40, 0x85, 0x75, 0x11, 0x46, 0x74, 0x0b, 0x49, 0x85, - 0x11, 0xa2, 0xe1, 0x08, 0x73, 0x91, 0x4e, 0xf6, 0x5b, 0x58, 0x8e, 0xc7, 0x8a, 0x69, 0x38, 0x3a, 0x0a, 0xf6, 0x85, - 0x15, 0xca, 0x9c, 0x22, 0x43, 0x36, 0xe1, 0xe2, 0xa1, 0xfe, 0xc4, 0x0a, 0x69, 0x3e, 0x8d, 0x06, 0x23, 0x8d, 0xcc, - 0x2a, 0x46, 0x38, 0xcb, 0xf9, 0x1c, 0xaa, 0x4e, 0x0a, 0x70, 0xfa, 0x81, 0xbf, 0x7c, 0x94, 0x86, 0x6d, 0x02, 0xf9, - 0xfa, 0x60, 0x83, 0xd9, 0xe0, 0x51, 0x41, 0x6f, 0x5e, 0x8b, 0xc7, 0xb0, 0xa3, 0x1e, 0x16, 0x8c, 0x42, 0x36, 0x24, - 0xbd, 0x83, 0xa6, 0xe0, 0x03, 0xda, 0x7c, 0x69, 0x00, 0x97, 0x9e, 0x9b, 0x0f, 0x5b, 0xd1, 0x47, 0x0d, 0x4c, 0xca, - 0xb6, 0x4c, 0xa6, 0x39, 0xa5, 0xab, 0x4c, 0x1b, 0x97, 0xa9, 0x9c, 0xc2, 0x1a, 0xbb, 0xa8, 0x27, 0xe1, 0x60, 0x46, - 0x54, 0x4d, 0xd3, 0xfe, 0xc0, 0xfc, 0x7d, 0x6d, 0x4b, 0xb6, 0xb0, 0x0b, 0xb5, 0xb3, 0xc6, 0xe6, 0xc9, 0xce, 0xa0, - 0x7c, 0x1b, 0xc3, 0x3d, 0x2c, 0xbc, 0x1b, 0x59, 0x23, 0x9f, 0x27, 0x9e, 0x6c, 0x9e, 0xac, 0xd7, 0x66, 0x20, 0x2a, - 0x05, 0x3d, 0xd0, 0x5b, 0xbf, 0x6d, 0x5a, 0xb0, 0x3d, 0xca, 0xaf, 0xd3, 0x16, 0x9e, 0x71, 0x78, 0x06, 0xd3, 0xb7, - 0x77, 0xa5, 0x0b, 0xf9, 0xd9, 0x81, 0xa4, 0x15, 0xa4, 0xd8, 0xe9, 0x04, 0x9d, 0x1d, 0xe3, 0x60, 0xe4, 0x40, 0xcf, - 0xaf, 0x3e, 0x5b, 0x58, 0xfb, 0xdf, 0x6f, 0xca, 0x82, 0x39, 0x1d, 0xb2, 0xbc, 0x9c, 0x50, 0xe6, 0xcf, 0xcf, 0x37, - 0x3c, 0xa9, 0x50, 0xc1, 0xbd, 0x1f, 0x05, 0x7b, 0xda, 0x86, 0x98, 0x9c, 0xd1, 0xbf, 0xed, 0x0f, 0x1b, 0x11, 0xa8, - 0xd4, 0xb2, 0x65, 0x85, 0x54, 0xea, 0xa1, 0x4d, 0xb3, 0x47, 0x0f, 0x1c, 0x91, 0x2f, 0xa1, 0x0b, 0xe0, 0xf5, 0x47, - 0x85, 0x9c, 0x1b, 0x44, 0x70, 0xbf, 0xdd, 0xb8, 0x8d, 0xaf, 0x00, 0x78, 0x3b, 0xec, 0x55, 0xff, 0xb4, 0x80, 0xfd, - 0x8d, 0xca, 0x92, 0x7e, 0xbc, 0x1d, 0x7b, 0xfc, 0x17, 0x12, 0xe2, 0x95, 0x5b, 0x3c, 0x4c, 0x1c, 0x3a, 0x95, 0xac, - 0x59, 0xf9, 0x73, 0xab, 0x24, 0x60, 0x58, 0xbd, 0x60, 0xc8, 0xc6, 0x6d, 0x15, 0xb7, 0x99, 0xff, 0x41, 0x05, 0x83, - 0x05, 0xdf, 0x1a, 0x49, 0xc5, 0xb2, 0xf8, 0xed, 0x53, 0xe7, 0xbf, 0xea, 0x1c, 0xd7, 0xbe, 0xae, 0xbd, 0x51, 0x39, - 0x34, 0xf1, 0x81, 0x23, 0x74, 0x70, 0xb0, 0x91, 0x41, 0xc7, 0x00, 0x78, 0xe4, 0xd8, 0x2f, 0xbf, 0x7c, 0x9e, 0x1d, - 0x33, 0x9a, 0xc7, 0x22, 0x0a, 0x99, 0x3b, 0xcf, 0xcd, 0xd9, 0x89, 0x3c, 0xa1, 0x6a, 0xea, 0x0b, 0x03, 0x1c, 0x1f, - 0x6d, 0xa5, 0x02, 0xbe, 0x47, 0xeb, 0x1d, 0x13, 0xd8, 0xe0, 0xb7, 0xec, 0xa4, 0x76, 0x15, 0xf4, 0x0b, 0xb4, 0xdc, - 0xc5, 0x54, 0x6e, 0x2c, 0x70, 0xb4, 0x39, 0x91, 0x9d, 0x43, 0xdf, 0xa8, 0x53, 0xb2, 0x1e, 0x4f, 0x76, 0x1b, 0x7d, - 0x49, 0xb1, 0x2b, 0xb9, 0xa2, 0x6d, 0x43, 0x56, 0xbd, 0x53, 0xab, 0x2b, 0x53, 0xa7, 0xea, 0x9a, 0xb7, 0xb2, 0xb4, - 0x29, 0xed, 0x92, 0xec, 0xdd, 0x16, 0x0b, 0xaf, 0xc2, 0x1b, 0x8d, 0xf2, 0x22, 0x14, 0xec, 0xb1, 0xc4, 0xa0, 0xcb, - 0x09, 0x5c, 0x2f, 0xac, 0x56, 0x31, 0xfc, 0xd9, 0x35, 0x86, 0x5d, 0xa6, 0x4b, 0x1f, 0xf8, 0x06, 0xbf, 0x12, 0x84, - 0xca, 0x75, 0x76, 0x90, 0x60, 0xdd, 0xe5, 0x06, 0x0d, 0xc7, 0x89, 0xff, 0x82, 0x87, 0x9a, 0xb5, 0x77, 0x39, 0x98, - 0x64, 0xdf, 0x78, 0xdc, 0xad, 0x64, 0x2d, 0x6b, 0x71, 0xd6, 0x37, 0x24, 0x18, 0x62, 0x37, 0xa5, 0x73, 0xdc, 0x4a, - 0xda, 0x28, 0x72, 0xc5, 0x2a, 0xf4, 0xff, 0x56, 0x91, 0xcc, 0x66, 0xfe, 0xd7, 0xd9, 0xd9, 0x99, 0x4b, 0x71, 0x36, - 0x7f, 0xca, 0x78, 0xc0, 0x99, 0x04, 0xf6, 0x85, 0x67, 0xcc, 0xe8, 0x90, 0xdf, 0xc2, 0x50, 0x88, 0x20, 0x97, 0xc2, - 0xb1, 0x4b, 0xf0, 0xce, 0x20, 0x50, 0x1e, 0x60, 0xff, 0x9e, 0x6c, 0x94, 0xf3, 0x0f, 0x15, 0xf9, 0x40, 0xbe, 0x65, - 0x83, 0xec, 0x8b, 0xf9, 0xec, 0x5b, 0x33, 0x19, 0x88, 0xcd, 0x1f, 0x61, 0xfb, 0xdb, 0xb0, 0xb4, 0xce, 0x52, 0x06, - 0x47, 0x5a, 0x2e, 0xb2, 0xa9, 0xd5, 0xfc, 0xbb, 0x0f, 0x53, 0xd6, 0x3d, 0x72, 0x03, 0x41, 0xb9, 0xc8, 0xd2, 0xc5, - 0xa3, 0x8c, 0x7e, 0x2c, 0x43, 0x4f, 0xee, 0xbd, 0x62, 0x0b, 0xf6, 0x23, 0xde, 0xab, 0x52, 0xe0, 0xe3, 0x61, 0xc1, - 0x69, 0xfe, 0x23, 0xde, 0xab, 0x42, 0x50, 0x82, 0x2b, 0xa4, 0x89, 0xe2, 0x88, 0xcd, 0x83, 0xce, 0x69, 0x24, 0x80, - 0x82, 0xe6, 0x91, 0x39, 0xc8, 0x9e, 0xbb, 0xa8, 0x85, 0x49, 0x07, 0xbb, 0xb8, 0x5f, 0x36, 0x16, 0xa9, 0x0d, 0xe1, - 0x0d, 0x91, 0xdc, 0xca, 0xd9, 0x98, 0xaf, 0x47, 0x1b, 0x0b, 0x62, 0x94, 0xc9, 0xe4, 0xf2, 0x39, 0x8f, 0xb7, 0x16, - 0x0b, 0x85, 0xd5, 0x82, 0x05, 0xaa, 0x55, 0xa9, 0xd2, 0xc3, 0xe2, 0xdb, 0x05, 0xb3, 0xa0, 0x88, 0xd9, 0x7a, 0x0f, - 0x6f, 0xb9, 0x22, 0x20, 0x25, 0xbb, 0x24, 0x78, 0x93, 0xdb, 0x60, 0xaa, 0x7f, 0x82, 0x1d, 0x08, 0x3d, 0x53, 0x3a, - 0xc2, 0x26, 0x4f, 0x41, 0x24, 0xb1, 0xfd, 0x16, 0x76, 0xac, 0xd1, 0x0b, 0xe1, 0x85, 0x14, 0x38, 0x57, 0x4d, 0x13, - 0x33, 0xca, 0x4d, 0x74, 0xb1, 0x87, 0x6a, 0xce, 0x32, 0x6d, 0x11, 0x60, 0xdf, 0xa1, 0xa1, 0x14, 0xcf, 0x0d, 0x28, - 0xcc, 0x63, 0xd2, 0x2e, 0xe5, 0x31, 0x2c, 0x5e, 0x90, 0x02, 0x44, 0x8d, 0x8b, 0x49, 0x59, 0x67, 0x9e, 0x2f, 0x26, - 0x5c, 0x54, 0xc8, 0x50, 0x30, 0x35, 0x97, 0x02, 0xde, 0x72, 0x28, 0x8b, 0x18, 0x3a, 0x54, 0xc3, 0x77, 0x4b, 0xc2, - 0xca, 0x3a, 0xe6, 0x98, 0xe2, 0xa2, 0xaa, 0x01, 0xcc, 0xc5, 0xc3, 0xf0, 0xd1, 0x77, 0xf5, 0x5a, 0xbc, 0x93, 0xf3, - 0x2a, 0xdf, 0xd3, 0x38, 0x1f, 0x32, 0xdd, 0xd9, 0x0d, 0xa3, 0xb5, 0x79, 0x6e, 0x29, 0xd8, 0xbe, 0x1f, 0x78, 0xf5, - 0x04, 0xd9, 0xda, 0x3c, 0xd8, 0x54, 0x66, 0x0d, 0x59, 0xf9, 0x3a, 0x41, 0xd5, 0x5e, 0xbd, 0xaa, 0x14, 0xb6, 0x22, - 0x40, 0xa5, 0xe0, 0xa3, 0xad, 0xfc, 0x27, 0xda, 0xe6, 0xdb, 0x73, 0xa8, 0x0c, 0x0f, 0xe4, 0xc9, 0x50, 0xd5, 0x03, - 0x2e, 0xca, 0x0f, 0x01, 0x2c, 0x7e, 0x64, 0x22, 0xd7, 0xee, 0xba, 0x40, 0xe6, 0x4c, 0xc5, 0x12, 0x2f, 0xfb, 0x74, - 0x90, 0x5a, 0x79, 0x28, 0x95, 0x60, 0xdb, 0x73, 0x53, 0x70, 0xed, 0x43, 0xe4, 0xe2, 0x3e, 0x1b, 0xa4, 0xcb, 0x7a, - 0x18, 0x5d, 0x1b, 0xc8, 0xd7, 0x9b, 0x73, 0x9a, 0xb8, 0xb3, 0x74, 0x80, 0x73, 0x02, 0xb6, 0xc7, 0x9e, 0x3d, 0x7d, - 0x13, 0x67, 0xa8, 0x57, 0xe7, 0xf0, 0x97, 0x6b, 0x9c, 0xe3, 0x0c, 0xa5, 0x0f, 0x63, 0xb8, 0xc0, 0x5a, 0x63, 0x00, - 0x5f, 0x66, 0x49, 0x15, 0x78, 0xa4, 0x66, 0x46, 0x62, 0x75, 0x17, 0x81, 0x68, 0xa9, 0xc3, 0xdb, 0x71, 0xe6, 0x03, - 0x51, 0x1b, 0xee, 0xf5, 0x99, 0x11, 0x0e, 0x27, 0x59, 0x5c, 0x3b, 0x67, 0x38, 0xb9, 0xdc, 0xe7, 0xb5, 0x13, 0x13, - 0xac, 0xbd, 0xc3, 0x53, 0x05, 0xf4, 0x68, 0x70, 0xaa, 0x58, 0x1a, 0x02, 0x31, 0x13, 0xc0, 0x9b, 0x39, 0x3c, 0xda, - 0x02, 0x9c, 0x8f, 0xd6, 0x38, 0xf8, 0x4a, 0x6b, 0x5d, 0x6d, 0x2a, 0x51, 0xd6, 0x6b, 0xdc, 0x9f, 0x66, 0x78, 0x94, - 0xe1, 0x79, 0x36, 0x08, 0x8e, 0x9b, 0x59, 0x16, 0x9a, 0x74, 0xad, 0x56, 0x4f, 0x9d, 0x19, 0x21, 0xb2, 0x3f, 0x2d, - 0xfd, 0x41, 0x3d, 0x40, 0xf8, 0x14, 0xb2, 0x80, 0x96, 0xf4, 0xdc, 0xdf, 0x86, 0x7d, 0xa7, 0x1a, 0x35, 0x62, 0x9e, - 0x58, 0x32, 0xd2, 0xf3, 0x3f, 0xca, 0x2c, 0xdb, 0x5a, 0x23, 0x9a, 0xdf, 0xee, 0x45, 0x0d, 0xdf, 0x5e, 0xa0, 0x65, - 0x2b, 0xcd, 0x76, 0x00, 0x51, 0xac, 0x71, 0x92, 0x0e, 0xd6, 0x48, 0xae, 0x56, 0xb1, 0x4d, 0x21, 0x3c, 0x99, 0x31, - 0xaa, 0x16, 0x85, 0x79, 0xba, 0x2d, 0x56, 0x28, 0x31, 0xfc, 0x2e, 0x76, 0x36, 0xa2, 0xf0, 0x52, 0x9a, 0x04, 0xc3, - 0x8d, 0x58, 0x10, 0x59, 0x13, 0xb9, 0x87, 0x59, 0x65, 0x19, 0x24, 0x88, 0x30, 0x22, 0xbf, 0xbd, 0x2e, 0x15, 0xf6, - 0x71, 0x38, 0xfb, 0xc7, 0xf8, 0x02, 0xc2, 0xcd, 0xdb, 0x84, 0x16, 0x43, 0x3a, 0x01, 0x36, 0x16, 0xe2, 0x10, 0x6e, - 0x25, 0xac, 0x56, 0xfd, 0x41, 0x57, 0x18, 0xf2, 0xec, 0x9e, 0xae, 0x2b, 0x1b, 0xda, 0xdd, 0x00, 0x5c, 0x75, 0x5b, - 0x6a, 0xae, 0x8d, 0xee, 0x87, 0x9a, 0xd7, 0xb5, 0xb8, 0x4b, 0x72, 0x0f, 0x64, 0x54, 0x6f, 0x60, 0xd7, 0x2c, 0xc0, - 0x4d, 0xe8, 0x2a, 0x3c, 0xc2, 0x0b, 0x6b, 0xc3, 0x69, 0x9e, 0x52, 0xa2, 0xe6, 0x05, 0x25, 0x78, 0xb8, 0x99, 0xb0, - 0x7e, 0x36, 0xc0, 0x23, 0x1f, 0x68, 0x7b, 0xff, 0x6d, 0x3c, 0x42, 0xa8, 0x20, 0x06, 0xa6, 0xd6, 0x65, 0x7b, 0x54, - 0xd9, 0xed, 0x9b, 0x4c, 0xc3, 0x30, 0x18, 0x23, 0xe6, 0x51, 0x68, 0xc4, 0x9c, 0x37, 0x1a, 0x68, 0x41, 0x46, 0x60, - 0xc4, 0xbc, 0x08, 0x5a, 0x5b, 0xd8, 0x67, 0x36, 0x83, 0xf6, 0x16, 0x08, 0x75, 0x39, 0xd0, 0x34, 0x0d, 0x0f, 0x6a, - 0x54, 0x0f, 0x9a, 0xfb, 0xe7, 0x9d, 0x8e, 0x3a, 0xa0, 0x48, 0x18, 0x5f, 0xfa, 0x49, 0x58, 0xd7, 0x70, 0x3b, 0xee, - 0xb1, 0x19, 0xb7, 0xb3, 0x6d, 0x50, 0x7d, 0xd9, 0xcf, 0x06, 0x83, 0xae, 0xf4, 0x56, 0x12, 0x2d, 0x3c, 0xae, 0x9e, - 0xe0, 0xa8, 0x16, 0xef, 0x8b, 0xde, 0xbc, 0xf2, 0xe6, 0xfe, 0x65, 0xcf, 0xcd, 0xf3, 0x18, 0x38, 0xa0, 0x7d, 0xb8, - 0x1f, 0xaa, 0xe2, 0x83, 0x1d, 0x75, 0x20, 0x0a, 0x5a, 0xda, 0xaa, 0x09, 0xa4, 0xd6, 0xcc, 0x2e, 0xd6, 0x4d, 0x85, - 0x0e, 0x05, 0x84, 0x21, 0x53, 0x55, 0x77, 0x77, 0x2a, 0x50, 0x0d, 0x71, 0x38, 0xf5, 0x1f, 0x5b, 0x23, 0xd6, 0x38, - 0xea, 0x8c, 0x22, 0x63, 0x24, 0x69, 0x97, 0x0f, 0x5e, 0xdd, 0x01, 0x2b, 0x01, 0x1f, 0xfd, 0xd8, 0x24, 0x19, 0x43, - 0x82, 0xb7, 0x2c, 0xd3, 0x86, 0x0f, 0xe1, 0x0e, 0x41, 0x79, 0x62, 0x63, 0x6d, 0xba, 0x4a, 0x16, 0x72, 0x55, 0x97, - 0xd7, 0x01, 0x7a, 0xde, 0x95, 0xbf, 0xb1, 0xe1, 0xc8, 0x82, 0x81, 0x65, 0x5b, 0xfb, 0x04, 0x3c, 0xf2, 0x71, 0x85, - 0x20, 0x7e, 0x29, 0x74, 0x62, 0x22, 0x45, 0x5f, 0xc1, 0x06, 0xc5, 0x73, 0x70, 0x10, 0x74, 0x12, 0x1c, 0x06, 0xef, - 0x32, 0xab, 0x49, 0x36, 0xb8, 0x35, 0x23, 0xf1, 0x7c, 0xb5, 0x6a, 0xa1, 0xc3, 0x7f, 0xcc, 0x63, 0xc8, 0xe3, 0x52, - 0xe1, 0x3e, 0xae, 0x14, 0xee, 0x60, 0x09, 0x48, 0xc6, 0x81, 0xae, 0x1d, 0xcb, 0x50, 0x8d, 0x0e, 0x71, 0xba, 0x5f, - 0x40, 0xd4, 0x66, 0x77, 0x2c, 0x81, 0x9e, 0x7d, 0xab, 0x80, 0xd5, 0xb5, 0x97, 0x25, 0x90, 0x11, 0xdc, 0xfd, 0x26, - 0x30, 0x2a, 0x44, 0xe3, 0xf3, 0x67, 0xde, 0x53, 0xe0, 0x89, 0xf3, 0xe7, 0x9a, 0x19, 0xd6, 0xbd, 0xa0, 0x37, 0xa6, - 0xf9, 0x78, 0x8c, 0x9b, 0x63, 0x0b, 0xce, 0xa3, 0x0e, 0xfc, 0xb4, 0x10, 0x3d, 0xea, 0x60, 0x97, 0x8a, 0xc7, 0x25, - 0x90, 0x43, 0xf4, 0x74, 0x06, 0x52, 0xc0, 0x4a, 0xc7, 0x56, 0x8b, 0x34, 0x41, 0xab, 0xd5, 0xe4, 0x82, 0xb4, 0x10, - 0x5a, 0xaa, 0x1b, 0xae, 0xb3, 0x29, 0xf8, 0x48, 0x83, 0x62, 0xe0, 0x0d, 0xd5, 0xd3, 0x18, 0xe1, 0x31, 0x5a, 0x8e, - 0xd8, 0x98, 0x2e, 0x72, 0x9d, 0xaa, 0x1e, 0x4f, 0x6c, 0x28, 0x5b, 0x66, 0x23, 0xc1, 0x1d, 0x75, 0xf0, 0xc4, 0xf0, - 0x97, 0x8f, 0x8c, 0x39, 0x48, 0x91, 0x99, 0xe4, 0x89, 0x49, 0xc0, 0x3c, 0xc9, 0x72, 0xa9, 0x98, 0x6d, 0xa6, 0x6b, - 0x6d, 0xcb, 0x21, 0x18, 0x76, 0xa4, 0x0b, 0x6e, 0xac, 0x28, 0xa3, 0x74, 0x4a, 0x54, 0x4f, 0x1d, 0x75, 0xd2, 0x09, - 0xe6, 0x09, 0x70, 0x7a, 0xef, 0x64, 0xcc, 0x1a, 0xe5, 0xad, 0xe8, 0x0c, 0x1d, 0x4e, 0xb1, 0xa8, 0x2e, 0x51, 0x67, - 0xe8, 0x70, 0x82, 0xf0, 0xac, 0x41, 0x72, 0x05, 0x1e, 0xc3, 0x5c, 0xfc, 0x1f, 0x29, 0xff, 0xcd, 0x61, 0x43, 0xd0, - 0xe5, 0xb7, 0xb0, 0x53, 0xd8, 0x28, 0x4a, 0x73, 0x02, 0x5e, 0x8b, 0xed, 0x33, 0x9c, 0x91, 0x49, 0x33, 0xf7, 0x01, - 0xf7, 0x4c, 0x2b, 0x8d, 0x5b, 0x8d, 0x0e, 0x33, 0x3c, 0xda, 0x4c, 0x8a, 0xcd, 0x5c, 0x9b, 0x79, 0x9a, 0xc1, 0xf9, - 0x5e, 0x8d, 0xc2, 0x95, 0x5f, 0x6c, 0x26, 0x85, 0xe5, 0x1d, 0x70, 0x9b, 0x23, 0x2c, 0x9a, 0x14, 0xe7, 0x78, 0xd6, - 0xfc, 0x8a, 0x67, 0xcd, 0x0f, 0x65, 0x46, 0x63, 0x81, 0x05, 0x04, 0xef, 0x83, 0x44, 0x3c, 0xab, 0x92, 0x47, 0x58, - 0x34, 0x4c, 0x79, 0x3c, 0x6b, 0x54, 0xa5, 0x9b, 0x0b, 0x2c, 0x1a, 0xa6, 0x74, 0xe3, 0x03, 0x9e, 0x35, 0xbe, 0xfe, - 0x8b, 0x49, 0x47, 0x29, 0xa0, 0xcb, 0x1c, 0x2d, 0x33, 0x3b, 0xc4, 0xab, 0xdf, 0xde, 0xbe, 0x6b, 0x5f, 0x77, 0x0e, - 0x27, 0xd8, 0xaf, 0x5f, 0x66, 0x70, 0x2c, 0xd3, 0x31, 0x6b, 0x02, 0x44, 0x33, 0xdc, 0x39, 0x9c, 0xe2, 0xce, 0x61, - 0xe6, 0x9a, 0x5a, 0xcf, 0x1a, 0xe4, 0x56, 0x87, 0x50, 0xd4, 0x51, 0x1a, 0xc2, 0xc7, 0x4f, 0x36, 0x9d, 0xa0, 0x1a, - 0x28, 0xd1, 0xe1, 0xa4, 0x06, 0x2a, 0xf8, 0x5e, 0xd4, 0xbe, 0xab, 0x7a, 0x15, 0x06, 0x59, 0x28, 0xa1, 0x70, 0xcd, - 0x0d, 0x78, 0x6a, 0x29, 0x06, 0x32, 0x61, 0x8a, 0x05, 0xca, 0x77, 0x40, 0x61, 0x94, 0x27, 0x66, 0xe8, 0xc1, 0x74, - 0x4c, 0xe2, 0xff, 0xcf, 0x93, 0x29, 0x87, 0x5e, 0x6e, 0x99, 0xad, 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, - 0x3f, 0xac, 0xa0, 0xfb, 0x62, 0xab, 0xfb, 0xc2, 0x74, 0x1f, 0x36, 0x6d, 0x54, 0x39, 0x69, 0x55, 0xc9, 0x92, 0xff, - 0x3a, 0xdd, 0xda, 0x02, 0x8d, 0xa8, 0xd1, 0xb3, 0x49, 0xd8, 0xe0, 0x7e, 0x3b, 0xdd, 0x81, 0xcc, 0x6b, 0x6e, 0xdf, - 0xe6, 0x84, 0xc3, 0x37, 0xb8, 0x53, 0xbd, 0x6c, 0x81, 0xf7, 0xa6, 0x32, 0xfa, 0xca, 0x38, 0xb4, 0x1c, 0x2c, 0x36, - 0x4d, 0xb9, 0x8d, 0xb1, 0x74, 0x72, 0x8a, 0x8d, 0x2b, 0x22, 0x54, 0xba, 0xbd, 0x04, 0xa5, 0xf8, 0x58, 0x37, 0x99, - 0xf9, 0xba, 0xd0, 0x89, 0xb9, 0x84, 0x6a, 0x98, 0xcf, 0xbb, 0x4b, 0x9d, 0x68, 0x39, 0xb7, 0x79, 0x77, 0x17, 0xd0, - 0x27, 0x68, 0x58, 0x1b, 0x81, 0xdd, 0x3e, 0x2b, 0x9c, 0x7e, 0xa7, 0x3a, 0x04, 0xc3, 0x03, 0xc8, 0x91, 0x16, 0xdb, - 0x07, 0x36, 0xad, 0x61, 0xd7, 0x45, 0xb3, 0x4c, 0xb4, 0xad, 0x36, 0x4d, 0xae, 0xdd, 0xc3, 0x7c, 0x1e, 0xf2, 0x14, - 0xbc, 0xb0, 0xfa, 0xf1, 0x1d, 0xec, 0xc6, 0x6d, 0x8d, 0x91, 0xa8, 0x2b, 0x99, 0x4a, 0xe8, 0x27, 0xb7, 0x98, 0x25, - 0x77, 0xc6, 0x8b, 0x51, 0x19, 0x7f, 0x1f, 0x13, 0xa9, 0x3e, 0xaa, 0x24, 0x39, 0xb0, 0xec, 0x6f, 0xb0, 0xe4, 0x16, - 0xcc, 0x13, 0xcb, 0x6a, 0x12, 0xeb, 0xe4, 0x2e, 0x58, 0x44, 0x69, 0x1a, 0x59, 0x1b, 0x06, 0xd4, 0x34, 0x63, 0xd5, - 0x83, 0xfb, 0x10, 0xe8, 0xa1, 0x57, 0x96, 0xd2, 0xae, 0xb3, 0xb4, 0xd6, 0xbd, 0x36, 0xdd, 0x6f, 0x0e, 0x28, 0xe0, - 0x0b, 0x03, 0xae, 0xe9, 0x5f, 0x4d, 0x22, 0x19, 0xb2, 0xaf, 0x9c, 0x15, 0x8f, 0x17, 0x85, 0xc1, 0x34, 0xd1, 0xd3, - 0x49, 0x36, 0x6f, 0x83, 0xa9, 0x5e, 0x36, 0xef, 0xdc, 0x62, 0xf7, 0x7d, 0x67, 0xbf, 0xef, 0xb0, 0xe8, 0x31, 0x93, - 0x91, 0x32, 0x53, 0xcc, 0x7f, 0xdf, 0xd9, 0xef, 0x3b, 0xbc, 0x3d, 0x98, 0x1b, 0x7f, 0xa1, 0x58, 0xb2, 0x33, 0x5c, - 0x82, 0x09, 0x79, 0xc0, 0xdd, 0xd4, 0xb2, 0x4c, 0x10, 0xd8, 0x5a, 0x02, 0xc4, 0xf9, 0x7c, 0x1a, 0x57, 0xbc, 0x1a, - 0x02, 0xee, 0xd3, 0xbb, 0xb6, 0x57, 0xa9, 0xc0, 0x63, 0x82, 0x46, 0xc4, 0xc4, 0xb6, 0x31, 0xef, 0x6a, 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, 0x79, 0x13, 0x79, 0xec, 0x0b, 0xb3, 0x9f, - 0x99, 0x9e, 0x16, 0x72, 0x31, 0x99, 0x82, 0x0f, 0x2d, 0xb0, 0x0c, 0x85, 0xa9, 0x57, 0xd9, 0xfa, 0xd7, 0x24, 0x37, - 0x01, 0x14, 0x4e, 0x37, 0x65, 0x42, 0x33, 0xbd, 0xa0, 0xb9, 0xb1, 0x24, 0xe5, 0x62, 0xf2, 0x48, 0xde, 0xbe, 0x04, - 0xec, 0xa6, 0x44, 0x37, 0x76, 0xe4, 0xbd, 0x85, 0x1d, 0x80, 0x33, 0xc2, 0x76, 0x55, 0x7c, 0xa8, 0x40, 0xe7, 0x8f, - 0x73, 0xc2, 0x76, 0x55, 0x7d, 0xc2, 0x6c, 0xf6, 0x94, 0x6c, 0x0c, 0xb7, 0x17, 0x67, 0x8d, 0x1c, 0x1d, 0x75, 0xd2, - 0xbc, 0xeb, 0x89, 0x81, 0x05, 0x68, 0x00, 0xdc, 0xad, 0xed, 0x59, 0xde, 0xdd, 0x10, 0xd0, 0xbb, 0x64, 0xd2, 0x5e, - 0x97, 0x9b, 0x94, 0xd5, 0xaa, 0x53, 0x51, 0xc1, 0x02, 0x4f, 0x83, 0xbd, 0x40, 0xed, 0xd7, 0x0e, 0x8a, 0x73, 0x95, - 0x6d, 0x9a, 0x9e, 0x97, 0x7d, 0x77, 0x77, 0x2c, 0x32, 0xb6, 0x69, 0x6f, 0x77, 0x10, 0x09, 0xcb, 0x09, 0xeb, 0x80, - 0x13, 0xae, 0x6a, 0x07, 0x04, 0xe8, 0x3a, 0x10, 0xb9, 0xb1, 0x24, 0xcb, 0x75, 0x65, 0x74, 0x1f, 0xf8, 0xdd, 0x52, - 0x22, 0xdd, 0x68, 0x4b, 0x82, 0xe9, 0x13, 0x8c, 0x9a, 0xce, 0x3c, 0x8a, 0x5c, 0x7b, 0xef, 0x77, 0x53, 0xb4, 0xf5, - 0xaf, 0x0f, 0x63, 0xb3, 0x3d, 0x4c, 0x0c, 0x65, 0x10, 0x03, 0xbd, 0x8f, 0x78, 0xb7, 0xd1, 0xc8, 0x10, 0x28, 0x64, - 0xb2, 0x01, 0x96, 0x89, 0xd7, 0xa2, 0x1f, 0x1c, 0x18, 0x78, 0x54, 0x09, 0x08, 0x53, 0x10, 0x42, 0xc2, 0xae, 0x0d, - 0xc2, 0x86, 0xcb, 0x55, 0xcb, 0x85, 0x8d, 0x54, 0x1b, 0x3a, 0xf8, 0x7f, 0x85, 0xcb, 0x56, 0xcf, 0x2c, 0x17, 0xc5, - 0xe0, 0x66, 0x6e, 0xc0, 0x22, 0x41, 0x7a, 0xb4, 0xd9, 0x1e, 0x8a, 0xbb, 0x73, 0xb1, 0xd9, 0x10, 0x90, 0x98, 0xc3, - 0x04, 0x45, 0xc3, 0xb9, 0x31, 0xc6, 0x2a, 0xa9, 0xb4, 0xac, 0x35, 0x89, 0x39, 0xf0, 0xa5, 0x0b, 0xd7, 0x7d, 0x79, - 0x9b, 0x32, 0x7c, 0x97, 0x0a, 0x7c, 0x03, 0x9e, 0x34, 0xa9, 0xc4, 0xee, 0xf1, 0x82, 0x62, 0x4d, 0x74, 0xd7, 0xb3, - 0xb7, 0x05, 0xac, 0xb3, 0xd9, 0x23, 0x22, 0xf8, 0x5d, 0xfd, 0x6a, 0x83, 0xef, 0x16, 0xfe, 0x0a, 0xd6, 0xcf, 0xc1, - 0x49, 0x8a, 0x45, 0x43, 0x36, 0x0b, 0x77, 0x64, 0x40, 0xb9, 0x8a, 0x5f, 0x0e, 0x53, 0xb7, 0x8a, 0xe1, 0xda, 0xc7, - 0x57, 0xfc, 0x61, 0xa3, 0xdd, 0x86, 0x2a, 0x8b, 0xdb, 0xbd, 0x29, 0x1a, 0xb2, 0x6a, 0x7a, 0x47, 0xe6, 0x46, 0x4a, - 0xfd, 0xeb, 0x03, 0x6e, 0x6d, 0xb5, 0xef, 0xa7, 0xf9, 0xd6, 0xa3, 0x73, 0xd5, 0xb4, 0x4f, 0xad, 0x15, 0xc1, 0xc1, - 0xcf, 0x16, 0x6e, 0x6e, 0x0d, 0x38, 0x80, 0x9f, 0xbf, 0xa3, 0x79, 0x9c, 0x41, 0x74, 0x7a, 0xab, 0x19, 0x5f, 0xc5, - 0x7f, 0x8e, 0x1a, 0x71, 0x2f, 0xfd, 0x33, 0xf9, 0x73, 0xd4, 0x40, 0x3d, 0x14, 0xcf, 0x6f, 0x57, 0x6c, 0xb6, 0x82, - 0x60, 0x6b, 0xf7, 0x8e, 0xf0, 0xeb, 0xb0, 0x24, 0xd7, 0x34, 0xe7, 0xd9, 0xca, 0x3d, 0x45, 0xb7, 0x72, 0xef, 0xf4, - 0xac, 0xcc, 0xeb, 0x4a, 0xab, 0x58, 0x0e, 0x73, 0x08, 0x2c, 0x1c, 0xef, 0x35, 0x7b, 0xfd, 0x56, 0xf3, 0xc1, 0xc0, - 0xfe, 0x6b, 0x22, 0xdc, 0xa3, 0x5a, 0xc4, 0xb6, 0x37, 0x1b, 0x5b, 0x3f, 0x06, 0xc3, 0x0e, 0x08, 0x05, 0x0e, 0x72, - 0xe9, 0xe3, 0x0c, 0x59, 0xdf, 0x93, 0xd5, 0x8a, 0xb9, 0x68, 0xd6, 0x4e, 0x83, 0x5f, 0xc6, 0x66, 0x3a, 0x6c, 0x27, - 0x9d, 0xae, 0x17, 0x63, 0x49, 0x03, 0x22, 0x4d, 0x63, 0x06, 0x81, 0xa4, 0x96, 0x86, 0xc3, 0x9a, 0xdf, 0x46, 0x69, - 0x75, 0x7f, 0x04, 0x29, 0x3f, 0x44, 0x29, 0x3f, 0x22, 0x10, 0x40, 0xdb, 0x32, 0x47, 0x65, 0x43, 0xde, 0x77, 0xe9, - 0x9e, 0x71, 0x66, 0x68, 0xf0, 0xd5, 0xaa, 0x55, 0x0d, 0x53, 0x14, 0xf5, 0x61, 0x2e, 0xd7, 0x58, 0x90, 0x37, 0xa0, - 0x6b, 0x56, 0x44, 0xf4, 0x42, 0x57, 0x79, 0x78, 0x89, 0x17, 0x4b, 0x02, 0x4e, 0xfa, 0x3d, 0xd1, 0x2b, 0xc8, 0xe5, - 0xc3, 0x18, 0x7c, 0xcc, 0x30, 0xef, 0xeb, 0x7e, 0x31, 0x18, 0xa0, 0xd4, 0x39, 0x9d, 0xa5, 0x26, 0xe2, 0x4a, 0xe0, - 0x97, 0x5c, 0x80, 0x5f, 0xb2, 0x42, 0xac, 0x5f, 0x0c, 0xc8, 0xbd, 0x2c, 0x96, 0xe0, 0x94, 0xbf, 0xc3, 0xe7, 0xf1, - 0x61, 0x68, 0x60, 0x6a, 0x86, 0x65, 0x2e, 0xb2, 0xc1, 0x62, 0xce, 0x5a, 0x02, 0xc1, 0xcd, 0x80, 0xbb, 0xd4, 0x86, - 0x44, 0x63, 0x0d, 0x14, 0xdd, 0x46, 0xa1, 0x99, 0xd1, 0xd3, 0xad, 0x36, 0xfa, 0x91, 0xc3, 0x0b, 0x73, 0x0d, 0x63, - 0x11, 0xc8, 0x5c, 0xae, 0x7a, 0xec, 0x2f, 0x3f, 0x6c, 0x56, 0x18, 0xbc, 0xc2, 0x98, 0xec, 0x94, 0x56, 0x89, 0x66, - 0x7c, 0x95, 0x27, 0x8e, 0x21, 0xc8, 0xc4, 0x52, 0xe9, 0x86, 0x63, 0xe2, 0x4a, 0xfa, 0x4c, 0x0c, 0xd9, 0x6e, 0x78, - 0x66, 0x2e, 0x74, 0xb3, 0xfd, 0xc3, 0xb9, 0x9d, 0x73, 0xc2, 0x8d, 0x56, 0xd2, 0x68, 0xa3, 0x9e, 0x19, 0xaa, 0xea, - 0x82, 0xf9, 0x3d, 0x74, 0x5a, 0x5a, 0xec, 0x5c, 0xbd, 0xbb, 0xe1, 0xbb, 0x70, 0x65, 0xfc, 0x2d, 0x56, 0x85, 0x56, - 0x64, 0xb8, 0xdd, 0x42, 0xde, 0x9c, 0xe9, 0xa1, 0x57, 0xe4, 0x42, 0x75, 0xf8, 0x8b, 0xba, 0xc2, 0x3c, 0x15, 0x19, - 0x35, 0x84, 0x47, 0xbf, 0xd7, 0x19, 0x28, 0xff, 0x60, 0x62, 0x32, 0x67, 0xc9, 0x0d, 0x2d, 0x44, 0xfc, 0xe3, 0x0b, - 0x61, 0x62, 0x55, 0xed, 0xc1, 0x40, 0xf6, 0x4c, 0xc5, 0x3d, 0xb8, 0x35, 0xe1, 0x63, 0xce, 0x46, 0xe9, 0x5e, 0xf4, - 0x63, 0x43, 0x34, 0x7e, 0x8c, 0x7e, 0x04, 0x77, 0x67, 0xf7, 0x2e, 0x61, 0x19, 0x17, 0xc2, 0xdf, 0x63, 0x3d, 0x2c, - 0x55, 0xca, 0x58, 0x7b, 0xdd, 0x72, 0x78, 0x21, 0xf5, 0x26, 0x8b, 0x1f, 0x3a, 0x62, 0x6d, 0x53, 0xb0, 0x0e, 0x29, - 0x29, 0x3c, 0xbb, 0x62, 0x6e, 0xb5, 0x98, 0xbb, 0xd4, 0x12, 0xfe, 0xfa, 0xea, 0x61, 0xa9, 0x82, 0x86, 0x83, 0xd0, - 0x95, 0xb6, 0x90, 0x00, 0x03, 0x97, 0xd2, 0xa7, 0xd3, 0x9d, 0x49, 0x64, 0x96, 0xc5, 0xf0, 0xee, 0x41, 0x05, 0xf3, - 0xdf, 0xd9, 0x46, 0x58, 0x15, 0xb8, 0x5c, 0xa9, 0xa2, 0x5e, 0x4a, 0x02, 0x01, 0xe8, 0x4b, 0xef, 0x41, 0x79, 0x51, - 0x74, 0x1b, 0x0d, 0x09, 0x5a, 0x58, 0x6a, 0xae, 0x55, 0x31, 0xdd, 0x0f, 0xdf, 0xd3, 0x0b, 0x3e, 0xbc, 0x43, 0xda, - 0xc6, 0xa3, 0x96, 0x94, 0x50, 0xbb, 0x83, 0xf6, 0xc1, 0x2a, 0x3b, 0x28, 0xff, 0x36, 0xa6, 0xc8, 0xe6, 0xf7, 0xd9, - 0x0f, 0xd4, 0x75, 0x38, 0x70, 0x05, 0xab, 0x5e, 0xca, 0x28, 0x18, 0xc2, 0x3e, 0x60, 0x1f, 0x8b, 0x24, 0xa3, 0xd9, - 0x94, 0x81, 0xba, 0xdf, 0x16, 0xad, 0xe6, 0xf6, 0xa4, 0xee, 0x37, 0x64, 0x9c, 0x7d, 0x84, 0x71, 0xf6, 0x51, 0xe0, - 0xc5, 0x22, 0xc9, 0x1f, 0x32, 0xd6, 0x38, 0x56, 0x4d, 0x81, 0x8e, 0x3a, 0xc0, 0x9d, 0x81, 0x03, 0x0f, 0xd8, 0xa2, - 0x1c, 0x1c, 0x50, 0x67, 0x71, 0x4f, 0x1b, 0x99, 0xf7, 0xf6, 0x84, 0xda, 0x45, 0x2c, 0x70, 0xb3, 0x66, 0xa6, 0x05, - 0xad, 0x15, 0xc6, 0x79, 0x3c, 0xe0, 0x6d, 0x9e, 0xd5, 0xe2, 0x27, 0x6c, 0x58, 0x53, 0xd5, 0x6f, 0xa0, 0x39, 0xaa, - 0x05, 0xb9, 0x79, 0x62, 0xbc, 0x55, 0x49, 0x3f, 0x8a, 0x06, 0x96, 0x53, 0x21, 0x86, 0x64, 0xf4, 0x5b, 0x83, 0xe0, - 0x56, 0x7b, 0xb5, 0xe2, 0x1e, 0xf1, 0x45, 0xcd, 0x5b, 0xcd, 0xdc, 0x02, 0xd0, 0x22, 0x8e, 0xca, 0x7b, 0x93, 0x08, - 0xbc, 0x6f, 0xcb, 0x08, 0x69, 0xcb, 0xbe, 0x7d, 0x34, 0xb1, 0x54, 0x6c, 0xbe, 0xa3, 0x93, 0x41, 0x1a, 0xd9, 0x11, - 0x45, 0xf8, 0xba, 0x84, 0x24, 0x5c, 0x25, 0x5d, 0xab, 0x4c, 0xce, 0x99, 0x4a, 0x39, 0xbe, 0x2e, 0xa4, 0xd4, 0x57, - 0xf6, 0x4b, 0xe2, 0xea, 0x4e, 0x46, 0xe0, 0xeb, 0x09, 0xd3, 0xef, 0x68, 0x31, 0x61, 0xe0, 0x57, 0xe4, 0x6f, 0xc7, - 0x52, 0x4a, 0x2e, 0x9f, 0x88, 0xb8, 0x4f, 0x31, 0xbc, 0xf8, 0x39, 0xc0, 0xda, 0x84, 0x40, 0x29, 0x71, 0x11, 0x2e, - 0x88, 0xde, 0x14, 0xf2, 0xf6, 0x2e, 0x2e, 0xb0, 0x73, 0x00, 0x2c, 0x9d, 0x26, 0x01, 0xfe, 0xe5, 0x63, 0x3e, 0x56, - 0x63, 0x4e, 0x8d, 0xae, 0xdf, 0xfd, 0x4e, 0xae, 0x81, 0xde, 0x96, 0x8e, 0x82, 0xfd, 0xd6, 0x00, 0x72, 0xe1, 0x2e, - 0x0c, 0x2e, 0xbe, 0xc2, 0xda, 0xb2, 0x30, 0xde, 0x58, 0x00, 0xbd, 0xbf, 0x33, 0xb0, 0x60, 0xc3, 0x1c, 0x53, 0x78, - 0x2e, 0x75, 0xc2, 0x74, 0x10, 0x15, 0xe4, 0x49, 0xf9, 0x20, 0x66, 0xad, 0xf6, 0x5b, 0x36, 0x86, 0x3b, 0x8c, 0xe4, - 0xdb, 0x85, 0x13, 0x07, 0x1e, 0x90, 0x69, 0x32, 0xdb, 0xec, 0x1b, 0x1f, 0x79, 0xe4, 0xf5, 0x38, 0xde, 0xd5, 0x52, - 0x98, 0x6f, 0x56, 0x74, 0x8d, 0x21, 0x14, 0x45, 0xd8, 0xef, 0x17, 0x15, 0x53, 0x54, 0x19, 0xb4, 0x41, 0xc3, 0xf2, - 0x46, 0xfc, 0x02, 0x67, 0x0c, 0xad, 0x17, 0xb2, 0x77, 0x74, 0xd6, 0xe1, 0xcc, 0x61, 0xc6, 0x94, 0xc0, 0xa8, 0xb4, - 0x2c, 0xe8, 0x04, 0x1c, 0x9d, 0xab, 0x0f, 0xa2, 0xe2, 0xea, 0x58, 0x01, 0x78, 0x92, 0x29, 0xfc, 0x93, 0x6f, 0x82, - 0x75, 0xbf, 0x55, 0x33, 0x4c, 0xfd, 0x45, 0x6f, 0xbb, 0x96, 0x2f, 0x43, 0x1c, 0x69, 0x63, 0x08, 0xad, 0x73, 0x7b, - 0x07, 0x28, 0xe2, 0x82, 0x5e, 0xa4, 0x1a, 0x5f, 0xab, 0xc5, 0xd0, 0xac, 0xaf, 0x71, 0x1d, 0xd3, 0x06, 0x51, 0xac, - 0xbb, 0x26, 0xbe, 0xae, 0xde, 0x1f, 0x55, 0xa9, 0x82, 0x33, 0x48, 0x20, 0xac, 0xca, 0xcb, 0x86, 0x54, 0x92, 0x4b, - 0xd3, 0xa9, 0x34, 0x9d, 0x56, 0x08, 0xe5, 0xd2, 0x93, 0xf2, 0xfe, 0x15, 0x42, 0x18, 0x98, 0x32, 0x3b, 0xb0, 0x4a, - 0x6d, 0x61, 0x15, 0xbc, 0x7a, 0xb1, 0x81, 0x55, 0x12, 0x8e, 0xe7, 0x12, 0x8d, 0x8a, 0x0a, 0x87, 0x0c, 0xe9, 0x0b, - 0xb1, 0x08, 0x12, 0x00, 0x8b, 0xde, 0x65, 0x2e, 0xef, 0x7b, 0x38, 0x14, 0xf6, 0x24, 0x93, 0x70, 0xba, 0x09, 0xcd, - 0xe1, 0x61, 0x5a, 0xd5, 0xf3, 0x08, 0x01, 0x4b, 0xcf, 0x31, 0x3c, 0x48, 0xfc, 0xfd, 0x87, 0x50, 0x9d, 0x05, 0x79, - 0xfa, 0x2f, 0x51, 0x12, 0x1a, 0xfb, 0xcf, 0xf1, 0xd0, 0x21, 0x61, 0x38, 0xf0, 0xcd, 0x11, 0x56, 0x38, 0xb8, 0x55, - 0xc4, 0x67, 0x70, 0x87, 0x8f, 0x75, 0xe8, 0x01, 0x60, 0x09, 0xc5, 0x21, 0xc8, 0x37, 0x50, 0xcc, 0xe0, 0x80, 0x26, - 0xcb, 0xf0, 0x02, 0x17, 0xac, 0x16, 0xca, 0xfb, 0xdb, 0x96, 0x97, 0xd2, 0x6a, 0x97, 0xbc, 0xc6, 0x1c, 0xa8, 0xfc, - 0x0c, 0x2f, 0x7c, 0x85, 0x79, 0x29, 0xd9, 0x7d, 0xe1, 0x6b, 0x07, 0xf4, 0x14, 0x02, 0x46, 0xba, 0xdf, 0x6b, 0xc2, - 0x3d, 0x45, 0x2f, 0x73, 0x71, 0xd8, 0x76, 0xd0, 0xbd, 0xc0, 0x5c, 0x5d, 0x55, 0x59, 0x73, 0x30, 0x85, 0x06, 0x07, - 0x55, 0x38, 0x23, 0x30, 0x57, 0x2f, 0xca, 0x82, 0x73, 0x10, 0xef, 0x7b, 0xc2, 0xe4, 0x94, 0xd1, 0x00, 0x5e, 0x64, - 0xe5, 0xa3, 0x53, 0x3d, 0x0e, 0x2e, 0xe3, 0x86, 0x4d, 0x7c, 0x21, 0x7c, 0x2a, 0xb0, 0x92, 0xd6, 0x38, 0x34, 0xa2, - 0x23, 0x3a, 0x07, 0xb3, 0x0d, 0xa0, 0xe0, 0xee, 0x7c, 0xd8, 0x58, 0xa8, 0xe0, 0x31, 0xd8, 0xda, 0xdb, 0xcd, 0x84, - 0x38, 0x93, 0xa6, 0xe0, 0x6e, 0xdb, 0x20, 0x83, 0x37, 0xbf, 0xfd, 0xb7, 0xc2, 0x22, 0xc1, 0x80, 0x4a, 0x4d, 0x12, - 0x84, 0x27, 0x28, 0x8d, 0x74, 0x2b, 0x37, 0x13, 0x48, 0x27, 0xa2, 0x66, 0xd4, 0xbd, 0x71, 0xbe, 0x3a, 0x6a, 0x20, - 0x2a, 0x6a, 0xa0, 0x02, 0x6a, 0x20, 0xeb, 0xdb, 0xbf, 0x80, 0x85, 0xb0, 0x11, 0xaa, 0x44, 0x10, 0x10, 0x61, 0xae, - 0x0d, 0x1f, 0x50, 0x24, 0x21, 0xe4, 0x0d, 0xa0, 0x62, 0x4a, 0x5e, 0x82, 0xd1, 0x38, 0xbc, 0xde, 0x03, 0xee, 0x97, - 0x96, 0x61, 0xf0, 0x9c, 0x82, 0xc9, 0x7f, 0xeb, 0xf3, 0xa1, 0x7a, 0xb9, 0x3a, 0x08, 0xe1, 0x17, 0x10, 0x2b, 0xc2, - 0xf1, 0x17, 0xbf, 0x00, 0xd9, 0x54, 0x58, 0x1e, 0x1c, 0x48, 0x10, 0xf8, 0x21, 0x8a, 0x70, 0xc0, 0x33, 0xbc, 0xcc, - 0x36, 0x88, 0x9e, 0x9f, 0x95, 0xaa, 0x66, 0x25, 0x83, 0x59, 0x15, 0x9e, 0xc6, 0xd1, 0x35, 0x61, 0x20, 0xb8, 0x50, - 0xbb, 0x6f, 0x10, 0x02, 0x65, 0xcb, 0x8d, 0xa1, 0x4b, 0x4f, 0xc1, 0x7c, 0x34, 0x8e, 0xde, 0x32, 0x78, 0xd2, 0xd6, - 0x98, 0xfc, 0x33, 0x6d, 0x1e, 0xb8, 0x4f, 0xf7, 0xa2, 0x46, 0xe0, 0xa4, 0x4e, 0x51, 0xf2, 0xb7, 0xe4, 0x22, 0x8e, - 0x9a, 0x97, 0x11, 0x6a, 0xc0, 0xbf, 0x0d, 0x8e, 0xba, 0x34, 0xa1, 0xa3, 0x91, 0x0f, 0x7e, 0x93, 0x11, 0xb3, 0xc9, - 0x56, 0x2b, 0x51, 0x11, 0xf4, 0xc4, 0x6e, 0x30, 0x60, 0x25, 0x5e, 0x00, 0xfb, 0x60, 0x39, 0x58, 0xf2, 0x4e, 0xc4, - 0xca, 0x9f, 0x52, 0x18, 0xac, 0x9e, 0x33, 0x84, 0x70, 0x16, 0xc4, 0x6c, 0xfc, 0xcf, 0x67, 0x1a, 0xae, 0x9f, 0x9f, - 0xaf, 0x63, 0x44, 0xa4, 0x0f, 0x22, 0x57, 0x63, 0x47, 0x44, 0x10, 0xb6, 0x4c, 0xf7, 0x5d, 0x99, 0x1f, 0xbc, 0x75, - 0xf5, 0xc0, 0x86, 0x8b, 0x03, 0x03, 0x6a, 0x14, 0x18, 0xad, 0xe0, 0x9c, 0x94, 0x03, 0x07, 0x25, 0x84, 0x66, 0x45, - 0x3c, 0x25, 0x97, 0x10, 0x09, 0x2f, 0x43, 0x5d, 0x30, 0x2c, 0x08, 0x24, 0xa8, 0x29, 0x48, 0x50, 0x99, 0xaf, 0x3d, - 0x82, 0x59, 0xe7, 0x66, 0xb6, 0x53, 0xd4, 0x75, 0x41, 0x7e, 0x7e, 0xd1, 0xf1, 0x08, 0x58, 0xda, 0x83, 0x83, 0x02, - 0x22, 0x88, 0x01, 0x05, 0x2f, 0x25, 0xc0, 0x40, 0x03, 0x5e, 0x6c, 0x68, 0xc0, 0xe7, 0xda, 0x78, 0x1d, 0x18, 0x5b, - 0x9f, 0x32, 0xc8, 0xc5, 0xb3, 0x6a, 0x4f, 0x13, 0x42, 0xf6, 0x5b, 0x3d, 0x9d, 0x6e, 0x47, 0x48, 0xec, 0x7d, 0xd4, - 0x26, 0xd0, 0x98, 0x23, 0xdd, 0xd5, 0xc6, 0xfc, 0x5a, 0xd3, 0x23, 0x56, 0x93, 0x90, 0x2e, 0x48, 0x97, 0xe7, 0xd3, - 0x9e, 0xc1, 0x15, 0xab, 0x34, 0x72, 0x70, 0x01, 0xfa, 0x6c, 0x40, 0x80, 0x02, 0x95, 0xa6, 0x12, 0x45, 0x11, 0x17, - 0x49, 0xc9, 0x86, 0x61, 0x06, 0x61, 0x0a, 0xab, 0x95, 0xa0, 0x1b, 0x6b, 0x00, 0xbc, 0x33, 0xb3, 0x7f, 0x4a, 0x1f, - 0x6c, 0xba, 0xf6, 0xe6, 0x11, 0x40, 0x40, 0xf6, 0xdb, 0x25, 0xbb, 0x2e, 0x36, 0x2a, 0xb3, 0xb0, 0x96, 0xb1, 0x95, - 0xdb, 0xf6, 0x18, 0x7b, 0x27, 0xb6, 0xf9, 0x04, 0x08, 0x51, 0x5b, 0x32, 0x8d, 0x10, 0x21, 0xb1, 0x88, 0x75, 0x6d, - 0xc8, 0x46, 0x1b, 0xda, 0x37, 0x4f, 0xc2, 0x43, 0xec, 0x03, 0x50, 0xbc, 0x39, 0x2e, 0xc1, 0x21, 0xbc, 0xf0, 0x08, - 0x7f, 0x0b, 0x2c, 0x52, 0x81, 0x19, 0x96, 0xab, 0x15, 0xd4, 0xf3, 0x78, 0x9f, 0x6d, 0x06, 0x27, 0x95, 0x1b, 0x63, - 0x97, 0x76, 0xe2, 0x71, 0xd9, 0x84, 0xc4, 0x19, 0xf4, 0xeb, 0x2b, 0xa2, 0xde, 0x7e, 0x3b, 0x7d, 0xe2, 0xdf, 0x2b, - 0x73, 0x3b, 0x10, 0x1b, 0xd6, 0x1b, 0xac, 0x3e, 0x80, 0x96, 0xbf, 0xca, 0xfc, 0x43, 0x65, 0xc1, 0x4d, 0x82, 0xda, - 0x5c, 0xc4, 0x2e, 0xeb, 0x22, 0x46, 0x6a, 0x8b, 0xbb, 0x43, 0x88, 0x7f, 0xb5, 0x15, 0xc5, 0x80, 0x27, 0x15, 0xff, - 0x1c, 0xa3, 0x2e, 0x84, 0xa2, 0xb6, 0x1e, 0x36, 0x40, 0x69, 0x97, 0xeb, 0x4a, 0x8c, 0x0c, 0x09, 0xe4, 0x5b, 0x17, - 0x5e, 0xd0, 0x9c, 0x44, 0x0a, 0xe4, 0xe4, 0x20, 0x2a, 0x69, 0xb6, 0x21, 0xcc, 0x75, 0xb7, 0x70, 0xcc, 0x5c, 0x6d, - 0xd0, 0x22, 0x7e, 0x01, 0xec, 0x0c, 0x37, 0x92, 0xa5, 0x03, 0x9f, 0xaa, 0x81, 0xcf, 0xaf, 0xb9, 0xa1, 0x28, 0x0a, - 0xf5, 0xde, 0xd9, 0x47, 0xe6, 0xe0, 0x77, 0x1a, 0x88, 0x8f, 0xd4, 0xe9, 0x48, 0x36, 0x42, 0xad, 0x39, 0x3b, 0x5e, - 0xb6, 0x19, 0x61, 0x50, 0xd8, 0xe8, 0x7d, 0x15, 0xb2, 0x8a, 0x9d, 0x9d, 0x8a, 0x60, 0x4e, 0x5f, 0x54, 0xe5, 0x9c, - 0xca, 0x2d, 0xa3, 0x5a, 0x6a, 0x1a, 0x20, 0xc2, 0x95, 0x4f, 0x24, 0xef, 0x33, 0x13, 0xfe, 0xc1, 0x60, 0x5c, 0x3d, - 0x52, 0xf8, 0xfb, 0x5d, 0xb1, 0x43, 0xb6, 0xa3, 0xc3, 0x6d, 0x04, 0xcd, 0x0b, 0x15, 0x3c, 0xe0, 0xa8, 0x64, 0x09, - 0x91, 0x22, 0x97, 0xfb, 0xaa, 0x66, 0xca, 0x76, 0x1d, 0x21, 0x84, 0xb4, 0xc7, 0x59, 0x37, 0xb4, 0x7a, 0xe8, 0x91, - 0x2a, 0xca, 0xe1, 0x16, 0xcd, 0x75, 0x01, 0x2a, 0x8c, 0x40, 0xba, 0xfc, 0xcc, 0xee, 0x52, 0x09, 0xd1, 0xcb, 0xd7, - 0x2e, 0x84, 0xb1, 0xb3, 0xb2, 0xc4, 0x85, 0x19, 0xb5, 0x0d, 0xa3, 0xeb, 0x36, 0x86, 0xb3, 0x81, 0x31, 0xd3, 0xa0, - 0xa4, 0x05, 0xa1, 0xae, 0xbb, 0xf4, 0x22, 0x33, 0x81, 0x1e, 0x73, 0x42, 0x1b, 0x0c, 0x4f, 0x89, 0x06, 0xcb, 0xa6, - 0x02, 0x2c, 0xf8, 0x96, 0x45, 0x6a, 0x6d, 0x36, 0x59, 0xfc, 0x51, 0xc7, 0xe6, 0x69, 0xbf, 0xbc, 0x62, 0x9e, 0x0b, - 0x47, 0xdd, 0x9e, 0x67, 0x3e, 0x1e, 0xdd, 0xd3, 0x37, 0x57, 0x2f, 0x5e, 0xbe, 0x7e, 0xb5, 0x5a, 0xb5, 0x59, 0xb3, - 0x7d, 0x82, 0x7f, 0xd2, 0x65, 0x3c, 0xd8, 0x32, 0x0a, 0xd0, 0xc1, 0xc1, 0x3e, 0x37, 0x2e, 0x3c, 0x9f, 0xf9, 0x1c, - 0xe2, 0x06, 0xe9, 0x01, 0xce, 0x8a, 0x32, 0x26, 0xc8, 0x6d, 0xd4, 0x8b, 0xee, 0x22, 0x50, 0x42, 0x55, 0xe4, 0xef, - 0xc3, 0xe6, 0xec, 0xf7, 0x20, 0x30, 0x11, 0xd4, 0x87, 0x08, 0x20, 0x10, 0xaf, 0x14, 0x17, 0x84, 0xf9, 0x04, 0x88, - 0xe2, 0xbd, 0x00, 0xce, 0xd4, 0x44, 0xad, 0x5a, 0xa8, 0xb8, 0x00, 0x92, 0x68, 0xc3, 0x51, 0xd2, 0x23, 0x13, 0xc0, - 0x1b, 0x82, 0x52, 0xda, 0x5f, 0xdd, 0xdc, 0xb9, 0x4b, 0xe5, 0xa8, 0xd7, 0x4a, 0x73, 0x3c, 0x75, 0x9f, 0x53, 0xf8, - 0x9c, 0x76, 0xfd, 0xe9, 0x20, 0x0e, 0x73, 0xbc, 0x20, 0xe2, 0xd0, 0x3f, 0x8b, 0xb8, 0x9c, 0x17, 0xec, 0x0b, 0x97, - 0x0b, 0x95, 0x2e, 0x6f, 0x53, 0x99, 0xdc, 0x36, 0x47, 0x87, 0x71, 0x91, 0xdc, 0x36, 0x55, 0x72, 0x8b, 0xf0, 0x5d, - 0x2a, 0x93, 0x3b, 0x9b, 0x72, 0xd7, 0x54, 0x70, 0xf3, 0x85, 0x05, 0x1c, 0x8a, 0xb6, 0x68, 0x63, 0xb1, 0x59, 0xd4, - 0xa6, 0xb8, 0xa2, 0x01, 0x06, 0xff, 0xbe, 0x63, 0xe3, 0x87, 0xe1, 0x4b, 0x70, 0x69, 0xd2, 0x44, 0x7e, 0x02, 0xe9, - 0xa7, 0x55, 0x19, 0xb8, 0x4f, 0x49, 0xab, 0x3b, 0xbd, 0x10, 0xcd, 0x76, 0xb7, 0xd1, 0x98, 0xc2, 0xde, 0xcd, 0x48, - 0xee, 0x8b, 0x4d, 0x1b, 0x26, 0xbe, 0xce, 0x7e, 0xb6, 0x5a, 0xed, 0xe7, 0xc8, 0x6c, 0xb8, 0x09, 0x8b, 0x75, 0x7f, - 0x3a, 0xc0, 0x2d, 0xfc, 0x3c, 0x43, 0x68, 0xc9, 0xfa, 0xd3, 0x01, 0x61, 0xfd, 0x69, 0xa3, 0x3d, 0xb0, 0x86, 0x76, - 0x66, 0x2b, 0xae, 0x21, 0x84, 0xe6, 0x74, 0x70, 0x64, 0x4a, 0x4a, 0x97, 0x6f, 0xbf, 0x68, 0x15, 0xd0, 0x4f, 0xd5, - 0x82, 0x97, 0x49, 0xdc, 0x81, 0xbe, 0xe8, 0x85, 0x7d, 0xba, 0xb5, 0x20, 0xc7, 0x47, 0x95, 0xab, 0x3d, 0x45, 0xd8, - 0xf4, 0xa4, 0x0e, 0x8b, 0x43, 0xd3, 0x8c, 0xeb, 0x52, 0xba, 0xef, 0x50, 0x33, 0xf2, 0xd1, 0xc1, 0x02, 0x10, 0xa4, - 0x82, 0x47, 0x56, 0xb8, 0x70, 0x4a, 0x21, 0x5c, 0x1c, 0x54, 0xb6, 0x60, 0x92, 0x93, 0x56, 0x37, 0x37, 0x96, 0xfe, - 0xb9, 0x8b, 0x68, 0x4a, 0x31, 0x25, 0x99, 0x2f, 0x99, 0x1b, 0xb0, 0xd0, 0x4d, 0xca, 0x33, 0x05, 0xbd, 0xd2, 0x00, - 0x8f, 0x08, 0xc4, 0x43, 0xea, 0x16, 0xc6, 0xc0, 0x2b, 0x9e, 0x36, 0x8b, 0x3e, 0x1b, 0xa0, 0xa3, 0x63, 0x4c, 0xfb, - 0x7f, 0x65, 0xf3, 0x36, 0x3c, 0x16, 0xf8, 0xd7, 0x80, 0x4c, 0x9b, 0xb2, 0x4c, 0x10, 0x90, 0x30, 0x6a, 0xca, 0x43, - 0xd8, 0x4b, 0x08, 0x67, 0xb6, 0x62, 0xd6, 0x67, 0x83, 0xe6, 0xb4, 0xac, 0xd8, 0xf1, 0x15, 0x1b, 0xb2, 0x4c, 0xb0, - 0x15, 0x1b, 0xae, 0x62, 0xf8, 0x3a, 0x83, 0x01, 0x41, 0x08, 0x00, 0x06, 0x00, 0xd0, 0x28, 0x88, 0xe6, 0x8b, 0x15, - 0xf1, 0x9b, 0xdd, 0xde, 0xe3, 0xb7, 0xc0, 0x02, 0xad, 0xb6, 0xff, 0x77, 0xa1, 0x0c, 0xd8, 0x53, 0x16, 0x26, 0x66, - 0x6e, 0x61, 0x55, 0x74, 0x00, 0x95, 0x12, 0x61, 0x0a, 0x03, 0x99, 0xfd, 0xcc, 0x40, 0x2d, 0xd0, 0x1a, 0xe4, 0x7d, - 0x3d, 0x68, 0x66, 0x70, 0xc4, 0xc0, 0x3b, 0x34, 0x64, 0x6a, 0x8c, 0x09, 0xe3, 0x1c, 0xa6, 0x98, 0x19, 0xf0, 0x4c, - 0xd3, 0xd6, 0x5a, 0x1a, 0x59, 0xae, 0x97, 0xf7, 0xfe, 0xd1, 0xb1, 0xea, 0x17, 0xcd, 0xf6, 0x00, 0xed, 0x13, 0x62, - 0x3f, 0x06, 0xb0, 0xc9, 0x5c, 0x6a, 0xc3, 0x7c, 0x1f, 0x75, 0x52, 0xfb, 0x09, 0x7f, 0x06, 0x6b, 0xb3, 0x03, 0x40, - 0x47, 0x86, 0xcd, 0xfa, 0xcb, 0x9a, 0xca, 0xeb, 0xe3, 0xce, 0x28, 0x95, 0xbb, 0xde, 0x9d, 0x0e, 0x34, 0xc5, 0xa1, - 0xb7, 0x1e, 0x2e, 0x1f, 0xea, 0x21, 0x60, 0xc6, 0x60, 0x6e, 0x99, 0xd1, 0xf7, 0x42, 0x24, 0x17, 0x44, 0x62, 0x69, - 0xb0, 0x86, 0xc1, 0xde, 0x3a, 0x38, 0x30, 0xd5, 0x58, 0x03, 0x9e, 0x27, 0x45, 0x20, 0x18, 0xf8, 0x08, 0xca, 0x80, - 0x26, 0xca, 0xdc, 0x86, 0x93, 0x8f, 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, 0xdd, 0xcd, 0x74, - 0xca, 0x66, 0x3a, 0xdb, 0xcd, 0x84, 0x9a, 0x99, 0x6f, 0x59, 0x45, 0x9a, 0x93, 0x35, 0x51, 0x73, 0x2a, 0x7e, 0xa2, - 0x73, 0xd0, 0x8e, 0x72, 0x7b, 0xaf, 0x0a, 0x27, 0x57, 0x4e, 0x2e, 0xf7, 0x73, 0x43, 0x5c, 0x91, 0xb9, 0x50, 0x87, - 0x00, 0x2f, 0x2f, 0xca, 0xc7, 0x07, 0xb8, 0x14, 0xbf, 0xca, 0x91, 0x8b, 0x72, 0x2a, 0xa4, 0x96, 0x82, 0x45, 0xc8, - 0xa0, 0xaa, 0x8b, 0x81, 0xbd, 0xb4, 0x7b, 0x4f, 0xf4, 0x78, 0xbf, 0x8a, 0x98, 0x37, 0x30, 0xcf, 0x7d, 0x7c, 0x4f, - 0x53, 0xec, 0xd4, 0xc4, 0x19, 0xf9, 0x90, 0xc5, 0x39, 0xc8, 0x66, 0xfd, 0xea, 0xb5, 0xdf, 0x46, 0x1b, 0x17, 0xcd, - 0x58, 0xf4, 0xcc, 0x13, 0x27, 0x3f, 0x14, 0xc6, 0x38, 0xc0, 0x3a, 0xfa, 0x23, 0x4c, 0x2d, 0xd8, 0xb3, 0xc4, 0x53, - 0xe8, 0xe4, 0xd6, 0xa6, 0xdd, 0x85, 0x69, 0x77, 0x26, 0xad, 0x03, 0xe5, 0x80, 0x34, 0xbb, 0x32, 0x9d, 0x3b, 0xff, - 0x7d, 0x07, 0x2f, 0xdd, 0xae, 0x21, 0x12, 0xf7, 0xfc, 0x91, 0x31, 0x86, 0x78, 0x03, 0x36, 0xa2, 0xea, 0xe0, 0xe0, - 0x0f, 0xe7, 0x7d, 0x5b, 0xc9, 0x7d, 0xdf, 0x0a, 0x07, 0xb6, 0xc1, 0x54, 0xba, 0xbc, 0x91, 0xcc, 0x16, 0x60, 0xd7, - 0xb9, 0xff, 0x8d, 0x78, 0xf8, 0x22, 0x64, 0x5a, 0xac, 0xab, 0xf8, 0x2b, 0x39, 0x2a, 0x3d, 0x44, 0x35, 0x44, 0x20, - 0xad, 0xac, 0x4b, 0x43, 0xd3, 0xd1, 0xab, 0x29, 0x1d, 0xc9, 0x9b, 0xb7, 0x52, 0xea, 0x81, 0x7d, 0x91, 0x5b, 0x27, - 0xf0, 0x68, 0x61, 0x8d, 0xa1, 0xb9, 0x2b, 0xbd, 0x93, 0x6c, 0x40, 0xd4, 0xfa, 0xb8, 0x43, 0x49, 0x24, 0x16, 0xd5, - 0x5d, 0x08, 0x87, 0xbb, 0x10, 0xcc, 0xcb, 0xa0, 0x6d, 0x10, 0xbb, 0xdd, 0x05, 0x6d, 0x03, 0xa7, 0x6e, 0x1b, 0xb8, - 0x3d, 0x18, 0x2c, 0xec, 0x7d, 0x78, 0x39, 0x96, 0x63, 0xe1, 0xaf, 0xc9, 0xec, 0x03, 0x40, 0xa0, 0xf6, 0x61, 0xc5, - 0x13, 0x07, 0x82, 0xc4, 0x19, 0x8e, 0xbe, 0xe7, 0xec, 0xc6, 0x5a, 0x0e, 0xcf, 0xe6, 0x0b, 0xcd, 0x46, 0xe6, 0x8e, - 0x1a, 0x54, 0x7c, 0x75, 0x3f, 0xaf, 0x9f, 0xb2, 0x9a, 0x6e, 0xfc, 0x1e, 0x84, 0x91, 0x70, 0xca, 0x0e, 0xa3, 0x90, - 0xb0, 0xc1, 0xac, 0xca, 0x78, 0x6d, 0xbf, 0x41, 0xbc, 0x07, 0x6d, 0xc2, 0x09, 0x16, 0xb5, 0x0b, 0xaa, 0x08, 0xdb, - 0x78, 0x63, 0x41, 0x94, 0x87, 0x37, 0x5b, 0x46, 0xd3, 0xcb, 0x35, 0x04, 0x3a, 0xee, 0x45, 0xcd, 0xa8, 0xc1, 0x52, - 0x17, 0x94, 0xd9, 0x47, 0x18, 0x57, 0x17, 0x27, 0x26, 0x4e, 0x7b, 0xa9, 0x57, 0xff, 0x2d, 0x03, 0x03, 0x7c, 0x01, - 0x5e, 0x62, 0x61, 0x74, 0xd7, 0xbe, 0x6e, 0x40, 0x7d, 0xd9, 0x60, 0x03, 0xb4, 0x5a, 0xb5, 0xca, 0x67, 0xa0, 0xdc, - 0x35, 0x97, 0xb0, 0xd7, 0x5c, 0xc2, 0x5d, 0x73, 0x09, 0x7f, 0xcd, 0x25, 0xcc, 0x35, 0x97, 0xf0, 0xd7, 0x5c, 0x1e, - 0x84, 0x9f, 0x82, 0x38, 0x8e, 0x31, 0x87, 0xb8, 0x8a, 0xda, 0x46, 0xc6, 0x83, 0x0b, 0xcf, 0x7d, 0x96, 0xa8, 0x72, - 0xf9, 0xc3, 0x18, 0x72, 0x5b, 0xb6, 0x12, 0xc6, 0x6d, 0x8a, 0x29, 0x88, 0x9c, 0x7e, 0x70, 0x50, 0xba, 0x3b, 0x83, - 0x8f, 0x7a, 0xca, 0xf1, 0xd2, 0x3a, 0xd1, 0xfe, 0x01, 0x3a, 0x79, 0xf3, 0xeb, 0x63, 0x2a, 0xd7, 0x44, 0x38, 0x93, - 0xfb, 0xfd, 0xb6, 0xa7, 0x14, 0x9f, 0x32, 0x13, 0x9e, 0x9c, 0x27, 0xda, 0x88, 0x20, 0x08, 0x51, 0xa2, 0x70, 0x46, - 0xa4, 0xdd, 0xef, 0xde, 0x15, 0xde, 0xa8, 0xa2, 0xbc, 0x59, 0xc9, 0xe3, 0x1c, 0x9c, 0xd8, 0x8d, 0x15, 0x06, 0xea, - 0x82, 0x0b, 0x41, 0x66, 0x12, 0xfe, 0x68, 0xe6, 0x96, 0x9c, 0x65, 0x65, 0xd2, 0xc7, 0x66, 0x6e, 0x08, 0x58, 0x41, - 0xf6, 0x3d, 0xcc, 0x96, 0xb7, 0x29, 0xc5, 0x77, 0x69, 0x86, 0x87, 0xf2, 0x36, 0x2d, 0x42, 0x5b, 0x10, 0x7f, 0xf1, - 0x37, 0x8e, 0x23, 0x41, 0xc1, 0xdf, 0x27, 0xe2, 0x62, 0x8f, 0x6f, 0x78, 0x01, 0x2e, 0x33, 0x63, 0x51, 0x9d, 0x32, - 0xfc, 0x0d, 0x4b, 0x78, 0x08, 0x4e, 0xa6, 0xb1, 0x22, 0xf7, 0x38, 0xb0, 0x13, 0x92, 0x80, 0xc3, 0xd5, 0xed, 0x15, - 0xff, 0x0a, 0x17, 0x5f, 0xa5, 0xb3, 0x65, 0x73, 0x28, 0x6f, 0x23, 0x5c, 0x90, 0x37, 0xf0, 0xfa, 0xd6, 0xff, 0xcb, - 0xde, 0xdb, 0x36, 0xb7, 0x6d, 0x64, 0xeb, 0xa2, 0x7f, 0x45, 0x62, 0xd9, 0x0c, 0x60, 0x36, 0x29, 0xca, 0xe7, 0xcc, - 0x54, 0x5d, 0x50, 0x6d, 0x96, 0x63, 0xc7, 0x13, 0x67, 0x22, 0xdb, 0x63, 0x79, 0x32, 0xc9, 0xb0, 0x78, 0x19, 0x08, - 0x68, 0x0a, 0x70, 0x40, 0x80, 0x01, 0x40, 0x89, 0x34, 0x89, 0xff, 0x7e, 0x6a, 0xad, 0xd5, 0xaf, 0x20, 0x28, 0x7b, - 0xf6, 0x3e, 0xfb, 0xd3, 0xbd, 0x5f, 0x6c, 0xb1, 0xd1, 0x68, 0xf4, 0x7b, 0xaf, 0x5e, 0x2f, 0xcf, 0xd3, 0x93, 0xb1, - 0xba, 0x3d, 0x70, 0xd6, 0xa5, 0x14, 0x1d, 0x6f, 0x8a, 0xc3, 0xdb, 0xf3, 0xd9, 0x7e, 0x1b, 0x44, 0x6c, 0x17, 0x64, - 0x58, 0xeb, 0xa4, 0xe1, 0x3f, 0xd1, 0xd6, 0xc1, 0x62, 0x84, 0xfd, 0x5f, 0xd6, 0x03, 0x2f, 0x21, 0x35, 0x14, 0xb8, - 0x18, 0x6c, 0x38, 0x5a, 0xdb, 0x65, 0x1a, 0xb8, 0xa9, 0x41, 0xaf, 0xef, 0x29, 0x44, 0x79, 0xc9, 0x68, 0x6e, 0x04, - 0xeb, 0xc6, 0x90, 0x8b, 0xc3, 0x71, 0xb3, 0x1c, 0xf2, 0x92, 0xa6, 0xd3, 0x20, 0x94, 0xee, 0x2c, 0x6b, 0x48, 0xa2, - 0xec, 0x83, 0x50, 0xbb, 0xb6, 0xec, 0xb7, 0x81, 0xed, 0xcb, 0x1f, 0x0d, 0x63, 0xff, 0x62, 0xf9, 0x4c, 0x48, 0x17, - 0xf1, 0x1c, 0x04, 0x51, 0xfb, 0x79, 0x36, 0xdc, 0xf8, 0x17, 0xeb, 0x67, 0x42, 0xf9, 0x8d, 0xe7, 0xb6, 0x1c, 0x52, - 0x67, 0x2d, 0x7c, 0x61, 0x3c, 0x3c, 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, 0x01, 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, 0xee, 0x52, 0xa6, 0xcb, 0x80, 0x4b, 0xfa, 0x5d, 0xaa, 0x94, 0xc2, 0x7f, 0x22, 0x00, 0x9d, 0x83, 0x7b, 0x7c, - 0x39, 0x06, 0xd2, 0x0c, 0x0b, 0xbf, 0x35, 0x3b, 0xbe, 0x26, 0xe1, 0x36, 0x09, 0x2e, 0x06, 0x38, 0x47, 0x57, 0x61, - 0x79, 0x97, 0x42, 0x04, 0x55, 0x09, 0xf5, 0xad, 0x4c, 0x83, 0xd2, 0x56, 0x83, 0xb0, 0x26, 0xa1, 0xce, 0x24, 0x1b, - 0x95, 0xb6, 0x1b, 0x85, 0xd9, 0x22, 0xae, 0x67, 0x84, 0x35, 0x67, 0x33, 0xd5, 0xc0, 0xa4, 0xe1, 0xb8, 0x69, 0xb4, - 0x16, 0x15, 0x6a, 0x0a, 0xf3, 0x1a, 0x57, 0x95, 0xaa, 0xee, 0xe6, 0xd4, 0x52, 0x5a, 0xb6, 0x57, 0xdd, 0x24, 0x1b, - 0x72, 0x19, 0xca, 0x30, 0xd8, 0xc8, 0x11, 0x4c, 0x20, 0x49, 0xce, 0xfc, 0x8d, 0xfc, 0x43, 0x6d, 0xba, 0x16, 0x30, - 0xc7, 0x98, 0x65, 0xc3, 0x82, 0x5e, 0x81, 0x7b, 0xa0, 0x95, 0x9e, 0x4f, 0xb3, 0x8b, 0x3c, 0x48, 0x86, 0x85, 0x5e, - 0x36, 0x19, 0xff, 0x53, 0x18, 0x69, 0x32, 0x63, 0x25, 0x8b, 0x6c, 0x57, 0xa7, 0xc4, 0x79, 0x9c, 0xc0, 0xf6, 0x68, - 0x7a, 0xcb, 0xf7, 0x19, 0x44, 0x05, 0x81, 0x82, 0x19, 0xf3, 0x65, 0x17, 0xcf, 0x7d, 0x9f, 0x59, 0xa6, 0xee, 0xc3, - 0xc1, 0x98, 0xb1, 0xfd, 0x7e, 0x3f, 0xef, 0xf7, 0xd5, 0x7c, 0xeb, 0xf7, 0x93, 0x17, 0xe6, 0x6f, 0x0f, 0x18, 0x14, - 0xe4, 0x44, 0x34, 0x15, 0x22, 0xf8, 0x87, 0xe4, 0x19, 0x92, 0xd1, 0x1d, 0xf7, 0xb9, 0xe5, 0x6c, 0x59, 0x1d, 0x81, - 0x60, 0x1e, 0x0e, 0x97, 0x0a, 0xec, 0x5a, 0xa2, 0x48, 0xc8, 0xf2, 0x9f, 0x81, 0xf1, 0xcc, 0x7d, 0x80, 0x25, 0x03, - 0x10, 0xb6, 0xca, 0xd3, 0xf5, 0x9e, 0xaf, 0x82, 0x77, 0x3a, 0xde, 0x35, 0x56, 0x64, 0x20, 0x6e, 0x81, 0x8d, 0x58, - 0x6b, 0x0f, 0xc8, 0x99, 0x02, 0x1c, 0x2f, 0x0e, 0x87, 0x73, 0xf9, 0x4b, 0x37, 0x5b, 0x27, 0x50, 0x29, 0x70, 0x7b, - 0x74, 0x72, 0xf0, 0xdf, 0x81, 0x66, 0x50, 0x0e, 0xf3, 0x7a, 0xfb, 0x3b, 0x73, 0xf2, 0xd3, 0x53, 0xfc, 0x13, 0x1e, - 0xa2, 0xd3, 0x6f, 0xf7, 0xe6, 0x0f, 0x8a, 0xca, 0xc3, 0x41, 0x2d, 0xfe, 0x73, 0xce, 0x2b, 0xf8, 0x85, 0x6f, 0x02, - 0xb3, 0xc9, 0xd4, 0x3b, 0xf9, 0x26, 0xcf, 0x99, 0x7a, 0x8d, 0x57, 0x4c, 0xbe, 0xc3, 0xe1, 0x5c, 0x8c, 0xea, 0xed, - 0xc8, 0x89, 0x76, 0xca, 0x31, 0x0e, 0x06, 0xff, 0x45, 0xb4, 0x4d, 0x08, 0x30, 0xa4, 0x6e, 0x49, 0x33, 0x1b, 0x57, - 0x96, 0x78, 0x96, 0xce, 0x2f, 0x27, 0x75, 0xb9, 0xd3, 0x8a, 0xa7, 0x3d, 0xb0, 0xb8, 0xad, 0xc1, 0x0b, 0xe0, 0xde, - 0x62, 0xeb, 0x4a, 0xc1, 0xe1, 0x02, 0xe2, 0x14, 0x27, 0x20, 0x82, 0xf6, 0xfb, 0x12, 0xef, 0x15, 0xf4, 0x49, 0x3f, - 0x40, 0x30, 0xe4, 0xcf, 0x12, 0x70, 0xd7, 0xeb, 0xd5, 0x18, 0xdf, 0x4b, 0x21, 0xb8, 0x3e, 0xd3, 0x00, 0xb4, 0xe0, - 0x77, 0xf9, 0x58, 0x4e, 0xbf, 0x89, 0xc0, 0xb3, 0x65, 0x6f, 0xa2, 0xdc, 0x6d, 0x78, 0xda, 0x3f, 0x5a, 0x08, 0xc0, - 0x52, 0x3c, 0x53, 0x82, 0x05, 0x39, 0xc5, 0x5c, 0xfc, 0xbf, 0xe0, 0x23, 0xe6, 0x7b, 0xd2, 0x45, 0x6c, 0xbd, 0x7d, - 0x72, 0x61, 0x20, 0x81, 0xa6, 0x03, 0xf0, 0xe3, 0x55, 0x40, 0x57, 0xc6, 0xcf, 0xcf, 0xb2, 0x1e, 0xeb, 0xe3, 0x3f, - 0x05, 0xf7, 0xe9, 0x67, 0x0a, 0x1f, 0x1d, 0x8e, 0xab, 0x74, 0xb4, 0xa3, 0x14, 0x44, 0x47, 0xb7, 0xcf, 0xa7, 0x3c, - 0xfb, 0xa6, 0x02, 0x72, 0xcb, 0x51, 0x7b, 0x2a, 0x00, 0x8b, 0x2d, 0x1d, 0x81, 0x4f, 0xb3, 0x7c, 0x42, 0xbe, 0xd7, - 0x53, 0x71, 0x75, 0xa9, 0xd3, 0xc5, 0x8b, 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, 0x75, 0x8d, 0x82, 0x95, 0x80, 0x33, 0xed, 0x1a, 0x0c, 0x36, 0xb0, - 0x6e, 0x59, 0x06, 0x7f, 0xc3, 0x35, 0x4d, 0xe0, 0x86, 0x45, 0xd6, 0x7b, 0x83, 0xad, 0x74, 0x0d, 0x8e, 0x96, 0x89, - 0x73, 0x29, 0xc9, 0xca, 0x16, 0x19, 0x57, 0x8f, 0x42, 0xaa, 0xa6, 0xfb, 0x5b, 0x51, 0x3f, 0x08, 0x91, 0x07, 0xab, - 0x94, 0x45, 0xc5, 0x0a, 0x64, 0xf6, 0xe0, 0x1f, 0x21, 0x23, 0x47, 0x39, 0x70, 0x14, 0xfa, 0x5b, 0x13, 0xe8, 0x3c, - 0x3f, 0x85, 0x3a, 0x8f, 0x04, 0x5b, 0xa9, 0x87, 0xc2, 0xca, 0x0b, 0x88, 0x0e, 0xb6, 0x30, 0x56, 0x79, 0x12, 0x2a, - 0x36, 0x65, 0x22, 0x8f, 0x83, 0x5a, 0x02, 0xc6, 0x0a, 0x82, 0x39, 0xcb, 0xa5, 0x0b, 0x52, 0xd5, 0xe8, 0x61, 0x91, - 0xb9, 0x9f, 0x0a, 0xca, 0xff, 0x54, 0xe5, 0x84, 0xeb, 0xcb, 0x10, 0xe0, 0x68, 0x9f, 0x82, 0x28, 0x31, 0xd6, 0x2f, - 0x5a, 0xbc, 0x93, 0x99, 0xb3, 0xa9, 0xed, 0x25, 0xc8, 0xd8, 0x0e, 0xbf, 0x42, 0x68, 0xb5, 0x50, 0x64, 0xd1, 0x70, - 0xc1, 0x74, 0x7b, 0x4a, 0xab, 0xee, 0x61, 0xc3, 0xb3, 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, 0x69, - 0x34, 0x9f, 0xe5, 0x73, 0x1f, 0x15, 0x17, 0x93, 0xc1, 0x60, 0xe3, 0x67, 0xc3, 0x21, 0x4b, 0x86, 0xc3, 0x49, 0xf6, - 0x14, 0x5e, 0x7b, 0xca, 0x23, 0xb5, 0xa4, 0x92, 0xab, 0x0c, 0xf6, 0xf7, 0x01, 0x8f, 0x7c, 0xd6, 0xf9, 0x69, 0xd9, - 0x74, 0xe9, 0x7e, 0x66, 0xc7, 0x5d, 0xe8, 0x0e, 0xb0, 0xf1, 0xb6, 0x41, 0x47, 0xfe, 0xf5, 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, 0x07, 0xf7, 0x85, 0x15, 0x05, - 0xfe, 0xdf, 0xb2, 0x05, 0xbb, 0x97, 0xc7, 0xc0, 0x35, 0x3a, 0x26, 0xc1, 0x05, 0xe2, 0x9e, 0xdd, 0x82, 0x1d, 0x16, - 0xfe, 0x82, 0xeb, 0xe4, 0x98, 0xed, 0xf0, 0x51, 0xe8, 0x15, 0xec, 0xd6, 0x27, 0xa0, 0x5d, 0xb0, 0x35, 0x40, 0x36, - 0xb6, 0xc5, 0x47, 0x77, 0x87, 0xc3, 0xb5, 0xe7, 0xb3, 0x07, 0xfc, 0x71, 0x7e, 0x77, 0x38, 0xec, 0x3c, 0xa3, 0xde, - 0xbb, 0xe1, 0x09, 0x7b, 0xcf, 0x93, 0xc9, 0xcd, 0x15, 0x8f, 0x27, 0x83, 0xc1, 0x8d, 0xbf, 0xe0, 0xf5, 0xec, 0x06, - 0xb4, 0x03, 0xe7, 0x0b, 0xa9, 0x6b, 0xf6, 0x6e, 0x79, 0xe6, 0x2d, 0x70, 0x6c, 0x6e, 0xe1, 0xe8, 0xed, 0xf7, 0xbd, - 0x3b, 0x1e, 0x79, 0xb7, 0xa4, 0x62, 0x5a, 0x71, 0xc5, 0xf1, 0xb6, 0xc5, 0xfd, 0x74, 0xc5, 0x43, 0x78, 0x84, 0x55, - 0x99, 0xde, 0x04, 0xef, 0x7d, 0xb6, 0xd2, 0x2c, 0x70, 0x0f, 0x98, 0x63, 0x4d, 0x76, 0x42, 0x33, 0xf1, 0x57, 0xd8, - 0x3f, 0x37, 0xaa, 0x7f, 0x68, 0xfe, 0x97, 0xba, 0x9f, 0xc0, 0xed, 0x8b, 0x2c, 0x48, 0xec, 0x3d, 0xbf, 0x61, 0xf7, - 0xdc, 0xb0, 0xcd, 0x9e, 0x99, 0xb2, 0x4f, 0x94, 0x1a, 0x3f, 0x52, 0xea, 0xda, 0x32, 0xac, 0x64, 0xee, 0xbe, 0x8c, - 0xc0, 0xe1, 0x80, 0xfc, 0x74, 0x87, 0x38, 0x08, 0xad, 0x9b, 0xac, 0xe6, 0x8a, 0x72, 0x2e, 0xb4, 0x65, 0xe6, 0xe5, - 0xc0, 0x62, 0x96, 0x52, 0x68, 0x2c, 0x00, 0x10, 0x4c, 0x0a, 0xad, 0xbd, 0x97, 0x01, 0xe4, 0x04, 0x0d, 0x7f, 0x6c, - 0xae, 0x8a, 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, 0xa7, - 0xbc, 0x66, 0x82, 0xc8, 0x36, 0x2a, 0x7f, 0x52, 0xbc, 0x40, 0x32, 0x82, 0xe2, 0x69, 0xad, 0x32, 0x16, 0x86, 0x79, - 0xa0, 0x80, 0xbc, 0x7b, 0x77, 0xea, 0x5b, 0xfb, 0x63, 0xc7, 0x9e, 0xad, 0x55, 0xa8, 0x85, 0x9a, 0xc2, 0x25, 0x87, - 0xe8, 0x0a, 0x32, 0x50, 0xc8, 0x78, 0xf2, 0x7a, 0x70, 0x39, 0x89, 0xae, 0xb8, 0x40, 0x67, 0x7c, 0x7d, 0xd3, 0x4d, - 0x67, 0xd1, 0xd3, 0x6a, 0x3e, 0x21, 0x25, 0xd9, 0xe1, 0x90, 0x8d, 0xaa, 0xba, 0x58, 0x4f, 0x43, 0xf9, 0xd3, 0x43, - 0xf0, 0xf5, 0x82, 0x7a, 0x4d, 0x56, 0xa9, 0x7e, 0x4a, 0x95, 0xf2, 0xa2, 0xe1, 0xa5, 0xff, 0xb4, 0x92, 0xfb, 0x1e, - 0x90, 0xd6, 0xf2, 0x92, 0xcb, 0xf7, 0x23, 0xc4, 0x18, 0xf1, 0x03, 0xaf, 0xe4, 0x11, 0x0b, 0xd5, 0x14, 0xae, 0x79, - 0x84, 0x20, 0x6f, 0x99, 0x0e, 0xfe, 0xd6, 0x13, 0xa7, 0xfb, 0x13, 0xa5, 0x5d, 0x7c, 0x61, 0x51, 0xf7, 0x64, 0x6d, - 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, 0xf9, 0xb0, 0xe1, 0x11, 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, 0xfb, 0xb9, 0x80, 0x20, 0x88, 0x92, 0x78, 0x7c, 0xc0, 0xfb, 0xb2, 0x1a, 0x6a, 0x94, 0x7c, 0x2c, - 0x1b, 0xa9, 0xf4, 0x4a, 0xf4, 0x77, 0x63, 0x2e, 0x31, 0xe0, 0x75, 0xd5, 0x16, 0x14, 0xce, 0xf3, 0xc3, 0xe1, 0x3c, - 0x1f, 0x19, 0xcf, 0x32, 0x50, 0xad, 0x4c, 0xeb, 0x20, 0x36, 0xf3, 0xc5, 0xc2, 0x5f, 0xec, 0x9c, 0x44, 0x44, 0x41, - 0x60, 0x47, 0xc2, 0x83, 0x48, 0xfd, 0xaa, 0xf2, 0x74, 0xa7, 0xfa, 0x6c, 0xbf, 0xb0, 0x89, 0xf4, 0x82, 0x92, 0xc9, - 0x27, 0xc1, 0x5e, 0xf5, 0x77, 0x10, 0x36, 0x84, 0x37, 0xaf, 0x7a, 0x9d, 0x65, 0x6a, 0x56, 0x82, 0x84, 0x19, 0x73, - 0x04, 0x8f, 0xc3, 0x4e, 0x63, 0x1b, 0x1e, 0x5b, 0x70, 0x74, 0xde, 0x9a, 0xdd, 0xb1, 0x15, 0xbb, 0x55, 0x75, 0x5a, - 0xf0, 0x70, 0x3a, 0xbc, 0x0c, 0x70, 0xf5, 0xad, 0xcf, 0x39, 0xbf, 0xa3, 0x13, 0x6c, 0x3d, 0xe0, 0xd1, 0x44, 0xcc, - 0xd6, 0x4f, 0x23, 0xb5, 0x78, 0xd6, 0x43, 0xbe, 0xa0, 0xf5, 0x27, 0x66, 0x77, 0x26, 0xf9, 0x6e, 0xc0, 0x17, 0x93, - 0xf5, 0xd3, 0x08, 0x5e, 0x7d, 0x0a, 0x56, 0x8c, 0xcc, 0x99, 0x65, 0xeb, 0xa7, 0x11, 0x8e, 0xd9, 0xdd, 0xd3, 0x88, - 0x46, 0x6d, 0x25, 0xf7, 0xa5, 0xdb, 0x06, 0x84, 0x95, 0x5b, 0x16, 0xc3, 0x6b, 0x20, 0x9e, 0x69, 0x23, 0xe9, 0x5a, - 0x1a, 0x7a, 0x63, 0x1e, 0x4e, 0xe3, 0x60, 0x4d, 0xad, 0x90, 0x67, 0x86, 0x98, 0xc5, 0x4f, 0xa3, 0x39, 0x5b, 0x61, - 0x45, 0x36, 0x3c, 0x1e, 0x5c, 0x4e, 0x36, 0x57, 0x7c, 0x0d, 0xe4, 0x67, 0x93, 0x8d, 0xd9, 0xa2, 0x6e, 0xb9, 0x98, - 0x6d, 0x9e, 0x46, 0xf3, 0xc9, 0x0a, 0x7a, 0xd6, 0x1e, 0x30, 0xef, 0x0d, 0x88, 0x50, 0x12, 0x52, 0x53, 0x6e, 0x7a, - 0x3d, 0xb6, 0x1e, 0x07, 0x77, 0x6c, 0x7d, 0x19, 0xdc, 0xb2, 0xf5, 0x18, 0x88, 0x38, 0xa8, 0xdf, 0xbd, 0x0d, 0x2c, - 0xbe, 0x88, 0xad, 0x2f, 0x4d, 0xda, 0xe6, 0x69, 0xc4, 0xdc, 0xc1, 0x69, 0xe0, 0x82, 0xb5, 0xc9, 0xbc, 0x15, 0x83, - 0x4b, 0xc8, 0xd2, 0x8b, 0xd9, 0x66, 0x78, 0xc9, 0xd6, 0x23, 0x9c, 0xea, 0x89, 0xcf, 0xee, 0xf8, 0x2d, 0x4b, 0xf8, - 0xaa, 0x89, 0xaf, 0x36, 0xa0, 0x11, 0x3d, 0xca, 0xa0, 0xaf, 0xa0, 0x66, 0xe6, 0xbc, 0xb2, 0x30, 0x2a, 0xf7, 0x2d, - 0x38, 0xa0, 0x20, 0x6d, 0x03, 0x04, 0x49, 0x3c, 0xbb, 0x57, 0xe1, 0xfa, 0x46, 0x0a, 0x03, 0x6e, 0x02, 0x33, 0x60, - 0x60, 0xfa, 0x19, 0xfc, 0xb0, 0xd2, 0x25, 0x42, 0x9c, 0xfd, 0x94, 0x92, 0x64, 0x9e, 0x9f, 0x8a, 0x34, 0x77, 0x0b, - 0xd7, 0x29, 0xcc, 0x8a, 0x02, 0xd5, 0x4f, 0x49, 0x69, 0x60, 0xa1, 0x12, 0x99, 0x4a, 0xc1, 0x2f, 0x9b, 0xf3, 0x28, - 0x3b, 0x46, 0xe7, 0x3a, 0xbf, 0x9c, 0x38, 0xa7, 0x93, 0xbe, 0xff, 0xc0, 0x31, 0x6c, 0x21, 0x03, 0x17, 0xfe, 0xd4, - 0x13, 0xc6, 0xa9, 0x15, 0x88, 0xa9, 0xe4, 0xd9, 0x53, 0xf8, 0x4c, 0x68, 0x75, 0x74, 0xe1, 0xfb, 0x41, 0xa1, 0x4d, - 0xd2, 0x2d, 0x48, 0x52, 0xf0, 0x14, 0x3d, 0xe7, 0xbc, 0x0d, 0x54, 0x8a, 0x11, 0x2d, 0x88, 0xb4, 0xb5, 0xcc, 0x1c, - 0xa4, 0x2d, 0xcd, 0x77, 0x4d, 0xfc, 0x1c, 0x16, 0x70, 0x11, 0x2d, 0x6c, 0x0d, 0x8f, 0xaa, 0x58, 0xb9, 0x37, 0x79, - 0x8e, 0x70, 0x46, 0x97, 0x32, 0x01, 0x70, 0xbd, 0x5f, 0x87, 0xb5, 0xc2, 0x2b, 0x6a, 0x16, 0x79, 0x51, 0xd3, 0x27, - 0x5b, 0xe0, 0x3e, 0x16, 0x25, 0x0a, 0x9c, 0xb5, 0x60, 0xc0, 0x56, 0x58, 0xb2, 0x93, 0xc2, 0xa6, 0x68, 0x09, 0xbd, - 0x3d, 0x7e, 0x3a, 0xa8, 0x99, 0x0c, 0xa0, 0x09, 0xa0, 0xf1, 0xf8, 0x17, 0x80, 0x9a, 0xde, 0xd4, 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, 0x83, 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, 0x8b, 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, 0xb5, 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, 0x4e, 0x6e, 0x61, 0xcb, 0x4c, - 0x56, 0xf3, 0x7d, 0xc5, 0x1d, 0x94, 0x6f, 0xb6, 0xce, 0xf8, 0x5e, 0x22, 0x7b, 0xb7, 0x81, 0x12, 0x5e, 0x8c, 0xfe, - 0x82, 0xf4, 0xdb, 0x0c, 0xe3, 0x94, 0xdb, 0x4a, 0x5a, 0x80, 0xd3, 0x3f, 0x1c, 0xde, 0x57, 0x18, 0x34, 0x38, 0xc2, - 0x38, 0xb2, 0x7e, 0xff, 0xb6, 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, 0x9f, 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, 0x3a, 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, 0xeb, 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, 0x4f, 0x9f, - 0x03, 0x69, 0x59, 0xbf, 0x1f, 0xbd, 0xb8, 0x9c, 0x3e, 0x1f, 0x46, 0x01, 0x38, 0x76, 0xd9, 0xcb, 0xcb, 0x98, 0xaf, - 0x2e, 0x99, 0x65, 0x0a, 0x8b, 0x7c, 0x33, 0xa0, 0xba, 0x64, 0xb5, 0x74, 0xbd, 0x02, 0x2c, 0x5d, 0x7e, 0xf3, 0x10, - 0xa6, 0x06, 0x34, 0xb2, 0xe6, 0xee, 0x34, 0xd7, 0x02, 0xa5, 0x9e, 0xf7, 0x33, 0x43, 0xbe, 0x2e, 0x83, 0xae, 0x20, - 0xdd, 0xf3, 0x88, 0xf4, 0x72, 0x2f, 0x9d, 0xee, 0xf7, 0xa5, 0x00, 0x4b, 0x7d, 0x29, 0x3e, 0x83, 0xc2, 0xa2, 0xf1, - 0x8d, 0x00, 0x6d, 0x0d, 0xd5, 0xb4, 0x57, 0x8a, 0xaa, 0x17, 0xf4, 0x4a, 0xf1, 0xb9, 0xa7, 0x87, 0xca, 0x7c, 0x59, - 0x3a, 0xfa, 0x9f, 0x50, 0x73, 0xc1, 0x09, 0x31, 0x13, 0x73, 0x00, 0x95, 0xa0, 0x8d, 0x6f, 0x75, 0xb4, 0xf1, 0xa9, - 0x5e, 0xc5, 0x4d, 0x9f, 0xd7, 0xd6, 0x32, 0x27, 0x84, 0x4d, 0xf7, 0x12, 0xa0, 0x22, 0xaf, 0x84, 0x47, 0xb0, 0xfc, - 0xf2, 0x87, 0x3c, 0x5d, 0x21, 0x5a, 0xc7, 0x3d, 0xcb, 0x5c, 0x1a, 0xfb, 0x37, 0x06, 0xd3, 0xd7, 0xb7, 0xdb, 0x22, - 0x3f, 0x35, 0x31, 0x61, 0x3d, 0x56, 0xf4, 0xcd, 0xbb, 0x70, 0x25, 0x50, 0xe0, 0x50, 0x22, 0xb1, 0x4d, 0x15, 0x8a, - 0x78, 0x90, 0xf4, 0xe9, 0xa2, 0xf5, 0x69, 0x80, 0xa9, 0xb5, 0x1c, 0x98, 0x43, 0xb8, 0x8a, 0x0b, 0x1f, 0x3d, 0x7d, - 0x8b, 0x59, 0x38, 0x9f, 0x78, 0x1f, 0xbd, 0x62, 0x64, 0x3e, 0xee, 0xa3, 0x52, 0x49, 0xff, 0x3c, 0x1c, 0x66, 0xd5, - 0xdc, 0x77, 0xe8, 0x23, 0x3d, 0x54, 0xb9, 0xa0, 0xec, 0x8d, 0x31, 0x89, 0x40, 0x69, 0x8c, 0xf7, 0x71, 0x70, 0x9c, - 0xf7, 0x69, 0x00, 0xa9, 0x7d, 0xe2, 0x3d, 0x29, 0x39, 0x3c, 0xe7, 0x98, 0x13, 0x4a, 0x2b, 0xc2, 0x2a, 0xbe, 0xc8, - 0x50, 0xae, 0x3b, 0xa5, 0x60, 0x92, 0x43, 0x82, 0xe1, 0xaf, 0x9a, 0x37, 0xb1, 0x02, 0x61, 0xd7, 0xcc, 0xab, 0xd1, - 0x93, 0x2a, 0x09, 0x4b, 0x01, 0x47, 0x65, 0xe6, 0x19, 0xf6, 0x86, 0x27, 0x86, 0x91, 0x83, 0xe5, 0xfe, 0xa8, 0x4e, - 0x44, 0xee, 0xd1, 0x05, 0x46, 0x65, 0xe1, 0x79, 0x43, 0x57, 0x1a, 0x54, 0x92, 0x1d, 0x7f, 0xc5, 0x35, 0xa0, 0xb6, - 0xc6, 0x88, 0xa1, 0x80, 0x51, 0xf0, 0xda, 0xfe, 0x10, 0xb2, 0x28, 0x5b, 0xbf, 0xc1, 0x31, 0x9f, 0x95, 0xdc, 0xf5, - 0x0e, 0x67, 0xa1, 0x25, 0xe4, 0xc9, 0x1d, 0x83, 0x34, 0x8d, 0xa5, 0x11, 0x70, 0x22, 0x92, 0x6d, 0x2c, 0x85, 0x23, - 0x80, 0x80, 0x40, 0x37, 0x65, 0x86, 0x31, 0x1d, 0x8c, 0x3c, 0x4f, 0x7a, 0xc6, 0x7b, 0x15, 0x9e, 0x42, 0x9a, 0x6c, - 0x5f, 0xcf, 0xdf, 0x1b, 0x41, 0x56, 0x6e, 0x39, 0xc7, 0xc3, 0xe2, 0x1b, 0x67, 0x5f, 0xe5, 0xe4, 0x29, 0x66, 0x19, - 0xe9, 0x9d, 0x62, 0x5e, 0xc0, 0x9f, 0xca, 0x52, 0x9f, 0xa3, 0xf4, 0x96, 0xf9, 0x64, 0x15, 0x49, 0x97, 0xde, 0xa6, - 0xdf, 0x8f, 0x47, 0xea, 0x50, 0xf3, 0xf7, 0xf1, 0x48, 0x9e, 0x61, 0x1b, 0x96, 0xb0, 0xd0, 0x2a, 0x18, 0x03, 0x48, - 0x62, 0x23, 0xa2, 0xc1, 0x68, 0x6f, 0x0e, 0x87, 0xf3, 0x8d, 0x39, 0x4b, 0xf6, 0xe0, 0xfa, 0xca, 0x13, 0xf3, 0x0e, - 0x7c, 0x99, 0xc7, 0x04, 0x11, 0x9b, 0x79, 0x1b, 0x56, 0x83, 0x07, 0x3b, 0xb8, 0x3e, 0x62, 0x8b, 0x62, 0xad, 0x63, - 0xa9, 0xac, 0x83, 0xd3, 0x3a, 0x36, 0xcd, 0x48, 0x29, 0xb2, 0xcf, 0xb1, 0xbf, 0x77, 0x83, 0xab, 0x6b, 0x63, 0x50, - 0x6b, 0xdc, 0x61, 0xee, 0x9c, 0x0a, 0xa8, 0xc7, 0x74, 0x05, 0xd5, 0xb3, 0x9c, 0x7c, 0xf9, 0xad, 0x9d, 0x03, 0x82, - 0x46, 0x20, 0x70, 0xd1, 0x40, 0xab, 0x76, 0x29, 0xe7, 0x5d, 0x40, 0x88, 0x6f, 0x52, 0xd0, 0xa7, 0x33, 0xd8, 0xc4, - 0xe6, 0x13, 0x88, 0x45, 0xd3, 0x7d, 0xae, 0x35, 0xf3, 0xc5, 0x88, 0x76, 0x66, 0xdd, 0x2d, 0x72, 0xab, 0x85, 0x48, - 0x46, 0xcf, 0x36, 0x13, 0x2e, 0x3a, 0x94, 0x33, 0x12, 0x30, 0x41, 0x6b, 0x2b, 0x25, 0x9f, 0xeb, 0x5e, 0x27, 0x68, - 0x0f, 0x24, 0xad, 0xfb, 0x37, 0x8b, 0xce, 0x28, 0x39, 0xb9, 0xde, 0xe4, 0x0c, 0x52, 0xb0, 0x60, 0x7b, 0x99, 0x13, - 0x6e, 0x80, 0x4f, 0x6c, 0x96, 0x9c, 0xa6, 0x41, 0x1e, 0x0b, 0xe3, 0x91, 0xd7, 0xe6, 0x97, 0x05, 0x74, 0x28, 0x59, - 0x34, 0x42, 0x3c, 0xc0, 0xce, 0x21, 0xb9, 0x2a, 0x50, 0x37, 0x0d, 0x74, 0xe5, 0xca, 0x99, 0x62, 0x0a, 0x5c, 0x08, - 0x05, 0x51, 0x3b, 0x3a, 0x89, 0xca, 0x79, 0x9f, 0x54, 0x97, 0xf9, 0xb4, 0x90, 0xa6, 0x81, 0x7c, 0x5a, 0x39, 0xe6, - 0x81, 0x9d, 0x6d, 0x5c, 0x13, 0x18, 0xe8, 0xd4, 0xbe, 0x16, 0xe5, 0x1c, 0xab, 0x88, 0xde, 0xe7, 0x1f, 0x2a, 0x7b, - 0xfa, 0x20, 0xc2, 0x46, 0x05, 0x1a, 0x4b, 0x89, 0xb1, 0x91, 0xe3, 0xdf, 0x12, 0x65, 0x43, 0x86, 0x80, 0x10, 0xd2, - 0x46, 0x4e, 0x3f, 0xac, 0x2f, 0x6f, 0x33, 0xed, 0xff, 0x49, 0xe2, 0xb7, 0xc1, 0x5e, 0x4e, 0xfd, 0xa9, 0x47, 0x3c, - 0x5e, 0x6b, 0xf4, 0x98, 0x92, 0x6e, 0x83, 0x3c, 0x55, 0x9e, 0x82, 0x64, 0xc2, 0x58, 0x42, 0xb0, 0x28, 0x17, 0x3c, - 0xe7, 0x15, 0x97, 0x70, 0x1f, 0xb5, 0xac, 0x88, 0x50, 0x95, 0xc8, 0xe9, 0xf3, 0x15, 0xf0, 0x4c, 0x40, 0xa0, 0x63, - 0x8c, 0x34, 0xaa, 0xe0, 0x4b, 0x60, 0xac, 0x03, 0x65, 0xa7, 0x19, 0x09, 0x2e, 0xbb, 0x37, 0x48, 0x94, 0xfa, 0x9a, - 0x94, 0xa4, 0xd7, 0xa2, 0xc6, 0x2b, 0xb1, 0x8a, 0x48, 0x20, 0x43, 0x0d, 0x11, 0xab, 0xea, 0xa9, 0x7b, 0x55, 0x4c, - 0x06, 0x83, 0xca, 0x97, 0xd3, 0x13, 0x6f, 0x68, 0xa8, 0xbc, 0xeb, 0x8a, 0x76, 0x7a, 0xa2, 0x95, 0xf2, 0x16, 0xd2, - 0x12, 0x34, 0x0d, 0x23, 0xcd, 0xa1, 0xd4, 0x95, 0x74, 0x37, 0x06, 0xf1, 0x25, 0x13, 0x3d, 0xdb, 0xa9, 0x1d, 0xa5, - 0x2d, 0x69, 0x0f, 0x21, 0x3d, 0x77, 0xc9, 0xc7, 0x2c, 0xe4, 0xea, 0x4e, 0x39, 0x29, 0xaf, 0x42, 0x74, 0x72, 0xdf, - 0x63, 0x48, 0x04, 0xfa, 0x9c, 0x63, 0x58, 0x17, 0x0d, 0x75, 0x0e, 0x2b, 0xc4, 0x6c, 0xa1, 0x84, 0xf9, 0x92, 0xf1, - 0x54, 0x32, 0x68, 0x00, 0x64, 0xc0, 0x67, 0x2f, 0x03, 0xcb, 0x5f, 0x41, 0xfc, 0x68, 0xe3, 0xc3, 0xe1, 0xcf, 0x9a, - 0x42, 0x6c, 0xff, 0x84, 0xcd, 0x10, 0x1e, 0xd5, 0x03, 0x9e, 0xf9, 0x26, 0x4e, 0xd0, 0x0a, 0x48, 0xca, 0xec, 0x68, - 0x22, 0x7b, 0xd5, 0x43, 0x38, 0x95, 0x15, 0xa8, 0xa3, 0xac, 0xb3, 0x12, 0x7e, 0x84, 0xa9, 0x6e, 0x25, 0xd6, 0x02, - 0x6d, 0xae, 0x56, 0xac, 0x05, 0x70, 0xe0, 0xe7, 0x10, 0x3c, 0x91, 0xcf, 0xc1, 0xc5, 0xa0, 0x00, 0x9f, 0x03, 0xe0, - 0x45, 0xee, 0xc2, 0x83, 0x79, 0x64, 0x59, 0x8d, 0x30, 0x1c, 0x55, 0xc4, 0xfa, 0x35, 0xdb, 0x91, 0x0f, 0xdc, 0x8e, - 0xf1, 0xb9, 0xf6, 0x58, 0xb2, 0x1c, 0x8c, 0x32, 0xf7, 0x6a, 0x89, 0x9e, 0x37, 0x69, 0xdc, 0x8c, 0x9e, 0xec, 0x6b, - 0xf9, 0xbf, 0xa0, 0x97, 0x41, 0x7f, 0x0b, 0xb7, 0xbc, 0xe6, 0x77, 0x0b, 0x22, 0xcd, 0xf4, 0x0a, 0x22, 0x65, 0xd4, - 0x88, 0x8c, 0x21, 0x6c, 0x52, 0xdd, 0xdc, 0x26, 0xd5, 0x85, 0x80, 0xa7, 0x23, 0x52, 0x5d, 0x0b, 0x69, 0x23, 0x9f, - 0xd6, 0x81, 0x8c, 0x45, 0x7a, 0xf7, 0xc3, 0xdf, 0x5e, 0x7e, 0x7a, 0xfb, 0xcb, 0x0f, 0x8b, 0xb7, 0xef, 0xde, 0xbc, - 0x7d, 0xf7, 0xf6, 0xd3, 0x6f, 0x04, 0xe1, 0x31, 0x15, 0x2a, 0xc3, 0x87, 0xf7, 0x37, 0x6f, 0x9d, 0x0c, 0xb6, 0x37, - 0x43, 0xd6, 0xbe, 0x91, 0x83, 0x21, 0x10, 0xd9, 0x20, 0x64, 0x90, 0x9d, 0xda, 0xf6, 0x67, 0x62, 0x8e, 0xb1, 0x77, - 0x02, 0x93, 0x2d, 0xe0, 0x1c, 0xcb, 0xbc, 0x64, 0x44, 0xae, 0x0a, 0xad, 0x1f, 0xd0, 0x82, 0x6b, 0x70, 0x91, 0x49, - 0xf3, 0xbb, 0x5f, 0x08, 0x62, 0x9f, 0x56, 0x52, 0xee, 0xab, 0x6d, 0xcd, 0xf3, 0xed, 0xfd, 0x5e, 0xc2, 0xf9, 0xcf, - 0xa5, 0x11, 0xb5, 0x00, 0x07, 0xe0, 0x73, 0xf8, 0xe3, 0x4a, 0x5b, 0xd2, 0x64, 0x16, 0xed, 0x67, 0x0c, 0x41, 0x97, - 0x06, 0x1f, 0xc4, 0x1e, 0x79, 0xa9, 0x4f, 0x16, 0x12, 0xb8, 0x23, 0x86, 0x4f, 0x2b, 0x82, 0x5e, 0x31, 0xa2, 0xb8, - 0xe4, 0x0a, 0x95, 0x52, 0xf2, 0x6f, 0x94, 0x5d, 0x54, 0xc8, 0x59, 0xc1, 0xee, 0x15, 0x39, 0x32, 0x7e, 0x10, 0x4c, - 0x7c, 0x39, 0xb8, 0xff, 0x12, 0xef, 0x70, 0xa6, 0x38, 0x92, 0x13, 0xfe, 0x90, 0x61, 0x60, 0x7f, 0x0e, 0x3e, 0xaf, - 0x0e, 0xf3, 0xf2, 0x46, 0x9f, 0x72, 0x4b, 0x3e, 0x9e, 0x2c, 0xaf, 0xc0, 0x60, 0xbf, 0x54, 0xcd, 0x5d, 0xf3, 0x7a, - 0xb6, 0x9c, 0xb3, 0xfd, 0x2c, 0x9a, 0x07, 0x77, 0x6c, 0x96, 0xcd, 0x83, 0x55, 0xc3, 0xd7, 0xec, 0x96, 0xaf, 0xad, - 0xaa, 0xad, 0xed, 0xaa, 0x4d, 0x36, 0xfc, 0x16, 0x24, 0x84, 0x9b, 0xcc, 0x03, 0xde, 0xe3, 0x3b, 0x9f, 0x6d, 0x40, - 0xa2, 0x5d, 0xb1, 0x0d, 0x5c, 0xc4, 0xd6, 0xfc, 0x87, 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, 0x7d, 0x5a, 0x6d, 0xc2, - 0x0c, 0x3d, 0xcb, 0xe1, 0xa3, 0xad, 0x14, 0xfc, 0xf4, 0x02, 0xbf, 0x64, 0x47, 0x6d, 0xa5, 0x6d, 0xbb, 0x2a, 0xb1, - 0x15, 0xb4, 0x28, 0xb2, 0x5a, 0xe1, 0x81, 0x39, 0x7f, 0x01, 0x0b, 0x18, 0x7b, 0x8e, 0x73, 0x5e, 0xfb, 0x23, 0x64, - 0xbc, 0x77, 0x00, 0xd0, 0x32, 0xc7, 0x01, 0x1e, 0xb1, 0x62, 0x14, 0x0d, 0xde, 0xf9, 0xa5, 0xb2, 0x5a, 0x69, 0x4e, - 0x42, 0xdb, 0x88, 0x55, 0xcb, 0x91, 0xaa, 0x19, 0x91, 0x3e, 0x48, 0xcf, 0xfb, 0x1e, 0x51, 0x0d, 0xf6, 0x64, 0x5e, - 0x07, 0xf6, 0xe9, 0x55, 0x6b, 0x55, 0x77, 0x7e, 0x4f, 0x95, 0x2e, 0x39, 0xb2, 0xe5, 0xa7, 0xcb, 0xf0, 0x41, 0xfd, - 0x29, 0xb9, 0x3e, 0x14, 0x38, 0xc2, 0x63, 0x15, 0x70, 0xbe, 0x5e, 0x89, 0x76, 0x27, 0xc2, 0xae, 0x5c, 0x02, 0x42, - 0x7c, 0x49, 0xd3, 0x1c, 0x8f, 0x23, 0x9a, 0x88, 0xb0, 0x89, 0xd1, 0x5f, 0xd8, 0x7d, 0x28, 0xb1, 0x9c, 0xe7, 0x1a, - 0x94, 0x5c, 0x32, 0x78, 0x4f, 0xda, 0x6b, 0xd0, 0x2c, 0xaf, 0x4a, 0x4d, 0x26, 0x72, 0x50, 0x3e, 0x1c, 0x0a, 0xd8, - 0x4b, 0x8d, 0x9f, 0x26, 0xfc, 0x84, 0xe5, 0xad, 0xbd, 0x35, 0xa5, 0xa8, 0xa4, 0x01, 0x2a, 0xf0, 0x31, 0x83, 0xff, - 0xdd, 0x19, 0x62, 0xc1, 0x14, 0x1d, 0x3f, 0x9c, 0x89, 0xb9, 0xf5, 0xdc, 0x2a, 0xeb, 0x28, 0x5b, 0xa3, 0x9c, 0x80, - 0x7f, 0x4b, 0x75, 0x9c, 0x24, 0xc2, 0xa9, 0xf7, 0x88, 0x8b, 0xba, 0x97, 0x43, 0xd4, 0x0d, 0x7b, 0x5b, 0xe9, 0x60, - 0xcb, 0x69, 0x1a, 0x1c, 0x89, 0x5f, 0xa9, 0xcf, 0xde, 0x67, 0x16, 0x8f, 0x3a, 0xb2, 0x11, 0x25, 0x69, 0x1c, 0x8b, - 0x1c, 0xb6, 0xf7, 0x85, 0xdc, 0xff, 0xfb, 0x7d, 0x08, 0x27, 0xad, 0x82, 0xa4, 0xf4, 0x04, 0x22, 0xc2, 0xd1, 0xe1, - 0x47, 0x84, 0x27, 0x52, 0x55, 0xf8, 0xa4, 0x3e, 0x71, 0x63, 0x76, 0x2f, 0xcc, 0x51, 0xbd, 0x05, 0x18, 0xc6, 0x7a, - 0x6b, 0x11, 0x92, 0x68, 0xa5, 0x19, 0x6d, 0x3d, 0x20, 0x46, 0xbc, 0x5f, 0x5b, 0x64, 0x30, 0xd6, 0x96, 0x44, 0x02, - 0xf8, 0x1d, 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, 0xeb, 0xa3, 0x74, 0x92, 0x58, 0xdf, - 0x77, 0x95, 0x0a, 0x36, 0x9b, 0x1b, 0xd4, 0x97, 0x1d, 0x25, 0xbf, 0x02, 0x27, 0x1d, 0x27, 0x59, 0xe4, 0x20, 0x6a, - 0x51, 0x39, 0x37, 0x49, 0x58, 0xda, 0xd5, 0xa9, 0x36, 0xeb, 0x75, 0x51, 0xd6, 0xd5, 0x6b, 0x11, 0x29, 0x7a, 0x1f, - 0xf5, 0xe8, 0x89, 0x84, 0x54, 0x68, 0x55, 0x6a, 0x97, 0x47, 0xe0, 0xb6, 0xa9, 0x15, 0xdb, 0x72, 0x09, 0x4b, 0xd4, - 0xf8, 0x4f, 0xd0, 0x47, 0xb9, 0x78, 0x90, 0x01, 0x1a, 0x1d, 0x4f, 0xcd, 0x5b, 0x8f, 0xbc, 0x72, 0x94, 0x5f, 0x5a, - 0x6d, 0xd2, 0x2f, 0x80, 0xcc, 0x68, 0xff, 0x68, 0x29, 0x81, 0xcc, 0xc0, 0x4c, 0x5a, 0x1a, 0x12, 0x39, 0x8a, 0x59, - 0x9a, 0xff, 0x81, 0x2b, 0xb6, 0x42, 0xa4, 0x61, 0x35, 0xf7, 0xf8, 0xcb, 0xca, 0xab, 0xe5, 0x5a, 0x66, 0x9a, 0x9b, - 0x25, 0x8e, 0x15, 0x8b, 0x8b, 0x7a, 0x5d, 0x89, 0x2c, 0x10, 0xe2, 0x08, 0xd3, 0x58, 0x4f, 0xbd, 0x51, 0x5a, 0x7d, - 0x40, 0x42, 0x99, 0x1f, 0xb0, 0xb7, 0x63, 0xaf, 0x07, 0x59, 0x88, 0x63, 0xcb, 0xc1, 0x66, 0xeb, 0x7d, 0x2a, 0x53, - 0x11, 0x9f, 0xd5, 0xc5, 0xd9, 0xa6, 0x12, 0x67, 0x75, 0x22, 0xce, 0xbe, 0x83, 0x9c, 0xdf, 0x9d, 0x51, 0xd1, 0x67, - 0x0f, 0x69, 0x9d, 0x14, 0x9b, 0x9a, 0x9e, 0xbc, 0xc1, 0x32, 0xbe, 0x3b, 0x23, 0xae, 0x9a, 0x33, 0x1a, 0xc9, 0x78, - 0x74, 0xf6, 0x21, 0x03, 0x92, 0xd7, 0xb3, 0x74, 0x05, 0x83, 0x77, 0x16, 0xe6, 0xf1, 0x59, 0x29, 0xee, 0xc0, 0xe2, - 0x54, 0x76, 0xbe, 0x07, 0x19, 0x56, 0xe1, 0x1f, 0xe2, 0x0c, 0xa0, 0x5d, 0xcf, 0xd2, 0xfa, 0x2c, 0xad, 0xce, 0xf2, - 0xa2, 0x3e, 0x53, 0x52, 0x38, 0x84, 0xf1, 0xc3, 0x7b, 0xfa, 0xca, 0x2e, 0x6f, 0xb3, 0xb8, 0xcb, 0x22, 0x7f, 0x8a, - 0x5e, 0x45, 0xc4, 0xa4, 0x51, 0x09, 0xaf, 0xdd, 0xdf, 0x36, 0xf7, 0x0f, 0xaf, 0x1b, 0xbb, 0x9f, 0xdd, 0x31, 0xa2, - 0x0b, 0xea, 0xf1, 0x4a, 0x52, 0x2a, 0x28, 0x20, 0x70, 0xa2, 0x59, 0xe3, 0xc1, 0x1d, 0x07, 0xbc, 0x1a, 0xd8, 0x92, - 0xad, 0x7d, 0xfe, 0x22, 0x96, 0x61, 0xda, 0x9b, 0x00, 0xff, 0x2a, 0x7b, 0xd3, 0x75, 0xb0, 0xc4, 0xfb, 0x16, 0xb2, - 0x0d, 0xbd, 0x7d, 0xcd, 0x5f, 0x7a, 0xb9, 0xfa, 0x9b, 0xfd, 0x13, 0x80, 0x30, 0x20, 0x66, 0xd5, 0x47, 0x13, 0xf7, - 0xce, 0xca, 0xb2, 0x73, 0xb2, 0xec, 0x7a, 0xe8, 0xd7, 0x24, 0x46, 0xa5, 0x95, 0xa5, 0x74, 0xb2, 0x94, 0x90, 0x05, - 0x7c, 0x62, 0x34, 0xb5, 0x11, 0x40, 0xd8, 0x8e, 0x52, 0xf9, 0x42, 0xe5, 0x45, 0x14, 0xce, 0x09, 0x9e, 0x27, 0x62, - 0x74, 0x6f, 0x25, 0x03, 0x86, 0x43, 0x08, 0xe6, 0xa0, 0x2d, 0xf6, 0x86, 0x6e, 0x22, 0xfe, 0x7a, 0x53, 0x94, 0x6f, - 0x63, 0xf2, 0x29, 0xd8, 0x9d, 0x7c, 0x5c, 0xc2, 0xe3, 0xf2, 0xe4, 0xe3, 0x10, 0x3d, 0x12, 0x4e, 0x3e, 0x06, 0xdf, - 0x23, 0x39, 0xaf, 0xbb, 0x1e, 0x27, 0xc8, 0x2d, 0xa4, 0xfb, 0xdb, 0x31, 0x09, 0xd0, 0xbc, 0x86, 0xe5, 0xa8, 0xa9, - 0xb8, 0x66, 0x66, 0x8c, 0xe7, 0x8d, 0xde, 0x1f, 0x3b, 0xde, 0x32, 0x85, 0x62, 0x16, 0xf3, 0x1a, 0x7e, 0xcf, 0xaa, - 0x40, 0xdd, 0xf5, 0x36, 0xc9, 0x2d, 0xb3, 0x7a, 0x8e, 0x76, 0xdf, 0xf7, 0x75, 0x22, 0xa8, 0xfd, 0x1d, 0xf6, 0x3c, - 0xb3, 0xde, 0x55, 0x31, 0x70, 0xa9, 0x92, 0x1d, 0x32, 0x55, 0x4d, 0x0f, 0x54, 0x4a, 0x83, 0xa7, 0x97, 0xd6, 0xe5, - 0x4b, 0xa5, 0x8d, 0x3c, 0xd3, 0xfc, 0x06, 0xf0, 0x62, 0xea, 0xb2, 0xd8, 0x7d, 0x75, 0x5f, 0xc1, 0x6d, 0xbc, 0xdf, - 0x5f, 0x56, 0x9e, 0xf9, 0x89, 0x0b, 0xc0, 0xde, 0x54, 0x68, 0x9d, 0x40, 0xa9, 0x61, 0x1d, 0xbe, 0x4a, 0x44, 0xf4, - 0x47, 0xbb, 0x5c, 0x67, 0xae, 0x03, 0x46, 0x14, 0xf1, 0xdb, 0x78, 0xf4, 0x07, 0x28, 0xae, 0x8d, 0x3d, 0x20, 0xac, - 0x43, 0x42, 0x9f, 0x11, 0x80, 0xd4, 0x63, 0x8e, 0x12, 0xd0, 0xac, 0x68, 0xee, 0x98, 0xfc, 0x5c, 0x5f, 0x29, 0xfd, - 0xfd, 0xb2, 0xf2, 0xc8, 0x9c, 0xd2, 0x36, 0xd3, 0x58, 0xad, 0xa9, 0x04, 0xc2, 0x2b, 0x2a, 0x59, 0x85, 0xcf, 0xe6, - 0x8d, 0xe8, 0xf7, 0xe5, 0x11, 0x9e, 0x56, 0x3f, 0x6c, 0x31, 0xbe, 0x15, 0x10, 0x8d, 0x04, 0x40, 0x3f, 0x01, 0xcc, - 0x8b, 0x6c, 0x66, 0xf7, 0x71, 0x40, 0x95, 0x12, 0x4d, 0xe3, 0x6c, 0x9e, 0xdf, 0xd2, 0x9b, 0xb2, 0x83, 0x4e, 0x9d, - 0x2a, 0x70, 0xc1, 0x55, 0xc9, 0x78, 0x65, 0x3d, 0x91, 0xcf, 0x6f, 0x6e, 0x37, 0x69, 0x16, 0xbf, 0x2f, 0xff, 0x89, - 0x63, 0xab, 0xeb, 0xf0, 0xc8, 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, 0x4d, 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, 0x1e, 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, 0x45, 0x85, 0x3a, 0x27, 0x96, 0xf1, 0x1a, 0x80, 0xb5, 0x73, 0xd5, 0xcf, - 0xb3, 0x1a, 0x3c, 0x69, 0x88, 0xcf, 0xc7, 0x68, 0x7b, 0x65, 0x73, 0x50, 0x6d, 0xa7, 0xb3, 0xf2, 0x8a, 0xe9, 0x72, - 0x60, 0xdc, 0x37, 0xbc, 0xa2, 0x38, 0xc3, 0x8f, 0x1e, 0x6c, 0x71, 0xfe, 0x74, 0x43, 0xed, 0xc7, 0xdc, 0xa8, 0x87, - 0x81, 0xd6, 0x82, 0x37, 0x05, 0xb1, 0xfe, 0x7e, 0xe8, 0xc8, 0xf6, 0x5e, 0x8b, 0x8c, 0x26, 0x9f, 0xfd, 0xfc, 0x43, - 0x99, 0xae, 0x52, 0xb8, 0x2f, 0x39, 0x59, 0x34, 0xf3, 0x10, 0xd8, 0x1b, 0x62, 0xb8, 0x3e, 0x2a, 0x3c, 0xa2, 0xac, - 0xdf, 0x87, 0xdf, 0x57, 0x19, 0x98, 0x62, 0xe0, 0xba, 0x42, 0x30, 0x1e, 0x02, 0x41, 0x3c, 0x4c, 0xa3, 0x93, 0x41, - 0x0d, 0xda, 0xf0, 0x0d, 0x40, 0x66, 0x80, 0x47, 0xe6, 0xd2, 0x23, 0xe0, 0x2e, 0x70, 0xed, 0xc9, 0x78, 0xec, 0x4f, - 0x4c, 0x43, 0xa3, 0xa6, 0x34, 0xd3, 0x73, 0xe3, 0x37, 0x1d, 0xd5, 0x72, 0xed, 0xfc, 0xc7, 0x97, 0xfc, 0x06, 0xbd, - 0xa0, 0xe5, 0xe5, 0x3e, 0x52, 0x97, 0xfb, 0x8c, 0xe2, 0x32, 0x91, 0x1c, 0x16, 0xc4, 0xb2, 0x84, 0x03, 0x8f, 0x51, - 0xc9, 0x62, 0x4b, 0x8f, 0x55, 0xd1, 0xf2, 0x45, 0xb9, 0x41, 0x3a, 0x74, 0x42, 0xb0, 0x44, 0x05, 0xc1, 0x12, 0x18, - 0x17, 0xb1, 0xe6, 0x9b, 0x41, 0xce, 0xe2, 0xd9, 0x66, 0xce, 0x91, 0xb0, 0x2e, 0x39, 0x1c, 0x0a, 0x09, 0x36, 0x93, - 0xcd, 0xd6, 0x73, 0xb6, 0xf6, 0x19, 0x28, 0x01, 0x4a, 0x99, 0x26, 0x28, 0x4d, 0x2b, 0xb6, 0xe2, 0xa6, 0x35, 0x58, - 0xad, 0xa6, 0x6c, 0x55, 0x53, 0x76, 0x4e, 0x53, 0x8e, 0x2a, 0x28, 0x39, 0xa1, 0x14, 0x65, 0x18, 0xc0, 0x88, 0x4d, - 0xa2, 0xab, 0x0c, 0x7d, 0xbc, 0x13, 0x1e, 0x41, 0x15, 0x11, 0xf9, 0x84, 0x21, 0x04, 0x26, 0xa2, 0xb8, 0x50, 0x85, - 0x62, 0x80, 0x8c, 0x48, 0x20, 0x98, 0xa8, 0xd4, 0x29, 0x30, 0x1f, 0x4d, 0x15, 0xc3, 0xa6, 0x3d, 0x51, 0xbe, 0xa5, - 0x8e, 0x7b, 0x94, 0x6d, 0xfe, 0x2e, 0x76, 0x41, 0x88, 0xdc, 0x8d, 0x3b, 0xf5, 0x33, 0xe2, 0xbd, 0xdd, 0x11, 0xc6, - 0x4f, 0x76, 0xdc, 0x22, 0x5c, 0x11, 0x6c, 0xa9, 0xe6, 0x10, 0x8b, 0x79, 0x35, 0x49, 0x50, 0xcb, 0x92, 0xf8, 0x1b, - 0x9e, 0x0c, 0x72, 0xb6, 0x04, 0x0f, 0xda, 0x39, 0xcb, 0x00, 0x7f, 0xc5, 0x6a, 0xd1, 0x6f, 0xb5, 0xb7, 0x04, 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, 0x8f, 0xbd, 0x04, 0x3b, 0x07, 0xbc, 0x81, 0xb4, 0x81, - 0x37, 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, 0x22, 0x01, - 0xc0, 0xa4, 0xce, 0x81, 0x38, 0x33, 0xc1, 0x2e, 0x4d, 0x22, 0xcb, 0xc7, 0x30, 0xbf, 0x13, 0x6f, 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, 0x52, 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, 0xd7, 0x90, 0x74, 0x6c, - 0xe0, 0xb4, 0xfa, 0x14, 0x7c, 0x90, 0xe4, 0x60, 0xa2, 0x0e, 0x5e, 0xee, 0x2f, 0xfd, 0x3e, 0x6c, 0xd9, 0xb9, 0x94, - 0xea, 0x58, 0xa9, 0xb7, 0x6d, 0xed, 0x07, 0xd1, 0x16, 0x1c, 0x59, 0xc4, 0xdf, 0x67, 0x88, 0x08, 0x66, 0x06, 0x11, - 0x76, 0x2d, 0xd4, 0xdd, 0x9e, 0x52, 0xcb, 0xa2, 0xde, 0xf6, 0x94, 0x52, 0xb7, 0x61, 0xf8, 0x6e, 0x82, 0x99, 0xe2, - 0x86, 0xff, 0x91, 0x79, 0xa1, 0xde, 0x78, 0x2c, 0x0a, 0x74, 0xcf, 0xdf, 0x2f, 0x79, 0x35, 0xdb, 0x28, 0x13, 0xe6, - 0x1d, 0x5f, 0xce, 0x42, 0xd9, 0xd5, 0xd2, 0xb8, 0xf3, 0xd9, 0x5b, 0xaa, 0xf9, 0xe0, 0x1f, 0x0e, 0x09, 0xc4, 0x1b, - 0xc5, 0x57, 0x77, 0x8d, 0xdc, 0xba, 0x26, 0x9b, 0xab, 0x12, 0x50, 0xbf, 0xcf, 0xd7, 0xb8, 0xdf, 0x62, 0xfd, 0xbb, - 0xa7, 0x41, 0xc6, 0x6a, 0x86, 0x2b, 0xa6, 0xf0, 0x29, 0x00, 0x0c, 0x0e, 0xa7, 0x82, 0xb4, 0xc0, 0x1b, 0x5e, 0x0e, - 0x2f, 0x27, 0x1b, 0x32, 0xe9, 0x6e, 0x7c, 0xe4, 0xce, 0x02, 0x55, 0xef, 0x37, 0x14, 0x27, 0x0d, 0x12, 0x8d, 0xbd, - 0x06, 0x5f, 0x66, 0x19, 0xe5, 0xa2, 0x89, 0xfb, 0x98, 0x7c, 0xa5, 0x07, 0x30, 0x57, 0xa1, 0x04, 0x88, 0x7e, 0x63, - 0x59, 0x6c, 0x44, 0xdb, 0x62, 0x03, 0x4b, 0xa9, 0x9a, 0xeb, 0xd5, 0xf4, 0xd9, 0x2b, 0xd1, 0xbc, 0x8f, 0x66, 0x9c, - 0xd2, 0x68, 0xc0, 0x71, 0x1a, 0x85, 0xdb, 0xf7, 0xf7, 0xa2, 0x5c, 0x66, 0x60, 0xc9, 0x56, 0xe1, 0x14, 0x97, 0x8d, - 0x3a, 0x23, 0x5e, 0xe6, 0xb1, 0x02, 0xe8, 0x78, 0x4c, 0x00, 0x54, 0x17, 0x04, 0x54, 0x44, 0x4b, 0xe9, 0xad, 0xd0, - 0x62, 0xa1, 0xde, 0x70, 0x94, 0xc2, 0x1f, 0xe9, 0xcf, 0x83, 0x7c, 0x0a, 0x40, 0xec, 0xfa, 0x38, 0x7a, 0x53, 0x94, - 0xf4, 0xa9, 0x62, 0x96, 0xcb, 0xc1, 0x04, 0x76, 0x75, 0x22, 0x43, 0xad, 0x20, 0x6f, 0xd5, 0x95, 0xb7, 0x32, 0x79, - 0x1b, 0xe3, 0x94, 0xfc, 0xc8, 0x4d, 0xc7, 0x1a, 0x31, 0xf0, 0xca, 0xd3, 0x3a, 0x4d, 0x90, 0x26, 0x17, 0xc0, 0x30, - 0xc4, 0xb7, 0x99, 0xf7, 0xd2, 0x73, 0xa4, 0x2a, 0x48, 0x66, 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, 0xcb, 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, 0xb5, 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, 0x17, 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, 0x57, 0x99, 0xbe, 0x85, 0x98, 0x28, 0xa7, 0x1a, 0x21, 0x71, 0xa5, 0x24, 0x11, 0x1f, - 0x2f, 0x5a, 0x56, 0x8c, 0xca, 0xf0, 0x81, 0x57, 0xaa, 0x7c, 0x75, 0xaa, 0xf2, 0x62, 0xa4, 0x6d, 0x09, 0xbc, 0x26, - 0xff, 0x10, 0xb9, 0xe6, 0xad, 0xaf, 0xbb, 0xca, 0xd0, 0x6b, 0x59, 0x81, 0x8e, 0x60, 0x2b, 0x4b, 0xc9, 0x01, 0x9f, - 0x54, 0x77, 0xd5, 0xaa, 0xf5, 0x39, 0x65, 0x1b, 0xe1, 0x26, 0xbf, 0x8e, 0x1d, 0x1c, 0x29, 0xbf, 0xc1, 0x73, 0x01, - 0xec, 0x35, 0x60, 0x6f, 0xce, 0x59, 0xd1, 0x3c, 0x3a, 0xa4, 0x6d, 0x81, 0x46, 0x66, 0x6e, 0xe7, 0xea, 0xbe, 0x2d, - 0x8f, 0xd2, 0x18, 0x22, 0xd3, 0x1e, 0x99, 0x0e, 0x36, 0xa3, 0xfc, 0xb7, 0x94, 0xdf, 0x2a, 0x1c, 0x03, 0xdf, 0x4e, - 0xbd, 0x03, 0xa8, 0x7a, 0xda, 0x20, 0x63, 0xcd, 0x30, 0xb4, 0xb2, 0xcb, 0xa5, 0xd0, 0x12, 0xb4, 0xd4, 0x4d, 0x10, - 0x9c, 0x1f, 0x11, 0xe5, 0x08, 0x40, 0x17, 0x29, 0x60, 0x82, 0x9f, 0xd2, 0x76, 0xf7, 0xfb, 0xeb, 0xd4, 0x23, 0xf7, - 0xae, 0x50, 0xa3, 0x84, 0x12, 0x8c, 0xfd, 0x44, 0x63, 0x06, 0x1d, 0x5d, 0x91, 0x13, 0x9e, 0xb5, 0x3a, 0xac, 0xeb, - 0xa6, 0x0c, 0xca, 0xe2, 0x98, 0x57, 0xd3, 0xd9, 0xef, 0x4f, 0xf6, 0x75, 0x83, 0x2c, 0xe4, 0xbf, 0xb3, 0x1e, 0x92, - 0x41, 0xf7, 0x20, 0x14, 0xa2, 0x37, 0x0f, 0x66, 0xf8, 0x1f, 0xdb, 0xf0, 0xec, 0x1b, 0x6e, 0xd4, 0x09, 0x60, 0x8e, - 0xb8, 0x5e, 0x7a, 0x8a, 0xb6, 0x1e, 0x6e, 0x81, 0x6c, 0x8d, 0x97, 0xb7, 0xf6, 0x1a, 0xc8, 0x29, 0x8e, 0xff, 0x8e, - 0x67, 0x6a, 0x65, 0x83, 0x9f, 0x9e, 0xb2, 0x1d, 0x78, 0x78, 0x11, 0x02, 0x8a, 0x61, 0xd9, 0xf8, 0x3b, 0xcb, 0x71, - 0x46, 0xff, 0xcd, 0x23, 0x86, 0xc1, 0x22, 0xf2, 0xe3, 0xcb, 0x52, 0x88, 0x2f, 0xc2, 0x7b, 0x5b, 0x79, 0x77, 0xe4, - 0x94, 0x79, 0xa7, 0x87, 0xd1, 0x75, 0x49, 0xfa, 0x26, 0xf9, 0xd8, 0x1a, 0xb6, 0xdf, 0xb5, 0xfb, 0xcd, 0x10, 0x41, - 0x08, 0xe5, 0xf8, 0x39, 0xa3, 0x13, 0x1a, 0x1f, 0x56, 0xb3, 0xd3, 0xeb, 0xf7, 0xce, 0xf1, 0x82, 0xad, 0xd1, 0x00, - 0x8f, 0x87, 0x2e, 0xe6, 0x89, 0x1a, 0x3a, 0x5d, 0xd7, 0xce, 0xc1, 0x03, 0x83, 0x2c, 0x4f, 0xbe, 0x61, 0x58, 0x62, - 0x7f, 0x12, 0xf1, 0xa4, 0xad, 0xda, 0xd8, 0x1c, 0xa9, 0x36, 0x6a, 0x06, 0x7e, 0xf0, 0x0a, 0x0a, 0x8c, 0x2e, 0x48, - 0x2b, 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, 0x6f, 0xa9, 0x57, 0xfb, 0x32, 0x66, 0x85, 0x7a, 0x7d, 0x61, 0xda, 0xf5, 0x5a, 0x5a, 0x14, 0x50, - 0x71, 0xdb, 0xaa, 0xed, 0x91, 0x9c, 0xff, 0xf8, 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, 0x6f, - 0xa9, 0x57, 0xb5, 0xa9, 0xea, 0xc1, 0x1b, 0x2f, 0x70, 0xf6, 0x4e, 0x6b, 0x01, 0x01, 0x14, 0xb6, 0x96, 0xe5, 0xe0, - 0xdc, 0xed, 0xaa, 0x96, 0x8a, 0x32, 0xea, 0xf7, 0xcf, 0x7f, 0x4b, 0x51, 0x11, 0x7b, 0xaa, 0x38, 0x65, 0xfd, 0x76, - 0xcb, 0x5c, 0x54, 0x96, 0xbc, 0x41, 0x15, 0xad, 0xd5, 0x51, 0x53, 0xb9, 0x6e, 0xae, 0x5a, 0x32, 0x41, 0x8c, 0xee, - 0xd3, 0xb5, 0xce, 0x9d, 0x7a, 0xef, 0x55, 0x1c, 0x31, 0x10, 0xdc, 0x74, 0x8f, 0x0f, 0x0e, 0x42, 0xa3, 0xa2, 0x5c, - 0x70, 0xa3, 0xb4, 0xaa, 0xa4, 0x14, 0xf2, 0x56, 0x45, 0x73, 0xa6, 0x8f, 0x00, 0x88, 0x00, 0xab, 0x44, 0xfd, 0x1f, - 0xbe, 0x34, 0xc6, 0x83, 0x07, 0xbe, 0x26, 0xd7, 0xb1, 0xf5, 0xfe, 0x69, 0x8d, 0xb4, 0xda, 0x38, 0x26, 0xb5, 0xea, - 0x65, 0xab, 0x78, 0xd9, 0xbd, 0x4e, 0xc5, 0xe0, 0xf9, 0xff, 0xdc, 0x07, 0xa8, 0x11, 0x2d, 0x65, 0x70, 0xeb, 0x6a, - 0x80, 0xc6, 0x87, 0x63, 0xe1, 0x1b, 0x3f, 0x64, 0x9c, 0x0f, 0x66, 0xe8, 0xa8, 0x36, 0x07, 0x07, 0x04, 0x47, 0x75, - 0x8f, 0xc6, 0x84, 0x59, 0x38, 0xf7, 0x20, 0x50, 0x7d, 0xe2, 0x3e, 0xe3, 0xda, 0x0b, 0xda, 0x04, 0x3e, 0x59, 0xd7, - 0x35, 0x45, 0x80, 0x8b, 0xd8, 0x98, 0x88, 0x21, 0x2e, 0x9b, 0x44, 0xea, 0x9b, 0x31, 0x28, 0x00, 0x8a, 0x17, 0x15, - 0xc9, 0xa5, 0x8b, 0x34, 0xaf, 0x44, 0x59, 0xeb, 0x66, 0x54, 0xac, 0x18, 0x02, 0xc0, 0x43, 0x50, 0x5c, 0x55, 0x66, - 0x42, 0x23, 0x36, 0x90, 0xca, 0x52, 0xb0, 0x6a, 0x58, 0xf8, 0x4d, 0xfb, 0x4d, 0x72, 0xd2, 0x3b, 0x1f, 0xb7, 0xce, - 0x1d, 0xfb, 0xde, 0x51, 0x48, 0x69, 0x0f, 0xc5, 0x04, 0x41, 0xf0, 0xd3, 0x3a, 0x9c, 0x3f, 0xe3, 0x2f, 0x08, 0x4c, - 0x45, 0x36, 0x63, 0xc0, 0x41, 0x88, 0xc8, 0x8c, 0xdf, 0x73, 0xf8, 0x82, 0x97, 0x93, 0x70, 0x38, 0xf4, 0x41, 0x1f, - 0xca, 0xb3, 0x59, 0x38, 0x14, 0x73, 0xe9, 0xbd, 0x0e, 0xd6, 0xba, 0x90, 0xd7, 0x93, 0x10, 0xd1, 0x42, 0x43, 0x1f, - 0x9c, 0xd7, 0x5d, 0x73, 0x84, 0x25, 0x00, 0x4d, 0x1c, 0x7d, 0x59, 0xbf, 0x1f, 0x79, 0xda, 0xd0, 0x22, 0xc5, 0x45, - 0xa3, 0xcc, 0x66, 0xb9, 0xec, 0x84, 0x8d, 0x6b, 0xb7, 0x40, 0x28, 0x1e, 0xa6, 0x2d, 0x54, 0xad, 0xa7, 0x7a, 0x3d, - 0x37, 0xed, 0xbe, 0x7b, 0x54, 0xad, 0x72, 0xa4, 0xb3, 0x36, 0x5d, 0xa9, 0xd5, 0x2d, 0xa3, 0x6a, 0x9d, 0xa5, 0x11, - 0x55, 0x6e, 0x92, 0xbb, 0x46, 0x2d, 0xf8, 0x64, 0x43, 0x97, 0x29, 0x3b, 0x5b, 0x83, 0x13, 0x47, 0x9e, 0x4b, 0x6e, - 0xf9, 0xee, 0xbc, 0xa2, 0xbb, 0x53, 0xed, 0x5b, 0x80, 0x7b, 0x33, 0x6c, 0xc8, 0x9c, 0xd7, 0xd8, 0x69, 0x10, 0x26, - 0x81, 0x1f, 0xb1, 0x8f, 0x19, 0xb2, 0xc1, 0x80, 0x8e, 0x42, 0xfa, 0x5f, 0x5b, 0xe6, 0x48, 0xc0, 0xe4, 0xaf, 0xe7, - 0x7e, 0xb3, 0x28, 0x72, 0x58, 0x8c, 0x1f, 0x36, 0x18, 0x69, 0xac, 0xd6, 0x60, 0x58, 0xde, 0x21, 0xf2, 0xa7, 0x76, - 0xc7, 0x34, 0xd5, 0xf1, 0x66, 0xbd, 0xd6, 0xfc, 0xea, 0xe9, 0x53, 0x5d, 0x9f, 0xff, 0xf6, 0xfd, 0x65, 0x58, 0x33, - 0xfb, 0x43, 0x10, 0x4a, 0xbb, 0x77, 0x8b, 0x73, 0x47, 0xa2, 0x77, 0xac, 0x34, 0xb3, 0x4b, 0xbb, 0x64, 0x97, 0xa6, - 0xb4, 0x1b, 0x72, 0xbd, 0xfa, 0x4a, 0x79, 0x63, 0xe7, 0x15, 0xd3, 0xfd, 0x7b, 0xa1, 0x77, 0x94, 0x53, 0x35, 0x81, - 0x88, 0x26, 0xed, 0x48, 0xdc, 0xee, 0x95, 0xe1, 0xf3, 0x49, 0xde, 0x2e, 0xe1, 0xa8, 0x6b, 0x58, 0x6e, 0xbe, 0xfd, - 0xcf, 0xbc, 0xea, 0xac, 0x70, 0xfb, 0xa5, 0x31, 0x6b, 0x7f, 0x0a, 0xe2, 0xaa, 0xfe, 0xf0, 0x9e, 0xd4, 0x4c, 0xc9, - 0xff, 0x55, 0x8f, 0x81, 0xab, 0x9f, 0x4c, 0x3b, 0xba, 0xa7, 0x10, 0x36, 0x98, 0xfd, 0xfc, 0xf8, 0xa1, 0x05, 0xab, - 0xea, 0x02, 0x45, 0x72, 0x00, 0x9d, 0xbb, 0x64, 0x84, 0xf7, 0x3b, 0xc6, 0xb9, 0x7f, 0xf5, 0xbd, 0x9a, 0x1c, 0x21, - 0xa2, 0x5d, 0x84, 0x03, 0x80, 0xb8, 0xd3, 0x54, 0xd6, 0xa1, 0x06, 0xe8, 0x03, 0x02, 0xeb, 0xd0, 0xb7, 0x19, 0xc0, - 0x41, 0x1f, 0x6d, 0x9e, 0x45, 0x20, 0xaf, 0x7b, 0xf7, 0xec, 0x9a, 0xed, 0x7c, 0xfe, 0x62, 0x95, 0x7a, 0xf7, 0xe8, - 0x10, 0x7c, 0x3e, 0xf6, 0xa7, 0x97, 0x81, 0xc1, 0x85, 0x66, 0xd7, 0xcf, 0x04, 0xdb, 0xb1, 0xdd, 0x33, 0x44, 0x2a, - 0xea, 0xce, 0x3f, 0xbc, 0x34, 0xd1, 0xf3, 0xce, 0x0b, 0x77, 0x7c, 0x09, 0xe0, 0x81, 0x2c, 0x06, 0x14, 0x9f, 0xa5, - 0xf7, 0x2f, 0x96, 0x80, 0x9a, 0xfc, 0x96, 0xaf, 0xbd, 0x2f, 0x94, 0xba, 0x80, 0x3f, 0x07, 0x94, 0x3e, 0xc9, 0xb9, - 0x77, 0x37, 0xbc, 0xf5, 0x2f, 0x9e, 0x83, 0xf3, 0xc4, 0x6a, 0xb8, 0x80, 0xbf, 0x0a, 0x3e, 0xf4, 0xee, 0x06, 0x98, - 0x58, 0xf2, 0xa1, 0xb7, 0x1a, 0x40, 0xaa, 0xc2, 0x85, 0xc4, 0xd8, 0x87, 0x5f, 0x83, 0x9c, 0xe1, 0x1f, 0xbf, 0x69, - 0x0c, 0xd6, 0x5f, 0x83, 0x42, 0xa3, 0xb1, 0x96, 0x2a, 0x64, 0x29, 0x16, 0x67, 0x02, 0x6c, 0xc2, 0x71, 0xb7, 0x2f, - 0x56, 0xb5, 0x59, 0x0b, 0xfa, 0xf3, 0x11, 0xdf, 0xa3, 0xb1, 0xba, 0x2a, 0xe7, 0xa2, 0xfc, 0x88, 0xf4, 0xa9, 0x8e, - 0x8f, 0x51, 0xb1, 0xa9, 0xbb, 0xd3, 0xa9, 0x56, 0x1d, 0x69, 0xbf, 0x29, 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, 0x2f, 0x06, 0xb9, 0x0c, 0x8d, 0xf9, 0x80, 0x6c, 0x18, 0xca, 0x87, 0x16, 0x19, 0x12, 0x22, 0xde, 0x43, - 0x25, 0x60, 0xdb, 0x82, 0x32, 0x29, 0xe0, 0x2c, 0x1a, 0xfc, 0x56, 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, 0x1f, 0xae, 0xf2, 0x4f, 0xd1, 0x52, 0x0f, 0xff, 0x9f, 0x31, 0x85, 0xd2, - 0xbf, 0x4a, 0xcb, 0x68, 0xb3, 0x5a, 0x8a, 0x52, 0xe4, 0x91, 0x38, 0xf9, 0x5a, 0x64, 0xe7, 0xf2, 0x9d, 0x4f, 0xa1, - 0x5f, 0x00, 0x5a, 0xf6, 0x09, 0x32, 0xfa, 0x7b, 0x26, 0xf8, 0xf0, 0x7b, 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, 0x7b, 0x83, 0x90, 0xe2, 0xf9, 0x03, 0x5b, 0xad, 0x8b, 0x8b, 0xc4, 0x2b, 0x64, - 0xa2, 0x05, 0xb1, 0x14, 0x81, 0x19, 0x2f, 0x34, 0x8d, 0x30, 0x41, 0x99, 0x12, 0x2c, 0x5a, 0xa3, 0x43, 0xfb, 0xc3, - 0x12, 0x76, 0x8f, 0x31, 0x02, 0x04, 0xaa, 0x4c, 0x9f, 0xc3, 0xd6, 0x84, 0xd9, 0xd4, 0xc5, 0x06, 0x68, 0xab, 0x18, - 0x1a, 0x84, 0xb5, 0x21, 0xe6, 0x63, 0x9a, 0xdf, 0xfd, 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, 0xee, 0x1a, 0xfe, 0x21, 0xf3, 0x62, 0x96, 0x80, 0x7e, 0x77, 0xc5, 0x55, 0x83, 0xa0, 0x19, 0x1b, 0x76, - 0x0b, 0xbf, 0x25, 0xd6, 0x6e, 0xe9, 0x5f, 0x2c, 0xd9, 0xc2, 0xf4, 0x81, 0x6e, 0x1d, 0x60, 0x19, 0x51, 0x93, 0xef, - 0x91, 0x77, 0xd3, 0x59, 0x51, 0xb8, 0x3d, 0xb1, 0x85, 0xcf, 0xae, 0xcd, 0x9b, 0xf7, 0xcf, 0x22, 0xc8, 0xbd, 0xe3, - 0xde, 0xfd, 0xf0, 0xda, 0xbf, 0xd0, 0x2d, 0x90, 0x93, 0x59, 0xce, 0x40, 0xea, 0x88, 0x4f, 0x10, 0xad, 0xec, 0x29, - 0xdf, 0x09, 0xb9, 0xb3, 0xad, 0x9f, 0xdd, 0xbb, 0xdb, 0xda, 0xdd, 0xb3, 0x7b, 0x56, 0x8d, 0x28, 0x56, 0x9c, 0xa6, - 0x48, 0x98, 0x45, 0x1b, 0xe0, 0xa9, 0x97, 0xef, 0x77, 0xec, 0x98, 0xc3, 0xdd, 0xb3, 0x8e, 0x8e, 0x97, 0x73, 0xc0, - 0xee, 0xfe, 0xa3, 0x4d, 0xd8, 0x58, 0xe9, 0x5a, 0x85, 0x0e, 0x77, 0xcf, 0x32, 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, 0x2b, 0x2e, 0xbe, 0x3f, 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, 0x9c, 0xc5, 0x90, 0x08, 0xb0, 0xdd, 0xa1, 0x62, 0x5b, 0xb8, 0x78, - 0xce, 0x36, 0xbc, 0xe8, 0xf7, 0x33, 0xd5, 0x29, 0x64, 0xdd, 0x59, 0xf2, 0x8d, 0x6a, 0x8e, 0x35, 0xd4, 0x6c, 0x6d, - 0x92, 0xad, 0x71, 0x6e, 0x2b, 0x3e, 0xee, 0xda, 0x8a, 0x8f, 0x95, 0xb5, 0x2e, 0xdd, 0xeb, 0x3d, 0xaa, 0x0b, 0x60, - 0xeb, 0xbf, 0x3d, 0x5e, 0xb9, 0x9e, 0xcf, 0x08, 0xe0, 0x6b, 0xc1, 0xc7, 0x93, 0x05, 0x7a, 0x95, 0x2c, 0xfc, 0xdb, - 0x81, 0x1a, 0x7f, 0xa7, 0x73, 0x17, 0x00, 0x5d, 0x49, 0x79, 0x05, 0xe4, 0x1d, 0xe4, 0x98, 0x5b, 0x76, 0xe5, 0xfd, - 0xc9, 0x77, 0xd8, 0x35, 0xaf, 0x67, 0x8b, 0x39, 0xdb, 0x81, 0x53, 0x41, 0x32, 0xb0, 0x97, 0x15, 0xdb, 0x05, 0xb1, - 0x9d, 0xf0, 0x1b, 0x01, 0x53, 0xbe, 0x84, 0x20, 0xae, 0xe0, 0x16, 0xe2, 0xf0, 0xe4, 0x9f, 0x83, 0xfb, 0xd6, 0x66, - 0x7d, 0xcf, 0xac, 0xce, 0x09, 0xd6, 0xcc, 0xea, 0xc1, 0x60, 0xd9, 0x4c, 0x56, 0xfd, 0xbe, 0xb7, 0xd3, 0x8e, 0x4f, - 0x77, 0x52, 0x27, 0x76, 0x5a, 0xab, 0xb5, 0x60, 0xd7, 0x52, 0xeb, 0x62, 0x0c, 0x3d, 0x40, 0xfc, 0x74, 0x3b, 0xe0, - 0xf7, 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, 0xc7, 0x6c, 0xc7, 0xb8, - 0xf9, 0xe9, 0xe5, 0x0f, 0x4e, 0x58, 0xb2, 0x62, 0xb5, 0x3f, 0xfd, 0xfe, 0x99, 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, 0x99, 0xfa, 0xc0, 0x88, 0x25, 0x81, 0xda, 0x5e, - 0x66, 0xe9, 0x1d, 0xa8, 0xf0, 0x7b, 0xb8, 0x9a, 0x88, 0xfd, 0xdc, 0x92, 0xa2, 0x22, 0x1b, 0xe9, 0x0d, 0xad, 0xc1, - 0x23, 0xb4, 0xa6, 0x7c, 0xef, 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, 0xd7, 0x24, 0x61, 0x4f, 0x0c, - 0x3a, 0x85, 0xaa, 0xdc, 0xee, 0x8e, 0xb6, 0xc0, 0x75, 0xcc, 0x52, 0xf4, 0xd2, 0x16, 0xb9, 0x5b, 0xfe, 0xdd, 0x73, - 0x45, 0xce, 0x7e, 0x09, 0x08, 0x4e, 0xcd, 0x57, 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, 0xe6, 0x2e, 0xc9, 0x37, 0xe0, - 0xcc, 0x40, 0xa9, 0x96, 0x7e, 0xe0, 0x58, 0x2d, 0xa0, 0xc2, 0xc1, 0xec, 0xa4, 0x5e, 0x58, 0x46, 0x3d, 0xa6, 0xcf, - 0xcf, 0x60, 0xef, 0x08, 0x09, 0x80, 0xfb, 0x65, 0x1f, 0x90, 0x80, 0x87, 0xce, 0xec, 0x80, 0x70, 0xc2, 0x2c, 0xaa, - 0x02, 0x89, 0xe4, 0x48, 0x3f, 0x7b, 0xcc, 0x44, 0xf2, 0x07, 0xb3, 0x9e, 0x73, 0x4a, 0xf4, 0x58, 0x4f, 0x1d, 0x21, - 0x3d, 0xd6, 0xb3, 0x8e, 0x88, 0x1e, 0xeb, 0x59, 0xc7, 0x47, 0x8f, 0xf5, 0xcc, 0xb1, 0xd3, 0x83, 0xc0, 0x04, 0x88, - 0x3c, 0x60, 0x3d, 0x9a, 0x4c, 0x3d, 0xc5, 0x3d, 0x40, 0x34, 0x08, 0xac, 0x27, 0x85, 0xf3, 0x1e, 0x20, 0x8f, 0x91, - 0x58, 0x1d, 0xf4, 0xfe, 0x32, 0x7e, 0xda, 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, - 0x07, 0x51, 0xf3, 0xb4, 0xd5, 0x56, 0xc1, 0xfe, 0x0e, 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, 0x1f, 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, 0x7f, 0x95, 0xa5, 0xc6, 0x39, 0x32, 0x97, 0xeb, 0xbb, 0x2e, 0xee, 0xee, 0x68, 0x9b, 0xb0, 0x0a, 0x11, - 0xea, 0xb6, 0xa1, 0x72, 0x29, 0xcc, 0xc6, 0xa6, 0x69, 0x80, 0x2f, 0x14, 0x95, 0x4a, 0x55, 0x6a, 0x2b, 0x95, 0x9c, - 0xf0, 0xae, 0xaf, 0x6a, 0x91, 0xba, 0x22, 0xd8, 0xc6, 0x0c, 0xf5, 0x50, 0x6e, 0xd4, 0xd8, 0xd7, 0x1d, 0xab, 0xf4, - 0x0e, 0x13, 0xe4, 0x8c, 0xbc, 0xc8, 0xc1, 0x45, 0x49, 0x41, 0xe6, 0x6a, 0x08, 0xf3, 0x47, 0x0d, 0x9f, 0x16, 0x96, - 0x7b, 0x28, 0x01, 0xb3, 0xa3, 0x86, 0x97, 0x11, 0x02, 0x11, 0x97, 0xca, 0xbe, 0x62, 0xe2, 0xf7, 0x14, 0xcc, 0x92, - 0x09, 0xdd, 0x8b, 0x58, 0x18, 0xa1, 0x8d, 0x4f, 0x92, 0x64, 0xea, 0x69, 0x0a, 0x6e, 0xe4, 0x32, 0xcc, 0xd1, 0x08, - 0x2d, 0xf9, 0xc8, 0x81, 0xf4, 0xb5, 0x9c, 0x4a, 0xf0, 0x11, 0x75, 0x0a, 0x38, 0x9e, 0x9f, 0x17, 0xd6, 0x4f, 0x96, - 0x4b, 0xcc, 0x65, 0x6d, 0xfe, 0xcb, 0x8e, 0x8e, 0xc1, 0x2e, 0x4f, 0x13, 0xc7, 0xd5, 0x7f, 0x54, 0x25, 0xc5, 0xc3, - 0xcf, 0x69, 0x0e, 0x28, 0x82, 0x99, 0x3d, 0xc5, 0xf8, 0xd8, 0x67, 0x99, 0x02, 0xfe, 0x76, 0xbd, 0xb5, 0x64, 0x62, - 0x97, 0xb4, 0x9b, 0x2b, 0xe3, 0x97, 0xda, 0xb0, 0xe3, 0xe0, 0xdc, 0x00, 0x14, 0x67, 0x8d, 0x0e, 0xcb, 0x6b, 0xdd, - 0xb6, 0x2a, 0x54, 0xa0, 0xd6, 0xff, 0xd9, 0x2d, 0x4c, 0x79, 0x9b, 0x97, 0xca, 0xdb, 0x3c, 0x34, 0x01, 0x02, 0x91, - 0x19, 0xf2, 0xac, 0xe9, 0x98, 0x24, 0xee, 0x1d, 0x29, 0x69, 0xdf, 0x91, 0xe2, 0x47, 0xef, 0x48, 0xc8, 0xb7, 0x84, - 0x8e, 0xec, 0x4b, 0x4e, 0x4e, 0xa0, 0xcc, 0x60, 0x2f, 0xaf, 0x99, 0xec, 0x1f, 0xd0, 0x5e, 0x38, 0x97, 0xe5, 0x15, - 0xbf, 0x16, 0xde, 0xda, 0x9f, 0xae, 0x4f, 0xbb, 0xaa, 0xde, 0x7e, 0x65, 0x66, 0x1e, 0x0e, 0xc5, 0xe1, 0x50, 0x99, - 0xa0, 0xdd, 0x05, 0x17, 0x83, 0x9c, 0xdd, 0xbb, 0xf1, 0xf1, 0xd7, 0x1c, 0x45, 0x6c, 0xa5, 0x3c, 0x92, 0x2e, 0x54, - 0x62, 0x78, 0x69, 0xe0, 0x61, 0x76, 0x7c, 0x3c, 0xd9, 0x5d, 0xdd, 0x4f, 0x06, 0x83, 0x9d, 0xea, 0xdb, 0x2d, 0xaf, - 0x67, 0xbb, 0x39, 0x7b, 0xe0, 0xb7, 0xd3, 0x6d, 0xb0, 0x6f, 0x60, 0xdb, 0xdd, 0x5d, 0x89, 0xc3, 0x61, 0xf7, 0x82, - 0x2f, 0xfc, 0xfd, 0x03, 0x02, 0x3a, 0xf3, 0xf3, 0x71, 0x1b, 0xe3, 0xe7, 0xa6, 0xed, 0xaa, 0xb5, 0x03, 0x78, 0xfa, - 0x1f, 0xbc, 0x9b, 0xd9, 0x72, 0xee, 0xb3, 0x27, 0xfc, 0x01, 0xfc, 0xf3, 0x71, 0x93, 0x44, 0xea, 0x13, 0xed, 0x32, - 0x79, 0x03, 0x0e, 0xe4, 0x3b, 0x9f, 0xbd, 0xe5, 0x0f, 0xb3, 0xe5, 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, 0x76, 0xc3, - 0x22, 0x3f, 0x80, 0x0f, 0xb2, 0x9d, 0x3f, 0x91, 0x35, 0xa5, 0xfb, 0xc5, 0x13, 0xff, 0x70, 0xa0, 0xbf, 0xde, 0xfa, - 0x87, 0xc3, 0x7b, 0xf6, 0x80, 0xe0, 0xe8, 0x7c, 0x07, 0xfd, 0xa3, 0x6f, 0x1d, 0x50, 0x95, 0xe1, 0xf5, 0x6c, 0x33, - 0xf7, 0x5f, 0xac, 0xd8, 0x1d, 0x70, 0xa1, 0x28, 0x2f, 0xb4, 0x1b, 0xf6, 0x80, 0x5e, 0x67, 0xe4, 0x44, 0x34, 0xdb, - 0xcd, 0x7d, 0x16, 0xe3, 0x73, 0x75, 0x5f, 0x4c, 0xbe, 0x7a, 0x5f, 0xdc, 0xb1, 0x6d, 0xf7, 0x7d, 0x51, 0xbe, 0xe9, - 0xae, 0x9f, 0x2d, 0xdb, 0xb1, 0x07, 0x98, 0x61, 0xd7, 0xfc, 0xa6, 0x39, 0x76, 0x8c, 0xfd, 0xea, 0x8d, 0x11, 0x40, - 0x99, 0x2d, 0x58, 0x2c, 0x38, 0x28, 0xd5, 0xaa, 0x6d, 0x49, 0xe4, 0x95, 0x0e, 0x54, 0x9b, 0x11, 0xdc, 0x57, 0x0b, - 0x39, 0xf3, 0xcc, 0x40, 0xdf, 0x56, 0x88, 0x16, 0x0e, 0x1b, 0xf0, 0x57, 0xda, 0x3a, 0xc6, 0x30, 0xcd, 0x6a, 0xa6, - 0x6d, 0x51, 0x97, 0xdf, 0xf6, 0x9e, 0xc9, 0x6f, 0x64, 0x60, 0x0b, 0x91, 0x14, 0x8e, 0xe3, 0x8b, 0xe7, 0x27, 0xfc, - 0x57, 0x2d, 0x8f, 0x5a, 0xed, 0x17, 0x4a, 0x7d, 0xfa, 0x8a, 0x8e, 0x68, 0xe2, 0x5e, 0xb4, 0x65, 0x58, 0xa3, 0xac, - 0xa9, 0xa5, 0xc3, 0x30, 0xae, 0x61, 0x5f, 0x1e, 0x38, 0xf4, 0x1d, 0x10, 0x68, 0xab, 0x54, 0x0a, 0xb4, 0x70, 0x0c, - 0xa3, 0x30, 0x0b, 0x29, 0x8f, 0x0b, 0xb3, 0x94, 0xf7, 0x58, 0xa0, 0xc5, 0xad, 0xba, 0xc7, 0xd4, 0x76, 0x0b, 0x22, - 0xac, 0xde, 0x32, 0xce, 0x2f, 0x1b, 0x55, 0xb8, 0x2d, 0x40, 0x51, 0x04, 0x65, 0xb0, 0x27, 0xb9, 0x6d, 0xa1, 0xa4, - 0xd9, 0x28, 0xac, 0xc5, 0x5d, 0x51, 0xee, 0x7a, 0x0d, 0x5b, 0xe0, 0x05, 0x55, 0x3f, 0x21, 0x6c, 0xcb, 0x9e, 0x75, - 0x28, 0x17, 0xe9, 0x7f, 0x64, 0xe9, 0xf9, 0x76, 0x6b, 0xce, 0xff, 0xf4, 0x15, 0x7d, 0x54, 0xfe, 0xe7, 0x97, 0xf4, - 0x93, 0xc1, 0x32, 0x72, 0x4a, 0x7d, 0x1f, 0x8d, 0x6e, 0xd3, 0x9c, 0x30, 0xb6, 0x7c, 0xfd, 0xf4, 0x1b, 0x64, 0x0a, - 0x92, 0x43, 0x29, 0x55, 0x39, 0xd9, 0x43, 0x5f, 0x78, 0xdd, 0x87, 0x99, 0x60, 0x00, 0xc2, 0x6b, 0xb4, 0xa9, 0x26, - 0x4c, 0xe2, 0xd1, 0x15, 0xfc, 0xdf, 0x08, 0x62, 0xd0, 0x3e, 0x51, 0xd4, 0xb1, 0x6d, 0xa4, 0xeb, 0xb6, 0x73, 0x90, - 0xdc, 0xa9, 0x2b, 0x7f, 0x54, 0x4e, 0xfe, 0x13, 0x0d, 0x91, 0x57, 0x5c, 0x21, 0x56, 0x16, 0x5c, 0x62, 0x31, 0x54, - 0xa4, 0x00, 0xd7, 0x10, 0x44, 0xca, 0xa2, 0xa4, 0x70, 0xcb, 0x41, 0x55, 0x04, 0x60, 0x5c, 0xad, 0x8e, 0x3a, 0x11, - 0x3e, 0x6e, 0xad, 0x45, 0x08, 0x56, 0x34, 0x6a, 0x65, 0xad, 0xc0, 0x17, 0xa4, 0x2f, 0x1d, 0x0a, 0x62, 0x7a, 0x14, - 0x52, 0x55, 0x3a, 0x14, 0x48, 0x73, 0xa8, 0xf8, 0xc6, 0x60, 0xa3, 0xa8, 0x48, 0xcf, 0x5f, 0x9a, 0x94, 0x5c, 0x1a, - 0x33, 0x3e, 0x88, 0x32, 0x12, 0x79, 0x1d, 0xde, 0x89, 0x69, 0x81, 0x7c, 0xa3, 0xc7, 0x0f, 0x82, 0x4b, 0x78, 0x37, - 0xe4, 0x5e, 0x01, 0xb6, 0x04, 0xec, 0x00, 0xf7, 0xca, 0x8c, 0x72, 0x9d, 0xd6, 0xf5, 0x5b, 0xeb, 0xa1, 0x18, 0x86, - 0xcf, 0x2c, 0x81, 0xed, 0x68, 0x1d, 0x1d, 0xe9, 0xe1, 0xc3, 0xff, 0xba, 0xaa, 0x39, 0xea, 0x54, 0x2e, 0x67, 0xc7, - 0x13, 0x96, 0x22, 0x66, 0xd0, 0xfd, 0x75, 0xfb, 0x4a, 0x00, 0xdd, 0x2e, 0x8b, 0x79, 0x36, 0xda, 0xc9, 0xbf, 0xa5, - 0x1b, 0x2b, 0x4a, 0x9b, 0x78, 0x97, 0xf5, 0xc6, 0xfe, 0x70, 0xf4, 0x97, 0x67, 0x5f, 0x26, 0x84, 0xaa, 0xb3, 0x61, - 0x6b, 0x1d, 0xe7, 0xf2, 0xbf, 0xfe, 0x3a, 0x26, 0x2b, 0x08, 0x0a, 0xc2, 0xb2, 0x53, 0x4c, 0x54, 0x30, 0x8a, 0x14, - 0x6b, 0x3e, 0x9e, 0xac, 0x51, 0x27, 0xbc, 0xf6, 0x97, 0x5a, 0x27, 0x4c, 0x8c, 0xac, 0x54, 0xfe, 0x9a, 0x55, 0xec, - 0x4e, 0x65, 0x16, 0x90, 0x79, 0x90, 0x4f, 0xd6, 0x46, 0x83, 0xb9, 0xe2, 0xf5, 0x6c, 0x3d, 0x97, 0xca, 0x67, 0x30, - 0xe5, 0x2c, 0x07, 0x27, 0x4b, 0x61, 0xf7, 0x24, 0x50, 0xb4, 0x66, 0xe8, 0xda, 0x9f, 0x62, 0xab, 0x5e, 0xa7, 0x55, - 0x0d, 0xf0, 0x80, 0x10, 0x03, 0x43, 0xed, 0xd5, 0xc2, 0x43, 0x6b, 0x01, 0xac, 0xfd, 0x51, 0xe9, 0x07, 0xe3, 0xc9, - 0x92, 0x2f, 0x90, 0x7f, 0x39, 0x72, 0xd4, 0xee, 0xfd, 0xbe, 0x77, 0x0f, 0x52, 0x70, 0xe4, 0x5a, 0x28, 0x90, 0x08, - 0x68, 0xc1, 0x37, 0xbe, 0xf2, 0xc1, 0xb8, 0x46, 0x6d, 0x35, 0x28, 0xa8, 0x1d, 0xdd, 0xf2, 0xd8, 0xd1, 0x3b, 0xdf, - 0x9f, 0xd0, 0x57, 0x2f, 0xb4, 0x70, 0xfc, 0x95, 0x33, 0x72, 0xcd, 0x56, 0x1d, 0x72, 0x44, 0x33, 0xe9, 0x10, 0x22, - 0x56, 0x6c, 0xcd, 0xae, 0x49, 0xe5, 0xdc, 0x39, 0x64, 0xa7, 0x8f, 0x50, 0xa5, 0xd7, 0x7a, 0x7c, 0x3b, 0x51, 0xba, - 0xdb, 0xe3, 0xdd, 0xe4, 0x5b, 0x36, 0x11, 0x31, 0x18, 0xd0, 0x06, 0xe1, 0x8c, 0xac, 0x43, 0xa4, 0xd2, 0x01, 0x42, - 0xe0, 0x98, 0x80, 0xa6, 0xff, 0xf8, 0x9a, 0x44, 0x01, 0x47, 0xda, 0x08, 0x59, 0xcb, 0x0e, 0x87, 0x1c, 0x34, 0xca, - 0xcd, 0x1f, 0x5e, 0xa1, 0x4e, 0x73, 0x60, 0x9e, 0x2e, 0x61, 0xcf, 0xc1, 0x23, 0xbd, 0x38, 0x3e, 0xd2, 0xff, 0x3b, - 0x9a, 0xa8, 0xf1, 0x7f, 0xae, 0x89, 0x52, 0x5a, 0x24, 0x47, 0xb5, 0xf4, 0x4d, 0xea, 0x28, 0xb8, 0xc8, 0x3b, 0x6a, - 0x21, 0x7b, 0x96, 0x8d, 0x1b, 0xd5, 0xbc, 0xff, 0x5f, 0x2b, 0xf3, 0xff, 0x35, 0xad, 0x0c, 0x53, 0xb2, 0x63, 0xa9, - 0x66, 0x1e, 0x68, 0x15, 0xc3, 0xec, 0x67, 0x92, 0x10, 0x19, 0x2e, 0x0d, 0xf8, 0x51, 0x05, 0xfb, 0x38, 0xad, 0xd6, - 0x59, 0xb8, 0x43, 0x25, 0xea, 0xad, 0xb8, 0x4b, 0xf3, 0x97, 0xf5, 0xbf, 0x45, 0x59, 0xc0, 0xd4, 0xbe, 0x2b, 0xd3, - 0x38, 0x20, 0x0b, 0x7f, 0x16, 0x96, 0x38, 0xb9, 0xb1, 0x8d, 0x3f, 0xcb, 0xf1, 0xb4, 0x5f, 0x75, 0x66, 0x1e, 0x48, - 0xa0, 0x06, 0xe2, 0x8f, 0x9c, 0xcb, 0xca, 0xe2, 0x01, 0xa1, 0x9b, 0x7f, 0x28, 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, 0xa7, 0xb1, 0x88, 0x47, 0x3d, 0x45, 0xc9, 0xf2, 0x26, 0x77, 0xe5, 0x5c, 0x7f, - 0xff, 0x07, 0x05, 0xb0, 0x1b, 0x30, 0xdb, 0x16, 0xd8, 0x01, 0x40, 0x82, 0x02, 0xd9, 0x42, 0x9d, 0x46, 0x67, 0x6a, - 0xa9, 0xc0, 0x7b, 0xae, 0x07, 0xf8, 0x9b, 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, 0xb7, 0x53, 0x45, 0x1e, 0x1f, 0xa5, 0x21, 0xaf, - 0xc0, 0x93, 0x8c, 0x23, 0x49, 0x94, 0x08, 0xde, 0xe4, 0x8d, 0x19, 0x87, 0x97, 0x6d, 0xca, 0xa9, 0xbd, 0x59, 0x2f, - 0x00, 0xe7, 0x09, 0xda, 0x32, 0xc0, 0x58, 0xc0, 0xe0, 0x5c, 0x88, 0x25, 0x4f, 0x11, 0xfc, 0xd2, 0x89, 0x14, 0xc6, - 0x5d, 0x0e, 0xc3, 0x3c, 0x28, 0x7a, 0x97, 0xd4, 0x1f, 0xfd, 0x3e, 0x6a, 0x93, 0xc1, 0x10, 0x54, 0x02, 0xa8, 0xac, - 0x1b, 0x24, 0x06, 0x56, 0xa5, 0x85, 0xc4, 0x25, 0xc4, 0xcb, 0x7c, 0x35, 0xad, 0xa3, 0xe0, 0x7d, 0x3d, 0x21, 0x84, - 0x13, 0x8c, 0x0f, 0x71, 0x03, 0x04, 0x0c, 0x56, 0x71, 0x81, 0x41, 0xf2, 0x5c, 0xa2, 0xfb, 0xe3, 0xf9, 0x8e, 0x01, - 0xae, 0x9c, 0xf7, 0x54, 0xbb, 0x7a, 0x60, 0x2f, 0x57, 0xe9, 0x92, 0x11, 0xc2, 0x8a, 0xff, 0x8b, 0xc8, 0xfb, 0x76, - 0x98, 0x80, 0xda, 0x46, 0xfe, 0x18, 0x24, 0xe6, 0x32, 0x51, 0x04, 0xf1, 0x28, 0x2b, 0x58, 0x92, 0x06, 0x9b, 0x51, - 0x92, 0x82, 0x46, 0x13, 0x63, 0xc8, 0x54, 0x68, 0x87, 0xa4, 0xd1, 0x6c, 0x4c, 0xf6, 0x31, 0xe4, 0x35, 0x5c, 0x2c, - 0x16, 0x78, 0xdf, 0xcf, 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, 0xcb, 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, 0x86, 0xd2, 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, 0xb3, 0xac, 0xc9, 0x5c, 0xbc, 0x2e, 0x1e, 0xbc, - 0x82, 0x3d, 0xf7, 0x07, 0xfa, 0x57, 0xc9, 0x9e, 0xfb, 0x36, 0x93, 0xeb, 0x9f, 0x69, 0xd7, 0x68, 0xcc, 0x74, 0xbc, - 0x76, 0x05, 0x56, 0x68, 0x80, 0xfc, 0x82, 0x1d, 0xed, 0x6d, 0x0e, 0x02, 0x01, 0xba, 0x97, 0xe0, 0x28, 0x0a, 0x88, - 0x9a, 0x56, 0x95, 0x47, 0xa7, 0x7b, 0x7f, 0x8f, 0x6f, 0x94, 0x80, 0x4d, 0x9e, 0x5a, 0xf7, 0x96, 0xb1, 0x7f, 0x38, - 0x40, 0x08, 0xbd, 0x9c, 0x7e, 0xa3, 0x2d, 0xab, 0x47, 0x3b, 0x96, 0xfb, 0x86, 0x51, 0x4f, 0xc1, 0x18, 0x86, 0x2e, - 0xac, 0x62, 0x24, 0xcf, 0x80, 0xac, 0xf1, 0x1b, 0x44, 0x17, 0xb0, 0xe8, 0xf5, 0x5e, 0x1f, 0xd1, 0x20, 0x02, 0x2a, - 0xbd, 0xe6, 0x2f, 0x45, 0x3e, 0x57, 0x85, 0xe8, 0xbd, 0xb7, 0x76, 0xde, 0xcc, 0x48, 0x96, 0x49, 0x23, 0xd5, 0x6e, - 0x65, 0xb1, 0xae, 0xbc, 0xd9, 0x09, 0xe9, 0x62, 0x8e, 0xa1, 0x32, 0x78, 0x1c, 0x80, 0xd2, 0xf3, 0x6f, 0xa1, 0x57, - 0x32, 0x64, 0x9a, 0x25, 0x9a, 0xd9, 0x5d, 0xe3, 0x4f, 0x56, 0xa9, 0x17, 0x23, 0x62, 0x36, 0xb0, 0x85, 0xb8, 0x2d, - 0x2a, 0xdd, 0x16, 0x85, 0xb2, 0x45, 0x91, 0x3e, 0xd4, 0xce, 0x74, 0x67, 0x16, 0x3e, 0xab, 0x4c, 0xfb, 0xde, 0x66, - 0x66, 0x6c, 0x80, 0xb6, 0x8b, 0xf0, 0x0d, 0x74, 0xa0, 0x42, 0xc8, 0x7f, 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, 0x5f, 0x53, - 0xb7, 0x67, 0xe5, 0x64, 0x2f, 0x3a, 0x27, 0xfb, 0x74, 0x36, 0x0f, 0x04, 0x97, 0x3b, 0xf7, 0x79, 0x3e, 0xd5, 0xd3, - 0xae, 0xf2, 0x83, 0xd6, 0x10, 0x99, 0x2f, 0x7c, 0xaa, 0xba, 0xd7, 0x15, 0x2c, 0x60, 0x09, 0xee, 0xd6, 0x4b, 0xf3, - 0x5f, 0xb1, 0xfb, 0x7b, 0x41, 0x2f, 0xcd, 0x7f, 0xa3, 0x3f, 0x29, 0x80, 0x03, 0xd0, 0x98, 0xda, 0x2d, 0xf0, 0x10, - 0x43, 0x05, 0x85, 0xbb, 0x59, 0x39, 0xf7, 0x6a, 0x80, 0xc3, 0x24, 0x7d, 0x43, 0xab, 0x57, 0x5a, 0xec, 0x7a, 0x99, - 0xec, 0x15, 0xe0, 0xa1, 0x0a, 0x79, 0x78, 0x38, 0x44, 0x1d, 0xc3, 0x0e, 0xea, 0x08, 0x18, 0xf6, 0x10, 0x1a, 0x5b, - 0xe0, 0xf9, 0xf8, 0x29, 0xe3, 0x7b, 0x01, 0x6a, 0x23, 0x84, 0xc7, 0xab, 0x45, 0x19, 0x62, 0xcb, 0xde, 0x22, 0x95, - 0xd4, 0xcf, 0x02, 0x51, 0x46, 0xab, 0x80, 0xb6, 0xda, 0x63, 0x96, 0xc6, 0x1b, 0x08, 0x15, 0x4b, 0x7d, 0x0c, 0xa1, - 0x81, 0xc3, 0xef, 0x70, 0x00, 0x09, 0xbe, 0xe4, 0x9a, 0x6c, 0xee, 0x6d, 0x7e, 0x4f, 0xfb, 0xfc, 0xe1, 0x70, 0x7e, - 0x89, 0xa0, 0x74, 0x29, 0x7c, 0xa4, 0x12, 0x51, 0x3d, 0xc5, 0x4d, 0x09, 0xd9, 0x2c, 0x59, 0xe9, 0x07, 0xbf, 0xaa, - 0x5f, 0x00, 0x20, 0x0b, 0x81, 0x36, 0x91, 0xd9, 0x9f, 0xce, 0x54, 0x74, 0x01, 0x70, 0x88, 0x3f, 0x7e, 0x82, 0xe8, - 0x1b, 0x5a, 0xa6, 0xe5, 0xe3, 0x84, 0x87, 0xa0, 0xb5, 0x25, 0x9d, 0x44, 0xac, 0x14, 0xd8, 0x10, 0x09, 0xdf, 0xef, - 0x9f, 0xc7, 0x92, 0x0e, 0x34, 0x6a, 0x75, 0x6f, 0xdc, 0xea, 0x5e, 0xf9, 0xba, 0xee, 0xe4, 0xc6, 0x07, 0x45, 0xfb, - 0x6c, 0xde, 0xa8, 0x7c, 0xdf, 0xd6, 0x39, 0xbb, 0xd3, 0xbd, 0x23, 0xe7, 0xc4, 0xb7, 0xf7, 0x10, 0x8a, 0x1e, 0x9a, - 0x22, 0xcb, 0x92, 0x30, 0xa0, 0xb5, 0x76, 0xed, 0x59, 0x46, 0x07, 0xaf, 0x7d, 0x43, 0x88, 0xc8, 0x53, 0x7c, 0x12, - 0x72, 0x8b, 0xe3, 0x83, 0x02, 0xfd, 0x33, 0xe3, 0xcf, 0x9c, 0xf8, 0x61, 0xab, 0x5f, 0x00, 0xe7, 0xa6, 0x7b, 0xef, - 0x4e, 0xcc, 0x7a, 0x0c, 0xa5, 0x6c, 0xfc, 0xdf, 0xef, 0x13, 0x59, 0xa0, 0xd3, 0x11, 0x0d, 0x03, 0xc1, 0x5d, 0x54, - 0xff, 0xf7, 0x8a, 0xd7, 0x3d, 0x6b, 0x75, 0xbe, 0xfc, 0xd4, 0xe9, 0x49, 0xaf, 0x5e, 0xc6, 0x3d, 0xa0, 0x42, 0x07, - 0x08, 0xe7, 0x75, 0xbf, 0x61, 0xbb, 0x6f, 0x7e, 0x79, 0x77, 0xf4, 0x32, 0xb0, 0x49, 0x91, 0xd8, 0x56, 0xf2, 0x59, - 0x0f, 0x14, 0x7e, 0x3d, 0xd6, 0xab, 0x8b, 0x75, 0x8f, 0xf5, 0x50, 0x0b, 0x88, 0x1e, 0x16, 0xa0, 0xfe, 0xeb, 0xd9, - 0xa7, 0xa1, 0x70, 0x90, 0x8d, 0x53, 0x05, 0x8a, 0x2c, 0xf8, 0x0b, 0x31, 0x5a, 0x17, 0x04, 0x88, 0x6c, 0x09, 0x69, - 0xd5, 0xc9, 0xec, 0x71, 0xa9, 0x25, 0x19, 0x7c, 0x13, 0x90, 0xd9, 0x81, 0x95, 0x13, 0x94, 0x8e, 0x5b, 0x03, 0xae, - 0x6c, 0xf1, 0x68, 0xb7, 0x3f, 0x0d, 0xb2, 0xb3, 0xe6, 0xa4, 0xd1, 0x3e, 0xec, 0xd3, 0x3c, 0x40, 0x20, 0x92, 0xa9, - 0x08, 0x72, 0xcd, 0xbd, 0x25, 0x7d, 0x74, 0x38, 0xe7, 0x85, 0xfc, 0x73, 0x2a, 0x75, 0x88, 0x43, 0x89, 0x35, 0x10, - 0xa8, 0x3c, 0x43, 0x95, 0xc3, 0x06, 0x39, 0xfe, 0xd9, 0x91, 0xcc, 0x24, 0x26, 0x8b, 0xdc, 0xad, 0x99, 0x0a, 0x3f, - 0x10, 0x7c, 0xcc, 0x72, 0x0e, 0x5c, 0x60, 0xb3, 0xb9, 0xaf, 0xa6, 0xb8, 0xb8, 0x02, 0x7f, 0x4c, 0xe1, 0x57, 0x3c, - 0x85, 0x9d, 0x76, 0xbf, 0x2e, 0xaa, 0x14, 0x75, 0x1b, 0x85, 0x45, 0x25, 0x0b, 0xa6, 0x35, 0xa4, 0x89, 0x0e, 0xa3, - 0x3f, 0xc8, 0x19, 0x28, 0x08, 0xf9, 0x65, 0xd3, 0x00, 0x23, 0x95, 0x5c, 0x1e, 0x54, 0x49, 0xe0, 0x05, 0xd8, 0x06, - 0x15, 0x5b, 0x17, 0x10, 0x64, 0x9b, 0x14, 0x65, 0xfa, 0xa5, 0xc8, 0xeb, 0x30, 0x0b, 0xaa, 0x51, 0x5a, 0xfd, 0xa8, - 0x7f, 0x02, 0xf3, 0x36, 0x15, 0xa3, 0x5a, 0xc5, 0xe4, 0x37, 0xfa, 0xfd, 0x62, 0xd0, 0xfa, 0x90, 0xc1, 0x47, 0xaf, - 0x4d, 0x83, 0x3f, 0x3a, 0x0d, 0x76, 0x98, 0x68, 0x04, 0x40, 0x32, 0xa7, 0x96, 0x3c, 0x14, 0xfd, 0x11, 0xe4, 0x58, - 0xa3, 0xca, 0x29, 0x18, 0xac, 0xff, 0x78, 0xb4, 0x03, 0x53, 0x2f, 0x8e, 0xb6, 0x64, 0x07, 0xad, 0x7c, 0x03, 0xdc, - 0xaf, 0x91, 0x2d, 0x66, 0x39, 0x40, 0xb3, 0xd7, 0x88, 0x8c, 0x4f, 0x5e, 0x00, 0x63, 0xb6, 0xce, 0xc2, 0x48, 0xc4, - 0xc1, 0x58, 0x35, 0x66, 0xcc, 0xc0, 0xc0, 0x05, 0xba, 0x96, 0x49, 0x49, 0x1a, 0xd2, 0xc1, 0x80, 0x95, 0xb2, 0x85, - 0x03, 0x5e, 0x34, 0xc7, 0xed, 0x78, 0xd3, 0xa2, 0xf1, 0xc0, 0x76, 0xb1, 0xfd, 0xfd, 0xf7, 0xc5, 0xf6, 0x3a, 0xdc, - 0x92, 0x5e, 0x21, 0x67, 0x09, 0xfd, 0xfc, 0x51, 0xf6, 0x59, 0xc3, 0xc9, 0xa9, 0xd0, 0x0c, 0x2d, 0x45, 0x42, 0x29, - 0xde, 0xe9, 0x49, 0x81, 0xb1, 0x8c, 0x85, 0xbf, 0x07, 0xce, 0xe9, 0x42, 0x11, 0xb9, 0x03, 0xc7, 0xf1, 0x0d, 0x54, - 0x30, 0x6a, 0x38, 0x78, 0x19, 0xc3, 0xb6, 0x28, 0x66, 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, - 0xe5, 0x41, 0x04, 0x90, 0xcf, 0xe1, 0x7d, 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, 0x8b, 0x33, 0xd8, 0x38, - 0xd7, 0x99, 0xe0, 0xc0, 0x8b, 0xa4, 0xd6, 0x6b, 0xc6, 0x5f, 0x64, 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, 0xfe, 0x5c, 0x49, 0x1c, 0x5a, 0x16, 0xc9, 0xbf, 0x77, 0x3d, - 0x7d, 0x85, 0xd4, 0x9d, 0x2c, 0x90, 0x19, 0xe3, 0x65, 0x1e, 0x7f, 0x02, 0xc2, 0x6c, 0xd0, 0x46, 0x45, 0x21, 0x84, - 0x6c, 0x10, 0x83, 0xc6, 0xcb, 0x3c, 0xfe, 0x5e, 0xd1, 0x78, 0xc8, 0x47, 0x91, 0xaf, 0xfe, 0x2a, 0xf5, 0x5f, 0xa1, - 0xcf, 0x4c, 0xf0, 0x08, 0xd5, 0x44, 0xff, 0xee, 0xf9, 0xec, 0x1e, 0xd4, 0x86, 0x51, 0x98, 0x99, 0xf2, 0x2b, 0xdf, - 0x14, 0x67, 0xaf, 0xbf, 0xa2, 0xab, 0x6c, 0xeb, 0x7e, 0xf4, 0xf1, 0x88, 0xc0, 0xda, 0x18, 0x5d, 0x71, 0x63, 0x00, - 0x39, 0x4c, 0xde, 0xaf, 0x28, 0x2d, 0x87, 0x34, 0x08, 0x1d, 0x34, 0x04, 0xbd, 0x92, 0xe8, 0x03, 0x89, 0x45, 0x8c, - 0xe1, 0x85, 0x78, 0x46, 0x6a, 0x32, 0xd1, 0x10, 0xaf, 0x88, 0xfd, 0x10, 0x2d, 0x39, 0x35, 0xd1, 0x8d, 0x30, 0xc5, - 0x40, 0x62, 0x67, 0x90, 0x9c, 0x24, 0xb5, 0xf2, 0x8b, 0x67, 0x92, 0xb0, 0xc4, 0xce, 0x43, 0x0c, 0x26, 0xb5, 0x74, - 0xa7, 0x37, 0x55, 0x7a, 0x77, 0xa4, 0xe5, 0xa0, 0x7d, 0x00, 0x76, 0x29, 0xe9, 0xfd, 0x93, 0x42, 0x11, 0x1f, 0xc2, - 0x38, 0x86, 0xf0, 0x2d, 0xa2, 0xba, 0x02, 0xe7, 0x5a, 0x81, 0xc6, 0x6a, 0xe0, 0xa1, 0x99, 0x55, 0xf3, 0x21, 0xa7, - 0x9f, 0x4a, 0xcb, 0x1f, 0x23, 0x1a, 0x1b, 0xad, 0x9b, 0xc3, 0x61, 0x4f, 0xab, 0x5e, 0x3a, 0x07, 0x5d, 0x36, 0x93, - 0x98, 0xb8, 0x81, 0x74, 0xfd, 0xe8, 0x37, 0x13, 0xf6, 0x22, 0x2a, 0xe4, 0x52, 0x08, 0x0a, 0x5a, 0x1d, 0x08, 0x1c, - 0x0a, 0x6f, 0x51, 0xe6, 0x8b, 0x98, 0x36, 0x10, 0x06, 0x9f, 0x1f, 0xc8, 0xcf, 0x37, 0x05, 0xa9, 0xd8, 0xb1, 0xae, - 0xfd, 0xfe, 0xa6, 0xf4, 0x00, 0x4f, 0xce, 0x24, 0x79, 0xda, 0x0c, 0x61, 0x45, 0x00, 0x8d, 0x59, 0x4d, 0x16, 0x27, - 0x5c, 0x99, 0xc3, 0x8f, 0x95, 0x57, 0xb2, 0x94, 0xa9, 0xf3, 0x54, 0x2f, 0x80, 0xa8, 0xe3, 0x0d, 0x5a, 0x91, 0xfa, - 0x15, 0x3a, 0x7b, 0xcd, 0x4a, 0xc8, 0x78, 0x78, 0xce, 0x79, 0x3a, 0x7a, 0x60, 0x09, 0x8f, 0xf0, 0xaf, 0x64, 0xa2, - 0x0f, 0xbf, 0x07, 0x0e, 0x37, 0xe3, 0x84, 0x47, 0x6e, 0xb3, 0xf7, 0x55, 0xb8, 0x82, 0x9b, 0x69, 0x01, 0x48, 0x6e, - 0x41, 0xd2, 0x04, 0x94, 0x90, 0xc8, 0x84, 0xcc, 0x9a, 0x92, 0x9f, 0x5b, 0xda, 0x06, 0x6b, 0x98, 0x74, 0x1e, 0xf0, - 0xa2, 0xd5, 0x47, 0xab, 0x89, 0x76, 0x99, 0xe5, 0xf3, 0x21, 0xce, 0x50, 0xcd, 0x71, 0x77, 0x06, 0x3f, 0x07, 0xbc, - 0x62, 0x55, 0x93, 0x8e, 0x76, 0x03, 0x2e, 0x3c, 0xb9, 0xce, 0xd3, 0xd1, 0x16, 0x7f, 0xc9, 0xfd, 0x01, 0xa0, 0x83, - 0xa9, 0x4b, 0xe0, 0x4f, 0xd5, 0x56, 0x53, 0xa9, 0x5f, 0x5a, 0xfb, 0x75, 0xdd, 0x59, 0xad, 0xdc, 0xb3, 0x2e, 0x43, - 0x7b, 0x64, 0xc8, 0x19, 0x33, 0xe0, 0xcf, 0x19, 0x4b, 0xfe, 0x9c, 0xb1, 0xe2, 0xcf, 0x19, 0x37, 0x46, 0x06, 0x50, - 0x82, 0x7b, 0xc9, 0x5f, 0xec, 0x11, 0x33, 0xc4, 0x6a, 0x50, 0x09, 0xac, 0x2c, 0xe5, 0xdc, 0x47, 0x4e, 0x31, 0xe5, - 0x94, 0xe1, 0xa5, 0xd3, 0x99, 0x3b, 0x90, 0xf3, 0x60, 0xe6, 0x0e, 0x93, 0xb3, 0x3e, 0xc5, 0xb1, 0x34, 0x26, 0x45, + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xcc, 0xbd, 0x6d, 0x7b, 0xdb, 0xb6, 0xb2, 0x28, 0xfa, + 0xf9, 0x9e, 0x5f, 0x61, 0x73, 0xa7, 0x2e, 0x61, 0x41, 0xb4, 0x24, 0x5b, 0x8e, 0x43, 0x19, 0xd6, 0x71, 0x9c, 0xa4, + 0x49, 0x9b, 0x26, 0x69, 0x9c, 0x26, 0x4d, 0x54, 0x6d, 0x07, 0x22, 0x21, 0x09, 0x0d, 0x45, 0xa8, 0x04, 0x14, 0xdb, + 0x95, 0xf4, 0xdf, 0xef, 0x33, 0x78, 0x21, 0x41, 0x49, 0xc9, 0x5a, 0xeb, 0xdc, 0x73, 0xee, 0x73, 0x76, 0xf7, 0x8a, + 0x45, 0xbc, 0x63, 0x30, 0x18, 0xcc, 0x0c, 0x66, 0x06, 0xe7, 0xfb, 0xa9, 0x48, 0xd4, 0xfd, 0x9c, 0xed, 0x4d, 0xd5, + 0x2c, 0xbb, 0x38, 0xb7, 0xff, 0x32, 0x9a, 0x5e, 0x9c, 0x67, 0x3c, 0xff, 0xb2, 0x57, 0xb0, 0x8c, 0xf0, 0x44, 0xe4, + 0x7b, 0xd3, 0x82, 0x8d, 0x49, 0x4a, 0x15, 0x8d, 0xf9, 0x8c, 0x4e, 0xd8, 0xde, 0xd1, 0xc5, 0xf9, 0x8c, 0x29, 0xba, + 0x97, 0x4c, 0x69, 0x21, 0x99, 0x22, 0xbf, 0xbf, 0x7b, 0xd6, 0x3c, 0xbb, 0x38, 0x97, 0x49, 0xc1, 0xe7, 0x6a, 0x0f, + 0x9a, 0x24, 0x33, 0x91, 0x2e, 0x32, 0x76, 0x71, 0x74, 0x74, 0x7b, 0x7b, 0x1b, 0xfd, 0x25, 0xff, 0xc7, 0x57, 0x5a, + 0xec, 0xfd, 0x52, 0x90, 0xd7, 0xa3, 0xbf, 0x58, 0xa2, 0xa2, 0x94, 0x8d, 0x79, 0xce, 0xde, 0x14, 0x62, 0xce, 0x0a, + 0x75, 0xdf, 0x83, 0xcc, 0x9f, 0x0a, 0x12, 0x72, 0xac, 0x30, 0x43, 0xe4, 0x42, 0xed, 0xf1, 0x7c, 0x8f, 0xf7, 0x7f, + 0x29, 0x74, 0xca, 0x92, 0xe5, 0x8b, 0x19, 0x2b, 0xe8, 0x28, 0x63, 0xf1, 0x7e, 0x0b, 0x27, 0x22, 0x1f, 0xf3, 0xc9, + 0xa2, 0xfc, 0xbe, 0x2d, 0xb8, 0x72, 0xbf, 0xbf, 0xd2, 0x6c, 0xc1, 0x62, 0xb6, 0x46, 0x31, 0x1f, 0xa8, 0x21, 0x61, + 0xba, 0xe5, 0x2f, 0x55, 0xc3, 0xe1, 0x4f, 0xba, 0xc9, 0xfb, 0x39, 0x13, 0xe3, 0x3d, 0xb5, 0x4f, 0x02, 0x79, 0x3f, + 0x1b, 0x89, 0x2c, 0xe8, 0xab, 0x46, 0x10, 0xc4, 0x50, 0x06, 0x33, 0xd4, 0x4b, 0x44, 0x2e, 0xd5, 0x9e, 0xe4, 0xe4, + 0x96, 0xe7, 0xa9, 0xb8, 0xc5, 0x5f, 0x25, 0x91, 0x3c, 0xba, 0x9e, 0xd2, 0x54, 0xdc, 0xbe, 0x15, 0x42, 0x1d, 0x1c, + 0x84, 0xf6, 0xfb, 0xfe, 0xea, 0xfa, 0x9a, 0x10, 0xf2, 0x55, 0xf0, 0x74, 0xaf, 0xb5, 0x5a, 0x79, 0xa9, 0x51, 0x4e, + 0x15, 0xff, 0xca, 0x4c, 0x25, 0x74, 0x70, 0x10, 0xd0, 0x54, 0xcc, 0x15, 0x4b, 0xaf, 0xd5, 0x7d, 0xc6, 0xae, 0xa7, + 0x8c, 0x29, 0x19, 0xf0, 0x7c, 0xef, 0x89, 0x48, 0x16, 0x33, 0x96, 0xab, 0x68, 0x5e, 0x08, 0x25, 0x60, 0x60, 0x07, + 0x07, 0x41, 0xc1, 0xe6, 0x19, 0x4d, 0x18, 0xe4, 0x5f, 0x5d, 0x5f, 0x57, 0x35, 0xaa, 0x42, 0xf8, 0x56, 0x92, 0x6b, + 0x3d, 0xf4, 0x10, 0xe1, 0xe7, 0x92, 0xe4, 0xec, 0x76, 0xef, 0x03, 0xa3, 0x5f, 0x7e, 0xa5, 0xf3, 0x5e, 0x92, 0x51, + 0x29, 0xf7, 0x9e, 0x89, 0xa5, 0x9e, 0x46, 0xb1, 0x48, 0x94, 0x28, 0x42, 0x85, 0x19, 0x96, 0x68, 0xc9, 0xc7, 0xa1, + 0x9a, 0x72, 0x19, 0xdd, 0x3c, 0x48, 0xa4, 0x7c, 0xcb, 0xe4, 0x22, 0x53, 0x0f, 0xc8, 0x7e, 0x0b, 0xcb, 0x7d, 0x42, + 0x6e, 0x25, 0x52, 0xd3, 0x42, 0xdc, 0xee, 0x3d, 0x2d, 0x0a, 0x51, 0x84, 0xc1, 0xd5, 0xf5, 0xb5, 0x29, 0xb1, 0xc7, + 0xe5, 0x5e, 0x2e, 0xd4, 0x5e, 0xd9, 0x1e, 0x40, 0x3b, 0xda, 0xfb, 0x5d, 0xb2, 0xbd, 0xcf, 0x8b, 0x5c, 0xd2, 0x31, + 0xbb, 0xba, 0xbe, 0xfe, 0xbc, 0x27, 0x8a, 0xbd, 0xcf, 0x89, 0x94, 0x9f, 0xf7, 0x78, 0x2e, 0x15, 0xa3, 0x69, 0x14, + 0xa0, 0x9e, 0xee, 0x2c, 0x91, 0xf2, 0x1d, 0xbb, 0x53, 0x44, 0x61, 0xfd, 0xa9, 0x08, 0x5b, 0x4f, 0x98, 0xda, 0x93, + 0xe5, 0xbc, 0x42, 0xb4, 0xcc, 0x98, 0xda, 0x53, 0x44, 0xe7, 0x0b, 0x0b, 0x7f, 0x66, 0x3e, 0x55, 0x8f, 0x8f, 0xc3, + 0xaf, 0xf2, 0xe0, 0x40, 0x95, 0x80, 0x46, 0x4b, 0xbb, 0x42, 0x84, 0xed, 0xbb, 0xb4, 0x83, 0x03, 0x16, 0x65, 0x2c, + 0x9f, 0xa8, 0x29, 0x21, 0xa4, 0xdd, 0x93, 0x07, 0x07, 0xa1, 0x22, 0xcf, 0x65, 0x34, 0x61, 0x2a, 0x64, 0x08, 0xe1, + 0xaa, 0xf6, 0xc1, 0x41, 0x68, 0x80, 0x20, 0x88, 0xd2, 0x80, 0xab, 0xc1, 0x18, 0x45, 0x16, 0xfa, 0xd7, 0xf7, 0x79, + 0x12, 0xfa, 0xe3, 0x47, 0x58, 0x1e, 0x1c, 0x3c, 0x97, 0x91, 0x84, 0x16, 0xb1, 0x42, 0x68, 0x5d, 0x30, 0xb5, 0x28, + 0xf2, 0x3d, 0xb5, 0x56, 0xe2, 0x5a, 0x15, 0x3c, 0x9f, 0x84, 0x68, 0xe9, 0xd2, 0xbc, 0x8a, 0xeb, 0xb5, 0x19, 0xee, + 0x6f, 0x05, 0xe1, 0xe4, 0x02, 0x7a, 0x7c, 0x26, 0x42, 0x8b, 0x83, 0x9c, 0x90, 0x40, 0xea, 0xba, 0x41, 0x9f, 0xc7, + 0xbc, 0x11, 0x04, 0xd8, 0x8c, 0x12, 0xdf, 0x4a, 0x84, 0xb9, 0x02, 0xd4, 0x8d, 0xa2, 0x48, 0x21, 0x72, 0xb1, 0x74, + 0x60, 0xe1, 0xde, 0x44, 0xfb, 0x7c, 0xd0, 0x1a, 0xc6, 0x2a, 0x2a, 0x58, 0xba, 0x48, 0x58, 0x18, 0x4a, 0x9c, 0x63, + 0x81, 0xc8, 0x85, 0x6c, 0x84, 0x05, 0xb9, 0x80, 0xf5, 0x2e, 0xea, 0x8b, 0x4d, 0xc8, 0x7e, 0x0b, 0xd9, 0x41, 0x16, + 0x6e, 0x84, 0x00, 0x62, 0x3b, 0xa0, 0x82, 0x90, 0x20, 0x5f, 0xcc, 0x46, 0xac, 0x08, 0xca, 0x62, 0xbd, 0x1a, 0x5e, + 0x2c, 0x24, 0xdb, 0x4b, 0xa4, 0xdc, 0x1b, 0x2f, 0xf2, 0x44, 0x71, 0x91, 0xef, 0x05, 0x8d, 0xa2, 0x11, 0x18, 0x7c, + 0x28, 0xd1, 0x21, 0x40, 0x6b, 0x14, 0xe6, 0xa8, 0xc1, 0x07, 0xa2, 0xd1, 0x1e, 0x62, 0x18, 0x25, 0xea, 0xd9, 0xf6, + 0x2c, 0x04, 0x18, 0xe6, 0x30, 0xc9, 0x35, 0xfe, 0x64, 0x76, 0x3e, 0x4c, 0xf1, 0xab, 0xec, 0xf3, 0x68, 0x7b, 0xa7, + 0x10, 0x15, 0xcd, 0xe8, 0x3c, 0x64, 0xe4, 0x82, 0x69, 0xec, 0xa2, 0x79, 0x02, 0x63, 0xad, 0x2d, 0x5c, 0x9f, 0xc5, + 0x2c, 0xaa, 0x70, 0x0a, 0xc5, 0x2a, 0x1a, 0x8b, 0xe2, 0x29, 0x4d, 0xa6, 0x50, 0xaf, 0xc4, 0x98, 0xd4, 0x6d, 0xb8, + 0xa4, 0x60, 0x54, 0xb1, 0xa7, 0x19, 0x83, 0xaf, 0x30, 0xd0, 0x35, 0x03, 0x84, 0x73, 0xd8, 0xea, 0x19, 0x57, 0xaf, + 0x44, 0x9e, 0xb0, 0x5e, 0xee, 0xe1, 0x97, 0x5e, 0xf9, 0x4b, 0xa5, 0x0a, 0x3e, 0x5a, 0x28, 0x16, 0x06, 0x39, 0x94, + 0x08, 0x70, 0x8e, 0xb0, 0x8c, 0x14, 0xbb, 0x53, 0x57, 0x22, 0x57, 0x2c, 0x57, 0x84, 0x39, 0xa8, 0x62, 0x1e, 0xd1, + 0xf9, 0x9c, 0xe5, 0xe9, 0xd5, 0x94, 0x67, 0x69, 0x28, 0xd1, 0x1a, 0xad, 0xf1, 0x07, 0x49, 0x60, 0x92, 0xe4, 0x82, + 0xc7, 0xf0, 0xcf, 0xb7, 0xa7, 0x13, 0x2a, 0x72, 0xa1, 0xb7, 0x05, 0x23, 0x41, 0xd0, 0x1b, 0x8b, 0x22, 0xb4, 0x53, + 0xd8, 0x03, 0xd2, 0x05, 0x7d, 0xbc, 0x5d, 0x64, 0x4c, 0x22, 0xd6, 0x20, 0x25, 0xa6, 0x39, 0x08, 0xff, 0x56, 0x84, + 0x0c, 0x16, 0x80, 0xa3, 0x98, 0x6b, 0x12, 0xf8, 0x92, 0xdb, 0x4d, 0x95, 0x96, 0x44, 0xed, 0x77, 0x49, 0x52, 0x1e, + 0xa9, 0x62, 0x21, 0x15, 0x4b, 0xdf, 0xdd, 0xcf, 0x99, 0xc4, 0x3f, 0x17, 0xe4, 0x77, 0xd9, 0xff, 0x5d, 0x46, 0x6c, + 0x36, 0x57, 0xf7, 0xd7, 0x9a, 0x9a, 0xc7, 0x41, 0x80, 0x3f, 0xea, 0xa2, 0x05, 0xa3, 0x09, 0x90, 0x34, 0x0b, 0xb2, + 0x37, 0x22, 0xbb, 0x1f, 0xf3, 0x2c, 0xbb, 0x5e, 0xcc, 0xe7, 0xa2, 0x50, 0x58, 0x49, 0xb2, 0x54, 0xa2, 0x82, 0x0f, + 0xac, 0xe8, 0x52, 0xde, 0x72, 0x95, 0x4c, 0x43, 0x85, 0x96, 0x09, 0x95, 0x6c, 0xef, 0xb1, 0x10, 0x19, 0xa3, 0x79, + 0xcc, 0x09, 0xef, 0xff, 0x5c, 0xc4, 0xf9, 0x22, 0xcb, 0x7a, 0xa3, 0x82, 0xd1, 0x2f, 0x3d, 0x9d, 0x6d, 0x0e, 0x87, + 0x58, 0xff, 0xbe, 0x2c, 0x0a, 0x7a, 0x0f, 0x05, 0x09, 0x81, 0x62, 0x7d, 0x1e, 0xff, 0x7c, 0xfd, 0xfa, 0x55, 0x64, + 0xf6, 0x0a, 0x1f, 0xdf, 0x87, 0xbc, 0xdc, 0x7f, 0x7c, 0x8d, 0xc7, 0x85, 0x98, 0x6d, 0x74, 0x6d, 0x40, 0xc7, 0x7b, + 0xdf, 0x18, 0x02, 0x23, 0x7c, 0xdf, 0x34, 0xed, 0x8f, 0xe0, 0x95, 0xc6, 0x7c, 0xc8, 0x24, 0xb6, 0x5f, 0xf8, 0x27, + 0x36, 0xc9, 0x21, 0x47, 0xdf, 0x1f, 0xad, 0x2a, 0xee, 0x97, 0x8c, 0xe8, 0x71, 0xce, 0xe1, 0x60, 0x84, 0x31, 0x26, + 0x54, 0x25, 0xd3, 0x25, 0xd3, 0x8d, 0xad, 0xdd, 0x88, 0xd9, 0x7a, 0x8d, 0x5f, 0x09, 0x87, 0xf5, 0x6a, 0x9f, 0x10, + 0xae, 0xe9, 0x15, 0x51, 0xab, 0x15, 0x27, 0x84, 0x23, 0xfc, 0x96, 0x93, 0x25, 0x75, 0x13, 0x82, 0x93, 0x0d, 0xb6, + 0x67, 0x6c, 0xa8, 0x0c, 0x9c, 0x80, 0x5f, 0x59, 0xa1, 0x58, 0x11, 0x2b, 0x89, 0x0b, 0x36, 0xce, 0x60, 0x1c, 0xfb, + 0x6d, 0x3c, 0xa5, 0xf2, 0x6a, 0x4a, 0xf3, 0x09, 0x4b, 0xe3, 0x57, 0x62, 0x8d, 0x99, 0x24, 0xc1, 0x98, 0xe7, 0x34, + 0xe3, 0xff, 0xb0, 0x34, 0xb0, 0xe7, 0xc2, 0x63, 0xb5, 0xc7, 0xee, 0x14, 0xcb, 0x53, 0xb9, 0xf7, 0xfc, 0xdd, 0xaf, + 0x2f, 0xed, 0x62, 0xd6, 0xce, 0x0a, 0xb4, 0x94, 0x8b, 0x39, 0x2b, 0x42, 0x84, 0xed, 0x59, 0xf1, 0x94, 0x6b, 0x3a, + 0xf9, 0x2b, 0x9d, 0x9b, 0x14, 0x2e, 0x7f, 0x9f, 0xa7, 0x54, 0xb1, 0x37, 0x2c, 0x4f, 0x79, 0x3e, 0x21, 0xfb, 0x6d, + 0x93, 0x3e, 0xa5, 0x36, 0x23, 0x2d, 0x93, 0x6e, 0x1e, 0x3c, 0xcd, 0xf4, 0xdc, 0xcb, 0xcf, 0x45, 0x88, 0xd6, 0x52, + 0x51, 0xc5, 0x93, 0x3d, 0x9a, 0xa6, 0x2f, 0x72, 0xae, 0xb8, 0x1e, 0x61, 0x01, 0x4b, 0x04, 0xb8, 0xca, 0xcc, 0xa9, + 0xe1, 0x46, 0x1e, 0x22, 0x1c, 0x86, 0xf6, 0x2c, 0x98, 0x22, 0xbb, 0x66, 0x07, 0x07, 0x15, 0xe5, 0xef, 0xb3, 0xd8, + 0x64, 0x92, 0xc1, 0x10, 0x45, 0xf3, 0x85, 0x84, 0xc5, 0x76, 0x5d, 0xc0, 0x41, 0x23, 0x46, 0x92, 0x15, 0x5f, 0x59, + 0x5a, 0x22, 0x88, 0x0c, 0xd1, 0x72, 0xa3, 0x0f, 0xbb, 0x3d, 0x14, 0x19, 0x0c, 0x7b, 0x3e, 0x09, 0x67, 0x16, 0xd9, + 0x0d, 0xa7, 0xc2, 0x99, 0x2c, 0x89, 0x4a, 0x08, 0x07, 0x6a, 0x49, 0x58, 0x72, 0xe2, 0xe6, 0x37, 0x0f, 0x25, 0xf0, + 0x10, 0x3e, 0xe5, 0x70, 0x67, 0xee, 0xd3, 0xaf, 0xfa, 0xf0, 0xc8, 0xb1, 0x44, 0x58, 0x99, 0x91, 0xe6, 0x08, 0xad, + 0x11, 0x56, 0x6e, 0xb8, 0x86, 0x28, 0x39, 0xbe, 0x08, 0x4e, 0x6d, 0xf2, 0x96, 0xeb, 0x63, 0x1b, 0x68, 0x1b, 0x55, + 0xec, 0xe0, 0x20, 0x64, 0x51, 0x89, 0x18, 0x64, 0xbf, 0x6d, 0x17, 0xc9, 0x83, 0xd6, 0x37, 0xc6, 0x0d, 0x3d, 0x6b, + 0x06, 0x67, 0x9f, 0x45, 0xb9, 0xb8, 0x4c, 0x12, 0x26, 0xa5, 0x28, 0x0e, 0x0e, 0xf6, 0x75, 0xf9, 0x92, 0xb3, 0x80, + 0x45, 0x7c, 0x7d, 0x9b, 0x57, 0x43, 0x40, 0xd5, 0x69, 0xeb, 0xf8, 0x26, 0x52, 0xf1, 0x4d, 0x8e, 0x09, 0x89, 0x83, + 0x9b, 0x9b, 0xa0, 0xa1, 0xb0, 0x85, 0xc3, 0x84, 0xb9, 0xae, 0xef, 0x9f, 0x30, 0xc3, 0x16, 0x6a, 0x26, 0x64, 0x0b, + 0x34, 0x3b, 0xf9, 0xc1, 0xb0, 0x3e, 0x24, 0xac, 0x70, 0x8e, 0xd6, 0xde, 0x8a, 0xee, 0x6c, 0x5a, 0xf3, 0x37, 0x66, + 0xe9, 0x96, 0x13, 0xcd, 0x53, 0x78, 0xeb, 0x38, 0x60, 0xc3, 0x35, 0xd6, 0xb0, 0x77, 0xb3, 0x11, 0x7a, 0xa0, 0x03, + 0x35, 0xec, 0xd9, 0x7c, 0x92, 0x1b, 0xc8, 0x15, 0xec, 0xef, 0x05, 0x93, 0xca, 0x20, 0x72, 0xa8, 0xb0, 0xc0, 0x70, + 0x46, 0x6d, 0x32, 0x9d, 0x35, 0x96, 0x74, 0xd7, 0xd8, 0x5e, 0xcf, 0xe1, 0x6c, 0x94, 0x80, 0xd4, 0xdf, 0xc7, 0x27, + 0x18, 0xab, 0x42, 0xab, 0xd5, 0x5b, 0xee, 0x5a, 0xa9, 0xd6, 0xb2, 0xe4, 0xd7, 0x36, 0x16, 0x85, 0x49, 0x64, 0x0f, + 0xe7, 0xfd, 0xb6, 0x1d, 0xbf, 0x1c, 0x92, 0xfd, 0x56, 0x89, 0xc5, 0x16, 0xac, 0x66, 0x3c, 0x06, 0x8a, 0xaf, 0x4d, + 0x53, 0x48, 0x9f, 0xf5, 0x35, 0x7c, 0x89, 0xa6, 0x5b, 0xb8, 0x3a, 0x25, 0x03, 0xe0, 0x3a, 0xa2, 0xe9, 0xf0, 0x5b, + 0xf8, 0xe4, 0x28, 0x42, 0xa8, 0xb6, 0xf3, 0x2a, 0xc2, 0xf1, 0xb5, 0x4e, 0x38, 0x36, 0xa6, 0x11, 0xcc, 0xcb, 0x2a, + 0x41, 0x89, 0x66, 0x76, 0xab, 0x57, 0x59, 0x58, 0xea, 0xc1, 0x54, 0x53, 0xf2, 0x9a, 0x78, 0x45, 0x67, 0x4c, 0x86, + 0x0c, 0xe1, 0x6f, 0x15, 0x30, 0xf8, 0x09, 0x45, 0x86, 0xde, 0x19, 0x9a, 0xc3, 0x19, 0x0a, 0xec, 0x2e, 0x30, 0x69, + 0xf5, 0x2d, 0x97, 0x63, 0x36, 0xc8, 0x87, 0x15, 0x6f, 0xe7, 0x4d, 0x5e, 0x1f, 0xce, 0x92, 0xd4, 0xf6, 0x9b, 0x49, + 0x33, 0x40, 0xd3, 0x2c, 0x84, 0x44, 0x78, 0xbf, 0xb5, 0xb9, 0x92, 0xae, 0x54, 0x35, 0xc7, 0xc1, 0x10, 0xd6, 0x41, + 0x1f, 0x1b, 0x11, 0x97, 0xfa, 0x6f, 0x6d, 0xab, 0x01, 0xd8, 0xae, 0x01, 0x33, 0xa2, 0x71, 0x46, 0x55, 0xd8, 0x3e, + 0x6a, 0x01, 0x63, 0xfa, 0x95, 0xc1, 0xa9, 0x82, 0xd0, 0xf6, 0x54, 0x58, 0xb4, 0xc8, 0xe5, 0x94, 0x8f, 0x55, 0xf8, + 0x41, 0x6a, 0xa2, 0xc2, 0x32, 0xc9, 0x40, 0xc2, 0xf1, 0xd8, 0x63, 0x4d, 0x70, 0x3e, 0xc0, 0x30, 0x4a, 0x56, 0x8c, + 0xb9, 0x91, 0x6a, 0xc2, 0x05, 0xe4, 0xa1, 0x62, 0xad, 0x2b, 0x32, 0xe3, 0x4a, 0x4b, 0xe0, 0x1e, 0xdb, 0x7d, 0xd3, + 0x62, 0x6c, 0xa9, 0x81, 0xf4, 0x38, 0x58, 0x19, 0xfb, 0x24, 0xc2, 0x26, 0xaa, 0x48, 0x89, 0x97, 0xe2, 0x96, 0x15, + 0x57, 0x14, 0x06, 0x1f, 0x9b, 0xea, 0x6b, 0x73, 0x14, 0x68, 0x8a, 0xaf, 0x7a, 0x0e, 0x5f, 0x6e, 0xf4, 0xc4, 0xdf, + 0x14, 0x62, 0xc6, 0x25, 0x03, 0xbe, 0xcd, 0xc0, 0x3f, 0x87, 0x8d, 0xa6, 0x77, 0x24, 0x1c, 0x37, 0xac, 0xc4, 0xaf, + 0xcb, 0x97, 0x75, 0xfc, 0xba, 0x79, 0xf0, 0x74, 0xe2, 0x28, 0x60, 0x7d, 0x1f, 0x23, 0x1c, 0x5a, 0xf1, 0xc2, 0x3b, + 0xe9, 0xa2, 0x29, 0xb2, 0xc7, 0xfc, 0x6a, 0xa5, 0x3c, 0x31, 0xae, 0xc6, 0x39, 0x32, 0xb3, 0x6d, 0xd0, 0x9a, 0xa6, + 0x29, 0xb0, 0x78, 0x85, 0xc8, 0x32, 0xef, 0xb0, 0xc2, 0xb2, 0x57, 0x1e, 0x4f, 0x37, 0x0f, 0x9e, 0x5e, 0x7f, 0xef, + 0x84, 0x82, 0x7c, 0xff, 0x90, 0x72, 0x03, 0xcd, 0x53, 0x56, 0x80, 0x5c, 0xe9, 0xad, 0x96, 0x3d, 0x67, 0xaf, 0x44, + 0x9e, 0xb3, 0x44, 0xb1, 0x14, 0x84, 0x16, 0x60, 0x83, 0xa7, 0x42, 0xaa, 0x32, 0xb1, 0x1a, 0xbd, 0xf4, 0x85, 0xd0, + 0x28, 0xa1, 0x59, 0x16, 0x1a, 0x01, 0x65, 0x26, 0xbe, 0xb2, 0x1d, 0xa3, 0xee, 0xd5, 0x86, 0x5c, 0x36, 0xc3, 0xbc, + 0x66, 0x58, 0x24, 0xe7, 0x19, 0x4f, 0x58, 0x79, 0x78, 0x5d, 0x47, 0x3c, 0x4f, 0xd9, 0x1d, 0xd0, 0x11, 0x74, 0x71, + 0x71, 0xd1, 0xc2, 0x6d, 0xb4, 0x36, 0x00, 0x5f, 0x6e, 0x01, 0xf6, 0x3b, 0xc7, 0xa6, 0x11, 0xc4, 0x97, 0x3b, 0xc9, + 0x1a, 0xf2, 0xce, 0x4a, 0xee, 0x04, 0x2d, 0x43, 0x9e, 0x11, 0x4e, 0x59, 0xc6, 0x14, 0x73, 0xe4, 0x1c, 0x98, 0x69, + 0xb3, 0x75, 0xdf, 0x96, 0xf0, 0x2b, 0xd1, 0xc9, 0xed, 0x32, 0xb7, 0xe6, 0xb2, 0x14, 0xdd, 0xab, 0xe5, 0xa9, 0xa0, + 0xdd, 0x57, 0x66, 0x79, 0xa8, 0x52, 0x34, 0x99, 0x1a, 0x89, 0x3d, 0xdc, 0x9a, 0x52, 0xd5, 0x86, 0x25, 0xed, 0xe5, + 0x26, 0xfa, 0x54, 0xd8, 0x61, 0xee, 0x02, 0xc1, 0xb5, 0x25, 0x0a, 0x0c, 0x84, 0x40, 0xb3, 0x6c, 0x57, 0x34, 0xcb, + 0x46, 0x34, 0xf9, 0x52, 0xc7, 0xfe, 0x0a, 0x0d, 0xc8, 0x26, 0x35, 0xf6, 0xb2, 0x3c, 0x92, 0xe5, 0xcf, 0xdb, 0x51, + 0xe9, 0xda, 0x46, 0x09, 0xf7, 0x5b, 0x15, 0xda, 0xd7, 0x17, 0xfa, 0x9b, 0xd8, 0xae, 0x47, 0x24, 0xed, 0xcc, 0x42, + 0xa0, 0x02, 0xff, 0x12, 0xe3, 0x1c, 0x3d, 0xb0, 0x78, 0x07, 0x82, 0xc7, 0x7a, 0x63, 0x20, 0x0a, 0x2d, 0xd7, 0x29, + 0x97, 0xdf, 0x86, 0xc0, 0xff, 0x96, 0x51, 0x3e, 0xf1, 0x7a, 0xf8, 0x77, 0x07, 0x5a, 0xd2, 0x38, 0xcb, 0x38, 0x97, + 0x23, 0xb3, 0x0c, 0x85, 0x23, 0x34, 0xbf, 0x00, 0xf3, 0xa2, 0xf1, 0xfd, 0xb5, 0xc9, 0xd2, 0x7c, 0x19, 0x0c, 0x23, + 0xef, 0xf9, 0x0c, 0x45, 0x0d, 0x05, 0x2c, 0x51, 0x35, 0x67, 0xae, 0xa8, 0x89, 0x92, 0x96, 0x6b, 0x37, 0xe2, 0xb8, + 0xa5, 0xb9, 0x05, 0x09, 0xc3, 0x30, 0x27, 0xba, 0x0d, 0xc3, 0xdf, 0x57, 0xb3, 0xc8, 0xb7, 0x66, 0x91, 0x47, 0x9e, + 0xb4, 0x85, 0x2a, 0x64, 0xf6, 0xaa, 0xc7, 0x4a, 0x22, 0xbf, 0x14, 0xb0, 0xac, 0x11, 0x50, 0x68, 0x54, 0x12, 0xdc, + 0x8c, 0x28, 0x5c, 0x58, 0x51, 0xc7, 0xe2, 0x1a, 0x90, 0x8c, 0xaa, 0x8a, 0x40, 0x66, 0x73, 0xd4, 0x64, 0x5f, 0x81, + 0x0b, 0xb4, 0xc1, 0xdf, 0xaf, 0xd7, 0x16, 0x4a, 0x0c, 0xd9, 0xd5, 0xa9, 0x31, 0xc6, 0x1e, 0x58, 0xb0, 0x20, 0xb9, + 0x61, 0x86, 0x0d, 0xeb, 0xb3, 0x09, 0x9c, 0xb2, 0xdd, 0x7d, 0x42, 0x44, 0x05, 0x9b, 0x3c, 0xda, 0xc1, 0x5d, 0x09, + 0x84, 0xa9, 0x63, 0x4b, 0x8b, 0x6a, 0xe2, 0x84, 0x04, 0x4e, 0x3b, 0x11, 0xf4, 0x97, 0x35, 0xe1, 0x30, 0xf6, 0x8a, + 0xad, 0x63, 0x20, 0xaa, 0xc5, 0x2e, 0x78, 0xef, 0xc2, 0x9a, 0x5a, 0x3b, 0x1e, 0xc4, 0x8b, 0x1a, 0xc4, 0x3d, 0xd0, + 0x0a, 0x43, 0xbc, 0xc4, 0x90, 0xd0, 0x7a, 0xe5, 0x90, 0xe1, 0xc2, 0x2c, 0xc4, 0x16, 0x14, 0x37, 0xd9, 0x4f, 0x8d, + 0x85, 0x20, 0xcb, 0xe6, 0xc0, 0xdf, 0xf9, 0x47, 0x44, 0x08, 0x83, 0x97, 0xab, 0xd5, 0x16, 0xda, 0xed, 0xe4, 0x42, + 0x51, 0x54, 0x49, 0x87, 0xab, 0xd5, 0x2b, 0x81, 0x42, 0xcb, 0xff, 0x62, 0x86, 0xfa, 0x8e, 0xe8, 0x5e, 0xbe, 0x84, + 0x52, 0x9a, 0x1d, 0xad, 0x52, 0x4a, 0xc1, 0xa1, 0x8e, 0xb5, 0xf5, 0x85, 0x52, 0x1e, 0xe5, 0xbe, 0xda, 0x22, 0x60, + 0x3a, 0xd1, 0x9e, 0xd4, 0xd5, 0x94, 0xaf, 0x6c, 0xd3, 0x12, 0x21, 0x14, 0xe7, 0x5a, 0x96, 0xd9, 0xdf, 0x25, 0x5f, + 0x1e, 0x1c, 0xe4, 0x5e, 0x43, 0x37, 0x25, 0xa5, 0xf8, 0x2b, 0x84, 0x53, 0x59, 0xde, 0xe7, 0x9a, 0x7d, 0xf9, 0xcb, + 0x9d, 0x43, 0x5b, 0xd2, 0x69, 0xab, 0x07, 0x82, 0x39, 0xbd, 0xa5, 0x5c, 0xed, 0x95, 0xad, 0x18, 0xc1, 0x3c, 0x64, + 0x68, 0x69, 0xb9, 0x8d, 0xa8, 0x60, 0xc0, 0x3f, 0x02, 0x59, 0x70, 0x5c, 0xb4, 0x41, 0xfc, 0x64, 0xca, 0x40, 0x95, + 0xed, 0x18, 0x89, 0x52, 0x3c, 0xdc, 0xb7, 0x07, 0x89, 0x6d, 0x78, 0xf7, 0xd8, 0xd7, 0x9b, 0xd5, 0x6b, 0xd2, 0xc0, + 0x9c, 0x15, 0x63, 0x51, 0xcc, 0x5c, 0xde, 0x7a, 0xe3, 0xdb, 0x12, 0x47, 0x3e, 0x0e, 0x77, 0xb6, 0x6d, 0x45, 0x80, + 0xde, 0x86, 0xec, 0x5d, 0x49, 0xed, 0xb5, 0xd3, 0xb4, 0x3c, 0x80, 0x8d, 0x82, 0xd0, 0x61, 0x66, 0xee, 0x4b, 0xf9, + 0x56, 0xbd, 0xda, 0x33, 0xba, 0x93, 0xfd, 0x76, 0xaf, 0x94, 0xfc, 0x1c, 0x36, 0xf4, 0x8c, 0x8e, 0xc3, 0x9e, 0xaa, + 0x62, 0x91, 0xa5, 0x76, 0xb0, 0x70, 0xc4, 0x59, 0x3c, 0xba, 0xe5, 0x59, 0x56, 0xa5, 0xfe, 0x27, 0xa4, 0x3d, 0xb7, + 0xa4, 0x5d, 0x38, 0xd2, 0x0e, 0xa4, 0x02, 0x48, 0xbb, 0x69, 0xae, 0xaa, 0x2e, 0xb6, 0xb6, 0xa7, 0x30, 0x44, 0x3d, + 0xd7, 0xe2, 0x34, 0xf4, 0xb7, 0x70, 0x23, 0x40, 0x25, 0xf3, 0xf5, 0x25, 0xb4, 0xfa, 0x18, 0x10, 0x03, 0x8d, 0x4e, + 0x93, 0xf9, 0x9a, 0x8a, 0x2f, 0x21, 0xc2, 0xf9, 0x9a, 0x95, 0x98, 0x7d, 0xf9, 0x14, 0x94, 0x76, 0xde, 0x74, 0xe0, + 0x1c, 0xd3, 0xc9, 0xff, 0x11, 0x1f, 0xe5, 0x66, 0x27, 0xed, 0xec, 0x72, 0x37, 0x3b, 0xa0, 0xf5, 0xd5, 0xec, 0xd2, + 0xef, 0x53, 0x7b, 0x3d, 0x3d, 0x59, 0x4e, 0xaf, 0x5a, 0xef, 0xd5, 0x2a, 0xdc, 0x48, 0x01, 0x8d, 0xbe, 0x95, 0x52, + 0x8a, 0xb2, 0x75, 0xa0, 0x01, 0x3e, 0x64, 0x20, 0x61, 0x6d, 0x26, 0x5d, 0x9e, 0x72, 0x2f, 0xff, 0x95, 0x9e, 0x47, + 0x2b, 0xee, 0x4d, 0xfd, 0x2b, 0x31, 0x9b, 0x03, 0x43, 0xb6, 0x81, 0xd2, 0x13, 0x66, 0x3b, 0xac, 0xf2, 0xd7, 0x3b, + 0xd2, 0x6a, 0x75, 0xf4, 0x7e, 0xac, 0x61, 0x53, 0x29, 0x35, 0xef, 0xb7, 0xd6, 0x8b, 0x32, 0xa9, 0x24, 0x1c, 0xbb, + 0x74, 0x2b, 0x57, 0x9b, 0x9a, 0x19, 0x97, 0xf1, 0x3a, 0x94, 0x86, 0x0e, 0x4b, 0xa0, 0x75, 0x1e, 0xf9, 0x71, 0xe8, + 0xee, 0xaf, 0xff, 0xba, 0x02, 0xce, 0x72, 0xbd, 0x01, 0xbe, 0xe5, 0x7a, 0xfd, 0x58, 0x59, 0x49, 0x1b, 0x3f, 0xde, + 0x21, 0xf7, 0x96, 0xd0, 0xab, 0x32, 0xad, 0xcc, 0x38, 0x18, 0x42, 0xda, 0x16, 0x0b, 0x49, 0x96, 0x33, 0x91, 0xb2, + 0x38, 0x10, 0x73, 0x96, 0x07, 0x6b, 0xd0, 0xb3, 0x5a, 0x04, 0xf8, 0x28, 0xc3, 0xe5, 0xdb, 0xba, 0xbe, 0x35, 0x7e, + 0xac, 0xd6, 0xa0, 0x0a, 0x7b, 0xc9, 0x77, 0x28, 0x63, 0xdf, 0xb3, 0x42, 0x6a, 0x9e, 0xb4, 0x64, 0x6f, 0x5f, 0xf2, + 0xea, 0x80, 0x7a, 0xc9, 0xe3, 0x6f, 0x57, 0xa9, 0x04, 0x92, 0xa0, 0x1d, 0x9d, 0x46, 0xc7, 0x01, 0xd2, 0x1a, 0xe3, + 0x67, 0x4e, 0x63, 0xbc, 0x28, 0x35, 0xc6, 0xcf, 0x15, 0x59, 0x6c, 0x68, 0x8c, 0xff, 0x96, 0xe4, 0xb9, 0xea, 0x3f, + 0x77, 0xda, 0xf4, 0x37, 0x22, 0xe3, 0xc9, 0x7d, 0x18, 0x64, 0x5c, 0x35, 0xe1, 0x36, 0x31, 0xc0, 0x4b, 0x93, 0x01, + 0xaa, 0x46, 0xad, 0xef, 0x5e, 0x3b, 0xf9, 0x0f, 0x73, 0x49, 0x82, 0x07, 0x19, 0x57, 0x0f, 0x02, 0x3c, 0x55, 0xe4, + 0x33, 0xfc, 0x7a, 0xb0, 0x0c, 0x7f, 0xa5, 0x6a, 0x1a, 0x15, 0x34, 0x4f, 0xc5, 0x2c, 0x44, 0x8d, 0x20, 0x40, 0x91, + 0xd4, 0x42, 0xc8, 0x23, 0xb4, 0x7e, 0xf0, 0x19, 0xff, 0x23, 0x48, 0xd0, 0x0f, 0x1a, 0x53, 0x85, 0x15, 0x25, 0x9f, + 0xcf, 0x1f, 0x2c, 0xff, 0x11, 0xeb, 0x8b, 0xcf, 0xf8, 0xa9, 0x2a, 0xd5, 0xfa, 0xf8, 0x8e, 0x91, 0x10, 0x91, 0x8b, + 0xa7, 0x6e, 0x48, 0x57, 0x62, 0x66, 0x14, 0xfc, 0x01, 0xc2, 0x5f, 0x41, 0xaf, 0x7b, 0xc1, 0x2b, 0x22, 0x64, 0xef, + 0x60, 0xf6, 0x49, 0x20, 0xb4, 0xf2, 0x20, 0x38, 0x38, 0xf0, 0xd2, 0x4a, 0x16, 0x02, 0xff, 0x25, 0x48, 0x4d, 0x54, + 0xc7, 0x8c, 0x42, 0x4b, 0x7f, 0x89, 0x90, 0x23, 0xd7, 0x4c, 0xe8, 0x34, 0xd5, 0x76, 0xc7, 0xf2, 0x81, 0xd1, 0x3d, + 0x44, 0x5c, 0xb1, 0x82, 0x2a, 0x51, 0x0c, 0x91, 0xcf, 0x96, 0xe0, 0x57, 0x9c, 0x7c, 0x1e, 0xec, 0xfd, 0x3f, 0xff, + 0xe3, 0xcf, 0xf1, 0x9f, 0xc5, 0xf0, 0x33, 0x96, 0x8c, 0x1c, 0x9d, 0x87, 0xfd, 0x38, 0xdc, 0x6f, 0x36, 0x57, 0x7f, + 0x1e, 0x0d, 0xfe, 0x9b, 0x36, 0xff, 0xb9, 0x6c, 0x7e, 0x1a, 0xa2, 0x55, 0xf8, 0xe7, 0x51, 0x7f, 0x60, 0xbf, 0x06, + 0xff, 0x7d, 0xf1, 0xa7, 0x1c, 0x1e, 0x9a, 0xc4, 0x07, 0x08, 0x1d, 0x4d, 0xf0, 0x1f, 0x92, 0x1c, 0x35, 0x9b, 0x17, + 0x47, 0x13, 0xfc, 0x8b, 0x24, 0x47, 0xf0, 0xf7, 0x5e, 0x91, 0xb7, 0x6c, 0xf2, 0xf4, 0x6e, 0x1e, 0x7e, 0xbe, 0x58, + 0x3d, 0x58, 0xbe, 0xe2, 0x6b, 0x68, 0x77, 0xf0, 0xdf, 0x7f, 0xfe, 0x29, 0x83, 0x1f, 0x2f, 0xc8, 0xd1, 0xb0, 0x81, + 0x42, 0x9d, 0x7c, 0x48, 0xcc, 0x9f, 0xb0, 0x1f, 0x0f, 0xfe, 0xdb, 0x0e, 0x25, 0xf8, 0xf1, 0xcf, 0xcf, 0xe7, 0x17, + 0x64, 0xb8, 0x0a, 0x83, 0xd5, 0x8f, 0x68, 0x85, 0xd0, 0xea, 0x01, 0xfa, 0x8c, 0x83, 0x49, 0x80, 0xf0, 0x4f, 0x92, + 0x1c, 0xfd, 0x78, 0x34, 0xc1, 0xbf, 0x49, 0x72, 0x14, 0x1c, 0x4d, 0xf0, 0x7b, 0x41, 0x8e, 0xfe, 0x3b, 0xec, 0xc7, + 0x46, 0x09, 0xb7, 0xd2, 0xea, 0x8f, 0x15, 0xdc, 0x84, 0xd0, 0x82, 0xd1, 0x95, 0xe2, 0x2a, 0x63, 0xe8, 0xc1, 0x11, + 0xc7, 0x8f, 0x05, 0x00, 0x2b, 0x54, 0xa0, 0xa4, 0xd1, 0x97, 0xb0, 0xcb, 0x1b, 0x58, 0x78, 0xc0, 0xa0, 0x07, 0x31, + 0xc7, 0x46, 0x4f, 0x20, 0x63, 0x65, 0x6e, 0x6f, 0x25, 0x5c, 0xdf, 0xe2, 0x2b, 0xf2, 0x58, 0x84, 0x6d, 0x84, 0x39, + 0x85, 0x1f, 0x1d, 0x84, 0x3f, 0x28, 0x7b, 0xe1, 0x09, 0xdb, 0xdc, 0x60, 0x58, 0x2e, 0x0c, 0x3f, 0x13, 0x20, 0xfc, + 0x72, 0x47, 0xa6, 0x9a, 0x82, 0xfa, 0x01, 0xe1, 0x4f, 0xb5, 0xeb, 0x51, 0x7c, 0xa5, 0x48, 0x89, 0x1c, 0xef, 0x0a, + 0xc6, 0x3e, 0xd0, 0xec, 0x0b, 0x2b, 0xc2, 0xa7, 0x0a, 0xb7, 0x3b, 0x8f, 0xb0, 0x56, 0x55, 0xef, 0xb7, 0x51, 0xaf, + 0xbc, 0xdd, 0x7a, 0x2e, 0xcc, 0x7d, 0x02, 0x9c, 0xc2, 0x75, 0x7d, 0x0d, 0xac, 0xfd, 0x3e, 0xdf, 0x52, 0x6a, 0x15, + 0xf4, 0x36, 0x40, 0xf5, 0xab, 0x54, 0x9e, 0x7f, 0xa5, 0x19, 0x4f, 0xf7, 0x14, 0x9b, 0xcd, 0x33, 0xaa, 0xd8, 0x9e, + 0x9d, 0xf3, 0x1e, 0x85, 0x86, 0x82, 0x92, 0xa7, 0xf8, 0x5b, 0x56, 0x9b, 0xf6, 0x6f, 0x27, 0xe7, 0xc1, 0xde, 0x09, + 0xe1, 0x3e, 0xcb, 0xf2, 0x25, 0x92, 0x96, 0xd7, 0x65, 0x9b, 0x37, 0x82, 0xcd, 0x36, 0x28, 0xcb, 0x86, 0xfa, 0xfc, + 0xce, 0x31, 0xdc, 0x6f, 0x12, 0xd2, 0xe9, 0x07, 0xe7, 0xf2, 0xeb, 0xe4, 0x22, 0x80, 0x9b, 0x9c, 0x82, 0x48, 0xa6, + 0x95, 0x47, 0x50, 0x82, 0x92, 0x56, 0x8f, 0x9e, 0xb3, 0x1e, 0x6d, 0x34, 0x1c, 0x9b, 0x9d, 0x10, 0x3e, 0xa0, 0xa6, + 0x7e, 0x86, 0xa7, 0x38, 0x25, 0xcd, 0x36, 0x5e, 0x90, 0x96, 0xae, 0xd2, 0x5b, 0x9c, 0x27, 0xb6, 0x9f, 0x83, 0x83, + 0xb0, 0x88, 0x32, 0x2a, 0xd5, 0x0b, 0xd0, 0x08, 0x90, 0x05, 0x9e, 0x92, 0x22, 0x62, 0x77, 0x2c, 0x09, 0x13, 0x84, + 0xa7, 0x96, 0x06, 0xa1, 0x1e, 0x5a, 0x10, 0xaf, 0x18, 0xc8, 0x19, 0x44, 0xb2, 0xfe, 0x74, 0xd0, 0x1e, 0x12, 0x42, + 0x82, 0xfd, 0x66, 0x33, 0xe8, 0x17, 0xe4, 0x0f, 0x19, 0x43, 0x8a, 0xc7, 0x4e, 0x93, 0x5f, 0x20, 0xa9, 0xe3, 0x25, + 0x85, 0xef, 0x45, 0xa4, 0x98, 0x54, 0x21, 0x24, 0x83, 0x92, 0x20, 0x77, 0x18, 0x1e, 0x9c, 0x1f, 0x05, 0x0d, 0x48, + 0xd5, 0x28, 0x8a, 0x70, 0x41, 0xee, 0x15, 0x8a, 0xa7, 0x83, 0xe3, 0xa1, 0x7f, 0x46, 0x98, 0x54, 0xe8, 0xff, 0x5e, + 0xf5, 0xa7, 0x83, 0x96, 0xee, 0xff, 0x22, 0xe8, 0x87, 0x05, 0xc9, 0xf7, 0xed, 0x3d, 0x4f, 0x2c, 0x99, 0x9e, 0x2f, + 0x8a, 0xed, 0x00, 0x6d, 0xdf, 0x29, 0x69, 0x76, 0xe2, 0x30, 0xf5, 0x67, 0xd2, 0x84, 0x0e, 0x2d, 0x28, 0x70, 0x46, + 0xa0, 0x3c, 0x2e, 0x08, 0x74, 0x5a, 0x55, 0xbb, 0x57, 0xb1, 0x4d, 0xf8, 0x31, 0xf8, 0xb1, 0xff, 0x9b, 0x8c, 0x7f, + 0x92, 0x66, 0x04, 0xbf, 0xc9, 0xd5, 0x0a, 0xfe, 0xfe, 0x24, 0xfb, 0x30, 0x2c, 0x9d, 0xf6, 0x87, 0x4d, 0xfb, 0x05, + 0xd2, 0x24, 0x8b, 0xf5, 0x80, 0x71, 0x5e, 0xf2, 0x63, 0x66, 0x71, 0xc6, 0xc4, 0xcc, 0xe0, 0xe0, 0x80, 0x0f, 0x68, + 0xa3, 0x3d, 0x84, 0x1b, 0x81, 0x42, 0xc9, 0x0f, 0x5c, 0x4d, 0xc3, 0xe0, 0xe8, 0x22, 0x40, 0xfd, 0x60, 0x0f, 0x56, + 0xb9, 0x27, 0x1a, 0xc4, 0xc2, 0x3a, 0x69, 0x28, 0x1a, 0xa7, 0x17, 0xa4, 0xd5, 0x0f, 0xa5, 0x21, 0xf2, 0x19, 0xc2, + 0x89, 0xa5, 0xa9, 0x2d, 0x9c, 0xa2, 0x06, 0x97, 0x0d, 0xf7, 0x9d, 0xa2, 0xc6, 0x54, 0x35, 0xc6, 0x28, 0x4e, 0xe0, + 0x6f, 0x98, 0x12, 0x42, 0x9a, 0x9d, 0xb2, 0xa2, 0x3b, 0x2c, 0x29, 0x8a, 0xc7, 0x4e, 0x3d, 0x3a, 0xd0, 0x9b, 0x43, + 0x34, 0x42, 0x3e, 0x60, 0xc3, 0xd5, 0x2a, 0x38, 0xef, 0x5f, 0x04, 0xa8, 0x11, 0x3a, 0xb4, 0x3b, 0x72, 0x78, 0x87, + 0x10, 0x96, 0xc3, 0xb5, 0xbd, 0x81, 0xba, 0x65, 0xb5, 0xdb, 0xa6, 0x65, 0xb5, 0xff, 0x3d, 0xb2, 0xc0, 0xd6, 0xa5, + 0xdc, 0x63, 0xf8, 0xdb, 0x39, 0x4c, 0xd5, 0xe1, 0xb6, 0x20, 0x2d, 0x5c, 0x10, 0xa7, 0xee, 0xa6, 0x44, 0x55, 0xf8, + 0x9f, 0x90, 0xaa, 0x38, 0x1e, 0x64, 0x78, 0x3a, 0x24, 0x92, 0x6a, 0xf9, 0xa5, 0xe7, 0x94, 0xe9, 0x2c, 0x23, 0xb7, + 0x6c, 0xe3, 0xfe, 0x37, 0x83, 0x3b, 0x99, 0x2b, 0x15, 0x25, 0x8b, 0xa2, 0x60, 0xb9, 0x7a, 0x25, 0x52, 0xcb, 0xd8, + 0xb1, 0x0c, 0x64, 0x2b, 0xb8, 0xd8, 0xc5, 0xc0, 0xd5, 0x75, 0xdc, 0x4e, 0x49, 0xb7, 0xb2, 0x17, 0x24, 0x35, 0x0c, + 0x97, 0xbe, 0xee, 0xed, 0x2d, 0xac, 0x28, 0x1d, 0x22, 0x9c, 0xda, 0x7b, 0xe0, 0x30, 0x8a, 0xa2, 0x45, 0x94, 0x40, + 0x36, 0x74, 0x20, 0xd1, 0x5a, 0xef, 0xab, 0x30, 0x27, 0x57, 0x2a, 0xca, 0xd9, 0x9d, 0xee, 0x36, 0x44, 0xd5, 0x21, + 0xee, 0xf6, 0xdb, 0x39, 0xed, 0x69, 0x02, 0x94, 0x47, 0xb9, 0x48, 0x19, 0x40, 0x08, 0xee, 0xfe, 0x6d, 0xd2, 0x94, + 0x4a, 0xff, 0x66, 0xab, 0x1a, 0xe0, 0xc0, 0x57, 0x79, 0x2f, 0x40, 0x4f, 0xac, 0x65, 0xe8, 0xb2, 0xb0, 0x51, 0x9e, + 0x23, 0xc4, 0xc7, 0xe1, 0x22, 0x82, 0x1b, 0x41, 0x8d, 0x49, 0x5c, 0xa2, 0xd5, 0x6a, 0xe1, 0xe3, 0xd6, 0xb4, 0x52, + 0x4c, 0x8f, 0xc9, 0x74, 0x50, 0x34, 0x1a, 0x5a, 0x79, 0x9d, 0x1a, 0xbc, 0x58, 0x20, 0x3c, 0x2e, 0xf7, 0x9a, 0x2b, + 0x37, 0x27, 0xf5, 0xae, 0xc2, 0x71, 0x5d, 0x09, 0xdc, 0xe0, 0x12, 0x69, 0xfd, 0xa2, 0x82, 0xd6, 0xf1, 0x84, 0x1c, + 0x85, 0x83, 0xa8, 0xff, 0x3f, 0x87, 0xa8, 0x1f, 0x46, 0x87, 0xe8, 0xc8, 0xd0, 0x92, 0x31, 0xea, 0x25, 0xa6, 0x8f, + 0xa5, 0xbe, 0xfd, 0x6c, 0x63, 0xad, 0x80, 0x8c, 0x05, 0xce, 0xe9, 0x8c, 0xc5, 0x13, 0xd8, 0xf5, 0x0e, 0x79, 0xe6, + 0x18, 0x90, 0x29, 0x9e, 0x58, 0xda, 0x12, 0x05, 0x7d, 0x41, 0xcb, 0xaf, 0x7e, 0xd0, 0xa7, 0xd5, 0xd7, 0xff, 0x0c, + 0xfa, 0x09, 0x8d, 0xaf, 0xf8, 0xda, 0x2a, 0xc9, 0x6b, 0x7d, 0x9c, 0xba, 0x3e, 0xd6, 0x66, 0x71, 0x3c, 0xe0, 0xa5, + 0x28, 0xdf, 0xd2, 0x8e, 0x2c, 0xd0, 0x9a, 0x8f, 0x4b, 0xea, 0x94, 0x47, 0x8a, 0x4e, 0x00, 0xaa, 0xde, 0x22, 0xe4, + 0xbe, 0x6d, 0x80, 0x37, 0x65, 0xc0, 0x16, 0x87, 0xb4, 0x00, 0xcd, 0xc5, 0x45, 0x0b, 0x2d, 0x6b, 0x85, 0x2d, 0x67, + 0x55, 0xbf, 0x8b, 0x2f, 0x89, 0xf7, 0x18, 0xa8, 0xf2, 0xf9, 0xa2, 0x37, 0x6e, 0x34, 0x50, 0xee, 0xf0, 0x2b, 0x1d, + 0x8c, 0x87, 0xf8, 0x0e, 0x50, 0x08, 0xd7, 0x30, 0x0a, 0xd7, 0xe6, 0xd8, 0xb1, 0x73, 0x6c, 0x34, 0xc4, 0x1a, 0xf5, + 0xbc, 0xca, 0x0b, 0x5b, 0x79, 0xbd, 0x36, 0x90, 0xd9, 0xc4, 0xb8, 0x33, 0xa4, 0x53, 0xc0, 0x10, 0x8c, 0x10, 0xf2, + 0x8f, 0x40, 0x3b, 0x9b, 0x85, 0x46, 0xa1, 0xba, 0xde, 0xbd, 0x40, 0x51, 0xcd, 0xe9, 0x11, 0x02, 0x2c, 0xa0, 0x6a, + 0xa9, 0x46, 0x9e, 0x2a, 0x9c, 0x36, 0xda, 0x1a, 0xdd, 0x9b, 0xed, 0x5e, 0xbd, 0xb1, 0x87, 0x55, 0x63, 0x38, 0x6d, + 0x90, 0x69, 0xb5, 0xc3, 0xd7, 0xa2, 0xd1, 0x58, 0xd7, 0xef, 0x4b, 0xdd, 0x26, 0xae, 0xdd, 0x5f, 0x3c, 0xdd, 0x32, + 0xf1, 0x70, 0xa7, 0x6f, 0x75, 0xde, 0xca, 0x88, 0xe7, 0x39, 0x2b, 0xe0, 0x84, 0x25, 0x0a, 0xcb, 0xf5, 0xba, 0x3c, + 0xf5, 0x7f, 0x57, 0xc6, 0x66, 0x8c, 0x70, 0xa0, 0x43, 0x5a, 0x6a, 0xc3, 0x02, 0x17, 0x98, 0x6a, 0x2a, 0x42, 0x08, + 0xf9, 0xa0, 0x9c, 0x79, 0x8c, 0xd2, 0x24, 0x29, 0x21, 0xde, 0xd9, 0x1d, 0xe6, 0x84, 0x45, 0x37, 0x0f, 0xae, 0xc4, + 0x77, 0x45, 0xba, 0x81, 0x1c, 0xc6, 0xba, 0x58, 0x66, 0x09, 0x59, 0x46, 0xbe, 0x82, 0x9c, 0x53, 0x5e, 0xb0, 0x44, + 0x9a, 0x20, 0x3e, 0xe1, 0x05, 0xd3, 0x8c, 0xfb, 0x03, 0x27, 0x37, 0x26, 0x75, 0x4e, 0x33, 0xf1, 0xb5, 0x3f, 0x00, + 0xcd, 0x0c, 0x94, 0x43, 0x82, 0x6c, 0x15, 0xbb, 0x79, 0x70, 0xf9, 0x7a, 0x97, 0x0c, 0xbd, 0x5a, 0x59, 0xe9, 0x39, + 0x01, 0xd6, 0x07, 0x67, 0xd5, 0x50, 0x13, 0xfb, 0x23, 0x0e, 0x13, 0xcd, 0x44, 0x65, 0x21, 0x07, 0x64, 0xba, 0x79, + 0x70, 0xf9, 0x2e, 0xe4, 0x5a, 0x37, 0x85, 0xb0, 0x3f, 0xef, 0xb0, 0x20, 0x21, 0x25, 0x0c, 0x99, 0xc9, 0x97, 0x74, + 0xac, 0xf0, 0x4e, 0xf7, 0x98, 0xea, 0x4c, 0x10, 0x3b, 0x06, 0x72, 0x48, 0x12, 0x0b, 0x02, 0x92, 0x20, 0x9c, 0xd4, + 0xe4, 0x3a, 0xa2, 0xd7, 0x40, 0x77, 0x76, 0x0d, 0x8b, 0x11, 0x19, 0xf6, 0x10, 0xe1, 0x44, 0x77, 0xab, 0xd6, 0xe6, + 0x38, 0xc9, 0xe9, 0xa6, 0xa1, 0x5b, 0x25, 0xcf, 0xbe, 0x07, 0xc1, 0xcb, 0x7d, 0xbc, 0xb2, 0x6d, 0x97, 0x09, 0x4f, + 0x9c, 0x45, 0xda, 0xcd, 0x83, 0xcb, 0x5f, 0xad, 0x51, 0xda, 0x9c, 0x3a, 0xf2, 0xbf, 0x25, 0xa3, 0x5e, 0xfe, 0x1a, + 0x55, 0xb9, 0xba, 0xf0, 0xcd, 0x83, 0xcb, 0xdf, 0x77, 0x15, 0x83, 0xf4, 0xf5, 0xa2, 0x52, 0x12, 0xe8, 0xf1, 0x2d, + 0x59, 0x16, 0x2f, 0xed, 0x59, 0x11, 0xcb, 0x35, 0xd6, 0x27, 0x54, 0x9c, 0xaf, 0x4b, 0xdd, 0xca, 0x13, 0x2c, 0x88, + 0xbe, 0x4a, 0xaa, 0x2f, 0x9b, 0x45, 0x63, 0x2e, 0xf2, 0xeb, 0x44, 0xcc, 0xd9, 0x37, 0xee, 0x97, 0x9e, 0x2a, 0x14, + 0xf1, 0x19, 0x18, 0xe2, 0xe8, 0xb1, 0x4b, 0xbc, 0xdf, 0x42, 0xbd, 0x8d, 0xf3, 0x4c, 0x68, 0x44, 0x2d, 0xea, 0x87, + 0x0d, 0xa6, 0xa4, 0x85, 0x13, 0xd2, 0xc2, 0x19, 0xc9, 0x07, 0x2d, 0x73, 0x62, 0xf4, 0xb2, 0xb2, 0x69, 0x73, 0xee, + 0xc0, 0x76, 0xcf, 0xcc, 0xbe, 0x35, 0x87, 0xf2, 0xb4, 0x97, 0x69, 0xfd, 0xa5, 0x3e, 0xe8, 0xa7, 0x1a, 0x35, 0x9e, + 0xb0, 0xb0, 0xc0, 0x85, 0x6e, 0xf9, 0x9a, 0x8f, 0x32, 0xb0, 0x53, 0x81, 0x99, 0x61, 0x85, 0xe2, 0xb2, 0x6c, 0xdb, + 0x96, 0xcd, 0x22, 0xbd, 0x56, 0x05, 0xce, 0x22, 0x20, 0xe5, 0x38, 0xb3, 0x76, 0x3d, 0x72, 0xbb, 0xca, 0xe9, 0xc1, + 0x41, 0x68, 0x2b, 0xd1, 0xb0, 0x70, 0xf9, 0xd5, 0x0d, 0xe0, 0x7b, 0x43, 0x35, 0xa6, 0x48, 0x4f, 0xa0, 0xd1, 0x48, + 0x86, 0x6b, 0xba, 0x4f, 0x48, 0x98, 0xd5, 0xa1, 0xe8, 0x46, 0xaf, 0x99, 0xc1, 0x0d, 0x00, 0x34, 0x1a, 0xe5, 0x75, + 0xef, 0x06, 0xc4, 0x9e, 0x2a, 0x2c, 0xd6, 0x5f, 0xc3, 0xd2, 0x9a, 0xa8, 0xb5, 0x65, 0x87, 0xe5, 0x46, 0x81, 0xa4, + 0x8f, 0xbb, 0xd2, 0xcd, 0xc7, 0xdb, 0x1a, 0xba, 0xdc, 0x0b, 0x6b, 0x03, 0x81, 0xb5, 0xd5, 0x96, 0x2d, 0xe4, 0x48, + 0x5b, 0x07, 0xc5, 0xae, 0x10, 0x5c, 0x70, 0x41, 0xa1, 0xc6, 0xda, 0x62, 0xf9, 0x13, 0xb6, 0x6d, 0xce, 0x89, 0x73, + 0x64, 0xb5, 0x65, 0x7a, 0x18, 0x1a, 0x60, 0x9d, 0x12, 0x30, 0xcf, 0xc9, 0xcb, 0x6f, 0xa3, 0xfe, 0xa5, 0x87, 0xfa, + 0x8f, 0x09, 0xf3, 0xb6, 0x81, 0x59, 0x82, 0x48, 0x58, 0x05, 0x45, 0xee, 0xb2, 0xae, 0xe6, 0x04, 0xb4, 0x71, 0x75, + 0xa8, 0xe6, 0xfe, 0x15, 0xe5, 0x37, 0x28, 0x8b, 0xbf, 0x53, 0xb4, 0x3e, 0x13, 0xbb, 0xfb, 0xe4, 0xb0, 0xba, 0xa0, + 0x83, 0xae, 0x77, 0x29, 0x07, 0x7d, 0x52, 0x78, 0xf9, 0xfb, 0xf7, 0xef, 0x56, 0xaf, 0xe6, 0xdb, 0x3b, 0xd8, 0x33, + 0x2b, 0x85, 0x59, 0x7b, 0x1b, 0xb8, 0x6e, 0x64, 0x0a, 0xfd, 0x97, 0x77, 0xe2, 0x75, 0x2a, 0xb4, 0xb1, 0x19, 0xdd, + 0x71, 0x08, 0xa3, 0x6d, 0xb7, 0x75, 0x09, 0xe6, 0x35, 0x0b, 0x74, 0xc9, 0x18, 0xb7, 0xd2, 0xe2, 0x1b, 0x64, 0xe4, + 0x52, 0x17, 0x60, 0x79, 0xba, 0x3b, 0xfb, 0xf1, 0xda, 0xe2, 0x89, 0x19, 0x1a, 0x5a, 0x6a, 0x42, 0x68, 0xf0, 0x1e, + 0x30, 0xc7, 0x1c, 0x11, 0x00, 0xa2, 0x97, 0x1a, 0x52, 0x15, 0xc8, 0x82, 0xa0, 0x52, 0xe4, 0x3f, 0xdf, 0x27, 0xe4, + 0x65, 0xa5, 0xc8, 0x7c, 0x5b, 0x19, 0x73, 0x01, 0x62, 0xa0, 0x18, 0x2e, 0x12, 0xca, 0x04, 0x73, 0x19, 0xfa, 0x41, + 0xb9, 0xf2, 0x5a, 0xda, 0x8c, 0x2a, 0x6e, 0xdc, 0xbb, 0x29, 0xd5, 0x2a, 0x3e, 0x93, 0xef, 0x20, 0xb1, 0x91, 0xfb, + 0x00, 0x72, 0x19, 0xd5, 0x83, 0x84, 0xef, 0x77, 0xba, 0xb4, 0x6b, 0x77, 0xfd, 0x65, 0xd3, 0x22, 0x66, 0x63, 0x5d, + 0x22, 0x9e, 0x4b, 0x56, 0xa8, 0xc7, 0x6c, 0x2c, 0x0a, 0xb8, 0xff, 0x28, 0xc1, 0x82, 0xd6, 0x0f, 0x3c, 0x1d, 0xa0, + 0x9e, 0xa0, 0x77, 0xe9, 0xb0, 0x31, 0x43, 0xfd, 0xeb, 0x8b, 0xbe, 0x03, 0xbf, 0xd9, 0xac, 0xf5, 0xf2, 0xe0, 0xe0, + 0x2b, 0xab, 0x00, 0x65, 0x87, 0xa9, 0x87, 0xe1, 0x11, 0x2f, 0xc3, 0xe5, 0xd8, 0x9b, 0xe1, 0x07, 0x61, 0xa5, 0x32, + 0x70, 0x84, 0xc3, 0x27, 0x42, 0xcf, 0x89, 0x5a, 0x4f, 0x36, 0xe9, 0xbd, 0xd5, 0x66, 0x48, 0x5f, 0xac, 0x01, 0x72, + 0x0f, 0x72, 0xb9, 0x51, 0x32, 0xe5, 0x95, 0xad, 0x6d, 0x39, 0x88, 0x2b, 0x00, 0x57, 0x98, 0x83, 0x90, 0xe2, 0xa1, + 0x61, 0xbe, 0x53, 0x68, 0x79, 0x2e, 0x80, 0xfd, 0xc7, 0x79, 0x04, 0x22, 0x2d, 0xaa, 0x6d, 0x5c, 0x84, 0x70, 0xae, + 0x25, 0x1e, 0xcf, 0x38, 0xe1, 0xf2, 0xf9, 0x2e, 0x0d, 0xb5, 0x43, 0x6d, 0xa6, 0xcf, 0x20, 0x28, 0x21, 0x50, 0x59, + 0x21, 0xfa, 0x1a, 0x4a, 0xcb, 0xcd, 0x95, 0xf7, 0x70, 0xec, 0x76, 0x2f, 0xa7, 0xa1, 0xb9, 0xdb, 0x82, 0xe3, 0xa3, + 0x88, 0x16, 0x61, 0xad, 0xeb, 0x5e, 0xa1, 0xab, 0x61, 0x0b, 0x3a, 0xea, 0xc3, 0xa9, 0xd0, 0xf7, 0x84, 0x57, 0x15, + 0x49, 0xfd, 0x64, 0x2d, 0xa0, 0x1c, 0x31, 0xac, 0x4c, 0x53, 0xbc, 0xf9, 0x7f, 0xb2, 0xe6, 0x6b, 0xe5, 0x31, 0xc1, + 0xf4, 0x30, 0x6e, 0xcd, 0x2a, 0xb0, 0x35, 0xe0, 0xd8, 0xf2, 0x2f, 0xe1, 0x2d, 0xaa, 0x53, 0x8a, 0xeb, 0x4e, 0x3d, + 0x26, 0xe0, 0x2d, 0x58, 0xcf, 0x6c, 0x6e, 0xfd, 0xe7, 0xfa, 0x60, 0x94, 0x38, 0xaf, 0x11, 0x78, 0xa1, 0x09, 0x3c, + 0x02, 0xc6, 0xcd, 0x99, 0x96, 0xf7, 0xad, 0x11, 0x8d, 0x74, 0x27, 0x9e, 0xc5, 0x33, 0xc3, 0x72, 0x6f, 0x7d, 0x6c, + 0xac, 0x48, 0x2c, 0x09, 0xd8, 0x16, 0x61, 0x4b, 0xe4, 0x05, 0xc2, 0x79, 0xa3, 0xd1, 0xcb, 0xcf, 0x59, 0xa5, 0x55, + 0xa9, 0x86, 0x29, 0xe1, 0x96, 0x18, 0xf0, 0xbe, 0x76, 0xa2, 0xe6, 0x08, 0x97, 0x66, 0xee, 0x39, 0xa8, 0xef, 0x2f, + 0xdf, 0x86, 0x3e, 0x7d, 0xf3, 0xcb, 0x96, 0x17, 0xb1, 0x30, 0xa5, 0xb0, 0xba, 0xc3, 0x79, 0xf3, 0x7d, 0xb3, 0x11, + 0x18, 0xf7, 0x7e, 0x1b, 0x83, 0x8d, 0x1b, 0xea, 0x29, 0x43, 0x1a, 0xca, 0x4d, 0xd8, 0x43, 0x95, 0xbd, 0xa3, 0xdf, + 0x59, 0x4f, 0x55, 0xd2, 0xae, 0x22, 0xf9, 0x7a, 0x2d, 0x59, 0x65, 0x34, 0xb0, 0x61, 0xd8, 0xa9, 0x8f, 0x99, 0x6d, + 0x05, 0xfe, 0xd5, 0x9c, 0x28, 0xec, 0x21, 0xeb, 0x9b, 0x6f, 0x5d, 0xa7, 0x54, 0xc3, 0x84, 0xed, 0x6d, 0xcf, 0xc7, + 0x2b, 0xbe, 0xeb, 0x7c, 0xc4, 0xc2, 0x6e, 0x7d, 0x7d, 0x36, 0xb6, 0xff, 0x8d, 0xb3, 0xd1, 0xaa, 0xed, 0xdd, 0xf1, + 0x08, 0xdc, 0x49, 0xed, 0x78, 0xcc, 0xeb, 0xc7, 0xa3, 0xc0, 0xee, 0xf4, 0xbe, 0xe8, 0xac, 0x56, 0x72, 0xd0, 0x02, + 0xb5, 0x53, 0x10, 0xc0, 0xcf, 0xb6, 0xf9, 0xe9, 0x91, 0x64, 0xa3, 0x43, 0x0e, 0xcb, 0xf3, 0xbe, 0x8d, 0x22, 0x30, + 0xa0, 0x0e, 0xb5, 0xad, 0x97, 0x46, 0x6c, 0x8b, 0x43, 0x16, 0xcb, 0x89, 0x2c, 0xaf, 0xae, 0x60, 0xc4, 0xfa, 0xd8, + 0xb0, 0x02, 0x66, 0xb8, 0xd3, 0xaa, 0xd0, 0x89, 0x9f, 0xff, 0x9a, 0x39, 0xad, 0x1d, 0x31, 0x86, 0x93, 0xa8, 0x59, + 0x31, 0xd8, 0x11, 0x58, 0x86, 0x71, 0x5f, 0x4b, 0xa8, 0xd5, 0xa9, 0x8e, 0x6a, 0x47, 0x12, 0x6e, 0x81, 0xda, 0x6d, + 0x5f, 0x9f, 0x4b, 0xab, 0xd5, 0xce, 0x83, 0x05, 0x17, 0x1e, 0x6e, 0x3f, 0x27, 0xaa, 0x46, 0x52, 0x28, 0xb1, 0x12, + 0x14, 0xce, 0x34, 0xaa, 0x2a, 0x22, 0x06, 0xad, 0x21, 0xf0, 0xa4, 0xbd, 0xe4, 0x5c, 0x54, 0x42, 0x72, 0xd2, 0x68, + 0xa0, 0xac, 0xec, 0x98, 0x0e, 0x64, 0x23, 0x19, 0x62, 0x86, 0x13, 0x23, 0xb0, 0xc0, 0xe9, 0x15, 0x66, 0x55, 0xd7, + 0x83, 0x64, 0x88, 0x70, 0xb1, 0x5a, 0x85, 0x66, 0x68, 0x19, 0x5a, 0xad, 0x32, 0x7f, 0x68, 0x3a, 0x1f, 0x2a, 0xbe, + 0xec, 0x2b, 0xf2, 0x52, 0x9f, 0x87, 0x2f, 0x61, 0x90, 0x0d, 0x12, 0x66, 0x56, 0x25, 0x98, 0x81, 0xe6, 0xaa, 0x21, + 0x06, 0x49, 0xa3, 0x3d, 0xf4, 0x68, 0xd8, 0x20, 0x19, 0x92, 0x6c, 0x0d, 0x96, 0xb3, 0xb9, 0x3d, 0x30, 0xff, 0x82, + 0x83, 0xed, 0x2f, 0x7d, 0xce, 0x98, 0x06, 0xfd, 0x35, 0xd9, 0x54, 0x19, 0x94, 0x78, 0x65, 0x17, 0xd7, 0x95, 0xab, + 0x19, 0x58, 0x94, 0x85, 0xb0, 0xbd, 0x66, 0xee, 0x83, 0xf0, 0x5f, 0x62, 0xbb, 0xa0, 0xa5, 0x11, 0xf7, 0x06, 0xe2, + 0x3b, 0xdb, 0xed, 0x28, 0x8a, 0x68, 0x31, 0xd1, 0x57, 0x22, 0x8e, 0x12, 0xeb, 0x3d, 0x70, 0x6c, 0xc7, 0xe9, 0xf5, + 0x3c, 0x28, 0x3b, 0x1b, 0x12, 0x33, 0x7e, 0xc7, 0xec, 0x38, 0xc7, 0x95, 0x82, 0xee, 0xd6, 0x45, 0x98, 0xc1, 0xd0, + 0xff, 0xe5, 0xc1, 0x9c, 0xd8, 0xc1, 0x18, 0x34, 0xd9, 0x80, 0xdb, 0x37, 0xe0, 0x51, 0xd0, 0x0d, 0xb8, 0x7d, 0x1b, + 0xbe, 0x0e, 0x5a, 0xc9, 0x37, 0x07, 0xe8, 0x91, 0x09, 0x33, 0xd2, 0x2a, 0xc1, 0x1b, 0x66, 0x77, 0x93, 0x23, 0x33, + 0x64, 0x15, 0x0e, 0x57, 0x45, 0x42, 0xb9, 0xb1, 0x17, 0x2a, 0x26, 0xd5, 0xe3, 0xfe, 0x65, 0xfc, 0x12, 0xf9, 0x4a, + 0x83, 0xba, 0x71, 0x0c, 0x60, 0x95, 0xd5, 0xd6, 0xbf, 0x3c, 0x38, 0x00, 0xf3, 0x68, 0x60, 0xed, 0xa2, 0x84, 0xce, + 0xd5, 0xa2, 0x00, 0xfe, 0x2a, 0x77, 0xbf, 0x21, 0x19, 0xdc, 0x4e, 0x74, 0x1a, 0xfc, 0x80, 0x84, 0x39, 0x95, 0x92, + 0x7f, 0x35, 0x69, 0xf6, 0x37, 0x2e, 0x88, 0xc3, 0xe8, 0xdc, 0x70, 0x8a, 0x02, 0xf5, 0x84, 0x45, 0xd7, 0x3a, 0xe4, + 0x9e, 0x7e, 0x65, 0xb9, 0x7a, 0xc9, 0xa5, 0x62, 0x39, 0x00, 0xa0, 0x42, 0x3c, 0x98, 0x52, 0x8e, 0x60, 0xeb, 0xd6, + 0x6a, 0xd1, 0x34, 0xfd, 0x6e, 0x15, 0x55, 0x67, 0x8b, 0xa6, 0x34, 0x4f, 0x33, 0xd3, 0x89, 0x6f, 0x33, 0xe9, 0xec, + 0x44, 0xcb, 0x92, 0xbe, 0xc5, 0x4e, 0xc5, 0x7e, 0x68, 0x5a, 0x1f, 0x4a, 0xe2, 0xce, 0x05, 0x77, 0x96, 0x7e, 0x97, + 0x8f, 0x81, 0x2b, 0xf5, 0x6f, 0xac, 0x82, 0x3f, 0x13, 0xac, 0x3c, 0xf2, 0x1a, 0xd5, 0xc7, 0xe9, 0x50, 0x27, 0xdb, + 0x52, 0x2e, 0x94, 0x46, 0x61, 0x1b, 0x27, 0x85, 0xc6, 0x94, 0xd3, 0x6f, 0x4b, 0x5c, 0xbf, 0xba, 0x63, 0xc4, 0x1d, + 0x1d, 0xf2, 0xdf, 0xa5, 0xd2, 0x68, 0x59, 0x22, 0x18, 0x72, 0x3b, 0xf2, 0x67, 0x09, 0x57, 0xb1, 0x19, 0x57, 0xcf, + 0xd5, 0x2c, 0xdb, 0xf0, 0xc4, 0xe9, 0xfd, 0x5c, 0x5e, 0x23, 0xff, 0x2c, 0xc3, 0x5b, 0x86, 0x9f, 0x30, 0xb8, 0x37, + 0x7e, 0xc6, 0xbd, 0x2a, 0xdb, 0xf7, 0xc5, 0xcf, 0xbc, 0xfb, 0xe2, 0x67, 0x3c, 0xde, 0x2e, 0xea, 0xdd, 0x13, 0x77, + 0xa2, 0xb3, 0xa8, 0x15, 0x38, 0x3e, 0x6a, 0x4a, 0x2b, 0xff, 0x4a, 0xb3, 0x35, 0x70, 0x65, 0x13, 0x07, 0xc6, 0x79, + 0x75, 0x11, 0x8a, 0x59, 0x73, 0x46, 0xc3, 0xe1, 0x7f, 0x6b, 0x9d, 0xec, 0xc9, 0x23, 0x8c, 0x14, 0xf2, 0x86, 0x16, + 0xea, 0x01, 0x6c, 0xb8, 0x62, 0xcb, 0x07, 0x90, 0x12, 0x50, 0xb6, 0xfd, 0x7b, 0x5d, 0x54, 0x8e, 0x07, 0xfd, 0xdc, + 0x38, 0x1f, 0xf9, 0xed, 0x93, 0xa2, 0xe4, 0xea, 0xea, 0x42, 0xc8, 0x9d, 0xd6, 0x12, 0x20, 0x4c, 0x9d, 0x6b, 0x1e, + 0xb3, 0x34, 0x99, 0xc5, 0xcb, 0x75, 0xa9, 0x3a, 0x28, 0x0c, 0x57, 0xc7, 0x11, 0x2e, 0xd6, 0xfa, 0x06, 0xfd, 0x1f, + 0x8e, 0xff, 0xe2, 0x96, 0x46, 0x7e, 0x2a, 0x29, 0xd0, 0xe3, 0xdd, 0xbe, 0x36, 0x3b, 0x48, 0xa4, 0x99, 0x43, 0x69, + 0x29, 0x00, 0x58, 0xad, 0xf1, 0x75, 0xed, 0x70, 0xea, 0x89, 0xb0, 0xb3, 0xf9, 0xa6, 0x21, 0x2c, 0x66, 0xa5, 0x05, + 0x8f, 0xee, 0x66, 0x87, 0xe5, 0xa8, 0x93, 0xc5, 0x55, 0xb9, 0xc7, 0x6a, 0xfd, 0xa2, 0x6f, 0x80, 0xb2, 0x32, 0x44, + 0x5b, 0xad, 0xc2, 0x3a, 0xbc, 0x89, 0xf4, 0xae, 0x41, 0x10, 0x96, 0x9e, 0x01, 0x47, 0x8d, 0xf1, 0x36, 0x75, 0x42, + 0xb4, 0x69, 0xbf, 0xe4, 0x58, 0xf7, 0xda, 0x38, 0x7c, 0x45, 0x83, 0xa9, 0xee, 0x6b, 0x1e, 0xb0, 0x99, 0x5d, 0xd9, + 0x91, 0x07, 0xa1, 0x29, 0x75, 0xc6, 0xb9, 0x95, 0x15, 0xed, 0x0e, 0xf8, 0xa2, 0xef, 0x98, 0xe7, 0x5a, 0xd0, 0x6d, + 0xe7, 0x7b, 0xb6, 0x4d, 0x4f, 0xc4, 0xb7, 0x6c, 0x9b, 0x6a, 0x9c, 0xf0, 0x7e, 0x0b, 0x7d, 0xdf, 0x10, 0xd6, 0xf4, + 0xb5, 0xbb, 0xc8, 0xff, 0x42, 0x77, 0x6d, 0x40, 0x4f, 0x03, 0x66, 0x47, 0x63, 0x3e, 0xa8, 0xf5, 0xfa, 0x53, 0xe9, + 0xbf, 0xa0, 0x6d, 0x85, 0x3e, 0x99, 0x5d, 0x60, 0xc5, 0x4a, 0xed, 0x10, 0x1c, 0xfe, 0xc3, 0xc9, 0x24, 0x13, 0x23, + 0x9a, 0xbd, 0x83, 0x1e, 0xab, 0xdc, 0xe7, 0xf7, 0x69, 0x41, 0x15, 0xb3, 0xb4, 0xa6, 0x1a, 0xc5, 0x3f, 0xdc, 0x1b, + 0xc6, 0x3f, 0xdc, 0x50, 0xee, 0xaa, 0x05, 0xbc, 0x7c, 0x59, 0x36, 0x11, 0x7f, 0x5a, 0x97, 0xfe, 0x56, 0xf9, 0xee, + 0x5e, 0x36, 0x49, 0x9a, 0xca, 0xcb, 0xd9, 0xe6, 0xe1, 0x66, 0x53, 0x61, 0xf8, 0xd7, 0x37, 0x06, 0xbb, 0x4d, 0xe6, + 0xfe, 0xf2, 0xc8, 0xdc, 0x5f, 0x3c, 0xfe, 0x6e, 0x2d, 0x8f, 0xe2, 0x1d, 0x47, 0xc7, 0xda, 0x32, 0xc6, 0x8c, 0xfa, + 0xad, 0x02, 0x83, 0x06, 0x45, 0x2e, 0x3c, 0x6f, 0x87, 0xea, 0xf4, 0x72, 0xf6, 0x47, 0x61, 0xb2, 0x90, 0x4a, 0xcc, + 0x6c, 0xa3, 0xd2, 0xfa, 0x38, 0xe9, 0x4c, 0x50, 0x60, 0xeb, 0x3b, 0xfc, 0xb8, 0xee, 0x46, 0xb6, 0xfc, 0xc2, 0xf3, + 0x34, 0xce, 0xb1, 0x3d, 0x5b, 0x64, 0x2c, 0xd6, 0xc4, 0x99, 0x39, 0x6f, 0xe7, 0xe1, 0x31, 0xcf, 0xb9, 0x9c, 0xb2, + 0x22, 0x2c, 0xd0, 0xf2, 0x5b, 0x9d, 0x15, 0x70, 0x9b, 0x63, 0x3a, 0xc3, 0x69, 0x69, 0x39, 0xa0, 0x22, 0x68, 0x0d, + 0x74, 0x46, 0x33, 0xa6, 0xa6, 0x22, 0x05, 0xc3, 0x97, 0x28, 0x2d, 0xdd, 0xa9, 0x0e, 0x0e, 0xf6, 0xc3, 0x40, 0xeb, + 0x2f, 0xc0, 0x07, 0xdd, 0xcf, 0x41, 0xfd, 0x25, 0x38, 0x06, 0x55, 0x5d, 0x33, 0xb4, 0x64, 0x9b, 0x3e, 0x34, 0x2a, + 0xfa, 0xc2, 0xee, 0x31, 0x47, 0xeb, 0x75, 0x6c, 0x46, 0x1d, 0x8c, 0x39, 0xcb, 0xd2, 0x00, 0x7f, 0x61, 0xf7, 0x71, + 0xe9, 0xb6, 0xae, 0xbd, 0xac, 0xf5, 0x22, 0x06, 0xe2, 0x36, 0x0f, 0x70, 0xd5, 0x49, 0xbc, 0x5c, 0x63, 0x51, 0xf0, + 0x09, 0xe0, 0xe8, 0x2f, 0xec, 0x3e, 0xb6, 0xed, 0x79, 0xae, 0x82, 0x68, 0xe9, 0x40, 0x1f, 0x79, 0xc9, 0xfe, 0x32, + 0x58, 0x81, 0x63, 0xa0, 0xeb, 0x0e, 0x49, 0xad, 0x5c, 0x25, 0x42, 0x22, 0xb4, 0xfe, 0x77, 0xa7, 0x82, 0x17, 0xfe, + 0x39, 0xa7, 0x6a, 0x16, 0xb7, 0x1b, 0x95, 0x18, 0x54, 0xa8, 0x2c, 0x48, 0x3e, 0x86, 0xdc, 0xed, 0x3e, 0xeb, 0xfd, + 0xe0, 0xe9, 0xcc, 0x16, 0xd4, 0x36, 0x1a, 0xa7, 0xfa, 0x17, 0xaa, 0xee, 0xa0, 0x66, 0xaa, 0xaa, 0xb8, 0xf7, 0x31, + 0x04, 0xc0, 0x83, 0xb5, 0x0c, 0xd5, 0x0e, 0xa1, 0x6b, 0x67, 0xa6, 0x3a, 0xa6, 0x24, 0x5c, 0xba, 0x39, 0xc4, 0xdc, + 0x07, 0xa3, 0x5a, 0x03, 0x1a, 0x5a, 0x04, 0x33, 0x96, 0x87, 0x7c, 0x1c, 0xca, 0xad, 0x33, 0x54, 0xe8, 0x33, 0x34, + 0xf2, 0x40, 0xfe, 0x8d, 0x33, 0x93, 0x69, 0x68, 0x68, 0xde, 0x52, 0x1f, 0x80, 0x76, 0x75, 0x2d, 0x0e, 0xf9, 0x2b, + 0x5a, 0x3a, 0xef, 0x99, 0x45, 0x17, 0xb5, 0x61, 0x85, 0xba, 0x1d, 0xb4, 0x8e, 0x61, 0x4a, 0xcc, 0x14, 0x58, 0x3b, + 0xbd, 0x0f, 0x77, 0x76, 0xb5, 0x61, 0x11, 0xb9, 0x69, 0x11, 0x07, 0x93, 0x90, 0xa2, 0x25, 0x0f, 0x29, 0x16, 0x60, + 0x07, 0x59, 0xac, 0xcb, 0xf1, 0x33, 0x7f, 0x39, 0x6a, 0x56, 0xd2, 0xbb, 0x1d, 0x0c, 0x81, 0xcb, 0x57, 0x60, 0x1b, + 0x8a, 0xb9, 0x23, 0x2c, 0x3c, 0xd4, 0x9e, 0x7e, 0xde, 0xba, 0xcd, 0xcd, 0x82, 0xb8, 0x15, 0x18, 0xd3, 0x70, 0xe9, + 0xcd, 0xc2, 0x77, 0x2a, 0xb7, 0x0e, 0x87, 0xf6, 0x9a, 0xb0, 0x32, 0x5e, 0x0d, 0x73, 0xb2, 0x71, 0xf4, 0x7c, 0xdf, + 0xc6, 0xf3, 0xef, 0x05, 0x2b, 0xee, 0xaf, 0x19, 0xd8, 0x58, 0x0b, 0x70, 0x37, 0xae, 0x96, 0xa1, 0x32, 0x90, 0xef, + 0x0b, 0xcd, 0xba, 0xac, 0xf1, 0x77, 0xa3, 0x62, 0xac, 0xf5, 0x3d, 0xa5, 0xa7, 0xad, 0x31, 0xdb, 0x85, 0x7d, 0xd3, + 0x75, 0x93, 0xf5, 0xb4, 0x22, 0xae, 0x82, 0xb4, 0xbd, 0x5b, 0xc0, 0x85, 0xef, 0x0f, 0x3b, 0xc8, 0x87, 0x9b, 0xaa, + 0x1b, 0x48, 0x82, 0x6b, 0x3f, 0xf1, 0xed, 0xa9, 0xee, 0xb2, 0xd6, 0xfd, 0xf6, 0x54, 0x6b, 0x97, 0x85, 0xda, 0x90, + 0x08, 0xdb, 0x7e, 0x4a, 0xff, 0x69, 0xb9, 0x5e, 0xa3, 0x35, 0x0c, 0xef, 0x3d, 0xef, 0x85, 0xe1, 0x7b, 0x67, 0xa1, + 0x18, 0xc1, 0x45, 0xee, 0x75, 0x26, 0x1c, 0x21, 0xaf, 0x46, 0xf0, 0x9e, 0x6f, 0x0d, 0xe1, 0x3d, 0xf7, 0x9c, 0x5e, + 0x41, 0x6a, 0x9a, 0xe4, 0x2c, 0x75, 0xf4, 0x13, 0x19, 0x24, 0xd4, 0x7c, 0xdc, 0x6b, 0x4e, 0xb8, 0xfa, 0x1c, 0x03, + 0xff, 0x85, 0x47, 0x0b, 0xa5, 0x44, 0x8e, 0x79, 0x3e, 0x5f, 0x28, 0x2c, 0xf5, 0xe8, 0x97, 0x63, 0x91, 0xab, 0xe6, + 0x98, 0xce, 0x78, 0x76, 0x1f, 0x2f, 0x78, 0x73, 0x26, 0x72, 0x21, 0xe7, 0x34, 0x61, 0x58, 0xde, 0x4b, 0xc5, 0x66, + 0xcd, 0x05, 0xc7, 0xcf, 0x59, 0xf6, 0x95, 0x29, 0x9e, 0x50, 0xfc, 0x56, 0x8c, 0x84, 0x12, 0xf8, 0xf5, 0xdd, 0xfd, + 0x84, 0xe5, 0xf8, 0xf7, 0xd1, 0x22, 0x57, 0x0b, 0x2c, 0x69, 0x2e, 0x9b, 0x92, 0x15, 0x7c, 0xdc, 0x6b, 0x36, 0xe7, + 0x05, 0x9f, 0xd1, 0xe2, 0xbe, 0x99, 0x88, 0x4c, 0x14, 0xf1, 0x7f, 0xb5, 0x8e, 0xe9, 0xa3, 0xf1, 0x49, 0x4f, 0x15, + 0x34, 0x97, 0x1c, 0x16, 0x26, 0xa6, 0x59, 0xb6, 0x77, 0xdc, 0x6d, 0xcd, 0xe4, 0xbe, 0xb9, 0xf0, 0xa3, 0xb9, 0x5a, + 0x7f, 0xc6, 0x1f, 0x04, 0x8c, 0x32, 0x1a, 0xa9, 0xdc, 0x0e, 0x72, 0x99, 0x2c, 0x0a, 0x29, 0x8a, 0x78, 0x2e, 0x78, + 0xae, 0x58, 0xd1, 0x1b, 0x89, 0x22, 0x65, 0x45, 0xb3, 0xa0, 0x29, 0x5f, 0xc8, 0xf8, 0x64, 0x7e, 0xd7, 0xab, 0xf7, + 0x60, 0xf2, 0xe3, 0x5c, 0xe4, 0xac, 0x07, 0xfc, 0xc6, 0xa4, 0x10, 0x8b, 0x3c, 0xb5, 0xc3, 0x58, 0xe4, 0x92, 0xa9, + 0xde, 0x9c, 0xa6, 0x60, 0x07, 0x1c, 0x9f, 0xcd, 0xef, 0x7a, 0x7a, 0xd6, 0xb7, 0x8c, 0x4f, 0xa6, 0x2a, 0xee, 0xb6, + 0x5a, 0xe6, 0x5b, 0xf2, 0x7f, 0x58, 0xdc, 0xee, 0x44, 0x9d, 0xee, 0xfc, 0x0e, 0x38, 0x78, 0xc5, 0x8a, 0x26, 0xc0, + 0x02, 0x2a, 0xb5, 0xa3, 0xd6, 0xa3, 0xe3, 0x87, 0x90, 0x01, 0x36, 0x0e, 0x4d, 0x3d, 0x21, 0x30, 0x76, 0x8f, 0x17, + 0xf3, 0x39, 0x2b, 0xc0, 0x8b, 0xbe, 0x37, 0xa3, 0xc5, 0x84, 0xe7, 0xcd, 0x42, 0x37, 0xda, 0x3c, 0x9b, 0xdf, 0xad, + 0x61, 0x3e, 0xb1, 0x31, 0x5b, 0xb5, 0xd3, 0xb2, 0x5f, 0x4b, 0x6f, 0x88, 0x3a, 0x26, 0x4d, 0x5c, 0x4c, 0x46, 0x34, + 0x6c, 0x77, 0x1e, 0x62, 0xf7, 0xbf, 0xa8, 0x83, 0x3c, 0xb0, 0x35, 0xd3, 0x45, 0xa1, 0x6f, 0x51, 0xe3, 0xb6, 0x34, + 0xcd, 0x4e, 0xc5, 0x57, 0x56, 0xb8, 0x56, 0xf5, 0xc7, 0x72, 0x6b, 0xde, 0xff, 0x49, 0xa3, 0x9f, 0xf1, 0x84, 0xc2, + 0x1a, 0x68, 0xe4, 0x18, 0x68, 0x79, 0x10, 0x66, 0x3a, 0x5c, 0xde, 0xf2, 0x54, 0x4d, 0xe3, 0x76, 0xab, 0xf5, 0x43, + 0xb5, 0x62, 0xbd, 0xa9, 0x01, 0x5d, 0xbb, 0x60, 0xb3, 0xda, 0x3a, 0xce, 0x68, 0x89, 0x6d, 0xcb, 0xb9, 0xb0, 0x4b, + 0x5e, 0xb0, 0x4c, 0x47, 0x93, 0x59, 0x5b, 0x94, 0xdb, 0x1a, 0x27, 0xcf, 0xa7, 0xac, 0xe0, 0xaa, 0x57, 0xff, 0xaa, + 0x3a, 0xde, 0x5e, 0xfd, 0xb5, 0x91, 0x43, 0x97, 0xa6, 0x86, 0xbd, 0xf4, 0xbc, 0x82, 0x8f, 0xed, 0xd5, 0xff, 0x4a, + 0x8b, 0x70, 0x03, 0x31, 0xb1, 0x5f, 0x03, 0xad, 0xbd, 0x39, 0x17, 0x60, 0x92, 0x39, 0xc4, 0xdf, 0x80, 0x42, 0x42, + 0xb3, 0x24, 0x84, 0x11, 0xed, 0x35, 0xf7, 0x8e, 0x0b, 0x36, 0x43, 0x0e, 0x10, 0xd1, 0xc3, 0x6e, 0xc1, 0x66, 0xeb, + 0x48, 0x57, 0x5f, 0x6a, 0x14, 0xa1, 0x19, 0x9f, 0xe4, 0x71, 0xc2, 0x00, 0x7d, 0xd7, 0x11, 0xcb, 0x15, 0x57, 0xf7, + 0xcd, 0x42, 0xdc, 0x2e, 0x53, 0x2e, 0xe7, 0x19, 0xbd, 0x8f, 0xc7, 0x19, 0xbb, 0xeb, 0xe9, 0x52, 0x4d, 0xae, 0xd8, + 0x4c, 0xda, 0xb2, 0x3d, 0x48, 0x6f, 0xa6, 0xc6, 0x6c, 0x02, 0xa0, 0x27, 0x6e, 0x37, 0xf7, 0x4f, 0x74, 0x2c, 0xf7, + 0x18, 0x95, 0xac, 0x29, 0x16, 0x6a, 0xaf, 0x25, 0x7b, 0x33, 0x9e, 0x37, 0xed, 0x40, 0x4e, 0x5a, 0xf3, 0xbb, 0xde, + 0x36, 0xe4, 0xbd, 0xfe, 0x23, 0x76, 0x37, 0xa7, 0x79, 0xca, 0xd2, 0xa5, 0x57, 0xad, 0x03, 0xf5, 0xfc, 0x52, 0x71, + 0xae, 0xa6, 0x4d, 0x6d, 0xeb, 0x15, 0x76, 0x72, 0xf4, 0x0d, 0xd4, 0x7a, 0xd4, 0xc2, 0xe6, 0xff, 0xa3, 0x36, 0xf2, + 0x2b, 0xef, 0x41, 0xd8, 0x25, 0x3e, 0xbe, 0x6f, 0xc2, 0xdf, 0x25, 0xf8, 0x16, 0xf1, 0x84, 0x66, 0x16, 0x22, 0x33, + 0x9e, 0xa6, 0x59, 0x6d, 0x44, 0x17, 0x5e, 0x67, 0x6d, 0xb4, 0x84, 0xf9, 0xc7, 0xad, 0xbd, 0xd6, 0x9e, 0x9e, 0x8b, + 0xdd, 0xe6, 0x27, 0x27, 0x0f, 0x8f, 0x1f, 0xb1, 0x5e, 0xc6, 0x73, 0x56, 0x9b, 0xea, 0x77, 0x41, 0xed, 0x37, 0xdc, + 0xb1, 0x0d, 0xb7, 0xf7, 0xda, 0x7b, 0x27, 0xad, 0x1f, 0xdc, 0x6e, 0xcd, 0xd8, 0x58, 0xc5, 0xed, 0xd3, 0xf9, 0x5d, + 0x7d, 0xfb, 0x9e, 0xb9, 0xa6, 0x6f, 0x0b, 0x3a, 0x8f, 0x73, 0x01, 0x7f, 0x7a, 0xb0, 0xc9, 0xc6, 0x99, 0xb8, 0x8d, + 0xa7, 0x3c, 0x4d, 0x59, 0x6e, 0x0a, 0x94, 0x89, 0x2c, 0xcb, 0xf8, 0x5c, 0x72, 0xb3, 0x1a, 0x16, 0x77, 0xbb, 0x1b, + 0x50, 0xf5, 0x07, 0x74, 0xec, 0x0d, 0xa8, 0x5b, 0x0d, 0xa8, 0xea, 0xdf, 0x1f, 0x61, 0x67, 0x63, 0xae, 0xba, 0x54, + 0xaf, 0x86, 0x49, 0x7f, 0x2d, 0xa4, 0x02, 0x98, 0x97, 0x46, 0x1a, 0x40, 0xc5, 0x9b, 0x23, 0xa6, 0x6e, 0x19, 0xcb, + 0xbf, 0x3d, 0x88, 0x8b, 0x58, 0xe4, 0xd9, 0xbd, 0xf9, 0x5c, 0xfa, 0x5d, 0xd2, 0x85, 0x12, 0xeb, 0x68, 0xc4, 0x73, + 0x5a, 0xdc, 0xdf, 0x48, 0x96, 0x4b, 0x51, 0xdc, 0x88, 0xf1, 0x78, 0xf9, 0x2d, 0xd2, 0xf2, 0x10, 0xad, 0x23, 0xc9, + 0xf3, 0x49, 0xc6, 0x0c, 0x51, 0xd2, 0x88, 0x60, 0x89, 0xb9, 0x69, 0x57, 0x37, 0x59, 0x1b, 0xb4, 0xbf, 0xf3, 0x74, + 0xbb, 0xc3, 0x38, 0x6e, 0xde, 0xb2, 0xd1, 0x17, 0xae, 0x0c, 0x9e, 0x35, 0xe5, 0x2d, 0x78, 0xbc, 0xe8, 0x65, 0x98, + 0xb3, 0x62, 0xe9, 0x68, 0x78, 0xcb, 0xa3, 0x3a, 0x51, 0x92, 0xf1, 0x19, 0x55, 0xcc, 0xa3, 0x54, 0x65, 0x27, 0x93, + 0x82, 0xa7, 0xdb, 0x38, 0xd2, 0x83, 0xe4, 0xa6, 0x33, 0xa8, 0x82, 0x9e, 0x16, 0xb3, 0x5c, 0xc6, 0x05, 0x9b, 0x33, + 0xaa, 0xc2, 0x63, 0xdc, 0x1e, 0x17, 0xa8, 0x37, 0xa1, 0xf3, 0x18, 0xf0, 0xc2, 0x75, 0xd9, 0x86, 0x25, 0xd8, 0xde, + 0xae, 0xeb, 0xcf, 0xf8, 0x8b, 0xd4, 0x87, 0x97, 0xa2, 0xa3, 0x26, 0x84, 0x1f, 0x63, 0x45, 0xb9, 0xc5, 0x79, 0xae, + 0x11, 0x56, 0xaf, 0xcf, 0xe6, 0x26, 0xf5, 0x8f, 0xa0, 0x93, 0x56, 0xcb, 0xf5, 0xd3, 0x34, 0x75, 0xe2, 0x76, 0xd4, + 0x65, 0xb3, 0x5d, 0xe4, 0xa1, 0x4e, 0x0b, 0xdb, 0x9d, 0xf9, 0xdd, 0x9e, 0xfe, 0xa7, 0xb5, 0xd7, 0xda, 0xa6, 0x7d, + 0xdb, 0xcb, 0x74, 0x8c, 0x1c, 0x62, 0x29, 0x31, 0x8f, 0xdb, 0x6c, 0xd6, 0x5b, 0x48, 0x38, 0xe7, 0x34, 0x69, 0xd6, + 0xe7, 0xe7, 0x5a, 0xcf, 0x04, 0xd0, 0x88, 0xf2, 0x1c, 0x8e, 0x15, 0x73, 0xb4, 0x42, 0x1f, 0x52, 0x80, 0x1d, 0xf8, + 0xce, 0x46, 0xeb, 0xc3, 0x6a, 0xed, 0x55, 0x03, 0x83, 0x7f, 0xd6, 0x9f, 0x2b, 0xc6, 0xf4, 0x05, 0xf3, 0x04, 0x03, + 0xde, 0x88, 0xba, 0xab, 0x96, 0x15, 0x06, 0x52, 0x55, 0xc9, 0x28, 0xda, 0x95, 0x62, 0x46, 0xef, 0x8c, 0x4f, 0xc5, + 0x8c, 0xe7, 0x60, 0xb1, 0x85, 0xb0, 0xf2, 0x6c, 0xdb, 0xa7, 0x7e, 0x43, 0xa9, 0x0a, 0xa1, 0xe1, 0xc3, 0x4e, 0xd4, + 0xed, 0x22, 0xdc, 0xc2, 0x9d, 0x6e, 0xd7, 0x13, 0x46, 0xc6, 0x6a, 0x57, 0xd1, 0x5d, 0x25, 0xf3, 0x1d, 0x25, 0x8f, + 0x74, 0xa3, 0x47, 0xed, 0x56, 0x0b, 0x6b, 0xbf, 0xf1, 0xb2, 0x30, 0xcb, 0x77, 0x34, 0xdb, 0x6e, 0xb5, 0xa0, 0x59, + 0xf8, 0x63, 0xe7, 0xf5, 0x0b, 0x59, 0xb6, 0xe2, 0x16, 0x6e, 0xc7, 0x6d, 0xdc, 0x89, 0x3b, 0xf8, 0x38, 0x3e, 0xc6, + 0x27, 0xf1, 0x09, 0xee, 0xc6, 0x5d, 0x7c, 0x1a, 0x9f, 0xe2, 0x87, 0xf1, 0x43, 0x7c, 0x16, 0x9f, 0xe1, 0x47, 0xf1, + 0x23, 0x7c, 0x19, 0xb7, 0x5b, 0xf8, 0x71, 0xdc, 0x6e, 0xe3, 0xab, 0xb8, 0xdd, 0xc1, 0x4f, 0xe2, 0xf6, 0x31, 0x7e, + 0x1a, 0xb7, 0x4f, 0xf0, 0xb3, 0xb8, 0xdd, 0xc5, 0x14, 0x72, 0x47, 0x90, 0x9b, 0x40, 0x6e, 0x0a, 0xb9, 0x0c, 0x72, + 0xc7, 0x71, 0xbb, 0xbb, 0xc6, 0xd2, 0xc4, 0x9a, 0x08, 0x5a, 0xed, 0xce, 0xf1, 0x49, 0xf7, 0xf4, 0xe1, 0xd9, 0xa3, + 0xcb, 0xc7, 0x57, 0x4f, 0x9e, 0x3e, 0x0b, 0x86, 0x78, 0xa4, 0x5d, 0x3e, 0xa4, 0x1c, 0xf0, 0x83, 0x76, 0x77, 0x88, + 0x6f, 0xdc, 0x67, 0xc8, 0x0f, 0x3a, 0x27, 0x2d, 0x74, 0x71, 0x71, 0x32, 0x6c, 0x94, 0xb9, 0xef, 0xb5, 0xa7, 0x49, + 0x95, 0x45, 0x08, 0x09, 0x21, 0x07, 0xe1, 0x7b, 0x5d, 0xef, 0x3d, 0x0b, 0x79, 0x54, 0xa0, 0x83, 0x03, 0xfd, 0x63, + 0xe2, 0x7e, 0x8c, 0xdc, 0x0f, 0xea, 0x2d, 0xd2, 0x1d, 0x0d, 0xad, 0xab, 0xb1, 0x2a, 0x0d, 0xfd, 0x4b, 0x1b, 0x9a, + 0x3d, 0x6e, 0xad, 0xd9, 0xff, 0x2b, 0x30, 0xd6, 0x2a, 0xe4, 0xc4, 0x68, 0x84, 0xba, 0x7d, 0x46, 0x96, 0x45, 0xdc, + 0xe9, 0x76, 0x0f, 0x7e, 0x19, 0xf0, 0x41, 0x7b, 0x38, 0x3c, 0x6c, 0x3f, 0xc4, 0x93, 0x32, 0xa1, 0x63, 0x12, 0x46, + 0x65, 0xc2, 0xb1, 0x49, 0xa0, 0xb1, 0xa9, 0x0d, 0x49, 0x27, 0x3a, 0x09, 0x4a, 0xac, 0x63, 0xdd, 0xf6, 0x43, 0xd3, + 0xf6, 0x23, 0x30, 0xa3, 0xd2, 0xcd, 0xdb, 0xa6, 0xcf, 0xcf, 0x4f, 0x56, 0xb6, 0x51, 0x3c, 0x89, 0x6d, 0x6b, 0x2e, + 0xf1, 0x64, 0x38, 0xc4, 0x23, 0x9d, 0xd8, 0xad, 0x12, 0x4f, 0x87, 0x43, 0xdb, 0xd5, 0x23, 0xdd, 0xd5, 0xc3, 0x2a, + 0xeb, 0x6c, 0x38, 0xd4, 0x5d, 0x22, 0xeb, 0x34, 0x2f, 0xd5, 0xde, 0xd7, 0x52, 0x71, 0xc1, 0xcf, 0x3b, 0xdd, 0x6e, + 0x1f, 0x30, 0x4c, 0x1b, 0xc3, 0x3a, 0x18, 0xdd, 0x7a, 0x30, 0xba, 0x87, 0xdf, 0xfd, 0x11, 0x8d, 0x6f, 0x68, 0x09, + 0xa4, 0x7e, 0xf0, 0x5f, 0x41, 0x43, 0x69, 0x98, 0xeb, 0x3f, 0x13, 0xf3, 0x67, 0x84, 0x1a, 0x5f, 0x29, 0x80, 0x1b, + 0x54, 0x31, 0x4e, 0x97, 0xaa, 0x7b, 0xfc, 0x42, 0xc1, 0xb7, 0x65, 0x2a, 0x33, 0xda, 0x5f, 0x4d, 0x6f, 0x47, 0xab, + 0xa9, 0xfc, 0x8a, 0xfe, 0x0c, 0xff, 0x94, 0x87, 0xe1, 0xa0, 0xd9, 0x88, 0xd8, 0x9f, 0x29, 0x38, 0xd1, 0xf4, 0xe3, + 0x94, 0x4d, 0x50, 0x7f, 0xf0, 0xa7, 0xc4, 0xc3, 0x86, 0x97, 0xf1, 0xc3, 0x76, 0x0a, 0xb8, 0xd8, 0x6c, 0x26, 0x86, + 0x3f, 0xa0, 0x3e, 0xea, 0xff, 0x29, 0x0f, 0xff, 0x44, 0x0f, 0x8e, 0xaa, 0xb9, 0xfc, 0x2e, 0xec, 0x16, 0xae, 0xe2, + 0xee, 0x1c, 0x96, 0x5b, 0x98, 0xe1, 0x76, 0x93, 0x41, 0x94, 0x32, 0xf0, 0xc1, 0x26, 0xa1, 0x68, 0xf0, 0xa3, 0xe3, + 0x16, 0xfa, 0xa1, 0xdd, 0x01, 0xad, 0x42, 0x53, 0x1e, 0x6e, 0x6f, 0xfa, 0xa2, 0x79, 0x8c, 0x1f, 0x35, 0x0b, 0xdc, + 0x46, 0xb8, 0xd9, 0x76, 0xea, 0xde, 0x41, 0x1e, 0xb6, 0x10, 0xce, 0xc3, 0x33, 0xf8, 0xe7, 0x04, 0x0d, 0xab, 0x0d, + 0x79, 0x4d, 0x37, 0x7b, 0x07, 0x87, 0x51, 0x12, 0xe6, 0x0d, 0x7e, 0x74, 0xda, 0x42, 0x3f, 0x9c, 0xea, 0x8e, 0xd8, + 0xa1, 0xda, 0xd1, 0x95, 0xc0, 0x27, 0x4d, 0x01, 0x1d, 0xb5, 0xca, 0x7e, 0x64, 0xd8, 0x45, 0x58, 0x86, 0xc7, 0xf0, + 0x4f, 0xdb, 0xef, 0xe7, 0xd7, 0xad, 0x7e, 0xf4, 0xbc, 0xdb, 0x38, 0xea, 0x1a, 0xff, 0xd3, 0xdc, 0x5c, 0x06, 0x37, + 0xd8, 0x45, 0x5b, 0xdf, 0x62, 0xb5, 0x8f, 0xe0, 0x03, 0x61, 0x75, 0x48, 0x72, 0xcc, 0x0e, 0xc1, 0x71, 0x15, 0xec, + 0x35, 0xf2, 0xf3, 0xe3, 0x5e, 0xde, 0x68, 0x20, 0x90, 0x0f, 0x0f, 0x49, 0xbb, 0xa9, 0x9a, 0x0c, 0xc3, 0xef, 0x06, + 0x29, 0xa3, 0xa1, 0xc9, 0xaa, 0xd7, 0x2b, 0xdb, 0xab, 0xb9, 0xf2, 0x76, 0xd8, 0x01, 0x62, 0x62, 0x3f, 0x54, 0x4d, + 0x86, 0x8e, 0x64, 0x23, 0x54, 0xe7, 0xac, 0x7f, 0x1a, 0xb7, 0x90, 0xc6, 0xce, 0xbc, 0x1f, 0xb2, 0x26, 0x87, 0xf4, + 0x4e, 0x1c, 0xf2, 0xa6, 0x82, 0x5f, 0x27, 0x1e, 0xb4, 0x24, 0xe0, 0x5d, 0xe5, 0x86, 0x53, 0x1c, 0x75, 0xba, 0x5d, + 0x2c, 0x09, 0x8f, 0x26, 0xfa, 0x57, 0x4e, 0x78, 0x34, 0xd2, 0xbf, 0x04, 0x29, 0xe1, 0x65, 0x7a, 0xc7, 0x05, 0xf1, + 0x56, 0x55, 0xa7, 0x50, 0x58, 0xd0, 0x02, 0x1d, 0x75, 0xdc, 0x7d, 0x38, 0x9e, 0xba, 0x39, 0x80, 0xfc, 0x5f, 0x68, + 0x53, 0x48, 0xd1, 0x2c, 0x70, 0x46, 0xe8, 0x45, 0xd4, 0xed, 0x4f, 0x8f, 0xc2, 0x4e, 0x53, 0x34, 0x0b, 0x14, 0x4f, + 0x8f, 0x74, 0x4d, 0x9c, 0x90, 0x2b, 0x6a, 0x5a, 0xc3, 0x53, 0xb8, 0xc4, 0x4c, 0x48, 0x72, 0x78, 0xda, 0x6a, 0x44, + 0x5d, 0x84, 0x07, 0xc9, 0xaa, 0x85, 0xb3, 0xd5, 0xaa, 0x85, 0xa9, 0xbf, 0x0c, 0xd2, 0x01, 0xa4, 0x54, 0x51, 0x6d, + 0x06, 0xa5, 0xe9, 0xf3, 0x50, 0xc1, 0x85, 0xbc, 0x02, 0x37, 0x17, 0x05, 0x0e, 0x38, 0x31, 0xb7, 0x37, 0x61, 0x48, + 0x87, 0xe5, 0x1b, 0xfb, 0x4a, 0xab, 0x2b, 0xe9, 0xd6, 0xd5, 0x8e, 0xfc, 0x57, 0x19, 0xfe, 0x2e, 0xb0, 0x49, 0xab, + 0x8a, 0xbd, 0xa6, 0xdb, 0xc5, 0x7e, 0xa5, 0x5b, 0xc5, 0xde, 0xec, 0x28, 0x76, 0xbd, 0x5d, 0xec, 0xa3, 0xf0, 0x54, + 0x6c, 0xfc, 0x87, 0xe3, 0xd3, 0x56, 0xe3, 0x18, 0x90, 0xf5, 0xf8, 0xb4, 0x55, 0x15, 0x7a, 0x40, 0xab, 0xb5, 0x52, + 0xe4, 0x0b, 0x35, 0x4e, 0x06, 0xdc, 0x79, 0x3b, 0xeb, 0x85, 0x33, 0xbe, 0xd6, 0xa5, 0x63, 0xf5, 0xa0, 0x0b, 0x46, + 0x1c, 0x52, 0x53, 0x3b, 0x35, 0x38, 0x1d, 0xf6, 0xa7, 0x2c, 0x6c, 0x40, 0x2a, 0x8a, 0xc7, 0xca, 0xfe, 0x42, 0xe5, + 0x5d, 0xee, 0x47, 0x01, 0x49, 0x9d, 0x21, 0xc2, 0x82, 0x34, 0xd4, 0xe0, 0x78, 0xa8, 0xcf, 0xbb, 0x02, 0x7e, 0x9f, + 0xe8, 0xdf, 0xa5, 0x26, 0xc5, 0x7a, 0x22, 0x4c, 0x6f, 0x47, 0x41, 0x5f, 0x92, 0xd7, 0x34, 0xd4, 0xc6, 0xe5, 0x28, + 0x2e, 0x33, 0xe4, 0x57, 0xc8, 0x78, 0x53, 0x66, 0x48, 0x72, 0x25, 0xed, 0x6f, 0xbc, 0x2c, 0x62, 0x30, 0x34, 0xc1, + 0x93, 0x18, 0x8c, 0x4c, 0xf0, 0x28, 0x96, 0xe0, 0x08, 0x41, 0x63, 0xe6, 0x99, 0xaf, 0x5f, 0x5a, 0xd5, 0x95, 0xbe, + 0x6e, 0x25, 0x1a, 0x4b, 0x7b, 0x0c, 0x4e, 0x8a, 0x8f, 0x22, 0x84, 0xbf, 0x0d, 0x85, 0x30, 0x83, 0x36, 0x19, 0xc2, + 0x3c, 0x2a, 0x08, 0xa4, 0x61, 0x1e, 0x4d, 0x08, 0x83, 0x26, 0x79, 0x34, 0x22, 0x6c, 0xd0, 0xf1, 0xd0, 0xe4, 0xa9, + 0x86, 0x1d, 0x00, 0x87, 0xd7, 0x6f, 0xb0, 0x95, 0x69, 0x1c, 0xae, 0xc6, 0xa1, 0x09, 0x49, 0x58, 0x1e, 0xc2, 0x2c, + 0x60, 0x73, 0xea, 0x9f, 0x9d, 0x2a, 0xee, 0x23, 0x8f, 0xa8, 0xa6, 0xde, 0x9f, 0x81, 0xac, 0x86, 0x0f, 0x96, 0x6c, + 0x8d, 0xf7, 0x1e, 0x2c, 0xe5, 0xfa, 0x07, 0xf8, 0x93, 0xdb, 0x3f, 0x4a, 0x9f, 0x7e, 0x6b, 0xf4, 0x39, 0x86, 0x62, + 0x3b, 0x4a, 0xa1, 0xcf, 0xce, 0x0f, 0x2e, 0x27, 0xcb, 0xbb, 0x38, 0x48, 0x69, 0xf1, 0x25, 0xc0, 0x9f, 0xe2, 0x20, + 0x03, 0x46, 0x30, 0xc0, 0x1f, 0xe3, 0xa0, 0x60, 0x01, 0xfe, 0x23, 0x0e, 0x46, 0xd9, 0x22, 0xc0, 0x1f, 0xe2, 0x60, + 0x52, 0x04, 0xf8, 0x3d, 0x68, 0x29, 0x53, 0xbe, 0x98, 0x05, 0xf8, 0xf7, 0x38, 0x90, 0xda, 0x0d, 0x00, 0x5f, 0xc6, + 0x01, 0x63, 0x01, 0x7e, 0x17, 0x07, 0x22, 0x0b, 0xf0, 0x75, 0x1c, 0x88, 0x22, 0xc0, 0x8f, 0xe3, 0xa0, 0xa0, 0x01, + 0xbe, 0x8a, 0x03, 0x28, 0x34, 0x09, 0xf0, 0x93, 0x38, 0x80, 0x96, 0x65, 0x80, 0xdf, 0xc6, 0x01, 0xcf, 0x03, 0xfc, + 0x5b, 0x1c, 0xa8, 0x45, 0xf1, 0xf7, 0x42, 0x70, 0x19, 0xe0, 0xa7, 0x71, 0x30, 0xe5, 0x01, 0x7e, 0x13, 0x07, 0x85, + 0x08, 0xf0, 0xeb, 0x38, 0xa0, 0x59, 0x80, 0x5f, 0xc5, 0x41, 0xc6, 0x02, 0xfc, 0x6b, 0x1c, 0xa4, 0x2c, 0xc0, 0x2f, + 0xe3, 0xe0, 0x9e, 0x65, 0x99, 0x08, 0xf0, 0xb3, 0x38, 0x60, 0x79, 0x80, 0x7f, 0x89, 0x83, 0x64, 0x1a, 0xe0, 0x9f, + 0xe2, 0x80, 0x16, 0x5f, 0x64, 0x80, 0x9f, 0xc7, 0x01, 0xa3, 0x01, 0x7e, 0x61, 0x3a, 0x9a, 0x04, 0xf8, 0xe7, 0x38, + 0xb8, 0x9d, 0x06, 0x6b, 0x9c, 0xe7, 0x64, 0xf9, 0x9a, 0x27, 0xec, 0x0f, 0x16, 0x07, 0xe3, 0xd6, 0xf8, 0x6c, 0x3c, + 0x0e, 0x30, 0xcd, 0x15, 0xff, 0x7b, 0xc1, 0x6e, 0x9f, 0x2a, 0x48, 0xa4, 0x6c, 0x94, 0x3e, 0x0c, 0x30, 0xfd, 0x7b, + 0x41, 0xe3, 0x60, 0x3c, 0xd6, 0x05, 0xfe, 0x5e, 0xd0, 0x19, 0x2d, 0xde, 0xb2, 0x38, 0x78, 0x38, 0x1e, 0x8f, 0xd3, + 0x93, 0x00, 0xd3, 0x7f, 0x16, 0x1f, 0x75, 0x0b, 0xba, 0xc0, 0x88, 0xf1, 0x09, 0xd4, 0xed, 0x8e, 0xbb, 0x69, 0x12, + 0xe0, 0x11, 0x97, 0x7f, 0x2f, 0xe0, 0x7b, 0xcc, 0x4e, 0x92, 0x93, 0x00, 0x8f, 0x32, 0x9a, 0x7c, 0x89, 0x83, 0x96, + 0xfe, 0x95, 0xff, 0xc2, 0xd2, 0xd7, 0x33, 0xa1, 0x75, 0xf8, 0x63, 0x36, 0x4a, 0xd2, 0x00, 0xeb, 0xc1, 0x8c, 0xe1, + 0xef, 0x57, 0xfe, 0x8e, 0xa9, 0x38, 0x38, 0xa3, 0x9d, 0x11, 0xeb, 0x04, 0x78, 0xf4, 0xe6, 0x36, 0x8f, 0x03, 0xda, + 0xed, 0xd0, 0x0e, 0x0d, 0xf0, 0x68, 0x51, 0x64, 0xf7, 0xb7, 0x42, 0xa4, 0x00, 0x84, 0xd1, 0xd9, 0xd9, 0xc3, 0x00, + 0x27, 0xf4, 0x57, 0x05, 0xb5, 0xbb, 0xe3, 0x47, 0x8c, 0xb6, 0x02, 0xfc, 0x0b, 0x2d, 0xd4, 0xc7, 0x85, 0xb4, 0x03, + 0x6d, 0x41, 0x8a, 0x48, 0xde, 0x81, 0x7e, 0x3b, 0x48, 0x3b, 0xa7, 0x8f, 0xda, 0x2c, 0xc0, 0xc9, 0xf5, 0x6b, 0xe8, + 0xed, 0xe1, 0xb8, 0xdb, 0x82, 0x8f, 0x1c, 0x04, 0x45, 0x56, 0x40, 0x23, 0xa7, 0x27, 0x8f, 0xba, 0x2c, 0xd5, 0x89, + 0x92, 0x67, 0x5f, 0xf4, 0xec, 0xcf, 0x60, 0x3e, 0x49, 0xc1, 0x67, 0x52, 0xe4, 0x71, 0x90, 0x26, 0xed, 0x93, 0x63, + 0x48, 0xb8, 0xa7, 0xb9, 0x03, 0xce, 0x1d, 0x54, 0x3d, 0x1b, 0x05, 0xf8, 0xce, 0xa4, 0x9e, 0x8d, 0xf4, 0xc7, 0xe4, + 0xdd, 0xaf, 0xf9, 0x9b, 0x34, 0x0e, 0x46, 0x67, 0x67, 0xa7, 0x2d, 0x48, 0xf8, 0x40, 0xef, 0xe3, 0x80, 0x3e, 0x82, + 0xff, 0x20, 0xfb, 0xe3, 0x33, 0xe8, 0x10, 0x46, 0x78, 0x37, 0xf9, 0xe8, 0xe7, 0x7c, 0x99, 0xd2, 0x2f, 0x3c, 0x0e, + 0x46, 0xe9, 0xe8, 0xe1, 0x29, 0xd4, 0x9b, 0xd1, 0xc9, 0x33, 0x45, 0xa1, 0xdd, 0x56, 0x4b, 0xb7, 0xfc, 0x8e, 0x7f, + 0x65, 0xba, 0x7a, 0xb7, 0x7b, 0x3a, 0xea, 0xc0, 0x08, 0xae, 0x41, 0xc3, 0x01, 0xe3, 0x39, 0x4b, 0x74, 0x83, 0xd7, + 0xc9, 0xd3, 0x34, 0x0e, 0x1e, 0x3d, 0x3a, 0xee, 0x24, 0x49, 0x80, 0xef, 0x3e, 0xa6, 0xa6, 0xb6, 0xce, 0x93, 0x00, + 0xfb, 0x38, 0x60, 0x8f, 0x1e, 0x9d, 0x3e, 0xa4, 0xf0, 0xfd, 0x5c, 0xb7, 0x75, 0x36, 0x1e, 0x25, 0x67, 0xd0, 0xd6, + 0xef, 0x30, 0x9d, 0x93, 0xb3, 0xe3, 0x54, 0xf7, 0xf5, 0xbb, 0x1e, 0x75, 0x67, 0x7c, 0x32, 0x3e, 0xd1, 0x99, 0x7a, + 0xa8, 0xe5, 0xe7, 0x6f, 0x2c, 0x0e, 0x12, 0x96, 0xb6, 0x03, 0x7c, 0x67, 0x17, 0xee, 0xd1, 0x49, 0xab, 0x95, 0x1e, + 0x07, 0x38, 0xbd, 0x9c, 0xcf, 0xdf, 0x6a, 0x08, 0xb6, 0x4f, 0x1e, 0x99, 0x6f, 0xf9, 0xe5, 0x1e, 0x9a, 0x1e, 0x69, + 0xa0, 0xa5, 0x7c, 0xa6, 0x5b, 0x3e, 0x7d, 0x04, 0xff, 0xe9, 0x6f, 0xdd, 0x74, 0xf9, 0x2d, 0xd2, 0x89, 0x59, 0x94, + 0x36, 0x7b, 0xd4, 0x82, 0x1a, 0x63, 0xfe, 0x71, 0x54, 0x70, 0x40, 0xa3, 0x51, 0x07, 0xfe, 0x2f, 0xc0, 0xe3, 0xec, + 0xfa, 0xb5, 0xc5, 0xd9, 0xf1, 0x98, 0x8e, 0x5b, 0x01, 0x1e, 0x8b, 0x8f, 0x52, 0x7d, 0xb8, 0xcc, 0xe3, 0xa0, 0xd3, + 0x39, 0x1b, 0xe9, 0x32, 0x8b, 0x5f, 0x24, 0xd7, 0x78, 0xdc, 0xd2, 0xad, 0x4c, 0xe8, 0x5b, 0x39, 0xba, 0x16, 0xb0, + 0x92, 0xf0, 0x5f, 0x80, 0x27, 0xa0, 0x16, 0xb3, 0xad, 0x9c, 0x99, 0xed, 0x30, 0x79, 0xa7, 0x51, 0x33, 0x7d, 0x08, + 0xf0, 0x72, 0xcb, 0x98, 0x52, 0xda, 0xed, 0xb4, 0x02, 0xac, 0x47, 0x7d, 0xd6, 0x82, 0xff, 0x02, 0x6c, 0x20, 0xa7, + 0xe1, 0x3a, 0xf9, 0xf8, 0xec, 0xe5, 0x6d, 0x1c, 0xd0, 0x74, 0x3c, 0x86, 0x25, 0xd1, 0x93, 0x71, 0xc5, 0xa6, 0x22, + 0x67, 0xf7, 0xbf, 0xde, 0xda, 0xed, 0xa2, 0x13, 0x94, 0x85, 0xce, 0xe9, 0xa3, 0xd1, 0x49, 0x80, 0xdf, 0xa6, 0x9c, + 0xe6, 0xb0, 0x4a, 0x49, 0xda, 0x4d, 0xba, 0x89, 0x4e, 0x98, 0x88, 0x38, 0x38, 0x81, 0x25, 0xef, 0x04, 0x98, 0x7f, + 0xbd, 0xbe, 0x37, 0xe8, 0x06, 0xb5, 0x2d, 0x82, 0x8c, 0x5b, 0xec, 0xf4, 0x2c, 0x09, 0x70, 0x46, 0xbf, 0x3e, 0xfb, + 0xb5, 0x88, 0x03, 0x76, 0xca, 0x4e, 0xc7, 0xd4, 0x7d, 0xff, 0x21, 0xa7, 0xba, 0x46, 0x6b, 0xdc, 0x85, 0xa4, 0xdb, + 0x5c, 0x8f, 0xf5, 0x61, 0x32, 0xd6, 0x18, 0xf2, 0x6a, 0x26, 0xf2, 0xe4, 0xe9, 0x78, 0x2c, 0x0c, 0x16, 0x53, 0xd8, + 0x84, 0x9f, 0x00, 0xda, 0x34, 0x4d, 0xcf, 0xd8, 0x69, 0x80, 0x3f, 0x99, 0x5d, 0x62, 0x27, 0xf0, 0xc9, 0x60, 0x36, + 0xb3, 0xbb, 0xfd, 0x93, 0x01, 0x0a, 0xcc, 0x77, 0x4c, 0xc7, 0x34, 0xed, 0x04, 0xf8, 0x93, 0x86, 0x4b, 0x7a, 0x0c, + 0xff, 0x41, 0x01, 0xe8, 0xec, 0x51, 0x8b, 0xb1, 0x47, 0x2d, 0xfd, 0xe5, 0xe7, 0xd9, 0x99, 0x8f, 0x4e, 0x93, 0x76, + 0x80, 0x3f, 0x59, 0x74, 0x1c, 0x8f, 0x69, 0x0b, 0xd0, 0xf1, 0x93, 0x45, 0xc7, 0x4e, 0x6b, 0xd4, 0xa1, 0xfa, 0xdb, + 0x60, 0xcd, 0xd9, 0xc3, 0x84, 0xc1, 0xe4, 0x3e, 0x19, 0x84, 0x7c, 0xf8, 0xf0, 0xec, 0xec, 0xd1, 0x23, 0xf8, 0xd4, + 0x6d, 0x97, 0x9f, 0x52, 0x5d, 0x66, 0x1a, 0xc9, 0x5a, 0xc9, 0x09, 0xd0, 0xc9, 0x4f, 0x7a, 0x8c, 0xe3, 0xf1, 0x98, + 0xb5, 0x02, 0x9c, 0xf1, 0x19, 0x33, 0x98, 0x60, 0x7e, 0xeb, 0x8e, 0x8e, 0x3b, 0x49, 0x7a, 0xdc, 0x09, 0x70, 0xf6, + 0xf6, 0x99, 0x9e, 0x4d, 0x0b, 0x66, 0xef, 0xb6, 0x9c, 0xc3, 0x9a, 0x19, 0x7d, 0x03, 0x83, 0x84, 0x95, 0x86, 0xca, + 0xef, 0x3d, 0x7a, 0x78, 0x7a, 0x9a, 0xa4, 0x30, 0xd0, 0xf7, 0xd0, 0x2d, 0x80, 0xf1, 0xbd, 0xd9, 0x7c, 0x23, 0xda, + 0xed, 0xc2, 0x74, 0xdf, 0xcf, 0x17, 0xc5, 0xfc, 0x55, 0x1c, 0x3c, 0x3a, 0x7e, 0xd8, 0x4a, 0x47, 0x01, 0x7e, 0x6f, + 0x27, 0x78, 0x9c, 0x8c, 0x8e, 0x1f, 0xb6, 0x03, 0xfc, 0x5e, 0xef, 0xb7, 0x87, 0xa3, 0xd3, 0x33, 0x38, 0x37, 0xde, + 0xcb, 0x79, 0xf1, 0x76, 0xa2, 0x0b, 0x8c, 0xe9, 0x23, 0x68, 0xf6, 0x37, 0xbd, 0x1b, 0xd3, 0x36, 0x6c, 0xe4, 0xf7, + 0x7a, 0x93, 0x69, 0x3c, 0x79, 0xd8, 0xee, 0x9e, 0x75, 0x03, 0x3c, 0xe3, 0x69, 0x0e, 0x04, 0x5e, 0x6f, 0x94, 0x47, + 0xed, 0x47, 0x0f, 0x5b, 0x01, 0x9e, 0xbd, 0x55, 0xc9, 0x47, 0x3a, 0xd3, 0xd4, 0x78, 0x0c, 0x30, 0x9b, 0x71, 0xa9, + 0xee, 0xdf, 0x48, 0x4b, 0x8f, 0x59, 0x3b, 0xc0, 0x33, 0x91, 0x24, 0x54, 0xbe, 0x35, 0x09, 0xa3, 0x6e, 0x80, 0x73, + 0xfa, 0x95, 0xfe, 0x25, 0xdc, 0x66, 0x4a, 0x19, 0x4d, 0x75, 0x9a, 0xc6, 0xe1, 0x00, 0xbf, 0x4b, 0xe1, 0x16, 0x2e, + 0x0e, 0xc6, 0xe9, 0xb8, 0x0b, 0xe0, 0x01, 0x02, 0x64, 0xb0, 0x1b, 0xa0, 0x01, 0x5f, 0xe9, 0xe3, 0x51, 0x1c, 0x9c, + 0x8e, 0xce, 0x58, 0xe7, 0x38, 0xc0, 0x25, 0x35, 0xa2, 0x5d, 0xc8, 0xd7, 0x9f, 0x1f, 0xf5, 0x96, 0x3a, 0x31, 0x09, + 0x1a, 0x40, 0x29, 0x7d, 0xd8, 0x4a, 0x4f, 0x03, 0x3c, 0x7f, 0xcd, 0xdc, 0x1e, 0x63, 0x8c, 0x9d, 0x01, 0x2c, 0x21, + 0x49, 0x23, 0xd0, 0xd9, 0x78, 0xf4, 0xe8, 0x4c, 0x7f, 0x03, 0x18, 0xe8, 0x98, 0x31, 0x00, 0xd2, 0xfc, 0x35, 0x2b, + 0x01, 0x91, 0x8e, 0x1e, 0xb6, 0x80, 0xbe, 0xcc, 0xe9, 0x9c, 0xde, 0xd3, 0xdb, 0xa7, 0x73, 0x3d, 0xa7, 0x71, 0xda, + 0x0d, 0xf0, 0xfc, 0xf9, 0x2f, 0xf3, 0xc5, 0x78, 0xac, 0x27, 0x44, 0x47, 0x8f, 0x02, 0x3c, 0x67, 0xc5, 0x02, 0xd6, + 0xe8, 0xac, 0x7b, 0x3c, 0x0e, 0xb0, 0x45, 0xc3, 0xa4, 0x95, 0x8c, 0xe0, 0x9a, 0x71, 0x31, 0x8b, 0x83, 0x34, 0xa5, + 0xad, 0x14, 0x2e, 0x1d, 0xc5, 0xed, 0xaf, 0x85, 0x41, 0x23, 0xa6, 0xf1, 0xc1, 0xae, 0x21, 0xcc, 0x17, 0xe0, 0xf1, + 0x71, 0xc4, 0x92, 0x84, 0xda, 0xc4, 0xd3, 0xd3, 0xe3, 0x63, 0xc0, 0x3d, 0x33, 0x43, 0x83, 0x20, 0x6f, 0xe4, 0xfd, + 0xa8, 0x10, 0x70, 0x74, 0x01, 0x51, 0x05, 0xb2, 0xfa, 0xe6, 0xfe, 0xb5, 0xa6, 0xab, 0xed, 0xd3, 0x47, 0xb0, 0x00, + 0x92, 0xa6, 0xe9, 0x2b, 0x73, 0xb8, 0x9d, 0x8d, 0x4e, 0xba, 0xed, 0xe3, 0x00, 0xbb, 0x8d, 0x40, 0xcf, 0x5a, 0x0f, + 0x3b, 0x50, 0x22, 0x4f, 0xef, 0x4d, 0x89, 0xf1, 0x09, 0x3d, 0x39, 0x6d, 0x05, 0xd8, 0x6d, 0x0d, 0x76, 0x36, 0xea, + 0x3e, 0x84, 0x4f, 0x39, 0x65, 0x59, 0xa6, 0xf1, 0xbb, 0x0b, 0x70, 0x91, 0xfc, 0x59, 0x4e, 0xe3, 0x80, 0xb6, 0xba, + 0x9d, 0x4e, 0x0a, 0x9f, 0xd9, 0x57, 0x56, 0xc4, 0x41, 0xd2, 0x82, 0xff, 0x02, 0xec, 0xed, 0x24, 0x36, 0x0a, 0xb0, + 0xc6, 0xbb, 0x53, 0xda, 0xd5, 0x7b, 0xdf, 0xee, 0xaa, 0xd6, 0x59, 0x0b, 0x36, 0xac, 0xdd, 0x54, 0xf6, 0x4b, 0xe6, + 0xe2, 0xd6, 0x92, 0x58, 0x1a, 0x60, 0x0f, 0x41, 0xc7, 0x0f, 0xc7, 0x01, 0x76, 0x3b, 0xee, 0xe4, 0xf4, 0xac, 0x03, + 0xa4, 0x4c, 0x01, 0xa1, 0x48, 0x3b, 0xa3, 0x13, 0x20, 0x4d, 0x8a, 0xbd, 0x36, 0x78, 0x12, 0x60, 0xf5, 0x54, 0xaa, + 0x57, 0x71, 0x90, 0x9e, 0x8d, 0xc6, 0xe9, 0x59, 0x80, 0x95, 0x98, 0x51, 0x25, 0x34, 0x05, 0x3c, 0x3e, 0x79, 0x18, + 0x60, 0x8d, 0xe6, 0x2d, 0xd6, 0x4a, 0x5b, 0x01, 0xb6, 0x47, 0x09, 0x63, 0x67, 0x1d, 0x98, 0xd6, 0xcf, 0xcf, 0x15, + 0xe0, 0x72, 0xca, 0x46, 0xc7, 0x01, 0x2e, 0xe9, 0xbd, 0x26, 0x44, 0xf0, 0x25, 0x67, 0xe2, 0x8b, 0x65, 0x3d, 0x80, + 0xd4, 0xb9, 0x0d, 0x0f, 0xcb, 0xf0, 0xf2, 0xd6, 0xa0, 0x11, 0xd5, 0x5b, 0xdc, 0xbb, 0x86, 0x7d, 0x42, 0x43, 0xc7, + 0xb6, 0x73, 0xb2, 0x5c, 0xe3, 0x32, 0xba, 0xe9, 0x17, 0x76, 0x2f, 0xc3, 0x1c, 0x4c, 0xe2, 0x6b, 0x29, 0x32, 0x47, + 0xce, 0x9e, 0xdf, 0xba, 0x6c, 0x82, 0x20, 0x29, 0x49, 0xab, 0x27, 0xcf, 0x9d, 0x1b, 0x69, 0x4f, 0x42, 0xcc, 0x03, + 0x48, 0x2f, 0x08, 0x25, 0x0a, 0x42, 0xc3, 0x18, 0x61, 0xd2, 0x59, 0xd7, 0x6b, 0x99, 0x52, 0x18, 0x7b, 0x7d, 0x4a, + 0xa8, 0x0b, 0x0a, 0x0f, 0x77, 0xc4, 0xf9, 0x40, 0x0c, 0x51, 0x4f, 0x10, 0x1d, 0xe2, 0xf9, 0x45, 0xae, 0xc2, 0x3c, + 0x1f, 0x14, 0x43, 0xdc, 0x3e, 0x45, 0x18, 0x82, 0x27, 0x90, 0x81, 0xb8, 0xb8, 0x68, 0x9f, 0x1e, 0x68, 0xa1, 0xef, + 0xe2, 0xe2, 0xcc, 0xfc, 0x80, 0x7f, 0x87, 0x55, 0xc0, 0x6a, 0x18, 0xdf, 0x63, 0xe6, 0x69, 0xf4, 0x34, 0x7f, 0xfd, + 0x98, 0xad, 0x56, 0xe1, 0x63, 0x46, 0x60, 0xc6, 0xf8, 0x31, 0x8b, 0xf4, 0xa5, 0x85, 0x71, 0x8d, 0x21, 0x03, 0xd0, + 0x9c, 0xb5, 0x30, 0x84, 0x51, 0x77, 0x9c, 0xf7, 0x63, 0x36, 0xe0, 0x75, 0xb7, 0xea, 0x2a, 0x76, 0xf1, 0xc1, 0xc1, + 0xb2, 0x88, 0x95, 0x11, 0x13, 0x94, 0x11, 0x13, 0x94, 0x11, 0x13, 0x54, 0x15, 0x3d, 0xfe, 0xa4, 0x0f, 0x52, 0x8a, + 0x56, 0xb6, 0x58, 0x9e, 0xfa, 0x1d, 0xa8, 0x3d, 0x40, 0x3b, 0xd9, 0xaf, 0x94, 0x1d, 0xa5, 0xae, 0x62, 0xa7, 0x02, + 0x63, 0x67, 0xa2, 0xd5, 0x76, 0x1c, 0xfd, 0x3b, 0xea, 0x8e, 0x97, 0x35, 0xb1, 0xec, 0xdd, 0x4e, 0xb1, 0x0c, 0x56, + 0x52, 0x8b, 0x66, 0xfb, 0x26, 0x10, 0x87, 0x1a, 0x3c, 0xd4, 0x82, 0x59, 0x15, 0x1d, 0xae, 0x01, 0x49, 0x3d, 0x90, + 0x42, 0xce, 0xb4, 0x94, 0x56, 0xa0, 0x38, 0x55, 0x61, 0x01, 0x1a, 0x4a, 0xa7, 0xa0, 0x2c, 0x83, 0x98, 0x36, 0x34, + 0x40, 0x72, 0x23, 0xa3, 0x19, 0x59, 0xad, 0x0b, 0xa2, 0x0b, 0x68, 0xc2, 0xb4, 0xc4, 0x02, 0x0d, 0x48, 0xdd, 0x80, + 0xb4, 0x95, 0x41, 0x9c, 0xb1, 0xd9, 0x27, 0x3a, 0x3b, 0xd7, 0xd9, 0x79, 0x99, 0x2d, 0x5c, 0xb6, 0x11, 0x12, 0x85, + 0xce, 0x16, 0x65, 0x36, 0xc8, 0x6c, 0x78, 0x12, 0xe7, 0x78, 0x14, 0x0b, 0x23, 0xaa, 0x55, 0xb2, 0xd5, 0x5b, 0xea, + 0x6b, 0x73, 0x0f, 0x0e, 0xc2, 0x52, 0x4e, 0xd2, 0x6a, 0xe2, 0x07, 0x4b, 0x1e, 0x15, 0x5a, 0x06, 0xe2, 0xd1, 0xc4, + 0xfe, 0x1d, 0xad, 0x37, 0x65, 0xa5, 0x62, 0x32, 0xfa, 0x46, 0x49, 0xf4, 0xd9, 0x29, 0x51, 0x1f, 0x73, 0x1d, 0xfe, + 0xe6, 0x9c, 0x44, 0xad, 0xd6, 0x71, 0xfb, 0xb8, 0x75, 0xd6, 0xe7, 0x87, 0xed, 0x4e, 0xf4, 0xa8, 0x13, 0x6b, 0x45, + 0xc4, 0x5c, 0xdc, 0x82, 0x02, 0xe6, 0xa8, 0x13, 0x9d, 0xa0, 0xc3, 0x76, 0xd4, 0xea, 0x76, 0x9b, 0xf0, 0x0f, 0x7e, + 0xaf, 0xca, 0x6a, 0x27, 0xad, 0x93, 0x6e, 0x9f, 0x1f, 0x6d, 0x54, 0x0a, 0x79, 0x03, 0x0a, 0xa2, 0x23, 0x5d, 0x09, + 0x43, 0xfd, 0x6a, 0x79, 0x9f, 0x6d, 0xe9, 0x79, 0xde, 0xab, 0x30, 0x37, 0xaa, 0x38, 0x80, 0xaa, 0xfb, 0x9a, 0x68, + 0x20, 0xba, 0xaf, 0x51, 0x19, 0xa2, 0x76, 0x59, 0x80, 0xa8, 0xfd, 0x98, 0x87, 0xb2, 0xc1, 0x0e, 0x43, 0x93, 0xaf, + 0xa0, 0x6e, 0x13, 0xc2, 0xc6, 0xe1, 0x89, 0xcd, 0xcd, 0xfd, 0xdc, 0x09, 0x42, 0xcd, 0x1c, 0x72, 0x47, 0x36, 0x57, + 0xf8, 0xb9, 0x23, 0x84, 0x9a, 0x02, 0x72, 0x69, 0xcc, 0x23, 0x0a, 0x39, 0x2a, 0xa2, 0x4d, 0x0d, 0xc9, 0x6a, 0x51, + 0x9e, 0x33, 0x37, 0x6c, 0x3e, 0x86, 0xe5, 0xd1, 0x04, 0xc5, 0x0a, 0xd2, 0x10, 0x35, 0xaf, 0xd2, 0xe6, 0xb4, 0x70, + 0xa9, 0xc6, 0x81, 0x8c, 0x06, 0xfc, 0x73, 0xc8, 0xf4, 0x7b, 0x13, 0xad, 0xfe, 0xf1, 0x69, 0x2b, 0x6e, 0x83, 0x8f, + 0x34, 0xc8, 0xda, 0xd2, 0xc8, 0xda, 0xd2, 0xc9, 0xda, 0xd2, 0xc9, 0xda, 0x20, 0xc0, 0x7b, 0x7d, 0xff, 0x2d, 0x6a, + 0x76, 0x27, 0xbc, 0x34, 0x62, 0x31, 0x56, 0x0a, 0xa1, 0x5a, 0xad, 0x96, 0x6b, 0x30, 0x31, 0x2a, 0x6b, 0x88, 0xbc, + 0x52, 0x7f, 0x2e, 0x8b, 0xb8, 0x85, 0x27, 0x31, 0x68, 0xb9, 0x5b, 0x98, 0xea, 0xcd, 0xed, 0xa8, 0xc2, 0x66, 0xf8, + 0x9a, 0xbe, 0x53, 0x27, 0x5f, 0x90, 0x63, 0xad, 0x3d, 0x5e, 0x16, 0x31, 0x37, 0x34, 0x83, 0x1b, 0x9a, 0xc1, 0x0d, + 0xcd, 0x80, 0x46, 0x70, 0x59, 0x58, 0x97, 0x8d, 0x28, 0x81, 0x2b, 0x81, 0xc1, 0xf1, 0x10, 0xa2, 0xf7, 0x85, 0x8a, + 0xe8, 0x51, 0x6f, 0x74, 0xde, 0x86, 0x68, 0x65, 0xa6, 0xa4, 0x8a, 0xa8, 0x76, 0xda, 0x2e, 0xc7, 0xfc, 0xaa, 0x86, + 0xf6, 0x11, 0x3c, 0x25, 0x73, 0xa9, 0xc2, 0x16, 0xd8, 0x6c, 0x04, 0x45, 0xd0, 0xd7, 0x64, 0x21, 0xd6, 0x3a, 0x1b, + 0x6b, 0x8b, 0xfd, 0x65, 0xc3, 0x05, 0xd6, 0x50, 0x02, 0xff, 0x01, 0x85, 0x2f, 0xac, 0xf2, 0xc9, 0x2f, 0x4d, 0x4d, + 0xad, 0x9d, 0x98, 0x39, 0x12, 0x7a, 0x60, 0x2f, 0xee, 0x82, 0x3d, 0xf5, 0x25, 0x11, 0xb9, 0xf6, 0x56, 0x24, 0x55, + 0xb8, 0x62, 0xf0, 0xde, 0x25, 0x77, 0x54, 0xfb, 0xb2, 0xbc, 0x30, 0x7f, 0x5e, 0x51, 0xcf, 0xd9, 0xaf, 0x98, 0x8c, + 0x9c, 0x8f, 0xec, 0x8d, 0x0e, 0xea, 0x43, 0xf6, 0xf7, 0x8d, 0x29, 0xb7, 0xfe, 0xda, 0xb4, 0xe5, 0xd6, 0x89, 0x3a, + 0x1b, 0x76, 0xa8, 0x5b, 0xa3, 0xbf, 0x9d, 0xab, 0x5a, 0x31, 0x19, 0x21, 0x8f, 0x66, 0x6b, 0xb0, 0xe6, 0x15, 0xb0, + 0xa4, 0xad, 0x57, 0x7a, 0x30, 0x42, 0xef, 0x7a, 0xcc, 0xeb, 0x62, 0x32, 0xda, 0xf9, 0xe6, 0x88, 0xe9, 0xb1, 0xff, + 0x96, 0x7a, 0x3d, 0x38, 0xd5, 0xf6, 0x94, 0xdd, 0x7d, 0xaf, 0xce, 0xed, 0xce, 0x3a, 0x32, 0xfb, 0x5e, 0x9d, 0xa7, + 0xbb, 0xea, 0xcc, 0xf8, 0x5d, 0xe8, 0xf6, 0x8e, 0xf2, 0xd4, 0xd8, 0xda, 0x3e, 0x68, 0x32, 0x82, 0x20, 0xf1, 0xf0, + 0xd7, 0x84, 0x72, 0xe9, 0x39, 0x12, 0x0e, 0xab, 0x20, 0xfa, 0x51, 0x37, 0x66, 0x98, 0x92, 0xce, 0x61, 0xa1, 0x83, + 0xb9, 0xc8, 0x88, 0x36, 0xf3, 0x88, 0xe2, 0x8c, 0x84, 0x21, 0x3d, 0x4c, 0x20, 0x24, 0x4d, 0xbb, 0x4f, 0xe3, 0x90, + 0x36, 0x12, 0x74, 0x14, 0xb6, 0x1b, 0xf4, 0x30, 0x41, 0xa8, 0xd1, 0x06, 0x9d, 0xa9, 0x20, 0xed, 0x66, 0x06, 0x41, + 0x2a, 0x35, 0x29, 0xce, 0x0e, 0x65, 0x54, 0x34, 0xc4, 0x61, 0x1e, 0x15, 0x8d, 0xa8, 0x8b, 0x65, 0x34, 0x29, 0x93, + 0x27, 0x3a, 0x79, 0x62, 0x92, 0x47, 0x65, 0xf2, 0x48, 0x27, 0x8f, 0x4c, 0x32, 0x25, 0xc5, 0xa1, 0x8c, 0x68, 0x23, + 0x6c, 0x37, 0x0b, 0x74, 0x08, 0x23, 0x70, 0xa3, 0x27, 0xd2, 0x8f, 0x0d, 0xbe, 0xd6, 0xc6, 0x35, 0x73, 0x91, 0xd9, + 0x68, 0x9d, 0x15, 0x90, 0x4a, 0x8f, 0x27, 0xa8, 0xf3, 0xcc, 0x03, 0x13, 0x56, 0xe6, 0x8f, 0x8b, 0x45, 0xb7, 0x4e, + 0x32, 0x91, 0x7b, 0x1e, 0x5d, 0x60, 0x84, 0xfe, 0xc5, 0xfa, 0xb1, 0x00, 0x54, 0xd7, 0x34, 0x9b, 0x4f, 0xe9, 0x96, + 0xdb, 0x6c, 0x31, 0x19, 0xd9, 0x9d, 0x55, 0x36, 0xc3, 0x68, 0x61, 0x62, 0x3c, 0xd7, 0x1d, 0x1c, 0x01, 0xd4, 0xce, + 0xa9, 0x32, 0xa2, 0x5a, 0x49, 0x6e, 0x6a, 0x4c, 0x0a, 0x76, 0x2f, 0x13, 0x9a, 0xb1, 0xb0, 0x3a, 0x80, 0xab, 0x61, + 0x32, 0xf2, 0x02, 0x4c, 0xe1, 0x8b, 0xc3, 0xe8, 0xb8, 0xa1, 0xa2, 0xc9, 0x61, 0xd4, 0x7d, 0xd4, 0x50, 0xd1, 0xe8, + 0x30, 0x6a, 0xb7, 0x2b, 0x9c, 0x8d, 0x0a, 0xa2, 0xa2, 0x09, 0x51, 0xa0, 0x31, 0x34, 0x8d, 0x8a, 0x39, 0x05, 0xdb, + 0xae, 0x7f, 0x63, 0x18, 0x0d, 0x3b, 0x8c, 0x9c, 0x4d, 0x4c, 0xb8, 0xcb, 0xad, 0x31, 0xf8, 0xdd, 0x74, 0xba, 0xdd, + 0xa6, 0x8a, 0x0a, 0xac, 0xcc, 0x4a, 0x36, 0x55, 0x34, 0xc1, 0xca, 0x2c, 0x5f, 0x53, 0x45, 0x23, 0xd3, 0x94, 0xd6, + 0x01, 0x82, 0xde, 0xb1, 0x04, 0xd6, 0x73, 0xe6, 0x41, 0xbe, 0xe3, 0xbc, 0x53, 0xd6, 0xa0, 0x35, 0xfc, 0x5e, 0xb9, + 0xa6, 0x2b, 0x28, 0xa9, 0x02, 0x1b, 0x1f, 0xf6, 0xad, 0xa2, 0xed, 0xaa, 0x49, 0xf6, 0xaf, 0xcb, 0x96, 0xcd, 0x16, + 0x42, 0xd5, 0x0b, 0x5e, 0xd6, 0x30, 0xc4, 0x96, 0xb2, 0x07, 0xf7, 0x3f, 0x94, 0x84, 0x10, 0xd4, 0x4e, 0x9f, 0x42, + 0x9c, 0x38, 0x3d, 0x32, 0x24, 0xf1, 0x46, 0x63, 0x8d, 0x42, 0xef, 0xbc, 0x7d, 0xea, 0x53, 0xd5, 0xad, 0x48, 0x77, + 0x84, 0x04, 0x8b, 0xdc, 0xd8, 0x42, 0xa6, 0x81, 0xc7, 0x82, 0x58, 0xed, 0x6e, 0xed, 0x80, 0x38, 0x38, 0xd8, 0x3c, + 0x2f, 0xdc, 0x9b, 0x03, 0x5b, 0xef, 0x0c, 0x54, 0x86, 0x74, 0xee, 0x25, 0x24, 0x63, 0x62, 0xcb, 0x3d, 0x44, 0x71, + 0x31, 0xa7, 0x1e, 0x6a, 0x0a, 0x3f, 0xa8, 0x02, 0xee, 0xd9, 0x9c, 0xe6, 0xa9, 0xce, 0xd0, 0x7d, 0x0d, 0xbd, 0xb1, + 0xbd, 0xf1, 0x27, 0x54, 0x1a, 0x09, 0xfe, 0xcb, 0x8e, 0xbd, 0x4e, 0xec, 0x4b, 0x2d, 0x7e, 0xa3, 0x7f, 0xf9, 0x26, + 0xb9, 0x15, 0x6c, 0xac, 0x33, 0xf6, 0x6a, 0x55, 0x7b, 0x97, 0xc7, 0xbc, 0xfe, 0x82, 0x0e, 0x0e, 0xb8, 0x7c, 0x06, + 0x56, 0xc4, 0x2c, 0x6c, 0xf8, 0x87, 0xef, 0xdf, 0xb5, 0xd3, 0xfa, 0x2f, 0x7d, 0xae, 0xc6, 0xde, 0x41, 0x77, 0x59, + 0xcb, 0xdf, 0xb9, 0x12, 0x7d, 0x15, 0x73, 0xbb, 0xd6, 0x7f, 0x55, 0x36, 0xda, 0x5b, 0x2f, 0x44, 0x1d, 0x1c, 0xf0, + 0x2a, 0x4e, 0x53, 0xf0, 0x43, 0x80, 0xfa, 0x5a, 0x06, 0x79, 0x96, 0x09, 0x0a, 0x37, 0xa2, 0x70, 0xc5, 0x10, 0x37, + 0xf8, 0x91, 0xc2, 0x7f, 0x88, 0xff, 0x4f, 0x8d, 0x1c, 0xaa, 0xb8, 0xc1, 0x3d, 0x01, 0xcc, 0x67, 0x85, 0xaa, 0x08, + 0x89, 0x1a, 0xd2, 0xbe, 0xc9, 0x35, 0x2a, 0x0f, 0x73, 0x3a, 0x9f, 0x67, 0xf7, 0xfa, 0x91, 0x2c, 0x8f, 0xa3, 0xaa, + 0x2e, 0x9a, 0x6c, 0x78, 0x3a, 0x5c, 0x00, 0x4f, 0x0f, 0xb8, 0x87, 0xb4, 0x7b, 0x69, 0x79, 0xb9, 0x2d, 0x11, 0x48, + 0x66, 0x39, 0x11, 0xcd, 0x76, 0x2f, 0xbf, 0x00, 0xb9, 0xac, 0xd9, 0x44, 0xca, 0x46, 0xed, 0xc6, 0x1c, 0x64, 0xb2, + 0xdc, 0xb8, 0x90, 0xee, 0x99, 0x82, 0x20, 0xb9, 0x09, 0x2d, 0xb2, 0xed, 0x2e, 0xc5, 0xc7, 0x21, 0xa0, 0x11, 0x32, + 0x02, 0x9f, 0x2f, 0x2c, 0x72, 0xe0, 0x3a, 0x0b, 0xd7, 0xf1, 0x37, 0x5a, 0x2a, 0x06, 0xf9, 0x70, 0x88, 0x0b, 0xfd, + 0x2e, 0x44, 0x39, 0x1f, 0xb8, 0x69, 0x2a, 0xdf, 0x19, 0xf2, 0x44, 0x14, 0xbe, 0x5a, 0xed, 0xc3, 0x33, 0x3e, 0xb6, + 0x4d, 0xf0, 0x39, 0xb5, 0x3f, 0xab, 0x27, 0x3b, 0x60, 0x1c, 0x8c, 0xb4, 0xf4, 0x45, 0xa1, 0x95, 0x37, 0xd9, 0xb9, + 0xec, 0x35, 0x1a, 0x4c, 0x47, 0x58, 0x22, 0x10, 0x4e, 0x0d, 0x1c, 0x02, 0xe1, 0x8f, 0x09, 0x9a, 0x24, 0x99, 0x09, + 0x3d, 0x07, 0x31, 0xb1, 0x6b, 0x09, 0xab, 0x55, 0x6e, 0x42, 0x9b, 0xe8, 0x1c, 0x13, 0xe4, 0xa4, 0xec, 0xa7, 0x8c, + 0xa1, 0x5a, 0x99, 0x71, 0x70, 0xbb, 0xd5, 0xdf, 0x56, 0xfb, 0x79, 0x8f, 0x9b, 0x6b, 0x3c, 0xae, 0x03, 0x06, 0x68, + 0x40, 0x2d, 0x37, 0x36, 0xb8, 0x31, 0x70, 0x0f, 0x8d, 0x35, 0x2e, 0xdb, 0x84, 0xa0, 0x2c, 0x1d, 0xe4, 0xcd, 0xcd, + 0xad, 0x0b, 0x18, 0x98, 0xeb, 0x39, 0xe5, 0x48, 0x0d, 0x40, 0x8e, 0x1e, 0x12, 0xe8, 0xdc, 0xfc, 0xac, 0xe8, 0x42, + 0x25, 0x13, 0x97, 0x63, 0xfc, 0xc5, 0xbb, 0xcd, 0x1b, 0x04, 0x37, 0x37, 0x7a, 0x93, 0xdf, 0xdc, 0x04, 0xd8, 0xb7, + 0x2a, 0x0f, 0x3c, 0x5e, 0x30, 0x18, 0x96, 0x31, 0xa5, 0xf4, 0xc6, 0x6f, 0xb6, 0xab, 0xc6, 0xde, 0xd3, 0x0a, 0xef, + 0x60, 0x79, 0x74, 0xe3, 0x5b, 0x5e, 0x98, 0x03, 0x0e, 0xf0, 0x66, 0x03, 0x3e, 0xec, 0xbd, 0x09, 0x73, 0x74, 0x70, + 0xf0, 0x26, 0x14, 0xa8, 0x7f, 0xcd, 0xf4, 0x9d, 0x1b, 0xb8, 0x61, 0x0f, 0xb8, 0x1e, 0xbe, 0xf0, 0x10, 0xe0, 0x9a, + 0x6d, 0x4a, 0x36, 0x6f, 0x75, 0xd0, 0x8b, 0x18, 0x82, 0x6a, 0x43, 0x68, 0x5f, 0x0b, 0x12, 0xe8, 0xf5, 0x8d, 0x0f, + 0xed, 0x1e, 0x23, 0x0c, 0x58, 0xf8, 0xd2, 0x49, 0x8e, 0x45, 0x33, 0x56, 0x4c, 0x58, 0xb1, 0x5a, 0xbd, 0xa7, 0xc6, + 0xf1, 0x6d, 0x23, 0x46, 0x63, 0xde, 0x6b, 0x34, 0xa8, 0x1e, 0x3f, 0x88, 0x0f, 0x74, 0x88, 0xf7, 0xdf, 0x84, 0x05, + 0x42, 0x60, 0x61, 0xc4, 0xf3, 0x85, 0x73, 0xf2, 0x4a, 0x6a, 0xeb, 0x52, 0xa0, 0xb2, 0x91, 0x8c, 0xb4, 0xf0, 0x94, + 0x24, 0xe5, 0x1a, 0x9d, 0x4f, 0x7b, 0x8d, 0x46, 0x86, 0x44, 0x98, 0x0c, 0xb2, 0x21, 0xe6, 0xb8, 0x80, 0xcb, 0xd4, + 0xed, 0x75, 0x98, 0xb3, 0x1a, 0xe5, 0xb2, 0xf3, 0x5d, 0x9a, 0xb1, 0xc6, 0x8f, 0xe9, 0xda, 0x03, 0xc6, 0x63, 0xea, + 0x11, 0x89, 0x5d, 0x40, 0x96, 0x06, 0xc8, 0xb9, 0x03, 0xb2, 0xd4, 0x40, 0xce, 0x51, 0x7f, 0x0e, 0xd1, 0x8a, 0x72, + 0x14, 0x6f, 0x51, 0xf4, 0x7a, 0x5c, 0x4d, 0xeb, 0xb3, 0x81, 0xb9, 0x0e, 0xed, 0x60, 0x97, 0x03, 0x1e, 0x3a, 0xb1, + 0x6e, 0x80, 0x39, 0x59, 0x06, 0x81, 0x0e, 0x31, 0x8b, 0xef, 0xf4, 0x9f, 0xe8, 0x0e, 0xdf, 0x9b, 0x1f, 0xf7, 0x9e, + 0x32, 0xe9, 0x79, 0x4d, 0xdb, 0xc0, 0x6d, 0x40, 0xb6, 0x20, 0x0a, 0x00, 0xad, 0x6d, 0x74, 0x41, 0x59, 0x7f, 0x70, + 0x2d, 0x37, 0x71, 0x20, 0x64, 0x83, 0xe4, 0x58, 0x7a, 0xa4, 0xf3, 0xcf, 0x3f, 0x03, 0xd4, 0x97, 0x10, 0xc6, 0xc7, + 0x9e, 0x6c, 0xcd, 0x36, 0x6a, 0x04, 0x51, 0x10, 0x87, 0x2e, 0x4a, 0x04, 0xec, 0x8c, 0x20, 0xf0, 0x1e, 0x5b, 0x29, + 0x87, 0xf1, 0xa1, 0x36, 0x0c, 0x3d, 0xa8, 0x2a, 0xee, 0xc5, 0xc5, 0x72, 0x33, 0xca, 0x90, 0x86, 0xaa, 0xd4, 0x21, + 0x5e, 0x90, 0x79, 0x81, 0x8c, 0x11, 0x76, 0x70, 0xc0, 0x06, 0x72, 0xe8, 0x3d, 0x29, 0x56, 0x5d, 0x87, 0x2b, 0x7f, + 0xe1, 0x42, 0x9a, 0x0f, 0xd4, 0x70, 0xb5, 0x32, 0x7f, 0xc9, 0x07, 0x2d, 0xcd, 0xc0, 0xdb, 0x70, 0xde, 0x6d, 0xbc, + 0xdc, 0x2d, 0x8b, 0x45, 0x4a, 0xfc, 0x0e, 0x56, 0x83, 0x2e, 0x68, 0x9f, 0x9d, 0x6a, 0xdb, 0x41, 0x7d, 0xae, 0x35, + 0x0a, 0x5e, 0xc8, 0xdc, 0xea, 0x48, 0xc3, 0x73, 0xe5, 0xe7, 0xd5, 0x42, 0xdf, 0x26, 0x79, 0x19, 0xc1, 0x14, 0x8e, + 0x94, 0x08, 0xcc, 0xc6, 0x35, 0x9d, 0x84, 0x1f, 0x75, 0x2a, 0x69, 0x59, 0x48, 0x80, 0x02, 0x47, 0xfa, 0x72, 0x5e, + 0x47, 0xa8, 0x67, 0x68, 0x07, 0x91, 0xf3, 0x4c, 0x68, 0xea, 0xb2, 0xa5, 0x0d, 0x25, 0x15, 0xcc, 0xc4, 0x42, 0xb2, + 0xc5, 0x1c, 0xce, 0xf7, 0x32, 0x2d, 0xc9, 0x78, 0xf2, 0xa5, 0x9e, 0x02, 0xe6, 0x9f, 0x77, 0x6a, 0xc6, 0xf2, 0x45, + 0x60, 0xe7, 0xf9, 0xca, 0x88, 0xfb, 0x6f, 0x5e, 0xe0, 0xc7, 0xa4, 0x73, 0xf8, 0x0a, 0x7f, 0xa4, 0xe4, 0x71, 0xe3, + 0x15, 0x9e, 0x70, 0x62, 0x78, 0x83, 0xe8, 0xcd, 0xeb, 0xeb, 0x17, 0xef, 0x5e, 0xbc, 0x7f, 0x7a, 0xf3, 0xe2, 0xd5, + 0xb3, 0x17, 0xaf, 0x5e, 0xbc, 0xfb, 0x88, 0xff, 0xa6, 0xe4, 0xd5, 0x51, 0xfb, 0xac, 0x85, 0x3f, 0x90, 0x57, 0x47, + 0x1d, 0x7c, 0xa7, 0xc8, 0xab, 0xa3, 0x13, 0x9c, 0xe5, 0xe4, 0xd5, 0x61, 0xe7, 0xe8, 0x18, 0x2f, 0x94, 0x69, 0x32, + 0x13, 0x93, 0x76, 0x0b, 0xff, 0x6d, 0xbf, 0x40, 0xbc, 0xaf, 0x66, 0x31, 0x61, 0x9b, 0xc6, 0x0f, 0x50, 0x86, 0x8e, + 0xa4, 0x36, 0x44, 0x39, 0xf7, 0xd0, 0x69, 0x9a, 0xfb, 0xe8, 0x64, 0x62, 0x28, 0x83, 0x0d, 0x23, 0xa0, 0x15, 0x27, + 0xb6, 0x1d, 0x7e, 0xd4, 0x66, 0xc7, 0x40, 0x9f, 0x78, 0x29, 0x1c, 0x97, 0x2a, 0x9c, 0xb6, 0xd5, 0x62, 0x8c, 0x33, + 0x21, 0x8a, 0x70, 0x01, 0x8c, 0x80, 0xd6, 0x5a, 0xf0, 0xa3, 0x32, 0x58, 0x93, 0x3c, 0x27, 0xed, 0x7e, 0x3b, 0x96, + 0xe7, 0xa4, 0xd3, 0xef, 0xc0, 0x9f, 0x6e, 0xbf, 0x1b, 0xb7, 0x5b, 0xe8, 0xd0, 0x1b, 0xc7, 0x1f, 0x35, 0xb4, 0x1e, + 0x0c, 0xb1, 0xed, 0x42, 0xfe, 0x5d, 0x28, 0xa7, 0xd2, 0x93, 0x56, 0x1d, 0xdb, 0xee, 0xc9, 0x73, 0xa6, 0xf5, 0xb0, + 0xfc, 0x07, 0x40, 0x6d, 0xed, 0x4f, 0x52, 0x6e, 0x1c, 0xfb, 0x8b, 0x1f, 0x49, 0x54, 0x8b, 0x08, 0x13, 0xb2, 0x55, + 0x0b, 0x01, 0xd3, 0xa8, 0xb3, 0xc1, 0x1c, 0x28, 0x92, 0xa2, 0x50, 0x2e, 0xaa, 0x7d, 0xde, 0x14, 0x28, 0x9a, 0x8b, + 0x79, 0x58, 0x53, 0x35, 0xfc, 0xea, 0x99, 0x39, 0xee, 0x73, 0xf9, 0x8a, 0xbe, 0x0a, 0x6b, 0x3c, 0x8f, 0xcf, 0xda, + 0xf9, 0xdb, 0xe2, 0x17, 0x6b, 0x45, 0x51, 0x03, 0x57, 0x09, 0x58, 0x37, 0xaa, 0xa6, 0x3a, 0x87, 0xe7, 0xfb, 0x58, + 0x43, 0x5d, 0x10, 0x8f, 0x7a, 0xfe, 0x54, 0x9a, 0x71, 0x95, 0xca, 0x68, 0xa7, 0x88, 0xd6, 0x66, 0x41, 0x4e, 0x11, + 0x7d, 0x9e, 0x6b, 0x20, 0x08, 0xc2, 0x07, 0x72, 0x08, 0x07, 0xbe, 0x19, 0xa0, 0xd0, 0x74, 0x0e, 0xd4, 0x4a, 0x95, + 0x99, 0x90, 0xfe, 0xd4, 0xb1, 0x09, 0x40, 0xf3, 0x54, 0xa9, 0xa0, 0xf4, 0x27, 0x16, 0xc8, 0x1b, 0xfa, 0x6f, 0xfe, + 0x06, 0x38, 0x0c, 0x35, 0x2a, 0xfa, 0x76, 0x35, 0xb2, 0x9e, 0xdf, 0x3e, 0x6b, 0x1d, 0xbd, 0xf2, 0xf2, 0xd3, 0xdc, + 0xd9, 0x7b, 0xfc, 0xe5, 0x51, 0x72, 0x13, 0x4d, 0xab, 0x8d, 0x5d, 0x20, 0xb4, 0x9e, 0x0f, 0x90, 0x43, 0x85, 0x8e, + 0xf4, 0x4b, 0x86, 0x3d, 0xa4, 0x0e, 0x49, 0xbb, 0x05, 0xd1, 0xcb, 0x76, 0x50, 0xbe, 0x9f, 0x36, 0x60, 0xaa, 0xa2, + 0xbb, 0x26, 0xd0, 0x6a, 0x78, 0xdc, 0xe8, 0xbe, 0xc9, 0xa3, 0x7b, 0x9c, 0x7b, 0x38, 0xc3, 0x0e, 0x59, 0x43, 0x1e, + 0x4a, 0x64, 0xa3, 0xbe, 0x9a, 0x0d, 0xa0, 0x68, 0xde, 0x31, 0x8f, 0xec, 0x39, 0xe3, 0xa8, 0xf3, 0x66, 0xd4, 0x3d, + 0x7c, 0x75, 0x70, 0x10, 0x8a, 0x06, 0x79, 0x8c, 0xf0, 0x92, 0x82, 0x11, 0x35, 0x38, 0x9d, 0x71, 0xc3, 0xc4, 0xc7, + 0xb9, 0x47, 0x1d, 0x17, 0x79, 0xed, 0x58, 0xab, 0x3a, 0x2b, 0x77, 0x83, 0x1b, 0x53, 0x07, 0x35, 0xbc, 0x34, 0x33, + 0xba, 0x4e, 0x0d, 0xca, 0x35, 0x0f, 0x31, 0xd8, 0x96, 0x8d, 0x8f, 0x14, 0xfd, 0xf0, 0xb8, 0xf9, 0xca, 0x9b, 0x70, + 0xcd, 0x34, 0xe9, 0x71, 0xe3, 0x31, 0xfa, 0xe1, 0xb1, 0xe7, 0xe3, 0xc7, 0x2b, 0xf6, 0xc4, 0x71, 0x23, 0x3f, 0x19, + 0xae, 0xf4, 0x27, 0x90, 0xec, 0x0b, 0xf2, 0x13, 0x60, 0x39, 0x25, 0x3f, 0x85, 0xa2, 0x99, 0x83, 0x41, 0xd7, 0x4f, + 0x61, 0x01, 0x3f, 0x32, 0xf2, 0x53, 0x08, 0xd8, 0x8e, 0xa7, 0xfa, 0x47, 0x51, 0xbd, 0xae, 0x0a, 0x6a, 0x14, 0xe3, + 0x5e, 0x56, 0xac, 0x56, 0xf2, 0xe0, 0x40, 0x98, 0x5f, 0xf4, 0x22, 0x39, 0x38, 0xc8, 0xce, 0xa7, 0x9e, 0xed, 0xad, + 0xda, 0x45, 0x5f, 0x34, 0x42, 0x61, 0xcf, 0x34, 0x8d, 0xfb, 0x33, 0xfe, 0xe4, 0x53, 0x56, 0xdd, 0x40, 0xf3, 0xb8, + 0xf3, 0xf0, 0xf4, 0x0c, 0xc3, 0xbf, 0x0f, 0xbd, 0x82, 0x3f, 0x97, 0x7c, 0x17, 0x69, 0xb3, 0xe6, 0x69, 0x85, 0x6c, + 0x17, 0x1e, 0x3e, 0x63, 0x86, 0x9a, 0xf2, 0xe0, 0x80, 0x9f, 0x7b, 0xb8, 0x8c, 0x19, 0x6a, 0x78, 0x16, 0x7b, 0x0f, + 0x4a, 0x7b, 0x32, 0xcd, 0x35, 0xc1, 0xab, 0xb6, 0x7c, 0x50, 0x0c, 0xcf, 0x95, 0xa5, 0x26, 0x7e, 0xec, 0xeb, 0x9c, + 0xb4, 0xec, 0x26, 0xeb, 0xc9, 0x66, 0x7e, 0xd1, 0xee, 0x21, 0x41, 0xf2, 0x86, 0xbc, 0xb8, 0x68, 0x63, 0x50, 0xc9, + 0xf7, 0x73, 0x22, 0x62, 0x49, 0x9c, 0x7f, 0xde, 0x32, 0x13, 0x71, 0x8e, 0xa7, 0x3c, 0x2e, 0xe5, 0xec, 0xd7, 0xce, + 0x7a, 0x5a, 0x7b, 0x4c, 0xea, 0x9e, 0x19, 0x96, 0xfd, 0xbc, 0xf4, 0xf4, 0x83, 0x4d, 0x9a, 0x0f, 0xe1, 0xd1, 0xc0, + 0x12, 0xf3, 0x98, 0x71, 0x6f, 0x63, 0x10, 0x94, 0x39, 0x6f, 0xb4, 0x21, 0x13, 0x3e, 0xd7, 0x71, 0x0e, 0x03, 0xd5, + 0x85, 0xcf, 0x81, 0x4c, 0x25, 0x95, 0x61, 0xb6, 0x6b, 0x18, 0x0a, 0x48, 0x28, 0x70, 0x41, 0x98, 0x27, 0xc1, 0xc3, + 0xed, 0x87, 0x47, 0x38, 0xea, 0xe4, 0xc2, 0x4c, 0xee, 0x3c, 0x87, 0xee, 0xe4, 0xf0, 0x5c, 0xf5, 0x90, 0x6c, 0x34, + 0x2c, 0xb7, 0x7d, 0x21, 0xf5, 0x20, 0x9a, 0xed, 0xe1, 0x05, 0xeb, 0xa1, 0xbc, 0xd9, 0x2c, 0x0d, 0x20, 0x2f, 0x5a, + 0xab, 0x55, 0x7e, 0xee, 0x1a, 0xe9, 0xbb, 0x73, 0x5c, 0xf3, 0x5d, 0x4e, 0xf0, 0xfc, 0x4d, 0x90, 0x41, 0x00, 0x54, + 0x15, 0xf8, 0x6c, 0x31, 0x0f, 0x70, 0xa0, 0xdf, 0x93, 0x83, 0xbf, 0xfa, 0x1d, 0xb0, 0x00, 0x07, 0xf6, 0x89, 0xb9, + 0x60, 0x58, 0x0d, 0x96, 0x27, 0x65, 0x74, 0x74, 0x1e, 0xdd, 0x00, 0xe3, 0xa0, 0xfe, 0x02, 0x4e, 0xbb, 0xfc, 0x1d, + 0x65, 0x36, 0x4e, 0x88, 0x74, 0xaf, 0x9e, 0xd9, 0x51, 0xad, 0x77, 0x7b, 0x66, 0x72, 0x1c, 0xb8, 0xaa, 0xf0, 0x7a, + 0xc0, 0x77, 0x9e, 0x5d, 0x6c, 0xdb, 0xd7, 0xbe, 0x97, 0x65, 0x0f, 0xc0, 0x79, 0xaf, 0xd7, 0x08, 0xff, 0x26, 0x76, + 0x3e, 0xfd, 0x1b, 0xdc, 0x88, 0xfc, 0x09, 0x55, 0x34, 0x68, 0xbc, 0xd6, 0x86, 0x6f, 0x46, 0xce, 0xea, 0x7d, 0x6b, + 0x1c, 0xec, 0xdf, 0xea, 0x1e, 0x22, 0x37, 0xd4, 0x5e, 0x29, 0x32, 0xb2, 0xaf, 0x8e, 0xd7, 0x21, 0x3c, 0xd3, 0xb7, + 0x1d, 0xf0, 0x70, 0x63, 0xa4, 0xe0, 0x4f, 0x6c, 0xf8, 0x24, 0x0a, 0x21, 0x51, 0x6b, 0x5e, 0xcc, 0x90, 0x62, 0xfa, + 0xd0, 0x1e, 0xaf, 0x6b, 0xe4, 0x73, 0xdd, 0xe3, 0xbc, 0x4e, 0x4c, 0xab, 0x6e, 0xb4, 0xd4, 0xc1, 0x36, 0x59, 0x70, + 0x56, 0xf5, 0xae, 0x25, 0x94, 0xea, 0x41, 0x37, 0xfd, 0x28, 0x67, 0xb3, 0xad, 0x5f, 0x39, 0x36, 0xcf, 0xbe, 0xe5, + 0x60, 0xc8, 0xbb, 0x5f, 0x46, 0xab, 0xba, 0x80, 0x63, 0x37, 0xf4, 0x20, 0x2b, 0xc8, 0xc5, 0xd2, 0x3e, 0xc9, 0xc6, + 0x07, 0x62, 0xb8, 0x2e, 0x1f, 0x68, 0xf3, 0xf0, 0xa0, 0x1a, 0xa9, 0x4c, 0x7c, 0xce, 0xc0, 0xbd, 0x6e, 0x58, 0xd3, + 0x0f, 0xf1, 0x7f, 0xe0, 0x80, 0xaf, 0x90, 0x34, 0x36, 0xea, 0x27, 0x78, 0x38, 0x09, 0x14, 0xde, 0xa6, 0xee, 0x27, + 0xe1, 0x7b, 0xa8, 0xd6, 0x75, 0x2a, 0xc6, 0x09, 0xb4, 0xae, 0x58, 0x29, 0x0b, 0x7b, 0xc7, 0x5d, 0x88, 0xd6, 0xb1, + 0x75, 0x18, 0xb5, 0xaf, 0x2d, 0x5d, 0xe6, 0xe0, 0xff, 0xc2, 0x45, 0xfe, 0xac, 0x80, 0xf0, 0x59, 0xbe, 0x3e, 0xed, + 0x67, 0xe1, 0x3f, 0x27, 0x3c, 0x80, 0x7b, 0xc2, 0x92, 0xe7, 0x2c, 0x9f, 0xc0, 0x86, 0x05, 0xca, 0x81, 0x42, 0xe5, + 0x58, 0xae, 0x56, 0xa1, 0xd4, 0x41, 0x15, 0x6c, 0x4c, 0x5d, 0xfb, 0x78, 0x86, 0xd6, 0xdf, 0x41, 0x5d, 0xec, 0xd4, + 0x23, 0xda, 0x84, 0x15, 0xf9, 0x97, 0x4e, 0x79, 0xe2, 0xf5, 0xb5, 0xab, 0x0f, 0x59, 0x4d, 0xb9, 0x1f, 0x6a, 0x7d, + 0xef, 0x3b, 0x3e, 0x63, 0x62, 0x01, 0xaf, 0x16, 0x61, 0x46, 0x24, 0x53, 0xee, 0x1b, 0x28, 0x08, 0x84, 0x9c, 0xe3, + 0x3e, 0x3e, 0x02, 0x5f, 0xe5, 0x68, 0x9d, 0x48, 0xdc, 0x5b, 0x18, 0x81, 0x8e, 0x55, 0x19, 0xf4, 0x03, 0x70, 0x5a, + 0x02, 0x11, 0x8a, 0x90, 0x80, 0xe5, 0x69, 0xd0, 0x0f, 0xb4, 0x8f, 0x54, 0x00, 0x56, 0x63, 0xa0, 0xe4, 0x0e, 0xf0, + 0x3c, 0xaf, 0x88, 0x98, 0x5f, 0x53, 0x79, 0x95, 0x58, 0xac, 0xcd, 0xb4, 0x8f, 0x3a, 0x15, 0x08, 0x8b, 0x64, 0x53, + 0x50, 0x56, 0x1b, 0xea, 0x02, 0x2c, 0x88, 0xc6, 0x58, 0x1e, 0xdd, 0x00, 0x37, 0xc7, 0x52, 0x5b, 0x74, 0xc9, 0xaf, + 0x41, 0x3d, 0x1d, 0x17, 0xf8, 0x46, 0x33, 0x6c, 0x69, 0x4c, 0xd7, 0x84, 0xe3, 0x84, 0x14, 0x11, 0xbd, 0x83, 0xa0, + 0x12, 0x33, 0x9e, 0xc7, 0x19, 0x9e, 0xd1, 0xbb, 0x78, 0x8a, 0x67, 0x3c, 0x7f, 0x62, 0x96, 0x3d, 0x4e, 0x21, 0xc9, + 0x7d, 0x2c, 0xd6, 0x44, 0xbf, 0x89, 0xf5, 0xbb, 0x64, 0xc5, 0x63, 0xe0, 0x55, 0x64, 0x88, 0x7a, 0xa9, 0xb6, 0x29, + 0x67, 0xaa, 0x32, 0x5e, 0x7f, 0xad, 0x42, 0x8a, 0x13, 0x9c, 0xa1, 0x28, 0x13, 0x98, 0xf5, 0x65, 0xfc, 0x1a, 0x02, + 0x4a, 0x27, 0xd8, 0xbc, 0xa7, 0xc5, 0xef, 0x58, 0xf6, 0x4c, 0x14, 0xef, 0xf5, 0x96, 0xcf, 0x10, 0x14, 0x02, 0x17, + 0x15, 0xd9, 0x84, 0xdb, 0xbd, 0x45, 0x5f, 0x54, 0x4d, 0xd1, 0x3b, 0xd3, 0x94, 0x1d, 0xe2, 0x14, 0x22, 0xf1, 0x46, + 0x53, 0xde, 0x68, 0x63, 0xd6, 0x6f, 0x7d, 0xa7, 0xd1, 0x29, 0x2a, 0x4b, 0x22, 0x0c, 0x4f, 0x04, 0x37, 0xf3, 0x58, + 0x10, 0xd9, 0xcc, 0xad, 0x84, 0xb7, 0xd4, 0xc0, 0x8e, 0x73, 0x9c, 0x88, 0x45, 0xae, 0x62, 0xe1, 0xe1, 0x0d, 0xad, + 0x36, 0xd7, 0xf2, 0xce, 0x40, 0x4c, 0xe1, 0x7b, 0xf3, 0x83, 0xe1, 0x1b, 0xad, 0xe2, 0x7f, 0x0b, 0x86, 0x3d, 0x32, + 0x96, 0x00, 0x3f, 0x30, 0x9c, 0x05, 0xc8, 0x19, 0x7e, 0xf2, 0x0e, 0xc0, 0x67, 0x58, 0xc8, 0x7b, 0x48, 0x65, 0x3a, + 0xf5, 0x1e, 0x52, 0x19, 0xa4, 0x6a, 0x57, 0xf2, 0x7d, 0x59, 0x29, 0x8b, 0xfc, 0x06, 0x49, 0x8e, 0x4b, 0x75, 0xb0, + 0x20, 0x32, 0x82, 0x76, 0xb5, 0x28, 0x37, 0xe3, 0x39, 0xc4, 0x14, 0x84, 0xc6, 0xcd, 0x37, 0xbd, 0x83, 0xef, 0x7b, + 0x93, 0xcf, 0x5c, 0xfe, 0xbd, 0xc9, 0xd7, 0x1d, 0x39, 0x8c, 0xaf, 0xdf, 0x76, 0x6a, 0xcb, 0x78, 0x61, 0xb1, 0xf6, + 0x43, 0xf9, 0x82, 0x4b, 0x4b, 0xbf, 0x94, 0x4d, 0xda, 0x78, 0xe2, 0x21, 0x65, 0xb3, 0xe2, 0xe1, 0x3a, 0xb8, 0xdd, + 0x3a, 0x0c, 0x79, 0x93, 0xb4, 0x11, 0x3a, 0xb4, 0xc2, 0x55, 0x1e, 0x6a, 0xc9, 0xe9, 0xf0, 0xf1, 0x11, 0xdc, 0xbd, + 0xcc, 0xf2, 0x0d, 0x5f, 0x29, 0x53, 0xad, 0xd9, 0x6e, 0x1d, 0xf2, 0x9d, 0x55, 0x1a, 0x6d, 0x3c, 0x63, 0x64, 0x09, + 0xce, 0x65, 0xb4, 0x30, 0xaa, 0x06, 0xf0, 0x21, 0x7d, 0x91, 0xff, 0xb6, 0xa0, 0xa9, 0xfe, 0x3e, 0x34, 0x29, 0xaf, + 0x17, 0xca, 0x25, 0x35, 0x39, 0x0c, 0xa2, 0x83, 0x6c, 0x49, 0x2f, 0x27, 0xe4, 0x47, 0x24, 0xea, 0xa2, 0xf3, 0x76, + 0x3f, 0xea, 0x1e, 0xf2, 0x43, 0x1e, 0x03, 0x0f, 0x1b, 0x36, 0x5d, 0x85, 0x66, 0xdb, 0xd5, 0xb9, 0x5a, 0x8c, 0x78, + 0x62, 0x9b, 0xaf, 0x3a, 0x28, 0x53, 0xcd, 0x1c, 0x21, 0x0b, 0x50, 0xcc, 0xf5, 0xe2, 0x65, 0xd7, 0xbb, 0x39, 0xe4, + 0x31, 0xf4, 0x03, 0xb5, 0x3a, 0xa6, 0x56, 0x39, 0xb8, 0xdf, 0x16, 0x80, 0x60, 0xae, 0xa3, 0xda, 0x5c, 0x4c, 0x7a, + 0x33, 0xac, 0x3a, 0x3b, 0xe4, 0xd5, 0x08, 0xfd, 0x32, 0xdb, 0xfd, 0xb9, 0xa9, 0x55, 0x5d, 0x1e, 0x7a, 0x10, 0xf9, + 0x6d, 0xc1, 0x73, 0xbf, 0x53, 0xbf, 0x5b, 0x9b, 0xe3, 0x77, 0x5a, 0x9f, 0xa5, 0x57, 0x64, 0xbb, 0xd7, 0xad, 0x99, + 0xd6, 0x67, 0x7b, 0x0d, 0x3e, 0x82, 0x30, 0x29, 0xbd, 0xd2, 0x89, 0x90, 0x21, 0x3f, 0xfc, 0x80, 0x6c, 0xeb, 0xaf, + 0x17, 0xca, 0xe5, 0x97, 0x88, 0x00, 0xd9, 0x55, 0xd7, 0x65, 0x75, 0xe8, 0xa3, 0x6c, 0xe2, 0xd5, 0x21, 0xf7, 0x56, + 0xee, 0xe9, 0xdd, 0x5c, 0xc4, 0x0e, 0x5f, 0xfb, 0xad, 0x78, 0x0b, 0x39, 0x81, 0x78, 0xd8, 0xee, 0xfc, 0xb2, 0x20, + 0x67, 0x37, 0xb7, 0x50, 0xd2, 0x9f, 0xb8, 0x2b, 0xfd, 0x81, 0x99, 0xeb, 0x06, 0x7e, 0x1e, 0x75, 0x61, 0xea, 0x9b, + 0x3d, 0x1c, 0x76, 0xa0, 0x0f, 0x0d, 0x87, 0xcd, 0x06, 0x5d, 0x66, 0x05, 0x91, 0x2b, 0x5e, 0x18, 0x3c, 0xbb, 0x20, + 0xed, 0x3e, 0x8f, 0xed, 0x66, 0xd2, 0xa2, 0x51, 0xbb, 0xc9, 0xbd, 0x99, 0x01, 0x7e, 0xd9, 0xb2, 0x7e, 0x11, 0xb7, + 0x4e, 0x1e, 0x94, 0x5c, 0xb1, 0x6a, 0x7d, 0x2a, 0x78, 0xd5, 0x1b, 0x8e, 0x37, 0xd3, 0xdd, 0xba, 0xc1, 0xed, 0xae, + 0x83, 0x27, 0xbc, 0xc0, 0x62, 0xd0, 0xda, 0x4d, 0x7c, 0x02, 0x1c, 0x50, 0xd4, 0x7a, 0xd8, 0x05, 0x17, 0xca, 0x12, + 0x96, 0xdb, 0xe5, 0x66, 0x5b, 0xe5, 0x0c, 0x1c, 0x4d, 0x49, 0x8f, 0x3b, 0xd8, 0x84, 0x28, 0x74, 0x70, 0xd8, 0xc1, + 0x51, 0xbb, 0xdd, 0xe9, 0xe2, 0xe8, 0xa4, 0x0b, 0x03, 0x6d, 0x44, 0xdd, 0xc3, 0x59, 0x6e, 0x00, 0xe8, 0xe5, 0xac, + 0x6d, 0xbb, 0x8f, 0x21, 0x5a, 0x93, 0x2f, 0x5e, 0xf3, 0xc3, 0x30, 0x6c, 0x47, 0x0f, 0x5b, 0xed, 0xee, 0x59, 0x03, + 0x00, 0xd4, 0xb4, 0x1f, 0xb6, 0xc6, 0xeb, 0x85, 0xaa, 0x57, 0x29, 0x11, 0xbe, 0x5e, 0xad, 0xe1, 0xaa, 0x35, 0xda, + 0xeb, 0x6a, 0x0a, 0xae, 0xaa, 0x15, 0xce, 0x4d, 0x11, 0xa7, 0xb4, 0xf1, 0xb7, 0x45, 0x68, 0x06, 0x12, 0x82, 0x74, + 0x1e, 0x75, 0x3b, 0x5d, 0x64, 0xc6, 0xa2, 0x2c, 0x7e, 0x94, 0xfb, 0x64, 0xab, 0x48, 0x43, 0x01, 0x92, 0x94, 0xb3, + 0x13, 0x0b, 0x90, 0xa8, 0x39, 0xb9, 0x68, 0x37, 0x67, 0x2c, 0x72, 0x13, 0xd0, 0xa9, 0xb0, 0x9c, 0xe5, 0x2a, 0xd8, + 0x24, 0x0f, 0x10, 0xe7, 0x60, 0x5c, 0xf4, 0xb0, 0xdb, 0x7f, 0x18, 0x75, 0x4f, 0x3b, 0x86, 0xe8, 0xf1, 0xf3, 0x4e, + 0x2d, 0x4d, 0x4f, 0x3d, 0xea, 0xea, 0x34, 0xe8, 0x3a, 0x7a, 0xd8, 0x85, 0x32, 0x36, 0xc5, 0x2f, 0x05, 0x51, 0x26, + 0xaa, 0x62, 0x10, 0x5a, 0x22, 0xae, 0xe5, 0x9e, 0xd6, 0xb2, 0xcf, 0x4e, 0x8e, 0x1f, 0x76, 0x7d, 0xa8, 0x95, 0xb3, + 0xd0, 0x0b, 0x6d, 0x27, 0xe2, 0x66, 0x07, 0x4b, 0x8b, 0x0e, 0xa3, 0x6e, 0xbc, 0x35, 0x41, 0xb3, 0x69, 0x0e, 0x35, + 0x0e, 0x78, 0x0a, 0xc7, 0x4b, 0x69, 0xf5, 0x25, 0xde, 0xfd, 0x58, 0x65, 0x68, 0xe2, 0x2b, 0x9c, 0xdd, 0x3d, 0xa5, + 0xf7, 0x90, 0xa4, 0x7f, 0x55, 0x79, 0x45, 0xf3, 0xaf, 0x54, 0xbe, 0xa1, 0x10, 0x3a, 0x23, 0x1f, 0x06, 0x36, 0xb0, + 0x77, 0x3d, 0xf7, 0x27, 0x70, 0x11, 0x66, 0x39, 0x5c, 0x68, 0x3a, 0x25, 0x68, 0xc5, 0x0b, 0x8c, 0x7c, 0x56, 0x57, + 0x0f, 0xab, 0xcf, 0x63, 0x6b, 0x52, 0xe0, 0xeb, 0xb6, 0x9e, 0xf3, 0xef, 0x95, 0x8b, 0xca, 0xab, 0xec, 0xa8, 0x8b, + 0x22, 0x7b, 0x59, 0x1e, 0xb5, 0x51, 0xe4, 0x99, 0x90, 0xd8, 0x23, 0x39, 0x49, 0xc8, 0x20, 0xb8, 0x0b, 0x70, 0x70, + 0x1f, 0xe0, 0xc0, 0xf8, 0x30, 0x7f, 0x00, 0x37, 0xf2, 0x00, 0x07, 0xc6, 0x95, 0x39, 0xc0, 0x81, 0x62, 0x39, 0x44, + 0xd4, 0x0a, 0x86, 0x38, 0x83, 0xd2, 0xda, 0xb3, 0xba, 0x2c, 0x7d, 0xe5, 0xbe, 0x4a, 0xd7, 0x6b, 0x93, 0xe2, 0x49, + 0x99, 0x53, 0xbd, 0x43, 0xcd, 0x8b, 0xd0, 0x01, 0x75, 0xcc, 0x7a, 0x80, 0x41, 0x00, 0xa1, 0xf7, 0xee, 0x45, 0xb9, + 0x2a, 0x18, 0x07, 0x3b, 0x86, 0x95, 0x06, 0x9f, 0xf3, 0xc0, 0x3f, 0xc3, 0x02, 0x3c, 0xce, 0x5d, 0x61, 0x10, 0x2b, + 0xdc, 0xef, 0x4c, 0x88, 0xb9, 0xfb, 0xad, 0x44, 0xf9, 0x0b, 0xde, 0x21, 0xb1, 0x16, 0x2d, 0x60, 0xb9, 0x65, 0x62, + 0xff, 0x8c, 0x58, 0x7d, 0x04, 0x37, 0x63, 0x1b, 0x9f, 0x0d, 0x24, 0xc2, 0x1b, 0x2d, 0x50, 0x39, 0xf9, 0xf0, 0xc6, + 0xc4, 0x0a, 0xd2, 0x9f, 0x10, 0x2c, 0x0c, 0xe2, 0x01, 0x0b, 0xb8, 0xd0, 0x98, 0x14, 0x4c, 0xca, 0xc0, 0x04, 0xd1, + 0x0b, 0x44, 0xee, 0x5e, 0x45, 0x74, 0x29, 0xe3, 0x3c, 0xd0, 0x1d, 0xd6, 0x67, 0x6b, 0xc4, 0xe1, 0x4c, 0x14, 0x32, + 0x36, 0x4f, 0xa4, 0x38, 0x30, 0xce, 0xcb, 0xf7, 0x07, 0xe3, 0x2c, 0x59, 0x63, 0x73, 0x87, 0x5d, 0x16, 0xb2, 0x57, + 0xda, 0x7e, 0xa9, 0x24, 0x59, 0x7f, 0x6b, 0x42, 0xb2, 0x36, 0x23, 0x6f, 0xa2, 0xd5, 0x80, 0xaa, 0x48, 0x1a, 0x50, + 0xd8, 0x44, 0x63, 0x89, 0x97, 0x65, 0xc9, 0x78, 0x59, 0x2e, 0xc3, 0x49, 0xab, 0xb5, 0x5e, 0xe3, 0x82, 0xe9, 0xa8, + 0x30, 0x3b, 0x4b, 0x40, 0xbe, 0x9c, 0x8a, 0x5b, 0x2f, 0x57, 0xc6, 0xe5, 0x2c, 0xf5, 0x12, 0x05, 0x9e, 0x11, 0x6c, + 0xb0, 0xc6, 0x5f, 0xb9, 0xe4, 0x00, 0x4f, 0x3b, 0xbb, 0x91, 0x10, 0x19, 0xa3, 0x10, 0x3c, 0xcc, 0x6b, 0x72, 0x8d, + 0xa7, 0x3c, 0x65, 0xbb, 0xdb, 0x04, 0x33, 0xe6, 0x7f, 0xaf, 0x45, 0x87, 0x40, 0x86, 0xdd, 0xd3, 0xa8, 0x03, 0x8b, + 0xb8, 0x82, 0x0e, 0x7c, 0x19, 0x3c, 0xf5, 0x71, 0x33, 0xa3, 0xf7, 0x62, 0xa1, 0x00, 0x2e, 0x0b, 0x25, 0xde, 0xd8, + 0xb8, 0x07, 0xfb, 0x2d, 0xec, 0x42, 0x20, 0x2c, 0x21, 0x64, 0x40, 0x0b, 0x9b, 0x10, 0x15, 0x2d, 0x3c, 0x12, 0x4a, + 0x89, 0x59, 0xdc, 0xc2, 0x3a, 0x5e, 0x44, 0x6b, 0x5d, 0x06, 0xf5, 0xba, 0xc9, 0xdd, 0x5b, 0x92, 0xd5, 0x26, 0x58, + 0x58, 0xe9, 0x50, 0x11, 0xe5, 0xdd, 0x1e, 0x32, 0xc2, 0x1b, 0x3f, 0x5f, 0xbf, 0x7e, 0x65, 0x43, 0x36, 0xf3, 0x31, + 0xb8, 0x6c, 0x5a, 0xd5, 0xd8, 0x8d, 0x7e, 0x84, 0x29, 0xac, 0x14, 0xa5, 0x46, 0x38, 0x85, 0x96, 0x5f, 0xe4, 0x2a, + 0x8b, 0xcc, 0xe5, 0xc5, 0x33, 0x51, 0xcc, 0xa8, 0xb9, 0x31, 0xc2, 0x37, 0xb9, 0x7d, 0x75, 0x5d, 0x3f, 0xec, 0x52, + 0x4d, 0xf2, 0xdd, 0xe6, 0x55, 0xc4, 0x22, 0xd1, 0xf2, 0x2b, 0x68, 0x03, 0x74, 0xe5, 0xf2, 0xd1, 0xdc, 0x82, 0xd8, + 0xc0, 0xf7, 0x1e, 0x79, 0x79, 0x6b, 0xa8, 0x4b, 0x10, 0x34, 0xb8, 0xc6, 0x4f, 0x56, 0xf0, 0xc4, 0xbb, 0x2e, 0xd4, + 0xec, 0x91, 0x15, 0x2f, 0x82, 0x56, 0x50, 0x7f, 0x74, 0x56, 0xab, 0x12, 0x5c, 0xd0, 0xd4, 0x28, 0x13, 0x20, 0x7a, + 0x94, 0xef, 0xdb, 0x71, 0x10, 0x4d, 0xdc, 0xdd, 0xf3, 0x45, 0xdb, 0xd1, 0xd9, 0xac, 0x52, 0x27, 0x96, 0x57, 0x26, + 0xe0, 0xe1, 0x68, 0x5e, 0x90, 0x41, 0xd8, 0x4b, 0x64, 0xa5, 0xf6, 0xd0, 0xe5, 0xa2, 0x5e, 0x98, 0x9d, 0xb7, 0x59, + 0xf3, 0x64, 0xb5, 0xca, 0x2e, 0xda, 0xac, 0xdd, 0x35, 0xef, 0xcd, 0x05, 0x32, 0x01, 0x9a, 0xcb, 0xc7, 0x3c, 0x09, + 0x40, 0x3b, 0x3b, 0x4e, 0x74, 0x38, 0x05, 0x17, 0x21, 0x99, 0x2c, 0x54, 0xd5, 0x97, 0x00, 0xe3, 0x52, 0x62, 0xf4, + 0xf8, 0x05, 0xea, 0xb7, 0xe3, 0x6d, 0x57, 0xe9, 0x66, 0xfb, 0xd0, 0xbb, 0x70, 0x29, 0x10, 0xee, 0x40, 0xc8, 0x03, + 0xd0, 0xef, 0x2e, 0x73, 0x30, 0x0d, 0x02, 0x54, 0xce, 0x41, 0xa4, 0xe5, 0xb3, 0xc5, 0xec, 0x59, 0x41, 0xf5, 0x32, + 0x3c, 0xe1, 0x13, 0xae, 0x64, 0x4c, 0x41, 0xba, 0xdd, 0x95, 0xbe, 0xde, 0x2d, 0x41, 0x25, 0xb5, 0xc0, 0xb3, 0x91, + 0xe2, 0xc9, 0x17, 0x69, 0x17, 0x0e, 0x61, 0xbd, 0xb2, 0x12, 0x27, 0x68, 0x8d, 0x33, 0x31, 0xa1, 0x05, 0x57, 0xd3, + 0xd9, 0xbf, 0xb5, 0x3a, 0x6c, 0xa0, 0x86, 0xfa, 0xc2, 0x0a, 0x40, 0x42, 0xf3, 0x74, 0xb5, 0xe2, 0x47, 0xdf, 0xbf, + 0x4f, 0x72, 0x3e, 0xe1, 0x6d, 0xdc, 0xc1, 0xc7, 0xb8, 0x8b, 0xdb, 0x2d, 0xdc, 0xee, 0xc2, 0xd5, 0x7d, 0x92, 0x2d, + 0x52, 0x06, 0xf6, 0xb1, 0xab, 0x95, 0xba, 0x88, 0xce, 0x0e, 0xcb, 0x70, 0xfb, 0xaa, 0x88, 0x2c, 0xba, 0x78, 0x51, + 0xdf, 0x6d, 0xb8, 0xbc, 0x20, 0xf0, 0x63, 0xb5, 0x8d, 0x7d, 0xd5, 0x49, 0xa9, 0x5f, 0xb8, 0x38, 0xee, 0x83, 0x3d, + 0xb7, 0x59, 0xd9, 0x26, 0x98, 0x7d, 0x9b, 0x9f, 0x71, 0xf5, 0xb3, 0xa9, 0x4a, 0xc4, 0x70, 0xd0, 0xab, 0xd0, 0x03, + 0x5d, 0x90, 0xf6, 0xc1, 0x01, 0x58, 0x1d, 0x79, 0xb3, 0xe1, 0x26, 0xfa, 0x01, 0x6f, 0xd6, 0xd2, 0x20, 0x58, 0x01, + 0x18, 0x77, 0xbe, 0xe1, 0x64, 0x69, 0x60, 0xab, 0x80, 0x0a, 0xab, 0xc2, 0x0f, 0x28, 0xe7, 0x93, 0x0a, 0x2d, 0x44, + 0xc3, 0x11, 0x66, 0x23, 0x9d, 0xec, 0xb7, 0xb0, 0x18, 0x8f, 0x25, 0x53, 0x70, 0x74, 0x14, 0xec, 0x2b, 0x2b, 0xa4, + 0x3e, 0x45, 0x46, 0x6c, 0xc2, 0xf3, 0x4b, 0xf5, 0x89, 0x15, 0x42, 0x7f, 0x6a, 0x0d, 0x46, 0x1c, 0xe8, 0x55, 0x0c, + 0x70, 0x92, 0xf1, 0x39, 0x54, 0x9d, 0x14, 0xe0, 0xf4, 0x03, 0x7f, 0x79, 0x1a, 0xfb, 0x6d, 0x02, 0xf9, 0xfa, 0x60, + 0xc2, 0xba, 0xe0, 0xb4, 0xa0, 0xb7, 0xaf, 0xf3, 0x2b, 0xd8, 0x51, 0x97, 0x05, 0xa3, 0x90, 0x0d, 0x49, 0xef, 0xa0, + 0x29, 0xf8, 0x80, 0x36, 0x5f, 0x6a, 0xc0, 0xc5, 0x67, 0xfa, 0xc3, 0x54, 0x74, 0x41, 0x0b, 0xa3, 0xb2, 0x2d, 0x9d, + 0xa9, 0x4f, 0xe9, 0x2a, 0xd3, 0x84, 0x85, 0x2a, 0xa7, 0xb0, 0xc6, 0x36, 0xea, 0x89, 0x3f, 0x98, 0x94, 0xca, 0x69, + 0x3c, 0x18, 0xea, 0xbf, 0xaf, 0x4d, 0xc9, 0x16, 0xb6, 0x41, 0x67, 0xd6, 0x58, 0xbf, 0x18, 0xea, 0x95, 0x6f, 0x63, + 0xb8, 0x87, 0x85, 0x67, 0x2b, 0x6b, 0xe4, 0xf3, 0xc4, 0x91, 0xcd, 0x93, 0xf5, 0x5a, 0x0f, 0x44, 0xc6, 0xa0, 0x07, + 0x7a, 0xeb, 0xb6, 0x4d, 0x0b, 0xb6, 0x47, 0xf9, 0xd5, 0x6d, 0xe1, 0x19, 0x87, 0x57, 0x38, 0x5d, 0x7b, 0xd7, 0xaa, + 0x10, 0x5f, 0x2c, 0x48, 0x5a, 0x5e, 0x8a, 0x99, 0x8e, 0xd7, 0xd9, 0x31, 0xf6, 0x46, 0x0e, 0xf4, 0xfc, 0xfa, 0x8b, + 0x81, 0xb5, 0xfb, 0xfd, 0xa6, 0x2c, 0x98, 0xd1, 0x11, 0xcb, 0xca, 0x09, 0x25, 0xee, 0xfc, 0x7c, 0xc3, 0xa3, 0x0a, + 0x15, 0xec, 0xf3, 0x55, 0xb0, 0xa7, 0x4d, 0x84, 0xcb, 0x19, 0xfd, 0xcb, 0xfc, 0x30, 0x81, 0x75, 0x4a, 0x2d, 0x5b, + 0x52, 0x08, 0x29, 0x2f, 0x4d, 0x9a, 0x39, 0x7a, 0xe0, 0x88, 0x7c, 0x09, 0x5d, 0x00, 0xaf, 0x9f, 0x16, 0x62, 0xae, + 0x11, 0xc1, 0xfe, 0xb6, 0xe3, 0xd6, 0xbe, 0x02, 0xe0, 0xed, 0xb0, 0x57, 0xfd, 0xd3, 0x02, 0xf6, 0x37, 0x28, 0x4b, + 0xba, 0xf1, 0x76, 0xcc, 0xf1, 0x5f, 0x08, 0x08, 0x97, 0x6e, 0xf0, 0x30, 0xb2, 0xe8, 0x54, 0xb2, 0x66, 0xe5, 0xcf, + 0xad, 0x92, 0x80, 0x61, 0xf5, 0x82, 0x3e, 0x1b, 0xb7, 0x55, 0xdc, 0x64, 0xfe, 0x07, 0x15, 0x34, 0x16, 0x7c, 0x6b, + 0x24, 0x15, 0xcb, 0xe2, 0xb6, 0x4f, 0x9d, 0xff, 0xaa, 0x73, 0x5c, 0xfb, 0xaa, 0xf6, 0x44, 0xe6, 0x48, 0x87, 0x27, + 0x0e, 0xd0, 0xc1, 0xc1, 0x46, 0x06, 0x1d, 0x03, 0xe0, 0x91, 0x65, 0xbf, 0xdc, 0xf2, 0x39, 0x76, 0x4c, 0x6b, 0x1e, + 0x8b, 0xc0, 0x67, 0xee, 0x1c, 0x37, 0x67, 0x26, 0xf2, 0x84, 0xca, 0xa9, 0x2b, 0x0c, 0x70, 0x7c, 0xbc, 0x95, 0x0a, + 0xf8, 0x1e, 0xac, 0x77, 0x4c, 0x60, 0x83, 0xdf, 0x32, 0x93, 0xda, 0x55, 0xd0, 0x2d, 0xd0, 0x72, 0x17, 0x53, 0xb9, + 0xb1, 0xc0, 0xc1, 0xe6, 0x44, 0x76, 0x0e, 0x7d, 0xa3, 0x4e, 0xc9, 0x7a, 0x3c, 0xd9, 0x6d, 0xf4, 0x95, 0xcb, 0x5d, + 0xc9, 0x15, 0x6d, 0x1b, 0xb1, 0xea, 0x99, 0x5c, 0x55, 0x99, 0x3a, 0x55, 0xd7, 0xbc, 0x95, 0xa5, 0x4d, 0x69, 0x97, + 0x64, 0xee, 0xb6, 0x98, 0x7f, 0x15, 0xde, 0x68, 0x94, 0x17, 0xa1, 0x60, 0x8f, 0x25, 0x87, 0x3d, 0x4e, 0xe0, 0x7a, + 0x61, 0xb5, 0x0a, 0xe1, 0xcf, 0xae, 0x31, 0xec, 0x32, 0x5d, 0xfa, 0xc0, 0x37, 0xf8, 0x15, 0x2f, 0x52, 0xaf, 0xb5, + 0x83, 0x04, 0xeb, 0x2e, 0x3b, 0x68, 0x38, 0x4e, 0xdc, 0x17, 0xbc, 0x13, 0xad, 0x9c, 0xcb, 0xc1, 0x24, 0xf9, 0xc6, + 0xdb, 0x72, 0x25, 0x6b, 0x59, 0x0b, 0xf3, 0xbe, 0x21, 0xc1, 0x10, 0xb3, 0x29, 0xad, 0xe3, 0x56, 0xd4, 0x46, 0x81, + 0x2d, 0x56, 0xa1, 0xff, 0xb7, 0x8a, 0x24, 0x26, 0xf3, 0xbf, 0x4e, 0x4f, 0x4f, 0x6d, 0x8a, 0xb5, 0xf9, 0x93, 0xda, + 0x03, 0x4e, 0x27, 0xb0, 0xaf, 0x3c, 0x61, 0x5a, 0x87, 0xfc, 0x16, 0x86, 0x42, 0x24, 0xb9, 0x70, 0xec, 0x12, 0x44, + 0xe5, 0x02, 0xca, 0x03, 0xec, 0xdf, 0x93, 0x8d, 0x72, 0xee, 0x9d, 0x24, 0x17, 0x47, 0xb8, 0x6c, 0x90, 0x7d, 0xd5, + 0x9f, 0x03, 0x63, 0x26, 0x03, 0x4f, 0x03, 0x04, 0xd8, 0xfc, 0xd6, 0x2c, 0xad, 0xb5, 0x94, 0xc1, 0x81, 0x12, 0x8b, + 0x64, 0x6a, 0x34, 0xff, 0xf6, 0x43, 0x97, 0xb5, 0x6f, 0xec, 0x40, 0x50, 0x2e, 0xb2, 0xb4, 0xe1, 0x30, 0x83, 0x1f, + 0xcb, 0xc8, 0x97, 0x7b, 0xaf, 0xd8, 0x82, 0xfd, 0x88, 0xf7, 0xaa, 0x14, 0xf8, 0xb8, 0x2c, 0x38, 0xcd, 0x7e, 0xc4, + 0x7b, 0x55, 0x04, 0x4c, 0x70, 0x85, 0xd4, 0x41, 0x24, 0xb1, 0x7e, 0x4f, 0x3a, 0x0e, 0x72, 0xa0, 0xa0, 0x59, 0xa0, + 0x0f, 0xb2, 0xe7, 0x36, 0x68, 0x62, 0xd4, 0xc1, 0x36, 0xee, 0x97, 0x09, 0x85, 0x6a, 0x22, 0x88, 0x43, 0x20, 0xb9, + 0x72, 0x36, 0xfa, 0xeb, 0xf1, 0xc6, 0x82, 0x68, 0x65, 0x32, 0xb9, 0x78, 0xce, 0xc3, 0x7c, 0x73, 0xb1, 0x90, 0x5f, + 0xcd, 0x5b, 0xa0, 0x5a, 0x95, 0x2a, 0xdd, 0x2f, 0xbe, 0x5d, 0x30, 0xf1, 0x8a, 0xe8, 0xad, 0x77, 0x79, 0x07, 0xcf, + 0x9d, 0xdf, 0x05, 0x2e, 0x09, 0x9e, 0x04, 0xd7, 0x98, 0xea, 0x5e, 0x80, 0x07, 0x42, 0xcf, 0xa4, 0x0a, 0xb0, 0xce, + 0x93, 0x10, 0x49, 0x6c, 0xbf, 0x85, 0x2d, 0x6b, 0xf4, 0x22, 0x77, 0x42, 0x0a, 0x9c, 0xab, 0xba, 0x89, 0x19, 0xe5, + 0x3a, 0xba, 0xd8, 0xa5, 0x9c, 0xb3, 0x44, 0x19, 0x04, 0xd8, 0xb7, 0x68, 0x28, 0xf2, 0xe7, 0x1a, 0x14, 0xfa, 0x2d, + 0x6b, 0x9b, 0x72, 0x05, 0x8b, 0xe7, 0xa5, 0x00, 0x51, 0xe3, 0xf9, 0xa4, 0xac, 0x33, 0xcf, 0x16, 0x13, 0x9e, 0x57, + 0xc8, 0x50, 0x30, 0x39, 0x17, 0x39, 0x3c, 0x25, 0x51, 0x16, 0xd1, 0x74, 0xa8, 0x86, 0xef, 0x86, 0x84, 0x95, 0x75, + 0xf4, 0x31, 0xc5, 0xf3, 0xaa, 0x06, 0x30, 0x17, 0x97, 0xfe, 0x9b, 0xf3, 0xf2, 0x75, 0xfe, 0x4e, 0xcc, 0xab, 0x7c, + 0x47, 0xe3, 0x5c, 0xc4, 0x76, 0x6b, 0x37, 0x8c, 0xd6, 0xfa, 0xb5, 0x27, 0x6f, 0xfb, 0x7e, 0xe0, 0xd5, 0x0b, 0x68, + 0x6b, 0xfd, 0x5e, 0x54, 0x99, 0x35, 0x62, 0xe5, 0xe3, 0x08, 0x55, 0x7b, 0xf5, 0xaa, 0xb9, 0xad, 0x08, 0x50, 0x29, + 0x78, 0xba, 0x95, 0xff, 0x44, 0x99, 0x7c, 0x73, 0x0e, 0x95, 0xe1, 0x81, 0x1c, 0x19, 0xaa, 0x7a, 0xc0, 0x45, 0xf9, + 0xa1, 0x9f, 0xbe, 0x0a, 0x74, 0xe0, 0xdc, 0x5d, 0x17, 0xc8, 0x9c, 0xc9, 0x50, 0xe0, 0xe5, 0x80, 0x0e, 0x63, 0x23, + 0x0f, 0xc5, 0x02, 0x6c, 0x7b, 0x6e, 0x0b, 0xae, 0x5c, 0x84, 0x5e, 0x3c, 0x60, 0xc3, 0x78, 0x59, 0x8f, 0xe2, 0x6b, + 0xe2, 0x08, 0x3b, 0x73, 0x4e, 0x1d, 0xf6, 0x96, 0x0e, 0x71, 0x46, 0xc0, 0xf6, 0xd8, 0xb1, 0xa7, 0x6f, 0xc2, 0x04, + 0xf5, 0xeb, 0x1c, 0xfe, 0x72, 0x8d, 0x33, 0x9c, 0xa0, 0xf8, 0x32, 0x84, 0x0b, 0xac, 0x35, 0x06, 0xf0, 0x25, 0x86, + 0x54, 0x81, 0x47, 0x6a, 0xa2, 0x25, 0x56, 0x7b, 0x11, 0x88, 0x96, 0xca, 0xbf, 0x1d, 0x67, 0x2e, 0x0e, 0xb6, 0xe6, + 0x5e, 0x9f, 0x69, 0xe1, 0x70, 0x92, 0x84, 0xb5, 0x73, 0x86, 0x93, 0x8b, 0x7d, 0x5e, 0x3b, 0x31, 0xc1, 0xda, 0xdb, + 0x3f, 0x55, 0x40, 0x8f, 0x06, 0xa7, 0x8a, 0xa1, 0x21, 0x10, 0x33, 0x01, 0xbc, 0x99, 0xfd, 0xa3, 0xcd, 0xc3, 0xf9, + 0x60, 0x8d, 0xbd, 0xaf, 0xb8, 0xd6, 0xd5, 0xa6, 0x12, 0x65, 0xbd, 0xc6, 0x83, 0x69, 0x82, 0xd3, 0x04, 0xcf, 0x93, + 0xa1, 0x77, 0xdc, 0xcc, 0x12, 0xdf, 0xa4, 0x6b, 0xb5, 0x7a, 0x6a, 0xcd, 0x08, 0x91, 0xf9, 0x69, 0xe8, 0x0f, 0xea, + 0x03, 0xc2, 0xc7, 0x90, 0x05, 0xb4, 0xa4, 0x6f, 0xff, 0x36, 0xcc, 0x33, 0xd9, 0xa8, 0x11, 0xf2, 0xc8, 0x90, 0x91, + 0xbe, 0xfb, 0x51, 0x66, 0x99, 0xd6, 0x1a, 0xc1, 0xfc, 0x6e, 0x2f, 0x68, 0xb8, 0xf6, 0x3c, 0x2d, 0x5b, 0x69, 0xb6, + 0x03, 0x88, 0x62, 0x8c, 0x93, 0x94, 0xb7, 0x46, 0x62, 0xb5, 0x0a, 0x4d, 0x0a, 0xe1, 0xd1, 0x8c, 0x51, 0xb9, 0x28, + 0xf4, 0xcb, 0x71, 0x61, 0x8e, 0x22, 0xcd, 0xef, 0x62, 0x6b, 0x23, 0x9a, 0x83, 0xdb, 0x23, 0x18, 0x6e, 0x84, 0x92, + 0x88, 0x9a, 0xc8, 0x3d, 0x4a, 0x2a, 0xcb, 0x20, 0x49, 0xa4, 0x16, 0xf9, 0xcd, 0x75, 0xa9, 0x39, 0x0c, 0xec, 0x1f, + 0xed, 0x0b, 0x08, 0x37, 0x6f, 0x13, 0x5a, 0x8c, 0xe8, 0x04, 0xd8, 0x58, 0x88, 0x43, 0xb8, 0x95, 0xb0, 0x5a, 0x0d, + 0x86, 0x3d, 0x43, 0x9e, 0xed, 0xcb, 0x79, 0x65, 0x43, 0xbb, 0x1b, 0x80, 0xab, 0x6e, 0x43, 0xcd, 0x95, 0xd6, 0xfd, + 0x50, 0xfd, 0xb8, 0x17, 0xb7, 0x49, 0xf6, 0x7d, 0x8e, 0xea, 0x09, 0xee, 0x9a, 0x05, 0xb8, 0x0e, 0x5d, 0x85, 0x53, + 0xbc, 0x30, 0x36, 0x9c, 0xfa, 0x25, 0x27, 0xaa, 0x1f, 0x70, 0x82, 0x77, 0xa3, 0x09, 0x1b, 0x24, 0x43, 0x9c, 0xba, + 0x38, 0xdf, 0xfb, 0x6f, 0xc3, 0x14, 0xa1, 0x82, 0x68, 0x98, 0x1a, 0x97, 0xed, 0xb4, 0xb2, 0xdb, 0xd7, 0x99, 0x9a, + 0x61, 0xd0, 0x46, 0xcc, 0xa9, 0x6f, 0xc4, 0x9c, 0x35, 0x1a, 0x68, 0x41, 0x52, 0x30, 0x62, 0x5e, 0x78, 0xad, 0x2d, + 0xcc, 0x2b, 0x9f, 0x5e, 0x7b, 0x0b, 0x84, 0x7a, 0x1c, 0x68, 0x9a, 0x82, 0xf7, 0x3c, 0xaa, 0xf7, 0xd4, 0xdd, 0xeb, + 0x52, 0x47, 0x1d, 0x50, 0x24, 0x8c, 0x2f, 0xdc, 0x24, 0x8c, 0x6b, 0xb8, 0x19, 0xf7, 0x58, 0x8f, 0xdb, 0xda, 0x36, + 0xe4, 0x03, 0x31, 0x48, 0x86, 0xc3, 0x9e, 0x70, 0x56, 0x12, 0x2d, 0x3c, 0xae, 0x5e, 0x00, 0xa9, 0x16, 0xef, 0xab, + 0xda, 0xbc, 0xf2, 0xe6, 0xee, 0x61, 0xd1, 0xcd, 0xf3, 0x18, 0x38, 0xa0, 0x7d, 0xb8, 0x1f, 0xaa, 0xe2, 0x83, 0x1d, + 0x75, 0x20, 0x0a, 0x5a, 0xdc, 0xaa, 0x09, 0xa4, 0xc6, 0xcc, 0x2e, 0x54, 0xcd, 0x1c, 0x1d, 0x4a, 0x08, 0x43, 0x96, + 0x57, 0xdd, 0xdd, 0xe7, 0x9e, 0x6a, 0x88, 0xc3, 0xa9, 0x7f, 0x65, 0x8c, 0x58, 0xc3, 0xa0, 0x93, 0x06, 0xda, 0x48, + 0xd2, 0x2c, 0x1f, 0x3c, 0xfa, 0x03, 0x56, 0x02, 0x2e, 0xf8, 0xb2, 0x4e, 0xd2, 0x86, 0x04, 0x6f, 0x59, 0xa2, 0x34, + 0x1f, 0xc2, 0x2d, 0x82, 0xf2, 0xc8, 0xc4, 0xda, 0xb4, 0x95, 0x0c, 0xe4, 0xaa, 0x2e, 0x6f, 0x3c, 0xf4, 0xbc, 0x4f, + 0xaa, 0xdd, 0x00, 0x1c, 0x99, 0x37, 0xb0, 0x64, 0x6b, 0x9f, 0x80, 0x47, 0x3e, 0xae, 0x10, 0xc4, 0x2d, 0x85, 0x8a, + 0x74, 0xa0, 0xea, 0x6b, 0xd8, 0xa0, 0x78, 0x0e, 0x0e, 0x82, 0x56, 0x82, 0xc3, 0xe0, 0x5d, 0x66, 0x34, 0xc9, 0x1a, + 0xb7, 0x66, 0x24, 0x9c, 0xaf, 0x56, 0x2d, 0x74, 0xf8, 0xb7, 0x7e, 0x8b, 0x79, 0x5c, 0x2a, 0xdc, 0xc7, 0x95, 0xc2, + 0x1d, 0x2c, 0x01, 0xc9, 0xd8, 0xd3, 0xb5, 0x63, 0xe1, 0xab, 0xd1, 0x21, 0x4c, 0xf8, 0x0b, 0x08, 0x1a, 0x6d, 0x8f, + 0x25, 0xd0, 0xb3, 0x6f, 0x15, 0x30, 0xba, 0xf6, 0xb2, 0x04, 0xd2, 0x82, 0xbb, 0xdb, 0x04, 0x5a, 0x85, 0xa8, 0x7d, + 0xfe, 0xf4, 0x73, 0x0e, 0x3c, 0xb2, 0xfe, 0x5c, 0x33, 0xcd, 0xba, 0x17, 0xf4, 0x56, 0x37, 0x1f, 0x8e, 0x71, 0x73, + 0x6c, 0xc0, 0x79, 0xd4, 0x81, 0x9f, 0x06, 0xa2, 0x47, 0x1d, 0x6c, 0x53, 0xf1, 0xb8, 0x04, 0xb2, 0x8f, 0x9e, 0xd6, + 0x40, 0x0a, 0x58, 0xe9, 0xd0, 0x68, 0x91, 0x26, 0x68, 0xb5, 0x9a, 0x9c, 0x93, 0x16, 0x42, 0x4b, 0x79, 0xcb, 0x55, + 0x32, 0x05, 0x1f, 0x69, 0x50, 0x0c, 0xbc, 0xa1, 0x6a, 0x1a, 0x22, 0x3c, 0x46, 0xcb, 0x94, 0x8d, 0xe9, 0x22, 0x53, + 0x71, 0xde, 0xe7, 0x91, 0x89, 0xa4, 0xcb, 0x4c, 0x24, 0xb8, 0xa3, 0x0e, 0x9e, 0x68, 0xfe, 0xf2, 0xb1, 0x36, 0x07, + 0x29, 0x12, 0x9d, 0x3c, 0xd1, 0x09, 0x98, 0x47, 0x49, 0x26, 0x24, 0x33, 0xcd, 0xf4, 0x8c, 0x6d, 0x39, 0xc4, 0xe2, + 0x0e, 0x54, 0xc1, 0xb5, 0x15, 0x65, 0x10, 0x4f, 0x49, 0xde, 0xcf, 0x8f, 0x3a, 0xf1, 0x04, 0xf3, 0x08, 0x38, 0xbd, + 0x77, 0x22, 0x64, 0x8d, 0xf2, 0x56, 0x74, 0x86, 0x0e, 0xa7, 0x58, 0x56, 0x97, 0xa8, 0x33, 0x74, 0x38, 0x41, 0x78, + 0xd6, 0x20, 0x59, 0x0e, 0x1e, 0xc3, 0x3c, 0xff, 0x3f, 0x52, 0xfe, 0x9b, 0xc3, 0x86, 0x98, 0xcf, 0x6f, 0x61, 0xa7, + 0xb0, 0x34, 0x88, 0x33, 0x02, 0x5e, 0x8b, 0xed, 0x53, 0x9c, 0x90, 0x49, 0x33, 0x73, 0x01, 0xf7, 0x74, 0x2b, 0x8d, + 0x3b, 0x85, 0x0e, 0x13, 0x9c, 0x6e, 0x26, 0x85, 0x7a, 0xae, 0xcd, 0x2c, 0x4e, 0xe0, 0x7c, 0xaf, 0x46, 0x61, 0xcb, + 0x2f, 0x36, 0x93, 0xfc, 0xf2, 0x16, 0xb8, 0xcd, 0x14, 0xcb, 0x26, 0xc5, 0x19, 0x9e, 0x35, 0x5f, 0xe1, 0x59, 0xf3, + 0x43, 0x99, 0xd1, 0x58, 0x60, 0x09, 0xc1, 0xfb, 0x20, 0x11, 0xcf, 0xaa, 0xe4, 0x14, 0xcb, 0x86, 0x2e, 0x8f, 0x67, + 0x8d, 0xaa, 0x74, 0x73, 0x81, 0x65, 0x43, 0x97, 0x6e, 0x7c, 0xc0, 0xb3, 0xc6, 0xab, 0x7f, 0x31, 0xe9, 0x20, 0x06, + 0x74, 0x99, 0xa3, 0x65, 0x62, 0x86, 0x78, 0xfd, 0xdb, 0xdb, 0x77, 0xed, 0x9b, 0xce, 0xe1, 0x04, 0xbb, 0xf5, 0x4b, + 0x34, 0x8e, 0x25, 0x2a, 0x64, 0x4d, 0x80, 0x68, 0x82, 0x3b, 0x87, 0x53, 0xdc, 0x39, 0x4c, 0x6c, 0x53, 0xeb, 0x59, + 0x83, 0xdc, 0x29, 0x1f, 0x8a, 0x2a, 0x88, 0x7d, 0xf8, 0xb8, 0xc9, 0xc6, 0x13, 0x54, 0x03, 0x25, 0x3a, 0x9c, 0xd4, + 0x40, 0x05, 0xdf, 0x8b, 0xda, 0x77, 0x55, 0xaf, 0xc2, 0x20, 0x03, 0x25, 0xe4, 0xaf, 0xb9, 0x06, 0x4f, 0x2d, 0x45, + 0x43, 0xc6, 0x4f, 0x31, 0x40, 0xf9, 0x0e, 0x28, 0xb4, 0xf2, 0x44, 0x0f, 0xdd, 0x9b, 0x8e, 0x4e, 0xfc, 0xff, 0x79, + 0x32, 0xe5, 0xd0, 0xcb, 0x2d, 0xb3, 0x35, 0x3d, 0x3b, 0x19, 0x7f, 0xf8, 0xc0, 0x63, 0xfd, 0x5f, 0x3b, 0x50, 0xac, + 0x41, 0x8a, 0xff, 0x2f, 0x1d, 0x9d, 0x0f, 0x46, 0xc8, 0x0a, 0xe2, 0xc2, 0x22, 0xfe, 0xf7, 0x87, 0xe5, 0x75, 0x5f, + 0x6c, 0x75, 0x5f, 0xe8, 0xee, 0xfd, 0xa6, 0xb5, 0x2a, 0x27, 0xae, 0x2a, 0x19, 0xf2, 0x5f, 0xa7, 0x5b, 0x5b, 0xa0, + 0x91, 0x35, 0x7a, 0x36, 0xf1, 0x1b, 0xdc, 0x6f, 0xc7, 0x3b, 0x90, 0x79, 0xcd, 0xcd, 0xd3, 0xa0, 0x70, 0xf8, 0x7a, + 0x77, 0xaa, 0x17, 0x2d, 0xf0, 0xde, 0x94, 0x5a, 0x5f, 0x19, 0xfa, 0x96, 0x83, 0xc5, 0xa6, 0x29, 0xb7, 0x36, 0x96, + 0x8e, 0xba, 0x58, 0xbb, 0x22, 0x42, 0xa5, 0xbb, 0x0b, 0x50, 0x8a, 0x8f, 0x55, 0x93, 0xe9, 0xaf, 0x73, 0x15, 0xe9, + 0x4b, 0xa8, 0x86, 0xfe, 0xbc, 0xbf, 0x50, 0x91, 0x12, 0x73, 0x93, 0x77, 0x7f, 0x0e, 0x7d, 0x82, 0x86, 0xb5, 0xe1, + 0xd9, 0xed, 0xb3, 0xc2, 0xea, 0x77, 0xaa, 0x43, 0xd0, 0x3f, 0x80, 0x2c, 0x69, 0x31, 0x7d, 0x60, 0xdd, 0x1a, 0xb6, + 0x5d, 0x34, 0xcb, 0x44, 0xd3, 0x6a, 0x53, 0xe7, 0x9a, 0x3d, 0xcc, 0xe7, 0x3e, 0x4f, 0xc1, 0x0b, 0xa3, 0x1f, 0xdf, + 0xc1, 0x6e, 0xdc, 0xd5, 0x18, 0x89, 0xba, 0x92, 0xa9, 0x84, 0x7e, 0x74, 0x87, 0x59, 0x74, 0xaf, 0xbd, 0x18, 0x73, + 0xed, 0xef, 0xa3, 0x03, 0xe5, 0x07, 0x95, 0x24, 0x07, 0x96, 0xfd, 0x0d, 0x16, 0xdd, 0x81, 0x79, 0x62, 0x59, 0x4d, + 0x60, 0x15, 0xdd, 0x7b, 0x8b, 0x28, 0x74, 0x23, 0x6b, 0xcd, 0x80, 0xea, 0x66, 0x8c, 0x7a, 0x70, 0x1f, 0x02, 0x3d, + 0xf4, 0xcb, 0x52, 0xca, 0x76, 0x16, 0xd7, 0xba, 0x57, 0xba, 0xfb, 0xcd, 0x01, 0x79, 0x7c, 0xa1, 0xc7, 0x35, 0xfd, + 0xab, 0x49, 0x44, 0x23, 0xf6, 0x0f, 0x67, 0xc5, 0xd5, 0xa2, 0xd0, 0x98, 0x26, 0xfb, 0x2a, 0x4a, 0xe6, 0x6d, 0x30, + 0xd5, 0x4b, 0xe6, 0x9d, 0x3b, 0x6c, 0xbf, 0xef, 0xcd, 0xf7, 0x3d, 0x96, 0x7d, 0xa6, 0x33, 0x62, 0xa6, 0x8b, 0xb9, + 0xef, 0x7b, 0xf3, 0x7d, 0x8f, 0xb7, 0x07, 0x73, 0xeb, 0x2e, 0x14, 0x4b, 0x76, 0x86, 0x0b, 0x30, 0x2c, 0xf7, 0xb8, + 0x9b, 0x5a, 0x96, 0x0e, 0x02, 0x5b, 0x4b, 0x80, 0x38, 0x9f, 0x4f, 0xc3, 0x8a, 0x57, 0x43, 0xc0, 0x7d, 0x3a, 0xd7, + 0xf6, 0x2a, 0x15, 0x78, 0x4c, 0xd0, 0x88, 0xe8, 0xd8, 0x36, 0xfa, 0x59, 0x2f, 0xe0, 0xf2, 0x88, 0x2a, 0xf5, 0x24, + 0x11, 0xf0, 0xaa, 0x5a, 0xe5, 0xad, 0x8b, 0x94, 0x5f, 0xc4, 0xcb, 0x71, 0xc5, 0x1e, 0x53, 0xc9, 0x00, 0x56, 0x65, + 0x49, 0x97, 0x40, 0xea, 0xf9, 0xde, 0x44, 0xbf, 0x6c, 0x22, 0x4f, 0xae, 0x6f, 0x4b, 0xbf, 0x30, 0x35, 0x2d, 0xc4, + 0x62, 0x32, 0x05, 0x1f, 0x5a, 0x60, 0x19, 0x0a, 0x5d, 0xaf, 0xb2, 0xf5, 0xaf, 0x49, 0x6e, 0x12, 0x28, 0x9c, 0x6a, + 0x8a, 0x88, 0x26, 0x6a, 0x41, 0x33, 0x6d, 0x49, 0xca, 0xf3, 0xc9, 0x63, 0x71, 0xf7, 0x12, 0xb0, 0x9b, 0x12, 0xd5, + 0xd8, 0x91, 0xf7, 0x16, 0x76, 0x00, 0x4e, 0x08, 0xdb, 0x55, 0xf1, 0x52, 0x82, 0xce, 0x1f, 0x67, 0x84, 0xed, 0xaa, + 0xfa, 0x84, 0x99, 0xec, 0x29, 0xd9, 0x18, 0x6e, 0x3f, 0x4c, 0x1a, 0x19, 0x3a, 0xea, 0xc4, 0x59, 0xcf, 0x11, 0x03, + 0x03, 0x50, 0x0f, 0xb8, 0x5b, 0xdb, 0xb3, 0xbc, 0xbb, 0x21, 0x79, 0x94, 0xb2, 0x44, 0x98, 0xeb, 0x72, 0x9d, 0xb2, + 0x5a, 0x75, 0x2a, 0x2a, 0x58, 0xe0, 0xa9, 0xb7, 0x17, 0xa8, 0xf9, 0xda, 0x41, 0x71, 0xae, 0x93, 0x4d, 0xd3, 0xf3, + 0xb2, 0xef, 0xde, 0x8e, 0x45, 0xc6, 0x26, 0xed, 0xed, 0x0e, 0x22, 0x61, 0x38, 0x61, 0xe5, 0x71, 0xc2, 0x55, 0x6d, + 0x8f, 0x00, 0xdd, 0x78, 0x22, 0x37, 0x16, 0x64, 0xb9, 0xae, 0x8c, 0xee, 0x3d, 0xbf, 0x5b, 0x4a, 0x84, 0x1d, 0x6d, + 0x49, 0x30, 0x5d, 0x82, 0x56, 0xd3, 0xe9, 0x37, 0x99, 0x6b, 0xcf, 0x0d, 0x6f, 0x8a, 0xb6, 0xb9, 0xbd, 0x49, 0xc7, + 0x7a, 0x7b, 0xe8, 0x18, 0xca, 0x20, 0x06, 0x3a, 0x1f, 0xf1, 0x5e, 0xa3, 0x91, 0x20, 0x50, 0xc8, 0x24, 0x43, 0x2c, + 0x22, 0xa7, 0x45, 0x3f, 0x38, 0xd0, 0xf0, 0xa8, 0x12, 0x10, 0xa6, 0x20, 0x84, 0xf8, 0x5d, 0x6b, 0x84, 0xf5, 0x97, + 0xab, 0x96, 0x0b, 0x1b, 0xa9, 0x36, 0x74, 0xf0, 0xff, 0xf2, 0x97, 0xad, 0x9e, 0x59, 0x2e, 0x8a, 0xc6, 0xcd, 0x4c, + 0x83, 0x45, 0x80, 0xf4, 0x68, 0xb2, 0x1d, 0x14, 0x77, 0xe7, 0x62, 0xbd, 0x21, 0x20, 0x31, 0x83, 0x09, 0xca, 0x86, + 0x75, 0x63, 0x0c, 0xf3, 0xa8, 0xd2, 0xb2, 0xd6, 0x24, 0x66, 0xcf, 0x97, 0xce, 0x5f, 0xf7, 0xe5, 0x5d, 0xcc, 0xf0, + 0x7d, 0x2c, 0xf1, 0x2d, 0x78, 0xd2, 0xc4, 0x02, 0xdb, 0xc7, 0x0b, 0x8a, 0x35, 0x51, 0x3d, 0xc7, 0xde, 0x16, 0xb0, + 0xce, 0x7a, 0x8f, 0x48, 0xef, 0x77, 0xf5, 0xab, 0x0d, 0xbe, 0x5b, 0xf8, 0x15, 0x58, 0x3f, 0x7b, 0x27, 0x29, 0x96, + 0x0d, 0xd1, 0x2c, 0xec, 0x91, 0x01, 0xe5, 0x2a, 0x7e, 0xd9, 0x4f, 0xdd, 0x2a, 0x86, 0x6b, 0x1f, 0xaf, 0xf0, 0x87, + 0x8d, 0x76, 0x1b, 0x79, 0x59, 0xdc, 0xec, 0x4d, 0xd9, 0x10, 0x55, 0xd3, 0x3b, 0x32, 0x37, 0x52, 0xea, 0x5f, 0x1f, + 0x70, 0x6b, 0xab, 0x7d, 0x37, 0xcd, 0xb7, 0x0e, 0x9d, 0xab, 0xa6, 0x5d, 0x6a, 0xad, 0x08, 0xf6, 0x7e, 0xb6, 0x70, + 0x73, 0x6b, 0xc0, 0x1e, 0xfc, 0xdc, 0x1d, 0xcd, 0x55, 0x02, 0xd1, 0xe9, 0x8d, 0x66, 0x7c, 0x15, 0xfe, 0x99, 0x36, + 0xc2, 0x7e, 0xfc, 0x67, 0xf4, 0x67, 0xda, 0x40, 0x7d, 0x14, 0xce, 0xef, 0x56, 0x6c, 0xb6, 0x82, 0x60, 0x6b, 0x0f, + 0x8e, 0xf0, 0x6b, 0xbf, 0x24, 0x57, 0x34, 0xe3, 0xc9, 0xca, 0xbe, 0x84, 0xb7, 0xb2, 0xcf, 0x04, 0xad, 0xf4, 0xe3, + 0x4e, 0xab, 0x50, 0x8c, 0x32, 0x08, 0x2c, 0x1c, 0xee, 0x35, 0xfb, 0x83, 0x56, 0xf3, 0xd1, 0xd0, 0xfc, 0xab, 0x23, + 0xdc, 0xa3, 0x5a, 0xc4, 0xb6, 0x37, 0x1b, 0x5b, 0x3f, 0x04, 0xc3, 0x0e, 0x08, 0x05, 0x0e, 0x72, 0xe9, 0x55, 0x82, + 0x8c, 0xef, 0xc9, 0x6a, 0xc5, 0x6c, 0x34, 0x6b, 0xab, 0xc1, 0x2f, 0x63, 0x33, 0x1d, 0xb6, 0xa3, 0x4e, 0xcf, 0x89, + 0xb1, 0xa4, 0x01, 0x91, 0xa6, 0x31, 0x83, 0x40, 0x52, 0x4b, 0xcd, 0x61, 0xcd, 0xef, 0x82, 0xb8, 0xba, 0x3f, 0x82, + 0x94, 0x1f, 0x82, 0x98, 0x1f, 0x11, 0x08, 0xa0, 0x6d, 0x98, 0xa3, 0xb2, 0x21, 0xe7, 0xbb, 0xf4, 0x40, 0x3b, 0x33, + 0x34, 0xf8, 0x6a, 0xd5, 0xaa, 0x86, 0x29, 0x8b, 0xfa, 0x30, 0x97, 0x6b, 0x2c, 0xc9, 0x1b, 0xd0, 0x35, 0xe7, 0x44, + 0xf6, 0x7d, 0x57, 0x79, 0x78, 0x08, 0x18, 0x0b, 0x02, 0x4e, 0xfa, 0x7d, 0xd9, 0x2f, 0xc8, 0xc5, 0x65, 0x08, 0x3e, + 0x66, 0x98, 0x0f, 0xd4, 0xa0, 0x18, 0x0e, 0x51, 0x6c, 0x9d, 0xce, 0x62, 0x1d, 0x71, 0xc5, 0xf3, 0x4b, 0x2e, 0xc0, + 0x2f, 0x39, 0x47, 0x6c, 0x50, 0x0c, 0xc9, 0x83, 0x24, 0x14, 0xe0, 0x94, 0xbf, 0xc3, 0xe7, 0xf1, 0xd2, 0x37, 0x30, + 0xd5, 0xc3, 0xd2, 0x17, 0xd9, 0x60, 0x31, 0x67, 0x2c, 0x81, 0xe0, 0x66, 0xc0, 0x5e, 0x6a, 0x43, 0xa2, 0xb6, 0x06, + 0x0a, 0xee, 0x02, 0xdf, 0xcc, 0xe8, 0xe9, 0x56, 0x1b, 0x83, 0xc0, 0xe2, 0x85, 0xbe, 0x86, 0x31, 0x08, 0xa4, 0x2f, + 0x57, 0x1d, 0xf6, 0x97, 0x1f, 0x26, 0xcb, 0x0f, 0x5e, 0xa1, 0x4d, 0x76, 0x4a, 0xab, 0x44, 0x3d, 0xbe, 0xca, 0x13, + 0x47, 0x13, 0x64, 0x62, 0xa8, 0x74, 0xc3, 0x32, 0x71, 0x25, 0x7d, 0x26, 0x9a, 0x6c, 0x37, 0x1c, 0x33, 0xe7, 0xbb, + 0xd9, 0xfe, 0x61, 0xdd, 0xce, 0x39, 0xe1, 0x5a, 0x2b, 0xa9, 0xb5, 0x51, 0xcf, 0x34, 0x55, 0xb5, 0xc1, 0xfc, 0x2e, + 0xad, 0x96, 0x16, 0x5b, 0x57, 0xef, 0x9e, 0xff, 0x2c, 0x5d, 0x19, 0x7f, 0x8b, 0x55, 0xa1, 0x15, 0x19, 0x6e, 0xb7, + 0x90, 0x33, 0x67, 0xba, 0x74, 0x8a, 0x5c, 0xa8, 0x0e, 0x7f, 0x51, 0x4f, 0xea, 0x97, 0x2a, 0x83, 0x86, 0x74, 0xe8, + 0xf7, 0x3a, 0x01, 0xe5, 0x1f, 0x4c, 0x4c, 0x64, 0x2c, 0xba, 0xa5, 0x45, 0x1e, 0xfe, 0xf8, 0x22, 0xd7, 0xb1, 0xaa, + 0xf6, 0x60, 0x20, 0x7b, 0xba, 0xe2, 0x1e, 0xdc, 0x9a, 0xf0, 0x31, 0x67, 0x69, 0xbc, 0x17, 0xfc, 0xd8, 0x90, 0x8d, + 0x1f, 0x83, 0x1f, 0xc1, 0xdd, 0xd9, 0x3e, 0x8b, 0x58, 0xc6, 0x85, 0x70, 0xf7, 0x58, 0x97, 0xa5, 0x4a, 0x19, 0x2b, + 0xa7, 0x5b, 0xf6, 0x2f, 0xa4, 0xde, 0x24, 0xe1, 0xa5, 0x25, 0xd6, 0x26, 0x05, 0x2b, 0x9f, 0x92, 0xc2, 0xb3, 0x2b, + 0xfa, 0x56, 0x8b, 0xd9, 0x4b, 0x2d, 0xe9, 0xae, 0xaf, 0x2e, 0x4b, 0x15, 0x34, 0x1c, 0x84, 0xb6, 0xb4, 0x81, 0x04, + 0x18, 0xb8, 0x94, 0x3e, 0x9d, 0xf6, 0x4c, 0x22, 0xb3, 0x24, 0x84, 0x77, 0x0f, 0x2a, 0x98, 0xff, 0xce, 0x36, 0xc2, + 0xaa, 0xc0, 0xe5, 0x4a, 0x15, 0xf5, 0x52, 0x10, 0x08, 0x40, 0x5f, 0x7a, 0x0f, 0x8a, 0xf3, 0xa2, 0xd7, 0x68, 0x08, + 0xd0, 0xc2, 0x52, 0x7d, 0xad, 0x8a, 0xe9, 0xbe, 0xff, 0x9c, 0x9f, 0xf7, 0xe1, 0x1c, 0xd2, 0x36, 0xde, 0xd4, 0xa4, + 0x84, 0x9a, 0x1d, 0xb4, 0x0f, 0x56, 0xd9, 0x5e, 0xf9, 0xb7, 0x21, 0x45, 0x26, 0x7f, 0xc0, 0x7e, 0xa0, 0xb6, 0xc3, + 0xa1, 0x2d, 0x58, 0xf5, 0x52, 0x46, 0xc1, 0x80, 0x95, 0x03, 0x6e, 0x4f, 0x46, 0x09, 0x4d, 0xa6, 0x0c, 0xd4, 0xfd, + 0xa6, 0x68, 0x35, 0xb7, 0x27, 0x75, 0xbf, 0x21, 0xed, 0xec, 0x23, 0xb5, 0xb3, 0x4f, 0x0e, 0x5e, 0x2c, 0x82, 0xfc, + 0x21, 0x42, 0x85, 0xc3, 0xbc, 0x29, 0xd1, 0x51, 0x07, 0xb8, 0x33, 0x70, 0xe0, 0x01, 0x5b, 0x94, 0x83, 0x03, 0x6a, + 0x2d, 0xee, 0x69, 0x23, 0x71, 0xde, 0x9e, 0x50, 0xbb, 0x08, 0x25, 0x6e, 0xd6, 0xcc, 0xb4, 0xa0, 0xb5, 0x42, 0x3b, + 0x8f, 0x7b, 0xbc, 0xcd, 0xb3, 0x5a, 0xfc, 0x84, 0x0d, 0x6b, 0xaa, 0xfa, 0x0d, 0x34, 0x47, 0xb5, 0x20, 0x37, 0x4f, + 0xb5, 0xb7, 0x2a, 0x19, 0x04, 0xc1, 0xd0, 0x70, 0x2a, 0x44, 0x93, 0x8c, 0x41, 0x6b, 0xe8, 0xdd, 0x6a, 0xaf, 0x56, + 0xdc, 0x21, 0xbe, 0xac, 0x79, 0xab, 0xe9, 0x5b, 0x00, 0x5a, 0x84, 0x41, 0x79, 0x6f, 0x12, 0x80, 0xf7, 0x6d, 0x19, + 0x21, 0x6d, 0x39, 0x30, 0x6f, 0x36, 0x96, 0x8a, 0xcd, 0x77, 0x74, 0x32, 0x8c, 0x03, 0x33, 0xa2, 0x00, 0xdf, 0x94, + 0x90, 0x84, 0xab, 0xa4, 0x1b, 0x99, 0x88, 0x39, 0x93, 0x31, 0xc7, 0x37, 0x85, 0x10, 0xea, 0xda, 0x7c, 0x09, 0x5c, + 0xdd, 0xc9, 0x48, 0x7c, 0x33, 0x61, 0xea, 0x1d, 0x2d, 0x26, 0x0c, 0xfc, 0x8a, 0xdc, 0xed, 0x58, 0x4c, 0xc9, 0xc5, + 0x53, 0x19, 0x0e, 0x28, 0x86, 0x07, 0x47, 0x87, 0x58, 0xe9, 0x10, 0x28, 0x15, 0x2e, 0xb2, 0xdb, 0xbd, 0x37, 0x85, + 0xb8, 0xbb, 0x0f, 0x0b, 0x6c, 0x1d, 0x00, 0x4b, 0xa7, 0x49, 0x80, 0x7f, 0xf9, 0x98, 0x8f, 0xd1, 0x98, 0x53, 0xad, + 0xeb, 0xb7, 0xbf, 0xa3, 0x1b, 0xa0, 0xb7, 0xa5, 0xa3, 0xe0, 0xa0, 0x35, 0x84, 0x5c, 0xb8, 0x0b, 0x83, 0x8b, 0x2f, + 0xbf, 0xb6, 0x28, 0xb4, 0x37, 0x16, 0x40, 0xef, 0xaf, 0x04, 0x2c, 0xd8, 0x30, 0xc7, 0x14, 0x5e, 0x6b, 0x9d, 0x30, + 0xe5, 0x45, 0x05, 0x79, 0x52, 0xbe, 0xc7, 0x59, 0xab, 0xfd, 0x96, 0x8d, 0xe1, 0x0e, 0x23, 0xfa, 0x76, 0xe1, 0xc8, + 0x82, 0x07, 0x64, 0x9a, 0xc4, 0x34, 0xfb, 0xc6, 0x45, 0x1e, 0x79, 0x3d, 0x0e, 0x77, 0xb5, 0xe4, 0xe7, 0xeb, 0x15, + 0x5d, 0x63, 0x08, 0x45, 0xe1, 0xf7, 0xfb, 0x15, 0x1e, 0x28, 0xad, 0x0c, 0xda, 0xa0, 0x61, 0x71, 0x9b, 0xff, 0x02, + 0x67, 0x0c, 0xad, 0x17, 0x32, 0x77, 0x74, 0xc6, 0xe1, 0xcc, 0x62, 0xc6, 0x94, 0xc0, 0xa8, 0x94, 0x28, 0xe8, 0x04, + 0x1c, 0x9d, 0xab, 0x0f, 0x92, 0x87, 0xd5, 0xb1, 0x02, 0xf0, 0x24, 0x53, 0xf8, 0x27, 0xdb, 0x04, 0xeb, 0x7e, 0xab, + 0x66, 0x98, 0xfa, 0x8b, 0xda, 0x76, 0x2d, 0x5f, 0xfa, 0x38, 0xd2, 0xc6, 0x10, 0x5a, 0xe7, 0xee, 0x1e, 0x50, 0xc4, + 0x06, 0xbd, 0x88, 0x15, 0xbe, 0x91, 0x8b, 0x91, 0x5e, 0x5f, 0xed, 0x3a, 0xa6, 0x00, 0x51, 0xac, 0xbb, 0x26, 0xbe, + 0xa9, 0x9e, 0x3f, 0x95, 0x71, 0x0e, 0x67, 0x10, 0x84, 0x38, 0x29, 0x2f, 0x1b, 0x62, 0x41, 0x2e, 0x74, 0xa7, 0x42, + 0x77, 0x5a, 0x21, 0x94, 0x4d, 0x8f, 0xca, 0xfb, 0x57, 0x08, 0x61, 0xa0, 0xcb, 0xec, 0xc0, 0xaa, 0x7c, 0x0b, 0xab, + 0xe0, 0xd5, 0x8b, 0x0d, 0xac, 0x12, 0x70, 0x3c, 0x97, 0x68, 0x54, 0x54, 0x38, 0xa4, 0x49, 0x9f, 0x8f, 0x45, 0x90, + 0x00, 0x58, 0xf4, 0x2e, 0xb1, 0x79, 0xdf, 0xc3, 0x21, 0xbf, 0x27, 0x11, 0xf9, 0xd3, 0x8d, 0x68, 0x06, 0xef, 0xe2, + 0xca, 0xbe, 0x43, 0x08, 0x58, 0x7a, 0x8e, 0xe1, 0x3d, 0xe4, 0xef, 0xbf, 0xc3, 0x6a, 0x2d, 0xc8, 0xe3, 0x7f, 0x89, + 0x92, 0xd0, 0xd8, 0x7f, 0x8e, 0x87, 0x16, 0x09, 0xfd, 0x81, 0x6f, 0x8e, 0xb0, 0xc2, 0xc1, 0xad, 0x22, 0x2e, 0x83, + 0x5b, 0x7c, 0xac, 0x43, 0x0f, 0x00, 0x4b, 0x28, 0xf6, 0x41, 0xbe, 0x81, 0x62, 0x1a, 0x07, 0x14, 0x59, 0xfa, 0x17, + 0xb8, 0x60, 0xb5, 0x50, 0xde, 0xdf, 0xb6, 0x9c, 0x94, 0x56, 0xbb, 0xe4, 0xd5, 0xe6, 0x40, 0xe5, 0xa7, 0x7f, 0xe1, + 0x2b, 0xf5, 0x43, 0xcd, 0xf6, 0x0b, 0xdf, 0x58, 0xa0, 0xc7, 0xa0, 0x08, 0xb0, 0xbf, 0xd7, 0x84, 0x3b, 0x8a, 0x5e, + 0xe6, 0x62, 0xbf, 0x6d, 0xaf, 0x7b, 0x89, 0xb9, 0xbc, 0xae, 0xb2, 0xe6, 0x60, 0x0a, 0x0d, 0x0e, 0xaa, 0x70, 0x46, + 0x60, 0x2e, 0x5f, 0x94, 0x05, 0xe7, 0x20, 0xde, 0xf7, 0xa5, 0xce, 0x29, 0xa3, 0x01, 0xbc, 0x48, 0xca, 0x47, 0xa7, + 0xfa, 0x1c, 0x5c, 0xc6, 0x35, 0x9b, 0xf8, 0x44, 0xba, 0x54, 0x60, 0x25, 0x8d, 0x71, 0x68, 0x40, 0x53, 0x3a, 0x07, + 0xb3, 0x0d, 0xa0, 0xe0, 0xf6, 0x7c, 0xd8, 0x58, 0x28, 0xef, 0x2d, 0xda, 0xda, 0xd3, 0xd1, 0x84, 0x58, 0x93, 0x26, + 0xef, 0x6e, 0x5b, 0x23, 0x83, 0x33, 0xbf, 0xfd, 0xb7, 0xc2, 0x22, 0xc1, 0x80, 0x4a, 0x4d, 0x12, 0x84, 0x27, 0x28, + 0x8d, 0x74, 0x2b, 0x37, 0x13, 0x48, 0x27, 0xb2, 0x66, 0xd4, 0xbd, 0x71, 0xbe, 0x5a, 0x6a, 0x20, 0x2b, 0x6a, 0x90, + 0x7b, 0xd4, 0x40, 0xd4, 0xb7, 0x7f, 0x01, 0x0b, 0x61, 0x22, 0x54, 0x49, 0x2f, 0x20, 0xc2, 0x5c, 0x69, 0x3e, 0xa0, + 0x88, 0x7c, 0xc8, 0x6b, 0x40, 0x85, 0x94, 0xbc, 0x04, 0xa3, 0x71, 0x78, 0xbd, 0x07, 0xdc, 0x2f, 0x0d, 0xc3, 0xe0, + 0x38, 0x05, 0x9d, 0xff, 0xd6, 0xe5, 0x43, 0xf5, 0x72, 0x75, 0x10, 0xc2, 0x4f, 0x24, 0x64, 0x98, 0x46, 0x7e, 0x01, + 0xb2, 0x99, 0x63, 0x71, 0x70, 0x20, 0x40, 0xe0, 0x87, 0x28, 0xc2, 0x1e, 0xcf, 0xf0, 0x32, 0xd9, 0x20, 0x7a, 0x6e, + 0x56, 0x79, 0x35, 0x2b, 0xe1, 0xcd, 0xaa, 0x70, 0x34, 0x8e, 0xae, 0x09, 0x03, 0xc1, 0x85, 0x9a, 0x7d, 0x83, 0x10, + 0x28, 0x5b, 0x6e, 0x35, 0x5d, 0x7a, 0x0a, 0xe6, 0xa3, 0x61, 0xf0, 0x96, 0xc1, 0x8b, 0xba, 0xda, 0xe4, 0x9f, 0x29, + 0x96, 0x28, 0xcd, 0x3c, 0x36, 0x3c, 0x27, 0x75, 0x8a, 0xa2, 0xbf, 0x04, 0xcf, 0xc3, 0xa0, 0x79, 0x11, 0xa0, 0x06, + 0xfc, 0xdb, 0xe0, 0xa8, 0x47, 0x23, 0x9a, 0xa6, 0x2e, 0xf8, 0x4d, 0x42, 0xf4, 0x26, 0x5b, 0xad, 0x64, 0x45, 0xd0, + 0x23, 0xb3, 0xc1, 0x80, 0x95, 0x78, 0x02, 0x3b, 0xd6, 0x70, 0xb0, 0xe4, 0x85, 0x0c, 0x73, 0x77, 0x4a, 0xe1, 0x1c, + 0x43, 0x3a, 0xc2, 0x89, 0x17, 0xb3, 0xf1, 0x3f, 0x9f, 0xa9, 0xbf, 0x7e, 0x6e, 0xbe, 0x96, 0x11, 0x11, 0x2e, 0x88, + 0x5c, 0x8d, 0x1d, 0x91, 0x5e, 0xd8, 0x32, 0x35, 0xb0, 0x65, 0x7e, 0x70, 0xd6, 0xd5, 0x43, 0x13, 0x2e, 0x0e, 0x0c, + 0xa8, 0x91, 0x67, 0xb4, 0x82, 0x33, 0x52, 0x0e, 0x1c, 0x94, 0x10, 0x8a, 0x15, 0xe1, 0x94, 0x5c, 0x40, 0x24, 0xbc, + 0x04, 0xf5, 0xc0, 0xb0, 0xc0, 0x93, 0xa0, 0xa6, 0x20, 0x41, 0x25, 0xae, 0x76, 0x0a, 0xb3, 0xce, 0xf4, 0x6c, 0xa7, + 0xa8, 0x67, 0x83, 0xfc, 0xfc, 0xa2, 0xc2, 0x14, 0x58, 0xda, 0x83, 0x83, 0x02, 0x22, 0x88, 0x01, 0x05, 0x2f, 0x25, + 0x40, 0x4f, 0x03, 0x5e, 0x6c, 0x68, 0xc0, 0xe7, 0x4a, 0x7b, 0x1d, 0x68, 0x5b, 0x9f, 0x32, 0xc8, 0xc5, 0xb3, 0x6a, + 0x4f, 0x13, 0x42, 0xf6, 0x5b, 0x7d, 0x15, 0x6f, 0x47, 0x48, 0xec, 0x7f, 0x54, 0x3a, 0xd0, 0x98, 0x25, 0xdd, 0xd5, + 0xc6, 0x7c, 0x55, 0xd3, 0x23, 0x56, 0x93, 0x10, 0x36, 0x48, 0x97, 0xe3, 0xd3, 0x9e, 0xc1, 0x15, 0xab, 0xd0, 0x72, + 0x70, 0x01, 0xfa, 0x6c, 0x40, 0x80, 0x02, 0x95, 0xa6, 0x12, 0x45, 0x11, 0x16, 0x51, 0xc9, 0x86, 0x61, 0x06, 0x61, + 0x0a, 0xab, 0x95, 0xa0, 0x1b, 0x6b, 0x00, 0xbc, 0x33, 0x33, 0x7f, 0x4a, 0x1f, 0x6c, 0xba, 0x76, 0xe6, 0x11, 0x40, + 0x40, 0xf6, 0xdb, 0x25, 0xbb, 0x2e, 0x37, 0x2a, 0x33, 0xbf, 0x96, 0xb6, 0x95, 0xdb, 0xf6, 0x18, 0x7b, 0x21, 0xb7, + 0xf9, 0x04, 0x08, 0x51, 0x5b, 0x32, 0x8d, 0x10, 0x21, 0xb1, 0x08, 0x55, 0x6d, 0xc8, 0x5a, 0x1b, 0x3a, 0xd0, 0x2f, + 0xd2, 0x43, 0xec, 0x03, 0x50, 0xbc, 0x59, 0x2e, 0xc1, 0x22, 0xbc, 0x74, 0x08, 0x7f, 0x97, 0x83, 0x33, 0x3c, 0x66, + 0x58, 0xac, 0x56, 0x50, 0xcf, 0xe1, 0x7d, 0xb2, 0x19, 0x9c, 0x54, 0x6c, 0x8c, 0x5d, 0x98, 0x89, 0x87, 0x65, 0x13, + 0x02, 0x27, 0xd0, 0xaf, 0xab, 0x88, 0xfa, 0xfb, 0xed, 0xf8, 0xa9, 0x0c, 0x6b, 0x3b, 0x10, 0x6b, 0xd6, 0x1b, 0xac, + 0x3e, 0x80, 0x96, 0xff, 0x93, 0xb8, 0x87, 0xca, 0xbc, 0x9b, 0x84, 0x7c, 0x73, 0x11, 0x7b, 0xac, 0x87, 0x18, 0xa9, + 0x2d, 0xee, 0x0e, 0x21, 0xfe, 0x9f, 0xad, 0x28, 0x06, 0x3c, 0xaa, 0xf8, 0xe7, 0x10, 0xf5, 0x20, 0x14, 0xb5, 0xf1, + 0xb0, 0x01, 0x4a, 0xbb, 0x5c, 0x57, 0x62, 0xa4, 0x4f, 0x20, 0xdf, 0xda, 0xf0, 0x82, 0xfa, 0x24, 0xca, 0x41, 0x4e, + 0xf6, 0xa2, 0x92, 0x26, 0x1b, 0xc2, 0x5c, 0x6f, 0x0b, 0xc7, 0xf4, 0xd5, 0x06, 0x2d, 0xc2, 0x17, 0xc0, 0xce, 0x70, + 0x2d, 0x59, 0x5a, 0xf0, 0xe5, 0x35, 0xf0, 0xb9, 0x35, 0xd7, 0x14, 0x25, 0x47, 0xfd, 0x17, 0x52, 0xdf, 0xfa, 0xc3, + 0xef, 0xd8, 0x13, 0x1f, 0xa9, 0xd5, 0x91, 0x6c, 0x84, 0x5a, 0xb3, 0x76, 0xbc, 0x6c, 0x33, 0xc2, 0xa0, 0x34, 0xd1, + 0xfb, 0x2a, 0x64, 0x95, 0x3b, 0x3b, 0x95, 0xde, 0x9c, 0xbe, 0xe6, 0x95, 0x73, 0x2a, 0x37, 0x8c, 0x6a, 0xa9, 0x69, + 0x80, 0x08, 0x57, 0x2e, 0x91, 0xbc, 0x4f, 0x74, 0xf8, 0x07, 0x8d, 0x71, 0xf5, 0x48, 0xe1, 0xef, 0x77, 0xc5, 0x0e, + 0xd9, 0x8e, 0x0e, 0xb7, 0x11, 0x34, 0xcf, 0x57, 0xf0, 0x80, 0xa3, 0x92, 0x21, 0x44, 0x39, 0xb9, 0xd8, 0xcf, 0x6b, + 0xa6, 0x6c, 0x37, 0x01, 0x42, 0x48, 0x39, 0x9c, 0x75, 0x0e, 0x91, 0xb5, 0xd0, 0x23, 0x55, 0x94, 0xc3, 0x2d, 0x9a, + 0x6b, 0x03, 0x54, 0x68, 0x81, 0x74, 0xf9, 0x85, 0xdd, 0xc7, 0x02, 0xa2, 0x97, 0xaf, 0x6d, 0x08, 0x63, 0x6b, 0x65, + 0x89, 0x0b, 0x3d, 0x6a, 0x13, 0x46, 0xd7, 0x6e, 0x0c, 0x6b, 0x03, 0xa3, 0xa7, 0x41, 0x49, 0x0b, 0x42, 0x5d, 0xf7, + 0xe8, 0x79, 0xa2, 0x03, 0x3d, 0x66, 0x84, 0x36, 0x18, 0x9e, 0x12, 0x05, 0x96, 0x4d, 0x05, 0x58, 0xf0, 0x2d, 0x8b, + 0x38, 0xd7, 0x36, 0x9b, 0x2c, 0xfc, 0xa8, 0x42, 0xfd, 0xb4, 0x5f, 0x56, 0x31, 0xcf, 0x85, 0xa5, 0x6e, 0xcf, 0x13, + 0x17, 0x8f, 0xee, 0xe9, 0x9b, 0xeb, 0x17, 0x2f, 0x5f, 0xbf, 0x5a, 0xad, 0xda, 0xac, 0xd9, 0x3e, 0xc1, 0x3f, 0xa9, + 0x32, 0x1e, 0x6c, 0x19, 0x05, 0xe8, 0xe0, 0x60, 0x9f, 0x6b, 0x17, 0x9e, 0x2f, 0x7c, 0x0e, 0x71, 0x83, 0xd4, 0x10, + 0x27, 0x45, 0x19, 0x13, 0xe4, 0x2e, 0xe8, 0x07, 0xf7, 0x01, 0x28, 0xa1, 0x2a, 0xf2, 0xf7, 0x61, 0x73, 0xf6, 0x7b, + 0x10, 0x98, 0x08, 0xea, 0x43, 0x04, 0x10, 0x88, 0x57, 0x8a, 0x0b, 0xc2, 0x5c, 0x02, 0x44, 0xf1, 0x5e, 0xc0, 0x9b, + 0x90, 0x3a, 0x6a, 0xd5, 0x22, 0x0f, 0x0b, 0x20, 0x89, 0x26, 0x1c, 0x25, 0x3d, 0xd2, 0x01, 0xbc, 0x21, 0x28, 0xa5, + 0xf9, 0xd5, 0xcb, 0xac, 0xbb, 0x54, 0x86, 0xfa, 0xad, 0x38, 0xc3, 0x53, 0xfb, 0x39, 0x85, 0xcf, 0x69, 0xcf, 0x9d, + 0x0e, 0xf2, 0x30, 0xc3, 0x0b, 0x22, 0x0f, 0xdd, 0xb3, 0x88, 0xcb, 0x79, 0xc1, 0xbe, 0x72, 0xb1, 0x90, 0xf1, 0xf2, + 0x2e, 0x16, 0xd1, 0x5d, 0x33, 0x3d, 0x0c, 0x8b, 0xe8, 0xae, 0x99, 0x47, 0x77, 0x08, 0xdf, 0xc7, 0x22, 0xba, 0x37, + 0x29, 0xf7, 0xcd, 0x1c, 0x6e, 0xbe, 0x70, 0x0e, 0x87, 0xa2, 0x29, 0xda, 0x58, 0x6c, 0x16, 0x35, 0x29, 0xb6, 0xa8, + 0x87, 0xc1, 0xbf, 0xef, 0xd8, 0xf8, 0x7e, 0xf8, 0x12, 0x5c, 0x9a, 0x34, 0x91, 0x9f, 0x40, 0xfa, 0x69, 0x55, 0x06, + 0xee, 0x53, 0xd2, 0xea, 0x4d, 0xcf, 0x65, 0xb3, 0xdd, 0x6b, 0x34, 0xa6, 0xb0, 0x77, 0x13, 0x92, 0xb9, 0x62, 0xd3, + 0x86, 0x8e, 0xaf, 0xb3, 0x9f, 0xac, 0x56, 0xfb, 0x19, 0xd2, 0x1b, 0x6e, 0xc2, 0x42, 0x35, 0x98, 0x0e, 0x71, 0x0b, + 0x3f, 0x4f, 0x10, 0x5a, 0xb2, 0xc1, 0x74, 0x48, 0xd8, 0x60, 0xda, 0x68, 0x0f, 0x8d, 0xa1, 0x9d, 0xde, 0x8a, 0x6b, + 0x08, 0xa1, 0x39, 0x1d, 0x1e, 0xe9, 0x92, 0xc2, 0xe6, 0x9b, 0x2f, 0x5a, 0x05, 0xf4, 0xcb, 0x6b, 0xc1, 0xcb, 0x04, + 0xee, 0x40, 0x5f, 0xf4, 0xdc, 0x3c, 0xdd, 0x5a, 0x90, 0xe3, 0xa3, 0xca, 0xd5, 0x9e, 0x22, 0xac, 0x7b, 0xca, 0x0f, + 0x8b, 0x43, 0xdd, 0x8c, 0xed, 0x52, 0xd8, 0x6f, 0x5f, 0x33, 0xf2, 0xd1, 0xc2, 0x02, 0x10, 0xa4, 0x82, 0x47, 0x52, + 0xd8, 0x70, 0x4a, 0x3e, 0x5c, 0x2c, 0x54, 0xb6, 0x60, 0x92, 0x91, 0x56, 0x2f, 0xd3, 0x96, 0xfe, 0x99, 0x8d, 0x68, + 0x4a, 0x31, 0x25, 0x89, 0x2b, 0x99, 0x69, 0xb0, 0xd0, 0x4d, 0xca, 0x33, 0x05, 0xbd, 0xd2, 0x10, 0xa7, 0x04, 0xe2, + 0x21, 0xf5, 0x0a, 0x6d, 0xe0, 0x15, 0x4e, 0x9b, 0xc5, 0x80, 0x0d, 0xd1, 0xd1, 0x31, 0xa6, 0x83, 0xcf, 0xc9, 0xbc, + 0x0d, 0x8f, 0x05, 0x7e, 0x1e, 0x92, 0x69, 0x53, 0x94, 0x09, 0x12, 0x12, 0xd2, 0xa6, 0x38, 0x84, 0xbd, 0x84, 0x70, + 0x62, 0x2a, 0x26, 0x03, 0x36, 0x6c, 0x4e, 0xcb, 0x8a, 0x1d, 0x57, 0xb1, 0x21, 0xca, 0x04, 0x53, 0xb1, 0x61, 0x2b, + 0xfa, 0xaf, 0x33, 0x68, 0x10, 0xf8, 0x00, 0x60, 0x00, 0x00, 0x85, 0xbc, 0x68, 0xbe, 0x38, 0x27, 0x6e, 0xb3, 0x9b, + 0x7b, 0xfc, 0x16, 0x58, 0xa0, 0xd5, 0xf6, 0xff, 0x2e, 0x94, 0x01, 0x7b, 0xca, 0x42, 0xc7, 0xcc, 0x2d, 0x8c, 0x8a, + 0x0e, 0xa0, 0x52, 0x22, 0x4c, 0xa1, 0x21, 0xb3, 0x9f, 0x68, 0xa8, 0x79, 0x5a, 0x83, 0x6c, 0xa0, 0x86, 0xcd, 0x04, + 0x8e, 0x18, 0x78, 0x87, 0x86, 0x4c, 0xb5, 0x31, 0x61, 0x98, 0xc1, 0x14, 0x13, 0x0d, 0x9e, 0x69, 0xdc, 0x5a, 0x0b, + 0x2d, 0xcb, 0xf5, 0xb3, 0xfe, 0xdf, 0x2a, 0xcc, 0x07, 0x45, 0xb3, 0x3d, 0x44, 0xfb, 0x84, 0x98, 0x8f, 0x21, 0x6c, + 0x32, 0x9b, 0xda, 0xd0, 0xdf, 0x47, 0x9d, 0xd8, 0x7c, 0xc2, 0x9f, 0xe1, 0x5a, 0xef, 0x00, 0x1d, 0x78, 0x50, 0xaf, + 0xbf, 0xa8, 0xa9, 0xbc, 0x3e, 0xee, 0x8c, 0x52, 0xb9, 0xeb, 0xdd, 0x69, 0x4f, 0x53, 0xec, 0x7b, 0xeb, 0xe1, 0xf2, + 0xa1, 0x1e, 0x02, 0x66, 0x0c, 0xfa, 0x96, 0x19, 0x7d, 0x2f, 0x44, 0x72, 0x41, 0x04, 0x16, 0x1a, 0x6b, 0x18, 0xec, + 0xad, 0x83, 0x03, 0x5d, 0x8d, 0x35, 0xe0, 0x79, 0x52, 0x04, 0x82, 0x81, 0x8b, 0xa0, 0x0c, 0x68, 0x92, 0xeb, 0xdb, + 0x70, 0xf2, 0x91, 0xd9, 0x5f, 0xb8, 0xbc, 0x7d, 0x2c, 0x8c, 0xb6, 0x55, 0x27, 0xdf, 0x97, 0x05, 0xee, 0xcb, 0x7b, + 0x49, 0xa3, 0xe0, 0x46, 0xe6, 0x26, 0x2f, 0xd7, 0x77, 0xeb, 0xae, 0x54, 0x67, 0x77, 0x33, 0x9d, 0xb2, 0x99, 0xce, + 0x76, 0x33, 0xbe, 0x66, 0xe6, 0x5b, 0x56, 0x91, 0xfa, 0x64, 0x8d, 0xe4, 0x9c, 0xe6, 0x3f, 0xd1, 0x39, 0x18, 0x05, + 0x73, 0x73, 0xaf, 0x0a, 0x27, 0x57, 0x46, 0x2e, 0xf6, 0x33, 0x4d, 0x5c, 0x91, 0xbe, 0x50, 0x87, 0x00, 0x2f, 0x2f, + 0xca, 0xc7, 0x07, 0xb8, 0xc8, 0x7f, 0x15, 0xa9, 0x8d, 0x72, 0x9a, 0x0b, 0x25, 0x72, 0x16, 0x20, 0x8d, 0xaa, 0x36, + 0x06, 0xf6, 0xd2, 0xec, 0x3d, 0xd9, 0xe7, 0x83, 0x2a, 0x62, 0xde, 0x50, 0x3f, 0xf7, 0xf1, 0x3d, 0x4d, 0xb1, 0x55, + 0x13, 0x27, 0xe4, 0x43, 0x12, 0x66, 0x20, 0x9b, 0x0d, 0xaa, 0xd7, 0x7e, 0x1b, 0x6d, 0x5c, 0x34, 0x43, 0xd9, 0xd7, + 0x4f, 0x9c, 0xfc, 0x50, 0x68, 0xe3, 0x00, 0xe3, 0xe8, 0x8f, 0x30, 0x35, 0x60, 0x4f, 0x22, 0x47, 0xa1, 0xa3, 0x3b, + 0x93, 0x76, 0xef, 0xa7, 0xdd, 0xeb, 0xb4, 0x0e, 0x94, 0x03, 0xd2, 0x6c, 0xcb, 0x74, 0xee, 0xdd, 0xf7, 0x3d, 0xbc, + 0x74, 0xbb, 0x86, 0x48, 0xdc, 0xf3, 0xc7, 0xda, 0x18, 0xe2, 0x0d, 0xd8, 0x88, 0xca, 0x83, 0x83, 0x3f, 0xac, 0xf7, + 0x6d, 0x25, 0xcb, 0xca, 0x6f, 0x84, 0x03, 0xdb, 0x60, 0x2a, 0x6d, 0x5e, 0x2a, 0x92, 0x05, 0xd8, 0x75, 0xee, 0xef, + 0x8e, 0x87, 0xff, 0x52, 0xfa, 0x4c, 0x8b, 0x71, 0x15, 0x7f, 0x25, 0xd2, 0xd2, 0x43, 0x54, 0x41, 0x04, 0xd2, 0xca, + 0xba, 0xd4, 0x37, 0x1d, 0xbd, 0x9e, 0xd2, 0x54, 0xdc, 0xbe, 0x15, 0x42, 0x0d, 0xcd, 0x8b, 0xdc, 0x2a, 0x82, 0x47, + 0x0b, 0x6b, 0x0c, 0xcd, 0x7d, 0xe9, 0x9d, 0x64, 0x02, 0xa2, 0xd6, 0xc7, 0xed, 0x4b, 0x22, 0xa1, 0xac, 0xee, 0x42, + 0x38, 0xdc, 0x85, 0x60, 0x5e, 0x06, 0x6d, 0x83, 0xd8, 0xed, 0x36, 0x68, 0x5b, 0x28, 0x89, 0x34, 0x81, 0xdb, 0xbd, + 0xc1, 0xc2, 0xde, 0x87, 0x97, 0x63, 0x39, 0x96, 0xee, 0x9a, 0xcc, 0x3c, 0x00, 0x04, 0x6a, 0x1f, 0x56, 0x3c, 0xb1, + 0x20, 0x88, 0xac, 0xe1, 0xe8, 0x7b, 0xce, 0x6e, 0x8d, 0xe5, 0xf0, 0x6c, 0xbe, 0x50, 0x2c, 0xd5, 0x77, 0xd4, 0x80, + 0x3f, 0x75, 0x3f, 0xaf, 0x9f, 0x92, 0x9a, 0x6e, 0xfc, 0x01, 0x84, 0x91, 0xb0, 0xca, 0x0e, 0xad, 0x90, 0x30, 0xc1, + 0xac, 0xca, 0x78, 0x6d, 0xbf, 0x41, 0xbc, 0x07, 0xa5, 0xc3, 0x09, 0x16, 0xb5, 0x0b, 0xaa, 0x00, 0x9b, 0x78, 0x63, + 0x5e, 0x94, 0x87, 0x37, 0x5b, 0x46, 0xd3, 0xcb, 0x35, 0x04, 0x3a, 0xee, 0x07, 0xcd, 0xa0, 0xc1, 0x62, 0x1b, 0x94, + 0xd9, 0x45, 0x18, 0xcf, 0xcf, 0x4f, 0x74, 0x9c, 0xf6, 0x52, 0xaf, 0xfe, 0x5b, 0x02, 0x06, 0xf8, 0x12, 0xbc, 0xc4, + 0xfc, 0xe8, 0xae, 0x03, 0xd5, 0x80, 0xfa, 0xa2, 0xc1, 0x86, 0x68, 0xb5, 0x6a, 0x95, 0xcf, 0x40, 0xd9, 0x6b, 0x2e, + 0x69, 0xae, 0xb9, 0xa4, 0xbd, 0xe6, 0x92, 0xee, 0x9a, 0x4b, 0xea, 0x6b, 0x2e, 0xe9, 0xae, 0xb9, 0x1c, 0x08, 0x3f, + 0x79, 0x71, 0x1c, 0x43, 0x0e, 0x71, 0x15, 0x95, 0x89, 0x8c, 0x07, 0x17, 0x9e, 0xfb, 0x2c, 0x92, 0xe5, 0xf2, 0xfb, + 0x31, 0xe4, 0xb6, 0x6c, 0x25, 0xb4, 0xdb, 0x14, 0x93, 0x10, 0x39, 0xfd, 0xe0, 0xa0, 0x74, 0x77, 0x06, 0x1f, 0xf5, + 0x98, 0xe3, 0xa5, 0x71, 0xa2, 0xfd, 0x03, 0x74, 0xf2, 0xfa, 0xd7, 0xc7, 0x58, 0xac, 0x89, 0xb4, 0x26, 0xf7, 0xfb, + 0x6d, 0x47, 0x29, 0x3e, 0x25, 0x3a, 0x3c, 0x39, 0x8f, 0x94, 0x16, 0x41, 0x10, 0xa2, 0x24, 0xc7, 0x09, 0x11, 0x66, + 0xbf, 0x3b, 0x57, 0x78, 0xad, 0x8a, 0x72, 0x66, 0x25, 0x57, 0x19, 0x38, 0xb1, 0x6b, 0x2b, 0x0c, 0xd4, 0x03, 0x17, + 0x82, 0x44, 0x27, 0xfc, 0xd1, 0xcc, 0x0c, 0x39, 0x4b, 0xca, 0xa4, 0x8f, 0xcd, 0x4c, 0x13, 0xb0, 0x82, 0xec, 0x3b, + 0x98, 0x2d, 0xef, 0x62, 0x8a, 0xef, 0xe3, 0x04, 0xff, 0xbf, 0xec, 0xbd, 0xeb, 0x92, 0xdb, 0x46, 0x96, 0x2e, 0xfa, + 0x2a, 0x55, 0x0c, 0x99, 0x06, 0xc4, 0x24, 0x8b, 0xa5, 0xbd, 0x67, 0x22, 0x0e, 0x58, 0x29, 0x86, 0x2c, 0x59, 0xdd, + 0x72, 0x5b, 0x97, 0x56, 0xa9, 0xdd, 0x76, 0x33, 0x78, 0x68, 0x14, 0x90, 0x24, 0x20, 0x83, 0x00, 0x0d, 0x80, 0x55, + 0xa4, 0x48, 0xbc, 0xfb, 0x8e, 0xb5, 0x56, 0x5e, 0x41, 0xb0, 0xa4, 0x9e, 0xd9, 0xf3, 0xeb, 0x9c, 0x3f, 0x52, 0x31, + 0x91, 0x48, 0xe4, 0x3d, 0x57, 0xae, 0xcb, 0xf7, 0xdd, 0x15, 0xbb, 0xa0, 0xb4, 0x7d, 0x41, 0x94, 0xe1, 0x6f, 0xe9, + 0xf5, 0xf2, 0x10, 0xe2, 0x7d, 0x7a, 0x69, 0x7e, 0x91, 0xb6, 0xa2, 0x00, 0x0f, 0x11, 0x7a, 0x54, 0x07, 0x82, 0x9d, + 0xf1, 0x84, 0x07, 0x70, 0xb2, 0x9a, 0xe5, 0xfc, 0x49, 0x0a, 0xe2, 0x44, 0xc1, 0x21, 0xe0, 0x6a, 0x77, 0x9b, 0x7e, + 0x01, 0xc3, 0x97, 0x0e, 0xb6, 0x1c, 0xde, 0x15, 0xbb, 0x1e, 0x2b, 0xf9, 0x07, 0x60, 0xdf, 0xea, 0xc9, 0x58, 0xdd, + 0x1e, 0x38, 0xeb, 0x52, 0x8a, 0x8e, 0x37, 0xc5, 0xe1, 0xed, 0xf9, 0xec, 0xb0, 0x0b, 0x22, 0xb6, 0x0f, 0x32, 0xac, + 0x75, 0xd2, 0xf0, 0x9f, 0x68, 0xeb, 0x60, 0x31, 0xc2, 0xfe, 0x2f, 0xeb, 0x81, 0x97, 0x90, 0x1a, 0x0a, 0x5c, 0x0c, + 0xb6, 0x1c, 0xad, 0xed, 0x32, 0x0d, 0xdc, 0xd4, 0xa0, 0xd7, 0x0f, 0x14, 0xa2, 0xbc, 0x64, 0x34, 0x37, 0x82, 0x4d, + 0x63, 0xc8, 0xc5, 0xe1, 0xb8, 0x59, 0x0e, 0x79, 0x49, 0xd3, 0x69, 0x10, 0x4a, 0x77, 0x96, 0x0d, 0x24, 0x51, 0xf6, + 0x41, 0xa8, 0x5d, 0x5b, 0x0e, 0xbb, 0xc0, 0xf6, 0xe5, 0x8f, 0x86, 0xb1, 0x7f, 0xb5, 0x7c, 0x2a, 0xa4, 0x8b, 0x78, + 0x05, 0x82, 0xa8, 0xfd, 0x3c, 0x1b, 0x6e, 0xfd, 0xab, 0xcd, 0x53, 0xa1, 0xfc, 0xc6, 0x2b, 0x5b, 0x0e, 0xa9, 0xb3, + 0x16, 0xbe, 0x30, 0x1e, 0x1e, 0x5c, 0x19, 0xda, 0x8e, 0x47, 0xa1, 0xff, 0x36, 0x6b, 0x04, 0x37, 0x36, 0xb4, 0xcf, + 0x17, 0x3e, 0x6c, 0x6d, 0x34, 0xd6, 0x14, 0xd3, 0x2d, 0xf4, 0x6f, 0x32, 0x5b, 0xda, 0xd3, 0xa8, 0xe4, 0xc5, 0xb9, + 0x69, 0xc4, 0x42, 0x18, 0x30, 0xf4, 0x93, 0xf9, 0x00, 0xaa, 0xb9, 0xd3, 0x11, 0xc8, 0xe4, 0x03, 0x3d, 0x58, 0x93, + 0x5a, 0xf5, 0xd7, 0x30, 0x93, 0xff, 0x47, 0x2a, 0x2c, 0x46, 0x77, 0xdb, 0x30, 0x53, 0x7f, 0x44, 0xf2, 0x0f, 0x56, + 0xf1, 0x7d, 0xea, 0x85, 0xda, 0x8f, 0x85, 0x15, 0x18, 0x94, 0xa8, 0x1a, 0xd0, 0x03, 0x11, 0x54, 0x65, 0x90, 0x66, + 0x58, 0x9d, 0x83, 0x7e, 0xf7, 0xb4, 0xea, 0x48, 0x0e, 0x69, 0xad, 0x86, 0x54, 0x30, 0x55, 0x6a, 0x50, 0x1d, 0x8f, + 0xab, 0x94, 0xe9, 0x32, 0xe0, 0x92, 0xbe, 0x4a, 0x95, 0x52, 0xf8, 0x4f, 0x04, 0xa0, 0x73, 0x70, 0x8f, 0xaf, 0xc7, + 0x40, 0x9a, 0x61, 0xe1, 0xb7, 0x66, 0xa7, 0xd7, 0x24, 0xdc, 0x26, 0xc1, 0xc5, 0x00, 0xe7, 0xe8, 0x3a, 0x2c, 0x57, + 0x29, 0x44, 0x50, 0x95, 0x50, 0xdf, 0xdc, 0x34, 0x28, 0x6d, 0x35, 0x08, 0x6b, 0x12, 0xea, 0x4c, 0xb2, 0x51, 0x69, + 0xbb, 0x51, 0x98, 0x2d, 0xe2, 0x7a, 0x46, 0x58, 0x73, 0x36, 0x53, 0x0d, 0x4c, 0x1a, 0x8e, 0x9b, 0x46, 0x6b, 0x51, + 0xa1, 0xa6, 0x30, 0xaf, 0x71, 0x55, 0xa9, 0xea, 0x6e, 0xcf, 0x2d, 0xa5, 0x65, 0x7b, 0xd5, 0x4d, 0xb2, 0x21, 0x97, + 0xa1, 0x0c, 0x83, 0xad, 0x1c, 0xc1, 0x04, 0x92, 0xe4, 0xcc, 0xdf, 0xca, 0x3f, 0xd4, 0xa6, 0x6b, 0x01, 0x73, 0x8c, + 0x59, 0x36, 0x2c, 0xe8, 0x15, 0xb8, 0x07, 0x5a, 0xe9, 0xd5, 0x34, 0xbb, 0xaa, 0x82, 0x64, 0x58, 0xe8, 0x65, 0x93, + 0xf1, 0x3f, 0x85, 0x91, 0x26, 0x33, 0x56, 0xb2, 0xc8, 0x76, 0x75, 0x4a, 0x9c, 0xc7, 0x09, 0x6c, 0x8f, 0xa6, 0xb7, + 0x7c, 0x9f, 0x41, 0x54, 0x10, 0x28, 0x98, 0x31, 0x5f, 0x76, 0xf5, 0xcc, 0xf7, 0x99, 0x65, 0xea, 0x3e, 0x1e, 0x8d, + 0x19, 0xdb, 0xef, 0xf7, 0xab, 0x7e, 0x5f, 0xcd, 0xb7, 0x7e, 0x3f, 0x79, 0x6e, 0xfe, 0xf6, 0x80, 0x41, 0x41, 0x4e, + 0x44, 0x53, 0x21, 0x82, 0x7f, 0x48, 0x9e, 0x22, 0x19, 0xdd, 0x69, 0x9f, 0x5b, 0xce, 0x96, 0xf9, 0x09, 0x08, 0xe6, + 0xf1, 0x78, 0xad, 0xc0, 0xae, 0x25, 0x8a, 0x84, 0x2c, 0xff, 0x29, 0x18, 0xcf, 0xdc, 0x07, 0x58, 0x32, 0x00, 0x61, + 0xab, 0x3c, 0x5d, 0xef, 0xf9, 0x2a, 0x78, 0xa7, 0xe3, 0x5d, 0x63, 0x45, 0x06, 0xe2, 0x16, 0xd8, 0x88, 0xb5, 0xf6, + 0x80, 0x9c, 0x29, 0xc0, 0xf1, 0xe2, 0x78, 0xbc, 0x94, 0xbf, 0x74, 0xb3, 0x75, 0x02, 0x95, 0x02, 0xb7, 0x47, 0x27, + 0x07, 0xff, 0x1d, 0x68, 0x06, 0xe5, 0x30, 0x6f, 0x76, 0xbf, 0x33, 0x27, 0x3f, 0x3d, 0xc5, 0x3f, 0xe1, 0x21, 0x3a, + 0xfd, 0x76, 0x6f, 0xfe, 0xa0, 0xa8, 0x3c, 0x1e, 0xd5, 0xe2, 0x07, 0x9e, 0x1f, 0xf8, 0x85, 0x6f, 0x02, 0xb3, 0xc9, + 0xd4, 0x3b, 0xfb, 0x26, 0xaf, 0x98, 0x7a, 0x8d, 0xe7, 0x4c, 0xbe, 0xc3, 0xe1, 0x5c, 0x8c, 0xea, 0xdd, 0xc8, 0x89, + 0x76, 0xaa, 0x30, 0x0e, 0x06, 0xff, 0x45, 0xb4, 0x4d, 0x08, 0x30, 0xa4, 0x6e, 0x49, 0x33, 0x1b, 0x57, 0x96, 0x78, + 0x96, 0x2e, 0xaf, 0x27, 0x75, 0xb9, 0xd7, 0x8a, 0xa7, 0x03, 0xb0, 0xb8, 0x6d, 0xc0, 0x0b, 0xe0, 0xde, 0x62, 0xeb, + 0x4a, 0xc1, 0xe1, 0x02, 0xe2, 0x14, 0x27, 0x20, 0x82, 0xf6, 0xfb, 0x12, 0xef, 0x15, 0xf4, 0x49, 0x3f, 0x42, 0x30, + 0xe4, 0xcf, 0x12, 0x70, 0xd7, 0xeb, 0xd5, 0x18, 0xdf, 0x4b, 0x21, 0xb8, 0x3e, 0xd3, 0x00, 0xb4, 0xe0, 0x77, 0xf9, + 0x58, 0x4e, 0xbf, 0x89, 0xc0, 0xb3, 0xe5, 0x60, 0xa2, 0xdc, 0x6d, 0x78, 0xda, 0x3f, 0x5a, 0x08, 0xc0, 0x52, 0x3c, + 0x53, 0x82, 0x05, 0x39, 0xc5, 0x5c, 0xfd, 0xbf, 0xe0, 0x23, 0xe6, 0x7b, 0xd2, 0x45, 0x6c, 0xb3, 0x7b, 0x72, 0x65, + 0x20, 0x81, 0xa6, 0x03, 0xe0, 0x21, 0x54, 0x40, 0x57, 0xc6, 0xcf, 0xcf, 0xb2, 0x1e, 0xeb, 0xe3, 0x3f, 0x05, 0xf7, + 0xe9, 0xa7, 0x0a, 0x1f, 0x1d, 0x8e, 0xab, 0x74, 0xb4, 0xa7, 0x14, 0x44, 0x47, 0xb7, 0xcf, 0xa7, 0x2a, 0xfb, 0xa6, + 0x02, 0x2a, 0xcb, 0x51, 0x7b, 0x2a, 0x00, 0x8b, 0x2d, 0x1d, 0x81, 0x4f, 0xb3, 0x7c, 0x42, 0xbe, 0xd7, 0x53, 0x71, + 0x73, 0xad, 0xd3, 0xc5, 0xf3, 0xf1, 0x14, 0xfe, 0x07, 0x62, 0x0f, 0xcb, 0x14, 0xd9, 0xb1, 0xeb, 0xe2, 0x07, 0xf1, + 0xb6, 0xb6, 0xa7, 0x3f, 0xf6, 0x10, 0xe9, 0x78, 0x20, 0x17, 0xea, 0x6b, 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, 0x56, 0xb6, 0xc8, 0xb8, 0x7a, 0x14, 0x52, 0x35, 0x3d, 0xdc, 0x89, 0xfa, 0x41, 0x88, 0x3c, 0x58, 0xa7, 0x2c, + 0x2a, 0xd6, 0x20, 0xb3, 0x07, 0x7f, 0x0f, 0x19, 0x39, 0xca, 0x81, 0xa3, 0xd0, 0x5f, 0x9a, 0x40, 0xe7, 0xf9, 0x29, + 0xd4, 0x79, 0x24, 0xd8, 0x4a, 0x3d, 0x14, 0x56, 0x5e, 0x40, 0x74, 0xb0, 0x85, 0xb1, 0xdc, 0x93, 0x50, 0xb1, 0x29, + 0x13, 0x79, 0x1c, 0xd4, 0x12, 0x30, 0x56, 0x10, 0xcc, 0x59, 0x25, 0x5d, 0x90, 0xf2, 0x46, 0x0f, 0x8b, 0xcc, 0xfd, + 0x9d, 0xa0, 0xfc, 0xdf, 0xa9, 0x9c, 0x70, 0x7d, 0x19, 0x02, 0x1c, 0xed, 0x77, 0x20, 0x4a, 0x8c, 0xf5, 0x8b, 0x16, + 0xef, 0x64, 0xe6, 0x6c, 0x6a, 0x07, 0x09, 0x32, 0xb6, 0xc7, 0xaf, 0x10, 0x5a, 0x2d, 0x14, 0x59, 0x34, 0x5c, 0x30, + 0xdd, 0x9e, 0xd2, 0xaa, 0x7b, 0xd8, 0xf0, 0xac, 0xf4, 0x50, 0xa9, 0x6f, 0x63, 0x02, 0xcb, 0x2a, 0x65, 0xf8, 0x76, + 0x42, 0xd5, 0x89, 0x41, 0xc5, 0xba, 0x65, 0x4b, 0x38, 0xc4, 0x62, 0xd2, 0x58, 0x67, 0x03, 0x1e, 0xb1, 0x04, 0xfe, + 0xd9, 0xf2, 0x31, 0x5b, 0xf2, 0x68, 0xb2, 0xbd, 0x59, 0xf6, 0xfb, 0xa5, 0x17, 0x7a, 0xf5, 0x2c, 0xfb, 0x2e, 0x9a, + 0xcf, 0xaa, 0xb9, 0x8f, 0x8a, 0x8b, 0xc9, 0x60, 0xb0, 0xf5, 0xb3, 0xe1, 0x90, 0x25, 0xc3, 0xe1, 0x24, 0xfb, 0x0e, + 0x5e, 0xfb, 0x8e, 0x47, 0x6a, 0x49, 0x25, 0x37, 0x19, 0xec, 0xef, 0x03, 0x1e, 0xf9, 0xac, 0xf3, 0xd3, 0xb2, 0xe9, + 0xd2, 0xfd, 0xcc, 0x8e, 0xbb, 0xd0, 0x1d, 0x60, 0xe3, 0x6d, 0x83, 0x8e, 0xfc, 0xeb, 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, 0x65, 0xe5, 0x96, 0x0d, 0xd7, 0xc3, 0xc1, 0x36, 0x8a, 0xcb, 0x66, 0x05, 0xf7, 0x85, 0x35, 0x05, 0xfe, + 0xdf, 0xb1, 0x05, 0xbb, 0x97, 0xc7, 0xc0, 0x5b, 0x74, 0x4c, 0x82, 0x0b, 0xc4, 0x3d, 0xbb, 0x03, 0x3b, 0x2c, 0xfc, + 0x05, 0xd7, 0xc9, 0x31, 0xdb, 0xe3, 0xa3, 0xd0, 0x2b, 0xd8, 0x9d, 0x4f, 0x40, 0xbb, 0x60, 0x6b, 0x80, 0x6c, 0x6c, + 0x87, 0x8f, 0x56, 0xc7, 0xe3, 0x5b, 0xcf, 0x67, 0x0f, 0xf8, 0xe3, 0x72, 0x75, 0x3c, 0xee, 0x3d, 0xa3, 0xde, 0xbb, + 0xe5, 0x09, 0x7b, 0xcf, 0x93, 0xc9, 0xed, 0x0d, 0x8f, 0x27, 0x83, 0xc1, 0xad, 0xbf, 0xe0, 0xf5, 0xec, 0x16, 0xb4, + 0x03, 0x97, 0x0b, 0xa9, 0x6b, 0xf6, 0xee, 0x78, 0xe6, 0x2d, 0x70, 0x6c, 0xee, 0xe0, 0xe8, 0xed, 0xf7, 0xbd, 0x15, + 0x8f, 0xbc, 0x3b, 0x52, 0x31, 0xad, 0xb9, 0xe2, 0x78, 0xdb, 0xe1, 0x7e, 0xba, 0xe6, 0x21, 0x3c, 0xc2, 0xaa, 0x4c, + 0x6f, 0x83, 0xf7, 0x3e, 0x5b, 0x6b, 0x16, 0xb8, 0x07, 0xcc, 0xb1, 0x21, 0x3b, 0xa1, 0x99, 0xf8, 0x6b, 0xec, 0x9f, + 0x5b, 0xd5, 0x3f, 0x34, 0xff, 0x4b, 0xdd, 0x4f, 0xe0, 0xf6, 0x45, 0x16, 0x24, 0xf6, 0x9e, 0xdf, 0xb2, 0x7b, 0x6e, + 0xd8, 0x66, 0x2f, 0x4c, 0xd9, 0x67, 0x4a, 0x8d, 0x1f, 0x29, 0x75, 0x63, 0x19, 0x56, 0x32, 0x77, 0x5f, 0x46, 0xe0, + 0x70, 0x40, 0x7e, 0x5a, 0x21, 0x0e, 0x42, 0xeb, 0x26, 0xab, 0xb9, 0xa2, 0x9c, 0x0b, 0x6d, 0x99, 0x79, 0x15, 0xb0, + 0x98, 0xa5, 0x14, 0x1a, 0x0b, 0x00, 0x04, 0x93, 0x42, 0x6b, 0xef, 0x65, 0x00, 0x39, 0x41, 0xc3, 0x9f, 0x9a, 0xab, + 0xa2, 0xac, 0x65, 0x4b, 0x42, 0x94, 0xed, 0x7a, 0x78, 0x8d, 0x90, 0x69, 0xfd, 0xfe, 0x25, 0x91, 0xac, 0x4d, 0xf2, + 0x9b, 0x1a, 0x2d, 0x01, 0x39, 0x59, 0x02, 0x26, 0x7e, 0xae, 0xf9, 0x04, 0xe0, 0x49, 0xc7, 0x83, 0xfc, 0x3b, 0x5e, + 0x33, 0x41, 0x64, 0x1b, 0xb9, 0x3f, 0x29, 0x9e, 0x23, 0x19, 0x41, 0xf1, 0x5d, 0xad, 0x32, 0x16, 0x86, 0x79, 0xa0, + 0x80, 0xbc, 0x07, 0x77, 0xea, 0x5b, 0xfb, 0x63, 0xc7, 0x9e, 0xad, 0x55, 0xa8, 0x85, 0x9a, 0xc2, 0x25, 0x87, 0xe8, + 0x0a, 0x32, 0x50, 0xc8, 0x78, 0xf2, 0x7a, 0x70, 0x3d, 0x89, 0x6e, 0xb8, 0x40, 0x67, 0x7c, 0x7d, 0xd3, 0x4d, 0x67, + 0xd1, 0x77, 0xf9, 0x7c, 0x42, 0x4a, 0xb2, 0xe3, 0x31, 0x1b, 0x55, 0x75, 0xb1, 0x99, 0x86, 0xf2, 0xa7, 0x87, 0xe0, + 0xeb, 0x05, 0xf5, 0x9a, 0xac, 0x52, 0xfd, 0x1d, 0x55, 0xca, 0x8b, 0x86, 0xd7, 0xfe, 0x77, 0xb9, 0xdc, 0xf7, 0x80, + 0xb4, 0x96, 0x97, 0x5c, 0xbe, 0x1f, 0x21, 0xc6, 0x88, 0x1f, 0x78, 0x25, 0x8f, 0x58, 0xa8, 0xa6, 0x70, 0xcd, 0x23, + 0x04, 0x79, 0xcb, 0x74, 0xf0, 0xb7, 0x9e, 0x38, 0xdd, 0x9f, 0x28, 0xed, 0xe2, 0x0b, 0x8b, 0xba, 0x27, 0x6b, 0xeb, + 0x06, 0xe4, 0x60, 0xc3, 0x74, 0x51, 0x90, 0x6d, 0x4a, 0x23, 0x68, 0xa3, 0xe5, 0xc0, 0x86, 0x93, 0xab, 0x0d, 0x67, + 0xae, 0x21, 0xb8, 0x2f, 0x2f, 0xd3, 0xd1, 0x02, 0x3e, 0xa4, 0xba, 0xbd, 0xc4, 0xcf, 0x87, 0x0d, 0x8f, 0x80, 0xcc, + 0x8e, 0xf8, 0xcc, 0x26, 0x92, 0x4e, 0xea, 0x52, 0x01, 0xbb, 0x5d, 0xbc, 0x05, 0x39, 0x62, 0xe6, 0xbe, 0x42, 0xf5, + 0x2d, 0x1a, 0x70, 0x65, 0xac, 0x7d, 0x4d, 0x32, 0x16, 0xde, 0x94, 0xd3, 0x70, 0x90, 0xc3, 0x73, 0xfa, 0xda, 0x72, + 0x9b, 0x65, 0x3f, 0x17, 0x10, 0x04, 0x51, 0x12, 0x8f, 0x0f, 0x78, 0x5f, 0xe6, 0x43, 0x8d, 0x92, 0x8f, 0x65, 0x23, + 0x95, 0x5e, 0x89, 0xfe, 0x6e, 0xcc, 0x25, 0x06, 0x7c, 0x9b, 0xb7, 0x05, 0x85, 0xcb, 0xea, 0x78, 0xbc, 0xac, 0x46, + 0xc6, 0xb3, 0x0c, 0x54, 0x2b, 0xd3, 0x3a, 0x88, 0xcd, 0x7c, 0xb1, 0xf0, 0x17, 0x3b, 0x27, 0x11, 0x51, 0x10, 0xd8, + 0x91, 0xf0, 0x20, 0x52, 0xbf, 0xcc, 0x3d, 0xdd, 0xa9, 0x3e, 0x3b, 0x2c, 0x6c, 0x22, 0xbd, 0xa0, 0x64, 0xf2, 0x49, + 0x70, 0x50, 0xfd, 0x1d, 0x84, 0x0d, 0xe1, 0xcd, 0xab, 0x5e, 0x67, 0x99, 0x9a, 0x95, 0x20, 0x61, 0xc6, 0x1c, 0xc1, + 0xe3, 0xb0, 0xd3, 0xd8, 0x96, 0xc7, 0x16, 0x1c, 0x9d, 0xb7, 0x61, 0x2b, 0xb6, 0x66, 0x77, 0xaa, 0x4e, 0x0b, 0x1e, + 0x4e, 0x87, 0xd7, 0x01, 0xae, 0xbe, 0xcd, 0x25, 0xe7, 0x2b, 0x3a, 0xc1, 0x36, 0x03, 0x1e, 0x4d, 0xc4, 0x6c, 0xf3, + 0x5d, 0xa4, 0x16, 0xcf, 0x66, 0xc8, 0x17, 0xb4, 0xfe, 0xc4, 0x6c, 0x65, 0x92, 0x57, 0x03, 0xbe, 0x98, 0x6c, 0xbe, + 0x8b, 0xe0, 0xd5, 0xef, 0xc0, 0x8a, 0x91, 0x39, 0xb3, 0x6c, 0xf3, 0x5d, 0x84, 0x63, 0xb6, 0xfa, 0x2e, 0xa2, 0x51, + 0x5b, 0xcb, 0x7d, 0xe9, 0xae, 0x01, 0x61, 0xe5, 0x8e, 0xc5, 0xf0, 0x1a, 0x88, 0x67, 0xda, 0x48, 0xba, 0x91, 0x86, + 0xde, 0x98, 0x87, 0xd3, 0x38, 0xd8, 0x50, 0x2b, 0xe4, 0x99, 0x21, 0x66, 0xf1, 0x77, 0xd1, 0x9c, 0xad, 0xb1, 0x22, + 0x5b, 0x1e, 0x0f, 0xae, 0x27, 0xdb, 0x1b, 0xbe, 0x01, 0xf2, 0xb3, 0xc9, 0xd6, 0x6c, 0x51, 0x77, 0x5c, 0xcc, 0xb6, + 0xdf, 0x45, 0xf3, 0xc9, 0x1a, 0x7a, 0xd6, 0x1e, 0x30, 0xef, 0x35, 0x88, 0x50, 0x12, 0x52, 0x53, 0x6e, 0x7a, 0x3d, + 0xb6, 0x19, 0x07, 0x2b, 0xb6, 0xb9, 0x0e, 0xee, 0xd8, 0x66, 0x0c, 0x44, 0x1c, 0xd4, 0xef, 0xde, 0x16, 0x16, 0x5f, + 0xc4, 0x36, 0xd7, 0x26, 0x6d, 0xfb, 0x5d, 0xc4, 0xdc, 0xc1, 0x69, 0xe0, 0x82, 0xb5, 0xcd, 0xbc, 0x35, 0x83, 0x4b, + 0xc8, 0xd2, 0x8b, 0xd9, 0x76, 0x78, 0xcd, 0x36, 0x23, 0x9c, 0xea, 0x89, 0xcf, 0x56, 0xfc, 0x8e, 0x25, 0x7c, 0xdd, + 0xc4, 0x37, 0x5b, 0xd0, 0x88, 0x9e, 0x64, 0xd0, 0x57, 0x50, 0x33, 0x73, 0x5e, 0x5a, 0x50, 0xb9, 0x87, 0x16, 0x1c, + 0x50, 0x90, 0xb6, 0x01, 0x82, 0x24, 0x9e, 0xdd, 0xcb, 0x70, 0x73, 0x2b, 0x85, 0x01, 0x37, 0x81, 0x19, 0x30, 0x30, + 0xfd, 0x0c, 0x7e, 0x58, 0xe9, 0x12, 0x21, 0xce, 0x7e, 0x4a, 0x49, 0x32, 0xcf, 0x4f, 0x45, 0x9a, 0xbb, 0x85, 0xeb, + 0x14, 0x66, 0x45, 0x81, 0xea, 0xa7, 0xa4, 0x34, 0xb0, 0x50, 0x89, 0x4c, 0xa5, 0xe0, 0x97, 0xcd, 0x79, 0x94, 0x9d, + 0xa2, 0x73, 0x5d, 0x5e, 0x4f, 0x9c, 0xd3, 0x49, 0xdf, 0x7f, 0xe0, 0x18, 0xb6, 0x90, 0x81, 0x0b, 0x7f, 0xea, 0x09, + 0xe3, 0xd4, 0x0a, 0xc4, 0x54, 0xf2, 0xec, 0x29, 0x7c, 0x26, 0xb4, 0x3a, 0xba, 0xf0, 0xfd, 0xa0, 0xd0, 0x26, 0xe9, + 0x16, 0x24, 0x29, 0x78, 0x8a, 0x5e, 0x72, 0xde, 0x06, 0x2a, 0xc5, 0x88, 0x16, 0x44, 0xda, 0x5a, 0x66, 0x0e, 0xd2, + 0x96, 0xe6, 0xbb, 0x26, 0x7e, 0x0e, 0x0b, 0xb8, 0x88, 0x16, 0x76, 0xa5, 0xe0, 0x51, 0x15, 0x2b, 0xf7, 0x36, 0xcf, + 0x11, 0xce, 0xe8, 0x5a, 0x26, 0x00, 0xae, 0xf7, 0xab, 0xb0, 0x56, 0x78, 0x45, 0xcd, 0x22, 0x2f, 0x6a, 0xfa, 0x64, + 0x0b, 0xdc, 0xc7, 0xa2, 0x44, 0x81, 0xb3, 0x16, 0x0c, 0xd8, 0x0a, 0x4b, 0x76, 0x52, 0xd8, 0x14, 0x2d, 0xa1, 0x77, + 0xc0, 0x4f, 0x07, 0x35, 0x93, 0x01, 0x34, 0x01, 0x34, 0x1e, 0xff, 0x02, 0x50, 0xd3, 0xdb, 0x5a, 0x6c, 0xaa, 0xa0, + 0x54, 0xca, 0x4d, 0xf8, 0x19, 0x18, 0x66, 0xf8, 0xa1, 0x90, 0xdb, 0x44, 0x89, 0x9c, 0x1f, 0x8b, 0x52, 0x2c, 0x4b, + 0x51, 0x25, 0xed, 0x86, 0x82, 0x47, 0x84, 0xdb, 0xa0, 0x31, 0x73, 0x7b, 0xa2, 0x8b, 0x56, 0x84, 0x72, 0x6c, 0x37, + 0x31, 0xd2, 0x28, 0xb3, 0xb3, 0x5d, 0x27, 0x0b, 0xed, 0xf7, 0x55, 0x0e, 0x59, 0x07, 0xac, 0x91, 0x7c, 0xbd, 0xe6, + 0xd0, 0x6d, 0xa3, 0xbc, 0x78, 0xf0, 0x7c, 0x05, 0xa7, 0x39, 0x9e, 0xd8, 0x5d, 0xaf, 0x3b, 0x45, 0x22, 0x5e, 0xe1, + 0xa4, 0xaa, 0x46, 0xb2, 0x70, 0xdc, 0xb9, 0xd3, 0x5a, 0xac, 0x95, 0x4c, 0xe3, 0x72, 0xd0, 0x00, 0xd0, 0x0c, 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, 0xf3, 0x4a, + 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, 0xce, 0x00, 0x3f, 0x0a, 0xc8, 0x47, 0x09, 0xb8, 0x19, 0x20, 0x7b, 0x64, 0x09, 0x20, 0x56, + 0x8c, 0x4e, 0x26, 0x9f, 0xfb, 0x5e, 0xa4, 0xe0, 0x9d, 0x7d, 0x56, 0xa9, 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, + 0x94, 0x64, 0x9b, 0x86, 0x48, 0x06, 0xcc, 0x88, 0x11, 0x41, 0x65, 0xb9, 0xf0, 0xbf, 0x07, 0x59, 0x14, 0x38, 0x80, + 0xab, 0x99, 0x0c, 0x5e, 0xbb, 0x30, 0x2a, 0x00, 0xce, 0x69, 0xe8, 0x94, 0x0e, 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, 0x4f, 0x5f, + 0xa7, 0xe9, 0xa4, 0xc4, 0x5d, 0xe1, 0x37, 0xe0, 0xa2, 0xd9, 0xe6, 0x43, 0x3f, 0x7d, 0x41, 0x11, 0x17, 0x35, 0xb8, + 0xf2, 0xce, 0xf5, 0x95, 0xea, 0x23, 0xa8, 0x85, 0x27, 0x46, 0xd6, 0xc2, 0x93, 0x4b, 0xd6, 0x5a, 0x10, 0xcc, 0x6c, + 0x0e, 0x5c, 0xc8, 0xaf, 0x94, 0x22, 0xde, 0x46, 0x42, 0x2d, 0x06, 0xad, 0xc7, 0xac, 0x58, 0x3e, 0x5a, 0xa8, 0xcc, + 0x08, 0xed, 0xdb, 0x5a, 0x74, 0x7e, 0x23, 0x3f, 0xe5, 0xa9, 0x7d, 0xd9, 0x1e, 0xe7, 0xd3, 0x3d, 0xba, 0xab, 0xce, + 0x32, 0x93, 0x32, 0x3e, 0x99, 0x25, 0x28, 0xdc, 0x25, 0xd8, 0x80, 0x24, 0xfb, 0xb5, 0x0e, 0x90, 0x51, 0x7b, 0xed, + 0x77, 0x9d, 0xe5, 0x5b, 0xa9, 0x66, 0x6b, 0x28, 0x2a, 0xb5, 0x92, 0x14, 0x07, 0x19, 0xae, 0xdb, 0xdc, 0x87, 0xcd, + 0x14, 0xf4, 0x8c, 0x91, 0xc8, 0x3c, 0x7f, 0x22, 0x5f, 0x82, 0x73, 0xc6, 0x59, 0x21, 0x30, 0x61, 0xac, 0xde, 0xb5, + 0x96, 0x4a, 0x43, 0x8a, 0xb1, 0x93, 0x51, 0x96, 0x55, 0x96, 0x2e, 0xb3, 0xb5, 0x84, 0x2d, 0xab, 0xc8, 0x2d, 0x6c, + 0x99, 0xc9, 0x6a, 0xbe, 0xcf, 0xb9, 0x83, 0xf2, 0xcd, 0x36, 0x19, 0x3f, 0x48, 0x64, 0xef, 0x36, 0x50, 0xc2, 0xf3, + 0xd1, 0x7f, 0x20, 0xfd, 0x36, 0xc3, 0x38, 0xe5, 0xb6, 0x92, 0x16, 0xe0, 0xf4, 0x8f, 0xc7, 0xf7, 0x39, 0x06, 0x0d, + 0x8e, 0x30, 0x8e, 0xac, 0xdf, 0xbf, 0xcb, 0xbd, 0x1a, 0x13, 0x75, 0xf4, 0x42, 0xbf, 0x9f, 0xd3, 0xc3, 0x69, 0x3e, + 0x5a, 0xa7, 0x3b, 0x64, 0x27, 0xb4, 0xb1, 0xf2, 0x83, 0x5a, 0x01, 0xb3, 0xb7, 0x3e, 0x9f, 0x0e, 0x40, 0xc7, 0x02, + 0x24, 0x9a, 0xcd, 0x44, 0x62, 0x4e, 0xba, 0x27, 0xe1, 0xe9, 0x81, 0x05, 0x0e, 0x30, 0x39, 0xff, 0x87, 0xf0, 0x66, + 0x60, 0x83, 0x46, 0x89, 0xbe, 0x46, 0x57, 0xb5, 0xb9, 0xd1, 0xf1, 0xd2, 0x53, 0x48, 0x64, 0x05, 0xcb, 0xe7, 0xbe, + 0xdc, 0xc0, 0x69, 0x0f, 0x35, 0x87, 0xca, 0x12, 0x3c, 0x3d, 0x97, 0xf9, 0xf1, 0xb8, 0xc9, 0xa0, 0xb0, 0xfd, 0x46, + 0x68, 0x6f, 0xcc, 0x52, 0x0d, 0x15, 0xe1, 0xa0, 0xf3, 0xb5, 0x98, 0xd5, 0x23, 0xfa, 0x7b, 0x7e, 0x3c, 0xae, 0x09, + 0x0c, 0x38, 0x2c, 0x65, 0x26, 0x5a, 0x28, 0x96, 0xd6, 0xd9, 0x8c, 0xea, 0xc0, 0x03, 0x13, 0x73, 0x16, 0xee, 0x01, + 0xb4, 0x49, 0xad, 0x02, 0xbd, 0x8a, 0xe8, 0x27, 0xee, 0xd7, 0xf6, 0xeb, 0xf5, 0xc8, 0x2c, 0x1d, 0xb9, 0x31, 0x16, + 0x00, 0x1c, 0x78, 0x59, 0x93, 0x3c, 0x27, 0x5f, 0x43, 0xbb, 0x27, 0x17, 0xf2, 0x27, 0x28, 0x5b, 0x78, 0xa5, 0x9a, + 0x56, 0x16, 0x6b, 0xae, 0xaa, 0x57, 0x17, 0x3c, 0x37, 0x99, 0xd6, 0x69, 0x25, 0x54, 0xac, 0x5f, 0x43, 0x5d, 0xe2, + 0xb5, 0xa6, 0x19, 0xa5, 0x36, 0xea, 0x4c, 0xd4, 0x80, 0x0d, 0xf6, 0x53, 0xb5, 0xd1, 0xc9, 0xb9, 0x7c, 0x79, 0x6d, + 0x1c, 0x3e, 0xed, 0xea, 0xcd, 0x4c, 0xe5, 0xc0, 0x5f, 0xab, 0x1a, 0x5a, 0x3d, 0x06, 0x3a, 0x20, 0xa7, 0x3f, 0x86, + 0xc5, 0xc4, 0xee, 0xd0, 0xaa, 0xdd, 0x5d, 0x56, 0x17, 0xe9, 0x9d, 0xa6, 0x64, 0x56, 0x6f, 0xf9, 0xcc, 0xea, 0xd1, + 0x01, 0x2f, 0x1e, 0xeb, 0xbd, 0xc2, 0x4c, 0x22, 0xb8, 0x18, 0xaa, 0x49, 0x64, 0x77, 0xa0, 0x35, 0x8f, 0x72, 0x26, + 0xc0, 0x0f, 0x4a, 0xad, 0xe9, 0x83, 0xdd, 0x15, 0xea, 0x94, 0xc2, 0xe3, 0xd6, 0x92, 0x1f, 0x98, 0x3b, 0xed, 0x5a, + 0xe7, 0xe3, 0xe5, 0xb5, 0xef, 0x37, 0xf2, 0x84, 0x36, 0x3b, 0x93, 0xd3, 0x3f, 0x55, 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, 0xc7, 0xa3, 0xb8, 0xa9, 0x7c, 0x76, 0xd9, 0x35, 0xb2, 0x72, 0x00, 0x73, 0x88, + 0x82, 0x71, 0x6b, 0x3e, 0xb6, 0x41, 0xba, 0xc4, 0xcd, 0xf8, 0xf4, 0x0d, 0xc5, 0x32, 0xd9, 0x44, 0x5c, 0x5c, 0x55, + 0xdf, 0x3d, 0x03, 0xd2, 0xb2, 0x7e, 0x3f, 0x7a, 0x7e, 0x3d, 0x7d, 0x36, 0x8c, 0x02, 0x70, 0xec, 0xb2, 0x97, 0x97, + 0x31, 0x5f, 0x5d, 0x33, 0xcb, 0x14, 0x16, 0xf9, 0x66, 0x40, 0x75, 0xc9, 0x6a, 0xe9, 0x7a, 0x05, 0x58, 0xba, 0xfc, + 0xe6, 0x21, 0x4c, 0x0d, 0x68, 0x64, 0xcd, 0xdd, 0x69, 0xae, 0x05, 0x4a, 0x3d, 0xef, 0x67, 0x86, 0x7c, 0x5d, 0x06, + 0x5d, 0x41, 0xba, 0xe7, 0x11, 0xe9, 0xe5, 0x41, 0x3a, 0xdd, 0x1f, 0x4a, 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, 0xa3, 0xe6, 0x82, 0x13, 0x62, 0x26, 0xe6, 0x00, 0x2a, 0x41, 0x1b, 0xdf, 0xfa, 0x64, + 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, 0xaf, 0x0d, 0xa6, 0xaf, 0x6f, + 0xb7, 0x45, 0x7e, 0x6a, 0x62, 0xc2, 0x7a, 0xac, 0xe8, 0x9b, 0x77, 0xe1, 0x5a, 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, 0x7a, 0xc5, 0xc8, 0x7c, 0xdc, 0x47, 0xa5, 0x92, 0xfe, 0x79, 0x3c, + 0xce, 0xf2, 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, 0x7b, 0x52, 0x72, 0x78, 0xce, 0x31, 0x27, 0x94, 0x56, 0x84, 0xe5, + 0x7c, 0x91, 0xa1, 0x5c, 0x77, 0x4e, 0xc1, 0x24, 0x87, 0x04, 0xc3, 0x5f, 0x35, 0x6f, 0x62, 0x05, 0xc2, 0xae, 0x91, + 0x33, 0x47, 0x4f, 0xaa, 0x24, 0x2c, 0x05, 0x1c, 0x95, 0x99, 0x67, 0xd8, 0x1b, 0x9e, 0x18, 0x46, 0x0e, 0x56, 0xf9, + 0xa3, 0x3a, 0x11, 0xb9, 0x47, 0x17, 0x18, 0x95, 0x85, 0x57, 0x0d, 0x5d, 0x69, 0x50, 0x49, 0x76, 0xfa, 0x15, 0xd7, + 0x80, 0xda, 0x1a, 0x23, 0x96, 0x83, 0x80, 0x51, 0xf0, 0xda, 0xfe, 0x10, 0xb2, 0x28, 0x5b, 0xbf, 0xc1, 0x31, 0x9f, + 0x95, 0xdc, 0xf5, 0x0e, 0x67, 0xa1, 0x25, 0xe4, 0xc9, 0x1d, 0x83, 0x34, 0x8d, 0xa5, 0x11, 0x70, 0x22, 0x92, 0x6d, + 0x2c, 0x85, 0x23, 0x80, 0x80, 0x40, 0x37, 0x65, 0x86, 0x31, 0x1d, 0x8c, 0x3c, 0x4f, 0x7a, 0xc6, 0x7b, 0x15, 0x9e, + 0x42, 0x9a, 0x6c, 0x5f, 0xcf, 0x3f, 0xe4, 0x5a, 0x90, 0x95, 0x5b, 0xce, 0xe9, 0xb0, 0xf8, 0xc6, 0xd9, 0x57, 0x39, + 0x79, 0x8a, 0x59, 0x46, 0x7a, 0xa7, 0x98, 0x17, 0xf0, 0xa7, 0xb2, 0xd4, 0x93, 0xf4, 0x96, 0xf9, 0x64, 0x15, 0x49, + 0x97, 0xde, 0xb6, 0xdf, 0x8f, 0x47, 0xea, 0x50, 0xf3, 0x0f, 0xf1, 0x48, 0x9e, 0x61, 0x5b, 0x96, 0xb0, 0xd0, 0x2a, + 0x18, 0x03, 0x48, 0x62, 0x23, 0xa2, 0xc1, 0x68, 0x6f, 0x8f, 0xc7, 0xcb, 0xad, 0x39, 0x4b, 0x0e, 0xe0, 0xfa, 0xca, + 0x13, 0xf3, 0x0e, 0x7c, 0x99, 0xc7, 0x04, 0x11, 0x9b, 0x79, 0x5b, 0x56, 0x83, 0x07, 0x3b, 0xb8, 0x3e, 0x62, 0x8b, + 0x62, 0xad, 0x63, 0xc9, 0xad, 0x83, 0xd3, 0x3a, 0x36, 0xcd, 0x48, 0x29, 0xb2, 0xcf, 0xb1, 0x7f, 0x70, 0x83, 0xab, + 0x6b, 0x63, 0x50, 0x6b, 0xdc, 0x61, 0xee, 0x9c, 0x0a, 0xa8, 0xc7, 0x74, 0x05, 0xd5, 0x8b, 0x8a, 0x7c, 0xf9, 0xad, + 0x9d, 0x03, 0x82, 0x46, 0x20, 0x70, 0xd1, 0x40, 0xab, 0x76, 0x29, 0xe7, 0x5d, 0x40, 0x88, 0x6f, 0x52, 0xd0, 0xa7, + 0x33, 0xd8, 0xc4, 0xe6, 0x13, 0x88, 0x45, 0xd3, 0x7d, 0xae, 0x35, 0xf3, 0xc5, 0x88, 0x76, 0x66, 0xdd, 0x2d, 0x72, + 0xab, 0x85, 0x48, 0x46, 0xcf, 0x36, 0x13, 0x2e, 0x3a, 0x94, 0x33, 0x12, 0x30, 0x41, 0x6b, 0x2b, 0x25, 0x9f, 0xeb, + 0x41, 0x27, 0x68, 0x0f, 0x24, 0xad, 0xfb, 0x37, 0x8b, 0xce, 0x28, 0x39, 0xb9, 0xde, 0xe4, 0x0c, 0x52, 0xb0, 0x60, + 0x07, 0x99, 0x13, 0x6e, 0x80, 0x4f, 0x6c, 0x96, 0x9c, 0xa6, 0x41, 0x1e, 0x0b, 0xe3, 0x91, 0xd7, 0xe6, 0x97, 0x05, + 0x74, 0x28, 0x59, 0x34, 0x42, 0x3c, 0xc0, 0xce, 0x21, 0xb9, 0x2a, 0x50, 0x37, 0x0d, 0x74, 0xe5, 0xca, 0x99, 0x62, + 0x0a, 0x5c, 0x08, 0x05, 0x51, 0x3b, 0x3a, 0x89, 0xca, 0x79, 0x9f, 0x54, 0x97, 0xd5, 0xb4, 0x90, 0xa6, 0x81, 0x6a, + 0x9a, 0x3b, 0xe6, 0x81, 0xbd, 0x6d, 0x5c, 0x13, 0x18, 0xe8, 0xd4, 0xbe, 0x16, 0x55, 0xfc, 0x83, 0x74, 0x2f, 0xce, + 0xe1, 0x2f, 0x6b, 0xfa, 0x20, 0xc2, 0x46, 0x0e, 0x1a, 0x4b, 0x89, 0xb1, 0x51, 0xe1, 0xdf, 0x12, 0x65, 0x43, 0x86, + 0x80, 0x10, 0xd2, 0x46, 0x45, 0x3f, 0xac, 0x2f, 0xef, 0x32, 0xed, 0xff, 0x49, 0xe2, 0xb7, 0xc1, 0x5e, 0x4e, 0xfd, + 0xa9, 0x47, 0x3c, 0x5e, 0x1b, 0xf4, 0x98, 0x92, 0x6e, 0x83, 0x3c, 0x55, 0x9e, 0x82, 0x64, 0xc2, 0x58, 0x42, 0xb0, + 0x28, 0x17, 0xbc, 0xe2, 0x39, 0x97, 0x70, 0x1f, 0xb5, 0xac, 0x88, 0x50, 0x95, 0xa8, 0xe8, 0xf3, 0x39, 0xf0, 0x4c, + 0x40, 0xa0, 0x63, 0x8c, 0x34, 0xaa, 0xe0, 0x4b, 0x60, 0xac, 0x03, 0x65, 0xa7, 0x19, 0x09, 0x2e, 0xbb, 0xb7, 0x48, + 0x94, 0xfa, 0x8a, 0x94, 0xa4, 0x6f, 0x45, 0x8d, 0x57, 0x62, 0x15, 0x91, 0x40, 0x86, 0x1a, 0x22, 0x56, 0xd5, 0x53, + 0xf7, 0xa6, 0x98, 0x0c, 0x06, 0xb9, 0x2f, 0xa7, 0x27, 0xde, 0xd0, 0x50, 0x79, 0xd7, 0x15, 0xed, 0xf4, 0x44, 0x2b, + 0xe5, 0x2d, 0xa4, 0x25, 0x68, 0x1a, 0x46, 0x9a, 0x43, 0xa9, 0x6b, 0xe9, 0x6e, 0x0c, 0xe2, 0x4b, 0x26, 0x7a, 0xb6, + 0x53, 0x3b, 0x4a, 0x5b, 0xd2, 0x1e, 0x42, 0x7a, 0xee, 0x92, 0x8f, 0x21, 0x42, 0x4c, 0x55, 0xa5, 0xbc, 0x09, 0xd1, + 0xc9, 0xfd, 0x80, 0x21, 0x11, 0xe8, 0x73, 0x8e, 0x61, 0x5d, 0x34, 0xd4, 0x18, 0x6c, 0x6d, 0xb6, 0x50, 0xc2, 0x7c, + 0xc9, 0x78, 0x2a, 0x19, 0x34, 0x00, 0x32, 0xe0, 0xb3, 0x97, 0x81, 0xe5, 0xaf, 0x20, 0x7e, 0xb4, 0xf1, 0xf1, 0xf8, + 0x67, 0x4d, 0x21, 0xb6, 0x7f, 0xc2, 0x66, 0x08, 0x8f, 0xea, 0x01, 0xcf, 0x7c, 0x13, 0x27, 0x68, 0x05, 0x24, 0x65, + 0x76, 0x34, 0x91, 0xbd, 0xea, 0x21, 0x9c, 0xca, 0x0a, 0xd4, 0x51, 0xd6, 0x59, 0x09, 0x3f, 0xc2, 0x54, 0xb7, 0x12, + 0x6b, 0x81, 0x36, 0x57, 0x2b, 0xd6, 0x02, 0x38, 0xf0, 0x2b, 0x08, 0x9e, 0xa8, 0xe6, 0xe0, 0x62, 0x50, 0x80, 0xcf, + 0x01, 0xf0, 0x22, 0x77, 0xe1, 0xc1, 0x3c, 0xb2, 0xac, 0x46, 0x18, 0x8e, 0x2a, 0x62, 0xfd, 0x9a, 0xed, 0xc8, 0x07, + 0x6e, 0xc7, 0xf8, 0x5c, 0x7b, 0x2c, 0x59, 0x0e, 0x46, 0x99, 0x7b, 0xb5, 0x44, 0xcf, 0x9b, 0x34, 0x6e, 0x46, 0x4f, + 0x0e, 0xb5, 0xfc, 0x5f, 0xd0, 0xcb, 0xa0, 0xbf, 0x85, 0x5b, 0x5e, 0xf3, 0xbb, 0x05, 0x91, 0x66, 0x7a, 0x05, 0x91, + 0x32, 0x6a, 0x44, 0xc6, 0x10, 0x36, 0xa9, 0x6e, 0x65, 0x93, 0xea, 0x42, 0xc0, 0xd3, 0x09, 0xa9, 0xae, 0x85, 0xb4, + 0x51, 0x4d, 0xeb, 0x40, 0xc6, 0x22, 0xbd, 0xfb, 0xf1, 0x2f, 0x2f, 0x3e, 0xbd, 0xf9, 0xe5, 0xc7, 0xc5, 0x9b, 0x77, + 0xaf, 0xdf, 0xbc, 0x7b, 0xf3, 0xe9, 0x37, 0x82, 0xf0, 0x98, 0x0a, 0x95, 0xe1, 0xc3, 0xfb, 0xdb, 0x37, 0x4e, 0x06, + 0xdb, 0x9b, 0x21, 0x6b, 0xdf, 0xc8, 0xc1, 0x10, 0x88, 0x6c, 0x10, 0x32, 0xc8, 0x4e, 0x6d, 0xfb, 0x33, 0x31, 0xc7, + 0xd8, 0x3b, 0x81, 0xc9, 0x16, 0x24, 0x87, 0x65, 0x5e, 0x32, 0x22, 0x57, 0x8e, 0xd6, 0x0f, 0x68, 0xc1, 0x5b, 0x70, + 0x91, 0x49, 0xf3, 0xd5, 0x2f, 0x04, 0xb1, 0x4f, 0x2b, 0xa9, 0xf2, 0xd5, 0xb6, 0xe6, 0xf9, 0xf6, 0x7e, 0x9f, 0xd3, + 0x8a, 0x99, 0x4b, 0x23, 0x6a, 0x01, 0x0e, 0xc0, 0x97, 0xf0, 0xc7, 0x8d, 0xb6, 0xa4, 0xc9, 0x2c, 0xfa, 0x2c, 0x84, + 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, 0xf7, 0x8a, 0x1c, 0x19, 0x3f, + 0x08, 0x26, 0xbe, 0x0a, 0xdc, 0x7f, 0x89, 0x77, 0x38, 0x53, 0x1c, 0xc9, 0x09, 0x7f, 0xc8, 0x30, 0xb0, 0xbf, 0x02, + 0x9f, 0x57, 0x87, 0x79, 0x79, 0xab, 0x4f, 0xb9, 0x25, 0x1f, 0x4f, 0x96, 0x37, 0x60, 0xb0, 0x5f, 0xaa, 0xe6, 0x6e, + 0x78, 0x3d, 0x5b, 0xce, 0xd9, 0x61, 0x16, 0xcd, 0x83, 0x15, 0x9b, 0x65, 0xf3, 0x60, 0xdd, 0xf0, 0x0d, 0xbb, 0xe3, + 0x1b, 0xab, 0x6a, 0x1b, 0xbb, 0x6a, 0x93, 0x2d, 0xbf, 0x03, 0x09, 0xe1, 0x36, 0xf3, 0x72, 0x96, 0xb0, 0x95, 0xcf, + 0xb6, 0x20, 0xd1, 0xae, 0xd9, 0x16, 0x2e, 0x62, 0x1b, 0xfe, 0x63, 0xee, 0x6d, 0x59, 0xc9, 0x2e, 0xc7, 0xac, 0xc2, + 0xf9, 0xe7, 0xc3, 0x03, 0xda, 0x0b, 0xf5, 0xb3, 0x6b, 0xf5, 0x6c, 0xa2, 0xec, 0x66, 0xdb, 0xd1, 0xe2, 0x3e, 0xad, + 0xb6, 0x61, 0x86, 0x9e, 0xe5, 0xf0, 0xd1, 0x56, 0x0a, 0x7e, 0x7a, 0x81, 0x5f, 0xb2, 0xa3, 0xb6, 0xd2, 0xb6, 0x5d, + 0x95, 0xd8, 0x0a, 0x5a, 0x14, 0x59, 0xad, 0xf0, 0xc0, 0x8a, 0x3f, 0x87, 0x05, 0x8c, 0x3d, 0xc7, 0x39, 0xaf, 0xfd, + 0x11, 0x32, 0xde, 0x3b, 0x00, 0x68, 0x99, 0xe3, 0x00, 0x8f, 0x58, 0x31, 0x8a, 0x06, 0xef, 0xf2, 0x5a, 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, 0xb2, 0xb5, 0xaa, 0x3b, 0xbf, 0xa7, 0x4a, 0x97, 0x1c, 0xd9, 0xf2, 0xd3, 0x65, 0xf8, + 0xa0, 0xfe, 0x94, 0x5c, 0x1f, 0x0a, 0x1c, 0xe1, 0xb1, 0x0a, 0x38, 0x5f, 0xcf, 0x45, 0xbb, 0x13, 0x61, 0x57, 0x2e, + 0x01, 0x21, 0xbe, 0xa4, 0x69, 0x8e, 0xc7, 0x11, 0x4d, 0x44, 0xd8, 0xc4, 0xe8, 0x2f, 0xec, 0x3e, 0x94, 0x58, 0x2e, + 0x2b, 0x0d, 0x4a, 0x2e, 0x19, 0xbc, 0x27, 0xed, 0x35, 0x68, 0x96, 0x57, 0xae, 0x26, 0x13, 0x39, 0x28, 0x1f, 0x8f, + 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, 0x4e, 0x1f, 0xce, 0xc4, 0xdc, 0x7a, 0x6e, 0x95, 0x75, 0x92, 0xad, 0x51, + 0x4e, 0xc0, 0xbf, 0xa5, 0x3a, 0x4e, 0x12, 0xe1, 0xd4, 0x7b, 0xc4, 0x45, 0xdd, 0xcb, 0x21, 0xea, 0x86, 0xbd, 0xc9, + 0x75, 0xb0, 0xe5, 0x34, 0x0d, 0x4e, 0xc4, 0xaf, 0xd4, 0x67, 0xef, 0x33, 0x8b, 0x47, 0x1d, 0xd9, 0x88, 0x92, 0x34, + 0x8e, 0x45, 0x0e, 0xdb, 0xfb, 0x42, 0xee, 0xff, 0xfd, 0x3e, 0x84, 0x93, 0x56, 0x41, 0x52, 0x7a, 0x02, 0x11, 0xe1, + 0xe8, 0xf0, 0x23, 0xc2, 0x13, 0xa9, 0x2a, 0x7c, 0x52, 0x9f, 0xb9, 0x31, 0xbb, 0x17, 0xe6, 0xa8, 0xde, 0x01, 0x0c, + 0x63, 0xbd, 0xb3, 0x08, 0x49, 0xb4, 0xd2, 0x8c, 0xb6, 0x1e, 0x10, 0x23, 0xde, 0x6f, 0x2c, 0x32, 0x18, 0x6b, 0x4b, + 0x22, 0x01, 0x7c, 0x45, 0x42, 0x86, 0xb6, 0x8d, 0xc0, 0x8c, 0xe1, 0xed, 0xac, 0xb8, 0x74, 0x1d, 0xb6, 0x39, 0x87, + 0x2f, 0x64, 0xa1, 0x59, 0x47, 0x94, 0x26, 0x08, 0xf9, 0x07, 0x9c, 0x2c, 0x14, 0x46, 0xf3, 0xea, 0x24, 0x9d, 0x24, + 0xd6, 0xf7, 0x5d, 0xa5, 0x82, 0xcd, 0xe6, 0x16, 0xf5, 0x65, 0x27, 0xc9, 0x2f, 0xc1, 0x49, 0xc7, 0x49, 0x16, 0x39, + 0x88, 0x5a, 0x54, 0xce, 0x6d, 0x12, 0x96, 0x76, 0x75, 0xaa, 0xed, 0x66, 0x53, 0x94, 0x75, 0xf5, 0x4a, 0x44, 0x8a, + 0xde, 0x47, 0x3d, 0x7a, 0x22, 0x21, 0x15, 0x5a, 0x95, 0xda, 0xe7, 0x11, 0xb8, 0x6d, 0x6a, 0xc5, 0xb6, 0x5c, 0xc2, + 0x12, 0x35, 0xfe, 0x13, 0xf4, 0x51, 0x2e, 0x1e, 0x64, 0x80, 0x46, 0xc7, 0x53, 0xf3, 0xd6, 0x23, 0xaf, 0x9c, 0xe4, + 0x97, 0x56, 0x9b, 0xf4, 0x0b, 0x20, 0x33, 0xda, 0x3f, 0x5a, 0x4a, 0x20, 0x33, 0x30, 0x93, 0x96, 0x86, 0x44, 0x8e, + 0x62, 0x96, 0xe6, 0x7f, 0xe0, 0x8a, 0xad, 0x10, 0x69, 0x58, 0xcd, 0x3d, 0xfe, 0x22, 0xf7, 0x6a, 0xb9, 0x96, 0x99, + 0xe6, 0x66, 0x89, 0x63, 0xc5, 0xe2, 0xa2, 0x5e, 0x57, 0x22, 0x0b, 0x84, 0x38, 0xc2, 0x34, 0xd6, 0x53, 0x6f, 0x94, + 0x56, 0x1f, 0x90, 0x50, 0xe6, 0x47, 0xec, 0xed, 0xd8, 0xeb, 0x41, 0x16, 0xe2, 0xd8, 0x72, 0xb0, 0xd9, 0x7a, 0x9f, + 0xca, 0x54, 0xc4, 0x17, 0x75, 0x71, 0xb1, 0xad, 0xc4, 0x45, 0x9d, 0x88, 0x8b, 0xef, 0x21, 0xe7, 0xf7, 0x17, 0x54, + 0xf4, 0xc5, 0x43, 0x5a, 0x27, 0xc5, 0xb6, 0xa6, 0x27, 0xaf, 0xb1, 0x8c, 0xef, 0x2f, 0x88, 0xab, 0xe6, 0x82, 0x46, + 0x32, 0x1e, 0x5d, 0x7c, 0xc8, 0x80, 0xe4, 0xf5, 0x22, 0x5d, 0xc3, 0xe0, 0x5d, 0x84, 0x79, 0x7c, 0x51, 0x8a, 0x15, + 0x58, 0x9c, 0xca, 0xce, 0xf7, 0x20, 0xc3, 0x3a, 0xfc, 0x43, 0x5c, 0x00, 0xb4, 0xeb, 0x45, 0x5a, 0x5f, 0xa4, 0xd5, + 0x45, 0x5e, 0xd4, 0x17, 0x4a, 0x0a, 0x87, 0x30, 0x7e, 0x78, 0x4f, 0x5f, 0xd9, 0xe5, 0x6d, 0x16, 0x77, 0x59, 0xe4, + 0x4f, 0xd1, 0xab, 0x88, 0x98, 0x34, 0x72, 0xe1, 0xb5, 0xfb, 0xdb, 0xe6, 0xfe, 0xe1, 0x75, 0x63, 0xf7, 0xb3, 0x3b, + 0x46, 0x74, 0x41, 0x3d, 0x5d, 0x49, 0x4a, 0x05, 0x05, 0x04, 0x4e, 0x34, 0x6b, 0x3c, 0xb8, 0xe3, 0x80, 0x57, 0x03, + 0x5b, 0xb2, 0x8d, 0xcf, 0x9f, 0xc7, 0x32, 0x4c, 0x7b, 0x1b, 0xe0, 0x5f, 0x65, 0x6f, 0xba, 0x09, 0x96, 0x78, 0xdf, + 0x42, 0xb6, 0xa1, 0x37, 0xaf, 0xf8, 0x0b, 0xaf, 0x52, 0x7f, 0xb3, 0x7f, 0x00, 0x10, 0x06, 0xc4, 0xac, 0xfa, 0x68, + 0xe2, 0xde, 0x5b, 0x59, 0xf6, 0x4e, 0x96, 0x7d, 0x0f, 0xfd, 0x9a, 0xc4, 0xa8, 0xb4, 0xb2, 0x94, 0x4e, 0x96, 0x12, + 0xb2, 0x80, 0x4f, 0x8c, 0xa6, 0x36, 0x02, 0x08, 0xdb, 0x51, 0x2a, 0x5f, 0x00, 0xc2, 0x49, 0x02, 0x12, 0x62, 0x09, + 0x17, 0xa3, 0x7b, 0x2b, 0x19, 0x30, 0x1c, 0x42, 0x30, 0x07, 0xed, 0xb0, 0x37, 0x74, 0x13, 0xf1, 0xd7, 0xeb, 0xa2, + 0x7c, 0x13, 0x93, 0x4f, 0xc1, 0xfe, 0xec, 0xe3, 0x12, 0x1e, 0x97, 0x67, 0x1f, 0x87, 0xe8, 0x91, 0x70, 0xf6, 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, 0xfe, 0xab, 0xfb, 0x0a, 0x6e, 0xe3, + 0xfd, 0xfe, 0x32, 0xf7, 0xcc, 0x4f, 0x5c, 0x00, 0xf6, 0xa6, 0x42, 0xeb, 0x04, 0x4a, 0x0d, 0xeb, 0xf0, 0x65, 0x22, + 0xa2, 0x3f, 0xda, 0xe5, 0x3a, 0x73, 0x1d, 0x30, 0xa2, 0x88, 0xdf, 0xc6, 0xa3, 0x3f, 0x40, 0x71, 0x6d, 0xec, 0x01, + 0x61, 0x1d, 0x12, 0xfa, 0x8c, 0x00, 0xa4, 0x1e, 0x73, 0x94, 0x80, 0x66, 0x45, 0x73, 0xc7, 0xc0, 0xc1, 0x2f, 0xaf, + 0x94, 0xfe, 0x61, 0x99, 0x7b, 0x64, 0x4e, 0x69, 0x9b, 0x69, 0xac, 0xd6, 0xe4, 0x02, 0xe1, 0x15, 0x95, 0xac, 0xc2, + 0x67, 0xf3, 0x46, 0xf4, 0xfb, 0xf2, 0x08, 0x4f, 0xab, 0x1f, 0x77, 0x18, 0xdf, 0x0a, 0x88, 0x46, 0x02, 0xa0, 0x9f, + 0x00, 0xe6, 0x45, 0x36, 0xb3, 0xfb, 0x38, 0xa0, 0x4a, 0x89, 0xa6, 0x71, 0x36, 0xcf, 0x6f, 0xe9, 0x4d, 0xd9, 0x41, + 0xe7, 0x4e, 0x15, 0xb8, 0xe0, 0xaa, 0x64, 0xbc, 0xb2, 0x9e, 0xc9, 0xe7, 0x37, 0x77, 0xdb, 0x34, 0x8b, 0xdf, 0x97, + 0xff, 0xc0, 0xb1, 0xd5, 0x75, 0x78, 0x64, 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, 0xca, 0x8b, 0x2e, + 0x06, 0x6b, 0x5f, 0x8e, 0x59, 0x0e, 0x5d, 0xaa, 0x1e, 0xab, 0x87, 0xc6, 0x66, 0x0e, 0x3d, 0x6b, 0x55, 0x9e, 0x79, + 0xf9, 0xf1, 0x88, 0xf8, 0x30, 0xfa, 0x4b, 0x7e, 0xbf, 0xff, 0x8a, 0xe6, 0x1f, 0x13, 0x6a, 0xfc, 0x6c, 0x33, 0x40, + 0xd7, 0xbe, 0x2b, 0x0f, 0x44, 0x3d, 0xd7, 0x2a, 0x41, 0x88, 0x37, 0x88, 0x89, 0x66, 0xc4, 0x1c, 0x9c, 0x76, 0xa8, + 0xf9, 0x27, 0xa9, 0x01, 0x21, 0x4a, 0xbc, 0x8e, 0x29, 0x0b, 0x72, 0xda, 0xc4, 0x91, 0x7e, 0x14, 0x4e, 0xe4, 0x47, + 0x51, 0x15, 0xd9, 0x3d, 0x5c, 0x30, 0x98, 0x7a, 0x4f, 0xfb, 0x25, 0xfa, 0x2d, 0xe1, 0xc8, 0x39, 0x5a, 0x15, 0x82, + 0xc8, 0x19, 0x61, 0xad, 0x21, 0x4c, 0x10, 0x1b, 0xc4, 0xcb, 0xbe, 0x4b, 0x32, 0x1c, 0x29, 0xb8, 0xac, 0x63, 0xc7, + 0x98, 0xab, 0xa3, 0xea, 0x35, 0x80, 0xf1, 0xaa, 0x10, 0x34, 0x1b, 0x45, 0x76, 0x09, 0x51, 0x45, 0x8e, 0x27, 0xa0, + 0x76, 0x50, 0x1a, 0x9b, 0xe9, 0xe5, 0x38, 0x80, 0x09, 0x8e, 0x3a, 0x27, 0x96, 0xf1, 0x1a, 0x80, 0xb5, 0x2b, 0xd5, + 0xcf, 0xb3, 0x1a, 0x3c, 0x69, 0x88, 0xcf, 0xc7, 0x68, 0x7b, 0x65, 0x73, 0x50, 0x6d, 0xa7, 0xb3, 0xf2, 0x9c, 0xe9, + 0x72, 0x60, 0xdc, 0xb7, 0x3c, 0xa7, 0x38, 0xc3, 0x8f, 0x5e, 0x3e, 0xab, 0xe7, 0xfe, 0x74, 0x4b, 0xed, 0xc7, 0xdc, + 0xa8, 0x87, 0x81, 0xd6, 0x82, 0x37, 0x05, 0xb1, 0xfe, 0x7e, 0xe8, 0xc8, 0xf6, 0x5e, 0x8b, 0x8c, 0x26, 0x9f, 0xfd, + 0xfc, 0x43, 0x99, 0xae, 0x53, 0xb8, 0x2f, 0x39, 0x59, 0x34, 0xf3, 0x10, 0xd8, 0x1b, 0x62, 0xb8, 0x3e, 0x2a, 0x3c, + 0xa2, 0xac, 0xdf, 0x87, 0xdf, 0x37, 0x19, 0x98, 0x62, 0xe0, 0xba, 0x42, 0x30, 0x1e, 0x02, 0x41, 0x3c, 0x4c, 0xa3, + 0x93, 0x41, 0x0d, 0xda, 0xf0, 0x2d, 0x40, 0x66, 0x80, 0x47, 0xe6, 0xd2, 0x23, 0xe0, 0x2e, 0x70, 0xed, 0xc9, 0x78, + 0xec, 0x4f, 0x4c, 0x43, 0xa3, 0xa6, 0x34, 0xd3, 0x73, 0xeb, 0x37, 0x1d, 0xd5, 0x72, 0xed, 0xfc, 0xa7, 0x97, 0xfc, + 0x06, 0xbd, 0xa0, 0xe5, 0xe5, 0x3e, 0x52, 0x97, 0xfb, 0x8c, 0xe2, 0x32, 0x91, 0x1c, 0x16, 0xc4, 0xb2, 0x84, 0x03, + 0x8f, 0x51, 0xc9, 0x62, 0x4b, 0x8f, 0x95, 0xd3, 0xf2, 0x45, 0xb9, 0x41, 0x3a, 0x74, 0x42, 0xb0, 0x44, 0x0e, 0xc1, + 0x12, 0x18, 0x17, 0xb1, 0xe1, 0xdb, 0x41, 0xc5, 0xe2, 0xd9, 0x76, 0xce, 0x91, 0xb0, 0x2e, 0x39, 0x1e, 0x0b, 0x09, + 0x36, 0x93, 0xcd, 0x36, 0x73, 0xb6, 0xf1, 0x19, 0x28, 0x01, 0x4a, 0x99, 0x26, 0x28, 0x4d, 0x2b, 0xb6, 0xe2, 0xa6, + 0x35, 0x58, 0xad, 0xa6, 0xec, 0x54, 0x53, 0xf6, 0x4e, 0x53, 0x4e, 0x2a, 0x28, 0x39, 0xa1, 0x14, 0x65, 0x18, 0xc0, + 0x88, 0x4d, 0xa2, 0x9b, 0x0c, 0x7d, 0xbc, 0x13, 0x1e, 0x41, 0x15, 0x11, 0xf9, 0x84, 0x21, 0x04, 0x26, 0xa2, 0xb8, + 0x50, 0x85, 0x62, 0x80, 0x8c, 0x48, 0x20, 0x98, 0xa8, 0xd4, 0x29, 0x30, 0x1f, 0x4d, 0x15, 0xc3, 0xa6, 0x3d, 0x51, + 0xbe, 0xa5, 0x8e, 0x07, 0x94, 0x6d, 0xfe, 0x26, 0xf6, 0x41, 0x88, 0xdc, 0x8d, 0x7b, 0xf5, 0x33, 0xe2, 0xbd, 0xfd, + 0x09, 0xc6, 0x4f, 0x76, 0xda, 0x22, 0x5c, 0x11, 0x6c, 0xa9, 0xe6, 0x10, 0x8c, 0xca, 0x24, 0x41, 0x2d, 0x4b, 0xe2, + 0x6f, 0x79, 0x32, 0xa8, 0xd8, 0x12, 0x3c, 0x68, 0xe7, 0x2c, 0x03, 0xfc, 0x15, 0xab, 0x45, 0xbf, 0xd5, 0xde, 0x12, + 0xe4, 0xa7, 0xad, 0xdd, 0x28, 0x4c, 0x8c, 0x20, 0x51, 0xb7, 0x2b, 0x03, 0xf9, 0xe1, 0x03, 0x4e, 0xc7, 0x53, 0x4f, + 0x19, 0x73, 0x2b, 0xd3, 0xcb, 0x74, 0xae, 0xe4, 0x1b, 0xb9, 0x97, 0x3e, 0xf6, 0x12, 0xec, 0x1c, 0xf0, 0x06, 0xd2, + 0x06, 0xde, 0xc2, 0x76, 0xe1, 0xb5, 0x41, 0xc2, 0x8c, 0x00, 0x5b, 0x9c, 0x1e, 0x23, 0x25, 0x30, 0x84, 0xe3, 0x2c, + 0x05, 0x60, 0x1a, 0x7d, 0x99, 0xcd, 0xed, 0xcb, 0xac, 0xd6, 0x6c, 0xa9, 0x9c, 0xee, 0x9d, 0x5b, 0xb7, 0xf3, 0x89, + 0x04, 0x00, 0x93, 0x3a, 0x07, 0xe2, 0xcc, 0x04, 0xbb, 0x34, 0x89, 0x2c, 0x1f, 0xc3, 0x7c, 0x25, 0x5e, 0x97, 0xc5, + 0x5a, 0x75, 0x45, 0xdb, 0x67, 0xa6, 0x9a, 0x91, 0x4e, 0x42, 0x05, 0x14, 0x14, 0x72, 0xad, 0x4f, 0xdf, 0x85, 0xef, + 0x82, 0x42, 0x03, 0xb3, 0xe5, 0xb8, 0xa7, 0xc9, 0x1a, 0xa9, 0x37, 0xf2, 0x7e, 0x9f, 0x5c, 0x03, 0xa9, 0xce, 0x1c, + 0x5a, 0xf6, 0x04, 0x9d, 0x64, 0x4f, 0x6e, 0xca, 0x52, 0xa8, 0x03, 0xa9, 0x07, 0x0c, 0x21, 0xda, 0xa6, 0x8f, 0x3f, + 0x19, 0x12, 0x5d, 0x80, 0x2d, 0x44, 0x1b, 0xf8, 0xf1, 0x27, 0xd8, 0x67, 0x41, 0x78, 0x4c, 0xf3, 0xb7, 0x90, 0x74, + 0x6a, 0xe0, 0xb4, 0xfa, 0x14, 0x7c, 0x90, 0xe4, 0x60, 0xa2, 0x0e, 0x5e, 0xee, 0x2f, 0xfd, 0x3e, 0x6c, 0xd9, 0x95, + 0x94, 0xea, 0x00, 0x6d, 0x4a, 0xb9, 0xab, 0x2b, 0x3f, 0x88, 0xb6, 0xe0, 0xc8, 0x22, 0xfe, 0x3e, 0x43, 0x44, 0x30, + 0x33, 0x88, 0xb0, 0x6b, 0xa1, 0xee, 0xf6, 0x9c, 0x5a, 0x16, 0xf5, 0xb6, 0xe7, 0x94, 0xba, 0x0d, 0xc3, 0x77, 0x13, + 0xcc, 0x14, 0x37, 0xfc, 0x8f, 0xcc, 0x0b, 0xf5, 0xc6, 0x63, 0x51, 0xa0, 0x7b, 0xfe, 0x61, 0xc9, 0xf3, 0xd9, 0x56, + 0x99, 0x30, 0x57, 0x7c, 0x39, 0x0b, 0x65, 0x57, 0x4b, 0xe3, 0xce, 0x67, 0x6f, 0xa9, 0xe6, 0x83, 0x7f, 0x3c, 0x26, + 0x10, 0x6f, 0x14, 0xdf, 0xac, 0x1a, 0xb9, 0x75, 0x4d, 0xb6, 0x37, 0x25, 0xa0, 0x7e, 0x5f, 0x6e, 0x70, 0xbf, 0xc5, + 0xfa, 0x77, 0x4f, 0x83, 0x8c, 0xd5, 0x0c, 0x57, 0x4c, 0xe1, 0x53, 0x00, 0x18, 0x1c, 0x4e, 0x05, 0x69, 0x81, 0xb7, + 0xbc, 0x1c, 0x5e, 0x4f, 0xb6, 0x64, 0xd2, 0xdd, 0xfa, 0xc8, 0x9d, 0x05, 0xaa, 0xde, 0x6f, 0x28, 0x4e, 0x1a, 0x24, + 0x1a, 0x7b, 0x0d, 0xbe, 0xc8, 0x32, 0xca, 0x45, 0x13, 0xf7, 0x31, 0xf9, 0x4a, 0x0f, 0x60, 0xa5, 0x42, 0x09, 0x10, + 0xfd, 0xc6, 0xb2, 0xd8, 0x88, 0xb6, 0xc5, 0x06, 0x96, 0x52, 0x3e, 0xd7, 0xab, 0xe9, 0xb3, 0x57, 0xa2, 0x79, 0x1f, + 0xcd, 0x38, 0xa5, 0xd1, 0x80, 0xe3, 0x34, 0x0a, 0x77, 0xef, 0xef, 0x45, 0xb9, 0xcc, 0xc0, 0x92, 0xad, 0xc2, 0x29, + 0xae, 0x1b, 0x75, 0x46, 0xbc, 0xc8, 0x63, 0x05, 0xd0, 0xf1, 0x98, 0x00, 0xa8, 0x2e, 0x08, 0xa8, 0x88, 0x96, 0xd2, + 0x5b, 0xa1, 0xc5, 0x42, 0xbd, 0xe1, 0x28, 0x85, 0x3f, 0xd2, 0x9f, 0x07, 0xd5, 0x14, 0x80, 0xd8, 0xf5, 0x71, 0xf4, + 0xba, 0x28, 0xe9, 0x53, 0xc5, 0xac, 0x92, 0x83, 0x09, 0xec, 0xea, 0x44, 0x86, 0x9a, 0x43, 0xde, 0xbc, 0x2b, 0x6f, + 0x6e, 0xf2, 0x36, 0xc6, 0x29, 0xf9, 0x91, 0x9b, 0x8e, 0x35, 0x62, 0xe0, 0x95, 0xa7, 0x75, 0x9a, 0x20, 0x4d, 0x2e, + 0x80, 0x61, 0x88, 0xef, 0x32, 0xef, 0x85, 0xe7, 0x48, 0x55, 0x90, 0xcc, 0xf6, 0x99, 0xa7, 0x2e, 0xa2, 0xfa, 0xca, + 0xa9, 0xa5, 0x33, 0xa7, 0x1f, 0x01, 0xbc, 0xc7, 0xd4, 0xa4, 0x21, 0x1f, 0xe1, 0xb6, 0x14, 0x5f, 0xef, 0xd4, 0x35, + 0x5e, 0x1a, 0x9d, 0xbb, 0x97, 0x2f, 0xdd, 0x69, 0xd0, 0x4f, 0x41, 0x50, 0xce, 0x17, 0xa5, 0x80, 0x3d, 0x65, 0x36, + 0xd7, 0xab, 0x55, 0x2b, 0xb4, 0x8e, 0xc7, 0xb1, 0x76, 0x14, 0xd2, 0xea, 0x2c, 0x60, 0xab, 0x91, 0x4e, 0x09, 0x10, + 0x82, 0xe3, 0x34, 0xec, 0x0c, 0xe3, 0x2e, 0x9d, 0x46, 0x64, 0xbd, 0x52, 0x92, 0x2e, 0xcc, 0x20, 0xf9, 0x27, 0x79, + 0x3d, 0x03, 0x5a, 0x02, 0x38, 0x14, 0xb1, 0x84, 0x87, 0x93, 0xe4, 0x06, 0xa0, 0xd3, 0xe1, 0xa0, 0xd2, 0xd0, 0x9c, + 0xf9, 0x2c, 0x99, 0x4f, 0x62, 0xa9, 0xaa, 0x3c, 0x1e, 0x3d, 0xe5, 0x66, 0xd0, 0xef, 0x67, 0xd3, 0x52, 0xb9, 0x00, + 0x04, 0xb1, 0x2e, 0x0c, 0x10, 0x8f, 0xb4, 0xf0, 0x64, 0xd1, 0xa7, 0x24, 0x7e, 0x39, 0x4b, 0xe6, 0x26, 0x1b, 0xde, + 0x81, 0x11, 0x6c, 0xc6, 0x75, 0x49, 0x99, 0xf6, 0xa8, 0xfc, 0x9e, 0xd1, 0x53, 0xdb, 0xd7, 0x5a, 0x6d, 0x11, 0xeb, + 0x3a, 0xb8, 0x2a, 0x51, 0x4f, 0xf1, 0x41, 0x49, 0x82, 0xf7, 0x2b, 0xe7, 0x66, 0xa4, 0x7c, 0x2d, 0x2a, 0x3f, 0x68, + 0x67, 0x6a, 0xe5, 0xc0, 0x11, 0xa8, 0xb0, 0x8a, 0x4a, 0x5e, 0xef, 0x3a, 0x04, 0x4f, 0xee, 0x4a, 0x05, 0xca, 0xc1, + 0xcf, 0x41, 0x8c, 0xae, 0x6f, 0x3a, 0x6b, 0xa8, 0x99, 0x46, 0x95, 0x47, 0xd0, 0xb9, 0x03, 0x78, 0x52, 0xf0, 0x52, + 0xab, 0x1f, 0x8f, 0x47, 0xcf, 0xfc, 0xe0, 0x2f, 0x33, 0x7d, 0x0b, 0x31, 0x51, 0x4e, 0x35, 0x42, 0xe2, 0x4a, 0x49, + 0x22, 0x3e, 0x5d, 0xb4, 0xac, 0x18, 0x95, 0xe1, 0x03, 0xb0, 0x00, 0x51, 0xf9, 0xea, 0x54, 0xe5, 0xc5, 0x48, 0xdb, + 0x12, 0x78, 0x4d, 0xfe, 0x21, 0x72, 0xcd, 0x5b, 0x5f, 0x77, 0x95, 0xa1, 0x6f, 0x65, 0x05, 0x3a, 0x82, 0xad, 0x2c, + 0x25, 0x07, 0x7c, 0x52, 0xdf, 0x55, 0x5b, 0x9f, 0x53, 0xb6, 0x11, 0x6e, 0xf2, 0xeb, 0xd8, 0xc1, 0x91, 0xf2, 0x1b, + 0xbc, 0x14, 0xc0, 0x5e, 0x03, 0xf6, 0xe6, 0x8a, 0x15, 0xcd, 0xa3, 0x43, 0xda, 0x16, 0x68, 0x64, 0xe6, 0x76, 0xae, + 0xee, 0xdb, 0xf2, 0x28, 0x8d, 0x21, 0x32, 0xed, 0x91, 0xe9, 0x60, 0x33, 0xca, 0x7f, 0x4b, 0xf9, 0xad, 0xc2, 0x31, + 0xf0, 0xed, 0xdc, 0x3b, 0x80, 0xaa, 0xa7, 0x0d, 0x32, 0xd6, 0x0c, 0x43, 0x2b, 0xbb, 0x5c, 0x0a, 0x2d, 0x41, 0x4b, + 0xdd, 0x04, 0xc1, 0xf9, 0x11, 0x51, 0x8e, 0x00, 0x74, 0x91, 0x02, 0x26, 0xf8, 0x39, 0x6d, 0x77, 0xbf, 0xbf, 0x49, + 0x3d, 0x72, 0xef, 0x0a, 0x95, 0xcd, 0xf2, 0x4d, 0x8e, 0x30, 0xf6, 0x13, 0x8d, 0x19, 0x74, 0x72, 0x45, 0x4e, 0x78, + 0xd6, 0xea, 0xb0, 0xae, 0x9b, 0x32, 0x28, 0x8b, 0x63, 0x9e, 0x4f, 0x67, 0xbf, 0x3f, 0x39, 0xd4, 0x0d, 0xb2, 0x90, + 0xff, 0xce, 0x7a, 0x48, 0x06, 0xdd, 0x83, 0x50, 0x88, 0xde, 0x3c, 0x98, 0xe1, 0x7f, 0x6c, 0xcb, 0xb3, 0x6f, 0xb8, + 0x51, 0x27, 0x80, 0x39, 0xe2, 0x7a, 0xe9, 0x29, 0xda, 0x7a, 0xb8, 0x05, 0xb2, 0x0d, 0x5e, 0xde, 0xda, 0x6b, 0xa0, + 0xa2, 0x38, 0xfe, 0x15, 0xcf, 0xd4, 0xca, 0x06, 0x3f, 0x3d, 0x65, 0x3b, 0xf0, 0xf0, 0x22, 0x04, 0x14, 0xc3, 0xb2, + 0xf1, 0x2b, 0xcb, 0x71, 0x46, 0xff, 0xcd, 0x23, 0x86, 0xc1, 0x22, 0xf2, 0xe3, 0xcb, 0x52, 0x88, 0x2f, 0xc2, 0x7b, + 0x93, 0x7b, 0x2b, 0x72, 0xca, 0x5c, 0xe9, 0x61, 0x74, 0x5d, 0x92, 0xbe, 0x49, 0x3e, 0xb6, 0x86, 0xed, 0x77, 0xed, + 0x7e, 0x33, 0x44, 0x10, 0x42, 0x39, 0x7e, 0xce, 0xe8, 0x84, 0xc6, 0x87, 0x35, 0xd7, 0x3b, 0xbd, 0x7e, 0xef, 0x12, + 0x2f, 0xd8, 0x1a, 0x0d, 0xf0, 0x74, 0xe8, 0x62, 0x9e, 0xa8, 0xa1, 0xd3, 0x75, 0xed, 0x1c, 0x3c, 0x30, 0xc8, 0xf2, + 0xe4, 0x1b, 0x86, 0x25, 0xf6, 0x27, 0x11, 0x4f, 0xda, 0xaa, 0x8d, 0xed, 0x89, 0x6a, 0xa3, 0x66, 0xe0, 0x07, 0xaf, + 0xa0, 0xc0, 0xe8, 0x82, 0xb4, 0x06, 0xe3, 0x70, 0x04, 0x20, 0x2b, 0xc6, 0xf1, 0xc8, 0x60, 0x02, 0x43, 0xba, 0xa1, + 0x28, 0x00, 0x0f, 0x8f, 0xd3, 0x41, 0xc8, 0x00, 0xd2, 0x05, 0x0f, 0x0d, 0xdb, 0x24, 0xa4, 0xfc, 0x3c, 0x2f, 0x6b, + 0x35, 0x84, 0xbe, 0xb3, 0x50, 0x1d, 0xfb, 0x91, 0xf6, 0x8a, 0x75, 0xad, 0x4a, 0x27, 0xb6, 0x3a, 0x40, 0xdf, 0x90, + 0x81, 0x6f, 0x1d, 0x5b, 0x00, 0x44, 0x4b, 0xfc, 0x96, 0x7a, 0xb5, 0x2f, 0x63, 0x56, 0xa8, 0xd7, 0x17, 0xa6, 0x5d, + 0xaf, 0xa4, 0x45, 0x01, 0x15, 0xb7, 0xad, 0xda, 0x9e, 0xc8, 0xf9, 0x8f, 0xef, 0x3a, 0xda, 0xf1, 0xd9, 0xa9, 0xb1, + 0x25, 0x94, 0xb9, 0xc5, 0x13, 0x59, 0x1d, 0x6d, 0xa9, 0x4e, 0xf5, 0x01, 0x97, 0x9a, 0x54, 0x67, 0xda, 0xa7, 0xc9, + 0x12, 0xa0, 0xdc, 0x42, 0x24, 0x8d, 0xc3, 0xc1, 0xf9, 0x64, 0x50, 0x30, 0xb7, 0x48, 0x40, 0x02, 0xdb, 0xda, 0xda, + 0x45, 0x73, 0xfd, 0xfa, 0x2d, 0xf5, 0xf2, 0x36, 0x55, 0x3d, 0x78, 0xe3, 0x05, 0xce, 0xde, 0x69, 0x2d, 0x20, 0x80, + 0xc2, 0xd6, 0xb2, 0x1c, 0x9c, 0xbb, 0x5d, 0xd5, 0x52, 0x51, 0x46, 0xfd, 0xfe, 0xe5, 0x6f, 0x29, 0x2a, 0x62, 0xcf, + 0x15, 0xa7, 0xac, 0xdf, 0x6e, 0x99, 0x8b, 0xca, 0x92, 0x37, 0xa8, 0xa2, 0xb5, 0x3a, 0x6a, 0x72, 0xd7, 0xcd, 0x55, + 0x4b, 0x26, 0x88, 0xd1, 0x7d, 0xbe, 0xd6, 0x95, 0x53, 0xef, 0x83, 0x8a, 0x23, 0x06, 0x82, 0x9b, 0xee, 0xf1, 0xc1, + 0x41, 0x68, 0x54, 0x94, 0x0b, 0x6e, 0x94, 0x56, 0x95, 0x94, 0x42, 0xde, 0xaa, 0x68, 0xc5, 0xf4, 0x11, 0x00, 0x11, + 0x60, 0x95, 0xa8, 0xff, 0xcd, 0x97, 0xc6, 0x78, 0xf0, 0xc0, 0xd7, 0xe4, 0x3a, 0xb6, 0xde, 0x3f, 0xaf, 0x91, 0x56, + 0x1b, 0xc7, 0xa4, 0x56, 0xbd, 0x6c, 0x15, 0x2f, 0xbb, 0xd7, 0xa9, 0x18, 0x3c, 0xff, 0x9f, 0xfb, 0x00, 0x35, 0xa2, + 0xa5, 0x0c, 0x6e, 0x5d, 0x0d, 0xd0, 0xf8, 0x70, 0x2a, 0x7c, 0xe3, 0x87, 0x8c, 0xf3, 0xc1, 0x0c, 0x1d, 0xd5, 0xe6, + 0xe0, 0x80, 0xe0, 0xa8, 0xee, 0xd1, 0x98, 0x30, 0x0b, 0xe7, 0x1e, 0x04, 0xaa, 0x4f, 0xdc, 0x67, 0x5c, 0x7b, 0x41, + 0x9b, 0xc0, 0x27, 0xeb, 0xba, 0xa6, 0x08, 0x70, 0x11, 0x1b, 0x13, 0x31, 0xc4, 0x65, 0x93, 0x48, 0x7d, 0x33, 0x06, + 0x05, 0x40, 0xf1, 0x3c, 0x27, 0xb9, 0x74, 0x91, 0xe6, 0x95, 0x28, 0x6b, 0xdd, 0x8c, 0x9c, 0x15, 0xc3, 0x9c, 0xd5, + 0x7e, 0x50, 0xdc, 0xe4, 0x66, 0x42, 0x23, 0x36, 0x90, 0xca, 0x52, 0xb0, 0x7c, 0x58, 0xf8, 0x4d, 0xfb, 0x4d, 0x72, + 0xd2, 0xbb, 0x1c, 0xb7, 0xce, 0x1d, 0xfb, 0xde, 0x51, 0x48, 0x69, 0x0f, 0xc5, 0x04, 0x41, 0xf0, 0xd3, 0x3a, 0x9c, + 0x3f, 0xe3, 0xcf, 0x09, 0x4c, 0x45, 0x36, 0x63, 0xc0, 0x41, 0x88, 0xc8, 0x8c, 0xdf, 0x73, 0xf8, 0x9c, 0x97, 0x93, + 0x70, 0x38, 0xf4, 0x41, 0x1f, 0xca, 0xb3, 0x59, 0x38, 0x14, 0x73, 0xe9, 0xbd, 0x0e, 0xd6, 0xba, 0x90, 0xd7, 0x93, + 0x10, 0xd1, 0x42, 0x43, 0x1f, 0x9c, 0xd7, 0x5d, 0x73, 0x84, 0x25, 0x00, 0x4d, 0x1c, 0x7d, 0x59, 0xbf, 0x1f, 0x79, + 0xda, 0xd0, 0x22, 0xc5, 0x45, 0xa3, 0xcc, 0x66, 0x95, 0xec, 0x84, 0xad, 0x6b, 0xb7, 0x40, 0x28, 0x1e, 0xa6, 0x2d, + 0x54, 0xad, 0xa7, 0x7a, 0x3d, 0x37, 0xed, 0xbe, 0x7b, 0x54, 0xad, 0x72, 0xa2, 0xb3, 0x36, 0x5d, 0xa9, 0xd5, 0x2d, + 0xa3, 0x6a, 0x93, 0xa5, 0x11, 0x55, 0x6e, 0x52, 0xb9, 0x46, 0x2d, 0xf8, 0x64, 0x43, 0xcd, 0xb5, 0xb3, 0x35, 0x38, + 0x71, 0xe4, 0xb9, 0xe4, 0x96, 0xef, 0xce, 0x2b, 0xba, 0x3b, 0xd5, 0xbe, 0x05, 0xb8, 0x37, 0xc3, 0x86, 0xcc, 0x79, + 0x8d, 0x9d, 0x06, 0x61, 0x12, 0xf8, 0x11, 0xfb, 0x98, 0x21, 0x1b, 0x0c, 0xe8, 0x28, 0xa4, 0x26, 0xc0, 0x32, 0x47, + 0x02, 0x26, 0x7f, 0x3d, 0xf7, 0x9b, 0x45, 0x91, 0xc3, 0x62, 0xfc, 0xb0, 0xc5, 0x48, 0x63, 0xb5, 0x06, 0xc3, 0x72, + 0x85, 0xc8, 0x9f, 0xda, 0x33, 0xd4, 0x54, 0xc7, 0x9b, 0xf5, 0x5a, 0xf3, 0xab, 0xa7, 0x4f, 0x75, 0x7d, 0xfe, 0xdb, + 0xf7, 0x97, 0x61, 0xcd, 0xec, 0x0f, 0x41, 0x28, 0xed, 0xc1, 0x2d, 0xce, 0x1d, 0x89, 0xde, 0xa9, 0xd2, 0xcc, 0x2e, + 0xed, 0x9a, 0x5d, 0x9b, 0xd2, 0x6e, 0xc9, 0xf5, 0xea, 0x2b, 0xe5, 0x8d, 0x9d, 0x57, 0x4c, 0xf7, 0x1f, 0x84, 0xde, + 0x51, 0xce, 0xd5, 0x04, 0x22, 0x9a, 0xb4, 0x23, 0x71, 0xbb, 0x57, 0x86, 0xcf, 0x26, 0x55, 0xbb, 0x84, 0x93, 0xae, + 0x61, 0x95, 0xf9, 0xf6, 0x3f, 0xf2, 0xaa, 0xb3, 0xc2, 0xed, 0x97, 0xc6, 0xac, 0xfd, 0x29, 0x88, 0xab, 0xfa, 0xc3, + 0x7b, 0x52, 0x33, 0x25, 0xff, 0x57, 0x3d, 0x06, 0xae, 0x7e, 0x32, 0xed, 0xe4, 0x9e, 0x42, 0xd8, 0x60, 0xf6, 0xf3, + 0xd3, 0x87, 0x16, 0xac, 0xaa, 0x0b, 0x14, 0xc9, 0x01, 0x74, 0xee, 0x9a, 0x11, 0xde, 0xef, 0x18, 0xe7, 0xfe, 0xcd, + 0x0f, 0x6a, 0x72, 0x84, 0x88, 0x76, 0x11, 0x0e, 0x00, 0xe2, 0x4e, 0x53, 0x59, 0x87, 0x1a, 0xa0, 0x0f, 0x08, 0xac, + 0x43, 0xdf, 0x66, 0x00, 0x07, 0x7d, 0xb4, 0x79, 0x16, 0x81, 0xbc, 0xee, 0xdd, 0xb3, 0xb7, 0x6c, 0xef, 0xf3, 0xe7, + 0xeb, 0xd4, 0xbb, 0x47, 0x87, 0xe0, 0xcb, 0xb1, 0x3f, 0xbd, 0x0e, 0x0c, 0x2e, 0x34, 0x7b, 0xfb, 0x54, 0xb0, 0x3d, + 0xdb, 0x3f, 0x45, 0xa4, 0xa2, 0xee, 0xfc, 0xc3, 0x6b, 0x13, 0x3d, 0xef, 0xbc, 0xb0, 0xe2, 0x4b, 0x00, 0x0f, 0x64, + 0x31, 0xa0, 0xf8, 0x2c, 0xbd, 0x7f, 0xb2, 0x04, 0xd4, 0xe4, 0x77, 0x7c, 0xe3, 0xbd, 0xa3, 0xd4, 0x05, 0xfc, 0x39, + 0xa0, 0xf4, 0x49, 0xc5, 0xbd, 0xd5, 0xf0, 0xce, 0xbf, 0x7a, 0x06, 0xce, 0x13, 0xeb, 0xe1, 0x02, 0xfe, 0x2a, 0xf8, + 0xd0, 0x5b, 0x0d, 0x30, 0xb1, 0xe4, 0x43, 0x6f, 0x3d, 0x80, 0x54, 0x85, 0x0b, 0x89, 0xb1, 0x0f, 0xbf, 0x06, 0x15, + 0xc3, 0x3f, 0x7e, 0xd3, 0x18, 0xac, 0xbf, 0x06, 0x85, 0x46, 0x63, 0x2d, 0x55, 0xc8, 0x52, 0x2c, 0x2e, 0x04, 0xd8, + 0x84, 0xe3, 0x6e, 0x5f, 0xac, 0x6a, 0xbb, 0x11, 0xf4, 0xe7, 0x23, 0xbe, 0x47, 0x63, 0x75, 0x55, 0xce, 0x45, 0xf9, + 0x11, 0xe9, 0x53, 0x1d, 0x1f, 0xa3, 0x62, 0x5b, 0x77, 0xa7, 0x53, 0xad, 0x3a, 0xd2, 0x7e, 0x53, 0xae, 0xc1, 0x8e, + 0xd7, 0xc9, 0x89, 0xa5, 0xf0, 0xa2, 0xc3, 0xce, 0x4b, 0xa7, 0x44, 0x87, 0x61, 0xbc, 0xdb, 0xaa, 0x67, 0x0c, 0xe5, + 0x95, 0xc1, 0x98, 0x2e, 0x78, 0xc4, 0x9f, 0x0f, 0x2a, 0x19, 0x1a, 0xf3, 0x01, 0xd9, 0x30, 0x94, 0x0f, 0x2d, 0x32, + 0x24, 0x44, 0xbc, 0x87, 0x4a, 0xc0, 0xb6, 0x05, 0x65, 0x52, 0xc0, 0x59, 0x34, 0xf8, 0xad, 0xf6, 0x2a, 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, 0x28, 0x59, 0xa7, 0x8d, 0x27, 0xc6, 0xdf, 0x5d, 0xe5, 0x9f, 0xa2, 0xa5, 0x1e, 0xfe, + 0x3f, 0x63, 0x0a, 0xa5, 0x7f, 0x99, 0x96, 0xd1, 0x76, 0xbd, 0x14, 0xa5, 0xc8, 0x23, 0x71, 0xf6, 0xb5, 0xc8, 0xce, + 0xe5, 0x3b, 0x9f, 0x42, 0xbf, 0x00, 0xb4, 0xec, 0x13, 0x64, 0xf4, 0x0f, 0x4c, 0xf0, 0xe1, 0x0f, 0xda, 0xb9, 0xb6, + 0xe2, 0xe3, 0x49, 0x75, 0x63, 0xed, 0xdd, 0x8e, 0x17, 0x89, 0x51, 0x8c, 0x55, 0xbe, 0xea, 0x66, 0xe5, 0x44, 0x25, + 0x07, 0x46, 0xba, 0x26, 0x7b, 0x95, 0x92, 0x75, 0x3b, 0xdd, 0x4a, 0x20, 0xa2, 0x0a, 0xbc, 0xc7, 0xb8, 0x8a, 0x7d, + 0x04, 0xd3, 0x75, 0xc7, 0x65, 0xb4, 0xe3, 0x3d, 0xe3, 0xd5, 0x89, 0xb2, 0x82, 0xdb, 0x8d, 0x68, 0x4f, 0xe8, 0xe8, + 0xa7, 0x49, 0x6d, 0x59, 0x38, 0x00, 0xb9, 0x4b, 0x18, 0xcb, 0x86, 0x60, 0xc5, 0xa0, 0xf4, 0xf5, 0x9a, 0x92, 0x65, + 0x01, 0x16, 0x9d, 0x5d, 0x46, 0x20, 0x86, 0x75, 0xd3, 0x9c, 0xd1, 0xf1, 0xd2, 0xc5, 0xf9, 0xa0, 0x55, 0xa4, 0xe0, + 0x19, 0x2d, 0x3a, 0xe6, 0xa6, 0x23, 0xdd, 0x18, 0xed, 0xed, 0x0f, 0x06, 0x21, 0xc5, 0xf3, 0x07, 0xb6, 0x5a, 0x17, + 0x17, 0x89, 0x57, 0xc8, 0x44, 0x0b, 0x62, 0x29, 0x02, 0x33, 0x5e, 0x68, 0x1a, 0x61, 0x82, 0x32, 0x25, 0x58, 0xb4, + 0x46, 0x87, 0xf6, 0x87, 0x25, 0xec, 0x1e, 0x63, 0x04, 0x08, 0x54, 0x99, 0x3e, 0x87, 0xad, 0x09, 0xb3, 0xad, 0x8b, + 0x2d, 0xd0, 0x56, 0x31, 0x34, 0x08, 0x6b, 0x43, 0xcc, 0xc7, 0x34, 0x5f, 0xfd, 0x13, 0x8b, 0xb1, 0x3d, 0x81, 0xd8, + 0xc1, 0xed, 0x9a, 0x84, 0xe9, 0x5e, 0x8b, 0x1b, 0xeb, 0xe5, 0xf6, 0x94, 0x63, 0x6a, 0xc7, 0xda, 0xaa, 0x1d, 0x6b, + 0xa9, 0x77, 0xac, 0x8d, 0xde, 0xb1, 0x56, 0x0d, 0xff, 0x90, 0x79, 0x31, 0x4b, 0x40, 0xbf, 0xbb, 0xe6, 0xaa, 0x41, + 0xd0, 0x8c, 0x2d, 0xbb, 0x83, 0xdf, 0x12, 0x6b, 0xb7, 0xf4, 0xaf, 0x96, 0x6c, 0x61, 0xfa, 0x40, 0xb7, 0x0e, 0xb0, + 0x8c, 0xa8, 0xc9, 0xf7, 0xc8, 0xbb, 0xe9, 0xac, 0x28, 0xdc, 0x9e, 0xd8, 0xc2, 0x67, 0x6f, 0xcd, 0x9b, 0xf7, 0x4f, + 0x23, 0xc8, 0xbd, 0xe7, 0xde, 0xfd, 0xf0, 0xad, 0x7f, 0xa5, 0x5b, 0x20, 0x27, 0xb3, 0x9c, 0x81, 0xd4, 0x11, 0x9f, + 0x20, 0x5a, 0xd9, 0x53, 0xbe, 0x13, 0x72, 0x67, 0xdb, 0x3c, 0xbd, 0x77, 0xb7, 0xb5, 0xd5, 0xd3, 0x7b, 0x96, 0x8f, + 0x28, 0x56, 0x9c, 0xa6, 0x48, 0x98, 0x45, 0x5b, 0xe0, 0xa9, 0x97, 0xef, 0x77, 0xec, 0x98, 0xc3, 0xfd, 0xd3, 0x8e, + 0x8e, 0x97, 0x73, 0xc0, 0xee, 0xfe, 0x93, 0x4d, 0xd8, 0x58, 0xe9, 0x5a, 0x85, 0x0e, 0xf7, 0x4f, 0x33, 0x8d, 0xe7, + 0x70, 0x22, 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, 0xba, 0xe4, 0xb1, 0xef, 0xd3, 0x2c, 0xad, 0xf7, 0xa8, 0xb5, 0xc8, 0x2d, 0xcb, 0xb0, 0xf6, 0x7e, 0xd0, 0x8a, + 0x61, 0xa9, 0xe9, 0x9f, 0x8e, 0x03, 0xb7, 0xb3, 0xdd, 0xca, 0xd8, 0x65, 0x3c, 0x2d, 0xae, 0x7e, 0x38, 0x2f, 0x94, + 0x6b, 0x37, 0x6f, 0xe3, 0x37, 0xad, 0x96, 0x2c, 0xad, 0xf5, 0x90, 0x97, 0x96, 0x45, 0x04, 0x02, 0x18, 0x4e, 0x94, + 0x5d, 0x2c, 0xe1, 0x1e, 0x61, 0x75, 0x0f, 0x42, 0xc9, 0xbc, 0x70, 0xf5, 0x8c, 0xc5, 0x90, 0x08, 0xb0, 0xdd, 0xa1, + 0x62, 0x5b, 0xb8, 0x7a, 0xc6, 0xb6, 0xbc, 0xe8, 0xf7, 0x33, 0xd5, 0x29, 0x64, 0xdd, 0x59, 0xf2, 0xad, 0x6a, 0x8e, + 0x35, 0xd4, 0x6c, 0x63, 0x92, 0xad, 0x71, 0x6e, 0x2b, 0x3e, 0x56, 0x6d, 0xc5, 0xc7, 0xda, 0x5a, 0x97, 0xee, 0xf5, + 0x1e, 0xd5, 0x05, 0xb0, 0xf5, 0xdf, 0x9d, 0xae, 0x5c, 0xcf, 0x67, 0x04, 0xf0, 0xb5, 0xe0, 0xe3, 0xc9, 0x02, 0xbd, + 0x4a, 0x16, 0xfe, 0xdd, 0x40, 0x8d, 0xbf, 0xd3, 0xb9, 0x0b, 0x80, 0xae, 0xa4, 0xbc, 0x02, 0xf2, 0x0e, 0x2a, 0xcc, + 0x2d, 0xbb, 0xf2, 0xfe, 0xec, 0x3b, 0xec, 0x2d, 0xaf, 0x67, 0x8b, 0x39, 0xdb, 0x83, 0x53, 0x41, 0x32, 0xb0, 0x97, + 0x15, 0xdb, 0x07, 0xb1, 0x9d, 0xf0, 0x1b, 0x01, 0x53, 0xbe, 0x80, 0x20, 0xae, 0xe0, 0x0e, 0xe2, 0xf0, 0xe4, 0x9f, + 0x83, 0xfb, 0xd6, 0x66, 0x7d, 0xcf, 0xac, 0xce, 0x09, 0x36, 0xcc, 0xea, 0xc1, 0x60, 0xd9, 0x4c, 0xd6, 0xfd, 0xbe, + 0xb7, 0xd7, 0x8e, 0x4f, 0x2b, 0xa9, 0x13, 0x3b, 0xaf, 0xd5, 0x5a, 0xb0, 0xb7, 0x52, 0xeb, 0x62, 0x0c, 0x3d, 0x80, + 0x5f, 0x70, 0x37, 0xe0, 0xf7, 0x1d, 0x6b, 0xcb, 0x7b, 0xcb, 0x16, 0x6c, 0x0f, 0x97, 0xa0, 0xa6, 0xbd, 0xec, 0xcf, + 0x2a, 0x17, 0xb4, 0x63, 0x97, 0xc4, 0xc3, 0x19, 0xb3, 0x5c, 0x99, 0x59, 0x27, 0xf9, 0x8d, 0xe8, 0x8c, 0xe9, 0xac, + 0xf5, 0x7c, 0xce, 0xe7, 0x93, 0x42, 0x83, 0xfa, 0x5d, 0x12, 0x1f, 0x51, 0xd1, 0x79, 0x02, 0x5b, 0xcb, 0x0a, 0xc8, + 0xbd, 0x2e, 0xc1, 0x5a, 0xab, 0x5d, 0xfa, 0xbd, 0x6a, 0xc0, 0x6d, 0xca, 0x61, 0x4d, 0x40, 0xd0, 0x9c, 0x59, 0x51, + 0x8f, 0xd9, 0x8e, 0x71, 0xf3, 0xd3, 0xcb, 0x1f, 0x9c, 0xb0, 0x64, 0xc5, 0x6a, 0x7f, 0xfa, 0xc3, 0x53, 0x4f, 0x7f, + 0xa7, 0xf6, 0xaf, 0x84, 0x1f, 0x8c, 0xff, 0x5d, 0xbb, 0xaf, 0xb5, 0x18, 0x95, 0xad, 0x72, 0x84, 0xc6, 0xdd, 0x4a, + 0x9a, 0x2c, 0x3f, 0x09, 0x4f, 0x58, 0x0b, 0x9e, 0x99, 0x33, 0x20, 0x2b, 0x60, 0x85, 0xb5, 0x4c, 0xc2, 0x39, 0xc6, + 0x6a, 0x69, 0xab, 0x6f, 0xd1, 0x34, 0xa7, 0x87, 0x73, 0x6d, 0x50, 0xa6, 0x9c, 0x9d, 0x11, 0xab, 0xe1, 0x32, 0x2c, + 0x4d, 0x28, 0x42, 0xf6, 0x60, 0x07, 0x37, 0x76, 0xca, 0x52, 0xca, 0x70, 0x8e, 0xc1, 0x84, 0x27, 0x62, 0x54, 0xee, + 0xfb, 0x87, 0x92, 0x57, 0x6d, 0x39, 0x28, 0x47, 0xd8, 0x47, 0x12, 0x25, 0x70, 0x2b, 0xd2, 0x42, 0x91, 0xb2, 0xf8, + 0xdb, 0x01, 0xba, 0xc0, 0x0b, 0xa8, 0xab, 0x51, 0xb7, 0x3f, 0x1c, 0xf1, 0xf0, 0x91, 0xa9, 0x0f, 0x8c, 0x58, 0x12, + 0xa8, 0xed, 0x45, 0x96, 0xae, 0x40, 0x85, 0xdf, 0xc3, 0xd5, 0x44, 0xec, 0xe7, 0x96, 0x14, 0x15, 0xd9, 0x48, 0x6f, + 0x68, 0x0d, 0x1e, 0xa1, 0x35, 0xe5, 0x07, 0x27, 0xd5, 0x26, 0x9d, 0x77, 0x84, 0x1c, 0xab, 0x6f, 0x2d, 0x61, 0xb4, + 0x2b, 0x7a, 0xf1, 0xe0, 0xe8, 0x3d, 0xcf, 0x57, 0xbd, 0xf2, 0x27, 0xae, 0x98, 0x27, 0xb7, 0x11, 0xa8, 0x5b, 0x41, + 0x75, 0x7b, 0xaf, 0x12, 0x2c, 0x58, 0xd2, 0xee, 0xe3, 0xb7, 0xb3, 0x76, 0x20, 0x2a, 0x63, 0x95, 0xbe, 0x26, 0x09, + 0x7b, 0x62, 0xd0, 0x29, 0x54, 0x55, 0x76, 0x77, 0xb4, 0x05, 0xae, 0x53, 0x96, 0xa2, 0x17, 0xb6, 0xc8, 0xdd, 0xf2, + 0xef, 0x9e, 0x2b, 0x72, 0xf6, 0x6b, 0x40, 0x70, 0x6a, 0xbe, 0x22, 0xbe, 0x9c, 0xe0, 0x51, 0x75, 0x0b, 0x1c, 0xe7, + 0xef, 0x00, 0xfe, 0xf1, 0x78, 0x0d, 0x9a, 0x80, 0x58, 0xb0, 0x5e, 0x1a, 0xf7, 0x58, 0x2f, 0x2e, 0xb6, 0xab, 0x24, + 0xdf, 0x82, 0x33, 0x03, 0xa5, 0x5a, 0xfa, 0x81, 0x53, 0xb5, 0x80, 0x0a, 0x07, 0xb3, 0x93, 0x7a, 0x61, 0x19, 0xf5, + 0x98, 0x3e, 0x3f, 0x83, 0x83, 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, 0x8f, 0xf1, 0x77, 0x3d, 0x23, 0x23, 0x8f, 0x5b, 0x87, 0xd5, 0xff, 0xfa, 0x4f, + 0x08, 0x80, 0xc3, 0xb3, 0xa9, 0x77, 0x3d, 0x86, 0xac, 0xb2, 0x8c, 0x40, 0xf2, 0x13, 0x83, 0x2f, 0x5f, 0x00, 0x54, + 0x7d, 0xa6, 0x6b, 0x35, 0x39, 0x6a, 0x8f, 0x39, 0x74, 0xc5, 0x00, 0xb0, 0x0d, 0x4b, 0x54, 0xd5, 0xc2, 0x26, 0x2c, + 0x6e, 0x3f, 0xc3, 0x68, 0x2e, 0x9b, 0x5e, 0xd0, 0x40, 0x3d, 0x42, 0xf0, 0x4b, 0xeb, 0xa1, 0xb5, 0x96, 0x29, 0x87, + 0xae, 0x8d, 0xa2, 0xca, 0x86, 0xba, 0x84, 0xd5, 0x46, 0x44, 0x35, 0x51, 0xa4, 0x5c, 0x33, 0x8a, 0x62, 0xa9, 0x82, + 0x43, 0x26, 0x56, 0x10, 0x35, 0x4f, 0x5b, 0x6d, 0x15, 0x1c, 0x56, 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, 0x8a, 0x20, 0xb2, 0x00, 0x01, 0x1c, 0x37, 0x10, 0xf8, 0xbc, 0xc6, 0x27, 0xd0, 0x28, 0x04, + 0xf2, 0x03, 0xeb, 0x70, 0xe3, 0x21, 0x2d, 0xb5, 0x46, 0x44, 0x89, 0xf8, 0xc9, 0xd5, 0x73, 0x6c, 0x5f, 0x3d, 0x8d, + 0xb5, 0xa5, 0x34, 0x41, 0xfc, 0xc4, 0x62, 0x0b, 0x31, 0x41, 0x54, 0x87, 0xe8, 0x04, 0x96, 0x13, 0x42, 0x14, 0xfe, + 0x10, 0xfa, 0xa9, 0x81, 0xbf, 0x64, 0xcb, 0x22, 0xaf, 0x09, 0x16, 0x33, 0x67, 0x80, 0x56, 0x45, 0xe0, 0x99, 0xce, + 0x96, 0xca, 0x9c, 0xe6, 0xd1, 0x91, 0x1d, 0x5c, 0x76, 0x1d, 0xec, 0xa5, 0x2f, 0x63, 0x27, 0xcb, 0xa6, 0x51, 0x1b, + 0x1b, 0x22, 0xe1, 0x15, 0xf9, 0xcb, 0x2c, 0x35, 0xce, 0x91, 0x6a, 0x7d, 0xd7, 0xc5, 0x6a, 0x45, 0xdb, 0x84, 0x55, + 0x88, 0x50, 0xb7, 0x0d, 0x95, 0x4b, 0x61, 0x36, 0x36, 0x4d, 0x03, 0x7c, 0xa1, 0xa8, 0x54, 0xca, 0x53, 0x5b, 0xa9, + 0xe4, 0x84, 0x77, 0x7d, 0x55, 0x8b, 0xd4, 0x15, 0xc1, 0x36, 0x66, 0xa8, 0x87, 0x72, 0xa3, 0xc6, 0xbe, 0xee, 0x58, + 0xa5, 0x77, 0x98, 0xa0, 0x62, 0xe4, 0x45, 0x0e, 0x2e, 0x4a, 0x0a, 0x32, 0x57, 0x43, 0x98, 0x3f, 0x6a, 0xf8, 0xb4, + 0xb0, 0xdc, 0x43, 0x09, 0x98, 0x1d, 0x35, 0xbc, 0x8c, 0x10, 0x88, 0xb8, 0x54, 0xf6, 0x15, 0x13, 0xbf, 0xa7, 0x60, + 0x96, 0x4c, 0xe8, 0x5e, 0xc4, 0xc2, 0x08, 0x6d, 0x7c, 0x92, 0x24, 0x53, 0xb9, 0x3e, 0x41, 0x17, 0x2a, 0x5c, 0x20, + 0x23, 0xb4, 0x48, 0xf3, 0x4f, 0x87, 0x53, 0x09, 0x3e, 0xa2, 0x4e, 0x01, 0xc7, 0xf3, 0xcb, 0xc2, 0xfa, 0xc9, 0x2a, + 0x89, 0xb9, 0xac, 0xcd, 0x7f, 0xd9, 0xc9, 0x31, 0xd8, 0xe5, 0x69, 0xe2, 0xb8, 0xfa, 0x8f, 0xaa, 0xa4, 0x78, 0xf8, + 0x39, 0xcd, 0x01, 0x45, 0x30, 0xb3, 0xa7, 0x18, 0x1f, 0xfb, 0x2c, 0x53, 0xc0, 0xdf, 0xae, 0xb7, 0x96, 0x4c, 0xec, + 0x92, 0x76, 0x2b, 0x65, 0xfc, 0x52, 0x1b, 0x76, 0x1c, 0x5c, 0x1a, 0x80, 0xe2, 0xac, 0xd1, 0x61, 0x79, 0xad, 0xdb, + 0x56, 0x8e, 0x0a, 0xd4, 0xfa, 0xdf, 0xbb, 0x85, 0x29, 0x6f, 0xf3, 0x52, 0x79, 0x9b, 0x87, 0x26, 0x40, 0x20, 0x32, + 0x43, 0x9e, 0x35, 0x1d, 0x93, 0xc4, 0xbd, 0x23, 0x25, 0xed, 0x3b, 0x52, 0xfc, 0xe8, 0x1d, 0x09, 0xf9, 0x96, 0xd0, + 0x91, 0x7d, 0xc9, 0xc9, 0x09, 0x94, 0x19, 0xec, 0xe5, 0x0d, 0x93, 0xfd, 0x03, 0xda, 0x0b, 0xe7, 0xb2, 0xbc, 0xe6, + 0x6f, 0x85, 0xb7, 0xf1, 0xa7, 0x9b, 0xf3, 0xae, 0xaa, 0x77, 0x5f, 0x99, 0x99, 0xc7, 0x63, 0x71, 0x3c, 0xe6, 0x26, + 0x68, 0x77, 0xc1, 0xc5, 0xa0, 0x62, 0xf7, 0x6e, 0x7c, 0xfc, 0x5b, 0x8e, 0x22, 0xb6, 0x52, 0x1e, 0x49, 0x17, 0x2a, + 0x31, 0xbc, 0x36, 0xf0, 0x30, 0x7b, 0x3e, 0x9e, 0xec, 0x6f, 0xee, 0x27, 0x83, 0xc1, 0x5e, 0xf5, 0xed, 0x8e, 0xd7, + 0xb3, 0xfd, 0x9c, 0x3d, 0xf0, 0xbb, 0xe9, 0x2e, 0x38, 0x34, 0xb0, 0xed, 0xee, 0x6f, 0xc4, 0xf1, 0xb8, 0x7f, 0xce, + 0x17, 0xfe, 0xe1, 0x01, 0x01, 0x9d, 0xf9, 0xe5, 0xb8, 0x8d, 0xf1, 0x73, 0xdb, 0x76, 0xd5, 0xda, 0x03, 0x3c, 0xfd, + 0x8f, 0xde, 0xed, 0x6c, 0x39, 0xf7, 0xd9, 0x13, 0xfe, 0x00, 0xfe, 0xf9, 0xb8, 0x49, 0x22, 0xf5, 0x89, 0x76, 0x99, + 0xbc, 0x05, 0x07, 0xf2, 0xbd, 0xcf, 0xde, 0xf0, 0x87, 0xd9, 0x72, 0xce, 0x8b, 0xe3, 0xf1, 0xfd, 0x34, 0x44, 0xb2, + 0xa6, 0xb0, 0x22, 0x96, 0x14, 0xcf, 0x0f, 0xc2, 0xd3, 0xf7, 0x22, 0x32, 0x44, 0x5a, 0xee, 0xdd, 0x21, 0xbb, 0x65, + 0x91, 0x1f, 0xc0, 0x07, 0xd9, 0xde, 0x9f, 0xc8, 0x9a, 0xd2, 0xfd, 0xe2, 0x89, 0x7f, 0x3c, 0xd2, 0x5f, 0x6f, 0xfc, + 0xe3, 0xf1, 0x3d, 0x7b, 0x40, 0x70, 0x74, 0xbe, 0x87, 0xfe, 0xd1, 0xb7, 0x0e, 0xa8, 0xca, 0xf0, 0xed, 0x6c, 0x3b, + 0xf7, 0x9f, 0xaf, 0xd9, 0x0a, 0xb8, 0x50, 0x94, 0x17, 0xda, 0x2d, 0x7b, 0x40, 0xaf, 0x33, 0x72, 0x22, 0x9a, 0xed, + 0xe7, 0x3e, 0x8b, 0xf1, 0xb9, 0xba, 0x2f, 0x26, 0x5f, 0xbd, 0x2f, 0xee, 0xd9, 0xae, 0xfb, 0xbe, 0x28, 0xdf, 0x74, + 0xd7, 0xcf, 0x8e, 0xed, 0xd9, 0x03, 0xcc, 0xb0, 0xb7, 0xfc, 0xb6, 0x39, 0x75, 0x8c, 0xfd, 0xea, 0x8d, 0x11, 0x40, + 0x99, 0x2d, 0x58, 0x2c, 0x38, 0x28, 0xd5, 0xaa, 0x6d, 0x49, 0xe4, 0xb9, 0x0e, 0x54, 0x9b, 0x11, 0xdc, 0x97, 0xde, + 0xa2, 0xd4, 0x45, 0x4f, 0xfb, 0x14, 0xe4, 0x88, 0x16, 0x0e, 0x1b, 0xf0, 0x57, 0xda, 0x3a, 0xc6, 0x30, 0xcd, 0x7c, + 0xa6, 0x1d, 0x3d, 0xaf, 0xbf, 0xed, 0x3d, 0x93, 0xdf, 0xc8, 0xc0, 0x16, 0x22, 0x29, 0x1c, 0xc7, 0x57, 0xcf, 0xce, + 0xf8, 0xaf, 0x5a, 0x1e, 0xb5, 0xda, 0x2f, 0x94, 0xfa, 0xf4, 0x25, 0x1d, 0xd1, 0xc4, 0xbd, 0x68, 0xcb, 0xb0, 0x46, + 0x59, 0x53, 0x4b, 0x87, 0x61, 0x5c, 0xc3, 0xbe, 0x3c, 0x70, 0xe8, 0x3b, 0x20, 0xd0, 0xe6, 0xa9, 0x14, 0x68, 0xe1, + 0x18, 0x46, 0x61, 0x16, 0x52, 0x1e, 0x17, 0x66, 0x29, 0xef, 0xa9, 0x40, 0x8b, 0x5b, 0x75, 0x8f, 0xa9, 0xed, 0x16, + 0x44, 0x58, 0xbd, 0x65, 0x5c, 0x5e, 0x37, 0xaa, 0x70, 0x5b, 0x80, 0xa2, 0x08, 0xca, 0xe0, 0x40, 0x72, 0xdb, 0x42, + 0x49, 0xb3, 0x51, 0x58, 0x8b, 0x55, 0x51, 0xee, 0x7b, 0x0d, 0x5b, 0xe0, 0x05, 0x55, 0x3f, 0x21, 0x6c, 0xcb, 0x9e, + 0x75, 0x28, 0x17, 0xe9, 0xbf, 0x65, 0xe9, 0xf9, 0x76, 0x6b, 0xce, 0xff, 0xf4, 0x15, 0x7d, 0x54, 0xfe, 0xfb, 0x97, + 0xf4, 0xb3, 0xc1, 0x32, 0x72, 0x4a, 0xfd, 0x10, 0x8d, 0xee, 0xd2, 0x9c, 0x30, 0xb6, 0x7c, 0xfd, 0xf4, 0x1b, 0x64, + 0x0a, 0x92, 0x43, 0x29, 0x55, 0x39, 0xd9, 0x43, 0x5f, 0x78, 0xdd, 0x87, 0x99, 0x60, 0x00, 0xc2, 0x6b, 0xb4, 0xa9, + 0x26, 0x4c, 0xe2, 0xd1, 0x15, 0xfc, 0xdf, 0x08, 0x62, 0xd0, 0x3e, 0x51, 0xd4, 0xb1, 0x6d, 0xa4, 0xeb, 0xb6, 0x73, + 0x90, 0xdc, 0xa9, 0x73, 0x7f, 0x54, 0x4e, 0xfe, 0x1d, 0x0d, 0x91, 0x57, 0xdc, 0x20, 0x56, 0x16, 0x5c, 0x62, 0x31, + 0x54, 0xa4, 0x00, 0xd7, 0x10, 0x44, 0xca, 0xa2, 0xa4, 0x70, 0xc7, 0x41, 0x55, 0x04, 0x60, 0x5c, 0xad, 0x8e, 0x3a, + 0x13, 0x3e, 0x6e, 0xad, 0x45, 0x88, 0x3a, 0x34, 0x6a, 0x65, 0xad, 0xc0, 0x17, 0xa4, 0x2f, 0x1d, 0x0a, 0x62, 0x7a, + 0x14, 0x52, 0x55, 0x3a, 0x14, 0x48, 0x73, 0xa8, 0xf8, 0xc6, 0x60, 0xa3, 0xc8, 0x49, 0xcf, 0x5f, 0x9a, 0x14, 0x65, + 0xcc, 0xf8, 0x20, 0xca, 0x48, 0xe4, 0x75, 0xb8, 0x12, 0xd3, 0x02, 0xf9, 0x46, 0x4f, 0x1f, 0x04, 0xd7, 0xf0, 0x6e, + 0xc8, 0xbd, 0x02, 0x6c, 0x09, 0xd8, 0x01, 0xee, 0x95, 0x19, 0xe5, 0x3a, 0xad, 0xeb, 0xb7, 0xd6, 0x43, 0x31, 0x0c, + 0x9f, 0x5a, 0x02, 0xdb, 0xc9, 0x3a, 0x3a, 0xd1, 0xc3, 0x87, 0xff, 0x75, 0x55, 0x73, 0xd4, 0xa9, 0x5c, 0xce, 0x4e, + 0x27, 0x2c, 0x45, 0xcc, 0xa0, 0xfb, 0xeb, 0xee, 0xa5, 0x00, 0xba, 0x5d, 0x16, 0xf3, 0x6c, 0xb4, 0x97, 0x7f, 0x4b, + 0x37, 0x56, 0x94, 0x36, 0xf1, 0x2e, 0xeb, 0x8d, 0xfd, 0xe1, 0xe8, 0x3f, 0x9e, 0xbe, 0x9b, 0x10, 0xaa, 0xce, 0x96, + 0x6d, 0x74, 0x9c, 0xcb, 0xff, 0xfa, 0xcf, 0x31, 0x59, 0x41, 0x50, 0x10, 0x96, 0x9d, 0x62, 0xa2, 0x82, 0x51, 0xa4, + 0xd8, 0xf0, 0xf1, 0x64, 0x83, 0x3a, 0xe1, 0x8d, 0xbf, 0xd4, 0x3a, 0x61, 0x62, 0x64, 0xa5, 0xf2, 0x37, 0x2c, 0x67, + 0x2b, 0x95, 0x59, 0x40, 0xe6, 0x41, 0x35, 0xd9, 0x18, 0x0d, 0xe6, 0x9a, 0xd7, 0xb3, 0xcd, 0x5c, 0x2a, 0x9f, 0xc1, + 0x94, 0xb3, 0x1c, 0x9c, 0x2d, 0x85, 0xdd, 0x93, 0x40, 0xd1, 0x9a, 0xa1, 0x1b, 0x7f, 0x8a, 0xad, 0x7a, 0x95, 0x56, + 0x35, 0xc0, 0x03, 0x42, 0x0c, 0x0c, 0xb5, 0x57, 0x0b, 0x0f, 0xad, 0x05, 0xb0, 0xf1, 0x47, 0xa5, 0x1f, 0x8c, 0x27, + 0x4b, 0xbe, 0x40, 0xfe, 0xe5, 0xc8, 0x51, 0xbb, 0xf7, 0xfb, 0xde, 0x3d, 0x48, 0xc1, 0x91, 0x6b, 0xa1, 0x40, 0x22, + 0xa0, 0x05, 0xdf, 0xfa, 0xca, 0x07, 0xe3, 0x2d, 0x6a, 0xab, 0x41, 0x41, 0xed, 0xe8, 0x96, 0xc7, 0x8e, 0xde, 0xf9, + 0xfe, 0x8c, 0xbe, 0x7a, 0xa1, 0x85, 0xe3, 0xaf, 0x9c, 0x91, 0x1b, 0xb6, 0xee, 0x90, 0x23, 0x9a, 0x49, 0x87, 0x10, + 0xb1, 0x66, 0x1b, 0xf6, 0x96, 0x54, 0xce, 0x9d, 0x43, 0x76, 0xfe, 0x08, 0x55, 0x7a, 0xad, 0xc7, 0xb7, 0x13, 0xa5, + 0xbb, 0x3d, 0xdd, 0x4d, 0xbe, 0x65, 0x13, 0x11, 0x83, 0x01, 0x6d, 0x10, 0xce, 0xc8, 0x3a, 0x44, 0x2a, 0x1d, 0x20, + 0x04, 0x8e, 0x09, 0x68, 0xfa, 0xf7, 0xaf, 0x49, 0x14, 0x70, 0xa4, 0x8d, 0x90, 0xb5, 0xec, 0x78, 0xac, 0x40, 0xa3, + 0xdc, 0xfc, 0xe1, 0x15, 0xea, 0x34, 0x07, 0xe6, 0xe9, 0x12, 0xf6, 0x1c, 0x3c, 0xd2, 0x8b, 0xd3, 0x23, 0xfd, 0xbf, + 0xa3, 0x89, 0x1a, 0xff, 0xfb, 0x9a, 0x28, 0xa5, 0x45, 0x72, 0x54, 0x4b, 0xdf, 0xa4, 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, 0x7e, 0x26, 0x09, 0x91, 0xe1, 0xd2, 0x80, 0x1f, 0x55, 0x70, 0x88, 0xd3, 0x6a, + 0x93, 0x85, 0x7b, 0x54, 0xa2, 0xde, 0x89, 0x55, 0x9a, 0xbf, 0xa8, 0xff, 0x25, 0xca, 0x02, 0xa6, 0xf6, 0xaa, 0x4c, + 0xe3, 0x80, 0x2c, 0xfc, 0x59, 0x58, 0xe2, 0xe4, 0xc6, 0x36, 0xfe, 0x2c, 0xc7, 0xd3, 0x7e, 0xd5, 0x99, 0x79, 0x20, + 0x81, 0x1a, 0x88, 0x3f, 0x72, 0x2e, 0x2b, 0x8b, 0x07, 0x84, 0x6e, 0xfe, 0xb1, 0x2c, 0x8b, 0xd2, 0xeb, 0x7d, 0x4a, + 0xd2, 0xea, 0x62, 0x2d, 0xea, 0xa4, 0x88, 0x15, 0x94, 0x4d, 0x0a, 0x30, 0xfa, 0xb0, 0xf2, 0x44, 0x1c, 0x5c, 0x20, + 0x50, 0xc3, 0x45, 0x9d, 0x84, 0x00, 0x34, 0xac, 0x10, 0xf6, 0x2f, 0xa0, 0x85, 0x17, 0x61, 0x1c, 0x6e, 0x00, 0x26, + 0x27, 0xad, 0x2e, 0x36, 0x65, 0x71, 0x9f, 0xc6, 0x22, 0x1e, 0xf5, 0x14, 0x25, 0xcb, 0xc7, 0xca, 0x95, 0x73, 0xfd, + 0xc3, 0x1f, 0x14, 0xc0, 0x6e, 0xc0, 0x6c, 0x5b, 0x60, 0x07, 0x00, 0x09, 0x0a, 0x64, 0x0b, 0x75, 0x1a, 0x5d, 0xa8, + 0xa5, 0x02, 0xef, 0xb9, 0x1e, 0xe0, 0x1f, 0x2b, 0xc0, 0x32, 0xae, 0x0b, 0x19, 0x30, 0x82, 0x00, 0x46, 0xe0, 0xa0, + 0x04, 0x0c, 0x9d, 0x61, 0x6d, 0xf1, 0xb8, 0x43, 0x73, 0xa5, 0xdb, 0x92, 0x9b, 0x46, 0x39, 0x5b, 0x89, 0x00, 0xfa, + 0xea, 0xa6, 0xc4, 0xe9, 0x72, 0xd9, 0x4a, 0xc2, 0xbe, 0x7d, 0xdf, 0x4e, 0x15, 0x79, 0x7c, 0x92, 0x86, 0xbc, 0x02, + 0x4f, 0x32, 0x8e, 0x24, 0x51, 0x22, 0xf8, 0x58, 0x35, 0x66, 0x1c, 0x5e, 0xb4, 0x29, 0xa7, 0x0e, 0x66, 0xbd, 0x00, + 0x9c, 0x27, 0x68, 0xcb, 0x00, 0x63, 0x01, 0x83, 0x73, 0x21, 0x96, 0x3c, 0x45, 0xf0, 0x4b, 0x27, 0x52, 0x18, 0x77, + 0x39, 0x0c, 0xf3, 0xa0, 0xe8, 0x5d, 0x52, 0x7f, 0xf4, 0xfb, 0xa8, 0x4d, 0x06, 0x43, 0x50, 0x09, 0xa0, 0xb2, 0x6e, + 0x90, 0x18, 0x58, 0x95, 0x16, 0x12, 0x97, 0x10, 0x2f, 0xf3, 0xd5, 0xb4, 0x8e, 0x82, 0xf7, 0xf5, 0x84, 0x10, 0x4e, + 0x30, 0x3e, 0xc4, 0x0d, 0x10, 0x30, 0x58, 0xc5, 0x05, 0x06, 0xc9, 0x73, 0x89, 0xee, 0x8f, 0xe7, 0x3b, 0x06, 0xb8, + 0x72, 0xde, 0x53, 0xed, 0xea, 0x81, 0xbd, 0x5c, 0xa5, 0x4b, 0x46, 0x08, 0x2b, 0xfe, 0x2f, 0x22, 0xef, 0xdb, 0x61, + 0x02, 0x6a, 0x1b, 0xf9, 0x63, 0x90, 0x98, 0xcb, 0x44, 0x11, 0xc4, 0xa3, 0xac, 0x60, 0x49, 0x1a, 0x6c, 0x47, 0x49, + 0x0a, 0x1a, 0x4d, 0x8c, 0x21, 0x53, 0xa1, 0x1d, 0x92, 0x46, 0xb3, 0x31, 0xd9, 0xc7, 0x90, 0xd7, 0x70, 0xb1, 0x58, + 0xe0, 0x7d, 0x3f, 0x0b, 0xd5, 0xc1, 0xb6, 0x34, 0x87, 0x80, 0x93, 0x04, 0x7b, 0xea, 0x8a, 0x94, 0x84, 0xd9, 0xe8, + 0x53, 0xc8, 0xb9, 0x01, 0x1d, 0x27, 0x8d, 0xa1, 0xfa, 0xc0, 0x24, 0xbc, 0x89, 0xd0, 0x49, 0x59, 0x21, 0x2c, 0xe0, + 0xbe, 0x91, 0xd1, 0x68, 0x25, 0x0d, 0x02, 0x6f, 0x33, 0x6c, 0x05, 0x36, 0xa1, 0xe1, 0x2f, 0x32, 0x0f, 0xd3, 0x6a, + 0x56, 0x82, 0x39, 0xdf, 0x40, 0x25, 0xc6, 0x93, 0xe5, 0x0d, 0xdf, 0xba, 0x58, 0x89, 0xc9, 0x6c, 0x39, 0x9f, 0x6c, + 0x24, 0xd5, 0x1c, 0x08, 0x19, 0x19, 0x5b, 0xc2, 0xfe, 0x61, 0x60, 0x28, 0x1d, 0xd8, 0xd1, 0x54, 0xd3, 0x26, 0x01, + 0x26, 0xd3, 0x25, 0xe7, 0xc3, 0x6b, 0x44, 0x93, 0xd5, 0xa9, 0x7b, 0x99, 0xaa, 0x76, 0x70, 0x4d, 0xce, 0xe4, 0xf4, + 0x48, 0x3d, 0xd5, 0xba, 0x97, 0x6a, 0xb4, 0x1b, 0xe6, 0xa3, 0x9d, 0x1f, 0x80, 0x5b, 0xa7, 0xb0, 0xd3, 0xf7, 0xc3, + 0x7c, 0xb4, 0xf7, 0x35, 0xec, 0x2e, 0x29, 0x04, 0xaa, 0x3f, 0xcb, 0x9a, 0xcc, 0xc5, 0x9b, 0xe2, 0xc1, 0x2b, 0xd8, + 0x33, 0x7f, 0xa0, 0x7f, 0x95, 0xec, 0x99, 0x6f, 0x33, 0xb9, 0xfe, 0x99, 0x76, 0x8d, 0xc6, 0x4c, 0xc7, 0x6b, 0xe7, + 0x60, 0x85, 0x06, 0xc8, 0x2f, 0xd8, 0xd1, 0xde, 0xe4, 0x20, 0x10, 0xa0, 0x7b, 0x09, 0x8e, 0xa2, 0x80, 0xa8, 0x69, + 0x55, 0x79, 0x74, 0xba, 0xf7, 0x0f, 0xf8, 0x46, 0x09, 0xd8, 0xe4, 0xa9, 0x75, 0x6f, 0x19, 0xfb, 0xc7, 0x23, 0x84, + 0xd0, 0xcb, 0xe9, 0x37, 0xda, 0xb1, 0x7a, 0xb4, 0x67, 0x12, 0xfc, 0x1c, 0x31, 0xe9, 0x15, 0x8c, 0x61, 0xe8, 0xc2, + 0x2a, 0x46, 0xf2, 0x0c, 0xc8, 0x1a, 0xbf, 0x41, 0x74, 0x01, 0x8b, 0x5e, 0xef, 0xd5, 0x09, 0x0d, 0x22, 0xa0, 0xd2, + 0x6b, 0xfe, 0x52, 0xe4, 0x73, 0x55, 0x88, 0xde, 0x07, 0x6b, 0xe7, 0xcd, 0x8c, 0x64, 0x99, 0x34, 0x52, 0xed, 0x56, + 0x16, 0x9b, 0xca, 0x9b, 0x9d, 0x91, 0x2e, 0xe6, 0x18, 0x2a, 0x83, 0xc7, 0x01, 0x28, 0x3d, 0xff, 0x12, 0x7a, 0x25, + 0x43, 0xa6, 0x59, 0xa2, 0x99, 0xdd, 0x37, 0xfe, 0x64, 0x9d, 0x7a, 0x31, 0x22, 0x66, 0x03, 0x5b, 0x88, 0xdb, 0xa2, + 0xd2, 0x6d, 0x51, 0x28, 0x5b, 0x14, 0xe9, 0x43, 0xed, 0x42, 0x77, 0x66, 0xe1, 0xb3, 0xdc, 0xb4, 0xef, 0x4d, 0x66, + 0xc6, 0x06, 0x68, 0xbb, 0x08, 0xdf, 0x40, 0x07, 0x2a, 0x84, 0xfc, 0x47, 0x44, 0x44, 0x22, 0x60, 0x97, 0x73, 0x77, + 0x62, 0xd3, 0x21, 0x99, 0x87, 0x98, 0x15, 0x6a, 0x94, 0x97, 0x3c, 0x39, 0x19, 0x90, 0x9c, 0x50, 0xb7, 0xfb, 0xfd, + 0xcb, 0xa5, 0x0b, 0x6a, 0xbf, 0xa1, 0xd8, 0x31, 0xba, 0x29, 0xe0, 0x5c, 0xf0, 0x28, 0xef, 0xa5, 0x77, 0x09, 0x68, + 0x8e, 0xed, 0x29, 0xb2, 0x01, 0x9c, 0xde, 0x76, 0x21, 0xc0, 0xf6, 0x59, 0xb3, 0x8d, 0x3f, 0x59, 0xdf, 0x44, 0x53, + 0xaf, 0xe4, 0x33, 0xdd, 0x45, 0x89, 0xdb, 0x45, 0xb1, 0xec, 0xa2, 0x6d, 0x03, 0xc1, 0x8e, 0x6b, 0x3f, 0x00, 0xde, + 0xd0, 0xa8, 0xdf, 0x2f, 0x5b, 0x3d, 0x7b, 0xf6, 0xb5, 0xd3, 0x9e, 0xcd, 0x7c, 0x56, 0x9a, 0x9e, 0xfd, 0x35, 0x75, + 0x7b, 0x56, 0x4e, 0xf6, 0xa2, 0x73, 0xb2, 0x4f, 0x67, 0xf3, 0x40, 0x70, 0xb9, 0x73, 0x5f, 0x56, 0x53, 0x3d, 0xed, + 0x72, 0x3f, 0x68, 0x0d, 0x91, 0xf9, 0xc2, 0xa7, 0xbc, 0x7b, 0x5d, 0xc1, 0x02, 0x96, 0xe0, 0x6e, 0xbd, 0x34, 0xff, + 0x15, 0xbb, 0xbf, 0x17, 0xf4, 0xd2, 0xfc, 0x37, 0xfa, 0x93, 0x02, 0x38, 0x00, 0x8d, 0xa9, 0xdd, 0x02, 0x0f, 0x31, + 0x54, 0x50, 0xb8, 0x9b, 0x95, 0x73, 0xaf, 0x06, 0x38, 0x4c, 0xd2, 0x37, 0xb4, 0x7a, 0xa5, 0xc5, 0xae, 0x97, 0xc9, + 0x5e, 0x01, 0x1e, 0xaa, 0x90, 0x87, 0xc7, 0x63, 0xd4, 0x31, 0xec, 0xa0, 0x8e, 0x80, 0x61, 0x0f, 0xa1, 0xb1, 0x05, + 0x9e, 0x8f, 0x9f, 0x32, 0x7e, 0x10, 0xa0, 0x36, 0x42, 0x78, 0xbc, 0x5a, 0x94, 0x21, 0xb6, 0xec, 0x0d, 0x52, 0x49, + 0xfd, 0x2c, 0x10, 0x65, 0xb4, 0x0a, 0x68, 0xab, 0x3d, 0x65, 0x69, 0xbc, 0x85, 0x50, 0xb1, 0xd4, 0xc7, 0x10, 0x1a, + 0x38, 0xfc, 0x8e, 0x47, 0x90, 0xe0, 0x4b, 0xae, 0xc9, 0xe6, 0xde, 0xe4, 0xf7, 0xb4, 0xcf, 0x1f, 0x8f, 0x97, 0xd7, + 0x08, 0x4a, 0x97, 0xc2, 0x47, 0x2a, 0x11, 0xd5, 0x53, 0xdc, 0x94, 0x90, 0xcd, 0x92, 0x95, 0x7e, 0xf0, 0xab, 0xfa, + 0x05, 0x00, 0xb2, 0x10, 0x68, 0x13, 0x99, 0xfd, 0xe9, 0x42, 0x45, 0x17, 0x00, 0x87, 0xf8, 0xe3, 0x27, 0x88, 0xbe, + 0xa1, 0x65, 0x5a, 0x3e, 0x4e, 0x78, 0x08, 0x5a, 0x5b, 0xd2, 0x49, 0xc4, 0x4a, 0x81, 0x0d, 0x91, 0xf0, 0xfd, 0xfe, + 0x65, 0x2c, 0xe9, 0x40, 0xa3, 0x56, 0xf7, 0xc6, 0xad, 0xee, 0x95, 0xaf, 0xeb, 0x4e, 0x6e, 0x7c, 0x50, 0xb4, 0xcf, + 0xe6, 0x8d, 0xca, 0xf7, 0x6d, 0x9d, 0xb3, 0x3f, 0xdf, 0x3b, 0x72, 0x4e, 0x7c, 0x7b, 0x0f, 0xa1, 0xe8, 0xa1, 0x29, + 0xb2, 0x2c, 0x09, 0x03, 0x5a, 0x6b, 0xd7, 0x9e, 0x65, 0x74, 0xf0, 0xda, 0x37, 0x84, 0x88, 0x3c, 0xc5, 0x27, 0x21, + 0xb7, 0x38, 0x3e, 0x28, 0xd0, 0x3f, 0x33, 0xfe, 0xcc, 0x89, 0x1f, 0xb6, 0xfa, 0x05, 0x70, 0x6e, 0xba, 0xf7, 0xee, + 0xc4, 0xac, 0xc7, 0x50, 0xca, 0xc6, 0xff, 0xfd, 0x3e, 0x91, 0x05, 0x3a, 0x1d, 0xd1, 0x30, 0x10, 0xdc, 0x45, 0xf5, + 0x7f, 0xaf, 0x78, 0xdd, 0xb3, 0x56, 0xe7, 0xcb, 0x4f, 0x9d, 0x9f, 0xf4, 0xea, 0x65, 0xdc, 0x03, 0x72, 0x74, 0x80, + 0x70, 0x5e, 0xf7, 0x1b, 0xb6, 0xff, 0xe6, 0x97, 0xf7, 0x27, 0x2f, 0x03, 0x9b, 0x14, 0x89, 0x6d, 0x25, 0x9f, 0xf5, + 0x40, 0xe1, 0xd7, 0x63, 0xbd, 0xba, 0xd8, 0xf4, 0x58, 0x0f, 0xb5, 0x80, 0xe8, 0x61, 0x01, 0xea, 0xbf, 0x9e, 0x7d, + 0x1a, 0x0a, 0x07, 0xd9, 0x38, 0x55, 0xa0, 0xc8, 0x82, 0x3f, 0x17, 0xa3, 0x4d, 0x41, 0x80, 0xc8, 0x96, 0x90, 0x96, + 0x9f, 0xcd, 0x1e, 0x97, 0x5a, 0x92, 0xc1, 0x37, 0x01, 0x99, 0x1d, 0x58, 0x39, 0x41, 0xe9, 0xb8, 0x33, 0xe0, 0xca, + 0x16, 0x8f, 0x76, 0xfb, 0xd3, 0x20, 0x3b, 0x6b, 0x4e, 0x1a, 0xed, 0xc3, 0x3e, 0x05, 0x4e, 0x1a, 0x10, 0x7b, 0x44, + 0xa0, 0xef, 0xb6, 0xb9, 0xf4, 0xd1, 0xe1, 0x9c, 0x17, 0xf2, 0xcf, 0xa9, 0xc4, 0xe0, 0x1e, 0x4a, 0xac, 0x81, 0x40, + 0xe5, 0x19, 0xaa, 0x1c, 0x36, 0xc8, 0xf1, 0xcf, 0x8e, 0x64, 0x26, 0x31, 0x59, 0xe4, 0x6e, 0xcd, 0x54, 0xf8, 0x81, + 0x00, 0xfe, 0x73, 0x0e, 0x5c, 0x60, 0xb3, 0xb9, 0xaf, 0xa6, 0xb8, 0xb8, 0x01, 0x7f, 0x4c, 0xe1, 0xe7, 0x3c, 0x85, + 0x9d, 0xf6, 0xb0, 0x29, 0xaa, 0x14, 0x75, 0x1b, 0x85, 0x45, 0x25, 0x0b, 0xa6, 0x35, 0xa4, 0x89, 0x0e, 0xa3, 0x3f, + 0xc8, 0x19, 0x28, 0x08, 0xf9, 0x75, 0xd3, 0x00, 0x23, 0x95, 0x5c, 0x1e, 0x54, 0x49, 0xe0, 0x05, 0xd8, 0x05, 0x39, + 0xdb, 0x14, 0x10, 0x64, 0x9b, 0x14, 0x65, 0xfa, 0xa5, 0xc8, 0xeb, 0x30, 0x0b, 0xf2, 0x51, 0x5a, 0xfd, 0x55, 0xff, + 0x04, 0xe6, 0x6d, 0x2a, 0x46, 0xb5, 0x8a, 0xc9, 0x6f, 0xf4, 0xfb, 0xc5, 0xa0, 0xf5, 0x21, 0x83, 0x8f, 0x5e, 0x9b, + 0x06, 0x7f, 0x74, 0x1a, 0xec, 0x30, 0xd1, 0x08, 0x80, 0x64, 0x4e, 0x2d, 0x79, 0x28, 0xfa, 0x23, 0xa8, 0xb0, 0x46, + 0xb9, 0x53, 0x30, 0x58, 0xff, 0xf1, 0x68, 0x07, 0xa6, 0x5e, 0x1c, 0x6d, 0xc9, 0x0e, 0x9a, 0xfb, 0x06, 0xb8, 0x5f, + 0x23, 0x5b, 0xcc, 0x2a, 0x80, 0x66, 0xaf, 0x11, 0x19, 0x9f, 0xbc, 0x00, 0xc6, 0x6c, 0x93, 0x85, 0x91, 0x88, 0x83, + 0xb1, 0x6a, 0xcc, 0x98, 0x81, 0x81, 0x0b, 0x74, 0x2d, 0x93, 0x92, 0x34, 0xa4, 0x83, 0x01, 0x2b, 0x65, 0x0b, 0x07, + 0xbc, 0x68, 0x4e, 0xdb, 0xf1, 0xba, 0x45, 0xe3, 0x81, 0xed, 0x62, 0x87, 0xfb, 0x1f, 0x8a, 0xdd, 0xdb, 0x70, 0x47, + 0x7a, 0x85, 0x8a, 0x25, 0xf4, 0xf3, 0xaf, 0xb2, 0xcf, 0x1a, 0x4e, 0x4e, 0x85, 0x66, 0x68, 0x29, 0x12, 0x4a, 0xf1, + 0x4e, 0x4f, 0x0a, 0x8c, 0x65, 0x2c, 0xfc, 0x03, 0x70, 0x4e, 0x17, 0x8a, 0xc8, 0x1d, 0x38, 0x8e, 0x6f, 0xa1, 0x82, + 0x51, 0xc3, 0xc1, 0xcb, 0x18, 0xb6, 0x45, 0x31, 0x0b, 0x09, 0xa7, 0x10, 0x2e, 0x56, 0x59, 0xbf, 0x2f, 0x7f, 0x51, + 0x17, 0x5d, 0x65, 0xb2, 0xee, 0x93, 0x70, 0x64, 0xc6, 0x72, 0xea, 0x85, 0xe4, 0x79, 0xcf, 0x93, 0x69, 0xf2, 0xb4, + 0x0a, 0x22, 0x80, 0x7c, 0x0e, 0xef, 0xc3, 0x34, 0x03, 0xab, 0x34, 0x29, 0x3f, 0x42, 0xe9, 0x8b, 0xcf, 0x73, 0x3f, + 0xd0, 0xd9, 0x2b, 0x93, 0x0c, 0x6f, 0xe6, 0xad, 0x37, 0xa9, 0x75, 0x5d, 0x3c, 0xe0, 0xef, 0x9c, 0xc1, 0xc6, 0xb9, + 0xce, 0x04, 0x07, 0x5e, 0x24, 0xb5, 0x5e, 0x33, 0xfe, 0x3c, 0xc3, 0x75, 0xa9, 0xda, 0xe8, 0xa3, 0x10, 0x5d, 0x41, + 0xa6, 0x02, 0x14, 0x8a, 0xb4, 0x7f, 0x50, 0x6a, 0x6e, 0x52, 0x69, 0x23, 0x01, 0x74, 0x0f, 0x93, 0x06, 0x5b, 0x0c, + 0x65, 0x2c, 0x4d, 0xa2, 0xdc, 0x69, 0x10, 0x57, 0xf6, 0xe7, 0x5c, 0xe2, 0xd0, 0xb2, 0x48, 0xfe, 0xbd, 0xef, 0xe9, + 0x2b, 0xa4, 0xee, 0x64, 0x81, 0xcc, 0x18, 0x2f, 0xf2, 0xf8, 0x13, 0x10, 0x66, 0x83, 0x36, 0x2a, 0x0a, 0x21, 0x64, + 0x83, 0x18, 0x34, 0x5e, 0xe4, 0xf1, 0x0f, 0x8a, 0xc6, 0x43, 0x3e, 0x8a, 0x7c, 0xf5, 0x57, 0xa9, 0xff, 0x0a, 0x7d, + 0x66, 0x82, 0x47, 0xa8, 0x26, 0xfa, 0x77, 0xcf, 0x67, 0xf7, 0xa0, 0x36, 0x8c, 0xc2, 0xcc, 0x94, 0x9f, 0xfb, 0xa6, + 0x38, 0x7b, 0xfd, 0x15, 0x5d, 0x65, 0x5b, 0xf7, 0xa3, 0x8f, 0x27, 0x04, 0xd6, 0xc6, 0xe8, 0x8a, 0x1b, 0x03, 0xc8, + 0x61, 0xf2, 0x7e, 0x45, 0x69, 0x15, 0xa4, 0x41, 0xe8, 0xa0, 0x21, 0xe8, 0x95, 0x44, 0x1f, 0x48, 0x2c, 0x62, 0x0c, + 0x2f, 0xc4, 0x33, 0x52, 0x93, 0x89, 0x86, 0x78, 0x45, 0xec, 0x87, 0x68, 0xc9, 0xa9, 0x89, 0x6e, 0x84, 0x29, 0x06, + 0x12, 0x3b, 0x83, 0xe4, 0x24, 0xa9, 0x95, 0x5f, 0x3c, 0x93, 0x84, 0x25, 0x76, 0x1e, 0x62, 0x30, 0xa9, 0xa5, 0x3b, + 0xbd, 0xa9, 0xd2, 0x97, 0x13, 0x2d, 0x07, 0xed, 0x03, 0xb0, 0x4b, 0x49, 0xef, 0x9f, 0x14, 0x8a, 0xf8, 0x10, 0xc6, + 0x31, 0x84, 0x6f, 0x11, 0xd5, 0x15, 0x38, 0xd7, 0x0a, 0x34, 0x56, 0x03, 0x0f, 0xcd, 0x2c, 0x9f, 0x0f, 0x39, 0xfd, + 0x54, 0x5a, 0xfe, 0x18, 0xd1, 0xd8, 0x68, 0xdd, 0x1c, 0x8f, 0x07, 0x5a, 0xf5, 0xd2, 0x39, 0xe8, 0xba, 0x99, 0xc4, + 0xc4, 0x0d, 0xa4, 0xeb, 0x47, 0xbf, 0x99, 0xb0, 0x17, 0x51, 0x21, 0x97, 0x42, 0x50, 0xd0, 0xea, 0x40, 0xe0, 0x50, + 0x78, 0x8b, 0x32, 0x5f, 0xc5, 0xb4, 0x81, 0x30, 0xf8, 0xfc, 0x40, 0x7e, 0xbe, 0x29, 0x48, 0xc5, 0x8e, 0x75, 0xed, + 0xf7, 0xb7, 0xa5, 0x07, 0x78, 0x72, 0x26, 0xc9, 0xd3, 0x66, 0x08, 0x2b, 0x02, 0x68, 0xcc, 0x6a, 0xb2, 0x38, 0xe1, + 0xca, 0x1c, 0x7e, 0xcc, 0xbd, 0x92, 0xa5, 0x4c, 0x9d, 0xa7, 0x7a, 0x01, 0x44, 0x1d, 0x6f, 0xd0, 0x8a, 0xd4, 0xaf, + 0xd0, 0xd9, 0x6b, 0x56, 0x42, 0xc6, 0xc3, 0x4b, 0xce, 0xd3, 0xd1, 0x03, 0x4b, 0x78, 0x84, 0x7f, 0x25, 0x13, 0x7d, + 0xf8, 0x3d, 0x70, 0xb8, 0x19, 0x27, 0x3c, 0x72, 0x9b, 0x7d, 0xa8, 0xc2, 0x35, 0xdc, 0x4c, 0x0b, 0x40, 0x72, 0x0b, + 0x92, 0x26, 0xa0, 0x84, 0x44, 0x26, 0x64, 0xd6, 0x94, 0xfc, 0xdc, 0xd2, 0x36, 0x58, 0xc3, 0xa4, 0xf3, 0x80, 0x17, + 0xad, 0x3e, 0x5a, 0x4d, 0xb4, 0xcb, 0xac, 0x9a, 0x0f, 0x71, 0x86, 0x6a, 0x8e, 0xbb, 0x0b, 0xf8, 0x39, 0xe0, 0x39, + 0xcb, 0x9b, 0x74, 0xb4, 0x1f, 0x70, 0xe1, 0xc9, 0x75, 0x9e, 0x8e, 0x76, 0xf8, 0x4b, 0xee, 0x0f, 0x00, 0x1d, 0x4c, + 0x5d, 0x02, 0x7f, 0xaa, 0xb6, 0x9a, 0x4a, 0xfd, 0xd2, 0xda, 0xaf, 0xeb, 0xce, 0x6a, 0xc1, 0x19, 0xa2, 0x2f, 0x43, + 0x07, 0x64, 0xc8, 0x19, 0x33, 0xe0, 0xcf, 0x19, 0x4b, 0xfe, 0x9c, 0xb1, 0xe2, 0xcf, 0x19, 0x37, 0x46, 0x06, 0x50, + 0x82, 0x7b, 0xc9, 0x9f, 0x1f, 0x10, 0x33, 0xc4, 0x6a, 0x50, 0x09, 0xac, 0x2c, 0xe5, 0xdc, 0x47, 0x4e, 0x31, 0xe5, + 0x94, 0xe1, 0xa5, 0xd3, 0x99, 0x3b, 0x90, 0xf3, 0x60, 0xe6, 0x0e, 0x93, 0xb3, 0x3e, 0xc5, 0xa9, 0x34, 0x26, 0x45, 0x05, 0xe9, 0x9c, 0x0e, 0x37, 0xaf, 0x8e, 0xf3, 0x84, 0x65, 0x7c, 0xdc, 0x3e, 0x53, 0x20, 0xc4, 0x16, 0xcf, 0x90, - 0x48, 0xa9, 0x9a, 0xe5, 0x36, 0x7f, 0x38, 0xd4, 0xa3, 0x07, 0xbd, 0xd3, 0xc3, 0xaf, 0x84, 0xfd, 0x92, 0x79, 0xf6, - 0x09, 0x02, 0x98, 0x24, 0xf2, 0x4c, 0xc2, 0xd1, 0x8f, 0xe5, 0xe8, 0x6f, 0x1a, 0xfe, 0x2e, 0x43, 0x75, 0x77, 0x08, - 0x4c, 0x6c, 0xd9, 0x81, 0x43, 0x70, 0xba, 0xaa, 0x44, 0x02, 0x0e, 0x36, 0x1b, 0x16, 0xe9, 0x3d, 0x1e, 0xe2, 0x7c, - 0x50, 0xf8, 0x08, 0x0d, 0x33, 0x7a, 0xbf, 0xbf, 0x11, 0x5e, 0x25, 0x5b, 0x79, 0x38, 0x24, 0xd6, 0x5d, 0xd8, 0xd1, - 0xc7, 0xd1, 0x1e, 0x25, 0xd4, 0x7e, 0x54, 0xeb, 0x4d, 0xa5, 0x1e, 0xe4, 0x66, 0x17, 0x12, 0x83, 0x8a, 0xa5, 0xfa, - 0xf4, 0x4a, 0xf5, 0xa1, 0x66, 0x9d, 0xdf, 0xd5, 0x71, 0x9f, 0x8a, 0xd1, 0x5a, 0x4e, 0x08, 0x70, 0x1d, 0x24, 0x1a, - 0x1d, 0x00, 0xe3, 0x6c, 0xb3, 0xe5, 0xa5, 0xb6, 0x4e, 0x94, 0x8e, 0xe3, 0x5c, 0x1f, 0xc7, 0x87, 0x83, 0x14, 0x33, - 0x2e, 0x8f, 0xc4, 0x8c, 0xcb, 0x06, 0xe0, 0xcd, 0x3a, 0x0f, 0xea, 0xc3, 0xe1, 0x92, 0x2e, 0x45, 0xa6, 0xb3, 0x8d, - 0xf2, 0xb3, 0x1e, 0x3d, 0x3c, 0x4b, 0xd0, 0xdc, 0x5b, 0x61, 0xef, 0x45, 0xb2, 0x3d, 0x93, 0x75, 0xea, 0x65, 0xe4, - 0xd3, 0x0b, 0xf7, 0xec, 0x92, 0xab, 0x1f, 0x56, 0x5f, 0x4f, 0x7f, 0x15, 0x5e, 0xc4, 0x2a, 0xda, 0xad, 0x4b, 0x26, - 0xec, 0x2d, 0xa5, 0x92, 0x56, 0x79, 0xf9, 0x74, 0xe3, 0x07, 0x98, 0x99, 0xf6, 0xf4, 0x41, 0x36, 0xa2, 0xfa, 0xb3, + 0x48, 0xa9, 0x9a, 0xe5, 0x36, 0x7f, 0x3c, 0xd6, 0xa3, 0x07, 0xbd, 0xd3, 0xc3, 0xaf, 0x84, 0xfd, 0x92, 0x79, 0xf6, + 0x09, 0x02, 0x98, 0x24, 0xf2, 0x4c, 0xc2, 0xd1, 0x8f, 0xe5, 0xe8, 0x6f, 0x1b, 0xfe, 0x25, 0x43, 0x75, 0x77, 0x08, + 0x4c, 0x6c, 0xd9, 0x91, 0x43, 0x70, 0xba, 0xaa, 0x44, 0x02, 0x0e, 0x36, 0x5b, 0x16, 0xe9, 0x3d, 0x1e, 0xe2, 0x7c, + 0x50, 0xf8, 0x08, 0x0d, 0x33, 0x7a, 0xbf, 0xbf, 0x15, 0x5e, 0x2e, 0x5b, 0x79, 0x3c, 0x26, 0xd6, 0x5d, 0xd8, 0xd1, + 0xc7, 0xd1, 0x1e, 0x25, 0xd4, 0x7e, 0x54, 0xeb, 0x4d, 0xa5, 0x1e, 0x54, 0x66, 0x17, 0x12, 0x83, 0x9c, 0xa5, 0xfa, + 0xf4, 0x4a, 0xf5, 0xa1, 0x66, 0x9d, 0xdf, 0xf9, 0x69, 0x9f, 0x8a, 0xd1, 0x46, 0x4e, 0x08, 0x70, 0x1d, 0x24, 0x1a, + 0x1d, 0x00, 0xe3, 0x6c, 0xb3, 0xe5, 0xa5, 0xb6, 0x4e, 0x94, 0x8e, 0xe3, 0x4a, 0x1f, 0xc7, 0xc7, 0xa3, 0x14, 0x33, + 0xae, 0x4f, 0xc4, 0x8c, 0xeb, 0x06, 0xe0, 0xcd, 0x3a, 0x0f, 0xea, 0xe3, 0xf1, 0x9a, 0x2e, 0x45, 0xa6, 0xb3, 0x8d, + 0xf2, 0xb3, 0x1e, 0x3d, 0x3c, 0x4d, 0xd0, 0xdc, 0x5b, 0x61, 0xef, 0x45, 0xb2, 0x3d, 0x93, 0x4d, 0xea, 0x65, 0xe4, + 0xd3, 0x0b, 0xf7, 0xec, 0x92, 0xab, 0x1f, 0x56, 0x5f, 0x4f, 0x7f, 0x15, 0x5e, 0xc4, 0x72, 0xda, 0xad, 0x4b, 0x26, + 0xec, 0x2d, 0x25, 0x97, 0x56, 0x79, 0xf9, 0x74, 0xeb, 0x07, 0x98, 0x99, 0xf6, 0xf4, 0x41, 0x36, 0xa2, 0xfa, 0xb3, 0x12, 0xb5, 0x32, 0x4c, 0x16, 0xce, 0x4b, 0xa6, 0x9e, 0x0c, 0x78, 0xcc, 0x4a, 0x1e, 0xc9, 0x4e, 0x6f, 0x0c, 0x82, - 0x00, 0xd6, 0x39, 0x69, 0xd5, 0x19, 0x47, 0xa3, 0x55, 0xe5, 0xe2, 0x74, 0x95, 0x0b, 0x0c, 0xb7, 0x5b, 0xb3, 0x8d, - 0xaa, 0xb3, 0xdc, 0xd4, 0x2a, 0xe5, 0x3b, 0x80, 0x8f, 0x65, 0x95, 0x0b, 0x3a, 0xa6, 0x4c, 0x9d, 0x37, 0x10, 0x8c, - 0xad, 0x6a, 0x5c, 0x38, 0x35, 0x2e, 0x78, 0x44, 0xed, 0x6e, 0x9a, 0x7a, 0xb4, 0x05, 0x96, 0xd2, 0xd1, 0x8e, 0x97, - 0xa8, 0x52, 0xf8, 0xbb, 0xe0, 0xfb, 0x30, 0x8e, 0xbf, 0x2f, 0xb6, 0xea, 0x40, 0xbc, 0x2d, 0xb6, 0x48, 0xfb, 0x22, + 0x00, 0xd6, 0x39, 0x69, 0xd5, 0x19, 0x47, 0xa3, 0x55, 0xe5, 0xe2, 0x7c, 0x95, 0x0b, 0x0c, 0xb7, 0xdb, 0xb0, 0xad, + 0xaa, 0xb3, 0xdc, 0xd4, 0x72, 0xe5, 0x3b, 0x80, 0x8f, 0x65, 0x95, 0x0b, 0x3a, 0xa6, 0x4c, 0x9d, 0xb7, 0x10, 0x8c, + 0xad, 0x6a, 0x5c, 0x38, 0x35, 0x2e, 0x78, 0x44, 0xed, 0x6e, 0x9a, 0x7a, 0xb4, 0x03, 0x96, 0xd2, 0xd1, 0x9e, 0x97, + 0xa8, 0x52, 0xf8, 0x9b, 0xe0, 0x87, 0x30, 0x8e, 0x7f, 0x28, 0x76, 0xea, 0x40, 0xbc, 0x2b, 0x76, 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, 0x09, 0xc6, 0x0c, 0x5d, 0x9a, 0x80, 0x65, 0x63, + 0x78, 0xa4, 0x95, 0x5d, 0xab, 0xbb, 0x42, 0xad, 0xc7, 0x1c, 0x36, 0xec, 0x45, 0x16, 0xee, 0x45, 0x09, 0x7e, 0x13, + 0xf2, 0xaf, 0xe3, 0x51, 0xab, 0x2c, 0xd5, 0x91, 0x3e, 0x3b, 0x7c, 0x09, 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, 0x58, 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, 0x1f, 0x55, 0x36, 0x76, 0x07, 0xe4, 0x90, 0x64, 0xb2, 0xb8, 0x1b, 0xdd, - 0x8a, 0x65, 0x51, 0x8a, 0x9f, 0xb1, 0x1e, 0xae, 0xd9, 0xc2, 0x7d, 0x06, 0x84, 0xf6, 0x13, 0xa5, 0xbd, 0x89, 0x34, - 0x41, 0xf7, 0x1d, 0x5b, 0x01, 0xc8, 0x00, 0x8a, 0xba, 0xda, 0xad, 0xcf, 0xf9, 0x39, 0x92, 0x66, 0x38, 0x8c, 0x6e, - 0x9f, 0xde, 0x05, 0x77, 0x83, 0x4b, 0xd4, 0x4a, 0x5f, 0xb2, 0xb8, 0x85, 0x41, 0xb5, 0x37, 0x4b, 0x38, 0xa8, 0x99, - 0xb5, 0x36, 0x02, 0xc1, 0x64, 0x0f, 0x05, 0x15, 0x73, 0x05, 0xfb, 0xa0, 0x60, 0x2d, 0x79, 0x1d, 0x1c, 0x6e, 0xed, - 0xcb, 0x4a, 0x71, 0xf1, 0xfc, 0x22, 0x69, 0x5d, 0x58, 0xca, 0x8b, 0xe7, 0x0d, 0x18, 0x5c, 0x8e, 0xb0, 0xa9, 0x2a, - 0x7f, 0xb2, 0x01, 0xd0, 0xad, 0x90, 0x22, 0x5e, 0x94, 0xc2, 0xb6, 0x95, 0xcf, 0x9c, 0xb0, 0xc1, 0x86, 0x3d, 0xc0, - 0xbd, 0x32, 0x28, 0x19, 0x5c, 0x88, 0x71, 0xbb, 0xd9, 0x05, 0xb8, 0x82, 0xa1, 0x30, 0xb6, 0xe6, 0x6f, 0x32, 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, 0x7c, 0xce, 0xbc, 0xa5, 0xcf, 0xde, 0x54, 0x32, 0x5a, 0x93, 0x44, - 0x79, 0xf5, 0x70, 0x09, 0x72, 0xc3, 0x72, 0xf4, 0xc0, 0x96, 0x20, 0x4e, 0x2c, 0x47, 0x09, 0x65, 0x74, 0x85, 0x7b, - 0x95, 0xd9, 0x32, 0x11, 0x48, 0x71, 0x60, 0x29, 0xe5, 0xde, 0x62, 0x1d, 0x2c, 0x71, 0x7f, 0x22, 0xb9, 0x80, 0x92, - 0x07, 0x50, 0xae, 0x14, 0x10, 0xf0, 0xe9, 0x00, 0xca, 0x97, 0xf2, 0x22, 0xfc, 0x89, 0x13, 0x35, 0x58, 0x8e, 0x1e, - 0x1a, 0xf6, 0xa3, 0x17, 0x5a, 0xf6, 0x87, 0x3b, 0xad, 0x69, 0x58, 0xf1, 0x3b, 0x98, 0x16, 0x13, 0xb7, 0x2f, 0x57, - 0x76, 0x55, 0x7c, 0xb6, 0x52, 0x67, 0x37, 0x35, 0x24, 0x61, 0x5f, 0x91, 0x55, 0x80, 0x83, 0x55, 0x11, 0xf7, 0x2c, - 0xcb, 0x7d, 0x18, 0xfd, 0xb9, 0x49, 0x4b, 0x61, 0xa1, 0x4a, 0xfa, 0xfb, 0xa6, 0x14, 0x48, 0x65, 0xa2, 0x13, 0x2d, - 0x04, 0x57, 0x60, 0x10, 0xb8, 0x17, 0x79, 0x0d, 0x80, 0x31, 0xe0, 0x52, 0xa0, 0x2c, 0xdb, 0x12, 0x42, 0xaa, 0xfb, - 0x19, 0xa8, 0xed, 0xc4, 0x7d, 0x1a, 0x91, 0xb5, 0x10, 0x7d, 0x15, 0x8c, 0x99, 0xf3, 0x52, 0xba, 0xc5, 0xa6, 0xab, - 0xcd, 0xea, 0x06, 0x9d, 0x4b, 0x5b, 0x6e, 0x7e, 0xc2, 0x16, 0x6b, 0x05, 0xca, 0x26, 0x24, 0x6d, 0xe7, 0x3c, 0x47, - 0xd9, 0x84, 0x96, 0xf6, 0x9e, 0x7a, 0x54, 0xa8, 0x4e, 0xb6, 0x5e, 0xaa, 0xa6, 0x16, 0x61, 0xb5, 0xb8, 0xa8, 0xfc, - 0x00, 0x74, 0x53, 0x69, 0xf5, 0xb2, 0xae, 0xd1, 0x14, 0x6a, 0xb5, 0x70, 0xdc, 0x68, 0x67, 0xd3, 0x65, 0x7a, 0x87, - 0x38, 0xab, 0xd2, 0x0e, 0xfd, 0x7d, 0xa6, 0x5d, 0x2f, 0x3b, 0xfa, 0xcd, 0xb8, 0xba, 0xc0, 0x85, 0xd8, 0x80, 0xcf, - 0xb9, 0xbf, 0xbc, 0xde, 0xf3, 0xb8, 0xe7, 0x1f, 0x0e, 0xc8, 0x9e, 0xd4, 0xfe, 0x50, 0x7d, 0xec, 0x0a, 0x86, 0x2c, - 0x8c, 0x52, 0x7f, 0x91, 0xf2, 0xde, 0x13, 0x1c, 0xf7, 0xcf, 0x55, 0x8f, 0xfd, 0x98, 0xf1, 0x7d, 0x5d, 0x6c, 0xa2, - 0x84, 0xa2, 0x1a, 0x7a, 0xab, 0x62, 0x53, 0x89, 0xb8, 0x78, 0xc8, 0x7b, 0x0c, 0x93, 0x61, 0x2c, 0x64, 0x2a, 0xfc, - 0x29, 0x53, 0xc1, 0x23, 0x84, 0x12, 0x37, 0xeb, 0x1e, 0x69, 0x37, 0x21, 0x4e, 0xa9, 0x16, 0xa5, 0x4c, 0xc6, 0xbf, - 0xf5, 0x13, 0x28, 0xcf, 0x29, 0x5a, 0xa6, 0x1f, 0x15, 0x2e, 0xd3, 0x37, 0xeb, 0xe3, 0xd2, 0x33, 0x11, 0xea, 0xcc, - 0xc5, 0xa6, 0xd6, 0xe9, 0x18, 0x3b, 0xa5, 0x53, 0x1b, 0xf6, 0xa5, 0x52, 0x5c, 0x56, 0x14, 0xfe, 0x8d, 0x44, 0x56, - 0x3d, 0x23, 0x8e, 0xff, 0x2b, 0x6b, 0x9f, 0x61, 0x15, 0xf8, 0x65, 0x20, 0xef, 0x17, 0x00, 0x1f, 0xd7, 0x75, 0x99, - 0xde, 0x6e, 0x80, 0x36, 0x84, 0x86, 0xbf, 0xe7, 0x23, 0x03, 0xa6, 0xfb, 0x08, 0x67, 0x48, 0x0f, 0x75, 0xce, 0xe9, - 0xac, 0x4c, 0xe7, 0x5c, 0x85, 0xb5, 0x04, 0x7b, 0x39, 0x69, 0x72, 0xb9, 0x2e, 0x41, 0xcd, 0x04, 0x6e, 0x1f, 0xda, - 0x23, 0x42, 0xa8, 0x4d, 0x59, 0x4d, 0x2f, 0xa1, 0xe6, 0x9d, 0x9c, 0x76, 0x34, 0x29, 0xc1, 0x55, 0x43, 0x67, 0xe5, - 0xfa, 0xaf, 0xc3, 0xa1, 0x77, 0x9b, 0x15, 0xd1, 0x1f, 0x3d, 0xf4, 0x77, 0xdc, 0xde, 0xa4, 0x5f, 0x20, 0x5a, 0xc6, - 0xfa, 0x1b, 0x32, 0xa0, 0xe3, 0xc9, 0xf0, 0xb6, 0xd8, 0xf6, 0xd8, 0x17, 0xd4, 0x60, 0xe9, 0xeb, 0xc7, 0x1f, 0x20, - 0xa1, 0xea, 0xda, 0x17, 0x16, 0x4f, 0x98, 0xa7, 0x44, 0xdb, 0xc2, 0x87, 0xb0, 0xd0, 0x2f, 0x10, 0x19, 0x09, 0xe1, - 0xa6, 0xb2, 0x7b, 0x94, 0xb4, 0x0b, 0x7d, 0xe9, 0x6b, 0xd9, 0x57, 0xbe, 0x73, 0x01, 0xb0, 0xb2, 0xcf, 0x6d, 0xb8, - 0x27, 0xfd, 0x29, 0xd5, 0x87, 0xed, 0x6f, 0xc9, 0x02, 0x0a, 0x2d, 0xac, 0xa7, 0x72, 0x76, 0xae, 0x4b, 0x9e, 0x66, - 0xd3, 0xfd, 0x1a, 0xf6, 0xa8, 0x7b, 0xf4, 0x9a, 0x0a, 0xce, 0x2f, 0xcd, 0xe8, 0xfd, 0xd3, 0x50, 0xa8, 0x8e, 0x3a, - 0x77, 0x90, 0x75, 0x69, 0x5d, 0x72, 0x7e, 0xb3, 0x72, 0x47, 0x61, 0x7e, 0x1f, 0x82, 0x67, 0x58, 0xf7, 0xee, 0xe2, - 0xbc, 0xf7, 0x67, 0x6b, 0x8e, 0xfc, 0x98, 0xcd, 0x52, 0xc4, 0x22, 0x99, 0x83, 0xd5, 0x0f, 0xfd, 0x3c, 0xf6, 0xdb, - 0x20, 0x87, 0xe3, 0xa6, 0x01, 0x1d, 0x36, 0x64, 0xd6, 0xbe, 0x44, 0xe0, 0x54, 0x23, 0x48, 0x53, 0x13, 0xd4, 0x2c, - 0x0f, 0x91, 0xd8, 0x2e, 0x65, 0xdb, 0x20, 0xd7, 0x5d, 0x30, 0xcd, 0x91, 0xf6, 0x0c, 0xde, 0x37, 0x69, 0x92, 0x0a, - 0xcd, 0x22, 0x6d, 0x95, 0x8c, 0x7f, 0x47, 0xda, 0x4c, 0xc9, 0x1e, 0x5b, 0x03, 0xef, 0x25, 0x28, 0x27, 0xc3, 0x14, - 0xc3, 0x77, 0x7c, 0xbd, 0xf3, 0x98, 0x7b, 0xce, 0x31, 0xdb, 0xa4, 0xec, 0x08, 0x26, 0xc9, 0xc6, 0x37, 0x14, 0x6f, - 0xf8, 0xfe, 0xb6, 0x12, 0x25, 0x80, 0x5e, 0x16, 0xfc, 0x85, 0xb4, 0xb9, 0x42, 0xb7, 0xbb, 0x77, 0x94, 0xc2, 0x2f, - 0x79, 0x79, 0x38, 0x6c, 0x53, 0x2f, 0x84, 0xce, 0x17, 0xf1, 0x3b, 0x30, 0x87, 0x31, 0xc4, 0x66, 0x04, 0x08, 0x73, - 0x7c, 0x40, 0x1d, 0xac, 0x1f, 0x01, 0x68, 0x9c, 0x40, 0x01, 0x46, 0x5f, 0x6d, 0x0b, 0xfa, 0x96, 0x17, 0x17, 0x11, - 0xa2, 0x46, 0x01, 0x26, 0x4a, 0x9a, 0xc5, 0x30, 0x1c, 0xe8, 0xfc, 0xbe, 0xb9, 0xad, 0x4b, 0x81, 0x43, 0xef, 0x58, - 0x86, 0xff, 0xfe, 0x3f, 0xd6, 0x96, 0x56, 0x95, 0xed, 0xd6, 0x38, 0xcd, 0xfc, 0x6f, 0xb7, 0x85, 0xbe, 0xff, 0x4a, - 0x28, 0x9e, 0x77, 0xbc, 0x6e, 0xbf, 0x83, 0xe8, 0x7d, 0xdd, 0xca, 0xbb, 0x52, 0xbb, 0x61, 0xa6, 0xfc, 0x21, 0xcd, - 0xe3, 0xe2, 0x61, 0x14, 0xb7, 0x8e, 0xbc, 0x49, 0x7a, 0xce, 0xf9, 0xbb, 0xaa, 0xdf, 0xf7, 0xde, 0x01, 0x19, 0xef, - 0x2b, 0x61, 0x1c, 0x31, 0x89, 0x83, 0x6f, 0x2f, 0x46, 0xd1, 0xa6, 0x84, 0x0d, 0xb9, 0x7d, 0x5a, 0x82, 0x66, 0xa6, - 0xdf, 0x47, 0x89, 0xd2, 0x9a, 0xef, 0x7f, 0x93, 0xf3, 0xfd, 0x95, 0x90, 0x37, 0x2b, 0xf9, 0xe1, 0xa3, 0x15, 0x06, - 0xbe, 0xc7, 0xe9, 0x17, 0xd1, 0x63, 0x77, 0xa5, 0x0f, 0xdf, 0x95, 0x96, 0x3e, 0xab, 0xa8, 0x7f, 0xa0, 0xa2, 0xe6, - 0x95, 0x18, 0x11, 0xf1, 0x20, 0x68, 0x67, 0xdb, 0xa5, 0x76, 0x2d, 0x41, 0xbb, 0x60, 0x53, 0xd8, 0xbf, 0x1f, 0x1d, - 0xf2, 0x7e, 0xff, 0x63, 0xee, 0xb5, 0x78, 0xdd, 0x75, 0x68, 0xca, 0x4f, 0x85, 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, 0x11, 0xeb, 0xa6, 0xa7, 0x55, 0x68, 0xf9, 0x1a, 0x82, 0x75, 0x91, 0x65, 0x1c, 0xc5, - 0x4c, 0x00, 0xb0, 0xf9, 0x08, 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, - 0x7b, 0xaa, 0x7a, 0x44, 0xa0, 0x57, 0x65, 0x5a, 0x45, 0x45, 0x9e, 0x8b, 0x08, 0x11, 0xaa, 0xa5, 0x73, 0x38, 0xf4, - 0x63, 0xbf, 0x8f, 0x03, 0x61, 0x5e, 0xfc, 0xe9, 0xb1, 0xae, 0xfc, 0xa9, 0xc0, 0xb5, 0x92, 0x02, 0xa7, 0xa2, 0x46, - 0x88, 0x10, 0xde, 0x9f, 0xc0, 0xb3, 0x9a, 0xfa, 0x7e, 0x63, 0x99, 0xe8, 0xfe, 0x99, 0x01, 0xe5, 0x0f, 0xc8, 0xd7, - 0x95, 0x14, 0x67, 0xea, 0xe4, 0x31, 0x71, 0xc6, 0x01, 0x88, 0xf9, 0xba, 0x44, 0xa3, 0xb1, 0xff, 0x01, 0x09, 0x86, - 0xea, 0x07, 0x3b, 0xdd, 0xd4, 0xfb, 0x57, 0x26, 0x71, 0x14, 0x7d, 0xda, 0x26, 0x8f, 0x25, 0x4b, 0xa3, 0x85, 0xa3, - 0xf7, 0x88, 0x61, 0x1c, 0x4e, 0xe7, 0x63, 0x92, 0x6d, 0x4c, 0x56, 0x01, 0xa4, 0x93, 0x99, 0x3a, 0xa6, 0xd4, 0xd1, - 0x38, 0xd7, 0x0b, 0xaa, 0xd0, 0x63, 0x5d, 0xf2, 0x1c, 0xac, 0x27, 0x3f, 0x78, 0xa5, 0x3f, 0x15, 0x72, 0x0e, 0x1b, - 0x89, 0xa0, 0xf0, 0x03, 0x5c, 0x0d, 0x56, 0x0a, 0x18, 0x4c, 0x7d, 0x0b, 0x5f, 0x13, 0xcf, 0x51, 0xf0, 0x28, 0xec, - 0x62, 0x6c, 0xad, 0x7c, 0xe7, 0x93, 0x82, 0x72, 0xcf, 0x8a, 0x39, 0xaf, 0x80, 0x73, 0x19, 0x14, 0xc2, 0x74, 0x3c, - 0xcb, 0xff, 0x99, 0xe4, 0xf5, 0xc4, 0x86, 0x00, 0x19, 0xfc, 0x29, 0x71, 0x5a, 0xba, 0x43, 0x77, 0x1e, 0x7a, 0x16, - 0x71, 0xd8, 0xe8, 0xc9, 0xba, 0x2c, 0xb6, 0x29, 0xea, 0x25, 0xcc, 0x0f, 0xe4, 0xe7, 0x2d, 0xf9, 0x3e, 0x44, 0xf1, - 0x36, 0xf8, 0x35, 0x63, 0xb1, 0xc0, 0xbf, 0xfe, 0x9e, 0x31, 0x9a, 0x68, 0xc1, 0xbf, 0xb3, 0x06, 0x89, 0x8a, 0x7f, - 0xca, 0x26, 0x00, 0xeb, 0xc8, 0xd5, 0x87, 0x4f, 0x89, 0xf1, 0xd6, 0x6c, 0x78, 0xe4, 0x9b, 0x15, 0xe8, 0xd4, 0xe7, - 0xee, 0xca, 0xf6, 0x54, 0x35, 0xfe, 0x9e, 0xea, 0x6a, 0xa4, 0xaa, 0x1a, 0x7f, 0x4f, 0xa9, 0x1a, 0xbf, 0x65, 0x14, - 0xbf, 0x53, 0xf9, 0x0c, 0x99, 0x93, 0x4d, 0x4c, 0xd2, 0xe9, 0x7b, 0xc3, 0x89, 0x5d, 0xf6, 0xab, 0xb7, 0x89, 0xcc, - 0x44, 0x0a, 0xb9, 0x37, 0x00, 0x6d, 0xbf, 0xcb, 0x0d, 0xa7, 0xc4, 0xf9, 0xb9, 0x87, 0x2b, 0x36, 0xad, 0x5e, 0xd1, - 0x82, 0x05, 0x36, 0x2f, 0xb3, 0x3c, 0x45, 0x02, 0xdb, 0xa6, 0xcc, 0xfa, 0x73, 0xee, 0x01, 0x04, 0x33, 0xa9, 0x09, - 0x00, 0x69, 0x21, 0x2a, 0x85, 0xc8, 0x5f, 0xe1, 0xac, 0x3e, 0xe7, 0xbd, 0x4d, 0x1e, 0x13, 0x69, 0x75, 0xaf, 0xdf, - 0x4f, 0xcf, 0xd2, 0x9c, 0x82, 0x1a, 0x8e, 0xb3, 0x4e, 0xbf, 0xcf, 0x82, 0x3a, 0x91, 0xab, 0xf4, 0x1f, 0x6e, 0x90, - 0x97, 0xf1, 0x7d, 0xdd, 0xf6, 0xfc, 0x89, 0xfa, 0x7b, 0x67, 0xfd, 0x6d, 0x81, 0xe0, 0x4e, 0x8e, 0xfd, 0x64, 0x55, - 0xca, 0x13, 0xe3, 0xd2, 0xde, 0xf3, 0x9b, 0xba, 0x28, 0xb2, 0x3a, 0x5d, 0x7f, 0x90, 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, 0xe8, 0x40, 0xbd, 0xb4, 0xd2, 0x3e, 0x82, 0x6e, - 0x05, 0x7a, 0x50, 0x0f, 0x7d, 0x9a, 0xb4, 0x2f, 0x24, 0xea, 0xf6, 0x56, 0xa7, 0xd1, 0x1f, 0x15, 0x5c, 0x4e, 0x61, - 0x72, 0xb8, 0xa1, 0x4f, 0xab, 0x70, 0xfb, 0x09, 0x9e, 0xfe, 0x0c, 0x94, 0x5b, 0x87, 0x43, 0x0e, 0x62, 0x0b, 0xb8, - 0x79, 0xac, 0xc2, 0xcf, 0x45, 0x29, 0x23, 0xea, 0xe3, 0x69, 0x01, 0xda, 0xbb, 0x00, 0x1d, 0xb0, 0x34, 0x88, 0x57, - 0x48, 0x9e, 0xb3, 0x11, 0xc0, 0xb2, 0x03, 0xcb, 0x59, 0xc6, 0x29, 0xcc, 0xb3, 0x7c, 0xa1, 0x56, 0xda, 0x59, 0x99, - 0x78, 0x35, 0xcb, 0xc0, 0x59, 0xe0, 0xa2, 0xf2, 0x59, 0xa6, 0x55, 0x4f, 0x55, 0x82, 0x3e, 0xaf, 0xe4, 0x04, 0x57, - 0x82, 0x93, 0x0d, 0xc8, 0x2f, 0x40, 0x92, 0xa6, 0x94, 0x35, 0xe5, 0x8b, 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, 0x3f, - 0x78, 0x4b, 0x7f, 0x3a, 0x0e, 0xc2, 0x21, 0x72, 0x43, 0xc5, 0x1c, 0xd8, 0xd3, 0x80, 0xc5, 0x26, 0xbe, 0xda, 0x4c, - 0xe2, 0xc1, 0xc0, 0xd7, 0x19, 0x8b, 0x59, 0x0c, 0x34, 0xc8, 0xf1, 0xe0, 0x72, 0xae, 0x4f, 0x08, 0xfd, 0x30, 0xa2, - 0x72, 0x54, 0xa0, 0x73, 0x10, 0x0d, 0x96, 0x80, 0xa7, 0xde, 0xca, 0x06, 0x49, 0xc6, 0x24, 0x93, 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, 0x3f, 0xcb, 0x07, 0x8e, 0x3b, 0x2a, 0x69, - 0x08, 0x0c, 0xde, 0x1e, 0xba, 0x9b, 0x19, 0x1a, 0xea, 0xa4, 0x7d, 0x18, 0x87, 0x72, 0x88, 0x55, 0x2b, 0x2e, 0xa4, - 0x37, 0x82, 0x6f, 0x17, 0x8a, 0xb1, 0x6c, 0xec, 0xd2, 0x50, 0x14, 0xfe, 0x0a, 0x60, 0x87, 0xda, 0x5f, 0xa9, 0xe4, - 0x63, 0x64, 0x54, 0xd3, 0x40, 0xc7, 0x00, 0x2c, 0x59, 0x9a, 0x48, 0xaa, 0x48, 0x23, 0xf1, 0x47, 0x66, 0xac, 0xa3, - 0xa6, 0xeb, 0x0b, 0xa6, 0xaa, 0x45, 0xd2, 0xed, 0x4c, 0x62, 0x39, 0x91, 0xa4, 0xb6, 0xfb, 0x88, 0x18, 0x0c, 0x7c, - 0xb0, 0x11, 0xd3, 0x4c, 0x84, 0x23, 0x1e, 0x95, 0xc8, 0xa2, 0xcb, 0x6f, 0xa3, 0x4c, 0xda, 0xbe, 0xac, 0xc8, 0x16, - 0x04, 0xd3, 0x93, 0xe8, 0x83, 0x24, 0xe5, 0x54, 0x24, 0xd2, 0x8c, 0x10, 0xe0, 0xc7, 0x93, 0xf2, 0x4a, 0x7f, 0x0e, - 0x9a, 0x56, 0x82, 0x97, 0x0c, 0x92, 0x47, 0xe2, 0x67, 0x52, 0x30, 0x8b, 0xb1, 0x6a, 0x30, 0xc0, 0x72, 0xaa, 0x67, - 0x8e, 0x49, 0xfa, 0x6f, 0x9d, 0x4e, 0xd8, 0x2f, 0xbd, 0xdc, 0xd6, 0xf2, 0xa6, 0xb9, 0xf7, 0xd2, 0xab, 0x58, 0xaa, - 0x61, 0x19, 0xf4, 0x5f, 0x13, 0xed, 0x82, 0xad, 0x2d, 0x63, 0xc2, 0xaa, 0x1f, 0x40, 0xda, 0x23, 0x5d, 0x5e, 0x35, - 0xcc, 0x99, 0xe0, 0xd1, 0x85, 0x35, 0x0f, 0xa2, 0x0b, 0xe1, 0x23, 0x97, 0xdd, 0x24, 0xb9, 0x1a, 0x4f, 0xfc, 0x70, - 0x30, 0x50, 0x00, 0xb4, 0xb4, 0x4e, 0x8a, 0x41, 0xf8, 0x4c, 0xc8, 0x81, 0x34, 0x3a, 0xaa, 0x02, 0x2c, 0x96, 0xd9, - 0x55, 0x39, 0xc9, 0x06, 0x03, 0x1f, 0xc4, 0xc6, 0xc4, 0x6e, 0x68, 0x36, 0xf7, 0xd9, 0x89, 0x82, 0xac, 0x36, 0x87, - 0xad, 0x99, 0x6e, 0x81, 0x01, 0xc0, 0x20, 0x22, 0x58, 0xee, 0x73, 0x23, 0x1f, 0x51, 0xa7, 0xa7, 0x30, 0x02, 0x82, - 0x5f, 0x4e, 0x04, 0x22, 0x17, 0x09, 0xd4, 0x03, 0xcc, 0x04, 0x98, 0x51, 0xc5, 0xf0, 0x12, 0xd8, 0xc5, 0x73, 0xf3, - 0x8a, 0x41, 0xff, 0xa2, 0x49, 0x96, 0x68, 0x2a, 0x71, 0x34, 0x46, 0x4e, 0xa5, 0x31, 0x32, 0x20, 0x76, 0x71, 0xfc, - 0x7b, 0x4a, 0x8f, 0x82, 0x94, 0x7d, 0xae, 0x0c, 0x71, 0x38, 0x8a, 0xaf, 0x60, 0xd5, 0x38, 0x1c, 0x6a, 0xf3, 0x7a, - 0x3a, 0xab, 0xe7, 0x03, 0x11, 0xc0, 0x7f, 0x43, 0xc1, 0x7e, 0xd1, 0x54, 0xe4, 0x06, 0xa9, 0xf3, 0x70, 0x48, 0x41, - 0x3e, 0xd5, 0x4d, 0xfe, 0xbe, 0x72, 0xf7, 0xd3, 0xd9, 0xdc, 0x9a, 0xa3, 0x17, 0x35, 0xae, 0x5b, 0xab, 0x1b, 0x0a, - 0x89, 0xd6, 0x34, 0x29, 0xae, 0xaa, 0x49, 0x31, 0xe0, 0xb9, 0x2f, 0x54, 0x17, 0x5b, 0x23, 0x58, 0xf8, 0x73, 0x0b, - 0x84, 0xc9, 0xb8, 0x17, 0x1f, 0x2d, 0xe4, 0x94, 0x76, 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, 0xf3, 0x20, 0xe3, 0x5e, 0x34, 0xec, 0xf8, 0x02, 0xec, 0xd5, 0x17, 0xcf, - 0x59, 0x34, 0xe0, 0xd5, 0x55, 0x3d, 0xcd, 0x82, 0x61, 0xc6, 0xa2, 0xab, 0x62, 0x08, 0x3e, 0xb4, 0x2f, 0xca, 0x41, - 0xe8, 0xfb, 0x66, 0xe7, 0xd0, 0xdd, 0x90, 0xc8, 0x23, 0xec, 0x47, 0x70, 0xdb, 0xd5, 0x12, 0x33, 0x98, 0x6c, 0xee, - 0x22, 0x66, 0xb0, 0xe5, 0x2f, 0x9e, 0x1b, 0x2e, 0xa1, 0xea, 0x85, 0xd4, 0x6c, 0x14, 0x68, 0x4e, 0xae, 0xd0, 0x9c, - 0xac, 0x84, 0x5a, 0xf2, 0x49, 0x85, 0x13, 0x76, 0x3e, 0xc9, 0x95, 0xdd, 0x68, 0x8c, 0x81, 0x8b, 0xf6, 0xdc, 0x16, - 0x46, 0x66, 0x3a, 0x4b, 0xd1, 0x80, 0x85, 0x67, 0xe2, 0x94, 0xc6, 0x80, 0xf6, 0xe5, 0xc0, 0xd2, 0x86, 0xfc, 0x28, - 0x67, 0x06, 0xda, 0x86, 0x94, 0x46, 0xcd, 0xc0, 0x9f, 0xa9, 0x09, 0xf3, 0x2b, 0x58, 0x89, 0x20, 0xaa, 0x0b, 0x30, - 0x49, 0x72, 0x32, 0x1a, 0x29, 0x2b, 0x91, 0x9c, 0x03, 0xde, 0x47, 0xf0, 0x64, 0x11, 0xdb, 0xda, 0x9f, 0xd2, 0xff, - 0xea, 0xf0, 0xb9, 0xf4, 0x9f, 0x09, 0x60, 0x21, 0x97, 0x06, 0x91, 0x81, 0xc2, 0x21, 0x35, 0x95, 0x88, 0x13, 0xc7, - 0x33, 0xf0, 0x0d, 0x5c, 0xa0, 0x29, 0xa0, 0x3f, 0xa8, 0x19, 0x45, 0x64, 0xe1, 0xaf, 0x9e, 0xdd, 0xd4, 0x8d, 0x9e, - 0x67, 0xce, 0x6b, 0xd0, 0xcc, 0x40, 0x48, 0x8f, 0x53, 0xf5, 0x36, 0x24, 0x3a, 0x2f, 0x2f, 0xf5, 0xcb, 0x84, 0x48, - 0x56, 0x44, 0x9e, 0xbe, 0xcf, 0xc1, 0x3c, 0xa2, 0x08, 0x1d, 0x5c, 0x99, 0x87, 0xc3, 0xb9, 0xa0, 0xf0, 0x1d, 0xe5, - 0xf9, 0x80, 0xd3, 0x2c, 0x4a, 0x40, 0x1b, 0xc8, 0x72, 0x53, 0xe6, 0x3a, 0x69, 0x99, 0xba, 0xf7, 0x60, 0x25, 0xa8, - 0xd0, 0xcd, 0x29, 0x28, 0x94, 0x91, 0xa0, 0x94, 0x56, 0x83, 0x50, 0xaa, 0xc3, 0x22, 0x88, 0x1c, 0xb2, 0x10, 0x70, - 0x33, 0x15, 0x8d, 0x96, 0x34, 0x3c, 0xc2, 0xb9, 0x81, 0x42, 0x00, 0x12, 0x7b, 0xaa, 0x28, 0xe3, 0x72, 0x08, 0xf8, - 0x28, 0xe1, 0x10, 0x67, 0x4d, 0xda, 0xf2, 0x1c, 0xc4, 0xb1, 0x5c, 0xf2, 0x75, 0x85, 0x60, 0x10, 0xa1, 0xcf, 0x90, - 0x3f, 0x59, 0xce, 0xbf, 0x5b, 0x87, 0x69, 0x47, 0xf8, 0xb0, 0xab, 0x2d, 0xb8, 0x98, 0xdd, 0xce, 0x27, 0x10, 0xdf, - 0x72, 0x3b, 0x3f, 0xc6, 0x10, 0x59, 0xf8, 0x83, 0xbb, 0xa1, 0xe4, 0x8a, 0x42, 0x97, 0xf5, 0x88, 0x14, 0xd9, 0xd3, - 0x35, 0x47, 0x10, 0x1c, 0x68, 0xd5, 0x20, 0x43, 0x23, 0xf1, 0xc5, 0x73, 0xc8, 0x1a, 0xac, 0xf9, 0xe7, 0x8a, 0x9c, - 0xd5, 0xfd, 0xc9, 0x06, 0xaa, 0x49, 0x26, 0x6b, 0x45, 0xe5, 0xfc, 0xf5, 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, 0xff, 0x15, 0xfc, 0x4b, 0x85, 0x2c, 0xd5, 0x69, 0x9d, 0x89, - 0x5f, 0x83, 0x25, 0xc3, 0x3f, 0x7e, 0x0b, 0xd6, 0x80, 0x25, 0x40, 0x96, 0xbb, 0x8d, 0x8d, 0xd6, 0x2b, 0xaf, 0x10, - 0x5f, 0x6a, 0x7d, 0xd1, 0x6f, 0xdd, 0x26, 0x6a, 0x05, 0x18, 0xa1, 0xd0, 0x22, 0xc0, 0x56, 0x0f, 0xdc, 0x53, 0xf0, - 0x03, 0x31, 0x9c, 0x6b, 0xd2, 0x9a, 0x3a, 0xe1, 0x75, 0x36, 0x8e, 0x44, 0x54, 0x6f, 0xe1, 0xe2, 0x5e, 0x6f, 0x2d, - 0xfe, 0x46, 0x05, 0x02, 0x20, 0x8b, 0x29, 0xd6, 0xce, 0x1b, 0xd2, 0x2b, 0xc3, 0x4e, 0x42, 0xef, 0x0d, 0x3b, 0x81, - 0xbc, 0x38, 0xec, 0x14, 0xba, 0x44, 0xdb, 0x29, 0x52, 0x13, 0x6d, 0x27, 0x2d, 0x56, 0x61, 0x09, 0xc1, 0xaf, 0xda, - 0x5b, 0x47, 0xd9, 0xbe, 0xc8, 0x12, 0xa6, 0x2d, 0x60, 0x94, 0x5b, 0xf5, 0x99, 0x53, 0xc4, 0x4a, 0xd9, 0x3b, 0x9d, - 0x54, 0xb9, 0x8b, 0x7c, 0x6a, 0x35, 0x45, 0x26, 0x7f, 0x7f, 0xdc, 0x22, 0xf9, 0xe4, 0xe7, 0x76, 0xc3, 0x64, 0xfa, - 0xc7, 0xa3, 0x2f, 0xa0, 0x2b, 0xb2, 0xd3, 0x27, 0x10, 0x90, 0xa9, 0xa0, 0x5a, 0xdd, 0x2a, 0xa6, 0x79, 0xbb, 0xca, - 0x6e, 0x2f, 0x94, 0x18, 0x4e, 0x67, 0x27, 0xe1, 0xd1, 0x66, 0xc8, 0xc0, 0x21, 0x08, 0x14, 0x42, 0x45, 0x31, 0x3c, - 0x02, 0xb5, 0x46, 0xf2, 0x01, 0x7e, 0xb4, 0x3b, 0x15, 0x44, 0x6a, 0x37, 0x15, 0x37, 0x4e, 0x6e, 0xba, 0x5e, 0x0a, - 0xd4, 0x3a, 0x25, 0x2b, 0x80, 0x12, 0xa2, 0xfe, 0x24, 0xb6, 0xf5, 0x2b, 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, 0x75, 0xbb, 0xe9, 0x98, 0xd8, 0xea, 0x9f, 0x45, 0xb5, 0xb9, 0x83, 0x8a, 0x88, 0xf8, 0x28, 0xbb, 0x79, 0xd2, - 0x7e, 0x07, 0x7b, 0xac, 0xd5, 0x20, 0xb2, 0xcf, 0xe0, 0x2a, 0xd7, 0x69, 0x91, 0xdb, 0x32, 0x38, 0xff, 0xf0, 0x6a, - 0x57, 0x61, 0x93, 0x63, 0x5d, 0x5d, 0xcd, 0x54, 0x27, 0x15, 0x1b, 0x18, 0x6b, 0x5a, 0x4b, 0x35, 0x8f, 0x21, 0xe9, - 0xae, 0x2c, 0xce, 0xaa, 0xa4, 0x9b, 0x9e, 0x1b, 0x67, 0x0a, 0x31, 0x70, 0xb6, 0x1a, 0x2d, 0x67, 0x18, 0xa2, 0xeb, - 0xc3, 0x2c, 0xf1, 0x5b, 0x3d, 0xe5, 0x3e, 0x0f, 0xb7, 0x7e, 0x57, 0x2f, 0x38, 0x99, 0xec, 0x27, 0xc7, 0xb9, 0xdb, - 0x45, 0xda, 0x4f, 0x7c, 0x1b, 0xe6, 0x5f, 0xdf, 0x20, 0xee, 0x44, 0xfd, 0xcf, 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, 0x7f, 0x7a, 0x35, 0x3b, 0x15, 0x54, 0x06, 0x6e, 0xc6, 0x7f, 0x7a, 0x82, 0x9d, 0xc2, 0x5a, - 0x01, 0x59, 0xe1, 0x4f, 0x2f, 0x7f, 0xe4, 0xfd, 0x8a, 0xff, 0xe9, 0x55, 0x8f, 0xbc, 0x8f, 0x38, 0x2f, 0x7f, 0x22, - 0xa9, 0x13, 0xa2, 0xba, 0xfc, 0x49, 0x98, 0x62, 0xab, 0x34, 0x7f, 0x4d, 0x0a, 0x9f, 0xe0, 0x33, 0xf0, 0x1d, 0xae, - 0xc2, 0xad, 0xf9, 0x0d, 0x1e, 0x3b, 0x16, 0xdb, 0x2e, 0xf5, 0x05, 0x94, 0x23, 0xb0, 0x88, 0xdc, 0x7e, 0xbb, 0xb2, - 0x5f, 0x2d, 0x8c, 0x32, 0xc6, 0xee, 0x4b, 0x56, 0xa2, 0x74, 0xd6, 0xef, 0x17, 0x52, 0x30, 0xb2, 0x0b, 0x6b, 0xb4, - 0x47, 0xa9, 0x7a, 0xf5, 0x3a, 0xac, 0xa3, 0x24, 0xcd, 0xef, 0x64, 0xf4, 0x91, 0x0c, 0x3b, 0xd2, 0x57, 0x52, 0xa2, - 0xbd, 0x56, 0x61, 0x39, 0x9a, 0xfd, 0xba, 0xe4, 0x40, 0x79, 0xdd, 0x0a, 0xca, 0x57, 0x4d, 0x00, 0xbd, 0x52, 0xed, - 0x33, 0xd0, 0x0a, 0x0a, 0x4b, 0xe5, 0xc1, 0x4a, 0x9c, 0x8b, 0x3e, 0x2b, 0x0e, 0x07, 0x75, 0x31, 0x24, 0x14, 0xa8, - 0x12, 0x27, 0xa1, 0x11, 0xcf, 0xe1, 0x42, 0x28, 0x5e, 0xe4, 0x18, 0x5b, 0x91, 0x03, 0x07, 0x32, 0xfc, 0x80, 0xc0, - 0x7b, 0xd9, 0xbf, 0x82, 0xc1, 0x30, 0xc1, 0x8d, 0x8c, 0x3a, 0x39, 0x67, 0x7f, 0x62, 0x60, 0x06, 0xf5, 0xa4, 0x76, - 0x9f, 0xdd, 0xab, 0xc0, 0x5e, 0x38, 0x03, 0xda, 0xbb, 0x31, 0xfa, 0x59, 0x15, 0x6b, 0x27, 0xfd, 0x53, 0xb1, 0x86, - 0x64, 0x3a, 0x2c, 0x8e, 0xb6, 0x69, 0x78, 0x24, 0x4f, 0x8e, 0xe3, 0x4d, 0xff, 0x70, 0x18, 0xe3, 0xc7, 0x51, 0x7e, - 0x6d, 0x01, 0xaf, 0xe2, 0x16, 0xd2, 0x58, 0xa4, 0xe8, 0x1d, 0x88, 0x39, 0x14, 0xbd, 0x64, 0xbf, 0x65, 0xbc, 0x9c, - 0x08, 0x4a, 0x49, 0x62, 0xc3, 0x3b, 0xd2, 0xd3, 0xb4, 0x1e, 0x6d, 0x65, 0xc0, 0x7e, 0x3d, 0xda, 0xd1, 0x5f, 0xa0, - 0x78, 0xb4, 0xf0, 0x97, 0xf4, 0x77, 0x71, 0x37, 0xf7, 0x9c, 0x6f, 0x1a, 0xdf, 0x11, 0x17, 0x28, 0xd6, 0xec, 0xfe, - 0x9a, 0x96, 0xce, 0x3a, 0x10, 0x1c, 0xf0, 0x16, 0xbb, 0x68, 0xdf, 0x6f, 0x5c, 0xa7, 0xa7, 0xfd, 0xb7, 0x6e, 0x8d, - 0xf2, 0xbd, 0x7f, 0x4a, 0x94, 0x83, 0xfd, 0x6b, 0x17, 0xcd, 0xdf, 0x7e, 0xca, 0x90, 0x54, 0x68, 0x6e, 0xb0, 0x9d, - 0x6c, 0x11, 0xd6, 0xc6, 0x38, 0xa8, 0xd8, 0x5d, 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, 0x5f, 0x11, 0x3e, 0xd4, 0x4e, 0x4a, 0x87, 0xf2, 0x57, 0xcf, 0xd9, - 0xff, 0xec, 0xb0, 0xa6, 0xa6, 0xdc, 0x00, 0x66, 0xce, 0x4a, 0xe4, 0x15, 0x42, 0xa7, 0xc8, 0xef, 0x55, 0x5d, 0x89, - 0xe1, 0xb2, 0x16, 0x65, 0x67, 0x76, 0xeb, 0x44, 0xef, 0x9c, 0x82, 0x5a, 0x2a, 0x1b, 0xe4, 0x24, 0xd5, 0xe6, 0x23, - 0x6b, 0x05, 0x25, 0xea, 0x1a, 0x05, 0x8e, 0x4f, 0xb9, 0x76, 0xff, 0xef, 0x9c, 0x09, 0x6a, 0xb6, 0x51, 0xdd, 0x5f, - 0xeb, 0xa7, 0xaa, 0x26, 0xb1, 0x00, 0x97, 0x93, 0x34, 0xef, 0x78, 0x84, 0xd5, 0x3f, 0x4e, 0x96, 0x22, 0xd0, 0xeb, - 0x88, 0x76, 0x25, 0x20, 0x41, 0x3b, 0x39, 0x0b, 0x15, 0x81, 0x02, 0x7d, 0xfd, 0xfb, 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, 0x0a, 0xb9, 0x41, 0x44, 0xd3, 0xef, 0x25, 0xaa, 0x1d, - 0x29, 0x90, 0x43, 0xc9, 0x4f, 0x88, 0xbf, 0x64, 0x6d, 0x8c, 0xfb, 0xa5, 0x53, 0xed, 0x57, 0x0a, 0xc1, 0xfd, 0x67, - 0x5b, 0x6c, 0x54, 0x79, 0xa2, 0x47, 0x9f, 0x62, 0xfd, 0x4f, 0x16, 0x50, 0xaa, 0xfb, 0x36, 0x38, 0x15, 0x8f, 0xc2, - 0x4d, 0x5d, 0xdc, 0x20, 0xb4, 0x40, 0x39, 0xaa, 0x8a, 0x4d, 0x19, 0x11, 0x27, 0xec, 0xa6, 0x2e, 0x7a, 0x9a, 0x03, - 0x9d, 0x3a, 0x2c, 0x4d, 0xe4, 0x89, 0xd0, 0x6e, 0x41, 0xf7, 0x34, 0xc7, 0x4a, 0xbc, 0x94, 0xa5, 0x83, 0xac, 0x13, - 0x69, 0x42, 0xe5, 0xae, 0xae, 0x3a, 0x2a, 0x95, 0xba, 0xe1, 0x4d, 0xaa, 0x19, 0x7f, 0x97, 0xe6, 0x4f, 0x2c, 0xfb, - 0x4d, 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, 0xb1, 0x28, 0xfe, 0xa8, 0xf4, 0x1d, 0x81, 0x8e, 0xee, 0xbc, 0xa8, 0xd3, 0xe5, 0xee, 0x03, 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, 0xbc, 0xc2, 0xfd, 0xa5, 0x22, 0x17, 0xfb, 0xce, 0x19, - 0xdd, 0x99, 0x59, 0xf7, 0xaa, 0xc2, 0xd5, 0x82, 0x5c, 0x1d, 0xd8, 0x5a, 0x76, 0x71, 0xb8, 0x61, 0x11, 0x05, 0x08, - 0xc4, 0xf4, 0x4a, 0xad, 0xfd, 0x11, 0x0d, 0x42, 0x3e, 0x18, 0xf8, 0x05, 0x06, 0xab, 0x02, 0x85, 0x0f, 0x14, 0xc9, - 0x5f, 0x7b, 0x02, 0x76, 0xf1, 0x0c, 0xd0, 0xad, 0xd8, 0xac, 0x18, 0x21, 0x42, 0x26, 0xcb, 0x59, 0x4d, 0x67, 0x90, - 0x4f, 0x7d, 0xf1, 0x8d, 0xad, 0x3a, 0x9d, 0xb7, 0x35, 0x55, 0x4e, 0x1d, 0x0a, 0xdd, 0xdd, 0xd4, 0x9d, 0x5b, 0x17, - 0x79, 0xea, 0x10, 0x72, 0xa5, 0x62, 0x25, 0xa6, 0xa1, 0xe6, 0x49, 0x9a, 0x51, 0x7f, 0xb1, 0xf7, 0x7b, 0x8d, 0xc2, - 0x29, 0x7f, 0x3a, 0x06, 0x55, 0xb8, 0xaa, 0x21, 0x8e, 0xa5, 0x2a, 0x1e, 0xd9, 0x20, 0xd0, 0xbc, 0xba, 0x55, 0x49, - 0x13, 0x32, 0xb9, 0x11, 0x3e, 0x35, 0x29, 0xe5, 0x69, 0xda, 0xa4, 0x95, 0x22, 0x75, 0xf0, 0x41, 0x9d, 0x6a, 0x3c, - 0x37, 0xab, 0x17, 0x00, 0x66, 0x9c, 0x5f, 0xf1, 0x4b, 0xc5, 0x65, 0xd4, 0x56, 0x66, 0xd2, 0xfe, 0xe4, 0x68, 0x6c, - 0xd4, 0xe5, 0xb4, 0x51, 0x46, 0x58, 0x29, 0xcd, 0x49, 0xb1, 0x1c, 0xcf, 0x3f, 0x60, 0xb0, 0xe6, 0x09, 0xec, 0x60, - 0xa2, 0x52, 0xde, 0x47, 0x40, 0x7c, 0x9d, 0xa4, 0x77, 0x09, 0xa4, 0x48, 0xff, 0xd2, 0x25, 0x77, 0x19, 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, 0xbe, 0x08, 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, 0xac, 0x3c, 0xe8, 0xff, 0x3a, 0x13, 0x96, 0xda, 0x4f, 0x4f, 0x07, 0x50, 0xc1, 0xfb, 0x8a, 0xb7, 0x11, 0xf1, - 0x7d, 0xe2, 0x67, 0xf1, 0x60, 0xf3, 0x6c, 0x03, 0xd6, 0xba, 0x27, 0xb9, 0xb1, 0xae, 0x12, 0x36, 0x10, 0xf0, 0x35, - 0x8a, 0xda, 0xf3, 0xda, 0xed, 0x1e, 0xfc, 0xd5, 0xbf, 0x08, 0x19, 0x30, 0x71, 0xfa, 0x3e, 0x73, 0xb2, 0x46, 0x17, - 0x99, 0x4c, 0x1f, 0x3a, 0xe9, 0x1b, 0x9d, 0xee, 0x3b, 0xe1, 0x1f, 0x15, 0xb3, 0xf8, 0x70, 0x4b, 0x5f, 0x69, 0x52, - 0xdc, 0x01, 0x2b, 0x9b, 0x47, 0x05, 0xa1, 0xce, 0x45, 0xf4, 0x95, 0x29, 0xdf, 0x12, 0x6a, 0xf6, 0x8d, 0x25, 0xa5, - 0x74, 0xaf, 0xa1, 0x37, 0x69, 0xad, 0xdf, 0x46, 0x09, 0xc6, 0x44, 0xc7, 0x93, 0x97, 0xf1, 0x58, 0x79, 0x1f, 0x8f, - 0x1b, 0xa9, 0x90, 0x07, 0x20, 0x02, 0x15, 0xe3, 0x4f, 0x57, 0x9e, 0x9c, 0xf4, 0xc2, 0x78, 0x15, 0x4a, 0x41, 0x61, - 0x40, 0x57, 0x20, 0x05, 0x3c, 0x6a, 0x4f, 0x74, 0x16, 0x76, 0x09, 0xf7, 0xe8, 0x26, 0x60, 0xac, 0xcf, 0x3f, 0x02, - 0x9a, 0xbb, 0x70, 0x87, 0x17, 0x03, 0xd4, 0xa6, 0x5e, 0xdd, 0x7d, 0x5c, 0xab, 0x73, 0x38, 0x04, 0x07, 0xab, 0x41, - 0x04, 0xa7, 0xf3, 0xa9, 0xa3, 0x59, 0x16, 0xa0, 0x72, 0xb2, 0xdc, 0xc8, 0x9b, 0x47, 0x8b, 0x5e, 0xdd, 0xf7, 0x96, - 0x69, 0x59, 0xd5, 0x41, 0xc6, 0xb2, 0xb0, 0x02, 0x5c, 0x1d, 0x5a, 0x3f, 0x08, 0x97, 0x85, 0xf3, 0x07, 0x42, 0x10, - 0xbb, 0x57, 0xdb, 0x92, 0xe7, 0x6a, 0x0e, 0x3f, 0x7b, 0xce, 0xd6, 0x5c, 0xa2, 0x4e, 0x3a, 0x13, 0x01, 0x88, 0x3d, - 0x35, 0xab, 0xe8, 0x1a, 0x48, 0xea, 0x34, 0xab, 0xe8, 0x9a, 0x9a, 0x6d, 0x8c, 0x03, 0xf9, 0x68, 0x95, 0x02, 0xf6, - 0xdd, 0x74, 0x1c, 0xac, 0x9e, 0xc5, 0xf2, 0x3a, 0x74, 0xf7, 0x6c, 0xa3, 0x7c, 0x06, 0x75, 0xab, 0x8d, 0x31, 0xb1, - 0xdd, 0x7c, 0x39, 0xd7, 0x6f, 0x07, 0x4b, 0xdf, 0x0e, 0x9a, 0x73, 0xca, 0xbe, 0xd3, 0x65, 0xaf, 0xec, 0xb2, 0xa9, - 0xe7, 0x8e, 0x8a, 0x56, 0x63, 0x40, 0x6f, 0x60, 0xc1, 0xfa, 0x5c, 0xa4, 0xd9, 0xaa, 0x54, 0x25, 0xe0, 0x85, 0xb1, - 0x62, 0x77, 0x7e, 0x23, 0x33, 0x24, 0x61, 0x1e, 0x67, 0xe2, 0x9a, 0xee, 0xb5, 0x30, 0x39, 0x8e, 0x45, 0x32, 0x25, - 0x74, 0x4a, 0x77, 0xb6, 0xa1, 0x73, 0x15, 0x46, 0x11, 0xad, 0x95, 0x54, 0x1a, 0x09, 0x4c, 0xcd, 0x00, 0x25, 0x73, - 0x05, 0x4e, 0xe9, 0x72, 0xff, 0x3b, 0x12, 0xe3, 0xcc, 0x17, 0x25, 0x33, 0xa0, 0x5b, 0x7e, 0x5d, 0xac, 0x5b, 0x29, - 0x32, 0xc2, 0xbc, 0x39, 0x6e, 0xaf, 0xeb, 0x43, 0x20, 0x57, 0xcb, 0x1e, 0x45, 0xe3, 0xa0, 0xd0, 0xe1, 0x52, 0x25, - 0xc0, 0xbe, 0x48, 0xfc, 0x8c, 0xb0, 0xa5, 0x3d, 0x90, 0xdb, 0xa3, 0x33, 0x61, 0xce, 0x39, 0x29, 0xcb, 0xce, 0xa5, - 0x19, 0x5c, 0x4e, 0x5c, 0x09, 0x2e, 0xd2, 0xdb, 0xf6, 0x34, 0x69, 0x69, 0xfb, 0xd8, 0x70, 0x8e, 0x86, 0xb6, 0x41, - 0x77, 0xec, 0x0f, 0xcd, 0xc5, 0x22, 0xb6, 0x2e, 0x16, 0xc3, 0xce, 0xec, 0x47, 0x8b, 0x05, 0xc8, 0x01, 0xe0, 0xa8, - 0xdb, 0xf0, 0x31, 0x5b, 0x02, 0xa7, 0xd5, 0x34, 0x9b, 0x7a, 0x1b, 0x5e, 0x3d, 0x53, 0x3d, 0xbd, 0xe4, 0xf9, 0x33, - 0x61, 0xc6, 0x62, 0xc3, 0xf3, 0x67, 0xd6, 0x91, 0x53, 0x3d, 0x13, 0x4a, 0xb4, 0x2e, 0xa0, 0x19, 0x78, 0x4d, 0x01, - 0x23, 0x96, 0x4c, 0xa6, 0x54, 0x91, 0xc7, 0xbd, 0xe9, 0x46, 0x0d, 0x5e, 0x50, 0x38, 0x04, 0x52, 0x3a, 0xfd, 0xe2, - 0x39, 0xd3, 0xef, 0x5d, 0x3c, 0xef, 0x90, 0xb5, 0x0d, 0xd3, 0xe5, 0x66, 0x98, 0x0c, 0x4a, 0xff, 0x99, 0x99, 0x18, - 0x17, 0xd6, 0x24, 0x01, 0xc4, 0xbf, 0xb1, 0xdf, 0x21, 0x85, 0x9b, 0xf7, 0x97, 0xc3, 0xf8, 0x91, 0xf7, 0x63, 0x64, - 0x4f, 0xd2, 0x0c, 0xb1, 0x66, 0x52, 0x21, 0x77, 0x5f, 0xad, 0x7f, 0x4c, 0xec, 0x26, 0x7b, 0x60, 0x01, 0x88, 0xad, - 0x69, 0xab, 0x5b, 0xde, 0xef, 0x7b, 0xa6, 0x08, 0xf0, 0x83, 0xf2, 0x8f, 0xee, 0x0c, 0xc9, 0xa0, 0xec, 0xba, 0x21, - 0xc4, 0x83, 0xb2, 0x69, 0xda, 0xeb, 0x6d, 0xef, 0xcc, 0x63, 0x75, 0x9d, 0x76, 0x16, 0x57, 0x8b, 0x0c, 0xd2, 0xea, - 0x43, 0x76, 0x9c, 0xd9, 0x67, 0x47, 0x4b, 0xa5, 0xfb, 0x7d, 0x88, 0x88, 0x3b, 0xca, 0xda, 0x7e, 0xbb, 0x05, 0xd7, - 0x70, 0x34, 0x08, 0x5d, 0xd9, 0xdb, 0x65, 0xb4, 0x71, 0x21, 0x8e, 0x7b, 0xa6, 0xf3, 0x05, 0x5f, 0x1e, 0xa5, 0x9d, - 0x07, 0xa7, 0x7a, 0xa2, 0xcf, 0x4d, 0x77, 0x95, 0xc9, 0xb5, 0x0e, 0xab, 0x31, 0xa8, 0xcd, 0xc2, 0x16, 0xee, 0xc2, - 0x36, 0x3a, 0x68, 0xed, 0xcb, 0x82, 0x7f, 0xca, 0x00, 0x7c, 0xe9, 0xd9, 0xb2, 0xed, 0x35, 0x69, 0xf5, 0x46, 0x46, - 0x21, 0xb6, 0xb4, 0xbd, 0xfa, 0x74, 0x94, 0x8f, 0x9b, 0x13, 0x8a, 0x0b, 0x39, 0xca, 0x8f, 0x5e, 0x43, 0xd4, 0xb5, - 0xae, 0xe3, 0x62, 0xd1, 0xe1, 0xc6, 0x55, 0xb7, 0xdd, 0xb8, 0x7e, 0x40, 0xbc, 0x35, 0xda, 0xa4, 0x50, 0x2b, 0x63, - 0x47, 0xf0, 0xb2, 0x7c, 0x38, 0x64, 0x62, 0x38, 0x94, 0x90, 0xa9, 0x8f, 0xdd, 0x1b, 0x9a, 0xf6, 0xf9, 0x69, 0xeb, - 0x47, 0x2c, 0x35, 0x8e, 0x62, 0xc3, 0x3b, 0x7d, 0xe7, 0xb1, 0x35, 0xae, 0xe4, 0xcb, 0x60, 0xb6, 0x2b, 0xa8, 0xb6, - 0xc6, 0x1b, 0xf6, 0x72, 0xfe, 0x7d, 0x25, 0x95, 0xfc, 0xed, 0xcf, 0x70, 0x0d, 0x6f, 0x6d, 0xe9, 0xa0, 0xa9, 0x66, - 0x39, 0xcb, 0xf5, 0xbd, 0xe0, 0xf8, 0xe3, 0xee, 0x15, 0xc1, 0xe0, 0xf7, 0x74, 0x14, 0xe4, 0x62, 0xa9, 0xd6, 0x80, - 0x82, 0x74, 0x64, 0xc7, 0x54, 0x16, 0x18, 0x06, 0xf0, 0x86, 0x0c, 0x90, 0xc7, 0x14, 0xee, 0x86, 0x0a, 0x2f, 0xfc, - 0xa5, 0x22, 0xbb, 0x04, 0xb6, 0x35, 0xe3, 0x63, 0x86, 0x3b, 0x08, 0xf9, 0x47, 0xb0, 0x3b, 0xb6, 0x62, 0xb7, 0x6c, - 0xc1, 0x90, 0x6c, 0x1c, 0x87, 0x31, 0xe6, 0xe3, 0x49, 0x7c, 0x25, 0x26, 0xf1, 0x80, 0x47, 0xe8, 0x18, 0xb1, 0xe6, - 0xf5, 0x2c, 0x96, 0x03, 0xc8, 0xee, 0xb8, 0xd2, 0x01, 0x21, 0x34, 0x36, 0xb4, 0xe4, 0x4d, 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, 0xdd, 0x45, 0x88, 0xf4, 0xb6, 0xe0, 0x77, 0x96, 0xa7, 0x0b, 0xbb, 0xe7, 0xd7, - 0x7c, 0xcc, 0xce, 0x7f, 0xf0, 0x20, 0x72, 0xf6, 0xfc, 0x23, 0xa0, 0x21, 0xde, 0xf3, 0xdb, 0xd4, 0xab, 0xd8, 0x2d, - 0x51, 0x10, 0xde, 0x82, 0x33, 0xd0, 0x3d, 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, 0xff, 0xc1, 0xdb, 0x51, 0xb9, 0xf0, 0x9f, 0xd7, 0x59, 0xf2, 0xce, 0x67, 0xd7, 0x03, 0xbe, 0x00, 0xbc, 0x25, - 0x74, 0xe0, 0xba, 0xf7, 0x99, 0xc4, 0x6b, 0xbb, 0xd6, 0xd7, 0x08, 0x24, 0xf2, 0x05, 0x60, 0xc4, 0xc4, 0xfc, 0xbe, - 0x86, 0x08, 0x8c, 0x04, 0x7c, 0x5b, 0xb5, 0x47, 0xfc, 0x96, 0x1b, 0xc0, 0xaf, 0xcc, 0x67, 0x0f, 0x3c, 0xd4, 0x3f, - 0x13, 0x9f, 0xdd, 0xf0, 0xf7, 0xfc, 0x85, 0x27, 0x25, 0xe9, 0x72, 0xf6, 0x7e, 0x0e, 0xd7, 0x43, 0x29, 0x4f, 0x87, - 0xf4, 0xb3, 0x31, 0x18, 0x40, 0x28, 0x64, 0xde, 0x78, 0xc0, 0x9a, 0x14, 0xe2, 0x5f, 0xc0, 0xb7, 0xa3, 0x84, 0xcd, - 0x1b, 0x6f, 0xeb, 0x6b, 0x79, 0xf3, 0xc6, 0x7b, 0xf0, 0x29, 0x0a, 0xb0, 0x0a, 0x4a, 0x59, 0x60, 0x15, 0x84, 0x8d, - 0x36, 0xc2, 0x18, 0xb8, 0x7a, 0xd7, 0x18, 0xea, 0x7a, 0x8e, 0xd8, 0xb6, 0xd2, 0x77, 0xe1, 0x3b, 0xc8, 0x80, 0x0f, - 0xde, 0x14, 0x25, 0xd1, 0xe7, 0xd4, 0x14, 0x49, 0xeb, 0x9e, 0xfb, 0xad, 0x75, 0x47, 0x6b, 0x4a, 0x7d, 0xe4, 0x6a, - 0x7c, 0x38, 0xd4, 0x2f, 0x84, 0x16, 0x09, 0xa6, 0xa0, 0x71, 0x0d, 0xda, 0x02, 0x04, 0x7d, 0x1e, 0x20, 0x6b, 0x49, - 0xb1, 0xe0, 0xdb, 0x5f, 0x21, 0x06, 0xaf, 0x4c, 0xef, 0x5c, 0xae, 0x32, 0x12, 0xb6, 0x17, 0x7e, 0x39, 0xac, 0xfd, - 0x89, 0x53, 0x0b, 0x4b, 0xab, 0x39, 0xa8, 0x9f, 0xd9, 0x72, 0x9c, 0xaa, 0xda, 0xbf, 0x25, 0x49, 0xb5, 0xab, 0xb4, - 0x9c, 0xde, 0xdb, 0x37, 0x5d, 0x26, 0xd8, 0xd8, 0x0f, 0xa8, 0x3a, 0xb2, 0x1a, 0x76, 0x5f, 0xa8, 0x2f, 0x7a, 0x4a, - 0x26, 0x34, 0x1f, 0x55, 0x34, 0xcf, 0xee, 0x37, 0x3b, 0xea, 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, 0x17, 0xe3, 0x69, 0x4d, 0x2c, 0xa9, 0x5d, 0x81, 0x31, 0x7a, 0x5c, 0x15, 0xb5, 0x4f, 0xfd, 0x02, 0x42, 0x91, - 0x6a, 0xcd, 0x1c, 0x6b, 0xdc, 0x18, 0x11, 0x77, 0x58, 0xb9, 0x76, 0x6a, 0xaf, 0x03, 0xb0, 0xbc, 0x1a, 0x17, 0x84, - 0x4d, 0x72, 0xec, 0x5c, 0xc0, 0x6a, 0x34, 0xa4, 0xda, 0x0d, 0xb7, 0x5e, 0x76, 0x7e, 0xf3, 0x38, 0xb1, 0xb5, 0x11, - 0x6e, 0x29, 0xa0, 0x8c, 0xf2, 0x1b, 0xcb, 0x09, 0xbb, 0x53, 0xbd, 0x23, 0x55, 0x3b, 0xe2, 0xc4, 0x05, 0x2c, 0x37, - 0x3c, 0xb5, 0xfa, 0x26, 0x06, 0x27, 0x42, 0xd5, 0x4a, 0xc7, 0x6b, 0x3f, 0xe2, 0x7e, 0x75, 0x5f, 0xf7, 0x4a, 0xf0, - 0x93, 0x90, 0xd7, 0x6f, 0x79, 0x07, 0x80, 0x15, 0x1f, 0xf2, 0x62, 0x5a, 0x38, 0x5a, 0x97, 0x41, 0x19, 0x20, 0x42, - 0x33, 0x00, 0x3a, 0xb9, 0x3a, 0x88, 0xd2, 0xc0, 0x15, 0x77, 0x88, 0xf0, 0xd3, 0xe8, 0x59, 0xfe, 0x22, 0x7c, 0x56, - 0x4d, 0xc3, 0x8b, 0x3c, 0x88, 0x2e, 0xaa, 0x20, 0x7a, 0x56, 0x5d, 0x85, 0xcf, 0xf2, 0x69, 0x74, 0x91, 0x07, 0xe1, - 0x45, 0xd5, 0xd8, 0x77, 0xed, 0xee, 0x9e, 0x90, 0xb7, 0x5d, 0xfd, 0x91, 0x73, 0x65, 0x4f, 0x99, 0x9e, 0x9f, 0xd7, - 0x7a, 0xa5, 0x76, 0x9b, 0xeb, 0x35, 0x6a, 0xa6, 0x3e, 0xca, 0xfe, 0x66, 0x1b, 0x0b, 0x8f, 0xe6, 0x10, 0xfa, 0x8c, - 0xb4, 0x98, 0x7b, 0x9c, 0xeb, 0xcd, 0x9e, 0x14, 0x06, 0x46, 0x4c, 0x2a, 0x19, 0x39, 0xbd, 0xc0, 0x45, 0xa8, 0x42, - 0x0c, 0x6b, 0xe9, 0x6a, 0x9f, 0x75, 0xe9, 0x0d, 0xd4, 0x35, 0xc5, 0xbe, 0x86, 0x0c, 0xbc, 0x68, 0x7a, 0x19, 0x8c, - 0x01, 0x39, 0x02, 0xef, 0xf8, 0x6c, 0x09, 0x07, 0xe6, 0x1a, 0xa0, 0x6f, 0x1e, 0xf5, 0x75, 0xb9, 0xe3, 0x6b, 0xd5, - 0x37, 0xd3, 0xf5, 0x48, 0x29, 0x3f, 0x56, 0xfc, 0xee, 0xe2, 0x39, 0xbb, 0xe5, 0x1a, 0x15, 0xe5, 0x17, 0xbd, 0x58, - 0xef, 0x81, 0xab, 0xee, 0x17, 0xb8, 0xcd, 0xe2, 0xb1, 0x2b, 0x0f, 0x58, 0xb6, 0x65, 0x0f, 0xec, 0x86, 0xbd, 0x67, - 0x4f, 0xd8, 0x5b, 0xf6, 0x8e, 0xfd, 0x84, 0xaa, 0x0d, 0x25, 0xe4, 0xf9, 0x0b, 0x7e, 0x2b, 0x4d, 0x8f, 0x12, 0x95, - 0xec, 0xc1, 0x36, 0xd3, 0x0c, 0x37, 0xec, 0x3d, 0x5f, 0x0c, 0x57, 0xec, 0x2d, 0x64, 0x43, 0x99, 0x78, 0xb0, 0x62, - 0x3f, 0x71, 0x05, 0x62, 0xa6, 0xcf, 0xc2, 0xd2, 0x12, 0x15, 0x4d, 0x99, 0x28, 0x43, 0xbf, 0xe5, 0xf8, 0x22, 0xfb, - 0x09, 0x8b, 0x90, 0x9f, 0x19, 0xae, 0xd8, 0x03, 0x5f, 0x0c, 0x56, 0xec, 0xbd, 0x36, 0x10, 0x0d, 0x36, 0x6e, 0x69, - 0x84, 0x64, 0xa5, 0xcb, 0x92, 0xd2, 0xf4, 0xd6, 0xbe, 0x06, 0x6e, 0xd8, 0x0d, 0xd6, 0xee, 0x09, 0x16, 0x8d, 0x02, - 0xff, 0x60, 0xc5, 0xde, 0x71, 0x09, 0xa0, 0xe6, 0x96, 0x27, 0xbd, 0x42, 0x75, 0x81, 0x74, 0x3f, 0x78, 0xc2, 0xe9, - 0x45, 0xf6, 0x0e, 0xcb, 0xa0, 0xaf, 0x0c, 0x57, 0x6c, 0x8b, 0xb5, 0xbb, 0x31, 0x96, 0x2d, 0xab, 0x7a, 0x12, 0x11, - 0x18, 0x05, 0x95, 0xd2, 0xf2, 0x6f, 0xc4, 0xb2, 0xa9, 0x9b, 0x06, 0xb5, 0xa1, 0x3f, 0x1f, 0x8c, 0xfe, 0xe2, 0xeb, - 0x77, 0x3f, 0x78, 0xa5, 0xbe, 0xf6, 0xfe, 0xe2, 0xb8, 0x56, 0x96, 0xe8, 0x5a, 0xf9, 0x2b, 0x2f, 0x67, 0xbf, 0xcc, - 0x27, 0xba, 0x96, 0xb4, 0xc3, 0x90, 0xaf, 0xe9, 0xec, 0x97, 0x0e, 0x67, 0xcb, 0x5f, 0x7d, 0xbf, 0x31, 0x5d, 0xac, - 0x3e, 0xab, 0x7b, 0xf7, 0x61, 0xb0, 0x69, 0x9c, 0x7a, 0xef, 0x4e, 0xd7, 0x1b, 0x9b, 0x59, 0x6b, 0xcf, 0xcc, 0xff, - 0xe1, 0x4a, 0x6f, 0x71, 0xe8, 0x6e, 0xf8, 0x76, 0xb8, 0xb1, 0x47, 0x41, 0x7e, 0x5f, 0x2a, 0x8d, 0xb3, 0x9a, 0xbf, - 0xf4, 0x3a, 0xa5, 0x58, 0x40, 0x34, 0xfa, 0x64, 0x24, 0xa1, 0x4b, 0x66, 0xe2, 0x19, 0xe2, 0x8b, 0x0c, 0x90, 0xb9, - 0x40, 0x34, 0xbb, 0xe7, 0xe3, 0xc9, 0xfd, 0x55, 0x3c, 0xb9, 0x1f, 0xf0, 0x4f, 0xa6, 0x05, 0xed, 0xc5, 0x76, 0xef, - 0xb3, 0x5f, 0x79, 0x61, 0x2f, 0xc7, 0x5f, 0x7c, 0xf6, 0x45, 0xb8, 0x2b, 0xf4, 0x17, 0x9f, 0xbd, 0x13, 0xfc, 0xd7, - 0x91, 0x26, 0xca, 0x60, 0xef, 0x6a, 0xfe, 0xeb, 0x08, 0x19, 0x3f, 0xd8, 0x67, 0xc1, 0xbf, 0x80, 0xef, 0x77, 0x95, - 0xa0, 0x55, 0xfc, 0x73, 0xad, 0x7e, 0xbe, 0x97, 0x71, 0x39, 0xf0, 0x26, 0xb4, 0x82, 0xde, 0xbc, 0xad, 0xe5, 0x4f, - 0xe2, 0xe1, 0x48, 0xd5, 0x53, 0xc3, 0x3f, 0x8b, 0xc5, 0x2c, 0xea, 0xa3, 0x74, 0x2a, 0x6f, 0x72, 0xcd, 0x33, 0x69, - 0x5d, 0xbe, 0x87, 0x50, 0xe0, 0x6b, 0x1b, 0xa2, 0x60, 0xc7, 0x71, 0x23, 0xb8, 0x66, 0xef, 0x84, 0xcf, 0xb2, 0xe9, - 0x96, 0xdf, 0xf0, 0x27, 0xfc, 0x1d, 0xdf, 0x05, 0x0f, 0xfc, 0x3d, 0x7f, 0xcb, 0x7f, 0xe2, 0x3b, 0xb6, 0x94, 0x68, - 0xa7, 0xf5, 0xf6, 0x32, 0xd8, 0xb2, 0x7a, 0x77, 0x19, 0x3c, 0xb0, 0x7a, 0xfb, 0x3c, 0xb8, 0x61, 0xf5, 0xee, 0x79, - 0xf0, 0x9e, 0x6d, 0x2f, 0x83, 0x27, 0x6c, 0x77, 0x19, 0xbc, 0x65, 0xdb, 0xe7, 0xc1, 0x3b, 0xb6, 0x7b, 0x1e, 0xfc, - 0x24, 0x31, 0x1e, 0xde, 0x09, 0xc9, 0x71, 0xf2, 0xae, 0x66, 0x86, 0x4f, 0x37, 0xf8, 0x2c, 0xac, 0x5f, 0x54, 0xc7, - 0xe0, 0x73, 0xcd, 0x74, 0x8b, 0x03, 0x21, 0x98, 0x6e, 0x6f, 0x70, 0x4b, 0x4f, 0x4c, 0xab, 0x82, 0x54, 0xb0, 0xae, - 0x76, 0x06, 0x8b, 0xba, 0x69, 0x9d, 0xc9, 0x8e, 0x5f, 0x62, 0xdc, 0xe1, 0x97, 0xb8, 0x60, 0xcb, 0xa6, 0xd3, 0x49, - 0xe7, 0xf4, 0x49, 0xa0, 0x37, 0x7f, 0xbd, 0xeb, 0x57, 0xd2, 0x77, 0xa6, 0x68, 0x78, 0xae, 0xb4, 0xc6, 0xad, 0x9d, - 0x3e, 0xb4, 0x76, 0x7a, 0x26, 0x55, 0x68, 0x11, 0x8b, 0xca, 0xa2, 0xaa, 0x90, 0x49, 0x3c, 0xc8, 0xb4, 0x3e, 0x2d, - 0x61, 0xa4, 0xc8, 0x04, 0x34, 0xfa, 0x82, 0x8e, 0x81, 0x9c, 0x2c, 0x0a, 0x6c, 0xc9, 0x37, 0x83, 0x84, 0xad, 0x79, - 0x3c, 0x1d, 0x26, 0xc1, 0x92, 0xdd, 0xf1, 0x61, 0xb7, 0x40, 0xb0, 0x52, 0x01, 0x4c, 0xfa, 0xe2, 0xd4, 0xde, 0xd7, - 0x79, 0x6f, 0x95, 0xc6, 0x71, 0x26, 0x50, 0xd9, 0x56, 0xe9, 0x0d, 0x7e, 0xeb, 0xec, 0xe7, 0x6b, 0xb5, 0xbf, 0x83, - 0xa4, 0xf0, 0x2b, 0x30, 0xec, 0x10, 0xe1, 0x1d, 0x54, 0x18, 0x79, 0x96, 0xcc, 0xa2, 0xaf, 0xec, 0x2d, 0x7d, 0x6b, - 0xb6, 0xe9, 0xff, 0xb4, 0x08, 0xda, 0xc7, 0x65, 0xe7, 0x7f, 0x32, 0xaf, 0xfe, 0xd6, 0xf1, 0xea, 0xc6, 0x9f, 0x3c, - 0xf0, 0x4f, 0x18, 0x96, 0x80, 0x89, 0x6c, 0xc7, 0x3f, 0x8d, 0xb6, 0x8d, 0x53, 0x9e, 0xdc, 0xc7, 0xff, 0xaf, 0x14, - 0x68, 0xef, 0xe4, 0x95, 0xbd, 0x23, 0x6e, 0x79, 0xc7, 0x3e, 0xbe, 0xb4, 0x36, 0x44, 0x03, 0x4d, 0xf2, 0x89, 0xbb, - 0xd1, 0xd0, 0xb0, 0x21, 0xfe, 0xc2, 0xab, 0xd9, 0xa7, 0xf9, 0x64, 0xcb, 0x8f, 0xb7, 0xc3, 0x4f, 0x1d, 0xdb, 0xe1, - 0x2f, 0xfe, 0x60, 0xd9, 0x7c, 0xad, 0x57, 0x3b, 0xb7, 0x71, 0xa7, 0xd2, 0x3b, 0x7e, 0xbc, 0x89, 0x0f, 0xff, 0xe3, - 0x4a, 0xef, 0xbe, 0xb9, 0xd2, 0x76, 0x95, 0xbb, 0x3b, 0xdf, 0x74, 0x7c, 0x23, 0x6b, 0x8d, 0x71, 0x66, 0x46, 0xb3, + 0x32, 0xdf, 0x54, 0xe5, 0x57, 0x77, 0xa4, 0xda, 0x0f, 0x86, 0xd7, 0x13, 0x71, 0x49, 0x97, 0x24, 0xf5, 0x54, 0x42, + 0x49, 0x08, 0x76, 0xed, 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, 0xcb, + 0x79, 0x58, 0x1b, 0x26, 0xb9, 0x51, 0x16, 0xee, 0x8b, 0x6d, 0xad, 0x96, 0xa7, 0xe3, 0x30, 0x02, 0x33, 0x82, 0x02, + 0x64, 0x5d, 0xb7, 0x11, 0x31, 0xcc, 0xe5, 0x32, 0x21, 0x9f, 0x10, 0x90, 0x45, 0xa9, 0x71, 0x3e, 0x6e, 0x81, 0x4a, + 0x04, 0x83, 0xd3, 0xd0, 0x5a, 0x75, 0x93, 0xbf, 0xaa, 0x6c, 0x6c, 0x05, 0xe4, 0x90, 0x64, 0xb2, 0x58, 0x8d, 0xee, + 0xc4, 0xb2, 0x28, 0xc5, 0xcf, 0x58, 0x0f, 0xd7, 0x6c, 0xe1, 0x3e, 0x03, 0x42, 0xfb, 0x89, 0xd2, 0xde, 0x44, 0x9a, + 0xa0, 0x7b, 0xc5, 0xd6, 0x00, 0x32, 0x80, 0xa2, 0xae, 0x76, 0xeb, 0x73, 0x7e, 0x8e, 0xa4, 0x19, 0x0e, 0xa3, 0xdb, + 0xa7, 0xab, 0x60, 0x35, 0xb8, 0x46, 0xad, 0xf4, 0x35, 0x8b, 0x5b, 0x18, 0x54, 0x07, 0xb3, 0x84, 0x83, 0x9a, 0x59, + 0x6b, 0x23, 0x10, 0x4c, 0xf6, 0x50, 0x90, 0x33, 0x57, 0xb0, 0x0f, 0x0a, 0xd6, 0x92, 0xd7, 0xc1, 0xe1, 0xd6, 0xbe, + 0xac, 0x14, 0x57, 0xcf, 0xae, 0x92, 0xd6, 0x85, 0xa5, 0xbc, 0x7a, 0xd6, 0x80, 0xc1, 0xe5, 0x04, 0x9b, 0x2a, 0xf7, + 0x27, 0x5b, 0x00, 0xdd, 0x0a, 0x29, 0xe2, 0x45, 0x29, 0x6c, 0x5b, 0xf9, 0xcc, 0x09, 0x1b, 0x6c, 0xd9, 0x03, 0xdc, + 0x2b, 0x83, 0x92, 0xc1, 0x85, 0x18, 0xb7, 0x9b, 0x7d, 0x80, 0x2b, 0x18, 0x0a, 0x63, 0x1b, 0xfe, 0x3a, 0xf3, 0x22, + 0x25, 0xe0, 0x66, 0x88, 0xf2, 0xb5, 0x85, 0x93, 0x49, 0x4f, 0xae, 0x25, 0x8b, 0x01, 0x0b, 0x1a, 0x7c, 0x47, 0xad, + 0xbf, 0x33, 0xf9, 0x37, 0x9e, 0x1e, 0xfa, 0xc1, 0xe7, 0xcc, 0x5b, 0xfa, 0xec, 0x75, 0x2e, 0xa3, 0x35, 0x49, 0x94, + 0x57, 0x0f, 0x97, 0x20, 0x37, 0x2c, 0x47, 0x0f, 0x6c, 0x09, 0xe2, 0xc4, 0x72, 0x94, 0x50, 0x46, 0x57, 0xb8, 0x57, + 0x99, 0x2d, 0x13, 0x81, 0x14, 0x07, 0x96, 0x52, 0xee, 0x2d, 0x36, 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, 0xa1, + 0x61, 0x7f, 0xf5, 0x42, 0xcb, 0xfe, 0xb0, 0xd2, 0x9a, 0x86, 0x35, 0x5f, 0xc1, 0xb4, 0x98, 0xb8, 0x7d, 0xb9, 0xb6, + 0xab, 0xe2, 0xb3, 0xb5, 0x3a, 0xbb, 0xa9, 0x21, 0x09, 0xfb, 0x8a, 0xac, 0x02, 0x1c, 0xac, 0x8a, 0xb8, 0x67, 0x59, + 0x1e, 0xc2, 0xe8, 0xcf, 0x6d, 0x5a, 0x0a, 0x0b, 0x55, 0xd2, 0x3f, 0x34, 0xa5, 0x40, 0x2a, 0x13, 0x9d, 0x68, 0x21, + 0xb8, 0x02, 0x83, 0xc0, 0xbd, 0xc8, 0x6b, 0x00, 0x8c, 0x01, 0x97, 0x02, 0x65, 0xd9, 0x96, 0x10, 0x52, 0xdd, 0xcf, + 0x40, 0x6d, 0x27, 0xee, 0xd3, 0x88, 0xac, 0x85, 0xe8, 0xab, 0x60, 0xcc, 0x9c, 0xd7, 0xd2, 0x2d, 0x36, 0x5d, 0x6f, + 0xd7, 0xb7, 0xe8, 0x5c, 0xda, 0x72, 0xf3, 0x13, 0xb6, 0x58, 0x2b, 0x50, 0x36, 0x21, 0x69, 0xbb, 0xe2, 0x15, 0xca, + 0x26, 0xb4, 0xb4, 0x0f, 0xd4, 0xa3, 0x42, 0x75, 0xb2, 0xf5, 0x52, 0x3e, 0xb5, 0x08, 0xab, 0xc5, 0x55, 0xee, 0x07, + 0xa0, 0x9b, 0x4a, 0xab, 0x17, 0x75, 0x8d, 0xa6, 0x50, 0xab, 0x85, 0xe3, 0x46, 0x3b, 0x9b, 0x2e, 0xd3, 0x15, 0xe2, + 0xac, 0x4a, 0x3b, 0xf4, 0x0f, 0x99, 0x76, 0xbd, 0xec, 0xe8, 0x37, 0xe3, 0xea, 0x02, 0x17, 0x62, 0x03, 0x3e, 0xe7, + 0xfe, 0xf2, 0x7a, 0xcf, 0xe2, 0x1e, 0x44, 0x3c, 0x03, 0x7b, 0x52, 0xfb, 0x43, 0xf5, 0xa9, 0x2b, 0x18, 0xb2, 0x30, + 0x4a, 0xfd, 0x45, 0xca, 0x7b, 0x4f, 0x70, 0xdc, 0x3f, 0x57, 0x3d, 0xf6, 0xd7, 0x8c, 0x1f, 0xea, 0x62, 0x1b, 0x25, + 0x14, 0xd5, 0xd0, 0x5b, 0x17, 0xdb, 0x4a, 0xc4, 0xc5, 0x43, 0xde, 0x63, 0x98, 0x0c, 0x63, 0x21, 0x53, 0xe1, 0x4f, + 0x99, 0x0a, 0x1e, 0x21, 0x94, 0xb8, 0xdd, 0xf4, 0x48, 0xbb, 0x09, 0x71, 0x4a, 0xb5, 0x28, 0x65, 0x32, 0xfe, 0xad, + 0x9f, 0x40, 0x79, 0x4e, 0xd1, 0x32, 0xfd, 0xa4, 0x70, 0x99, 0xbe, 0xdd, 0x9c, 0x96, 0x9e, 0x89, 0x50, 0x67, 0x2e, + 0xb6, 0xb5, 0x4e, 0xc7, 0xd8, 0x29, 0x9d, 0xda, 0xb0, 0x77, 0xb9, 0xe2, 0xb2, 0xa2, 0xf0, 0x6f, 0x24, 0xb2, 0xea, + 0x19, 0x71, 0xfc, 0x9f, 0x59, 0xfb, 0x0c, 0xab, 0xc0, 0x2f, 0x03, 0x79, 0xbf, 0x00, 0xf8, 0xb8, 0xae, 0xcb, 0xf4, + 0x6e, 0x0b, 0xb4, 0x21, 0x34, 0xfc, 0x3d, 0x1f, 0x19, 0x30, 0xdd, 0x47, 0x38, 0x43, 0x7a, 0xa8, 0x73, 0x4e, 0x67, + 0x65, 0x3a, 0xe7, 0x2a, 0xac, 0x25, 0x38, 0xc8, 0x49, 0x53, 0xc9, 0x75, 0x09, 0x6a, 0x26, 0x70, 0xfb, 0xd0, 0x1e, + 0x11, 0x42, 0x6d, 0xca, 0x6a, 0x7a, 0x09, 0x35, 0xef, 0xe4, 0xb4, 0xa3, 0x49, 0x09, 0xae, 0x1a, 0x3a, 0x2b, 0xd7, + 0x7f, 0x1d, 0x8f, 0xbd, 0xbb, 0xac, 0x88, 0xfe, 0xe8, 0xa1, 0xbf, 0xe3, 0xee, 0x36, 0xfd, 0x02, 0xd1, 0x32, 0xd6, + 0xdf, 0x90, 0x01, 0x1d, 0x4f, 0x86, 0x77, 0xc5, 0xae, 0xc7, 0xde, 0xe5, 0x78, 0x81, 0x55, 0xd7, 0x8f, 0x3f, 0x40, + 0x42, 0xd5, 0xb5, 0x2f, 0x2c, 0x9e, 0x30, 0x4f, 0x89, 0xb6, 0x85, 0x0f, 0x61, 0xa1, 0xef, 0x72, 0xd8, 0x84, 0xa1, + 0x79, 0xd4, 0x3d, 0x4a, 0xda, 0x85, 0xbe, 0xf4, 0xb5, 0xec, 0x2b, 0xdf, 0xb9, 0x02, 0x58, 0xd9, 0x67, 0x36, 0xdc, + 0x93, 0xfe, 0x94, 0xea, 0xc3, 0xf6, 0xb7, 0x64, 0x01, 0x85, 0x16, 0xd6, 0x53, 0x39, 0x3b, 0x37, 0x25, 0x4f, 0xb3, + 0xe9, 0x61, 0x03, 0x7b, 0xd4, 0x3d, 0x7a, 0x4d, 0x05, 0x97, 0xd7, 0x66, 0xf4, 0xfe, 0x61, 0x28, 0x54, 0x47, 0x9d, + 0x3b, 0xc8, 0xa6, 0xb4, 0x2e, 0x39, 0xbf, 0x59, 0xb9, 0xa3, 0x30, 0xbf, 0x0f, 0xc1, 0x33, 0xac, 0x7b, 0x77, 0x71, + 0xde, 0xfb, 0xb3, 0x35, 0x47, 0xfe, 0x9a, 0xcd, 0x52, 0xc4, 0x22, 0x99, 0x83, 0xd5, 0x0f, 0xfd, 0x3c, 0x0e, 0xbb, + 0xa0, 0x82, 0xe3, 0xa6, 0x01, 0x1d, 0x36, 0x64, 0xd6, 0xbe, 0x44, 0xe0, 0x54, 0x23, 0x48, 0x53, 0x13, 0xd4, 0x2c, + 0x0f, 0x91, 0xd8, 0x2e, 0x65, 0xbb, 0xc0, 0xd0, 0xb6, 0x4d, 0x89, 0xf6, 0x0c, 0xde, 0x37, 0x69, 0x39, 0x51, 0xa1, + 0x59, 0xa4, 0xad, 0x92, 0xf1, 0xef, 0x44, 0x9b, 0x29, 0xd9, 0x63, 0x6b, 0xe0, 0xbd, 0x04, 0xe5, 0x64, 0x98, 0x62, + 0xf8, 0x8e, 0xaf, 0x77, 0x1e, 0x73, 0xcf, 0x39, 0x65, 0x9b, 0x94, 0x1d, 0xc1, 0x72, 0x22, 0x1b, 0xdf, 0x52, 0xbc, + 0xe1, 0xfb, 0xbb, 0x4a, 0x94, 0x00, 0x7a, 0x59, 0xf0, 0xe7, 0xd2, 0xe6, 0x0a, 0xdd, 0xee, 0xde, 0x51, 0x0a, 0xbf, + 0xe4, 0xe5, 0xf1, 0xb8, 0x4b, 0xbd, 0x10, 0x3a, 0x5f, 0xc4, 0xef, 0xc0, 0x1c, 0xc6, 0x10, 0x9b, 0x11, 0x20, 0xcc, + 0xf1, 0x01, 0x75, 0xb0, 0x7e, 0x04, 0xa0, 0x71, 0x02, 0x05, 0x18, 0x7d, 0xb5, 0x2d, 0xe8, 0x5b, 0x5e, 0x5c, 0x44, + 0x88, 0x1a, 0x05, 0x98, 0x28, 0x69, 0x16, 0xc3, 0x70, 0xa0, 0xf3, 0xfb, 0xf6, 0xae, 0x2e, 0x05, 0x0e, 0xbd, 0x63, + 0x19, 0xfe, 0xdb, 0xff, 0x58, 0x5b, 0x5a, 0x55, 0xb6, 0x5b, 0xe3, 0x34, 0xf3, 0xbf, 0xdd, 0x16, 0xfa, 0xfe, 0x4b, + 0xa1, 0x78, 0xde, 0xf1, 0xba, 0xfd, 0x05, 0xa2, 0xf7, 0x75, 0x2b, 0x57, 0xa5, 0x76, 0xc3, 0x4c, 0xf9, 0x43, 0x9a, + 0xc7, 0xc5, 0xc3, 0x28, 0x6e, 0x1d, 0x79, 0x93, 0xf4, 0x92, 0xf3, 0x2f, 0xe0, 0x6c, 0xfd, 0x05, 0xc8, 0x78, 0x5f, + 0x0a, 0xe3, 0x88, 0x49, 0x1c, 0x7c, 0x07, 0x31, 0x8a, 0xb6, 0x25, 0x6c, 0xc8, 0xed, 0xd3, 0x12, 0x34, 0x33, 0xfd, + 0x3e, 0x4a, 0x94, 0xd6, 0x7c, 0xff, 0x8b, 0x9c, 0xef, 0x2f, 0x85, 0xbc, 0x59, 0xc9, 0x0f, 0x9f, 0xac, 0x30, 0xf0, + 0x3d, 0x4e, 0xbf, 0x88, 0x1e, 0x5b, 0x95, 0x3e, 0x7c, 0x57, 0x5a, 0xfa, 0xac, 0xa2, 0xfe, 0x8e, 0x8a, 0x9a, 0x97, + 0x62, 0x44, 0xc4, 0x83, 0xa0, 0x9d, 0x6d, 0x97, 0xda, 0xb5, 0x04, 0xed, 0x82, 0x4d, 0x61, 0xff, 0x7a, 0x6c, 0xc8, + 0xab, 0x7e, 0xff, 0xe7, 0xca, 0x6b, 0xf1, 0xba, 0xeb, 0xd0, 0x94, 0x9f, 0x0a, 0x0f, 0x21, 0x80, 0xb5, 0x0c, 0x94, + 0xf1, 0x1c, 0x60, 0xd2, 0x45, 0x5e, 0xa3, 0x6c, 0x3a, 0x11, 0xf8, 0x98, 0x65, 0x37, 0x4e, 0x32, 0x0d, 0x30, 0xa3, + 0x9a, 0x62, 0xcc, 0x8a, 0x78, 0xb8, 0xf8, 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, 0xee, 0x33, 0x1c, 0x96, 0xc2, 0x31, + 0xe2, 0xff, 0x2d, 0x55, 0x3d, 0x22, 0xd0, 0xab, 0x32, 0xad, 0xa2, 0x22, 0xcf, 0x45, 0x84, 0x08, 0xd5, 0xd2, 0x39, + 0x1c, 0xfa, 0xb1, 0xdf, 0xc7, 0x81, 0x30, 0x2f, 0xfe, 0xf4, 0x58, 0x57, 0xfe, 0x54, 0xe0, 0x5a, 0x49, 0x81, 0x53, + 0x51, 0x23, 0x44, 0x08, 0xef, 0x4f, 0xe0, 0x59, 0x4d, 0x7d, 0xbf, 0xb1, 0x4c, 0x74, 0xff, 0xc8, 0x80, 0xf2, 0x07, + 0xe4, 0xeb, 0x5c, 0x8a, 0x33, 0x75, 0xf2, 0x98, 0x38, 0xe3, 0x00, 0xc4, 0x7c, 0x5d, 0xa2, 0xd1, 0xd8, 0xff, 0x80, + 0x04, 0x43, 0xf5, 0x83, 0x9d, 0x6e, 0xea, 0xfd, 0x33, 0x93, 0x38, 0x8a, 0x3e, 0x6d, 0x93, 0xa7, 0x92, 0xa5, 0xd1, + 0xc2, 0xd1, 0x7b, 0xc4, 0x30, 0x0e, 0xa7, 0xf3, 0x29, 0xc9, 0x36, 0x26, 0xab, 0x00, 0xd2, 0xc9, 0x4c, 0x1d, 0x53, + 0xea, 0x68, 0x9c, 0xeb, 0x05, 0x55, 0xe8, 0xb1, 0x2e, 0x79, 0x05, 0xd6, 0x93, 0x1f, 0xbd, 0xd2, 0x9f, 0x0a, 0x39, + 0x87, 0x8d, 0x44, 0x50, 0xf8, 0x01, 0xae, 0x06, 0x2b, 0x05, 0x0c, 0xa6, 0xbe, 0x85, 0xaf, 0x89, 0xe7, 0x28, 0x78, + 0x14, 0x76, 0x31, 0xb6, 0xe6, 0xbe, 0xf3, 0x49, 0x41, 0xb9, 0x67, 0xc5, 0x9c, 0xe7, 0xc0, 0xb9, 0x0c, 0x0a, 0x61, + 0x3a, 0x9e, 0xe5, 0xff, 0x4c, 0xf2, 0x7a, 0x62, 0x43, 0x80, 0x0c, 0xfe, 0x9c, 0x38, 0x2d, 0xdd, 0xa1, 0x3b, 0x0f, + 0x3d, 0x8b, 0x38, 0x6c, 0xf4, 0x64, 0x53, 0x16, 0xbb, 0x14, 0xf5, 0x12, 0xe6, 0x07, 0xf2, 0xf3, 0x96, 0xfc, 0x10, + 0xa2, 0x78, 0x1b, 0xfc, 0x9a, 0xb1, 0x58, 0xe0, 0x5f, 0x7f, 0xcb, 0x18, 0x4d, 0xb4, 0xe0, 0x5f, 0x59, 0x83, 0x44, + 0xc5, 0x3f, 0x65, 0x93, 0x1c, 0xb8, 0x4c, 0xd5, 0x87, 0xcf, 0x89, 0xf1, 0xd6, 0x6c, 0x78, 0xe4, 0x9b, 0x39, 0xe8, + 0xd4, 0xe7, 0xee, 0xca, 0xf6, 0x54, 0x35, 0xfe, 0x96, 0xea, 0x6a, 0xa4, 0xaa, 0x1a, 0x7f, 0x4b, 0xa9, 0x1a, 0xbf, + 0x65, 0x14, 0xbf, 0x93, 0xfb, 0x0c, 0x99, 0x93, 0x4d, 0x4c, 0xd2, 0xf9, 0x7b, 0xc3, 0x99, 0x5d, 0xf6, 0xab, 0xb7, + 0x89, 0xcc, 0x44, 0x0a, 0xb9, 0x37, 0x00, 0x35, 0x13, 0x7f, 0xae, 0x0c, 0xa7, 0xc4, 0xe5, 0xa5, 0x87, 0x2b, 0x36, + 0xad, 0x5e, 0xd2, 0x82, 0x05, 0x36, 0x2f, 0xb3, 0x3c, 0x45, 0x02, 0xdb, 0xa6, 0xcc, 0xfa, 0xa9, 0xf2, 0x00, 0x82, + 0x99, 0xd4, 0x04, 0x80, 0xb4, 0x10, 0x95, 0x42, 0xe4, 0x2f, 0x71, 0x56, 0x5f, 0xf2, 0xde, 0x36, 0x8f, 0x89, 0xb4, + 0xba, 0xd7, 0xef, 0xa7, 0x17, 0x69, 0x4e, 0x41, 0x0d, 0xa7, 0x59, 0xa7, 0x3f, 0x64, 0x41, 0x9d, 0xc8, 0x55, 0xfa, + 0x77, 0x37, 0xc8, 0xcb, 0xf8, 0xbe, 0xee, 0x7a, 0xfe, 0x44, 0xfd, 0xbd, 0xb7, 0xfe, 0xb6, 0x40, 0x70, 0x27, 0xa7, + 0x7e, 0xb2, 0x2a, 0xe5, 0x89, 0x71, 0x69, 0xef, 0xf9, 0x4d, 0x5d, 0x14, 0x59, 0x9d, 0x6e, 0x3e, 0x48, 0x3d, 0x8d, + 0xee, 0x8b, 0x03, 0x18, 0x83, 0xf7, 0x00, 0x78, 0xa6, 0x43, 0x03, 0xa4, 0xef, 0x19, 0x79, 0xb8, 0xcf, 0x2d, 0xf9, + 0x49, 0x65, 0x6d, 0x92, 0xb0, 0xa2, 0xd8, 0x0c, 0x63, 0x84, 0x92, 0x71, 0x1a, 0x3b, 0xbf, 0xdf, 0x57, 0x7f, 0xef, + 0x31, 0x8a, 0x8a, 0x8a, 0x3b, 0x45, 0xa3, 0xb2, 0xaa, 0x47, 0xdb, 0xc1, 0xf1, 0x78, 0x59, 0xd9, 0x38, 0xda, 0x7a, + 0x05, 0x1c, 0xac, 0x50, 0x29, 0x7b, 0x25, 0xc2, 0xf2, 0xc3, 0x95, 0xdf, 0xef, 0xc3, 0xbf, 0x32, 0xd2, 0xc2, 0xf3, + 0xa7, 0xf8, 0x6b, 0x51, 0x17, 0x18, 0x9e, 0x41, 0x6b, 0x34, 0x87, 0x60, 0x82, 0xbf, 0x77, 0xa0, 0x5e, 0x5a, 0x69, + 0x1f, 0x41, 0xb7, 0x02, 0x3d, 0xa8, 0x87, 0x3e, 0x4d, 0xda, 0x17, 0x12, 0x75, 0x7b, 0xab, 0xd3, 0xe8, 0x8f, 0x0a, + 0x2e, 0xa7, 0x30, 0x39, 0xdc, 0xd0, 0xa7, 0x75, 0xb8, 0xfb, 0x04, 0x4f, 0x7f, 0x06, 0xca, 0xad, 0xe3, 0x11, 0xc5, + 0x16, 0x70, 0xf3, 0x58, 0x87, 0x9f, 0x8b, 0x52, 0x46, 0xd4, 0xc7, 0xd3, 0x02, 0xb4, 0x77, 0x01, 0x3a, 0x60, 0x69, + 0x10, 0xaf, 0x90, 0x3c, 0x67, 0x23, 0x80, 0x65, 0x07, 0x96, 0xb3, 0x8c, 0x53, 0x98, 0x67, 0xf9, 0x5c, 0xad, 0xb4, + 0x8b, 0x32, 0xf1, 0x6a, 0x96, 0x81, 0xb3, 0xc0, 0x55, 0xee, 0xb3, 0x4c, 0xab, 0x9e, 0xf2, 0x04, 0x7d, 0x5e, 0xc9, + 0x09, 0xae, 0x04, 0x27, 0x1b, 0x90, 0x5f, 0x80, 0x24, 0x4d, 0x29, 0x6b, 0xca, 0xe7, 0xd7, 0x74, 0x43, 0x46, 0xcf, + 0x79, 0xcf, 0x8b, 0x86, 0xa1, 0x7f, 0xe5, 0x95, 0x10, 0xbe, 0x89, 0xdb, 0x36, 0x4a, 0x61, 0x7f, 0x11, 0x58, 0x7c, + 0xc2, 0x7e, 0xf4, 0x96, 0xfe, 0x74, 0x1c, 0x84, 0x43, 0xe4, 0x86, 0x8a, 0x39, 0xb0, 0xa7, 0x01, 0x8b, 0x4d, 0x7c, + 0xb3, 0x9d, 0xc4, 0x83, 0x81, 0xaf, 0x33, 0x16, 0xb3, 0x18, 0x68, 0x90, 0xe3, 0xc1, 0xf5, 0x5c, 0x9f, 0x10, 0xfa, + 0x61, 0x44, 0xe5, 0xa8, 0x40, 0xe7, 0x20, 0x1a, 0x2c, 0x01, 0x4f, 0xbd, 0x95, 0x0d, 0x92, 0x8c, 0x49, 0x26, 0x71, + 0xad, 0x49, 0xaa, 0xc3, 0x09, 0xad, 0x03, 0x1d, 0x57, 0x17, 0xd0, 0xf9, 0xb8, 0xee, 0x7d, 0xbc, 0x1a, 0x2e, 0xa8, + 0xf4, 0x2b, 0x31, 0xf0, 0xea, 0xe9, 0x38, 0xb8, 0xa6, 0x5b, 0xe1, 0x62, 0x1d, 0xee, 0x7e, 0x96, 0x0f, 0x1c, 0x77, + 0x54, 0xd2, 0x10, 0x18, 0xbc, 0x3d, 0x74, 0x37, 0x33, 0x34, 0xd4, 0x49, 0xfb, 0x30, 0x0e, 0xe5, 0x10, 0xab, 0x56, + 0x5c, 0x49, 0x6f, 0x04, 0xdf, 0x2e, 0x14, 0x63, 0xd9, 0xd8, 0xb5, 0xa1, 0x28, 0xfc, 0x15, 0xc0, 0x0e, 0xb5, 0xbf, + 0x52, 0xc9, 0xc7, 0xc8, 0xa8, 0xa6, 0x81, 0x8e, 0x01, 0x58, 0xb2, 0x34, 0x91, 0x54, 0x91, 0x46, 0xe2, 0x8f, 0xcc, + 0x58, 0x47, 0x4d, 0xd7, 0x17, 0x4c, 0x55, 0x8b, 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, 0x99, 0xb4, 0x7d, 0x59, + 0x91, 0x2d, 0x08, 0xa6, 0x27, 0xd1, 0x07, 0x49, 0xd0, 0xba, 0x48, 0xa4, 0x19, 0x21, 0xc0, 0x8f, 0x27, 0xe5, 0x8d, + 0xfe, 0x1c, 0x34, 0xad, 0x04, 0x2f, 0x19, 0x24, 0x8f, 0xc4, 0xcf, 0xa4, 0x60, 0x16, 0x63, 0xf9, 0x60, 0x80, 0xe5, + 0xe4, 0x4f, 0x1d, 0x93, 0xf4, 0x5f, 0x3a, 0x9d, 0xb0, 0x5f, 0x78, 0x95, 0xad, 0xe5, 0x4d, 0x73, 0xef, 0x85, 0x97, + 0xb3, 0x54, 0xc3, 0x32, 0xe8, 0xbf, 0x26, 0xda, 0x05, 0x5b, 0x5b, 0xc6, 0x84, 0x55, 0x3f, 0x80, 0xb4, 0x47, 0xba, + 0xbc, 0x7c, 0x58, 0x31, 0xc1, 0xa3, 0x2b, 0x6b, 0x1e, 0x44, 0x57, 0xc2, 0x47, 0x2e, 0xbb, 0x49, 0x72, 0x33, 0x9e, + 0xf8, 0xe1, 0x60, 0xa0, 0x00, 0x68, 0x69, 0x9d, 0x14, 0x83, 0xf0, 0xa9, 0x90, 0x03, 0x69, 0x74, 0x54, 0x05, 0x58, + 0x2c, 0xb3, 0x9b, 0x72, 0x92, 0x0d, 0x06, 0x3e, 0x88, 0x8d, 0x89, 0xdd, 0xd0, 0x6c, 0xee, 0xb3, 0x33, 0x05, 0x59, + 0x6d, 0x0e, 0x5b, 0x33, 0xdd, 0x02, 0x03, 0x80, 0x41, 0x44, 0xb0, 0xdc, 0x67, 0x46, 0x3e, 0xa2, 0x4e, 0x4f, 0x61, + 0x04, 0x04, 0xbf, 0x9e, 0x08, 0x44, 0x2e, 0x12, 0xa8, 0x07, 0x98, 0x09, 0x30, 0xa3, 0x8a, 0xe1, 0x35, 0xb0, 0x8b, + 0x57, 0xe6, 0x15, 0x83, 0xfe, 0x45, 0x93, 0x2c, 0xd1, 0x54, 0xe2, 0x68, 0x8c, 0x9c, 0x4a, 0x63, 0x64, 0x40, 0xec, + 0xe2, 0xf8, 0xf7, 0x94, 0x1e, 0x05, 0x29, 0xfb, 0x9c, 0x1b, 0xe2, 0x70, 0x14, 0x5f, 0xc1, 0xaa, 0x71, 0x3c, 0xd6, + 0xe6, 0xf5, 0x74, 0x56, 0xcf, 0x07, 0x22, 0x80, 0xff, 0x86, 0x82, 0xfd, 0xa2, 0xa9, 0xc8, 0x0d, 0x52, 0xe7, 0xf1, + 0x98, 0x82, 0x7c, 0xaa, 0x9b, 0xfc, 0x43, 0xee, 0xee, 0xa7, 0xb3, 0xb9, 0x35, 0x47, 0xaf, 0x6a, 0x5c, 0xb7, 0x56, + 0x37, 0x14, 0x12, 0xad, 0x69, 0x52, 0xdc, 0xe4, 0x93, 0x62, 0xc0, 0x2b, 0x5f, 0xa8, 0x2e, 0xb6, 0x46, 0xb0, 0xf0, + 0xe7, 0x16, 0x08, 0x93, 0x71, 0x2f, 0x3e, 0x59, 0xc8, 0x29, 0xed, 0xda, 0x6a, 0xb7, 0xb5, 0x49, 0xd3, 0x58, 0x35, + 0xbc, 0x86, 0x5d, 0x3a, 0x45, 0xb4, 0xed, 0x92, 0xe0, 0x0b, 0xd0, 0xb2, 0xba, 0x10, 0x79, 0x4c, 0xbf, 0x42, 0x7e, + 0x2d, 0x86, 0xff, 0x29, 0xdd, 0x9b, 0x53, 0x1b, 0xe4, 0x00, 0xb6, 0x7b, 0x0f, 0xb7, 0x63, 0xf4, 0x40, 0x06, 0x6f, + 0x04, 0x10, 0x8d, 0xaf, 0xa7, 0xd6, 0x8c, 0x89, 0x86, 0x05, 0x2b, 0x87, 0x91, 0x1f, 0x20, 0xe3, 0xe5, 0x14, 0x58, + 0xd9, 0x4f, 0x8a, 0xb8, 0xf6, 0x87, 0x91, 0x7f, 0xf5, 0x2c, 0xc8, 0xb8, 0x17, 0x0d, 0x3b, 0xbe, 0x00, 0x7b, 0xf5, + 0xd5, 0x33, 0x16, 0x0d, 0x78, 0x7e, 0x53, 0x4f, 0xb3, 0x60, 0x98, 0xb1, 0xe8, 0xa6, 0x18, 0x82, 0x0f, 0xed, 0xf3, + 0x72, 0x10, 0xfa, 0xbe, 0xd9, 0x39, 0x74, 0x37, 0x24, 0xf2, 0x08, 0xfb, 0x2b, 0xb8, 0xed, 0x6a, 0x89, 0x19, 0xe0, + 0x06, 0x56, 0x11, 0x33, 0xd8, 0xf2, 0x57, 0xcf, 0x0c, 0x97, 0x50, 0xfe, 0x5c, 0x6a, 0x36, 0x0a, 0x34, 0x27, 0xe7, + 0x68, 0x4e, 0x56, 0x42, 0x2d, 0xf9, 0xa4, 0xc2, 0xa9, 0x3a, 0x9f, 0x68, 0xbb, 0xd1, 0x18, 0x03, 0x17, 0xed, 0xb9, + 0x2d, 0x8c, 0xcc, 0x74, 0x91, 0xa2, 0x01, 0x0b, 0xcf, 0xc4, 0x29, 0x8d, 0x01, 0xed, 0xcb, 0x81, 0xa5, 0x0d, 0xf9, + 0xab, 0x9c, 0x19, 0x68, 0x1b, 0x52, 0x1a, 0x35, 0x03, 0x7f, 0xa6, 0x26, 0xcc, 0xaf, 0x60, 0x25, 0x82, 0xa8, 0x2e, + 0xc0, 0x24, 0xa9, 0xc8, 0x68, 0xa4, 0xac, 0x44, 0x72, 0x0e, 0x78, 0x1f, 0xc1, 0x93, 0x45, 0xec, 0x6a, 0x7f, 0x4a, + 0xff, 0xab, 0xc3, 0xe7, 0xda, 0x7f, 0x2a, 0x80, 0x85, 0x5c, 0x1a, 0x44, 0x06, 0x0a, 0x87, 0xd4, 0x54, 0x22, 0x4e, + 0x1c, 0xcf, 0xc0, 0xd7, 0x70, 0x81, 0xa6, 0x80, 0xfe, 0xa0, 0x66, 0x14, 0x91, 0x85, 0xbf, 0x7a, 0x76, 0x53, 0xb7, + 0x7a, 0x9e, 0x39, 0xaf, 0x41, 0x33, 0x03, 0x21, 0x3d, 0x4e, 0xd5, 0xdb, 0x90, 0xe8, 0xbc, 0xbc, 0xd4, 0x2f, 0x13, + 0x22, 0x59, 0x11, 0x79, 0xfa, 0x3e, 0x07, 0xf3, 0x88, 0x22, 0x74, 0x70, 0x65, 0x1e, 0x8f, 0x97, 0x82, 0xc2, 0x77, + 0x94, 0xe7, 0x03, 0x4e, 0xb3, 0x28, 0x01, 0x6d, 0x20, 0xab, 0x4c, 0x99, 0x9b, 0xa4, 0x65, 0xea, 0x3e, 0x80, 0x95, + 0x20, 0x47, 0x37, 0xa7, 0xa0, 0x50, 0x46, 0x82, 0x52, 0x5a, 0x0d, 0x42, 0xa9, 0x0e, 0x8b, 0x20, 0x72, 0xc8, 0x42, + 0xc0, 0xcd, 0x54, 0x34, 0x5a, 0xd2, 0xf0, 0x08, 0xe7, 0x06, 0x0a, 0x01, 0x48, 0xec, 0xa9, 0xa2, 0x8c, 0xcb, 0x61, + 0xce, 0xd6, 0x3c, 0x1c, 0xe2, 0xac, 0x49, 0x5b, 0x9e, 0x83, 0x38, 0x96, 0x4b, 0xbe, 0xc9, 0x11, 0x0c, 0x22, 0xf4, + 0x19, 0xf2, 0x27, 0xcb, 0xf9, 0x77, 0xe7, 0x30, 0xed, 0x08, 0x1f, 0x76, 0xb5, 0x05, 0x17, 0xb3, 0xbb, 0xf9, 0x04, + 0xe2, 0x5b, 0xee, 0xe6, 0xa7, 0x18, 0x22, 0x0b, 0x7f, 0xb0, 0x1a, 0x4a, 0xae, 0x28, 0x74, 0x59, 0x8f, 0x48, 0x91, + 0x3d, 0xdd, 0x70, 0x04, 0xc1, 0x81, 0x56, 0x0d, 0x32, 0x34, 0x12, 0x5f, 0x3d, 0x83, 0xac, 0xc1, 0x86, 0x7f, 0xce, + 0xc9, 0x59, 0xdd, 0x9f, 0x6c, 0xa1, 0x9a, 0x64, 0xb2, 0x56, 0x54, 0xce, 0x5f, 0xaf, 0xca, 0xf2, 0x6c, 0x55, 0x86, + 0xeb, 0x41, 0x57, 0x55, 0x96, 0x1c, 0xa9, 0x0d, 0xd0, 0x9a, 0xae, 0x10, 0x43, 0x21, 0x6b, 0xb0, 0xb4, 0xaa, 0xb2, + 0xa1, 0x3e, 0x81, 0x40, 0x1f, 0x60, 0x19, 0x35, 0xfb, 0xe9, 0xf0, 0x9f, 0xc1, 0x3f, 0x55, 0xc8, 0x52, 0x9d, 0xd6, + 0x99, 0xf8, 0x35, 0x58, 0x32, 0xfc, 0xe3, 0xb7, 0x60, 0x03, 0x58, 0x02, 0x64, 0xb9, 0xdb, 0xda, 0x68, 0xbd, 0xf2, + 0x0a, 0xf1, 0xae, 0xd6, 0x17, 0xfd, 0xd6, 0x6d, 0xa2, 0x56, 0x80, 0x11, 0x0a, 0x2d, 0x02, 0x6c, 0xf5, 0xc0, 0x3d, + 0x05, 0x3f, 0x10, 0xc3, 0xb9, 0x26, 0xad, 0xa9, 0x13, 0x5e, 0x67, 0xe3, 0x48, 0x44, 0xf5, 0x0e, 0x2e, 0xee, 0xf5, + 0xce, 0xe2, 0x6f, 0x54, 0x20, 0x00, 0xb2, 0x98, 0x62, 0xe3, 0xbc, 0x21, 0xbd, 0x32, 0xec, 0x24, 0xf4, 0xde, 0xb0, + 0x13, 0xc8, 0x8b, 0xc3, 0x4e, 0xa1, 0x4b, 0xb4, 0x9d, 0x22, 0x35, 0xd1, 0x76, 0xd2, 0x62, 0x1d, 0x96, 0x10, 0xfc, + 0xaa, 0xbd, 0x75, 0x94, 0xed, 0x8b, 0x2c, 0x61, 0xda, 0x02, 0x46, 0xb9, 0x55, 0x9f, 0x39, 0x45, 0xac, 0x95, 0xbd, + 0xd3, 0x49, 0x95, 0xbb, 0xc8, 0xa7, 0x56, 0x53, 0x64, 0xf2, 0x0f, 0xa7, 0x2d, 0x92, 0x4f, 0x7e, 0x6e, 0x37, 0x4c, + 0xa6, 0x7f, 0x3c, 0xf9, 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, 0x57, 0xbf, 0x84, 0x2b, 0x36, 0x3f, 0x34, 0x8a, + 0x9e, 0x5c, 0x9f, 0xa2, 0x6e, 0xc5, 0xd5, 0x69, 0xda, 0x6a, 0x8e, 0x1d, 0x67, 0xc8, 0xc1, 0xb3, 0x82, 0x60, 0x3b, + 0x2a, 0x51, 0xbe, 0x6d, 0x37, 0x1d, 0x13, 0x5b, 0xfd, 0xb3, 0xa8, 0xb6, 0x2b, 0xa8, 0x88, 0x88, 0x4f, 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, 0xe7, 0x77, 0xf5, 0x82, 0x93, 0xc9, 0x7e, 0x72, 0x9a, + 0xbb, 0x5d, 0xa4, 0xfd, 0xc4, 0xb7, 0x61, 0xfe, 0xf5, 0x0d, 0x62, 0x25, 0xea, 0x7f, 0x54, 0x00, 0x34, 0xb8, 0xcd, + 0x63, 0x89, 0x52, 0x7f, 0x50, 0xd5, 0x0f, 0x6a, 0xa6, 0x6a, 0x1a, 0x08, 0xe6, 0x54, 0x0a, 0xf8, 0xc3, 0xed, 0xc2, + 0x15, 0x8f, 0xb8, 0x61, 0x61, 0xfc, 0xd3, 0xab, 0xd9, 0xb9, 0xa0, 0x32, 0x70, 0x33, 0xfe, 0xd3, 0x13, 0xec, 0x1c, + 0xd6, 0x0a, 0xc8, 0x0a, 0x7f, 0x7a, 0xd5, 0x23, 0xef, 0xe7, 0xfc, 0x4f, 0x2f, 0x7f, 0xe4, 0x7d, 0xc4, 0x79, 0xf9, + 0x13, 0x49, 0x9d, 0x10, 0xd5, 0xe5, 0x4f, 0xc2, 0x14, 0x5b, 0xa7, 0xf9, 0x2b, 0x52, 0xf8, 0x04, 0x9f, 0x81, 0xef, + 0x70, 0x1d, 0xee, 0xcc, 0x6f, 0xf0, 0xd8, 0xb1, 0xd8, 0x76, 0xa9, 0x2f, 0xa0, 0x1c, 0x81, 0x45, 0x54, 0xf6, 0xdb, + 0xb9, 0xfd, 0x6a, 0x61, 0x94, 0x31, 0x76, 0x5f, 0xb2, 0x12, 0xa5, 0xb3, 0x7e, 0xbf, 0x90, 0x82, 0x91, 0x5d, 0x58, + 0xa3, 0x3d, 0x4a, 0xd5, 0xab, 0x6f, 0xc3, 0x3a, 0x4a, 0xd2, 0x7c, 0x25, 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, 0x01, 0x23, 0xa7, 0xb0, 0x54, 0x1e, 0xac, 0xc4, 0xb9, 0xe8, 0xb3, 0xe2, 0x78, 0xf4, 0x2c, 0x34, 0xf3, + 0x0a, 0x1e, 0x84, 0x3b, 0x0b, 0x23, 0x15, 0x2e, 0x84, 0xe2, 0x79, 0x85, 0xb1, 0x15, 0x15, 0x70, 0x20, 0xc3, 0x0f, + 0x08, 0xbc, 0x97, 0xfd, 0x2b, 0x18, 0x0c, 0x13, 0xdc, 0xc8, 0xa8, 0x93, 0x2b, 0xf6, 0x27, 0x06, 0x66, 0x50, 0x4f, + 0x6a, 0xf7, 0xd9, 0x83, 0x0a, 0xec, 0x85, 0x33, 0xa0, 0xbd, 0x1b, 0xa3, 0x9f, 0x55, 0xb1, 0x71, 0xd2, 0x3f, 0x15, + 0x1b, 0x48, 0xa6, 0xc3, 0xe2, 0x64, 0x9b, 0x86, 0x47, 0xf2, 0xe4, 0x38, 0xdd, 0xf4, 0x8f, 0xc7, 0x31, 0x7e, 0x1c, + 0xe5, 0xd7, 0x16, 0xf0, 0x2a, 0x6e, 0x21, 0x8d, 0x45, 0x8a, 0xde, 0x81, 0x98, 0x43, 0xd1, 0x4b, 0xf6, 0x5b, 0xc6, + 0xcb, 0x89, 0xa0, 0x94, 0x24, 0x36, 0xbc, 0x23, 0x3d, 0x4d, 0xeb, 0xd1, 0x4e, 0x06, 0xec, 0xd7, 0xa3, 0x3d, 0xfd, + 0x05, 0x8a, 0x47, 0x0b, 0x7f, 0x49, 0x7f, 0x17, 0x77, 0x73, 0xcf, 0xf9, 0xa6, 0xf1, 0x1d, 0x71, 0x81, 0x62, 0xcd, + 0xee, 0xaf, 0x69, 0xe9, 0xac, 0x03, 0xc1, 0x01, 0x6f, 0xb1, 0x8b, 0xf6, 0xfd, 0xc6, 0x75, 0x7a, 0x3a, 0x7c, 0xeb, + 0xd6, 0x28, 0xdf, 0xfb, 0x87, 0x44, 0x39, 0x38, 0xbc, 0x72, 0xd1, 0xfc, 0xed, 0xa7, 0x0c, 0x49, 0x85, 0xe6, 0x06, + 0xdb, 0xc9, 0x16, 0x61, 0x6d, 0x8c, 0x83, 0x9c, 0xad, 0xca, 0x30, 0x02, 0x06, 0x75, 0xec, 0x7f, 0xf4, 0xd9, 0xb4, + 0x21, 0xfb, 0x00, 0x50, 0xb9, 0x0a, 0x01, 0x7b, 0x00, 0x4e, 0x34, 0xc2, 0x0d, 0x70, 0xab, 0xd1, 0x92, 0x0e, 0xea, + 0xb6, 0x60, 0x20, 0x5a, 0xc2, 0xc6, 0x09, 0x5d, 0xdf, 0x57, 0x84, 0x8f, 0xca, 0xb7, 0x0f, 0xe5, 0xaf, 0x9e, 0xb3, + 0xff, 0xde, 0x61, 0x4d, 0x4d, 0xb9, 0x05, 0xcc, 0x9c, 0xb5, 0xc8, 0x2b, 0x84, 0x4e, 0x91, 0xdf, 0xab, 0xba, 0x12, + 0xc3, 0x65, 0x2d, 0xca, 0xce, 0xec, 0xd6, 0x89, 0xde, 0x39, 0x05, 0xb5, 0x54, 0x36, 0x20, 0x01, 0x6e, 0x20, 0xc5, + 0xb6, 0xc0, 0x92, 0xce, 0x06, 0x28, 0xfe, 0x0d, 0x2a, 0xed, 0xfe, 0xdf, 0x39, 0x13, 0xd4, 0x6c, 0xa3, 0xba, 0xbf, + 0xd2, 0x4f, 0x55, 0x4d, 0x62, 0x01, 0x2e, 0x27, 0x69, 0xde, 0xf1, 0x08, 0xab, 0x7f, 0x9a, 0x2c, 0x45, 0xa0, 0x57, + 0x11, 0xed, 0x4a, 0x40, 0x82, 0x76, 0x76, 0x16, 0x2a, 0x02, 0x05, 0xfa, 0xfa, 0x0f, 0xdb, 0x34, 0x8b, 0xe5, 0x6a, + 0xb6, 0x87, 0x89, 0xb2, 0x58, 0x0f, 0x11, 0xe4, 0xcc, 0xd4, 0xc1, 0x7e, 0x4f, 0x33, 0x9a, 0x85, 0x37, 0xa6, 0x04, + 0x97, 0xe2, 0x2a, 0x2a, 0x72, 0xf0, 0x39, 0xc4, 0x17, 0x3e, 0x15, 0x72, 0x83, 0x88, 0xa6, 0x3f, 0xe4, 0x9e, 0x79, + 0x83, 0x85, 0x92, 0x9f, 0x10, 0x7f, 0xc9, 0xda, 0x18, 0xf7, 0x4b, 0xa7, 0xda, 0x2f, 0x15, 0x82, 0xfb, 0xcf, 0xb6, + 0xd8, 0xa8, 0xf2, 0x44, 0x8f, 0x3e, 0xc5, 0xfa, 0x9f, 0x2d, 0xa0, 0x54, 0xf7, 0x6d, 0x70, 0x2a, 0x1e, 0x85, 0xdb, + 0xba, 0xb8, 0x45, 0x68, 0x81, 0x72, 0x54, 0x15, 0xdb, 0x32, 0x22, 0x4e, 0xd8, 0x6d, 0x5d, 0xf4, 0x34, 0x07, 0x3a, + 0x75, 0x58, 0x9a, 0xc8, 0x13, 0xa1, 0xdd, 0x82, 0xee, 0x69, 0x8e, 0x95, 0x78, 0x21, 0x4b, 0x07, 0x59, 0x27, 0xd2, + 0x84, 0xca, 0x5d, 0x5d, 0x75, 0x52, 0x2a, 0x75, 0xc3, 0xeb, 0x54, 0x33, 0xfe, 0x2e, 0xcd, 0x9f, 0x58, 0xf6, 0xeb, + 0xd6, 0x6f, 0xb5, 0xda, 0x1b, 0xab, 0x47, 0x25, 0x6b, 0x8e, 0xb3, 0x09, 0x49, 0xe9, 0x13, 0xb6, 0x9b, 0x49, 0xd7, + 0x3a, 0xf0, 0x24, 0xb8, 0x1c, 0x7a, 0x02, 0x2a, 0x06, 0x4d, 0xbc, 0xdd, 0x05, 0xea, 0x11, 0x78, 0x06, 0xaa, 0x19, + 0x24, 0xd7, 0x01, 0xbf, 0xac, 0xb5, 0x3c, 0x65, 0x84, 0x61, 0xb5, 0xb3, 0x68, 0x39, 0x58, 0x49, 0x78, 0xae, 0x08, + 0x5c, 0xbb, 0x12, 0x78, 0x35, 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, 0x43, 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, 0x7a, 0xf5, 0xeb, 0xba, 0xc3, 0x75, 0xde, 0x04, 0xc7, 0x4d, 0xd7, 0xb6, 0xda, 0xd9, 0xcf, 0xdd, 0xbd, 0xb5, + 0x88, 0xc2, 0x2c, 0xfb, 0x6b, 0x51, 0xfc, 0x51, 0xe9, 0x3b, 0x02, 0x1d, 0xdd, 0x79, 0x51, 0xa7, 0xcb, 0xfd, 0x07, + 0xc2, 0x78, 0xf2, 0xea, 0x13, 0xa2, 0x5b, 0xdf, 0x67, 0xee, 0x57, 0x80, 0x1b, 0xc1, 0x1d, 0x44, 0x7b, 0xb7, 0xd4, + 0x27, 0xb5, 0xfa, 0x5a, 0xaf, 0x9d, 0xa7, 0xe7, 0x37, 0x9d, 0xdb, 0xef, 0xa1, 0x39, 0xd9, 0x7a, 0x4f, 0x0b, 0x6b, + 0x65, 0xe9, 0xa9, 0x2a, 0xd8, 0x9b, 0xe5, 0xb9, 0x2a, 0x98, 0x3c, 0xf0, 0x9a, 0xfd, 0x82, 0x06, 0x57, 0x3a, 0xd9, + 0x78, 0xcf, 0xd4, 0xc0, 0x2d, 0x0a, 0x4b, 0x87, 0x5f, 0x72, 0x33, 0x79, 0x89, 0xfb, 0x4b, 0x45, 0x2e, 0xf6, 0x9d, + 0x33, 0xba, 0x33, 0xb3, 0xee, 0x55, 0x85, 0xab, 0x05, 0xb9, 0x3a, 0xb0, 0xb5, 0xec, 0xe2, 0x70, 0xc3, 0x22, 0x0a, + 0x10, 0x88, 0xe9, 0x95, 0x5a, 0xfb, 0x13, 0x1a, 0x84, 0x6a, 0x30, 0xf0, 0x0b, 0x0c, 0x56, 0x05, 0x0a, 0x1f, 0x28, + 0x92, 0xbf, 0xf2, 0x04, 0xec, 0xe2, 0x19, 0xa0, 0x5b, 0xb1, 0x59, 0x31, 0x42, 0x84, 0x4c, 0x56, 0xb1, 0x9a, 0xce, + 0x20, 0x9f, 0xfa, 0xe2, 0x1b, 0x5b, 0x75, 0x3e, 0x6f, 0x6b, 0xaa, 0x9c, 0x3b, 0x14, 0xba, 0xbb, 0xa9, 0x3b, 0xb7, + 0x2e, 0xf2, 0xdc, 0x21, 0xe4, 0x4a, 0xc5, 0x4a, 0x4c, 0x43, 0xcd, 0x93, 0x34, 0xa3, 0xfe, 0x62, 0x9f, 0x8a, 0x1a, + 0x85, 0x53, 0xfe, 0x74, 0x0c, 0xaa, 0x70, 0x55, 0x43, 0x1c, 0x4b, 0x55, 0x3c, 0xb2, 0x41, 0xa0, 0x79, 0x75, 0xa7, + 0x92, 0x26, 0x64, 0x72, 0x23, 0x7c, 0x6a, 0x52, 0xca, 0xd3, 0xb4, 0x49, 0x2b, 0x45, 0xea, 0xe0, 0x83, 0x3a, 0xd5, + 0x78, 0x6e, 0xe6, 0xcf, 0x01, 0xcc, 0xb8, 0xba, 0xe1, 0xd7, 0x8a, 0xcb, 0xa8, 0xad, 0xcc, 0xa4, 0xfd, 0xc9, 0xd1, + 0xd8, 0x28, 0x56, 0xe3, 0x46, 0x19, 0x61, 0xa5, 0x34, 0x27, 0xc5, 0x72, 0x3c, 0xff, 0x80, 0xc1, 0x9a, 0x27, 0xb0, + 0x83, 0x89, 0x4a, 0x79, 0x1f, 0x01, 0xf1, 0x75, 0x92, 0xae, 0x12, 0x48, 0x91, 0xfe, 0xa5, 0x4b, 0xee, 0x32, 0x36, + 0x10, 0x63, 0x56, 0xcc, 0x8c, 0xfe, 0x07, 0x77, 0x49, 0x7f, 0x12, 0x02, 0xe0, 0x26, 0x9a, 0x42, 0xa7, 0xce, 0x93, + 0xab, 0x2a, 0x58, 0x5e, 0x79, 0x68, 0xc5, 0x88, 0x07, 0xff, 0xf9, 0x3c, 0x44, 0x10, 0x73, 0x4c, 0xf1, 0xf4, 0x0b, + 0xa3, 0xff, 0x08, 0xae, 0x31, 0x82, 0xd0, 0xdd, 0x3b, 0x87, 0x21, 0xdc, 0xec, 0x41, 0x06, 0xf5, 0x87, 0x3a, 0x24, + 0x6a, 0xf8, 0xd7, 0xdc, 0x83, 0xfe, 0xaf, 0x33, 0x61, 0xa9, 0xfd, 0xf4, 0x74, 0x00, 0x15, 0xbc, 0xaf, 0x78, 0x1b, + 0x11, 0xdf, 0x27, 0x7e, 0x1a, 0x0f, 0xb6, 0x4f, 0xb7, 0x60, 0xad, 0xfb, 0x50, 0x19, 0xeb, 0x2a, 0x61, 0x03, 0x01, + 0x5f, 0xa3, 0xa8, 0x3d, 0xaf, 0xdd, 0xee, 0xc1, 0x7f, 0xfa, 0x57, 0x21, 0x03, 0x26, 0x4e, 0xdf, 0x67, 0x4e, 0xd6, + 0xe8, 0x2a, 0x93, 0xe9, 0x43, 0x27, 0x7d, 0xab, 0xd3, 0x7d, 0x27, 0xfc, 0x23, 0x67, 0x16, 0x1f, 0x6e, 0xe9, 0x2b, + 0x4d, 0x8a, 0x3b, 0x60, 0x65, 0xf3, 0xa8, 0x20, 0xd4, 0xb9, 0x88, 0xbe, 0x32, 0xe5, 0x5b, 0x42, 0xcd, 0xa1, 0xb1, + 0xa4, 0x94, 0xee, 0x35, 0xf4, 0x3a, 0xad, 0xf5, 0xdb, 0x28, 0xc1, 0x98, 0xe8, 0x78, 0xf2, 0x32, 0x1e, 0x2b, 0xef, + 0xe3, 0x71, 0x23, 0x15, 0xf2, 0x00, 0x44, 0xa0, 0x62, 0xfc, 0xe9, 0xca, 0x53, 0x91, 0x5e, 0x18, 0xaf, 0x42, 0x29, + 0x28, 0x0c, 0xe8, 0x0a, 0xa4, 0x80, 0x47, 0xed, 0x89, 0xce, 0xc2, 0x2e, 0xe1, 0x1e, 0xdd, 0x04, 0x8c, 0xf5, 0xf9, + 0xaf, 0xb9, 0x97, 0x33, 0xe1, 0x0e, 0x2f, 0x06, 0xa8, 0x4d, 0xbd, 0xba, 0xfb, 0xb8, 0x56, 0xe7, 0x70, 0x08, 0x0e, + 0x56, 0x83, 0x08, 0x4e, 0xe7, 0x73, 0x47, 0xb3, 0x2c, 0x40, 0xe5, 0x64, 0x95, 0x91, 0x37, 0x4f, 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, 0xd7, 0x47, 0xf5, 0xd3, 0x67, 0x6c, 0xc3, 0x25, 0xea, 0xa4, 0x33, 0x11, 0x80, + 0xd8, 0x53, 0xb3, 0x8a, 0x6e, 0x80, 0xa4, 0x4e, 0xb3, 0x8a, 0x6e, 0xa8, 0xd9, 0xc6, 0x38, 0x00, 0xca, 0x58, 0xc0, + 0xbe, 0x9b, 0x8e, 0x83, 0xf5, 0xd3, 0x58, 0x5e, 0x87, 0x56, 0x4f, 0xb7, 0xca, 0x67, 0x50, 0xb7, 0xda, 0x18, 0x13, + 0xdb, 0xcd, 0x97, 0x73, 0xfd, 0x6e, 0xb0, 0xf4, 0xed, 0xa0, 0x39, 0xa7, 0xec, 0x95, 0x2e, 0x7b, 0x6d, 0x97, 0x4d, + 0x3d, 0x77, 0x52, 0xb4, 0x1a, 0x03, 0x7a, 0x03, 0x0b, 0xd6, 0xe7, 0x22, 0xcd, 0x56, 0xa5, 0x2a, 0x01, 0x2f, 0x8c, + 0x35, 0x5b, 0xf9, 0x8d, 0xcc, 0x90, 0x84, 0x79, 0x9c, 0x89, 0xb7, 0x74, 0xaf, 0x85, 0xc9, 0x71, 0x2a, 0x92, 0x29, + 0xa1, 0x53, 0xba, 0xb3, 0x0d, 0x9d, 0xab, 0x30, 0x8a, 0x68, 0xad, 0xa4, 0xd2, 0x48, 0x60, 0x6a, 0x06, 0x28, 0x99, + 0x2b, 0x70, 0x4a, 0x97, 0xfb, 0xdf, 0x89, 0x18, 0x67, 0xbe, 0x28, 0x99, 0x01, 0xdd, 0xf2, 0xeb, 0x62, 0xd3, 0x4a, + 0x91, 0x11, 0xe6, 0xcd, 0x69, 0x7b, 0x5d, 0x1f, 0x02, 0xb9, 0x5a, 0x0e, 0x28, 0x1a, 0x07, 0x85, 0x0e, 0x97, 0x2a, + 0x01, 0xf6, 0x45, 0xe2, 0x67, 0x84, 0x2d, 0xed, 0x81, 0xdc, 0x1e, 0x9d, 0x09, 0x73, 0xc9, 0x49, 0x59, 0x76, 0x29, + 0xcd, 0xe0, 0x72, 0xe2, 0x4a, 0x70, 0x91, 0xde, 0xae, 0xa7, 0x49, 0x4b, 0xdb, 0xc7, 0x86, 0x73, 0x34, 0xb4, 0x0d, + 0xba, 0x63, 0x7f, 0x68, 0x2e, 0x16, 0xb1, 0x75, 0xb1, 0x18, 0x76, 0x66, 0x3f, 0x59, 0x2c, 0x40, 0x0e, 0x00, 0x47, + 0xdd, 0x96, 0x8f, 0xd9, 0x12, 0x38, 0xad, 0xa6, 0xd9, 0xd4, 0xdb, 0xf2, 0xfc, 0xa9, 0xea, 0xe9, 0x25, 0xaf, 0x9e, + 0x0a, 0x33, 0x16, 0x5b, 0x5e, 0x3d, 0xb5, 0x8e, 0x9c, 0xfc, 0xa9, 0x50, 0xa2, 0x75, 0x01, 0xcd, 0xc0, 0x6b, 0x0a, + 0x18, 0xb1, 0x64, 0x32, 0xa5, 0x8a, 0x3c, 0xee, 0x4d, 0xb7, 0x6a, 0xf0, 0x82, 0xc2, 0x21, 0x90, 0xd2, 0xe9, 0x57, + 0xcf, 0x98, 0x7e, 0xef, 0xea, 0x59, 0x87, 0xac, 0x6d, 0x98, 0x2e, 0xb7, 0xc3, 0x64, 0x50, 0xfa, 0x4f, 0xcd, 0xc4, + 0xb8, 0xb2, 0x26, 0x09, 0x20, 0xfe, 0x8d, 0xfd, 0x0e, 0x29, 0xdc, 0xbc, 0xbf, 0x1c, 0xc6, 0x8f, 0xbc, 0x1f, 0x23, + 0x7b, 0x92, 0x66, 0x88, 0x35, 0x93, 0x0a, 0xb9, 0xfb, 0x6a, 0xfd, 0x63, 0x62, 0x37, 0xd9, 0x03, 0x0b, 0x40, 0x6c, + 0x4d, 0x5b, 0xdd, 0xf2, 0x7e, 0xdf, 0x33, 0x45, 0x80, 0x1f, 0x94, 0x7f, 0x72, 0x67, 0x48, 0x06, 0x65, 0xd7, 0x0d, + 0x21, 0x1e, 0x94, 0x4d, 0xd3, 0x5e, 0x6f, 0x07, 0x67, 0x1e, 0xab, 0xeb, 0xb4, 0xb3, 0xb8, 0x5a, 0x64, 0x90, 0x56, + 0x1f, 0xb2, 0xd3, 0xcc, 0x3e, 0x3b, 0x59, 0x2a, 0xdd, 0xef, 0x43, 0x44, 0xdc, 0x49, 0xd6, 0xf6, 0xdb, 0x2d, 0xb8, + 0x86, 0x93, 0x41, 0xe8, 0xca, 0xde, 0x2e, 0xa3, 0x8d, 0x0b, 0x71, 0xda, 0x33, 0x9d, 0x2f, 0xf8, 0xf2, 0x28, 0xed, + 0x3c, 0x38, 0xd5, 0x13, 0x7d, 0x6e, 0xba, 0xab, 0x4c, 0xae, 0x75, 0x58, 0x8d, 0x41, 0x6d, 0x16, 0xb6, 0x70, 0x17, + 0xb6, 0xd1, 0x41, 0x6b, 0x5f, 0x16, 0xfc, 0x53, 0x06, 0xe0, 0x4b, 0xcf, 0x96, 0x5d, 0xaf, 0x49, 0xab, 0xd7, 0x32, + 0x0a, 0xb1, 0xa5, 0xed, 0xd5, 0xa7, 0xa3, 0x7c, 0xdc, 0x9c, 0x51, 0x5c, 0xc8, 0x51, 0x7e, 0xf4, 0x1a, 0xa2, 0xae, + 0x75, 0x1d, 0x17, 0x8b, 0x0e, 0x37, 0xae, 0xba, 0xed, 0xc6, 0xf5, 0x23, 0xe2, 0xad, 0xd1, 0x26, 0x85, 0x5a, 0x19, + 0x3b, 0x82, 0x97, 0x55, 0xc3, 0x21, 0x13, 0xc3, 0xa1, 0x84, 0x4c, 0x7d, 0xec, 0xde, 0xd0, 0xb4, 0xcf, 0x4f, 0x5b, + 0x3f, 0x62, 0xa9, 0x71, 0x14, 0x1b, 0xde, 0xf9, 0x3b, 0x8f, 0xad, 0x71, 0x25, 0x5f, 0x06, 0xb3, 0x5d, 0x41, 0xb5, + 0x35, 0xde, 0xb0, 0x57, 0xf1, 0x1f, 0x72, 0xa9, 0xe4, 0x6f, 0x7f, 0x86, 0x6b, 0x78, 0x6b, 0x4b, 0x07, 0x4d, 0x35, + 0xab, 0x98, 0xb9, 0x17, 0x9c, 0x7e, 0xdc, 0xbd, 0x22, 0x18, 0xfc, 0x9e, 0x8e, 0x82, 0x5c, 0x2c, 0xd5, 0x1a, 0x50, + 0x90, 0x4e, 0xec, 0x98, 0xca, 0x02, 0xc3, 0x00, 0xde, 0x90, 0x01, 0xf2, 0x98, 0xc2, 0xdd, 0x50, 0xe1, 0x85, 0xbf, + 0xe4, 0x64, 0x97, 0xc0, 0xb6, 0x66, 0x7c, 0xcc, 0x70, 0x07, 0x21, 0xff, 0x08, 0xb6, 0x62, 0x6b, 0x76, 0xc7, 0x16, + 0x0c, 0xc9, 0xc6, 0x71, 0x18, 0x63, 0x3e, 0x9e, 0xc4, 0x37, 0x62, 0x12, 0x0f, 0x78, 0x84, 0x8e, 0x11, 0x1b, 0x5e, + 0xcf, 0x62, 0x39, 0x80, 0x6c, 0xc5, 0x95, 0x0e, 0x08, 0xa1, 0xb1, 0xa1, 0x25, 0xaf, 0x0b, 0x83, 0x8b, 0x1d, 0xfb, + 0x2c, 0x47, 0x91, 0x8c, 0x43, 0xb0, 0x68, 0x55, 0x03, 0x0b, 0x13, 0xbb, 0xe3, 0xc5, 0x6c, 0x3d, 0xc7, 0x7f, 0x8e, + 0x47, 0x04, 0xc0, 0x0e, 0x0e, 0x0d, 0x5b, 0x45, 0x88, 0xf4, 0xb6, 0xe0, 0x2b, 0xcb, 0xd3, 0x85, 0xdd, 0xf3, 0xb7, + 0x7c, 0xcc, 0x2e, 0x7f, 0xf4, 0x20, 0x72, 0xf6, 0xf2, 0x23, 0xa0, 0x21, 0xde, 0xf3, 0xbb, 0xd4, 0xcb, 0xd9, 0x1d, + 0x51, 0x10, 0xde, 0x81, 0x33, 0xd0, 0x3d, 0x44, 0xc0, 0xbe, 0xe5, 0x0b, 0x8c, 0x15, 0xbb, 0x48, 0x97, 0x1e, 0x66, + 0x84, 0xda, 0xd3, 0xf9, 0xb2, 0x51, 0x93, 0x70, 0x7b, 0xb3, 0x9c, 0x0c, 0x06, 0x5b, 0x7f, 0xcf, 0x37, 0xc0, 0x07, + 0x73, 0xf9, 0xa3, 0xb7, 0xa7, 0x72, 0xe1, 0x3f, 0xaf, 0xb3, 0xe4, 0xbd, 0xcf, 0xde, 0x0e, 0xf8, 0x02, 0xf0, 0x96, + 0xd0, 0x81, 0xeb, 0xde, 0x67, 0x12, 0xaf, 0xed, 0xad, 0xbe, 0x46, 0x20, 0x91, 0x2f, 0x00, 0x23, 0x26, 0xe6, 0xf7, + 0x5b, 0x88, 0xc0, 0x48, 0xc0, 0xb7, 0x55, 0x7b, 0xc4, 0xef, 0xb8, 0x01, 0xfc, 0xca, 0x7c, 0xf6, 0xc0, 0x43, 0xfd, + 0x33, 0xf1, 0xd9, 0x2d, 0x7f, 0xcf, 0x9f, 0x7b, 0x52, 0x92, 0x2e, 0x67, 0xef, 0xe7, 0x70, 0x3d, 0x94, 0xf2, 0x74, + 0x48, 0x3f, 0x1b, 0x83, 0x01, 0x84, 0x42, 0xe6, 0xad, 0x07, 0xac, 0x49, 0x21, 0xfe, 0x05, 0x7c, 0x3b, 0x4a, 0xd8, + 0xbc, 0xf5, 0x76, 0xbe, 0x96, 0x37, 0x6f, 0xbd, 0x07, 0x9f, 0xa2, 0x00, 0xab, 0xa0, 0x94, 0x05, 0x56, 0x41, 0xd8, + 0x68, 0x23, 0x8c, 0x81, 0xab, 0x77, 0x8d, 0xa1, 0xae, 0xe7, 0x88, 0x6d, 0x2b, 0x7d, 0x17, 0xbe, 0x83, 0x0c, 0xf8, + 0xe0, 0x75, 0x51, 0x12, 0x7d, 0x4e, 0x4d, 0x91, 0xb4, 0xee, 0xb9, 0xdf, 0x5a, 0x77, 0xb4, 0xa6, 0xd4, 0x47, 0x6e, + 0xc6, 0xc7, 0x63, 0xfd, 0x5c, 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, 0xd7, 0xc3, 0xda, + 0x9f, 0x38, 0xb5, 0xb0, 0xb4, 0x9a, 0x83, 0xfa, 0xa9, 0x2d, 0xc7, 0xa9, 0xaa, 0xfd, 0x4b, 0x92, 0x54, 0xbb, 0x4a, + 0xcb, 0xe9, 0xbd, 0x7d, 0xd3, 0x65, 0x82, 0x8d, 0xfd, 0x80, 0xaa, 0x23, 0xab, 0x61, 0xf7, 0x85, 0xfa, 0xa2, 0xa7, + 0x64, 0x42, 0xf3, 0x51, 0x45, 0xf3, 0xec, 0x7e, 0xb3, 0xa3, 0xfe, 0xd3, 0xeb, 0xa1, 0x08, 0x90, 0xac, 0xd2, 0x62, + 0x29, 0x72, 0x36, 0xf6, 0xd3, 0x61, 0x92, 0xa9, 0xf0, 0x82, 0x74, 0x74, 0xf7, 0x1b, 0xf7, 0xb7, 0xdc, 0x40, 0xd6, + 0x68, 0xd5, 0x06, 0x63, 0xa5, 0x68, 0x19, 0xac, 0x6f, 0xc6, 0xfd, 0xbe, 0xb8, 0x19, 0x4f, 0x45, 0x50, 0x03, 0x71, + 0x91, 0x78, 0x3e, 0x9e, 0xd6, 0xc4, 0x92, 0xda, 0x15, 0x18, 0xa3, 0xc7, 0x55, 0x51, 0xfb, 0xd4, 0xcf, 0x21, 0x14, + 0xa9, 0xd6, 0xcc, 0xb1, 0xc6, 0x8d, 0x11, 0x71, 0x87, 0x95, 0x6b, 0xa7, 0xf6, 0x3a, 0x00, 0xcb, 0xab, 0x71, 0x41, + 0xd8, 0x26, 0xa7, 0xce, 0x05, 0xac, 0x46, 0x43, 0xaa, 0xdd, 0x70, 0xeb, 0x65, 0xe7, 0x37, 0x8f, 0x13, 0x5b, 0x1b, + 0xe1, 0x96, 0x02, 0xca, 0x28, 0xbf, 0xb1, 0x9c, 0xb0, 0x3b, 0xd5, 0x3b, 0x52, 0xb5, 0x23, 0xce, 0x5c, 0xc0, 0x2a, + 0xc3, 0x53, 0xab, 0x6f, 0x62, 0x70, 0x22, 0xe4, 0xad, 0x74, 0xbc, 0xf6, 0x23, 0xee, 0x57, 0xf7, 0x75, 0xaf, 0x04, + 0x3f, 0x09, 0x79, 0xfd, 0x96, 0x77, 0x00, 0x58, 0xf1, 0x21, 0x2f, 0xa6, 0x85, 0xa3, 0x75, 0x19, 0x94, 0x01, 0x22, + 0x34, 0x03, 0xa0, 0x93, 0xab, 0x83, 0x28, 0x0d, 0x5c, 0x71, 0x87, 0x08, 0x3f, 0x8d, 0x9e, 0x56, 0xcf, 0xc3, 0xa7, + 0xf9, 0x34, 0xbc, 0xaa, 0x82, 0xe8, 0x2a, 0x0f, 0xa2, 0xa7, 0xf9, 0x4d, 0xf8, 0xb4, 0x9a, 0x46, 0x57, 0x55, 0x10, + 0x5e, 0xe5, 0x8d, 0x7d, 0xd7, 0xee, 0xee, 0x09, 0x79, 0xdb, 0xd5, 0x1f, 0xb9, 0x54, 0xf6, 0x94, 0xe9, 0xe5, 0x65, + 0xad, 0x57, 0x6a, 0xb7, 0xb9, 0x5e, 0xa3, 0x66, 0xea, 0xa3, 0xec, 0x2f, 0xb6, 0xb1, 0xf0, 0x64, 0x0e, 0xa1, 0xcf, + 0x48, 0x8b, 0xb9, 0xc7, 0xb9, 0xde, 0x1c, 0x48, 0x61, 0x60, 0xc4, 0xa4, 0x92, 0x91, 0xd3, 0x0b, 0x5c, 0x84, 0x72, + 0xc4, 0xb0, 0x96, 0xae, 0xf6, 0x59, 0x97, 0xde, 0x40, 0x5d, 0x53, 0xec, 0x6b, 0xc8, 0xc0, 0x8b, 0xa6, 0xd7, 0xc1, + 0x18, 0x90, 0x23, 0xf0, 0x8e, 0xcf, 0x96, 0x70, 0x60, 0x6e, 0x00, 0xfa, 0xe6, 0x51, 0x5f, 0x97, 0x15, 0xdf, 0xa8, + 0xbe, 0x99, 0x6e, 0x46, 0x4a, 0xf9, 0xb1, 0xe6, 0xab, 0xab, 0x67, 0xec, 0x8e, 0x6b, 0x54, 0x94, 0x5f, 0xf4, 0x62, + 0xbd, 0x07, 0xae, 0xba, 0x5f, 0xe0, 0x36, 0x8b, 0xc7, 0xae, 0x3c, 0x60, 0xd9, 0x8e, 0x3d, 0xb0, 0x5b, 0xf6, 0x9e, + 0x3d, 0x61, 0x6f, 0xd8, 0x17, 0xf6, 0x13, 0xaa, 0x36, 0x94, 0x90, 0xe7, 0x2f, 0xf8, 0x9d, 0x34, 0x3d, 0x4a, 0x54, + 0xb2, 0x07, 0xdb, 0x4c, 0x33, 0xdc, 0xb2, 0xf7, 0x7c, 0x31, 0x5c, 0xb3, 0x37, 0x90, 0x0d, 0x65, 0xe2, 0xc1, 0x9a, + 0xfd, 0xc4, 0x15, 0x88, 0x99, 0x3e, 0x0b, 0x4b, 0x4b, 0x54, 0x34, 0x65, 0xa2, 0x0c, 0xfd, 0x86, 0xe3, 0x8b, 0xec, + 0x27, 0x2c, 0x42, 0x7e, 0x66, 0xb8, 0x66, 0x0f, 0x7c, 0x31, 0x58, 0xb3, 0xf7, 0xda, 0x40, 0x34, 0xd8, 0xba, 0xa5, + 0x11, 0x92, 0x95, 0x2e, 0x4b, 0x4a, 0xd3, 0x3b, 0xfb, 0x1a, 0xb8, 0x65, 0xb7, 0x58, 0xbb, 0x27, 0x58, 0x34, 0x0a, + 0xfc, 0x83, 0x35, 0xfb, 0xc2, 0x25, 0x80, 0x9a, 0x5b, 0x9e, 0xf4, 0x0a, 0xd5, 0x05, 0xd2, 0xfd, 0xe0, 0x09, 0xa7, + 0x17, 0xd9, 0x17, 0x2c, 0x83, 0xbe, 0x32, 0x5c, 0xb3, 0x1d, 0xd6, 0xee, 0xd6, 0x58, 0xb6, 0xac, 0xea, 0x49, 0x44, + 0x60, 0x14, 0x54, 0x4a, 0xcb, 0xbf, 0x11, 0xcb, 0xa6, 0x6e, 0x1a, 0xd4, 0x86, 0xfe, 0x7c, 0x30, 0xfa, 0x0f, 0x5f, + 0xbf, 0xfb, 0xc1, 0x2b, 0xf5, 0xb5, 0xf7, 0x17, 0xc7, 0xb5, 0xb2, 0x44, 0xd7, 0xca, 0x5f, 0x79, 0x39, 0xfb, 0x65, + 0x3e, 0xd1, 0xb5, 0xa4, 0x1d, 0x86, 0x7c, 0x4d, 0x67, 0xbf, 0x74, 0x38, 0x5b, 0xfe, 0xea, 0xfb, 0x8d, 0xe9, 0x62, + 0xf5, 0x59, 0xdd, 0xbb, 0x0f, 0x83, 0x6d, 0xe3, 0xd4, 0x7b, 0x7f, 0xbe, 0xde, 0xd8, 0xcc, 0x5a, 0x7b, 0x66, 0xfe, + 0x0f, 0x57, 0x7a, 0x87, 0x43, 0x77, 0xcb, 0x77, 0xc3, 0xad, 0x3d, 0x0a, 0xf2, 0xfb, 0x52, 0x69, 0x9c, 0xd5, 0xfc, + 0x85, 0x97, 0x77, 0x49, 0xb1, 0x80, 0x68, 0xf4, 0xc9, 0x48, 0x42, 0xd7, 0xcc, 0xc4, 0x33, 0xc4, 0x57, 0x19, 0x20, + 0x73, 0x81, 0x68, 0x76, 0xcf, 0xc7, 0x93, 0xfb, 0x9b, 0x78, 0x72, 0x3f, 0xe0, 0x9f, 0x4c, 0x0b, 0xda, 0x8b, 0xed, + 0xde, 0x67, 0xbf, 0xf2, 0xc2, 0x5e, 0x8e, 0xbf, 0xf8, 0xec, 0x9d, 0x70, 0x57, 0xe8, 0x2f, 0x3e, 0xfb, 0x22, 0xf8, + 0xaf, 0x23, 0x4d, 0x94, 0xc1, 0xbe, 0xd4, 0xfc, 0xd7, 0x11, 0x32, 0x7e, 0xb0, 0xcf, 0x82, 0xbf, 0x03, 0xdf, 0xef, + 0x2a, 0x41, 0xab, 0xf8, 0xe7, 0x5a, 0xfd, 0x7c, 0x2f, 0xe3, 0x72, 0xe0, 0x4d, 0x68, 0x05, 0xbd, 0x79, 0x57, 0xcb, + 0x9f, 0xc4, 0xc3, 0x91, 0xaa, 0xa7, 0x86, 0x7f, 0x16, 0x8b, 0x59, 0xd4, 0x27, 0xe9, 0x54, 0xde, 0xe4, 0x2d, 0xcf, + 0xa4, 0x75, 0xf9, 0x1e, 0x42, 0x81, 0xdf, 0xda, 0x10, 0x05, 0x7b, 0x8e, 0x1b, 0xc1, 0x5b, 0x06, 0xf0, 0x91, 0xd9, + 0x74, 0xc7, 0x6f, 0xf9, 0x13, 0xfe, 0x85, 0xef, 0x83, 0x07, 0xfe, 0x9e, 0xbf, 0xe1, 0x3f, 0xf1, 0x3d, 0x5b, 0x4a, + 0xb4, 0xd3, 0x7a, 0x77, 0x1d, 0xec, 0x58, 0xbd, 0xbf, 0x0e, 0x1e, 0x58, 0xbd, 0x7b, 0x16, 0xdc, 0xb2, 0x7a, 0xff, + 0x2c, 0x78, 0xcf, 0x76, 0xd7, 0xc1, 0x13, 0xb6, 0xbf, 0x0e, 0xde, 0xb0, 0xdd, 0xb3, 0xe0, 0x0b, 0xdb, 0x3f, 0x0b, + 0x7e, 0x92, 0x18, 0x0f, 0x5f, 0x84, 0xe4, 0x38, 0xf9, 0x52, 0x33, 0xc3, 0xa7, 0x1b, 0x7c, 0x16, 0xd6, 0x2f, 0xaa, + 0x63, 0xf0, 0xb9, 0x66, 0xba, 0xc5, 0x81, 0x10, 0x4c, 0xb7, 0x37, 0xb8, 0xa3, 0x27, 0xa6, 0x55, 0x41, 0x2a, 0x58, + 0x57, 0x3b, 0x83, 0x45, 0xdd, 0xb4, 0xce, 0x64, 0xc7, 0x2f, 0x31, 0xee, 0xf0, 0x4b, 0x5c, 0xb0, 0x65, 0xd3, 0xe9, + 0xa4, 0x73, 0xfe, 0x24, 0xd0, 0x9b, 0xbf, 0xde, 0xf5, 0x73, 0xe9, 0x3b, 0x53, 0x34, 0x5c, 0x6b, 0x8d, 0x5b, 0x3b, + 0x7d, 0x68, 0xed, 0xf4, 0x4c, 0xaa, 0xd0, 0x22, 0x16, 0x95, 0x45, 0x55, 0x21, 0x93, 0x78, 0x90, 0x69, 0x7d, 0x5a, + 0xc2, 0x48, 0x91, 0x09, 0x68, 0xf4, 0x05, 0x1d, 0x03, 0x15, 0x59, 0x14, 0xd8, 0x92, 0x6f, 0x07, 0x09, 0xdb, 0xf0, + 0x78, 0x3a, 0x4c, 0x82, 0x25, 0x5b, 0xf1, 0x61, 0xb7, 0x40, 0xb0, 0x56, 0x01, 0x4c, 0xfa, 0xe2, 0xd4, 0xde, 0xd7, + 0x79, 0x6f, 0x9d, 0xc6, 0x71, 0x26, 0x50, 0xd9, 0x96, 0xeb, 0x0d, 0x7e, 0xe7, 0xec, 0xe7, 0x1b, 0xb5, 0xbf, 0x83, + 0xa4, 0xf0, 0x2b, 0x30, 0xec, 0x10, 0xe1, 0x1d, 0x54, 0x18, 0x79, 0x96, 0xcc, 0xa2, 0xcf, 0xed, 0x2d, 0x7d, 0x67, + 0xb6, 0xe9, 0x7f, 0xb7, 0x08, 0xda, 0xc7, 0x65, 0xe7, 0x7f, 0x32, 0xaf, 0xfe, 0xd6, 0xf1, 0xea, 0xd6, 0x9f, 0x3c, + 0xf0, 0x4f, 0x18, 0x96, 0x80, 0x89, 0x6c, 0xcf, 0x3f, 0x8d, 0x76, 0x8d, 0x53, 0x9e, 0xdc, 0xc7, 0xff, 0xaf, 0x14, + 0x68, 0xef, 0xe4, 0xb9, 0xbd, 0x23, 0xee, 0x78, 0xc7, 0x3e, 0xbe, 0xb4, 0x36, 0x44, 0x03, 0x4d, 0xf2, 0x89, 0xbb, + 0xd1, 0xd0, 0xb0, 0x21, 0xfe, 0xc2, 0xf3, 0xd9, 0xa7, 0xf9, 0x64, 0xc7, 0x4f, 0xb7, 0xc3, 0x4f, 0x1d, 0xdb, 0xe1, + 0x2f, 0xfe, 0x60, 0xd9, 0x7c, 0xad, 0x57, 0x3b, 0xb7, 0x71, 0xa7, 0xd2, 0x7b, 0x7e, 0xba, 0x89, 0x0f, 0xff, 0xed, + 0x4a, 0xef, 0xbf, 0xb9, 0xd2, 0x76, 0x95, 0xbb, 0x3b, 0xdf, 0x74, 0x7c, 0x23, 0x6b, 0x8d, 0x71, 0x66, 0x46, 0xb3, 0xf8, 0x13, 0xcd, 0xd2, 0x20, 0xb2, 0x14, 0x8a, 0x3f, 0x99, 0x69, 0xa7, 0xee, 0x54, 0x59, 0xdd, 0x2d, 0xdf, 0xe2, - 0x1e, 0x7f, 0xcb, 0xc7, 0x6c, 0x61, 0x3c, 0x35, 0x6f, 0xaf, 0x16, 0x93, 0xc1, 0xe0, 0xd6, 0xdf, 0xdf, 0xf3, 0x70, - 0x76, 0x3b, 0x67, 0xd7, 0xfc, 0x9e, 0x16, 0xd3, 0x44, 0x35, 0xbd, 0x78, 0x4c, 0xf0, 0xba, 0xf5, 0xfd, 0x89, 0xc5, - 0xff, 0x6a, 0x5f, 0x34, 0x6f, 0xfd, 0x81, 0xb4, 0x46, 0xcb, 0x5d, 0xfd, 0xfd, 0xe3, 0x8a, 0x89, 0x5b, 0x10, 0x2f, - 0xde, 0xdb, 0x9a, 0x86, 0xb7, 0xfc, 0xa3, 0x77, 0xed, 0x4f, 0xaf, 0x75, 0xcc, 0xcd, 0x44, 0x1d, 0x49, 0x6f, 0x2f, - 0x9e, 0xb3, 0x5f, 0xf9, 0x27, 0x79, 0x9c, 0x7c, 0x11, 0x72, 0xd2, 0xde, 0x20, 0x77, 0x13, 0x9d, 0x12, 0xef, 0xdc, - 0x44, 0xc2, 0x82, 0x40, 0x18, 0x8e, 0x9a, 0x3f, 0x4c, 0xca, 0xa9, 0xb7, 0x03, 0x6e, 0x57, 0x6e, 0xeb, 0x9f, 0x6f, - 0x39, 0xe7, 0x8b, 0xe1, 0xe5, 0xf4, 0x5d, 0xb7, 0x4b, 0x8f, 0x8a, 0x66, 0x53, 0x81, 0x6e, 0xb7, 0x18, 0x7b, 0x75, - 0x32, 0xb3, 0xcc, 0x25, 0x5f, 0x7a, 0x57, 0x9b, 0x99, 0xc7, 0xf4, 0x7e, 0x33, 0xcd, 0x90, 0xc8, 0x17, 0x08, 0x99, - 0x0e, 0x87, 0xbb, 0x73, 0x2c, 0x8f, 0x0f, 0xdf, 0x3e, 0x7b, 0x32, 0x78, 0x82, 0x91, 0x5b, 0x56, 0x34, 0xc8, 0x3b, - 0x3e, 0xcc, 0xea, 0xd6, 0x6d, 0xe3, 0xe2, 0xf9, 0xf0, 0x17, 0xc8, 0x1b, 0x74, 0x3d, 0x34, 0x45, 0xb4, 0xca, 0xef, - 0x28, 0xfa, 0x44, 0xc9, 0x41, 0xc7, 0x13, 0xa8, 0x1d, 0x52, 0xe0, 0xbe, 0x7b, 0xc6, 0x41, 0xbf, 0x81, 0xa5, 0xf6, - 0xfb, 0xe7, 0x9f, 0x88, 0x47, 0x1a, 0xc6, 0xfb, 0xfb, 0x30, 0xfa, 0x23, 0x2e, 0x8b, 0x35, 0x9c, 0xae, 0x03, 0xf8, - 0xdc, 0x33, 0x7d, 0xfb, 0xba, 0xf3, 0x7d, 0x3f, 0xf0, 0xb6, 0xfc, 0x86, 0xbd, 0xe3, 0xde, 0xe5, 0xf0, 0xad, 0xff, - 0xec, 0x09, 0x88, 0x4e, 0x30, 0x2e, 0x9f, 0x31, 0x12, 0xb6, 0xa3, 0x18, 0xb5, 0x0a, 0x3f, 0xd7, 0x10, 0xa2, 0xf5, - 0x09, 0x19, 0xbb, 0x20, 0xfd, 0x83, 0x02, 0xf4, 0x13, 0x02, 0xab, 0x49, 0x6a, 0x14, 0x98, 0xc4, 0xb7, 0x35, 0x24, - 0x90, 0x82, 0x05, 0x42, 0x6f, 0xa0, 0xf8, 0x54, 0xf0, 0x77, 0xc3, 0xcf, 0x24, 0xf9, 0x2d, 0x6a, 0x3e, 0x86, 0xbf, - 0x61, 0x68, 0x26, 0xd5, 0x43, 0x5a, 0x47, 0x89, 0xf7, 0x93, 0xbf, 0x8f, 0xc2, 0x4a, 0xa8, 0x63, 0x21, 0x48, 0xc5, - 0x90, 0x0b, 0x71, 0xf1, 0x7c, 0x72, 0x5b, 0x8a, 0xf0, 0x8f, 0x09, 0x3e, 0x93, 0x0b, 0x4d, 0x3e, 0xa3, 0x27, 0x8d, - 0x7c, 0xff, 0x41, 0xbe, 0x2f, 0x3b, 0x35, 0x58, 0xd4, 0x43, 0x7e, 0x5b, 0xbb, 0xef, 0xcb, 0x29, 0x41, 0x8f, 0xec, - 0x07, 0x34, 0x05, 0x03, 0x35, 0x01, 0x29, 0x43, 0x70, 0x0b, 0x57, 0x7d, 0x4f, 0x15, 0xe4, 0xcb, 0xef, 0x7d, 0x16, - 0x32, 0x5c, 0x65, 0x41, 0x48, 0x72, 0xa9, 0x90, 0xc2, 0xc6, 0x6d, 0x3d, 0xf8, 0xac, 0x31, 0x49, 0x24, 0xe4, 0x94, - 0x80, 0x24, 0x69, 0x6f, 0x20, 0x49, 0xc4, 0xf4, 0x1f, 0xae, 0x93, 0xa6, 0x59, 0x49, 0xe9, 0x86, 0x38, 0x55, 0xaf, - 0x91, 0xe6, 0x2c, 0x78, 0xcf, 0x60, 0xe9, 0x48, 0xb1, 0xe2, 0x9d, 0x31, 0x18, 0xeb, 0x60, 0xa1, 0x3b, 0x59, 0xdc, - 0xaf, 0x92, 0x30, 0x8d, 0x44, 0x95, 0x2f, 0x42, 0xfe, 0xfc, 0x97, 0x12, 0x7f, 0xf4, 0x96, 0x06, 0x22, 0x10, 0xfc, - 0x00, 0xad, 0x07, 0xac, 0xf1, 0xe0, 0x27, 0x56, 0x97, 0x61, 0x5e, 0x65, 0x54, 0xde, 0x6c, 0xc7, 0xb6, 0x73, 0xa6, - 0xaa, 0x16, 0x7c, 0x16, 0x86, 0x16, 0xed, 0x6c, 0xd5, 0x9c, 0xdc, 0xe6, 0x0d, 0xbe, 0x33, 0x49, 0x22, 0xb5, 0x94, - 0x44, 0xda, 0xea, 0xfa, 0x74, 0xe9, 0x75, 0x8b, 0x0a, 0x1a, 0x23, 0x40, 0x2f, 0x49, 0x77, 0x95, 0x4f, 0x28, 0x5e, - 0x59, 0x0d, 0xab, 0xe1, 0xa5, 0x43, 0x11, 0xc6, 0xda, 0x9b, 0x2b, 0x79, 0x76, 0x07, 0xd6, 0x23, 0xb4, 0x76, 0x55, - 0xea, 0x10, 0xb6, 0x9f, 0xe8, 0x3d, 0xa7, 0x52, 0x7f, 0x03, 0xaa, 0xc0, 0xa9, 0xa3, 0xa1, 0x3e, 0x6a, 0xa7, 0x90, - 0xed, 0xdc, 0x5b, 0x12, 0x54, 0xae, 0xe4, 0xa6, 0x4a, 0x8b, 0x52, 0xca, 0x94, 0xaf, 0x65, 0xb6, 0xb2, 0xfb, 0x64, - 0x00, 0xf1, 0x6c, 0x50, 0x20, 0xb9, 0xa8, 0xad, 0xe6, 0x20, 0x7d, 0x34, 0x4b, 0x1c, 0x6b, 0x07, 0x85, 0x97, 0x55, - 0x60, 0xe6, 0x32, 0x97, 0xcb, 0x41, 0xc1, 0x72, 0xbd, 0xd5, 0x4c, 0x33, 0xd5, 0x17, 0xb9, 0xbd, 0xcd, 0x78, 0x99, - 0xfe, 0x9b, 0x25, 0x03, 0x1e, 0x5d, 0x3c, 0xf7, 0x03, 0x48, 0x93, 0xbc, 0x0e, 0x90, 0x04, 0x9b, 0x83, 0x5d, 0xec, - 0x30, 0x6c, 0x15, 0x2b, 0x7b, 0xf2, 0x74, 0xb9, 0x43, 0x53, 0x2e, 0x61, 0x24, 0x27, 0xe6, 0x52, 0xea, 0xfb, 0x92, - 0xea, 0x86, 0x82, 0x93, 0x4d, 0x13, 0x50, 0x0a, 0x68, 0xb7, 0xe0, 0xbf, 0xf0, 0xa9, 0xa1, 0xd3, 0x02, 0x2c, 0xb5, - 0xdd, 0x80, 0xff, 0x42, 0xbf, 0xd8, 0x3e, 0xa2, 0x7e, 0x60, 0x1e, 0xec, 0xcd, 0xda, 0xca, 0x18, 0x10, 0x91, 0xb8, - 0x82, 0x3c, 0x12, 0xfc, 0xa0, 0xd8, 0xd3, 0x65, 0xe2, 0xc0, 0x99, 0xe2, 0x62, 0x29, 0xb5, 0x99, 0x79, 0xed, 0xb7, - 0xd4, 0xc4, 0x9b, 0x28, 0x89, 0x0a, 0xdb, 0x21, 0x8d, 0x5e, 0x52, 0xc6, 0x54, 0xc1, 0x86, 0xe8, 0xbe, 0x6e, 0x82, - 0x29, 0xf0, 0xa6, 0xaa, 0x02, 0x22, 0xd4, 0x5e, 0x64, 0x79, 0x7e, 0xd3, 0x05, 0x56, 0x17, 0x7c, 0x6c, 0x4c, 0xb3, - 0x0b, 0x56, 0x72, 0x35, 0x93, 0x3e, 0xf3, 0x76, 0xa0, 0x85, 0xbc, 0xcb, 0xcb, 0xa2, 0x15, 0xba, 0x1e, 0x44, 0x0b, - 0x7f, 0xaf, 0x39, 0x1e, 0x3d, 0xdb, 0x56, 0x53, 0x9b, 0x7d, 0xad, 0xc5, 0x02, 0x19, 0x88, 0x86, 0xbe, 0x90, 0x33, - 0x0a, 0x77, 0x95, 0xe6, 0x6a, 0xb5, 0xaf, 0xca, 0x20, 0x81, 0x89, 0x20, 0x6b, 0x59, 0x78, 0x8f, 0xee, 0xd5, 0x23, - 0xcd, 0x2b, 0x09, 0x9e, 0xb9, 0xf8, 0x0b, 0x00, 0xa1, 0x3c, 0x49, 0xc8, 0x01, 0x39, 0x80, 0xbf, 0xa5, 0x28, 0x95, - 0x06, 0xf8, 0x67, 0x75, 0x39, 0xb6, 0xf5, 0xfd, 0x9d, 0x56, 0x31, 0xb8, 0xfe, 0x7c, 0xdd, 0xf5, 0xac, 0x1d, 0xe2, - 0x5c, 0xd9, 0xea, 0xb5, 0x65, 0x9a, 0xc7, 0x48, 0x5d, 0x03, 0x70, 0x27, 0xd2, 0x23, 0x10, 0xc9, 0x4c, 0x34, 0xc8, - 0xd9, 0x0b, 0x3e, 0x9e, 0x8a, 0xc7, 0xa4, 0xbd, 0xca, 0xf7, 0xcd, 0x85, 0x3e, 0x18, 0x63, 0xdf, 0x82, 0x06, 0xf1, - 0xd1, 0x6a, 0x6b, 0x05, 0x62, 0xbd, 0x55, 0xea, 0x43, 0x37, 0x46, 0x41, 0x07, 0x8f, 0xb8, 0x91, 0x0b, 0x8e, 0xed, - 0xae, 0xad, 0xa7, 0xf4, 0x15, 0x80, 0xb9, 0x0e, 0x54, 0x32, 0x0c, 0x52, 0xe7, 0x89, 0xc2, 0x24, 0x3f, 0x4f, 0x48, - 0x42, 0x44, 0x75, 0xb6, 0x1c, 0xa5, 0xdc, 0xb4, 0x80, 0xcb, 0x8c, 0x0c, 0x30, 0x9b, 0x34, 0xeb, 0x27, 0x97, 0x2f, - 0x41, 0x2a, 0x0d, 0x11, 0xdc, 0xb0, 0xbd, 0x64, 0x74, 0xeb, 0xa8, 0x1b, 0x54, 0x49, 0xe6, 0xfa, 0xcd, 0xed, 0x2c, - 0x52, 0xe6, 0xcd, 0x47, 0x18, 0x6b, 0xf2, 0x21, 0xac, 0x13, 0xfc, 0x36, 0x40, 0x25, 0x7d, 0x2a, 0xbc, 0x68, 0x04, - 0x10, 0xea, 0x3b, 0x55, 0xc6, 0xa7, 0xc2, 0xcb, 0x46, 0x5b, 0x96, 0x51, 0x0a, 0xd5, 0x05, 0xb3, 0x5b, 0xd3, 0x85, - 0xe8, 0x56, 0xd5, 0x40, 0x1b, 0xb8, 0x76, 0x1d, 0x28, 0xa0, 0xa1, 0xda, 0x95, 0x1b, 0x16, 0x80, 0xd5, 0x4c, 0x04, - 0x86, 0xcb, 0xbf, 0xcf, 0x5f, 0xa9, 0x18, 0x9e, 0x7e, 0x3f, 0xf4, 0xf6, 0xdb, 0x20, 0x1a, 0x6d, 0x2f, 0xd9, 0x2e, - 0x88, 0x46, 0xbb, 0xcb, 0x86, 0xd1, 0xef, 0xe7, 0xf4, 0xfb, 0x79, 0x03, 0x3a, 0x12, 0x61, 0xc2, 0xec, 0xf5, 0x1b, - 0xb5, 0x7c, 0xa5, 0xd6, 0xef, 0xd4, 0xf2, 0xa5, 0x1a, 0xde, 0xda, 0x93, 0x44, 0x10, 0x59, 0xaa, 0x9a, 0x07, 0x49, - 0x91, 0x6a, 0xe9, 0x72, 0x8c, 0x16, 0x23, 0x6a, 0x29, 0x6b, 0x8e, 0x75, 0x22, 0xed, 0x1c, 0x94, 0x0c, 0x70, 0xb4, - 0xb8, 0xaa, 0x31, 0xdd, 0xac, 0x68, 0x09, 0xc4, 0x08, 0x2b, 0xdb, 0x72, 0x71, 0x93, 0xfa, 0xe8, 0x9c, 0x7c, 0xdb, - 0x2a, 0xe5, 0xdb, 0x56, 0xf0, 0xfc, 0x2b, 0x0a, 0xe5, 0x92, 0x6b, 0xd7, 0xb2, 0x69, 0xa1, 0x14, 0xca, 0xb8, 0x06, - 0x5b, 0xfb, 0x26, 0x30, 0x64, 0x3e, 0x52, 0xd4, 0xd8, 0x5e, 0x34, 0xca, 0x21, 0xc8, 0xd6, 0xc1, 0xa8, 0x53, 0x16, - 0x2c, 0xbe, 0xdd, 0x21, 0x03, 0x19, 0xe8, 0xa8, 0x6a, 0xe3, 0xd5, 0xce, 0x4a, 0x7f, 0x58, 0x5e, 0x3c, 0x67, 0x89, - 0x95, 0x4e, 0x7e, 0x53, 0xa1, 0x3f, 0x08, 0xd1, 0x37, 0x65, 0xc3, 0xc1, 0x8b, 0x2e, 0xb6, 0x32, 0x20, 0xde, 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, 0xf3, 0x28, 0xd4, - 0x2c, 0x4f, 0x00, 0x0b, 0x5e, 0x98, 0x19, 0x2e, 0xcc, 0x0c, 0xc7, 0x21, 0x35, 0x4e, 0x0f, 0x7a, 0xaf, 0x73, 0xcf, - 0x2d, 0x77, 0xa3, 0xd3, 0x30, 0x6f, 0x47, 0x1b, 0xcc, 0xf1, 0x41, 0x38, 0x81, 0xf8, 0xc0, 0x12, 0x01, 0x7a, 0x34, - 0xac, 0x8e, 0x1a, 0x2a, 0x47, 0xf1, 0x65, 0x01, 0x48, 0x96, 0x04, 0x20, 0xb9, 0x57, 0xe3, 0x5c, 0x5a, 0x7e, 0x5d, - 0x25, 0x21, 0x47, 0x64, 0xbc, 0x94, 0x76, 0xf7, 0x84, 0x97, 0x23, 0x23, 0x34, 0x4f, 0x16, 0xa9, 0x97, 0xb3, 0x8c, - 0x8d, 0x11, 0xb8, 0x28, 0xf4, 0x9b, 0xaa, 0xdf, 0x4f, 0x4b, 0x2f, 0xa7, 0x76, 0x7e, 0x02, 0x7f, 0xcb, 0x53, 0x67, - 0x91, 0x23, 0xe4, 0xd5, 0xc8, 0x24, 0x2c, 0x2f, 0x95, 0x7a, 0xfa, 0x12, 0x66, 0x50, 0x77, 0x6f, 0x14, 0x80, 0x6b, - 0x91, 0x4b, 0xa7, 0xda, 0x12, 0xae, 0x4c, 0xb9, 0xc1, 0x3e, 0x0f, 0x79, 0x4e, 0x42, 0xa8, 0x44, 0x1e, 0x29, 0xac, - 0xfb, 0xf6, 0xc5, 0xf3, 0x89, 0xeb, 0xc3, 0x62, 0xa3, 0x11, 0x1c, 0x0e, 0x00, 0x73, 0x30, 0xf5, 0xa2, 0x01, 0x2f, - 0xd5, 0x9c, 0xf9, 0xe8, 0xe5, 0x84, 0x8d, 0x01, 0x6a, 0x8a, 0x81, 0x53, 0xd6, 0x33, 0xf9, 0xc8, 0xf8, 0x96, 0xf9, - 0x7e, 0x80, 0xef, 0xd6, 0x85, 0x84, 0x7c, 0x50, 0xa8, 0x04, 0x99, 0x42, 0x25, 0x48, 0x0c, 0x2a, 0x41, 0x6c, 0x50, - 0x09, 0x36, 0x0d, 0x5f, 0x4b, 0xe5, 0x6d, 0x04, 0x1c, 0x11, 0x3e, 0xf4, 0x2c, 0x6c, 0xac, 0x50, 0x3c, 0x1b, 0xb3, - 0x31, 0x2b, 0xd4, 0xce, 0x93, 0xcb, 0xa9, 0xd8, 0x59, 0x8c, 0x75, 0x13, 0x59, 0x26, 0x5e, 0x48, 0xd0, 0x71, 0xce, - 0x85, 0x44, 0x5d, 0xfd, 0xdc, 0x7b, 0x49, 0xc6, 0x92, 0x79, 0x43, 0xa3, 0x06, 0xf3, 0xb2, 0xeb, 0x00, 0xa6, 0x25, - 0xdf, 0x16, 0x34, 0x98, 0x4e, 0x95, 0x47, 0xa4, 0x49, 0x50, 0x3b, 0x97, 0x49, 0x91, 0x13, 0xc2, 0x24, 0xe8, 0x95, - 0xe0, 0x37, 0x12, 0xda, 0xff, 0xab, 0x9e, 0xef, 0x80, 0xc1, 0x44, 0xab, 0xe4, 0x0b, 0x58, 0x2d, 0x73, 0xfe, 0x52, - 0x7a, 0x62, 0x23, 0xfe, 0x62, 0x99, 0xc6, 0xa3, 0x2f, 0x6c, 0x88, 0x78, 0x56, 0x2f, 0xd1, 0xb4, 0x04, 0x75, 0x80, - 0x47, 0xf4, 0xd7, 0xe8, 0x8b, 0xe1, 0x4d, 0xe9, 0x6a, 0xa4, 0xae, 0xd9, 0x39, 0xe7, 0x5f, 0x6a, 0x43, 0x84, 0x8c, - 0x69, 0x53, 0x20, 0x19, 0x10, 0x48, 0x32, 0x10, 0x00, 0x98, 0x9a, 0xce, 0xec, 0x15, 0x40, 0x34, 0x10, 0xc0, 0xe3, - 0xbc, 0xe3, 0xf1, 0x23, 0xfd, 0x55, 0x1c, 0xf7, 0x4e, 0xd3, 0xb0, 0xfd, 0x17, 0xa0, 0x29, 0x86, 0x72, 0x3c, 0xdf, - 0x29, 0x48, 0xf6, 0x28, 0x65, 0xe9, 0xaa, 0x89, 0xec, 0x50, 0xac, 0x4f, 0x73, 0xca, 0x42, 0xda, 0x96, 0x63, 0xb4, - 0xc5, 0xfa, 0x31, 0xf2, 0xde, 0xdc, 0xa8, 0xc8, 0x07, 0x3d, 0xb8, 0xbd, 0xbd, 0x7d, 0xdd, 0x63, 0x36, 0xc9, 0x8a, - 0x45, 0xae, 0x22, 0x4e, 0x9c, 0xd6, 0x21, 0x07, 0x0c, 0xc8, 0x49, 0x08, 0x4c, 0x63, 0x5c, 0x2a, 0xd0, 0x41, 0xc9, - 0x72, 0x5e, 0x03, 0xb5, 0x2c, 0x22, 0x6b, 0x80, 0xa8, 0xa6, 0xf9, 0x57, 0x0d, 0xf9, 0x49, 0xd5, 0x9c, 0x52, 0xa8, - 0x7d, 0xc5, 0xc3, 0xea, 0xf4, 0x89, 0x55, 0x9b, 0x18, 0xeb, 0x5f, 0x6b, 0x4f, 0xd0, 0x56, 0xd2, 0x40, 0x7c, 0xe7, - 0xeb, 0xf4, 0x8e, 0x42, 0x77, 0x9c, 0x99, 0x78, 0xaa, 0x02, 0x63, 0xdf, 0xda, 0x11, 0x14, 0x0e, 0x4d, 0xd7, 0x01, - 0x87, 0x69, 0x74, 0xc2, 0xe2, 0x9f, 0xd2, 0x71, 0xf2, 0xa2, 0x56, 0x88, 0x24, 0xff, 0x10, 0x2e, 0x0c, 0x89, 0x05, - 0x79, 0x49, 0xa8, 0x23, 0x32, 0x62, 0x35, 0x2a, 0xd6, 0x42, 0x45, 0xc5, 0x29, 0x1e, 0x6f, 0x15, 0x14, 0x97, 0xa2, - 0x54, 0x29, 0x15, 0xb9, 0x51, 0x29, 0x20, 0x96, 0x0d, 0xbc, 0x5b, 0xc0, 0x01, 0x10, 0x74, 0x96, 0xbb, 0xb5, 0xed, - 0x6e, 0x23, 0xf3, 0x99, 0x69, 0x9e, 0x56, 0x1f, 0xd4, 0xdf, 0xef, 0x97, 0x18, 0x5b, 0xe3, 0xe9, 0xef, 0xdb, 0xb4, - 0xe0, 0xe6, 0x6f, 0x18, 0xa2, 0x3b, 0x40, 0xc4, 0x2c, 0xed, 0xa1, 0x90, 0x05, 0x13, 0x96, 0xa1, 0x2a, 0x4f, 0x39, - 0xea, 0xe5, 0x93, 0x5b, 0x80, 0x50, 0x43, 0xbf, 0x36, 0x3a, 0xd5, 0x55, 0x09, 0xc2, 0xf7, 0x5d, 0xa1, 0x1e, 0x9b, - 0x03, 0x9e, 0x0c, 0x80, 0xbf, 0x22, 0xaf, 0xf5, 0xd8, 0xfe, 0x41, 0x6f, 0xd4, 0x1b, 0x20, 0x88, 0xce, 0x79, 0xe1, - 0x1f, 0x71, 0xae, 0x53, 0x7f, 0xc6, 0x85, 0x20, 0xbe, 0xf5, 0x24, 0xbc, 0x17, 0x67, 0x69, 0x1c, 0x9c, 0xf5, 0x06, - 0xe6, 0x22, 0x50, 0x9c, 0xa5, 0xf9, 0x19, 0x88, 0xe5, 0x88, 0x89, 0x58, 0xb3, 0x3b, 0x80, 0x09, 0x2c, 0x75, 0x1c, - 0xb2, 0xea, 0xd8, 0x7e, 0xff, 0xcd, 0xc8, 0x90, 0xa5, 0x23, 0x0c, 0x8c, 0xfe, 0x5d, 0x81, 0x00, 0x05, 0xcb, 0xcc, - 0xf6, 0x60, 0xd2, 0xd5, 0x9e, 0xd5, 0xf3, 0x66, 0x93, 0x77, 0xf5, 0x8e, 0xd5, 0xb4, 0x9c, 0x9a, 0x56, 0x59, 0x4d, - 0x9b, 0xe4, 0x50, 0x33, 0xd1, 0xef, 0x6b, 0x50, 0xd4, 0x7c, 0x0e, 0x60, 0x6c, 0x98, 0xfc, 0x66, 0x56, 0xcd, 0xfb, - 0x7d, 0x4f, 0x3e, 0x82, 0x5f, 0xc8, 0x56, 0xe6, 0xd6, 0x58, 0x3e, 0x7d, 0x4d, 0x24, 0x66, 0x06, 0xe6, 0xe8, 0xee, - 0x08, 0xdf, 0xeb, 0x46, 0x78, 0x1d, 0x73, 0x85, 0xcd, 0xc4, 0xf4, 0x0d, 0x0c, 0x9e, 0x27, 0x7c, 0x70, 0x91, 0xa3, - 0xbf, 0x91, 0xc3, 0x4c, 0x61, 0x41, 0xce, 0xfd, 0xc9, 0x1b, 0xc4, 0x4b, 0x46, 0x78, 0x07, 0x9d, 0x4e, 0x78, 0x90, - 0xfd, 0xfe, 0x0a, 0x3a, 0xb3, 0x95, 0x4a, 0xd9, 0xaa, 0xa8, 0x4c, 0xd7, 0x75, 0x51, 0x56, 0xd0, 0xb1, 0xf4, 0xf3, - 0x56, 0xc8, 0xcc, 0xfa, 0x99, 0x05, 0xf7, 0xb4, 0x92, 0x00, 0x53, 0xb6, 0x6d, 0xa2, 0x36, 0xf0, 0xb2, 0x2e, 0x3e, - 0x17, 0x78, 0x74, 0xd6, 0x5e, 0x6f, 0x84, 0xda, 0xe7, 0x7c, 0xb4, 0x2e, 0xd6, 0x1e, 0xf8, 0xc1, 0xcc, 0xd2, 0xb9, - 0x22, 0xce, 0xc8, 0xfd, 0xd1, 0xe7, 0x22, 0xcd, 0x29, 0x0f, 0x70, 0x1f, 0x8a, 0xb9, 0xfd, 0x16, 0x48, 0x3f, 0xf4, - 0x16, 0xc8, 0x3e, 0x3a, 0xe7, 0xe4, 0x0d, 0x20, 0xd2, 0x21, 0x0c, 0x6e, 0x45, 0x82, 0x8e, 0x55, 0xc3, 0x5b, 0x0b, - 0xec, 0xb4, 0x97, 0xc6, 0xbd, 0x34, 0x3f, 0x4b, 0xfb, 0x7d, 0x83, 0x9a, 0x99, 0x22, 0x1c, 0x3c, 0xce, 0xc8, 0x45, - 0xd2, 0x82, 0x2d, 0xa5, 0xfd, 0x57, 0x03, 0x47, 0x10, 0xf2, 0xf7, 0x3f, 0x84, 0xf7, 0x04, 0x20, 0x36, 0x69, 0x03, - 0xae, 0x7a, 0x4c, 0x47, 0x63, 0x4b, 0xa2, 0x56, 0x9d, 0x0d, 0x90, 0x38, 0x55, 0x5a, 0x4f, 0xb9, 0x59, 0x53, 0x18, - 0xa4, 0xca, 0x42, 0xfd, 0xc6, 0x7a, 0x32, 0x59, 0xe5, 0x22, 0x23, 0x8e, 0xca, 0xf4, 0xa5, 0x66, 0x04, 0xd3, 0xa5, - 0x9f, 0x2f, 0x60, 0xc9, 0xc6, 0x1f, 0x71, 0xf2, 0x96, 0x80, 0x63, 0x3b, 0x6b, 0x57, 0xd5, 0x2e, 0xc7, 0xad, 0xdd, - 0x1c, 0xe0, 0x7b, 0xbd, 0xd1, 0x68, 0xa4, 0x9d, 0xe3, 0x04, 0x0c, 0x55, 0x4f, 0x2d, 0x85, 0x1e, 0xab, 0x15, 0xa0, - 0x6e, 0x47, 0x2e, 0xb3, 0x64, 0x30, 0x5f, 0x18, 0xc7, 0xaf, 0xcc, 0x47, 0x1f, 0x2f, 0x95, 0xb5, 0xeb, 0x88, 0xaf, - 0xff, 0x20, 0xab, 0xf5, 0x2d, 0xef, 0xaa, 0x26, 0xe0, 0x8b, 0x2a, 0xa0, 0xf4, 0x1b, 0xde, 0x93, 0xbd, 0x8b, 0xaf, - 0xdd, 0x60, 0x97, 0x7c, 0xcb, 0x5b, 0xd4, 0x79, 0xbe, 0x72, 0x70, 0xa3, 0x4a, 0xb7, 0xf7, 0x92, 0x05, 0xae, 0xbd, - 0xa3, 0xa6, 0xb1, 0x9e, 0xf9, 0xd1, 0xc3, 0x22, 0x64, 0x3b, 0x1f, 0x7b, 0x5f, 0x35, 0x4f, 0xcf, 0x1a, 0x7a, 0x93, - 0x1a, 0xfa, 0xd8, 0x8b, 0xb2, 0x7d, 0x6a, 0x1a, 0xd1, 0x6b, 0xd8, 0xd0, 0xc7, 0xde, 0x92, 0x93, 0x43, 0x22, 0xc0, - 0xa9, 0x31, 0x7f, 0x7c, 0x38, 0x9d, 0xe1, 0xef, 0x18, 0x50, 0x09, 0xc4, 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, 0x24, 0x77, 0xa5, 0x37, 0xb0, 0x02, 0x69, 0x5b, 0x54, 0x1f, 0xca, - 0xa5, 0xb7, 0x53, 0x87, 0x76, 0xe5, 0x4f, 0xf2, 0xc3, 0xa1, 0x18, 0x99, 0x63, 0x1c, 0xc0, 0x4d, 0x0a, 0x25, 0x47, - 0xc9, 0x5a, 0x82, 0xe8, 0x94, 0xc6, 0x53, 0x59, 0xaf, 0xad, 0x88, 0xbc, 0x1a, 0x71, 0x1e, 0x82, 0x1f, 0x3d, 0x50, - 0x8b, 0xbf, 0xd0, 0x82, 0xd8, 0x63, 0x9f, 0x2a, 0xa5, 0x17, 0xbc, 0x2a, 0x20, 0x44, 0xec, 0xef, 0x06, 0xda, 0x41, - 0x09, 0x0e, 0x25, 0xdc, 0x07, 0x84, 0x85, 0x7e, 0xed, 0xe5, 0x33, 0x19, 0xa3, 0xdc, 0x1b, 0x54, 0x73, 0x06, 0x30, - 0x95, 0x3e, 0x03, 0xbf, 0x4b, 0x80, 0x3a, 0xc5, 0xa7, 0xe8, 0x54, 0x6f, 0x1e, 0x36, 0x5d, 0x9f, 0x96, 0x28, 0x8a, - 0xe8, 0xce, 0xcf, 0xc7, 0x80, 0xd8, 0xd9, 0xb5, 0x19, 0x69, 0xd7, 0x7e, 0x83, 0x06, 0x2b, 0x25, 0x89, 0x76, 0x4e, - 0x09, 0xbb, 0x9d, 0x8f, 0x6c, 0xe9, 0x47, 0x29, 0x10, 0x73, 0xc7, 0x89, 0x44, 0xf6, 0x60, 0x23, 0x27, 0x70, 0x8b, - 0xf6, 0x8e, 0x0e, 0x40, 0xe5, 0x46, 0x41, 0x7e, 0x35, 0x47, 0x72, 0xc7, 0x77, 0xbd, 0xef, 0x06, 0xf5, 0xe0, 0xbb, - 0xde, 0x59, 0x4a, 0x72, 0x47, 0x78, 0xa6, 0xa6, 0x84, 0x88, 0xcf, 0xbe, 0x1b, 0xe4, 0x03, 0x3c, 0x4b, 0xb4, 0x48, - 0x8b, 0x84, 0x6a, 0x75, 0x8d, 0x9b, 0xf0, 0x22, 0x91, 0xdc, 0x43, 0xbb, 0xce, 0x23, 0x62, 0x01, 0xc8, 0x58, 0x7c, - 0x36, 0x6f, 0x28, 0xd4, 0xdd, 0xc4, 0x6c, 0xd1, 0x5d, 0x16, 0xfb, 0xfd, 0x6d, 0x9e, 0xd6, 0x3d, 0x1d, 0x1f, 0x83, - 0x2f, 0x48, 0x35, 0x01, 0x1e, 0xed, 0xaf, 0xcd, 0xf1, 0xea, 0xd5, 0xe6, 0x48, 0x59, 0xa8, 0x12, 0xf5, 0x5b, 0xac, - 0x66, 0x3d, 0x84, 0xe1, 0xce, 0x32, 0x63, 0x6d, 0x2f, 0x78, 0x25, 0x67, 0x55, 0x6c, 0x97, 0xe3, 0x2b, 0x96, 0xda, - 0x4a, 0xa2, 0x72, 0xb4, 0x1e, 0x6b, 0x53, 0x8c, 0xfc, 0x4a, 0x21, 0x51, 0x16, 0x1d, 0x5b, 0x0b, 0x05, 0xc4, 0x0b, - 0xd0, 0x97, 0xec, 0x4c, 0x03, 0xac, 0x37, 0x7a, 0x15, 0x11, 0x5a, 0x3e, 0x52, 0xe1, 0x4d, 0x6e, 0xaa, 0xcc, 0xca, - 0x66, 0xd1, 0xee, 0xa7, 0x8a, 0x57, 0x08, 0x56, 0x6f, 0xd4, 0x1e, 0x05, 0xa8, 0x3d, 0xb4, 0x50, 0x06, 0x90, 0xd2, - 0x34, 0x03, 0x40, 0x06, 0x00, 0x99, 0x2a, 0xe2, 0x33, 0x01, 0x2a, 0x6d, 0x75, 0xa3, 0xc0, 0x89, 0xf4, 0x1a, 0x68, - 0x16, 0x58, 0xe9, 0x23, 0x05, 0x19, 0x2c, 0xb6, 0x08, 0xc0, 0xca, 0x91, 0x33, 0x4c, 0x63, 0xc8, 0x36, 0x9a, 0xb8, - 0x24, 0xcd, 0xef, 0xc3, 0x2c, 0x95, 0x78, 0x12, 0x3f, 0xc8, 0x1a, 0x23, 0x00, 0x90, 0xbe, 0x4f, 0x2f, 0x8a, 0x2c, - 0x26, 0x1c, 0x38, 0xeb, 0xa9, 0x83, 0xa2, 0x26, 0xe7, 0x5a, 0xd3, 0xea, 0x59, 0x6d, 0xf2, 0x90, 0x05, 0x3a, 0x7b, - 0x30, 0x26, 0xb5, 0x7c, 0xcf, 0x23, 0xfb, 0x2b, 0xc7, 0x33, 0xc2, 0x77, 0xdd, 0xc1, 0xa9, 0xff, 0x6e, 0x6a, 0x60, - 0x62, 0x4a, 0x00, 0x36, 0x06, 0x47, 0x13, 0xe2, 0x77, 0x3a, 0x26, 0x53, 0x9b, 0x14, 0x81, 0xc0, 0x43, 0xf0, 0x0a, - 0x9e, 0x1b, 0x2e, 0xb7, 0xdc, 0xd8, 0x59, 0xe4, 0x69, 0x02, 0x70, 0xe2, 0x05, 0xdf, 0x02, 0x1c, 0xa7, 0x5e, 0x15, - 0xb2, 0x67, 0xcf, 0xc5, 0x74, 0x36, 0x0f, 0x1e, 0x12, 0xda, 0xbf, 0x98, 0xf0, 0x9b, 0xee, 0x2a, 0xb9, 0x32, 0xb5, - 0xee, 0x4d, 0x74, 0x95, 0xcb, 0x9d, 0x3e, 0xad, 0x38, 0x86, 0x39, 0x83, 0x55, 0x40, 0xce, 0xd9, 0x90, 0xbf, 0x38, - 0x07, 0xc0, 0x96, 0x95, 0xf0, 0x22, 0xfe, 0x22, 0x94, 0xd5, 0x02, 0xb8, 0x47, 0xce, 0x23, 0xf3, 0xcb, 0x57, 0xdb, - 0xa1, 0x9c, 0x53, 0x14, 0xc6, 0x72, 0x6a, 0x5a, 0x52, 0x9c, 0x0e, 0x3d, 0x05, 0x93, 0xa9, 0x2d, 0x7f, 0x6f, 0x13, - 0x97, 0xd9, 0x9b, 0x49, 0x38, 0x5f, 0x47, 0xb6, 0xad, 0x55, 0xf7, 0xd0, 0x0d, 0xc1, 0xa0, 0x8f, 0x11, 0xb4, 0x6c, - 0xae, 0xef, 0xd6, 0x83, 0x81, 0xc2, 0xf6, 0xad, 0xe9, 0xa6, 0x45, 0xa7, 0x38, 0xe0, 0xcc, 0x5a, 0xd7, 0xa8, 0x54, - 0x15, 0x87, 0x5e, 0xf2, 0x6e, 0x59, 0x95, 0x5d, 0x96, 0x5e, 0x08, 0x52, 0xa3, 0xae, 0x22, 0x44, 0x4a, 0xc5, 0x0e, - 0xef, 0xc9, 0xaf, 0x81, 0x89, 0x67, 0x56, 0x8e, 0xd2, 0x78, 0x0e, 0x30, 0x41, 0x0a, 0x7d, 0x53, 0x7e, 0x05, 0xb8, - 0xa1, 0x8b, 0x28, 0xcc, 0xde, 0xc6, 0x55, 0x50, 0x5b, 0x4d, 0xbf, 0x77, 0x70, 0x62, 0xcf, 0xeb, 0x7e, 0x3f, 0x25, - 0x1a, 0x3f, 0x0c, 0xbd, 0xc0, 0xbf, 0xc7, 0xd3, 0x7d, 0x13, 0xa4, 0xe6, 0x95, 0x07, 0x78, 0x45, 0x97, 0x5b, 0x9b, - 0x72, 0x45, 0xe3, 0x62, 0x5e, 0x23, 0x22, 0x7c, 0xea, 0x28, 0xb6, 0xdb, 0xfc, 0x38, 0xb5, 0x31, 0x18, 0x84, 0x70, - 0xdf, 0xca, 0xf8, 0x7d, 0xe2, 0xe5, 0xb3, 0x68, 0x0e, 0x8a, 0xd2, 0x4c, 0x93, 0x84, 0x14, 0xd2, 0x4b, 0x80, 0x3e, - 0x1a, 0x84, 0x5a, 0x5d, 0xf9, 0x47, 0xe2, 0xa5, 0x6a, 0x5a, 0x9b, 0xa7, 0x58, 0xa3, 0x40, 0xcc, 0xa2, 0x79, 0xc3, - 0x32, 0x3a, 0x24, 0xd5, 0xe5, 0xd2, 0x34, 0xe3, 0x0f, 0xab, 0x19, 0xaa, 0x15, 0x47, 0x4d, 0x50, 0xa3, 0x74, 0x03, - 0x17, 0xc0, 0xbf, 0xd3, 0x1d, 0x47, 0x35, 0x8a, 0x14, 0x0d, 0xf8, 0x04, 0x81, 0x61, 0xcd, 0xe6, 0x09, 0x6b, 0x4d, - 0x5d, 0x33, 0xfa, 0x7d, 0x19, 0x27, 0x64, 0x92, 0x90, 0x9c, 0x0f, 0x97, 0xeb, 0x47, 0x52, 0x5d, 0x00, 0xa9, 0x72, - 0xc5, 0x66, 0xbd, 0xde, 0x1c, 0x30, 0x7a, 0x61, 0xfd, 0xc2, 0xc6, 0x15, 0x9c, 0x5f, 0x12, 0xe6, 0xae, 0xfa, 0x11, - 0x66, 0x19, 0x54, 0x01, 0x69, 0x7e, 0x2c, 0x78, 0xf3, 0xdc, 0x05, 0xa2, 0x7e, 0x33, 0x52, 0x17, 0x94, 0x59, 0x3a, - 0xb7, 0x88, 0x40, 0xc0, 0x6b, 0x58, 0x3d, 0x81, 0x64, 0x5f, 0x3e, 0xf6, 0x69, 0x46, 0x81, 0xea, 0x08, 0x40, 0xd9, - 0xac, 0x1f, 0xc2, 0xfe, 0x01, 0xe1, 0x84, 0xfa, 0x9b, 0x37, 0x72, 0xd6, 0x90, 0x3c, 0x90, 0x6a, 0xc2, 0x63, 0x38, - 0x35, 0x16, 0xf8, 0xd2, 0xa2, 0x37, 0x15, 0xbc, 0x26, 0x38, 0xee, 0x05, 0x5a, 0xfb, 0x16, 0x70, 0x84, 0x08, 0x2e, - 0x43, 0x13, 0xa7, 0xbd, 0x5d, 0x2f, 0x40, 0x42, 0x73, 0x0b, 0xe7, 0xfa, 0xda, 0x05, 0x2d, 0x4e, 0x91, 0x93, 0x45, - 0x17, 0x18, 0xe8, 0x82, 0xcc, 0x1b, 0xff, 0xaa, 0x60, 0xe5, 0x02, 0x64, 0x2f, 0x15, 0x2b, 0x89, 0xd8, 0x76, 0xea, - 0x8f, 0x52, 0xd9, 0x6f, 0xcf, 0xac, 0x09, 0xfc, 0x2a, 0xb1, 0x5f, 0x22, 0x93, 0x6f, 0x7a, 0x6c, 0xf2, 0x95, 0xb1, - 0xd0, 0xa9, 0x65, 0x70, 0x4e, 0x8f, 0x0c, 0xce, 0xbd, 0x9d, 0x55, 0x9b, 0x10, 0x86, 0x82, 0x24, 0xd0, 0x74, 0xe9, - 0x61, 0xdd, 0xf4, 0xe7, 0x27, 0x2d, 0x7e, 0xad, 0xda, 0xb7, 0xee, 0xc7, 0x21, 0x76, 0xf1, 0xab, 0xc4, 0x33, 0xec, - 0xa3, 0x3e, 0x70, 0x80, 0xc9, 0x88, 0x89, 0xcb, 0x7e, 0x1f, 0x0a, 0x9b, 0x8d, 0xe7, 0xa3, 0xba, 0xf8, 0xb9, 0x78, - 0x00, 0x28, 0x87, 0x0a, 0xec, 0x72, 0x28, 0x43, 0x19, 0xb1, 0xa9, 0x2d, 0xf7, 0xfc, 0xfe, 0x2a, 0xcc, 0x41, 0xde, - 0xd1, 0x98, 0x38, 0x67, 0x20, 0x86, 0xc1, 0xd7, 0xbf, 0x7b, 0xb2, 0x4f, 0x9b, 0xef, 0xce, 0xe0, 0xbb, 0xa3, 0xb3, - 0x0f, 0xc8, 0x71, 0x73, 0xb6, 0x2e, 0x8b, 0xfb, 0x34, 0x16, 0x67, 0xdf, 0x41, 0xea, 0x77, 0x67, 0x45, 0x79, 0xf6, - 0x9d, 0xaa, 0xcc, 0x77, 0x67, 0xb4, 0xe0, 0x46, 0xbf, 0x5b, 0x13, 0xef, 0x9f, 0x95, 0xa6, 0x3d, 0x5b, 0x42, 0x38, - 0x96, 0x56, 0x3f, 0x82, 0x12, 0x51, 0x91, 0xa2, 0xca, 0x50, 0x56, 0x6b, 0xc7, 0x79, 0x9f, 0x68, 0x78, 0x6c, 0x9a, - 0x90, 0xb8, 0x5a, 0xc2, 0x3a, 0xd4, 0xb3, 0xd3, 0x26, 0xd9, 0x71, 0x1e, 0xa8, 0x03, 0x22, 0xe7, 0x2f, 0xf2, 0xd1, - 0x96, 0xbe, 0x06, 0xdf, 0x3a, 0x1c, 0xf2, 0xd1, 0xce, 0xfc, 0xf4, 0xc9, 0x5a, 0x29, 0x83, 0x8d, 0x14, 0xa3, 0x10, - 0x12, 0xc5, 0x6d, 0x7b, 0x0c, 0x80, 0xff, 0xfd, 0xc3, 0x81, 0x7e, 0xef, 0xe4, 0x6f, 0xb5, 0x5b, 0x5a, 0xf5, 0xfc, - 0xd0, 0x22, 0xcc, 0x78, 0x5d, 0x1b, 0x76, 0xb6, 0xbd, 0x04, 0x94, 0xde, 0x37, 0x0d, 0x6a, 0x8a, 0xe8, 0x27, 0xac, - 0x26, 0x56, 0x71, 0x58, 0x90, 0x12, 0x87, 0x18, 0x8e, 0xd1, 0x0e, 0x3d, 0x4e, 0x17, 0x35, 0x4f, 0xee, 0x3b, 0x64, - 0xdc, 0xfa, 0x3e, 0x20, 0xb9, 0x14, 0xce, 0x3f, 0x78, 0xa1, 0xc1, 0x44, 0x2f, 0xf2, 0xaa, 0xc8, 0xc4, 0x48, 0xd0, - 0x28, 0xbf, 0x25, 0x71, 0xe6, 0x0c, 0x6b, 0x71, 0xa6, 0x10, 0xc2, 0x42, 0x42, 0xe5, 0x2e, 0x4a, 0x4a, 0x0f, 0xce, - 0x9e, 0xec, 0xcb, 0xe6, 0x77, 0xc2, 0x84, 0x18, 0x2d, 0x80, 0x06, 0x67, 0xd7, 0x2e, 0xef, 0x21, 0x2c, 0x73, 0xef, - 0xf7, 0xb7, 0x77, 0x79, 0x01, 0x71, 0x99, 0x67, 0x52, 0xb1, 0x5a, 0x9e, 0x01, 0x4d, 0x9e, 0x88, 0xcf, 0xc2, 0x4a, - 0x4e, 0x83, 0xaa, 0xa3, 0x58, 0xbd, 0x8d, 0xe7, 0x1e, 0xf0, 0x7a, 0xbf, 0x4f, 0x80, 0xc0, 0xdd, 0x67, 0x6f, 0x94, - 0x5b, 0x2a, 0xe9, 0x91, 0xe7, 0x18, 0x22, 0x99, 0x00, 0xaf, 0x33, 0x04, 0x47, 0x0a, 0xab, 0xe7, 0x26, 0xc8, 0x3f, - 0xbe, 0x3e, 0xa1, 0xf8, 0xa2, 0x79, 0x14, 0x35, 0x2c, 0x64, 0x09, 0x1c, 0x0f, 0xc9, 0x2c, 0x9b, 0x23, 0x35, 0x79, - 0xda, 0x9e, 0x22, 0x1d, 0x9d, 0x58, 0xe2, 0xb7, 0x35, 0xa9, 0x5e, 0xa4, 0xc2, 0x2e, 0x69, 0x67, 0x2b, 0x73, 0x2f, - 0x84, 0xa1, 0x4a, 0xb8, 0xf7, 0xba, 0x9e, 0x85, 0x72, 0x53, 0xb4, 0x2a, 0x66, 0x0f, 0x53, 0x62, 0x86, 0x29, 0xd6, - 0x5f, 0xd8, 0xf0, 0x9b, 0xc4, 0x8b, 0xc1, 0x70, 0xbd, 0xe4, 0xe5, 0x6c, 0x63, 0x16, 0xc2, 0xe1, 0xb0, 0x99, 0x14, - 0xb3, 0x25, 0xc4, 0xb6, 0x2e, 0xe7, 0x87, 0x43, 0x57, 0xcb, 0xd6, 0xc2, 0x83, 0x87, 0xaa, 0x85, 0x9b, 0x86, 0xe5, - 0xf0, 0x33, 0x99, 0xc5, 0xd8, 0xbe, 0xc6, 0x67, 0xf6, 0xe7, 0x8b, 0xee, 0x59, 0x82, 0x8c, 0x1b, 0x6b, 0xe0, 0x1a, - 0x9b, 0xb5, 0x3b, 0x5c, 0x8d, 0x80, 0xe4, 0x71, 0x37, 0xfa, 0xbb, 0xb2, 0x93, 0x9c, 0x04, 0x09, 0xa3, 0x15, 0xc2, - 0xef, 0xbe, 0xf1, 0x27, 0x5a, 0xec, 0x41, 0xbb, 0x8d, 0x2d, 0x21, 0xaa, 0x69, 0xcf, 0xe5, 0x4a, 0xb1, 0x34, 0x6f, - 0xa5, 0x0d, 0x99, 0x0f, 0xeb, 0x73, 0xdf, 0xc8, 0x81, 0x82, 0x31, 0xe2, 0xa9, 0x75, 0x10, 0xcd, 0xe6, 0xc0, 0x7d, - 0x81, 0xe6, 0x11, 0x9e, 0x5a, 0x90, 0xa0, 0xcc, 0xda, 0xb0, 0x9f, 0x24, 0x27, 0xcb, 0xe3, 0xf0, 0x2d, 0xfc, 0xcb, - 0x67, 0xd8, 0x24, 0xa6, 0x28, 0x1e, 0x7f, 0xab, 0x14, 0xff, 0x1d, 0x5b, 0x10, 0xc1, 0xda, 0x8d, 0xa8, 0x0d, 0x7f, - 0xc3, 0xbf, 0x85, 0x7d, 0x84, 0xfd, 0x86, 0x26, 0x08, 0x03, 0x58, 0x7f, 0x26, 0x10, 0x17, 0x16, 0x82, 0x04, 0x7f, - 0xab, 0x24, 0xff, 0x9c, 0xf0, 0xd9, 0xa2, 0x04, 0xb2, 0x3a, 0x8c, 0xe2, 0x13, 0x8a, 0x89, 0x42, 0x18, 0x6e, 0x09, - 0xbd, 0xa3, 0xff, 0x46, 0x94, 0x64, 0x93, 0xdc, 0x8a, 0xf5, 0x40, 0x26, 0x49, 0x30, 0xc1, 0xca, 0x0b, 0xe5, 0x4b, - 0xf7, 0x42, 0xa9, 0xb5, 0x16, 0xb4, 0x7e, 0xf9, 0x93, 0xc4, 0x33, 0xa0, 0x7b, 0x20, 0x63, 0xd0, 0x6d, 0x44, 0x35, - 0xc9, 0x31, 0x7d, 0x94, 0xce, 0x33, 0x50, 0x01, 0x9d, 0xad, 0xb3, 0xb0, 0x5e, 0x16, 0xe5, 0xaa, 0x15, 0x1e, 0x2a, - 0x4b, 0x1f, 0xa9, 0xc7, 0x98, 0x17, 0xe6, 0xc9, 0x89, 0x7c, 0xf0, 0x08, 0xd0, 0xf0, 0x28, 0x4f, 0xab, 0x8e, 0xd2, - 0xfa, 0x81, 0x65, 0xc0, 0x08, 0x9c, 0x28, 0x03, 0x1e, 0x61, 0x19, 0x98, 0xa7, 0x5d, 0x86, 0x1a, 0xc4, 0x1a, 0x55, - 0x57, 0x6a, 0x83, 0x39, 0x51, 0x94, 0x7c, 0x8a, 0xa5, 0x15, 0xc6, 0xd0, 0xd4, 0x95, 0x47, 0xd6, 0x4b, 0x4e, 0xd8, - 0x93, 0xdd, 0x40, 0xba, 0x85, 0x8d, 0x02, 0x17, 0x74, 0x2d, 0x4b, 0x94, 0x8b, 0x6e, 0x19, 0x51, 0x26, 0x42, 0xea, - 0x67, 0x0f, 0x67, 0x5a, 0xed, 0x37, 0x76, 0xd2, 0xbe, 0x3d, 0x52, 0xf4, 0x82, 0x81, 0xf8, 0xb4, 0x47, 0x4a, 0x3d, - 0x6b, 0xe4, 0x32, 0xb0, 0xa5, 0x4b, 0x55, 0xcf, 0x7f, 0x83, 0xf2, 0x1d, 0xcc, 0x8c, 0xb3, 0xd9, 0xef, 0x7a, 0x73, - 0x7b, 0xb2, 0xaf, 0x9b, 0xdf, 0x59, 0xaf, 0x07, 0x5b, 0x83, 0x4c, 0x7c, 0xa9, 0xa8, 0xa7, 0xac, 0x42, 0xac, 0xc8, - 0xec, 0x7f, 0x0b, 0xef, 0x77, 0x78, 0x6b, 0x84, 0x66, 0x65, 0x3c, 0xcc, 0x47, 0x4f, 0xf6, 0xa2, 0xf9, 0xbd, 0xb3, - 0x6c, 0x2b, 0x57, 0x25, 0xb3, 0xfd, 0x7e, 0x94, 0x34, 0x67, 0x8f, 0xd7, 0x48, 0xea, 0x00, 0x1f, 0xaf, 0xcf, 0xf0, - 0x91, 0x4a, 0x28, 0xb5, 0xa0, 0xaa, 0x41, 0xeb, 0x63, 0xbf, 0xb7, 0x9e, 0xd3, 0xc7, 0x8f, 0xe5, 0x74, 0x4b, 0x8a, - 0x30, 0x7e, 0x60, 0x30, 0x65, 0x27, 0x4e, 0x5d, 0xf2, 0x66, 0x48, 0xef, 0xba, 0x55, 0x52, 0x97, 0x3d, 0x4a, 0x04, - 0xa1, 0x0e, 0xd6, 0x2f, 0xf6, 0x43, 0x98, 0xd9, 0xa2, 0x3f, 0x6c, 0x56, 0x73, 0x42, 0x41, 0x04, 0x88, 0x56, 0x79, - 0x1f, 0x38, 0x26, 0x09, 0xb3, 0xe6, 0x86, 0x74, 0xeb, 0xcd, 0x95, 0xf6, 0x4a, 0x0a, 0xe8, 0xe7, 0x20, 0x73, 0xfb, - 0xe8, 0x96, 0xab, 0x96, 0x79, 0x2e, 0x6d, 0x39, 0x60, 0xd1, 0x42, 0x74, 0x66, 0xe7, 0xd2, 0xe1, 0xe0, 0x3f, 0xa8, - 0x2b, 0x51, 0x45, 0x04, 0x1d, 0x45, 0x0b, 0x46, 0xab, 0x55, 0xbb, 0x9c, 0x6c, 0x2a, 0x64, 0x4b, 0x22, 0x9c, 0x28, - 0xd9, 0x2b, 0xa1, 0x3e, 0xca, 0xd5, 0x9e, 0x69, 0x88, 0x3f, 0x13, 0xb0, 0x69, 0x83, 0xbf, 0x05, 0xee, 0x65, 0x70, - 0x66, 0xda, 0xa7, 0x61, 0x04, 0x44, 0xe6, 0x10, 0xec, 0xe7, 0x77, 0x3d, 0xa8, 0xe0, 0x41, 0x47, 0xfa, 0xeb, 0x7a, - 0x56, 0xe0, 0x99, 0x7b, 0xe2, 0xf9, 0x9b, 0x13, 0xe9, 0x45, 0x0e, 0x0f, 0x34, 0xf7, 0x61, 0xc6, 0x5f, 0x96, 0x65, - 0xb8, 0x1b, 0x2d, 0xcb, 0x62, 0xe5, 0x45, 0x7a, 0x1f, 0xcf, 0xa4, 0x18, 0x48, 0x74, 0x98, 0x19, 0x5d, 0xc5, 0x3a, - 0xce, 0x61, 0xdc, 0xdb, 0x93, 0xb0, 0x42, 0xfb, 0x67, 0x89, 0xbd, 0x2e, 0x00, 0xc0, 0x21, 0x6b, 0xd0, 0x0a, 0xef, - 0x74, 0x7b, 0xbb, 0xc7, 0x25, 0x25, 0x8a, 0x1b, 0x35, 0x3f, 0xab, 0xa1, 0x65, 0x82, 0x5a, 0x66, 0xdd, 0xc9, 0x64, - 0x8a, 0x24, 0xf0, 0x6d, 0xd8, 0x1b, 0x56, 0xe4, 0xf3, 0x46, 0x6e, 0x0f, 0xef, 0xc2, 0x95, 0x88, 0xb5, 0x05, 0x9d, - 0x74, 0x64, 0x1c, 0xee, 0x85, 0xe6, 0x46, 0xba, 0x7f, 0x52, 0x25, 0x61, 0x29, 0x62, 0xb8, 0x05, 0xb2, 0xbd, 0xda, - 0x56, 0x82, 0x12, 0x48, 0x60, 0x3f, 0x94, 0x62, 0x99, 0x6e, 0x05, 0x80, 0x39, 0xf0, 0x3f, 0x25, 0x0c, 0xa1, 0xbb, - 0xf3, 0x10, 0xaf, 0x1a, 0x79, 0xdf, 0x20, 0x04, 0xfb, 0x6b, 0x90, 0xd3, 0x80, 0x41, 0xa4, 0x18, 0xc9, 0x82, 0x81, - 0x04, 0x20, 0xe7, 0x6b, 0x30, 0xc9, 0x4d, 0x73, 0xcf, 0x0f, 0x72, 0xdd, 0xc1, 0xb4, 0x0f, 0xba, 0x17, 0xd7, 0x9a, - 0xe5, 0xe0, 0x15, 0x13, 0xf1, 0xbf, 0xd7, 0x5e, 0xc9, 0x72, 0x96, 0xf9, 0x8d, 0xb9, 0xe8, 0x64, 0x70, 0xd5, 0x10, - 0x7e, 0x31, 0xcb, 0xe6, 0x3c, 0x9a, 0x65, 0x3a, 0xd4, 0xbf, 0x68, 0x8e, 0x4a, 0x01, 0x0c, 0x75, 0xbc, 0x00, 0x6b, - 0xbc, 0x2b, 0xdd, 0xb4, 0xe2, 0x91, 0xc6, 0x18, 0x05, 0x15, 0x3a, 0x08, 0xfd, 0xbd, 0x06, 0x78, 0x0d, 0x26, 0xb9, - 0x11, 0x2a, 0x1f, 0x5c, 0xd0, 0x0d, 0xdd, 0x72, 0xe5, 0x12, 0xd4, 0xa4, 0x6a, 0xf9, 0xe5, 0x08, 0xf5, 0xae, 0x96, - 0x5c, 0xaa, 0xcd, 0xa7, 0x46, 0x59, 0x23, 0xc8, 0xe4, 0x28, 0xfd, 0x3e, 0xe5, 0xc2, 0xad, 0x8c, 0xc9, 0xfa, 0x70, - 0xf0, 0x0a, 0x6e, 0x6a, 0xfc, 0x3a, 0x27, 0x16, 0x51, 0x7b, 0x48, 0x84, 0xad, 0xdd, 0x0a, 0xdd, 0x7b, 0xdc, 0x28, - 0xcd, 0xa3, 0x6c, 0x13, 0x8b, 0xca, 0xeb, 0x25, 0x60, 0x2d, 0xee, 0x01, 0x19, 0x2a, 0x2d, 0xfd, 0x8a, 0x15, 0x00, - 0x19, 0x20, 0x85, 0x8d, 0x1f, 0x90, 0xf6, 0xea, 0x83, 0x97, 0xfa, 0xfd, 0xbe, 0x31, 0xe5, 0xbf, 0x7f, 0xc8, 0x81, - 0x99, 0x50, 0x94, 0xf5, 0x0e, 0x26, 0x10, 0x5c, 0x3b, 0x49, 0x7b, 0x56, 0xf3, 0x17, 0xeb, 0xda, 0x03, 0x52, 0x2b, - 0xdf, 0x62, 0xae, 0x7a, 0x6d, 0x5f, 0x6c, 0xf6, 0x69, 0x75, 0x63, 0x34, 0x0e, 0x82, 0xa5, 0xd5, 0x5b, 0xad, 0x72, - 0xc8, 0x1b, 0x5e, 0x81, 0x48, 0x65, 0x5d, 0x5d, 0x2b, 0xe7, 0xea, 0x5a, 0x70, 0x24, 0x90, 0x2d, 0x79, 0x0e, 0xff, - 0x85, 0xdc, 0x2b, 0x0f, 0x87, 0xc2, 0xef, 0xf7, 0xd3, 0x19, 0x69, 0x65, 0x81, 0x32, 0x6d, 0x5d, 0x7b, 0xa1, 0x7f, - 0x38, 0xfc, 0x00, 0x5e, 0x23, 0xfe, 0xe1, 0x50, 0xf6, 0xfb, 0x1f, 0xcd, 0x4d, 0xe6, 0x7c, 0xac, 0x94, 0xb2, 0x97, - 0xa8, 0x74, 0x7f, 0x9b, 0xf0, 0xde, 0xff, 0x1e, 0xfd, 0xef, 0xd1, 0x65, 0x4f, 0x05, 0x80, 0x25, 0x7c, 0x86, 0x37, - 0x74, 0xa6, 0x2e, 0xe7, 0x4c, 0xba, 0xbb, 0x2b, 0x3f, 0xf4, 0x9e, 0xc6, 0x87, 0xef, 0xcd, 0x4d, 0x1b, 0x7f, 0xad, - 0x8e, 0x34, 0x09, 0x1d, 0x17, 0xfd, 0xc3, 0xe1, 0x53, 0xa2, 0xf5, 0x69, 0xa9, 0xd2, 0xa7, 0x29, 0xf0, 0x24, 0xc3, - 0x86, 0xeb, 0x16, 0xa6, 0xa3, 0xf9, 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, 0x5b, 0xe5, 0x0a, 0xde, 0xda, - 0xe3, 0xdd, 0x60, 0x44, 0xa9, 0x23, 0x7d, 0xd2, 0x86, 0xd0, 0x25, 0x95, 0xfc, 0x47, 0x91, 0xc7, 0x18, 0xb3, 0xf1, - 0x9a, 0xc8, 0x3e, 0x8b, 0xfc, 0x55, 0x01, 0x80, 0x45, 0x80, 0x80, 0x9c, 0xce, 0x1d, 0x49, 0xfc, 0xe7, 0xe4, 0xdb, - 0x3f, 0xa6, 0x4b, 0xfb, 0x50, 0x16, 0x77, 0xa5, 0xa8, 0xaa, 0xa3, 0xd2, 0x76, 0xb6, 0x5c, 0x0f, 0xf4, 0xa1, 0xfd, - 0xbe, 0xa4, 0x0f, 0x4d, 0x31, 0x14, 0x05, 0x6e, 0x8d, 0xbd, 0x69, 0xca, 0x15, 0x4d, 0xf5, 0xc8, 0x58, 0x3f, 0xbf, - 0xdf, 0xbd, 0x8d, 0xbd, 0xd4, 0x0f, 0x52, 0x10, 0x84, 0x35, 0x7e, 0x52, 0x8a, 0x24, 0x70, 0x3e, 0xc3, 0x54, 0xe2, - 0xd3, 0xa5, 0x54, 0xf9, 0xc3, 0x48, 0xf3, 0x61, 0x0a, 0x7a, 0xd9, 0x7f, 0x54, 0x30, 0xff, 0x75, 0x7b, 0xb0, 0x3e, - 0xad, 0xcb, 0x34, 0xaa, 0x88, 0x2a, 0x2f, 0x4c, 0xb5, 0x09, 0x44, 0xf0, 0x17, 0xc2, 0x22, 0xf9, 0xf5, 0xc9, 0x91, - 0xa0, 0x31, 0x93, 0xe5, 0xe3, 0x91, 0xfb, 0x85, 0x7d, 0xe5, 0x3a, 0x9e, 0xff, 0xb9, 0x99, 0xff, 0x03, 0x74, 0x86, - 0x2c, 0x5e, 0x70, 0xcb, 0x60, 0x81, 0xb3, 0x5f, 0xba, 0x7a, 0xc0, 0xdf, 0xcc, 0x13, 0x2f, 0x80, 0x83, 0xf9, 0x05, - 0xba, 0x2a, 0xa6, 0xb3, 0x62, 0x00, 0x04, 0xb6, 0x7e, 0x63, 0xcd, 0x89, 0x37, 0x16, 0xcf, 0x95, 0x5c, 0x10, 0xfa, - 0xba, 0x0a, 0xb3, 0x71, 0x55, 0x6c, 0x2a, 0x51, 0x6c, 0xea, 0x1e, 0xa9, 0x65, 0xf3, 0x69, 0x6d, 0x2b, 0x64, 0x7f, - 0x12, 0x2d, 0xda, 0x2e, 0x43, 0x35, 0x19, 0x65, 0xe9, 0x7a, 0x0a, 0xa4, 0x7a, 0x01, 0x9c, 0x45, 0xe6, 0x95, 0x2f, - 0xce, 0x1e, 0xb0, 0x45, 0xe3, 0x29, 0x30, 0xa2, 0xd2, 0x1f, 0x79, 0x63, 0x74, 0x7a, 0xa2, 0xdf, 0xcf, 0xa7, 0x14, - 0xf2, 0xf5, 0x13, 0x60, 0x72, 0xd5, 0x72, 0x01, 0xfa, 0x32, 0xd4, 0x41, 0x25, 0x4a, 0xad, 0x18, 0x46, 0x2c, 0xfc, - 0x24, 0x90, 0xbd, 0x99, 0x82, 0x9a, 0x55, 0x94, 0x84, 0x4a, 0x54, 0x4a, 0xb6, 0x26, 0xa8, 0xa5, 0xf7, 0x45, 0x51, - 0xef, 0x2b, 0x70, 0x94, 0x8c, 0xb4, 0x59, 0x4e, 0x99, 0x71, 0x51, 0xe6, 0xa2, 0x1f, 0xec, 0xdf, 0x95, 0xe7, 0x37, - 0x32, 0x9f, 0xe5, 0xbe, 0xa3, 0x73, 0xda, 0x8e, 0x0b, 0x94, 0xb9, 0xe5, 0xb4, 0xd5, 0x92, 0xc7, 0xe4, 0x3d, 0x0b, - 0xb6, 0xfd, 0x97, 0x09, 0xf2, 0x2a, 0xc2, 0x7c, 0x42, 0x95, 0xcd, 0x3f, 0x20, 0xcc, 0x16, 0x07, 0xf6, 0xd8, 0x85, - 0x89, 0x48, 0x6f, 0xc1, 0x92, 0x18, 0x66, 0xa5, 0x08, 0xe3, 0x1d, 0x78, 0xff, 0x6c, 0x2a, 0x31, 0x3a, 0x43, 0x27, - 0xf7, 0xb3, 0x87, 0xb4, 0x4e, 0xce, 0xde, 0xbe, 0x3e, 0xfb, 0xae, 0x37, 0x28, 0x46, 0x69, 0x3c, 0xe8, 0x7d, 0x77, - 0xb6, 0xda, 0x00, 0x44, 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, 0x74, 0x7b, 0x22, 0xed, 0xaa, 0x74, 0x05, 0x84, 0x1e, - 0x00, 0x27, 0x5d, 0xf9, 0xf3, 0x70, 0x10, 0x09, 0x84, 0x5a, 0x30, 0x27, 0xd3, 0x88, 0x6e, 0x48, 0xaf, 0xb0, 0xcf, - 0xc0, 0x2c, 0xa4, 0x34, 0x0f, 0x6e, 0xae, 0x16, 0x2d, 0x77, 0xc5, 0xca, 0x51, 0x58, 0xad, 0x45, 0x54, 0x23, 0xd5, - 0x31, 0x38, 0xef, 0x40, 0x04, 0x80, 0x62, 0x04, 0xcf, 0x78, 0xd4, 0xef, 0x47, 0x2a, 0x28, 0x27, 0xa1, 0x5f, 0x14, - 0xfa, 0xa5, 0x31, 0x28, 0x63, 0xfe, 0x2e, 0xd4, 0xc4, 0x00, 0xf5, 0x96, 0x87, 0x8a, 0x23, 0x00, 0x97, 0x73, 0xc4, - 0x8c, 0xf3, 0x1e, 0x77, 0xd1, 0x38, 0x15, 0xef, 0x84, 0xba, 0x0e, 0x96, 0x0a, 0x75, 0xde, 0xd4, 0x47, 0x7a, 0x4e, - 0x9a, 0x04, 0x0d, 0xe2, 0x06, 0x1e, 0xaf, 0x86, 0x80, 0x6a, 0x25, 0xa4, 0xde, 0x42, 0xa7, 0x54, 0x75, 0x08, 0xac, - 0x01, 0x2e, 0x51, 0xd8, 0x56, 0x98, 0x1c, 0xd1, 0xa6, 0x2c, 0x45, 0x7e, 0xc4, 0x06, 0xed, 0x92, 0x91, 0xa9, 0x83, - 0xcb, 0xe5, 0x72, 0x22, 0xea, 0x5f, 0xf3, 0x2d, 0x80, 0xf3, 0x42, 0x7e, 0x6b, 0x37, 0x5b, 0x26, 0xd9, 0xae, 0x2b, - 0xc3, 0x59, 0x52, 0x8a, 0x6a, 0x5d, 0xe4, 0x55, 0x7a, 0x2f, 0x7e, 0xd6, 0x0f, 0x5d, 0x02, 0x29, 0xf4, 0x23, 0xbd, - 0x6e, 0x37, 0x47, 0xaa, 0x71, 0x74, 0x39, 0xb6, 0xa7, 0xd2, 0x4e, 0xf6, 0xaa, 0xc5, 0x9b, 0x2d, 0x73, 0x25, 0x69, - 0x1c, 0x8b, 0xfc, 0x6d, 0x1e, 0xa7, 0x91, 0x95, 0x1c, 0xfe, 0x1f, 0xde, 0xbe, 0x85, 0xbb, 0x6d, 0x1b, 0x5b, 0xf7, - 0xaf, 0x58, 0xbc, 0xa9, 0x4a, 0x44, 0x90, 0x2c, 0x39, 0x49, 0x67, 0x4a, 0x19, 0xd6, 0x71, 0xf3, 0x68, 0xd3, 0x36, - 0x71, 0x1a, 0xa7, 0x9d, 0xce, 0xe8, 0xea, 0xb8, 0x34, 0x09, 0x5b, 0x6c, 0x68, 0x40, 0x25, 0x29, 0x3f, 0x22, 0xf1, - 0xbf, 0xdf, 0xb5, 0x37, 0x9e, 0xa4, 0x68, 0x27, 0x33, 0xf7, 0xdc, 0xbb, 0xb2, 0x56, 0x2c, 0x82, 0x20, 0xde, 0xd8, - 0xd8, 0xd8, 0x8f, 0x6f, 0xeb, 0x00, 0xd5, 0x2e, 0xf2, 0x95, 0x8b, 0x8d, 0xfc, 0x22, 0x2b, 0x31, 0x60, 0x70, 0xa3, - 0x51, 0xad, 0x50, 0x53, 0x26, 0xf0, 0x85, 0x7c, 0x8f, 0x11, 0xb7, 0x59, 0x99, 0x00, 0xc3, 0x8f, 0x89, 0xfa, 0x92, - 0x9e, 0x42, 0x94, 0x07, 0x15, 0x8f, 0xfb, 0x05, 0x47, 0xc4, 0x6b, 0xab, 0x32, 0x07, 0x26, 0x5b, 0xab, 0x20, 0x11, - 0xec, 0x2e, 0x9b, 0xeb, 0x45, 0xb4, 0x50, 0x77, 0xa1, 0x5e, 0xbc, 0xdd, 0xf6, 0x12, 0x45, 0x07, 0x9c, 0xfc, 0x34, - 0x78, 0x15, 0x67, 0x39, 0x4f, 0xf7, 0x2a, 0xb9, 0xa7, 0x36, 0xd4, 0x9e, 0x72, 0xe6, 0x80, 0x9d, 0xf7, 0x75, 0xb5, - 0xa7, 0xd7, 0xf4, 0x9e, 0x6e, 0xe7, 0x1e, 0x5c, 0x30, 0x70, 0xe7, 0x5e, 0x66, 0xd7, 0x5c, 0xec, 0x81, 0x32, 0xd0, - 0x1a, 0x0f, 0xd4, 0xa2, 0x1a, 0xa9, 0x89, 0xd1, 0x81, 0xab, 0x13, 0x7d, 0x30, 0x07, 0xf4, 0x7b, 0x88, 0x15, 0xde, - 0x7a, 0xbb, 0xd2, 0x07, 0x6d, 0x40, 0x7f, 0x5e, 0x9a, 0x3e, 0xe8, 0x68, 0xf1, 0x2a, 0x24, 0x70, 0x63, 0x48, 0x35, - 0x52, 0xab, 0x91, 0x55, 0xa0, 0x78, 0xc3, 0x5b, 0xbc, 0x3b, 0xd7, 0x92, 0x8d, 0xf7, 0x12, 0x81, 0xbd, 0x32, 0x51, - 0xc5, 0x99, 0x38, 0xf6, 0x52, 0x79, 0xad, 0x9d, 0x64, 0x84, 0xf1, 0x2d, 0x2b, 0xa9, 0xbf, 0x43, 0xcc, 0x2d, 0xd2, - 0x1c, 0x06, 0x2f, 0xc3, 0x8a, 0xcc, 0x78, 0xbf, 0x2f, 0x67, 0x32, 0x2a, 0x67, 0x62, 0xbf, 0x8c, 0x14, 0x42, 0xdb, - 0x7d, 0x22, 0xa0, 0x07, 0x25, 0x40, 0xbe, 0x00, 0xa8, 0x7a, 0x48, 0xf8, 0xf3, 0x90, 0xd4, 0xa7, 0x53, 0xe8, 0x53, - 0x68, 0xeb, 0x15, 0xaf, 0xa0, 0xaa, 0x6e, 0x8c, 0x6c, 0xa3, 0x82, 0x16, 0x8f, 0xe5, 0x59, 0x6d, 0x18, 0x9b, 0x53, - 0xeb, 0x5d, 0x6f, 0x36, 0x98, 0xb2, 0xb9, 0x50, 0xab, 0x30, 0x24, 0xd1, 0x4d, 0xe9, 0x85, 0x0f, 0xb1, 0x58, 0x59, - 0xad, 0xcd, 0x6f, 0x62, 0x7f, 0x64, 0x22, 0xc5, 0xfd, 0x6c, 0x89, 0x73, 0x17, 0x8f, 0xe7, 0x55, 0x5f, 0x6b, 0x69, - 0x91, 0x69, 0xf3, 0x9d, 0xbe, 0x0c, 0x69, 0x2a, 0x6a, 0x48, 0xa3, 0xce, 0x0c, 0xba, 0x6f, 0x97, 0x57, 0x54, 0x23, - 0x4c, 0x80, 0x57, 0x3a, 0x83, 0x6e, 0x34, 0x1e, 0x88, 0xa2, 0x1a, 0x15, 0x6b, 0x21, 0x10, 0x6d, 0x18, 0x72, 0xcc, - 0x2c, 0x21, 0xc9, 0x3e, 0xf1, 0xef, 0x54, 0x70, 0x85, 0x22, 0xbe, 0x31, 0x70, 0xde, 0x95, 0xf5, 0xec, 0xae, 0x23, - 0x3f, 0x27, 0x16, 0x56, 0xfb, 0x0f, 0xcd, 0xa3, 0xd6, 0x38, 0x0b, 0x68, 0x6b, 0x5a, 0xdd, 0x70, 0xb8, 0x47, 0x75, - 0x2c, 0x4a, 0x03, 0x48, 0xec, 0x91, 0xe5, 0xa2, 0x75, 0xcc, 0xa0, 0x01, 0xfd, 0x6d, 0x76, 0xb5, 0xbe, 0x42, 0xd4, - 0xb6, 0x12, 0x59, 0x27, 0xa9, 0xfc, 0x4b, 0xda, 0xa3, 0xae, 0xed, 0xa9, 0xfc, 0x6f, 0xdb, 0x54, 0x39, 0xb4, 0x40, - 0xf2, 0xd8, 0xcd, 0x59, 0xa0, 0x3a, 0x12, 0x44, 0x81, 0xda, 0x7a, 0xc1, 0xd4, 0x3b, 0x65, 0x8a, 0x0e, 0xe4, 0xe7, - 0xc2, 0x9c, 0x61, 0x5f, 0x70, 0xc4, 0x98, 0xa5, 0x12, 0x83, 0xa9, 0x8f, 0x31, 0xaa, 0x69, 0xad, 0x00, 0x5d, 0x3f, - 0xdd, 0xc0, 0x9f, 0xa8, 0xa8, 0xd1, 0x50, 0x6b, 0x24, 0x85, 0xa2, 0x89, 0x0a, 0x3a, 0x96, 0x16, 0x3a, 0x98, 0x42, - 0x27, 0x91, 0xb0, 0x04, 0x34, 0x4c, 0x88, 0x4e, 0x2a, 0xf0, 0xd6, 0x00, 0xce, 0x7c, 0x5c, 0x94, 0xeb, 0x42, 0x1b, - 0xcc, 0xfd, 0x10, 0x5f, 0xf3, 0xd7, 0x2f, 0x9c, 0x51, 0x7d, 0xcb, 0x5a, 0xdf, 0xd3, 0x82, 0xfc, 0x10, 0x72, 0x8a, - 0x0e, 0x4c, 0xec, 0x68, 0x83, 0xc6, 0x18, 0x65, 0xad, 0x43, 0x5d, 0x9c, 0xe8, 0xf8, 0x2b, 0xda, 0x04, 0xef, 0x01, - 0x4f, 0x11, 0x6d, 0x78, 0x28, 0x8c, 0x55, 0x35, 0x3e, 0x95, 0xac, 0xa5, 0x07, 0x2b, 0x78, 0xba, 0x4e, 0x78, 0x08, - 0x7a, 0x24, 0xc2, 0x8e, 0xc2, 0x62, 0x1e, 0x2f, 0xe0, 0x38, 0x29, 0x08, 0xa8, 0x1d, 0xf4, 0x15, 0x7c, 0xbe, 0x40, - 0xf7, 0x57, 0x89, 0x1e, 0x60, 0x68, 0x41, 0xdc, 0x0c, 0x7d, 0x3a, 0xba, 0x8a, 0x57, 0x0d, 0x15, 0x09, 0x9f, 0x17, - 0x60, 0x3b, 0xa4, 0xd4, 0x53, 0xa0, 0x85, 0x4a, 0x94, 0x7e, 0x18, 0xf8, 0x0e, 0x0d, 0x7c, 0xad, 0x75, 0x80, 0x86, - 0x7e, 0xc6, 0x34, 0xb5, 0xce, 0x50, 0xf9, 0xcc, 0xbb, 0x67, 0x46, 0xcb, 0x99, 0x05, 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, 0xe3, 0x50, 0x69, 0x73, 0x20, 0xbe, 0x11, 0x1a, 0xf7, 0x4f, - 0xc3, 0xd8, 0x6a, 0x8a, 0xad, 0xdd, 0xdb, 0x76, 0xfb, 0x7b, 0xe9, 0xa5, 0xd3, 0x9c, 0xf4, 0x18, 0xfb, 0xbd, 0x0c, - 0x8b, 0x91, 0xed, 0x08, 0x81, 0x25, 0xe7, 0x7d, 0xea, 0xbf, 0xa2, 0xe5, 0x3c, 0x01, 0xd3, 0x11, 0x1d, 0x21, 0x17, - 0x28, 0x3b, 0x46, 0x71, 0x07, 0x06, 0x57, 0xf4, 0xfb, 0x60, 0x95, 0x61, 0x2e, 0x24, 0x4b, 0x92, 0x32, 0x78, 0x9e, - 0x7a, 0x18, 0xf0, 0x6b, 0xa6, 0xcc, 0x5d, 0x94, 0xf5, 0xe9, 0x92, 0x4c, 0x53, 0x64, 0x20, 0xd6, 0xe1, 0x26, 0x4b, - 0xa3, 0x44, 0x89, 0xc8, 0x96, 0xe8, 0x1f, 0x69, 0x28, 0x96, 0x0e, 0xd7, 0x8b, 0x54, 0x89, 0x50, 0x31, 0x4f, 0xf1, - 0xa4, 0x4e, 0xeb, 0x74, 0x84, 0xf1, 0x26, 0x41, 0x29, 0x57, 0xc3, 0x40, 0x95, 0x54, 0x2f, 0x85, 0x4d, 0xb1, 0xdd, - 0xea, 0x8b, 0x95, 0x98, 0xc7, 0x0b, 0x7c, 0x29, 0x70, 0x14, 0x7f, 0xe2, 0x5e, 0xac, 0x29, 0xb5, 0x3d, 0xa8, 0x1d, - 0x51, 0x42, 0x7f, 0xe2, 0x70, 0x91, 0xf8, 0x4e, 0xea, 0xb8, 0x7f, 0x68, 0x11, 0x72, 0xa6, 0x0e, 0x52, 0xc3, 0x0d, - 0xed, 0x08, 0xff, 0x0d, 0xd7, 0x67, 0x9c, 0xd1, 0x9b, 0x6a, 0x46, 0x8d, 0xdf, 0xeb, 0xe1, 0x19, 0xa3, 0x3e, 0x1b, - 0x38, 0xac, 0x10, 0x85, 0x36, 0xec, 0xa8, 0x54, 0xa2, 0x85, 0xa1, 0x54, 0x7f, 0x09, 0x15, 0x47, 0xdc, 0x99, 0x51, - 0x96, 0x8c, 0x4f, 0xcb, 0x43, 0x31, 0x1d, 0x0c, 0x4a, 0x52, 0x19, 0x0b, 0x3d, 0xb8, 0x1e, 0x78, 0xfe, 0x3d, 0x70, - 0x0b, 0xf1, 0xe0, 0x90, 0xc5, 0x90, 0x1b, 0x70, 0xfc, 0x16, 0x27, 0x57, 0x8d, 0x4a, 0x15, 0xbc, 0x9a, 0xa8, 0x16, - 0xfc, 0x54, 0x86, 0x01, 0xfa, 0x24, 0x05, 0x60, 0x32, 0x98, 0xf2, 0x5b, 0x90, 0x28, 0x9d, 0xa9, 0x1b, 0xd2, 0xaf, - 0xa2, 0xe0, 0x17, 0xbc, 0xe0, 0x22, 0x71, 0x05, 0x58, 0xde, 0xc1, 0xf6, 0x3a, 0xaa, 0xa8, 0x02, 0xe2, 0x35, 0x3d, - 0x8e, 0xb8, 0xf1, 0xfe, 0x33, 0x3d, 0xb6, 0x40, 0xad, 0xd6, 0xb1, 0xc1, 0x67, 0x8e, 0xc1, 0x05, 0x5d, 0x4b, 0x6c, - 0x0d, 0xd5, 0xb0, 0x22, 0x30, 0x70, 0x01, 0x07, 0x61, 0x89, 0xe2, 0xd8, 0x4a, 0x5e, 0x91, 0x86, 0x94, 0xf6, 0x81, - 0xe1, 0x68, 0x93, 0x1c, 0xdf, 0x66, 0xd9, 0x4d, 0xe0, 0x7c, 0xd1, 0x39, 0x69, 0x26, 0x96, 0x0d, 0xde, 0xe7, 0xcd, - 0xf9, 0x75, 0xff, 0x90, 0x50, 0x15, 0xec, 0x86, 0xb7, 0x83, 0xdd, 0x38, 0xe1, 0xd7, 0x5c, 0x2c, 0x74, 0x7c, 0x16, - 0x73, 0xc9, 0xf2, 0x5b, 0xeb, 0xdd, 0x92, 0xa4, 0x56, 0x40, 0xfb, 0x2c, 0x0b, 0x6a, 0x22, 0x00, 0xdd, 0x0f, 0x7f, - 0x81, 0xd0, 0x19, 0xfe, 0xf6, 0x18, 0x5c, 0x91, 0xc2, 0x7b, 0x87, 0x40, 0x58, 0xd3, 0xcd, 0x9d, 0xda, 0x80, 0x2f, - 0xc6, 0xfd, 0x19, 0x53, 0x4f, 0xbf, 0xcd, 0xe4, 0xae, 0xae, 0xdb, 0x23, 0xcb, 0xf0, 0x11, 0xae, 0x14, 0x00, 0xcb, - 0x84, 0xbf, 0x18, 0x5b, 0x52, 0x7d, 0x02, 0x70, 0x6a, 0x3a, 0xa2, 0x4f, 0x10, 0x18, 0x38, 0x25, 0x5a, 0x8c, 0xae, - 0x95, 0x23, 0x9a, 0x41, 0x5a, 0xd3, 0xad, 0x30, 0xde, 0x7a, 0xd0, 0x42, 0xcf, 0x34, 0x9c, 0xf8, 0x0f, 0x9a, 0x79, - 0x55, 0x40, 0x00, 0xad, 0x8c, 0xe0, 0xad, 0xf5, 0xd1, 0x1c, 0x21, 0x3e, 0x61, 0x49, 0x34, 0x61, 0xf1, 0x4c, 0xf1, - 0x63, 0x42, 0x37, 0x4d, 0x6d, 0xd3, 0x07, 0xa4, 0xbf, 0xb8, 0x66, 0xfd, 0x94, 0x65, 0xed, 0xdb, 0x43, 0xc5, 0x8b, - 0x69, 0x33, 0xf8, 0x61, 0xa2, 0x8a, 0xf1, 0xbf, 0xa8, 0x7c, 0xa9, 0x15, 0xc0, 0x30, 0x77, 0xd5, 0xd3, 0xef, 0x37, - 0xb3, 0xe5, 0x40, 0xa8, 0xfc, 0xce, 0x20, 0xe9, 0xd3, 0xf1, 0xfc, 0xc0, 0x26, 0x51, 0x5b, 0xe8, 0xf9, 0xe3, 0x52, - 0x37, 0xa1, 0xf2, 0xda, 0xd4, 0x88, 0x56, 0xc8, 0x50, 0xd9, 0x3a, 0x60, 0x7d, 0xff, 0x10, 0xee, 0x2e, 0x6a, 0x1a, - 0x6a, 0xdd, 0x73, 0xd7, 0xa2, 0xe0, 0xc4, 0x1f, 0x60, 0x2c, 0x2e, 0x24, 0xb5, 0x0e, 0xc2, 0xa4, 0x1f, 0x2d, 0x4e, - 0x72, 0xa3, 0xae, 0x4e, 0xce, 0x14, 0xf3, 0x04, 0x2e, 0xaa, 0x65, 0xdb, 0x5f, 0x51, 0xa9, 0x4b, 0xb9, 0xbd, 0xa2, - 0x34, 0x3d, 0xa4, 0xed, 0x55, 0x9c, 0xb7, 0x05, 0x17, 0xfc, 0x0b, 0x05, 0x17, 0xd6, 0xc1, 0xba, 0xe3, 0x4e, 0xd9, - 0x13, 0x9e, 0x28, 0xd3, 0xda, 0xe0, 0xae, 0x1b, 0x8c, 0x89, 0xb1, 0xdf, 0x5d, 0xf2, 0xe4, 0x23, 0xb2, 0xe0, 0xdf, - 0x65, 0x02, 0x3c, 0x93, 0xdd, 0x2b, 0x95, 0xff, 0x07, 0xff, 0x6a, 0x6b, 0xdf, 0x59, 0xf3, 0x4f, 0xcf, 0x7a, 0xb8, - 0x73, 0x98, 0xfc, 0x00, 0x9d, 0x01, 0xdd, 0x5c, 0xc9, 0x94, 0x03, 0x32, 0x80, 0xb5, 0x48, 0x46, 0x03, 0x3e, 0xb4, - 0xb2, 0x6c, 0xfb, 0x4e, 0xab, 0x0b, 0xc2, 0xbd, 0x04, 0x6e, 0x7a, 0x7f, 0x6d, 0x66, 0xe6, 0x74, 0xad, 0x44, 0xd3, - 0xa5, 0xb1, 0xb5, 0x2c, 0x55, 0xc0, 0xee, 0xf7, 0x9e, 0x64, 0xd3, 0xfc, 0x70, 0x39, 0xcd, 0x2d, 0x75, 0xdb, 0xb8, - 0x65, 0x03, 0x40, 0x88, 0x5d, 0x6b, 0x2b, 0x07, 0x90, 0xdc, 0x1e, 0x84, 0xf0, 0xb5, 0x22, 0xf4, 0x54, 0x89, 0xd0, - 0xa7, 0x69, 0xb3, 0x0f, 0x76, 0x55, 0xad, 0x1b, 0x71, 0x8e, 0x06, 0xa9, 0x66, 0xe4, 0x4f, 0xae, 0x79, 0x71, 0x91, - 0xcb, 0x1b, 0xc0, 0x40, 0x26, 0xb5, 0x51, 0x58, 0x5e, 0x81, 0x3b, 0x3f, 0x3a, 0x8e, 0x33, 0x31, 0xca, 0x31, 0x58, - 0x2b, 0xc2, 0x23, 0xeb, 0xc4, 0x19, 0x80, 0x20, 0xfb, 0x93, 0xa6, 0xe3, 0xb9, 0x16, 0x18, 0xd3, 0x17, 0xb8, 0xab, - 0x9c, 0x1d, 0x6d, 0x72, 0xbb, 0xe8, 0x9b, 0x33, 0xac, 0x3b, 0x52, 0x5a, 0x1b, 0x8b, 0xae, 0x3b, 0x58, 0x6b, 0x06, - 0x6d, 0x11, 0x4a, 0x3e, 0xe4, 0x4e, 0xda, 0x4f, 0x01, 0x0d, 0xce, 0xb2, 0xf4, 0xd6, 0x5a, 0xe5, 0x6f, 0xb4, 0x10, - 0x27, 0x8a, 0xa9, 0x13, 0xdf, 0x44, 0x89, 0x3e, 0x3f, 0x13, 0xe3, 0x06, 0x02, 0xa9, 0x3f, 0x60, 0x50, 0x8d, 0x22, - 0x4c, 0xe0, 0x3a, 0x10, 0xc5, 0xf6, 0x44, 0x6d, 0x2c, 0x47, 0xd0, 0x09, 0x21, 0xde, 0x41, 0x19, 0xc6, 0xea, 0xe2, - 0x40, 0x1b, 0x2c, 0x7d, 0xdd, 0x5a, 0xe7, 0x86, 0x50, 0x18, 0x27, 0x30, 0xc5, 0x20, 0xa9, 0xb3, 0xce, 0x32, 0x41, - 0x95, 0x1d, 0x93, 0xce, 0xfb, 0x00, 0xdd, 0x5d, 0x8b, 0xa6, 0xf8, 0xba, 0x73, 0x07, 0xdd, 0xc7, 0xf5, 0x6b, 0x2d, - 0x72, 0x83, 0x3f, 0x6f, 0x89, 0xb0, 0x08, 0x9c, 0xb5, 0x26, 0x5f, 0x35, 0xc2, 0x81, 0x29, 0xc9, 0x34, 0xec, 0x25, - 0xca, 0xa6, 0x7b, 0xbb, 0xed, 0xf5, 0xee, 0x15, 0x71, 0xf5, 0x18, 0xab, 0xbc, 0x9b, 0xb9, 0xbd, 0x53, 0xad, 0xc5, - 0xee, 0x4d, 0xdb, 0x4f, 0xb1, 0xa3, 0xd6, 0xda, 0xed, 0x86, 0x13, 0x6a, 0xc8, 0xb7, 0xa2, 0x4a, 0xab, 0xd3, 0x8d, - 0x41, 0x3b, 0xc4, 0xb3, 0x16, 0x19, 0xdc, 0x28, 0x5f, 0x38, 0xa1, 0x93, 0x8a, 0xb3, 0xea, 0xd4, 0x05, 0x9b, 0x2b, - 0x5e, 0x2d, 0x65, 0x1a, 0x09, 0x8a, 0x36, 0xe7, 0x51, 0x49, 0x13, 0xb9, 0x16, 0x55, 0x24, 0x6b, 0xd4, 0x8b, 0x5a, - 0x8d, 0x01, 0x02, 0x32, 0x9d, 0x35, 0x3d, 0xa8, 0x82, 0xd9, 0x50, 0x46, 0x72, 0xfa, 0x1e, 0x2c, 0xed, 0x91, 0x63, - 0xad, 0xef, 0xab, 0xb3, 0xc5, 0xb7, 0x7a, 0x42, 0x30, 0x85, 0xd9, 0x03, 0x61, 0xe0, 0x9a, 0xc6, 0x90, 0xd3, 0x2e, - 0x71, 0x59, 0xd3, 0x2d, 0xe1, 0x1e, 0x6e, 0x57, 0xb2, 0x23, 0x37, 0x4f, 0x9a, 0x9b, 0x2b, 0xd8, 0x51, 0x31, 0x1f, - 0x83, 0xf6, 0x4b, 0xaa, 0x6b, 0x97, 0xe6, 0xd6, 0xe3, 0x41, 0x40, 0x83, 0x41, 0x61, 0xf8, 0xd7, 0x89, 0xf1, 0xf0, - 0xa4, 0x01, 0x41, 0x52, 0x2e, 0xc2, 0xb1, 0x6f, 0x44, 0x3f, 0x99, 0xca, 0x43, 0x8e, 0x16, 0xef, 0xd0, 0xea, 0x04, - 0xa2, 0x78, 0x89, 0x50, 0x12, 0xa3, 0x2a, 0x34, 0x22, 0x28, 0x4f, 0xcb, 0x5f, 0xaa, 0xea, 0x10, 0x50, 0x48, 0xfb, - 0x8a, 0x42, 0xd9, 0x26, 0x31, 0x34, 0xc3, 0x2f, 0xe7, 0x93, 0x85, 0x9e, 0x81, 0x81, 0x9c, 0x1f, 0x2c, 0xf4, 0x2c, - 0x0c, 0xe4, 0xfc, 0xc9, 0xa2, 0x76, 0xeb, 0x40, 0x13, 0x10, 0xcf, 0x85, 0xa3, 0x93, 0xd2, 0xaa, 0x6c, 0x01, 0xdd, - 0x3c, 0x44, 0xd0, 0x7f, 0xb2, 0x87, 0xa0, 0x93, 0x0b, 0xed, 0xc8, 0x0d, 0x68, 0x3b, 0x0e, 0x81, 0xbd, 0x62, 0x52, - 0x61, 0x02, 0x10, 0x1d, 0xb2, 0x31, 0x18, 0x62, 0xab, 0x0f, 0x0e, 0xd9, 0x78, 0xea, 0x93, 0x20, 0x60, 0x74, 0x7f, - 0x30, 0x90, 0xe0, 0xb7, 0x78, 0x95, 0x3e, 0xda, 0x08, 0x74, 0xd3, 0x77, 0x77, 0x43, 0xef, 0xe2, 0x0a, 0x4e, 0xd5, - 0xee, 0x9e, 0x84, 0x6e, 0x32, 0xed, 0x00, 0xbd, 0x86, 0xb8, 0x21, 0xbf, 0x32, 0x1a, 0x8d, 0x6c, 0x4a, 0x48, 0x88, - 0xe1, 0x1c, 0x9a, 0x39, 0x2d, 0x97, 0xaf, 0x6e, 0x3d, 0x1b, 0x90, 0x61, 0xa6, 0xb7, 0x4c, 0xd6, 0x0f, 0x50, 0x56, - 0x3d, 0x86, 0x76, 0xe8, 0x3d, 0x72, 0xfc, 0xf0, 0xe0, 0x9b, 0x8c, 0x9f, 0x39, 0x5c, 0x7b, 0x38, 0x17, 0xbe, 0xcb, - 0x9a, 0x91, 0x39, 0x74, 0x9e, 0x7d, 0x1c, 0xef, 0x61, 0x9c, 0x7c, 0x9e, 0x85, 0xf2, 0xc6, 0x6b, 0xfa, 0x1f, 0x95, - 0xde, 0xec, 0x70, 0xc8, 0xe9, 0x0a, 0x56, 0xdc, 0xac, 0x0a, 0x0d, 0x3f, 0x8b, 0xbc, 0x71, 0xc4, 0x6b, 0x12, 0x55, - 0xdd, 0xe7, 0xbd, 0x0d, 0x53, 0xda, 0x31, 0x0e, 0x00, 0x4e, 0xd4, 0xaa, 0x61, 0x57, 0x1a, 0xd7, 0xea, 0x20, 0x86, - 0xa1, 0x84, 0xad, 0x12, 0x47, 0x42, 0xf9, 0x1b, 0x80, 0xb0, 0x18, 0x8a, 0xe3, 0xad, 0x61, 0x7d, 0x80, 0xfd, 0xd0, - 0x05, 0x9a, 0xe6, 0x94, 0x6a, 0x06, 0x00, 0x49, 0xc0, 0x1f, 0x3d, 0xdd, 0x34, 0x54, 0xb6, 0x79, 0x1e, 0x5a, 0x56, - 0x57, 0xf0, 0x40, 0x4f, 0x5d, 0xc9, 0xc0, 0xb8, 0xaa, 0x63, 0x6f, 0x73, 0x7f, 0x7b, 0xb4, 0x8a, 0x7c, 0x67, 0x93, - 0xda, 0x66, 0x55, 0x68, 0xec, 0xe3, 0x09, 0x3d, 0x9d, 0x00, 0xad, 0xd7, 0x96, 0x8a, 0xf6, 0xfb, 0x28, 0x46, 0x8d, - 0x0b, 0x05, 0x56, 0x61, 0x22, 0xc1, 0x21, 0xc2, 0x08, 0xa1, 0xdf, 0x97, 0xe1, 0xc6, 0x17, 0x64, 0x10, 0x0d, 0xd7, - 0xa2, 0xe3, 0x0f, 0x39, 0x5e, 0xb4, 0x2d, 0x55, 0x35, 0x27, 0x4d, 0x5b, 0x02, 0x6f, 0xc2, 0x01, 0xb6, 0xf3, 0x4f, - 0x1b, 0x22, 0x57, 0xe1, 0xa2, 0x84, 0xef, 0x88, 0x6b, 0x41, 0x74, 0x53, 0x9b, 0x7a, 0x1b, 0x76, 0x88, 0x8e, 0xa6, - 0x78, 0x74, 0xc8, 0x3d, 0x77, 0xcf, 0x6d, 0x11, 0xdf, 0x7c, 0x86, 0xdc, 0x35, 0x9d, 0xbd, 0x14, 0x61, 0x50, 0xb7, - 0x6c, 0xa0, 0x58, 0x87, 0x4e, 0x50, 0x80, 0x51, 0x5b, 0x3e, 0x01, 0x1d, 0x1b, 0x0c, 0x2a, 0x82, 0x4f, 0x0a, 0xdb, - 0xa6, 0x41, 0xfe, 0x88, 0x77, 0x43, 0x87, 0xd7, 0x96, 0x3c, 0x10, 0xaf, 0xb0, 0xcf, 0x94, 0x70, 0xff, 0x82, 0x82, - 0xee, 0x28, 0x2f, 0x57, 0x85, 0xab, 0xd2, 0x00, 0x54, 0xd9, 0xf1, 0x5c, 0x6b, 0x4a, 0x5a, 0xc0, 0x4a, 0x49, 0xdd, - 0xf9, 0x4d, 0x44, 0xdc, 0x92, 0xa9, 0x98, 0xad, 0xba, 0x51, 0xe5, 0xa1, 0x44, 0x91, 0x8e, 0x3d, 0xdb, 0x39, 0x58, - 0x03, 0xe0, 0x29, 0x6c, 0x2f, 0xce, 0xb0, 0xa0, 0x8c, 0xcb, 0x96, 0xb9, 0x04, 0x8a, 0xfa, 0x61, 0x9c, 0x97, 0x1d, - 0x5f, 0xee, 0x8e, 0xb6, 0xf7, 0xd0, 0x1b, 0xb1, 0x31, 0x5e, 0x5f, 0x46, 0x4d, 0xbf, 0x78, 0x86, 0x2b, 0x4b, 0x41, - 0x1e, 0x68, 0xaa, 0x47, 0x18, 0x1d, 0x02, 0xd3, 0x94, 0x1f, 0xb1, 0xf1, 0x74, 0x38, 0x34, 0x64, 0xd0, 0x6b, 0x26, - 0xc6, 0xff, 0xfa, 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, 0x58, 0x12, 0xa3, 0x10, 0xbf, 0x38, - 0x55, 0xb6, 0x13, 0x42, 0x05, 0xc4, 0x43, 0xd7, 0xba, 0x71, 0x24, 0x55, 0xec, 0x49, 0xa1, 0xf1, 0xd4, 0x70, 0xdf, - 0x0b, 0x1d, 0xb3, 0x0e, 0xb3, 0xb8, 0xcd, 0x1a, 0x49, 0x8d, 0x71, 0x2a, 0x4c, 0x70, 0x4a, 0xb9, 0x8a, 0x04, 0x46, - 0xc7, 0xb3, 0x85, 0x41, 0x54, 0x49, 0x4c, 0x32, 0xb6, 0x16, 0xc2, 0xc4, 0xae, 0x73, 0x85, 0x69, 0xea, 0x22, 0xf5, - 0x9b, 0x81, 0xc9, 0x82, 0x86, 0xfc, 0x1e, 0x8d, 0xd6, 0x54, 0x4d, 0x01, 0x86, 0x71, 0x94, 0x6a, 0xfc, 0x5b, 0x84, - 0xda, 0x0c, 0x03, 0x00, 0xdb, 0xbc, 0x93, 0x99, 0xa8, 0x5e, 0x0b, 0x84, 0x40, 0x73, 0xf6, 0x53, 0x45, 0xb5, 0x33, - 0x0b, 0x46, 0xd1, 0x6e, 0xaf, 0x7c, 0x3e, 0x70, 0x42, 0x79, 0xac, 0x2e, 0x50, 0xaf, 0x64, 0xf1, 0x46, 0xa6, 0xbc, - 0x15, 0x17, 0x73, 0x4f, 0xb2, 0x0f, 0xf9, 0x08, 0xce, 0x2b, 0x74, 0x2a, 0x37, 0xdb, 0x44, 0x99, 0x25, 0x49, 0xc6, - 0x02, 0x63, 0xf3, 0x12, 0xcc, 0xa4, 0x66, 0xc6, 0xf0, 0x6b, 0x08, 0x2e, 0xb6, 0x73, 0x12, 0x6e, 0xee, 0xe7, 0x81, - 0x21, 0x34, 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, 0xe1, 0xce, 0x7f, 0x50, 0x58, - 0x83, 0xca, 0x88, 0xcb, 0x88, 0xf2, 0xcc, 0x81, 0x6e, 0x9a, 0x14, 0x71, 0x7a, 0xb6, 0x8a, 0x8b, 0x92, 0xa7, 0x50, - 0xa9, 0xa6, 0x6e, 0x51, 0x6f, 0x02, 0xf6, 0x86, 0x48, 0x92, 0xac, 0xa5, 0xb1, 0x15, 0xbb, 0x34, 0x48, 0xcf, 0xbd, - 0x61, 0x96, 0x5e, 0x55, 0x68, 0x48, 0x4b, 0xbd, 0xb3, 0x50, 0xc9, 0xfc, 0x15, 0xff, 0x19, 0xd4, 0x0a, 0x74, 0xb4, - 0x49, 0x31, 0x9e, 0x03, 0x23, 0xbe, 0x1b, 0xc1, 0xea, 0x01, 0xe2, 0xa2, 0x09, 0x4a, 0xbd, 0x23, 0x76, 0xfc, 0xdc, - 0xe4, 0xe1, 0x5d, 0xc8, 0x39, 0x83, 0x4f, 0x1f, 0x66, 0x89, 0x5a, 0xeb, 0x48, 0x8c, 0xd4, 0x0c, 0xa0, 0xe9, 0xa0, - 0xcc, 0x79, 0x2c, 0x82, 0x59, 0xcf, 0x24, 0x46, 0x3d, 0xae, 0x7f, 0x81, 0x86, 0xda, 0x6f, 0x56, 0x96, 0x67, 0xd5, - 0xdd, 0x97, 0x70, 0x60, 0x53, 0x5b, 0x41, 0x8f, 0xd7, 0x95, 0xbc, 0xbc, 0x54, 0xdd, 0xf6, 0x0b, 0x31, 0x72, 0xba, - 0xc6, 0xb5, 0x74, 0x5e, 0x2d, 0x58, 0xaf, 0x3b, 0xdd, 0x2c, 0xee, 0x66, 0x19, 0x0d, 0x84, 0xb5, 0x9d, 0x4f, 0x34, - 0x7f, 0xd6, 0x6c, 0xbb, 0x8f, 0xb7, 0x20, 0x66, 0x01, 0x00, 0xa4, 0x07, 0x51, 0xb0, 0xcc, 0x52, 0x1e, 0x50, 0x79, - 0x1f, 0x47, 0x59, 0x28, 0xbd, 0x9c, 0x65, 0xfc, 0xb4, 0x69, 0xac, 0x75, 0x56, 0x28, 0x43, 0x6b, 0xa3, 0x3b, 0x5d, - 0x65, 0x88, 0xed, 0x27, 0x71, 0xb6, 0x00, 0xf7, 0xc7, 0x0c, 0x85, 0x86, 0xce, 0x32, 0xd2, 0x44, 0xc3, 0x77, 0xdd, - 0x33, 0xc8, 0x28, 0x4e, 0xd6, 0x79, 0x25, 0xdd, 0xe8, 0xb3, 0x36, 0x12, 0xe6, 0x1e, 0xa2, 0x5f, 0xc5, 0xe0, 0x51, - 0xee, 0xf3, 0xda, 0xe8, 0x64, 0x5a, 0x46, 0xda, 0x9d, 0x9f, 0xd4, 0xcb, 0x2c, 0xd5, 0x3a, 0x6c, 0x9f, 0x61, 0x6f, - 0x8d, 0x49, 0x6f, 0x42, 0x6a, 0x18, 0x89, 0xcf, 0x67, 0xd4, 0x08, 0x01, 0x6d, 0x39, 0xfe, 0x0e, 0x9f, 0x61, 0x68, - 0x0a, 0x2c, 0x55, 0xdc, 0xc2, 0x6e, 0xf8, 0x9a, 0x4f, 0x56, 0x2d, 0x00, 0x11, 0xac, 0x7c, 0xbd, 0x8b, 0x57, 0x42, - 0x7d, 0xa6, 0xcd, 0x00, 0x90, 0x05, 0xa5, 0xdc, 0xf1, 0x53, 0x2a, 0x1d, 0x2c, 0x51, 0xb4, 0xbd, 0x9c, 0xbe, 0xd1, - 0xb1, 0xf1, 0x43, 0x7a, 0x2e, 0x60, 0xbb, 0x90, 0xdf, 0xba, 0x57, 0x2f, 0x51, 0x91, 0xda, 0x36, 0xeb, 0x01, 0xbe, - 0xdc, 0xa0, 0x49, 0x18, 0x41, 0x99, 0x32, 0x05, 0x30, 0xb8, 0xa9, 0x46, 0xc1, 0xa4, 0xd5, 0x48, 0xd8, 0x52, 0x4f, - 0xb2, 0xdc, 0xf4, 0xc1, 0xa9, 0xee, 0x11, 0xf4, 0x68, 0x87, 0x93, 0x96, 0xfd, 0x5a, 0xc1, 0xd1, 0xc9, 0xd5, 0x10, - 0x35, 0xf3, 0x5e, 0xdb, 0x91, 0x21, 0xe5, 0x32, 0x0c, 0x04, 0x53, 0x8e, 0x79, 0x7a, 0x6c, 0x3d, 0x23, 0xa2, 0x07, - 0xce, 0x3e, 0xd3, 0xad, 0xba, 0x92, 0x80, 0xe8, 0xf8, 0xcd, 0xd3, 0xd7, 0x57, 0xf1, 0xa5, 0x41, 0x51, 0x6a, 0x58, - 0xc4, 0x28, 0xd3, 0xbe, 0x4a, 0xc2, 0xe0, 0xfd, 0xfa, 0xfe, 0x67, 0x95, 0xa5, 0xf6, 0x7b, 0xb0, 0xb1, 0xa2, 0xaa, - 0x5f, 0x4b, 0x5e, 0x34, 0x05, 0x58, 0xf7, 0x59, 0xa2, 0x40, 0xee, 0xf7, 0x36, 0xcd, 0x7c, 0x13, 0x35, 0x6e, 0x36, - 0xac, 0x37, 0xae, 0xdb, 0xa5, 0xb6, 0x64, 0x47, 0x56, 0x22, 0x67, 0x16, 0x83, 0x19, 0x3f, 0x2a, 0x0c, 0x4a, 0xc3, - 0x06, 0x55, 0xa9, 0xf8, 0xbd, 0x11, 0xc1, 0xa9, 0x63, 0x55, 0x61, 0x4c, 0x03, 0x66, 0x5b, 0x51, 0x6b, 0x50, 0x07, - 0xa5, 0xb4, 0x35, 0x51, 0xd8, 0x7e, 0x67, 0x05, 0x35, 0xbf, 0xff, 0x69, 0x0c, 0xf9, 0x9a, 0x52, 0x50, 0x49, 0xc0, - 0xce, 0xa0, 0xd1, 0x53, 0x25, 0x0c, 0xa4, 0x20, 0x78, 0x02, 0x94, 0x2f, 0xa2, 0xc6, 0x6a, 0xb7, 0xaf, 0x4e, 0x8d, - 0xd1, 0x16, 0x10, 0x5a, 0x48, 0x8f, 0x2e, 0xfb, 0xb8, 0x8d, 0x75, 0x20, 0xf1, 0xe0, 0x04, 0xdb, 0xb9, 0xba, 0x46, - 0x23, 0xa1, 0xf9, 0x43, 0xa3, 0x01, 0xaf, 0x69, 0x05, 0x0a, 0xf5, 0x1c, 0x47, 0x43, 0x67, 0x87, 0x14, 0x44, 0x6c, - 0xd0, 0xc2, 0xbe, 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, 0x82, 0x61, 0x0b, 0xbf, - 0x39, 0x35, 0x05, 0x60, 0xc3, 0x63, 0x5d, 0x96, 0x6f, 0xd4, 0x44, 0x66, 0x71, 0x48, 0x22, 0x90, 0x6c, 0x37, 0x37, - 0xb7, 0x11, 0x6c, 0x7b, 0x0b, 0xb5, 0xa1, 0xfe, 0xf2, 0xb6, 0xfb, 0x3d, 0xc3, 0xcb, 0x3d, 0xb9, 0x77, 0xd3, 0x86, - 0xf2, 0x87, 0xfb, 0x57, 0xc9, 0xff, 0x55, 0x25, 0xf7, 0x5b, 0x65, 0xd6, 0x6d, 0xf1, 0x7e, 0xd7, 0x71, 0xcb, 0x31, - 0x1a, 0x04, 0xd6, 0x14, 0x18, 0x48, 0x4f, 0x1a, 0xd3, 0x44, 0x87, 0x54, 0x66, 0xcc, 0xe0, 0xd1, 0x05, 0x68, 0x0e, - 0xd3, 0x79, 0x1e, 0x03, 0x70, 0x80, 0x7f, 0xe4, 0x11, 0xea, 0x9f, 0xce, 0xf3, 0xe0, 0x2c, 0x18, 0x94, 0x83, 0x40, - 0x7f, 0xe2, 0x9a, 0x13, 0x2c, 0x40, 0xe7, 0x16, 0x33, 0x08, 0x36, 0x69, 0xcd, 0x1c, 0xe2, 0xc3, 0x64, 0x3a, 0x18, - 0xc4, 0x64, 0x03, 0x20, 0x7d, 0xf1, 0xc2, 0x3a, 0x07, 0x15, 0x7a, 0x41, 0xb6, 0xea, 0x2e, 0x9a, 0x15, 0x7b, 0xd5, - 0x4e, 0xf3, 0x7e, 0x3f, 0x9f, 0x97, 0x83, 0xa0, 0x51, 0x61, 0x61, 0xbc, 0xff, 0x68, 0xf3, 0x4b, 0xa3, 0x93, 0x26, - 0x18, 0xa6, 0xf6, 0x18, 0xd5, 0x2b, 0x9e, 0x66, 0xb4, 0x71, 0x3b, 0x56, 0xca, 0x17, 0x10, 0xc5, 0x03, 0x43, 0xd6, - 0xca, 0xbb, 0x73, 0xf0, 0xba, 0xdc, 0x78, 0x73, 0x44, 0x01, 0x76, 0x53, 0x18, 0x27, 0x35, 0x17, 0x5d, 0xd4, 0xc4, - 0x33, 0xd8, 0xe9, 0xea, 0xad, 0x44, 0xab, 0xf1, 0x5e, 0xbc, 0x6b, 0x36, 0xfe, 0x56, 0xee, 0xe9, 0x32, 0xf7, 0x2e, - 0x00, 0x71, 0x76, 0x2f, 0xae, 0xf6, 0xb0, 0xd4, 0xbd, 0x60, 0x60, 0x91, 0x43, 0xda, 0xd5, 0xea, 0xa1, 0x88, 0xd4, - 0x79, 0x0c, 0x06, 0x4c, 0xa6, 0x21, 0x35, 0x99, 0xf6, 0x0a, 0x05, 0x69, 0x63, 0xad, 0x05, 0xb4, 0xe1, 0xb0, 0xd8, - 0xb1, 0x1b, 0x76, 0xa7, 0x5b, 0x87, 0x42, 0x09, 0xa3, 0x57, 0xd7, 0xcd, 0x43, 0xad, 0xe1, 0x89, 0xa0, 0x07, 0xd5, - 0x68, 0x3f, 0x3d, 0x94, 0x27, 0xed, 0xb1, 0x00, 0x17, 0x3d, 0x7c, 0xf9, 0x52, 0xe0, 0x45, 0x7b, 0x07, 0x79, 0xce, - 0x7c, 0xaa, 0x7c, 0x10, 0x1b, 0x6e, 0x19, 0x3e, 0xb4, 0x8f, 0x6f, 0x05, 0x32, 0xa9, 0x3b, 0x9a, 0xda, 0xda, 0x1d, - 0x8d, 0x63, 0x02, 0xfd, 0xa6, 0x1c, 0xa5, 0x4c, 0x4c, 0x2d, 0x4b, 0x76, 0xd4, 0xcb, 0x95, 0x37, 0x54, 0xca, 0x8e, - 0x96, 0x6d, 0xce, 0x2f, 0x6d, 0x24, 0xf4, 0xfb, 0xda, 0x1d, 0x08, 0xdf, 0xa8, 0xf5, 0x86, 0xbc, 0x6c, 0x88, 0x58, - 0x0e, 0x31, 0x03, 0xc7, 0x0b, 0xa9, 0x5c, 0xbb, 0x8b, 0xa6, 0xaa, 0x6e, 0x67, 0x2b, 0x17, 0xb4, 0xc4, 0x5b, 0x29, - 0xb0, 0x8a, 0xd4, 0xe9, 0xf5, 0x54, 0xe2, 0x7d, 0x1f, 0xc5, 0xf6, 0x23, 0x60, 0x1b, 0x1b, 0x47, 0x63, 0xe3, 0x16, - 0xb1, 0xc1, 0x57, 0x51, 0x45, 0x0b, 0x0e, 0x10, 0xdc, 0x6d, 0x49, 0x2d, 0xcd, 0x1c, 0xe2, 0xbe, 0xe2, 0x01, 0xda, - 0x77, 0x71, 0xc4, 0xa9, 0x00, 0xdb, 0xba, 0xd6, 0x39, 0xab, 0xe5, 0x80, 0xcd, 0x44, 0xcf, 0x3f, 0xad, 0x1a, 0x89, - 0x18, 0x56, 0xd9, 0x48, 0x59, 0xa1, 0x3d, 0x28, 0x5d, 0xc2, 0xc5, 0x17, 0xe0, 0x65, 0xfb, 0x7e, 0x65, 0xf7, 0xd9, - 0x12, 0xfb, 0x87, 0x79, 0xd5, 0x04, 0x8f, 0xbc, 0xc6, 0xdb, 0x7b, 0x98, 0xf8, 0x52, 0x29, 0x84, 0x57, 0x29, 0x0d, - 0x25, 0x00, 0x83, 0x24, 0xa8, 0xe1, 0x4a, 0xdb, 0x66, 0x90, 0xca, 0x18, 0x76, 0xb7, 0x7a, 0xab, 0xff, 0xd3, 0x2a, - 0x5c, 0x54, 0xb2, 0x18, 0x93, 0x40, 0xe7, 0x54, 0xcb, 0x4d, 0x4c, 0xc1, 0xb3, 0x5d, 0x72, 0x04, 0x0a, 0x3b, 0x01, - 0xdc, 0x50, 0xc2, 0x7e, 0xc5, 0xdb, 0x50, 0xce, 0x5e, 0x59, 0xc9, 0x93, 0xdb, 0x97, 0x54, 0xd0, 0x84, 0x4c, 0x85, - 0xdd, 0xbf, 0xad, 0x0d, 0xfb, 0x22, 0x94, 0x23, 0x29, 0x70, 0x71, 0xd0, 0x39, 0x80, 0xfd, 0x41, 0x2e, 0x63, 0xf3, - 0x99, 0xf4, 0xfb, 0xea, 0xfd, 0xf3, 0x3c, 0x4b, 0x3e, 0xee, 0xbc, 0x37, 0x3c, 0xcd, 0x92, 0x01, 0x95, 0x88, 0xa9, - 0x75, 0x55, 0x0c, 0x97, 0xda, 0xc5, 0xb8, 0x41, 0x32, 0xe2, 0x7b, 0xa9, 0x43, 0x8c, 0x18, 0x5f, 0x64, 0x87, 0xa4, - 0xe4, 0x74, 0x59, 0x77, 0xf6, 0x5c, 0x8b, 0x66, 0xd0, 0x18, 0x6e, 0xc7, 0x7b, 0x49, 0xaf, 0x00, 0x15, 0x15, 0xba, - 0x67, 0x81, 0x6b, 0x78, 0x73, 0x49, 0x34, 0xb6, 0xf4, 0xb4, 0x25, 0x1a, 0xb8, 0x57, 0x26, 0x24, 0xd5, 0xc6, 0x01, - 0x16, 0xb1, 0xae, 0x3f, 0x86, 0x12, 0x80, 0x5a, 0x0d, 0xd2, 0x2b, 0x7d, 0x45, 0xa8, 0x4a, 0x42, 0x30, 0x3a, 0x91, - 0xf0, 0x32, 0xa0, 0x71, 0x66, 0x12, 0x2d, 0x6c, 0x70, 0x40, 0x5f, 0x54, 0x26, 0xd1, 0xd8, 0x90, 0x07, 0xb4, 0xb2, - 0x69, 0x00, 0x83, 0x0f, 0x92, 0x24, 0xfa, 0x7a, 0x69, 0x92, 0x40, 0x50, 0x82, 0xf2, 0x0d, 0xfa, 0x4b, 0xe9, 0xf9, - 0x58, 0xfe, 0xcb, 0x3b, 0x94, 0x7e, 0x08, 0x25, 0xc8, 0x14, 0x75, 0xc5, 0x34, 0x63, 0x47, 0x59, 0xb7, 0x31, 0x89, - 0xe7, 0x69, 0x77, 0x5b, 0x28, 0x97, 0x2e, 0xf0, 0x2b, 0xcb, 0x10, 0xc7, 0xfa, 0x79, 0xbc, 0x62, 0xc7, 0x21, 0xd7, - 0x78, 0xe9, 0xcf, 0xe3, 0x15, 0xce, 0x10, 0xad, 0x5a, 0x09, 0x44, 0xf9, 0xaf, 0xda, 0xc0, 0x21, 0xee, 0x13, 0x0c, - 0x72, 0x51, 0x79, 0x0f, 0x04, 0xf2, 0xb6, 0x82, 0x88, 0x34, 0xb3, 0xeb, 0x30, 0x22, 0xd5, 0x4e, 0x92, 0xf9, 0xf2, - 0x47, 0x99, 0x09, 0xef, 0x1b, 0x78, 0x6c, 0x36, 0xcb, 0xa6, 0x98, 0x2f, 0x54, 0x30, 0x07, 0xf7, 0x89, 0x8a, 0x4b, - 0x51, 0xf9, 0x4f, 0xd8, 0x05, 0x2f, 0xc6, 0x83, 0xd7, 0x6b, 0x04, 0xd8, 0xaf, 0xfc, 0x27, 0x6f, 0xcc, 0xde, 0x5a, - 0x37, 0xbe, 0xcc, 0x44, 0x7c, 0xe0, 0xa3, 0x5b, 0xca, 0x47, 0x77, 0x5e, 0xa6, 0x3f, 0x1b, 0x50, 0x22, 0xa3, 0xb2, - 0xe2, 0xab, 0x15, 0x4f, 0x67, 0xb7, 0x49, 0x94, 0x8d, 0x2a, 0x2e, 0x60, 0x7a, 0xc1, 0xf1, 0x2e, 0x59, 0x9f, 0x67, - 0xc9, 0x6b, 0x88, 0x3d, 0xb0, 0x92, 0x0a, 0x8b, 0x1f, 0x96, 0x99, 0x5a, 0xcc, 0x42, 0x56, 0x52, 0xf0, 0x60, 0x76, - 0x9d, 0x44, 0x6f, 0x97, 0x1e, 0x92, 0x9a, 0x99, 0xb2, 0x4d, 0xed, 0x08, 0xb5, 0xf1, 0x75, 0xa4, 0x1b, 0x6d, 0x01, - 0x00, 0xf7, 0x6c, 0x91, 0x46, 0x92, 0x89, 0xe1, 0xa4, 0x66, 0xdc, 0xa4, 0x17, 0x98, 0x1a, 0xd7, 0xac, 0xa2, 0x89, - 0xb3, 0x90, 0x01, 0xbd, 0x3f, 0xe0, 0xe5, 0xe0, 0x73, 0x06, 0xf7, 0x1f, 0xb4, 0x06, 0x2e, 0x0f, 0x8b, 0x7e, 0x5f, - 0x1e, 0x16, 0xdb, 0x6d, 0x79, 0x14, 0xf7, 0xfb, 0xf2, 0x28, 0x36, 0xfc, 0x83, 0x52, 0x6c, 0x1b, 0x73, 0x83, 0x84, - 0xe6, 0x12, 0xa2, 0x16, 0x8d, 0xe0, 0x0f, 0xcd, 0x72, 0x2e, 0xa2, 0xfc, 0x30, 0xe9, 0xf7, 0x7b, 0xcb, 0x99, 0x18, - 0xe4, 0xc3, 0x24, 0xca, 0x87, 0x89, 0xe7, 0x84, 0xf8, 0x9b, 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, 0x5d, 0x84, 0x25, - 0x96, 0x42, 0x97, 0xec, 0xcf, 0x25, 0xf0, 0x44, 0x39, 0xaf, 0x36, 0xc0, 0xc0, 0x46, 0x78, 0xe7, 0x30, 0xe1, 0x24, - 0xd6, 0x35, 0xa0, 0x9d, 0x6e, 0x6a, 0x7a, 0x41, 0x57, 0xf4, 0x12, 0xf9, 0xd9, 0x0b, 0x30, 0x58, 0x3a, 0x64, 0xf9, - 0x74, 0x30, 0xb8, 0x20, 0x2b, 0x56, 0xce, 0xc3, 0x78, 0x10, 0xae, 0x67, 0xf9, 0xf0, 0x22, 0xba, 0x20, 0xe4, 0xab, - 0x62, 0x41, 0x7b, 0xab, 0x51, 0xf9, 0x31, 0x83, 0xe0, 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, 0x86, 0xe8, - 0xb6, 0xc7, 0x49, 0x02, 0x8e, 0xc9, 0xae, 0xf8, 0x68, 0xac, 0x0a, 0xef, 0xfa, 0x8e, 0xd0, 0x5e, 0x2f, 0x71, 0x83, - 0xf4, 0x5d, 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, 0xde, 0xc0, 0x81, 0x3d, 0x08, 0xf3, 0x59, 0x3c, 0x7c, 0x13, 0xbd, - 0x21, 0xe4, 0x2b, 0x49, 0xaf, 0xd5, 0xa5, 0x0c, 0xc2, 0x20, 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, 0xdd, 0x11, 0xb0, 0xf0, 0x1a, 0x4f, 0xd7, 0x87, - 0x2c, 0x9e, 0x0e, 0x06, 0x6b, 0xa4, 0xea, 0x2a, 0xf7, 0x9a, 0x2c, 0xe8, 0x05, 0x4e, 0x04, 0x01, 0x86, 0x3e, 0x13, - 0x6b, 0x43, 0xc3, 0xdf, 0x30, 0xf8, 0xf8, 0x8e, 0x5d, 0x8c, 0xee, 0xe8, 0x2d, 0x7b, 0xb3, 0x1d, 0x4f, 0x81, 0x99, - 0x5a, 0xcd, 0xc2, 0xbb, 0xc3, 0xcb, 0xd9, 0x25, 0xbb, 0x8b, 0xee, 0x8e, 0xa0, 0xa1, 0x57, 0xec, 0x0e, 0x01, 0x97, - 0xd2, 0xc7, 0xcb, 0xc1, 0x1b, 0xb2, 0x3f, 0x18, 0xa4, 0x24, 0x0a, 0xaf, 0x43, 0xaf, 0x95, 0x6f, 0xe8, 0x1d, 0xa1, - 0x2b, 0x76, 0x8b, 0xa3, 0x71, 0xc9, 0xf0, 0x83, 0x73, 0x76, 0x57, 0x5f, 0x87, 0xde, 0x6e, 0x4e, 0x44, 0x27, 0x88, - 0x11, 0xfa, 0x1a, 0x38, 0x9a, 0xe5, 0xc2, 0x4c, 0xc0, 0x93, 0xb9, 0xc8, 0x68, 0x51, 0x68, 0x06, 0xe2, 0xac, 0x04, - 0xc4, 0x92, 0xa8, 0xfb, 0xcd, 0x46, 0x67, 0xb0, 0x9c, 0xfb, 0xfd, 0x5e, 0x65, 0xe8, 0x01, 0x22, 0x67, 0x76, 0xd2, - 0x83, 0x9e, 0x4f, 0x0f, 0xf0, 0x13, 0xbd, 0x6a, 0x10, 0x27, 0xf3, 0xbb, 0x65, 0xf4, 0x9b, 0x47, 0x1f, 0x7e, 0xe8, - 0xa6, 0x3c, 0x22, 0xff, 0xf7, 0x29, 0x4f, 0x99, 0x47, 0x6f, 0x2a, 0x0f, 0x04, 0xcf, 0x5b, 0x93, 0x4a, 0x23, 0x51, - 0x8d, 0xce, 0x56, 0x31, 0x68, 0x23, 0x51, 0xdb, 0xa0, 0x9f, 0xd0, 0xc2, 0x0a, 0x22, 0xe4, 0x1c, 0xbc, 0x00, 0x83, - 0x54, 0x08, 0x95, 0xa3, 0x16, 0x25, 0x1a, 0x82, 0xe4, 0xb2, 0xe4, 0x2a, 0x7c, 0x0e, 0xa1, 0xea, 0xf4, 0x71, 0x26, - 0xc2, 0x86, 0x1e, 0x87, 0x3e, 0x00, 0xfc, 0xaf, 0x3b, 0xe4, 0xa2, 0xe4, 0x97, 0x78, 0x36, 0xb7, 0x09, 0x46, 0xc1, - 0x12, 0xd1, 0x0c, 0x6d, 0x83, 0xd8, 0x8f, 0x25, 0xc1, 0x7a, 0x24, 0x8d, 0x47, 0xa5, 0x39, 0x22, 0xfc, 0x28, 0x3e, - 0x8a, 0x9e, 0xc6, 0x86, 0x44, 0x72, 0x24, 0x91, 0x7c, 0x00, 0x84, 0x93, 0xa0, 0xbf, 0xb8, 0x6b, 0xb2, 0x6b, 0x21, - 0x31, 0xe8, 0x4f, 0x4b, 0xa6, 0x65, 0xf7, 0xaa, 0xc7, 0xbe, 0x22, 0xc8, 0x1d, 0xd3, 0x7f, 0x79, 0x7d, 0xf8, 0xe7, - 0x12, 0x67, 0xd0, 0x7a, 0xbe, 0xa8, 0xce, 0xcc, 0xbc, 0xc1, 0x8d, 0xbc, 0x2e, 0x6b, 0xd7, 0xe5, 0x0b, 0xbe, 0xc7, - 0x6f, 0x2b, 0x2e, 0xd2, 0x72, 0xef, 0x97, 0xaa, 0x8d, 0xe7, 0x54, 0xae, 0x57, 0x2e, 0xce, 0x8a, 0x32, 0x4e, 0xf5, - 0xa4, 0x2e, 0xc6, 0x1a, 0xb6, 0xe1, 0xf7, 0x88, 0xba, 0x92, 0x96, 0xa3, 0xa7, 0x94, 0xab, 0x66, 0xca, 0xc5, 0x3a, - 0xcf, 0x7f, 0xde, 0x49, 0xc5, 0x29, 0x6e, 0xa6, 0x20, 0x55, 0x6a, 0xb9, 0x80, 0xea, 0x39, 0x6a, 0xb9, 0x5b, 0x9a, - 0x1d, 0xe0, 0xdc, 0x36, 0xd5, 0xc7, 0xca, 0xec, 0xc2, 0x4b, 0x6e, 0xdc, 0x9f, 0x4c, 0x19, 0x16, 0x8c, 0x42, 0x9b, - 0x55, 0x57, 0xda, 0xbe, 0xd0, 0x3a, 0x0d, 0xc3, 0x95, 0x1f, 0x2f, 0x20, 0x5d, 0xc0, 0x38, 0x5e, 0x94, 0x4c, 0x8c, - 0xdb, 0xa3, 0xb7, 0x82, 0xf8, 0x92, 0xad, 0x40, 0xc0, 0x5c, 0xc3, 0xdb, 0x75, 0x1d, 0x6d, 0xf7, 0xc4, 0x29, 0xa3, - 0x72, 0x15, 0x8b, 0xef, 0xe3, 0x95, 0x81, 0x4c, 0x56, 0xc7, 0x63, 0x63, 0x4c, 0xa7, 0x3f, 0x25, 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, 0x9e, 0x31, 0x57, 0x08, 0x56, 0xaa, 0xec, 0xf6, - 0x9d, 0x1a, 0x53, 0x31, 0x83, 0x29, 0xb6, 0x9d, 0xc5, 0xa4, 0x5b, 0xf9, 0xa7, 0x9d, 0xfb, 0x65, 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, 0x59, 0x49, 0xbe, 0x2b, 0x8d, 0xb9, 0xf4, - 0xa9, 0xd2, 0xc4, 0x70, 0xb2, 0x18, 0x71, 0x91, 0x2e, 0xea, 0xcc, 0xae, 0x85, 0xcf, 0x78, 0x19, 0xce, 0xf9, 0xc2, - 0xe8, 0xa6, 0x74, 0xe9, 0x05, 0x8b, 0x75, 0xa7, 0x37, 0x2b, 0x8d, 0x95, 0x12, 0x71, 0x6b, 0x96, 0x09, 0x94, 0xa5, - 0xac, 0x95, 0xf0, 0xa6, 0x68, 0xd9, 0x4a, 0x1a, 0x79, 0xcf, 0x1c, 0xdc, 0xc7, 0x7e, 0x40, 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, 0x26, 0x56, 0x0a, 0xd8, 0x0b, 0xbc, 0xbc, 0xe1, 0x99, 0xaa, 0x69, 0xd9, 0xa5, 0xe2, 0x00, 0xe3, 0xf3, - 0x32, 0x0c, 0xcb, 0xe1, 0x05, 0x58, 0x4b, 0xec, 0x87, 0xab, 0x39, 0x5f, 0xa8, 0xdf, 0x10, 0x70, 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, 0x9e, 0xaa, 0x99, 0x69, 0xc9, 0x7f, 0x12, 0xb5, 0xa1, 0x89, - 0xbe, 0xc1, 0x2a, 0xf2, 0x87, 0xc7, 0x47, 0x97, 0x40, 0xc6, 0xce, 0xae, 0x64, 0xe6, 0x43, 0xdf, 0x47, 0x06, 0xf7, - 0xdc, 0x94, 0x33, 0xae, 0x82, 0x44, 0x19, 0xb8, 0x7b, 0x35, 0x4b, 0xc6, 0x5a, 0x84, 0xef, 0x1e, 0x15, 0x45, 0x9f, - 0x49, 0xd3, 0x80, 0xee, 0x23, 0xc1, 0x1c, 0xe8, 0xbd, 0x42, 0x87, 0xcb, 0x6a, 0x9b, 0x09, 0xf8, 0x8b, 0x04, 0xf9, - 0xad, 0xd0, 0xab, 0x1a, 0x83, 0x2a, 0xda, 0x45, 0x2c, 0xfd, 0xfb, 0x88, 0x1f, 0x65, 0xf3, 0x2f, 0x73, 0x8f, 0x57, - 0x12, 0x06, 0x3f, 0xa4, 0x66, 0x93, 0xcc, 0xdb, 0x2b, 0xf6, 0x3d, 0x74, 0xd4, 0xa3, 0xd6, 0x78, 0x5f, 0xbd, 0xe0, - 0x14, 0x62, 0x94, 0x50, 0x74, 0x12, 0x0c, 0xe0, 0x76, 0x09, 0x29, 0xee, 0x06, 0xbb, 0x69, 0x5e, 0xf3, 0xa2, 0xe0, - 0x7c, 0x5d, 0x55, 0x81, 0x1f, 0xd0, 0x70, 0xbe, 0xd8, 0x0d, 0x61, 0x38, 0xa6, 0xad, 0x6b, 0x18, 0x84, 0x19, 0xc3, - 0x48, 0x08, 0x5e, 0xff, 0xa2, 0x27, 0x34, 0x89, 0x57, 0xdf, 0xf1, 0x4f, 0x19, 0x2f, 0x14, 0x91, 0x06, 0x11, 0x52, - 0x37, 0xf1, 0x8d, 0x4c, 0x93, 0x02, 0x0a, 0x01, 0x46, 0x01, 0x95, 0xd8, 0xd0, 0x54, 0xfc, 0xad, 0x16, 0x1f, 0xfc, - 0xd4, 0x74, 0x3c, 0x1a, 0xd7, 0xad, 0xce, 0xa8, 0xa0, 0x33, 0xd0, 0xa3, 0x56, 0xd4, 0xd3, 0xa0, 0x95, 0x60, 0x1a, - 0x69, 0xde, 0xba, 0x87, 0xc0, 0x2b, 0xd3, 0xe2, 0x9d, 0x07, 0x74, 0x73, 0xe6, 0x83, 0x27, 0x8f, 0xe9, 0x99, 0x43, - 0x4f, 0xae, 0xd8, 0x51, 0xd5, 0x43, 0xed, 0xbd, 0x19, 0xa1, 0xa0, 0xdf, 0xc7, 0x14, 0xe8, 0x46, 0x50, 0x7b, 0x57, - 0xf7, 0x1f, 0xcb, 0x5d, 0x0e, 0xdf, 0x71, 0x96, 0x1b, 0xc0, 0x52, 0x91, 0xb5, 0x02, 0x8f, 0x02, 0xd4, 0xa5, 0x32, - 0x84, 0x2d, 0xe6, 0x70, 0xa8, 0xec, 0x56, 0xad, 0x86, 0x92, 0x1c, 0x96, 0x23, 0x70, 0x08, 0x5d, 0x97, 0x83, 0x72, - 0xb4, 0xcc, 0xaa, 0xf7, 0xf8, 0x5b, 0xb3, 0x0e, 0x49, 0x76, 0x1f, 0xeb, 0xc0, 0x2d, 0xeb, 0x30, 0xfd, 0x68, 0x90, - 0x02, 0xd0, 0x64, 0x23, 0x70, 0x09, 0xc0, 0x7b, 0xfb, 0x8f, 0x08, 0xb5, 0x32, 0xbd, 0x97, 0xb1, 0x50, 0xdf, 0x37, - 0x92, 0xa0, 0x84, 0x66, 0x42, 0xe5, 0x58, 0x0a, 0xde, 0x79, 0xa4, 0x73, 0x52, 0x67, 0xe2, 0x3d, 0x88, 0xd3, 0xc2, - 0x07, 0xf6, 0x16, 0x04, 0xe7, 0x2c, 0xe8, 0x1d, 0xde, 0x66, 0xb5, 0xd4, 0x46, 0x0f, 0x14, 0xc0, 0xef, 0x06, 0x77, - 0x08, 0xf2, 0xd5, 0x18, 0xae, 0x95, 0xbc, 0x09, 0xf9, 0xb0, 0xa0, 0x07, 0x64, 0x60, 0x9f, 0xc5, 0x30, 0xa6, 0x07, - 0xe4, 0xd0, 0x3e, 0x4b, 0x37, 0x80, 0x03, 0xa9, 0x47, 0x95, 0x1e, 0x40, 0x83, 0x7e, 0xb7, 0x2d, 0xb2, 0x24, 0xeb, - 0xc7, 0xd2, 0x28, 0x62, 0xa0, 0x4a, 0x10, 0x51, 0x8b, 0x7f, 0x3e, 0x98, 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, 0xbd, 0xc9, 0xe0, 0xc0, 0xc8, 0xf0, - 0xa5, 0xb7, 0x7f, 0xe1, 0x6b, 0x2d, 0xdd, 0x13, 0x83, 0x92, 0x3c, 0x3e, 0x50, 0xf4, 0xef, 0x5e, 0x59, 0xf9, 0xd4, - 0x4e, 0xff, 0x76, 0x6b, 0xd6, 0xe7, 0xe1, 0x68, 0xb2, 0xdd, 0xf6, 0xb4, 0x81, 0x2b, 0xd5, 0x2a, 0x04, 0xec, 0x42, - 0x49, 0xf6, 0x0f, 0x20, 0x2a, 0x42, 0x33, 0xee, 0x66, 0xd9, 0x90, 0xc8, 0xf8, 0x71, 0x3a, 0xcb, 0x86, 0x60, 0x87, - 0x7b, 0x51, 0x89, 0xcb, 0x51, 0x6b, 0x83, 0xd3, 0xb3, 0x24, 0x84, 0x50, 0x0e, 0x58, 0xd9, 0xad, 0xfa, 0x73, 0xa7, - 0xcc, 0x84, 0xd4, 0x64, 0x75, 0x3b, 0xa5, 0x7b, 0x98, 0xe6, 0x7b, 0x66, 0x04, 0x07, 0xdc, 0xdb, 0x5f, 0xf5, 0xc7, - 0x30, 0xc9, 0x34, 0x39, 0x45, 0xf2, 0x8b, 0xf4, 0x14, 0x92, 0x76, 0xe8, 0xa9, 0x22, 0x80, 0x13, 0x6a, 0x3f, 0x86, - 0xdf, 0x30, 0xee, 0xdf, 0x35, 0x5f, 0xbb, 0xa9, 0x88, 0x9e, 0x52, 0x2c, 0x53, 0x93, 0xd3, 0x24, 0x2b, 0x12, 0x88, - 0xda, 0xa8, 0x9a, 0x11, 0x3d, 0x71, 0x31, 0x1f, 0x15, 0xe1, 0xf3, 0x6a, 0xfd, 0x9f, 0x21, 0x7c, 0x46, 0xe1, 0x06, - 0x70, 0x79, 0xc5, 0xe5, 0x79, 0xf8, 0xec, 0x29, 0xdd, 0x9b, 0x7c, 0x73, 0x40, 0xf7, 0x0e, 0x9e, 0x3c, 0x23, 0x00, - 0x8b, 0x76, 0x79, 0x1e, 0x1e, 0x3c, 0x7b, 0x46, 0xf7, 0xbe, 0xfd, 0x96, 0xee, 0x4d, 0x9e, 0x1c, 0x34, 0xd2, 0x26, - 0xcf, 0xbe, 0xa5, 0x7b, 0xdf, 0x3c, 0x6d, 0xa4, 0x1d, 0x8c, 0x9f, 0xd1, 0xbd, 0xbf, 0x7f, 0x63, 0xd2, 0xfe, 0x06, - 0xd9, 0xbe, 0x3d, 0xc0, 0xff, 0x4c, 0xda, 0xe4, 0xd9, 0x13, 0xba, 0x37, 0x19, 0x43, 0x25, 0xcf, 0x5c, 0x25, 0xe3, - 0x09, 0x7c, 0xfc, 0x04, 0xfe, 0xfb, 0x1b, 0x09, 0x16, 0xb4, 0x92, 0x2c, 0x17, 0xa8, 0x3f, 0x43, 0x11, 0x27, 0xaa, - 0x26, 0x12, 0x1e, 0x62, 0x66, 0xf5, 0x4d, 0x1c, 0x06, 0xc4, 0xa5, 0x43, 0x41, 0x74, 0x6f, 0x3c, 0x7a, 0x46, 0x02, - 0x1f, 0x9e, 0xee, 0xc6, 0x07, 0x19, 0xcb, 0xc5, 0x3c, 0xfb, 0x2a, 0x37, 0xb1, 0x15, 0x3c, 0x00, 0xab, 0x8f, 0x7e, - 0xae, 0x4a, 0xce, 0xb3, 0xaf, 0x2a, 0xb9, 0x9b, 0xeb, 0xf7, 0x16, 0xa0, 0xbc, 0xbf, 0x6a, 0xd9, 0x4d, 0xa1, 0x42, - 0xa7, 0xb5, 0x46, 0x9f, 0x7d, 0xc4, 0xf4, 0xc1, 0xc0, 0xbb, 0x61, 0xff, 0xb4, 0x53, 0x4e, 0xeb, 0x1b, 0x8d, 0x42, - 0x8d, 0xca, 0x43, 0xc2, 0x8e, 0xa0, 0xe8, 0xc1, 0x00, 0x78, 0x02, 0x0f, 0xf7, 0xed, 0xdf, 0x2c, 0xe3, 0x63, 0x47, - 0x19, 0xbf, 0xa0, 0x0c, 0x01, 0x8d, 0x7a, 0x98, 0xdd, 0xf4, 0xb0, 0xd1, 0xad, 0x5e, 0xb2, 0x54, 0x27, 0x53, 0xd3, - 0x33, 0xd8, 0xd7, 0xba, 0x96, 0x7b, 0x46, 0x14, 0x2d, 0x2f, 0xf6, 0x52, 0x3e, 0xab, 0xd8, 0x4f, 0x4b, 0x54, 0x6f, - 0x45, 0x8d, 0x37, 0x32, 0x9b, 0x55, 0xec, 0x7b, 0xf3, 0x06, 0xb8, 0x19, 0xf6, 0xbb, 0x7a, 0xf2, 0x03, 0x67, 0x70, - 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, 0x5c, 0xd9, 0xff, 0x6a, 0xc8, 0x4b, 0x50, 0xb8, 0xd5, 0x2c, 0x6f, - 0xa7, 0x30, 0x84, 0x10, 0xfc, 0x71, 0xc9, 0x00, 0x70, 0x20, 0xc0, 0x60, 0xac, 0x65, 0x40, 0xcd, 0x96, 0x8f, 0x36, - 0x5c, 0xa9, 0x27, 0x81, 0x33, 0xb8, 0x90, 0x45, 0xc2, 0x4f, 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, 0xb0, 0x05, 0x91, 0x21, - 0x78, 0xb8, 0xfd, 0x6b, 0xa9, 0x02, 0x47, 0xf5, 0xfb, 0x5c, 0xfa, 0x6e, 0x4f, 0xc6, 0x8e, 0x1c, 0xa7, 0x7e, 0x2a, - 0x1c, 0xfc, 0x37, 0xa9, 0x6b, 0x63, 0xb9, 0x92, 0x32, 0xcb, 0xb2, 0xb0, 0xa3, 0x50, 0xcb, 0x3d, 0x2a, 0x0f, 0x92, - 0x2f, 0xe4, 0x10, 0xc9, 0x02, 0xa3, 0x50, 0x90, 0xe1, 0x84, 0x8a, 0xd1, 0x5a, 0x94, 0xcb, 0xec, 0xa2, 0x0a, 0x37, - 0x4a, 0xa1, 0xcc, 0x29, 0xfa, 0x76, 0x83, 0x03, 0x09, 0x89, 0xb2, 0xf2, 0x6d, 0xfc, 0x36, 0x44, 0xb0, 0x3a, 0xae, - 0x6d, 0xa1, 0xb8, 0xb7, 0x3f, 0x79, 0xda, 0xc5, 0x1f, 0x19, 0x17, 0x50, 0x17, 0x8b, 0x69, 0x38, 0xb1, 0xb1, 0x6f, - 0xdc, 0x17, 0x56, 0xd3, 0x03, 0x50, 0xdf, 0xa5, 0x12, 0x23, 0xa8, 0xaf, 0x8c, 0x7d, 0x6c, 0x8f, 0x31, 0x39, 0x83, - 0x58, 0xc3, 0x2a, 0x67, 0xa6, 0xfa, 0x46, 0xd8, 0x11, 0x00, 0x37, 0x42, 0x6b, 0x14, 0x04, 0x1e, 0xaf, 0x42, 0x3c, - 0x2f, 0x55, 0xf8, 0xd6, 0x8c, 0xd0, 0x31, 0x78, 0x53, 0xd9, 0x46, 0x66, 0xd2, 0x17, 0x0c, 0x9a, 0x63, 0x5b, 0x47, - 0x61, 0xb5, 0x95, 0x65, 0x47, 0x00, 0x37, 0x90, 0x1d, 0x9a, 0x8b, 0xe7, 0xac, 0x9a, 0x67, 0x8b, 0xc8, 0x04, 0x05, - 0x5c, 0x0a, 0xcb, 0xa0, 0x7d, 0xba, 0x47, 0xb6, 0xe3, 0x10, 0xba, 0xe1, 0x3e, 0x82, 0xf1, 0xb4, 0x9b, 0x82, 0x15, - 0x44, 0x23, 0xc4, 0xc3, 0x8c, 0x59, 0x7c, 0xaf, 0x34, 0xe5, 0xa9, 0x6a, 0x09, 0x04, 0x8e, 0x42, 0xa8, 0x8b, 0x5d, - 0xa3, 0x04, 0x97, 0xa9, 0x11, 0xcc, 0x60, 0xc7, 0x8e, 0xd4, 0x76, 0xc9, 0x39, 0x1d, 0xaa, 0x29, 0x2d, 0xf5, 0x94, - 0x6a, 0x5f, 0x43, 0x31, 0x2f, 0xd1, 0x43, 0x0f, 0x5c, 0x0f, 0xb4, 0x43, 0x5e, 0x49, 0x27, 0x26, 0x82, 0x4e, 0xab, - 0x4d, 0xd8, 0xb9, 0x91, 0x6e, 0x59, 0x8d, 0xbc, 0x63, 0x68, 0x76, 0xc4, 0x4b, 0x3f, 0x50, 0x17, 0x40, 0x84, 0xdc, - 0xdb, 0x22, 0x73, 0x44, 0xb3, 0xac, 0x7c, 0x05, 0x65, 0x71, 0xc4, 0xd6, 0x15, 0x70, 0x2d, 0x05, 0x93, 0x4b, 0x1e, - 0xf1, 0x14, 0x11, 0x01, 0x8f, 0x95, 0x76, 0x7d, 0xa7, 0x25, 0x84, 0x66, 0x29, 0x10, 0x37, 0x17, 0xc5, 0xb9, 0xb6, - 0x81, 0x2c, 0x80, 0xbe, 0xfd, 0x9c, 0x5d, 0x79, 0xe1, 0x60, 0x37, 0x57, 0x99, 0x78, 0xc1, 0x2f, 0x32, 0xc1, 0x53, - 0x04, 0xbb, 0xba, 0x35, 0x0f, 0xdc, 0xb1, 0x6d, 0x60, 0xf9, 0xf6, 0x1d, 0x2c, 0x98, 0x32, 0xd4, 0x4a, 0x89, 0x4c, - 0x44, 0x02, 0x32, 0xfb, 0xcc, 0xdd, 0x9b, 0x4c, 0xbc, 0x89, 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, 0x0e, 0xbf, 0xc4, 0x50, 0x2b, 0xe3, 0x7e, 0x1f, 0x24, 0x66, 0xd2, 0x36, 0x65, 0x26, 0x23, 0xa9, 0xd1, 0x42, - 0x2a, 0xca, 0x07, 0x13, 0xb2, 0xbb, 0x52, 0x2d, 0x23, 0x6a, 0xbf, 0x0a, 0xc5, 0x6c, 0x1c, 0x4d, 0x08, 0x9d, 0x74, - 0xac, 0x77, 0xd3, 0x5a, 0xc8, 0x34, 0x7a, 0x16, 0x79, 0x3e, 0x9d, 0x05, 0xab, 0xa6, 0xc5, 0x21, 0xe3, 0xd3, 0x62, - 0x30, 0x20, 0xda, 0xa5, 0x70, 0x83, 0xf5, 0x80, 0x29, 0x8d, 0x8b, 0xb7, 0x66, 0x5a, 0xfd, 0x4a, 0xaa, 0x90, 0xf4, - 0x9e, 0x01, 0x49, 0x26, 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, 0xde, 0xc6, 0x6f, 0x23, 0x7b, 0x59, 0xd0, 0x45, 0xbe, 0x40, 0x21, 0x6b, 0x1e, 0x86, 0xd5, 0xb0, 0x3d, - 0x88, 0x64, 0xbf, 0x3d, 0x09, 0x8d, 0xc6, 0xc0, 0x02, 0xd9, 0xa1, 0x11, 0xb8, 0x08, 0xad, 0xfc, 0xed, 0x10, 0x5c, - 0xb8, 0x2c, 0x22, 0xcb, 0x50, 0xc7, 0x6f, 0x6a, 0x37, 0x41, 0xf5, 0x0a, 0x9d, 0xa6, 0xb0, 0x2a, 0x65, 0x92, 0x0f, - 0xbf, 0x5e, 0xc9, 0x02, 0x33, 0x79, 0x5d, 0xf6, 0xe8, 0x6b, 0xbb, 0xbd, 0x03, 0x53, 0xb0, 0xee, 0x93, 0xf7, 0xf5, - 0xe3, 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, 0xa3, 0x4c, - 0xd6, 0xfe, 0xd5, 0x5d, 0xa4, 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, 0x86, 0x85, 0x57, 0xc3, - 0x4b, 0xb2, 0x1f, 0xa6, 0x83, 0x89, 0x12, 0x8c, 0xdd, 0xb1, 0x65, 0x19, 0xaa, 0xc4, 0xd5, 0xfe, 0x05, 0x79, 0x7c, - 0x41, 0x6f, 0xe9, 0x0d, 0x3d, 0xa5, 0x27, 0x40, 0xf8, 0xef, 0x0e, 0x27, 0x7c, 0x38, 0x79, 0xda, 0xef, 0xf7, 0xce, - 0xfb, 0xfd, 0xde, 0x99, 0x31, 0xa0, 0xd0, 0xbb, 0xe8, 0xb2, 0xa6, 0xfa, 0xd7, 0x55, 0xbd, 0x98, 0x9e, 0xa8, 0x8d, - 0x9b, 0xf0, 0x2c, 0x0f, 0xaf, 0xf6, 0xef, 0xc8, 0x10, 0x1f, 0x2f, 0x72, 0x29, 0x8b, 0xf0, 0x72, 0xff, 0x8e, 0xd0, - 0x93, 0x23, 0xd0, 0x9b, 0x62, 0x7d, 0x27, 0x8f, 0xef, 0x74, 0x6d, 0x84, 0xbe, 0x0c, 0x13, 0xd8, 0x26, 0xb7, 0xcc, - 0xde, 0xb5, 0x27, 0x63, 0x88, 0x65, 0x72, 0xe7, 0x95, 0x77, 0xf7, 0xf8, 0x96, 0xec, 0xdf, 0x82, 0xa7, 0xa8, 0x25, - 0x7f, 0xb3, 0xf0, 0x86, 0xb5, 0x6a, 0x78, 0x7c, 0x47, 0x4f, 0x5b, 0x8d, 0x78, 0x7c, 0x47, 0xa2, 0xf0, 0x86, 0x5d, - 0xd2, 0x53, 0x76, 0x45, 0xe8, 0x79, 0xbf, 0x7f, 0xd6, 0xef, 0xcb, 0x7e, 0xff, 0xa7, 0x38, 0x0c, 0xe3, 0x61, 0x41, - 0xf6, 0x25, 0xbd, 0xdb, 0x9f, 0xf0, 0x27, 0x64, 0x16, 0xea, 0xe6, 0xab, 0x05, 0x67, 0x55, 0xde, 0x2a, 0xd7, 0x1d, - 0x05, 0x6b, 0x85, 0x3b, 0xa6, 0x9e, 0x4e, 0xe8, 0x0d, 0x2b, 0xe8, 0x29, 0x8b, 0x49, 0x74, 0x0d, 0xad, 0x38, 0x9f, - 0x15, 0xd1, 0x0d, 0x3d, 0x65, 0x67, 0xb3, 0x38, 0x3a, 0xa5, 0x27, 0x2c, 0x1f, 0x4e, 0x20, 0xef, 0xe9, 0xf0, 0x86, - 0xec, 0x9f, 0x90, 0x28, 0x3c, 0xd1, 0xbf, 0xef, 0xe8, 0x25, 0x0f, 0x4f, 0xa8, 0x57, 0xcd, 0x09, 0x31, 0xd5, 0x37, - 0x6a, 0x3f, 0x21, 0x91, 0x3f, 0x98, 0x27, 0xd6, 0x9e, 0xe6, 0x91, 0xa3, 0x8d, 0x69, 0x19, 0x82, 0xbe, 0xb9, 0x0c, - 0x6f, 0x08, 0x99, 0x36, 0xc7, 0x0e, 0x06, 0x74, 0xf6, 0x28, 0x4a, 0x08, 0xbd, 0xf1, 0x4b, 0xbd, 0xc1, 0x31, 0x34, - 0x23, 0xa4, 0xd2, 0x4e, 0x31, 0x0d, 0xd7, 0xc1, 0x6b, 0x0d, 0xd6, 0x71, 0xde, 0xef, 0x87, 0xeb, 0x7e, 0x1f, 0x22, - 0xdd, 0x17, 0x33, 0x13, 0xdb, 0xcd, 0x91, 0x4d, 0x7a, 0x03, 0xda, 0xff, 0xd7, 0x83, 0x01, 0x74, 0xc6, 0x2b, 0x29, - 0xbc, 0x19, 0xbc, 0x7e, 0x7c, 0x47, 0x54, 0x1d, 0x05, 0x15, 0x32, 0x2c, 0xe8, 0x1b, 0x9a, 0x01, 0xe0, 0xd7, 0xeb, - 0xc1, 0x80, 0x44, 0xe6, 0x33, 0x32, 0x7d, 0x7d, 0x78, 0x32, 0x1d, 0x0c, 0x5e, 0x9b, 0x6d, 0xf2, 0x96, 0xdd, 0x53, - 0x0a, 0xac, 0xbf, 0xb3, 0x7e, 0xff, 0xed, 0x51, 0x4c, 0xce, 0x0b, 0x1e, 0x7f, 0x9c, 0x36, 0xdb, 0xf2, 0xd6, 0x45, - 0x55, 0x3b, 0xeb, 0xf7, 0xd7, 0xfd, 0xfe, 0x29, 0x60, 0x17, 0xcd, 0x9c, 0xaf, 0x27, 0x48, 0x5b, 0xe6, 0x8e, 0x22, - 0x69, 0x92, 0x43, 0x63, 0x68, 0x5b, 0xac, 0xda, 0x36, 0xeb, 0xc8, 0xc0, 0xe2, 0xa8, 0x59, 0x51, 0x5c, 0x93, 0x28, - 0xec, 0x9d, 0x6d, 0xb7, 0xa7, 0x8c, 0xb1, 0x98, 0x80, 0xf4, 0xc3, 0x7f, 0x7d, 0x5a, 0x37, 0x62, 0x88, 0x09, 0x89, - 0xcc, 0xe6, 0x66, 0x69, 0x0f, 0x81, 0x88, 0xc3, 0xa6, 0x7f, 0x6f, 0xee, 0xe5, 0xa2, 0x76, 0x7c, 0xeb, 0x2f, 0x00, - 0x42, 0x24, 0x59, 0xc8, 0x67, 0x38, 0x06, 0x65, 0x06, 0x40, 0xe6, 0x91, 0x9a, 0x79, 0x09, 0x20, 0xc0, 0x64, 0xbb, - 0x1d, 0x8d, 0xc7, 0x13, 0x5a, 0xb0, 0xd1, 0xdf, 0x9e, 0x3d, 0xae, 0x1e, 0x87, 0x41, 0x30, 0xc8, 0x48, 0x4b, 0x4f, - 0x61, 0x17, 0x6b, 0xb5, 0x0f, 0x46, 0xf0, 0x9a, 0x7d, 0xbc, 0xce, 0xbe, 0x98, 0x7d, 0x44, 0xc2, 0xda, 0x60, 0x1c, - 0xb9, 0x48, 0x5b, 0x7a, 0xbb, 0x7b, 0x18, 0x4c, 0x2e, 0xd2, 0xcf, 0xb0, 0x9d, 0x3e, 0xff, 0xe6, 0xc1, 0x78, 0xc2, - 0xc1, 0xe8, 0x2e, 0x0a, 0xfa, 0x4c, 0xdb, 0x6e, 0x2b, 0xff, 0x12, 0xf8, 0x16, 0x53, 0x41, 0xc7, 0x66, 0x59, 0xb8, - 0x41, 0x45, 0xd4, 0xd1, 0x32, 0xa8, 0x6a, 0x65, 0x3b, 0x07, 0xd4, 0x12, 0xab, 0x32, 0x71, 0x0b, 0x0c, 0x43, 0x86, - 0xba, 0xdc, 0xe3, 0xea, 0x5f, 0xbc, 0x90, 0x06, 0x3e, 0xc3, 0x89, 0x08, 0x3d, 0x6e, 0x8d, 0xfb, 0xdc, 0x9a, 0xf8, - 0x0c, 0xb7, 0x56, 0x22, 0x89, 0x35, 0xb0, 0xa4, 0xe6, 0x72, 0x94, 0xb0, 0xa3, 0x92, 0xf1, 0x59, 0x19, 0x25, 0x34, - 0x86, 0x07, 0xc9, 0xc4, 0x4c, 0x46, 0x09, 0xda, 0x27, 0xba, 0x08, 0x83, 0x7f, 0x01, 0x66, 0x3f, 0xcd, 0xe1, 0xaf, - 0x24, 0xd3, 0xe4, 0x10, 0x02, 0x42, 0x1c, 0x8e, 0x67, 0x71, 0x38, 0x26, 0x51, 0x72, 0x04, 0x4f, 0xf0, 0x5f, 0x11, - 0x8e, 0x49, 0xad, 0xef, 0x30, 0x52, 0x5d, 0x6e, 0x13, 0x06, 0x70, 0x65, 0xe3, 0xd9, 0x24, 0xb2, 0xd2, 0x5d, 0xf9, - 0x78, 0x34, 0x7e, 0x46, 0xa6, 0x71, 0x28, 0x07, 0x09, 0xa1, 0xe0, 0xdd, 0x1b, 0x96, 0xc3, 0x44, 0xc3, 0xb3, 0x01, - 0x9b, 0x57, 0x3a, 0x36, 0x4f, 0xc2, 0x09, 0x08, 0xc3, 0x84, 0x1c, 0xeb, 0x3d, 0x48, 0x29, 0xfa, 0x3c, 0xc7, 0x7e, - 0xea, 0x23, 0x08, 0xb3, 0xa3, 0x96, 0x8a, 0xaf, 0x00, 0xe8, 0x12, 0x07, 0x87, 0xda, 0x33, 0x5f, 0xcc, 0xc2, 0xd2, - 0xa3, 0x52, 0xa6, 0xba, 0x7d, 0xd1, 0xa0, 0xfc, 0xa6, 0x41, 0xfb, 0x82, 0x0c, 0x26, 0xb4, 0x3c, 0x9a, 0xf0, 0x27, - 0x10, 0xc0, 0xa3, 0x11, 0xf1, 0x4b, 0xe1, 0xc4, 0x40, 0x78, 0x15, 0x64, 0xa0, 0xd2, 0x5a, 0x35, 0x66, 0x64, 0x2b, - 0xde, 0x83, 0x30, 0x29, 0x7b, 0x37, 0x72, 0x9d, 0xa7, 0x10, 0x15, 0x6c, 0x9d, 0x57, 0x7b, 0x97, 0x60, 0xc9, 0x1e, - 0x57, 0x10, 0x27, 0x6c, 0xbd, 0x02, 0xec, 0xdc, 0x47, 0x9b, 0xb2, 0xde, 0x53, 0xdf, 0xed, 0x61, 0xcb, 0xe1, 0x55, - 0x25, 0xf7, 0x26, 0xe3, 0xf1, 0x78, 0xf4, 0x07, 0x1c, 0x1d, 0x40, 0x68, 0x49, 0x64, 0xf8, 0x64, 0x80, 0xc6, 0x5d, - 0x57, 0xdc, 0x1b, 0x17, 0x8a, 0xb2, 0xd2, 0xc9, 0x84, 0x80, 0xf8, 0xd9, 0xf4, 0x0d, 0xf6, 0x15, 0xd7, 0xf1, 0x4f, - 0x76, 0x3f, 0x31, 0x2b, 0x5a, 0xad, 0xd4, 0xd1, 0xbb, 0x93, 0xd3, 0xd7, 0x1f, 0x5e, 0xff, 0xf6, 0xf2, 0xec, 0xf5, - 0xdb, 0x57, 0xaf, 0xdf, 0xbe, 0xfe, 0xf0, 0xcf, 0x07, 0x18, 0x6c, 0xdf, 0x56, 0xc4, 0x8e, 0xbd, 0x77, 0x8f, 0xf1, - 0x6a, 0xf1, 0x85, 0xb3, 0x07, 0xee, 0x16, 0x0b, 0xb0, 0x09, 0x86, 0x5b, 0x10, 0x54, 0x33, 0x1a, 0x95, 0xbe, 0x27, - 0x20, 0xa3, 0x51, 0x21, 0x1b, 0x0f, 0x2b, 0xb6, 0x42, 0x2e, 0xde, 0x31, 0x1c, 0x7c, 0x64, 0x7f, 0x2b, 0xce, 0x84, - 0xdb, 0xd1, 0xd6, 0xac, 0x08, 0xf8, 0x7c, 0xad, 0x45, 0xe5, 0x71, 0x21, 0x6a, 0x6f, 0xdb, 0xe7, 0x90, 0x50, 0x8f, - 0xc8, 0x75, 0xf0, 0xbe, 0x0d, 0xb2, 0xc7, 0x47, 0xde, 0x93, 0xf2, 0x0c, 0xf5, 0x39, 0x1a, 0x3e, 0x6a, 0x3c, 0xa3, - 0x13, 0x73, 0x6d, 0x74, 0xa8, 0x67, 0x05, 0xec, 0x6f, 0x25, 0xc6, 0x86, 0x68, 0x0f, 0x29, 0x62, 0x7d, 0x38, 0xdd, - 0xef, 0xee, 0xcd, 0xe8, 0x7b, 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, 0xf7, 0x5c, 0x29, 0x9a, 0xb7, 0x2e, 0xb0, 0x07, 0x6a, 0x5e, 0xc7, 0x4b, 0x16, 0x02, 0x36, 0xe3, - 0xbe, 0x5d, 0x24, 0xce, 0xef, 0x9d, 0x4e, 0xc8, 0xfe, 0xc1, 0x94, 0x0f, 0x59, 0x49, 0xc5, 0x80, 0x95, 0xf5, 0x0e, - 0x35, 0xe7, 0x6d, 0x42, 0x2e, 0x76, 0x69, 0xb8, 0x18, 0xf2, 0x87, 0x2e, 0x49, 0x1f, 0x78, 0xc3, 0xa1, 0xda, 0x36, - 0x17, 0x43, 0x9a, 0x72, 0xba, 0x4b, 0x65, 0x40, 0x88, 0x74, 0x15, 0x57, 0xa4, 0xd6, 0x47, 0x55, 0xea, 0x24, 0x1d, - 0xd7, 0xd9, 0xe6, 0x33, 0x97, 0x6c, 0x75, 0xbb, 0xf6, 0xaf, 0xd5, 0xed, 0x0b, 0x33, 0x90, 0xbf, 0x3f, 0x11, 0xd5, - 0xc4, 0x40, 0x74, 0x01, 0x15, 0xfc, 0x13, 0xbc, 0x3c, 0x79, 0xa4, 0x15, 0xa0, 0xf7, 0x9d, 0x1d, 0x5d, 0x7b, 0xbc, - 0x31, 0x8b, 0xad, 0x25, 0xce, 0x59, 0xe5, 0x3b, 0xcb, 0xab, 0xb2, 0x15, 0xba, 0x8e, 0x60, 0xbf, 0x84, 0x1d, 0x7d, - 0xf7, 0xb6, 0x01, 0x10, 0xa5, 0xb0, 0x72, 0x67, 0xbf, 0xf0, 0xce, 0x7e, 0x61, 0xcf, 0x7e, 0xbb, 0x09, 0x94, 0x0f, - 0x2b, 0xb4, 0xec, 0x95, 0x14, 0x95, 0x69, 0xf2, 0xb8, 0xa9, 0xcb, 0x42, 0x5a, 0xcc, 0xf7, 0x2d, 0xed, 0x7a, 0x3a, - 0xa6, 0x12, 0xd5, 0x23, 0x3f, 0x60, 0xab, 0xf6, 0x4b, 0xf2, 0xf0, 0x3d, 0xf3, 0x7f, 0xf6, 0x06, 0x79, 0xdf, 0xdd, - 0xee, 0xff, 0xe6, 0x42, 0x07, 0xb7, 0xb5, 0x54, 0x78, 0xea, 0xea, 0xb8, 0xc0, 0xbb, 0x5a, 0xfa, 0xf0, 0x5d, 0xed, - 0x5d, 0xa6, 0x97, 0x5d, 0x05, 0xa8, 0x41, 0x62, 0x7d, 0xc5, 0x8b, 0x2c, 0xa9, 0xad, 0x42, 0xe3, 0x84, 0x43, 0x68, - 0x0f, 0xef, 0xe0, 0x02, 0x39, 0x2c, 0x21, 0xf4, 0x63, 0x65, 0x04, 0x80, 0x3e, 0x8b, 0x7d, 0xc2, 0xc3, 0x8c, 0x0c, - 0x7c, 0x89, 0x5f, 0x29, 0x7d, 0x71, 0xf1, 0xfe, 0x4e, 0x66, 0x82, 0x5e, 0x25, 0x36, 0xbb, 0x94, 0xed, 0x98, 0x1f, - 0xfe, 0x17, 0x18, 0x0d, 0xc2, 0x6b, 0x4b, 0xb6, 0x2f, 0x3a, 0x66, 0xb9, 0x82, 0xa3, 0xb6, 0x74, 0x65, 0x96, 0xad, - 0xeb, 0x67, 0x35, 0xcc, 0xf4, 0x99, 0x72, 0x02, 0xb2, 0x2f, 0xe4, 0xee, 0xa7, 0xba, 0x62, 0x41, 0x8e, 0x26, 0xe3, - 0x29, 0x11, 0x83, 0x41, 0x2b, 0xf9, 0x10, 0x93, 0x87, 0xc3, 0x1d, 0xe6, 0x52, 0xe8, 0x7e, 0x78, 0x7d, 0x80, 0xfa, - 0x1a, 0x5b, 0x92, 0x6c, 0x2a, 0xf6, 0x17, 0x98, 0xc5, 0x02, 0x71, 0x74, 0xf0, 0x8b, 0xf3, 0x05, 0x80, 0x2c, 0xc3, - 0x32, 0xd3, 0xc2, 0xa2, 0x32, 0x55, 0x3e, 0xb2, 0x05, 0x93, 0x87, 0xe3, 0x99, 0xdf, 0x73, 0xc7, 0xe0, 0x10, 0x12, - 0x4d, 0xac, 0xf1, 0x8b, 0x9f, 0x05, 0xe3, 0x38, 0x94, 0x47, 0xb2, 0xf1, 0x5d, 0x49, 0xa2, 0xb1, 0x31, 0x55, 0xd6, - 0x57, 0x89, 0x6a, 0x98, 0x90, 0xc7, 0x05, 0xd9, 0x2f, 0xe8, 0xd2, 0x1f, 0x4b, 0x4c, 0xdf, 0x8f, 0xf7, 0x27, 0x63, - 0xf2, 0x38, 0x7e, 0x3c, 0x31, 0x70, 0xc3, 0x7e, 0x8e, 0x7c, 0xb8, 0x24, 0xfb, 0xcd, 0x2a, 0xc1, 0x14, 0xd5, 0xf4, - 0xcc, 0xaf, 0x24, 0x19, 0x2c, 0x07, 0xe9, 0xe3, 0x56, 0x5e, 0xac, 0x55, 0x8f, 0xf7, 0xfa, 0x90, 0x4f, 0x89, 0x68, - 0xdc, 0x18, 0xd6, 0xf4, 0x2a, 0xfe, 0x53, 0x16, 0x51, 0x29, 0x01, 0x91, 0x10, 0xd4, 0xdb, 0xd9, 0x45, 0x96, 0xc4, - 0x22, 0x8d, 0xd2, 0x9a, 0xd0, 0xf4, 0x88, 0x4d, 0xc6, 0xb3, 0x94, 0xa5, 0x87, 0x93, 0x67, 0xb3, 0xc9, 0xb3, 0xe8, - 0x60, 0x1c, 0xa5, 0x83, 0x01, 0x24, 0x1f, 0x8c, 0xc1, 0xc5, 0x0e, 0x7e, 0xb3, 0x03, 0x18, 0xba, 0x23, 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, 0x0b, 0xf9, 0xff, 0xe3, 0x86, 0x71, 0xdf, 0x5d, 0xc2, 0x2c, - 0xae, 0xeb, 0x6c, 0xb4, 0x2a, 0x64, 0x25, 0xe1, 0x36, 0xa1, 0x44, 0x61, 0xa3, 0x78, 0xb5, 0xca, 0xb5, 0x8b, 0xd8, - 0xbc, 0xa2, 0x00, 0xee, 0x02, 0x71, 0x8a, 0x81, 0x85, 0x36, 0x06, 0x72, 0x9f, 0x78, 0x21, 0x99, 0x55, 0xfb, 0x98, - 0x7b, 0xe4, 0x9f, 0x21, 0x18, 0xa3, 0x8a, 0xa3, 0xf1, 0x4c, 0x61, 0x5d, 0x7c, 0x4e, 0xde, 0xfb, 0x6f, 0x1c, 0x45, - 0xf6, 0x68, 0x06, 0x3d, 0x41, 0xe4, 0x3c, 0xe2, 0xec, 0xc9, 0xe4, 0x65, 0xe0, 0x7e, 0x06, 0x2b, 0xfd, 0x75, 0xb7, - 0x19, 0x6b, 0xdb, 0xa3, 0x7b, 0x61, 0x84, 0xa2, 0x9f, 0xf0, 0x9d, 0xa9, 0x17, 0x70, 0x09, 0xd5, 0xc0, 0xae, 0x2f, - 0x2f, 0x79, 0x09, 0x20, 0x42, 0x99, 0xe8, 0xf7, 0x7b, 0x7f, 0x1a, 0x68, 0xd2, 0x92, 0x17, 0x6f, 0x32, 0x61, 0x9d, - 0x71, 0xa0, 0xa9, 0x40, 0xfd, 0x3f, 0x56, 0xf6, 0x99, 0x8e, 0xc9, 0xcc, 0x7f, 0x1c, 0x4e, 0x48, 0xd4, 0x7c, 0x4d, - 0x3e, 0x73, 0x9a, 0x7e, 0xe6, 0x8a, 0xf6, 0x1f, 0xc8, 0xcc, 0x0d, 0x87, 0x0c, 0xf5, 0x97, 0x8e, 0x79, 0x32, 0x7a, - 0x9d, 0x98, 0x1d, 0x09, 0x56, 0xcd, 0x20, 0x0a, 0x7b, 0x01, 0x0f, 0xea, 0x5a, 0x16, 0x4f, 0x61, 0xf6, 0x41, 0x8d, - 0x28, 0x0e, 0xd9, 0x78, 0x16, 0xca, 0x70, 0x02, 0xf6, 0xbd, 0x93, 0x31, 0xdc, 0x07, 0x64, 0xf8, 0xb1, 0x0a, 0xb1, - 0x73, 0x90, 0xf6, 0xb1, 0x42, 0xc5, 0x04, 0x40, 0x04, 0x42, 0xde, 0x7e, 0x5f, 0xaa, 0x24, 0x7c, 0x5d, 0x62, 0x4a, - 0xa1, 0x3e, 0xf8, 0x4f, 0xa4, 0xea, 0x8e, 0xe9, 0x57, 0xeb, 0xc7, 0x9f, 0x09, 0xc5, 0xa7, 0xbb, 0x94, 0xf8, 0x16, - 0x82, 0x3b, 0x4b, 0xd0, 0x41, 0x54, 0x68, 0xc6, 0xf6, 0x30, 0xbf, 0x2b, 0xee, 0xe7, 0x77, 0xc5, 0xff, 0x3b, 0x7e, - 0x57, 0x3c, 0xc4, 0x18, 0x56, 0x16, 0x1a, 0x7e, 0x16, 0x8c, 0x83, 0xe8, 0x3f, 0xe7, 0x13, 0xef, 0xe5, 0xa9, 0xaf, - 0x32, 0x31, 0xbd, 0x87, 0x69, 0xf6, 0x09, 0x0a, 0xc2, 0x2a, 0xee, 0xd2, 0x93, 0x75, 0x65, 0x6f, 0xad, 0x64, 0x88, - 0x79, 0x1e, 0x60, 0x8d, 0xc2, 0xca, 0x03, 0xba, 0x47, 0xd5, 0x06, 0x71, 0x22, 0x78, 0x18, 0x33, 0x2b, 0x7d, 0xdf, - 0x6e, 0x8d, 0x0a, 0xf3, 0x41, 0x2e, 0x0a, 0xb2, 0x9b, 0x8f, 0x67, 0xe3, 0x28, 0xc4, 0x06, 0xfc, 0xc7, 0x8c, 0x55, - 0x43, 0x36, 0xdf, 0xc9, 0x48, 0xed, 0x98, 0x3c, 0x4d, 0x76, 0x49, 0xef, 0x80, 0x77, 0xc8, 0xcf, 0xeb, 0x8f, 0x61, - 0x21, 0x0d, 0xbf, 0x25, 0x2f, 0xe3, 0x22, 0xab, 0x96, 0x57, 0x59, 0x82, 0x4c, 0x17, 0xbc, 0xf8, 0x62, 0xa6, 0xcb, - 0xfb, 0x58, 0x1f, 0x30, 0x9e, 0x52, 0xbc, 0x6e, 0x88, 0xd2, 0xd7, 0x2d, 0xcf, 0x0a, 0x75, 0x79, 0x52, 0x31, 0xdb, - 0xb3, 0x12, 0x9c, 0x4e, 0xc1, 0x04, 0x5f, 0xff, 0x74, 0xbd, 0x8f, 0x01, 0x17, 0x14, 0x6a, 0x4e, 0x0b, 0xb9, 0x32, - 0x58, 0x4e, 0x16, 0xba, 0x13, 0x30, 0x43, 0xa5, 0xc0, 0x0b, 0x14, 0xfc, 0x45, 0x03, 0x23, 0xfa, 0xca, 0xfd, 0x26, - 0x03, 0x83, 0x74, 0x69, 0x4e, 0x84, 0xb1, 0xe3, 0x76, 0x8a, 0xb4, 0x15, 0xe5, 0x8c, 0xb3, 0xf7, 0xea, 0x4a, 0x01, - 0x06, 0x78, 0x9b, 0x9b, 0xe8, 0x3c, 0x41, 0xaf, 0x05, 0xa5, 0xf3, 0x06, 0xee, 0x66, 0x19, 0x19, 0xe1, 0xe2, 0xe3, - 0xca, 0x63, 0xc1, 0x3d, 0xfb, 0x85, 0x58, 0x1a, 0xcd, 0x34, 0x18, 0xb3, 0x79, 0xc1, 0x02, 0x85, 0x0a, 0x14, 0x58, - 0xce, 0xb4, 0xa5, 0x69, 0x35, 0xe4, 0xfb, 0x07, 0x68, 0x6d, 0x5a, 0x0d, 0xf8, 0xfe, 0x41, 0x1d, 0x65, 0x87, 0x90, - 0xe5, 0xc8, 0xcf, 0xa0, 0x5e, 0xd7, 0x91, 0x49, 0x31, 0xd9, 0xfd, 0xfa, 0x52, 0x7f, 0x54, 0x37, 0xe0, 0xfa, 0x01, - 0x08, 0x60, 0x03, 0x70, 0x08, 0x54, 0x83, 0xa5, 0x11, 0xc1, 0xa2, 0x4c, 0xa1, 0x7d, 0x0d, 0xbd, 0x37, 0x1a, 0xfe, - 0x0b, 0xdc, 0x45, 0xe4, 0xca, 0xff, 0x04, 0x81, 0xbf, 0xa2, 0x4c, 0x2b, 0x53, 0xfc, 0x4f, 0xb4, 0x7a, 0x85, 0x72, - 0xd6, 0xb4, 0xe6, 0x83, 0x68, 0x4d, 0x84, 0x6a, 0xc6, 0x10, 0xfc, 0x5b, 0x59, 0xa6, 0x2d, 0x55, 0x95, 0xfa, 0xd0, - 0x78, 0xad, 0x15, 0xce, 0xf2, 0x71, 0xe4, 0xbd, 0xc6, 0xd0, 0xb1, 0x89, 0xb3, 0x94, 0x53, 0xa9, 0xb3, 0x4f, 0xfb, - 0x32, 0x72, 0x80, 0xd3, 0x09, 0x1b, 0x4f, 0x93, 0x43, 0x39, 0x4d, 0x1c, 0x64, 0x7e, 0xce, 0x30, 0xb2, 0xaa, 0x01, - 0x61, 0x51, 0x36, 0x94, 0xb6, 0x00, 0x93, 0x9c, 0x10, 0x32, 0xc5, 0x50, 0x14, 0xf9, 0x48, 0xf7, 0xc3, 0x7a, 0xb3, - 0xba, 0x2f, 0xde, 0x69, 0x80, 0xd3, 0x30, 0x81, 0x40, 0xe0, 0x45, 0x7c, 0x93, 0x89, 0x4b, 0xf0, 0x18, 0x1e, 0xc0, - 0x97, 0xe0, 0x26, 0x97, 0xb2, 0xdf, 0xab, 0x30, 0xc7, 0xb5, 0x05, 0x0c, 0x1a, 0xac, 0x1e, 0x44, 0x87, 0x4b, 0x69, - 0xb3, 0xab, 0x00, 0xb1, 0x31, 0x85, 0x58, 0x16, 0x6c, 0x6d, 0xd9, 0xb3, 0xef, 0x55, 0xd3, 0xd0, 0x3a, 0xe1, 0x58, - 0x5c, 0xe6, 0x10, 0x45, 0x65, 0x10, 0x83, 0x3b, 0x92, 0xc7, 0xe7, 0x3d, 0x12, 0xe1, 0x05, 0x01, 0xb7, 0xb2, 0x58, - 0x86, 0x2b, 0xba, 0x1c, 0xdd, 0xd2, 0xf5, 0xe8, 0x86, 0x8e, 0xe9, 0xe4, 0xef, 0x63, 0xb0, 0xc8, 0xd6, 0xa9, 0x77, - 0x74, 0x3d, 0x5a, 0xd2, 0x6f, 0xc7, 0xf4, 0xe0, 0x6f, 0x60, 0xc2, 0x87, 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, 0xae, 0xf8, 0x55, 0xc9, 0x52, - 0xd8, 0x16, 0xb0, 0x7c, 0x3d, 0xaf, 0xa8, 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, 0x8e, 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, 0xca, 0xd3, 0xf6, - 0x75, 0xb0, 0xb1, 0xaa, 0xe8, 0x86, 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, 0xbe, 0x87, 0x88, 0xca, 0x50, 0xde, 0xe0, 0x1f, 0x18, 0x3c, 0x99, 0xad, 0xd2, 0x30, - 0x19, 0xdd, 0xd1, 0x78, 0xb4, 0x44, 0x38, 0x18, 0xb6, 0x4e, 0x15, 0xde, 0xfa, 0x05, 0xa4, 0xdf, 0xd2, 0x78, 0x74, - 0x43, 0x53, 0x6b, 0x73, 0x6a, 0xa0, 0xae, 0x7a, 0x63, 0x7a, 0x1b, 0xc1, 0xeb, 0xbb, 0x68, 0x49, 0x61, 0x2b, 0x1d, - 0xe7, 0xd9, 0xa5, 0x88, 0x52, 0x8a, 0x08, 0x84, 0x6b, 0x44, 0x0e, 0x5c, 0x6a, 0xb4, 0xc1, 0xf5, 0x00, 0xca, 0xd0, - 0x70, 0x81, 0xcb, 0x41, 0x3c, 0x5a, 0x7a, 0x64, 0x6a, 0xa9, 0x2f, 0xb2, 0x08, 0x1f, 0xed, 0x6c, 0xb4, 0x14, 0xcf, - 0x88, 0x85, 0x71, 0x05, 0x43, 0xa8, 0x0b, 0x2b, 0x4d, 0x41, 0xd2, 0x05, 0x8e, 0xec, 0x85, 0x45, 0x15, 0x6e, 0xc0, - 0xb4, 0xe8, 0x0e, 0xcc, 0xa3, 0x40, 0xe1, 0xe0, 0x12, 0xa4, 0x9f, 0x50, 0xb6, 0x73, 0x94, 0x26, 0x87, 0x37, 0x41, - 0xe9, 0xce, 0x04, 0x21, 0xed, 0xea, 0x26, 0x5b, 0xd2, 0x37, 0xd8, 0xde, 0xa1, 0x53, 0x51, 0x41, 0xf5, 0xb9, 0x05, - 0x93, 0x25, 0x1b, 0x84, 0x2d, 0x61, 0x7a, 0xa6, 0xd7, 0x80, 0x3d, 0xbd, 0x7f, 0xb0, 0x33, 0xdf, 0xc5, 0xec, 0xd3, - 0x7e, 0x19, 0x8d, 0x95, 0x05, 0x6f, 0x6e, 0x89, 0xdd, 0x92, 0x8d, 0xa7, 0xcb, 0xc3, 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, - 0x96, 0x69, 0x98, 0xe2, 0x22, 0x30, 0x29, 0xfd, 0x7e, 0x98, 0xb3, 0x94, 0x78, 0xd0, 0xa1, 0xee, 0xd4, 0x4e, 0x7d, - 0x21, 0x08, 0xf0, 0x48, 0xea, 0x1c, 0x9b, 0xfc, 0x7d, 0x3c, 0x0b, 0xd4, 0x40, 0x04, 0x51, 0x76, 0x88, 0x8f, 0x18, - 0xb8, 0x28, 0xd2, 0x71, 0x3b, 0x5d, 0x11, 0x17, 0xbb, 0xc7, 0x2c, 0xc4, 0x49, 0xc2, 0x5c, 0xb3, 0x6c, 0xc8, 0xaa, - 0x08, 0x13, 0x74, 0x61, 0x60, 0x96, 0x37, 0x64, 0xd5, 0xfe, 0x01, 0x44, 0x6a, 0xb5, 0x65, 0xac, 0xba, 0xca, 0xf8, - 0x16, 0x80, 0xac, 0x19, 0x63, 0x07, 0x7f, 0x1b, 0xcf, 0xd4, 0x37, 0x51, 0xc8, 0x8f, 0x0e, 0xfe, 0x06, 0xc9, 0x87, - 0xdf, 0x22, 0x33, 0x07, 0xc9, 0x8d, 0x82, 0x2e, 0x9b, 0xb3, 0xae, 0xa1, 0x34, 0x71, 0xed, 0x95, 0x7a, 0xed, 0x49, - 0xb3, 0xf6, 0x0a, 0x74, 0xa7, 0x36, 0xbc, 0x87, 0xb2, 0x9d, 0x05, 0x13, 0x74, 0x34, 0xbb, 0x03, 0x1d, 0xbc, 0x53, - 0x04, 0xbd, 0x4c, 0x42, 0xe3, 0x11, 0xaa, 0x8c, 0x7a, 0x61, 0x47, 0x76, 0xb3, 0x2e, 0x99, 0x67, 0xc0, 0x1c, 0xdb, - 0x73, 0x48, 0x0c, 0x73, 0x75, 0x50, 0xa7, 0xac, 0x1c, 0xe6, 0x78, 0x00, 0xaf, 0x99, 0x1c, 0x8a, 0x41, 0xae, 0x51, - 0xbe, 0x2f, 0x58, 0x31, 0x2c, 0x07, 0xb9, 0xe6, 0x66, 0xa6, 0xcd, 0xd8, 0xb4, 0x89, 0x0e, 0xcf, 0xbc, 0x62, 0x47, - 0xab, 0x1e, 0xf0, 0xb1, 0xe0, 0xc9, 0xec, 0x7b, 0x3e, 0xbe, 0x01, 0x4e, 0x66, 0x73, 0x1b, 0x2d, 0xe9, 0x5d, 0x94, - 0xd2, 0x9b, 0x68, 0x4d, 0x97, 0xd1, 0x85, 0x31, 0x31, 0x4e, 0x6a, 0x38, 0x07, 0xa0, 0x55, 0x00, 0x89, 0xa7, 0x7e, - 0xbd, 0xe7, 0x49, 0x15, 0x2e, 0x69, 0x0a, 0x6e, 0xc3, 0xbe, 0x7d, 0xe6, 0x95, 0x2f, 0x91, 0xda, 0x20, 0xc6, 0x9a, - 0x35, 0x54, 0xdc, 0x78, 0xeb, 0x3e, 0x12, 0x35, 0xec, 0x5c, 0x17, 0x9b, 0xa8, 0x1a, 0x4e, 0xa6, 0x25, 0x20, 0xb6, - 0x96, 0xc3, 0xa1, 0x3b, 0x42, 0x76, 0x8f, 0x1f, 0x1d, 0xe8, 0xb9, 0x27, 0x2d, 0xb6, 0x6d, 0xcb, 0x1f, 0x18, 0xc2, - 0x94, 0x7e, 0xfe, 0xc8, 0x07, 0xc4, 0x8a, 0x4b, 0x38, 0x1b, 0x81, 0x3a, 0x5a, 0xa1, 0xd3, 0xef, 0x55, 0x58, 0xe8, - 0x03, 0x7c, 0x73, 0x1b, 0x25, 0xf4, 0x2e, 0xca, 0x3d, 0xb2, 0xb6, 0xac, 0x99, 0x9c, 0x9e, 0x65, 0x21, 0x6f, 0x1f, - 0xe8, 0xe5, 0x02, 0x40, 0xb4, 0x06, 0xb1, 0x2f, 0x75, 0x3d, 0x00, 0xa7, 0x21, 0x34, 0x09, 0x8d, 0xe0, 0xaa, 0x82, - 0x30, 0x02, 0xae, 0x24, 0xfc, 0x0d, 0x26, 0x2a, 0xf0, 0x05, 0xb8, 0xc8, 0xa4, 0x69, 0xce, 0x83, 0xda, 0x1f, 0xc9, - 0xd3, 0xa2, 0xed, 0xed, 0x0a, 0xa3, 0x09, 0xc6, 0x9e, 0x68, 0x9f, 0x47, 0xca, 0x51, 0x5c, 0x24, 0x61, 0x36, 0xba, - 0x55, 0xe7, 0x39, 0xcd, 0x46, 0x77, 0xfa, 0x57, 0x45, 0xc7, 0xf4, 0x3b, 0x1d, 0xd0, 0x46, 0x49, 0xdf, 0x3a, 0xce, - 0x06, 0xb4, 0x5e, 0x2c, 0x8d, 0xff, 0xb5, 0x1c, 0xdd, 0x52, 0x39, 0xba, 0xf3, 0x2d, 0xa9, 0x26, 0xd3, 0xe2, 0x50, - 0xa0, 0x21, 0x55, 0xe7, 0xf7, 0x05, 0xf0, 0x73, 0xa5, 0xf1, 0x9d, 0x36, 0xdf, 0x7b, 0xed, 0x3f, 0xef, 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, 0xcb, 0xed, 0x56, 0xc5, 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, 0x5c, 0xd7, 0xcf, 0xda, 0xd4, 0xe8, 0x15, 0x58, 0xf8, - 0x6e, 0x94, 0x79, 0x24, 0xb7, 0x08, 0xa9, 0x0a, 0xac, 0xd4, 0x2d, 0x24, 0x98, 0x7f, 0x25, 0x67, 0xab, 0x32, 0x5f, - 0x3d, 0xf2, 0xa0, 0x9c, 0x4d, 0x4f, 0x7f, 0x43, 0x82, 0x76, 0xd7, 0x91, 0xe6, 0xf1, 0x16, 0x1d, 0x3e, 0xbb, 0xd6, - 0x12, 0x73, 0x27, 0x51, 0xf1, 0x7c, 0x0a, 0xd8, 0xea, 0x45, 0x76, 0xa5, 0x7c, 0xac, 0x76, 0x71, 0xfc, 0xcc, 0xf9, - 0x13, 0x57, 0xe1, 0x5a, 0x34, 0x94, 0x20, 0xe0, 0xcd, 0x61, 0xec, 0x0a, 0x55, 0x40, 0x43, 0x73, 0x03, 0xc7, 0xb9, - 0x1a, 0x56, 0x9a, 0x80, 0x69, 0x29, 0x8f, 0x0e, 0x70, 0x68, 0xf2, 0xa8, 0xdd, 0x34, 0xac, 0x0c, 0x5d, 0x6b, 0xf4, - 0xb9, 0xad, 0x74, 0xc6, 0x9b, 0x0d, 0xdf, 0x3f, 0x18, 0x54, 0xf8, 0x93, 0x34, 0x47, 0xa3, 0x9d, 0x1b, 0xee, 0x34, - 0x02, 0x33, 0x57, 0x72, 0x45, 0x76, 0x47, 0xc9, 0xcb, 0xef, 0xe9, 0x85, 0x05, 0xf4, 0xe7, 0x3f, 0x17, 0x13, 0x4e, - 0x5a, 0x62, 0x42, 0xb4, 0x74, 0xd0, 0xa2, 0x83, 0x1d, 0xe5, 0x95, 0x7d, 0x89, 0x97, 0xce, 0xf1, 0xbf, 0xaf, 0xc7, - 0xda, 0x55, 0x20, 0xb4, 0x3a, 0xb9, 0xdf, 0x9e, 0x2c, 0x10, 0x35, 0xa0, 0x9a, 0x5d, 0x95, 0xa3, 0x4c, 0x3b, 0x2b, - 0xb2, 0x69, 0xc8, 0x5c, 0x77, 0xb3, 0x34, 0x6c, 0x26, 0x3b, 0x16, 0x96, 0x19, 0x06, 0x6b, 0xa7, 0x8a, 0x3e, 0x07, - 0x2d, 0x3f, 0x82, 0x17, 0x4d, 0xe5, 0x99, 0xcf, 0x66, 0x19, 0xf1, 0x02, 0x9d, 0x73, 0x2a, 0x16, 0x4d, 0xe9, 0x58, - 0xb9, 0xdd, 0x96, 0x68, 0x2c, 0x51, 0x46, 0x41, 0x50, 0xdb, 0x20, 0xec, 0xba, 0x74, 0x4f, 0xfa, 0xb4, 0x8b, 0x4f, - 0x2b, 0xd0, 0xf7, 0xf8, 0x3e, 0x03, 0x89, 0xa9, 0x27, 0x79, 0xa8, 0x1a, 0xcd, 0xd1, 0xc9, 0xb3, 0x38, 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, 0x07, 0xd4, 0xa9, 0x8b, 0x75, 0x1b, 0x50, 0xb2, 0xe4, 0xdd, 0x3a, 0x3d, 0xb1, 0xd2, 0x77, 0xfb, - 0xe1, 0xce, 0x3c, 0x6a, 0x76, 0x77, 0xbb, 0x9d, 0x90, 0xb6, 0x7d, 0x30, 0xde, 0x97, 0xb0, 0x10, 0xe7, 0x1d, 0xb6, - 0xf7, 0x7d, 0x58, 0x3d, 0xe6, 0x83, 0x5f, 0x70, 0x9c, 0x61, 0xf4, 0x33, 0x65, 0xe8, 0xf3, 0xaa, 0x90, 0x57, 0xaa, - 0x53, 0xbe, 0xd0, 0xad, 0x65, 0xea, 0xfd, 0x36, 0x7e, 0xdb, 0x0a, 0x10, 0xe3, 0x75, 0xc5, 0x4a, 0xf1, 0x86, 0x56, - 0x18, 0xd7, 0xc0, 0x6d, 0x72, 0xa8, 0xa5, 0x5a, 0x20, 0xea, 0xf2, 0x93, 0xc7, 0x3c, 0x32, 0xea, 0x4c, 0xf8, 0xee, - 0x31, 0xf7, 0xa5, 0x6b, 0xbb, 0x4d, 0xfc, 0x5c, 0xd3, 0xf6, 0x77, 0x07, 0xba, 0xa3, 0x75, 0x0f, 0x37, 0xcf, 0xe6, - 0xe7, 0x91, 0xf9, 0x62, 0x80, 0xcd, 0xda, 0x65, 0x5c, 0x76, 0x0c, 0xf7, 0xbd, 0xe9, 0xc1, 0x58, 0x40, 0x20, 0x31, - 0x43, 0x2f, 0x03, 0x17, 0xb8, 0xc0, 0x5d, 0x61, 0xc0, 0x10, 0xd7, 0xb4, 0xe4, 0x4c, 0x5b, 0xd9, 0xfa, 0xc8, 0xdb, - 0xa8, 0x10, 0xac, 0xeb, 0x8e, 0x9b, 0x24, 0x87, 0xe0, 0x84, 0x2d, 0xf7, 0xbe, 0xf6, 0xda, 0x19, 0xfe, 0x63, 0x20, - 0x9c, 0x5b, 0xa2, 0x67, 0xd4, 0xf6, 0x58, 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, 0xde, 0xbf, 0xe6, 0x38, 0x71, 0x96, 0xc2, 0xf6, 0xc3, 0x87, 0x0b, 0x76, 0x4d, 0x00, 0x83, 0x16, 0x93, 0x05, - 0x4a, 0x50, 0xc9, 0x5a, 0xd5, 0x6e, 0xa7, 0xc4, 0x2f, 0xf7, 0x8b, 0x2e, 0xb3, 0x9d, 0xc7, 0xaf, 0x9b, 0xb4, 0xcf, - 0x7c, 0x8e, 0x7e, 0x98, 0xdf, 0x59, 0x27, 0x25, 0x67, 0x18, 0xd7, 0xf2, 0xff, 0xab, 0xe8, 0x65, 0x91, 0xa5, 0xd1, - 0xc6, 0xf0, 0x60, 0x36, 0xd4, 0xa6, 0x0f, 0x8d, 0x51, 0xb9, 0x65, 0xa3, 0x88, 0x68, 0x75, 0x0b, 0x82, 0x19, 0xc5, - 0x7d, 0x89, 0x36, 0xaf, 0x54, 0x59, 0x78, 0x87, 0xcf, 0x6c, 0xf4, 0x86, 0xed, 0x09, 0xa1, 0x7c, 0xf7, 0xb4, 0x30, - 0xab, 0x96, 0x8a, 0x06, 0xdb, 0x25, 0xbc, 0x8b, 0x51, 0xa5, 0x9f, 0x30, 0xd9, 0xb2, 0x60, 0xaa, 0xff, 0xdf, 0x17, - 0x59, 0xda, 0xa6, 0xe8, 0xc0, 0x74, 0x36, 0x7d, 0x3a, 0xe9, 0x06, 0xd7, 0x19, 0xb0, 0x88, 0x60, 0x4b, 0x85, 0xe3, - 0x51, 0x6a, 0x37, 0x48, 0x98, 0x08, 0x6e, 0xa2, 0x5e, 0x76, 0xb4, 0x4c, 0xc9, 0xaa, 0x80, 0xe7, 0x57, 0xae, 0x32, - 0x1d, 0x47, 0x43, 0xbf, 0x7f, 0x95, 0x9a, 0xd0, 0xaf, 0xd4, 0x4b, 0x55, 0x9c, 0x87, 0x51, 0x75, 0xa8, 0x30, 0x46, - 0x4b, 0x9a, 0xc2, 0x31, 0x98, 0x5d, 0x84, 0x29, 0x5e, 0xce, 0x36, 0x09, 0xfb, 0x82, 0x81, 0x5c, 0x6a, 0x83, 0x7a, - 0x4d, 0x89, 0xd6, 0xac, 0xbd, 0x99, 0x53, 0x42, 0x2f, 0x58, 0xe9, 0xdf, 0x85, 0xd6, 0x20, 0x50, 0x94, 0xcd, 0x94, - 0xe9, 0xb9, 0x6e, 0xe7, 0x05, 0x4d, 0x68, 0x41, 0x57, 0xa4, 0x06, 0x7d, 0xaf, 0x93, 0xb3, 0xa3, 0x93, 0x9d, 0x99, - 0xf5, 0x98, 0x15, 0xc3, 0xc9, 0x34, 0x86, 0x6b, 0x5a, 0xec, 0xae, 0x69, 0xcb, 0xe6, 0x8d, 0xab, 0xb1, 0x71, 0x1a, - 0xb4, 0x0b, 0xa4, 0x6d, 0x9a, 0xdb, 0x4f, 0x3d, 0x6e, 0x7f, 0x5d, 0xb3, 0xe5, 0xb4, 0xb7, 0xde, 0x6e, 0x7b, 0x29, - 0xd8, 0x88, 0x7a, 0x7c, 0xfc, 0x5a, 0x49, 0xd7, 0x2d, 0x97, 0x9f, 0xc2, 0xb3, 0xc7, 0xd7, 0x2f, 0x7d, 0x70, 0x39, - 0x5a, 0xb5, 0xb9, 0xfb, 0xe5, 0x2e, 0xb2, 0xdc, 0x17, 0x0d, 0x2d, 0xd7, 0x33, 0xd4, 0x24, 0xcf, 0x46, 0x7b, 0x87, - 0x5a, 0xb0, 0x9c, 0x75, 0x13, 0x9e, 0x18, 0xec, 0xd8, 0xab, 0xc6, 0xe6, 0xa8, 0xcc, 0x25, 0xab, 0x41, 0x02, 0x7d, - 0x92, 0x67, 0x9a, 0xfe, 0x41, 0x86, 0xf9, 0xe8, 0x96, 0xe6, 0x80, 0x2b, 0x56, 0xd9, 0x4b, 0x06, 0xa9, 0xab, 0xf6, - 0x12, 0x57, 0xbe, 0xc2, 0x21, 0xd9, 0xe0, 0x93, 0x61, 0xaa, 0x3e, 0xbb, 0xe4, 0xc1, 0xff, 0xdb, 0xaa, 0x55, 0x7a, - 0x6e, 0x92, 0x1b, 0x8e, 0x7f, 0x9d, 0xb4, 0x7d, 0x4c, 0x0c, 0x12, 0xf0, 0xd4, 0x2e, 0x86, 0x6a, 0x54, 0x15, 0xb1, - 0x28, 0x73, 0x13, 0x73, 0xec, 0xde, 0xae, 0xa1, 0x83, 0x32, 0xf8, 0x75, 0xc3, 0x27, 0xe6, 0x0e, 0x6c, 0x05, 0x3a, - 0x3a, 0xd1, 0x5c, 0x86, 0x99, 0xb9, 0x0c, 0xd3, 0xae, 0xad, 0x02, 0xc3, 0xab, 0xb6, 0x4a, 0xa2, 0x5c, 0x8d, 0x7a, - 0xdc, 0xcc, 0x52, 0xb3, 0x17, 0x79, 0xf7, 0x9a, 0xf4, 0x24, 0xfe, 0x74, 0xe9, 0xc9, 0xeb, 0x61, 0x40, 0xe4, 0x97, - 0x2c, 0x0d, 0xd7, 0x28, 0x08, 0x4e, 0xad, 0x76, 0x20, 0xcd, 0x47, 0x80, 0xcc, 0x8f, 0xd3, 0xf0, 0x9d, 0x16, 0xe7, - 0x90, 0x8d, 0xd2, 0x38, 0xb1, 0xa5, 0x51, 0x0f, 0xc1, 0x9d, 0xf7, 0x8a, 0xc7, 0x10, 0xf8, 0xf0, 0x03, 0x6e, 0x06, - 0x15, 0xdd, 0x96, 0x98, 0x28, 0x6d, 0x1e, 0x75, 0xcb, 0x47, 0x0d, 0xa1, 0x92, 0x95, 0xe1, 0xc5, 0xd0, 0xde, 0x1d, - 0x81, 0x51, 0xe5, 0x04, 0x32, 0xc3, 0x62, 0xff, 0x60, 0x98, 0x2a, 0x41, 0xd1, 0x50, 0x0e, 0x97, 0x28, 0x07, 0xc4, - 0x24, 0x10, 0x18, 0x15, 0x83, 0x54, 0x57, 0xa6, 0x5e, 0x0c, 0x52, 0x7d, 0xab, 0x22, 0xf5, 0x59, 0x16, 0x56, 0x54, - 0xb7, 0x88, 0x8e, 0xe9, 0x50, 0xd2, 0xa5, 0xd9, 0xa9, 0xb9, 0x96, 0x5e, 0xa8, 0xe5, 0xf8, 0x5c, 0xa7, 0xc1, 0x28, - 0x9e, 0xba, 0x14, 0xfd, 0x56, 0xed, 0x67, 0xff, 0x2d, 0xa6, 0xd4, 0x88, 0x4d, 0xed, 0x2d, 0x62, 0x58, 0xb5, 0x1f, - 0xb2, 0x2a, 0x07, 0xed, 0x2e, 0x28, 0x1b, 0x2b, 0xe3, 0x3c, 0xdf, 0x08, 0x66, 0x0e, 0xda, 0xc6, 0xaa, 0xe9, 0x43, - 0x6f, 0xc4, 0xa8, 0xbd, 0x31, 0xd5, 0xb8, 0x27, 0xf0, 0xd3, 0x06, 0x4d, 0xf7, 0x22, 0xcf, 0x51, 0x8f, 0xbc, 0xfb, - 0x9f, 0x39, 0xb2, 0x33, 0xf9, 0x2c, 0x96, 0x49, 0xdd, 0x3e, 0x26, 0xc1, 0x42, 0xd5, 0x31, 0xba, 0x70, 0x23, 0x53, - 0xda, 0xcf, 0x9d, 0xe9, 0x47, 0x3c, 0x93, 0x87, 0xed, 0xd0, 0xa8, 0x2f, 0x0d, 0x6b, 0x49, 0x11, 0xf5, 0x05, 0xbd, - 0x35, 0xd5, 0xd1, 0x01, 0xf5, 0x3a, 0x02, 0xab, 0x2b, 0xda, 0xa0, 0x06, 0x60, 0x32, 0xae, 0x6d, 0x6d, 0x3e, 0x07, - 0x53, 0x5b, 0x55, 0xc1, 0x33, 0xba, 0x2b, 0x94, 0xee, 0x4d, 0xea, 0xba, 0x35, 0xc4, 0x16, 0x30, 0x20, 0x70, 0xa3, - 0xa7, 0xa6, 0x3f, 0x68, 0xa2, 0x02, 0xd0, 0xa0, 0x71, 0x3b, 0xd3, 0x39, 0x12, 0xfd, 0x4e, 0x6d, 0xda, 0x66, 0xaa, - 0x57, 0x95, 0x0f, 0xa0, 0xe2, 0xcf, 0xd2, 0xd9, 0x85, 0x19, 0xb1, 0x00, 0xc6, 0x3d, 0x70, 0xa6, 0x7a, 0xc7, 0x19, - 0x58, 0x4f, 0xe4, 0x79, 0x56, 0xf2, 0x44, 0x0a, 0x98, 0x11, 0x79, 0x75, 0x25, 0x05, 0x0c, 0x83, 0x1a, 0x00, 0xb4, - 0x68, 0x2e, 0xa3, 0x09, 0x7f, 0x52, 0xd3, 0xfb, 0xf2, 0xf0, 0x27, 0x3a, 0xd7, 0x37, 0xe3, 0x1a, 0x0c, 0x95, 0xd7, - 0x15, 0xdf, 0xc9, 0xf4, 0x0d, 0x7f, 0xea, 0x65, 0x5a, 0xca, 0x75, 0xb1, 0x93, 0xe5, 0xc9, 0x37, 0xfc, 0x99, 0xce, - 0x73, 0xf0, 0xb4, 0xa6, 0x69, 0x7c, 0xb7, 0x93, 0xe5, 0xef, 0xdf, 0x3c, 0xb5, 0x79, 0x9e, 0x8c, 0x6b, 0x7a, 0xc3, - 0xf9, 0x47, 0x97, 0x69, 0xa2, 0xab, 0x1a, 0x3f, 0xfd, 0xbb, 0xcd, 0xf5, 0xb4, 0xa6, 0x57, 0x52, 0x54, 0xcb, 0x9d, - 0xa2, 0x0e, 0xbe, 0x39, 0xf8, 0x3b, 0xff, 0xc6, 0x74, 0xef, 0xa0, 0xa6, 0x7f, 0xad, 0xe3, 0xa2, 0xe2, 0xc5, 0x4e, - 0x71, 0x7f, 0xfb, 0xfb, 0xdf, 0x9f, 0xda, 0x8c, 0x4f, 0x6b, 0x7a, 0xc7, 0xe3, 0x8e, 0xb6, 0x4f, 0x9e, 0x3d, 0xe5, - 0x7f, 0xab, 0x6b, 0xfa, 0x2b, 0xf3, 0x83, 0xa3, 0x1e, 0x67, 0x9e, 0x1e, 0x3e, 0x91, 0x4d, 0xd4, 0x80, 0xa1, 0x87, - 0x06, 0x90, 0x4b, 0xab, 0xa6, 0xb9, 0xc7, 0x2b, 0x17, 0xdc, 0xbe, 0xcf, 0xe2, 0x34, 0x5e, 0xc1, 0x41, 0xb0, 0x41, - 0xe3, 0xac, 0x02, 0x38, 0x55, 0xe0, 0x3d, 0xa3, 0x92, 0x66, 0xa5, 0xfc, 0x07, 0xe7, 0x1f, 0x61, 0xd0, 0x10, 0xd2, - 0x46, 0x45, 0x06, 0x3a, 0x59, 0xe9, 0xc8, 0x46, 0xe8, 0xbf, 0xd9, 0x8c, 0x83, 0xe3, 0xc3, 0xe8, 0xf5, 0xfb, 0x61, - 0xc1, 0x44, 0x58, 0x10, 0x42, 0xff, 0x0c, 0x0b, 0x70, 0x28, 0x29, 0x98, 0x97, 0xcf, 0xf8, 0x9e, 0x6b, 0xa3, 0xb0, - 0x10, 0x44, 0x77, 0x91, 0x7d, 0x40, 0xd5, 0xa3, 0xef, 0xd0, 0x0d, 0xf1, 0xb2, 0xc2, 0x82, 0xa1, 0x55, 0x0d, 0xcc, - 0x10, 0x14, 0xff, 0x86, 0x87, 0x12, 0x7c, 0xe2, 0x01, 0x3e, 0x7a, 0x4c, 0x66, 0x5c, 0x5d, 0x6b, 0x4f, 0x2e, 0xc2, - 0x82, 0x06, 0xba, 0xed, 0x10, 0x74, 0x20, 0xf2, 0x5f, 0x80, 0xa7, 0xc0, 0xc0, 0x87, 0x85, 0x5d, 0xca, 0x5d, 0x7f, - 0xf5, 0x5f, 0x0d, 0xeb, 0xe8, 0xc2, 0x8f, 0xfe, 0x6a, 0x5d, 0xd8, 0x33, 0x32, 0x95, 0x87, 0xe5, 0x70, 0x32, 0x1d, - 0x0c, 0xa4, 0x8b, 0xe3, 0x76, 0x9c, 0xcd, 0x7f, 0x9d, 0xcb, 0xc5, 0x02, 0x75, 0xdf, 0x38, 0xaf, 0x33, 0xfd, 0x37, - 0xd2, 0xce, 0x07, 0x6f, 0x8e, 0x7f, 0x3f, 0x3b, 0x3d, 0x7e, 0x05, 0xce, 0x07, 0x1f, 0x5e, 0x7e, 0xff, 0xf2, 0xbd, - 0x0a, 0xee, 0xae, 0xe6, 0xbc, 0xdf, 0x77, 0x52, 0x9f, 0x90, 0x0f, 0x2b, 0xb2, 0x1f, 0xc6, 0x8f, 0x0b, 0x65, 0xf4, - 0x40, 0x0e, 0x99, 0x85, 0x42, 0x86, 0x2a, 0x6a, 0xfb, 0xbb, 0x1c, 0x4e, 0x3c, 0x30, 0x8b, 0xbb, 0x86, 0x08, 0xd7, - 0x6f, 0xb9, 0x0d, 0xb2, 0x26, 0x8f, 0xbc, 0x7e, 0x70, 0x32, 0x95, 0x8e, 0x2d, 0x2c, 0x18, 0x94, 0x0d, 0x6d, 0x3a, - 0xce, 0xe6, 0xc5, 0xc2, 0xb6, 0xcb, 0x2d, 0x90, 0x51, 0x9a, 0x5d, 0x5c, 0x84, 0x0a, 0xba, 0xfa, 0x08, 0x34, 0x00, - 0xa6, 0x51, 0x85, 0x6b, 0x11, 0x9f, 0xf9, 0xe5, 0x47, 0x63, 0xaf, 0x79, 0xb7, 0xa8, 0x7b, 0x32, 0xcd, 0xaa, 0x1a, - 0x03, 0x3a, 0x98, 0x50, 0xee, 0x06, 0xdd, 0x04, 0x93, 0x51, 0x6d, 0xf9, 0x75, 0x5e, 0x2d, 0x4c, 0x73, 0xdc, 0x30, - 0x54, 0x5e, 0xc9, 0x6b, 0xd9, 0x40, 0x64, 0x20, 0x19, 0x86, 0x3d, 0x1a, 0xa3, 0x48, 0x7d, 0x6f, 0xd7, 0x3b, 0x7e, - 0x93, 0x4b, 0x88, 0xa6, 0x98, 0x81, 0x74, 0xfe, 0x58, 0x28, 0xe7, 0x72, 0xc9, 0xf8, 0x5c, 0x2c, 0x8e, 0xc0, 0xed, - 0x7c, 0x2e, 0x16, 0x11, 0x06, 0xe5, 0xcb, 0x20, 0x56, 0x09, 0xd8, 0xbd, 0x38, 0x08, 0xdf, 0x4e, 0x68, 0x03, 0xbb, - 0x81, 0x24, 0x1b, 0x94, 0x76, 0xa5, 0x21, 0xca, 0x9d, 0xf2, 0x68, 0x83, 0xc8, 0x43, 0xac, 0x9a, 0x57, 0x6d, 0x4f, - 0x36, 0x73, 0x31, 0xc1, 0x55, 0x16, 0x33, 0x39, 0x8d, 0x0f, 0x59, 0x31, 0x8d, 0xa1, 0x94, 0x38, 0x4d, 0xc3, 0x98, - 0x4e, 0xa8, 0x20, 0x24, 0x61, 0x7c, 0x1e, 0x2f, 0x68, 0x82, 0x52, 0x82, 0x10, 0x42, 0x7e, 0x8c, 0xd0, 0x36, 0x07, - 0x96, 0xbc, 0xdd, 0x7e, 0x9e, 0x7e, 0x6e, 0xc7, 0x70, 0x19, 0x15, 0xa1, 0x1b, 0x74, 0xd6, 0xf0, 0x6f, 0x44, 0x05, - 0x8d, 0xb1, 0x62, 0x08, 0x02, 0x5e, 0x60, 0x54, 0xc2, 0x82, 0xc4, 0xac, 0x82, 0x28, 0x02, 0xe5, 0x3c, 0x5e, 0xb0, - 0x82, 0x36, 0x6d, 0x4e, 0x63, 0x6d, 0x12, 0xd4, 0x73, 0x58, 0x6a, 0x7b, 0x52, 0xa9, 0x10, 0x7b, 0x7c, 0x26, 0xa2, - 0x6b, 0x6d, 0x68, 0x00, 0x28, 0x50, 0x4a, 0x2e, 0x7e, 0xf3, 0xe5, 0x1e, 0x6e, 0x0a, 0xfa, 0x9f, 0x6d, 0x4c, 0xb4, - 0xb3, 0x5c, 0x1d, 0x7a, 0xf3, 0x05, 0x8d, 0xf3, 0x1c, 0x42, 0xb1, 0x19, 0x04, 0x72, 0x91, 0x55, 0x10, 0xd1, 0xe2, - 0x2e, 0x30, 0x21, 0xe1, 0xa0, 0x4d, 0xbf, 0x42, 0x6a, 0x43, 0x4c, 0xae, 0x3c, 0x31, 0xb0, 0xdb, 0x2a, 0x41, 0xc0, - 0x91, 0x9e, 0x67, 0x9f, 0x9a, 0x18, 0x6b, 0x9a, 0x9a, 0x99, 0x78, 0x1b, 0x0a, 0xd1, 0xa0, 0x05, 0xd1, 0x0c, 0xde, - 0x3f, 0x57, 0x1c, 0xaf, 0x3a, 0xf0, 0x03, 0xde, 0xb9, 0x38, 0xf3, 0x6a, 0xe6, 0x11, 0x39, 0xf5, 0x51, 0x8e, 0xe8, - 0x97, 0x3c, 0xac, 0x46, 0x3a, 0x19, 0x63, 0x25, 0x71, 0xd0, 0xdb, 0x60, 0xc1, 0x9c, 0xd0, 0x15, 0x0f, 0x2d, 0x1f, - 0xff, 0x0a, 0x99, 0x8c, 0x92, 0x1a, 0x2b, 0xba, 0xd2, 0x62, 0xc4, 0x79, 0x0d, 0xb3, 0x34, 0x59, 0xd1, 0xc5, 0x42, - 0x93, 0x66, 0xa1, 0x4c, 0x03, 0x7c, 0x02, 0x2d, 0x46, 0xee, 0xa1, 0xa6, 0x0d, 0x84, 0x86, 0xdd, 0x21, 0xe0, 0x23, - 0xf7, 0xd0, 0xe1, 0xff, 0xe7, 0xd9, 0x05, 0x22, 0xed, 0xcd, 0x4d, 0x64, 0x3c, 0x52, 0x37, 0x70, 0x50, 0x8c, 0x8f, - 0x7d, 0x33, 0xf1, 0x0b, 0x67, 0xf4, 0x21, 0xa9, 0x7c, 0x87, 0x0f, 0x96, 0x3f, 0xde, 0xd4, 0xcc, 0xca, 0x08, 0xd6, - 0xc3, 0x76, 0x8b, 0x0b, 0xa2, 0xed, 0x02, 0x48, 0x3d, 0xe3, 0xd5, 0xc2, 0x37, 0x5e, 0x8d, 0xef, 0x31, 0x5e, 0x75, - 0x67, 0x6a, 0x98, 0x93, 0x0d, 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, 0x6e, - 0xb7, 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, 0x5f, 0xc4, 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, 0x21, 0xbb, 0xe2, 0x65, 0x15, 0x5f, 0xad, 0x8c, 0x25, 0x31, - 0x67, 0xf7, 0xb9, 0xed, 0x51, 0x61, 0x5e, 0xbd, 0x7d, 0xf9, 0xfd, 0x71, 0xe3, 0xd5, 0x2e, 0xe2, 0x68, 0x08, 0xb6, - 0x15, 0x63, 0x8c, 0xde, 0xe2, 0xd3, 0x60, 0xa2, 0x5c, 0x23, 0xd0, 0xbb, 0x14, 0xf4, 0xdb, 0x5f, 0xea, 0x09, 0x78, - 0xc5, 0xf5, 0xf2, 0x4b, 0x3e, 0x02, 0x96, 0xa8, 0xd0, 0xb3, 0xc2, 0xdc, 0xac, 0xcc, 0xee, 0xed, 0x56, 0x64, 0xa6, - 0x5d, 0x69, 0x64, 0x20, 0x5e, 0x6d, 0x87, 0xb1, 0x70, 0xe9, 0x9a, 0x6e, 0x07, 0xbb, 0x5a, 0x7a, 0x96, 0xc8, 0xdb, - 0x6d, 0x09, 0x1d, 0xb2, 0x03, 0xee, 0xbd, 0x8c, 0x6f, 0xe1, 0x65, 0xe9, 0x75, 0xb3, 0x19, 0x3c, 0x01, 0xcc, 0x84, - 0x0b, 0x67, 0x59, 0x1c, 0x33, 0x9e, 0x84, 0x2a, 0x36, 0x57, 0x43, 0xe4, 0xad, 0x08, 0xad, 0xd9, 0x5f, 0xa1, 0x18, - 0x81, 0xdd, 0xc9, 0xe9, 0xc7, 0x6c, 0x35, 0x5b, 0x02, 0x6a, 0xfe, 0x55, 0x26, 0x80, 0xe6, 0xda, 0xb5, 0x60, 0x9b, - 0x42, 0x9b, 0xeb, 0xfa, 0x79, 0xbc, 0x8a, 0x13, 0x50, 0xdd, 0x80, 0xb7, 0xc8, 0x9d, 0x16, 0x5d, 0x19, 0x74, 0x51, - 0xfa, 0x40, 0x39, 0x96, 0x14, 0x3a, 0xfa, 0xde, 0x13, 0xea, 0xdc, 0x33, 0x80, 0x4b, 0x1a, 0x35, 0x4f, 0xb5, 0x94, - 0xb1, 0x00, 0x58, 0xe8, 0x60, 0xa6, 0xc8, 0x56, 0x74, 0x6b, 0x30, 0x29, 0xe0, 0xad, 0x01, 0xfe, 0x10, 0x59, 0xa5, - 0xee, 0x8a, 0x65, 0x58, 0x7a, 0xf6, 0xd7, 0xfd, 0x7e, 0xec, 0xd9, 0x5f, 0x5f, 0x68, 0x5a, 0x17, 0xb7, 0x1b, 0x40, - 0x6a, 0x0c, 0x20, 0x72, 0xac, 0x07, 0xc2, 0x44, 0x14, 0x6b, 0xfa, 0xfe, 0x1d, 0x9b, 0x2c, 0x0a, 0x84, 0x7e, 0xa7, - 0x5e, 0x4f, 0x4a, 0x02, 0x3a, 0xb5, 0x8a, 0x1d, 0x0d, 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, - 0xfb, 0xbf, 0x99, 0x2c, 0x08, 0x6a, 0xae, 0xfc, 0x40, 0x8e, 0x3b, 0x99, 0x1a, 0x7b, 0xaa, 0x51, 0x83, 0x60, 0x32, - 0x82, 0xc0, 0x70, 0xc3, 0x2f, 0xf8, 0xf8, 0x60, 0x41, 0x40, 0x45, 0x66, 0xcd, 0x42, 0xcc, 0x8b, 0xc3, 0x27, 0x80, - 0x1a, 0x33, 0x3a, 0x78, 0x06, 0xa0, 0xb0, 0x10, 0x10, 0x7d, 0x0c, 0x32, 0x5a, 0x01, 0xbf, 0x85, 0xfa, 0xdd, 0x3a, - 0xf1, 0x7d, 0xe8, 0x57, 0x41, 0x2f, 0x62, 0x60, 0x38, 0xa2, 0xc9, 0x7e, 0xc8, 0x07, 0x93, 0x01, 0x68, 0x4b, 0xbc, - 0xdd, 0xd7, 0xd2, 0x8a, 0x9b, 0xd3, 0xa5, 0xd3, 0xfd, 0x93, 0x36, 0x41, 0x12, 0xa9, 0x64, 0xa5, 0x22, 0x06, 0x10, - 0xca, 0x52, 0x6d, 0x93, 0x25, 0x58, 0x56, 0x98, 0x25, 0xcd, 0x0d, 0x4a, 0xe2, 0xee, 0x66, 0xe0, 0x18, 0x35, 0xeb, - 0x38, 0x2c, 0x5b, 0x6e, 0xd4, 0x00, 0x9f, 0x93, 0xb0, 0xc2, 0xde, 0x70, 0x66, 0xd2, 0x3b, 0xd3, 0xe1, 0xea, 0x98, - 0xb3, 0x37, 0x1c, 0xc1, 0x38, 0x12, 0xbc, 0xf1, 0xd0, 0x25, 0xd3, 0x50, 0x91, 0x29, 0xe3, 0x60, 0xda, 0x03, 0xdc, - 0x7b, 0x0e, 0xc6, 0x61, 0x6c, 0x50, 0x59, 0x52, 0x9f, 0x7a, 0x77, 0x21, 0x10, 0xa4, 0xb5, 0x5e, 0xe6, 0x33, 0x3c, - 0x3d, 0x23, 0x94, 0xfd, 0x21, 0x87, 0x2f, 0xc0, 0x8e, 0x82, 0x1c, 0x4d, 0xf8, 0xb3, 0xc7, 0xbb, 0x81, 0xaa, 0xf8, - 0x20, 0xd8, 0x8b, 0x45, 0xba, 0x17, 0x0c, 0x04, 0xfc, 0x2a, 0xf8, 0x5e, 0x25, 0xe5, 0xde, 0x45, 0x5c, 0xec, 0xc5, - 0xab, 0xb8, 0xa8, 0xf6, 0x6e, 0xb2, 0x6a, 0xb9, 0x67, 0x3a, 0x04, 0xd0, 0xbc, 0xc1, 0x20, 0x1e, 0x04, 0x7b, 0xc1, - 0xa0, 0x30, 0x53, 0xbb, 0x62, 0x65, 0xe3, 0x38, 0x33, 0x21, 0xca, 0x82, 0x66, 0x80, 0xb0, 0xc6, 0x69, 0x00, 0x7c, - 0xea, 0x9a, 0xa5, 0xf4, 0x02, 0xc3, 0x0d, 0x88, 0xe9, 0x1a, 0xfa, 0x00, 0x3c, 0xf2, 0x9a, 0xc6, 0xb0, 0x04, 0x2e, - 0x06, 0x03, 0xb2, 0x86, 0xc8, 0x05, 0x6b, 0x6a, 0x83, 0x38, 0x84, 0x6b, 0x65, 0xa7, 0xbd, 0x0b, 0xcc, 0xb4, 0xdd, - 0x02, 0xa2, 0xf2, 0x84, 0xf4, 0xfb, 0xf6, 0x1b, 0xea, 0x5f, 0xb0, 0x97, 0x60, 0x7f, 0x55, 0x54, 0x61, 0x22, 0x95, - 0xe6, 0xfb, 0x92, 0x1d, 0x0d, 0x54, 0xc4, 0xe1, 0x1d, 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, 0xaf, 0x34, 0xbb, 0xf4, 0x30, 0x90, 0x32, - 0x6e, 0x0f, 0x2d, 0x61, 0xd2, 0xf2, 0x22, 0xbc, 0xf7, 0x9a, 0x9b, 0xdc, 0x8b, 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, 0xcf, 0x74, 0x17, 0x80, 0xd1, 0x2f, 0x66, 0x69, 0xb4, 0xbc, 0xd7, 0xcc, 0x02, 0xc9, 0x33, 0xf4, 0x5d, - 0x07, 0xdb, 0x1b, 0xfb, 0x20, 0xe5, 0xfc, 0x50, 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, 0x3f, 0x91, 0x6f, 0x72, 0x07, 0x5d, 0x2e, 0xc7, - 0x9a, 0xb7, 0x1c, 0x80, 0x8a, 0x7e, 0xa4, 0xa8, 0xee, 0x17, 0x38, 0xc2, 0x3c, 0x58, 0xb7, 0xf9, 0x64, 0xdf, 0x14, - 0x38, 0x44, 0x9e, 0xb4, 0xd1, 0x14, 0xd0, 0xbd, 0x8b, 0xc7, 0x5d, 0xfd, 0xb6, 0x74, 0x17, 0x28, 0xd1, 0x4e, 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, - 0xeb, 0x33, 0x8e, 0xa2, 0x1f, 0xa3, 0x46, 0xbe, 0x89, 0xc4, 0x63, 0x39, 0x88, 0x1f, 0x17, 0x74, 0x19, 0x89, 0xc7, - 0xc5, 0x20, 0x7e, 0x2c, 0xeb, 0x7a, 0xf7, 0x5c, 0xb9, 0xbf, 0x8f, 0xc8, 0xb3, 0xee, 0xec, 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, 0xfd, 0x62, 0x74, 0xe3, 0xbb, 0xeb, 0xef, 0x17, 0xa3, 0x25, 0x19, 0x4e, 0xcc, 0xe4, 0xc7, 0x47, 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, 0xdf, 0xab, 0x76, 0xb4, 0x69, 0x6f, 0xe2, 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, 0x4d, 0xd9, 0xfc, 0x2a, 0xda, 0xe7, 0xc8, 0x48, - 0xd9, 0x26, 0x23, 0x15, 0x18, 0x61, 0x4a, 0x91, 0xc4, 0x55, 0x08, 0x81, 0xec, 0xbf, 0xa4, 0xb8, 0x16, 0x4b, 0xef, - 0x35, 0x08, 0x13, 0x6c, 0x17, 0xb4, 0x5f, 0xdd, 0xce, 0x6d, 0xa5, 0xc5, 0x1e, 0xa9, 0xef, 0x73, 0x67, 0xbb, 0xa2, - 0xc9, 0xdf, 0x97, 0x0d, 0x68, 0x03, 0x88, 0xf2, 0xbe, 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, 0x80, - 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, 0x53, 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, 0x11, 0xcb, 0xe6, 0x62, 0x31, 0x5a, 0x49, 0x08, 0x1b, 0x7c, 0xc8, 0xb2, 0x79, 0xa9, - 0x1f, 0x42, 0x5f, 0x58, 0x7a, 0x02, 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, 0x23, 0xd4, - 0xfe, 0x7e, 0x1e, 0xc5, 0x5a, 0x2e, 0xb9, 0x72, 0x7e, 0xf1, 0x37, 0x9f, 0xb1, 0xd7, 0x3d, 0xc3, 0x60, 0x01, 0xce, - 0xd2, 0xf6, 0x2a, 0x13, 0xef, 0x64, 0x2b, 0x38, 0x0e, 0x66, 0x51, 0x0e, 0xab, 0x9e, 0x1c, 0xd1, 0x5c, 0xe4, 0xda, - 0xbb, 0x08, 0x91, 0x83, 0xcc, 0x1e, 0x03, 0xec, 0x46, 0xf8, 0x3a, 0xb4, 0x36, 0xb7, 0xba, 0x42, 0xfc, 0x8d, 0x12, - 0x89, 0x9f, 0xa5, 0xfc, 0xb8, 0x5e, 0xa9, 0x5c, 0x95, 0xc1, 0x63, 0xd5, 0xcd, 0xe0, 0x99, 0xf6, 0x3d, 0xd6, 0xfe, - 0xad, 0xed, 0xe6, 0x78, 0xef, 0xc1, 0x83, 0xd6, 0xff, 0xd6, 0x93, 0x10, 0xda, 0x2b, 0x27, 0xa9, 0x3b, 0x6a, 0xf4, - 0xcc, 0x64, 0x8d, 0xa8, 0x84, 0xa9, 0xdd, 0xa9, 0x1c, 0x03, 0x35, 0x1d, 0xc0, 0xb5, 0x44, 0x4d, 0xd0, 0x93, 0x82, - 0x8d, 0xe1, 0x88, 0xb3, 0x38, 0x68, 0x87, 0x31, 0x8a, 0x97, 0x73, 0x25, 0x5e, 0xce, 0x8f, 0x18, 0x07, 0x68, 0x2d, - 0x40, 0xaa, 0xd7, 0xb0, 0x9f, 0xb9, 0x82, 0x05, 0x36, 0x77, 0xbe, 0x03, 0x0b, 0x64, 0x88, 0x93, 0xcd, 0x71, 0xb2, - 0xc7, 0xb5, 0x9e, 0x7b, 0x81, 0x8f, 0x93, 0x7a, 0xe1, 0xd5, 0x55, 0xb6, 0xeb, 0x5a, 0xb2, 0x72, 0x5e, 0x0c, 0x26, - 0x10, 0x94, 0xa5, 0x9c, 0x17, 0xc3, 0xc9, 0x82, 0xe6, 0xf0, 0x63, 0xd1, 0x40, 0x87, 0x58, 0x0e, 0x12, 0xb8, 0x74, - 0xf6, 0x18, 0xf0, 0x86, 0x52, 0x8b, 0xbb, 0xb1, 0x8e, 0x1c, 0xeb, 0x28, 0xf6, 0xc3, 0x18, 0x70, 0x65, 0x9d, 0xc0, - 0xfb, 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, 0x1d, 0x95, 0x43, - 0x2d, 0x84, 0xeb, 0x5a, 0x78, 0x1d, 0xa7, 0x65, 0x0c, 0x2e, 0xd2, 0xda, 0x36, 0xf1, 0x1e, 0xba, 0xee, 0xf9, 0x31, - 0xb7, 0x3a, 0x46, 0x5b, 0x48, 0xbf, 0x1d, 0x9d, 0xde, 0x73, 0x18, 0x80, 0xa6, 0x07, 0xb3, 0xaa, 0x7d, 0x26, 0x71, - 0x73, 0xda, 0x09, 0x42, 0x22, 0x10, 0x45, 0xe9, 0x8c, 0x30, 0xfd, 0x3b, 0xcd, 0x65, 0x15, 0xad, 0x1e, 0xe4, 0x99, - 0x43, 0x9e, 0x85, 0xde, 0xf6, 0xa0, 0x55, 0x73, 0x37, 0x18, 0x27, 0x6e, 0xb7, 0x77, 0xfe, 0xdf, 0xb2, 0xae, 0xad, - 0xd6, 0x88, 0xc7, 0xed, 0xea, 0x07, 0x8d, 0xbd, 0xda, 0x53, 0x31, 0x60, 0x56, 0xd2, 0x3b, 0xa3, 0x4a, 0x5e, 0x64, - 0xbc, 0xc4, 0x93, 0x6a, 0xd5, 0xf0, 0xf1, 0xbe, 0xc9, 0x46, 0xe6, 0x81, 0x4c, 0x01, 0xf1, 0xfc, 0x26, 0x35, 0xea, - 0xe3, 0x14, 0x25, 0xe0, 0xef, 0x74, 0x7c, 0x23, 0xfa, 0xd1, 0xbe, 0xb8, 0xe4, 0xd5, 0xc9, 0x8d, 0x30, 0x2f, 0x5e, - 0x58, 0x9d, 0x3f, 0x7d, 0x53, 0xf8, 0xd0, 0xe1, 0xa8, 0xbd, 0x83, 0x22, 0x4b, 0x26, 0x8e, 0x26, 0x46, 0xd6, 0x26, - 0x66, 0x1f, 0x15, 0x5c, 0x4c, 0x54, 0xa1, 0x67, 0x9d, 0x3d, 0x61, 0x0a, 0xd0, 0x37, 0x8e, 0x51, 0xc9, 0x18, 0x16, - 0x0c, 0xd4, 0x69, 0x4a, 0x88, 0x1e, 0x8a, 0x19, 0xc6, 0x2b, 0x06, 0x50, 0x98, 0x42, 0x81, 0x28, 0x3a, 0xfb, 0x70, - 0xa0, 0x09, 0xfd, 0xfe, 0x4d, 0xaa, 0x33, 0xd0, 0xb2, 0x9e, 0x4a, 0x10, 0xd5, 0x41, 0xb4, 0x55, 0x5e, 0x84, 0x3f, - 0x2e, 0x69, 0x99, 0xd1, 0xa5, 0xa0, 0xa9, 0xa0, 0x49, 0x46, 0x2f, 0xb8, 0x12, 0x15, 0x5f, 0x08, 0xa6, 0x68, 0xbb, - 0x21, 0xec, 0xff, 0x6a, 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, 0x9d, 0xae, 0xcf, 0x9f, 0xcb, 0xab, 0x95, 0x14, 0x5c, 0x54, 0x0a, 0xa2, 0xdf, 0xe0, 0xbe, 0x9b, 0xb8, - 0xea, 0xac, 0x59, 0x2b, 0x7d, 0xe8, 0x5b, 0x9f, 0xb5, 0x71, 0x5f, 0x18, 0x1c, 0x83, 0x9d, 0x8f, 0x88, 0x81, 0x34, - 0xa8, 0x74, 0x8b, 0x43, 0x13, 0xa0, 0x4b, 0x87, 0x14, 0xb2, 0x64, 0x2a, 0x53, 0x25, 0xa8, 0xf8, 0xc6, 0xef, 0xa5, - 0xac, 0x46, 0x7f, 0xad, 0x79, 0x71, 0x77, 0xca, 0x73, 0x8e, 0x63, 0x14, 0x24, 0xb1, 0xb8, 0x8e, 0xcb, 0x80, 0xf8, - 0x96, 0x57, 0xc1, 0x41, 0x6a, 0xc2, 0xc6, 0xec, 0x54, 0x8d, 0x5a, 0x2f, 0x89, 0xbe, 0x32, 0xca, 0x37, 0x06, 0x43, - 0x13, 0x51, 0x05, 0x7d, 0xaf, 0xd5, 0x3d, 0xad, 0x6e, 0x58, 0x40, 0xfc, 0xb9, 0xd2, 0x0b, 0xb5, 0x5e, 0x37, 0x63, - 0x6e, 0x98, 0x08, 0x41, 0xa3, 0x27, 0xf5, 0xa2, 0xf6, 0xdc, 0xd2, 0x54, 0x64, 0xdc, 0x68, 0x93, 0xf3, 0x4b, 0x90, - 0xf1, 0x39, 0x73, 0xa1, 0x49, 0x5d, 0x53, 0x05, 0x55, 0x18, 0x6d, 0x6e, 0x1b, 0xe9, 0xf4, 0x0e, 0xdc, 0xd9, 0x8c, - 0xd9, 0x91, 0x76, 0x69, 0xac, 0x69, 0xc1, 0xcb, 0x95, 0x14, 0x25, 0x84, 0x71, 0xee, 0x8d, 0xe9, 0x55, 0x9c, 0x89, - 0x2a, 0xce, 0xc4, 0x71, 0xb9, 0xe2, 0x49, 0xf5, 0x1e, 0x6e, 0x71, 0xca, 0xea, 0xa6, 0x2e, 0xe1, 0x4a, 0x97, 0xec, - 0x61, 0x30, 0x35, 0x15, 0xf7, 0xd8, 0x19, 0x5c, 0x54, 0x7f, 0x44, 0x4b, 0x89, 0xb1, 0x50, 0x75, 0xf1, 0xf1, 0x79, - 0x29, 0xf3, 0x75, 0x05, 0xda, 0xdd, 0x8b, 0x2a, 0x3a, 0x78, 0xba, 0xba, 0x9d, 0xaa, 0x1b, 0x4c, 0xf4, 0xf4, 0x60, - 0x75, 0xdb, 0xcb, 0xae, 0x56, 0xb2, 0xa8, 0x62, 0x51, 0x4d, 0x15, 0x22, 0x59, 0x12, 0xe7, 0x49, 0x38, 0x19, 0x8f, - 0xbf, 0xda, 0x1b, 0xee, 0x41, 0x06, 0x32, 0xfd, 0x34, 0x54, 0x2e, 0x47, 0xc3, 0xc9, 0x78, 0x3c, 0x95, 0xea, 0x6e, - 0x17, 0x8d, 0x26, 0x35, 0xd6, 0x33, 0x4c, 0xf4, 0xcc, 0x8c, 0xf8, 0xed, 0x2a, 0x16, 0x29, 0xc4, 0xaf, 0xd3, 0xc5, - 0x1f, 0x3c, 0x1d, 0x37, 0xca, 0xb7, 0x9f, 0x3e, 0xab, 0xff, 0xa8, 0x4d, 0x58, 0x6b, 0xd3, 0xee, 0xe7, 0x7f, 0x1c, - 0xaa, 0xf9, 0x3e, 0x3a, 0xdc, 0xd7, 0x3f, 0xfe, 0xa8, 0xeb, 0xe9, 0x9b, 0x22, 0x9c, 0xff, 0x33, 0x54, 0xf3, 0x79, - 0x5c, 0x14, 0xf1, 0x5d, 0x0d, 0x91, 0x3c, 0x85, 0xf3, 0x26, 0xa1, 0xde, 0x36, 0xa0, 0x07, 0x64, 0x7a, 0x21, 0x18, - 0x7c, 0xf3, 0xbe, 0x0a, 0x03, 0x5e, 0xae, 0x86, 0x5c, 0x54, 0x59, 0x75, 0x37, 0xc4, 0x3c, 0x01, 0x7e, 0x6a, 0x78, - 0xb3, 0xe7, 0x85, 0x21, 0x36, 0x17, 0x05, 0xe7, 0x9f, 0x78, 0xa8, 0x8c, 0xa3, 0xc7, 0x68, 0x1c, 0x3d, 0xa6, 0x6a, - 0x30, 0x26, 0xdf, 0x50, 0xdd, 0x99, 0xc9, 0x37, 0x60, 0x82, 0x94, 0xb5, 0xbf, 0x51, 0xc6, 0x89, 0xd1, 0x98, 0x5e, - 0xbf, 0xca, 0xb3, 0x15, 0x30, 0xc1, 0x4b, 0xfd, 0xa3, 0x26, 0xf4, 0x3d, 0x6f, 0x67, 0x1f, 0x8d, 0x46, 0xcf, 0x0b, - 0x3a, 0x1a, 0x8d, 0x3e, 0x66, 0x35, 0xa1, 0x2b, 0xd1, 0xf1, 0xfe, 0x3d, 0xa7, 0xe7, 0x32, 0xbd, 0x8b, 0x82, 0x80, - 0x2e, 0xb3, 0x34, 0xe5, 0x42, 0x95, 0x75, 0x9a, 0xb6, 0xf3, 0xaa, 0x16, 0x22, 0xf0, 0x8f, 0x6e, 0x23, 0x42, 0x10, - 0x11, 0x7a, 0xb2, 0xd3, 0xb3, 0xd1, 0x68, 0x74, 0x9a, 0x9a, 0x6a, 0x1d, 0x43, 0xfe, 0x06, 0xcd, 0x07, 0x9c, 0x5d, - 0x3e, 0x58, 0xdf, 0x98, 0x68, 0x27, 0xfb, 0xff, 0x3d, 0x9c, 0xcd, 0xc7, 0xc3, 0x6f, 0x47, 0x8b, 0xc7, 0xfb, 0x34, - 0x08, 0x7c, 0xd0, 0xea, 0x50, 0x5b, 0x73, 0x4c, 0xcb, 0xc3, 0xf1, 0x94, 0x94, 0x03, 0xf6, 0xd4, 0xfa, 0xd2, 0x7c, - 0xf5, 0x14, 0x90, 0x48, 0x51, 0x84, 0x1a, 0x38, 0xe9, 0x1f, 0x5e, 0x45, 0x5e, 0x0b, 0xc0, 0x47, 0xb3, 0x91, 0x0c, - 0x8c, 0x16, 0x70, 0x1c, 0x41, 0x79, 0xb5, 0x35, 0x8d, 0xe8, 0x31, 0x96, 0x99, 0xa8, 0xa0, 0xe3, 0x69, 0x79, 0x93, - 0x55, 0xc9, 0x12, 0x03, 0x1b, 0xc5, 0x25, 0x0f, 0xbe, 0x0a, 0xa2, 0x92, 0x1d, 0x3c, 0x9b, 0x2a, 0x78, 0x5f, 0x4c, - 0x4a, 0xf9, 0x25, 0x24, 0x7e, 0x3b, 0x46, 0x08, 0x54, 0xa2, 0x3d, 0x16, 0xb1, 0xc6, 0x57, 0xb9, 0x8c, 0xc1, 0x83, - 0xb3, 0xd4, 0x3c, 0x8b, 0x3d, 0x09, 0xac, 0xfd, 0x45, 0xab, 0x39, 0x12, 0x9a, 0x13, 0x4a, 0x26, 0xf7, 0x4b, 0x2a, - 0xbf, 0x9a, 0xa0, 0x57, 0x10, 0xb8, 0x55, 0x47, 0x70, 0xdc, 0x59, 0xcb, 0x06, 0xbd, 0x7c, 0x52, 0xb6, 0x3f, 0xff, - 0xdf, 0x25, 0x5d, 0x0c, 0xf6, 0xdd, 0xd0, 0x9c, 0x68, 0xf7, 0xd5, 0x0a, 0x19, 0xa5, 0x2a, 0x7c, 0x9e, 0x12, 0x6b, - 0x7c, 0xca, 0xd9, 0xd1, 0xc6, 0x74, 0x67, 0x54, 0x15, 0xd9, 0x55, 0x48, 0x74, 0xaf, 0x1c, 0x28, 0x66, 0x10, 0x65, - 0x23, 0x5c, 0x3f, 0x60, 0x2d, 0xe2, 0x75, 0xf2, 0x9a, 0x17, 0x55, 0x96, 0xa8, 0xf7, 0xd7, 0x8d, 0xf7, 0x40, 0x0d, - 0x54, 0x83, 0xde, 0x15, 0x0c, 0xe6, 0xf9, 0xa4, 0x00, 0xd0, 0xce, 0x92, 0x17, 0xd7, 0xdc, 0xa7, 0x1b, 0x41, 0x50, - 0xbb, 0x66, 0x5e, 0x36, 0x82, 0x4d, 0xc0, 0x57, 0xef, 0x0a, 0xc0, 0xdc, 0x08, 0x41, 0x6a, 0x0a, 0xa1, 0x70, 0xe0, - 0x02, 0x5f, 0x55, 0x45, 0x76, 0xbe, 0xae, 0x38, 0x06, 0xfb, 0xf0, 0xe2, 0x26, 0x2a, 0x27, 0x3c, 0x1e, 0x06, 0xf8, - 0x23, 0xa0, 0x2a, 0xe0, 0x86, 0xf1, 0xb0, 0x83, 0x17, 0xea, 0x97, 0x7b, 0xa3, 0xf6, 0x08, 0x7b, 0x93, 0x86, 0x10, - 0x5c, 0x07, 0x1f, 0x02, 0x58, 0x52, 0x84, 0x9e, 0xe0, 0xa9, 0x1a, 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, 0x28, 0xef, - 0xf4, 0xc4, 0xb8, 0x30, 0x7d, 0x1c, 0x22, 0xbf, 0xbc, 0x2b, 0x54, 0xe8, 0x17, 0xbe, 0x00, 0xf0, 0x2b, 0xb8, 0xdd, - 0xef, 0xc6, 0x77, 0x51, 0xd9, 0xcf, 0x38, 0xdb, 0xff, 0xef, 0x79, 0x3c, 0xfc, 0x34, 0x1e, 0x7e, 0xbb, 0x18, 0x84, - 0x43, 0xfb, 0x93, 0x3c, 0x7e, 0xb4, 0x4f, 0x5f, 0x71, 0xcb, 0x95, 0xc0, 0xc2, 0x6f, 0x04, 0xb7, 0x51, 0x2b, 0x21, - 0x88, 0x02, 0xbc, 0x51, 0xb8, 0xd5, 0x38, 0x01, 0x80, 0xbf, 0xe0, 0xbf, 0x02, 0x34, 0x12, 0x72, 0x17, 0x0d, 0xd0, - 0x0f, 0xa8, 0xdf, 0x47, 0x4f, 0x1a, 0x06, 0x72, 0x20, 0x9e, 0x50, 0x31, 0x50, 0x88, 0x2e, 0x63, 0xa2, 0x60, 0x7f, - 0x6d, 0xf6, 0xed, 0xb6, 0xd7, 0x96, 0xfc, 0xe0, 0x97, 0x7e, 0xa6, 0x89, 0x99, 0x77, 0xb8, 0xa1, 0xac, 0xe4, 0x2a, - 0x44, 0x6c, 0x3c, 0xfd, 0x2b, 0x67, 0x10, 0x6b, 0xf2, 0x3a, 0x03, 0x1f, 0x06, 0xfb, 0xc5, 0x78, 0x06, 0x6c, 0x03, - 0xdc, 0x71, 0x0a, 0x7e, 0x91, 0x81, 0x5b, 0xb3, 0x88, 0xf1, 0x82, 0x6d, 0x97, 0x44, 0xbf, 0xdf, 0xcb, 0xb3, 0x30, - 0xd7, 0x38, 0xcb, 0x79, 0x6d, 0xc4, 0xee, 0xa8, 0x13, 0x06, 0x71, 0xbb, 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, 0xb8, 0x2e, 0xb3, 0x5e, 0x2f, 0x0c, 0xd1, 0xa1, 0x11, 0x4b, 0xc5, - 0xda, 0x20, 0xbc, 0x8f, 0x49, 0x18, 0x5d, 0x81, 0xac, 0x2e, 0x3c, 0xe3, 0x04, 0xf9, 0x32, 0x30, 0x59, 0x53, 0xd5, - 0x7a, 0x39, 0xe1, 0xb1, 0x91, 0x2f, 0x1b, 0x41, 0x83, 0xbc, 0xa4, 0xa8, 0x37, 0x71, 0x3b, 0xf6, 0x51, 0x0b, 0xa9, - 0x71, 0x53, 0x4f, 0x7b, 0x9a, 0x54, 0xf4, 0x58, 0xaf, 0x52, 0xbf, 0xc0, 0xb2, 0xc0, 0x92, 0x0f, 0x42, 0x7b, 0x9a, - 0x56, 0x60, 0x86, 0x6b, 0x9b, 0xc1, 0xd0, 0x0f, 0x87, 0xb6, 0x08, 0x9d, 0x51, 0xdb, 0x12, 0xc2, 0xb6, 0x0d, 0xc2, - 0xca, 0x7b, 0x22, 0x5f, 0x3d, 0xf5, 0x18, 0xe1, 0x90, 0x9b, 0xcd, 0x2c, 0x1a, 0x18, 0xe6, 0x57, 0xb2, 0xd9, 0x3c, - 0xdd, 0x5c, 0x2f, 0x2a, 0xa6, 0x80, 0xed, 0xb6, 0x12, 0x04, 0xff, 0x7e, 0xcc, 0x66, 0xf8, 0x37, 0xeb, 0xf7, 0x7b, - 0x21, 0xfe, 0xe2, 0x18, 0xbc, 0x67, 0x2e, 0x16, 0xec, 0x23, 0xc8, 0x54, 0x48, 0x84, 0xa9, 0xca, 0xf8, 0x8d, 0x55, - 0x60, 0x01, 0x67, 0x3e, 0x50, 0xb9, 0x30, 0x93, 0xbd, 0xbc, 0xb8, 0x86, 0x1c, 0xb7, 0xc6, 0x29, 0x1b, 0x65, 0x89, - 0x72, 0x5d, 0xc8, 0x46, 0x71, 0x9e, 0xc5, 0x25, 0x2f, 0xb7, 0x5b, 0x7d, 0x38, 0x26, 0x05, 0x07, 0xf6, 0x54, 0x51, - 0xa9, 0x92, 0x75, 0xa4, 0xba, 0xf1, 0x97, 0x61, 0x81, 0xfb, 0x94, 0xcf, 0x0b, 0x43, 0x23, 0xf6, 0xe0, 0xf2, 0xce, - 0xd4, 0xad, 0xb4, 0x17, 0x16, 0xd0, 0xbc, 0x92, 0x90, 0x0d, 0xa6, 0x7a, 0x16, 0xad, 0x31, 0x13, 0xf3, 0x62, 0x01, - 0x61, 0x64, 0x8a, 0x05, 0xd8, 0x4c, 0x71, 0x01, 0x5e, 0x24, 0x31, 0xc0, 0xc4, 0xc5, 0x64, 0x0a, 0xf1, 0xcc, 0x55, - 0x39, 0xf1, 0xc2, 0xdc, 0x2f, 0x13, 0x87, 0x94, 0x01, 0xaf, 0x6a, 0x83, 0x26, 0x66, 0x1b, 0x8e, 0x3a, 0x41, 0x4e, - 0x4c, 0x7e, 0x3f, 0x55, 0x10, 0xe2, 0x4e, 0x1c, 0x09, 0x97, 0x15, 0xdb, 0x85, 0x97, 0x1d, 0x88, 0x31, 0x6a, 0x70, - 0xca, 0xcf, 0x0c, 0x8e, 0xc6, 0xe0, 0xdc, 0x78, 0x27, 0x48, 0x11, 0xc6, 0x64, 0x23, 0xd9, 0x95, 0x0c, 0xc5, 0x3c, - 0x5e, 0x80, 0xb2, 0x2e, 0x5e, 0x80, 0x65, 0x8d, 0x31, 0xc0, 0x04, 0x79, 0x15, 0xf7, 0x42, 0x3f, 0x51, 0x5c, 0x21, - 0xd2, 0xb3, 0x72, 0x7d, 0x54, 0xb4, 0x43, 0x5f, 0xe0, 0xf5, 0x5e, 0x99, 0xe3, 0x66, 0x3d, 0x16, 0x48, 0x6c, 0x08, - 0x18, 0x1b, 0xe9, 0x34, 0xd5, 0x5a, 0xf7, 0xc6, 0xcc, 0x03, 0x9f, 0x66, 0x23, 0x21, 0xab, 0xb3, 0x0b, 0x10, 0xa1, - 0xf8, 0x68, 0xf0, 0xc8, 0x2f, 0xe2, 0xce, 0x32, 0x6f, 0x6d, 0x8b, 0x4a, 0x76, 0xb4, 0x01, 0x90, 0x3e, 0x1d, 0x2d, - 0x4a, 0xc9, 0x29, 0x4a, 0x52, 0xbb, 0x4d, 0x01, 0x2b, 0xc9, 0x5f, 0xc0, 0x10, 0x6c, 0x6c, 0x4f, 0x38, 0x9d, 0x22, - 0xc4, 0x27, 0x9a, 0x22, 0xb2, 0x62, 0x58, 0x52, 0x1c, 0xdb, 0x12, 0x51, 0x3f, 0x6d, 0x59, 0x76, 0x30, 0x4c, 0x54, - 0xdc, 0x17, 0xa9, 0x47, 0x89, 0x82, 0x80, 0xea, 0x21, 0x07, 0x89, 0xad, 0x6d, 0x20, 0x3c, 0x20, 0x8f, 0xe8, 0x8d, - 0xf5, 0xf7, 0x59, 0xe7, 0xd9, 0x85, 0xe6, 0xa8, 0x5c, 0xef, 0x0a, 0x33, 0x46, 0x78, 0x92, 0x19, 0x98, 0x7c, 0xef, - 0x3c, 0x33, 0x6a, 0x8a, 0x9e, 0x87, 0x4f, 0x76, 0x8c, 0x11, 0xe9, 0xee, 0x19, 0x74, 0x13, 0xbc, 0xaa, 0xc3, 0x46, - 0xbb, 0x52, 0x10, 0x12, 0xa6, 0x16, 0x4d, 0xcc, 0x7a, 0xd6, 0x80, 0x7a, 0xbb, 0xed, 0xe9, 0xb9, 0xba, 0x7f, 0xee, - 0xb6, 0xdb, 0x1e, 0x76, 0xeb, 0x45, 0xda, 0x6d, 0x05, 0x5e, 0xa9, 0x0f, 0xda, 0xe3, 0xcf, 0xdd, 0xf8, 0x73, 0x83, - 0xe4, 0x51, 0x3a, 0x9a, 0x69, 0xeb, 0x83, 0x70, 0xb8, 0xe9, 0x5d, 0xa3, 0x49, 0xdf, 0x67, 0xa1, 0xa4, 0x2b, 0xd1, - 0xa8, 0xae, 0x76, 0x26, 0x95, 0x0f, 0xae, 0xff, 0x87, 0x57, 0x01, 0x1e, 0x71, 0x6a, 0x67, 0xdf, 0xdb, 0xa0, 0xa2, - 0xd1, 0x16, 0x8e, 0x14, 0xa1, 0x07, 0x24, 0xe1, 0xbe, 0x96, 0xb5, 0xb8, 0xcd, 0xd3, 0xec, 0x61, 0xfa, 0xf4, 0x3a, - 0xf5, 0xad, 0xee, 0xdd, 0x32, 0xcb, 0xcc, 0x81, 0x57, 0x51, 0x1c, 0xd0, 0xa8, 0x8b, 0xf6, 0x5d, 0x65, 0x65, 0x09, - 0x5e, 0x1e, 0x70, 0x7d, 0x3e, 0xe5, 0x3e, 0xdc, 0xdc, 0x65, 0xd5, 0xdc, 0xa4, 0xa7, 0xd9, 0x3c, 0x5b, 0x6c, 0xb7, - 0x21, 0xfe, 0xed, 0x6a, 0x91, 0xa3, 0xc9, 0x73, 0xd0, 0xe1, 0x61, 0xe4, 0x1e, 0xa6, 0x1b, 0xe7, 0x6d, 0xfe, 0x4f, - 0xa2, 0xe1, 0x24, 0x70, 0x0c, 0xf4, 0x62, 0xf6, 0x08, 0x64, 0x30, 0xc6, 0xa9, 0x5f, 0xcc, 0xf4, 0x9a, 0x81, 0xe8, - 0x5b, 0x22, 0x02, 0x1c, 0x5d, 0x6c, 0x24, 0x1a, 0x59, 0x70, 0x52, 0x13, 0xb0, 0xd8, 0xb4, 0xe5, 0x7d, 0xb0, 0xb4, - 0xad, 0x2a, 0xee, 0xbc, 0x25, 0xcd, 0x71, 0x1d, 0x38, 0xdb, 0x7e, 0x33, 0xc4, 0xa6, 0xec, 0x6a, 0x81, 0xdc, 0x2f, - 0xaf, 0x69, 0x6f, 0x5c, 0x27, 0x30, 0x6b, 0x9b, 0xda, 0x32, 0x7e, 0xb6, 0xf4, 0x9f, 0xf5, 0xe0, 0x2a, 0xe3, 0xa7, - 0xb9, 0xb1, 0x4a, 0xb0, 0xfb, 0xc6, 0xf3, 0x1d, 0x80, 0x70, 0x6c, 0x3e, 0x3d, 0x3e, 0xcd, 0x3c, 0x7a, 0x0c, 0x44, - 0xc7, 0x7c, 0x54, 0xba, 0x8f, 0xec, 0xee, 0xf5, 0x03, 0xe0, 0xcd, 0xab, 0x76, 0x41, 0xf3, 0x72, 0x01, 0x81, 0x44, - 0xbd, 0xf2, 0x0a, 0xcb, 0x67, 0xc6, 0xec, 0x12, 0xc8, 0x50, 0x41, 0xc0, 0x26, 0xa9, 0xeb, 0x5c, 0x88, 0x55, 0x87, - 0x95, 0xf9, 0x48, 0xc2, 0x8e, 0x42, 0x34, 0xe7, 0x0c, 0x66, 0xc1, 0x7f, 0x05, 0x83, 0x72, 0x10, 0x44, 0x41, 0x14, - 0x04, 0x64, 0x50, 0xc0, 0x2f, 0xc4, 0x19, 0x23, 0x18, 0xa3, 0x04, 0x3a, 0xfc, 0x8e, 0x33, 0x9f, 0x11, 0x79, 0xd9, - 0x08, 0x63, 0xe9, 0x06, 0xe0, 0x5c, 0xca, 0x9c, 0xc7, 0xe8, 0x63, 0xf1, 0x8e, 0xb3, 0x8c, 0xd0, 0x77, 0xde, 0xa9, - 0xfc, 0x88, 0x37, 0x82, 0xdb, 0xed, 0x0e, 0xdb, 0x2b, 0x1e, 0x66, 0xb4, 0x37, 0xa6, 0xef, 0x38, 0x89, 0xb2, 0x86, - 0xf3, 0x30, 0x87, 0x9e, 0x55, 0x96, 0xb5, 0xa2, 0x86, 0xdc, 0xa0, 0x58, 0x17, 0x59, 0x26, 0x27, 0xc3, 0x55, 0x73, - 0x2a, 0x70, 0xdd, 0xd9, 0xf5, 0x02, 0x92, 0x32, 0xa1, 0x59, 0x3a, 0x1b, 0xbe, 0xda, 0xb6, 0xec, 0x45, 0xeb, 0x14, - 0xf2, 0x1a, 0xa2, 0xa2, 0x1f, 0x3a, 0x02, 0x6a, 0x68, 0xc5, 0x65, 0x05, 0x2e, 0xbb, 0xa6, 0x3d, 0xdc, 0xb4, 0xc7, - 0x34, 0xe3, 0x03, 0xc4, 0x88, 0xe3, 0xd8, 0x32, 0xb0, 0x9b, 0x70, 0x78, 0x36, 0xce, 0xf7, 0x65, 0x97, 0xde, 0xba, - 0x5a, 0x3c, 0xc2, 0xda, 0xf3, 0x56, 0x48, 0x08, 0x90, 0x96, 0xa6, 0xd2, 0xed, 0x36, 0x08, 0x60, 0x80, 0xfb, 0xfd, - 0x1e, 0x70, 0xad, 0x86, 0x9d, 0x34, 0xb7, 0x66, 0x4b, 0xec, 0x15, 0x85, 0xc7, 0x40, 0x94, 0x9a, 0xff, 0x0c, 0x02, - 0x8a, 0xe7, 0x6e, 0x08, 0xf6, 0x95, 0xec, 0x68, 0x53, 0xf4, 0xfb, 0x2f, 0x0a, 0x7c, 0x40, 0x39, 0x28, 0x88, 0x75, - 0x75, 0xdc, 0x0a, 0xc3, 0x3e, 0xa9, 0x0f, 0x71, 0x2c, 0xf2, 0x2c, 0x74, 0x84, 0xa5, 0x32, 0x84, 0x85, 0x2b, 0x46, - 0x3a, 0x88, 0x83, 0x9a, 0x74, 0x0e, 0x56, 0xe5, 0x82, 0x0d, 0xf7, 0x7a, 0x9f, 0x00, 0x16, 0x3c, 0xf3, 0x86, 0xe5, - 0xbd, 0x07, 0x00, 0xd6, 0xeb, 0xe1, 0x42, 0x71, 0x2f, 0x5f, 0x35, 0xd0, 0x27, 0xf1, 0xa5, 0x65, 0xd7, 0x67, 0x5a, - 0x56, 0x32, 0x1a, 0x8d, 0xaa, 0x5a, 0x49, 0x3e, 0x1c, 0x79, 0x69, 0xa1, 0x56, 0xca, 0x38, 0xe5, 0x29, 0x58, 0x7a, - 0x1b, 0x4a, 0x37, 0x5f, 0xd0, 0x15, 0x17, 0xa9, 0xfa, 0xe9, 0xa1, 0x4d, 0x36, 0x88, 0x6b, 0xd6, 0xd4, 0x59, 0xd8, - 0xe1, 0x87, 0x80, 0x8f, 0xf6, 0x61, 0xe6, 0xd2, 0x35, 0x2c, 0x2d, 0x88, 0x23, 0xe3, 0x82, 0x87, 0x2e, 0x0f, 0x60, - 0xfd, 0x99, 0x43, 0x12, 0x3f, 0x85, 0x9f, 0x33, 0x93, 0xd6, 0xf1, 0x19, 0xce, 0x66, 0x54, 0xaa, 0x1b, 0x41, 0xfb, - 0x35, 0x24, 0x12, 0x83, 0x6c, 0xdc, 0x60, 0x28, 0x5a, 0x77, 0x1b, 0xb8, 0xf2, 0x5b, 0x7a, 0xe7, 0xd3, 0x20, 0xc0, - 0xb6, 0xc6, 0x62, 0x00, 0x30, 0x14, 0x7f, 0xa0, 0xaa, 0xc6, 0x5c, 0x51, 0x4c, 0xc3, 0x54, 0xa2, 0xbd, 0xe3, 0xb8, - 0x8e, 0x1a, 0x57, 0x59, 0xc1, 0x4a, 0x6b, 0xcb, 0xeb, 0xde, 0xd2, 0xc2, 0x96, 0x80, 0x6a, 0x30, 0xdc, 0x09, 0xe0, - 0x33, 0x22, 0xd5, 0x81, 0x20, 0xbb, 0x0f, 0x0e, 0x9a, 0xb3, 0x04, 0xcf, 0xc3, 0x10, 0xfe, 0xc0, 0xc2, 0x81, 0x65, - 0xa9, 0xfa, 0xb9, 0x9c, 0xc6, 0x70, 0xee, 0xe6, 0x6a, 0x87, 0xcf, 0x96, 0xa0, 0xc8, 0x53, 0x73, 0x6a, 0x2e, 0x5f, - 0x79, 0x63, 0xbf, 0xc7, 0x04, 0xf3, 0x98, 0xd9, 0x86, 0xdf, 0x7a, 0xba, 0xad, 0x2f, 0xac, 0x1b, 0x38, 0x69, 0x2f, - 0x9c, 0xf6, 0x62, 0xbb, 0x34, 0x10, 0x77, 0x75, 0x43, 0x88, 0xf0, 0x5a, 0x13, 0x8b, 0xac, 0x21, 0xd3, 0xb1, 0xd8, - 0x18, 0xaa, 0x4d, 0xc5, 0x73, 0xad, 0x10, 0x2f, 0xa7, 0xea, 0xc2, 0xd4, 0x4a, 0x65, 0xc2, 0x20, 0xcc, 0x94, 0xb0, - 0xa8, 0x32, 0xf0, 0xd9, 0xaf, 0x90, 0xe2, 0xda, 0x7a, 0xde, 0xe2, 0xf2, 0xcd, 0x4c, 0x9b, 0xed, 0xa7, 0xaf, 0xf2, - 0xf8, 0x72, 0xbb, 0x0d, 0xbb, 0x5f, 0x80, 0xf9, 0x65, 0xa9, 0x34, 0x6a, 0xe0, 0xf4, 0x10, 0xa2, 0x9f, 0xf3, 0x3d, - 0x39, 0x27, 0x8e, 0x93, 0x6b, 0x37, 0x6f, 0xb6, 0x93, 0x62, 0x04, 0x16, 0x70, 0xe2, 0x22, 0x1d, 0x68, 0xa9, 0xe0, - 0xb4, 0x65, 0xbc, 0xb7, 0xe9, 0x1d, 0xa5, 0xc2, 0xab, 0x85, 0x26, 0x21, 0x95, 0xbb, 0x97, 0xd8, 0x51, 0x03, 0xce, - 0x49, 0xdd, 0x41, 0xc0, 0x49, 0x4d, 0x37, 0xd6, 0x2a, 0x4e, 0x4d, 0x82, 0xf7, 0x4a, 0x0f, 0x5d, 0xa2, 0x9d, 0xb8, - 0xdd, 0xb6, 0x2a, 0x5b, 0xa8, 0x8f, 0x7b, 0x39, 0x4b, 0xd4, 0xf1, 0x80, 0x42, 0x17, 0x75, 0x34, 0xe4, 0x0b, 0x52, - 0xe8, 0x95, 0xa3, 0x55, 0xab, 0xbb, 0x92, 0x81, 0x52, 0xad, 0x82, 0xbc, 0x26, 0xd6, 0x5d, 0x2b, 0x6b, 0x2c, 0xae, - 0x9c, 0x90, 0xc2, 0x26, 0x7c, 0x69, 0x29, 0x16, 0x56, 0xb0, 0x37, 0xa6, 0xbe, 0x70, 0x89, 0xd0, 0x76, 0xb7, 0x21, - 0x26, 0x19, 0xac, 0x9b, 0xed, 0xf6, 0x75, 0x11, 0xce, 0xb3, 0x05, 0x95, 0xa3, 0x2c, 0x45, 0x08, 0x31, 0xe3, 0xa1, - 0x6b, 0xbb, 0x60, 0x26, 0x86, 0xba, 0xf6, 0x78, 0x49, 0xa6, 0x58, 0x9b, 0x24, 0x47, 0xf1, 0xb9, 0x2c, 0xd4, 0x5a, - 0x23, 0x04, 0x0f, 0xf7, 0x3f, 0x53, 0x88, 0xe1, 0x66, 0xd6, 0xdd, 0x6f, 0x3b, 0x37, 0xc4, 0x3f, 0x21, 0x90, 0x40, - 0xc9, 0x5e, 0x17, 0xa3, 0xf3, 0x4c, 0xa4, 0xb8, 0x53, 0x55, 0x54, 0x5c, 0xb5, 0x0e, 0x9a, 0x2d, 0xb7, 0xf7, 0x62, - 0x4b, 0x14, 0x20, 0xae, 0xb1, 0xd0, 0x8c, 0x67, 0xe5, 0x2c, 0x45, 0x32, 0x8a, 0x0d, 0x89, 0x4a, 0x2f, 0x2a, 0xba, - 0xcf, 0xd3, 0x98, 0x1e, 0xba, 0x35, 0x08, 0xae, 0x9a, 0x3b, 0x1b, 0x69, 0xbe, 0x20, 0x44, 0x4d, 0x80, 0x84, 0x8d, - 0x6a, 0x4e, 0xad, 0x4b, 0xf1, 0x30, 0xab, 0x7c, 0xa6, 0x0f, 0xe2, 0x4b, 0x01, 0x3c, 0xac, 0xb7, 0xbd, 0xaf, 0x84, - 0xc7, 0xda, 0xe0, 0xdb, 0xed, 0xf6, 0x52, 0xcc, 0x83, 0xc0, 0x63, 0x34, 0xbf, 0x53, 0x12, 0xf3, 0xde, 0x98, 0xc2, - 0x8a, 0xf7, 0x5d, 0xda, 0xba, 0x49, 0xad, 0xb5, 0x40, 0xdd, 0xe1, 0xfa, 0x80, 0xe7, 0x29, 0x71, 0xb4, 0xa3, 0x72, - 0x2a, 0xad, 0xae, 0x1c, 0xbb, 0x22, 0x30, 0x30, 0xf4, 0x0f, 0x29, 0xdb, 0x80, 0x39, 0x1e, 0x58, 0xdb, 0xa0, 0x9f, - 0x92, 0xd2, 0xc2, 0x8c, 0xd1, 0x98, 0x45, 0xae, 0xab, 0xe8, 0x80, 0xeb, 0xe8, 0xed, 0x3c, 0xfa, 0xdb, 0xb3, 0x31, - 0x2d, 0x62, 0x91, 0xca, 0x2b, 0x50, 0x41, 0x80, 0x32, 0x04, 0x0d, 0xff, 0x35, 0x35, 0x00, 0x0d, 0x82, 0x1b, 0x80, - 0x7f, 0x74, 0x3a, 0x0d, 0xda, 0x9a, 0x7c, 0x4c, 0x52, 0x55, 0xe4, 0xac, 0x0d, 0x65, 0xa6, 0x92, 0x43, 0xf2, 0xb8, - 0x04, 0x3c, 0x47, 0x6c, 0x96, 0xb2, 0xb9, 0x50, 0x9b, 0x4d, 0xbd, 0x56, 0xec, 0xc8, 0x6d, 0xa3, 0x68, 0xb3, 0x16, - 0xb5, 0x9d, 0xc4, 0x7c, 0x31, 0xbd, 0xb5, 0xc2, 0xc0, 0xa9, 0x69, 0xcd, 0xcd, 0x0e, 0x74, 0x9a, 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, 0x0d, 0x69, 0xaa, 0xd0, 0xa3, 0x03, 0xbd, 0x1d, 0x02, 0x9a, 0xb3, 0x31, - 0x5d, 0xd2, 0x14, 0x2f, 0xd0, 0x74, 0x0d, 0x66, 0x29, 0x17, 0xd0, 0xd7, 0x6e, 0x9f, 0xe4, 0x0b, 0xd5, 0x13, 0xe1, - 0x2d, 0x51, 0xf0, 0xe5, 0x48, 0xc1, 0x2b, 0x2b, 0xe7, 0xb1, 0x99, 0x43, 0xc0, 0x63, 0x51, 0x25, 0x7a, 0x27, 0xc5, - 0x25, 0x28, 0x53, 0xe1, 0x08, 0x34, 0x55, 0x23, 0x96, 0x70, 0x80, 0xdb, 0x8b, 0xa7, 0x01, 0xa1, 0x20, 0xd5, 0x5d, - 0xdb, 0x15, 0x79, 0xcb, 0x8e, 0x36, 0xb7, 0x60, 0x16, 0x5b, 0xad, 0xcb, 0xd6, 0x57, 0x36, 0xd9, 0x7d, 0x5c, 0x13, - 0x6c, 0xbb, 0xb7, 0x41, 0xc2, 0x5b, 0x7a, 0x43, 0x36, 0x37, 0xfd, 0x7e, 0x08, 0xfd, 0x21, 0x54, 0x77, 0xe8, 0xb6, - 0xb3, 0x43, 0xb7, 0x3e, 0xf3, 0x6b, 0xf5, 0x7c, 0xca, 0x1b, 0xe2, 0x03, 0x9a, 0x68, 0xd1, 0x55, 0x7c, 0x07, 0x9b, - 0x3a, 0xaa, 0xa8, 0xaa, 0x3c, 0x4a, 0x28, 0xa8, 0x80, 0x33, 0x5e, 0x9e, 0x72, 0x8c, 0x6d, 0xaa, 0x9f, 0xde, 0x69, - 0x5e, 0x6d, 0x6d, 0xd6, 0x66, 0xb9, 0x3e, 0x07, 0x8b, 0x80, 0x73, 0x1e, 0x5d, 0x69, 0x5a, 0x72, 0xe9, 0x31, 0xf5, - 0x67, 0x38, 0x2a, 0xc1, 0x45, 0x9c, 0xe5, 0x3c, 0x0d, 0xe8, 0x45, 0xb3, 0xff, 0xa1, 0xb6, 0x95, 0x5a, 0x36, 0xce, - 0xdc, 0xeb, 0x90, 0x6c, 0xfe, 0xc7, 0x06, 0xea, 0x4d, 0x88, 0x11, 0x51, 0xcd, 0x82, 0x3e, 0x61, 0x10, 0x1b, 0x33, - 0x28, 0xd7, 0x49, 0xc2, 0xcb, 0x32, 0x30, 0x4a, 0xad, 0x35, 0x5b, 0x9b, 0xf3, 0xec, 0x11, 0x3b, 0x7a, 0xd4, 0x63, - 0xec, 0x96, 0xd0, 0x44, 0xeb, 0x84, 0x4c, 0x8d, 0x91, 0xa7, 0x05, 0xd2, 0x1d, 0x8a, 0xb2, 0x8b, 0xf0, 0x04, 0x85, - 0x2c, 0xed, 0x7d, 0x6e, 0x4e, 0x64, 0xf5, 0x8d, 0x36, 0xba, 0x88, 0x54, 0x22, 0xc8, 0xc6, 0x6f, 0x10, 0xb0, 0x17, - 0x9a, 0x1d, 0x90, 0xcd, 0x92, 0x9d, 0xd2, 0x33, 0x6b, 0x02, 0x03, 0xaf, 0x4f, 0x54, 0xa2, 0x19, 0x65, 0x45, 0x74, - 0x95, 0x91, 0xcb, 0x5d, 0x48, 0xa2, 0xb3, 0x90, 0xf8, 0xb9, 0x61, 0x69, 0x5d, 0x87, 0x28, 0x66, 0x36, 0x1b, 0x5e, - 0x75, 0xf7, 0x51, 0x63, 0x5b, 0x19, 0x9f, 0xea, 0x5b, 0x9b, 0x46, 0xa6, 0xd0, 0xd7, 0xe1, 0xa4, 0xdf, 0x87, 0xbf, - 0x9a, 0x7e, 0xe0, 0x2d, 0x05, 0x7f, 0xb1, 0x47, 0xa4, 0x4e, 0x58, 0x00, 0x70, 0x84, 0x39, 0xaf, 0x9a, 0x13, 0xf8, - 0x88, 0x1d, 0x6d, 0x1e, 0x85, 0xa7, 0x8d, 0x99, 0xbb, 0x0b, 0xf1, 0x52, 0x95, 0xf4, 0xbc, 0x79, 0x32, 0x03, 0xb1, - 0x0a, 0xcd, 0x7e, 0xbd, 0x65, 0x56, 0x9f, 0x00, 0x44, 0xea, 0xd6, 0x3a, 0x94, 0xe2, 0xc7, 0xa6, 0xcb, 0x64, 0x93, - 0xb2, 0x36, 0x13, 0xa5, 0x54, 0x24, 0xcd, 0x45, 0x00, 0xfd, 0x86, 0xe1, 0xa8, 0x01, 0xde, 0x5b, 0x8f, 0xbd, 0x19, - 0x1a, 0x6f, 0x4c, 0x0d, 0x3d, 0xdb, 0xe8, 0xe5, 0xed, 0x28, 0x84, 0x19, 0x8b, 0xe8, 0xd6, 0x1d, 0x8b, 0xe1, 0x29, - 0x3d, 0x81, 0x0a, 0xdf, 0x84, 0x18, 0x4d, 0x97, 0xd4, 0xf5, 0x74, 0xad, 0xb6, 0xd2, 0x0d, 0xa1, 0x39, 0x46, 0xf1, - 0xf1, 0xda, 0x76, 0x47, 0x8d, 0xd0, 0x9e, 0x50, 0x1e, 0xde, 0xd2, 0x8a, 0xde, 0x58, 0x16, 0xc1, 0xc9, 0x8f, 0xbd, - 0xfc, 0x84, 0x9e, 0x7b, 0x02, 0x93, 0xa2, 0xad, 0x01, 0xfc, 0x01, 0xf5, 0xc3, 0x59, 0x3d, 0xb5, 0x52, 0x0e, 0x4f, - 0xe1, 0x4b, 0x36, 0x20, 0x57, 0xd0, 0x8b, 0x35, 0x66, 0x47, 0x31, 0xe8, 0xa0, 0x76, 0x76, 0x87, 0x37, 0x29, 0x65, - 0x88, 0xd6, 0x77, 0x0e, 0xe2, 0xe9, 0x1f, 0xa0, 0xe9, 0x83, 0xb4, 0x30, 0xa5, 0x6b, 0x14, 0xf0, 0x80, 0xbe, 0xa9, - 0xdf, 0xcf, 0xf1, 0xb9, 0xf6, 0x2c, 0xb1, 0xb0, 0xc7, 0x4b, 0x42, 0x97, 0x5e, 0xdc, 0x28, 0x90, 0x36, 0x3b, 0x56, - 0x01, 0x58, 0x91, 0x04, 0x1a, 0x91, 0x80, 0xa5, 0x8e, 0x27, 0x2e, 0xdb, 0xa0, 0x01, 0x49, 0x54, 0x52, 0xc8, 0x12, - 0x49, 0xe0, 0x87, 0x11, 0x84, 0x28, 0x8a, 0x41, 0xdc, 0xab, 0x97, 0x57, 0x5c, 0x53, 0x03, 0x4e, 0x14, 0xc1, 0x04, - 0xeb, 0x74, 0x0a, 0xc4, 0x56, 0xac, 0x57, 0xe0, 0x79, 0xe9, 0x38, 0x71, 0x64, 0x09, 0xd0, 0x20, 0xcd, 0x97, 0x4e, - 0xbb, 0xe5, 0xed, 0x89, 0x96, 0x2a, 0x36, 0xf7, 0x5e, 0x2c, 0x2c, 0xf7, 0x58, 0xf9, 0xdb, 0x81, 0xf6, 0xc2, 0x6a, - 0x47, 0x44, 0x0d, 0x56, 0x76, 0x6d, 0xbb, 0x36, 0x94, 0x86, 0xea, 0x5e, 0x39, 0x26, 0xa0, 0xa2, 0xab, 0xb8, 0x5a, - 0x46, 0xd9, 0x08, 0xfe, 0x6c, 0xb7, 0xc1, 0x7e, 0x00, 0x16, 0x90, 0xbf, 0xbe, 0xff, 0x39, 0xc2, 0xf0, 0x4c, 0xbf, - 0xbe, 0xff, 0x79, 0xbb, 0x7d, 0x36, 0x1e, 0x1b, 0xae, 0xc0, 0xa9, 0x75, 0x80, 0x3f, 0x30, 0x6c, 0x83, 0x5d, 0xb2, - 0xdb, 0xed, 0x33, 0xe0, 0x20, 0x14, 0xdb, 0x60, 0x76, 0xb1, 0x72, 0xe4, 0x52, 0xac, 0x86, 0xde, 0x91, 0x80, 0x55, - 0xb7, 0xc3, 0x52, 0xec, 0x52, 0x1f, 0x15, 0x82, 0x51, 0x2f, 0xfa, 0x97, 0x9d, 0x02, 0x4b, 0x0a, 0xa6, 0xab, 0xc1, - 0xb2, 0xaa, 0x56, 0x65, 0xb4, 0xbf, 0x1f, 0xaf, 0xb2, 0x51, 0x99, 0xc1, 0x36, 0x2f, 0xaf, 0x2f, 0x01, 0x50, 0x21, - 0xa0, 0x8d, 0x77, 0x6b, 0x91, 0x99, 0x17, 0x0b, 0xba, 0xcc, 0x70, 0x4d, 0x82, 0xd9, 0x41, 0xce, 0xad, 0x6e, 0x72, - 0x4a, 0xec, 0x03, 0xd8, 0x1c, 0x6e, 0xb7, 0x0d, 0x7e, 0xe1, 0x68, 0xf4, 0x6c, 0xb6, 0xcc, 0xb4, 0x41, 0x27, 0x37, - 0xfb, 0x9f, 0x44, 0x5e, 0x1a, 0x2a, 0x3e, 0xc9, 0xf4, 0x65, 0x06, 0x7c, 0x1e, 0x7b, 0x2b, 0x42, 0x9f, 0xe5, 0x6a, - 0xb4, 0x06, 0xd8, 0xd8, 0xec, 0xe2, 0x6e, 0x94, 0x72, 0x88, 0x48, 0x11, 0x58, 0x75, 0xcd, 0x32, 0x23, 0xbe, 0x4d, - 0xc5, 0x5d, 0x4b, 0x15, 0xf6, 0x56, 0x78, 0xce, 0x2a, 0xdc, 0x38, 0xca, 0xf4, 0x26, 0x51, 0xf8, 0x12, 0x85, 0xa8, - 0x1c, 0x8d, 0xe9, 0x9c, 0x40, 0x2a, 0xf3, 0x98, 0x50, 0xcc, 0xe1, 0xde, 0xfd, 0x9a, 0x3a, 0x73, 0x19, 0x5f, 0xb8, - 0xf7, 0xd2, 0x97, 0x99, 0xdc, 0x4a, 0x00, 0x45, 0x52, 0xb5, 0xff, 0xf2, 0x19, 0xa9, 0xf1, 0x3f, 0x53, 0xad, 0x01, - 0xe8, 0xfd, 0x02, 0x35, 0x39, 0x82, 0x80, 0xad, 0x98, 0xfa, 0x68, 0xfa, 0x56, 0x32, 0xff, 0x01, 0x75, 0x3b, 0x82, - 0x6d, 0x54, 0xfc, 0x9c, 0xa8, 0xa2, 0x05, 0x4f, 0xd7, 0x22, 0x8d, 0x45, 0x72, 0x17, 0xf1, 0x7a, 0x8a, 0x25, 0x31, - 0x1b, 0x21, 0xeb, 0x97, 0x66, 0x17, 0x7e, 0x2e, 0x1a, 0x26, 0xe0, 0xb4, 0xf4, 0xb7, 0x95, 0xb7, 0x99, 0x2c, 0xe3, - 0x8c, 0x4c, 0xb9, 0x42, 0xec, 0xb6, 0xfa, 0x1e, 0x73, 0x82, 0x3f, 0x3d, 0x78, 0x4a, 0xe8, 0xad, 0x9c, 0x96, 0x08, - 0x4a, 0x27, 0x52, 0xeb, 0xaa, 0x89, 0xfd, 0x9a, 0x42, 0x14, 0x07, 0xc1, 0x20, 0x74, 0xa7, 0x69, 0x9f, 0xe2, 0xfb, - 0x6c, 0xd9, 0x6f, 0x4d, 0xd9, 0x92, 0x6c, 0x04, 0x74, 0x4c, 0x3a, 0x6f, 0x4f, 0x6f, 0xcf, 0xce, 0xbc, 0xdf, 0xa0, - 0x09, 0x07, 0xd5, 0x0d, 0xb4, 0xab, 0x20, 0xd3, 0x18, 0xc5, 0x66, 0x31, 0xd6, 0x6e, 0x4d, 0x44, 0x10, 0x74, 0xba, - 0x9c, 0x85, 0xed, 0x76, 0x42, 0x7c, 0x09, 0x24, 0x50, 0xe0, 0xca, 0x45, 0x39, 0x09, 0x89, 0xba, 0x90, 0xe9, 0xc9, - 0xba, 0x96, 0x2c, 0xd0, 0x6b, 0xec, 0x20, 0xa0, 0xc7, 0xdc, 0x3e, 0x05, 0xf4, 0x7d, 0xc1, 0x8e, 0xf9, 0x20, 0x18, - 0x62, 0x7c, 0xd5, 0x80, 0xde, 0x48, 0xf5, 0x08, 0x1e, 0xc2, 0xc0, 0x72, 0xd1, 0x57, 0x05, 0x43, 0x58, 0xa1, 0xbf, - 0x52, 0x36, 0xf9, 0xe6, 0xef, 0x6e, 0x7e, 0xcf, 0xb5, 0x98, 0x1d, 0x84, 0xe2, 0xf6, 0x7a, 0x02, 0xc4, 0xaf, 0xe2, - 0x57, 0x60, 0x5d, 0xad, 0x25, 0xde, 0x6e, 0x7a, 0xfe, 0x14, 0xbe, 0x1c, 0xdd, 0x7e, 0x52, 0x9a, 0x4f, 0x20, 0x48, - 0x8d, 0x93, 0x94, 0xbb, 0xef, 0x3e, 0x4a, 0x57, 0x11, 0x8c, 0x16, 0x20, 0xd6, 0xdd, 0x5b, 0xc9, 0x59, 0x53, 0xf8, - 0x8f, 0x75, 0xbe, 0xc7, 0xd8, 0x21, 0xf2, 0x14, 0xa7, 0xbf, 0x01, 0x86, 0x7d, 0xe7, 0xdf, 0xca, 0xac, 0x21, 0xd1, - 0xb9, 0xfa, 0x08, 0xe8, 0xff, 0x58, 0x8f, 0xdf, 0x31, 0x4a, 0xfa, 0x92, 0x38, 0x47, 0xb8, 0x22, 0x5e, 0xa2, 0xa9, - 0x5e, 0x6f, 0x5c, 0xd3, 0x4f, 0x85, 0x79, 0xa1, 0x15, 0x1c, 0xf6, 0xad, 0x51, 0x78, 0xe0, 0x99, 0xf7, 0x9b, 0x68, - 0x08, 0xba, 0x7f, 0xc7, 0xbd, 0xf1, 0x9b, 0x60, 0x19, 0xde, 0x94, 0xb3, 0xcc, 0xdc, 0xe1, 0x6e, 0x32, 0x91, 0xca, - 0x1b, 0xc6, 0x82, 0xb5, 0x50, 0xe6, 0xab, 0x69, 0x30, 0xdb, 0xd4, 0x91, 0x4a, 0x76, 0xdf, 0xbf, 0x6d, 0x9c, 0xb0, - 0xd9, 0x20, 0x38, 0xad, 0x64, 0x11, 0x5f, 0xf2, 0x60, 0xaa, 0x55, 0x14, 0x59, 0xd6, 0xef, 0x67, 0x80, 0x0c, 0xe3, - 0xb4, 0x77, 0xf0, 0x64, 0xa9, 0x99, 0x09, 0x71, 0x6d, 0x75, 0x16, 0xf0, 0xd6, 0x8c, 0xe6, 0x71, 0x05, 0xbb, 0xcc, - 0x57, 0x52, 0xfc, 0xd9, 0x92, 0x64, 0x63, 0xfd, 0x0d, 0x19, 0xb6, 0x95, 0xcf, 0x9c, 0x03, 0xc6, 0xcc, 0x8d, 0x54, - 0x41, 0xee, 0x7a, 0xc0, 0x08, 0x21, 0x11, 0x10, 0xce, 0x62, 0xe2, 0x4e, 0x98, 0xf0, 0x8f, 0x2e, 0x30, 0x4e, 0x8c, - 0x81, 0x71, 0x3e, 0xca, 0x90, 0xd3, 0x63, 0x3e, 0x48, 0x1a, 0xb3, 0xf5, 0xa7, 0x2a, 0x91, 0x5e, 0x4b, 0x42, 0xcf, - 0xe0, 0xf7, 0xb8, 0xc5, 0x03, 0x35, 0x82, 0x53, 0xba, 0x9b, 0xd3, 0xfe, 0xab, 0x82, 0x0c, 0xff, 0x02, 0xef, 0xae, - 0xd8, 0x5e, 0x96, 0x13, 0x58, 0xdc, 0xb1, 0x57, 0x3c, 0xcd, 0x55, 0x8b, 0x13, 0xe2, 0x11, 0x8b, 0xdc, 0x27, 0x16, - 0x30, 0xa2, 0x86, 0xd1, 0xf8, 0xf1, 0xf4, 0xe4, 0xad, 0xc6, 0x6c, 0xca, 0xfd, 0x0f, 0x60, 0x44, 0xb5, 0xb4, 0xdd, - 0x0e, 0xf8, 0x72, 0x84, 0x06, 0xdb, 0xa9, 0x1b, 0xec, 0x7e, 0xdf, 0xa4, 0x1d, 0x95, 0x5e, 0x36, 0x27, 0x06, 0xdd, - 0x51, 0xda, 0x2c, 0x95, 0x41, 0x6d, 0x57, 0xe1, 0x68, 0x3e, 0x6b, 0xc4, 0xaa, 0xde, 0x87, 0xe1, 0x92, 0xc6, 0x56, - 0x56, 0x6e, 0x77, 0x13, 0x8e, 0x6c, 0x02, 0x5c, 0x9f, 0x82, 0xb2, 0x6a, 0xce, 0x41, 0x0b, 0x3a, 0x13, 0x38, 0xa2, - 0xed, 0x36, 0x84, 0x08, 0x1c, 0xc5, 0x70, 0x32, 0x0b, 0x8b, 0xe1, 0x50, 0x0d, 0x7c, 0x41, 0x48, 0xf4, 0xa9, 0x98, - 0x67, 0x0b, 0x85, 0xd8, 0xe3, 0xef, 0xa4, 0xdf, 0x0a, 0xc5, 0x29, 0xf7, 0x7e, 0x13, 0x64, 0xf3, 0x7b, 0x8a, 0x31, - 0x07, 0x9d, 0x66, 0x33, 0x03, 0x09, 0xeb, 0x71, 0x45, 0xd4, 0x3a, 0xb2, 0xb3, 0x01, 0xaa, 0x58, 0x34, 0x85, 0x05, - 0x75, 0x8b, 0x27, 0xd6, 0x33, 0x7a, 0x0f, 0x2a, 0x41, 0x54, 0x0b, 0x76, 0x63, 0xb8, 0xd6, 0x3e, 0x89, 0x50, 0x52, - 0x4e, 0x9a, 0xcc, 0x8c, 0x15, 0x0d, 0x16, 0x20, 0x24, 0x8d, 0xcb, 0xea, 0x8d, 0x4c, 0xb3, 0x8b, 0x0c, 0x10, 0x13, - 0x9c, 0xff, 0x9c, 0x6c, 0xbc, 0x79, 0xae, 0xe6, 0xa5, 0x2b, 0x71, 0x66, 0x61, 0x3e, 0xba, 0xde, 0xd2, 0x82, 0x44, - 0x05, 0xd0, 0x28, 0x5f, 0xcb, 0xf3, 0xd3, 0x8e, 0x55, 0xc8, 0xee, 0x87, 0x53, 0x65, 0x3b, 0xc4, 0x8f, 0x58, 0x45, - 0xbc, 0xd3, 0xba, 0x52, 0x22, 0x8d, 0x8e, 0xb6, 0x01, 0x31, 0x6c, 0xd9, 0xb7, 0xa8, 0xe1, 0x83, 0x30, 0x83, 0x4e, - 0xf2, 0x83, 0x9e, 0xd1, 0xb1, 0x35, 0x90, 0xf4, 0xb5, 0x08, 0xbe, 0x46, 0x47, 0x3a, 0x51, 0xa6, 0x91, 0x98, 0x42, - 0xa2, 0x5f, 0x2f, 0xb4, 0xc6, 0x32, 0xca, 0xbe, 0x22, 0xff, 0x7b, 0xdd, 0xbd, 0xdf, 0xc4, 0x76, 0x0b, 0x93, 0xec, - 0x79, 0x5c, 0xc1, 0xa6, 0x46, 0xad, 0x10, 0xce, 0xce, 0x71, 0x85, 0xda, 0xb1, 0x5e, 0x58, 0x02, 0x79, 0x00, 0x5b, - 0x91, 0x06, 0x65, 0x90, 0xec, 0x53, 0x31, 0x17, 0x0b, 0x27, 0xca, 0x91, 0x0a, 0xef, 0x4b, 0x8e, 0x52, 0x0e, 0x57, - 0xb1, 0xb0, 0x60, 0xc8, 0xaf, 0x8e, 0x2e, 0x0a, 0x79, 0x05, 0x92, 0x12, 0xc3, 0x50, 0x59, 0x5e, 0x17, 0x57, 0x6d, - 0x49, 0x68, 0xef, 0x0c, 0x40, 0x58, 0x0a, 0x10, 0xbc, 0x34, 0x6a, 0x88, 0xd9, 0x46, 0xed, 0xae, 0xe8, 0x5e, 0x72, - 0x40, 0x9d, 0xee, 0xda, 0xad, 0x37, 0x65, 0x9b, 0x6d, 0xc5, 0x85, 0x7f, 0x42, 0xe9, 0xc7, 0x7c, 0x50, 0xf8, 0x54, - 0x02, 0x37, 0xbe, 0xda, 0x64, 0xd9, 0xc5, 0x1d, 0x2e, 0xfd, 0xaa, 0x31, 0x7e, 0xfd, 0x7e, 0x4f, 0x2d, 0x84, 0x46, - 0x2a, 0x30, 0xdf, 0x3e, 0x33, 0x55, 0x19, 0x4d, 0xa9, 0xbd, 0x04, 0x57, 0xce, 0x7e, 0x04, 0x15, 0x71, 0x5d, 0x91, - 0xc9, 0xd4, 0x00, 0xed, 0x79, 0x59, 0xe1, 0x56, 0x16, 0xe0, 0xb1, 0x13, 0x90, 0xed, 0x96, 0x87, 0x81, 0x3e, 0x74, - 0x02, 0x7f, 0x4b, 0x9e, 0x22, 0xb3, 0x66, 0x1f, 0x7f, 0xd1, 0x82, 0x7f, 0x6c, 0xc1, 0xcf, 0x28, 0xee, 0xb4, 0x32, - 0xff, 0x56, 0x5a, 0xb7, 0xb8, 0x7f, 0x27, 0xd3, 0x84, 0xa2, 0x32, 0xa1, 0xf6, 0x2b, 0xfd, 0x97, 0x09, 0x96, 0xa4, - 0xb2, 0x7f, 0x90, 0xf0, 0xc1, 0xac, 0xf1, 0xc4, 0x1a, 0x4f, 0x86, 0xd3, 0xad, 0x34, 0x0c, 0x01, 0x0a, 0xfd, 0xbc, - 0xcc, 0x15, 0xd5, 0xcf, 0xbf, 0xac, 0xf9, 0x9a, 0x37, 0x5b, 0x6c, 0x93, 0x1e, 0x68, 0xb0, 0x97, 0x47, 0x53, 0x0a, - 0x27, 0x51, 0xe7, 0x46, 0xa2, 0x2e, 0x6a, 0x96, 0xa1, 0x3a, 0xc1, 0xab, 0x79, 0xaa, 0x87, 0xbd, 0x99, 0x88, 0xd6, - 0x4a, 0xca, 0x12, 0x03, 0xd6, 0x3a, 0xf2, 0x90, 0xdc, 0xad, 0x75, 0xdc, 0x69, 0xa8, 0x4b, 0x53, 0x28, 0x01, 0x56, - 0xb8, 0x00, 0x47, 0xd0, 0xcf, 0x45, 0xc8, 0xe1, 0x9a, 0xaa, 0xf4, 0x0b, 0x9a, 0x92, 0x27, 0x9e, 0xa2, 0x56, 0x2b, - 0xd2, 0xed, 0x47, 0x39, 0x76, 0xc3, 0x37, 0x4e, 0xc8, 0x89, 0x11, 0xfa, 0xbb, 0x63, 0x29, 0x67, 0x68, 0xf1, 0xa0, - 0x4e, 0xb0, 0x5e, 0xde, 0x52, 0xa0, 0x98, 0xa3, 0xcb, 0xaa, 0x6b, 0x5e, 0xa3, 0xed, 0xcb, 0xb2, 0xdf, 0xcf, 0x6d, - 0x3d, 0x29, 0x3b, 0xda, 0x2c, 0xcd, 0x3e, 0x44, 0xc5, 0x14, 0xee, 0xfa, 0x44, 0xf3, 0x57, 0xa1, 0xbe, 0x6a, 0xcb, - 0x9c, 0x8f, 0x38, 0xe2, 0x62, 0xe4, 0xa4, 0xfe, 0x45, 0x4d, 0xbd, 0x12, 0xf7, 0xab, 0x4a, 0xbe, 0x13, 0xc6, 0x8a, - 0xd1, 0x01, 0xf5, 0xa7, 0x4a, 0xe5, 0xfd, 0xb2, 0x00, 0xb8, 0x27, 0xc1, 0x3e, 0x81, 0x7d, 0x85, 0x46, 0xf8, 0x6d, - 0x09, 0xf8, 0x37, 0x8a, 0x1b, 0xb0, 0x0a, 0x0c, 0x30, 0x9a, 0x6c, 0xcf, 0x69, 0x02, 0x07, 0x9c, 0xd0, 0x2a, 0x0a, - 0x2a, 0xcc, 0xd0, 0x50, 0x5b, 0x18, 0x3d, 0x45, 0x19, 0xb7, 0xca, 0xec, 0xdd, 0x18, 0x3b, 0x2d, 0xf0, 0x1a, 0xfe, - 0x7c, 0x5e, 0xe8, 0x61, 0xa3, 0x0e, 0xd2, 0xa3, 0x93, 0x98, 0xfe, 0xb8, 0x85, 0x93, 0x9b, 0x85, 0xb3, 0xac, 0x59, - 0x02, 0xdd, 0x81, 0x0b, 0x62, 0xdc, 0xef, 0xe7, 0x70, 0x64, 0x9a, 0x91, 0x2f, 0x58, 0x4e, 0x63, 0xb6, 0xa4, 0xda, - 0xd3, 0xee, 0xb2, 0x0a, 0x73, 0xba, 0xb4, 0x32, 0xde, 0x94, 0x81, 0xca, 0x68, 0xbb, 0x0d, 0xe1, 0x4f, 0xb7, 0xb5, - 0x4b, 0x3a, 0x5f, 0x42, 0x06, 0xf8, 0x03, 0x12, 0x51, 0xc4, 0xbe, 0xfe, 0xb7, 0x1a, 0xa7, 0xf4, 0x44, 0x69, 0xcd, - 0x12, 0xba, 0x66, 0xba, 0x7e, 0x7a, 0xc1, 0xd6, 0x8d, 0xa5, 0xb0, 0xdd, 0x86, 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, 0xf9, 0x50, 0x99, 0xaf, 0x8d, 0x47, 0xdc, 0xbf, 0xd2, 0x30, 0x31, 0x45, 0xa2, 0x42, 0x74, 0xf6, - 0x1b, 0xc8, 0x72, 0x04, 0xe0, 0x58, 0x9e, 0xca, 0x9a, 0xfe, 0x98, 0x42, 0x1c, 0x74, 0x68, 0xd0, 0xbb, 0x42, 0x5e, - 0x65, 0x25, 0x0f, 0xf1, 0x9e, 0xe0, 0x69, 0x46, 0xef, 0x37, 0xf8, 0xd0, 0xd6, 0x1e, 0x3d, 0x41, 0x36, 0x9e, 0x72, - 0xbf, 0xfe, 0x4e, 0x84, 0x73, 0x88, 0x56, 0xb9, 0xa0, 0x5a, 0x5d, 0xed, 0x00, 0xa8, 0x3c, 0xdb, 0xab, 0x47, 0x70, - 0xba, 0xe9, 0xeb, 0x5b, 0x15, 0x3a, 0x73, 0x00, 0x69, 0x0f, 0xc9, 0xba, 0xe6, 0x7a, 0x07, 0xb8, 0x23, 0xb1, 0x5a, - 0x03, 0x8d, 0x75, 0x5b, 0xb3, 0xd3, 0x1e, 0xc5, 0x63, 0x22, 0x33, 0x63, 0x91, 0x62, 0xcc, 0xdd, 0x3a, 0x2d, 0x8a, - 0x36, 0x68, 0x86, 0xb0, 0x7b, 0xd7, 0xe1, 0xeb, 0x56, 0x84, 0xf5, 0xfb, 0x6d, 0x5f, 0x60, 0x34, 0x8c, 0xb9, 0x76, - 0xcf, 0x33, 0x74, 0xc3, 0x06, 0xdb, 0xc8, 0x79, 0x88, 0x7c, 0x98, 0xa9, 0x03, 0x51, 0xd6, 0xd6, 0x80, 0xed, 0x11, - 0xd7, 0x9b, 0x56, 0xf1, 0xf3, 0x2a, 0xe6, 0x6c, 0xcf, 0x1a, 0xa7, 0xb4, 0xbe, 0xc6, 0x35, 0xc7, 0x55, 0x21, 0xa2, - 0xb6, 0x9e, 0xf1, 0x30, 0xec, 0x7c, 0x81, 0x3b, 0xb3, 0xc2, 0xe0, 0x45, 0x58, 0x2a, 0xd9, 0xa9, 0x5c, 0x7f, 0x0e, - 0x5b, 0x1c, 0xa4, 0xf2, 0xa5, 0xd7, 0xdf, 0x7f, 0xf9, 0xe2, 0x0b, 0x74, 0x53, 0x73, 0x7e, 0x04, 0x41, 0x26, 0xd0, - 0x21, 0x4b, 0xa9, 0x1e, 0xbf, 0x2b, 0x80, 0xda, 0xc3, 0x3c, 0x7c, 0x57, 0x30, 0x11, 0x5f, 0x67, 0x97, 0x71, 0x25, - 0x8b, 0xd1, 0x35, 0x17, 0xa9, 0x2c, 0xac, 0xd4, 0x38, 0x38, 0x5e, 0xad, 0x72, 0x1e, 0x80, 0xa9, 0xbc, 0x65, 0x94, - 0x6d, 0x65, 0x99, 0x1e, 0x5c, 0x2d, 0x4f, 0xaf, 0xb4, 0xe8, 0xbc, 0xbc, 0xbe, 0x0c, 0x22, 0xfc, 0x75, 0x6e, 0x7e, - 0x5c, 0xc5, 0xe5, 0xc7, 0x20, 0xb2, 0x36, 0x75, 0xe6, 0x07, 0x4a, 0xe5, 0xc1, 0x7f, 0x0a, 0x64, 0xba, 0xdf, 0x15, - 0x60, 0x99, 0x6d, 0x2b, 0x3e, 0x8c, 0xb1, 0xd6, 0xe1, 0x84, 0xcc, 0x54, 0x89, 0xde, 0xbb, 0x64, 0x5d, 0x80, 0xb5, - 0x9f, 0xc2, 0x32, 0x56, 0xb9, 0x66, 0x58, 0x99, 0xaa, 0xc8, 0xcc, 0xca, 0x9a, 0xed, 0x87, 0xd6, 0x89, 0x66, 0x8e, - 0xde, 0x02, 0xfa, 0x81, 0xec, 0x5f, 0xd2, 0x72, 0xcd, 0x3c, 0x1f, 0x9b, 0xc6, 0xeb, 0x47, 0xfb, 0x97, 0x6e, 0xc1, - 0xde, 0xda, 0x3b, 0x39, 0x0a, 0x13, 0xc1, 0xb3, 0xd6, 0x8c, 0x2f, 0xf2, 0xac, 0x80, 0x95, 0x33, 0x19, 0x8f, 0xa9, - 0xb7, 0xb4, 0x5a, 0x37, 0x47, 0x87, 0xe4, 0x9a, 0x3d, 0xae, 0x1e, 0x73, 0xb2, 0xcf, 0x5b, 0xa6, 0xb6, 0x6d, 0xeb, - 0x38, 0x4f, 0x93, 0xaf, 0x4c, 0xf7, 0xc5, 0xda, 0x46, 0x44, 0x57, 0xce, 0x7d, 0xce, 0x2b, 0xb8, 0xf5, 0x4d, 0x69, - 0xe8, 0xb5, 0x04, 0x20, 0x3a, 0x6d, 0xc0, 0x5f, 0xb0, 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, 0xb1, 0xbb, 0xca, 0xa5, 0x13, 0xf5, - 0x5b, 0x26, 0x5c, 0xb9, 0x12, 0x04, 0x64, 0x5a, 0xb0, 0x5e, 0x61, 0x76, 0x91, 0x5c, 0x03, 0x21, 0x03, 0xc3, 0xd7, - 0x60, 0x2d, 0x4a, 0x6e, 0xac, 0x60, 0xbd, 0x7b, 0xbe, 0x4e, 0x10, 0x52, 0xf0, 0xc0, 0x4d, 0xd0, 0x0f, 0xad, 0x9b, - 0xb7, 0xa3, 0x44, 0x19, 0xc4, 0xe3, 0xd6, 0x4e, 0x39, 0x48, 0x20, 0x00, 0xf7, 0x54, 0x85, 0xe0, 0x50, 0x20, 0xeb, - 0xe0, 0x6a, 0xc6, 0x11, 0x5c, 0x5d, 0x39, 0x73, 0x71, 0x03, 0xb0, 0xae, 0xfc, 0xb9, 0x6c, 0x70, 0x61, 0x3d, 0xa2, - 0xca, 0x9c, 0x71, 0x8a, 0x41, 0x8c, 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, 0x20, 0x0a, 0xb5, 0x01, 0x43, 0xe0, 0x90, 0xf8, 0x83, 0x41, 0xa8, 0xf1, 0x4e, 0x06, 0x2a, 0x20, 0x16, - 0xf1, 0x78, 0x6c, 0xc4, 0xcd, 0x0a, 0xc7, 0x43, 0x0c, 0x7e, 0xd5, 0x7c, 0x41, 0x02, 0x42, 0x4d, 0x69, 0xe8, 0xf2, - 0x18, 0x0e, 0x27, 0x7b, 0x13, 0x48, 0xc5, 0xcc, 0x4c, 0x15, 0xc6, 0xc6, 0x24, 0x82, 0x78, 0xa7, 0x9d, 0xf5, 0x42, - 0xb9, 0xdd, 0x35, 0x1a, 0xc8, 0x95, 0xc1, 0x17, 0x55, 0x3c, 0xd9, 0x1b, 0x76, 0x55, 0x8c, 0xa3, 0x70, 0x6d, 0x94, - 0x6f, 0x67, 0x87, 0x00, 0x5e, 0x7b, 0x36, 0xf4, 0xe5, 0x12, 0x67, 0xfb, 0x4f, 0xc9, 0xe3, 0xa7, 0x84, 0x9e, 0xb1, - 0xb3, 0xaf, 0x9e, 0xd2, 0x33, 0x45, 0x4e, 0xf6, 0x26, 0xd1, 0x35, 0xb3, 0x98, 0x2f, 0x07, 0xaa, 0x09, 0xf4, 0x72, - 0xb4, 0x16, 0x6a, 0x81, 0x69, 0x87, 0xa6, 0xf0, 0xdb, 0xf1, 0x5e, 0x30, 0xb8, 0x6e, 0x37, 0xfd, 0xba, 0xdd, 0x56, - 0xcf, 0xab, 0x6b, 0xef, 0x20, 0xda, 0x2d, 0x66, 0xf2, 0xf7, 0xf1, 0x9e, 0x9b, 0x03, 0xac, 0xef, 0xe1, 0x31, 0x31, - 0x4d, 0xda, 0x19, 0x15, 0xbf, 0xa6, 0x27, 0xd8, 0x87, 0x66, 0x91, 0x1d, 0x7d, 0x18, 0xfe, 0x5b, 0x9d, 0xa8, 0xcf, - 0xbe, 0x3a, 0x00, 0x72, 0x04, 0x32, 0x50, 0x2c, 0x11, 0xcc, 0x70, 0xa0, 0x29, 0xa0, 0x20, 0xd3, 0xe3, 0x4e, 0xf5, - 0xf0, 0xab, 0x51, 0x53, 0x33, 0x72, 0x0d, 0x53, 0x83, 0x6d, 0xc1, 0x0f, 0x54, 0x37, 0xf4, 0x37, 0x1a, 0xdd, 0x48, - 0x3b, 0x99, 0x99, 0x97, 0xd4, 0xc6, 0x75, 0xbb, 0x86, 0x00, 0xc6, 0x0e, 0x5e, 0x50, 0xb2, 0xaf, 0x0f, 0x2f, 0xf7, - 0x70, 0x15, 0x01, 0x4a, 0x16, 0x0b, 0xbe, 0x1e, 0x5c, 0xea, 0xcd, 0xbd, 0x17, 0x90, 0xc1, 0xd7, 0xc1, 0xd1, 0xd7, - 0x03, 0x39, 0x08, 0x0e, 0xf7, 0x2f, 0x8f, 0x02, 0x67, 0xdc, 0x0f, 0x21, 0x1e, 0x55, 0x45, 0x31, 0x13, 0xa6, 0x8a, - 0xc4, 0xd6, 0x9e, 0xdb, 0x7a, 0x95, 0xf1, 0x19, 0x4d, 0xa7, 0x16, 0xf9, 0x3b, 0x4c, 0x59, 0x6c, 0x7e, 0x07, 0x13, - 0x7e, 0x15, 0x44, 0x2e, 0x08, 0xea, 0x2c, 0x8f, 0x62, 0xba, 0x64, 0xb7, 0x22, 0x4c, 0x69, 0xb2, 0x9f, 0x13, 0x12, - 0x85, 0x4b, 0x05, 0x9e, 0xa7, 0x5e, 0x27, 0x10, 0xc7, 0xd5, 0x7d, 0x7e, 0x2b, 0xc2, 0x25, 0xcd, 0xf7, 0x13, 0xd2, - 0x2a, 0xc2, 0x45, 0x64, 0xd9, 0xd4, 0xf4, 0x82, 0x85, 0x2b, 0x7a, 0x09, 0xcc, 0x94, 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, 0xed, 0x4d, 0x6c, 0x4e, 0xf6, 0x32, 0x5a, 0x2b, 0x97, 0x55, 0xcb, 0x90, 0x14, 0x6b, 0x86, - 0xfc, 0x3d, 0x4a, 0x4e, 0xad, 0xc0, 0x93, 0x5d, 0xf0, 0x2a, 0x59, 0xfa, 0x07, 0x95, 0xb5, 0x1a, 0xb0, 0xc7, 0x88, - 0x65, 0xa1, 0x70, 0xec, 0xdf, 0x64, 0xac, 0x58, 0xfb, 0x02, 0x8d, 0x18, 0xb9, 0xb7, 0x37, 0x19, 0xf3, 0x62, 0xae, - 0x26, 0x6b, 0x2f, 0x54, 0x9d, 0x97, 0x9e, 0xb7, 0x78, 0x2f, 0xa7, 0xd4, 0x30, 0x12, 0xd1, 0xbd, 0xb1, 0x32, 0xa3, - 0x54, 0x89, 0x5a, 0x83, 0x46, 0x04, 0x1b, 0xbb, 0xe0, 0x97, 0xe0, 0x84, 0xca, 0x3d, 0x75, 0xb6, 0x6f, 0xa7, 0x54, - 0x7a, 0xc0, 0xb2, 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, - 0x24, 0x77, 0xb9, 0x6e, 0x05, 0xc9, 0x7d, 0x3a, 0x7e, 0xaa, 0x07, 0x3a, 0x5d, 0x6b, 0xc7, 0x43, 0x9f, 0xdf, 0x46, - 0x7c, 0x6d, 0xdd, 0x7b, 0xaa, 0xb5, 0x0a, 0x65, 0xa0, 0xc5, 0x8a, 0xca, 0x95, 0x5a, 0xd2, 0xfb, 0x5d, 0x04, 0xc0, - 0x22, 0x36, 0x66, 0xe3, 0x5d, 0xdb, 0xac, 0x10, 0x34, 0xba, 0xec, 0x68, 0x13, 0x0f, 0x58, 0xa2, 0x5b, 0x3b, 0x98, - 0xd0, 0xf8, 0x88, 0x95, 0xfd, 0x7e, 0x7e, 0x04, 0xf4, 0x54, 0x1b, 0x31, 0x15, 0x70, 0xe4, 0x7f, 0x69, 0x45, 0xa6, - 0x28, 0xb0, 0x59, 0x53, 0x77, 0x6b, 0x2c, 0x23, 0xd1, 0x97, 0x29, 0x5d, 0x9e, 0xf0, 0x0c, 0x98, 0xd6, 0xeb, 0x96, - 0xe3, 0xca, 0xae, 0xe2, 0xc8, 0x53, 0x61, 0x59, 0x71, 0x5e, 0x85, 0xe3, 0xad, 0xc7, 0x37, 0xd8, 0x37, 0x6c, 0xda, - 0x85, 0x3f, 0x84, 0xb0, 0x10, 0xde, 0x64, 0x70, 0x1b, 0xd1, 0x76, 0x12, 0xa8, 0xbc, 0x31, 0xd7, 0x09, 0x65, 0x73, - 0xbb, 0x5e, 0x7b, 0x06, 0xe9, 0xc4, 0x1c, 0x28, 0xd5, 0x08, 0x5a, 0xa3, 0x59, 0x50, 0x35, 0xe2, 0x91, 0xe3, 0xe1, - 0x9d, 0x41, 0xac, 0x96, 0x2f, 0x69, 0x2a, 0x45, 0x03, 0x30, 0x2e, 0x80, 0xcb, 0xd3, 0xaf, 0xef, 0x7f, 0x3e, 0xe5, - 0x71, 0x91, 0x2c, 0xdf, 0xc5, 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, 0xdd, 0x07, 0x20, 0x4f, 0xe3, 0x42, 0x1a, 0x49, 0x5d, 0x88, 0x31, 0x17, 0xf1, 0xba, 0x3e, 0x1e, 0x37, - 0xba, 0x5e, 0xb2, 0x67, 0xe3, 0x27, 0xd3, 0x37, 0x59, 0x98, 0x0d, 0x04, 0x19, 0x55, 0x4b, 0x2e, 0x5a, 0xa6, 0x9c, - 0xca, 0x24, 0x00, 0x7d, 0x3c, 0x7b, 0x8c, 0x1d, 0x8c, 0xc7, 0x64, 0xd3, 0x16, 0x0f, 0xf0, 0x70, 0xb9, 0x0e, 0x0b, - 0x32, 0xd3, 0x75, 0x44, 0x81, 0xe0, 0xb7, 0x55, 0x00, 0x48, 0x8e, 0xb6, 0x2a, 0xc3, 0xa5, 0xb1, 0x67, 0xe3, 0x09, - 0x95, 0xd8, 0xed, 0x90, 0xd4, 0x5e, 0x85, 0x6e, 0xe6, 0xa5, 0xef, 0x51, 0x24, 0x8d, 0xcb, 0xd2, 0x4e, 0xa5, 0x52, - 0xed, 0x99, 0x99, 0xeb, 0x1a, 0xc4, 0x60, 0x08, 0x75, 0xdd, 0xa5, 0x57, 0xf7, 0x6e, 0x73, 0xad, 0xd9, 0x0e, 0x78, - 0xaf, 0x41, 0x33, 0x94, 0xbc, 0xc5, 0xbc, 0x75, 0x45, 0xd4, 0x74, 0xb5, 0x06, 0xb3, 0x62, 0x94, 0x2d, 0x45, 0xe9, - 0x9a, 0x82, 0x52, 0x30, 0xba, 0x58, 0x7b, 0x0b, 0xf7, 0x8d, 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, 0xc7, - 0x15, 0x39, 0x06, 0x47, 0x2f, 0x93, 0xd3, 0x50, 0xe0, 0x1f, 0x33, 0x05, 0x62, 0x3a, 0x54, 0xf7, 0x1b, 0xdc, 0xfc, - 0xff, 0x28, 0x58, 0xe0, 0xf1, 0xad, 0x97, 0xb8, 0x8d, 0xfe, 0x51, 0xf8, 0xb4, 0xf4, 0xb9, 0xf4, 0x5d, 0x5d, 0x3c, - 0x69, 0x6f, 0x36, 0x4a, 0x96, 0x59, 0x9e, 0xbe, 0x95, 0x29, 0x07, 0x91, 0x19, 0x5a, 0x83, 0xb2, 0x23, 0xd1, 0xb8, - 0xe1, 0x81, 0x11, 0x63, 0xe3, 0xc6, 0xf7, 0x63, 0x06, 0xb2, 0x61, 0xb0, 0xfa, 0x66, 0xa9, 0x4c, 0xd6, 0x57, 0x80, - 0x29, 0xa2, 0xe4, 0x27, 0x2f, 0x73, 0x0e, 0x4f, 0xa1, 0xbe, 0x7e, 0x81, 0xdb, 0x5c, 0xe9, 0xfb, 0x9c, 0xff, 0x98, - 0xd1, 0x1f, 0x11, 0xe8, 0x24, 0x5e, 0x81, 0xdc, 0xe3, 0x39, 0xd4, 0x8d, 0x30, 0xb5, 0x1c, 0x83, 0x03, 0x21, 0x1a, - 0x88, 0xa8, 0x58, 0xa0, 0xa0, 0x2e, 0x0c, 0xb0, 0x86, 0xba, 0x60, 0x0e, 0xcf, 0x73, 0x99, 0x7c, 0x9c, 0x1a, 0x9f, - 0xf9, 0x61, 0x8c, 0x31, 0x93, 0x83, 0x41, 0x58, 0xcd, 0x82, 0xe1, 0x78, 0x34, 0x39, 0x78, 0x06, 0xe7, 0x76, 0x30, - 0x0e, 0xc8, 0x20, 0xa8, 0xcb, 0x55, 0x2c, 0x68, 0x79, 0x7d, 0x69, 0xcb, 0xc0, 0x8f, 0xeb, 0x60, 0xf0, 0x8f, 0xc2, - 0x53, 0xbc, 0x83, 0xe6, 0xe4, 0x4c, 0x86, 0x60, 0x63, 0xbf, 0x26, 0x20, 0x29, 0xeb, 0x69, 0x7e, 0x52, 0x1f, 0x6e, - 0x4c, 0x69, 0xff, 0xcc, 0xe1, 0x05, 0x87, 0x1d, 0x12, 0x28, 0x90, 0xc6, 0xd3, 0x6c, 0xf4, 0x5a, 0x29, 0x72, 0xdf, - 0x15, 0x1c, 0xee, 0xcc, 0x3d, 0x67, 0x7a, 0xe4, 0x14, 0x12, 0xcd, 0x2c, 0xe0, 0x46, 0xfe, 0x5a, 0x5c, 0xc7, 0x79, - 0x96, 0xee, 0x35, 0xdf, 0xec, 0x95, 0x77, 0xa2, 0x8a, 0x6f, 0x47, 0x81, 0xb1, 0x26, 0xe4, 0xbe, 0xea, 0x09, 0xd0, - 0x13, 0x60, 0x0b, 0x80, 0x01, 0xf1, 0x8e, 0x99, 0xc9, 0x8c, 0x47, 0xe0, 0x11, 0xd8, 0xf4, 0x81, 0x2c, 0xee, 0x9c, - 0x4b, 0x92, 0xbf, 0x99, 0x4a, 0x7b, 0xd5, 0x2b, 0x77, 0x0a, 0xb2, 0x5e, 0x6d, 0xe5, 0xae, 0x5b, 0x9f, 0x7d, 0xd3, - 0xe1, 0x15, 0x78, 0x2e, 0xc1, 0x2d, 0xb2, 0xdf, 0x6f, 0x0a, 0x2a, 0x85, 0x51, 0x11, 0xef, 0x24, 0xd7, 0xe8, 0xdf, - 0xee, 0x8d, 0x8d, 0x22, 0xb9, 0xe5, 0xc3, 0x03, 0xa8, 0x33, 0x79, 0x57, 0xdc, 0xce, 0x21, 0x6a, 0xeb, 0x6e, 0x3c, - 0xb0, 0xda, 0xa0, 0x5d, 0xd6, 0x1c, 0xc1, 0x85, 0x17, 0x7b, 0x19, 0x8c, 0x05, 0xce, 0xca, 0x48, 0xa9, 0x71, 0x0d, - 0xa9, 0x05, 0x9f, 0xe4, 0xe9, 0x3d, 0x64, 0xa9, 0x27, 0x41, 0x91, 0xe3, 0x59, 0x0c, 0x99, 0xc6, 0xdb, 0xc0, 0xe3, - 0x77, 0x32, 0x04, 0x69, 0xda, 0x76, 0xdb, 0x1c, 0x81, 0xb2, 0x7b, 0x60, 0x4a, 0x52, 0xd7, 0xc6, 0xd4, 0x40, 0x43, - 0xed, 0xa1, 0x46, 0x2a, 0xe2, 0xec, 0xe8, 0x0d, 0xe8, 0x10, 0xc1, 0xf7, 0x3b, 0xcd, 0xca, 0x8e, 0x17, 0x13, 0x82, - 0x27, 0xef, 0xcb, 0xdb, 0xac, 0xac, 0xca, 0xe8, 0x7d, 0x8a, 0x86, 0x50, 0x89, 0x14, 0xd1, 0x2b, 0x88, 0xa7, 0x57, - 0xe2, 0xef, 0x32, 0xfa, 0x39, 0xa5, 0x71, 0x9a, 0x62, 0xfa, 0x8b, 0x02, 0x7e, 0x3e, 0x07, 0x54, 0x47, 0xdc, 0x09, - 0xd1, 0xb9, 0x04, 0x7b, 0x35, 0x88, 0x66, 0x55, 0x71, 0xc0, 0xd0, 0x8c, 0x6e, 0x05, 0x45, 0x8c, 0x36, 0xcc, 0xfe, - 0x43, 0x81, 0x42, 0x21, 0x55, 0xcc, 0x77, 0xc2, 0x3e, 0x44, 0x3f, 0x62, 0x91, 0xc7, 0xef, 0x5e, 0x9b, 0x21, 0x8d, - 0xee, 0x24, 0xd5, 0x5b, 0x1b, 0x8f, 0x2d, 0x0c, 0x5c, 0x16, 0x5d, 0xae, 0xe9, 0x59, 0xbc, 0xca, 0xa2, 0x0d, 0xe0, - 0x4f, 0xbc, 0x7b, 0xfd, 0x5c, 0x59, 0x98, 0xbc, 0xc8, 0x40, 0x71, 0x70, 0xfc, 0xee, 0xf5, 0x1b, 0x99, 0xae, 0x73, - 0x1e, 0x9d, 0x49, 0x24, 0xad, 0xc7, 0xef, 0x5e, 0xff, 0x82, 0xe6, 0x5e, 0x3f, 0x17, 0xf0, 0xfe, 0x15, 0xf0, 0x96, - 0x51, 0xbc, 0x86, 0x3e, 0xa9, 0xdf, 0xc9, 0x1a, 0x3b, 0xe5, 0xd5, 0x5a, 0x46, 0xbf, 0xa6, 0xb5, 0x27, 0xad, 0xfa, - 0x67, 0xe1, 0x53, 0x3b, 0x4f, 0xc0, 0x73, 0x9b, 0x67, 0xe2, 0x63, 0x64, 0x45, 0x3b, 0x41, 0xf4, 0xf5, 0xde, 0xed, - 0x55, 0x2e, 0xca, 0x08, 0x5f, 0x30, 0xb4, 0x0b, 0x8a, 0xf6, 0xf7, 0x6f, 0x6e, 0x6e, 0x46, 0x37, 0x4f, 0x46, 0xb2, - 0xb8, 0xdc, 0x9f, 0x7c, 0xfb, 0xed, 0xb7, 0xfb, 0xf8, 0x36, 0xf8, 0xba, 0xed, 0xf6, 0x5e, 0x11, 0x3e, 0x60, 0x01, - 0x22, 0x54, 0x7f, 0x0d, 0x57, 0x14, 0xd0, 0xc2, 0x0d, 0xbe, 0x0e, 0xbe, 0xd6, 0x87, 0xce, 0xd7, 0x87, 0xe5, 0xf5, - 0xa5, 0x2a, 0xbf, 0xab, 0xe4, 0x83, 0xf1, 0x78, 0xbc, 0x0f, 0x12, 0xa8, 0xaf, 0x07, 0x7c, 0x10, 0x1c, 0x05, 0x83, - 0x0c, 0x2e, 0x34, 0xe5, 0xf5, 0xe5, 0x51, 0xe0, 0x99, 0xe6, 0x36, 0x58, 0x44, 0x07, 0xe2, 0x12, 0xec, 0x5f, 0xd2, - 0xe0, 0xeb, 0x80, 0xb8, 0x94, 0xaf, 0x20, 0xe5, 0xab, 0x83, 0x67, 0x7e, 0xda, 0xff, 0x52, 0x69, 0x4f, 0xfc, 0xb4, - 0x43, 0x4c, 0x7b, 0xf2, 0xdc, 0x4f, 0x3b, 0x52, 0x69, 0x2f, 0xfd, 0xb4, 0xff, 0x5d, 0x0e, 0x20, 0x75, 0xcf, 0xb7, - 0xfe, 0x3b, 0xf7, 0x5a, 0x83, 0xa7, 0x50, 0x94, 0x5d, 0xc5, 0x97, 0x1c, 0x1a, 0x3d, 0xb8, 0xbd, 0xca, 0x69, 0x30, - 0xc0, 0xf6, 0x7a, 0x26, 0x21, 0xde, 0x07, 0x5f, 0xaf, 0x8b, 0x3c, 0x0c, 0xbe, 0x1e, 0x60, 0x21, 0x83, 0xaf, 0x03, - 0xf2, 0xb5, 0x31, 0x90, 0x11, 0x6c, 0x13, 0xb8, 0x50, 0xa4, 0x43, 0x1b, 0x20, 0xcc, 0x97, 0xc6, 0xd5, 0xf4, 0xaf, - 0xa2, 0x3b, 0x1b, 0xde, 0x12, 0x95, 0x9b, 0x6e, 0x50, 0xd3, 0x13, 0xf0, 0x4e, 0x80, 0x46, 0x45, 0xc1, 0x75, 0x5c, - 0x84, 0xc3, 0x61, 0x79, 0x7d, 0x49, 0xc0, 0x2e, 0x73, 0xc5, 0xe3, 0x2a, 0x0a, 0x84, 0x1c, 0xaa, 0x9f, 0x81, 0x8a, - 0x7c, 0x15, 0x20, 0x20, 0x12, 0xfc, 0x17, 0xd4, 0xf4, 0x9d, 0x64, 0x9b, 0x60, 0x78, 0xc3, 0xcf, 0x3f, 0x66, 0xd5, - 0x50, 0x89, 0x16, 0xaf, 0x05, 0x85, 0x1f, 0xf0, 0xd7, 0x55, 0x1d, 0xfd, 0x05, 0x6e, 0xdc, 0x4d, 0x0d, 0xfb, 0x3b, - 0xe9, 0x58, 0xd4, 0x77, 0x72, 0x9e, 0x2d, 0xa6, 0xad, 0x03, 0xfd, 0x44, 0x92, 0x6a, 0x9e, 0x0d, 0x82, 0x61, 0x30, - 0xe0, 0x0b, 0x76, 0x22, 0xe7, 0xdc, 0x33, 0x9f, 0x7a, 0x24, 0xfd, 0x69, 0x9e, 0x65, 0x03, 0xf0, 0x4d, 0x41, 0x7e, - 0x64, 0xff, 0xbf, 0xe7, 0x43, 0x14, 0x1e, 0x0e, 0x1e, 0xed, 0x93, 0x59, 0xb0, 0xba, 0x45, 0x8f, 0xce, 0x28, 0xc8, - 0xc4, 0x92, 0x17, 0x59, 0xe5, 0x2d, 0x95, 0xbb, 0x75, 0xdb, 0xcb, 0xe3, 0xde, 0xb3, 0x79, 0x15, 0x8b, 0x40, 0x9d, - 0x73, 0xa0, 0x78, 0x43, 0xd9, 0x53, 0xd9, 0x94, 0x90, 0x6a, 0x43, 0xde, 0xb0, 0x1c, 0xb0, 0xe0, 0xb0, 0x37, 0x1c, - 0xee, 0x05, 0x03, 0xa7, 0xce, 0x1d, 0x04, 0x7b, 0xc3, 0xe1, 0x51, 0xe0, 0xee, 0x43, 0xd9, 0xc8, 0xdd, 0x19, 0x69, - 0xc1, 0xfe, 0x59, 0x84, 0x25, 0x05, 0xf1, 0x98, 0xd4, 0xe2, 0x2f, 0x0d, 0x2e, 0x33, 0x00, 0xe8, 0x23, 0x25, 0x01, - 0x33, 0xb0, 0x32, 0x03, 0x08, 0xcd, 0x4d, 0x63, 0x76, 0x06, 0xcc, 0x23, 0x70, 0xcc, 0x23, 0x64, 0x1c, 0x00, 0xb1, - 0x24, 0xc0, 0xb9, 0x0b, 0xa2, 0x58, 0x17, 0xf2, 0x08, 0x40, 0xef, 0xf1, 0x27, 0x31, 0xa5, 0x60, 0x92, 0x8e, 0x55, - 0x08, 0x82, 0x38, 0x3e, 0xbb, 0x16, 0xad, 0xc9, 0x59, 0xa2, 0x83, 0x19, 0x49, 0x80, 0x0d, 0x31, 0xb0, 0x73, 0x70, - 0x3f, 0x07, 0xa5, 0x87, 0xd5, 0x3b, 0x21, 0x17, 0x7c, 0xc7, 0x3d, 0xd9, 0x2c, 0x5c, 0x3d, 0xe1, 0x20, 0xb8, 0xe3, - 0x9a, 0x05, 0x18, 0x55, 0xc5, 0xba, 0xac, 0x78, 0xfa, 0xe1, 0x6e, 0x05, 0xb1, 0xef, 0x70, 0x40, 0xdf, 0xc9, 0x3c, - 0x4b, 0xee, 0x42, 0x67, 0xcf, 0xb5, 0x51, 0xe9, 0x3f, 0x7c, 0x78, 0xf3, 0x73, 0x04, 0x22, 0xc7, 0xda, 0x50, 0xfa, - 0x3b, 0x8e, 0x67, 0x93, 0x1f, 0xe1, 0xc9, 0xdf, 0xd8, 0x77, 0xdc, 0x9e, 0x1e, 0xfd, 0x3e, 0xd4, 0x4d, 0xef, 0xf8, - 0xec, 0x8e, 0x8f, 0x5c, 0x71, 0xa8, 0xae, 0x70, 0x5f, 0xdf, 0xac, 0x7d, 0x23, 0xa4, 0x87, 0xe7, 0x99, 0xf2, 0xc6, - 0xfc, 0x68, 0x07, 0xc3, 0x20, 0x98, 0x6a, 0xa1, 0x24, 0x44, 0xdd, 0x60, 0x4a, 0xc0, 0x10, 0xed, 0xe9, 0x65, 0x35, - 0x45, 0xce, 0x4d, 0x8d, 0x2c, 0xbc, 0x1f, 0x30, 0x2d, 0x74, 0x68, 0xe4, 0x50, 0x7e, 0x70, 0x38, 0x61, 0xcc, 0xc2, - 0x6f, 0x95, 0x30, 0xfd, 0x6a, 0x51, 0x39, 0x07, 0xd1, 0x3d, 0x30, 0xc6, 0x15, 0xbc, 0x80, 0xae, 0xb0, 0xeb, 0xb5, - 0x8a, 0x8a, 0x81, 0xe0, 0x71, 0xc8, 0x01, 0x7a, 0xd8, 0x05, 0x2d, 0x2b, 0x4b, 0x75, 0xab, 0x72, 0x96, 0x2a, 0xea, - 0x32, 0x94, 0x95, 0xb1, 0xc2, 0x7c, 0x2f, 0xd9, 0x0f, 0x05, 0x7a, 0x96, 0x4f, 0x45, 0x17, 0xbc, 0x10, 0x4a, 0xb0, - 0x5c, 0xd7, 0x3b, 0x11, 0x88, 0x3a, 0x3f, 0xf4, 0xae, 0xfa, 0x1a, 0xc7, 0x8e, 0xa7, 0x6f, 0x64, 0xca, 0xb5, 0x09, - 0x85, 0xe6, 0xf3, 0xa5, 0xaf, 0x98, 0x28, 0xd8, 0x0d, 0xf4, 0xab, 0x6d, 0xa3, 0xcf, 0xee, 0xd6, 0x7a, 0x33, 0x28, - 0xd1, 0x31, 0xaf, 0x51, 0x70, 0xad, 0x14, 0x0a, 0x46, 0x7b, 0x1b, 0x7f, 0x86, 0x23, 0xb7, 0xba, 0x3d, 0xf4, 0x7e, - 0xab, 0xe2, 0xcb, 0xb7, 0xe8, 0xdb, 0x69, 0x7f, 0x8e, 0x2a, 0xf9, 0xeb, 0x6a, 0x05, 0x3e, 0x54, 0x10, 0x59, 0xc4, - 0xe2, 0xd2, 0x42, 0x3d, 0xa7, 0xef, 0x8e, 0xdf, 0x82, 0x1f, 0x25, 0xfe, 0xfe, 0xed, 0xfb, 0xa0, 0x26, 0xd3, 0x78, - 0x56, 0x98, 0x0f, 0x6d, 0x0e, 0x08, 0x4d, 0xe2, 0xd2, 0xec, 0xfb, 0x59, 0xdc, 0x64, 0xdf, 0x35, 0x5b, 0x4f, 0x8b, - 0x26, 0x92, 0x94, 0xe1, 0xf6, 0xc1, 0x80, 0x40, 0x1f, 0x20, 0x8a, 0xb3, 0x2f, 0x68, 0x0c, 0x69, 0x3e, 0xb3, 0xef, - 0x47, 0xc4, 0x7b, 0xb9, 0x13, 0x42, 0x8c, 0x2b, 0x2c, 0x1a, 0x3d, 0xe4, 0x33, 0x1e, 0x29, 0xc3, 0xa2, 0xf7, 0x98, - 0x40, 0x9c, 0xe1, 0xb4, 0x7a, 0x8f, 0x98, 0xc7, 0x78, 0x37, 0xd0, 0xb2, 0x87, 0x28, 0xa3, 0x2e, 0x7b, 0xc3, 0xe2, - 0xfb, 0xe3, 0x3a, 0xcc, 0xac, 0xe5, 0xe5, 0x10, 0xfe, 0x06, 0xda, 0x00, 0x9c, 0x72, 0x64, 0xf9, 0x2a, 0xb3, 0xd1, - 0xd5, 0x12, 0xd3, 0x9b, 0x08, 0x62, 0xf1, 0xe8, 0x74, 0x58, 0xbb, 0x3a, 0x55, 0xef, 0x6a, 0xe7, 0x33, 0xd1, 0xab, - 0x40, 0x2b, 0xd7, 0xb6, 0xc7, 0x43, 0xb8, 0x4b, 0x2d, 0xad, 0xb0, 0x11, 0xe5, 0x5c, 0x3c, 0xdd, 0x39, 0x36, 0x27, - 0xa0, 0xc1, 0x95, 0x4c, 0x01, 0x38, 0x4b, 0xab, 0xd1, 0xa8, 0x11, 0xf6, 0x59, 0x39, 0x9f, 0xc3, 0xd6, 0x42, 0x3c, - 0x2d, 0x00, 0xc3, 0x6d, 0x62, 0x50, 0xf2, 0x6e, 0x0c, 0xca, 0xe9, 0x47, 0x05, 0x6f, 0x1d, 0x9c, 0x95, 0xcb, 0x38, - 0x95, 0x37, 0x80, 0xc5, 0x18, 0xf8, 0xa9, 0x58, 0xaa, 0x97, 0x90, 0x2c, 0x79, 0xf2, 0x11, 0xad, 0x36, 0xd2, 0x00, - 0xb8, 0xca, 0xa9, 0xb1, 0xdc, 0x53, 0x20, 0xa1, 0xae, 0x14, 0x95, 0x10, 0x57, 0x55, 0x9c, 0x2c, 0x4f, 0x31, 0x35, - 0xdc, 0x40, 0x2f, 0xa2, 0x40, 0xae, 0xb8, 0x00, 0x92, 0x9e, 0xb3, 0x7f, 0x65, 0x1a, 0x6b, 0xfc, 0xb9, 0x44, 0x01, - 0x93, 0x46, 0x0d, 0xc6, 0x4a, 0xd9, 0x4b, 0x69, 0xa2, 0xbd, 0x05, 0x41, 0xed, 0x5e, 0xfe, 0x05, 0x75, 0x3f, 0x87, - 0x56, 0x84, 0x0d, 0x30, 0x44, 0x79, 0x8e, 0x3b, 0x34, 0xb5, 0x4b, 0xce, 0x03, 0x46, 0x74, 0xde, 0x67, 0xb5, 0xdd, - 0xea, 0xcf, 0x97, 0x80, 0x6d, 0x9a, 0x1a, 0x9f, 0xc2, 0x30, 0x21, 0x26, 0x36, 0xb0, 0x55, 0x56, 0xda, 0x0d, 0x65, - 0xda, 0x49, 0x97, 0xcc, 0x6b, 0xe1, 0x34, 0xef, 0x31, 0xb6, 0x1c, 0xa9, 0xdc, 0xfd, 0x7e, 0x68, 0x7e, 0xb2, 0x9c, - 0x3e, 0xd7, 0x21, 0x9b, 0xbd, 0xf1, 0xa0, 0x39, 0xd1, 0xea, 0xaa, 0x8e, 0x7e, 0x40, 0x07, 0x60, 0xa6, 0x2d, 0x40, - 0xa6, 0x0b, 0x36, 0xed, 0x2b, 0x51, 0x71, 0x49, 0xc2, 0x52, 0x49, 0x60, 0x67, 0x37, 0x25, 0x3b, 0x9b, 0x80, 0x78, - 0x86, 0xbb, 0x9e, 0x16, 0x3b, 0x21, 0x4d, 0x78, 0x8b, 0xbd, 0x04, 0x44, 0x1d, 0xaa, 0xba, 0x84, 0x6c, 0x8c, 0xa1, - 0x8b, 0x7f, 0x51, 0x0a, 0x13, 0xd6, 0x32, 0xa9, 0x4a, 0x4c, 0x10, 0xa4, 0x72, 0xb7, 0x45, 0x60, 0x89, 0x82, 0x1d, - 0xc0, 0xde, 0xbb, 0x51, 0x37, 0xa3, 0xa6, 0xaa, 0x53, 0x2f, 0xc1, 0xc7, 0x69, 0xd6, 0x55, 0x90, 0x59, 0xd8, 0x55, - 0xb1, 0xe6, 0x81, 0x8e, 0x4d, 0xa5, 0x8c, 0x89, 0xbb, 0xb4, 0xc8, 0x10, 0x0f, 0x18, 0x63, 0xe9, 0x42, 0x20, 0xdf, - 0x6c, 0x77, 0xdc, 0xf4, 0x04, 0xa1, 0x9f, 0xb0, 0xa1, 0x04, 0x6e, 0x3a, 0xdb, 0x53, 0xd3, 0xcc, 0x07, 0x44, 0x1c, - 0x06, 0x14, 0x48, 0x36, 0x0e, 0x69, 0x8e, 0xf4, 0x05, 0x49, 0x13, 0x06, 0x86, 0x56, 0x3c, 0x27, 0xc8, 0x8a, 0x42, - 0xcf, 0xd6, 0x55, 0x1b, 0xe7, 0xca, 0x30, 0x47, 0x4b, 0x4e, 0x85, 0xcf, 0x09, 0x32, 0xb1, 0x7b, 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, 0x68, 0x18, 0x62, 0xb7, 0x3f, 0xc1, 0x7e, 0xad, 0x9d, 0xd6, 0x65, 0x8a, 0xe5, 0x65, 0x0a, - 0xd1, 0x5e, 0xc8, 0xfc, 0x46, 0x91, 0xe8, 0x4e, 0x11, 0x86, 0x84, 0x75, 0x94, 0x3d, 0x69, 0x53, 0x03, 0xe8, 0xa9, - 0x17, 0xf0, 0xbc, 0x73, 0x2d, 0xc3, 0x2e, 0xd2, 0xfd, 0x55, 0xc1, 0xa7, 0x74, 0x83, 0x20, 0x45, 0x6f, 0x52, 0x30, - 0xe7, 0xf5, 0x28, 0xa9, 0x37, 0xa7, 0x2d, 0x33, 0xaa, 0x8e, 0x8a, 0x90, 0x72, 0x82, 0xff, 0xe4, 0xa5, 0xd4, 0xc4, - 0x26, 0x4c, 0xf0, 0xc0, 0x87, 0x79, 0x86, 0x0d, 0xbc, 0xdd, 0xbe, 0x4b, 0xc3, 0xa4, 0xcd, 0x36, 0xa4, 0x20, 0xad, - 0x30, 0x71, 0x31, 0xa0, 0xb2, 0xd7, 0xb8, 0x5f, 0xb0, 0x9d, 0x34, 0x05, 0x0f, 0xc2, 0x46, 0x03, 0x13, 0xb7, 0xba, - 0xf8, 0x3a, 0x4c, 0x68, 0xb8, 0xa4, 0xda, 0xd9, 0x49, 0x4b, 0x9a, 0xdb, 0xeb, 0xf2, 0xc2, 0xf6, 0x41, 0xc7, 0x0e, - 0xeb, 0x1a, 0x1e, 0x68, 0x5e, 0xb3, 0x8b, 0x2b, 0xa6, 0x69, 0xa2, 0xb1, 0x1e, 0x52, 0x96, 0x1c, 0xeb, 0x7a, 0xba, - 0xc2, 0xd5, 0x32, 0xd3, 0xc0, 0xee, 0x12, 0x2f, 0xf4, 0x80, 0x87, 0x1d, 0xae, 0x48, 0x74, 0x81, 0xcd, 0x66, 0xab, - 0x9a, 0x4c, 0xf3, 0xfb, 0xb2, 0xe5, 0x26, 0x20, 0x9c, 0xa5, 0xbe, 0xb9, 0x4f, 0x8e, 0x35, 0x6d, 0xf3, 0x93, 0x00, - 0xc7, 0xdb, 0x2b, 0x20, 0xe9, 0x58, 0x82, 0x2e, 0xbe, 0xa5, 0x3f, 0x88, 0xd4, 0x4c, 0x05, 0xbd, 0x77, 0xbe, 0x48, - 0xdd, 0xfc, 0x02, 0x6c, 0xa3, 0x36, 0xc6, 0x34, 0x2b, 0x5b, 0x87, 0x89, 0xb2, 0xb0, 0x46, 0x16, 0x72, 0x09, 0x3e, - 0x98, 0xbb, 0x4d, 0x9d, 0x1e, 0x77, 0x10, 0x61, 0xbf, 0x8b, 0x1e, 0x8f, 0x30, 0x56, 0xac, 0x41, 0x62, 0x58, 0x85, - 0x35, 0x6d, 0x2e, 0x87, 0x28, 0xa7, 0x66, 0xc9, 0x44, 0x4b, 0xea, 0x53, 0x8a, 0x28, 0x05, 0x73, 0xe3, 0x69, 0xd9, - 0x30, 0x25, 0x44, 0xc8, 0x0a, 0xe9, 0x80, 0x6a, 0x2d, 0xb4, 0x54, 0x13, 0xf4, 0x3a, 0xf4, 0xb2, 0xd0, 0x98, 0x82, - 0xe8, 0x23, 0x32, 0xdc, 0x88, 0x23, 0xa3, 0xbb, 0x63, 0x14, 0x13, 0x08, 0x55, 0xed, 0xe5, 0x85, 0xd5, 0xa7, 0x65, - 0x5b, 0x1d, 0xc4, 0x15, 0x22, 0xdf, 0x77, 0x13, 0xd4, 0x18, 0x05, 0x6d, 0x4e, 0x37, 0xfa, 0x6b, 0x11, 0xfa, 0x76, - 0xe1, 0xd8, 0x8d, 0x82, 0x48, 0x88, 0xc0, 0xea, 0x35, 0x15, 0x03, 0xb2, 0xce, 0x63, 0x17, 0xa1, 0x49, 0x77, 0x0b, - 0x51, 0xde, 0xa8, 0xac, 0x3f, 0xae, 0x43, 0xb2, 0xdd, 0x62, 0x59, 0xe0, 0xcb, 0x7e, 0xba, 0xbe, 0x07, 0xf2, 0xfb, - 0xcd, 0xfa, 0xb3, 0x90, 0xdf, 0xaf, 0xb3, 0x2f, 0x81, 0xfc, 0x7e, 0xb3, 0xfe, 0x9f, 0x86, 0xfc, 0x3e, 0x5d, 0x7b, - 0x90, 0xdf, 0x6a, 0x30, 0x7e, 0x2f, 0x58, 0x70, 0xf2, 0x36, 0xa0, 0x2f, 0x24, 0x0b, 0x4e, 0x5e, 0xbd, 0xf2, 0x8d, - 0x40, 0x84, 0x46, 0xae, 0x37, 0xb2, 0x60, 0xc4, 0x6d, 0x81, 0x57, 0xa8, 0x75, 0xf2, 0x81, 0x8a, 0x32, 0x00, 0x5e, - 0x2f, 0xff, 0x91, 0x55, 0xcb, 0x30, 0xd8, 0x0f, 0xc8, 0xcc, 0x41, 0x82, 0x0e, 0x27, 0x70, 0x7b, 0x43, 0x23, 0xcb, - 0xea, 0x8b, 0xe0, 0xc3, 0x47, 0xa3, 0x51, 0x5c, 0x5c, 0xe2, 0xa5, 0xce, 0x6c, 0x24, 0x04, 0x3c, 0xce, 0x78, 0x69, - 0x43, 0x44, 0x2c, 0xe3, 0xf2, 0x4c, 0xc7, 0x66, 0x29, 0xed, 0x56, 0x84, 0x88, 0xf3, 0x67, 0x80, 0x53, 0x6f, 0xf7, - 0x66, 0x8c, 0xfd, 0x50, 0x1c, 0xb1, 0x0e, 0x20, 0xfb, 0x7c, 0xad, 0xdf, 0x9d, 0xc7, 0x25, 0x7f, 0x17, 0x57, 0x4b, - 0x06, 0xbd, 0x84, 0xbb, 0x88, 0xe0, 0x49, 0xe5, 0xb1, 0x4d, 0x0a, 0xa8, 0x3c, 0xd3, 0x40, 0xe5, 0x1d, 0xef, 0x69, - 0x68, 0x87, 0x45, 0xfb, 0x00, 0x1b, 0xe9, 0x72, 0x06, 0x46, 0x8b, 0x2f, 0xaf, 0xb9, 0xa8, 0x7e, 0x06, 0x3c, 0x75, - 0xc1, 0x0b, 0xb8, 0x25, 0x20, 0x17, 0xdb, 0x70, 0x42, 0xa0, 0xc2, 0xf7, 0xec, 0x50, 0x51, 0x63, 0x8c, 0x68, 0xa2, - 0xd1, 0x6f, 0xbc, 0x09, 0xa1, 0x77, 0x27, 0xe8, 0x8a, 0x30, 0x12, 0xde, 0x5f, 0x6b, 0x7e, 0x96, 0x81, 0xf9, 0xbc, - 0x00, 0x28, 0x0d, 0x84, 0x43, 0x65, 0x4a, 0x6e, 0x81, 0x09, 0x1b, 0x63, 0xae, 0x94, 0xa5, 0x1e, 0x52, 0x29, 0x55, - 0x70, 0xba, 0x82, 0xa6, 0x12, 0x70, 0xb8, 0x23, 0x09, 0x60, 0xa6, 0xb6, 0x30, 0x88, 0x6e, 0x9b, 0xd2, 0x2c, 0x8d, - 0x9c, 0x22, 0xcd, 0xe1, 0x93, 0x52, 0x05, 0x3a, 0x7d, 0x96, 0xc4, 0x15, 0xbf, 0x94, 0x05, 0x84, 0xc2, 0x6d, 0xa5, - 0x50, 0xa4, 0xdf, 0x67, 0x62, 0x7d, 0xc5, 0x8b, 0x2c, 0x39, 0x5b, 0x66, 0x65, 0x05, 0xf9, 0xe6, 0xfa, 0xf4, 0x5b, - 0xd4, 0xd3, 0x02, 0xe7, 0x4d, 0x4d, 0x0a, 0x33, 0xf3, 0x78, 0xac, 0x76, 0x3a, 0xa8, 0x57, 0xbd, 0xd7, 0x06, 0xfb, - 0xbd, 0x39, 0xd1, 0xe3, 0xd6, 0x7a, 0xb0, 0x9a, 0xd4, 0x66, 0xaa, 0x82, 0x38, 0x02, 0xea, 0xc0, 0x8e, 0xe2, 0x76, - 0x33, 0x0f, 0x93, 0x76, 0xca, 0x76, 0xbb, 0x93, 0x09, 0x0e, 0xee, 0x56, 0x12, 0xdc, 0x12, 0x61, 0xc5, 0x1f, 0x2a, - 0x08, 0x96, 0xd9, 0x70, 0x12, 0x99, 0x70, 0xac, 0x05, 0xff, 0x6b, 0xcd, 0x0d, 0x16, 0x7c, 0xa8, 0x1d, 0xf2, 0x9c, - 0xe4, 0x5c, 0x0f, 0x80, 0x67, 0xc3, 0xa6, 0x67, 0x67, 0x0e, 0xf6, 0x53, 0x7e, 0xcb, 0x21, 0x60, 0x4b, 0xe7, 0x28, - 0x2e, 0xa6, 0xda, 0x9a, 0xd7, 0xb0, 0x12, 0xf4, 0xcb, 0xbe, 0xd3, 0x38, 0xb5, 0x09, 0x0f, 0x87, 0xcf, 0xc6, 0xa4, - 0xd6, 0xa6, 0xe5, 0x38, 0xcf, 0xf6, 0xb7, 0x5a, 0x0b, 0xee, 0xd9, 0xae, 0x07, 0xda, 0x74, 0x0a, 0x68, 0xd7, 0x48, - 0xc5, 0x3d, 0xdd, 0xaf, 0x49, 0xed, 0xe6, 0xd5, 0x0a, 0x7a, 0xfe, 0x50, 0x87, 0xcb, 0xd9, 0xa3, 0x4d, 0xa6, 0xab, - 0xac, 0xff, 0xc8, 0x6c, 0x58, 0xb8, 0xc6, 0x46, 0xad, 0xf5, 0x8c, 0xfb, 0xa8, 0x6c, 0x1d, 0xd9, 0xf4, 0x0c, 0xb1, - 0xac, 0x73, 0xb7, 0x8f, 0xd4, 0x23, 0x57, 0x51, 0xb2, 0xba, 0xb3, 0xf0, 0x5b, 0x9e, 0x84, 0x5d, 0x0d, 0x53, 0x8c, - 0xb8, 0xe9, 0x02, 0x02, 0x55, 0x82, 0xf8, 0x3d, 0xfc, 0xe3, 0xd1, 0xa6, 0x49, 0x3d, 0xea, 0x7d, 0xef, 0x33, 0xfc, - 0x9d, 0xa5, 0xf0, 0xb7, 0xaa, 0xff, 0xa0, 0x9b, 0x2b, 0x5e, 0x2d, 0x65, 0x1a, 0x05, 0xef, 0x4e, 0x4e, 0x3f, 0x04, - 0x1a, 0x00, 0x1d, 0xaf, 0x01, 0x46, 0xf1, 0x6b, 0xa0, 0x96, 0x40, 0x11, 0x92, 0xcb, 0x4b, 0xc4, 0x00, 0xd4, 0x20, - 0xf2, 0xa7, 0x4b, 0x79, 0x73, 0x9c, 0xe7, 0x3e, 0xaf, 0x6a, 0xe8, 0x9b, 0x66, 0xdf, 0x1a, 0xc4, 0x21, 0x04, 0x91, - 0xdb, 0x28, 0x2b, 0xcf, 0xb4, 0x92, 0x24, 0x3d, 0x3b, 0xbf, 0x3b, 0xd3, 0x82, 0x18, 0x0b, 0xc2, 0xf8, 0xfc, 0x8f, - 0xc3, 0x34, 0xbb, 0xde, 0x43, 0x22, 0xcc, 0x02, 0xb0, 0x60, 0xcf, 0xf9, 0xf9, 0xba, 0xaa, 0xa4, 0x18, 0x16, 0xf2, - 0x26, 0x38, 0x3a, 0x54, 0x0f, 0x26, 0x43, 0xac, 0x1e, 0x83, 0xbd, 0xff, 0x4a, 0xf2, 0x2c, 0xf9, 0xc8, 0x82, 0x47, - 0x9b, 0x8c, 0x1d, 0xb5, 0x48, 0xed, 0xb8, 0x0e, 0x8e, 0xa0, 0xad, 0x7b, 0xc7, 0x79, 0x7e, 0xb8, 0xaf, 0xbe, 0x38, - 0x3a, 0xdc, 0x4f, 0xb3, 0xeb, 0x23, 0x0f, 0x0f, 0xdf, 0x99, 0xb7, 0x22, 0xf2, 0x98, 0xbb, 0xbe, 0x82, 0x1f, 0x6b, - 0xc2, 0x43, 0x7b, 0xe0, 0x83, 0xd0, 0xc4, 0x44, 0x13, 0x41, 0x41, 0x4b, 0x18, 0xc3, 0xf1, 0xb6, 0xdd, 0x86, 0xd6, - 0xf6, 0x26, 0xf1, 0x80, 0x69, 0x0a, 0x60, 0x08, 0x30, 0x0b, 0x4d, 0x08, 0x4d, 0x6a, 0x12, 0x1a, 0xf8, 0x9c, 0x98, - 0xd0, 0xa2, 0xa6, 0x40, 0xf1, 0xdf, 0xc4, 0x2b, 0x23, 0x6b, 0xd2, 0x77, 0x77, 0xd3, 0xfa, 0x59, 0x63, 0x1c, 0xa3, - 0xf6, 0xa8, 0x1a, 0x40, 0xab, 0x5e, 0x79, 0xdf, 0xc0, 0x82, 0x78, 0x31, 0xac, 0x68, 0xd0, 0x22, 0x15, 0x20, 0x1e, - 0xf4, 0xa5, 0x5a, 0x9c, 0x86, 0xf3, 0x92, 0xca, 0x05, 0x61, 0x47, 0xe1, 0x06, 0xb9, 0xdb, 0x52, 0x11, 0xcb, 0x48, - 0xd6, 0x0e, 0x5d, 0x52, 0xcd, 0xce, 0xd1, 0xa3, 0x8d, 0x40, 0x40, 0xc3, 0x92, 0x1d, 0x35, 0xe7, 0xab, 0x8a, 0xcf, - 0x87, 0x4b, 0x0e, 0x6e, 0x30, 0xc1, 0xde, 0x7f, 0xa5, 0xe7, 0xb9, 0x9d, 0x14, 0xb5, 0x22, 0x97, 0xb1, 0x48, 0x73, - 0xfe, 0x21, 0x3e, 0xff, 0x01, 0xf3, 0xbc, 0x38, 0xcf, 0x9f, 0x43, 0x86, 0x3a, 0x38, 0x7a, 0xb4, 0x49, 0xaa, 0xd1, - 0xcb, 0xb7, 0x1f, 0x5e, 0x7f, 0xf8, 0xe7, 0xd9, 0xf3, 0xe3, 0x0f, 0x2f, 0xbf, 0x3f, 0x79, 0xff, 0xfa, 0xe5, 0xe9, - 0xdc, 0xfa, 0x9d, 0x2a, 0x38, 0x33, 0xb2, 0xd8, 0x6e, 0x5d, 0xbe, 0x5f, 0xdf, 0xbe, 0x78, 0xf9, 0xea, 0xf5, 0xdb, - 0x97, 0x2f, 0x6a, 0x35, 0x97, 0xed, 0x86, 0xc0, 0x0e, 0x8d, 0x33, 0xc1, 0x0b, 0x28, 0x5e, 0x07, 0x55, 0xc4, 0x66, - 0x6b, 0x14, 0xbe, 0x66, 0xd3, 0x75, 0xc0, 0x02, 0x58, 0x64, 0x7b, 0x7a, 0xb3, 0x40, 0xc3, 0xa5, 0xd9, 0x38, 0xfe, - 0x12, 0xf3, 0x7b, 0xf3, 0x12, 0xbf, 0x7b, 0x2f, 0x6f, 0x4c, 0x57, 0xf4, 0x08, 0x29, 0x80, 0xad, 0xd9, 0xf3, 0x3f, - 0x0e, 0x7d, 0xa1, 0x16, 0xde, 0xfc, 0x55, 0xb9, 0xf0, 0xab, 0x0e, 0xf6, 0xb4, 0x81, 0x5d, 0x00, 0xf1, 0x21, 0x82, - 0xa3, 0xc3, 0x7d, 0x3f, 0xf7, 0xd1, 0x1f, 0xd1, 0xcf, 0x5e, 0xe7, 0xb0, 0x54, 0x18, 0x87, 0x66, 0xda, 0xce, 0x21, - 0x04, 0x11, 0x8c, 0xdc, 0x31, 0xa5, 0x56, 0x90, 0x21, 0x57, 0x92, 0x44, 0x76, 0x12, 0x95, 0xe1, 0x88, 0x29, 0xed, - 0x0f, 0xfd, 0xd7, 0xf5, 0x19, 0x2f, 0xe2, 0x5c, 0x94, 0xb2, 0x08, 0xa0, 0x1f, 0xed, 0xb0, 0x0e, 0x7b, 0x5e, 0xf8, - 0x14, 0xec, 0x51, 0x27, 0x79, 0x87, 0x11, 0xd9, 0x6f, 0x7f, 0xea, 0x75, 0xec, 0x0f, 0xe2, 0x7e, 0xec, 0xe9, 0xce, - 0xb4, 0xc8, 0x8b, 0x6d, 0xe0, 0xfd, 0xe1, 0x37, 0xe6, 0x27, 0x19, 0xfd, 0x87, 0xa4, 0x97, 0x31, 0xbd, 0x8a, 0xe9, - 0xa9, 0x58, 0xd4, 0x9d, 0xb3, 0x63, 0x43, 0xbb, 0x50, 0x3e, 0x0d, 0x01, 0x20, 0x42, 0xb3, 0xed, 0x9a, 0x99, 0xcd, - 0x46, 0x5a, 0xa5, 0xf5, 0x21, 0x2e, 0x2e, 0xb9, 0x89, 0xa8, 0x62, 0xde, 0x56, 0x7a, 0x54, 0x88, 0x37, 0x2c, 0x80, - 0x9e, 0xd2, 0xd3, 0x9a, 0xff, 0x6c, 0x94, 0x54, 0x45, 0xfe, 0x13, 0xbf, 0x03, 0xe6, 0xaa, 0xac, 0xe4, 0x0a, 0x58, - 0xea, 0xf8, 0x52, 0x8b, 0x48, 0x68, 0xc8, 0xbf, 0xac, 0xba, 0xed, 0x96, 0x8f, 0x70, 0x49, 0x02, 0x5f, 0x36, 0xaa, - 0xe4, 0xe5, 0x65, 0xce, 0xc3, 0xc0, 0xc4, 0xf8, 0x08, 0xa8, 0xad, 0x66, 0xf6, 0x7f, 0x9a, 0x7b, 0xfa, 0xe5, 0xb6, - 0x6d, 0xe4, 0xff, 0xbf, 0xa7, 0x60, 0x98, 0x5c, 0x2a, 0x26, 0x24, 0x4d, 0x4a, 0x96, 0xed, 0x48, 0x96, 0xdd, 0x36, - 0x49, 0xe7, 0xdc, 0x71, 0x9b, 0x4e, 0xe2, 0xcb, 0xdc, 0xd5, 0xf5, 0x58, 0x14, 0x05, 0x49, 0xbc, 0x50, 0xa4, 0x86, - 0xa4, 0x6c, 0xb9, 0x2a, 0xef, 0x59, 0xfa, 0x2c, 0xf7, 0x64, 0xbf, 0xd9, 0x5d, 0x00, 0x04, 0x3f, 0xf4, 0xe1, 0x26, - 0xbd, 0xfb, 0x4d, 0xcf, 0x17, 0x11, 0x04, 0x40, 0x60, 0x01, 0x2c, 0xf6, 0x7b, 0x9f, 0x38, 0x22, 0xb0, 0xa6, 0x91, - 0x6f, 0x3a, 0x5a, 0x62, 0xc6, 0x4c, 0x46, 0x9e, 0x23, 0x02, 0x13, 0x45, 0xa8, 0x77, 0xa8, 0x85, 0xe0, 0xeb, 0x52, - 0x1c, 0x5d, 0x6b, 0x1c, 0x2f, 0x47, 0x21, 0xb3, 0x70, 0xbb, 0xc3, 0x27, 0xd7, 0xa3, 0xe5, 0x68, 0x04, 0xc9, 0x54, - 0x9e, 0x38, 0x26, 0x84, 0x87, 0x89, 0x53, 0x64, 0xdb, 0x72, 0xa3, 0x0f, 0x93, 0xb2, 0xb3, 0xea, 0xf0, 0xc1, 0xa4, - 0x03, 0x24, 0x32, 0xf4, 0x81, 0x0c, 0x58, 0xb4, 0x86, 0x53, 0x3b, 0xd0, 0x3f, 0xc0, 0xee, 0x4b, 0xf5, 0x7e, 0xd3, - 0xd1, 0x1f, 0x5c, 0xeb, 0x1f, 0x10, 0xc6, 0x98, 0x64, 0xf8, 0x35, 0xed, 0x5e, 0xdd, 0xd4, 0x49, 0x37, 0xbd, 0xc4, - 0x74, 0x03, 0x20, 0x9b, 0x7d, 0x13, 0x78, 0xd3, 0x28, 0x4e, 0xb3, 0xc0, 0xd7, 0x6f, 0xfa, 0x17, 0x41, 0xeb, 0x7a, - 0x9e, 0xb5, 0x8c, 0x1b, 0xd3, 0xcf, 0xd4, 0x4c, 0x25, 0x02, 0x61, 0x62, 0xa2, 0x92, 0x4d, 0x95, 0xd4, 0x13, 0xb4, - 0xb5, 0xa2, 0x40, 0xcd, 0x58, 0xc9, 0xcf, 0x06, 0x50, 0xaf, 0x92, 0xf6, 0x04, 0xf3, 0x37, 0xe9, 0xd8, 0xd2, 0xe8, - 0x13, 0x43, 0xf1, 0x7a, 0xb9, 0xc6, 0xab, 0x3c, 0x2b, 0x6e, 0x4b, 0x0c, 0xd5, 0x2b, 0xfc, 0x5b, 0xe8, 0xf9, 0x89, - 0x6a, 0x9b, 0x59, 0xba, 0x77, 0x87, 0xdf, 0x94, 0xe9, 0x02, 0xb8, 0xbf, 0xc1, 0x30, 0x22, 0x8a, 0x33, 0x0d, 0xe2, - 0xcf, 0xc0, 0x17, 0x87, 0x55, 0x5b, 0x2e, 0xde, 0x6b, 0xcb, 0xc8, 0x39, 0x32, 0xf8, 0x16, 0x2f, 0xbf, 0x16, 0x8f, - 0x42, 0x56, 0x0a, 0x34, 0x41, 0x34, 0x7d, 0x04, 0x0b, 0x98, 0xc5, 0x97, 0xf1, 0x7d, 0x55, 0x5d, 0xf1, 0x7a, 0xb8, - 0xfb, 0xee, 0xc5, 0x0b, 0x10, 0xf6, 0x9b, 0x48, 0xbe, 0xd7, 0xe2, 0xf9, 0x43, 0x05, 0xa1, 0x53, 0x39, 0x53, 0x68, - 0x9f, 0x21, 0x68, 0x98, 0x0c, 0xcc, 0xb9, 0xf0, 0x2e, 0x00, 0x94, 0xc4, 0xaf, 0xe9, 0x61, 0x7e, 0x2b, 0x32, 0x1c, - 0x8b, 0xfc, 0xc2, 0xca, 0xe5, 0x0c, 0xd8, 0x35, 0x5a, 0x2c, 0x33, 0x8c, 0x88, 0x0b, 0x03, 0x60, 0xb9, 0xae, 0x61, - 0x84, 0x4d, 0xc0, 0xd2, 0x05, 0x99, 0x98, 0xeb, 0x5a, 0x30, 0xae, 0x97, 0x71, 0xa2, 0x17, 0x90, 0x17, 0xe2, 0x77, - 0x94, 0x27, 0xc1, 0x63, 0xc2, 0xa7, 0xe1, 0x9b, 0x45, 0x38, 0xf9, 0x96, 0x8f, 0x7a, 0x97, 0x06, 0xcc, 0xe0, 0x53, - 0x3f, 0xfd, 0x56, 0xd8, 0x38, 0x59, 0x88, 0x92, 0x59, 0x9a, 0xe6, 0xf0, 0xd9, 0x3a, 0xca, 0xcf, 0x9f, 0xad, 0xd3, - 0x7c, 0xf0, 0x6c, 0xed, 0x01, 0x25, 0x97, 0xeb, 0x30, 0xd1, 0xc2, 0x9f, 0xa6, 0x98, 0x1e, 0x6c, 0x2a, 0x2a, 0xd7, - 0x50, 0xa1, 0x3e, 0xe0, 0x6a, 0xf3, 0x45, 0x12, 0xcc, 0xbd, 0xe4, 0x81, 0xb4, 0xec, 0xa6, 0xaa, 0x8a, 0x37, 0x74, - 0x8d, 0xf0, 0x3a, 0xcd, 0x97, 0x50, 0xbc, 0xae, 0x7d, 0x2d, 0xcb, 0x18, 0x9f, 0x9c, 0x54, 0x35, 0xc2, 0xb7, 0x6e, - 0xf5, 0x97, 0xcc, 0x1e, 0xb3, 0xcc, 0x0b, 0x42, 0x6a, 0xd2, 0x17, 0x39, 0xe4, 0x6b, 0xb3, 0x49, 0xcb, 0xb3, 0x89, - 0xca, 0xdb, 0x05, 0x27, 0x43, 0x18, 0x9f, 0xc6, 0x8d, 0x33, 0xc3, 0xdc, 0x52, 0xcd, 0x0b, 0x48, 0xef, 0xfe, 0xab, - 0xd0, 0x67, 0x00, 0xfd, 0x08, 0xa0, 0xcf, 0x22, 0x3f, 0x1e, 0xb3, 0xbf, 0xbf, 0xbf, 0x90, 0xc9, 0xac, 0x40, 0x2e, - 0x33, 0xe4, 0xfb, 0x30, 0x45, 0x72, 0x21, 0x41, 0x52, 0x81, 0xd2, 0x4e, 0x69, 0x72, 0xc7, 0x24, 0xb9, 0xae, 0x9d, - 0xd3, 0xd8, 0xd9, 0x98, 0x46, 0x3d, 0x88, 0xb1, 0x55, 0x92, 0x9f, 0x1e, 0x50, 0x6d, 0xba, 0xdc, 0xa8, 0x12, 0x80, - 0x21, 0x81, 0x19, 0x16, 0x50, 0x80, 0xbc, 0x9b, 0x03, 0xb7, 0xe0, 0x1f, 0xec, 0x39, 0x4a, 0xbf, 0xdd, 0xf3, 0x32, - 0x65, 0x82, 0xad, 0xf4, 0xb3, 0x53, 0xcc, 0xa4, 0x05, 0xd7, 0x33, 0xc4, 0xde, 0x38, 0x3d, 0xa0, 0x47, 0xad, 0x72, - 0x00, 0x8a, 0x4e, 0x04, 0x27, 0xd7, 0xe3, 0x1d, 0x3c, 0xea, 0x64, 0x40, 0xe2, 0x76, 0x28, 0xf5, 0x72, 0x5d, 0x9b, - 0x73, 0x4a, 0x88, 0x07, 0xf9, 0x81, 0x08, 0x00, 0x0e, 0x1c, 0x55, 0x5d, 0x9b, 0x7b, 0x2b, 0x9c, 0xb9, 0x78, 0xe3, - 0xad, 0x5a, 0x2e, 0x7f, 0x55, 0x1c, 0xad, 0xb4, 0x7c, 0xb4, 0x7c, 0xbe, 0xb8, 0x60, 0xde, 0x2f, 0xa4, 0xb6, 0xad, - 0x19, 0xaa, 0x4d, 0x1b, 0x16, 0x77, 0x26, 0x16, 0x77, 0xbc, 0x61, 0x71, 0xc7, 0x5b, 0x16, 0x37, 0xe4, 0x0b, 0xa9, - 0x49, 0xd0, 0x25, 0xe8, 0xb2, 0x25, 0x81, 0xc7, 0xe9, 0x8a, 0x1e, 0x3f, 0x67, 0x08, 0x27, 0x2b, 0x0d, 0xc1, 0x64, - 0x69, 0x03, 0xac, 0x9a, 0xe0, 0xa2, 0x00, 0xa2, 0x3e, 0x71, 0x79, 0xea, 0xc4, 0xbc, 0x21, 0x33, 0x66, 0x2b, 0xac, - 0xce, 0x17, 0x76, 0x29, 0x65, 0xfd, 0x6e, 0xcd, 0x36, 0xcc, 0x74, 0xb6, 0x65, 0xa6, 0x7e, 0xe9, 0xe8, 0xf2, 0x69, - 0xd3, 0x21, 0x54, 0x27, 0x05, 0x7b, 0x10, 0xcc, 0x38, 0x71, 0xcb, 0x94, 0xf7, 0xe1, 0x66, 0x94, 0xaa, 0xec, 0xa8, - 0x85, 0x97, 0xa6, 0xf7, 0x71, 0x02, 0x7a, 0x10, 0xe8, 0xe6, 0x71, 0x5b, 0x6a, 0x1e, 0x44, 0x3c, 0xc4, 0xca, 0xc6, - 0xcd, 0x54, 0xbc, 0x57, 0xb7, 0x54, 0xbb, 0xdb, 0xa5, 0x1a, 0x0b, 0x2f, 0xcb, 0x58, 0x82, 0x40, 0xf7, 0x20, 0x16, - 0x77, 0xae, 0x6b, 0xff, 0x0f, 0x76, 0x59, 0x03, 0x0a, 0x09, 0x8d, 0x02, 0xa9, 0x23, 0x82, 0x5e, 0x00, 0x25, 0x95, - 0x88, 0x6b, 0x57, 0x89, 0xd6, 0x96, 0x48, 0xb8, 0xff, 0x88, 0xa7, 0xb5, 0x95, 0x28, 0xfe, 0x44, 0xee, 0x91, 0x61, - 0x2f, 0xbc, 0xf1, 0x07, 0xd0, 0xb6, 0xb5, 0xda, 0x26, 0x58, 0xce, 0xaa, 0xb1, 0xd9, 0x12, 0x22, 0xed, 0xfc, 0x02, - 0x47, 0x22, 0x92, 0xe4, 0x76, 0x49, 0xe0, 0xd2, 0xe8, 0x59, 0x93, 0x9b, 0x75, 0x3b, 0x3f, 0x98, 0x06, 0x46, 0x0d, - 0x69, 0x02, 0x66, 0x0b, 0x07, 0x67, 0x92, 0xc3, 0x0a, 0x4d, 0xf7, 0xc8, 0x00, 0x71, 0xec, 0x35, 0x24, 0x19, 0x75, - 0x04, 0xfb, 0x3a, 0x4c, 0xe0, 0x8e, 0xba, 0x76, 0x6e, 0xf2, 0xe7, 0x53, 0xfc, 0xe5, 0xde, 0xe4, 0xcf, 0x47, 0xf8, - 0xab, 0x7d, 0x83, 0xe9, 0xe4, 0x1a, 0xd8, 0x76, 0x65, 0xce, 0xfa, 0x59, 0x69, 0x3b, 0x91, 0x51, 0xd8, 0x23, 0x76, - 0x0d, 0x5f, 0xe0, 0xa7, 0xcf, 0xd6, 0x29, 0xb8, 0x41, 0xaa, 0x73, 0x88, 0xec, 0xc4, 0xc8, 0x1b, 0xcb, 0xa7, 0x1b, - 0xca, 0x47, 0xc6, 0x7f, 0xf9, 0x9a, 0xc7, 0x5d, 0x12, 0x17, 0x57, 0x4a, 0x59, 0xe8, 0x70, 0x3b, 0x0a, 0x22, 0x2f, - 0x79, 0xb8, 0x25, 0x66, 0xa2, 0x25, 0x28, 0x75, 0x29, 0x4c, 0x21, 0x62, 0xb2, 0xac, 0x83, 0xca, 0x14, 0xa9, 0xeb, - 0x03, 0xbf, 0xe7, 0x07, 0xff, 0x48, 0x14, 0x22, 0xad, 0xc4, 0x6e, 0xf2, 0x05, 0x29, 0x7d, 0xe8, 0xf6, 0xd9, 0xba, - 0xc5, 0xea, 0xdd, 0x54, 0x66, 0x5b, 0xa1, 0x02, 0x61, 0x79, 0x90, 0x75, 0x9d, 0x8f, 0x83, 0x1e, 0x2a, 0x99, 0x46, - 0xf1, 0xca, 0x7a, 0xb6, 0xce, 0xce, 0xf5, 0xb9, 0x97, 0x7c, 0x62, 0x63, 0xcb, 0x0f, 0x12, 0x3f, 0x64, 0x7a, 0x4f, - 0x1f, 0x85, 0x5e, 0xf4, 0x89, 0x3f, 0x5a, 0xf1, 0x32, 0x43, 0xb5, 0xf1, 0x4e, 0x4e, 0x57, 0xc0, 0x84, 0x04, 0x74, - 0x48, 0x9a, 0x36, 0x40, 0x41, 0x7b, 0x2d, 0xc5, 0x5b, 0x05, 0x59, 0x58, 0xd4, 0x32, 0xc1, 0xea, 0x11, 0x34, 0xd9, - 0xe0, 0x46, 0x6a, 0xea, 0xb8, 0x5e, 0xba, 0xa9, 0x4e, 0x95, 0x44, 0x93, 0x32, 0x0f, 0xe2, 0x2d, 0xf6, 0xf0, 0xc7, - 0x3f, 0x47, 0x19, 0xaa, 0xf7, 0xff, 0x1c, 0x27, 0xf1, 0x36, 0x7f, 0x50, 0x6d, 0xec, 0xa5, 0xe9, 0x72, 0xce, 0xc6, - 0xa4, 0x31, 0x3b, 0x2f, 0x86, 0x52, 0x26, 0xe5, 0xd5, 0xe1, 0xfc, 0xb2, 0x6c, 0x1f, 0x1f, 0xbe, 0x06, 0x4d, 0x3e, - 0x90, 0x74, 0xf1, 0x64, 0xa2, 0x17, 0x4c, 0xf5, 0x8e, 0x66, 0xee, 0xe1, 0x2f, 0xcb, 0xef, 0xde, 0x3a, 0xdf, 0xc9, - 0xc6, 0x91, 0x6e, 0xe4, 0x43, 0xa1, 0x96, 0xe4, 0x94, 0xa9, 0x32, 0x5e, 0x31, 0xa3, 0x89, 0x17, 0x6d, 0x9e, 0xce, - 0x75, 0x69, 0x97, 0x2d, 0x18, 0x1b, 0x83, 0xc5, 0xaa, 0x59, 0x2b, 0xbd, 0x0d, 0xd9, 0x1d, 0x93, 0x2a, 0xcf, 0xfa, - 0xc7, 0x1a, 0x5a, 0x60, 0x4c, 0x36, 0xae, 0x4a, 0xe5, 0x74, 0x95, 0x32, 0xa5, 0x21, 0xce, 0x81, 0xcf, 0x5c, 0xdd, - 0xe5, 0x95, 0x5d, 0x3d, 0x34, 0x75, 0x65, 0x00, 0x1b, 0x47, 0x76, 0xbe, 0xa1, 0xbc, 0x87, 0x09, 0x99, 0x9b, 0xc7, - 0x66, 0xba, 0x46, 0x0f, 0x62, 0x58, 0x73, 0x38, 0x85, 0xb0, 0xf9, 0x5b, 0x85, 0xfc, 0x61, 0x13, 0xc4, 0x9a, 0xa4, - 0x52, 0x3a, 0x89, 0x3b, 0x84, 0x15, 0x20, 0x9a, 0xc3, 0x0a, 0xc1, 0x4f, 0xe3, 0xda, 0x68, 0xe5, 0x99, 0x8f, 0x30, - 0xd1, 0x69, 0xc4, 0xd2, 0x74, 0x23, 0xc0, 0xe4, 0xa2, 0x9b, 0x7a, 0x51, 0xbb, 0x0c, 0x8f, 0xa2, 0xdc, 0x74, 0x4c, - 0xb8, 0x94, 0x71, 0x82, 0xd5, 0x6f, 0x21, 0x86, 0xbf, 0x9d, 0x73, 0x3b, 0x8e, 0x64, 0x3a, 0xd2, 0xb9, 0x8e, 0x7d, - 0xd3, 0xfb, 0x7b, 0x9d, 0x0f, 0xaa, 0x74, 0x53, 0x36, 0x0e, 0xad, 0x55, 0xc2, 0x7e, 0x35, 0xf9, 0x0c, 0x76, 0x20, - 0xc6, 0x54, 0x41, 0x71, 0x6c, 0x32, 0x61, 0x7e, 0x96, 0x1a, 0x42, 0x5a, 0x23, 0xa3, 0xaa, 0x82, 0x37, 0xcd, 0x93, - 0x81, 0xfe, 0x23, 0xf8, 0x96, 0x8b, 0xe0, 0x43, 0x7c, 0x40, 0x82, 0x6b, 0x69, 0x06, 0x13, 0xf5, 0x58, 0x06, 0x11, - 0xff, 0x0a, 0x24, 0xcd, 0x6e, 0x28, 0xc7, 0xa1, 0xf1, 0x2b, 0xa0, 0xd8, 0x17, 0xb1, 0xb4, 0xf6, 0xd8, 0x8e, 0x80, - 0xb6, 0x1d, 0xdf, 0xb5, 0xfb, 0x5d, 0xd7, 0x75, 0x72, 0xdd, 0x04, 0x9f, 0xa6, 0x4f, 0xfb, 0x1e, 0x7a, 0x6c, 0xd5, - 0x81, 0x56, 0xcb, 0xe8, 0x31, 0xed, 0xda, 0xee, 0x2b, 0x57, 0x37, 0xc9, 0x94, 0x4c, 0xc1, 0x6d, 0x7e, 0x7c, 0xc7, - 0x92, 0xcf, 0x9e, 0x4a, 0xb9, 0xf3, 0xfd, 0xc6, 0x73, 0xe4, 0x3a, 0x80, 0x84, 0xb3, 0x78, 0xf1, 0x88, 0x29, 0x74, - 0x74, 0x53, 0xf7, 0xc3, 0x38, 0x65, 0xea, 0x1c, 0x48, 0xea, 0xf0, 0x99, 0x93, 0xf8, 0xe9, 0xfd, 0xdb, 0x0f, 0x1f, - 0x74, 0x13, 0x33, 0x64, 0xa6, 0x6a, 0xef, 0x7c, 0x43, 0xed, 0xc0, 0xfe, 0x8d, 0xfb, 0x8e, 0x6e, 0x18, 0x62, 0x2b, - 0xcb, 0x7b, 0x8e, 0xca, 0x6a, 0x5b, 0x8e, 0xdf, 0x3c, 0xfc, 0xcb, 0xc4, 0x0b, 0xee, 0x35, 0xaf, 0x06, 0xdc, 0xb0, - 0xfd, 0x7a, 0x2b, 0x95, 0xcc, 0x83, 0xe8, 0xb6, 0xa1, 0xd4, 0x5b, 0x35, 0x94, 0x02, 0x33, 0x55, 0xc3, 0x55, 0xcb, - 0x78, 0xae, 0xdc, 0xce, 0x90, 0xe0, 0x78, 0x17, 0xb8, 0x14, 0x8e, 0xe6, 0x33, 0x06, 0xcd, 0x23, 0x9c, 0x57, 0x47, - 0xdd, 0x50, 0xcc, 0xd9, 0x10, 0x09, 0x5b, 0x3f, 0x04, 0x43, 0x38, 0xa6, 0xaa, 0xc1, 0xca, 0x94, 0x9b, 0x34, 0x63, - 0x55, 0x3a, 0x21, 0x0a, 0xf3, 0x36, 0x63, 0xf3, 0x05, 0x4b, 0xbc, 0x6c, 0x99, 0xb0, 0xdb, 0x30, 0xbe, 0x7f, 0x52, - 0x98, 0x99, 0xef, 0xa8, 0x3c, 0x0b, 0xa6, 0x33, 0x59, 0xfb, 0xbc, 0xc5, 0x06, 0x72, 0x01, 0xb7, 0x7e, 0x20, 0xff, - 0xcf, 0xef, 0xb6, 0xfd, 0x9f, 0xdf, 0x77, 0x56, 0x85, 0xee, 0xf3, 0xa1, 0x99, 0x0d, 0xf6, 0xd8, 0x17, 0xcd, 0x5f, - 0x2a, 0xc3, 0xbc, 0xb9, 0x4e, 0x6d, 0x11, 0xe0, 0x7d, 0x6d, 0x09, 0x6a, 0x85, 0xe5, 0x7d, 0xf3, 0xa8, 0x81, 0xc1, - 0xbc, 0x76, 0x8e, 0x0c, 0x2a, 0x7d, 0xd6, 0xd0, 0x86, 0x46, 0x6f, 0xaf, 0x15, 0xf9, 0xe3, 0x10, 0xde, 0x35, 0x87, - 0xcf, 0x1c, 0x3e, 0x97, 0x0c, 0xbe, 0x1e, 0x0e, 0x65, 0xce, 0x35, 0xb5, 0x29, 0x98, 0xbe, 0x9f, 0xd7, 0x4a, 0xf8, - 0xe5, 0xd9, 0x73, 0x0c, 0xf2, 0x49, 0x1f, 0xbc, 0x1e, 0xa2, 0x91, 0xd6, 0xe9, 0x28, 0x29, 0x88, 0x95, 0x8d, 0xa8, - 0x8d, 0x8c, 0xac, 0x6b, 0x9d, 0xd6, 0xf0, 0x1a, 0x94, 0x62, 0x22, 0xae, 0x7c, 0x68, 0x98, 0xaf, 0x87, 0x5c, 0xb4, - 0xc3, 0xed, 0x42, 0x7b, 0xd5, 0xad, 0xcd, 0x05, 0xa3, 0x25, 0xa0, 0x9b, 0x1a, 0x29, 0x5c, 0xb0, 0x32, 0x2b, 0x24, - 0x69, 0x28, 0x51, 0x07, 0xa6, 0x7e, 0x98, 0x63, 0x1e, 0x90, 0x77, 0x9b, 0x6c, 0xa7, 0x7e, 0xda, 0x6d, 0x3b, 0x75, - 0xb5, 0x97, 0xed, 0xd4, 0x4f, 0x5f, 0xdc, 0x76, 0xea, 0x9d, 0x6a, 0x3b, 0x05, 0x8b, 0xf8, 0x96, 0xed, 0x65, 0xd0, - 0x24, 0xcc, 0x24, 0xe2, 0xfb, 0x74, 0xe0, 0x72, 0x92, 0x36, 0xf5, 0x67, 0x0c, 0xd8, 0x74, 0xbe, 0x2a, 0x61, 0x3c, - 0x05, 0xe3, 0xa6, 0x3f, 0xdf, 0x0c, 0x29, 0x8c, 0xa7, 0xaa, 0x11, 0x52, 0xc4, 0x23, 0xa1, 0x16, 0xd1, 0x8d, 0xc8, - 0xf0, 0xc7, 0x31, 0x45, 0x2c, 0x24, 0xeb, 0xd0, 0x50, 0xb2, 0x3d, 0x4b, 0xab, 0xae, 0xb6, 0x30, 0x0d, 0xea, 0xa1, - 0x55, 0x91, 0x6c, 0xd8, 0x7e, 0x29, 0x62, 0x3e, 0xa8, 0x3d, 0x48, 0xeb, 0x59, 0x8a, 0x9f, 0xb0, 0xd6, 0x7f, 0x59, - 0xb9, 0xdf, 0x5e, 0xbb, 0xfd, 0x8e, 0x0b, 0x4e, 0xcb, 0xc0, 0xe4, 0x61, 0x81, 0xd3, 0xef, 0x74, 0xa0, 0xe0, 0x5e, - 0x29, 0x68, 0x43, 0x41, 0xa0, 0x14, 0x74, 0xa1, 0xc0, 0x57, 0x0a, 0x8e, 0xa0, 0x60, 0xac, 0x14, 0x1c, 0x43, 0xc1, - 0x9d, 0x9e, 0x5f, 0x47, 0x72, 0xb8, 0xc7, 0xc6, 0x8d, 0x49, 0x4c, 0x85, 0x28, 0x3b, 0x36, 0x5d, 0xb0, 0x26, 0xf2, - 0xa6, 0xbd, 0xd8, 0x24, 0xf9, 0x5e, 0x2f, 0x31, 0xef, 0x67, 0x8c, 0x02, 0x28, 0xbf, 0xc1, 0x3b, 0xc7, 0xce, 0x62, - 0xb0, 0x27, 0x16, 0x81, 0x09, 0x04, 0x1c, 0x34, 0xdd, 0x00, 0x99, 0x4d, 0x5f, 0xae, 0x9c, 0x08, 0xee, 0xa0, 0xac, - 0x65, 0xf1, 0x8e, 0x3e, 0x67, 0xc9, 0x2d, 0x50, 0x98, 0x78, 0xb4, 0x54, 0xb9, 0xe0, 0x97, 0x50, 0xf4, 0xbf, 0x61, - 0xa3, 0xe5, 0x54, 0xbb, 0x8c, 0xa7, 0x3b, 0x75, 0xf6, 0xea, 0x2b, 0x18, 0xa5, 0x4e, 0x0a, 0x10, 0x4b, 0x6c, 0x4b, - 0xfe, 0x2d, 0x7a, 0xcc, 0xcb, 0xf5, 0x33, 0x18, 0x9b, 0x96, 0x91, 0xc5, 0x08, 0x7c, 0x07, 0x60, 0xa4, 0x28, 0xcd, - 0x2f, 0x01, 0xce, 0xca, 0xf3, 0x95, 0xa7, 0x8c, 0xe7, 0xec, 0x07, 0x96, 0xa6, 0xde, 0x54, 0xd4, 0xaf, 0x8f, 0x13, - 0xac, 0x64, 0x24, 0xff, 0x85, 0x00, 0x04, 0x61, 0x5a, 0x50, 0x33, 0x86, 0x48, 0xe2, 0x7b, 0x0d, 0xcc, 0x6d, 0x60, - 0x43, 0x15, 0x86, 0x01, 0x81, 0x0d, 0x4b, 0x58, 0x56, 0xe1, 0xc3, 0xe1, 0xbf, 0x63, 0x61, 0xb5, 0x30, 0xf3, 0xa6, - 0xd5, 0x22, 0xda, 0x07, 0xb9, 0x3a, 0x36, 0xa9, 0x41, 0x2f, 0x15, 0x7e, 0x8e, 0x4a, 0x38, 0x8c, 0xa7, 0x7f, 0xaa, - 0x3e, 0x78, 0x8b, 0x1e, 0xff, 0x43, 0x64, 0x06, 0xd9, 0xd0, 0x46, 0x18, 0x6b, 0x36, 0x80, 0xb0, 0x17, 0x65, 0x33, - 0x0b, 0x5d, 0xae, 0x5a, 0xed, 0xc8, 0x30, 0x6d, 0x5c, 0xdb, 0x75, 0xd5, 0xd1, 0xb4, 0x97, 0x4c, 0x47, 0x5e, 0xcb, - 0x6d, 0x1f, 0x9b, 0xe2, 0xcf, 0x76, 0xba, 0x46, 0x8e, 0x3d, 0x68, 0xe3, 0xe0, 0x6e, 0x3d, 0x89, 0xa3, 0xcc, 0x9a, - 0x78, 0xf3, 0x20, 0x7c, 0xe8, 0xcd, 0xe3, 0x28, 0x4e, 0x17, 0x9e, 0xcf, 0xfa, 0x05, 0x43, 0xdd, 0xc7, 0x10, 0x06, - 0xdc, 0x8b, 0xce, 0xb5, 0xdb, 0x09, 0x9b, 0x53, 0x6b, 0x19, 0xa1, 0x60, 0x12, 0xb2, 0x55, 0xce, 0x3f, 0x5f, 0xaa, - 0x4c, 0x55, 0x71, 0xcb, 0x51, 0x0b, 0xa0, 0x48, 0x79, 0xf8, 0x03, 0x08, 0xfa, 0xd3, 0x5f, 0x78, 0x63, 0x8c, 0xd8, - 0x67, 0xb7, 0xbb, 0x09, 0x9b, 0x6b, 0x76, 0x77, 0x63, 0xe7, 0x49, 0x7c, 0x7f, 0x06, 0xa3, 0xc5, 0xc6, 0x56, 0xca, - 0xc2, 0x09, 0xbe, 0xb1, 0xd0, 0xe3, 0x42, 0xf4, 0x63, 0x21, 0x23, 0x0e, 0xbd, 0xb1, 0x79, 0x1f, 0x5e, 0xf7, 0xda, - 0x9a, 0xd3, 0x9f, 0x07, 0x91, 0x45, 0xd3, 0x39, 0x76, 0x16, 0x4a, 0x5f, 0x2a, 0xfc, 0x8c, 0x35, 0x56, 0x77, 0x35, - 0xa7, 0x0f, 0xcc, 0xda, 0x24, 0x8c, 0xef, 0x7b, 0xb3, 0x60, 0x3c, 0x66, 0x51, 0x1f, 0xc7, 0x2c, 0x0b, 0x59, 0x18, - 0x06, 0x8b, 0x34, 0x48, 0xfb, 0x73, 0x6f, 0xc5, 0x7b, 0x3d, 0xdc, 0xd4, 0x6b, 0x87, 0xf7, 0xda, 0xd9, 0xbb, 0x57, - 0xa5, 0x1b, 0xf0, 0xee, 0xa0, 0x7e, 0xf8, 0xd0, 0xba, 0x9a, 0x53, 0x99, 0xe7, 0xde, 0xbd, 0x2e, 0x12, 0xb6, 0x9e, - 0x7b, 0xc9, 0x34, 0x88, 0x7a, 0x4e, 0x6e, 0xdf, 0xad, 0x69, 0x63, 0x3c, 0x3d, 0x39, 0x39, 0xc9, 0xed, 0xb1, 0x78, - 0x72, 0xc6, 0xe3, 0xdc, 0xf6, 0xc5, 0xd3, 0x64, 0xe2, 0x38, 0x93, 0x49, 0x6e, 0x07, 0xa2, 0xa0, 0xd3, 0xf6, 0xc7, - 0x9d, 0x76, 0x6e, 0xdf, 0x2b, 0x35, 0x72, 0x9b, 0xf1, 0xa7, 0x84, 0x8d, 0xfb, 0xb8, 0x91, 0xee, 0x69, 0xe9, 0x8f, - 0x1d, 0x27, 0x47, 0x0c, 0x70, 0x5d, 0xc2, 0x4d, 0x28, 0xeb, 0xb9, 0x59, 0xef, 0x5d, 0x53, 0x2b, 0x3e, 0xe7, 0xfb, - 0x8d, 0xf5, 0xc6, 0x5e, 0xf2, 0xe9, 0x46, 0x53, 0x66, 0xe1, 0x79, 0x54, 0x6d, 0x2d, 0xc0, 0x60, 0xad, 0x7a, 0x10, - 0xca, 0xaa, 0x3f, 0x8a, 0x13, 0x38, 0xb3, 0x89, 0x37, 0x0e, 0x96, 0x69, 0xcf, 0x6d, 0x2f, 0x56, 0xa2, 0x88, 0xef, - 0xf5, 0xa2, 0x00, 0xcf, 0x5e, 0x2f, 0x8d, 0xc3, 0x60, 0x2c, 0x8a, 0x36, 0x9d, 0x25, 0xb7, 0x6d, 0xf4, 0xd1, 0x91, - 0x3b, 0xc0, 0x70, 0x04, 0x5e, 0x18, 0x6a, 0x76, 0x27, 0xd5, 0x98, 0x97, 0xa2, 0x88, 0x57, 0x73, 0x52, 0x82, 0x0b, - 0x3a, 0x6d, 0xbb, 0x87, 0x8b, 0x95, 0xdc, 0xf3, 0xee, 0xd1, 0x62, 0x95, 0x7f, 0x3d, 0x67, 0xe3, 0xc0, 0xd3, 0x5a, - 0xc5, 0x6e, 0x72, 0x1d, 0x10, 0x03, 0x1b, 0xeb, 0x0d, 0xdb, 0x54, 0x1c, 0x0b, 0x08, 0xf9, 0xf7, 0x24, 0x98, 0x2f, - 0xe2, 0x24, 0xf3, 0xa2, 0x2c, 0xcf, 0x87, 0x37, 0x79, 0xde, 0xbf, 0x0a, 0x5a, 0xd7, 0xff, 0x6c, 0xd1, 0x3d, 0x4d, - 0x6a, 0x93, 0xdc, 0xb8, 0x31, 0xdf, 0x32, 0xd5, 0x48, 0x03, 0xae, 0x31, 0x34, 0xd0, 0x50, 0x2b, 0xd3, 0x2d, 0x59, - 0xaf, 0x4c, 0x40, 0x96, 0xd5, 0xc9, 0xe8, 0xa3, 0x5c, 0x05, 0x6f, 0x20, 0xa8, 0xf0, 0x96, 0x0d, 0xae, 0x14, 0x83, - 0x0f, 0x20, 0x56, 0xb0, 0x32, 0xd9, 0xdb, 0x3f, 0xdb, 0x44, 0x33, 0x7e, 0xb3, 0x9b, 0x66, 0xfc, 0x39, 0xdb, 0x87, - 0x66, 0xfc, 0xe6, 0x8b, 0xd3, 0x8c, 0xcf, 0xea, 0xf6, 0xf6, 0x17, 0xf1, 0x40, 0x97, 0x42, 0x7e, 0xb8, 0x9a, 0x12, - 0x8a, 0x64, 0x73, 0xf1, 0x87, 0xcd, 0xe3, 0x45, 0x6f, 0x94, 0x9b, 0x8d, 0x6e, 0x6e, 0x90, 0xc7, 0xbe, 0x8b, 0x06, - 0xff, 0x48, 0xd4, 0xe7, 0xc9, 0x64, 0xf0, 0x26, 0x56, 0x0a, 0xe4, 0x13, 0x37, 0x7f, 0x28, 0x45, 0x1d, 0xa0, 0x37, - 0xc2, 0xec, 0x11, 0xf3, 0x32, 0x80, 0xd3, 0x32, 0x99, 0xf9, 0x8e, 0xa5, 0xb9, 0x57, 0xbf, 0x3c, 0x84, 0x96, 0xb4, - 0xb1, 0x14, 0xae, 0x29, 0x35, 0x51, 0xe2, 0x94, 0x65, 0xdc, 0x97, 0xf4, 0xdb, 0x87, 0x8b, 0x71, 0xeb, 0x22, 0x36, - 0xf2, 0x20, 0x7d, 0x57, 0x75, 0x0c, 0xe1, 0xea, 0x97, 0x81, 0x3a, 0x9d, 0x9c, 0x9b, 0x6c, 0xa9, 0x89, 0x97, 0xe1, - 0x35, 0x35, 0x3f, 0x2f, 0xcd, 0xb4, 0xa7, 0x36, 0xe4, 0x09, 0xa0, 0x6a, 0x97, 0x31, 0xb7, 0xca, 0x5f, 0x73, 0x0a, - 0x10, 0x73, 0x5a, 0xa1, 0x3f, 0xed, 0x98, 0x9a, 0x07, 0xe3, 0x3c, 0x37, 0xfa, 0x02, 0x10, 0xca, 0x45, 0xcb, 0x76, - 0x11, 0x71, 0xe9, 0xbd, 0xb4, 0x2a, 0xe0, 0x4a, 0x3a, 0xd2, 0xc0, 0x5d, 0x80, 0x4a, 0x9b, 0xeb, 0xeb, 0x38, 0xcc, - 0x74, 0x8d, 0xc0, 0x47, 0xa6, 0x0e, 0xca, 0x84, 0x40, 0xe3, 0x2d, 0xe1, 0x2f, 0x5e, 0x89, 0x82, 0xba, 0xd1, 0x24, - 0x01, 0x07, 0x75, 0xf2, 0xe0, 0xfd, 0x2e, 0xe4, 0xda, 0x84, 0x76, 0x78, 0x1d, 0x7c, 0xc8, 0x75, 0x49, 0xfb, 0xe1, - 0xf6, 0x3b, 0x3b, 0x3d, 0x80, 0x06, 0x67, 0x15, 0xd5, 0xfd, 0x0e, 0x93, 0x40, 0x20, 0x25, 0xd2, 0x7b, 0xd3, 0x4e, - 0xef, 0xb5, 0x17, 0x6b, 0x11, 0x39, 0x22, 0xf3, 0x16, 0x16, 0xb0, 0xf8, 0x88, 0x7b, 0x39, 0xc6, 0x53, 0x82, 0x54, - 0xf4, 0x97, 0x29, 0xe0, 0x46, 0x64, 0x54, 0x11, 0xff, 0xf4, 0xfd, 0x65, 0x92, 0xc6, 0x49, 0x6f, 0x11, 0x07, 0x51, - 0xc6, 0x92, 0x1c, 0x41, 0x75, 0x8d, 0xf0, 0x11, 0xe0, 0xb9, 0x59, 0xc7, 0x0b, 0xcf, 0x0f, 0xb2, 0x87, 0x9e, 0xc3, - 0x49, 0x0a, 0xa7, 0xcf, 0xa9, 0x03, 0xa7, 0xb1, 0x7e, 0x8f, 0x43, 0xf3, 0x25, 0x12, 0x7e, 0x49, 0x9d, 0x9c, 0x51, - 0xb7, 0x79, 0x5f, 0x79, 0x4b, 0xb1, 0x33, 0x80, 0xfc, 0xf0, 0x12, 0x6b, 0x0a, 0x58, 0x1e, 0x96, 0xda, 0x19, 0xb3, - 0xa9, 0x89, 0x58, 0x1b, 0xe4, 0xf2, 0xe2, 0xcf, 0xee, 0x1a, 0x9a, 0xd3, 0x5c, 0x0c, 0x14, 0x8f, 0xb1, 0xcf, 0xc8, - 0x7a, 0x1e, 0x64, 0x9a, 0x32, 0xf7, 0xa9, 0x39, 0x62, 0x93, 0x38, 0x61, 0x14, 0x67, 0xd5, 0x3d, 0x59, 0xac, 0xf6, - 0xef, 0x7e, 0xfb, 0xf4, 0x9b, 0xfb, 0x89, 0xe2, 0xac, 0x25, 0x3a, 0x33, 0x76, 0xf4, 0x56, 0xbf, 0xcf, 0x80, 0x34, - 0x24, 0xc8, 0xfb, 0x14, 0xd2, 0xaa, 0xa7, 0xeb, 0xfd, 0xc6, 0x70, 0x56, 0x8b, 0x98, 0xdf, 0x79, 0x09, 0x0b, 0xbd, - 0x2c, 0xb8, 0x13, 0x34, 0x63, 0xe7, 0x68, 0xb1, 0x12, 0x6b, 0x8c, 0x17, 0xde, 0x23, 0x16, 0xa9, 0x32, 0x14, 0xb1, - 0x48, 0xd5, 0x62, 0x5c, 0xa4, 0x7e, 0x6d, 0x36, 0x22, 0xc2, 0x43, 0xe5, 0xa6, 0xef, 0x2e, 0x56, 0xea, 0x15, 0x5d, - 0x34, 0x93, 0x37, 0x75, 0x35, 0x34, 0xd7, 0x3c, 0x18, 0x8f, 0x43, 0x96, 0x97, 0x16, 0xba, 0xbc, 0x96, 0x0a, 0x70, - 0x24, 0x1c, 0xbc, 0x51, 0x1a, 0x87, 0xcb, 0x8c, 0x35, 0x83, 0x8b, 0x80, 0xd3, 0x76, 0x0a, 0xe0, 0xe0, 0xef, 0xf2, - 0x58, 0xbb, 0x40, 0x6e, 0xc3, 0x36, 0x71, 0xfa, 0x10, 0x89, 0xd7, 0xea, 0x94, 0x87, 0x0e, 0xaf, 0xe4, 0xa0, 0xcd, - 0x86, 0x89, 0x98, 0x70, 0x2d, 0x11, 0xf6, 0xd6, 0x6c, 0x97, 0x97, 0xc9, 0x68, 0xa4, 0xb2, 0x28, 0x2f, 0x4f, 0xe6, - 0xcf, 0x39, 0x63, 0xaf, 0x9a, 0xcf, 0xd8, 0x2b, 0x71, 0xc6, 0xb6, 0xef, 0xcc, 0xa7, 0x13, 0x17, 0xfe, 0xeb, 0x17, - 0x13, 0xea, 0x39, 0x5a, 0x67, 0xb1, 0xd2, 0xdc, 0xc5, 0x4a, 0xb3, 0xda, 0x8b, 0x95, 0x86, 0x5d, 0xa3, 0x49, 0x86, - 0x69, 0xb7, 0x0d, 0xd3, 0xd1, 0xa0, 0x10, 0xfe, 0x9c, 0xd2, 0x2b, 0xf7, 0x10, 0xde, 0x41, 0xab, 0x6e, 0xfd, 0x5d, - 0x7b, 0xfb, 0x51, 0xa7, 0xb3, 0x24, 0x90, 0xb6, 0x61, 0x67, 0xde, 0x68, 0xc4, 0xc6, 0xbd, 0x49, 0xec, 0x2f, 0xd3, - 0x7f, 0xf3, 0xf1, 0x73, 0x20, 0x6e, 0x45, 0x04, 0x95, 0x7e, 0x44, 0x53, 0x50, 0x94, 0xdc, 0x31, 0xd1, 0xc3, 0x5a, - 0xae, 0x53, 0x8f, 0xc2, 0x06, 0xb7, 0xed, 0xc3, 0x86, 0x4d, 0xde, 0x0c, 0xe8, 0x3f, 0x6d, 0x95, 0x36, 0xa3, 0x98, - 0xcf, 0x00, 0xcb, 0x56, 0x70, 0x3c, 0x1e, 0x1a, 0x7c, 0x35, 0x9d, 0x93, 0xe6, 0xe1, 0x5e, 0x8b, 0x2f, 0xdd, 0x88, - 0x4b, 0x85, 0xdf, 0x5b, 0xdc, 0x13, 0x64, 0x7b, 0xaf, 0x9b, 0xf6, 0x48, 0xad, 0xd7, 0x2d, 0x17, 0x42, 0x51, 0x77, - 0x4f, 0x2c, 0xff, 0xf4, 0xd5, 0x21, 0xfc, 0x47, 0x54, 0xfd, 0xcf, 0x59, 0x13, 0xa1, 0x7e, 0x51, 0x36, 0xbd, 0x26, - 0x52, 0x09, 0x09, 0xf1, 0xfd, 0xeb, 0x4f, 0x26, 0x8f, 0x6b, 0xb0, 0x77, 0x6d, 0xb2, 0x66, 0xaa, 0xd6, 0xfe, 0x36, - 0x8e, 0x21, 0xa5, 0x65, 0xbd, 0xba, 0x00, 0x0f, 0x59, 0x97, 0x67, 0x03, 0x68, 0x24, 0xf8, 0x08, 0xd2, 0xe2, 0xeb, - 0xd8, 0x86, 0x58, 0x89, 0xb7, 0x9b, 0x58, 0x89, 0x37, 0xbb, 0x59, 0x89, 0xef, 0xf7, 0x62, 0x25, 0xde, 0x7c, 0x71, - 0x56, 0xe2, 0x6d, 0x9d, 0x95, 0xb8, 0x8a, 0x85, 0x05, 0xab, 0x79, 0xb1, 0xe4, 0x3f, 0x3f, 0x92, 0x52, 0xee, 0x32, - 0x1e, 0x74, 0x1d, 0x0a, 0x05, 0x7c, 0xf5, 0x87, 0x19, 0x0b, 0xdc, 0x88, 0xef, 0xd1, 0xa2, 0xab, 0x60, 0x2d, 0x38, - 0x66, 0xc7, 0xef, 0x28, 0xc5, 0x61, 0x1c, 0x4d, 0x7f, 0x02, 0xa5, 0x2c, 0x88, 0x03, 0x13, 0xe5, 0x45, 0x90, 0xfe, - 0x14, 0x2f, 0x96, 0x8b, 0x0b, 0xe8, 0xeb, 0x63, 0x90, 0x06, 0xa3, 0x90, 0x49, 0x0f, 0x5d, 0xb2, 0x40, 0xe3, 0x32, - 0x71, 0xb0, 0xf9, 0x14, 0x3f, 0xbd, 0x95, 0xf8, 0x89, 0x56, 0xa1, 0xfc, 0x37, 0x99, 0xb6, 0xe9, 0xcd, 0x8c, 0x88, - 0x50, 0x02, 0x2a, 0x83, 0x7e, 0x3c, 0x33, 0x72, 0x15, 0x1b, 0x0d, 0xb3, 0x14, 0xf6, 0x0e, 0x1b, 0xfb, 0x61, 0x35, - 0xa6, 0x66, 0x69, 0x98, 0x32, 0x34, 0x55, 0x5d, 0x0c, 0x3f, 0x8f, 0x97, 0x29, 0x1b, 0xc7, 0xf7, 0x91, 0x6e, 0x46, - 0xd2, 0xaa, 0x1f, 0x34, 0x9c, 0xb2, 0x0d, 0x26, 0x55, 0xfc, 0x80, 0x84, 0x72, 0x9c, 0xb4, 0x74, 0xc8, 0xe9, 0xb9, - 0x5c, 0x58, 0xa4, 0x6a, 0xb6, 0x70, 0x8a, 0xba, 0xcc, 0xfe, 0xf3, 0xa4, 0xd5, 0x8a, 0x07, 0x8f, 0x6b, 0x29, 0x4c, - 0x35, 0x62, 0x9b, 0x4b, 0x85, 0xd3, 0x56, 0x24, 0x84, 0x8b, 0x22, 0x3e, 0x44, 0xc3, 0xc2, 0xf1, 0x37, 0xe4, 0x2b, - 0x5a, 0xbc, 0x85, 0xe8, 0x1a, 0xf9, 0x92, 0xaf, 0x07, 0x8f, 0x96, 0x40, 0x8f, 0xaf, 0x15, 0x30, 0xbe, 0xbb, 0x63, - 0x49, 0xe8, 0x3d, 0xb4, 0x8c, 0x3c, 0x8e, 0x7e, 0x00, 0x00, 0xbc, 0x89, 0xef, 0x23, 0xb5, 0x02, 0x26, 0x31, 0x69, - 0xd8, 0x4b, 0x8d, 0x71, 0x3d, 0xc0, 0x53, 0x44, 0x19, 0x01, 0xa4, 0x8f, 0x9d, 0xb2, 0x7f, 0x98, 0xf4, 0xef, 0x3f, - 0x8d, 0xdc, 0xbc, 0x8c, 0xe5, 0x87, 0xfe, 0xbe, 0xd8, 0xe3, 0x33, 0xcf, 0x9f, 0x3f, 0xd9, 0x3c, 0xed, 0x72, 0xda, - 0xf2, 0x86, 0xd6, 0xc6, 0xc6, 0x53, 0x00, 0xa3, 0xb8, 0x8a, 0x97, 0xfe, 0x0c, 0x6d, 0x4d, 0xbf, 0xdc, 0x7c, 0x33, - 0xe8, 0x13, 0xb3, 0x77, 0xca, 0xa9, 0x57, 0x8a, 0x0a, 0x28, 0xe0, 0xf7, 0xdf, 0x42, 0x60, 0xca, 0xff, 0x21, 0x18, - 0xea, 0xbb, 0x86, 0x73, 0xf1, 0xc1, 0xe3, 0x36, 0x6f, 0x1f, 0x92, 0x4c, 0xf2, 0x90, 0x0f, 0x42, 0xb9, 0xd6, 0x8c, - 0x64, 0xf2, 0x2a, 0xd0, 0xd4, 0xf0, 0x6a, 0x9b, 0x22, 0xc7, 0x89, 0xaf, 0x30, 0x9b, 0xd8, 0x74, 0x6e, 0xea, 0x6f, - 0x32, 0x8e, 0xad, 0x2a, 0x48, 0x86, 0x9b, 0x3c, 0x30, 0x44, 0x5f, 0xd5, 0x77, 0xf3, 0x20, 0x32, 0x31, 0x3a, 0x7a, - 0xfd, 0x8d, 0xb7, 0x82, 0xf8, 0xc0, 0x80, 0xdc, 0xaa, 0xaf, 0xa0, 0xd0, 0x54, 0x1d, 0xd5, 0x20, 0x05, 0x92, 0xde, - 0x08, 0x09, 0xa1, 0xc5, 0x1b, 0xfe, 0x45, 0xd3, 0x34, 0x4d, 0xb2, 0x11, 0x9a, 0xe4, 0x23, 0xb0, 0x1c, 0xd9, 0x01, - 0xd0, 0x96, 0xe4, 0x8b, 0x15, 0x95, 0x00, 0x67, 0x80, 0x3a, 0x59, 0x51, 0xc0, 0x43, 0xe0, 0x75, 0x1d, 0x51, 0x20, - 0x18, 0x7a, 0x08, 0x5f, 0xe6, 0x25, 0x10, 0x29, 0xb7, 0xa7, 0x21, 0xc3, 0x8e, 0x6f, 0xb9, 0x24, 0x58, 0x73, 0xe8, - 0x71, 0xd8, 0x67, 0xcd, 0xb1, 0xd2, 0x22, 0x05, 0x0b, 0x82, 0xd6, 0xa1, 0x12, 0xfa, 0xd8, 0x64, 0x0d, 0xb8, 0x11, - 0xf9, 0xa2, 0x55, 0x36, 0x67, 0xd1, 0x52, 0xc7, 0x5c, 0x49, 0x18, 0xbb, 0x0e, 0xea, 0xbc, 0x21, 0x62, 0x0b, 0xb0, - 0x4d, 0x73, 0xcb, 0x19, 0xdd, 0x85, 0x29, 0x47, 0xa9, 0x9e, 0xe9, 0x73, 0xc5, 0x66, 0xca, 0x71, 0x5b, 0xf5, 0x86, - 0xe0, 0x4b, 0x1a, 0x57, 0x3d, 0xa7, 0xc8, 0x18, 0x19, 0xfa, 0xa0, 0xa8, 0x11, 0x5c, 0x5c, 0x24, 0xc0, 0xde, 0xf2, - 0xaa, 0x8b, 0x26, 0x35, 0x32, 0x5e, 0x45, 0x50, 0x94, 0x18, 0xf5, 0x6e, 0xf8, 0x38, 0x21, 0x60, 0xcf, 0xc6, 0x7e, - 0xfc, 0x5a, 0x3f, 0x1b, 0x26, 0xfd, 0x89, 0x3d, 0xd0, 0x45, 0x42, 0xa0, 0xfa, 0xc4, 0x1e, 0xc0, 0xf6, 0xef, 0x2d, - 0x48, 0x53, 0xf4, 0x2d, 0xe8, 0xda, 0x84, 0x10, 0xf8, 0x3e, 0x04, 0x71, 0xda, 0x72, 0x80, 0x9c, 0x7c, 0x0b, 0x16, - 0x47, 0x10, 0x43, 0xb6, 0x63, 0x71, 0x88, 0xb9, 0x95, 0x7d, 0xab, 0x11, 0xc6, 0x56, 0xc3, 0xd1, 0x30, 0x5e, 0xb8, - 0x8e, 0x73, 0x50, 0xab, 0x0f, 0x82, 0xec, 0xa6, 0xda, 0x86, 0x99, 0x0d, 0x5c, 0xc7, 0x0a, 0x5e, 0xd8, 0xed, 0x7e, - 0xed, 0x8e, 0x56, 0x62, 0x2c, 0x0e, 0x51, 0xfc, 0x75, 0xf6, 0x6c, 0xdd, 0xaa, 0x1d, 0x48, 0xa3, 0x6a, 0xb5, 0x8e, - 0x63, 0xcb, 0xb9, 0xfc, 0x6b, 0x58, 0xbf, 0xfa, 0x29, 0xc2, 0x23, 0xe5, 0xfb, 0x18, 0x42, 0x94, 0xe0, 0x16, 0x1c, - 0xa3, 0xbf, 0x6a, 0x2f, 0xb5, 0x16, 0x1d, 0x1f, 0xc3, 0x18, 0xca, 0x34, 0xd2, 0xc2, 0xab, 0x4b, 0xed, 0xa0, 0xf2, - 0xc5, 0xb4, 0x8a, 0xe1, 0x78, 0x3c, 0x52, 0x56, 0x68, 0xf4, 0xb6, 0x52, 0x0b, 0xd8, 0xff, 0x86, 0xeb, 0xd3, 0x1e, - 0x41, 0x20, 0x00, 0xa8, 0x01, 0x31, 0xc5, 0x77, 0x76, 0xb8, 0x5c, 0x94, 0xbb, 0x2b, 0x5f, 0x92, 0xfb, 0x77, 0x86, - 0x97, 0x0e, 0xea, 0xd0, 0x64, 0x7f, 0xcd, 0xd7, 0xdd, 0x23, 0xbb, 0x64, 0xd1, 0xb8, 0xdc, 0x61, 0xe5, 0xfe, 0xda, - 0xbf, 0xbb, 0x12, 0x46, 0x81, 0x60, 0xfb, 0x71, 0x03, 0x46, 0xc9, 0xe3, 0x08, 0x37, 0x3f, 0x1d, 0xb7, 0x60, 0x2f, - 0x2a, 0x06, 0x1b, 0x50, 0xa4, 0x2c, 0xd9, 0x4c, 0x11, 0x8a, 0x43, 0x44, 0x67, 0xf4, 0xc3, 0x6d, 0x09, 0x42, 0x74, - 0xe3, 0x4e, 0xcc, 0x84, 0x4d, 0x61, 0xd1, 0x26, 0xe0, 0x31, 0x1a, 0xf7, 0x95, 0x5a, 0x07, 0xbb, 0xa5, 0xd6, 0xd9, - 0x2e, 0xa9, 0x35, 0x39, 0x34, 0xdd, 0x27, 0xde, 0x42, 0xf1, 0x89, 0x13, 0xc4, 0xb9, 0xea, 0x1a, 0x57, 0x12, 0x75, - 0xa3, 0xff, 0x93, 0x68, 0x55, 0xeb, 0x8d, 0xac, 0x04, 0x51, 0xfc, 0xad, 0x30, 0x28, 0x42, 0xa1, 0xae, 0xca, 0xc6, - 0xaf, 0x0a, 0xd9, 0x38, 0x71, 0x35, 0x85, 0x2f, 0x8b, 0xa0, 0xfe, 0x15, 0x37, 0x31, 0xc9, 0x1d, 0x14, 0xee, 0x62, - 0xc5, 0x48, 0x15, 0x07, 0xa8, 0x82, 0xd1, 0x50, 0xdc, 0xea, 0x04, 0x97, 0x51, 0xf6, 0xae, 0x2b, 0x57, 0x2d, 0xbc, - 0xcd, 0x8a, 0x72, 0x90, 0xba, 0xe3, 0x90, 0x65, 0xb1, 0xba, 0x6d, 0xca, 0x1e, 0x30, 0xea, 0x6b, 0x65, 0x93, 0x48, - 0x57, 0x15, 0x02, 0xb0, 0x10, 0xd3, 0x57, 0xf4, 0xda, 0xd2, 0x06, 0x02, 0x07, 0xd9, 0xe0, 0x58, 0xb7, 0x5b, 0x3a, - 0x4f, 0x79, 0x04, 0x0a, 0x2d, 0xbc, 0x2a, 0x83, 0x40, 0xf8, 0xde, 0xac, 0x1b, 0x6e, 0x79, 0xbc, 0xe4, 0xf9, 0xfd, - 0x0e, 0xe2, 0x45, 0xcd, 0x51, 0x15, 0xf9, 0x78, 0x32, 0x2d, 0x32, 0xcf, 0xc5, 0xaa, 0xf5, 0x4e, 0x49, 0x88, 0xb3, - 0xe6, 0xce, 0x29, 0x65, 0x19, 0x3d, 0xaf, 0xd1, 0x13, 0xdf, 0xe5, 0x5b, 0x27, 0x59, 0x46, 0x18, 0xf3, 0xdd, 0xca, - 0x12, 0xcf, 0xff, 0xa4, 0x0c, 0x59, 0xc8, 0x39, 0x41, 0x06, 0x5c, 0xd6, 0x14, 0xf4, 0x3d, 0x0c, 0x91, 0xc8, 0x7a, - 0x76, 0x3b, 0x55, 0xa4, 0x2f, 0xbd, 0xa7, 0x4e, 0xc7, 0x7b, 0x35, 0x39, 0xac, 0x08, 0x45, 0xdb, 0xdd, 0xb2, 0xc8, - 0x7c, 0xc3, 0x38, 0xb2, 0xd9, 0x72, 0x3e, 0x5a, 0xab, 0xb2, 0x55, 0x45, 0xe4, 0x5a, 0x17, 0xb3, 0xaa, 0x9f, 0x9d, - 0x4c, 0x26, 0x65, 0x41, 0xa3, 0xa3, 0x1d, 0xa2, 0xb0, 0xf0, 0xa9, 0xe3, 0x38, 0xd5, 0xb1, 0x6f, 0x07, 0xbb, 0x85, - 0x72, 0xdb, 0x93, 0xc6, 0x11, 0x23, 0x6c, 0x77, 0xc1, 0xaf, 0x0e, 0x8e, 0xdc, 0x2e, 0x4e, 0x76, 0xc9, 0x2c, 0xa2, - 0x4f, 0xc6, 0x10, 0x41, 0xc6, 0xe6, 0x69, 0xcf, 0x67, 0xa8, 0x83, 0xb1, 0x95, 0x03, 0x8d, 0x86, 0x03, 0xd6, 0x14, - 0x4c, 0x45, 0x5c, 0xb1, 0x2b, 0x1c, 0x0d, 0xe5, 0xe1, 0x35, 0xe1, 0xbd, 0xf8, 0x08, 0x1e, 0x94, 0x75, 0x5d, 0xa6, - 0x8d, 0xd3, 0xea, 0x3a, 0x7f, 0x2d, 0xd5, 0xd3, 0xe0, 0x02, 0x5c, 0x0b, 0x85, 0x36, 0xc9, 0x67, 0xf1, 0xff, 0xa5, - 0xfc, 0xff, 0xd5, 0x62, 0x55, 0xb6, 0x1f, 0x39, 0x01, 0x89, 0x76, 0x71, 0x5a, 0x68, 0xd4, 0x4d, 0x7b, 0x40, 0x5a, - 0x19, 0x4c, 0x54, 0x05, 0x3a, 0x28, 0xe9, 0x4b, 0x89, 0x31, 0x1a, 0xc4, 0xef, 0x48, 0x31, 0xc3, 0x12, 0x17, 0x22, - 0xc4, 0x22, 0xad, 0x1b, 0xcc, 0xc1, 0x7c, 0x79, 0x82, 0xfa, 0x83, 0xd2, 0x9e, 0x00, 0x6d, 0x7c, 0x6d, 0x6e, 0x7b, - 0x89, 0xfb, 0xab, 0x7a, 0x2d, 0xd1, 0x31, 0x80, 0xcc, 0x85, 0x43, 0x88, 0x86, 0x04, 0x5a, 0x65, 0x73, 0xd3, 0x28, - 0xe5, 0x5b, 0x55, 0xcf, 0x26, 0x06, 0x86, 0xdd, 0x35, 0x57, 0xa1, 0xbe, 0x85, 0xb6, 0x00, 0x26, 0xcb, 0xb7, 0x1f, - 0x3e, 0x5b, 0xb0, 0xc4, 0xea, 0x7e, 0x74, 0x71, 0xc9, 0x71, 0xff, 0x5a, 0x78, 0x77, 0xa6, 0x74, 0xfe, 0x51, 0xbe, - 0xf8, 0x7d, 0xa3, 0x40, 0xef, 0xaa, 0x24, 0xa1, 0xe3, 0xd6, 0xe2, 0x6d, 0x63, 0xaf, 0xda, 0xf3, 0x20, 0xda, 0xbf, - 0xae, 0xb7, 0xda, 0xbb, 0x2e, 0x5c, 0x18, 0x7b, 0x57, 0x86, 0x1b, 0x87, 0x2c, 0x17, 0xb2, 0xc1, 0xf7, 0x8a, 0x40, - 0x51, 0xf5, 0xfb, 0xd5, 0xb1, 0x15, 0x51, 0xf9, 0x57, 0x4b, 0x20, 0x3e, 0xf7, 0x4a, 0x7c, 0xa0, 0x89, 0xdc, 0x65, - 0xfa, 0xb1, 0x76, 0xa2, 0x1d, 0x77, 0xb4, 0x23, 0x47, 0x27, 0x2e, 0x6c, 0xa0, 0x77, 0xdb, 0x85, 0x43, 0xdf, 0xa1, - 0xa3, 0x9f, 0x9d, 0x4e, 0xc5, 0x25, 0x31, 0x09, 0xc2, 0x90, 0x50, 0x45, 0x9a, 0x25, 0xf1, 0x27, 0x56, 0x56, 0xb3, - 0x50, 0x19, 0x37, 0x02, 0x69, 0x8b, 0x47, 0x38, 0x3b, 0xbe, 0xb7, 0xe8, 0xe1, 0xd9, 0x50, 0x0b, 0xc1, 0x80, 0x93, - 0x4a, 0xf1, 0x13, 0x70, 0x07, 0x8f, 0xf4, 0xb3, 0x53, 0x08, 0xed, 0xa7, 0x8d, 0x07, 0xfa, 0x0f, 0xed, 0x63, 0xcd, - 0xed, 0xde, 0x59, 0x1d, 0xdf, 0xb1, 0x5c, 0xfb, 0x50, 0x73, 0xec, 0x23, 0xab, 0x6d, 0x1f, 0x6b, 0x6d, 0xbb, 0x0b, - 0xff, 0xfa, 0xae, 0xfd, 0x4a, 0x73, 0xe0, 0x49, 0x73, 0xed, 0x0e, 0xfe, 0xdb, 0xb6, 0x8f, 0xef, 0x3a, 0x74, 0xd3, - 0x7b, 0xd2, 0xad, 0xaa, 0x32, 0x0a, 0x70, 0x02, 0xd1, 0x0f, 0xce, 0x4e, 0x97, 0x29, 0xd3, 0x56, 0x03, 0xfd, 0x95, - 0xae, 0xcd, 0x12, 0x36, 0x19, 0xe8, 0x4f, 0x3d, 0xa5, 0xd4, 0x3d, 0x69, 0x2c, 0x6e, 0x1f, 0x37, 0x16, 0x77, 0x8e, - 0x1a, 0x8b, 0x0f, 0xbb, 0xe5, 0xe2, 0x83, 0x29, 0xbd, 0x52, 0x32, 0xeb, 0xcd, 0xbd, 0x2c, 0x09, 0x56, 0x2d, 0x57, - 0x03, 0x74, 0x6d, 0xc1, 0x3f, 0xc7, 0x6d, 0x43, 0xb6, 0x1a, 0x41, 0x2b, 0x09, 0x8d, 0xe3, 0x13, 0xcd, 0x3d, 0xfa, - 0x5b, 0xfb, 0xc8, 0x87, 0x7a, 0x90, 0x07, 0x12, 0xfe, 0xee, 0x3a, 0x27, 0xbe, 0xa3, 0x41, 0x43, 0x17, 0xfe, 0x9b, - 0x75, 0xdb, 0x3e, 0x3d, 0x38, 0xf0, 0xfe, 0xa3, 0x7b, 0x9c, 0x3a, 0x96, 0x0b, 0xff, 0xfd, 0x2a, 0x55, 0xee, 0xa0, - 0xf0, 0x57, 0xfb, 0x3d, 0x74, 0xb4, 0xce, 0xc9, 0xac, 0x6d, 0xbf, 0xba, 0x3b, 0xb6, 0x4f, 0x66, 0xee, 0xf1, 0x47, - 0x7a, 0x0a, 0xad, 0xb6, 0xfd, 0x0a, 0xfe, 0x3e, 0x76, 0x9c, 0x99, 0xe5, 0xda, 0x27, 0x77, 0x1d, 0xbb, 0x13, 0x5a, - 0x47, 0xf6, 0x09, 0xfc, 0xfd, 0x0a, 0xe0, 0x05, 0xb8, 0xf2, 0xc4, 0x9d, 0x1a, 0x6c, 0x8c, 0x8a, 0xfd, 0x86, 0xfa, - 0x91, 0xf6, 0xa1, 0xd6, 0x3d, 0xfc, 0xdb, 0xc9, 0x9d, 0x75, 0x38, 0x73, 0xdb, 0x77, 0xd6, 0xc6, 0x9f, 0x1f, 0x01, - 0xf2, 0xdb, 0x17, 0x0e, 0xc0, 0x88, 0x99, 0x3a, 0xfe, 0x32, 0x34, 0x2f, 0x37, 0x89, 0xd1, 0xdf, 0xef, 0x16, 0xa3, - 0x7f, 0xb7, 0xdc, 0x47, 0x8c, 0xfe, 0xfe, 0x8b, 0x8b, 0xd1, 0x2f, 0xab, 0x56, 0xdc, 0xef, 0xab, 0x11, 0xc5, 0x7f, - 0x5e, 0x57, 0x89, 0xe4, 0xc0, 0x6b, 0x5d, 0x5f, 0x2d, 0x6f, 0x20, 0xd8, 0xce, 0xfb, 0x78, 0xf0, 0xdd, 0xb2, 0x64, - 0xa2, 0x14, 0x03, 0x06, 0x78, 0x1f, 0x13, 0x06, 0xf8, 0x75, 0x39, 0x00, 0xbb, 0x08, 0x7e, 0x6b, 0x06, 0x63, 0x6b, - 0xe6, 0x85, 0x13, 0x79, 0xe3, 0x42, 0x49, 0x1f, 0x8b, 0xc1, 0x66, 0x1e, 0x2e, 0x13, 0x50, 0xd6, 0x2c, 0xe7, 0x51, - 0xda, 0x3b, 0x72, 0x00, 0xcd, 0xb7, 0x27, 0x49, 0x5e, 0x69, 0x6c, 0x8b, 0xf0, 0x44, 0xb7, 0xdc, 0xa6, 0x7f, 0xe3, - 0x7b, 0x34, 0x59, 0x6b, 0xee, 0xdd, 0xad, 0xf7, 0xab, 0x81, 0x2d, 0x88, 0x30, 0xe9, 0x03, 0x62, 0xa3, 0xe9, 0x7d, - 0xd9, 0x70, 0xac, 0x62, 0x2a, 0xb8, 0x79, 0xa4, 0x30, 0x92, 0x6a, 0x7b, 0xb7, 0x6c, 0x78, 0xb6, 0x6b, 0x9a, 0x0d, - 0x9f, 0x2f, 0x35, 0xdf, 0x62, 0xf5, 0x26, 0x3b, 0xae, 0x82, 0xaa, 0x92, 0x0f, 0xab, 0x11, 0x20, 0x05, 0xed, 0x59, - 0x98, 0xc6, 0x15, 0x84, 0x8f, 0xa3, 0xe1, 0x6d, 0xec, 0x28, 0xef, 0x4a, 0x7d, 0xaa, 0xe6, 0x74, 0x2f, 0xd6, 0x48, - 0x0f, 0x06, 0xbf, 0x02, 0x61, 0xc3, 0xef, 0xe3, 0x51, 0xac, 0xc2, 0x79, 0xad, 0xf4, 0x4b, 0xa4, 0x76, 0x3e, 0x73, - 0xd7, 0x75, 0xd2, 0x66, 0xa3, 0x21, 0xad, 0xcb, 0xe6, 0xe2, 0x8e, 0xc6, 0xcf, 0x93, 0xd9, 0x6a, 0x4e, 0xa6, 0xc5, - 0x68, 0x99, 0xbb, 0xad, 0x33, 0x51, 0xef, 0x29, 0x6c, 0x62, 0x93, 0x3f, 0xa8, 0x8e, 0xe3, 0xeb, 0x09, 0xe4, 0x2e, - 0xee, 0x21, 0x11, 0xa1, 0x50, 0x50, 0x6d, 0xb4, 0xb1, 0xed, 0x6f, 0x31, 0xff, 0x50, 0x3b, 0xe6, 0x9d, 0xa0, 0xad, - 0xee, 0x36, 0x8b, 0x11, 0xe9, 0xda, 0xb0, 0x2e, 0x29, 0x50, 0xdd, 0xee, 0xb1, 0xe9, 0x1e, 0x99, 0xf6, 0x71, 0xd7, - 0xc8, 0xc5, 0x81, 0x53, 0xbb, 0x2c, 0x01, 0x04, 0x4c, 0x76, 0xe5, 0x30, 0x83, 0x28, 0xc8, 0x02, 0x2f, 0xcc, 0x01, - 0xd5, 0x97, 0x69, 0xde, 0x7f, 0x2d, 0xd3, 0x0c, 0xe6, 0x28, 0x48, 0x32, 0x34, 0x57, 0xb6, 0x46, 0x2c, 0xbb, 0x67, - 0x2c, 0xda, 0xa0, 0xca, 0xad, 0x5a, 0x3f, 0xff, 0x79, 0xb6, 0xa0, 0x39, 0xd9, 0x59, 0x8c, 0xb2, 0x88, 0xef, 0x0f, - 0x61, 0xaa, 0x9b, 0x0f, 0xcd, 0x1f, 0x37, 0x21, 0xdc, 0x7f, 0xed, 0x46, 0xb8, 0x19, 0xdb, 0x07, 0xe1, 0xfe, 0xeb, - 0x8b, 0x23, 0xdc, 0x1f, 0x55, 0x84, 0x5b, 0xf2, 0x54, 0x29, 0x64, 0xa2, 0x1f, 0xf0, 0xb9, 0x05, 0xa1, 0x78, 0x5f, - 0xea, 0x07, 0x44, 0x5e, 0xea, 0x4a, 0x8a, 0xd4, 0x8f, 0xa5, 0x9c, 0x2f, 0xc8, 0xb2, 0x63, 0x4c, 0x52, 0xca, 0x2f, - 0x01, 0xe9, 0x43, 0x65, 0x22, 0x6c, 0xe8, 0xf3, 0x22, 0xca, 0x42, 0xfb, 0x3d, 0x67, 0x4b, 0x40, 0x05, 0xf1, 0x5d, - 0x9c, 0xcc, 0x3d, 0x8c, 0xc7, 0xa6, 0x63, 0xae, 0x38, 0x78, 0x70, 0xc0, 0x3b, 0xca, 0x8f, 0xa3, 0xb1, 0x94, 0xa3, - 0xb3, 0xc1, 0x35, 0xd1, 0x83, 0xfa, 0x03, 0xf3, 0x12, 0xdd, 0xa4, 0xd7, 0xb0, 0xb8, 0x2f, 0x3a, 0xce, 0x8b, 0xf6, - 0xe1, 0x8b, 0x23, 0x07, 0xfe, 0xe7, 0xb2, 0x4e, 0x6e, 0xf2, 0x8a, 0xf3, 0x38, 0x82, 0x74, 0x15, 0xa2, 0xe6, 0xa6, - 0x6a, 0xf7, 0x8c, 0x7d, 0x2a, 0x6a, 0x1d, 0x37, 0x57, 0x1a, 0x7b, 0x0f, 0x45, 0x9d, 0xc6, 0x1a, 0xb3, 0x78, 0xa9, - 0x0c, 0xab, 0x61, 0x34, 0x41, 0xb4, 0x04, 0xc9, 0x90, 0x52, 0x43, 0x7d, 0xcd, 0xa7, 0x5b, 0xcc, 0x8b, 0x75, 0xf2, - 0x9b, 0x22, 0x27, 0x8e, 0xc8, 0xcd, 0xb1, 0x13, 0x82, 0x5c, 0xa8, 0xee, 0x60, 0x44, 0x6d, 0xcc, 0x0a, 0xa3, 0x41, - 0x46, 0xba, 0x22, 0xf1, 0x39, 0x2e, 0x50, 0x96, 0x2c, 0x23, 0x9f, 0x72, 0x9b, 0x7b, 0xa3, 0xb4, 0x15, 0x1c, 0x40, - 0xb0, 0x4e, 0xfc, 0xb0, 0x81, 0xab, 0xe6, 0x9d, 0x39, 0x45, 0x02, 0x81, 0x54, 0xac, 0x8a, 0xf7, 0x22, 0x33, 0x13, - 0x4a, 0x3b, 0x8a, 0x4b, 0x6b, 0x0d, 0xbc, 0x17, 0xb2, 0xe1, 0x8b, 0xcc, 0x84, 0xd4, 0x9f, 0xb0, 0xdc, 0xcf, 0x9f, - 0x53, 0x2d, 0x48, 0xc6, 0x47, 0xd3, 0x3a, 0xf7, 0x65, 0x02, 0x2f, 0x5d, 0xf3, 0xa6, 0xb1, 0x8e, 0x09, 0xbc, 0x7a, - 0xbe, 0x19, 0xbf, 0x7c, 0x79, 0x36, 0x70, 0x0d, 0x9e, 0x4a, 0xb2, 0x94, 0xf7, 0xe8, 0x72, 0x3f, 0xd5, 0xb8, 0xd1, - 0xe8, 0xb4, 0xb5, 0x08, 0xa2, 0xa9, 0xd0, 0x4c, 0x4b, 0xec, 0x05, 0x79, 0x08, 0x48, 0x05, 0xe6, 0x09, 0x15, 0xb5, - 0xa8, 0x73, 0xc7, 0x12, 0x48, 0x83, 0x39, 0xd0, 0x3b, 0xb6, 0x63, 0x3b, 0xba, 0x6c, 0x38, 0x09, 0xa6, 0x83, 0x75, - 0x9c, 0x79, 0x90, 0xd1, 0x25, 0x8c, 0xa7, 0xe0, 0xf9, 0x91, 0x05, 0x59, 0x08, 0xe9, 0x41, 0xc0, 0x05, 0x64, 0x4e, - 0x5c, 0x63, 0xce, 0xed, 0x71, 0xbd, 0xe4, 0x13, 0xa6, 0x88, 0x13, 0x4e, 0x5f, 0x18, 0x92, 0xe6, 0x07, 0xb8, 0x0c, - 0x5b, 0x7a, 0x0b, 0x12, 0x14, 0xb2, 0x24, 0xb5, 0x54, 0xfb, 0xf6, 0x9e, 0x06, 0x6d, 0x20, 0x79, 0x38, 0x76, 0x30, - 0x49, 0xbc, 0x39, 0x44, 0xd2, 0x5e, 0xe7, 0x26, 0xc7, 0xb4, 0x3a, 0x47, 0xb5, 0x9a, 0xfb, 0xea, 0xc8, 0xd4, 0xda, - 0xae, 0xa9, 0x39, 0x80, 0x6e, 0xf5, 0xdc, 0x5c, 0xe7, 0x37, 0xfd, 0x5d, 0x2a, 0x3a, 0xc2, 0x2f, 0x4f, 0x69, 0x1e, - 0xa4, 0x9c, 0xe3, 0xc2, 0xcf, 0x8c, 0xe2, 0x09, 0xb6, 0x94, 0x18, 0xd7, 0x01, 0x89, 0xe9, 0xaf, 0xd8, 0x2a, 0x33, - 0x30, 0x7d, 0x06, 0xaf, 0x12, 0x18, 0x6b, 0x74, 0x4d, 0x0b, 0x22, 0x2d, 0xf8, 0xed, 0xb7, 0x56, 0x00, 0xe6, 0xf7, - 0x03, 0x05, 0x3e, 0xf0, 0x6c, 0x94, 0x00, 0x16, 0x14, 0x8a, 0x25, 0x04, 0x16, 0xf8, 0xc6, 0xc0, 0xbf, 0x45, 0xb1, - 0xf8, 0xc1, 0x15, 0x7b, 0x76, 0xe8, 0x45, 0x53, 0x40, 0x69, 0x5e, 0x34, 0xad, 0x19, 0x10, 0x90, 0x77, 0x5d, 0xa5, - 0xb4, 0xe8, 0xaa, 0x50, 0xee, 0xa7, 0xdf, 0x3e, 0x5c, 0x51, 0x7a, 0x20, 0x48, 0x45, 0xed, 0x8d, 0xd1, 0x15, 0xac, - 0xd0, 0x3d, 0xbc, 0x1c, 0x7c, 0x75, 0x3a, 0x67, 0x99, 0x47, 0x82, 0x4b, 0x60, 0xf1, 0x80, 0x1c, 0xd0, 0x7c, 0x91, - 0xda, 0x93, 0x18, 0xbc, 0x31, 0xbb, 0x0b, 0x7c, 0xce, 0xa7, 0x99, 0x1a, 0xbf, 0xa7, 0x2c, 0xb4, 0x51, 0x1a, 0xb8, - 0x26, 0x99, 0xc8, 0xfa, 0x1e, 0x46, 0x1d, 0x1c, 0x44, 0xb1, 0x7e, 0xf6, 0x95, 0xf4, 0x26, 0xda, 0xb4, 0x08, 0x90, - 0xa3, 0xef, 0x3a, 0x61, 0xe1, 0xbf, 0x07, 0x5f, 0xc1, 0xc5, 0xfd, 0xd5, 0x8d, 0x6e, 0xf4, 0x33, 0x1b, 0xf9, 0x98, - 0xaf, 0x1a, 0x72, 0xd5, 0x21, 0x8f, 0xca, 0x99, 0xcd, 0x8e, 0xc2, 0x6c, 0xc2, 0xef, 0xdd, 0xac, 0xeb, 0xd9, 0x29, - 0x5e, 0x68, 0x67, 0xc0, 0x5d, 0xac, 0x4b, 0x3c, 0xa7, 0xdb, 0x47, 0x06, 0x75, 0x14, 0x7a, 0xfe, 0x27, 0xc1, 0xa1, - 0xaa, 0x0f, 0xfb, 0xf0, 0xa2, 0x92, 0xb2, 0x6b, 0xdc, 0xcb, 0xb8, 0x95, 0xd7, 0xf8, 0x65, 0xfc, 0xd4, 0xfd, 0x2c, - 0xc8, 0x24, 0x33, 0x8c, 0x0f, 0x39, 0x68, 0x73, 0x70, 0x7c, 0x05, 0xfb, 0x03, 0x0c, 0xaa, 0x7b, 0xf2, 0xb7, 0xee, - 0x9d, 0xeb, 0xcc, 0xda, 0xae, 0x0d, 0x6c, 0xce, 0xac, 0x63, 0x1f, 0x87, 0x56, 0xc7, 0x3e, 0x86, 0xbf, 0x8f, 0xc0, - 0x7a, 0x59, 0x6d, 0xfb, 0xf0, 0xa3, 0xdb, 0x0e, 0xad, 0x13, 0xfb, 0x18, 0xfe, 0x2e, 0xa9, 0xd5, 0xcf, 0xc8, 0xf4, - 0x00, 0xc3, 0xf3, 0x55, 0x09, 0x0b, 0x28, 0xbf, 0xa5, 0x16, 0xc1, 0x2c, 0x5d, 0x6f, 0x0d, 0x9a, 0x08, 0x40, 0x19, - 0xba, 0x29, 0x82, 0x04, 0x46, 0xfd, 0x16, 0x24, 0xcf, 0xc6, 0xb0, 0xef, 0xc2, 0x20, 0x23, 0x2a, 0x12, 0xc1, 0x6f, - 0x3e, 0x46, 0xbc, 0x4d, 0x73, 0xfc, 0x6d, 0x91, 0x4f, 0x88, 0x54, 0x17, 0x7f, 0x5f, 0x60, 0x60, 0x1d, 0x11, 0x31, - 0x5c, 0xc1, 0x4a, 0x45, 0x4e, 0xbb, 0x7c, 0xf7, 0xc0, 0xd1, 0x6f, 0x94, 0xc9, 0x9c, 0x2a, 0x5f, 0xb4, 0x6f, 0xae, - 0xce, 0x90, 0xbd, 0xff, 0xd1, 0x7e, 0x30, 0x95, 0x28, 0xf5, 0x23, 0x82, 0x7b, 0x8e, 0x83, 0x44, 0x0e, 0x4f, 0x41, - 0xd1, 0x6e, 0x73, 0xe0, 0x72, 0x03, 0x92, 0x4f, 0x5c, 0x00, 0x95, 0x7c, 0xe7, 0x85, 0x8a, 0xe9, 0x85, 0xd2, 0xf2, - 0x89, 0xc4, 0xfc, 0xcf, 0x9f, 0x17, 0x83, 0xb3, 0x2a, 0xe3, 0x3e, 0x75, 0xbb, 0x70, 0xed, 0x76, 0x59, 0x67, 0xab, - 0x15, 0xd0, 0xee, 0xe8, 0xb0, 0x45, 0x38, 0x49, 0xa1, 0xe9, 0x17, 0x3a, 0xc6, 0x8d, 0xa6, 0x48, 0x35, 0x0d, 0x23, - 0xc4, 0xd5, 0xad, 0xb0, 0x3a, 0xba, 0xd1, 0x8f, 0x84, 0xc2, 0x2c, 0xda, 0x12, 0x11, 0x97, 0xf3, 0x62, 0x3a, 0x80, - 0x66, 0xcb, 0x3c, 0x76, 0xb8, 0x34, 0xfe, 0xaf, 0x27, 0x81, 0xee, 0x45, 0xa0, 0xe1, 0xab, 0x9c, 0xd6, 0x92, 0xbb, - 0x89, 0xbc, 0x57, 0xe9, 0x42, 0x65, 0xe9, 0xb9, 0x0e, 0x45, 0x90, 0x95, 0x08, 0x13, 0x91, 0x49, 0xf3, 0x26, 0x79, - 0x5b, 0x14, 0x05, 0x66, 0x00, 0x21, 0xa1, 0x5b, 0xc2, 0xd5, 0xc9, 0x78, 0xfe, 0x7c, 0xe3, 0x25, 0x44, 0xea, 0x64, - 0x35, 0x1f, 0xa3, 0xae, 0xe2, 0x37, 0x5d, 0x45, 0x31, 0xb2, 0x5f, 0xc4, 0x1a, 0xc2, 0x2a, 0x8b, 0xf6, 0x1e, 0xfe, - 0x1c, 0x31, 0x2f, 0xb3, 0xb9, 0x1e, 0xa4, 0xa5, 0x5c, 0xee, 0xa6, 0xcb, 0x3a, 0x60, 0x8f, 0xc5, 0xe3, 0x6f, 0xf1, - 0x60, 0x73, 0xcf, 0xd6, 0x1f, 0x97, 0xdc, 0x0f, 0x19, 0xfa, 0xf8, 0xcd, 0x29, 0x82, 0xa7, 0xbc, 0xcb, 0x3c, 0x8a, - 0xb0, 0xa1, 0x5e, 0xb9, 0x71, 0xe6, 0x89, 0xec, 0x1f, 0x40, 0x97, 0xf7, 0x1b, 0x15, 0x86, 0x8a, 0xaf, 0xf2, 0xd9, - 0xbb, 0xab, 0x6f, 0x34, 0xbe, 0xff, 0x49, 0xbf, 0x85, 0x8c, 0x0c, 0x05, 0xc1, 0x1f, 0x50, 0x10, 0x7c, 0x8d, 0x27, - 0x7f, 0x80, 0x50, 0xf2, 0xf9, 0x01, 0x41, 0x50, 0xd7, 0x58, 0xe4, 0x93, 0xd6, 0x6f, 0xbe, 0x0c, 0xb3, 0x60, 0xe1, - 0x25, 0xd9, 0x01, 0x34, 0xb5, 0x00, 0xc9, 0xe9, 0x9b, 0x3c, 0x98, 0x49, 0x71, 0x28, 0x84, 0x6a, 0x59, 0x24, 0x34, - 0x87, 0x93, 0x20, 0x94, 0x8a, 0x43, 0xf1, 0x01, 0xcf, 0xf7, 0xd9, 0x22, 0x1b, 0xe8, 0xde, 0x02, 0x92, 0x21, 0x60, - 0x78, 0xe3, 0x83, 0xd8, 0xcf, 0x58, 0x66, 0xa5, 0x59, 0xc2, 0xbc, 0xb9, 0x2e, 0x43, 0x7d, 0xd6, 0xfb, 0x4b, 0x97, - 0xa3, 0x79, 0x90, 0xc9, 0x60, 0x79, 0x34, 0x41, 0x50, 0xe1, 0xc1, 0x10, 0xcf, 0x86, 0x39, 0x07, 0xe1, 0x65, 0x3c, - 0xad, 0xec, 0xa8, 0x82, 0x72, 0x39, 0xc7, 0x48, 0xac, 0x3c, 0x00, 0xfe, 0x18, 0x3d, 0x72, 0x6e, 0xb9, 0xd7, 0xb5, - 0x8c, 0xe9, 0xa7, 0x9f, 0x9d, 0x72, 0xf6, 0x56, 0xc3, 0x40, 0x01, 0x7a, 0xd7, 0x81, 0x58, 0xb3, 0x9b, 0xfc, 0xb1, - 0x0f, 0x78, 0x65, 0xb8, 0x9a, 0xa8, 0x67, 0x0c, 0xfb, 0x4d, 0x63, 0xb9, 0x02, 0x42, 0xa8, 0xa4, 0xe2, 0x9d, 0xb9, - 0x67, 0xd2, 0x01, 0x08, 0x47, 0x85, 0xb4, 0xd2, 0x6f, 0xbf, 0xbd, 0x1e, 0xfe, 0xe7, 0x77, 0x88, 0x4d, 0x3e, 0x73, - 0x85, 0x17, 0xf4, 0xb5, 0x5a, 0x8b, 0x53, 0x9f, 0xe6, 0x10, 0xd5, 0xfb, 0x6c, 0x2c, 0xc2, 0x82, 0x88, 0xad, 0x95, - 0x0f, 0x6f, 0x44, 0xa8, 0x27, 0xc8, 0x3f, 0x60, 0x08, 0x5f, 0xed, 0x21, 0x2c, 0xef, 0x50, 0x84, 0x08, 0xd0, 0x7e, - 0x59, 0x7d, 0x7b, 0x0c, 0xb9, 0x74, 0x6b, 0x69, 0x01, 0x94, 0x01, 0xe2, 0x1e, 0x3a, 0x3b, 0xf5, 0xb8, 0xf0, 0x15, - 0xc8, 0x8f, 0xb4, 0x77, 0x00, 0xd3, 0x9c, 0xc5, 0x73, 0x66, 0x07, 0xf1, 0xc1, 0x3d, 0x1b, 0x59, 0xde, 0x22, 0x20, - 0xf9, 0x32, 0xca, 0xdd, 0x34, 0xa2, 0xfc, 0xa4, 0x82, 0x96, 0xe8, 0xeb, 0xbc, 0x00, 0x65, 0x5c, 0x00, 0x0a, 0x7e, - 0x7a, 0x67, 0xe5, 0x00, 0x7e, 0xb6, 0x08, 0x18, 0x5f, 0xc6, 0xf2, 0xe7, 0x14, 0x87, 0x4f, 0x84, 0xdc, 0x2b, 0x1e, - 0xac, 0x78, 0x32, 0x51, 0x83, 0xee, 0xd9, 0xe5, 0xef, 0x4b, 0xa8, 0x14, 0x7b, 0x36, 0x5e, 0xd0, 0x97, 0xea, 0x9f, - 0x90, 0x3f, 0x21, 0xa7, 0x2d, 0x8f, 0xcf, 0x08, 0xe7, 0xb9, 0x16, 0xbc, 0x4f, 0x82, 0xe4, 0x29, 0x55, 0xe2, 0x88, - 0xa2, 0x1a, 0x18, 0x7a, 0x03, 0x69, 0xf2, 0x64, 0x30, 0x20, 0x3c, 0x56, 0x45, 0x67, 0x00, 0xa5, 0x86, 0xe0, 0xf9, - 0x30, 0xd9, 0x0c, 0x1a, 0x5a, 0xe4, 0xc1, 0x85, 0x8d, 0xaa, 0xd3, 0xa9, 0x8f, 0xf1, 0xc0, 0x13, 0xfb, 0xab, 0xb4, - 0x03, 0x61, 0x67, 0xf1, 0x85, 0x05, 0x04, 0x2e, 0xfa, 0xa9, 0xe0, 0x71, 0xed, 0x6b, 0x42, 0xd9, 0x56, 0xe8, 0x3d, - 0xc4, 0x8a, 0x66, 0x9d, 0x3b, 0xd9, 0x5f, 0x62, 0xe9, 0x95, 0x70, 0x6e, 0xab, 0x9d, 0x24, 0x19, 0x80, 0xbc, 0x7e, - 0x9a, 0xd4, 0x88, 0xe1, 0xbb, 0x0e, 0x93, 0x5a, 0xb7, 0x3c, 0x19, 0xc4, 0x8e, 0x79, 0x71, 0xd0, 0x4a, 0x2f, 0xf1, - 0xdc, 0xe7, 0xa7, 0x07, 0x30, 0x3f, 0x08, 0x0c, 0x50, 0xa2, 0x8c, 0x02, 0x03, 0xa2, 0x0f, 0x78, 0x29, 0x59, 0x07, - 0x5c, 0x8c, 0x05, 0x51, 0x87, 0x9c, 0xa3, 0x8c, 0x0e, 0x5a, 0xaa, 0x52, 0x27, 0x56, 0x9c, 0x66, 0x2a, 0x6f, 0x77, - 0xc0, 0xfe, 0x5f, 0x97, 0x18, 0xad, 0x3f, 0xef, 0x67, 0x4c, 0xf8, 0xdd, 0x5e, 0x66, 0x1b, 0x5c, 0x73, 0x37, 0x55, - 0x21, 0x82, 0x75, 0x4b, 0x85, 0x62, 0x1f, 0x6f, 0xab, 0x55, 0x90, 0x46, 0xb2, 0xda, 0xc2, 0x6b, 0xe9, 0x4f, 0x71, - 0xc7, 0xd7, 0x6a, 0x63, 0x29, 0xd4, 0xbb, 0xcc, 0x06, 0x50, 0x55, 0x08, 0xdb, 0xbd, 0xc5, 0x82, 0x2a, 0x1b, 0xfd, - 0xd3, 0x03, 0xe2, 0x3b, 0xcf, 0x68, 0x87, 0x9d, 0x9d, 0x82, 0x75, 0x21, 0x2d, 0xba, 0xb7, 0x58, 0xf0, 0x25, 0xa5, - 0x5f, 0xf4, 0xe6, 0x60, 0x96, 0xcd, 0xc3, 0xb3, 0xff, 0x03, 0x30, 0x11, 0x13, 0xf1, 0xb7, 0x59, 0x03, 0x00}; + 0x1e, 0x7f, 0xc7, 0xc7, 0x6c, 0x61, 0x3c, 0x35, 0xef, 0x6e, 0x16, 0x93, 0xc1, 0xe0, 0xce, 0x3f, 0xdc, 0xf3, 0x70, + 0x76, 0x37, 0x67, 0x6f, 0xf9, 0x3d, 0x2d, 0xa6, 0x89, 0x6a, 0x7a, 0xf1, 0x98, 0xe0, 0x75, 0xe7, 0xfb, 0x13, 0x8b, + 0xff, 0xd5, 0xbe, 0x68, 0xde, 0xf9, 0x03, 0x69, 0x8d, 0x96, 0xbb, 0xfa, 0xfb, 0xc7, 0x15, 0x13, 0x77, 0x20, 0x5e, + 0xbc, 0xb7, 0x35, 0x0d, 0x6f, 0xf8, 0x47, 0xef, 0xad, 0x3f, 0x7d, 0xab, 0x63, 0x6e, 0x26, 0xea, 0x48, 0x7a, 0x73, + 0xf5, 0x8c, 0xfd, 0xca, 0x3f, 0xc9, 0xe3, 0xe4, 0x9d, 0x90, 0x93, 0xf6, 0x16, 0xb9, 0x9b, 0xe8, 0x94, 0xf8, 0xe2, + 0x26, 0x12, 0x16, 0x04, 0xc2, 0x70, 0xd4, 0xfc, 0x61, 0x52, 0x4e, 0xbd, 0x3d, 0x70, 0xbb, 0x72, 0x5b, 0xff, 0x7c, + 0xc7, 0x39, 0x5f, 0x0c, 0xaf, 0xa7, 0x5f, 0xba, 0x5d, 0x7a, 0x54, 0x34, 0x9b, 0x0a, 0x74, 0xbb, 0xc3, 0xd8, 0xab, + 0xb3, 0x99, 0x65, 0x2e, 0xf9, 0xd2, 0x97, 0xda, 0xcc, 0x3c, 0xa6, 0xf7, 0x9b, 0x69, 0x86, 0x44, 0xbe, 0x40, 0xc8, + 0x74, 0x3c, 0xae, 0x2e, 0xb1, 0x3c, 0x3e, 0x7c, 0xf3, 0xf4, 0xc9, 0xe0, 0x09, 0x46, 0x6e, 0x59, 0xd1, 0x20, 0x5f, + 0xf8, 0x30, 0xab, 0x5b, 0xb7, 0x8d, 0xab, 0x67, 0xc3, 0x5f, 0x20, 0x6f, 0xd0, 0xf5, 0xd0, 0x14, 0xd1, 0x2a, 0xbf, + 0xa3, 0xe8, 0x33, 0x25, 0x07, 0x1d, 0x4f, 0xa0, 0x76, 0x48, 0x81, 0xfb, 0xe5, 0x29, 0x07, 0xfd, 0x06, 0x96, 0xda, + 0xef, 0x5f, 0x7e, 0x22, 0x1e, 0x69, 0x18, 0xef, 0x1f, 0xc2, 0xe8, 0x8f, 0xb8, 0x2c, 0x36, 0x70, 0xba, 0x0e, 0xe0, + 0x73, 0x4f, 0xf5, 0xed, 0x6b, 0xe5, 0xfb, 0x7e, 0xe0, 0xed, 0xf8, 0x2d, 0xfb, 0xc2, 0xbd, 0xeb, 0xe1, 0x1b, 0xff, + 0xe9, 0x13, 0x10, 0x9d, 0x60, 0x5c, 0x3e, 0x63, 0x24, 0x6c, 0x47, 0x31, 0x6a, 0x15, 0x7e, 0xae, 0x21, 0x44, 0xeb, + 0x13, 0x32, 0x76, 0x41, 0xfa, 0x07, 0x05, 0xe8, 0x27, 0x04, 0x56, 0x93, 0xd4, 0x28, 0x30, 0x89, 0xef, 0x6a, 0x48, + 0x20, 0x05, 0x0b, 0x84, 0xde, 0x40, 0xf1, 0xa9, 0xe0, 0x5f, 0x86, 0x9f, 0x49, 0xf2, 0x5b, 0xd4, 0x7c, 0x0c, 0x7f, + 0xc3, 0xd0, 0x4c, 0xaa, 0x87, 0xb4, 0x8e, 0x12, 0xef, 0x27, 0xff, 0x10, 0x85, 0x95, 0x50, 0xc7, 0x42, 0x90, 0x8a, + 0x21, 0x17, 0xe2, 0xea, 0xd9, 0xe4, 0xae, 0x14, 0xe1, 0x1f, 0x13, 0x7c, 0x26, 0x17, 0x9a, 0x7c, 0x46, 0x4f, 0x1a, + 0xf9, 0xfe, 0x83, 0x7c, 0x5f, 0x76, 0x6a, 0xb0, 0xa8, 0x87, 0xfc, 0xae, 0x76, 0xdf, 0x97, 0x53, 0x82, 0x1e, 0xd9, + 0x0f, 0x68, 0x0a, 0x06, 0x6a, 0x02, 0x52, 0x86, 0xe0, 0x0e, 0xae, 0xfa, 0x9e, 0x2a, 0xc8, 0x97, 0xdf, 0xfb, 0x2c, + 0x64, 0xb8, 0xca, 0x82, 0x90, 0xe4, 0x52, 0x21, 0x85, 0x8d, 0xbb, 0x7a, 0xf0, 0x59, 0x63, 0x92, 0x48, 0xc8, 0x29, + 0x01, 0x49, 0xd2, 0xde, 0x40, 0x92, 0x88, 0xe9, 0x3f, 0x5c, 0x27, 0x4d, 0xb3, 0x96, 0xd2, 0x0d, 0x71, 0xaa, 0xbe, + 0x45, 0x9a, 0xb3, 0xe0, 0x3d, 0x83, 0xa5, 0x23, 0xc5, 0x8a, 0x2f, 0xc6, 0x60, 0xac, 0x83, 0x85, 0x56, 0xb2, 0xb8, + 0x5f, 0x25, 0x61, 0x1a, 0x89, 0x2a, 0xef, 0x84, 0xfc, 0xf9, 0x4f, 0x25, 0xfe, 0xe8, 0x2d, 0x0d, 0x44, 0x20, 0xf8, + 0x01, 0x5a, 0x0f, 0x58, 0xe3, 0xc1, 0x4f, 0xac, 0x2e, 0xc3, 0xbc, 0xca, 0xa8, 0xbc, 0xd9, 0x9e, 0xed, 0xe6, 0x4c, + 0x55, 0x2d, 0xf8, 0x2c, 0x0c, 0x2d, 0xda, 0xc5, 0xba, 0x39, 0xbb, 0xcd, 0x1b, 0x7c, 0x67, 0x92, 0x44, 0x6a, 0x29, + 0x89, 0xb4, 0xd5, 0xf5, 0xe9, 0xd2, 0xeb, 0x16, 0x15, 0x34, 0x46, 0x80, 0x5e, 0x92, 0xee, 0x2a, 0x9f, 0x50, 0xbc, + 0xb2, 0x1a, 0x56, 0xc3, 0x4b, 0x87, 0x22, 0x8c, 0xb5, 0x37, 0xe7, 0xf2, 0xec, 0x0e, 0xac, 0x47, 0x68, 0xed, 0xca, + 0xd5, 0x21, 0x6c, 0x3f, 0xd1, 0x7b, 0x4e, 0xae, 0xfe, 0x06, 0x54, 0x81, 0x73, 0x47, 0x43, 0x7d, 0xd2, 0x4e, 0x21, + 0xdb, 0x79, 0xb0, 0x24, 0xa8, 0x4a, 0xc9, 0x4d, 0xb9, 0x16, 0xa5, 0x94, 0x29, 0x5f, 0xcb, 0x6c, 0x65, 0xf7, 0xc9, + 0x00, 0xe2, 0xd9, 0xa0, 0x40, 0x72, 0x51, 0x5b, 0xcd, 0x41, 0xfa, 0x68, 0x96, 0x38, 0xd6, 0x0e, 0x0a, 0x2f, 0xcb, + 0xc1, 0xcc, 0x65, 0x2e, 0x97, 0x83, 0x82, 0x55, 0x7a, 0xab, 0x99, 0x66, 0xaa, 0x2f, 0x2a, 0x7b, 0x9b, 0xf1, 0x32, + 0xfd, 0x37, 0x4b, 0x06, 0x3c, 0xba, 0x7a, 0xe6, 0x07, 0x90, 0x26, 0x79, 0x1d, 0x20, 0x09, 0x36, 0x07, 0xbb, 0xd8, + 0x61, 0xd8, 0x2a, 0x56, 0xf6, 0xe4, 0xf9, 0x72, 0x87, 0xa6, 0x5c, 0xc2, 0x48, 0x4e, 0xcc, 0xa5, 0xd4, 0xf7, 0x25, + 0xd5, 0x0d, 0x05, 0x27, 0x9b, 0x26, 0xa0, 0x14, 0xd0, 0x6e, 0xc1, 0x7f, 0xe1, 0x53, 0x43, 0xa7, 0x05, 0x58, 0x6a, + 0xbb, 0x01, 0xff, 0x85, 0x7e, 0xb1, 0x7d, 0x44, 0xfd, 0xc0, 0x3c, 0x38, 0x98, 0xb5, 0x95, 0x31, 0x20, 0x22, 0x71, + 0x05, 0x79, 0x24, 0xf8, 0x41, 0xb1, 0xa7, 0xcb, 0xc4, 0x81, 0x33, 0xc5, 0xc5, 0x52, 0x6a, 0x33, 0xf3, 0xda, 0x6f, + 0xa9, 0x89, 0x37, 0x51, 0x12, 0x15, 0xb6, 0x43, 0x1a, 0xbd, 0xa4, 0x8c, 0xa9, 0x82, 0x0d, 0xd1, 0x7d, 0xdd, 0x04, + 0x53, 0xe0, 0x4d, 0x55, 0x05, 0x44, 0xa8, 0xbd, 0xc8, 0xf2, 0xfc, 0xa6, 0x0b, 0xac, 0x2e, 0xf8, 0xd4, 0x98, 0x66, + 0x17, 0xac, 0xe4, 0x6a, 0x26, 0x7d, 0xe6, 0xed, 0x40, 0x0b, 0x79, 0x97, 0x97, 0x45, 0x2b, 0x74, 0x3d, 0x88, 0x16, + 0xfe, 0x41, 0x73, 0x3c, 0x7a, 0xb6, 0xad, 0xa6, 0x36, 0xfb, 0x5a, 0x8b, 0x05, 0x32, 0x10, 0x0d, 0x7d, 0xa1, 0x62, + 0x14, 0xee, 0x2a, 0xcd, 0xd5, 0x6a, 0x5f, 0x95, 0x41, 0x02, 0x13, 0x41, 0xd6, 0xb2, 0xf0, 0x1e, 0xdd, 0xab, 0x47, + 0x9a, 0x57, 0x12, 0x3c, 0x73, 0xf1, 0x17, 0x00, 0x42, 0x79, 0x92, 0x90, 0x03, 0x72, 0x00, 0x7f, 0x4b, 0x51, 0x2a, + 0x0d, 0xf0, 0xcf, 0xea, 0x72, 0x6c, 0xeb, 0xfb, 0x3b, 0xad, 0x62, 0x70, 0xfd, 0xf9, 0xba, 0xeb, 0x59, 0x3b, 0xc4, + 0x39, 0xb7, 0xd5, 0x6b, 0xcb, 0x34, 0x8f, 0x91, 0xba, 0x06, 0xe0, 0x4e, 0xa4, 0x47, 0x20, 0x92, 0x99, 0x68, 0x90, + 0xb3, 0xe7, 0x7c, 0x3c, 0x15, 0x8f, 0x49, 0x7b, 0xb9, 0xef, 0x9b, 0x0b, 0x7d, 0x30, 0xc6, 0xbe, 0x05, 0x0d, 0xe2, + 0xa3, 0xd5, 0xd6, 0x0a, 0xc4, 0x7a, 0xa7, 0xd4, 0x87, 0x6e, 0x8c, 0x82, 0x0e, 0x1e, 0x71, 0x23, 0x17, 0x1c, 0xdb, + 0x5d, 0x5b, 0x4f, 0xe9, 0x2b, 0x00, 0x73, 0x1d, 0xa8, 0x64, 0x18, 0xa4, 0x2e, 0x13, 0x85, 0x49, 0x7e, 0x99, 0x90, + 0x84, 0x88, 0xea, 0x6c, 0x39, 0x4a, 0x95, 0x69, 0x01, 0x97, 0x19, 0x19, 0x60, 0x36, 0x69, 0xd6, 0x4f, 0x2e, 0x5f, + 0x62, 0x18, 0x01, 0xf1, 0x33, 0xfa, 0xb1, 0x56, 0x89, 0x97, 0x8c, 0xee, 0x1c, 0x75, 0x83, 0x2a, 0xc9, 0x5c, 0xbf, + 0xb9, 0x9d, 0x45, 0xca, 0xbc, 0x60, 0xb8, 0x5d, 0xa5, 0xf9, 0x87, 0xb0, 0x4e, 0xf0, 0xdb, 0x00, 0x95, 0xf4, 0xa9, + 0xf0, 0xa2, 0x11, 0x40, 0xa8, 0xef, 0x55, 0x19, 0x9f, 0x0a, 0x2f, 0x1b, 0xed, 0x58, 0x46, 0x29, 0x54, 0x17, 0xcc, + 0x6e, 0x4d, 0x17, 0xa2, 0x5b, 0x55, 0x03, 0x6d, 0xe0, 0xda, 0x15, 0x52, 0xba, 0x81, 0x6a, 0x57, 0x6e, 0x58, 0x80, + 0x68, 0x33, 0x11, 0x18, 0x2e, 0xff, 0x3e, 0x7f, 0xa9, 0x62, 0x78, 0xfa, 0xfd, 0xd0, 0x3b, 0xec, 0x82, 0x68, 0xb4, + 0xbb, 0x66, 0xfb, 0x20, 0x1a, 0xed, 0xaf, 0x1b, 0x46, 0xbf, 0x9f, 0xd1, 0xef, 0x67, 0x0d, 0xe8, 0x48, 0x84, 0x09, + 0xb3, 0xd7, 0x6f, 0xd4, 0xf2, 0x95, 0x5a, 0xbf, 0x53, 0xcb, 0x97, 0x6a, 0x78, 0xeb, 0x40, 0x12, 0x41, 0x64, 0xa9, + 0x6a, 0x1e, 0x24, 0x45, 0xaa, 0xa5, 0xcb, 0x31, 0x5a, 0x8c, 0xa8, 0xa5, 0xac, 0x39, 0xd5, 0x89, 0xb4, 0x73, 0x50, + 0x32, 0xc0, 0xd1, 0xe2, 0xaa, 0xc6, 0x74, 0xb3, 0xa2, 0x25, 0x10, 0x23, 0xac, 0x6c, 0xcb, 0xc5, 0x4d, 0xea, 0xa3, + 0x2b, 0xf2, 0x6d, 0xcb, 0x95, 0x6f, 0x5b, 0xc1, 0xab, 0xaf, 0x28, 0x94, 0x4b, 0xae, 0x95, 0xed, 0xd3, 0x42, 0x29, + 0x94, 0x71, 0x0d, 0xb6, 0xf6, 0x4d, 0x60, 0xc8, 0x7c, 0xa4, 0xa8, 0xb1, 0xbd, 0x68, 0x94, 0x43, 0x90, 0xad, 0x83, + 0x51, 0xa7, 0x2c, 0x58, 0x7c, 0xbb, 0x43, 0x06, 0x32, 0xd0, 0x51, 0xd5, 0xc6, 0xab, 0x9d, 0x95, 0xfe, 0xb0, 0xbc, + 0x7a, 0xc6, 0x12, 0x2b, 0x9d, 0xfc, 0xa6, 0x42, 0x7f, 0x10, 0xa2, 0x6f, 0xca, 0x96, 0x83, 0x17, 0x5d, 0x6c, 0x65, + 0x40, 0xbc, 0x61, 0x7a, 0x6f, 0x6b, 0x25, 0xcb, 0x5d, 0x53, 0xbe, 0x98, 0xf1, 0x84, 0xe3, 0xe8, 0xcb, 0xd5, 0x22, + 0xac, 0xd5, 0x22, 0x3b, 0x01, 0x1e, 0x5a, 0xab, 0xa5, 0x90, 0xab, 0x45, 0x38, 0x33, 0x5d, 0xa8, 0x99, 0x9e, 0x81, + 0xe6, 0x51, 0xa8, 0x59, 0x9e, 0x00, 0x16, 0xbc, 0x30, 0x33, 0x5c, 0x98, 0x19, 0x8e, 0x43, 0x6a, 0x9c, 0x1e, 0xf4, + 0x5e, 0xe7, 0x9e, 0x5b, 0xee, 0x46, 0xa7, 0x61, 0xde, 0x4e, 0x36, 0x98, 0xd3, 0x83, 0x70, 0x02, 0xf1, 0x81, 0x25, + 0x02, 0xf4, 0x68, 0x58, 0x1d, 0x35, 0x54, 0x8e, 0xe2, 0xcb, 0x02, 0x90, 0x2c, 0x09, 0x40, 0xf2, 0xa0, 0xc6, 0xb9, + 0xb4, 0xfc, 0xba, 0x4a, 0x42, 0x8e, 0xc8, 0x78, 0x29, 0xed, 0xee, 0x09, 0x2f, 0x47, 0x46, 0x68, 0x9e, 0x2c, 0x52, + 0xaf, 0x62, 0x19, 0x1b, 0x23, 0x70, 0x51, 0xe8, 0x37, 0x79, 0xbf, 0x9f, 0x96, 0x5e, 0x45, 0xed, 0xfc, 0x04, 0xfe, + 0x96, 0xe7, 0xce, 0x22, 0x47, 0xc8, 0xab, 0x91, 0x49, 0x58, 0x5e, 0x2a, 0xf5, 0xf4, 0x25, 0xcc, 0xa0, 0xee, 0xde, + 0x28, 0x00, 0xd7, 0x42, 0x39, 0xd5, 0x96, 0x70, 0x65, 0xaa, 0x0c, 0xf6, 0x79, 0xc8, 0x65, 0x68, 0x87, 0x44, 0x1e, + 0x29, 0xac, 0xfb, 0xf6, 0xd5, 0xb3, 0x89, 0xeb, 0xc3, 0x62, 0xa3, 0x11, 0x1c, 0x8f, 0x00, 0x73, 0x30, 0xf5, 0xa2, + 0x01, 0x2f, 0xd5, 0x9c, 0xf9, 0xe8, 0x55, 0x84, 0x8d, 0x01, 0x6a, 0x8a, 0x81, 0x53, 0xd6, 0x53, 0xf9, 0xc8, 0xf8, + 0x96, 0xf9, 0x7e, 0x80, 0xef, 0xd6, 0x85, 0x84, 0x7c, 0x50, 0xa8, 0x04, 0x99, 0x42, 0x25, 0x48, 0x0c, 0x2a, 0x41, + 0x6c, 0x50, 0x09, 0xb6, 0x0d, 0xdf, 0x48, 0xe5, 0x6d, 0x04, 0x1c, 0x11, 0x3e, 0xf4, 0x2c, 0x6c, 0xac, 0x50, 0x3c, + 0x1b, 0xb3, 0x31, 0x2b, 0xd4, 0xce, 0x53, 0xc9, 0xa9, 0xd8, 0x59, 0x8c, 0x75, 0x13, 0x59, 0x26, 0x5e, 0x48, 0xd0, + 0x71, 0xce, 0x85, 0x44, 0x5d, 0xfd, 0xdc, 0x7b, 0x49, 0xc6, 0x92, 0x79, 0x43, 0xa3, 0x06, 0xf3, 0xb2, 0xeb, 0x00, + 0xa6, 0x25, 0xdf, 0x16, 0x34, 0x98, 0x4e, 0x95, 0x47, 0xa4, 0x49, 0x50, 0x3b, 0x97, 0x49, 0x91, 0x13, 0xc2, 0x24, + 0xe8, 0x95, 0xe0, 0x37, 0x12, 0xda, 0xff, 0xab, 0x9e, 0xef, 0x80, 0xc1, 0x44, 0xab, 0xe4, 0x0b, 0x58, 0x2d, 0x2b, + 0xfe, 0x42, 0x7a, 0x62, 0x23, 0xfe, 0x62, 0x99, 0xc6, 0xa3, 0x2f, 0x6c, 0x88, 0x78, 0x56, 0x2f, 0xd0, 0xb4, 0x04, + 0x75, 0x80, 0x47, 0xf4, 0xd7, 0xe8, 0x8b, 0xe1, 0x4d, 0xe9, 0x6a, 0xa4, 0xae, 0xd9, 0x25, 0xe7, 0xef, 0x6a, 0x43, + 0x84, 0x8c, 0x69, 0x53, 0x20, 0x19, 0x10, 0x48, 0x32, 0x10, 0x00, 0x98, 0x9a, 0xce, 0xec, 0x15, 0x40, 0x34, 0x10, + 0xc0, 0xe3, 0xaa, 0xe3, 0xf1, 0x23, 0xfd, 0x55, 0x9c, 0xf6, 0x4e, 0xd3, 0xb0, 0xc3, 0x17, 0xa0, 0x29, 0x86, 0x72, + 0x3c, 0xdf, 0x29, 0x48, 0xf6, 0x28, 0x65, 0xe9, 0xaa, 0x89, 0xec, 0x50, 0xac, 0x4f, 0x73, 0xce, 0x42, 0xda, 0x96, + 0x63, 0xb4, 0xc5, 0xfa, 0x31, 0xf2, 0xde, 0xca, 0xa8, 0xc8, 0x07, 0x3d, 0xb8, 0xbd, 0xbd, 0x79, 0xd5, 0x63, 0x36, + 0xc9, 0x8a, 0x45, 0xae, 0x22, 0xce, 0x9c, 0xd6, 0x21, 0x07, 0x0c, 0xc8, 0x49, 0x08, 0x4c, 0x63, 0x5c, 0x2a, 0xd0, + 0x41, 0xc9, 0x72, 0x59, 0x03, 0xb5, 0x2c, 0x22, 0x6b, 0x80, 0xa8, 0xa6, 0xf9, 0x57, 0x0d, 0xf9, 0x49, 0xde, 0x9c, + 0x53, 0xa8, 0x7d, 0xc5, 0xc3, 0xea, 0xfc, 0x89, 0x55, 0x9b, 0x18, 0xeb, 0x5f, 0x6b, 0x4f, 0xd0, 0x56, 0xd2, 0x40, + 0x7c, 0xe7, 0xab, 0x74, 0x45, 0xa1, 0x3b, 0xce, 0x4c, 0x3c, 0x57, 0x81, 0xb1, 0x6f, 0xed, 0x08, 0x0a, 0x87, 0xa6, + 0xeb, 0x80, 0xc3, 0x34, 0x3a, 0x61, 0xf1, 0x4f, 0xe9, 0x38, 0x79, 0x55, 0x2b, 0x44, 0x92, 0xbf, 0x0b, 0x17, 0x86, + 0xc4, 0x82, 0xbc, 0x24, 0xd4, 0x11, 0x19, 0xb1, 0x1a, 0x15, 0x1b, 0xa1, 0xa2, 0xe2, 0x14, 0x8f, 0xb7, 0x0a, 0x8a, + 0x4b, 0x51, 0xaa, 0x94, 0x8a, 0xdc, 0xa8, 0x14, 0x10, 0xcb, 0x06, 0xde, 0x2d, 0xe0, 0x00, 0x08, 0x3a, 0xcb, 0xfd, + 0xc6, 0x76, 0xb7, 0x91, 0xf9, 0xcc, 0x34, 0x4f, 0xab, 0x0f, 0xea, 0xef, 0xf7, 0x4b, 0x8c, 0xad, 0xf1, 0xf4, 0xf7, + 0x6d, 0x5a, 0x70, 0xf3, 0x37, 0x0c, 0xd1, 0x0a, 0x10, 0x31, 0x4b, 0x7b, 0x28, 0x64, 0xc1, 0x84, 0x65, 0xa8, 0xca, + 0x53, 0x8e, 0x7a, 0xd5, 0xe4, 0x0e, 0x20, 0xd4, 0xd0, 0xaf, 0x8d, 0x4e, 0x75, 0x55, 0x82, 0xf0, 0x7d, 0x57, 0xa8, + 0xc7, 0xe6, 0x80, 0x27, 0x03, 0xe0, 0xaf, 0xc8, 0x6b, 0x3d, 0xb6, 0x7f, 0xd0, 0x1b, 0xf5, 0x06, 0x08, 0xa2, 0x73, + 0x59, 0xf8, 0x27, 0x9c, 0xeb, 0xd4, 0x9f, 0x71, 0x21, 0x88, 0x6f, 0x3d, 0x09, 0xef, 0xc5, 0x45, 0x1a, 0x07, 0x17, + 0xbd, 0x81, 0xb9, 0x08, 0x14, 0x17, 0x69, 0x7e, 0x01, 0x61, 0xf9, 0x88, 0x89, 0x58, 0xb3, 0x15, 0xc0, 0x04, 0x96, + 0x3a, 0x0e, 0x59, 0x75, 0x6c, 0xbf, 0xff, 0x7a, 0x64, 0xc8, 0xd2, 0x11, 0x06, 0x46, 0xff, 0x06, 0x14, 0xa1, 0x12, + 0x96, 0x99, 0xed, 0xc1, 0xa4, 0xab, 0x3d, 0xab, 0xe7, 0xcd, 0x36, 0xef, 0xea, 0x1d, 0xab, 0x69, 0x15, 0x35, 0x2d, + 0xb7, 0x9a, 0x36, 0xa9, 0xa0, 0x66, 0xa2, 0xdf, 0xd7, 0xa0, 0xa8, 0xd5, 0x1c, 0xc0, 0xd8, 0x30, 0xf9, 0xf5, 0x2c, + 0x9f, 0xf7, 0xfb, 0x9e, 0x7c, 0x04, 0xbf, 0x90, 0xad, 0xcc, 0xad, 0xb1, 0x7c, 0xfa, 0x8a, 0x48, 0xcc, 0x0c, 0xcc, + 0xd1, 0xea, 0x04, 0xdf, 0xeb, 0x56, 0x78, 0x1d, 0x73, 0x85, 0xcd, 0xc4, 0xf4, 0x35, 0x0c, 0x9e, 0x27, 0x7c, 0x70, + 0x91, 0xa3, 0xbf, 0x91, 0xc3, 0x4c, 0x61, 0x41, 0xce, 0xfd, 0xc9, 0x6b, 0xc4, 0x4b, 0x46, 0x78, 0x07, 0x9d, 0x4e, + 0x78, 0x90, 0xfd, 0xfe, 0x1a, 0x3a, 0xb3, 0x95, 0x4a, 0xd9, 0xaa, 0xa8, 0x4c, 0x37, 0x75, 0x51, 0x56, 0xd0, 0xb1, + 0xf4, 0xf3, 0x4e, 0xc8, 0xcc, 0xfa, 0x99, 0x05, 0xf7, 0xb4, 0x96, 0x00, 0x53, 0xb6, 0x6d, 0xa2, 0x36, 0xf0, 0xb2, + 0x2e, 0x3e, 0x17, 0x78, 0x74, 0xd6, 0x5e, 0x6f, 0x84, 0xda, 0x67, 0xb8, 0xcf, 0x6f, 0x3c, 0xf0, 0x83, 0x99, 0xa5, + 0x73, 0x45, 0x9c, 0x51, 0xf9, 0xa3, 0xcf, 0x45, 0x9a, 0x53, 0x1e, 0xe0, 0x3e, 0x14, 0x73, 0xfb, 0x2d, 0x90, 0x7e, + 0xe8, 0x2d, 0x90, 0x7d, 0x74, 0xce, 0xc9, 0x6b, 0x40, 0xa4, 0x43, 0x18, 0xdc, 0x9c, 0x04, 0x1d, 0xab, 0x86, 0x77, + 0x16, 0xd8, 0x69, 0x2f, 0x8d, 0x7b, 0x69, 0x7e, 0x91, 0xf6, 0xfb, 0x06, 0x35, 0x33, 0x45, 0x38, 0x78, 0x9c, 0x91, + 0x8b, 0xa4, 0x05, 0x5b, 0x4a, 0xfb, 0xaf, 0x06, 0x8e, 0xa8, 0x10, 0xa0, 0xf9, 0xef, 0xc2, 0x7b, 0x02, 0x10, 0x9b, + 0xb4, 0x01, 0x57, 0x3d, 0xa6, 0xa3, 0xb1, 0x25, 0x51, 0xab, 0xce, 0x06, 0x48, 0x9c, 0x2a, 0xad, 0xa7, 0xdc, 0xac, + 0x29, 0x0c, 0x52, 0x65, 0xa1, 0x7e, 0x63, 0x3d, 0x99, 0xac, 0x72, 0x91, 0x11, 0x47, 0x65, 0x7a, 0x57, 0x33, 0x82, + 0xe9, 0xd2, 0xcf, 0x17, 0xb0, 0x64, 0xe3, 0x8f, 0x38, 0x79, 0x4b, 0xc0, 0xb1, 0x9d, 0xb5, 0xab, 0x6a, 0x97, 0xe3, + 0xd6, 0x6e, 0x0e, 0xf0, 0xbd, 0xde, 0x68, 0x34, 0xd2, 0xce, 0x71, 0x02, 0x86, 0xaa, 0xa7, 0x96, 0x42, 0x8f, 0xd5, + 0x0a, 0x50, 0xb7, 0x23, 0x97, 0x59, 0x32, 0x98, 0x2f, 0x8c, 0xe3, 0x97, 0xe6, 0xa3, 0x8f, 0x97, 0xca, 0xda, 0x75, + 0xc4, 0xd7, 0x7f, 0x94, 0xd5, 0xfa, 0x96, 0x77, 0x55, 0x13, 0xf0, 0x45, 0x15, 0x50, 0xfa, 0x0d, 0xef, 0xc9, 0xde, + 0xc5, 0xd7, 0x6e, 0xb1, 0x4b, 0xbe, 0xe5, 0x2d, 0xea, 0x3c, 0x5f, 0x39, 0xb8, 0x51, 0xa5, 0xdb, 0x7b, 0xc9, 0x02, + 0xd7, 0xde, 0x49, 0xd3, 0x58, 0xcf, 0xfc, 0xe8, 0x61, 0x11, 0xb2, 0x9d, 0x8f, 0xbd, 0xaf, 0x9a, 0xa7, 0x67, 0x0d, + 0xbd, 0x49, 0x0d, 0x7d, 0xec, 0x45, 0xd9, 0x3e, 0x35, 0x8d, 0xe8, 0x35, 0x6c, 0xe8, 0x63, 0x6f, 0xc9, 0xc9, 0x21, + 0x11, 0xe0, 0xd4, 0x98, 0x3f, 0x3e, 0x9c, 0xce, 0xf0, 0x77, 0x0c, 0xa8, 0x04, 0x62, 0x3e, 0x3f, 0xa6, 0x1d, 0x05, + 0x98, 0x51, 0xa5, 0xb7, 0xcf, 0x0f, 0x6c, 0xc7, 0xcb, 0x7a, 0x68, 0xe9, 0xdd, 0xb3, 0xa3, 0xdb, 0xf1, 0xaa, 0x1a, + 0x5f, 0xca, 0x21, 0xcf, 0xf3, 0xd9, 0x68, 0x34, 0x12, 0x06, 0x92, 0x3b, 0xd7, 0x1b, 0x58, 0x81, 0xb4, 0x2d, 0xaa, + 0x0f, 0xe5, 0xd2, 0xdb, 0xab, 0x43, 0x3b, 0xf7, 0x27, 0xd5, 0xf1, 0x58, 0x8c, 0xcc, 0x31, 0x9e, 0xfb, 0xc7, 0x63, + 0xa1, 0xe4, 0x28, 0x59, 0x4b, 0x10, 0x9d, 0xd2, 0x78, 0x2a, 0xeb, 0xb5, 0x13, 0x91, 0x57, 0x23, 0xce, 0x43, 0xf0, + 0x57, 0x2f, 0x67, 0xa5, 0xfe, 0x54, 0xf8, 0xe8, 0xa7, 0x4a, 0xe9, 0x05, 0xaf, 0x0a, 0x08, 0x11, 0xfb, 0xbb, 0x81, + 0x76, 0x50, 0x82, 0x43, 0x09, 0xf7, 0x1e, 0xaf, 0x93, 0xaf, 0xbc, 0x6a, 0x26, 0x63, 0x94, 0x7b, 0x83, 0x7c, 0xce, + 0x00, 0xa6, 0xd2, 0x67, 0xe0, 0x77, 0x09, 0x50, 0xa7, 0xf8, 0x14, 0x9d, 0xea, 0xcd, 0xc3, 0xa6, 0xeb, 0xd3, 0x12, + 0x45, 0x11, 0xdd, 0xf9, 0xf9, 0x18, 0x10, 0x3b, 0xbb, 0x36, 0x23, 0xed, 0xda, 0x6f, 0xd0, 0x60, 0x95, 0x26, 0xad, + 0x95, 0x53, 0xc2, 0x6e, 0x57, 0x23, 0x5b, 0xfa, 0x51, 0x0a, 0xc4, 0xca, 0x71, 0x22, 0x91, 0x3d, 0xd8, 0xc8, 0x09, + 0xdc, 0xa2, 0xbd, 0xa3, 0x03, 0x50, 0xb9, 0x51, 0x90, 0x5f, 0xcd, 0x89, 0xdc, 0xf1, 0x7d, 0xef, 0xfb, 0x41, 0x3d, + 0xf8, 0xbe, 0x77, 0x91, 0x92, 0xdc, 0x11, 0x5e, 0xa8, 0x29, 0x21, 0xe2, 0x8b, 0xef, 0x07, 0xd5, 0x00, 0xcf, 0x12, + 0x2d, 0xd2, 0x22, 0xa1, 0x5a, 0x5d, 0xe3, 0x26, 0xbc, 0x48, 0x24, 0xf7, 0xd0, 0xbe, 0xf3, 0x88, 0x58, 0x00, 0x32, + 0x16, 0x9f, 0xcd, 0x1b, 0x0a, 0x75, 0x37, 0x31, 0x5b, 0x74, 0x97, 0xc5, 0x7e, 0x7f, 0x93, 0xa7, 0x75, 0x4f, 0xc7, + 0xc7, 0xe0, 0x0b, 0x52, 0x4d, 0x80, 0x47, 0xfb, 0x2b, 0x73, 0xbc, 0x7a, 0xb5, 0x39, 0x52, 0x16, 0xaa, 0x44, 0xfd, + 0x16, 0xab, 0x59, 0x0f, 0x61, 0xb8, 0xb3, 0xcc, 0x58, 0xdb, 0x0b, 0x9e, 0xcb, 0x59, 0x15, 0xdb, 0xe5, 0xf8, 0x8a, + 0xa5, 0x36, 0x97, 0xa8, 0x1c, 0xad, 0xc7, 0xda, 0x14, 0x23, 0xbf, 0x52, 0x48, 0x94, 0x45, 0xc7, 0xd6, 0x42, 0x01, + 0xf1, 0x02, 0xf4, 0x25, 0x7b, 0xd3, 0x00, 0xeb, 0x8d, 0x5e, 0x45, 0x84, 0x96, 0x8f, 0x54, 0x78, 0x9b, 0x9b, 0x2a, + 0xb3, 0xb2, 0x59, 0xb4, 0xfb, 0x29, 0xe7, 0x39, 0x82, 0xd5, 0x1b, 0xb5, 0x47, 0x01, 0x6a, 0x0f, 0x2d, 0x94, 0x01, + 0xa4, 0x34, 0xcd, 0x00, 0x90, 0x01, 0x40, 0xa6, 0x8a, 0xf8, 0x4c, 0x80, 0x4a, 0x5b, 0xdd, 0x28, 0x70, 0x22, 0xbd, + 0x02, 0x9a, 0x05, 0x56, 0xfa, 0x48, 0x41, 0x06, 0x8b, 0x2d, 0x02, 0xb0, 0x72, 0xe4, 0x0c, 0xd3, 0x18, 0xb2, 0x8d, + 0x26, 0x2e, 0x49, 0xf3, 0xfb, 0x30, 0x4b, 0x25, 0x9e, 0xc4, 0x8f, 0xb2, 0xc6, 0x08, 0x00, 0xa4, 0xef, 0xd3, 0x8b, + 0x22, 0x8b, 0x09, 0x07, 0xce, 0x7a, 0xea, 0xa0, 0xa8, 0xc9, 0xb9, 0xd6, 0xb4, 0x7a, 0x56, 0x9b, 0x3c, 0x64, 0x81, + 0xce, 0x1e, 0x8c, 0x49, 0x2d, 0xdf, 0xf3, 0xc8, 0xfe, 0xca, 0xe9, 0x8c, 0xf0, 0x5d, 0x77, 0x70, 0xea, 0xbf, 0xdb, + 0x1a, 0x98, 0x98, 0x12, 0x80, 0x8d, 0xc1, 0xd1, 0x84, 0xf8, 0x9d, 0x8e, 0xc9, 0xd4, 0x26, 0x45, 0x20, 0xf0, 0x10, + 0xbc, 0x82, 0xeb, 0x0b, 0x19, 0x30, 0x20, 0x68, 0x3b, 0x8b, 0x3c, 0x4d, 0x00, 0x4e, 0xbc, 0xe0, 0x3b, 0x80, 0xe3, + 0xd4, 0xab, 0x42, 0xf6, 0xec, 0xa5, 0x98, 0xce, 0xe6, 0xc1, 0x43, 0x42, 0xfb, 0x17, 0x13, 0x7e, 0xd3, 0x5d, 0x25, + 0x57, 0xa6, 0xd6, 0xbd, 0x89, 0xae, 0x72, 0x95, 0xd3, 0xa7, 0x39, 0xc7, 0x30, 0x67, 0xb0, 0x0a, 0xc8, 0x39, 0x1b, + 0xf2, 0xe7, 0x97, 0x00, 0xd8, 0xb2, 0x16, 0x5e, 0xc4, 0x9f, 0x87, 0xb2, 0x5a, 0x00, 0xf7, 0xc8, 0x79, 0x64, 0x7e, + 0xf9, 0x6a, 0x3b, 0x94, 0x73, 0x8a, 0xc2, 0x58, 0xce, 0x4d, 0x4b, 0x8a, 0xd3, 0xa1, 0xa7, 0x60, 0x32, 0xb5, 0xe5, + 0xef, 0x5d, 0xe2, 0x32, 0x7b, 0x33, 0x09, 0xe7, 0xeb, 0xc8, 0xb6, 0xb5, 0xea, 0x1e, 0xba, 0x21, 0x18, 0xf4, 0x31, + 0x82, 0x96, 0xd5, 0x9b, 0x5f, 0x31, 0x18, 0x28, 0x6c, 0xdf, 0x9a, 0x6e, 0x5a, 0x74, 0x8a, 0x03, 0xce, 0xac, 0x75, + 0x8d, 0x4a, 0x55, 0x71, 0xe8, 0x25, 0xef, 0x96, 0x95, 0xdb, 0x65, 0xe9, 0x85, 0x20, 0x35, 0xea, 0x2a, 0x42, 0xa4, + 0x54, 0xec, 0xf0, 0x9e, 0xfc, 0x1a, 0x98, 0x78, 0x66, 0xe5, 0x28, 0x8d, 0xe7, 0x00, 0x13, 0xa4, 0xd0, 0x37, 0xe5, + 0x57, 0x80, 0x1b, 0xba, 0x88, 0xc2, 0xec, 0x4d, 0x5c, 0x05, 0xb5, 0xd5, 0xf4, 0x7b, 0x07, 0x27, 0xf6, 0xb2, 0xee, + 0xf7, 0x53, 0xa2, 0xf1, 0xc3, 0xd0, 0x0b, 0xfc, 0x7b, 0x3c, 0x3d, 0x34, 0x41, 0x6a, 0x5e, 0x79, 0x80, 0x57, 0x74, + 0xb9, 0xb5, 0x29, 0x57, 0x34, 0x2e, 0xe6, 0x35, 0x22, 0xc2, 0xa7, 0x8e, 0x62, 0xbb, 0xcd, 0x8f, 0x53, 0x1b, 0x83, + 0x41, 0x08, 0xf7, 0xad, 0x8c, 0xdf, 0x27, 0x5e, 0x35, 0x8b, 0xe6, 0xa0, 0x28, 0xcd, 0x34, 0x49, 0x48, 0x21, 0xbd, + 0x04, 0xe8, 0xa3, 0x41, 0xa8, 0xd5, 0x95, 0x7f, 0x24, 0x5e, 0xaa, 0xa6, 0xb5, 0x79, 0x8a, 0x35, 0x0a, 0xc4, 0x2c, + 0x9a, 0x37, 0x2c, 0xa3, 0x43, 0x52, 0x5d, 0x2e, 0x4d, 0x33, 0xfe, 0xb0, 0x9a, 0xa1, 0x5a, 0x71, 0xd2, 0x04, 0x35, + 0x4a, 0xb7, 0x70, 0x01, 0xfc, 0x1b, 0xdd, 0x71, 0x54, 0xa3, 0x48, 0xd1, 0x80, 0x4f, 0x20, 0xa6, 0xab, 0x30, 0x9b, + 0x27, 0xac, 0x35, 0x75, 0xcd, 0xe8, 0xf7, 0x65, 0x9c, 0x90, 0x49, 0x42, 0x72, 0x3e, 0x5c, 0xae, 0x1f, 0x49, 0x75, + 0x01, 0xa4, 0xca, 0x39, 0x9b, 0xf5, 0x7a, 0x73, 0xc0, 0xe8, 0x85, 0xf5, 0x0b, 0x1b, 0x57, 0x70, 0x79, 0x4d, 0x98, + 0xbb, 0xea, 0x47, 0x98, 0x65, 0x50, 0x05, 0xa4, 0xf9, 0xb1, 0xa0, 0xd3, 0x2b, 0x17, 0x88, 0xfa, 0xf5, 0x48, 0x5d, + 0x50, 0x66, 0xe9, 0xdc, 0x22, 0x02, 0x01, 0xaf, 0x61, 0xf5, 0x04, 0x92, 0x7d, 0xf9, 0xd8, 0xa7, 0x19, 0x05, 0xaa, + 0x23, 0x00, 0x65, 0xb3, 0x7e, 0x08, 0xfb, 0x07, 0x84, 0x13, 0xea, 0x6f, 0xde, 0xca, 0x59, 0x43, 0xf2, 0x40, 0xaa, + 0x09, 0x8f, 0xe1, 0xd4, 0x58, 0xe0, 0x4b, 0x8b, 0xde, 0x54, 0xf0, 0x9a, 0xe0, 0xb8, 0x17, 0x68, 0xed, 0x5b, 0xc0, + 0x11, 0x22, 0xb8, 0x0c, 0x4d, 0x9c, 0xf6, 0xf6, 0xbd, 0x00, 0x09, 0xcd, 0x2d, 0x9c, 0xeb, 0xb7, 0x2e, 0x68, 0x71, + 0x8a, 0x9c, 0x2c, 0xba, 0xc0, 0x40, 0x17, 0x64, 0xde, 0xf8, 0x67, 0x0e, 0x2b, 0x17, 0x20, 0x7b, 0xa9, 0x58, 0x49, + 0xc4, 0xb6, 0x57, 0x7f, 0x94, 0xca, 0x7e, 0x7b, 0x61, 0x4d, 0xe0, 0x97, 0x89, 0xfd, 0x12, 0x99, 0x7c, 0xd3, 0x53, + 0x93, 0xaf, 0x8c, 0x85, 0x4e, 0x2d, 0x83, 0x73, 0x7a, 0x62, 0x70, 0xee, 0xed, 0xad, 0xda, 0x94, 0x30, 0x14, 0x24, + 0x81, 0xa6, 0x4b, 0x0f, 0xeb, 0xa6, 0x3f, 0x3f, 0x69, 0xf1, 0x6b, 0xd5, 0xbe, 0x75, 0x3f, 0x0e, 0xb1, 0x8b, 0x5f, + 0x26, 0x9e, 0x61, 0x1f, 0xf5, 0x81, 0x03, 0x4c, 0x46, 0x4c, 0x5c, 0xf7, 0xfb, 0x50, 0xd8, 0x6c, 0x3c, 0x1f, 0xd5, + 0xc5, 0xcf, 0xc5, 0x03, 0x40, 0x39, 0x54, 0x60, 0x97, 0x43, 0x19, 0xca, 0x88, 0x4d, 0x6d, 0xb9, 0xe7, 0xf7, 0x97, + 0x61, 0x0e, 0xf2, 0x8e, 0xc6, 0xc4, 0xb9, 0x00, 0x31, 0x0c, 0xbe, 0xfe, 0xfd, 0x93, 0x43, 0xda, 0x7c, 0x7f, 0x01, + 0xdf, 0x1d, 0x5d, 0x7c, 0x40, 0x8e, 0x9b, 0x8b, 0x4d, 0x59, 0xdc, 0xa7, 0xb1, 0xb8, 0xf8, 0x1e, 0x52, 0xbf, 0xbf, + 0x28, 0xca, 0x8b, 0xef, 0x55, 0x65, 0xbe, 0xbf, 0xa0, 0x05, 0x37, 0xfa, 0xdd, 0x9a, 0x78, 0xff, 0xc8, 0x35, 0xed, + 0xd9, 0x12, 0xc2, 0xb1, 0xb4, 0xfa, 0x11, 0x94, 0x88, 0x8a, 0x14, 0x55, 0x86, 0xb2, 0x5a, 0x3b, 0xce, 0xfb, 0x44, + 0xc3, 0x63, 0xd3, 0x84, 0xc4, 0xd5, 0x12, 0xd6, 0xa1, 0x9e, 0x9d, 0x36, 0xc9, 0x8e, 0xf3, 0x40, 0x1d, 0x10, 0x15, + 0x7f, 0x5e, 0x8d, 0x76, 0xf4, 0x35, 0xf8, 0xd6, 0xf1, 0x58, 0x8d, 0xf6, 0xe6, 0xa7, 0x4f, 0xd6, 0x4a, 0x19, 0x6c, + 0xa4, 0x18, 0x85, 0x90, 0x28, 0x6e, 0xd7, 0x63, 0x00, 0xfc, 0xef, 0x1f, 0x8f, 0xf4, 0x7b, 0x2f, 0x7f, 0xab, 0xdd, + 0xd2, 0xaa, 0xe7, 0x87, 0x16, 0x61, 0xc6, 0xab, 0xda, 0xb0, 0xb3, 0x1d, 0x24, 0xa0, 0xf4, 0xa1, 0x69, 0x50, 0x53, + 0x44, 0x3f, 0x61, 0x35, 0xb1, 0x9c, 0xc3, 0x82, 0x94, 0x38, 0xc4, 0x70, 0x8c, 0x76, 0xe8, 0x71, 0xba, 0xa8, 0x79, + 0x2a, 0xdf, 0x21, 0xe3, 0xd6, 0xf7, 0x01, 0xc9, 0xa5, 0x70, 0xf9, 0xc1, 0x0b, 0x0d, 0x26, 0x7a, 0x91, 0x57, 0x45, + 0x26, 0x46, 0x82, 0x46, 0xf9, 0x0d, 0x89, 0x33, 0x17, 0x58, 0x8b, 0x0b, 0x85, 0x10, 0x16, 0x12, 0x2a, 0x77, 0x51, + 0x52, 0x7a, 0x70, 0xf1, 0xe4, 0x50, 0x36, 0xbf, 0x13, 0x26, 0xc4, 0x68, 0x01, 0x34, 0x38, 0xfb, 0x76, 0x79, 0x0f, + 0x61, 0x99, 0x7b, 0xbf, 0xbf, 0x59, 0xe5, 0x05, 0xc4, 0x65, 0x5e, 0x48, 0xc5, 0x6a, 0x79, 0x01, 0x34, 0x79, 0x22, + 0xbe, 0x08, 0x2b, 0x39, 0x0d, 0xaa, 0x8e, 0x62, 0xd5, 0x36, 0x5e, 0x56, 0x1e, 0xf0, 0x7a, 0xbf, 0x4f, 0x80, 0xc0, + 0xdd, 0x67, 0xaf, 0x95, 0x5b, 0x2a, 0xe9, 0x91, 0xe7, 0x18, 0x22, 0x99, 0x00, 0xaf, 0x33, 0x04, 0x47, 0x0a, 0xab, + 0xe7, 0x26, 0xc8, 0x3f, 0xbe, 0x39, 0xa3, 0xf8, 0xa2, 0x79, 0x14, 0x35, 0x2c, 0x64, 0x09, 0x1c, 0x0f, 0xc9, 0x2c, + 0x9b, 0x23, 0x35, 0x79, 0xda, 0x9e, 0x22, 0x1d, 0x9d, 0x58, 0xe2, 0xb7, 0x35, 0xa9, 0x5e, 0xa4, 0xc2, 0x2e, 0x69, + 0x67, 0x2b, 0x2a, 0x2f, 0x84, 0xa1, 0x4a, 0xb8, 0xf7, 0xaa, 0x9e, 0x85, 0x72, 0x53, 0xb4, 0x2a, 0x66, 0x0f, 0x53, + 0x62, 0x86, 0x29, 0xd6, 0x5f, 0xd8, 0xf2, 0xdb, 0xc4, 0x8b, 0xc1, 0x70, 0xbd, 0xe4, 0xe5, 0x6c, 0x6b, 0x16, 0xc2, + 0xf1, 0xb8, 0x9d, 0x14, 0xb3, 0x25, 0xc4, 0xb6, 0x2e, 0xe7, 0xc7, 0x63, 0x57, 0xcb, 0x36, 0xc2, 0x83, 0x87, 0xaa, + 0x85, 0xdb, 0x86, 0x55, 0xf0, 0x33, 0x99, 0xc5, 0xd8, 0xbe, 0xc6, 0x67, 0xf6, 0xe7, 0x8b, 0xee, 0x59, 0x82, 0x8c, + 0x1b, 0x1b, 0xe0, 0x1a, 0x9b, 0xb5, 0x3b, 0x5c, 0x8d, 0x80, 0xe4, 0x71, 0x37, 0xfa, 0xbb, 0xb2, 0x93, 0x9c, 0x04, + 0x09, 0xa3, 0x15, 0xc2, 0xef, 0xa1, 0xf1, 0x27, 0x5a, 0xec, 0x41, 0xbb, 0x8d, 0x2d, 0x21, 0xaa, 0x69, 0xcf, 0xe5, + 0x4a, 0xb1, 0x34, 0x6f, 0xa5, 0x0d, 0x99, 0x0f, 0xeb, 0xf3, 0xd0, 0xc8, 0x81, 0x82, 0x31, 0xe2, 0xa9, 0x75, 0x10, + 0xcd, 0xe6, 0xc0, 0x7d, 0x81, 0xe6, 0x11, 0x9e, 0x5a, 0x90, 0xa0, 0xcc, 0xda, 0xb0, 0x9f, 0x24, 0x67, 0xcb, 0xe3, + 0xf0, 0x2d, 0xfc, 0xcb, 0x67, 0xd8, 0x24, 0xa6, 0x28, 0x1e, 0x7f, 0xcb, 0x15, 0xff, 0x1d, 0x5b, 0x10, 0xc1, 0xda, + 0xad, 0xa8, 0x0d, 0x7f, 0xc3, 0xbf, 0x84, 0x7d, 0x84, 0xfd, 0x96, 0xe3, 0x4d, 0xd2, 0x10, 0x90, 0x09, 0xc4, 0x85, + 0x85, 0x20, 0xc1, 0xdf, 0x72, 0xc9, 0x3f, 0x27, 0x7c, 0xb6, 0x28, 0x81, 0xac, 0x0e, 0xa3, 0xf8, 0x84, 0x62, 0xa2, + 0x10, 0x86, 0x5b, 0x42, 0xef, 0xe8, 0xbf, 0x11, 0x25, 0xd9, 0xa4, 0xb2, 0x62, 0x3d, 0x90, 0x49, 0x12, 0x4c, 0xb0, + 0xf2, 0x42, 0xf9, 0xc2, 0xbd, 0x50, 0x6a, 0xad, 0x05, 0xad, 0x5f, 0xfe, 0x24, 0xf1, 0x0c, 0xe8, 0x1e, 0xc8, 0x18, + 0x74, 0x1b, 0x51, 0x4d, 0x72, 0x4c, 0x1f, 0xa5, 0xf3, 0x0c, 0x54, 0x40, 0x17, 0x9b, 0x2c, 0xac, 0x97, 0x45, 0xb9, + 0x6e, 0x85, 0x87, 0xca, 0xd2, 0x47, 0xea, 0x31, 0xe6, 0x85, 0x79, 0x72, 0x26, 0x1f, 0x3c, 0x02, 0x34, 0x3c, 0xca, + 0xd3, 0xaa, 0xa3, 0xb4, 0x7e, 0x60, 0x19, 0x30, 0x02, 0x67, 0xca, 0x80, 0x47, 0x58, 0x06, 0xe6, 0x69, 0x97, 0xa1, + 0x06, 0xb1, 0x46, 0xd5, 0x95, 0xda, 0x60, 0xce, 0x14, 0x25, 0x9f, 0x62, 0x69, 0x85, 0x31, 0x34, 0x75, 0xe5, 0x91, + 0xf5, 0x92, 0x13, 0xf6, 0x6c, 0x37, 0x90, 0x6e, 0x61, 0xab, 0xc0, 0x05, 0x5d, 0xcb, 0x12, 0xe5, 0xa2, 0x5b, 0x46, + 0x94, 0x89, 0x90, 0xfa, 0xd9, 0xc3, 0x99, 0x56, 0xfb, 0x8d, 0x9d, 0x74, 0x68, 0x8f, 0x14, 0xbd, 0x60, 0x20, 0x3e, + 0xed, 0x91, 0x52, 0xcf, 0x1a, 0xb9, 0x0c, 0x6c, 0xe9, 0x52, 0xd5, 0xf3, 0x5f, 0xa0, 0x7c, 0x07, 0x33, 0xe3, 0x6c, + 0xf6, 0xbb, 0xde, 0xdc, 0x9e, 0x1c, 0xea, 0xe6, 0x77, 0xd6, 0xeb, 0xc1, 0xd6, 0x20, 0x13, 0x5f, 0x28, 0xea, 0x29, + 0xab, 0x10, 0x2b, 0x32, 0xfb, 0x5f, 0xc2, 0xfb, 0x1d, 0xde, 0x1a, 0xa1, 0x59, 0x19, 0x0f, 0xf3, 0xd1, 0x93, 0x83, + 0x68, 0x7e, 0xef, 0x2c, 0xdb, 0xca, 0x55, 0xc9, 0x6c, 0xbf, 0x9f, 0x24, 0xcd, 0xd9, 0xe3, 0x35, 0x92, 0x3a, 0xc0, + 0xc7, 0xeb, 0x33, 0x7c, 0xa4, 0x12, 0x4a, 0x2d, 0xa8, 0x6a, 0xd0, 0xfa, 0xd8, 0xef, 0xad, 0xe7, 0xf4, 0xf1, 0x53, + 0x39, 0xdd, 0x92, 0x22, 0x8c, 0x1f, 0x18, 0x4c, 0xd9, 0x89, 0x53, 0x97, 0xaa, 0x19, 0xd2, 0xbb, 0x6e, 0x95, 0xd4, + 0x65, 0x8f, 0x12, 0x41, 0xa8, 0x83, 0xf5, 0x8b, 0xfd, 0x10, 0x66, 0xb6, 0xe8, 0x0f, 0x9b, 0xd5, 0x9c, 0x50, 0x10, + 0x01, 0xa2, 0x55, 0xde, 0x07, 0x4e, 0x49, 0xc2, 0xac, 0xb9, 0x21, 0xdd, 0x7a, 0x2b, 0xa5, 0xbd, 0x92, 0x02, 0xfa, + 0x65, 0x7e, 0x3c, 0xa2, 0xf9, 0xcd, 0xec, 0x5c, 0x95, 0xb4, 0xe5, 0x00, 0x22, 0x75, 0xde, 0xb4, 0x2f, 0x1d, 0x0e, + 0xfe, 0x83, 0xba, 0x12, 0xe5, 0x44, 0xd0, 0x51, 0xb4, 0x60, 0xb4, 0x5a, 0xb5, 0xab, 0xc8, 0xa6, 0x42, 0xb6, 0x24, + 0xc2, 0x89, 0x92, 0xbd, 0x12, 0xea, 0xa3, 0x5c, 0xed, 0x99, 0x86, 0xf8, 0x33, 0x01, 0x9b, 0x36, 0xf8, 0x5b, 0xe0, + 0x5e, 0x06, 0x67, 0xa6, 0x7d, 0x1a, 0x46, 0x40, 0x64, 0x0e, 0xc1, 0x7e, 0x7e, 0xd7, 0x83, 0x1c, 0x1e, 0x74, 0xa4, + 0xbf, 0xaa, 0x67, 0x05, 0x9e, 0xb9, 0x67, 0x9e, 0xbf, 0x3e, 0x93, 0x9e, 0x57, 0xf0, 0x40, 0x73, 0x1f, 0x66, 0xfc, + 0x45, 0x59, 0x86, 0xfb, 0xd1, 0xb2, 0x2c, 0xd6, 0x5e, 0xa4, 0xf7, 0xf1, 0x4c, 0x8a, 0x81, 0x44, 0x87, 0x99, 0xd1, + 0x55, 0xac, 0xe3, 0x1c, 0xc6, 0xbd, 0x3d, 0x09, 0x2b, 0xb4, 0x7f, 0x96, 0xd8, 0xeb, 0x02, 0x00, 0x1c, 0xb2, 0x06, + 0xad, 0xf0, 0x4e, 0xb7, 0xb7, 0x7b, 0x5c, 0x52, 0xa2, 0xb8, 0x51, 0xf3, 0xb3, 0x1a, 0x5a, 0x26, 0xa8, 0x65, 0xd6, + 0x9d, 0x4c, 0xa6, 0x48, 0x02, 0xdf, 0x86, 0xbd, 0x66, 0x79, 0x35, 0x6f, 0xe4, 0xf6, 0xf0, 0x2e, 0x5c, 0x8b, 0x58, + 0x5b, 0xd0, 0x49, 0x47, 0xc6, 0xe1, 0x5e, 0x68, 0x6e, 0xa4, 0x87, 0x27, 0x55, 0x12, 0x96, 0x22, 0x86, 0x5b, 0x20, + 0x3b, 0xa8, 0x6d, 0x25, 0x28, 0x81, 0x04, 0xf6, 0x43, 0x29, 0x96, 0xe9, 0x4e, 0x00, 0x98, 0x03, 0xff, 0x53, 0x1a, + 0xbb, 0xdd, 0x9d, 0x87, 0x78, 0xd5, 0xc8, 0xfb, 0x06, 0x21, 0xd8, 0x5f, 0x81, 0x9c, 0x06, 0x0c, 0x22, 0xc5, 0x48, + 0x16, 0x0c, 0x24, 0x00, 0x15, 0xdf, 0x80, 0x49, 0x6e, 0x5a, 0x79, 0x7e, 0x50, 0xe9, 0x0e, 0xa6, 0x7d, 0xd0, 0xbd, + 0xb8, 0xd6, 0x0c, 0x90, 0x7f, 0x27, 0x11, 0xff, 0x5b, 0xed, 0x95, 0xac, 0x62, 0x99, 0xdf, 0x98, 0x8b, 0x4e, 0x06, + 0x57, 0x0d, 0xe1, 0x17, 0xb3, 0x6c, 0xce, 0xa3, 0x59, 0xa6, 0x43, 0xfd, 0x8b, 0xe6, 0xa4, 0x14, 0xc0, 0x50, 0xc7, + 0x0b, 0xb0, 0xc6, 0xbb, 0xd2, 0x4d, 0x2b, 0x1e, 0x69, 0x8c, 0x51, 0x50, 0xa1, 0x83, 0xd0, 0xdf, 0x6a, 0x80, 0xd7, + 0x60, 0x92, 0x1b, 0x21, 0xf7, 0xc1, 0x05, 0xdd, 0xd0, 0x2d, 0xe7, 0x2e, 0x41, 0x4d, 0xaa, 0x96, 0x5f, 0x85, 0x50, + 0xef, 0x6a, 0xc9, 0xa5, 0xda, 0x7c, 0x6a, 0x94, 0x35, 0x82, 0x4c, 0x8e, 0xd2, 0xef, 0x53, 0x2e, 0xdc, 0xdc, 0x98, + 0xac, 0x8f, 0x47, 0xaf, 0xe0, 0xa6, 0xc6, 0x3f, 0x56, 0x92, 0x45, 0xd4, 0x1a, 0x12, 0x61, 0x6b, 0xb7, 0x42, 0xf7, + 0x1e, 0x37, 0x4a, 0xf3, 0x28, 0xdb, 0xc6, 0xa2, 0xf2, 0x7a, 0x09, 0x58, 0x8b, 0x7b, 0x40, 0x86, 0x4a, 0x4b, 0x3f, + 0x67, 0x05, 0x40, 0x06, 0x48, 0x61, 0xe3, 0x47, 0xa4, 0xbd, 0xfa, 0xe0, 0xa5, 0x7e, 0xbf, 0x6f, 0x4c, 0xf9, 0xef, + 0x1f, 0x72, 0x60, 0x26, 0x14, 0x65, 0xbd, 0x87, 0x09, 0x54, 0x79, 0xa9, 0x4f, 0xda, 0xb3, 0x9a, 0x3f, 0xdf, 0xd4, + 0x1e, 0x90, 0x5a, 0xf9, 0x16, 0x73, 0xd5, 0x2b, 0xfb, 0x62, 0x73, 0x48, 0xab, 0x5b, 0xa3, 0x71, 0x10, 0x2c, 0xad, + 0xde, 0x68, 0x95, 0x43, 0xd5, 0xf0, 0x1c, 0x44, 0x2a, 0xeb, 0xea, 0x9a, 0x3b, 0x57, 0xd7, 0x82, 0x23, 0x81, 0x6c, + 0xc9, 0x21, 0x2c, 0x8d, 0x85, 0xdc, 0x2b, 0x8f, 0xc7, 0xc2, 0xef, 0xf7, 0xd3, 0x59, 0x8e, 0x97, 0x16, 0xa0, 0x4c, + 0xdb, 0xd4, 0x5e, 0xe8, 0x1f, 0x8f, 0x3f, 0x82, 0xd7, 0x88, 0x7f, 0x3c, 0x96, 0xfd, 0xfe, 0x47, 0x73, 0x93, 0xb9, + 0x1c, 0x2b, 0xa5, 0xec, 0x35, 0x2a, 0xdd, 0xdf, 0x24, 0xbc, 0xf7, 0xbf, 0x47, 0xff, 0x7b, 0x74, 0xdd, 0x53, 0x01, + 0x60, 0x09, 0x9f, 0xe1, 0x0d, 0x9d, 0xa9, 0xcb, 0x39, 0x93, 0xee, 0xee, 0xca, 0x0f, 0xbd, 0xa7, 0xf1, 0xe1, 0x7b, + 0x73, 0xd3, 0xc6, 0x5f, 0xf3, 0x13, 0x4d, 0x42, 0xc7, 0x45, 0xff, 0x78, 0xfc, 0x94, 0x68, 0x7d, 0x5a, 0xaa, 0xf4, + 0x69, 0x0a, 0x3c, 0xc9, 0xb0, 0xe1, 0xba, 0x85, 0xe9, 0x68, 0x7e, 0xdc, 0x7c, 0x95, 0xbc, 0x38, 0x4b, 0xe1, 0xda, + 0x0b, 0x3a, 0x97, 0x29, 0x58, 0x57, 0x86, 0xe0, 0x66, 0x10, 0x40, 0xea, 0x10, 0xd2, 0xac, 0x69, 0xf8, 0x97, 0xdc, + 0x15, 0xbc, 0xb5, 0xc7, 0xbb, 0xc1, 0x88, 0x52, 0x47, 0xfa, 0xa4, 0x0d, 0xa1, 0x4b, 0x2a, 0xf9, 0x8f, 0x22, 0x8f, + 0x31, 0x66, 0xe3, 0x15, 0x91, 0x7d, 0x16, 0xf9, 0xcb, 0x02, 0x00, 0x8b, 0x00, 0x01, 0x39, 0x9d, 0x3b, 0x92, 0xf8, + 0xcf, 0xc9, 0xb7, 0x7f, 0x4c, 0x97, 0xf6, 0xa1, 0x2c, 0x56, 0xa5, 0xa8, 0xaa, 0x93, 0xd2, 0xf6, 0xb6, 0x5c, 0x0f, + 0xf4, 0xa1, 0xfd, 0xbe, 0xa4, 0x0f, 0x4d, 0x31, 0x14, 0x05, 0x6e, 0x8d, 0xbd, 0x69, 0xca, 0x15, 0x4d, 0xf5, 0xc8, + 0x58, 0x3f, 0x7f, 0xd8, 0xbf, 0x89, 0xbd, 0xd4, 0x0f, 0x52, 0x10, 0x84, 0x35, 0x7e, 0x52, 0x8a, 0x24, 0x70, 0x3e, + 0xc3, 0x54, 0xe2, 0xd3, 0xa5, 0x54, 0xf9, 0xc3, 0x48, 0xf3, 0x61, 0x0a, 0x7a, 0xd9, 0xbf, 0xe7, 0x30, 0xff, 0x75, + 0x7b, 0xb0, 0x3e, 0xad, 0xcb, 0x34, 0xaa, 0x88, 0x2a, 0x2f, 0x4c, 0xb5, 0x09, 0x44, 0xf0, 0xe7, 0xc2, 0x22, 0xf9, + 0xf5, 0xc9, 0x91, 0xa0, 0x31, 0x93, 0xe5, 0xe3, 0x89, 0xfb, 0x85, 0x7d, 0xe5, 0x3a, 0x9d, 0xff, 0x95, 0x99, 0xff, + 0x03, 0x8c, 0x49, 0x28, 0x9e, 0x73, 0xcb, 0x60, 0x81, 0xb3, 0x5f, 0xba, 0x7a, 0xc0, 0xdf, 0xcc, 0x13, 0xcf, 0x81, + 0x83, 0xf9, 0x39, 0xba, 0x2a, 0xa6, 0xb3, 0x62, 0x00, 0x04, 0xb6, 0x7e, 0x63, 0xcd, 0x89, 0xd7, 0x16, 0xcf, 0x95, + 0x5c, 0x10, 0xfa, 0xba, 0x0a, 0xb3, 0x71, 0x5d, 0x6c, 0x2b, 0x51, 0x6c, 0x21, 0x6c, 0x04, 0xd4, 0xb2, 0xd5, 0xb4, + 0xb6, 0x15, 0xb2, 0x3f, 0x89, 0x16, 0x6d, 0x97, 0xa1, 0x9a, 0x8c, 0xb2, 0x74, 0x33, 0x05, 0x52, 0xbd, 0x00, 0xce, + 0x22, 0xf3, 0xca, 0x3b, 0x67, 0x0f, 0xd8, 0xa1, 0xf1, 0x14, 0x18, 0x51, 0xe9, 0x8f, 0xaa, 0x31, 0x3a, 0x3d, 0xd1, + 0xef, 0x57, 0x53, 0x0a, 0xf9, 0xfa, 0x09, 0x30, 0xb9, 0x6a, 0xb9, 0x00, 0x7d, 0x19, 0xea, 0xa0, 0x12, 0xa5, 0x56, + 0x0c, 0x23, 0x16, 0x7e, 0x12, 0xc8, 0xde, 0x4c, 0x41, 0xcd, 0x2a, 0x4a, 0x42, 0x25, 0x2a, 0x25, 0x5b, 0x13, 0xd4, + 0xd2, 0xfb, 0xa2, 0xa8, 0x0f, 0x15, 0x38, 0x4a, 0x46, 0xda, 0x2c, 0xa7, 0xcc, 0xb8, 0x28, 0x73, 0xd1, 0x0f, 0xf6, + 0x2f, 0xc0, 0xf8, 0x92, 0xf9, 0x2c, 0xf7, 0x1d, 0x9d, 0xd3, 0x76, 0x5c, 0xa0, 0xcc, 0x2d, 0xa7, 0xad, 0x96, 0x3c, + 0x26, 0xef, 0x59, 0xb0, 0xed, 0xbf, 0x48, 0x90, 0x57, 0x11, 0xe6, 0x13, 0xaa, 0x6c, 0xfe, 0x9e, 0x7b, 0xc4, 0x3e, + 0xda, 0xe1, 0xc2, 0x44, 0xa4, 0xb7, 0x60, 0x49, 0x0c, 0xb3, 0x52, 0x84, 0xf1, 0x1e, 0xbc, 0x7f, 0xb6, 0x95, 0x18, + 0x5d, 0xa0, 0x93, 0xfb, 0xc5, 0x43, 0x5a, 0x27, 0x17, 0x6f, 0x5e, 0x5d, 0x7c, 0xdf, 0x1b, 0x14, 0xa3, 0x34, 0x1e, + 0xf4, 0xbe, 0xbf, 0x58, 0x6f, 0x01, 0x22, 0x53, 0x5c, 0xc4, 0x64, 0x4a, 0x13, 0xf1, 0x05, 0x19, 0x06, 0x2f, 0xea, + 0x44, 0x5c, 0xd0, 0xc4, 0x74, 0x5f, 0xa3, 0x34, 0xf9, 0x76, 0x14, 0xe6, 0xf0, 0x72, 0x29, 0xb6, 0x95, 0x88, 0xc1, + 0x4e, 0xa9, 0xe6, 0xd9, 0xc9, 0x59, 0x2c, 0x3d, 0x06, 0x5d, 0x59, 0xa5, 0x03, 0x74, 0x7b, 0x22, 0xed, 0xaa, 0x74, + 0x05, 0x84, 0x1e, 0xf0, 0xcc, 0xcf, 0xe3, 0x51, 0x24, 0x10, 0x6a, 0xc1, 0x9c, 0x4c, 0x23, 0xba, 0x21, 0xbd, 0xc4, + 0x3e, 0x03, 0xb3, 0x90, 0xd2, 0x3c, 0xb8, 0xb9, 0x5a, 0xb4, 0xdc, 0x39, 0x2b, 0x47, 0x61, 0xb5, 0x11, 0x51, 0x8d, + 0x54, 0xc7, 0xe0, 0xbc, 0x03, 0x11, 0x00, 0x8a, 0x11, 0x3c, 0xe3, 0x51, 0xbf, 0x1f, 0xa9, 0xa0, 0x9c, 0x84, 0x7e, + 0x51, 0xe8, 0x97, 0xc6, 0xa0, 0x8c, 0xf9, 0x97, 0x50, 0x13, 0x03, 0xd4, 0x3b, 0x1e, 0x2a, 0x8e, 0x00, 0x5c, 0xce, + 0x11, 0x33, 0xce, 0x7b, 0xdc, 0x45, 0xe3, 0x54, 0xbc, 0x13, 0xea, 0x3a, 0x58, 0x2a, 0xd4, 0x79, 0x53, 0x1f, 0xe9, + 0x39, 0x69, 0x12, 0x34, 0x88, 0x1b, 0x78, 0xbc, 0x1a, 0x02, 0xaa, 0xb5, 0x90, 0x7a, 0x0b, 0x9d, 0x52, 0xd5, 0x21, + 0xb0, 0x06, 0xb8, 0x44, 0x61, 0x3b, 0x61, 0x72, 0x44, 0xdb, 0xb2, 0x14, 0xf9, 0x09, 0x1b, 0xb4, 0x4b, 0x46, 0xa6, + 0x0e, 0x2e, 0x97, 0xcb, 0x89, 0xa8, 0x7f, 0xcd, 0xb7, 0x00, 0xce, 0x0b, 0xf9, 0xad, 0xdd, 0x6c, 0x99, 0x64, 0xbb, + 0xfe, 0x3f, 0xbc, 0x7d, 0x09, 0x77, 0xdb, 0x46, 0xb2, 0xee, 0x5f, 0x11, 0xf1, 0x1c, 0x06, 0x6d, 0x36, 0x29, 0x52, + 0xb1, 0x33, 0x09, 0xa8, 0x16, 0xaf, 0xe2, 0x25, 0x71, 0x26, 0x5e, 0x62, 0x39, 0x99, 0xcc, 0xf0, 0xf1, 0x2a, 0x10, + 0xd0, 0x12, 0x11, 0x43, 0x68, 0x06, 0x00, 0xb5, 0x84, 0xc4, 0x7f, 0x7f, 0xa7, 0xaa, 0x77, 0x10, 0x94, 0x3d, 0xf3, + 0xee, 0x7b, 0xc7, 0xe7, 0x58, 0x44, 0xa3, 0xd1, 0x7b, 0x57, 0x57, 0xd7, 0xf2, 0x55, 0x65, 0x63, 0x96, 0x94, 0xbc, + 0x5a, 0x89, 0xa2, 0xca, 0x6e, 0xf8, 0x4f, 0xe6, 0xa5, 0x1f, 0x40, 0x0a, 0xed, 0x48, 0x5f, 0xb7, 0xbb, 0xa3, 0xc4, + 0x38, 0xa6, 0x1c, 0xd7, 0x52, 0xe9, 0x5e, 0x8d, 0xaa, 0x13, 0x37, 0x5b, 0xe5, 0x5a, 0x66, 0x69, 0xca, 0x8b, 0x57, + 0x45, 0x9a, 0x25, 0x4e, 0x72, 0xac, 0x02, 0x54, 0xdb, 0xc8, 0x57, 0x36, 0x36, 0xf2, 0xf3, 0xac, 0xc2, 0x80, 0xc1, + 0x5e, 0xa3, 0x5a, 0xa1, 0xa6, 0x74, 0xe0, 0x0b, 0xf1, 0x1e, 0x23, 0x6e, 0xb3, 0x22, 0x01, 0x86, 0x1f, 0x13, 0xd5, + 0x25, 0x3d, 0x85, 0x28, 0x0f, 0x32, 0x1e, 0xf7, 0x73, 0x8e, 0x88, 0xd7, 0x46, 0x65, 0x0e, 0x4c, 0xb6, 0x52, 0x41, + 0x22, 0xd8, 0x5d, 0x36, 0x57, 0x8b, 0x68, 0x21, 0xef, 0x42, 0xbd, 0x78, 0xbb, 0xed, 0x25, 0x92, 0x0e, 0x58, 0xf9, + 0x69, 0xf0, 0x32, 0xce, 0x72, 0x9e, 0x1e, 0xd4, 0xe2, 0x40, 0x6e, 0xa8, 0x03, 0xe9, 0xcc, 0x01, 0x3b, 0xef, 0xcb, + 0xfa, 0x40, 0xad, 0xe9, 0x03, 0xd5, 0xce, 0x03, 0xb8, 0x60, 0xe0, 0xce, 0xbd, 0xca, 0x6e, 0x78, 0x71, 0x00, 0xca, + 0x40, 0x63, 0x3c, 0xd0, 0x54, 0xf5, 0x48, 0x4e, 0x8c, 0x0a, 0x5c, 0x9d, 0xa8, 0x83, 0x39, 0xa0, 0xdf, 0x03, 0x52, + 0x54, 0xeb, 0xed, 0x4a, 0x1d, 0xb4, 0x01, 0xfd, 0x69, 0xa9, 0xfb, 0xa0, 0xa2, 0xc5, 0xcb, 0x90, 0xc0, 0xde, 0x90, + 0x2a, 0xa4, 0x56, 0x2d, 0xab, 0x40, 0xf1, 0x86, 0xb3, 0x78, 0x77, 0xae, 0x25, 0x1b, 0xe7, 0x25, 0x02, 0x7b, 0x65, + 0x45, 0x1d, 0x67, 0xc5, 0xa9, 0x93, 0xca, 0x1b, 0xe5, 0x24, 0x53, 0x69, 0xdf, 0xb2, 0x82, 0xba, 0x3b, 0x44, 0xdf, + 0x22, 0xf5, 0x61, 0xf0, 0x22, 0xac, 0xc9, 0x8c, 0xf7, 0xfb, 0x62, 0x26, 0xa2, 0x62, 0x56, 0x1d, 0x16, 0x91, 0x44, + 0x68, 0xdb, 0x27, 0x02, 0x7a, 0x50, 0x02, 0xe4, 0x0a, 0x80, 0xea, 0x87, 0x84, 0x3f, 0x0f, 0x49, 0x7d, 0x3a, 0x85, + 0x3e, 0xa5, 0xb2, 0x5e, 0x71, 0x0a, 0xaa, 0x1b, 0x6f, 0x64, 0xbd, 0x0a, 0x5a, 0x3c, 0x96, 0x63, 0xb5, 0xa1, 0x6d, + 0x4e, 0x8d, 0x77, 0xbd, 0xde, 0x60, 0xd2, 0xe6, 0x42, 0xae, 0xc2, 0x90, 0x44, 0xb7, 0x85, 0x13, 0x3e, 0xc4, 0x60, + 0x65, 0xb5, 0x36, 0xbf, 0x8e, 0xfd, 0x91, 0x15, 0x29, 0xee, 0x67, 0x43, 0x9c, 0xbb, 0x78, 0x3c, 0xa7, 0xfa, 0x46, + 0x49, 0x8b, 0x74, 0x9b, 0xef, 0xd5, 0x65, 0x48, 0x51, 0x51, 0x4d, 0x1a, 0x55, 0x66, 0xd0, 0x7d, 0xdb, 0xbc, 0x55, + 0x3d, 0xc2, 0x04, 0x78, 0xa5, 0x32, 0xa8, 0x46, 0xe3, 0x81, 0x58, 0xd5, 0xa3, 0x72, 0x5d, 0x14, 0x88, 0x36, 0x0c, + 0x39, 0x66, 0x86, 0x90, 0x64, 0x7f, 0xf1, 0xef, 0x64, 0x70, 0x85, 0x32, 0xbe, 0xd5, 0x70, 0xde, 0xb5, 0xf1, 0xec, + 0x6e, 0x22, 0x37, 0x27, 0x16, 0xd6, 0xb8, 0x0f, 0xfe, 0x51, 0xab, 0x9d, 0x05, 0x94, 0x35, 0xad, 0x6a, 0x38, 0xdc, + 0xa3, 0x3a, 0x16, 0xa5, 0x06, 0x24, 0x76, 0xc8, 0x72, 0xd9, 0x3a, 0x66, 0xd0, 0x80, 0xfe, 0x2e, 0xbb, 0x5e, 0x5f, + 0x23, 0x6a, 0x5b, 0x81, 0xac, 0x93, 0x90, 0xfe, 0x25, 0xed, 0x51, 0x57, 0xf6, 0x54, 0xee, 0xb7, 0x6d, 0xaa, 0x1c, + 0x1a, 0x20, 0x79, 0xec, 0xe6, 0x2c, 0x90, 0x1d, 0x09, 0xa2, 0x40, 0x6e, 0xbd, 0x60, 0xea, 0x9c, 0x32, 0x65, 0x07, + 0xf2, 0x73, 0xa9, 0xcf, 0xb0, 0xcf, 0x38, 0x62, 0xf4, 0x52, 0x89, 0xc1, 0xd4, 0x47, 0x1b, 0xd5, 0xb4, 0x56, 0x80, + 0xaa, 0x9f, 0x6e, 0xe0, 0x4f, 0x54, 0x36, 0x68, 0xa8, 0x35, 0x12, 0x85, 0xa4, 0x89, 0x12, 0x3a, 0x96, 0x96, 0x2a, + 0x98, 0x42, 0x27, 0x91, 0x30, 0x04, 0x34, 0x4c, 0x88, 0x4a, 0x2a, 0xf1, 0xd6, 0x00, 0xce, 0x7c, 0xbc, 0xa8, 0xd6, + 0xa5, 0x32, 0x98, 0xfb, 0x21, 0xbe, 0xe1, 0xaf, 0x9e, 0x5b, 0xa3, 0xfa, 0x96, 0xb5, 0xbe, 0xa3, 0x05, 0xf9, 0x21, + 0xe4, 0x14, 0x1d, 0x98, 0xd8, 0xc9, 0x06, 0x0f, 0xe6, 0xa2, 0x51, 0xa1, 0x2e, 0xde, 0xaa, 0xf8, 0x2b, 0xca, 0x04, + 0xef, 0x01, 0x4f, 0x11, 0x65, 0x78, 0x58, 0x69, 0xab, 0x6a, 0x7c, 0x2a, 0x58, 0x4b, 0x0f, 0x56, 0xf2, 0x74, 0x9d, + 0xf0, 0x10, 0xf4, 0x48, 0x84, 0x9d, 0x84, 0xe5, 0x3c, 0x5e, 0xc0, 0x71, 0x52, 0x12, 0x50, 0x3b, 0xa8, 0x2b, 0xf8, + 0x7c, 0x81, 0xee, 0xaf, 0x02, 0x3d, 0xc0, 0xd0, 0x82, 0xd8, 0x0f, 0x7d, 0x3a, 0xba, 0x8e, 0x57, 0x9e, 0x8a, 0x84, + 0xcf, 0x4b, 0xb0, 0x1d, 0x92, 0xea, 0x29, 0xd0, 0x42, 0x25, 0x52, 0x3f, 0x0c, 0x7c, 0x87, 0x02, 0xbe, 0x56, 0x3a, + 0x40, 0x4d, 0x3f, 0x63, 0x9a, 0x1a, 0x67, 0xa8, 0x7c, 0xe6, 0xdc, 0x33, 0xa3, 0xe5, 0xcc, 0x80, 0x31, 0xa8, 0xdb, + 0x68, 0x8a, 0xe2, 0x9c, 0x7c, 0x16, 0x94, 0x71, 0x9a, 0xc5, 0x39, 0xf8, 0x6d, 0xc6, 0x25, 0x66, 0x4c, 0xe2, 0x9a, + 0x5f, 0x89, 0x12, 0xb4, 0xdd, 0xb9, 0x4c, 0x6d, 0x1a, 0x10, 0x90, 0xfd, 0x00, 0x56, 0x2f, 0x9e, 0x8e, 0xca, 0x7a, + 0x77, 0x29, 0x53, 0x88, 0xb2, 0x0a, 0xc1, 0xa6, 0x99, 0x2e, 0xd9, 0x69, 0x28, 0xb5, 0x39, 0x10, 0xdf, 0x08, 0x8d, + 0xfb, 0xa7, 0x61, 0x6c, 0x34, 0xc5, 0xc6, 0xee, 0x6d, 0xbb, 0xfd, 0xad, 0x70, 0xd2, 0x69, 0x4e, 0x7a, 0x8c, 0xfd, + 0x56, 0x84, 0xe5, 0xc8, 0x74, 0x84, 0xc0, 0x92, 0x73, 0x3e, 0x75, 0x5f, 0xd1, 0x62, 0x9e, 0x80, 0xe9, 0x88, 0x8a, + 0x90, 0x0b, 0x94, 0x1d, 0xa3, 0xb8, 0x03, 0x83, 0x0b, 0x66, 0x42, 0x10, 0x4b, 0x4f, 0x5d, 0x48, 0x96, 0x24, 0x65, + 0xf0, 0x3c, 0x75, 0x30, 0xe0, 0xd7, 0x4c, 0x9a, 0xbb, 0x48, 0xeb, 0xd3, 0x25, 0x99, 0xa6, 0xc8, 0x40, 0xac, 0xc3, + 0x4d, 0x96, 0x46, 0x89, 0x14, 0x91, 0x2d, 0xd1, 0x3f, 0x52, 0x53, 0x2c, 0x15, 0xae, 0x17, 0xa9, 0x12, 0xa1, 0xd5, + 0x3c, 0xc5, 0x93, 0x3a, 0x6d, 0xd2, 0x11, 0xc6, 0x9b, 0x04, 0xa5, 0x5c, 0x03, 0x03, 0x55, 0x50, 0xb5, 0x14, 0x36, + 0xe5, 0x76, 0xab, 0x2e, 0x56, 0xd5, 0x3c, 0x5e, 0xe0, 0xcb, 0x0a, 0x47, 0xf1, 0xef, 0xdc, 0x89, 0x35, 0x25, 0xb7, + 0x07, 0x35, 0x23, 0x4a, 0xe8, 0xdf, 0x39, 0x5c, 0x24, 0xbe, 0x13, 0x2a, 0xee, 0x1f, 0x5a, 0x84, 0x9c, 0xcb, 0x83, + 0x54, 0x73, 0x43, 0x3b, 0xc2, 0x7f, 0xcd, 0xf5, 0x69, 0x67, 0x74, 0x5f, 0xcd, 0xa8, 0xf0, 0x7b, 0x1d, 0x3c, 0x63, + 0xd4, 0x67, 0x03, 0x87, 0x15, 0xa2, 0xd0, 0x86, 0x9d, 0x14, 0x52, 0xb4, 0x30, 0x14, 0xf2, 0x2f, 0xa1, 0xd5, 0x09, + 0xb7, 0x66, 0x94, 0x05, 0xe3, 0xd3, 0xe2, 0xb8, 0x9a, 0x0e, 0x06, 0x05, 0xa9, 0xb5, 0x85, 0x1e, 0x5c, 0x0f, 0x1c, + 0xff, 0x1e, 0xb8, 0x85, 0x38, 0x70, 0xc8, 0xd5, 0x90, 0x6b, 0x70, 0xfc, 0x16, 0x27, 0x57, 0x8f, 0x2a, 0x19, 0xbc, + 0x9a, 0xc8, 0x16, 0xfc, 0xbd, 0x08, 0x03, 0xf4, 0x49, 0x0a, 0xc0, 0x64, 0x30, 0xe5, 0x77, 0x20, 0x51, 0x3a, 0x97, + 0x37, 0xa4, 0x5f, 0x8a, 0x92, 0x5f, 0xf2, 0x92, 0x17, 0x89, 0x2d, 0xc0, 0xf0, 0x0e, 0xa6, 0xd7, 0x51, 0x4d, 0x25, + 0x10, 0xaf, 0xee, 0x71, 0xc4, 0xb5, 0xf7, 0x9f, 0xee, 0xb1, 0x01, 0x6a, 0x35, 0x8e, 0x0d, 0x2e, 0x73, 0x0c, 0x2e, + 0xe8, 0x4a, 0x62, 0xab, 0xa9, 0x86, 0x11, 0x81, 0x81, 0x0b, 0x38, 0x08, 0x4b, 0x24, 0xc7, 0x56, 0xf1, 0x9a, 0x78, + 0x52, 0xda, 0x07, 0x86, 0xa3, 0x4d, 0x72, 0x5c, 0x9b, 0x65, 0x3b, 0x81, 0xf3, 0x45, 0xe7, 0xa4, 0xe9, 0x58, 0x36, + 0x78, 0x9f, 0xd7, 0xe7, 0xd7, 0xfe, 0x21, 0xa1, 0x32, 0xd8, 0x0d, 0x6f, 0x07, 0xbb, 0xb1, 0xc2, 0xaf, 0x79, 0xb5, + 0x50, 0xf1, 0x59, 0xf4, 0x25, 0xcb, 0x6d, 0xad, 0x73, 0x4b, 0x12, 0x4a, 0x01, 0xed, 0xb2, 0x2c, 0xa8, 0x89, 0x00, + 0x74, 0x3f, 0xfc, 0x05, 0x42, 0x67, 0xf8, 0xdb, 0x63, 0x70, 0x45, 0x0a, 0xf7, 0x0e, 0x41, 0x65, 0x4c, 0x37, 0x77, + 0x6a, 0x03, 0xbe, 0x18, 0xf7, 0x67, 0x4c, 0x1d, 0xfd, 0x36, 0x13, 0xbb, 0xba, 0x6e, 0x87, 0x2c, 0xc3, 0x47, 0xb8, + 0x52, 0x00, 0x2c, 0x13, 0xfe, 0x62, 0x6c, 0x49, 0xf9, 0x09, 0xc0, 0xa9, 0xa9, 0x88, 0x3e, 0x41, 0xa0, 0xe1, 0x94, + 0x68, 0x39, 0xba, 0x91, 0x8e, 0x68, 0x1a, 0x69, 0x4d, 0xb5, 0x42, 0x7b, 0xeb, 0x61, 0x91, 0xd6, 0x34, 0x9c, 0xb8, + 0x0f, 0x8a, 0x79, 0x95, 0x40, 0x00, 0xad, 0x8c, 0xe0, 0xad, 0xf5, 0x51, 0x1f, 0x21, 0x2e, 0x61, 0x49, 0x14, 0x61, + 0x71, 0x4c, 0xf1, 0x63, 0x42, 0x37, 0xbe, 0xb6, 0xe9, 0x03, 0xd2, 0x5f, 0x5c, 0xb3, 0x6e, 0xca, 0xb2, 0x71, 0xed, + 0xa1, 0xe2, 0xc5, 0xd4, 0x0f, 0x7e, 0x98, 0xc8, 0x62, 0xdc, 0x2f, 0x6a, 0x57, 0x6a, 0x05, 0x30, 0xcc, 0x5d, 0xf5, + 0xf4, 0xfb, 0x7e, 0xb6, 0x1c, 0x08, 0x95, 0xdb, 0x19, 0x24, 0x7d, 0x2a, 0x9e, 0x1f, 0x1c, 0xd1, 0xca, 0x42, 0xcf, + 0x1d, 0x97, 0xc6, 0x87, 0xca, 0x6b, 0x53, 0x23, 0x5a, 0x23, 0x43, 0x65, 0xea, 0x80, 0xf5, 0xfd, 0x43, 0xb8, 0xbb, + 0xa8, 0x69, 0xa8, 0x74, 0xcf, 0x5d, 0x8b, 0x82, 0x13, 0x77, 0x80, 0xb1, 0xb8, 0x90, 0x34, 0x2a, 0x08, 0x93, 0x7a, + 0x34, 0x38, 0xc9, 0x5e, 0x5d, 0x9d, 0x9c, 0x29, 0xe6, 0x09, 0x6c, 0x54, 0xcb, 0xb6, 0xbf, 0xa2, 0x54, 0x97, 0x72, + 0x73, 0x45, 0xf1, 0x3d, 0xa4, 0xcd, 0x55, 0x9c, 0xb7, 0x05, 0x17, 0xfc, 0x33, 0x05, 0x17, 0xc6, 0xc1, 0xba, 0xe3, + 0x4e, 0xd9, 0x73, 0x45, 0x99, 0xc6, 0x06, 0x77, 0xed, 0x31, 0x26, 0xda, 0x7e, 0x77, 0xc9, 0x93, 0x8f, 0xc8, 0x82, + 0x7f, 0x97, 0x15, 0xe0, 0x99, 0x6c, 0x5f, 0xc9, 0xfc, 0x3f, 0xb8, 0x57, 0x5b, 0xf3, 0xce, 0x98, 0x7f, 0x3a, 0xd6, + 0xc3, 0x9d, 0xc3, 0xe4, 0x06, 0xe8, 0x0c, 0xe8, 0xe6, 0x5a, 0xa4, 0x1c, 0x90, 0x01, 0x8c, 0x45, 0x32, 0x1a, 0xf0, + 0xa1, 0x95, 0x65, 0xdb, 0x77, 0x5a, 0x5e, 0x10, 0xf6, 0x12, 0xb8, 0xe9, 0xfe, 0xda, 0xf4, 0xcc, 0xa9, 0x5a, 0x89, + 0xa2, 0x4b, 0x63, 0x63, 0x59, 0x2a, 0x81, 0xdd, 0xf7, 0x9e, 0x64, 0xd3, 0xfc, 0x78, 0x39, 0xcd, 0x0d, 0x75, 0xdb, + 0xd8, 0x65, 0x03, 0x40, 0x88, 0x5d, 0x6b, 0x2b, 0x07, 0x90, 0xdc, 0x1e, 0x84, 0xf0, 0x35, 0x22, 0xf4, 0x54, 0x8a, + 0xd0, 0xa7, 0xa9, 0xdf, 0x07, 0xb3, 0xaa, 0xd6, 0x5e, 0x9c, 0xa3, 0x41, 0xaa, 0x18, 0xf9, 0xb7, 0x37, 0xbc, 0xbc, + 0xcc, 0xc5, 0x2d, 0x60, 0x20, 0x93, 0x46, 0x2b, 0x2c, 0xaf, 0xc1, 0x9d, 0x1f, 0x1d, 0xc7, 0x19, 0xc0, 0x26, 0x41, + 0xb0, 0x56, 0x84, 0x47, 0x56, 0x89, 0x33, 0x00, 0x41, 0x76, 0x27, 0x4d, 0xc5, 0x73, 0x2d, 0x31, 0xa6, 0x2f, 0x70, + 0x57, 0x39, 0x3b, 0xd9, 0xe4, 0x66, 0xd1, 0xfb, 0x33, 0xac, 0x3a, 0x52, 0x19, 0x1b, 0x8b, 0xae, 0x3b, 0x58, 0x6b, + 0x06, 0x4d, 0x11, 0x52, 0x3e, 0x64, 0x4f, 0xda, 0xbf, 0x02, 0x1a, 0x9c, 0x67, 0xe9, 0x9d, 0xb1, 0xca, 0xdf, 0x28, + 0x21, 0x4e, 0x14, 0x53, 0x2b, 0xbe, 0x89, 0x12, 0x75, 0x7e, 0x26, 0xda, 0x0d, 0x04, 0x52, 0x7f, 0xc0, 0xa0, 0x1a, + 0x65, 0x98, 0xc0, 0x75, 0x20, 0x8a, 0xcd, 0x89, 0xea, 0x2d, 0x47, 0xd0, 0x09, 0x21, 0xde, 0x01, 0x50, 0xef, 0xd8, + 0xfa, 0x08, 0x68, 0x96, 0xbe, 0x69, 0xad, 0x73, 0x4d, 0x28, 0xb4, 0x13, 0x98, 0x64, 0x90, 0xe4, 0x59, 0x67, 0x98, + 0xa0, 0xda, 0x8c, 0x49, 0xe7, 0x7d, 0x80, 0xee, 0xae, 0x45, 0x5d, 0x7c, 0xd3, 0xb9, 0x83, 0xf6, 0x71, 0xfd, 0x4a, + 0x8b, 0xec, 0xf1, 0xe7, 0x2d, 0x11, 0x16, 0x81, 0xb3, 0x56, 0xe7, 0xab, 0x47, 0x38, 0x30, 0x15, 0x99, 0x86, 0xbd, + 0x44, 0x2a, 0x59, 0xb6, 0xdb, 0x5e, 0x6f, 0xaf, 0x88, 0xab, 0xc7, 0x58, 0xed, 0xdc, 0xcc, 0xcd, 0x9d, 0x6a, 0x5d, + 0xec, 0xde, 0xb4, 0xdd, 0x14, 0x33, 0x6a, 0xad, 0xdd, 0xae, 0x39, 0x21, 0x4f, 0xbe, 0x15, 0xd5, 0x4a, 0x9d, 0xae, + 0x0d, 0xda, 0x21, 0x9e, 0x75, 0x91, 0xc1, 0x8d, 0xf2, 0xb9, 0x15, 0x3a, 0xc9, 0x38, 0xab, 0x56, 0x5d, 0xb0, 0xb9, + 0xe6, 0xf5, 0x52, 0xa4, 0x51, 0x45, 0xd1, 0xe6, 0x3c, 0x2a, 0x68, 0x22, 0xd6, 0x45, 0x1d, 0x89, 0x06, 0xf5, 0xa2, + 0x46, 0x63, 0x80, 0x80, 0x4c, 0xe7, 0xbe, 0x07, 0x55, 0x30, 0x1b, 0x8a, 0x48, 0x4c, 0xdf, 0x83, 0xa5, 0x7d, 0x01, + 0xfb, 0xa2, 0xd9, 0x57, 0x67, 0x8b, 0x6f, 0x75, 0x84, 0x60, 0x12, 0xb3, 0x07, 0xc2, 0xc0, 0xf9, 0xc6, 0x90, 0xd3, + 0x2e, 0x71, 0x99, 0xef, 0x96, 0xb0, 0x87, 0xdb, 0x15, 0xec, 0xc4, 0xce, 0x93, 0xe2, 0xe6, 0x4a, 0x76, 0x52, 0xce, + 0xc7, 0xa0, 0xfd, 0x12, 0xf2, 0xda, 0xa5, 0xb8, 0xf5, 0x78, 0x10, 0xd0, 0x60, 0x50, 0x6a, 0xfe, 0x75, 0xa2, 0x3d, + 0x3c, 0x69, 0x40, 0x90, 0x94, 0x83, 0x8b, 0xb6, 0x63, 0xf8, 0x3e, 0x99, 0x8a, 0x63, 0x8e, 0x16, 0xef, 0xd0, 0xea, + 0x04, 0xa2, 0x78, 0x81, 0xbd, 0x9b, 0x56, 0x15, 0x6a, 0x11, 0x94, 0xa3, 0xe5, 0x2f, 0x64, 0x75, 0x08, 0x28, 0xa4, + 0x7c, 0x45, 0xa1, 0x6c, 0x9d, 0x18, 0xea, 0xe1, 0x17, 0xf3, 0xc9, 0x42, 0xcd, 0xc0, 0x40, 0xcc, 0x8f, 0x16, 0x6a, + 0x16, 0x06, 0x62, 0xfe, 0xd5, 0xa2, 0xb1, 0xeb, 0x40, 0x11, 0x10, 0xc7, 0x85, 0xa3, 0x93, 0xd2, 0xca, 0x6c, 0x01, + 0xdd, 0x3c, 0x44, 0xd0, 0xff, 0x6e, 0x0e, 0x41, 0x2b, 0x17, 0xda, 0x91, 0x1b, 0xd0, 0x76, 0x1c, 0x02, 0x73, 0xc5, + 0xa4, 0x95, 0x0e, 0x40, 0x74, 0xcc, 0xc6, 0x60, 0x88, 0x2d, 0x3f, 0x38, 0x66, 0xe3, 0xa9, 0x4b, 0x82, 0x80, 0xd1, + 0xfd, 0x41, 0x43, 0x82, 0xdf, 0xe1, 0x55, 0xfa, 0x64, 0x83, 0xbe, 0x66, 0xce, 0xdd, 0xd0, 0xb9, 0xb8, 0x82, 0x53, + 0xb5, 0xbd, 0x27, 0xa1, 0x9b, 0x4c, 0x3b, 0x40, 0xaf, 0x26, 0x6e, 0xc8, 0xaf, 0x8c, 0x46, 0xa3, 0x62, 0x64, 0x00, + 0x20, 0x88, 0xe6, 0x1c, 0xfc, 0x9c, 0x86, 0xcb, 0x97, 0xb7, 0x9e, 0x4d, 0x31, 0x02, 0x5a, 0xc8, 0x44, 0xf3, 0x00, + 0x65, 0x55, 0x63, 0x68, 0x86, 0xde, 0x21, 0xc7, 0x0f, 0x0f, 0xbe, 0xce, 0xf8, 0x89, 0xc3, 0xb5, 0x87, 0x73, 0xe1, + 0xba, 0xac, 0x69, 0x99, 0x43, 0xe7, 0xd9, 0xc7, 0xf1, 0x1e, 0xc6, 0xc9, 0xa7, 0x59, 0x28, 0x67, 0xbc, 0xa6, 0xff, + 0x51, 0xe9, 0x7e, 0x87, 0x43, 0x4e, 0x57, 0xb0, 0xe2, 0x66, 0x75, 0xa8, 0xf9, 0x59, 0xe4, 0x8d, 0x23, 0xde, 0x90, + 0xa8, 0xee, 0x3e, 0xef, 0x4d, 0x98, 0xd2, 0x8e, 0x71, 0x00, 0x70, 0xa2, 0x56, 0x0d, 0xbb, 0xd2, 0xb8, 0x56, 0x07, + 0x31, 0x0c, 0x25, 0x6c, 0x95, 0x38, 0xaa, 0xa4, 0xbf, 0x01, 0x08, 0x8b, 0xa1, 0x38, 0xde, 0x1a, 0xd6, 0x07, 0xd8, + 0x0f, 0x55, 0xa0, 0x6e, 0x4e, 0x21, 0x67, 0x00, 0x90, 0x04, 0xdc, 0xd1, 0x53, 0x4d, 0x43, 0x65, 0x9b, 0xe3, 0xa1, + 0x65, 0x74, 0x05, 0x0f, 0xf4, 0xd4, 0x96, 0x0c, 0x8c, 0xab, 0x3c, 0xf6, 0x36, 0xfb, 0xdb, 0xa3, 0x54, 0xe4, 0x3b, + 0x9b, 0xd4, 0x34, 0xab, 0x46, 0x63, 0x1f, 0x47, 0xe8, 0x69, 0x05, 0x68, 0xbd, 0xb6, 0x54, 0xb4, 0xdf, 0x47, 0x31, + 0x6a, 0x5c, 0x4a, 0xb0, 0x0a, 0x1d, 0x09, 0x0e, 0x11, 0x46, 0x08, 0xfd, 0xbe, 0x08, 0x37, 0xae, 0x20, 0x83, 0x28, + 0xb8, 0x16, 0x15, 0x7f, 0xc8, 0xf2, 0xa2, 0x6d, 0xa9, 0xaa, 0x3e, 0x69, 0xda, 0x12, 0x78, 0x1d, 0x0e, 0xb0, 0x9d, + 0x7f, 0xea, 0x89, 0x5c, 0x2b, 0x1b, 0x25, 0x7c, 0x47, 0x5c, 0x0b, 0xa2, 0x9b, 0x46, 0xd7, 0xeb, 0xd9, 0x21, 0x5a, + 0x9a, 0xe2, 0xd0, 0x21, 0xfb, 0xdc, 0x3d, 0xb7, 0x65, 0x7c, 0xfb, 0x09, 0x72, 0xe7, 0x3b, 0x7b, 0x49, 0xc2, 0x20, + 0x6f, 0xd9, 0x40, 0xb1, 0x8e, 0xad, 0xa0, 0x00, 0xa3, 0xb6, 0xfc, 0x05, 0x74, 0x6c, 0x30, 0xa8, 0x09, 0x3e, 0x49, + 0x6c, 0x1b, 0x8f, 0xfc, 0x11, 0xe7, 0x86, 0x0e, 0xaf, 0x0d, 0x79, 0x20, 0x4e, 0x61, 0x9f, 0x28, 0x61, 0xff, 0x82, + 0x82, 0xee, 0x48, 0x2f, 0x57, 0x89, 0xab, 0xe2, 0x01, 0xaa, 0xec, 0x78, 0xae, 0xf9, 0x92, 0x16, 0x5a, 0x69, 0x64, + 0x15, 0x1d, 0x11, 0xb7, 0x60, 0x32, 0x66, 0xab, 0x6a, 0x54, 0x71, 0x2c, 0x50, 0xa4, 0x63, 0xce, 0x76, 0x0e, 0xd6, + 0x00, 0x78, 0x0a, 0x9b, 0x8b, 0x33, 0x2c, 0x28, 0xed, 0xb2, 0xa5, 0x2f, 0x81, 0x55, 0xf3, 0x30, 0xce, 0xcb, 0x8e, + 0x2f, 0x77, 0x47, 0xdb, 0x7b, 0xe8, 0x8d, 0xe8, 0x8d, 0xd7, 0xe7, 0x51, 0xd3, 0xcf, 0x9e, 0xe1, 0xda, 0x50, 0x90, + 0x07, 0x9a, 0xea, 0x10, 0x46, 0x8b, 0xc0, 0x34, 0xe5, 0x27, 0x6c, 0x3c, 0x1d, 0x0e, 0x35, 0x19, 0x74, 0x9a, 0x89, + 0xf1, 0xbf, 0x3e, 0x83, 0xd6, 0xe9, 0x89, 0xf3, 0x3e, 0x6d, 0x5f, 0x41, 0xeb, 0x3b, 0x94, 0xc9, 0x9d, 0x83, 0xe1, + 0x03, 0x2d, 0x98, 0x84, 0xa9, 0xc2, 0x1b, 0x22, 0x15, 0xec, 0xcd, 0xd2, 0x38, 0xec, 0x9b, 0x85, 0x42, 0x4b, 0x45, + 0xfc, 0x6a, 0x4d, 0xfc, 0xe4, 0x75, 0xe6, 0xdf, 0xa6, 0x7d, 0x72, 0x10, 0x4b, 0x43, 0x62, 0x24, 0xe2, 0x17, 0xa7, + 0xd2, 0x76, 0x42, 0x05, 0xc4, 0x43, 0xd7, 0xba, 0x71, 0x24, 0x64, 0xec, 0x49, 0x8d, 0xa7, 0x86, 0xfb, 0x5e, 0xc7, + 0xac, 0xc3, 0x2c, 0x76, 0xb3, 0x46, 0x42, 0x61, 0x9c, 0x9a, 0xe0, 0x94, 0x62, 0x15, 0xc9, 0xe8, 0x78, 0xa6, 0x30, + 0x88, 0x2a, 0x29, 0x21, 0xd6, 0x94, 0xad, 0x85, 0x89, 0x5d, 0x67, 0x0b, 0x53, 0xd4, 0x45, 0xa8, 0x37, 0x03, 0x9d, + 0x05, 0x0d, 0xf9, 0x1d, 0x1a, 0xad, 0xa8, 0x9a, 0x04, 0x0c, 0xe3, 0x28, 0xd5, 0xf8, 0xb7, 0x08, 0xb5, 0x1e, 0x06, + 0x00, 0xb6, 0x79, 0x27, 0xb2, 0xa2, 0x7e, 0x55, 0x20, 0x04, 0x9a, 0xb5, 0x9f, 0x2a, 0xeb, 0x9d, 0x59, 0xd0, 0x8a, + 0x76, 0x73, 0xe5, 0x73, 0x81, 0x13, 0xaa, 0x53, 0x79, 0x81, 0x7a, 0x29, 0xca, 0xd7, 0x22, 0xe5, 0xad, 0xb8, 0x98, + 0x07, 0x82, 0x7d, 0xc8, 0x47, 0x70, 0x5e, 0xa1, 0x53, 0xb9, 0xde, 0x26, 0xd2, 0x2c, 0x49, 0x30, 0x16, 0x68, 0x9b, + 0x97, 0x60, 0x26, 0x14, 0x33, 0x86, 0x5f, 0x43, 0x70, 0xb1, 0x9d, 0x93, 0x70, 0xb3, 0x9f, 0x07, 0x86, 0xd0, 0xe4, + 0x55, 0x4b, 0x34, 0x6c, 0xec, 0x78, 0x1d, 0xb9, 0x26, 0xdc, 0x87, 0xb5, 0x58, 0x93, 0x31, 0xc6, 0x95, 0xb9, 0x91, + 0xf1, 0xa3, 0x05, 0x1e, 0x8c, 0x49, 0xeb, 0x4f, 0x20, 0xd3, 0x52, 0xca, 0x3a, 0x5f, 0x68, 0x31, 0x93, 0x4c, 0x74, + 0x6e, 0xdf, 0xf8, 0x2c, 0xef, 0x22, 0xf2, 0xb7, 0xf2, 0x7b, 0x92, 0x0f, 0xf7, 0xee, 0x83, 0xc4, 0x1a, 0x94, 0x46, + 0x5c, 0x5a, 0x94, 0xa7, 0x0f, 0x74, 0xdd, 0xa4, 0x88, 0xd3, 0xf3, 0x55, 0x5c, 0x56, 0x3c, 0x85, 0x4a, 0x15, 0x75, + 0x8b, 0x7a, 0x13, 0xb0, 0x37, 0x44, 0x92, 0x64, 0x2c, 0x8d, 0x8d, 0xd8, 0xc5, 0x23, 0x3d, 0x7b, 0xc3, 0x2c, 0xbd, + 0xac, 0xd1, 0x90, 0x96, 0x3a, 0x67, 0xa1, 0x94, 0xf9, 0x4b, 0xfe, 0x33, 0x68, 0x24, 0xe8, 0xa8, 0x4f, 0x31, 0x9e, + 0x01, 0x23, 0xbe, 0x1b, 0xc1, 0xea, 0x01, 0xe2, 0xa2, 0x08, 0x4a, 0xb3, 0x23, 0x76, 0xfc, 0xd4, 0xe4, 0xe1, 0x5d, + 0xc8, 0x3a, 0x83, 0x4f, 0x1f, 0x66, 0x89, 0x5a, 0xeb, 0xa8, 0x1a, 0xc9, 0x19, 0x40, 0xd3, 0x41, 0x91, 0xf3, 0xb8, + 0x08, 0x66, 0x3d, 0x9d, 0x18, 0xf5, 0xb8, 0xfa, 0x05, 0x1a, 0x6a, 0xb7, 0x59, 0x59, 0x9e, 0xd5, 0xf7, 0x9f, 0xc3, + 0x81, 0x4d, 0x4d, 0x05, 0x3d, 0xde, 0xd4, 0xe2, 0xea, 0x4a, 0x76, 0xdb, 0x2d, 0x44, 0xcb, 0xe9, 0xbc, 0x6b, 0xe9, + 0xbc, 0x5e, 0xb0, 0x5e, 0x77, 0xba, 0x5e, 0xdc, 0x7e, 0x19, 0x1e, 0xc2, 0xda, 0xce, 0x27, 0x8a, 0x3f, 0xf3, 0xdb, + 0xee, 0xe2, 0x2d, 0x54, 0xb3, 0x00, 0x00, 0xd2, 0x83, 0x28, 0x58, 0x66, 0x29, 0x0f, 0xa8, 0xd8, 0xc7, 0x51, 0x96, + 0x52, 0x2f, 0x67, 0x18, 0x3f, 0x65, 0x1a, 0x6b, 0x9c, 0x15, 0xaa, 0xd0, 0xd8, 0xe8, 0x4e, 0x57, 0x19, 0x62, 0xfb, + 0x09, 0x9c, 0x2d, 0xc0, 0xfd, 0xd1, 0x43, 0xa1, 0xee, 0x4d, 0x5a, 0x9a, 0xa8, 0xf9, 0xae, 0x3d, 0x83, 0x8c, 0xe2, + 0x64, 0x95, 0x57, 0xd0, 0x8d, 0x3a, 0x6b, 0xa3, 0x4a, 0xdf, 0x43, 0xd4, 0xab, 0x18, 0x3c, 0xca, 0x5d, 0x5e, 0x1b, + 0x9d, 0x4c, 0x8b, 0x48, 0xb9, 0xf3, 0x93, 0x66, 0x99, 0xa5, 0x4a, 0x87, 0xed, 0x32, 0xec, 0xad, 0x31, 0xe9, 0x4d, + 0x48, 0x03, 0x23, 0xf1, 0xe9, 0x8c, 0x0a, 0x21, 0xa0, 0x2d, 0xc7, 0xdf, 0xe1, 0x33, 0x34, 0x4d, 0x81, 0xa5, 0x8a, + 0x5b, 0xd8, 0x0e, 0x9f, 0xff, 0x64, 0xd4, 0x02, 0x10, 0xc1, 0xca, 0xd5, 0xbb, 0x38, 0x25, 0x34, 0xe7, 0xca, 0x0c, + 0x00, 0x59, 0x50, 0xca, 0x2d, 0x3f, 0x25, 0xd3, 0xc1, 0x12, 0x45, 0xd9, 0xcb, 0xa9, 0x1b, 0x1d, 0x1b, 0x3f, 0xa4, + 0xe7, 0x02, 0xb6, 0x0b, 0xf9, 0xad, 0xbd, 0x7a, 0x89, 0x9a, 0x34, 0xa6, 0x59, 0x0f, 0xf0, 0xe5, 0x1a, 0x4d, 0x42, + 0x0b, 0xca, 0xa4, 0x29, 0x80, 0xc6, 0x4d, 0xd5, 0x0a, 0x26, 0xa5, 0x46, 0xc2, 0x96, 0x3a, 0x92, 0x65, 0xdf, 0x07, + 0xa7, 0xde, 0x23, 0xe8, 0x01, 0xf3, 0x08, 0xf4, 0xf4, 0x5f, 0xba, 0x6a, 0xff, 0x92, 0xa3, 0x93, 0xab, 0x26, 0x6a, + 0xfa, 0xbd, 0xb2, 0x23, 0x43, 0xca, 0xa5, 0x19, 0x08, 0x26, 0x1d, 0xf3, 0xd4, 0xd8, 0x3a, 0x46, 0x44, 0x0f, 0x9c, + 0x7d, 0xba, 0x5b, 0x4d, 0x2d, 0x00, 0xd1, 0xf1, 0xeb, 0x27, 0xaf, 0xae, 0xe3, 0x2b, 0x8d, 0xa2, 0xe4, 0x59, 0xc4, + 0x48, 0xd3, 0xbe, 0x5a, 0xc0, 0xe0, 0xfd, 0xf2, 0xfe, 0x27, 0x99, 0xa5, 0x71, 0x7b, 0xb0, 0x31, 0xa2, 0xaa, 0x5f, + 0x2a, 0x5e, 0xfa, 0x02, 0xac, 0x7d, 0x96, 0x28, 0x90, 0xfb, 0xbd, 0x49, 0xd3, 0xdf, 0x44, 0xde, 0xcd, 0x86, 0xf5, + 0xc6, 0x4d, 0xbb, 0xd4, 0x96, 0xec, 0xc8, 0x48, 0xe4, 0xf4, 0x62, 0xd0, 0xe3, 0x47, 0x2b, 0x8d, 0xd2, 0xb0, 0x41, + 0x55, 0x2a, 0x7e, 0xaf, 0x45, 0x70, 0xf2, 0x58, 0x95, 0x18, 0xd3, 0x80, 0xd9, 0x56, 0x36, 0x0a, 0xd4, 0x41, 0x2a, + 0x6d, 0x75, 0x14, 0xb6, 0xdf, 0x58, 0x49, 0xf5, 0xef, 0x7f, 0x6a, 0x43, 0x3e, 0x5f, 0x0a, 0x2a, 0x08, 0xd8, 0x19, + 0x78, 0x3d, 0x95, 0xc2, 0x40, 0x2a, 0xd8, 0x49, 0x05, 0x28, 0x5f, 0x44, 0x8e, 0xd5, 0x6e, 0x5f, 0xad, 0x1a, 0xa3, + 0x2d, 0x20, 0x34, 0x90, 0x1e, 0x5d, 0xf6, 0x71, 0x1b, 0xe3, 0x40, 0xe2, 0xc0, 0x09, 0xb6, 0x73, 0x75, 0x8d, 0x46, + 0x42, 0xf3, 0x87, 0x46, 0x03, 0x5e, 0xd3, 0x1a, 0x14, 0xea, 0x39, 0x8e, 0x86, 0xca, 0x0e, 0x29, 0x88, 0xd8, 0xa0, + 0x84, 0x7d, 0x7b, 0x3e, 0xd4, 0xfb, 0x7a, 0x9e, 0x2c, 0x48, 0x43, 0x85, 0xfd, 0xdc, 0x2e, 0x21, 0x63, 0xd5, 0x21, + 0xad, 0x3c, 0xc0, 0xf1, 0x42, 0xca, 0xfc, 0x2d, 0x26, 0x35, 0x4a, 0x63, 0x42, 0x6d, 0xc4, 0x02, 0x96, 0x04, 0xed, + 0xf5, 0x40, 0xdd, 0x32, 0x08, 0x75, 0x4c, 0x4f, 0x04, 0x3e, 0xa5, 0x5c, 0x7e, 0x5a, 0x92, 0x66, 0x5a, 0x32, 0x0b, + 0x7a, 0xe9, 0x5a, 0xf9, 0x15, 0xde, 0x47, 0xbb, 0x7b, 0x57, 0x5f, 0x58, 0xc7, 0x10, 0x0c, 0xbb, 0x72, 0x9b, 0xd3, + 0x50, 0x00, 0x36, 0x3c, 0x55, 0x65, 0xb9, 0x46, 0x4d, 0x64, 0x16, 0x87, 0x24, 0x02, 0xc9, 0xb6, 0xbf, 0xb9, 0xb5, + 0x60, 0xdb, 0x59, 0xa8, 0x9e, 0xfa, 0xcb, 0xd9, 0xee, 0x7b, 0x86, 0x97, 0x3b, 0x72, 0x6f, 0xdf, 0x86, 0xf2, 0x87, + 0xfd, 0xab, 0xe4, 0xff, 0xaa, 0x92, 0xfd, 0x56, 0x99, 0x4d, 0x5b, 0xbc, 0xdf, 0x75, 0xdc, 0x72, 0x8c, 0x06, 0x81, + 0x35, 0x05, 0x1a, 0xd2, 0x93, 0xc6, 0x34, 0x51, 0x21, 0x95, 0x19, 0xd3, 0x78, 0x74, 0x01, 0x9a, 0xc3, 0x74, 0x9e, + 0xc7, 0x00, 0x1c, 0xe0, 0x1e, 0x79, 0x84, 0xba, 0xa7, 0xf3, 0x3c, 0x38, 0x0f, 0x06, 0xc5, 0x20, 0x50, 0x9f, 0xd8, + 0xe6, 0x04, 0x0b, 0xd0, 0xb9, 0xc5, 0x0c, 0x82, 0x4d, 0x1a, 0x33, 0x87, 0xf8, 0x38, 0x99, 0x0e, 0x06, 0x31, 0xd9, + 0x00, 0x48, 0x5f, 0xbc, 0x30, 0xce, 0x41, 0xa5, 0x5a, 0x90, 0xad, 0xba, 0x4b, 0xbf, 0x62, 0xa7, 0xda, 0x69, 0xde, + 0xef, 0xe7, 0xf3, 0x62, 0x10, 0x78, 0x15, 0x96, 0xda, 0xfb, 0x8f, 0xfa, 0x5f, 0x6a, 0x9d, 0x34, 0xc1, 0x30, 0xb5, + 0xa7, 0xa8, 0x5e, 0x71, 0x34, 0xa3, 0xde, 0xed, 0x58, 0x2a, 0x5f, 0x40, 0x14, 0x0f, 0x0c, 0x59, 0x2b, 0xef, 0xce, + 0xc1, 0x6b, 0x73, 0xe3, 0xcd, 0x11, 0x05, 0xd8, 0xbe, 0x30, 0x4e, 0x28, 0x2e, 0xba, 0x6c, 0x88, 0x63, 0xb0, 0xd3, + 0xd5, 0x5b, 0x81, 0x56, 0xe3, 0xbd, 0x78, 0xd7, 0x6c, 0xfc, 0x8d, 0x38, 0x50, 0x65, 0x1e, 0x5c, 0x02, 0xe2, 0xec, + 0x41, 0x5c, 0x1f, 0x60, 0xa9, 0x07, 0xc1, 0xc0, 0x20, 0x87, 0xb4, 0xab, 0x55, 0x43, 0x11, 0xc9, 0xf3, 0x18, 0x0c, + 0x98, 0x74, 0x43, 0x1a, 0x32, 0xed, 0x95, 0x12, 0xd2, 0xc6, 0x58, 0x0b, 0x28, 0xc3, 0xe1, 0x6a, 0xc7, 0x6e, 0xd8, + 0x9e, 0x6e, 0x1d, 0x0a, 0x25, 0x8c, 0x5e, 0xdd, 0xf8, 0x87, 0x9a, 0xe7, 0x89, 0xa0, 0x06, 0x55, 0x6b, 0x3f, 0x1d, + 0x94, 0x27, 0xe5, 0xb1, 0x00, 0x17, 0x3d, 0x7c, 0xf9, 0xa2, 0xc0, 0x8b, 0xf6, 0x0e, 0xf2, 0x9c, 0xfe, 0x54, 0xfa, + 0x20, 0x7a, 0x6e, 0x19, 0x2e, 0xb4, 0x8f, 0x6b, 0x05, 0x32, 0x69, 0x3a, 0x9a, 0xda, 0xda, 0x1d, 0xde, 0x31, 0x81, + 0x7e, 0x53, 0x96, 0x52, 0x26, 0xba, 0x96, 0x25, 0x3b, 0xe9, 0xe5, 0xd2, 0x1b, 0x2a, 0x65, 0x27, 0xcb, 0x36, 0xe7, + 0x97, 0x7a, 0x09, 0xfd, 0xbe, 0x72, 0x07, 0xc2, 0x37, 0x72, 0xbd, 0x21, 0x2f, 0x1b, 0x22, 0x96, 0x43, 0xcc, 0xc0, + 0xf1, 0x42, 0x48, 0xd7, 0xee, 0xd2, 0x57, 0xd5, 0xed, 0x6c, 0xe5, 0x92, 0x16, 0x78, 0x2b, 0x05, 0x56, 0x91, 0x5a, + 0xbd, 0x9e, 0x4c, 0xdc, 0xf7, 0x51, 0x6c, 0x3e, 0x02, 0xb6, 0xd1, 0x3b, 0x1a, 0xbd, 0x5b, 0xc4, 0x06, 0x5f, 0x45, + 0x35, 0x2d, 0x39, 0x40, 0x70, 0xb7, 0x25, 0xb5, 0x34, 0xb3, 0x88, 0xfb, 0x92, 0x07, 0x68, 0xdf, 0xc5, 0xe1, 0x4c, + 0x2a, 0xc1, 0xb6, 0xae, 0x75, 0xce, 0x2a, 0x39, 0xa0, 0x9f, 0xe8, 0xf8, 0xa7, 0xd5, 0xa3, 0x22, 0x86, 0x55, 0x36, + 0x92, 0x56, 0x68, 0x0f, 0x4a, 0x97, 0x70, 0xf1, 0x05, 0x78, 0xd9, 0xde, 0xaf, 0xec, 0x3e, 0x5f, 0x62, 0xff, 0x30, + 0xaf, 0x9c, 0xe0, 0x91, 0xd3, 0x78, 0x73, 0x0f, 0xab, 0x3e, 0x57, 0x0a, 0xe1, 0x54, 0x4a, 0x43, 0x01, 0xc0, 0x20, + 0x09, 0x6a, 0xb8, 0xd2, 0xb6, 0x19, 0xa4, 0x34, 0x86, 0xdd, 0xad, 0xde, 0xe8, 0xff, 0x94, 0x0a, 0x17, 0xa0, 0x94, + 0x0d, 0xdc, 0x90, 0x75, 0xaa, 0xe5, 0x3a, 0xa6, 0xe0, 0xf9, 0x2e, 0x39, 0x02, 0x85, 0x1d, 0x18, 0x99, 0xd1, 0x84, + 0xfd, 0x82, 0xb7, 0xa1, 0x9c, 0xbd, 0x34, 0x92, 0x27, 0xbb, 0x2f, 0x69, 0x45, 0x13, 0x32, 0xad, 0xcc, 0xfe, 0x6d, + 0x6d, 0xd8, 0xe7, 0xa1, 0x18, 0x89, 0x02, 0x17, 0x07, 0x9d, 0x03, 0xd8, 0x1f, 0xe4, 0xd2, 0x36, 0x9f, 0x49, 0xbf, + 0x2f, 0xdf, 0x3f, 0xcb, 0xb3, 0xe4, 0xe3, 0xce, 0x7b, 0xcd, 0xd3, 0x2c, 0x19, 0x50, 0x89, 0x98, 0x1a, 0x57, 0xc5, + 0x70, 0xa9, 0x5c, 0x8c, 0x3d, 0x92, 0x11, 0xef, 0xa5, 0x0e, 0x31, 0x62, 0x7c, 0x91, 0x1d, 0x92, 0x92, 0xd3, 0x65, + 0xd3, 0xd9, 0x73, 0x25, 0x9a, 0x41, 0x63, 0xb8, 0x1d, 0xef, 0x25, 0xb5, 0x02, 0x64, 0x54, 0xe8, 0x9e, 0x01, 0xae, + 0xe1, 0xfe, 0x92, 0xf0, 0xb6, 0xf4, 0xb4, 0x25, 0x1a, 0xd8, 0x2b, 0x13, 0x12, 0x72, 0xe3, 0x00, 0x8b, 0xd8, 0x34, + 0x1f, 0x43, 0x01, 0x40, 0xad, 0x1a, 0xe9, 0x95, 0xbe, 0x24, 0x54, 0x26, 0x21, 0x18, 0x5d, 0x91, 0xf0, 0x2a, 0xa0, + 0x71, 0xa6, 0x13, 0x0d, 0x6c, 0x70, 0x40, 0x9f, 0xd7, 0x3a, 0x51, 0xdb, 0x90, 0x07, 0xb4, 0x36, 0x69, 0x00, 0x83, + 0x0f, 0x92, 0x24, 0xfa, 0x6a, 0xa9, 0x93, 0x40, 0x50, 0x82, 0xf2, 0x0d, 0xfa, 0x73, 0xe1, 0xf8, 0x58, 0x82, 0xff, + 0x91, 0x26, 0x82, 0x3f, 0x84, 0x02, 0x64, 0x8a, 0xaa, 0x62, 0x9a, 0xb1, 0x93, 0xac, 0xdb, 0x98, 0xc4, 0xf1, 0xb4, + 0xbb, 0x2b, 0xa5, 0x4b, 0x17, 0xf8, 0x95, 0x65, 0x88, 0x63, 0xfd, 0x2c, 0x5e, 0xb1, 0xd3, 0x90, 0x2b, 0xbc, 0xf4, + 0x67, 0xf1, 0x0a, 0x67, 0x88, 0xd6, 0xad, 0x04, 0x22, 0xfd, 0x57, 0x4d, 0xe0, 0x10, 0xfb, 0x09, 0x06, 0xb9, 0xa8, + 0x9d, 0x07, 0x02, 0x79, 0x5b, 0x41, 0x44, 0xfc, 0xec, 0x2a, 0x8c, 0x48, 0xbd, 0x93, 0xa4, 0xbf, 0xfc, 0x51, 0x64, + 0x85, 0xf3, 0x0d, 0x3c, 0xfa, 0xcd, 0x32, 0x29, 0xfa, 0x0b, 0x19, 0xcc, 0xc1, 0x7e, 0x22, 0xe3, 0x52, 0xd4, 0xee, + 0x13, 0x76, 0xc1, 0x89, 0xf1, 0xe0, 0xf4, 0x1a, 0x01, 0xf6, 0x6b, 0xf7, 0xc9, 0x19, 0xb3, 0xbf, 0x8c, 0x1b, 0x5f, + 0xa6, 0x23, 0x3e, 0xf0, 0xd1, 0x1d, 0xe5, 0xa3, 0x7b, 0x27, 0xd3, 0x1f, 0x1e, 0x94, 0xc8, 0xa8, 0xaa, 0xf9, 0x6a, + 0xc5, 0xd3, 0xd9, 0x5d, 0x12, 0x65, 0xa3, 0x9a, 0x17, 0x30, 0xbd, 0xe0, 0x78, 0x97, 0xac, 0x2f, 0xb2, 0xe4, 0x15, + 0xc4, 0x1e, 0x58, 0x09, 0x89, 0xc5, 0x0f, 0xcb, 0x4c, 0x2e, 0xe6, 0x42, 0xd4, 0xa2, 0xe0, 0xc1, 0xec, 0x26, 0x89, + 0xfe, 0x5a, 0x3a, 0x48, 0x6a, 0x7a, 0xca, 0x36, 0x8d, 0x25, 0xd4, 0xda, 0xd7, 0x91, 0x6e, 0x94, 0x05, 0x00, 0xdc, + 0xb3, 0x8b, 0x34, 0x12, 0xac, 0x1a, 0x4e, 0x1a, 0xc6, 0x75, 0x7a, 0x89, 0xa9, 0x71, 0xc3, 0x6a, 0x9a, 0x58, 0x0b, + 0x19, 0xd0, 0xfb, 0x03, 0x5e, 0x0e, 0x3e, 0x67, 0x45, 0x28, 0xa4, 0x35, 0x70, 0x71, 0x5c, 0xf6, 0xfb, 0xe2, 0xb8, + 0xdc, 0x6e, 0x8b, 0x93, 0xb8, 0xdf, 0x17, 0x27, 0xb1, 0xe6, 0x1f, 0xa4, 0x62, 0x5b, 0x9b, 0x1b, 0x24, 0x34, 0x17, + 0x10, 0xb5, 0x68, 0x04, 0x7f, 0x68, 0x96, 0xf3, 0x22, 0xca, 0x8f, 0x93, 0x7e, 0xbf, 0xb7, 0x9c, 0x55, 0x83, 0x7c, + 0x98, 0x44, 0xf9, 0x30, 0x71, 0x9c, 0x10, 0x7f, 0x75, 0x9c, 0x10, 0x25, 0x0d, 0x5c, 0xc1, 0x99, 0x01, 0x88, 0x02, + 0x2e, 0xfd, 0xa3, 0xaa, 0x96, 0x52, 0xd5, 0x12, 0xcb, 0x5a, 0x12, 0x55, 0x41, 0xc3, 0x6e, 0xca, 0xb0, 0xc0, 0x52, + 0xe8, 0x92, 0xfd, 0xb1, 0x04, 0x9e, 0x28, 0xe7, 0xf5, 0x06, 0x18, 0xd8, 0x08, 0xef, 0x1c, 0x3a, 0x9c, 0xc4, 0xba, + 0x61, 0x12, 0x32, 0xe9, 0x92, 0xae, 0xe8, 0x15, 0xf2, 0xb3, 0x97, 0x60, 0xb0, 0x74, 0xcc, 0xf2, 0xe9, 0x60, 0x70, + 0x49, 0x56, 0xac, 0x98, 0x87, 0xf1, 0x20, 0x5c, 0xcf, 0xf2, 0xe1, 0x65, 0x74, 0x49, 0xc8, 0x17, 0xe5, 0x82, 0xf6, + 0x56, 0xa3, 0xea, 0x63, 0x06, 0xc1, 0xfd, 0xd2, 0x59, 0x98, 0xe9, 0x38, 0x1f, 0xab, 0xd1, 0x1d, 0x5d, 0x41, 0xfc, + 0x1a, 0xb8, 0x91, 0x90, 0x08, 0x3a, 0x72, 0x45, 0x57, 0x74, 0x4d, 0x85, 0x9e, 0x61, 0x0c, 0xd1, 0x6d, 0x8e, 0x93, + 0x04, 0x1c, 0x93, 0x6d, 0xf1, 0xd1, 0x58, 0x16, 0xde, 0xf5, 0x1d, 0xa1, 0xbd, 0x5e, 0x62, 0x07, 0xe9, 0xbb, 0xf6, + 0x20, 0x01, 0x23, 0x32, 0x92, 0x03, 0xa5, 0x47, 0x46, 0x50, 0x3d, 0xa9, 0x38, 0x24, 0xb1, 0x3b, 0x24, 0x72, 0x1c, + 0x12, 0x77, 0x1c, 0x72, 0x35, 0x0e, 0xc8, 0xdd, 0x2f, 0xd9, 0x98, 0xa6, 0x6c, 0x4c, 0xd7, 0x72, 0x54, 0xe8, 0x35, + 0xbd, 0x50, 0xd4, 0xf1, 0x9c, 0xbd, 0x86, 0x03, 0x7b, 0x10, 0xe6, 0xb3, 0x78, 0xf8, 0x3a, 0x7a, 0x4d, 0xc8, 0x17, + 0x82, 0xde, 0xc8, 0x4b, 0x19, 0x84, 0x41, 0xbc, 0x06, 0xe7, 0x52, 0x1b, 0xea, 0xe4, 0x5a, 0xef, 0x38, 0x7c, 0xba, + 0xf2, 0x9e, 0x2e, 0x20, 0xa2, 0x0f, 0x5a, 0xa9, 0xf4, 0xfb, 0xe1, 0x25, 0x2b, 0xe6, 0xe7, 0xe1, 0x98, 0x00, 0x0e, + 0x8f, 0x1a, 0xce, 0xcb, 0xd1, 0x1d, 0xbd, 0x1c, 0xdd, 0x13, 0xb0, 0xf0, 0x1a, 0x4f, 0xd7, 0xc7, 0x2c, 0x9e, 0x0e, + 0x06, 0x6b, 0xa4, 0xea, 0x32, 0xf7, 0x9a, 0x2c, 0xe8, 0x25, 0x4e, 0x04, 0x01, 0x86, 0x3e, 0x2b, 0xd6, 0x9a, 0x86, + 0xbf, 0x66, 0xf0, 0xf1, 0x3d, 0xbb, 0x1c, 0xdd, 0xd3, 0x3b, 0xf6, 0x7a, 0x3b, 0x9e, 0x02, 0x33, 0xb5, 0x9a, 0x85, + 0xf7, 0xc7, 0x57, 0xb3, 0x2b, 0x76, 0x1f, 0xdd, 0x9f, 0x40, 0x43, 0xaf, 0xd9, 0x3d, 0x02, 0x2e, 0xa5, 0x8f, 0x97, + 0x83, 0xd7, 0xe4, 0x70, 0x30, 0x48, 0x49, 0x14, 0xde, 0x84, 0x4e, 0x2b, 0x5f, 0xd3, 0x7b, 0x42, 0x57, 0xec, 0x0e, + 0x47, 0xe3, 0x8a, 0xe1, 0x07, 0x17, 0xec, 0xbe, 0xb9, 0x09, 0x9d, 0xdd, 0x1c, 0x57, 0x9d, 0x20, 0x46, 0xe8, 0x6b, + 0x60, 0x69, 0x96, 0x0d, 0x33, 0x01, 0x4f, 0xfa, 0x22, 0xa3, 0x44, 0xa1, 0x19, 0x88, 0xb3, 0x12, 0x10, 0x4b, 0xa2, + 0xee, 0x37, 0x1b, 0x9d, 0xc3, 0x72, 0xee, 0xf7, 0x7b, 0xb5, 0xa6, 0x07, 0x88, 0x9c, 0xd9, 0x49, 0x0f, 0x7a, 0x2e, + 0x3d, 0xc0, 0x4f, 0xd4, 0xaa, 0x41, 0x9c, 0xcc, 0xef, 0x96, 0xd1, 0xaf, 0x0e, 0x7d, 0xf8, 0xa1, 0x9b, 0xf2, 0x54, + 0xf9, 0xbf, 0x4f, 0x79, 0x8a, 0x3c, 0x7a, 0x5d, 0x3b, 0x20, 0x78, 0xce, 0x9a, 0x94, 0x1a, 0x89, 0x7a, 0x74, 0xbe, + 0x8a, 0x41, 0x1b, 0x89, 0xda, 0x06, 0xf5, 0x84, 0x16, 0x56, 0x10, 0x21, 0xe7, 0xe8, 0x39, 0x18, 0xa4, 0x42, 0xa8, + 0x1c, 0xb9, 0x28, 0xd1, 0x10, 0x24, 0x17, 0x15, 0x97, 0xe1, 0x73, 0x08, 0x95, 0xa7, 0x8f, 0x35, 0x11, 0xd6, 0xf4, + 0x18, 0x0c, 0xb0, 0x2d, 0xfc, 0xdb, 0x0e, 0xb9, 0xa8, 0xf8, 0x15, 0x9e, 0xcd, 0x6d, 0x82, 0x51, 0xb2, 0xb8, 0x15, + 0xda, 0x06, 0xb1, 0x1f, 0x0b, 0x82, 0xf5, 0x08, 0x1a, 0x8f, 0x2a, 0x7d, 0x44, 0xb8, 0x51, 0x7c, 0x24, 0x3d, 0x8d, + 0x35, 0x89, 0xe4, 0x48, 0x22, 0xf9, 0x00, 0x08, 0x27, 0x41, 0x7f, 0x71, 0xdb, 0x64, 0xdb, 0x42, 0xa2, 0xd1, 0x9f, + 0x96, 0x4c, 0xc9, 0xee, 0x65, 0x8f, 0x5d, 0x45, 0x90, 0x3d, 0xa6, 0xff, 0x74, 0xfa, 0xf0, 0xcf, 0x25, 0xce, 0xa0, + 0xf1, 0x7c, 0x91, 0x9d, 0x99, 0x39, 0x83, 0x1b, 0x39, 0x5d, 0x56, 0xae, 0xcb, 0x97, 0xfc, 0x80, 0xdf, 0xd5, 0xbc, + 0x48, 0xab, 0x83, 0x9f, 0xeb, 0x36, 0x9e, 0x53, 0xb5, 0x5e, 0xd9, 0x38, 0x2b, 0xd2, 0x38, 0xd5, 0x91, 0xba, 0x68, + 0x6b, 0x58, 0xcf, 0xef, 0x11, 0x75, 0x25, 0x2d, 0x47, 0x4f, 0x21, 0x56, 0x7e, 0xca, 0xe5, 0x3a, 0xcf, 0x7f, 0xda, + 0x49, 0xc5, 0x29, 0xf6, 0x53, 0x90, 0x2a, 0xb5, 0x5c, 0x40, 0xd5, 0x1c, 0xb5, 0xdc, 0x2d, 0xf5, 0x0e, 0xb0, 0x6e, + 0x9b, 0xf2, 0x63, 0x69, 0x76, 0xe1, 0x24, 0x7b, 0xf7, 0x27, 0x5d, 0x86, 0x01, 0xa3, 0x50, 0x66, 0xd5, 0xb5, 0xb2, + 0x2f, 0x34, 0x4e, 0xc3, 0x70, 0xe5, 0xc7, 0x0b, 0x48, 0x17, 0x30, 0x8e, 0x13, 0x25, 0x13, 0xe3, 0xf6, 0xa8, 0xad, + 0x50, 0x7d, 0xce, 0x56, 0x20, 0x60, 0xae, 0xe1, 0xec, 0xba, 0x8e, 0xb6, 0x3b, 0xe2, 0x94, 0x51, 0xb5, 0x8a, 0x8b, + 0xef, 0xe3, 0x55, 0x35, 0xb3, 0x43, 0x1b, 0xf9, 0x63, 0x3a, 0xfd, 0x7b, 0x12, 0xba, 0x85, 0x50, 0xb8, 0xe5, 0x16, + 0x46, 0x9e, 0xdc, 0x1e, 0x96, 0x71, 0x83, 0x5e, 0x89, 0x2b, 0xd5, 0x37, 0x2d, 0x85, 0x54, 0x23, 0x5f, 0xfb, 0x02, + 0x7a, 0x3d, 0xf6, 0x7e, 0x2a, 0xcc, 0xdb, 0x9e, 0x31, 0x97, 0x08, 0x56, 0xb2, 0xec, 0xf6, 0x9d, 0x1a, 0x53, 0x31, + 0x83, 0x2e, 0xb6, 0x9d, 0x45, 0xa7, 0x1b, 0xf9, 0xa7, 0x99, 0xfb, 0x65, 0xde, 0xe1, 0xae, 0xa8, 0xde, 0x02, 0x17, + 0x9a, 0x95, 0x55, 0xdd, 0x96, 0x0d, 0x9b, 0xc6, 0x6b, 0x59, 0x28, 0x36, 0xc0, 0xb0, 0xe7, 0xae, 0x85, 0x07, 0x88, + 0x9b, 0x70, 0xcf, 0x2e, 0x1a, 0xb8, 0x31, 0x7c, 0x5e, 0x49, 0xae, 0x2b, 0x8d, 0xbe, 0xf4, 0xc9, 0xd2, 0xaa, 0xe1, + 0x64, 0x31, 0xe2, 0x45, 0xba, 0x68, 0x32, 0xb3, 0x16, 0x3e, 0xe1, 0x65, 0x38, 0xe7, 0x0b, 0xad, 0x9b, 0x52, 0xa5, + 0x97, 0x2c, 0x56, 0x9d, 0xde, 0xac, 0x14, 0x56, 0x4a, 0xc4, 0x8d, 0x59, 0x26, 0x50, 0x96, 0xa2, 0x91, 0xc2, 0x9b, + 0xb2, 0x65, 0x2b, 0xa9, 0xe5, 0x3d, 0x73, 0x70, 0x1f, 0xfb, 0x01, 0x31, 0x91, 0x75, 0x60, 0x52, 0x34, 0x74, 0x40, + 0xbb, 0xea, 0xd2, 0x35, 0xa3, 0x1e, 0x0c, 0x72, 0x43, 0x12, 0xb1, 0x82, 0x14, 0x2b, 0x58, 0x37, 0xac, 0x9c, 0xe7, + 0x0b, 0x7a, 0xc9, 0xc4, 0x3c, 0x5d, 0xd0, 0x15, 0x13, 0xf3, 0x35, 0xde, 0x84, 0x2e, 0xe1, 0x84, 0x24, 0x9b, 0x58, + 0x2a, 0x60, 0x2f, 0xf1, 0xf2, 0x86, 0x67, 0xaa, 0xa2, 0x65, 0x57, 0x92, 0x03, 0x8c, 0x2f, 0xaa, 0x30, 0x2c, 0x86, + 0x97, 0x60, 0x2d, 0x71, 0x18, 0xae, 0xe6, 0x7c, 0x21, 0x7f, 0x43, 0xc0, 0xf9, 0x24, 0x94, 0xec, 0x82, 0xd9, 0x0b, + 0x64, 0x7a, 0x3d, 0xe7, 0x0b, 0x39, 0x12, 0xaa, 0xe0, 0x6b, 0x63, 0x6c, 0x12, 0x3b, 0x82, 0x96, 0x59, 0x3c, 0x1f, + 0x2f, 0xa2, 0xb8, 0x81, 0x65, 0x78, 0x26, 0x67, 0xa6, 0x25, 0xff, 0xd1, 0x76, 0x52, 0xea, 0x06, 0x2b, 0xc9, 0x1f, + 0x1e, 0x1f, 0x5d, 0x02, 0x19, 0x33, 0xbb, 0x82, 0xe9, 0x0f, 0x5d, 0x1f, 0x19, 0xdc, 0x73, 0x53, 0xce, 0xb8, 0x0c, + 0x12, 0xa5, 0x05, 0x0e, 0x72, 0x96, 0xb4, 0xb5, 0x08, 0xdf, 0x3d, 0x2a, 0xca, 0x3e, 0x13, 0xba, 0x01, 0xdd, 0x47, + 0x82, 0x3e, 0xd0, 0x7b, 0xa5, 0x0a, 0x97, 0xd5, 0x36, 0x13, 0x70, 0x17, 0x09, 0xf2, 0x5b, 0xa1, 0x53, 0x35, 0x06, + 0x55, 0x34, 0x8b, 0x58, 0xb8, 0xf7, 0x11, 0x37, 0xca, 0xe6, 0x9f, 0xfa, 0x1e, 0x2f, 0x25, 0x0c, 0x6e, 0x48, 0x4d, + 0x9f, 0xcc, 0x9b, 0x2b, 0xf6, 0x1e, 0x3a, 0xea, 0x50, 0x6b, 0xbc, 0xaf, 0x5e, 0x72, 0x0a, 0x31, 0x4a, 0x28, 0x3a, + 0x09, 0x06, 0x70, 0xbb, 0x84, 0x14, 0x7b, 0x83, 0xdd, 0xf8, 0xd7, 0xbc, 0x28, 0xb8, 0x58, 0xd7, 0x75, 0xe0, 0x06, + 0x34, 0x9c, 0x2f, 0x76, 0x43, 0x18, 0x8e, 0x69, 0xeb, 0x1a, 0x06, 0x61, 0xc6, 0x30, 0x12, 0x82, 0xd3, 0xbf, 0xe8, + 0x2b, 0x9a, 0xc4, 0xab, 0xef, 0xf8, 0x5f, 0x19, 0x2f, 0x25, 0x91, 0x06, 0x11, 0x52, 0x37, 0xf1, 0x8d, 0x74, 0x93, + 0x02, 0x0a, 0x01, 0x46, 0x01, 0x95, 0x58, 0xd3, 0x54, 0xfc, 0x2d, 0x17, 0x1f, 0xfc, 0x54, 0x74, 0x3c, 0x1a, 0x37, + 0xad, 0xce, 0xc8, 0xa0, 0x33, 0xd0, 0xa3, 0x56, 0xd4, 0xd3, 0xa0, 0x95, 0xa0, 0x1b, 0xa9, 0xdf, 0xda, 0x87, 0xc0, + 0x29, 0xd3, 0xe0, 0x9d, 0x07, 0x74, 0x73, 0xee, 0x82, 0x27, 0x8f, 0xe9, 0xb9, 0x45, 0x4f, 0xae, 0xd9, 0x49, 0xdd, + 0x43, 0xed, 0xbd, 0x1e, 0xa1, 0xa0, 0xdf, 0xc7, 0x14, 0xe8, 0x46, 0xd0, 0x38, 0x57, 0xf7, 0x1f, 0x8b, 0x5d, 0x0e, + 0xdf, 0x72, 0x96, 0x1b, 0xc0, 0x52, 0x11, 0x8d, 0x04, 0x8f, 0x02, 0xd4, 0xa5, 0x2a, 0x84, 0x2d, 0x66, 0x71, 0xa8, + 0xcc, 0x56, 0xad, 0x87, 0x82, 0x1c, 0x17, 0x23, 0x70, 0x08, 0x5d, 0x57, 0x83, 0x62, 0xb4, 0xcc, 0xea, 0xf7, 0xf8, + 0x5b, 0xb1, 0x0e, 0x49, 0xb6, 0x8f, 0x75, 0xe0, 0x86, 0x75, 0x98, 0x7e, 0xd4, 0x48, 0x01, 0x68, 0xb2, 0x11, 0xd8, + 0x04, 0xe0, 0xbd, 0xdd, 0x47, 0x84, 0x5a, 0x99, 0xee, 0x65, 0x2c, 0xe4, 0xf7, 0x5e, 0x12, 0x94, 0xe0, 0x27, 0xd4, + 0x96, 0xa5, 0xe0, 0x9d, 0x47, 0x3a, 0x27, 0x4d, 0x56, 0xbc, 0x07, 0x71, 0x5a, 0xf8, 0xc0, 0xde, 0x82, 0xe0, 0x9c, + 0x25, 0xbd, 0xc7, 0xdb, 0xac, 0x92, 0xda, 0xa8, 0x81, 0x02, 0xf8, 0xdd, 0xe0, 0x1e, 0x41, 0xbe, 0xbc, 0xe1, 0x5a, + 0x89, 0xdb, 0x90, 0x0f, 0x4b, 0x7a, 0x44, 0x06, 0xe6, 0xb9, 0x1a, 0xc6, 0xf4, 0x88, 0x1c, 0x9b, 0x67, 0x61, 0x07, + 0x70, 0x20, 0xd4, 0xa8, 0xd2, 0x23, 0x68, 0xd0, 0x6f, 0xa6, 0x45, 0x86, 0x64, 0xfd, 0xa8, 0x1b, 0x8c, 0x88, 0xbf, + 0x20, 0xa2, 0x2e, 0xfe, 0xf9, 0x60, 0xae, 0x7b, 0xcc, 0x05, 0xc2, 0x1c, 0x0c, 0x38, 0x88, 0xdb, 0x20, 0xd4, 0x07, + 0xcc, 0xe6, 0x2e, 0xaa, 0xe8, 0xbd, 0x31, 0xcc, 0xec, 0xe8, 0x0f, 0x37, 0x12, 0x7c, 0x9d, 0xb5, 0x41, 0x9d, 0x17, + 0x87, 0x40, 0x10, 0xdc, 0x17, 0xaa, 0x9a, 0xab, 0x1e, 0xd8, 0x78, 0xcb, 0x7e, 0x6c, 0xb7, 0xe3, 0x69, 0x65, 0xaf, + 0xfd, 0x15, 0x85, 0x93, 0x4f, 0xca, 0xbf, 0xde, 0xeb, 0x0c, 0x16, 0x8c, 0x0c, 0x5f, 0x3a, 0xfb, 0x17, 0xbe, 0x56, + 0xd2, 0xbd, 0x6a, 0x50, 0x90, 0xc7, 0x47, 0x92, 0xfe, 0xed, 0x95, 0x95, 0x4f, 0xcd, 0xf4, 0x6f, 0xb7, 0x7a, 0x7d, + 0x1e, 0x8f, 0x26, 0xdb, 0x6d, 0x4f, 0x19, 0xb8, 0x52, 0x1d, 0x43, 0x08, 0x9d, 0xeb, 0xc9, 0xe1, 0x11, 0x44, 0x45, + 0xf0, 0xe3, 0x6e, 0x16, 0x9e, 0x44, 0xc6, 0x8d, 0xd3, 0x59, 0x78, 0x82, 0x1d, 0xee, 0x44, 0x25, 0x2e, 0x46, 0xad, + 0x0d, 0x4e, 0xcf, 0x93, 0x10, 0x42, 0x39, 0x60, 0x65, 0x77, 0xf2, 0xcf, 0xbd, 0x34, 0x13, 0x92, 0x93, 0xd5, 0xed, + 0x94, 0xee, 0x60, 0x9a, 0x1f, 0xe8, 0x11, 0x1c, 0x70, 0x67, 0x7f, 0x35, 0x1f, 0xc3, 0x24, 0x53, 0xe4, 0x14, 0xc9, + 0x2f, 0xd2, 0x53, 0x48, 0xda, 0xa1, 0xa7, 0x92, 0x00, 0x4e, 0xa8, 0xf9, 0x18, 0x7e, 0xc3, 0xb8, 0x7f, 0xe7, 0xbf, + 0xb6, 0x53, 0x11, 0x3d, 0xa1, 0x58, 0xa6, 0x22, 0xa7, 0x49, 0x56, 0x26, 0x10, 0xb5, 0x51, 0x36, 0x23, 0xfa, 0xca, + 0xc6, 0x7c, 0x94, 0x84, 0xcf, 0xa9, 0xf5, 0x7f, 0x86, 0xf0, 0x69, 0x74, 0x46, 0x80, 0xcb, 0x2b, 0xaf, 0x2e, 0xc2, + 0xa7, 0x4f, 0xe8, 0xc1, 0xe4, 0xeb, 0x23, 0x7a, 0x70, 0xf4, 0xd5, 0x53, 0x02, 0xb0, 0x68, 0x57, 0x17, 0xe1, 0xd1, + 0xd3, 0xa7, 0xf4, 0xe0, 0xdb, 0x6f, 0xe9, 0xc1, 0xe4, 0xab, 0x23, 0x2f, 0x6d, 0xf2, 0xf4, 0x5b, 0x7a, 0xf0, 0xf5, + 0x13, 0x2f, 0xed, 0x68, 0xfc, 0x94, 0x1e, 0x7c, 0xf3, 0xb5, 0x4e, 0xfb, 0x1b, 0x64, 0xfb, 0xf6, 0x08, 0xff, 0xd3, + 0x69, 0x93, 0xa7, 0x5f, 0xd1, 0x83, 0xc9, 0x18, 0x2a, 0x79, 0x6a, 0x2b, 0x19, 0x4f, 0xe0, 0xe3, 0xaf, 0xe0, 0xbf, + 0xbf, 0x91, 0x60, 0x41, 0x6b, 0xc1, 0x92, 0x0a, 0xf5, 0x67, 0x28, 0xe2, 0x44, 0xd5, 0x44, 0xc2, 0x43, 0xcc, 0x2c, + 0xbf, 0x89, 0xc3, 0x80, 0xd8, 0x74, 0x28, 0x88, 0x1e, 0x8c, 0x47, 0x4f, 0x49, 0xe0, 0xc2, 0xd3, 0xdd, 0xba, 0x20, + 0x63, 0x49, 0x35, 0xcf, 0xbe, 0x48, 0x34, 0x63, 0xe0, 0x00, 0x58, 0x7d, 0x74, 0x73, 0xd5, 0x62, 0x9e, 0x7d, 0x51, + 0x8b, 0xdd, 0x5c, 0xbf, 0xb5, 0x00, 0xe5, 0xdd, 0x55, 0xcb, 0x6e, 0x4b, 0x19, 0x3a, 0xad, 0x35, 0xfa, 0xec, 0x23, + 0xa6, 0x0f, 0x06, 0xce, 0x0d, 0xfb, 0xef, 0x3b, 0xe5, 0xb4, 0xbe, 0x51, 0x28, 0xd4, 0xa8, 0x3c, 0x24, 0xec, 0x04, + 0x8a, 0x1e, 0x0c, 0x80, 0x27, 0x70, 0x70, 0xdf, 0xfe, 0xcd, 0x32, 0x3e, 0x76, 0x94, 0xf1, 0x33, 0xca, 0x10, 0xd0, + 0xa8, 0x87, 0x99, 0x4d, 0x0f, 0x1b, 0xdd, 0xe8, 0x25, 0x0b, 0x79, 0x32, 0xf9, 0x9e, 0xc1, 0xae, 0xd6, 0xb5, 0x38, + 0xd0, 0xa2, 0x68, 0x71, 0x79, 0x90, 0xf2, 0x59, 0xcd, 0xfe, 0xbe, 0x44, 0xf5, 0x56, 0xe4, 0xbd, 0x11, 0xd9, 0xac, + 0x66, 0xdf, 0xeb, 0x37, 0xc0, 0xcd, 0xb0, 0xdf, 0xe4, 0x93, 0x1b, 0x38, 0x83, 0x0b, 0xd3, 0x1e, 0x69, 0x62, 0x04, + 0x58, 0x01, 0x19, 0x38, 0xf0, 0x00, 0xe8, 0xa0, 0x3b, 0xda, 0xdb, 0xad, 0x4c, 0xf1, 0xfb, 0x6c, 0x60, 0x00, 0x35, + 0xf3, 0x36, 0xb1, 0x65, 0xff, 0xcb, 0x93, 0x97, 0xa0, 0x70, 0xcb, 0x2f, 0x6f, 0xa7, 0x30, 0x84, 0x10, 0xfc, 0x71, + 0xc9, 0x00, 0x70, 0x20, 0xc0, 0x60, 0xac, 0x55, 0x40, 0xf5, 0x96, 0x8f, 0x36, 0x5c, 0xaa, 0x27, 0x81, 0x33, 0xb8, + 0x14, 0x65, 0xc2, 0xdf, 0x2a, 0xb1, 0x3f, 0x5a, 0x3f, 0xba, 0xbe, 0x3d, 0x0e, 0xac, 0x7d, 0x8f, 0x8f, 0xd4, 0x67, + 0xde, 0x75, 0x60, 0xd3, 0xf2, 0x8d, 0xaf, 0x1a, 0x23, 0xf1, 0x28, 0x80, 0x37, 0xd0, 0x11, 0x29, 0x34, 0x52, 0x2d, + 0x70, 0x0c, 0x85, 0xb4, 0x40, 0x1c, 0x79, 0x75, 0x83, 0x2d, 0x88, 0x08, 0xc1, 0xc3, 0xed, 0x5f, 0x4b, 0x19, 0x38, + 0xaa, 0xdf, 0xe7, 0xc2, 0x75, 0x7b, 0xd2, 0x76, 0xe4, 0x38, 0xf5, 0x53, 0x07, 0xdf, 0x9c, 0x34, 0x8d, 0xb6, 0x5c, + 0x49, 0x99, 0x61, 0x59, 0xd8, 0x49, 0xa8, 0xe4, 0x1e, 0xb5, 0x03, 0xc9, 0x17, 0x72, 0x88, 0x64, 0x81, 0x51, 0x28, + 0xc8, 0x70, 0x42, 0xc1, 0x66, 0xaa, 0x5a, 0x66, 0x97, 0x75, 0xb8, 0x91, 0x0a, 0x65, 0x4e, 0xd1, 0xb7, 0x1b, 0x1c, + 0x48, 0x48, 0x94, 0x55, 0x6f, 0xe2, 0x37, 0x21, 0x82, 0xd5, 0x71, 0x65, 0x0b, 0xc5, 0x9d, 0xfd, 0xc9, 0xd3, 0x2e, + 0xfe, 0x48, 0xbb, 0x80, 0xda, 0x58, 0x4c, 0xc3, 0x89, 0x89, 0x7d, 0x63, 0xbf, 0x30, 0x9a, 0x1e, 0x80, 0xfa, 0xae, + 0xa4, 0x18, 0x41, 0x7e, 0xa5, 0xed, 0x63, 0x7b, 0x8c, 0x89, 0x19, 0xc4, 0x1a, 0x96, 0x39, 0x33, 0xd9, 0x37, 0xc2, + 0x4e, 0x00, 0xb8, 0x11, 0x5a, 0x23, 0x21, 0xf0, 0x78, 0x1d, 0xe2, 0x79, 0x29, 0xc3, 0xb7, 0x66, 0x84, 0x8e, 0xc1, + 0x9b, 0xca, 0x34, 0x32, 0x13, 0xae, 0x60, 0x50, 0x1f, 0xdb, 0x2a, 0x0a, 0xab, 0xa9, 0x2c, 0x3b, 0x01, 0xb8, 0x81, + 0xec, 0x58, 0x5f, 0x3c, 0x67, 0xf5, 0x3c, 0x5b, 0x44, 0x3a, 0x28, 0x60, 0x5e, 0x19, 0x06, 0xed, 0xcd, 0x1e, 0xd9, + 0x8e, 0x45, 0xe8, 0x86, 0xfb, 0x08, 0xc6, 0xd3, 0xf6, 0x05, 0x2b, 0x88, 0x46, 0x88, 0x87, 0x19, 0x33, 0xf8, 0x5e, + 0x69, 0xca, 0x53, 0xd9, 0x12, 0x08, 0x1c, 0x85, 0x50, 0x17, 0xbb, 0x46, 0x09, 0x36, 0x93, 0x17, 0xcc, 0x60, 0xc7, + 0x8e, 0xd4, 0x74, 0xc9, 0x3a, 0x1d, 0xca, 0x29, 0x2d, 0xd4, 0x94, 0x2a, 0x5f, 0xc3, 0x6a, 0x5e, 0xa0, 0x87, 0x1e, + 0xb8, 0x1e, 0x28, 0x87, 0xbc, 0x82, 0x4e, 0x74, 0x04, 0x9d, 0x56, 0x9b, 0xb0, 0x73, 0x23, 0xd5, 0xb2, 0x06, 0x79, + 0xc7, 0x50, 0xef, 0x88, 0x17, 0x4e, 0xa0, 0x2e, 0x84, 0x08, 0xd9, 0xdb, 0x22, 0x7d, 0x44, 0xb3, 0xac, 0x7a, 0x09, + 0x65, 0x71, 0xc4, 0xd6, 0x05, 0x2b, 0x6d, 0x34, 0xb9, 0xe4, 0x11, 0x4f, 0x11, 0x11, 0xf0, 0x54, 0x6a, 0xd7, 0x77, + 0x5a, 0x42, 0x68, 0x96, 0x02, 0x71, 0xb3, 0x51, 0x9c, 0x1b, 0x13, 0xc8, 0x02, 0xe8, 0xdb, 0x4f, 0xd9, 0xb5, 0x13, + 0x0e, 0x76, 0x73, 0x9d, 0x15, 0xcf, 0xf9, 0x65, 0x56, 0xf0, 0x14, 0xc1, 0xae, 0xee, 0xf4, 0x03, 0xb7, 0x6c, 0x1b, + 0x58, 0xbe, 0x7d, 0x07, 0x0b, 0xa6, 0x0a, 0x95, 0x52, 0x22, 0x2b, 0xa2, 0x0a, 0x32, 0xbb, 0xcc, 0xdd, 0xeb, 0xac, + 0x78, 0x1d, 0xdf, 0x81, 0x37, 0x85, 0xc7, 0x4f, 0x8f, 0x2e, 0xf0, 0x4b, 0x44, 0x12, 0x85, 0x18, 0xb6, 0x18, 0x11, + 0x0b, 0x91, 0x63, 0xc7, 0x84, 0x72, 0x29, 0x68, 0x6d, 0x0d, 0x81, 0x13, 0x7f, 0x5a, 0x76, 0xef, 0x3a, 0x2b, 0xb4, + 0x7d, 0xc6, 0x75, 0x7c, 0xc7, 0x0a, 0x09, 0x66, 0x81, 0x71, 0xee, 0xdb, 0x52, 0x92, 0xeb, 0xac, 0xd0, 0x02, 0x92, + 0xeb, 0xf8, 0x8e, 0xfa, 0x32, 0x0e, 0x65, 0x45, 0xe7, 0xc4, 0xf9, 0xdd, 0x1d, 0x7e, 0x81, 0xa1, 0x56, 0xc6, 0xfd, + 0x3e, 0x48, 0xcc, 0x84, 0x69, 0xca, 0x4c, 0x44, 0x42, 0xa1, 0x85, 0xd4, 0x94, 0x0f, 0x26, 0x64, 0x77, 0xa5, 0x1a, + 0x46, 0xd4, 0x7c, 0x15, 0x56, 0xb3, 0x71, 0x34, 0x21, 0x74, 0xd2, 0xb1, 0xde, 0x75, 0x6b, 0x21, 0xd3, 0xe8, 0x69, + 0xe4, 0xf8, 0x74, 0x96, 0xac, 0x9e, 0x96, 0xc7, 0x8c, 0x4f, 0xcb, 0xc1, 0x80, 0xa8, 0xd0, 0xc1, 0x1b, 0xac, 0x07, + 0x4c, 0x69, 0x6c, 0xbc, 0x35, 0xdd, 0xea, 0x97, 0x42, 0x86, 0xa4, 0x77, 0x0c, 0x48, 0x32, 0x61, 0x83, 0xdd, 0x82, + 0x44, 0xd1, 0xf1, 0xbf, 0x93, 0x5b, 0x70, 0xd7, 0x83, 0xd1, 0x8f, 0xee, 0xeb, 0x18, 0xff, 0xa1, 0xb6, 0x05, 0x51, + 0x9f, 0x2a, 0xd6, 0xeb, 0x48, 0x94, 0x21, 0x17, 0xe1, 0x67, 0x47, 0x43, 0x34, 0x51, 0xed, 0xb1, 0xa0, 0x58, 0x5f, + 0x5f, 0xf0, 0x12, 0xa7, 0x9f, 0xd9, 0xcb, 0x15, 0x6c, 0x0b, 0x5a, 0x6b, 0x1a, 0xf5, 0x26, 0x7e, 0x13, 0x99, 0xcb, + 0x82, 0x2a, 0xf2, 0x39, 0x0a, 0x59, 0xf3, 0x30, 0xac, 0x87, 0xed, 0x41, 0x24, 0x87, 0xed, 0x49, 0xf0, 0x1a, 0x03, + 0x0b, 0x64, 0x87, 0x46, 0xe0, 0x22, 0x34, 0xf2, 0xb7, 0x63, 0x70, 0xe1, 0x32, 0x88, 0x2c, 0x43, 0x15, 0xbf, 0xa9, + 0xdd, 0x04, 0xd9, 0x2b, 0x74, 0x9a, 0xc2, 0xaa, 0xa4, 0x49, 0x3e, 0xfc, 0x7a, 0x29, 0x4a, 0xcc, 0xe4, 0x74, 0xd9, + 0xa1, 0xaf, 0xed, 0xf6, 0x0e, 0x74, 0xc1, 0xaa, 0x4f, 0xce, 0xd7, 0x8f, 0x3b, 0x7b, 0x02, 0x46, 0xb1, 0x32, 0x87, + 0x2f, 0xa4, 0x54, 0x3e, 0x28, 0xcd, 0xc7, 0x30, 0xaf, 0x14, 0xc7, 0x6e, 0x00, 0x93, 0x80, 0x7d, 0x86, 0x54, 0x87, + 0x69, 0xc7, 0x3e, 0x47, 0x1b, 0x58, 0x12, 0x70, 0xf8, 0x47, 0x99, 0x68, 0xdc, 0xab, 0x7b, 0x95, 0xfa, 0x21, 0x5b, + 0xe6, 0x0b, 0xe0, 0xf3, 0x61, 0xd7, 0x46, 0x05, 0xca, 0x26, 0x22, 0x41, 0x61, 0xcb, 0x63, 0x90, 0xf6, 0x28, 0xa6, + 0xab, 0x92, 0x27, 0x19, 0x4a, 0x29, 0x12, 0xe5, 0x13, 0x9c, 0xc3, 0x1b, 0xdc, 0x8f, 0x32, 0x20, 0xbc, 0x0c, 0x39, + 0x1d, 0xa5, 0x54, 0x59, 0xc0, 0x48, 0xea, 0x01, 0xa2, 0xbc, 0x0c, 0xe4, 0x78, 0xdb, 0xed, 0x84, 0xae, 0xd8, 0x72, + 0x38, 0xa1, 0x48, 0x4a, 0xae, 0xb0, 0xdc, 0x6b, 0xd0, 0x79, 0x5c, 0xb0, 0xde, 0x0b, 0xc0, 0x22, 0x38, 0x87, 0xbf, + 0x31, 0xa1, 0x37, 0xf0, 0x37, 0x27, 0xf4, 0x35, 0x0b, 0xaf, 0x87, 0x57, 0xe4, 0x30, 0x4c, 0x07, 0x13, 0x29, 0x18, + 0xbb, 0x67, 0xcb, 0x22, 0x94, 0x89, 0xab, 0xc3, 0x4b, 0xf2, 0xf8, 0x92, 0xde, 0xd1, 0x5b, 0x7a, 0x46, 0xdf, 0x02, + 0xe1, 0xbf, 0x3f, 0x9e, 0xf0, 0xe1, 0xe4, 0x49, 0xbf, 0xdf, 0xbb, 0xe8, 0xf7, 0x7b, 0xe7, 0xda, 0x80, 0x42, 0xed, + 0xa2, 0xab, 0x86, 0xaa, 0x5f, 0xd7, 0xcd, 0x62, 0xfa, 0x56, 0x6e, 0xdc, 0x84, 0x67, 0x79, 0x78, 0x7d, 0x78, 0x4f, + 0x86, 0xf8, 0x78, 0x99, 0x0b, 0x51, 0x86, 0x57, 0x87, 0xf7, 0x84, 0xbe, 0x3d, 0x01, 0xbd, 0x29, 0xd6, 0xf7, 0xf6, + 0xf1, 0xbd, 0xaa, 0x8d, 0xd0, 0x17, 0x61, 0x02, 0xdb, 0xe4, 0x8e, 0x99, 0xbb, 0xf6, 0x64, 0x0c, 0xb1, 0x4c, 0xee, + 0x9d, 0xf2, 0xee, 0x1f, 0xdf, 0x91, 0xc3, 0x3b, 0xf0, 0x14, 0x35, 0xe4, 0x6f, 0x16, 0xde, 0xb2, 0x56, 0x0d, 0x8f, + 0xef, 0xe9, 0x59, 0xab, 0x11, 0x8f, 0xef, 0x49, 0x14, 0xde, 0xb2, 0x2b, 0x7a, 0xc6, 0xae, 0x09, 0xbd, 0xe8, 0xf7, + 0xcf, 0xfb, 0x7d, 0xd1, 0xef, 0xff, 0x3d, 0x0e, 0xc3, 0x78, 0x58, 0x92, 0x43, 0x41, 0xef, 0x0f, 0x27, 0xfc, 0x2b, + 0x32, 0x0b, 0x55, 0xf3, 0xe5, 0x82, 0x33, 0x2a, 0x6f, 0x99, 0xeb, 0x9e, 0x82, 0xb5, 0xc2, 0x3d, 0x93, 0x4f, 0x6f, + 0xe9, 0x2d, 0x2b, 0xe9, 0x19, 0x8b, 0x49, 0x74, 0x03, 0xad, 0xb8, 0x98, 0x95, 0xd1, 0x2d, 0x3d, 0x63, 0xe7, 0xb3, + 0x38, 0x3a, 0xa3, 0x6f, 0x59, 0x3e, 0x9c, 0x40, 0xde, 0xb3, 0xe1, 0x2d, 0x39, 0x7c, 0x4b, 0xa2, 0xf0, 0xad, 0xfa, + 0x7d, 0x4f, 0xaf, 0x78, 0xf8, 0x96, 0x3a, 0xd5, 0xbc, 0x25, 0xba, 0x7a, 0xaf, 0xf6, 0xb7, 0x24, 0x72, 0x07, 0xf3, + 0xad, 0xb1, 0xa7, 0x79, 0x64, 0x69, 0x63, 0x5a, 0x84, 0xa0, 0x6f, 0x2e, 0xc2, 0x5b, 0x42, 0xa6, 0xfe, 0xd8, 0xc1, + 0x80, 0xce, 0x1e, 0x45, 0x09, 0xa1, 0xb7, 0x6e, 0xa9, 0xb7, 0x38, 0x86, 0x7a, 0x84, 0x64, 0xda, 0x19, 0xa6, 0xe1, + 0x3a, 0x78, 0xa5, 0xc0, 0x3a, 0x2e, 0xfa, 0xfd, 0x70, 0xdd, 0xef, 0x43, 0xa4, 0xfb, 0x72, 0xa6, 0x63, 0xbb, 0x59, + 0xb2, 0x49, 0x6f, 0x41, 0xfb, 0xff, 0x6a, 0x30, 0x80, 0xce, 0x38, 0x25, 0x85, 0xb7, 0x83, 0x57, 0x8f, 0xef, 0x89, + 0xac, 0xa3, 0xa4, 0x95, 0x08, 0x4b, 0xfa, 0x9a, 0x66, 0x00, 0xf8, 0xf5, 0x6a, 0x30, 0x20, 0x91, 0xfe, 0x8c, 0x4c, + 0x5f, 0x1d, 0xbf, 0x9d, 0x0e, 0x06, 0xaf, 0xf4, 0x36, 0xf9, 0x8b, 0xed, 0x29, 0x05, 0xd6, 0xdf, 0x79, 0xbf, 0xff, + 0xd7, 0x49, 0x4c, 0x2e, 0x4a, 0x1e, 0x7f, 0x9c, 0xfa, 0x6d, 0xf9, 0xcb, 0x46, 0x55, 0x3b, 0xef, 0xf7, 0xd7, 0xfd, + 0xfe, 0x19, 0x60, 0x17, 0xcd, 0xac, 0xaf, 0x27, 0x48, 0x5b, 0xe6, 0x96, 0x22, 0x29, 0x92, 0x43, 0x63, 0x68, 0x5b, + 0x2c, 0xdb, 0x36, 0xeb, 0xc8, 0xc0, 0xe2, 0xc8, 0xaf, 0x28, 0x6e, 0x48, 0x14, 0xf6, 0xce, 0xb7, 0xdb, 0x33, 0xc6, + 0x58, 0x4c, 0x40, 0xfa, 0xe1, 0xbe, 0x3e, 0x6b, 0xbc, 0x18, 0x62, 0x95, 0x40, 0x66, 0x73, 0xb3, 0x34, 0x87, 0x40, + 0xc4, 0x61, 0xd3, 0xbf, 0xd7, 0xf7, 0xf2, 0xaa, 0xb1, 0x7c, 0xeb, 0xcf, 0x00, 0x42, 0x24, 0x58, 0xc8, 0x67, 0x38, + 0x06, 0x55, 0x06, 0xc0, 0xbf, 0x91, 0x9c, 0x79, 0x01, 0xa0, 0xe6, 0x64, 0xbb, 0x1d, 0x8d, 0xc7, 0x13, 0x5a, 0xb2, + 0xd1, 0xdf, 0x9e, 0x3e, 0xae, 0x1f, 0x87, 0x41, 0x30, 0xc8, 0x48, 0x4b, 0x4f, 0x61, 0x16, 0x6b, 0x7d, 0x08, 0x46, + 0xf0, 0x8a, 0x7d, 0xbc, 0xc9, 0x3e, 0x9b, 0x7d, 0x44, 0xc2, 0xea, 0x31, 0x8e, 0xbc, 0x48, 0x5b, 0x7a, 0xbb, 0x3d, + 0x0c, 0x26, 0x2f, 0xd2, 0x4f, 0xb0, 0x9d, 0x2e, 0xff, 0xe6, 0xc0, 0x78, 0xc2, 0xc1, 0x68, 0x2f, 0x0a, 0xea, 0x4c, + 0xdb, 0x6e, 0x6b, 0xf7, 0x12, 0xf8, 0x06, 0x53, 0x41, 0xc7, 0x66, 0x58, 0xb8, 0x41, 0x4d, 0xe4, 0xd1, 0x32, 0xa8, + 0x1b, 0x69, 0x3b, 0x07, 0xd4, 0x12, 0xab, 0xd2, 0x71, 0x0b, 0x34, 0x43, 0x86, 0xba, 0xdc, 0xd3, 0xfa, 0x5f, 0xbc, + 0x14, 0x1a, 0x3e, 0xc3, 0x8a, 0x08, 0x1d, 0x6e, 0x8d, 0xbb, 0xdc, 0x5a, 0xf5, 0x09, 0x6e, 0xad, 0x40, 0x12, 0xab, + 0x61, 0x49, 0xf5, 0xe5, 0x28, 0x61, 0x27, 0x05, 0xe3, 0x33, 0xa0, 0xe3, 0x31, 0x3c, 0x08, 0x56, 0xcd, 0x44, 0x94, + 0xa0, 0x7d, 0xa2, 0x8d, 0x30, 0xf8, 0x27, 0x60, 0xf6, 0xd3, 0x1c, 0xfe, 0x0a, 0x32, 0x4d, 0x8e, 0x21, 0x20, 0xc4, + 0xf1, 0x78, 0x16, 0x87, 0x63, 0x12, 0x25, 0x27, 0xf0, 0x04, 0xff, 0x95, 0xe1, 0x98, 0x34, 0xea, 0x0e, 0x23, 0xe4, + 0xe5, 0x36, 0x61, 0x00, 0x57, 0x36, 0x9e, 0x4d, 0x22, 0x23, 0xdd, 0x15, 0x8f, 0x47, 0xe3, 0xa7, 0x64, 0x1a, 0x87, + 0x62, 0x90, 0x10, 0x0a, 0xde, 0xbd, 0x61, 0x31, 0x4c, 0x14, 0x3c, 0x1b, 0xb0, 0x79, 0x85, 0x65, 0xf3, 0x04, 0x9c, + 0x80, 0x30, 0x4c, 0xc8, 0xb1, 0xee, 0x41, 0x4a, 0x51, 0xe7, 0x39, 0xf6, 0x53, 0x1d, 0x41, 0x98, 0x1d, 0xb5, 0x54, + 0x7c, 0x05, 0x40, 0x97, 0x38, 0x38, 0xd4, 0x20, 0x61, 0x54, 0xb3, 0xb0, 0x70, 0xa8, 0x94, 0xae, 0xee, 0xb0, 0xf2, + 0x28, 0xbf, 0x6e, 0xd0, 0x61, 0x45, 0x06, 0x13, 0x5a, 0x9c, 0x4c, 0xf8, 0x57, 0x10, 0xc0, 0xc3, 0x8b, 0xf8, 0x25, + 0x71, 0x62, 0x20, 0xbc, 0x0a, 0x32, 0x50, 0x69, 0x23, 0x1b, 0x33, 0x32, 0x15, 0x1f, 0x40, 0x98, 0x94, 0x83, 0x5b, + 0xb1, 0xce, 0x53, 0x88, 0x0a, 0xb6, 0xce, 0xeb, 0x83, 0x2b, 0xb0, 0x64, 0x8f, 0x6b, 0x88, 0x13, 0xb6, 0x5e, 0x01, + 0x76, 0xee, 0xa3, 0x4d, 0xd1, 0x1c, 0xc8, 0xef, 0x0e, 0xb0, 0xe5, 0xf0, 0xaa, 0x16, 0x07, 0x93, 0xf1, 0x78, 0x3c, + 0xfa, 0x1d, 0x8e, 0x0e, 0x20, 0xb4, 0x24, 0xd2, 0x7c, 0x32, 0x40, 0xe3, 0xae, 0x6b, 0xee, 0x8c, 0x0b, 0x45, 0x59, + 0xe9, 0x64, 0x42, 0x40, 0xfc, 0xac, 0xfb, 0x06, 0xfb, 0x8a, 0xab, 0xf8, 0x27, 0xbb, 0x9f, 0xe8, 0x15, 0x2d, 0x57, + 0xea, 0xe8, 0xdd, 0xdb, 0xb3, 0x57, 0x1f, 0x5e, 0xfd, 0xfa, 0xe2, 0xfc, 0xd5, 0x9b, 0x97, 0xaf, 0xde, 0xbc, 0xfa, + 0xf0, 0xcf, 0x07, 0x18, 0x6c, 0xd7, 0x56, 0xc4, 0x8c, 0xbd, 0x73, 0x8f, 0x71, 0x6a, 0x71, 0x85, 0xb3, 0x47, 0xf6, + 0x16, 0x0b, 0xb0, 0x09, 0x9a, 0x5b, 0xa8, 0xa8, 0x62, 0x34, 0x6a, 0x75, 0x4f, 0x40, 0x46, 0xa3, 0x46, 0x36, 0x1e, + 0x56, 0x6c, 0x8d, 0x5c, 0xbc, 0x65, 0x38, 0xf8, 0xc8, 0xfc, 0x96, 0x9c, 0x09, 0x37, 0xa3, 0xad, 0x58, 0x11, 0xf0, + 0xf9, 0x5a, 0x17, 0xb5, 0xc3, 0x85, 0xc8, 0xbd, 0x6d, 0x9e, 0x43, 0x42, 0x1d, 0x22, 0xd7, 0xc1, 0xfb, 0x7a, 0x64, + 0x8f, 0x8f, 0x9c, 0x27, 0xe9, 0x19, 0xea, 0x72, 0x34, 0x7c, 0xe4, 0x3d, 0xa3, 0x13, 0x73, 0xa3, 0x75, 0xa8, 0xe7, + 0x25, 0xec, 0x6f, 0x29, 0xc6, 0x86, 0x68, 0x0f, 0x29, 0x62, 0x7d, 0x58, 0xdd, 0xef, 0xee, 0xcd, 0xe8, 0x7b, 0x38, + 0x7e, 0xa4, 0x6a, 0x02, 0x69, 0x51, 0x20, 0x75, 0x65, 0xc8, 0x6d, 0xcf, 0xc2, 0x52, 0xff, 0x0c, 0x3d, 0x02, 0x68, + 0x2e, 0x3b, 0x86, 0x04, 0xea, 0xc5, 0x6b, 0x5c, 0xff, 0x9c, 0x7c, 0x59, 0xd1, 0xce, 0x17, 0xdf, 0x41, 0x88, 0x61, + 0xf7, 0x8a, 0xe0, 0x4d, 0xb8, 0x9d, 0x64, 0x7b, 0x69, 0xd1, 0xf7, 0xaa, 0xeb, 0x18, 0x8f, 0xbb, 0x3d, 0x57, 0x0a, + 0xff, 0xd6, 0x05, 0xf6, 0x40, 0xfe, 0x75, 0xbc, 0x60, 0x21, 0x60, 0x33, 0x1e, 0x9a, 0x45, 0x62, 0xfd, 0xde, 0xe9, + 0x84, 0x1c, 0x1e, 0x4d, 0xf9, 0x90, 0x15, 0xb4, 0x1a, 0xb0, 0xa2, 0xd9, 0xa1, 0xe6, 0xbc, 0x4d, 0xc8, 0xab, 0x5d, + 0x1a, 0x5e, 0x0d, 0xf9, 0x43, 0x97, 0xa4, 0x0f, 0xdc, 0x73, 0xa8, 0x36, 0xcd, 0xc5, 0x90, 0xa6, 0x9c, 0xee, 0x52, + 0x19, 0x10, 0x22, 0x5d, 0xc7, 0x35, 0x69, 0xd4, 0x51, 0xb5, 0xb4, 0x92, 0x8e, 0x9b, 0x6c, 0xf3, 0x89, 0x4b, 0xb6, + 0xbc, 0x5d, 0xbb, 0xd7, 0xea, 0xf6, 0x85, 0x19, 0xc8, 0xdf, 0x1f, 0x88, 0x6a, 0xa2, 0x21, 0xba, 0x80, 0x0a, 0xfe, + 0x01, 0x5e, 0x9e, 0x3c, 0x52, 0x0a, 0xd0, 0x7d, 0x67, 0x47, 0xd7, 0x1e, 0xf7, 0x66, 0xb1, 0xb5, 0xc4, 0x39, 0xab, + 0x5d, 0x67, 0x79, 0x59, 0xb6, 0x44, 0xd7, 0xa9, 0xd8, 0xcf, 0x61, 0x47, 0xdf, 0x9d, 0x6d, 0x00, 0x44, 0x29, 0xac, + 0xed, 0xd9, 0x5f, 0x39, 0x67, 0x7f, 0x65, 0xce, 0x7e, 0xb3, 0x09, 0xa4, 0x0f, 0x2b, 0xb4, 0xec, 0xa5, 0x28, 0x6a, + 0xdd, 0xe4, 0xb1, 0xaf, 0xcb, 0x42, 0x5a, 0xcc, 0x0f, 0x0d, 0xed, 0x7a, 0x32, 0xa6, 0x02, 0xd5, 0x23, 0x3f, 0x60, + 0xab, 0x0e, 0x0b, 0xf2, 0xf0, 0x3d, 0xf3, 0x7f, 0xf6, 0x06, 0xb9, 0xef, 0x6e, 0xf7, 0x7f, 0x73, 0xa1, 0x83, 0xdb, + 0xda, 0xb2, 0x72, 0xd4, 0xd5, 0x71, 0x89, 0x77, 0xb5, 0xe5, 0xc3, 0x77, 0xb5, 0x77, 0x99, 0x5a, 0x76, 0x35, 0xa0, + 0x06, 0x15, 0xeb, 0x6b, 0x5e, 0x66, 0x49, 0x63, 0x14, 0x1a, 0x6f, 0x39, 0x84, 0xf6, 0x70, 0x0e, 0x2e, 0x90, 0xc3, + 0x12, 0x42, 0x3f, 0xd6, 0x5a, 0x00, 0xe8, 0xb2, 0xd8, 0x6f, 0x79, 0x98, 0x91, 0x81, 0x2b, 0xf1, 0x2b, 0x84, 0x2b, + 0x2e, 0x3e, 0xdc, 0xc9, 0x4c, 0xd0, 0xab, 0xc4, 0x46, 0xcd, 0x15, 0xed, 0x98, 0x1f, 0xee, 0x17, 0x18, 0x0d, 0xc2, + 0x69, 0x4b, 0x76, 0x58, 0x75, 0xcc, 0x72, 0x0d, 0x47, 0x6d, 0x61, 0xcb, 0x2c, 0x5a, 0xd7, 0xcf, 0x7a, 0x98, 0xa9, + 0x33, 0xe5, 0x2d, 0xc8, 0xbe, 0x90, 0xbb, 0x9f, 0xaa, 0x8a, 0x2b, 0x72, 0x32, 0x19, 0x4f, 0x49, 0x35, 0x18, 0xb4, + 0x92, 0x8f, 0x31, 0x79, 0x38, 0xdc, 0x61, 0x2e, 0x2b, 0xd5, 0x0f, 0xa7, 0x0f, 0x50, 0x9f, 0xb7, 0x25, 0xc9, 0xa6, + 0x66, 0x7f, 0x82, 0x59, 0x2c, 0x10, 0x47, 0x0b, 0xbf, 0x38, 0x5f, 0x00, 0xc8, 0x32, 0x2c, 0x33, 0x25, 0x2c, 0x82, + 0x2b, 0x3d, 0x74, 0xb2, 0x64, 0xe2, 0x78, 0x3c, 0x73, 0x7b, 0x6e, 0x19, 0x1c, 0x42, 0xa2, 0x89, 0x31, 0x7e, 0x71, + 0xb3, 0x60, 0x1c, 0x87, 0xe2, 0x44, 0x78, 0xdf, 0x15, 0x24, 0x1a, 0x6b, 0x53, 0x65, 0x75, 0x95, 0xa8, 0x87, 0x09, + 0x79, 0x5c, 0x92, 0xc3, 0x92, 0x2e, 0xdd, 0xb1, 0xc4, 0xf4, 0xc3, 0xf8, 0x70, 0x32, 0x26, 0x8f, 0xe3, 0xc7, 0x13, + 0x0d, 0x37, 0xec, 0xe6, 0xc8, 0x87, 0x4b, 0x72, 0xe8, 0x57, 0x09, 0xa6, 0xa8, 0xba, 0x67, 0x6e, 0x25, 0xc9, 0x60, + 0x39, 0x48, 0x1f, 0xb7, 0xf2, 0x62, 0xad, 0x6a, 0xbc, 0xd7, 0xc7, 0x7c, 0x4a, 0x2a, 0xef, 0xc6, 0xb0, 0xa6, 0xd7, + 0xf1, 0x1f, 0xa2, 0x8c, 0x0a, 0x01, 0x88, 0x84, 0xa0, 0xde, 0xce, 0x2e, 0xb3, 0x24, 0x2e, 0xd2, 0x28, 0x6d, 0x08, + 0x4d, 0x4f, 0xd8, 0x64, 0x3c, 0x4b, 0x59, 0x7a, 0x3c, 0x79, 0x3a, 0x9b, 0x3c, 0x8d, 0x8e, 0xc6, 0x51, 0x3a, 0x18, + 0x40, 0xf2, 0xd1, 0x18, 0x5c, 0xec, 0xe0, 0x37, 0x3b, 0x82, 0xa1, 0x3b, 0x41, 0x96, 0xb0, 0x84, 0xa6, 0x7d, 0x5e, + 0x93, 0xd4, 0x70, 0x5e, 0xca, 0x9e, 0xc4, 0x77, 0x74, 0xed, 0x38, 0xb8, 0xb8, 0x2d, 0xbc, 0xb4, 0x2d, 0xbc, 0xdc, + 0x6d, 0xa1, 0xb6, 0x20, 0x28, 0xc5, 0xff, 0x8f, 0x1b, 0xc6, 0xbe, 0xbb, 0x84, 0x5e, 0x5c, 0x37, 0xd9, 0x68, 0x55, + 0x8a, 0x5a, 0xc0, 0x6d, 0x42, 0x8a, 0xc2, 0x46, 0xf1, 0x6a, 0x95, 0x2b, 0x17, 0xb1, 0x79, 0x4d, 0x01, 0xdc, 0x05, + 0xce, 0x56, 0x60, 0xa1, 0xb5, 0x81, 0xdc, 0x5f, 0xbc, 0x14, 0xcc, 0xa8, 0x7d, 0xf4, 0x3d, 0xf2, 0x8f, 0x10, 0xc1, + 0x96, 0x4e, 0xc6, 0xb3, 0x0a, 0x11, 0x2d, 0x3e, 0x25, 0xef, 0xfd, 0x37, 0x8e, 0x22, 0x73, 0x34, 0x8f, 0x51, 0xa1, + 0x65, 0x3c, 0xe2, 0xcc, 0xc9, 0xe4, 0x64, 0xe0, 0x6e, 0x06, 0x23, 0xfd, 0xb5, 0xb7, 0x19, 0x63, 0xdb, 0xa3, 0x7a, + 0xa1, 0x85, 0xa2, 0x7f, 0xe1, 0x3b, 0x5d, 0x2f, 0xe0, 0x12, 0xca, 0x81, 0x5d, 0x5f, 0x5d, 0xf1, 0x0a, 0x40, 0x84, + 0xb2, 0xa2, 0xdf, 0xef, 0xfd, 0xa1, 0xa1, 0x49, 0x2b, 0x5e, 0xbe, 0xce, 0x0a, 0xe3, 0x8c, 0x03, 0x4d, 0x05, 0xea, + 0xff, 0xb1, 0x36, 0xcf, 0x74, 0x4c, 0x66, 0xee, 0xe3, 0x70, 0x42, 0x22, 0xff, 0x35, 0xf9, 0xc4, 0x69, 0xfa, 0x89, + 0x2b, 0xda, 0x7f, 0x20, 0x33, 0xd7, 0x1c, 0x32, 0xd4, 0x5f, 0x58, 0xe6, 0x49, 0xeb, 0x75, 0x62, 0x76, 0x52, 0xb1, + 0x7a, 0x06, 0xe8, 0xe9, 0x25, 0x3c, 0xc8, 0x6b, 0x59, 0x3c, 0x85, 0xd9, 0x07, 0x35, 0x62, 0x75, 0xcc, 0xc6, 0xb3, + 0x50, 0x84, 0x13, 0xb0, 0xef, 0x9d, 0x8c, 0xe1, 0x3e, 0x20, 0xc2, 0x8f, 0x75, 0x58, 0x51, 0x94, 0x92, 0x97, 0xf0, + 0x1b, 0x14, 0x13, 0x00, 0x11, 0x08, 0x79, 0xfb, 0x7d, 0x21, 0x93, 0xf0, 0x75, 0x81, 0x29, 0xa5, 0xfc, 0xe0, 0x3f, + 0x91, 0xaa, 0x5b, 0xa6, 0x5f, 0xae, 0x1f, 0x77, 0x26, 0x24, 0x9f, 0x6e, 0x53, 0xe2, 0x3b, 0x08, 0xee, 0x2c, 0x40, + 0x07, 0x51, 0xa3, 0x19, 0xdb, 0xc3, 0xfc, 0x6e, 0xb5, 0x9f, 0xdf, 0xad, 0xfe, 0xdf, 0xf1, 0xbb, 0xd5, 0x43, 0x8c, + 0x61, 0x6d, 0xa0, 0xe1, 0x67, 0xc1, 0x38, 0x88, 0xfe, 0x73, 0x3e, 0x71, 0x2f, 0x4f, 0x7d, 0x9d, 0x15, 0xd3, 0x3d, + 0x4c, 0xb3, 0x4b, 0x50, 0x10, 0x56, 0x71, 0x97, 0x9e, 0xac, 0x6b, 0x73, 0x6b, 0x25, 0x43, 0xcc, 0xf3, 0x00, 0x6b, + 0x14, 0xd6, 0x0e, 0xd0, 0x3d, 0xaa, 0x36, 0x88, 0x15, 0xc1, 0xc3, 0x98, 0x19, 0xe9, 0xfb, 0x76, 0xab, 0x55, 0x98, + 0x0f, 0x72, 0x51, 0x90, 0x5d, 0x7f, 0x3c, 0x1b, 0x47, 0x21, 0x36, 0xe0, 0x3f, 0x66, 0xac, 0x3c, 0xd9, 0x7c, 0x27, + 0x23, 0xb5, 0x63, 0xf2, 0x34, 0xd9, 0x25, 0xbd, 0x03, 0xde, 0x21, 0x3f, 0x6f, 0x3e, 0x86, 0xa5, 0xd0, 0xfc, 0x96, + 0xb8, 0x8a, 0xcb, 0xac, 0x5e, 0x5e, 0x67, 0x09, 0x32, 0x5d, 0xf0, 0xe2, 0xb3, 0x99, 0x2e, 0xe7, 0x63, 0x75, 0xc0, + 0x38, 0x4a, 0xf1, 0xc6, 0x13, 0xa5, 0xa7, 0x2d, 0xcf, 0x0a, 0x79, 0x79, 0x92, 0x31, 0xdb, 0xb3, 0x0a, 0x9c, 0x4e, + 0xc1, 0x04, 0x5f, 0xfd, 0xb4, 0xbd, 0x8f, 0x01, 0x17, 0x14, 0x6a, 0x4e, 0x4b, 0xb1, 0xd2, 0x58, 0x4e, 0x06, 0xba, + 0x13, 0x30, 0x43, 0x45, 0x81, 0x17, 0x28, 0xf8, 0x8b, 0x06, 0x46, 0xf4, 0xa5, 0xfd, 0x4d, 0x06, 0x1a, 0xe9, 0x52, + 0x9f, 0x08, 0x63, 0xcb, 0xed, 0x94, 0x69, 0x2b, 0xca, 0x19, 0x67, 0xef, 0xe5, 0x95, 0x02, 0x0c, 0xf0, 0x36, 0xb7, + 0xd1, 0x45, 0x82, 0x5e, 0x0b, 0x52, 0xe7, 0x0d, 0xdc, 0xcd, 0x32, 0xd2, 0xc2, 0xc5, 0xc7, 0xb5, 0xc3, 0x82, 0x3b, + 0xf6, 0x0b, 0xb1, 0xd0, 0x9a, 0x69, 0x30, 0x66, 0x73, 0x82, 0x05, 0x56, 0x32, 0x50, 0x60, 0x31, 0x53, 0x96, 0xa6, + 0xf5, 0x90, 0x1f, 0x1e, 0xa1, 0xb5, 0x69, 0x3d, 0xe0, 0x87, 0x47, 0x4d, 0x94, 0x1d, 0x43, 0x96, 0x13, 0x37, 0x83, + 0x7c, 0xdd, 0x44, 0x3a, 0x45, 0x67, 0x77, 0xeb, 0x4b, 0xdd, 0x51, 0xdd, 0x80, 0xeb, 0x07, 0x20, 0x80, 0x0d, 0xc0, + 0x21, 0x50, 0x0e, 0x96, 0x42, 0x04, 0x8b, 0x32, 0x89, 0xf6, 0x35, 0x74, 0xde, 0x28, 0xf8, 0x2f, 0x70, 0x17, 0x11, + 0x2b, 0xf7, 0x13, 0x04, 0xfe, 0x8a, 0x32, 0xa5, 0x4c, 0x71, 0x3f, 0x51, 0xea, 0x15, 0xca, 0x99, 0x6f, 0xcd, 0x07, + 0xd1, 0x9a, 0x08, 0x55, 0x8c, 0x21, 0xf8, 0xb7, 0xb2, 0x4c, 0x59, 0xaa, 0x4a, 0xf5, 0xa1, 0xf6, 0x5a, 0x2b, 0xad, + 0xe5, 0xe3, 0xc8, 0x79, 0x8d, 0xa1, 0x63, 0x13, 0x6b, 0x29, 0x27, 0x53, 0x67, 0x6f, 0x0e, 0x45, 0x64, 0x01, 0xa7, + 0x13, 0x36, 0x9e, 0x26, 0xc7, 0x62, 0x9a, 0x58, 0xc8, 0xfc, 0x9c, 0x61, 0x64, 0x55, 0x0d, 0xc2, 0x22, 0x6d, 0x28, + 0x4d, 0x01, 0x3a, 0x39, 0x21, 0x64, 0x8a, 0xa1, 0x28, 0xf2, 0x91, 0xea, 0x87, 0xf1, 0x66, 0xb5, 0x5f, 0xbc, 0x53, + 0x00, 0xa7, 0x61, 0x02, 0x81, 0xc0, 0xcb, 0xf8, 0x36, 0x2b, 0xae, 0xc0, 0x63, 0x78, 0x00, 0x5f, 0x82, 0x9b, 0x5c, + 0xca, 0x7e, 0xab, 0xc3, 0x1c, 0xd7, 0x16, 0x30, 0x68, 0xb0, 0x7a, 0x10, 0x1d, 0x2e, 0xa5, 0x7e, 0x57, 0x01, 0x62, + 0x63, 0x0a, 0xff, 0xb3, 0xb5, 0x61, 0xcf, 0xbe, 0x97, 0x4d, 0x43, 0xeb, 0x84, 0xd3, 0xe2, 0x2a, 0x87, 0x28, 0x2a, + 0x83, 0x18, 0xdc, 0x91, 0x1c, 0x3e, 0xef, 0x5d, 0x15, 0x5e, 0x12, 0x70, 0x2b, 0x8b, 0x45, 0xb8, 0xa2, 0xcb, 0xd1, + 0x1d, 0x5d, 0x8f, 0x6e, 0xe9, 0x98, 0x4e, 0xbe, 0x19, 0x83, 0x45, 0xb6, 0x4a, 0xbd, 0xa7, 0xeb, 0xd1, 0x92, 0x7e, + 0x3b, 0xa6, 0x47, 0x7f, 0x03, 0x13, 0x3e, 0x3c, 0x4c, 0xe8, 0x25, 0x38, 0x76, 0x91, 0x06, 0x3d, 0x35, 0x5d, 0x83, + 0xc3, 0x7a, 0x94, 0x0f, 0xf9, 0x28, 0xa7, 0x7c, 0x54, 0x0e, 0xeb, 0x11, 0x78, 0x3a, 0xd6, 0x43, 0x3e, 0xaa, 0x29, + 0x1f, 0x5d, 0x0c, 0xeb, 0xd1, 0x05, 0xf1, 0x9b, 0xfe, 0xaa, 0xe6, 0xd7, 0x15, 0x4b, 0x61, 0x5b, 0xc0, 0xf2, 0xb5, + 0xab, 0x2c, 0x49, 0xdd, 0x55, 0xad, 0x4f, 0x66, 0xc3, 0xd9, 0x9b, 0xeb, 0x2e, 0x27, 0x06, 0x8f, 0xdb, 0xa4, 0xc3, + 0xd5, 0x97, 0x13, 0x79, 0xd2, 0x4b, 0xe4, 0x87, 0xf1, 0x54, 0x9d, 0x43, 0x60, 0x26, 0x31, 0x0b, 0x63, 0x86, 0xcd, + 0x54, 0x69, 0xa0, 0xc0, 0xc9, 0x46, 0x8e, 0x8b, 0x62, 0x36, 0xca, 0x29, 0xbc, 0x8f, 0x09, 0x89, 0xf0, 0xac, 0x3a, + 0xa9, 0x47, 0x25, 0xc4, 0x1c, 0x61, 0x21, 0x3e, 0x42, 0xbf, 0xe4, 0x47, 0x0e, 0x12, 0x78, 0x86, 0x7d, 0x2d, 0x07, + 0x31, 0x1c, 0xf1, 0xa6, 0xb2, 0x7a, 0x16, 0x26, 0x50, 0x59, 0x3d, 0x2c, 0x74, 0x65, 0x25, 0xcd, 0x46, 0xb5, 0x5b, + 0x59, 0x8d, 0x63, 0x94, 0x10, 0x12, 0x15, 0xaa, 0x32, 0x50, 0x9f, 0x24, 0x2c, 0x2c, 0x54, 0x65, 0x17, 0xf2, 0xa3, + 0x0b, 0xb7, 0xb2, 0x0b, 0x70, 0x21, 0x1d, 0x24, 0xee, 0x55, 0x2a, 0x4f, 0xdb, 0xd7, 0x41, 0x6f, 0x55, 0xd1, 0x0d, + 0xbf, 0xab, 0xcb, 0x38, 0x2a, 0xa8, 0x8d, 0x01, 0x8d, 0x0b, 0x23, 0x12, 0x54, 0xad, 0x51, 0xf0, 0x87, 0x04, 0x51, + 0x69, 0x0c, 0x5e, 0x9d, 0x49, 0xd7, 0x4a, 0xad, 0x69, 0x35, 0x28, 0x06, 0x25, 0xdc, 0x9f, 0xf2, 0xd6, 0x42, 0xfa, + 0x1e, 0x22, 0x2a, 0x43, 0x79, 0x83, 0x7f, 0x60, 0xf0, 0x64, 0xb6, 0x4a, 0xc3, 0x64, 0x74, 0x4f, 0xe3, 0xd1, 0x12, + 0xe1, 0x60, 0xd8, 0x3a, 0x95, 0x78, 0xeb, 0x97, 0x90, 0x7e, 0x47, 0xe3, 0xd1, 0x2d, 0x4d, 0x8d, 0xcd, 0xa9, 0x86, + 0xba, 0xea, 0x8d, 0xe9, 0x5d, 0x04, 0xaf, 0xef, 0xa3, 0x25, 0x85, 0xad, 0x74, 0x9a, 0x67, 0x57, 0x45, 0x94, 0x52, + 0x44, 0x20, 0x5c, 0x23, 0x72, 0xe0, 0x52, 0xa1, 0x0d, 0xae, 0x07, 0x50, 0x86, 0x82, 0x0b, 0x5c, 0x0e, 0xe2, 0xd1, + 0xd2, 0x21, 0x53, 0x4b, 0x75, 0x91, 0x45, 0xf8, 0x68, 0x6b, 0xa3, 0x25, 0x79, 0x46, 0x2c, 0x8c, 0x4b, 0x18, 0x42, + 0x55, 0x58, 0xa1, 0x0b, 0x12, 0x36, 0x70, 0x64, 0x2f, 0x2c, 0xeb, 0x70, 0x03, 0xa6, 0x45, 0xf7, 0x60, 0x1e, 0x05, + 0x0a, 0x07, 0x9b, 0x20, 0xdc, 0x84, 0xa2, 0x9d, 0xa3, 0xd0, 0x39, 0x9c, 0x09, 0x4a, 0x77, 0x26, 0x08, 0x69, 0x57, + 0x37, 0xd9, 0x12, 0xae, 0xc1, 0xf6, 0x0e, 0x9d, 0x8a, 0x4a, 0xaa, 0xce, 0x2d, 0x98, 0x2c, 0xe1, 0x11, 0xb6, 0x84, + 0xa9, 0x99, 0x4e, 0xe1, 0x06, 0x7c, 0x78, 0xb4, 0x33, 0xdf, 0xe5, 0xec, 0xcd, 0x21, 0xd8, 0x76, 0x4a, 0x1f, 0x10, + 0x43, 0xec, 0x96, 0x6c, 0x3c, 0x5d, 0x1e, 0x17, 0xd3, 0x25, 0x12, 0x3b, 0x4d, 0xb7, 0x18, 0x9f, 0x2f, 0x17, 0x34, + 0xc1, 0xb3, 0x8d, 0xd5, 0xf3, 0xa5, 0x46, 0x4b, 0x49, 0x19, 0xae, 0xb7, 0x25, 0xfa, 0xff, 0xcb, 0x8b, 0x5f, 0x0a, + 0xf0, 0x12, 0x8c, 0x05, 0x80, 0x70, 0x0f, 0xa6, 0x05, 0xa9, 0x89, 0xb2, 0xb1, 0x4c, 0xc3, 0x14, 0x17, 0x81, 0x4e, + 0xe9, 0xf7, 0xc3, 0x9c, 0xa5, 0xc4, 0x81, 0x0e, 0x35, 0xa3, 0xb4, 0x4e, 0x5d, 0x21, 0x08, 0xf0, 0x48, 0xf2, 0x1c, + 0x9b, 0x7c, 0x33, 0x9e, 0x05, 0x72, 0x20, 0x82, 0x28, 0x3b, 0xc6, 0x47, 0x0c, 0x5c, 0x14, 0xa9, 0xb8, 0x9d, 0xb6, + 0x88, 0xcb, 0xdd, 0x63, 0x16, 0xe2, 0x24, 0x61, 0xae, 0x59, 0x36, 0x64, 0x75, 0x84, 0x09, 0xaa, 0x30, 0x30, 0xcb, + 0x1b, 0xb2, 0xfa, 0xf0, 0x08, 0x22, 0xb5, 0x9a, 0x32, 0x56, 0x5d, 0x65, 0x7c, 0x0b, 0x40, 0xd6, 0x8c, 0xb1, 0xa3, + 0xbf, 0x8d, 0x67, 0xf2, 0x9b, 0x28, 0xe4, 0x27, 0x47, 0x7f, 0x83, 0xe4, 0xe3, 0x6f, 0x91, 0x99, 0x83, 0x64, 0xaf, + 0xa0, 0x2b, 0x7f, 0xd6, 0x15, 0x94, 0x26, 0xae, 0xbd, 0x42, 0xad, 0x3d, 0xa1, 0xd7, 0x5e, 0x89, 0xee, 0xd4, 0x9a, + 0xf7, 0x90, 0xb6, 0xb3, 0x60, 0x82, 0x8e, 0x66, 0x77, 0xa0, 0x83, 0xb7, 0x8a, 0xa0, 0x17, 0x49, 0xa8, 0x3d, 0x42, + 0xa5, 0x51, 0x2f, 0xec, 0xc8, 0x6e, 0xd6, 0x25, 0x73, 0x0c, 0x98, 0x63, 0x73, 0x0e, 0x55, 0xc3, 0x5c, 0x1e, 0xd4, + 0x29, 0x2b, 0x86, 0x39, 0x1e, 0xc0, 0x6b, 0x26, 0x86, 0xd5, 0x20, 0x57, 0x28, 0xdf, 0x97, 0xac, 0x1c, 0x16, 0x83, + 0x5c, 0x71, 0x33, 0x53, 0x3f, 0x36, 0x6d, 0xa2, 0xc2, 0x33, 0xaf, 0xd8, 0xc9, 0xaa, 0x07, 0x7c, 0x2c, 0x78, 0x32, + 0xbb, 0x9e, 0x8f, 0xaf, 0x81, 0x93, 0xd9, 0xdc, 0x45, 0x4b, 0x7a, 0x1f, 0xa5, 0xf4, 0x36, 0x5a, 0xd3, 0x65, 0x74, + 0xa9, 0x4d, 0x8c, 0x93, 0x06, 0xce, 0x01, 0x68, 0x15, 0x40, 0xe2, 0xc9, 0x5f, 0xef, 0x79, 0x52, 0x87, 0x4b, 0x9a, + 0x82, 0xdb, 0xb0, 0x6b, 0x9f, 0x79, 0xed, 0x4a, 0xa4, 0x36, 0x88, 0xb1, 0x66, 0x0c, 0x15, 0x37, 0xce, 0xba, 0x8f, + 0xaa, 0x06, 0x76, 0xae, 0x8d, 0x4d, 0x54, 0x0f, 0x27, 0xd3, 0x02, 0x10, 0x5b, 0x8b, 0xe1, 0xd0, 0x1e, 0x21, 0xbb, + 0xc7, 0x8f, 0x0a, 0xf4, 0xdc, 0x13, 0x06, 0xdb, 0xb6, 0xe5, 0x0f, 0x0c, 0x61, 0x4a, 0x3f, 0x7d, 0xe4, 0x17, 0x84, + 0x4c, 0xaf, 0xe0, 0x6c, 0x04, 0xea, 0x68, 0x84, 0x4e, 0xbf, 0xd5, 0x61, 0xa9, 0x0e, 0xf0, 0xcd, 0x5d, 0x94, 0xd0, + 0xfb, 0x28, 0x77, 0xc8, 0xda, 0xb2, 0x61, 0x62, 0x7a, 0x9e, 0x85, 0xbc, 0x7d, 0xa0, 0x17, 0x0b, 0x00, 0xd1, 0x1a, + 0xc4, 0xae, 0xd4, 0xf5, 0x08, 0x9c, 0x86, 0xd0, 0x24, 0x34, 0x82, 0xab, 0x0a, 0xc2, 0x08, 0xd8, 0x92, 0xf0, 0x37, + 0x98, 0xa8, 0xc0, 0x17, 0xe0, 0x22, 0x93, 0xa6, 0x39, 0x0f, 0x1a, 0x77, 0x24, 0xcf, 0xca, 0xb6, 0xb7, 0x2b, 0x8c, + 0x26, 0x18, 0x7b, 0xa2, 0x7d, 0x1e, 0x29, 0x46, 0x71, 0x99, 0x84, 0xd9, 0xe8, 0x4e, 0x9e, 0xe7, 0x34, 0x1b, 0xdd, + 0xab, 0x5f, 0x35, 0x1d, 0xd3, 0xef, 0x54, 0x40, 0x1b, 0x29, 0x7d, 0xeb, 0x38, 0x1b, 0xd0, 0x7a, 0xb1, 0xd0, 0xfe, + 0xd7, 0x62, 0x74, 0x47, 0xc5, 0xe8, 0xde, 0xb5, 0xa4, 0x9a, 0x4c, 0xcb, 0xe3, 0x0a, 0x0d, 0xa9, 0x3a, 0xbf, 0x2f, + 0x81, 0x9f, 0x2b, 0xb4, 0xef, 0xb4, 0xfe, 0xde, 0x69, 0xff, 0x45, 0x27, 0x4f, 0x20, 0x59, 0xa2, 0x92, 0xd5, 0x23, + 0xb0, 0x63, 0x5f, 0xe7, 0x71, 0xa9, 0x47, 0x29, 0xa6, 0xc6, 0xa4, 0x1f, 0x03, 0x57, 0x4c, 0x7b, 0x25, 0xb8, 0x5a, + 0x6e, 0xb7, 0x32, 0x86, 0x26, 0xec, 0xd9, 0x31, 0x44, 0x3d, 0xd7, 0x8e, 0x51, 0xc2, 0x73, 0x0f, 0x88, 0x95, 0xcc, + 0x5b, 0xba, 0x04, 0x24, 0xf0, 0xd6, 0xc1, 0xa4, 0x28, 0x46, 0x29, 0xc0, 0x4f, 0xa8, 0x3c, 0x0e, 0xfa, 0x84, 0x7c, + 0xa1, 0x50, 0x27, 0x84, 0xb7, 0x25, 0x70, 0xfc, 0x61, 0x7d, 0x54, 0x08, 0x5e, 0xe5, 0xb8, 0xfe, 0x0a, 0xe3, 0xfa, + 0x4b, 0x85, 0xe3, 0x8e, 0x65, 0xbb, 0x7e, 0xde, 0xa6, 0x46, 0x2f, 0xc1, 0xc2, 0x77, 0x23, 0xcd, 0x23, 0xb9, 0x41, + 0x48, 0x95, 0x60, 0xa5, 0x76, 0x21, 0xc1, 0xfc, 0x4b, 0x39, 0x5b, 0x9d, 0xb9, 0xea, 0x91, 0x07, 0xe5, 0x6c, 0x6a, + 0xfa, 0x3d, 0x09, 0xda, 0x7d, 0x47, 0x9a, 0xc3, 0x5b, 0x74, 0xf8, 0xec, 0x1a, 0x4b, 0xcc, 0x9d, 0x44, 0xc9, 0xf3, + 0x49, 0x60, 0xab, 0xe7, 0xd9, 0xb5, 0xf4, 0xb1, 0xda, 0xc5, 0xf1, 0xd3, 0xe7, 0x4f, 0x5c, 0x87, 0x69, 0xe5, 0x29, + 0x41, 0xc0, 0x9b, 0x43, 0xdb, 0x15, 0xca, 0x80, 0x86, 0xfa, 0x06, 0x8e, 0x73, 0x35, 0xac, 0x15, 0x01, 0x53, 0x52, + 0x1e, 0x15, 0xe0, 0x50, 0xe7, 0x91, 0xbb, 0x69, 0x58, 0x6b, 0xba, 0xe6, 0xf5, 0xb9, 0xad, 0x74, 0xc6, 0x9b, 0x0d, + 0x3f, 0x3c, 0x1a, 0xd4, 0xf8, 0x93, 0xf8, 0xa3, 0xd1, 0xce, 0x0d, 0x77, 0x9a, 0x0a, 0x33, 0xd7, 0x62, 0x45, 0x76, + 0x47, 0xc9, 0xc9, 0xef, 0xe8, 0x85, 0xb1, 0x3f, 0xff, 0xb9, 0x98, 0x70, 0xd2, 0x12, 0x13, 0xa2, 0xa5, 0x83, 0x12, + 0x1d, 0xec, 0x28, 0xaf, 0xcc, 0x4b, 0xbc, 0x74, 0x8e, 0xff, 0x7d, 0x3d, 0xd6, 0xae, 0x02, 0xa1, 0xd5, 0xc9, 0xc3, + 0xf6, 0x64, 0x81, 0xa8, 0x01, 0xd5, 0xec, 0xb2, 0x1c, 0x69, 0xda, 0x59, 0x93, 0x8d, 0x27, 0x73, 0xdd, 0xcd, 0xe2, + 0xd9, 0x4c, 0x76, 0x2c, 0x2c, 0x3d, 0x0c, 0xc6, 0x4e, 0x15, 0x7d, 0x0e, 0x5a, 0x7e, 0x04, 0xcf, 0x7d, 0xe5, 0x99, + 0xcb, 0x66, 0x69, 0xf1, 0x02, 0x9d, 0x73, 0xaa, 0x21, 0x87, 0x1c, 0x80, 0xe3, 0x02, 0x8d, 0x25, 0x8a, 0x28, 0x08, + 0x1a, 0x13, 0x84, 0x5d, 0x95, 0xee, 0x48, 0x9f, 0x76, 0xf1, 0x69, 0x2b, 0xf4, 0x3d, 0xde, 0x67, 0x20, 0x31, 0x75, + 0x24, 0x0f, 0xb5, 0xd7, 0x1c, 0x95, 0x3c, 0x8b, 0x53, 0x85, 0xcf, 0x2f, 0x65, 0x67, 0xfe, 0xdd, 0x6a, 0x4c, 0xf1, + 0x1f, 0x69, 0xda, 0x77, 0x2e, 0x4d, 0x13, 0xdd, 0xb5, 0x3c, 0x68, 0x29, 0x2c, 0x38, 0x6e, 0x1b, 0x77, 0xfd, 0xfa, + 0x39, 0xaa, 0x61, 0x61, 0x73, 0x38, 0x13, 0x3a, 0xb4, 0x77, 0x95, 0x9d, 0xb9, 0x3e, 0xa2, 0x56, 0x5d, 0xac, 0xda, + 0x80, 0x92, 0x25, 0xe7, 0xd6, 0xe9, 0x88, 0x95, 0xbe, 0x3b, 0x0c, 0x77, 0xe6, 0x51, 0xb1, 0xbb, 0xdb, 0xed, 0x84, + 0xb4, 0xed, 0x83, 0xf1, 0xbe, 0x84, 0x85, 0x58, 0xef, 0xb0, 0x83, 0xef, 0xc3, 0xfa, 0x31, 0x1f, 0xfc, 0x1c, 0xca, + 0x75, 0x55, 0x3f, 0xcf, 0xa4, 0xa1, 0xcf, 0xcb, 0x52, 0x5c, 0xcb, 0x4e, 0xb9, 0x42, 0xb7, 0x96, 0xa9, 0xf7, 0x9b, + 0xf8, 0x4d, 0x2b, 0x40, 0x8c, 0xd3, 0x15, 0x23, 0xc5, 0x1b, 0x1a, 0x61, 0x9c, 0x87, 0xdb, 0x64, 0x51, 0x4b, 0x95, + 0x40, 0xd4, 0xe6, 0x27, 0x8f, 0x79, 0xa4, 0xd5, 0x99, 0xf0, 0xdd, 0x63, 0xee, 0x4a, 0xd7, 0x76, 0x9b, 0xf8, 0xa9, + 0xa6, 0x1d, 0xee, 0x0e, 0x74, 0x47, 0xeb, 0x1e, 0x6e, 0x9e, 0xc9, 0xcf, 0x23, 0xfd, 0xc5, 0x00, 0x9b, 0xb5, 0xcb, + 0xb8, 0xec, 0x18, 0xee, 0x3b, 0xd3, 0x83, 0xb1, 0x80, 0x40, 0x62, 0x86, 0x5e, 0x06, 0x36, 0x70, 0x81, 0xbd, 0xc2, + 0x80, 0x21, 0xae, 0x6e, 0xc9, 0xb9, 0xb2, 0xb2, 0x75, 0x91, 0xb7, 0x51, 0x21, 0xd8, 0x34, 0x1d, 0x37, 0x49, 0x0e, + 0xc1, 0x09, 0x5b, 0xee, 0x7d, 0xed, 0xb5, 0x33, 0xfc, 0xc7, 0xa0, 0xb2, 0x6e, 0x89, 0x8e, 0x51, 0xdb, 0x63, 0xa5, + 0xee, 0xd5, 0xbc, 0xca, 0x7d, 0xe4, 0x58, 0xbf, 0xe9, 0x97, 0x9a, 0x7d, 0xc1, 0x6b, 0x29, 0x38, 0x34, 0xb6, 0x5b, + 0x61, 0x17, 0x8b, 0x73, 0xb4, 0x1a, 0x59, 0x6b, 0xab, 0xbd, 0x46, 0x2a, 0xba, 0x7f, 0xcd, 0x71, 0x62, 0x2d, 0x85, + 0xcd, 0x87, 0x0f, 0x17, 0x6c, 0x9b, 0x00, 0x06, 0x2d, 0x3a, 0x0b, 0x94, 0x20, 0x93, 0x95, 0xaa, 0xdd, 0x4c, 0x89, + 0x5b, 0xee, 0x67, 0x5d, 0x66, 0x3b, 0x8f, 0x5f, 0x3b, 0x69, 0x9f, 0xf8, 0x1c, 0xfd, 0x30, 0xbf, 0x33, 0x4e, 0x4a, + 0xd6, 0x30, 0xae, 0xe5, 0xff, 0x57, 0xd3, 0xab, 0x32, 0x4b, 0xa3, 0x8d, 0xe6, 0xc1, 0x4c, 0xa8, 0x4d, 0x17, 0x1a, + 0xa3, 0xb6, 0xcb, 0x46, 0x12, 0xd1, 0xfa, 0x0e, 0x04, 0x33, 0x92, 0xfb, 0xaa, 0xda, 0xbc, 0x52, 0x6d, 0xe0, 0x1d, + 0x3e, 0xb1, 0xd1, 0x3d, 0xdb, 0x13, 0x42, 0xf9, 0xee, 0x69, 0xa1, 0x57, 0x2d, 0xad, 0x3c, 0xb6, 0xab, 0x72, 0x2e, + 0x46, 0xb5, 0x7a, 0xc2, 0x64, 0xc3, 0x82, 0xc9, 0xfe, 0x7f, 0x5f, 0x66, 0x69, 0x9b, 0xa2, 0x03, 0xd3, 0xe9, 0xfb, + 0x74, 0xd2, 0x0d, 0xae, 0x33, 0x60, 0x11, 0xc1, 0x96, 0x0a, 0xc7, 0xa3, 0x50, 0x6e, 0x90, 0x30, 0x11, 0x5c, 0x47, + 0xbd, 0xec, 0x68, 0x99, 0x94, 0x55, 0x01, 0xcf, 0x2f, 0x5d, 0x65, 0x3a, 0x8e, 0x86, 0x7e, 0xff, 0x3a, 0xd5, 0xa1, + 0x5f, 0x69, 0xe1, 0x9c, 0x23, 0xcb, 0xcc, 0x51, 0x75, 0xc8, 0x30, 0x46, 0x4b, 0x9a, 0xc2, 0x31, 0x98, 0x5d, 0x86, + 0x29, 0x5e, 0xce, 0x36, 0x09, 0xfb, 0x8c, 0x81, 0x5c, 0x2a, 0x83, 0x7a, 0x45, 0x89, 0xd6, 0xac, 0xbd, 0x99, 0x53, + 0x42, 0x2f, 0x59, 0xe1, 0xde, 0x85, 0xd6, 0x20, 0x50, 0x14, 0x7e, 0xca, 0xf4, 0x42, 0xb5, 0xf3, 0x92, 0x26, 0xb4, + 0xa4, 0x2b, 0xd2, 0x80, 0xbe, 0xd7, 0xca, 0xd9, 0xd1, 0xc9, 0x4e, 0xcf, 0x7a, 0xcc, 0xca, 0xe1, 0x64, 0x1a, 0xc3, + 0x35, 0x2d, 0xb6, 0xd7, 0xb4, 0xa5, 0x7f, 0xe3, 0xf2, 0x36, 0x8e, 0x47, 0xbb, 0x40, 0xda, 0xa6, 0xb8, 0xfd, 0xd4, + 0xe1, 0xf6, 0xd7, 0x0d, 0x5b, 0x4e, 0x7b, 0xeb, 0xed, 0xb6, 0x97, 0x82, 0x8d, 0xa8, 0xc3, 0xc7, 0xaf, 0xa5, 0x74, + 0xdd, 0x70, 0xf9, 0x29, 0x3c, 0x3b, 0x7c, 0xfd, 0xd2, 0x05, 0x97, 0xa3, 0x75, 0x9b, 0xbb, 0x5f, 0xee, 0x22, 0xcb, + 0x7d, 0xd6, 0xd0, 0x72, 0x35, 0x43, 0x3e, 0x79, 0xd6, 0xda, 0x3b, 0xd4, 0x82, 0xe5, 0xac, 0x9b, 0xf0, 0xc4, 0x60, + 0xc7, 0x5e, 0x7b, 0x9b, 0xa3, 0xd6, 0x97, 0x2c, 0x8f, 0x04, 0xba, 0x24, 0x4f, 0x37, 0xfd, 0x83, 0x08, 0xf3, 0xd1, + 0x1d, 0xcd, 0x01, 0x57, 0xac, 0x36, 0x97, 0x0c, 0xd2, 0xd4, 0xed, 0x25, 0x2e, 0x7d, 0x85, 0x43, 0xb2, 0xc1, 0x27, + 0xcd, 0x54, 0x7d, 0x72, 0xc9, 0x83, 0xff, 0xb7, 0x51, 0xab, 0xf4, 0xec, 0x24, 0x7b, 0x8e, 0x7f, 0x9d, 0xb4, 0x7d, + 0x4c, 0x34, 0x12, 0xf0, 0xd4, 0x2c, 0x86, 0x7a, 0x54, 0x97, 0x71, 0x51, 0xe5, 0x3a, 0xe6, 0xd8, 0xde, 0xae, 0xa1, + 0x83, 0x32, 0xf8, 0x75, 0xc3, 0x27, 0xfa, 0x0e, 0x6c, 0x04, 0x3a, 0x2a, 0x51, 0x5f, 0x86, 0x99, 0xbe, 0x0c, 0xd3, + 0xae, 0xad, 0x02, 0xc3, 0x2b, 0xb7, 0x4a, 0x22, 0x5d, 0x8d, 0x7a, 0x5c, 0xcf, 0x92, 0xdf, 0x8b, 0xbc, 0x7b, 0x4d, + 0x3a, 0x12, 0x7f, 0xba, 0x74, 0xe4, 0xf5, 0x30, 0x20, 0xe2, 0x73, 0x96, 0x86, 0x6d, 0x14, 0x04, 0xa7, 0x96, 0x3b, + 0x90, 0xe6, 0x23, 0x40, 0xe6, 0xc7, 0x69, 0xf8, 0x4e, 0x89, 0x73, 0xc8, 0x46, 0x6a, 0x9c, 0xd8, 0x52, 0xab, 0x87, + 0xe0, 0xce, 0x7b, 0xcd, 0x63, 0x08, 0x7c, 0xf8, 0x01, 0x37, 0x83, 0x8c, 0x6e, 0x4b, 0x74, 0x94, 0x36, 0x87, 0xba, + 0xe5, 0x23, 0x4f, 0xa8, 0x64, 0x64, 0x78, 0x31, 0xb4, 0x77, 0x47, 0x60, 0x54, 0x5b, 0x81, 0xcc, 0xb0, 0x3c, 0x3c, + 0x1a, 0xa6, 0x52, 0x50, 0x34, 0x14, 0xc3, 0x25, 0xca, 0x01, 0x31, 0x09, 0x04, 0x46, 0xe5, 0x20, 0x55, 0x95, 0xc9, + 0x17, 0x83, 0x54, 0xdd, 0xaa, 0x48, 0x73, 0x9e, 0x85, 0x35, 0x55, 0x2d, 0xa2, 0x63, 0x3a, 0x14, 0x74, 0xa9, 0x77, + 0x6a, 0xae, 0xa4, 0x17, 0x72, 0x39, 0x3e, 0x53, 0x69, 0x30, 0x8a, 0x67, 0x36, 0x45, 0xbd, 0x95, 0xfb, 0xd9, 0x7d, + 0x8b, 0x29, 0x0d, 0x62, 0x53, 0x3b, 0x8b, 0x18, 0x56, 0xed, 0x87, 0xac, 0xce, 0x41, 0xbb, 0x0b, 0xca, 0xc6, 0x5a, + 0x3b, 0xcf, 0x7b, 0xc1, 0xcc, 0x41, 0xdb, 0x58, 0xfb, 0x3e, 0xf4, 0x5a, 0x8c, 0xda, 0x1b, 0x53, 0x85, 0x7b, 0x02, + 0x3f, 0x4d, 0xd0, 0x74, 0x27, 0xf2, 0x1c, 0x75, 0xc8, 0xbb, 0xfb, 0x99, 0x25, 0x3b, 0x93, 0x4f, 0x62, 0x99, 0x34, + 0xed, 0x63, 0x12, 0xa3, 0x96, 0x18, 0x46, 0x17, 0x6e, 0x64, 0x52, 0xfb, 0xb9, 0x33, 0xfd, 0x88, 0x67, 0xf2, 0xb0, + 0x1d, 0x1a, 0x75, 0xa5, 0x61, 0x2d, 0x29, 0xa2, 0xba, 0xa0, 0xb7, 0xa6, 0x3a, 0x3a, 0xa2, 0x4e, 0x47, 0x60, 0x75, + 0x45, 0x1b, 0xd4, 0x00, 0x4c, 0xc6, 0x8d, 0xa9, 0xcd, 0xe5, 0x60, 0x1a, 0xa3, 0x2a, 0x78, 0x4a, 0x77, 0x85, 0xd2, + 0xbd, 0x49, 0xd3, 0xb4, 0x86, 0xd8, 0x00, 0x06, 0x04, 0x76, 0xf4, 0xe4, 0xf4, 0x07, 0x3e, 0x2a, 0x00, 0x0d, 0xbc, + 0xdb, 0x99, 0xca, 0x91, 0xa8, 0x77, 0x72, 0xd3, 0xfa, 0xa9, 0x4e, 0x55, 0x2e, 0x80, 0x8a, 0x3b, 0x4b, 0xe7, 0x97, + 0x7a, 0xc4, 0x02, 0x18, 0xf7, 0xc0, 0x9a, 0xea, 0x9d, 0x66, 0x60, 0x3d, 0x91, 0xe7, 0x59, 0xc5, 0x13, 0x51, 0xc0, + 0x8c, 0x88, 0xeb, 0x6b, 0x51, 0xc0, 0x30, 0xc8, 0x01, 0x40, 0x8b, 0xe6, 0x2a, 0x9a, 0xf0, 0xaf, 0x1a, 0xba, 0x2f, + 0x0f, 0xff, 0x4a, 0xe5, 0xfa, 0x7a, 0xdc, 0x80, 0xa1, 0xf2, 0xba, 0xe6, 0x3b, 0x99, 0xbe, 0xe6, 0x4f, 0x9c, 0x4c, + 0x4b, 0xb1, 0x2e, 0x77, 0xb2, 0x7c, 0xf5, 0x35, 0x7f, 0xaa, 0xf2, 0x1c, 0x3d, 0x69, 0x68, 0x1a, 0xdf, 0xef, 0x64, + 0xf9, 0xe6, 0xeb, 0x27, 0x26, 0xcf, 0x57, 0xe3, 0x86, 0xde, 0x72, 0xfe, 0xd1, 0x66, 0x9a, 0xa8, 0xaa, 0xc6, 0x4f, + 0xbe, 0x31, 0xb9, 0x9e, 0x34, 0xf4, 0x5a, 0x14, 0xf5, 0x72, 0xa7, 0xa8, 0xa3, 0xaf, 0x8f, 0xbe, 0xe1, 0x5f, 0xeb, + 0xee, 0x1d, 0x35, 0xf4, 0xcf, 0x75, 0x5c, 0xd6, 0xbc, 0xdc, 0x29, 0xee, 0x6f, 0xdf, 0x7c, 0xf3, 0xc4, 0x64, 0x7c, + 0xd2, 0xd0, 0x7b, 0x1e, 0x77, 0xb4, 0x7d, 0xf2, 0xf4, 0x09, 0xff, 0x5b, 0xd3, 0xd0, 0x5f, 0x98, 0x1b, 0x1c, 0xf5, + 0x34, 0x73, 0xf4, 0xf0, 0x89, 0xf0, 0x51, 0x03, 0x86, 0x0e, 0x1a, 0x40, 0x2e, 0x8c, 0x9a, 0x66, 0x8f, 0x57, 0x2e, + 0xb8, 0x7d, 0x9f, 0xc7, 0x69, 0xbc, 0x82, 0x83, 0x60, 0x83, 0xc6, 0x59, 0x25, 0x70, 0xaa, 0xc0, 0x7b, 0x46, 0x05, + 0xcd, 0x2a, 0xf1, 0x0f, 0xce, 0x3f, 0xc2, 0xa0, 0x21, 0xa4, 0x8d, 0x8c, 0x0c, 0xf4, 0x76, 0xa5, 0x22, 0x1b, 0xa1, + 0xff, 0xa6, 0x1f, 0x07, 0xc7, 0x85, 0xd1, 0xeb, 0xf7, 0xc3, 0x92, 0x55, 0x61, 0x49, 0x08, 0xfd, 0x23, 0x2c, 0xc1, + 0xa1, 0xa4, 0x64, 0x4e, 0x3e, 0xed, 0x7b, 0xae, 0x8c, 0xc2, 0x42, 0x10, 0xdd, 0x45, 0xe6, 0x01, 0x55, 0x8f, 0xae, + 0x43, 0x37, 0xc4, 0xcb, 0x0a, 0x4b, 0x86, 0x0e, 0x66, 0x30, 0x43, 0x50, 0xfc, 0x6b, 0x1e, 0x0a, 0xf0, 0x89, 0x07, + 0xf8, 0xe8, 0x31, 0x99, 0x71, 0x79, 0xad, 0x7d, 0x7b, 0x19, 0x96, 0x34, 0x50, 0x6d, 0x87, 0xa0, 0x03, 0x91, 0xfb, + 0x02, 0x3c, 0x05, 0x06, 0x2e, 0x2c, 0xec, 0x52, 0xec, 0xfa, 0xab, 0xff, 0xa2, 0x59, 0x47, 0x1b, 0x7e, 0xf4, 0x17, + 0xe3, 0xc2, 0x9e, 0x91, 0xa9, 0x38, 0x2e, 0x86, 0x93, 0xe9, 0x60, 0x20, 0x6c, 0x1c, 0xb7, 0xd3, 0x6c, 0xfe, 0xcb, + 0x5c, 0x2c, 0x16, 0xa8, 0xfb, 0xc6, 0x79, 0x9d, 0xa9, 0xbf, 0x91, 0x72, 0x3e, 0x78, 0x7d, 0xfa, 0xdb, 0xf9, 0xd9, + 0xe9, 0x4b, 0x70, 0x3e, 0xf8, 0xf0, 0xe2, 0xfb, 0x17, 0xef, 0x65, 0x70, 0x77, 0x39, 0xe7, 0xfd, 0xbe, 0x95, 0xfa, + 0x84, 0x7c, 0x58, 0x93, 0xc3, 0x30, 0x7e, 0x5c, 0x4a, 0xa3, 0x07, 0x72, 0xcc, 0x0c, 0x14, 0x32, 0x54, 0xd1, 0x98, + 0xdf, 0xc5, 0x70, 0xe2, 0x80, 0x59, 0xdc, 0x7b, 0x22, 0x5c, 0xb7, 0xe5, 0x26, 0xc8, 0x9a, 0x38, 0x71, 0xfa, 0xc1, + 0xc9, 0x54, 0x58, 0xb6, 0xb0, 0x64, 0x50, 0x36, 0xb4, 0xe9, 0x34, 0x9b, 0x97, 0x0b, 0xd3, 0x2e, 0xbb, 0x40, 0x46, + 0x69, 0x76, 0x79, 0x19, 0x4a, 0xe8, 0xea, 0x13, 0xd0, 0x00, 0xe8, 0x46, 0x95, 0xb6, 0x45, 0x7c, 0xe6, 0x96, 0x1f, + 0x8d, 0x9d, 0xe6, 0xdd, 0xa1, 0xee, 0x49, 0x37, 0xab, 0xf6, 0x06, 0x74, 0x30, 0xa1, 0xdc, 0x0e, 0xba, 0x0e, 0x26, + 0x23, 0xdb, 0xf2, 0xcb, 0xbc, 0x5e, 0xe8, 0xe6, 0xd8, 0x61, 0xa8, 0x9d, 0x92, 0xd7, 0xc2, 0x43, 0x64, 0x20, 0x19, + 0x86, 0x3d, 0x1a, 0xa3, 0x48, 0xfd, 0x60, 0xd7, 0x3b, 0x7e, 0x93, 0x0b, 0x88, 0xa6, 0x98, 0x81, 0x74, 0xfe, 0x51, + 0x25, 0x9d, 0xcb, 0x05, 0xe3, 0xf3, 0x6a, 0x71, 0x02, 0x6e, 0xe7, 0xf3, 0x6a, 0x11, 0x61, 0x50, 0xbe, 0x0c, 0x62, + 0x95, 0x80, 0xdd, 0x8b, 0x85, 0xf0, 0xed, 0x84, 0x36, 0x30, 0x1b, 0x48, 0xb0, 0x41, 0x61, 0x56, 0x1a, 0xa2, 0xdc, + 0x49, 0x8f, 0x36, 0x88, 0x3c, 0xc4, 0xea, 0x79, 0xdd, 0xf6, 0x64, 0xd3, 0x17, 0x13, 0x5c, 0x65, 0x31, 0x13, 0xd3, + 0xf8, 0x98, 0x95, 0xd3, 0x18, 0x4a, 0x89, 0xd3, 0x34, 0x8c, 0xe9, 0x84, 0x56, 0x84, 0x24, 0x8c, 0xcf, 0xe3, 0x05, + 0x4d, 0x50, 0x4a, 0x10, 0x42, 0xc8, 0x8f, 0x11, 0xda, 0xe6, 0xc0, 0x92, 0x37, 0xdb, 0xcf, 0xd1, 0xcf, 0xed, 0x18, + 0x2e, 0xa3, 0x22, 0x74, 0x83, 0xce, 0x1a, 0xee, 0x8d, 0xa8, 0xa4, 0x31, 0x56, 0x0c, 0x41, 0xc0, 0x4b, 0x8c, 0x4a, + 0x58, 0x92, 0x98, 0xd5, 0x10, 0x45, 0xa0, 0x98, 0xc7, 0x0b, 0x56, 0x52, 0xdf, 0xe6, 0x34, 0x56, 0x26, 0x41, 0x3d, + 0x8b, 0xa5, 0x76, 0x20, 0xa4, 0x0a, 0xb1, 0xc7, 0x67, 0x55, 0x74, 0xa3, 0x0c, 0x0d, 0x00, 0x05, 0x4a, 0xca, 0xc5, + 0x6f, 0x3f, 0xdf, 0xc3, 0x4d, 0x42, 0xff, 0xb3, 0x8d, 0x8e, 0x76, 0x96, 0xcb, 0x43, 0x6f, 0xbe, 0xa0, 0x71, 0x9e, + 0x43, 0x28, 0x36, 0x8d, 0x40, 0x5e, 0x64, 0x35, 0x44, 0xb4, 0xb8, 0x0f, 0x74, 0x48, 0x38, 0x68, 0xd3, 0x2f, 0x90, + 0xea, 0x89, 0xc9, 0xa5, 0x27, 0x06, 0xc6, 0xed, 0x90, 0x09, 0x05, 0x1c, 0xe9, 0x79, 0xf6, 0x97, 0x8f, 0xb1, 0xa6, + 0xa8, 0x99, 0x8e, 0xb7, 0x21, 0x11, 0x0d, 0x5a, 0x10, 0xcd, 0xe0, 0xfd, 0x73, 0xcd, 0xf1, 0xaa, 0x03, 0x3f, 0xe0, + 0x9d, 0x8d, 0x33, 0x2f, 0x67, 0x1e, 0x91, 0x53, 0x1f, 0xe5, 0x88, 0x7e, 0xc9, 0xc3, 0x7a, 0xa4, 0x92, 0x31, 0x56, + 0x12, 0x07, 0xbd, 0x0d, 0x16, 0xcc, 0x09, 0x5d, 0xf1, 0xd0, 0xf0, 0xf1, 0x2f, 0x91, 0xc9, 0xa8, 0x68, 0xa1, 0xd8, + 0x8d, 0xca, 0x60, 0xc4, 0x39, 0x0d, 0x33, 0x34, 0x59, 0xd2, 0xc5, 0x52, 0x91, 0xe6, 0x4a, 0x9a, 0x06, 0xb8, 0x04, + 0x1a, 0x3c, 0x1f, 0xf4, 0x43, 0x43, 0x3d, 0x84, 0x86, 0xdd, 0x21, 0xe0, 0x23, 0xfb, 0xd0, 0xe1, 0xff, 0xe7, 0xd8, + 0x05, 0x22, 0xed, 0xcd, 0x75, 0x64, 0x3c, 0xd2, 0x78, 0x38, 0x28, 0xda, 0xc7, 0xde, 0x4f, 0xfc, 0xcc, 0x19, 0x7d, + 0x48, 0x2a, 0xdf, 0xe1, 0x83, 0xe5, 0x8e, 0x37, 0xd5, 0xb3, 0x32, 0x82, 0xf5, 0xb0, 0xdd, 0xe2, 0x82, 0x68, 0xbb, + 0x00, 0x52, 0xc7, 0x78, 0xb5, 0x74, 0x8d, 0x57, 0xe3, 0x3d, 0xc6, 0xab, 0xf6, 0x4c, 0x0d, 0x73, 0xb2, 0x41, 0x7d, + 0x96, 0x94, 0xe7, 0xe7, 0x28, 0x13, 0xf4, 0x5d, 0xce, 0x0a, 0x2a, 0x53, 0x09, 0xed, 0xc5, 0x6e, 0xc6, 0xf8, 0x8e, + 0x60, 0x9c, 0x15, 0x8b, 0x91, 0x40, 0x65, 0x2a, 0x69, 0xc2, 0x5e, 0x09, 0xea, 0x31, 0x78, 0xaf, 0x31, 0x44, 0xb5, + 0x8c, 0x5d, 0xb7, 0x81, 0xd0, 0x50, 0x5b, 0x8f, 0xf6, 0x8c, 0xf5, 0xe8, 0x76, 0x5b, 0x6b, 0x7f, 0x3b, 0xb1, 0x2e, + 0x13, 0x44, 0x15, 0x96, 0xa3, 0x09, 0xf0, 0xa6, 0x89, 0xb9, 0x2d, 0x59, 0xa5, 0x05, 0x86, 0xcf, 0xfe, 0x23, 0x2c, + 0xac, 0x4a, 0xa2, 0x20, 0xb3, 0x22, 0x1a, 0xd8, 0x73, 0xf0, 0x79, 0x5c, 0xc3, 0x1a, 0x80, 0x48, 0x8e, 0xe8, 0xe1, + 0xfa, 0x47, 0x28, 0x6c, 0x66, 0x41, 0x66, 0x02, 0x32, 0xf3, 0x22, 0x6d, 0x67, 0x1d, 0x4c, 0xac, 0x49, 0xad, 0x33, + 0x16, 0x62, 0xa8, 0x91, 0x1f, 0x40, 0x19, 0x62, 0xf1, 0xc9, 0x07, 0x13, 0x2a, 0x64, 0x28, 0x55, 0xaf, 0x9b, 0xdd, + 0xc0, 0x2b, 0x1f, 0xb2, 0x6b, 0x5e, 0xd5, 0xf1, 0xf5, 0x4a, 0x5b, 0x12, 0x73, 0xb6, 0xcf, 0x6d, 0x8f, 0x56, 0xfa, + 0xd5, 0x9b, 0x17, 0xdf, 0x9f, 0x7a, 0xaf, 0x76, 0x11, 0x47, 0x43, 0xb0, 0xad, 0x18, 0x63, 0xf4, 0x16, 0x97, 0x06, + 0x13, 0xe9, 0x1a, 0x81, 0xde, 0xa5, 0xa0, 0xdf, 0xfe, 0x5c, 0x4f, 0xc0, 0x6b, 0xae, 0x96, 0x5f, 0xf2, 0x11, 0xb0, + 0x44, 0xf5, 0xac, 0x30, 0x3b, 0x2b, 0xb3, 0xbd, 0xdd, 0x8a, 0xf4, 0xb4, 0x4b, 0x8d, 0x0c, 0xc4, 0xab, 0xed, 0x30, + 0x16, 0x2e, 0x6c, 0xd3, 0xcd, 0x60, 0xd7, 0x4b, 0xc7, 0x12, 0x79, 0xbb, 0x2d, 0xa0, 0x43, 0x66, 0xc0, 0x9d, 0x97, + 0xf1, 0x1d, 0xbc, 0x2c, 0x9c, 0x6e, 0xfa, 0xc1, 0x13, 0xc0, 0x4c, 0xb8, 0xb4, 0x96, 0xc5, 0x31, 0xe3, 0x09, 0xcc, + 0x1f, 0x2d, 0x7d, 0x91, 0xb7, 0x24, 0xb4, 0x7a, 0x7f, 0x85, 0xd5, 0x08, 0xec, 0x4e, 0xce, 0x3e, 0x66, 0xab, 0xd9, + 0x12, 0x50, 0xf3, 0xaf, 0xb3, 0x02, 0x68, 0xae, 0x59, 0x0b, 0xa6, 0x29, 0xd4, 0x5f, 0xd7, 0xcf, 0xe2, 0x55, 0x9c, + 0x80, 0xea, 0x06, 0xbc, 0x45, 0xee, 0x95, 0xe8, 0x4a, 0xa3, 0x8b, 0xd2, 0x07, 0xca, 0x31, 0xa4, 0xd0, 0xd2, 0xf7, + 0x5e, 0x25, 0xcf, 0x3d, 0x0d, 0xb8, 0xa4, 0x50, 0xf3, 0x64, 0x4b, 0x19, 0x0b, 0x80, 0x85, 0x0e, 0x66, 0x92, 0x6c, + 0x45, 0x77, 0x1a, 0x93, 0x02, 0xde, 0x6a, 0xe0, 0x8f, 0x22, 0xab, 0xe5, 0x5d, 0xb1, 0x0a, 0x0b, 0xc7, 0xfe, 0xba, + 0xdf, 0x8f, 0x1d, 0xfb, 0xeb, 0x4b, 0x45, 0xeb, 0xe2, 0x76, 0x03, 0x48, 0x83, 0x01, 0x44, 0x4e, 0xd5, 0x40, 0xe8, + 0x88, 0x62, 0xbe, 0xef, 0xdf, 0xa9, 0xce, 0x22, 0x41, 0xe8, 0x77, 0xea, 0x75, 0xa4, 0x24, 0xa0, 0x53, 0xab, 0xd9, + 0xc9, 0x40, 0x99, 0x7d, 0x40, 0x40, 0x54, 0x37, 0x23, 0x9b, 0x2f, 0xa4, 0x73, 0xb1, 0x0c, 0x1f, 0x3e, 0xa6, 0x10, + 0x50, 0xb8, 0xa3, 0x46, 0xeb, 0x6d, 0x88, 0x04, 0xca, 0x08, 0x45, 0x8c, 0x79, 0xb1, 0x92, 0x84, 0xcc, 0xc7, 0x0b, + 0x14, 0x5c, 0x59, 0x60, 0x57, 0xce, 0x26, 0xc3, 0x22, 0xe2, 0x2c, 0xdc, 0xff, 0xcd, 0x64, 0x41, 0x50, 0x73, 0xe5, + 0x06, 0x72, 0xdc, 0xc9, 0xe4, 0xed, 0x29, 0xaf, 0x86, 0x8a, 0x89, 0x08, 0x02, 0xc3, 0x0d, 0x3f, 0xe3, 0xe3, 0xa3, + 0x05, 0x01, 0x15, 0x99, 0x31, 0x0b, 0xd1, 0x2f, 0x8e, 0xbf, 0x02, 0xd4, 0x98, 0xd1, 0xd1, 0x53, 0x00, 0x85, 0x85, + 0x80, 0xe8, 0x63, 0x90, 0xd1, 0x56, 0xf0, 0xbb, 0x92, 0xbf, 0x5b, 0x27, 0xbe, 0x0b, 0xfd, 0x5a, 0xd1, 0xcb, 0x18, + 0x18, 0x8e, 0x68, 0x72, 0x18, 0xf2, 0xc1, 0x64, 0x00, 0xda, 0x12, 0x67, 0xf7, 0xb5, 0xb4, 0xe2, 0xfa, 0x74, 0xe9, + 0x74, 0xff, 0xa4, 0x3e, 0x48, 0x22, 0x15, 0xac, 0x90, 0xc4, 0x00, 0x42, 0x59, 0xca, 0x6d, 0xb2, 0x04, 0xcb, 0x0a, + 0xbd, 0xa4, 0xb9, 0x46, 0x49, 0xdc, 0xdd, 0x0c, 0x1c, 0xa3, 0x66, 0x9d, 0x86, 0x45, 0xcb, 0x8d, 0x1a, 0xe0, 0x73, + 0x12, 0x56, 0x9a, 0x1b, 0xce, 0x4c, 0x38, 0x67, 0x3a, 0x5c, 0x1d, 0x73, 0xf6, 0x9a, 0x23, 0x18, 0x47, 0x82, 0x37, + 0x1e, 0xba, 0x64, 0x0a, 0x2a, 0x32, 0x65, 0x1c, 0x4c, 0x7b, 0x80, 0x7b, 0xcf, 0xc1, 0x38, 0x8c, 0x0d, 0x6a, 0x43, + 0xea, 0x53, 0xe7, 0x2e, 0x04, 0x82, 0xb4, 0xd6, 0xcb, 0x7c, 0x86, 0xa7, 0x67, 0x84, 0xb2, 0x3f, 0xe4, 0xf0, 0x01, + 0xf0, 0xb2, 0x24, 0x27, 0x13, 0xfe, 0xf4, 0xf1, 0x6e, 0xa0, 0x2a, 0x3e, 0x08, 0x0e, 0xe2, 0x22, 0x3d, 0x08, 0x06, + 0x15, 0xfc, 0x2a, 0xf9, 0x41, 0x2d, 0xc4, 0xc1, 0x65, 0x5c, 0x1e, 0xc4, 0xab, 0xb8, 0xac, 0x0f, 0x6e, 0xb3, 0x7a, + 0x79, 0xa0, 0x3b, 0x04, 0xd0, 0xbc, 0xc1, 0x20, 0x1e, 0x04, 0x07, 0xc1, 0xa0, 0xd4, 0x53, 0xbb, 0x62, 0x85, 0x77, + 0x9c, 0xe9, 0x10, 0x65, 0x81, 0x1f, 0x20, 0xcc, 0x3b, 0x0d, 0x80, 0x4f, 0x5d, 0xb3, 0x94, 0x5e, 0x62, 0xb8, 0x81, + 0x6a, 0xba, 0x86, 0x3e, 0x00, 0x8f, 0xbc, 0xa6, 0x31, 0x2c, 0x81, 0xcb, 0xc1, 0x80, 0xac, 0x21, 0x72, 0xc1, 0x9a, + 0x9a, 0x20, 0x0e, 0xe1, 0x5a, 0xda, 0x69, 0x17, 0x3b, 0x14, 0x76, 0xbb, 0x05, 0x44, 0xe5, 0x09, 0xe9, 0xf7, 0xcd, + 0x37, 0xd4, 0xbd, 0x60, 0x2f, 0xc1, 0xfe, 0xaa, 0xac, 0xc3, 0x44, 0x48, 0xcd, 0xf7, 0x15, 0x3b, 0x19, 0xc8, 0x88, + 0xc3, 0x3b, 0x8e, 0x14, 0x6d, 0x54, 0x2e, 0xc3, 0x9e, 0x2c, 0x3d, 0x5f, 0x89, 0x6b, 0x6e, 0xfd, 0xb8, 0x6a, 0x21, + 0xf2, 0x3a, 0x5b, 0x49, 0xf6, 0x6f, 0xc6, 0x15, 0xf7, 0x07, 0xd6, 0x9f, 0xfe, 0x2b, 0xb8, 0xb6, 0x3a, 0xef, 0x7c, + 0xae, 0x11, 0x39, 0x4b, 0x28, 0x97, 0x34, 0x26, 0x0f, 0x6f, 0xe9, 0xfb, 0xdc, 0xea, 0xdb, 0x4c, 0xa7, 0xf6, 0x59, + 0x85, 0x85, 0x0b, 0xd1, 0x8a, 0xe0, 0xd0, 0x10, 0x0b, 0xff, 0x08, 0xd0, 0xd7, 0x3e, 0x53, 0x41, 0x49, 0x9a, 0xf3, + 0x1a, 0xbd, 0x5b, 0x21, 0xe1, 0xa5, 0x62, 0x97, 0x1e, 0x06, 0x52, 0xc6, 0xed, 0xa1, 0x24, 0x4c, 0x4a, 0x5e, 0x84, + 0xf7, 0x5e, 0x7d, 0x93, 0x7b, 0x1e, 0x62, 0xf4, 0x22, 0xc7, 0x4e, 0x40, 0x5b, 0x77, 0x89, 0xce, 0x86, 0x27, 0x6e, + 0xc3, 0x73, 0xd6, 0xa2, 0xd1, 0x74, 0xc9, 0x92, 0x7e, 0x3f, 0x06, 0x13, 0xef, 0x94, 0xe5, 0xf0, 0x2b, 0x5f, 0xd0, + 0x35, 0x03, 0x4c, 0x31, 0x7a, 0x09, 0x09, 0x29, 0x22, 0x91, 0xac, 0xe5, 0x49, 0xf2, 0x89, 0xee, 0x42, 0x70, 0x84, + 0xcb, 0x59, 0x1a, 0x2d, 0xf7, 0x9a, 0x59, 0x20, 0x79, 0x86, 0xbe, 0xab, 0x60, 0x7b, 0x63, 0x17, 0xa4, 0x9c, 0x1f, + 0x57, 0xd3, 0xc1, 0x80, 0x13, 0x05, 0x37, 0x5e, 0x48, 0x71, 0xad, 0x6a, 0x71, 0xc7, 0x30, 0x16, 0xea, 0xb6, 0x88, + 0xc1, 0x01, 0xbb, 0x68, 0x65, 0xb7, 0x0f, 0xb0, 0xab, 0x1c, 0xef, 0x52, 0x65, 0x77, 0x7a, 0xcc, 0xf8, 0xcb, 0x56, + 0x91, 0x4e, 0x5a, 0xed, 0x27, 0xf2, 0x3e, 0x77, 0xd0, 0xe5, 0x72, 0xac, 0x78, 0xcb, 0x41, 0x45, 0x1e, 0xf3, 0x91, + 0xa4, 0xba, 0x9f, 0xe1, 0x08, 0xf3, 0x60, 0xdd, 0xfa, 0x93, 0x43, 0x5d, 0xe0, 0x10, 0x79, 0x52, 0xaf, 0x29, 0xa0, + 0x7b, 0xaf, 0x1e, 0x77, 0xf5, 0xdb, 0xd0, 0x5d, 0xa0, 0x44, 0x3b, 0x15, 0x7b, 0x7e, 0x4c, 0xd4, 0xea, 0x4c, 0x3d, + 0xa1, 0x7f, 0xad, 0xc5, 0xfd, 0x85, 0x76, 0x15, 0xf7, 0xbd, 0xcb, 0x67, 0x1c, 0xea, 0xec, 0x86, 0x50, 0x00, 0xae, + 0xda, 0xd1, 0xa9, 0x6b, 0x43, 0x7a, 0xa9, 0x44, 0x37, 0xc1, 0xc1, 0xf6, 0xfa, 0x8c, 0xa3, 0xe8, 0x47, 0xab, 0x91, + 0x6f, 0xa3, 0xea, 0xb1, 0x18, 0xc4, 0x8f, 0x4b, 0xba, 0x8c, 0xaa, 0xc7, 0xe5, 0x20, 0x7e, 0x2c, 0x9a, 0x66, 0xf7, + 0x5c, 0xd9, 0xdf, 0x47, 0xe4, 0x59, 0x77, 0xf6, 0x52, 0x01, 0x1b, 0x03, 0xcf, 0xae, 0x05, 0x84, 0x53, 0x70, 0x44, + 0xb6, 0x86, 0x3e, 0x74, 0x6e, 0xf7, 0xb1, 0x61, 0x92, 0x20, 0xe8, 0x79, 0x9b, 0x4d, 0xa2, 0xd8, 0x59, 0xff, 0xe8, + 0xc3, 0x29, 0x10, 0xd0, 0xed, 0xb6, 0x59, 0x57, 0x6b, 0x40, 0x31, 0x0d, 0xc7, 0xfc, 0xb0, 0x1c, 0xdd, 0xba, 0xee, + 0xfa, 0x87, 0xe5, 0x68, 0x49, 0x86, 0x13, 0x3d, 0xf9, 0xf1, 0xc9, 0x78, 0x16, 0x47, 0x93, 0xa6, 0xe3, 0xb4, 0x50, + 0xf8, 0xa7, 0xce, 0x2d, 0x14, 0x81, 0x53, 0x31, 0x82, 0x23, 0xa7, 0xca, 0x49, 0xc9, 0xc3, 0xf0, 0x3f, 0xa8, 0x77, + 0xb4, 0x69, 0xaf, 0xe3, 0x3a, 0x59, 0x66, 0xc5, 0x95, 0x0a, 0x1f, 0xae, 0xa2, 0x8b, 0x9b, 0x80, 0x76, 0xce, 0x65, + 0xda, 0xf2, 0xeb, 0xc4, 0xa3, 0x27, 0xb6, 0x66, 0x06, 0xdc, 0xba, 0x1b, 0xa1, 0x19, 0x02, 0xa3, 0xe5, 0xf9, 0x3b, + 0xc4, 0xdc, 0xfe, 0x55, 0xda, 0xfc, 0x4a, 0xda, 0x67, 0xc9, 0x48, 0xd1, 0x26, 0x23, 0x35, 0x18, 0x61, 0x8a, 0x22, + 0x89, 0xeb, 0xb0, 0x80, 0x20, 0xd8, 0x9f, 0x51, 0x5c, 0x8b, 0xa5, 0x77, 0x1a, 0x84, 0x09, 0xa6, 0x0b, 0xca, 0xaf, + 0x6e, 0xe7, 0xb6, 0xd2, 0x62, 0x8f, 0xe4, 0xf7, 0xb9, 0xb5, 0x5d, 0x51, 0xe4, 0xef, 0xf3, 0x06, 0xd4, 0x03, 0xa2, + 0xdc, 0xd7, 0x47, 0x29, 0x70, 0xd2, 0xe2, 0x86, 0x02, 0xa3, 0x17, 0x74, 0x75, 0x22, 0x77, 0xec, 0xd4, 0x9c, 0xa9, + 0x98, 0xc9, 0xb8, 0xf2, 0x7e, 0xcf, 0xdc, 0x07, 0x4d, 0x41, 0x2b, 0x30, 0xf0, 0xd6, 0x67, 0x3c, 0x3a, 0xd0, 0xdd, + 0x6a, 0x9d, 0x16, 0x6c, 0x16, 0xd4, 0x65, 0xdd, 0xb6, 0xf1, 0xa0, 0x11, 0x07, 0x45, 0xb2, 0x2a, 0x54, 0x4b, 0x78, + 0x22, 0x10, 0x30, 0x65, 0xd7, 0x3c, 0xd2, 0x82, 0x9a, 0xde, 0x84, 0xc2, 0x86, 0x82, 0xbf, 0x52, 0x54, 0xd3, 0x9b, + 0x50, 0x9f, 0x89, 0x53, 0x0c, 0x22, 0x98, 0x11, 0x9b, 0xfd, 0x16, 0x50, 0x7f, 0x6b, 0x46, 0x9b, 0xa6, 0x31, 0xda, + 0x2a, 0xe4, 0x92, 0x22, 0x69, 0xf9, 0x6f, 0xd5, 0x54, 0x50, 0x52, 0xcb, 0x45, 0x6f, 0xe2, 0xbb, 0xe8, 0xf1, 0x4c, + 0x4b, 0x02, 0xa5, 0x5b, 0xee, 0x18, 0xfd, 0x21, 0x0c, 0xf0, 0x88, 0x8e, 0x13, 0x0b, 0xe6, 0x56, 0x27, 0x2c, 0x9b, + 0x57, 0x8b, 0xd1, 0x4a, 0x40, 0xd8, 0xe0, 0x63, 0x96, 0xcd, 0x0b, 0xf5, 0x10, 0xba, 0xc2, 0xd2, 0xb7, 0x60, 0x17, + 0x1b, 0xac, 0x44, 0x15, 0x80, 0xef, 0x05, 0xdd, 0xac, 0x44, 0x15, 0x09, 0xd9, 0xfd, 0xb8, 0xc1, 0x12, 0x64, 0x5a, + 0x29, 0xd3, 0x92, 0x06, 0x0b, 0x02, 0x5f, 0x55, 0x55, 0x3e, 0x24, 0xdb, 0x0a, 0xe4, 0x53, 0x47, 0x0d, 0x38, 0x05, + 0xb2, 0x0a, 0x2c, 0x48, 0x80, 0xca, 0xd0, 0x56, 0x81, 0x69, 0x25, 0xa6, 0xe9, 0x2a, 0x6c, 0x94, 0xd9, 0xa1, 0xd0, + 0xeb, 0x25, 0x9f, 0xc5, 0x83, 0x30, 0x19, 0xc6, 0xe4, 0x31, 0x42, 0xed, 0x1f, 0xe6, 0x51, 0xac, 0xe4, 0x92, 0x2b, + 0xeb, 0x17, 0x7f, 0xfb, 0x09, 0x7b, 0xdd, 0x73, 0x0c, 0x16, 0x60, 0x2d, 0x6d, 0xaf, 0xb3, 0xe2, 0x9d, 0x68, 0x05, + 0xc7, 0xc1, 0x2c, 0xd2, 0x61, 0xd5, 0x91, 0x23, 0xea, 0x8b, 0x5c, 0x7b, 0x17, 0x21, 0x72, 0x90, 0xde, 0x63, 0x80, + 0xdd, 0x08, 0x5f, 0x87, 0xc6, 0xe6, 0x56, 0x55, 0x88, 0xbf, 0x51, 0x22, 0xf1, 0x93, 0x10, 0x1f, 0xd7, 0x2b, 0x99, + 0xab, 0xd6, 0x78, 0xac, 0xaa, 0x19, 0x3c, 0x53, 0xbe, 0xc7, 0xca, 0xbf, 0xb5, 0xdd, 0x1c, 0xe7, 0x3d, 0x78, 0xd0, + 0xba, 0xdf, 0x3a, 0x12, 0x42, 0x73, 0xe5, 0x24, 0x4d, 0x47, 0x8d, 0x8e, 0x99, 0xac, 0x16, 0x95, 0x30, 0xb9, 0x3b, + 0xa5, 0x63, 0xa0, 0xa2, 0x03, 0xb8, 0x96, 0xa8, 0x0e, 0x7a, 0x52, 0xb2, 0x31, 0x1c, 0x71, 0x06, 0x07, 0xed, 0x38, + 0x46, 0xf1, 0x72, 0x2e, 0xc5, 0xcb, 0xf9, 0x09, 0xe3, 0x00, 0xad, 0x05, 0x48, 0xf5, 0x0a, 0xf6, 0x33, 0x97, 0xb0, + 0xc0, 0xfa, 0xce, 0x77, 0x64, 0x80, 0x0c, 0x71, 0xb2, 0x39, 0x4e, 0xf6, 0xb8, 0x51, 0x73, 0x5f, 0xe1, 0xe3, 0xa4, + 0x59, 0x38, 0x75, 0x15, 0xed, 0xba, 0x96, 0xac, 0x98, 0x97, 0x83, 0x09, 0x04, 0x65, 0x29, 0xe6, 0xe5, 0x70, 0xb2, + 0xa0, 0x39, 0xfc, 0x58, 0x78, 0xe8, 0x10, 0xcb, 0x41, 0x02, 0x97, 0xce, 0x1e, 0x03, 0xde, 0x50, 0x28, 0x71, 0x37, + 0xd6, 0x91, 0x63, 0x1d, 0xe5, 0x61, 0x18, 0x03, 0xae, 0xac, 0x15, 0x78, 0xef, 0xbf, 0x3e, 0xfa, 0x80, 0xac, 0xca, + 0x15, 0x5e, 0x8e, 0x72, 0xd7, 0x95, 0x46, 0x5d, 0x52, 0x7a, 0x95, 0x13, 0x3c, 0x95, 0x6c, 0xb7, 0x3d, 0x63, 0x4f, + 0xe5, 0x20, 0xf1, 0x8e, 0x11, 0xbd, 0x98, 0x7a, 0x99, 0x39, 0x81, 0x33, 0xdb, 0x5e, 0xb6, 0x31, 0x3f, 0x76, 0x80, + 0x83, 0x45, 0x10, 0x12, 0x37, 0x84, 0x61, 0x62, 0x27, 0xc5, 0x50, 0x09, 0xe1, 0xba, 0x16, 0x5e, 0xc7, 0x69, 0x19, + 0x83, 0x8b, 0xb4, 0xb2, 0x4d, 0xdc, 0x43, 0xd7, 0x1d, 0x3f, 0xe6, 0x56, 0xc7, 0x68, 0xcb, 0x7c, 0xb8, 0xa3, 0xd3, + 0x07, 0x16, 0x03, 0x50, 0xf7, 0x60, 0x56, 0xb7, 0xcf, 0x24, 0xae, 0x4f, 0xbb, 0x8a, 0x90, 0x08, 0x44, 0x51, 0x2a, + 0x23, 0x4c, 0xff, 0x4e, 0x73, 0x59, 0x4d, 0xeb, 0x07, 0x79, 0xe6, 0x90, 0x67, 0xa1, 0xb3, 0x3d, 0x68, 0xed, 0xef, + 0x06, 0xed, 0xc4, 0x6d, 0xf7, 0xce, 0xff, 0x5b, 0xd6, 0xb5, 0xd5, 0x9a, 0xea, 0x71, 0xbb, 0xfa, 0x81, 0xb7, 0x57, + 0x7b, 0x32, 0x06, 0xcc, 0x4a, 0x38, 0x67, 0x54, 0xc5, 0xcb, 0x8c, 0x57, 0x78, 0x52, 0xad, 0x3c, 0x1f, 0xef, 0xdb, + 0x6c, 0xa4, 0x1f, 0xc8, 0x14, 0x10, 0xcf, 0x6f, 0x53, 0xad, 0x3e, 0x4e, 0x51, 0x02, 0xfe, 0x4e, 0xc5, 0x37, 0xa2, + 0x1f, 0xcd, 0x8b, 0x2b, 0x5e, 0xbf, 0xbd, 0x2d, 0xf4, 0x8b, 0xe7, 0x46, 0xe7, 0x4f, 0x5f, 0x97, 0x2e, 0x74, 0x38, + 0x6a, 0xef, 0xa0, 0xc8, 0x82, 0x55, 0x27, 0x13, 0x2d, 0x6b, 0xab, 0x66, 0x1f, 0x25, 0x5c, 0x4c, 0x54, 0xa3, 0x67, + 0x9d, 0x39, 0x61, 0x4a, 0xd0, 0x37, 0x8e, 0x51, 0xc9, 0x18, 0x96, 0x0c, 0xd4, 0x69, 0x52, 0x88, 0x1e, 0x56, 0x33, + 0x8c, 0x57, 0x0c, 0xa0, 0x30, 0xa5, 0x04, 0x51, 0xb4, 0x06, 0xc1, 0x40, 0x13, 0xfa, 0xfd, 0xdb, 0x54, 0x65, 0xa0, + 0x45, 0x33, 0x15, 0x20, 0xaa, 0x83, 0x68, 0xab, 0xbc, 0x0c, 0x7f, 0x5c, 0xd2, 0x22, 0xa3, 0x79, 0x45, 0x97, 0x15, + 0x4d, 0x32, 0x7a, 0xc9, 0xa5, 0xa8, 0x78, 0x5d, 0x31, 0x49, 0xdb, 0x35, 0x61, 0xff, 0x97, 0x47, 0xd7, 0x5b, 0xb1, + 0xd6, 0xd0, 0xee, 0x04, 0x19, 0xa1, 0xf9, 0x42, 0x05, 0x21, 0x43, 0xe5, 0x24, 0x74, 0xad, 0x56, 0x78, 0x05, 0x36, + 0x99, 0x66, 0xa3, 0x65, 0x5c, 0x85, 0x81, 0xf9, 0x2a, 0x30, 0x98, 0x1c, 0x98, 0x74, 0xb6, 0xbe, 0x78, 0x26, 0xae, + 0x57, 0xa2, 0xe0, 0x45, 0x2d, 0x21, 0xfa, 0x35, 0xee, 0xbb, 0x8e, 0xab, 0xce, 0xfc, 0x5a, 0xe9, 0x43, 0xdf, 0xba, + 0xac, 0x8d, 0xfd, 0x42, 0xe3, 0x18, 0xec, 0x7c, 0x44, 0x34, 0xa4, 0x41, 0xad, 0x5a, 0x1c, 0xea, 0x00, 0x5d, 0x2a, + 0xa4, 0x90, 0x21, 0x53, 0x99, 0x2c, 0x41, 0xc6, 0x37, 0x7e, 0x2f, 0x44, 0x3d, 0xfa, 0x73, 0xcd, 0xcb, 0xfb, 0x33, + 0x9e, 0x73, 0x1c, 0xa3, 0x20, 0x89, 0x8b, 0x9b, 0xb8, 0x0a, 0x88, 0x6b, 0x79, 0x15, 0x1c, 0xa5, 0x3a, 0x6c, 0xcc, + 0x4e, 0xd5, 0xa8, 0xf5, 0x12, 0xe8, 0x2b, 0x23, 0x7d, 0x63, 0x30, 0x34, 0x11, 0x95, 0xd0, 0xf7, 0x4a, 0xdd, 0xd3, + 0xea, 0x86, 0x01, 0xc4, 0x9f, 0x4b, 0xbd, 0x50, 0xeb, 0xb5, 0x1f, 0x73, 0x43, 0x47, 0x08, 0x1a, 0x7d, 0xd5, 0x2c, + 0x1a, 0xc7, 0x2d, 0x4d, 0x46, 0xc6, 0x8d, 0x36, 0x39, 0xbf, 0x02, 0x19, 0x9f, 0x35, 0x17, 0x9a, 0x34, 0x0d, 0x95, + 0x50, 0x85, 0xd1, 0xe6, 0xce, 0x4b, 0xa7, 0xf7, 0xe0, 0xce, 0xa6, 0xcd, 0x8e, 0x94, 0x4b, 0x63, 0x43, 0x4b, 0x5e, + 0xad, 0x44, 0x51, 0x41, 0x18, 0xe7, 0xde, 0x98, 0x5e, 0xc7, 0x59, 0x51, 0xc7, 0x59, 0x71, 0x5a, 0xad, 0x78, 0x52, + 0xbf, 0x87, 0x5b, 0x9c, 0xb4, 0xba, 0x69, 0x2a, 0xb8, 0xd2, 0x25, 0x07, 0x18, 0x4c, 0x4d, 0xc6, 0x3d, 0xb6, 0x06, + 0x17, 0xf5, 0xef, 0xd1, 0x52, 0x60, 0x2c, 0x54, 0x55, 0x7c, 0x7c, 0x51, 0x89, 0x7c, 0x5d, 0x83, 0x76, 0xf7, 0xb2, + 0x8e, 0x8e, 0x9e, 0xac, 0xee, 0xa6, 0xf2, 0x06, 0x13, 0x3d, 0x39, 0x5a, 0xdd, 0xf5, 0xb2, 0xeb, 0x95, 0x28, 0xeb, + 0xb8, 0xa8, 0xa7, 0x12, 0x91, 0x2c, 0x89, 0xf3, 0x24, 0x9c, 0x8c, 0xc7, 0x5f, 0x1c, 0x0c, 0x0f, 0x20, 0x03, 0x99, + 0xfe, 0x35, 0x94, 0x2e, 0x47, 0xc3, 0xc9, 0x78, 0x3c, 0x15, 0xf2, 0x6e, 0x17, 0x8d, 0x26, 0x0d, 0xd6, 0x33, 0x4c, + 0xd4, 0xcc, 0x8c, 0xf8, 0xdd, 0x2a, 0x2e, 0x52, 0x88, 0x5f, 0xa7, 0x8a, 0x3f, 0x7a, 0x32, 0xf6, 0xca, 0x37, 0x9f, + 0x3e, 0x6d, 0x7e, 0x6f, 0x74, 0x58, 0x6b, 0xdd, 0xee, 0x67, 0xbf, 0x1f, 0xcb, 0xf9, 0x3e, 0x39, 0x3e, 0x54, 0x3f, + 0x7e, 0x6f, 0x9a, 0xe9, 0xeb, 0x32, 0x9c, 0xff, 0x33, 0x94, 0xf3, 0x79, 0x5a, 0x96, 0xf1, 0x7d, 0x43, 0x16, 0x74, + 0x5d, 0x59, 0x6f, 0x12, 0xea, 0x6c, 0x03, 0x7a, 0x44, 0xa6, 0xeb, 0x8a, 0xc1, 0x37, 0xef, 0xeb, 0x30, 0xe0, 0xd5, + 0x6a, 0xc8, 0x8b, 0x3a, 0xab, 0xef, 0x87, 0x98, 0x27, 0xc0, 0x4f, 0x35, 0x6f, 0xf6, 0xac, 0xd4, 0xc4, 0xe6, 0xb2, + 0xe4, 0xfc, 0x2f, 0x1e, 0x4a, 0xe3, 0xe8, 0x31, 0x1a, 0x47, 0x8f, 0xa9, 0x1c, 0x8c, 0xc9, 0xd7, 0x54, 0x75, 0x66, + 0xf2, 0x35, 0x98, 0x20, 0x65, 0xed, 0x6f, 0xa4, 0x71, 0x62, 0x34, 0xa6, 0x37, 0x2f, 0xf3, 0x6c, 0x05, 0x4c, 0xf0, + 0x52, 0xfd, 0x68, 0x08, 0x7d, 0xcf, 0xdb, 0xd9, 0x47, 0xa3, 0xd1, 0xb3, 0x92, 0x8e, 0x46, 0xa3, 0x8f, 0x59, 0x43, + 0xe8, 0x65, 0xd5, 0xf1, 0xfe, 0x3d, 0xa7, 0x17, 0x22, 0xbd, 0x8f, 0x82, 0x80, 0x2e, 0xb3, 0x34, 0xe5, 0x85, 0x2c, + 0xeb, 0x2c, 0x6d, 0xe7, 0x95, 0x2d, 0x44, 0xe0, 0x1f, 0xd5, 0x46, 0x84, 0x20, 0x22, 0xf4, 0xed, 0x4e, 0xcf, 0x46, + 0xa3, 0xd1, 0x59, 0xaa, 0xab, 0xb5, 0x0c, 0xf9, 0x6b, 0x34, 0x1f, 0xb0, 0x76, 0xf9, 0x60, 0x7d, 0xa3, 0xa3, 0x9d, + 0x1c, 0xfe, 0xf7, 0x70, 0x36, 0x1f, 0x0f, 0xbf, 0x1d, 0x2d, 0x1e, 0x1f, 0xd2, 0x20, 0x70, 0x41, 0xab, 0x43, 0x65, + 0xcd, 0x31, 0x2d, 0x8e, 0xc7, 0x53, 0x52, 0x0c, 0xd8, 0x13, 0xe3, 0x4b, 0xf3, 0xc5, 0x13, 0x40, 0x22, 0x45, 0x11, + 0x6a, 0x60, 0xa5, 0x7f, 0x78, 0x15, 0x79, 0x55, 0x00, 0x3e, 0x9a, 0x89, 0x64, 0xa0, 0xb5, 0x80, 0xe3, 0x08, 0xca, + 0x6b, 0x8c, 0x69, 0x44, 0x8f, 0xb1, 0x4c, 0x47, 0x05, 0x1d, 0x4f, 0xab, 0xdb, 0xac, 0x4e, 0x96, 0x18, 0xd8, 0x28, + 0xae, 0x78, 0xf0, 0x45, 0x10, 0x15, 0xec, 0xe8, 0xe9, 0x54, 0xc2, 0xfb, 0x62, 0x52, 0xca, 0xaf, 0x20, 0xf1, 0xdb, + 0x31, 0x42, 0xa0, 0x12, 0xe5, 0xb1, 0x88, 0x35, 0xbe, 0xcc, 0x45, 0x0c, 0x1e, 0x9c, 0x95, 0xe2, 0x59, 0xcc, 0x49, + 0x60, 0xec, 0x2f, 0x5a, 0xcd, 0x11, 0xd0, 0x9c, 0x50, 0x30, 0x71, 0x58, 0x50, 0xf1, 0xc5, 0x04, 0xbd, 0x82, 0xc0, + 0xad, 0x3a, 0x82, 0xe3, 0xce, 0x58, 0x36, 0xa8, 0xe5, 0x93, 0xb2, 0xc3, 0xf9, 0xff, 0xae, 0xe8, 0x62, 0x70, 0x68, + 0x87, 0xe6, 0xad, 0x72, 0x5f, 0xad, 0x91, 0x51, 0xaa, 0xc3, 0x67, 0x29, 0x31, 0xc6, 0xa7, 0x9c, 0x9d, 0x6c, 0x74, + 0x77, 0x46, 0x75, 0x99, 0x5d, 0x87, 0x44, 0xf5, 0xca, 0x82, 0x62, 0x06, 0x51, 0x36, 0xc2, 0xf5, 0x03, 0xd6, 0x22, + 0x4e, 0x27, 0x6f, 0x78, 0x59, 0x67, 0x89, 0x7c, 0x7f, 0xe3, 0xbd, 0x07, 0x6a, 0x20, 0x1b, 0xf4, 0xae, 0x64, 0x30, + 0xcf, 0x6f, 0x4b, 0x00, 0xed, 0xac, 0x78, 0x79, 0xc3, 0x5d, 0xba, 0x11, 0x04, 0x8d, 0x6d, 0xe6, 0x95, 0x17, 0x6c, + 0x02, 0xbe, 0x7a, 0x57, 0x02, 0xe6, 0x46, 0x08, 0x52, 0x53, 0x08, 0x85, 0x03, 0x17, 0xf8, 0xba, 0x2e, 0xb3, 0x8b, + 0x75, 0xcd, 0x31, 0xd8, 0x47, 0x61, 0xb5, 0x98, 0xd2, 0x09, 0x8f, 0x87, 0x01, 0xfe, 0x08, 0xa8, 0x0c, 0xb8, 0xa1, + 0x3d, 0xec, 0xe0, 0x85, 0xfc, 0x65, 0xdf, 0xc8, 0x3d, 0xc2, 0x5e, 0xa7, 0x21, 0x04, 0xd7, 0xc1, 0x87, 0x00, 0x96, + 0x14, 0xa1, 0x6f, 0xf1, 0x54, 0x0d, 0x83, 0xcb, 0x3c, 0x5b, 0xa9, 0xa4, 0x7a, 0xd4, 0xd1, 0x7c, 0x28, 0xb5, 0x23, + 0x39, 0xa0, 0x4e, 0x7a, 0x8c, 0xe9, 0xa5, 0x4c, 0x97, 0x45, 0x59, 0x23, 0x94, 0x77, 0x6a, 0x62, 0x6c, 0x98, 0x3e, + 0x0e, 0x91, 0x5f, 0xde, 0x95, 0x32, 0xf4, 0x0b, 0x5f, 0x00, 0xf8, 0x15, 0xdc, 0xee, 0x77, 0xe3, 0xbb, 0xc8, 0xec, + 0xe7, 0x9c, 0x1d, 0xfe, 0xf7, 0x3c, 0x1e, 0xfe, 0x35, 0x1e, 0x7e, 0xbb, 0x18, 0x84, 0x43, 0xf3, 0x93, 0x3c, 0x7e, + 0x74, 0x48, 0x5f, 0x72, 0xc3, 0x95, 0xc0, 0xc2, 0xf7, 0x82, 0xdb, 0xc8, 0x95, 0x10, 0x44, 0x01, 0xde, 0x28, 0xec, + 0x6a, 0x9c, 0x00, 0xc0, 0x5f, 0xf0, 0x5f, 0x01, 0x1a, 0x09, 0xd9, 0x8b, 0x06, 0xe8, 0x07, 0xe4, 0xef, 0x93, 0xaf, + 0x3c, 0x03, 0x39, 0x10, 0x4f, 0xc8, 0x18, 0x28, 0x44, 0x95, 0x31, 0x91, 0xb0, 0xbf, 0x26, 0xfb, 0x76, 0xdb, 0x6b, + 0x4b, 0x7e, 0xf0, 0x4b, 0x37, 0xd3, 0x44, 0xcf, 0x3b, 0xdc, 0x50, 0x56, 0x62, 0x15, 0x22, 0x36, 0x9e, 0xfa, 0x95, + 0x33, 0x88, 0x35, 0x79, 0x93, 0x81, 0x0f, 0x83, 0xf9, 0x62, 0x3c, 0x03, 0x69, 0x11, 0xdc, 0x71, 0x4a, 0x7e, 0x99, + 0x81, 0x5b, 0x73, 0x11, 0xe3, 0x05, 0xdb, 0x2c, 0x89, 0x7e, 0xbf, 0x97, 0x67, 0x61, 0xae, 0x70, 0x96, 0xf3, 0x46, + 0x8b, 0xdd, 0x51, 0x27, 0x0c, 0xe2, 0x76, 0x35, 0x04, 0x43, 0x39, 0x04, 0x65, 0x47, 0x5b, 0x6c, 0xbd, 0xa6, 0x9e, + 0x52, 0xf7, 0x56, 0xd6, 0x57, 0x8e, 0xfe, 0x10, 0x59, 0x81, 0x85, 0xb4, 0x6b, 0x8e, 0x55, 0xcd, 0x31, 0xd2, 0x9e, + 0x7e, 0xbf, 0xf2, 0xc8, 0x4f, 0x67, 0xe1, 0x41, 0x20, 0x4b, 0x15, 0x3b, 0x65, 0x51, 0x6e, 0x4a, 0x73, 0xc6, 0xb0, + 0xa1, 0x79, 0x66, 0xe2, 0xba, 0xcc, 0x7a, 0xbd, 0x30, 0x44, 0x87, 0x46, 0x2c, 0x15, 0x6b, 0x83, 0xf0, 0x3e, 0x3a, + 0x61, 0x74, 0x0d, 0xb2, 0xba, 0xf0, 0x9c, 0x13, 0xe4, 0xcb, 0xc0, 0x64, 0x4d, 0x56, 0xeb, 0xe4, 0x84, 0x47, 0x2f, + 0x5f, 0x36, 0x82, 0x06, 0x39, 0x49, 0x51, 0x6f, 0x62, 0x77, 0xec, 0xa3, 0x16, 0x52, 0xe3, 0xa6, 0x99, 0xf6, 0x14, + 0xa9, 0xe8, 0xb1, 0x5e, 0x2d, 0x7f, 0x81, 0x65, 0x81, 0x21, 0x1f, 0x84, 0xf6, 0x14, 0xad, 0xc0, 0x0c, 0x37, 0x26, + 0x83, 0xa6, 0x1f, 0x16, 0x6d, 0x11, 0x3a, 0x23, 0xb7, 0x25, 0x84, 0x6d, 0x1b, 0x84, 0xb5, 0xf3, 0x44, 0xbe, 0x78, + 0xe2, 0x30, 0xc2, 0x21, 0xd7, 0x9b, 0xb9, 0xf2, 0x30, 0xcc, 0xaf, 0x85, 0xdf, 0x3c, 0xd5, 0x5c, 0x27, 0x2a, 0x66, + 0x05, 0xdb, 0xed, 0xb2, 0x22, 0xf8, 0xf7, 0x63, 0x36, 0xc3, 0xbf, 0x59, 0xbf, 0xdf, 0x0b, 0xf1, 0x17, 0xc7, 0xe0, + 0x3d, 0xf3, 0x6a, 0xc1, 0x3e, 0x82, 0x4c, 0x85, 0x44, 0x98, 0x2a, 0x8d, 0xdf, 0x58, 0x0d, 0x16, 0x70, 0xfa, 0x03, + 0x99, 0x0b, 0x33, 0x99, 0xcb, 0x8b, 0x6d, 0xc8, 0x69, 0x6b, 0x9c, 0xb2, 0x51, 0x96, 0x48, 0xd7, 0x85, 0x6c, 0x14, + 0xe7, 0x59, 0x5c, 0xf1, 0x6a, 0xbb, 0x55, 0x87, 0x63, 0x52, 0x72, 0xf4, 0x2b, 0x40, 0x2a, 0x55, 0xb0, 0x8e, 0x54, + 0x3b, 0xfe, 0x22, 0x2c, 0x71, 0x9f, 0xf2, 0x79, 0xb9, 0x30, 0x7b, 0x6b, 0x5e, 0x2e, 0x98, 0xbc, 0x95, 0xf6, 0xc2, + 0x12, 0x9a, 0x57, 0x10, 0xb2, 0xc1, 0x54, 0xc7, 0xa2, 0x35, 0x66, 0xd5, 0xbc, 0x5c, 0x40, 0x18, 0x99, 0x72, 0x01, + 0x36, 0x53, 0xbc, 0x00, 0x2f, 0x92, 0x18, 0x60, 0xe2, 0x62, 0x32, 0x85, 0x78, 0xe6, 0xb2, 0x9c, 0x78, 0xa1, 0xef, + 0x97, 0x89, 0x45, 0xca, 0x80, 0x57, 0x8d, 0x46, 0x13, 0x33, 0x0d, 0x47, 0x9d, 0x20, 0x27, 0x3a, 0xbf, 0x9b, 0x5a, + 0x11, 0x62, 0x4f, 0x1c, 0x01, 0x97, 0x15, 0xd3, 0x85, 0x17, 0x1d, 0x88, 0x31, 0x72, 0x70, 0x8a, 0x4f, 0x0c, 0x8e, + 0xc2, 0xe0, 0xdc, 0x38, 0x27, 0x48, 0x19, 0xc6, 0x64, 0x23, 0xd8, 0xb5, 0x08, 0xab, 0x79, 0xbc, 0x00, 0x65, 0x5d, + 0xbc, 0x00, 0xcb, 0x1a, 0x6d, 0x80, 0x09, 0xf2, 0x2a, 0xee, 0x84, 0x7e, 0xa2, 0xb8, 0x42, 0x84, 0x63, 0xe5, 0xfa, + 0xa8, 0x6c, 0x87, 0xbe, 0xc0, 0xeb, 0xbd, 0x34, 0xc7, 0xcd, 0x7a, 0x2c, 0x10, 0xd8, 0x10, 0x30, 0x36, 0x52, 0x69, + 0xb2, 0xb5, 0xf6, 0x8d, 0x9e, 0x07, 0x3e, 0xcd, 0x46, 0x85, 0xa8, 0xcf, 0x2f, 0x41, 0x84, 0xe2, 0xa2, 0xc1, 0x23, + 0xbf, 0x88, 0x3b, 0x4b, 0xbf, 0x35, 0x2d, 0x2a, 0xd8, 0xc9, 0x06, 0x40, 0xfa, 0x54, 0xb4, 0x28, 0x29, 0xa7, 0x28, + 0x48, 0x63, 0x37, 0x05, 0xac, 0x24, 0x77, 0x01, 0x43, 0xb0, 0xb1, 0x83, 0xca, 0xea, 0x14, 0x11, 0x49, 0x02, 0x91, + 0x15, 0xc3, 0x82, 0xe2, 0xd8, 0x16, 0x88, 0xfa, 0x69, 0xca, 0x32, 0x83, 0xa1, 0xa3, 0xe2, 0x3e, 0x4f, 0x1d, 0x4a, + 0x14, 0x04, 0x54, 0x0d, 0x39, 0x48, 0x6c, 0x4d, 0x03, 0xe1, 0x01, 0x79, 0x44, 0x67, 0xac, 0xbf, 0xcf, 0x3a, 0xcf, + 0x2e, 0x34, 0x47, 0xe5, 0x6a, 0x57, 0xe8, 0x31, 0xc2, 0x93, 0x4c, 0xc3, 0xe4, 0x3b, 0xe7, 0x99, 0x56, 0x53, 0xf4, + 0x1c, 0x7c, 0xb2, 0x53, 0x8c, 0x48, 0xb7, 0x67, 0xd0, 0x75, 0xf0, 0xaa, 0x0e, 0x1b, 0xed, 0x5a, 0x42, 0x48, 0xe8, + 0x5a, 0x14, 0x31, 0xeb, 0x19, 0x03, 0xea, 0xed, 0xb6, 0xa7, 0xe6, 0x6a, 0xff, 0xdc, 0x6d, 0xb7, 0x3d, 0xec, 0xd6, + 0xf3, 0xb4, 0xdb, 0x0a, 0xbc, 0x96, 0x1f, 0xb4, 0xc7, 0x9f, 0xdb, 0xf1, 0xe7, 0x1a, 0xc9, 0xa3, 0xb0, 0x34, 0xd3, + 0xd4, 0x07, 0xe1, 0x70, 0xd3, 0x7b, 0xaf, 0x49, 0xdf, 0x67, 0xa1, 0xa0, 0x97, 0x95, 0x57, 0x5d, 0x63, 0x4d, 0x2a, + 0x1f, 0x5c, 0xff, 0x0f, 0xaf, 0x02, 0x3c, 0xe2, 0xe4, 0xce, 0xde, 0xdb, 0xa0, 0xd2, 0x6b, 0x0b, 0x47, 0x8a, 0xd0, + 0x03, 0x92, 0xb0, 0xaf, 0x65, 0x2d, 0x6e, 0xf3, 0x2c, 0x7b, 0x98, 0x3e, 0xbd, 0x4a, 0x5d, 0xab, 0x7b, 0xbb, 0xcc, + 0x32, 0x7d, 0xe0, 0xd5, 0x14, 0x07, 0x34, 0xea, 0xa2, 0x7d, 0xd7, 0x59, 0x55, 0x81, 0x97, 0x07, 0x5c, 0x9f, 0xcf, + 0xb8, 0x0b, 0x37, 0x77, 0x55, 0xfb, 0x9b, 0xf4, 0x2c, 0x9b, 0x67, 0x8b, 0xed, 0x36, 0xc4, 0xbf, 0x5d, 0x2d, 0xb2, + 0x34, 0x79, 0x0e, 0x3a, 0x3c, 0x8c, 0xdc, 0xc3, 0x54, 0xe3, 0x9c, 0xcd, 0xff, 0xb2, 0xf2, 0x9c, 0x04, 0x4e, 0x81, + 0x5e, 0xcc, 0x1e, 0x81, 0x0c, 0x46, 0x3b, 0xf5, 0x57, 0x33, 0xb5, 0x66, 0x20, 0xfa, 0x56, 0x15, 0x01, 0x8e, 0x2e, + 0x36, 0x12, 0x8d, 0x2c, 0x38, 0x69, 0x08, 0x58, 0x6c, 0x9a, 0xf2, 0x3e, 0x18, 0xda, 0x56, 0x97, 0xf7, 0xce, 0x92, + 0xe6, 0xb8, 0x0e, 0xac, 0x6d, 0xbf, 0x1e, 0x62, 0x5d, 0x76, 0xbd, 0x40, 0xee, 0x97, 0x37, 0xb4, 0x37, 0x6e, 0x12, + 0x98, 0xb5, 0x4d, 0x63, 0x18, 0x3f, 0x53, 0xfa, 0x4f, 0x6a, 0x70, 0xa5, 0xf1, 0xd3, 0x5c, 0x5b, 0x25, 0x98, 0x7d, + 0xe3, 0xf8, 0x0e, 0x40, 0x38, 0x36, 0x97, 0x1e, 0x9f, 0x65, 0x0e, 0x3d, 0x06, 0xa2, 0xa3, 0x3f, 0x2a, 0xec, 0x47, + 0x66, 0xf7, 0xba, 0x01, 0xf0, 0xe6, 0x75, 0xbb, 0xa0, 0x79, 0xb1, 0x80, 0x40, 0xa2, 0x4e, 0x79, 0xa5, 0xe1, 0x33, + 0x63, 0x76, 0x05, 0x64, 0xa8, 0x24, 0x60, 0x93, 0xd4, 0x75, 0x2e, 0xc4, 0xb2, 0xc3, 0xd2, 0x7c, 0x24, 0x61, 0x27, + 0x21, 0xa0, 0xbd, 0x06, 0xc1, 0x2c, 0xf8, 0xaf, 0x60, 0x50, 0x0c, 0x82, 0x28, 0x88, 0x82, 0x80, 0x0c, 0x4a, 0xf8, + 0x85, 0x38, 0x63, 0x04, 0x63, 0x94, 0x40, 0x87, 0xdf, 0x71, 0xe6, 0x32, 0x22, 0x2f, 0xbc, 0x30, 0x96, 0x76, 0x00, + 0x2e, 0x84, 0xc8, 0x79, 0x8c, 0x3e, 0x16, 0xef, 0x38, 0xcb, 0x08, 0x7d, 0xe7, 0x9c, 0xca, 0x8f, 0xb8, 0x17, 0xdc, + 0x6e, 0x77, 0xd8, 0x5e, 0xf2, 0x30, 0xa3, 0xbd, 0x31, 0x7d, 0xc7, 0x49, 0x94, 0x79, 0xce, 0xc3, 0x1c, 0x7a, 0x56, + 0x1b, 0xd6, 0x8a, 0x6a, 0x72, 0x83, 0x62, 0x5d, 0x64, 0x99, 0xac, 0x0c, 0x57, 0xce, 0x69, 0x85, 0xeb, 0xce, 0xac, + 0x17, 0x90, 0x94, 0x55, 0x8a, 0xa5, 0x33, 0xe1, 0xab, 0x4d, 0xcb, 0x9e, 0xb7, 0x4e, 0x21, 0xa7, 0x21, 0x32, 0xfa, + 0xa1, 0x25, 0xa0, 0x9a, 0x56, 0x5c, 0xd5, 0xe0, 0xb2, 0xab, 0xdb, 0xc3, 0x75, 0x7b, 0x74, 0x33, 0x3e, 0x40, 0x8c, + 0x38, 0x8e, 0x2d, 0x03, 0xbb, 0x09, 0x8b, 0x67, 0x63, 0x7d, 0x5f, 0x76, 0xe9, 0xad, 0xad, 0xc5, 0x21, 0xac, 0x3d, + 0x67, 0x85, 0x84, 0x00, 0x69, 0xa9, 0x2b, 0xdd, 0x6e, 0x83, 0x00, 0x06, 0xb8, 0xdf, 0xef, 0x01, 0xd7, 0xaa, 0xd9, + 0x49, 0x7d, 0x6b, 0x36, 0xc4, 0x5e, 0x52, 0x78, 0x0c, 0x44, 0xa9, 0xf8, 0xcf, 0x20, 0xa0, 0x78, 0xee, 0x86, 0x60, + 0x5f, 0xc9, 0x4e, 0x36, 0x65, 0xbf, 0xff, 0xbc, 0xc4, 0x07, 0x94, 0x83, 0x82, 0x58, 0x57, 0xc5, 0xad, 0xd0, 0xec, + 0x93, 0xfc, 0x10, 0xc7, 0x22, 0xcf, 0x42, 0x4b, 0x58, 0x6a, 0x4d, 0x58, 0xb8, 0x64, 0xa4, 0x83, 0x38, 0x68, 0x48, + 0xe7, 0x60, 0xd5, 0x36, 0xd8, 0x70, 0xaf, 0xf7, 0xb2, 0x0a, 0x2b, 0x9a, 0x39, 0xc3, 0xf2, 0xde, 0x01, 0x00, 0xeb, + 0xf5, 0x70, 0xa1, 0x38, 0x64, 0xc2, 0x43, 0x9f, 0xc4, 0x97, 0x86, 0x5d, 0x9f, 0x29, 0x59, 0xc9, 0x68, 0x34, 0xaa, + 0x1b, 0x29, 0xf9, 0x30, 0xdf, 0xbd, 0x69, 0xa1, 0x56, 0x8a, 0x38, 0xe5, 0x29, 0x58, 0x7a, 0x6b, 0x4a, 0x37, 0x5f, + 0xd0, 0x15, 0x2f, 0x52, 0xf9, 0xd3, 0x41, 0x9b, 0xf4, 0x88, 0x6b, 0xe6, 0xeb, 0x2c, 0xcc, 0xf0, 0x43, 0xc0, 0x47, + 0xf3, 0x30, 0xb3, 0xe9, 0x0a, 0x96, 0x16, 0xc4, 0x91, 0x71, 0xc9, 0x43, 0x9b, 0x07, 0xb0, 0xfe, 0xf4, 0x21, 0x89, + 0x9f, 0xc2, 0xcf, 0x99, 0x4e, 0xeb, 0xf8, 0x0c, 0x67, 0x33, 0x2a, 0xe4, 0x8d, 0xa0, 0xfd, 0x1a, 0x12, 0x89, 0x46, + 0x36, 0xf6, 0x18, 0x8a, 0xd6, 0xdd, 0x06, 0xae, 0xfc, 0x86, 0xde, 0xb9, 0x34, 0x08, 0xb0, 0xad, 0xb1, 0x18, 0x38, + 0xe3, 0xf1, 0x07, 0xaa, 0x6a, 0xf4, 0x15, 0x45, 0x37, 0x4c, 0x26, 0x9a, 0x3b, 0x8e, 0xed, 0xa8, 0x76, 0x95, 0xad, + 0x58, 0x61, 0x6c, 0x79, 0xed, 0x5b, 0x5a, 0x9a, 0x12, 0x50, 0x0d, 0x86, 0x3b, 0x01, 0x7c, 0x46, 0x84, 0x3c, 0x10, + 0x44, 0xf7, 0xc1, 0x41, 0x73, 0x96, 0xe0, 0x79, 0x18, 0xc2, 0x1f, 0x58, 0x38, 0xb0, 0x2c, 0x65, 0x3f, 0x97, 0xd3, + 0x18, 0xce, 0xdd, 0x5c, 0xee, 0xf0, 0xd9, 0x12, 0x14, 0x79, 0x72, 0x4e, 0xf5, 0xe5, 0x2b, 0xf7, 0xf6, 0x7b, 0x4c, + 0x30, 0x8f, 0x9e, 0x6d, 0xf8, 0xad, 0xa6, 0xdb, 0xf8, 0xc2, 0xda, 0x81, 0x13, 0xe6, 0xc2, 0x69, 0x2e, 0xb6, 0x4b, + 0x0d, 0x71, 0xd7, 0x78, 0x42, 0x84, 0x57, 0x8a, 0x58, 0x64, 0x9e, 0x4c, 0xc7, 0x60, 0x63, 0xc8, 0x36, 0x95, 0xcf, + 0x94, 0x42, 0xbc, 0x9a, 0xca, 0x0b, 0x53, 0x2b, 0x95, 0x55, 0x1a, 0x61, 0xa6, 0x80, 0x45, 0x95, 0x81, 0xcf, 0x7e, + 0x8d, 0x14, 0xd7, 0xd4, 0xf3, 0x17, 0x2e, 0xdf, 0x4c, 0xb7, 0xd9, 0x7c, 0xfa, 0x32, 0x8f, 0xaf, 0xb6, 0xdb, 0xb0, + 0xfb, 0x05, 0x98, 0x5f, 0x56, 0x52, 0xa3, 0x06, 0x4e, 0x0f, 0x21, 0xfa, 0x39, 0xef, 0xc9, 0x39, 0xb1, 0x9c, 0x5c, + 0xbb, 0x79, 0xb3, 0x9d, 0x14, 0x2d, 0xb0, 0x80, 0x13, 0x17, 0xe9, 0x40, 0x4b, 0x05, 0xa7, 0x2c, 0xe3, 0x9d, 0x4d, + 0x6f, 0x29, 0x15, 0x5e, 0x2d, 0x14, 0x09, 0xa9, 0xed, 0xbd, 0xc4, 0x8c, 0x1a, 0x70, 0x4e, 0xf2, 0x0e, 0x02, 0x4e, + 0x6a, 0xaa, 0xb1, 0x46, 0x71, 0xaa, 0x13, 0x9c, 0x57, 0x6a, 0xe8, 0x12, 0xe5, 0xc4, 0x6d, 0xb7, 0x55, 0xd1, 0x42, + 0x7d, 0x3c, 0xc8, 0x59, 0x22, 0x8f, 0x07, 0x14, 0xba, 0xc8, 0xa3, 0x21, 0x5f, 0x90, 0x52, 0xad, 0x1c, 0xa5, 0x5a, + 0xdd, 0x95, 0x0c, 0x14, 0x72, 0x15, 0xe4, 0x0d, 0x31, 0xee, 0x5a, 0x99, 0xb7, 0xb8, 0x72, 0x42, 0x4a, 0x93, 0xf0, + 0xb9, 0xa5, 0x18, 0x58, 0xc1, 0xde, 0x98, 0xba, 0xc2, 0x25, 0x42, 0xdb, 0xdd, 0x86, 0x98, 0x64, 0xb0, 0x6e, 0xb6, + 0xdb, 0x57, 0x65, 0x38, 0xcf, 0x16, 0x54, 0x8c, 0xb2, 0x14, 0x21, 0xc4, 0xb4, 0x87, 0xae, 0xe9, 0x82, 0x9e, 0x18, + 0x6a, 0xdb, 0xe3, 0x24, 0xe9, 0x62, 0x4d, 0x92, 0x18, 0xc5, 0x17, 0xa2, 0x94, 0x6b, 0x8d, 0x10, 0x3c, 0xdc, 0xff, + 0x48, 0x21, 0x86, 0x9b, 0x5e, 0x77, 0xbf, 0xee, 0xdc, 0x10, 0xff, 0x80, 0x40, 0x02, 0x05, 0x7b, 0x55, 0x8e, 0x2e, + 0xb2, 0x22, 0xc5, 0x9d, 0x2a, 0xa3, 0xe2, 0xca, 0x75, 0xe0, 0xb7, 0xdc, 0xf0, 0xaf, 0x86, 0x28, 0x40, 0x5c, 0xe3, + 0x4a, 0x31, 0x9e, 0xb5, 0xb5, 0x14, 0xc9, 0x28, 0x36, 0x24, 0x2a, 0x9c, 0xa8, 0xe8, 0x2e, 0x4f, 0xa3, 0x7b, 0x68, + 0xd7, 0x20, 0xb8, 0x6a, 0xee, 0x6c, 0xa4, 0xf9, 0x82, 0x10, 0x39, 0x01, 0x02, 0x36, 0xaa, 0x3e, 0xb5, 0x56, 0xd5, + 0xc3, 0xac, 0xf2, 0xb9, 0x3a, 0x88, 0x57, 0x15, 0xf0, 0xb0, 0xce, 0xf6, 0xbe, 0xaa, 0x1c, 0xd6, 0x06, 0xdf, 0x6e, + 0xb7, 0xab, 0x6a, 0x1e, 0x04, 0x0e, 0xa3, 0xf9, 0x9d, 0x94, 0x98, 0xf7, 0xc6, 0x14, 0x56, 0xbc, 0xeb, 0xd2, 0xd6, + 0x4d, 0x6a, 0x8d, 0x05, 0xea, 0x0e, 0xd7, 0x07, 0x3c, 0x4f, 0x81, 0xa3, 0x1d, 0x15, 0x53, 0x61, 0x74, 0xe5, 0xd8, + 0x95, 0x0a, 0x03, 0x43, 0xff, 0x90, 0xb2, 0x0d, 0x98, 0xe3, 0x81, 0xb5, 0x0d, 0xfa, 0x29, 0x49, 0x2d, 0xcc, 0x18, + 0x8d, 0x59, 0xc4, 0xba, 0x8e, 0x8e, 0xb8, 0x8a, 0xde, 0xce, 0xa3, 0xbf, 0x3d, 0x1d, 0xd3, 0x32, 0x2e, 0x52, 0x71, + 0x0d, 0x2a, 0x08, 0x50, 0x86, 0xa0, 0xe1, 0xbf, 0xa2, 0x06, 0xa0, 0x41, 0xb0, 0x03, 0xf0, 0x8f, 0x4e, 0xa7, 0x41, + 0x53, 0x93, 0x8b, 0x49, 0x2a, 0x8b, 0x9c, 0xb5, 0xa1, 0xcc, 0x64, 0x72, 0x48, 0x1e, 0x17, 0x80, 0xe7, 0x88, 0xcd, + 0x92, 0x36, 0x17, 0x72, 0xb3, 0xc9, 0xd7, 0x92, 0x1d, 0xb9, 0xf3, 0x8a, 0xd6, 0x6b, 0x51, 0xd9, 0x49, 0xcc, 0x17, + 0xd3, 0x3b, 0x23, 0x0c, 0x9c, 0xea, 0xd6, 0xdc, 0xee, 0x40, 0xa7, 0x99, 0xfa, 0x74, 0x6e, 0x02, 0xc4, 0x01, 0x86, + 0xeb, 0x6e, 0x7e, 0xbb, 0x20, 0xf4, 0x8e, 0xdd, 0x19, 0xb1, 0xea, 0xad, 0x91, 0x8b, 0xe8, 0xb4, 0xdb, 0xc1, 0x04, + 0x2e, 0xe3, 0xac, 0x34, 0x2f, 0x94, 0xba, 0xa1, 0xec, 0x68, 0x9b, 0x30, 0x9f, 0x77, 0xb4, 0x1b, 0x2e, 0xf8, 0x46, + 0xac, 0x63, 0xdd, 0x90, 0xa6, 0x12, 0x3d, 0x3a, 0x50, 0xdb, 0x21, 0xa0, 0x39, 0x1b, 0xd3, 0x25, 0x40, 0x6d, 0xc2, + 0x7e, 0x59, 0x83, 0x59, 0xca, 0x25, 0xf4, 0xb5, 0xdb, 0x27, 0xf9, 0x52, 0xf6, 0xa4, 0x72, 0x96, 0x28, 0xf8, 0x72, + 0xa4, 0xe0, 0x95, 0x95, 0xf3, 0x58, 0xcf, 0x21, 0xe0, 0xb1, 0xc8, 0x12, 0x9d, 0x93, 0xe2, 0x0a, 0x94, 0xa9, 0x70, + 0x04, 0xea, 0xaa, 0x11, 0x4b, 0x38, 0xc0, 0xed, 0xc5, 0xd3, 0x80, 0x50, 0x90, 0xea, 0xae, 0xcd, 0x8a, 0xbc, 0x63, + 0x27, 0x9b, 0x3b, 0x30, 0x8b, 0xad, 0xd7, 0x55, 0xeb, 0x2b, 0x93, 0x6c, 0x3f, 0x6e, 0x08, 0xb6, 0xdd, 0x91, 0xf2, + 0x85, 0x77, 0xf4, 0x96, 0x6c, 0x6e, 0xfb, 0xfd, 0x10, 0xfa, 0x43, 0xa8, 0xea, 0xd0, 0x5d, 0x67, 0x87, 0xee, 0x5c, + 0xe6, 0xd7, 0xe8, 0xf9, 0xa4, 0x37, 0xc4, 0x07, 0x34, 0xd1, 0xa2, 0xab, 0xf8, 0x1e, 0x36, 0x75, 0x54, 0x53, 0x59, + 0x79, 0x94, 0x50, 0x50, 0x01, 0x67, 0xbc, 0x3a, 0xe3, 0x18, 0xdb, 0x54, 0x3d, 0xbd, 0x53, 0xbc, 0xda, 0x5a, 0xaf, + 0xcd, 0x6a, 0x7d, 0x01, 0x16, 0x01, 0x17, 0x3c, 0xba, 0x56, 0xb4, 0xe4, 0xca, 0x61, 0xea, 0xcf, 0x71, 0x54, 0x82, + 0xcb, 0x38, 0xcb, 0x79, 0x1a, 0xd0, 0x4b, 0xbf, 0xff, 0xa1, 0xb2, 0x95, 0x5a, 0x7a, 0x67, 0xee, 0x4d, 0x48, 0x36, + 0xff, 0x63, 0x03, 0xf5, 0x3a, 0xc4, 0x88, 0xa8, 0x7a, 0x41, 0xbf, 0x65, 0x10, 0x1b, 0x33, 0xa8, 0xd6, 0x49, 0xc2, + 0xab, 0x2a, 0xd0, 0x4a, 0xad, 0x35, 0x5b, 0xeb, 0xf3, 0xec, 0x11, 0x3b, 0x79, 0xd4, 0x63, 0xec, 0x8e, 0xd0, 0x44, + 0xe9, 0x84, 0x74, 0x8d, 0x91, 0xa3, 0x05, 0x52, 0x1d, 0x8a, 0xb2, 0xcb, 0xf0, 0x2d, 0x0a, 0x59, 0xda, 0xfb, 0x5c, + 0x9f, 0xc8, 0xf2, 0x1b, 0x65, 0x74, 0x11, 0xc9, 0x44, 0x90, 0x8d, 0xdf, 0x22, 0x60, 0x2f, 0x34, 0x3b, 0x20, 0x9b, + 0x25, 0x3b, 0xa3, 0xe7, 0xc6, 0x04, 0x06, 0x5e, 0xbf, 0x95, 0x89, 0x7a, 0x94, 0x25, 0xd1, 0x95, 0x46, 0x2e, 0xf7, + 0x21, 0x89, 0xce, 0x43, 0xe2, 0xe6, 0x86, 0xa5, 0x75, 0x13, 0xa2, 0x98, 0x59, 0x6f, 0x78, 0xd9, 0xdd, 0x47, 0xde, + 0xb6, 0xd2, 0x3e, 0xd5, 0x77, 0x26, 0x8d, 0x4c, 0xa1, 0xaf, 0xc3, 0x49, 0xbf, 0x0f, 0x7f, 0x15, 0xfd, 0xc0, 0x5b, + 0x0a, 0xfe, 0x62, 0x8f, 0x48, 0x93, 0xb0, 0x00, 0xe0, 0x08, 0x73, 0x5e, 0xfb, 0x13, 0xf8, 0x88, 0x9d, 0x6c, 0x1e, + 0x85, 0x67, 0xde, 0xcc, 0xdd, 0x87, 0x78, 0xa9, 0x4a, 0x7a, 0xce, 0x3c, 0xe9, 0x81, 0x58, 0x85, 0x7a, 0xbf, 0xde, + 0x31, 0xa3, 0x4f, 0x00, 0x22, 0x75, 0x67, 0x1c, 0x4a, 0xf1, 0x63, 0xdd, 0x65, 0xb2, 0x49, 0x59, 0x9b, 0x89, 0x92, + 0x2a, 0x12, 0x7f, 0x11, 0x40, 0xbf, 0x61, 0x38, 0x1a, 0x80, 0xf7, 0x56, 0x63, 0xaf, 0x87, 0xc6, 0x19, 0x53, 0x4d, + 0xcf, 0x36, 0x6a, 0x79, 0x5b, 0x0a, 0xa1, 0xc7, 0x22, 0xba, 0xb3, 0xc7, 0x62, 0x78, 0x46, 0xdf, 0x42, 0x85, 0xaf, + 0x43, 0x8c, 0xa6, 0x4b, 0x9a, 0x66, 0xba, 0x96, 0x5b, 0xe9, 0x96, 0xd0, 0x1c, 0xa3, 0xf8, 0x38, 0x6d, 0xbb, 0xa7, + 0x5a, 0x68, 0x4f, 0x28, 0x0f, 0xef, 0x68, 0x4d, 0x6f, 0x0d, 0x8b, 0x60, 0x91, 0x96, 0x9d, 0xfc, 0x84, 0x5e, 0x38, + 0x02, 0x93, 0xb2, 0xad, 0x01, 0xfc, 0x01, 0xf5, 0xc3, 0x59, 0x33, 0x35, 0x52, 0x0e, 0x47, 0xe1, 0x4b, 0x36, 0x20, + 0x57, 0x50, 0x8b, 0x35, 0x66, 0x27, 0x31, 0xe8, 0xa0, 0x76, 0x76, 0x87, 0x33, 0x29, 0x88, 0x64, 0x44, 0x73, 0x0b, + 0xf1, 0xf4, 0x0f, 0xd0, 0xf4, 0x41, 0x5a, 0x98, 0xd2, 0x35, 0x0a, 0x78, 0x40, 0xdf, 0xd4, 0xef, 0xe7, 0xf8, 0xdc, + 0x38, 0x96, 0x58, 0xd8, 0xe3, 0x25, 0xa1, 0x4b, 0x27, 0x6e, 0x14, 0x48, 0x9b, 0x2d, 0xab, 0x00, 0xac, 0x48, 0x02, + 0x8d, 0x48, 0xd0, 0x52, 0xc7, 0x8a, 0xcb, 0x36, 0x68, 0x40, 0x12, 0x15, 0x14, 0xb2, 0x44, 0x02, 0xf8, 0x61, 0x04, + 0x21, 0x8a, 0x62, 0x10, 0xf7, 0xaa, 0xe5, 0x15, 0x37, 0x54, 0x83, 0x13, 0x45, 0x30, 0xc1, 0x2a, 0x9d, 0x02, 0xb1, + 0x2d, 0xd6, 0x2b, 0xf0, 0xbc, 0xb4, 0x17, 0x49, 0x64, 0x09, 0xd0, 0x20, 0xcd, 0x95, 0x4e, 0xdb, 0xe5, 0xed, 0x88, + 0x96, 0x6a, 0x36, 0x77, 0x5e, 0x2c, 0x0c, 0xf7, 0x58, 0xbb, 0xdb, 0x81, 0xf6, 0xc2, 0x7a, 0x47, 0x44, 0x0d, 0x56, + 0x76, 0x6d, 0xbb, 0x36, 0x94, 0x86, 0xaa, 0x5e, 0x59, 0x26, 0xa0, 0xa6, 0xab, 0xb8, 0x5e, 0x46, 0xd9, 0x08, 0xfe, + 0x6c, 0xb7, 0xc1, 0x61, 0x00, 0x16, 0x90, 0xbf, 0xbc, 0xff, 0x29, 0xc2, 0xf0, 0x4c, 0xbf, 0xbc, 0xff, 0x69, 0xbb, + 0x7d, 0x3a, 0x1e, 0x6b, 0xae, 0xc0, 0xaa, 0x75, 0x80, 0x3f, 0xd0, 0x6c, 0x83, 0x59, 0xb2, 0xdb, 0xed, 0x53, 0xe0, + 0x20, 0x24, 0xdb, 0xa0, 0x77, 0xb1, 0x74, 0xe4, 0x92, 0xac, 0x86, 0xda, 0x91, 0x80, 0x55, 0xb7, 0xc3, 0x52, 0xec, + 0x52, 0x1f, 0x19, 0x82, 0x51, 0x2d, 0xfa, 0x17, 0x9d, 0x02, 0x4b, 0x0a, 0xa6, 0xab, 0xc1, 0xb2, 0xae, 0x57, 0x55, + 0x74, 0x78, 0x18, 0xaf, 0xb2, 0x51, 0x95, 0xc1, 0x36, 0xaf, 0x6e, 0xae, 0x00, 0x50, 0x21, 0xa0, 0xde, 0xbb, 0x75, + 0x91, 0xe9, 0x17, 0x0b, 0xba, 0xcc, 0x70, 0x4d, 0x82, 0xd9, 0x41, 0xce, 0x8d, 0x6e, 0x72, 0x4a, 0xcc, 0x03, 0xd8, + 0x1c, 0x6e, 0xb7, 0x1e, 0xbf, 0x70, 0x32, 0x7a, 0x3a, 0x5b, 0x66, 0xca, 0xa0, 0x93, 0xeb, 0xfd, 0x4f, 0x22, 0x27, + 0x0d, 0x15, 0x9f, 0x64, 0xfa, 0x22, 0x03, 0x3e, 0x8f, 0xbd, 0xa9, 0x42, 0x97, 0xe5, 0xf2, 0x5a, 0x03, 0x6c, 0x6c, + 0x76, 0x79, 0x3f, 0x4a, 0x39, 0x44, 0xa4, 0x08, 0x8c, 0xba, 0x66, 0x99, 0x11, 0xd7, 0xa6, 0xe2, 0xbe, 0xa5, 0x0a, + 0x7b, 0x53, 0x39, 0xce, 0x2a, 0x5c, 0x3b, 0xca, 0xf4, 0x26, 0x51, 0xf8, 0x02, 0x85, 0xa8, 0x1c, 0x8d, 0xe9, 0xac, + 0x40, 0x2a, 0x73, 0x98, 0x50, 0xcc, 0x61, 0xdf, 0xfd, 0x92, 0x5a, 0x73, 0x19, 0x57, 0xb8, 0xf7, 0xc2, 0x95, 0x99, + 0xdc, 0x09, 0x00, 0x45, 0x92, 0xb5, 0xff, 0xfc, 0x09, 0xa9, 0xf1, 0x3f, 0x53, 0xa5, 0x01, 0xe8, 0xfd, 0x0c, 0x35, + 0x59, 0x82, 0x80, 0xad, 0x98, 0xba, 0x68, 0xfa, 0x46, 0x32, 0xff, 0x01, 0x75, 0x3b, 0x15, 0xdb, 0xc8, 0xf8, 0x39, + 0x51, 0x4d, 0x4b, 0x9e, 0xae, 0x8b, 0x34, 0x2e, 0x92, 0xfb, 0x88, 0x37, 0x53, 0x2c, 0x89, 0x55, 0x9a, 0x02, 0xfd, + 0xec, 0x77, 0xe1, 0xa7, 0xd2, 0x33, 0x01, 0xa7, 0x85, 0xbb, 0xad, 0x9c, 0xcd, 0x64, 0x18, 0x67, 0x64, 0xca, 0x25, + 0x62, 0xb7, 0xd1, 0xf7, 0xe8, 0x13, 0xfc, 0xc9, 0xd1, 0x13, 0x42, 0xef, 0xc4, 0xb4, 0x40, 0x50, 0xba, 0x22, 0x35, + 0xae, 0x9a, 0xd8, 0xaf, 0x29, 0x44, 0x71, 0xa8, 0x18, 0x84, 0xee, 0xd4, 0xed, 0x93, 0x7c, 0x9f, 0x29, 0xfb, 0x8d, + 0x2e, 0x5b, 0x90, 0x4d, 0x05, 0x1d, 0x13, 0xd6, 0xdb, 0xd3, 0xd9, 0xb3, 0x33, 0xe7, 0x37, 0x68, 0xc2, 0x41, 0x75, + 0x03, 0xed, 0x2a, 0xc9, 0x34, 0x46, 0xb1, 0x59, 0x8c, 0xb5, 0x1b, 0x13, 0x11, 0x04, 0x9d, 0x2e, 0x66, 0x61, 0xbb, + 0x9d, 0x10, 0x5f, 0x02, 0x09, 0x14, 0xb8, 0x72, 0x51, 0x4e, 0x42, 0x22, 0x2f, 0x64, 0x6a, 0xb2, 0x6e, 0x04, 0x0b, + 0xd4, 0x1a, 0x3b, 0x0a, 0xe8, 0x29, 0x37, 0x4f, 0x01, 0x7d, 0x5f, 0xb2, 0x53, 0x3e, 0x08, 0x86, 0x18, 0x5f, 0x35, + 0xa0, 0xb7, 0x42, 0x3e, 0x82, 0x87, 0x30, 0xb0, 0x5c, 0xf4, 0x65, 0xc9, 0x10, 0x56, 0xe8, 0xcf, 0x94, 0x4d, 0xbe, + 0xfe, 0xc6, 0xce, 0xef, 0xb5, 0x12, 0xb3, 0x83, 0x50, 0xdc, 0x5c, 0x4f, 0x80, 0xf8, 0xd5, 0xfc, 0x1a, 0xac, 0xab, + 0x95, 0xc4, 0xdb, 0x91, 0x3c, 0x54, 0xae, 0x1c, 0xdd, 0x7c, 0x52, 0xe9, 0x4f, 0x20, 0x48, 0x8d, 0x95, 0x94, 0xdb, + 0xef, 0x3e, 0x0a, 0x5b, 0x11, 0x8c, 0x16, 0x20, 0xd6, 0xed, 0xad, 0xe4, 0xc2, 0x17, 0xfe, 0x63, 0x9d, 0xef, 0x31, + 0x76, 0x88, 0x38, 0xc3, 0xe9, 0xf7, 0xc1, 0xb0, 0xbd, 0x5b, 0x99, 0x36, 0x24, 0xba, 0x96, 0x1f, 0x01, 0xfd, 0x1f, + 0xab, 0xf1, 0x3b, 0x45, 0x49, 0x5f, 0x12, 0xe7, 0x08, 0x57, 0xc4, 0x2b, 0x34, 0xd5, 0xeb, 0x8d, 0x1b, 0xfa, 0xa6, + 0xd4, 0x2f, 0x94, 0x82, 0xc3, 0xbc, 0xd5, 0x0a, 0x0f, 0x3c, 0xf3, 0xfe, 0xa8, 0x3c, 0x41, 0xf7, 0x6f, 0xb8, 0x37, + 0xfe, 0xa8, 0x58, 0x86, 0x37, 0xe5, 0x2c, 0xd3, 0x77, 0xb8, 0xdb, 0xac, 0x48, 0xc5, 0x2d, 0x63, 0xc1, 0xba, 0x90, + 0xe6, 0xab, 0x69, 0x30, 0xdb, 0x34, 0x91, 0x4c, 0xb6, 0xdf, 0xff, 0xe5, 0x9d, 0xb0, 0xd9, 0x20, 0x38, 0xab, 0x45, + 0x19, 0x5f, 0xf1, 0x60, 0xaa, 0x54, 0x14, 0x59, 0xd6, 0xef, 0x67, 0x80, 0x0c, 0x63, 0xb5, 0x77, 0xf0, 0x64, 0xa8, + 0x99, 0x0e, 0x71, 0x6d, 0x74, 0x16, 0xf0, 0x56, 0x8f, 0xe6, 0x69, 0x0d, 0xbb, 0xcc, 0x55, 0x52, 0xfc, 0xd1, 0x92, + 0x64, 0x63, 0xfd, 0x9e, 0x0c, 0xdb, 0xc8, 0x67, 0xae, 0x01, 0x63, 0xe6, 0x56, 0xc8, 0x20, 0x77, 0x3d, 0x60, 0x84, + 0x90, 0x08, 0x54, 0xd6, 0x62, 0xe2, 0xbc, 0xd2, 0xe1, 0x1f, 0x6d, 0x60, 0x9c, 0x18, 0x03, 0xe3, 0x7c, 0x14, 0x21, + 0xa7, 0xa7, 0x7c, 0x90, 0x78, 0xb3, 0xf5, 0x97, 0x2c, 0x91, 0xde, 0x08, 0x42, 0x2f, 0xe0, 0xf7, 0xb8, 0xc5, 0x03, + 0x79, 0xc1, 0x29, 0xed, 0xcd, 0xe9, 0xf0, 0x65, 0x49, 0x86, 0x7f, 0x82, 0x77, 0x57, 0x6c, 0x2e, 0xcb, 0x09, 0x2c, + 0xee, 0xd8, 0x29, 0x9e, 0xe6, 0xb2, 0xc5, 0x09, 0x71, 0x88, 0x45, 0xee, 0x12, 0x0b, 0x18, 0x51, 0xcd, 0x68, 0xfc, + 0x78, 0xf6, 0xf6, 0x8d, 0xc2, 0x6c, 0xca, 0xdd, 0x0f, 0x60, 0x44, 0x95, 0xb4, 0xdd, 0x0c, 0xf8, 0x72, 0x84, 0x06, + 0xdb, 0xa9, 0x1d, 0xec, 0x7e, 0x5f, 0xa7, 0x9d, 0x14, 0x4e, 0x36, 0x2b, 0x06, 0xdd, 0x51, 0xda, 0x2c, 0xa5, 0x41, + 0x6d, 0x57, 0xe1, 0x68, 0x3e, 0xab, 0xc5, 0xaa, 0xce, 0x87, 0xe1, 0x92, 0xc6, 0x46, 0x56, 0x6e, 0x76, 0x13, 0x8e, + 0x6c, 0x02, 0x5c, 0x9f, 0x84, 0xb2, 0xf2, 0xe7, 0xa0, 0x05, 0x9d, 0x09, 0x1c, 0xd1, 0x76, 0x1b, 0x42, 0x04, 0x8e, + 0x72, 0x38, 0x99, 0x85, 0xe5, 0x70, 0x28, 0x07, 0xbe, 0x24, 0x24, 0x7a, 0x53, 0xce, 0xb3, 0x85, 0x44, 0xec, 0x71, + 0x77, 0xd2, 0xaf, 0xa5, 0xe4, 0x94, 0x7b, 0x7f, 0x54, 0x64, 0xf3, 0x5b, 0x8a, 0x31, 0x07, 0xad, 0x66, 0x33, 0x03, + 0x09, 0xeb, 0x69, 0x4d, 0xe4, 0x3a, 0x32, 0xb3, 0x01, 0xaa, 0x58, 0x34, 0x85, 0x05, 0x75, 0x8b, 0x23, 0xd6, 0xd3, + 0x7a, 0x0f, 0x2a, 0x40, 0x54, 0x0b, 0x76, 0x63, 0xb8, 0xd6, 0x5e, 0x56, 0xa1, 0xa0, 0x9c, 0xf8, 0xcc, 0x8c, 0x11, + 0x0d, 0x96, 0x20, 0x24, 0x8d, 0xab, 0xfa, 0xb5, 0x48, 0xb3, 0xcb, 0x0c, 0x10, 0x13, 0xac, 0xff, 0x9c, 0xf0, 0xde, + 0x3c, 0x93, 0xf3, 0xd2, 0x95, 0x38, 0x33, 0x30, 0x1f, 0x5d, 0x6f, 0x69, 0x49, 0xa2, 0x12, 0x68, 0x94, 0xab, 0xe5, + 0xf9, 0xfb, 0x8e, 0x55, 0xc8, 0xee, 0x87, 0x53, 0x69, 0x3b, 0xc4, 0x4f, 0x58, 0x4d, 0x9c, 0xd3, 0xba, 0x96, 0x22, + 0x8d, 0x8e, 0xb6, 0x01, 0x31, 0x6c, 0xd9, 0xb7, 0xc8, 0xe1, 0x03, 0x83, 0x0a, 0x2b, 0xf9, 0x29, 0x70, 0xf8, 0x8c, + 0x81, 0xa4, 0xab, 0x45, 0x70, 0x35, 0x3a, 0xc2, 0x8a, 0x32, 0xb5, 0xc4, 0x14, 0x12, 0xdd, 0x7a, 0xa1, 0x35, 0x86, + 0x51, 0x76, 0x15, 0xf9, 0xdf, 0xab, 0xee, 0xfd, 0x51, 0x6d, 0xb7, 0x30, 0xc9, 0x8e, 0xc7, 0x15, 0x6c, 0x6a, 0xd4, + 0x0a, 0xe1, 0xec, 0x9c, 0xd6, 0xa8, 0x1d, 0xeb, 0x85, 0x05, 0x90, 0x07, 0xb0, 0x15, 0xf1, 0x28, 0x83, 0x60, 0x6f, + 0xca, 0x79, 0xb5, 0xb0, 0xa2, 0x1c, 0x21, 0xf1, 0xbe, 0xc4, 0x28, 0xe5, 0x70, 0x15, 0x0b, 0x4b, 0x86, 0xfc, 0xea, + 0xe8, 0xb2, 0x14, 0xd7, 0x20, 0x29, 0xd1, 0x0c, 0x95, 0xe1, 0x75, 0x71, 0xd5, 0x16, 0x84, 0xf6, 0x2e, 0x2a, 0x50, + 0x47, 0x82, 0xe0, 0xc5, 0xab, 0x21, 0x66, 0x1b, 0xb9, 0xbb, 0xa2, 0xbd, 0xe4, 0x80, 0x5a, 0xdd, 0xb5, 0x5d, 0x6f, + 0xd2, 0x36, 0xdb, 0x88, 0x0b, 0xff, 0x82, 0xd2, 0x4f, 0xf9, 0xa0, 0x74, 0xa9, 0x04, 0x6e, 0x7c, 0xb9, 0xc9, 0xb2, + 0xcb, 0x7b, 0x5c, 0xfa, 0xb5, 0x37, 0x7e, 0xfd, 0x7e, 0x4f, 0x2e, 0x04, 0x2f, 0x15, 0x98, 0x6f, 0x97, 0x99, 0xaa, + 0xb5, 0xa6, 0xd4, 0x5c, 0x82, 0x6b, 0x6b, 0x3f, 0x82, 0x8a, 0xb8, 0xae, 0xc8, 0x64, 0x72, 0x80, 0x0e, 0x9c, 0xac, + 0x70, 0x2b, 0x0b, 0xf0, 0xd8, 0x09, 0xc8, 0x76, 0xcb, 0xc3, 0x40, 0x1d, 0x3a, 0x81, 0xbb, 0x25, 0xcf, 0x90, 0x59, + 0x33, 0x8f, 0x3f, 0x2b, 0xc1, 0x3f, 0xb6, 0xe0, 0x27, 0x14, 0x77, 0x1a, 0x99, 0x7f, 0x2b, 0xad, 0x5b, 0xdc, 0xbf, + 0x93, 0x69, 0x42, 0x51, 0x99, 0xd0, 0xb8, 0x95, 0xfe, 0x4b, 0x07, 0x4b, 0x92, 0xd9, 0x3f, 0x08, 0xf8, 0x60, 0xe6, + 0x3d, 0x31, 0xef, 0x49, 0x73, 0xba, 0xb5, 0x82, 0x21, 0x40, 0xa1, 0x9f, 0x93, 0xb9, 0xa6, 0xea, 0xf9, 0xe7, 0x35, + 0x5f, 0x73, 0xbf, 0xc5, 0x26, 0xe9, 0x81, 0x06, 0x3b, 0x79, 0x14, 0xa5, 0xb0, 0x12, 0x75, 0xae, 0x25, 0xea, 0x55, + 0xc3, 0x32, 0x54, 0x27, 0x38, 0x35, 0x4f, 0xd5, 0xb0, 0xfb, 0x89, 0x68, 0xad, 0x24, 0x2d, 0x31, 0x60, 0xad, 0x23, + 0x0f, 0xc9, 0xed, 0x5a, 0xc7, 0x9d, 0x86, 0xba, 0x34, 0x89, 0x12, 0x60, 0x84, 0x0b, 0x70, 0x04, 0xfd, 0x54, 0x86, + 0x1c, 0xae, 0xa9, 0x52, 0xbf, 0xa0, 0x28, 0x79, 0xe2, 0x28, 0x6a, 0x95, 0x22, 0xdd, 0x7c, 0x94, 0x63, 0x37, 0x5c, + 0xe3, 0x84, 0x9c, 0x68, 0xa1, 0xbf, 0x3d, 0x96, 0x72, 0x86, 0x16, 0x0f, 0xf2, 0x04, 0xeb, 0xe5, 0x2d, 0x05, 0x8a, + 0x3e, 0xba, 0x8c, 0xba, 0xe6, 0x15, 0xda, 0xbe, 0x2c, 0xfb, 0xfd, 0xdc, 0xd4, 0x93, 0xb2, 0x93, 0xcd, 0x52, 0xef, + 0x43, 0x54, 0x4c, 0xe1, 0xae, 0x4f, 0x14, 0x7f, 0x15, 0xaa, 0xab, 0xb6, 0xc8, 0xf9, 0x88, 0x23, 0x2e, 0x46, 0x4e, + 0x9a, 0x9f, 0xe5, 0xd4, 0x4b, 0x71, 0xbf, 0xac, 0xe4, 0xd7, 0x4a, 0x5b, 0x31, 0x5a, 0xa0, 0xfe, 0x54, 0xaa, 0xbc, + 0x5f, 0x94, 0x00, 0xf7, 0x54, 0xb1, 0x37, 0x60, 0x5f, 0xa1, 0x10, 0x7e, 0x5b, 0x02, 0xfe, 0x8d, 0xe4, 0x06, 0x8c, + 0x02, 0x03, 0x8c, 0x26, 0xdb, 0x73, 0x9a, 0xc0, 0x01, 0x57, 0x29, 0x15, 0x05, 0xad, 0xf4, 0xd0, 0x50, 0x53, 0x18, + 0x3d, 0x43, 0x19, 0xb7, 0xcc, 0xec, 0xdc, 0x18, 0x3b, 0x2d, 0xf0, 0x3c, 0x7f, 0x3e, 0x27, 0xf4, 0xb0, 0x56, 0x07, + 0xa9, 0xd1, 0x49, 0x74, 0x7f, 0xec, 0xc2, 0xc9, 0xf5, 0xc2, 0x59, 0x36, 0x2c, 0x81, 0xee, 0xc0, 0x05, 0x31, 0xee, + 0xf7, 0x73, 0x38, 0x32, 0xf5, 0xc8, 0x97, 0x2c, 0xa7, 0x31, 0x5b, 0x52, 0xe5, 0x69, 0x77, 0x55, 0x87, 0x39, 0x5d, + 0x1a, 0x19, 0x6f, 0xca, 0x8a, 0x79, 0x0e, 0x1a, 0x49, 0xf8, 0xd3, 0x6d, 0xed, 0x92, 0xce, 0x97, 0x90, 0x01, 0xfe, + 0x80, 0x44, 0x14, 0xb1, 0xaf, 0xff, 0xad, 0xc6, 0x49, 0x3d, 0x51, 0xda, 0xb0, 0x84, 0xae, 0x99, 0xaa, 0x9f, 0x5e, + 0xb2, 0xb5, 0xb7, 0x14, 0xb6, 0xdb, 0xd0, 0x4f, 0x60, 0x8a, 0x73, 0x25, 0xd3, 0x4b, 0xd4, 0x49, 0x01, 0x15, 0x0b, + 0x2f, 0x71, 0xf9, 0xa5, 0x84, 0x42, 0x73, 0xe7, 0xcb, 0x85, 0x56, 0x62, 0x42, 0xab, 0xc4, 0xe7, 0x0f, 0x95, 0xfe, + 0x5a, 0x7b, 0xc4, 0xfd, 0x2b, 0x0d, 0x13, 0x5d, 0x24, 0x2a, 0x44, 0x67, 0xbf, 0x82, 0x2c, 0xa7, 0x02, 0x1c, 0xcb, + 0x33, 0xd1, 0xd0, 0x1f, 0x53, 0x88, 0x83, 0x0e, 0x0d, 0x7a, 0x57, 0x8a, 0xeb, 0xac, 0xe2, 0x21, 0xde, 0x13, 0x1c, + 0xcd, 0xe8, 0x7e, 0x83, 0x0f, 0x65, 0xed, 0xd1, 0xab, 0xc8, 0xc6, 0x51, 0xee, 0x37, 0xbf, 0x56, 0xe1, 0x1c, 0xa2, + 0x55, 0x2e, 0xa8, 0x52, 0x57, 0x5b, 0x00, 0x2a, 0xc7, 0xf6, 0xea, 0x11, 0x9c, 0x6e, 0xea, 0xfa, 0x56, 0x87, 0xd6, + 0x1c, 0x40, 0x98, 0x43, 0xb2, 0x69, 0xb8, 0xda, 0x01, 0xf6, 0x48, 0xac, 0xd7, 0x40, 0x63, 0xed, 0xd6, 0xec, 0xb4, + 0x47, 0x71, 0x98, 0xc8, 0x4c, 0x5b, 0xa4, 0x68, 0x73, 0xb7, 0x4e, 0x8b, 0xa2, 0x0d, 0x9a, 0x21, 0xec, 0xde, 0x75, + 0xf8, 0xba, 0x15, 0x61, 0x7d, 0xbf, 0xed, 0x0b, 0x8c, 0x86, 0x36, 0xd7, 0xee, 0x39, 0x86, 0x6e, 0xd8, 0x60, 0x13, + 0x39, 0x0f, 0x91, 0x0f, 0x33, 0x79, 0x20, 0x8a, 0xc6, 0x18, 0xb0, 0x3d, 0xe2, 0x6a, 0xd3, 0x4a, 0x7e, 0x5e, 0xc6, + 0x9c, 0xed, 0x19, 0xe3, 0x94, 0xd6, 0xd7, 0xb8, 0xe6, 0xb8, 0x2c, 0xa4, 0x6a, 0x8c, 0x67, 0x3c, 0x0c, 0x3b, 0x5f, + 0xe0, 0xce, 0xac, 0x31, 0x78, 0x11, 0x96, 0x4a, 0x76, 0x2a, 0x57, 0x9f, 0xc3, 0x16, 0x47, 0xb3, 0x31, 0xa7, 0xbf, + 0xff, 0x72, 0xc5, 0x17, 0xe8, 0xa6, 0x66, 0xfd, 0x08, 0x82, 0xac, 0x40, 0x87, 0x2c, 0xa9, 0x7a, 0xfc, 0xae, 0x04, + 0x6a, 0x0f, 0xf3, 0xf0, 0x5d, 0xc9, 0x8a, 0xf8, 0x26, 0xbb, 0x8a, 0x6b, 0x51, 0x8e, 0x6e, 0x78, 0x91, 0x8a, 0xd2, + 0x48, 0x8d, 0x83, 0xd3, 0xd5, 0x2a, 0xe7, 0x01, 0x98, 0xca, 0x1b, 0x46, 0xd9, 0x54, 0x96, 0xa9, 0xc1, 0x55, 0xf2, + 0xf4, 0x5a, 0x89, 0xce, 0xab, 0x9b, 0xab, 0x20, 0xc2, 0x5f, 0x17, 0xfa, 0xc7, 0x75, 0x5c, 0x7d, 0x0c, 0x22, 0x63, + 0x53, 0xa7, 0x7f, 0xa0, 0x54, 0x1e, 0xfc, 0xa7, 0x40, 0xa6, 0xfb, 0x5d, 0x09, 0x96, 0xd9, 0xa6, 0xe2, 0xe3, 0x18, + 0x6b, 0x1d, 0x4e, 0xc8, 0x4c, 0x96, 0xe8, 0xbc, 0x4b, 0xd6, 0x25, 0x58, 0xfb, 0x49, 0x2c, 0x63, 0x99, 0x6b, 0x86, + 0x95, 0xc9, 0x8a, 0xf4, 0xac, 0xac, 0xd9, 0x61, 0x68, 0x9c, 0x68, 0xe6, 0xe8, 0x2d, 0xa0, 0x1e, 0xc8, 0xe1, 0x15, + 0x2d, 0xd6, 0xcc, 0xf1, 0xb1, 0xf1, 0x5e, 0x3f, 0x3a, 0xbc, 0x72, 0x04, 0x4a, 0xe6, 0x4e, 0x8e, 0xc2, 0x44, 0xf0, + 0xac, 0xd5, 0xe3, 0x8b, 0x3c, 0x2b, 0x60, 0xe5, 0x4c, 0xc6, 0x63, 0xea, 0x2c, 0xad, 0xd6, 0xcd, 0xd1, 0x22, 0xb9, + 0x66, 0x8f, 0xeb, 0xc7, 0x9c, 0x1c, 0xf2, 0x96, 0xa9, 0x6d, 0xdb, 0x3a, 0xce, 0xd1, 0xe4, 0x4b, 0xd3, 0xfd, 0x6a, + 0x6d, 0x22, 0xa2, 0x4b, 0xe7, 0x3e, 0xeb, 0x15, 0xdc, 0xfa, 0xa6, 0xd0, 0xf4, 0x5a, 0x00, 0x10, 0x9d, 0x32, 0xe0, + 0x2f, 0x59, 0xb1, 0x1e, 0xd5, 0xbc, 0xaa, 0x41, 0xc2, 0x82, 0x22, 0xbc, 0x29, 0xf6, 0xa6, 0xb4, 0x37, 0x4e, 0xc7, + 0x61, 0x07, 0x2e, 0xa6, 0xe8, 0x8e, 0x03, 0x76, 0xfd, 0x5a, 0x2b, 0x1a, 0xa9, 0x5f, 0xb6, 0x2f, 0xb1, 0xea, 0x8b, + 0x52, 0xe6, 0x99, 0x9c, 0x12, 0x8b, 0xdd, 0x56, 0x2e, 0xac, 0xa8, 0xdf, 0x30, 0xe1, 0xd2, 0x95, 0x20, 0x20, 0xd3, + 0x92, 0xf5, 0x4a, 0xbd, 0x8b, 0xc4, 0x1a, 0x08, 0x19, 0x18, 0xbe, 0x06, 0xeb, 0xa2, 0xe2, 0xda, 0x0a, 0xd6, 0xb9, + 0xe7, 0xab, 0x84, 0x42, 0x14, 0x3c, 0xb0, 0x13, 0xf4, 0x43, 0xeb, 0xe6, 0x6d, 0x29, 0x51, 0x06, 0xf1, 0xb8, 0x95, + 0x53, 0x0e, 0x12, 0x08, 0xc0, 0x3d, 0x95, 0x21, 0x38, 0x24, 0xc8, 0x3a, 0xb8, 0x9a, 0x71, 0x04, 0x57, 0x97, 0xce, + 0x5c, 0x5c, 0x03, 0xac, 0x4b, 0x7f, 0x2e, 0x13, 0x5c, 0x58, 0x8d, 0xa8, 0x34, 0x67, 0x9c, 0x62, 0x10, 0x23, 0x43, + 0xd0, 0x57, 0x86, 0xd2, 0x5e, 0x81, 0xa6, 0xf1, 0x9a, 0xad, 0xa4, 0x0f, 0x00, 0xbd, 0x60, 0x2b, 0x69, 0xec, 0x8f, + 0x5f, 0x9f, 0xb3, 0x95, 0x92, 0x06, 0x4f, 0xaf, 0x67, 0x17, 0xb3, 0xf3, 0x01, 0x3b, 0x8a, 0x42, 0x65, 0xc0, 0x10, + 0x58, 0x24, 0xfe, 0x60, 0x10, 0x16, 0xb2, 0x11, 0x83, 0x42, 0x46, 0xc1, 0x72, 0x78, 0x6c, 0xc4, 0xcd, 0x0a, 0xc7, + 0xc3, 0x02, 0x43, 0x5e, 0x79, 0x2f, 0x48, 0x40, 0xa8, 0x2e, 0x0d, 0x5d, 0x1e, 0xc3, 0xe1, 0xe4, 0x60, 0x02, 0xa9, + 0x98, 0x99, 0xc9, 0xc2, 0xd8, 0x98, 0x44, 0x10, 0xef, 0xb4, 0xb3, 0x5e, 0x28, 0xb7, 0xbb, 0xc6, 0x42, 0x8d, 0xc3, + 0xe0, 0xb3, 0x2a, 0x9e, 0x1c, 0x0c, 0xbb, 0x2a, 0xc6, 0x51, 0xb8, 0xd1, 0xca, 0xb7, 0xf3, 0x63, 0x00, 0xaf, 0x3d, + 0x1f, 0xba, 0x72, 0x89, 0xf3, 0xc3, 0x27, 0xe4, 0xf1, 0x13, 0x42, 0xcf, 0xd9, 0xf9, 0x17, 0x4f, 0xe8, 0xb9, 0x24, + 0x27, 0x07, 0x93, 0xe8, 0x86, 0xe9, 0x06, 0x1c, 0x1e, 0xc9, 0x26, 0xd0, 0xab, 0xd1, 0xba, 0x90, 0x0b, 0x4c, 0x39, + 0x34, 0x85, 0xdf, 0x8e, 0x0f, 0x82, 0xc1, 0x4d, 0xbb, 0xe9, 0x37, 0xed, 0xb6, 0x3a, 0x5e, 0x5d, 0x07, 0x47, 0xd1, + 0x6e, 0x31, 0x93, 0x6f, 0xc6, 0x07, 0x76, 0x0e, 0xb0, 0xbe, 0x87, 0xc7, 0x44, 0x37, 0x69, 0x67, 0x54, 0xdc, 0x9a, + 0xbe, 0xc2, 0x3e, 0xf8, 0x45, 0x76, 0xf4, 0x61, 0xf8, 0x6f, 0x75, 0xa2, 0x39, 0xff, 0xe2, 0x08, 0xc8, 0x11, 0xc8, + 0x40, 0xb1, 0x44, 0x30, 0xc3, 0x81, 0xa6, 0x80, 0x82, 0x4c, 0x8d, 0x3b, 0x55, 0xc3, 0x2f, 0x47, 0x4d, 0xce, 0xc8, + 0x0d, 0x4c, 0x0d, 0xb6, 0x05, 0x3f, 0x90, 0xdd, 0x50, 0xdf, 0x28, 0x74, 0x23, 0xe5, 0x64, 0xa6, 0x5f, 0x52, 0xfd, + 0x83, 0xdd, 0x40, 0x00, 0x63, 0x0b, 0x2f, 0x28, 0xd8, 0x97, 0xc7, 0x57, 0x07, 0xb8, 0x8a, 0x00, 0x25, 0x8b, 0x05, + 0x5f, 0x0e, 0xae, 0xd4, 0xe6, 0x3e, 0x08, 0xc8, 0xe0, 0xcb, 0xe0, 0xe4, 0xcb, 0x81, 0x18, 0x04, 0xc7, 0x87, 0x57, + 0x27, 0x81, 0x35, 0xee, 0x87, 0x10, 0x8f, 0xb2, 0xa2, 0x98, 0x69, 0x34, 0x1f, 0xf4, 0x82, 0x92, 0x89, 0xb9, 0xa9, + 0x57, 0x1a, 0x9f, 0xd1, 0x74, 0x6a, 0x90, 0xbf, 0xc3, 0x94, 0xc5, 0xfa, 0x77, 0x30, 0xe1, 0xd7, 0x41, 0x64, 0x83, + 0xa0, 0xce, 0xf2, 0x28, 0xa6, 0x4b, 0x76, 0x5f, 0x85, 0x29, 0x4d, 0x0e, 0x73, 0x42, 0xa2, 0x70, 0x29, 0xc1, 0xf3, + 0xe4, 0xeb, 0x04, 0xe2, 0xb8, 0xda, 0xcf, 0x01, 0xd7, 0x8d, 0xe6, 0x87, 0x09, 0x69, 0x15, 0x61, 0x23, 0xb2, 0x6c, + 0x1a, 0x7a, 0xc9, 0xc2, 0x15, 0xbd, 0x02, 0x66, 0x4a, 0xac, 0xc3, 0x2b, 0xe0, 0xf2, 0xd6, 0xf3, 0xd5, 0x82, 0x5d, + 0x79, 0xd2, 0x37, 0xcd, 0x17, 0x5f, 0x1a, 0x9f, 0x3c, 0xe0, 0x21, 0xad, 0x1f, 0x5e, 0x0a, 0x36, 0x00, 0x37, 0x19, + 0xbf, 0xfd, 0x4e, 0xdc, 0xa9, 0x79, 0x69, 0x4f, 0x31, 0xce, 0x4c, 0x3b, 0x31, 0x69, 0x27, 0xe4, 0xee, 0x7d, 0x7b, + 0x13, 0xeb, 0x93, 0xbd, 0x8a, 0xd6, 0xd2, 0x65, 0xd5, 0x30, 0x24, 0xe5, 0x9a, 0x21, 0x7f, 0x8f, 0x92, 0x53, 0x23, + 0xf0, 0x64, 0x97, 0xbc, 0x4e, 0x96, 0xee, 0x41, 0x65, 0xac, 0x06, 0xcc, 0x31, 0x62, 0x58, 0x28, 0x1c, 0xfb, 0xd7, + 0x19, 0x2b, 0xd7, 0xae, 0x40, 0x23, 0x46, 0xee, 0xed, 0x75, 0xc6, 0x9c, 0x98, 0xab, 0xc9, 0xda, 0x09, 0x55, 0xe7, + 0xa4, 0xe7, 0x2d, 0xde, 0xcb, 0x2a, 0x35, 0xb4, 0x44, 0xf4, 0x60, 0x2c, 0xcd, 0x28, 0x65, 0xa2, 0xd2, 0xa0, 0x91, + 0x8a, 0x8d, 0x6d, 0xf0, 0x4b, 0x70, 0x42, 0xe5, 0x8e, 0x3a, 0xdb, 0xb5, 0x53, 0x2a, 0x1c, 0x60, 0x59, 0xaa, 0x55, + 0xe5, 0x76, 0x99, 0x09, 0x56, 0x0f, 0x82, 0xd1, 0x1f, 0x95, 0x28, 0x66, 0x78, 0x67, 0x64, 0xc1, 0x14, 0xac, 0x04, + 0x65, 0x2d, 0xc3, 0x62, 0xc8, 0x51, 0x8b, 0xa7, 0x7d, 0x52, 0x85, 0xfa, 0xd1, 0x11, 0x24, 0x77, 0xb9, 0x6e, 0x05, + 0xc9, 0x7d, 0x32, 0x7e, 0xa2, 0x06, 0x3a, 0x5d, 0x2b, 0xc7, 0x43, 0x97, 0xdf, 0x46, 0x7c, 0x6d, 0xd5, 0x7b, 0xaa, + 0xb4, 0x0a, 0x55, 0xa0, 0xc4, 0x8a, 0xd2, 0x95, 0x5a, 0xd0, 0xfd, 0x2e, 0x02, 0x60, 0x11, 0x1b, 0xb3, 0xf1, 0xae, + 0x6d, 0x56, 0x08, 0x1a, 0x5d, 0x76, 0xb2, 0x89, 0x07, 0x2c, 0x51, 0xad, 0x1d, 0x4c, 0x68, 0x7c, 0xc2, 0x8a, 0x7e, + 0x3f, 0x3f, 0x01, 0x7a, 0xaa, 0x8c, 0x98, 0x4a, 0x38, 0xf2, 0x3f, 0xb7, 0x22, 0x5d, 0x14, 0xd8, 0xac, 0xc9, 0xbb, + 0x35, 0x96, 0x91, 0xa8, 0xcb, 0x94, 0x2a, 0xaf, 0x72, 0x0c, 0x98, 0xd6, 0xeb, 0x96, 0xe3, 0xca, 0xae, 0xe2, 0xc8, + 0x51, 0x61, 0x19, 0x71, 0x5e, 0x8d, 0xe3, 0xad, 0xc6, 0x37, 0x38, 0xd4, 0x6c, 0xda, 0xa5, 0x3b, 0x84, 0xb0, 0x10, + 0x5e, 0x67, 0x70, 0x1b, 0x51, 0x76, 0x12, 0xa8, 0xbc, 0xd1, 0xd7, 0x09, 0x69, 0x73, 0xbb, 0x5e, 0x3b, 0x06, 0xe9, + 0x44, 0x1f, 0x28, 0xf5, 0x08, 0x5a, 0xa3, 0x58, 0x50, 0x39, 0xe2, 0x91, 0xe5, 0xe1, 0xad, 0x41, 0xac, 0x92, 0x2f, + 0x29, 0x2a, 0x45, 0x03, 0xf4, 0xbf, 0xe4, 0xb7, 0x07, 0xbf, 0xbc, 0xff, 0xe9, 0x8c, 0xc7, 0x65, 0xb2, 0x7c, 0x17, + 0x97, 0xf1, 0x75, 0x15, 0x6e, 0xe4, 0x18, 0xc5, 0x0d, 0x99, 0x56, 0x03, 0x26, 0xf4, 0x4a, 0xf2, 0x77, 0xa5, 0x22, + 0xc4, 0x58, 0x67, 0xb2, 0xae, 0x6a, 0x71, 0xed, 0x55, 0xba, 0x2e, 0x33, 0xfc, 0xb8, 0xe5, 0x73, 0x7a, 0x08, 0x40, + 0x9e, 0xda, 0x85, 0x34, 0x12, 0xaa, 0x10, 0x6d, 0x2e, 0xe2, 0x74, 0x7d, 0x3c, 0xf6, 0xba, 0x5e, 0xb0, 0xa7, 0xe3, + 0xaf, 0xa6, 0xaf, 0xb3, 0x30, 0x1b, 0x54, 0x64, 0x54, 0x2f, 0x79, 0xd1, 0x32, 0xe5, 0x94, 0x26, 0x01, 0xe8, 0xe3, + 0xd9, 0x63, 0xec, 0x68, 0x3c, 0x26, 0x9b, 0xb6, 0x78, 0x80, 0x87, 0xcb, 0x75, 0x58, 0x92, 0x99, 0xaa, 0x23, 0x0a, + 0x0a, 0x7e, 0x57, 0x07, 0x80, 0xe4, 0x68, 0xaa, 0xd2, 0x5c, 0x1a, 0x7b, 0x3a, 0x9e, 0x50, 0x81, 0xdd, 0x0e, 0x49, + 0xe3, 0x54, 0x68, 0x67, 0x5e, 0xb8, 0x1e, 0x45, 0x42, 0xbb, 0x2c, 0xed, 0x54, 0x2a, 0xe4, 0x9e, 0x99, 0xd9, 0xae, + 0x41, 0x0c, 0x86, 0x50, 0xd5, 0x5d, 0x38, 0x75, 0xef, 0x36, 0xd7, 0x98, 0xed, 0x80, 0xf7, 0x1a, 0x34, 0x43, 0xca, + 0x5b, 0xf4, 0x5b, 0x5b, 0x44, 0x43, 0x57, 0x6b, 0x30, 0x2b, 0x46, 0xd9, 0x52, 0x94, 0xae, 0x29, 0x28, 0x05, 0xa3, + 0xcb, 0xb5, 0xb3, 0x70, 0x5f, 0x0b, 0xef, 0xc2, 0x92, 0xa9, 0xd5, 0x22, 0xa5, 0x84, 0xf2, 0xa6, 0xa2, 0xa5, 0x84, + 0x91, 0xd4, 0xf0, 0xd4, 0xae, 0x17, 0x78, 0x9c, 0xe7, 0x41, 0xd4, 0xf2, 0x02, 0x3b, 0xad, 0xc9, 0x29, 0x38, 0x7a, + 0xe9, 0x9c, 0x9a, 0x02, 0xff, 0x98, 0x49, 0x10, 0xd3, 0xa1, 0xbc, 0xdf, 0xe0, 0xe6, 0xff, 0x47, 0xc9, 0x02, 0x87, + 0x6f, 0xbd, 0xc2, 0x6d, 0xf4, 0x8f, 0xd2, 0xa5, 0xa5, 0xcf, 0x84, 0xeb, 0xea, 0xe2, 0x48, 0x7b, 0xb3, 0x51, 0xb2, + 0xcc, 0xf2, 0xf4, 0x8d, 0x48, 0x79, 0x45, 0xa4, 0x09, 0x46, 0xc5, 0x4e, 0x2a, 0xef, 0x86, 0x07, 0x46, 0x8c, 0xde, + 0x8d, 0xef, 0xc7, 0x0c, 0x64, 0xc3, 0x60, 0xf5, 0xcd, 0x52, 0x91, 0xac, 0xaf, 0x01, 0x53, 0x44, 0xca, 0x4f, 0x5e, + 0xe4, 0x1c, 0x9e, 0x42, 0x75, 0xfd, 0x02, 0xb7, 0xb9, 0xca, 0xf5, 0x39, 0xff, 0x31, 0xa3, 0x3f, 0x22, 0xd0, 0x49, + 0xbc, 0x02, 0xb9, 0xc7, 0x33, 0xa8, 0x1b, 0x61, 0x6a, 0x39, 0x06, 0x07, 0x42, 0x34, 0x90, 0xa2, 0x66, 0x81, 0x84, + 0xba, 0xd0, 0xc0, 0x1a, 0xf2, 0x82, 0x39, 0xbc, 0xc8, 0x45, 0xf2, 0x71, 0xaa, 0x7d, 0xe6, 0x87, 0x31, 0xc6, 0x4c, + 0x0e, 0x06, 0x61, 0x3d, 0x0b, 0x86, 0xe3, 0xd1, 0xe4, 0xe8, 0x29, 0x9c, 0xdb, 0xc1, 0x38, 0x20, 0x83, 0xa0, 0xa9, + 0x56, 0x71, 0x41, 0xab, 0x9b, 0x2b, 0x53, 0x06, 0x7e, 0xdc, 0x04, 0x83, 0x7f, 0x94, 0x8e, 0xe2, 0x1d, 0x34, 0x27, + 0xe7, 0x22, 0x04, 0x1b, 0xfb, 0x35, 0x01, 0x49, 0x59, 0x4f, 0xf1, 0x93, 0xea, 0x70, 0x63, 0x52, 0xfb, 0xa7, 0x0f, + 0x2f, 0x38, 0xec, 0x90, 0x40, 0x81, 0x34, 0x9e, 0x66, 0xa3, 0x57, 0x52, 0x91, 0xfb, 0xae, 0xe4, 0x70, 0x67, 0xee, + 0x59, 0xd3, 0x23, 0xab, 0x90, 0xf0, 0xb3, 0x80, 0x1b, 0xf9, 0xab, 0xe2, 0x26, 0xce, 0xb3, 0xf4, 0xc0, 0x7f, 0x73, + 0x50, 0xdd, 0x17, 0x75, 0x7c, 0x37, 0x0a, 0xb4, 0x35, 0x21, 0x77, 0x55, 0x4f, 0x80, 0x9e, 0x00, 0x5b, 0x00, 0x0c, + 0x88, 0x77, 0xcc, 0x4c, 0x66, 0x3c, 0x02, 0x8f, 0x40, 0xdf, 0x07, 0xb2, 0xbc, 0xb7, 0x2e, 0x49, 0xee, 0x66, 0x2a, + 0xcc, 0x55, 0xaf, 0xd8, 0x29, 0xc8, 0x78, 0xb5, 0x15, 0xbb, 0x6e, 0x7d, 0xe6, 0x4d, 0x87, 0x57, 0xe0, 0x85, 0x00, + 0xb7, 0xc8, 0x7e, 0xdf, 0x17, 0x54, 0x56, 0x5a, 0x45, 0xbc, 0x93, 0xdc, 0xa0, 0x7f, 0xbb, 0x33, 0x36, 0x92, 0xe4, + 0x56, 0x0f, 0x0f, 0xa0, 0xca, 0xe4, 0x5c, 0x71, 0x3b, 0x87, 0xa8, 0xad, 0xbb, 0x71, 0xc0, 0x6a, 0x83, 0x76, 0x59, + 0x73, 0x04, 0x17, 0x5e, 0x1c, 0x64, 0x90, 0x13, 0x67, 0x65, 0x24, 0xd5, 0xb8, 0x9a, 0xd4, 0x82, 0x4f, 0xf2, 0x74, + 0x0f, 0x59, 0xea, 0x09, 0x50, 0xe4, 0x38, 0x16, 0x43, 0xba, 0xf1, 0x26, 0xf0, 0xf8, 0xbd, 0x08, 0x41, 0x9a, 0xb6, + 0xdd, 0xfa, 0x23, 0x50, 0x74, 0x0f, 0x4c, 0x41, 0x9a, 0x46, 0x9b, 0x1a, 0x28, 0xa8, 0x3d, 0xd4, 0x48, 0x45, 0x9c, + 0x9d, 0xbc, 0x06, 0x1d, 0x22, 0xf8, 0x7e, 0xa7, 0x59, 0xd5, 0xf1, 0x62, 0x42, 0xf0, 0xe4, 0x7d, 0x71, 0x97, 0x55, + 0x75, 0x15, 0xbd, 0x4f, 0xd1, 0x10, 0x2a, 0x11, 0x45, 0xf4, 0x12, 0xe2, 0xe9, 0x55, 0xf8, 0xbb, 0x8a, 0x7e, 0x4a, + 0x69, 0x9c, 0xa6, 0x98, 0xfe, 0xbc, 0x84, 0x9f, 0xcf, 0x00, 0xd5, 0x11, 0x77, 0x42, 0x74, 0x21, 0xc0, 0x5e, 0x0d, + 0xa2, 0x59, 0xd5, 0x1c, 0x30, 0x34, 0xa3, 0xfb, 0x8a, 0x22, 0x46, 0x1b, 0x66, 0xff, 0xa1, 0x44, 0xa1, 0x90, 0x2c, + 0xe6, 0xd7, 0xca, 0x3c, 0x44, 0x3f, 0x62, 0x91, 0xa7, 0xef, 0x5e, 0xe9, 0x21, 0x8d, 0xee, 0x05, 0x55, 0x5b, 0x1b, + 0x8f, 0x2d, 0x0c, 0x5c, 0x16, 0x5d, 0xad, 0xe9, 0x79, 0xbc, 0xca, 0xa2, 0x0d, 0xe0, 0x4f, 0xbc, 0x7b, 0xf5, 0x4c, + 0x5a, 0x98, 0x3c, 0xcf, 0x40, 0x71, 0x70, 0xfa, 0xee, 0xd5, 0x6b, 0x91, 0xae, 0x73, 0x1e, 0x9d, 0x0b, 0x24, 0xad, + 0xa7, 0xef, 0x5e, 0xfd, 0x8c, 0xe6, 0x5e, 0x3f, 0x95, 0xf0, 0xfe, 0x25, 0xf0, 0x96, 0x51, 0xbc, 0x86, 0x3e, 0xc9, + 0xdf, 0xc9, 0x1a, 0x3b, 0xe5, 0xd4, 0x5a, 0x45, 0xbf, 0xa4, 0x8d, 0x23, 0xad, 0xfa, 0x67, 0xe9, 0x52, 0x3b, 0x47, + 0xc0, 0x73, 0x97, 0x67, 0xc5, 0xc7, 0xc8, 0x88, 0x76, 0x82, 0xe8, 0xcb, 0x83, 0xbb, 0xeb, 0xbc, 0xa8, 0x22, 0x7c, + 0xc1, 0xd0, 0x2e, 0x28, 0x3a, 0x3c, 0xbc, 0xbd, 0xbd, 0x1d, 0xdd, 0x7e, 0x35, 0x12, 0xe5, 0xd5, 0xe1, 0xe4, 0xdb, + 0x6f, 0xbf, 0x3d, 0xc4, 0xb7, 0xc1, 0x97, 0x6d, 0xb7, 0xf7, 0x9a, 0xf0, 0x01, 0x0b, 0x10, 0xa1, 0xfa, 0x4b, 0xb8, + 0xa2, 0x80, 0x16, 0x6e, 0xf0, 0x65, 0xf0, 0xa5, 0x3a, 0x74, 0xbe, 0x3c, 0xae, 0x6e, 0xae, 0x64, 0xf9, 0x5d, 0x25, + 0x1f, 0x8d, 0xc7, 0xe3, 0x43, 0x90, 0x40, 0x7d, 0x39, 0xe0, 0x83, 0xe0, 0x24, 0x18, 0x64, 0x70, 0xa1, 0xa9, 0x6e, + 0xae, 0x4e, 0x02, 0xc7, 0x34, 0xd7, 0x63, 0x11, 0x2d, 0x88, 0x4b, 0x70, 0x78, 0x45, 0x83, 0x2f, 0x03, 0x62, 0x53, + 0xbe, 0x80, 0x94, 0x2f, 0x8e, 0x9e, 0xba, 0x69, 0xff, 0x4b, 0xa6, 0x7d, 0xe5, 0xa6, 0x1d, 0x63, 0xda, 0x57, 0xcf, + 0xdc, 0xb4, 0x13, 0x99, 0xf6, 0xc2, 0x4d, 0xfb, 0xdf, 0xd5, 0x00, 0x52, 0x0f, 0x5c, 0xeb, 0xbf, 0x0b, 0xa7, 0x35, + 0x78, 0x0a, 0x45, 0xd9, 0x75, 0x7c, 0xc5, 0xa1, 0xd1, 0x83, 0xbb, 0xeb, 0x9c, 0x06, 0x03, 0x6c, 0xaf, 0x63, 0xe4, + 0xe1, 0x7c, 0xf0, 0xe5, 0xba, 0xcc, 0xc3, 0xe0, 0xcb, 0x01, 0x16, 0x32, 0xf8, 0x32, 0x20, 0x5f, 0xaa, 0x23, 0xed, + 0xae, 0x62, 0x9b, 0xc0, 0x86, 0x22, 0x1d, 0x9a, 0x00, 0x61, 0xae, 0x34, 0xae, 0xa1, 0x7f, 0x96, 0xdd, 0xd9, 0xf0, + 0x96, 0x28, 0xdd, 0x74, 0x83, 0x86, 0xbe, 0x05, 0xef, 0x04, 0x68, 0x54, 0x14, 0xdc, 0xc4, 0x65, 0x38, 0x1c, 0x56, + 0x37, 0x57, 0x04, 0xec, 0x32, 0x57, 0x3c, 0xae, 0xa3, 0xa0, 0x10, 0x43, 0xf9, 0x33, 0x90, 0x91, 0xaf, 0x02, 0x04, + 0x44, 0x82, 0xff, 0x82, 0x86, 0xbe, 0x13, 0x6c, 0x13, 0x0c, 0x6f, 0xf9, 0xc5, 0xc7, 0xac, 0x1e, 0x4a, 0xd1, 0xe2, + 0x5d, 0x45, 0xe1, 0x07, 0xfc, 0xb5, 0x55, 0x47, 0x7f, 0x82, 0x1b, 0xb7, 0xaf, 0x61, 0x7f, 0x27, 0x2c, 0x8b, 0xfa, + 0x4e, 0xcc, 0xb3, 0xc5, 0xb4, 0x75, 0xa0, 0xbf, 0x15, 0xa4, 0x9e, 0x67, 0x83, 0x60, 0x18, 0x0c, 0xf8, 0x82, 0xbd, + 0x15, 0x73, 0xee, 0x98, 0x4f, 0x3d, 0x12, 0xee, 0x34, 0xcf, 0xb2, 0x01, 0xf8, 0xa6, 0x20, 0x3f, 0x72, 0xf8, 0xdf, + 0xf3, 0x21, 0x0a, 0x0f, 0x07, 0x8f, 0x0e, 0xc9, 0x2c, 0x58, 0xdd, 0xa1, 0x47, 0x67, 0x14, 0x64, 0xc5, 0x92, 0x97, + 0x59, 0xed, 0x2c, 0x95, 0xfb, 0x75, 0xdb, 0xcb, 0x63, 0xef, 0xd9, 0xbc, 0x8a, 0x8b, 0x40, 0x9e, 0x73, 0xa0, 0x78, + 0x43, 0xd9, 0x53, 0xe1, 0x4b, 0x48, 0x95, 0x21, 0x6f, 0x58, 0x0c, 0x58, 0x70, 0xdc, 0x1b, 0x0e, 0x0f, 0x82, 0x81, + 0x55, 0xe7, 0x0e, 0x82, 0x83, 0xe1, 0xf0, 0x24, 0xb0, 0xf7, 0xa1, 0x6c, 0x64, 0xef, 0x8c, 0xb4, 0x64, 0xff, 0x2c, + 0xc3, 0x82, 0x82, 0x78, 0x4c, 0x28, 0xf1, 0x97, 0x02, 0x97, 0x19, 0x00, 0xf4, 0x91, 0x94, 0x80, 0x69, 0x58, 0x99, + 0x01, 0x84, 0xe6, 0xa6, 0x31, 0x3b, 0x07, 0xe6, 0x91, 0x26, 0x20, 0xde, 0x03, 0x8a, 0x01, 0x88, 0x25, 0x01, 0xce, + 0x5d, 0x10, 0xc5, 0xaa, 0x90, 0x47, 0x00, 0x7a, 0x8f, 0x3f, 0x89, 0x2e, 0x05, 0x93, 0x54, 0xac, 0x42, 0x10, 0xc4, + 0xf1, 0xd9, 0x5d, 0xd5, 0x9a, 0x9c, 0x25, 0x3a, 0x98, 0x91, 0x04, 0xd8, 0x10, 0x0d, 0x3b, 0x07, 0xf7, 0x73, 0x50, + 0x7a, 0x18, 0xbd, 0x13, 0x72, 0xc1, 0xf7, 0xdc, 0xb2, 0x50, 0x77, 0x70, 0xf5, 0x84, 0x83, 0xe0, 0x9e, 0x2b, 0x16, + 0x60, 0x54, 0x97, 0xeb, 0xaa, 0xe6, 0xe9, 0x87, 0xfb, 0x15, 0xc4, 0xbe, 0xc3, 0x01, 0x7d, 0x27, 0xf2, 0x2c, 0xb9, + 0x0f, 0xad, 0x3d, 0xd7, 0x46, 0xa6, 0xff, 0xf0, 0xe1, 0xf5, 0x4f, 0x11, 0x88, 0x1c, 0x1b, 0x4d, 0xe9, 0xef, 0x39, + 0x9e, 0x4d, 0x6e, 0x84, 0x27, 0x77, 0x63, 0xdf, 0x73, 0x73, 0x7a, 0xf4, 0xfb, 0x50, 0x37, 0xbd, 0xe7, 0xb3, 0x7b, + 0x3e, 0xb2, 0xc5, 0xa1, 0xba, 0xc2, 0x7e, 0x7d, 0xbb, 0x76, 0x8d, 0x90, 0x1e, 0x9e, 0x67, 0xca, 0xbd, 0xf9, 0x51, + 0x0e, 0x86, 0x41, 0x30, 0x55, 0x42, 0x49, 0x88, 0xba, 0xc1, 0xa4, 0x80, 0x21, 0x3a, 0x50, 0xcb, 0x6a, 0x8a, 0x9c, + 0x9b, 0x1c, 0x59, 0x78, 0x3f, 0x60, 0x4a, 0xe8, 0xe0, 0xe5, 0x90, 0x7e, 0x70, 0x38, 0x61, 0xcc, 0xc0, 0x6f, 0x15, + 0x30, 0xfd, 0x72, 0x51, 0x59, 0x07, 0xd1, 0x03, 0x30, 0xc6, 0x2d, 0x78, 0x09, 0x5d, 0x61, 0x37, 0x6b, 0x19, 0x15, + 0x03, 0xc1, 0xe3, 0x90, 0x03, 0x74, 0xb0, 0x0b, 0x5a, 0x56, 0x96, 0xf2, 0x56, 0x65, 0x2d, 0x55, 0xe4, 0x65, 0x28, + 0xab, 0x62, 0x89, 0xf9, 0x5e, 0xb0, 0x1f, 0x4a, 0xf4, 0x2c, 0x9f, 0x56, 0x5d, 0xf0, 0x42, 0x28, 0xc1, 0xb2, 0x5d, + 0xef, 0x44, 0x20, 0xea, 0x4c, 0x75, 0xae, 0xfa, 0x0a, 0xc7, 0x8e, 0xa7, 0xaf, 0x45, 0xca, 0x95, 0x09, 0x85, 0xe2, + 0xf3, 0x85, 0xab, 0x98, 0x28, 0xd9, 0x2d, 0xf4, 0xab, 0x6d, 0xa3, 0xcf, 0xee, 0xd7, 0x6a, 0x33, 0x48, 0xd1, 0x31, + 0x6f, 0x50, 0x70, 0x2d, 0x15, 0x0a, 0x5a, 0x7b, 0x1b, 0x7f, 0x82, 0x23, 0x37, 0xba, 0x3d, 0xf4, 0x7e, 0xab, 0xe3, + 0xab, 0x37, 0xe8, 0xdb, 0x69, 0x7e, 0x8e, 0x6a, 0xf1, 0xcb, 0x6a, 0x05, 0x3e, 0x54, 0x10, 0x59, 0xc4, 0xe0, 0xd2, + 0x42, 0x3d, 0x67, 0xef, 0x4e, 0xdf, 0x80, 0x1f, 0x25, 0xfe, 0xfe, 0xf5, 0xfb, 0xa0, 0x21, 0xd3, 0x78, 0x56, 0xea, + 0x0f, 0x4d, 0x0e, 0x08, 0x4d, 0x62, 0xd3, 0xcc, 0xfb, 0x59, 0xec, 0xb3, 0xef, 0x8a, 0xad, 0xa7, 0xa5, 0x8f, 0x24, + 0xa5, 0xb9, 0x7d, 0x30, 0x20, 0x50, 0x07, 0x88, 0xe4, 0xec, 0x4b, 0x1a, 0x43, 0x9a, 0xcb, 0xec, 0xbb, 0x11, 0xf1, + 0x5e, 0xec, 0x84, 0x10, 0xe3, 0x12, 0x8b, 0x46, 0x0d, 0xf9, 0x8c, 0x47, 0xd2, 0xb0, 0xe8, 0x3d, 0x26, 0x10, 0x6b, + 0x38, 0x2d, 0xdf, 0x23, 0xe6, 0x31, 0xde, 0x0d, 0x94, 0xec, 0x21, 0xca, 0xa8, 0xcd, 0xee, 0x59, 0x7c, 0x7f, 0x5c, + 0x87, 0x99, 0xb1, 0xbc, 0x1c, 0xc2, 0xdf, 0x40, 0x19, 0x80, 0x53, 0x8e, 0x2c, 0x5f, 0xad, 0x37, 0xba, 0x5c, 0x62, + 0x6a, 0x13, 0x41, 0x2c, 0x1e, 0x95, 0x0e, 0x6b, 0x57, 0xa5, 0xaa, 0x5d, 0x6d, 0x7d, 0x26, 0x7a, 0x35, 0x68, 0xe5, + 0xda, 0xf6, 0x78, 0x08, 0x77, 0xa9, 0xa4, 0x15, 0x26, 0xb0, 0x5e, 0x65, 0x15, 0x2a, 0xd8, 0x9c, 0x80, 0x06, 0xd7, + 0x22, 0x05, 0xe0, 0x2c, 0xa5, 0x46, 0xa3, 0x5a, 0xd8, 0x67, 0xe4, 0x7c, 0x16, 0x5b, 0x0b, 0xf1, 0xb4, 0x00, 0x0c, + 0xd7, 0xc7, 0xa0, 0xe4, 0xdd, 0x18, 0x94, 0xd3, 0x8f, 0x12, 0xde, 0x3a, 0x38, 0xaf, 0x96, 0x71, 0x2a, 0x6e, 0x01, + 0x8b, 0x31, 0x70, 0x53, 0xb1, 0x54, 0x27, 0x21, 0x59, 0xf2, 0xe4, 0x23, 0x5a, 0x6d, 0xa4, 0x01, 0x70, 0x95, 0x53, + 0x6d, 0xb9, 0x27, 0x41, 0x42, 0x6d, 0x29, 0x32, 0x21, 0xae, 0xeb, 0x38, 0x59, 0x9e, 0x61, 0x6a, 0xb8, 0x81, 0x5e, + 0x44, 0x81, 0x58, 0xf1, 0x02, 0x48, 0x7a, 0xce, 0xfe, 0x95, 0x29, 0xac, 0xf1, 0x67, 0x02, 0x05, 0x4c, 0x0a, 0x35, + 0x18, 0x2b, 0x65, 0x2f, 0x84, 0x8e, 0xf6, 0x16, 0x04, 0x8d, 0x7d, 0xf9, 0x27, 0xd4, 0xfd, 0x0c, 0x5a, 0x11, 0x7a, + 0x60, 0x88, 0xe2, 0x02, 0x77, 0x68, 0x6a, 0x96, 0x9c, 0x03, 0x8c, 0x58, 0x18, 0xef, 0xb3, 0xc6, 0x6c, 0xf5, 0x67, + 0x4b, 0xc0, 0x36, 0x4d, 0xb5, 0x4f, 0x61, 0x98, 0x10, 0x1d, 0x1b, 0xd8, 0x28, 0x2b, 0xcd, 0x86, 0xd2, 0xed, 0xa4, + 0x4b, 0xe6, 0xb4, 0x70, 0x9a, 0xf7, 0x18, 0x5b, 0x8e, 0x64, 0xee, 0x7e, 0x3f, 0xd4, 0x3f, 0x59, 0x4e, 0x9f, 0xa9, + 0x90, 0xcd, 0xce, 0x78, 0xd0, 0x9c, 0x28, 0x75, 0x55, 0x47, 0x3f, 0xa0, 0x03, 0x30, 0xd3, 0x06, 0x20, 0xd3, 0x06, + 0x9b, 0x76, 0x95, 0xa8, 0xb8, 0x24, 0x61, 0xa9, 0x24, 0xb0, 0xb3, 0x7d, 0xc9, 0xce, 0x26, 0x20, 0x8e, 0xe1, 0xae, + 0xa3, 0xc5, 0x4e, 0x88, 0x0f, 0x6f, 0x71, 0x90, 0x80, 0xa8, 0x43, 0x56, 0x97, 0x90, 0x8d, 0x36, 0x74, 0x71, 0x2f, + 0x4a, 0x61, 0xc2, 0x5a, 0x26, 0x55, 0x89, 0x0e, 0x82, 0x54, 0xed, 0xb6, 0x08, 0x2c, 0x51, 0xb0, 0x03, 0xd8, 0x7b, + 0x3b, 0xea, 0x7a, 0xd4, 0x64, 0x75, 0xf2, 0x25, 0xf8, 0x38, 0xcd, 0xba, 0x0a, 0xd2, 0x0b, 0xbb, 0x2e, 0xd7, 0x3c, + 0x50, 0xb1, 0xa9, 0xa4, 0x31, 0x71, 0x97, 0x16, 0x19, 0xe2, 0x01, 0x63, 0x2c, 0x5d, 0x08, 0xe4, 0x9b, 0xed, 0x8e, + 0x9b, 0x9a, 0x20, 0xf4, 0x13, 0xd6, 0x94, 0xc0, 0x4e, 0x67, 0x7b, 0x6a, 0xfc, 0x7c, 0x40, 0xc4, 0x61, 0x40, 0x81, + 0x64, 0xe3, 0x90, 0xe6, 0x48, 0x5f, 0x90, 0x34, 0x61, 0x60, 0x68, 0xc9, 0x73, 0x82, 0xac, 0x28, 0x74, 0x6c, 0x5d, + 0x95, 0x71, 0xae, 0x08, 0x73, 0xb4, 0xe4, 0x94, 0xf8, 0x9c, 0x20, 0x13, 0xdb, 0xd3, 0x36, 0x3d, 0x19, 0x96, 0x92, + 0x05, 0xfa, 0x57, 0x10, 0x25, 0xf6, 0x4c, 0x33, 0x2a, 0x07, 0xed, 0x02, 0x16, 0x28, 0xe5, 0x7b, 0xd0, 0x78, 0x6b, + 0x68, 0xa3, 0x60, 0x88, 0xed, 0xfe, 0x04, 0xfb, 0xb5, 0x76, 0x5a, 0x97, 0x29, 0x96, 0x93, 0x29, 0x44, 0x7b, 0x21, + 0xfd, 0x1b, 0x45, 0xa2, 0x3b, 0x45, 0x68, 0x12, 0xd6, 0x51, 0xf6, 0xa4, 0x4d, 0x0d, 0xa0, 0xa7, 0x4e, 0xc0, 0xf3, + 0xce, 0xb5, 0x0c, 0xbb, 0x48, 0xf5, 0x57, 0x06, 0x9f, 0x52, 0x0d, 0x82, 0x14, 0xb5, 0x49, 0xc1, 0x9c, 0xd7, 0xa1, + 0xa4, 0xce, 0x9c, 0xb6, 0xcc, 0xa8, 0x3a, 0x2a, 0x42, 0xca, 0x09, 0xfe, 0x93, 0x57, 0x42, 0x11, 0x9b, 0x30, 0xc1, + 0x03, 0x1f, 0xe6, 0x19, 0x36, 0xf0, 0x76, 0xfb, 0x2e, 0x0d, 0x93, 0x36, 0xdb, 0x90, 0x82, 0xb4, 0x42, 0xc7, 0xc5, + 0x80, 0xca, 0x5e, 0xe1, 0x7e, 0xc1, 0x76, 0xd2, 0x14, 0x3c, 0x08, 0xbd, 0x06, 0x26, 0x76, 0x75, 0xf1, 0x75, 0x98, + 0xd0, 0x70, 0x49, 0x95, 0xb3, 0x93, 0x92, 0x34, 0xb7, 0xd7, 0xe5, 0xa5, 0xe9, 0x83, 0x8a, 0x1d, 0xd6, 0x35, 0x3c, + 0xd0, 0x3c, 0xbf, 0x8b, 0x2b, 0xa6, 0x68, 0xa2, 0xb6, 0x1e, 0x92, 0x96, 0x1c, 0xeb, 0x66, 0xba, 0xc2, 0xd5, 0x32, + 0x53, 0xc0, 0xee, 0x02, 0x2f, 0xf4, 0x80, 0x87, 0x1d, 0xae, 0x48, 0x74, 0x89, 0xcd, 0x66, 0xab, 0x86, 0x4c, 0xf3, + 0x7d, 0xd9, 0x72, 0x1d, 0x10, 0xce, 0x50, 0xdf, 0xdc, 0x25, 0xc7, 0x8a, 0xb6, 0xb9, 0x49, 0x80, 0xe3, 0xed, 0x14, + 0x90, 0x74, 0x2c, 0x41, 0x1b, 0xdf, 0xd2, 0x1d, 0x44, 0xaa, 0xa7, 0x82, 0xee, 0x9d, 0x2f, 0xd2, 0xf8, 0x5f, 0x80, + 0x6d, 0xd4, 0x46, 0x9b, 0x66, 0x65, 0xeb, 0x30, 0x91, 0x16, 0xd6, 0xc8, 0x42, 0x2e, 0xc1, 0x07, 0x73, 0xb7, 0xa9, + 0xd3, 0xd3, 0x0e, 0x22, 0xec, 0x76, 0xd1, 0xe1, 0x11, 0xc6, 0x92, 0x35, 0x48, 0x34, 0xab, 0xb0, 0xa6, 0xfe, 0x72, + 0x88, 0x72, 0xaa, 0x97, 0x4c, 0xb4, 0xa4, 0x2e, 0xa5, 0x88, 0x52, 0x30, 0x37, 0x9e, 0x16, 0x9e, 0x29, 0x21, 0x42, + 0x56, 0x08, 0x0b, 0x54, 0x6b, 0xa0, 0xa5, 0x7c, 0xd0, 0xeb, 0xd0, 0xc9, 0x42, 0x63, 0x0a, 0xa2, 0x8f, 0x48, 0x73, + 0x23, 0x96, 0x8c, 0xee, 0x8e, 0x51, 0x4c, 0x20, 0x54, 0xb5, 0x93, 0x17, 0x56, 0x9f, 0x92, 0x6d, 0x75, 0x10, 0xd7, + 0x98, 0x26, 0x7b, 0x08, 0x6a, 0x8c, 0x82, 0x36, 0xab, 0x1b, 0xfd, 0xa5, 0x0c, 0x5d, 0xbb, 0x70, 0xec, 0x46, 0x49, + 0x04, 0x44, 0x60, 0x75, 0x9a, 0x8a, 0x01, 0x59, 0xe7, 0xb1, 0x8d, 0xd0, 0xa4, 0xba, 0x85, 0x28, 0x6f, 0x54, 0x34, + 0x1f, 0xd7, 0x21, 0xd9, 0x6e, 0xb1, 0x2c, 0xf0, 0x65, 0x3f, 0x5b, 0xef, 0x81, 0xfc, 0x7e, 0xbd, 0xfe, 0x24, 0xe4, + 0xf7, 0xab, 0xec, 0x73, 0x20, 0xbf, 0x5f, 0xaf, 0xff, 0xa7, 0x21, 0xbf, 0xcf, 0xd6, 0x0e, 0xe4, 0xb7, 0x1c, 0x8c, + 0xdf, 0x4a, 0x16, 0xbc, 0x7d, 0x13, 0xd0, 0xe7, 0x82, 0x05, 0x6f, 0x5f, 0xbe, 0x74, 0x84, 0xe9, 0xdf, 0xe9, 0x38, + 0x2f, 0x5a, 0x16, 0x8c, 0xb8, 0x2d, 0xf0, 0x0a, 0xb5, 0x4e, 0x2e, 0x50, 0x51, 0x06, 0xc0, 0xeb, 0xd5, 0x3f, 0xb2, + 0x7a, 0x19, 0x06, 0x87, 0x01, 0x99, 0x59, 0x48, 0xd0, 0xe1, 0x04, 0x6e, 0x6f, 0x68, 0x64, 0x59, 0x7f, 0x16, 0x7c, + 0xf8, 0x68, 0x34, 0x8a, 0xcb, 0x2b, 0xbc, 0xd4, 0xe9, 0x8d, 0x84, 0x80, 0xc7, 0x19, 0xaf, 0x4c, 0x88, 0x88, 0x65, + 0x5c, 0x9d, 0xab, 0xd8, 0x2c, 0x95, 0xd9, 0x8a, 0x10, 0x71, 0xfe, 0x1c, 0x70, 0xea, 0xcd, 0xde, 0x8c, 0xb1, 0x1f, + 0x92, 0x23, 0x56, 0x01, 0x64, 0x9f, 0xad, 0xd5, 0xbb, 0x8b, 0xb8, 0xe2, 0xef, 0xe2, 0x7a, 0xc9, 0xa0, 0x97, 0x70, + 0x17, 0x29, 0x78, 0x52, 0x3b, 0x6c, 0x93, 0x04, 0x2a, 0xcf, 0x14, 0x50, 0x79, 0xc7, 0x7b, 0x1a, 0x9a, 0x61, 0x51, + 0x3e, 0xc0, 0x5a, 0xba, 0x9c, 0x81, 0xd1, 0xe2, 0x8b, 0x1b, 0x5e, 0xd4, 0x3f, 0x01, 0x9e, 0x7a, 0xc1, 0x4b, 0xb8, + 0x25, 0x20, 0x17, 0xeb, 0x39, 0x21, 0xd0, 0xca, 0xf5, 0xec, 0x90, 0x51, 0x63, 0xb4, 0x68, 0xc2, 0xeb, 0x37, 0xde, + 0x84, 0xd0, 0xbb, 0x13, 0x74, 0x45, 0x18, 0x09, 0xef, 0xcf, 0x35, 0x3f, 0xcf, 0xc0, 0x7c, 0xbe, 0x02, 0x28, 0x0d, + 0x84, 0x43, 0x65, 0x52, 0x6e, 0x81, 0x09, 0x1b, 0x6d, 0xae, 0x94, 0xa5, 0x0e, 0x52, 0x29, 0x95, 0x70, 0xba, 0x15, + 0x4d, 0x05, 0xe0, 0x70, 0x47, 0x02, 0xc0, 0x4c, 0x4d, 0x61, 0x10, 0xdd, 0x36, 0xa5, 0x59, 0x1a, 0x59, 0x45, 0x9a, + 0xc5, 0x27, 0xa5, 0x12, 0x74, 0xfa, 0x3c, 0x89, 0x6b, 0x7e, 0x25, 0x4a, 0x08, 0x85, 0xdb, 0x4a, 0x69, 0x0c, 0x16, + 0x80, 0x3c, 0xee, 0xac, 0xcd, 0xd6, 0xac, 0x94, 0x29, 0xe7, 0xc5, 0xfa, 0x9a, 0x97, 0x59, 0x72, 0xbe, 0xcc, 0xaa, + 0x5a, 0x94, 0xf7, 0x6c, 0xae, 0xb2, 0x2e, 0xa2, 0x6a, 0xa4, 0x24, 0x5e, 0xe7, 0x35, 0xbf, 0x5e, 0x41, 0xe8, 0x87, + 0x75, 0x09, 0xac, 0xe7, 0xde, 0x2f, 0x65, 0x64, 0xd2, 0xb0, 0xf3, 0x3b, 0xb2, 0x00, 0xbd, 0x2b, 0xac, 0x11, 0xb9, + 0x00, 0x98, 0x5e, 0x33, 0xa7, 0x92, 0xaa, 0x94, 0xfe, 0x6b, 0x8d, 0x33, 0xef, 0x2f, 0xaa, 0x71, 0x6b, 0xed, 0x19, + 0xad, 0xad, 0x9f, 0x2a, 0xe1, 0x94, 0x80, 0x12, 0xb1, 0x13, 0x5c, 0x31, 0x29, 0x5d, 0x1b, 0xb4, 0x16, 0xb0, 0xac, + 0xc0, 0x1c, 0x59, 0x71, 0x75, 0x7e, 0x2b, 0x65, 0x35, 0x3d, 0x49, 0xcd, 0xd2, 0x28, 0x96, 0x28, 0x42, 0x4b, 0x16, + 0xae, 0x59, 0xb2, 0x27, 0xd7, 0x3a, 0x4a, 0x3c, 0x3c, 0xb0, 0xb8, 0x3d, 0xe8, 0xc7, 0x49, 0x3b, 0x65, 0xbb, 0xdd, + 0xc9, 0x04, 0x6c, 0x48, 0x2b, 0x09, 0x22, 0x83, 0x2c, 0x67, 0xc3, 0x49, 0x04, 0x70, 0x2d, 0x8a, 0x84, 0xfe, 0xb9, + 0xe6, 0x1a, 0xd0, 0x3e, 0x54, 0x5e, 0x85, 0x72, 0x15, 0xcd, 0xc1, 0xce, 0xcb, 0xed, 0x35, 0x04, 0x96, 0xe9, 0x9c, + 0x97, 0xc5, 0xfe, 0x35, 0xa0, 0xcc, 0x91, 0xd5, 0x0b, 0xb2, 0x6f, 0xc6, 0x55, 0xb6, 0x07, 0xa7, 0xb7, 0x35, 0x07, + 0x7b, 0x5b, 0xa3, 0x50, 0x7a, 0x13, 0x1e, 0x0e, 0x9f, 0x8e, 0x8d, 0x3f, 0x03, 0xae, 0x72, 0xf3, 0x5b, 0xee, 0x04, + 0xfb, 0x6c, 0x76, 0x03, 0xf5, 0x5d, 0x22, 0xda, 0x35, 0xd2, 0x6a, 0xcf, 0xb8, 0x35, 0xa4, 0xb1, 0x2b, 0xcd, 0x88, + 0xb9, 0x7e, 0x97, 0x47, 0xeb, 0xf9, 0xa3, 0x4d, 0xa6, 0xaa, 0x6c, 0x7e, 0xcf, 0x4c, 0x50, 0x3c, 0x8f, 0x4c, 0x35, + 0x6a, 0x0d, 0xba, 0x98, 0x74, 0x1d, 0xd9, 0xd4, 0x8c, 0xb2, 0xac, 0x93, 0xd6, 0x8d, 0xe4, 0x23, 0x97, 0x31, 0xc2, + 0xba, 0xb3, 0xf0, 0x3b, 0x9e, 0x84, 0x5d, 0x0d, 0x93, 0xd7, 0x10, 0xdd, 0x05, 0x84, 0xe9, 0x04, 0xe5, 0x43, 0xf8, + 0xfb, 0xa3, 0x8d, 0x4f, 0x3b, 0x9b, 0x43, 0xe7, 0x33, 0xfc, 0x9d, 0xa5, 0xf0, 0xb7, 0x6e, 0x7e, 0xa7, 0x9b, 0x6b, + 0x5e, 0x2f, 0x45, 0x1a, 0x05, 0xef, 0xde, 0x9e, 0x7d, 0x08, 0x14, 0xfc, 0x3b, 0x5e, 0x82, 0xb4, 0xda, 0x5b, 0x03, + 0x4d, 0x81, 0x1a, 0x28, 0x17, 0x57, 0x88, 0x80, 0xa8, 0x20, 0xf4, 0xcf, 0x96, 0xe2, 0xf6, 0x34, 0xcf, 0x5d, 0x4e, + 0x5d, 0x53, 0x77, 0xc5, 0xbc, 0x7a, 0xa4, 0x31, 0x04, 0x81, 0xe3, 0x28, 0xab, 0xce, 0x95, 0x8a, 0x28, 0x3d, 0xbf, + 0xb8, 0x3f, 0x57, 0x62, 0x28, 0x03, 0x41, 0xf9, 0xec, 0xf7, 0xe3, 0x34, 0xbb, 0x39, 0xc0, 0x23, 0x88, 0x05, 0x60, + 0xbf, 0x9f, 0xf3, 0x8b, 0x75, 0x5d, 0x8b, 0x62, 0x58, 0x8a, 0xdb, 0xe0, 0xe4, 0x58, 0x3e, 0xe8, 0x0c, 0xb1, 0x7c, + 0x0c, 0x0e, 0xfe, 0x2b, 0xc9, 0xb3, 0xe4, 0x23, 0x0b, 0x1e, 0x6d, 0x32, 0x76, 0xd2, 0x3a, 0x68, 0xc6, 0x4d, 0x70, + 0x02, 0x6d, 0x3d, 0x38, 0xcd, 0xf3, 0xe3, 0x43, 0xf9, 0xc5, 0xc9, 0xf1, 0x61, 0x9a, 0xdd, 0x9c, 0x38, 0xd1, 0x00, + 0xac, 0x71, 0x2f, 0xe2, 0xae, 0xd9, 0xcb, 0x3b, 0x78, 0xf1, 0x26, 0x3c, 0x34, 0xec, 0x0e, 0x88, 0x8c, 0x74, 0x2c, + 0x15, 0x14, 0x33, 0x85, 0x31, 0x1c, 0xee, 0xdb, 0x6d, 0x68, 0x2c, 0x8f, 0x12, 0x07, 0x96, 0xa7, 0x04, 0x76, 0x08, + 0xb3, 0xd0, 0x84, 0xd0, 0xa4, 0x21, 0xa1, 0x06, 0x0f, 0x8a, 0x09, 0x2d, 0x1b, 0x0a, 0xe7, 0xdd, 0xeb, 0x78, 0xa5, + 0x25, 0x6d, 0x4a, 0x72, 0xa1, 0x5b, 0x3f, 0xf3, 0xc6, 0x31, 0x6a, 0x8f, 0xaa, 0x86, 0xf3, 0xea, 0x15, 0xfb, 0x06, + 0x16, 0x84, 0xab, 0x61, 0x4d, 0x83, 0x16, 0x69, 0x01, 0xe1, 0xa8, 0x2b, 0xd3, 0xe3, 0x34, 0x9c, 0x17, 0x54, 0x2c, + 0x08, 0x3b, 0x09, 0x37, 0xc8, 0xdb, 0x17, 0x54, 0xb2, 0xfa, 0xa2, 0xb1, 0xd8, 0x9a, 0x72, 0x76, 0x4e, 0x1e, 0x6d, + 0x64, 0xcc, 0xde, 0x82, 0x9d, 0xf8, 0xf3, 0x55, 0xc7, 0x17, 0xc3, 0x25, 0x07, 0x27, 0xa0, 0xe0, 0xe0, 0xbf, 0xd2, + 0x8b, 0xdc, 0x4c, 0x8a, 0x5c, 0x91, 0xcb, 0xb8, 0x48, 0x73, 0xfe, 0x21, 0xbe, 0xf8, 0x01, 0xf3, 0x3c, 0xbf, 0xc8, + 0x9f, 0x41, 0x86, 0x26, 0x38, 0x79, 0xb4, 0x49, 0xea, 0xd1, 0x8b, 0x37, 0x1f, 0x5e, 0x7d, 0xf8, 0xe7, 0xf9, 0xb3, + 0xd3, 0x0f, 0x2f, 0xbe, 0x7f, 0xfb, 0xfe, 0xd5, 0x8b, 0xb3, 0xb9, 0xf1, 0xba, 0x95, 0x60, 0x6e, 0x64, 0xb1, 0xdd, + 0xda, 0x7c, 0xbf, 0xbc, 0x79, 0xfe, 0xe2, 0xe5, 0xab, 0x37, 0x2f, 0x9e, 0x37, 0x72, 0x2e, 0xdb, 0x0d, 0x81, 0x1d, + 0x1a, 0x67, 0x05, 0x2f, 0xa1, 0x78, 0x75, 0xbb, 0xc3, 0x66, 0x2b, 0x0c, 0x42, 0xbf, 0xe9, 0x2a, 0x5c, 0x03, 0x2c, + 0xb2, 0x03, 0xb5, 0x59, 0xa0, 0xe1, 0x42, 0x6f, 0x1c, 0x77, 0x89, 0xb9, 0xbd, 0x79, 0x81, 0xdf, 0xbd, 0x17, 0xb7, + 0xba, 0x2b, 0x6a, 0x84, 0x24, 0xbc, 0xd8, 0xec, 0xd9, 0xef, 0xc7, 0xae, 0x48, 0x0f, 0xe5, 0x1e, 0xb2, 0x5c, 0xf8, + 0xd5, 0x04, 0x07, 0xca, 0xbc, 0x30, 0x80, 0xe8, 0x18, 0xc1, 0xc9, 0xf1, 0xa1, 0x9b, 0xfb, 0xe4, 0xf7, 0xe8, 0x27, + 0xa7, 0x73, 0x58, 0x2a, 0x8c, 0x83, 0x9f, 0xb6, 0x73, 0x2c, 0x02, 0x7d, 0xb6, 0x07, 0xa7, 0x5c, 0x41, 0x9a, 0x5c, + 0x09, 0x12, 0x99, 0x49, 0x94, 0x66, 0x33, 0xba, 0xb4, 0xdf, 0xd5, 0x5f, 0xdb, 0x67, 0x14, 0x43, 0xf0, 0xa2, 0x12, + 0x25, 0xd8, 0xb8, 0x38, 0x89, 0x49, 0x0e, 0x82, 0x0f, 0x1e, 0x40, 0xef, 0xda, 0xa1, 0x2e, 0x0e, 0x9c, 0x90, 0x32, + 0xd8, 0xcf, 0x4e, 0xa2, 0x0f, 0xe3, 0x74, 0xd8, 0xfe, 0xd4, 0xe9, 0xee, 0xef, 0xc4, 0xfe, 0x38, 0x50, 0x5d, 0x6c, + 0x11, 0x1d, 0xd3, 0xec, 0xfd, 0x21, 0x49, 0xe6, 0x6f, 0xff, 0x4f, 0x73, 0x4f, 0xbb, 0xdd, 0xb6, 0x71, 0xe5, 0xff, + 0x3e, 0x05, 0x0c, 0xbb, 0x0e, 0x60, 0x03, 0x10, 0x40, 0x8a, 0x92, 0x4c, 0x8a, 0x52, 0x13, 0xdb, 0x39, 0x51, 0xaa, + 0xd4, 0x39, 0x8e, 0xea, 0x6d, 0xa3, 0xe8, 0x98, 0x43, 0x70, 0x48, 0xa2, 0x02, 0x01, 0x1e, 0x00, 0x94, 0xa8, 0xd0, + 0xe8, 0x53, 0xec, 0xff, 0xed, 0x73, 0xec, 0xfe, 0xeb, 0x13, 0xed, 0x23, 0xec, 0xb9, 0x77, 0x3e, 0x30, 0xf8, 0x22, + 0xa9, 0xc4, 0x69, 0xf7, 0xa4, 0xaa, 0x89, 0xc1, 0xcc, 0x60, 0xe6, 0xce, 0xcc, 0x9d, 0xfb, 0x7d, 0x03, 0xeb, 0x3f, + 0x62, 0x6b, 0x46, 0xac, 0x05, 0xb1, 0x6e, 0xd3, 0x9b, 0xbc, 0x71, 0xcd, 0x64, 0xba, 0x1b, 0x4c, 0x89, 0x68, 0x18, + 0x10, 0x37, 0x83, 0x73, 0x33, 0x9c, 0xc6, 0x0f, 0xc4, 0x05, 0x77, 0x45, 0x92, 0x19, 0x15, 0x89, 0x66, 0xc4, 0xdb, + 0x8c, 0x43, 0xc6, 0x2c, 0xc1, 0xcb, 0x30, 0xe8, 0xe3, 0xba, 0xa1, 0x6a, 0x37, 0x02, 0xc2, 0x18, 0x43, 0xf3, 0x09, + 0xb7, 0xac, 0x08, 0x1c, 0x3f, 0x4b, 0xc2, 0x3f, 0xd2, 0x07, 0x20, 0x5e, 0xd3, 0x2c, 0x5e, 0x02, 0xcb, 0x42, 0x66, + 0x5c, 0x04, 0x65, 0x19, 0xe9, 0x7e, 0x1f, 0x84, 0x64, 0x59, 0xb8, 0xe9, 0x81, 0xee, 0x75, 0xb2, 0x78, 0x36, 0x0b, + 0xa9, 0xa1, 0x8b, 0x1c, 0x2a, 0xba, 0x25, 0x3f, 0x73, 0xfe, 0xc4, 0x15, 0x81, 0x4b, 0xcd, 0xbc, 0xed, 0xf0, 0x0a, + 0xe8, 0x51, 0x19, 0xd9, 0x8f, 0x11, 0xf0, 0x28, 0xa2, 0xbe, 0x43, 0x2d, 0x0f, 0x5f, 0xe3, 0x02, 0x39, 0xd8, 0x93, + 0x78, 0x35, 0x0e, 0xa9, 0x8d, 0x07, 0x0a, 0x3e, 0xb9, 0x19, 0xaf, 0xc6, 0x63, 0x48, 0x56, 0xf3, 0xc4, 0xb5, 0x20, + 0xfc, 0x4e, 0x9c, 0x22, 0x5b, 0x9c, 0x9b, 0x03, 0x80, 0xa2, 0x93, 0x95, 0x87, 0xcf, 0xb2, 0x77, 0x82, 0xc4, 0x8b, + 0x7d, 0x20, 0x03, 0x16, 0xb8, 0x01, 0x2f, 0x0c, 0xf5, 0x1f, 0x60, 0x7f, 0xa7, 0xfa, 0xa0, 0x09, 0xb9, 0x0c, 0xaf, + 0xf5, 0x1f, 0x70, 0xb1, 0x30, 0x89, 0xf3, 0x6b, 0x76, 0x3e, 0x74, 0x4b, 0x67, 0xba, 0xff, 0x15, 0xa6, 0x73, 0x00, + 0xd9, 0xf7, 0x9b, 0x80, 0xcc, 0xa2, 0x38, 0xcd, 0x02, 0x5f, 0xbf, 0x19, 0x5c, 0x04, 0xc6, 0xf5, 0x22, 0x33, 0xcc, + 0x1b, 0xcb, 0xcf, 0xd4, 0x4c, 0x30, 0x02, 0x25, 0x63, 0x22, 0x98, 0xb6, 0x4a, 0xea, 0x19, 0xdd, 0x5a, 0x51, 0x20, + 0x7f, 0xac, 0xe4, 0x67, 0x43, 0xa8, 0x57, 0x49, 0x2b, 0x83, 0xf9, 0xb1, 0x74, 0x6c, 0x69, 0x0e, 0x18, 0xc3, 0xf6, + 0x7a, 0xb5, 0x41, 0x62, 0x21, 0x2b, 0xee, 0x63, 0x0c, 0x85, 0x2c, 0xfc, 0x87, 0xd8, 0xf3, 0x13, 0xd5, 0xf6, 0xb5, + 0x74, 0xb3, 0x8f, 0xbe, 0x2c, 0x53, 0x1e, 0x40, 0x21, 0x80, 0xe1, 0x49, 0x14, 0x67, 0x1a, 0xc4, 0xf7, 0x81, 0x2f, + 0x8e, 0xaa, 0xb6, 0x72, 0xbc, 0x57, 0xc3, 0xcc, 0x39, 0xba, 0xf9, 0x0a, 0xaf, 0x57, 0x83, 0x47, 0x79, 0x2b, 0x05, + 0xf2, 0x60, 0x3c, 0x53, 0x0a, 0x0b, 0x98, 0xc5, 0x97, 0xf1, 0x7d, 0x55, 0x1d, 0xf4, 0x7a, 0xb4, 0xfb, 0x76, 0x37, + 0x04, 0x05, 0x2f, 0x92, 0x1b, 0x1a, 0x3c, 0x3f, 0xab, 0x20, 0xa5, 0x2a, 0xa7, 0x0a, 0xed, 0x5f, 0x04, 0x95, 0x94, + 0x81, 0xb9, 0x1c, 0xde, 0x36, 0x80, 0xf4, 0x38, 0x21, 0x30, 0xca, 0x91, 0x6c, 0x95, 0xc9, 0x9f, 0x84, 0xc3, 0x4b, + 0x79, 0xdc, 0xe9, 0x10, 0xa5, 0xb2, 0xf3, 0x60, 0x36, 0xd7, 0xcf, 0x33, 0xbe, 0x23, 0x55, 0x7a, 0xf7, 0x23, 0xbc, + 0xea, 0x37, 0xbd, 0x81, 0x84, 0x54, 0x0d, 0xf5, 0xc3, 0xf8, 0x1e, 0xbc, 0xd9, 0x8b, 0x5e, 0x39, 0x35, 0xdd, 0xda, + 0xb9, 0xf9, 0x52, 0xd6, 0x80, 0xac, 0xe2, 0x66, 0x7f, 0x4b, 0x83, 0xf6, 0x6f, 0x56, 0x7b, 0xb1, 0xe2, 0x47, 0x8d, + 0xc1, 0xfe, 0x2c, 0x63, 0xa8, 0xf4, 0x32, 0x88, 0x86, 0xd1, 0x99, 0x2c, 0x5a, 0x90, 0x35, 0x36, 0x30, 0xcf, 0xeb, + 0x45, 0xfd, 0xc8, 0x8a, 0x87, 0xf1, 0x9e, 0x75, 0x63, 0x6e, 0x78, 0x4c, 0xcf, 0x47, 0x29, 0xcd, 0xce, 0x1b, 0xc6, + 0x02, 0x1b, 0x61, 0xf8, 0x6c, 0x13, 0xe5, 0xa3, 0x7e, 0x4b, 0x15, 0xf6, 0xd6, 0x22, 0xbb, 0x3b, 0x89, 0xb7, 0x76, + 0x12, 0xe7, 0xa3, 0xc7, 0x6c, 0x73, 0x9f, 0xef, 0xf2, 0x70, 0xe0, 0x37, 0x61, 0xfa, 0xb0, 0x71, 0xcf, 0x43, 0x30, + 0xda, 0xd2, 0x6e, 0x4f, 0x70, 0xb7, 0xff, 0xef, 0x7f, 0xfd, 0xe7, 0x7f, 0x17, 0x64, 0xef, 0x38, 0x39, 0x3b, 0xc5, + 0x8c, 0x64, 0x40, 0xc5, 0xe5, 0xa7, 0x07, 0xec, 0x37, 0x16, 0xff, 0x8b, 0x46, 0x45, 0xc4, 0xa8, 0xfe, 0x47, 0x3d, + 0x83, 0x22, 0x8b, 0xbb, 0xc8, 0xa1, 0xae, 0x90, 0xe0, 0x40, 0x43, 0x45, 0xcb, 0x55, 0x86, 0x51, 0xbf, 0x61, 0x1c, + 0x34, 0xd7, 0x35, 0x8c, 0x22, 0x0c, 0xb4, 0x58, 0xc1, 0x0c, 0xe6, 0xba, 0x16, 0x4c, 0xea, 0x65, 0x9c, 0xc9, 0x05, + 0x62, 0x04, 0xa9, 0x38, 0x94, 0x99, 0xc3, 0x63, 0xc2, 0xa7, 0xe3, 0x5b, 0x45, 0xca, 0x0c, 0xc3, 0x47, 0xdd, 0x72, + 0xc3, 0xfd, 0xec, 0xb3, 0x7e, 0x06, 0xfb, 0x4e, 0x73, 0x04, 0xf0, 0x3d, 0x87, 0xed, 0x33, 0x7c, 0xb6, 0x21, 0xc0, + 0xaf, 0xe5, 0x3a, 0x4c, 0xb4, 0xf0, 0x19, 0x2c, 0xa6, 0x07, 0x88, 0x9d, 0x95, 0x6b, 0x68, 0x34, 0x34, 0xe4, 0xa6, + 0x41, 0xcb, 0x24, 0x58, 0x90, 0xe4, 0x81, 0x59, 0x12, 0x59, 0xaa, 0xb9, 0x91, 0xa9, 0x6b, 0x8c, 0x7a, 0x63, 0xf3, + 0x65, 0x84, 0x9c, 0xae, 0xfd, 0x41, 0x96, 0x51, 0x3e, 0x39, 0x81, 0xbe, 0x74, 0xf8, 0xd6, 0x47, 0xfd, 0x25, 0x75, + 0x26, 0x34, 0x23, 0x41, 0xc8, 0x9a, 0x0c, 0x8c, 0xa8, 0x65, 0x36, 0x51, 0x79, 0x36, 0x69, 0x19, 0x65, 0xe3, 0x64, + 0x18, 0x05, 0xc7, 0xc6, 0x8d, 0x33, 0x43, 0x14, 0xda, 0xbc, 0x80, 0xec, 0x9d, 0xb2, 0x97, 0x00, 0xf8, 0x49, 0x7d, + 0x17, 0xe5, 0xed, 0x4b, 0xd4, 0x50, 0xfb, 0xb7, 0x59, 0x36, 0x0a, 0xcb, 0x96, 0xc2, 0xb2, 0xd1, 0xc8, 0x8f, 0x27, + 0xf4, 0xcf, 0xef, 0x2f, 0x64, 0xa6, 0x3f, 0x10, 0x5a, 0x8f, 0xf8, 0x25, 0x12, 0x21, 0x37, 0x91, 0x20, 0x27, 0xc1, + 0x72, 0xf2, 0x69, 0x72, 0xab, 0x25, 0xb9, 0xae, 0x9d, 0xb3, 0x49, 0xd3, 0x09, 0x9b, 0xc9, 0x30, 0xc6, 0x56, 0x49, + 0x7e, 0x7a, 0xc0, 0x6a, 0x33, 0x2a, 0x97, 0x55, 0x02, 0xf8, 0x25, 0x30, 0xeb, 0x02, 0x7c, 0x90, 0x94, 0x78, 0xe8, + 0x15, 0xe2, 0x05, 0x67, 0x81, 0xaa, 0x41, 0xef, 0xbc, 0xcc, 0xb8, 0x60, 0x2b, 0xbd, 0x38, 0xd4, 0x31, 0x04, 0x26, + 0x12, 0xe7, 0x5a, 0xab, 0x9c, 0x9c, 0xa2, 0x13, 0x21, 0xf2, 0xe9, 0xf3, 0x0e, 0x1e, 0x75, 0xa4, 0x00, 0x6b, 0x43, + 0x29, 0xc9, 0x75, 0x6d, 0xc1, 0x19, 0x25, 0x1e, 0x01, 0x0d, 0xc2, 0xa3, 0xb8, 0x70, 0xcf, 0xea, 0xda, 0x82, 0xac, + 0x71, 0xe6, 0xe2, 0x0d, 0x59, 0x1b, 0x1e, 0x7f, 0x55, 0x9c, 0xc9, 0xa8, 0xbc, 0xe0, 0x02, 0xc5, 0x80, 0xef, 0x93, + 0x14, 0xd0, 0xcd, 0xd1, 0xa6, 0xa4, 0x61, 0x71, 0xe7, 0x62, 0x71, 0x27, 0x2d, 0x8b, 0x3b, 0xd9, 0xb2, 0xb8, 0x21, + 0x5f, 0x48, 0x4d, 0x82, 0x2e, 0x41, 0x7f, 0xd6, 0x02, 0x29, 0x32, 0x06, 0xa3, 0xcf, 0x0f, 0x28, 0xc2, 0xc9, 0x4e, + 0x43, 0xb0, 0xe7, 0x6c, 0x81, 0x55, 0x13, 0x5c, 0x14, 0x40, 0xd4, 0x27, 0x2e, 0x8f, 0xab, 0x44, 0xad, 0xd6, 0x1c, + 0xb6, 0xaa, 0x5f, 0xa5, 0x79, 0x43, 0xd6, 0xd0, 0x32, 0xe6, 0x2d, 0x33, 0x9d, 0x6f, 0x99, 0xa9, 0x5f, 0x3a, 0xf3, + 0x7c, 0xda, 0xec, 0xf4, 0xaa, 0x93, 0x62, 0xa4, 0xd0, 0x3a, 0xc3, 0x2d, 0x53, 0xde, 0x87, 0xed, 0xb8, 0x58, 0xd9, + 0x51, 0x4b, 0x92, 0xa6, 0xf7, 0x71, 0x02, 0x4a, 0x62, 0xe8, 0xe6, 0x71, 0x5b, 0x6a, 0x11, 0x44, 0x3c, 0xfe, 0x54, + 0xeb, 0x66, 0x2a, 0xde, 0xab, 0x5b, 0xaa, 0xd3, 0xeb, 0xb1, 0x1a, 0x4b, 0x92, 0x65, 0x34, 0x41, 0xa0, 0x13, 0x48, + 0x54, 0xf0, 0xff, 0x64, 0x9b, 0x35, 0xe0, 0x90, 0xd0, 0x2c, 0xae, 0x03, 0x44, 0xed, 0x4b, 0xe0, 0x83, 0x12, 0x41, + 0x34, 0x2b, 0xb1, 0x2c, 0x13, 0x09, 0x78, 0x4e, 0xdf, 0x24, 0x8a, 0xb7, 0xa5, 0x77, 0x64, 0x3a, 0x4b, 0x32, 0xf9, + 0x01, 0x6c, 0x11, 0x8c, 0x8e, 0x05, 0x7e, 0x05, 0x6a, 0xe4, 0xca, 0x84, 0x31, 0x66, 0x7e, 0x81, 0x24, 0x11, 0x4b, + 0x72, 0xab, 0x4d, 0x70, 0xf8, 0x26, 0xf6, 0xf4, 0x66, 0xd3, 0xc9, 0x0f, 0x66, 0x81, 0x59, 0xc3, 0x9a, 0x80, 0xda, + 0xc2, 0xe1, 0x99, 0x94, 0xc0, 0x84, 0x96, 0x77, 0x64, 0x82, 0xb2, 0xea, 0x1a, 0x52, 0x30, 0xbb, 0x42, 0xbc, 0x35, + 0x4a, 0xe0, 0x76, 0xbb, 0x76, 0x6f, 0xf2, 0xe7, 0x33, 0xfc, 0xe5, 0xdd, 0xe4, 0xcf, 0xc7, 0xf8, 0xab, 0x73, 0x83, + 0xc9, 0x36, 0x1b, 0xc4, 0x7a, 0xca, 0x9c, 0xf5, 0xb3, 0xd2, 0x7e, 0x62, 0x26, 0xb3, 0x8f, 0xd8, 0x36, 0x7c, 0x81, + 0x9f, 0x3e, 0xdb, 0x44, 0xe0, 0x24, 0xae, 0xce, 0x21, 0x75, 0x12, 0x33, 0x6f, 0x2c, 0x9f, 0xb5, 0x94, 0x8f, 0xcd, + 0x7f, 0x31, 0x81, 0x80, 0xbb, 0x24, 0x2e, 0xee, 0x94, 0xb2, 0x50, 0xf2, 0xe3, 0x38, 0x88, 0x48, 0xf2, 0xf0, 0x91, + 0xc9, 0x14, 0x0c, 0xc1, 0x67, 0x4b, 0x61, 0x2b, 0x63, 0x05, 0xcb, 0x1a, 0xfa, 0x4c, 0xd1, 0x49, 0x3d, 0x70, 0x0a, + 0x61, 0xf8, 0x97, 0x44, 0xa1, 0x3d, 0x4b, 0xe2, 0x28, 0xbe, 0x20, 0xa5, 0x0f, 0x7d, 0x7c, 0xb6, 0x31, 0x68, 0xbd, + 0x9b, 0x9a, 0xb8, 0xa2, 0x44, 0x10, 0xc0, 0xf2, 0xa0, 0x68, 0x6b, 0x31, 0x09, 0xfa, 0xa8, 0x82, 0x1f, 0xc7, 0x6b, + 0xfb, 0xd9, 0x26, 0x3b, 0xd7, 0x17, 0x24, 0xb9, 0xa5, 0x13, 0xdb, 0x0f, 0x12, 0x3f, 0xa4, 0x7a, 0x5f, 0x1f, 0x87, + 0x24, 0xba, 0xe5, 0x8f, 0x76, 0xbc, 0xca, 0xd0, 0xa8, 0x66, 0xa7, 0x24, 0x4c, 0xc0, 0x84, 0x09, 0xf0, 0x91, 0x41, + 0x6b, 0x80, 0x82, 0xf6, 0x5a, 0x8a, 0xbf, 0x0b, 0x82, 0xb2, 0xa8, 0x65, 0x81, 0x4d, 0x38, 0xd8, 0xf9, 0x80, 0x93, + 0xbd, 0xa5, 0xe3, 0x7a, 0xe9, 0x96, 0x3a, 0x55, 0xa6, 0xf7, 0x90, 0x59, 0x62, 0x3f, 0x62, 0x0f, 0xbf, 0xfc, 0x73, + 0x50, 0xf2, 0x98, 0xcf, 0x71, 0xe2, 0xb0, 0xfd, 0x83, 0x6a, 0x63, 0x92, 0xa6, 0xab, 0x05, 0x9d, 0x30, 0x7b, 0x82, + 0xf3, 0x62, 0x28, 0x65, 0x46, 0x5c, 0x1d, 0xce, 0x4f, 0xab, 0xce, 0xf1, 0xe1, 0x6b, 0xb0, 0x73, 0x02, 0x62, 0x30, + 0x9e, 0x4e, 0xf5, 0x42, 0xbc, 0xb6, 0xa3, 0x99, 0x77, 0xf8, 0xd3, 0xea, 0xeb, 0xb7, 0xee, 0xd7, 0xb2, 0x71, 0xa4, + 0x9b, 0xf9, 0x48, 0x18, 0x6d, 0x70, 0x9a, 0x56, 0x19, 0xaf, 0x98, 0xd1, 0x94, 0x44, 0xed, 0xd3, 0xb9, 0x2e, 0xed, + 0xb2, 0x25, 0xa5, 0x13, 0xb0, 0xe7, 0xb7, 0x6a, 0xa5, 0x1f, 0x43, 0x7a, 0x47, 0xa5, 0x41, 0x48, 0xfd, 0x63, 0x0d, + 0x2d, 0x30, 0x62, 0x25, 0x37, 0x34, 0xe1, 0x84, 0x95, 0x32, 0xa5, 0x11, 0xce, 0x81, 0xcf, 0x5c, 0xdd, 0xe5, 0x95, + 0x5d, 0x3d, 0xb2, 0x74, 0x65, 0x00, 0xad, 0x23, 0x3b, 0x6f, 0x29, 0xef, 0x63, 0xba, 0xfa, 0xe6, 0xb1, 0x59, 0x9e, + 0xd9, 0x87, 0x08, 0xff, 0x1c, 0x4e, 0x21, 0x6c, 0x7e, 0x43, 0x4a, 0x22, 0x07, 0x6d, 0x10, 0x6b, 0x92, 0x5a, 0xeb, + 0x4c, 0xf0, 0x29, 0x6c, 0xa4, 0xd1, 0x59, 0x40, 0x08, 0x86, 0x1b, 0xd7, 0x46, 0x2b, 0xcf, 0x7c, 0x8c, 0x69, 0xa0, + 0x23, 0x9a, 0xa6, 0xad, 0x00, 0x93, 0x8b, 0x6e, 0xe9, 0x45, 0xed, 0x32, 0x3c, 0x8a, 0x72, 0xcb, 0xb5, 0xe0, 0x56, + 0xc6, 0x09, 0x56, 0xbf, 0x85, 0x18, 0xfe, 0xe3, 0x82, 0x5b, 0xb9, 0x25, 0xb3, 0xb1, 0xce, 0x2d, 0x90, 0xda, 0xde, + 0xdf, 0xeb, 0x7c, 0x50, 0xa5, 0x9b, 0xb2, 0x71, 0x68, 0x46, 0x09, 0xfb, 0xd5, 0xc4, 0xb4, 0xd8, 0x81, 0x18, 0x53, + 0x05, 0xc5, 0xd1, 0xe9, 0x94, 0xfa, 0x59, 0x6a, 0x0a, 0x59, 0xab, 0x8c, 0x39, 0x0d, 0xbe, 0x86, 0x4f, 0x86, 0xfa, + 0x9f, 0x20, 0xf2, 0x86, 0x08, 0xcd, 0xc6, 0x07, 0x24, 0xf8, 0x9d, 0x66, 0x30, 0xb1, 0x1e, 0xcb, 0x20, 0xe2, 0x5f, + 0xf9, 0xf4, 0x49, 0x98, 0x48, 0x94, 0xca, 0x71, 0x68, 0xfc, 0x0a, 0x28, 0xf6, 0x45, 0x2c, 0x6d, 0xe1, 0xb6, 0x23, + 0xa0, 0x6d, 0xc7, 0x77, 0xe3, 0x7d, 0xdd, 0xf3, 0xdc, 0x5c, 0xb7, 0xc0, 0xe3, 0xf3, 0x76, 0xdf, 0x43, 0x8f, 0xad, + 0xba, 0xd0, 0x6a, 0x15, 0x3d, 0xa6, 0x5d, 0xc7, 0x7b, 0xe5, 0xe9, 0x16, 0x33, 0xb4, 0x55, 0x70, 0x9b, 0x1f, 0xdf, + 0xd1, 0xe4, 0x57, 0x4f, 0xa5, 0xdc, 0xf9, 0x7e, 0xe3, 0x39, 0xf2, 0x5c, 0x40, 0xc2, 0x59, 0xbc, 0x7c, 0xc4, 0x14, + 0xba, 0xba, 0xa5, 0xfb, 0x61, 0x9c, 0x52, 0x75, 0x0e, 0x4c, 0x5e, 0xf1, 0x2b, 0x27, 0xf1, 0xfd, 0xfb, 0xb7, 0x3f, + 0xfc, 0xa0, 0x5b, 0x98, 0x3f, 0x38, 0x55, 0x7b, 0xe7, 0x1b, 0x6a, 0x07, 0xf6, 0x6f, 0xdc, 0x77, 0xec, 0x86, 0x61, + 0x7c, 0x65, 0x79, 0xcf, 0xb1, 0xb2, 0xda, 0x96, 0xe3, 0x37, 0x0f, 0xff, 0x32, 0x63, 0x06, 0xf7, 0x9a, 0x57, 0x03, + 0x6e, 0xd8, 0x7e, 0xbd, 0x95, 0x4a, 0x16, 0x41, 0xf4, 0xb1, 0xa1, 0x94, 0xac, 0x1b, 0x4a, 0x51, 0x36, 0x58, 0xc5, + 0x1f, 0xab, 0x78, 0xa1, 0xdc, 0xce, 0x90, 0xfe, 0x7d, 0x17, 0xb8, 0x14, 0x96, 0xe6, 0x57, 0x0c, 0x9a, 0xe7, 0x7f, + 0xa8, 0x8e, 0xba, 0xa1, 0x98, 0xf3, 0x21, 0x12, 0xb6, 0x5c, 0x97, 0xa3, 0xaa, 0xc9, 0xcb, 0x94, 0x9b, 0xda, 0xb8, + 0x59, 0x60, 0xfa, 0xa4, 0x70, 0xbe, 0xd9, 0x51, 0x19, 0x84, 0xb4, 0xb2, 0x76, 0x41, 0x13, 0x6c, 0xed, 0x3d, 0xff, + 0xe7, 0x3f, 0x1c, 0xe7, 0x9f, 0xff, 0xd8, 0x59, 0x15, 0xfa, 0xce, 0x81, 0x1d, 0xde, 0x55, 0x33, 0x1f, 0xa1, 0xd0, + 0x29, 0x1b, 0xbe, 0x1e, 0x8d, 0x06, 0x46, 0x09, 0x64, 0xe0, 0x33, 0x72, 0x5e, 0x2b, 0xe1, 0x78, 0xb5, 0xef, 0x9a, + 0x18, 0xcc, 0x01, 0x1a, 0xca, 0xeb, 0xab, 0x75, 0xb3, 0x33, 0xa7, 0x84, 0x5a, 0x5f, 0xb5, 0x9d, 0x0e, 0xa5, 0x98, + 0xb8, 0x2e, 0x1f, 0x99, 0x3c, 0xc7, 0x00, 0x8c, 0x8b, 0xab, 0x0f, 0x4a, 0x2b, 0x07, 0x7e, 0x36, 0x59, 0x79, 0x7c, + 0xbc, 0xac, 0x32, 0x42, 0xba, 0xd7, 0x08, 0x59, 0xdb, 0xf2, 0x18, 0x79, 0x7f, 0xb5, 0x51, 0xb2, 0x72, 0x31, 0x4e, + 0x0b, 0x45, 0x66, 0x3c, 0xca, 0x08, 0x67, 0x9a, 0xb8, 0x4a, 0xb0, 0xa4, 0xf6, 0xad, 0xa8, 0x2e, 0x94, 0x21, 0xec, + 0x5e, 0xf6, 0x73, 0x3d, 0x8c, 0xef, 0xd1, 0x59, 0x4f, 0xd5, 0x27, 0x73, 0x61, 0xc8, 0x69, 0x9a, 0x25, 0x71, 0x34, + 0x3b, 0xab, 0x5c, 0xde, 0x75, 0x3b, 0x1f, 0x90, 0x60, 0xb1, 0xaa, 0x65, 0xb1, 0x89, 0x3a, 0xca, 0xed, 0x5b, 0xea, + 0x7c, 0xc7, 0x4c, 0x98, 0x6a, 0x42, 0xb9, 0x1c, 0x45, 0xd7, 0x0d, 0x6a, 0x70, 0x95, 0x94, 0x2b, 0xbf, 0x96, 0x8f, + 0x07, 0x1c, 0xae, 0x67, 0xa3, 0x1c, 0x93, 0x1d, 0xbd, 0x6b, 0x33, 0x10, 0xfd, 0x7e, 0xb7, 0x81, 0xe8, 0xd5, 0x5e, + 0x06, 0xa2, 0xdf, 0x7f, 0x76, 0x03, 0xd1, 0x77, 0xaa, 0x81, 0x28, 0x6c, 0xe9, 0xb7, 0x74, 0x2f, 0xab, 0x4d, 0x61, + 0x0d, 0x15, 0xdf, 0xa7, 0x43, 0x8f, 0x53, 0xa6, 0xa9, 0x3f, 0xa7, 0xc0, 0x6d, 0xf3, 0x6d, 0x1a, 0xc6, 0x33, 0xb0, + 0xe0, 0xfc, 0xed, 0x6d, 0x2d, 0xc3, 0x78, 0xa6, 0x5a, 0x5a, 0xa6, 0x3c, 0xdc, 0x73, 0x11, 0xc2, 0x8d, 0x59, 0x37, + 0xba, 0x96, 0x38, 0x7b, 0xf6, 0xa1, 0xa9, 0xa4, 0xb4, 0x97, 0xa6, 0xab, 0x1d, 0x61, 0xff, 0xd8, 0x47, 0xd3, 0x49, + 0xd9, 0xb0, 0xf3, 0x32, 0x96, 0x49, 0x7b, 0x8a, 0x1e, 0xa4, 0x8b, 0x00, 0x0b, 0x12, 0xb3, 0xd1, 0x7f, 0x5a, 0x7b, + 0x5f, 0x5d, 0x7b, 0x83, 0xae, 0x07, 0x91, 0x19, 0x80, 0x57, 0xc3, 0x02, 0x77, 0xd0, 0xed, 0x42, 0xc1, 0xbd, 0x52, + 0xd0, 0x81, 0x82, 0x40, 0x29, 0xe8, 0x41, 0x81, 0xaf, 0x14, 0x1c, 0x41, 0xc1, 0x44, 0x29, 0x38, 0x86, 0x82, 0x3b, + 0x3d, 0xbf, 0x2e, 0x12, 0x39, 0x1d, 0x9b, 0x37, 0x16, 0xe3, 0x0d, 0x44, 0xd9, 0xb1, 0xe5, 0x81, 0x19, 0x23, 0x99, + 0xf5, 0x63, 0x8b, 0xc9, 0xe9, 0xfa, 0x89, 0x75, 0x3f, 0xa7, 0x2c, 0x4a, 0xfc, 0x1b, 0xbc, 0x3a, 0x9c, 0x2c, 0x06, + 0xa7, 0x09, 0x11, 0x7d, 0x45, 0xc0, 0x41, 0xd3, 0x4d, 0x10, 0xbd, 0x0c, 0xe4, 0xca, 0x89, 0x08, 0x36, 0xca, 0x5a, + 0x16, 0xef, 0xd8, 0xe7, 0x6c, 0xb9, 0x05, 0x0a, 0x4b, 0x2e, 0x43, 0x95, 0xef, 0x7d, 0x0e, 0x7b, 0x9e, 0x37, 0x74, + 0xbc, 0x9a, 0x69, 0x97, 0xf1, 0x6c, 0xa7, 0x69, 0x8e, 0xfa, 0x0a, 0x46, 0xa9, 0x33, 0x0d, 0x88, 0x2d, 0xb6, 0x25, + 0xff, 0x16, 0x7b, 0xcc, 0xcb, 0xf5, 0x33, 0x18, 0x9b, 0x96, 0x31, 0xc3, 0x30, 0xf8, 0x0e, 0xc0, 0x48, 0x39, 0xf5, + 0x97, 0x00, 0x67, 0xe5, 0xf9, 0x8a, 0x28, 0xe3, 0x39, 0xfb, 0x8e, 0xa6, 0x29, 0x99, 0x89, 0xfa, 0xf5, 0x71, 0x82, + 0x31, 0x9c, 0x64, 0xa3, 0x10, 0x80, 0x20, 0x13, 0x0b, 0x6a, 0x36, 0x4f, 0x49, 0x7c, 0xaf, 0x81, 0x55, 0x1d, 0x6c, + 0xa8, 0xc2, 0xfe, 0x27, 0x70, 0x60, 0x09, 0xcb, 0x38, 0x08, 0x0e, 0xff, 0x1d, 0x0d, 0xab, 0x85, 0x19, 0x99, 0x55, + 0x8b, 0xd8, 0x3e, 0xc8, 0xd5, 0xb1, 0x49, 0x93, 0x98, 0x52, 0xe1, 0xaf, 0xb1, 0xcb, 0x08, 0xe3, 0xd9, 0x6f, 0x6a, + 0x94, 0xb1, 0xc5, 0x30, 0xe7, 0x36, 0xb5, 0x82, 0x6c, 0xe4, 0x20, 0x8c, 0x35, 0x07, 0x40, 0xd8, 0x8f, 0xb2, 0xb9, + 0x8d, 0x7e, 0xa5, 0x46, 0x27, 0x32, 0x2d, 0x07, 0xd7, 0x76, 0x53, 0xf5, 0xa6, 0xef, 0x27, 0xb3, 0x31, 0x31, 0xbc, + 0xce, 0xb1, 0x25, 0xfe, 0x1c, 0xb7, 0x67, 0xe6, 0xd8, 0x83, 0x36, 0x09, 0xee, 0x36, 0xd3, 0x38, 0xca, 0xec, 0x29, + 0x59, 0x04, 0xe1, 0x43, 0x7f, 0x11, 0x47, 0x71, 0xba, 0x24, 0x3e, 0x1d, 0x14, 0x7c, 0xf1, 0x00, 0xe3, 0xb4, 0x70, + 0x57, 0x61, 0xcf, 0xe9, 0x24, 0x74, 0xc1, 0x5a, 0xcb, 0x30, 0x2c, 0xd3, 0x90, 0xae, 0x73, 0xfe, 0xf9, 0x52, 0x65, + 0x56, 0x15, 0xb7, 0x1c, 0x6b, 0x01, 0x84, 0x25, 0x8f, 0xf1, 0x02, 0x91, 0xcd, 0x06, 0x4b, 0x32, 0xc1, 0xb0, 0xa4, + 0x4e, 0xa7, 0x97, 0xd0, 0x85, 0xe6, 0xf4, 0x5a, 0x3b, 0x4f, 0xe2, 0xfb, 0x33, 0x18, 0x2d, 0x36, 0xb6, 0x53, 0x1a, + 0x4e, 0xf1, 0x8d, 0x8d, 0x6e, 0x65, 0xa2, 0x1f, 0x1b, 0xf9, 0x69, 0xe8, 0x8d, 0x2e, 0x06, 0xf0, 0xba, 0xdf, 0xd1, + 0xdc, 0xc1, 0x22, 0x88, 0x6c, 0x36, 0x9d, 0x63, 0x77, 0xa9, 0xf4, 0xa5, 0xc2, 0xcf, 0xdc, 0x60, 0x75, 0x4f, 0x73, + 0x07, 0xc0, 0x73, 0x4d, 0xc3, 0xf8, 0xbe, 0x3f, 0x0f, 0x26, 0x13, 0x1a, 0x0d, 0x70, 0xcc, 0xb2, 0x90, 0x86, 0x61, + 0xb0, 0x4c, 0x83, 0x74, 0xb0, 0x20, 0x6b, 0xde, 0xeb, 0x61, 0x5b, 0xaf, 0x5d, 0xde, 0x6b, 0x77, 0xef, 0x5e, 0x95, + 0x6e, 0xc0, 0x85, 0x8d, 0xf5, 0xc3, 0x87, 0xd6, 0xd3, 0xdc, 0xca, 0x3c, 0xf7, 0xee, 0x75, 0x99, 0xd0, 0xcd, 0x82, + 0x24, 0xb3, 0x20, 0xea, 0xbb, 0xb9, 0x73, 0xb7, 0x61, 0x1b, 0xe3, 0xe9, 0xc9, 0xc9, 0x49, 0xee, 0x4c, 0xc4, 0x93, + 0x3b, 0x99, 0xe4, 0x8e, 0x2f, 0x9e, 0xa6, 0x53, 0xd7, 0x9d, 0x4e, 0x73, 0x27, 0x10, 0x05, 0xdd, 0x8e, 0x3f, 0xe9, + 0x76, 0x72, 0xe7, 0x5e, 0xa9, 0x91, 0x3b, 0x94, 0x3f, 0x25, 0x74, 0x32, 0xc0, 0x8d, 0xc4, 0xec, 0xbc, 0xfb, 0xc7, + 0xae, 0x9b, 0x23, 0x06, 0xb8, 0x2e, 0xe1, 0x26, 0x14, 0xd9, 0xdc, 0x6c, 0xf6, 0xae, 0xa9, 0x15, 0x9f, 0xf3, 0xfd, + 0xc6, 0x7a, 0x13, 0x92, 0xdc, 0xde, 0x68, 0xca, 0x2c, 0x08, 0x61, 0xd5, 0x36, 0x02, 0x0c, 0xf6, 0xba, 0x0f, 0xf1, + 0xfa, 0x06, 0xe3, 0x38, 0x81, 0x33, 0x9b, 0x90, 0x49, 0xb0, 0x4a, 0xfb, 0x5e, 0x67, 0xb9, 0x16, 0x45, 0x7c, 0xaf, + 0x17, 0x05, 0x78, 0xf6, 0xfa, 0x69, 0x1c, 0x06, 0x13, 0x51, 0xd4, 0x76, 0x96, 0xbc, 0x8e, 0x39, 0xc0, 0x68, 0x15, + 0x01, 0xc6, 0x5c, 0x21, 0x61, 0xa8, 0x39, 0xdd, 0x54, 0xa3, 0x24, 0x45, 0x49, 0xad, 0xe6, 0xa6, 0x0c, 0x2e, 0x18, + 0x99, 0xc2, 0x3b, 0x5c, 0xae, 0xe5, 0x9e, 0xf7, 0x8e, 0x96, 0xeb, 0xfc, 0x0f, 0x0b, 0x3a, 0x09, 0x88, 0x66, 0x14, + 0xbb, 0xc9, 0x73, 0x41, 0x9a, 0x6b, 0x6e, 0x5a, 0xb6, 0xa9, 0x38, 0x16, 0x10, 0xd7, 0xf4, 0x49, 0xb0, 0x58, 0xc6, + 0x49, 0x46, 0xa2, 0x2c, 0xcf, 0x47, 0x37, 0x79, 0x3e, 0xb8, 0x0a, 0x8c, 0xeb, 0xbf, 0x1a, 0xec, 0x9e, 0x66, 0xda, + 0x8f, 0xdc, 0xbc, 0xb1, 0xde, 0x52, 0xd5, 0x52, 0x0a, 0xae, 0x31, 0xb4, 0x92, 0x52, 0x2b, 0xb3, 0x5b, 0xb2, 0x5e, + 0x99, 0x01, 0x59, 0x56, 0x67, 0x96, 0x57, 0xe5, 0x2a, 0x78, 0x03, 0x41, 0x85, 0xb7, 0x74, 0x78, 0xa5, 0x58, 0x5d, + 0x01, 0xb1, 0x82, 0x95, 0x99, 0x53, 0xd1, 0xb3, 0x36, 0x9a, 0xf1, 0xcb, 0xdd, 0x34, 0xe3, 0x8f, 0xd9, 0x3e, 0x34, + 0xe3, 0x97, 0x9f, 0x9d, 0x66, 0x7c, 0x56, 0x77, 0x2a, 0xba, 0x88, 0x87, 0xba, 0x94, 0xd5, 0xc3, 0xd5, 0x94, 0xb0, + 0x70, 0x5d, 0x17, 0xbf, 0xd8, 0x07, 0x48, 0xf4, 0xc6, 0x12, 0x50, 0xb2, 0x9b, 0x1b, 0x68, 0xf1, 0x77, 0xd1, 0xf0, + 0x2f, 0x89, 0xfa, 0x3c, 0x9d, 0x0e, 0xdf, 0xc4, 0x4a, 0x81, 0x7c, 0xe2, 0xf6, 0x0f, 0xa5, 0xd0, 0x2a, 0xec, 0x8d, + 0xb0, 0x6e, 0xc6, 0xe4, 0x33, 0x10, 0x99, 0x81, 0x59, 0xf3, 0x4f, 0xa4, 0xfd, 0xe6, 0xa0, 0x3c, 0x04, 0x43, 0x9a, + 0x52, 0x0b, 0xff, 0xbb, 0x9a, 0x44, 0x70, 0x46, 0x33, 0xee, 0x30, 0xff, 0xd5, 0xc3, 0xc5, 0xc4, 0xb8, 0x88, 0xcd, + 0x3c, 0x48, 0xdf, 0x55, 0xbd, 0xdf, 0xb8, 0x16, 0x65, 0xa8, 0x4e, 0x27, 0xe7, 0x76, 0x93, 0x6a, 0x76, 0x79, 0x78, + 0xcd, 0x9a, 0x9f, 0x97, 0x66, 0xda, 0x57, 0x1b, 0x72, 0x0e, 0xb4, 0x76, 0x19, 0x73, 0xd7, 0xa3, 0x0d, 0xa7, 0x00, + 0x31, 0x71, 0x1f, 0x06, 0x0d, 0x98, 0xb0, 0xe6, 0xc1, 0x24, 0xcf, 0xcd, 0x81, 0x00, 0x84, 0x72, 0xd1, 0xd2, 0x5d, + 0x44, 0x5c, 0x7a, 0x2f, 0xad, 0x03, 0xb8, 0xae, 0x8d, 0x29, 0xd2, 0x2e, 0x40, 0x35, 0xcd, 0xd5, 0x6e, 0x1c, 0x66, + 0xba, 0xc6, 0xc0, 0xc7, 0x4c, 0x16, 0x94, 0x09, 0x81, 0x2e, 0x55, 0xc2, 0x5f, 0xbc, 0x12, 0x05, 0x75, 0xdb, 0x68, + 0x06, 0x1c, 0xd4, 0xad, 0x43, 0x88, 0x0f, 0x21, 0x9e, 0x66, 0x68, 0x87, 0xd7, 0xc1, 0x87, 0x5c, 0x97, 0xb4, 0x1f, + 0x6e, 0x3f, 0x60, 0xcf, 0x96, 0x24, 0xaa, 0xf0, 0x92, 0xbb, 0x6c, 0x7c, 0x81, 0x94, 0x48, 0xef, 0x2d, 0x27, 0xbd, + 0xd7, 0x5e, 0x6c, 0x44, 0x78, 0x9c, 0x8c, 0x2c, 0x6d, 0xe0, 0x1c, 0x11, 0xf7, 0x72, 0x8c, 0xa7, 0x44, 0xe2, 0x19, + 0xac, 0x52, 0xc0, 0x8d, 0xc8, 0x70, 0x22, 0xfe, 0x19, 0xf8, 0xab, 0x24, 0x8d, 0x93, 0xfe, 0x32, 0x0e, 0xa2, 0x8c, + 0x26, 0x39, 0x82, 0xea, 0x1a, 0xe1, 0x23, 0xc0, 0x73, 0xb3, 0x89, 0x97, 0xc4, 0x0f, 0xb2, 0x87, 0xbe, 0xcb, 0x49, + 0x0a, 0x77, 0xc0, 0xa9, 0x03, 0xb7, 0xb1, 0x7e, 0x9f, 0x43, 0xf3, 0x25, 0x12, 0x7e, 0x49, 0x9d, 0x9c, 0x51, 0xb7, + 0xf9, 0x40, 0x79, 0xcb, 0x02, 0x04, 0x01, 0xf9, 0x41, 0x12, 0x7b, 0x06, 0x58, 0x1e, 0x96, 0xda, 0x9d, 0xd0, 0x99, + 0x85, 0x58, 0x1b, 0xc4, 0xeb, 0xe2, 0xcf, 0xe9, 0x99, 0x9a, 0xdb, 0x5c, 0x0c, 0x14, 0x8f, 0xb9, 0xcf, 0xc8, 0xfa, + 0x04, 0xd2, 0xe9, 0x59, 0xfb, 0xd4, 0x1c, 0xd3, 0x69, 0x9c, 0x50, 0x16, 0x4c, 0xda, 0x3b, 0x59, 0xae, 0xf7, 0xef, + 0x7e, 0xfb, 0xf4, 0x9b, 0xfb, 0x89, 0xe2, 0xcc, 0x10, 0x9d, 0x99, 0x3b, 0x7a, 0xab, 0xdf, 0x67, 0x40, 0x1a, 0x32, + 0xc8, 0xfb, 0x2c, 0x6e, 0x5f, 0x5f, 0xd7, 0x07, 0x8d, 0x31, 0xfb, 0x96, 0x31, 0xbf, 0xf3, 0x12, 0x1a, 0x92, 0x2c, + 0xb8, 0x13, 0x34, 0x63, 0xf7, 0x68, 0xb9, 0x16, 0x6b, 0x8c, 0x17, 0xde, 0x23, 0x16, 0xa9, 0x32, 0x14, 0xb1, 0x48, + 0xd5, 0x62, 0x5c, 0xa4, 0x41, 0x6d, 0x36, 0x22, 0x8c, 0x4d, 0xe5, 0xa6, 0xef, 0x2d, 0xd7, 0xea, 0x15, 0x5d, 0x34, + 0x93, 0x37, 0x75, 0x35, 0xfe, 0xe0, 0x22, 0x98, 0x4c, 0x42, 0x9a, 0x97, 0x16, 0xba, 0xbc, 0x96, 0x0a, 0x70, 0x24, + 0x1c, 0xc8, 0x38, 0x8d, 0xc3, 0x55, 0x46, 0x9b, 0xc1, 0xc5, 0x80, 0xd3, 0x71, 0x0b, 0xe0, 0xe0, 0xef, 0xf2, 0x58, + 0x7b, 0x40, 0x6e, 0xc3, 0x36, 0x71, 0x07, 0x10, 0x6e, 0xdc, 0xee, 0x96, 0x87, 0x0e, 0xaf, 0xe4, 0xa0, 0xad, 0x86, + 0x89, 0x58, 0x70, 0x2d, 0x31, 0xec, 0xad, 0x39, 0x1e, 0x2f, 0x93, 0x21, 0x97, 0x65, 0x51, 0x5e, 0x9e, 0xcc, 0x6f, + 0x73, 0xc6, 0x5e, 0x35, 0x9f, 0xb1, 0x57, 0xe2, 0x8c, 0x6d, 0xdf, 0x99, 0x4f, 0xa7, 0x1e, 0xfc, 0x37, 0x28, 0x26, + 0xd4, 0x77, 0xb5, 0xee, 0x72, 0xad, 0x79, 0xcb, 0xb5, 0x66, 0x77, 0x96, 0x6b, 0x0d, 0xbb, 0x46, 0xcb, 0x0a, 0xcb, + 0xe9, 0x98, 0x96, 0xab, 0x41, 0x21, 0xfc, 0xb9, 0xa5, 0x57, 0xde, 0x21, 0xbc, 0x83, 0x56, 0xbd, 0xfa, 0xbb, 0xce, + 0xf6, 0xa3, 0xce, 0xce, 0x92, 0x40, 0xda, 0xa6, 0x93, 0x91, 0xf1, 0x98, 0x4e, 0xfa, 0xd3, 0xd8, 0x5f, 0xa5, 0x7f, + 0xe7, 0xe3, 0xe7, 0x40, 0xdc, 0x8a, 0x08, 0x2a, 0xfd, 0x88, 0xa6, 0xa0, 0xef, 0xb8, 0xa3, 0xa2, 0x87, 0x8d, 0x5c, + 0xa7, 0x3e, 0x8b, 0x8d, 0xde, 0x71, 0x0e, 0x1b, 0x36, 0x79, 0x33, 0xa0, 0x7f, 0xb3, 0x55, 0x6a, 0x47, 0x31, 0xbf, + 0x02, 0x2c, 0x5b, 0xc1, 0xf1, 0x78, 0x68, 0xf0, 0xd5, 0x74, 0x4f, 0x9a, 0x87, 0x7b, 0x2d, 0xbe, 0x74, 0x23, 0x2e, + 0x15, 0x7e, 0x6f, 0x71, 0x87, 0xaf, 0xed, 0xbd, 0xb6, 0xed, 0x91, 0x5a, 0xaf, 0x5b, 0x2e, 0x84, 0xa2, 0xee, 0x9e, + 0x58, 0xfe, 0xe9, 0xab, 0x43, 0xf8, 0x8f, 0x51, 0xf5, 0x3f, 0x66, 0x4d, 0x84, 0xfa, 0x45, 0xd9, 0xff, 0x81, 0x91, + 0x4a, 0x48, 0x88, 0xef, 0x5f, 0x7f, 0x3a, 0x7d, 0x5c, 0x83, 0xbd, 0x6b, 0x33, 0xa3, 0xa4, 0x6a, 0xed, 0xaf, 0xe2, + 0x18, 0xf2, 0xf6, 0xd6, 0xab, 0x0b, 0xf0, 0x30, 0x17, 0x8f, 0x6c, 0x08, 0x8d, 0x04, 0x1f, 0xc1, 0x94, 0xf1, 0x3a, + 0xb6, 0x61, 0xac, 0xc4, 0xdb, 0x36, 0x56, 0xe2, 0xcd, 0x6e, 0x56, 0xe2, 0xdb, 0xbd, 0x58, 0x89, 0x37, 0x9f, 0x9d, + 0x95, 0x78, 0x5b, 0x67, 0x25, 0xae, 0x62, 0x61, 0x89, 0x6a, 0x5d, 0xac, 0xf8, 0xcf, 0x0f, 0x4c, 0xb7, 0x76, 0x19, + 0x0f, 0x7b, 0x2e, 0x8b, 0x77, 0x7e, 0xf5, 0x8b, 0x19, 0x0b, 0xdc, 0x88, 0xef, 0xd1, 0x30, 0xab, 0x60, 0x2d, 0x38, + 0x66, 0xc7, 0xef, 0x28, 0xc5, 0x61, 0x1c, 0xcd, 0xbe, 0x07, 0xdd, 0x2a, 0x88, 0x03, 0x13, 0xe5, 0x45, 0x90, 0x7e, + 0x1f, 0x2f, 0x57, 0xcb, 0x0b, 0xe8, 0xeb, 0x43, 0x90, 0x06, 0xe3, 0x90, 0xca, 0x30, 0x04, 0xcc, 0x90, 0x8c, 0xcb, + 0xc4, 0xc1, 0x76, 0x53, 0xfc, 0x24, 0x6b, 0xf1, 0x13, 0xad, 0x3b, 0xf9, 0x6f, 0x66, 0xa1, 0xa6, 0x37, 0x33, 0x22, + 0x10, 0xb0, 0xab, 0x32, 0xe8, 0xc7, 0x33, 0x23, 0x57, 0xb1, 0xd9, 0x30, 0x4b, 0x61, 0xb6, 0xd0, 0xda, 0x0f, 0xad, + 0x31, 0x35, 0x2b, 0xd3, 0x92, 0xf1, 0xf7, 0xea, 0x62, 0xf8, 0x45, 0xbc, 0x4a, 0xe9, 0x24, 0xbe, 0x8f, 0x74, 0x2b, + 0x95, 0xae, 0x35, 0xa0, 0xa8, 0x94, 0x6d, 0x30, 0x73, 0xac, 0xd4, 0xcc, 0xe8, 0x90, 0xb8, 0x78, 0xb5, 0xb4, 0x99, + 0xc6, 0xd8, 0xc6, 0x29, 0xea, 0x32, 0xc5, 0xd9, 0x13, 0xc3, 0x88, 0x87, 0x8f, 0x6b, 0x29, 0x2c, 0x2e, 0x62, 0x87, + 0x4b, 0x85, 0x53, 0x23, 0x15, 0xc2, 0x45, 0x11, 0x04, 0xa7, 0x61, 0xe1, 0xf8, 0x1b, 0xe6, 0x12, 0x5e, 0xbc, 0x85, + 0x10, 0x42, 0xf9, 0x8a, 0xaf, 0x07, 0x0f, 0x09, 0xc3, 0x1e, 0x5f, 0x2b, 0x60, 0x7c, 0x77, 0x47, 0x93, 0x90, 0x3c, + 0x18, 0x66, 0x1e, 0x47, 0xdf, 0x01, 0x00, 0xde, 0xc4, 0xf7, 0x91, 0x5a, 0x01, 0x33, 0x35, 0x35, 0xec, 0xa5, 0xc6, + 0xe0, 0x45, 0xe0, 0xae, 0xa5, 0x8c, 0x00, 0x72, 0x64, 0xcf, 0xe8, 0x5f, 0x2c, 0xf6, 0xef, 0x5f, 0xcd, 0xdc, 0xba, + 0x8c, 0xe5, 0x87, 0xfe, 0xbc, 0xdc, 0xe3, 0x33, 0xcf, 0x9f, 0x3f, 0x69, 0x9f, 0xb6, 0x01, 0xe9, 0xc2, 0x45, 0xe6, + 0x6b, 0xa3, 0xa1, 0xb5, 0xd9, 0x7a, 0x0a, 0x60, 0x14, 0x57, 0xf1, 0xca, 0x9f, 0xa3, 0xc9, 0xe8, 0xe7, 0x9b, 0x6f, + 0x06, 0x7d, 0x62, 0x8a, 0x62, 0x39, 0xf5, 0x4a, 0x51, 0x01, 0x05, 0xfc, 0xfe, 0x5b, 0x88, 0xbe, 0xfb, 0x6f, 0x04, + 0x43, 0x7d, 0xd7, 0x70, 0x2e, 0x3e, 0x78, 0xdc, 0xe6, 0x1d, 0x40, 0x26, 0x5d, 0x1e, 0xd7, 0x46, 0x28, 0xd7, 0x9a, + 0x91, 0x4c, 0x5e, 0x05, 0x9a, 0x1a, 0x43, 0xb2, 0x2d, 0x3c, 0xa6, 0xf8, 0x0a, 0x75, 0x18, 0x9b, 0xce, 0x4d, 0xf6, + 0x2d, 0xca, 0xb1, 0x55, 0x05, 0xc9, 0x70, 0xcb, 0x05, 0x8a, 0xe8, 0xab, 0xfa, 0x6e, 0x11, 0x44, 0x16, 0xa6, 0x80, + 0xa8, 0xbf, 0x21, 0x6b, 0x08, 0x82, 0x0e, 0xc8, 0xad, 0xfa, 0x0a, 0x0a, 0x2d, 0xaa, 0x78, 0x8b, 0x42, 0x9e, 0x37, + 0xbd, 0x11, 0x12, 0x42, 0x8b, 0x37, 0xfa, 0x9d, 0xa6, 0x69, 0x9a, 0x64, 0x23, 0x34, 0xc9, 0x47, 0x60, 0x39, 0xb2, + 0x03, 0xa0, 0x2d, 0xc9, 0x97, 0x6b, 0x56, 0x02, 0x9c, 0x01, 0x98, 0x78, 0xc8, 0x02, 0x1e, 0xe7, 0xb3, 0xe7, 0x8a, + 0x02, 0xc1, 0xd0, 0x43, 0x8c, 0x46, 0x92, 0x40, 0x38, 0xf0, 0xbe, 0x86, 0x0c, 0x3b, 0xbe, 0xe5, 0x92, 0x60, 0xcd, + 0x65, 0x8f, 0xa3, 0x01, 0x6d, 0x0e, 0x08, 0x99, 0x2a, 0x58, 0x10, 0xb4, 0x0e, 0x95, 0xf8, 0xee, 0x16, 0x6d, 0xc0, + 0x8d, 0xc8, 0x17, 0xad, 0xb3, 0x05, 0x8d, 0x56, 0x3a, 0x26, 0x84, 0xc3, 0xe0, 0xe2, 0x50, 0xe7, 0x0d, 0x23, 0xb6, + 0x00, 0xdb, 0x34, 0xb7, 0x9c, 0xb3, 0xbb, 0x30, 0xe2, 0x28, 0x95, 0x58, 0x3e, 0x57, 0x6c, 0x46, 0x1c, 0xb7, 0x55, + 0x6f, 0x08, 0xbe, 0xa4, 0x71, 0xd5, 0x7d, 0x91, 0xd9, 0x14, 0x43, 0x1f, 0x2c, 0x34, 0x0e, 0x17, 0x17, 0x09, 0xb0, + 0x1b, 0xa4, 0xba, 0x68, 0x52, 0x23, 0x43, 0x2a, 0x82, 0xa2, 0xc4, 0xac, 0x77, 0xc3, 0xc7, 0x09, 0x51, 0xc9, 0x5a, + 0xfb, 0xf1, 0x6b, 0xfd, 0xb4, 0x4c, 0xfa, 0x96, 0x3e, 0xb0, 0x8b, 0x84, 0x81, 0xea, 0x96, 0x3e, 0x80, 0x09, 0xdf, + 0x5b, 0x90, 0xa6, 0xe8, 0x5b, 0xd0, 0xb5, 0x05, 0x79, 0x3e, 0x7c, 0x88, 0x54, 0xb7, 0xe5, 0x00, 0xb9, 0xf9, 0x16, + 0x2c, 0x8e, 0x20, 0x86, 0x94, 0xee, 0xe2, 0x10, 0x73, 0x63, 0x79, 0xa3, 0x11, 0xc6, 0x76, 0xc3, 0xd1, 0x30, 0x5f, + 0x78, 0xae, 0x7b, 0x50, 0xab, 0x0f, 0x82, 0xec, 0xa6, 0xda, 0xa6, 0x95, 0x0d, 0x3d, 0xd7, 0x0e, 0x5e, 0x38, 0x9d, + 0x41, 0xed, 0x8e, 0x56, 0x02, 0xc9, 0x8e, 0x50, 0xfc, 0x75, 0xf6, 0x6c, 0x63, 0xa4, 0x2d, 0xe0, 0x2d, 0x8c, 0xcf, + 0x71, 0x6c, 0x39, 0x97, 0x7f, 0x8d, 0xea, 0x57, 0x3f, 0x0b, 0x63, 0xcb, 0x92, 0x1a, 0x8d, 0x20, 0x14, 0xba, 0x01, + 0xc7, 0xe8, 0xf7, 0xda, 0x4b, 0xcd, 0x60, 0xc7, 0xc7, 0x34, 0x47, 0x03, 0x81, 0x51, 0x84, 0x5b, 0x97, 0xda, 0x41, + 0xe5, 0x8b, 0x51, 0x15, 0xc3, 0xf1, 0xa0, 0xcb, 0xb4, 0xd0, 0xe8, 0x6d, 0xa5, 0x16, 0xb0, 0xff, 0x96, 0xeb, 0xd3, + 0x19, 0x43, 0xbc, 0x0f, 0xa8, 0x01, 0x89, 0x13, 0x76, 0x76, 0xb8, 0x5a, 0x96, 0xbb, 0x2b, 0x5f, 0x92, 0xfb, 0x77, + 0x86, 0x97, 0x0e, 0xea, 0xd0, 0x64, 0x7f, 0xcd, 0xd7, 0xdd, 0x23, 0xbb, 0xa4, 0xd1, 0xa4, 0xdc, 0x61, 0xe5, 0xfe, + 0xda, 0xbf, 0xbb, 0x12, 0x46, 0x81, 0x8c, 0x22, 0x71, 0x03, 0x46, 0xc9, 0xe3, 0x08, 0x37, 0x3f, 0x3b, 0x6e, 0xc1, + 0x5e, 0x54, 0x0c, 0x36, 0x60, 0xe1, 0x00, 0x65, 0x33, 0x45, 0x28, 0x0e, 0x61, 0xeb, 0xd1, 0x19, 0xde, 0x10, 0x84, + 0x68, 0xeb, 0x4e, 0xcc, 0x84, 0x69, 0x60, 0xd1, 0x26, 0xe0, 0x81, 0x68, 0xf7, 0x95, 0x5a, 0x07, 0xbb, 0xa5, 0xd6, + 0xd9, 0x2e, 0xa9, 0x35, 0x73, 0x4c, 0xba, 0x4f, 0xc8, 0x52, 0xf1, 0x6d, 0x13, 0xc4, 0xb9, 0xea, 0xe2, 0x56, 0x12, + 0x75, 0xa3, 0x1f, 0x93, 0x68, 0x55, 0xeb, 0x8d, 0x19, 0xfb, 0xa1, 0xf8, 0x5b, 0x61, 0x50, 0x84, 0x42, 0x5d, 0x95, + 0x8d, 0x5f, 0x15, 0xb2, 0x71, 0xc6, 0xd5, 0x14, 0x2e, 0x29, 0x82, 0xfa, 0x57, 0xdc, 0xbd, 0x24, 0x77, 0x50, 0xb8, + 0x7d, 0x15, 0x23, 0x55, 0x1c, 0x99, 0x0a, 0x46, 0x43, 0x71, 0x8f, 0x13, 0x5c, 0x46, 0xd9, 0x4b, 0xae, 0x5c, 0xb5, + 0xf0, 0x63, 0x2a, 0xca, 0x41, 0xea, 0x8e, 0x43, 0x96, 0xc5, 0xea, 0xb6, 0x29, 0x3b, 0xb2, 0xa8, 0xaf, 0x95, 0x4d, + 0x22, 0x3d, 0x4e, 0x18, 0x80, 0x85, 0x98, 0xbe, 0xa2, 0xd7, 0x96, 0x36, 0x10, 0x38, 0xc8, 0x06, 0x07, 0xb9, 0xdd, + 0xd2, 0x79, 0x96, 0x2c, 0xa5, 0xd0, 0xc2, 0xab, 0x32, 0x08, 0x84, 0xef, 0xcd, 0xa6, 0xe1, 0x96, 0xc7, 0x4b, 0x9e, + 0xdf, 0xef, 0x20, 0x5e, 0xd4, 0x5c, 0x55, 0x91, 0x8f, 0x27, 0xd3, 0x66, 0x56, 0xb6, 0x58, 0xb5, 0xde, 0x29, 0x13, + 0xe2, 0x6c, 0xb8, 0x8f, 0x49, 0x59, 0x46, 0xcf, 0x6b, 0xf4, 0xc5, 0x77, 0xf9, 0xd6, 0x49, 0x56, 0x11, 0x26, 0xb6, + 0xb0, 0xb3, 0x84, 0xf8, 0xb7, 0xca, 0x90, 0x85, 0x9c, 0x13, 0x64, 0xc0, 0x65, 0x4d, 0xc1, 0x80, 0x60, 0x1c, 0x58, + 0xda, 0x77, 0x3a, 0xa9, 0x22, 0x7d, 0xe9, 0x3f, 0x75, 0xbb, 0xe4, 0xd5, 0xf4, 0xb0, 0x22, 0x14, 0xed, 0xf4, 0xca, + 0x22, 0xf3, 0x96, 0x71, 0x64, 0xf3, 0xd5, 0x62, 0xbc, 0x51, 0x65, 0xab, 0x8a, 0xc8, 0xb5, 0x2e, 0x66, 0x55, 0x3f, + 0x3b, 0x9d, 0x4e, 0xcb, 0x82, 0x46, 0x57, 0x3b, 0x44, 0x61, 0xe1, 0x53, 0xd7, 0x75, 0xab, 0x63, 0xdf, 0x0e, 0x76, + 0x1b, 0xe5, 0xb6, 0x27, 0x8d, 0x23, 0x46, 0xd8, 0xee, 0x82, 0x5f, 0x1d, 0x1c, 0xb9, 0x53, 0x9c, 0xec, 0x92, 0x59, + 0xc4, 0x80, 0x19, 0x43, 0x04, 0x19, 0x5d, 0xa4, 0x7d, 0x9f, 0xa2, 0x0e, 0xc6, 0x51, 0x0e, 0x34, 0x1a, 0x0e, 0xd8, + 0x33, 0x30, 0x15, 0xf1, 0xc4, 0xae, 0x70, 0x35, 0x94, 0x87, 0xd7, 0x84, 0xf7, 0xe2, 0x23, 0x78, 0x50, 0x36, 0x75, + 0x99, 0x36, 0x4e, 0xab, 0xe7, 0xfe, 0xbe, 0x54, 0x4f, 0x83, 0x0b, 0x70, 0x23, 0x14, 0xda, 0x4c, 0x3e, 0x8b, 0xff, + 0x2f, 0xe5, 0xff, 0xaf, 0x96, 0xeb, 0xb2, 0xfd, 0xc8, 0x09, 0x48, 0xb4, 0x8b, 0xd3, 0xc2, 0x46, 0xdd, 0xb4, 0x07, + 0xa4, 0x95, 0xc1, 0x54, 0x55, 0xa0, 0x83, 0x92, 0xbe, 0x94, 0xfd, 0xa7, 0x41, 0xfc, 0x8e, 0x14, 0x33, 0x2c, 0x71, + 0x21, 0x42, 0x2c, 0x72, 0x57, 0xc2, 0x1c, 0xac, 0x97, 0x27, 0xa8, 0x3f, 0x28, 0xed, 0x09, 0xd0, 0xc6, 0xd7, 0xe6, + 0xb6, 0x97, 0xb8, 0xbf, 0xaa, 0xd7, 0x12, 0x1d, 0x03, 0xc8, 0x3c, 0x38, 0x84, 0x68, 0x48, 0xa0, 0x55, 0x36, 0x37, + 0x1b, 0xa5, 0x7c, 0xab, 0xea, 0xd9, 0xc4, 0xc0, 0xb0, 0xbb, 0xe6, 0x2a, 0xac, 0x6f, 0xa1, 0x2d, 0x80, 0xc9, 0xf2, + 0xed, 0x87, 0xcf, 0x36, 0x2c, 0xb1, 0xba, 0x1f, 0x3d, 0x5c, 0x72, 0xdc, 0xbf, 0x36, 0xde, 0x9d, 0x29, 0x3b, 0xff, + 0x28, 0x5f, 0xfc, 0xb6, 0x51, 0xa0, 0x77, 0x55, 0x92, 0xd0, 0x71, 0xa3, 0xef, 0x8e, 0xb9, 0x57, 0xed, 0x45, 0x10, + 0xed, 0x5f, 0x97, 0xac, 0xf7, 0xae, 0x0b, 0x17, 0xc6, 0xde, 0x95, 0xe1, 0xc6, 0x61, 0x96, 0x0b, 0xd9, 0xf0, 0x5b, + 0x45, 0xa0, 0xa8, 0xfa, 0xef, 0xea, 0xd8, 0x8a, 0x51, 0xf9, 0x57, 0x2b, 0x20, 0x3e, 0xf7, 0xca, 0xee, 0xa2, 0x89, + 0x04, 0x8d, 0xfa, 0xb1, 0x76, 0xa2, 0x1d, 0x77, 0xb5, 0x23, 0x57, 0x67, 0x5c, 0xd8, 0x50, 0xef, 0x75, 0x0a, 0xbf, + 0xbc, 0x43, 0x57, 0x3f, 0x3b, 0x9d, 0x89, 0x4b, 0x62, 0x1a, 0x84, 0x21, 0x43, 0x15, 0x60, 0xfe, 0x7b, 0x4b, 0xcb, + 0x6a, 0x16, 0x56, 0xc6, 0x8d, 0x40, 0x3a, 0xe2, 0x11, 0xce, 0x8e, 0x4f, 0x96, 0x7d, 0x3c, 0x1b, 0x6a, 0x21, 0x18, + 0x70, 0xb2, 0x52, 0xfc, 0x04, 0xdc, 0xc1, 0x63, 0xfd, 0xec, 0x14, 0xe2, 0x97, 0x6a, 0x93, 0xa1, 0xfe, 0x5d, 0xe7, + 0x58, 0xf3, 0x7a, 0x77, 0x76, 0xd7, 0x77, 0x6d, 0xcf, 0x39, 0xd4, 0x5c, 0xe7, 0xc8, 0xee, 0x38, 0xc7, 0x5a, 0xc7, + 0xe9, 0xc1, 0xbf, 0xbe, 0xe7, 0xbc, 0xd2, 0x5c, 0x78, 0xd2, 0x3c, 0xa7, 0x8b, 0xff, 0x76, 0x9c, 0xe3, 0xbb, 0x2e, + 0xbb, 0xe9, 0x89, 0xf4, 0x8e, 0xaa, 0x8c, 0x02, 0x7c, 0x39, 0xf4, 0x83, 0xb3, 0xd3, 0x55, 0x4a, 0xb5, 0xf5, 0x50, + 0x7f, 0xa5, 0x6b, 0xf3, 0x84, 0x4e, 0x87, 0xfa, 0x53, 0xa2, 0x94, 0x7a, 0x27, 0x8d, 0xc5, 0x9d, 0xe3, 0xc6, 0xe2, + 0xee, 0x51, 0x63, 0xf1, 0x61, 0xaf, 0x5c, 0x7c, 0x30, 0x63, 0xaf, 0x94, 0xf4, 0xa1, 0x0b, 0x92, 0x25, 0xc1, 0xda, + 0xf0, 0x34, 0x40, 0xd7, 0x36, 0xfc, 0x73, 0xdc, 0x31, 0x65, 0xab, 0x31, 0xb4, 0x92, 0xd0, 0x38, 0x3e, 0xd1, 0xbc, + 0xa3, 0x6f, 0x3a, 0x47, 0x3e, 0xd4, 0x83, 0x64, 0xb7, 0xf0, 0x77, 0xd7, 0x3d, 0xf1, 0x5d, 0x0d, 0x1a, 0x7a, 0xf0, + 0xdf, 0xbc, 0xd7, 0xf1, 0xd9, 0x83, 0x0b, 0xef, 0x3f, 0x78, 0xc7, 0xa9, 0x6b, 0x7b, 0xf0, 0xdf, 0xcf, 0x52, 0xe5, + 0x0e, 0x0a, 0x7f, 0xb5, 0xdf, 0x43, 0x57, 0xeb, 0x9e, 0xcc, 0x3b, 0xce, 0xab, 0xbb, 0x63, 0xe7, 0x64, 0xee, 0x1d, + 0x7f, 0x60, 0x4f, 0xa1, 0xdd, 0x71, 0x5e, 0xc1, 0xdf, 0x87, 0xae, 0x3b, 0xb7, 0x3d, 0xe7, 0xe4, 0xae, 0xeb, 0x74, + 0x43, 0xfb, 0xc8, 0x39, 0x81, 0xbf, 0x9f, 0x01, 0xbc, 0x00, 0x57, 0x9e, 0x9d, 0x58, 0x83, 0x8d, 0x51, 0xb1, 0xdf, + 0x50, 0x3f, 0xd2, 0x39, 0xd4, 0x7a, 0x87, 0xdf, 0x9c, 0xdc, 0xd9, 0x87, 0x73, 0xaf, 0x73, 0x67, 0xb7, 0xfe, 0xfc, + 0x00, 0x90, 0xdf, 0xbe, 0x70, 0x00, 0x46, 0x4c, 0x47, 0xf4, 0xbb, 0x91, 0x75, 0xd9, 0x26, 0x46, 0x7f, 0xbf, 0x5b, + 0x8c, 0xfe, 0xf5, 0x6a, 0x1f, 0x31, 0xfa, 0xfb, 0xcf, 0x2e, 0x46, 0xbf, 0xac, 0x5a, 0x71, 0xbf, 0xaf, 0xa6, 0x4d, + 0xf8, 0x71, 0x53, 0x25, 0x92, 0x03, 0x62, 0x5c, 0x5f, 0xad, 0x6e, 0x20, 0xe2, 0xd5, 0xfb, 0x78, 0xf8, 0xf5, 0xaa, + 0x64, 0xa2, 0x14, 0x03, 0x06, 0x78, 0x1f, 0x33, 0x0c, 0xf0, 0xa7, 0xd5, 0x10, 0xec, 0x22, 0xf8, 0xad, 0x19, 0x4c, + 0xec, 0x39, 0x09, 0xa7, 0xf2, 0xc6, 0x85, 0x92, 0x01, 0x16, 0x83, 0xdd, 0x3d, 0x5c, 0x26, 0xa0, 0xac, 0x59, 0x2d, + 0xa2, 0xb4, 0x7f, 0xe4, 0x02, 0x9a, 0xef, 0x4c, 0x93, 0xbc, 0xd2, 0xd8, 0x11, 0x31, 0xc2, 0x3e, 0x72, 0xcb, 0xfc, + 0xd6, 0xf7, 0x68, 0xb2, 0xd6, 0xdc, 0xbb, 0x57, 0xef, 0x57, 0x03, 0x5b, 0x10, 0x61, 0xd2, 0x07, 0xc4, 0x46, 0xd3, + 0xfb, 0xb2, 0xe1, 0x58, 0xc5, 0x54, 0xb0, 0x7d, 0xa4, 0x30, 0x92, 0x6a, 0x7b, 0xaf, 0x6c, 0x78, 0xb6, 0x6b, 0x9a, + 0x0d, 0x9f, 0x2f, 0x35, 0xdf, 0x62, 0xf5, 0x26, 0x3b, 0xae, 0x82, 0xaa, 0x92, 0xf4, 0xaf, 0x11, 0x20, 0x05, 0xed, + 0x59, 0x98, 0xc6, 0x15, 0x84, 0x8f, 0xab, 0xe1, 0x6d, 0xec, 0x2a, 0xef, 0x4a, 0x7d, 0xaa, 0xe6, 0x74, 0x2f, 0x36, + 0x48, 0x0f, 0x06, 0x3f, 0x03, 0x61, 0xc3, 0xef, 0xe3, 0x71, 0xac, 0xc2, 0x79, 0xa3, 0xf4, 0xcb, 0x48, 0xed, 0x7c, + 0xee, 0x6d, 0xea, 0xa4, 0x4d, 0xab, 0x21, 0xad, 0x47, 0x17, 0xe2, 0x8e, 0xc6, 0xcf, 0x33, 0xb3, 0xd5, 0x9c, 0x99, + 0x16, 0xa3, 0x65, 0xee, 0xb6, 0xce, 0x44, 0xbd, 0xa7, 0xb0, 0x89, 0x2d, 0xfe, 0xa0, 0xfa, 0x7f, 0x6f, 0xa6, 0x90, + 0xa0, 0xbd, 0x8f, 0x44, 0x84, 0x42, 0x41, 0x75, 0xd0, 0xc6, 0x76, 0xb0, 0xc5, 0xfc, 0x43, 0xed, 0x98, 0x77, 0x82, + 0xb6, 0xba, 0xdb, 0x2c, 0x46, 0xa4, 0x6b, 0xc3, 0xa6, 0xa4, 0x40, 0xf5, 0x7a, 0xc7, 0x96, 0x77, 0x64, 0x39, 0xc7, + 0x3d, 0x33, 0x17, 0x07, 0x4e, 0xed, 0xb2, 0x04, 0x10, 0x30, 0xd9, 0x95, 0xc3, 0x0c, 0xa2, 0x20, 0x0b, 0x48, 0x98, + 0x03, 0xaa, 0x2f, 0xd3, 0xbc, 0x7f, 0x5b, 0xa5, 0x19, 0xcc, 0x51, 0x90, 0x64, 0x68, 0xae, 0x6c, 0x8f, 0x69, 0x76, + 0x4f, 0x69, 0xd4, 0xa2, 0xca, 0xad, 0x5a, 0x3f, 0xff, 0x76, 0xb6, 0xa0, 0x39, 0xb3, 0xb3, 0x18, 0x67, 0x11, 0xdf, + 0x1f, 0xc2, 0x54, 0x37, 0x1f, 0x59, 0x3f, 0xb7, 0x21, 0xdc, 0xbf, 0xed, 0x46, 0xb8, 0x19, 0xdd, 0x07, 0xe1, 0xfe, + 0xed, 0xb3, 0x23, 0xdc, 0x9f, 0x55, 0x84, 0x5b, 0xf2, 0x54, 0x29, 0x64, 0xa2, 0x3f, 0xe0, 0xb3, 0x01, 0xf1, 0xc6, + 0x5f, 0xea, 0x07, 0x8c, 0xbc, 0xd4, 0x95, 0x3c, 0xd0, 0x1f, 0x4a, 0x89, 0xad, 0x90, 0x65, 0xc7, 0xd0, 0xc3, 0x2c, + 0x89, 0x0e, 0xe4, 0x48, 0x76, 0x85, 0xfb, 0x21, 0xf4, 0x79, 0x11, 0x65, 0xa1, 0xf3, 0x9e, 0xb3, 0x25, 0xa0, 0x82, + 0xf8, 0x3a, 0x4e, 0x16, 0x04, 0x83, 0x22, 0xea, 0x98, 0x10, 0x13, 0x1e, 0x5c, 0x70, 0x18, 0xf3, 0xe3, 0x68, 0x22, + 0xe5, 0xe8, 0x74, 0x78, 0xcd, 0xe8, 0x41, 0xfd, 0x81, 0x92, 0x44, 0xb7, 0xd8, 0x6b, 0x58, 0xdc, 0x17, 0x5d, 0xf7, + 0x45, 0xe7, 0xf0, 0xc5, 0x91, 0x0b, 0xff, 0xf3, 0x68, 0x37, 0xb7, 0x78, 0xc5, 0x45, 0x1c, 0x41, 0x4e, 0x1e, 0x51, + 0xb3, 0xad, 0xda, 0x3d, 0xa5, 0xb7, 0x45, 0xad, 0xe3, 0xe6, 0x4a, 0x13, 0xf2, 0x50, 0xd4, 0x69, 0xac, 0x31, 0x8f, + 0x57, 0xca, 0xb0, 0x1a, 0x46, 0x13, 0x44, 0x2b, 0x90, 0x0c, 0x29, 0x35, 0xd4, 0xd7, 0x7c, 0xba, 0xc5, 0xbc, 0x68, + 0x37, 0xbf, 0x29, 0x12, 0x7f, 0x89, 0x04, 0x44, 0x3b, 0x21, 0xc8, 0x85, 0xea, 0x2e, 0xa6, 0x0d, 0xc0, 0x68, 0x6f, + 0x1a, 0xa4, 0xdd, 0x14, 0x0b, 0x44, 0xd8, 0x02, 0x65, 0xc9, 0x2a, 0xf2, 0x0d, 0xfc, 0x49, 0xc6, 0xa9, 0x11, 0x1c, + 0x40, 0x4c, 0x5e, 0xfc, 0xb0, 0x89, 0xab, 0x46, 0xce, 0xdc, 0x22, 0x4b, 0x4a, 0x24, 0x56, 0x85, 0xbc, 0xc8, 0xac, + 0x84, 0xe5, 0x56, 0xc6, 0xa5, 0xb5, 0x87, 0xe4, 0x85, 0x6c, 0xf8, 0x22, 0xb3, 0x20, 0xbf, 0x31, 0x2c, 0xf7, 0xf3, + 0xe7, 0xac, 0x16, 0x64, 0x1c, 0x65, 0xd3, 0x3a, 0xf7, 0x65, 0x96, 0x42, 0x5d, 0x23, 0xb3, 0x58, 0xc7, 0x2c, 0x85, + 0x7d, 0xdf, 0x8a, 0x5f, 0xbe, 0x3c, 0x1b, 0x7a, 0x26, 0xcf, 0x97, 0x5b, 0x4a, 0xee, 0x76, 0xb9, 0x9f, 0x6a, 0xdc, + 0x6c, 0x74, 0xda, 0x5a, 0x06, 0xd1, 0x4c, 0x68, 0xa6, 0x25, 0xf6, 0x82, 0x64, 0x2b, 0x4c, 0x05, 0x46, 0x84, 0x8a, + 0x5a, 0xd4, 0xb9, 0xa3, 0x09, 0xe4, 0xfa, 0x1d, 0xea, 0x5d, 0xc7, 0x75, 0x5c, 0x5d, 0x36, 0x9c, 0x06, 0xb3, 0xe1, + 0x26, 0xce, 0x08, 0xa4, 0xad, 0x0a, 0xe3, 0x19, 0x78, 0x7e, 0x64, 0x41, 0x16, 0x42, 0x0e, 0x24, 0x70, 0x01, 0x59, + 0x30, 0xae, 0x31, 0xe7, 0xf6, 0xb8, 0x24, 0xb9, 0xc5, 0x3c, 0x98, 0xc2, 0xe9, 0x0b, 0x23, 0xcb, 0x7c, 0x07, 0x97, + 0xa1, 0xa1, 0x1b, 0x90, 0x85, 0x95, 0x26, 0xa9, 0xad, 0xda, 0xb7, 0xf7, 0x35, 0x68, 0x63, 0xea, 0x7c, 0x12, 0xd3, + 0x84, 0x2c, 0x20, 0x5d, 0xc0, 0x26, 0xb7, 0x38, 0xa6, 0xd5, 0x39, 0xaa, 0xd5, 0xbc, 0x57, 0x47, 0x96, 0xd6, 0xf1, + 0x2c, 0xcd, 0x05, 0x74, 0xab, 0xe7, 0xd6, 0x26, 0xbf, 0x19, 0xec, 0x52, 0xd1, 0x31, 0xfc, 0xf2, 0x94, 0xcd, 0x83, + 0x29, 0xe7, 0xb8, 0xf0, 0x33, 0x63, 0x41, 0x3d, 0x0d, 0x25, 0x90, 0x7f, 0xc0, 0xc4, 0xf4, 0x57, 0x74, 0x9d, 0x99, + 0x98, 0x23, 0x88, 0x57, 0x09, 0xcc, 0x0d, 0xba, 0xa6, 0x05, 0x91, 0x16, 0x7c, 0xfa, 0x64, 0x04, 0x60, 0x7e, 0x3f, + 0x54, 0xe0, 0x03, 0xcf, 0x66, 0x09, 0x60, 0x41, 0xa1, 0x58, 0x42, 0x60, 0x81, 0x6f, 0x0c, 0xfc, 0x5b, 0x14, 0x8b, + 0x1f, 0x5c, 0xb1, 0xe7, 0x84, 0x24, 0x9a, 0x01, 0x4a, 0x23, 0xd1, 0xac, 0x66, 0x40, 0xc0, 0xbc, 0xeb, 0x2a, 0xa5, + 0x45, 0x57, 0x85, 0x72, 0x3f, 0xfd, 0xea, 0xe1, 0x8a, 0xe5, 0x40, 0x33, 0x74, 0xb8, 0xe5, 0xd0, 0x15, 0xac, 0xd0, + 0x3d, 0xbc, 0x1c, 0x7e, 0x71, 0xba, 0xa0, 0x19, 0x61, 0x82, 0x4b, 0x60, 0xf1, 0x80, 0x1c, 0xd0, 0x7c, 0x91, 0xbf, + 0x98, 0x31, 0x78, 0x13, 0x7a, 0x17, 0xf8, 0x9c, 0x4f, 0xb3, 0x34, 0x7e, 0x4f, 0xd9, 0x68, 0xa3, 0x34, 0xf4, 0x2c, + 0x66, 0x22, 0xeb, 0x13, 0x0c, 0xfd, 0x39, 0x8c, 0x62, 0xfd, 0xec, 0x0b, 0xe9, 0x4d, 0xd4, 0xb6, 0x08, 0x90, 0x88, + 0xf4, 0x3a, 0xa1, 0xe1, 0xdf, 0x87, 0x5f, 0xc0, 0xc5, 0xfd, 0xc5, 0x8d, 0x6e, 0x0e, 0x32, 0x07, 0xf9, 0x98, 0x2f, + 0x1a, 0x12, 0x72, 0x22, 0x8f, 0xca, 0x99, 0xcd, 0xae, 0xc2, 0x6c, 0xc2, 0xef, 0xdd, 0xac, 0x2b, 0xb8, 0xa9, 0x3e, + 0x84, 0xf4, 0x0c, 0xb8, 0x8b, 0x4d, 0x89, 0xe7, 0xf4, 0x06, 0xc8, 0xa0, 0x8e, 0x43, 0xe2, 0xdf, 0x0a, 0x0e, 0x55, + 0x7d, 0xd8, 0x87, 0x17, 0x95, 0x94, 0x5d, 0xe3, 0x5e, 0xc6, 0xad, 0xbc, 0xc1, 0x2f, 0xe3, 0xa7, 0xee, 0xe7, 0x41, + 0x26, 0x99, 0x61, 0x7c, 0xc8, 0xd1, 0x37, 0x16, 0xc6, 0x57, 0xb0, 0x3f, 0xc0, 0xa0, 0x7a, 0x27, 0xdf, 0xf4, 0xee, + 0x3c, 0x77, 0xde, 0xf1, 0x1c, 0x60, 0x73, 0xe6, 0x5d, 0xe7, 0x38, 0xb4, 0xbb, 0xce, 0x31, 0xfc, 0x7d, 0x00, 0xd6, + 0xcb, 0xee, 0x38, 0x87, 0x1f, 0xbc, 0x4e, 0x68, 0x9f, 0x38, 0xc7, 0xf0, 0x77, 0xc9, 0x5a, 0xfd, 0x88, 0x4c, 0x0f, + 0x30, 0x3c, 0x5f, 0x94, 0xb0, 0x80, 0xf2, 0x5b, 0x6a, 0x11, 0xac, 0xd2, 0xf5, 0xd6, 0xa0, 0x89, 0x00, 0x94, 0xa1, + 0x5b, 0x22, 0x4a, 0x60, 0x3a, 0x30, 0xd2, 0x21, 0xcf, 0x6d, 0x21, 0x0c, 0x32, 0x84, 0xd7, 0xa4, 0xc8, 0xbc, 0xd0, + 0x78, 0x8c, 0x78, 0x9b, 0xe6, 0x30, 0xfb, 0x22, 0x69, 0x1a, 0x53, 0x5d, 0xfc, 0x79, 0x89, 0xf1, 0x71, 0xa8, 0x59, + 0xc3, 0x4a, 0x45, 0xe2, 0xce, 0x7c, 0xf7, 0xc0, 0xd1, 0x6f, 0x94, 0xca, 0xc4, 0x51, 0x9f, 0xb5, 0x6f, 0xae, 0xce, + 0x90, 0xbd, 0xff, 0xd2, 0x7e, 0x30, 0x5f, 0x32, 0xeb, 0x47, 0x44, 0xd8, 0x9d, 0x04, 0x89, 0x1c, 0x9e, 0x82, 0xa2, + 0xbd, 0xe6, 0xfc, 0x04, 0x26, 0x64, 0xd8, 0xb9, 0x00, 0x2a, 0xf9, 0x8e, 0x84, 0x8a, 0xe9, 0x85, 0xd2, 0xf2, 0x89, + 0xc4, 0xfc, 0xcf, 0x9f, 0x17, 0x83, 0xb3, 0x2b, 0xe3, 0x3e, 0xf5, 0x7a, 0x70, 0xed, 0xf6, 0x68, 0x77, 0xab, 0x15, + 0xd0, 0xee, 0x10, 0xcd, 0x45, 0x3c, 0x49, 0xa1, 0xe9, 0x17, 0x3a, 0xc6, 0x56, 0x53, 0xa4, 0x9a, 0x86, 0x11, 0xc2, + 0x5b, 0x57, 0x58, 0x1d, 0xdd, 0x1c, 0xa4, 0xfb, 0x84, 0xa5, 0xe6, 0xbc, 0x98, 0x0e, 0xa0, 0xd9, 0x32, 0x8f, 0x1d, + 0x2e, 0x8d, 0xff, 0xee, 0x49, 0xa0, 0x7b, 0x11, 0x68, 0xf8, 0x2a, 0xa7, 0xb5, 0xe4, 0x6e, 0x22, 0xef, 0x55, 0x76, + 0xa1, 0xd2, 0xf4, 0x5c, 0x87, 0x22, 0x48, 0xbd, 0x86, 0xd9, 0x16, 0xa5, 0x79, 0x93, 0xbc, 0x2d, 0x8a, 0x02, 0x2b, + 0x80, 0xc8, 0xef, 0x86, 0x70, 0x75, 0x32, 0x9f, 0x3f, 0x6f, 0xbd, 0x84, 0x98, 0x3a, 0x59, 0x4d, 0x3a, 0xab, 0xab, + 0xf8, 0x4d, 0x57, 0x51, 0x8c, 0xec, 0x17, 0xb1, 0x86, 0xb0, 0xca, 0x62, 0x7b, 0x0f, 0x7f, 0x8e, 0x29, 0xc9, 0x1c, + 0xae, 0x07, 0x31, 0x94, 0xcb, 0xdd, 0xf2, 0x68, 0x17, 0xec, 0xb1, 0x78, 0x18, 0x2d, 0x1e, 0x33, 0xee, 0xd9, 0xe6, + 0xc3, 0x8a, 0xfb, 0x21, 0x43, 0x1f, 0x9f, 0xdc, 0x22, 0x06, 0xca, 0xbb, 0x8c, 0xb0, 0x40, 0x19, 0xea, 0x95, 0x1b, + 0x67, 0x44, 0xa4, 0x38, 0x02, 0xba, 0x7c, 0xd0, 0xa8, 0x30, 0x54, 0x7c, 0x95, 0xcf, 0xde, 0x5d, 0x7d, 0xa9, 0xf1, + 0xfd, 0xcf, 0xf4, 0x5b, 0xc8, 0xc8, 0xb0, 0x5c, 0x17, 0x43, 0x96, 0xeb, 0x42, 0xe3, 0x59, 0x67, 0x20, 0x63, 0x44, + 0x7e, 0xc0, 0x20, 0xa8, 0x6b, 0x34, 0xf2, 0x99, 0xd6, 0x6f, 0xb1, 0x0a, 0xb3, 0x60, 0x49, 0x92, 0xec, 0x00, 0x9a, + 0xda, 0x80, 0xe4, 0xf4, 0x36, 0x0f, 0x66, 0xa6, 0x38, 0x14, 0x42, 0xb5, 0x2c, 0x12, 0x9a, 0xc3, 0x69, 0x10, 0x4a, + 0xc5, 0xa1, 0xf8, 0x00, 0xf1, 0x7d, 0xba, 0xcc, 0x86, 0x3a, 0x59, 0x42, 0xce, 0x13, 0x0c, 0x63, 0x7a, 0x10, 0xfb, + 0x19, 0xcd, 0xec, 0x34, 0x4b, 0x28, 0x59, 0xe8, 0x32, 0x64, 0x67, 0xbd, 0xbf, 0x74, 0x35, 0x5e, 0x04, 0x99, 0x8c, + 0x79, 0xc7, 0x26, 0x08, 0x2a, 0x3c, 0x18, 0x22, 0x84, 0x33, 0x60, 0x20, 0xbc, 0x8c, 0x67, 0x95, 0x1d, 0x55, 0x50, + 0x2e, 0xe7, 0x4a, 0x5c, 0x09, 0x10, 0x8e, 0xfa, 0x71, 0xf8, 0x91, 0x7b, 0x5d, 0xcb, 0xd0, 0x7c, 0xfa, 0xd9, 0x29, + 0x67, 0x6f, 0x35, 0x0c, 0x14, 0xa0, 0xf7, 0x5c, 0x08, 0x36, 0xdb, 0xe6, 0x8f, 0x7d, 0xc0, 0x2b, 0xab, 0x91, 0x15, + 0xfa, 0x97, 0x7c, 0x2c, 0x57, 0x40, 0x08, 0x95, 0x54, 0xbc, 0x73, 0xef, 0x4c, 0x3a, 0x00, 0xe1, 0xa8, 0x90, 0x56, + 0xfa, 0xf4, 0xe9, 0xf5, 0xe8, 0x9f, 0xff, 0x80, 0x14, 0x04, 0x73, 0x4f, 0x78, 0x41, 0x5f, 0xab, 0xb5, 0x38, 0xf5, + 0x69, 0x8d, 0x50, 0xbd, 0x4f, 0x27, 0x22, 0x2a, 0x8c, 0xd8, 0x5a, 0xf9, 0xe8, 0x46, 0x44, 0x6c, 0x82, 0x34, 0x23, + 0xa6, 0xf0, 0xd5, 0x1e, 0xc1, 0xf2, 0x8e, 0x44, 0x88, 0x00, 0xed, 0xa7, 0xf5, 0x57, 0xc7, 0x9a, 0x5e, 0xe4, 0x0e, + 0x68, 0xd0, 0x41, 0xb3, 0x3d, 0x74, 0x76, 0x4a, 0xb8, 0xf0, 0x15, 0xc8, 0x8f, 0xb4, 0x7f, 0x00, 0xd3, 0x9c, 0xc7, + 0x0b, 0xea, 0x04, 0xf1, 0xc1, 0x3d, 0x1d, 0xdb, 0x64, 0x19, 0x30, 0xf9, 0x32, 0xca, 0xdd, 0x34, 0x46, 0xf9, 0x49, + 0x05, 0x2d, 0xa3, 0xaf, 0xf3, 0x02, 0x94, 0x71, 0x01, 0x28, 0xf8, 0x49, 0xce, 0xca, 0x71, 0xf8, 0x1c, 0x91, 0x17, + 0xa2, 0x8c, 0xe5, 0xcf, 0x59, 0x38, 0x3d, 0x11, 0x39, 0xaf, 0x78, 0xb0, 0xe3, 0xe9, 0x54, 0x8d, 0x9d, 0xe7, 0x94, + 0xbf, 0x2f, 0xa1, 0x52, 0xec, 0xd9, 0x78, 0xc9, 0xbe, 0x54, 0xff, 0x84, 0xfc, 0x09, 0xb1, 0x40, 0x78, 0x98, 0x45, + 0x38, 0xcf, 0xb5, 0x18, 0x7c, 0x12, 0x24, 0x4f, 0x59, 0x25, 0x8e, 0x28, 0xaa, 0xd1, 0xd9, 0x5b, 0x48, 0x93, 0x27, + 0xc3, 0x21, 0xc3, 0x63, 0x55, 0x74, 0x06, 0x50, 0x6a, 0xc8, 0x91, 0x01, 0x93, 0xcd, 0xa0, 0xa1, 0xcd, 0x3c, 0xb8, + 0xb0, 0x51, 0x75, 0x3a, 0xf5, 0x31, 0x1e, 0x10, 0xb1, 0xbf, 0x4a, 0x3b, 0x10, 0x76, 0x16, 0x5f, 0x58, 0x40, 0xe0, + 0xa2, 0x9f, 0x0a, 0x1e, 0xd7, 0xfe, 0xc0, 0x50, 0xb6, 0x1d, 0x92, 0x87, 0x58, 0xd1, 0xac, 0x73, 0x27, 0xfb, 0x4b, + 0x2c, 0xbd, 0x12, 0xce, 0x6d, 0xb5, 0x93, 0x24, 0xb3, 0x00, 0xd4, 0x4f, 0x93, 0x1a, 0xb6, 0x7f, 0xd7, 0x61, 0x52, + 0xeb, 0x96, 0x27, 0x83, 0xd8, 0x31, 0x2f, 0x0e, 0x5a, 0xe9, 0x25, 0x9e, 0xfb, 0xfc, 0xf4, 0x00, 0xe6, 0x07, 0x81, + 0x01, 0x4a, 0x94, 0x51, 0x60, 0x42, 0xf4, 0x01, 0x92, 0x32, 0xeb, 0x80, 0x8b, 0x89, 0x20, 0xea, 0x90, 0x73, 0x94, + 0x41, 0x3e, 0x4b, 0x55, 0xea, 0xc4, 0x8a, 0xdb, 0x4c, 0xe5, 0xed, 0xce, 0xc0, 0xf1, 0xa7, 0x15, 0xa6, 0xdf, 0xc8, + 0x07, 0x19, 0x15, 0x7e, 0xb7, 0x97, 0x59, 0x8b, 0x6b, 0x6e, 0x5b, 0x15, 0x46, 0xb0, 0x6e, 0xa9, 0x50, 0xec, 0xe3, + 0x6d, 0xb5, 0x0a, 0xd2, 0x48, 0x56, 0x5b, 0x12, 0x43, 0x7f, 0x8a, 0x3b, 0xbe, 0x56, 0x1b, 0x4b, 0xa1, 0xde, 0x65, + 0x36, 0x84, 0xaa, 0x42, 0xd8, 0x4e, 0x96, 0x4b, 0x56, 0xd9, 0x1c, 0x9c, 0x1e, 0x30, 0xbe, 0xf3, 0x8c, 0xed, 0xb0, + 0xb3, 0x53, 0xb0, 0x2e, 0x64, 0x8b, 0x4e, 0x96, 0x4b, 0xbe, 0xa4, 0xec, 0x17, 0x7b, 0x73, 0x30, 0xcf, 0x16, 0xe1, + 0xd9, 0xff, 0x01, 0xff, 0xd7, 0x9f, 0x05, 0x1b, 0x5f, 0x03, 0x00}; } // namespace web_server } // namespace esphome From bd8ccde8625752160f904fe4847cef6443aefebb Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 8 May 2024 13:22:04 +1200 Subject: [PATCH 1387/2101] Bump version to 2024.5.0b1 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index c0d27337d6..7996a7a24a 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.5.0-dev" +__version__ = "2024.5.0b1" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From b7c6125a0bbd79c9bc5c07cde453cd95354ecd6b Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 8 May 2024 13:22:05 +1200 Subject: [PATCH 1388/2101] Bump version to 2024.6.0-dev --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index c0d27337d6..dba974610a 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.5.0-dev" +__version__ = "2024.6.0-dev" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 7764ab2411a4498dbb7171cf54f2565db0a9a617 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 8 May 2024 16:17:45 +1200 Subject: [PATCH 1389/2101] [github] Upgrade to actions/{upload,download}-artifact v4 (#6698) --- .github/actions/build-image/action.yaml | 16 ---------------- .github/workflows/release.yml | 16 +++++++++++++--- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/.github/actions/build-image/action.yaml b/.github/actions/build-image/action.yaml index 838bc362a1..87ea28fd20 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -57,14 +57,6 @@ runs: digest="${{ steps.build-ghcr.outputs.digest }}" touch "/tmp/digests/${{ inputs.target }}/ghcr/${digest#sha256:}" - - name: Upload ghcr digest - uses: actions/upload-artifact@v3.1.3 - with: - name: digests-${{ inputs.target }}-ghcr - path: /tmp/digests/${{ inputs.target }}/ghcr/* - if-no-files-found: error - retention-days: 1 - - name: Build and push to dockerhub by digest id: build-dockerhub uses: docker/build-push-action@v5.3.0 @@ -87,11 +79,3 @@ runs: mkdir -p /tmp/digests/${{ inputs.target }}/dockerhub digest="${{ steps.build-dockerhub.outputs.digest }}" touch "/tmp/digests/${{ inputs.target }}/dockerhub/${digest#sha256:}" - - - name: Upload dockerhub digest - uses: actions/upload-artifact@v3.1.3 - with: - name: digests-${{ inputs.target }}-dockerhub - path: /tmp/digests/${{ inputs.target }}/dockerhub/* - if-no-files-found: error - retention-days: 1 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6d91d00b85..5002f041e1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -132,6 +132,13 @@ jobs: suffix: lint version: ${{ needs.init.outputs.tag }} + - name: Upload digests + uses: actions/upload-artifact@v4.3.3 + with: + name: digests-${{ matrix.platform }} + path: /tmp/digests + retention-days: 1 + deploy-manifest: name: Publish ESPHome ${{ matrix.image.title }} to ${{ matrix.registry }} runs-on: ubuntu-latest @@ -160,11 +167,14 @@ jobs: - dockerhub steps: - uses: actions/checkout@v4.1.5 + - name: Download digests - uses: actions/download-artifact@v3.0.2 + uses: actions/download-artifact@v4.1.7 with: - name: digests-${{ matrix.image.target }}-${{ matrix.registry }} + pattern: digests-* path: /tmp/digests + merge-multiple: true + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3.3.0 @@ -195,7 +205,7 @@ jobs: done - name: Create manifest list and push - working-directory: /tmp/digests + working-directory: /tmp/digests/${{ matrix.image.target }}/${{ matrix.registry }} run: | docker buildx imagetools create $(jq -Rcnr 'inputs | . / "," | map("-t " + .) | join(" ")' <<< "${{ steps.tags.outputs.tags}}") \ $(printf '${{ steps.tags.outputs.image }}@sha256:%s ' *) From e48d02495b65fcef806cbd07da24a928e7e646bc Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Wed, 8 May 2024 21:05:24 +0200 Subject: [PATCH 1390/2101] [nextion] Replace flags to `USE_ARDUINO` (#6700) --- esphome/components/nextion/nextion.h | 10 +++++----- esphome/components/nextion/nextion_upload_arduino.cpp | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/esphome/components/nextion/nextion.h b/esphome/components/nextion/nextion.h index 6435e2b4e2..dfa74f644d 100644 --- a/esphome/components/nextion/nextion.h +++ b/esphome/components/nextion/nextion.h @@ -12,7 +12,7 @@ #include "esphome/components/display/display_color_utils.h" #ifdef USE_NEXTION_TFT_UPLOAD -#ifdef ARDUINO +#ifdef USE_ARDUINO #ifdef USE_ESP32 #include #endif // USE_ESP32 @@ -22,7 +22,7 @@ #endif // USE_ESP8266 #elif defined(USE_ESP_IDF) #include -#endif // ARDUINO vs ESP-IDF +#endif // ARDUINO vs USE_ESP_IDF #endif // USE_NEXTION_TFT_UPLOAD namespace esphome { @@ -987,7 +987,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe #ifdef USE_NEXTION_TFT_UPLOAD /** - * Set the tft file URL. https seems problematic with arduino.. + * Set the tft file URL. https seems problematic with Arduino.. */ void set_tft_url(const std::string &tft_url) { this->tft_url_ = tft_url; } @@ -1190,7 +1190,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe uint32_t original_baud_rate_ = 0; bool upload_first_chunk_sent_ = false; -#ifdef ARDUINO +#ifdef USE_ARDUINO /** * will request chunk_size chunks from the web server * and send each to the nextion @@ -1208,7 +1208,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * @return position of last byte transferred, -1 for failure. */ int upload_by_chunks_(esp_http_client_handle_t http_client, uint32_t &range_start); -#endif // ARDUINO vs USE_ESP_IDF +#endif // USE_ARDUINO vs USE_ESP_IDF /** * Ends the upload process, restart Nextion and, if successful, diff --git a/esphome/components/nextion/nextion_upload_arduino.cpp b/esphome/components/nextion/nextion_upload_arduino.cpp index b199db91b7..1187c77c8e 100644 --- a/esphome/components/nextion/nextion_upload_arduino.cpp +++ b/esphome/components/nextion/nextion_upload_arduino.cpp @@ -1,7 +1,7 @@ #include "nextion.h" #ifdef USE_NEXTION_TFT_UPLOAD -#ifdef ARDUINO +#ifdef USE_ARDUINO #include "esphome/core/application.h" #include "esphome/core/defines.h" @@ -383,5 +383,5 @@ WiFiClient *Nextion::get_wifi_client_() { } // namespace nextion } // namespace esphome -#endif // ARDUINO +#endif // USE_ARDUINO #endif // USE_NEXTION_TFT_UPLOAD From 487e171443054d1613cdefb573a336c98012f427 Mon Sep 17 00:00:00 2001 From: Mat931 <49403702+Mat931@users.noreply.github.com> Date: Wed, 8 May 2024 21:58:40 +0000 Subject: [PATCH 1391/2101] [remote_receiver, remote_transmitter] Improve error messages on the ESP32 (#6701) --- esphome/components/remote_receiver/remote_receiver.h | 1 + .../remote_receiver/remote_receiver_esp32.cpp | 11 ++++++++++- .../remote_transmitter/remote_transmitter.h | 1 + .../remote_transmitter/remote_transmitter_esp32.cpp | 9 ++++++++- 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/esphome/components/remote_receiver/remote_receiver.h b/esphome/components/remote_receiver/remote_receiver.h index a1db671e5c..773f8cf636 100644 --- a/esphome/components/remote_receiver/remote_receiver.h +++ b/esphome/components/remote_receiver/remote_receiver.h @@ -58,6 +58,7 @@ class RemoteReceiverComponent : public remote_base::RemoteReceiverBase, void decode_rmt_(rmt_item32_t *item, size_t len); RingbufHandle_t ringbuf_; esp_err_t error_code_{ESP_OK}; + std::string error_string_{""}; #endif #if defined(USE_ESP8266) || defined(USE_LIBRETINY) diff --git a/esphome/components/remote_receiver/remote_receiver_esp32.cpp b/esphome/components/remote_receiver/remote_receiver_esp32.cpp index c0bfb0222f..91295871e2 100644 --- a/esphome/components/remote_receiver/remote_receiver_esp32.cpp +++ b/esphome/components/remote_receiver/remote_receiver_esp32.cpp @@ -29,6 +29,7 @@ void RemoteReceiverComponent::setup() { esp_err_t error = rmt_config(&rmt); if (error != ESP_OK) { this->error_code_ = error; + this->error_string_ = "in rmt_config"; this->mark_failed(); return; } @@ -36,18 +37,25 @@ void RemoteReceiverComponent::setup() { error = rmt_driver_install(this->channel_, this->buffer_size_, 0); if (error != ESP_OK) { this->error_code_ = error; + if (error == ESP_ERR_INVALID_STATE) { + this->error_string_ = str_sprintf("RMT channel %i is already in use by another component", this->channel_); + } else { + this->error_string_ = "in rmt_driver_install"; + } this->mark_failed(); return; } error = rmt_get_ringbuf_handle(this->channel_, &this->ringbuf_); if (error != ESP_OK) { this->error_code_ = error; + this->error_string_ = "in rmt_get_ringbuf_handle"; this->mark_failed(); return; } error = rmt_rx_start(this->channel_, true); if (error != ESP_OK) { this->error_code_ = error; + this->error_string_ = "in rmt_rx_start"; this->mark_failed(); return; } @@ -67,7 +75,8 @@ void RemoteReceiverComponent::dump_config() { ESP_LOGCONFIG(TAG, " Filter out pulses shorter than: %" PRIu32 " us", this->filter_us_); ESP_LOGCONFIG(TAG, " Signal is done after %" PRIu32 " us of no changes", this->idle_us_); if (this->is_failed()) { - ESP_LOGE(TAG, "Configuring RMT driver failed: %s", esp_err_to_name(this->error_code_)); + ESP_LOGE(TAG, "Configuring RMT driver failed: %s (%s)", esp_err_to_name(this->error_code_), + this->error_string_.c_str()); } } diff --git a/esphome/components/remote_transmitter/remote_transmitter.h b/esphome/components/remote_transmitter/remote_transmitter.h index e736172cda..b897fa8fab 100644 --- a/esphome/components/remote_transmitter/remote_transmitter.h +++ b/esphome/components/remote_transmitter/remote_transmitter.h @@ -53,6 +53,7 @@ class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase, bool initialized_{false}; std::vector rmt_temp_; esp_err_t error_code_{ESP_OK}; + std::string error_string_{""}; bool inverted_{false}; #endif uint8_t carrier_duty_percent_; diff --git a/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp b/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp index c3d4d42e4f..eea35019ff 100644 --- a/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp +++ b/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp @@ -23,7 +23,8 @@ void RemoteTransmitterComponent::dump_config() { } if (this->is_failed()) { - ESP_LOGE(TAG, "Configuring RMT driver failed: %s", esp_err_to_name(this->error_code_)); + ESP_LOGE(TAG, "Configuring RMT driver failed: %s (%s)", esp_err_to_name(this->error_code_), + this->error_string_.c_str()); } } @@ -56,6 +57,7 @@ void RemoteTransmitterComponent::configure_rmt_() { esp_err_t error = rmt_config(&c); if (error != ESP_OK) { this->error_code_ = error; + this->error_string_ = "in rmt_config"; this->mark_failed(); return; } @@ -64,6 +66,11 @@ void RemoteTransmitterComponent::configure_rmt_() { error = rmt_driver_install(this->channel_, 0, 0); if (error != ESP_OK) { this->error_code_ = error; + if (error == ESP_ERR_INVALID_STATE) { + this->error_string_ = str_sprintf("RMT channel %i is already in use by another component", this->channel_); + } else { + this->error_string_ = "in rmt_driver_install"; + } this->mark_failed(); return; } From 72481006e4b8634eb4309092327b082afc099d64 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 9 May 2024 12:25:57 +1200 Subject: [PATCH 1392/2101] [ethernet] Use constexpr instead of inline define for KSZ80XX_PC2R_REG_ADDR (#6705) --- esphome/components/ethernet/ethernet_component.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index 243135de89..17093ffb3d 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -1,12 +1,12 @@ #include "ethernet_component.h" +#include "esphome/core/application.h" #include "esphome/core/log.h" #include "esphome/core/util.h" -#include "esphome/core/application.h" #ifdef USE_ESP32 -#include #include +#include #include "esp_event.h" #ifdef USE_ETHERNET_SPI @@ -554,9 +554,10 @@ bool EthernetComponent::powerdown() { } #ifndef USE_ETHERNET_SPI -void EthernetComponent::ksz8081_set_clock_reference_(esp_eth_mac_t *mac) { -#define KSZ80XX_PC2R_REG_ADDR (0x1F) +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; @@ -581,8 +582,6 @@ void EthernetComponent::ksz8081_set_clock_reference_(esp_eth_mac_t *mac) { ESPHL_ERROR_CHECK(err, "Read PHY Control 2 failed"); ESP_LOGVV(TAG, "KSZ8081 PHY Control 2: %s", format_hex_pretty((u_int8_t *) &phy_control_2, 2).c_str()); } - -#undef KSZ80XX_PC2R_REG_ADDR } #endif From 819be760133e4c13a4ce141737705ae5fcae6292 Mon Sep 17 00:00:00 2001 From: Nate Clark Date: Wed, 8 May 2024 20:47:25 -0400 Subject: [PATCH 1393/2101] Add PHY register writes to enable external clock on Ethernet with RTL8201 (#6704) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- .../ethernet/ethernet_component.cpp | 44 +++++++++++++++++++ .../components/ethernet/ethernet_component.h | 2 + 2 files changed, 46 insertions(+) diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index 17093ffb3d..3af462d593 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -184,6 +184,10 @@ void EthernetComponent::setup() { // KSZ8081RNA default is incorrect. It expects a 25MHz clock instead of the 50MHz we provide. this->ksz8081_set_clock_reference_(mac); } + if (this->type_ == ETHERNET_TYPE_RTL8201 && this->clk_mode_ == EMAC_CLK_EXT_IN) { + // Change in default behavior of RTL8201FI may require register setting to enable external clock + this->rtl8201_set_rmii_mode_(mac); + } #endif // use ESP internal eth mac @@ -583,6 +587,46 @@ void EthernetComponent::ksz8081_set_clock_reference_(esp_eth_mac_t *mac) { ESP_LOGVV(TAG, "KSZ8081 PHY Control 2: %s", format_hex_pretty((u_int8_t *) &phy_control_2, 2).c_str()); } } +constexpr uint8_t RTL8201_RMSR_REG_ADDR = 0x10; +void EthernetComponent::rtl8201_set_rmii_mode_(esp_eth_mac_t *mac) { + esp_err_t err; + uint32_t phy_rmii_mode; + err = mac->write_phy_reg(mac, this->phy_addr_, 0x1f, 0x07); + ESPHL_ERROR_CHECK(err, "Setting Page 7 failed"); + + /* + * RTL8201 RMII Mode Setting Register (RMSR) + * Page 7 Register 16 + * + * bit 0 Reserved 0 + * bit 1 Rg_rmii_rxdsel 1 (default) + * bit 2 Rg_rmii_rxdv_sel: 0 (default) + * bit 3 RMII Mode: 1 (RMII Mode) + * bit 4~7 Rg_rmii_rx_offset: 1111 (default) + * bit 8~11 Rg_rmii_tx_offset: 1111 (default) + * bit 12 Rg_rmii_clkdir: 1 (Input) + * bit 13~15 Reserved 000 + * + * Binary: 0001 1111 1111 1010 + * Hex: 0x1FFA + * + */ + + err = mac->read_phy_reg(mac, this->phy_addr_, RTL8201_RMSR_REG_ADDR, &(phy_rmii_mode)); + ESPHL_ERROR_CHECK(err, "Read PHY RMSR Register failed"); + ESP_LOGV(TAG, "Hardware default RTL8201 RMII Mode Register is: 0x%04X", phy_rmii_mode); + + err = mac->write_phy_reg(mac, this->phy_addr_, RTL8201_RMSR_REG_ADDR, 0x1FFA); + ESPHL_ERROR_CHECK(err, "Setting Register 16 RMII Mode Setting failed"); + + err = mac->read_phy_reg(mac, this->phy_addr_, RTL8201_RMSR_REG_ADDR, &(phy_rmii_mode)); + ESPHL_ERROR_CHECK(err, "Read PHY RMSR Register failed"); + ESP_LOGV(TAG, "Setting RTL8201 RMII Mode Register to: 0x%04X", phy_rmii_mode); + + err = mac->write_phy_reg(mac, this->phy_addr_, 0x1f, 0x0); + ESPHL_ERROR_CHECK(err, "Setting Page 0 failed"); +} + #endif } // namespace ethernet diff --git a/esphome/components/ethernet/ethernet_component.h b/esphome/components/ethernet/ethernet_component.h index daeb5a2029..6276885fd1 100644 --- a/esphome/components/ethernet/ethernet_component.h +++ b/esphome/components/ethernet/ethernet_component.h @@ -86,6 +86,8 @@ class EthernetComponent : public Component { void dump_connect_params_(); /// @brief Set `RMII Reference Clock Select` bit for KSZ8081. void ksz8081_set_clock_reference_(esp_eth_mac_t *mac); + /// @brief Set `RMII Mode Setting Register` for RTL8201. + void rtl8201_set_rmii_mode_(esp_eth_mac_t *mac); std::string use_address_; #ifdef USE_ETHERNET_SPI From 3ec4a66c9efb8258966f22e734fe23e06326d614 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 8 May 2024 20:45:10 -0500 Subject: [PATCH 1394/2101] Bump recommended ESP-IDF to 4.4.7 (#6703) --- esphome/components/esp32/__init__.py | 2 +- platformio.ini | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 5d74838daa..8f46567266 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -227,7 +227,7 @@ ARDUINO_PLATFORM_VERSION = cv.Version(5, 4, 0) # The default/recommended esp-idf framework version # - https://github.com/espressif/esp-idf/releases # - https://api.registry.platformio.org/v3/packages/platformio/tool/framework-espidf -RECOMMENDED_ESP_IDF_FRAMEWORK_VERSION = cv.Version(4, 4, 6) +RECOMMENDED_ESP_IDF_FRAMEWORK_VERSION = cv.Version(4, 4, 7) # The platformio/espressif32 version to use for esp-idf frameworks # - https://github.com/platformio/platform-espressif32/releases # - https://api.registry.platformio.org/v3/packages/platformio/platform/espressif32 diff --git a/platformio.ini b/platformio.ini index e699057fa3..d342b32b02 100644 --- a/platformio.ini +++ b/platformio.ini @@ -137,7 +137,7 @@ extra_scripts = post:esphome/components/esp32/post_build.py.script extends = common:idf platform = platformio/espressif32@5.4.0 platform_packages = - platformio/framework-espidf@~3.40406.0 + platformio/framework-espidf@~3.40407.0 framework = espidf lib_deps = From 054587c0e48fa4874a99a48f94e89c17ef98ce12 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 8 May 2024 16:17:45 +1200 Subject: [PATCH 1395/2101] [github] Upgrade to actions/{upload,download}-artifact v4 (#6698) --- .github/actions/build-image/action.yaml | 16 ---------------- .github/workflows/release.yml | 16 +++++++++++++--- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/.github/actions/build-image/action.yaml b/.github/actions/build-image/action.yaml index 838bc362a1..87ea28fd20 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -57,14 +57,6 @@ runs: digest="${{ steps.build-ghcr.outputs.digest }}" touch "/tmp/digests/${{ inputs.target }}/ghcr/${digest#sha256:}" - - name: Upload ghcr digest - uses: actions/upload-artifact@v3.1.3 - with: - name: digests-${{ inputs.target }}-ghcr - path: /tmp/digests/${{ inputs.target }}/ghcr/* - if-no-files-found: error - retention-days: 1 - - name: Build and push to dockerhub by digest id: build-dockerhub uses: docker/build-push-action@v5.3.0 @@ -87,11 +79,3 @@ runs: mkdir -p /tmp/digests/${{ inputs.target }}/dockerhub digest="${{ steps.build-dockerhub.outputs.digest }}" touch "/tmp/digests/${{ inputs.target }}/dockerhub/${digest#sha256:}" - - - name: Upload dockerhub digest - uses: actions/upload-artifact@v3.1.3 - with: - name: digests-${{ inputs.target }}-dockerhub - path: /tmp/digests/${{ inputs.target }}/dockerhub/* - if-no-files-found: error - retention-days: 1 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6d91d00b85..5002f041e1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -132,6 +132,13 @@ jobs: suffix: lint version: ${{ needs.init.outputs.tag }} + - name: Upload digests + uses: actions/upload-artifact@v4.3.3 + with: + name: digests-${{ matrix.platform }} + path: /tmp/digests + retention-days: 1 + deploy-manifest: name: Publish ESPHome ${{ matrix.image.title }} to ${{ matrix.registry }} runs-on: ubuntu-latest @@ -160,11 +167,14 @@ jobs: - dockerhub steps: - uses: actions/checkout@v4.1.5 + - name: Download digests - uses: actions/download-artifact@v3.0.2 + uses: actions/download-artifact@v4.1.7 with: - name: digests-${{ matrix.image.target }}-${{ matrix.registry }} + pattern: digests-* path: /tmp/digests + merge-multiple: true + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3.3.0 @@ -195,7 +205,7 @@ jobs: done - name: Create manifest list and push - working-directory: /tmp/digests + working-directory: /tmp/digests/${{ matrix.image.target }}/${{ matrix.registry }} run: | docker buildx imagetools create $(jq -Rcnr 'inputs | . / "," | map("-t " + .) | join(" ")' <<< "${{ steps.tags.outputs.tags}}") \ $(printf '${{ steps.tags.outputs.image }}@sha256:%s ' *) From 34585a6f15ba05805d3e54c14645b6ebcfaf83e1 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Wed, 8 May 2024 21:05:24 +0200 Subject: [PATCH 1396/2101] [nextion] Replace flags to `USE_ARDUINO` (#6700) --- esphome/components/nextion/nextion.h | 10 +++++----- esphome/components/nextion/nextion_upload_arduino.cpp | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/esphome/components/nextion/nextion.h b/esphome/components/nextion/nextion.h index 6435e2b4e2..dfa74f644d 100644 --- a/esphome/components/nextion/nextion.h +++ b/esphome/components/nextion/nextion.h @@ -12,7 +12,7 @@ #include "esphome/components/display/display_color_utils.h" #ifdef USE_NEXTION_TFT_UPLOAD -#ifdef ARDUINO +#ifdef USE_ARDUINO #ifdef USE_ESP32 #include #endif // USE_ESP32 @@ -22,7 +22,7 @@ #endif // USE_ESP8266 #elif defined(USE_ESP_IDF) #include -#endif // ARDUINO vs ESP-IDF +#endif // ARDUINO vs USE_ESP_IDF #endif // USE_NEXTION_TFT_UPLOAD namespace esphome { @@ -987,7 +987,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe #ifdef USE_NEXTION_TFT_UPLOAD /** - * Set the tft file URL. https seems problematic with arduino.. + * Set the tft file URL. https seems problematic with Arduino.. */ void set_tft_url(const std::string &tft_url) { this->tft_url_ = tft_url; } @@ -1190,7 +1190,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe uint32_t original_baud_rate_ = 0; bool upload_first_chunk_sent_ = false; -#ifdef ARDUINO +#ifdef USE_ARDUINO /** * will request chunk_size chunks from the web server * and send each to the nextion @@ -1208,7 +1208,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * @return position of last byte transferred, -1 for failure. */ int upload_by_chunks_(esp_http_client_handle_t http_client, uint32_t &range_start); -#endif // ARDUINO vs USE_ESP_IDF +#endif // USE_ARDUINO vs USE_ESP_IDF /** * Ends the upload process, restart Nextion and, if successful, diff --git a/esphome/components/nextion/nextion_upload_arduino.cpp b/esphome/components/nextion/nextion_upload_arduino.cpp index b199db91b7..1187c77c8e 100644 --- a/esphome/components/nextion/nextion_upload_arduino.cpp +++ b/esphome/components/nextion/nextion_upload_arduino.cpp @@ -1,7 +1,7 @@ #include "nextion.h" #ifdef USE_NEXTION_TFT_UPLOAD -#ifdef ARDUINO +#ifdef USE_ARDUINO #include "esphome/core/application.h" #include "esphome/core/defines.h" @@ -383,5 +383,5 @@ WiFiClient *Nextion::get_wifi_client_() { } // namespace nextion } // namespace esphome -#endif // ARDUINO +#endif // USE_ARDUINO #endif // USE_NEXTION_TFT_UPLOAD From 879f404b48e1de4535097e119698ae9861f7294f Mon Sep 17 00:00:00 2001 From: Mat931 <49403702+Mat931@users.noreply.github.com> Date: Wed, 8 May 2024 21:58:40 +0000 Subject: [PATCH 1397/2101] [remote_receiver, remote_transmitter] Improve error messages on the ESP32 (#6701) --- esphome/components/remote_receiver/remote_receiver.h | 1 + .../remote_receiver/remote_receiver_esp32.cpp | 11 ++++++++++- .../remote_transmitter/remote_transmitter.h | 1 + .../remote_transmitter/remote_transmitter_esp32.cpp | 9 ++++++++- 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/esphome/components/remote_receiver/remote_receiver.h b/esphome/components/remote_receiver/remote_receiver.h index a1db671e5c..773f8cf636 100644 --- a/esphome/components/remote_receiver/remote_receiver.h +++ b/esphome/components/remote_receiver/remote_receiver.h @@ -58,6 +58,7 @@ class RemoteReceiverComponent : public remote_base::RemoteReceiverBase, void decode_rmt_(rmt_item32_t *item, size_t len); RingbufHandle_t ringbuf_; esp_err_t error_code_{ESP_OK}; + std::string error_string_{""}; #endif #if defined(USE_ESP8266) || defined(USE_LIBRETINY) diff --git a/esphome/components/remote_receiver/remote_receiver_esp32.cpp b/esphome/components/remote_receiver/remote_receiver_esp32.cpp index c0bfb0222f..91295871e2 100644 --- a/esphome/components/remote_receiver/remote_receiver_esp32.cpp +++ b/esphome/components/remote_receiver/remote_receiver_esp32.cpp @@ -29,6 +29,7 @@ void RemoteReceiverComponent::setup() { esp_err_t error = rmt_config(&rmt); if (error != ESP_OK) { this->error_code_ = error; + this->error_string_ = "in rmt_config"; this->mark_failed(); return; } @@ -36,18 +37,25 @@ void RemoteReceiverComponent::setup() { error = rmt_driver_install(this->channel_, this->buffer_size_, 0); if (error != ESP_OK) { this->error_code_ = error; + if (error == ESP_ERR_INVALID_STATE) { + this->error_string_ = str_sprintf("RMT channel %i is already in use by another component", this->channel_); + } else { + this->error_string_ = "in rmt_driver_install"; + } this->mark_failed(); return; } error = rmt_get_ringbuf_handle(this->channel_, &this->ringbuf_); if (error != ESP_OK) { this->error_code_ = error; + this->error_string_ = "in rmt_get_ringbuf_handle"; this->mark_failed(); return; } error = rmt_rx_start(this->channel_, true); if (error != ESP_OK) { this->error_code_ = error; + this->error_string_ = "in rmt_rx_start"; this->mark_failed(); return; } @@ -67,7 +75,8 @@ void RemoteReceiverComponent::dump_config() { ESP_LOGCONFIG(TAG, " Filter out pulses shorter than: %" PRIu32 " us", this->filter_us_); ESP_LOGCONFIG(TAG, " Signal is done after %" PRIu32 " us of no changes", this->idle_us_); if (this->is_failed()) { - ESP_LOGE(TAG, "Configuring RMT driver failed: %s", esp_err_to_name(this->error_code_)); + ESP_LOGE(TAG, "Configuring RMT driver failed: %s (%s)", esp_err_to_name(this->error_code_), + this->error_string_.c_str()); } } diff --git a/esphome/components/remote_transmitter/remote_transmitter.h b/esphome/components/remote_transmitter/remote_transmitter.h index e736172cda..b897fa8fab 100644 --- a/esphome/components/remote_transmitter/remote_transmitter.h +++ b/esphome/components/remote_transmitter/remote_transmitter.h @@ -53,6 +53,7 @@ class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase, bool initialized_{false}; std::vector rmt_temp_; esp_err_t error_code_{ESP_OK}; + std::string error_string_{""}; bool inverted_{false}; #endif uint8_t carrier_duty_percent_; diff --git a/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp b/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp index c3d4d42e4f..eea35019ff 100644 --- a/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp +++ b/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp @@ -23,7 +23,8 @@ void RemoteTransmitterComponent::dump_config() { } if (this->is_failed()) { - ESP_LOGE(TAG, "Configuring RMT driver failed: %s", esp_err_to_name(this->error_code_)); + ESP_LOGE(TAG, "Configuring RMT driver failed: %s (%s)", esp_err_to_name(this->error_code_), + this->error_string_.c_str()); } } @@ -56,6 +57,7 @@ void RemoteTransmitterComponent::configure_rmt_() { esp_err_t error = rmt_config(&c); if (error != ESP_OK) { this->error_code_ = error; + this->error_string_ = "in rmt_config"; this->mark_failed(); return; } @@ -64,6 +66,11 @@ void RemoteTransmitterComponent::configure_rmt_() { error = rmt_driver_install(this->channel_, 0, 0); if (error != ESP_OK) { this->error_code_ = error; + if (error == ESP_ERR_INVALID_STATE) { + this->error_string_ = str_sprintf("RMT channel %i is already in use by another component", this->channel_); + } else { + this->error_string_ = "in rmt_driver_install"; + } this->mark_failed(); return; } From 2fbe80c1f78cc407d79a8d06e4c0c948f013f1ae Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 9 May 2024 12:25:57 +1200 Subject: [PATCH 1398/2101] [ethernet] Use constexpr instead of inline define for KSZ80XX_PC2R_REG_ADDR (#6705) --- esphome/components/ethernet/ethernet_component.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index 243135de89..17093ffb3d 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -1,12 +1,12 @@ #include "ethernet_component.h" +#include "esphome/core/application.h" #include "esphome/core/log.h" #include "esphome/core/util.h" -#include "esphome/core/application.h" #ifdef USE_ESP32 -#include #include +#include #include "esp_event.h" #ifdef USE_ETHERNET_SPI @@ -554,9 +554,10 @@ bool EthernetComponent::powerdown() { } #ifndef USE_ETHERNET_SPI -void EthernetComponent::ksz8081_set_clock_reference_(esp_eth_mac_t *mac) { -#define KSZ80XX_PC2R_REG_ADDR (0x1F) +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; @@ -581,8 +582,6 @@ void EthernetComponent::ksz8081_set_clock_reference_(esp_eth_mac_t *mac) { ESPHL_ERROR_CHECK(err, "Read PHY Control 2 failed"); ESP_LOGVV(TAG, "KSZ8081 PHY Control 2: %s", format_hex_pretty((u_int8_t *) &phy_control_2, 2).c_str()); } - -#undef KSZ80XX_PC2R_REG_ADDR } #endif From ed1344edd24c983196c1f50bc0571eaf0580a472 Mon Sep 17 00:00:00 2001 From: Nate Clark Date: Wed, 8 May 2024 20:47:25 -0400 Subject: [PATCH 1399/2101] Add PHY register writes to enable external clock on Ethernet with RTL8201 (#6704) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- .../ethernet/ethernet_component.cpp | 44 +++++++++++++++++++ .../components/ethernet/ethernet_component.h | 2 + 2 files changed, 46 insertions(+) diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index 17093ffb3d..3af462d593 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -184,6 +184,10 @@ void EthernetComponent::setup() { // KSZ8081RNA default is incorrect. It expects a 25MHz clock instead of the 50MHz we provide. this->ksz8081_set_clock_reference_(mac); } + if (this->type_ == ETHERNET_TYPE_RTL8201 && this->clk_mode_ == EMAC_CLK_EXT_IN) { + // Change in default behavior of RTL8201FI may require register setting to enable external clock + this->rtl8201_set_rmii_mode_(mac); + } #endif // use ESP internal eth mac @@ -583,6 +587,46 @@ void EthernetComponent::ksz8081_set_clock_reference_(esp_eth_mac_t *mac) { ESP_LOGVV(TAG, "KSZ8081 PHY Control 2: %s", format_hex_pretty((u_int8_t *) &phy_control_2, 2).c_str()); } } +constexpr uint8_t RTL8201_RMSR_REG_ADDR = 0x10; +void EthernetComponent::rtl8201_set_rmii_mode_(esp_eth_mac_t *mac) { + esp_err_t err; + uint32_t phy_rmii_mode; + err = mac->write_phy_reg(mac, this->phy_addr_, 0x1f, 0x07); + ESPHL_ERROR_CHECK(err, "Setting Page 7 failed"); + + /* + * RTL8201 RMII Mode Setting Register (RMSR) + * Page 7 Register 16 + * + * bit 0 Reserved 0 + * bit 1 Rg_rmii_rxdsel 1 (default) + * bit 2 Rg_rmii_rxdv_sel: 0 (default) + * bit 3 RMII Mode: 1 (RMII Mode) + * bit 4~7 Rg_rmii_rx_offset: 1111 (default) + * bit 8~11 Rg_rmii_tx_offset: 1111 (default) + * bit 12 Rg_rmii_clkdir: 1 (Input) + * bit 13~15 Reserved 000 + * + * Binary: 0001 1111 1111 1010 + * Hex: 0x1FFA + * + */ + + err = mac->read_phy_reg(mac, this->phy_addr_, RTL8201_RMSR_REG_ADDR, &(phy_rmii_mode)); + ESPHL_ERROR_CHECK(err, "Read PHY RMSR Register failed"); + ESP_LOGV(TAG, "Hardware default RTL8201 RMII Mode Register is: 0x%04X", phy_rmii_mode); + + err = mac->write_phy_reg(mac, this->phy_addr_, RTL8201_RMSR_REG_ADDR, 0x1FFA); + ESPHL_ERROR_CHECK(err, "Setting Register 16 RMII Mode Setting failed"); + + err = mac->read_phy_reg(mac, this->phy_addr_, RTL8201_RMSR_REG_ADDR, &(phy_rmii_mode)); + ESPHL_ERROR_CHECK(err, "Read PHY RMSR Register failed"); + ESP_LOGV(TAG, "Setting RTL8201 RMII Mode Register to: 0x%04X", phy_rmii_mode); + + err = mac->write_phy_reg(mac, this->phy_addr_, 0x1f, 0x0); + ESPHL_ERROR_CHECK(err, "Setting Page 0 failed"); +} + #endif } // namespace ethernet diff --git a/esphome/components/ethernet/ethernet_component.h b/esphome/components/ethernet/ethernet_component.h index daeb5a2029..6276885fd1 100644 --- a/esphome/components/ethernet/ethernet_component.h +++ b/esphome/components/ethernet/ethernet_component.h @@ -86,6 +86,8 @@ class EthernetComponent : public Component { void dump_connect_params_(); /// @brief Set `RMII Reference Clock Select` bit for KSZ8081. void ksz8081_set_clock_reference_(esp_eth_mac_t *mac); + /// @brief Set `RMII Mode Setting Register` for RTL8201. + void rtl8201_set_rmii_mode_(esp_eth_mac_t *mac); std::string use_address_; #ifdef USE_ETHERNET_SPI From 98dc9fde6c6041a491f56d0a9ea67dc12ebab963 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 8 May 2024 20:45:10 -0500 Subject: [PATCH 1400/2101] Bump recommended ESP-IDF to 4.4.7 (#6703) --- esphome/components/esp32/__init__.py | 2 +- platformio.ini | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 5d74838daa..8f46567266 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -227,7 +227,7 @@ ARDUINO_PLATFORM_VERSION = cv.Version(5, 4, 0) # The default/recommended esp-idf framework version # - https://github.com/espressif/esp-idf/releases # - https://api.registry.platformio.org/v3/packages/platformio/tool/framework-espidf -RECOMMENDED_ESP_IDF_FRAMEWORK_VERSION = cv.Version(4, 4, 6) +RECOMMENDED_ESP_IDF_FRAMEWORK_VERSION = cv.Version(4, 4, 7) # The platformio/espressif32 version to use for esp-idf frameworks # - https://github.com/platformio/platform-espressif32/releases # - https://api.registry.platformio.org/v3/packages/platformio/platform/espressif32 diff --git a/platformio.ini b/platformio.ini index e699057fa3..d342b32b02 100644 --- a/platformio.ini +++ b/platformio.ini @@ -137,7 +137,7 @@ extra_scripts = post:esphome/components/esp32/post_build.py.script extends = common:idf platform = platformio/espressif32@5.4.0 platform_packages = - platformio/framework-espidf@~3.40406.0 + platformio/framework-espidf@~3.40407.0 framework = espidf lib_deps = From 0ca395e8d0c7dc728da6f54c41c627117f74a006 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 9 May 2024 14:45:40 +1200 Subject: [PATCH 1401/2101] Bump version to 2024.5.0b2 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 7996a7a24a..46fc5fc20b 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.5.0b1" +__version__ = "2024.5.0b2" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From d0120cefd24dda9f512b3d8124c410179cdda87a Mon Sep 17 00:00:00 2001 From: chbmuc Date: Thu, 9 May 2024 05:02:43 +0200 Subject: [PATCH 1402/2101] Add IRK support to ble_rssi (#6422) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- .../ble_presence/ble_presence_device.h | 49 +------------------ esphome/components/ble_rssi/ble_rssi_sensor.h | 14 +++++- esphome/components/ble_rssi/sensor.py | 11 ++++- .../esp32_ble_tracker/esp32_ble_tracker.cpp | 36 ++++++++++++++ .../esp32_ble_tracker/esp32_ble_tracker.h | 2 + tests/components/ble_rssi/common.yaml | 3 ++ 6 files changed, 65 insertions(+), 50 deletions(-) diff --git a/esphome/components/ble_presence/ble_presence_device.h b/esphome/components/ble_presence/ble_presence_device.h index e74c2f4f45..3ed60d1b49 100644 --- a/esphome/components/ble_presence/ble_presence_device.h +++ b/esphome/components/ble_presence/ble_presence_device.h @@ -6,16 +6,6 @@ #ifdef USE_ESP32 -#ifdef USE_ARDUINO -#include "mbedtls/aes.h" -#include "mbedtls/base64.h" -#endif - -#ifdef USE_ESP_IDF -#define MBEDTLS_AES_ALT -#include -#endif - namespace esphome { namespace ble_presence { @@ -72,7 +62,7 @@ class BLEPresenceDevice : public binary_sensor::BinarySensorInitiallyOff, } break; case MATCH_BY_IRK: - if (resolve_irk_(device.address_uint64(), this->irk_)) { + if (device.resolve_irk(this->irk_)) { this->set_found_(true); return true; } @@ -142,43 +132,6 @@ class BLEPresenceDevice : public binary_sensor::BinarySensorInitiallyOff, bool check_ibeacon_minor_{false}; bool check_minimum_rssi_{false}; - bool resolve_irk_(uint64_t addr64, const uint8_t *irk) { - uint8_t ecb_key[16]; - uint8_t ecb_plaintext[16]; - uint8_t ecb_ciphertext[16]; - - memcpy(&ecb_key, irk, 16); - memset(&ecb_plaintext, 0, 16); - - ecb_plaintext[13] = (addr64 >> 40) & 0xff; - ecb_plaintext[14] = (addr64 >> 32) & 0xff; - ecb_plaintext[15] = (addr64 >> 24) & 0xff; - - mbedtls_aes_context ctx = {0, 0, {0}}; - mbedtls_aes_init(&ctx); - - if (mbedtls_aes_setkey_enc(&ctx, ecb_key, 128) != 0) { - mbedtls_aes_free(&ctx); - return false; - } - - if (mbedtls_aes_crypt_ecb(&ctx, -#ifdef USE_ARDUINO - MBEDTLS_AES_ENCRYPT, -#elif defined(USE_ESP_IDF) - ESP_AES_ENCRYPT, -#endif - ecb_plaintext, ecb_ciphertext) != 0) { - mbedtls_aes_free(&ctx); - return false; - } - - mbedtls_aes_free(&ctx); - - return ecb_ciphertext[15] == (addr64 & 0xff) && ecb_ciphertext[14] == ((addr64 >> 8) & 0xff) && - ecb_ciphertext[13] == ((addr64 >> 16) & 0xff); - } - bool found_{false}; uint32_t last_seen_{}; uint32_t timeout_{}; diff --git a/esphome/components/ble_rssi/ble_rssi_sensor.h b/esphome/components/ble_rssi/ble_rssi_sensor.h index 79aebce7d3..89e4f33aca 100644 --- a/esphome/components/ble_rssi/ble_rssi_sensor.h +++ b/esphome/components/ble_rssi/ble_rssi_sensor.h @@ -15,6 +15,10 @@ class BLERSSISensor : public sensor::Sensor, public esp32_ble_tracker::ESPBTDevi this->match_by_ = MATCH_BY_MAC_ADDRESS; this->address_ = address; } + void set_irk(uint8_t *irk) { + this->match_by_ = MATCH_BY_IRK; + this->irk_ = irk; + } void set_service_uuid16(uint16_t uuid) { this->match_by_ = MATCH_BY_SERVICE_UUID; this->uuid_ = esp32_ble_tracker::ESPBTUUID::from_uint16(uuid); @@ -53,6 +57,13 @@ class BLERSSISensor : public sensor::Sensor, public esp32_ble_tracker::ESPBTDevi return true; } break; + case MATCH_BY_IRK: + if (device.resolve_irk(this->irk_)) { + this->publish_state(device.get_rssi()); + this->found_ = true; + return true; + } + break; case MATCH_BY_SERVICE_UUID: for (auto uuid : device.get_service_uuids()) { if (this->uuid_ == uuid) { @@ -91,12 +102,13 @@ class BLERSSISensor : public sensor::Sensor, public esp32_ble_tracker::ESPBTDevi float get_setup_priority() const override { return setup_priority::DATA; } protected: - enum MatchType { MATCH_BY_MAC_ADDRESS, MATCH_BY_SERVICE_UUID, MATCH_BY_IBEACON_UUID }; + enum MatchType { MATCH_BY_MAC_ADDRESS, MATCH_BY_IRK, MATCH_BY_SERVICE_UUID, MATCH_BY_IBEACON_UUID }; MatchType match_by_; bool found_{false}; uint64_t address_; + uint8_t *irk_; esp32_ble_tracker::ESPBTUUID uuid_; diff --git a/esphome/components/ble_rssi/sensor.py b/esphome/components/ble_rssi/sensor.py index 4246d311ab..0543eb0578 100644 --- a/esphome/components/ble_rssi/sensor.py +++ b/esphome/components/ble_rssi/sensor.py @@ -12,6 +12,8 @@ from esphome.const import ( UNIT_DECIBEL_MILLIWATT, ) +CONF_IRK = "irk" + DEPENDENCIES = ["esp32_ble_tracker"] ble_rssi_ns = cg.esphome_ns.namespace("ble_rssi") @@ -39,6 +41,7 @@ CONFIG_SCHEMA = cv.All( .extend( { cv.Optional(CONF_MAC_ADDRESS): cv.mac_address, + cv.Optional(CONF_IRK): cv.uuid, cv.Optional(CONF_SERVICE_UUID): esp32_ble_tracker.bt_uuid, cv.Optional(CONF_IBEACON_MAJOR): cv.uint16_t, cv.Optional(CONF_IBEACON_MINOR): cv.uint16_t, @@ -47,7 +50,9 @@ CONFIG_SCHEMA = cv.All( ) .extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA) .extend(cv.COMPONENT_SCHEMA), - cv.has_exactly_one_key(CONF_MAC_ADDRESS, CONF_SERVICE_UUID, CONF_IBEACON_UUID), + cv.has_exactly_one_key( + CONF_MAC_ADDRESS, CONF_IRK, CONF_SERVICE_UUID, CONF_IBEACON_UUID + ), _validate, ) @@ -60,6 +65,10 @@ async def to_code(config): if mac_address := config.get(CONF_MAC_ADDRESS): cg.add(var.set_address(mac_address.as_hex)) + if irk := config.get(CONF_IRK): + irk = esp32_ble_tracker.as_hex_array(str(irk)) + cg.add(var.set_irk(irk)) + if service_uuid := config.get(CONF_SERVICE_UUID): if len(service_uuid) == len(esp32_ble_tracker.bt_uuid16_format): cg.add(var.set_service_uuid16(esp32_ble_tracker.as_hex(service_uuid))) diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp index a5209c764a..4ae7929ded 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp @@ -25,6 +25,9 @@ #include #endif +#define MBEDTLS_AES_ALT +#include + // bt_trace.h #undef TAG @@ -692,6 +695,39 @@ 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]; + + uint64_t addr64 = esp32_ble::ble_addr_to_uint64(this->address_); + + memcpy(&ecb_key, irk, 16); + memset(&ecb_plaintext, 0, 16); + + ecb_plaintext[13] = (addr64 >> 40) & 0xff; + ecb_plaintext[14] = (addr64 >> 32) & 0xff; + ecb_plaintext[15] = (addr64 >> 24) & 0xff; + + mbedtls_aes_context ctx = {0, 0, {0}}; + mbedtls_aes_init(&ctx); + + if (mbedtls_aes_setkey_enc(&ctx, ecb_key, 128) != 0) { + mbedtls_aes_free(&ctx); + return false; + } + + if (mbedtls_aes_crypt_ecb(&ctx, ESP_AES_ENCRYPT, ecb_plaintext, ecb_ciphertext) != 0) { + mbedtls_aes_free(&ctx); + return false; + } + + mbedtls_aes_free(&ctx); + + return ecb_ciphertext[15] == (addr64 & 0xff) && ecb_ciphertext[14] == ((addr64 >> 8) & 0xff) && + ecb_ciphertext[13] == ((addr64 >> 16) & 0xff); +} + } // namespace esp32_ble_tracker } // namespace esphome diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h index 76dee875c5..3db7a54f6e 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h @@ -86,6 +86,8 @@ class ESPBTDevice { const esp_ble_gap_cb_param_t::ble_scan_result_evt_param &get_scan_result() const { return scan_result_; } + bool resolve_irk(const uint8_t *irk) const; + optional get_ibeacon() const { for (auto &it : this->manufacturer_datas_) { auto res = ESPBLEiBeacon::from_manufacturer_data(it); diff --git a/tests/components/ble_rssi/common.yaml b/tests/components/ble_rssi/common.yaml index 52e5b865c6..43bed1d0e7 100644 --- a/tests/components/ble_rssi/common.yaml +++ b/tests/components/ble_rssi/common.yaml @@ -16,3 +16,6 @@ sensor: - platform: ble_rssi service_uuid: 11223344-5566-7788-99aa-bbccddeeff00 name: BLE Test iBeacon UUID + - platform: ble_rssi + irk: 1234567890abcdef1234567890abcdef + name: "BLE Tracker with Identity Resolving Key" From afe81184a8ab3a742d52cd25e09c393313277ae7 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Thu, 9 May 2024 13:08:30 +1000 Subject: [PATCH 1403/2101] [core] Ensure that a generated ID name is distinct from its type. (#6706) --- esphome/core/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/core/__init__.py b/esphome/core/__init__.py index 58ae23e139..f25891965a 100644 --- a/esphome/core/__init__.py +++ b/esphome/core/__init__.py @@ -340,6 +340,8 @@ class ID: if self.id is None: base = str(self.type).replace("::", "_").lower() + if base == self.type: + base = base + "_id" name = "".join(c for c in base if c.isalnum() or c == "_") used = set(registered_ids) | set(RESERVED_IDS) | CORE.loaded_integrations self.id = ensure_unique_string(name, used) From 5956bebcb782a7c4adc45cc6f4049effb82137ac Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Thu, 9 May 2024 13:14:31 +1000 Subject: [PATCH 1404/2101] [color] Fix crash when hex color parses as int, improve error reporting. (#6707) --- esphome/components/color/__init__.py | 40 +++++++++++++++++++++------- tests/components/color/common.yaml | 9 +++++++ 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/esphome/components/color/__init__.py b/esphome/components/color/__init__.py index 4a55beef38..609d416a0b 100644 --- a/esphome/components/color/__init__.py +++ b/esphome/components/color/__init__.py @@ -14,15 +14,41 @@ CONF_HEX = "hex" def hex_color(value): + if isinstance(value, int): + value = str(value) + if not isinstance(value, str): + raise cv.Invalid("Invalid value for hex color") if len(value) != 6: - raise cv.Invalid("Color must have six digits") + raise cv.Invalid("Hex color must have six digits") try: - return (int(value[0:2], 16), int(value[2:4], 16), int(value[4:6], 16)) + return int(value[0:2], 16), int(value[2:4], 16), int(value[4:6], 16) except ValueError as exc: raise cv.Invalid("Color must be hexadecimal") from exc -CONFIG_SCHEMA = cv.Any( +components = { + CONF_RED, + CONF_RED_INT, + CONF_GREEN, + CONF_GREEN_INT, + CONF_BLUE, + CONF_BLUE_INT, + CONF_WHITE, + CONF_WHITE_INT, +} + + +def validate_color(config): + has_components = set(config) & components + has_hex = CONF_HEX in config + if has_hex and has_components: + raise cv.Invalid("Hex color value may not be combined with component values") + if not has_hex and not has_components: + raise cv.Invalid("Must provide at least one color option") + return config + + +CONFIG_SCHEMA = cv.All( cv.Schema( { cv.Required(CONF_ID): cv.declare_id(ColorStruct), @@ -34,14 +60,10 @@ CONFIG_SCHEMA = cv.Any( cv.Exclusive(CONF_BLUE_INT, "blue"): cv.uint8_t, cv.Exclusive(CONF_WHITE, "white"): cv.percentage, cv.Exclusive(CONF_WHITE_INT, "white"): cv.uint8_t, + cv.Optional(CONF_HEX): hex_color, } ).extend(cv.COMPONENT_SCHEMA), - cv.Schema( - { - cv.Required(CONF_ID): cv.declare_id(ColorStruct), - cv.Required(CONF_HEX): hex_color, - } - ).extend(cv.COMPONENT_SCHEMA), + validate_color, ) diff --git a/tests/components/color/common.yaml b/tests/components/color/common.yaml index 7aa308bb63..88524e6a5f 100644 --- a/tests/components/color/common.yaml +++ b/tests/components/color/common.yaml @@ -9,3 +9,12 @@ color: blue: 100% - id: kbx_green hex: "3DEC55" + - id: kbx_green_1 + hex: 3DEC55 + - id: cps_red + hex: 800000 + - id: cps_green + hex: 008000 + - id: cps_blue + hex: 000080 + From 78d1a50853b6d0cc62927e604f883f9a8fb7574f Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 9 May 2024 21:25:48 +1200 Subject: [PATCH 1405/2101] [github] Fix digest artifact name (#6710) --- .github/workflows/release.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5002f041e1..03ed523e1d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -132,10 +132,16 @@ jobs: suffix: lint version: ${{ needs.init.outputs.tag }} + - name: Sanitize platform name + id: sanitize + run: | + echo "${{ matrix.platform }}" | sed 's|/|-|g' > /tmp/platform + echo name=$(cat /tmp/platform) >> $GITHUB_OUTPUT + - name: Upload digests uses: actions/upload-artifact@v4.3.3 with: - name: digests-${{ matrix.platform }} + name: digests-${{ steps.sanitize.outputs.name }} path: /tmp/digests retention-days: 1 From 26048d18ef3a674847d9b14b6f396b57949b7279 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Thu, 9 May 2024 13:08:30 +1000 Subject: [PATCH 1406/2101] [core] Ensure that a generated ID name is distinct from its type. (#6706) --- esphome/core/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/core/__init__.py b/esphome/core/__init__.py index 58ae23e139..f25891965a 100644 --- a/esphome/core/__init__.py +++ b/esphome/core/__init__.py @@ -340,6 +340,8 @@ class ID: if self.id is None: base = str(self.type).replace("::", "_").lower() + if base == self.type: + base = base + "_id" name = "".join(c for c in base if c.isalnum() or c == "_") used = set(registered_ids) | set(RESERVED_IDS) | CORE.loaded_integrations self.id = ensure_unique_string(name, used) From 819bb9f8bc82603e370a3e94bfdb47fbb1bdb9f2 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Thu, 9 May 2024 13:14:31 +1000 Subject: [PATCH 1407/2101] [color] Fix crash when hex color parses as int, improve error reporting. (#6707) --- esphome/components/color/__init__.py | 40 +++++++++++++++++++++------- tests/components/color/common.yaml | 9 +++++++ 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/esphome/components/color/__init__.py b/esphome/components/color/__init__.py index 4a55beef38..609d416a0b 100644 --- a/esphome/components/color/__init__.py +++ b/esphome/components/color/__init__.py @@ -14,15 +14,41 @@ CONF_HEX = "hex" def hex_color(value): + if isinstance(value, int): + value = str(value) + if not isinstance(value, str): + raise cv.Invalid("Invalid value for hex color") if len(value) != 6: - raise cv.Invalid("Color must have six digits") + raise cv.Invalid("Hex color must have six digits") try: - return (int(value[0:2], 16), int(value[2:4], 16), int(value[4:6], 16)) + return int(value[0:2], 16), int(value[2:4], 16), int(value[4:6], 16) except ValueError as exc: raise cv.Invalid("Color must be hexadecimal") from exc -CONFIG_SCHEMA = cv.Any( +components = { + CONF_RED, + CONF_RED_INT, + CONF_GREEN, + CONF_GREEN_INT, + CONF_BLUE, + CONF_BLUE_INT, + CONF_WHITE, + CONF_WHITE_INT, +} + + +def validate_color(config): + has_components = set(config) & components + has_hex = CONF_HEX in config + if has_hex and has_components: + raise cv.Invalid("Hex color value may not be combined with component values") + if not has_hex and not has_components: + raise cv.Invalid("Must provide at least one color option") + return config + + +CONFIG_SCHEMA = cv.All( cv.Schema( { cv.Required(CONF_ID): cv.declare_id(ColorStruct), @@ -34,14 +60,10 @@ CONFIG_SCHEMA = cv.Any( cv.Exclusive(CONF_BLUE_INT, "blue"): cv.uint8_t, cv.Exclusive(CONF_WHITE, "white"): cv.percentage, cv.Exclusive(CONF_WHITE_INT, "white"): cv.uint8_t, + cv.Optional(CONF_HEX): hex_color, } ).extend(cv.COMPONENT_SCHEMA), - cv.Schema( - { - cv.Required(CONF_ID): cv.declare_id(ColorStruct), - cv.Required(CONF_HEX): hex_color, - } - ).extend(cv.COMPONENT_SCHEMA), + validate_color, ) diff --git a/tests/components/color/common.yaml b/tests/components/color/common.yaml index 7aa308bb63..88524e6a5f 100644 --- a/tests/components/color/common.yaml +++ b/tests/components/color/common.yaml @@ -9,3 +9,12 @@ color: blue: 100% - id: kbx_green hex: "3DEC55" + - id: kbx_green_1 + hex: 3DEC55 + - id: cps_red + hex: 800000 + - id: cps_green + hex: 008000 + - id: cps_blue + hex: 000080 + From bd776baf8dfddac65590162f10375604a60e3a07 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 9 May 2024 21:25:48 +1200 Subject: [PATCH 1408/2101] [github] Fix digest artifact name (#6710) --- .github/workflows/release.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5002f041e1..03ed523e1d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -132,10 +132,16 @@ jobs: suffix: lint version: ${{ needs.init.outputs.tag }} + - name: Sanitize platform name + id: sanitize + run: | + echo "${{ matrix.platform }}" | sed 's|/|-|g' > /tmp/platform + echo name=$(cat /tmp/platform) >> $GITHUB_OUTPUT + - name: Upload digests uses: actions/upload-artifact@v4.3.3 with: - name: digests-${{ matrix.platform }} + name: digests-${{ steps.sanitize.outputs.name }} path: /tmp/digests retention-days: 1 From 8ae8cd1168bcdac80bb4de76255c6b2894179e07 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 9 May 2024 21:55:34 +1200 Subject: [PATCH 1409/2101] Bump version to 2024.5.0b3 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 46fc5fc20b..6e00c1bbe1 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.5.0b2" +__version__ = "2024.5.0b3" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 8280772b9151e71ef544ee8e849285536ee2bcdb Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 10 May 2024 10:57:47 +1200 Subject: [PATCH 1410/2101] Add new Error type to skip prepending path (#6716) --- esphome/config.py | 2 ++ esphome/config_validation.py | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/esphome/config.py b/esphome/config.py index 36a81f677b..4f340225fe 100644 --- a/esphome/config.py +++ b/esphome/config.py @@ -148,6 +148,8 @@ class Config(OrderedDict, fv.FinalValidateConfig): path = path or [] try: yield + except cv.FinalExternalInvalid as e: + self.add_error(e) except vol.Invalid as e: e.prepend(path) self.add_error(e) diff --git a/esphome/config_validation.py b/esphome/config_validation.py index 512f1d8f67..5fc72921e1 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -267,6 +267,10 @@ class Required(vol.Required): super().__init__(key, msg=msg) +class FinalExternalInvalid(Invalid): + """Represents an invalid value in the final validation phase where the path should not be prepended.""" + + def check_not_templatable(value): if isinstance(value, Lambda): raise Invalid("This option is not templatable!") From ca5050d4a51a6e8dc136a7051d08d4ae3494b038 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 10 May 2024 11:04:32 +1200 Subject: [PATCH 1411/2101] [github] Only save platformio cache for dev branch (#6711) --- .github/workflows/ci.yml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fbebc55676..ba0a8a363c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -364,12 +364,20 @@ jobs: with: python-version: ${{ env.DEFAULT_PYTHON }} cache-key: ${{ needs.common.outputs.cache-key }} + - name: Cache platformio + if: github.ref == 'refs/heads/dev' uses: actions/cache@v4.0.2 with: path: ~/.platformio - # yamllint disable-line rule:line-length - key: platformio-${{ matrix.pio_cache_key }}-${{ hashFiles('platformio.ini') }} + key: platformio-${{ matrix.pio_cache_key }} + + - name: Cache platformio + if: github.ref != 'refs/heads/dev' + uses: actions/cache/restore@v4.0.2 + with: + path: ~/.platformio + key: platformio-${{ matrix.pio_cache_key }} - name: Install clang-tidy run: sudo apt-get install clang-tidy-14 From 47a1710b1ed9da2304d0f17454f0b578d8d1554c Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 10 May 2024 11:55:35 +1200 Subject: [PATCH 1412/2101] Only cache docker images on dev branch (#6714) --- .github/actions/build-image/action.yaml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/actions/build-image/action.yaml b/.github/actions/build-image/action.yaml index 87ea28fd20..d36bd65bb6 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -34,6 +34,16 @@ runs: echo $l >> $GITHUB_OUTPUT done + # set cache-to only if dev branch + - id: cache-to + shell: bash + run: |- + if [[ "${{ github.ref }}" == "refs/heads/dev" ]]; then + echo "value=type=gha,mode=max" >> $GITHUB_OUTPUT + else + echo "value=" >> $GITHUB_OUTPUT + fi + - name: Build and push to ghcr by digest id: build-ghcr uses: docker/build-push-action@v5.3.0 @@ -43,7 +53,7 @@ runs: platforms: ${{ inputs.platform }} target: ${{ inputs.target }} cache-from: type=gha - cache-to: type=gha,mode=max + cache-to: ${{ steps.cache-to.outputs.value }} build-args: | BASEIMGTYPE=${{ inputs.baseimg }} BUILD_VERSION=${{ inputs.version }} @@ -66,7 +76,7 @@ runs: platforms: ${{ inputs.platform }} target: ${{ inputs.target }} cache-from: type=gha - cache-to: type=gha,mode=max + cache-to: ${{ steps.cache-to.outputs.value }} build-args: | BASEIMGTYPE=${{ inputs.baseimg }} BUILD_VERSION=${{ inputs.version }} From 1a458589041e2df1ba1b8a8ed9e128627b4ea036 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Mon, 13 May 2024 07:56:55 +1000 Subject: [PATCH 1413/2101] Add pylint to git pre-commit hooks (#6726) --- .pre-commit-config.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6f4bb52104..ce226846e3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -40,3 +40,10 @@ repos: hooks: - id: clang-format types_or: [c, c++] + - repo: local + hooks: + - id: pylint + name: pylint + entry: pylint + language: system + types: [python] From 61b65e2726485ea4d12fc5f47de1e614236fa182 Mon Sep 17 00:00:00 2001 From: Marcin Krasowski Date: Mon, 13 May 2024 01:25:41 +0200 Subject: [PATCH 1414/2101] fix(ltr390): stuck ALS values when configured for ALS+UV readings (#6723) --- esphome/components/ltr390/ltr390.cpp | 31 ++++++++++++++++++---------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/esphome/components/ltr390/ltr390.cpp b/esphome/components/ltr390/ltr390.cpp index 65c08ab614..4eb1ff2c46 100644 --- a/esphome/components/ltr390/ltr390.cpp +++ b/esphome/components/ltr390/ltr390.cpp @@ -8,6 +8,9 @@ namespace ltr390 { static const char *const TAG = "ltr390"; +static const uint8_t LTR390_WAKEUP_TIME = 10; +static const uint8_t LTR390_SETTLE_TIME = 5; + static const uint8_t LTR390_MAIN_CTRL = 0x00; static const uint8_t LTR390_MEAS_RATE = 0x04; static const uint8_t LTR390_GAIN = 0x05; @@ -101,21 +104,27 @@ void LTR390Component::read_mode_(int mode_index) { std::bitset<8> ctrl = this->reg(LTR390_MAIN_CTRL).get(); ctrl[LTR390_CTRL_MODE] = mode; + ctrl[LTR390_CTRL_EN] = true; this->reg(LTR390_MAIN_CTRL) = ctrl.to_ulong(); // After the sensor integration time do the following - this->set_timeout(((uint32_t) RESOLUTIONVALUE[this->res_]) * 100, [this, mode_index]() { - // Read from the sensor - std::get<1>(this->mode_funcs_[mode_index])(); + this->set_timeout(((uint32_t) RESOLUTIONVALUE[this->res_]) * 100 + LTR390_WAKEUP_TIME + LTR390_SETTLE_TIME, + [this, mode_index]() { + // Read from the sensor + std::get<1>(this->mode_funcs_[mode_index])(); - // If there are more modes to read then begin the next - // otherwise stop - if (mode_index + 1 < (int) this->mode_funcs_.size()) { - this->read_mode_(mode_index + 1); - } else { - this->reading_ = false; - } - }); + // If there are more modes to read then begin the next + // otherwise stop + if (mode_index + 1 < (int) this->mode_funcs_.size()) { + this->read_mode_(mode_index + 1); + } else { + // put sensor in standby + std::bitset<8> ctrl = this->reg(LTR390_MAIN_CTRL).get(); + ctrl[LTR390_CTRL_EN] = false; + this->reg(LTR390_MAIN_CTRL) = ctrl.to_ulong(); + this->reading_ = false; + } + }); } void LTR390Component::setup() { From 67ca60e2afa118818a97c12246a1b751b16a2cf4 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Mon, 13 May 2024 01:54:43 +0200 Subject: [PATCH 1415/2101] separate debug component for each platform in different file (#6715) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/debug/debug_component.cpp | 374 +------------------ esphome/components/debug/debug_component.h | 5 + esphome/components/debug/debug_esp32.cpp | 287 ++++++++++++++ esphome/components/debug/debug_esp8266.cpp | 94 +++++ esphome/components/debug/debug_host.cpp | 18 + esphome/components/debug/debug_libretiny.cpp | 44 +++ esphome/components/debug/debug_rp2040.cpp | 23 ++ 7 files changed, 479 insertions(+), 366 deletions(-) create mode 100644 esphome/components/debug/debug_esp32.cpp create mode 100644 esphome/components/debug/debug_esp8266.cpp create mode 100644 esphome/components/debug/debug_host.cpp create mode 100644 esphome/components/debug/debug_libretiny.cpp create mode 100644 esphome/components/debug/debug_rp2040.cpp diff --git a/esphome/components/debug/debug_component.cpp b/esphome/components/debug/debug_component.cpp index f22a8a2e5d..cbd4249d92 100644 --- a/esphome/components/debug/debug_component.cpp +++ b/esphome/components/debug/debug_component.cpp @@ -8,62 +8,16 @@ #include #include -#ifdef USE_ESP32 - -#include -#include - -#include -#if defined(USE_ESP32_VARIANT_ESP32) -#include -#elif defined(USE_ESP32_VARIANT_ESP32C3) -#include -#elif defined(USE_ESP32_VARIANT_ESP32C6) -#include -#elif defined(USE_ESP32_VARIANT_ESP32S2) -#include -#elif defined(USE_ESP32_VARIANT_ESP32S3) -#include -#endif - -#endif // USE_ESP32 - -#ifdef USE_ARDUINO -#ifdef USE_RP2040 -#include -#elif defined(USE_ESP32) || defined(USE_ESP8266) -#include -#endif -#endif - namespace esphome { namespace debug { static const char *const TAG = "debug"; -static uint32_t get_free_heap() { -#if defined(USE_ESP8266) - return ESP.getFreeHeap(); // NOLINT(readability-static-accessed-through-instance) -#elif defined(USE_ESP32) - return heap_caps_get_free_size(MALLOC_CAP_INTERNAL); -#elif defined(USE_RP2040) - return rp2040.getFreeHeap(); -#elif defined(USE_LIBRETINY) - return lt_heap_get_free(); -#elif defined(USE_HOST) - return INT_MAX; -#endif -} - void DebugComponent::dump_config() { #ifndef ESPHOME_LOG_HAS_DEBUG return; // Can't log below if debug logging is disabled #endif - std::string device_info; - std::string reset_reason; - device_info.reserve(256); - ESP_LOGCONFIG(TAG, "Debug component:"); #ifdef USE_TEXT_SENSOR LOG_TEXT_SENSOR(" ", "Device info", this->device_info_); @@ -76,305 +30,15 @@ void DebugComponent::dump_config() { #endif // defined(USE_ESP8266) && USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 5, 2) #endif // USE_SENSOR + std::string device_info; + device_info.reserve(256); ESP_LOGD(TAG, "ESPHome version %s", ESPHOME_VERSION); device_info += ESPHOME_VERSION; - this->free_heap_ = get_free_heap(); + this->free_heap_ = get_free_heap_(); ESP_LOGD(TAG, "Free Heap Size: %" PRIu32 " bytes", this->free_heap_); -#if defined(USE_ARDUINO) && (defined(USE_ESP32) || defined(USE_ESP8266)) - const char *flash_mode; - switch (ESP.getFlashChipMode()) { // NOLINT(readability-static-accessed-through-instance) - case FM_QIO: - flash_mode = "QIO"; - break; - case FM_QOUT: - flash_mode = "QOUT"; - break; - case FM_DIO: - flash_mode = "DIO"; - break; - case FM_DOUT: - flash_mode = "DOUT"; - break; -#ifdef USE_ESP32 - case FM_FAST_READ: - flash_mode = "FAST_READ"; - break; - case FM_SLOW_READ: - flash_mode = "SLOW_READ"; - break; -#endif - default: - flash_mode = "UNKNOWN"; - } - ESP_LOGD(TAG, "Flash Chip: Size=%ukB Speed=%uMHz Mode=%s", - ESP.getFlashChipSize() / 1024, // NOLINT - ESP.getFlashChipSpeed() / 1000000, flash_mode); // NOLINT - device_info += "|Flash: " + to_string(ESP.getFlashChipSize() / 1024) + // NOLINT - "kB Speed:" + to_string(ESP.getFlashChipSpeed() / 1000000) + "MHz Mode:"; // NOLINT - device_info += flash_mode; -#endif // USE_ARDUINO && (USE_ESP32 || USE_ESP8266) - -#ifdef USE_ESP32 - esp_chip_info_t info; - esp_chip_info(&info); - const char *model; -#if defined(USE_ESP32_VARIANT_ESP32) - model = "ESP32"; -#elif defined(USE_ESP32_VARIANT_ESP32C3) - model = "ESP32-C3"; -#elif defined(USE_ESP32_VARIANT_ESP32C6) - model = "ESP32-C6"; -#elif defined(USE_ESP32_VARIANT_ESP32S2) - model = "ESP32-S2"; -#elif defined(USE_ESP32_VARIANT_ESP32S3) - model = "ESP32-S3"; -#elif defined(USE_ESP32_VARIANT_ESP32H2) - model = "ESP32-H2"; -#else - model = "UNKNOWN"; -#endif - std::string features; - if (info.features & CHIP_FEATURE_EMB_FLASH) { - features += "EMB_FLASH,"; - info.features &= ~CHIP_FEATURE_EMB_FLASH; - } - if (info.features & CHIP_FEATURE_WIFI_BGN) { - features += "WIFI_BGN,"; - info.features &= ~CHIP_FEATURE_WIFI_BGN; - } - if (info.features & CHIP_FEATURE_BLE) { - features += "BLE,"; - info.features &= ~CHIP_FEATURE_BLE; - } - if (info.features & CHIP_FEATURE_BT) { - features += "BT,"; - info.features &= ~CHIP_FEATURE_BT; - } - if (info.features & CHIP_FEATURE_EMB_PSRAM) { - features += "EMB_PSRAM,"; - info.features &= ~CHIP_FEATURE_EMB_PSRAM; - } - if (info.features) - features += "Other:" + format_hex(info.features); - ESP_LOGD(TAG, "Chip: Model=%s, Features=%s Cores=%u, Revision=%u", model, features.c_str(), info.cores, - info.revision); - device_info += "|Chip: "; - device_info += model; - device_info += " Features:"; - device_info += features; - device_info += " Cores:" + to_string(info.cores); - device_info += " Revision:" + to_string(info.revision); - - ESP_LOGD(TAG, "ESP-IDF Version: %s", esp_get_idf_version()); - device_info += "|ESP-IDF: "; - device_info += esp_get_idf_version(); - - std::string mac = get_mac_address_pretty(); - ESP_LOGD(TAG, "EFuse MAC: %s", mac.c_str()); - device_info += "|EFuse MAC: "; - device_info += mac; - - switch (rtc_get_reset_reason(0)) { - case POWERON_RESET: - reset_reason = "Power On Reset"; - break; -#if defined(USE_ESP32_VARIANT_ESP32) - case SW_RESET: -#elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) - case RTC_SW_SYS_RESET: -#endif - reset_reason = "Software Reset Digital Core"; - break; -#if defined(USE_ESP32_VARIANT_ESP32) - case OWDT_RESET: - reset_reason = "Watch Dog Reset Digital Core"; - break; -#endif - case DEEPSLEEP_RESET: - reset_reason = "Deep Sleep Reset Digital Core"; - break; -#if defined(USE_ESP32_VARIANT_ESP32) - case SDIO_RESET: - reset_reason = "SLC Module Reset Digital Core"; - break; -#endif - case TG0WDT_SYS_RESET: - reset_reason = "Timer Group 0 Watch Dog Reset Digital Core"; - break; - case TG1WDT_SYS_RESET: - reset_reason = "Timer Group 1 Watch Dog Reset Digital Core"; - break; - case RTCWDT_SYS_RESET: - reset_reason = "RTC Watch Dog Reset Digital Core"; - break; -#if !defined(USE_ESP32_VARIANT_ESP32C6) - case INTRUSION_RESET: - reset_reason = "Intrusion Reset CPU"; - break; -#endif -#if defined(USE_ESP32_VARIANT_ESP32) - case TGWDT_CPU_RESET: - reset_reason = "Timer Group Reset CPU"; - break; -#elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) - case TG0WDT_CPU_RESET: - reset_reason = "Timer Group 0 Reset CPU"; - break; -#endif -#if defined(USE_ESP32_VARIANT_ESP32) - case SW_CPU_RESET: -#elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) - case RTC_SW_CPU_RESET: -#endif - reset_reason = "Software Reset CPU"; - break; - case RTCWDT_CPU_RESET: - reset_reason = "RTC Watch Dog Reset CPU"; - break; -#if defined(USE_ESP32_VARIANT_ESP32) - case EXT_CPU_RESET: - reset_reason = "External CPU Reset"; - break; -#endif - case RTCWDT_BROWN_OUT_RESET: - reset_reason = "Voltage Unstable Reset"; - break; - case RTCWDT_RTC_RESET: - reset_reason = "RTC Watch Dog Reset Digital Core And RTC Module"; - break; -#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) - case TG1WDT_CPU_RESET: - reset_reason = "Timer Group 1 Reset CPU"; - break; - case SUPER_WDT_RESET: - reset_reason = "Super Watchdog Reset Digital Core And RTC Module"; - break; - case GLITCH_RTC_RESET: - reset_reason = "Glitch Reset Digital Core And RTC Module"; - break; - case EFUSE_RESET: - reset_reason = "eFuse Reset Digital Core"; - break; -#endif -#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S3) - case USB_UART_CHIP_RESET: - reset_reason = "USB UART Reset Digital Core"; - break; - case USB_JTAG_CHIP_RESET: - reset_reason = "USB JTAG Reset Digital Core"; - break; - case POWER_GLITCH_RESET: - reset_reason = "Power Glitch Reset Digital Core And RTC Module"; - break; -#endif - default: - reset_reason = "Unknown Reset Reason"; - } - ESP_LOGD(TAG, "Reset Reason: %s", reset_reason.c_str()); - device_info += "|Reset: "; - device_info += reset_reason; - - const char *wakeup_reason; - switch (rtc_get_wakeup_cause()) { - case NO_SLEEP: - wakeup_reason = "No Sleep"; - break; - case EXT_EVENT0_TRIG: - wakeup_reason = "External Event 0"; - break; - case EXT_EVENT1_TRIG: - wakeup_reason = "External Event 1"; - break; - case GPIO_TRIG: - wakeup_reason = "GPIO"; - break; - case TIMER_EXPIRE: - wakeup_reason = "Wakeup Timer"; - break; - case SDIO_TRIG: - wakeup_reason = "SDIO"; - break; - case MAC_TRIG: - wakeup_reason = "MAC"; - break; - case UART0_TRIG: - wakeup_reason = "UART0"; - break; - case UART1_TRIG: - wakeup_reason = "UART1"; - break; - case TOUCH_TRIG: - wakeup_reason = "Touch"; - break; - case SAR_TRIG: - wakeup_reason = "SAR"; - break; - case BT_TRIG: - wakeup_reason = "BT"; - break; - default: - wakeup_reason = "Unknown"; - } - ESP_LOGD(TAG, "Wakeup Reason: %s", wakeup_reason); - device_info += "|Wakeup: "; - device_info += wakeup_reason; -#endif - -#if defined(USE_ESP8266) && !defined(CLANG_TIDY) - ESP_LOGD(TAG, "Chip ID: 0x%08X", ESP.getChipId()); - ESP_LOGD(TAG, "SDK Version: %s", ESP.getSdkVersion()); - ESP_LOGD(TAG, "Core Version: %s", ESP.getCoreVersion().c_str()); - ESP_LOGD(TAG, "Boot Version=%u Mode=%u", ESP.getBootVersion(), ESP.getBootMode()); - ESP_LOGD(TAG, "CPU Frequency: %u", ESP.getCpuFreqMHz()); - ESP_LOGD(TAG, "Flash Chip ID=0x%08X", ESP.getFlashChipId()); - ESP_LOGD(TAG, "Reset Reason: %s", ESP.getResetReason().c_str()); - ESP_LOGD(TAG, "Reset Info: %s", ESP.getResetInfo().c_str()); - - device_info += "|Chip: 0x" + format_hex(ESP.getChipId()); - device_info += "|SDK: "; - device_info += ESP.getSdkVersion(); - device_info += "|Core: "; - device_info += ESP.getCoreVersion().c_str(); - device_info += "|Boot: "; - device_info += to_string(ESP.getBootVersion()); - device_info += "|Mode: " + to_string(ESP.getBootMode()); - device_info += "|CPU: " + to_string(ESP.getCpuFreqMHz()); - device_info += "|Flash: 0x" + format_hex(ESP.getFlashChipId()); - device_info += "|Reset: "; - device_info += ESP.getResetReason().c_str(); - device_info += "|"; - device_info += ESP.getResetInfo().c_str(); - - reset_reason = ESP.getResetReason().c_str(); -#endif - -#ifdef USE_RP2040 - ESP_LOGD(TAG, "CPU Frequency: %u", rp2040.f_cpu()); - device_info += "CPU Frequency: " + to_string(rp2040.f_cpu()); -#endif // USE_RP2040 - -#ifdef USE_LIBRETINY - ESP_LOGD(TAG, "LibreTiny Version: %s", lt_get_version()); - ESP_LOGD(TAG, "Chip: %s (%04x) @ %u MHz", lt_cpu_get_model_name(), lt_cpu_get_model(), lt_cpu_get_freq_mhz()); - ESP_LOGD(TAG, "Chip ID: 0x%06X", lt_cpu_get_mac_id()); - ESP_LOGD(TAG, "Board: %s", lt_get_board_code()); - ESP_LOGD(TAG, "Flash: %u KiB / RAM: %u KiB", lt_flash_get_size() / 1024, lt_ram_get_size() / 1024); - ESP_LOGD(TAG, "Reset Reason: %s", lt_get_reboot_reason_name(lt_get_reboot_reason())); - - device_info += "|Version: "; - device_info += LT_BANNER_STR + 10; - device_info += "|Reset Reason: "; - device_info += lt_get_reboot_reason_name(lt_get_reboot_reason()); - device_info += "|Chip Name: "; - device_info += lt_cpu_get_model_name(); - device_info += "|Chip ID: 0x" + format_hex(lt_cpu_get_mac_id()); - device_info += "|Flash: " + to_string(lt_flash_get_size() / 1024) + " KiB"; - device_info += "|RAM: " + to_string(lt_ram_get_size() / 1024) + " KiB"; - - reset_reason = lt_get_reboot_reason_name(lt_get_reboot_reason()); -#endif // USE_LIBRETINY + get_device_info_(device_info); #ifdef USE_TEXT_SENSOR if (this->device_info_ != nullptr) { @@ -383,14 +47,14 @@ void DebugComponent::dump_config() { this->device_info_->publish_state(device_info); } if (this->reset_reason_ != nullptr) { - this->reset_reason_->publish_state(reset_reason); + this->reset_reason_->publish_state(get_reset_reason_()); } #endif // USE_TEXT_SENSOR } void DebugComponent::loop() { // log when free heap space has halved - uint32_t new_free_heap = get_free_heap(); + uint32_t new_free_heap = get_free_heap_(); if (new_free_heap < this->free_heap_ / 2) { this->free_heap_ = new_free_heap; ESP_LOGD(TAG, "Free Heap Size: %" PRIu32 " bytes", this->free_heap_); @@ -411,38 +75,16 @@ void DebugComponent::loop() { void DebugComponent::update() { #ifdef USE_SENSOR if (this->free_sensor_ != nullptr) { - this->free_sensor_->publish_state(get_free_heap()); + this->free_sensor_->publish_state(get_free_heap_()); } - if (this->block_sensor_ != nullptr) { -#if defined(USE_ESP8266) - // NOLINTNEXTLINE(readability-static-accessed-through-instance) - this->block_sensor_->publish_state(ESP.getMaxFreeBlockSize()); -#elif defined(USE_ESP32) - this->block_sensor_->publish_state(heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL)); -#elif defined(USE_LIBRETINY) - this->block_sensor_->publish_state(lt_heap_get_max_alloc()); -#endif - } - -#if defined(USE_ESP8266) && USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 5, 2) - if (this->fragmentation_sensor_ != nullptr) { - // NOLINTNEXTLINE(readability-static-accessed-through-instance) - this->fragmentation_sensor_->publish_state(ESP.getHeapFragmentation()); - } -#endif - if (this->loop_time_sensor_ != nullptr) { this->loop_time_sensor_->publish_state(this->max_loop_time_); this->max_loop_time_ = 0; } -#ifdef USE_ESP32 - if (this->psram_sensor_ != nullptr) { - this->psram_sensor_->publish_state(heap_caps_get_free_size(MALLOC_CAP_SPIRAM)); - } -#endif // USE_ESP32 #endif // USE_SENSOR + update_platform_(); } float DebugComponent::get_setup_priority() const { return setup_priority::LATE; } diff --git a/esphome/components/debug/debug_component.h b/esphome/components/debug/debug_component.h index 93e3ba4857..2b54406603 100644 --- a/esphome/components/debug/debug_component.h +++ b/esphome/components/debug/debug_component.h @@ -59,6 +59,11 @@ class DebugComponent : public PollingComponent { text_sensor::TextSensor *device_info_{nullptr}; text_sensor::TextSensor *reset_reason_{nullptr}; #endif // USE_TEXT_SENSOR + + std::string get_reset_reason_(); + uint32_t get_free_heap_(); + void get_device_info_(std::string &device_info); + void update_platform_(); }; } // namespace debug diff --git a/esphome/components/debug/debug_esp32.cpp b/esphome/components/debug/debug_esp32.cpp new file mode 100644 index 0000000000..cfdfdd2a61 --- /dev/null +++ b/esphome/components/debug/debug_esp32.cpp @@ -0,0 +1,287 @@ +#include "debug_component.h" +#ifdef USE_ESP32 +#include "esphome/core/log.h" + +#include +#include +#include + +#if defined(USE_ESP32_VARIANT_ESP32) +#include +#elif defined(USE_ESP32_VARIANT_ESP32C3) +#include +#elif defined(USE_ESP32_VARIANT_ESP32C6) +#include +#elif defined(USE_ESP32_VARIANT_ESP32S2) +#include +#elif defined(USE_ESP32_VARIANT_ESP32S3) +#include +#endif +#ifdef USE_ARDUINO +#include +#endif + +namespace esphome { +namespace debug { + +static const char *const TAG = "debug"; + +std::string DebugComponent::get_reset_reason_() { + std::string reset_reason; + switch (rtc_get_reset_reason(0)) { + case POWERON_RESET: + reset_reason = "Power On Reset"; + break; +#if defined(USE_ESP32_VARIANT_ESP32) + case SW_RESET: +#elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) + case RTC_SW_SYS_RESET: +#endif + reset_reason = "Software Reset Digital Core"; + break; +#if defined(USE_ESP32_VARIANT_ESP32) + case OWDT_RESET: + reset_reason = "Watch Dog Reset Digital Core"; + break; +#endif + case DEEPSLEEP_RESET: + reset_reason = "Deep Sleep Reset Digital Core"; + break; +#if defined(USE_ESP32_VARIANT_ESP32) + case SDIO_RESET: + reset_reason = "SLC Module Reset Digital Core"; + break; +#endif + case TG0WDT_SYS_RESET: + reset_reason = "Timer Group 0 Watch Dog Reset Digital Core"; + break; + case TG1WDT_SYS_RESET: + reset_reason = "Timer Group 1 Watch Dog Reset Digital Core"; + break; + case RTCWDT_SYS_RESET: + reset_reason = "RTC Watch Dog Reset Digital Core"; + break; +#if !defined(USE_ESP32_VARIANT_ESP32C6) + case INTRUSION_RESET: + reset_reason = "Intrusion Reset CPU"; + break; +#endif +#if defined(USE_ESP32_VARIANT_ESP32) + case TGWDT_CPU_RESET: + reset_reason = "Timer Group Reset CPU"; + break; +#elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) + case TG0WDT_CPU_RESET: + reset_reason = "Timer Group 0 Reset CPU"; + break; +#endif +#if defined(USE_ESP32_VARIANT_ESP32) + case SW_CPU_RESET: +#elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) + case RTC_SW_CPU_RESET: +#endif + reset_reason = "Software Reset CPU"; + break; + case RTCWDT_CPU_RESET: + reset_reason = "RTC Watch Dog Reset CPU"; + break; +#if defined(USE_ESP32_VARIANT_ESP32) + case EXT_CPU_RESET: + reset_reason = "External CPU Reset"; + break; +#endif + case RTCWDT_BROWN_OUT_RESET: + reset_reason = "Voltage Unstable Reset"; + break; + case RTCWDT_RTC_RESET: + reset_reason = "RTC Watch Dog Reset Digital Core And RTC Module"; + break; +#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) + case TG1WDT_CPU_RESET: + reset_reason = "Timer Group 1 Reset CPU"; + break; + case SUPER_WDT_RESET: + reset_reason = "Super Watchdog Reset Digital Core And RTC Module"; + break; + case GLITCH_RTC_RESET: + reset_reason = "Glitch Reset Digital Core And RTC Module"; + break; + case EFUSE_RESET: + reset_reason = "eFuse Reset Digital Core"; + break; +#endif +#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S3) + case USB_UART_CHIP_RESET: + reset_reason = "USB UART Reset Digital Core"; + break; + case USB_JTAG_CHIP_RESET: + reset_reason = "USB JTAG Reset Digital Core"; + break; + case POWER_GLITCH_RESET: + reset_reason = "Power Glitch Reset Digital Core And RTC Module"; + break; +#endif + default: + reset_reason = "Unknown Reset Reason"; + } + ESP_LOGD(TAG, "Reset Reason: %s", reset_reason.c_str()); + return reset_reason; +} + +uint32_t DebugComponent::get_free_heap_() { return heap_caps_get_free_size(MALLOC_CAP_INTERNAL); } + +void DebugComponent::get_device_info_(std::string &device_info) { +#if defined(USE_ARDUINO) + const char *flash_mode; + switch (ESP.getFlashChipMode()) { // NOLINT(readability-static-accessed-through-instance) + case FM_QIO: + flash_mode = "QIO"; + break; + case FM_QOUT: + flash_mode = "QOUT"; + break; + case FM_DIO: + flash_mode = "DIO"; + break; + case FM_DOUT: + flash_mode = "DOUT"; + break; + case FM_FAST_READ: + flash_mode = "FAST_READ"; + break; + case FM_SLOW_READ: + flash_mode = "SLOW_READ"; + break; + default: + flash_mode = "UNKNOWN"; + } + ESP_LOGD(TAG, "Flash Chip: Size=%ukB Speed=%uMHz Mode=%s", + ESP.getFlashChipSize() / 1024, // NOLINT + ESP.getFlashChipSpeed() / 1000000, flash_mode); // NOLINT + device_info += "|Flash: " + to_string(ESP.getFlashChipSize() / 1024) + // NOLINT + "kB Speed:" + to_string(ESP.getFlashChipSpeed() / 1000000) + "MHz Mode:"; // NOLINT + device_info += flash_mode; +#endif + + esp_chip_info_t info; + esp_chip_info(&info); + const char *model; +#if defined(USE_ESP32_VARIANT_ESP32) + model = "ESP32"; +#elif defined(USE_ESP32_VARIANT_ESP32C3) + model = "ESP32-C3"; +#elif defined(USE_ESP32_VARIANT_ESP32C6) + model = "ESP32-C6"; +#elif defined(USE_ESP32_VARIANT_ESP32S2) + model = "ESP32-S2"; +#elif defined(USE_ESP32_VARIANT_ESP32S3) + model = "ESP32-S3"; +#elif defined(USE_ESP32_VARIANT_ESP32H2) + model = "ESP32-H2"; +#else + model = "UNKNOWN"; +#endif + std::string features; + if (info.features & CHIP_FEATURE_EMB_FLASH) { + features += "EMB_FLASH,"; + info.features &= ~CHIP_FEATURE_EMB_FLASH; + } + if (info.features & CHIP_FEATURE_WIFI_BGN) { + features += "WIFI_BGN,"; + info.features &= ~CHIP_FEATURE_WIFI_BGN; + } + if (info.features & CHIP_FEATURE_BLE) { + features += "BLE,"; + info.features &= ~CHIP_FEATURE_BLE; + } + if (info.features & CHIP_FEATURE_BT) { + features += "BT,"; + info.features &= ~CHIP_FEATURE_BT; + } + if (info.features & CHIP_FEATURE_EMB_PSRAM) { + features += "EMB_PSRAM,"; + info.features &= ~CHIP_FEATURE_EMB_PSRAM; + } + if (info.features) + features += "Other:" + format_hex(info.features); + ESP_LOGD(TAG, "Chip: Model=%s, Features=%s Cores=%u, Revision=%u", model, features.c_str(), info.cores, + info.revision); + device_info += "|Chip: "; + device_info += model; + device_info += " Features:"; + device_info += features; + device_info += " Cores:" + to_string(info.cores); + device_info += " Revision:" + to_string(info.revision); + + ESP_LOGD(TAG, "ESP-IDF Version: %s", esp_get_idf_version()); + device_info += "|ESP-IDF: "; + device_info += esp_get_idf_version(); + + std::string mac = get_mac_address_pretty(); + ESP_LOGD(TAG, "EFuse MAC: %s", mac.c_str()); + device_info += "|EFuse MAC: "; + device_info += mac; + + device_info += "|Reset: "; + device_info += get_reset_reason_(); + + const char *wakeup_reason; + switch (rtc_get_wakeup_cause()) { + case NO_SLEEP: + wakeup_reason = "No Sleep"; + break; + case EXT_EVENT0_TRIG: + wakeup_reason = "External Event 0"; + break; + case EXT_EVENT1_TRIG: + wakeup_reason = "External Event 1"; + break; + case GPIO_TRIG: + wakeup_reason = "GPIO"; + break; + case TIMER_EXPIRE: + wakeup_reason = "Wakeup Timer"; + break; + case SDIO_TRIG: + wakeup_reason = "SDIO"; + break; + case MAC_TRIG: + wakeup_reason = "MAC"; + break; + case UART0_TRIG: + wakeup_reason = "UART0"; + break; + case UART1_TRIG: + wakeup_reason = "UART1"; + break; + case TOUCH_TRIG: + wakeup_reason = "Touch"; + break; + case SAR_TRIG: + wakeup_reason = "SAR"; + break; + case BT_TRIG: + wakeup_reason = "BT"; + break; + default: + wakeup_reason = "Unknown"; + } + ESP_LOGD(TAG, "Wakeup Reason: %s", wakeup_reason); + device_info += "|Wakeup: "; + device_info += wakeup_reason; +} + +void DebugComponent::update_platform_() { +#ifdef USE_SENSOR + if (this->block_sensor_ != nullptr) { + this->block_sensor_->publish_state(heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL)); + } + if (this->psram_sensor_ != nullptr) { + this->psram_sensor_->publish_state(heap_caps_get_free_size(MALLOC_CAP_SPIRAM)); + } +#endif +} + +} // namespace debug +} // namespace esphome +#endif diff --git a/esphome/components/debug/debug_esp8266.cpp b/esphome/components/debug/debug_esp8266.cpp new file mode 100644 index 0000000000..3395d9db12 --- /dev/null +++ b/esphome/components/debug/debug_esp8266.cpp @@ -0,0 +1,94 @@ +#include "debug_component.h" +#ifdef USE_ESP8266 +#include "esphome/core/log.h" +#include + +namespace esphome { +namespace debug { + +static const char *const TAG = "debug"; + +std::string DebugComponent::get_reset_reason_() { +#if !defined(CLANG_TIDY) + return ESP.getResetReason().c_str(); +#else + return ""; +#endif +} + +uint32_t DebugComponent::get_free_heap_() { + return ESP.getFreeHeap(); // NOLINT(readability-static-accessed-through-instance) +} + +void DebugComponent::get_device_info_(std::string &device_info) { + const char *flash_mode; + switch (ESP.getFlashChipMode()) { // NOLINT(readability-static-accessed-through-instance) + case FM_QIO: + flash_mode = "QIO"; + break; + case FM_QOUT: + flash_mode = "QOUT"; + break; + case FM_DIO: + flash_mode = "DIO"; + break; + case FM_DOUT: + flash_mode = "DOUT"; + break; + default: + flash_mode = "UNKNOWN"; + } + ESP_LOGD(TAG, "Flash Chip: Size=%ukB Speed=%uMHz Mode=%s", + ESP.getFlashChipSize() / 1024, // NOLINT + ESP.getFlashChipSpeed() / 1000000, flash_mode); // NOLINT + device_info += "|Flash: " + to_string(ESP.getFlashChipSize() / 1024) + // NOLINT + "kB Speed:" + to_string(ESP.getFlashChipSpeed() / 1000000) + "MHz Mode:"; // NOLINT + device_info += flash_mode; + +#if !defined(CLANG_TIDY) + auto reset_reason = get_reset_reason_(); + ESP_LOGD(TAG, "Chip ID: 0x%08X", ESP.getChipId()); + ESP_LOGD(TAG, "SDK Version: %s", ESP.getSdkVersion()); + ESP_LOGD(TAG, "Core Version: %s", ESP.getCoreVersion().c_str()); + ESP_LOGD(TAG, "Boot Version=%u Mode=%u", ESP.getBootVersion(), ESP.getBootMode()); + ESP_LOGD(TAG, "CPU Frequency: %u", ESP.getCpuFreqMHz()); + ESP_LOGD(TAG, "Flash Chip ID=0x%08X", ESP.getFlashChipId()); + ESP_LOGD(TAG, "Reset Reason: %s", reset_reason.c_str()); + ESP_LOGD(TAG, "Reset Info: %s", ESP.getResetInfo().c_str()); + + device_info += "|Chip: 0x" + format_hex(ESP.getChipId()); + device_info += "|SDK: "; + device_info += ESP.getSdkVersion(); + device_info += "|Core: "; + device_info += ESP.getCoreVersion().c_str(); + device_info += "|Boot: "; + device_info += to_string(ESP.getBootVersion()); + device_info += "|Mode: " + to_string(ESP.getBootMode()); + device_info += "|CPU: " + to_string(ESP.getCpuFreqMHz()); + device_info += "|Flash: 0x" + format_hex(ESP.getFlashChipId()); + device_info += "|Reset: "; + device_info += reset_reason; + device_info += "|"; + device_info += ESP.getResetInfo().c_str(); +#endif +} + +void DebugComponent::update_platform_() { +#ifdef USE_SENSOR + if (this->block_sensor_ != nullptr) { + // NOLINTNEXTLINE(readability-static-accessed-through-instance) + this->block_sensor_->publish_state(ESP.getMaxFreeBlockSize()); + } +#if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 5, 2) + if (this->fragmentation_sensor_ != nullptr) { + // NOLINTNEXTLINE(readability-static-accessed-through-instance) + this->fragmentation_sensor_->publish_state(ESP.getHeapFragmentation()); + } +#endif + +#endif +} + +} // namespace debug +} // namespace esphome +#endif diff --git a/esphome/components/debug/debug_host.cpp b/esphome/components/debug/debug_host.cpp new file mode 100644 index 0000000000..09ad34ef88 --- /dev/null +++ b/esphome/components/debug/debug_host.cpp @@ -0,0 +1,18 @@ +#include "debug_component.h" +#ifdef USE_HOST +#include + +namespace esphome { +namespace debug { + +std::string DebugComponent::get_reset_reason_() { return ""; } + +uint32_t DebugComponent::get_free_heap_() { return INT_MAX; } + +void DebugComponent::get_device_info_(std::string &device_info) {} + +void DebugComponent::update_platform_() {} + +} // namespace debug +} // namespace esphome +#endif diff --git a/esphome/components/debug/debug_libretiny.cpp b/esphome/components/debug/debug_libretiny.cpp new file mode 100644 index 0000000000..725cd870ca --- /dev/null +++ b/esphome/components/debug/debug_libretiny.cpp @@ -0,0 +1,44 @@ +#include "debug_component.h" +#ifdef USE_LIBRETINY +#include "esphome/core/log.h" + +namespace esphome { +namespace debug { + +static const char *const TAG = "debug"; + +std::string DebugComponent::get_reset_reason_() { return lt_get_reboot_reason_name(lt_get_reboot_reason()); } + +uint32_t DebugComponent::get_free_heap_() { return lt_heap_get_free(); } + +void DebugComponent::get_device_info_(std::string &device_info) { + reset_reason = get_reset_reason_(); + ESP_LOGD(TAG, "LibreTiny Version: %s", lt_get_version()); + ESP_LOGD(TAG, "Chip: %s (%04x) @ %u MHz", lt_cpu_get_model_name(), lt_cpu_get_model(), lt_cpu_get_freq_mhz()); + ESP_LOGD(TAG, "Chip ID: 0x%06X", lt_cpu_get_mac_id()); + ESP_LOGD(TAG, "Board: %s", lt_get_board_code()); + ESP_LOGD(TAG, "Flash: %u KiB / RAM: %u KiB", lt_flash_get_size() / 1024, lt_ram_get_size() / 1024); + ESP_LOGD(TAG, "Reset Reason: %s", reset_reason.c_str()); + + device_info += "|Version: "; + device_info += LT_BANNER_STR + 10; + device_info += "|Reset Reason: "; + device_info += reset_reason; + device_info += "|Chip Name: "; + device_info += lt_cpu_get_model_name(); + device_info += "|Chip ID: 0x" + format_hex(lt_cpu_get_mac_id()); + device_info += "|Flash: " + to_string(lt_flash_get_size() / 1024) + " KiB"; + device_info += "|RAM: " + to_string(lt_ram_get_size() / 1024) + " KiB"; +} + +void DebugComponent::update_platform_() { +#ifdef USE_SENSOR + if (this->block_sensor_ != nullptr) { + this->block_sensor_->publish_state(lt_heap_get_max_alloc()); + } +#endif +} + +} // namespace debug +} // namespace esphome +#endif diff --git a/esphome/components/debug/debug_rp2040.cpp b/esphome/components/debug/debug_rp2040.cpp new file mode 100644 index 0000000000..497547e30d --- /dev/null +++ b/esphome/components/debug/debug_rp2040.cpp @@ -0,0 +1,23 @@ +#include "debug_component.h" +#ifdef USE_RP2040 +#include "esphome/core/log.h" +#include +namespace esphome { +namespace debug { + +static const char *const TAG = "debug"; + +std::string DebugComponent::get_reset_reason_() { return ""; } + +uint32_t DebugComponent::get_free_heap_() { return rp2040.getFreeHeap(); } + +void DebugComponent::get_device_info_(std::string &device_info) { + ESP_LOGD(TAG, "CPU Frequency: %u", rp2040.f_cpu()); + device_info += "CPU Frequency: " + to_string(rp2040.f_cpu()); +} + +void DebugComponent::update_platform_() {} + +} // namespace debug +} // namespace esphome +#endif From 13e3920c13ce8af481b0e89d61703e61051a0b0d Mon Sep 17 00:00:00 2001 From: Szewcson Date: Mon, 13 May 2024 03:36:10 +0200 Subject: [PATCH 1416/2101] GDK101 support (#4703) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- CODEOWNERS | 1 + esphome/components/gdk101/__init__.py | 32 ++++ esphome/components/gdk101/binary_sensor.py | 29 +++ esphome/components/gdk101/gdk101.cpp | 189 ++++++++++++++++++++ esphome/components/gdk101/gdk101.h | 52 ++++++ esphome/components/gdk101/sensor.py | 83 +++++++++ esphome/const.py | 3 + tests/components/gdk101/common.yaml | 28 +++ tests/components/gdk101/test.esp32-idf.yaml | 5 + tests/components/gdk101/test.esp32.yaml | 5 + tests/components/gdk101/test.esp8266.yaml | 5 + tests/components/gdk101/test.rp2040.yaml | 5 + 12 files changed, 437 insertions(+) create mode 100644 esphome/components/gdk101/__init__.py create mode 100644 esphome/components/gdk101/binary_sensor.py create mode 100644 esphome/components/gdk101/gdk101.cpp create mode 100644 esphome/components/gdk101/gdk101.h create mode 100644 esphome/components/gdk101/sensor.py create mode 100644 tests/components/gdk101/common.yaml create mode 100644 tests/components/gdk101/test.esp32-idf.yaml create mode 100644 tests/components/gdk101/test.esp32.yaml create mode 100644 tests/components/gdk101/test.esp8266.yaml create mode 100644 tests/components/gdk101/test.rp2040.yaml diff --git a/CODEOWNERS b/CODEOWNERS index c630db7948..88f875f368 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -135,6 +135,7 @@ esphome/components/fs3000/* @kahrendt esphome/components/ft5x06/* @clydebarrow esphome/components/ft63x6/* @gpambrozio esphome/components/gcja5/* @gcormier +esphome/components/gdk101/* @Szewcson esphome/components/globals/* @esphome/core esphome/components/gp8403/* @jesserockz esphome/components/gpio/* @esphome/core diff --git a/esphome/components/gdk101/__init__.py b/esphome/components/gdk101/__init__.py new file mode 100644 index 0000000000..0d90257964 --- /dev/null +++ b/esphome/components/gdk101/__init__.py @@ -0,0 +1,32 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import i2c +from esphome.const import CONF_ID + +CODEOWNERS = ["@Szewcson"] + +DEPENDENCIES = ["i2c"] +MULTI_CONF = True + +CONF_GDK101_ID = "gdk101_id" + +gdk101_ns = cg.esphome_ns.namespace("gdk101") +GDK101Component = gdk101_ns.class_( + "GDK101Component", cg.PollingComponent, i2c.I2CDevice +) + +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(GDK101Component), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x18)) +) + + +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) diff --git a/esphome/components/gdk101/binary_sensor.py b/esphome/components/gdk101/binary_sensor.py new file mode 100644 index 0000000000..2a3d6f07eb --- /dev/null +++ b/esphome/components/gdk101/binary_sensor.py @@ -0,0 +1,29 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import binary_sensor +from esphome.const import ( + CONF_VIBRATIONS, + DEVICE_CLASS_VIBRATION, + ENTITY_CATEGORY_DIAGNOSTIC, + ICON_VIBRATE, +) +from . import CONF_GDK101_ID, GDK101Component + +DEPENDENCIES = ["gdk101"] + +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(CONF_GDK101_ID): cv.use_id(GDK101Component), + cv.Required(CONF_VIBRATIONS): binary_sensor.binary_sensor_schema( + device_class=DEVICE_CLASS_VIBRATION, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + icon=ICON_VIBRATE, + ), + } +) + + +async def to_code(config): + hub = await cg.get_variable(config[CONF_GDK101_ID]) + var = await binary_sensor.new_binary_sensor(config[CONF_VIBRATIONS]) + cg.add(hub.set_vibration_binary_sensor(var)) diff --git a/esphome/components/gdk101/gdk101.cpp b/esphome/components/gdk101/gdk101.cpp new file mode 100644 index 0000000000..93f3c20fa8 --- /dev/null +++ b/esphome/components/gdk101/gdk101.cpp @@ -0,0 +1,189 @@ +#include "gdk101.h" +#include "esphome/core/hal.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace gdk101 { + +static const char *const TAG = "gdk101"; +static const uint8_t NUMBER_OF_READ_RETRIES = 5; + +void GDK101Component::update() { + uint8_t data[2]; + if (!this->read_dose_1m_(data)) { + this->status_set_warning("Failed to read dose 1m"); + return; + } + + if (!this->read_dose_10m_(data)) { + this->status_set_warning("Failed to read dose 10m"); + return; + } + + if (!this->read_status_(data)) { + this->status_set_warning("Failed to read status"); + return; + } + + if (!this->read_measurement_duration_(data)) { + this->status_set_warning("Failed to read measurement duration"); + return; + } + this->status_clear_warning(); +} + +void GDK101Component::setup() { + uint8_t data[2]; + ESP_LOGCONFIG(TAG, "Setting up GDK101..."); + // first, reset the sensor + if (!this->reset_sensor_(data)) { + this->status_set_error("Reset failed!"); + this->mark_failed(); + return; + } + // sensor should acknowledge success of the reset procedure + if (data[0] != 1) { + this->status_set_error("Reset not acknowledged!"); + this->mark_failed(); + return; + } + delay(10); + // read firmware version + if (!this->read_fw_version_(data)) { + this->status_set_error("Failed to read firmware version"); + this->mark_failed(); + return; + } +} + +void GDK101Component::dump_config() { + ESP_LOGCONFIG(TAG, "GDK101:"); + LOG_I2C_DEVICE(this); + if (this->is_failed()) { + ESP_LOGE(TAG, "Communication with GDK101 failed!"); + } +#ifdef USE_SENSOR + LOG_SENSOR(" ", "Firmware Version", this->fw_version_sensor_); + LOG_SENSOR(" ", "Average Radaition Dose per 1 minute", this->rad_1m_sensor_); + LOG_SENSOR(" ", "Average Radaition Dose per 10 minutes", this->rad_10m_sensor_); + LOG_SENSOR(" ", "Status", this->status_sensor_); + LOG_SENSOR(" ", "Measurement Duration", this->measurement_duration_sensor_); +#endif // USE_SENSOR + +#ifdef USE_BINARY_SENSOR + LOG_BINARY_SENSOR(" ", "Vibration Status", this->vibration_binary_sensor_); +#endif // USE_BINARY_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; + while (!status && retry) { + status = this->read_bytes(a_register, data, len); + retry--; + } + return status; +} + +bool GDK101Component::reset_sensor_(uint8_t *data) { + // It looks like reset is not so well designed in that sensor + // After sending reset command it looks that sensor start performing reset and is unresponsible during read + // after a while we can send another reset command and read "0x01" as confirmation + // Documentation not going in to such details unfortunately + if (!this->read_bytes_with_retry_(GDK101_REG_RESET, data, 2)) { + ESP_LOGE(TAG, "Updating GDK101 failed!"); + return false; + } + + return true; +} + +bool GDK101Component::read_dose_1m_(uint8_t *data) { +#ifdef USE_SENSOR + if (this->rad_1m_sensor_ != nullptr) { + if (!this->read_bytes(GDK101_REG_READ_1MIN_AVG, data, 2)) { + ESP_LOGE(TAG, "Updating GDK101 failed!"); + return false; + } + + const float dose = data[0] + (data[1] / 100.0f); + + this->rad_1m_sensor_->publish_state(dose); + } +#endif // USE_SENSOR + return true; +} + +bool GDK101Component::read_dose_10m_(uint8_t *data) { +#ifdef USE_SENSOR + if (this->rad_10m_sensor_ != nullptr) { + if (!this->read_bytes(GDK101_REG_READ_10MIN_AVG, data, 2)) { + ESP_LOGE(TAG, "Updating GDK101 failed!"); + return false; + } + + const float dose = data[0] + (data[1] / 100.0f); + + this->rad_10m_sensor_->publish_state(dose); + } +#endif // USE_SENSOR + return true; +} + +bool GDK101Component::read_status_(uint8_t *data) { + if (!this->read_bytes(GDK101_REG_READ_STATUS, data, 2)) { + ESP_LOGE(TAG, "Updating GDK101 failed!"); + return false; + } + +#ifdef USE_SENSOR + if (this->status_sensor_ != nullptr) { + this->status_sensor_->publish_state(data[0]); + } +#endif // USE_SENSOR + +#ifdef USE_BINARY_SENSOR + if (this->vibration_binary_sensor_ != nullptr) { + this->vibration_binary_sensor_->publish_state(data[1]); + } +#endif // USE_BINARY_SENSOR + + return true; +} + +bool GDK101Component::read_fw_version_(uint8_t *data) { +#ifdef USE_SENSOR + if (this->fw_version_sensor_ != nullptr) { + if (!this->read_bytes(GDK101_REG_READ_FIRMWARE, data, 2)) { + ESP_LOGE(TAG, "Updating GDK101 failed!"); + return false; + } + + const float fw_version = data[0] + (data[1] / 10.0f); + + this->fw_version_sensor_->publish_state(fw_version); + } +#endif // USE_SENSOR + return true; +} + +bool GDK101Component::read_measurement_duration_(uint8_t *data) { +#ifdef USE_SENSOR + if (this->measurement_duration_sensor_ != nullptr) { + if (!this->read_bytes(GDK101_REG_READ_MEASURING_TIME, data, 2)) { + ESP_LOGE(TAG, "Updating GDK101 failed!"); + return false; + } + + const float meas_time = (data[0] * 60) + data[1]; + + this->measurement_duration_sensor_->publish_state(meas_time); + } +#endif // USE_SENSOR + return true; +} + +} // namespace gdk101 +} // namespace esphome diff --git a/esphome/components/gdk101/gdk101.h b/esphome/components/gdk101/gdk101.h new file mode 100644 index 0000000000..460e72ac89 --- /dev/null +++ b/esphome/components/gdk101/gdk101.h @@ -0,0 +1,52 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/core/defines.h" +#ifdef USE_SENSOR +#include "esphome/components/sensor/sensor.h" +#endif // USE_SENSOR +#ifdef USE_BINARY_SENSOR +#include "esphome/components/binary_sensor/binary_sensor.h" +#endif // USE_BINARY_SENSOR +#include "esphome/components/i2c/i2c.h" + +namespace esphome { +namespace gdk101 { + +static const uint8_t GDK101_REG_READ_FIRMWARE = 0xB4; // Firmware version +static const uint8_t GDK101_REG_RESET = 0xA0; // Reset register - reading its value triggers reset +static const uint8_t GDK101_REG_READ_STATUS = 0xB0; // Status register +static const uint8_t GDK101_REG_READ_MEASURING_TIME = 0xB1; // Mesuring time +static const uint8_t GDK101_REG_READ_10MIN_AVG = 0xB2; // Average radiation dose per 10 min +static const uint8_t GDK101_REG_READ_1MIN_AVG = 0xB3; // Average radiation dose per 1 min + +class GDK101Component : public PollingComponent, public i2c::I2CDevice { +#ifdef USE_SENSOR + SUB_SENSOR(rad_1m) + SUB_SENSOR(rad_10m) + SUB_SENSOR(status) + SUB_SENSOR(fw_version) + SUB_SENSOR(measurement_duration) +#endif // USE_SENSOR +#ifdef USE_BINARY_SENSOR + SUB_BINARY_SENSOR(vibration) +#endif // USE_BINARY_SENSOR + + public: + void setup() override; + void dump_config() override; + float get_setup_priority() const override; + void update() override; + + protected: + bool read_bytes_with_retry_(uint8_t a_register, uint8_t *data, uint8_t len); + bool reset_sensor_(uint8_t *data); + bool read_dose_1m_(uint8_t *data); + bool read_dose_10m_(uint8_t *data); + bool read_status_(uint8_t *data); + bool read_fw_version_(uint8_t *data); + bool read_measurement_duration_(uint8_t *data); +}; + +} // namespace gdk101 +} // namespace esphome diff --git a/esphome/components/gdk101/sensor.py b/esphome/components/gdk101/sensor.py new file mode 100644 index 0000000000..f782264615 --- /dev/null +++ b/esphome/components/gdk101/sensor.py @@ -0,0 +1,83 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import sensor +from esphome.const import ( + DEVICE_CLASS_DURATION, + DEVICE_CLASS_EMPTY, + ENTITY_CATEGORY_DIAGNOSTIC, + CONF_MEASUREMENT_DURATION, + CONF_STATUS, + CONF_VERSION, + ICON_RADIOACTIVE, + ICON_TIMER, + STATE_CLASS_MEASUREMENT, + STATE_CLASS_TOTAL_INCREASING, + UNIT_MICROSILVERTS_PER_HOUR, + UNIT_SECOND, +) +from . import CONF_GDK101_ID, GDK101Component + +CONF_RADIATION_DOSE_PER_1M = "radiation_dose_per_1m" +CONF_RADIATION_DOSE_PER_10M = "radiation_dose_per_10m" + +DEPENDENCIES = ["gdk101"] + +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(CONF_GDK101_ID): cv.use_id(GDK101Component), + cv.Optional(CONF_RADIATION_DOSE_PER_1M): sensor.sensor_schema( + icon=ICON_RADIOACTIVE, + unit_of_measurement=UNIT_MICROSILVERTS_PER_HOUR, + accuracy_decimals=2, + device_class=DEVICE_CLASS_EMPTY, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_RADIATION_DOSE_PER_10M): sensor.sensor_schema( + icon=ICON_RADIOACTIVE, + unit_of_measurement=UNIT_MICROSILVERTS_PER_HOUR, + accuracy_decimals=2, + device_class=DEVICE_CLASS_EMPTY, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_VERSION): sensor.sensor_schema( + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + accuracy_decimals=1, + ), + cv.Optional(CONF_STATUS): sensor.sensor_schema( + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + accuracy_decimals=0, + ), + cv.Optional(CONF_MEASUREMENT_DURATION): sensor.sensor_schema( + unit_of_measurement=UNIT_SECOND, + icon=ICON_TIMER, + accuracy_decimals=0, + state_class=STATE_CLASS_TOTAL_INCREASING, + device_class=DEVICE_CLASS_DURATION, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + ), + } +) + + +async def to_code(config): + hub = await cg.get_variable(config[CONF_GDK101_ID]) + + if radiation_dose_per_1m := config.get(CONF_RADIATION_DOSE_PER_1M): + sens = await sensor.new_sensor(radiation_dose_per_1m) + cg.add(hub.set_rad_1m_sensor(sens)) + + if radiation_dose_per_10m := config.get(CONF_RADIATION_DOSE_PER_10M): + sens = await sensor.new_sensor(radiation_dose_per_10m) + cg.add(hub.set_rad_10m_sensor(sens)) + + if version_config := config.get(CONF_VERSION): + sens = await sensor.new_sensor(version_config) + cg.add(hub.set_fw_version_sensor(sens)) + + if status_config := config.get(CONF_STATUS): + sens = await sensor.new_sensor(status_config) + cg.add(hub.set_status_sensor(sens)) + + if measurement_duration_config := config.get(CONF_MEASUREMENT_DURATION): + sens = await sensor.new_sensor(measurement_duration_config) + cg.add(hub.set_measurement_duration_sensor(sens)) diff --git a/esphome/const.py b/esphome/const.py index dba974610a..542183d3b2 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -884,6 +884,7 @@ CONF_VALUE_FONT = "value_font" CONF_VARIABLES = "variables" CONF_VARIANT = "variant" CONF_VERSION = "version" +CONF_VIBRATIONS = "vibrations" CONF_VISIBLE = "visible" CONF_VISUAL = "visual" CONF_VOLTAGE = "voltage" @@ -983,6 +984,7 @@ ICON_SIGNAL_DISTANCE_VARIANT = "mdi:signal" ICON_THERMOMETER = "mdi:thermometer" ICON_TIMELAPSE = "mdi:timelapse" ICON_TIMER = "mdi:timer-outline" +ICON_VIBRATE = "mdi:vibrate" ICON_WATER = "mdi:water" ICON_WATER_PERCENT = "mdi:water-percent" ICON_WEATHER_SUNSET = "mdi:weather-sunset" @@ -1024,6 +1026,7 @@ UNIT_METER_PER_SECOND_SQUARED = "m/s²" UNIT_MICROGRAMS_PER_CUBIC_METER = "µg/m³" UNIT_MICROMETER = "µm" UNIT_MICROSIEMENS_PER_CENTIMETER = "µS/cm" +UNIT_MICROSILVERTS_PER_HOUR = "µSv/h" UNIT_MICROTESLA = "µT" UNIT_MILLIGRAMS_PER_CUBIC_METER = "mg/m³" UNIT_MILLISECOND = "ms" diff --git a/tests/components/gdk101/common.yaml b/tests/components/gdk101/common.yaml new file mode 100644 index 0000000000..f886fc415b --- /dev/null +++ b/tests/components/gdk101/common.yaml @@ -0,0 +1,28 @@ +i2c: + id: i2c_bus + sda: ${i2c_sda} + scl: ${i2c_scl} + +gdk101: + id: my_gdk101 + i2c_id: i2c_bus + +sensor: + - platform: gdk101 + gdk101_id: my_gdk101 + radiation_dose_per_1m: + name: Radiation Dose @ 1 min + radiation_dose_per_10m: + name: Radiation Dose @ 10 min + status: + name: Status + version: + name: FW Version + measurement_duration: + name: Measuring Time + +binary_sensor: + - platform: gdk101 + gdk101_id: my_gdk101 + vibrations: + name: Vibrations diff --git a/tests/components/gdk101/test.esp32-idf.yaml b/tests/components/gdk101/test.esp32-idf.yaml new file mode 100644 index 0000000000..1037d5d35b --- /dev/null +++ b/tests/components/gdk101/test.esp32-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + i2c_scl: GPIO16 + i2c_sda: GPIO17 + +<<: !include common.yaml diff --git a/tests/components/gdk101/test.esp32.yaml b/tests/components/gdk101/test.esp32.yaml new file mode 100644 index 0000000000..1037d5d35b --- /dev/null +++ b/tests/components/gdk101/test.esp32.yaml @@ -0,0 +1,5 @@ +substitutions: + i2c_scl: GPIO16 + i2c_sda: GPIO17 + +<<: !include common.yaml diff --git a/tests/components/gdk101/test.esp8266.yaml b/tests/components/gdk101/test.esp8266.yaml new file mode 100644 index 0000000000..d7ae0d5161 --- /dev/null +++ b/tests/components/gdk101/test.esp8266.yaml @@ -0,0 +1,5 @@ +substitutions: + i2c_scl: GPIO5 + i2c_sda: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/gdk101/test.rp2040.yaml b/tests/components/gdk101/test.rp2040.yaml new file mode 100644 index 0000000000..d7ae0d5161 --- /dev/null +++ b/tests/components/gdk101/test.rp2040.yaml @@ -0,0 +1,5 @@ +substitutions: + i2c_scl: GPIO5 + i2c_sda: GPIO4 + +<<: !include common.yaml From dd81c836862be87cdad41902f3847c097d8b0fa5 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Mon, 13 May 2024 13:21:02 +1000 Subject: [PATCH 1417/2101] Typing hint and doc fixes (#6729) --- esphome/cpp_generator.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/esphome/cpp_generator.py b/esphome/cpp_generator.py index 04616d97c2..9a4cb2269a 100644 --- a/esphome/cpp_generator.py +++ b/esphome/cpp_generator.py @@ -2,7 +2,7 @@ import abc import inspect import math import re -from collections.abc import Generator, Sequence +from collections.abc import Sequence from typing import Any, Callable, Optional, Union from esphome.core import ( @@ -477,6 +477,7 @@ def variable( :param rhs: The expression to place on the right hand side of the assignment. :param type_: Manually define a type for the variable, only use this when it's not possible to do so during config validation phase (for example because of template arguments). + :param register: If true register the variable with the core :return: The new variable as a MockObj. """ @@ -492,9 +493,7 @@ def variable( return obj -def with_local_variable( - id_: ID, rhs: SafeExpType, callback: Callable[["MockObj"], None], *args -) -> None: +def with_local_variable(id_: ID, rhs: SafeExpType, callback: Callable, *args) -> None: """Declare a new variable, not pointer type, in the code generation, within a scoped block The variable is only usable within the callback The callback cannot be async. @@ -599,6 +598,7 @@ def add_library(name: str, version: Optional[str], repository: Optional[str] = N :param name: The name of the library (for example 'AsyncTCP') :param version: The version of the library, may be None. + :param repository: The repository for the library """ CORE.add_library(Library(name, version, repository)) @@ -654,7 +654,7 @@ async def process_lambda( parameters: list[tuple[SafeExpType, str]], capture: str = "=", return_type: SafeExpType = None, -) -> Generator[LambdaExpression, None, None]: +) -> Union[LambdaExpression, None]: """Process the given lambda value into a LambdaExpression. This is a coroutine because lambdas can depend on other IDs, @@ -673,7 +673,7 @@ async def process_lambda( ) if value is None: - return + return None parts = value.parts[:] for i, id in enumerate(value.requires_ids): full_id, var = await get_variable_with_full_id(id) @@ -712,7 +712,7 @@ async def templatable( value: Any, args: list[tuple[SafeExpType, str]], output_type: Optional[SafeExpType], - to_exp: Any = None, + to_exp: Union[Callable, dict] = None, ): """Generate code for a templatable config option. From a23d1631e199ac274a1f11d5fbe16ee12fe5b65c Mon Sep 17 00:00:00 2001 From: Jorge-Crespo-Celdran <86021690+Jorge-Crespo-Celdran@users.noreply.github.com> Date: Mon, 13 May 2024 06:04:06 +0200 Subject: [PATCH 1418/2101] time_based_cover.cpp with manual control fix (#6719) --- esphome/components/time_based/time_based_cover.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/esphome/components/time_based/time_based_cover.cpp b/esphome/components/time_based/time_based_cover.cpp index 50376224a9..e1936d5ee1 100644 --- a/esphome/components/time_based/time_based_cover.cpp +++ b/esphome/components/time_based/time_based_cover.cpp @@ -96,6 +96,9 @@ void TimeBasedCover::control(const CoverCall &call) { } } else { auto op = pos < this->position ? COVER_OPERATION_CLOSING : COVER_OPERATION_OPENING; + if (this->manual_control_ && (pos == COVER_OPEN || pos == COVER_CLOSED)) { + this->position = pos == COVER_CLOSED ? COVER_OPEN : COVER_CLOSED; + } this->target_position_ = pos; this->start_direction_(op); } From 5ee4bf380215d705c19ac4a07fb27a84cbc660db Mon Sep 17 00:00:00 2001 From: Mischa Siekmann <45062894+gnumpi@users.noreply.github.com> Date: Mon, 13 May 2024 06:05:13 +0200 Subject: [PATCH 1419/2101] Set FEATURE_API_AUDIO flag also if the speaker component is not used (#6712) --- esphome/components/voice_assistant/voice_assistant.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/voice_assistant/voice_assistant.h b/esphome/components/voice_assistant/voice_assistant.h index d6b1502381..1c0ea12f4f 100644 --- a/esphome/components/voice_assistant/voice_assistant.h +++ b/esphome/components/voice_assistant/voice_assistant.h @@ -94,10 +94,10 @@ class VoiceAssistant : public Component { uint32_t get_feature_flags() const { uint32_t flags = 0; flags |= VoiceAssistantFeature::FEATURE_VOICE_ASSISTANT; + flags |= VoiceAssistantFeature::FEATURE_API_AUDIO; #ifdef USE_SPEAKER if (this->speaker_ != nullptr) { flags |= VoiceAssistantFeature::FEATURE_SPEAKER; - flags |= VoiceAssistantFeature::FEATURE_API_AUDIO; } #endif return flags; From 91007952e2276d09c4f52c1cc7ceabe3138c52eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20BOU=C3=89?= Date: Mon, 13 May 2024 11:21:06 +0100 Subject: [PATCH 1420/2101] [CST816] Add support for Hynitron Microelectronics CST826 capacitive touch (#6682) --- esphome/components/cst816/touchscreen/cst816_touchscreen.cpp | 4 ++++ esphome/components/cst816/touchscreen/cst816_touchscreen.h | 1 + 2 files changed, 5 insertions(+) diff --git a/esphome/components/cst816/touchscreen/cst816_touchscreen.cpp b/esphome/components/cst816/touchscreen/cst816_touchscreen.cpp index d2b8cc81f1..9e59810c7e 100644 --- a/esphome/components/cst816/touchscreen/cst816_touchscreen.cpp +++ b/esphome/components/cst816/touchscreen/cst816_touchscreen.cpp @@ -15,6 +15,7 @@ void CST816Touchscreen::continue_setup_() { } switch (this->chip_id_) { case CST820_CHIP_ID: + case CST826_CHIP_ID: case CST716_CHIP_ID: case CST816S_CHIP_ID: case CST816D_CHIP_ID: @@ -90,6 +91,9 @@ void CST816Touchscreen::dump_config() { case CST820_CHIP_ID: name = "CST820"; break; + case CST826_CHIP_ID: + name = "CST826"; + break; case CST816S_CHIP_ID: name = "CST816S"; break; diff --git a/esphome/components/cst816/touchscreen/cst816_touchscreen.h b/esphome/components/cst816/touchscreen/cst816_touchscreen.h index 0d987f2739..24e664e7ee 100644 --- a/esphome/components/cst816/touchscreen/cst816_touchscreen.h +++ b/esphome/components/cst816/touchscreen/cst816_touchscreen.h @@ -24,6 +24,7 @@ static const uint8_t REG_SLEEP = 0xE5; static const uint8_t REG_IRQ_CTL = 0xFA; static const uint8_t IRQ_EN_MOTION = 0x70; +static const uint8_t CST826_CHIP_ID = 0x11; static const uint8_t CST820_CHIP_ID = 0xB7; static const uint8_t CST816S_CHIP_ID = 0xB4; static const uint8_t CST816D_CHIP_ID = 0xB6; From eae97dbaa0d450872e35234ecb53f5119da4aa95 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 May 2024 07:11:59 +1200 Subject: [PATCH 1421/2101] Bump platformio from 6.1.13 to 6.1.15 (#6634) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index df94b8b77c..698ae56447 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,7 +9,7 @@ tornado==6.4 tzlocal==5.2 # from time tzdata>=2021.1 # from time pyserial==3.5 -platformio==6.1.13 # When updating platformio, also update Dockerfile +platformio==6.1.15 # When updating platformio, also update Dockerfile esptool==4.7.0 click==8.1.7 esphome-dashboard==20240412.0 From 47b40505c2952b4ee1d066119eac3d212a6761b1 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 14 May 2024 09:42:53 +1200 Subject: [PATCH 1422/2101] Fix ESPHOME_PROJECT_VERSION_30 (#6731) --- esphome/core/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/core/config.py b/esphome/core/config.py index 2d87796987..80b731b905 100644 --- a/esphome/core/config.py +++ b/esphome/core/config.py @@ -394,7 +394,7 @@ async def to_code(config): if project_conf := config.get(CONF_PROJECT): cg.add_define("ESPHOME_PROJECT_NAME", project_conf[CONF_NAME]) cg.add_define("ESPHOME_PROJECT_VERSION", project_conf[CONF_VERSION]) - cg.add_define("ESPHOME_PROJECT_VERSION_30", project_conf[CONF_VERSION][:30]) + cg.add_define("ESPHOME_PROJECT_VERSION_30", project_conf[CONF_VERSION][:29]) for conf in project_conf.get(CONF_ON_UPDATE, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID]) await cg.register_component(trigger, conf) From 2ac0821cab11c4fbd23d17af1ada42577156d258 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 May 2024 09:58:43 +1200 Subject: [PATCH 1423/2101] Bump pytest from 8.1.1 to 8.2.0 (#6732) 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 78820765f4..ae833841ca 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -5,7 +5,7 @@ pyupgrade==3.15.2 # also change in .pre-commit-config.yaml when updating pre-commit # Unit tests -pytest==8.1.1 +pytest==8.2.0 pytest-cov==4.1.0 pytest-mock==3.14.0 pytest-asyncio==0.23.6 From 4ec2ef27a87cb8efa5f8a3899bd0fa7e2a80068c Mon Sep 17 00:00:00 2001 From: Marcin Krasowski Date: Mon, 13 May 2024 01:25:41 +0200 Subject: [PATCH 1424/2101] fix(ltr390): stuck ALS values when configured for ALS+UV readings (#6723) --- esphome/components/ltr390/ltr390.cpp | 31 ++++++++++++++++++---------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/esphome/components/ltr390/ltr390.cpp b/esphome/components/ltr390/ltr390.cpp index 65c08ab614..4eb1ff2c46 100644 --- a/esphome/components/ltr390/ltr390.cpp +++ b/esphome/components/ltr390/ltr390.cpp @@ -8,6 +8,9 @@ namespace ltr390 { static const char *const TAG = "ltr390"; +static const uint8_t LTR390_WAKEUP_TIME = 10; +static const uint8_t LTR390_SETTLE_TIME = 5; + static const uint8_t LTR390_MAIN_CTRL = 0x00; static const uint8_t LTR390_MEAS_RATE = 0x04; static const uint8_t LTR390_GAIN = 0x05; @@ -101,21 +104,27 @@ void LTR390Component::read_mode_(int mode_index) { std::bitset<8> ctrl = this->reg(LTR390_MAIN_CTRL).get(); ctrl[LTR390_CTRL_MODE] = mode; + ctrl[LTR390_CTRL_EN] = true; this->reg(LTR390_MAIN_CTRL) = ctrl.to_ulong(); // After the sensor integration time do the following - this->set_timeout(((uint32_t) RESOLUTIONVALUE[this->res_]) * 100, [this, mode_index]() { - // Read from the sensor - std::get<1>(this->mode_funcs_[mode_index])(); + this->set_timeout(((uint32_t) RESOLUTIONVALUE[this->res_]) * 100 + LTR390_WAKEUP_TIME + LTR390_SETTLE_TIME, + [this, mode_index]() { + // Read from the sensor + std::get<1>(this->mode_funcs_[mode_index])(); - // If there are more modes to read then begin the next - // otherwise stop - if (mode_index + 1 < (int) this->mode_funcs_.size()) { - this->read_mode_(mode_index + 1); - } else { - this->reading_ = false; - } - }); + // If there are more modes to read then begin the next + // otherwise stop + if (mode_index + 1 < (int) this->mode_funcs_.size()) { + this->read_mode_(mode_index + 1); + } else { + // put sensor in standby + std::bitset<8> ctrl = this->reg(LTR390_MAIN_CTRL).get(); + ctrl[LTR390_CTRL_EN] = false; + this->reg(LTR390_MAIN_CTRL) = ctrl.to_ulong(); + this->reading_ = false; + } + }); } void LTR390Component::setup() { From 694f75117e63e1261c873cb5fc080b2d4591b956 Mon Sep 17 00:00:00 2001 From: Mischa Siekmann <45062894+gnumpi@users.noreply.github.com> Date: Mon, 13 May 2024 06:05:13 +0200 Subject: [PATCH 1425/2101] Set FEATURE_API_AUDIO flag also if the speaker component is not used (#6712) --- esphome/components/voice_assistant/voice_assistant.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/voice_assistant/voice_assistant.h b/esphome/components/voice_assistant/voice_assistant.h index d6b1502381..1c0ea12f4f 100644 --- a/esphome/components/voice_assistant/voice_assistant.h +++ b/esphome/components/voice_assistant/voice_assistant.h @@ -94,10 +94,10 @@ class VoiceAssistant : public Component { uint32_t get_feature_flags() const { uint32_t flags = 0; flags |= VoiceAssistantFeature::FEATURE_VOICE_ASSISTANT; + flags |= VoiceAssistantFeature::FEATURE_API_AUDIO; #ifdef USE_SPEAKER if (this->speaker_ != nullptr) { flags |= VoiceAssistantFeature::FEATURE_SPEAKER; - flags |= VoiceAssistantFeature::FEATURE_API_AUDIO; } #endif return flags; From ba3fc4c5d08dd643099590daf42c5638d496d128 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 May 2024 07:11:59 +1200 Subject: [PATCH 1426/2101] Bump platformio from 6.1.13 to 6.1.15 (#6634) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index df94b8b77c..698ae56447 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,7 +9,7 @@ tornado==6.4 tzlocal==5.2 # from time tzdata>=2021.1 # from time pyserial==3.5 -platformio==6.1.13 # When updating platformio, also update Dockerfile +platformio==6.1.15 # When updating platformio, also update Dockerfile esptool==4.7.0 click==8.1.7 esphome-dashboard==20240412.0 From 5afe0e5ec2a3619a341593884d7fe4ce6e35a791 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 14 May 2024 09:42:53 +1200 Subject: [PATCH 1427/2101] Fix ESPHOME_PROJECT_VERSION_30 (#6731) --- esphome/core/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/core/config.py b/esphome/core/config.py index 2d87796987..80b731b905 100644 --- a/esphome/core/config.py +++ b/esphome/core/config.py @@ -394,7 +394,7 @@ async def to_code(config): if project_conf := config.get(CONF_PROJECT): cg.add_define("ESPHOME_PROJECT_NAME", project_conf[CONF_NAME]) cg.add_define("ESPHOME_PROJECT_VERSION", project_conf[CONF_VERSION]) - cg.add_define("ESPHOME_PROJECT_VERSION_30", project_conf[CONF_VERSION][:30]) + cg.add_define("ESPHOME_PROJECT_VERSION_30", project_conf[CONF_VERSION][:29]) for conf in project_conf.get(CONF_ON_UPDATE, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID]) await cg.register_component(trigger, conf) From 1e4d6ee34457f7afc3d7f26fddc72cec893702c1 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 14 May 2024 10:02:22 +1200 Subject: [PATCH 1428/2101] Bump version to 2024.5.0b4 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 6e00c1bbe1..e3d9bfeb64 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.5.0b3" +__version__ = "2024.5.0b4" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 921e56f2c693d8dd2facd642967c4f39db32e0d3 Mon Sep 17 00:00:00 2001 From: Mischa Siekmann <45062894+gnumpi@users.noreply.github.com> Date: Tue, 14 May 2024 03:25:24 +0200 Subject: [PATCH 1429/2101] =?UTF-8?q?Voice-Assistant:=20Start-order=20chan?= =?UTF-8?q?ge=20for=20VAD=20disabled:=20start=20va-pipeline=20when=20micro?= =?UTF-8?q?phon=E2=80=A6=20(#6391)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- esphome/components/voice_assistant/voice_assistant.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index e68e00948e..3bd41e1fcf 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -152,7 +152,7 @@ void VoiceAssistant::loop() { } else #endif { - this->set_state_(State::START_PIPELINE, State::START_MICROPHONE); + this->set_state_(State::START_MICROPHONE, State::START_PIPELINE); } } else { this->high_freq_.stop(); @@ -514,7 +514,7 @@ void VoiceAssistant::request_start(bool continuous, bool silence_detection) { } else #endif { - this->set_state_(State::START_PIPELINE, State::START_MICROPHONE); + this->set_state_(State::START_MICROPHONE, State::START_PIPELINE); } } } From 036a666e369009a7d85b4c1614cccdf296e3809f Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 14 May 2024 15:38:53 +1200 Subject: [PATCH 1430/2101] [web_server] Minor python formatting (#6735) --- esphome/components/web_server/__init__.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/esphome/components/web_server/__init__.py b/esphome/components/web_server/__init__.py index bbd5bc662e..fa614fb5a6 100644 --- a/esphome/components/web_server/__init__.py +++ b/esphome/components/web_server/__init__.py @@ -35,19 +35,19 @@ WebServer = web_server_ns.class_("WebServer", cg.Component, cg.Controller) def default_url(config): config = config.copy() if config[CONF_VERSION] == 1: - if not (CONF_CSS_URL in config): + if CONF_CSS_URL not in config: config[CONF_CSS_URL] = "https://esphome.io/_static/webserver-v1.min.css" - if not (CONF_JS_URL in config): + if CONF_JS_URL not in config: config[CONF_JS_URL] = "https://esphome.io/_static/webserver-v1.min.js" if config[CONF_VERSION] == 2: - if not (CONF_CSS_URL in config): + if CONF_CSS_URL not in config: config[CONF_CSS_URL] = "" - if not (CONF_JS_URL in config): + if CONF_JS_URL not in config: config[CONF_JS_URL] = "https://oi.esphome.io/v2/www.js" if config[CONF_VERSION] == 3: - if not (CONF_CSS_URL in config): + if CONF_CSS_URL not in config: config[CONF_CSS_URL] = "" - if not (CONF_JS_URL in config): + if CONF_JS_URL not in config: config[CONF_JS_URL] = "https://oi.esphome.io/v3/www.js" return config From 7d791cbdfb028e24bc75e67af81919904ef78301 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 14 May 2024 16:22:43 +1200 Subject: [PATCH 1431/2101] [esp32_ble] Fix compilation error on esp32c6 (#6734) --- esphome/components/esp32_ble/ble.cpp | 9 +++ esphome/components/esp32_ble/const_esp32c6.h | 67 ++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 esphome/components/esp32_ble/const_esp32c6.h diff --git a/esphome/components/esp32_ble/ble.cpp b/esphome/components/esp32_ble/ble.cpp index 3797f3221e..ceb6516a02 100644 --- a/esphome/components/esp32_ble/ble.cpp +++ b/esphome/components/esp32_ble/ble.cpp @@ -1,6 +1,11 @@ #ifdef USE_ESP32 #include "ble.h" + +#ifdef USE_ESP32_VARIANT_ESP32C6 +#include "const_esp32c6.h" +#endif // USE_ESP32_VARIANT_ESP32C6 + #include "esphome/core/application.h" #include "esphome/core/log.h" @@ -114,7 +119,11 @@ bool ESP32BLE::ble_setup_() { if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) { // start bt controller if (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_IDLE) { +#ifdef USE_ESP32_VARIANT_ESP32C6 + esp_bt_controller_config_t cfg = BT_CONTROLLER_CONFIG; +#else esp_bt_controller_config_t cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); +#endif err = esp_bt_controller_init(&cfg); if (err != ESP_OK) { ESP_LOGE(TAG, "esp_bt_controller_init failed: %s", esp_err_to_name(err)); diff --git a/esphome/components/esp32_ble/const_esp32c6.h b/esphome/components/esp32_ble/const_esp32c6.h new file mode 100644 index 0000000000..69f9adcf6b --- /dev/null +++ b/esphome/components/esp32_ble/const_esp32c6.h @@ -0,0 +1,67 @@ +#pragma once + +#ifdef USE_ESP32_VARIANT_ESP32C6 + +#include + +namespace esphome { +namespace esp32_ble { + +static const esp_bt_controller_config_t BT_CONTROLLER_CONFIG = { + .config_version = CONFIG_VERSION, + .ble_ll_resolv_list_size = CONFIG_BT_LE_LL_RESOLV_LIST_SIZE, + .ble_hci_evt_hi_buf_count = DEFAULT_BT_LE_HCI_EVT_HI_BUF_COUNT, + .ble_hci_evt_lo_buf_count = DEFAULT_BT_LE_HCI_EVT_LO_BUF_COUNT, + .ble_ll_sync_list_cnt = DEFAULT_BT_LE_MAX_PERIODIC_ADVERTISER_LIST, + .ble_ll_sync_cnt = DEFAULT_BT_LE_MAX_PERIODIC_SYNCS, + .ble_ll_rsp_dup_list_count = CONFIG_BT_LE_LL_DUP_SCAN_LIST_COUNT, + .ble_ll_adv_dup_list_count = CONFIG_BT_LE_LL_DUP_SCAN_LIST_COUNT, + .ble_ll_tx_pwr_dbm = BLE_LL_TX_PWR_DBM_N, + .rtc_freq = RTC_FREQ_N, + .ble_ll_sca = CONFIG_BT_LE_LL_SCA, + .ble_ll_scan_phy_number = BLE_LL_SCAN_PHY_NUMBER_N, + .ble_ll_conn_def_auth_pyld_tmo = BLE_LL_CONN_DEF_AUTH_PYLD_TMO_N, + .ble_ll_jitter_usecs = BLE_LL_JITTER_USECS_N, + .ble_ll_sched_max_adv_pdu_usecs = BLE_LL_SCHED_MAX_ADV_PDU_USECS_N, + .ble_ll_sched_direct_adv_max_usecs = BLE_LL_SCHED_DIRECT_ADV_MAX_USECS_N, + .ble_ll_sched_adv_max_usecs = BLE_LL_SCHED_ADV_MAX_USECS_N, + .ble_scan_rsp_data_max_len = DEFAULT_BT_LE_SCAN_RSP_DATA_MAX_LEN_N, + .ble_ll_cfg_num_hci_cmd_pkts = BLE_LL_CFG_NUM_HCI_CMD_PKTS_N, + .ble_ll_ctrl_proc_timeout_ms = BLE_LL_CTRL_PROC_TIMEOUT_MS_N, + .nimble_max_connections = DEFAULT_BT_LE_MAX_CONNECTIONS, + .ble_whitelist_size = DEFAULT_BT_NIMBLE_WHITELIST_SIZE, // NOLINT + .ble_acl_buf_size = DEFAULT_BT_LE_ACL_BUF_SIZE, + .ble_acl_buf_count = DEFAULT_BT_LE_ACL_BUF_COUNT, + .ble_hci_evt_buf_size = DEFAULT_BT_LE_HCI_EVT_BUF_SIZE, + .ble_multi_adv_instances = DEFAULT_BT_LE_MAX_EXT_ADV_INSTANCES, + .ble_ext_adv_max_size = DEFAULT_BT_LE_EXT_ADV_MAX_SIZE, + .controller_task_stack_size = NIMBLE_LL_STACK_SIZE, + .controller_task_prio = ESP_TASK_BT_CONTROLLER_PRIO, + .controller_run_cpu = 0, + .enable_qa_test = RUN_QA_TEST, + .enable_bqb_test = RUN_BQB_TEST, + .enable_uart_hci = HCI_UART_EN, + .ble_hci_uart_port = DEFAULT_BT_LE_HCI_UART_PORT, + .ble_hci_uart_baud = DEFAULT_BT_LE_HCI_UART_BAUD, + .ble_hci_uart_data_bits = DEFAULT_BT_LE_HCI_UART_DATA_BITS, + .ble_hci_uart_stop_bits = DEFAULT_BT_LE_HCI_UART_STOP_BITS, + .ble_hci_uart_flow_ctrl = DEFAULT_BT_LE_HCI_UART_FLOW_CTRL, + .ble_hci_uart_uart_parity = DEFAULT_BT_LE_HCI_UART_PARITY, + .enable_tx_cca = DEFAULT_BT_LE_TX_CCA_ENABLED, + .cca_rssi_thresh = 256 - DEFAULT_BT_LE_CCA_RSSI_THRESH, + .sleep_en = NIMBLE_SLEEP_ENABLE, + .coex_phy_coded_tx_rx_time_limit = DEFAULT_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF, + .dis_scan_backoff = NIMBLE_DISABLE_SCAN_BACKOFF, + .ble_scan_classify_filter_enable = 1, + .main_xtal_freq = CONFIG_XTAL_FREQ, + .version_num = (uint8_t) efuse_hal_chip_revision(), + .cpu_freq_mhz = CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ, + .ignore_wl_for_direct_adv = 0, + .enable_pcl = DEFAULT_BT_LE_POWER_CONTROL_ENABLED, + .config_magic = CONFIG_MAGIC, +}; + +} // namespace esp32_ble +} // namespace esphome + +#endif // USE_ESP32_VARIANT_ESP32C6 From 636037cec17bb0abae6def201fd1273bc752cea2 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 14 May 2024 17:01:07 +1200 Subject: [PATCH 1432/2101] [core] Fix minor formatting issues (#6738) --- esphome/__main__.py | 2 +- esphome/components/animation/__init__.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/esphome/__main__.py b/esphome/__main__.py index 54c1aa112a..daf74eebb0 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -65,7 +65,7 @@ def choose_prompt(options, purpose: str = None): f'Found multiple options{f" for {purpose}" if purpose else ""}, please choose one:' ) for i, (desc, _) in enumerate(options): - safe_print(f" [{i+1}] {desc}") + safe_print(f" [{i + 1}] {desc}") while True: opt = input("(number): ") diff --git a/esphome/components/animation/__init__.py b/esphome/components/animation/__init__.py index 9151d6e56d..a7a955bead 100644 --- a/esphome/components/animation/__init__.py +++ b/esphome/components/animation/__init__.py @@ -157,7 +157,7 @@ async def to_code(config): pixels = list(frame.getdata()) if len(pixels) != height * width: raise core.EsphomeError( - f"Unexpected number of pixels in {path} frame {frameIndex}: ({len(pixels)} != {height*width})" + f"Unexpected number of pixels in {path} frame {frameIndex}: ({len(pixels)} != {height * width})" ) for pix, a in pixels: if transparent: @@ -180,7 +180,7 @@ async def to_code(config): pixels = list(frame.getdata()) if len(pixels) != height * width: raise core.EsphomeError( - f"Unexpected number of pixels in {path} frame {frameIndex}: ({len(pixels)} != {height*width})" + f"Unexpected number of pixels in {path} frame {frameIndex}: ({len(pixels)} != {height * width})" ) for pix in pixels: data[pos] = pix[0] @@ -203,7 +203,7 @@ async def to_code(config): pixels = list(frame.getdata()) if len(pixels) != height * width: raise core.EsphomeError( - f"Unexpected number of pixels in {path} frame {frameIndex}: ({len(pixels)} != {height*width})" + f"Unexpected number of pixels in {path} frame {frameIndex}: ({len(pixels)} != {height * width})" ) for r, g, b, a in pixels: if transparent: @@ -232,7 +232,7 @@ async def to_code(config): pixels = list(frame.getdata()) if len(pixels) != height * width: raise core.EsphomeError( - f"Unexpected number of pixels in {path} frame {frameIndex}: ({len(pixels)} != {height*width})" + f"Unexpected number of pixels in {path} frame {frameIndex}: ({len(pixels)} != {height * width})" ) for r, g, b, a in pixels: R = r >> 3 From d5eeab81d66f6d053a995f792a22424f7095527d Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Tue, 14 May 2024 19:31:03 +1000 Subject: [PATCH 1433/2101] [config] Improve error reporting (#6736) --- esphome/config.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/esphome/config.py b/esphome/config.py index 4f340225fe..2b231fc402 100644 --- a/esphome/config.py +++ b/esphome/config.py @@ -34,7 +34,7 @@ from esphome.voluptuous_schema import ExtraKeysInvalid from esphome.log import color, Fore import esphome.final_validate as fv import esphome.config_validation as cv -from esphome.types import ConfigType, ConfigPathType, ConfigFragmentType +from esphome.types import ConfigType, ConfigFragmentType _LOGGER = logging.getLogger(__name__) @@ -213,7 +213,7 @@ class Config(OrderedDict, fv.FinalValidateConfig): return doc_range def get_nested_item( - self, path: ConfigPathType, raise_error: bool = False + self, path: ConfigPath, raise_error: bool = False ) -> ConfigFragmentType: data = self for item_index in path: @@ -244,7 +244,7 @@ class Config(OrderedDict, fv.FinalValidateConfig): return path raise KeyError(f"ID {id} not found in configuration") - def get_config_for_path(self, path: ConfigPathType) -> ConfigFragmentType: + def get_config_for_path(self, path: ConfigPath) -> ConfigFragmentType: return self.get_nested_item(path, raise_error=True) @property @@ -885,6 +885,9 @@ def _get_parent_name(path, config): # Sub-item break return domain + # When processing a list, skip back over the index + while len(path) > 1 and isinstance(path[-1], int): + path = path[:-1] return path[-1] @@ -1106,7 +1109,14 @@ def read_config(command_line_substitutions): if errline: errstr += f" {errline}" safe_print(errstr) - safe_print(indent(dump_dict(res, path)[0])) + split_dump = dump_dict(res, path)[0].splitlines() + # find the last error message + i = len(split_dump) - 1 + while i > 10 and "\033[" not in split_dump[i]: + i = i - 1 + # discard lines more than 4 beyond the last error + i = min(i + 4, len(split_dump)) + safe_print(indent("\n".join(split_dump[:i]))) for err in res.errors: safe_print(color(Fore.BOLD_RED, err.msg)) From 6f53607e5ad20594268c2ed7ade53c8f95bcc070 Mon Sep 17 00:00:00 2001 From: Mischa Siekmann <45062894+gnumpi@users.noreply.github.com> Date: Tue, 14 May 2024 11:40:08 +0200 Subject: [PATCH 1434/2101] Add ANNOUNCING state to media_player. (#6691) --- esphome/components/api/api.proto | 3 +++ esphome/components/api/api_connection.cpp | 9 ++++++++- esphome/components/api/api_pb2.cpp | 18 ++++++++++++++++++ esphome/components/api/api_pb2.h | 2 ++ .../media_player/i2s_audio_media_player.cpp | 17 ++++++++++++++--- .../media_player/i2s_audio_media_player.h | 1 + esphome/components/media_player/__init__.py | 12 ++++++++++++ esphome/components/media_player/automation.h | 1 + .../components/media_player/media_player.cpp | 10 ++++++++++ esphome/components/media_player/media_player.h | 6 +++++- .../voice_assistant/voice_assistant.cpp | 4 ++-- 11 files changed, 76 insertions(+), 7 deletions(-) diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index b8073abc19..774ca7ed9b 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -1147,6 +1147,9 @@ message MediaPlayerCommandRequest { bool has_media_url = 6; string media_url = 7; + + bool has_announcement = 8; + bool announcement = 9; } // ==================== BLUETOOTH ==================== diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index b31212bbdb..2804dba31f 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1002,7 +1002,11 @@ bool APIConnection::send_media_player_state(media_player::MediaPlayer *media_pla MediaPlayerStateResponse resp{}; resp.key = media_player->get_object_id_hash(); - resp.state = static_cast(media_player->state); + + media_player::MediaPlayerState report_state = media_player->state == media_player::MEDIA_PLAYER_STATE_ANNOUNCING + ? media_player::MEDIA_PLAYER_STATE_PLAYING + : media_player->state; + resp.state = static_cast(report_state); resp.volume = media_player->volume; resp.muted = media_player->is_muted(); return this->send_media_player_state_response(resp); @@ -1038,6 +1042,9 @@ void APIConnection::media_player_command(const MediaPlayerCommandRequest &msg) { if (msg.has_media_url) { call.set_media_url(msg.media_url); } + if (msg.has_announcement) { + call.set_announcement(msg.announcement); + } call.perform(); } #endif diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index 6ec1870d72..a48087e348 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -5253,6 +5253,14 @@ bool MediaPlayerCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt val this->has_media_url = value.as_bool(); return true; } + case 8: { + this->has_announcement = value.as_bool(); + return true; + } + case 9: { + this->announcement = value.as_bool(); + return true; + } default: return false; } @@ -5289,6 +5297,8 @@ void MediaPlayerCommandRequest::encode(ProtoWriteBuffer buffer) const { buffer.encode_float(5, this->volume); buffer.encode_bool(6, this->has_media_url); buffer.encode_string(7, this->media_url); + buffer.encode_bool(8, this->has_announcement); + buffer.encode_bool(9, this->announcement); } #ifdef HAS_PROTO_MESSAGE_DUMP void MediaPlayerCommandRequest::dump_to(std::string &out) const { @@ -5323,6 +5333,14 @@ void MediaPlayerCommandRequest::dump_to(std::string &out) const { out.append(" media_url: "); out.append("'").append(this->media_url).append("'"); out.append("\n"); + + out.append(" has_announcement: "); + out.append(YESNO(this->has_announcement)); + out.append("\n"); + + out.append(" announcement: "); + out.append(YESNO(this->announcement)); + out.append("\n"); out.append("}"); } #endif diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index 14fd95df37..807b150d82 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -1298,6 +1298,8 @@ class MediaPlayerCommandRequest : public ProtoMessage { float volume{0.0f}; bool has_media_url{false}; std::string media_url{}; + bool has_announcement{false}; + bool announcement{false}; void encode(ProtoWriteBuffer buffer) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; 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 6e07983920..1890e27bdf 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 @@ -10,6 +10,11 @@ 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; + if (call.get_announcement().has_value()) { + play_state = call.get_announcement().value() ? 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(); if (this->i2s_state_ != I2S_STATE_STOPPED && this->audio_ != nullptr) { @@ -17,7 +22,7 @@ void I2SAudioMediaPlayer::control(const media_player::MediaPlayerCall &call) { this->audio_->stopSong(); } this->audio_->connecttohost(this->current_url_.value().c_str()); - this->state = media_player::MEDIA_PLAYER_STATE_PLAYING; + this->state = play_state; } else { this->start(); } @@ -35,7 +40,7 @@ void I2SAudioMediaPlayer::control(const media_player::MediaPlayerCall &call) { case media_player::MEDIA_PLAYER_COMMAND_PLAY: if (!this->audio_->isRunning()) this->audio_->pauseResume(); - this->state = media_player::MEDIA_PLAYER_STATE_PLAYING; + this->state = play_state; break; case media_player::MEDIA_PLAYER_COMMAND_PAUSE: if (this->audio_->isRunning()) @@ -126,7 +131,9 @@ void I2SAudioMediaPlayer::loop() { void I2SAudioMediaPlayer::play_() { this->audio_->loop(); - if (this->state == media_player::MEDIA_PLAYER_STATE_PLAYING && !this->audio_->isRunning()) { + if ((this->state == media_player::MEDIA_PLAYER_STATE_PLAYING || + this->state == media_player::MEDIA_PLAYER_STATE_ANNOUNCING) && + !this->audio_->isRunning()) { this->stop(); } } @@ -164,6 +171,10 @@ void I2SAudioMediaPlayer::start_() { if (this->current_url_.has_value()) { this->audio_->connecttohost(this->current_url_.value().c_str()); this->state = media_player::MEDIA_PLAYER_STATE_PLAYING; + if (this->is_announcement_.has_value()) { + this->state = this->is_announcement_.value() ? media_player::MEDIA_PLAYER_STATE_ANNOUNCING + : media_player::MEDIA_PLAYER_STATE_PLAYING; + } this->publish_state(); } } diff --git a/esphome/components/i2s_audio/media_player/i2s_audio_media_player.h b/esphome/components/i2s_audio/media_player/i2s_audio_media_player.h index 092e6de8e8..d7d9b1f74a 100644 --- a/esphome/components/i2s_audio/media_player/i2s_audio_media_player.h +++ b/esphome/components/i2s_audio/media_player/i2s_audio_media_player.h @@ -78,6 +78,7 @@ class I2SAudioMediaPlayer : public Component, public media_player::MediaPlayer, HighFrequencyLoopRequester high_freq_; optional current_url_{}; + optional is_announcement_{}; }; } // namespace i2s_audio diff --git a/esphome/components/media_player/__init__.py b/esphome/components/media_player/__init__.py index 5db78150bb..320014e355 100644 --- a/esphome/components/media_player/__init__.py +++ b/esphome/components/media_player/__init__.py @@ -51,12 +51,16 @@ VolumeSetAction = media_player_ns.class_( 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() +) IsIdleCondition = media_player_ns.class_("IsIdleCondition", automation.Condition) IsPlayingCondition = media_player_ns.class_("IsPlayingCondition", automation.Condition) @@ -75,6 +79,9 @@ async def setup_media_player_core_(var, config): 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) async def register_media_player(var, config): @@ -106,6 +113,11 @@ MEDIA_PLAYER_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend( 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), + } + ), } ) diff --git a/esphome/components/media_player/automation.h b/esphome/components/media_player/automation.h index 261e93775c..fc3ce7a764 100644 --- a/esphome/components/media_player/automation.h +++ b/esphome/components/media_player/automation.h @@ -52,6 +52,7 @@ class StateTrigger : public Trigger<> { MEDIA_PLAYER_SIMPLE_STATE_TRIGGER(IdleTrigger, IDLE) MEDIA_PLAYER_SIMPLE_STATE_TRIGGER(PlayTrigger, PLAYING) MEDIA_PLAYER_SIMPLE_STATE_TRIGGER(PauseTrigger, PAUSED) +MEDIA_PLAYER_SIMPLE_STATE_TRIGGER(AnnouncementTrigger, ANNOUNCING) template class IsIdleCondition : public Condition, public Parented { public: diff --git a/esphome/components/media_player/media_player.cpp b/esphome/components/media_player/media_player.cpp index 81cb6ca751..586345ac9f 100644 --- a/esphome/components/media_player/media_player.cpp +++ b/esphome/components/media_player/media_player.cpp @@ -15,6 +15,8 @@ const char *media_player_state_to_string(MediaPlayerState state) { return "PLAYING"; case MEDIA_PLAYER_STATE_PAUSED: return "PAUSED"; + case MEDIA_PLAYER_STATE_ANNOUNCING: + return "ANNOUNCING"; case MEDIA_PLAYER_STATE_NONE: default: return "UNKNOWN"; @@ -68,6 +70,9 @@ void MediaPlayerCall::perform() { if (this->volume_.has_value()) { ESP_LOGD(TAG, " Volume: %.2f", this->volume_.value()); } + if (this->announcement_.has_value()) { + ESP_LOGD(TAG, " Announcement: %s", this->announcement_.value() ? "yes" : "no"); + } this->parent_->control(*this); } @@ -108,6 +113,11 @@ MediaPlayerCall &MediaPlayerCall::set_volume(float volume) { return *this; } +MediaPlayerCall &MediaPlayerCall::set_announcement(bool announce) { + this->announcement_ = announce; + return *this; +} + void MediaPlayer::add_on_state_callback(std::function &&callback) { this->state_callback_.add(std::move(callback)); } diff --git a/esphome/components/media_player/media_player.h b/esphome/components/media_player/media_player.h index 88114d5337..77746e1808 100644 --- a/esphome/components/media_player/media_player.h +++ b/esphome/components/media_player/media_player.h @@ -10,7 +10,8 @@ enum MediaPlayerState : uint8_t { MEDIA_PLAYER_STATE_NONE = 0, MEDIA_PLAYER_STATE_IDLE = 1, MEDIA_PLAYER_STATE_PLAYING = 2, - MEDIA_PLAYER_STATE_PAUSED = 3 + MEDIA_PLAYER_STATE_PAUSED = 3, + MEDIA_PLAYER_STATE_ANNOUNCING = 4 }; const char *media_player_state_to_string(MediaPlayerState state); @@ -51,12 +52,14 @@ class MediaPlayerCall { MediaPlayerCall &set_media_url(const std::string &url); MediaPlayerCall &set_volume(float volume); + MediaPlayerCall &set_announcement(bool announce); void perform(); const optional &get_command() const { return command_; } const optional &get_media_url() const { return media_url_; } const optional &get_volume() const { return volume_; } + const optional &get_announcement() const { return announcement_; } protected: void validate_(); @@ -64,6 +67,7 @@ class MediaPlayerCall { optional command_; optional media_url_; optional volume_; + optional announcement_; }; class MediaPlayer : public EntityBase { diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index 3bd41e1fcf..109e52f8eb 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -318,7 +318,7 @@ void VoiceAssistant::loop() { #endif #ifdef USE_MEDIA_PLAYER if (this->media_player_ != nullptr) { - playing = (this->media_player_->state == media_player::MediaPlayerState::MEDIA_PLAYER_STATE_PLAYING); + playing = (this->media_player_->state == media_player::MediaPlayerState::MEDIA_PLAYER_STATE_ANNOUNCING); } #endif if (playing) { @@ -640,7 +640,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { this->defer([this, url]() { #ifdef USE_MEDIA_PLAYER if (this->media_player_ != nullptr) { - this->media_player_->make_call().set_media_url(url).perform(); + this->media_player_->make_call().set_media_url(url).set_announcement(true).perform(); } #endif this->tts_end_trigger_->trigger(url); From 128fad57b3f91907ce8cacb3e91dbc96e8fc51a6 Mon Sep 17 00:00:00 2001 From: Mischa Siekmann <45062894+gnumpi@users.noreply.github.com> Date: Tue, 14 May 2024 03:25:24 +0200 Subject: [PATCH 1435/2101] =?UTF-8?q?Voice-Assistant:=20Start-order=20chan?= =?UTF-8?q?ge=20for=20VAD=20disabled:=20start=20va-pipeline=20when=20micro?= =?UTF-8?q?phon=E2=80=A6=20(#6391)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- esphome/components/voice_assistant/voice_assistant.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index e68e00948e..3bd41e1fcf 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -152,7 +152,7 @@ void VoiceAssistant::loop() { } else #endif { - this->set_state_(State::START_PIPELINE, State::START_MICROPHONE); + this->set_state_(State::START_MICROPHONE, State::START_PIPELINE); } } else { this->high_freq_.stop(); @@ -514,7 +514,7 @@ void VoiceAssistant::request_start(bool continuous, bool silence_detection) { } else #endif { - this->set_state_(State::START_PIPELINE, State::START_MICROPHONE); + this->set_state_(State::START_MICROPHONE, State::START_PIPELINE); } } } From 28a09cc0d03d4842961e04d8ade99c3cbc6a5269 Mon Sep 17 00:00:00 2001 From: Mischa Siekmann <45062894+gnumpi@users.noreply.github.com> Date: Tue, 14 May 2024 11:40:08 +0200 Subject: [PATCH 1436/2101] Add ANNOUNCING state to media_player. (#6691) --- esphome/components/api/api.proto | 3 +++ esphome/components/api/api_connection.cpp | 9 ++++++++- esphome/components/api/api_pb2.cpp | 18 ++++++++++++++++++ esphome/components/api/api_pb2.h | 2 ++ .../media_player/i2s_audio_media_player.cpp | 17 ++++++++++++++--- .../media_player/i2s_audio_media_player.h | 1 + esphome/components/media_player/__init__.py | 12 ++++++++++++ esphome/components/media_player/automation.h | 1 + .../components/media_player/media_player.cpp | 10 ++++++++++ esphome/components/media_player/media_player.h | 6 +++++- .../voice_assistant/voice_assistant.cpp | 4 ++-- 11 files changed, 76 insertions(+), 7 deletions(-) diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index b8073abc19..774ca7ed9b 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -1147,6 +1147,9 @@ message MediaPlayerCommandRequest { bool has_media_url = 6; string media_url = 7; + + bool has_announcement = 8; + bool announcement = 9; } // ==================== BLUETOOTH ==================== diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index b31212bbdb..2804dba31f 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1002,7 +1002,11 @@ bool APIConnection::send_media_player_state(media_player::MediaPlayer *media_pla MediaPlayerStateResponse resp{}; resp.key = media_player->get_object_id_hash(); - resp.state = static_cast(media_player->state); + + media_player::MediaPlayerState report_state = media_player->state == media_player::MEDIA_PLAYER_STATE_ANNOUNCING + ? media_player::MEDIA_PLAYER_STATE_PLAYING + : media_player->state; + resp.state = static_cast(report_state); resp.volume = media_player->volume; resp.muted = media_player->is_muted(); return this->send_media_player_state_response(resp); @@ -1038,6 +1042,9 @@ void APIConnection::media_player_command(const MediaPlayerCommandRequest &msg) { if (msg.has_media_url) { call.set_media_url(msg.media_url); } + if (msg.has_announcement) { + call.set_announcement(msg.announcement); + } call.perform(); } #endif diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index 6ec1870d72..a48087e348 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -5253,6 +5253,14 @@ bool MediaPlayerCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt val this->has_media_url = value.as_bool(); return true; } + case 8: { + this->has_announcement = value.as_bool(); + return true; + } + case 9: { + this->announcement = value.as_bool(); + return true; + } default: return false; } @@ -5289,6 +5297,8 @@ void MediaPlayerCommandRequest::encode(ProtoWriteBuffer buffer) const { buffer.encode_float(5, this->volume); buffer.encode_bool(6, this->has_media_url); buffer.encode_string(7, this->media_url); + buffer.encode_bool(8, this->has_announcement); + buffer.encode_bool(9, this->announcement); } #ifdef HAS_PROTO_MESSAGE_DUMP void MediaPlayerCommandRequest::dump_to(std::string &out) const { @@ -5323,6 +5333,14 @@ void MediaPlayerCommandRequest::dump_to(std::string &out) const { out.append(" media_url: "); out.append("'").append(this->media_url).append("'"); out.append("\n"); + + out.append(" has_announcement: "); + out.append(YESNO(this->has_announcement)); + out.append("\n"); + + out.append(" announcement: "); + out.append(YESNO(this->announcement)); + out.append("\n"); out.append("}"); } #endif diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index 14fd95df37..807b150d82 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -1298,6 +1298,8 @@ class MediaPlayerCommandRequest : public ProtoMessage { float volume{0.0f}; bool has_media_url{false}; std::string media_url{}; + bool has_announcement{false}; + bool announcement{false}; void encode(ProtoWriteBuffer buffer) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; 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 6e07983920..1890e27bdf 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 @@ -10,6 +10,11 @@ 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; + if (call.get_announcement().has_value()) { + play_state = call.get_announcement().value() ? 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(); if (this->i2s_state_ != I2S_STATE_STOPPED && this->audio_ != nullptr) { @@ -17,7 +22,7 @@ void I2SAudioMediaPlayer::control(const media_player::MediaPlayerCall &call) { this->audio_->stopSong(); } this->audio_->connecttohost(this->current_url_.value().c_str()); - this->state = media_player::MEDIA_PLAYER_STATE_PLAYING; + this->state = play_state; } else { this->start(); } @@ -35,7 +40,7 @@ void I2SAudioMediaPlayer::control(const media_player::MediaPlayerCall &call) { case media_player::MEDIA_PLAYER_COMMAND_PLAY: if (!this->audio_->isRunning()) this->audio_->pauseResume(); - this->state = media_player::MEDIA_PLAYER_STATE_PLAYING; + this->state = play_state; break; case media_player::MEDIA_PLAYER_COMMAND_PAUSE: if (this->audio_->isRunning()) @@ -126,7 +131,9 @@ void I2SAudioMediaPlayer::loop() { void I2SAudioMediaPlayer::play_() { this->audio_->loop(); - if (this->state == media_player::MEDIA_PLAYER_STATE_PLAYING && !this->audio_->isRunning()) { + if ((this->state == media_player::MEDIA_PLAYER_STATE_PLAYING || + this->state == media_player::MEDIA_PLAYER_STATE_ANNOUNCING) && + !this->audio_->isRunning()) { this->stop(); } } @@ -164,6 +171,10 @@ void I2SAudioMediaPlayer::start_() { if (this->current_url_.has_value()) { this->audio_->connecttohost(this->current_url_.value().c_str()); this->state = media_player::MEDIA_PLAYER_STATE_PLAYING; + if (this->is_announcement_.has_value()) { + this->state = this->is_announcement_.value() ? media_player::MEDIA_PLAYER_STATE_ANNOUNCING + : media_player::MEDIA_PLAYER_STATE_PLAYING; + } this->publish_state(); } } diff --git a/esphome/components/i2s_audio/media_player/i2s_audio_media_player.h b/esphome/components/i2s_audio/media_player/i2s_audio_media_player.h index 092e6de8e8..d7d9b1f74a 100644 --- a/esphome/components/i2s_audio/media_player/i2s_audio_media_player.h +++ b/esphome/components/i2s_audio/media_player/i2s_audio_media_player.h @@ -78,6 +78,7 @@ class I2SAudioMediaPlayer : public Component, public media_player::MediaPlayer, HighFrequencyLoopRequester high_freq_; optional current_url_{}; + optional is_announcement_{}; }; } // namespace i2s_audio diff --git a/esphome/components/media_player/__init__.py b/esphome/components/media_player/__init__.py index 5db78150bb..320014e355 100644 --- a/esphome/components/media_player/__init__.py +++ b/esphome/components/media_player/__init__.py @@ -51,12 +51,16 @@ VolumeSetAction = media_player_ns.class_( 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() +) IsIdleCondition = media_player_ns.class_("IsIdleCondition", automation.Condition) IsPlayingCondition = media_player_ns.class_("IsPlayingCondition", automation.Condition) @@ -75,6 +79,9 @@ async def setup_media_player_core_(var, config): 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) async def register_media_player(var, config): @@ -106,6 +113,11 @@ MEDIA_PLAYER_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend( 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), + } + ), } ) diff --git a/esphome/components/media_player/automation.h b/esphome/components/media_player/automation.h index 261e93775c..fc3ce7a764 100644 --- a/esphome/components/media_player/automation.h +++ b/esphome/components/media_player/automation.h @@ -52,6 +52,7 @@ class StateTrigger : public Trigger<> { MEDIA_PLAYER_SIMPLE_STATE_TRIGGER(IdleTrigger, IDLE) MEDIA_PLAYER_SIMPLE_STATE_TRIGGER(PlayTrigger, PLAYING) MEDIA_PLAYER_SIMPLE_STATE_TRIGGER(PauseTrigger, PAUSED) +MEDIA_PLAYER_SIMPLE_STATE_TRIGGER(AnnouncementTrigger, ANNOUNCING) template class IsIdleCondition : public Condition, public Parented { public: diff --git a/esphome/components/media_player/media_player.cpp b/esphome/components/media_player/media_player.cpp index 81cb6ca751..586345ac9f 100644 --- a/esphome/components/media_player/media_player.cpp +++ b/esphome/components/media_player/media_player.cpp @@ -15,6 +15,8 @@ const char *media_player_state_to_string(MediaPlayerState state) { return "PLAYING"; case MEDIA_PLAYER_STATE_PAUSED: return "PAUSED"; + case MEDIA_PLAYER_STATE_ANNOUNCING: + return "ANNOUNCING"; case MEDIA_PLAYER_STATE_NONE: default: return "UNKNOWN"; @@ -68,6 +70,9 @@ void MediaPlayerCall::perform() { if (this->volume_.has_value()) { ESP_LOGD(TAG, " Volume: %.2f", this->volume_.value()); } + if (this->announcement_.has_value()) { + ESP_LOGD(TAG, " Announcement: %s", this->announcement_.value() ? "yes" : "no"); + } this->parent_->control(*this); } @@ -108,6 +113,11 @@ MediaPlayerCall &MediaPlayerCall::set_volume(float volume) { return *this; } +MediaPlayerCall &MediaPlayerCall::set_announcement(bool announce) { + this->announcement_ = announce; + return *this; +} + void MediaPlayer::add_on_state_callback(std::function &&callback) { this->state_callback_.add(std::move(callback)); } diff --git a/esphome/components/media_player/media_player.h b/esphome/components/media_player/media_player.h index 88114d5337..77746e1808 100644 --- a/esphome/components/media_player/media_player.h +++ b/esphome/components/media_player/media_player.h @@ -10,7 +10,8 @@ enum MediaPlayerState : uint8_t { MEDIA_PLAYER_STATE_NONE = 0, MEDIA_PLAYER_STATE_IDLE = 1, MEDIA_PLAYER_STATE_PLAYING = 2, - MEDIA_PLAYER_STATE_PAUSED = 3 + MEDIA_PLAYER_STATE_PAUSED = 3, + MEDIA_PLAYER_STATE_ANNOUNCING = 4 }; const char *media_player_state_to_string(MediaPlayerState state); @@ -51,12 +52,14 @@ class MediaPlayerCall { MediaPlayerCall &set_media_url(const std::string &url); MediaPlayerCall &set_volume(float volume); + MediaPlayerCall &set_announcement(bool announce); void perform(); const optional &get_command() const { return command_; } const optional &get_media_url() const { return media_url_; } const optional &get_volume() const { return volume_; } + const optional &get_announcement() const { return announcement_; } protected: void validate_(); @@ -64,6 +67,7 @@ class MediaPlayerCall { optional command_; optional media_url_; optional volume_; + optional announcement_; }; class MediaPlayer : public EntityBase { diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index 3bd41e1fcf..109e52f8eb 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -318,7 +318,7 @@ void VoiceAssistant::loop() { #endif #ifdef USE_MEDIA_PLAYER if (this->media_player_ != nullptr) { - playing = (this->media_player_->state == media_player::MediaPlayerState::MEDIA_PLAYER_STATE_PLAYING); + playing = (this->media_player_->state == media_player::MediaPlayerState::MEDIA_PLAYER_STATE_ANNOUNCING); } #endif if (playing) { @@ -640,7 +640,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { this->defer([this, url]() { #ifdef USE_MEDIA_PLAYER if (this->media_player_ != nullptr) { - this->media_player_->make_call().set_media_url(url).perform(); + this->media_player_->make_call().set_media_url(url).set_announcement(true).perform(); } #endif this->tts_end_trigger_->trigger(url); From db4aa0b679b3b2324d715a1d2d16423661ed3057 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 15 May 2024 07:37:22 +1200 Subject: [PATCH 1437/2101] Bump version to 2024.5.0b5 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index e3d9bfeb64..2e5e9cc9de 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.5.0b4" +__version__ = "2024.5.0b5" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 9a6e90af54f0704d8150905e01b1e2d105a28dc7 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 15 May 2024 12:51:01 +1200 Subject: [PATCH 1438/2101] [adc] Fix 11db deprecation warning (#6749) --- esphome/components/adc/__init__.py | 14 ++++++++++++- esphome/components/adc/adc_sensor.cpp | 30 +++++++++++++-------------- esphome/components/adc/adc_sensor.h | 23 ++++++++++++++++---- esphome/components/adc/sensor.py | 18 ++++++++++++++-- 4 files changed, 63 insertions(+), 22 deletions(-) diff --git a/esphome/components/adc/__init__.py b/esphome/components/adc/__init__.py index 87d769fec2..11b0ba2389 100644 --- a/esphome/components/adc/__init__.py +++ b/esphome/components/adc/__init__.py @@ -18,11 +18,23 @@ from esphome.components.esp32.const import ( CODEOWNERS = ["@esphome/core"] +adc_ns = cg.esphome_ns.namespace("adc") + + +""" +From the below patch versions (and 5.2+) ADC_ATTEN_DB_11 is deprecated and replaced with ADC_ATTEN_DB_12. +4.4.7 +5.0.5 +5.1.3 +5.2+ +""" + ATTENUATION_MODES = { "0db": cg.global_ns.ADC_ATTEN_DB_0, "2.5db": cg.global_ns.ADC_ATTEN_DB_2_5, "6db": cg.global_ns.ADC_ATTEN_DB_6, - "11db": cg.global_ns.ADC_ATTEN_DB_11, + "11db": adc_ns.ADC_ATTEN_DB_12_COMPAT, + "12db": adc_ns.ADC_ATTEN_DB_12_COMPAT, "auto": "auto", } diff --git a/esphome/components/adc/adc_sensor.cpp b/esphome/components/adc/adc_sensor.cpp index a9ac5a5cfe..1a76bdb264 100644 --- a/esphome/components/adc/adc_sensor.cpp +++ b/esphome/components/adc/adc_sensor.cpp @@ -62,7 +62,7 @@ extern "C" } // load characteristics for each attenuation - for (int32_t i = 0; i <= ADC_ATTEN_DB_11; i++) { + for (int32_t i = 0; i <= ADC_ATTEN_DB_12_COMPAT; i++) { auto adc_unit = channel1_ != ADC1_CHANNEL_MAX ? ADC_UNIT_1 : ADC_UNIT_2; auto cal_value = esp_adc_cal_characterize(adc_unit, (adc_atten_t) i, ADC_WIDTH_MAX_SOC_BITS, 1100, // default vref @@ -118,8 +118,8 @@ void ADCSensor::dump_config() { case ADC_ATTEN_DB_6: ESP_LOGCONFIG(TAG, " Attenuation: 6db"); break; - case ADC_ATTEN_DB_11: - ESP_LOGCONFIG(TAG, " Attenuation: 11db"); + case ADC_ATTEN_DB_12_COMPAT: + ESP_LOGCONFIG(TAG, " Attenuation: 12db"); break; default: // This is to satisfy the unused ADC_ATTEN_MAX break; @@ -183,12 +183,12 @@ float ADCSensor::sample() { return mv / 1000.0f; } - int raw11 = ADC_MAX, raw6 = ADC_MAX, raw2 = ADC_MAX, raw0 = ADC_MAX; + int raw12 = ADC_MAX, raw6 = ADC_MAX, raw2 = ADC_MAX, raw0 = ADC_MAX; if (channel1_ != ADC1_CHANNEL_MAX) { - adc1_config_channel_atten(channel1_, ADC_ATTEN_DB_11); - raw11 = adc1_get_raw(channel1_); - if (raw11 < ADC_MAX) { + adc1_config_channel_atten(channel1_, ADC_ATTEN_DB_12_COMPAT); + raw12 = adc1_get_raw(channel1_); + if (raw12 < ADC_MAX) { adc1_config_channel_atten(channel1_, ADC_ATTEN_DB_6); raw6 = adc1_get_raw(channel1_); if (raw6 < ADC_MAX) { @@ -201,9 +201,9 @@ float ADCSensor::sample() { } } } else if (channel2_ != ADC2_CHANNEL_MAX) { - adc2_config_channel_atten(channel2_, ADC_ATTEN_DB_11); - adc2_get_raw(channel2_, ADC_WIDTH_MAX_SOC_BITS, &raw11); - if (raw11 < ADC_MAX) { + adc2_config_channel_atten(channel2_, ADC_ATTEN_DB_12_COMPAT); + adc2_get_raw(channel2_, ADC_WIDTH_MAX_SOC_BITS, &raw12); + if (raw12 < ADC_MAX) { adc2_config_channel_atten(channel2_, ADC_ATTEN_DB_6); adc2_get_raw(channel2_, ADC_WIDTH_MAX_SOC_BITS, &raw6); if (raw6 < ADC_MAX) { @@ -217,25 +217,25 @@ float ADCSensor::sample() { } } - if (raw0 == -1 || raw2 == -1 || raw6 == -1 || raw11 == -1) { + if (raw0 == -1 || raw2 == -1 || raw6 == -1 || raw12 == -1) { return NAN; } - uint32_t mv11 = esp_adc_cal_raw_to_voltage(raw11, &cal_characteristics_[(int32_t) ADC_ATTEN_DB_11]); + uint32_t mv12 = esp_adc_cal_raw_to_voltage(raw12, &cal_characteristics_[(int32_t) ADC_ATTEN_DB_12_COMPAT]); uint32_t mv6 = esp_adc_cal_raw_to_voltage(raw6, &cal_characteristics_[(int32_t) ADC_ATTEN_DB_6]); uint32_t mv2 = esp_adc_cal_raw_to_voltage(raw2, &cal_characteristics_[(int32_t) ADC_ATTEN_DB_2_5]); uint32_t mv0 = esp_adc_cal_raw_to_voltage(raw0, &cal_characteristics_[(int32_t) ADC_ATTEN_DB_0]); // Contribution of each value, in range 0-2048 (12 bit ADC) or 0-4096 (13 bit ADC) - uint32_t c11 = std::min(raw11, ADC_HALF); + uint32_t c12 = std::min(raw12, ADC_HALF); uint32_t c6 = ADC_HALF - std::abs(raw6 - ADC_HALF); uint32_t c2 = ADC_HALF - std::abs(raw2 - ADC_HALF); uint32_t c0 = std::min(ADC_MAX - raw0, ADC_HALF); // max theoretical csum value is 4096*4 = 16384 - uint32_t csum = c11 + c6 + c2 + c0; + uint32_t csum = c12 + c6 + c2 + c0; // each mv is max 3900; so max value is 3900*4096*4, fits in unsigned32 - uint32_t mv_scaled = (mv11 * c11) + (mv6 * c6) + (mv2 * c2) + (mv0 * c0); + uint32_t mv_scaled = (mv12 * c12) + (mv6 * c6) + (mv2 * c2) + (mv0 * c0); return mv_scaled / (float) (csum * 1000U); } #endif // USE_ESP32 diff --git a/esphome/components/adc/adc_sensor.h b/esphome/components/adc/adc_sensor.h index b1fdcd5d29..d99c4bc75b 100644 --- a/esphome/components/adc/adc_sensor.h +++ b/esphome/components/adc/adc_sensor.h @@ -1,19 +1,34 @@ #pragma once -#include "esphome/core/component.h" -#include "esphome/core/hal.h" -#include "esphome/core/defines.h" #include "esphome/components/sensor/sensor.h" #include "esphome/components/voltage_sampler/voltage_sampler.h" +#include "esphome/core/component.h" +#include "esphome/core/defines.h" +#include "esphome/core/hal.h" #ifdef USE_ESP32 -#include "driver/adc.h" #include +#include "driver/adc.h" #endif namespace esphome { namespace adc { +#ifdef USE_ESP32 +// clang-format off +#if (ESP_IDF_VERSION_MAJOR == 4 && ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 7)) || \ + (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)) \ + ) +// clang-format on +static const adc_atten_t ADC_ATTEN_DB_12_COMPAT = ADC_ATTEN_DB_12; +#else +static const adc_atten_t ADC_ATTEN_DB_12_COMPAT = ADC_ATTEN_DB_11; +#endif +#endif // USE_ESP32 + class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage_sampler::VoltageSampler { public: #ifdef USE_ESP32 diff --git a/esphome/components/adc/sensor.py b/esphome/components/adc/sensor.py index c1ae22214d..4cf3d52802 100644 --- a/esphome/components/adc/sensor.py +++ b/esphome/components/adc/sensor.py @@ -1,3 +1,5 @@ +import logging + import esphome.codegen as cg import esphome.config_validation as cv import esphome.final_validate as fv @@ -19,16 +21,29 @@ from . import ( ATTENUATION_MODES, ESP32_VARIANT_ADC1_PIN_TO_CHANNEL, ESP32_VARIANT_ADC2_PIN_TO_CHANNEL, + adc_ns, validate_adc_pin, ) +_LOGGER = logging.getLogger(__name__) + AUTO_LOAD = ["voltage_sampler"] +_attenuation = cv.enum(ATTENUATION_MODES, lower=True) + + def validate_config(config): if config[CONF_RAW] and config.get(CONF_ATTENUATION, None) == "auto": raise cv.Invalid("Automatic attenuation cannot be used when raw output is set") + if config.get(CONF_ATTENUATION) == "11db": + _LOGGER.warning( + "`attenuation: 11db` is deprecated, use `attenuation: 12db` instead" + ) + # Alter value here so `config` command prints the recommended change + config[CONF_ATTENUATION] = _attenuation("12db") + return config @@ -47,7 +62,6 @@ def final_validate_config(config): return config -adc_ns = cg.esphome_ns.namespace("adc") ADCSensor = adc_ns.class_( "ADCSensor", sensor.Sensor, cg.PollingComponent, voltage_sampler.VoltageSampler ) @@ -65,7 +79,7 @@ CONFIG_SCHEMA = cv.All( cv.Required(CONF_PIN): validate_adc_pin, cv.Optional(CONF_RAW, default=False): cv.boolean, cv.SplitDefault(CONF_ATTENUATION, esp32="0db"): cv.All( - cv.only_on_esp32, cv.enum(ATTENUATION_MODES, lower=True) + cv.only_on_esp32, _attenuation ), } ) From ebc3f0fe1710ef3e11cc78cdd8f73bc5b319ae7c Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 15 May 2024 12:51:01 +1200 Subject: [PATCH 1439/2101] [adc] Fix 11db deprecation warning (#6749) --- esphome/components/adc/__init__.py | 14 ++++++++++++- esphome/components/adc/adc_sensor.cpp | 30 +++++++++++++-------------- esphome/components/adc/adc_sensor.h | 23 ++++++++++++++++---- esphome/components/adc/sensor.py | 18 ++++++++++++++-- 4 files changed, 63 insertions(+), 22 deletions(-) diff --git a/esphome/components/adc/__init__.py b/esphome/components/adc/__init__.py index 87d769fec2..11b0ba2389 100644 --- a/esphome/components/adc/__init__.py +++ b/esphome/components/adc/__init__.py @@ -18,11 +18,23 @@ from esphome.components.esp32.const import ( CODEOWNERS = ["@esphome/core"] +adc_ns = cg.esphome_ns.namespace("adc") + + +""" +From the below patch versions (and 5.2+) ADC_ATTEN_DB_11 is deprecated and replaced with ADC_ATTEN_DB_12. +4.4.7 +5.0.5 +5.1.3 +5.2+ +""" + ATTENUATION_MODES = { "0db": cg.global_ns.ADC_ATTEN_DB_0, "2.5db": cg.global_ns.ADC_ATTEN_DB_2_5, "6db": cg.global_ns.ADC_ATTEN_DB_6, - "11db": cg.global_ns.ADC_ATTEN_DB_11, + "11db": adc_ns.ADC_ATTEN_DB_12_COMPAT, + "12db": adc_ns.ADC_ATTEN_DB_12_COMPAT, "auto": "auto", } diff --git a/esphome/components/adc/adc_sensor.cpp b/esphome/components/adc/adc_sensor.cpp index a9ac5a5cfe..1a76bdb264 100644 --- a/esphome/components/adc/adc_sensor.cpp +++ b/esphome/components/adc/adc_sensor.cpp @@ -62,7 +62,7 @@ extern "C" } // load characteristics for each attenuation - for (int32_t i = 0; i <= ADC_ATTEN_DB_11; i++) { + for (int32_t i = 0; i <= ADC_ATTEN_DB_12_COMPAT; i++) { auto adc_unit = channel1_ != ADC1_CHANNEL_MAX ? ADC_UNIT_1 : ADC_UNIT_2; auto cal_value = esp_adc_cal_characterize(adc_unit, (adc_atten_t) i, ADC_WIDTH_MAX_SOC_BITS, 1100, // default vref @@ -118,8 +118,8 @@ void ADCSensor::dump_config() { case ADC_ATTEN_DB_6: ESP_LOGCONFIG(TAG, " Attenuation: 6db"); break; - case ADC_ATTEN_DB_11: - ESP_LOGCONFIG(TAG, " Attenuation: 11db"); + case ADC_ATTEN_DB_12_COMPAT: + ESP_LOGCONFIG(TAG, " Attenuation: 12db"); break; default: // This is to satisfy the unused ADC_ATTEN_MAX break; @@ -183,12 +183,12 @@ float ADCSensor::sample() { return mv / 1000.0f; } - int raw11 = ADC_MAX, raw6 = ADC_MAX, raw2 = ADC_MAX, raw0 = ADC_MAX; + int raw12 = ADC_MAX, raw6 = ADC_MAX, raw2 = ADC_MAX, raw0 = ADC_MAX; if (channel1_ != ADC1_CHANNEL_MAX) { - adc1_config_channel_atten(channel1_, ADC_ATTEN_DB_11); - raw11 = adc1_get_raw(channel1_); - if (raw11 < ADC_MAX) { + adc1_config_channel_atten(channel1_, ADC_ATTEN_DB_12_COMPAT); + raw12 = adc1_get_raw(channel1_); + if (raw12 < ADC_MAX) { adc1_config_channel_atten(channel1_, ADC_ATTEN_DB_6); raw6 = adc1_get_raw(channel1_); if (raw6 < ADC_MAX) { @@ -201,9 +201,9 @@ float ADCSensor::sample() { } } } else if (channel2_ != ADC2_CHANNEL_MAX) { - adc2_config_channel_atten(channel2_, ADC_ATTEN_DB_11); - adc2_get_raw(channel2_, ADC_WIDTH_MAX_SOC_BITS, &raw11); - if (raw11 < ADC_MAX) { + adc2_config_channel_atten(channel2_, ADC_ATTEN_DB_12_COMPAT); + adc2_get_raw(channel2_, ADC_WIDTH_MAX_SOC_BITS, &raw12); + if (raw12 < ADC_MAX) { adc2_config_channel_atten(channel2_, ADC_ATTEN_DB_6); adc2_get_raw(channel2_, ADC_WIDTH_MAX_SOC_BITS, &raw6); if (raw6 < ADC_MAX) { @@ -217,25 +217,25 @@ float ADCSensor::sample() { } } - if (raw0 == -1 || raw2 == -1 || raw6 == -1 || raw11 == -1) { + if (raw0 == -1 || raw2 == -1 || raw6 == -1 || raw12 == -1) { return NAN; } - uint32_t mv11 = esp_adc_cal_raw_to_voltage(raw11, &cal_characteristics_[(int32_t) ADC_ATTEN_DB_11]); + uint32_t mv12 = esp_adc_cal_raw_to_voltage(raw12, &cal_characteristics_[(int32_t) ADC_ATTEN_DB_12_COMPAT]); uint32_t mv6 = esp_adc_cal_raw_to_voltage(raw6, &cal_characteristics_[(int32_t) ADC_ATTEN_DB_6]); uint32_t mv2 = esp_adc_cal_raw_to_voltage(raw2, &cal_characteristics_[(int32_t) ADC_ATTEN_DB_2_5]); uint32_t mv0 = esp_adc_cal_raw_to_voltage(raw0, &cal_characteristics_[(int32_t) ADC_ATTEN_DB_0]); // Contribution of each value, in range 0-2048 (12 bit ADC) or 0-4096 (13 bit ADC) - uint32_t c11 = std::min(raw11, ADC_HALF); + uint32_t c12 = std::min(raw12, ADC_HALF); uint32_t c6 = ADC_HALF - std::abs(raw6 - ADC_HALF); uint32_t c2 = ADC_HALF - std::abs(raw2 - ADC_HALF); uint32_t c0 = std::min(ADC_MAX - raw0, ADC_HALF); // max theoretical csum value is 4096*4 = 16384 - uint32_t csum = c11 + c6 + c2 + c0; + uint32_t csum = c12 + c6 + c2 + c0; // each mv is max 3900; so max value is 3900*4096*4, fits in unsigned32 - uint32_t mv_scaled = (mv11 * c11) + (mv6 * c6) + (mv2 * c2) + (mv0 * c0); + uint32_t mv_scaled = (mv12 * c12) + (mv6 * c6) + (mv2 * c2) + (mv0 * c0); return mv_scaled / (float) (csum * 1000U); } #endif // USE_ESP32 diff --git a/esphome/components/adc/adc_sensor.h b/esphome/components/adc/adc_sensor.h index b1fdcd5d29..d99c4bc75b 100644 --- a/esphome/components/adc/adc_sensor.h +++ b/esphome/components/adc/adc_sensor.h @@ -1,19 +1,34 @@ #pragma once -#include "esphome/core/component.h" -#include "esphome/core/hal.h" -#include "esphome/core/defines.h" #include "esphome/components/sensor/sensor.h" #include "esphome/components/voltage_sampler/voltage_sampler.h" +#include "esphome/core/component.h" +#include "esphome/core/defines.h" +#include "esphome/core/hal.h" #ifdef USE_ESP32 -#include "driver/adc.h" #include +#include "driver/adc.h" #endif namespace esphome { namespace adc { +#ifdef USE_ESP32 +// clang-format off +#if (ESP_IDF_VERSION_MAJOR == 4 && ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 7)) || \ + (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)) \ + ) +// clang-format on +static const adc_atten_t ADC_ATTEN_DB_12_COMPAT = ADC_ATTEN_DB_12; +#else +static const adc_atten_t ADC_ATTEN_DB_12_COMPAT = ADC_ATTEN_DB_11; +#endif +#endif // USE_ESP32 + class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage_sampler::VoltageSampler { public: #ifdef USE_ESP32 diff --git a/esphome/components/adc/sensor.py b/esphome/components/adc/sensor.py index c1ae22214d..4cf3d52802 100644 --- a/esphome/components/adc/sensor.py +++ b/esphome/components/adc/sensor.py @@ -1,3 +1,5 @@ +import logging + import esphome.codegen as cg import esphome.config_validation as cv import esphome.final_validate as fv @@ -19,16 +21,29 @@ from . import ( ATTENUATION_MODES, ESP32_VARIANT_ADC1_PIN_TO_CHANNEL, ESP32_VARIANT_ADC2_PIN_TO_CHANNEL, + adc_ns, validate_adc_pin, ) +_LOGGER = logging.getLogger(__name__) + AUTO_LOAD = ["voltage_sampler"] +_attenuation = cv.enum(ATTENUATION_MODES, lower=True) + + def validate_config(config): if config[CONF_RAW] and config.get(CONF_ATTENUATION, None) == "auto": raise cv.Invalid("Automatic attenuation cannot be used when raw output is set") + if config.get(CONF_ATTENUATION) == "11db": + _LOGGER.warning( + "`attenuation: 11db` is deprecated, use `attenuation: 12db` instead" + ) + # Alter value here so `config` command prints the recommended change + config[CONF_ATTENUATION] = _attenuation("12db") + return config @@ -47,7 +62,6 @@ def final_validate_config(config): return config -adc_ns = cg.esphome_ns.namespace("adc") ADCSensor = adc_ns.class_( "ADCSensor", sensor.Sensor, cg.PollingComponent, voltage_sampler.VoltageSampler ) @@ -65,7 +79,7 @@ CONFIG_SCHEMA = cv.All( cv.Required(CONF_PIN): validate_adc_pin, cv.Optional(CONF_RAW, default=False): cv.boolean, cv.SplitDefault(CONF_ATTENUATION, esp32="0db"): cv.All( - cv.only_on_esp32, cv.enum(ATTENUATION_MODES, lower=True) + cv.only_on_esp32, _attenuation ), } ) From 5d2e3a7d8d803d03b3afda680e4fcb11b8e5ca2a Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 15 May 2024 13:14:15 +1200 Subject: [PATCH 1440/2101] Bump version to 2024.5.0b6 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 2e5e9cc9de..786f988f91 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.5.0b5" +__version__ = "2024.5.0b6" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 0d3adc8f0c12d5900f63fc36df5dd72c85428229 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 15 May 2024 17:08:43 +1200 Subject: [PATCH 1441/2101] Bump version to 2024.5.0 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 786f988f91..9871ea704f 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.5.0b6" +__version__ = "2024.5.0" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 891f56b421456dbc9d523945f6ebf97b1975d0d6 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Wed, 15 May 2024 00:14:19 -0500 Subject: [PATCH 1442/2101] [tests] ``test2.yaml`` has become too large (#6750) --- tests/test2.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/test2.yaml b/tests/test2.yaml index 2fdef72c08..970076e78b 100644 --- a/tests/test2.yaml +++ b/tests/test2.yaml @@ -1,10 +1,12 @@ --- esphome: name: $devicename - platform: ESP32 - board: nodemcu-32s build_path: build/test2 +esp32: + board: esp32dev + flash_size: 8MB + globals: - id: my_global_string type: std::string From 9f1ba00b7cc67c03667b6ac23707e9787238fde9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 May 2024 17:16:04 +1200 Subject: [PATCH 1443/2101] Bump esphome-dashboard from 20240412.0 to 20240429.1 (#6743) 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 698ae56447..05e46ca31e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ pyserial==3.5 platformio==6.1.15 # When updating platformio, also update Dockerfile esptool==4.7.0 click==8.1.7 -esphome-dashboard==20240412.0 +esphome-dashboard==20240429.1 aioesphomeapi==24.3.0 zeroconf==0.132.2 python-magic==0.4.27 From 773951d85eba1031eaca56c1d340f20f8ad59009 Mon Sep 17 00:00:00 2001 From: Alex Boyd Date: Wed, 15 May 2024 17:31:08 -0600 Subject: [PATCH 1444/2101] BedJet: expose the outlet temperature on the climate and as a sensor (#6633) --- CODEOWNERS | 1 + esphome/components/bedjet/__init__.py | 2 +- esphome/components/bedjet/bedjet_codec.cpp | 6 ++ esphome/components/bedjet/bedjet_codec.h | 3 + esphome/components/bedjet/bedjet_const.h | 8 +++ esphome/components/bedjet/climate/__init__.py | 10 ++++ .../bedjet/climate/bedjet_climate.cpp | 15 +++-- .../bedjet/climate/bedjet_climate.h | 3 + esphome/components/bedjet/sensor/__init__.py | 55 +++++++++++++++++++ .../bedjet/sensor/bedjet_sensor.cpp | 34 ++++++++++++ .../components/bedjet/sensor/bedjet_sensor.h | 32 +++++++++++ tests/components/bedjet/common.yaml | 8 +++ 12 files changed, 168 insertions(+), 9 deletions(-) create mode 100644 esphome/components/bedjet/sensor/__init__.py create mode 100644 esphome/components/bedjet/sensor/bedjet_sensor.cpp create mode 100644 esphome/components/bedjet/sensor/bedjet_sensor.h diff --git a/CODEOWNERS b/CODEOWNERS index 88f875f368..a661eba9b3 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -51,6 +51,7 @@ esphome/components/bang_bang/* @OttoWinter esphome/components/bedjet/* @jhansche esphome/components/bedjet/climate/* @jhansche esphome/components/bedjet/fan/* @jhansche +esphome/components/bedjet/sensor/* @javawizard @jhansche esphome/components/bh1750/* @OttoWinter esphome/components/binary_sensor/* @esphome/core esphome/components/bk72xx/* @kuba2k2 diff --git a/esphome/components/bedjet/__init__.py b/esphome/components/bedjet/__init__.py index 395a5f25e4..a4b8a50eab 100644 --- a/esphome/components/bedjet/__init__.py +++ b/esphome/components/bedjet/__init__.py @@ -31,7 +31,7 @@ CONFIG_SCHEMA = ( BEDJET_CLIENT_SCHEMA = cv.Schema( { - cv.Required(CONF_BEDJET_ID): cv.use_id(BedJetHub), + cv.GenerateID(CONF_BEDJET_ID): cv.use_id(BedJetHub), } ) diff --git a/esphome/components/bedjet/bedjet_codec.cpp b/esphome/components/bedjet/bedjet_codec.cpp index 735393ffcb..7e90621235 100644 --- a/esphome/components/bedjet/bedjet_codec.cpp +++ b/esphome/components/bedjet/bedjet_codec.cpp @@ -157,5 +157,11 @@ bool BedjetCodec::compare(const uint8_t *data, uint16_t length) { return explicit_fields_changed; } +/// Converts a BedJet temp step into degrees Celsius. +float bedjet_temp_to_c(uint8_t temp) { + // BedJet temp is "C*2"; to get C, divide by 2. + return temp / 2.0f; +} + } // namespace bedjet } // namespace esphome diff --git a/esphome/components/bedjet/bedjet_codec.h b/esphome/components/bedjet/bedjet_codec.h index 3a41313ada..527e757d7f 100644 --- a/esphome/components/bedjet/bedjet_codec.h +++ b/esphome/components/bedjet/bedjet_codec.h @@ -187,5 +187,8 @@ class BedjetCodec { BedjetStatusPacket buf_; }; +/// Converts a BedJet temp step into degrees Celsius. +float bedjet_temp_to_c(uint8_t temp); + } // namespace bedjet } // namespace esphome diff --git a/esphome/components/bedjet/bedjet_const.h b/esphome/components/bedjet/bedjet_const.h index 27a75b2671..7cac1b61ff 100644 --- a/esphome/components/bedjet/bedjet_const.h +++ b/esphome/components/bedjet/bedjet_const.h @@ -40,6 +40,14 @@ enum BedjetHeatMode { HEAT_MODE_EXTENDED, }; +// Which temperature to use as the climate entity's current temperature reading +enum BedjetTemperatureSource { + // Use the temperature of the air the BedJet is putting out + TEMPERATURE_SOURCE_OUTLET, + // Use the ambient temperature of the room the BedJet is in + TEMPERATURE_SOURCE_AMBIENT +}; + enum BedjetButton : uint8_t { /// Turn BedJet off BTN_OFF = 0x1, diff --git a/esphome/components/bedjet/climate/__init__.py b/esphome/components/bedjet/climate/__init__.py index b12622868f..e454b0922b 100644 --- a/esphome/components/bedjet/climate/__init__.py +++ b/esphome/components/bedjet/climate/__init__.py @@ -7,6 +7,7 @@ from esphome.const import ( CONF_HEAT_MODE, CONF_ID, CONF_RECEIVE_TIMEOUT, + CONF_TEMPERATURE_SOURCE, CONF_TIME_ID, ) from .. import ( @@ -21,10 +22,15 @@ DEPENDENCIES = ["bedjet"] BedJetClimate = bedjet_ns.class_("BedJetClimate", climate.Climate, cg.PollingComponent) BedjetHeatMode = bedjet_ns.enum("BedjetHeatMode") +BedjetTemperatureSource = bedjet_ns.enum("BedjetTemperatureSource") BEDJET_HEAT_MODES = { "heat": BedjetHeatMode.HEAT_MODE_HEAT, "extended": BedjetHeatMode.HEAT_MODE_EXTENDED, } +BEDJET_TEMPERATURE_SOURCES = { + "outlet": BedjetTemperatureSource.TEMPERATURE_SOURCE_OUTLET, + "ambient": BedjetTemperatureSource.TEMPERATURE_SOURCE_AMBIENT, +} CONFIG_SCHEMA = ( climate.CLIMATE_SCHEMA.extend( @@ -33,6 +39,9 @@ CONFIG_SCHEMA = ( cv.Optional(CONF_HEAT_MODE, default="heat"): cv.enum( BEDJET_HEAT_MODES, lower=True ), + cv.Optional(CONF_TEMPERATURE_SOURCE, default="ambient"): cv.enum( + BEDJET_TEMPERATURE_SOURCES, lower=True + ), } ) .extend(cv.polling_component_schema("60s")) @@ -63,3 +72,4 @@ async def to_code(config): await register_bedjet_child(var, config) cg.add(var.set_heating_mode(config[CONF_HEAT_MODE])) + cg.add(var.set_temperature_source(config[CONF_TEMPERATURE_SOURCE])) diff --git a/esphome/components/bedjet/climate/bedjet_climate.cpp b/esphome/components/bedjet/climate/bedjet_climate.cpp index 431cf614e9..854129f816 100644 --- a/esphome/components/bedjet/climate/bedjet_climate.cpp +++ b/esphome/components/bedjet/climate/bedjet_climate.cpp @@ -8,12 +8,6 @@ namespace bedjet { using namespace esphome::climate; -/// Converts a BedJet temp step into degrees Celsius. -float bedjet_temp_to_c(const uint8_t temp) { - // BedJet temp is "C*2"; to get C, divide by 2. - return temp / 2.0f; -} - static const std::string *bedjet_fan_step_to_fan_mode(const uint8_t fan_step) { if (fan_step < BEDJET_FAN_SPEED_COUNT) return &BEDJET_FAN_STEP_NAME_STRINGS[fan_step]; @@ -236,9 +230,14 @@ void BedJetClimate::on_status(const BedjetStatusPacket *data) { if (converted_temp > 0) this->target_temperature = converted_temp; - converted_temp = bedjet_temp_to_c(data->ambient_temp_step); - if (converted_temp > 0) + if (this->temperature_source_ == TEMPERATURE_SOURCE_OUTLET) { + converted_temp = bedjet_temp_to_c(data->actual_temp_step); + } else { + converted_temp = bedjet_temp_to_c(data->ambient_temp_step); + } + if (converted_temp > 0) { this->current_temperature = converted_temp; + } const auto *fan_mode_name = bedjet_fan_step_to_fan_mode(data->fan_step); if (fan_mode_name != nullptr) { diff --git a/esphome/components/bedjet/climate/bedjet_climate.h b/esphome/components/bedjet/climate/bedjet_climate.h index 48c50d842f..7eaa735a3f 100644 --- a/esphome/components/bedjet/climate/bedjet_climate.h +++ b/esphome/components/bedjet/climate/bedjet_climate.h @@ -28,6 +28,8 @@ class BedJetClimate : public climate::Climate, public BedJetClient, public Polli /** Sets the default strategy to use for climate::CLIMATE_MODE_HEAT. */ void set_heating_mode(BedjetHeatMode mode) { this->heating_mode_ = mode; } + /** Sets the temperature source to use for the climate entity's current temperature */ + void set_temperature_source(BedjetTemperatureSource source) { this->temperature_source_ = source; } climate::ClimateTraits traits() override { auto traits = climate::ClimateTraits(); @@ -74,6 +76,7 @@ class BedJetClimate : public climate::Climate, public BedJetClient, public Polli void control(const climate::ClimateCall &call) override; BedjetHeatMode heating_mode_ = HEAT_MODE_HEAT; + BedjetTemperatureSource temperature_source_ = TEMPERATURE_SOURCE_AMBIENT; void reset_state_(); bool update_status_(); diff --git a/esphome/components/bedjet/sensor/__init__.py b/esphome/components/bedjet/sensor/__init__.py new file mode 100644 index 0000000000..756b31de53 --- /dev/null +++ b/esphome/components/bedjet/sensor/__init__.py @@ -0,0 +1,55 @@ +import logging + +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import sensor +from esphome.const import ( + CONF_ID, + DEVICE_CLASS_TEMPERATURE, + STATE_CLASS_MEASUREMENT, + UNIT_CELSIUS, +) +from .. import ( + BEDJET_CLIENT_SCHEMA, + bedjet_ns, + register_bedjet_child, +) + +_LOGGER = logging.getLogger(__name__) +CODEOWNERS = ["@jhansche", "@javawizard"] +DEPENDENCIES = ["bedjet"] + +CONF_OUTLET_TEMPERATURE = "outlet_temperature" +CONF_AMBIENT_TEMPERATURE = "ambient_temperature" + +BedjetSensor = bedjet_ns.class_("BedjetSensor", cg.Component) + +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.declare_id(BedjetSensor), + cv.Optional(CONF_OUTLET_TEMPERATURE): sensor.sensor_schema( + unit_of_measurement=UNIT_CELSIUS, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_AMBIENT_TEMPERATURE): sensor.sensor_schema( + unit_of_measurement=UNIT_CELSIUS, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + ), + } +).extend(BEDJET_CLIENT_SCHEMA) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, config) + await register_bedjet_child(var, config) + + if outlet_temperature_sensor := config.get(CONF_OUTLET_TEMPERATURE): + sensor_var = await sensor.new_sensor(outlet_temperature_sensor) + cg.add(var.set_outlet_temperature_sensor(sensor_var)) + + if ambient_temperature_sensor := config.get(CONF_AMBIENT_TEMPERATURE): + sensor_var = await sensor.new_sensor(ambient_temperature_sensor) + cg.add(var.set_ambient_temperature_sensor(sensor_var)) diff --git a/esphome/components/bedjet/sensor/bedjet_sensor.cpp b/esphome/components/bedjet/sensor/bedjet_sensor.cpp new file mode 100644 index 0000000000..2fda8c927f --- /dev/null +++ b/esphome/components/bedjet/sensor/bedjet_sensor.cpp @@ -0,0 +1,34 @@ +#include "bedjet_sensor.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace bedjet { + +std::string BedjetSensor::describe() { return "BedJet Sensor"; } + +void BedjetSensor::dump_config() { + ESP_LOGCONFIG(TAG, "BedJet Sensor:"); + LOG_SENSOR(" ", "Outlet Temperature", this->outlet_temperature_sensor_); + LOG_SENSOR(" ", "Ambient Temperature", this->ambient_temperature_sensor_); +} + +void BedjetSensor::on_bedjet_state(bool is_ready) {} + +void BedjetSensor::on_status(const BedjetStatusPacket *data) { + if (this->outlet_temperature_sensor_ != nullptr) { + float converted_temp = bedjet_temp_to_c(data->actual_temp_step); + if (converted_temp > 0) { + this->outlet_temperature_sensor_->publish_state(converted_temp); + } + } + + if (this->ambient_temperature_sensor_ != nullptr) { + float converted_temp = bedjet_temp_to_c(data->ambient_temp_step); + if (converted_temp > 0) { + this->ambient_temperature_sensor_->publish_state(converted_temp); + } + } +} + +} // namespace bedjet +} // namespace esphome diff --git a/esphome/components/bedjet/sensor/bedjet_sensor.h b/esphome/components/bedjet/sensor/bedjet_sensor.h new file mode 100644 index 0000000000..8cbaa863ee --- /dev/null +++ b/esphome/components/bedjet/sensor/bedjet_sensor.h @@ -0,0 +1,32 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/components/sensor/sensor.h" +#include "esphome/components/bedjet/bedjet_child.h" +#include "esphome/components/bedjet/bedjet_codec.h" + +namespace esphome { +namespace bedjet { + +class BedjetSensor : public BedJetClient, public Component { + public: + void dump_config() override; + + void on_status(const BedjetStatusPacket *data) override; + void on_bedjet_state(bool is_ready) override; + std::string describe() override; + + void set_outlet_temperature_sensor(sensor::Sensor *outlet_temperature_sensor) { + this->outlet_temperature_sensor_ = outlet_temperature_sensor; + } + void set_ambient_temperature_sensor(sensor::Sensor *ambient_temperature_sensor) { + this->ambient_temperature_sensor_ = ambient_temperature_sensor; + } + + protected: + sensor::Sensor *outlet_temperature_sensor_{nullptr}; + sensor::Sensor *ambient_temperature_sensor_{nullptr}; +}; + +} // namespace bedjet +} // namespace esphome diff --git a/tests/components/bedjet/common.yaml b/tests/components/bedjet/common.yaml index c2be04a49a..1563fc9dae 100644 --- a/tests/components/bedjet/common.yaml +++ b/tests/components/bedjet/common.yaml @@ -26,8 +26,16 @@ climate: name: My Bedjet bedjet_id: bedjet_hub heat_mode: extended + temperature_source: ambient fan: - platform: bedjet name: My Bedjet fan bedjet_id: bedjet_hub + +sensor: + - platform: bedjet + ambient_temperature: + name: My BedJet Ambient Temperature + outlet_temperature: + name: My BedJet Outlet Temperature From 46eee4a4f0c63c88294da9c3f27407af26d2ef98 Mon Sep 17 00:00:00 2001 From: Mat931 <49403702+Mat931@users.noreply.github.com> Date: Wed, 15 May 2024 23:32:48 +0000 Subject: [PATCH 1445/2101] Add beken_spi_led_strip component (#6515) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- CODEOWNERS | 1 + .../beken_spi_led_strip/__init__.py | 0 .../beken_spi_led_strip/led_strip.cpp | 384 ++++++++++++++++++ .../beken_spi_led_strip/led_strip.h | 85 ++++ .../components/beken_spi_led_strip/light.py | 134 ++++++ .../components/esp32_rmt_led_strip/light.py | 2 +- .../components/rp2040_pio_led_strip/light.py | 2 +- esphome/const.py | 1 + .../beken_spi_led_strip/test.bk72xx.yaml | 7 + .../build_components_base.bk72xx.yaml | 2 +- 10 files changed, 615 insertions(+), 3 deletions(-) create mode 100644 esphome/components/beken_spi_led_strip/__init__.py create mode 100644 esphome/components/beken_spi_led_strip/led_strip.cpp create mode 100644 esphome/components/beken_spi_led_strip/led_strip.h create mode 100644 esphome/components/beken_spi_led_strip/light.py create mode 100644 tests/components/beken_spi_led_strip/test.bk72xx.yaml diff --git a/CODEOWNERS b/CODEOWNERS index a661eba9b3..65ea3b1683 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -52,6 +52,7 @@ esphome/components/bedjet/* @jhansche esphome/components/bedjet/climate/* @jhansche esphome/components/bedjet/fan/* @jhansche esphome/components/bedjet/sensor/* @javawizard @jhansche +esphome/components/beken_spi_led_strip/* @Mat931 esphome/components/bh1750/* @OttoWinter esphome/components/binary_sensor/* @esphome/core esphome/components/bk72xx/* @kuba2k2 diff --git a/esphome/components/beken_spi_led_strip/__init__.py b/esphome/components/beken_spi_led_strip/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/beken_spi_led_strip/led_strip.cpp b/esphome/components/beken_spi_led_strip/led_strip.cpp new file mode 100644 index 0000000000..04c8649b90 --- /dev/null +++ b/esphome/components/beken_spi_led_strip/led_strip.cpp @@ -0,0 +1,384 @@ +#include "led_strip.h" + +#ifdef USE_BK72XX + +#include "esphome/core/helpers.h" +#include "esphome/core/log.h" + +extern "C" { +#include "rtos_pub.h" +#include "spi.h" +#include "arm_arch.h" +#include "general_dma_pub.h" +#include "gpio_pub.h" +#include "icu_pub.h" +#undef SPI_DAT +#undef SPI_BASE +}; + +static const uint32_t SPI_TX_DMA_CHANNEL = GDMA_CHANNEL_3; + +// TODO: Check if SPI_PERI_CLK_DCO depends on the chip variant +static const uint32_t SPI_PERI_CLK_26M = 26000000; +static const uint32_t SPI_PERI_CLK_DCO = 120000000; + +static const uint32_t SPI_BASE = 0x00802700; +static const uint32_t SPI_DAT = SPI_BASE + 3 * 4; +static const uint32_t SPI_CONFIG = SPI_BASE + 1 * 4; + +static const uint32_t SPI_TX_EN = 1 << 0; +static const uint32_t CTRL_NSSMD_3 = 1 << 17; +static const uint32_t SPI_TX_FINISH_EN = 1 << 2; +static const uint32_t SPI_RX_FINISH_EN = 1 << 3; + +namespace esphome { +namespace beken_spi_led_strip { + +static const char *const TAG = "beken_spi_led_strip"; + +struct spi_data_t { + SemaphoreHandle_t dma_tx_semaphore; + volatile bool tx_in_progress; + bool first_run; +}; + +static spi_data_t *spi_data = nullptr; + +static void set_spi_ctrl_register(unsigned long bit, bool val) { + uint32_t value = REG_READ(SPI_CTRL); + if (val == 0) { + value &= ~bit; + } else if (val == 1) { + value |= bit; + } + REG_WRITE(SPI_CTRL, value); +} + +static void set_spi_config_register(unsigned long bit, bool val) { + uint32_t value = REG_READ(SPI_CONFIG); + if (val == 0) { + value &= ~bit; + } else if (val == 1) { + value |= bit; + } + REG_WRITE(SPI_CONFIG, value); +} + +void spi_dma_tx_enable(bool enable) { + GDMA_CFG_ST en_cfg; + set_spi_config_register(SPI_TX_EN, enable ? 1 : 0); + en_cfg.channel = SPI_TX_DMA_CHANNEL; + en_cfg.param = enable ? 1 : 0; + sddev_control(GDMA_DEV_NAME, CMD_GDMA_SET_DMA_ENABLE, &en_cfg); +} + +static void spi_set_clock(uint32_t max_hz) { + int source_clk = 0; + int spi_clk = 0; + int div = 0; + uint32_t param; + if (max_hz > 4333000) { + if (max_hz > 30000000) { + spi_clk = 30000000; + } else { + spi_clk = max_hz; + } + sddev_control(ICU_DEV_NAME, CMD_CLK_PWR_DOWN, ¶m); + source_clk = SPI_PERI_CLK_DCO; + param = PCLK_POSI_SPI; + sddev_control(ICU_DEV_NAME, CMD_CONF_PCLK_DCO, ¶m); + param = PWD_SPI_CLK_BIT; + sddev_control(ICU_DEV_NAME, CMD_CLK_PWR_UP, ¶m); + } else { + spi_clk = max_hz; +#if CFG_XTAL_FREQUENCE + source_clk = CFG_XTAL_FREQUENCE; +#else + source_clk = SPI_PERI_CLK_26M; +#endif + param = PCLK_POSI_SPI; + sddev_control(ICU_DEV_NAME, CMD_CONF_PCLK_26M, ¶m); + } + div = ((source_clk >> 1) / spi_clk); + if (div < 2) { + div = 2; + } else if (div >= 255) { + div = 255; + } + param = REG_READ(SPI_CTRL); + param &= ~(SPI_CKR_MASK << SPI_CKR_POSI); + param |= (div << SPI_CKR_POSI); + REG_WRITE(SPI_CTRL, param); + ESP_LOGD(TAG, "target frequency: %d, actual frequency: %d", max_hz, source_clk / 2 / div); +} + +void spi_dma_tx_finish_callback(unsigned int param) { + spi_data->tx_in_progress = false; + xSemaphoreGive(spi_data->dma_tx_semaphore); + spi_dma_tx_enable(0); +} + +void BekenSPILEDStripLightOutput::setup() { + ESP_LOGCONFIG(TAG, "Setting up Beken SPI LED Strip..."); + + size_t buffer_size = this->get_buffer_size_(); + size_t dma_buffer_size = (buffer_size * 8) + (2 * 64); + + ExternalRAMAllocator allocator(ExternalRAMAllocator::ALLOW_FAILURE); + this->buf_ = allocator.allocate(buffer_size); + if (this->buf_ == nullptr) { + ESP_LOGE(TAG, "Cannot allocate LED buffer!"); + this->mark_failed(); + return; + } + + this->effect_data_ = allocator.allocate(this->num_leds_); + if (this->effect_data_ == nullptr) { + ESP_LOGE(TAG, "Cannot allocate effect data!"); + this->mark_failed(); + return; + } + + this->dma_buf_ = allocator.allocate(dma_buffer_size); + if (this->dma_buf_ == nullptr) { + ESP_LOGE(TAG, "Cannot allocate DMA buffer!"); + this->mark_failed(); + return; + } + + memset(this->buf_, 0, buffer_size); + memset(this->effect_data_, 0, this->num_leds_); + memset(this->dma_buf_, 0, dma_buffer_size); + + uint32_t value = PCLK_POSI_SPI; + sddev_control(ICU_DEV_NAME, CMD_CONF_PCLK_26M, &value); + + value = PWD_SPI_CLK_BIT; + sddev_control(ICU_DEV_NAME, CMD_CLK_PWR_UP, &value); + + if (spi_data != nullptr) { + ESP_LOGE(TAG, "SPI device already initialized!"); + this->mark_failed(); + return; + } + + spi_data = (spi_data_t *) calloc(1, sizeof(spi_data_t)); + if (spi_data == nullptr) { + ESP_LOGE(TAG, "Cannot allocate spi_data!"); + this->mark_failed(); + return; + } + + spi_data->dma_tx_semaphore = xSemaphoreCreateBinary(); + if (spi_data->dma_tx_semaphore == nullptr) { + ESP_LOGE(TAG, "TX Semaphore init faild!"); + this->mark_failed(); + return; + } + + spi_data->first_run = true; + + set_spi_ctrl_register(MSTEN, 0); + set_spi_ctrl_register(BIT_WDTH, 0); + spi_set_clock(this->spi_frequency_); + set_spi_ctrl_register(CKPOL, 0); + set_spi_ctrl_register(CKPHA, 0); + set_spi_ctrl_register(MSTEN, 1); + set_spi_ctrl_register(SPIEN, 1); + + set_spi_ctrl_register(TXINT_EN, 0); + set_spi_ctrl_register(RXINT_EN, 0); + set_spi_config_register(SPI_TX_FINISH_EN, 1); + set_spi_config_register(SPI_RX_FINISH_EN, 1); + set_spi_ctrl_register(RXOVR_EN, 0); + set_spi_ctrl_register(TXOVR_EN, 0); + + value = REG_READ(SPI_CTRL); + value &= ~CTRL_NSSMD_3; + value |= (1 << 17); + REG_WRITE(SPI_CTRL, value); + + value = GFUNC_MODE_SPI_DMA; + sddev_control(GPIO_DEV_NAME, CMD_GPIO_ENABLE_SECOND, &value); + set_spi_ctrl_register(SPI_S_CS_UP_INT_EN, 0); + + GDMA_CFG_ST en_cfg; + GDMACFG_TPYES_ST init_cfg; + memset(&init_cfg, 0, sizeof(GDMACFG_TPYES_ST)); + + init_cfg.dstdat_width = 8; + init_cfg.srcdat_width = 32; + init_cfg.dstptr_incr = 0; + init_cfg.srcptr_incr = 1; + init_cfg.src_start_addr = this->dma_buf_; + init_cfg.dst_start_addr = (void *) SPI_DAT; // SPI_DMA_REG4_TXFIFO + init_cfg.channel = SPI_TX_DMA_CHANNEL; + init_cfg.prio = 0; // 10 + init_cfg.u.type4.src_loop_start_addr = this->dma_buf_; + init_cfg.u.type4.src_loop_end_addr = this->dma_buf_ + dma_buffer_size; + init_cfg.half_fin_handler = nullptr; + init_cfg.fin_handler = spi_dma_tx_finish_callback; + init_cfg.src_module = GDMA_X_SRC_DTCM_RD_REQ; + init_cfg.dst_module = GDMA_X_DST_GSPI_TX_REQ; // GDMA_X_DST_HSSPI_TX_REQ + sddev_control(GDMA_DEV_NAME, CMD_GDMA_CFG_TYPE4, (void *) &init_cfg); + en_cfg.channel = SPI_TX_DMA_CHANNEL; + en_cfg.param = dma_buffer_size; + sddev_control(GDMA_DEV_NAME, CMD_GDMA_SET_TRANS_LENGTH, (void *) &en_cfg); + en_cfg.channel = SPI_TX_DMA_CHANNEL; + en_cfg.param = 0; + sddev_control(GDMA_DEV_NAME, CMD_GDMA_CFG_WORK_MODE, (void *) &en_cfg); + en_cfg.channel = SPI_TX_DMA_CHANNEL; + en_cfg.param = 0; + sddev_control(GDMA_DEV_NAME, CMD_GDMA_CFG_SRCADDR_LOOP, &en_cfg); + + spi_dma_tx_enable(0); + + value = REG_READ(SPI_CONFIG); + value &= ~(0xFFF << 8); + value |= ((dma_buffer_size & 0xFFF) << 8); + REG_WRITE(SPI_CONFIG, value); +} + +void BekenSPILEDStripLightOutput::set_led_params(uint8_t bit0, uint8_t bit1, uint32_t spi_frequency) { + this->bit0_ = bit0; + this->bit1_ = bit1; + this->spi_frequency_ = spi_frequency; +} + +void BekenSPILEDStripLightOutput::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_) { + // try again next loop iteration, so that this change won't get lost + this->schedule_show(); + return; + } + this->last_refresh_ = now; + this->mark_shown_(); + + ESP_LOGVV(TAG, "Writing RGB values to bus..."); + + if (spi_data == nullptr) { + ESP_LOGE(TAG, "SPI not initialized"); + this->status_set_warning(); + return; + } + + if (!spi_data->first_run && !xSemaphoreTake(spi_data->dma_tx_semaphore, 10 / portTICK_PERIOD_MS)) { + ESP_LOGE(TAG, "Timed out waiting for semaphore"); + return; + } + + if (spi_data->tx_in_progress) { + ESP_LOGE(TAG, "tx_in_progress is set"); + this->status_set_warning(); + return; + } + + spi_data->tx_in_progress = true; + + size_t buffer_size = this->get_buffer_size_(); + size_t size = 0; + uint8_t *psrc = this->buf_; + uint8_t *pdest = this->dma_buf_ + 64; + // The 64 byte padding is a workaround for a SPI DMA bug where the + // output doesn't exactly start at the beginning of dma_buf_ + + while (size < buffer_size) { + uint8_t b = *psrc; + for (int i = 0; i < 8; i++) { + *pdest++ = b & (1 << (7 - i)) ? this->bit1_ : this->bit0_; + } + size++; + psrc++; + } + + spi_data->first_run = false; + spi_dma_tx_enable(1); + + this->status_clear_warning(); +} + +light::ESPColorView BekenSPILEDStripLightOutput::get_view_internal(int32_t index) const { + int32_t r = 0, g = 0, b = 0; + switch (this->rgb_order_) { + case ORDER_RGB: + r = 0; + g = 1; + b = 2; + break; + case ORDER_RBG: + r = 0; + g = 2; + b = 1; + break; + case ORDER_GRB: + r = 1; + g = 0; + b = 2; + break; + case ORDER_GBR: + r = 2; + g = 0; + b = 1; + break; + case ORDER_BGR: + r = 2; + g = 1; + b = 0; + break; + case ORDER_BRG: + r = 1; + g = 2; + b = 0; + break; + } + uint8_t multiplier = this->is_rgbw_ || this->is_wrgb_ ? 4 : 3; + uint8_t white = this->is_wrgb_ ? 0 : 3; + + return {this->buf_ + (index * multiplier) + r + this->is_wrgb_, + this->buf_ + (index * multiplier) + g + this->is_wrgb_, + this->buf_ + (index * multiplier) + b + this->is_wrgb_, + this->is_rgbw_ || this->is_wrgb_ ? this->buf_ + (index * multiplier) + white : nullptr, + &this->effect_data_[index], + &this->correction_}; +} + +void BekenSPILEDStripLightOutput::dump_config() { + ESP_LOGCONFIG(TAG, "Beken SPI LED Strip:"); + ESP_LOGCONFIG(TAG, " Pin: %u", this->pin_); + const char *rgb_order; + switch (this->rgb_order_) { + case ORDER_RGB: + rgb_order = "RGB"; + break; + case ORDER_RBG: + rgb_order = "RBG"; + break; + case ORDER_GRB: + rgb_order = "GRB"; + break; + case ORDER_GBR: + rgb_order = "GBR"; + break; + case ORDER_BGR: + rgb_order = "BGR"; + break; + case ORDER_BRG: + rgb_order = "BRG"; + break; + default: + rgb_order = "UNKNOWN"; + break; + } + ESP_LOGCONFIG(TAG, " RGB Order: %s", rgb_order); + ESP_LOGCONFIG(TAG, " Max refresh rate: %" PRIu32, *this->max_refresh_rate_); + ESP_LOGCONFIG(TAG, " Number of LEDs: %u", this->num_leds_); +} + +float BekenSPILEDStripLightOutput::get_setup_priority() const { return setup_priority::HARDWARE; } + +} // namespace beken_spi_led_strip +} // namespace esphome + +#endif // USE_BK72XX diff --git a/esphome/components/beken_spi_led_strip/led_strip.h b/esphome/components/beken_spi_led_strip/led_strip.h new file mode 100644 index 0000000000..705f9102a9 --- /dev/null +++ b/esphome/components/beken_spi_led_strip/led_strip.h @@ -0,0 +1,85 @@ +#pragma once + +#ifdef USE_BK72XX + +#include "esphome/components/light/addressable_light.h" +#include "esphome/components/light/light_output.h" +#include "esphome/core/color.h" +#include "esphome/core/component.h" +#include "esphome/core/helpers.h" + +namespace esphome { +namespace beken_spi_led_strip { + +enum RGBOrder : uint8_t { + ORDER_RGB, + ORDER_RBG, + ORDER_GRB, + ORDER_GBR, + ORDER_BGR, + ORDER_BRG, +}; + +class BekenSPILEDStripLightOutput : public light::AddressableLight { + public: + void setup() override; + void write_state(light::LightState *state) override; + float get_setup_priority() const override; + + int32_t size() const override { return this->num_leds_; } + light::LightTraits get_traits() override { + auto traits = light::LightTraits(); + if (this->is_rgbw_ || this->is_wrgb_) { + traits.set_supported_color_modes({light::ColorMode::RGB_WHITE, light::ColorMode::WHITE}); + } else { + traits.set_supported_color_modes({light::ColorMode::RGB}); + } + return traits; + } + + void set_pin(uint8_t pin) { this->pin_ = pin; } + void set_num_leds(uint16_t num_leds) { this->num_leds_ = num_leds; } + void set_is_rgbw(bool is_rgbw) { this->is_rgbw_ = is_rgbw; } + void set_is_wrgb(bool is_wrgb) { this->is_wrgb_ = is_wrgb; } + + /// Set a maximum refresh rate in µs as some lights do not like being updated too often. + void set_max_refresh_rate(uint32_t interval_us) { this->max_refresh_rate_ = interval_us; } + + void set_led_params(uint8_t bit0, uint8_t bit1, uint32_t spi_frequency); + + void set_rgb_order(RGBOrder rgb_order) { this->rgb_order_ = rgb_order; } + + void clear_effect_data() override { + for (int i = 0; i < this->size(); i++) + this->effect_data_[i] = 0; + } + + void dump_config() override; + + protected: + light::ESPColorView get_view_internal(int32_t index) const override; + + size_t get_buffer_size_() const { return this->num_leds_ * (this->is_rgbw_ || this->is_wrgb_ ? 4 : 3); } + + uint8_t *buf_{nullptr}; + uint8_t *effect_data_{nullptr}; + uint8_t *dma_buf_{nullptr}; + + uint8_t pin_; + uint16_t num_leds_; + bool is_rgbw_; + bool is_wrgb_; + + uint32_t spi_frequency_{6666666}; + uint8_t bit0_{0xE0}; + uint8_t bit1_{0xFC}; + RGBOrder rgb_order_; + + uint32_t last_refresh_{0}; + optional max_refresh_rate_{}; +}; + +} // namespace beken_spi_led_strip +} // namespace esphome + +#endif // USE_BK72XX diff --git a/esphome/components/beken_spi_led_strip/light.py b/esphome/components/beken_spi_led_strip/light.py new file mode 100644 index 0000000000..2a1aa05c79 --- /dev/null +++ b/esphome/components/beken_spi_led_strip/light.py @@ -0,0 +1,134 @@ +from dataclasses import dataclass + +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome import pins +from esphome.components import libretiny, light +from esphome.const import ( + CONF_CHIPSET, + CONF_IS_RGBW, + CONF_MAX_REFRESH_RATE, + CONF_NUM_LEDS, + CONF_OUTPUT_ID, + CONF_PIN, + CONF_RGB_ORDER, +) + +CODEOWNERS = ["@Mat931"] +DEPENDENCIES = ["libretiny"] + +beken_spi_led_strip_ns = cg.esphome_ns.namespace("beken_spi_led_strip") +BekenSPILEDStripLightOutput = beken_spi_led_strip_ns.class_( + "BekenSPILEDStripLightOutput", light.AddressableLight +) + +RGBOrder = beken_spi_led_strip_ns.enum("RGBOrder") + +RGB_ORDERS = { + "RGB": RGBOrder.ORDER_RGB, + "RBG": RGBOrder.ORDER_RBG, + "GRB": RGBOrder.ORDER_GRB, + "GBR": RGBOrder.ORDER_GBR, + "BGR": RGBOrder.ORDER_BGR, + "BRG": RGBOrder.ORDER_BRG, +} + + +@dataclass +class LEDStripTimings: + bit0: int + bit1: int + spi_frequency: int + + +CHIPSETS = { + "WS2812": LEDStripTimings( + 0b11100000, 0b11111100, 6666666 + ), # Clock divider: 9, Bit time: 1350ns + "SK6812": LEDStripTimings( + 0b11000000, 0b11111000, 7500000 + ), # Clock divider: 8, Bit time: 1200ns + "APA106": LEDStripTimings( + 0b11000000, 0b11111110, 5454545 + ), # Clock divider: 11, Bit time: 1650ns + "SM16703": LEDStripTimings( + 0b11000000, 0b11111110, 7500000 + ), # Clock divider: 8, Bit time: 1200ns +} + + +CONF_IS_WRGB = "is_wrgb" + +SUPPORTED_PINS = { + libretiny.const.FAMILY_BK7231N: [16], + libretiny.const.FAMILY_BK7231T: [16], + libretiny.const.FAMILY_BK7251: [16], +} + + +def _validate_pin(value): + family = libretiny.get_libretiny_family() + if family not in SUPPORTED_PINS: + raise cv.Invalid(f"Chip family {family} is not supported.") + if value not in SUPPORTED_PINS[family]: + supported_pin_info = ", ".join(f"{x}" for x in SUPPORTED_PINS[family]) + raise cv.Invalid( + f"Pin {value} is not supported on the {family}. Supported pins: {supported_pin_info}" + ) + return value + + +def _validate_num_leds(value): + max_num_leds = 165 # 170 + if value[CONF_IS_RGBW] or value[CONF_IS_WRGB]: + max_num_leds = 123 # 127 + if value[CONF_NUM_LEDS] > max_num_leds: + raise cv.Invalid( + f"The maximum number of LEDs for this configuration is {max_num_leds}.", + path=CONF_NUM_LEDS, + ) + return value + + +CONFIG_SCHEMA = cv.All( + light.ADDRESSABLE_LIGHT_SCHEMA.extend( + { + cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(BekenSPILEDStripLightOutput), + cv.Required(CONF_PIN): cv.All( + pins.internal_gpio_output_pin_number, _validate_pin + ), + cv.Required(CONF_NUM_LEDS): cv.positive_not_null_int, + cv.Required(CONF_RGB_ORDER): cv.enum(RGB_ORDERS, upper=True), + cv.Optional(CONF_MAX_REFRESH_RATE): cv.positive_time_period_microseconds, + cv.Required(CONF_CHIPSET): cv.one_of(*CHIPSETS, upper=True), + cv.Optional(CONF_IS_RGBW, default=False): cv.boolean, + cv.Optional(CONF_IS_WRGB, default=False): cv.boolean, + } + ), + _validate_num_leds, +) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_OUTPUT_ID]) + await light.register_light(var, config) + await cg.register_component(var, config) + + cg.add(var.set_num_leds(config[CONF_NUM_LEDS])) + cg.add(var.set_pin(config[CONF_PIN])) + + if CONF_MAX_REFRESH_RATE in config: + cg.add(var.set_max_refresh_rate(config[CONF_MAX_REFRESH_RATE])) + + chipset = CHIPSETS[config[CONF_CHIPSET]] + cg.add( + var.set_led_params( + chipset.bit0, + chipset.bit1, + chipset.spi_frequency, + ) + ) + + cg.add(var.set_rgb_order(config[CONF_RGB_ORDER])) + cg.add(var.set_is_rgbw(config[CONF_IS_RGBW])) + cg.add(var.set_is_wrgb(config[CONF_IS_WRGB])) diff --git a/esphome/components/esp32_rmt_led_strip/light.py b/esphome/components/esp32_rmt_led_strip/light.py index 1c15a468d9..4c8472b8d2 100644 --- a/esphome/components/esp32_rmt_led_strip/light.py +++ b/esphome/components/esp32_rmt_led_strip/light.py @@ -6,6 +6,7 @@ from esphome import pins from esphome.components import esp32_rmt, light from esphome.const import ( CONF_CHIPSET, + CONF_IS_RGBW, CONF_MAX_REFRESH_RATE, CONF_NUM_LEDS, CONF_OUTPUT_ID, @@ -52,7 +53,6 @@ CHIPSETS = { } -CONF_IS_RGBW = "is_rgbw" CONF_IS_WRGB = "is_wrgb" CONF_BIT0_HIGH = "bit0_high" CONF_BIT0_LOW = "bit0_low" diff --git a/esphome/components/rp2040_pio_led_strip/light.py b/esphome/components/rp2040_pio_led_strip/light.py index 6c51b57e97..202263c914 100644 --- a/esphome/components/rp2040_pio_led_strip/light.py +++ b/esphome/components/rp2040_pio_led_strip/light.py @@ -5,6 +5,7 @@ from esphome.components import light, rp2040 from esphome.const import ( CONF_CHIPSET, CONF_ID, + CONF_IS_RGBW, CONF_NUM_LEDS, CONF_OUTPUT_ID, CONF_PIN, @@ -165,7 +166,6 @@ CHIPSETS = { "SM16703": LEDStripTimings(17, 52, 52, 17), } -CONF_IS_RGBW = "is_rgbw" CONF_BIT0_HIGH = "bit0_high" CONF_BIT0_LOW = "bit0_low" CONF_BIT1_HIGH = "bit1_high" diff --git a/esphome/const.py b/esphome/const.py index 542183d3b2..eb48080040 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -399,6 +399,7 @@ CONF_INVERT_COLORS = "invert_colors" CONF_INVERTED = "inverted" CONF_IP_ADDRESS = "ip_address" CONF_IRQ_PIN = "irq_pin" +CONF_IS_RGBW = "is_rgbw" CONF_JS_INCLUDE = "js_include" CONF_JS_URL = "js_url" CONF_JVC = "jvc" diff --git a/tests/components/beken_spi_led_strip/test.bk72xx.yaml b/tests/components/beken_spi_led_strip/test.bk72xx.yaml new file mode 100644 index 0000000000..15409caeaf --- /dev/null +++ b/tests/components/beken_spi_led_strip/test.bk72xx.yaml @@ -0,0 +1,7 @@ +light: + - platform: beken_spi_led_strip + rgb_order: GRB + pin: P16 + num_leds: 30 + chipset: ws2812 + name: "My Light" diff --git a/tests/test_build_components/build_components_base.bk72xx.yaml b/tests/test_build_components/build_components_base.bk72xx.yaml index 9fd9431826..9a4e15d5cf 100644 --- a/tests/test_build_components/build_components_base.bk72xx.yaml +++ b/tests/test_build_components/build_components_base.bk72xx.yaml @@ -3,7 +3,7 @@ esphome: friendly_name: $component_name bk72xx: - board: cb3s + board: generic-bk7231n-qfn32-tuya logger: level: VERY_VERBOSE From 073fb4c124c6725c262d16b5a94bfac43f9cc344 Mon Sep 17 00:00:00 2001 From: ius Date: Thu, 16 May 2024 01:33:15 +0200 Subject: [PATCH 1446/2101] i2c: fix format string specifiers (#6746) --- 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 cbb748cca1..3a9c229778 100644 --- a/esphome/components/i2c/i2c_bus_esp_idf.cpp +++ b/esphome/components/i2c/i2c_bus_esp_idf.cpp @@ -56,7 +56,7 @@ void IDFI2CBus::setup() { this->mark_failed(); return; } else { - ESP_LOGV(TAG, "i2c_timeout set to %d ticks (%d us)", timeout_ * 80, timeout_); + ESP_LOGV(TAG, "i2c_timeout set to %" PRIu32 " ticks (%" PRIu32 " us)", timeout_ * 80, timeout_); } } err = i2c_driver_install(port_, I2C_MODE_MASTER, 0, 0, ESP_INTR_FLAG_IRAM); From 8952719045f2fb0ed53d9c014d682933d10960ae Mon Sep 17 00:00:00 2001 From: lbilger Date: Thu, 16 May 2024 01:33:27 +0200 Subject: [PATCH 1447/2101] Allow one timing to cancel others (#6744) Co-authored-by: Lars Bilger --- esphome/components/binary_sensor/automation.cpp | 5 +++++ esphome/components/binary_sensor/automation.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/esphome/components/binary_sensor/automation.cpp b/esphome/components/binary_sensor/automation.cpp index 7ac201b2db..c2e76246aa 100644 --- a/esphome/components/binary_sensor/automation.cpp +++ b/esphome/components/binary_sensor/automation.cpp @@ -98,6 +98,11 @@ void binary_sensor::MultiClickTrigger::schedule_is_not_valid_(uint32_t max_lengt this->schedule_cooldown_(); }); } +void binary_sensor::MultiClickTrigger::cancel() { + ESP_LOGV(TAG, "Multi Click: Sequence explicitly cancelled."); + this->is_valid_ = false; + this->schedule_cooldown_(); +} void binary_sensor::MultiClickTrigger::trigger_() { ESP_LOGV(TAG, "Multi Click: Hooray, multi click is valid. Triggering!"); this->at_index_.reset(); diff --git a/esphome/components/binary_sensor/automation.h b/esphome/components/binary_sensor/automation.h index a5e9d208a1..12b07a05e3 100644 --- a/esphome/components/binary_sensor/automation.h +++ b/esphome/components/binary_sensor/automation.h @@ -105,6 +105,8 @@ class MultiClickTrigger : public Trigger<>, public Component { void set_invalid_cooldown(uint32_t invalid_cooldown) { this->invalid_cooldown_ = invalid_cooldown; } + void cancel(); + protected: void on_state_(bool state); void schedule_cooldown_(); From ebfccc64c7f2b7274a79e4cfaf19e1d46cc87bb2 Mon Sep 17 00:00:00 2001 From: Daniel Mahaney Date: Wed, 15 May 2024 19:33:52 -0400 Subject: [PATCH 1448/2101] fix rp2040_pio_led flicker and proper multi-strip support (#6194) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- .../rp2040_pio_led_strip/led_strip.cpp | 75 +++++++++++++++---- .../rp2040_pio_led_strip/led_strip.h | 20 +++++ .../components/rp2040_pio_led_strip/light.py | 65 +++++++++------- 3 files changed, 122 insertions(+), 38 deletions(-) diff --git a/esphome/components/rp2040_pio_led_strip/led_strip.cpp b/esphome/components/rp2040_pio_led_strip/led_strip.cpp index c04419a9bf..3e5e82898d 100644 --- a/esphome/components/rp2040_pio_led_strip/led_strip.cpp +++ b/esphome/components/rp2040_pio_led_strip/led_strip.cpp @@ -6,6 +6,7 @@ #include "esphome/core/log.h" #include +#include #include #include @@ -14,6 +15,15 @@ namespace rp2040_pio_led_strip { static const char *TAG = "rp2040_pio_led_strip"; +static uint8_t num_instance_[2] = {0, 0}; +static std::map chipset_offsets_ = { + {CHIPSET_WS2812, 0}, {CHIPSET_WS2812B, 0}, {CHIPSET_SK6812, 0}, {CHIPSET_SM16703, 0}, {CHIPSET_CUSTOM, 0}, +}; +static std::map conf_count_ = { + {CHIPSET_WS2812, false}, {CHIPSET_WS2812B, false}, {CHIPSET_SK6812, false}, + {CHIPSET_SM16703, false}, {CHIPSET_CUSTOM, false}, +}; + void RP2040PIOLEDStripLightOutput::setup() { ESP_LOGCONFIG(TAG, "Setting up RP2040 LED Strip..."); @@ -34,24 +44,71 @@ void RP2040PIOLEDStripLightOutput::setup() { return; } + // Initialize the PIO program + // Select PIO instance to use (0 or 1) - this->pio_ = pio0; if (this->pio_ == nullptr) { ESP_LOGE(TAG, "Failed to claim PIO instance"); this->mark_failed(); return; } - // Load the assembled program into the PIO and get its location in the PIO's instruction memory - uint offset = pio_add_program(this->pio_, this->program_); + // if there are multiple strips, we can reuse the same PIO program and save space + // but there are only 4 state machines on each PIO so we can only have 4 strips per PIO + uint offset = 0; + + if (num_instance_[this->pio_ == pio0 ? 0 : 1] > 4) { + ESP_LOGE(TAG, "Too many instances of PIO program"); + this->mark_failed(); + return; + } + // keep track of how many instances of the PIO program are running on each PIO + num_instance_[this->pio_ == pio0 ? 0 : 1]++; + + // if there are multiple strips of the same chipset, we can reuse the same PIO program and save space + if (this->conf_count_[this->chipset_]) { + offset = chipset_offsets_[this->chipset_]; + } else { + // Load the assembled program into the PIO and get its location in the PIO's instruction memory and save it + offset = pio_add_program(this->pio_, this->program_); + chipset_offsets_[this->chipset_] = offset; + conf_count_[this->chipset_] = true; + } // Configure the state machine's PIO, and start it this->sm_ = pio_claim_unused_sm(this->pio_, true); if (this->sm_ < 0) { + // in theory this code should never be reached ESP_LOGE(TAG, "Failed to claim PIO state machine"); this->mark_failed(); return; } + + // Initalize the DMA channel (Note: There are 12 DMA channels and 8 state machines so we won't run out) + + this->dma_chan_ = dma_claim_unused_channel(true); + if (this->dma_chan_ < 0) { + ESP_LOGE(TAG, "Failed to claim DMA channel"); + this->mark_failed(); + return; + } + + this->dma_config_ = dma_channel_get_default_config(this->dma_chan_); + channel_config_set_transfer_data_size( + &this->dma_config_, + DMA_SIZE_8); // 8 bit transfers (could be 32 but the pio program would need to be changed to handle junk data) + channel_config_set_read_increment(&this->dma_config_, true); // increment the read address + channel_config_set_write_increment(&this->dma_config_, false); // don't increment the write address + channel_config_set_dreq(&this->dma_config_, + pio_get_dreq(this->pio_, this->sm_, true)); // set the DREQ to the state machine's TX FIFO + + dma_channel_configure(this->dma_chan_, &this->dma_config_, + &this->pio_->txf[this->sm_], // write to the state machine's TX FIFO + this->buf_, // read from memory + this->is_rgbw_ ? num_leds_ * 4 : num_leds_ * 3, // number of bytes to transfer + false // don't start yet + ); + this->init_(this->pio_, this->sm_, offset, this->pin_, this->max_refresh_rate_); } @@ -68,16 +125,8 @@ void RP2040PIOLEDStripLightOutput::write_state(light::LightState *state) { return; } - // assemble bits in buffer to 32 bit words with ex for GBR: 0bGGGGGGGGRRRRRRRRBBBBBBBB00000000 - for (int i = 0; i < this->num_leds_; i++) { - uint8_t multiplier = this->is_rgbw_ ? 4 : 3; - uint8_t c1 = this->buf_[(i * multiplier) + 0]; - uint8_t c2 = this->buf_[(i * multiplier) + 1]; - uint8_t c3 = this->buf_[(i * multiplier) + 2]; - uint8_t w = this->is_rgbw_ ? this->buf_[(i * 4) + 3] : 0; - uint32_t color = encode_uint32(c1, c2, c3, w); - pio_sm_put_blocking(this->pio_, this->sm_, color); - } + // the bits are already in the correct order for the pio program so we can just copy the buffer using DMA + dma_channel_transfer_from_buffer_now(this->dma_chan_, this->buf_, this->get_buffer_size_()); } light::ESPColorView RP2040PIOLEDStripLightOutput::get_view_internal(int32_t index) const { diff --git a/esphome/components/rp2040_pio_led_strip/led_strip.h b/esphome/components/rp2040_pio_led_strip/led_strip.h index 25ef9ca55f..9976842f02 100644 --- a/esphome/components/rp2040_pio_led_strip/led_strip.h +++ b/esphome/components/rp2040_pio_led_strip/led_strip.h @@ -9,9 +9,11 @@ #include "esphome/components/light/addressable_light.h" #include "esphome/components/light/light_output.h" +#include #include #include #include +#include namespace esphome { namespace rp2040_pio_led_strip { @@ -25,6 +27,15 @@ enum RGBOrder : uint8_t { ORDER_BRG, }; +enum Chipset : uint8_t { + CHIPSET_WS2812, + CHIPSET_WS2812B, + CHIPSET_SK6812, + CHIPSET_SM16703, + CHIPSET_APA102, + CHIPSET_CUSTOM = 0xFF, +}; + inline const char *rgb_order_to_string(RGBOrder order) { switch (order) { case ORDER_RGB: @@ -69,6 +80,7 @@ class RP2040PIOLEDStripLightOutput : public light::AddressableLight { void set_program(const pio_program_t *program) { this->program_ = program; } void set_init_function(init_fn init) { this->init_ = init; } + void set_chipset(Chipset chipset) { this->chipset_ = chipset; }; void set_rgb_order(RGBOrder rgb_order) { this->rgb_order_ = rgb_order; } void clear_effect_data() override { for (int i = 0; i < this->size(); i++) { @@ -92,14 +104,22 @@ class RP2040PIOLEDStripLightOutput : public light::AddressableLight { pio_hw_t *pio_; uint sm_; + uint dma_chan_; + dma_channel_config dma_config_; RGBOrder rgb_order_{ORDER_RGB}; + Chipset chipset_{CHIPSET_CUSTOM}; uint32_t last_refresh_{0}; float max_refresh_rate_; const pio_program_t *program_; init_fn init_; + + private: + inline static int num_instance_[2]; + inline static std::map conf_count_; + inline static std::map chipset_offsets_; }; } // namespace rp2040_pio_led_strip diff --git a/esphome/components/rp2040_pio_led_strip/light.py b/esphome/components/rp2040_pio_led_strip/light.py index 202263c914..8dd2549ad4 100644 --- a/esphome/components/rp2040_pio_led_strip/light.py +++ b/esphome/components/rp2040_pio_led_strip/light.py @@ -68,12 +68,15 @@ static inline void rp2040_pio_led_strip_driver_{id}_init(PIO pio, uint sm, uint pio_sm_config c = rp2040_pio_led_strip_{id}_program_get_default_config(offset); sm_config_set_set_pins(&c, pin, 1); - sm_config_set_out_shift(&c, false, true, {32 if rgbw else 24}); + sm_config_set_out_shift(&c, false, true, 8); sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); - int cycles_per_bit = 69; - float div = 2.409; - sm_config_set_clkdiv(&c, div); + // target frequency is 57.5MHz + long clk = clock_get_hz(clk_sys); + long target_freq = 57500000; + int n = 2; + int f = round(((clk / target_freq) - n ) * 256); + sm_config_set_clkdiv_int_frac(&c, n, f); pio_sm_init(pio, sm, offset, &c); @@ -86,8 +89,9 @@ static inline void rp2040_pio_led_strip_driver_{id}_init(PIO pio, uint sm, uint .wrap_target awaiting_data: ; Wait for data in FIFO queue + ; out null, 24 ; discard the byte lane replication of the FIFO since we only need 8 bits (not needed????) pull block ; this will block until there is data in the FIFO queue and then it will pull it into the shift register - set y, {31 if rgbw else 23} ; set y to the number of bits to write counting 0, (23 if RGB, 31 if RGBW) + set y, 7 ; set y to the number of bits to write counting 0, (always 7 because we are doing one word at a time) mainloop: ; go through each bit in the shift register and jump to the appropriate label @@ -95,7 +99,15 @@ mainloop: out x, 1 jmp !x, writezero - jmp writeone + +writeone: + ; Write T1H and T1L bits to the output pin + set pins, 1 [{t1h}] +{nops_t1h} + set pins, 0 [{t1l}] +{nops_t1l} + jmp y--, mainloop + jmp awaiting_data writezero: ; Write T0H and T0L bits to the output pin @@ -106,14 +118,7 @@ writezero: jmp y--, mainloop jmp awaiting_data -writeone: - ; Write T1H and T1L bits to the output pin - set pins, 1 [{t1h}] -{nops_t1h} - set pins, 0 [{t1l}] -{nops_t1l} - jmp y--, mainloop - jmp awaiting_data + .wrap""" @@ -139,7 +144,15 @@ RP2040PIOLEDStripLightOutput = rp2040_pio_led_strip_ns.class_( RGBOrder = rp2040_pio_led_strip_ns.enum("RGBOrder") -Chipsets = rp2040_pio_led_strip_ns.enum("Chipset") +Chipset = rp2040_pio_led_strip_ns.enum("Chipset") + +CHIPSETS = { + "WS2812": Chipset.CHIPSET_WS2812, + "WS2812B": Chipset.CHIPSET_WS2812B, + "SK6812": Chipset.CHIPSET_SK6812, + "SM16703": Chipset.CHIPSET_SM16703, + "CUSTOM": Chipset.CHIPSET_CUSTOM, +} @dataclass @@ -159,10 +172,10 @@ RGB_ORDERS = { "BRG": RGBOrder.ORDER_BRG, } -CHIPSETS = { - "WS2812": LEDStripTimings(20, 43, 41, 31), - "WS2812B": LEDStripTimings(23, 46, 46, 23), - "SK6812": LEDStripTimings(17, 52, 31, 31), +CHIPSET_TIMINGS = { + "WS2812": LEDStripTimings(20, 40, 46, 34), + "WS2812B": LEDStripTimings(23, 49, 46, 26), + "SK6812": LEDStripTimings(17, 52, 34, 34), "SM16703": LEDStripTimings(17, 52, 52, 17), } @@ -192,7 +205,7 @@ CONFIG_SCHEMA = cv.All( cv.Required(CONF_NUM_LEDS): cv.positive_not_null_int, cv.Required(CONF_RGB_ORDER): cv.enum(RGB_ORDERS, upper=True), cv.Required(CONF_PIO): cv.one_of(0, 1, int=True), - cv.Optional(CONF_CHIPSET): cv.one_of(*CHIPSETS, upper=True), + cv.Optional(CONF_CHIPSET): cv.enum(CHIPSETS, upper=True), cv.Optional(CONF_IS_RGBW, default=False): cv.boolean, cv.Inclusive( CONF_BIT0_HIGH, @@ -238,7 +251,8 @@ async def to_code(config): key = f"led_strip_{id}" - if CONF_CHIPSET in config: + if chipset := config.get(CONF_CHIPSET): + cg.add(var.set_chipset(chipset)) _LOGGER.info("Generating PIO assembly code") rp2040.add_pio_file( __name__, @@ -246,13 +260,14 @@ async def to_code(config): generate_assembly_code( id, config[CONF_IS_RGBW], - CHIPSETS[config[CONF_CHIPSET]].T0H, - CHIPSETS[config[CONF_CHIPSET]].T0L, - CHIPSETS[config[CONF_CHIPSET]].T1H, - CHIPSETS[config[CONF_CHIPSET]].T1L, + CHIPSET_TIMINGS[chipset].T0H, + CHIPSET_TIMINGS[chipset].T0L, + CHIPSET_TIMINGS[chipset].T1H, + CHIPSET_TIMINGS[chipset].T1L, ), ) else: + cg.add(var.set_chipset(Chipset.CHIPSET_CUSTOM)) _LOGGER.info("Generating custom PIO assembly code") rp2040.add_pio_file( __name__, From 08509f775529a0ed07b3d0958208cc9f5cb51d86 Mon Sep 17 00:00:00 2001 From: heggi Date: Thu, 16 May 2024 03:35:17 +0400 Subject: [PATCH 1449/2101] Mirage remote receiver & transmitter (#6479) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/remote_base/__init__.py | 38 +++++++++ .../remote_base/mirage_protocol.cpp | 84 +++++++++++++++++++ .../components/remote_base/mirage_protocol.h | 39 +++++++++ .../remote_receiver/esp32-common.yaml | 4 + .../remote_receiver/test.esp8266.yaml | 4 + .../remote_transmitter/common-buttons.yaml | 5 ++ 6 files changed, 174 insertions(+) create mode 100644 esphome/components/remote_base/mirage_protocol.cpp create mode 100644 esphome/components/remote_base/mirage_protocol.h diff --git a/esphome/components/remote_base/__init__.py b/esphome/components/remote_base/__init__.py index 8a1d50d1c6..9d49026aa3 100644 --- a/esphome/components/remote_base/__init__.py +++ b/esphome/components/remote_base/__init__.py @@ -1913,3 +1913,41 @@ async def abbwelcome_action(var, config, args): cg.add(var.set_data_template(template_)) else: cg.add(var.set_data_static(data_)) + + +# Mirage +( + MirageData, + MirageBinarySensor, + MirageTrigger, + MirageAction, + MirageDumper, +) = declare_protocol("Mirage") + +MIRAGE_SCHEMA = cv.Schema( + { + cv.Required(CONF_CODE): cv.All([cv.hex_uint8_t], cv.Length(min=14, max=14)), + } +) + + +@register_binary_sensor("mirage", MirageBinarySensor, MIRAGE_SCHEMA) +def mirage_binary_sensor(var, config): + cg.add(var.set_code(config[CONF_CODE])) + + +@register_trigger("mirage", MirageTrigger, MirageData) +def mirage_trigger(var, config): + pass + + +@register_dumper("mirage", MirageDumper) +def mirage_dumper(var, config): + pass + + +@register_action("mirage", MirageAction, MIRAGE_SCHEMA) +async def mirage_action(var, config, args): + vec_ = cg.std_vector.template(cg.uint8) + template_ = await cg.templatable(config[CONF_CODE], args, vec_, vec_) + cg.add(var.set_code(template_)) diff --git a/esphome/components/remote_base/mirage_protocol.cpp b/esphome/components/remote_base/mirage_protocol.cpp new file mode 100644 index 0000000000..10d644a1cd --- /dev/null +++ b/esphome/components/remote_base/mirage_protocol.cpp @@ -0,0 +1,84 @@ +#include "mirage_protocol.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace remote_base { + +static const char *const TAG = "remote.mirage"; + +constexpr uint32_t HEADER_MARK_US = 8360; +constexpr uint32_t HEADER_SPACE_US = 4248; +constexpr uint32_t BIT_MARK_US = 554; +constexpr uint32_t BIT_ONE_SPACE_US = 1592; +constexpr uint32_t BIT_ZERO_SPACE_US = 545; + +constexpr unsigned int MIRAGE_IR_PACKET_BIT_SIZE = 120; + +void MirageProtocol::encode(RemoteTransmitData *dst, const MirageData &data) { + ESP_LOGI(TAG, "Transive Mirage: %s", format_hex_pretty(data.data).c_str()); + dst->set_carrier_frequency(38000); + dst->reserve(5 + ((data.data.size() + 1) * 2)); + dst->mark(HEADER_MARK_US); + dst->space(HEADER_SPACE_US); + dst->mark(BIT_MARK_US); + uint8_t checksum = 0; + for (uint8_t item : data.data) { + this->encode_byte_(dst, item); + checksum += (item >> 4) + (item & 0xF); + } + this->encode_byte_(dst, checksum); +} + +void MirageProtocol::encode_byte_(RemoteTransmitData *dst, uint8_t item) { + for (uint8_t b = 0; b < 8; b++) { + if (item & (1UL << b)) { + dst->space(BIT_ONE_SPACE_US); + } else { + dst->space(BIT_ZERO_SPACE_US); + } + dst->mark(BIT_MARK_US); + } +} + +optional MirageProtocol::decode(RemoteReceiveData src) { + if (!src.expect_item(HEADER_MARK_US, HEADER_SPACE_US)) { + return {}; + } + if (!src.expect_mark(BIT_MARK_US)) { + return {}; + } + size_t size = src.size() - src.get_index() - 1; + if (size < MIRAGE_IR_PACKET_BIT_SIZE * 2) + return {}; + size = MIRAGE_IR_PACKET_BIT_SIZE * 2; + uint8_t checksum = 0; + MirageData out; + while (size > 0) { + uint8_t data = 0; + for (uint8_t b = 0; b < 8; b++) { + if (src.expect_space(BIT_ONE_SPACE_US)) { + data |= (1UL << b); + } else if (!src.expect_space(BIT_ZERO_SPACE_US)) { + return {}; + } + if (!src.expect_mark(BIT_MARK_US)) { + return {}; + } + size -= 2; + } + if (size > 0) { + checksum += (data >> 4) + (data & 0xF); + out.data.push_back(data); + } else if (checksum != data) { + return {}; + } + } + return out; +} + +void MirageProtocol::dump(const MirageData &data) { + ESP_LOGI(TAG, "Received Mirage: %s", format_hex_pretty(data.data).c_str()); +} + +} // namespace remote_base +} // namespace esphome diff --git a/esphome/components/remote_base/mirage_protocol.h b/esphome/components/remote_base/mirage_protocol.h new file mode 100644 index 0000000000..4257f7fa00 --- /dev/null +++ b/esphome/components/remote_base/mirage_protocol.h @@ -0,0 +1,39 @@ +#pragma once + +#include "esphome/core/component.h" +#include "remote_base.h" + +namespace esphome { +namespace remote_base { + +struct MirageData { + std::vector data; + + bool operator==(const MirageData &rhs) const { return data == rhs.data; } +}; + +class MirageProtocol : public RemoteProtocol { + public: + void encode(RemoteTransmitData *dst, const MirageData &data) override; + optional decode(RemoteReceiveData src) override; + void dump(const MirageData &data) override; + + protected: + void encode_byte_(RemoteTransmitData *dst, uint8_t item); +}; + +DECLARE_REMOTE_PROTOCOL(Mirage) + +template class MirageAction : public RemoteTransmitterActionBase { + public: + TEMPLATABLE_VALUE(std::vector, code) + + void encode(RemoteTransmitData *dst, Ts... x) override { + MirageData data{}; + data.data = this->code_.value(x...); + MirageProtocol().encode(dst, data); + } +}; + +} // namespace remote_base +} // namespace esphome diff --git a/tests/components/remote_receiver/esp32-common.yaml b/tests/components/remote_receiver/esp32-common.yaml index 0e71143fc3..c2b5a2cf19 100644 --- a/tests/components/remote_receiver/esp32-common.yaml +++ b/tests/components/remote_receiver/esp32-common.yaml @@ -143,6 +143,10 @@ remote_receiver: - logger.log: format: "on_toshiba_ac: %llu %llu" args: ["x.rc_code_1", "x.rc_code_2"] + on_mirage: + then: + - lambda: |- + ESP_LOGD("mirage", "Mirage data: %s", format_hex(x.data).c_str()); binary_sensor: - platform: remote_receiver diff --git a/tests/components/remote_receiver/test.esp8266.yaml b/tests/components/remote_receiver/test.esp8266.yaml index e96f031e90..27d36d4a16 100644 --- a/tests/components/remote_receiver/test.esp8266.yaml +++ b/tests/components/remote_receiver/test.esp8266.yaml @@ -142,6 +142,10 @@ remote_receiver: - logger.log: format: "on_toshiba_ac: %llu %llu" args: ["x.rc_code_1", "x.rc_code_2"] + on_mirage: + then: + - lambda: |- + ESP_LOGD("mirage", "Mirage data: %s", format_hex(x.data).c_str()); binary_sensor: - platform: remote_receiver diff --git a/tests/components/remote_transmitter/common-buttons.yaml b/tests/components/remote_transmitter/common-buttons.yaml index 27683b387f..e727017e85 100644 --- a/tests/components/remote_transmitter/common-buttons.yaml +++ b/tests/components/remote_transmitter/common-buttons.yaml @@ -176,6 +176,11 @@ button: 0x00, 0x05, ] + - platform: template + name: Mirage + on_press: + remote_transmitter.transmit_mirage: + code: [0x56, 0x77, 0x00, 0x00, 0x22, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] - platform: template name: Dooya on_press: From 2921831b55b327d1670ee92b8b33163867fa7434 Mon Sep 17 00:00:00 2001 From: shxshxshxshx Date: Thu, 16 May 2024 01:37:53 +0200 Subject: [PATCH 1450/2101] WPA2 Enterprise - Explicitly set TTLS Phase 2 (#6436) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/wifi/__init__.py | 13 +++++++++++++ esphome/components/wifi/wifi_component.cpp | 15 +++++++++++++++ esphome/components/wifi/wifi_component.h | 8 ++++++++ .../components/wifi/wifi_component_esp_idf.cpp | 5 +++++ esphome/const.py | 1 + 5 files changed, 42 insertions(+) diff --git a/esphome/components/wifi/__init__.py b/esphome/components/wifi/__init__.py index e0a17e9a2a..3b9e00956f 100644 --- a/esphome/components/wifi/__init__.py +++ b/esphome/components/wifi/__init__.py @@ -33,6 +33,7 @@ from esphome.const import ( CONF_KEY, CONF_USERNAME, CONF_EAP, + CONF_TTLS_PHASE_2, CONF_ON_CONNECT, CONF_ON_DISCONNECT, ) @@ -98,6 +99,14 @@ STA_MANUAL_IP_SCHEMA = AP_MANUAL_IP_SCHEMA.extend( } ) +TTLS_PHASE_2 = { + "pap": cg.global_ns.ESP_EAP_TTLS_PHASE2_PAP, + "chap": cg.global_ns.ESP_EAP_TTLS_PHASE2_CHAP, + "mschap": cg.global_ns.ESP_EAP_TTLS_PHASE2_MSCHAP, + "mschapv2": cg.global_ns.ESP_EAP_TTLS_PHASE2_MSCHAPV2, + "eap": cg.global_ns.ESP_EAP_TTLS_PHASE2_EAP, +} + EAP_AUTH_SCHEMA = cv.All( cv.Schema( { @@ -105,6 +114,9 @@ EAP_AUTH_SCHEMA = cv.All( cv.Optional(CONF_USERNAME): cv.string_strict, cv.Optional(CONF_PASSWORD): cv.string_strict, cv.Optional(CONF_CERTIFICATE_AUTHORITY): wpa2_eap.validate_certificate, + cv.Optional(CONF_TTLS_PHASE_2): cv.All( + cv.enum(TTLS_PHASE_2), cv.only_with_esp_idf + ), cv.Inclusive( CONF_CERTIFICATE, "certificate_and_key" ): wpa2_eap.validate_certificate, @@ -338,6 +350,7 @@ def eap_auth(config): ("ca_cert", ca_cert), ("client_cert", client_cert), ("client_key", key), + ("ttls_phase_2", config.get(CONF_TTLS_PHASE_2, TTLS_PHASE_2["mschapv2"])), ) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 7e245d3e86..f4a44b03a4 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -1,5 +1,10 @@ #include "wifi_component.h" #include +#include + +#ifdef USE_ESP_IDF +#include +#endif #if defined(USE_ESP32) || defined(USE_ESP_IDF) #include @@ -318,6 +323,16 @@ void WiFiComponent::start_connecting(const WiFiAP &ap, bool two) { ESP_LOGV(TAG, " Identity: " LOG_SECRET("'%s'"), eap_config.identity.c_str()); ESP_LOGV(TAG, " Username: " LOG_SECRET("'%s'"), eap_config.username.c_str()); ESP_LOGV(TAG, " Password: " LOG_SECRET("'%s'"), eap_config.password.c_str()); +#ifdef USE_ESP_IDF +#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE + std::map phase2types = {{ESP_EAP_TTLS_PHASE2_PAP, "pap"}, + {ESP_EAP_TTLS_PHASE2_CHAP, "chap"}, + {ESP_EAP_TTLS_PHASE2_MSCHAP, "mschap"}, + {ESP_EAP_TTLS_PHASE2_MSCHAPV2, "mschapv2"}, + {ESP_EAP_TTLS_PHASE2_EAP, "eap"}}; + ESP_LOGV(TAG, " TTLS Phase 2: " LOG_SECRET("'%s'"), phase2types[eap_config.ttls_phase_2].c_str()); +#endif +#endif bool ca_cert_present = eap_config.ca_cert != nullptr && strlen(eap_config.ca_cert); bool client_cert_present = eap_config.client_cert != nullptr && strlen(eap_config.client_cert); bool client_key_present = eap_config.client_key != nullptr && strlen(eap_config.client_key); diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index 133fa2970c..0b077819ae 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -19,6 +19,10 @@ #include #endif +#if defined(USE_ESP_IDF) && defined(USE_WIFI_WPA2_EAP) +#include +#endif + #ifdef USE_ESP8266 #include #include @@ -102,6 +106,10 @@ struct EAPAuth { // used for EAP-TLS const char *client_cert; const char *client_key; +// used for EAP-TTLS +#ifdef USE_ESP_IDF + esp_eap_ttls_phase2_types ttls_phase_2; +#endif }; #endif // USE_WIFI_WPA2_EAP diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index ebb2fb92ea..5489a5d249 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -396,6 +396,11 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) { if (err != ESP_OK) { ESP_LOGV(TAG, "esp_wifi_sta_wpa2_ent_set_password failed! %d", err); } + // set TTLS Phase 2, defaults to MSCHAPV2 + err = esp_wifi_sta_wpa2_ent_set_ttls_phase2_method(eap.ttls_phase_2); + if (err != ESP_OK) { + ESP_LOGV(TAG, "esp_wifi_sta_wpa2_ent_set_ttls_phase2_method failed! %d", err); + } } err = esp_wifi_sta_wpa2_ent_enable(); if (err != ESP_OK) { diff --git a/esphome/const.py b/esphome/const.py index eb48080040..7745cca321 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -856,6 +856,7 @@ CONF_TRANSFORM = "transform" CONF_TRANSITION_LENGTH = "transition_length" CONF_TRIGGER_ID = "trigger_id" CONF_TRIGGER_PIN = "trigger_pin" +CONF_TTLS_PHASE_2 = "ttls_phase_2" CONF_TUNE_ANTENNA = "tune_antenna" CONF_TURN_OFF_ACTION = "turn_off_action" CONF_TURN_ON_ACTION = "turn_on_action" From 7d804bf90f646b669f5d46df7e1d9edca2988109 Mon Sep 17 00:00:00 2001 From: Shawn Wilsher <656602+sdwilsh@users.noreply.github.com> Date: Wed, 15 May 2024 16:39:57 -0700 Subject: [PATCH 1451/2101] Fix Prometheus Output to Match Spec (#6032) --- .../prometheus/prometheus_handler.cpp | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/esphome/components/prometheus/prometheus_handler.cpp b/esphome/components/prometheus/prometheus_handler.cpp index 68bca95a21..09913bd713 100644 --- a/esphome/components/prometheus/prometheus_handler.cpp +++ b/esphome/components/prometheus/prometheus_handler.cpp @@ -65,8 +65,8 @@ std::string PrometheusHandler::relabel_name_(EntityBase *obj) { // Type-specific implementation #ifdef USE_SENSOR void PrometheusHandler::sensor_type_(AsyncResponseStream *stream) { - stream->print(F("#TYPE esphome_sensor_value GAUGE\n")); - stream->print(F("#TYPE esphome_sensor_failed GAUGE\n")); + stream->print(F("#TYPE esphome_sensor_value gauge\n")); + stream->print(F("#TYPE esphome_sensor_failed gauge\n")); } void PrometheusHandler::sensor_row_(AsyncResponseStream *stream, sensor::Sensor *obj) { if (obj->is_internal() && !this->include_internal_) @@ -102,8 +102,8 @@ void PrometheusHandler::sensor_row_(AsyncResponseStream *stream, sensor::Sensor // Type-specific implementation #ifdef USE_BINARY_SENSOR void PrometheusHandler::binary_sensor_type_(AsyncResponseStream *stream) { - stream->print(F("#TYPE esphome_binary_sensor_value GAUGE\n")); - stream->print(F("#TYPE esphome_binary_sensor_failed GAUGE\n")); + stream->print(F("#TYPE esphome_binary_sensor_value gauge\n")); + stream->print(F("#TYPE esphome_binary_sensor_failed gauge\n")); } void PrometheusHandler::binary_sensor_row_(AsyncResponseStream *stream, binary_sensor::BinarySensor *obj) { if (obj->is_internal() && !this->include_internal_) @@ -136,10 +136,10 @@ void PrometheusHandler::binary_sensor_row_(AsyncResponseStream *stream, binary_s #ifdef USE_FAN void PrometheusHandler::fan_type_(AsyncResponseStream *stream) { - stream->print(F("#TYPE esphome_fan_value GAUGE\n")); - stream->print(F("#TYPE esphome_fan_failed GAUGE\n")); - stream->print(F("#TYPE esphome_fan_speed GAUGE\n")); - stream->print(F("#TYPE esphome_fan_oscillation GAUGE\n")); + stream->print(F("#TYPE esphome_fan_value gauge\n")); + stream->print(F("#TYPE esphome_fan_failed gauge\n")); + stream->print(F("#TYPE esphome_fan_speed gauge\n")); + stream->print(F("#TYPE esphome_fan_oscillation gauge\n")); } void PrometheusHandler::fan_row_(AsyncResponseStream *stream, fan::Fan *obj) { if (obj->is_internal() && !this->include_internal_) @@ -182,9 +182,9 @@ void PrometheusHandler::fan_row_(AsyncResponseStream *stream, fan::Fan *obj) { #ifdef USE_LIGHT void PrometheusHandler::light_type_(AsyncResponseStream *stream) { - stream->print(F("#TYPE esphome_light_state GAUGE\n")); - stream->print(F("#TYPE esphome_light_color GAUGE\n")); - stream->print(F("#TYPE esphome_light_effect_active GAUGE\n")); + stream->print(F("#TYPE esphome_light_state gauge\n")); + stream->print(F("#TYPE esphome_light_color gauge\n")); + stream->print(F("#TYPE esphome_light_effect_active gauge\n")); } void PrometheusHandler::light_row_(AsyncResponseStream *stream, light::LightState *obj) { if (obj->is_internal() && !this->include_internal_) @@ -259,8 +259,8 @@ void PrometheusHandler::light_row_(AsyncResponseStream *stream, light::LightStat #ifdef USE_COVER void PrometheusHandler::cover_type_(AsyncResponseStream *stream) { - stream->print(F("#TYPE esphome_cover_value GAUGE\n")); - stream->print(F("#TYPE esphome_cover_failed GAUGE\n")); + stream->print(F("#TYPE esphome_cover_value gauge\n")); + stream->print(F("#TYPE esphome_cover_failed gauge\n")); } void PrometheusHandler::cover_row_(AsyncResponseStream *stream, cover::Cover *obj) { if (obj->is_internal() && !this->include_internal_) @@ -302,8 +302,8 @@ void PrometheusHandler::cover_row_(AsyncResponseStream *stream, cover::Cover *ob #ifdef USE_SWITCH void PrometheusHandler::switch_type_(AsyncResponseStream *stream) { - stream->print(F("#TYPE esphome_switch_value GAUGE\n")); - stream->print(F("#TYPE esphome_switch_failed GAUGE\n")); + stream->print(F("#TYPE esphome_switch_value gauge\n")); + stream->print(F("#TYPE esphome_switch_failed gauge\n")); } void PrometheusHandler::switch_row_(AsyncResponseStream *stream, switch_::Switch *obj) { if (obj->is_internal() && !this->include_internal_) @@ -326,8 +326,8 @@ void PrometheusHandler::switch_row_(AsyncResponseStream *stream, switch_::Switch #ifdef USE_LOCK void PrometheusHandler::lock_type_(AsyncResponseStream *stream) { - stream->print(F("#TYPE esphome_lock_value GAUGE\n")); - stream->print(F("#TYPE esphome_lock_failed GAUGE\n")); + stream->print(F("#TYPE esphome_lock_value gauge\n")); + stream->print(F("#TYPE esphome_lock_failed gauge\n")); } void PrometheusHandler::lock_row_(AsyncResponseStream *stream, lock::Lock *obj) { if (obj->is_internal() && !this->include_internal_) From f0ec900e4841a32023491f8482af3c4a07432adb Mon Sep 17 00:00:00 2001 From: Andrew McFague <144809+amcfague@users.noreply.github.com> Date: Wed, 15 May 2024 16:49:04 -0700 Subject: [PATCH 1452/2101] Skip gpio validation (#5615) --- esphome/components/esp32/gpio.py | 40 ++++++++++++++++++++-- esphome/components/esp32_touch/__init__.py | 2 +- esphome/const.py | 1 + esphome/pins.py | 2 ++ tests/test8.yaml | 13 +++++++ 5 files changed, 54 insertions(+), 4 deletions(-) diff --git a/esphome/components/esp32/gpio.py b/esphome/components/esp32/gpio.py index 16f99f2b15..0d9cb5daf0 100644 --- a/esphome/components/esp32/gpio.py +++ b/esphome/components/esp32/gpio.py @@ -1,5 +1,6 @@ from dataclasses import dataclass from typing import Any +import logging from esphome.const import ( CONF_ID, @@ -8,6 +9,7 @@ from esphome.const import ( CONF_NUMBER, CONF_OPEN_DRAIN, CONF_OUTPUT, + CONF_IGNORE_PIN_VALIDATION_ERROR, CONF_IGNORE_STRAPPING_WARNING, PLATFORM_ESP32, ) @@ -42,6 +44,9 @@ from .gpio_esp32_h2 import esp32_h2_validate_gpio_pin, esp32_h2_validate_support ESP32InternalGPIOPin = esp32_ns.class_("ESP32InternalGPIOPin", cg.InternalGPIOPin) +_LOGGER = logging.getLogger(__name__) + + def _lookup_pin(value): board = CORE.data[KEY_ESP32][KEY_BOARD] board_pins = boards.ESP32_BOARD_PINS.get(board, {}) @@ -111,7 +116,7 @@ _esp32_validations = { } -def validate_gpio_pin(value): +def gpio_pin_number_validator(value): value = _translate_pin(value) board = CORE.data[KEY_ESP32][KEY_BOARD] board_pins = boards.ESP32_BOARD_PINS.get(board, {}) @@ -127,7 +132,33 @@ def validate_gpio_pin(value): if variant not in _esp32_validations: raise cv.Invalid(f"Unsupported ESP32 variant {variant}") - return _esp32_validations[variant].pin_validation(value) + return value + + +def validate_gpio_pin(pin): + variant = CORE.data[KEY_ESP32][KEY_VARIANT] + if variant not in _esp32_validations: + raise cv.Invalid(f"Unsupported ESP32 variant {variant}") + + ignore_pin_validation_warning = pin[CONF_IGNORE_PIN_VALIDATION_ERROR] + try: + pin[CONF_NUMBER] = _esp32_validations[variant].pin_validation(pin[CONF_NUMBER]) + except cv.Invalid as exc: + if not ignore_pin_validation_warning: + raise + + _LOGGER.warning( + "Ignoring validation error on pin %d; error: %s", + pin[CONF_NUMBER], + exc, + ) + else: + # Throw an exception if used for a pin that would not have resulted + # in a validation error anyway! + if ignore_pin_validation_warning: + raise cv.Invalid(f"GPIO{pin[CONF_NUMBER]} is not a reserved pin") + + return pin def validate_supports(value): @@ -158,9 +189,11 @@ DRIVE_STRENGTHS = { gpio_num_t = cg.global_ns.enum("gpio_num_t") CONF_DRIVE_STRENGTH = "drive_strength" + ESP32_PIN_SCHEMA = cv.All( - pins.gpio_base_schema(ESP32InternalGPIOPin, validate_gpio_pin).extend( + pins.gpio_base_schema(ESP32InternalGPIOPin, gpio_pin_number_validator).extend( { + cv.Optional(CONF_IGNORE_PIN_VALIDATION_ERROR, default=False): cv.boolean, cv.Optional(CONF_IGNORE_STRAPPING_WARNING, default=False): cv.boolean, cv.Optional(CONF_DRIVE_STRENGTH, default="20mA"): cv.All( cv.float_with_unit("current", "mA", optional_unit=True), @@ -168,6 +201,7 @@ ESP32_PIN_SCHEMA = cv.All( ), } ), + validate_gpio_pin, validate_supports, ) diff --git a/esphome/components/esp32_touch/__init__.py b/esphome/components/esp32_touch/__init__.py index 0180d18104..fc7bf200e4 100644 --- a/esphome/components/esp32_touch/__init__.py +++ b/esphome/components/esp32_touch/__init__.py @@ -150,7 +150,7 @@ TOUCH_PAD_WATERPROOF_SHIELD_DRIVER = { def validate_touch_pad(value): - value = gpio.validate_gpio_pin(value) + value = gpio.gpio_pin_number_validator(value) variant = get_esp32_variant() if variant not in TOUCH_PADS: raise cv.Invalid(f"ESP32 variant {variant} does not support touch pads.") diff --git a/esphome/const.py b/esphome/const.py index 7745cca321..616b686052 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -367,6 +367,7 @@ CONF_IDLE_TIME = "idle_time" CONF_IF = "if" CONF_IGNORE_EFUSE_MAC_CRC = "ignore_efuse_mac_crc" CONF_IGNORE_OUT_OF_RANGE = "ignore_out_of_range" +CONF_IGNORE_PIN_VALIDATION_ERROR = "ignore_pin_validation_error" CONF_IGNORE_STRAPPING_WARNING = "ignore_strapping_warning" CONF_IIR_FILTER = "iir_filter" CONF_ILLUMINANCE = "illuminance" diff --git a/esphome/pins.py b/esphome/pins.py index d02ad357a0..5ccb696738 100644 --- a/esphome/pins.py +++ b/esphome/pins.py @@ -327,6 +327,8 @@ def gpio_base_schema( cv.Optional(CONF_MODE, default={}): cv.All(mode_dict, mode_validator), } ) + if invertable: return schema.extend({cv.Optional(CONF_INVERTED, default=False): cv.boolean}) + return schema diff --git a/tests/test8.yaml b/tests/test8.yaml index 5a8ae77468..fcc93c6154 100644 --- a/tests/test8.yaml +++ b/tests/test8.yaml @@ -38,6 +38,11 @@ light: id: rgb_led name: "RGB LED" data_rate: 8MHz + - platform: binary + name: "Red Info Light" + output: board_info_ed + entity_category: diagnostic + restore_mode: ALWAYS_OFF spi: id: spi_id_1 @@ -73,6 +78,14 @@ i2c: scl: GPIO18 sda: GPIO8 +output: + - platform: gpio + id: board_info_ed + pin: + # This pin is reserved on the ESP32S3! + number: 26 + ignore_pin_validation_error: true + touchscreen: - platform: tt21100 display: displ8 From f2ef06d8b538deee919efbc396040eee502fd22c Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 16 May 2024 13:19:37 +1200 Subject: [PATCH 1453/2101] [core] Migrate to pyproject.toml (#6737) --- setup.cfg => .flake8 | 51 +++++++++------------------ docker/Dockerfile | 4 +-- pyproject.toml | 53 ++++++++++++++++++++++++++++ script/setup | 6 ++-- setup.py | 82 -------------------------------------------- 5 files changed, 74 insertions(+), 122 deletions(-) rename setup.cfg => .flake8 (56%) delete mode 100755 setup.py diff --git a/setup.cfg b/.flake8 similarity index 56% rename from setup.cfg rename to .flake8 index b3cfbba6a1..2724da06b6 100644 --- a/setup.cfg +++ b/.flake8 @@ -1,19 +1,3 @@ -[metadata] -license = MIT -license_file = LICENSE -platforms = any -description = Make creating custom firmwares for ESP32/ESP8266 super easy. -long_description = file: README.md -keywords = home, automation -classifier = - Environment :: Console - Intended Audience :: Developers - Intended Audience :: End Users/Desktop - License :: OSI Approved :: MIT License - Programming Language :: C++ - Programming Language :: Python :: 3 - Topic :: Home Automation - [flake8] max-line-length = 120 # Following 4 for black compatibility @@ -37,25 +21,22 @@ max-line-length = 120 # D401 First line should be in imperative mood ignore = - E501, - W503, - E203, - D202, + E501, + W503, + E203, + D202, - D100, - D101, - D102, - D103, - D104, - D105, - D107, - D200, - D205, - D209, - D400, - D401, + D100, + D101, + D102, + D103, + D104, + D105, + D107, + D200, + D205, + D209, + D400, + D401, exclude = api_pb2.py - -[bdist_wheel] -universal = 1 diff --git a/docker/Dockerfile b/docker/Dockerfile index 5d9ece16a1..3c661b7e1c 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -110,7 +110,7 @@ RUN if [ "$TARGETARCH$TARGETVARIANT" = "armv7" ]; then \ export PIP_EXTRA_INDEX_URL="https://www.piwheels.org/simple"; \ fi; \ pip3 install \ - --break-system-packages --no-cache-dir --no-use-pep517 -e /esphome + --break-system-packages --no-cache-dir -e /esphome # Settings for dashboard ENV USERNAME="" PASSWORD="" @@ -160,7 +160,7 @@ RUN if [ "$TARGETARCH$TARGETVARIANT" = "armv7" ]; then \ export PIP_EXTRA_INDEX_URL="https://www.piwheels.org/simple"; \ fi; \ pip3 install \ - --break-system-packages --no-cache-dir --no-use-pep517 -e /esphome + --break-system-packages --no-cache-dir -e /esphome # Labels LABEL \ diff --git a/pyproject.toml b/pyproject.toml index a49abb7b3d..aa524e2d62 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,56 @@ +[build-system] +requires = ["setuptools==69.2.0", "wheel~=0.43.0"] +build-backend = "setuptools.build_meta" + +[project] +name = "esphome" +license = {text = "MIT"} +description = "Make creating custom firmwares for ESP32/ESP8266 super easy." +readme = "README.md" +authors = [ + {name = "The ESPHome Authors", email = "esphome@nabucasa.com"} +] +keywords = ["home", "automation"] +classifiers = [ + "Environment :: Console", + "Intended Audience :: Developers", + "Intended Audience :: End Users/Desktop", + "License :: OSI Approved :: MIT License", + "Programming Language :: C++", + "Programming Language :: Python :: 3", + "Topic :: Home Automation", +] +requires-python = ">=3.9.0" + +dynamic = ["dependencies", "optional-dependencies", "version"] + +[project.urls] +"Documentation" = "https://esphome.io" +"Source Code" = "https://github.com/esphome/esphome" +"Bug Tracker" = "https://github.com/esphome/issues/issues" +"Feature Request Tracker" = "https://github.com/esphome/feature-requests/issues" +"Discord" = "https://discord.gg/KhAMKrd" +"Forum" = "https://community.home-assistant.io/c/esphome" +"Twitter" = "https://twitter.com/esphome_" + +[project.scripts] +esphome = "esphome.__main__:main" + +[tool.setuptools] +platforms = ["any"] +zip-safe = false +include-package-data = true + +[tool.setuptools.dynamic] +dependencies = {file = ["requirements.txt"]} +optional-dependencies.dev = { file = ["requirements_dev.txt"] } +optional-dependencies.test = { file = ["requirements_test.txt"] } +optional-dependencies.displays = { file = ["requirements_optional.txt"] } +version = {attr = "esphome.const.__version__"} + +[tool.setuptools.packages.find] +include = ["esphome*"] + [tool.black] target-version = ["py39", "py310"] exclude = 'generated' diff --git a/script/setup b/script/setup index f286b4672a..71573a9352 100755 --- a/script/setup +++ b/script/setup @@ -10,17 +10,17 @@ if [ ! -n "$DEVCONTAINER" ] && [ ! -n "$VIRTUAL_ENV" ] && [ ! "$ESPHOME_NO_VENV" if [ -f venv/Scripts/activate ]; then location="venv/Scripts/activate" fi - source $location; + source $location fi # Avoid unsafe git error when running inside devcontainer -if [ -n "$DEVCONTAINER" ];then +if [ -n "$DEVCONTAINER" ]; then git config --global --add safe.directory "$PWD" fi pip3 install -r requirements.txt -r requirements_optional.txt -r requirements_test.txt -r requirements_dev.txt pip3 install setuptools wheel -pip3 install --no-use-pep517 -e . +pip3 install -e --config-settings editable_mode=compat ".[dev,test,displays]" pre-commit install diff --git a/setup.py b/setup.py deleted file mode 100755 index 95453960ff..0000000000 --- a/setup.py +++ /dev/null @@ -1,82 +0,0 @@ -#!/usr/bin/env python3 -"""esphome setup script.""" -import os - -from setuptools import setup, find_packages - -from esphome import const - -PROJECT_NAME = "esphome" -PROJECT_PACKAGE_NAME = "esphome" -PROJECT_LICENSE = "MIT" -PROJECT_AUTHOR = "ESPHome" -PROJECT_COPYRIGHT = "2019, ESPHome" -PROJECT_URL = "https://esphome.io/" -PROJECT_EMAIL = "esphome@nabucasa.com" - -PROJECT_GITHUB_USERNAME = "esphome" -PROJECT_GITHUB_REPOSITORY = "esphome" - -PYPI_URL = f"https://pypi.python.org/pypi/{PROJECT_PACKAGE_NAME}" -GITHUB_PATH = f"{PROJECT_GITHUB_USERNAME}/{PROJECT_GITHUB_REPOSITORY}" -GITHUB_URL = f"https://github.com/{GITHUB_PATH}" - -DOWNLOAD_URL = f"{GITHUB_URL}/archive/{const.__version__}.zip" - -here = os.path.abspath(os.path.dirname(__file__)) - -with open(os.path.join(here, "requirements.txt")) as requirements_txt: - REQUIRES = requirements_txt.read().splitlines() - -with open(os.path.join(here, "README.md")) as readme: - LONG_DESCRIPTION = readme.read() - -# If you have problems importing platformio and esptool as modules you can set -# $ESPHOME_USE_SUBPROCESS to make ESPHome call their executables instead. -# This means they have to be in your $PATH. -if "ESPHOME_USE_SUBPROCESS" in os.environ: - # Remove platformio and esptool from requirements - REQUIRES = [ - req - for req in REQUIRES - if not any(req.startswith(prefix) for prefix in ["platformio", "esptool"]) - ] - -CLASSIFIERS = [ - "Environment :: Console", - "Intended Audience :: Developers", - "Intended Audience :: End Users/Desktop", - "License :: OSI Approved :: MIT License", - "Programming Language :: C++", - "Programming Language :: Python :: 3", - "Topic :: Home Automation", -] - -setup( - name=PROJECT_PACKAGE_NAME, - version=const.__version__, - license=PROJECT_LICENSE, - url=GITHUB_URL, - project_urls={ - "Bug Tracker": "https://github.com/esphome/issues/issues", - "Feature Request Tracker": "https://github.com/esphome/feature-requests/issues", - "Source Code": "https://github.com/esphome/esphome", - "Documentation": "https://esphome.io", - "Twitter": "https://twitter.com/esphome_", - }, - download_url=DOWNLOAD_URL, - author=PROJECT_AUTHOR, - author_email=PROJECT_EMAIL, - description="Make creating custom firmwares for ESP32/ESP8266 super easy.", - long_description=LONG_DESCRIPTION, - long_description_content_type="text/markdown", - include_package_data=True, - zip_safe=False, - platforms="any", - test_suite="tests", - python_requires=">=3.9.0", - install_requires=REQUIRES, - keywords=["home", "automation"], - entry_points={"console_scripts": ["esphome = esphome.__main__:main"]}, - packages=find_packages(include="esphome.*"), -) From bf48ccaf22a32e11e9974cf888bed1e424de8822 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 16 May 2024 13:20:12 +1200 Subject: [PATCH 1454/2101] [core] Move pytest config into pyproject.toml (#6740) --- pyproject.toml | 9 +++++++++ pytest.ini | 4 ---- 2 files changed, 9 insertions(+), 4 deletions(-) delete mode 100644 pytest.ini diff --git a/pyproject.toml b/pyproject.toml index aa524e2d62..4406165433 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -54,3 +54,12 @@ include = ["esphome*"] [tool.black] target-version = ["py39", "py310"] exclude = 'generated' + +[tool.pytest.ini_options] +testpaths = [ + "tests", +] +addopts = [ + "--cov=esphome", + "--cov-branch", +] diff --git a/pytest.ini b/pytest.ini deleted file mode 100644 index a91a2ea200..0000000000 --- a/pytest.ini +++ /dev/null @@ -1,4 +0,0 @@ -[pytest] -addopts = - --cov=esphome - --cov-branch From a27c05483cf3d20f98ea8db392dde5b277ff2337 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 16 May 2024 13:47:36 +1200 Subject: [PATCH 1455/2101] [core] Move pylint config into pyproject.toml (#6739) --- pylintrc | 30 ------------------------------ pyproject.toml | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 30 deletions(-) delete mode 100644 pylintrc diff --git a/pylintrc b/pylintrc deleted file mode 100644 index b70e5c7da9..0000000000 --- a/pylintrc +++ /dev/null @@ -1,30 +0,0 @@ -[MASTER] -reports=no -ignore=api_pb2.py - -disable= - format, - missing-docstring, - fixme, - unused-argument, - global-statement, - too-few-public-methods, - too-many-lines, - too-many-locals, - too-many-ancestors, - too-many-branches, - too-many-statements, - too-many-arguments, - too-many-return-statements, - too-many-instance-attributes, - duplicate-code, - invalid-name, - cyclic-import, - redefined-builtin, - undefined-loop-variable, - useless-object-inheritance, - stop-iteration-return, - import-outside-toplevel, - # Broken - unsupported-membership-test, - unsubscriptable-object, diff --git a/pyproject.toml b/pyproject.toml index 4406165433..fe558f695f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -63,3 +63,45 @@ addopts = [ "--cov=esphome", "--cov-branch", ] + +[tool.pylint.MAIN] +py-version = "3.9" +ignore = [ + "api_pb2.py", +] +persistent = false + +[tool.pylint.REPORTS] +score = false + +[tool.pylint."MESSAGES CONTROL"] +disable = [ + "format", + "missing-docstring", + "fixme", + "unused-argument", + "global-statement", + "too-few-public-methods", + "too-many-lines", + "too-many-locals", + "too-many-ancestors", + "too-many-branches", + "too-many-statements", + "too-many-arguments", + "too-many-return-statements", + "too-many-instance-attributes", + "duplicate-code", + "invalid-name", + "cyclic-import", + "redefined-builtin", + "undefined-loop-variable", + "useless-object-inheritance", + "stop-iteration-return", + "import-outside-toplevel", + # Broken + "unsupported-membership-test", + "unsubscriptable-object", +] + +[tool.pylint.FORMAT] +expected-line-ending-format = "LF" From f91c31f093142d11225e1ca3d4fa79817a719490 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 16 May 2024 13:47:56 +1200 Subject: [PATCH 1456/2101] [core] Fix running pylint via pre-commit from GUI apps (#6754) --- .pre-commit-config.yaml | 4 ++-- script/run-in-env.sh | 13 +++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) create mode 100755 script/run-in-env.sh diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ce226846e3..418716e4f4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -44,6 +44,6 @@ repos: hooks: - id: pylint name: pylint - entry: pylint - language: system + entry: script/run-in-env.sh pylint + language: script types: [python] diff --git a/script/run-in-env.sh b/script/run-in-env.sh new file mode 100755 index 0000000000..2e05fe1d17 --- /dev/null +++ b/script/run-in-env.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env sh +set -eu + +my_path=$(git rev-parse --show-toplevel) + +for venv in venv .venv .; do + if [ -f "${my_path}/${venv}/bin/activate" ]; then + . "${my_path}/${venv}/bin/activate" + break + fi +done + +exec "$@" From f46c499c4e4598b95d24f546a2d2cbaa13206850 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Wed, 15 May 2024 21:01:09 -0500 Subject: [PATCH 1457/2101] Separate `OTABackend` from OTA component (#6459) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/__main__.py | 25 +- .../esp32_ble_tracker/esp32_ble_tracker.cpp | 13 +- esphome/components/esphome/ota/__init__.py | 72 ++++++ .../ota/ota_esphome.cpp} | 215 ++++++++---------- .../ota/ota_esphome.h} | 62 +---- esphome/components/ota/__init__.py | 106 ++++----- esphome/components/ota/automation.h | 19 +- esphome/components/ota/ota_backend.cpp | 20 ++ esphome/components/ota/ota_backend.h | 79 ++++++- .../ota/ota_backend_arduino_esp32.cpp | 5 +- .../ota/ota_backend_arduino_esp32.h | 6 +- .../ota/ota_backend_arduino_esp8266.cpp | 9 +- .../ota/ota_backend_arduino_esp8266.h | 5 +- .../ota/ota_backend_arduino_libretiny.cpp | 9 +- .../ota/ota_backend_arduino_libretiny.h | 5 +- .../ota/ota_backend_arduino_rp2040.cpp | 9 +- .../ota/ota_backend_arduino_rp2040.h | 7 +- .../components/ota/ota_backend_esp_idf.cpp | 13 +- esphome/components/ota/ota_backend_esp_idf.h | 8 +- .../components/safe_mode/button/__init__.py | 16 +- .../safe_mode/button/safe_mode_button.cpp | 2 +- .../safe_mode/button/safe_mode_button.h | 8 +- .../components/safe_mode/switch/__init__.py | 14 +- .../safe_mode/switch/safe_mode_switch.cpp | 4 +- .../safe_mode/switch/safe_mode_switch.h | 8 +- esphome/cpp_helpers.py | 21 +- esphome/wizard.py | 5 +- tests/components/ota/common.yaml | 51 +++-- tests/components/safe_mode/common.yaml | 2 + tests/dummy_main.cpp | 4 +- tests/test1.yaml | 47 ++-- tests/test11.5.yaml | 1 + tests/test2.yaml | 7 +- tests/test3.1.yaml | 3 +- tests/test3.yaml | 7 +- tests/test4.yaml | 5 +- tests/test5.yaml | 1 + tests/test6.yaml | 1 + tests/test9.1.yaml | 1 + tests/test9.yaml | 1 + 40 files changed, 505 insertions(+), 391 deletions(-) create mode 100644 esphome/components/esphome/ota/__init__.py rename esphome/components/{ota/ota_component.cpp => esphome/ota/ota_esphome.cpp} (66%) rename esphome/components/{ota/ota_component.h => esphome/ota/ota_esphome.h} (50%) create mode 100644 esphome/components/ota/ota_backend.cpp diff --git a/esphome/__main__.py b/esphome/__main__.py index daf74eebb0..9930119c86 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -18,22 +18,23 @@ from esphome.const import ( CONF_BAUD_RATE, CONF_BROKER, CONF_DEASSERT_RTS_DTR, + CONF_DISABLED, + CONF_ESPHOME, CONF_LOGGER, + CONF_MDNS, + CONF_MQTT, CONF_NAME, CONF_OTA, - CONF_MQTT, - CONF_MDNS, - CONF_DISABLED, CONF_PASSWORD, - CONF_PORT, - CONF_ESPHOME, + CONF_PLATFORM, CONF_PLATFORMIO_OPTIONS, + CONF_PORT, CONF_SUBSTITUTIONS, PLATFORM_BK72XX, - PLATFORM_RTL87XX, PLATFORM_ESP32, PLATFORM_ESP8266, PLATFORM_RP2040, + PLATFORM_RTL87XX, SECRETS_FILES, ) from esphome.core import CORE, EsphomeError, coroutine @@ -330,15 +331,19 @@ def upload_program(config, args, host): return 1 # Unknown target platform - if CONF_OTA not in config: + ota_conf = {} + for ota_item in config.get(CONF_OTA, []): + if ota_item[CONF_PLATFORM] == CONF_ESPHOME: + ota_conf = ota_item + break + + if not ota_conf: raise EsphomeError( - "Cannot upload Over the Air as the config does not include the ota: " - "component" + f"Cannot upload Over the Air as the {CONF_OTA} configuration is not present or does not include {CONF_PLATFORM}: {CONF_ESPHOME}" ) from esphome import espota2 - ota_conf = config[CONF_OTA] remote_port = ota_conf[CONF_PORT] password = ota_conf.get(CONF_PASSWORD, "") diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp index 4ae7929ded..d154d4e519 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp @@ -18,7 +18,7 @@ #include #ifdef USE_OTA -#include "esphome/components/ota/ota_component.h" +#include "esphome/components/ota/ota_backend.h" #endif #ifdef USE_ARDUINO @@ -61,11 +61,12 @@ void ESP32BLETracker::setup() { this->scanner_idle_ = true; #ifdef USE_OTA - ota::global_ota_component->add_on_state_callback([this](ota::OTAState state, float progress, uint8_t error) { - if (state == ota::OTA_STARTED) { - this->stop_scan(); - } - }); + ota::get_global_ota_callback()->add_on_state_callback( + [this](ota::OTAState state, float progress, uint8_t error, ota::OTAComponent *comp) { + if (state == ota::OTA_STARTED) { + this->stop_scan(); + } + }); #endif } diff --git a/esphome/components/esphome/ota/__init__.py b/esphome/components/esphome/ota/__init__.py new file mode 100644 index 0000000000..abe9323b53 --- /dev/null +++ b/esphome/components/esphome/ota/__init__.py @@ -0,0 +1,72 @@ +from esphome.cpp_generator import RawExpression +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components.ota import BASE_OTA_SCHEMA, ota_to_code, OTAComponent +from esphome.const import ( + CONF_ID, + CONF_NUM_ATTEMPTS, + CONF_OTA, + CONF_PASSWORD, + CONF_PORT, + CONF_REBOOT_TIMEOUT, + CONF_SAFE_MODE, + CONF_VERSION, + KEY_PAST_SAFE_MODE, +) +from esphome.core import CORE, coroutine_with_priority + + +CODEOWNERS = ["@esphome/core"] +AUTO_LOAD = ["md5", "socket"] +DEPENDENCIES = ["network"] + +esphome = cg.esphome_ns.namespace("esphome") +ESPHomeOTAComponent = esphome.class_("ESPHomeOTAComponent", OTAComponent) + + +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(ESPHomeOTAComponent), + cv.Optional(CONF_SAFE_MODE, default=True): cv.boolean, + cv.Optional(CONF_VERSION, default=2): cv.one_of(1, 2, int=True), + cv.SplitDefault( + CONF_PORT, + esp8266=8266, + esp32=3232, + rp2040=2040, + bk72xx=8892, + rtl87xx=8892, + ): cv.port, + cv.Optional(CONF_PASSWORD): cv.string, + cv.Optional( + CONF_REBOOT_TIMEOUT, default="5min" + ): cv.positive_time_period_milliseconds, + cv.Optional(CONF_NUM_ATTEMPTS, default="10"): cv.positive_not_null_int, + } + ) + .extend(BASE_OTA_SCHEMA) + .extend(cv.COMPONENT_SCHEMA) +) + + +@coroutine_with_priority(50.0) +async def to_code(config): + CORE.data[CONF_OTA] = {} + + var = cg.new_Pvariable(config[CONF_ID]) + await ota_to_code(var, config) + cg.add(var.set_port(config[CONF_PORT])) + if CONF_PASSWORD in config: + cg.add(var.set_auth_password(config[CONF_PASSWORD])) + cg.add_define("USE_OTA_PASSWORD") + cg.add_define("USE_OTA_VERSION", config[CONF_VERSION]) + + await cg.register_component(var, config) + + if config[CONF_SAFE_MODE]: + condition = var.should_enter_safe_mode( + config[CONF_NUM_ATTEMPTS], config[CONF_REBOOT_TIMEOUT] + ) + cg.add(RawExpression(f"if ({condition}) return")) + CORE.data[CONF_OTA][KEY_PAST_SAFE_MODE] = True diff --git a/esphome/components/ota/ota_component.cpp b/esphome/components/esphome/ota/ota_esphome.cpp similarity index 66% rename from esphome/components/ota/ota_component.cpp rename to esphome/components/esphome/ota/ota_esphome.cpp index 15af14ff1a..f2f1cfc6a8 100644 --- a/esphome/components/ota/ota_component.cpp +++ b/esphome/components/esphome/ota/ota_esphome.cpp @@ -1,55 +1,34 @@ -#include "ota_component.h" -#include "ota_backend.h" -#include "ota_backend_arduino_esp32.h" -#include "ota_backend_arduino_esp8266.h" -#include "ota_backend_arduino_rp2040.h" -#include "ota_backend_arduino_libretiny.h" -#include "ota_backend_esp_idf.h" +#include "ota_esphome.h" -#include "esphome/core/log.h" -#include "esphome/core/application.h" -#include "esphome/core/hal.h" -#include "esphome/core/util.h" #include "esphome/components/md5/md5.h" #include "esphome/components/network/util.h" +#include "esphome/components/ota/ota_backend.h" +#include "esphome/components/ota/ota_backend_arduino_esp32.h" +#include "esphome/components/ota/ota_backend_arduino_esp8266.h" +#include "esphome/components/ota/ota_backend_arduino_libretiny.h" +#include "esphome/components/ota/ota_backend_arduino_rp2040.h" +#include "esphome/components/ota/ota_backend_esp_idf.h" +#include "esphome/core/application.h" +#include "esphome/core/hal.h" +#include "esphome/core/log.h" +#include "esphome/core/util.h" #include #include namespace esphome { -namespace ota { -static const char *const TAG = "ota"; +static const char *const TAG = "esphome.ota"; static constexpr u_int16_t OTA_BLOCK_SIZE = 8192; -OTAComponent *global_ota_component = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) - -std::unique_ptr make_ota_backend() { -#ifdef USE_ARDUINO -#ifdef USE_ESP8266 - return make_unique(); -#endif // USE_ESP8266 -#ifdef USE_ESP32 - return make_unique(); -#endif // USE_ESP32 -#endif // USE_ARDUINO -#ifdef USE_ESP_IDF - return make_unique(); -#endif // USE_ESP_IDF -#ifdef USE_RP2040 - return make_unique(); -#endif // USE_RP2040 -#ifdef USE_LIBRETINY - return make_unique(); +void ESPHomeOTAComponent::setup() { +#ifdef USE_OTA_STATE_CALLBACK + ota::register_ota_platform(this); #endif -} -OTAComponent::OTAComponent() { global_ota_component = this; } - -void OTAComponent::setup() { server_ = socket::socket_ip(SOCK_STREAM, 0); if (server_ == nullptr) { - ESP_LOGW(TAG, "Could not create socket."); + ESP_LOGW(TAG, "Could not create socket"); this->mark_failed(); return; } @@ -88,41 +67,39 @@ void OTAComponent::setup() { this->mark_failed(); return; } - - this->dump_config(); } -void OTAComponent::dump_config() { - ESP_LOGCONFIG(TAG, "Over-The-Air Updates:"); +void ESPHomeOTAComponent::dump_config() { + ESP_LOGCONFIG(TAG, "Over-The-Air updates:"); ESP_LOGCONFIG(TAG, " Address: %s:%u", network::get_use_address().c_str(), this->port_); + ESP_LOGCONFIG(TAG, " Version: %d", USE_OTA_VERSION); #ifdef USE_OTA_PASSWORD if (!this->password_.empty()) { - ESP_LOGCONFIG(TAG, " Using Password."); + ESP_LOGCONFIG(TAG, " Password configured"); } #endif - ESP_LOGCONFIG(TAG, " OTA version: %d.", USE_OTA_VERSION); if (this->has_safe_mode_ && this->safe_mode_rtc_value_ > 1 && - this->safe_mode_rtc_value_ != esphome::ota::OTAComponent::ENTER_SAFE_MODE_MAGIC) { - ESP_LOGW(TAG, "Last Boot was an unhandled reset, will proceed to safe mode in %" PRIu32 " restarts", + this->safe_mode_rtc_value_ != ESPHomeOTAComponent::ENTER_SAFE_MODE_MAGIC) { + ESP_LOGW(TAG, "Last reset occurred too quickly; safe mode will be invoked in %" PRIu32 " restarts", this->safe_mode_num_attempts_ - this->safe_mode_rtc_value_); } } -void OTAComponent::loop() { +void ESPHomeOTAComponent::loop() { this->handle_(); if (this->has_safe_mode_ && (millis() - this->safe_mode_start_time_) > this->safe_mode_enable_time_) { this->has_safe_mode_ = false; // successful boot, reset counter - ESP_LOGI(TAG, "Boot seems successful, resetting boot loop counter."); + ESP_LOGI(TAG, "Boot seems successful; resetting boot loop counter"); this->clean_rtc(); } } static const uint8_t FEATURE_SUPPORTS_COMPRESSION = 0x01; -void OTAComponent::handle_() { - OTAResponseTypes error_code = OTA_RESPONSE_ERROR_UNKNOWN; +void ESPHomeOTAComponent::handle_() { + ota::OTAResponseTypes error_code = ota::OTA_RESPONSE_ERROR_UNKNOWN; bool update_started = false; size_t total = 0; uint32_t last_progress = 0; @@ -130,7 +107,7 @@ void OTAComponent::handle_() { char *sbuf = reinterpret_cast(buf); size_t ota_size; uint8_t ota_features; - std::unique_ptr backend; + std::unique_ptr backend; (void) ota_features; #if USE_OTA_VERSION == 2 size_t size_acknowledged = 0; @@ -147,54 +124,54 @@ void OTAComponent::handle_() { int enable = 1; int err = client_->setsockopt(IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(int)); if (err != 0) { - ESP_LOGW(TAG, "Socket could not enable tcp nodelay, errno: %d", errno); + ESP_LOGW(TAG, "Socket could not enable TCP nodelay, errno %d", errno); return; } - ESP_LOGD(TAG, "Starting OTA Update from %s...", this->client_->getpeername().c_str()); + ESP_LOGD(TAG, "Starting update from %s...", this->client_->getpeername().c_str()); this->status_set_warning(); #ifdef USE_OTA_STATE_CALLBACK - this->state_callback_.call(OTA_STARTED, 0.0f, 0); + this->state_callback_.call(ota::OTA_STARTED, 0.0f, 0); #endif if (!this->readall_(buf, 5)) { - ESP_LOGW(TAG, "Reading magic bytes failed!"); + ESP_LOGW(TAG, "Reading magic bytes failed"); goto error; // NOLINT(cppcoreguidelines-avoid-goto) } // 0x6C, 0x26, 0xF7, 0x5C, 0x45 if (buf[0] != 0x6C || buf[1] != 0x26 || buf[2] != 0xF7 || buf[3] != 0x5C || buf[4] != 0x45) { ESP_LOGW(TAG, "Magic bytes do not match! 0x%02X-0x%02X-0x%02X-0x%02X-0x%02X", buf[0], buf[1], buf[2], buf[3], buf[4]); - error_code = OTA_RESPONSE_ERROR_MAGIC; + error_code = ota::OTA_RESPONSE_ERROR_MAGIC; goto error; // NOLINT(cppcoreguidelines-avoid-goto) } // Send OK and version - 2 bytes - buf[0] = OTA_RESPONSE_OK; + buf[0] = ota::OTA_RESPONSE_OK; buf[1] = USE_OTA_VERSION; this->writeall_(buf, 2); - backend = make_ota_backend(); + backend = ota::make_ota_backend(); // Read features - 1 byte if (!this->readall_(buf, 1)) { - ESP_LOGW(TAG, "Reading features failed!"); + ESP_LOGW(TAG, "Reading features failed"); goto error; // NOLINT(cppcoreguidelines-avoid-goto) } ota_features = buf[0]; // NOLINT - ESP_LOGV(TAG, "OTA features is 0x%02X", ota_features); + ESP_LOGV(TAG, "Features: 0x%02X", ota_features); // Acknowledge header - 1 byte - buf[0] = OTA_RESPONSE_HEADER_OK; + buf[0] = ota::OTA_RESPONSE_HEADER_OK; if ((ota_features & FEATURE_SUPPORTS_COMPRESSION) != 0 && backend->supports_compression()) { - buf[0] = OTA_RESPONSE_SUPPORTS_COMPRESSION; + buf[0] = ota::OTA_RESPONSE_SUPPORTS_COMPRESSION; } this->writeall_(buf, 1); #ifdef USE_OTA_PASSWORD if (!this->password_.empty()) { - buf[0] = OTA_RESPONSE_REQUEST_AUTH; + buf[0] = ota::OTA_RESPONSE_REQUEST_AUTH; this->writeall_(buf, 1); md5::MD5Digest md5{}; md5.init(); @@ -206,7 +183,7 @@ void OTAComponent::handle_() { // Send nonce, 32 bytes hex MD5 if (!this->writeall_(reinterpret_cast(sbuf), 32)) { - ESP_LOGW(TAG, "Auth: Writing nonce failed!"); + ESP_LOGW(TAG, "Auth: Writing nonce failed"); goto error; // NOLINT(cppcoreguidelines-avoid-goto) } @@ -218,7 +195,7 @@ void OTAComponent::handle_() { // Receive cnonce, 32 bytes hex MD5 if (!this->readall_(buf, 32)) { - ESP_LOGW(TAG, "Auth: Reading cnonce failed!"); + ESP_LOGW(TAG, "Auth: Reading cnonce failed"); goto error; // NOLINT(cppcoreguidelines-avoid-goto) } sbuf[32] = '\0'; @@ -233,7 +210,7 @@ void OTAComponent::handle_() { // Receive result, 32 bytes hex MD5 if (!this->readall_(buf + 64, 32)) { - ESP_LOGW(TAG, "Auth: Reading response failed!"); + ESP_LOGW(TAG, "Auth: Reading response failed"); goto error; // NOLINT(cppcoreguidelines-avoid-goto) } sbuf[64 + 32] = '\0'; @@ -244,20 +221,20 @@ void OTAComponent::handle_() { matches = matches && buf[i] == buf[64 + i]; if (!matches) { - ESP_LOGW(TAG, "Auth failed! Passwords do not match!"); - error_code = OTA_RESPONSE_ERROR_AUTH_INVALID; + ESP_LOGW(TAG, "Auth failed! Passwords do not match"); + error_code = ota::OTA_RESPONSE_ERROR_AUTH_INVALID; goto error; // NOLINT(cppcoreguidelines-avoid-goto) } } #endif // USE_OTA_PASSWORD // Acknowledge auth OK - 1 byte - buf[0] = OTA_RESPONSE_AUTH_OK; + buf[0] = ota::OTA_RESPONSE_AUTH_OK; this->writeall_(buf, 1); // Read size, 4 bytes MSB first if (!this->readall_(buf, 4)) { - ESP_LOGW(TAG, "Reading size failed!"); + ESP_LOGW(TAG, "Reading size failed"); goto error; // NOLINT(cppcoreguidelines-avoid-goto) } ota_size = 0; @@ -265,20 +242,20 @@ void OTAComponent::handle_() { ota_size <<= 8; ota_size |= buf[i]; } - ESP_LOGV(TAG, "OTA size is %u bytes", ota_size); + ESP_LOGV(TAG, "Size is %u bytes", ota_size); error_code = backend->begin(ota_size); - if (error_code != OTA_RESPONSE_OK) + if (error_code != ota::OTA_RESPONSE_OK) goto error; // NOLINT(cppcoreguidelines-avoid-goto) update_started = true; // Acknowledge prepare OK - 1 byte - buf[0] = OTA_RESPONSE_UPDATE_PREPARE_OK; + buf[0] = ota::OTA_RESPONSE_UPDATE_PREPARE_OK; this->writeall_(buf, 1); // Read binary MD5, 32 bytes if (!this->readall_(buf, 32)) { - ESP_LOGW(TAG, "Reading binary MD5 checksum failed!"); + ESP_LOGW(TAG, "Reading binary MD5 checksum failed"); goto error; // NOLINT(cppcoreguidelines-avoid-goto) } sbuf[32] = '\0'; @@ -286,7 +263,7 @@ void OTAComponent::handle_() { backend->set_update_md5(sbuf); // Acknowledge MD5 OK - 1 byte - buf[0] = OTA_RESPONSE_BIN_MD5_OK; + buf[0] = ota::OTA_RESPONSE_BIN_MD5_OK; this->writeall_(buf, 1); while (total < ota_size) { @@ -299,7 +276,7 @@ void OTAComponent::handle_() { delay(1); continue; } - ESP_LOGW(TAG, "Error receiving data for update, errno: %d", errno); + ESP_LOGW(TAG, "Error receiving data for update, errno %d", errno); goto error; // NOLINT(cppcoreguidelines-avoid-goto) } else if (read == 0) { // $ man recv @@ -310,14 +287,14 @@ void OTAComponent::handle_() { } error_code = backend->write(buf, read); - if (error_code != OTA_RESPONSE_OK) { + if (error_code != ota::OTA_RESPONSE_OK) { ESP_LOGW(TAG, "Error writing binary data to flash!, error_code: %d", error_code); goto error; // NOLINT(cppcoreguidelines-avoid-goto) } total += read; #if USE_OTA_VERSION == 2 while (size_acknowledged + OTA_BLOCK_SIZE <= total || (total == ota_size && size_acknowledged < ota_size)) { - buf[0] = OTA_RESPONSE_CHUNK_OK; + buf[0] = ota::OTA_RESPONSE_CHUNK_OK; this->writeall_(buf, 1); size_acknowledged += OTA_BLOCK_SIZE; } @@ -327,9 +304,9 @@ void OTAComponent::handle_() { if (now - last_progress > 1000) { last_progress = now; float percentage = (total * 100.0f) / ota_size; - ESP_LOGD(TAG, "OTA in progress: %0.1f%%", percentage); + ESP_LOGD(TAG, "Progress: %0.1f%%", percentage); #ifdef USE_OTA_STATE_CALLBACK - this->state_callback_.call(OTA_IN_PROGRESS, percentage, 0); + this->state_callback_.call(ota::OTA_IN_PROGRESS, percentage, 0); #endif // feed watchdog and give other tasks a chance to run App.feed_wdt(); @@ -338,32 +315,32 @@ void OTAComponent::handle_() { } // Acknowledge receive OK - 1 byte - buf[0] = OTA_RESPONSE_RECEIVE_OK; + buf[0] = ota::OTA_RESPONSE_RECEIVE_OK; this->writeall_(buf, 1); error_code = backend->end(); - if (error_code != OTA_RESPONSE_OK) { - ESP_LOGW(TAG, "Error ending OTA!, error_code: %d", error_code); + if (error_code != ota::OTA_RESPONSE_OK) { + ESP_LOGW(TAG, "Error ending update! error_code: %d", error_code); goto error; // NOLINT(cppcoreguidelines-avoid-goto) } // Acknowledge Update end OK - 1 byte - buf[0] = OTA_RESPONSE_UPDATE_END_OK; + buf[0] = ota::OTA_RESPONSE_UPDATE_END_OK; this->writeall_(buf, 1); // Read ACK - if (!this->readall_(buf, 1) || buf[0] != OTA_RESPONSE_OK) { - ESP_LOGW(TAG, "Reading back acknowledgement failed!"); + if (!this->readall_(buf, 1) || buf[0] != ota::OTA_RESPONSE_OK) { + ESP_LOGW(TAG, "Reading back acknowledgement failed"); // do not go to error, this is not fatal } this->client_->close(); this->client_ = nullptr; delay(10); - ESP_LOGI(TAG, "OTA update finished!"); + ESP_LOGI(TAG, "Update complete"); this->status_clear_warning(); #ifdef USE_OTA_STATE_CALLBACK - this->state_callback_.call(OTA_COMPLETED, 100.0f, 0); + this->state_callback_.call(ota::OTA_COMPLETED, 100.0f, 0); #endif delay(100); // NOLINT App.safe_reboot(); @@ -380,11 +357,11 @@ error: this->status_momentary_error("onerror", 5000); #ifdef USE_OTA_STATE_CALLBACK - this->state_callback_.call(OTA_ERROR, 0.0f, static_cast(error_code)); + this->state_callback_.call(ota::OTA_ERROR, 0.0f, static_cast(error_code)); #endif } -bool OTAComponent::readall_(uint8_t *buf, size_t len) { +bool ESPHomeOTAComponent::readall_(uint8_t *buf, size_t len) { uint32_t start = millis(); uint32_t at = 0; while (len - at > 0) { @@ -401,7 +378,7 @@ bool OTAComponent::readall_(uint8_t *buf, size_t len) { delay(1); continue; } - ESP_LOGW(TAG, "Failed to read %d bytes of data, errno: %d", len, errno); + ESP_LOGW(TAG, "Failed to read %d bytes of data, errno %d", len, errno); return false; } else if (read == 0) { ESP_LOGW(TAG, "Remote closed connection"); @@ -415,7 +392,7 @@ bool OTAComponent::readall_(uint8_t *buf, size_t len) { return true; } -bool OTAComponent::writeall_(const uint8_t *buf, size_t len) { +bool ESPHomeOTAComponent::writeall_(const uint8_t *buf, size_t len) { uint32_t start = millis(); uint32_t at = 0; while (len - at > 0) { @@ -432,7 +409,7 @@ bool OTAComponent::writeall_(const uint8_t *buf, size_t len) { delay(1); continue; } - ESP_LOGW(TAG, "Failed to write %d bytes of data, errno: %d", len, errno); + ESP_LOGW(TAG, "Failed to write %d bytes of data, errno %d", len, errno); return false; } else { at += written; @@ -443,31 +420,31 @@ bool OTAComponent::writeall_(const uint8_t *buf, size_t len) { return true; } -float OTAComponent::get_setup_priority() const { return setup_priority::AFTER_WIFI; } -uint16_t OTAComponent::get_port() const { return this->port_; } -void OTAComponent::set_port(uint16_t port) { this->port_ = port; } +float ESPHomeOTAComponent::get_setup_priority() const { return setup_priority::AFTER_WIFI; } +uint16_t ESPHomeOTAComponent::get_port() const { return this->port_; } +void ESPHomeOTAComponent::set_port(uint16_t port) { this->port_ = port; } -void OTAComponent::set_safe_mode_pending(const bool &pending) { +void ESPHomeOTAComponent::set_safe_mode_pending(const bool &pending) { if (!this->has_safe_mode_) return; uint32_t current_rtc = this->read_rtc_(); - if (pending && current_rtc != esphome::ota::OTAComponent::ENTER_SAFE_MODE_MAGIC) { - ESP_LOGI(TAG, "Device will enter safe mode on next boot."); - this->write_rtc_(esphome::ota::OTAComponent::ENTER_SAFE_MODE_MAGIC); + if (pending && current_rtc != ESPHomeOTAComponent::ENTER_SAFE_MODE_MAGIC) { + ESP_LOGI(TAG, "Device will enter safe mode on next boot"); + this->write_rtc_(ESPHomeOTAComponent::ENTER_SAFE_MODE_MAGIC); } - if (!pending && current_rtc == esphome::ota::OTAComponent::ENTER_SAFE_MODE_MAGIC) { + if (!pending && current_rtc == ESPHomeOTAComponent::ENTER_SAFE_MODE_MAGIC) { ESP_LOGI(TAG, "Safe mode pending has been cleared"); this->clean_rtc(); } } -bool OTAComponent::get_safe_mode_pending() { - return this->has_safe_mode_ && this->read_rtc_() == esphome::ota::OTAComponent::ENTER_SAFE_MODE_MAGIC; +bool ESPHomeOTAComponent::get_safe_mode_pending() { + return this->has_safe_mode_ && this->read_rtc_() == ESPHomeOTAComponent::ENTER_SAFE_MODE_MAGIC; } -bool OTAComponent::should_enter_safe_mode(uint8_t num_attempts, uint32_t enable_time) { +bool ESPHomeOTAComponent::should_enter_safe_mode(uint8_t num_attempts, uint32_t enable_time) { this->has_safe_mode_ = true; this->safe_mode_start_time_ = millis(); this->safe_mode_enable_time_ = enable_time; @@ -475,24 +452,24 @@ bool OTAComponent::should_enter_safe_mode(uint8_t num_attempts, uint32_t enable_ this->rtc_ = global_preferences->make_preference(233825507UL, false); this->safe_mode_rtc_value_ = this->read_rtc_(); - bool is_manual_safe_mode = this->safe_mode_rtc_value_ == esphome::ota::OTAComponent::ENTER_SAFE_MODE_MAGIC; + bool is_manual_safe_mode = this->safe_mode_rtc_value_ == ESPHomeOTAComponent::ENTER_SAFE_MODE_MAGIC; if (is_manual_safe_mode) { ESP_LOGI(TAG, "Safe mode has been entered manually"); } else { - ESP_LOGCONFIG(TAG, "There have been %" PRIu32 " suspected unsuccessful boot attempts.", this->safe_mode_rtc_value_); + ESP_LOGCONFIG(TAG, "There have been %" PRIu32 " suspected unsuccessful boot attempts", this->safe_mode_rtc_value_); } if (this->safe_mode_rtc_value_ >= num_attempts || is_manual_safe_mode) { this->clean_rtc(); if (!is_manual_safe_mode) { - ESP_LOGE(TAG, "Boot loop detected. Proceeding to safe mode."); + ESP_LOGE(TAG, "Boot loop detected. Proceeding to safe mode"); } this->status_set_error(); this->set_timeout(enable_time, []() { - ESP_LOGE(TAG, "No OTA attempt made, restarting."); + ESP_LOGE(TAG, "No OTA attempt made, restarting"); App.reboot(); }); @@ -500,7 +477,7 @@ bool OTAComponent::should_enter_safe_mode(uint8_t num_attempts, uint32_t enable_ delay(300); // NOLINT App.setup(); - ESP_LOGI(TAG, "Waiting for OTA attempt."); + ESP_LOGI(TAG, "Waiting for OTA attempt"); return true; } else { @@ -509,27 +486,23 @@ bool OTAComponent::should_enter_safe_mode(uint8_t num_attempts, uint32_t enable_ return false; } } -void OTAComponent::write_rtc_(uint32_t val) { + +void ESPHomeOTAComponent::write_rtc_(uint32_t val) { this->rtc_.save(&val); global_preferences->sync(); } -uint32_t OTAComponent::read_rtc_() { + +uint32_t ESPHomeOTAComponent::read_rtc_() { uint32_t val; if (!this->rtc_.load(&val)) return 0; return val; } -void OTAComponent::clean_rtc() { this->write_rtc_(0); } -void OTAComponent::on_safe_shutdown() { - if (this->has_safe_mode_ && this->read_rtc_() != esphome::ota::OTAComponent::ENTER_SAFE_MODE_MAGIC) + +void ESPHomeOTAComponent::clean_rtc() { this->write_rtc_(0); } + +void ESPHomeOTAComponent::on_safe_shutdown() { + if (this->has_safe_mode_ && this->read_rtc_() != ESPHomeOTAComponent::ENTER_SAFE_MODE_MAGIC) this->clean_rtc(); } - -#ifdef USE_OTA_STATE_CALLBACK -void OTAComponent::add_on_state_callback(std::function &&callback) { - this->state_callback_.add(std::move(callback)); -} -#endif - -} // namespace ota } // namespace esphome diff --git a/esphome/components/ota/ota_component.h b/esphome/components/esphome/ota/ota_esphome.h similarity index 50% rename from esphome/components/ota/ota_component.h rename to esphome/components/esphome/ota/ota_esphome.h index c20f4f0709..e8f36f05ca 100644 --- a/esphome/components/ota/ota_component.h +++ b/esphome/components/esphome/ota/ota_esphome.h @@ -1,49 +1,16 @@ #pragma once -#include "esphome/components/socket/socket.h" -#include "esphome/core/component.h" -#include "esphome/core/preferences.h" -#include "esphome/core/helpers.h" #include "esphome/core/defines.h" +#include "esphome/core/helpers.h" +#include "esphome/core/preferences.h" +#include "esphome/components/ota/ota_backend.h" +#include "esphome/components/socket/socket.h" namespace esphome { -namespace ota { -enum OTAResponseTypes { - OTA_RESPONSE_OK = 0x00, - OTA_RESPONSE_REQUEST_AUTH = 0x01, - - OTA_RESPONSE_HEADER_OK = 0x40, - OTA_RESPONSE_AUTH_OK = 0x41, - OTA_RESPONSE_UPDATE_PREPARE_OK = 0x42, - OTA_RESPONSE_BIN_MD5_OK = 0x43, - OTA_RESPONSE_RECEIVE_OK = 0x44, - OTA_RESPONSE_UPDATE_END_OK = 0x45, - OTA_RESPONSE_SUPPORTS_COMPRESSION = 0x46, - OTA_RESPONSE_CHUNK_OK = 0x47, - - OTA_RESPONSE_ERROR_MAGIC = 0x80, - OTA_RESPONSE_ERROR_UPDATE_PREPARE = 0x81, - OTA_RESPONSE_ERROR_AUTH_INVALID = 0x82, - OTA_RESPONSE_ERROR_WRITING_FLASH = 0x83, - OTA_RESPONSE_ERROR_UPDATE_END = 0x84, - OTA_RESPONSE_ERROR_INVALID_BOOTSTRAPPING = 0x85, - OTA_RESPONSE_ERROR_WRONG_CURRENT_FLASH_CONFIG = 0x86, - OTA_RESPONSE_ERROR_WRONG_NEW_FLASH_CONFIG = 0x87, - OTA_RESPONSE_ERROR_ESP8266_NOT_ENOUGH_SPACE = 0x88, - OTA_RESPONSE_ERROR_ESP32_NOT_ENOUGH_SPACE = 0x89, - OTA_RESPONSE_ERROR_NO_UPDATE_PARTITION = 0x8A, - OTA_RESPONSE_ERROR_MD5_MISMATCH = 0x8B, - OTA_RESPONSE_ERROR_RP2040_NOT_ENOUGH_SPACE = 0x8C, - OTA_RESPONSE_ERROR_UNKNOWN = 0xFF, -}; - -enum OTAState { OTA_COMPLETED = 0, OTA_STARTED, OTA_IN_PROGRESS, OTA_ERROR }; - -/// OTAComponent provides a simple way to integrate Over-the-Air updates into your app using ArduinoOTA. -class OTAComponent : public Component { +/// ESPHomeOTAComponent provides a simple way to integrate Over-the-Air updates into your app using ArduinoOTA. +class ESPHomeOTAComponent : public ota::OTAComponent { public: - OTAComponent(); #ifdef USE_OTA_PASSWORD void set_auth_password(const std::string &password) { password_ = password; } #endif // USE_OTA_PASSWORD @@ -57,10 +24,6 @@ class OTAComponent : public Component { void set_safe_mode_pending(const bool &pending); bool get_safe_mode_pending(); -#ifdef USE_OTA_STATE_CALLBACK - void add_on_state_callback(std::function &&callback); -#endif - // ========== INTERNAL METHODS ========== // (In most use cases you won't need these) void setup() override; @@ -91,22 +54,15 @@ class OTAComponent : public Component { std::unique_ptr server_; std::unique_ptr client_; - bool has_safe_mode_{false}; ///< stores whether safe mode can be enabled. - uint32_t safe_mode_start_time_; ///< stores when safe mode was enabled. - uint32_t safe_mode_enable_time_{60000}; ///< The time safe mode should be on for. + bool has_safe_mode_{false}; ///< stores whether safe mode can be enabled + uint32_t safe_mode_start_time_; ///< stores when safe mode was enabled + uint32_t safe_mode_enable_time_{60000}; ///< The time safe mode should be on for uint32_t safe_mode_rtc_value_; uint8_t safe_mode_num_attempts_; ESPPreferenceObject rtc_; static const uint32_t ENTER_SAFE_MODE_MAGIC = 0x5afe5afe; ///< a magic number to indicate that safe mode should be entered on next boot - -#ifdef USE_OTA_STATE_CALLBACK - CallbackManager state_callback_{}; -#endif }; -extern OTAComponent *global_ota_component; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) - -} // namespace ota } // namespace esphome diff --git a/esphome/components/ota/__init__.py b/esphome/components/ota/__init__.py index 3c845490dc..728d36f3fa 100644 --- a/esphome/components/ota/__init__.py +++ b/esphome/components/ota/__init__.py @@ -1,71 +1,67 @@ -from esphome.cpp_generator import RawExpression import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation -from esphome.const import ( - CONF_ID, - CONF_NUM_ATTEMPTS, - CONF_PASSWORD, - CONF_PORT, - CONF_REBOOT_TIMEOUT, - CONF_SAFE_MODE, - CONF_TRIGGER_ID, - CONF_OTA, - KEY_PAST_SAFE_MODE, - CONF_VERSION, -) from esphome.core import CORE, coroutine_with_priority -CODEOWNERS = ["@esphome/core"] -DEPENDENCIES = ["network"] -AUTO_LOAD = ["socket", "md5"] +from esphome.const import CONF_ESPHOME, CONF_OTA, CONF_PLATFORM, CONF_TRIGGER_ID -CONF_ON_STATE_CHANGE = "on_state_change" +CODEOWNERS = ["@esphome/core"] +AUTO_LOAD = ["md5"] + +IS_PLATFORM_COMPONENT = True + +CONF_ON_ABORT = "on_abort" CONF_ON_BEGIN = "on_begin" -CONF_ON_PROGRESS = "on_progress" CONF_ON_END = "on_end" CONF_ON_ERROR = "on_error" +CONF_ON_PROGRESS = "on_progress" +CONF_ON_STATE_CHANGE = "on_state_change" + ota_ns = cg.esphome_ns.namespace("ota") -OTAState = ota_ns.enum("OTAState") OTAComponent = ota_ns.class_("OTAComponent", cg.Component) +OTAState = ota_ns.enum("OTAState") +OTAAbortTrigger = ota_ns.class_("OTAAbortTrigger", automation.Trigger.template()) +OTAEndTrigger = ota_ns.class_("OTAEndTrigger", automation.Trigger.template()) +OTAErrorTrigger = ota_ns.class_("OTAErrorTrigger", automation.Trigger.template()) +OTAProgressTrigger = ota_ns.class_("OTAProgressTrigger", automation.Trigger.template()) +OTAStartTrigger = ota_ns.class_("OTAStartTrigger", automation.Trigger.template()) OTAStateChangeTrigger = ota_ns.class_( "OTAStateChangeTrigger", automation.Trigger.template() ) -OTAStartTrigger = ota_ns.class_("OTAStartTrigger", automation.Trigger.template()) -OTAProgressTrigger = ota_ns.class_("OTAProgressTrigger", automation.Trigger.template()) -OTAEndTrigger = ota_ns.class_("OTAEndTrigger", automation.Trigger.template()) -OTAErrorTrigger = ota_ns.class_("OTAErrorTrigger", automation.Trigger.template()) -CONFIG_SCHEMA = cv.Schema( +def _ota_final_validate(config): + if len(config) < 1: + raise cv.Invalid( + f"At least one platform must be specified for '{CONF_OTA}'; add '{CONF_PLATFORM}: {CONF_ESPHOME}' for original OTA functionality" + ) + + +FINAL_VALIDATE_SCHEMA = _ota_final_validate + +BASE_OTA_SCHEMA = cv.Schema( { - cv.GenerateID(): cv.declare_id(OTAComponent), - cv.Optional(CONF_SAFE_MODE, default=True): cv.boolean, - cv.Optional(CONF_VERSION, default=2): cv.one_of(1, 2, int=True), - cv.SplitDefault( - CONF_PORT, - esp8266=8266, - esp32=3232, - rp2040=2040, - bk72xx=8892, - rtl87xx=8892, - ): cv.port, - cv.Optional(CONF_PASSWORD): cv.string, - cv.Optional( - CONF_REBOOT_TIMEOUT, default="5min" - ): cv.positive_time_period_milliseconds, - cv.Optional(CONF_NUM_ATTEMPTS, default="10"): cv.positive_not_null_int, cv.Optional(CONF_ON_STATE_CHANGE): automation.validate_automation( { cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(OTAStateChangeTrigger), } ), + cv.Optional(CONF_ON_ABORT): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(OTAAbortTrigger), + } + ), cv.Optional(CONF_ON_BEGIN): automation.validate_automation( { cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(OTAStartTrigger), } ), + cv.Optional(CONF_ON_END): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(OTAEndTrigger), + } + ), cv.Optional(CONF_ON_ERROR): automation.validate_automation( { cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(OTAErrorTrigger), @@ -76,35 +72,13 @@ CONFIG_SCHEMA = cv.Schema( cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(OTAProgressTrigger), } ), - cv.Optional(CONF_ON_END): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(OTAEndTrigger), - } - ), } -).extend(cv.COMPONENT_SCHEMA) +) @coroutine_with_priority(50.0) async def to_code(config): - CORE.data[CONF_OTA] = {} - - var = cg.new_Pvariable(config[CONF_ID]) - cg.add(var.set_port(config[CONF_PORT])) cg.add_define("USE_OTA") - if CONF_PASSWORD in config: - cg.add(var.set_auth_password(config[CONF_PASSWORD])) - cg.add_define("USE_OTA_PASSWORD") - cg.add_define("USE_OTA_VERSION", config[CONF_VERSION]) - - await cg.register_component(var, config) - - if config[CONF_SAFE_MODE]: - condition = var.should_enter_safe_mode( - config[CONF_NUM_ATTEMPTS], config[CONF_REBOOT_TIMEOUT] - ) - cg.add(RawExpression(f"if ({condition}) return")) - CORE.data[CONF_OTA][KEY_PAST_SAFE_MODE] = True if CORE.is_esp32 and CORE.using_arduino: cg.add_library("Update", None) @@ -112,11 +86,17 @@ async def to_code(config): if CORE.is_rp2040 and CORE.using_arduino: cg.add_library("Updater", None) + +async def ota_to_code(var, config): use_state_callback = False for conf in config.get(CONF_ON_STATE_CHANGE, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) await automation.build_automation(trigger, [(OTAState, "state")], conf) use_state_callback = True + for conf in config.get(CONF_ON_ABORT, []): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + await automation.build_automation(trigger, [], conf) + use_state_callback = True for conf in config.get(CONF_ON_BEGIN, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) await automation.build_automation(trigger, [], conf) diff --git a/esphome/components/ota/automation.h b/esphome/components/ota/automation.h index 0c77a18ce1..4605193480 100644 --- a/esphome/components/ota/automation.h +++ b/esphome/components/ota/automation.h @@ -1,11 +1,8 @@ #pragma once - -#include "esphome/core/defines.h" #ifdef USE_OTA_STATE_CALLBACK +#include "ota_backend.h" -#include "esphome/core/component.h" #include "esphome/core/automation.h" -#include "esphome/components/ota/ota_component.h" namespace esphome { namespace ota { @@ -54,6 +51,17 @@ class OTAEndTrigger : public Trigger<> { } }; +class OTAAbortTrigger : public Trigger<> { + public: + explicit OTAAbortTrigger(OTAComponent *parent) { + parent->add_on_state_callback([this, parent](OTAState state, float progress, uint8_t error) { + if (state == OTA_ABORT && !parent->is_failed()) { + trigger(); + } + }); + } +}; + class OTAErrorTrigger : public Trigger { public: explicit OTAErrorTrigger(OTAComponent *parent) { @@ -67,5 +75,4 @@ class OTAErrorTrigger : public Trigger { } // namespace ota } // namespace esphome - -#endif // USE_OTA_STATE_CALLBACK +#endif diff --git a/esphome/components/ota/ota_backend.cpp b/esphome/components/ota/ota_backend.cpp new file mode 100644 index 0000000000..30de4ec4b3 --- /dev/null +++ b/esphome/components/ota/ota_backend.cpp @@ -0,0 +1,20 @@ +#include "ota_backend.h" + +namespace esphome { +namespace ota { + +#ifdef USE_OTA_STATE_CALLBACK +OTAGlobalCallback *global_ota_callback{nullptr}; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + +OTAGlobalCallback *get_global_ota_callback() { + if (global_ota_callback == nullptr) { + global_ota_callback = new OTAGlobalCallback(); // NOLINT(cppcoreguidelines-owning-memory) + } + return global_ota_callback; +} + +void register_ota_platform(OTAComponent *ota_caller) { get_global_ota_callback()->register_ota(ota_caller); } +#endif + +} // namespace ota +} // namespace esphome diff --git a/esphome/components/ota/ota_backend.h b/esphome/components/ota/ota_backend.h index 5c5b61a278..bc8ab46643 100644 --- a/esphome/components/ota/ota_backend.h +++ b/esphome/components/ota/ota_backend.h @@ -1,9 +1,53 @@ #pragma once -#include "ota_component.h" + +#include "esphome/core/component.h" +#include "esphome/core/defines.h" +#include "esphome/core/helpers.h" + +#ifdef USE_OTA_STATE_CALLBACK +#include "esphome/core/automation.h" +#endif namespace esphome { namespace ota { +enum OTAResponseTypes { + OTA_RESPONSE_OK = 0x00, + OTA_RESPONSE_REQUEST_AUTH = 0x01, + + OTA_RESPONSE_HEADER_OK = 0x40, + OTA_RESPONSE_AUTH_OK = 0x41, + OTA_RESPONSE_UPDATE_PREPARE_OK = 0x42, + OTA_RESPONSE_BIN_MD5_OK = 0x43, + OTA_RESPONSE_RECEIVE_OK = 0x44, + OTA_RESPONSE_UPDATE_END_OK = 0x45, + OTA_RESPONSE_SUPPORTS_COMPRESSION = 0x46, + OTA_RESPONSE_CHUNK_OK = 0x47, + + OTA_RESPONSE_ERROR_MAGIC = 0x80, + OTA_RESPONSE_ERROR_UPDATE_PREPARE = 0x81, + OTA_RESPONSE_ERROR_AUTH_INVALID = 0x82, + OTA_RESPONSE_ERROR_WRITING_FLASH = 0x83, + OTA_RESPONSE_ERROR_UPDATE_END = 0x84, + OTA_RESPONSE_ERROR_INVALID_BOOTSTRAPPING = 0x85, + OTA_RESPONSE_ERROR_WRONG_CURRENT_FLASH_CONFIG = 0x86, + OTA_RESPONSE_ERROR_WRONG_NEW_FLASH_CONFIG = 0x87, + OTA_RESPONSE_ERROR_ESP8266_NOT_ENOUGH_SPACE = 0x88, + OTA_RESPONSE_ERROR_ESP32_NOT_ENOUGH_SPACE = 0x89, + OTA_RESPONSE_ERROR_NO_UPDATE_PARTITION = 0x8A, + OTA_RESPONSE_ERROR_MD5_MISMATCH = 0x8B, + OTA_RESPONSE_ERROR_RP2040_NOT_ENOUGH_SPACE = 0x8C, + OTA_RESPONSE_ERROR_UNKNOWN = 0xFF, +}; + +enum OTAState { + OTA_COMPLETED = 0, + OTA_STARTED, + OTA_IN_PROGRESS, + OTA_ABORT, + OTA_ERROR, +}; + class OTABackend { public: virtual ~OTABackend() = default; @@ -15,5 +59,38 @@ class OTABackend { virtual bool supports_compression() = 0; }; +class OTAComponent : public Component { +#ifdef USE_OTA_STATE_CALLBACK + public: + void add_on_state_callback(std::function &&callback) { + this->state_callback_.add(std::move(callback)); + } + + protected: + CallbackManager state_callback_{}; +#endif +}; + +#ifdef USE_OTA_STATE_CALLBACK +class OTAGlobalCallback { + public: + void register_ota(OTAComponent *ota_caller) { + ota_caller->add_on_state_callback([this, ota_caller](OTAState state, float progress, uint8_t error) { + this->state_callback_.call(state, progress, error, ota_caller); + }); + } + void add_on_state_callback(std::function &&callback) { + this->state_callback_.add(std::move(callback)); + } + + protected: + CallbackManager state_callback_{}; +}; + +OTAGlobalCallback *get_global_ota_callback(); +void register_ota_platform(OTAComponent *ota_caller); +#endif +std::unique_ptr make_ota_backend(); + } // namespace ota } // namespace esphome diff --git a/esphome/components/ota/ota_backend_arduino_esp32.cpp b/esphome/components/ota/ota_backend_arduino_esp32.cpp index 4759737dbd..62c6a72388 100644 --- a/esphome/components/ota/ota_backend_arduino_esp32.cpp +++ b/esphome/components/ota/ota_backend_arduino_esp32.cpp @@ -1,8 +1,7 @@ -#include "esphome/core/defines.h" #ifdef USE_ESP32_FRAMEWORK_ARDUINO +#include "esphome/core/defines.h" #include "ota_backend_arduino_esp32.h" -#include "ota_component.h" #include "ota_backend.h" #include @@ -10,6 +9,8 @@ namespace esphome { namespace ota { +std::unique_ptr make_ota_backend() { return make_unique(); } + OTAResponseTypes ArduinoESP32OTABackend::begin(size_t image_size) { bool ret = Update.begin(image_size, U_FLASH); if (ret) { diff --git a/esphome/components/ota/ota_backend_arduino_esp32.h b/esphome/components/ota/ota_backend_arduino_esp32.h index f86a70d678..ac7fe9f14f 100644 --- a/esphome/components/ota/ota_backend_arduino_esp32.h +++ b/esphome/components/ota/ota_backend_arduino_esp32.h @@ -1,10 +1,10 @@ #pragma once -#include "esphome/core/defines.h" #ifdef USE_ESP32_FRAMEWORK_ARDUINO - -#include "ota_component.h" #include "ota_backend.h" +#include "esphome/core/defines.h" +#include "esphome/core/helpers.h" + namespace esphome { namespace ota { diff --git a/esphome/components/ota/ota_backend_arduino_esp8266.cpp b/esphome/components/ota/ota_backend_arduino_esp8266.cpp index 23dc0d4e21..b317075bd0 100644 --- a/esphome/components/ota/ota_backend_arduino_esp8266.cpp +++ b/esphome/components/ota/ota_backend_arduino_esp8266.cpp @@ -1,10 +1,9 @@ -#include "esphome/core/defines.h" #ifdef USE_ARDUINO #ifdef USE_ESP8266 - -#include "ota_backend_arduino_esp8266.h" -#include "ota_component.h" #include "ota_backend.h" +#include "ota_backend_arduino_esp8266.h" + +#include "esphome/core/defines.h" #include "esphome/components/esp8266/preferences.h" #include @@ -12,6 +11,8 @@ namespace esphome { namespace ota { +std::unique_ptr make_ota_backend() { return make_unique(); } + OTAResponseTypes ArduinoESP8266OTABackend::begin(size_t image_size) { bool ret = Update.begin(image_size, U_FLASH); if (ret) { diff --git a/esphome/components/ota/ota_backend_arduino_esp8266.h b/esphome/components/ota/ota_backend_arduino_esp8266.h index 7937c665b0..7f44d7c965 100644 --- a/esphome/components/ota/ota_backend_arduino_esp8266.h +++ b/esphome/components/ota/ota_backend_arduino_esp8266.h @@ -1,10 +1,9 @@ #pragma once -#include "esphome/core/defines.h" #ifdef USE_ARDUINO #ifdef USE_ESP8266 - -#include "ota_component.h" #include "ota_backend.h" + +#include "esphome/core/defines.h" #include "esphome/core/macros.h" namespace esphome { diff --git a/esphome/components/ota/ota_backend_arduino_libretiny.cpp b/esphome/components/ota/ota_backend_arduino_libretiny.cpp index dbf6c97988..df4e774ebc 100644 --- a/esphome/components/ota/ota_backend_arduino_libretiny.cpp +++ b/esphome/components/ota/ota_backend_arduino_libretiny.cpp @@ -1,15 +1,16 @@ -#include "esphome/core/defines.h" #ifdef USE_LIBRETINY - -#include "ota_backend_arduino_libretiny.h" -#include "ota_component.h" #include "ota_backend.h" +#include "ota_backend_arduino_libretiny.h" + +#include "esphome/core/defines.h" #include namespace esphome { namespace ota { +std::unique_ptr make_ota_backend() { return make_unique(); } + OTAResponseTypes ArduinoLibreTinyOTABackend::begin(size_t image_size) { bool ret = Update.begin(image_size, U_FLASH); if (ret) { diff --git a/esphome/components/ota/ota_backend_arduino_libretiny.h b/esphome/components/ota/ota_backend_arduino_libretiny.h index 79656bb353..11deb6e2f2 100644 --- a/esphome/components/ota/ota_backend_arduino_libretiny.h +++ b/esphome/components/ota/ota_backend_arduino_libretiny.h @@ -1,10 +1,9 @@ #pragma once -#include "esphome/core/defines.h" #ifdef USE_LIBRETINY - -#include "ota_component.h" #include "ota_backend.h" +#include "esphome/core/defines.h" + namespace esphome { namespace ota { diff --git a/esphome/components/ota/ota_backend_arduino_rp2040.cpp b/esphome/components/ota/ota_backend_arduino_rp2040.cpp index 260387cec1..4448b0c95e 100644 --- a/esphome/components/ota/ota_backend_arduino_rp2040.cpp +++ b/esphome/components/ota/ota_backend_arduino_rp2040.cpp @@ -1,17 +1,18 @@ -#include "esphome/core/defines.h" #ifdef USE_ARDUINO #ifdef USE_RP2040 - -#include "esphome/components/rp2040/preferences.h" #include "ota_backend.h" #include "ota_backend_arduino_rp2040.h" -#include "ota_component.h" + +#include "esphome/components/rp2040/preferences.h" +#include "esphome/core/defines.h" #include namespace esphome { namespace ota { +std::unique_ptr make_ota_backend() { return make_unique(); } + OTAResponseTypes ArduinoRP2040OTABackend::begin(size_t image_size) { bool ret = Update.begin(image_size, U_FLASH); if (ret) { diff --git a/esphome/components/ota/ota_backend_arduino_rp2040.h b/esphome/components/ota/ota_backend_arduino_rp2040.h index 5aa2ec9435..b189964ab3 100644 --- a/esphome/components/ota/ota_backend_arduino_rp2040.h +++ b/esphome/components/ota/ota_backend_arduino_rp2040.h @@ -1,11 +1,10 @@ #pragma once -#include "esphome/core/defines.h" #ifdef USE_ARDUINO #ifdef USE_RP2040 - -#include "esphome/core/macros.h" #include "ota_backend.h" -#include "ota_component.h" + +#include "esphome/core/defines.h" +#include "esphome/core/macros.h" namespace esphome { namespace ota { diff --git a/esphome/components/ota/ota_backend_esp_idf.cpp b/esphome/components/ota/ota_backend_esp_idf.cpp index 319a1482f1..6f45fb75e4 100644 --- a/esphome/components/ota/ota_backend_esp_idf.cpp +++ b/esphome/components/ota/ota_backend_esp_idf.cpp @@ -1,12 +1,11 @@ -#include "esphome/core/defines.h" #ifdef USE_ESP_IDF - -#include - #include "ota_backend_esp_idf.h" -#include "ota_component.h" -#include + #include "esphome/components/md5/md5.h" +#include "esphome/core/defines.h" + +#include +#include #if ESP_IDF_VERSION_MAJOR >= 5 #include @@ -15,6 +14,8 @@ namespace esphome { namespace ota { +std::unique_ptr make_ota_backend() { return make_unique(); } + OTAResponseTypes IDFOTABackend::begin(size_t image_size) { this->partition_ = esp_ota_get_next_update_partition(nullptr); if (this->partition_ == nullptr) { diff --git a/esphome/components/ota/ota_backend_esp_idf.h b/esphome/components/ota/ota_backend_esp_idf.h index af09d0d693..ed66d9b970 100644 --- a/esphome/components/ota/ota_backend_esp_idf.h +++ b/esphome/components/ota/ota_backend_esp_idf.h @@ -1,11 +1,11 @@ #pragma once -#include "esphome/core/defines.h" #ifdef USE_ESP_IDF - -#include "ota_component.h" #include "ota_backend.h" -#include + #include "esphome/components/md5/md5.h" +#include "esphome/core/defines.h" + +#include namespace esphome { namespace ota { diff --git a/esphome/components/safe_mode/button/__init__.py b/esphome/components/safe_mode/button/__init__.py index 307e4e372e..bd51d2e038 100644 --- a/esphome/components/safe_mode/button/__init__.py +++ b/esphome/components/safe_mode/button/__init__.py @@ -1,18 +1,17 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import button -from esphome.components.ota import OTAComponent +from esphome.components.esphome.ota import ESPHomeOTAComponent from esphome.const import ( - CONF_ID, - CONF_OTA, + CONF_ESPHOME, DEVICE_CLASS_RESTART, ENTITY_CATEGORY_CONFIG, ICON_RESTART_ALERT, ) +from .. import safe_mode_ns -DEPENDENCIES = ["ota"] +DEPENDENCIES = ["ota.esphome"] -safe_mode_ns = cg.esphome_ns.namespace("safe_mode") SafeModeButton = safe_mode_ns.class_("SafeModeButton", button.Button, cg.Component) CONFIG_SCHEMA = ( @@ -22,15 +21,14 @@ CONFIG_SCHEMA = ( entity_category=ENTITY_CATEGORY_CONFIG, icon=ICON_RESTART_ALERT, ) - .extend({cv.GenerateID(CONF_OTA): cv.use_id(OTAComponent)}) + .extend({cv.GenerateID(CONF_ESPHOME): cv.use_id(ESPHomeOTAComponent)}) .extend(cv.COMPONENT_SCHEMA) ) async def to_code(config): - var = cg.new_Pvariable(config[CONF_ID]) + var = await button.new_button(config) await cg.register_component(var, config) - await button.register_button(var, config) - ota = await cg.get_variable(config[CONF_OTA]) + ota = await cg.get_variable(config[CONF_ESPHOME]) cg.add(var.set_ota(ota)) diff --git a/esphome/components/safe_mode/button/safe_mode_button.cpp b/esphome/components/safe_mode/button/safe_mode_button.cpp index 2b8654de46..d513b79c12 100644 --- a/esphome/components/safe_mode/button/safe_mode_button.cpp +++ b/esphome/components/safe_mode/button/safe_mode_button.cpp @@ -8,7 +8,7 @@ namespace safe_mode { static const char *const TAG = "safe_mode.button"; -void SafeModeButton::set_ota(ota::OTAComponent *ota) { this->ota_ = ota; } +void SafeModeButton::set_ota(esphome::ESPHomeOTAComponent *ota) { this->ota_ = ota; } void SafeModeButton::press_action() { ESP_LOGI(TAG, "Restarting device in safe mode..."); diff --git a/esphome/components/safe_mode/button/safe_mode_button.h b/esphome/components/safe_mode/button/safe_mode_button.h index 63e0d1755e..a306735b7f 100644 --- a/esphome/components/safe_mode/button/safe_mode_button.h +++ b/esphome/components/safe_mode/button/safe_mode_button.h @@ -1,8 +1,8 @@ #pragma once -#include "esphome/core/component.h" -#include "esphome/components/ota/ota_component.h" #include "esphome/components/button/button.h" +#include "esphome/components/esphome/ota/ota_esphome.h" +#include "esphome/core/component.h" namespace esphome { namespace safe_mode { @@ -10,10 +10,10 @@ namespace safe_mode { class SafeModeButton : public button::Button, public Component { public: void dump_config() override; - void set_ota(ota::OTAComponent *ota); + void set_ota(esphome::ESPHomeOTAComponent *ota); protected: - ota::OTAComponent *ota_; + esphome::ESPHomeOTAComponent *ota_; void press_action() override; }; diff --git a/esphome/components/safe_mode/switch/__init__.py b/esphome/components/safe_mode/switch/__init__.py index a6fcdfbece..0f8e500482 100644 --- a/esphome/components/safe_mode/switch/__init__.py +++ b/esphome/components/safe_mode/switch/__init__.py @@ -1,26 +1,26 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import switch -from esphome.components.ota import OTAComponent +from esphome.components.esphome.ota import ESPHomeOTAComponent from esphome.const import ( - CONF_OTA, + CONF_ESPHOME, ENTITY_CATEGORY_CONFIG, ICON_RESTART_ALERT, ) from .. import safe_mode_ns -DEPENDENCIES = ["ota"] +DEPENDENCIES = ["ota.esphome"] SafeModeSwitch = safe_mode_ns.class_("SafeModeSwitch", switch.Switch, cg.Component) CONFIG_SCHEMA = ( switch.switch_schema( SafeModeSwitch, - icon=ICON_RESTART_ALERT, - entity_category=ENTITY_CATEGORY_CONFIG, block_inverted=True, + entity_category=ENTITY_CATEGORY_CONFIG, + icon=ICON_RESTART_ALERT, ) - .extend({cv.GenerateID(CONF_OTA): cv.use_id(OTAComponent)}) + .extend({cv.GenerateID(CONF_ESPHOME): cv.use_id(ESPHomeOTAComponent)}) .extend(cv.COMPONENT_SCHEMA) ) @@ -29,5 +29,5 @@ async def to_code(config): var = await switch.new_switch(config) await cg.register_component(var, config) - ota = await cg.get_variable(config[CONF_OTA]) + ota = await cg.get_variable(config[CONF_ESPHOME]) cg.add(var.set_ota(ota)) diff --git a/esphome/components/safe_mode/switch/safe_mode_switch.cpp b/esphome/components/safe_mode/switch/safe_mode_switch.cpp index a3979eec06..71408df140 100644 --- a/esphome/components/safe_mode/switch/safe_mode_switch.cpp +++ b/esphome/components/safe_mode/switch/safe_mode_switch.cpp @@ -1,14 +1,14 @@ #include "safe_mode_switch.h" +#include "esphome/core/application.h" #include "esphome/core/hal.h" #include "esphome/core/log.h" -#include "esphome/core/application.h" namespace esphome { namespace safe_mode { static const char *const TAG = "safe_mode_switch"; -void SafeModeSwitch::set_ota(ota::OTAComponent *ota) { this->ota_ = ota; } +void SafeModeSwitch::set_ota(esphome::ESPHomeOTAComponent *ota) { this->ota_ = ota; } void SafeModeSwitch::write_state(bool state) { // Acknowledge diff --git a/esphome/components/safe_mode/switch/safe_mode_switch.h b/esphome/components/safe_mode/switch/safe_mode_switch.h index 2772db3d84..5bd15a44de 100644 --- a/esphome/components/safe_mode/switch/safe_mode_switch.h +++ b/esphome/components/safe_mode/switch/safe_mode_switch.h @@ -1,8 +1,8 @@ #pragma once -#include "esphome/core/component.h" -#include "esphome/components/ota/ota_component.h" +#include "esphome/components/esphome/ota/ota_esphome.h" #include "esphome/components/switch/switch.h" +#include "esphome/core/component.h" namespace esphome { namespace safe_mode { @@ -10,10 +10,10 @@ namespace safe_mode { class SafeModeSwitch : public switch_::Switch, public Component { public: void dump_config() override; - void set_ota(ota::OTAComponent *ota); + void set_ota(esphome::ESPHomeOTAComponent *ota); protected: - ota::OTAComponent *ota_; + esphome::ESPHomeOTAComponent *ota_; void write_state(bool state) override; }; diff --git a/esphome/cpp_helpers.py b/esphome/cpp_helpers.py index 4b3716e223..ce494e5d9d 100644 --- a/esphome/cpp_helpers.py +++ b/esphome/cpp_helpers.py @@ -3,14 +3,16 @@ import logging from esphome.const import ( CONF_DISABLED_BY_DEFAULT, CONF_ENTITY_CATEGORY, + CONF_ESPHOME, CONF_ICON, CONF_INTERNAL, CONF_NAME, - CONF_SETUP_PRIORITY, - CONF_UPDATE_INTERVAL, - CONF_TYPE_ID, CONF_OTA, + CONF_PLATFORM, CONF_SAFE_MODE, + CONF_SETUP_PRIORITY, + CONF_TYPE_ID, + CONF_UPDATE_INTERVAL, KEY_PAST_SAFE_MODE, ) @@ -139,9 +141,16 @@ async def build_registry_list(registry, config): async def past_safe_mode(): - safe_mode_enabled = ( - CONF_OTA in CORE.config and CORE.config[CONF_OTA][CONF_SAFE_MODE] - ) + ota_conf = {} + for ota_item in CORE.config.get(CONF_OTA, []): + if ota_item[CONF_PLATFORM] == CONF_ESPHOME: + ota_conf = ota_item + break + + if not ota_conf: + return + + safe_mode_enabled = ota_conf[CONF_SAFE_MODE] if not safe_mode_enabled: return diff --git a/esphome/wizard.py b/esphome/wizard.py index 4ec366bbb9..9680ade044 100644 --- a/esphome/wizard.py +++ b/esphome/wizard.py @@ -153,10 +153,11 @@ def wizard_file(**kwargs): # Configure OTA config += "\nota:\n" + config += " - platform: esphome\n" if "ota_password" in kwargs: - config += f" password: \"{kwargs['ota_password']}\"" + config += f" password: \"{kwargs['ota_password']}\"" elif "password" in kwargs: - config += f" password: \"{kwargs['password']}\"" + config += f" password: \"{kwargs['password']}\"" # Configuring wifi config += "\n\nwifi:\n" diff --git a/tests/components/ota/common.yaml b/tests/components/ota/common.yaml index 367454995f..4910e2d891 100644 --- a/tests/components/ota/common.yaml +++ b/tests/components/ota/common.yaml @@ -3,28 +3,29 @@ wifi: password: password1 ota: - safe_mode: true - password: "superlongpasswordthatnoonewillknow" - port: 3286 - reboot_timeout: 2min - num_attempts: 5 - 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); + - platform: esphome + safe_mode: true + password: "superlongpasswordthatnoonewillknow" + port: 3286 + reboot_timeout: 2min + num_attempts: 5 + 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); diff --git a/tests/components/safe_mode/common.yaml b/tests/components/safe_mode/common.yaml index df0abd9aec..1dfc516254 100644 --- a/tests/components/safe_mode/common.yaml +++ b/tests/components/safe_mode/common.yaml @@ -3,6 +3,8 @@ wifi: password: password1 ota: + - platform: esphome + safe_mode: true button: - platform: safe_mode diff --git a/tests/dummy_main.cpp b/tests/dummy_main.cpp index da5c6d10d0..3ba4c8bd07 100644 --- a/tests/dummy_main.cpp +++ b/tests/dummy_main.cpp @@ -5,7 +5,7 @@ #include #include -#include +#include #include #include @@ -25,7 +25,7 @@ void setup() { ap.set_password("password1"); wifi->add_sta(ap); - auto *ota = new ota::OTAComponent(); // NOLINT + auto *ota = new esphome::ESPHomeOTAComponent(); // NOLINT ota->set_port(8266); App.setup(); diff --git a/tests/test1.yaml b/tests/test1.yaml index 79b836da4a..dc46b55c44 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -265,29 +265,30 @@ uart: baud_rate: 9600 ota: - safe_mode: true - password: "superlongpasswordthatnoonewillknow" - port: 3286 - reboot_timeout: 2min - num_attempts: 5 - on_state_change: - then: - lambda: >- - ESP_LOGD("ota", "State %d", state); - on_begin: - then: - logger.log: OTA begin - on_progress: - then: - lambda: >- - ESP_LOGD("ota", "Got progress %f", x); - on_end: - then: - logger.log: OTA end - on_error: - then: - lambda: >- - ESP_LOGD("ota", "Got error code %d", x); + - platform: esphome + safe_mode: true + password: "superlongpasswordthatnoonewillknow" + port: 3286 + reboot_timeout: 2min + num_attempts: 5 + on_state_change: + then: + lambda: >- + ESP_LOGD("ota", "State %d", state); + on_begin: + then: + logger.log: OTA begin + on_progress: + then: + lambda: >- + ESP_LOGD("ota", "Got progress %f", x); + on_end: + then: + logger.log: OTA end + on_error: + then: + lambda: >- + ESP_LOGD("ota", "Got error code %d", x); logger: baud_rate: 0 diff --git a/tests/test11.5.yaml b/tests/test11.5.yaml index 13de7f1929..758f295a6c 100644 --- a/tests/test11.5.yaml +++ b/tests/test11.5.yaml @@ -31,6 +31,7 @@ network: api: ota: + - platform: esphome logger: diff --git a/tests/test2.yaml b/tests/test2.yaml index 970076e78b..54ff4807a3 100644 --- a/tests/test2.yaml +++ b/tests/test2.yaml @@ -80,9 +80,10 @@ uart: - lambda: UARTDebug::log_hex(direction, bytes, ':'); ota: - safe_mode: true - port: 3286 - num_attempts: 15 + - platform: esphome + safe_mode: true + port: 3286 + num_attempts: 15 logger: level: DEBUG diff --git a/tests/test3.1.yaml b/tests/test3.1.yaml index 2bddd6f4d7..18d92289cd 100644 --- a/tests/test3.1.yaml +++ b/tests/test3.1.yaml @@ -49,7 +49,8 @@ spi: number: GPIO14 ota: - version: 2 + - platform: esphome + version: 2 logger: diff --git a/tests/test3.yaml b/tests/test3.yaml index 61d814385b..7554d4bcb2 100644 --- a/tests/test3.yaml +++ b/tests/test3.yaml @@ -328,9 +328,10 @@ vbus: uart_id: uart_4 ota: - safe_mode: true - port: 3286 - reboot_timeout: 15min + - platform: esphome + safe_mode: true + port: 3286 + reboot_timeout: 15min logger: hardware_uart: UART1 diff --git a/tests/test4.yaml b/tests/test4.yaml index 993ce126a8..86beee81c6 100644 --- a/tests/test4.yaml +++ b/tests/test4.yaml @@ -103,8 +103,9 @@ uart: parity: EVEN ota: - safe_mode: true - port: 3286 + - platform: esphome + safe_mode: true + port: 3286 logger: level: DEBUG diff --git a/tests/test5.yaml b/tests/test5.yaml index afd3359098..f7a34d5a1b 100644 --- a/tests/test5.yaml +++ b/tests/test5.yaml @@ -28,6 +28,7 @@ network: api: ota: + - platform: esphome logger: diff --git a/tests/test6.yaml b/tests/test6.yaml index 2c5aa30aad..b1103eb126 100644 --- a/tests/test6.yaml +++ b/tests/test6.yaml @@ -22,6 +22,7 @@ network: api: ota: + - platform: esphome logger: diff --git a/tests/test9.1.yaml b/tests/test9.1.yaml index f7455b7668..2d205ef4e6 100644 --- a/tests/test9.1.yaml +++ b/tests/test9.1.yaml @@ -12,6 +12,7 @@ esphome: logger: ota: + - platform: esphome captive_portal: diff --git a/tests/test9.yaml b/tests/test9.yaml index d660b4f24a..5017ccc5ed 100644 --- a/tests/test9.yaml +++ b/tests/test9.yaml @@ -12,6 +12,7 @@ esphome: logger: ota: + - platform: esphome captive_portal: From 247b2eee302fd69096bdd01f79d63b8b629c91ba Mon Sep 17 00:00:00 2001 From: Mat931 <49403702+Mat931@users.noreply.github.com> Date: Thu, 16 May 2024 02:11:21 +0000 Subject: [PATCH 1458/2101] Add ADC multisampling (#6330) --- esphome/components/adc/adc_sensor.cpp | 158 +++++++++++++++----------- esphome/components/adc/adc_sensor.h | 18 +-- esphome/components/adc/sensor.py | 8 ++ 3 files changed, 112 insertions(+), 72 deletions(-) diff --git a/esphome/components/adc/adc_sensor.cpp b/esphome/components/adc/adc_sensor.cpp index 1a76bdb264..7257793016 100644 --- a/esphome/components/adc/adc_sensor.cpp +++ b/esphome/components/adc/adc_sensor.cpp @@ -46,27 +46,27 @@ extern "C" ADCSensor::setup() { ESP_LOGCONFIG(TAG, "Setting up ADC '%s'...", this->get_name().c_str()); #if !defined(USE_ADC_SENSOR_VCC) && !defined(USE_RP2040) - pin_->setup(); + this->pin_->setup(); #endif #ifdef USE_ESP32 - if (channel1_ != ADC1_CHANNEL_MAX) { + if (this->channel1_ != ADC1_CHANNEL_MAX) { adc1_config_width(ADC_WIDTH_MAX_SOC_BITS); - if (!autorange_) { - adc1_config_channel_atten(channel1_, attenuation_); + if (!this->autorange_) { + adc1_config_channel_atten(this->channel1_, this->attenuation_); } - } else if (channel2_ != ADC2_CHANNEL_MAX) { - if (!autorange_) { - adc2_config_channel_atten(channel2_, attenuation_); + } else if (this->channel2_ != ADC2_CHANNEL_MAX) { + if (!this->autorange_) { + adc2_config_channel_atten(this->channel2_, this->attenuation_); } } // load characteristics for each attenuation for (int32_t i = 0; i <= ADC_ATTEN_DB_12_COMPAT; i++) { - auto adc_unit = channel1_ != ADC1_CHANNEL_MAX ? ADC_UNIT_1 : ADC_UNIT_2; + auto adc_unit = this->channel1_ != ADC1_CHANNEL_MAX ? ADC_UNIT_1 : ADC_UNIT_2; auto cal_value = esp_adc_cal_characterize(adc_unit, (adc_atten_t) i, ADC_WIDTH_MAX_SOC_BITS, 1100, // default vref - &cal_characteristics_[i]); + &this->cal_characteristics_[i]); switch (cal_value) { case ESP_ADC_CAL_VAL_EFUSE_VREF: ESP_LOGV(TAG, "Using eFuse Vref for calibration"); @@ -99,27 +99,27 @@ void ADCSensor::dump_config() { #ifdef USE_ADC_SENSOR_VCC ESP_LOGCONFIG(TAG, " Pin: VCC"); #else - LOG_PIN(" Pin: ", pin_); + LOG_PIN(" Pin: ", this->pin_); #endif #endif // USE_ESP8266 || USE_LIBRETINY #ifdef USE_ESP32 - LOG_PIN(" Pin: ", pin_); - if (autorange_) { - ESP_LOGCONFIG(TAG, " Attenuation: auto"); + LOG_PIN(" Pin: ", this->pin_); + if (this->autorange_) { + ESP_LOGCONFIG(TAG, " Attenuation: auto"); } else { switch (this->attenuation_) { case ADC_ATTEN_DB_0: - ESP_LOGCONFIG(TAG, " Attenuation: 0db"); + ESP_LOGCONFIG(TAG, " Attenuation: 0db"); break; case ADC_ATTEN_DB_2_5: - ESP_LOGCONFIG(TAG, " Attenuation: 2.5db"); + ESP_LOGCONFIG(TAG, " Attenuation: 2.5db"); break; case ADC_ATTEN_DB_6: - ESP_LOGCONFIG(TAG, " Attenuation: 6db"); + ESP_LOGCONFIG(TAG, " Attenuation: 6db"); break; case ADC_ATTEN_DB_12_COMPAT: - ESP_LOGCONFIG(TAG, " Attenuation: 12db"); + ESP_LOGCONFIG(TAG, " Attenuation: 12db"); break; default: // This is to satisfy the unused ADC_ATTEN_MAX break; @@ -134,11 +134,11 @@ void ADCSensor::dump_config() { #ifdef USE_ADC_SENSOR_VCC ESP_LOGCONFIG(TAG, " Pin: VCC"); #else - LOG_PIN(" Pin: ", pin_); + LOG_PIN(" Pin: ", this->pin_); #endif // USE_ADC_SENSOR_VCC } #endif // USE_RP2040 - + ESP_LOGCONFIG(TAG, " Samples: %i", this->sample_count_); LOG_UPDATE_INTERVAL(this); } @@ -149,14 +149,24 @@ void ADCSensor::update() { this->publish_state(value_v); } +void ADCSensor::set_sample_count(uint8_t sample_count) { + if (sample_count != 0) { + this->sample_count_ = sample_count; + } +} + #ifdef USE_ESP8266 float ADCSensor::sample() { + uint32_t raw = 0; + for (uint8_t sample = 0; sample < this->sample_count_; sample++) { #ifdef USE_ADC_SENSOR_VCC - int32_t raw = ESP.getVcc(); // NOLINT(readability-static-accessed-through-instance) + raw += ESP.getVcc(); // NOLINT(readability-static-accessed-through-instance) #else - int32_t raw = analogRead(this->pin_->get_pin()); // NOLINT + raw += analogRead(this->pin_->get_pin()); // NOLINT #endif - if (output_raw_) { + } + raw = (raw + (this->sample_count_ >> 1)) / this->sample_count_; // NOLINT(clang-analyzer-core.DivideZero) + if (this->output_raw_) { return raw; } return raw / 1024.0f; @@ -165,53 +175,57 @@ float ADCSensor::sample() { #ifdef USE_ESP32 float ADCSensor::sample() { - if (!autorange_) { - int raw = -1; - if (channel1_ != ADC1_CHANNEL_MAX) { - raw = adc1_get_raw(channel1_); - } else if (channel2_ != ADC2_CHANNEL_MAX) { - adc2_get_raw(channel2_, ADC_WIDTH_MAX_SOC_BITS, &raw); + if (!this->autorange_) { + uint32_t sum = 0; + for (uint8_t sample = 0; sample < this->sample_count_; sample++) { + int raw = -1; + if (this->channel1_ != ADC1_CHANNEL_MAX) { + raw = adc1_get_raw(this->channel1_); + } else if (this->channel2_ != ADC2_CHANNEL_MAX) { + adc2_get_raw(this->channel2_, ADC_WIDTH_MAX_SOC_BITS, &raw); + } + if (raw == -1) { + return NAN; + } + sum += raw; } - - if (raw == -1) { - return NAN; + sum = (sum + (this->sample_count_ >> 1)) / this->sample_count_; // NOLINT(clang-analyzer-core.DivideZero) + if (this->output_raw_) { + return sum; } - if (output_raw_) { - return raw; - } - uint32_t mv = esp_adc_cal_raw_to_voltage(raw, &cal_characteristics_[(int32_t) attenuation_]); + uint32_t mv = esp_adc_cal_raw_to_voltage(sum, &this->cal_characteristics_[(int32_t) this->attenuation_]); return mv / 1000.0f; } int raw12 = ADC_MAX, raw6 = ADC_MAX, raw2 = ADC_MAX, raw0 = ADC_MAX; - if (channel1_ != ADC1_CHANNEL_MAX) { - adc1_config_channel_atten(channel1_, ADC_ATTEN_DB_12_COMPAT); - raw12 = adc1_get_raw(channel1_); + if (this->channel1_ != ADC1_CHANNEL_MAX) { + adc1_config_channel_atten(this->channel1_, ADC_ATTEN_DB_12_COMPAT); + raw12 = adc1_get_raw(this->channel1_); if (raw12 < ADC_MAX) { - adc1_config_channel_atten(channel1_, ADC_ATTEN_DB_6); - raw6 = adc1_get_raw(channel1_); + adc1_config_channel_atten(this->channel1_, ADC_ATTEN_DB_6); + raw6 = adc1_get_raw(this->channel1_); if (raw6 < ADC_MAX) { - adc1_config_channel_atten(channel1_, ADC_ATTEN_DB_2_5); - raw2 = adc1_get_raw(channel1_); + adc1_config_channel_atten(this->channel1_, ADC_ATTEN_DB_2_5); + raw2 = adc1_get_raw(this->channel1_); if (raw2 < ADC_MAX) { - adc1_config_channel_atten(channel1_, ADC_ATTEN_DB_0); - raw0 = adc1_get_raw(channel1_); + adc1_config_channel_atten(this->channel1_, ADC_ATTEN_DB_0); + raw0 = adc1_get_raw(this->channel1_); } } } - } else if (channel2_ != ADC2_CHANNEL_MAX) { - adc2_config_channel_atten(channel2_, ADC_ATTEN_DB_12_COMPAT); - adc2_get_raw(channel2_, ADC_WIDTH_MAX_SOC_BITS, &raw12); + } else if (this->channel2_ != ADC2_CHANNEL_MAX) { + adc2_config_channel_atten(this->channel2_, ADC_ATTEN_DB_12_COMPAT); + adc2_get_raw(this->channel2_, ADC_WIDTH_MAX_SOC_BITS, &raw12); if (raw12 < ADC_MAX) { - adc2_config_channel_atten(channel2_, ADC_ATTEN_DB_6); - adc2_get_raw(channel2_, ADC_WIDTH_MAX_SOC_BITS, &raw6); + adc2_config_channel_atten(this->channel2_, ADC_ATTEN_DB_6); + adc2_get_raw(this->channel2_, ADC_WIDTH_MAX_SOC_BITS, &raw6); if (raw6 < ADC_MAX) { - adc2_config_channel_atten(channel2_, ADC_ATTEN_DB_2_5); - adc2_get_raw(channel2_, ADC_WIDTH_MAX_SOC_BITS, &raw2); + adc2_config_channel_atten(this->channel2_, ADC_ATTEN_DB_2_5); + adc2_get_raw(this->channel2_, ADC_WIDTH_MAX_SOC_BITS, &raw2); if (raw2 < ADC_MAX) { - adc2_config_channel_atten(channel2_, ADC_ATTEN_DB_0); - adc2_get_raw(channel2_, ADC_WIDTH_MAX_SOC_BITS, &raw0); + adc2_config_channel_atten(this->channel2_, ADC_ATTEN_DB_0); + adc2_get_raw(this->channel2_, ADC_WIDTH_MAX_SOC_BITS, &raw0); } } } @@ -221,10 +235,10 @@ float ADCSensor::sample() { return NAN; } - uint32_t mv12 = esp_adc_cal_raw_to_voltage(raw12, &cal_characteristics_[(int32_t) ADC_ATTEN_DB_12_COMPAT]); - uint32_t mv6 = esp_adc_cal_raw_to_voltage(raw6, &cal_characteristics_[(int32_t) ADC_ATTEN_DB_6]); - uint32_t mv2 = esp_adc_cal_raw_to_voltage(raw2, &cal_characteristics_[(int32_t) ADC_ATTEN_DB_2_5]); - uint32_t mv0 = esp_adc_cal_raw_to_voltage(raw0, &cal_characteristics_[(int32_t) ADC_ATTEN_DB_0]); + uint32_t mv12 = esp_adc_cal_raw_to_voltage(raw12, &this->cal_characteristics_[(int32_t) ADC_ATTEN_DB_12_COMPAT]); + uint32_t mv6 = esp_adc_cal_raw_to_voltage(raw6, &this->cal_characteristics_[(int32_t) ADC_ATTEN_DB_6]); + uint32_t mv2 = esp_adc_cal_raw_to_voltage(raw2, &this->cal_characteristics_[(int32_t) ADC_ATTEN_DB_2_5]); + uint32_t mv0 = esp_adc_cal_raw_to_voltage(raw0, &this->cal_characteristics_[(int32_t) ADC_ATTEN_DB_0]); // Contribution of each value, in range 0-2048 (12 bit ADC) or 0-4096 (13 bit ADC) uint32_t c12 = std::min(raw12, ADC_HALF); @@ -246,8 +260,11 @@ float ADCSensor::sample() { adc_set_temp_sensor_enabled(true); delay(1); adc_select_input(4); - - int32_t raw = adc_read(); + uint32_t raw = 0; + for (uint8_t sample = 0; sample < this->sample_count_; sample++) { + raw += adc_read(); + } + raw = (raw + (this->sample_count_ >> 1)) / this->sample_count_; // NOLINT(clang-analyzer-core.DivideZero) adc_set_temp_sensor_enabled(false); if (this->output_raw_) { return raw; @@ -268,7 +285,11 @@ float ADCSensor::sample() { adc_gpio_init(pin); adc_select_input(pin - 26); - int32_t raw = adc_read(); + uint32_t raw = 0; + for (uint8_t sample = 0; sample < this->sample_count_; sample++) { + raw += adc_read(); + } + raw = (raw + (this->sample_count_ >> 1)) / this->sample_count_; // NOLINT(clang-analyzer-core.DivideZero) #ifdef CYW43_USES_VSYS_PIN if (pin == PICO_VSYS_PIN) { @@ -276,7 +297,7 @@ float ADCSensor::sample() { } #endif // CYW43_USES_VSYS_PIN - if (output_raw_) { + if (this->output_raw_) { return raw; } float coeff = pin == PICO_VSYS_PIN ? 3.0 : 1.0; @@ -287,10 +308,19 @@ float ADCSensor::sample() { #ifdef USE_LIBRETINY float ADCSensor::sample() { - if (output_raw_) { - return analogRead(this->pin_->get_pin()); // NOLINT + uint32_t raw = 0; + if (this->output_raw_) { + for (uint8_t sample = 0; sample < this->sample_count_; sample++) { + raw += analogRead(this->pin_->get_pin()); // NOLINT + } + raw = (raw + (this->sample_count_ >> 1)) / this->sample_count_; // NOLINT(clang-analyzer-core.DivideZero) + return raw; } - return analogReadVoltage(this->pin_->get_pin()) / 1000.0f; // NOLINT + for (uint8_t sample = 0; sample < this->sample_count_; sample++) { + raw += analogReadVoltage(this->pin_->get_pin()); // NOLINT + } + raw = (raw + (this->sample_count_ >> 1)) / this->sample_count_; // NOLINT(clang-analyzer-core.DivideZero) + return raw / 1000.0f; } #endif // USE_LIBRETINY diff --git a/esphome/components/adc/adc_sensor.h b/esphome/components/adc/adc_sensor.h index d99c4bc75b..b697d6dd7e 100644 --- a/esphome/components/adc/adc_sensor.h +++ b/esphome/components/adc/adc_sensor.h @@ -33,16 +33,16 @@ class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage public: #ifdef USE_ESP32 /// Set the attenuation for this pin. Only available on the ESP32. - void set_attenuation(adc_atten_t attenuation) { attenuation_ = attenuation; } + void set_attenuation(adc_atten_t attenuation) { this->attenuation_ = attenuation; } void set_channel1(adc1_channel_t channel) { - channel1_ = channel; - channel2_ = ADC2_CHANNEL_MAX; + this->channel1_ = channel; + this->channel2_ = ADC2_CHANNEL_MAX; } void set_channel2(adc2_channel_t channel) { - channel2_ = channel; - channel1_ = ADC1_CHANNEL_MAX; + this->channel2_ = channel; + this->channel1_ = ADC1_CHANNEL_MAX; } - void set_autorange(bool autorange) { autorange_ = autorange; } + void set_autorange(bool autorange) { this->autorange_ = autorange; } #endif /// Update ADC values @@ -53,7 +53,8 @@ class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage /// `HARDWARE_LATE` setup priority float get_setup_priority() const override; void set_pin(InternalGPIOPin *pin) { this->pin_ = pin; } - void set_output_raw(bool output_raw) { output_raw_ = output_raw; } + void set_output_raw(bool output_raw) { this->output_raw_ = output_raw; } + void set_sample_count(uint8_t sample_count); float sample() override; #ifdef USE_ESP8266 @@ -61,12 +62,13 @@ class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage #endif #ifdef USE_RP2040 - void set_is_temperature() { is_temperature_ = true; } + void set_is_temperature() { this->is_temperature_ = true; } #endif protected: InternalGPIOPin *pin_; bool output_raw_{false}; + uint8_t sample_count_{1}; #ifdef USE_RP2040 bool is_temperature_{false}; diff --git a/esphome/components/adc/sensor.py b/esphome/components/adc/sensor.py index 4cf3d52802..59ea9e184c 100644 --- a/esphome/components/adc/sensor.py +++ b/esphome/components/adc/sensor.py @@ -29,6 +29,8 @@ _LOGGER = logging.getLogger(__name__) AUTO_LOAD = ["voltage_sampler"] +CONF_SAMPLES = "samples" + _attenuation = cv.enum(ATTENUATION_MODES, lower=True) @@ -37,6 +39,10 @@ def validate_config(config): if config[CONF_RAW] and config.get(CONF_ATTENUATION, None) == "auto": raise cv.Invalid("Automatic attenuation cannot be used when raw output is set") + if config.get(CONF_ATTENUATION, None) == "auto" and config.get(CONF_SAMPLES, 1) > 1: + raise cv.Invalid( + "Automatic attenuation cannot be used when multisampling is set" + ) if config.get(CONF_ATTENUATION) == "11db": _LOGGER.warning( "`attenuation: 11db` is deprecated, use `attenuation: 12db` instead" @@ -81,6 +87,7 @@ CONFIG_SCHEMA = cv.All( cv.SplitDefault(CONF_ATTENUATION, esp32="0db"): cv.All( cv.only_on_esp32, _attenuation ), + cv.Optional(CONF_SAMPLES, default=1): cv.int_range(min=1, max=255), } ) .extend(cv.polling_component_schema("60s")), @@ -104,6 +111,7 @@ async def to_code(config): cg.add(var.set_pin(pin)) cg.add(var.set_output_raw(config[CONF_RAW])) + cg.add(var.set_sample_count(config[CONF_SAMPLES])) if attenuation := config.get(CONF_ATTENUATION): if attenuation == "auto": From 7c243dafb35decec2869f6eed38b7f9ef64611c7 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 16 May 2024 14:11:54 +1200 Subject: [PATCH 1459/2101] [core] Fix some extends cases (#6748) --- esphome/components/substitutions/__init__.py | 4 +-- esphome/config_helpers.py | 27 +++++++++++++++++--- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/esphome/components/substitutions/__init__.py b/esphome/components/substitutions/__init__.py index 2d3a79ccae..fa52200d46 100644 --- a/esphome/components/substitutions/__init__.py +++ b/esphome/components/substitutions/__init__.py @@ -4,7 +4,7 @@ import esphome.config_validation as cv from esphome import core from esphome.const import CONF_SUBSTITUTIONS, VALID_SUBSTITUTIONS_CHARACTERS from esphome.yaml_util import ESPHomeDataBase, make_data_base -from esphome.config_helpers import merge_config +from esphome.config_helpers import merge_config, Extend, Remove CODEOWNERS = ["@esphome/core"] _LOGGER = logging.getLogger(__name__) @@ -105,7 +105,7 @@ def _substitute_item(substitutions, item, path, ignore_missing): sub = _expand_substitutions(substitutions, item, path, ignore_missing) if sub != item: return sub - elif isinstance(item, core.Lambda): + elif isinstance(item, (core.Lambda, Extend, Remove)): sub = _expand_substitutions(substitutions, item.value, path, ignore_missing) if sub != item: item.value = sub diff --git a/esphome/config_helpers.py b/esphome/config_helpers.py index 7b47e097c8..b5e0b26143 100644 --- a/esphome/config_helpers.py +++ b/esphome/config_helpers.py @@ -8,6 +8,9 @@ class Extend: def __str__(self): return f"!extend {self.value}" + def __repr__(self): + return f"Extend({self.value})" + def __eq__(self, b): """ Check if two Extend objects contain the same ID. @@ -24,6 +27,9 @@ class Remove: def __str__(self): return f"!remove {self.value}" + def __repr__(self): + return f"Remove({self.value})" + def __eq__(self, b): """ Check if two Remove objects contain the same ID. @@ -50,14 +56,19 @@ def merge_config(full_old, full_new): return new res = old.copy() ids = { - v[CONF_ID]: i + v_id: i for i, v in enumerate(res) - if CONF_ID in v and isinstance(v[CONF_ID], str) + if (v_id := v.get(CONF_ID)) and isinstance(v_id, str) } + extend_ids = { + v_id.value: i + for i, v in enumerate(res) + if (v_id := v.get(CONF_ID)) and isinstance(v_id, Extend) + } + ids_to_delete = [] for v in new: - if CONF_ID in v: - new_id = v[CONF_ID] + if new_id := v.get(CONF_ID): if isinstance(new_id, Extend): new_id = new_id.value if new_id in ids: @@ -69,6 +80,14 @@ def merge_config(full_old, full_new): if new_id in ids: ids_to_delete.append(ids[new_id]) continue + elif ( + new_id in extend_ids + ): # When a package is extending a non-packaged item + extend_res = res[extend_ids[new_id]] + extend_res[CONF_ID] = new_id + new_v = merge(v, extend_res) + res[extend_ids[new_id]] = new_v + continue else: ids[new_id] = len(res) res.append(v) From 0bb2773c646fc3b0d1fe65a73e8e98dd57523e95 Mon Sep 17 00:00:00 2001 From: Faidon Liambotis Date: Thu, 16 May 2024 05:49:40 +0300 Subject: [PATCH 1460/2101] Port wifi_component_esp32_arduino from tcpip_adapter to esp_netif (#6476) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- .../wifi/wifi_component_esp32_arduino.cpp | 329 ++++++++++-------- .../wifi/wifi_component_esp_idf.cpp | 60 ++-- 2 files changed, 219 insertions(+), 170 deletions(-) diff --git a/esphome/components/wifi/wifi_component_esp32_arduino.cpp b/esphome/components/wifi/wifi_component_esp32_arduino.cpp index 44d77b4eed..ef7a624cd5 100644 --- a/esphome/components/wifi/wifi_component_esp32_arduino.cpp +++ b/esphome/components/wifi/wifi_component_esp32_arduino.cpp @@ -2,6 +2,7 @@ #ifdef USE_ESP32_FRAMEWORK_ARDUINO +#include #include #include @@ -24,45 +25,73 @@ namespace wifi { static const char *const TAG = "wifi_esp32"; +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) +#endif // USE_WIFI_AP + static bool s_sta_connecting = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) +void WiFiComponent::wifi_pre_setup_() { + auto f = std::bind(&WiFiComponent::wifi_event_callback_, this, std::placeholders::_1, std::placeholders::_2); + WiFi.onEvent(f); + WiFi.persistent(false); + // Make sure WiFi is in clean state before anything starts + this->wifi_mode_(false, false); +} + bool WiFiComponent::wifi_mode_(optional sta, optional ap) { - uint8_t current_mode = WiFiClass::getMode(); - bool current_sta = current_mode & 0b01; - bool current_ap = current_mode & 0b10; - bool enable_sta = sta.value_or(current_sta); - bool enable_ap = ap.value_or(current_ap); - if (current_sta == enable_sta && current_ap == enable_ap) + wifi_mode_t current_mode = WiFiClass::getMode(); + bool current_sta = current_mode == WIFI_MODE_STA || current_mode == WIFI_MODE_APSTA; + bool current_ap = current_mode == WIFI_MODE_AP || current_mode == WIFI_MODE_APSTA; + + bool set_sta = sta.value_or(current_sta); + bool set_ap = ap.value_or(current_ap); + + wifi_mode_t set_mode; + if (set_sta && set_ap) { + set_mode = WIFI_MODE_APSTA; + } else if (set_sta && !set_ap) { + set_mode = WIFI_MODE_STA; + } else if (!set_sta && set_ap) { + set_mode = WIFI_MODE_AP; + } else { + set_mode = WIFI_MODE_NULL; + } + + if (current_mode == set_mode) return true; - if (enable_sta && !current_sta) { + if (set_sta && !current_sta) { ESP_LOGV(TAG, "Enabling STA."); - } else if (!enable_sta && current_sta) { + } else if (!set_sta && current_sta) { ESP_LOGV(TAG, "Disabling STA."); } - if (enable_ap && !current_ap) { + if (set_ap && !current_ap) { ESP_LOGV(TAG, "Enabling AP."); - } else if (!enable_ap && current_ap) { + } else if (!set_ap && current_ap) { ESP_LOGV(TAG, "Disabling AP."); } - uint8_t mode = 0; - if (enable_sta) - mode |= 0b01; - if (enable_ap) - mode |= 0b10; - bool ret = WiFiClass::mode(static_cast(mode)); + bool ret = WiFiClass::mode(set_mode); if (!ret) { ESP_LOGW(TAG, "Setting WiFi mode failed!"); + return false; } + // WiFiClass::mode above calls esp_netif_create_default_wifi_sta() and + // esp_netif_create_default_wifi_ap(), which creates the interfaces. + if (set_sta) + s_sta_netif = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"); +#ifdef USE_WIFI_AP + if (set_ap) + s_ap_netif = esp_netif_get_handle_from_ifkey("WIFI_AP_DEF"); +#endif + return ret; } -bool WiFiComponent::wifi_apply_output_power_(float output_power) { - int8_t val = static_cast(output_power * 4); - return esp_wifi_set_max_tx_power(val) == ESP_OK; -} + bool WiFiComponent::wifi_sta_pre_setup_() { if (!this->wifi_mode_(true, {})) return false; @@ -71,6 +100,12 @@ bool WiFiComponent::wifi_sta_pre_setup_() { delay(10); return true; } + +bool WiFiComponent::wifi_apply_output_power_(float output_power) { + int8_t val = static_cast(output_power * 4); + return esp_wifi_set_max_tx_power(val) == ESP_OK; +} + bool WiFiComponent::wifi_apply_power_save_() { wifi_ps_type_t power_save; switch (this->power_save_) { @@ -87,99 +122,7 @@ bool WiFiComponent::wifi_apply_power_save_() { } return esp_wifi_set_ps(power_save) == ESP_OK; } -bool WiFiComponent::wifi_sta_ip_config_(optional manual_ip) { - // enable STA - if (!this->wifi_mode_(true, {})) - return false; - tcpip_adapter_dhcp_status_t dhcp_status; - tcpip_adapter_dhcpc_get_status(TCPIP_ADAPTER_IF_STA, &dhcp_status); - if (!manual_ip.has_value()) { - // lwIP starts the SNTP client if it gets an SNTP server from DHCP. We don't need the time, and more importantly, - // the built-in SNTP client has a memory leak in certain situations. Disable this feature. - // https://github.com/esphome/issues/issues/2299 - sntp_servermode_dhcp(false); - - // Use DHCP client - if (dhcp_status != TCPIP_ADAPTER_DHCP_STARTED) { - esp_err_t err = tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA); - if (err != ESP_OK) { - ESP_LOGV(TAG, "Starting DHCP client failed! %d", err); - } - return err == ESP_OK; - } - return true; - } - - tcpip_adapter_ip_info_t info; - memset(&info, 0, sizeof(info)); - info.ip = manual_ip->static_ip; - info.gw = manual_ip->gateway; - info.netmask = manual_ip->subnet; - - esp_err_t dhcp_stop_ret = tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA); - if (dhcp_stop_ret != ESP_OK && dhcp_stop_ret != ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED) { - ESP_LOGV(TAG, "Stopping DHCP client failed! %s", esp_err_to_name(dhcp_stop_ret)); - } - - esp_err_t wifi_set_info_ret = tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_STA, &info); - if (wifi_set_info_ret != ESP_OK) { - ESP_LOGV(TAG, "Setting manual IP info failed! %s", esp_err_to_name(wifi_set_info_ret)); - } - - ip_addr_t dns; -// TODO: is this needed? -#if LWIP_IPV6 - dns.type = IPADDR_TYPE_V4; -#endif /* LWIP_IPV6 */ - if (manual_ip->dns1.is_set()) { - dns = manual_ip->dns1; - dns_setserver(0, &dns); - } - if (manual_ip->dns2.is_set()) { - dns = manual_ip->dns2; - dns_setserver(1, &dns); - } - - return true; -} - -network::IPAddresses WiFiComponent::wifi_sta_ip_addresses() { - if (!this->has_sta()) - return {}; - network::IPAddresses addresses; - tcpip_adapter_ip_info_t ip; - esp_err_t err = tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &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 - ip6_addr_t ipv6; - err = tcpip_adapter_get_ip6_global(TCPIP_ADAPTER_IF_STA, &ipv6); - if (err != ESP_OK) { - ESP_LOGV(TAG, "esp_netif_get_ip6_gobal failed: %s", esp_err_to_name(err)); - } else { - addresses[1] = network::IPAddress(&ipv6); - } - err = tcpip_adapter_get_ip6_linklocal(TCPIP_ADAPTER_IF_STA, &ipv6); - if (err != ESP_OK) { - ESP_LOGV(TAG, "esp_netif_get_ip6_linklocal failed: %s", esp_err_to_name(err)); - } else { - addresses[2] = network::IPAddress(&ipv6); - } -#endif /* USE_NETWORK_IPV6 */ - - return addresses; -} - -bool WiFiComponent::wifi_apply_hostname_() { - // setting is done in SYSTEM_EVENT_STA_START callback - return true; -} bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) { // enable STA if (!this->wifi_mode_(true, {})) @@ -233,19 +176,24 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) { wifi_config_t current_conf; esp_err_t err; - esp_wifi_get_config(WIFI_IF_STA, ¤t_conf); + err = esp_wifi_get_config(WIFI_IF_STA, ¤t_conf); + if (err != ERR_OK) { + ESP_LOGW(TAG, "esp_wifi_get_config failed: %s", esp_err_to_name(err)); + // can continue + } if (memcmp(¤t_conf, &conf, sizeof(wifi_config_t)) != 0) { // NOLINT err = esp_wifi_disconnect(); if (err != ESP_OK) { - ESP_LOGV(TAG, "esp_wifi_disconnect failed! %d", err); + ESP_LOGV(TAG, "esp_wifi_disconnect failed: %s", esp_err_to_name(err)); return false; } } err = esp_wifi_set_config(WIFI_IF_STA, &conf); if (err != ESP_OK) { - ESP_LOGV(TAG, "esp_wifi_set_config failed! %d", err); + ESP_LOGV(TAG, "esp_wifi_set_config failed: %s", esp_err_to_name(err)); + return false; } if (!this->wifi_sta_ip_config_(ap.get_manual_ip())) { @@ -304,12 +252,98 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) { err = esp_wifi_connect(); if (err != ESP_OK) { - ESP_LOGW(TAG, "esp_wifi_connect failed! %d", err); + ESP_LOGW(TAG, "esp_wifi_connect failed: %s", esp_err_to_name(err)); return false; } return true; } + +bool WiFiComponent::wifi_sta_ip_config_(optional manual_ip) { + // enable STA + if (!this->wifi_mode_(true, {})) + return false; + + esp_netif_dhcp_status_t dhcp_status; + esp_err_t err = esp_netif_dhcpc_get_status(s_sta_netif, &dhcp_status); + if (err != ESP_OK) { + ESP_LOGV(TAG, "esp_netif_dhcpc_get_status failed: %s", esp_err_to_name(err)); + return false; + } + + if (!manual_ip.has_value()) { + // lwIP starts the SNTP client if it gets an SNTP server from DHCP. We don't need the time, and more importantly, + // the built-in SNTP client has a memory leak in certain situations. Disable this feature. + // https://github.com/esphome/issues/issues/2299 + sntp_servermode_dhcp(false); + + // No manual IP is set; use DHCP client + if (dhcp_status != ESP_NETIF_DHCP_STARTED) { + err = esp_netif_dhcpc_start(s_sta_netif); + if (err != ESP_OK) { + ESP_LOGV(TAG, "Starting DHCP client failed! %d", err); + } + return err == ESP_OK; + } + return true; + } + + esp_netif_ip_info_t info; // struct of ip4_addr_t with ip, netmask, gw + info.ip = manual_ip->static_ip; + info.gw = manual_ip->gateway; + info.netmask = manual_ip->subnet; + err = esp_netif_dhcpc_stop(s_sta_netif); + if (err != ESP_OK && err != ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED) { + ESP_LOGV(TAG, "Stopping DHCP client failed! %s", esp_err_to_name(err)); + } + + err = esp_netif_set_ip_info(s_sta_netif, &info); + if (err != ESP_OK) { + ESP_LOGV(TAG, "Setting manual IP info failed! %s", esp_err_to_name(err)); + } + + esp_netif_dns_info_t dns; + if (manual_ip->dns1.is_set()) { + dns.ip = manual_ip->dns1; + esp_netif_set_dns_info(s_sta_netif, ESP_NETIF_DNS_MAIN, &dns); + } + if (manual_ip->dns2.is_set()) { + dns.ip = manual_ip->dns2; + esp_netif_set_dns_info(s_sta_netif, ESP_NETIF_DNS_BACKUP, &dns); + } + + return true; +} + +network::IPAddresses WiFiComponent::wifi_sta_ip_addresses() { + if (!this->has_sta()) + return {}; + network::IPAddresses addresses; + esp_netif_ip_info_t ip; + esp_err_t err = esp_netif_get_ip_info(s_sta_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(s_sta_netif, if_ip6s); + assert(count <= CONFIG_LWIP_IPV6_NUM_ADDRESSES); + for (int i = 0; i < count; i++) { + addresses[i + 1] = network::IPAddress(&if_ip6s[i]); + } +#endif /* USE_NETWORK_IPV6 */ + return addresses; +} + +bool WiFiComponent::wifi_apply_hostname_() { + // setting is done in SYSTEM_EVENT_STA_START callback + return true; +} const char *get_auth_mode_str(uint8_t mode) { switch (mode) { case WIFI_AUTH_OPEN: @@ -324,6 +358,12 @@ const char *get_auth_mode_str(uint8_t mode) { return "WPA/WPA2 PSK"; case WIFI_AUTH_WPA2_ENTERPRISE: return "WPA2 Enterprise"; + case WIFI_AUTH_WPA3_PSK: + return "WPA3 PSK"; + case WIFI_AUTH_WPA2_WPA3_PSK: + return "WPA2/WPA3 PSK"; + case WIFI_AUTH_WAPI_PSK: + return "WAPI PSK"; default: return "UNKNOWN"; } @@ -409,12 +449,16 @@ const char *get_disconnect_reason_str(uint8_t reason) { return "Handshake Failed"; case WIFI_REASON_CONNECTION_FAIL: return "Connection Failed"; + case WIFI_REASON_ROAMING: + return "Station Roaming"; case WIFI_REASON_UNSPECIFIED: default: return "Unspecified"; } } +void WiFiComponent::wifi_loop_() {} + #define ESPHOME_EVENT_ID_WIFI_READY ARDUINO_EVENT_WIFI_READY #define ESPHOME_EVENT_ID_WIFI_SCAN_DONE ARDUINO_EVENT_WIFI_SCAN_DONE #define ESPHOME_EVENT_ID_WIFI_STA_START ARDUINO_EVENT_WIFI_STA_START @@ -450,7 +494,11 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_ } case ESPHOME_EVENT_ID_WIFI_STA_START: { ESP_LOGV(TAG, "Event: WiFi STA start"); - tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, App.get_name().c_str()); + // apply hostname + esp_err_t err = esp_netif_set_hostname(s_sta_netif, App.get_name().c_str()); + if (err != ERR_OK) { + ESP_LOGW(TAG, "esp_netif_set_hostname failed: %s", esp_err_to_name(err)); + } break; } case ESPHOME_EVENT_ID_WIFI_STA_STOP: { @@ -573,22 +621,19 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_ break; } } -void WiFiComponent::wifi_pre_setup_() { - auto f = std::bind(&WiFiComponent::wifi_event_callback_, this, std::placeholders::_1, std::placeholders::_2); - WiFi.onEvent(f); - WiFi.persistent(false); - // Make sure WiFi is in clean state before anything starts - this->wifi_mode_(false, false); -} + WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() { auto status = WiFiClass::status(); if (status == WL_CONNECT_FAILED || status == WL_CONNECTION_LOST) { return WiFiSTAConnectStatus::ERROR_CONNECT_FAILED; - } else if (status == WL_NO_SSID_AVAIL) { + } + if (status == WL_NO_SSID_AVAIL) { return WiFiSTAConnectStatus::ERROR_NETWORK_NOT_FOUND; - } else if (s_sta_connecting) { + } + if (s_sta_connecting) { return WiFiSTAConnectStatus::CONNECTING; - } else if (status == WL_CONNECTED) { + } + if (status == WL_CONNECTED) { return WiFiSTAConnectStatus::CONNECTED; } return WiFiSTAConnectStatus::IDLE; @@ -638,8 +683,7 @@ bool WiFiComponent::wifi_ap_ip_config_(optional manual_ip) { if (!this->wifi_mode_({}, true)) return false; - tcpip_adapter_ip_info_t info; - memset(&info, 0, sizeof(info)); + esp_netif_ip_info_t info; if (manual_ip.has_value()) { info.ip = manual_ip->static_ip; info.gw = manual_ip->gateway; @@ -649,17 +693,16 @@ bool WiFiComponent::wifi_ap_ip_config_(optional manual_ip) { info.gw = network::IPAddress(192, 168, 4, 1); info.netmask = network::IPAddress(255, 255, 255, 0); } - tcpip_adapter_dhcp_status_t dhcp_status; - tcpip_adapter_dhcps_get_status(TCPIP_ADAPTER_IF_AP, &dhcp_status); - err = tcpip_adapter_dhcps_stop(TCPIP_ADAPTER_IF_AP); - if (err != ESP_OK) { - ESP_LOGV(TAG, "tcpip_adapter_dhcps_stop failed! %d", err); + + err = esp_netif_dhcpc_stop(s_ap_netif); + if (err != ESP_OK && err != ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED) { + ESP_LOGV(TAG, "esp_netif_dhcpc_stop failed: %s", esp_err_to_name(err)); return false; } - err = tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_AP, &info); + err = esp_netif_set_ip_info(s_ap_netif, &info); if (err != ESP_OK) { - ESP_LOGV(TAG, "tcpip_adapter_set_ip_info failed! %d", err); + ESP_LOGV(TAG, "esp_netif_set_ip_info failed! %d", err); return false; } @@ -672,17 +715,17 @@ bool WiFiComponent::wifi_ap_ip_config_(optional manual_ip) { start_address += 100; lease.end_ip = start_address; ESP_LOGV(TAG, "DHCP server IP lease end: %s", start_address.str().c_str()); - err = tcpip_adapter_dhcps_option(TCPIP_ADAPTER_OP_SET, TCPIP_ADAPTER_REQUESTED_IP_ADDRESS, &lease, sizeof(lease)); + err = esp_netif_dhcps_option(s_ap_netif, ESP_NETIF_OP_SET, ESP_NETIF_REQUESTED_IP_ADDRESS, &lease, sizeof(lease)); if (err != ESP_OK) { - ESP_LOGV(TAG, "tcpip_adapter_dhcps_option failed! %d", err); + ESP_LOGV(TAG, "esp_netif_dhcps_option failed! %d", err); return false; } - err = tcpip_adapter_dhcps_start(TCPIP_ADAPTER_IF_AP); + err = esp_netif_dhcps_start(s_ap_netif); if (err != ESP_OK) { - ESP_LOGV(TAG, "tcpip_adapter_dhcps_start failed! %d", err); + ESP_LOGV(TAG, "esp_netif_dhcps_start failed! %d", err); return false; } @@ -710,6 +753,7 @@ bool WiFiComponent::wifi_start_ap_(const WiFiAP &ap) { strncpy(reinterpret_cast(conf.ap.password), ap.get_password().c_str(), sizeof(conf.ap.password)); } + // pairwise cipher of SoftAP, group cipher will be derived using this. conf.ap.pairwise_cipher = WIFI_CIPHER_TYPE_CCMP; esp_err_t err = esp_wifi_set_config(WIFI_IF_AP, &conf); @@ -729,8 +773,8 @@ bool WiFiComponent::wifi_start_ap_(const WiFiAP &ap) { } network::IPAddress WiFiComponent::wifi_soft_ap_ip() { - tcpip_adapter_ip_info_t ip; - tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, &ip); + esp_netif_ip_info_t ip; + esp_netif_get_ip_info(s_ap_netif, &ip); return network::IPAddress(&ip.ip); } #endif // USE_WIFI_AP @@ -752,7 +796,6 @@ int32_t WiFiComponent::wifi_channel_() { return WiFi.channel(); } network::IPAddress WiFiComponent::wifi_subnet_mask_() { return network::IPAddress(WiFi.subnetMask()); } network::IPAddress WiFiComponent::wifi_gateway_ip_() { return network::IPAddress(WiFi.gatewayIP()); } network::IPAddress WiFiComponent::wifi_dns_ip_(int num) { return network::IPAddress(WiFi.dnsIP(num)); } -void WiFiComponent::wifi_loop_() {} } // namespace wifi } // namespace esphome diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index 5489a5d249..bc575e6a2d 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -2,18 +2,18 @@ #ifdef USE_ESP_IDF -#include -#include -#include +#include +#include #include #include #include -#include -#include +#include +#include +#include +#include #include #include -#include #ifdef USE_WIFI_WPA2_EAP #include #endif @@ -22,13 +22,14 @@ #include "dhcpserver/dhcpserver.h" #endif // USE_WIFI_AP -#include "lwip/err.h" +#include "lwip/apps/sntp.h" #include "lwip/dns.h" +#include "lwip/err.h" +#include "esphome/core/application.h" +#include "esphome/core/hal.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" -#include "esphome/core/hal.h" -#include "esphome/core/application.h" #include "esphome/core/util.h" namespace esphome { @@ -196,8 +197,8 @@ bool WiFiComponent::wifi_mode_(optional sta, optional ap) { bool current_sta = current_mode == WIFI_MODE_STA || current_mode == WIFI_MODE_APSTA; bool current_ap = current_mode == WIFI_MODE_AP || current_mode == WIFI_MODE_APSTA; - bool set_sta = sta.has_value() ? *sta : current_sta; - bool set_ap = ap.has_value() ? *ap : current_ap; + bool set_sta = sta.value_or(current_sta); + bool set_ap = ap.value_or(current_ap); wifi_mode_t set_mode; if (set_sta && set_ap) { @@ -438,6 +439,11 @@ bool WiFiComponent::wifi_sta_ip_config_(optional manual_ip) { } if (!manual_ip.has_value()) { + // lwIP starts the SNTP client if it gets an SNTP server from DHCP. We don't need the time, and more importantly, + // the built-in SNTP client has a memory leak in certain situations. Disable this feature. + // https://github.com/esphome/issues/issues/2299 + sntp_servermode_dhcp(false); + // No manual IP is set; use DHCP client if (dhcp_status != ESP_NETIF_DHCP_STARTED) { err = esp_netif_dhcpc_start(s_sta_netif); @@ -455,13 +461,12 @@ bool WiFiComponent::wifi_sta_ip_config_(optional manual_ip) { info.netmask = manual_ip->subnet; err = esp_netif_dhcpc_stop(s_sta_netif); if (err != ESP_OK && err != ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED) { - ESP_LOGV(TAG, "esp_netif_dhcpc_stop failed: %s", esp_err_to_name(err)); - return false; + ESP_LOGV(TAG, "Stopping DHCP client failed! %s", esp_err_to_name(err)); } + err = esp_netif_set_ip_info(s_sta_netif, &info); if (err != ESP_OK) { - ESP_LOGV(TAG, "esp_netif_set_ip_info failed: %s", esp_err_to_name(err)); - return false; + ESP_LOGV(TAG, "Setting manual IP info failed! %s", esp_err_to_name(err)); } esp_netif_dns_info_t dns; @@ -795,7 +800,7 @@ bool WiFiComponent::wifi_scan_start_(bool passive) { return false; } - scan_done_ = false; + this->scan_done_ = false; return true; } @@ -818,13 +823,13 @@ bool WiFiComponent::wifi_ap_ip_config_(optional manual_ip) { info.netmask = network::IPAddress(255, 255, 255, 0); } - err = esp_netif_dhcpc_stop(s_sta_netif); + err = esp_netif_dhcpc_stop(s_ap_netif); if (err != ESP_OK && err != ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED) { ESP_LOGV(TAG, "esp_netif_dhcpc_stop failed: %s", esp_err_to_name(err)); return false; } - err = esp_netif_set_ip_info(s_sta_netif, &info); + err = esp_netif_set_ip_info(s_ap_netif, &info); if (err != ESP_OK) { ESP_LOGV(TAG, "esp_netif_set_ip_info failed! %d", err); return false; @@ -839,14 +844,14 @@ bool WiFiComponent::wifi_ap_ip_config_(optional manual_ip) { start_address += 100; lease.end_ip = start_address; ESP_LOGV(TAG, "DHCP server IP lease end: %s", start_address.str().c_str()); - err = esp_netif_dhcps_option(s_sta_netif, ESP_NETIF_OP_SET, ESP_NETIF_REQUESTED_IP_ADDRESS, &lease, sizeof(lease)); + err = esp_netif_dhcps_option(s_ap_netif, ESP_NETIF_OP_SET, ESP_NETIF_REQUESTED_IP_ADDRESS, &lease, sizeof(lease)); if (err != ESP_OK) { ESP_LOGV(TAG, "esp_netif_dhcps_option failed! %d", err); return false; } - err = esp_netif_dhcps_start(s_sta_netif); + err = esp_netif_dhcps_start(s_ap_netif); if (err != ESP_OK) { ESP_LOGV(TAG, "esp_netif_dhcps_start failed! %d", err); @@ -893,25 +898,26 @@ bool WiFiComponent::wifi_start_ap_(const WiFiAP &ap) { return true; } -#endif // USE_WIFI_AP network::IPAddress WiFiComponent::wifi_soft_ap_ip() { esp_netif_ip_info_t ip; - esp_netif_get_ip_info(s_sta_netif, &ip); + esp_netif_get_ip_info(s_ap_netif, &ip); return network::IPAddress(&ip.ip); } +#endif // USE_WIFI_AP + bool WiFiComponent::wifi_disconnect_() { return esp_wifi_disconnect(); } bssid_t WiFiComponent::wifi_bssid() { + bssid_t bssid{}; wifi_ap_record_t info; esp_err_t err = esp_wifi_sta_get_ap_info(&info); - bssid_t res{}; if (err != ESP_OK) { ESP_LOGW(TAG, "esp_wifi_sta_get_ap_info failed: %s", esp_err_to_name(err)); - return res; + return bssid; } - std::copy(info.bssid, info.bssid + 6, res.begin()); - return res; + std::copy(info.bssid, info.bssid + 6, bssid.begin()); + return bssid; } std::string WiFiComponent::wifi_ssid() { wifi_ap_record_t info{}; @@ -969,4 +975,4 @@ network::IPAddress WiFiComponent::wifi_dns_ip_(int num) { } // namespace wifi } // namespace esphome -#endif +#endif // USE_ESP_IDF From 98cb6555df956bf73f456eaeb74e5fa0399554e4 Mon Sep 17 00:00:00 2001 From: Anton Viktorov Date: Thu, 16 May 2024 05:22:40 +0200 Subject: [PATCH 1461/2101] SPI and I2C for ENS160 (#6369) --- CODEOWNERS | 5 +- esphome/components/ens160/__init__.py | 1 - esphome/components/ens160/sensor.py | 90 ++----------------- esphome/components/ens160_base/__init__.py | 78 ++++++++++++++++ .../ens160_base.cpp} | 7 +- .../ens160.h => ens160_base/ens160_base.h} | 12 ++- esphome/components/ens160_i2c/__init__.py | 0 esphome/components/ens160_i2c/ens160_i2c.cpp | 32 +++++++ esphome/components/ens160_i2c/ens160_i2c.h | 19 ++++ esphome/components/ens160_i2c/sensor.py | 22 +++++ esphome/components/ens160_spi/__init__.py | 0 esphome/components/ens160_spi/ens160_spi.cpp | 59 ++++++++++++ esphome/components/ens160_spi/ens160_spi.h | 22 +++++ esphome/components/ens160_spi/sensor.py | 22 +++++ .../components/ens160/test.esp32-c3-idf.yaml | 13 --- tests/components/ens160/test.esp32-c3.yaml | 13 --- tests/components/ens160/test.esp32-idf.yaml | 13 --- tests/components/ens160/test.esp32.yaml | 13 --- tests/components/ens160/test.esp8266.yaml | 13 --- tests/components/ens160/test.rp2040.yaml | 13 --- tests/components/ens160_i2c/common.yaml | 15 ++++ .../ens160_i2c/test.esp32-c3-idf.yaml | 5 ++ .../components/ens160_i2c/test.esp32-c3.yaml | 5 ++ .../components/ens160_i2c/test.esp32-idf.yaml | 5 ++ tests/components/ens160_i2c/test.esp32.yaml | 5 ++ tests/components/ens160_i2c/test.esp8266.yaml | 5 ++ tests/components/ens160_i2c/test.rp2040.yaml | 5 ++ tests/components/ens160_spi/common.yaml | 17 ++++ .../ens160_spi/test.esp32-c3-idf.yaml | 7 ++ .../components/ens160_spi/test.esp32-c3.yaml | 7 ++ .../components/ens160_spi/test.esp32-idf.yaml | 7 ++ tests/components/ens160_spi/test.esp32.yaml | 7 ++ tests/components/ens160_spi/test.esp8266.yaml | 7 ++ tests/components/ens160_spi/test.rp2040.yaml | 7 ++ tests/test3.1.yaml | 7 -- 35 files changed, 378 insertions(+), 180 deletions(-) create mode 100644 esphome/components/ens160_base/__init__.py rename esphome/components/{ens160/ens160.cpp => ens160_base/ens160_base.cpp} (99%) rename esphome/components/{ens160/ens160.h => ens160_base/ens160_base.h} (76%) create mode 100644 esphome/components/ens160_i2c/__init__.py create mode 100644 esphome/components/ens160_i2c/ens160_i2c.cpp create mode 100644 esphome/components/ens160_i2c/ens160_i2c.h create mode 100644 esphome/components/ens160_i2c/sensor.py create mode 100644 esphome/components/ens160_spi/__init__.py create mode 100644 esphome/components/ens160_spi/ens160_spi.cpp create mode 100644 esphome/components/ens160_spi/ens160_spi.h create mode 100644 esphome/components/ens160_spi/sensor.py delete mode 100644 tests/components/ens160/test.esp32-c3-idf.yaml delete mode 100644 tests/components/ens160/test.esp32-c3.yaml delete mode 100644 tests/components/ens160/test.esp32-idf.yaml delete mode 100644 tests/components/ens160/test.esp32.yaml delete mode 100644 tests/components/ens160/test.esp8266.yaml delete mode 100644 tests/components/ens160/test.rp2040.yaml create mode 100644 tests/components/ens160_i2c/common.yaml create mode 100644 tests/components/ens160_i2c/test.esp32-c3-idf.yaml create mode 100644 tests/components/ens160_i2c/test.esp32-c3.yaml create mode 100644 tests/components/ens160_i2c/test.esp32-idf.yaml create mode 100644 tests/components/ens160_i2c/test.esp32.yaml create mode 100644 tests/components/ens160_i2c/test.esp8266.yaml create mode 100644 tests/components/ens160_i2c/test.rp2040.yaml create mode 100644 tests/components/ens160_spi/common.yaml create mode 100644 tests/components/ens160_spi/test.esp32-c3-idf.yaml create mode 100644 tests/components/ens160_spi/test.esp32-c3.yaml create mode 100644 tests/components/ens160_spi/test.esp32-idf.yaml create mode 100644 tests/components/ens160_spi/test.esp32.yaml create mode 100644 tests/components/ens160_spi/test.esp8266.yaml create mode 100644 tests/components/ens160_spi/test.rp2040.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 65ea3b1683..4227cdb06d 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -111,7 +111,10 @@ esphome/components/ee895/* @Stock-M esphome/components/ektf2232/touchscreen/* @jesserockz esphome/components/emc2101/* @ellull esphome/components/emmeti/* @E440QF -esphome/components/ens160/* @vincentscode +esphome/components/ens160/* @latonita +esphome/components/ens160_base/* @latonita @vincentscode +esphome/components/ens160_i2c/* @latonita +esphome/components/ens160_spi/* @latonita esphome/components/ens210/* @itn3rd77 esphome/components/esp32/* @esphome/core esphome/components/esp32_ble/* @Rapsssito @jesserockz diff --git a/esphome/components/ens160/__init__.py b/esphome/components/ens160/__init__.py index d26770a89d..e69de29bb2 100644 --- a/esphome/components/ens160/__init__.py +++ b/esphome/components/ens160/__init__.py @@ -1 +0,0 @@ -CODEOWNERS = ["@vincentscode"] diff --git a/esphome/components/ens160/sensor.py b/esphome/components/ens160/sensor.py index 6572c4e397..f666b530b3 100644 --- a/esphome/components/ens160/sensor.py +++ b/esphome/components/ens160/sensor.py @@ -1,87 +1,7 @@ -import esphome.codegen as cg import esphome.config_validation as cv -from esphome.components import i2c, sensor -from esphome.const import ( - CONF_COMPENSATION, - CONF_ECO2, - CONF_HUMIDITY, - CONF_ID, - CONF_TEMPERATURE, - CONF_TVOC, - DEVICE_CLASS_AQI, - DEVICE_CLASS_CARBON_DIOXIDE, - DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS_PARTS, - ICON_CHEMICAL_WEAPON, - ICON_MOLECULE_CO2, - ICON_RADIATOR, - STATE_CLASS_MEASUREMENT, - UNIT_PARTS_PER_BILLION, - UNIT_PARTS_PER_MILLION, + +CODEOWNERS = ["@latonita"] + +CONFIG_SCHEMA = CONFIG_SCHEMA = cv.invalid( + "The ens160 sensor component has been renamed to ens160_i2c." ) - -CODEOWNERS = ["@vincentscode"] -DEPENDENCIES = ["i2c"] - -ens160_ns = cg.esphome_ns.namespace("ens160") -ENS160Component = ens160_ns.class_( - "ENS160Component", cg.PollingComponent, i2c.I2CDevice, sensor.Sensor -) - -CONF_AQI = "aqi" -UNIT_INDEX = "index" - -CONFIG_SCHEMA = ( - cv.Schema( - { - cv.GenerateID(): cv.declare_id(ENS160Component), - cv.Required(CONF_ECO2): 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.Required(CONF_TVOC): sensor.sensor_schema( - unit_of_measurement=UNIT_PARTS_PER_BILLION, - icon=ICON_RADIATOR, - accuracy_decimals=0, - device_class=DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS_PARTS, - state_class=STATE_CLASS_MEASUREMENT, - ), - cv.Required(CONF_AQI): sensor.sensor_schema( - icon=ICON_CHEMICAL_WEAPON, - accuracy_decimals=0, - device_class=DEVICE_CLASS_AQI, - state_class=STATE_CLASS_MEASUREMENT, - ), - cv.Optional(CONF_COMPENSATION): cv.Schema( - { - cv.Required(CONF_TEMPERATURE): cv.use_id(sensor.Sensor), - cv.Required(CONF_HUMIDITY): cv.use_id(sensor.Sensor), - } - ), - } - ) - .extend(cv.polling_component_schema("60s")) - .extend(i2c.i2c_device_schema(0x53)) -) - - -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) - - sens = await sensor.new_sensor(config[CONF_ECO2]) - cg.add(var.set_co2(sens)) - sens = await sensor.new_sensor(config[CONF_TVOC]) - cg.add(var.set_tvoc(sens)) - sens = await sensor.new_sensor(config[CONF_AQI]) - cg.add(var.set_aqi(sens)) - - if CONF_COMPENSATION in config: - compensation_config = config[CONF_COMPENSATION] - sens = await cg.get_variable(compensation_config[CONF_TEMPERATURE]) - cg.add(var.set_temperature(sens)) - sens = await cg.get_variable(compensation_config[CONF_HUMIDITY]) - cg.add(var.set_humidity(sens)) diff --git a/esphome/components/ens160_base/__init__.py b/esphome/components/ens160_base/__init__.py new file mode 100644 index 0000000000..eb6d0880af --- /dev/null +++ b/esphome/components/ens160_base/__init__.py @@ -0,0 +1,78 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import sensor +from esphome.const import ( + CONF_COMPENSATION, + CONF_ECO2, + CONF_HUMIDITY, + CONF_ID, + CONF_TEMPERATURE, + CONF_TVOC, + DEVICE_CLASS_AQI, + DEVICE_CLASS_CARBON_DIOXIDE, + DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS_PARTS, + ICON_CHEMICAL_WEAPON, + ICON_MOLECULE_CO2, + ICON_RADIATOR, + STATE_CLASS_MEASUREMENT, + UNIT_PARTS_PER_BILLION, + UNIT_PARTS_PER_MILLION, +) + +CODEOWNERS = ["@vincentscode", "@latonita"] + +ens160_ns = cg.esphome_ns.namespace("ens160_base") + +CONF_AQI = "aqi" +UNIT_INDEX = "index" + +CONFIG_SCHEMA_BASE = cv.Schema( + { + cv.Required(CONF_ECO2): 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.Required(CONF_TVOC): sensor.sensor_schema( + unit_of_measurement=UNIT_PARTS_PER_BILLION, + icon=ICON_RADIATOR, + accuracy_decimals=0, + device_class=DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS_PARTS, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Required(CONF_AQI): sensor.sensor_schema( + icon=ICON_CHEMICAL_WEAPON, + accuracy_decimals=0, + device_class=DEVICE_CLASS_AQI, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_COMPENSATION): cv.Schema( + { + cv.Required(CONF_TEMPERATURE): cv.use_id(sensor.Sensor), + cv.Required(CONF_HUMIDITY): cv.use_id(sensor.Sensor), + } + ), + } +).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) + + sens = await sensor.new_sensor(config[CONF_ECO2]) + cg.add(var.set_co2(sens)) + sens = await sensor.new_sensor(config[CONF_TVOC]) + cg.add(var.set_tvoc(sens)) + sens = await sensor.new_sensor(config[CONF_AQI]) + cg.add(var.set_aqi(sens)) + + if compensation_config := config.get(CONF_COMPENSATION): + sens = await cg.get_variable(compensation_config[CONF_TEMPERATURE]) + cg.add(var.set_temperature(sens)) + sens = await cg.get_variable(compensation_config[CONF_HUMIDITY]) + cg.add(var.set_humidity(sens)) + + return var diff --git a/esphome/components/ens160/ens160.cpp b/esphome/components/ens160_base/ens160_base.cpp similarity index 99% rename from esphome/components/ens160/ens160.cpp rename to esphome/components/ens160_base/ens160_base.cpp index c7a6ccbb73..71082c58c2 100644 --- a/esphome/components/ens160/ens160.cpp +++ b/esphome/components/ens160_base/ens160_base.cpp @@ -5,12 +5,12 @@ // Implementation based on: // https://github.com/sciosense/ENS160_driver -#include "ens160.h" +#include "ens160_base.h" #include "esphome/core/log.h" #include "esphome/core/hal.h" namespace esphome { -namespace ens160 { +namespace ens160_base { static const char *const TAG = "ens160"; @@ -303,7 +303,6 @@ void ENS160Component::dump_config() { ESP_LOGI(TAG, "Firmware Version: %d.%d.%d", this->firmware_ver_major_, this->firmware_ver_minor_, this->firmware_ver_build_); - LOG_I2C_DEVICE(this); LOG_UPDATE_INTERVAL(this); LOG_SENSOR(" ", "CO2 Sensor:", this->co2_); LOG_SENSOR(" ", "TVOC Sensor:", this->tvoc_); @@ -317,5 +316,5 @@ void ENS160Component::dump_config() { } } -} // namespace ens160 +} // namespace ens160_base } // namespace esphome diff --git a/esphome/components/ens160/ens160.h b/esphome/components/ens160_base/ens160_base.h similarity index 76% rename from esphome/components/ens160/ens160.h rename to esphome/components/ens160_base/ens160_base.h index 88bc8e3501..729225a5ae 100644 --- a/esphome/components/ens160/ens160.h +++ b/esphome/components/ens160_base/ens160_base.h @@ -2,12 +2,11 @@ #include "esphome/core/component.h" #include "esphome/components/sensor/sensor.h" -#include "esphome/components/i2c/i2c.h" namespace esphome { -namespace ens160 { +namespace ens160_base { -class ENS160Component : public PollingComponent, public i2c::I2CDevice, public sensor::Sensor { +class ENS160Component : public PollingComponent, public sensor::Sensor { public: void set_co2(sensor::Sensor *co2) { co2_ = co2; } void set_tvoc(sensor::Sensor *tvoc) { tvoc_ = tvoc; } @@ -44,6 +43,11 @@ class ENS160Component : public PollingComponent, public i2c::I2CDevice, public s bool warming_up_{false}; bool initial_startup_{false}; + virtual bool read_byte(uint8_t a_register, uint8_t *data) = 0; + virtual bool write_byte(uint8_t a_register, uint8_t data) = 0; + virtual bool read_bytes(uint8_t a_register, uint8_t *data, size_t len) = 0; + virtual bool write_bytes(uint8_t a_register, uint8_t *data, size_t len) = 0; + uint8_t firmware_ver_major_{0}; uint8_t firmware_ver_minor_{0}; uint8_t firmware_ver_build_{0}; @@ -56,5 +60,5 @@ class ENS160Component : public PollingComponent, public i2c::I2CDevice, public s sensor::Sensor *temperature_{nullptr}; }; -} // namespace ens160 +} // namespace ens160_base } // namespace esphome diff --git a/esphome/components/ens160_i2c/__init__.py b/esphome/components/ens160_i2c/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/ens160_i2c/ens160_i2c.cpp b/esphome/components/ens160_i2c/ens160_i2c.cpp new file mode 100644 index 0000000000..7163a5ad6e --- /dev/null +++ b/esphome/components/ens160_i2c/ens160_i2c.cpp @@ -0,0 +1,32 @@ +#include +#include + +#include "ens160_i2c.h" +#include "esphome/components/i2c/i2c.h" +#include "../ens160_base/ens160_base.h" + +namespace esphome { +namespace ens160_i2c { + +static const char *const TAG = "ens160_i2c.sensor"; + +bool ENS160I2CComponent::read_byte(uint8_t a_register, uint8_t *data) { + return I2CDevice::read_byte(a_register, data); +}; +bool ENS160I2CComponent::write_byte(uint8_t a_register, uint8_t data) { + return I2CDevice::write_byte(a_register, data); +}; +bool ENS160I2CComponent::read_bytes(uint8_t a_register, uint8_t *data, size_t len) { + return I2CDevice::read_bytes(a_register, data, len); +}; +bool ENS160I2CComponent::write_bytes(uint8_t a_register, uint8_t *data, size_t len) { + return I2CDevice::write_bytes(a_register, data, len); +}; + +void ENS160I2CComponent::dump_config() { + ENS160Component::dump_config(); + LOG_I2C_DEVICE(this); +} + +} // namespace ens160_i2c +} // namespace esphome diff --git a/esphome/components/ens160_i2c/ens160_i2c.h b/esphome/components/ens160_i2c/ens160_i2c.h new file mode 100644 index 0000000000..2df32f27bf --- /dev/null +++ b/esphome/components/ens160_i2c/ens160_i2c.h @@ -0,0 +1,19 @@ +#pragma once + +#include "esphome/components/ens160_base/ens160_base.h" +#include "esphome/components/i2c/i2c.h" + +namespace esphome { +namespace ens160_i2c { + +class ENS160I2CComponent : public esphome::ens160_base::ENS160Component, public i2c::I2CDevice { + void dump_config() override; + + bool read_byte(uint8_t a_register, uint8_t *data) override; + bool write_byte(uint8_t a_register, uint8_t data) override; + bool read_bytes(uint8_t a_register, uint8_t *data, size_t len) override; + bool write_bytes(uint8_t a_register, uint8_t *data, size_t len) override; +}; + +} // namespace ens160_i2c +} // namespace esphome diff --git a/esphome/components/ens160_i2c/sensor.py b/esphome/components/ens160_i2c/sensor.py new file mode 100644 index 0000000000..96cbbaa7e9 --- /dev/null +++ b/esphome/components/ens160_i2c/sensor.py @@ -0,0 +1,22 @@ +import esphome.codegen as cg +from esphome.components import i2c +from ..ens160_base import to_code_base, cv, CONFIG_SCHEMA_BASE + +AUTO_LOAD = ["ens160_base"] +CODEOWNERS = ["@latonita"] +DEPENDENCIES = ["i2c"] + +ens160_ns = cg.esphome_ns.namespace("ens160_i2c") + +ENS160I2CComponent = ens160_ns.class_( + "ENS160I2CComponent", cg.PollingComponent, i2c.I2CDevice +) + +CONFIG_SCHEMA = CONFIG_SCHEMA_BASE.extend( + i2c.i2c_device_schema(default_address=0x52) +).extend({cv.GenerateID(): cv.declare_id(ENS160I2CComponent)}) + + +async def to_code(config): + var = await to_code_base(config) + await i2c.register_i2c_device(var, config) diff --git a/esphome/components/ens160_spi/__init__.py b/esphome/components/ens160_spi/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/ens160_spi/ens160_spi.cpp b/esphome/components/ens160_spi/ens160_spi.cpp new file mode 100644 index 0000000000..fba2fdf0e4 --- /dev/null +++ b/esphome/components/ens160_spi/ens160_spi.cpp @@ -0,0 +1,59 @@ +#include +#include + +#include "ens160_spi.h" +#include + +namespace esphome { +namespace ens160_spi { + +static const char *const TAG = "ens160_spi.sensor"; + +inline uint8_t reg_read(uint8_t reg) { return (reg << 1) | 0x01; } + +inline uint8_t reg_write(uint8_t reg) { return (reg << 1) & 0xFE; } + +void ENS160SPIComponent::setup() { + this->spi_setup(); + ENS160Component::setup(); +}; + +void ENS160SPIComponent::dump_config() { + ENS160Component::dump_config(); + LOG_PIN(" CS Pin: ", this->cs_); +} + +bool ENS160SPIComponent::read_byte(uint8_t a_register, uint8_t *data) { + this->enable(); + this->transfer_byte(reg_read(a_register)); + *data = this->transfer_byte(0); + this->disable(); + return true; +} + +bool ENS160SPIComponent::write_byte(uint8_t a_register, uint8_t data) { + this->enable(); + this->transfer_byte(reg_write(a_register)); + this->transfer_byte(data); + this->disable(); + return true; +} + +bool ENS160SPIComponent::read_bytes(uint8_t a_register, uint8_t *data, size_t len) { + this->enable(); + this->transfer_byte(reg_read(a_register)); + this->read_array(data, len); + this->disable(); + return true; +} + +bool ENS160SPIComponent::write_bytes(uint8_t a_register, uint8_t *data, size_t len) { + this->enable(); + this->transfer_byte(reg_write(a_register)); + this->transfer_array(data, len); + this->disable(); + return true; +} + +} // namespace ens160_spi +} // namespace esphome diff --git a/esphome/components/ens160_spi/ens160_spi.h b/esphome/components/ens160_spi/ens160_spi.h new file mode 100644 index 0000000000..3371f37ffd --- /dev/null +++ b/esphome/components/ens160_spi/ens160_spi.h @@ -0,0 +1,22 @@ +#pragma once + +#include "esphome/components/ens160_base/ens160_base.h" +#include "esphome/components/spi/spi.h" + +namespace esphome { +namespace ens160_spi { + +class ENS160SPIComponent : public esphome::ens160_base::ENS160Component, + public spi::SPIDevice { + void setup() override; + void dump_config() override; + + bool read_byte(uint8_t a_register, uint8_t *data) override; + bool write_byte(uint8_t a_register, uint8_t data) override; + bool read_bytes(uint8_t a_register, uint8_t *data, size_t len) override; + bool write_bytes(uint8_t a_register, uint8_t *data, size_t len) override; +}; + +} // namespace ens160_spi +} // namespace esphome diff --git a/esphome/components/ens160_spi/sensor.py b/esphome/components/ens160_spi/sensor.py new file mode 100644 index 0000000000..552697fe1b --- /dev/null +++ b/esphome/components/ens160_spi/sensor.py @@ -0,0 +1,22 @@ +import esphome.codegen as cg +from esphome.components import spi +from ..ens160_base import to_code_base, cv, CONFIG_SCHEMA_BASE + +AUTO_LOAD = ["ens160_base"] +CODEOWNERS = ["@latonita"] +DEPENDENCIES = ["spi"] + +ens160_spi_ns = cg.esphome_ns.namespace("ens160_spi") + +ENS160SPIComponent = ens160_spi_ns.class_( + "ENS160SPIComponent", cg.PollingComponent, spi.SPIDevice +) + +CONFIG_SCHEMA = CONFIG_SCHEMA_BASE.extend(spi.spi_device_schema()).extend( + {cv.GenerateID(): cv.declare_id(ENS160SPIComponent)} +) + + +async def to_code(config): + var = await to_code_base(config) + await spi.register_spi_device(var, config) diff --git a/tests/components/ens160/test.esp32-c3-idf.yaml b/tests/components/ens160/test.esp32-c3-idf.yaml deleted file mode 100644 index 29f48e812f..0000000000 --- a/tests/components/ens160/test.esp32-c3-idf.yaml +++ /dev/null @@ -1,13 +0,0 @@ -i2c: - - id: i2c_ens160 - scl: 5 - sda: 4 - -sensor: - - platform: ens160 - eco2: - name: ENS160 eCO2 - tvoc: - name: ENS160 Total Volatile Organic Compounds - aqi: - name: ENS160 Air Quality Index diff --git a/tests/components/ens160/test.esp32-c3.yaml b/tests/components/ens160/test.esp32-c3.yaml deleted file mode 100644 index 29f48e812f..0000000000 --- a/tests/components/ens160/test.esp32-c3.yaml +++ /dev/null @@ -1,13 +0,0 @@ -i2c: - - id: i2c_ens160 - scl: 5 - sda: 4 - -sensor: - - platform: ens160 - eco2: - name: ENS160 eCO2 - tvoc: - name: ENS160 Total Volatile Organic Compounds - aqi: - name: ENS160 Air Quality Index diff --git a/tests/components/ens160/test.esp32-idf.yaml b/tests/components/ens160/test.esp32-idf.yaml deleted file mode 100644 index 23f7674aef..0000000000 --- a/tests/components/ens160/test.esp32-idf.yaml +++ /dev/null @@ -1,13 +0,0 @@ -i2c: - - id: i2c_ens160 - scl: 16 - sda: 17 - -sensor: - - platform: ens160 - eco2: - name: ENS160 eCO2 - tvoc: - name: ENS160 Total Volatile Organic Compounds - aqi: - name: ENS160 Air Quality Index diff --git a/tests/components/ens160/test.esp32.yaml b/tests/components/ens160/test.esp32.yaml deleted file mode 100644 index 23f7674aef..0000000000 --- a/tests/components/ens160/test.esp32.yaml +++ /dev/null @@ -1,13 +0,0 @@ -i2c: - - id: i2c_ens160 - scl: 16 - sda: 17 - -sensor: - - platform: ens160 - eco2: - name: ENS160 eCO2 - tvoc: - name: ENS160 Total Volatile Organic Compounds - aqi: - name: ENS160 Air Quality Index diff --git a/tests/components/ens160/test.esp8266.yaml b/tests/components/ens160/test.esp8266.yaml deleted file mode 100644 index 29f48e812f..0000000000 --- a/tests/components/ens160/test.esp8266.yaml +++ /dev/null @@ -1,13 +0,0 @@ -i2c: - - id: i2c_ens160 - scl: 5 - sda: 4 - -sensor: - - platform: ens160 - eco2: - name: ENS160 eCO2 - tvoc: - name: ENS160 Total Volatile Organic Compounds - aqi: - name: ENS160 Air Quality Index diff --git a/tests/components/ens160/test.rp2040.yaml b/tests/components/ens160/test.rp2040.yaml deleted file mode 100644 index 29f48e812f..0000000000 --- a/tests/components/ens160/test.rp2040.yaml +++ /dev/null @@ -1,13 +0,0 @@ -i2c: - - id: i2c_ens160 - scl: 5 - sda: 4 - -sensor: - - platform: ens160 - eco2: - name: ENS160 eCO2 - tvoc: - name: ENS160 Total Volatile Organic Compounds - aqi: - name: ENS160 Air Quality Index diff --git a/tests/components/ens160_i2c/common.yaml b/tests/components/ens160_i2c/common.yaml new file mode 100644 index 0000000000..39a5b35067 --- /dev/null +++ b/tests/components/ens160_i2c/common.yaml @@ -0,0 +1,15 @@ +i2c: + - id: i2c_ens160 + scl: ${scl_pin} + sda: ${sda_pin} + +sensor: + - platform: ens160_i2c + i2c_id: i2c_ens160 + address: 0x53 + eco2: + name: "ENS160 eCO2" + tvoc: + name: "ENS160 Total Volatile Organic Compounds" + aqi: + name: "ENS160 Air Quality Index" diff --git a/tests/components/ens160_i2c/test.esp32-c3-idf.yaml b/tests/components/ens160_i2c/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/ens160_i2c/test.esp32-c3-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/ens160_i2c/test.esp32-c3.yaml b/tests/components/ens160_i2c/test.esp32-c3.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/ens160_i2c/test.esp32-c3.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/ens160_i2c/test.esp32-idf.yaml b/tests/components/ens160_i2c/test.esp32-idf.yaml new file mode 100644 index 0000000000..63c3bd6afd --- /dev/null +++ b/tests/components/ens160_i2c/test.esp32-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO16 + sda_pin: GPIO17 + +<<: !include common.yaml diff --git a/tests/components/ens160_i2c/test.esp32.yaml b/tests/components/ens160_i2c/test.esp32.yaml new file mode 100644 index 0000000000..63c3bd6afd --- /dev/null +++ b/tests/components/ens160_i2c/test.esp32.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO16 + sda_pin: GPIO17 + +<<: !include common.yaml diff --git a/tests/components/ens160_i2c/test.esp8266.yaml b/tests/components/ens160_i2c/test.esp8266.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/ens160_i2c/test.esp8266.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/ens160_i2c/test.rp2040.yaml b/tests/components/ens160_i2c/test.rp2040.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/ens160_i2c/test.rp2040.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/ens160_spi/common.yaml b/tests/components/ens160_spi/common.yaml new file mode 100644 index 0000000000..7250ead228 --- /dev/null +++ b/tests/components/ens160_spi/common.yaml @@ -0,0 +1,17 @@ +spi: + - id: spi_ens160 + clk_pin: ${clk_pin} + mosi_pin: ${mosi_pin} + miso_pin: ${miso_pin} + +sensor: + - platform: ens160_spi + spi_id: spi_ens160 + cs_pin: ${cs_pin} + eco2: + name: "ENS160 eCO2" + tvoc: + name: "ENS160 Total Volatile Organic Compounds" + aqi: + name: "ENS160 Air Quality Index" + diff --git a/tests/components/ens160_spi/test.esp32-c3-idf.yaml b/tests/components/ens160_spi/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..2415ba5dc6 --- /dev/null +++ b/tests/components/ens160_spi/test.esp32-c3-idf.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO6 + mosi_pin: GPIO7 + miso_pin: GPIO5 + cs_pin: GPIO8 + +<<: !include common.yaml diff --git a/tests/components/ens160_spi/test.esp32-c3.yaml b/tests/components/ens160_spi/test.esp32-c3.yaml new file mode 100644 index 0000000000..2415ba5dc6 --- /dev/null +++ b/tests/components/ens160_spi/test.esp32-c3.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO6 + mosi_pin: GPIO7 + miso_pin: GPIO5 + cs_pin: GPIO8 + +<<: !include common.yaml diff --git a/tests/components/ens160_spi/test.esp32-idf.yaml b/tests/components/ens160_spi/test.esp32-idf.yaml new file mode 100644 index 0000000000..54e027a614 --- /dev/null +++ b/tests/components/ens160_spi/test.esp32-idf.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO16 + mosi_pin: GPIO17 + miso_pin: GPIO15 + cs_pin: GPIO5 + +<<: !include common.yaml diff --git a/tests/components/ens160_spi/test.esp32.yaml b/tests/components/ens160_spi/test.esp32.yaml new file mode 100644 index 0000000000..54e027a614 --- /dev/null +++ b/tests/components/ens160_spi/test.esp32.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO16 + mosi_pin: GPIO17 + miso_pin: GPIO15 + cs_pin: GPIO5 + +<<: !include common.yaml diff --git a/tests/components/ens160_spi/test.esp8266.yaml b/tests/components/ens160_spi/test.esp8266.yaml new file mode 100644 index 0000000000..dbd158d030 --- /dev/null +++ b/tests/components/ens160_spi/test.esp8266.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO14 + mosi_pin: GPIO13 + miso_pin: GPIO12 + cs_pin: GPIO15 + +<<: !include common.yaml diff --git a/tests/components/ens160_spi/test.rp2040.yaml b/tests/components/ens160_spi/test.rp2040.yaml new file mode 100644 index 0000000000..f6c3f1eeca --- /dev/null +++ b/tests/components/ens160_spi/test.rp2040.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO2 + mosi_pin: GPIO3 + miso_pin: GPIO4 + cs_pin: GPIO5 + +<<: !include common.yaml diff --git a/tests/test3.1.yaml b/tests/test3.1.yaml index 18d92289cd..a7d8dcb3f4 100644 --- a/tests/test3.1.yaml +++ b/tests/test3.1.yaml @@ -245,13 +245,6 @@ sensor: name: "ADE7953 Reactive Power B" update_interval: 1s - - platform: ens160 - eco2: - name: "ENS160 eCO2" - tvoc: - name: "ENS160 Total Volatile Organic Compounds" - aqi: - name: "ENS160 Air Quality Index" - platform: tmp102 name: TMP102 Temperature - platform: hm3301 From 996f71c03c2822c7fba5c761b1ab07ef3b119a0c Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Wed, 15 May 2024 23:40:21 -0500 Subject: [PATCH 1462/2101] Fix wifi compile error on IDF 5.1+ (#6756) --- esphome/components/wifi/wifi_component.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index f4a44b03a4..2f34f2b05b 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -3,8 +3,12 @@ #include #ifdef USE_ESP_IDF +#if (ESP_IDF_VERSION_MAJOR >= 5 && ESP_IDF_VERSION_MINOR >= 1) +#include +#else #include #endif +#endif #if defined(USE_ESP32) || defined(USE_ESP_IDF) #include From 034c196ad80a8ec4d1ba806bec3a2c87679a6477 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 16 May 2024 16:46:16 +1200 Subject: [PATCH 1463/2101] [core] Update some coroutine priorities (#6755) --- esphome/components/datetime/__init__.py | 2 +- esphome/components/number/__init__.py | 2 +- esphome/components/ota/__init__.py | 2 +- esphome/components/select/__init__.py | 2 +- esphome/components/sensor/__init__.py | 2 +- esphome/components/template/datetime/__init__.py | 2 -- esphome/components/text/__init__.py | 2 +- 7 files changed, 6 insertions(+), 8 deletions(-) diff --git a/esphome/components/datetime/__init__.py b/esphome/components/datetime/__init__.py index 3d08e4a6d0..262f1e2315 100644 --- a/esphome/components/datetime/__init__.py +++ b/esphome/components/datetime/__init__.py @@ -156,7 +156,7 @@ async def new_datetime(config, *args): return var -@coroutine_with_priority(40.0) +@coroutine_with_priority(100.0) async def to_code(config): cg.add_define("USE_DATETIME") cg.add_global(datetime_ns.using) diff --git a/esphome/components/number/__init__.py b/esphome/components/number/__init__.py index 6d7ec97c90..8c3b15d22d 100644 --- a/esphome/components/number/__init__.py +++ b/esphome/components/number/__init__.py @@ -293,7 +293,7 @@ async def number_in_range_to_code(config, condition_id, template_arg, args): return var -@coroutine_with_priority(40.0) +@coroutine_with_priority(100.0) async def to_code(config): cg.add_define("USE_NUMBER") cg.add_global(number_ns.using) diff --git a/esphome/components/ota/__init__.py b/esphome/components/ota/__init__.py index 728d36f3fa..3d2956931c 100644 --- a/esphome/components/ota/__init__.py +++ b/esphome/components/ota/__init__.py @@ -76,7 +76,7 @@ BASE_OTA_SCHEMA = cv.Schema( ) -@coroutine_with_priority(50.0) +@coroutine_with_priority(51.0) async def to_code(config): cg.add_define("USE_OTA") diff --git a/esphome/components/select/__init__.py b/esphome/components/select/__init__.py index 7ad14f2440..1d234d5617 100644 --- a/esphome/components/select/__init__.py +++ b/esphome/components/select/__init__.py @@ -113,7 +113,7 @@ async def new_select(config, *, options: list[str]): return var -@coroutine_with_priority(40.0) +@coroutine_with_priority(100.0) async def to_code(config): cg.add_define("USE_SELECT") cg.add_global(select_ns.using) diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index ece232e1a6..ef5c4cc645 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -912,7 +912,7 @@ def _lstsq(a, b): return _mat_dot(_mat_dot(x, a_t), b) -@coroutine_with_priority(40.0) +@coroutine_with_priority(100.0) async def to_code(config): cg.add_define("USE_SENSOR") cg.add_global(sensor_ns.using) diff --git a/esphome/components/template/datetime/__init__.py b/esphome/components/template/datetime/__init__.py index 0c9447116f..746ab8a6f3 100644 --- a/esphome/components/template/datetime/__init__.py +++ b/esphome/components/template/datetime/__init__.py @@ -17,7 +17,6 @@ from esphome.const import ( CONF_YEAR, ) -from esphome.core import coroutine_with_priority from .. import template_ns CODEOWNERS = ["@rfdarter"] @@ -100,7 +99,6 @@ CONFIG_SCHEMA = cv.All( ) -@coroutine_with_priority(-100.0) async def to_code(config): var = await datetime.new_datetime(config) diff --git a/esphome/components/text/__init__.py b/esphome/components/text/__init__.py index c0140ff082..4ca055a730 100644 --- a/esphome/components/text/__init__.py +++ b/esphome/components/text/__init__.py @@ -108,7 +108,7 @@ async def new_text( return var -@coroutine_with_priority(40.0) +@coroutine_with_priority(100.0) async def to_code(config): cg.add_define("USE_TEXT") cg.add_global(text_ns.using) From b06e0746f55010434a7b4622a85ee8ef3aaf4cb2 Mon Sep 17 00:00:00 2001 From: Anton Viktorov Date: Thu, 16 May 2024 06:50:28 +0200 Subject: [PATCH 1464/2101] INA228/INA229, INA238/INA239, INA237 power/energy/charge monitor (I2C, SPI) (#6138) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- CODEOWNERS | 3 + esphome/components/ina2xx_base/__init__.py | 255 ++++++++ .../components/ina2xx_base/ina2xx_base.cpp | 604 ++++++++++++++++++ esphome/components/ina2xx_base/ina2xx_base.h | 253 ++++++++ esphome/components/ina2xx_i2c/__init__.py | 0 esphome/components/ina2xx_i2c/ina2xx_i2c.cpp | 39 ++ esphome/components/ina2xx_i2c/ina2xx_i2c.h | 21 + esphome/components/ina2xx_i2c/sensor.py | 34 + esphome/components/ina2xx_spi/__init__.py | 0 esphome/components/ina2xx_spi/ina2xx_spi.cpp | 38 ++ esphome/components/ina2xx_spi/ina2xx_spi.h | 22 + esphome/components/ina2xx_spi/sensor.py | 33 + tests/components/ina2xx_i2c/common.yaml | 20 + .../ina2xx_i2c/test.esp32-c3-idf.yaml | 5 + .../components/ina2xx_i2c/test.esp32-c3.yaml | 5 + .../components/ina2xx_i2c/test.esp32-idf.yaml | 5 + tests/components/ina2xx_i2c/test.esp32.yaml | 5 + tests/components/ina2xx_i2c/test.esp8266.yaml | 5 + tests/components/ina2xx_i2c/test.rp2040.yaml | 5 + tests/components/ina2xx_spi/common.yaml | 21 + .../ina2xx_spi/test.esp32-c3-idf.yaml | 7 + .../components/ina2xx_spi/test.esp32-c3.yaml | 7 + .../components/ina2xx_spi/test.esp32-idf.yaml | 7 + tests/components/ina2xx_spi/test.esp32.yaml | 7 + tests/components/ina2xx_spi/test.esp8266.yaml | 7 + tests/components/ina2xx_spi/test.rp2040.yaml | 7 + 26 files changed, 1415 insertions(+) create mode 100644 esphome/components/ina2xx_base/__init__.py create mode 100644 esphome/components/ina2xx_base/ina2xx_base.cpp create mode 100644 esphome/components/ina2xx_base/ina2xx_base.h create mode 100644 esphome/components/ina2xx_i2c/__init__.py create mode 100644 esphome/components/ina2xx_i2c/ina2xx_i2c.cpp create mode 100644 esphome/components/ina2xx_i2c/ina2xx_i2c.h create mode 100644 esphome/components/ina2xx_i2c/sensor.py create mode 100644 esphome/components/ina2xx_spi/__init__.py create mode 100644 esphome/components/ina2xx_spi/ina2xx_spi.cpp create mode 100644 esphome/components/ina2xx_spi/ina2xx_spi.h create mode 100644 esphome/components/ina2xx_spi/sensor.py create mode 100644 tests/components/ina2xx_i2c/common.yaml create mode 100644 tests/components/ina2xx_i2c/test.esp32-c3-idf.yaml create mode 100644 tests/components/ina2xx_i2c/test.esp32-c3.yaml create mode 100644 tests/components/ina2xx_i2c/test.esp32-idf.yaml create mode 100644 tests/components/ina2xx_i2c/test.esp32.yaml create mode 100644 tests/components/ina2xx_i2c/test.esp8266.yaml create mode 100644 tests/components/ina2xx_i2c/test.rp2040.yaml create mode 100644 tests/components/ina2xx_spi/common.yaml create mode 100644 tests/components/ina2xx_spi/test.esp32-c3-idf.yaml create mode 100644 tests/components/ina2xx_spi/test.esp32-c3.yaml create mode 100644 tests/components/ina2xx_spi/test.esp32-idf.yaml create mode 100644 tests/components/ina2xx_spi/test.esp32.yaml create mode 100644 tests/components/ina2xx_spi/test.esp8266.yaml create mode 100644 tests/components/ina2xx_spi/test.rp2040.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 4227cdb06d..d97207941f 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -180,6 +180,9 @@ esphome/components/improv_base/* @esphome/core esphome/components/improv_serial/* @esphome/core esphome/components/ina226/* @Sergio303 @latonita esphome/components/ina260/* @mreditor97 +esphome/components/ina2xx_base/* @latonita +esphome/components/ina2xx_i2c/* @latonita +esphome/components/ina2xx_spi/* @latonita esphome/components/inkbird_ibsth1_mini/* @fkirill esphome/components/inkplate6/* @jesserockz esphome/components/integration/* @OttoWinter diff --git a/esphome/components/ina2xx_base/__init__.py b/esphome/components/ina2xx_base/__init__.py new file mode 100644 index 0000000000..35b5baa83e --- /dev/null +++ b/esphome/components/ina2xx_base/__init__.py @@ -0,0 +1,255 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import sensor +from esphome.const import ( + CONF_BUS_VOLTAGE, + CONF_CURRENT, + CONF_ENERGY, + CONF_MAX_CURRENT, + CONF_MODEL, + CONF_NAME, + CONF_POWER, + CONF_SHUNT_RESISTANCE, + CONF_SHUNT_VOLTAGE, + CONF_TEMPERATURE, + DEVICE_CLASS_CURRENT, + DEVICE_CLASS_ENERGY, + DEVICE_CLASS_POWER, + DEVICE_CLASS_TEMPERATURE, + DEVICE_CLASS_VOLTAGE, + STATE_CLASS_MEASUREMENT, + UNIT_AMPERE, + UNIT_CELSIUS, + UNIT_VOLT, + UNIT_WATT_HOURS, + UNIT_WATT, +) + +CODEOWNERS = ["@latonita"] + +CONF_ADC_AVERAGING = "adc_averaging" +CONF_ADC_RANGE = "adc_range" +CONF_ADC_TIME = "adc_time" +CONF_CHARGE = "charge" +CONF_CHARGE_COULOMBS = "charge_coulombs" +CONF_ENERGY_JOULES = "energy_joules" +CONF_TEMPERATURE_COEFFICIENT = "temperature_coefficient" +UNIT_AMPERE_HOURS = "Ah" +UNIT_COULOMB = "C" +UNIT_JOULE = "J" +UNIT_MILLIVOLT = "mV" + +ina2xx_base_ns = cg.esphome_ns.namespace("ina2xx_base") +INA2XX = ina2xx_base_ns.class_("INA2XX", cg.PollingComponent) + +AdcTime = ina2xx_base_ns.enum("AdcTime") +ADC_TIMES = { + 50: AdcTime.ADC_TIME_50US, + 84: AdcTime.ADC_TIME_84US, + 150: AdcTime.ADC_TIME_150US, + 280: AdcTime.ADC_TIME_280US, + 540: AdcTime.ADC_TIME_540US, + 1052: AdcTime.ADC_TIME_1052US, + 2074: AdcTime.ADC_TIME_2074US, + 4120: AdcTime.ADC_TIME_4120US, +} + +AdcAvgSamples = ina2xx_base_ns.enum("AdcAvgSamples") +ADC_SAMPLES = { + 1: AdcAvgSamples.ADC_AVG_SAMPLES_1, + 4: AdcAvgSamples.ADC_AVG_SAMPLES_4, + 16: AdcAvgSamples.ADC_AVG_SAMPLES_16, + 64: AdcAvgSamples.ADC_AVG_SAMPLES_64, + 128: AdcAvgSamples.ADC_AVG_SAMPLES_128, + 256: AdcAvgSamples.ADC_AVG_SAMPLES_256, + 512: AdcAvgSamples.ADC_AVG_SAMPLES_512, + 1024: AdcAvgSamples.ADC_AVG_SAMPLES_1024, +} + +SENSOR_MODEL_OPTIONS = { + CONF_ENERGY: ["INA228", "INA229"], + CONF_ENERGY_JOULES: ["INA228", "INA229"], + CONF_CHARGE: ["INA228", "INA229"], + CONF_CHARGE_COULOMBS: ["INA228", "INA229"], +} + + +def validate_model_config(config): + model = config[CONF_MODEL] + + for key in config: + if key in SENSOR_MODEL_OPTIONS: + if model not in SENSOR_MODEL_OPTIONS[key]: + raise cv.Invalid( + f"Device model '{model}' does not support '{key}' sensor" + ) + + tempco = config[CONF_TEMPERATURE_COEFFICIENT] + if tempco > 0 and model not in ["INA228", "INA229"]: + raise cv.Invalid( + f"Device model '{model}' does not support temperature coefficient" + ) + + return config + + +def validate_adc_time(value): + value = cv.positive_time_period_microseconds(value).total_microseconds + return cv.enum(ADC_TIMES, int=True)(value) + + +INA2XX_SCHEMA = cv.Schema( + { + cv.Required(CONF_SHUNT_RESISTANCE): cv.All(cv.resistance, cv.Range(min=0.0)), + cv.Required(CONF_MAX_CURRENT): cv.All(cv.current, cv.Range(min=0.0)), + cv.Optional(CONF_ADC_RANGE, default=0): cv.int_range(min=0, max=1), + cv.Optional(CONF_ADC_TIME, default="4120 us"): cv.Any( + validate_adc_time, + { + cv.Optional(CONF_BUS_VOLTAGE, default="4120 us"): validate_adc_time, + cv.Optional(CONF_SHUNT_VOLTAGE, default="4120 us"): validate_adc_time, + cv.Optional(CONF_TEMPERATURE, default="4120 us"): validate_adc_time, + }, + ), + cv.Optional(CONF_ADC_AVERAGING, default=128): cv.enum(ADC_SAMPLES, int=True), + cv.Optional(CONF_TEMPERATURE_COEFFICIENT, default=0): cv.int_range( + min=0, max=16383 + ), + cv.Optional(CONF_SHUNT_VOLTAGE): cv.maybe_simple_value( + sensor.sensor_schema( + unit_of_measurement=UNIT_MILLIVOLT, + accuracy_decimals=5, + device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, + ), + key=CONF_NAME, + ), + cv.Optional(CONF_BUS_VOLTAGE): cv.maybe_simple_value( + sensor.sensor_schema( + unit_of_measurement=UNIT_VOLT, + accuracy_decimals=5, + device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, + ), + key=CONF_NAME, + ), + cv.Optional(CONF_TEMPERATURE): cv.maybe_simple_value( + sensor.sensor_schema( + unit_of_measurement=UNIT_CELSIUS, + accuracy_decimals=5, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + ), + key=CONF_NAME, + ), + cv.Optional(CONF_CURRENT): cv.maybe_simple_value( + sensor.sensor_schema( + unit_of_measurement=UNIT_AMPERE, + accuracy_decimals=8, + device_class=DEVICE_CLASS_CURRENT, + state_class=STATE_CLASS_MEASUREMENT, + ), + key=CONF_NAME, + ), + cv.Optional(CONF_POWER): cv.maybe_simple_value( + sensor.sensor_schema( + unit_of_measurement=UNIT_WATT, + accuracy_decimals=6, + device_class=DEVICE_CLASS_POWER, + state_class=STATE_CLASS_MEASUREMENT, + ), + key=CONF_NAME, + ), + cv.Optional(CONF_ENERGY): cv.maybe_simple_value( + sensor.sensor_schema( + unit_of_measurement=UNIT_WATT_HOURS, + accuracy_decimals=8, + device_class=DEVICE_CLASS_ENERGY, + state_class=STATE_CLASS_MEASUREMENT, + ), + key=CONF_NAME, + ), + cv.Optional(CONF_ENERGY_JOULES): cv.maybe_simple_value( + sensor.sensor_schema( + unit_of_measurement=UNIT_JOULE, + accuracy_decimals=8, + state_class=STATE_CLASS_MEASUREMENT, + ), + key=CONF_NAME, + ), + cv.Optional(CONF_CHARGE): cv.maybe_simple_value( + sensor.sensor_schema( + unit_of_measurement=UNIT_AMPERE_HOURS, + accuracy_decimals=8, + state_class=STATE_CLASS_MEASUREMENT, + ), + key=CONF_NAME, + ), + cv.Optional(CONF_CHARGE_COULOMBS): cv.maybe_simple_value( + sensor.sensor_schema( + unit_of_measurement=UNIT_COULOMB, + accuracy_decimals=8, + state_class=STATE_CLASS_MEASUREMENT, + ), + key=CONF_NAME, + ), + } +).extend(cv.polling_component_schema("60s")) + + +async def setup_ina2xx(var, config): + await cg.register_component(var, config) + + cg.add(var.set_model(config[CONF_MODEL])) + + cg.add(var.set_shunt_resistance_ohm(config[CONF_SHUNT_RESISTANCE])) + cg.add(var.set_max_current_a(config[CONF_MAX_CURRENT])) + cg.add(var.set_adc_range(config[CONF_ADC_RANGE])) + cg.add(var.set_adc_avg_samples(config[CONF_ADC_AVERAGING])) + cg.add(var.set_shunt_tempco(config[CONF_TEMPERATURE_COEFFICIENT])) + + adc_time_config = config[CONF_ADC_TIME] + if isinstance(adc_time_config, dict): + cg.add(var.set_adc_time_bus_voltage(adc_time_config[CONF_BUS_VOLTAGE])) + cg.add(var.set_adc_time_shunt_voltage(adc_time_config[CONF_SHUNT_VOLTAGE])) + cg.add(var.set_adc_time_die_temperature(adc_time_config[CONF_TEMPERATURE])) + else: + cg.add(var.set_adc_time_bus_voltage(adc_time_config)) + cg.add(var.set_adc_time_shunt_voltage(adc_time_config)) + cg.add(var.set_adc_time_die_temperature(adc_time_config)) + + if conf := config.get(CONF_SHUNT_VOLTAGE): + sens = await sensor.new_sensor(conf) + cg.add(var.set_shunt_voltage_sensor(sens)) + + if conf := config.get(CONF_BUS_VOLTAGE): + sens = await sensor.new_sensor(conf) + cg.add(var.set_bus_voltage_sensor(sens)) + + if conf := config.get(CONF_TEMPERATURE): + sens = await sensor.new_sensor(conf) + cg.add(var.set_die_temperature_sensor(sens)) + + if conf := config.get(CONF_CURRENT): + sens = await sensor.new_sensor(conf) + cg.add(var.set_current_sensor(sens)) + + if conf := config.get(CONF_POWER): + sens = await sensor.new_sensor(conf) + cg.add(var.set_power_sensor(sens)) + + if conf := config.get(CONF_ENERGY): + sens = await sensor.new_sensor(conf) + cg.add(var.set_energy_sensor_wh(sens)) + + if conf := config.get(CONF_ENERGY_JOULES): + sens = await sensor.new_sensor(conf) + cg.add(var.set_energy_sensor_j(sens)) + + if conf := config.get(CONF_CHARGE): + sens = await sensor.new_sensor(conf) + cg.add(var.set_charge_sensor_ah(sens)) + + if conf := config.get(CONF_CHARGE_COULOMBS): + sens = await sensor.new_sensor(conf) + cg.add(var.set_charge_sensor_c(sens)) diff --git a/esphome/components/ina2xx_base/ina2xx_base.cpp b/esphome/components/ina2xx_base/ina2xx_base.cpp new file mode 100644 index 0000000000..5d947d0537 --- /dev/null +++ b/esphome/components/ina2xx_base/ina2xx_base.cpp @@ -0,0 +1,604 @@ +#include "ina2xx_base.h" +#include "esphome/core/log.h" +#include "esphome/core/hal.h" +#include "esphome/core/helpers.h" +#include +#include + +namespace esphome { +namespace ina2xx_base { + +static const char *const TAG = "ina2xx"; + +#define OKFAILED(b) ((b) ? "OK" : "FAILED") + +static const uint16_t ADC_TIMES[8] = {50, 84, 150, 280, 540, 1052, 2074, 4120}; +static const uint16_t ADC_SAMPLES[8] = {1, 4, 16, 64, 128, 256, 512, 1024}; + +static const char *get_device_name(INAModel model) { + switch (model) { + case INAModel::INA_228: + return "INA228"; + case INAModel::INA_229: + return "INA229"; + case INAModel::INA_238: + return "INA238"; + case INAModel::INA_239: + return "INA239"; + case INAModel::INA_237: + return "INA237"; + default: + return "UNKNOWN"; + } +}; + +static bool check_model_and_device_match(INAModel model, uint16_t dev_id) { + switch (model) { + case INAModel::INA_228: + return dev_id == 0x228; + case INAModel::INA_229: + return dev_id == 0x229; + case INAModel::INA_238: + return dev_id == 0x238; + case INAModel::INA_239: + return dev_id == 0x239; + case INAModel::INA_237: + return dev_id == 0x237; + default: + return false; + } +} + +void INA2XX::setup() { + ESP_LOGCONFIG(TAG, "Setting up INA2xx..."); + + if (!this->reset_config_()) { + ESP_LOGE(TAG, "Reset failed, check connection"); + this->mark_failed(); + return; + } + delay(2); + + if (!this->check_device_model_()) { + ESP_LOGE(TAG, "Device not supported or model selected improperly in yaml file"); + this->mark_failed(); + return; + } + delay(1); + + this->configure_adc_range_(); + delay(1); + + this->configure_adc_(); + delay(1); + + this->configure_shunt_(); + delay(1); + + this->configure_shunt_tempco_(); + delay(1); + + 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) { + ESP_LOGD(TAG, "Initiating new data collection"); + this->state_ = State::DATA_COLLECTION_1; + return; + } +} + +void INA2XX::loop() { + if (this->is_ready()) { + switch (this->state_) { + case State::NOT_INITIALIZED: + case State::IDLE: + break; + + case State::DATA_COLLECTION_1: + this->full_loop_is_okay_ = true; + + if (this->shunt_voltage_sensor_ != nullptr) { + float shunt_voltage{0}; + this->full_loop_is_okay_ &= this->read_shunt_voltage_mv_(shunt_voltage); + this->shunt_voltage_sensor_->publish_state(shunt_voltage); + } + this->state_ = State::DATA_COLLECTION_2; + break; + + case State::DATA_COLLECTION_2: + if (this->bus_voltage_sensor_ != nullptr) { + float bus_voltage{0}; + this->full_loop_is_okay_ &= this->read_bus_voltage_(bus_voltage); + this->bus_voltage_sensor_->publish_state(bus_voltage); + } + this->state_ = State::DATA_COLLECTION_3; + break; + + case State::DATA_COLLECTION_3: + if (this->die_temperature_sensor_ != nullptr) { + float die_temperature{0}; + this->full_loop_is_okay_ &= this->read_die_temp_c_(die_temperature); + this->die_temperature_sensor_->publish_state(die_temperature); + } + this->state_ = State::DATA_COLLECTION_4; + break; + + case State::DATA_COLLECTION_4: + if (this->current_sensor_ != nullptr) { + float current{0}; + this->full_loop_is_okay_ &= this->read_current_a_(current); + this->current_sensor_->publish_state(current); + } + this->state_ = State::DATA_COLLECTION_5; + break; + + case State::DATA_COLLECTION_5: + if (this->power_sensor_ != nullptr) { + float power{0}; + this->full_loop_is_okay_ &= this->read_power_w_(power); + this->power_sensor_->publish_state(power); + } + this->state_ = State::DATA_COLLECTION_6; + break; + + case State::DATA_COLLECTION_6: + if (this->ina_model_ == INAModel::INA_228 || this->ina_model_ == INAModel::INA_229) { + if (this->energy_sensor_j_ != nullptr || this->energy_sensor_wh_ != nullptr || + this->charge_sensor_c_ != nullptr || this->charge_sensor_ah_ != nullptr) { + this->read_diagnostics_and_act_(); + } + if (this->energy_sensor_j_ != nullptr || this->energy_sensor_wh_ != nullptr) { + double energy_j{0}, energy_wh{0}; + this->full_loop_is_okay_ &= this->read_energy_(energy_j, energy_wh); + if (this->energy_sensor_j_ != nullptr) + this->energy_sensor_j_->publish_state(energy_j); + if (this->energy_sensor_wh_ != nullptr) + this->energy_sensor_wh_->publish_state(energy_wh); + } + } + this->state_ = State::DATA_COLLECTION_7; + break; + + case State::DATA_COLLECTION_7: + if (this->ina_model_ == INAModel::INA_228 || this->ina_model_ == INAModel::INA_229) { + if (this->charge_sensor_c_ != nullptr || this->charge_sensor_ah_ != nullptr) { + double charge_c{0}, charge_ah{0}; + this->full_loop_is_okay_ &= this->read_charge_(charge_c, charge_ah); + if (this->charge_sensor_c_ != nullptr) + this->charge_sensor_c_->publish_state(charge_c); + if (this->charge_sensor_ah_ != nullptr) + this->charge_sensor_ah_->publish_state(charge_ah); + } + } + this->state_ = State::DATA_COLLECTION_8; + break; + + case State::DATA_COLLECTION_8: + if (this->full_loop_is_okay_) { + this->status_clear_warning(); + } else { + this->status_set_warning(); + } + this->state_ = State::IDLE; + break; + + default: + ESP_LOGW(TAG, "Unknown state of the component, might be due to memory corruption"); + break; + } + } +} + +void INA2XX::dump_config() { + ESP_LOGCONFIG(TAG, "INA2xx:"); + ESP_LOGCONFIG(TAG, " Device model = %s", get_device_name(this->ina_model_)); + + if (this->device_mismatch_) { + ESP_LOGE(TAG, " Device model mismatch. Found device with ID = %x. Please check your configuration.", + this->dev_id_); + } + if (this->is_failed()) { + ESP_LOGE(TAG, "Communication with INA2xx failed!"); + } + LOG_UPDATE_INTERVAL(this); + ESP_LOGCONFIG(TAG, " Shunt resistance = %f Ohm", this->shunt_resistance_ohm_); + ESP_LOGCONFIG(TAG, " Max current = %f A", this->max_current_a_); + ESP_LOGCONFIG(TAG, " Shunt temp coeff = %d ppm/°C", this->shunt_tempco_ppm_c_); + ESP_LOGCONFIG(TAG, " ADCRANGE = %d (%s)", (uint8_t) this->adc_range_, this->adc_range_ ? "±40.96 mV" : "±163.84 mV"); + ESP_LOGCONFIG(TAG, " CURRENT_LSB = %f", this->current_lsb_); + ESP_LOGCONFIG(TAG, " SHUNT_CAL = %d", this->shunt_cal_); + + ESP_LOGCONFIG(TAG, " ADC Samples = %d; ADC times: Bus = %d μs, Shunt = %d μs, Temp = %d μs", + ADC_SAMPLES[0b111 & (uint8_t) this->adc_avg_samples_], + ADC_TIMES[0b111 & (uint8_t) this->adc_time_bus_voltage_], + ADC_TIMES[0b111 & (uint8_t) this->adc_time_shunt_voltage_], + ADC_TIMES[0b111 & (uint8_t) this->adc_time_die_temperature_]); + + ESP_LOGCONFIG(TAG, " Device is %s", get_device_name(this->ina_model_)); + + LOG_SENSOR(" ", "Shunt Voltage", this->shunt_voltage_sensor_); + LOG_SENSOR(" ", "Bus Voltage", this->bus_voltage_sensor_); + LOG_SENSOR(" ", "Die Temperature", this->die_temperature_sensor_); + LOG_SENSOR(" ", "Current", this->current_sensor_); + LOG_SENSOR(" ", "Power", this->power_sensor_); + + if (this->ina_model_ == INAModel::INA_228 || this->ina_model_ == INAModel::INA_229) { + LOG_SENSOR(" ", "Energy J", this->energy_sensor_j_); + LOG_SENSOR(" ", "Energy Wh", this->energy_sensor_wh_); + LOG_SENSOR(" ", "Charge C", this->charge_sensor_c_); + LOG_SENSOR(" ", "Charge Ah", this->charge_sensor_ah_); + } +} + +bool INA2XX::reset_energy_counters() { + if (this->ina_model_ != INAModel::INA_228 && this->ina_model_ != INAModel::INA_229) { + return false; + } + ESP_LOGV(TAG, "reset_energy_counters"); + + ConfigurationRegister cfg{0}; + auto ret = this->read_unsigned_16_(RegisterMap::REG_CONFIG, cfg.raw_u16); + cfg.RSTACC = true; + cfg.ADCRANGE = this->adc_range_; + ret = ret && this->write_unsigned_16_(RegisterMap::REG_CONFIG, cfg.raw_u16); + + this->energy_overflows_count_ = 0; + this->charge_overflows_count_ = 0; + return ret; +} + +bool INA2XX::reset_config_() { + ESP_LOGV(TAG, "Reset"); + ConfigurationRegister cfg{0}; + cfg.RST = true; + return this->write_unsigned_16_(RegisterMap::REG_CONFIG, cfg.raw_u16); +} + +bool INA2XX::check_device_model_() { + constexpr uint16_t manufacturer_ti = 0x5449; // "TI" + + uint16_t manufacturer_id{0}, rev_id{0}; + this->read_unsigned_16_(RegisterMap::REG_MANUFACTURER_ID, manufacturer_id); + if (!this->read_unsigned_16_(RegisterMap::REG_DEVICE_ID, this->dev_id_)) { + this->dev_id_ = 0; + ESP_LOGV(TAG, "Can't read device ID"); + }; + rev_id = this->dev_id_ & 0x0F; + this->dev_id_ >>= 4; + ESP_LOGI(TAG, "Manufacturer: 0x%04X, Device ID: 0x%04X, Revision: %d", manufacturer_id, this->dev_id_, rev_id); + + if (manufacturer_id != manufacturer_ti) { + ESP_LOGE(TAG, "Manufacturer ID doesn't match original 0x5449"); + this->device_mismatch_ = true; + return false; + } + + if (this->dev_id_ == 0x228 || this->dev_id_ == 0x229) { + ESP_LOGI(TAG, "Supported device found: INA%x, 85-V, 20-Bit, Ultra-Precise Power/Energy/Charge Monitor", + this->dev_id_); + } else if (this->dev_id_ == 0x238 || this->dev_id_ == 0x239) { + ESP_LOGI(TAG, "Supported device found: INA%x, 85-V, 16-Bit, High-Precision Power Monitor", this->dev_id_); + } else if (this->dev_id_ == 0x0 || this->dev_id_ == 0xFF) { + ESP_LOGI(TAG, "We assume device is: INA237 85-V, 16-Bit, Precision Power Monitor"); + this->dev_id_ = 0x237; + } else { + ESP_LOGE(TAG, "Unknown device ID %x.", this->dev_id_); + this->device_mismatch_ = true; + return false; + } + + // Check user-selected model agains what we have found. Mark as failed if selected model != found model + if (!check_model_and_device_match(this->ina_model_, this->dev_id_)) { + ESP_LOGE(TAG, "Selected model %s doesn't match found device INA%x", get_device_name(this->ina_model_), + this->dev_id_); + this->device_mismatch_ = true; + return false; + } + + // setup device coefficients + if (this->ina_model_ == INAModel::INA_228 || this->ina_model_ == INAModel::INA_229) { + this->cfg_.vbus_lsb = 0.0001953125f; + this->cfg_.v_shunt_lsb_range0 = 0.0003125f; + this->cfg_.v_shunt_lsb_range1 = 0.000078125f; + this->cfg_.shunt_cal_scale = 13107.2f * 1000000.0f; + this->cfg_.current_lsb_scale_factor = -19; + this->cfg_.die_temp_lsb = 0.0078125f; + this->cfg_.power_coeff = 3.2f; + this->cfg_.energy_coeff = 16.0f * 3.2f; + } else { + this->cfg_.vbus_lsb = 0.0031250000f; + this->cfg_.v_shunt_lsb_range0 = 0.0050000f; + this->cfg_.v_shunt_lsb_range1 = 0.001250000f; + this->cfg_.shunt_cal_scale = 819.2f * 1000000.0f; + this->cfg_.current_lsb_scale_factor = -15; + this->cfg_.die_temp_lsb = 0.1250000f; + this->cfg_.power_coeff = 0.2f; + this->cfg_.energy_coeff = 0.0f; // N/A + } + + return true; +} + +bool INA2XX::configure_adc_range_() { + ESP_LOGV(TAG, "Setting ADCRANGE = %d", (uint8_t) this->adc_range_); + ConfigurationRegister cfg{0}; + auto ret = this->read_unsigned_16_(RegisterMap::REG_CONFIG, cfg.raw_u16); + cfg.ADCRANGE = this->adc_range_; + ret = ret && this->write_unsigned_16_(RegisterMap::REG_CONFIG, cfg.raw_u16); + + return ret; +} + +bool INA2XX::configure_adc_() { + bool ret{false}; + AdcConfigurationRegister adc_cfg{0}; + adc_cfg.MODE = 0x0F; // Fh = Continuous bus voltage, shunt voltage and temperature + adc_cfg.VBUSCT = this->adc_time_bus_voltage_; + adc_cfg.VSHCT = this->adc_time_shunt_voltage_; + adc_cfg.VTCT = this->adc_time_die_temperature_; + adc_cfg.AVG = this->adc_avg_samples_; + ret = this->write_unsigned_16_(RegisterMap::REG_ADC_CONFIG, adc_cfg.raw_u16); + return ret; +} + +bool INA2XX::configure_shunt_() { + this->current_lsb_ = ldexp(this->max_current_a_, this->cfg_.current_lsb_scale_factor); + this->shunt_cal_ = (uint16_t) (this->cfg_.shunt_cal_scale * this->current_lsb_ * this->shunt_resistance_ohm_); + if (this->adc_range_) + this->shunt_cal_ *= 4; + + if (this->shunt_cal_ & 0x8000) { + // cant be more than 15 bits + ESP_LOGW(TAG, "Shunt value too high"); + } + this->shunt_cal_ &= 0x7FFF; + ESP_LOGV(TAG, "Given Rshunt=%f Ohm and Max_current=%.3f", this->shunt_resistance_ohm_, this->max_current_a_); + ESP_LOGV(TAG, "New CURRENT_LSB=%f, SHUNT_CAL=%u", this->current_lsb_, this->shunt_cal_); + return this->write_unsigned_16_(RegisterMap::REG_SHUNT_CAL, this->shunt_cal_); +} + +bool INA2XX::configure_shunt_tempco_() { + // Only for 228/229 + // unsigned 14-bit value + // 0x0000 = 0 ppm/°C + // 0x3FFF = 16383 ppm/°C + if ((this->ina_model_ == INAModel::INA_228 || this->ina_model_ == INAModel::INA_229) && + this->shunt_tempco_ppm_c_ > 0) { + return this->write_unsigned_16_(RegisterMap::REG_SHUNT_TEMPCO, this->shunt_tempco_ppm_c_ & 0x3FFF); + } + return true; +} + +bool INA2XX::read_shunt_voltage_mv_(float &volt_out) { + // Two's complement value + // 228, 229 - 24bit: 20(23-4) + 4(3-0) res + // 237, 238, 239 - 16bit + + bool ret{false}; + float volt_reading{0}; + uint64_t raw{0}; + if (this->ina_model_ == INAModel::INA_228 || this->ina_model_ == INAModel::INA_229) { + ret = this->read_unsigned_(RegisterMap::REG_VSHUNT, 3, raw); + raw >>= 4; + volt_reading = this->two_complement_(raw, 20); + } else { + ret = this->read_unsigned_(RegisterMap::REG_VSHUNT, 2, raw); + volt_reading = this->two_complement_(raw, 16); + } + + if (ret) { + volt_out = (this->adc_range_ ? this->cfg_.v_shunt_lsb_range1 : this->cfg_.v_shunt_lsb_range0) * volt_reading; + } + + ESP_LOGV(TAG, "read_shunt_voltage_mv_ ret=%s, shunt_cal=%d, reading_lsb=%f", OKFAILED(ret), this->shunt_cal_, + volt_reading); + + return ret; +} + +bool INA2XX::read_bus_voltage_(float &volt_out) { + // Two's complement value + // 228, 229 - 24bit: 20(23-4) + 4(3-0) res + // 237, 238, 239 - 16bit + + bool ret{false}; + float volt_reading{0}; + uint64_t raw{0}; + if (this->ina_model_ == INAModel::INA_228 || this->ina_model_ == INAModel::INA_229) { + ret = this->read_unsigned_(RegisterMap::REG_VBUS, 3, raw); + raw >>= 4; + volt_reading = this->two_complement_(raw, 20); + } else { + ret = this->read_unsigned_(RegisterMap::REG_VBUS, 2, raw); + volt_reading = this->two_complement_(raw, 16); + } + if (ret) { + volt_out = this->cfg_.vbus_lsb * (float) volt_reading; + } + + ESP_LOGV(TAG, "read_bus_voltage_ ret=%s, reading_lsb=%f", OKFAILED(ret), volt_reading); + return ret; +} + +bool INA2XX::read_die_temp_c_(float &temp_out) { + // Two's complement value + // 228, 229 - 16bit + // 237, 238, 239 - 16bit: 12(15-4) + 4(3-0) res + + bool ret{false}; + float temp_reading{0}; + uint64_t raw{0}; + + if (this->ina_model_ == INAModel::INA_228 || this->ina_model_ == INAModel::INA_229) { + ret = this->read_unsigned_(RegisterMap::REG_DIETEMP, 2, raw); + temp_reading = this->two_complement_(raw, 16); + } else { + ret = this->read_unsigned_(RegisterMap::REG_DIETEMP, 2, raw); + raw >>= 4; + temp_reading = this->two_complement_(raw, 12); + } + if (ret) { + temp_out = this->cfg_.die_temp_lsb * (float) temp_reading; + } + + ESP_LOGV(TAG, "read_die_temp_c_ ret=%s, reading_lsb=%f", OKFAILED(ret), temp_reading); + return ret; +} + +bool INA2XX::read_current_a_(float &s_out) { + // Two's complement value + // 228, 229 - 24bit: 20(23-4) + 4(3-0) res + // 237, 238, 239 - 16bit + bool ret{false}; + float amps_reading{0}; + uint64_t raw{0}; + + if (this->ina_model_ == INAModel::INA_228 || this->ina_model_ == INAModel::INA_229) { + ret = this->read_unsigned_(RegisterMap::REG_CURRENT, 3, raw); + raw >>= 4; + amps_reading = this->two_complement_(raw, 20); + } else { + ret = this->read_unsigned_(RegisterMap::REG_CURRENT, 2, raw); + amps_reading = this->two_complement_(raw, 16); + } + + ESP_LOGV(TAG, "read_current_a_ ret=%s. current_lsb=%f. reading_lsb=%f", OKFAILED(ret), this->current_lsb_, + amps_reading); + if (ret) { + amps_out = this->current_lsb_ * (float) amps_reading; + } + + return ret; +} + +bool INA2XX::read_power_w_(float &power_out) { + // Unsigned value + // 228, 229 - 24bit + // 237, 238, 239 - 24bit + uint64_t power_reading{0}; + auto ret = this->read_unsigned_((uint8_t) RegisterMap::REG_POWER, 3, power_reading); + + ESP_LOGV(TAG, "read_power_w_ ret=%s, reading_lsb=%d", OKFAILED(ret), (uint32_t) power_reading); + if (ret) { + power_out = this->cfg_.power_coeff * this->current_lsb_ * (float) power_reading; + } + + return ret; +} + +bool INA2XX::read_energy_(double &joules_out, double &watt_hours_out) { + // Unsigned value + // 228, 229 - 40bit + // 237, 238, 239 - not available + if (this->ina_model_ != INAModel::INA_228 && this->ina_model_ != INAModel::INA_229) { + joules_out = 0; + return false; + } + uint64_t joules_reading = 0; + uint64_t previous_energy = this->energy_overflows_count_ * (((uint64_t) 1) << 40); + auto ret = this->read_unsigned_((uint8_t) RegisterMap::REG_ENERGY, 5, joules_reading); + + ESP_LOGV(TAG, "read_energy_j_ ret=%s, reading_lsb=0x%" PRIX64 ", current_lsb=%f, overflow_cnt=%d", OKFAILED(ret), + joules_reading, this->current_lsb_, this->energy_overflows_count_); + if (ret) { + joules_out = this->cfg_.energy_coeff * this->current_lsb_ * (double) joules_reading + (double) previous_energy; + watt_hours_out = joules_out / 3600.0; + } + return ret; +} + +bool INA2XX::read_charge_(double &coulombs_out, double &_hours_out) { + // Two's complement value + // 228, 229 - 40bit + // 237, 238, 239 - not available + if (this->ina_model_ != INAModel::INA_228 && this->ina_model_ != INAModel::INA_229) { + coulombs_out = 0; + return false; + } + + // and what to do with this? datasheet doesnt tell us what if charge is negative + uint64_t previous_charge = this->charge_overflows_count_ * (((uint64_t) 1) << 39); + double coulombs_reading = 0; + uint64_t raw{0}; + auto ret = this->read_unsigned_((uint8_t) RegisterMap::REG_CHARGE, 5, raw); + coulombs_reading = this->two_complement_(raw, 40); + + ESP_LOGV(TAG, "read_charge_c_ ret=%d, curr_charge=%f + 39-bit overflow_cnt=%d", ret, coulombs_reading, + this->charge_overflows_count_); + if (ret) { + coulombs_out = this->current_lsb_ * (double) coulombs_reading + (double) previous_charge; + amp_hours_out = coulombs_out / 3600.0; + } + return ret; +} + +bool INA2XX::read_diagnostics_and_act_() { + if (this->ina_model_ != INAModel::INA_228 && this->ina_model_ != INAModel::INA_229) { + return false; + } + + DiagnosticRegister diag{0}; + auto ret = this->read_unsigned_16_(RegisterMap::REG_DIAG_ALRT, diag.raw_u16); + ESP_LOGV(TAG, "read_diagnostics_and_act_ ret=%s, 0x%04X", OKFAILED(ret), diag.raw_u16); + + if (diag.ENERGYOF) { + this->energy_overflows_count_++; // 40-bit overflow + } + + if (diag.CHARGEOF) { + this->charge_overflows_count_++; // 39-bit overflow + } + + return ret; +} + +bool INA2XX::write_unsigned_16_(uint8_t reg, uint16_t val) { + uint16_t data_out = byteswap(val); + auto ret = this->write_ina_register(reg, (uint8_t *) &data_out, 2); + if (!ret) { + ESP_LOGV(TAG, "write_unsigned_16_ FAILED reg=0x%02X, val=0x%04X", reg, val); + } + return ret; +} + +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) { + return false; + } + + auto ret = this->read_ina_register(reg, rx_buf, reg_size); + + // Combine bytes + data_out = rx_buf[0]; + for (uint8_t i = 1; i < reg_size; i++) { + data_out = (data_out << 8) | rx_buf[i]; + } + ESP_LOGV(TAG, "read_unsigned_ reg=0x%02X, ret=%s, len=%d, val=0x%" PRIX64, reg, OKFAILED(ret), reg_size, data_out); + + return ret; +} + +bool INA2XX::read_unsigned_16_(uint8_t reg, uint16_t &out) { + uint16_t data_in{0}; + auto ret = this->read_ina_register(reg, (uint8_t *) &data_in, 2); + out = byteswap(data_in); + ESP_LOGV(TAG, "read_unsigned_16_ 0x%02X, ret= %s, val=0x%04X", reg, OKFAILED(ret), out); + return ret; +} + +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; + } +} +} // namespace ina2xx_base +} // namespace esphome diff --git a/esphome/components/ina2xx_base/ina2xx_base.h b/esphome/components/ina2xx_base/ina2xx_base.h new file mode 100644 index 0000000000..261c5321bf --- /dev/null +++ b/esphome/components/ina2xx_base/ina2xx_base.h @@ -0,0 +1,253 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/components/sensor/sensor.h" + +namespace esphome { +namespace ina2xx_base { + +enum RegisterMap : uint8_t { + REG_CONFIG = 0x00, + REG_ADC_CONFIG = 0x01, + REG_SHUNT_CAL = 0x02, + REG_SHUNT_TEMPCO = 0x03, + REG_VSHUNT = 0x04, + REG_VBUS = 0x05, + REG_DIETEMP = 0x06, + REG_CURRENT = 0x07, + REG_POWER = 0x08, + REG_ENERGY = 0x09, + REG_CHARGE = 0x0A, + REG_DIAG_ALRT = 0x0B, + REG_SOVL = 0x0C, + REG_SUVL = 0x0D, + REG_BOVL = 0x0E, + REG_BUVL = 0x0F, + REG_TEMP_LIMIT = 0x10, + REG_PWR_LIMIT = 0x11, + REG_MANUFACTURER_ID = 0x3E, + REG_DEVICE_ID = 0x3F +}; + +enum AdcRange : uint16_t { + ADC_RANGE_0 = 0, + ADC_RANGE_1 = 1, +}; + +enum AdcTime : uint16_t { + ADC_TIME_50US = 0, + ADC_TIME_84US = 1, + ADC_TIME_150US = 2, + ADC_TIME_280US = 3, + ADC_TIME_540US = 4, + ADC_TIME_1052US = 5, + ADC_TIME_2074US = 6, + ADC_TIME_4120US = 7, +}; + +enum AdcAvgSamples : uint16_t { + ADC_AVG_SAMPLES_1 = 0, + ADC_AVG_SAMPLES_4 = 1, + ADC_AVG_SAMPLES_16 = 2, + ADC_AVG_SAMPLES_64 = 3, + ADC_AVG_SAMPLES_128 = 4, + ADC_AVG_SAMPLES_256 = 5, + ADC_AVG_SAMPLES_512 = 6, + ADC_AVG_SAMPLES_1024 = 7, +}; + +union ConfigurationRegister { + uint16_t raw_u16; + struct { + uint16_t reserved_0_3 : 4; // Reserved + AdcRange ADCRANGE : 1; // Shunt measurement range 0: ±163.84 mV, 1: ±40.96 mV + bool TEMPCOMP : 1; // Temperature compensation enable + uint16_t CONVDLY : 8; // Sets the Delay for initial ADC conversion in steps of 2 ms. + bool RSTACC : 1; // Reset counters + bool RST : 1; // Full device reset + } __attribute__((packed)); +}; + +union AdcConfigurationRegister { + uint16_t raw_u16; + struct { + AdcAvgSamples AVG : 3; + AdcTime VTCT : 3; // Voltage conversion time + AdcTime VSHCT : 3; // Shunt voltage conversion time + AdcTime VBUSCT : 3; // Bus voltage conversion time + uint16_t MODE : 4; + } __attribute__((packed)); +}; + +union TempCompensationRegister { + uint16_t raw_u16; + struct { + uint16_t TEMPCO : 14; + uint16_t reserved : 2; + } __attribute__((packed)); +}; + +union DiagnosticRegister { + uint16_t raw_u16; + struct { + bool MEMSTAT : 1; + bool CNVRF : 1; + bool POL : 1; + bool BUSUL : 1; + bool BUSOL : 1; + bool SHNTUL : 1; + bool SHNTOL : 1; + bool TMPOL : 1; + bool RESERVED1 : 1; + bool MATHOF : 1; + bool CHARGEOF : 1; + bool ENERGYOF : 1; + bool APOL : 1; + bool SLOWALERT : 1; + bool CNVR : 1; + bool ALATCH : 1; + } __attribute__((packed)); +}; + +enum INAModel : uint8_t { INA_UNKNOWN = 0, INA_228, INA_229, INA_238, INA_239, INA_237 }; + +class INA2XX : public PollingComponent { + public: + void setup() override; + float get_setup_priority() const override; + void update() override; + void loop() override; + void dump_config() override; + + void set_shunt_resistance_ohm(float shunt_resistance_ohm) { this->shunt_resistance_ohm_ = shunt_resistance_ohm; } + void set_max_current_a(float max_current_a) { this->max_current_a_ = max_current_a; } + void set_adc_range(uint8_t range) { this->adc_range_ = (range == 0) ? AdcRange::ADC_RANGE_0 : AdcRange::ADC_RANGE_1; } + void set_adc_time_bus_voltage(AdcTime time) { this->adc_time_bus_voltage_ = time; } + void set_adc_time_shunt_voltage(AdcTime time) { this->adc_time_shunt_voltage_ = time; } + void set_adc_time_die_temperature(AdcTime time) { this->adc_time_die_temperature_ = time; } + void set_adc_avg_samples(AdcAvgSamples samples) { this->adc_avg_samples_ = samples; } + void set_shunt_tempco(uint16_t coeff) { this->shunt_tempco_ppm_c_ = coeff; } + + void set_shunt_voltage_sensor(sensor::Sensor *sensor) { this->shunt_voltage_sensor_ = sensor; } + void set_bus_voltage_sensor(sensor::Sensor *sensor) { this->bus_voltage_sensor_ = sensor; } + void set_die_temperature_sensor(sensor::Sensor *sensor) { this->die_temperature_sensor_ = sensor; } + void set_current_sensor(sensor::Sensor *sensor) { this->current_sensor_ = sensor; } + void set_power_sensor(sensor::Sensor *sensor) { this->power_sensor_ = sensor; } + void set_energy_sensor_j(sensor::Sensor *sensor) { this->energy_sensor_j_ = sensor; } + void set_energy_sensor_wh(sensor::Sensor *sensor) { this->energy_sensor_wh_ = sensor; } + void set_charge_sensor_c(sensor::Sensor *sensor) { this->charge_sensor_c_ = sensor; } + void set_charge_sensor_ah(sensor::Sensor *sensor) { this->charge_sensor_ah_ = sensor; } + + void set_model(INAModel model) { this->ina_model_ = model; } + + bool reset_energy_counters(); + + protected: + bool reset_config_(); + bool check_device_model_(); + bool configure_adc_(); + + bool configure_shunt_(); + bool configure_shunt_tempco_(); + bool configure_adc_range_(); + + bool read_shunt_voltage_mv_(float &volt_out); + bool read_bus_voltage_(float &volt_out); + bool read_die_temp_c_(float &temp); + bool read_current_a_(float &s_out); + bool read_power_w_(float &power_out); + bool read_energy_(double &joules_out, double &watt_hours_out); + bool read_charge_(double &coulombs_out, double &_hours_out); + + bool read_diagnostics_and_act_(); + + // + // User configuration + // + float shunt_resistance_ohm_; + float max_current_a_; + AdcRange adc_range_{AdcRange::ADC_RANGE_0}; + AdcTime adc_time_bus_voltage_{AdcTime::ADC_TIME_4120US}; + AdcTime adc_time_shunt_voltage_{AdcTime::ADC_TIME_4120US}; + AdcTime adc_time_die_temperature_{AdcTime::ADC_TIME_4120US}; + AdcAvgSamples adc_avg_samples_{AdcAvgSamples::ADC_AVG_SAMPLES_128}; + uint16_t shunt_tempco_ppm_c_{0}; + + // + // Calculated coefficients + // + uint16_t shunt_cal_{0}; + float current_lsb_{0}; + + uint32_t energy_overflows_count_{0}; + uint32_t charge_overflows_count_{0}; + + // + // Sensor objects + // + sensor::Sensor *shunt_voltage_sensor_{nullptr}; + sensor::Sensor *bus_voltage_sensor_{nullptr}; + sensor::Sensor *die_temperature_sensor_{nullptr}; + sensor::Sensor *current_sensor_{nullptr}; + sensor::Sensor *power_sensor_{nullptr}; + sensor::Sensor *energy_sensor_j_{nullptr}; + sensor::Sensor *energy_sensor_wh_{nullptr}; + sensor::Sensor *charge_sensor_c_{nullptr}; + sensor::Sensor *charge_sensor_ah_{nullptr}; + + // + // FSM states + // + enum class State : uint8_t { + NOT_INITIALIZED = 0x0, + IDLE, + DATA_COLLECTION_1, + DATA_COLLECTION_2, + DATA_COLLECTION_3, + DATA_COLLECTION_4, + DATA_COLLECTION_5, + DATA_COLLECTION_6, + DATA_COLLECTION_7, + DATA_COLLECTION_8, + } state_{State::NOT_INITIALIZED}; + + bool full_loop_is_okay_{true}; + + // + // Device model + // + INAModel ina_model_{INAModel::INA_UNKNOWN}; + uint16_t dev_id_{0}; + bool device_mismatch_{false}; + + // + // Device specific parameters + // + struct { + float vbus_lsb; + float v_shunt_lsb_range0; + float v_shunt_lsb_range1; + float shunt_cal_scale; + int8_t current_lsb_scale_factor; + float die_temp_lsb; + float power_coeff; + float energy_coeff; + } cfg_; + + // + // Register read/write + // + bool read_unsigned_(uint8_t reg, uint8_t reg_size, uint64_t &data_out); + bool read_unsigned_16_(uint8_t reg, uint16_t &out); + bool write_unsigned_16_(uint8_t reg, uint16_t val); + + int64_t two_complement_(uint64_t value, uint8_t bits); + + // + // Interface-specific implementation + // + virtual bool read_ina_register(uint8_t a_register, uint8_t *data, size_t len) = 0; + virtual bool write_ina_register(uint8_t a_register, const uint8_t *data, size_t len) = 0; +}; +} // namespace ina2xx_base +} // namespace esphome diff --git a/esphome/components/ina2xx_i2c/__init__.py b/esphome/components/ina2xx_i2c/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/ina2xx_i2c/ina2xx_i2c.cpp b/esphome/components/ina2xx_i2c/ina2xx_i2c.cpp new file mode 100644 index 0000000000..d28525635d --- /dev/null +++ b/esphome/components/ina2xx_i2c/ina2xx_i2c.cpp @@ -0,0 +1,39 @@ +#include "ina2xx_i2c.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace ina2xx_i2c { + +static const char *const TAG = "ina2xx_i2c"; + +void INA2XXI2C::setup() { + auto err = this->write(nullptr, 0); + if (err != i2c::ERROR_OK) { + this->mark_failed(); + return; + } + INA2XX::setup(); +} + +void INA2XXI2C::dump_config() { + INA2XX::dump_config(); + LOG_I2C_DEVICE(this); +} + +bool INA2XXI2C::read_ina_register(uint8_t reg, uint8_t *data, size_t len) { + auto ret = this->read_register(reg, data, len, false); + if (ret != i2c::ERROR_OK) { + ESP_LOGE(TAG, "read_ina_register_ failed. Reg=0x%02X Err=%d", reg, ret); + } + return ret == i2c::ERROR_OK; +} + +bool INA2XXI2C::write_ina_register(uint8_t reg, const uint8_t *data, size_t len) { + auto ret = this->write_register(reg, data, len); + if (ret != i2c::ERROR_OK) { + ESP_LOGE(TAG, "write_register failed. Reg=0x%02X Err=%d", reg, ret); + } + return ret == i2c::ERROR_OK; +} +} // namespace ina2xx_i2c +} // namespace esphome diff --git a/esphome/components/ina2xx_i2c/ina2xx_i2c.h b/esphome/components/ina2xx_i2c/ina2xx_i2c.h new file mode 100644 index 0000000000..c90b9bf190 --- /dev/null +++ b/esphome/components/ina2xx_i2c/ina2xx_i2c.h @@ -0,0 +1,21 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/components/ina2xx_base/ina2xx_base.h" +#include "esphome/components/i2c/i2c.h" + +namespace esphome { +namespace ina2xx_i2c { + +class INA2XXI2C : public ina2xx_base::INA2XX, public i2c::I2CDevice { + public: + void setup() override; + void dump_config() override; + + protected: + bool read_ina_register(uint8_t reg, uint8_t *data, size_t len) override; + bool write_ina_register(uint8_t reg, const uint8_t *data, size_t len) override; +}; + +} // namespace ina2xx_i2c +} // namespace esphome diff --git a/esphome/components/ina2xx_i2c/sensor.py b/esphome/components/ina2xx_i2c/sensor.py new file mode 100644 index 0000000000..57ddcef17a --- /dev/null +++ b/esphome/components/ina2xx_i2c/sensor.py @@ -0,0 +1,34 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import ina2xx_base, i2c +from esphome.const import CONF_ID, CONF_MODEL + +AUTO_LOAD = ["ina2xx_base"] +CODEOWNERS = ["@latonita"] +DEPENDENCIES = ["i2c"] + +ina2xx_i2c = cg.esphome_ns.namespace("ina2xx_i2c") +INA2XX_I2C = ina2xx_i2c.class_("INA2XXI2C", ina2xx_base.INA2XX, i2c.I2CDevice) + +INAModel = ina2xx_base.ina2xx_base_ns.enum("INAModel") +INA_MODELS = { + "INA228": INAModel.INA_228, + "INA238": INAModel.INA_238, + "INA237": INAModel.INA_237, +} + +CONFIG_SCHEMA = cv.All( + ina2xx_base.INA2XX_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(INA2XX_I2C), + cv.Required(CONF_MODEL): cv.enum(INA_MODELS, upper=True), + } + ).extend(i2c.i2c_device_schema(0x40)), + ina2xx_base.validate_model_config, +) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + await ina2xx_base.setup_ina2xx(var, config) + await i2c.register_i2c_device(var, config) diff --git a/esphome/components/ina2xx_spi/__init__.py b/esphome/components/ina2xx_spi/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/ina2xx_spi/ina2xx_spi.cpp b/esphome/components/ina2xx_spi/ina2xx_spi.cpp new file mode 100644 index 0000000000..3e04a87665 --- /dev/null +++ b/esphome/components/ina2xx_spi/ina2xx_spi.cpp @@ -0,0 +1,38 @@ +#include "ina2xx_spi.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace ina2xx_spi { + +static const char *const TAG = "ina2xx_spi"; + +void INA2XXSPI::setup() { + this->spi_setup(); + INA2XX::setup(); +} + +void INA2XXSPI::dump_config() { + INA2XX::dump_config(); + LOG_PIN(" CS Pin: ", this->cs_); +} + +bool INA2XXSPI::read_ina_register(uint8_t reg, uint8_t *data, size_t len) { + reg = (reg << 2); // top 6 bits + reg |= 0x01; // read + this->enable(); + this->write_byte(reg); + this->read_array(data, len); + this->disable(); + return true; +} + +bool INA2XXSPI::write_ina_register(uint8_t reg, const uint8_t *data, size_t len) { + reg = (reg << 2); // top 6 bits + this->enable(); + this->write_byte(reg); + this->write_array(data, len); + this->disable(); + return true; +} +} // namespace ina2xx_spi +} // namespace esphome diff --git a/esphome/components/ina2xx_spi/ina2xx_spi.h b/esphome/components/ina2xx_spi/ina2xx_spi.h new file mode 100644 index 0000000000..3b21518d34 --- /dev/null +++ b/esphome/components/ina2xx_spi/ina2xx_spi.h @@ -0,0 +1,22 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/components/ina2xx_base/ina2xx_base.h" +#include "esphome/components/spi/spi.h" + +namespace esphome { +namespace ina2xx_spi { + +class INA2XXSPI : public ina2xx_base::INA2XX, + public spi::SPIDevice { + public: + void setup() override; + void dump_config() override; + + protected: + bool read_ina_register(uint8_t reg, uint8_t *data, size_t len) override; + bool write_ina_register(uint8_t reg, const uint8_t *data, size_t len) override; +}; +} // namespace ina2xx_spi +} // namespace esphome diff --git a/esphome/components/ina2xx_spi/sensor.py b/esphome/components/ina2xx_spi/sensor.py new file mode 100644 index 0000000000..e7ae51d516 --- /dev/null +++ b/esphome/components/ina2xx_spi/sensor.py @@ -0,0 +1,33 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import ina2xx_base, spi +from esphome.const import CONF_ID, CONF_MODEL + +AUTO_LOAD = ["ina2xx_base"] +CODEOWNERS = ["@latonita"] +DEPENDENCIES = ["spi"] + +ina2xx_spi = cg.esphome_ns.namespace("ina2xx_spi") +INA2XX_SPI = ina2xx_spi.class_("INA2XXSPI", ina2xx_base.INA2XX, spi.SPIDevice) + +INAModel = ina2xx_base.ina2xx_base_ns.enum("INAModel") +INA_MODELS = { + "INA229": INAModel.INA_229, + "INA239": INAModel.INA_239, +} + +CONFIG_SCHEMA = cv.All( + ina2xx_base.INA2XX_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(INA2XX_SPI), + cv.Required(CONF_MODEL): cv.enum(INA_MODELS, upper=True), + } + ).extend(spi.spi_device_schema(cs_pin_required=True)), + ina2xx_base.validate_model_config, +) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + await ina2xx_base.setup_ina2xx(var, config) + await spi.register_spi_device(var, config) diff --git a/tests/components/ina2xx_i2c/common.yaml b/tests/components/ina2xx_i2c/common.yaml new file mode 100644 index 0000000000..320b680b6b --- /dev/null +++ b/tests/components/ina2xx_i2c/common.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_ina2xx + scl: ${scl_pin} + sda: ${sda_pin} + +sensor: + - platform: ina2xx_i2c + i2c_id: i2c_ina2xx + address: 0x40 + model: INA228 + shunt_resistance: 0.001130 ohm + max_current: 40 A + adc_range: 1 + temperature_coefficient: 50 + shunt_voltage: "INA2xx Shunt Voltage" + bus_voltage: "INA2xx Bus Voltage" + current: "INA2xx Current" + power: "INA2xx Power" + energy: "INA2xx Energy" + charge: "INA2xx Charge" diff --git a/tests/components/ina2xx_i2c/test.esp32-c3-idf.yaml b/tests/components/ina2xx_i2c/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/ina2xx_i2c/test.esp32-c3-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/ina2xx_i2c/test.esp32-c3.yaml b/tests/components/ina2xx_i2c/test.esp32-c3.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/ina2xx_i2c/test.esp32-c3.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/ina2xx_i2c/test.esp32-idf.yaml b/tests/components/ina2xx_i2c/test.esp32-idf.yaml new file mode 100644 index 0000000000..63c3bd6afd --- /dev/null +++ b/tests/components/ina2xx_i2c/test.esp32-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO16 + sda_pin: GPIO17 + +<<: !include common.yaml diff --git a/tests/components/ina2xx_i2c/test.esp32.yaml b/tests/components/ina2xx_i2c/test.esp32.yaml new file mode 100644 index 0000000000..63c3bd6afd --- /dev/null +++ b/tests/components/ina2xx_i2c/test.esp32.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO16 + sda_pin: GPIO17 + +<<: !include common.yaml diff --git a/tests/components/ina2xx_i2c/test.esp8266.yaml b/tests/components/ina2xx_i2c/test.esp8266.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/ina2xx_i2c/test.esp8266.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/ina2xx_i2c/test.rp2040.yaml b/tests/components/ina2xx_i2c/test.rp2040.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/ina2xx_i2c/test.rp2040.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/ina2xx_spi/common.yaml b/tests/components/ina2xx_spi/common.yaml new file mode 100644 index 0000000000..3eab7e6f0a --- /dev/null +++ b/tests/components/ina2xx_spi/common.yaml @@ -0,0 +1,21 @@ +spi: + - id: spi_ina2xx + clk_pin: ${clk_pin} + mosi_pin: ${mosi_pin} + miso_pin: ${miso_pin} + +sensor: + - platform: ina2xx_spi + spi_id: spi_ina2xx + cs_pin: ${cs_pin} + model: INA229 + shunt_resistance: 0.001130 ohm + max_current: 40 A + adc_range: 1 + temperature_coefficient: 50 + shunt_voltage: "INA2xx Shunt Voltage" + bus_voltage: "INA2xx Bus Voltage" + current: "INA2xx Current" + power: "INA2xx Power" + energy: "INA2xx Energy" + charge: "INA2xx Charge" diff --git a/tests/components/ina2xx_spi/test.esp32-c3-idf.yaml b/tests/components/ina2xx_spi/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..2415ba5dc6 --- /dev/null +++ b/tests/components/ina2xx_spi/test.esp32-c3-idf.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO6 + mosi_pin: GPIO7 + miso_pin: GPIO5 + cs_pin: GPIO8 + +<<: !include common.yaml diff --git a/tests/components/ina2xx_spi/test.esp32-c3.yaml b/tests/components/ina2xx_spi/test.esp32-c3.yaml new file mode 100644 index 0000000000..2415ba5dc6 --- /dev/null +++ b/tests/components/ina2xx_spi/test.esp32-c3.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO6 + mosi_pin: GPIO7 + miso_pin: GPIO5 + cs_pin: GPIO8 + +<<: !include common.yaml diff --git a/tests/components/ina2xx_spi/test.esp32-idf.yaml b/tests/components/ina2xx_spi/test.esp32-idf.yaml new file mode 100644 index 0000000000..54e027a614 --- /dev/null +++ b/tests/components/ina2xx_spi/test.esp32-idf.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO16 + mosi_pin: GPIO17 + miso_pin: GPIO15 + cs_pin: GPIO5 + +<<: !include common.yaml diff --git a/tests/components/ina2xx_spi/test.esp32.yaml b/tests/components/ina2xx_spi/test.esp32.yaml new file mode 100644 index 0000000000..54e027a614 --- /dev/null +++ b/tests/components/ina2xx_spi/test.esp32.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO16 + mosi_pin: GPIO17 + miso_pin: GPIO15 + cs_pin: GPIO5 + +<<: !include common.yaml diff --git a/tests/components/ina2xx_spi/test.esp8266.yaml b/tests/components/ina2xx_spi/test.esp8266.yaml new file mode 100644 index 0000000000..dbd158d030 --- /dev/null +++ b/tests/components/ina2xx_spi/test.esp8266.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO14 + mosi_pin: GPIO13 + miso_pin: GPIO12 + cs_pin: GPIO15 + +<<: !include common.yaml diff --git a/tests/components/ina2xx_spi/test.rp2040.yaml b/tests/components/ina2xx_spi/test.rp2040.yaml new file mode 100644 index 0000000000..f6c3f1eeca --- /dev/null +++ b/tests/components/ina2xx_spi/test.rp2040.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO2 + mosi_pin: GPIO3 + miso_pin: GPIO4 + cs_pin: GPIO5 + +<<: !include common.yaml From d410cc4f7beac8b483b67adc6bba635dce5230ad Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Thu, 16 May 2024 12:22:18 +0200 Subject: [PATCH 1465/2101] [nextion] Fix type on sprintf for IDF v5 (#6758) --- esphome/components/nextion/nextion_upload_idf.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/nextion/nextion_upload_idf.cpp b/esphome/components/nextion/nextion_upload_idf.cpp index 448b6fc0ff..b5bb5478c1 100644 --- a/esphome/components/nextion/nextion_upload_idf.cpp +++ b/esphome/components/nextion/nextion_upload_idf.cpp @@ -260,7 +260,7 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { // Tells the Nextion the content length of the tft file and baud rate it will be sent at // Once the Nextion accepts the command it will wait until the file is successfully uploaded // If it fails for any reason a power cycle of the display will be needed - sprintf(command, "whmi-wris %d,%" PRIu32 ",1", this->content_length_, baud_rate); + sprintf(command, "whmi-wris %" PRIu32 ",%" PRIu32 ",1", this->content_length_, baud_rate); // Clear serial receive buffer ESP_LOGV(TAG, "Clear serial receive buffer"); From df838b5788e8d9b42718225d89c8f5f3854fa076 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 16 May 2024 22:33:33 +1200 Subject: [PATCH 1466/2101] [core] Remove references to deleted setup.py (#6757) --- .github/workflows/release.yml | 4 +++- CODEOWNERS | 2 +- script/build_codeowners.py | 2 +- script/ci-custom.py | 1 - 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 03ed523e1d..c1c502394a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -61,7 +61,9 @@ jobs: ESPHOME_NO_VENV: 1 run: script/setup - name: Build - run: python setup.py sdist bdist_wheel + run: |- + pip3 install build + python3 -m build - name: Publish uses: pypa/gh-action-pypi-publish@v1.8.14 diff --git a/CODEOWNERS b/CODEOWNERS index d97207941f..dc6c8caa87 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -6,7 +6,7 @@ # the integration's code owner is automatically notified. # Core Code -setup.py @esphome/core +pyproject.toml @esphome/core esphome/*.py @esphome/core esphome/core/* @esphome/core diff --git a/script/build_codeowners.py b/script/build_codeowners.py index 22f3c1b4bc..6bc558d351 100755 --- a/script/build_codeowners.py +++ b/script/build_codeowners.py @@ -28,7 +28,7 @@ BASE = """ # the integration's code owner is automatically notified. # Core Code -setup.py @esphome/core +pyproject.toml @esphome/core esphome/*.py @esphome/core esphome/core/* @esphome/core diff --git a/script/ci-custom.py b/script/ci-custom.py index 704962fa97..e2ee81f742 100755 --- a/script/ci-custom.py +++ b/script/ci-custom.py @@ -229,7 +229,6 @@ def lint_ext_check(fname): "docker/ha-addon-rootfs/**", "docker/*.py", "script/*", - "setup.py", ] ) def lint_executable_bit(fname): From 94b63d7bc2675b02b3f869018de7a842a69edb00 Mon Sep 17 00:00:00 2001 From: acshef Date: Fri, 17 May 2024 22:17:09 -0600 Subject: [PATCH 1467/2101] Add device_class to valve core config (#6765) --- esphome/components/valve/__init__.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/esphome/components/valve/__init__.py b/esphome/components/valve/__init__.py index 22d617cc36..13c2947438 100644 --- a/esphome/components/valve/__init__.py +++ b/esphome/components/valve/__init__.py @@ -14,6 +14,8 @@ from esphome.const import ( CONF_STATE, CONF_STOP, CONF_TRIGGER_ID, + DEVICE_CLASS_GAS, + DEVICE_CLASS_WATER, ) from esphome.core import CORE, coroutine_with_priority from esphome.cpp_helpers import setup_entity @@ -22,6 +24,11 @@ IS_PLATFORM_COMPONENT = True CODEOWNERS = ["@esphome/core"] +DEVICE_CLASSES = [ + DEVICE_CLASS_GAS, + DEVICE_CLASS_WATER, +] + valve_ns = cg.esphome_ns.namespace("valve") Valve = valve_ns.class_("Valve", cg.EntityBase) @@ -65,6 +72,7 @@ VALVE_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA).ex { cv.GenerateID(): cv.declare_id(Valve), cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTValveComponent), + 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 ), From 1164cb86106bc44cf57ab280e379499fe03f440b Mon Sep 17 00:00:00 2001 From: esphomebot Date: Sat, 18 May 2024 19:15:52 +1200 Subject: [PATCH 1468/2101] Synchronise Device Classes from Home Assistant (#6768) --- esphome/components/valve/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/components/valve/__init__.py b/esphome/components/valve/__init__.py index 13c2947438..ea6bfc6055 100644 --- a/esphome/components/valve/__init__.py +++ b/esphome/components/valve/__init__.py @@ -14,6 +14,7 @@ from esphome.const import ( CONF_STATE, CONF_STOP, CONF_TRIGGER_ID, + DEVICE_CLASS_EMPTY, DEVICE_CLASS_GAS, DEVICE_CLASS_WATER, ) @@ -25,6 +26,7 @@ IS_PLATFORM_COMPONENT = True CODEOWNERS = ["@esphome/core"] DEVICE_CLASSES = [ + DEVICE_CLASS_EMPTY, DEVICE_CLASS_GAS, DEVICE_CLASS_WATER, ] From 70e0925f9abaab0aa0cc13646b1115cdce230a98 Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Sun, 19 May 2024 01:31:36 +0200 Subject: [PATCH 1469/2101] Fix pip3 install (#6771) --- script/setup | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/setup b/script/setup index 71573a9352..1a18a6a9ea 100755 --- a/script/setup +++ b/script/setup @@ -20,7 +20,7 @@ fi pip3 install -r requirements.txt -r requirements_optional.txt -r requirements_test.txt -r requirements_dev.txt pip3 install setuptools wheel -pip3 install -e --config-settings editable_mode=compat ".[dev,test,displays]" +pip3 install -e ".[dev,test,displays]" --config-settings editable_mode=compat pre-commit install From 4469ba402498e6b8e20b6fc89873f70f61a1a21e Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Sun, 19 May 2024 01:47:23 +0200 Subject: [PATCH 1470/2101] [tests] make test_build_components work with venv without installing esphome (#6761) --- script/test_build_components | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/script/test_build_components b/script/test_build_components index 4d91256572..f82dd5c3b6 100755 --- a/script/test_build_components +++ b/script/test_build_components @@ -37,9 +37,10 @@ start_esphome() { # Start esphome process echo "> [$target_component] [$test_name] [$target_platform]" - echo "esphome -s component_name $target_component -s component_dir ../../components/$target_component -s test_name $test_name -s target_platform $target_platform $esphome_command $component_test_file" + set -x # TODO: Validate escape of Command line substitution value - esphome -s component_name $target_component -s component_dir ../../components/$target_component -s test_name $test_name -s target_platform $target_platform $esphome_command $component_test_file + python -m esphome -s component_name $target_component -s component_dir ../../components/$target_component -s test_name $test_name -s target_platform $target_platform $esphome_command $component_test_file + { set +x; } 2>/dev/null } # Find all test yaml files. From ba73187c1bf20ac0c9d823a5ff8d8aa5f8a07e03 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Sun, 19 May 2024 22:11:27 +0200 Subject: [PATCH 1471/2101] separate deep_sleep component for each platform in different file (#6762) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- .../deep_sleep/deep_sleep_component.cpp | 115 ++---------------- .../deep_sleep/deep_sleep_component.h | 4 + .../deep_sleep/deep_sleep_esp32.cpp | 104 ++++++++++++++++ .../deep_sleep/deep_sleep_esp8266.cpp | 23 ++++ 4 files changed, 143 insertions(+), 103 deletions(-) create mode 100644 esphome/components/deep_sleep/deep_sleep_esp32.cpp create mode 100644 esphome/components/deep_sleep/deep_sleep_esp8266.cpp diff --git a/esphome/components/deep_sleep/deep_sleep_component.cpp b/esphome/components/deep_sleep/deep_sleep_component.cpp index 97fdf11366..1e7637f3e5 100644 --- a/esphome/components/deep_sleep/deep_sleep_component.cpp +++ b/esphome/components/deep_sleep/deep_sleep_component.cpp @@ -1,12 +1,7 @@ #include "deep_sleep_component.h" -#include #include "esphome/core/application.h" #include "esphome/core/log.h" -#ifdef USE_ESP8266 -#include -#endif - namespace esphome { namespace deep_sleep { @@ -14,25 +9,6 @@ static const char *const TAG = "deep_sleep"; bool global_has_deep_sleep = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) -optional DeepSleepComponent::get_run_duration_() const { -#ifdef USE_ESP32 - if (this->wakeup_cause_to_run_duration_.has_value()) { - esp_sleep_wakeup_cause_t wakeup_cause = esp_sleep_get_wakeup_cause(); - switch (wakeup_cause) { - case ESP_SLEEP_WAKEUP_EXT0: - case ESP_SLEEP_WAKEUP_EXT1: - case ESP_SLEEP_WAKEUP_GPIO: - return this->wakeup_cause_to_run_duration_->gpio_cause; - case ESP_SLEEP_WAKEUP_TOUCHPAD: - return this->wakeup_cause_to_run_duration_->touch_cause; - default: - return this->wakeup_cause_to_run_duration_->default_cause; - } - } -#endif - return this->run_duration_; -} - void DeepSleepComponent::setup() { ESP_LOGCONFIG(TAG, "Setting up Deep Sleep..."); global_has_deep_sleep = true; @@ -45,6 +21,7 @@ void DeepSleepComponent::setup() { ESP_LOGD(TAG, "Not scheduling Deep Sleep, as no run duration is configured."); } } + void DeepSleepComponent::dump_config() { ESP_LOGCONFIG(TAG, "Setting up Deep Sleep..."); if (this->sleep_duration_.has_value()) { @@ -54,65 +31,31 @@ void DeepSleepComponent::dump_config() { if (this->run_duration_.has_value()) { ESP_LOGCONFIG(TAG, " Run Duration: %" PRIu32 " ms", *this->run_duration_); } -#ifdef USE_ESP32 - if (wakeup_pin_ != nullptr) { - LOG_PIN(" Wakeup Pin: ", this->wakeup_pin_); - } - if (this->wakeup_cause_to_run_duration_.has_value()) { - ESP_LOGCONFIG(TAG, " Default Wakeup Run Duration: %" PRIu32 " ms", - this->wakeup_cause_to_run_duration_->default_cause); - ESP_LOGCONFIG(TAG, " Touch Wakeup Run Duration: %" PRIu32 " ms", this->wakeup_cause_to_run_duration_->touch_cause); - ESP_LOGCONFIG(TAG, " GPIO Wakeup Run Duration: %" PRIu32 " ms", this->wakeup_cause_to_run_duration_->gpio_cause); - } -#endif + this->dump_config_platform_(); } + void DeepSleepComponent::loop() { if (this->next_enter_deep_sleep_) this->begin_sleep(); } + float DeepSleepComponent::get_loop_priority() const { return -100.0f; // run after everything else is ready } + void DeepSleepComponent::set_sleep_duration(uint32_t time_ms) { this->sleep_duration_ = uint64_t(time_ms) * 1000; } -#if defined(USE_ESP32) -void DeepSleepComponent::set_wakeup_pin_mode(WakeupPinMode wakeup_pin_mode) { - this->wakeup_pin_mode_ = wakeup_pin_mode; -} -#endif - -#if defined(USE_ESP32) -#if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32C6) - -void DeepSleepComponent::set_ext1_wakeup(Ext1Wakeup ext1_wakeup) { this->ext1_wakeup_ = ext1_wakeup; } - -void DeepSleepComponent::set_touch_wakeup(bool touch_wakeup) { this->touch_wakeup_ = touch_wakeup; } - -#endif - -void DeepSleepComponent::set_run_duration(WakeupCauseToRunDuration wakeup_cause_to_run_duration) { - wakeup_cause_to_run_duration_ = wakeup_cause_to_run_duration; -} - -#endif void DeepSleepComponent::set_run_duration(uint32_t time_ms) { this->run_duration_ = time_ms; } + void DeepSleepComponent::begin_sleep(bool manual) { if (this->prevent_ && !manual) { this->next_enter_deep_sleep_ = true; return; } -#ifdef USE_ESP32 - if (this->wakeup_pin_mode_ == WAKEUP_PIN_MODE_KEEP_AWAKE && this->wakeup_pin_ != nullptr && - !this->sleep_duration_.has_value() && this->wakeup_pin_->digital_read()) { - // Defer deep sleep until inactive - if (!this->next_enter_deep_sleep_) { - this->status_set_warning(); - ESP_LOGW(TAG, "Waiting for pin_ to switch state to enter deep sleep..."); - } - this->next_enter_deep_sleep_ = true; + + if (!this->prepare_to_sleep_()) { return; } -#endif ESP_LOGI(TAG, "Beginning Deep Sleep"); if (this->sleep_duration_.has_value()) { @@ -120,47 +63,13 @@ void DeepSleepComponent::begin_sleep(bool manual) { } App.run_safe_shutdown_hooks(); -#if defined(USE_ESP32) -#if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32C6) - if (this->sleep_duration_.has_value()) - esp_sleep_enable_timer_wakeup(*this->sleep_duration_); - if (this->wakeup_pin_ != nullptr) { - bool level = !this->wakeup_pin_->is_inverted(); - if (this->wakeup_pin_mode_ == WAKEUP_PIN_MODE_INVERT_WAKEUP && this->wakeup_pin_->digital_read()) { - level = !level; - } - esp_sleep_enable_ext0_wakeup(gpio_num_t(this->wakeup_pin_->get_pin()), level); - } - if (this->ext1_wakeup_.has_value()) { - esp_sleep_enable_ext1_wakeup(this->ext1_wakeup_->mask, this->ext1_wakeup_->wakeup_mode); - } - - if (this->touch_wakeup_.has_value() && *(this->touch_wakeup_)) { - esp_sleep_enable_touchpad_wakeup(); - esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON); - } -#endif -#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) - if (this->sleep_duration_.has_value()) - esp_sleep_enable_timer_wakeup(*this->sleep_duration_); - if (this->wakeup_pin_ != nullptr) { - bool level = !this->wakeup_pin_->is_inverted(); - if (this->wakeup_pin_mode_ == WAKEUP_PIN_MODE_INVERT_WAKEUP && this->wakeup_pin_->digital_read()) { - level = !level; - } - esp_deep_sleep_enable_gpio_wakeup(1 << this->wakeup_pin_->get_pin(), - static_cast(level)); - } -#endif - esp_deep_sleep_start(); -#endif - -#ifdef USE_ESP8266 - ESP.deepSleep(*this->sleep_duration_); // NOLINT(readability-static-accessed-through-instance) -#endif + this->deep_sleep_(); } + float DeepSleepComponent::get_setup_priority() const { return setup_priority::LATE; } + void DeepSleepComponent::prevent_deep_sleep() { this->prevent_ = true; } + void DeepSleepComponent::allow_deep_sleep() { this->prevent_ = false; } } // namespace deep_sleep diff --git a/esphome/components/deep_sleep/deep_sleep_component.h b/esphome/components/deep_sleep/deep_sleep_component.h index e97d8300c4..be56b529ba 100644 --- a/esphome/components/deep_sleep/deep_sleep_component.h +++ b/esphome/components/deep_sleep/deep_sleep_component.h @@ -106,6 +106,10 @@ class DeepSleepComponent : public Component { // duration before entering deep sleep. optional get_run_duration_() const; + void dump_config_platform_(); + bool prepare_to_sleep_(); + void deep_sleep_(); + optional sleep_duration_; #ifdef USE_ESP32 InternalGPIOPin *wakeup_pin_; diff --git a/esphome/components/deep_sleep/deep_sleep_esp32.cpp b/esphome/components/deep_sleep/deep_sleep_esp32.cpp new file mode 100644 index 0000000000..d54046bc11 --- /dev/null +++ b/esphome/components/deep_sleep/deep_sleep_esp32.cpp @@ -0,0 +1,104 @@ +#ifdef USE_ESP32 +#include "deep_sleep_component.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace deep_sleep { + +static const char *const TAG = "deep_sleep"; + +optional DeepSleepComponent::get_run_duration_() const { + if (this->wakeup_cause_to_run_duration_.has_value()) { + esp_sleep_wakeup_cause_t wakeup_cause = esp_sleep_get_wakeup_cause(); + switch (wakeup_cause) { + case ESP_SLEEP_WAKEUP_EXT0: + case ESP_SLEEP_WAKEUP_EXT1: + case ESP_SLEEP_WAKEUP_GPIO: + return this->wakeup_cause_to_run_duration_->gpio_cause; + case ESP_SLEEP_WAKEUP_TOUCHPAD: + return this->wakeup_cause_to_run_duration_->touch_cause; + default: + return this->wakeup_cause_to_run_duration_->default_cause; + } + } + return this->run_duration_; +} + +void DeepSleepComponent::set_wakeup_pin_mode(WakeupPinMode wakeup_pin_mode) { + this->wakeup_pin_mode_ = wakeup_pin_mode; +} + +#if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32C6) +void DeepSleepComponent::set_ext1_wakeup(Ext1Wakeup ext1_wakeup) { this->ext1_wakeup_ = ext1_wakeup; } + +void DeepSleepComponent::set_touch_wakeup(bool touch_wakeup) { this->touch_wakeup_ = touch_wakeup; } +#endif + +void DeepSleepComponent::set_run_duration(WakeupCauseToRunDuration wakeup_cause_to_run_duration) { + wakeup_cause_to_run_duration_ = wakeup_cause_to_run_duration; +} + +void DeepSleepComponent::dump_config_platform_() { + if (wakeup_pin_ != nullptr) { + LOG_PIN(" Wakeup Pin: ", this->wakeup_pin_); + } + if (this->wakeup_cause_to_run_duration_.has_value()) { + ESP_LOGCONFIG(TAG, " Default Wakeup Run Duration: %" PRIu32 " ms", + this->wakeup_cause_to_run_duration_->default_cause); + ESP_LOGCONFIG(TAG, " Touch Wakeup Run Duration: %" PRIu32 " ms", this->wakeup_cause_to_run_duration_->touch_cause); + ESP_LOGCONFIG(TAG, " GPIO Wakeup Run Duration: %" PRIu32 " ms", this->wakeup_cause_to_run_duration_->gpio_cause); + } +} + +bool DeepSleepComponent::prepare_to_sleep_() { + if (this->wakeup_pin_mode_ == WAKEUP_PIN_MODE_KEEP_AWAKE && this->wakeup_pin_ != nullptr && + !this->sleep_duration_.has_value() && this->wakeup_pin_->digital_read()) { + // Defer deep sleep until inactive + if (!this->next_enter_deep_sleep_) { + this->status_set_warning(); + ESP_LOGW(TAG, "Waiting for pin_ to switch state to enter deep sleep..."); + } + this->next_enter_deep_sleep_ = true; + return false; + } + return true; +} + +void DeepSleepComponent::deep_sleep_() { +#if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32C6) + if (this->sleep_duration_.has_value()) + esp_sleep_enable_timer_wakeup(*this->sleep_duration_); + if (this->wakeup_pin_ != nullptr) { + bool level = !this->wakeup_pin_->is_inverted(); + if (this->wakeup_pin_mode_ == WAKEUP_PIN_MODE_INVERT_WAKEUP && this->wakeup_pin_->digital_read()) { + level = !level; + } + esp_sleep_enable_ext0_wakeup(gpio_num_t(this->wakeup_pin_->get_pin()), level); + } + if (this->ext1_wakeup_.has_value()) { + esp_sleep_enable_ext1_wakeup(this->ext1_wakeup_->mask, this->ext1_wakeup_->wakeup_mode); + } + + if (this->touch_wakeup_.has_value() && *(this->touch_wakeup_)) { + esp_sleep_enable_touchpad_wakeup(); + esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON); + } +#endif +#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) + if (this->sleep_duration_.has_value()) + esp_sleep_enable_timer_wakeup(*this->sleep_duration_); + if (this->wakeup_pin_ != nullptr) { + bool level = !this->wakeup_pin_->is_inverted(); + if (this->wakeup_pin_mode_ == WAKEUP_PIN_MODE_INVERT_WAKEUP && this->wakeup_pin_->digital_read()) { + level = !level; + } + esp_deep_sleep_enable_gpio_wakeup(1 << this->wakeup_pin_->get_pin(), + static_cast(level)); + } +#endif + esp_deep_sleep_start(); +} + +} // namespace deep_sleep +} // namespace esphome +#endif diff --git a/esphome/components/deep_sleep/deep_sleep_esp8266.cpp b/esphome/components/deep_sleep/deep_sleep_esp8266.cpp new file mode 100644 index 0000000000..54d2aa993d --- /dev/null +++ b/esphome/components/deep_sleep/deep_sleep_esp8266.cpp @@ -0,0 +1,23 @@ +#ifdef USE_ESP8266 +#include "deep_sleep_component.h" + +#include + +namespace esphome { +namespace deep_sleep { + +static const char *const TAG = "deep_sleep"; + +optional DeepSleepComponent::get_run_duration_() const { return this->run_duration_; } + +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) +} + +} // namespace deep_sleep +} // namespace esphome +#endif From a85d37a1cfae47d77c05e4deac830e5811af8066 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 May 2024 08:12:32 +1200 Subject: [PATCH 1472/2101] Bump actions/checkout from 4.1.5 to 4.1.6 (#6764) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-api-proto.yml | 2 +- .github/workflows/ci-docker.yml | 2 +- .github/workflows/ci.yml | 32 +++++++++++------------ .github/workflows/release.yml | 8 +++--- .github/workflows/sync-device-classes.yml | 4 +-- .github/workflows/yaml-lint.yml | 2 +- 6 files changed, 25 insertions(+), 25 deletions(-) diff --git a/.github/workflows/ci-api-proto.yml b/.github/workflows/ci-api-proto.yml index 448d0fd10f..1628464061 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@v4.1.5 + uses: actions/checkout@v4.1.6 - name: Set up Python uses: actions/setup-python@v5.1.0 with: diff --git a/.github/workflows/ci-docker.yml b/.github/workflows/ci-docker.yml index 72a16233fb..dd5c051cfb 100644 --- a/.github/workflows/ci-docker.yml +++ b/.github/workflows/ci-docker.yml @@ -40,7 +40,7 @@ jobs: arch: [amd64, armv7, aarch64] build_type: ["ha-addon", "docker", "lint"] steps: - - uses: actions/checkout@v4.1.5 + - uses: actions/checkout@v4.1.6 - name: Set up Python uses: actions/setup-python@v5.1.0 with: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ba0a8a363c..2b3c80cb35 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,7 +34,7 @@ jobs: cache-key: ${{ steps.cache-key.outputs.key }} steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.5 + uses: actions/checkout@v4.1.6 - name: Generate cache-key id: cache-key run: echo key="${{ hashFiles('requirements.txt', 'requirements_optional.txt', 'requirements_test.txt') }}" >> $GITHUB_OUTPUT @@ -66,7 +66,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.5 + uses: actions/checkout@v4.1.6 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -87,7 +87,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.5 + uses: actions/checkout@v4.1.6 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -108,7 +108,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.5 + uses: actions/checkout@v4.1.6 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -129,7 +129,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.5 + uses: actions/checkout@v4.1.6 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -150,7 +150,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.5 + uses: actions/checkout@v4.1.6 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -199,7 +199,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.5 + uses: actions/checkout@v4.1.6 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -229,7 +229,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.5 + uses: actions/checkout@v4.1.6 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -254,7 +254,7 @@ jobs: matrix: ${{ steps.set-matrix.outputs.matrix }} steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.5 + uses: actions/checkout@v4.1.6 - name: Find all YAML test files id: set-matrix run: echo "matrix=$(ls tests/test*.yaml | jq -R -s -c 'split("\n")[:-1]')" >> $GITHUB_OUTPUT @@ -271,7 +271,7 @@ jobs: file: ${{ fromJson(needs.compile-tests-list.outputs.matrix) }} steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.5 + uses: actions/checkout@v4.1.6 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -303,7 +303,7 @@ jobs: file: ${{ fromJson(needs.compile-tests-list.outputs.matrix) }} steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.5 + uses: actions/checkout@v4.1.6 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -358,7 +358,7 @@ jobs: steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.5 + uses: actions/checkout@v4.1.6 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -410,7 +410,7 @@ jobs: count: ${{ steps.list-components.outputs.count }} steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.5 + uses: actions/checkout@v4.1.6 with: # Fetch enough history so `git merge-base refs/remotes/origin/dev HEAD` works. fetch-depth: 500 @@ -458,7 +458,7 @@ jobs: run: sudo apt-get install libsodium-dev - name: Check out code from GitHub - uses: actions/checkout@v4.1.5 + uses: actions/checkout@v4.1.6 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -484,7 +484,7 @@ jobs: matrix: ${{ steps.split.outputs.components }} steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.5 + uses: actions/checkout@v4.1.6 - name: Split components into 20 groups id: split run: | @@ -512,7 +512,7 @@ jobs: run: sudo apt-get install libsodium-dev - name: Check out code from GitHub - uses: actions/checkout@v4.1.5 + uses: actions/checkout@v4.1.6 - name: Restore Python uses: ./.github/actions/restore-python with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c1c502394a..47dc217bf7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,7 +19,7 @@ jobs: tag: ${{ steps.tag.outputs.tag }} branch_build: ${{ steps.tag.outputs.branch_build }} steps: - - uses: actions/checkout@v4.1.5 + - uses: actions/checkout@v4.1.6 - name: Get tag id: tag # yamllint disable rule:line-length @@ -51,7 +51,7 @@ jobs: contents: read id-token: write steps: - - uses: actions/checkout@v4.1.5 + - uses: actions/checkout@v4.1.6 - name: Set up Python uses: actions/setup-python@v5.1.0 with: @@ -83,7 +83,7 @@ jobs: - linux/arm/v7 - linux/arm64 steps: - - uses: actions/checkout@v4.1.5 + - uses: actions/checkout@v4.1.6 - name: Set up Python uses: actions/setup-python@v5.1.0 with: @@ -174,7 +174,7 @@ jobs: - ghcr - dockerhub steps: - - uses: actions/checkout@v4.1.5 + - uses: actions/checkout@v4.1.6 - name: Download digests uses: actions/download-artifact@v4.1.7 diff --git a/.github/workflows/sync-device-classes.yml b/.github/workflows/sync-device-classes.yml index 7d67999b77..9a8c9d1753 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@v4.1.5 + uses: actions/checkout@v4.1.6 - name: Checkout Home Assistant - uses: actions/checkout@v4.1.5 + uses: actions/checkout@v4.1.6 with: repository: home-assistant/core path: lib/home-assistant diff --git a/.github/workflows/yaml-lint.yml b/.github/workflows/yaml-lint.yml index 761247529b..f009643629 100644 --- a/.github/workflows/yaml-lint.yml +++ b/.github/workflows/yaml-lint.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.5 + uses: actions/checkout@v4.1.6 - name: Run yamllint uses: frenck/action-yamllint@v1.5.0 with: From 080f8bc86ed215dd12a1f6dc8d0b2bfa80302df2 Mon Sep 17 00:00:00 2001 From: Markus <974709+Links2004@users.noreply.github.com> Date: Sun, 19 May 2024 22:33:20 +0200 Subject: [PATCH 1473/2101] Fix Upload from Dashboard with MQTT discovery. (#6774) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/__main__.py b/esphome/__main__.py index 9930119c86..f3c4ff3e23 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -351,7 +351,7 @@ def upload_program(config, args, host): not is_ip_address(CORE.address) # pylint: disable=too-many-boolean-expressions and (get_port_type(host) == "MQTT" or config[CONF_MDNS][CONF_DISABLED]) and CONF_MQTT in config - and (not args.device or args.device == "MQTT") + and (not args.device or args.device in ("MQTT", "OTA")) ): from esphome import mqtt From 91e7a44c3172cddddc93804e04206a962384e2ab Mon Sep 17 00:00:00 2001 From: Markus <974709+Links2004@users.noreply.github.com> Date: Mon, 20 May 2024 01:52:14 +0200 Subject: [PATCH 1474/2101] Fix MQTT dashboard discovery (Exception in MqttStatusThread). (#6775) --- esphome/dashboard/status/mqtt.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/dashboard/status/mqtt.py b/esphome/dashboard/status/mqtt.py index 8c35dd2535..0e53c21679 100644 --- a/esphome/dashboard/status/mqtt.py +++ b/esphome/dashboard/status/mqtt.py @@ -18,7 +18,7 @@ class MqttStatusThread(threading.Thread): """Run the status thread.""" dashboard = DASHBOARD entries = dashboard.entries - current_entries = entries.all() + current_entries = entries.async_all() config = mqtt.config_from_env() topic = "esphome/discover/#" @@ -33,7 +33,7 @@ class MqttStatusThread(threading.Thread): return for entry in current_entries: if entry.name == data["name"]: - entries.set_state(entry, EntryState.ONLINE) + entries.async_set_state(entry, EntryState.ONLINE) return def on_connect(client, userdata, flags, return_code): @@ -53,11 +53,11 @@ class MqttStatusThread(threading.Thread): client.loop_start() while not dashboard.stop_event.wait(2): - current_entries = entries.all() + current_entries = entries.async_all() # will be set to true on on_message for entry in current_entries: if entry.no_mdns: - entries.set_state(entry, EntryState.OFFLINE) + entries.async_set_state(entry, EntryState.OFFLINE) client.publish("esphome/discover", None, retain=False) dashboard.mqtt_ping_request.wait() From b9bb3cd4bec794f155357e1688831456df77734d Mon Sep 17 00:00:00 2001 From: fodfodfod <94200657+fodfodfod@users.noreply.github.com> Date: Sun, 19 May 2024 20:42:30 -0400 Subject: [PATCH 1475/2101] add rp2040 support to the wizard (#6239) --- esphome/wizard.py | 115 ++++++++++++++++++++++++++-------------------- 1 file changed, 64 insertions(+), 51 deletions(-) diff --git a/esphome/wizard.py b/esphome/wizard.py index 9680ade044..f8911ae844 100644 --- a/esphome/wizard.py +++ b/esphome/wizard.py @@ -277,6 +277,7 @@ def wizard(path): from esphome.components.esp32 import boards as esp32_boards from esphome.components.esp8266 import boards as esp8266_boards from esphome.components.rtl87xx import boards as rtl87xx_boards + from esphome.components.rp2040 import boards as rp2040_boards if not path.endswith(".yaml") and not path.endswith(".yml"): safe_print( @@ -343,7 +344,7 @@ def wizard(path): "firmwares for it." ) - wizard_platforms = ["ESP32", "ESP8266", "BK72XX", "RTL87XX"] + wizard_platforms = ["ESP32", "ESP8266", "BK72XX", "RTL87XX", "RP2040"] safe_print( "Please choose one of the supported microcontrollers " "(Use ESP8266 for Sonoff devices)." @@ -373,6 +374,10 @@ def wizard(path): board_link = ( "http://docs.platformio.org/en/latest/platforms/espressif8266.html#boards" ) + elif platform == "RP2040": + board_link = ( + "https://www.raspberrypi.com/documentation/microcontrollers/rp2040.html" + ) elif platform in ["BK72XX", "RTL87XX"]: board_link = "https://docs.libretiny.eu/docs/status/supported/" else: @@ -397,6 +402,10 @@ def wizard(path): elif platform == "RTL87XX": safe_print(f"For example \"{color(Fore.BOLD_WHITE, 'wr3')}\".") boards_list = rtl87xx_boards.BOARDS.items() + elif platform == "RP2040": + safe_print(f"For example \"{color(Fore.BOLD_WHITE, 'rpipicow')}\".") + boards_list = rp2040_boards.BOARDS.items() + else: raise NotImplementedError("Unknown platform!") @@ -423,60 +432,64 @@ def wizard(path): safe_print() sleep(1) - safe_print_step(3, WIFI_BIG) - safe_print("In this step, I'm going to create the configuration for WiFi.") - safe_print() - sleep(1) - safe_print( - f"First, what's the {color(Fore.GREEN, 'SSID')} (the name) of the WiFi network {name} should connect to?" - ) - sleep(1.5) - safe_print(f"For example \"{color(Fore.BOLD_WHITE, 'Abraham Linksys')}\".") - while True: - ssid = safe_input(color(Fore.BOLD_WHITE, "(ssid): ")) - try: - ssid = cv.ssid(ssid) - break - except vol.Invalid: - safe_print( - color( - Fore.RED, - f'Unfortunately, "{ssid}" doesn\'t seem to be a valid SSID. Please try again.', + # Do not create wifi if the board does not support it + if board not in ["rpipico"]: + safe_print_step(3, WIFI_BIG) + safe_print("In this step, I'm going to create the configuration for WiFi.") + safe_print() + sleep(1) + safe_print( + f"First, what's the {color(Fore.GREEN, 'SSID')} (the name) of the WiFi network {name} should connect to?" + ) + sleep(1.5) + safe_print(f"For example \"{color(Fore.BOLD_WHITE, 'Abraham Linksys')}\".") + while True: + ssid = safe_input(color(Fore.BOLD_WHITE, "(ssid): ")) + try: + ssid = cv.ssid(ssid) + break + except vol.Invalid: + safe_print( + color( + Fore.RED, + f'Unfortunately, "{ssid}" doesn\'t seem to be a valid SSID. Please try again.', + ) ) - ) - safe_print() - sleep(1) + safe_print() + sleep(1) - safe_print( - f'Thank you very much! You\'ve just chosen "{color(Fore.CYAN, ssid)}" as your SSID.' - ) - safe_print() - sleep(0.75) + safe_print( + f'Thank you very much! You\'ve just chosen "{color(Fore.CYAN, ssid)}" as your SSID.' + ) + safe_print() + sleep(0.75) - safe_print( - f"Now please state the {color(Fore.GREEN, 'password')} of the WiFi network so that I can connect to it (Leave empty for no password)" - ) - safe_print() - safe_print(f"For example \"{color(Fore.BOLD_WHITE, 'PASSWORD42')}\"") - sleep(0.5) - psk = safe_input(color(Fore.BOLD_WHITE, "(PSK): ")) - safe_print( - "Perfect! WiFi is now set up (you can create static IPs and so on later)." - ) - sleep(1.5) + safe_print( + f"Now please state the {color(Fore.GREEN, 'password')} of the WiFi network so that I can connect to it (Leave empty for no password)" + ) + safe_print() + safe_print(f"For example \"{color(Fore.BOLD_WHITE, 'PASSWORD42')}\"") + sleep(0.5) + psk = safe_input(color(Fore.BOLD_WHITE, "(PSK): ")) + safe_print( + "Perfect! WiFi is now set up (you can create static IPs and so on later)." + ) + sleep(1.5) - safe_print_step(4, OTA_BIG) - safe_print( - "Almost there! ESPHome can automatically upload custom firmwares over WiFi " - "(over the air) and integrates into Home Assistant with a native API." - ) - safe_print( - f"This can be insecure if you do not trust the WiFi network. Do you want to set a {color(Fore.GREEN, 'password')} for connecting to this ESP?" - ) - safe_print() - sleep(0.25) - safe_print("Press ENTER for no password") - password = safe_input(color(Fore.BOLD_WHITE, "(password): ")) + safe_print_step(4, OTA_BIG) + safe_print( + "Almost there! ESPHome can automatically upload custom firmwares over WiFi " + "(over the air) and integrates into Home Assistant with a native API." + ) + safe_print( + f"This can be insecure if you do not trust the WiFi network. Do you want to set a {color(Fore.GREEN, 'password')} for connecting to this ESP?" + ) + safe_print() + sleep(0.25) + safe_print("Press ENTER for no password") + password = safe_input(color(Fore.BOLD_WHITE, "(password): ")) + else: + ssid, password, psk = "", "", "" if not wizard_write( path=path, From 840f69ffe673401f5b1434dbf23213a51489d569 Mon Sep 17 00:00:00 2001 From: acshef Date: Fri, 17 May 2024 22:17:09 -0600 Subject: [PATCH 1476/2101] Add device_class to valve core config (#6765) --- esphome/components/valve/__init__.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/esphome/components/valve/__init__.py b/esphome/components/valve/__init__.py index 22d617cc36..13c2947438 100644 --- a/esphome/components/valve/__init__.py +++ b/esphome/components/valve/__init__.py @@ -14,6 +14,8 @@ from esphome.const import ( CONF_STATE, CONF_STOP, CONF_TRIGGER_ID, + DEVICE_CLASS_GAS, + DEVICE_CLASS_WATER, ) from esphome.core import CORE, coroutine_with_priority from esphome.cpp_helpers import setup_entity @@ -22,6 +24,11 @@ IS_PLATFORM_COMPONENT = True CODEOWNERS = ["@esphome/core"] +DEVICE_CLASSES = [ + DEVICE_CLASS_GAS, + DEVICE_CLASS_WATER, +] + valve_ns = cg.esphome_ns.namespace("valve") Valve = valve_ns.class_("Valve", cg.EntityBase) @@ -65,6 +72,7 @@ VALVE_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA).ex { cv.GenerateID(): cv.declare_id(Valve), cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTValveComponent), + 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 ), From 4fc2f2284afd663d6e5649a959ed312dc96c5a38 Mon Sep 17 00:00:00 2001 From: esphomebot Date: Sat, 18 May 2024 19:15:52 +1200 Subject: [PATCH 1477/2101] Synchronise Device Classes from Home Assistant (#6768) --- esphome/components/valve/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/components/valve/__init__.py b/esphome/components/valve/__init__.py index 13c2947438..ea6bfc6055 100644 --- a/esphome/components/valve/__init__.py +++ b/esphome/components/valve/__init__.py @@ -14,6 +14,7 @@ from esphome.const import ( CONF_STATE, CONF_STOP, CONF_TRIGGER_ID, + DEVICE_CLASS_EMPTY, DEVICE_CLASS_GAS, DEVICE_CLASS_WATER, ) @@ -25,6 +26,7 @@ IS_PLATFORM_COMPONENT = True CODEOWNERS = ["@esphome/core"] DEVICE_CLASSES = [ + DEVICE_CLASS_EMPTY, DEVICE_CLASS_GAS, DEVICE_CLASS_WATER, ] From 7452879fb1a85c4bd1795b44d08c4853595ae97e Mon Sep 17 00:00:00 2001 From: Markus <974709+Links2004@users.noreply.github.com> Date: Sun, 19 May 2024 22:33:20 +0200 Subject: [PATCH 1478/2101] Fix Upload from Dashboard with MQTT discovery. (#6774) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/__main__.py b/esphome/__main__.py index 54c1aa112a..1d316a97ee 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -346,7 +346,7 @@ def upload_program(config, args, host): not is_ip_address(CORE.address) # pylint: disable=too-many-boolean-expressions and (get_port_type(host) == "MQTT" or config[CONF_MDNS][CONF_DISABLED]) and CONF_MQTT in config - and (not args.device or args.device == "MQTT") + and (not args.device or args.device in ("MQTT", "OTA")) ): from esphome import mqtt From ec6d86c8f5a57ca652449ed9b91b5e975d23f882 Mon Sep 17 00:00:00 2001 From: Markus <974709+Links2004@users.noreply.github.com> Date: Mon, 20 May 2024 01:52:14 +0200 Subject: [PATCH 1479/2101] Fix MQTT dashboard discovery (Exception in MqttStatusThread). (#6775) --- esphome/dashboard/status/mqtt.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/dashboard/status/mqtt.py b/esphome/dashboard/status/mqtt.py index 8c35dd2535..0e53c21679 100644 --- a/esphome/dashboard/status/mqtt.py +++ b/esphome/dashboard/status/mqtt.py @@ -18,7 +18,7 @@ class MqttStatusThread(threading.Thread): """Run the status thread.""" dashboard = DASHBOARD entries = dashboard.entries - current_entries = entries.all() + current_entries = entries.async_all() config = mqtt.config_from_env() topic = "esphome/discover/#" @@ -33,7 +33,7 @@ class MqttStatusThread(threading.Thread): return for entry in current_entries: if entry.name == data["name"]: - entries.set_state(entry, EntryState.ONLINE) + entries.async_set_state(entry, EntryState.ONLINE) return def on_connect(client, userdata, flags, return_code): @@ -53,11 +53,11 @@ class MqttStatusThread(threading.Thread): client.loop_start() while not dashboard.stop_event.wait(2): - current_entries = entries.all() + current_entries = entries.async_all() # will be set to true on on_message for entry in current_entries: if entry.no_mdns: - entries.set_state(entry, EntryState.OFFLINE) + entries.async_set_state(entry, EntryState.OFFLINE) client.publish("esphome/discover", None, retain=False) dashboard.mqtt_ping_request.wait() From d2d3db4b8c2a29db046eb3478199c9917a28904d Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 20 May 2024 17:14:17 +1200 Subject: [PATCH 1480/2101] Bump version to 2024.5.1 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 9871ea704f..9d2b8b78ea 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.5.0" +__version__ = "2024.5.1" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 25ee24299a220c231baf37d50156ee35d78e561c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 20 May 2024 01:49:00 -1000 Subject: [PATCH 1481/2101] Revert "Fix MQTT dashboard discovery (Exception in MqttStatusThread)." (#6782) --- esphome/dashboard/status/mqtt.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/dashboard/status/mqtt.py b/esphome/dashboard/status/mqtt.py index 0e53c21679..8c35dd2535 100644 --- a/esphome/dashboard/status/mqtt.py +++ b/esphome/dashboard/status/mqtt.py @@ -18,7 +18,7 @@ class MqttStatusThread(threading.Thread): """Run the status thread.""" dashboard = DASHBOARD entries = dashboard.entries - current_entries = entries.async_all() + current_entries = entries.all() config = mqtt.config_from_env() topic = "esphome/discover/#" @@ -33,7 +33,7 @@ class MqttStatusThread(threading.Thread): return for entry in current_entries: if entry.name == data["name"]: - entries.async_set_state(entry, EntryState.ONLINE) + entries.set_state(entry, EntryState.ONLINE) return def on_connect(client, userdata, flags, return_code): @@ -53,11 +53,11 @@ class MqttStatusThread(threading.Thread): client.loop_start() while not dashboard.stop_event.wait(2): - current_entries = entries.async_all() + current_entries = entries.all() # will be set to true on on_message for entry in current_entries: if entry.no_mdns: - entries.async_set_state(entry, EntryState.OFFLINE) + entries.set_state(entry, EntryState.OFFLINE) client.publish("esphome/discover", None, retain=False) dashboard.mqtt_ping_request.wait() From 59b1e9c1b024191a666b98e97fe60da18de0d4e8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 20 May 2024 01:52:24 -1000 Subject: [PATCH 1482/2101] Fix DashboardEntries.all() call (#6783) --- esphome/dashboard/entries.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/dashboard/entries.py b/esphome/dashboard/entries.py index cd318ba8a7..7a9bff4ec1 100644 --- a/esphome/dashboard/entries.py +++ b/esphome/dashboard/entries.py @@ -103,7 +103,7 @@ class DashboardEntries: def all(self) -> list[DashboardEntry]: """Return all entries.""" - return asyncio.run_coroutine_threadsafe(self._async_all, self._loop).result() + return asyncio.run_coroutine_threadsafe(self._async_all(), self._loop).result() def async_all(self) -> list[DashboardEntry]: """Return all entries.""" From bad400e1cd2da09a2d3cf8072bc1d66bfe6d0801 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Tue, 21 May 2024 07:18:13 +1000 Subject: [PATCH 1483/2101] [ili9xxx] Add 18bit mode selection and custom init sequence (#6745) --- esphome/components/ili9xxx/display.py | 58 ++++++++++++-- .../components/ili9xxx/ili9xxx_display.cpp | 80 +++++++++++++++---- esphome/components/ili9xxx/ili9xxx_display.h | 14 +++- tests/components/ili9xxx/test.esp32-idf.yaml | 20 +---- 4 files changed, 132 insertions(+), 40 deletions(-) diff --git a/esphome/components/ili9xxx/display.py b/esphome/components/ili9xxx/display.py index 3aaf76d6f8..f0ac5ba9ef 100644 --- a/esphome/components/ili9xxx/display.py +++ b/esphome/components/ili9xxx/display.py @@ -47,6 +47,12 @@ ILI9XXXDisplay = ili9xxx_ns.class_( display.DisplayBuffer, ) +PixelMode = ili9xxx_ns.enum("PixelMode") +PIXEL_MODES = { + "16bit": PixelMode.PIXEL_MODE_16, + "18bit": PixelMode.PIXEL_MODE_18, +} + ILI9XXXColorMode = ili9xxx_ns.enum("ILI9XXXColorMode") ColorOrder = display.display_ns.enum("ColorMode") @@ -68,6 +74,7 @@ MODELS = { "S3BOX": ili9xxx_ns.class_("ILI9XXXS3Box", ILI9XXXDisplay), "S3BOX_LITE": ili9xxx_ns.class_("ILI9XXXS3BoxLite", ILI9XXXDisplay), "WAVESHARE_RES_3_5": ili9xxx_ns.class_("WAVESHARERES35", ILI9XXXDisplay), + "CUSTOM": ILI9XXXDisplay, } COLOR_ORDERS = { @@ -80,14 +87,37 @@ COLOR_PALETTE = cv.one_of("NONE", "GRAYSCALE", "IMAGE_ADAPTIVE") CONF_LED_PIN = "led_pin" CONF_COLOR_PALETTE_IMAGES = "color_palette_images" CONF_INVERT_DISPLAY = "invert_display" +CONF_PIXEL_MODE = "pixel_mode" +CONF_INIT_SEQUENCE = "init_sequence" + + +def cmd(c, *args): + """ + Create a command sequence + :param c: The command (8 bit) + :param args: zero or more arguments (8 bit values) + :return: a list with the command, the argument count and the arguments + """ + return [c, len(args)] + list(args) + + +def map_sequence(value): + """ + An initialisation sequence is a literal array of data bytes. + The format is a repeated sequence of [CMD, ] + """ + if len(value) == 0: + raise cv.Invalid("Empty sequence") + return cmd(*value) def _validate(config): - if config.get(CONF_COLOR_PALETTE) == "IMAGE_ADAPTIVE" and not config.get( - CONF_COLOR_PALETTE_IMAGES + if ( + config.get(CONF_COLOR_PALETTE) == "IMAGE_ADAPTIVE" + and CONF_COLOR_PALETTE_IMAGES not in config ): raise cv.Invalid( - "Color palette in IMAGE_ADAPTIVE mode requires at least one 'color_palette_images' entry to generate palette" + "IMAGE_ADAPTIVE palette requires at least one 'color_palette_images' entry" ) if ( config.get(CONF_COLOR_PALETTE_IMAGES) @@ -96,7 +126,8 @@ def _validate(config): raise cv.Invalid( "Providing color palette images requires palette mode to be 'IMAGE_ADAPTIVE'" ) - if CORE.is_esp8266 and config.get(CONF_MODEL) not in [ + model = config[CONF_MODEL] + if CORE.is_esp8266 and model not in [ "M5STACK", "TFT_2.4", "TFT_2.4R", @@ -104,9 +135,12 @@ def _validate(config): "ILI9342", "ST7789V", ]: - raise cv.Invalid( - "Provided model can't run on ESP8266. Use an ESP32 with PSRAM onboard" - ) + raise cv.Invalid("Selected model can't run on ESP8266.") + + if model == "CUSTOM": + if CONF_INIT_SEQUENCE not in config or CONF_DIMENSIONS not in config: + raise cv.Invalid("CUSTOM model requires init_sequence and dimensions") + return config @@ -116,6 +150,7 @@ CONFIG_SCHEMA = cv.All( { cv.GenerateID(): cv.declare_id(ILI9XXXDisplay), cv.Required(CONF_MODEL): cv.enum(MODELS, upper=True, space="_"), + cv.Optional(CONF_PIXEL_MODE): cv.enum(PIXEL_MODES), cv.Optional(CONF_DIMENSIONS): cv.Any( cv.dimensions, cv.Schema( @@ -150,6 +185,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_MIRROR_Y, default=False): cv.boolean, } ), + cv.Optional(CONF_INIT_SEQUENCE): cv.ensure_list(map_sequence), } ) .extend(cv.polling_component_schema("1s")) @@ -167,6 +203,14 @@ async def to_code(config): await spi.register_spi_device(var, config) 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): + sequence = [] + for seq in init_sequences: + sequence.extend(seq) + cg.add(var.add_init_sequence(sequence)) + + if pixel_mode := config.get(CONF_PIXEL_MODE): + cg.add(var.set_pixel_mode(pixel_mode)) if CONF_COLOR_ORDER in config: cg.add(var.set_color_order(COLOR_ORDERS[config[CONF_COLOR_ORDER]])) if CONF_TRANSFORM in config: diff --git a/esphome/components/ili9xxx/ili9xxx_display.cpp b/esphome/components/ili9xxx/ili9xxx_display.cpp index e292906a93..463e3dd851 100644 --- a/esphome/components/ili9xxx/ili9xxx_display.cpp +++ b/esphome/components/ili9xxx/ili9xxx_display.cpp @@ -34,7 +34,26 @@ void ILI9XXXDisplay::setup() { ESP_LOGD(TAG, "Setting up ILI9xxx"); this->setup_pins_(); - this->init_lcd_(); + this->init_lcd_(this->init_sequence_); + this->init_lcd_(this->extra_init_sequence_.data()); + switch (this->pixel_mode_) { + case PIXEL_MODE_16: + if (this->is_18bitdisplay_) { + this->command(ILI9XXX_PIXFMT); + this->data(0x55); + this->is_18bitdisplay_ = false; + } + break; + case PIXEL_MODE_18: + if (!this->is_18bitdisplay_) { + this->command(ILI9XXX_PIXFMT); + this->data(0x66); + this->is_18bitdisplay_ = true; + } + break; + default: + break; + } this->set_madctl(); this->command(this->pre_invertcolors_ ? ILI9XXX_INVON : ILI9XXX_INVOFF); @@ -203,7 +222,6 @@ void ILI9XXXDisplay::update() { } void ILI9XXXDisplay::display_() { - uint8_t transfer_buffer[ILI9XXX_TRANSFER_BUFFER_SIZE]; // check if something was displayed if ((this->x_high_ < this->x_low_) || (this->y_high_ < this->y_low_)) { return; @@ -231,6 +249,7 @@ void ILI9XXXDisplay::display_() { this->write_array(this->buffer_ + this->y_low_ * this->width_ * 2, h * this->width_ * 2); } else { ESP_LOGV(TAG, "Doing multiple write"); + uint8_t transfer_buffer[ILI9XXX_TRANSFER_BUFFER_SIZE]; size_t rem = h * w; // remaining number of pixels to write set_addr_window_(this->x_low_, this->y_low_, this->x_high_, this->y_high_); size_t idx = 0; // index into transfer_buffer @@ -247,7 +266,7 @@ void ILI9XXXDisplay::display_() { display::ColorUtil::index8_to_color_palette888(this->buffer_[pos++], this->palette_)); break; default: // case BITS_16: - color_val = (buffer_[pos * 2] << 8) + buffer_[pos * 2 + 1]; + color_val = (this->buffer_[pos * 2] << 8) + this->buffer_[pos * 2 + 1]; pos++; break; } @@ -259,7 +278,7 @@ void ILI9XXXDisplay::display_() { put16_be(transfer_buffer + idx, color_val); idx += 2; } - if (idx == ILI9XXX_TRANSFER_BUFFER_SIZE) { + if (idx == sizeof(transfer_buffer)) { this->write_array(transfer_buffer, idx); idx = 0; App.feed_wdt(); @@ -293,20 +312,50 @@ void ILI9XXXDisplay::draw_pixels_at(int x_start, int y_start, int w, int h, cons // if color mapping or software rotation is required, hand this off to the parent implementation. This will // do color conversion pixel-by-pixel into the buffer and draw it later. If this is happening the user has not // configured the renderer well. - if (this->rotation_ != display::DISPLAY_ROTATION_0_DEGREES || bitness != display::COLOR_BITNESS_565 || !big_endian || - this->is_18bitdisplay_) { + if (this->rotation_ != display::DISPLAY_ROTATION_0_DEGREES || bitness != display::COLOR_BITNESS_565 || !big_endian) { return display::Display::draw_pixels_at(x_start, y_start, w, h, ptr, order, bitness, big_endian, x_offset, y_offset, x_pad); } this->set_addr_window_(x_start, y_start, x_start + w - 1, y_start + h - 1); // x_ and y_offset are offsets into the source buffer, unrelated to our own offsets into the display. - if (x_offset == 0 && x_pad == 0 && y_offset == 0) { - // we could deal here with a non-zero y_offset, but if x_offset is zero, y_offset probably will be so don't bother - this->write_array(ptr, w * h * 2); + auto stride = x_offset + w + x_pad; + if (!this->is_18bitdisplay_) { + if (x_offset == 0 && x_pad == 0 && y_offset == 0) { + // we could deal here with a non-zero y_offset, but if x_offset is zero, y_offset probably will be so don't bother + this->write_array(ptr, w * h * 2); + } else { + for (size_t y = 0; y != h; y++) { + this->write_array(ptr + (y + y_offset) * stride + x_offset, w * 2); + } + } } else { - auto stride = x_offset + w + x_pad; - for (size_t y = 0; y != h; y++) { - this->write_array(ptr + (y + y_offset) * stride + x_offset, w * 2); + // 18 bit mode + uint8_t transfer_buffer[ILI9XXX_TRANSFER_BUFFER_SIZE * 4]; + ESP_LOGV(TAG, "Doing multiple write"); + size_t rem = h * w; // remaining number of pixels to write + size_t idx = 0; // index into transfer_buffer + size_t pixel = 0; // pixel number offset + ptr += (y_offset * stride + x_offset) * 2; + while (rem-- != 0) { + uint8_t hi_byte = *ptr++; + uint8_t lo_byte = *ptr++; + transfer_buffer[idx++] = hi_byte & 0xF8; // Blue + transfer_buffer[idx++] = ((hi_byte << 5) | (lo_byte) >> 5); // Green + transfer_buffer[idx++] = lo_byte << 3; // Red + if (idx == sizeof(transfer_buffer)) { + this->write_array(transfer_buffer, idx); + idx = 0; + App.feed_wdt(); + } + // end of line? Skip to the next. + if (++pixel == w) { + pixel = 0; + ptr += (x_pad + x_offset) * 2; + } + } + // flush any balance. + if (idx != 0) { + this->write_array(transfer_buffer, idx); } } this->end_data_(); @@ -356,10 +405,11 @@ void ILI9XXXDisplay::reset_() { } } -void ILI9XXXDisplay::init_lcd_() { +void ILI9XXXDisplay::init_lcd_(const uint8_t *addr) { + if (addr == nullptr) + return; uint8_t cmd, x, num_args; - const uint8_t *addr = this->init_sequence_; - while ((cmd = *addr++) > 0) { + while ((cmd = *addr++) != 0) { x = *addr++; num_args = x & 0x7F; this->send_command(cmd, addr, num_args); diff --git a/esphome/components/ili9xxx/ili9xxx_display.h b/esphome/components/ili9xxx/ili9xxx_display.h index 11a90e142f..4446686e7b 100644 --- a/esphome/components/ili9xxx/ili9xxx_display.h +++ b/esphome/components/ili9xxx/ili9xxx_display.h @@ -17,6 +17,12 @@ enum ILI9XXXColorMode { BITS_16 = 0x10, }; +enum PixelMode { + PIXEL_MODE_UNSPECIFIED, + PIXEL_MODE_16, + PIXEL_MODE_18, +}; + class ILI9XXXDisplay : public display::DisplayBuffer, public spi::SPIDevice { @@ -52,6 +58,7 @@ class ILI9XXXDisplay : public display::DisplayBuffer, } } + void add_init_sequence(const std::vector &sequence) { this->extra_init_sequence_ = sequence; } 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; } @@ -73,6 +80,7 @@ class ILI9XXXDisplay : public display::DisplayBuffer, void set_swap_xy(bool swap_xy) { this->swap_xy_ = swap_xy; } void set_mirror_x(bool mirror_x) { this->mirror_x_ = mirror_x; } void set_mirror_y(bool mirror_y) { this->mirror_y_ = mirror_y; } + void set_pixel_mode(PixelMode mode) { this->pixel_mode_ = mode; } void update() override; @@ -99,11 +107,12 @@ class ILI9XXXDisplay : public display::DisplayBuffer, virtual void set_madctl(); void display_(); - void init_lcd_(); + void init_lcd_(const uint8_t *addr); void set_addr_window_(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2); void reset_(); uint8_t const *init_sequence_{}; + std::vector extra_init_sequence_; int16_t width_{0}; ///< Display width as modified by current rotation int16_t height_{0}; ///< Display height as modified by current rotation int16_t offset_x_{0}; @@ -112,7 +121,7 @@ class ILI9XXXDisplay : public display::DisplayBuffer, uint16_t y_low_{0}; uint16_t x_high_{0}; uint16_t y_high_{0}; - const uint8_t *palette_; + const uint8_t *palette_{}; ILI9XXXColorMode buffer_color_mode_{BITS_16}; @@ -133,6 +142,7 @@ class ILI9XXXDisplay : public display::DisplayBuffer, bool prossing_update_ = false; bool need_update_ = false; bool is_18bitdisplay_ = false; + PixelMode pixel_mode_{}; bool pre_invertcolors_ = false; display::ColorOrder color_order_{display::COLOR_ORDER_BGR}; bool swap_xy_{}; diff --git a/tests/components/ili9xxx/test.esp32-idf.yaml b/tests/components/ili9xxx/test.esp32-idf.yaml index 0d7bda8ac6..6da62f69d2 100644 --- a/tests/components/ili9xxx/test.esp32-idf.yaml +++ b/tests/components/ili9xxx/test.esp32-idf.yaml @@ -12,24 +12,12 @@ display: swap_xy: true mirror_x: true mirror_y: false - model: TFT 2.4 - color_palette: GRAYSCALE + model: custom cs_pin: 12 dc_pin: 13 reset_pin: 14 + init_sequence: + - [0xFF, 0x77, 0x01, 0x00, 0x00, 0x10] + lambda: |- it.rectangle(0, 0, it.get_width(), it.get_height()); - - platform: ili9xxx - dimensions: - width: 320 - height: 240 - offset_width: 20 - offset_height: 10 - model: TFT 2.4 - cs_pin: 25 - dc_pin: 26 - reset_pin: 27 - auto_clear_enabled: false - rotation: 90 - lambda: |- - it.fill(Color::WHITE); From 9de67feccd4b4c3ec9f5db40573c07ecca4bcf32 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 21 May 2024 10:53:16 +1200 Subject: [PATCH 1484/2101] [remote_receiver] Add better error message for tolerance breaking change (#6784) --- esphome/components/remote_receiver/__init__.py | 8 +++++++- tests/components/remote_receiver/esp32-common.yaml | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/esphome/components/remote_receiver/__init__.py b/esphome/components/remote_receiver/__init__.py index 6fe20153f4..e5085bb33c 100644 --- a/esphome/components/remote_receiver/__init__.py +++ b/esphome/components/remote_receiver/__init__.py @@ -63,7 +63,13 @@ def validate_tolerance(value): if "%" in str(value): type_ = TYPE_PERCENTAGE else: - type_ = TYPE_TIME + try: + cv.positive_time_period_microseconds(value) + type_ = TYPE_TIME + except cv.Invalid as exc: + raise cv.Invalid( + "Tolerance must be a percentage or time. Configurations made before 2024.5.0 treated the value as a percentage." + ) from exc return TOLERANCE_SCHEMA( { diff --git a/tests/components/remote_receiver/esp32-common.yaml b/tests/components/remote_receiver/esp32-common.yaml index c2b5a2cf19..c3987f8cd9 100644 --- a/tests/components/remote_receiver/esp32-common.yaml +++ b/tests/components/remote_receiver/esp32-common.yaml @@ -3,6 +3,7 @@ remote_receiver: pin: ${pin} rmt_channel: ${rmt_channel} dump: all + tolerance: 25% on_abbwelcome: then: - logger.log: From ce6dc040dab9bef5230c86840f8da3edacb7b8cd Mon Sep 17 00:00:00 2001 From: Anton Viktorov Date: Mon, 20 May 2024 22:54:38 +0000 Subject: [PATCH 1485/2101] Tiny fix in automation.h - unused return value removed (#6760) --- esphome/core/automation.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/core/automation.h b/esphome/core/automation.h index 9b62640a0c..5a0a17ea1a 100644 --- a/esphome/core/automation.h +++ b/esphome/core/automation.h @@ -233,7 +233,7 @@ template class Automation { public: explicit Automation(Trigger *trigger) : trigger_(trigger) { this->trigger_->set_automation_parent(this); } - Action *add_action(Action *action) { this->actions_.add_action(action); } + void add_action(Action *action) { this->actions_.add_action(action); } void add_actions(const std::vector *> &actions) { this->actions_.add_actions(actions); } void stop() { this->actions_.stop(); } From 525c4891d52f5c0d6bd5a79ba8c3400aa3e5d588 Mon Sep 17 00:00:00 2001 From: esphomebot Date: Tue, 21 May 2024 10:55:56 +1200 Subject: [PATCH 1486/2101] Update webserver local assets to 20240519-215627 (#6779) --- .../components/web_server/server_index_v3.h | 7970 ++++++++--------- 1 file changed, 3977 insertions(+), 3993 deletions(-) diff --git a/esphome/components/web_server/server_index_v3.h b/esphome/components/web_server/server_index_v3.h index 66cd9de47a..f2f278b08f 100644 --- a/esphome/components/web_server/server_index_v3.h +++ b/esphome/components/web_server/server_index_v3.h @@ -10,4004 +10,3988 @@ namespace esphome { namespace web_server { const uint8_t INDEX_GZ[] PROGMEM = { - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xcc, 0xbd, 0x6d, 0x7b, 0xdb, 0xb6, 0xb2, 0x28, 0xfa, - 0xf9, 0x9e, 0x5f, 0x61, 0x73, 0xa7, 0x2e, 0x61, 0x41, 0xb4, 0x24, 0x5b, 0x8e, 0x43, 0x19, 0xd6, 0x71, 0x9c, 0xa4, - 0x49, 0x9b, 0x26, 0x69, 0x9c, 0x26, 0x4d, 0x54, 0x6d, 0x07, 0x22, 0x21, 0x09, 0x0d, 0x45, 0xa8, 0x04, 0x14, 0xdb, - 0x95, 0xf4, 0xdf, 0xef, 0x33, 0x78, 0x21, 0x41, 0x49, 0xc9, 0x5a, 0xeb, 0xdc, 0x73, 0xee, 0x73, 0x76, 0xf7, 0x8a, - 0x45, 0xbc, 0x63, 0x30, 0x18, 0xcc, 0x0c, 0x66, 0x06, 0xe7, 0xfb, 0xa9, 0x48, 0xd4, 0xfd, 0x9c, 0xed, 0x4d, 0xd5, - 0x2c, 0xbb, 0x38, 0xb7, 0xff, 0x32, 0x9a, 0x5e, 0x9c, 0x67, 0x3c, 0xff, 0xb2, 0x57, 0xb0, 0x8c, 0xf0, 0x44, 0xe4, - 0x7b, 0xd3, 0x82, 0x8d, 0x49, 0x4a, 0x15, 0x8d, 0xf9, 0x8c, 0x4e, 0xd8, 0xde, 0xd1, 0xc5, 0xf9, 0x8c, 0x29, 0xba, - 0x97, 0x4c, 0x69, 0x21, 0x99, 0x22, 0xbf, 0xbf, 0x7b, 0xd6, 0x3c, 0xbb, 0x38, 0x97, 0x49, 0xc1, 0xe7, 0x6a, 0x0f, - 0x9a, 0x24, 0x33, 0x91, 0x2e, 0x32, 0x76, 0x71, 0x74, 0x74, 0x7b, 0x7b, 0x1b, 0xfd, 0x25, 0xff, 0xc7, 0x57, 0x5a, - 0xec, 0xfd, 0x52, 0x90, 0xd7, 0xa3, 0xbf, 0x58, 0xa2, 0xa2, 0x94, 0x8d, 0x79, 0xce, 0xde, 0x14, 0x62, 0xce, 0x0a, - 0x75, 0xdf, 0x83, 0xcc, 0x9f, 0x0a, 0x12, 0x72, 0xac, 0x30, 0x43, 0xe4, 0x42, 0xed, 0xf1, 0x7c, 0x8f, 0xf7, 0x7f, - 0x29, 0x74, 0xca, 0x92, 0xe5, 0x8b, 0x19, 0x2b, 0xe8, 0x28, 0x63, 0xf1, 0x7e, 0x0b, 0x27, 0x22, 0x1f, 0xf3, 0xc9, - 0xa2, 0xfc, 0xbe, 0x2d, 0xb8, 0x72, 0xbf, 0xbf, 0xd2, 0x6c, 0xc1, 0x62, 0xb6, 0x46, 0x31, 0x1f, 0xa8, 0x21, 0x61, - 0xba, 0xe5, 0x2f, 0x55, 0xc3, 0xe1, 0x4f, 0xba, 0xc9, 0xfb, 0x39, 0x13, 0xe3, 0x3d, 0xb5, 0x4f, 0x02, 0x79, 0x3f, - 0x1b, 0x89, 0x2c, 0xe8, 0xab, 0x46, 0x10, 0xc4, 0x50, 0x06, 0x33, 0xd4, 0x4b, 0x44, 0x2e, 0xd5, 0x9e, 0xe4, 0xe4, - 0x96, 0xe7, 0xa9, 0xb8, 0xc5, 0x5f, 0x25, 0x91, 0x3c, 0xba, 0x9e, 0xd2, 0x54, 0xdc, 0xbe, 0x15, 0x42, 0x1d, 0x1c, - 0x84, 0xf6, 0xfb, 0xfe, 0xea, 0xfa, 0x9a, 0x10, 0xf2, 0x55, 0xf0, 0x74, 0xaf, 0xb5, 0x5a, 0x79, 0xa9, 0x51, 0x4e, - 0x15, 0xff, 0xca, 0x4c, 0x25, 0x74, 0x70, 0x10, 0xd0, 0x54, 0xcc, 0x15, 0x4b, 0xaf, 0xd5, 0x7d, 0xc6, 0xae, 0xa7, - 0x8c, 0x29, 0x19, 0xf0, 0x7c, 0xef, 0x89, 0x48, 0x16, 0x33, 0x96, 0xab, 0x68, 0x5e, 0x08, 0x25, 0x60, 0x60, 0x07, - 0x07, 0x41, 0xc1, 0xe6, 0x19, 0x4d, 0x18, 0xe4, 0x5f, 0x5d, 0x5f, 0x57, 0x35, 0xaa, 0x42, 0xf8, 0x56, 0x92, 0x6b, - 0x3d, 0xf4, 0x10, 0xe1, 0xe7, 0x92, 0xe4, 0xec, 0x76, 0xef, 0x03, 0xa3, 0x5f, 0x7e, 0xa5, 0xf3, 0x5e, 0x92, 0x51, - 0x29, 0xf7, 0x9e, 0x89, 0xa5, 0x9e, 0x46, 0xb1, 0x48, 0x94, 0x28, 0x42, 0x85, 0x19, 0x96, 0x68, 0xc9, 0xc7, 0xa1, - 0x9a, 0x72, 0x19, 0xdd, 0x3c, 0x48, 0xa4, 0x7c, 0xcb, 0xe4, 0x22, 0x53, 0x0f, 0xc8, 0x7e, 0x0b, 0xcb, 0x7d, 0x42, - 0x6e, 0x25, 0x52, 0xd3, 0x42, 0xdc, 0xee, 0x3d, 0x2d, 0x0a, 0x51, 0x84, 0xc1, 0xd5, 0xf5, 0xb5, 0x29, 0xb1, 0xc7, - 0xe5, 0x5e, 0x2e, 0xd4, 0x5e, 0xd9, 0x1e, 0x40, 0x3b, 0xda, 0xfb, 0x5d, 0xb2, 0xbd, 0xcf, 0x8b, 0x5c, 0xd2, 0x31, - 0xbb, 0xba, 0xbe, 0xfe, 0xbc, 0x27, 0x8a, 0xbd, 0xcf, 0x89, 0x94, 0x9f, 0xf7, 0x78, 0x2e, 0x15, 0xa3, 0x69, 0x14, - 0xa0, 0x9e, 0xee, 0x2c, 0x91, 0xf2, 0x1d, 0xbb, 0x53, 0x44, 0x61, 0xfd, 0xa9, 0x08, 0x5b, 0x4f, 0x98, 0xda, 0x93, - 0xe5, 0xbc, 0x42, 0xb4, 0xcc, 0x98, 0xda, 0x53, 0x44, 0xe7, 0x0b, 0x0b, 0x7f, 0x66, 0x3e, 0x55, 0x8f, 0x8f, 0xc3, - 0xaf, 0xf2, 0xe0, 0x40, 0x95, 0x80, 0x46, 0x4b, 0xbb, 0x42, 0x84, 0xed, 0xbb, 0xb4, 0x83, 0x03, 0x16, 0x65, 0x2c, - 0x9f, 0xa8, 0x29, 0x21, 0xa4, 0xdd, 0x93, 0x07, 0x07, 0xa1, 0x22, 0xcf, 0x65, 0x34, 0x61, 0x2a, 0x64, 0x08, 0xe1, - 0xaa, 0xf6, 0xc1, 0x41, 0x68, 0x80, 0x20, 0x88, 0xd2, 0x80, 0xab, 0xc1, 0x18, 0x45, 0x16, 0xfa, 0xd7, 0xf7, 0x79, - 0x12, 0xfa, 0xe3, 0x47, 0x58, 0x1e, 0x1c, 0x3c, 0x97, 0x91, 0x84, 0x16, 0xb1, 0x42, 0x68, 0x5d, 0x30, 0xb5, 0x28, - 0xf2, 0x3d, 0xb5, 0x56, 0xe2, 0x5a, 0x15, 0x3c, 0x9f, 0x84, 0x68, 0xe9, 0xd2, 0xbc, 0x8a, 0xeb, 0xb5, 0x19, 0xee, - 0x6f, 0x05, 0xe1, 0xe4, 0x02, 0x7a, 0x7c, 0x26, 0x42, 0x8b, 0x83, 0x9c, 0x90, 0x40, 0xea, 0xba, 0x41, 0x9f, 0xc7, - 0xbc, 0x11, 0x04, 0xd8, 0x8c, 0x12, 0xdf, 0x4a, 0x84, 0xb9, 0x02, 0xd4, 0x8d, 0xa2, 0x48, 0x21, 0x72, 0xb1, 0x74, - 0x60, 0xe1, 0xde, 0x44, 0xfb, 0x7c, 0xd0, 0x1a, 0xc6, 0x2a, 0x2a, 0x58, 0xba, 0x48, 0x58, 0x18, 0x4a, 0x9c, 0x63, - 0x81, 0xc8, 0x85, 0x6c, 0x84, 0x05, 0xb9, 0x80, 0xf5, 0x2e, 0xea, 0x8b, 0x4d, 0xc8, 0x7e, 0x0b, 0xd9, 0x41, 0x16, - 0x6e, 0x84, 0x00, 0x62, 0x3b, 0xa0, 0x82, 0x90, 0x20, 0x5f, 0xcc, 0x46, 0xac, 0x08, 0xca, 0x62, 0xbd, 0x1a, 0x5e, - 0x2c, 0x24, 0xdb, 0x4b, 0xa4, 0xdc, 0x1b, 0x2f, 0xf2, 0x44, 0x71, 0x91, 0xef, 0x05, 0x8d, 0xa2, 0x11, 0x18, 0x7c, - 0x28, 0xd1, 0x21, 0x40, 0x6b, 0x14, 0xe6, 0xa8, 0xc1, 0x07, 0xa2, 0xd1, 0x1e, 0x62, 0x18, 0x25, 0xea, 0xd9, 0xf6, - 0x2c, 0x04, 0x18, 0xe6, 0x30, 0xc9, 0x35, 0xfe, 0x64, 0x76, 0x3e, 0x4c, 0xf1, 0xab, 0xec, 0xf3, 0x68, 0x7b, 0xa7, - 0x10, 0x15, 0xcd, 0xe8, 0x3c, 0x64, 0xe4, 0x82, 0x69, 0xec, 0xa2, 0x79, 0x02, 0x63, 0xad, 0x2d, 0x5c, 0x9f, 0xc5, - 0x2c, 0xaa, 0x70, 0x0a, 0xc5, 0x2a, 0x1a, 0x8b, 0xe2, 0x29, 0x4d, 0xa6, 0x50, 0xaf, 0xc4, 0x98, 0xd4, 0x6d, 0xb8, - 0xa4, 0x60, 0x54, 0xb1, 0xa7, 0x19, 0x83, 0xaf, 0x30, 0xd0, 0x35, 0x03, 0x84, 0x73, 0xd8, 0xea, 0x19, 0x57, 0xaf, - 0x44, 0x9e, 0xb0, 0x5e, 0xee, 0xe1, 0x97, 0x5e, 0xf9, 0x4b, 0xa5, 0x0a, 0x3e, 0x5a, 0x28, 0x16, 0x06, 0x39, 0x94, - 0x08, 0x70, 0x8e, 0xb0, 0x8c, 0x14, 0xbb, 0x53, 0x57, 0x22, 0x57, 0x2c, 0x57, 0x84, 0x39, 0xa8, 0x62, 0x1e, 0xd1, - 0xf9, 0x9c, 0xe5, 0xe9, 0xd5, 0x94, 0x67, 0x69, 0x28, 0xd1, 0x1a, 0xad, 0xf1, 0x07, 0x49, 0x60, 0x92, 0xe4, 0x82, - 0xc7, 0xf0, 0xcf, 0xb7, 0xa7, 0x13, 0x2a, 0x72, 0xa1, 0xb7, 0x05, 0x23, 0x41, 0xd0, 0x1b, 0x8b, 0x22, 0xb4, 0x53, - 0xd8, 0x03, 0xd2, 0x05, 0x7d, 0xbc, 0x5d, 0x64, 0x4c, 0x22, 0xd6, 0x20, 0x25, 0xa6, 0x39, 0x08, 0xff, 0x56, 0x84, - 0x0c, 0x16, 0x80, 0xa3, 0x98, 0x6b, 0x12, 0xf8, 0x92, 0xdb, 0x4d, 0x95, 0x96, 0x44, 0xed, 0x77, 0x49, 0x52, 0x1e, - 0xa9, 0x62, 0x21, 0x15, 0x4b, 0xdf, 0xdd, 0xcf, 0x99, 0xc4, 0x3f, 0x17, 0xe4, 0x77, 0xd9, 0xff, 0x5d, 0x46, 0x6c, - 0x36, 0x57, 0xf7, 0xd7, 0x9a, 0x9a, 0xc7, 0x41, 0x80, 0x3f, 0xea, 0xa2, 0x05, 0xa3, 0x09, 0x90, 0x34, 0x0b, 0xb2, - 0x37, 0x22, 0xbb, 0x1f, 0xf3, 0x2c, 0xbb, 0x5e, 0xcc, 0xe7, 0xa2, 0x50, 0x58, 0x49, 0xb2, 0x54, 0xa2, 0x82, 0x0f, - 0xac, 0xe8, 0x52, 0xde, 0x72, 0x95, 0x4c, 0x43, 0x85, 0x96, 0x09, 0x95, 0x6c, 0xef, 0xb1, 0x10, 0x19, 0xa3, 0x79, - 0xcc, 0x09, 0xef, 0xff, 0x5c, 0xc4, 0xf9, 0x22, 0xcb, 0x7a, 0xa3, 0x82, 0xd1, 0x2f, 0x3d, 0x9d, 0x6d, 0x0e, 0x87, - 0x58, 0xff, 0xbe, 0x2c, 0x0a, 0x7a, 0x0f, 0x05, 0x09, 0x81, 0x62, 0x7d, 0x1e, 0xff, 0x7c, 0xfd, 0xfa, 0x55, 0x64, - 0xf6, 0x0a, 0x1f, 0xdf, 0x87, 0xbc, 0xdc, 0x7f, 0x7c, 0x8d, 0xc7, 0x85, 0x98, 0x6d, 0x74, 0x6d, 0x40, 0xc7, 0x7b, - 0xdf, 0x18, 0x02, 0x23, 0x7c, 0xdf, 0x34, 0xed, 0x8f, 0xe0, 0x95, 0xc6, 0x7c, 0xc8, 0x24, 0xb6, 0x5f, 0xf8, 0x27, - 0x36, 0xc9, 0x21, 0x47, 0xdf, 0x1f, 0xad, 0x2a, 0xee, 0x97, 0x8c, 0xe8, 0x71, 0xce, 0xe1, 0x60, 0x84, 0x31, 0x26, - 0x54, 0x25, 0xd3, 0x25, 0xd3, 0x8d, 0xad, 0xdd, 0x88, 0xd9, 0x7a, 0x8d, 0x5f, 0x09, 0x87, 0xf5, 0x6a, 0x9f, 0x10, - 0xae, 0xe9, 0x15, 0x51, 0xab, 0x15, 0x27, 0x84, 0x23, 0xfc, 0x96, 0x93, 0x25, 0x75, 0x13, 0x82, 0x93, 0x0d, 0xb6, - 0x67, 0x6c, 0xa8, 0x0c, 0x9c, 0x80, 0x5f, 0x59, 0xa1, 0x58, 0x11, 0x2b, 0x89, 0x0b, 0x36, 0xce, 0x60, 0x1c, 0xfb, - 0x6d, 0x3c, 0xa5, 0xf2, 0x6a, 0x4a, 0xf3, 0x09, 0x4b, 0xe3, 0x57, 0x62, 0x8d, 0x99, 0x24, 0xc1, 0x98, 0xe7, 0x34, - 0xe3, 0xff, 0xb0, 0x34, 0xb0, 0xe7, 0xc2, 0x63, 0xb5, 0xc7, 0xee, 0x14, 0xcb, 0x53, 0xb9, 0xf7, 0xfc, 0xdd, 0xaf, - 0x2f, 0xed, 0x62, 0xd6, 0xce, 0x0a, 0xb4, 0x94, 0x8b, 0x39, 0x2b, 0x42, 0x84, 0xed, 0x59, 0xf1, 0x94, 0x6b, 0x3a, - 0xf9, 0x2b, 0x9d, 0x9b, 0x14, 0x2e, 0x7f, 0x9f, 0xa7, 0x54, 0xb1, 0x37, 0x2c, 0x4f, 0x79, 0x3e, 0x21, 0xfb, 0x6d, - 0x93, 0x3e, 0xa5, 0x36, 0x23, 0x2d, 0x93, 0x6e, 0x1e, 0x3c, 0xcd, 0xf4, 0xdc, 0xcb, 0xcf, 0x45, 0x88, 0xd6, 0x52, - 0x51, 0xc5, 0x93, 0x3d, 0x9a, 0xa6, 0x2f, 0x72, 0xae, 0xb8, 0x1e, 0x61, 0x01, 0x4b, 0x04, 0xb8, 0xca, 0xcc, 0xa9, - 0xe1, 0x46, 0x1e, 0x22, 0x1c, 0x86, 0xf6, 0x2c, 0x98, 0x22, 0xbb, 0x66, 0x07, 0x07, 0x15, 0xe5, 0xef, 0xb3, 0xd8, - 0x64, 0x92, 0xc1, 0x10, 0x45, 0xf3, 0x85, 0x84, 0xc5, 0x76, 0x5d, 0xc0, 0x41, 0x23, 0x46, 0x92, 0x15, 0x5f, 0x59, - 0x5a, 0x22, 0x88, 0x0c, 0xd1, 0x72, 0xa3, 0x0f, 0xbb, 0x3d, 0x14, 0x19, 0x0c, 0x7b, 0x3e, 0x09, 0x67, 0x16, 0xd9, - 0x0d, 0xa7, 0xc2, 0x99, 0x2c, 0x89, 0x4a, 0x08, 0x07, 0x6a, 0x49, 0x58, 0x72, 0xe2, 0xe6, 0x37, 0x0f, 0x25, 0xf0, - 0x10, 0x3e, 0xe5, 0x70, 0x67, 0xee, 0xd3, 0xaf, 0xfa, 0xf0, 0xc8, 0xb1, 0x44, 0x58, 0x99, 0x91, 0xe6, 0x08, 0xad, - 0x11, 0x56, 0x6e, 0xb8, 0x86, 0x28, 0x39, 0xbe, 0x08, 0x4e, 0x6d, 0xf2, 0x96, 0xeb, 0x63, 0x1b, 0x68, 0x1b, 0x55, - 0xec, 0xe0, 0x20, 0x64, 0x51, 0x89, 0x18, 0x64, 0xbf, 0x6d, 0x17, 0xc9, 0x83, 0xd6, 0x37, 0xc6, 0x0d, 0x3d, 0x6b, - 0x06, 0x67, 0x9f, 0x45, 0xb9, 0xb8, 0x4c, 0x12, 0x26, 0xa5, 0x28, 0x0e, 0x0e, 0xf6, 0x75, 0xf9, 0x92, 0xb3, 0x80, - 0x45, 0x7c, 0x7d, 0x9b, 0x57, 0x43, 0x40, 0xd5, 0x69, 0xeb, 0xf8, 0x26, 0x52, 0xf1, 0x4d, 0x8e, 0x09, 0x89, 0x83, - 0x9b, 0x9b, 0xa0, 0xa1, 0xb0, 0x85, 0xc3, 0x84, 0xb9, 0xae, 0xef, 0x9f, 0x30, 0xc3, 0x16, 0x6a, 0x26, 0x64, 0x0b, - 0x34, 0x3b, 0xf9, 0xc1, 0xb0, 0x3e, 0x24, 0xac, 0x70, 0x8e, 0xd6, 0xde, 0x8a, 0xee, 0x6c, 0x5a, 0xf3, 0x37, 0x66, - 0xe9, 0x96, 0x13, 0xcd, 0x53, 0x78, 0xeb, 0x38, 0x60, 0xc3, 0x35, 0xd6, 0xb0, 0x77, 0xb3, 0x11, 0x7a, 0xa0, 0x03, - 0x35, 0xec, 0xd9, 0x7c, 0x92, 0x1b, 0xc8, 0x15, 0xec, 0xef, 0x05, 0x93, 0xca, 0x20, 0x72, 0xa8, 0xb0, 0xc0, 0x70, - 0x46, 0x6d, 0x32, 0x9d, 0x35, 0x96, 0x74, 0xd7, 0xd8, 0x5e, 0xcf, 0xe1, 0x6c, 0x94, 0x80, 0xd4, 0xdf, 0xc7, 0x27, - 0x18, 0xab, 0x42, 0xab, 0xd5, 0x5b, 0xee, 0x5a, 0xa9, 0xd6, 0xb2, 0xe4, 0xd7, 0x36, 0x16, 0x85, 0x49, 0x64, 0x0f, - 0xe7, 0xfd, 0xb6, 0x1d, 0xbf, 0x1c, 0x92, 0xfd, 0x56, 0x89, 0xc5, 0x16, 0xac, 0x66, 0x3c, 0x06, 0x8a, 0xaf, 0x4d, - 0x53, 0x48, 0x9f, 0xf5, 0x35, 0x7c, 0x89, 0xa6, 0x5b, 0xb8, 0x3a, 0x25, 0x03, 0xe0, 0x3a, 0xa2, 0xe9, 0xf0, 0x5b, - 0xf8, 0xe4, 0x28, 0x42, 0xa8, 0xb6, 0xf3, 0x2a, 0xc2, 0xf1, 0xb5, 0x4e, 0x38, 0x36, 0xa6, 0x11, 0xcc, 0xcb, 0x2a, - 0x41, 0x89, 0x66, 0x76, 0xab, 0x57, 0x59, 0x58, 0xea, 0xc1, 0x54, 0x53, 0xf2, 0x9a, 0x78, 0x45, 0x67, 0x4c, 0x86, - 0x0c, 0xe1, 0x6f, 0x15, 0x30, 0xf8, 0x09, 0x45, 0x86, 0xde, 0x19, 0x9a, 0xc3, 0x19, 0x0a, 0xec, 0x2e, 0x30, 0x69, - 0xf5, 0x2d, 0x97, 0x63, 0x36, 0xc8, 0x87, 0x15, 0x6f, 0xe7, 0x4d, 0x5e, 0x1f, 0xce, 0x92, 0xd4, 0xf6, 0x9b, 0x49, - 0x33, 0x40, 0xd3, 0x2c, 0x84, 0x44, 0x78, 0xbf, 0xb5, 0xb9, 0x92, 0xae, 0x54, 0x35, 0xc7, 0xc1, 0x10, 0xd6, 0x41, - 0x1f, 0x1b, 0x11, 0x97, 0xfa, 0x6f, 0x6d, 0xab, 0x01, 0xd8, 0xae, 0x01, 0x33, 0xa2, 0x71, 0x46, 0x55, 0xd8, 0x3e, - 0x6a, 0x01, 0x63, 0xfa, 0x95, 0xc1, 0xa9, 0x82, 0xd0, 0xf6, 0x54, 0x58, 0xb4, 0xc8, 0xe5, 0x94, 0x8f, 0x55, 0xf8, - 0x41, 0x6a, 0xa2, 0xc2, 0x32, 0xc9, 0x40, 0xc2, 0xf1, 0xd8, 0x63, 0x4d, 0x70, 0x3e, 0xc0, 0x30, 0x4a, 0x56, 0x8c, - 0xb9, 0x91, 0x6a, 0xc2, 0x05, 0xe4, 0xa1, 0x62, 0xad, 0x2b, 0x32, 0xe3, 0x4a, 0x4b, 0xe0, 0x1e, 0xdb, 0x7d, 0xd3, - 0x62, 0x6c, 0xa9, 0x81, 0xf4, 0x38, 0x58, 0x19, 0xfb, 0x24, 0xc2, 0x26, 0xaa, 0x48, 0x89, 0x97, 0xe2, 0x96, 0x15, - 0x57, 0x14, 0x06, 0x1f, 0x9b, 0xea, 0x6b, 0x73, 0x14, 0x68, 0x8a, 0xaf, 0x7a, 0x0e, 0x5f, 0x6e, 0xf4, 0xc4, 0xdf, - 0x14, 0x62, 0xc6, 0x25, 0x03, 0xbe, 0xcd, 0xc0, 0x3f, 0x87, 0x8d, 0xa6, 0x77, 0x24, 0x1c, 0x37, 0xac, 0xc4, 0xaf, - 0xcb, 0x97, 0x75, 0xfc, 0xba, 0x79, 0xf0, 0x74, 0xe2, 0x28, 0x60, 0x7d, 0x1f, 0x23, 0x1c, 0x5a, 0xf1, 0xc2, 0x3b, - 0xe9, 0xa2, 0x29, 0xb2, 0xc7, 0xfc, 0x6a, 0xa5, 0x3c, 0x31, 0xae, 0xc6, 0x39, 0x32, 0xb3, 0x6d, 0xd0, 0x9a, 0xa6, - 0x29, 0xb0, 0x78, 0x85, 0xc8, 0x32, 0xef, 0xb0, 0xc2, 0xb2, 0x57, 0x1e, 0x4f, 0x37, 0x0f, 0x9e, 0x5e, 0x7f, 0xef, - 0x84, 0x82, 0x7c, 0xff, 0x90, 0x72, 0x03, 0xcd, 0x53, 0x56, 0x80, 0x5c, 0xe9, 0xad, 0x96, 0x3d, 0x67, 0xaf, 0x44, - 0x9e, 0xb3, 0x44, 0xb1, 0x14, 0x84, 0x16, 0x60, 0x83, 0xa7, 0x42, 0xaa, 0x32, 0xb1, 0x1a, 0xbd, 0xf4, 0x85, 0xd0, - 0x28, 0xa1, 0x59, 0x16, 0x1a, 0x01, 0x65, 0x26, 0xbe, 0xb2, 0x1d, 0xa3, 0xee, 0xd5, 0x86, 0x5c, 0x36, 0xc3, 0xbc, - 0x66, 0x58, 0x24, 0xe7, 0x19, 0x4f, 0x58, 0x79, 0x78, 0x5d, 0x47, 0x3c, 0x4f, 0xd9, 0x1d, 0xd0, 0x11, 0x74, 0x71, - 0x71, 0xd1, 0xc2, 0x6d, 0xb4, 0x36, 0x00, 0x5f, 0x6e, 0x01, 0xf6, 0x3b, 0xc7, 0xa6, 0x11, 0xc4, 0x97, 0x3b, 0xc9, - 0x1a, 0xf2, 0xce, 0x4a, 0xee, 0x04, 0x2d, 0x43, 0x9e, 0x11, 0x4e, 0x59, 0xc6, 0x14, 0x73, 0xe4, 0x1c, 0x98, 0x69, - 0xb3, 0x75, 0xdf, 0x96, 0xf0, 0x2b, 0xd1, 0xc9, 0xed, 0x32, 0xb7, 0xe6, 0xb2, 0x14, 0xdd, 0xab, 0xe5, 0xa9, 0xa0, - 0xdd, 0x57, 0x66, 0x79, 0xa8, 0x52, 0x34, 0x99, 0x1a, 0x89, 0x3d, 0xdc, 0x9a, 0x52, 0xd5, 0x86, 0x25, 0xed, 0xe5, - 0x26, 0xfa, 0x54, 0xd8, 0x61, 0xee, 0x02, 0xc1, 0xb5, 0x25, 0x0a, 0x0c, 0x84, 0x40, 0xb3, 0x6c, 0x57, 0x34, 0xcb, - 0x46, 0x34, 0xf9, 0x52, 0xc7, 0xfe, 0x0a, 0x0d, 0xc8, 0x26, 0x35, 0xf6, 0xb2, 0x3c, 0x92, 0xe5, 0xcf, 0xdb, 0x51, - 0xe9, 0xda, 0x46, 0x09, 0xf7, 0x5b, 0x15, 0xda, 0xd7, 0x17, 0xfa, 0x9b, 0xd8, 0xae, 0x47, 0x24, 0xed, 0xcc, 0x42, - 0xa0, 0x02, 0xff, 0x12, 0xe3, 0x1c, 0x3d, 0xb0, 0x78, 0x07, 0x82, 0xc7, 0x7a, 0x63, 0x20, 0x0a, 0x2d, 0xd7, 0x29, - 0x97, 0xdf, 0x86, 0xc0, 0xff, 0x96, 0x51, 0x3e, 0xf1, 0x7a, 0xf8, 0x77, 0x07, 0x5a, 0xd2, 0x38, 0xcb, 0x38, 0x97, - 0x23, 0xb3, 0x0c, 0x85, 0x23, 0x34, 0xbf, 0x00, 0xf3, 0xa2, 0xf1, 0xfd, 0xb5, 0xc9, 0xd2, 0x7c, 0x19, 0x0c, 0x23, - 0xef, 0xf9, 0x0c, 0x45, 0x0d, 0x05, 0x2c, 0x51, 0x35, 0x67, 0xae, 0xa8, 0x89, 0x92, 0x96, 0x6b, 0x37, 0xe2, 0xb8, - 0xa5, 0xb9, 0x05, 0x09, 0xc3, 0x30, 0x27, 0xba, 0x0d, 0xc3, 0xdf, 0x57, 0xb3, 0xc8, 0xb7, 0x66, 0x91, 0x47, 0x9e, - 0xb4, 0x85, 0x2a, 0x64, 0xf6, 0xaa, 0xc7, 0x4a, 0x22, 0xbf, 0x14, 0xb0, 0xac, 0x11, 0x50, 0x68, 0x54, 0x12, 0xdc, - 0x8c, 0x28, 0x5c, 0x58, 0x51, 0xc7, 0xe2, 0x1a, 0x90, 0x8c, 0xaa, 0x8a, 0x40, 0x66, 0x73, 0xd4, 0x64, 0x5f, 0x81, - 0x0b, 0xb4, 0xc1, 0xdf, 0xaf, 0xd7, 0x16, 0x4a, 0x0c, 0xd9, 0xd5, 0xa9, 0x31, 0xc6, 0x1e, 0x58, 0xb0, 0x20, 0xb9, - 0x61, 0x86, 0x0d, 0xeb, 0xb3, 0x09, 0x9c, 0xb2, 0xdd, 0x7d, 0x42, 0x44, 0x05, 0x9b, 0x3c, 0xda, 0xc1, 0x5d, 0x09, - 0x84, 0xa9, 0x63, 0x4b, 0x8b, 0x6a, 0xe2, 0x84, 0x04, 0x4e, 0x3b, 0x11, 0xf4, 0x97, 0x35, 0xe1, 0x30, 0xf6, 0x8a, - 0xad, 0x63, 0x20, 0xaa, 0xc5, 0x2e, 0x78, 0xef, 0xc2, 0x9a, 0x5a, 0x3b, 0x1e, 0xc4, 0x8b, 0x1a, 0xc4, 0x3d, 0xd0, - 0x0a, 0x43, 0xbc, 0xc4, 0x90, 0xd0, 0x7a, 0xe5, 0x90, 0xe1, 0xc2, 0x2c, 0xc4, 0x16, 0x14, 0x37, 0xd9, 0x4f, 0x8d, - 0x85, 0x20, 0xcb, 0xe6, 0xc0, 0xdf, 0xf9, 0x47, 0x44, 0x08, 0x83, 0x97, 0xab, 0xd5, 0x16, 0xda, 0xed, 0xe4, 0x42, - 0x51, 0x54, 0x49, 0x87, 0xab, 0xd5, 0x2b, 0x81, 0x42, 0xcb, 0xff, 0x62, 0x86, 0xfa, 0x8e, 0xe8, 0x5e, 0xbe, 0x84, - 0x52, 0x9a, 0x1d, 0xad, 0x52, 0x4a, 0xc1, 0xa1, 0x8e, 0xb5, 0xf5, 0x85, 0x52, 0x1e, 0xe5, 0xbe, 0xda, 0x22, 0x60, - 0x3a, 0xd1, 0x9e, 0xd4, 0xd5, 0x94, 0xaf, 0x6c, 0xd3, 0x12, 0x21, 0x14, 0xe7, 0x5a, 0x96, 0xd9, 0xdf, 0x25, 0x5f, - 0x1e, 0x1c, 0xe4, 0x5e, 0x43, 0x37, 0x25, 0xa5, 0xf8, 0x2b, 0x84, 0x53, 0x59, 0xde, 0xe7, 0x9a, 0x7d, 0xf9, 0xcb, - 0x9d, 0x43, 0x5b, 0xd2, 0x69, 0xab, 0x07, 0x82, 0x39, 0xbd, 0xa5, 0x5c, 0xed, 0x95, 0xad, 0x18, 0xc1, 0x3c, 0x64, - 0x68, 0x69, 0xb9, 0x8d, 0xa8, 0x60, 0xc0, 0x3f, 0x02, 0x59, 0x70, 0x5c, 0xb4, 0x41, 0xfc, 0x64, 0xca, 0x40, 0x95, - 0xed, 0x18, 0x89, 0x52, 0x3c, 0xdc, 0xb7, 0x07, 0x89, 0x6d, 0x78, 0xf7, 0xd8, 0xd7, 0x9b, 0xd5, 0x6b, 0xd2, 0xc0, - 0x9c, 0x15, 0x63, 0x51, 0xcc, 0x5c, 0xde, 0x7a, 0xe3, 0xdb, 0x12, 0x47, 0x3e, 0x0e, 0x77, 0xb6, 0x6d, 0x45, 0x80, - 0xde, 0x86, 0xec, 0x5d, 0x49, 0xed, 0xb5, 0xd3, 0xb4, 0x3c, 0x80, 0x8d, 0x82, 0xd0, 0x61, 0x66, 0xee, 0x4b, 0xf9, - 0x56, 0xbd, 0xda, 0x33, 0xba, 0x93, 0xfd, 0x76, 0xaf, 0x94, 0xfc, 0x1c, 0x36, 0xf4, 0x8c, 0x8e, 0xc3, 0x9e, 0xaa, - 0x62, 0x91, 0xa5, 0x76, 0xb0, 0x70, 0xc4, 0x59, 0x3c, 0xba, 0xe5, 0x59, 0x56, 0xa5, 0xfe, 0x27, 0xa4, 0x3d, 0xb7, - 0xa4, 0x5d, 0x38, 0xd2, 0x0e, 0xa4, 0x02, 0x48, 0xbb, 0x69, 0xae, 0xaa, 0x2e, 0xb6, 0xb6, 0xa7, 0x30, 0x44, 0x3d, - 0xd7, 0xe2, 0x34, 0xf4, 0xb7, 0x70, 0x23, 0x40, 0x25, 0xf3, 0xf5, 0x25, 0xb4, 0xfa, 0x18, 0x10, 0x03, 0x8d, 0x4e, - 0x93, 0xf9, 0x9a, 0x8a, 0x2f, 0x21, 0xc2, 0xf9, 0x9a, 0x95, 0x98, 0x7d, 0xf9, 0x14, 0x94, 0x76, 0xde, 0x74, 0xe0, - 0x1c, 0xd3, 0xc9, 0xff, 0x11, 0x1f, 0xe5, 0x66, 0x27, 0xed, 0xec, 0x72, 0x37, 0x3b, 0xa0, 0xf5, 0xd5, 0xec, 0xd2, - 0xef, 0x53, 0x7b, 0x3d, 0x3d, 0x59, 0x4e, 0xaf, 0x5a, 0xef, 0xd5, 0x2a, 0xdc, 0x48, 0x01, 0x8d, 0xbe, 0x95, 0x52, - 0x8a, 0xb2, 0x75, 0xa0, 0x01, 0x3e, 0x64, 0x20, 0x61, 0x6d, 0x26, 0x5d, 0x9e, 0x72, 0x2f, 0xff, 0x95, 0x9e, 0x47, - 0x2b, 0xee, 0x4d, 0xfd, 0x2b, 0x31, 0x9b, 0x03, 0x43, 0xb6, 0x81, 0xd2, 0x13, 0x66, 0x3b, 0xac, 0xf2, 0xd7, 0x3b, - 0xd2, 0x6a, 0x75, 0xf4, 0x7e, 0xac, 0x61, 0x53, 0x29, 0x35, 0xef, 0xb7, 0xd6, 0x8b, 0x32, 0xa9, 0x24, 0x1c, 0xbb, - 0x74, 0x2b, 0x57, 0x9b, 0x9a, 0x19, 0x97, 0xf1, 0x3a, 0x94, 0x86, 0x0e, 0x4b, 0xa0, 0x75, 0x1e, 0xf9, 0x71, 0xe8, - 0xee, 0xaf, 0xff, 0xba, 0x02, 0xce, 0x72, 0xbd, 0x01, 0xbe, 0xe5, 0x7a, 0xfd, 0x58, 0x59, 0x49, 0x1b, 0x3f, 0xde, - 0x21, 0xf7, 0x96, 0xd0, 0xab, 0x32, 0xad, 0xcc, 0x38, 0x18, 0x42, 0xda, 0x16, 0x0b, 0x49, 0x96, 0x33, 0x91, 0xb2, - 0x38, 0x10, 0x73, 0x96, 0x07, 0x6b, 0xd0, 0xb3, 0x5a, 0x04, 0xf8, 0x28, 0xc3, 0xe5, 0xdb, 0xba, 0xbe, 0x35, 0x7e, - 0xac, 0xd6, 0xa0, 0x0a, 0x7b, 0xc9, 0x77, 0x28, 0x63, 0xdf, 0xb3, 0x42, 0x6a, 0x9e, 0xb4, 0x64, 0x6f, 0x5f, 0xf2, - 0xea, 0x80, 0x7a, 0xc9, 0xe3, 0x6f, 0x57, 0xa9, 0x04, 0x92, 0xa0, 0x1d, 0x9d, 0x46, 0xc7, 0x01, 0xd2, 0x1a, 0xe3, - 0x67, 0x4e, 0x63, 0xbc, 0x28, 0x35, 0xc6, 0xcf, 0x15, 0x59, 0x6c, 0x68, 0x8c, 0xff, 0x96, 0xe4, 0xb9, 0xea, 0x3f, - 0x77, 0xda, 0xf4, 0x37, 0x22, 0xe3, 0xc9, 0x7d, 0x18, 0x64, 0x5c, 0x35, 0xe1, 0x36, 0x31, 0xc0, 0x4b, 0x93, 0x01, - 0xaa, 0x46, 0xad, 0xef, 0x5e, 0x3b, 0xf9, 0x0f, 0x73, 0x49, 0x82, 0x07, 0x19, 0x57, 0x0f, 0x02, 0x3c, 0x55, 0xe4, - 0x33, 0xfc, 0x7a, 0xb0, 0x0c, 0x7f, 0xa5, 0x6a, 0x1a, 0x15, 0x34, 0x4f, 0xc5, 0x2c, 0x44, 0x8d, 0x20, 0x40, 0x91, - 0xd4, 0x42, 0xc8, 0x23, 0xb4, 0x7e, 0xf0, 0x19, 0xff, 0x23, 0x48, 0xd0, 0x0f, 0x1a, 0x53, 0x85, 0x15, 0x25, 0x9f, - 0xcf, 0x1f, 0x2c, 0xff, 0x11, 0xeb, 0x8b, 0xcf, 0xf8, 0xa9, 0x2a, 0xd5, 0xfa, 0xf8, 0x8e, 0x91, 0x10, 0x91, 0x8b, - 0xa7, 0x6e, 0x48, 0x57, 0x62, 0x66, 0x14, 0xfc, 0x01, 0xc2, 0x5f, 0x41, 0xaf, 0x7b, 0xc1, 0x2b, 0x22, 0x64, 0xef, - 0x60, 0xf6, 0x49, 0x20, 0xb4, 0xf2, 0x20, 0x38, 0x38, 0xf0, 0xd2, 0x4a, 0x16, 0x02, 0xff, 0x25, 0x48, 0x4d, 0x54, - 0xc7, 0x8c, 0x42, 0x4b, 0x7f, 0x89, 0x90, 0x23, 0xd7, 0x4c, 0xe8, 0x34, 0xd5, 0x76, 0xc7, 0xf2, 0x81, 0xd1, 0x3d, - 0x44, 0x5c, 0xb1, 0x82, 0x2a, 0x51, 0x0c, 0x91, 0xcf, 0x96, 0xe0, 0x57, 0x9c, 0x7c, 0x1e, 0xec, 0xfd, 0x3f, 0xff, - 0xe3, 0xcf, 0xf1, 0x9f, 0xc5, 0xf0, 0x33, 0x96, 0x8c, 0x1c, 0x9d, 0x87, 0xfd, 0x38, 0xdc, 0x6f, 0x36, 0x57, 0x7f, - 0x1e, 0x0d, 0xfe, 0x9b, 0x36, 0xff, 0xb9, 0x6c, 0x7e, 0x1a, 0xa2, 0x55, 0xf8, 0xe7, 0x51, 0x7f, 0x60, 0xbf, 0x06, - 0xff, 0x7d, 0xf1, 0xa7, 0x1c, 0x1e, 0x9a, 0xc4, 0x07, 0x08, 0x1d, 0x4d, 0xf0, 0x1f, 0x92, 0x1c, 0x35, 0x9b, 0x17, - 0x47, 0x13, 0xfc, 0x8b, 0x24, 0x47, 0xf0, 0xf7, 0x5e, 0x91, 0xb7, 0x6c, 0xf2, 0xf4, 0x6e, 0x1e, 0x7e, 0xbe, 0x58, - 0x3d, 0x58, 0xbe, 0xe2, 0x6b, 0x68, 0x77, 0xf0, 0xdf, 0x7f, 0xfe, 0x29, 0x83, 0x1f, 0x2f, 0xc8, 0xd1, 0xb0, 0x81, - 0x42, 0x9d, 0x7c, 0x48, 0xcc, 0x9f, 0xb0, 0x1f, 0x0f, 0xfe, 0xdb, 0x0e, 0x25, 0xf8, 0xf1, 0xcf, 0xcf, 0xe7, 0x17, - 0x64, 0xb8, 0x0a, 0x83, 0xd5, 0x8f, 0x68, 0x85, 0xd0, 0xea, 0x01, 0xfa, 0x8c, 0x83, 0x49, 0x80, 0xf0, 0x4f, 0x92, - 0x1c, 0xfd, 0x78, 0x34, 0xc1, 0xbf, 0x49, 0x72, 0x14, 0x1c, 0x4d, 0xf0, 0x7b, 0x41, 0x8e, 0xfe, 0x3b, 0xec, 0xc7, - 0x46, 0x09, 0xb7, 0xd2, 0xea, 0x8f, 0x15, 0xdc, 0x84, 0xd0, 0x82, 0xd1, 0x95, 0xe2, 0x2a, 0x63, 0xe8, 0xc1, 0x11, - 0xc7, 0x8f, 0x05, 0x00, 0x2b, 0x54, 0xa0, 0xa4, 0xd1, 0x97, 0xb0, 0xcb, 0x1b, 0x58, 0x78, 0xc0, 0xa0, 0x07, 0x31, - 0xc7, 0x46, 0x4f, 0x20, 0x63, 0x65, 0x6e, 0x6f, 0x25, 0x5c, 0xdf, 0xe2, 0x2b, 0xf2, 0x58, 0x84, 0x6d, 0x84, 0x39, - 0x85, 0x1f, 0x1d, 0x84, 0x3f, 0x28, 0x7b, 0xe1, 0x09, 0xdb, 0xdc, 0x60, 0x58, 0x2e, 0x0c, 0x3f, 0x13, 0x20, 0xfc, - 0x72, 0x47, 0xa6, 0x9a, 0x82, 0xfa, 0x01, 0xe1, 0x4f, 0xb5, 0xeb, 0x51, 0x7c, 0xa5, 0x48, 0x89, 0x1c, 0xef, 0x0a, - 0xc6, 0x3e, 0xd0, 0xec, 0x0b, 0x2b, 0xc2, 0xa7, 0x0a, 0xb7, 0x3b, 0x8f, 0xb0, 0x56, 0x55, 0xef, 0xb7, 0x51, 0xaf, - 0xbc, 0xdd, 0x7a, 0x2e, 0xcc, 0x7d, 0x02, 0x9c, 0xc2, 0x75, 0x7d, 0x0d, 0xac, 0xfd, 0x3e, 0xdf, 0x52, 0x6a, 0x15, - 0xf4, 0x36, 0x40, 0xf5, 0xab, 0x54, 0x9e, 0x7f, 0xa5, 0x19, 0x4f, 0xf7, 0x14, 0x9b, 0xcd, 0x33, 0xaa, 0xd8, 0x9e, - 0x9d, 0xf3, 0x1e, 0x85, 0x86, 0x82, 0x92, 0xa7, 0xf8, 0x5b, 0x56, 0x9b, 0xf6, 0x6f, 0x27, 0xe7, 0xc1, 0xde, 0x09, - 0xe1, 0x3e, 0xcb, 0xf2, 0x25, 0x92, 0x96, 0xd7, 0x65, 0x9b, 0x37, 0x82, 0xcd, 0x36, 0x28, 0xcb, 0x86, 0xfa, 0xfc, - 0xce, 0x31, 0xdc, 0x6f, 0x12, 0xd2, 0xe9, 0x07, 0xe7, 0xf2, 0xeb, 0xe4, 0x22, 0x80, 0x9b, 0x9c, 0x82, 0x48, 0xa6, - 0x95, 0x47, 0x50, 0x82, 0x92, 0x56, 0x8f, 0x9e, 0xb3, 0x1e, 0x6d, 0x34, 0x1c, 0x9b, 0x9d, 0x10, 0x3e, 0xa0, 0xa6, - 0x7e, 0x86, 0xa7, 0x38, 0x25, 0xcd, 0x36, 0x5e, 0x90, 0x96, 0xae, 0xd2, 0x5b, 0x9c, 0x27, 0xb6, 0x9f, 0x83, 0x83, - 0xb0, 0x88, 0x32, 0x2a, 0xd5, 0x0b, 0xd0, 0x08, 0x90, 0x05, 0x9e, 0x92, 0x22, 0x62, 0x77, 0x2c, 0x09, 0x13, 0x84, - 0xa7, 0x96, 0x06, 0xa1, 0x1e, 0x5a, 0x10, 0xaf, 0x18, 0xc8, 0x19, 0x44, 0xb2, 0xfe, 0x74, 0xd0, 0x1e, 0x12, 0x42, - 0x82, 0xfd, 0x66, 0x33, 0xe8, 0x17, 0xe4, 0x0f, 0x19, 0x43, 0x8a, 0xc7, 0x4e, 0x93, 0x5f, 0x20, 0xa9, 0xe3, 0x25, - 0x85, 0xef, 0x45, 0xa4, 0x98, 0x54, 0x21, 0x24, 0x83, 0x92, 0x20, 0x77, 0x18, 0x1e, 0x9c, 0x1f, 0x05, 0x0d, 0x48, - 0xd5, 0x28, 0x8a, 0x70, 0x41, 0xee, 0x15, 0x8a, 0xa7, 0x83, 0xe3, 0xa1, 0x7f, 0x46, 0x98, 0x54, 0xe8, 0xff, 0x5e, - 0xf5, 0xa7, 0x83, 0x96, 0xee, 0xff, 0x22, 0xe8, 0x87, 0x05, 0xc9, 0xf7, 0xed, 0x3d, 0x4f, 0x2c, 0x99, 0x9e, 0x2f, - 0x8a, 0xed, 0x00, 0x6d, 0xdf, 0x29, 0x69, 0x76, 0xe2, 0x30, 0xf5, 0x67, 0xd2, 0x84, 0x0e, 0x2d, 0x28, 0x70, 0x46, - 0xa0, 0x3c, 0x2e, 0x08, 0x74, 0x5a, 0x55, 0xbb, 0x57, 0xb1, 0x4d, 0xf8, 0x31, 0xf8, 0xb1, 0xff, 0x9b, 0x8c, 0x7f, - 0x92, 0x66, 0x04, 0xbf, 0xc9, 0xd5, 0x0a, 0xfe, 0xfe, 0x24, 0xfb, 0x30, 0x2c, 0x9d, 0xf6, 0x87, 0x4d, 0xfb, 0x05, - 0xd2, 0x24, 0x8b, 0xf5, 0x80, 0x71, 0x5e, 0xf2, 0x63, 0x66, 0x71, 0xc6, 0xc4, 0xcc, 0xe0, 0xe0, 0x80, 0x0f, 0x68, - 0xa3, 0x3d, 0x84, 0x1b, 0x81, 0x42, 0xc9, 0x0f, 0x5c, 0x4d, 0xc3, 0xe0, 0xe8, 0x22, 0x40, 0xfd, 0x60, 0x0f, 0x56, - 0xb9, 0x27, 0x1a, 0xc4, 0xc2, 0x3a, 0x69, 0x28, 0x1a, 0xa7, 0x17, 0xa4, 0xd5, 0x0f, 0xa5, 0x21, 0xf2, 0x19, 0xc2, - 0x89, 0xa5, 0xa9, 0x2d, 0x9c, 0xa2, 0x06, 0x97, 0x0d, 0xf7, 0x9d, 0xa2, 0xc6, 0x54, 0x35, 0xc6, 0x28, 0x4e, 0xe0, - 0x6f, 0x98, 0x12, 0x42, 0x9a, 0x9d, 0xb2, 0xa2, 0x3b, 0x2c, 0x29, 0x8a, 0xc7, 0x4e, 0x3d, 0x3a, 0xd0, 0x9b, 0x43, - 0x34, 0x42, 0x3e, 0x60, 0xc3, 0xd5, 0x2a, 0x38, 0xef, 0x5f, 0x04, 0xa8, 0x11, 0x3a, 0xb4, 0x3b, 0x72, 0x78, 0x87, - 0x10, 0x96, 0xc3, 0xb5, 0xbd, 0x81, 0xba, 0x65, 0xb5, 0xdb, 0xa6, 0x65, 0xb5, 0xff, 0x3d, 0xb2, 0xc0, 0xd6, 0xa5, - 0xdc, 0x63, 0xf8, 0xdb, 0x39, 0x4c, 0xd5, 0xe1, 0xb6, 0x20, 0x2d, 0x5c, 0x10, 0xa7, 0xee, 0xa6, 0x44, 0x55, 0xf8, - 0x9f, 0x90, 0xaa, 0x38, 0x1e, 0x64, 0x78, 0x3a, 0x24, 0x92, 0x6a, 0xf9, 0xa5, 0xe7, 0x94, 0xe9, 0x2c, 0x23, 0xb7, - 0x6c, 0xe3, 0xfe, 0x37, 0x83, 0x3b, 0x99, 0x2b, 0x15, 0x25, 0x8b, 0xa2, 0x60, 0xb9, 0x7a, 0x25, 0x52, 0xcb, 0xd8, - 0xb1, 0x0c, 0x64, 0x2b, 0xb8, 0xd8, 0xc5, 0xc0, 0xd5, 0x75, 0xdc, 0x4e, 0x49, 0xb7, 0xb2, 0x17, 0x24, 0x35, 0x0c, - 0x97, 0xbe, 0xee, 0xed, 0x2d, 0xac, 0x28, 0x1d, 0x22, 0x9c, 0xda, 0x7b, 0xe0, 0x30, 0x8a, 0xa2, 0x45, 0x94, 0x40, - 0x36, 0x74, 0x20, 0xd1, 0x5a, 0xef, 0xab, 0x30, 0x27, 0x57, 0x2a, 0xca, 0xd9, 0x9d, 0xee, 0x36, 0x44, 0xd5, 0x21, - 0xee, 0xf6, 0xdb, 0x39, 0xed, 0x69, 0x02, 0x94, 0x47, 0xb9, 0x48, 0x19, 0x40, 0x08, 0xee, 0xfe, 0x6d, 0xd2, 0x94, - 0x4a, 0xff, 0x66, 0xab, 0x1a, 0xe0, 0xc0, 0x57, 0x79, 0x2f, 0x40, 0x4f, 0xac, 0x65, 0xe8, 0xb2, 0xb0, 0x51, 0x9e, - 0x23, 0xc4, 0xc7, 0xe1, 0x22, 0x82, 0x1b, 0x41, 0x8d, 0x49, 0x5c, 0xa2, 0xd5, 0x6a, 0xe1, 0xe3, 0xd6, 0xb4, 0x52, - 0x4c, 0x8f, 0xc9, 0x74, 0x50, 0x34, 0x1a, 0x5a, 0x79, 0x9d, 0x1a, 0xbc, 0x58, 0x20, 0x3c, 0x2e, 0xf7, 0x9a, 0x2b, - 0x37, 0x27, 0xf5, 0xae, 0xc2, 0x71, 0x5d, 0x09, 0xdc, 0xe0, 0x12, 0x69, 0xfd, 0xa2, 0x82, 0xd6, 0xf1, 0x84, 0x1c, - 0x85, 0x83, 0xa8, 0xff, 0x3f, 0x87, 0xa8, 0x1f, 0x46, 0x87, 0xe8, 0xc8, 0xd0, 0x92, 0x31, 0xea, 0x25, 0xa6, 0x8f, - 0xa5, 0xbe, 0xfd, 0x6c, 0x63, 0xad, 0x80, 0x8c, 0x05, 0xce, 0xe9, 0x8c, 0xc5, 0x13, 0xd8, 0xf5, 0x0e, 0x79, 0xe6, - 0x18, 0x90, 0x29, 0x9e, 0x58, 0xda, 0x12, 0x05, 0x7d, 0x41, 0xcb, 0xaf, 0x7e, 0xd0, 0xa7, 0xd5, 0xd7, 0xff, 0x0c, - 0xfa, 0x09, 0x8d, 0xaf, 0xf8, 0xda, 0x2a, 0xc9, 0x6b, 0x7d, 0x9c, 0xba, 0x3e, 0xd6, 0x66, 0x71, 0x3c, 0xe0, 0xa5, - 0x28, 0xdf, 0xd2, 0x8e, 0x2c, 0xd0, 0x9a, 0x8f, 0x4b, 0xea, 0x94, 0x47, 0x8a, 0x4e, 0x00, 0xaa, 0xde, 0x22, 0xe4, - 0xbe, 0x6d, 0x80, 0x37, 0x65, 0xc0, 0x16, 0x87, 0xb4, 0x00, 0xcd, 0xc5, 0x45, 0x0b, 0x2d, 0x6b, 0x85, 0x2d, 0x67, - 0x55, 0xbf, 0x8b, 0x2f, 0x89, 0xf7, 0x18, 0xa8, 0xf2, 0xf9, 0xa2, 0x37, 0x6e, 0x34, 0x50, 0xee, 0xf0, 0x2b, 0x1d, - 0x8c, 0x87, 0xf8, 0x0e, 0x50, 0x08, 0xd7, 0x30, 0x0a, 0xd7, 0xe6, 0xd8, 0xb1, 0x73, 0x6c, 0x34, 0xc4, 0x1a, 0xf5, - 0xbc, 0xca, 0x0b, 0x5b, 0x79, 0xbd, 0x36, 0x90, 0xd9, 0xc4, 0xb8, 0x33, 0xa4, 0x53, 0xc0, 0x10, 0x8c, 0x10, 0xf2, - 0x8f, 0x40, 0x3b, 0x9b, 0x85, 0x46, 0xa1, 0xba, 0xde, 0xbd, 0x40, 0x51, 0xcd, 0xe9, 0x11, 0x02, 0x2c, 0xa0, 0x6a, - 0xa9, 0x46, 0x9e, 0x2a, 0x9c, 0x36, 0xda, 0x1a, 0xdd, 0x9b, 0xed, 0x5e, 0xbd, 0xb1, 0x87, 0x55, 0x63, 0x38, 0x6d, - 0x90, 0x69, 0xb5, 0xc3, 0xd7, 0xa2, 0xd1, 0x58, 0xd7, 0xef, 0x4b, 0xdd, 0x26, 0xae, 0xdd, 0x5f, 0x3c, 0xdd, 0x32, - 0xf1, 0x70, 0xa7, 0x6f, 0x75, 0xde, 0xca, 0x88, 0xe7, 0x39, 0x2b, 0xe0, 0x84, 0x25, 0x0a, 0xcb, 0xf5, 0xba, 0x3c, - 0xf5, 0x7f, 0x57, 0xc6, 0x66, 0x8c, 0x70, 0xa0, 0x43, 0x5a, 0x6a, 0xc3, 0x02, 0x17, 0x98, 0x6a, 0x2a, 0x42, 0x08, - 0xf9, 0xa0, 0x9c, 0x79, 0x8c, 0xd2, 0x24, 0x29, 0x21, 0xde, 0xd9, 0x1d, 0xe6, 0x84, 0x45, 0x37, 0x0f, 0xae, 0xc4, - 0x77, 0x45, 0xba, 0x81, 0x1c, 0xc6, 0xba, 0x58, 0x66, 0x09, 0x59, 0x46, 0xbe, 0x82, 0x9c, 0x53, 0x5e, 0xb0, 0x44, - 0x9a, 0x20, 0x3e, 0xe1, 0x05, 0xd3, 0x8c, 0xfb, 0x03, 0x27, 0x37, 0x26, 0x75, 0x4e, 0x33, 0xf1, 0xb5, 0x3f, 0x00, - 0xcd, 0x0c, 0x94, 0x43, 0x82, 0x6c, 0x15, 0xbb, 0x79, 0x70, 0xf9, 0x7a, 0x97, 0x0c, 0xbd, 0x5a, 0x59, 0xe9, 0x39, - 0x01, 0xd6, 0x07, 0x67, 0xd5, 0x50, 0x13, 0xfb, 0x23, 0x0e, 0x13, 0xcd, 0x44, 0x65, 0x21, 0x07, 0x64, 0xba, 0x79, - 0x70, 0xf9, 0x2e, 0xe4, 0x5a, 0x37, 0x85, 0xb0, 0x3f, 0xef, 0xb0, 0x20, 0x21, 0x25, 0x0c, 0x99, 0xc9, 0x97, 0x74, - 0xac, 0xf0, 0x4e, 0xf7, 0x98, 0xea, 0x4c, 0x10, 0x3b, 0x06, 0x72, 0x48, 0x12, 0x0b, 0x02, 0x92, 0x20, 0x9c, 0xd4, - 0xe4, 0x3a, 0xa2, 0xd7, 0x40, 0x77, 0x76, 0x0d, 0x8b, 0x11, 0x19, 0xf6, 0x10, 0xe1, 0x44, 0x77, 0xab, 0xd6, 0xe6, - 0x38, 0xc9, 0xe9, 0xa6, 0xa1, 0x5b, 0x25, 0xcf, 0xbe, 0x07, 0xc1, 0xcb, 0x7d, 0xbc, 0xb2, 0x6d, 0x97, 0x09, 0x4f, - 0x9c, 0x45, 0xda, 0xcd, 0x83, 0xcb, 0x5f, 0xad, 0x51, 0xda, 0x9c, 0x3a, 0xf2, 0xbf, 0x25, 0xa3, 0x5e, 0xfe, 0x1a, - 0x55, 0xb9, 0xba, 0xf0, 0xcd, 0x83, 0xcb, 0xdf, 0x77, 0x15, 0x83, 0xf4, 0xf5, 0xa2, 0x52, 0x12, 0xe8, 0xf1, 0x2d, - 0x59, 0x16, 0x2f, 0xed, 0x59, 0x11, 0xcb, 0x35, 0xd6, 0x27, 0x54, 0x9c, 0xaf, 0x4b, 0xdd, 0xca, 0x13, 0x2c, 0x88, - 0xbe, 0x4a, 0xaa, 0x2f, 0x9b, 0x45, 0x63, 0x2e, 0xf2, 0xeb, 0x44, 0xcc, 0xd9, 0x37, 0xee, 0x97, 0x9e, 0x2a, 0x14, - 0xf1, 0x19, 0x18, 0xe2, 0xe8, 0xb1, 0x4b, 0xbc, 0xdf, 0x42, 0xbd, 0x8d, 0xf3, 0x4c, 0x68, 0x44, 0x2d, 0xea, 0x87, - 0x0d, 0xa6, 0xa4, 0x85, 0x13, 0xd2, 0xc2, 0x19, 0xc9, 0x07, 0x2d, 0x73, 0x62, 0xf4, 0xb2, 0xb2, 0x69, 0x73, 0xee, - 0xc0, 0x76, 0xcf, 0xcc, 0xbe, 0x35, 0x87, 0xf2, 0xb4, 0x97, 0x69, 0xfd, 0xa5, 0x3e, 0xe8, 0xa7, 0x1a, 0x35, 0x9e, - 0xb0, 0xb0, 0xc0, 0x85, 0x6e, 0xf9, 0x9a, 0x8f, 0x32, 0xb0, 0x53, 0x81, 0x99, 0x61, 0x85, 0xe2, 0xb2, 0x6c, 0xdb, - 0x96, 0xcd, 0x22, 0xbd, 0x56, 0x05, 0xce, 0x22, 0x20, 0xe5, 0x38, 0xb3, 0x76, 0x3d, 0x72, 0xbb, 0xca, 0xe9, 0xc1, - 0x41, 0x68, 0x2b, 0xd1, 0xb0, 0x70, 0xf9, 0xd5, 0x0d, 0xe0, 0x7b, 0x43, 0x35, 0xa6, 0x48, 0x4f, 0xa0, 0xd1, 0x48, - 0x86, 0x6b, 0xba, 0x4f, 0x48, 0x98, 0xd5, 0xa1, 0xe8, 0x46, 0xaf, 0x99, 0xc1, 0x0d, 0x00, 0x34, 0x1a, 0xe5, 0x75, - 0xef, 0x06, 0xc4, 0x9e, 0x2a, 0x2c, 0xd6, 0x5f, 0xc3, 0xd2, 0x9a, 0xa8, 0xb5, 0x65, 0x87, 0xe5, 0x46, 0x81, 0xa4, - 0x8f, 0xbb, 0xd2, 0xcd, 0xc7, 0xdb, 0x1a, 0xba, 0xdc, 0x0b, 0x6b, 0x03, 0x81, 0xb5, 0xd5, 0x96, 0x2d, 0xe4, 0x48, - 0x5b, 0x07, 0xc5, 0xae, 0x10, 0x5c, 0x70, 0x41, 0xa1, 0xc6, 0xda, 0x62, 0xf9, 0x13, 0xb6, 0x6d, 0xce, 0x89, 0x73, - 0x64, 0xb5, 0x65, 0x7a, 0x18, 0x1a, 0x60, 0x9d, 0x12, 0x30, 0xcf, 0xc9, 0xcb, 0x6f, 0xa3, 0xfe, 0xa5, 0x87, 0xfa, - 0x8f, 0x09, 0xf3, 0xb6, 0x81, 0x59, 0x82, 0x48, 0x58, 0x05, 0x45, 0xee, 0xb2, 0xae, 0xe6, 0x04, 0xb4, 0x71, 0x75, - 0xa8, 0xe6, 0xfe, 0x15, 0xe5, 0x37, 0x28, 0x8b, 0xbf, 0x53, 0xb4, 0x3e, 0x13, 0xbb, 0xfb, 0xe4, 0xb0, 0xba, 0xa0, - 0x83, 0xae, 0x77, 0x29, 0x07, 0x7d, 0x52, 0x78, 0xf9, 0xfb, 0xf7, 0xef, 0x56, 0xaf, 0xe6, 0xdb, 0x3b, 0xd8, 0x33, - 0x2b, 0x85, 0x59, 0x7b, 0x1b, 0xb8, 0x6e, 0x64, 0x0a, 0xfd, 0x97, 0x77, 0xe2, 0x75, 0x2a, 0xb4, 0xb1, 0x19, 0xdd, - 0x71, 0x08, 0xa3, 0x6d, 0xb7, 0x75, 0x09, 0xe6, 0x35, 0x0b, 0x74, 0xc9, 0x18, 0xb7, 0xd2, 0xe2, 0x1b, 0x64, 0xe4, - 0x52, 0x17, 0x60, 0x79, 0xba, 0x3b, 0xfb, 0xf1, 0xda, 0xe2, 0x89, 0x19, 0x1a, 0x5a, 0x6a, 0x42, 0x68, 0xf0, 0x1e, - 0x30, 0xc7, 0x1c, 0x11, 0x00, 0xa2, 0x97, 0x1a, 0x52, 0x15, 0xc8, 0x82, 0xa0, 0x52, 0xe4, 0x3f, 0xdf, 0x27, 0xe4, - 0x65, 0xa5, 0xc8, 0x7c, 0x5b, 0x19, 0x73, 0x01, 0x62, 0xa0, 0x18, 0x2e, 0x12, 0xca, 0x04, 0x73, 0x19, 0xfa, 0x41, - 0xb9, 0xf2, 0x5a, 0xda, 0x8c, 0x2a, 0x6e, 0xdc, 0xbb, 0x29, 0xd5, 0x2a, 0x3e, 0x93, 0xef, 0x20, 0xb1, 0x91, 0xfb, - 0x00, 0x72, 0x19, 0xd5, 0x83, 0x84, 0xef, 0x77, 0xba, 0xb4, 0x6b, 0x77, 0xfd, 0x65, 0xd3, 0x22, 0x66, 0x63, 0x5d, - 0x22, 0x9e, 0x4b, 0x56, 0xa8, 0xc7, 0x6c, 0x2c, 0x0a, 0xb8, 0xff, 0x28, 0xc1, 0x82, 0xd6, 0x0f, 0x3c, 0x1d, 0xa0, - 0x9e, 0xa0, 0x77, 0xe9, 0xb0, 0x31, 0x43, 0xfd, 0xeb, 0x8b, 0xbe, 0x03, 0xbf, 0xd9, 0xac, 0xf5, 0xf2, 0xe0, 0xe0, - 0x2b, 0xab, 0x00, 0x65, 0x87, 0xa9, 0x87, 0xe1, 0x11, 0x2f, 0xc3, 0xe5, 0xd8, 0x9b, 0xe1, 0x07, 0x61, 0xa5, 0x32, - 0x70, 0x84, 0xc3, 0x27, 0x42, 0xcf, 0x89, 0x5a, 0x4f, 0x36, 0xe9, 0xbd, 0xd5, 0x66, 0x48, 0x5f, 0xac, 0x01, 0x72, - 0x0f, 0x72, 0xb9, 0x51, 0x32, 0xe5, 0x95, 0xad, 0x6d, 0x39, 0x88, 0x2b, 0x00, 0x57, 0x98, 0x83, 0x90, 0xe2, 0xa1, - 0x61, 0xbe, 0x53, 0x68, 0x79, 0x2e, 0x80, 0xfd, 0xc7, 0x79, 0x04, 0x22, 0x2d, 0xaa, 0x6d, 0x5c, 0x84, 0x70, 0xae, - 0x25, 0x1e, 0xcf, 0x38, 0xe1, 0xf2, 0xf9, 0x2e, 0x0d, 0xb5, 0x43, 0x6d, 0xa6, 0xcf, 0x20, 0x28, 0x21, 0x50, 0x59, - 0x21, 0xfa, 0x1a, 0x4a, 0xcb, 0xcd, 0x95, 0xf7, 0x70, 0xec, 0x76, 0x2f, 0xa7, 0xa1, 0xb9, 0xdb, 0x82, 0xe3, 0xa3, - 0x88, 0x16, 0x61, 0xad, 0xeb, 0x5e, 0xa1, 0xab, 0x61, 0x0b, 0x3a, 0xea, 0xc3, 0xa9, 0xd0, 0xf7, 0x84, 0x57, 0x15, - 0x49, 0xfd, 0x64, 0x2d, 0xa0, 0x1c, 0x31, 0xac, 0x4c, 0x53, 0xbc, 0xf9, 0x7f, 0xb2, 0xe6, 0x6b, 0xe5, 0x31, 0xc1, - 0xf4, 0x30, 0x6e, 0xcd, 0x2a, 0xb0, 0x35, 0xe0, 0xd8, 0xf2, 0x2f, 0xe1, 0x2d, 0xaa, 0x53, 0x8a, 0xeb, 0x4e, 0x3d, - 0x26, 0xe0, 0x2d, 0x58, 0xcf, 0x6c, 0x6e, 0xfd, 0xe7, 0xfa, 0x60, 0x94, 0x38, 0xaf, 0x11, 0x78, 0xa1, 0x09, 0x3c, - 0x02, 0xc6, 0xcd, 0x99, 0x96, 0xf7, 0xad, 0x11, 0x8d, 0x74, 0x27, 0x9e, 0xc5, 0x33, 0xc3, 0x72, 0x6f, 0x7d, 0x6c, - 0xac, 0x48, 0x2c, 0x09, 0xd8, 0x16, 0x61, 0x4b, 0xe4, 0x05, 0xc2, 0x79, 0xa3, 0xd1, 0xcb, 0xcf, 0x59, 0xa5, 0x55, - 0xa9, 0x86, 0x29, 0xe1, 0x96, 0x18, 0xf0, 0xbe, 0x76, 0xa2, 0xe6, 0x08, 0x97, 0x66, 0xee, 0x39, 0xa8, 0xef, 0x2f, - 0xdf, 0x86, 0x3e, 0x7d, 0xf3, 0xcb, 0x96, 0x17, 0xb1, 0x30, 0xa5, 0xb0, 0xba, 0xc3, 0x79, 0xf3, 0x7d, 0xb3, 0x11, - 0x18, 0xf7, 0x7e, 0x1b, 0x83, 0x8d, 0x1b, 0xea, 0x29, 0x43, 0x1a, 0xca, 0x4d, 0xd8, 0x43, 0x95, 0xbd, 0xa3, 0xdf, - 0x59, 0x4f, 0x55, 0xd2, 0xae, 0x22, 0xf9, 0x7a, 0x2d, 0x59, 0x65, 0x34, 0xb0, 0x61, 0xd8, 0xa9, 0x8f, 0x99, 0x6d, - 0x05, 0xfe, 0xd5, 0x9c, 0x28, 0xec, 0x21, 0xeb, 0x9b, 0x6f, 0x5d, 0xa7, 0x54, 0xc3, 0x84, 0xed, 0x6d, 0xcf, 0xc7, - 0x2b, 0xbe, 0xeb, 0x7c, 0xc4, 0xc2, 0x6e, 0x7d, 0x7d, 0x36, 0xb6, 0xff, 0x8d, 0xb3, 0xd1, 0xaa, 0xed, 0xdd, 0xf1, - 0x08, 0xdc, 0x49, 0xed, 0x78, 0xcc, 0xeb, 0xc7, 0xa3, 0xc0, 0xee, 0xf4, 0xbe, 0xe8, 0xac, 0x56, 0x72, 0xd0, 0x02, - 0xb5, 0x53, 0x10, 0xc0, 0xcf, 0xb6, 0xf9, 0xe9, 0x91, 0x64, 0xa3, 0x43, 0x0e, 0xcb, 0xf3, 0xbe, 0x8d, 0x22, 0x30, - 0xa0, 0x0e, 0xb5, 0xad, 0x97, 0x46, 0x6c, 0x8b, 0x43, 0x16, 0xcb, 0x89, 0x2c, 0xaf, 0xae, 0x60, 0xc4, 0xfa, 0xd8, - 0xb0, 0x02, 0x66, 0xb8, 0xd3, 0xaa, 0xd0, 0x89, 0x9f, 0xff, 0x9a, 0x39, 0xad, 0x1d, 0x31, 0x86, 0x93, 0xa8, 0x59, - 0x31, 0xd8, 0x11, 0x58, 0x86, 0x71, 0x5f, 0x4b, 0xa8, 0xd5, 0xa9, 0x8e, 0x6a, 0x47, 0x12, 0x6e, 0x81, 0xda, 0x6d, - 0x5f, 0x9f, 0x4b, 0xab, 0xd5, 0xce, 0x83, 0x05, 0x17, 0x1e, 0x6e, 0x3f, 0x27, 0xaa, 0x46, 0x52, 0x28, 0xb1, 0x12, - 0x14, 0xce, 0x34, 0xaa, 0x2a, 0x22, 0x06, 0xad, 0x21, 0xf0, 0xa4, 0xbd, 0xe4, 0x5c, 0x54, 0x42, 0x72, 0xd2, 0x68, - 0xa0, 0xac, 0xec, 0x98, 0x0e, 0x64, 0x23, 0x19, 0x62, 0x86, 0x13, 0x23, 0xb0, 0xc0, 0xe9, 0x15, 0x66, 0x55, 0xd7, - 0x83, 0x64, 0x88, 0x70, 0xb1, 0x5a, 0x85, 0x66, 0x68, 0x19, 0x5a, 0xad, 0x32, 0x7f, 0x68, 0x3a, 0x1f, 0x2a, 0xbe, - 0xec, 0x2b, 0xf2, 0x52, 0x9f, 0x87, 0x2f, 0x61, 0x90, 0x0d, 0x12, 0x66, 0x56, 0x25, 0x98, 0x81, 0xe6, 0xaa, 0x21, - 0x06, 0x49, 0xa3, 0x3d, 0xf4, 0x68, 0xd8, 0x20, 0x19, 0x92, 0x6c, 0x0d, 0x96, 0xb3, 0xb9, 0x3d, 0x30, 0xff, 0x82, - 0x83, 0xed, 0x2f, 0x7d, 0xce, 0x98, 0x06, 0xfd, 0x35, 0xd9, 0x54, 0x19, 0x94, 0x78, 0x65, 0x17, 0xd7, 0x95, 0xab, - 0x19, 0x58, 0x94, 0x85, 0xb0, 0xbd, 0x66, 0xee, 0x83, 0xf0, 0x5f, 0x62, 0xbb, 0xa0, 0xa5, 0x11, 0xf7, 0x06, 0xe2, - 0x3b, 0xdb, 0xed, 0x28, 0x8a, 0x68, 0x31, 0xd1, 0x57, 0x22, 0x8e, 0x12, 0xeb, 0x3d, 0x70, 0x6c, 0xc7, 0xe9, 0xf5, - 0x3c, 0x28, 0x3b, 0x1b, 0x12, 0x33, 0x7e, 0xc7, 0xec, 0x38, 0xc7, 0x95, 0x82, 0xee, 0xd6, 0x45, 0x98, 0xc1, 0xd0, - 0xff, 0xe5, 0xc1, 0x9c, 0xd8, 0xc1, 0x18, 0x34, 0xd9, 0x80, 0xdb, 0x37, 0xe0, 0x51, 0xd0, 0x0d, 0xb8, 0x7d, 0x1b, - 0xbe, 0x0e, 0x5a, 0xc9, 0x37, 0x07, 0xe8, 0x91, 0x09, 0x33, 0xd2, 0x2a, 0xc1, 0x1b, 0x66, 0x77, 0x93, 0x23, 0x33, - 0x64, 0x15, 0x0e, 0x57, 0x45, 0x42, 0xb9, 0xb1, 0x17, 0x2a, 0x26, 0xd5, 0xe3, 0xfe, 0x65, 0xfc, 0x12, 0xf9, 0x4a, - 0x83, 0xba, 0x71, 0x0c, 0x60, 0x95, 0xd5, 0xd6, 0xbf, 0x3c, 0x38, 0x00, 0xf3, 0x68, 0x60, 0xed, 0xa2, 0x84, 0xce, - 0xd5, 0xa2, 0x00, 0xfe, 0x2a, 0x77, 0xbf, 0x21, 0x19, 0xdc, 0x4e, 0x74, 0x1a, 0xfc, 0x80, 0x84, 0x39, 0x95, 0x92, - 0x7f, 0x35, 0x69, 0xf6, 0x37, 0x2e, 0x88, 0xc3, 0xe8, 0xdc, 0x70, 0x8a, 0x02, 0xf5, 0x84, 0x45, 0xd7, 0x3a, 0xe4, - 0x9e, 0x7e, 0x65, 0xb9, 0x7a, 0xc9, 0xa5, 0x62, 0x39, 0x00, 0xa0, 0x42, 0x3c, 0x98, 0x52, 0x8e, 0x60, 0xeb, 0xd6, - 0x6a, 0xd1, 0x34, 0xfd, 0x6e, 0x15, 0x55, 0x67, 0x8b, 0xa6, 0x34, 0x4f, 0x33, 0xd3, 0x89, 0x6f, 0x33, 0xe9, 0xec, - 0x44, 0xcb, 0x92, 0xbe, 0xc5, 0x4e, 0xc5, 0x7e, 0x68, 0x5a, 0x1f, 0x4a, 0xe2, 0xce, 0x05, 0x77, 0x96, 0x7e, 0x97, - 0x8f, 0x81, 0x2b, 0xf5, 0x6f, 0xac, 0x82, 0x3f, 0x13, 0xac, 0x3c, 0xf2, 0x1a, 0xd5, 0xc7, 0xe9, 0x50, 0x27, 0xdb, - 0x52, 0x2e, 0x94, 0x46, 0x61, 0x1b, 0x27, 0x85, 0xc6, 0x94, 0xd3, 0x6f, 0x4b, 0x5c, 0xbf, 0xba, 0x63, 0xc4, 0x1d, - 0x1d, 0xf2, 0xdf, 0xa5, 0xd2, 0x68, 0x59, 0x22, 0x18, 0x72, 0x3b, 0xf2, 0x67, 0x09, 0x57, 0xb1, 0x19, 0x57, 0xcf, - 0xd5, 0x2c, 0xdb, 0xf0, 0xc4, 0xe9, 0xfd, 0x5c, 0x5e, 0x23, 0xff, 0x2c, 0xc3, 0x5b, 0x86, 0x9f, 0x30, 0xb8, 0x37, - 0x7e, 0xc6, 0xbd, 0x2a, 0xdb, 0xf7, 0xc5, 0xcf, 0xbc, 0xfb, 0xe2, 0x67, 0x3c, 0xde, 0x2e, 0xea, 0xdd, 0x13, 0x77, - 0xa2, 0xb3, 0xa8, 0x15, 0x38, 0x3e, 0x6a, 0x4a, 0x2b, 0xff, 0x4a, 0xb3, 0x35, 0x70, 0x65, 0x13, 0x07, 0xc6, 0x79, - 0x75, 0x11, 0x8a, 0x59, 0x73, 0x46, 0xc3, 0xe1, 0x7f, 0x6b, 0x9d, 0xec, 0xc9, 0x23, 0x8c, 0x14, 0xf2, 0x86, 0x16, - 0xea, 0x01, 0x6c, 0xb8, 0x62, 0xcb, 0x07, 0x90, 0x12, 0x50, 0xb6, 0xfd, 0x7b, 0x5d, 0x54, 0x8e, 0x07, 0xfd, 0xdc, - 0x38, 0x1f, 0xf9, 0xed, 0x93, 0xa2, 0xe4, 0xea, 0xea, 0x42, 0xc8, 0x9d, 0xd6, 0x12, 0x20, 0x4c, 0x9d, 0x6b, 0x1e, - 0xb3, 0x34, 0x99, 0xc5, 0xcb, 0x75, 0xa9, 0x3a, 0x28, 0x0c, 0x57, 0xc7, 0x11, 0x2e, 0xd6, 0xfa, 0x06, 0xfd, 0x1f, - 0x8e, 0xff, 0xe2, 0x96, 0x46, 0x7e, 0x2a, 0x29, 0xd0, 0xe3, 0xdd, 0xbe, 0x36, 0x3b, 0x48, 0xa4, 0x99, 0x43, 0x69, - 0x29, 0x00, 0x58, 0xad, 0xf1, 0x75, 0xed, 0x70, 0xea, 0x89, 0xb0, 0xb3, 0xf9, 0xa6, 0x21, 0x2c, 0x66, 0xa5, 0x05, - 0x8f, 0xee, 0x66, 0x87, 0xe5, 0xa8, 0x93, 0xc5, 0x55, 0xb9, 0xc7, 0x6a, 0xfd, 0xa2, 0x6f, 0x80, 0xb2, 0x32, 0x44, - 0x5b, 0xad, 0xc2, 0x3a, 0xbc, 0x89, 0xf4, 0xae, 0x41, 0x10, 0x96, 0x9e, 0x01, 0x47, 0x8d, 0xf1, 0x36, 0x75, 0x42, - 0xb4, 0x69, 0xbf, 0xe4, 0x58, 0xf7, 0xda, 0x38, 0x7c, 0x45, 0x83, 0xa9, 0xee, 0x6b, 0x1e, 0xb0, 0x99, 0x5d, 0xd9, - 0x91, 0x07, 0xa1, 0x29, 0x75, 0xc6, 0xb9, 0x95, 0x15, 0xed, 0x0e, 0xf8, 0xa2, 0xef, 0x98, 0xe7, 0x5a, 0xd0, 0x6d, - 0xe7, 0x7b, 0xb6, 0x4d, 0x4f, 0xc4, 0xb7, 0x6c, 0x9b, 0x6a, 0x9c, 0xf0, 0x7e, 0x0b, 0x7d, 0xdf, 0x10, 0xd6, 0xf4, - 0xb5, 0xbb, 0xc8, 0xff, 0x42, 0x77, 0x6d, 0x40, 0x4f, 0x03, 0x66, 0x47, 0x63, 0x3e, 0xa8, 0xf5, 0xfa, 0x53, 0xe9, - 0xbf, 0xa0, 0x6d, 0x85, 0x3e, 0x99, 0x5d, 0x60, 0xc5, 0x4a, 0xed, 0x10, 0x1c, 0xfe, 0xc3, 0xc9, 0x24, 0x13, 0x23, - 0x9a, 0xbd, 0x83, 0x1e, 0xab, 0xdc, 0xe7, 0xf7, 0x69, 0x41, 0x15, 0xb3, 0xb4, 0xa6, 0x1a, 0xc5, 0x3f, 0xdc, 0x1b, - 0xc6, 0x3f, 0xdc, 0x50, 0xee, 0xaa, 0x05, 0xbc, 0x7c, 0x59, 0x36, 0x11, 0x7f, 0x5a, 0x97, 0xfe, 0x56, 0xf9, 0xee, - 0x5e, 0x36, 0x49, 0x9a, 0xca, 0xcb, 0xd9, 0xe6, 0xe1, 0x66, 0x53, 0x61, 0xf8, 0xd7, 0x37, 0x06, 0xbb, 0x4d, 0xe6, - 0xfe, 0xf2, 0xc8, 0xdc, 0x5f, 0x3c, 0xfe, 0x6e, 0x2d, 0x8f, 0xe2, 0x1d, 0x47, 0xc7, 0xda, 0x32, 0xc6, 0x8c, 0xfa, - 0xad, 0x02, 0x83, 0x06, 0x45, 0x2e, 0x3c, 0x6f, 0x87, 0xea, 0xf4, 0x72, 0xf6, 0x47, 0x61, 0xb2, 0x90, 0x4a, 0xcc, - 0x6c, 0xa3, 0xd2, 0xfa, 0x38, 0xe9, 0x4c, 0x50, 0x60, 0xeb, 0x3b, 0xfc, 0xb8, 0xee, 0x46, 0xb6, 0xfc, 0xc2, 0xf3, - 0x34, 0xce, 0xb1, 0x3d, 0x5b, 0x64, 0x2c, 0xd6, 0xc4, 0x99, 0x39, 0x6f, 0xe7, 0xe1, 0x31, 0xcf, 0xb9, 0x9c, 0xb2, - 0x22, 0x2c, 0xd0, 0xf2, 0x5b, 0x9d, 0x15, 0x70, 0x9b, 0x63, 0x3a, 0xc3, 0x69, 0x69, 0x39, 0xa0, 0x22, 0x68, 0x0d, - 0x74, 0x46, 0x33, 0xa6, 0xa6, 0x22, 0x05, 0xc3, 0x97, 0x28, 0x2d, 0xdd, 0xa9, 0x0e, 0x0e, 0xf6, 0xc3, 0x40, 0xeb, - 0x2f, 0xc0, 0x07, 0xdd, 0xcf, 0x41, 0xfd, 0x25, 0x38, 0x06, 0x55, 0x5d, 0x33, 0xb4, 0x64, 0x9b, 0x3e, 0x34, 0x2a, - 0xfa, 0xc2, 0xee, 0x31, 0x47, 0xeb, 0x75, 0x6c, 0x46, 0x1d, 0x8c, 0x39, 0xcb, 0xd2, 0x00, 0x7f, 0x61, 0xf7, 0x71, - 0xe9, 0xb6, 0xae, 0xbd, 0xac, 0xf5, 0x22, 0x06, 0xe2, 0x36, 0x0f, 0x70, 0xd5, 0x49, 0xbc, 0x5c, 0x63, 0x51, 0xf0, - 0x09, 0xe0, 0xe8, 0x2f, 0xec, 0x3e, 0xb6, 0xed, 0x79, 0xae, 0x82, 0x68, 0xe9, 0x40, 0x1f, 0x79, 0xc9, 0xfe, 0x32, - 0x58, 0x81, 0x63, 0xa0, 0xeb, 0x0e, 0x49, 0xad, 0x5c, 0x25, 0x42, 0x22, 0xb4, 0xfe, 0x77, 0xa7, 0x82, 0x17, 0xfe, - 0x39, 0xa7, 0x6a, 0x16, 0xb7, 0x1b, 0x95, 0x18, 0x54, 0xa8, 0x2c, 0x48, 0x3e, 0x86, 0xdc, 0xed, 0x3e, 0xeb, 0xfd, - 0xe0, 0xe9, 0xcc, 0x16, 0xd4, 0x36, 0x1a, 0xa7, 0xfa, 0x17, 0xaa, 0xee, 0xa0, 0x66, 0xaa, 0xaa, 0xb8, 0xf7, 0x31, - 0x04, 0xc0, 0x83, 0xb5, 0x0c, 0xd5, 0x0e, 0xa1, 0x6b, 0x67, 0xa6, 0x3a, 0xa6, 0x24, 0x5c, 0xba, 0x39, 0xc4, 0xdc, - 0x07, 0xa3, 0x5a, 0x03, 0x1a, 0x5a, 0x04, 0x33, 0x96, 0x87, 0x7c, 0x1c, 0xca, 0xad, 0x33, 0x54, 0xe8, 0x33, 0x34, - 0xf2, 0x40, 0xfe, 0x8d, 0x33, 0x93, 0x69, 0x68, 0x68, 0xde, 0x52, 0x1f, 0x80, 0x76, 0x75, 0x2d, 0x0e, 0xf9, 0x2b, - 0x5a, 0x3a, 0xef, 0x99, 0x45, 0x17, 0xb5, 0x61, 0x85, 0xba, 0x1d, 0xb4, 0x8e, 0x61, 0x4a, 0xcc, 0x14, 0x58, 0x3b, - 0xbd, 0x0f, 0x77, 0x76, 0xb5, 0x61, 0x11, 0xb9, 0x69, 0x11, 0x07, 0x93, 0x90, 0xa2, 0x25, 0x0f, 0x29, 0x16, 0x60, - 0x07, 0x59, 0xac, 0xcb, 0xf1, 0x33, 0x7f, 0x39, 0x6a, 0x56, 0xd2, 0xbb, 0x1d, 0x0c, 0x81, 0xcb, 0x57, 0x60, 0x1b, - 0x8a, 0xb9, 0x23, 0x2c, 0x3c, 0xd4, 0x9e, 0x7e, 0xde, 0xba, 0xcd, 0xcd, 0x82, 0xb8, 0x15, 0x18, 0xd3, 0x70, 0xe9, - 0xcd, 0xc2, 0x77, 0x2a, 0xb7, 0x0e, 0x87, 0xf6, 0x9a, 0xb0, 0x32, 0x5e, 0x0d, 0x73, 0xb2, 0x71, 0xf4, 0x7c, 0xdf, - 0xc6, 0xf3, 0xef, 0x05, 0x2b, 0xee, 0xaf, 0x19, 0xd8, 0x58, 0x0b, 0x70, 0x37, 0xae, 0x96, 0xa1, 0x32, 0x90, 0xef, - 0x0b, 0xcd, 0xba, 0xac, 0xf1, 0x77, 0xa3, 0x62, 0xac, 0xf5, 0x3d, 0xa5, 0xa7, 0xad, 0x31, 0xdb, 0x85, 0x7d, 0xd3, - 0x75, 0x93, 0xf5, 0xb4, 0x22, 0xae, 0x82, 0xb4, 0xbd, 0x5b, 0xc0, 0x85, 0xef, 0x0f, 0x3b, 0xc8, 0x87, 0x9b, 0xaa, - 0x1b, 0x48, 0x82, 0x6b, 0x3f, 0xf1, 0xed, 0xa9, 0xee, 0xb2, 0xd6, 0xfd, 0xf6, 0x54, 0x6b, 0x97, 0x85, 0xda, 0x90, - 0x08, 0xdb, 0x7e, 0x4a, 0xff, 0x69, 0xb9, 0x5e, 0xa3, 0x35, 0x0c, 0xef, 0x3d, 0xef, 0x85, 0xe1, 0x7b, 0x67, 0xa1, - 0x18, 0xc1, 0x45, 0xee, 0x75, 0x26, 0x1c, 0x21, 0xaf, 0x46, 0xf0, 0x9e, 0x6f, 0x0d, 0xe1, 0x3d, 0xf7, 0x9c, 0x5e, - 0x41, 0x6a, 0x9a, 0xe4, 0x2c, 0x75, 0xf4, 0x13, 0x19, 0x24, 0xd4, 0x7c, 0xdc, 0x6b, 0x4e, 0xb8, 0xfa, 0x1c, 0x03, - 0xff, 0x85, 0x47, 0x0b, 0xa5, 0x44, 0x8e, 0x79, 0x3e, 0x5f, 0x28, 0x2c, 0xf5, 0xe8, 0x97, 0x63, 0x91, 0xab, 0xe6, - 0x98, 0xce, 0x78, 0x76, 0x1f, 0x2f, 0x78, 0x73, 0x26, 0x72, 0x21, 0xe7, 0x34, 0x61, 0x58, 0xde, 0x4b, 0xc5, 0x66, - 0xcd, 0x05, 0xc7, 0xcf, 0x59, 0xf6, 0x95, 0x29, 0x9e, 0x50, 0xfc, 0x56, 0x8c, 0x84, 0x12, 0xf8, 0xf5, 0xdd, 0xfd, - 0x84, 0xe5, 0xf8, 0xf7, 0xd1, 0x22, 0x57, 0x0b, 0x2c, 0x69, 0x2e, 0x9b, 0x92, 0x15, 0x7c, 0xdc, 0x6b, 0x36, 0xe7, - 0x05, 0x9f, 0xd1, 0xe2, 0xbe, 0x99, 0x88, 0x4c, 0x14, 0xf1, 0x7f, 0xb5, 0x8e, 0xe9, 0xa3, 0xf1, 0x49, 0x4f, 0x15, - 0x34, 0x97, 0x1c, 0x16, 0x26, 0xa6, 0x59, 0xb6, 0x77, 0xdc, 0x6d, 0xcd, 0xe4, 0xbe, 0xb9, 0xf0, 0xa3, 0xb9, 0x5a, - 0x7f, 0xc6, 0x1f, 0x04, 0x8c, 0x32, 0x1a, 0xa9, 0xdc, 0x0e, 0x72, 0x99, 0x2c, 0x0a, 0x29, 0x8a, 0x78, 0x2e, 0x78, - 0xae, 0x58, 0xd1, 0x1b, 0x89, 0x22, 0x65, 0x45, 0xb3, 0xa0, 0x29, 0x5f, 0xc8, 0xf8, 0x64, 0x7e, 0xd7, 0xab, 0xf7, - 0x60, 0xf2, 0xe3, 0x5c, 0xe4, 0xac, 0x07, 0xfc, 0xc6, 0xa4, 0x10, 0x8b, 0x3c, 0xb5, 0xc3, 0x58, 0xe4, 0x92, 0xa9, - 0xde, 0x9c, 0xa6, 0x60, 0x07, 0x1c, 0x9f, 0xcd, 0xef, 0x7a, 0x7a, 0xd6, 0xb7, 0x8c, 0x4f, 0xa6, 0x2a, 0xee, 0xb6, - 0x5a, 0xe6, 0x5b, 0xf2, 0x7f, 0x58, 0xdc, 0xee, 0x44, 0x9d, 0xee, 0xfc, 0x0e, 0x38, 0x78, 0xc5, 0x8a, 0x26, 0xc0, - 0x02, 0x2a, 0xb5, 0xa3, 0xd6, 0xa3, 0xe3, 0x87, 0x90, 0x01, 0x36, 0x0e, 0x4d, 0x3d, 0x21, 0x30, 0x76, 0x8f, 0x17, - 0xf3, 0x39, 0x2b, 0xc0, 0x8b, 0xbe, 0x37, 0xa3, 0xc5, 0x84, 0xe7, 0xcd, 0x42, 0x37, 0xda, 0x3c, 0x9b, 0xdf, 0xad, - 0x61, 0x3e, 0xb1, 0x31, 0x5b, 0xb5, 0xd3, 0xb2, 0x5f, 0x4b, 0x6f, 0x88, 0x3a, 0x26, 0x4d, 0x5c, 0x4c, 0x46, 0x34, - 0x6c, 0x77, 0x1e, 0x62, 0xf7, 0xbf, 0xa8, 0x83, 0x3c, 0xb0, 0x35, 0xd3, 0x45, 0xa1, 0x6f, 0x51, 0xe3, 0xb6, 0x34, - 0xcd, 0x4e, 0xc5, 0x57, 0x56, 0xb8, 0x56, 0xf5, 0xc7, 0x72, 0x6b, 0xde, 0xff, 0x49, 0xa3, 0x9f, 0xf1, 0x84, 0xc2, - 0x1a, 0x68, 0xe4, 0x18, 0x68, 0x79, 0x10, 0x66, 0x3a, 0x5c, 0xde, 0xf2, 0x54, 0x4d, 0xe3, 0x76, 0xab, 0xf5, 0x43, - 0xb5, 0x62, 0xbd, 0xa9, 0x01, 0x5d, 0xbb, 0x60, 0xb3, 0xda, 0x3a, 0xce, 0x68, 0x89, 0x6d, 0xcb, 0xb9, 0xb0, 0x4b, - 0x5e, 0xb0, 0x4c, 0x47, 0x93, 0x59, 0x5b, 0x94, 0xdb, 0x1a, 0x27, 0xcf, 0xa7, 0xac, 0xe0, 0xaa, 0x57, 0xff, 0xaa, - 0x3a, 0xde, 0x5e, 0xfd, 0xb5, 0x91, 0x43, 0x97, 0xa6, 0x86, 0xbd, 0xf4, 0xbc, 0x82, 0x8f, 0xed, 0xd5, 0xff, 0x4a, - 0x8b, 0x70, 0x03, 0x31, 0xb1, 0x5f, 0x03, 0xad, 0xbd, 0x39, 0x17, 0x60, 0x92, 0x39, 0xc4, 0xdf, 0x80, 0x42, 0x42, - 0xb3, 0x24, 0x84, 0x11, 0xed, 0x35, 0xf7, 0x8e, 0x0b, 0x36, 0x43, 0x0e, 0x10, 0xd1, 0xc3, 0x6e, 0xc1, 0x66, 0xeb, - 0x48, 0x57, 0x5f, 0x6a, 0x14, 0xa1, 0x19, 0x9f, 0xe4, 0x71, 0xc2, 0x00, 0x7d, 0xd7, 0x11, 0xcb, 0x15, 0x57, 0xf7, - 0xcd, 0x42, 0xdc, 0x2e, 0x53, 0x2e, 0xe7, 0x19, 0xbd, 0x8f, 0xc7, 0x19, 0xbb, 0xeb, 0xe9, 0x52, 0x4d, 0xae, 0xd8, - 0x4c, 0xda, 0xb2, 0x3d, 0x48, 0x6f, 0xa6, 0xc6, 0x6c, 0x02, 0xa0, 0x27, 0x6e, 0x37, 0xf7, 0x4f, 0x74, 0x2c, 0xf7, - 0x18, 0x95, 0xac, 0x29, 0x16, 0x6a, 0xaf, 0x25, 0x7b, 0x33, 0x9e, 0x37, 0xed, 0x40, 0x4e, 0x5a, 0xf3, 0xbb, 0xde, - 0x36, 0xe4, 0xbd, 0xfe, 0x23, 0x76, 0x37, 0xa7, 0x79, 0xca, 0xd2, 0xa5, 0x57, 0xad, 0x03, 0xf5, 0xfc, 0x52, 0x71, - 0xae, 0xa6, 0x4d, 0x6d, 0xeb, 0x15, 0x76, 0x72, 0xf4, 0x0d, 0xd4, 0x7a, 0xd4, 0xc2, 0xe6, 0xff, 0xa3, 0x36, 0xf2, - 0x2b, 0xef, 0x41, 0xd8, 0x25, 0x3e, 0xbe, 0x6f, 0xc2, 0xdf, 0x25, 0xf8, 0x16, 0xf1, 0x84, 0x66, 0x16, 0x22, 0x33, - 0x9e, 0xa6, 0x59, 0x6d, 0x44, 0x17, 0x5e, 0x67, 0x6d, 0xb4, 0x84, 0xf9, 0xc7, 0xad, 0xbd, 0xd6, 0x9e, 0x9e, 0x8b, - 0xdd, 0xe6, 0x27, 0x27, 0x0f, 0x8f, 0x1f, 0xb1, 0x5e, 0xc6, 0x73, 0x56, 0x9b, 0xea, 0x77, 0x41, 0xed, 0x37, 0xdc, - 0xb1, 0x0d, 0xb7, 0xf7, 0xda, 0x7b, 0x27, 0xad, 0x1f, 0xdc, 0x6e, 0xcd, 0xd8, 0x58, 0xc5, 0xed, 0xd3, 0xf9, 0x5d, - 0x7d, 0xfb, 0x9e, 0xb9, 0xa6, 0x6f, 0x0b, 0x3a, 0x8f, 0x73, 0x01, 0x7f, 0x7a, 0xb0, 0xc9, 0xc6, 0x99, 0xb8, 0x8d, - 0xa7, 0x3c, 0x4d, 0x59, 0x6e, 0x0a, 0x94, 0x89, 0x2c, 0xcb, 0xf8, 0x5c, 0x72, 0xb3, 0x1a, 0x16, 0x77, 0xbb, 0x1b, - 0x50, 0xf5, 0x07, 0x74, 0xec, 0x0d, 0xa8, 0x5b, 0x0d, 0xa8, 0xea, 0xdf, 0x1f, 0x61, 0x67, 0x63, 0xae, 0xba, 0x54, - 0xaf, 0x86, 0x49, 0x7f, 0x2d, 0xa4, 0x02, 0x98, 0x97, 0x46, 0x1a, 0x40, 0xc5, 0x9b, 0x23, 0xa6, 0x6e, 0x19, 0xcb, - 0xbf, 0x3d, 0x88, 0x8b, 0x58, 0xe4, 0xd9, 0xbd, 0xf9, 0x5c, 0xfa, 0x5d, 0xd2, 0x85, 0x12, 0xeb, 0x68, 0xc4, 0x73, - 0x5a, 0xdc, 0xdf, 0x48, 0x96, 0x4b, 0x51, 0xdc, 0x88, 0xf1, 0x78, 0xf9, 0x2d, 0xd2, 0xf2, 0x10, 0xad, 0x23, 0xc9, - 0xf3, 0x49, 0xc6, 0x0c, 0x51, 0xd2, 0x88, 0x60, 0x89, 0xb9, 0x69, 0x57, 0x37, 0x59, 0x1b, 0xb4, 0xbf, 0xf3, 0x74, - 0xbb, 0xc3, 0x38, 0x6e, 0xde, 0xb2, 0xd1, 0x17, 0xae, 0x0c, 0x9e, 0x35, 0xe5, 0x2d, 0x78, 0xbc, 0xe8, 0x65, 0x98, - 0xb3, 0x62, 0xe9, 0x68, 0x78, 0xcb, 0xa3, 0x3a, 0x51, 0x92, 0xf1, 0x19, 0x55, 0xcc, 0xa3, 0x54, 0x65, 0x27, 0x93, - 0x82, 0xa7, 0xdb, 0x38, 0xd2, 0x83, 0xe4, 0xa6, 0x33, 0xa8, 0x82, 0x9e, 0x16, 0xb3, 0x5c, 0xc6, 0x05, 0x9b, 0x33, - 0xaa, 0xc2, 0x63, 0xdc, 0x1e, 0x17, 0xa8, 0x37, 0xa1, 0xf3, 0x18, 0xf0, 0xc2, 0x75, 0xd9, 0x86, 0x25, 0xd8, 0xde, - 0xae, 0xeb, 0xcf, 0xf8, 0x8b, 0xd4, 0x87, 0x97, 0xa2, 0xa3, 0x26, 0x84, 0x1f, 0x63, 0x45, 0xb9, 0xc5, 0x79, 0xae, - 0x11, 0x56, 0xaf, 0xcf, 0xe6, 0x26, 0xf5, 0x8f, 0xa0, 0x93, 0x56, 0xcb, 0xf5, 0xd3, 0x34, 0x75, 0xe2, 0x76, 0xd4, - 0x65, 0xb3, 0x5d, 0xe4, 0xa1, 0x4e, 0x0b, 0xdb, 0x9d, 0xf9, 0xdd, 0x9e, 0xfe, 0xa7, 0xb5, 0xd7, 0xda, 0xa6, 0x7d, - 0xdb, 0xcb, 0x74, 0x8c, 0x1c, 0x62, 0x29, 0x31, 0x8f, 0xdb, 0x6c, 0xd6, 0x5b, 0x48, 0x38, 0xe7, 0x34, 0x69, 0xd6, - 0xe7, 0xe7, 0x5a, 0xcf, 0x04, 0xd0, 0x88, 0xf2, 0x1c, 0x8e, 0x15, 0x73, 0xb4, 0x42, 0x1f, 0x52, 0x80, 0x1d, 0xf8, - 0xce, 0x46, 0xeb, 0xc3, 0x6a, 0xed, 0x55, 0x03, 0x83, 0x7f, 0xd6, 0x9f, 0x2b, 0xc6, 0xf4, 0x05, 0xf3, 0x04, 0x03, - 0xde, 0x88, 0xba, 0xab, 0x96, 0x15, 0x06, 0x52, 0x55, 0xc9, 0x28, 0xda, 0x95, 0x62, 0x46, 0xef, 0x8c, 0x4f, 0xc5, - 0x8c, 0xe7, 0x60, 0xb1, 0x85, 0xb0, 0xf2, 0x6c, 0xdb, 0xa7, 0x7e, 0x43, 0xa9, 0x0a, 0xa1, 0xe1, 0xc3, 0x4e, 0xd4, - 0xed, 0x22, 0xdc, 0xc2, 0x9d, 0x6e, 0xd7, 0x13, 0x46, 0xc6, 0x6a, 0x57, 0xd1, 0x5d, 0x25, 0xf3, 0x1d, 0x25, 0x8f, - 0x74, 0xa3, 0x47, 0xed, 0x56, 0x0b, 0x6b, 0xbf, 0xf1, 0xb2, 0x30, 0xcb, 0x77, 0x34, 0xdb, 0x6e, 0xb5, 0xa0, 0x59, - 0xf8, 0x63, 0xe7, 0xf5, 0x0b, 0x59, 0xb6, 0xe2, 0x16, 0x6e, 0xc7, 0x6d, 0xdc, 0x89, 0x3b, 0xf8, 0x38, 0x3e, 0xc6, - 0x27, 0xf1, 0x09, 0xee, 0xc6, 0x5d, 0x7c, 0x1a, 0x9f, 0xe2, 0x87, 0xf1, 0x43, 0x7c, 0x16, 0x9f, 0xe1, 0x47, 0xf1, - 0x23, 0x7c, 0x19, 0xb7, 0x5b, 0xf8, 0x71, 0xdc, 0x6e, 0xe3, 0xab, 0xb8, 0xdd, 0xc1, 0x4f, 0xe2, 0xf6, 0x31, 0x7e, - 0x1a, 0xb7, 0x4f, 0xf0, 0xb3, 0xb8, 0xdd, 0xc5, 0x14, 0x72, 0x47, 0x90, 0x9b, 0x40, 0x6e, 0x0a, 0xb9, 0x0c, 0x72, - 0xc7, 0x71, 0xbb, 0xbb, 0xc6, 0xd2, 0xc4, 0x9a, 0x08, 0x5a, 0xed, 0xce, 0xf1, 0x49, 0xf7, 0xf4, 0xe1, 0xd9, 0xa3, - 0xcb, 0xc7, 0x57, 0x4f, 0x9e, 0x3e, 0x0b, 0x86, 0x78, 0xa4, 0x5d, 0x3e, 0xa4, 0x1c, 0xf0, 0x83, 0x76, 0x77, 0x88, - 0x6f, 0xdc, 0x67, 0xc8, 0x0f, 0x3a, 0x27, 0x2d, 0x74, 0x71, 0x71, 0x32, 0x6c, 0x94, 0xb9, 0xef, 0xb5, 0xa7, 0x49, - 0x95, 0x45, 0x08, 0x09, 0x21, 0x07, 0xe1, 0x7b, 0x5d, 0xef, 0x3d, 0x0b, 0x79, 0x54, 0xa0, 0x83, 0x03, 0xfd, 0x63, - 0xe2, 0x7e, 0x8c, 0xdc, 0x0f, 0xea, 0x2d, 0xd2, 0x1d, 0x0d, 0xad, 0xab, 0xb1, 0x2a, 0x0d, 0xfd, 0x4b, 0x1b, 0x9a, - 0x3d, 0x6e, 0xad, 0xd9, 0xff, 0x2b, 0x30, 0xd6, 0x2a, 0xe4, 0xc4, 0x68, 0x84, 0xba, 0x7d, 0x46, 0x96, 0x45, 0xdc, - 0xe9, 0x76, 0x0f, 0x7e, 0x19, 0xf0, 0x41, 0x7b, 0x38, 0x3c, 0x6c, 0x3f, 0xc4, 0x93, 0x32, 0xa1, 0x63, 0x12, 0x46, - 0x65, 0xc2, 0xb1, 0x49, 0xa0, 0xb1, 0xa9, 0x0d, 0x49, 0x27, 0x3a, 0x09, 0x4a, 0xac, 0x63, 0xdd, 0xf6, 0x43, 0xd3, - 0xf6, 0x23, 0x30, 0xa3, 0xd2, 0xcd, 0xdb, 0xa6, 0xcf, 0xcf, 0x4f, 0x56, 0xb6, 0x51, 0x3c, 0x89, 0x6d, 0x6b, 0x2e, - 0xf1, 0x64, 0x38, 0xc4, 0x23, 0x9d, 0xd8, 0xad, 0x12, 0x4f, 0x87, 0x43, 0xdb, 0xd5, 0x23, 0xdd, 0xd5, 0xc3, 0x2a, - 0xeb, 0x6c, 0x38, 0xd4, 0x5d, 0x22, 0xeb, 0x34, 0x2f, 0xd5, 0xde, 0xd7, 0x52, 0x71, 0xc1, 0xcf, 0x3b, 0xdd, 0x6e, - 0x1f, 0x30, 0x4c, 0x1b, 0xc3, 0x3a, 0x18, 0xdd, 0x7a, 0x30, 0xba, 0x87, 0xdf, 0xfd, 0x11, 0x8d, 0x6f, 0x68, 0x09, - 0xa4, 0x7e, 0xf0, 0x5f, 0x41, 0x43, 0x69, 0x98, 0xeb, 0x3f, 0x13, 0xf3, 0x67, 0x84, 0x1a, 0x5f, 0x29, 0x80, 0x1b, - 0x54, 0x31, 0x4e, 0x97, 0xaa, 0x7b, 0xfc, 0x42, 0xc1, 0xb7, 0x65, 0x2a, 0x33, 0xda, 0x5f, 0x4d, 0x6f, 0x47, 0xab, - 0xa9, 0xfc, 0x8a, 0xfe, 0x0c, 0xff, 0x94, 0x87, 0xe1, 0xa0, 0xd9, 0x88, 0xd8, 0x9f, 0x29, 0x38, 0xd1, 0xf4, 0xe3, - 0x94, 0x4d, 0x50, 0x7f, 0xf0, 0xa7, 0xc4, 0xc3, 0x86, 0x97, 0xf1, 0xc3, 0x76, 0x0a, 0xb8, 0xd8, 0x6c, 0x26, 0x86, - 0x3f, 0xa0, 0x3e, 0xea, 0xff, 0x29, 0x0f, 0xff, 0x44, 0x0f, 0x8e, 0xaa, 0xb9, 0xfc, 0x2e, 0xec, 0x16, 0xae, 0xe2, - 0xee, 0x1c, 0x96, 0x5b, 0x98, 0xe1, 0x76, 0x93, 0x41, 0x94, 0x32, 0xf0, 0xc1, 0x26, 0xa1, 0x68, 0xf0, 0xa3, 0xe3, - 0x16, 0xfa, 0xa1, 0xdd, 0x01, 0xad, 0x42, 0x53, 0x1e, 0x6e, 0x6f, 0xfa, 0xa2, 0x79, 0x8c, 0x1f, 0x35, 0x0b, 0xdc, - 0x46, 0xb8, 0xd9, 0x76, 0xea, 0xde, 0x41, 0x1e, 0xb6, 0x10, 0xce, 0xc3, 0x33, 0xf8, 0xe7, 0x04, 0x0d, 0xab, 0x0d, - 0x79, 0x4d, 0x37, 0x7b, 0x07, 0x87, 0x51, 0x12, 0xe6, 0x0d, 0x7e, 0x74, 0xda, 0x42, 0x3f, 0x9c, 0xea, 0x8e, 0xd8, - 0xa1, 0xda, 0xd1, 0x95, 0xc0, 0x27, 0x4d, 0x01, 0x1d, 0xb5, 0xca, 0x7e, 0x64, 0xd8, 0x45, 0x58, 0x86, 0xc7, 0xf0, - 0x4f, 0xdb, 0xef, 0xe7, 0xd7, 0xad, 0x7e, 0xf4, 0xbc, 0xdb, 0x38, 0xea, 0x1a, 0xff, 0xd3, 0xdc, 0x5c, 0x06, 0x37, - 0xd8, 0x45, 0x5b, 0xdf, 0x62, 0xb5, 0x8f, 0xe0, 0x03, 0x61, 0x75, 0x48, 0x72, 0xcc, 0x0e, 0xc1, 0x71, 0x15, 0xec, - 0x35, 0xf2, 0xf3, 0xe3, 0x5e, 0xde, 0x68, 0x20, 0x90, 0x0f, 0x0f, 0x49, 0xbb, 0xa9, 0x9a, 0x0c, 0xc3, 0xef, 0x06, - 0x29, 0xa3, 0xa1, 0xc9, 0xaa, 0xd7, 0x2b, 0xdb, 0xab, 0xb9, 0xf2, 0x76, 0xd8, 0x01, 0x62, 0x62, 0x3f, 0x54, 0x4d, - 0x86, 0x8e, 0x64, 0x23, 0x54, 0xe7, 0xac, 0x7f, 0x1a, 0xb7, 0x90, 0xc6, 0xce, 0xbc, 0x1f, 0xb2, 0x26, 0x87, 0xf4, - 0x4e, 0x1c, 0xf2, 0xa6, 0x82, 0x5f, 0x27, 0x1e, 0xb4, 0x24, 0xe0, 0x5d, 0xe5, 0x86, 0x53, 0x1c, 0x75, 0xba, 0x5d, - 0x2c, 0x09, 0x8f, 0x26, 0xfa, 0x57, 0x4e, 0x78, 0x34, 0xd2, 0xbf, 0x04, 0x29, 0xe1, 0x65, 0x7a, 0xc7, 0x05, 0xf1, - 0x56, 0x55, 0xa7, 0x50, 0x58, 0xd0, 0x02, 0x1d, 0x75, 0xdc, 0x7d, 0x38, 0x9e, 0xba, 0x39, 0x80, 0xfc, 0x5f, 0x68, - 0x53, 0x48, 0xd1, 0x2c, 0x70, 0x46, 0xe8, 0x45, 0xd4, 0xed, 0x4f, 0x8f, 0xc2, 0x4e, 0x53, 0x34, 0x0b, 0x14, 0x4f, - 0x8f, 0x74, 0x4d, 0x9c, 0x90, 0x2b, 0x6a, 0x5a, 0xc3, 0x53, 0xb8, 0xc4, 0x4c, 0x48, 0x72, 0x78, 0xda, 0x6a, 0x44, - 0x5d, 0x84, 0x07, 0xc9, 0xaa, 0x85, 0xb3, 0xd5, 0xaa, 0x85, 0xa9, 0xbf, 0x0c, 0xd2, 0x01, 0xa4, 0x54, 0x51, 0x6d, - 0x06, 0xa5, 0xe9, 0xf3, 0x50, 0xc1, 0x85, 0xbc, 0x02, 0x37, 0x17, 0x05, 0x0e, 0x38, 0x31, 0xb7, 0x37, 0x61, 0x48, - 0x87, 0xe5, 0x1b, 0xfb, 0x4a, 0xab, 0x2b, 0xe9, 0xd6, 0xd5, 0x8e, 0xfc, 0x57, 0x19, 0xfe, 0x2e, 0xb0, 0x49, 0xab, - 0x8a, 0xbd, 0xa6, 0xdb, 0xc5, 0x7e, 0xa5, 0x5b, 0xc5, 0xde, 0xec, 0x28, 0x76, 0xbd, 0x5d, 0xec, 0xa3, 0xf0, 0x54, - 0x6c, 0xfc, 0x87, 0xe3, 0xd3, 0x56, 0xe3, 0x18, 0x90, 0xf5, 0xf8, 0xb4, 0x55, 0x15, 0x7a, 0x40, 0xab, 0xb5, 0x52, - 0xe4, 0x0b, 0x35, 0x4e, 0x06, 0xdc, 0x79, 0x3b, 0xeb, 0x85, 0x33, 0xbe, 0xd6, 0xa5, 0x63, 0xf5, 0xa0, 0x0b, 0x46, - 0x1c, 0x52, 0x53, 0x3b, 0x35, 0x38, 0x1d, 0xf6, 0xa7, 0x2c, 0x6c, 0x40, 0x2a, 0x8a, 0xc7, 0xca, 0xfe, 0x42, 0xe5, - 0x5d, 0xee, 0x47, 0x01, 0x49, 0x9d, 0x21, 0xc2, 0x82, 0x34, 0xd4, 0xe0, 0x78, 0xa8, 0xcf, 0xbb, 0x02, 0x7e, 0x9f, - 0xe8, 0xdf, 0xa5, 0x26, 0xc5, 0x7a, 0x22, 0x4c, 0x6f, 0x47, 0x41, 0x5f, 0x92, 0xd7, 0x34, 0xd4, 0xc6, 0xe5, 0x28, - 0x2e, 0x33, 0xe4, 0x57, 0xc8, 0x78, 0x53, 0x66, 0x48, 0x72, 0x25, 0xed, 0x6f, 0xbc, 0x2c, 0x62, 0x30, 0x34, 0xc1, - 0x93, 0x18, 0x8c, 0x4c, 0xf0, 0x28, 0x96, 0xe0, 0x08, 0x41, 0x63, 0xe6, 0x99, 0xaf, 0x5f, 0x5a, 0xd5, 0x95, 0xbe, - 0x6e, 0x25, 0x1a, 0x4b, 0x7b, 0x0c, 0x4e, 0x8a, 0x8f, 0x22, 0x84, 0xbf, 0x0d, 0x85, 0x30, 0x83, 0x36, 0x19, 0xc2, - 0x3c, 0x2a, 0x08, 0xa4, 0x61, 0x1e, 0x4d, 0x08, 0x83, 0x26, 0x79, 0x34, 0x22, 0x6c, 0xd0, 0xf1, 0xd0, 0xe4, 0xa9, - 0x86, 0x1d, 0x00, 0x87, 0xd7, 0x6f, 0xb0, 0x95, 0x69, 0x1c, 0xae, 0xc6, 0xa1, 0x09, 0x49, 0x58, 0x1e, 0xc2, 0x2c, - 0x60, 0x73, 0xea, 0x9f, 0x9d, 0x2a, 0xee, 0x23, 0x8f, 0xa8, 0xa6, 0xde, 0x9f, 0x81, 0xac, 0x86, 0x0f, 0x96, 0x6c, - 0x8d, 0xf7, 0x1e, 0x2c, 0xe5, 0xfa, 0x07, 0xf8, 0x93, 0xdb, 0x3f, 0x4a, 0x9f, 0x7e, 0x6b, 0xf4, 0x39, 0x86, 0x62, - 0x3b, 0x4a, 0xa1, 0xcf, 0xce, 0x0f, 0x2e, 0x27, 0xcb, 0xbb, 0x38, 0x48, 0x69, 0xf1, 0x25, 0xc0, 0x9f, 0xe2, 0x20, - 0x03, 0x46, 0x30, 0xc0, 0x1f, 0xe3, 0xa0, 0x60, 0x01, 0xfe, 0x23, 0x0e, 0x46, 0xd9, 0x22, 0xc0, 0x1f, 0xe2, 0x60, - 0x52, 0x04, 0xf8, 0x3d, 0x68, 0x29, 0x53, 0xbe, 0x98, 0x05, 0xf8, 0xf7, 0x38, 0x90, 0xda, 0x0d, 0x00, 0x5f, 0xc6, - 0x01, 0x63, 0x01, 0x7e, 0x17, 0x07, 0x22, 0x0b, 0xf0, 0x75, 0x1c, 0x88, 0x22, 0xc0, 0x8f, 0xe3, 0xa0, 0xa0, 0x01, - 0xbe, 0x8a, 0x03, 0x28, 0x34, 0x09, 0xf0, 0x93, 0x38, 0x80, 0x96, 0x65, 0x80, 0xdf, 0xc6, 0x01, 0xcf, 0x03, 0xfc, - 0x5b, 0x1c, 0xa8, 0x45, 0xf1, 0xf7, 0x42, 0x70, 0x19, 0xe0, 0xa7, 0x71, 0x30, 0xe5, 0x01, 0x7e, 0x13, 0x07, 0x85, - 0x08, 0xf0, 0xeb, 0x38, 0xa0, 0x59, 0x80, 0x5f, 0xc5, 0x41, 0xc6, 0x02, 0xfc, 0x6b, 0x1c, 0xa4, 0x2c, 0xc0, 0x2f, - 0xe3, 0xe0, 0x9e, 0x65, 0x99, 0x08, 0xf0, 0xb3, 0x38, 0x60, 0x79, 0x80, 0x7f, 0x89, 0x83, 0x64, 0x1a, 0xe0, 0x9f, - 0xe2, 0x80, 0x16, 0x5f, 0x64, 0x80, 0x9f, 0xc7, 0x01, 0xa3, 0x01, 0x7e, 0x61, 0x3a, 0x9a, 0x04, 0xf8, 0xe7, 0x38, - 0xb8, 0x9d, 0x06, 0x6b, 0x9c, 0xe7, 0x64, 0xf9, 0x9a, 0x27, 0xec, 0x0f, 0x16, 0x07, 0xe3, 0xd6, 0xf8, 0x6c, 0x3c, - 0x0e, 0x30, 0xcd, 0x15, 0xff, 0x7b, 0xc1, 0x6e, 0x9f, 0x2a, 0x48, 0xa4, 0x6c, 0x94, 0x3e, 0x0c, 0x30, 0xfd, 0x7b, - 0x41, 0xe3, 0x60, 0x3c, 0xd6, 0x05, 0xfe, 0x5e, 0xd0, 0x19, 0x2d, 0xde, 0xb2, 0x38, 0x78, 0x38, 0x1e, 0x8f, 0xd3, - 0x93, 0x00, 0xd3, 0x7f, 0x16, 0x1f, 0x75, 0x0b, 0xba, 0xc0, 0x88, 0xf1, 0x09, 0xd4, 0xed, 0x8e, 0xbb, 0x69, 0x12, - 0xe0, 0x11, 0x97, 0x7f, 0x2f, 0xe0, 0x7b, 0xcc, 0x4e, 0x92, 0x93, 0x00, 0x8f, 0x32, 0x9a, 0x7c, 0x89, 0x83, 0x96, - 0xfe, 0x95, 0xff, 0xc2, 0xd2, 0xd7, 0x33, 0xa1, 0x75, 0xf8, 0x63, 0x36, 0x4a, 0xd2, 0x00, 0xeb, 0xc1, 0x8c, 0xe1, - 0xef, 0x57, 0xfe, 0x8e, 0xa9, 0x38, 0x38, 0xa3, 0x9d, 0x11, 0xeb, 0x04, 0x78, 0xf4, 0xe6, 0x36, 0x8f, 0x03, 0xda, - 0xed, 0xd0, 0x0e, 0x0d, 0xf0, 0x68, 0x51, 0x64, 0xf7, 0xb7, 0x42, 0xa4, 0x00, 0x84, 0xd1, 0xd9, 0xd9, 0xc3, 0x00, - 0x27, 0xf4, 0x57, 0x05, 0xb5, 0xbb, 0xe3, 0x47, 0x8c, 0xb6, 0x02, 0xfc, 0x0b, 0x2d, 0xd4, 0xc7, 0x85, 0xb4, 0x03, - 0x6d, 0x41, 0x8a, 0x48, 0xde, 0x81, 0x7e, 0x3b, 0x48, 0x3b, 0xa7, 0x8f, 0xda, 0x2c, 0xc0, 0xc9, 0xf5, 0x6b, 0xe8, - 0xed, 0xe1, 0xb8, 0xdb, 0x82, 0x8f, 0x1c, 0x04, 0x45, 0x56, 0x40, 0x23, 0xa7, 0x27, 0x8f, 0xba, 0x2c, 0xd5, 0x89, - 0x92, 0x67, 0x5f, 0xf4, 0xec, 0xcf, 0x60, 0x3e, 0x49, 0xc1, 0x67, 0x52, 0xe4, 0x71, 0x90, 0x26, 0xed, 0x93, 0x63, - 0x48, 0xb8, 0xa7, 0xb9, 0x03, 0xce, 0x1d, 0x54, 0x3d, 0x1b, 0x05, 0xf8, 0xce, 0xa4, 0x9e, 0x8d, 0xf4, 0xc7, 0xe4, - 0xdd, 0xaf, 0xf9, 0x9b, 0x34, 0x0e, 0x46, 0x67, 0x67, 0xa7, 0x2d, 0x48, 0xf8, 0x40, 0xef, 0xe3, 0x80, 0x3e, 0x82, - 0xff, 0x20, 0xfb, 0xe3, 0x33, 0xe8, 0x10, 0x46, 0x78, 0x37, 0xf9, 0xe8, 0xe7, 0x7c, 0x99, 0xd2, 0x2f, 0x3c, 0x0e, - 0x46, 0xe9, 0xe8, 0xe1, 0x29, 0xd4, 0x9b, 0xd1, 0xc9, 0x33, 0x45, 0xa1, 0xdd, 0x56, 0x4b, 0xb7, 0xfc, 0x8e, 0x7f, - 0x65, 0xba, 0x7a, 0xb7, 0x7b, 0x3a, 0xea, 0xc0, 0x08, 0xae, 0x41, 0xc3, 0x01, 0xe3, 0x39, 0x4b, 0x74, 0x83, 0xd7, - 0xc9, 0xd3, 0x34, 0x0e, 0x1e, 0x3d, 0x3a, 0xee, 0x24, 0x49, 0x80, 0xef, 0x3e, 0xa6, 0xa6, 0xb6, 0xce, 0x93, 0x00, - 0xfb, 0x38, 0x60, 0x8f, 0x1e, 0x9d, 0x3e, 0xa4, 0xf0, 0xfd, 0x5c, 0xb7, 0x75, 0x36, 0x1e, 0x25, 0x67, 0xd0, 0xd6, - 0xef, 0x30, 0x9d, 0x93, 0xb3, 0xe3, 0x54, 0xf7, 0xf5, 0xbb, 0x1e, 0x75, 0x67, 0x7c, 0x32, 0x3e, 0xd1, 0x99, 0x7a, - 0xa8, 0xe5, 0xe7, 0x6f, 0x2c, 0x0e, 0x12, 0x96, 0xb6, 0x03, 0x7c, 0x67, 0x17, 0xee, 0xd1, 0x49, 0xab, 0x95, 0x1e, - 0x07, 0x38, 0xbd, 0x9c, 0xcf, 0xdf, 0x6a, 0x08, 0xb6, 0x4f, 0x1e, 0x99, 0x6f, 0xf9, 0xe5, 0x1e, 0x9a, 0x1e, 0x69, - 0xa0, 0xa5, 0x7c, 0xa6, 0x5b, 0x3e, 0x7d, 0x04, 0xff, 0xe9, 0x6f, 0xdd, 0x74, 0xf9, 0x2d, 0xd2, 0x89, 0x59, 0x94, - 0x36, 0x7b, 0xd4, 0x82, 0x1a, 0x63, 0xfe, 0x71, 0x54, 0x70, 0x40, 0xa3, 0x51, 0x07, 0xfe, 0x2f, 0xc0, 0xe3, 0xec, - 0xfa, 0xb5, 0xc5, 0xd9, 0xf1, 0x98, 0x8e, 0x5b, 0x01, 0x1e, 0x8b, 0x8f, 0x52, 0x7d, 0xb8, 0xcc, 0xe3, 0xa0, 0xd3, - 0x39, 0x1b, 0xe9, 0x32, 0x8b, 0x5f, 0x24, 0xd7, 0x78, 0xdc, 0xd2, 0xad, 0x4c, 0xe8, 0x5b, 0x39, 0xba, 0x16, 0xb0, - 0x92, 0xf0, 0x5f, 0x80, 0x27, 0xa0, 0x16, 0xb3, 0xad, 0x9c, 0x99, 0xed, 0x30, 0x79, 0xa7, 0x51, 0x33, 0x7d, 0x08, - 0xf0, 0x72, 0xcb, 0x98, 0x52, 0xda, 0xed, 0xb4, 0x02, 0xac, 0x47, 0x7d, 0xd6, 0x82, 0xff, 0x02, 0x6c, 0x20, 0xa7, - 0xe1, 0x3a, 0xf9, 0xf8, 0xec, 0xe5, 0x6d, 0x1c, 0xd0, 0x74, 0x3c, 0x86, 0x25, 0xd1, 0x93, 0x71, 0xc5, 0xa6, 0x22, - 0x67, 0xf7, 0xbf, 0xde, 0xda, 0xed, 0xa2, 0x13, 0x94, 0x85, 0xce, 0xe9, 0xa3, 0xd1, 0x49, 0x80, 0xdf, 0xa6, 0x9c, - 0xe6, 0xb0, 0x4a, 0x49, 0xda, 0x4d, 0xba, 0x89, 0x4e, 0x98, 0x88, 0x38, 0x38, 0x81, 0x25, 0xef, 0x04, 0x98, 0x7f, - 0xbd, 0xbe, 0x37, 0xe8, 0x06, 0xb5, 0x2d, 0x82, 0x8c, 0x5b, 0xec, 0xf4, 0x2c, 0x09, 0x70, 0x46, 0xbf, 0x3e, 0xfb, - 0xb5, 0x88, 0x03, 0x76, 0xca, 0x4e, 0xc7, 0xd4, 0x7d, 0xff, 0x21, 0xa7, 0xba, 0x46, 0x6b, 0xdc, 0x85, 0xa4, 0xdb, - 0x5c, 0x8f, 0xf5, 0x61, 0x32, 0xd6, 0x18, 0xf2, 0x6a, 0x26, 0xf2, 0xe4, 0xe9, 0x78, 0x2c, 0x0c, 0x16, 0x53, 0xd8, - 0x84, 0x9f, 0x00, 0xda, 0x34, 0x4d, 0xcf, 0xd8, 0x69, 0x80, 0x3f, 0x99, 0x5d, 0x62, 0x27, 0xf0, 0xc9, 0x60, 0x36, - 0xb3, 0xbb, 0xfd, 0x93, 0x01, 0x0a, 0xcc, 0x77, 0x4c, 0xc7, 0x34, 0xed, 0x04, 0xf8, 0x93, 0x86, 0x4b, 0x7a, 0x0c, - 0xff, 0x41, 0x01, 0xe8, 0xec, 0x51, 0x8b, 0xb1, 0x47, 0x2d, 0xfd, 0xe5, 0xe7, 0xd9, 0x99, 0x8f, 0x4e, 0x93, 0x76, - 0x80, 0x3f, 0x59, 0x74, 0x1c, 0x8f, 0x69, 0x0b, 0xd0, 0xf1, 0x93, 0x45, 0xc7, 0x4e, 0x6b, 0xd4, 0xa1, 0xfa, 0xdb, - 0x60, 0xcd, 0xd9, 0xc3, 0x84, 0xc1, 0xe4, 0x3e, 0x19, 0x84, 0x7c, 0xf8, 0xf0, 0xec, 0xec, 0xd1, 0x23, 0xf8, 0xd4, - 0x6d, 0x97, 0x9f, 0x52, 0x5d, 0x66, 0x1a, 0xc9, 0x5a, 0xc9, 0x09, 0xd0, 0xc9, 0x4f, 0x7a, 0x8c, 0xe3, 0xf1, 0x98, - 0xb5, 0x02, 0x9c, 0xf1, 0x19, 0x33, 0x98, 0x60, 0x7e, 0xeb, 0x8e, 0x8e, 0x3b, 0x49, 0x7a, 0xdc, 0x09, 0x70, 0xf6, - 0xf6, 0x99, 0x9e, 0x4d, 0x0b, 0x66, 0xef, 0xb6, 0x9c, 0xc3, 0x9a, 0x19, 0x7d, 0x03, 0x83, 0x84, 0x95, 0x86, 0xca, - 0xef, 0x3d, 0x7a, 0x78, 0x7a, 0x9a, 0xa4, 0x30, 0xd0, 0xf7, 0xd0, 0x2d, 0x80, 0xf1, 0xbd, 0xd9, 0x7c, 0x23, 0xda, - 0xed, 0xc2, 0x74, 0xdf, 0xcf, 0x17, 0xc5, 0xfc, 0x55, 0x1c, 0x3c, 0x3a, 0x7e, 0xd8, 0x4a, 0x47, 0x01, 0x7e, 0x6f, - 0x27, 0x78, 0x9c, 0x8c, 0x8e, 0x1f, 0xb6, 0x03, 0xfc, 0x5e, 0xef, 0xb7, 0x87, 0xa3, 0xd3, 0x33, 0x38, 0x37, 0xde, - 0xcb, 0x79, 0xf1, 0x76, 0xa2, 0x0b, 0x8c, 0xe9, 0x23, 0x68, 0xf6, 0x37, 0xbd, 0x1b, 0xd3, 0x36, 0x6c, 0xe4, 0xf7, - 0x7a, 0x93, 0x69, 0x3c, 0x79, 0xd8, 0xee, 0x9e, 0x75, 0x03, 0x3c, 0xe3, 0x69, 0x0e, 0x04, 0x5e, 0x6f, 0x94, 0x47, - 0xed, 0x47, 0x0f, 0x5b, 0x01, 0x9e, 0xbd, 0x55, 0xc9, 0x47, 0x3a, 0xd3, 0xd4, 0x78, 0x0c, 0x30, 0x9b, 0x71, 0xa9, - 0xee, 0xdf, 0x48, 0x4b, 0x8f, 0x59, 0x3b, 0xc0, 0x33, 0x91, 0x24, 0x54, 0xbe, 0x35, 0x09, 0xa3, 0x6e, 0x80, 0x73, - 0xfa, 0x95, 0xfe, 0x25, 0xdc, 0x66, 0x4a, 0x19, 0x4d, 0x75, 0x9a, 0xc6, 0xe1, 0x00, 0xbf, 0x4b, 0xe1, 0x16, 0x2e, - 0x0e, 0xc6, 0xe9, 0xb8, 0x0b, 0xe0, 0x01, 0x02, 0x64, 0xb0, 0x1b, 0xa0, 0x01, 0x5f, 0xe9, 0xe3, 0x51, 0x1c, 0x9c, - 0x8e, 0xce, 0x58, 0xe7, 0x38, 0xc0, 0x25, 0x35, 0xa2, 0x5d, 0xc8, 0xd7, 0x9f, 0x1f, 0xf5, 0x96, 0x3a, 0x31, 0x09, - 0x1a, 0x40, 0x29, 0x7d, 0xd8, 0x4a, 0x4f, 0x03, 0x3c, 0x7f, 0xcd, 0xdc, 0x1e, 0x63, 0x8c, 0x9d, 0x01, 0x2c, 0x21, - 0x49, 0x23, 0xd0, 0xd9, 0x78, 0xf4, 0xe8, 0x4c, 0x7f, 0x03, 0x18, 0xe8, 0x98, 0x31, 0x00, 0xd2, 0xfc, 0x35, 0x2b, - 0x01, 0x91, 0x8e, 0x1e, 0xb6, 0x80, 0xbe, 0xcc, 0xe9, 0x9c, 0xde, 0xd3, 0xdb, 0xa7, 0x73, 0x3d, 0xa7, 0x71, 0xda, - 0x0d, 0xf0, 0xfc, 0xf9, 0x2f, 0xf3, 0xc5, 0x78, 0xac, 0x27, 0x44, 0x47, 0x8f, 0x02, 0x3c, 0x67, 0xc5, 0x02, 0xd6, - 0xe8, 0xac, 0x7b, 0x3c, 0x0e, 0xb0, 0x45, 0xc3, 0xa4, 0x95, 0x8c, 0xe0, 0x9a, 0x71, 0x31, 0x8b, 0x83, 0x34, 0xa5, - 0xad, 0x14, 0x2e, 0x1d, 0xc5, 0xed, 0xaf, 0x85, 0x41, 0x23, 0xa6, 0xf1, 0xc1, 0xae, 0x21, 0xcc, 0x17, 0xe0, 0xf1, - 0x71, 0xc4, 0x92, 0x84, 0xda, 0xc4, 0xd3, 0xd3, 0xe3, 0x63, 0xc0, 0x3d, 0x33, 0x43, 0x83, 0x20, 0x6f, 0xe4, 0xfd, - 0xa8, 0x10, 0x70, 0x74, 0x01, 0x51, 0x05, 0xb2, 0xfa, 0xe6, 0xfe, 0xb5, 0xa6, 0xab, 0xed, 0xd3, 0x47, 0xb0, 0x00, - 0x92, 0xa6, 0xe9, 0x2b, 0x73, 0xb8, 0x9d, 0x8d, 0x4e, 0xba, 0xed, 0xe3, 0x00, 0xbb, 0x8d, 0x40, 0xcf, 0x5a, 0x0f, - 0x3b, 0x50, 0x22, 0x4f, 0xef, 0x4d, 0x89, 0xf1, 0x09, 0x3d, 0x39, 0x6d, 0x05, 0xd8, 0x6d, 0x0d, 0x76, 0x36, 0xea, - 0x3e, 0x84, 0x4f, 0x39, 0x65, 0x59, 0xa6, 0xf1, 0xbb, 0x0b, 0x70, 0x91, 0xfc, 0x59, 0x4e, 0xe3, 0x80, 0xb6, 0xba, - 0x9d, 0x4e, 0x0a, 0x9f, 0xd9, 0x57, 0x56, 0xc4, 0x41, 0xd2, 0x82, 0xff, 0x02, 0xec, 0xed, 0x24, 0x36, 0x0a, 0xb0, - 0xc6, 0xbb, 0x53, 0xda, 0xd5, 0x7b, 0xdf, 0xee, 0xaa, 0xd6, 0x59, 0x0b, 0x36, 0xac, 0xdd, 0x54, 0xf6, 0x4b, 0xe6, - 0xe2, 0xd6, 0x92, 0x58, 0x1a, 0x60, 0x0f, 0x41, 0xc7, 0x0f, 0xc7, 0x01, 0x76, 0x3b, 0xee, 0xe4, 0xf4, 0xac, 0x03, - 0xa4, 0x4c, 0x01, 0xa1, 0x48, 0x3b, 0xa3, 0x13, 0x20, 0x4d, 0x8a, 0xbd, 0x36, 0x78, 0x12, 0x60, 0xf5, 0x54, 0xaa, - 0x57, 0x71, 0x90, 0x9e, 0x8d, 0xc6, 0xe9, 0x59, 0x80, 0x95, 0x98, 0x51, 0x25, 0x34, 0x05, 0x3c, 0x3e, 0x79, 0x18, - 0x60, 0x8d, 0xe6, 0x2d, 0xd6, 0x4a, 0x5b, 0x01, 0xb6, 0x47, 0x09, 0x63, 0x67, 0x1d, 0x98, 0xd6, 0xcf, 0xcf, 0x15, - 0xe0, 0x72, 0xca, 0x46, 0xc7, 0x01, 0x2e, 0xe9, 0xbd, 0x26, 0x44, 0xf0, 0x25, 0x67, 0xe2, 0x8b, 0x65, 0x3d, 0x80, - 0xd4, 0xb9, 0x0d, 0x0f, 0xcb, 0xf0, 0xf2, 0xd6, 0xa0, 0x11, 0xd5, 0x5b, 0xdc, 0xbb, 0x86, 0x7d, 0x42, 0x43, 0xc7, - 0xb6, 0x73, 0xb2, 0x5c, 0xe3, 0x32, 0xba, 0xe9, 0x17, 0x76, 0x2f, 0xc3, 0x1c, 0x4c, 0xe2, 0x6b, 0x29, 0x32, 0x47, - 0xce, 0x9e, 0xdf, 0xba, 0x6c, 0x82, 0x20, 0x29, 0x49, 0xab, 0x27, 0xcf, 0x9d, 0x1b, 0x69, 0x4f, 0x42, 0xcc, 0x03, - 0x48, 0x2f, 0x08, 0x25, 0x0a, 0x42, 0xc3, 0x18, 0x61, 0xd2, 0x59, 0xd7, 0x6b, 0x99, 0x52, 0x18, 0x7b, 0x7d, 0x4a, - 0xa8, 0x0b, 0x0a, 0x0f, 0x77, 0xc4, 0xf9, 0x40, 0x0c, 0x51, 0x4f, 0x10, 0x1d, 0xe2, 0xf9, 0x45, 0xae, 0xc2, 0x3c, - 0x1f, 0x14, 0x43, 0xdc, 0x3e, 0x45, 0x18, 0x82, 0x27, 0x90, 0x81, 0xb8, 0xb8, 0x68, 0x9f, 0x1e, 0x68, 0xa1, 0xef, - 0xe2, 0xe2, 0xcc, 0xfc, 0x80, 0x7f, 0x87, 0x55, 0xc0, 0x6a, 0x18, 0xdf, 0x63, 0xe6, 0x69, 0xf4, 0x34, 0x7f, 0xfd, - 0x98, 0xad, 0x56, 0xe1, 0x63, 0x46, 0x60, 0xc6, 0xf8, 0x31, 0x8b, 0xf4, 0xa5, 0x85, 0x71, 0x8d, 0x21, 0x03, 0xd0, - 0x9c, 0xb5, 0x30, 0x84, 0x51, 0x77, 0x9c, 0xf7, 0x63, 0x36, 0xe0, 0x75, 0xb7, 0xea, 0x2a, 0x76, 0xf1, 0xc1, 0xc1, - 0xb2, 0x88, 0x95, 0x11, 0x13, 0x94, 0x11, 0x13, 0x94, 0x11, 0x13, 0x54, 0x15, 0x3d, 0xfe, 0xa4, 0x0f, 0x52, 0x8a, - 0x56, 0xb6, 0x58, 0x9e, 0xfa, 0x1d, 0xa8, 0x3d, 0x40, 0x3b, 0xd9, 0xaf, 0x94, 0x1d, 0xa5, 0xae, 0x62, 0xa7, 0x02, - 0x63, 0x67, 0xa2, 0xd5, 0x76, 0x1c, 0xfd, 0x3b, 0xea, 0x8e, 0x97, 0x35, 0xb1, 0xec, 0xdd, 0x4e, 0xb1, 0x0c, 0x56, - 0x52, 0x8b, 0x66, 0xfb, 0x26, 0x10, 0x87, 0x1a, 0x3c, 0xd4, 0x82, 0x59, 0x15, 0x1d, 0xae, 0x01, 0x49, 0x3d, 0x90, - 0x42, 0xce, 0xb4, 0x94, 0x56, 0xa0, 0x38, 0x55, 0x61, 0x01, 0x1a, 0x4a, 0xa7, 0xa0, 0x2c, 0x83, 0x98, 0x36, 0x34, - 0x40, 0x72, 0x23, 0xa3, 0x19, 0x59, 0xad, 0x0b, 0xa2, 0x0b, 0x68, 0xc2, 0xb4, 0xc4, 0x02, 0x0d, 0x48, 0xdd, 0x80, - 0xb4, 0x95, 0x41, 0x9c, 0xb1, 0xd9, 0x27, 0x3a, 0x3b, 0xd7, 0xd9, 0x79, 0x99, 0x2d, 0x5c, 0xb6, 0x11, 0x12, 0x85, - 0xce, 0x16, 0x65, 0x36, 0xc8, 0x6c, 0x78, 0x12, 0xe7, 0x78, 0x14, 0x0b, 0x23, 0xaa, 0x55, 0xb2, 0xd5, 0x5b, 0xea, - 0x6b, 0x73, 0x0f, 0x0e, 0xc2, 0x52, 0x4e, 0xd2, 0x6a, 0xe2, 0x07, 0x4b, 0x1e, 0x15, 0x5a, 0x06, 0xe2, 0xd1, 0xc4, - 0xfe, 0x1d, 0xad, 0x37, 0x65, 0xa5, 0x62, 0x32, 0xfa, 0x46, 0x49, 0xf4, 0xd9, 0x29, 0x51, 0x1f, 0x73, 0x1d, 0xfe, - 0xe6, 0x9c, 0x44, 0xad, 0xd6, 0x71, 0xfb, 0xb8, 0x75, 0xd6, 0xe7, 0x87, 0xed, 0x4e, 0xf4, 0xa8, 0x13, 0x6b, 0x45, - 0xc4, 0x5c, 0xdc, 0x82, 0x02, 0xe6, 0xa8, 0x13, 0x9d, 0xa0, 0xc3, 0x76, 0xd4, 0xea, 0x76, 0x9b, 0xf0, 0x0f, 0x7e, - 0xaf, 0xca, 0x6a, 0x27, 0xad, 0x93, 0x6e, 0x9f, 0x1f, 0x6d, 0x54, 0x0a, 0x79, 0x03, 0x0a, 0xa2, 0x23, 0x5d, 0x09, - 0x43, 0xfd, 0x6a, 0x79, 0x9f, 0x6d, 0xe9, 0x79, 0xde, 0xab, 0x30, 0x37, 0xaa, 0x38, 0x80, 0xaa, 0xfb, 0x9a, 0x68, - 0x20, 0xba, 0xaf, 0x51, 0x19, 0xa2, 0x76, 0x59, 0x80, 0xa8, 0xfd, 0x98, 0x87, 0xb2, 0xc1, 0x0e, 0x43, 0x93, 0xaf, - 0xa0, 0x6e, 0x13, 0xc2, 0xc6, 0xe1, 0x89, 0xcd, 0xcd, 0xfd, 0xdc, 0x09, 0x42, 0xcd, 0x1c, 0x72, 0x47, 0x36, 0x57, - 0xf8, 0xb9, 0x23, 0x84, 0x9a, 0x02, 0x72, 0x69, 0xcc, 0x23, 0x0a, 0x39, 0x2a, 0xa2, 0x4d, 0x0d, 0xc9, 0x6a, 0x51, - 0x9e, 0x33, 0x37, 0x6c, 0x3e, 0x86, 0xe5, 0xd1, 0x04, 0xc5, 0x0a, 0xd2, 0x10, 0x35, 0xaf, 0xd2, 0xe6, 0xb4, 0x70, - 0xa9, 0xc6, 0x81, 0x8c, 0x06, 0xfc, 0x73, 0xc8, 0xf4, 0x7b, 0x13, 0xad, 0xfe, 0xf1, 0x69, 0x2b, 0x6e, 0x83, 0x8f, - 0x34, 0xc8, 0xda, 0xd2, 0xc8, 0xda, 0xd2, 0xc9, 0xda, 0xd2, 0xc9, 0xda, 0x20, 0xc0, 0x7b, 0x7d, 0xff, 0x2d, 0x6a, - 0x76, 0x27, 0xbc, 0x34, 0x62, 0x31, 0x56, 0x0a, 0xa1, 0x5a, 0xad, 0x96, 0x6b, 0x30, 0x31, 0x2a, 0x6b, 0x88, 0xbc, - 0x52, 0x7f, 0x2e, 0x8b, 0xb8, 0x85, 0x27, 0x31, 0x68, 0xb9, 0x5b, 0x98, 0xea, 0xcd, 0xed, 0xa8, 0xc2, 0x66, 0xf8, - 0x9a, 0xbe, 0x53, 0x27, 0x5f, 0x90, 0x63, 0xad, 0x3d, 0x5e, 0x16, 0x31, 0x37, 0x34, 0x83, 0x1b, 0x9a, 0xc1, 0x0d, - 0xcd, 0x80, 0x46, 0x70, 0x59, 0x58, 0x97, 0x8d, 0x28, 0x81, 0x2b, 0x81, 0xc1, 0xf1, 0x10, 0xa2, 0xf7, 0x85, 0x8a, - 0xe8, 0x51, 0x6f, 0x74, 0xde, 0x86, 0x68, 0x65, 0xa6, 0xa4, 0x8a, 0xa8, 0x76, 0xda, 0x2e, 0xc7, 0xfc, 0xaa, 0x86, - 0xf6, 0x11, 0x3c, 0x25, 0x73, 0xa9, 0xc2, 0x16, 0xd8, 0x6c, 0x04, 0x45, 0xd0, 0xd7, 0x64, 0x21, 0xd6, 0x3a, 0x1b, - 0x6b, 0x8b, 0xfd, 0x65, 0xc3, 0x05, 0xd6, 0x50, 0x02, 0xff, 0x01, 0x85, 0x2f, 0xac, 0xf2, 0xc9, 0x2f, 0x4d, 0x4d, - 0xad, 0x9d, 0x98, 0x39, 0x12, 0x7a, 0x60, 0x2f, 0xee, 0x82, 0x3d, 0xf5, 0x25, 0x11, 0xb9, 0xf6, 0x56, 0x24, 0x55, - 0xb8, 0x62, 0xf0, 0xde, 0x25, 0x77, 0x54, 0xfb, 0xb2, 0xbc, 0x30, 0x7f, 0x5e, 0x51, 0xcf, 0xd9, 0xaf, 0x98, 0x8c, - 0x9c, 0x8f, 0xec, 0x8d, 0x0e, 0xea, 0x43, 0xf6, 0xf7, 0x8d, 0x29, 0xb7, 0xfe, 0xda, 0xb4, 0xe5, 0xd6, 0x89, 0x3a, - 0x1b, 0x76, 0xa8, 0x5b, 0xa3, 0xbf, 0x9d, 0xab, 0x5a, 0x31, 0x19, 0x21, 0x8f, 0x66, 0x6b, 0xb0, 0xe6, 0x15, 0xb0, - 0xa4, 0xad, 0x57, 0x7a, 0x30, 0x42, 0xef, 0x7a, 0xcc, 0xeb, 0x62, 0x32, 0xda, 0xf9, 0xe6, 0x88, 0xe9, 0xb1, 0xff, - 0x96, 0x7a, 0x3d, 0x38, 0xd5, 0xf6, 0x94, 0xdd, 0x7d, 0xaf, 0xce, 0xed, 0xce, 0x3a, 0x32, 0xfb, 0x5e, 0x9d, 0xa7, - 0xbb, 0xea, 0xcc, 0xf8, 0x5d, 0xe8, 0xf6, 0x8e, 0xf2, 0xd4, 0xd8, 0xda, 0x3e, 0x68, 0x32, 0x82, 0x20, 0xf1, 0xf0, - 0xd7, 0x84, 0x72, 0xe9, 0x39, 0x12, 0x0e, 0xab, 0x20, 0xfa, 0x51, 0x37, 0x66, 0x98, 0x92, 0xce, 0x61, 0xa1, 0x83, - 0xb9, 0xc8, 0x88, 0x36, 0xf3, 0x88, 0xe2, 0x8c, 0x84, 0x21, 0x3d, 0x4c, 0x20, 0x24, 0x4d, 0xbb, 0x4f, 0xe3, 0x90, - 0x36, 0x12, 0x74, 0x14, 0xb6, 0x1b, 0xf4, 0x30, 0x41, 0xa8, 0xd1, 0x06, 0x9d, 0xa9, 0x20, 0xed, 0x66, 0x06, 0x41, - 0x2a, 0x35, 0x29, 0xce, 0x0e, 0x65, 0x54, 0x34, 0xc4, 0x61, 0x1e, 0x15, 0x8d, 0xa8, 0x8b, 0x65, 0x34, 0x29, 0x93, - 0x27, 0x3a, 0x79, 0x62, 0x92, 0x47, 0x65, 0xf2, 0x48, 0x27, 0x8f, 0x4c, 0x32, 0x25, 0xc5, 0xa1, 0x8c, 0x68, 0x23, - 0x6c, 0x37, 0x0b, 0x74, 0x08, 0x23, 0x70, 0xa3, 0x27, 0xd2, 0x8f, 0x0d, 0xbe, 0xd6, 0xc6, 0x35, 0x73, 0x91, 0xd9, - 0x68, 0x9d, 0x15, 0x90, 0x4a, 0x8f, 0x27, 0xa8, 0xf3, 0xcc, 0x03, 0x13, 0x56, 0xe6, 0x8f, 0x8b, 0x45, 0xb7, 0x4e, - 0x32, 0x91, 0x7b, 0x1e, 0x5d, 0x60, 0x84, 0xfe, 0xc5, 0xfa, 0xb1, 0x00, 0x54, 0xd7, 0x34, 0x9b, 0x4f, 0xe9, 0x96, - 0xdb, 0x6c, 0x31, 0x19, 0xd9, 0x9d, 0x55, 0x36, 0xc3, 0x68, 0x61, 0x62, 0x3c, 0xd7, 0x1d, 0x1c, 0x01, 0xd4, 0xce, - 0xa9, 0x32, 0xa2, 0x5a, 0x49, 0x6e, 0x6a, 0x4c, 0x0a, 0x76, 0x2f, 0x13, 0x9a, 0xb1, 0xb0, 0x3a, 0x80, 0xab, 0x61, - 0x32, 0xf2, 0x02, 0x4c, 0xe1, 0x8b, 0xc3, 0xe8, 0xb8, 0xa1, 0xa2, 0xc9, 0x61, 0xd4, 0x7d, 0xd4, 0x50, 0xd1, 0xe8, - 0x30, 0x6a, 0xb7, 0x2b, 0x9c, 0x8d, 0x0a, 0xa2, 0xa2, 0x09, 0x51, 0xa0, 0x31, 0x34, 0x8d, 0x8a, 0x39, 0x05, 0xdb, - 0xae, 0x7f, 0x63, 0x18, 0x0d, 0x3b, 0x8c, 0x9c, 0x4d, 0x4c, 0xb8, 0xcb, 0xad, 0x31, 0xf8, 0xdd, 0x74, 0xba, 0xdd, - 0xa6, 0x8a, 0x0a, 0xac, 0xcc, 0x4a, 0x36, 0x55, 0x34, 0xc1, 0xca, 0x2c, 0x5f, 0x53, 0x45, 0x23, 0xd3, 0x94, 0xd6, - 0x01, 0x82, 0xde, 0xb1, 0x04, 0xd6, 0x73, 0xe6, 0x41, 0xbe, 0xe3, 0xbc, 0x53, 0xd6, 0xa0, 0x35, 0xfc, 0x5e, 0xb9, - 0xa6, 0x2b, 0x28, 0xa9, 0x02, 0x1b, 0x1f, 0xf6, 0xad, 0xa2, 0xed, 0xaa, 0x49, 0xf6, 0xaf, 0xcb, 0x96, 0xcd, 0x16, - 0x42, 0xd5, 0x0b, 0x5e, 0xd6, 0x30, 0xc4, 0x96, 0xb2, 0x07, 0xf7, 0x3f, 0x94, 0x84, 0x10, 0xd4, 0x4e, 0x9f, 0x42, - 0x9c, 0x38, 0x3d, 0x32, 0x24, 0xf1, 0x46, 0x63, 0x8d, 0x42, 0xef, 0xbc, 0x7d, 0xea, 0x53, 0xd5, 0xad, 0x48, 0x77, - 0x84, 0x04, 0x8b, 0xdc, 0xd8, 0x42, 0xa6, 0x81, 0xc7, 0x82, 0x58, 0xed, 0x6e, 0xed, 0x80, 0x38, 0x38, 0xd8, 0x3c, - 0x2f, 0xdc, 0x9b, 0x03, 0x5b, 0xef, 0x0c, 0x54, 0x86, 0x74, 0xee, 0x25, 0x24, 0x63, 0x62, 0xcb, 0x3d, 0x44, 0x71, - 0x31, 0xa7, 0x1e, 0x6a, 0x0a, 0x3f, 0xa8, 0x02, 0xee, 0xd9, 0x9c, 0xe6, 0xa9, 0xce, 0xd0, 0x7d, 0x0d, 0xbd, 0xb1, - 0xbd, 0xf1, 0x27, 0x54, 0x1a, 0x09, 0xfe, 0xcb, 0x8e, 0xbd, 0x4e, 0xec, 0x4b, 0x2d, 0x7e, 0xa3, 0x7f, 0xf9, 0x26, - 0xb9, 0x15, 0x6c, 0xac, 0x33, 0xf6, 0x6a, 0x55, 0x7b, 0x97, 0xc7, 0xbc, 0xfe, 0x82, 0x0e, 0x0e, 0xb8, 0x7c, 0x06, - 0x56, 0xc4, 0x2c, 0x6c, 0xf8, 0x87, 0xef, 0xdf, 0xb5, 0xd3, 0xfa, 0x2f, 0x7d, 0xae, 0xc6, 0xde, 0x41, 0x77, 0x59, - 0xcb, 0xdf, 0xb9, 0x12, 0x7d, 0x15, 0x73, 0xbb, 0xd6, 0x7f, 0x55, 0x36, 0xda, 0x5b, 0x2f, 0x44, 0x1d, 0x1c, 0xf0, - 0x2a, 0x4e, 0x53, 0xf0, 0x43, 0x80, 0xfa, 0x5a, 0x06, 0x79, 0x96, 0x09, 0x0a, 0x37, 0xa2, 0x70, 0xc5, 0x10, 0x37, - 0xf8, 0x91, 0xc2, 0x7f, 0x88, 0xff, 0x4f, 0x8d, 0x1c, 0xaa, 0xb8, 0xc1, 0x3d, 0x01, 0xcc, 0x67, 0x85, 0xaa, 0x08, - 0x89, 0x1a, 0xd2, 0xbe, 0xc9, 0x35, 0x2a, 0x0f, 0x73, 0x3a, 0x9f, 0x67, 0xf7, 0xfa, 0x91, 0x2c, 0x8f, 0xa3, 0xaa, - 0x2e, 0x9a, 0x6c, 0x78, 0x3a, 0x5c, 0x00, 0x4f, 0x0f, 0xb8, 0x87, 0xb4, 0x7b, 0x69, 0x79, 0xb9, 0x2d, 0x11, 0x48, - 0x66, 0x39, 0x11, 0xcd, 0x76, 0x2f, 0xbf, 0x00, 0xb9, 0xac, 0xd9, 0x44, 0xca, 0x46, 0xed, 0xc6, 0x1c, 0x64, 0xb2, - 0xdc, 0xb8, 0x90, 0xee, 0x99, 0x82, 0x20, 0xb9, 0x09, 0x2d, 0xb2, 0xed, 0x2e, 0xc5, 0xc7, 0x21, 0xa0, 0x11, 0x32, - 0x02, 0x9f, 0x2f, 0x2c, 0x72, 0xe0, 0x3a, 0x0b, 0xd7, 0xf1, 0x37, 0x5a, 0x2a, 0x06, 0xf9, 0x70, 0x88, 0x0b, 0xfd, - 0x2e, 0x44, 0x39, 0x1f, 0xb8, 0x69, 0x2a, 0xdf, 0x19, 0xf2, 0x44, 0x14, 0xbe, 0x5a, 0xed, 0xc3, 0x33, 0x3e, 0xb6, - 0x4d, 0xf0, 0x39, 0xb5, 0x3f, 0xab, 0x27, 0x3b, 0x60, 0x1c, 0x8c, 0xb4, 0xf4, 0x45, 0xa1, 0x95, 0x37, 0xd9, 0xb9, - 0xec, 0x35, 0x1a, 0x4c, 0x47, 0x58, 0x22, 0x10, 0x4e, 0x0d, 0x1c, 0x02, 0xe1, 0x8f, 0x09, 0x9a, 0x24, 0x99, 0x09, - 0x3d, 0x07, 0x31, 0xb1, 0x6b, 0x09, 0xab, 0x55, 0x6e, 0x42, 0x9b, 0xe8, 0x1c, 0x13, 0xe4, 0xa4, 0xec, 0xa7, 0x8c, - 0xa1, 0x5a, 0x99, 0x71, 0x70, 0xbb, 0xd5, 0xdf, 0x56, 0xfb, 0x79, 0x8f, 0x9b, 0x6b, 0x3c, 0xae, 0x03, 0x06, 0x68, - 0x40, 0x2d, 0x37, 0x36, 0xb8, 0x31, 0x70, 0x0f, 0x8d, 0x35, 0x2e, 0xdb, 0x84, 0xa0, 0x2c, 0x1d, 0xe4, 0xcd, 0xcd, - 0xad, 0x0b, 0x18, 0x98, 0xeb, 0x39, 0xe5, 0x48, 0x0d, 0x40, 0x8e, 0x1e, 0x12, 0xe8, 0xdc, 0xfc, 0xac, 0xe8, 0x42, - 0x25, 0x13, 0x97, 0x63, 0xfc, 0xc5, 0xbb, 0xcd, 0x1b, 0x04, 0x37, 0x37, 0x7a, 0x93, 0xdf, 0xdc, 0x04, 0xd8, 0xb7, - 0x2a, 0x0f, 0x3c, 0x5e, 0x30, 0x18, 0x96, 0x31, 0xa5, 0xf4, 0xc6, 0x6f, 0xb6, 0xab, 0xc6, 0xde, 0xd3, 0x0a, 0xef, - 0x60, 0x79, 0x74, 0xe3, 0x5b, 0x5e, 0x98, 0x03, 0x0e, 0xf0, 0x66, 0x03, 0x3e, 0xec, 0xbd, 0x09, 0x73, 0x74, 0x70, - 0xf0, 0x26, 0x14, 0xa8, 0x7f, 0xcd, 0xf4, 0x9d, 0x1b, 0xb8, 0x61, 0x0f, 0xb8, 0x1e, 0xbe, 0xf0, 0x10, 0xe0, 0x9a, - 0x6d, 0x4a, 0x36, 0x6f, 0x75, 0xd0, 0x8b, 0x18, 0x82, 0x6a, 0x43, 0x68, 0x5f, 0x0b, 0x12, 0xe8, 0xf5, 0x8d, 0x0f, - 0xed, 0x1e, 0x23, 0x0c, 0x58, 0xf8, 0xd2, 0x49, 0x8e, 0x45, 0x33, 0x56, 0x4c, 0x58, 0xb1, 0x5a, 0xbd, 0xa7, 0xc6, - 0xf1, 0x6d, 0x23, 0x46, 0x63, 0xde, 0x6b, 0x34, 0xa8, 0x1e, 0x3f, 0x88, 0x0f, 0x74, 0x88, 0xf7, 0xdf, 0x84, 0x05, - 0x42, 0x60, 0x61, 0xc4, 0xf3, 0x85, 0x73, 0xf2, 0x4a, 0x6a, 0xeb, 0x52, 0xa0, 0xb2, 0x91, 0x8c, 0xb4, 0xf0, 0x94, - 0x24, 0xe5, 0x1a, 0x9d, 0x4f, 0x7b, 0x8d, 0x46, 0x86, 0x44, 0x98, 0x0c, 0xb2, 0x21, 0xe6, 0xb8, 0x80, 0xcb, 0xd4, - 0xed, 0x75, 0x98, 0xb3, 0x1a, 0xe5, 0xb2, 0xf3, 0x5d, 0x9a, 0xb1, 0xc6, 0x8f, 0xe9, 0xda, 0x03, 0xc6, 0x63, 0xea, - 0x11, 0x89, 0x5d, 0x40, 0x96, 0x06, 0xc8, 0xb9, 0x03, 0xb2, 0xd4, 0x40, 0xce, 0x51, 0x7f, 0x0e, 0xd1, 0x8a, 0x72, - 0x14, 0x6f, 0x51, 0xf4, 0x7a, 0x5c, 0x4d, 0xeb, 0xb3, 0x81, 0xb9, 0x0e, 0xed, 0x60, 0x97, 0x03, 0x1e, 0x3a, 0xb1, - 0x6e, 0x80, 0x39, 0x59, 0x06, 0x81, 0x0e, 0x31, 0x8b, 0xef, 0xf4, 0x9f, 0xe8, 0x0e, 0xdf, 0x9b, 0x1f, 0xf7, 0x9e, - 0x32, 0xe9, 0x79, 0x4d, 0xdb, 0xc0, 0x6d, 0x40, 0xb6, 0x20, 0x0a, 0x00, 0xad, 0x6d, 0x74, 0x41, 0x59, 0x7f, 0x70, - 0x2d, 0x37, 0x71, 0x20, 0x64, 0x83, 0xe4, 0x58, 0x7a, 0xa4, 0xf3, 0xcf, 0x3f, 0x03, 0xd4, 0x97, 0x10, 0xc6, 0xc7, - 0x9e, 0x6c, 0xcd, 0x36, 0x6a, 0x04, 0x51, 0x10, 0x87, 0x2e, 0x4a, 0x04, 0xec, 0x8c, 0x20, 0xf0, 0x1e, 0x5b, 0x29, - 0x87, 0xf1, 0xa1, 0x36, 0x0c, 0x3d, 0xa8, 0x2a, 0xee, 0xc5, 0xc5, 0x72, 0x33, 0xca, 0x90, 0x86, 0xaa, 0xd4, 0x21, - 0x5e, 0x90, 0x79, 0x81, 0x8c, 0x11, 0x76, 0x70, 0xc0, 0x06, 0x72, 0xe8, 0x3d, 0x29, 0x56, 0x5d, 0x87, 0x2b, 0x7f, - 0xe1, 0x42, 0x9a, 0x0f, 0xd4, 0x70, 0xb5, 0x32, 0x7f, 0xc9, 0x07, 0x2d, 0xcd, 0xc0, 0xdb, 0x70, 0xde, 0x6d, 0xbc, - 0xdc, 0x2d, 0x8b, 0x45, 0x4a, 0xfc, 0x0e, 0x56, 0x83, 0x2e, 0x68, 0x9f, 0x9d, 0x6a, 0xdb, 0x41, 0x7d, 0xae, 0x35, - 0x0a, 0x5e, 0xc8, 0xdc, 0xea, 0x48, 0xc3, 0x73, 0xe5, 0xe7, 0xd5, 0x42, 0xdf, 0x26, 0x79, 0x19, 0xc1, 0x14, 0x8e, - 0x94, 0x08, 0xcc, 0xc6, 0x35, 0x9d, 0x84, 0x1f, 0x75, 0x2a, 0x69, 0x59, 0x48, 0x80, 0x02, 0x47, 0xfa, 0x72, 0x5e, - 0x47, 0xa8, 0x67, 0x68, 0x07, 0x91, 0xf3, 0x4c, 0x68, 0xea, 0xb2, 0xa5, 0x0d, 0x25, 0x15, 0xcc, 0xc4, 0x42, 0xb2, - 0xc5, 0x1c, 0xce, 0xf7, 0x32, 0x2d, 0xc9, 0x78, 0xf2, 0xa5, 0x9e, 0x02, 0xe6, 0x9f, 0x77, 0x6a, 0xc6, 0xf2, 0x45, - 0x60, 0xe7, 0xf9, 0xca, 0x88, 0xfb, 0x6f, 0x5e, 0xe0, 0xc7, 0xa4, 0x73, 0xf8, 0x0a, 0x7f, 0xa4, 0xe4, 0x71, 0xe3, - 0x15, 0x9e, 0x70, 0x62, 0x78, 0x83, 0xe8, 0xcd, 0xeb, 0xeb, 0x17, 0xef, 0x5e, 0xbc, 0x7f, 0x7a, 0xf3, 0xe2, 0xd5, - 0xb3, 0x17, 0xaf, 0x5e, 0xbc, 0xfb, 0x88, 0xff, 0xa6, 0xe4, 0xd5, 0x51, 0xfb, 0xac, 0x85, 0x3f, 0x90, 0x57, 0x47, - 0x1d, 0x7c, 0xa7, 0xc8, 0xab, 0xa3, 0x13, 0x9c, 0xe5, 0xe4, 0xd5, 0x61, 0xe7, 0xe8, 0x18, 0x2f, 0x94, 0x69, 0x32, - 0x13, 0x93, 0x76, 0x0b, 0xff, 0x6d, 0xbf, 0x40, 0xbc, 0xaf, 0x66, 0x31, 0x61, 0x9b, 0xc6, 0x0f, 0x50, 0x86, 0x8e, - 0xa4, 0x36, 0x44, 0x39, 0xf7, 0xd0, 0x69, 0x9a, 0xfb, 0xe8, 0x64, 0x62, 0x28, 0x83, 0x0d, 0x23, 0xa0, 0x15, 0x27, - 0xb6, 0x1d, 0x7e, 0xd4, 0x66, 0xc7, 0x40, 0x9f, 0x78, 0x29, 0x1c, 0x97, 0x2a, 0x9c, 0xb6, 0xd5, 0x62, 0x8c, 0x33, - 0x21, 0x8a, 0x70, 0x01, 0x8c, 0x80, 0xd6, 0x5a, 0xf0, 0xa3, 0x32, 0x58, 0x93, 0x3c, 0x27, 0xed, 0x7e, 0x3b, 0x96, - 0xe7, 0xa4, 0xd3, 0xef, 0xc0, 0x9f, 0x6e, 0xbf, 0x1b, 0xb7, 0x5b, 0xe8, 0xd0, 0x1b, 0xc7, 0x1f, 0x35, 0xb4, 0x1e, - 0x0c, 0xb1, 0xed, 0x42, 0xfe, 0x5d, 0x28, 0xa7, 0xd2, 0x93, 0x56, 0x1d, 0xdb, 0xee, 0xc9, 0x73, 0xa6, 0xf5, 0xb0, - 0xfc, 0x07, 0x40, 0x6d, 0xed, 0x4f, 0x52, 0x6e, 0x1c, 0xfb, 0x8b, 0x1f, 0x49, 0x54, 0x8b, 0x08, 0x13, 0xb2, 0x55, - 0x0b, 0x01, 0xd3, 0xa8, 0xb3, 0xc1, 0x1c, 0x28, 0x92, 0xa2, 0x50, 0x2e, 0xaa, 0x7d, 0xde, 0x14, 0x28, 0x9a, 0x8b, - 0x79, 0x58, 0x53, 0x35, 0xfc, 0xea, 0x99, 0x39, 0xee, 0x73, 0xf9, 0x8a, 0xbe, 0x0a, 0x6b, 0x3c, 0x8f, 0xcf, 0xda, - 0xf9, 0xdb, 0xe2, 0x17, 0x6b, 0x45, 0x51, 0x03, 0x57, 0x09, 0x58, 0x37, 0xaa, 0xa6, 0x3a, 0x87, 0xe7, 0xfb, 0x58, - 0x43, 0x5d, 0x10, 0x8f, 0x7a, 0xfe, 0x54, 0x9a, 0x71, 0x95, 0xca, 0x68, 0xa7, 0x88, 0xd6, 0x66, 0x41, 0x4e, 0x11, - 0x7d, 0x9e, 0x6b, 0x20, 0x08, 0xc2, 0x07, 0x72, 0x08, 0x07, 0xbe, 0x19, 0xa0, 0xd0, 0x74, 0x0e, 0xd4, 0x4a, 0x95, - 0x99, 0x90, 0xfe, 0xd4, 0xb1, 0x09, 0x40, 0xf3, 0x54, 0xa9, 0xa0, 0xf4, 0x27, 0x16, 0xc8, 0x1b, 0xfa, 0x6f, 0xfe, - 0x06, 0x38, 0x0c, 0x35, 0x2a, 0xfa, 0x76, 0x35, 0xb2, 0x9e, 0xdf, 0x3e, 0x6b, 0x1d, 0xbd, 0xf2, 0xf2, 0xd3, 0xdc, - 0xd9, 0x7b, 0xfc, 0xe5, 0x51, 0x72, 0x13, 0x4d, 0xab, 0x8d, 0x5d, 0x20, 0xb4, 0x9e, 0x0f, 0x90, 0x43, 0x85, 0x8e, - 0xf4, 0x4b, 0x86, 0x3d, 0xa4, 0x0e, 0x49, 0xbb, 0x05, 0xd1, 0xcb, 0x76, 0x50, 0xbe, 0x9f, 0x36, 0x60, 0xaa, 0xa2, - 0xbb, 0x26, 0xd0, 0x6a, 0x78, 0xdc, 0xe8, 0xbe, 0xc9, 0xa3, 0x7b, 0x9c, 0x7b, 0x38, 0xc3, 0x0e, 0x59, 0x43, 0x1e, - 0x4a, 0x64, 0xa3, 0xbe, 0x9a, 0x0d, 0xa0, 0x68, 0xde, 0x31, 0x8f, 0xec, 0x39, 0xe3, 0xa8, 0xf3, 0x66, 0xd4, 0x3d, - 0x7c, 0x75, 0x70, 0x10, 0x8a, 0x06, 0x79, 0x8c, 0xf0, 0x92, 0x82, 0x11, 0x35, 0x38, 0x9d, 0x71, 0xc3, 0xc4, 0xc7, - 0xb9, 0x47, 0x1d, 0x17, 0x79, 0xed, 0x58, 0xab, 0x3a, 0x2b, 0x77, 0x83, 0x1b, 0x53, 0x07, 0x35, 0xbc, 0x34, 0x33, - 0xba, 0x4e, 0x0d, 0xca, 0x35, 0x0f, 0x31, 0xd8, 0x96, 0x8d, 0x8f, 0x14, 0xfd, 0xf0, 0xb8, 0xf9, 0xca, 0x9b, 0x70, - 0xcd, 0x34, 0xe9, 0x71, 0xe3, 0x31, 0xfa, 0xe1, 0xb1, 0xe7, 0xe3, 0xc7, 0x2b, 0xf6, 0xc4, 0x71, 0x23, 0x3f, 0x19, - 0xae, 0xf4, 0x27, 0x90, 0xec, 0x0b, 0xf2, 0x13, 0x60, 0x39, 0x25, 0x3f, 0x85, 0xa2, 0x99, 0x83, 0x41, 0xd7, 0x4f, - 0x61, 0x01, 0x3f, 0x32, 0xf2, 0x53, 0x08, 0xd8, 0x8e, 0xa7, 0xfa, 0x47, 0x51, 0xbd, 0xae, 0x0a, 0x6a, 0x14, 0xe3, - 0x5e, 0x56, 0xac, 0x56, 0xf2, 0xe0, 0x40, 0x98, 0x5f, 0xf4, 0x22, 0x39, 0x38, 0xc8, 0xce, 0xa7, 0x9e, 0xed, 0xad, - 0xda, 0x45, 0x5f, 0x34, 0x42, 0x61, 0xcf, 0x34, 0x8d, 0xfb, 0x33, 0xfe, 0xe4, 0x53, 0x56, 0xdd, 0x40, 0xf3, 0xb8, - 0xf3, 0xf0, 0xf4, 0x0c, 0xc3, 0xbf, 0x0f, 0xbd, 0x82, 0x3f, 0x97, 0x7c, 0x17, 0x69, 0xb3, 0xe6, 0x69, 0x85, 0x6c, - 0x17, 0x1e, 0x3e, 0x63, 0x86, 0x9a, 0xf2, 0xe0, 0x80, 0x9f, 0x7b, 0xb8, 0x8c, 0x19, 0x6a, 0x78, 0x16, 0x7b, 0x0f, - 0x4a, 0x7b, 0x32, 0xcd, 0x35, 0xc1, 0xab, 0xb6, 0x7c, 0x50, 0x0c, 0xcf, 0x95, 0xa5, 0x26, 0x7e, 0xec, 0xeb, 0x9c, - 0xb4, 0xec, 0x26, 0xeb, 0xc9, 0x66, 0x7e, 0xd1, 0xee, 0x21, 0x41, 0xf2, 0x86, 0xbc, 0xb8, 0x68, 0x63, 0x50, 0xc9, - 0xf7, 0x73, 0x22, 0x62, 0x49, 0x9c, 0x7f, 0xde, 0x32, 0x13, 0x71, 0x8e, 0xa7, 0x3c, 0x2e, 0xe5, 0xec, 0xd7, 0xce, - 0x7a, 0x5a, 0x7b, 0x4c, 0xea, 0x9e, 0x19, 0x96, 0xfd, 0xbc, 0xf4, 0xf4, 0x83, 0x4d, 0x9a, 0x0f, 0xe1, 0xd1, 0xc0, - 0x12, 0xf3, 0x98, 0x71, 0x6f, 0x63, 0x10, 0x94, 0x39, 0x6f, 0xb4, 0x21, 0x13, 0x3e, 0xd7, 0x71, 0x0e, 0x03, 0xd5, - 0x85, 0xcf, 0x81, 0x4c, 0x25, 0x95, 0x61, 0xb6, 0x6b, 0x18, 0x0a, 0x48, 0x28, 0x70, 0x41, 0x98, 0x27, 0xc1, 0xc3, - 0xed, 0x87, 0x47, 0x38, 0xea, 0xe4, 0xc2, 0x4c, 0xee, 0x3c, 0x87, 0xee, 0xe4, 0xf0, 0x5c, 0xf5, 0x90, 0x6c, 0x34, - 0x2c, 0xb7, 0x7d, 0x21, 0xf5, 0x20, 0x9a, 0xed, 0xe1, 0x05, 0xeb, 0xa1, 0xbc, 0xd9, 0x2c, 0x0d, 0x20, 0x2f, 0x5a, - 0xab, 0x55, 0x7e, 0xee, 0x1a, 0xe9, 0xbb, 0x73, 0x5c, 0xf3, 0x5d, 0x4e, 0xf0, 0xfc, 0x4d, 0x90, 0x41, 0x00, 0x54, - 0x15, 0xf8, 0x6c, 0x31, 0x0f, 0x70, 0xa0, 0xdf, 0x93, 0x83, 0xbf, 0xfa, 0x1d, 0xb0, 0x00, 0x07, 0xf6, 0x89, 0xb9, - 0x60, 0x58, 0x0d, 0x96, 0x27, 0x65, 0x74, 0x74, 0x1e, 0xdd, 0x00, 0xe3, 0xa0, 0xfe, 0x02, 0x4e, 0xbb, 0xfc, 0x1d, - 0x65, 0x36, 0x4e, 0x88, 0x74, 0xaf, 0x9e, 0xd9, 0x51, 0xad, 0x77, 0x7b, 0x66, 0x72, 0x1c, 0xb8, 0xaa, 0xf0, 0x7a, - 0xc0, 0x77, 0x9e, 0x5d, 0x6c, 0xdb, 0xd7, 0xbe, 0x97, 0x65, 0x0f, 0xc0, 0x79, 0xaf, 0xd7, 0x08, 0xff, 0x26, 0x76, - 0x3e, 0xfd, 0x1b, 0xdc, 0x88, 0xfc, 0x09, 0x55, 0x34, 0x68, 0xbc, 0xd6, 0x86, 0x6f, 0x46, 0xce, 0xea, 0x7d, 0x6b, - 0x1c, 0xec, 0xdf, 0xea, 0x1e, 0x22, 0x37, 0xd4, 0x5e, 0x29, 0x32, 0xb2, 0xaf, 0x8e, 0xd7, 0x21, 0x3c, 0xd3, 0xb7, - 0x1d, 0xf0, 0x70, 0x63, 0xa4, 0xe0, 0x4f, 0x6c, 0xf8, 0x24, 0x0a, 0x21, 0x51, 0x6b, 0x5e, 0xcc, 0x90, 0x62, 0xfa, - 0xd0, 0x1e, 0xaf, 0x6b, 0xe4, 0x73, 0xdd, 0xe3, 0xbc, 0x4e, 0x4c, 0xab, 0x6e, 0xb4, 0xd4, 0xc1, 0x36, 0x59, 0x70, - 0x56, 0xf5, 0xae, 0x25, 0x94, 0xea, 0x41, 0x37, 0xfd, 0x28, 0x67, 0xb3, 0xad, 0x5f, 0x39, 0x36, 0xcf, 0xbe, 0xe5, - 0x60, 0xc8, 0xbb, 0x5f, 0x46, 0xab, 0xba, 0x80, 0x63, 0x37, 0xf4, 0x20, 0x2b, 0xc8, 0xc5, 0xd2, 0x3e, 0xc9, 0xc6, - 0x07, 0x62, 0xb8, 0x2e, 0x1f, 0x68, 0xf3, 0xf0, 0xa0, 0x1a, 0xa9, 0x4c, 0x7c, 0xce, 0xc0, 0xbd, 0x6e, 0x58, 0xd3, - 0x0f, 0xf1, 0x7f, 0xe0, 0x80, 0xaf, 0x90, 0x34, 0x36, 0xea, 0x27, 0x78, 0x38, 0x09, 0x14, 0xde, 0xa6, 0xee, 0x27, - 0xe1, 0x7b, 0xa8, 0xd6, 0x75, 0x2a, 0xc6, 0x09, 0xb4, 0xae, 0x58, 0x29, 0x0b, 0x7b, 0xc7, 0x5d, 0x88, 0xd6, 0xb1, - 0x75, 0x18, 0xb5, 0xaf, 0x2d, 0x5d, 0xe6, 0xe0, 0xff, 0xc2, 0x45, 0xfe, 0xac, 0x80, 0xf0, 0x59, 0xbe, 0x3e, 0xed, - 0x67, 0xe1, 0x3f, 0x27, 0x3c, 0x80, 0x7b, 0xc2, 0x92, 0xe7, 0x2c, 0x9f, 0xc0, 0x86, 0x05, 0xca, 0x81, 0x42, 0xe5, - 0x58, 0xae, 0x56, 0xa1, 0xd4, 0x41, 0x15, 0x6c, 0x4c, 0x5d, 0xfb, 0x78, 0x86, 0xd6, 0xdf, 0x41, 0x5d, 0xec, 0xd4, - 0x23, 0xda, 0x84, 0x15, 0xf9, 0x97, 0x4e, 0x79, 0xe2, 0xf5, 0xb5, 0xab, 0x0f, 0x59, 0x4d, 0xb9, 0x1f, 0x6a, 0x7d, - 0xef, 0x3b, 0x3e, 0x63, 0x62, 0x01, 0xaf, 0x16, 0x61, 0x46, 0x24, 0x53, 0xee, 0x1b, 0x28, 0x08, 0x84, 0x9c, 0xe3, - 0x3e, 0x3e, 0x02, 0x5f, 0xe5, 0x68, 0x9d, 0x48, 0xdc, 0x5b, 0x18, 0x81, 0x8e, 0x55, 0x19, 0xf4, 0x03, 0x70, 0x5a, - 0x02, 0x11, 0x8a, 0x90, 0x80, 0xe5, 0x69, 0xd0, 0x0f, 0xb4, 0x8f, 0x54, 0x00, 0x56, 0x63, 0xa0, 0xe4, 0x0e, 0xf0, - 0x3c, 0xaf, 0x88, 0x98, 0x5f, 0x53, 0x79, 0x95, 0x58, 0xac, 0xcd, 0xb4, 0x8f, 0x3a, 0x15, 0x08, 0x8b, 0x64, 0x53, - 0x50, 0x56, 0x1b, 0xea, 0x02, 0x2c, 0x88, 0xc6, 0x58, 0x1e, 0xdd, 0x00, 0x37, 0xc7, 0x52, 0x5b, 0x74, 0xc9, 0xaf, - 0x41, 0x3d, 0x1d, 0x17, 0xf8, 0x46, 0x33, 0x6c, 0x69, 0x4c, 0xd7, 0x84, 0xe3, 0x84, 0x14, 0x11, 0xbd, 0x83, 0xa0, - 0x12, 0x33, 0x9e, 0xc7, 0x19, 0x9e, 0xd1, 0xbb, 0x78, 0x8a, 0x67, 0x3c, 0x7f, 0x62, 0x96, 0x3d, 0x4e, 0x21, 0xc9, - 0x7d, 0x2c, 0xd6, 0x44, 0xbf, 0x89, 0xf5, 0xbb, 0x64, 0xc5, 0x63, 0xe0, 0x55, 0x64, 0x88, 0x7a, 0xa9, 0xb6, 0x29, - 0x67, 0xaa, 0x32, 0x5e, 0x7f, 0xad, 0x42, 0x8a, 0x13, 0x9c, 0xa1, 0x28, 0x13, 0x98, 0xf5, 0x65, 0xfc, 0x1a, 0x02, - 0x4a, 0x27, 0xd8, 0xbc, 0xa7, 0xc5, 0xef, 0x58, 0xf6, 0x4c, 0x14, 0xef, 0xf5, 0x96, 0xcf, 0x10, 0x14, 0x02, 0x17, - 0x15, 0xd9, 0x84, 0xdb, 0xbd, 0x45, 0x5f, 0x54, 0x4d, 0xd1, 0x3b, 0xd3, 0x94, 0x1d, 0xe2, 0x14, 0x22, 0xf1, 0x46, - 0x53, 0xde, 0x68, 0x63, 0xd6, 0x6f, 0x7d, 0xa7, 0xd1, 0x29, 0x2a, 0x4b, 0x22, 0x0c, 0x4f, 0x04, 0x37, 0xf3, 0x58, - 0x10, 0xd9, 0xcc, 0xad, 0x84, 0xb7, 0xd4, 0xc0, 0x8e, 0x73, 0x9c, 0x88, 0x45, 0xae, 0x62, 0xe1, 0xe1, 0x0d, 0xad, - 0x36, 0xd7, 0xf2, 0xce, 0x40, 0x4c, 0xe1, 0x7b, 0xf3, 0x83, 0xe1, 0x1b, 0xad, 0xe2, 0x7f, 0x0b, 0x86, 0x3d, 0x32, - 0x96, 0x00, 0x3f, 0x30, 0x9c, 0x05, 0xc8, 0x19, 0x7e, 0xf2, 0x0e, 0xc0, 0x67, 0x58, 0xc8, 0x7b, 0x48, 0x65, 0x3a, - 0xf5, 0x1e, 0x52, 0x19, 0xa4, 0x6a, 0x57, 0xf2, 0x7d, 0x59, 0x29, 0x8b, 0xfc, 0x06, 0x49, 0x8e, 0x4b, 0x75, 0xb0, - 0x20, 0x32, 0x82, 0x76, 0xb5, 0x28, 0x37, 0xe3, 0x39, 0xc4, 0x14, 0x84, 0xc6, 0xcd, 0x37, 0xbd, 0x83, 0xef, 0x7b, - 0x93, 0xcf, 0x5c, 0xfe, 0xbd, 0xc9, 0xd7, 0x1d, 0x39, 0x8c, 0xaf, 0xdf, 0x76, 0x6a, 0xcb, 0x78, 0x61, 0xb1, 0xf6, - 0x43, 0xf9, 0x82, 0x4b, 0x4b, 0xbf, 0x94, 0x4d, 0xda, 0x78, 0xe2, 0x21, 0x65, 0xb3, 0xe2, 0xe1, 0x3a, 0xb8, 0xdd, - 0x3a, 0x0c, 0x79, 0x93, 0xb4, 0x11, 0x3a, 0xb4, 0xc2, 0x55, 0x1e, 0x6a, 0xc9, 0xe9, 0xf0, 0xf1, 0x11, 0xdc, 0xbd, - 0xcc, 0xf2, 0x0d, 0x5f, 0x29, 0x53, 0xad, 0xd9, 0x6e, 0x1d, 0xf2, 0x9d, 0x55, 0x1a, 0x6d, 0x3c, 0x63, 0x64, 0x09, - 0xce, 0x65, 0xb4, 0x30, 0xaa, 0x06, 0xf0, 0x21, 0x7d, 0x91, 0xff, 0xb6, 0xa0, 0xa9, 0xfe, 0x3e, 0x34, 0x29, 0xaf, - 0x17, 0xca, 0x25, 0x35, 0x39, 0x0c, 0xa2, 0x83, 0x6c, 0x49, 0x2f, 0x27, 0xe4, 0x47, 0x24, 0xea, 0xa2, 0xf3, 0x76, - 0x3f, 0xea, 0x1e, 0xf2, 0x43, 0x1e, 0x03, 0x0f, 0x1b, 0x36, 0x5d, 0x85, 0x66, 0xdb, 0xd5, 0xb9, 0x5a, 0x8c, 0x78, - 0x62, 0x9b, 0xaf, 0x3a, 0x28, 0x53, 0xcd, 0x1c, 0x21, 0x0b, 0x50, 0xcc, 0xf5, 0xe2, 0x65, 0xd7, 0xbb, 0x39, 0xe4, - 0x31, 0xf4, 0x03, 0xb5, 0x3a, 0xa6, 0x56, 0x39, 0xb8, 0xdf, 0x16, 0x80, 0x60, 0xae, 0xa3, 0xda, 0x5c, 0x4c, 0x7a, - 0x33, 0xac, 0x3a, 0x3b, 0xe4, 0xd5, 0x08, 0xfd, 0x32, 0xdb, 0xfd, 0xb9, 0xa9, 0x55, 0x5d, 0x1e, 0x7a, 0x10, 0xf9, - 0x6d, 0xc1, 0x73, 0xbf, 0x53, 0xbf, 0x5b, 0x9b, 0xe3, 0x77, 0x5a, 0x9f, 0xa5, 0x57, 0x64, 0xbb, 0xd7, 0xad, 0x99, - 0xd6, 0x67, 0x7b, 0x0d, 0x3e, 0x82, 0x30, 0x29, 0xbd, 0xd2, 0x89, 0x90, 0x21, 0x3f, 0xfc, 0x80, 0x6c, 0xeb, 0xaf, - 0x17, 0xca, 0xe5, 0x97, 0x88, 0x00, 0xd9, 0x55, 0xd7, 0x65, 0x75, 0xe8, 0xa3, 0x6c, 0xe2, 0xd5, 0x21, 0xf7, 0x56, - 0xee, 0xe9, 0xdd, 0x5c, 0xc4, 0x0e, 0x5f, 0xfb, 0xad, 0x78, 0x0b, 0x39, 0x81, 0x78, 0xd8, 0xee, 0xfc, 0xb2, 0x20, - 0x67, 0x37, 0xb7, 0x50, 0xd2, 0x9f, 0xb8, 0x2b, 0xfd, 0x81, 0x99, 0xeb, 0x06, 0x7e, 0x1e, 0x75, 0x61, 0xea, 0x9b, - 0x3d, 0x1c, 0x76, 0xa0, 0x0f, 0x0d, 0x87, 0xcd, 0x06, 0x5d, 0x66, 0x05, 0x91, 0x2b, 0x5e, 0x18, 0x3c, 0xbb, 0x20, - 0xed, 0x3e, 0x8f, 0xed, 0x66, 0xd2, 0xa2, 0x51, 0xbb, 0xc9, 0xbd, 0x99, 0x01, 0x7e, 0xd9, 0xb2, 0x7e, 0x11, 0xb7, - 0x4e, 0x1e, 0x94, 0x5c, 0xb1, 0x6a, 0x7d, 0x2a, 0x78, 0xd5, 0x1b, 0x8e, 0x37, 0xd3, 0xdd, 0xba, 0xc1, 0xed, 0xae, - 0x83, 0x27, 0xbc, 0xc0, 0x62, 0xd0, 0xda, 0x4d, 0x7c, 0x02, 0x1c, 0x50, 0xd4, 0x7a, 0xd8, 0x05, 0x17, 0xca, 0x12, - 0x96, 0xdb, 0xe5, 0x66, 0x5b, 0xe5, 0x0c, 0x1c, 0x4d, 0x49, 0x8f, 0x3b, 0xd8, 0x84, 0x28, 0x74, 0x70, 0xd8, 0xc1, - 0x51, 0xbb, 0xdd, 0xe9, 0xe2, 0xe8, 0xa4, 0x0b, 0x03, 0x6d, 0x44, 0xdd, 0xc3, 0x59, 0x6e, 0x00, 0xe8, 0xe5, 0xac, - 0x6d, 0xbb, 0x8f, 0x21, 0x5a, 0x93, 0x2f, 0x5e, 0xf3, 0xc3, 0x30, 0x6c, 0x47, 0x0f, 0x5b, 0xed, 0xee, 0x59, 0x03, - 0x00, 0xd4, 0xb4, 0x1f, 0xb6, 0xc6, 0xeb, 0x85, 0xaa, 0x57, 0x29, 0x11, 0xbe, 0x5e, 0xad, 0xe1, 0xaa, 0x35, 0xda, - 0xeb, 0x6a, 0x0a, 0xae, 0xaa, 0x15, 0xce, 0x4d, 0x11, 0xa7, 0xb4, 0xf1, 0xb7, 0x45, 0x68, 0x06, 0x12, 0x82, 0x74, - 0x1e, 0x75, 0x3b, 0x5d, 0x64, 0xc6, 0xa2, 0x2c, 0x7e, 0x94, 0xfb, 0x64, 0xab, 0x48, 0x43, 0x01, 0x92, 0x94, 0xb3, - 0x13, 0x0b, 0x90, 0xa8, 0x39, 0xb9, 0x68, 0x37, 0x67, 0x2c, 0x72, 0x13, 0xd0, 0xa9, 0xb0, 0x9c, 0xe5, 0x2a, 0xd8, - 0x24, 0x0f, 0x10, 0xe7, 0x60, 0x5c, 0xf4, 0xb0, 0xdb, 0x7f, 0x18, 0x75, 0x4f, 0x3b, 0x86, 0xe8, 0xf1, 0xf3, 0x4e, - 0x2d, 0x4d, 0x4f, 0x3d, 0xea, 0xea, 0x34, 0xe8, 0x3a, 0x7a, 0xd8, 0x85, 0x32, 0x36, 0xc5, 0x2f, 0x05, 0x51, 0x26, - 0xaa, 0x62, 0x10, 0x5a, 0x22, 0xae, 0xe5, 0x9e, 0xd6, 0xb2, 0xcf, 0x4e, 0x8e, 0x1f, 0x76, 0x7d, 0xa8, 0x95, 0xb3, - 0xd0, 0x0b, 0x6d, 0x27, 0xe2, 0x66, 0x07, 0x4b, 0x8b, 0x0e, 0xa3, 0x6e, 0xbc, 0x35, 0x41, 0xb3, 0x69, 0x0e, 0x35, - 0x0e, 0x78, 0x0a, 0xc7, 0x4b, 0x69, 0xf5, 0x25, 0xde, 0xfd, 0x58, 0x65, 0x68, 0xe2, 0x2b, 0x9c, 0xdd, 0x3d, 0xa5, - 0xf7, 0x90, 0xa4, 0x7f, 0x55, 0x79, 0x45, 0xf3, 0xaf, 0x54, 0xbe, 0xa1, 0x10, 0x3a, 0x23, 0x1f, 0x06, 0x36, 0xb0, - 0x77, 0x3d, 0xf7, 0x27, 0x70, 0x11, 0x66, 0x39, 0x5c, 0x68, 0x3a, 0x25, 0x68, 0xc5, 0x0b, 0x8c, 0x7c, 0x56, 0x57, - 0x0f, 0xab, 0xcf, 0x63, 0x6b, 0x52, 0xe0, 0xeb, 0xb6, 0x9e, 0xf3, 0xef, 0x95, 0x8b, 0xca, 0xab, 0xec, 0xa8, 0x8b, - 0x22, 0x7b, 0x59, 0x1e, 0xb5, 0x51, 0xe4, 0x99, 0x90, 0xd8, 0x23, 0x39, 0x49, 0xc8, 0x20, 0xb8, 0x0b, 0x70, 0x70, - 0x1f, 0xe0, 0xc0, 0xf8, 0x30, 0x7f, 0x00, 0x37, 0xf2, 0x00, 0x07, 0xc6, 0x95, 0x39, 0xc0, 0x81, 0x62, 0x39, 0x44, - 0xd4, 0x0a, 0x86, 0x38, 0x83, 0xd2, 0xda, 0xb3, 0xba, 0x2c, 0x7d, 0xe5, 0xbe, 0x4a, 0xd7, 0x6b, 0x93, 0xe2, 0x49, - 0x99, 0x53, 0xbd, 0x43, 0xcd, 0x8b, 0xd0, 0x01, 0x75, 0xcc, 0x7a, 0x80, 0x41, 0x00, 0xa1, 0xf7, 0xee, 0x45, 0xb9, - 0x2a, 0x18, 0x07, 0x3b, 0x86, 0x95, 0x06, 0x9f, 0xf3, 0xc0, 0x3f, 0xc3, 0x02, 0x3c, 0xce, 0x5d, 0x61, 0x10, 0x2b, - 0xdc, 0xef, 0x4c, 0x88, 0xb9, 0xfb, 0xad, 0x44, 0xf9, 0x0b, 0xde, 0x21, 0xb1, 0x16, 0x2d, 0x60, 0xb9, 0x65, 0x62, - 0xff, 0x8c, 0x58, 0x7d, 0x04, 0x37, 0x63, 0x1b, 0x9f, 0x0d, 0x24, 0xc2, 0x1b, 0x2d, 0x50, 0x39, 0xf9, 0xf0, 0xc6, - 0xc4, 0x0a, 0xd2, 0x9f, 0x10, 0x2c, 0x0c, 0xe2, 0x01, 0x0b, 0xb8, 0xd0, 0x98, 0x14, 0x4c, 0xca, 0xc0, 0x04, 0xd1, - 0x0b, 0x44, 0xee, 0x5e, 0x45, 0x74, 0x29, 0xe3, 0x3c, 0xd0, 0x1d, 0xd6, 0x67, 0x6b, 0xc4, 0xe1, 0x4c, 0x14, 0x32, - 0x36, 0x4f, 0xa4, 0x38, 0x30, 0xce, 0xcb, 0xf7, 0x07, 0xe3, 0x2c, 0x59, 0x63, 0x73, 0x87, 0x5d, 0x16, 0xb2, 0x57, - 0xda, 0x7e, 0xa9, 0x24, 0x59, 0x7f, 0x6b, 0x42, 0xb2, 0x36, 0x23, 0x6f, 0xa2, 0xd5, 0x80, 0xaa, 0x48, 0x1a, 0x50, - 0xd8, 0x44, 0x63, 0x89, 0x97, 0x65, 0xc9, 0x78, 0x59, 0x2e, 0xc3, 0x49, 0xab, 0xb5, 0x5e, 0xe3, 0x82, 0xe9, 0xa8, - 0x30, 0x3b, 0x4b, 0x40, 0xbe, 0x9c, 0x8a, 0x5b, 0x2f, 0x57, 0xc6, 0xe5, 0x2c, 0xf5, 0x12, 0x05, 0x9e, 0x11, 0x6c, - 0xb0, 0xc6, 0x5f, 0xb9, 0xe4, 0x00, 0x4f, 0x3b, 0xbb, 0x91, 0x10, 0x19, 0xa3, 0x10, 0x3c, 0xcc, 0x6b, 0x72, 0x8d, - 0xa7, 0x3c, 0x65, 0xbb, 0xdb, 0x04, 0x33, 0xe6, 0x7f, 0xaf, 0x45, 0x87, 0x40, 0x86, 0xdd, 0xd3, 0xa8, 0x03, 0x8b, - 0xb8, 0x82, 0x0e, 0x7c, 0x19, 0x3c, 0xf5, 0x71, 0x33, 0xa3, 0xf7, 0x62, 0xa1, 0x00, 0x2e, 0x0b, 0x25, 0xde, 0xd8, - 0xb8, 0x07, 0xfb, 0x2d, 0xec, 0x42, 0x20, 0x2c, 0x21, 0x64, 0x40, 0x0b, 0x9b, 0x10, 0x15, 0x2d, 0x3c, 0x12, 0x4a, - 0x89, 0x59, 0xdc, 0xc2, 0x3a, 0x5e, 0x44, 0x6b, 0x5d, 0x06, 0xf5, 0xba, 0xc9, 0xdd, 0x5b, 0x92, 0xd5, 0x26, 0x58, - 0x58, 0xe9, 0x50, 0x11, 0xe5, 0xdd, 0x1e, 0x32, 0xc2, 0x1b, 0x3f, 0x5f, 0xbf, 0x7e, 0x65, 0x43, 0x36, 0xf3, 0x31, - 0xb8, 0x6c, 0x5a, 0xd5, 0xd8, 0x8d, 0x7e, 0x84, 0x29, 0xac, 0x14, 0xa5, 0x46, 0x38, 0x85, 0x96, 0x5f, 0xe4, 0x2a, - 0x8b, 0xcc, 0xe5, 0xc5, 0x33, 0x51, 0xcc, 0xa8, 0xb9, 0x31, 0xc2, 0x37, 0xb9, 0x7d, 0x75, 0x5d, 0x3f, 0xec, 0x52, - 0x4d, 0xf2, 0xdd, 0xe6, 0x55, 0xc4, 0x22, 0xd1, 0xf2, 0x2b, 0x68, 0x03, 0x74, 0xe5, 0xf2, 0xd1, 0xdc, 0x82, 0xd8, - 0xc0, 0xf7, 0x1e, 0x79, 0x79, 0x6b, 0xa8, 0x4b, 0x10, 0x34, 0xb8, 0xc6, 0x4f, 0x56, 0xf0, 0xc4, 0xbb, 0x2e, 0xd4, - 0xec, 0x91, 0x15, 0x2f, 0x82, 0x56, 0x50, 0x7f, 0x74, 0x56, 0xab, 0x12, 0x5c, 0xd0, 0xd4, 0x28, 0x13, 0x20, 0x7a, - 0x94, 0xef, 0xdb, 0x71, 0x10, 0x4d, 0xdc, 0xdd, 0xf3, 0x45, 0xdb, 0xd1, 0xd9, 0xac, 0x52, 0x27, 0x96, 0x57, 0x26, - 0xe0, 0xe1, 0x68, 0x5e, 0x90, 0x41, 0xd8, 0x4b, 0x64, 0xa5, 0xf6, 0xd0, 0xe5, 0xa2, 0x5e, 0x98, 0x9d, 0xb7, 0x59, - 0xf3, 0x64, 0xb5, 0xca, 0x2e, 0xda, 0xac, 0xdd, 0x35, 0xef, 0xcd, 0x05, 0x32, 0x01, 0x9a, 0xcb, 0xc7, 0x3c, 0x09, - 0x40, 0x3b, 0x3b, 0x4e, 0x74, 0x38, 0x05, 0x17, 0x21, 0x99, 0x2c, 0x54, 0xd5, 0x97, 0x00, 0xe3, 0x52, 0x62, 0xf4, - 0xf8, 0x05, 0xea, 0xb7, 0xe3, 0x6d, 0x57, 0xe9, 0x66, 0xfb, 0xd0, 0xbb, 0x70, 0x29, 0x10, 0xee, 0x40, 0xc8, 0x03, - 0xd0, 0xef, 0x2e, 0x73, 0x30, 0x0d, 0x02, 0x54, 0xce, 0x41, 0xa4, 0xe5, 0xb3, 0xc5, 0xec, 0x59, 0x41, 0xf5, 0x32, - 0x3c, 0xe1, 0x13, 0xae, 0x64, 0x4c, 0x41, 0xba, 0xdd, 0x95, 0xbe, 0xde, 0x2d, 0x41, 0x25, 0xb5, 0xc0, 0xb3, 0x91, - 0xe2, 0xc9, 0x17, 0x69, 0x17, 0x0e, 0x61, 0xbd, 0xb2, 0x12, 0x27, 0x68, 0x8d, 0x33, 0x31, 0xa1, 0x05, 0x57, 0xd3, - 0xd9, 0xbf, 0xb5, 0x3a, 0x6c, 0xa0, 0x86, 0xfa, 0xc2, 0x0a, 0x40, 0x42, 0xf3, 0x74, 0xb5, 0xe2, 0x47, 0xdf, 0xbf, - 0x4f, 0x72, 0x3e, 0xe1, 0x6d, 0xdc, 0xc1, 0xc7, 0xb8, 0x8b, 0xdb, 0x2d, 0xdc, 0xee, 0xc2, 0xd5, 0x7d, 0x92, 0x2d, - 0x52, 0x06, 0xf6, 0xb1, 0xab, 0x95, 0xba, 0x88, 0xce, 0x0e, 0xcb, 0x70, 0xfb, 0xaa, 0x88, 0x2c, 0xba, 0x78, 0x51, - 0xdf, 0x6d, 0xb8, 0xbc, 0x20, 0xf0, 0x63, 0xb5, 0x8d, 0x7d, 0xd5, 0x49, 0xa9, 0x5f, 0xb8, 0x38, 0xee, 0x83, 0x3d, - 0xb7, 0x59, 0xd9, 0x26, 0x98, 0x7d, 0x9b, 0x9f, 0x71, 0xf5, 0xb3, 0xa9, 0x4a, 0xc4, 0x70, 0xd0, 0xab, 0xd0, 0x03, - 0x5d, 0x90, 0xf6, 0xc1, 0x01, 0x58, 0x1d, 0x79, 0xb3, 0xe1, 0x26, 0xfa, 0x01, 0x6f, 0xd6, 0xd2, 0x20, 0x58, 0x01, - 0x18, 0x77, 0xbe, 0xe1, 0x64, 0x69, 0x60, 0xab, 0x80, 0x0a, 0xab, 0xc2, 0x0f, 0x28, 0xe7, 0x93, 0x0a, 0x2d, 0x44, - 0xc3, 0x11, 0x66, 0x23, 0x9d, 0xec, 0xb7, 0xb0, 0x18, 0x8f, 0x25, 0x53, 0x70, 0x74, 0x14, 0xec, 0x2b, 0x2b, 0xa4, - 0x3e, 0x45, 0x46, 0x6c, 0xc2, 0xf3, 0x4b, 0xf5, 0x89, 0x15, 0x42, 0x7f, 0x6a, 0x0d, 0x46, 0x1c, 0xe8, 0x55, 0x0c, - 0x70, 0x92, 0xf1, 0x39, 0x54, 0x9d, 0x14, 0xe0, 0xf4, 0x03, 0x7f, 0x79, 0x1a, 0xfb, 0x6d, 0x02, 0xf9, 0xfa, 0x60, - 0xc2, 0xba, 0xe0, 0xb4, 0xa0, 0xb7, 0xaf, 0xf3, 0x2b, 0xd8, 0x51, 0x97, 0x05, 0xa3, 0x90, 0x0d, 0x49, 0xef, 0xa0, - 0x29, 0xf8, 0x80, 0x36, 0x5f, 0x6a, 0xc0, 0xc5, 0x67, 0xfa, 0xc3, 0x54, 0x74, 0x41, 0x0b, 0xa3, 0xb2, 0x2d, 0x9d, - 0xa9, 0x4f, 0xe9, 0x2a, 0xd3, 0x84, 0x85, 0x2a, 0xa7, 0xb0, 0xc6, 0x36, 0xea, 0x89, 0x3f, 0x98, 0x94, 0xca, 0x69, - 0x3c, 0x18, 0xea, 0xbf, 0xaf, 0x4d, 0xc9, 0x16, 0xb6, 0x41, 0x67, 0xd6, 0x58, 0xbf, 0x18, 0xea, 0x95, 0x6f, 0x63, - 0xb8, 0x87, 0x85, 0x67, 0x2b, 0x6b, 0xe4, 0xf3, 0xc4, 0x91, 0xcd, 0x93, 0xf5, 0x5a, 0x0f, 0x44, 0xc6, 0xa0, 0x07, - 0x7a, 0xeb, 0xb6, 0x4d, 0x0b, 0xb6, 0x47, 0xf9, 0xd5, 0x6d, 0xe1, 0x19, 0x87, 0x57, 0x38, 0x5d, 0x7b, 0xd7, 0xaa, - 0x10, 0x5f, 0x2c, 0x48, 0x5a, 0x5e, 0x8a, 0x99, 0x8e, 0xd7, 0xd9, 0x31, 0xf6, 0x46, 0x0e, 0xf4, 0xfc, 0xfa, 0x8b, - 0x81, 0xb5, 0xfb, 0xfd, 0xa6, 0x2c, 0x98, 0xd1, 0x11, 0xcb, 0xca, 0x09, 0x25, 0xee, 0xfc, 0x7c, 0xc3, 0xa3, 0x0a, - 0x15, 0xec, 0xf3, 0x55, 0xb0, 0xa7, 0x4d, 0x84, 0xcb, 0x19, 0xfd, 0xcb, 0xfc, 0x30, 0x81, 0x75, 0x4a, 0x2d, 0x5b, - 0x52, 0x08, 0x29, 0x2f, 0x4d, 0x9a, 0x39, 0x7a, 0xe0, 0x88, 0x7c, 0x09, 0x5d, 0x00, 0xaf, 0x9f, 0x16, 0x62, 0xae, - 0x11, 0xc1, 0xfe, 0xb6, 0xe3, 0xd6, 0xbe, 0x02, 0xe0, 0xed, 0xb0, 0x57, 0xfd, 0xd3, 0x02, 0xf6, 0x37, 0x28, 0x4b, - 0xba, 0xf1, 0x76, 0xcc, 0xf1, 0x5f, 0x08, 0x08, 0x97, 0x6e, 0xf0, 0x30, 0xb2, 0xe8, 0x54, 0xb2, 0x66, 0xe5, 0xcf, - 0xad, 0x92, 0x80, 0x61, 0xf5, 0x82, 0x3e, 0x1b, 0xb7, 0x55, 0xdc, 0x64, 0xfe, 0x07, 0x15, 0x34, 0x16, 0x7c, 0x6b, - 0x24, 0x15, 0xcb, 0xe2, 0xb6, 0x4f, 0x9d, 0xff, 0xaa, 0x73, 0x5c, 0xfb, 0xaa, 0xf6, 0x44, 0xe6, 0x48, 0x87, 0x27, - 0x0e, 0xd0, 0xc1, 0xc1, 0x46, 0x06, 0x1d, 0x03, 0xe0, 0x91, 0x65, 0xbf, 0xdc, 0xf2, 0x39, 0x76, 0x4c, 0x6b, 0x1e, - 0x8b, 0xc0, 0x67, 0xee, 0x1c, 0x37, 0x67, 0x26, 0xf2, 0x84, 0xca, 0xa9, 0x2b, 0x0c, 0x70, 0x7c, 0xbc, 0x95, 0x0a, - 0xf8, 0x1e, 0xac, 0x77, 0x4c, 0x60, 0x83, 0xdf, 0x32, 0x93, 0xda, 0x55, 0xd0, 0x2d, 0xd0, 0x72, 0x17, 0x53, 0xb9, - 0xb1, 0xc0, 0xc1, 0xe6, 0x44, 0x76, 0x0e, 0x7d, 0xa3, 0x4e, 0xc9, 0x7a, 0x3c, 0xd9, 0x6d, 0xf4, 0x95, 0xcb, 0x5d, - 0xc9, 0x15, 0x6d, 0x1b, 0xb1, 0xea, 0x99, 0x5c, 0x55, 0x99, 0x3a, 0x55, 0xd7, 0xbc, 0x95, 0xa5, 0x4d, 0x69, 0x97, - 0x64, 0xee, 0xb6, 0x98, 0x7f, 0x15, 0xde, 0x68, 0x94, 0x17, 0xa1, 0x60, 0x8f, 0x25, 0x87, 0x3d, 0x4e, 0xe0, 0x7a, - 0x61, 0xb5, 0x0a, 0xe1, 0xcf, 0xae, 0x31, 0xec, 0x32, 0x5d, 0xfa, 0xc0, 0x37, 0xf8, 0x15, 0x2f, 0x52, 0xaf, 0xb5, - 0x83, 0x04, 0xeb, 0x2e, 0x3b, 0x68, 0x38, 0x4e, 0xdc, 0x17, 0xbc, 0x13, 0xad, 0x9c, 0xcb, 0xc1, 0x24, 0xf9, 0xc6, - 0xdb, 0x72, 0x25, 0x6b, 0x59, 0x0b, 0xf3, 0xbe, 0x21, 0xc1, 0x10, 0xb3, 0x29, 0xad, 0xe3, 0x56, 0xd4, 0x46, 0x81, - 0x2d, 0x56, 0xa1, 0xff, 0xb7, 0x8a, 0x24, 0x26, 0xf3, 0xbf, 0x4e, 0x4f, 0x4f, 0x6d, 0x8a, 0xb5, 0xf9, 0x93, 0xda, - 0x03, 0x4e, 0x27, 0xb0, 0xaf, 0x3c, 0x61, 0x5a, 0x87, 0xfc, 0x16, 0x86, 0x42, 0x24, 0xb9, 0x70, 0xec, 0x12, 0x44, - 0xe5, 0x02, 0xca, 0x03, 0xec, 0xdf, 0x93, 0x8d, 0x72, 0xee, 0x9d, 0x24, 0x17, 0x47, 0xb8, 0x6c, 0x90, 0x7d, 0xd5, - 0x9f, 0x03, 0x63, 0x26, 0x03, 0x4f, 0x03, 0x04, 0xd8, 0xfc, 0xd6, 0x2c, 0xad, 0xb5, 0x94, 0xc1, 0x81, 0x12, 0x8b, - 0x64, 0x6a, 0x34, 0xff, 0xf6, 0x43, 0x97, 0xb5, 0x6f, 0xec, 0x40, 0x50, 0x2e, 0xb2, 0xb4, 0xe1, 0x30, 0x83, 0x1f, - 0xcb, 0xc8, 0x97, 0x7b, 0xaf, 0xd8, 0x82, 0xfd, 0x88, 0xf7, 0xaa, 0x14, 0xf8, 0xb8, 0x2c, 0x38, 0xcd, 0x7e, 0xc4, - 0x7b, 0x55, 0x04, 0x4c, 0x70, 0x85, 0xd4, 0x41, 0x24, 0xb1, 0x7e, 0x4f, 0x3a, 0x0e, 0x72, 0xa0, 0xa0, 0x59, 0xa0, - 0x0f, 0xb2, 0xe7, 0x36, 0x68, 0x62, 0xd4, 0xc1, 0x36, 0xee, 0x97, 0x09, 0x85, 0x6a, 0x22, 0x88, 0x43, 0x20, 0xb9, - 0x72, 0x36, 0xfa, 0xeb, 0xf1, 0xc6, 0x82, 0x68, 0x65, 0x32, 0xb9, 0x78, 0xce, 0xc3, 0x7c, 0x73, 0xb1, 0x90, 0x5f, - 0xcd, 0x5b, 0xa0, 0x5a, 0x95, 0x2a, 0xdd, 0x2f, 0xbe, 0x5d, 0x30, 0xf1, 0x8a, 0xe8, 0xad, 0x77, 0x79, 0x07, 0xcf, - 0x9d, 0xdf, 0x05, 0x2e, 0x09, 0x9e, 0x04, 0xd7, 0x98, 0xea, 0x5e, 0x80, 0x07, 0x42, 0xcf, 0xa4, 0x0a, 0xb0, 0xce, - 0x93, 0x10, 0x49, 0x6c, 0xbf, 0x85, 0x2d, 0x6b, 0xf4, 0x22, 0x77, 0x42, 0x0a, 0x9c, 0xab, 0xba, 0x89, 0x19, 0xe5, - 0x3a, 0xba, 0xd8, 0xa5, 0x9c, 0xb3, 0x44, 0x19, 0x04, 0xd8, 0xb7, 0x68, 0x28, 0xf2, 0xe7, 0x1a, 0x14, 0xfa, 0x2d, - 0x6b, 0x9b, 0x72, 0x05, 0x8b, 0xe7, 0xa5, 0x00, 0x51, 0xe3, 0xf9, 0xa4, 0xac, 0x33, 0xcf, 0x16, 0x13, 0x9e, 0x57, - 0xc8, 0x50, 0x30, 0x39, 0x17, 0x39, 0x3c, 0x25, 0x51, 0x16, 0xd1, 0x74, 0xa8, 0x86, 0xef, 0x86, 0x84, 0x95, 0x75, - 0xf4, 0x31, 0xc5, 0xf3, 0xaa, 0x06, 0x30, 0x17, 0x97, 0xfe, 0x9b, 0xf3, 0xf2, 0x75, 0xfe, 0x4e, 0xcc, 0xab, 0x7c, - 0x47, 0xe3, 0x5c, 0xc4, 0x76, 0x6b, 0x37, 0x8c, 0xd6, 0xfa, 0xb5, 0x27, 0x6f, 0xfb, 0x7e, 0xe0, 0xd5, 0x0b, 0x68, - 0x6b, 0xfd, 0x5e, 0x54, 0x99, 0x35, 0x62, 0xe5, 0xe3, 0x08, 0x55, 0x7b, 0xf5, 0xaa, 0xb9, 0xad, 0x08, 0x50, 0x29, - 0x78, 0xba, 0x95, 0xff, 0x44, 0x99, 0x7c, 0x73, 0x0e, 0x95, 0xe1, 0x81, 0x1c, 0x19, 0xaa, 0x7a, 0xc0, 0x45, 0xf9, - 0xa1, 0x9f, 0xbe, 0x0a, 0x74, 0xe0, 0xdc, 0x5d, 0x17, 0xc8, 0x9c, 0xc9, 0x50, 0xe0, 0xe5, 0x80, 0x0e, 0x63, 0x23, - 0x0f, 0xc5, 0x02, 0x6c, 0x7b, 0x6e, 0x0b, 0xae, 0x5c, 0x84, 0x5e, 0x3c, 0x60, 0xc3, 0x78, 0x59, 0x8f, 0xe2, 0x6b, - 0xe2, 0x08, 0x3b, 0x73, 0x4e, 0x1d, 0xf6, 0x96, 0x0e, 0x71, 0x46, 0xc0, 0xf6, 0xd8, 0xb1, 0xa7, 0x6f, 0xc2, 0x04, - 0xf5, 0xeb, 0x1c, 0xfe, 0x72, 0x8d, 0x33, 0x9c, 0xa0, 0xf8, 0x32, 0x84, 0x0b, 0xac, 0x35, 0x06, 0xf0, 0x25, 0x86, - 0x54, 0x81, 0x47, 0x6a, 0xa2, 0x25, 0x56, 0x7b, 0x11, 0x88, 0x96, 0xca, 0xbf, 0x1d, 0x67, 0x2e, 0x0e, 0xb6, 0xe6, - 0x5e, 0x9f, 0x69, 0xe1, 0x70, 0x92, 0x84, 0xb5, 0x73, 0x86, 0x93, 0x8b, 0x7d, 0x5e, 0x3b, 0x31, 0xc1, 0xda, 0xdb, - 0x3f, 0x55, 0x40, 0x8f, 0x06, 0xa7, 0x8a, 0xa1, 0x21, 0x10, 0x33, 0x01, 0xbc, 0x99, 0xfd, 0xa3, 0xcd, 0xc3, 0xf9, - 0x60, 0x8d, 0xbd, 0xaf, 0xb8, 0xd6, 0xd5, 0xa6, 0x12, 0x65, 0xbd, 0xc6, 0x83, 0x69, 0x82, 0xd3, 0x04, 0xcf, 0x93, - 0xa1, 0x77, 0xdc, 0xcc, 0x12, 0xdf, 0xa4, 0x6b, 0xb5, 0x7a, 0x6a, 0xcd, 0x08, 0x91, 0xf9, 0x69, 0xe8, 0x0f, 0xea, - 0x03, 0xc2, 0xc7, 0x90, 0x05, 0xb4, 0xa4, 0x6f, 0xff, 0x36, 0xcc, 0x33, 0xd9, 0xa8, 0x11, 0xf2, 0xc8, 0x90, 0x91, - 0xbe, 0xfb, 0x51, 0x66, 0x99, 0xd6, 0x1a, 0xc1, 0xfc, 0x6e, 0x2f, 0x68, 0xb8, 0xf6, 0x3c, 0x2d, 0x5b, 0x69, 0xb6, - 0x03, 0x88, 0x62, 0x8c, 0x93, 0x94, 0xb7, 0x46, 0x62, 0xb5, 0x0a, 0x4d, 0x0a, 0xe1, 0xd1, 0x8c, 0x51, 0xb9, 0x28, - 0xf4, 0xcb, 0x71, 0x61, 0x8e, 0x22, 0xcd, 0xef, 0x62, 0x6b, 0x23, 0x9a, 0x83, 0xdb, 0x23, 0x18, 0x6e, 0x84, 0x92, - 0x88, 0x9a, 0xc8, 0x3d, 0x4a, 0x2a, 0xcb, 0x20, 0x49, 0xa4, 0x16, 0xf9, 0xcd, 0x75, 0xa9, 0x39, 0x0c, 0xec, 0x1f, - 0xed, 0x0b, 0x08, 0x37, 0x6f, 0x13, 0x5a, 0x8c, 0xe8, 0x04, 0xd8, 0x58, 0x88, 0x43, 0xb8, 0x95, 0xb0, 0x5a, 0x0d, - 0x86, 0x3d, 0x43, 0x9e, 0xed, 0xcb, 0x79, 0x65, 0x43, 0xbb, 0x1b, 0x80, 0xab, 0x6e, 0x43, 0xcd, 0x95, 0xd6, 0xfd, - 0x50, 0xfd, 0xb8, 0x17, 0xb7, 0x49, 0xf6, 0x7d, 0x8e, 0xea, 0x09, 0xee, 0x9a, 0x05, 0xb8, 0x0e, 0x5d, 0x85, 0x53, - 0xbc, 0x30, 0x36, 0x9c, 0xfa, 0x25, 0x27, 0xaa, 0x1f, 0x70, 0x82, 0x77, 0xa3, 0x09, 0x1b, 0x24, 0x43, 0x9c, 0xba, - 0x38, 0xdf, 0xfb, 0x6f, 0xc3, 0x14, 0xa1, 0x82, 0x68, 0x98, 0x1a, 0x97, 0xed, 0xb4, 0xb2, 0xdb, 0xd7, 0x99, 0x9a, - 0x61, 0xd0, 0x46, 0xcc, 0xa9, 0x6f, 0xc4, 0x9c, 0x35, 0x1a, 0x68, 0x41, 0x52, 0x30, 0x62, 0x5e, 0x78, 0xad, 0x2d, - 0xcc, 0x2b, 0x9f, 0x5e, 0x7b, 0x0b, 0x84, 0x7a, 0x1c, 0x68, 0x9a, 0x82, 0xf7, 0x3c, 0xaa, 0xf7, 0xd4, 0xdd, 0xeb, - 0x52, 0x47, 0x1d, 0x50, 0x24, 0x8c, 0x2f, 0xdc, 0x24, 0x8c, 0x6b, 0xb8, 0x19, 0xf7, 0x58, 0x8f, 0xdb, 0xda, 0x36, - 0xe4, 0x03, 0x31, 0x48, 0x86, 0xc3, 0x9e, 0x70, 0x56, 0x12, 0x2d, 0x3c, 0xae, 0x5e, 0x00, 0xa9, 0x16, 0xef, 0xab, - 0xda, 0xbc, 0xf2, 0xe6, 0xee, 0x61, 0xd1, 0xcd, 0xf3, 0x18, 0x38, 0xa0, 0x7d, 0xb8, 0x1f, 0xaa, 0xe2, 0x83, 0x1d, - 0x75, 0x20, 0x0a, 0x5a, 0xdc, 0xaa, 0x09, 0xa4, 0xc6, 0xcc, 0x2e, 0x54, 0xcd, 0x1c, 0x1d, 0x4a, 0x08, 0x43, 0x96, - 0x57, 0xdd, 0xdd, 0xe7, 0x9e, 0x6a, 0x88, 0xc3, 0xa9, 0x7f, 0x65, 0x8c, 0x58, 0xc3, 0xa0, 0x93, 0x06, 0xda, 0x48, - 0xd2, 0x2c, 0x1f, 0x3c, 0xfa, 0x03, 0x56, 0x02, 0x2e, 0xf8, 0xb2, 0x4e, 0xd2, 0x86, 0x04, 0x6f, 0x59, 0xa2, 0x34, - 0x1f, 0xc2, 0x2d, 0x82, 0xf2, 0xc8, 0xc4, 0xda, 0xb4, 0x95, 0x0c, 0xe4, 0xaa, 0x2e, 0x6f, 0x3c, 0xf4, 0xbc, 0x4f, - 0xaa, 0xdd, 0x00, 0x1c, 0x99, 0x37, 0xb0, 0x64, 0x6b, 0x9f, 0x80, 0x47, 0x3e, 0xae, 0x10, 0xc4, 0x2d, 0x85, 0x8a, - 0x74, 0xa0, 0xea, 0x6b, 0xd8, 0xa0, 0x78, 0x0e, 0x0e, 0x82, 0x56, 0x82, 0xc3, 0xe0, 0x5d, 0x66, 0x34, 0xc9, 0x1a, - 0xb7, 0x66, 0x24, 0x9c, 0xaf, 0x56, 0x2d, 0x74, 0xf8, 0xb7, 0x7e, 0x8b, 0x79, 0x5c, 0x2a, 0xdc, 0xc7, 0x95, 0xc2, - 0x1d, 0x2c, 0x01, 0xc9, 0xd8, 0xd3, 0xb5, 0x63, 0xe1, 0xab, 0xd1, 0x21, 0x4c, 0xf8, 0x0b, 0x08, 0x1a, 0x6d, 0x8f, - 0x25, 0xd0, 0xb3, 0x6f, 0x15, 0x30, 0xba, 0xf6, 0xb2, 0x04, 0xd2, 0x82, 0xbb, 0xdb, 0x04, 0x5a, 0x85, 0xa8, 0x7d, - 0xfe, 0xf4, 0x73, 0x0e, 0x3c, 0xb2, 0xfe, 0x5c, 0x33, 0xcd, 0xba, 0x17, 0xf4, 0x56, 0x37, 0x1f, 0x8e, 0x71, 0x73, - 0x6c, 0xc0, 0x79, 0xd4, 0x81, 0x9f, 0x06, 0xa2, 0x47, 0x1d, 0x6c, 0x53, 0xf1, 0xb8, 0x04, 0xb2, 0x8f, 0x9e, 0xd6, - 0x40, 0x0a, 0x58, 0xe9, 0xd0, 0x68, 0x91, 0x26, 0x68, 0xb5, 0x9a, 0x9c, 0x93, 0x16, 0x42, 0x4b, 0x79, 0xcb, 0x55, - 0x32, 0x05, 0x1f, 0x69, 0x50, 0x0c, 0xbc, 0xa1, 0x6a, 0x1a, 0x22, 0x3c, 0x46, 0xcb, 0x94, 0x8d, 0xe9, 0x22, 0x53, - 0x71, 0xde, 0xe7, 0x91, 0x89, 0xa4, 0xcb, 0x4c, 0x24, 0xb8, 0xa3, 0x0e, 0x9e, 0x68, 0xfe, 0xf2, 0xb1, 0x36, 0x07, - 0x29, 0x12, 0x9d, 0x3c, 0xd1, 0x09, 0x98, 0x47, 0x49, 0x26, 0x24, 0x33, 0xcd, 0xf4, 0x8c, 0x6d, 0x39, 0xc4, 0xe2, - 0x0e, 0x54, 0xc1, 0xb5, 0x15, 0x65, 0x10, 0x4f, 0x49, 0xde, 0xcf, 0x8f, 0x3a, 0xf1, 0x04, 0xf3, 0x08, 0x38, 0xbd, - 0x77, 0x22, 0x64, 0x8d, 0xf2, 0x56, 0x74, 0x86, 0x0e, 0xa7, 0x58, 0x56, 0x97, 0xa8, 0x33, 0x74, 0x38, 0x41, 0x78, - 0xd6, 0x20, 0x59, 0x0e, 0x1e, 0xc3, 0x3c, 0xff, 0x3f, 0x52, 0xfe, 0x9b, 0xc3, 0x86, 0x98, 0xcf, 0x6f, 0x61, 0xa7, - 0xb0, 0x34, 0x88, 0x33, 0x02, 0x5e, 0x8b, 0xed, 0x53, 0x9c, 0x90, 0x49, 0x33, 0x73, 0x01, 0xf7, 0x74, 0x2b, 0x8d, - 0x3b, 0x85, 0x0e, 0x13, 0x9c, 0x6e, 0x26, 0x85, 0x7a, 0xae, 0xcd, 0x2c, 0x4e, 0xe0, 0x7c, 0xaf, 0x46, 0x61, 0xcb, - 0x2f, 0x36, 0x93, 0xfc, 0xf2, 0x16, 0xb8, 0xcd, 0x14, 0xcb, 0x26, 0xc5, 0x19, 0x9e, 0x35, 0x5f, 0xe1, 0x59, 0xf3, - 0x43, 0x99, 0xd1, 0x58, 0x60, 0x09, 0xc1, 0xfb, 0x20, 0x11, 0xcf, 0xaa, 0xe4, 0x14, 0xcb, 0x86, 0x2e, 0x8f, 0x67, - 0x8d, 0xaa, 0x74, 0x73, 0x81, 0x65, 0x43, 0x97, 0x6e, 0x7c, 0xc0, 0xb3, 0xc6, 0xab, 0x7f, 0x31, 0xe9, 0x20, 0x06, - 0x74, 0x99, 0xa3, 0x65, 0x62, 0x86, 0x78, 0xfd, 0xdb, 0xdb, 0x77, 0xed, 0x9b, 0xce, 0xe1, 0x04, 0xbb, 0xf5, 0x4b, - 0x34, 0x8e, 0x25, 0x2a, 0x64, 0x4d, 0x80, 0x68, 0x82, 0x3b, 0x87, 0x53, 0xdc, 0x39, 0x4c, 0x6c, 0x53, 0xeb, 0x59, - 0x83, 0xdc, 0x29, 0x1f, 0x8a, 0x2a, 0x88, 0x7d, 0xf8, 0xb8, 0xc9, 0xc6, 0x13, 0x54, 0x03, 0x25, 0x3a, 0x9c, 0xd4, - 0x40, 0x05, 0xdf, 0x8b, 0xda, 0x77, 0x55, 0xaf, 0xc2, 0x20, 0x03, 0x25, 0xe4, 0xaf, 0xb9, 0x06, 0x4f, 0x2d, 0x45, - 0x43, 0xc6, 0x4f, 0x31, 0x40, 0xf9, 0x0e, 0x28, 0xb4, 0xf2, 0x44, 0x0f, 0xdd, 0x9b, 0x8e, 0x4e, 0xfc, 0xff, 0x79, - 0x32, 0xe5, 0xd0, 0xcb, 0x2d, 0xb3, 0x35, 0x3d, 0x3b, 0x19, 0x7f, 0xf8, 0xc0, 0x63, 0xfd, 0x5f, 0x3b, 0x50, 0xac, - 0x41, 0x8a, 0xff, 0x2f, 0x1d, 0x9d, 0x0f, 0x46, 0xc8, 0x0a, 0xe2, 0xc2, 0x22, 0xfe, 0xf7, 0x87, 0xe5, 0x75, 0x5f, - 0x6c, 0x75, 0x5f, 0xe8, 0xee, 0xfd, 0xa6, 0xb5, 0x2a, 0x27, 0xae, 0x2a, 0x19, 0xf2, 0x5f, 0xa7, 0x5b, 0x5b, 0xa0, - 0x91, 0x35, 0x7a, 0x36, 0xf1, 0x1b, 0xdc, 0x6f, 0xc7, 0x3b, 0x90, 0x79, 0xcd, 0xcd, 0xd3, 0xa0, 0x70, 0xf8, 0x7a, - 0x77, 0xaa, 0x17, 0x2d, 0xf0, 0xde, 0x94, 0x5a, 0x5f, 0x19, 0xfa, 0x96, 0x83, 0xc5, 0xa6, 0x29, 0xb7, 0x36, 0x96, - 0x8e, 0xba, 0x58, 0xbb, 0x22, 0x42, 0xa5, 0xbb, 0x0b, 0x50, 0x8a, 0x8f, 0x55, 0x93, 0xe9, 0xaf, 0x73, 0x15, 0xe9, - 0x4b, 0xa8, 0x86, 0xfe, 0xbc, 0xbf, 0x50, 0x91, 0x12, 0x73, 0x93, 0x77, 0x7f, 0x0e, 0x7d, 0x82, 0x86, 0xb5, 0xe1, - 0xd9, 0xed, 0xb3, 0xc2, 0xea, 0x77, 0xaa, 0x43, 0xd0, 0x3f, 0x80, 0x2c, 0x69, 0x31, 0x7d, 0x60, 0xdd, 0x1a, 0xb6, - 0x5d, 0x34, 0xcb, 0x44, 0xd3, 0x6a, 0x53, 0xe7, 0x9a, 0x3d, 0xcc, 0xe7, 0x3e, 0x4f, 0xc1, 0x0b, 0xa3, 0x1f, 0xdf, - 0xc1, 0x6e, 0xdc, 0xd5, 0x18, 0x89, 0xba, 0x92, 0xa9, 0x84, 0x7e, 0x74, 0x87, 0x59, 0x74, 0xaf, 0xbd, 0x18, 0x73, - 0xed, 0xef, 0xa3, 0x03, 0xe5, 0x07, 0x95, 0x24, 0x07, 0x96, 0xfd, 0x0d, 0x16, 0xdd, 0x81, 0x79, 0x62, 0x59, 0x4d, - 0x60, 0x15, 0xdd, 0x7b, 0x8b, 0x28, 0x74, 0x23, 0x6b, 0xcd, 0x80, 0xea, 0x66, 0x8c, 0x7a, 0x70, 0x1f, 0x02, 0x3d, - 0xf4, 0xcb, 0x52, 0xca, 0x76, 0x16, 0xd7, 0xba, 0x57, 0xba, 0xfb, 0xcd, 0x01, 0x79, 0x7c, 0xa1, 0xc7, 0x35, 0xfd, - 0xab, 0x49, 0x44, 0x23, 0xf6, 0x0f, 0x67, 0xc5, 0xd5, 0xa2, 0xd0, 0x98, 0x26, 0xfb, 0x2a, 0x4a, 0xe6, 0x6d, 0x30, - 0xd5, 0x4b, 0xe6, 0x9d, 0x3b, 0x6c, 0xbf, 0xef, 0xcd, 0xf7, 0x3d, 0x96, 0x7d, 0xa6, 0x33, 0x62, 0xa6, 0x8b, 0xb9, - 0xef, 0x7b, 0xf3, 0x7d, 0x8f, 0xb7, 0x07, 0x73, 0xeb, 0x2e, 0x14, 0x4b, 0x76, 0x86, 0x0b, 0x30, 0x2c, 0xf7, 0xb8, - 0x9b, 0x5a, 0x96, 0x0e, 0x02, 0x5b, 0x4b, 0x80, 0x38, 0x9f, 0x4f, 0xc3, 0x8a, 0x57, 0x43, 0xc0, 0x7d, 0x3a, 0xd7, - 0xf6, 0x2a, 0x15, 0x78, 0x4c, 0xd0, 0x88, 0xe8, 0xd8, 0x36, 0xfa, 0x59, 0x2f, 0xe0, 0xf2, 0x88, 0x2a, 0xf5, 0x24, - 0x11, 0xf0, 0xaa, 0x5a, 0xe5, 0xad, 0x8b, 0x94, 0x5f, 0xc4, 0xcb, 0x71, 0xc5, 0x1e, 0x53, 0xc9, 0x00, 0x56, 0x65, - 0x49, 0x97, 0x40, 0xea, 0xf9, 0xde, 0x44, 0xbf, 0x6c, 0x22, 0x4f, 0xae, 0x6f, 0x4b, 0xbf, 0x30, 0x35, 0x2d, 0xc4, - 0x62, 0x32, 0x05, 0x1f, 0x5a, 0x60, 0x19, 0x0a, 0x5d, 0xaf, 0xb2, 0xf5, 0xaf, 0x49, 0x6e, 0x12, 0x28, 0x9c, 0x6a, - 0x8a, 0x88, 0x26, 0x6a, 0x41, 0x33, 0x6d, 0x49, 0xca, 0xf3, 0xc9, 0x63, 0x71, 0xf7, 0x12, 0xb0, 0x9b, 0x12, 0xd5, - 0xd8, 0x91, 0xf7, 0x16, 0x76, 0x00, 0x4e, 0x08, 0xdb, 0x55, 0xf1, 0x52, 0x82, 0xce, 0x1f, 0x67, 0x84, 0xed, 0xaa, - 0xfa, 0x84, 0x99, 0xec, 0x29, 0xd9, 0x18, 0x6e, 0x3f, 0x4c, 0x1a, 0x19, 0x3a, 0xea, 0xc4, 0x59, 0xcf, 0x11, 0x03, - 0x03, 0x50, 0x0f, 0xb8, 0x5b, 0xdb, 0xb3, 0xbc, 0xbb, 0x21, 0x79, 0x94, 0xb2, 0x44, 0x98, 0xeb, 0x72, 0x9d, 0xb2, - 0x5a, 0x75, 0x2a, 0x2a, 0x58, 0xe0, 0xa9, 0xb7, 0x17, 0xa8, 0xf9, 0xda, 0x41, 0x71, 0xae, 0x93, 0x4d, 0xd3, 0xf3, - 0xb2, 0xef, 0xde, 0x8e, 0x45, 0xc6, 0x26, 0xed, 0xed, 0x0e, 0x22, 0x61, 0x38, 0x61, 0xe5, 0x71, 0xc2, 0x55, 0x6d, - 0x8f, 0x00, 0xdd, 0x78, 0x22, 0x37, 0x16, 0x64, 0xb9, 0xae, 0x8c, 0xee, 0x3d, 0xbf, 0x5b, 0x4a, 0x84, 0x1d, 0x6d, - 0x49, 0x30, 0x5d, 0x82, 0x56, 0xd3, 0xe9, 0x37, 0x99, 0x6b, 0xcf, 0x0d, 0x6f, 0x8a, 0xb6, 0xb9, 0xbd, 0x49, 0xc7, - 0x7a, 0x7b, 0xe8, 0x18, 0xca, 0x20, 0x06, 0x3a, 0x1f, 0xf1, 0x5e, 0xa3, 0x91, 0x20, 0x50, 0xc8, 0x24, 0x43, 0x2c, - 0x22, 0xa7, 0x45, 0x3f, 0x38, 0xd0, 0xf0, 0xa8, 0x12, 0x10, 0xa6, 0x20, 0x84, 0xf8, 0x5d, 0x6b, 0x84, 0xf5, 0x97, - 0xab, 0x96, 0x0b, 0x1b, 0xa9, 0x36, 0x74, 0xf0, 0xff, 0xf2, 0x97, 0xad, 0x9e, 0x59, 0x2e, 0x8a, 0xc6, 0xcd, 0x4c, - 0x83, 0x45, 0x80, 0xf4, 0x68, 0xb2, 0x1d, 0x14, 0x77, 0xe7, 0x62, 0xbd, 0x21, 0x20, 0x31, 0x83, 0x09, 0xca, 0x86, - 0x75, 0x63, 0x0c, 0xf3, 0xa8, 0xd2, 0xb2, 0xd6, 0x24, 0x66, 0xcf, 0x97, 0xce, 0x5f, 0xf7, 0xe5, 0x5d, 0xcc, 0xf0, - 0x7d, 0x2c, 0xf1, 0x2d, 0x78, 0xd2, 0xc4, 0x02, 0xdb, 0xc7, 0x0b, 0x8a, 0x35, 0x51, 0x3d, 0xc7, 0xde, 0x16, 0xb0, - 0xce, 0x7a, 0x8f, 0x48, 0xef, 0x77, 0xf5, 0xab, 0x0d, 0xbe, 0x5b, 0xf8, 0x15, 0x58, 0x3f, 0x7b, 0x27, 0x29, 0x96, - 0x0d, 0xd1, 0x2c, 0xec, 0x91, 0x01, 0xe5, 0x2a, 0x7e, 0xd9, 0x4f, 0xdd, 0x2a, 0x86, 0x6b, 0x1f, 0xaf, 0xf0, 0x87, - 0x8d, 0x76, 0x1b, 0x79, 0x59, 0xdc, 0xec, 0x4d, 0xd9, 0x10, 0x55, 0xd3, 0x3b, 0x32, 0x37, 0x52, 0xea, 0x5f, 0x1f, - 0x70, 0x6b, 0xab, 0x7d, 0x37, 0xcd, 0xb7, 0x0e, 0x9d, 0xab, 0xa6, 0x5d, 0x6a, 0xad, 0x08, 0xf6, 0x7e, 0xb6, 0x70, - 0x73, 0x6b, 0xc0, 0x1e, 0xfc, 0xdc, 0x1d, 0xcd, 0x55, 0x02, 0xd1, 0xe9, 0x8d, 0x66, 0x7c, 0x15, 0xfe, 0x99, 0x36, - 0xc2, 0x7e, 0xfc, 0x67, 0xf4, 0x67, 0xda, 0x40, 0x7d, 0x14, 0xce, 0xef, 0x56, 0x6c, 0xb6, 0x82, 0x60, 0x6b, 0x0f, - 0x8e, 0xf0, 0x6b, 0xbf, 0x24, 0x57, 0x34, 0xe3, 0xc9, 0xca, 0xbe, 0x84, 0xb7, 0xb2, 0xcf, 0x04, 0xad, 0xf4, 0xe3, - 0x4e, 0xab, 0x50, 0x8c, 0x32, 0x08, 0x2c, 0x1c, 0xee, 0x35, 0xfb, 0x83, 0x56, 0xf3, 0xd1, 0xd0, 0xfc, 0xab, 0x23, - 0xdc, 0xa3, 0x5a, 0xc4, 0xb6, 0x37, 0x1b, 0x5b, 0x3f, 0x04, 0xc3, 0x0e, 0x08, 0x05, 0x0e, 0x72, 0xe9, 0x55, 0x82, - 0x8c, 0xef, 0xc9, 0x6a, 0xc5, 0x6c, 0x34, 0x6b, 0xab, 0xc1, 0x2f, 0x63, 0x33, 0x1d, 0xb6, 0xa3, 0x4e, 0xcf, 0x89, - 0xb1, 0xa4, 0x01, 0x91, 0xa6, 0x31, 0x83, 0x40, 0x52, 0x4b, 0xcd, 0x61, 0xcd, 0xef, 0x82, 0xb8, 0xba, 0x3f, 0x82, - 0x94, 0x1f, 0x82, 0x98, 0x1f, 0x11, 0x08, 0xa0, 0x6d, 0x98, 0xa3, 0xb2, 0x21, 0xe7, 0xbb, 0xf4, 0x40, 0x3b, 0x33, - 0x34, 0xf8, 0x6a, 0xd5, 0xaa, 0x86, 0x29, 0x8b, 0xfa, 0x30, 0x97, 0x6b, 0x2c, 0xc9, 0x1b, 0xd0, 0x35, 0xe7, 0x44, - 0xf6, 0x7d, 0x57, 0x79, 0x78, 0x08, 0x18, 0x0b, 0x02, 0x4e, 0xfa, 0x7d, 0xd9, 0x2f, 0xc8, 0xc5, 0x65, 0x08, 0x3e, - 0x66, 0x98, 0x0f, 0xd4, 0xa0, 0x18, 0x0e, 0x51, 0x6c, 0x9d, 0xce, 0x62, 0x1d, 0x71, 0xc5, 0xf3, 0x4b, 0x2e, 0xc0, - 0x2f, 0x39, 0x47, 0x6c, 0x50, 0x0c, 0xc9, 0x83, 0x24, 0x14, 0xe0, 0x94, 0xbf, 0xc3, 0xe7, 0xf1, 0xd2, 0x37, 0x30, - 0xd5, 0xc3, 0xd2, 0x17, 0xd9, 0x60, 0x31, 0x67, 0x2c, 0x81, 0xe0, 0x66, 0xc0, 0x5e, 0x6a, 0x43, 0xa2, 0xb6, 0x06, - 0x0a, 0xee, 0x02, 0xdf, 0xcc, 0xe8, 0xe9, 0x56, 0x1b, 0x83, 0xc0, 0xe2, 0x85, 0xbe, 0x86, 0x31, 0x08, 0xa4, 0x2f, - 0x57, 0x1d, 0xf6, 0x97, 0x1f, 0x26, 0xcb, 0x0f, 0x5e, 0xa1, 0x4d, 0x76, 0x4a, 0xab, 0x44, 0x3d, 0xbe, 0xca, 0x13, - 0x47, 0x13, 0x64, 0x62, 0xa8, 0x74, 0xc3, 0x32, 0x71, 0x25, 0x7d, 0x26, 0x9a, 0x6c, 0x37, 0x1c, 0x33, 0xe7, 0xbb, - 0xd9, 0xfe, 0x61, 0xdd, 0xce, 0x39, 0xe1, 0x5a, 0x2b, 0xa9, 0xb5, 0x51, 0xcf, 0x34, 0x55, 0xb5, 0xc1, 0xfc, 0x2e, - 0xad, 0x96, 0x16, 0x5b, 0x57, 0xef, 0x9e, 0xff, 0x2c, 0x5d, 0x19, 0x7f, 0x8b, 0x55, 0xa1, 0x15, 0x19, 0x6e, 0xb7, - 0x90, 0x33, 0x67, 0xba, 0x74, 0x8a, 0x5c, 0xa8, 0x0e, 0x7f, 0x51, 0x4f, 0xea, 0x97, 0x2a, 0x83, 0x86, 0x74, 0xe8, - 0xf7, 0x3a, 0x01, 0xe5, 0x1f, 0x4c, 0x4c, 0x64, 0x2c, 0xba, 0xa5, 0x45, 0x1e, 0xfe, 0xf8, 0x22, 0xd7, 0xb1, 0xaa, - 0xf6, 0x60, 0x20, 0x7b, 0xba, 0xe2, 0x1e, 0xdc, 0x9a, 0xf0, 0x31, 0x67, 0x69, 0xbc, 0x17, 0xfc, 0xd8, 0x90, 0x8d, - 0x1f, 0x83, 0x1f, 0xc1, 0xdd, 0xd9, 0x3e, 0x8b, 0x58, 0xc6, 0x85, 0x70, 0xf7, 0x58, 0x97, 0xa5, 0x4a, 0x19, 0x2b, - 0xa7, 0x5b, 0xf6, 0x2f, 0xa4, 0xde, 0x24, 0xe1, 0xa5, 0x25, 0xd6, 0x26, 0x05, 0x2b, 0x9f, 0x92, 0xc2, 0xb3, 0x2b, - 0xfa, 0x56, 0x8b, 0xd9, 0x4b, 0x2d, 0xe9, 0xae, 0xaf, 0x2e, 0x4b, 0x15, 0x34, 0x1c, 0x84, 0xb6, 0xb4, 0x81, 0x04, - 0x18, 0xb8, 0x94, 0x3e, 0x9d, 0xf6, 0x4c, 0x22, 0xb3, 0x24, 0x84, 0x77, 0x0f, 0x2a, 0x98, 0xff, 0xce, 0x36, 0xc2, - 0xaa, 0xc0, 0xe5, 0x4a, 0x15, 0xf5, 0x52, 0x10, 0x08, 0x40, 0x5f, 0x7a, 0x0f, 0x8a, 0xf3, 0xa2, 0xd7, 0x68, 0x08, - 0xd0, 0xc2, 0x52, 0x7d, 0xad, 0x8a, 0xe9, 0xbe, 0xff, 0x9c, 0x9f, 0xf7, 0xe1, 0x1c, 0xd2, 0x36, 0xde, 0xd4, 0xa4, - 0x84, 0x9a, 0x1d, 0xb4, 0x0f, 0x56, 0xd9, 0x5e, 0xf9, 0xb7, 0x21, 0x45, 0x26, 0x7f, 0xc0, 0x7e, 0xa0, 0xb6, 0xc3, - 0xa1, 0x2d, 0x58, 0xf5, 0x52, 0x46, 0xc1, 0x80, 0x95, 0x03, 0x6e, 0x4f, 0x46, 0x09, 0x4d, 0xa6, 0x0c, 0xd4, 0xfd, - 0xa6, 0x68, 0x35, 0xb7, 0x27, 0x75, 0xbf, 0x21, 0xed, 0xec, 0x23, 0xb5, 0xb3, 0x4f, 0x0e, 0x5e, 0x2c, 0x82, 0xfc, - 0x21, 0x42, 0x85, 0xc3, 0xbc, 0x29, 0xd1, 0x51, 0x07, 0xb8, 0x33, 0x70, 0xe0, 0x01, 0x5b, 0x94, 0x83, 0x03, 0x6a, - 0x2d, 0xee, 0x69, 0x23, 0x71, 0xde, 0x9e, 0x50, 0xbb, 0x08, 0x25, 0x6e, 0xd6, 0xcc, 0xb4, 0xa0, 0xb5, 0x42, 0x3b, - 0x8f, 0x7b, 0xbc, 0xcd, 0xb3, 0x5a, 0xfc, 0x84, 0x0d, 0x6b, 0xaa, 0xfa, 0x0d, 0x34, 0x47, 0xb5, 0x20, 0x37, 0x4f, - 0xb5, 0xb7, 0x2a, 0x19, 0x04, 0xc1, 0xd0, 0x70, 0x2a, 0x44, 0x93, 0x8c, 0x41, 0x6b, 0xe8, 0xdd, 0x6a, 0xaf, 0x56, - 0xdc, 0x21, 0xbe, 0xac, 0x79, 0xab, 0xe9, 0x5b, 0x00, 0x5a, 0x84, 0x41, 0x79, 0x6f, 0x12, 0x80, 0xf7, 0x6d, 0x19, - 0x21, 0x6d, 0x39, 0x30, 0x6f, 0x36, 0x96, 0x8a, 0xcd, 0x77, 0x74, 0x32, 0x8c, 0x03, 0x33, 0xa2, 0x00, 0xdf, 0x94, - 0x90, 0x84, 0xab, 0xa4, 0x1b, 0x99, 0x88, 0x39, 0x93, 0x31, 0xc7, 0x37, 0x85, 0x10, 0xea, 0xda, 0x7c, 0x09, 0x5c, - 0xdd, 0xc9, 0x48, 0x7c, 0x33, 0x61, 0xea, 0x1d, 0x2d, 0x26, 0x0c, 0xfc, 0x8a, 0xdc, 0xed, 0x58, 0x4c, 0xc9, 0xc5, - 0x53, 0x19, 0x0e, 0x28, 0x86, 0x07, 0x47, 0x87, 0x58, 0xe9, 0x10, 0x28, 0x15, 0x2e, 0xb2, 0xdb, 0xbd, 0x37, 0x85, - 0xb8, 0xbb, 0x0f, 0x0b, 0x6c, 0x1d, 0x00, 0x4b, 0xa7, 0x49, 0x80, 0x7f, 0xf9, 0x98, 0x8f, 0xd1, 0x98, 0x53, 0xad, - 0xeb, 0xb7, 0xbf, 0xa3, 0x1b, 0xa0, 0xb7, 0xa5, 0xa3, 0xe0, 0xa0, 0x35, 0x84, 0x5c, 0xb8, 0x0b, 0x83, 0x8b, 0x2f, - 0xbf, 0xb6, 0x28, 0xb4, 0x37, 0x16, 0x40, 0xef, 0xaf, 0x04, 0x2c, 0xd8, 0x30, 0xc7, 0x14, 0x5e, 0x6b, 0x9d, 0x30, - 0xe5, 0x45, 0x05, 0x79, 0x52, 0xbe, 0xc7, 0x59, 0xab, 0xfd, 0x96, 0x8d, 0xe1, 0x0e, 0x23, 0xfa, 0x76, 0xe1, 0xc8, - 0x82, 0x07, 0x64, 0x9a, 0xc4, 0x34, 0xfb, 0xc6, 0x45, 0x1e, 0x79, 0x3d, 0x0e, 0x77, 0xb5, 0xe4, 0xe7, 0xeb, 0x15, - 0x5d, 0x63, 0x08, 0x45, 0xe1, 0xf7, 0xfb, 0x15, 0x1e, 0x28, 0xad, 0x0c, 0xda, 0xa0, 0x61, 0x71, 0x9b, 0xff, 0x02, - 0x67, 0x0c, 0xad, 0x17, 0x32, 0x77, 0x74, 0xc6, 0xe1, 0xcc, 0x62, 0xc6, 0x94, 0xc0, 0xa8, 0x94, 0x28, 0xe8, 0x04, - 0x1c, 0x9d, 0xab, 0x0f, 0x92, 0x87, 0xd5, 0xb1, 0x02, 0xf0, 0x24, 0x53, 0xf8, 0x27, 0xdb, 0x04, 0xeb, 0x7e, 0xab, - 0x66, 0x98, 0xfa, 0x8b, 0xda, 0x76, 0x2d, 0x5f, 0xfa, 0x38, 0xd2, 0xc6, 0x10, 0x5a, 0xe7, 0xee, 0x1e, 0x50, 0xc4, - 0x06, 0xbd, 0x88, 0x15, 0xbe, 0x91, 0x8b, 0x91, 0x5e, 0x5f, 0xed, 0x3a, 0xa6, 0x00, 0x51, 0xac, 0xbb, 0x26, 0xbe, - 0xa9, 0x9e, 0x3f, 0x95, 0x71, 0x0e, 0x67, 0x10, 0x84, 0x38, 0x29, 0x2f, 0x1b, 0x62, 0x41, 0x2e, 0x74, 0xa7, 0x42, - 0x77, 0x5a, 0x21, 0x94, 0x4d, 0x8f, 0xca, 0xfb, 0x57, 0x08, 0x61, 0xa0, 0xcb, 0xec, 0xc0, 0xaa, 0x7c, 0x0b, 0xab, - 0xe0, 0xd5, 0x8b, 0x0d, 0xac, 0x12, 0x70, 0x3c, 0x97, 0x68, 0x54, 0x54, 0x38, 0xa4, 0x49, 0x9f, 0x8f, 0x45, 0x90, - 0x00, 0x58, 0xf4, 0x2e, 0xb1, 0x79, 0xdf, 0xc3, 0x21, 0xbf, 0x27, 0x11, 0xf9, 0xd3, 0x8d, 0x68, 0x06, 0xef, 0xe2, - 0xca, 0xbe, 0x43, 0x08, 0x58, 0x7a, 0x8e, 0xe1, 0x3d, 0xe4, 0xef, 0xbf, 0xc3, 0x6a, 0x2d, 0xc8, 0xe3, 0x7f, 0x89, - 0x92, 0xd0, 0xd8, 0x7f, 0x8e, 0x87, 0x16, 0x09, 0xfd, 0x81, 0x6f, 0x8e, 0xb0, 0xc2, 0xc1, 0xad, 0x22, 0x2e, 0x83, - 0x5b, 0x7c, 0xac, 0x43, 0x0f, 0x00, 0x4b, 0x28, 0xf6, 0x41, 0xbe, 0x81, 0x62, 0x1a, 0x07, 0x14, 0x59, 0xfa, 0x17, - 0xb8, 0x60, 0xb5, 0x50, 0xde, 0xdf, 0xb6, 0x9c, 0x94, 0x56, 0xbb, 0xe4, 0xd5, 0xe6, 0x40, 0xe5, 0xa7, 0x7f, 0xe1, - 0x2b, 0xf5, 0x43, 0xcd, 0xf6, 0x0b, 0xdf, 0x58, 0xa0, 0xc7, 0xa0, 0x08, 0xb0, 0xbf, 0xd7, 0x84, 0x3b, 0x8a, 0x5e, - 0xe6, 0x62, 0xbf, 0x6d, 0xaf, 0x7b, 0x89, 0xb9, 0xbc, 0xae, 0xb2, 0xe6, 0x60, 0x0a, 0x0d, 0x0e, 0xaa, 0x70, 0x46, - 0x60, 0x2e, 0x5f, 0x94, 0x05, 0xe7, 0x20, 0xde, 0xf7, 0xa5, 0xce, 0x29, 0xa3, 0x01, 0xbc, 0x48, 0xca, 0x47, 0xa7, - 0xfa, 0x1c, 0x5c, 0xc6, 0x35, 0x9b, 0xf8, 0x44, 0xba, 0x54, 0x60, 0x25, 0x8d, 0x71, 0x68, 0x40, 0x53, 0x3a, 0x07, - 0xb3, 0x0d, 0xa0, 0xe0, 0xf6, 0x7c, 0xd8, 0x58, 0x28, 0xef, 0x2d, 0xda, 0xda, 0xd3, 0xd1, 0x84, 0x58, 0x93, 0x26, - 0xef, 0x6e, 0x5b, 0x23, 0x83, 0x33, 0xbf, 0xfd, 0xb7, 0xc2, 0x22, 0xc1, 0x80, 0x4a, 0x4d, 0x12, 0x84, 0x27, 0x28, - 0x8d, 0x74, 0x2b, 0x37, 0x13, 0x48, 0x27, 0xb2, 0x66, 0xd4, 0xbd, 0x71, 0xbe, 0x5a, 0x6a, 0x20, 0x2b, 0x6a, 0x90, - 0x7b, 0xd4, 0x40, 0xd4, 0xb7, 0x7f, 0x01, 0x0b, 0x61, 0x22, 0x54, 0x49, 0x2f, 0x20, 0xc2, 0x5c, 0x69, 0x3e, 0xa0, - 0x88, 0x7c, 0xc8, 0x6b, 0x40, 0x85, 0x94, 0xbc, 0x04, 0xa3, 0x71, 0x78, 0xbd, 0x07, 0xdc, 0x2f, 0x0d, 0xc3, 0xe0, - 0x38, 0x05, 0x9d, 0xff, 0xd6, 0xe5, 0x43, 0xf5, 0x72, 0x75, 0x10, 0xc2, 0x4f, 0x24, 0x64, 0x98, 0x46, 0x7e, 0x01, - 0xb2, 0x99, 0x63, 0x71, 0x70, 0x20, 0x40, 0xe0, 0x87, 0x28, 0xc2, 0x1e, 0xcf, 0xf0, 0x32, 0xd9, 0x20, 0x7a, 0x6e, - 0x56, 0x79, 0x35, 0x2b, 0xe1, 0xcd, 0xaa, 0x70, 0x34, 0x8e, 0xae, 0x09, 0x03, 0xc1, 0x85, 0x9a, 0x7d, 0x83, 0x10, - 0x28, 0x5b, 0x6e, 0x35, 0x5d, 0x7a, 0x0a, 0xe6, 0xa3, 0x61, 0xf0, 0x96, 0xc1, 0x8b, 0xba, 0xda, 0xe4, 0x9f, 0x29, - 0x96, 0x28, 0xcd, 0x3c, 0x36, 0x3c, 0x27, 0x75, 0x8a, 0xa2, 0xbf, 0x04, 0xcf, 0xc3, 0xa0, 0x79, 0x11, 0xa0, 0x06, - 0xfc, 0xdb, 0xe0, 0xa8, 0x47, 0x23, 0x9a, 0xa6, 0x2e, 0xf8, 0x4d, 0x42, 0xf4, 0x26, 0x5b, 0xad, 0x64, 0x45, 0xd0, - 0x23, 0xb3, 0xc1, 0x80, 0x95, 0x78, 0x02, 0x3b, 0xd6, 0x70, 0xb0, 0xe4, 0x85, 0x0c, 0x73, 0x77, 0x4a, 0xe1, 0x1c, - 0x43, 0x3a, 0xc2, 0x89, 0x17, 0xb3, 0xf1, 0x3f, 0x9f, 0xa9, 0xbf, 0x7e, 0x6e, 0xbe, 0x96, 0x11, 0x11, 0x2e, 0x88, - 0x5c, 0x8d, 0x1d, 0x91, 0x5e, 0xd8, 0x32, 0x35, 0xb0, 0x65, 0x7e, 0x70, 0xd6, 0xd5, 0x43, 0x13, 0x2e, 0x0e, 0x0c, - 0xa8, 0x91, 0x67, 0xb4, 0x82, 0x33, 0x52, 0x0e, 0x1c, 0x94, 0x10, 0x8a, 0x15, 0xe1, 0x94, 0x5c, 0x40, 0x24, 0xbc, - 0x04, 0xf5, 0xc0, 0xb0, 0xc0, 0x93, 0xa0, 0xa6, 0x20, 0x41, 0x25, 0xae, 0x76, 0x0a, 0xb3, 0xce, 0xf4, 0x6c, 0xa7, - 0xa8, 0x67, 0x83, 0xfc, 0xfc, 0xa2, 0xc2, 0x14, 0x58, 0xda, 0x83, 0x83, 0x02, 0x22, 0x88, 0x01, 0x05, 0x2f, 0x25, - 0x40, 0x4f, 0x03, 0x5e, 0x6c, 0x68, 0xc0, 0xe7, 0x4a, 0x7b, 0x1d, 0x68, 0x5b, 0x9f, 0x32, 0xc8, 0xc5, 0xb3, 0x6a, - 0x4f, 0x13, 0x42, 0xf6, 0x5b, 0x7d, 0x15, 0x6f, 0x47, 0x48, 0xec, 0x7f, 0x54, 0x3a, 0xd0, 0x98, 0x25, 0xdd, 0xd5, - 0xc6, 0x7c, 0x55, 0xd3, 0x23, 0x56, 0x93, 0x10, 0x36, 0x48, 0x97, 0xe3, 0xd3, 0x9e, 0xc1, 0x15, 0xab, 0xd0, 0x72, - 0x70, 0x01, 0xfa, 0x6c, 0x40, 0x80, 0x02, 0x95, 0xa6, 0x12, 0x45, 0x11, 0x16, 0x51, 0xc9, 0x86, 0x61, 0x06, 0x61, - 0x0a, 0xab, 0x95, 0xa0, 0x1b, 0x6b, 0x00, 0xbc, 0x33, 0x33, 0x7f, 0x4a, 0x1f, 0x6c, 0xba, 0x76, 0xe6, 0x11, 0x40, - 0x40, 0xf6, 0xdb, 0x25, 0xbb, 0x2e, 0x37, 0x2a, 0x33, 0xbf, 0x96, 0xb6, 0x95, 0xdb, 0xf6, 0x18, 0x7b, 0x21, 0xb7, - 0xf9, 0x04, 0x08, 0x51, 0x5b, 0x32, 0x8d, 0x10, 0x21, 0xb1, 0x08, 0x55, 0x6d, 0xc8, 0x5a, 0x1b, 0x3a, 0xd0, 0x2f, - 0xd2, 0x43, 0xec, 0x03, 0x50, 0xbc, 0x59, 0x2e, 0xc1, 0x22, 0xbc, 0x74, 0x08, 0x7f, 0x97, 0x83, 0x33, 0x3c, 0x66, - 0x58, 0xac, 0x56, 0x50, 0xcf, 0xe1, 0x7d, 0xb2, 0x19, 0x9c, 0x54, 0x6c, 0x8c, 0x5d, 0x98, 0x89, 0x87, 0x65, 0x13, - 0x02, 0x27, 0xd0, 0xaf, 0xab, 0x88, 0xfa, 0xfb, 0xed, 0xf8, 0xa9, 0x0c, 0x6b, 0x3b, 0x10, 0x6b, 0xd6, 0x1b, 0xac, - 0x3e, 0x80, 0x96, 0xff, 0x93, 0xb8, 0x87, 0xca, 0xbc, 0x9b, 0x84, 0x7c, 0x73, 0x11, 0x7b, 0xac, 0x87, 0x18, 0xa9, - 0x2d, 0xee, 0x0e, 0x21, 0xfe, 0x9f, 0xad, 0x28, 0x06, 0x3c, 0xaa, 0xf8, 0xe7, 0x10, 0xf5, 0x20, 0x14, 0xb5, 0xf1, - 0xb0, 0x01, 0x4a, 0xbb, 0x5c, 0x57, 0x62, 0xa4, 0x4f, 0x20, 0xdf, 0xda, 0xf0, 0x82, 0xfa, 0x24, 0xca, 0x41, 0x4e, - 0xf6, 0xa2, 0x92, 0x26, 0x1b, 0xc2, 0x5c, 0x6f, 0x0b, 0xc7, 0xf4, 0xd5, 0x06, 0x2d, 0xc2, 0x17, 0xc0, 0xce, 0x70, - 0x2d, 0x59, 0x5a, 0xf0, 0xe5, 0x35, 0xf0, 0xb9, 0x35, 0xd7, 0x14, 0x25, 0x47, 0xfd, 0x17, 0x52, 0xdf, 0xfa, 0xc3, - 0xef, 0xd8, 0x13, 0x1f, 0xa9, 0xd5, 0x91, 0x6c, 0x84, 0x5a, 0xb3, 0x76, 0xbc, 0x6c, 0x33, 0xc2, 0xa0, 0x34, 0xd1, - 0xfb, 0x2a, 0x64, 0x95, 0x3b, 0x3b, 0x95, 0xde, 0x9c, 0xbe, 0xe6, 0x95, 0x73, 0x2a, 0x37, 0x8c, 0x6a, 0xa9, 0x69, - 0x80, 0x08, 0x57, 0x2e, 0x91, 0xbc, 0x4f, 0x74, 0xf8, 0x07, 0x8d, 0x71, 0xf5, 0x48, 0xe1, 0xef, 0x77, 0xc5, 0x0e, - 0xd9, 0x8e, 0x0e, 0xb7, 0x11, 0x34, 0xcf, 0x57, 0xf0, 0x80, 0xa3, 0x92, 0x21, 0x44, 0x39, 0xb9, 0xd8, 0xcf, 0x6b, - 0xa6, 0x6c, 0x37, 0x01, 0x42, 0x48, 0x39, 0x9c, 0x75, 0x0e, 0x91, 0xb5, 0xd0, 0x23, 0x55, 0x94, 0xc3, 0x2d, 0x9a, - 0x6b, 0x03, 0x54, 0x68, 0x81, 0x74, 0xf9, 0x85, 0xdd, 0xc7, 0x02, 0xa2, 0x97, 0xaf, 0x6d, 0x08, 0x63, 0x6b, 0x65, - 0x89, 0x0b, 0x3d, 0x6a, 0x13, 0x46, 0xd7, 0x6e, 0x0c, 0x6b, 0x03, 0xa3, 0xa7, 0x41, 0x49, 0x0b, 0x42, 0x5d, 0xf7, - 0xe8, 0x79, 0xa2, 0x03, 0x3d, 0x66, 0x84, 0x36, 0x18, 0x9e, 0x12, 0x05, 0x96, 0x4d, 0x05, 0x58, 0xf0, 0x2d, 0x8b, - 0x38, 0xd7, 0x36, 0x9b, 0x2c, 0xfc, 0xa8, 0x42, 0xfd, 0xb4, 0x5f, 0x56, 0x31, 0xcf, 0x85, 0xa5, 0x6e, 0xcf, 0x13, - 0x17, 0x8f, 0xee, 0xe9, 0x9b, 0xeb, 0x17, 0x2f, 0x5f, 0xbf, 0x5a, 0xad, 0xda, 0xac, 0xd9, 0x3e, 0xc1, 0x3f, 0xa9, - 0x32, 0x1e, 0x6c, 0x19, 0x05, 0xe8, 0xe0, 0x60, 0x9f, 0x6b, 0x17, 0x9e, 0x2f, 0x7c, 0x0e, 0x71, 0x83, 0xd4, 0x10, - 0x27, 0x45, 0x19, 0x13, 0xe4, 0x2e, 0xe8, 0x07, 0xf7, 0x01, 0x28, 0xa1, 0x2a, 0xf2, 0xf7, 0x61, 0x73, 0xf6, 0x7b, - 0x10, 0x98, 0x08, 0xea, 0x43, 0x04, 0x10, 0x88, 0x57, 0x8a, 0x0b, 0xc2, 0x5c, 0x02, 0x44, 0xf1, 0x5e, 0xc0, 0x9b, - 0x90, 0x3a, 0x6a, 0xd5, 0x22, 0x0f, 0x0b, 0x20, 0x89, 0x26, 0x1c, 0x25, 0x3d, 0xd2, 0x01, 0xbc, 0x21, 0x28, 0xa5, - 0xf9, 0xd5, 0xcb, 0xac, 0xbb, 0x54, 0x86, 0xfa, 0xad, 0x38, 0xc3, 0x53, 0xfb, 0x39, 0x85, 0xcf, 0x69, 0xcf, 0x9d, - 0x0e, 0xf2, 0x30, 0xc3, 0x0b, 0x22, 0x0f, 0xdd, 0xb3, 0x88, 0xcb, 0x79, 0xc1, 0xbe, 0x72, 0xb1, 0x90, 0xf1, 0xf2, - 0x2e, 0x16, 0xd1, 0x5d, 0x33, 0x3d, 0x0c, 0x8b, 0xe8, 0xae, 0x99, 0x47, 0x77, 0x08, 0xdf, 0xc7, 0x22, 0xba, 0x37, - 0x29, 0xf7, 0xcd, 0x1c, 0x6e, 0xbe, 0x70, 0x0e, 0x87, 0xa2, 0x29, 0xda, 0x58, 0x6c, 0x16, 0x35, 0x29, 0xb6, 0xa8, - 0x87, 0xc1, 0xbf, 0xef, 0xd8, 0xf8, 0x7e, 0xf8, 0x12, 0x5c, 0x9a, 0x34, 0x91, 0x9f, 0x40, 0xfa, 0x69, 0x55, 0x06, - 0xee, 0x53, 0xd2, 0xea, 0x4d, 0xcf, 0x65, 0xb3, 0xdd, 0x6b, 0x34, 0xa6, 0xb0, 0x77, 0x13, 0x92, 0xb9, 0x62, 0xd3, - 0x86, 0x8e, 0xaf, 0xb3, 0x9f, 0xac, 0x56, 0xfb, 0x19, 0xd2, 0x1b, 0x6e, 0xc2, 0x42, 0x35, 0x98, 0x0e, 0x71, 0x0b, - 0x3f, 0x4f, 0x10, 0x5a, 0xb2, 0xc1, 0x74, 0x48, 0xd8, 0x60, 0xda, 0x68, 0x0f, 0x8d, 0xa1, 0x9d, 0xde, 0x8a, 0x6b, - 0x08, 0xa1, 0x39, 0x1d, 0x1e, 0xe9, 0x92, 0xc2, 0xe6, 0x9b, 0x2f, 0x5a, 0x05, 0xf4, 0xcb, 0x6b, 0xc1, 0xcb, 0x04, - 0xee, 0x40, 0x5f, 0xf4, 0xdc, 0x3c, 0xdd, 0x5a, 0x90, 0xe3, 0xa3, 0xca, 0xd5, 0x9e, 0x22, 0xac, 0x7b, 0xca, 0x0f, - 0x8b, 0x43, 0xdd, 0x8c, 0xed, 0x52, 0xd8, 0x6f, 0x5f, 0x33, 0xf2, 0xd1, 0xc2, 0x02, 0x10, 0xa4, 0x82, 0x47, 0x52, - 0xd8, 0x70, 0x4a, 0x3e, 0x5c, 0x2c, 0x54, 0xb6, 0x60, 0x92, 0x91, 0x56, 0x2f, 0xd3, 0x96, 0xfe, 0x99, 0x8d, 0x68, - 0x4a, 0x31, 0x25, 0x89, 0x2b, 0x99, 0x69, 0xb0, 0xd0, 0x4d, 0xca, 0x33, 0x05, 0xbd, 0xd2, 0x10, 0xa7, 0x04, 0xe2, - 0x21, 0xf5, 0x0a, 0x6d, 0xe0, 0x15, 0x4e, 0x9b, 0xc5, 0x80, 0x0d, 0xd1, 0xd1, 0x31, 0xa6, 0x83, 0xcf, 0xc9, 0xbc, - 0x0d, 0x8f, 0x05, 0x7e, 0x1e, 0x92, 0x69, 0x53, 0x94, 0x09, 0x12, 0x12, 0xd2, 0xa6, 0x38, 0x84, 0xbd, 0x84, 0x70, - 0x62, 0x2a, 0x26, 0x03, 0x36, 0x6c, 0x4e, 0xcb, 0x8a, 0x1d, 0x57, 0xb1, 0x21, 0xca, 0x04, 0x53, 0xb1, 0x61, 0x2b, - 0xfa, 0xaf, 0x33, 0x68, 0x10, 0xf8, 0x00, 0x60, 0x00, 0x00, 0x85, 0xbc, 0x68, 0xbe, 0x38, 0x27, 0x6e, 0xb3, 0x9b, - 0x7b, 0xfc, 0x16, 0x58, 0xa0, 0xd5, 0xf6, 0xff, 0x2e, 0x94, 0x01, 0x7b, 0xca, 0x42, 0xc7, 0xcc, 0x2d, 0x8c, 0x8a, - 0x0e, 0xa0, 0x52, 0x22, 0x4c, 0xa1, 0x21, 0xb3, 0x9f, 0x68, 0xa8, 0x79, 0x5a, 0x83, 0x6c, 0xa0, 0x86, 0xcd, 0x04, - 0x8e, 0x18, 0x78, 0x87, 0x86, 0x4c, 0xb5, 0x31, 0x61, 0x98, 0xc1, 0x14, 0x13, 0x0d, 0x9e, 0x69, 0xdc, 0x5a, 0x0b, - 0x2d, 0xcb, 0xf5, 0xb3, 0xfe, 0xdf, 0x2a, 0xcc, 0x07, 0x45, 0xb3, 0x3d, 0x44, 0xfb, 0x84, 0x98, 0x8f, 0x21, 0x6c, - 0x32, 0x9b, 0xda, 0xd0, 0xdf, 0x47, 0x9d, 0xd8, 0x7c, 0xc2, 0x9f, 0xe1, 0x5a, 0xef, 0x00, 0x1d, 0x78, 0x50, 0xaf, - 0xbf, 0xa8, 0xa9, 0xbc, 0x3e, 0xee, 0x8c, 0x52, 0xb9, 0xeb, 0xdd, 0x69, 0x4f, 0x53, 0xec, 0x7b, 0xeb, 0xe1, 0xf2, - 0xa1, 0x1e, 0x02, 0x66, 0x0c, 0xfa, 0x96, 0x19, 0x7d, 0x2f, 0x44, 0x72, 0x41, 0x04, 0x16, 0x1a, 0x6b, 0x18, 0xec, - 0xad, 0x83, 0x03, 0x5d, 0x8d, 0x35, 0xe0, 0x79, 0x52, 0x04, 0x82, 0x81, 0x8b, 0xa0, 0x0c, 0x68, 0x92, 0xeb, 0xdb, - 0x70, 0xf2, 0x91, 0xd9, 0x5f, 0xb8, 0xbc, 0x7d, 0x2c, 0x8c, 0xb6, 0x55, 0x27, 0xdf, 0x97, 0x05, 0xee, 0xcb, 0x7b, - 0x49, 0xa3, 0xe0, 0x46, 0xe6, 0x26, 0x2f, 0xd7, 0x77, 0xeb, 0xae, 0x54, 0x67, 0x77, 0x33, 0x9d, 0xb2, 0x99, 0xce, - 0x76, 0x33, 0xbe, 0x66, 0xe6, 0x5b, 0x56, 0x91, 0xfa, 0x64, 0x8d, 0xe4, 0x9c, 0xe6, 0x3f, 0xd1, 0x39, 0x18, 0x05, - 0x73, 0x73, 0xaf, 0x0a, 0x27, 0x57, 0x46, 0x2e, 0xf6, 0x33, 0x4d, 0x5c, 0x91, 0xbe, 0x50, 0x87, 0x00, 0x2f, 0x2f, - 0xca, 0xc7, 0x07, 0xb8, 0xc8, 0x7f, 0x15, 0xa9, 0x8d, 0x72, 0x9a, 0x0b, 0x25, 0x72, 0x16, 0x20, 0x8d, 0xaa, 0x36, - 0x06, 0xf6, 0xd2, 0xec, 0x3d, 0xd9, 0xe7, 0x83, 0x2a, 0x62, 0xde, 0x50, 0x3f, 0xf7, 0xf1, 0x3d, 0x4d, 0xb1, 0x55, - 0x13, 0x27, 0xe4, 0x43, 0x12, 0x66, 0x20, 0x9b, 0x0d, 0xaa, 0xd7, 0x7e, 0x1b, 0x6d, 0x5c, 0x34, 0x43, 0xd9, 0xd7, - 0x4f, 0x9c, 0xfc, 0x50, 0x68, 0xe3, 0x00, 0xe3, 0xe8, 0x8f, 0x30, 0x35, 0x60, 0x4f, 0x22, 0x47, 0xa1, 0xa3, 0x3b, - 0x93, 0x76, 0xef, 0xa7, 0xdd, 0xeb, 0xb4, 0x0e, 0x94, 0x03, 0xd2, 0x6c, 0xcb, 0x74, 0xee, 0xdd, 0xf7, 0x3d, 0xbc, - 0x74, 0xbb, 0x86, 0x48, 0xdc, 0xf3, 0xc7, 0xda, 0x18, 0xe2, 0x0d, 0xd8, 0x88, 0xca, 0x83, 0x83, 0x3f, 0xac, 0xf7, - 0x6d, 0x25, 0xcb, 0xca, 0x6f, 0x84, 0x03, 0xdb, 0x60, 0x2a, 0x6d, 0x5e, 0x2a, 0x92, 0x05, 0xd8, 0x75, 0xee, 0xef, - 0x8e, 0x87, 0xff, 0x52, 0xfa, 0x4c, 0x8b, 0x71, 0x15, 0x7f, 0x25, 0xd2, 0xd2, 0x43, 0x54, 0x41, 0x04, 0xd2, 0xca, - 0xba, 0xd4, 0x37, 0x1d, 0xbd, 0x9e, 0xd2, 0x54, 0xdc, 0xbe, 0x15, 0x42, 0x0d, 0xcd, 0x8b, 0xdc, 0x2a, 0x82, 0x47, - 0x0b, 0x6b, 0x0c, 0xcd, 0x7d, 0xe9, 0x9d, 0x64, 0x02, 0xa2, 0xd6, 0xc7, 0xed, 0x4b, 0x22, 0xa1, 0xac, 0xee, 0x42, - 0x38, 0xdc, 0x85, 0x60, 0x5e, 0x06, 0x6d, 0x83, 0xd8, 0xed, 0x36, 0x68, 0x5b, 0x28, 0x89, 0x34, 0x81, 0xdb, 0xbd, - 0xc1, 0xc2, 0xde, 0x87, 0x97, 0x63, 0x39, 0x96, 0xee, 0x9a, 0xcc, 0x3c, 0x00, 0x04, 0x6a, 0x1f, 0x56, 0x3c, 0xb1, - 0x20, 0x88, 0xac, 0xe1, 0xe8, 0x7b, 0xce, 0x6e, 0x8d, 0xe5, 0xf0, 0x6c, 0xbe, 0x50, 0x2c, 0xd5, 0x77, 0xd4, 0x80, - 0x3f, 0x75, 0x3f, 0xaf, 0x9f, 0x92, 0x9a, 0x6e, 0xfc, 0x01, 0x84, 0x91, 0xb0, 0xca, 0x0e, 0xad, 0x90, 0x30, 0xc1, - 0xac, 0xca, 0x78, 0x6d, 0xbf, 0x41, 0xbc, 0x07, 0xa5, 0xc3, 0x09, 0x16, 0xb5, 0x0b, 0xaa, 0x00, 0x9b, 0x78, 0x63, - 0x5e, 0x94, 0x87, 0x37, 0x5b, 0x46, 0xd3, 0xcb, 0x35, 0x04, 0x3a, 0xee, 0x07, 0xcd, 0xa0, 0xc1, 0x62, 0x1b, 0x94, - 0xd9, 0x45, 0x18, 0xcf, 0xcf, 0x4f, 0x74, 0x9c, 0xf6, 0x52, 0xaf, 0xfe, 0x5b, 0x02, 0x06, 0xf8, 0x12, 0xbc, 0xc4, - 0xfc, 0xe8, 0xae, 0x03, 0xd5, 0x80, 0xfa, 0xa2, 0xc1, 0x86, 0x68, 0xb5, 0x6a, 0x95, 0xcf, 0x40, 0xd9, 0x6b, 0x2e, - 0x69, 0xae, 0xb9, 0xa4, 0xbd, 0xe6, 0x92, 0xee, 0x9a, 0x4b, 0xea, 0x6b, 0x2e, 0xe9, 0xae, 0xb9, 0x1c, 0x08, 0x3f, - 0x79, 0x71, 0x1c, 0x43, 0x0e, 0x71, 0x15, 0x95, 0x89, 0x8c, 0x07, 0x17, 0x9e, 0xfb, 0x2c, 0x92, 0xe5, 0xf2, 0xfb, - 0x31, 0xe4, 0xb6, 0x6c, 0x25, 0xb4, 0xdb, 0x14, 0x93, 0x10, 0x39, 0xfd, 0xe0, 0xa0, 0x74, 0x77, 0x06, 0x1f, 0xf5, - 0x98, 0xe3, 0xa5, 0x71, 0xa2, 0xfd, 0x03, 0x74, 0xf2, 0xfa, 0xd7, 0xc7, 0x58, 0xac, 0x89, 0xb4, 0x26, 0xf7, 0xfb, - 0x6d, 0x47, 0x29, 0x3e, 0x25, 0x3a, 0x3c, 0x39, 0x8f, 0x94, 0x16, 0x41, 0x10, 0xa2, 0x24, 0xc7, 0x09, 0x11, 0x66, - 0xbf, 0x3b, 0x57, 0x78, 0xad, 0x8a, 0x72, 0x66, 0x25, 0x57, 0x19, 0x38, 0xb1, 0x6b, 0x2b, 0x0c, 0xd4, 0x03, 0x17, - 0x82, 0x44, 0x27, 0xfc, 0xd1, 0xcc, 0x0c, 0x39, 0x4b, 0xca, 0xa4, 0x8f, 0xcd, 0x4c, 0x13, 0xb0, 0x82, 0xec, 0x3b, - 0x98, 0x2d, 0xef, 0x62, 0x8a, 0xef, 0xe3, 0x04, 0xff, 0xbf, 0xec, 0xbd, 0xeb, 0x92, 0xdb, 0x46, 0x96, 0x2e, 0xfa, - 0x2a, 0x55, 0x0c, 0x99, 0x06, 0xc4, 0x24, 0x8b, 0xa5, 0xbd, 0x67, 0x22, 0x0e, 0x58, 0x29, 0x86, 0x2c, 0x59, 0xdd, - 0x72, 0x5b, 0x97, 0x56, 0xa9, 0xdd, 0x76, 0x33, 0x78, 0x68, 0x14, 0x90, 0x24, 0x20, 0x83, 0x00, 0x0d, 0x80, 0x55, - 0xa4, 0x48, 0xbc, 0xfb, 0x8e, 0xb5, 0x56, 0x5e, 0x41, 0xb0, 0xa4, 0x9e, 0xd9, 0xf3, 0xeb, 0x9c, 0x3f, 0x52, 0x31, - 0x91, 0x48, 0xe4, 0x3d, 0x57, 0xae, 0xcb, 0xf7, 0xdd, 0x15, 0xbb, 0xa0, 0xb4, 0x7d, 0x41, 0x94, 0xe1, 0x6f, 0xe9, - 0xf5, 0xf2, 0x10, 0xe2, 0x7d, 0x7a, 0x69, 0x7e, 0x91, 0xb6, 0xa2, 0x00, 0x0f, 0x11, 0x7a, 0x54, 0x07, 0x82, 0x9d, - 0xf1, 0x84, 0x07, 0x70, 0xb2, 0x9a, 0xe5, 0xfc, 0x49, 0x0a, 0xe2, 0x44, 0xc1, 0x21, 0xe0, 0x6a, 0x77, 0x9b, 0x7e, - 0x01, 0xc3, 0x97, 0x0e, 0xb6, 0x1c, 0xde, 0x15, 0xbb, 0x1e, 0x2b, 0xf9, 0x07, 0x60, 0xdf, 0xea, 0xc9, 0x58, 0xdd, - 0x1e, 0x38, 0xeb, 0x52, 0x8a, 0x8e, 0x37, 0xc5, 0xe1, 0xed, 0xf9, 0xec, 0xb0, 0x0b, 0x22, 0xb6, 0x0f, 0x32, 0xac, - 0x75, 0xd2, 0xf0, 0x9f, 0x68, 0xeb, 0x60, 0x31, 0xc2, 0xfe, 0x2f, 0xeb, 0x81, 0x97, 0x90, 0x1a, 0x0a, 0x5c, 0x0c, - 0xb6, 0x1c, 0xad, 0xed, 0x32, 0x0d, 0xdc, 0xd4, 0xa0, 0xd7, 0x0f, 0x14, 0xa2, 0xbc, 0x64, 0x34, 0x37, 0x82, 0x4d, - 0x63, 0xc8, 0xc5, 0xe1, 0xb8, 0x59, 0x0e, 0x79, 0x49, 0xd3, 0x69, 0x10, 0x4a, 0x77, 0x96, 0x0d, 0x24, 0x51, 0xf6, - 0x41, 0xa8, 0x5d, 0x5b, 0x0e, 0xbb, 0xc0, 0xf6, 0xe5, 0x8f, 0x86, 0xb1, 0x7f, 0xb5, 0x7c, 0x2a, 0xa4, 0x8b, 0x78, - 0x05, 0x82, 0xa8, 0xfd, 0x3c, 0x1b, 0x6e, 0xfd, 0xab, 0xcd, 0x53, 0xa1, 0xfc, 0xc6, 0x2b, 0x5b, 0x0e, 0xa9, 0xb3, - 0x16, 0xbe, 0x30, 0x1e, 0x1e, 0x5c, 0x19, 0xda, 0x8e, 0x47, 0xa1, 0xff, 0x36, 0x6b, 0x04, 0x37, 0x36, 0xb4, 0xcf, - 0x17, 0x3e, 0x6c, 0x6d, 0x34, 0xd6, 0x14, 0xd3, 0x2d, 0xf4, 0x6f, 0x32, 0x5b, 0xda, 0xd3, 0xa8, 0xe4, 0xc5, 0xb9, - 0x69, 0xc4, 0x42, 0x18, 0x30, 0xf4, 0x93, 0xf9, 0x00, 0xaa, 0xb9, 0xd3, 0x11, 0xc8, 0xe4, 0x03, 0x3d, 0x58, 0x93, - 0x5a, 0xf5, 0xd7, 0x30, 0x93, 0xff, 0x47, 0x2a, 0x2c, 0x46, 0x77, 0xdb, 0x30, 0x53, 0x7f, 0x44, 0xf2, 0x0f, 0x56, - 0xf1, 0x7d, 0xea, 0x85, 0xda, 0x8f, 0x85, 0x15, 0x18, 0x94, 0xa8, 0x1a, 0xd0, 0x03, 0x11, 0x54, 0x65, 0x90, 0x66, - 0x58, 0x9d, 0x83, 0x7e, 0xf7, 0xb4, 0xea, 0x48, 0x0e, 0x69, 0xad, 0x86, 0x54, 0x30, 0x55, 0x6a, 0x50, 0x1d, 0x8f, - 0xab, 0x94, 0xe9, 0x32, 0xe0, 0x92, 0xbe, 0x4a, 0x95, 0x52, 0xf8, 0x4f, 0x04, 0xa0, 0x73, 0x70, 0x8f, 0xaf, 0xc7, - 0x40, 0x9a, 0x61, 0xe1, 0xb7, 0x66, 0xa7, 0xd7, 0x24, 0xdc, 0x26, 0xc1, 0xc5, 0x00, 0xe7, 0xe8, 0x3a, 0x2c, 0x57, - 0x29, 0x44, 0x50, 0x95, 0x50, 0xdf, 0xdc, 0x34, 0x28, 0x6d, 0x35, 0x08, 0x6b, 0x12, 0xea, 0x4c, 0xb2, 0x51, 0x69, - 0xbb, 0x51, 0x98, 0x2d, 0xe2, 0x7a, 0x46, 0x58, 0x73, 0x36, 0x53, 0x0d, 0x4c, 0x1a, 0x8e, 0x9b, 0x46, 0x6b, 0x51, - 0xa1, 0xa6, 0x30, 0xaf, 0x71, 0x55, 0xa9, 0xea, 0x6e, 0xcf, 0x2d, 0xa5, 0x65, 0x7b, 0xd5, 0x4d, 0xb2, 0x21, 0x97, - 0xa1, 0x0c, 0x83, 0xad, 0x1c, 0xc1, 0x04, 0x92, 0xe4, 0xcc, 0xdf, 0xca, 0x3f, 0xd4, 0xa6, 0x6b, 0x01, 0x73, 0x8c, - 0x59, 0x36, 0x2c, 0xe8, 0x15, 0xb8, 0x07, 0x5a, 0xe9, 0xd5, 0x34, 0xbb, 0xaa, 0x82, 0x64, 0x58, 0xe8, 0x65, 0x93, - 0xf1, 0x3f, 0x85, 0x91, 0x26, 0x33, 0x56, 0xb2, 0xc8, 0x76, 0x75, 0x4a, 0x9c, 0xc7, 0x09, 0x6c, 0x8f, 0xa6, 0xb7, - 0x7c, 0x9f, 0x41, 0x54, 0x10, 0x28, 0x98, 0x31, 0x5f, 0x76, 0xf5, 0xcc, 0xf7, 0x99, 0x65, 0xea, 0x3e, 0x1e, 0x8d, - 0x19, 0xdb, 0xef, 0xf7, 0xab, 0x7e, 0x5f, 0xcd, 0xb7, 0x7e, 0x3f, 0x79, 0x6e, 0xfe, 0xf6, 0x80, 0x41, 0x41, 0x4e, - 0x44, 0x53, 0x21, 0x82, 0x7f, 0x48, 0x9e, 0x22, 0x19, 0xdd, 0x69, 0x9f, 0x5b, 0xce, 0x96, 0xf9, 0x09, 0x08, 0xe6, - 0xf1, 0x78, 0xad, 0xc0, 0xae, 0x25, 0x8a, 0x84, 0x2c, 0xff, 0x29, 0x18, 0xcf, 0xdc, 0x07, 0x58, 0x32, 0x00, 0x61, - 0xab, 0x3c, 0x5d, 0xef, 0xf9, 0x2a, 0x78, 0xa7, 0xe3, 0x5d, 0x63, 0x45, 0x06, 0xe2, 0x16, 0xd8, 0x88, 0xb5, 0xf6, - 0x80, 0x9c, 0x29, 0xc0, 0xf1, 0xe2, 0x78, 0xbc, 0x94, 0xbf, 0x74, 0xb3, 0x75, 0x02, 0x95, 0x02, 0xb7, 0x47, 0x27, - 0x07, 0xff, 0x1d, 0x68, 0x06, 0xe5, 0x30, 0x6f, 0x76, 0xbf, 0x33, 0x27, 0x3f, 0x3d, 0xc5, 0x3f, 0xe1, 0x21, 0x3a, - 0xfd, 0x76, 0x6f, 0xfe, 0xa0, 0xa8, 0x3c, 0x1e, 0xd5, 0xe2, 0x07, 0x9e, 0x1f, 0xf8, 0x85, 0x6f, 0x02, 0xb3, 0xc9, - 0xd4, 0x3b, 0xfb, 0x26, 0xaf, 0x98, 0x7a, 0x8d, 0xe7, 0x4c, 0xbe, 0xc3, 0xe1, 0x5c, 0x8c, 0xea, 0xdd, 0xc8, 0x89, - 0x76, 0xaa, 0x30, 0x0e, 0x06, 0xff, 0x45, 0xb4, 0x4d, 0x08, 0x30, 0xa4, 0x6e, 0x49, 0x33, 0x1b, 0x57, 0x96, 0x78, - 0x96, 0x2e, 0xaf, 0x27, 0x75, 0xb9, 0xd7, 0x8a, 0xa7, 0x03, 0xb0, 0xb8, 0x6d, 0xc0, 0x0b, 0xe0, 0xde, 0x62, 0xeb, - 0x4a, 0xc1, 0xe1, 0x02, 0xe2, 0x14, 0x27, 0x20, 0x82, 0xf6, 0xfb, 0x12, 0xef, 0x15, 0xf4, 0x49, 0x3f, 0x42, 0x30, - 0xe4, 0xcf, 0x12, 0x70, 0xd7, 0xeb, 0xd5, 0x18, 0xdf, 0x4b, 0x21, 0xb8, 0x3e, 0xd3, 0x00, 0xb4, 0xe0, 0x77, 0xf9, - 0x58, 0x4e, 0xbf, 0x89, 0xc0, 0xb3, 0xe5, 0x60, 0xa2, 0xdc, 0x6d, 0x78, 0xda, 0x3f, 0x5a, 0x08, 0xc0, 0x52, 0x3c, - 0x53, 0x82, 0x05, 0x39, 0xc5, 0x5c, 0xfd, 0xbf, 0xe0, 0x23, 0xe6, 0x7b, 0xd2, 0x45, 0x6c, 0xb3, 0x7b, 0x72, 0x65, - 0x20, 0x81, 0xa6, 0x03, 0xe0, 0x21, 0x54, 0x40, 0x57, 0xc6, 0xcf, 0xcf, 0xb2, 0x1e, 0xeb, 0xe3, 0x3f, 0x05, 0xf7, - 0xe9, 0xa7, 0x0a, 0x1f, 0x1d, 0x8e, 0xab, 0x74, 0xb4, 0xa7, 0x14, 0x44, 0x47, 0xb7, 0xcf, 0xa7, 0x2a, 0xfb, 0xa6, - 0x02, 0x2a, 0xcb, 0x51, 0x7b, 0x2a, 0x00, 0x8b, 0x2d, 0x1d, 0x81, 0x4f, 0xb3, 0x7c, 0x42, 0xbe, 0xd7, 0x53, 0x71, - 0x73, 0xad, 0xd3, 0xc5, 0xf3, 0xf1, 0x14, 0xfe, 0x07, 0x62, 0x0f, 0xcb, 0x14, 0xd9, 0xb1, 0xeb, 0xe2, 0x07, 0xf1, - 0xb6, 0xb6, 0xa7, 0x3f, 0xf6, 0x10, 0xe9, 0x78, 0x20, 0x17, 0xea, 0x6b, 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, 0x56, 0xb6, 0xc8, 0xb8, 0x7a, 0x14, 0x52, 0x35, 0x3d, 0xdc, 0x89, 0xfa, 0x41, 0x88, 0x3c, 0x58, 0xa7, 0x2c, - 0x2a, 0xd6, 0x20, 0xb3, 0x07, 0x7f, 0x0f, 0x19, 0x39, 0xca, 0x81, 0xa3, 0xd0, 0x5f, 0x9a, 0x40, 0xe7, 0xf9, 0x29, - 0xd4, 0x79, 0x24, 0xd8, 0x4a, 0x3d, 0x14, 0x56, 0x5e, 0x40, 0x74, 0xb0, 0x85, 0xb1, 0xdc, 0x93, 0x50, 0xb1, 0x29, - 0x13, 0x79, 0x1c, 0xd4, 0x12, 0x30, 0x56, 0x10, 0xcc, 0x59, 0x25, 0x5d, 0x90, 0xf2, 0x46, 0x0f, 0x8b, 0xcc, 0xfd, - 0x9d, 0xa0, 0xfc, 0xdf, 0xa9, 0x9c, 0x70, 0x7d, 0x19, 0x02, 0x1c, 0xed, 0x77, 0x20, 0x4a, 0x8c, 0xf5, 0x8b, 0x16, - 0xef, 0x64, 0xe6, 0x6c, 0x6a, 0x07, 0x09, 0x32, 0xb6, 0xc7, 0xaf, 0x10, 0x5a, 0x2d, 0x14, 0x59, 0x34, 0x5c, 0x30, - 0xdd, 0x9e, 0xd2, 0xaa, 0x7b, 0xd8, 0xf0, 0xac, 0xf4, 0x50, 0xa9, 0x6f, 0x63, 0x02, 0xcb, 0x2a, 0x65, 0xf8, 0x76, - 0x42, 0xd5, 0x89, 0x41, 0xc5, 0xba, 0x65, 0x4b, 0x38, 0xc4, 0x62, 0xd2, 0x58, 0x67, 0x03, 0x1e, 0xb1, 0x04, 0xfe, - 0xd9, 0xf2, 0x31, 0x5b, 0xf2, 0x68, 0xb2, 0xbd, 0x59, 0xf6, 0xfb, 0xa5, 0x17, 0x7a, 0xf5, 0x2c, 0xfb, 0x2e, 0x9a, - 0xcf, 0xaa, 0xb9, 0x8f, 0x8a, 0x8b, 0xc9, 0x60, 0xb0, 0xf5, 0xb3, 0xe1, 0x90, 0x25, 0xc3, 0xe1, 0x24, 0xfb, 0x0e, - 0x5e, 0xfb, 0x8e, 0x47, 0x6a, 0x49, 0x25, 0x37, 0x19, 0xec, 0xef, 0x03, 0x1e, 0xf9, 0xac, 0xf3, 0xd3, 0xb2, 0xe9, - 0xd2, 0xfd, 0xcc, 0x8e, 0xbb, 0xd0, 0x1d, 0x60, 0xe3, 0x6d, 0x83, 0x8e, 0xfc, 0xeb, 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, 0x65, 0xe5, 0x96, 0x0d, 0xd7, 0xc3, 0xc1, 0x36, 0x8a, 0xcb, 0x66, 0x05, 0xf7, 0x85, 0x35, 0x05, 0xfe, - 0xdf, 0xb1, 0x05, 0xbb, 0x97, 0xc7, 0xc0, 0x5b, 0x74, 0x4c, 0x82, 0x0b, 0xc4, 0x3d, 0xbb, 0x03, 0x3b, 0x2c, 0xfc, - 0x05, 0xd7, 0xc9, 0x31, 0xdb, 0xe3, 0xa3, 0xd0, 0x2b, 0xd8, 0x9d, 0x4f, 0x40, 0xbb, 0x60, 0x6b, 0x80, 0x6c, 0x6c, - 0x87, 0x8f, 0x56, 0xc7, 0xe3, 0x5b, 0xcf, 0x67, 0x0f, 0xf8, 0xe3, 0x72, 0x75, 0x3c, 0xee, 0x3d, 0xa3, 0xde, 0xbb, - 0xe5, 0x09, 0x7b, 0xcf, 0x93, 0xc9, 0xed, 0x0d, 0x8f, 0x27, 0x83, 0xc1, 0xad, 0xbf, 0xe0, 0xf5, 0xec, 0x16, 0xb4, - 0x03, 0x97, 0x0b, 0xa9, 0x6b, 0xf6, 0xee, 0x78, 0xe6, 0x2d, 0x70, 0x6c, 0xee, 0xe0, 0xe8, 0xed, 0xf7, 0xbd, 0x15, - 0x8f, 0xbc, 0x3b, 0x52, 0x31, 0xad, 0xb9, 0xe2, 0x78, 0xdb, 0xe1, 0x7e, 0xba, 0xe6, 0x21, 0x3c, 0xc2, 0xaa, 0x4c, - 0x6f, 0x83, 0xf7, 0x3e, 0x5b, 0x6b, 0x16, 0xb8, 0x07, 0xcc, 0xb1, 0x21, 0x3b, 0xa1, 0x99, 0xf8, 0x6b, 0xec, 0x9f, - 0x5b, 0xd5, 0x3f, 0x34, 0xff, 0x4b, 0xdd, 0x4f, 0xe0, 0xf6, 0x45, 0x16, 0x24, 0xf6, 0x9e, 0xdf, 0xb2, 0x7b, 0x6e, - 0xd8, 0x66, 0x2f, 0x4c, 0xd9, 0x67, 0x4a, 0x8d, 0x1f, 0x29, 0x75, 0x63, 0x19, 0x56, 0x32, 0x77, 0x5f, 0x46, 0xe0, - 0x70, 0x40, 0x7e, 0x5a, 0x21, 0x0e, 0x42, 0xeb, 0x26, 0xab, 0xb9, 0xa2, 0x9c, 0x0b, 0x6d, 0x99, 0x79, 0x15, 0xb0, - 0x98, 0xa5, 0x14, 0x1a, 0x0b, 0x00, 0x04, 0x93, 0x42, 0x6b, 0xef, 0x65, 0x00, 0x39, 0x41, 0xc3, 0x9f, 0x9a, 0xab, - 0xa2, 0xac, 0x65, 0x4b, 0x42, 0x94, 0xed, 0x7a, 0x78, 0x8d, 0x90, 0x69, 0xfd, 0xfe, 0x25, 0x91, 0xac, 0x4d, 0xf2, - 0x9b, 0x1a, 0x2d, 0x01, 0x39, 0x59, 0x02, 0x26, 0x7e, 0xae, 0xf9, 0x04, 0xe0, 0x49, 0xc7, 0x83, 0xfc, 0x3b, 0x5e, - 0x33, 0x41, 0x64, 0x1b, 0xb9, 0x3f, 0x29, 0x9e, 0x23, 0x19, 0x41, 0xf1, 0x5d, 0xad, 0x32, 0x16, 0x86, 0x79, 0xa0, - 0x80, 0xbc, 0x07, 0x77, 0xea, 0x5b, 0xfb, 0x63, 0xc7, 0x9e, 0xad, 0x55, 0xa8, 0x85, 0x9a, 0xc2, 0x25, 0x87, 0xe8, - 0x0a, 0x32, 0x50, 0xc8, 0x78, 0xf2, 0x7a, 0x70, 0x3d, 0x89, 0x6e, 0xb8, 0x40, 0x67, 0x7c, 0x7d, 0xd3, 0x4d, 0x67, - 0xd1, 0x77, 0xf9, 0x7c, 0x42, 0x4a, 0xb2, 0xe3, 0x31, 0x1b, 0x55, 0x75, 0xb1, 0x99, 0x86, 0xf2, 0xa7, 0x87, 0xe0, - 0xeb, 0x05, 0xf5, 0x9a, 0xac, 0x52, 0xfd, 0x1d, 0x55, 0xca, 0x8b, 0x86, 0xd7, 0xfe, 0x77, 0xb9, 0xdc, 0xf7, 0x80, - 0xb4, 0x96, 0x97, 0x5c, 0xbe, 0x1f, 0x21, 0xc6, 0x88, 0x1f, 0x78, 0x25, 0x8f, 0x58, 0xa8, 0xa6, 0x70, 0xcd, 0x23, - 0x04, 0x79, 0xcb, 0x74, 0xf0, 0xb7, 0x9e, 0x38, 0xdd, 0x9f, 0x28, 0xed, 0xe2, 0x0b, 0x8b, 0xba, 0x27, 0x6b, 0xeb, - 0x06, 0xe4, 0x60, 0xc3, 0x74, 0x51, 0x90, 0x6d, 0x4a, 0x23, 0x68, 0xa3, 0xe5, 0xc0, 0x86, 0x93, 0xab, 0x0d, 0x67, - 0xae, 0x21, 0xb8, 0x2f, 0x2f, 0xd3, 0xd1, 0x02, 0x3e, 0xa4, 0xba, 0xbd, 0xc4, 0xcf, 0x87, 0x0d, 0x8f, 0x80, 0xcc, - 0x8e, 0xf8, 0xcc, 0x26, 0x92, 0x4e, 0xea, 0x52, 0x01, 0xbb, 0x5d, 0xbc, 0x05, 0x39, 0x62, 0xe6, 0xbe, 0x42, 0xf5, - 0x2d, 0x1a, 0x70, 0x65, 0xac, 0x7d, 0x4d, 0x32, 0x16, 0xde, 0x94, 0xd3, 0x70, 0x90, 0xc3, 0x73, 0xfa, 0xda, 0x72, - 0x9b, 0x65, 0x3f, 0x17, 0x10, 0x04, 0x51, 0x12, 0x8f, 0x0f, 0x78, 0x5f, 0xe6, 0x43, 0x8d, 0x92, 0x8f, 0x65, 0x23, - 0x95, 0x5e, 0x89, 0xfe, 0x6e, 0xcc, 0x25, 0x06, 0x7c, 0x9b, 0xb7, 0x05, 0x85, 0xcb, 0xea, 0x78, 0xbc, 0xac, 0x46, - 0xc6, 0xb3, 0x0c, 0x54, 0x2b, 0xd3, 0x3a, 0x88, 0xcd, 0x7c, 0xb1, 0xf0, 0x17, 0x3b, 0x27, 0x11, 0x51, 0x10, 0xd8, - 0x91, 0xf0, 0x20, 0x52, 0xbf, 0xcc, 0x3d, 0xdd, 0xa9, 0x3e, 0x3b, 0x2c, 0x6c, 0x22, 0xbd, 0xa0, 0x64, 0xf2, 0x49, - 0x70, 0x50, 0xfd, 0x1d, 0x84, 0x0d, 0xe1, 0xcd, 0xab, 0x5e, 0x67, 0x99, 0x9a, 0x95, 0x20, 0x61, 0xc6, 0x1c, 0xc1, - 0xe3, 0xb0, 0xd3, 0xd8, 0x96, 0xc7, 0x16, 0x1c, 0x9d, 0xb7, 0x61, 0x2b, 0xb6, 0x66, 0x77, 0xaa, 0x4e, 0x0b, 0x1e, - 0x4e, 0x87, 0xd7, 0x01, 0xae, 0xbe, 0xcd, 0x25, 0xe7, 0x2b, 0x3a, 0xc1, 0x36, 0x03, 0x1e, 0x4d, 0xc4, 0x6c, 0xf3, - 0x5d, 0xa4, 0x16, 0xcf, 0x66, 0xc8, 0x17, 0xb4, 0xfe, 0xc4, 0x6c, 0x65, 0x92, 0x57, 0x03, 0xbe, 0x98, 0x6c, 0xbe, - 0x8b, 0xe0, 0xd5, 0xef, 0xc0, 0x8a, 0x91, 0x39, 0xb3, 0x6c, 0xf3, 0x5d, 0x84, 0x63, 0xb6, 0xfa, 0x2e, 0xa2, 0x51, - 0x5b, 0xcb, 0x7d, 0xe9, 0xae, 0x01, 0x61, 0xe5, 0x8e, 0xc5, 0xf0, 0x1a, 0x88, 0x67, 0xda, 0x48, 0xba, 0x91, 0x86, - 0xde, 0x98, 0x87, 0xd3, 0x38, 0xd8, 0x50, 0x2b, 0xe4, 0x99, 0x21, 0x66, 0xf1, 0x77, 0xd1, 0x9c, 0xad, 0xb1, 0x22, - 0x5b, 0x1e, 0x0f, 0xae, 0x27, 0xdb, 0x1b, 0xbe, 0x01, 0xf2, 0xb3, 0xc9, 0xd6, 0x6c, 0x51, 0x77, 0x5c, 0xcc, 0xb6, - 0xdf, 0x45, 0xf3, 0xc9, 0x1a, 0x7a, 0xd6, 0x1e, 0x30, 0xef, 0x35, 0x88, 0x50, 0x12, 0x52, 0x53, 0x6e, 0x7a, 0x3d, - 0xb6, 0x19, 0x07, 0x2b, 0xb6, 0xb9, 0x0e, 0xee, 0xd8, 0x66, 0x0c, 0x44, 0x1c, 0xd4, 0xef, 0xde, 0x16, 0x16, 0x5f, - 0xc4, 0x36, 0xd7, 0x26, 0x6d, 0xfb, 0x5d, 0xc4, 0xdc, 0xc1, 0x69, 0xe0, 0x82, 0xb5, 0xcd, 0xbc, 0x35, 0x83, 0x4b, - 0xc8, 0xd2, 0x8b, 0xd9, 0x76, 0x78, 0xcd, 0x36, 0x23, 0x9c, 0xea, 0x89, 0xcf, 0x56, 0xfc, 0x8e, 0x25, 0x7c, 0xdd, - 0xc4, 0x37, 0x5b, 0xd0, 0x88, 0x9e, 0x64, 0xd0, 0x57, 0x50, 0x33, 0x73, 0x5e, 0x5a, 0x50, 0xb9, 0x87, 0x16, 0x1c, - 0x50, 0x90, 0xb6, 0x01, 0x82, 0x24, 0x9e, 0xdd, 0xcb, 0x70, 0x73, 0x2b, 0x85, 0x01, 0x37, 0x81, 0x19, 0x30, 0x30, - 0xfd, 0x0c, 0x7e, 0x58, 0xe9, 0x12, 0x21, 0xce, 0x7e, 0x4a, 0x49, 0x32, 0xcf, 0x4f, 0x45, 0x9a, 0xbb, 0x85, 0xeb, - 0x14, 0x66, 0x45, 0x81, 0xea, 0xa7, 0xa4, 0x34, 0xb0, 0x50, 0x89, 0x4c, 0xa5, 0xe0, 0x97, 0xcd, 0x79, 0x94, 0x9d, - 0xa2, 0x73, 0x5d, 0x5e, 0x4f, 0x9c, 0xd3, 0x49, 0xdf, 0x7f, 0xe0, 0x18, 0xb6, 0x90, 0x81, 0x0b, 0x7f, 0xea, 0x09, - 0xe3, 0xd4, 0x0a, 0xc4, 0x54, 0xf2, 0xec, 0x29, 0x7c, 0x26, 0xb4, 0x3a, 0xba, 0xf0, 0xfd, 0xa0, 0xd0, 0x26, 0xe9, - 0x16, 0x24, 0x29, 0x78, 0x8a, 0x5e, 0x72, 0xde, 0x06, 0x2a, 0xc5, 0x88, 0x16, 0x44, 0xda, 0x5a, 0x66, 0x0e, 0xd2, - 0x96, 0xe6, 0xbb, 0x26, 0x7e, 0x0e, 0x0b, 0xb8, 0x88, 0x16, 0x76, 0xa5, 0xe0, 0x51, 0x15, 0x2b, 0xf7, 0x36, 0xcf, - 0x11, 0xce, 0xe8, 0x5a, 0x26, 0x00, 0xae, 0xf7, 0xab, 0xb0, 0x56, 0x78, 0x45, 0xcd, 0x22, 0x2f, 0x6a, 0xfa, 0x64, - 0x0b, 0xdc, 0xc7, 0xa2, 0x44, 0x81, 0xb3, 0x16, 0x0c, 0xd8, 0x0a, 0x4b, 0x76, 0x52, 0xd8, 0x14, 0x2d, 0xa1, 0x77, - 0xc0, 0x4f, 0x07, 0x35, 0x93, 0x01, 0x34, 0x01, 0x34, 0x1e, 0xff, 0x02, 0x50, 0xd3, 0xdb, 0x5a, 0x6c, 0xaa, 0xa0, - 0x54, 0xca, 0x4d, 0xf8, 0x19, 0x18, 0x66, 0xf8, 0xa1, 0x90, 0xdb, 0x44, 0x89, 0x9c, 0x1f, 0x8b, 0x52, 0x2c, 0x4b, - 0x51, 0x25, 0xed, 0x86, 0x82, 0x47, 0x84, 0xdb, 0xa0, 0x31, 0x73, 0x7b, 0xa2, 0x8b, 0x56, 0x84, 0x72, 0x6c, 0x37, - 0x31, 0xd2, 0x28, 0xb3, 0xb3, 0x5d, 0x27, 0x0b, 0xed, 0xf7, 0x55, 0x0e, 0x59, 0x07, 0xac, 0x91, 0x7c, 0xbd, 0xe6, - 0xd0, 0x6d, 0xa3, 0xbc, 0x78, 0xf0, 0x7c, 0x05, 0xa7, 0x39, 0x9e, 0xd8, 0x5d, 0xaf, 0x3b, 0x45, 0x22, 0x5e, 0xe1, - 0xa4, 0xaa, 0x46, 0xb2, 0x70, 0xdc, 0xb9, 0xd3, 0x5a, 0xac, 0x95, 0x4c, 0xe3, 0x72, 0xd0, 0x00, 0xd0, 0x0c, 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, 0xf3, 0x4a, - 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, 0xce, 0x00, 0x3f, 0x0a, 0xc8, 0x47, 0x09, 0xb8, 0x19, 0x20, 0x7b, 0x64, 0x09, 0x20, 0x56, - 0x8c, 0x4e, 0x26, 0x9f, 0xfb, 0x5e, 0xa4, 0xe0, 0x9d, 0x7d, 0x56, 0xa9, 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, - 0x94, 0x64, 0x9b, 0x86, 0x48, 0x06, 0xcc, 0x88, 0x11, 0x41, 0x65, 0xb9, 0xf0, 0xbf, 0x07, 0x59, 0x14, 0x38, 0x80, - 0xab, 0x99, 0x0c, 0x5e, 0xbb, 0x30, 0x2a, 0x00, 0xce, 0x69, 0xe8, 0x94, 0x0e, 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, 0x4f, 0x5f, - 0xa7, 0xe9, 0xa4, 0xc4, 0x5d, 0xe1, 0x37, 0xe0, 0xa2, 0xd9, 0xe6, 0x43, 0x3f, 0x7d, 0x41, 0x11, 0x17, 0x35, 0xb8, - 0xf2, 0xce, 0xf5, 0x95, 0xea, 0x23, 0xa8, 0x85, 0x27, 0x46, 0xd6, 0xc2, 0x93, 0x4b, 0xd6, 0x5a, 0x10, 0xcc, 0x6c, - 0x0e, 0x5c, 0xc8, 0xaf, 0x94, 0x22, 0xde, 0x46, 0x42, 0x2d, 0x06, 0xad, 0xc7, 0xac, 0x58, 0x3e, 0x5a, 0xa8, 0xcc, - 0x08, 0xed, 0xdb, 0x5a, 0x74, 0x7e, 0x23, 0x3f, 0xe5, 0xa9, 0x7d, 0xd9, 0x1e, 0xe7, 0xd3, 0x3d, 0xba, 0xab, 0xce, - 0x32, 0x93, 0x32, 0x3e, 0x99, 0x25, 0x28, 0xdc, 0x25, 0xd8, 0x80, 0x24, 0xfb, 0xb5, 0x0e, 0x90, 0x51, 0x7b, 0xed, - 0x77, 0x9d, 0xe5, 0x5b, 0xa9, 0x66, 0x6b, 0x28, 0x2a, 0xb5, 0x92, 0x14, 0x07, 0x19, 0xae, 0xdb, 0xdc, 0x87, 0xcd, - 0x14, 0xf4, 0x8c, 0x91, 0xc8, 0x3c, 0x7f, 0x22, 0x5f, 0x82, 0x73, 0xc6, 0x59, 0x21, 0x30, 0x61, 0xac, 0xde, 0xb5, - 0x96, 0x4a, 0x43, 0x8a, 0xb1, 0x93, 0x51, 0x96, 0x55, 0x96, 0x2e, 0xb3, 0xb5, 0x84, 0x2d, 0xab, 0xc8, 0x2d, 0x6c, - 0x99, 0xc9, 0x6a, 0xbe, 0xcf, 0xb9, 0x83, 0xf2, 0xcd, 0x36, 0x19, 0x3f, 0x48, 0x64, 0xef, 0x36, 0x50, 0xc2, 0xf3, - 0xd1, 0x7f, 0x20, 0xfd, 0x36, 0xc3, 0x38, 0xe5, 0xb6, 0x92, 0x16, 0xe0, 0xf4, 0x8f, 0xc7, 0xf7, 0x39, 0x06, 0x0d, - 0x8e, 0x30, 0x8e, 0xac, 0xdf, 0xbf, 0xcb, 0xbd, 0x1a, 0x13, 0x75, 0xf4, 0x42, 0xbf, 0x9f, 0xd3, 0xc3, 0x69, 0x3e, - 0x5a, 0xa7, 0x3b, 0x64, 0x27, 0xb4, 0xb1, 0xf2, 0x83, 0x5a, 0x01, 0xb3, 0xb7, 0x3e, 0x9f, 0x0e, 0x40, 0xc7, 0x02, - 0x24, 0x9a, 0xcd, 0x44, 0x62, 0x4e, 0xba, 0x27, 0xe1, 0xe9, 0x81, 0x05, 0x0e, 0x30, 0x39, 0xff, 0x87, 0xf0, 0x66, - 0x60, 0x83, 0x46, 0x89, 0xbe, 0x46, 0x57, 0xb5, 0xb9, 0xd1, 0xf1, 0xd2, 0x53, 0x48, 0x64, 0x05, 0xcb, 0xe7, 0xbe, - 0xdc, 0xc0, 0x69, 0x0f, 0x35, 0x87, 0xca, 0x12, 0x3c, 0x3d, 0x97, 0xf9, 0xf1, 0xb8, 0xc9, 0xa0, 0xb0, 0xfd, 0x46, - 0x68, 0x6f, 0xcc, 0x52, 0x0d, 0x15, 0xe1, 0xa0, 0xf3, 0xb5, 0x98, 0xd5, 0x23, 0xfa, 0x7b, 0x7e, 0x3c, 0xae, 0x09, - 0x0c, 0x38, 0x2c, 0x65, 0x26, 0x5a, 0x28, 0x96, 0xd6, 0xd9, 0x8c, 0xea, 0xc0, 0x03, 0x13, 0x73, 0x16, 0xee, 0x01, - 0xb4, 0x49, 0xad, 0x02, 0xbd, 0x8a, 0xe8, 0x27, 0xee, 0xd7, 0xf6, 0xeb, 0xf5, 0xc8, 0x2c, 0x1d, 0xb9, 0x31, 0x16, - 0x00, 0x1c, 0x78, 0x59, 0x93, 0x3c, 0x27, 0x5f, 0x43, 0xbb, 0x27, 0x17, 0xf2, 0x27, 0x28, 0x5b, 0x78, 0xa5, 0x9a, - 0x56, 0x16, 0x6b, 0xae, 0xaa, 0x57, 0x17, 0x3c, 0x37, 0x99, 0xd6, 0x69, 0x25, 0x54, 0xac, 0x5f, 0x43, 0x5d, 0xe2, - 0xb5, 0xa6, 0x19, 0xa5, 0x36, 0xea, 0x4c, 0xd4, 0x80, 0x0d, 0xf6, 0x53, 0xb5, 0xd1, 0xc9, 0xb9, 0x7c, 0x79, 0x6d, - 0x1c, 0x3e, 0xed, 0xea, 0xcd, 0x4c, 0xe5, 0xc0, 0x5f, 0xab, 0x1a, 0x5a, 0x3d, 0x06, 0x3a, 0x20, 0xa7, 0x3f, 0x86, - 0xc5, 0xc4, 0xee, 0xd0, 0xaa, 0xdd, 0x5d, 0x56, 0x17, 0xe9, 0x9d, 0xa6, 0x64, 0x56, 0x6f, 0xf9, 0xcc, 0xea, 0xd1, - 0x01, 0x2f, 0x1e, 0xeb, 0xbd, 0xc2, 0x4c, 0x22, 0xb8, 0x18, 0xaa, 0x49, 0x64, 0x77, 0xa0, 0x35, 0x8f, 0x72, 0x26, - 0xc0, 0x0f, 0x4a, 0xad, 0xe9, 0x83, 0xdd, 0x15, 0xea, 0x94, 0xc2, 0xe3, 0xd6, 0x92, 0x1f, 0x98, 0x3b, 0xed, 0x5a, - 0xe7, 0xe3, 0xe5, 0xb5, 0xef, 0x37, 0xf2, 0x84, 0x36, 0x3b, 0x93, 0xd3, 0x3f, 0x55, 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, 0xc7, 0xa3, 0xb8, 0xa9, 0x7c, 0x76, 0xd9, 0x35, 0xb2, 0x72, 0x00, 0x73, 0x88, - 0x82, 0x71, 0x6b, 0x3e, 0xb6, 0x41, 0xba, 0xc4, 0xcd, 0xf8, 0xf4, 0x0d, 0xc5, 0x32, 0xd9, 0x44, 0x5c, 0x5c, 0x55, - 0xdf, 0x3d, 0x03, 0xd2, 0xb2, 0x7e, 0x3f, 0x7a, 0x7e, 0x3d, 0x7d, 0x36, 0x8c, 0x02, 0x70, 0xec, 0xb2, 0x97, 0x97, - 0x31, 0x5f, 0x5d, 0x33, 0xcb, 0x14, 0x16, 0xf9, 0x66, 0x40, 0x75, 0xc9, 0x6a, 0xe9, 0x7a, 0x05, 0x58, 0xba, 0xfc, - 0xe6, 0x21, 0x4c, 0x0d, 0x68, 0x64, 0xcd, 0xdd, 0x69, 0xae, 0x05, 0x4a, 0x3d, 0xef, 0x67, 0x86, 0x7c, 0x5d, 0x06, - 0x5d, 0x41, 0xba, 0xe7, 0x11, 0xe9, 0xe5, 0x41, 0x3a, 0xdd, 0x1f, 0x4a, 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, 0xa3, 0xe6, 0x82, 0x13, 0x62, 0x26, 0xe6, 0x00, 0x2a, 0x41, 0x1b, 0xdf, 0xfa, 0x64, - 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, 0xaf, 0x0d, 0xa6, 0xaf, 0x6f, - 0xb7, 0x45, 0x7e, 0x6a, 0x62, 0xc2, 0x7a, 0xac, 0xe8, 0x9b, 0x77, 0xe1, 0x5a, 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, 0x7a, 0xc5, 0xc8, 0x7c, 0xdc, 0x47, 0xa5, 0x92, 0xfe, 0x79, 0x3c, - 0xce, 0xf2, 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, 0x7b, 0x52, 0x72, 0x78, 0xce, 0x31, 0x27, 0x94, 0x56, 0x84, 0xe5, - 0x7c, 0x91, 0xa1, 0x5c, 0x77, 0x4e, 0xc1, 0x24, 0x87, 0x04, 0xc3, 0x5f, 0x35, 0x6f, 0x62, 0x05, 0xc2, 0xae, 0x91, - 0x33, 0x47, 0x4f, 0xaa, 0x24, 0x2c, 0x05, 0x1c, 0x95, 0x99, 0x67, 0xd8, 0x1b, 0x9e, 0x18, 0x46, 0x0e, 0x56, 0xf9, - 0xa3, 0x3a, 0x11, 0xb9, 0x47, 0x17, 0x18, 0x95, 0x85, 0x57, 0x0d, 0x5d, 0x69, 0x50, 0x49, 0x76, 0xfa, 0x15, 0xd7, - 0x80, 0xda, 0x1a, 0x23, 0x96, 0x83, 0x80, 0x51, 0xf0, 0xda, 0xfe, 0x10, 0xb2, 0x28, 0x5b, 0xbf, 0xc1, 0x31, 0x9f, - 0x95, 0xdc, 0xf5, 0x0e, 0x67, 0xa1, 0x25, 0xe4, 0xc9, 0x1d, 0x83, 0x34, 0x8d, 0xa5, 0x11, 0x70, 0x22, 0x92, 0x6d, - 0x2c, 0x85, 0x23, 0x80, 0x80, 0x40, 0x37, 0x65, 0x86, 0x31, 0x1d, 0x8c, 0x3c, 0x4f, 0x7a, 0xc6, 0x7b, 0x15, 0x9e, - 0x42, 0x9a, 0x6c, 0x5f, 0xcf, 0x3f, 0xe4, 0x5a, 0x90, 0x95, 0x5b, 0xce, 0xe9, 0xb0, 0xf8, 0xc6, 0xd9, 0x57, 0x39, - 0x79, 0x8a, 0x59, 0x46, 0x7a, 0xa7, 0x98, 0x17, 0xf0, 0xa7, 0xb2, 0xd4, 0x93, 0xf4, 0x96, 0xf9, 0x64, 0x15, 0x49, - 0x97, 0xde, 0xb6, 0xdf, 0x8f, 0x47, 0xea, 0x50, 0xf3, 0x0f, 0xf1, 0x48, 0x9e, 0x61, 0x5b, 0x96, 0xb0, 0xd0, 0x2a, - 0x18, 0x03, 0x48, 0x62, 0x23, 0xa2, 0xc1, 0x68, 0x6f, 0x8f, 0xc7, 0xcb, 0xad, 0x39, 0x4b, 0x0e, 0xe0, 0xfa, 0xca, - 0x13, 0xf3, 0x0e, 0x7c, 0x99, 0xc7, 0x04, 0x11, 0x9b, 0x79, 0x5b, 0x56, 0x83, 0x07, 0x3b, 0xb8, 0x3e, 0x62, 0x8b, - 0x62, 0xad, 0x63, 0xc9, 0xad, 0x83, 0xd3, 0x3a, 0x36, 0xcd, 0x48, 0x29, 0xb2, 0xcf, 0xb1, 0x7f, 0x70, 0x83, 0xab, - 0x6b, 0x63, 0x50, 0x6b, 0xdc, 0x61, 0xee, 0x9c, 0x0a, 0xa8, 0xc7, 0x74, 0x05, 0xd5, 0x8b, 0x8a, 0x7c, 0xf9, 0xad, - 0x9d, 0x03, 0x82, 0x46, 0x20, 0x70, 0xd1, 0x40, 0xab, 0x76, 0x29, 0xe7, 0x5d, 0x40, 0x88, 0x6f, 0x52, 0xd0, 0xa7, - 0x33, 0xd8, 0xc4, 0xe6, 0x13, 0x88, 0x45, 0xd3, 0x7d, 0xae, 0x35, 0xf3, 0xc5, 0x88, 0x76, 0x66, 0xdd, 0x2d, 0x72, - 0xab, 0x85, 0x48, 0x46, 0xcf, 0x36, 0x13, 0x2e, 0x3a, 0x94, 0x33, 0x12, 0x30, 0x41, 0x6b, 0x2b, 0x25, 0x9f, 0xeb, - 0x41, 0x27, 0x68, 0x0f, 0x24, 0xad, 0xfb, 0x37, 0x8b, 0xce, 0x28, 0x39, 0xb9, 0xde, 0xe4, 0x0c, 0x52, 0xb0, 0x60, - 0x07, 0x99, 0x13, 0x6e, 0x80, 0x4f, 0x6c, 0x96, 0x9c, 0xa6, 0x41, 0x1e, 0x0b, 0xe3, 0x91, 0xd7, 0xe6, 0x97, 0x05, - 0x74, 0x28, 0x59, 0x34, 0x42, 0x3c, 0xc0, 0xce, 0x21, 0xb9, 0x2a, 0x50, 0x37, 0x0d, 0x74, 0xe5, 0xca, 0x99, 0x62, - 0x0a, 0x5c, 0x08, 0x05, 0x51, 0x3b, 0x3a, 0x89, 0xca, 0x79, 0x9f, 0x54, 0x97, 0xd5, 0xb4, 0x90, 0xa6, 0x81, 0x6a, - 0x9a, 0x3b, 0xe6, 0x81, 0xbd, 0x6d, 0x5c, 0x13, 0x18, 0xe8, 0xd4, 0xbe, 0x16, 0x55, 0xfc, 0x83, 0x74, 0x2f, 0xce, - 0xe1, 0x2f, 0x6b, 0xfa, 0x20, 0xc2, 0x46, 0x0e, 0x1a, 0x4b, 0x89, 0xb1, 0x51, 0xe1, 0xdf, 0x12, 0x65, 0x43, 0x86, - 0x80, 0x10, 0xd2, 0x46, 0x45, 0x3f, 0xac, 0x2f, 0xef, 0x32, 0xed, 0xff, 0x49, 0xe2, 0xb7, 0xc1, 0x5e, 0x4e, 0xfd, - 0xa9, 0x47, 0x3c, 0x5e, 0x1b, 0xf4, 0x98, 0x92, 0x6e, 0x83, 0x3c, 0x55, 0x9e, 0x82, 0x64, 0xc2, 0x58, 0x42, 0xb0, - 0x28, 0x17, 0xbc, 0xe2, 0x39, 0x97, 0x70, 0x1f, 0xb5, 0xac, 0x88, 0x50, 0x95, 0xa8, 0xe8, 0xf3, 0x39, 0xf0, 0x4c, - 0x40, 0xa0, 0x63, 0x8c, 0x34, 0xaa, 0xe0, 0x4b, 0x60, 0xac, 0x03, 0x65, 0xa7, 0x19, 0x09, 0x2e, 0xbb, 0xb7, 0x48, - 0x94, 0xfa, 0x8a, 0x94, 0xa4, 0x6f, 0x45, 0x8d, 0x57, 0x62, 0x15, 0x91, 0x40, 0x86, 0x1a, 0x22, 0x56, 0xd5, 0x53, - 0xf7, 0xa6, 0x98, 0x0c, 0x06, 0xb9, 0x2f, 0xa7, 0x27, 0xde, 0xd0, 0x50, 0x79, 0xd7, 0x15, 0xed, 0xf4, 0x44, 0x2b, - 0xe5, 0x2d, 0xa4, 0x25, 0x68, 0x1a, 0x46, 0x9a, 0x43, 0xa9, 0x6b, 0xe9, 0x6e, 0x0c, 0xe2, 0x4b, 0x26, 0x7a, 0xb6, - 0x53, 0x3b, 0x4a, 0x5b, 0xd2, 0x1e, 0x42, 0x7a, 0xee, 0x92, 0x8f, 0x21, 0x42, 0x4c, 0x55, 0xa5, 0xbc, 0x09, 0xd1, - 0xc9, 0xfd, 0x80, 0x21, 0x11, 0xe8, 0x73, 0x8e, 0x61, 0x5d, 0x34, 0xd4, 0x18, 0x6c, 0x6d, 0xb6, 0x50, 0xc2, 0x7c, - 0xc9, 0x78, 0x2a, 0x19, 0x34, 0x00, 0x32, 0xe0, 0xb3, 0x97, 0x81, 0xe5, 0xaf, 0x20, 0x7e, 0xb4, 0xf1, 0xf1, 0xf8, - 0x67, 0x4d, 0x21, 0xb6, 0x7f, 0xc2, 0x66, 0x08, 0x8f, 0xea, 0x01, 0xcf, 0x7c, 0x13, 0x27, 0x68, 0x05, 0x24, 0x65, - 0x76, 0x34, 0x91, 0xbd, 0xea, 0x21, 0x9c, 0xca, 0x0a, 0xd4, 0x51, 0xd6, 0x59, 0x09, 0x3f, 0xc2, 0x54, 0xb7, 0x12, - 0x6b, 0x81, 0x36, 0x57, 0x2b, 0xd6, 0x02, 0x38, 0xf0, 0x2b, 0x08, 0x9e, 0xa8, 0xe6, 0xe0, 0x62, 0x50, 0x80, 0xcf, - 0x01, 0xf0, 0x22, 0x77, 0xe1, 0xc1, 0x3c, 0xb2, 0xac, 0x46, 0x18, 0x8e, 0x2a, 0x62, 0xfd, 0x9a, 0xed, 0xc8, 0x07, - 0x6e, 0xc7, 0xf8, 0x5c, 0x7b, 0x2c, 0x59, 0x0e, 0x46, 0x99, 0x7b, 0xb5, 0x44, 0xcf, 0x9b, 0x34, 0x6e, 0x46, 0x4f, - 0x0e, 0xb5, 0xfc, 0x5f, 0xd0, 0xcb, 0xa0, 0xbf, 0x85, 0x5b, 0x5e, 0xf3, 0xbb, 0x05, 0x91, 0x66, 0x7a, 0x05, 0x91, - 0x32, 0x6a, 0x44, 0xc6, 0x10, 0x36, 0xa9, 0x6e, 0x65, 0x93, 0xea, 0x42, 0xc0, 0xd3, 0x09, 0xa9, 0xae, 0x85, 0xb4, - 0x51, 0x4d, 0xeb, 0x40, 0xc6, 0x22, 0xbd, 0xfb, 0xf1, 0x2f, 0x2f, 0x3e, 0xbd, 0xf9, 0xe5, 0xc7, 0xc5, 0x9b, 0x77, - 0xaf, 0xdf, 0xbc, 0x7b, 0xf3, 0xe9, 0x37, 0x82, 0xf0, 0x98, 0x0a, 0x95, 0xe1, 0xc3, 0xfb, 0xdb, 0x37, 0x4e, 0x06, - 0xdb, 0x9b, 0x21, 0x6b, 0xdf, 0xc8, 0xc1, 0x10, 0x88, 0x6c, 0x10, 0x32, 0xc8, 0x4e, 0x6d, 0xfb, 0x33, 0x31, 0xc7, - 0xd8, 0x3b, 0x81, 0xc9, 0x16, 0x24, 0x87, 0x65, 0x5e, 0x32, 0x22, 0x57, 0x8e, 0xd6, 0x0f, 0x68, 0xc1, 0x5b, 0x70, - 0x91, 0x49, 0xf3, 0xd5, 0x2f, 0x04, 0xb1, 0x4f, 0x2b, 0xa9, 0xf2, 0xd5, 0xb6, 0xe6, 0xf9, 0xf6, 0x7e, 0x9f, 0xd3, - 0x8a, 0x99, 0x4b, 0x23, 0x6a, 0x01, 0x0e, 0xc0, 0x97, 0xf0, 0xc7, 0x8d, 0xb6, 0xa4, 0xc9, 0x2c, 0xfa, 0x2c, 0x84, - 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, 0xf7, 0x8a, 0x1c, 0x19, 0x3f, - 0x08, 0x26, 0xbe, 0x0a, 0xdc, 0x7f, 0x89, 0x77, 0x38, 0x53, 0x1c, 0xc9, 0x09, 0x7f, 0xc8, 0x30, 0xb0, 0xbf, 0x02, - 0x9f, 0x57, 0x87, 0x79, 0x79, 0xab, 0x4f, 0xb9, 0x25, 0x1f, 0x4f, 0x96, 0x37, 0x60, 0xb0, 0x5f, 0xaa, 0xe6, 0x6e, - 0x78, 0x3d, 0x5b, 0xce, 0xd9, 0x61, 0x16, 0xcd, 0x83, 0x15, 0x9b, 0x65, 0xf3, 0x60, 0xdd, 0xf0, 0x0d, 0xbb, 0xe3, - 0x1b, 0xab, 0x6a, 0x1b, 0xbb, 0x6a, 0x93, 0x2d, 0xbf, 0x03, 0x09, 0xe1, 0x36, 0xf3, 0x72, 0x96, 0xb0, 0x95, 0xcf, - 0xb6, 0x20, 0xd1, 0xae, 0xd9, 0x16, 0x2e, 0x62, 0x1b, 0xfe, 0x63, 0xee, 0x6d, 0x59, 0xc9, 0x2e, 0xc7, 0xac, 0xc2, - 0xf9, 0xe7, 0xc3, 0x03, 0xda, 0x0b, 0xf5, 0xb3, 0x6b, 0xf5, 0x6c, 0xa2, 0xec, 0x66, 0xdb, 0xd1, 0xe2, 0x3e, 0xad, - 0xb6, 0x61, 0x86, 0x9e, 0xe5, 0xf0, 0xd1, 0x56, 0x0a, 0x7e, 0x7a, 0x81, 0x5f, 0xb2, 0xa3, 0xb6, 0xd2, 0xb6, 0x5d, - 0x95, 0xd8, 0x0a, 0x5a, 0x14, 0x59, 0xad, 0xf0, 0xc0, 0x8a, 0x3f, 0x87, 0x05, 0x8c, 0x3d, 0xc7, 0x39, 0xaf, 0xfd, - 0x11, 0x32, 0xde, 0x3b, 0x00, 0x68, 0x99, 0xe3, 0x00, 0x8f, 0x58, 0x31, 0x8a, 0x06, 0xef, 0xf2, 0x5a, 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, 0xb2, 0xb5, 0xaa, 0x3b, 0xbf, 0xa7, 0x4a, 0x97, 0x1c, 0xd9, 0xf2, 0xd3, 0x65, 0xf8, - 0xa0, 0xfe, 0x94, 0x5c, 0x1f, 0x0a, 0x1c, 0xe1, 0xb1, 0x0a, 0x38, 0x5f, 0xcf, 0x45, 0xbb, 0x13, 0x61, 0x57, 0x2e, - 0x01, 0x21, 0xbe, 0xa4, 0x69, 0x8e, 0xc7, 0x11, 0x4d, 0x44, 0xd8, 0xc4, 0xe8, 0x2f, 0xec, 0x3e, 0x94, 0x58, 0x2e, - 0x2b, 0x0d, 0x4a, 0x2e, 0x19, 0xbc, 0x27, 0xed, 0x35, 0x68, 0x96, 0x57, 0xae, 0x26, 0x13, 0x39, 0x28, 0x1f, 0x8f, - 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, 0x4e, 0x1f, 0xce, 0xc4, 0xdc, 0x7a, 0x6e, 0x95, 0x75, 0x92, 0xad, 0x51, - 0x4e, 0xc0, 0xbf, 0xa5, 0x3a, 0x4e, 0x12, 0xe1, 0xd4, 0x7b, 0xc4, 0x45, 0xdd, 0xcb, 0x21, 0xea, 0x86, 0xbd, 0xc9, - 0x75, 0xb0, 0xe5, 0x34, 0x0d, 0x4e, 0xc4, 0xaf, 0xd4, 0x67, 0xef, 0x33, 0x8b, 0x47, 0x1d, 0xd9, 0x88, 0x92, 0x34, - 0x8e, 0x45, 0x0e, 0xdb, 0xfb, 0x42, 0xee, 0xff, 0xfd, 0x3e, 0x84, 0x93, 0x56, 0x41, 0x52, 0x7a, 0x02, 0x11, 0xe1, - 0xe8, 0xf0, 0x23, 0xc2, 0x13, 0xa9, 0x2a, 0x7c, 0x52, 0x9f, 0xb9, 0x31, 0xbb, 0x17, 0xe6, 0xa8, 0xde, 0x01, 0x0c, - 0x63, 0xbd, 0xb3, 0x08, 0x49, 0xb4, 0xd2, 0x8c, 0xb6, 0x1e, 0x10, 0x23, 0xde, 0x6f, 0x2c, 0x32, 0x18, 0x6b, 0x4b, - 0x22, 0x01, 0x7c, 0x45, 0x42, 0x86, 0xb6, 0x8d, 0xc0, 0x8c, 0xe1, 0xed, 0xac, 0xb8, 0x74, 0x1d, 0xb6, 0x39, 0x87, - 0x2f, 0x64, 0xa1, 0x59, 0x47, 0x94, 0x26, 0x08, 0xf9, 0x07, 0x9c, 0x2c, 0x14, 0x46, 0xf3, 0xea, 0x24, 0x9d, 0x24, - 0xd6, 0xf7, 0x5d, 0xa5, 0x82, 0xcd, 0xe6, 0x16, 0xf5, 0x65, 0x27, 0xc9, 0x2f, 0xc1, 0x49, 0xc7, 0x49, 0x16, 0x39, - 0x88, 0x5a, 0x54, 0xce, 0x6d, 0x12, 0x96, 0x76, 0x75, 0xaa, 0xed, 0x66, 0x53, 0x94, 0x75, 0xf5, 0x4a, 0x44, 0x8a, - 0xde, 0x47, 0x3d, 0x7a, 0x22, 0x21, 0x15, 0x5a, 0x95, 0xda, 0xe7, 0x11, 0xb8, 0x6d, 0x6a, 0xc5, 0xb6, 0x5c, 0xc2, - 0x12, 0x35, 0xfe, 0x13, 0xf4, 0x51, 0x2e, 0x1e, 0x64, 0x80, 0x46, 0xc7, 0x53, 0xf3, 0xd6, 0x23, 0xaf, 0x9c, 0xe4, - 0x97, 0x56, 0x9b, 0xf4, 0x0b, 0x20, 0x33, 0xda, 0x3f, 0x5a, 0x4a, 0x20, 0x33, 0x30, 0x93, 0x96, 0x86, 0x44, 0x8e, - 0x62, 0x96, 0xe6, 0x7f, 0xe0, 0x8a, 0xad, 0x10, 0x69, 0x58, 0xcd, 0x3d, 0xfe, 0x22, 0xf7, 0x6a, 0xb9, 0x96, 0x99, - 0xe6, 0x66, 0x89, 0x63, 0xc5, 0xe2, 0xa2, 0x5e, 0x57, 0x22, 0x0b, 0x84, 0x38, 0xc2, 0x34, 0xd6, 0x53, 0x6f, 0x94, - 0x56, 0x1f, 0x90, 0x50, 0xe6, 0x47, 0xec, 0xed, 0xd8, 0xeb, 0x41, 0x16, 0xe2, 0xd8, 0x72, 0xb0, 0xd9, 0x7a, 0x9f, - 0xca, 0x54, 0xc4, 0x17, 0x75, 0x71, 0xb1, 0xad, 0xc4, 0x45, 0x9d, 0x88, 0x8b, 0xef, 0x21, 0xe7, 0xf7, 0x17, 0x54, - 0xf4, 0xc5, 0x43, 0x5a, 0x27, 0xc5, 0xb6, 0xa6, 0x27, 0xaf, 0xb1, 0x8c, 0xef, 0x2f, 0x88, 0xab, 0xe6, 0x82, 0x46, - 0x32, 0x1e, 0x5d, 0x7c, 0xc8, 0x80, 0xe4, 0xf5, 0x22, 0x5d, 0xc3, 0xe0, 0x5d, 0x84, 0x79, 0x7c, 0x51, 0x8a, 0x15, - 0x58, 0x9c, 0xca, 0xce, 0xf7, 0x20, 0xc3, 0x3a, 0xfc, 0x43, 0x5c, 0x00, 0xb4, 0xeb, 0x45, 0x5a, 0x5f, 0xa4, 0xd5, - 0x45, 0x5e, 0xd4, 0x17, 0x4a, 0x0a, 0x87, 0x30, 0x7e, 0x78, 0x4f, 0x5f, 0xd9, 0xe5, 0x6d, 0x16, 0x77, 0x59, 0xe4, - 0x4f, 0xd1, 0xab, 0x88, 0x98, 0x34, 0x72, 0xe1, 0xb5, 0xfb, 0xdb, 0xe6, 0xfe, 0xe1, 0x75, 0x63, 0xf7, 0xb3, 0x3b, - 0x46, 0x74, 0x41, 0x3d, 0x5d, 0x49, 0x4a, 0x05, 0x05, 0x04, 0x4e, 0x34, 0x6b, 0x3c, 0xb8, 0xe3, 0x80, 0x57, 0x03, - 0x5b, 0xb2, 0x8d, 0xcf, 0x9f, 0xc7, 0x32, 0x4c, 0x7b, 0x1b, 0xe0, 0x5f, 0x65, 0x6f, 0xba, 0x09, 0x96, 0x78, 0xdf, - 0x42, 0xb6, 0xa1, 0x37, 0xaf, 0xf8, 0x0b, 0xaf, 0x52, 0x7f, 0xb3, 0x7f, 0x00, 0x10, 0x06, 0xc4, 0xac, 0xfa, 0x68, - 0xe2, 0xde, 0x5b, 0x59, 0xf6, 0x4e, 0x96, 0x7d, 0x0f, 0xfd, 0x9a, 0xc4, 0xa8, 0xb4, 0xb2, 0x94, 0x4e, 0x96, 0x12, - 0xb2, 0x80, 0x4f, 0x8c, 0xa6, 0x36, 0x02, 0x08, 0xdb, 0x51, 0x2a, 0x5f, 0x00, 0xc2, 0x49, 0x02, 0x12, 0x62, 0x09, - 0x17, 0xa3, 0x7b, 0x2b, 0x19, 0x30, 0x1c, 0x42, 0x30, 0x07, 0xed, 0xb0, 0x37, 0x74, 0x13, 0xf1, 0xd7, 0xeb, 0xa2, - 0x7c, 0x13, 0x93, 0x4f, 0xc1, 0xfe, 0xec, 0xe3, 0x12, 0x1e, 0x97, 0x67, 0x1f, 0x87, 0xe8, 0x91, 0x70, 0xf6, 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, 0xfe, 0xab, 0xfb, 0x0a, 0x6e, 0xe3, - 0xfd, 0xfe, 0x32, 0xf7, 0xcc, 0x4f, 0x5c, 0x00, 0xf6, 0xa6, 0x42, 0xeb, 0x04, 0x4a, 0x0d, 0xeb, 0xf0, 0x65, 0x22, - 0xa2, 0x3f, 0xda, 0xe5, 0x3a, 0x73, 0x1d, 0x30, 0xa2, 0x88, 0xdf, 0xc6, 0xa3, 0x3f, 0x40, 0x71, 0x6d, 0xec, 0x01, - 0x61, 0x1d, 0x12, 0xfa, 0x8c, 0x00, 0xa4, 0x1e, 0x73, 0x94, 0x80, 0x66, 0x45, 0x73, 0xc7, 0xc0, 0xc1, 0x2f, 0xaf, - 0x94, 0xfe, 0x61, 0x99, 0x7b, 0x64, 0x4e, 0x69, 0x9b, 0x69, 0xac, 0xd6, 0xe4, 0x02, 0xe1, 0x15, 0x95, 0xac, 0xc2, - 0x67, 0xf3, 0x46, 0xf4, 0xfb, 0xf2, 0x08, 0x4f, 0xab, 0x1f, 0x77, 0x18, 0xdf, 0x0a, 0x88, 0x46, 0x02, 0xa0, 0x9f, - 0x00, 0xe6, 0x45, 0x36, 0xb3, 0xfb, 0x38, 0xa0, 0x4a, 0x89, 0xa6, 0x71, 0x36, 0xcf, 0x6f, 0xe9, 0x4d, 0xd9, 0x41, - 0xe7, 0x4e, 0x15, 0xb8, 0xe0, 0xaa, 0x64, 0xbc, 0xb2, 0x9e, 0xc9, 0xe7, 0x37, 0x77, 0xdb, 0x34, 0x8b, 0xdf, 0x97, - 0xff, 0xc0, 0xb1, 0xd5, 0x75, 0x78, 0x64, 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, 0xca, 0x8b, 0x2e, - 0x06, 0x6b, 0x5f, 0x8e, 0x59, 0x0e, 0x5d, 0xaa, 0x1e, 0xab, 0x87, 0xc6, 0x66, 0x0e, 0x3d, 0x6b, 0x55, 0x9e, 0x79, - 0xf9, 0xf1, 0x88, 0xf8, 0x30, 0xfa, 0x4b, 0x7e, 0xbf, 0xff, 0x8a, 0xe6, 0x1f, 0x13, 0x6a, 0xfc, 0x6c, 0x33, 0x40, - 0xd7, 0xbe, 0x2b, 0x0f, 0x44, 0x3d, 0xd7, 0x2a, 0x41, 0x88, 0x37, 0x88, 0x89, 0x66, 0xc4, 0x1c, 0x9c, 0x76, 0xa8, - 0xf9, 0x27, 0xa9, 0x01, 0x21, 0x4a, 0xbc, 0x8e, 0x29, 0x0b, 0x72, 0xda, 0xc4, 0x91, 0x7e, 0x14, 0x4e, 0xe4, 0x47, - 0x51, 0x15, 0xd9, 0x3d, 0x5c, 0x30, 0x98, 0x7a, 0x4f, 0xfb, 0x25, 0xfa, 0x2d, 0xe1, 0xc8, 0x39, 0x5a, 0x15, 0x82, - 0xc8, 0x19, 0x61, 0xad, 0x21, 0x4c, 0x10, 0x1b, 0xc4, 0xcb, 0xbe, 0x4b, 0x32, 0x1c, 0x29, 0xb8, 0xac, 0x63, 0xc7, - 0x98, 0xab, 0xa3, 0xea, 0x35, 0x80, 0xf1, 0xaa, 0x10, 0x34, 0x1b, 0x45, 0x76, 0x09, 0x51, 0x45, 0x8e, 0x27, 0xa0, - 0x76, 0x50, 0x1a, 0x9b, 0xe9, 0xe5, 0x38, 0x80, 0x09, 0x8e, 0x3a, 0x27, 0x96, 0xf1, 0x1a, 0x80, 0xb5, 0x2b, 0xd5, - 0xcf, 0xb3, 0x1a, 0x3c, 0x69, 0x88, 0xcf, 0xc7, 0x68, 0x7b, 0x65, 0x73, 0x50, 0x6d, 0xa7, 0xb3, 0xf2, 0x9c, 0xe9, - 0x72, 0x60, 0xdc, 0xb7, 0x3c, 0xa7, 0x38, 0xc3, 0x8f, 0x5e, 0x3e, 0xab, 0xe7, 0xfe, 0x74, 0x4b, 0xed, 0xc7, 0xdc, - 0xa8, 0x87, 0x81, 0xd6, 0x82, 0x37, 0x05, 0xb1, 0xfe, 0x7e, 0xe8, 0xc8, 0xf6, 0x5e, 0x8b, 0x8c, 0x26, 0x9f, 0xfd, - 0xfc, 0x43, 0x99, 0xae, 0x53, 0xb8, 0x2f, 0x39, 0x59, 0x34, 0xf3, 0x10, 0xd8, 0x1b, 0x62, 0xb8, 0x3e, 0x2a, 0x3c, - 0xa2, 0xac, 0xdf, 0x87, 0xdf, 0x37, 0x19, 0x98, 0x62, 0xe0, 0xba, 0x42, 0x30, 0x1e, 0x02, 0x41, 0x3c, 0x4c, 0xa3, - 0x93, 0x41, 0x0d, 0xda, 0xf0, 0x2d, 0x40, 0x66, 0x80, 0x47, 0xe6, 0xd2, 0x23, 0xe0, 0x2e, 0x70, 0xed, 0xc9, 0x78, - 0xec, 0x4f, 0x4c, 0x43, 0xa3, 0xa6, 0x34, 0xd3, 0x73, 0xeb, 0x37, 0x1d, 0xd5, 0x72, 0xed, 0xfc, 0xa7, 0x97, 0xfc, - 0x06, 0xbd, 0xa0, 0xe5, 0xe5, 0x3e, 0x52, 0x97, 0xfb, 0x8c, 0xe2, 0x32, 0x91, 0x1c, 0x16, 0xc4, 0xb2, 0x84, 0x03, - 0x8f, 0x51, 0xc9, 0x62, 0x4b, 0x8f, 0x95, 0xd3, 0xf2, 0x45, 0xb9, 0x41, 0x3a, 0x74, 0x42, 0xb0, 0x44, 0x0e, 0xc1, - 0x12, 0x18, 0x17, 0xb1, 0xe1, 0xdb, 0x41, 0xc5, 0xe2, 0xd9, 0x76, 0xce, 0x91, 0xb0, 0x2e, 0x39, 0x1e, 0x0b, 0x09, - 0x36, 0x93, 0xcd, 0x36, 0x73, 0xb6, 0xf1, 0x19, 0x28, 0x01, 0x4a, 0x99, 0x26, 0x28, 0x4d, 0x2b, 0xb6, 0xe2, 0xa6, - 0x35, 0x58, 0xad, 0xa6, 0xec, 0x54, 0x53, 0xf6, 0x4e, 0x53, 0x4e, 0x2a, 0x28, 0x39, 0xa1, 0x14, 0x65, 0x18, 0xc0, - 0x88, 0x4d, 0xa2, 0x9b, 0x0c, 0x7d, 0xbc, 0x13, 0x1e, 0x41, 0x15, 0x11, 0xf9, 0x84, 0x21, 0x04, 0x26, 0xa2, 0xb8, - 0x50, 0x85, 0x62, 0x80, 0x8c, 0x48, 0x20, 0x98, 0xa8, 0xd4, 0x29, 0x30, 0x1f, 0x4d, 0x15, 0xc3, 0xa6, 0x3d, 0x51, - 0xbe, 0xa5, 0x8e, 0x07, 0x94, 0x6d, 0xfe, 0x26, 0xf6, 0x41, 0x88, 0xdc, 0x8d, 0x7b, 0xf5, 0x33, 0xe2, 0xbd, 0xfd, - 0x09, 0xc6, 0x4f, 0x76, 0xda, 0x22, 0x5c, 0x11, 0x6c, 0xa9, 0xe6, 0x10, 0x8c, 0xca, 0x24, 0x41, 0x2d, 0x4b, 0xe2, - 0x6f, 0x79, 0x32, 0xa8, 0xd8, 0x12, 0x3c, 0x68, 0xe7, 0x2c, 0x03, 0xfc, 0x15, 0xab, 0x45, 0xbf, 0xd5, 0xde, 0x12, - 0xe4, 0xa7, 0xad, 0xdd, 0x28, 0x4c, 0x8c, 0x20, 0x51, 0xb7, 0x2b, 0x03, 0xf9, 0xe1, 0x03, 0x4e, 0xc7, 0x53, 0x4f, - 0x19, 0x73, 0x2b, 0xd3, 0xcb, 0x74, 0xae, 0xe4, 0x1b, 0xb9, 0x97, 0x3e, 0xf6, 0x12, 0xec, 0x1c, 0xf0, 0x06, 0xd2, - 0x06, 0xde, 0xc2, 0x76, 0xe1, 0xb5, 0x41, 0xc2, 0x8c, 0x00, 0x5b, 0x9c, 0x1e, 0x23, 0x25, 0x30, 0x84, 0xe3, 0x2c, - 0x05, 0x60, 0x1a, 0x7d, 0x99, 0xcd, 0xed, 0xcb, 0xac, 0xd6, 0x6c, 0xa9, 0x9c, 0xee, 0x9d, 0x5b, 0xb7, 0xf3, 0x89, - 0x04, 0x00, 0x93, 0x3a, 0x07, 0xe2, 0xcc, 0x04, 0xbb, 0x34, 0x89, 0x2c, 0x1f, 0xc3, 0x7c, 0x25, 0x5e, 0x97, 0xc5, - 0x5a, 0x75, 0x45, 0xdb, 0x67, 0xa6, 0x9a, 0x91, 0x4e, 0x42, 0x05, 0x14, 0x14, 0x72, 0xad, 0x4f, 0xdf, 0x85, 0xef, - 0x82, 0x42, 0x03, 0xb3, 0xe5, 0xb8, 0xa7, 0xc9, 0x1a, 0xa9, 0x37, 0xf2, 0x7e, 0x9f, 0x5c, 0x03, 0xa9, 0xce, 0x1c, - 0x5a, 0xf6, 0x04, 0x9d, 0x64, 0x4f, 0x6e, 0xca, 0x52, 0xa8, 0x03, 0xa9, 0x07, 0x0c, 0x21, 0xda, 0xa6, 0x8f, 0x3f, - 0x19, 0x12, 0x5d, 0x80, 0x2d, 0x44, 0x1b, 0xf8, 0xf1, 0x27, 0xd8, 0x67, 0x41, 0x78, 0x4c, 0xf3, 0xb7, 0x90, 0x74, - 0x6a, 0xe0, 0xb4, 0xfa, 0x14, 0x7c, 0x90, 0xe4, 0x60, 0xa2, 0x0e, 0x5e, 0xee, 0x2f, 0xfd, 0x3e, 0x6c, 0xd9, 0x95, - 0x94, 0xea, 0x00, 0x6d, 0x4a, 0xb9, 0xab, 0x2b, 0x3f, 0x88, 0xb6, 0xe0, 0xc8, 0x22, 0xfe, 0x3e, 0x43, 0x44, 0x30, - 0x33, 0x88, 0xb0, 0x6b, 0xa1, 0xee, 0xf6, 0x9c, 0x5a, 0x16, 0xf5, 0xb6, 0xe7, 0x94, 0xba, 0x0d, 0xc3, 0x77, 0x13, - 0xcc, 0x14, 0x37, 0xfc, 0x8f, 0xcc, 0x0b, 0xf5, 0xc6, 0x63, 0x51, 0xa0, 0x7b, 0xfe, 0x61, 0xc9, 0xf3, 0xd9, 0x56, - 0x99, 0x30, 0x57, 0x7c, 0x39, 0x0b, 0x65, 0x57, 0x4b, 0xe3, 0xce, 0x67, 0x6f, 0xa9, 0xe6, 0x83, 0x7f, 0x3c, 0x26, - 0x10, 0x6f, 0x14, 0xdf, 0xac, 0x1a, 0xb9, 0x75, 0x4d, 0xb6, 0x37, 0x25, 0xa0, 0x7e, 0x5f, 0x6e, 0x70, 0xbf, 0xc5, - 0xfa, 0x77, 0x4f, 0x83, 0x8c, 0xd5, 0x0c, 0x57, 0x4c, 0xe1, 0x53, 0x00, 0x18, 0x1c, 0x4e, 0x05, 0x69, 0x81, 0xb7, - 0xbc, 0x1c, 0x5e, 0x4f, 0xb6, 0x64, 0xd2, 0xdd, 0xfa, 0xc8, 0x9d, 0x05, 0xaa, 0xde, 0x6f, 0x28, 0x4e, 0x1a, 0x24, - 0x1a, 0x7b, 0x0d, 0xbe, 0xc8, 0x32, 0xca, 0x45, 0x13, 0xf7, 0x31, 0xf9, 0x4a, 0x0f, 0x60, 0xa5, 0x42, 0x09, 0x10, - 0xfd, 0xc6, 0xb2, 0xd8, 0x88, 0xb6, 0xc5, 0x06, 0x96, 0x52, 0x3e, 0xd7, 0xab, 0xe9, 0xb3, 0x57, 0xa2, 0x79, 0x1f, - 0xcd, 0x38, 0xa5, 0xd1, 0x80, 0xe3, 0x34, 0x0a, 0x77, 0xef, 0xef, 0x45, 0xb9, 0xcc, 0xc0, 0x92, 0xad, 0xc2, 0x29, - 0xae, 0x1b, 0x75, 0x46, 0xbc, 0xc8, 0x63, 0x05, 0xd0, 0xf1, 0x98, 0x00, 0xa8, 0x2e, 0x08, 0xa8, 0x88, 0x96, 0xd2, - 0x5b, 0xa1, 0xc5, 0x42, 0xbd, 0xe1, 0x28, 0x85, 0x3f, 0xd2, 0x9f, 0x07, 0xd5, 0x14, 0x80, 0xd8, 0xf5, 0x71, 0xf4, - 0xba, 0x28, 0xe9, 0x53, 0xc5, 0xac, 0x92, 0x83, 0x09, 0xec, 0xea, 0x44, 0x86, 0x9a, 0x43, 0xde, 0xbc, 0x2b, 0x6f, - 0x6e, 0xf2, 0x36, 0xc6, 0x29, 0xf9, 0x91, 0x9b, 0x8e, 0x35, 0x62, 0xe0, 0x95, 0xa7, 0x75, 0x9a, 0x20, 0x4d, 0x2e, - 0x80, 0x61, 0x88, 0xef, 0x32, 0xef, 0x85, 0xe7, 0x48, 0x55, 0x90, 0xcc, 0xf6, 0x99, 0xa7, 0x2e, 0xa2, 0xfa, 0xca, - 0xa9, 0xa5, 0x33, 0xa7, 0x1f, 0x01, 0xbc, 0xc7, 0xd4, 0xa4, 0x21, 0x1f, 0xe1, 0xb6, 0x14, 0x5f, 0xef, 0xd4, 0x35, - 0x5e, 0x1a, 0x9d, 0xbb, 0x97, 0x2f, 0xdd, 0x69, 0xd0, 0x4f, 0x41, 0x50, 0xce, 0x17, 0xa5, 0x80, 0x3d, 0x65, 0x36, - 0xd7, 0xab, 0x55, 0x2b, 0xb4, 0x8e, 0xc7, 0xb1, 0x76, 0x14, 0xd2, 0xea, 0x2c, 0x60, 0xab, 0x91, 0x4e, 0x09, 0x10, - 0x82, 0xe3, 0x34, 0xec, 0x0c, 0xe3, 0x2e, 0x9d, 0x46, 0x64, 0xbd, 0x52, 0x92, 0x2e, 0xcc, 0x20, 0xf9, 0x27, 0x79, - 0x3d, 0x03, 0x5a, 0x02, 0x38, 0x14, 0xb1, 0x84, 0x87, 0x93, 0xe4, 0x06, 0xa0, 0xd3, 0xe1, 0xa0, 0xd2, 0xd0, 0x9c, - 0xf9, 0x2c, 0x99, 0x4f, 0x62, 0xa9, 0xaa, 0x3c, 0x1e, 0x3d, 0xe5, 0x66, 0xd0, 0xef, 0x67, 0xd3, 0x52, 0xb9, 0x00, - 0x04, 0xb1, 0x2e, 0x0c, 0x10, 0x8f, 0xb4, 0xf0, 0x64, 0xd1, 0xa7, 0x24, 0x7e, 0x39, 0x4b, 0xe6, 0x26, 0x1b, 0xde, - 0x81, 0x11, 0x6c, 0xc6, 0x75, 0x49, 0x99, 0xf6, 0xa8, 0xfc, 0x9e, 0xd1, 0x53, 0xdb, 0xd7, 0x5a, 0x6d, 0x11, 0xeb, - 0x3a, 0xb8, 0x2a, 0x51, 0x4f, 0xf1, 0x41, 0x49, 0x82, 0xf7, 0x2b, 0xe7, 0x66, 0xa4, 0x7c, 0x2d, 0x2a, 0x3f, 0x68, - 0x67, 0x6a, 0xe5, 0xc0, 0x11, 0xa8, 0xb0, 0x8a, 0x4a, 0x5e, 0xef, 0x3a, 0x04, 0x4f, 0xee, 0x4a, 0x05, 0xca, 0xc1, - 0xcf, 0x41, 0x8c, 0xae, 0x6f, 0x3a, 0x6b, 0xa8, 0x99, 0x46, 0x95, 0x47, 0xd0, 0xb9, 0x03, 0x78, 0x52, 0xf0, 0x52, - 0xab, 0x1f, 0x8f, 0x47, 0xcf, 0xfc, 0xe0, 0x2f, 0x33, 0x7d, 0x0b, 0x31, 0x51, 0x4e, 0x35, 0x42, 0xe2, 0x4a, 0x49, - 0x22, 0x3e, 0x5d, 0xb4, 0xac, 0x18, 0x95, 0xe1, 0x03, 0xb0, 0x00, 0x51, 0xf9, 0xea, 0x54, 0xe5, 0xc5, 0x48, 0xdb, - 0x12, 0x78, 0x4d, 0xfe, 0x21, 0x72, 0xcd, 0x5b, 0x5f, 0x77, 0x95, 0xa1, 0x6f, 0x65, 0x05, 0x3a, 0x82, 0xad, 0x2c, - 0x25, 0x07, 0x7c, 0x52, 0xdf, 0x55, 0x5b, 0x9f, 0x53, 0xb6, 0x11, 0x6e, 0xf2, 0xeb, 0xd8, 0xc1, 0x91, 0xf2, 0x1b, - 0xbc, 0x14, 0xc0, 0x5e, 0x03, 0xf6, 0xe6, 0x8a, 0x15, 0xcd, 0xa3, 0x43, 0xda, 0x16, 0x68, 0x64, 0xe6, 0x76, 0xae, - 0xee, 0xdb, 0xf2, 0x28, 0x8d, 0x21, 0x32, 0xed, 0x91, 0xe9, 0x60, 0x33, 0xca, 0x7f, 0x4b, 0xf9, 0xad, 0xc2, 0x31, - 0xf0, 0xed, 0xdc, 0x3b, 0x80, 0xaa, 0xa7, 0x0d, 0x32, 0xd6, 0x0c, 0x43, 0x2b, 0xbb, 0x5c, 0x0a, 0x2d, 0x41, 0x4b, - 0xdd, 0x04, 0xc1, 0xf9, 0x11, 0x51, 0x8e, 0x00, 0x74, 0x91, 0x02, 0x26, 0xf8, 0x39, 0x6d, 0x77, 0xbf, 0xbf, 0x49, - 0x3d, 0x72, 0xef, 0x0a, 0x95, 0xcd, 0xf2, 0x4d, 0x8e, 0x30, 0xf6, 0x13, 0x8d, 0x19, 0x74, 0x72, 0x45, 0x4e, 0x78, - 0xd6, 0xea, 0xb0, 0xae, 0x9b, 0x32, 0x28, 0x8b, 0x63, 0x9e, 0x4f, 0x67, 0xbf, 0x3f, 0x39, 0xd4, 0x0d, 0xb2, 0x90, - 0xff, 0xce, 0x7a, 0x48, 0x06, 0xdd, 0x83, 0x50, 0x88, 0xde, 0x3c, 0x98, 0xe1, 0x7f, 0x6c, 0xcb, 0xb3, 0x6f, 0xb8, - 0x51, 0x27, 0x80, 0x39, 0xe2, 0x7a, 0xe9, 0x29, 0xda, 0x7a, 0xb8, 0x05, 0xb2, 0x0d, 0x5e, 0xde, 0xda, 0x6b, 0xa0, - 0xa2, 0x38, 0xfe, 0x15, 0xcf, 0xd4, 0xca, 0x06, 0x3f, 0x3d, 0x65, 0x3b, 0xf0, 0xf0, 0x22, 0x04, 0x14, 0xc3, 0xb2, - 0xf1, 0x2b, 0xcb, 0x71, 0x46, 0xff, 0xcd, 0x23, 0x86, 0xc1, 0x22, 0xf2, 0xe3, 0xcb, 0x52, 0x88, 0x2f, 0xc2, 0x7b, - 0x93, 0x7b, 0x2b, 0x72, 0xca, 0x5c, 0xe9, 0x61, 0x74, 0x5d, 0x92, 0xbe, 0x49, 0x3e, 0xb6, 0x86, 0xed, 0x77, 0xed, - 0x7e, 0x33, 0x44, 0x10, 0x42, 0x39, 0x7e, 0xce, 0xe8, 0x84, 0xc6, 0x87, 0x35, 0xd7, 0x3b, 0xbd, 0x7e, 0xef, 0x12, - 0x2f, 0xd8, 0x1a, 0x0d, 0xf0, 0x74, 0xe8, 0x62, 0x9e, 0xa8, 0xa1, 0xd3, 0x75, 0xed, 0x1c, 0x3c, 0x30, 0xc8, 0xf2, - 0xe4, 0x1b, 0x86, 0x25, 0xf6, 0x27, 0x11, 0x4f, 0xda, 0xaa, 0x8d, 0xed, 0x89, 0x6a, 0xa3, 0x66, 0xe0, 0x07, 0xaf, - 0xa0, 0xc0, 0xe8, 0x82, 0xb4, 0x06, 0xe3, 0x70, 0x04, 0x20, 0x2b, 0xc6, 0xf1, 0xc8, 0x60, 0x02, 0x43, 0xba, 0xa1, - 0x28, 0x00, 0x0f, 0x8f, 0xd3, 0x41, 0xc8, 0x00, 0xd2, 0x05, 0x0f, 0x0d, 0xdb, 0x24, 0xa4, 0xfc, 0x3c, 0x2f, 0x6b, - 0x35, 0x84, 0xbe, 0xb3, 0x50, 0x1d, 0xfb, 0x91, 0xf6, 0x8a, 0x75, 0xad, 0x4a, 0x27, 0xb6, 0x3a, 0x40, 0xdf, 0x90, - 0x81, 0x6f, 0x1d, 0x5b, 0x00, 0x44, 0x4b, 0xfc, 0x96, 0x7a, 0xb5, 0x2f, 0x63, 0x56, 0xa8, 0xd7, 0x17, 0xa6, 0x5d, - 0xaf, 0xa4, 0x45, 0x01, 0x15, 0xb7, 0xad, 0xda, 0x9e, 0xc8, 0xf9, 0x8f, 0xef, 0x3a, 0xda, 0xf1, 0xd9, 0xa9, 0xb1, - 0x25, 0x94, 0xb9, 0xc5, 0x13, 0x59, 0x1d, 0x6d, 0xa9, 0x4e, 0xf5, 0x01, 0x97, 0x9a, 0x54, 0x67, 0xda, 0xa7, 0xc9, - 0x12, 0xa0, 0xdc, 0x42, 0x24, 0x8d, 0xc3, 0xc1, 0xf9, 0x64, 0x50, 0x30, 0xb7, 0x48, 0x40, 0x02, 0xdb, 0xda, 0xda, - 0x45, 0x73, 0xfd, 0xfa, 0x2d, 0xf5, 0xf2, 0x36, 0x55, 0x3d, 0x78, 0xe3, 0x05, 0xce, 0xde, 0x69, 0x2d, 0x20, 0x80, - 0xc2, 0xd6, 0xb2, 0x1c, 0x9c, 0xbb, 0x5d, 0xd5, 0x52, 0x51, 0x46, 0xfd, 0xfe, 0xe5, 0x6f, 0x29, 0x2a, 0x62, 0xcf, - 0x15, 0xa7, 0xac, 0xdf, 0x6e, 0x99, 0x8b, 0xca, 0x92, 0x37, 0xa8, 0xa2, 0xb5, 0x3a, 0x6a, 0x72, 0xd7, 0xcd, 0x55, - 0x4b, 0x26, 0x88, 0xd1, 0x7d, 0xbe, 0xd6, 0x95, 0x53, 0xef, 0x83, 0x8a, 0x23, 0x06, 0x82, 0x9b, 0xee, 0xf1, 0xc1, - 0x41, 0x68, 0x54, 0x94, 0x0b, 0x6e, 0x94, 0x56, 0x95, 0x94, 0x42, 0xde, 0xaa, 0x68, 0xc5, 0xf4, 0x11, 0x00, 0x11, - 0x60, 0x95, 0xa8, 0xff, 0xcd, 0x97, 0xc6, 0x78, 0xf0, 0xc0, 0xd7, 0xe4, 0x3a, 0xb6, 0xde, 0x3f, 0xaf, 0x91, 0x56, - 0x1b, 0xc7, 0xa4, 0x56, 0xbd, 0x6c, 0x15, 0x2f, 0xbb, 0xd7, 0xa9, 0x18, 0x3c, 0xff, 0x9f, 0xfb, 0x00, 0x35, 0xa2, - 0xa5, 0x0c, 0x6e, 0x5d, 0x0d, 0xd0, 0xf8, 0x70, 0x2a, 0x7c, 0xe3, 0x87, 0x8c, 0xf3, 0xc1, 0x0c, 0x1d, 0xd5, 0xe6, - 0xe0, 0x80, 0xe0, 0xa8, 0xee, 0xd1, 0x98, 0x30, 0x0b, 0xe7, 0x1e, 0x04, 0xaa, 0x4f, 0xdc, 0x67, 0x5c, 0x7b, 0x41, - 0x9b, 0xc0, 0x27, 0xeb, 0xba, 0xa6, 0x08, 0x70, 0x11, 0x1b, 0x13, 0x31, 0xc4, 0x65, 0x93, 0x48, 0x7d, 0x33, 0x06, - 0x05, 0x40, 0xf1, 0x3c, 0x27, 0xb9, 0x74, 0x91, 0xe6, 0x95, 0x28, 0x6b, 0xdd, 0x8c, 0x9c, 0x15, 0xc3, 0x9c, 0xd5, - 0x7e, 0x50, 0xdc, 0xe4, 0x66, 0x42, 0x23, 0x36, 0x90, 0xca, 0x52, 0xb0, 0x7c, 0x58, 0xf8, 0x4d, 0xfb, 0x4d, 0x72, - 0xd2, 0xbb, 0x1c, 0xb7, 0xce, 0x1d, 0xfb, 0xde, 0x51, 0x48, 0x69, 0x0f, 0xc5, 0x04, 0x41, 0xf0, 0xd3, 0x3a, 0x9c, - 0x3f, 0xe3, 0xcf, 0x09, 0x4c, 0x45, 0x36, 0x63, 0xc0, 0x41, 0x88, 0xc8, 0x8c, 0xdf, 0x73, 0xf8, 0x9c, 0x97, 0x93, - 0x70, 0x38, 0xf4, 0x41, 0x1f, 0xca, 0xb3, 0x59, 0x38, 0x14, 0x73, 0xe9, 0xbd, 0x0e, 0xd6, 0xba, 0x90, 0xd7, 0x93, - 0x10, 0xd1, 0x42, 0x43, 0x1f, 0x9c, 0xd7, 0x5d, 0x73, 0x84, 0x25, 0x00, 0x4d, 0x1c, 0x7d, 0x59, 0xbf, 0x1f, 0x79, - 0xda, 0xd0, 0x22, 0xc5, 0x45, 0xa3, 0xcc, 0x66, 0x95, 0xec, 0x84, 0xad, 0x6b, 0xb7, 0x40, 0x28, 0x1e, 0xa6, 0x2d, - 0x54, 0xad, 0xa7, 0x7a, 0x3d, 0x37, 0xed, 0xbe, 0x7b, 0x54, 0xad, 0x72, 0xa2, 0xb3, 0x36, 0x5d, 0xa9, 0xd5, 0x2d, - 0xa3, 0x6a, 0x93, 0xa5, 0x11, 0x55, 0x6e, 0x52, 0xb9, 0x46, 0x2d, 0xf8, 0x64, 0x43, 0xcd, 0xb5, 0xb3, 0x35, 0x38, - 0x71, 0xe4, 0xb9, 0xe4, 0x96, 0xef, 0xce, 0x2b, 0xba, 0x3b, 0xd5, 0xbe, 0x05, 0xb8, 0x37, 0xc3, 0x86, 0xcc, 0x79, - 0x8d, 0x9d, 0x06, 0x61, 0x12, 0xf8, 0x11, 0xfb, 0x98, 0x21, 0x1b, 0x0c, 0xe8, 0x28, 0xa4, 0x26, 0xc0, 0x32, 0x47, - 0x02, 0x26, 0x7f, 0x3d, 0xf7, 0x9b, 0x45, 0x91, 0xc3, 0x62, 0xfc, 0xb0, 0xc5, 0x48, 0x63, 0xb5, 0x06, 0xc3, 0x72, - 0x85, 0xc8, 0x9f, 0xda, 0x33, 0xd4, 0x54, 0xc7, 0x9b, 0xf5, 0x5a, 0xf3, 0xab, 0xa7, 0x4f, 0x75, 0x7d, 0xfe, 0xdb, - 0xf7, 0x97, 0x61, 0xcd, 0xec, 0x0f, 0x41, 0x28, 0xed, 0xc1, 0x2d, 0xce, 0x1d, 0x89, 0xde, 0xa9, 0xd2, 0xcc, 0x2e, - 0xed, 0x9a, 0x5d, 0x9b, 0xd2, 0x6e, 0xc9, 0xf5, 0xea, 0x2b, 0xe5, 0x8d, 0x9d, 0x57, 0x4c, 0xf7, 0x1f, 0x84, 0xde, - 0x51, 0xce, 0xd5, 0x04, 0x22, 0x9a, 0xb4, 0x23, 0x71, 0xbb, 0x57, 0x86, 0xcf, 0x26, 0x55, 0xbb, 0x84, 0x93, 0xae, - 0x61, 0x95, 0xf9, 0xf6, 0x3f, 0xf2, 0xaa, 0xb3, 0xc2, 0xed, 0x97, 0xc6, 0xac, 0xfd, 0x29, 0x88, 0xab, 0xfa, 0xc3, - 0x7b, 0x52, 0x33, 0x25, 0xff, 0x57, 0x3d, 0x06, 0xae, 0x7e, 0x32, 0xed, 0xe4, 0x9e, 0x42, 0xd8, 0x60, 0xf6, 0xf3, - 0xd3, 0x87, 0x16, 0xac, 0xaa, 0x0b, 0x14, 0xc9, 0x01, 0x74, 0xee, 0x9a, 0x11, 0xde, 0xef, 0x18, 0xe7, 0xfe, 0xcd, - 0x0f, 0x6a, 0x72, 0x84, 0x88, 0x76, 0x11, 0x0e, 0x00, 0xe2, 0x4e, 0x53, 0x59, 0x87, 0x1a, 0xa0, 0x0f, 0x08, 0xac, - 0x43, 0xdf, 0x66, 0x00, 0x07, 0x7d, 0xb4, 0x79, 0x16, 0x81, 0xbc, 0xee, 0xdd, 0xb3, 0xb7, 0x6c, 0xef, 0xf3, 0xe7, - 0xeb, 0xd4, 0xbb, 0x47, 0x87, 0xe0, 0xcb, 0xb1, 0x3f, 0xbd, 0x0e, 0x0c, 0x2e, 0x34, 0x7b, 0xfb, 0x54, 0xb0, 0x3d, - 0xdb, 0x3f, 0x45, 0xa4, 0xa2, 0xee, 0xfc, 0xc3, 0x6b, 0x13, 0x3d, 0xef, 0xbc, 0xb0, 0xe2, 0x4b, 0x00, 0x0f, 0x64, - 0x31, 0xa0, 0xf8, 0x2c, 0xbd, 0x7f, 0xb2, 0x04, 0xd4, 0xe4, 0x77, 0x7c, 0xe3, 0xbd, 0xa3, 0xd4, 0x05, 0xfc, 0x39, - 0xa0, 0xf4, 0x49, 0xc5, 0xbd, 0xd5, 0xf0, 0xce, 0xbf, 0x7a, 0x06, 0xce, 0x13, 0xeb, 0xe1, 0x02, 0xfe, 0x2a, 0xf8, - 0xd0, 0x5b, 0x0d, 0x30, 0xb1, 0xe4, 0x43, 0x6f, 0x3d, 0x80, 0x54, 0x85, 0x0b, 0x89, 0xb1, 0x0f, 0xbf, 0x06, 0x15, - 0xc3, 0x3f, 0x7e, 0xd3, 0x18, 0xac, 0xbf, 0x06, 0x85, 0x46, 0x63, 0x2d, 0x55, 0xc8, 0x52, 0x2c, 0x2e, 0x04, 0xd8, - 0x84, 0xe3, 0x6e, 0x5f, 0xac, 0x6a, 0xbb, 0x11, 0xf4, 0xe7, 0x23, 0xbe, 0x47, 0x63, 0x75, 0x55, 0xce, 0x45, 0xf9, - 0x11, 0xe9, 0x53, 0x1d, 0x1f, 0xa3, 0x62, 0x5b, 0x77, 0xa7, 0x53, 0xad, 0x3a, 0xd2, 0x7e, 0x53, 0xae, 0xc1, 0x8e, - 0xd7, 0xc9, 0x89, 0xa5, 0xf0, 0xa2, 0xc3, 0xce, 0x4b, 0xa7, 0x44, 0x87, 0x61, 0xbc, 0xdb, 0xaa, 0x67, 0x0c, 0xe5, - 0x95, 0xc1, 0x98, 0x2e, 0x78, 0xc4, 0x9f, 0x0f, 0x2a, 0x19, 0x1a, 0xf3, 0x01, 0xd9, 0x30, 0x94, 0x0f, 0x2d, 0x32, - 0x24, 0x44, 0xbc, 0x87, 0x4a, 0xc0, 0xb6, 0x05, 0x65, 0x52, 0xc0, 0x59, 0x34, 0xf8, 0xad, 0xf6, 0x2a, 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, 0x28, 0x59, 0xa7, 0x8d, 0x27, 0xc6, 0xdf, 0x5d, 0xe5, 0x9f, 0xa2, 0xa5, 0x1e, 0xfe, - 0x3f, 0x63, 0x0a, 0xa5, 0x7f, 0x99, 0x96, 0xd1, 0x76, 0xbd, 0x14, 0xa5, 0xc8, 0x23, 0x71, 0xf6, 0xb5, 0xc8, 0xce, - 0xe5, 0x3b, 0x9f, 0x42, 0xbf, 0x00, 0xb4, 0xec, 0x13, 0x64, 0xf4, 0x0f, 0x4c, 0xf0, 0xe1, 0x0f, 0xda, 0xb9, 0xb6, - 0xe2, 0xe3, 0x49, 0x75, 0x63, 0xed, 0xdd, 0x8e, 0x17, 0x89, 0x51, 0x8c, 0x55, 0xbe, 0xea, 0x66, 0xe5, 0x44, 0x25, - 0x07, 0x46, 0xba, 0x26, 0x7b, 0x95, 0x92, 0x75, 0x3b, 0xdd, 0x4a, 0x20, 0xa2, 0x0a, 0xbc, 0xc7, 0xb8, 0x8a, 0x7d, - 0x04, 0xd3, 0x75, 0xc7, 0x65, 0xb4, 0xe3, 0x3d, 0xe3, 0xd5, 0x89, 0xb2, 0x82, 0xdb, 0x8d, 0x68, 0x4f, 0xe8, 0xe8, - 0xa7, 0x49, 0x6d, 0x59, 0x38, 0x00, 0xb9, 0x4b, 0x18, 0xcb, 0x86, 0x60, 0xc5, 0xa0, 0xf4, 0xf5, 0x9a, 0x92, 0x65, - 0x01, 0x16, 0x9d, 0x5d, 0x46, 0x20, 0x86, 0x75, 0xd3, 0x9c, 0xd1, 0xf1, 0xd2, 0xc5, 0xf9, 0xa0, 0x55, 0xa4, 0xe0, - 0x19, 0x2d, 0x3a, 0xe6, 0xa6, 0x23, 0xdd, 0x18, 0xed, 0xed, 0x0f, 0x06, 0x21, 0xc5, 0xf3, 0x07, 0xb6, 0x5a, 0x17, - 0x17, 0x89, 0x57, 0xc8, 0x44, 0x0b, 0x62, 0x29, 0x02, 0x33, 0x5e, 0x68, 0x1a, 0x61, 0x82, 0x32, 0x25, 0x58, 0xb4, - 0x46, 0x87, 0xf6, 0x87, 0x25, 0xec, 0x1e, 0x63, 0x04, 0x08, 0x54, 0x99, 0x3e, 0x87, 0xad, 0x09, 0xb3, 0xad, 0x8b, - 0x2d, 0xd0, 0x56, 0x31, 0x34, 0x08, 0x6b, 0x43, 0xcc, 0xc7, 0x34, 0x5f, 0xfd, 0x13, 0x8b, 0xb1, 0x3d, 0x81, 0xd8, - 0xc1, 0xed, 0x9a, 0x84, 0xe9, 0x5e, 0x8b, 0x1b, 0xeb, 0xe5, 0xf6, 0x94, 0x63, 0x6a, 0xc7, 0xda, 0xaa, 0x1d, 0x6b, - 0xa9, 0x77, 0xac, 0x8d, 0xde, 0xb1, 0x56, 0x0d, 0xff, 0x90, 0x79, 0x31, 0x4b, 0x40, 0xbf, 0xbb, 0xe6, 0xaa, 0x41, - 0xd0, 0x8c, 0x2d, 0xbb, 0x83, 0xdf, 0x12, 0x6b, 0xb7, 0xf4, 0xaf, 0x96, 0x6c, 0x61, 0xfa, 0x40, 0xb7, 0x0e, 0xb0, - 0x8c, 0xa8, 0xc9, 0xf7, 0xc8, 0xbb, 0xe9, 0xac, 0x28, 0xdc, 0x9e, 0xd8, 0xc2, 0x67, 0x6f, 0xcd, 0x9b, 0xf7, 0x4f, - 0x23, 0xc8, 0xbd, 0xe7, 0xde, 0xfd, 0xf0, 0xad, 0x7f, 0xa5, 0x5b, 0x20, 0x27, 0xb3, 0x9c, 0x81, 0xd4, 0x11, 0x9f, - 0x20, 0x5a, 0xd9, 0x53, 0xbe, 0x13, 0x72, 0x67, 0xdb, 0x3c, 0xbd, 0x77, 0xb7, 0xb5, 0xd5, 0xd3, 0x7b, 0x96, 0x8f, - 0x28, 0x56, 0x9c, 0xa6, 0x48, 0x98, 0x45, 0x5b, 0xe0, 0xa9, 0x97, 0xef, 0x77, 0xec, 0x98, 0xc3, 0xfd, 0xd3, 0x8e, - 0x8e, 0x97, 0x73, 0xc0, 0xee, 0xfe, 0x93, 0x4d, 0xd8, 0x58, 0xe9, 0x5a, 0x85, 0x0e, 0xf7, 0x4f, 0x33, 0x8d, 0xe7, - 0x70, 0x22, 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, 0xba, 0xe4, 0xb1, 0xef, 0xd3, 0x2c, 0xad, 0xf7, 0xa8, 0xb5, 0xc8, 0x2d, 0xcb, 0xb0, 0xf6, 0x7e, 0xd0, 0x8a, - 0x61, 0xa9, 0xe9, 0x9f, 0x8e, 0x03, 0xb7, 0xb3, 0xdd, 0xca, 0xd8, 0x65, 0x3c, 0x2d, 0xae, 0x7e, 0x38, 0x2f, 0x94, - 0x6b, 0x37, 0x6f, 0xe3, 0x37, 0xad, 0x96, 0x2c, 0xad, 0xf5, 0x90, 0x97, 0x96, 0x45, 0x04, 0x02, 0x18, 0x4e, 0x94, - 0x5d, 0x2c, 0xe1, 0x1e, 0x61, 0x75, 0x0f, 0x42, 0xc9, 0xbc, 0x70, 0xf5, 0x8c, 0xc5, 0x90, 0x08, 0xb0, 0xdd, 0xa1, - 0x62, 0x5b, 0xb8, 0x7a, 0xc6, 0xb6, 0xbc, 0xe8, 0xf7, 0x33, 0xd5, 0x29, 0x64, 0xdd, 0x59, 0xf2, 0xad, 0x6a, 0x8e, - 0x35, 0xd4, 0x6c, 0x63, 0x92, 0xad, 0x71, 0x6e, 0x2b, 0x3e, 0x56, 0x6d, 0xc5, 0xc7, 0xda, 0x5a, 0x97, 0xee, 0xf5, - 0x1e, 0xd5, 0x05, 0xb0, 0xf5, 0xdf, 0x9d, 0xae, 0x5c, 0xcf, 0x67, 0x04, 0xf0, 0xb5, 0xe0, 0xe3, 0xc9, 0x02, 0xbd, - 0x4a, 0x16, 0xfe, 0xdd, 0x40, 0x8d, 0xbf, 0xd3, 0xb9, 0x0b, 0x80, 0xae, 0xa4, 0xbc, 0x02, 0xf2, 0x0e, 0x2a, 0xcc, - 0x2d, 0xbb, 0xf2, 0xfe, 0xec, 0x3b, 0xec, 0x2d, 0xaf, 0x67, 0x8b, 0x39, 0xdb, 0x83, 0x53, 0x41, 0x32, 0xb0, 0x97, - 0x15, 0xdb, 0x07, 0xb1, 0x9d, 0xf0, 0x1b, 0x01, 0x53, 0xbe, 0x80, 0x20, 0xae, 0xe0, 0x0e, 0xe2, 0xf0, 0xe4, 0x9f, - 0x83, 0xfb, 0xd6, 0x66, 0x7d, 0xcf, 0xac, 0xce, 0x09, 0x36, 0xcc, 0xea, 0xc1, 0x60, 0xd9, 0x4c, 0xd6, 0xfd, 0xbe, - 0xb7, 0xd7, 0x8e, 0x4f, 0x2b, 0xa9, 0x13, 0x3b, 0xaf, 0xd5, 0x5a, 0xb0, 0xb7, 0x52, 0xeb, 0x62, 0x0c, 0x3d, 0x80, - 0x5f, 0x70, 0x37, 0xe0, 0xf7, 0x1d, 0x6b, 0xcb, 0x7b, 0xcb, 0x16, 0x6c, 0x0f, 0x97, 0xa0, 0xa6, 0xbd, 0xec, 0xcf, - 0x2a, 0x17, 0xb4, 0x63, 0x97, 0xc4, 0xc3, 0x19, 0xb3, 0x5c, 0x99, 0x59, 0x27, 0xf9, 0x8d, 0xe8, 0x8c, 0xe9, 0xac, - 0xf5, 0x7c, 0xce, 0xe7, 0x93, 0x42, 0x83, 0xfa, 0x5d, 0x12, 0x1f, 0x51, 0xd1, 0x79, 0x02, 0x5b, 0xcb, 0x0a, 0xc8, - 0xbd, 0x2e, 0xc1, 0x5a, 0xab, 0x5d, 0xfa, 0xbd, 0x6a, 0xc0, 0x6d, 0xca, 0x61, 0x4d, 0x40, 0xd0, 0x9c, 0x59, 0x51, - 0x8f, 0xd9, 0x8e, 0x71, 0xf3, 0xd3, 0xcb, 0x1f, 0x9c, 0xb0, 0x64, 0xc5, 0x6a, 0x7f, 0xfa, 0xc3, 0x53, 0x4f, 0x7f, - 0xa7, 0xf6, 0xaf, 0x84, 0x1f, 0x8c, 0xff, 0x5d, 0xbb, 0xaf, 0xb5, 0x18, 0x95, 0xad, 0x72, 0x84, 0xc6, 0xdd, 0x4a, - 0x9a, 0x2c, 0x3f, 0x09, 0x4f, 0x58, 0x0b, 0x9e, 0x99, 0x33, 0x20, 0x2b, 0x60, 0x85, 0xb5, 0x4c, 0xc2, 0x39, 0xc6, - 0x6a, 0x69, 0xab, 0x6f, 0xd1, 0x34, 0xa7, 0x87, 0x73, 0x6d, 0x50, 0xa6, 0x9c, 0x9d, 0x11, 0xab, 0xe1, 0x32, 0x2c, - 0x4d, 0x28, 0x42, 0xf6, 0x60, 0x07, 0x37, 0x76, 0xca, 0x52, 0xca, 0x70, 0x8e, 0xc1, 0x84, 0x27, 0x62, 0x54, 0xee, - 0xfb, 0x87, 0x92, 0x57, 0x6d, 0x39, 0x28, 0x47, 0xd8, 0x47, 0x12, 0x25, 0x70, 0x2b, 0xd2, 0x42, 0x91, 0xb2, 0xf8, - 0xdb, 0x01, 0xba, 0xc0, 0x0b, 0xa8, 0xab, 0x51, 0xb7, 0x3f, 0x1c, 0xf1, 0xf0, 0x91, 0xa9, 0x0f, 0x8c, 0x58, 0x12, - 0xa8, 0xed, 0x45, 0x96, 0xae, 0x40, 0x85, 0xdf, 0xc3, 0xd5, 0x44, 0xec, 0xe7, 0x96, 0x14, 0x15, 0xd9, 0x48, 0x6f, - 0x68, 0x0d, 0x1e, 0xa1, 0x35, 0xe5, 0x07, 0x27, 0xd5, 0x26, 0x9d, 0x77, 0x84, 0x1c, 0xab, 0x6f, 0x2d, 0x61, 0xb4, - 0x2b, 0x7a, 0xf1, 0xe0, 0xe8, 0x3d, 0xcf, 0x57, 0xbd, 0xf2, 0x27, 0xae, 0x98, 0x27, 0xb7, 0x11, 0xa8, 0x5b, 0x41, - 0x75, 0x7b, 0xaf, 0x12, 0x2c, 0x58, 0xd2, 0xee, 0xe3, 0xb7, 0xb3, 0x76, 0x20, 0x2a, 0x63, 0x95, 0xbe, 0x26, 0x09, - 0x7b, 0x62, 0xd0, 0x29, 0x54, 0x55, 0x76, 0x77, 0xb4, 0x05, 0xae, 0x53, 0x96, 0xa2, 0x17, 0xb6, 0xc8, 0xdd, 0xf2, - 0xef, 0x9e, 0x2b, 0x72, 0xf6, 0x6b, 0x40, 0x70, 0x6a, 0xbe, 0x22, 0xbe, 0x9c, 0xe0, 0x51, 0x75, 0x0b, 0x1c, 0xe7, - 0xef, 0x00, 0xfe, 0xf1, 0x78, 0x0d, 0x9a, 0x80, 0x58, 0xb0, 0x5e, 0x1a, 0xf7, 0x58, 0x2f, 0x2e, 0xb6, 0xab, 0x24, - 0xdf, 0x82, 0x33, 0x03, 0xa5, 0x5a, 0xfa, 0x81, 0x53, 0xb5, 0x80, 0x0a, 0x07, 0xb3, 0x93, 0x7a, 0x61, 0x19, 0xf5, - 0x98, 0x3e, 0x3f, 0x83, 0x83, 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, 0x8f, 0xf1, 0x77, 0x3d, 0x23, 0x23, 0x8f, 0x5b, 0x87, 0xd5, 0xff, 0xfa, 0x4f, - 0x08, 0x80, 0xc3, 0xb3, 0xa9, 0x77, 0x3d, 0x86, 0xac, 0xb2, 0x8c, 0x40, 0xf2, 0x13, 0x83, 0x2f, 0x5f, 0x00, 0x54, - 0x7d, 0xa6, 0x6b, 0x35, 0x39, 0x6a, 0x8f, 0x39, 0x74, 0xc5, 0x00, 0xb0, 0x0d, 0x4b, 0x54, 0xd5, 0xc2, 0x26, 0x2c, - 0x6e, 0x3f, 0xc3, 0x68, 0x2e, 0x9b, 0x5e, 0xd0, 0x40, 0x3d, 0x42, 0xf0, 0x4b, 0xeb, 0xa1, 0xb5, 0x96, 0x29, 0x87, - 0xae, 0x8d, 0xa2, 0xca, 0x86, 0xba, 0x84, 0xd5, 0x46, 0x44, 0x35, 0x51, 0xa4, 0x5c, 0x33, 0x8a, 0x62, 0xa9, 0x82, - 0x43, 0x26, 0x56, 0x10, 0x35, 0x4f, 0x5b, 0x6d, 0x15, 0x1c, 0x56, 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, 0x8a, 0x20, 0xb2, 0x00, 0x01, 0x1c, 0x37, 0x10, 0xf8, 0xbc, 0xc6, 0x27, 0xd0, 0x28, 0x04, - 0xf2, 0x03, 0xeb, 0x70, 0xe3, 0x21, 0x2d, 0xb5, 0x46, 0x44, 0x89, 0xf8, 0xc9, 0xd5, 0x73, 0x6c, 0x5f, 0x3d, 0x8d, - 0xb5, 0xa5, 0x34, 0x41, 0xfc, 0xc4, 0x62, 0x0b, 0x31, 0x41, 0x54, 0x87, 0xe8, 0x04, 0x96, 0x13, 0x42, 0x14, 0xfe, - 0x10, 0xfa, 0xa9, 0x81, 0xbf, 0x64, 0xcb, 0x22, 0xaf, 0x09, 0x16, 0x33, 0x67, 0x80, 0x56, 0x45, 0xe0, 0x99, 0xce, - 0x96, 0xca, 0x9c, 0xe6, 0xd1, 0x91, 0x1d, 0x5c, 0x76, 0x1d, 0xec, 0xa5, 0x2f, 0x63, 0x27, 0xcb, 0xa6, 0x51, 0x1b, - 0x1b, 0x22, 0xe1, 0x15, 0xf9, 0xcb, 0x2c, 0x35, 0xce, 0x91, 0x6a, 0x7d, 0xd7, 0xc5, 0x6a, 0x45, 0xdb, 0x84, 0x55, - 0x88, 0x50, 0xb7, 0x0d, 0x95, 0x4b, 0x61, 0x36, 0x36, 0x4d, 0x03, 0x7c, 0xa1, 0xa8, 0x54, 0xca, 0x53, 0x5b, 0xa9, - 0xe4, 0x84, 0x77, 0x7d, 0x55, 0x8b, 0xd4, 0x15, 0xc1, 0x36, 0x66, 0xa8, 0x87, 0x72, 0xa3, 0xc6, 0xbe, 0xee, 0x58, - 0xa5, 0x77, 0x98, 0xa0, 0x62, 0xe4, 0x45, 0x0e, 0x2e, 0x4a, 0x0a, 0x32, 0x57, 0x43, 0x98, 0x3f, 0x6a, 0xf8, 0xb4, - 0xb0, 0xdc, 0x43, 0x09, 0x98, 0x1d, 0x35, 0xbc, 0x8c, 0x10, 0x88, 0xb8, 0x54, 0xf6, 0x15, 0x13, 0xbf, 0xa7, 0x60, - 0x96, 0x4c, 0xe8, 0x5e, 0xc4, 0xc2, 0x08, 0x6d, 0x7c, 0x92, 0x24, 0x53, 0xb9, 0x3e, 0x41, 0x17, 0x2a, 0x5c, 0x20, - 0x23, 0xb4, 0x48, 0xf3, 0x4f, 0x87, 0x53, 0x09, 0x3e, 0xa2, 0x4e, 0x01, 0xc7, 0xf3, 0xcb, 0xc2, 0xfa, 0xc9, 0x2a, - 0x89, 0xb9, 0xac, 0xcd, 0x7f, 0xd9, 0xc9, 0x31, 0xd8, 0xe5, 0x69, 0xe2, 0xb8, 0xfa, 0x8f, 0xaa, 0xa4, 0x78, 0xf8, - 0x39, 0xcd, 0x01, 0x45, 0x30, 0xb3, 0xa7, 0x18, 0x1f, 0xfb, 0x2c, 0x53, 0xc0, 0xdf, 0xae, 0xb7, 0x96, 0x4c, 0xec, - 0x92, 0x76, 0x2b, 0x65, 0xfc, 0x52, 0x1b, 0x76, 0x1c, 0x5c, 0x1a, 0x80, 0xe2, 0xac, 0xd1, 0x61, 0x79, 0xad, 0xdb, - 0x56, 0x8e, 0x0a, 0xd4, 0xfa, 0xdf, 0xbb, 0x85, 0x29, 0x6f, 0xf3, 0x52, 0x79, 0x9b, 0x87, 0x26, 0x40, 0x20, 0x32, - 0x43, 0x9e, 0x35, 0x1d, 0x93, 0xc4, 0xbd, 0x23, 0x25, 0xed, 0x3b, 0x52, 0xfc, 0xe8, 0x1d, 0x09, 0xf9, 0x96, 0xd0, - 0x91, 0x7d, 0xc9, 0xc9, 0x09, 0x94, 0x19, 0xec, 0xe5, 0x0d, 0x93, 0xfd, 0x03, 0xda, 0x0b, 0xe7, 0xb2, 0xbc, 0xe6, - 0x6f, 0x85, 0xb7, 0xf1, 0xa7, 0x9b, 0xf3, 0xae, 0xaa, 0x77, 0x5f, 0x99, 0x99, 0xc7, 0x63, 0x71, 0x3c, 0xe6, 0x26, - 0x68, 0x77, 0xc1, 0xc5, 0xa0, 0x62, 0xf7, 0x6e, 0x7c, 0xfc, 0x5b, 0x8e, 0x22, 0xb6, 0x52, 0x1e, 0x49, 0x17, 0x2a, - 0x31, 0xbc, 0x36, 0xf0, 0x30, 0x7b, 0x3e, 0x9e, 0xec, 0x6f, 0xee, 0x27, 0x83, 0xc1, 0x5e, 0xf5, 0xed, 0x8e, 0xd7, - 0xb3, 0xfd, 0x9c, 0x3d, 0xf0, 0xbb, 0xe9, 0x2e, 0x38, 0x34, 0xb0, 0xed, 0xee, 0x6f, 0xc4, 0xf1, 0xb8, 0x7f, 0xce, - 0x17, 0xfe, 0xe1, 0x01, 0x01, 0x9d, 0xf9, 0xe5, 0xb8, 0x8d, 0xf1, 0x73, 0xdb, 0x76, 0xd5, 0xda, 0x03, 0x3c, 0xfd, - 0x8f, 0xde, 0xed, 0x6c, 0x39, 0xf7, 0xd9, 0x13, 0xfe, 0x00, 0xfe, 0xf9, 0xb8, 0x49, 0x22, 0xf5, 0x89, 0x76, 0x99, - 0xbc, 0x05, 0x07, 0xf2, 0xbd, 0xcf, 0xde, 0xf0, 0x87, 0xd9, 0x72, 0xce, 0x8b, 0xe3, 0xf1, 0xfd, 0x34, 0x44, 0xb2, - 0xa6, 0xb0, 0x22, 0x96, 0x14, 0xcf, 0x0f, 0xc2, 0xd3, 0xf7, 0x22, 0x32, 0x44, 0x5a, 0xee, 0xdd, 0x21, 0xbb, 0x65, - 0x91, 0x1f, 0xc0, 0x07, 0xd9, 0xde, 0x9f, 0xc8, 0x9a, 0xd2, 0xfd, 0xe2, 0x89, 0x7f, 0x3c, 0xd2, 0x5f, 0x6f, 0xfc, - 0xe3, 0xf1, 0x3d, 0x7b, 0x40, 0x70, 0x74, 0xbe, 0x87, 0xfe, 0xd1, 0xb7, 0x0e, 0xa8, 0xca, 0xf0, 0xed, 0x6c, 0x3b, - 0xf7, 0x9f, 0xaf, 0xd9, 0x0a, 0xb8, 0x50, 0x94, 0x17, 0xda, 0x2d, 0x7b, 0x40, 0xaf, 0x33, 0x72, 0x22, 0x9a, 0xed, - 0xe7, 0x3e, 0x8b, 0xf1, 0xb9, 0xba, 0x2f, 0x26, 0x5f, 0xbd, 0x2f, 0xee, 0xd9, 0xae, 0xfb, 0xbe, 0x28, 0xdf, 0x74, - 0xd7, 0xcf, 0x8e, 0xed, 0xd9, 0x03, 0xcc, 0xb0, 0xb7, 0xfc, 0xb6, 0x39, 0x75, 0x8c, 0xfd, 0xea, 0x8d, 0x11, 0x40, - 0x99, 0x2d, 0x58, 0x2c, 0x38, 0x28, 0xd5, 0xaa, 0x6d, 0x49, 0xe4, 0xb9, 0x0e, 0x54, 0x9b, 0x11, 0xdc, 0x97, 0xde, - 0xa2, 0xd4, 0x45, 0x4f, 0xfb, 0x14, 0xe4, 0x88, 0x16, 0x0e, 0x1b, 0xf0, 0x57, 0xda, 0x3a, 0xc6, 0x30, 0xcd, 0x7c, - 0xa6, 0x1d, 0x3d, 0xaf, 0xbf, 0xed, 0x3d, 0x93, 0xdf, 0xc8, 0xc0, 0x16, 0x22, 0x29, 0x1c, 0xc7, 0x57, 0xcf, 0xce, - 0xf8, 0xaf, 0x5a, 0x1e, 0xb5, 0xda, 0x2f, 0x94, 0xfa, 0xf4, 0x25, 0x1d, 0xd1, 0xc4, 0xbd, 0x68, 0xcb, 0xb0, 0x46, - 0x59, 0x53, 0x4b, 0x87, 0x61, 0x5c, 0xc3, 0xbe, 0x3c, 0x70, 0xe8, 0x3b, 0x20, 0xd0, 0xe6, 0xa9, 0x14, 0x68, 0xe1, - 0x18, 0x46, 0x61, 0x16, 0x52, 0x1e, 0x17, 0x66, 0x29, 0xef, 0xa9, 0x40, 0x8b, 0x5b, 0x75, 0x8f, 0xa9, 0xed, 0x16, - 0x44, 0x58, 0xbd, 0x65, 0x5c, 0x5e, 0x37, 0xaa, 0x70, 0x5b, 0x80, 0xa2, 0x08, 0xca, 0xe0, 0x40, 0x72, 0xdb, 0x42, - 0x49, 0xb3, 0x51, 0x58, 0x8b, 0x55, 0x51, 0xee, 0x7b, 0x0d, 0x5b, 0xe0, 0x05, 0x55, 0x3f, 0x21, 0x6c, 0xcb, 0x9e, - 0x75, 0x28, 0x17, 0xe9, 0xbf, 0x65, 0xe9, 0xf9, 0x76, 0x6b, 0xce, 0xff, 0xf4, 0x15, 0x7d, 0x54, 0xfe, 0xfb, 0x97, - 0xf4, 0xb3, 0xc1, 0x32, 0x72, 0x4a, 0xfd, 0x10, 0x8d, 0xee, 0xd2, 0x9c, 0x30, 0xb6, 0x7c, 0xfd, 0xf4, 0x1b, 0x64, - 0x0a, 0x92, 0x43, 0x29, 0x55, 0x39, 0xd9, 0x43, 0x5f, 0x78, 0xdd, 0x87, 0x99, 0x60, 0x00, 0xc2, 0x6b, 0xb4, 0xa9, - 0x26, 0x4c, 0xe2, 0xd1, 0x15, 0xfc, 0xdf, 0x08, 0x62, 0xd0, 0x3e, 0x51, 0xd4, 0xb1, 0x6d, 0xa4, 0xeb, 0xb6, 0x73, - 0x90, 0xdc, 0xa9, 0x73, 0x7f, 0x54, 0x4e, 0xfe, 0x1d, 0x0d, 0x91, 0x57, 0xdc, 0x20, 0x56, 0x16, 0x5c, 0x62, 0x31, - 0x54, 0xa4, 0x00, 0xd7, 0x10, 0x44, 0xca, 0xa2, 0xa4, 0x70, 0xc7, 0x41, 0x55, 0x04, 0x60, 0x5c, 0xad, 0x8e, 0x3a, - 0x13, 0x3e, 0x6e, 0xad, 0x45, 0x88, 0x3a, 0x34, 0x6a, 0x65, 0xad, 0xc0, 0x17, 0xa4, 0x2f, 0x1d, 0x0a, 0x62, 0x7a, - 0x14, 0x52, 0x55, 0x3a, 0x14, 0x48, 0x73, 0xa8, 0xf8, 0xc6, 0x60, 0xa3, 0xc8, 0x49, 0xcf, 0x5f, 0x9a, 0x14, 0x65, - 0xcc, 0xf8, 0x20, 0xca, 0x48, 0xe4, 0x75, 0xb8, 0x12, 0xd3, 0x02, 0xf9, 0x46, 0x4f, 0x1f, 0x04, 0xd7, 0xf0, 0x6e, - 0xc8, 0xbd, 0x02, 0x6c, 0x09, 0xd8, 0x01, 0xee, 0x95, 0x19, 0xe5, 0x3a, 0xad, 0xeb, 0xb7, 0xd6, 0x43, 0x31, 0x0c, - 0x9f, 0x5a, 0x02, 0xdb, 0xc9, 0x3a, 0x3a, 0xd1, 0xc3, 0x87, 0xff, 0x75, 0x55, 0x73, 0xd4, 0xa9, 0x5c, 0xce, 0x4e, - 0x27, 0x2c, 0x45, 0xcc, 0xa0, 0xfb, 0xeb, 0xee, 0xa5, 0x00, 0xba, 0x5d, 0x16, 0xf3, 0x6c, 0xb4, 0x97, 0x7f, 0x4b, - 0x37, 0x56, 0x94, 0x36, 0xf1, 0x2e, 0xeb, 0x8d, 0xfd, 0xe1, 0xe8, 0x3f, 0x9e, 0xbe, 0x9b, 0x10, 0xaa, 0xce, 0x96, - 0x6d, 0x74, 0x9c, 0xcb, 0xff, 0xfa, 0xcf, 0x31, 0x59, 0x41, 0x50, 0x10, 0x96, 0x9d, 0x62, 0xa2, 0x82, 0x51, 0xa4, - 0xd8, 0xf0, 0xf1, 0x64, 0x83, 0x3a, 0xe1, 0x8d, 0xbf, 0xd4, 0x3a, 0x61, 0x62, 0x64, 0xa5, 0xf2, 0x37, 0x2c, 0x67, - 0x2b, 0x95, 0x59, 0x40, 0xe6, 0x41, 0x35, 0xd9, 0x18, 0x0d, 0xe6, 0x9a, 0xd7, 0xb3, 0xcd, 0x5c, 0x2a, 0x9f, 0xc1, - 0x94, 0xb3, 0x1c, 0x9c, 0x2d, 0x85, 0xdd, 0x93, 0x40, 0xd1, 0x9a, 0xa1, 0x1b, 0x7f, 0x8a, 0xad, 0x7a, 0x95, 0x56, - 0x35, 0xc0, 0x03, 0x42, 0x0c, 0x0c, 0xb5, 0x57, 0x0b, 0x0f, 0xad, 0x05, 0xb0, 0xf1, 0x47, 0xa5, 0x1f, 0x8c, 0x27, - 0x4b, 0xbe, 0x40, 0xfe, 0xe5, 0xc8, 0x51, 0xbb, 0xf7, 0xfb, 0xde, 0x3d, 0x48, 0xc1, 0x91, 0x6b, 0xa1, 0x40, 0x22, - 0xa0, 0x05, 0xdf, 0xfa, 0xca, 0x07, 0xe3, 0x2d, 0x6a, 0xab, 0x41, 0x41, 0xed, 0xe8, 0x96, 0xc7, 0x8e, 0xde, 0xf9, - 0xfe, 0x8c, 0xbe, 0x7a, 0xa1, 0x85, 0xe3, 0xaf, 0x9c, 0x91, 0x1b, 0xb6, 0xee, 0x90, 0x23, 0x9a, 0x49, 0x87, 0x10, - 0xb1, 0x66, 0x1b, 0xf6, 0x96, 0x54, 0xce, 0x9d, 0x43, 0x76, 0xfe, 0x08, 0x55, 0x7a, 0xad, 0xc7, 0xb7, 0x13, 0xa5, - 0xbb, 0x3d, 0xdd, 0x4d, 0xbe, 0x65, 0x13, 0x11, 0x83, 0x01, 0x6d, 0x10, 0xce, 0xc8, 0x3a, 0x44, 0x2a, 0x1d, 0x20, - 0x04, 0x8e, 0x09, 0x68, 0xfa, 0xf7, 0xaf, 0x49, 0x14, 0x70, 0xa4, 0x8d, 0x90, 0xb5, 0xec, 0x78, 0xac, 0x40, 0xa3, - 0xdc, 0xfc, 0xe1, 0x15, 0xea, 0x34, 0x07, 0xe6, 0xe9, 0x12, 0xf6, 0x1c, 0x3c, 0xd2, 0x8b, 0xd3, 0x23, 0xfd, 0xbf, - 0xa3, 0x89, 0x1a, 0xff, 0xfb, 0x9a, 0x28, 0xa5, 0x45, 0x72, 0x54, 0x4b, 0xdf, 0xa4, 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, 0x7e, 0x26, 0x09, 0x91, 0xe1, 0xd2, 0x80, 0x1f, 0x55, 0x70, 0x88, 0xd3, 0x6a, - 0x93, 0x85, 0x7b, 0x54, 0xa2, 0xde, 0x89, 0x55, 0x9a, 0xbf, 0xa8, 0xff, 0x25, 0xca, 0x02, 0xa6, 0xf6, 0xaa, 0x4c, - 0xe3, 0x80, 0x2c, 0xfc, 0x59, 0x58, 0xe2, 0xe4, 0xc6, 0x36, 0xfe, 0x2c, 0xc7, 0xd3, 0x7e, 0xd5, 0x99, 0x79, 0x20, - 0x81, 0x1a, 0x88, 0x3f, 0x72, 0x2e, 0x2b, 0x8b, 0x07, 0x84, 0x6e, 0xfe, 0xb1, 0x2c, 0x8b, 0xd2, 0xeb, 0x7d, 0x4a, - 0xd2, 0xea, 0x62, 0x2d, 0xea, 0xa4, 0x88, 0x15, 0x94, 0x4d, 0x0a, 0x30, 0xfa, 0xb0, 0xf2, 0x44, 0x1c, 0x5c, 0x20, - 0x50, 0xc3, 0x45, 0x9d, 0x84, 0x00, 0x34, 0xac, 0x10, 0xf6, 0x2f, 0xa0, 0x85, 0x17, 0x61, 0x1c, 0x6e, 0x00, 0x26, - 0x27, 0xad, 0x2e, 0x36, 0x65, 0x71, 0x9f, 0xc6, 0x22, 0x1e, 0xf5, 0x14, 0x25, 0xcb, 0xc7, 0xca, 0x95, 0x73, 0xfd, - 0xc3, 0x1f, 0x14, 0xc0, 0x6e, 0xc0, 0x6c, 0x5b, 0x60, 0x07, 0x00, 0x09, 0x0a, 0x64, 0x0b, 0x75, 0x1a, 0x5d, 0xa8, - 0xa5, 0x02, 0xef, 0xb9, 0x1e, 0xe0, 0x1f, 0x2b, 0xc0, 0x32, 0xae, 0x0b, 0x19, 0x30, 0x82, 0x00, 0x46, 0xe0, 0xa0, - 0x04, 0x0c, 0x9d, 0x61, 0x6d, 0xf1, 0xb8, 0x43, 0x73, 0xa5, 0xdb, 0x92, 0x9b, 0x46, 0x39, 0x5b, 0x89, 0x00, 0xfa, - 0xea, 0xa6, 0xc4, 0xe9, 0x72, 0xd9, 0x4a, 0xc2, 0xbe, 0x7d, 0xdf, 0x4e, 0x15, 0x79, 0x7c, 0x92, 0x86, 0xbc, 0x02, - 0x4f, 0x32, 0x8e, 0x24, 0x51, 0x22, 0xf8, 0x58, 0x35, 0x66, 0x1c, 0x5e, 0xb4, 0x29, 0xa7, 0x0e, 0x66, 0xbd, 0x00, - 0x9c, 0x27, 0x68, 0xcb, 0x00, 0x63, 0x01, 0x83, 0x73, 0x21, 0x96, 0x3c, 0x45, 0xf0, 0x4b, 0x27, 0x52, 0x18, 0x77, - 0x39, 0x0c, 0xf3, 0xa0, 0xe8, 0x5d, 0x52, 0x7f, 0xf4, 0xfb, 0xa8, 0x4d, 0x06, 0x43, 0x50, 0x09, 0xa0, 0xb2, 0x6e, - 0x90, 0x18, 0x58, 0x95, 0x16, 0x12, 0x97, 0x10, 0x2f, 0xf3, 0xd5, 0xb4, 0x8e, 0x82, 0xf7, 0xf5, 0x84, 0x10, 0x4e, - 0x30, 0x3e, 0xc4, 0x0d, 0x10, 0x30, 0x58, 0xc5, 0x05, 0x06, 0xc9, 0x73, 0x89, 0xee, 0x8f, 0xe7, 0x3b, 0x06, 0xb8, - 0x72, 0xde, 0x53, 0xed, 0xea, 0x81, 0xbd, 0x5c, 0xa5, 0x4b, 0x46, 0x08, 0x2b, 0xfe, 0x2f, 0x22, 0xef, 0xdb, 0x61, - 0x02, 0x6a, 0x1b, 0xf9, 0x63, 0x90, 0x98, 0xcb, 0x44, 0x11, 0xc4, 0xa3, 0xac, 0x60, 0x49, 0x1a, 0x6c, 0x47, 0x49, - 0x0a, 0x1a, 0x4d, 0x8c, 0x21, 0x53, 0xa1, 0x1d, 0x92, 0x46, 0xb3, 0x31, 0xd9, 0xc7, 0x90, 0xd7, 0x70, 0xb1, 0x58, - 0xe0, 0x7d, 0x3f, 0x0b, 0xd5, 0xc1, 0xb6, 0x34, 0x87, 0x80, 0x93, 0x04, 0x7b, 0xea, 0x8a, 0x94, 0x84, 0xd9, 0xe8, - 0x53, 0xc8, 0xb9, 0x01, 0x1d, 0x27, 0x8d, 0xa1, 0xfa, 0xc0, 0x24, 0xbc, 0x89, 0xd0, 0x49, 0x59, 0x21, 0x2c, 0xe0, - 0xbe, 0x91, 0xd1, 0x68, 0x25, 0x0d, 0x02, 0x6f, 0x33, 0x6c, 0x05, 0x36, 0xa1, 0xe1, 0x2f, 0x32, 0x0f, 0xd3, 0x6a, - 0x56, 0x82, 0x39, 0xdf, 0x40, 0x25, 0xc6, 0x93, 0xe5, 0x0d, 0xdf, 0xba, 0x58, 0x89, 0xc9, 0x6c, 0x39, 0x9f, 0x6c, - 0x24, 0xd5, 0x1c, 0x08, 0x19, 0x19, 0x5b, 0xc2, 0xfe, 0x61, 0x60, 0x28, 0x1d, 0xd8, 0xd1, 0x54, 0xd3, 0x26, 0x01, - 0x26, 0xd3, 0x25, 0xe7, 0xc3, 0x6b, 0x44, 0x93, 0xd5, 0xa9, 0x7b, 0x99, 0xaa, 0x76, 0x70, 0x4d, 0xce, 0xe4, 0xf4, - 0x48, 0x3d, 0xd5, 0xba, 0x97, 0x6a, 0xb4, 0x1b, 0xe6, 0xa3, 0x9d, 0x1f, 0x80, 0x5b, 0xa7, 0xb0, 0xd3, 0xf7, 0xc3, - 0x7c, 0xb4, 0xf7, 0x35, 0xec, 0x2e, 0x29, 0x04, 0xaa, 0x3f, 0xcb, 0x9a, 0xcc, 0xc5, 0x9b, 0xe2, 0xc1, 0x2b, 0xd8, - 0x33, 0x7f, 0xa0, 0x7f, 0x95, 0xec, 0x99, 0x6f, 0x33, 0xb9, 0xfe, 0x99, 0x76, 0x8d, 0xc6, 0x4c, 0xc7, 0x6b, 0xe7, - 0x60, 0x85, 0x06, 0xc8, 0x2f, 0xd8, 0xd1, 0xde, 0xe4, 0x20, 0x10, 0xa0, 0x7b, 0x09, 0x8e, 0xa2, 0x80, 0xa8, 0x69, - 0x55, 0x79, 0x74, 0xba, 0xf7, 0x0f, 0xf8, 0x46, 0x09, 0xd8, 0xe4, 0xa9, 0x75, 0x6f, 0x19, 0xfb, 0xc7, 0x23, 0x84, - 0xd0, 0xcb, 0xe9, 0x37, 0xda, 0xb1, 0x7a, 0xb4, 0x67, 0x12, 0xfc, 0x1c, 0x31, 0xe9, 0x15, 0x8c, 0x61, 0xe8, 0xc2, - 0x2a, 0x46, 0xf2, 0x0c, 0xc8, 0x1a, 0xbf, 0x41, 0x74, 0x01, 0x8b, 0x5e, 0xef, 0xd5, 0x09, 0x0d, 0x22, 0xa0, 0xd2, - 0x6b, 0xfe, 0x52, 0xe4, 0x73, 0x55, 0x88, 0xde, 0x07, 0x6b, 0xe7, 0xcd, 0x8c, 0x64, 0x99, 0x34, 0x52, 0xed, 0x56, - 0x16, 0x9b, 0xca, 0x9b, 0x9d, 0x91, 0x2e, 0xe6, 0x18, 0x2a, 0x83, 0xc7, 0x01, 0x28, 0x3d, 0xff, 0x12, 0x7a, 0x25, - 0x43, 0xa6, 0x59, 0xa2, 0x99, 0xdd, 0x37, 0xfe, 0x64, 0x9d, 0x7a, 0x31, 0x22, 0x66, 0x03, 0x5b, 0x88, 0xdb, 0xa2, - 0xd2, 0x6d, 0x51, 0x28, 0x5b, 0x14, 0xe9, 0x43, 0xed, 0x42, 0x77, 0x66, 0xe1, 0xb3, 0xdc, 0xb4, 0xef, 0x4d, 0x66, - 0xc6, 0x06, 0x68, 0xbb, 0x08, 0xdf, 0x40, 0x07, 0x2a, 0x84, 0xfc, 0x47, 0x44, 0x44, 0x22, 0x60, 0x97, 0x73, 0x77, - 0x62, 0xd3, 0x21, 0x99, 0x87, 0x98, 0x15, 0x6a, 0x94, 0x97, 0x3c, 0x39, 0x19, 0x90, 0x9c, 0x50, 0xb7, 0xfb, 0xfd, - 0xcb, 0xa5, 0x0b, 0x6a, 0xbf, 0xa1, 0xd8, 0x31, 0xba, 0x29, 0xe0, 0x5c, 0xf0, 0x28, 0xef, 0xa5, 0x77, 0x09, 0x68, - 0x8e, 0xed, 0x29, 0xb2, 0x01, 0x9c, 0xde, 0x76, 0x21, 0xc0, 0xf6, 0x59, 0xb3, 0x8d, 0x3f, 0x59, 0xdf, 0x44, 0x53, - 0xaf, 0xe4, 0x33, 0xdd, 0x45, 0x89, 0xdb, 0x45, 0xb1, 0xec, 0xa2, 0x6d, 0x03, 0xc1, 0x8e, 0x6b, 0x3f, 0x00, 0xde, - 0xd0, 0xa8, 0xdf, 0x2f, 0x5b, 0x3d, 0x7b, 0xf6, 0xb5, 0xd3, 0x9e, 0xcd, 0x7c, 0x56, 0x9a, 0x9e, 0xfd, 0x35, 0x75, - 0x7b, 0x56, 0x4e, 0xf6, 0xa2, 0x73, 0xb2, 0x4f, 0x67, 0xf3, 0x40, 0x70, 0xb9, 0x73, 0x5f, 0x56, 0x53, 0x3d, 0xed, - 0x72, 0x3f, 0x68, 0x0d, 0x91, 0xf9, 0xc2, 0xa7, 0xbc, 0x7b, 0x5d, 0xc1, 0x02, 0x96, 0xe0, 0x6e, 0xbd, 0x34, 0xff, - 0x15, 0xbb, 0xbf, 0x17, 0xf4, 0xd2, 0xfc, 0x37, 0xfa, 0x93, 0x02, 0x38, 0x00, 0x8d, 0xa9, 0xdd, 0x02, 0x0f, 0x31, - 0x54, 0x50, 0xb8, 0x9b, 0x95, 0x73, 0xaf, 0x06, 0x38, 0x4c, 0xd2, 0x37, 0xb4, 0x7a, 0xa5, 0xc5, 0xae, 0x97, 0xc9, - 0x5e, 0x01, 0x1e, 0xaa, 0x90, 0x87, 0xc7, 0x63, 0xd4, 0x31, 0xec, 0xa0, 0x8e, 0x80, 0x61, 0x0f, 0xa1, 0xb1, 0x05, - 0x9e, 0x8f, 0x9f, 0x32, 0x7e, 0x10, 0xa0, 0x36, 0x42, 0x78, 0xbc, 0x5a, 0x94, 0x21, 0xb6, 0xec, 0x0d, 0x52, 0x49, - 0xfd, 0x2c, 0x10, 0x65, 0xb4, 0x0a, 0x68, 0xab, 0x3d, 0x65, 0x69, 0xbc, 0x85, 0x50, 0xb1, 0xd4, 0xc7, 0x10, 0x1a, - 0x38, 0xfc, 0x8e, 0x47, 0x90, 0xe0, 0x4b, 0xae, 0xc9, 0xe6, 0xde, 0xe4, 0xf7, 0xb4, 0xcf, 0x1f, 0x8f, 0x97, 0xd7, - 0x08, 0x4a, 0x97, 0xc2, 0x47, 0x2a, 0x11, 0xd5, 0x53, 0xdc, 0x94, 0x90, 0xcd, 0x92, 0x95, 0x7e, 0xf0, 0xab, 0xfa, - 0x05, 0x00, 0xb2, 0x10, 0x68, 0x13, 0x99, 0xfd, 0xe9, 0x42, 0x45, 0x17, 0x00, 0x87, 0xf8, 0xe3, 0x27, 0x88, 0xbe, - 0xa1, 0x65, 0x5a, 0x3e, 0x4e, 0x78, 0x08, 0x5a, 0x5b, 0xd2, 0x49, 0xc4, 0x4a, 0x81, 0x0d, 0x91, 0xf0, 0xfd, 0xfe, - 0x65, 0x2c, 0xe9, 0x40, 0xa3, 0x56, 0xf7, 0xc6, 0xad, 0xee, 0x95, 0xaf, 0xeb, 0x4e, 0x6e, 0x7c, 0x50, 0xb4, 0xcf, - 0xe6, 0x8d, 0xca, 0xf7, 0x6d, 0x9d, 0xb3, 0x3f, 0xdf, 0x3b, 0x72, 0x4e, 0x7c, 0x7b, 0x0f, 0xa1, 0xe8, 0xa1, 0x29, - 0xb2, 0x2c, 0x09, 0x03, 0x5a, 0x6b, 0xd7, 0x9e, 0x65, 0x74, 0xf0, 0xda, 0x37, 0x84, 0x88, 0x3c, 0xc5, 0x27, 0x21, - 0xb7, 0x38, 0x3e, 0x28, 0xd0, 0x3f, 0x33, 0xfe, 0xcc, 0x89, 0x1f, 0xb6, 0xfa, 0x05, 0x70, 0x6e, 0xba, 0xf7, 0xee, - 0xc4, 0xac, 0xc7, 0x50, 0xca, 0xc6, 0xff, 0xfd, 0x3e, 0x91, 0x05, 0x3a, 0x1d, 0xd1, 0x30, 0x10, 0xdc, 0x45, 0xf5, - 0x7f, 0xaf, 0x78, 0xdd, 0xb3, 0x56, 0xe7, 0xcb, 0x4f, 0x9d, 0x9f, 0xf4, 0xea, 0x65, 0xdc, 0x03, 0x72, 0x74, 0x80, - 0x70, 0x5e, 0xf7, 0x1b, 0xb6, 0xff, 0xe6, 0x97, 0xf7, 0x27, 0x2f, 0x03, 0x9b, 0x14, 0x89, 0x6d, 0x25, 0x9f, 0xf5, - 0x40, 0xe1, 0xd7, 0x63, 0xbd, 0xba, 0xd8, 0xf4, 0x58, 0x0f, 0xb5, 0x80, 0xe8, 0x61, 0x01, 0xea, 0xbf, 0x9e, 0x7d, - 0x1a, 0x0a, 0x07, 0xd9, 0x38, 0x55, 0xa0, 0xc8, 0x82, 0x3f, 0x17, 0xa3, 0x4d, 0x41, 0x80, 0xc8, 0x96, 0x90, 0x96, - 0x9f, 0xcd, 0x1e, 0x97, 0x5a, 0x92, 0xc1, 0x37, 0x01, 0x99, 0x1d, 0x58, 0x39, 0x41, 0xe9, 0xb8, 0x33, 0xe0, 0xca, - 0x16, 0x8f, 0x76, 0xfb, 0xd3, 0x20, 0x3b, 0x6b, 0x4e, 0x1a, 0xed, 0xc3, 0x3e, 0x05, 0x4e, 0x1a, 0x10, 0x7b, 0x44, - 0xa0, 0xef, 0xb6, 0xb9, 0xf4, 0xd1, 0xe1, 0x9c, 0x17, 0xf2, 0xcf, 0xa9, 0xc4, 0xe0, 0x1e, 0x4a, 0xac, 0x81, 0x40, - 0xe5, 0x19, 0xaa, 0x1c, 0x36, 0xc8, 0xf1, 0xcf, 0x8e, 0x64, 0x26, 0x31, 0x59, 0xe4, 0x6e, 0xcd, 0x54, 0xf8, 0x81, - 0x00, 0xfe, 0x73, 0x0e, 0x5c, 0x60, 0xb3, 0xb9, 0xaf, 0xa6, 0xb8, 0xb8, 0x01, 0x7f, 0x4c, 0xe1, 0xe7, 0x3c, 0x85, - 0x9d, 0xf6, 0xb0, 0x29, 0xaa, 0x14, 0x75, 0x1b, 0x85, 0x45, 0x25, 0x0b, 0xa6, 0x35, 0xa4, 0x89, 0x0e, 0xa3, 0x3f, - 0xc8, 0x19, 0x28, 0x08, 0xf9, 0x75, 0xd3, 0x00, 0x23, 0x95, 0x5c, 0x1e, 0x54, 0x49, 0xe0, 0x05, 0xd8, 0x05, 0x39, - 0xdb, 0x14, 0x10, 0x64, 0x9b, 0x14, 0x65, 0xfa, 0xa5, 0xc8, 0xeb, 0x30, 0x0b, 0xf2, 0x51, 0x5a, 0xfd, 0x55, 0xff, - 0x04, 0xe6, 0x6d, 0x2a, 0x46, 0xb5, 0x8a, 0xc9, 0x6f, 0xf4, 0xfb, 0xc5, 0xa0, 0xf5, 0x21, 0x83, 0x8f, 0x5e, 0x9b, - 0x06, 0x7f, 0x74, 0x1a, 0xec, 0x30, 0xd1, 0x08, 0x80, 0x64, 0x4e, 0x2d, 0x79, 0x28, 0xfa, 0x23, 0xa8, 0xb0, 0x46, - 0xb9, 0x53, 0x30, 0x58, 0xff, 0xf1, 0x68, 0x07, 0xa6, 0x5e, 0x1c, 0x6d, 0xc9, 0x0e, 0x9a, 0xfb, 0x06, 0xb8, 0x5f, - 0x23, 0x5b, 0xcc, 0x2a, 0x80, 0x66, 0xaf, 0x11, 0x19, 0x9f, 0xbc, 0x00, 0xc6, 0x6c, 0x93, 0x85, 0x91, 0x88, 0x83, - 0xb1, 0x6a, 0xcc, 0x98, 0x81, 0x81, 0x0b, 0x74, 0x2d, 0x93, 0x92, 0x34, 0xa4, 0x83, 0x01, 0x2b, 0x65, 0x0b, 0x07, - 0xbc, 0x68, 0x4e, 0xdb, 0xf1, 0xba, 0x45, 0xe3, 0x81, 0xed, 0x62, 0x87, 0xfb, 0x1f, 0x8a, 0xdd, 0xdb, 0x70, 0x47, - 0x7a, 0x85, 0x8a, 0x25, 0xf4, 0xf3, 0xaf, 0xb2, 0xcf, 0x1a, 0x4e, 0x4e, 0x85, 0x66, 0x68, 0x29, 0x12, 0x4a, 0xf1, - 0x4e, 0x4f, 0x0a, 0x8c, 0x65, 0x2c, 0xfc, 0x03, 0x70, 0x4e, 0x17, 0x8a, 0xc8, 0x1d, 0x38, 0x8e, 0x6f, 0xa1, 0x82, - 0x51, 0xc3, 0xc1, 0xcb, 0x18, 0xb6, 0x45, 0x31, 0x0b, 0x09, 0xa7, 0x10, 0x2e, 0x56, 0x59, 0xbf, 0x2f, 0x7f, 0x51, - 0x17, 0x5d, 0x65, 0xb2, 0xee, 0x93, 0x70, 0x64, 0xc6, 0x72, 0xea, 0x85, 0xe4, 0x79, 0xcf, 0x93, 0x69, 0xf2, 0xb4, - 0x0a, 0x22, 0x80, 0x7c, 0x0e, 0xef, 0xc3, 0x34, 0x03, 0xab, 0x34, 0x29, 0x3f, 0x42, 0xe9, 0x8b, 0xcf, 0x73, 0x3f, - 0xd0, 0xd9, 0x2b, 0x93, 0x0c, 0x6f, 0xe6, 0xad, 0x37, 0xa9, 0x75, 0x5d, 0x3c, 0xe0, 0xef, 0x9c, 0xc1, 0xc6, 0xb9, - 0xce, 0x04, 0x07, 0x5e, 0x24, 0xb5, 0x5e, 0x33, 0xfe, 0x3c, 0xc3, 0x75, 0xa9, 0xda, 0xe8, 0xa3, 0x10, 0x5d, 0x41, - 0xa6, 0x02, 0x14, 0x8a, 0xb4, 0x7f, 0x50, 0x6a, 0x6e, 0x52, 0x69, 0x23, 0x01, 0x74, 0x0f, 0x93, 0x06, 0x5b, 0x0c, - 0x65, 0x2c, 0x4d, 0xa2, 0xdc, 0x69, 0x10, 0x57, 0xf6, 0xe7, 0x5c, 0xe2, 0xd0, 0xb2, 0x48, 0xfe, 0xbd, 0xef, 0xe9, - 0x2b, 0xa4, 0xee, 0x64, 0x81, 0xcc, 0x18, 0x2f, 0xf2, 0xf8, 0x13, 0x10, 0x66, 0x83, 0x36, 0x2a, 0x0a, 0x21, 0x64, - 0x83, 0x18, 0x34, 0x5e, 0xe4, 0xf1, 0x0f, 0x8a, 0xc6, 0x43, 0x3e, 0x8a, 0x7c, 0xf5, 0x57, 0xa9, 0xff, 0x0a, 0x7d, - 0x66, 0x82, 0x47, 0xa8, 0x26, 0xfa, 0x77, 0xcf, 0x67, 0xf7, 0xa0, 0x36, 0x8c, 0xc2, 0xcc, 0x94, 0x9f, 0xfb, 0xa6, - 0x38, 0x7b, 0xfd, 0x15, 0x5d, 0x65, 0x5b, 0xf7, 0xa3, 0x8f, 0x27, 0x04, 0xd6, 0xc6, 0xe8, 0x8a, 0x1b, 0x03, 0xc8, - 0x61, 0xf2, 0x7e, 0x45, 0x69, 0x15, 0xa4, 0x41, 0xe8, 0xa0, 0x21, 0xe8, 0x95, 0x44, 0x1f, 0x48, 0x2c, 0x62, 0x0c, - 0x2f, 0xc4, 0x33, 0x52, 0x93, 0x89, 0x86, 0x78, 0x45, 0xec, 0x87, 0x68, 0xc9, 0xa9, 0x89, 0x6e, 0x84, 0x29, 0x06, - 0x12, 0x3b, 0x83, 0xe4, 0x24, 0xa9, 0x95, 0x5f, 0x3c, 0x93, 0x84, 0x25, 0x76, 0x1e, 0x62, 0x30, 0xa9, 0xa5, 0x3b, - 0xbd, 0xa9, 0xd2, 0x97, 0x13, 0x2d, 0x07, 0xed, 0x03, 0xb0, 0x4b, 0x49, 0xef, 0x9f, 0x14, 0x8a, 0xf8, 0x10, 0xc6, - 0x31, 0x84, 0x6f, 0x11, 0xd5, 0x15, 0x38, 0xd7, 0x0a, 0x34, 0x56, 0x03, 0x0f, 0xcd, 0x2c, 0x9f, 0x0f, 0x39, 0xfd, - 0x54, 0x5a, 0xfe, 0x18, 0xd1, 0xd8, 0x68, 0xdd, 0x1c, 0x8f, 0x07, 0x5a, 0xf5, 0xd2, 0x39, 0xe8, 0xba, 0x99, 0xc4, - 0xc4, 0x0d, 0xa4, 0xeb, 0x47, 0xbf, 0x99, 0xb0, 0x17, 0x51, 0x21, 0x97, 0x42, 0x50, 0xd0, 0xea, 0x40, 0xe0, 0x50, - 0x78, 0x8b, 0x32, 0x5f, 0xc5, 0xb4, 0x81, 0x30, 0xf8, 0xfc, 0x40, 0x7e, 0xbe, 0x29, 0x48, 0xc5, 0x8e, 0x75, 0xed, - 0xf7, 0xb7, 0xa5, 0x07, 0x78, 0x72, 0x26, 0xc9, 0xd3, 0x66, 0x08, 0x2b, 0x02, 0x68, 0xcc, 0x6a, 0xb2, 0x38, 0xe1, - 0xca, 0x1c, 0x7e, 0xcc, 0xbd, 0x92, 0xa5, 0x4c, 0x9d, 0xa7, 0x7a, 0x01, 0x44, 0x1d, 0x6f, 0xd0, 0x8a, 0xd4, 0xaf, - 0xd0, 0xd9, 0x6b, 0x56, 0x42, 0xc6, 0xc3, 0x4b, 0xce, 0xd3, 0xd1, 0x03, 0x4b, 0x78, 0x84, 0x7f, 0x25, 0x13, 0x7d, - 0xf8, 0x3d, 0x70, 0xb8, 0x19, 0x27, 0x3c, 0x72, 0x9b, 0x7d, 0xa8, 0xc2, 0x35, 0xdc, 0x4c, 0x0b, 0x40, 0x72, 0x0b, - 0x92, 0x26, 0xa0, 0x84, 0x44, 0x26, 0x64, 0xd6, 0x94, 0xfc, 0xdc, 0xd2, 0x36, 0x58, 0xc3, 0xa4, 0xf3, 0x80, 0x17, - 0xad, 0x3e, 0x5a, 0x4d, 0xb4, 0xcb, 0xac, 0x9a, 0x0f, 0x71, 0x86, 0x6a, 0x8e, 0xbb, 0x0b, 0xf8, 0x39, 0xe0, 0x39, - 0xcb, 0x9b, 0x74, 0xb4, 0x1f, 0x70, 0xe1, 0xc9, 0x75, 0x9e, 0x8e, 0x76, 0xf8, 0x4b, 0xee, 0x0f, 0x00, 0x1d, 0x4c, - 0x5d, 0x02, 0x7f, 0xaa, 0xb6, 0x9a, 0x4a, 0xfd, 0xd2, 0xda, 0xaf, 0xeb, 0xce, 0x6a, 0xc1, 0x19, 0xa2, 0x2f, 0x43, - 0x07, 0x64, 0xc8, 0x19, 0x33, 0xe0, 0xcf, 0x19, 0x4b, 0xfe, 0x9c, 0xb1, 0xe2, 0xcf, 0x19, 0x37, 0x46, 0x06, 0x50, - 0x82, 0x7b, 0xc9, 0x9f, 0x1f, 0x10, 0x33, 0xc4, 0x6a, 0x50, 0x09, 0xac, 0x2c, 0xe5, 0xdc, 0x47, 0x4e, 0x31, 0xe5, - 0x94, 0xe1, 0xa5, 0xd3, 0x99, 0x3b, 0x90, 0xf3, 0x60, 0xe6, 0x0e, 0x93, 0xb3, 0x3e, 0xc5, 0xa9, 0x34, 0x26, 0x45, + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xcc, 0xbd, 0xeb, 0x7a, 0x1b, 0xb7, 0xb2, 0x20, 0xfa, + 0xfb, 0xcc, 0x53, 0x48, 0xbd, 0x1d, 0xa5, 0x21, 0x82, 0x2d, 0x92, 0xba, 0x58, 0x6e, 0x0a, 0xe2, 0xf8, 0x1a, 0x3b, + 0x71, 0x6c, 0xc7, 0x72, 0xec, 0xd8, 0x0c, 0xb7, 0x02, 0x36, 0x41, 0x12, 0x71, 0x13, 0x60, 0x1a, 0xa0, 0x25, 0x99, + 0xe4, 0xbb, 0x9f, 0xaf, 0x70, 0xe9, 0x46, 0x93, 0xb4, 0xd7, 0x5a, 0x73, 0x66, 0xce, 0x37, 0x3b, 0x7b, 0x59, 0x6c, + 0xdc, 0x51, 0x28, 0x14, 0xaa, 0x0a, 0x55, 0x85, 0x8b, 0xfd, 0x91, 0xcc, 0xf4, 0xdd, 0x9c, 0xed, 0x4d, 0xf5, 0x2c, + 0xbf, 0xbc, 0x70, 0xff, 0x32, 0x3a, 0xba, 0xbc, 0xc8, 0xb9, 0xf8, 0xbc, 0x57, 0xb0, 0x9c, 0xf0, 0x4c, 0x8a, 0xbd, + 0x69, 0xc1, 0xc6, 0x64, 0x44, 0x35, 0x4d, 0xf9, 0x8c, 0x4e, 0xd8, 0xde, 0xd1, 0xe5, 0xc5, 0x8c, 0x69, 0xba, 0x97, + 0x4d, 0x69, 0xa1, 0x98, 0x26, 0xbf, 0xbf, 0x7b, 0xd6, 0x3c, 0xbf, 0xbc, 0x50, 0x59, 0xc1, 0xe7, 0x7a, 0x0f, 0x9a, + 0x24, 0x33, 0x39, 0x5a, 0xe4, 0xec, 0xf2, 0xe8, 0xe8, 0xe6, 0xe6, 0x26, 0xf9, 0x5b, 0xfd, 0x8f, 0x2f, 0xb4, 0xd8, + 0xfb, 0xa5, 0x20, 0xaf, 0x87, 0x7f, 0xb3, 0x4c, 0x27, 0x23, 0x36, 0xe6, 0x82, 0xbd, 0x29, 0xe4, 0x9c, 0x15, 0xfa, + 0xae, 0x0b, 0x99, 0x3f, 0x15, 0x24, 0xe6, 0x58, 0x63, 0x86, 0xc8, 0xa5, 0xde, 0xe3, 0x62, 0x8f, 0xf7, 0x7e, 0x29, + 0x4c, 0xca, 0x92, 0x89, 0xc5, 0x8c, 0x15, 0x74, 0x98, 0xb3, 0x74, 0xbf, 0x85, 0x33, 0x29, 0xc6, 0x7c, 0xb2, 0x28, + 0xbf, 0x6f, 0x0a, 0xae, 0xfd, 0xef, 0x2f, 0x34, 0x5f, 0xb0, 0x94, 0xad, 0x51, 0xca, 0xfb, 0x7a, 0x40, 0x98, 0x69, + 0xf9, 0x73, 0xd5, 0x70, 0xfc, 0x93, 0x69, 0xf2, 0x6e, 0xce, 0xe4, 0x78, 0x4f, 0xef, 0x93, 0x48, 0xdd, 0xcd, 0x86, + 0x32, 0x8f, 0x7a, 0xba, 0x11, 0x45, 0x29, 0x94, 0xc1, 0x0c, 0x75, 0x33, 0x29, 0x94, 0xde, 0x13, 0x9c, 0xdc, 0x70, + 0x31, 0x92, 0x37, 0xf8, 0x46, 0x10, 0xc1, 0x93, 0xab, 0x29, 0x1d, 0xc9, 0x9b, 0xb7, 0x52, 0xea, 0x83, 0x83, 0xd8, + 0x7d, 0xdf, 0x3d, 0xbe, 0xba, 0x22, 0x84, 0x7c, 0x91, 0x7c, 0xb4, 0xd7, 0x5a, 0xad, 0x82, 0xd4, 0x44, 0x50, 0xcd, + 0xbf, 0x30, 0x5b, 0x09, 0x1d, 0x1c, 0x44, 0x74, 0x24, 0xe7, 0x9a, 0x8d, 0xae, 0xf4, 0x5d, 0xce, 0xae, 0xa6, 0x8c, + 0x69, 0x15, 0x71, 0xb1, 0xf7, 0x44, 0x66, 0x8b, 0x19, 0x13, 0x3a, 0x99, 0x17, 0x52, 0x4b, 0x18, 0xd8, 0xc1, 0x41, + 0x54, 0xb0, 0x79, 0x4e, 0x33, 0x06, 0xf9, 0x8f, 0xaf, 0xae, 0xaa, 0x1a, 0x55, 0x21, 0xfc, 0x59, 0x90, 0x2b, 0x33, + 0xf4, 0x18, 0xe1, 0x0f, 0x82, 0x08, 0x76, 0xb3, 0xf7, 0x81, 0xd1, 0xcf, 0xbf, 0xd2, 0x79, 0x37, 0xcb, 0xa9, 0x52, + 0x7b, 0xcf, 0xe4, 0xd2, 0x4c, 0xa3, 0x58, 0x64, 0x5a, 0x16, 0xb1, 0xc6, 0x0c, 0x0b, 0xb4, 0xe4, 0xe3, 0x58, 0x4f, + 0xb9, 0x4a, 0xae, 0xef, 0x65, 0x4a, 0xbd, 0x65, 0x6a, 0x91, 0xeb, 0x7b, 0x64, 0xbf, 0x85, 0xc5, 0x3e, 0x21, 0x9f, + 0x05, 0xd2, 0xd3, 0x42, 0xde, 0xec, 0x3d, 0x2d, 0x0a, 0x59, 0xc4, 0xd1, 0xe3, 0xab, 0x2b, 0x5b, 0x62, 0x8f, 0xab, + 0x3d, 0x21, 0xf5, 0x5e, 0xd9, 0x1e, 0x40, 0x3b, 0xd9, 0xfb, 0x5d, 0xb1, 0xbd, 0xbf, 0x16, 0x42, 0xd1, 0x31, 0x7b, + 0x7c, 0x75, 0xf5, 0xd7, 0x9e, 0x2c, 0xf6, 0xfe, 0xca, 0x94, 0xfa, 0x6b, 0x8f, 0x0b, 0xa5, 0x19, 0x1d, 0x25, 0x11, + 0xea, 0x9a, 0xce, 0x32, 0xa5, 0xde, 0xb1, 0x5b, 0x4d, 0x34, 0x36, 0x9f, 0x9a, 0xb0, 0xf5, 0x84, 0xe9, 0x3d, 0x55, + 0xce, 0x2b, 0x46, 0xcb, 0x9c, 0xe9, 0x3d, 0x4d, 0x4c, 0xbe, 0x74, 0xf0, 0x67, 0xf6, 0x53, 0x77, 0xf9, 0x38, 0xbe, + 0x11, 0x07, 0x07, 0xba, 0x04, 0x34, 0x5a, 0xba, 0x15, 0x22, 0x6c, 0xdf, 0xa7, 0x1d, 0x1c, 0xb0, 0x24, 0x67, 0x62, + 0xa2, 0xa7, 0x84, 0x90, 0x76, 0x57, 0x1c, 0x1c, 0xc4, 0x9a, 0x7c, 0x10, 0xc9, 0x84, 0xe9, 0x98, 0x21, 0x84, 0xab, + 0xda, 0x07, 0x07, 0xb1, 0x05, 0x82, 0x24, 0xda, 0x00, 0xae, 0x06, 0x63, 0x94, 0x38, 0xe8, 0x5f, 0xdd, 0x89, 0x2c, + 0x0e, 0xc7, 0x8f, 0xb0, 0x38, 0x38, 0xf8, 0x20, 0x12, 0x05, 0x2d, 0x62, 0x8d, 0xd0, 0xba, 0x60, 0x7a, 0x51, 0x88, + 0x3d, 0xbd, 0xd6, 0xf2, 0x4a, 0x17, 0x5c, 0x4c, 0x62, 0xb4, 0xf4, 0x69, 0x41, 0xc5, 0xf5, 0xda, 0x0e, 0xf7, 0xb7, + 0x82, 0x70, 0x72, 0x09, 0x3d, 0x3e, 0x93, 0xb1, 0xc3, 0x41, 0x4e, 0x48, 0xa4, 0x4c, 0xdd, 0xa8, 0xc7, 0x53, 0xde, + 0x88, 0x22, 0x6c, 0x47, 0x89, 0x3f, 0x0b, 0x84, 0xb9, 0x06, 0xd4, 0x4d, 0x92, 0x44, 0x23, 0x72, 0xb9, 0xf4, 0x60, + 0xe1, 0xc1, 0x44, 0x7b, 0xbc, 0xdf, 0x1a, 0xa4, 0x3a, 0x29, 0xd8, 0x68, 0x91, 0xb1, 0x38, 0x16, 0x58, 0x61, 0x89, + 0xc8, 0xa5, 0x68, 0xc4, 0x05, 0xb9, 0x84, 0xf5, 0x2e, 0xea, 0x8b, 0x4d, 0xc8, 0x7e, 0x0b, 0xb9, 0x41, 0x16, 0x7e, + 0x84, 0x00, 0x62, 0x37, 0xa0, 0x82, 0x90, 0x48, 0x2c, 0x66, 0x43, 0x56, 0x44, 0x65, 0xb1, 0x6e, 0x0d, 0x2f, 0x16, + 0x8a, 0xed, 0x65, 0x4a, 0xed, 0x8d, 0x17, 0x22, 0xd3, 0x5c, 0x8a, 0xbd, 0xa8, 0x51, 0x34, 0x22, 0x8b, 0x0f, 0x25, + 0x3a, 0x44, 0x68, 0x8d, 0x62, 0x85, 0x1a, 0xbc, 0x2f, 0x1b, 0xed, 0x01, 0x86, 0x51, 0xa2, 0xae, 0x6b, 0xcf, 0x41, + 0x80, 0x61, 0x0e, 0x93, 0x5c, 0xe3, 0x4f, 0x76, 0xe7, 0xc3, 0x14, 0x6f, 0x44, 0x8f, 0x27, 0xdb, 0x3b, 0x85, 0xe8, + 0x64, 0x46, 0xe7, 0x31, 0x23, 0x97, 0xcc, 0x60, 0x17, 0x15, 0x19, 0x8c, 0xb5, 0xb6, 0x70, 0x3d, 0x96, 0xb2, 0xa4, + 0xc2, 0x29, 0x94, 0xea, 0x64, 0x2c, 0x8b, 0xa7, 0x34, 0x9b, 0x42, 0xbd, 0x12, 0x63, 0x46, 0x7e, 0xc3, 0x65, 0x05, + 0xa3, 0x9a, 0x3d, 0xcd, 0x19, 0x7c, 0xc5, 0x91, 0xa9, 0x19, 0x21, 0xac, 0x60, 0xab, 0xe7, 0x5c, 0xbf, 0x92, 0x22, + 0x63, 0x5d, 0x15, 0xe0, 0x97, 0x59, 0xf9, 0x87, 0x5a, 0x17, 0x7c, 0xb8, 0xd0, 0x2c, 0x8e, 0x04, 0x94, 0x88, 0xb0, + 0x42, 0x58, 0x24, 0x9a, 0xdd, 0xea, 0xc7, 0x52, 0x68, 0x26, 0x34, 0x61, 0x1e, 0xaa, 0x98, 0x27, 0x74, 0x3e, 0x67, + 0x62, 0xf4, 0x78, 0xca, 0xf3, 0x51, 0x2c, 0xd0, 0x1a, 0xad, 0xf1, 0xef, 0x82, 0xc0, 0x24, 0xc9, 0x25, 0x4f, 0xe1, + 0x9f, 0x6f, 0x4f, 0x27, 0xd6, 0xe4, 0xd2, 0x6c, 0x0b, 0x46, 0xa2, 0xa8, 0x3b, 0x96, 0x45, 0xec, 0xa6, 0xb0, 0x07, + 0xa4, 0x0b, 0xfa, 0x78, 0xbb, 0xc8, 0x99, 0x42, 0xac, 0x41, 0x44, 0xb9, 0x8e, 0x0e, 0xc2, 0xbf, 0x15, 0x31, 0x83, + 0x05, 0xe0, 0x28, 0xe5, 0x86, 0x04, 0xbe, 0xe4, 0x6e, 0x53, 0x8d, 0x4a, 0xa2, 0xf6, 0x51, 0x90, 0x11, 0x4f, 0x74, + 0xb1, 0x50, 0x9a, 0x8d, 0xde, 0xdd, 0xcd, 0x99, 0xc2, 0x3f, 0x17, 0xe4, 0xa3, 0xe8, 0x7d, 0x14, 0x09, 0x9b, 0xcd, + 0xf5, 0xdd, 0x95, 0xa1, 0xe6, 0x69, 0x14, 0xe1, 0x7f, 0x4c, 0xd1, 0x82, 0xd1, 0x0c, 0x48, 0x9a, 0x03, 0xd9, 0x1b, + 0x99, 0xdf, 0x8d, 0x79, 0x9e, 0x5f, 0x2d, 0xe6, 0x73, 0x59, 0x68, 0xac, 0x05, 0x59, 0x6a, 0x59, 0xc1, 0x07, 0x56, + 0x74, 0xa9, 0x6e, 0xb8, 0xce, 0xa6, 0xb1, 0x46, 0xcb, 0x8c, 0x2a, 0xb6, 0xf7, 0x48, 0xca, 0x9c, 0x51, 0x91, 0x72, + 0xc2, 0x7b, 0x3f, 0x17, 0xa9, 0x58, 0xe4, 0x79, 0x77, 0x58, 0x30, 0xfa, 0xb9, 0x6b, 0xb2, 0xed, 0xe1, 0x90, 0x9a, + 0xdf, 0x0f, 0x8b, 0x82, 0xde, 0x41, 0x41, 0x42, 0xa0, 0x58, 0x8f, 0xa7, 0x3f, 0x5f, 0xbd, 0x7e, 0x95, 0xd8, 0xbd, + 0xc2, 0xc7, 0x77, 0x31, 0x2f, 0xf7, 0x1f, 0x5f, 0xe3, 0x71, 0x21, 0x67, 0x1b, 0x5d, 0x5b, 0xd0, 0xf1, 0xee, 0x37, + 0x86, 0xc0, 0x08, 0xdf, 0xb7, 0x4d, 0x87, 0x23, 0x78, 0x65, 0x30, 0x1f, 0x32, 0x89, 0xeb, 0x17, 0xfe, 0x49, 0x6d, + 0x72, 0xcc, 0xd1, 0xf7, 0x47, 0xab, 0x8b, 0xbb, 0x25, 0x23, 0x66, 0x9c, 0x73, 0x38, 0x18, 0x61, 0x8c, 0x19, 0xd5, + 0xd9, 0x74, 0xc9, 0x4c, 0x63, 0x6b, 0x3f, 0x62, 0xb6, 0x5e, 0xe3, 0xaf, 0xd2, 0x63, 0xbd, 0xde, 0x27, 0x84, 0x1b, + 0x7a, 0x45, 0xf4, 0x6a, 0xc5, 0x09, 0xe1, 0x08, 0xbf, 0xe5, 0x64, 0x49, 0xfd, 0x84, 0xe0, 0x64, 0x83, 0xed, 0x99, + 0x5a, 0x2a, 0x03, 0x27, 0xe0, 0x17, 0x56, 0x68, 0x56, 0xa4, 0x5a, 0xe0, 0x82, 0x8d, 0x73, 0x18, 0xc7, 0x7e, 0x1b, + 0x4f, 0xa9, 0x7a, 0x3c, 0xa5, 0x62, 0xc2, 0x46, 0xe9, 0x57, 0xb9, 0xc6, 0x4c, 0x90, 0x68, 0xcc, 0x05, 0xcd, 0xf9, + 0x57, 0x36, 0x8a, 0xdc, 0xb9, 0xf0, 0x48, 0xef, 0xb1, 0x5b, 0xcd, 0xc4, 0x48, 0xed, 0x3d, 0x7f, 0xf7, 0xeb, 0x4b, + 0xb7, 0x98, 0xb5, 0xb3, 0x02, 0x2d, 0xd5, 0x62, 0xce, 0x8a, 0x18, 0x61, 0x77, 0x56, 0x3c, 0xe5, 0x86, 0x4e, 0xfe, + 0x4a, 0xe7, 0x36, 0x85, 0xab, 0xdf, 0xe7, 0x23, 0xaa, 0xd9, 0x1b, 0x26, 0x46, 0x5c, 0x4c, 0xc8, 0x7e, 0xdb, 0xa6, + 0x4f, 0xa9, 0xcb, 0x18, 0x95, 0x49, 0xd7, 0xf7, 0x9e, 0xe6, 0x66, 0xee, 0xe5, 0xe7, 0x22, 0x46, 0x6b, 0xa5, 0xa9, + 0xe6, 0xd9, 0x1e, 0x1d, 0x8d, 0x5e, 0x08, 0xae, 0xb9, 0x19, 0x61, 0x01, 0x4b, 0x04, 0xb8, 0xca, 0xec, 0xa9, 0xe1, + 0x47, 0x1e, 0x23, 0x1c, 0xc7, 0xee, 0x2c, 0x98, 0x22, 0xb7, 0x66, 0x07, 0x07, 0x15, 0xe5, 0xef, 0xb1, 0xd4, 0x66, + 0x92, 0xfe, 0x00, 0x25, 0xf3, 0x85, 0x82, 0xc5, 0xf6, 0x5d, 0xc0, 0x41, 0x23, 0x87, 0x8a, 0x15, 0x5f, 0xd8, 0xa8, + 0x44, 0x10, 0x15, 0xa3, 0xe5, 0x46, 0x1f, 0x6e, 0x7b, 0x68, 0xd2, 0x1f, 0x74, 0x43, 0x12, 0xce, 0x1c, 0xb2, 0x5b, + 0x4e, 0x85, 0x33, 0x55, 0x12, 0x95, 0x18, 0x0e, 0xd4, 0x92, 0xb0, 0x28, 0xe2, 0xe7, 0x37, 0x8f, 0x05, 0xf0, 0x10, + 0x21, 0xe5, 0xf0, 0x67, 0xee, 0xd3, 0x2f, 0xe6, 0xf0, 0x50, 0x58, 0x20, 0xac, 0xed, 0x48, 0x15, 0x42, 0x6b, 0x84, + 0xb5, 0x1f, 0xae, 0x25, 0x4a, 0x9e, 0x2f, 0x82, 0x53, 0x9b, 0xbc, 0xe5, 0xe6, 0xd8, 0x06, 0xda, 0x46, 0x35, 0x3b, + 0x38, 0x88, 0x59, 0x52, 0x22, 0x06, 0xd9, 0x6f, 0xbb, 0x45, 0x0a, 0xa0, 0xf5, 0x8d, 0x71, 0x43, 0xcf, 0x86, 0xc1, + 0xd9, 0x67, 0x89, 0x90, 0x0f, 0xb3, 0x8c, 0x29, 0x25, 0x8b, 0x83, 0x83, 0x7d, 0x53, 0xbe, 0xe4, 0x2c, 0x60, 0x11, + 0x5f, 0xdf, 0x88, 0x6a, 0x08, 0xa8, 0x3a, 0x6d, 0x3d, 0xdf, 0x44, 0x2a, 0xbe, 0xc9, 0x33, 0x21, 0x69, 0x74, 0x7d, + 0x1d, 0x35, 0x34, 0x76, 0x70, 0x98, 0x30, 0xdf, 0xf5, 0xdd, 0x13, 0x66, 0xd9, 0x42, 0xc3, 0x84, 0x6c, 0x81, 0x66, + 0x27, 0x3f, 0x18, 0xd7, 0x87, 0x84, 0x35, 0x56, 0x68, 0x1d, 0xac, 0xe8, 0xce, 0xa6, 0x0d, 0x7f, 0x63, 0x97, 0x6e, + 0x39, 0x31, 0x3c, 0x45, 0xb0, 0x8e, 0x7d, 0x36, 0x58, 0x63, 0x03, 0x7b, 0x3f, 0x1b, 0x69, 0x06, 0xda, 0xd7, 0x83, + 0xae, 0xcb, 0x27, 0xca, 0x42, 0xae, 0x60, 0xff, 0x2c, 0x98, 0xd2, 0x16, 0x91, 0x63, 0x8d, 0x25, 0x86, 0x33, 0x6a, + 0x93, 0xe9, 0xac, 0xb1, 0xa4, 0xbb, 0xc6, 0xf6, 0x7a, 0x0e, 0x67, 0xa3, 0x02, 0xa4, 0xfe, 0x3e, 0x3e, 0xc1, 0x58, + 0x35, 0x5a, 0xad, 0xde, 0x72, 0xdf, 0x4a, 0xb5, 0x96, 0x25, 0xbf, 0xb6, 0xb1, 0x28, 0x4c, 0x20, 0x77, 0x38, 0xef, + 0xb7, 0xdd, 0xf8, 0xc5, 0x80, 0xec, 0xb7, 0x4a, 0x2c, 0x76, 0x60, 0xb5, 0xe3, 0xb1, 0x50, 0x7c, 0x6d, 0x9b, 0x42, + 0xe6, 0xac, 0xaf, 0xe1, 0x4b, 0x32, 0xdd, 0xc2, 0xd5, 0x29, 0xe9, 0x03, 0xd7, 0x91, 0x4c, 0x07, 0xdf, 0xc2, 0x27, + 0x4f, 0x11, 0x62, 0xbd, 0x9d, 0x57, 0x11, 0x8e, 0x2f, 0x75, 0xc2, 0xb1, 0x31, 0x8d, 0x68, 0x5e, 0x56, 0x89, 0x4a, + 0x34, 0x73, 0x5b, 0xbd, 0xca, 0xc2, 0xc2, 0x0c, 0xa6, 0x9a, 0x52, 0xd0, 0xc4, 0x2b, 0x3a, 0x63, 0x2a, 0x66, 0x08, + 0x7f, 0xab, 0x80, 0xc5, 0x4f, 0x28, 0x32, 0x08, 0xce, 0x50, 0x05, 0x67, 0x28, 0xb0, 0xbb, 0xc0, 0xa4, 0xd5, 0xb7, + 0x9c, 0xc2, 0xac, 0xaf, 0x06, 0x15, 0x6f, 0x17, 0x4c, 0xde, 0x1c, 0xce, 0x0e, 0xc1, 0x3d, 0xfc, 0x6c, 0x9a, 0x05, + 0x9a, 0x61, 0x21, 0x14, 0xc2, 0xfb, 0xad, 0xcd, 0x95, 0xf4, 0xa5, 0xaa, 0x39, 0xf6, 0x07, 0xb0, 0x0e, 0xe6, 0xd8, + 0x48, 0xb8, 0x32, 0x7f, 0x6b, 0x5b, 0x0d, 0xc0, 0x76, 0x05, 0x98, 0x91, 0x8c, 0x73, 0xaa, 0xe3, 0xf6, 0x51, 0x0b, + 0x18, 0xd3, 0x2f, 0x0c, 0x4e, 0x15, 0x84, 0xb6, 0xa7, 0xc2, 0x92, 0x85, 0x50, 0x53, 0x3e, 0xd6, 0xf1, 0xef, 0xc2, + 0x10, 0x15, 0x96, 0x2b, 0x06, 0x12, 0x4e, 0xc0, 0x1e, 0x1b, 0x82, 0xf3, 0xbb, 0x80, 0x7e, 0xba, 0xe5, 0x41, 0xe4, + 0x46, 0x6a, 0x08, 0x17, 0x90, 0x87, 0x8a, 0xb5, 0xae, 0xc8, 0x4c, 0xc9, 0xb8, 0x01, 0xf7, 0xd8, 0xee, 0xd9, 0x16, + 0x53, 0x47, 0x0d, 0x44, 0xc0, 0xc1, 0x8a, 0x34, 0x24, 0x11, 0x2e, 0x51, 0x27, 0x5a, 0xbe, 0x94, 0x37, 0xac, 0x78, + 0x4c, 0x61, 0xf0, 0xa9, 0xad, 0xbe, 0xb6, 0x47, 0x81, 0xa1, 0xf8, 0xba, 0xeb, 0xf1, 0xe5, 0xda, 0x4c, 0xfc, 0x4d, + 0x21, 0x67, 0x5c, 0x31, 0xe0, 0xdb, 0x2c, 0xfc, 0x05, 0x6c, 0x34, 0xb3, 0x23, 0xe1, 0xb8, 0x61, 0x25, 0x7e, 0x3d, + 0x7c, 0x59, 0xc7, 0xaf, 0xeb, 0x7b, 0x4f, 0x27, 0x9e, 0x02, 0xd6, 0xf7, 0x31, 0xc2, 0xb1, 0x13, 0x2f, 0x82, 0x93, + 0x2e, 0x99, 0x22, 0x77, 0xcc, 0xaf, 0x56, 0x3a, 0x10, 0xe3, 0x6a, 0x9c, 0x23, 0xb3, 0xdb, 0x06, 0xad, 0xe9, 0x68, + 0x04, 0x2c, 0x5e, 0x21, 0xf3, 0x3c, 0x38, 0xac, 0xb0, 0xe8, 0x96, 0xc7, 0xd3, 0xf5, 0xbd, 0xa7, 0x57, 0xdf, 0x3b, + 0xa1, 0x20, 0x3f, 0x3c, 0xa4, 0xfc, 0x40, 0xc5, 0x88, 0x15, 0x20, 0x57, 0x06, 0xab, 0xe5, 0xce, 0xd9, 0xc7, 0x52, + 0x08, 0x96, 0x69, 0x36, 0x02, 0xa1, 0x45, 0x10, 0x9d, 0x4c, 0xa5, 0xd2, 0x65, 0x62, 0x35, 0x7a, 0x11, 0x0a, 0xa1, + 0x49, 0x46, 0xf3, 0x3c, 0xb6, 0x02, 0xca, 0x4c, 0x7e, 0x61, 0x3b, 0x46, 0xdd, 0xad, 0x0d, 0xb9, 0x6c, 0x86, 0x05, + 0xcd, 0xb0, 0x44, 0xcd, 0x73, 0x9e, 0xb1, 0xf2, 0xf0, 0xba, 0x4a, 0xb8, 0x18, 0xb1, 0x5b, 0xa0, 0x23, 0xe8, 0xf2, + 0xf2, 0xb2, 0x85, 0xdb, 0x68, 0x6d, 0x01, 0xbe, 0xdc, 0x02, 0xec, 0x77, 0x8e, 0x4d, 0x2b, 0x88, 0x2f, 0x77, 0x92, + 0x35, 0x14, 0x9c, 0x95, 0xdc, 0x0b, 0x5a, 0x96, 0x3c, 0x23, 0x3c, 0x62, 0x39, 0xd3, 0xcc, 0x93, 0x73, 0x60, 0xa6, + 0xed, 0xd6, 0x7d, 0x5b, 0xc2, 0xaf, 0x44, 0x27, 0xbf, 0xcb, 0xfc, 0x9a, 0xab, 0x52, 0x74, 0xaf, 0x96, 0xa7, 0x82, + 0x76, 0x4f, 0xdb, 0xe5, 0xa1, 0x5a, 0xd3, 0x6c, 0x6a, 0x25, 0xf6, 0x78, 0x6b, 0x4a, 0x55, 0x1b, 0x8e, 0xb4, 0x97, + 0x9b, 0xe8, 0x53, 0xe1, 0x86, 0xb9, 0x0b, 0x04, 0x57, 0x8e, 0x28, 0x30, 0x10, 0x02, 0xed, 0xb2, 0x3d, 0xa6, 0x79, + 0x3e, 0xa4, 0xd9, 0xe7, 0x3a, 0xf6, 0x57, 0x68, 0x40, 0x36, 0xa9, 0x71, 0x90, 0x15, 0x90, 0xac, 0x70, 0xde, 0x9e, + 0x4a, 0xd7, 0x36, 0x4a, 0xbc, 0xdf, 0xaa, 0xd0, 0xbe, 0xbe, 0xd0, 0xdf, 0xc4, 0x76, 0x33, 0x22, 0xe1, 0x66, 0x16, + 0x03, 0x15, 0xf8, 0x97, 0x18, 0xe7, 0xe9, 0x81, 0xc3, 0x3b, 0x10, 0x3c, 0xd6, 0x1b, 0x03, 0xd1, 0x68, 0xb9, 0x1e, + 0x71, 0xf5, 0x6d, 0x08, 0xfc, 0x6f, 0x19, 0xe5, 0x93, 0xa0, 0x87, 0x7f, 0x77, 0xa0, 0x25, 0x8d, 0x73, 0x8c, 0x73, + 0x39, 0x32, 0xc7, 0x50, 0x78, 0x42, 0xf3, 0x0b, 0x30, 0x2f, 0x06, 0xdf, 0x5f, 0xdb, 0x2c, 0xc3, 0x97, 0xc1, 0x30, + 0x54, 0x37, 0x64, 0x28, 0x6a, 0x28, 0xe0, 0x88, 0xaa, 0x30, 0x67, 0xae, 0xac, 0x89, 0x92, 0x8e, 0x6b, 0xb7, 0xe2, + 0xb8, 0xa3, 0xb9, 0x05, 0x89, 0xe3, 0x58, 0x81, 0x34, 0xe7, 0xf9, 0xfb, 0x6a, 0x16, 0x6a, 0x6b, 0x16, 0x2a, 0x09, + 0xa4, 0x2d, 0x54, 0x21, 0x73, 0x50, 0x3d, 0xd5, 0x02, 0x85, 0xa5, 0x80, 0x65, 0x4d, 0x80, 0x42, 0xa3, 0x92, 0xe0, + 0xe6, 0x44, 0xe3, 0xc2, 0x89, 0x3a, 0x0e, 0xd7, 0x80, 0x64, 0x54, 0x55, 0x24, 0xb2, 0x9b, 0xa3, 0x26, 0xfb, 0x4a, + 0x5c, 0xa0, 0x0d, 0xfe, 0x7e, 0xbd, 0x76, 0x50, 0x62, 0xc8, 0xad, 0x4e, 0x8d, 0x31, 0x0e, 0xc0, 0x82, 0x25, 0x71, + 0xcc, 0xb0, 0x65, 0x7d, 0x36, 0x81, 0x53, 0xb6, 0xbb, 0x4f, 0x88, 0xac, 0x60, 0x53, 0x63, 0x2a, 0x3d, 0x77, 0x25, + 0x11, 0xa6, 0x9e, 0x2d, 0x2d, 0xaa, 0x89, 0x13, 0x12, 0x79, 0xed, 0x44, 0xd4, 0x5b, 0xd6, 0x84, 0xc3, 0x34, 0x28, + 0xb6, 0x4e, 0x81, 0xa8, 0x16, 0xbb, 0xe0, 0xbd, 0x0b, 0x6b, 0x6a, 0xed, 0x04, 0x10, 0x2f, 0x6a, 0x10, 0x0f, 0x40, + 0x2b, 0x2d, 0xf1, 0x92, 0x03, 0x42, 0xeb, 0x95, 0x63, 0x86, 0x0b, 0xbb, 0x10, 0x5b, 0x50, 0xdc, 0x64, 0x3f, 0x0d, + 0x16, 0x82, 0x2c, 0xab, 0x80, 0xbf, 0x0b, 0x8f, 0x88, 0x18, 0x06, 0x2f, 0x56, 0xab, 0x2d, 0xb4, 0xdb, 0xc9, 0x85, + 0xa2, 0xa4, 0x92, 0x0e, 0x57, 0xab, 0xaf, 0x12, 0xc5, 0x8e, 0xff, 0xc5, 0x0c, 0xf5, 0x3c, 0xd1, 0x7d, 0xf8, 0x12, + 0x4a, 0x19, 0x76, 0xb4, 0x4a, 0x29, 0x05, 0x87, 0x3a, 0xd6, 0xd6, 0x17, 0x4a, 0x07, 0x94, 0xfb, 0xf1, 0x16, 0x01, + 0x33, 0x89, 0xee, 0xa4, 0xae, 0xa6, 0xfc, 0xd8, 0x35, 0x2d, 0x10, 0x42, 0xa9, 0x32, 0xb2, 0xcc, 0xfe, 0x2e, 0xf9, + 0xf2, 0xe0, 0x40, 0x05, 0x0d, 0x5d, 0x97, 0x94, 0xe2, 0xef, 0x18, 0x4e, 0x65, 0x75, 0x27, 0x0c, 0xfb, 0xf2, 0xb7, + 0x3f, 0x87, 0xb6, 0xa4, 0xd3, 0x56, 0x17, 0x04, 0x73, 0x7a, 0x43, 0xb9, 0xde, 0x2b, 0x5b, 0xb1, 0x82, 0x79, 0xcc, + 0xd0, 0xd2, 0x71, 0x1b, 0x49, 0xc1, 0x80, 0x7f, 0x04, 0xb2, 0xe0, 0xb9, 0x68, 0x8b, 0xf8, 0xd9, 0x94, 0x81, 0x2a, + 0xdb, 0x33, 0x12, 0xa5, 0x78, 0xb8, 0xef, 0x0e, 0x12, 0xd7, 0xf0, 0xee, 0xb1, 0xaf, 0x37, 0xab, 0xd7, 0xa4, 0x81, + 0x39, 0x2b, 0xc6, 0xb2, 0x98, 0xf9, 0xbc, 0xf5, 0xc6, 0xb7, 0x23, 0x8e, 0x7c, 0x1c, 0xef, 0x6c, 0xdb, 0x89, 0x00, + 0xdd, 0x0d, 0xd9, 0xbb, 0x92, 0xda, 0x6b, 0xa7, 0x69, 0x79, 0x00, 0x5b, 0x05, 0xa1, 0xc7, 0x4c, 0x15, 0x4a, 0xf9, + 0x4e, 0xbd, 0xda, 0xb5, 0xba, 0x93, 0xfd, 0x76, 0xb7, 0x94, 0xfc, 0x3c, 0x36, 0x74, 0xad, 0x8e, 0xc3, 0x9d, 0xaa, + 0x72, 0x91, 0x8f, 0xdc, 0x60, 0x05, 0xc2, 0xcc, 0xe1, 0xd1, 0x0d, 0xcf, 0xf3, 0x2a, 0xf5, 0x3f, 0x21, 0xed, 0xca, + 0x91, 0x76, 0xe9, 0x49, 0x3b, 0x90, 0x0a, 0x20, 0xed, 0xb6, 0xb9, 0xaa, 0xba, 0xdc, 0xda, 0x9e, 0xd2, 0x12, 0x75, + 0x65, 0xc4, 0x69, 0xe8, 0x6f, 0xe1, 0x47, 0x80, 0x4a, 0xe6, 0xeb, 0x73, 0xec, 0xf4, 0x31, 0x20, 0x06, 0x5a, 0x9d, + 0x26, 0x0b, 0x35, 0x15, 0x9f, 0x63, 0x84, 0xd5, 0x9a, 0x95, 0x98, 0xfd, 0xf0, 0x29, 0x28, 0xed, 0x82, 0xe9, 0xc0, + 0x39, 0x66, 0x92, 0xff, 0x23, 0x3e, 0xca, 0xcf, 0x4e, 0xb8, 0xd9, 0x29, 0x3f, 0x3b, 0xa0, 0xf5, 0xd5, 0xec, 0x46, + 0xdf, 0xa7, 0xf6, 0x66, 0x7a, 0xa2, 0x9c, 0x5e, 0xb5, 0xde, 0xab, 0x55, 0xbc, 0x91, 0x02, 0x1a, 0x7d, 0x27, 0xa5, + 0x14, 0x65, 0xeb, 0x40, 0x03, 0x42, 0xc8, 0x40, 0xc2, 0xda, 0x4e, 0xba, 0x3c, 0xe5, 0x5e, 0xfe, 0x2b, 0x3d, 0x8f, + 0x51, 0xdc, 0xdb, 0xfa, 0x8f, 0xe5, 0x6c, 0x0e, 0x0c, 0xd9, 0x06, 0x4a, 0x4f, 0x98, 0xeb, 0xb0, 0xca, 0x5f, 0xef, + 0x48, 0xab, 0xd5, 0x31, 0xfb, 0xb1, 0x86, 0x4d, 0xa5, 0xd4, 0xbc, 0xdf, 0x5a, 0x2f, 0xca, 0xa4, 0x92, 0x70, 0xec, + 0xd2, 0xad, 0x3c, 0xde, 0xd4, 0xcc, 0xf8, 0x8c, 0xd7, 0xb1, 0xb0, 0x74, 0x58, 0x00, 0xad, 0x0b, 0xc8, 0x8f, 0x47, + 0xf7, 0x70, 0xfd, 0xd7, 0x15, 0x70, 0x96, 0xeb, 0x0d, 0xf0, 0x2d, 0xd7, 0xeb, 0x47, 0xda, 0x49, 0xda, 0xf8, 0xd1, + 0x0e, 0xb9, 0xb7, 0x84, 0x5e, 0x95, 0xe9, 0x64, 0xc6, 0xfe, 0x00, 0xd2, 0xb6, 0x58, 0x48, 0xb2, 0x9c, 0xc9, 0x11, + 0x4b, 0x23, 0x39, 0x67, 0x22, 0x5a, 0x83, 0x9e, 0xd5, 0x21, 0xc0, 0x3f, 0x22, 0x5e, 0xbe, 0xad, 0xeb, 0x5b, 0xd3, + 0x47, 0x7a, 0x0d, 0xaa, 0xb0, 0x97, 0x7c, 0x87, 0x32, 0xf6, 0x3d, 0x2b, 0x94, 0xe1, 0x49, 0x4b, 0xf6, 0xf6, 0x25, + 0xaf, 0x0e, 0xa8, 0x97, 0x3c, 0xfd, 0x76, 0x95, 0x4a, 0x20, 0x89, 0xda, 0xc9, 0x59, 0x72, 0x1c, 0x21, 0xa3, 0x31, + 0x7e, 0xe6, 0x35, 0xc6, 0x8b, 0x52, 0x63, 0xfc, 0x5c, 0x93, 0xc5, 0x86, 0xc6, 0xf8, 0x0f, 0x41, 0x9e, 0xeb, 0xde, + 0x73, 0xaf, 0x4d, 0x7f, 0x23, 0x73, 0x9e, 0xdd, 0xc5, 0x51, 0xce, 0x75, 0x13, 0x6e, 0x13, 0x23, 0xbc, 0xb4, 0x19, + 0xa0, 0x6a, 0x34, 0xfa, 0xee, 0xb5, 0x97, 0xff, 0xb0, 0x10, 0x24, 0xba, 0x97, 0x73, 0x7d, 0x2f, 0xc2, 0x53, 0x4d, + 0xfe, 0x82, 0x5f, 0xf7, 0x96, 0xf1, 0xaf, 0x54, 0x4f, 0x93, 0x82, 0x8a, 0x91, 0x9c, 0xc5, 0xa8, 0x11, 0x45, 0x28, + 0x51, 0x46, 0x08, 0x79, 0x80, 0xd6, 0xf7, 0xfe, 0xc2, 0xaf, 0x24, 0x89, 0x7a, 0x51, 0x63, 0xaa, 0xb1, 0xa6, 0xe4, + 0xaf, 0x8b, 0x7b, 0xcb, 0x57, 0x72, 0x7d, 0xf9, 0x17, 0x7e, 0xaa, 0x4b, 0xb5, 0x3e, 0xbe, 0x65, 0x24, 0x46, 0xe4, + 0xf2, 0xa9, 0x1f, 0xd2, 0x63, 0x39, 0xb3, 0x0a, 0xfe, 0x08, 0xe1, 0x2f, 0xa0, 0xd7, 0xbd, 0xe4, 0x15, 0x11, 0x72, + 0x77, 0x30, 0xfb, 0x24, 0x92, 0x46, 0x79, 0x10, 0x1d, 0x1c, 0x04, 0x69, 0x25, 0x0b, 0x81, 0xff, 0x96, 0xa4, 0x26, + 0xaa, 0x63, 0x46, 0xa1, 0xa5, 0xbf, 0x65, 0xcc, 0x91, 0x6f, 0x26, 0xf6, 0x9a, 0x6a, 0xb7, 0x63, 0x79, 0xdf, 0xea, + 0x1e, 0x12, 0xae, 0x59, 0x41, 0xb5, 0x2c, 0x06, 0x28, 0x64, 0x4b, 0xf0, 0x57, 0x4e, 0xfe, 0xea, 0xef, 0xfd, 0x3f, + 0xff, 0xe3, 0xcf, 0xf1, 0x9f, 0xc5, 0xe0, 0x2f, 0x2c, 0x18, 0x39, 0xba, 0x88, 0x7b, 0x69, 0xbc, 0xdf, 0x6c, 0xae, + 0xfe, 0x3c, 0xea, 0xff, 0x37, 0x6d, 0x7e, 0x7d, 0xd8, 0xfc, 0x34, 0x40, 0xab, 0xf8, 0xcf, 0xa3, 0x5e, 0xdf, 0x7d, + 0xf5, 0xff, 0xfb, 0xf2, 0x4f, 0x35, 0x38, 0xb4, 0x89, 0xf7, 0x10, 0x3a, 0x9a, 0xe0, 0x5f, 0x04, 0x39, 0x6a, 0x36, + 0x2f, 0x8f, 0x26, 0xf8, 0x27, 0x41, 0x8e, 0xe0, 0xef, 0x9d, 0x26, 0x6f, 0xd9, 0xe4, 0xe9, 0xed, 0x3c, 0xfe, 0xeb, + 0x72, 0x75, 0x6f, 0xf9, 0x95, 0xaf, 0xa1, 0xdd, 0xfe, 0x7f, 0xff, 0xf9, 0xa7, 0x8a, 0x7e, 0xbc, 0x24, 0x47, 0x83, + 0x06, 0x8a, 0x4d, 0xf2, 0x21, 0xb1, 0x7f, 0xe2, 0x5e, 0xda, 0xff, 0x6f, 0x37, 0x94, 0xe8, 0xc7, 0x3f, 0xff, 0xba, + 0xb8, 0x24, 0x83, 0x55, 0x1c, 0xad, 0x7e, 0x44, 0x2b, 0x84, 0x56, 0xf7, 0xd0, 0x5f, 0x38, 0x9a, 0x44, 0x08, 0xff, + 0x26, 0xc8, 0xd1, 0x8f, 0x47, 0x13, 0xfc, 0x49, 0x90, 0xa3, 0xe8, 0x68, 0x82, 0xdf, 0x4b, 0x72, 0xf4, 0xdf, 0x71, + 0x2f, 0xb5, 0x4a, 0xb8, 0x95, 0x51, 0x7f, 0xac, 0xe0, 0x26, 0x84, 0x16, 0x8c, 0xae, 0x34, 0xd7, 0x39, 0x43, 0xf7, + 0x8e, 0x38, 0x7e, 0x24, 0x01, 0x58, 0xb1, 0x06, 0x25, 0x8d, 0xb9, 0x84, 0x5d, 0x5e, 0xc3, 0xc2, 0x03, 0x06, 0xdd, + 0x4b, 0x39, 0xb6, 0x7a, 0x02, 0x95, 0x6a, 0x7b, 0x7b, 0xab, 0xe0, 0xfa, 0x16, 0x3f, 0x26, 0x8f, 0x64, 0xdc, 0x46, + 0x98, 0x53, 0xf8, 0xd1, 0x41, 0xf8, 0x83, 0x76, 0x17, 0x9e, 0xb0, 0xcd, 0x2d, 0x86, 0x09, 0x69, 0xf9, 0x99, 0x08, + 0xe1, 0x97, 0x3b, 0x32, 0xf5, 0x14, 0xd4, 0x0f, 0x08, 0xff, 0x5c, 0xbb, 0x1e, 0xc5, 0x8f, 0x35, 0x29, 0x91, 0xe3, + 0x5d, 0xc1, 0xd8, 0x07, 0x9a, 0x7f, 0x66, 0x45, 0xfc, 0x54, 0xe3, 0x76, 0xe7, 0x01, 0x36, 0xaa, 0xea, 0xfd, 0x36, + 0xea, 0x96, 0xb7, 0x5b, 0xcf, 0xa5, 0xbd, 0x4f, 0x80, 0x53, 0xb8, 0xae, 0xaf, 0x81, 0xb5, 0xdf, 0xe7, 0x5b, 0x4a, + 0xad, 0x82, 0xde, 0x44, 0xa8, 0x7e, 0x95, 0xca, 0xc5, 0x17, 0x9a, 0xf3, 0xd1, 0x9e, 0x66, 0xb3, 0x79, 0x4e, 0x35, + 0xdb, 0x73, 0x73, 0xde, 0xa3, 0xd0, 0x50, 0x54, 0xf2, 0x14, 0x7f, 0x88, 0x6a, 0xd3, 0xfe, 0x21, 0x92, 0x6a, 0xef, + 0xc4, 0x70, 0x9f, 0xe5, 0xf8, 0x12, 0x41, 0xcb, 0xeb, 0xb2, 0xcd, 0x1b, 0xc1, 0x66, 0x1b, 0x94, 0x65, 0x03, 0x73, + 0x7e, 0x2b, 0x0c, 0xf7, 0x9b, 0x84, 0x74, 0x7a, 0xd1, 0x85, 0xfa, 0x32, 0xb9, 0x8c, 0xe0, 0x26, 0xa7, 0x20, 0x82, + 0x19, 0xe5, 0x11, 0x94, 0xa0, 0xa4, 0xd5, 0xa5, 0x17, 0xac, 0x4b, 0x1b, 0x0d, 0xcf, 0x66, 0x67, 0x84, 0xf7, 0xa9, + 0xad, 0x9f, 0xe3, 0x29, 0x1e, 0x91, 0x66, 0x1b, 0x2f, 0x48, 0xcb, 0x54, 0xe9, 0x2e, 0x2e, 0x32, 0xd7, 0xcf, 0xc1, + 0x41, 0x5c, 0x24, 0x39, 0x55, 0xfa, 0x05, 0x68, 0x04, 0xc8, 0x02, 0x4f, 0x49, 0x91, 0xb0, 0x5b, 0x96, 0xc5, 0x19, + 0xc2, 0x53, 0x47, 0x83, 0x50, 0x17, 0x2d, 0x48, 0x50, 0x0c, 0xe4, 0x0c, 0x22, 0x58, 0x6f, 0xda, 0x6f, 0x0f, 0x08, + 0x21, 0xd1, 0x7e, 0xb3, 0x19, 0xf5, 0x0a, 0xf2, 0x8b, 0x48, 0x21, 0x25, 0x60, 0xa7, 0xc9, 0x4f, 0x90, 0xd4, 0x09, + 0x92, 0xe2, 0xf7, 0x32, 0xd1, 0x4c, 0xe9, 0x18, 0x92, 0x41, 0x49, 0xa0, 0x3c, 0x86, 0x47, 0x17, 0x47, 0x51, 0x03, + 0x52, 0x0d, 0x8a, 0x22, 0x5c, 0x90, 0x3b, 0x8d, 0xd2, 0x69, 0xff, 0x78, 0x10, 0x9e, 0x11, 0x36, 0x15, 0xfa, 0xbf, + 0xd3, 0xbd, 0x69, 0xbf, 0x65, 0xfa, 0xbf, 0x8c, 0x7a, 0x71, 0x41, 0x94, 0x65, 0xe3, 0x7a, 0x2a, 0x15, 0xcc, 0xcc, + 0x17, 0xa5, 0x6e, 0x80, 0xae, 0xef, 0x11, 0x69, 0x76, 0xd2, 0x78, 0x14, 0xce, 0xa4, 0x09, 0x1d, 0x3a, 0x50, 0xe0, + 0x9c, 0x40, 0x79, 0x5c, 0x10, 0xe8, 0xb4, 0xaa, 0x76, 0xa7, 0x53, 0x97, 0xf0, 0x63, 0xf4, 0x63, 0xef, 0x93, 0x48, + 0x7f, 0x13, 0x76, 0x04, 0x9f, 0xc4, 0x6a, 0x05, 0x7f, 0x7f, 0x13, 0x3d, 0x18, 0x96, 0x49, 0xfb, 0xc5, 0xa5, 0xfd, + 0x04, 0x69, 0x82, 0xa5, 0x66, 0xc0, 0x58, 0x95, 0xfc, 0x98, 0x5d, 0x9c, 0x31, 0xb1, 0x33, 0x38, 0x38, 0xe0, 0x7d, + 0xda, 0x68, 0x0f, 0xe0, 0x46, 0xa0, 0xd0, 0xea, 0x03, 0xd7, 0xd3, 0x38, 0x3a, 0xba, 0x8c, 0x50, 0x2f, 0xda, 0x83, + 0x55, 0xee, 0xca, 0x06, 0x71, 0xb0, 0xce, 0x1a, 0x9a, 0xa6, 0xa3, 0x4b, 0xd2, 0xea, 0xc5, 0xc2, 0x12, 0xf9, 0x1c, + 0xe1, 0xcc, 0xd1, 0xd4, 0x16, 0x1e, 0xa1, 0x86, 0x10, 0x0d, 0xff, 0x3d, 0x42, 0x8d, 0xa9, 0x6e, 0x8c, 0x51, 0x9a, + 0xc1, 0xdf, 0x78, 0x44, 0x08, 0x69, 0x76, 0xca, 0x8a, 0xfe, 0xb0, 0xa4, 0x28, 0x1d, 0x7b, 0xf5, 0x68, 0xdf, 0x6c, + 0x0e, 0xd9, 0x88, 0x79, 0x9f, 0x0d, 0x56, 0xab, 0xe8, 0xa2, 0x77, 0x19, 0xa1, 0x46, 0xec, 0xd1, 0xee, 0xc8, 0xe3, + 0x1d, 0x42, 0x58, 0x0c, 0xd6, 0xee, 0x06, 0xea, 0x86, 0xd5, 0x6e, 0x9b, 0x96, 0xd5, 0xfe, 0x0f, 0xc8, 0x02, 0x5b, + 0x97, 0x72, 0x8f, 0xe5, 0x6f, 0xe7, 0x30, 0x55, 0x8f, 0xdb, 0x92, 0xb4, 0x70, 0x41, 0xbc, 0xba, 0x9b, 0x12, 0x5d, + 0xe1, 0x7f, 0x46, 0xaa, 0xe2, 0xb8, 0x9f, 0xe3, 0xe9, 0x80, 0x08, 0x6a, 0xe4, 0x97, 0xae, 0x57, 0xa6, 0xb3, 0x9c, + 0xdc, 0xb0, 0x8d, 0xfb, 0xdf, 0x1c, 0xee, 0x64, 0x1e, 0xeb, 0x24, 0x5b, 0x14, 0x05, 0x13, 0xfa, 0x95, 0x1c, 0x39, + 0xc6, 0x8e, 0xe5, 0x20, 0x5b, 0xc1, 0xc5, 0x2e, 0x06, 0xae, 0xae, 0xe3, 0x77, 0xca, 0x68, 0x2b, 0x7b, 0x41, 0x46, + 0x96, 0xe1, 0x32, 0xd7, 0xbd, 0xdd, 0x85, 0x13, 0xa5, 0x63, 0x84, 0x47, 0xee, 0x1e, 0x38, 0x4e, 0x92, 0x64, 0x91, + 0x64, 0x90, 0x0d, 0x1d, 0x28, 0xb4, 0x36, 0xfb, 0x2a, 0x56, 0xe4, 0xb1, 0x4e, 0x04, 0xbb, 0x35, 0xdd, 0xc6, 0xa8, + 0x3a, 0xc4, 0xfd, 0x7e, 0xbb, 0xa0, 0x5d, 0x43, 0x80, 0x54, 0x22, 0xe4, 0x88, 0x01, 0x84, 0xe0, 0xee, 0xdf, 0x25, + 0x4d, 0xa9, 0x0a, 0x6f, 0xb6, 0xaa, 0x01, 0xf6, 0x43, 0x95, 0xf7, 0x02, 0xf4, 0xc4, 0x86, 0x3d, 0x2b, 0x0b, 0x5b, + 0xe5, 0x39, 0x42, 0x7c, 0x1c, 0x2f, 0x12, 0xb8, 0x11, 0x34, 0x98, 0x24, 0x04, 0x5a, 0xad, 0x16, 0x21, 0x6e, 0x4d, + 0x2b, 0xc5, 0xf4, 0x98, 0x4c, 0xfb, 0x45, 0xa3, 0x61, 0x94, 0xd7, 0x23, 0x8b, 0x17, 0x0b, 0x84, 0xc7, 0xe5, 0x5e, + 0xf3, 0xe5, 0xe6, 0xa4, 0xde, 0x55, 0x3c, 0xae, 0x2b, 0x81, 0x1b, 0x42, 0x20, 0xa3, 0x5f, 0xd4, 0xd0, 0x3a, 0x9e, + 0x90, 0xa3, 0xb8, 0x9f, 0xf4, 0xfe, 0xe7, 0x00, 0xf5, 0xe2, 0xe4, 0x10, 0x1d, 0x59, 0x5a, 0x32, 0x46, 0xdd, 0xcc, + 0xf6, 0xb1, 0x34, 0xb7, 0x9f, 0x6d, 0x6c, 0x14, 0x90, 0xa9, 0xc4, 0x82, 0xce, 0x58, 0x3a, 0x81, 0x5d, 0xef, 0x91, + 0x67, 0x8e, 0x01, 0x99, 0xd2, 0x89, 0xa3, 0x2d, 0x49, 0xd4, 0x93, 0xb4, 0xfc, 0xea, 0x45, 0x3d, 0x5a, 0x7d, 0xfd, + 0xcf, 0xa8, 0x97, 0xd1, 0xf4, 0x31, 0x5f, 0x3b, 0x25, 0x79, 0xad, 0x8f, 0x33, 0xdf, 0xc7, 0xda, 0x2e, 0x4e, 0x00, + 0xbc, 0x11, 0xda, 0xd6, 0x8e, 0x2c, 0xd0, 0x9a, 0x8f, 0x4b, 0xea, 0xa4, 0x12, 0x4d, 0x27, 0x00, 0xd5, 0x60, 0x11, + 0x54, 0x68, 0x1b, 0x10, 0x4c, 0x19, 0xb0, 0xc5, 0x23, 0x2d, 0x40, 0x73, 0x71, 0xd9, 0x42, 0xcb, 0x5a, 0x61, 0xc7, + 0x59, 0xd5, 0xef, 0xe2, 0x4b, 0xe2, 0x3d, 0x06, 0xaa, 0x7c, 0xb1, 0xe8, 0x8e, 0x1b, 0x0d, 0xa4, 0x3c, 0x7e, 0x8d, + 0xfa, 0xe3, 0x01, 0xbe, 0x05, 0x14, 0xc2, 0x35, 0x8c, 0xc2, 0xb5, 0x39, 0x76, 0xdc, 0x1c, 0x1b, 0x0d, 0xb9, 0x46, + 0xdd, 0xa0, 0xf2, 0xc2, 0x55, 0x5e, 0xaf, 0x2d, 0x64, 0x36, 0x31, 0xee, 0x1c, 0x99, 0x14, 0x30, 0x04, 0x23, 0x84, + 0xbc, 0x92, 0x68, 0x67, 0xb3, 0xd0, 0x28, 0x54, 0x37, 0xbb, 0x17, 0x28, 0xaa, 0x3d, 0x3d, 0x62, 0x80, 0x05, 0x54, + 0x2d, 0xd5, 0xc8, 0x53, 0x8d, 0x47, 0x8d, 0xb6, 0x41, 0xf7, 0x66, 0xbb, 0x5b, 0x6f, 0xec, 0x7e, 0xd5, 0x18, 0x1e, + 0x35, 0xc8, 0xb4, 0xda, 0xe1, 0x6b, 0xd9, 0x68, 0xac, 0xeb, 0xf7, 0xa5, 0x7e, 0x13, 0xd7, 0xee, 0x2f, 0x9e, 0x6e, + 0x99, 0x78, 0xf8, 0xd3, 0xb7, 0x3a, 0x6f, 0x45, 0xc2, 0x85, 0x60, 0x05, 0x9c, 0xb0, 0x44, 0x63, 0xb1, 0x5e, 0x97, + 0xa7, 0xfe, 0xef, 0xda, 0xda, 0x8c, 0x11, 0x0e, 0x74, 0xc8, 0x48, 0x6d, 0x58, 0xe2, 0x02, 0x53, 0x43, 0x45, 0x08, + 0x21, 0x1f, 0xb4, 0x37, 0x8f, 0xd1, 0x86, 0x24, 0x65, 0x24, 0x38, 0xbb, 0x63, 0x45, 0x58, 0x72, 0x7d, 0xef, 0xb1, + 0xfc, 0xae, 0x48, 0xd7, 0x17, 0x83, 0xd4, 0x14, 0xcb, 0x1d, 0x21, 0xcb, 0xc9, 0x17, 0x90, 0x73, 0xca, 0x0b, 0x96, + 0xc4, 0x10, 0xc4, 0x27, 0xbc, 0x60, 0x86, 0x71, 0xbf, 0xe7, 0xe5, 0xc6, 0xac, 0xce, 0x69, 0x66, 0xa1, 0xf6, 0x07, + 0xa0, 0x99, 0x83, 0x72, 0x48, 0x92, 0xad, 0x62, 0xd7, 0xf7, 0x1e, 0xbe, 0xde, 0x25, 0x43, 0xaf, 0x56, 0x4e, 0x7a, + 0xce, 0x80, 0xf5, 0xc1, 0x79, 0x35, 0xd4, 0xcc, 0xfd, 0x48, 0xe3, 0xcc, 0x30, 0x51, 0x79, 0xcc, 0x01, 0x99, 0xae, + 0xef, 0x3d, 0x7c, 0x17, 0x73, 0xa3, 0x9b, 0x42, 0x38, 0x9c, 0x77, 0x5c, 0x90, 0x98, 0x12, 0x86, 0xec, 0xe4, 0x4b, + 0x3a, 0x56, 0x04, 0xa7, 0x7b, 0x4a, 0x4d, 0x26, 0x88, 0x1d, 0x7d, 0x31, 0x20, 0x99, 0x03, 0x01, 0xc9, 0x10, 0xce, + 0x6a, 0x72, 0x1d, 0x31, 0x6b, 0x60, 0x3a, 0xbb, 0x82, 0xc5, 0x48, 0x2c, 0x7b, 0x88, 0x70, 0x66, 0xba, 0xd5, 0x6b, + 0x7b, 0x9c, 0x28, 0xba, 0x69, 0xe8, 0x56, 0xc9, 0xb3, 0xef, 0x41, 0xf0, 0xf2, 0x1f, 0xaf, 0x5c, 0xdb, 0x65, 0xc2, + 0x13, 0x6f, 0x91, 0x76, 0x7d, 0xef, 0xe1, 0xaf, 0xce, 0x28, 0x6d, 0x4e, 0x3d, 0xf9, 0xdf, 0x92, 0x51, 0x1f, 0xfe, + 0x9a, 0x54, 0xb9, 0xa6, 0xf0, 0xf5, 0xbd, 0x87, 0xbf, 0xef, 0x2a, 0x06, 0xe9, 0xeb, 0x45, 0xa5, 0x24, 0x30, 0xe3, + 0x5b, 0xb2, 0x3c, 0x5d, 0xba, 0xb3, 0x22, 0x15, 0x6b, 0x6c, 0x4e, 0xa8, 0x54, 0xad, 0x4b, 0xdd, 0xca, 0x13, 0x2c, + 0x89, 0xb9, 0x4a, 0xaa, 0x2f, 0x9b, 0x43, 0x63, 0x2e, 0xc5, 0x55, 0x26, 0xe7, 0xec, 0x1b, 0xf7, 0x4b, 0x4f, 0x35, + 0x4a, 0xf8, 0x0c, 0x0c, 0x71, 0xcc, 0xd8, 0x05, 0xde, 0x6f, 0xa1, 0xee, 0xc6, 0x79, 0x26, 0x0d, 0xa2, 0x16, 0xf5, + 0xc3, 0x06, 0x53, 0xd2, 0xc2, 0x19, 0x69, 0xe1, 0x9c, 0xa8, 0x7e, 0xcb, 0x9e, 0x18, 0xdd, 0xbc, 0x6c, 0xda, 0x9e, + 0x3b, 0xb0, 0xdd, 0x73, 0xbb, 0x6f, 0xed, 0xa1, 0x3c, 0xed, 0xe6, 0x46, 0x7f, 0x69, 0x0e, 0xfa, 0xa9, 0x41, 0x8d, + 0x27, 0x2c, 0x2e, 0x70, 0x61, 0x5a, 0xbe, 0xe2, 0xc3, 0x1c, 0xec, 0x54, 0x60, 0x66, 0x58, 0xa3, 0xb4, 0x2c, 0xdb, + 0x76, 0x65, 0xf3, 0xc4, 0xac, 0x55, 0x81, 0xf3, 0x04, 0x48, 0x39, 0xce, 0x9d, 0x5d, 0x8f, 0xda, 0xae, 0x72, 0x76, + 0x70, 0x10, 0xbb, 0x4a, 0x34, 0x2e, 0x7c, 0x7e, 0x75, 0x03, 0xf8, 0xde, 0x52, 0x8d, 0x29, 0x32, 0x13, 0x68, 0x34, + 0xb2, 0xc1, 0x9a, 0xee, 0x13, 0x12, 0xe7, 0x75, 0x28, 0xfa, 0xd1, 0x1b, 0x66, 0x70, 0x03, 0x00, 0x8d, 0x46, 0x79, + 0xdd, 0xbb, 0x01, 0xb1, 0xa7, 0x1a, 0xcb, 0xf5, 0x97, 0xb8, 0xb4, 0x26, 0x6a, 0x6d, 0xd9, 0x61, 0xf9, 0x51, 0x20, + 0x11, 0xe2, 0xae, 0xf0, 0xf3, 0x09, 0xb6, 0x86, 0x80, 0x72, 0x2f, 0x9c, 0x0d, 0x04, 0x36, 0x56, 0x5b, 0xae, 0x90, + 0x27, 0x6d, 0x1d, 0x94, 0xfa, 0x42, 0x70, 0xc1, 0x05, 0x85, 0x1a, 0x6b, 0x87, 0xe5, 0x4f, 0xd8, 0xb6, 0x39, 0x27, + 0x56, 0xc8, 0x69, 0xcb, 0xcc, 0x30, 0x0c, 0xc0, 0x3a, 0x25, 0x60, 0x9e, 0x93, 0x97, 0xdf, 0x46, 0xfd, 0x87, 0x01, + 0xea, 0x3f, 0x22, 0x2c, 0xd8, 0x06, 0x56, 0x57, 0x92, 0x48, 0xa7, 0xa0, 0x50, 0x3e, 0xeb, 0xf1, 0x9c, 0x80, 0x36, + 0xae, 0x0e, 0xd5, 0xda, 0x15, 0xe5, 0x37, 0x28, 0x4b, 0xb8, 0x53, 0x8c, 0x3e, 0x13, 0xfb, 0xfb, 0xe4, 0xb8, 0xba, + 0xa0, 0x83, 0xae, 0x77, 0x29, 0x07, 0x43, 0x52, 0xf8, 0xf0, 0xf7, 0xef, 0xdf, 0xad, 0x3e, 0x9e, 0x6f, 0xef, 0xe0, + 0xc0, 0xac, 0x14, 0x66, 0x1d, 0x6c, 0xe0, 0xba, 0x91, 0x29, 0xf4, 0x5f, 0xde, 0x89, 0xd7, 0xa9, 0xd0, 0xc6, 0x66, + 0xf4, 0xc7, 0x21, 0x8c, 0xb6, 0xdd, 0x36, 0x25, 0x58, 0xd0, 0x2c, 0xd0, 0x25, 0x6b, 0xdc, 0x4a, 0x8b, 0x6f, 0x90, + 0x91, 0x87, 0xa6, 0x00, 0x13, 0xa3, 0xdd, 0xd9, 0x8f, 0xd6, 0x0e, 0x4f, 0xec, 0xd0, 0xd0, 0xd2, 0x10, 0x42, 0x8b, + 0xf7, 0x80, 0x39, 0xf6, 0x88, 0x00, 0x10, 0xbd, 0x34, 0x90, 0xaa, 0x40, 0x16, 0x45, 0x95, 0x22, 0xff, 0xf9, 0x3e, + 0x21, 0x2f, 0x2b, 0x45, 0xe6, 0xdb, 0xca, 0x98, 0x0b, 0x10, 0x03, 0xa5, 0x70, 0x91, 0x50, 0x26, 0xd8, 0xcb, 0xd0, + 0x0f, 0xda, 0x97, 0x37, 0xd2, 0x66, 0x52, 0x71, 0xe3, 0xc1, 0x4d, 0xa9, 0x51, 0xf1, 0xd9, 0x7c, 0x0f, 0x89, 0x8d, + 0xdc, 0x7b, 0x90, 0xcb, 0xa8, 0x19, 0x24, 0x7c, 0xbf, 0x33, 0xa5, 0x7d, 0xbb, 0xeb, 0xcf, 0x9b, 0x16, 0x31, 0x1b, + 0xeb, 0x92, 0x70, 0xa1, 0x58, 0xa1, 0x1f, 0xb1, 0xb1, 0x2c, 0xe0, 0xfe, 0xa3, 0x04, 0x0b, 0x5a, 0xdf, 0x0b, 0x74, + 0x80, 0x66, 0x82, 0xc1, 0xa5, 0xc3, 0xc6, 0x0c, 0xcd, 0xaf, 0xcf, 0xe6, 0x0e, 0xfc, 0x7a, 0xb3, 0xd6, 0xcb, 0x83, + 0x83, 0x2f, 0xac, 0x02, 0x94, 0x1b, 0xa6, 0x19, 0x46, 0x40, 0xbc, 0x2c, 0x97, 0xe3, 0x6e, 0x86, 0xef, 0xc5, 0x95, + 0xca, 0xc0, 0x13, 0x8e, 0x90, 0x08, 0x3d, 0x27, 0x7a, 0x3d, 0xd9, 0xa4, 0xf7, 0x4e, 0x9b, 0x21, 0x42, 0xb1, 0x06, + 0xc8, 0x3d, 0xc8, 0xe5, 0x56, 0xc9, 0xa4, 0x2a, 0x5b, 0xdb, 0x72, 0x10, 0x8f, 0x01, 0x5c, 0xb1, 0x11, 0x52, 0x02, + 0x34, 0xdc, 0x2d, 0xb4, 0x3c, 0x97, 0xc0, 0xfe, 0x63, 0x95, 0x80, 0x48, 0x8b, 0x6a, 0x1b, 0x17, 0x21, 0x6c, 0x4d, + 0x7d, 0x02, 0xe3, 0x84, 0x87, 0xcf, 0x77, 0x69, 0xa8, 0x3d, 0x6a, 0x33, 0x73, 0x06, 0x41, 0x09, 0x89, 0xca, 0x0a, + 0xc9, 0x97, 0x58, 0x38, 0x6e, 0xce, 0xdf, 0xc3, 0x01, 0x29, 0x56, 0x34, 0xb6, 0x77, 0x5b, 0x70, 0x7c, 0x14, 0xc9, + 0x22, 0xae, 0x75, 0xdd, 0x2d, 0x4c, 0x35, 0xec, 0x40, 0x47, 0x43, 0x38, 0x15, 0xe6, 0x9e, 0xf0, 0x71, 0x45, 0x52, + 0x7f, 0xb6, 0x26, 0xda, 0xda, 0x13, 0xc3, 0xca, 0x34, 0x25, 0x98, 0xff, 0xcf, 0xd6, 0xea, 0xba, 0x2c, 0x84, 0x99, + 0x19, 0xc6, 0x8d, 0x5d, 0x05, 0xb6, 0x06, 0x1c, 0x5b, 0xfe, 0x2d, 0x83, 0x45, 0xf5, 0x4a, 0x71, 0xd3, 0x69, 0xc0, + 0x04, 0xbc, 0x05, 0xeb, 0x99, 0xcd, 0xad, 0xff, 0xdc, 0x1c, 0x8c, 0x02, 0xab, 0x1a, 0x81, 0x97, 0x86, 0xc0, 0x23, + 0x60, 0xdc, 0xbc, 0x69, 0x79, 0xcf, 0x19, 0xd1, 0x08, 0x7f, 0xe2, 0x39, 0x3c, 0xb3, 0x2c, 0xf7, 0xd6, 0xc7, 0xc6, + 0x8a, 0xa4, 0x82, 0x80, 0x6d, 0x11, 0x76, 0x44, 0x5e, 0x22, 0xac, 0x1a, 0x8d, 0xae, 0xba, 0x60, 0x95, 0x56, 0xa5, + 0x1a, 0xa6, 0x80, 0x5b, 0x62, 0xc0, 0xfb, 0xda, 0x89, 0x0a, 0x86, 0x04, 0xde, 0xfa, 0x5b, 0x81, 0xfa, 0xfe, 0xe1, + 0xdb, 0x38, 0xa4, 0x6f, 0x61, 0xd9, 0xf2, 0x22, 0x16, 0xa6, 0x14, 0x57, 0x77, 0x38, 0x6f, 0xbe, 0x6f, 0x36, 0x02, + 0xe3, 0xde, 0x6f, 0x63, 0xb0, 0x71, 0x43, 0x5d, 0x6d, 0x49, 0x43, 0xb9, 0x09, 0xbb, 0xa8, 0xb2, 0x77, 0x0c, 0x3b, + 0xeb, 0xea, 0x4a, 0xda, 0xd5, 0x44, 0xad, 0xd7, 0x8a, 0x55, 0x46, 0x03, 0x1b, 0x86, 0x9d, 0xe6, 0x98, 0xd9, 0x56, + 0xe0, 0x3f, 0x9e, 0x13, 0x8d, 0x03, 0x64, 0x7d, 0xf3, 0xad, 0xeb, 0x94, 0x6a, 0x98, 0xb0, 0xbd, 0xdd, 0xf9, 0xf8, + 0x98, 0xef, 0x3a, 0x1f, 0xb1, 0x74, 0x5b, 0xdf, 0x9c, 0x8d, 0xed, 0x7f, 0xe3, 0x6c, 0x74, 0x6a, 0x7b, 0x7f, 0x3c, + 0x02, 0x77, 0x52, 0x3b, 0x1e, 0xeb, 0x6b, 0x4a, 0x24, 0x16, 0x6e, 0x39, 0x2e, 0x3b, 0xab, 0x95, 0xe8, 0xb7, 0x40, + 0xed, 0x14, 0x45, 0xf0, 0xb3, 0x6d, 0x7f, 0x06, 0x24, 0xd9, 0xea, 0x90, 0x63, 0x51, 0x8a, 0x32, 0x28, 0x01, 0x03, + 0xea, 0xd8, 0xd8, 0x7a, 0x19, 0xc4, 0x76, 0x38, 0xe4, 0xb0, 0x9c, 0x88, 0xf2, 0xea, 0x0a, 0x46, 0x6c, 0x8e, 0x0d, + 0x27, 0x60, 0xc6, 0x3b, 0xad, 0x0a, 0xbd, 0xf8, 0xf9, 0xaf, 0x99, 0xd3, 0xda, 0x11, 0x63, 0x39, 0x89, 0x9a, 0x15, + 0x83, 0x1b, 0x81, 0x63, 0x18, 0xf7, 0x8d, 0x84, 0x5a, 0x9d, 0xea, 0xa8, 0x76, 0x24, 0xe1, 0x16, 0xa8, 0xdd, 0xf6, + 0xcd, 0xb9, 0xb4, 0x5a, 0xed, 0x3c, 0x58, 0x70, 0x11, 0xe0, 0xf6, 0x73, 0xa2, 0x6b, 0x24, 0x85, 0x12, 0x27, 0x41, + 0xe1, 0xdc, 0xa0, 0xaa, 0x26, 0xb2, 0xdf, 0x1a, 0x00, 0x4f, 0xda, 0xcd, 0x2e, 0x64, 0x25, 0x24, 0x67, 0x8d, 0x06, + 0xca, 0xcb, 0x8e, 0x69, 0x5f, 0x34, 0xb2, 0x01, 0x66, 0x38, 0xb3, 0x02, 0x0b, 0x9c, 0x5e, 0x71, 0x5e, 0x75, 0xdd, + 0xcf, 0x06, 0x08, 0x17, 0xab, 0x55, 0x6c, 0x87, 0x96, 0xa3, 0xd5, 0x2a, 0x0f, 0x87, 0x66, 0xf2, 0xa1, 0xe2, 0xcb, + 0x9e, 0x26, 0x2f, 0xcd, 0x79, 0xf8, 0x12, 0x06, 0xd9, 0x20, 0x71, 0xee, 0x54, 0x82, 0x39, 0x68, 0xae, 0x1a, 0xb2, + 0x9f, 0x35, 0xda, 0x83, 0x80, 0x86, 0xf5, 0xb3, 0x01, 0xc9, 0xd7, 0x60, 0x39, 0xab, 0xdc, 0x81, 0xf9, 0x37, 0x1c, + 0x6c, 0x7f, 0x9b, 0x73, 0xc6, 0x36, 0x18, 0xae, 0xc9, 0xa6, 0xca, 0xa0, 0xc4, 0x2b, 0xb7, 0xb8, 0xbe, 0x5c, 0xcd, + 0xc0, 0xa2, 0x2c, 0x84, 0xdd, 0x35, 0x73, 0x0f, 0x84, 0xff, 0x12, 0xdb, 0x25, 0x2d, 0x8d, 0xb8, 0x37, 0x10, 0xdf, + 0xdb, 0x6e, 0x27, 0x49, 0x42, 0x8b, 0x89, 0xb9, 0x12, 0xf1, 0x37, 0xbc, 0x66, 0x0f, 0x1c, 0xbb, 0x71, 0x06, 0x3d, + 0xf7, 0xcb, 0xce, 0x06, 0xc4, 0x8e, 0xdf, 0x33, 0x3b, 0xde, 0x71, 0xa5, 0xa0, 0xbb, 0x75, 0x11, 0x76, 0x30, 0xf4, + 0x7f, 0x79, 0x30, 0x27, 0x6e, 0x30, 0x16, 0x4d, 0x36, 0xe0, 0xf6, 0x0d, 0x78, 0x14, 0x74, 0x03, 0x6e, 0xdf, 0x86, + 0xaf, 0x87, 0x56, 0xf6, 0xcd, 0x01, 0x06, 0x64, 0xc2, 0x8e, 0xb4, 0x4a, 0x08, 0x86, 0x79, 0xba, 0xc9, 0x91, 0x59, + 0xb2, 0x0a, 0x87, 0xab, 0x26, 0xb1, 0xd8, 0xd8, 0x0b, 0x15, 0x93, 0x1a, 0x08, 0xc6, 0x22, 0x7d, 0x89, 0x42, 0xa5, + 0x41, 0xdd, 0x38, 0x06, 0xb0, 0xca, 0x69, 0xeb, 0x5f, 0x1e, 0x1c, 0x80, 0xd0, 0x00, 0xac, 0x5d, 0x92, 0xd1, 0xb9, + 0x5e, 0x14, 0xc0, 0x5f, 0x29, 0xff, 0x1b, 0x92, 0xc1, 0xed, 0xc4, 0xa4, 0xc1, 0x0f, 0x48, 0x98, 0x53, 0xa5, 0xf8, + 0x17, 0x9b, 0xe6, 0x7e, 0xe3, 0x82, 0x78, 0x8c, 0x56, 0x96, 0x53, 0x94, 0xa8, 0x2b, 0x1d, 0xba, 0xd6, 0x21, 0xf7, + 0xf4, 0x0b, 0x13, 0xfa, 0x25, 0x57, 0x9a, 0x09, 0x00, 0x40, 0x85, 0x78, 0x30, 0x25, 0x85, 0x60, 0xeb, 0xd6, 0x6a, + 0xd1, 0xd1, 0xe8, 0xbb, 0x55, 0x74, 0x9d, 0x2d, 0x9a, 0x52, 0x31, 0xca, 0x6d, 0x27, 0xa1, 0xcd, 0xa4, 0xb7, 0x13, + 0x2d, 0x4b, 0x86, 0x16, 0x3b, 0x15, 0xfb, 0x61, 0x68, 0x7d, 0x2c, 0x88, 0x3f, 0x17, 0xfc, 0x59, 0xfa, 0x5d, 0x3e, + 0x06, 0xae, 0xd4, 0xbf, 0xb1, 0x0a, 0xe1, 0x4c, 0xb0, 0x0e, 0xc8, 0x6b, 0x52, 0x1f, 0xa7, 0x47, 0x9d, 0x7c, 0x4b, + 0xb9, 0x50, 0x1a, 0x85, 0x6d, 0x9c, 0x14, 0x06, 0x53, 0xce, 0xbe, 0x2d, 0x71, 0xfd, 0xea, 0x8f, 0x11, 0x7f, 0x74, + 0x88, 0x7f, 0x97, 0x4a, 0xa3, 0x65, 0x89, 0x60, 0xc8, 0xef, 0x48, 0xad, 0xe0, 0x2a, 0x36, 0xe7, 0xfa, 0xb9, 0x9e, + 0xe5, 0x1b, 0x9e, 0x38, 0x5d, 0xad, 0x4a, 0xa9, 0x40, 0xc5, 0x37, 0x0c, 0x3f, 0x61, 0x70, 0x6f, 0xfc, 0x8c, 0x07, + 0x55, 0xb6, 0xef, 0x8b, 0x9f, 0x05, 0xf7, 0xc5, 0xcf, 0x78, 0xba, 0x5d, 0x34, 0xb8, 0x27, 0xee, 0x24, 0xe7, 0x49, + 0x2b, 0xf2, 0x7c, 0xd4, 0x94, 0x56, 0xfe, 0x95, 0x76, 0x6b, 0xe0, 0xca, 0x26, 0x0e, 0x8c, 0xf3, 0xea, 0x22, 0x14, + 0x73, 0xe6, 0x8c, 0x96, 0xc3, 0xff, 0xd6, 0x3a, 0xb9, 0x93, 0x47, 0x5a, 0x29, 0xe4, 0x0d, 0x2d, 0xf4, 0x3d, 0xd8, + 0x70, 0xc5, 0x96, 0x0f, 0x20, 0x25, 0xa0, 0x6c, 0xfb, 0xf7, 0xba, 0x08, 0xc4, 0x71, 0x65, 0x9d, 0x8f, 0xc2, 0xf6, + 0x49, 0x51, 0x72, 0x75, 0x75, 0x21, 0xe4, 0xd6, 0x68, 0x09, 0x10, 0xa6, 0xde, 0x35, 0x8f, 0x39, 0x9a, 0xcc, 0xd2, + 0xe5, 0xba, 0x54, 0x1d, 0x14, 0x96, 0xab, 0xe3, 0x08, 0x17, 0x6b, 0x73, 0x83, 0xfe, 0x8a, 0xe3, 0xbf, 0xb9, 0xa3, + 0x91, 0x9f, 0x4a, 0x0a, 0xf4, 0x68, 0xb7, 0xaf, 0xcd, 0x0e, 0x12, 0x69, 0xe7, 0x50, 0x5a, 0x0a, 0x00, 0x56, 0x1b, + 0x7c, 0x5d, 0x7b, 0x9c, 0x7a, 0x22, 0xdd, 0x6c, 0xbe, 0x69, 0x08, 0x8b, 0x59, 0x69, 0xc1, 0x63, 0xba, 0xd9, 0x61, + 0x39, 0xea, 0x65, 0x71, 0x5d, 0xee, 0xb1, 0x5a, 0xbf, 0xe8, 0x1b, 0xa0, 0xac, 0x0c, 0xd1, 0x56, 0xab, 0xb8, 0x0e, + 0x6f, 0x22, 0x82, 0x6b, 0x10, 0x84, 0x45, 0x60, 0xc0, 0x51, 0x63, 0xbc, 0x6d, 0x9d, 0x18, 0x6d, 0xda, 0x2f, 0x79, + 0xd6, 0xbd, 0x36, 0x8e, 0x50, 0xd1, 0x60, 0xab, 0x87, 0x9a, 0x07, 0x6c, 0x67, 0x57, 0x76, 0x14, 0x40, 0x68, 0x4a, + 0xbd, 0x71, 0x6e, 0x65, 0x45, 0xbb, 0x03, 0xbe, 0xe8, 0x3b, 0xe6, 0xb9, 0x0e, 0x74, 0xdb, 0xf9, 0x81, 0x6d, 0xd3, + 0x13, 0xf9, 0x2d, 0xdb, 0xa6, 0x1a, 0x27, 0xbc, 0xdf, 0x42, 0xdf, 0x37, 0x84, 0xb5, 0x7d, 0xed, 0x2e, 0xf2, 0xbf, + 0xd0, 0x5d, 0x1b, 0xd0, 0xd3, 0x82, 0xd9, 0xd3, 0x98, 0x0f, 0x7a, 0xbd, 0xfe, 0x54, 0xfa, 0x2f, 0x18, 0x5b, 0xa1, + 0x4f, 0x76, 0x17, 0x38, 0xb1, 0xd2, 0x38, 0x04, 0xc7, 0xaf, 0x38, 0x99, 0xe4, 0x72, 0x48, 0xf3, 0x77, 0xd0, 0x63, + 0x95, 0xfb, 0xfc, 0x6e, 0x54, 0x50, 0xcd, 0x1c, 0xad, 0xa9, 0x46, 0xf1, 0x8a, 0x07, 0xc3, 0x78, 0xc5, 0x2d, 0xe5, + 0xae, 0x5a, 0xc0, 0xcb, 0x97, 0x65, 0x13, 0xe9, 0xa7, 0x75, 0x29, 0x83, 0xa9, 0xdd, 0xbd, 0x6c, 0x92, 0x34, 0x56, + 0x92, 0x34, 0xa6, 0xe2, 0xcd, 0xa6, 0xe2, 0xf8, 0xef, 0x6f, 0x0c, 0x76, 0x9b, 0xcc, 0xfd, 0x1d, 0x90, 0xb9, 0xbf, + 0x79, 0xfa, 0xdd, 0x5a, 0x01, 0xc5, 0x3b, 0x4e, 0x8e, 0x8d, 0x65, 0x8c, 0x1d, 0xf5, 0x5b, 0x0d, 0x06, 0x0d, 0x9a, + 0x5c, 0x06, 0xde, 0x0e, 0xd5, 0xe9, 0xe5, 0xed, 0x8f, 0xe2, 0x6c, 0xa1, 0xb4, 0x9c, 0xb9, 0x46, 0x95, 0xf3, 0x71, + 0x32, 0x99, 0xa0, 0xc0, 0x36, 0x77, 0xf8, 0x69, 0xdd, 0x8d, 0x6c, 0xf9, 0x99, 0x8b, 0x51, 0xaa, 0xb0, 0x3b, 0x5b, + 0x54, 0x2a, 0xd7, 0xc4, 0x9b, 0x39, 0x6f, 0xe7, 0xe1, 0x31, 0x17, 0x5c, 0x4d, 0x59, 0x11, 0x17, 0x68, 0xf9, 0xad, + 0xce, 0x0a, 0xb8, 0xcd, 0xb1, 0x9d, 0xe1, 0x51, 0x69, 0x39, 0xa0, 0x13, 0x68, 0x0d, 0x74, 0x46, 0x33, 0xa6, 0xa7, + 0x72, 0x04, 0x86, 0x2f, 0xc9, 0xa8, 0x74, 0xa7, 0x3a, 0x38, 0xd8, 0x8f, 0x23, 0xa3, 0xbf, 0x00, 0x1f, 0xf4, 0x30, + 0x07, 0xf5, 0x96, 0xe0, 0x18, 0x54, 0x75, 0xcd, 0xd0, 0x92, 0x6d, 0xfa, 0xd0, 0xe8, 0xe4, 0x33, 0xbb, 0xc3, 0x1c, + 0xad, 0xd7, 0xa9, 0x1d, 0x75, 0x34, 0xe6, 0x2c, 0x1f, 0x45, 0xf8, 0x33, 0xbb, 0x4b, 0x4b, 0xb7, 0x75, 0xe3, 0x65, + 0x6d, 0x16, 0x31, 0x92, 0x37, 0x22, 0xc2, 0x55, 0x27, 0xe9, 0x72, 0x8d, 0x65, 0xc1, 0x27, 0x80, 0xa3, 0xbf, 0xb0, + 0xbb, 0xd4, 0xb5, 0x17, 0xb8, 0x0a, 0xa2, 0xa5, 0x07, 0x7d, 0x12, 0x24, 0x87, 0xcb, 0xe0, 0x04, 0x8e, 0xbe, 0xa9, + 0x3b, 0x20, 0xb5, 0x72, 0x95, 0x08, 0x89, 0xd0, 0xfa, 0xdf, 0x9d, 0x0a, 0x5e, 0x84, 0xe7, 0x9c, 0xae, 0x59, 0xdc, + 0x6e, 0x54, 0x62, 0x50, 0xa1, 0xb2, 0x20, 0xf9, 0x18, 0x73, 0xbf, 0xfb, 0x9c, 0xf7, 0x43, 0xa0, 0x33, 0x5b, 0x50, + 0xd7, 0x68, 0x3a, 0x32, 0xbf, 0x50, 0x75, 0x07, 0x35, 0xd3, 0x55, 0xc5, 0xbd, 0x8f, 0x31, 0x00, 0x1e, 0xac, 0x65, + 0xa8, 0x71, 0x08, 0x5d, 0x7b, 0x33, 0xd5, 0x31, 0x25, 0xf1, 0xd2, 0xcf, 0x21, 0xe5, 0x21, 0x18, 0xf5, 0x1a, 0xd0, + 0xd0, 0x21, 0x98, 0xb5, 0x3c, 0xe4, 0xe3, 0x58, 0x6c, 0x9d, 0xa1, 0xd2, 0x9c, 0xa1, 0x49, 0x00, 0xf2, 0x6f, 0x9c, + 0x99, 0xcc, 0x40, 0xc3, 0xf0, 0x96, 0xe6, 0x00, 0x74, 0xab, 0xeb, 0x70, 0x28, 0x5c, 0xd1, 0xd2, 0x79, 0xcf, 0x2e, + 0xba, 0xac, 0x0d, 0x2b, 0x36, 0xed, 0xa0, 0x75, 0x0a, 0x53, 0x62, 0xb6, 0xc0, 0xda, 0xeb, 0x7d, 0xb8, 0xb7, 0xab, + 0x8d, 0x8b, 0xc4, 0x4f, 0x8b, 0x78, 0x98, 0xc4, 0x14, 0x2d, 0x79, 0x4c, 0xb1, 0x04, 0x3b, 0xc8, 0x62, 0x5d, 0x8e, + 0x9f, 0x85, 0xcb, 0x51, 0xb3, 0x92, 0xde, 0xed, 0x60, 0x08, 0x5c, 0xbe, 0x06, 0xdb, 0x50, 0xcc, 0x3d, 0x61, 0xe1, + 0xb1, 0xf1, 0xf4, 0x0b, 0xd6, 0x6d, 0x6e, 0x17, 0xc4, 0xaf, 0xc0, 0x98, 0xc6, 0xcb, 0x60, 0x16, 0xa1, 0x53, 0xb9, + 0x73, 0x38, 0x74, 0xd7, 0x84, 0x95, 0xf1, 0x6a, 0xac, 0xc8, 0xc6, 0xd1, 0xf3, 0x7d, 0x1b, 0xcf, 0x7f, 0x16, 0xac, + 0xb8, 0xbb, 0x62, 0x60, 0x63, 0x2d, 0xc1, 0xdd, 0xb8, 0x5a, 0x86, 0xca, 0x40, 0xbe, 0x27, 0x0d, 0xeb, 0xb2, 0xc6, + 0xdf, 0x8d, 0x8a, 0xb1, 0x36, 0xf7, 0x94, 0x81, 0xb6, 0xc6, 0x6e, 0x17, 0xf6, 0x4d, 0xd7, 0x4d, 0xd6, 0x35, 0x8a, + 0xb8, 0x0a, 0xd2, 0xee, 0x6e, 0x01, 0x17, 0xa1, 0x3f, 0x6c, 0x5f, 0x0d, 0x36, 0x55, 0x37, 0x90, 0x04, 0xd7, 0x7e, + 0xf2, 0xdb, 0x53, 0xdd, 0x65, 0xad, 0xfb, 0xed, 0xa9, 0xd6, 0x2e, 0x0b, 0x8d, 0x21, 0x11, 0x76, 0xfd, 0x94, 0xfe, + 0xd3, 0x62, 0xbd, 0x46, 0x6b, 0x18, 0xde, 0x7b, 0xde, 0x8d, 0xe3, 0xf7, 0xde, 0x42, 0x31, 0x81, 0x8b, 0xdc, 0xab, + 0x5c, 0x7a, 0x42, 0x5e, 0x8d, 0xe0, 0x3d, 0xdf, 0x1a, 0xc2, 0x7b, 0x1e, 0x38, 0xbd, 0x82, 0xd4, 0x34, 0x11, 0x6c, + 0xe4, 0xe9, 0x27, 0xb2, 0x48, 0x68, 0xf8, 0xb8, 0xd7, 0x9c, 0x70, 0xfd, 0x57, 0x0a, 0xfc, 0x17, 0x1e, 0x2e, 0xb4, + 0x96, 0x02, 0x73, 0x31, 0x5f, 0x68, 0xac, 0xcc, 0xe8, 0x97, 0x63, 0x29, 0x74, 0x73, 0x4c, 0x67, 0x3c, 0xbf, 0x4b, + 0x17, 0xbc, 0x39, 0x93, 0x42, 0xaa, 0x39, 0xcd, 0x18, 0x56, 0x77, 0x4a, 0xb3, 0x59, 0x73, 0xc1, 0xf1, 0x73, 0x96, + 0x7f, 0x61, 0x9a, 0x67, 0x14, 0xbf, 0x95, 0x43, 0xa9, 0x25, 0x7e, 0x7d, 0x7b, 0x37, 0x61, 0x02, 0xff, 0x3e, 0x5c, + 0x08, 0xbd, 0xc0, 0x8a, 0x0a, 0xd5, 0x54, 0xac, 0xe0, 0xe3, 0x6e, 0xb3, 0x39, 0x2f, 0xf8, 0x8c, 0x16, 0x77, 0xcd, + 0x4c, 0xe6, 0xb2, 0x48, 0xff, 0xab, 0x75, 0x4c, 0x1f, 0x8c, 0x4f, 0xba, 0xba, 0xa0, 0x42, 0x71, 0x58, 0x98, 0x94, + 0xe6, 0xf9, 0xde, 0xf1, 0x69, 0x6b, 0xa6, 0xf6, 0xed, 0x85, 0x1f, 0x15, 0x7a, 0xfd, 0x17, 0xfe, 0x20, 0x61, 0x94, + 0xc9, 0x50, 0x0b, 0x37, 0xc8, 0x65, 0xb6, 0x28, 0x94, 0x2c, 0xd2, 0xb9, 0xe4, 0x42, 0xb3, 0xa2, 0x3b, 0x94, 0xc5, + 0x88, 0x15, 0xcd, 0x82, 0x8e, 0xf8, 0x42, 0xa5, 0x27, 0xf3, 0xdb, 0x6e, 0xbd, 0x07, 0x9b, 0x9f, 0x0a, 0x29, 0x58, + 0x17, 0xf8, 0x8d, 0x49, 0x21, 0x17, 0x62, 0xe4, 0x86, 0xb1, 0x10, 0x8a, 0xe9, 0xee, 0x9c, 0x8e, 0xc0, 0x0e, 0x38, + 0x3d, 0x9f, 0xdf, 0x76, 0xcd, 0xac, 0x6f, 0x18, 0x9f, 0x4c, 0x75, 0x7a, 0xda, 0x6a, 0xd9, 0x6f, 0xc5, 0xbf, 0xb2, + 0xb4, 0xdd, 0x49, 0x3a, 0xa7, 0xf3, 0x5b, 0xe0, 0xe0, 0x35, 0x2b, 0x9a, 0x00, 0x0b, 0xa8, 0xd4, 0x4e, 0x5a, 0x0f, + 0x8e, 0xef, 0x43, 0x06, 0xd8, 0x38, 0x34, 0xcd, 0x84, 0xc0, 0xd8, 0x3d, 0x5d, 0xcc, 0xe7, 0xac, 0x00, 0x2f, 0xfa, + 0xee, 0x8c, 0x16, 0x13, 0x2e, 0x9a, 0x85, 0x69, 0xb4, 0x79, 0x3e, 0xbf, 0x5d, 0xc3, 0x7c, 0x52, 0x6b, 0xb6, 0xea, + 0xa6, 0xe5, 0xbe, 0x96, 0xc1, 0x10, 0x4d, 0x4c, 0x9a, 0xb4, 0x98, 0x0c, 0x69, 0xdc, 0xee, 0xdc, 0xc7, 0xfe, 0x7f, + 0x49, 0x07, 0x05, 0x60, 0x6b, 0x8e, 0x16, 0x85, 0xb9, 0x45, 0x4d, 0xdb, 0xca, 0x36, 0x3b, 0x95, 0x5f, 0x58, 0xe1, + 0x5b, 0x35, 0x1f, 0xcb, 0xad, 0x79, 0xff, 0x27, 0x8d, 0xfe, 0x85, 0x27, 0x14, 0xd6, 0xc0, 0x20, 0x47, 0xdf, 0xc8, + 0x83, 0x30, 0xd3, 0xc1, 0xf2, 0x86, 0x8f, 0xf4, 0x34, 0x6d, 0xb7, 0x5a, 0x3f, 0x54, 0x2b, 0xd6, 0x9d, 0x5a, 0xd0, + 0xb5, 0x0b, 0x36, 0xab, 0xad, 0xe3, 0x8c, 0x96, 0xd8, 0xb6, 0x9c, 0x4b, 0xb7, 0xe4, 0x05, 0xcb, 0x4d, 0x34, 0x99, + 0xb5, 0x43, 0xb9, 0xad, 0x71, 0x72, 0x31, 0x65, 0x05, 0xd7, 0xdd, 0xfa, 0x57, 0xd5, 0xf1, 0xf6, 0xea, 0xaf, 0xad, + 0x1c, 0xba, 0xb4, 0x35, 0xdc, 0xa5, 0xe7, 0x63, 0xf8, 0xd8, 0x5e, 0xfd, 0x2f, 0xb4, 0x88, 0x37, 0x10, 0x13, 0x87, + 0x35, 0xd0, 0x3a, 0x98, 0x73, 0x01, 0x26, 0x99, 0x03, 0xfc, 0x0d, 0x28, 0x64, 0x34, 0xcf, 0x62, 0x18, 0xd1, 0x5e, + 0x73, 0xef, 0xb8, 0x60, 0x33, 0xe4, 0x01, 0x91, 0xdc, 0x3f, 0x2d, 0xd8, 0x6c, 0x9d, 0x98, 0xea, 0x4b, 0x83, 0x22, + 0x34, 0xe7, 0x13, 0x91, 0x66, 0x0c, 0xd0, 0x77, 0x9d, 0x30, 0xa1, 0xb9, 0xbe, 0x6b, 0x16, 0xf2, 0x66, 0x39, 0xe2, + 0x6a, 0x9e, 0xd3, 0xbb, 0x74, 0x9c, 0xb3, 0xdb, 0xae, 0x29, 0xd5, 0xe4, 0x9a, 0xcd, 0x94, 0x2b, 0xdb, 0x85, 0xf4, + 0xe6, 0xc8, 0x9a, 0x4d, 0x00, 0xf4, 0xe4, 0xcd, 0xe6, 0xfe, 0x49, 0x8e, 0xd5, 0x1e, 0xa3, 0x8a, 0x35, 0xe5, 0x42, + 0xef, 0xb5, 0x54, 0x77, 0xc6, 0x45, 0xd3, 0x0d, 0xe4, 0xa4, 0x35, 0xbf, 0xed, 0x6e, 0x43, 0x3e, 0xe8, 0x3f, 0x61, + 0xb7, 0x73, 0x2a, 0x46, 0x6c, 0xb4, 0x0c, 0xaa, 0x75, 0xa0, 0x5e, 0x58, 0x2a, 0x15, 0x7a, 0xda, 0x34, 0xb6, 0x5e, + 0x71, 0x47, 0xa0, 0x6f, 0xa0, 0xd6, 0x83, 0x16, 0xb6, 0xff, 0x9f, 0xb4, 0x51, 0x58, 0x79, 0x0f, 0xc2, 0x2e, 0xf1, + 0xf1, 0x5d, 0x13, 0xfe, 0x2e, 0xc1, 0xb7, 0x88, 0x67, 0x34, 0x77, 0x10, 0x99, 0xf1, 0xd1, 0x28, 0xaf, 0x8d, 0xe8, + 0x32, 0xe8, 0xac, 0x8d, 0x96, 0x30, 0xff, 0xb4, 0xb5, 0xd7, 0xda, 0x33, 0x73, 0x71, 0xdb, 0xfc, 0xe4, 0xe4, 0xfe, + 0xf1, 0x03, 0xd6, 0xcd, 0xb9, 0x60, 0xb5, 0xa9, 0x7e, 0x17, 0xd4, 0x61, 0xc3, 0x1d, 0xd7, 0x70, 0x7b, 0xaf, 0xbd, + 0x77, 0xd2, 0xfa, 0xc1, 0xef, 0xd6, 0x9c, 0x8d, 0x75, 0xda, 0x3e, 0x9b, 0xdf, 0xd6, 0xb7, 0xef, 0xb9, 0x6f, 0xfa, + 0xa6, 0xa0, 0xf3, 0x54, 0x48, 0xf8, 0xd3, 0x85, 0x4d, 0x36, 0xce, 0xe5, 0x4d, 0x3a, 0xe5, 0xa3, 0x11, 0x13, 0xb6, + 0x40, 0x99, 0xc8, 0xf2, 0x9c, 0xcf, 0x15, 0xb7, 0xab, 0xe1, 0x70, 0xf7, 0x74, 0x03, 0xaa, 0xe1, 0x80, 0x8e, 0x83, + 0x01, 0x9d, 0x56, 0x03, 0xaa, 0xfa, 0x0f, 0x47, 0xd8, 0xd9, 0x98, 0xab, 0x29, 0xd5, 0xad, 0x61, 0xd2, 0xdf, 0x0b, + 0xa5, 0x01, 0xe6, 0xde, 0x48, 0xc3, 0x50, 0xf1, 0xe6, 0x90, 0xe9, 0x1b, 0xc6, 0xc4, 0xb7, 0x07, 0x71, 0x99, 0x4a, + 0x91, 0xdf, 0xd9, 0xcf, 0x65, 0xd8, 0x25, 0x5d, 0x68, 0xb9, 0x4e, 0x86, 0x5c, 0xd0, 0xe2, 0xee, 0x5a, 0x31, 0xa1, + 0x64, 0x71, 0x2d, 0xc7, 0xe3, 0xe5, 0xb7, 0x48, 0xcb, 0x7d, 0xb4, 0x4e, 0x14, 0x17, 0x93, 0x9c, 0x59, 0xa2, 0x64, + 0x10, 0xc1, 0x11, 0x73, 0xdb, 0xae, 0x69, 0xb2, 0x36, 0xe8, 0x70, 0xe7, 0x99, 0x76, 0x07, 0x69, 0xda, 0xbc, 0x61, + 0xc3, 0xcf, 0x5c, 0x5b, 0x3c, 0x6b, 0xaa, 0x1b, 0xf0, 0x78, 0x31, 0xcb, 0x30, 0x67, 0xc5, 0xd2, 0xd3, 0xf0, 0x56, + 0x8d, 0xea, 0x5c, 0x09, 0x73, 0x7a, 0x68, 0x3a, 0x6c, 0x42, 0xfc, 0x2f, 0x56, 0x94, 0x7b, 0x8c, 0x0b, 0x83, 0x31, + 0x06, 0x40, 0x9b, 0xbb, 0x24, 0x3c, 0x03, 0x4e, 0x5a, 0x2d, 0x7f, 0x3e, 0x34, 0x6d, 0x9d, 0xb4, 0x9d, 0x9c, 0xb2, + 0xd9, 0xae, 0xfd, 0x59, 0x27, 0x46, 0xed, 0xce, 0xfc, 0x76, 0xcf, 0xfc, 0xd3, 0xda, 0x6b, 0x6d, 0x13, 0x9f, 0x6d, + 0x38, 0x1d, 0x23, 0xbf, 0xb2, 0x5a, 0xce, 0xd3, 0x36, 0x9b, 0x75, 0x17, 0x0a, 0x0e, 0x1a, 0x43, 0x1b, 0xcd, 0x01, + 0xb6, 0x36, 0x33, 0x81, 0x75, 0xa4, 0x5c, 0x00, 0x5d, 0xb7, 0x67, 0x1b, 0xf4, 0xa1, 0x24, 0x18, 0x62, 0xef, 0x6c, + 0xb4, 0x3e, 0xac, 0xd6, 0x5e, 0x35, 0x30, 0xf8, 0x67, 0xfd, 0x57, 0xc5, 0x19, 0xbe, 0x60, 0x01, 0x67, 0xce, 0x1b, + 0xc9, 0xe9, 0xaa, 0xe5, 0xb8, 0xf1, 0x91, 0xae, 0x84, 0x04, 0xe3, 0xcb, 0x30, 0xa3, 0xb7, 0xd6, 0xa9, 0x61, 0xc6, + 0x05, 0x98, 0x4c, 0x21, 0xac, 0x03, 0xe3, 0xf2, 0x69, 0xd8, 0xd0, 0x48, 0xc7, 0xd0, 0xf0, 0x61, 0x27, 0x39, 0x3d, + 0x45, 0xb8, 0x85, 0x3b, 0xa7, 0xa7, 0x81, 0x34, 0x30, 0xd6, 0xbb, 0x8a, 0xee, 0x2a, 0xa9, 0x76, 0x94, 0x3c, 0x32, + 0x8d, 0x1e, 0xb5, 0x5b, 0x2d, 0x6c, 0x1c, 0xb7, 0xcb, 0xc2, 0x5c, 0xed, 0x68, 0xb6, 0xdd, 0x6a, 0x41, 0xb3, 0xf0, + 0xc7, 0xcd, 0xeb, 0x17, 0xb2, 0x6c, 0xa5, 0x2d, 0xdc, 0x4e, 0xdb, 0xb8, 0x93, 0x76, 0xf0, 0x71, 0x7a, 0x8c, 0x4f, + 0xd2, 0x13, 0x7c, 0x9a, 0x9e, 0xe2, 0xb3, 0xf4, 0x0c, 0xdf, 0x4f, 0xef, 0xe3, 0xf3, 0xf4, 0x1c, 0x3f, 0x48, 0x1f, + 0xe0, 0x87, 0x69, 0xbb, 0x85, 0x1f, 0xa5, 0xed, 0x36, 0x7e, 0x9c, 0xb6, 0x3b, 0xf8, 0x49, 0xda, 0x3e, 0xc6, 0x4f, + 0xd3, 0xf6, 0x09, 0x7e, 0x96, 0xb6, 0x4f, 0x31, 0x85, 0xdc, 0x21, 0xe4, 0x66, 0x90, 0x3b, 0x82, 0x5c, 0x06, 0xb9, + 0xe3, 0xb4, 0x7d, 0xba, 0xc6, 0xca, 0x06, 0x7b, 0x88, 0x5a, 0xed, 0xce, 0xf1, 0xc9, 0xe9, 0xd9, 0xfd, 0xf3, 0x07, + 0x0f, 0x1f, 0x3d, 0x7e, 0xf2, 0xf4, 0x59, 0x34, 0xc0, 0x43, 0xe3, 0x73, 0xa1, 0x44, 0x9f, 0x1f, 0xb4, 0x4f, 0x07, + 0xf8, 0xda, 0x7f, 0xc6, 0xfc, 0xa0, 0x73, 0xd2, 0x42, 0x97, 0x97, 0x27, 0x83, 0x46, 0x99, 0xfb, 0xde, 0xb8, 0x7a, + 0x54, 0x59, 0x84, 0x90, 0x18, 0x72, 0x10, 0xbe, 0x33, 0xf5, 0xde, 0xb3, 0x98, 0x27, 0x05, 0x3a, 0x38, 0x30, 0x3f, + 0x26, 0xfe, 0xc7, 0xd0, 0xff, 0xa0, 0xc1, 0x22, 0xdd, 0xd2, 0xd8, 0xf9, 0xfa, 0xea, 0xd2, 0xd2, 0xbe, 0x34, 0x62, + 0xd9, 0xe3, 0xce, 0x9c, 0xfc, 0xbf, 0x22, 0x6b, 0x2e, 0x42, 0x4e, 0xac, 0x4a, 0xe6, 0xb4, 0xc7, 0xc8, 0xb2, 0x48, + 0x3b, 0xa7, 0xa7, 0x07, 0xbf, 0xf4, 0x79, 0xbf, 0x3d, 0x18, 0x1c, 0xb6, 0xef, 0xe3, 0x49, 0x99, 0xd0, 0xb1, 0x09, + 0xc3, 0x32, 0xe1, 0xd8, 0x26, 0xd0, 0xd4, 0xd6, 0x86, 0xa4, 0x13, 0x93, 0x04, 0x25, 0xd6, 0xa9, 0x69, 0xfb, 0xbe, + 0x6d, 0xfb, 0x01, 0xd8, 0x31, 0x99, 0xe6, 0x5d, 0xd3, 0x17, 0x17, 0x27, 0x2b, 0xd7, 0x28, 0x9e, 0xa4, 0xae, 0x35, + 0x9f, 0x78, 0x32, 0x18, 0xe0, 0xa1, 0x49, 0x3c, 0xad, 0x12, 0xcf, 0x06, 0x03, 0xd7, 0xd5, 0x03, 0xd3, 0xd5, 0xfd, + 0x2a, 0xeb, 0x7c, 0x30, 0x30, 0x5d, 0x22, 0xe7, 0xb5, 0xae, 0xf4, 0xde, 0x97, 0x52, 0x73, 0xc0, 0x2f, 0x3a, 0xa7, + 0xa7, 0x3d, 0xc0, 0x30, 0x63, 0x8d, 0xea, 0x61, 0x74, 0x13, 0xc0, 0xe8, 0x0e, 0x7e, 0xf7, 0x86, 0x34, 0xbd, 0xa6, + 0x25, 0x90, 0x7a, 0xd1, 0x7f, 0x45, 0x0d, 0x6d, 0x60, 0x6e, 0xfe, 0x4c, 0xec, 0x9f, 0x21, 0x6a, 0x7c, 0xa1, 0x00, + 0x6e, 0xd0, 0x85, 0x78, 0x65, 0xa6, 0xe9, 0xf1, 0x33, 0x05, 0xe7, 0x92, 0xa9, 0xca, 0x69, 0x6f, 0x35, 0xbd, 0x19, + 0xae, 0xa6, 0xea, 0x0b, 0xfa, 0x33, 0xfe, 0x53, 0x1d, 0xc6, 0xfd, 0x66, 0x23, 0x61, 0x7f, 0x8e, 0xc0, 0x8b, 0xa5, + 0x97, 0x8e, 0xd8, 0x04, 0xf5, 0xfa, 0x7f, 0x2a, 0x3c, 0x68, 0x04, 0x19, 0x3f, 0x6c, 0xa7, 0x80, 0x8f, 0xcb, 0x66, + 0x62, 0xfc, 0x03, 0xea, 0xa1, 0xde, 0x9f, 0xea, 0xf0, 0x4f, 0x74, 0xef, 0xa8, 0x9a, 0xcb, 0xef, 0xd2, 0x6d, 0xe1, + 0x2a, 0xf0, 0xcd, 0x61, 0xb9, 0x85, 0x19, 0x6e, 0x37, 0x19, 0x84, 0x09, 0x03, 0x27, 0x68, 0x12, 0xcb, 0x06, 0x3f, + 0x3a, 0x6e, 0xa1, 0x1f, 0xda, 0x1d, 0x10, 0xeb, 0x9b, 0xe2, 0x70, 0x7b, 0xd3, 0x17, 0xcd, 0x63, 0xfc, 0xa0, 0x59, + 0xe0, 0x36, 0xc2, 0xcd, 0xb6, 0xd7, 0xb7, 0xf6, 0x55, 0xdc, 0x42, 0x58, 0xc5, 0xe7, 0xf0, 0xcf, 0x09, 0x1a, 0x54, + 0x1b, 0xf2, 0x8a, 0x6e, 0xf6, 0x0e, 0x1e, 0x9b, 0x24, 0x56, 0x0d, 0x7e, 0x74, 0xd6, 0x42, 0x3f, 0x9c, 0x99, 0x8e, + 0xd8, 0xa1, 0xde, 0xd1, 0x95, 0xc4, 0x27, 0x4d, 0x09, 0x1d, 0xb5, 0xca, 0x7e, 0x44, 0x7c, 0x8a, 0xb0, 0x88, 0x8f, + 0xe1, 0x9f, 0x76, 0xd8, 0xcf, 0xaf, 0x5b, 0xfd, 0x98, 0x79, 0xb7, 0x71, 0x72, 0x6a, 0x1d, 0x40, 0x95, 0xbd, 0x8d, + 0x6d, 0xb0, 0xcb, 0xb6, 0xb9, 0x46, 0x6a, 0x1f, 0xc1, 0x07, 0xc2, 0xfa, 0x90, 0x28, 0xcc, 0x0e, 0xc1, 0x73, 0x14, + 0x0c, 0x26, 0xd4, 0xc5, 0x71, 0x57, 0x35, 0x1a, 0x48, 0xf4, 0xd5, 0xe0, 0x90, 0xb4, 0x9b, 0xba, 0xc9, 0x30, 0xfc, + 0x6e, 0x90, 0x32, 0x1c, 0x99, 0xa8, 0x7a, 0x7d, 0xec, 0x7a, 0xb5, 0x77, 0xce, 0x1e, 0x3b, 0x08, 0x21, 0xaa, 0x17, + 0xeb, 0x26, 0x43, 0x47, 0xa2, 0x11, 0xeb, 0x0b, 0xd6, 0x3b, 0x4b, 0x5b, 0xc8, 0x60, 0xa7, 0xea, 0xc5, 0xac, 0xc9, + 0x21, 0xbd, 0x93, 0xc6, 0xbc, 0xa9, 0xe1, 0xd7, 0x49, 0x30, 0x0b, 0x01, 0x78, 0x57, 0xf9, 0xc1, 0x14, 0x47, 0x9d, + 0xd3, 0x53, 0x2c, 0x08, 0x4f, 0x26, 0xe6, 0x97, 0x22, 0x3c, 0x19, 0x9a, 0x5f, 0x92, 0x94, 0xf0, 0xb2, 0xbd, 0xe3, + 0x82, 0x04, 0xab, 0x6a, 0x52, 0x28, 0x2c, 0x68, 0x81, 0x8e, 0x3a, 0xfe, 0x42, 0x1a, 0x4f, 0xfd, 0x1c, 0x40, 0x00, + 0x2f, 0x8c, 0x2d, 0xa2, 0x6c, 0x16, 0x38, 0x27, 0xf4, 0x32, 0x39, 0xed, 0x4d, 0x8f, 0xe2, 0x4e, 0x53, 0x36, 0x0b, + 0x94, 0x4e, 0x8f, 0x4c, 0x4d, 0x9c, 0x91, 0xc7, 0xd4, 0xb6, 0x86, 0xa7, 0x70, 0x8b, 0x98, 0x91, 0xec, 0xf0, 0xac, + 0xd5, 0x48, 0x4e, 0x11, 0xee, 0x67, 0xab, 0x16, 0xce, 0x57, 0xab, 0x16, 0xa6, 0xc1, 0x32, 0x3c, 0x16, 0x1e, 0x20, + 0xa5, 0x8e, 0x68, 0x33, 0x2a, 0x4c, 0x8f, 0xc7, 0x1a, 0x6e, 0xc4, 0x35, 0xf8, 0x99, 0x68, 0xf0, 0x80, 0x49, 0xb9, + 0xbb, 0x8a, 0x42, 0x26, 0x2e, 0xde, 0x38, 0xd4, 0x1a, 0xbd, 0x16, 0x7e, 0x5d, 0xbd, 0x4d, 0xa3, 0x88, 0x7f, 0x97, + 0xd8, 0xa6, 0x05, 0xc5, 0xe8, 0x76, 0xb1, 0x5f, 0xe9, 0x56, 0xb1, 0x37, 0x3b, 0x8a, 0x5d, 0x6d, 0x17, 0xfb, 0x28, + 0x03, 0x1d, 0x17, 0xff, 0xe1, 0xf8, 0xac, 0xd5, 0x38, 0x06, 0x64, 0x3d, 0x3e, 0x6b, 0x55, 0x85, 0xee, 0xd1, 0x6a, + 0xad, 0x34, 0xf9, 0x4c, 0xad, 0x95, 0x3f, 0xf7, 0xee, 0xc6, 0x66, 0xe1, 0xac, 0xb3, 0x73, 0xe9, 0xd9, 0xdc, 0x3f, + 0x05, 0x2b, 0x0a, 0x61, 0xa8, 0x9d, 0xee, 0x9f, 0x0d, 0x7a, 0x53, 0x16, 0x37, 0x20, 0x15, 0xa5, 0x63, 0xed, 0x7e, + 0xa1, 0xf2, 0x32, 0xf5, 0xa3, 0x84, 0xa4, 0xce, 0x00, 0x61, 0x49, 0x1a, 0xba, 0x7f, 0x3c, 0x30, 0xe7, 0x5d, 0x01, + 0xbf, 0x4f, 0xcc, 0xef, 0x52, 0x95, 0xe1, 0x5c, 0x01, 0xa6, 0x37, 0xc3, 0xa8, 0x27, 0xc8, 0x6b, 0x1a, 0x1b, 0xeb, + 0x6e, 0x94, 0x96, 0x19, 0xea, 0x0b, 0x64, 0xbc, 0x29, 0x33, 0x04, 0x79, 0x2d, 0xdc, 0x6f, 0xbc, 0x2c, 0x52, 0xb0, + 0xf4, 0xc0, 0x93, 0x14, 0xac, 0x3c, 0xf0, 0x30, 0x15, 0xe0, 0x89, 0x40, 0x53, 0x16, 0xd8, 0x8f, 0x3f, 0x74, 0xba, + 0x23, 0x73, 0xdf, 0x49, 0x0c, 0x96, 0x76, 0x19, 0x9c, 0x14, 0x1f, 0x65, 0x0c, 0x7f, 0x1b, 0x1a, 0x61, 0x06, 0x6d, + 0x32, 0x84, 0x79, 0x52, 0x10, 0x48, 0xc3, 0x3c, 0x99, 0x10, 0x06, 0x4d, 0xf2, 0x64, 0x48, 0x58, 0xbf, 0x13, 0xa0, + 0xc9, 0x53, 0x03, 0x3b, 0x00, 0x0e, 0xaf, 0x5f, 0x21, 0x6b, 0xdb, 0x38, 0xdc, 0x4d, 0x43, 0x13, 0x82, 0x70, 0x15, + 0xc3, 0x2c, 0x60, 0x73, 0x9a, 0x9f, 0x9d, 0x2a, 0xf0, 0x22, 0x4f, 0xa8, 0xa1, 0xde, 0x7f, 0x01, 0x59, 0x8d, 0xef, + 0x2d, 0xd9, 0x1a, 0xef, 0xdd, 0x5b, 0x8a, 0xf5, 0x0f, 0xf0, 0x47, 0xb9, 0x3f, 0xda, 0x9c, 0x7e, 0x6b, 0xf4, 0x57, + 0x0a, 0xc5, 0x76, 0x94, 0x42, 0x7f, 0x79, 0x47, 0x34, 0x45, 0x96, 0xb7, 0x69, 0x34, 0xa2, 0xc5, 0xe7, 0x08, 0x7f, + 0x4a, 0xa3, 0x1c, 0x18, 0xc1, 0x08, 0x7f, 0x4c, 0xa3, 0x82, 0x45, 0xf8, 0x8f, 0x34, 0x1a, 0xe6, 0x8b, 0x08, 0x7f, + 0x48, 0xa3, 0x49, 0x11, 0xe1, 0xf7, 0xa0, 0x26, 0x1c, 0xf1, 0xc5, 0x2c, 0xc2, 0xbf, 0xa7, 0x91, 0x32, 0x76, 0xf8, + 0xf8, 0x61, 0x1a, 0x31, 0x16, 0xe1, 0x77, 0x69, 0x24, 0xf3, 0x08, 0x5f, 0xa5, 0x91, 0x2c, 0x22, 0xfc, 0x28, 0x8d, + 0x0a, 0x1a, 0xe1, 0xc7, 0x69, 0x04, 0x85, 0x26, 0x11, 0x7e, 0x92, 0x46, 0xd0, 0xb2, 0x8a, 0xf0, 0xdb, 0x34, 0xe2, + 0x22, 0xc2, 0xbf, 0xa5, 0x91, 0x5e, 0x14, 0xff, 0x2c, 0x24, 0x57, 0x11, 0x7e, 0x9a, 0x46, 0x53, 0x1e, 0xe1, 0x37, + 0x69, 0x54, 0xc8, 0x08, 0xbf, 0x4e, 0x23, 0x9a, 0x47, 0xf8, 0x55, 0x1a, 0xe5, 0x2c, 0xc2, 0xbf, 0xa6, 0xd1, 0x88, + 0x45, 0xf8, 0x65, 0x1a, 0xdd, 0xb1, 0x3c, 0x97, 0x11, 0x7e, 0x96, 0x46, 0x4c, 0x44, 0xf8, 0x97, 0x34, 0xca, 0xa6, + 0x11, 0xfe, 0x29, 0x8d, 0x68, 0xf1, 0x59, 0x45, 0xf8, 0x79, 0x1a, 0x31, 0x1a, 0xe1, 0x17, 0xb6, 0xa3, 0x49, 0x84, + 0x7f, 0x4e, 0xa3, 0x9b, 0x69, 0xb4, 0xc6, 0x4a, 0x91, 0xe5, 0x6b, 0x9e, 0xb1, 0x3f, 0x58, 0x1a, 0x8d, 0x5b, 0xe3, + 0xf3, 0xf1, 0x38, 0xc2, 0x54, 0x68, 0xfe, 0xcf, 0x82, 0xdd, 0x3c, 0xd5, 0x90, 0x48, 0xd9, 0x70, 0x74, 0x3f, 0xc2, + 0xf4, 0x9f, 0x05, 0x4d, 0xa3, 0xf1, 0xd8, 0x14, 0xf8, 0x67, 0x41, 0x67, 0xb4, 0x78, 0xcb, 0xd2, 0xe8, 0xfe, 0x78, + 0x3c, 0x1e, 0x9d, 0x44, 0x98, 0x7e, 0x5d, 0x7c, 0x34, 0x2d, 0x98, 0x02, 0x43, 0xc6, 0x27, 0x50, 0xf7, 0x74, 0x7c, + 0x3a, 0xca, 0x22, 0x3c, 0xe4, 0xea, 0x9f, 0x05, 0x7c, 0x8f, 0xd9, 0x49, 0x76, 0x12, 0xe1, 0x61, 0x4e, 0xb3, 0xcf, + 0x69, 0xd4, 0x32, 0xbf, 0xc4, 0x2f, 0x6c, 0xf4, 0x7a, 0x26, 0x8d, 0x12, 0x7d, 0xcc, 0x86, 0xd9, 0x28, 0xc2, 0x66, + 0x30, 0x63, 0xf8, 0xfb, 0x85, 0xbf, 0x63, 0x3a, 0x8d, 0xce, 0x69, 0x67, 0xc8, 0x3a, 0x11, 0x1e, 0xbe, 0xb9, 0x11, + 0x69, 0x44, 0x4f, 0x3b, 0xb4, 0x43, 0x23, 0x3c, 0x5c, 0x14, 0xf9, 0xdd, 0x8d, 0x94, 0x23, 0x00, 0xc2, 0xf0, 0xfc, + 0xfc, 0x7e, 0x84, 0x33, 0xfa, 0xab, 0x86, 0xda, 0xa7, 0xe3, 0x07, 0x8c, 0xb6, 0x22, 0xfc, 0x0b, 0x2d, 0xf4, 0xc7, + 0x85, 0x72, 0x03, 0x6d, 0x41, 0x8a, 0xcc, 0xde, 0x81, 0x82, 0x39, 0x1a, 0x75, 0xce, 0x1e, 0xb4, 0x59, 0x84, 0xb3, + 0xab, 0xd7, 0xd0, 0xdb, 0xfd, 0xf1, 0x69, 0x0b, 0x3e, 0x04, 0x48, 0x6a, 0xac, 0x80, 0x46, 0xce, 0x4e, 0x1e, 0x9c, + 0xb2, 0x91, 0x49, 0x54, 0x3c, 0xff, 0x6c, 0x66, 0x7f, 0x0e, 0xf3, 0xc9, 0x0a, 0x3e, 0x53, 0x52, 0xa4, 0xd1, 0x28, + 0x6b, 0x9f, 0x1c, 0x43, 0xc2, 0x1d, 0x15, 0x1e, 0x38, 0xb7, 0x50, 0xf5, 0x7c, 0x18, 0xe1, 0x5b, 0x9b, 0x7a, 0x3e, + 0x34, 0x1f, 0x93, 0x77, 0xbf, 0x8a, 0x37, 0xa3, 0x34, 0x1a, 0x9e, 0x9f, 0x9f, 0xb5, 0x20, 0xe1, 0x03, 0xbd, 0x4b, + 0x23, 0xfa, 0x00, 0xfe, 0x83, 0xec, 0x8f, 0xcf, 0xa0, 0x43, 0x18, 0xe1, 0xed, 0xe4, 0x63, 0x98, 0xf3, 0x79, 0x4a, + 0x3f, 0xf3, 0x34, 0x1a, 0x8e, 0x86, 0xf7, 0xcf, 0xa0, 0xde, 0x8c, 0x4e, 0x9e, 0x69, 0x0a, 0xed, 0xb6, 0x5a, 0xa6, + 0xe5, 0x77, 0xfc, 0x0b, 0x33, 0xd5, 0x4f, 0x4f, 0xcf, 0x86, 0x1d, 0x18, 0xc1, 0x15, 0xa8, 0x18, 0x60, 0x3c, 0xe7, + 0x99, 0x69, 0xf0, 0x2a, 0x7b, 0x3a, 0x4a, 0xa3, 0x07, 0x0f, 0x8e, 0x3b, 0x59, 0x16, 0xe1, 0xdb, 0x8f, 0x23, 0x5b, + 0xdb, 0xe4, 0x29, 0x80, 0x7d, 0x1a, 0xb1, 0x07, 0x0f, 0xce, 0xee, 0x53, 0xf8, 0x7e, 0x6e, 0xda, 0x3a, 0x1f, 0x0f, + 0xb3, 0x73, 0x68, 0xeb, 0x77, 0x98, 0xce, 0xc9, 0xf9, 0xf1, 0xc8, 0xf4, 0xf5, 0xbb, 0x19, 0x75, 0x67, 0x7c, 0x32, + 0x3e, 0x31, 0x99, 0x66, 0xa8, 0xe5, 0xe7, 0x6f, 0x2c, 0x8d, 0x32, 0x36, 0x6a, 0x47, 0xf8, 0xd6, 0x2d, 0xdc, 0x83, + 0x93, 0x56, 0x6b, 0x74, 0x1c, 0xe1, 0xd1, 0xc3, 0xf9, 0xfc, 0xad, 0x81, 0x60, 0xfb, 0xe4, 0x81, 0xfd, 0x56, 0x9f, + 0xef, 0xa0, 0xe9, 0xa1, 0x01, 0xda, 0x88, 0xcf, 0x4c, 0xcb, 0x67, 0x0f, 0xe0, 0x3f, 0xf3, 0x6d, 0x9a, 0x2e, 0xbf, + 0xe5, 0x68, 0x62, 0x17, 0xa5, 0xcd, 0x1e, 0xb4, 0xa0, 0xc6, 0x98, 0x7f, 0x1c, 0x16, 0x1c, 0xd0, 0x68, 0xd8, 0x81, + 0xff, 0x8b, 0xf0, 0x38, 0xbf, 0x7a, 0xed, 0x70, 0x76, 0x3c, 0xa6, 0xe3, 0x56, 0x84, 0xc7, 0xf2, 0xa3, 0xd2, 0x1f, + 0x1e, 0x8a, 0x34, 0xea, 0x74, 0xce, 0x87, 0xa6, 0xcc, 0xe2, 0x17, 0xc5, 0x0d, 0x1e, 0xb7, 0x4c, 0x2b, 0x13, 0xfa, + 0x56, 0x0d, 0xaf, 0x24, 0xac, 0x24, 0xfc, 0x17, 0xe1, 0x09, 0xe8, 0xa5, 0x5c, 0x2b, 0xe7, 0x76, 0x3b, 0x4c, 0xde, + 0x19, 0xd4, 0x1c, 0xdd, 0x07, 0x78, 0xf9, 0x65, 0x1c, 0x51, 0x7a, 0xda, 0x69, 0x45, 0xd8, 0x8c, 0xfa, 0xbc, 0x05, + 0xff, 0x45, 0xd8, 0x42, 0xce, 0xc0, 0x75, 0xf2, 0xf1, 0xd9, 0xcb, 0x9b, 0x34, 0xa2, 0xa3, 0xf1, 0x18, 0x96, 0xc4, + 0x4c, 0xc6, 0x17, 0x9b, 0x4a, 0xc1, 0xee, 0x7e, 0xbd, 0x71, 0xdb, 0xc5, 0x24, 0x68, 0x07, 0x9d, 0xb3, 0x07, 0xc3, + 0x93, 0x08, 0xbf, 0x1d, 0x71, 0x2a, 0x60, 0x95, 0xb2, 0xd1, 0x69, 0x76, 0x9a, 0x99, 0x84, 0x89, 0x4c, 0xa3, 0x13, + 0x58, 0xf2, 0x4e, 0x84, 0xf9, 0x97, 0xab, 0x3b, 0x8b, 0x6e, 0x50, 0xdb, 0x21, 0xc8, 0xb8, 0xc5, 0xce, 0xce, 0xb3, + 0x08, 0xe7, 0xf4, 0xcb, 0xb3, 0x5f, 0x8b, 0x34, 0x62, 0x67, 0xec, 0x6c, 0x4c, 0xfd, 0xf7, 0x1f, 0x6a, 0x6a, 0x6a, + 0xb4, 0xc6, 0xa7, 0x90, 0x74, 0x23, 0xcc, 0x58, 0xef, 0x67, 0x63, 0x83, 0x21, 0xaf, 0x66, 0x52, 0x64, 0x4f, 0xc7, + 0x63, 0x69, 0xb1, 0x98, 0xc2, 0x26, 0xfc, 0x04, 0xd0, 0xa6, 0xa3, 0xd1, 0x39, 0x3b, 0x8b, 0xf0, 0x27, 0xbb, 0x4b, + 0xdc, 0x04, 0x3e, 0x59, 0xcc, 0x66, 0x6e, 0xb7, 0x7f, 0xb2, 0x40, 0x81, 0xf9, 0x8e, 0xe9, 0x98, 0x8e, 0x3a, 0x11, + 0xfe, 0x64, 0xe0, 0x32, 0x3a, 0x86, 0xff, 0xa0, 0x00, 0x74, 0xf6, 0xa0, 0xc5, 0xd8, 0x83, 0x96, 0xf9, 0x0a, 0xf3, + 0xdc, 0xcc, 0x87, 0x67, 0x59, 0x3b, 0xc2, 0x9f, 0x1c, 0x3a, 0x8e, 0xc7, 0xb4, 0x05, 0xe8, 0xf8, 0xc9, 0xa1, 0x63, + 0xa7, 0x35, 0xec, 0x50, 0xf3, 0x6d, 0xb1, 0xe6, 0xfc, 0x7e, 0xc6, 0x60, 0x72, 0x9f, 0x2c, 0x42, 0xde, 0xbf, 0x7f, + 0x7e, 0xfe, 0xe0, 0x01, 0x7c, 0x9a, 0xb6, 0xcb, 0x4f, 0xa5, 0x1f, 0xe6, 0x06, 0xc9, 0x5a, 0xd9, 0x09, 0xd0, 0xc9, + 0x4f, 0x66, 0x8c, 0xe3, 0xf1, 0x98, 0xb5, 0x22, 0x9c, 0xf3, 0x19, 0xb3, 0x98, 0x60, 0x7f, 0x9b, 0x8e, 0x8e, 0x3b, + 0xd9, 0xe8, 0xb8, 0x13, 0xe1, 0xfc, 0xed, 0x33, 0x33, 0x9b, 0x16, 0xcc, 0xde, 0x6f, 0x39, 0x8f, 0x35, 0x33, 0xfa, + 0x06, 0x06, 0x09, 0x2b, 0x0d, 0x95, 0xdf, 0x07, 0xf4, 0xf0, 0xec, 0x2c, 0x1b, 0xc1, 0x40, 0xdf, 0x43, 0xb7, 0x00, + 0xc6, 0xf7, 0x76, 0xf3, 0x0d, 0xe9, 0xe9, 0x29, 0x4c, 0xf7, 0xfd, 0x7c, 0x51, 0xcc, 0x5f, 0xa5, 0xd1, 0x83, 0xe3, + 0xfb, 0xad, 0xd1, 0x30, 0xc2, 0xef, 0xdd, 0x04, 0x8f, 0xb3, 0xe1, 0xf1, 0xfd, 0x76, 0x84, 0xdf, 0x9b, 0xfd, 0x76, + 0x7f, 0x78, 0x76, 0x0e, 0xe7, 0xc6, 0x7b, 0x35, 0x2f, 0xde, 0x4e, 0x4c, 0x81, 0x31, 0x7d, 0x00, 0xcd, 0xfe, 0x66, + 0x76, 0xe3, 0xa8, 0x0d, 0x1b, 0xf9, 0xbd, 0xd9, 0x64, 0x06, 0x4f, 0xee, 0xb7, 0x4f, 0xcf, 0x4f, 0x23, 0x3c, 0xe3, + 0x23, 0x01, 0x04, 0xde, 0x6c, 0x94, 0x07, 0xed, 0x07, 0xf7, 0x5b, 0x11, 0x9e, 0xbd, 0xd5, 0xd9, 0x47, 0x3a, 0x33, + 0xd4, 0x78, 0x0c, 0x30, 0x9b, 0x71, 0xa5, 0xef, 0xde, 0x28, 0x47, 0x8f, 0x59, 0x3b, 0xc2, 0x33, 0x99, 0x65, 0x54, + 0xbd, 0xb5, 0x09, 0xc3, 0xd3, 0x08, 0x0b, 0xfa, 0x85, 0xfe, 0x2d, 0xfd, 0x66, 0x1a, 0x31, 0x3a, 0x32, 0x69, 0x06, + 0x87, 0x23, 0xfc, 0x6e, 0x04, 0xd7, 0x60, 0x69, 0x34, 0x1e, 0x8d, 0x4f, 0x01, 0x3c, 0x40, 0x80, 0x2c, 0x76, 0x03, + 0x34, 0xe0, 0x6b, 0xf4, 0x68, 0x98, 0x46, 0x67, 0xc3, 0x73, 0xd6, 0x39, 0x8e, 0x70, 0x49, 0x8d, 0xe8, 0x29, 0xe4, + 0x9b, 0xcf, 0x8f, 0x66, 0x4b, 0x9d, 0xd8, 0x04, 0x03, 0xa0, 0x11, 0xbd, 0xdf, 0x1a, 0x9d, 0x45, 0x78, 0xfe, 0x9a, + 0xf9, 0x3d, 0xc6, 0x18, 0x3b, 0x07, 0x58, 0x42, 0x92, 0x41, 0xa0, 0xf3, 0xf1, 0xf0, 0xc1, 0xb9, 0xf9, 0x06, 0x30, + 0xd0, 0x31, 0x63, 0x00, 0xa4, 0xf9, 0x6b, 0x56, 0x02, 0x62, 0x34, 0xbc, 0xdf, 0x02, 0xfa, 0x32, 0xa7, 0x73, 0x7a, + 0x47, 0x6f, 0x9e, 0xce, 0xcd, 0x9c, 0xc6, 0xa3, 0xd3, 0x08, 0xcf, 0x9f, 0xff, 0x32, 0x5f, 0x8c, 0xc7, 0x66, 0x42, + 0x74, 0xf8, 0x20, 0xc2, 0x73, 0x56, 0x2c, 0x60, 0x8d, 0xce, 0x4f, 0x8f, 0xc7, 0x11, 0x76, 0x68, 0x98, 0xb5, 0xb2, + 0x21, 0xdc, 0xf3, 0x2d, 0x66, 0x69, 0x34, 0x1a, 0xd1, 0xd6, 0x08, 0x6e, 0xfd, 0xe4, 0xcd, 0xaf, 0x85, 0x45, 0x23, + 0x66, 0xf0, 0xc1, 0xad, 0x21, 0xcc, 0x17, 0xe0, 0xf1, 0x71, 0xc8, 0xb2, 0x8c, 0xba, 0xc4, 0xb3, 0xb3, 0xe3, 0x63, + 0xc0, 0x3d, 0x3b, 0x43, 0x8b, 0x20, 0x6f, 0xd4, 0xdd, 0xb0, 0x90, 0x70, 0x74, 0x01, 0x51, 0x05, 0xb2, 0xfa, 0xe6, + 0xee, 0xb5, 0xa1, 0xab, 0xed, 0xb3, 0x07, 0xb0, 0x00, 0x8a, 0x8e, 0x46, 0xaf, 0xec, 0xe1, 0x76, 0x3e, 0x3c, 0x39, + 0x6d, 0x1f, 0x47, 0xd8, 0x6f, 0x04, 0x7a, 0xde, 0xba, 0xdf, 0x81, 0x12, 0x62, 0x74, 0x67, 0x4b, 0x8c, 0x4f, 0xe8, + 0xc9, 0x59, 0x2b, 0xc2, 0x7e, 0x6b, 0xb0, 0xf3, 0xe1, 0xe9, 0x7d, 0xf8, 0x54, 0x53, 0x96, 0xe7, 0x06, 0xbf, 0x4f, + 0x01, 0x2e, 0x8a, 0x3f, 0x13, 0x34, 0x8d, 0x68, 0xeb, 0xb4, 0xd3, 0x19, 0xc1, 0x67, 0xfe, 0x85, 0x15, 0x69, 0x94, + 0xb5, 0xe0, 0xbf, 0x08, 0x07, 0x3b, 0x89, 0x0d, 0x23, 0x6c, 0xf0, 0xee, 0x8c, 0x9e, 0x9a, 0xbd, 0xef, 0x76, 0x55, + 0xeb, 0xbc, 0x05, 0x1b, 0xd6, 0x6d, 0x2a, 0xf7, 0xa5, 0x84, 0xbc, 0x71, 0x24, 0x96, 0x46, 0x38, 0x40, 0xd0, 0xf1, + 0xfd, 0x71, 0x84, 0xfd, 0x8e, 0x3b, 0x39, 0x3b, 0xef, 0x00, 0x29, 0xd3, 0x40, 0x28, 0x46, 0x9d, 0xe1, 0x09, 0x90, + 0x26, 0xcd, 0x5e, 0x5b, 0x3c, 0x89, 0xb0, 0x7e, 0xaa, 0xf4, 0xab, 0x34, 0x1a, 0x9d, 0x0f, 0xc7, 0xa3, 0xf3, 0x08, + 0x6b, 0x39, 0xa3, 0x5a, 0x1a, 0x0a, 0x78, 0x7c, 0x72, 0x3f, 0xc2, 0x06, 0xcd, 0x5b, 0xac, 0x35, 0x6a, 0x45, 0xd8, + 0x1d, 0x25, 0x8c, 0x9d, 0x77, 0x60, 0x5a, 0x3f, 0x3f, 0xd7, 0x80, 0xcb, 0x23, 0x36, 0x3c, 0x8e, 0x70, 0x49, 0xef, + 0x0d, 0x21, 0x82, 0x2f, 0x35, 0x93, 0x9f, 0x1d, 0xeb, 0x01, 0xa4, 0xce, 0x6f, 0x78, 0x58, 0x86, 0x97, 0x37, 0x16, + 0x8d, 0xa8, 0xd9, 0xe2, 0xc1, 0x3d, 0xe8, 0x13, 0x1a, 0x7b, 0xb6, 0x9d, 0x93, 0xe5, 0x1a, 0x97, 0xe1, 0x45, 0x3f, + 0xb3, 0x3b, 0x15, 0x2b, 0x65, 0x38, 0xd9, 0x20, 0x05, 0x5c, 0x00, 0x9c, 0x41, 0xbd, 0xf3, 0x99, 0x04, 0x41, 0x52, + 0x90, 0x56, 0x57, 0x5c, 0x78, 0x3f, 0xce, 0xae, 0x80, 0xa0, 0x03, 0x90, 0x5e, 0x10, 0x4a, 0x34, 0xc4, 0x66, 0xb1, + 0xc2, 0xa4, 0x37, 0x6f, 0x37, 0x32, 0xa5, 0xb4, 0x06, 0xf3, 0x94, 0x50, 0x1f, 0x95, 0x1d, 0x2e, 0x69, 0x21, 0x6e, + 0x11, 0xea, 0x4a, 0x62, 0x62, 0x2c, 0xbf, 0x10, 0x3a, 0x56, 0xaa, 0x5f, 0x0c, 0x70, 0xfb, 0x0c, 0x61, 0x88, 0x5e, + 0x40, 0xfa, 0xf2, 0xf2, 0xb2, 0x7d, 0x76, 0x60, 0x84, 0xbe, 0xcb, 0xcb, 0x73, 0xfb, 0x03, 0xfe, 0x1d, 0x54, 0x11, + 0xa3, 0x61, 0x7c, 0x8f, 0x58, 0xa0, 0xd1, 0x33, 0xfc, 0xf5, 0x23, 0xb6, 0x5a, 0xc5, 0x8f, 0x18, 0x81, 0x19, 0xe3, + 0x47, 0x2c, 0x31, 0xb7, 0x06, 0xd6, 0x37, 0x85, 0xf4, 0x41, 0x73, 0xd6, 0xc2, 0x10, 0xc7, 0xdc, 0x73, 0xde, 0x8f, + 0x58, 0x9f, 0xd7, 0xfd, 0x9a, 0xab, 0xe0, 0xc1, 0x07, 0x07, 0xcb, 0x22, 0xd5, 0x56, 0x4c, 0xd0, 0x56, 0x4c, 0xd0, + 0x56, 0x4c, 0xd0, 0x55, 0xf8, 0xf6, 0x93, 0x1e, 0x48, 0x29, 0x46, 0xd9, 0xe2, 0x78, 0xea, 0x77, 0xa0, 0xf6, 0x00, + 0xed, 0x64, 0xaf, 0x52, 0x76, 0x94, 0xba, 0x8a, 0x9d, 0x0a, 0x8c, 0x9d, 0x89, 0x4e, 0xdb, 0x71, 0xf4, 0xef, 0xa8, + 0x3b, 0x5e, 0xd6, 0xc4, 0xb2, 0x77, 0x3b, 0xc5, 0x32, 0x58, 0x49, 0x23, 0x9a, 0xed, 0xdb, 0x48, 0x18, 0xba, 0x7f, + 0xdf, 0x08, 0x66, 0x55, 0x78, 0xb6, 0x06, 0x24, 0x75, 0x41, 0x0a, 0x39, 0x37, 0x52, 0x5a, 0x81, 0xd2, 0x91, 0x8e, + 0x0b, 0xd0, 0x50, 0x7a, 0x05, 0x65, 0x19, 0x45, 0xb4, 0x61, 0x00, 0xa2, 0xac, 0x8c, 0x66, 0x65, 0xb5, 0x53, 0x10, + 0x5d, 0x40, 0x13, 0x66, 0x24, 0x16, 0x68, 0x40, 0x98, 0x06, 0x84, 0xab, 0x0c, 0xe2, 0x8c, 0xcb, 0x3e, 0x31, 0xd9, + 0xca, 0x64, 0xab, 0x32, 0x5b, 0xfa, 0x6c, 0x2b, 0x24, 0x4a, 0x93, 0x2d, 0xcb, 0x6c, 0x90, 0xd9, 0xf0, 0x24, 0x55, + 0x78, 0x98, 0x4a, 0x2b, 0xaa, 0x55, 0xb2, 0xd5, 0x5b, 0x1a, 0x6a, 0x73, 0x0f, 0x0e, 0xe2, 0x52, 0x4e, 0x32, 0x6a, + 0xe2, 0x7b, 0x4b, 0x9e, 0x14, 0x46, 0x06, 0xe2, 0xc9, 0xc4, 0xfd, 0x1d, 0xae, 0x37, 0x65, 0xa5, 0x62, 0x32, 0xfc, + 0x46, 0x49, 0xf4, 0x97, 0x57, 0xa2, 0x3e, 0xe2, 0x26, 0xfe, 0xcc, 0x05, 0x49, 0x5a, 0xad, 0xe3, 0xf6, 0x71, 0xeb, + 0xbc, 0xc7, 0x0f, 0xdb, 0x9d, 0xe4, 0x41, 0x27, 0x35, 0x8a, 0x88, 0xb9, 0xbc, 0x01, 0x05, 0xcc, 0x51, 0x27, 0x39, + 0x41, 0x87, 0xed, 0xa4, 0x75, 0x7a, 0xda, 0x84, 0x7f, 0xf0, 0x7b, 0x5d, 0x56, 0x3b, 0x69, 0x9d, 0x9c, 0xf6, 0xf8, + 0xd1, 0x46, 0xa5, 0x98, 0x37, 0xa0, 0x20, 0x3a, 0x32, 0x95, 0x30, 0xd4, 0xaf, 0x96, 0xf7, 0xd9, 0x96, 0x9e, 0xe7, + 0xbd, 0x8e, 0x95, 0x55, 0xc5, 0x01, 0x54, 0xfd, 0xd7, 0xc4, 0x00, 0xd1, 0x7f, 0x0d, 0xcb, 0x18, 0xb1, 0xcb, 0x02, + 0x44, 0xed, 0x47, 0x3c, 0x16, 0x0d, 0x76, 0x18, 0xdb, 0x7c, 0x0d, 0x75, 0x9b, 0x10, 0xb7, 0x0d, 0x4f, 0x5c, 0xae, + 0x0a, 0x73, 0x27, 0x08, 0x35, 0x15, 0xe4, 0x0e, 0x5d, 0xae, 0x0c, 0x73, 0x87, 0x08, 0x35, 0x25, 0xe4, 0xd2, 0x94, + 0x27, 0x14, 0x72, 0x74, 0x42, 0x9b, 0x06, 0x92, 0xd5, 0xa2, 0x3c, 0x67, 0x7e, 0xd8, 0x7c, 0x0c, 0xcb, 0x63, 0x08, + 0x8a, 0x13, 0xa4, 0x05, 0xbc, 0xed, 0x51, 0x6a, 0x73, 0x5a, 0xb8, 0x54, 0xe3, 0x40, 0x46, 0x03, 0xfe, 0x39, 0x64, + 0xe6, 0xc1, 0x87, 0x56, 0xef, 0xf8, 0xac, 0x95, 0xb6, 0xc1, 0x49, 0x19, 0x64, 0x6d, 0x61, 0x65, 0x6d, 0xe1, 0x65, + 0x6d, 0xe1, 0x65, 0x6d, 0x10, 0xe0, 0x83, 0xbe, 0xff, 0x91, 0x35, 0xc3, 0x0f, 0x5e, 0x5a, 0x91, 0x58, 0x33, 0x81, + 0x58, 0xaf, 0x56, 0xcb, 0x35, 0xd8, 0xf8, 0x94, 0x35, 0xa4, 0xaa, 0xd4, 0x9f, 0xcb, 0x22, 0x6d, 0xe1, 0x49, 0x0a, + 0x5a, 0xee, 0x16, 0xa6, 0x66, 0x73, 0x7b, 0xaa, 0xb0, 0x19, 0x3f, 0xa6, 0xe7, 0xd5, 0xc9, 0x97, 0xe4, 0xd8, 0x68, + 0x8f, 0x97, 0x45, 0xca, 0x2d, 0xcd, 0xe0, 0x96, 0x66, 0x70, 0x4b, 0x33, 0xa0, 0x11, 0x5c, 0x16, 0x36, 0x65, 0x13, + 0x4a, 0xe0, 0x4a, 0xa0, 0x7f, 0x3c, 0x80, 0xf0, 0x79, 0xb1, 0x26, 0x66, 0xd4, 0x1b, 0x9d, 0xb7, 0x21, 0x5c, 0x98, + 0x2d, 0xa9, 0x13, 0x6a, 0xbc, 0xa6, 0xcb, 0x31, 0x7f, 0xad, 0xa1, 0x7d, 0x02, 0x6f, 0xb9, 0x3c, 0xd4, 0x71, 0x0b, + 0x8c, 0x26, 0xa2, 0x22, 0xea, 0x19, 0xb2, 0x90, 0x1a, 0x9d, 0x8d, 0x33, 0x86, 0xfe, 0xbc, 0xe1, 0x83, 0x6a, 0x29, + 0x41, 0xf8, 0x82, 0xc1, 0x67, 0x56, 0x39, 0xc5, 0x97, 0xb6, 0x9e, 0xce, 0x50, 0xcb, 0x1e, 0x09, 0x5d, 0x30, 0xd8, + 0xf6, 0xd1, 0x96, 0x7a, 0x82, 0x48, 0x65, 0xdc, 0x05, 0x49, 0x15, 0x2f, 0x18, 0xdc, 0x67, 0xc9, 0x2d, 0x35, 0xce, + 0x24, 0x2f, 0xec, 0x9f, 0xaf, 0x34, 0xf0, 0xb6, 0x2b, 0x26, 0x43, 0xef, 0xa4, 0x7a, 0x6d, 0xa2, 0xea, 0x90, 0xfd, + 0x7d, 0x6b, 0x4b, 0x6d, 0xbe, 0x36, 0x8d, 0xa9, 0x4d, 0xa2, 0xc9, 0x86, 0x1d, 0xea, 0xd7, 0xe8, 0x1f, 0xef, 0x2b, + 0x56, 0x4c, 0x86, 0x28, 0xa0, 0xd9, 0x06, 0xac, 0xaa, 0x02, 0x96, 0x72, 0xf5, 0x4a, 0x17, 0x42, 0xe8, 0xdd, 0x8c, + 0x79, 0x5d, 0x4c, 0x86, 0x3b, 0x1f, 0xfd, 0xb0, 0x3d, 0xf6, 0xde, 0xd2, 0xa0, 0x07, 0xaf, 0xda, 0x9e, 0xb2, 0xdb, + 0xef, 0xd5, 0xb9, 0xd9, 0x59, 0x47, 0xe5, 0xdf, 0xab, 0xf3, 0x74, 0x57, 0x9d, 0x19, 0xbf, 0x8d, 0xfd, 0xde, 0xd1, + 0x81, 0x1a, 0xdb, 0x18, 0xe8, 0x4c, 0x86, 0x10, 0xa5, 0x1d, 0xfe, 0xda, 0x58, 0x2a, 0x5d, 0x4f, 0xc2, 0x61, 0x15, + 0x64, 0x2f, 0x39, 0x4d, 0x19, 0xa6, 0xa4, 0x73, 0x58, 0x98, 0x68, 0x2a, 0x22, 0xa1, 0x4d, 0x95, 0x50, 0x9c, 0x93, + 0x38, 0xa6, 0x87, 0x19, 0xc4, 0x84, 0x69, 0xf7, 0x68, 0x1a, 0xd3, 0x46, 0x86, 0x8e, 0xe2, 0x76, 0x83, 0x1e, 0x66, + 0x08, 0x35, 0xda, 0xa0, 0x33, 0x95, 0xa4, 0xdd, 0xcc, 0x21, 0x4a, 0xa4, 0x21, 0xc5, 0xf9, 0xa1, 0x48, 0x8a, 0x86, + 0x3c, 0x54, 0x49, 0xd1, 0x48, 0x4e, 0xb1, 0x48, 0x26, 0x65, 0xf2, 0xc4, 0x24, 0x4f, 0x6c, 0xf2, 0xb0, 0x4c, 0x1e, + 0x9a, 0xe4, 0xa1, 0x4d, 0xa6, 0xa4, 0x38, 0x14, 0x09, 0x6d, 0xc4, 0xed, 0x66, 0x81, 0x0e, 0x61, 0x04, 0x7e, 0xf4, + 0x44, 0x84, 0xc1, 0xb9, 0xd7, 0xc6, 0xba, 0x65, 0x2e, 0x73, 0x17, 0x2e, 0xb3, 0x02, 0x52, 0xe9, 0x72, 0x04, 0x75, + 0x9e, 0x05, 0x60, 0xc2, 0xda, 0xfe, 0xf1, 0xc1, 0xe0, 0xd6, 0x59, 0x2e, 0x45, 0xe0, 0x52, 0x05, 0x56, 0xe0, 0x9f, + 0x9d, 0x23, 0x09, 0x40, 0x75, 0x4d, 0xf3, 0xf9, 0x94, 0x6e, 0xf9, 0xad, 0x16, 0x93, 0xa1, 0xdb, 0x59, 0x65, 0x33, + 0x8c, 0x16, 0x36, 0xc8, 0x72, 0xdd, 0xc3, 0x10, 0x40, 0xed, 0xbd, 0x1a, 0x13, 0x6a, 0x94, 0xe4, 0xb6, 0xc6, 0xa4, + 0x60, 0x77, 0x2a, 0xa3, 0x39, 0x8b, 0xab, 0x03, 0xb8, 0x1a, 0x26, 0x23, 0x2f, 0xc0, 0x16, 0xbd, 0x38, 0x4c, 0x8e, + 0x1b, 0x3a, 0x99, 0x1c, 0x26, 0xa7, 0x0f, 0x1a, 0x3a, 0x19, 0x1e, 0x26, 0xed, 0x76, 0x85, 0xb3, 0x49, 0x41, 0x74, + 0x32, 0x21, 0x1a, 0x34, 0x86, 0xb6, 0x51, 0x39, 0xa7, 0x60, 0x5c, 0xf5, 0x6f, 0x0c, 0xa3, 0xe1, 0x86, 0x21, 0xd8, + 0xc4, 0xc6, 0x9b, 0xdc, 0x1a, 0x43, 0xd8, 0x4d, 0xe7, 0xf4, 0xb4, 0xa9, 0x93, 0x02, 0x6b, 0xbb, 0x92, 0x4d, 0x9d, + 0x4c, 0xb0, 0xb6, 0xcb, 0xd7, 0xd4, 0xc9, 0xd0, 0x36, 0x65, 0x74, 0x80, 0x4c, 0x04, 0xc0, 0x7a, 0xce, 0x02, 0xc8, + 0x77, 0xbc, 0x7b, 0xc8, 0x1a, 0xb4, 0x86, 0xdf, 0x2b, 0xd7, 0xf4, 0x05, 0x15, 0xd5, 0x60, 0x64, 0xc3, 0xbe, 0x55, + 0xb4, 0x5d, 0x35, 0xc9, 0xfe, 0x75, 0xd9, 0xb2, 0xd9, 0x42, 0xea, 0x7a, 0xc1, 0x87, 0x35, 0x0c, 0x71, 0xa5, 0xdc, + 0xc1, 0xfd, 0x8a, 0x92, 0x18, 0xa2, 0xca, 0x99, 0x53, 0x88, 0x13, 0xaf, 0x47, 0x86, 0x24, 0xde, 0x68, 0xac, 0x51, + 0x1c, 0x9c, 0xb7, 0x4f, 0x43, 0xaa, 0xba, 0x15, 0x6a, 0x8e, 0x90, 0x68, 0x21, 0xac, 0x31, 0xe2, 0x28, 0x0a, 0x58, + 0x10, 0xa7, 0xdd, 0xad, 0x1d, 0x10, 0x07, 0x07, 0x9b, 0xe7, 0x85, 0x0f, 0xfa, 0xbf, 0x15, 0xe8, 0xbf, 0xb2, 0x64, + 0xf3, 0x4f, 0x11, 0x59, 0x1b, 0x57, 0x1e, 0x20, 0x8a, 0x0f, 0xfa, 0x74, 0xdf, 0x50, 0xf8, 0x7e, 0x15, 0xf1, 0xce, + 0xe5, 0x34, 0xcf, 0x4c, 0x86, 0xe9, 0x6b, 0x10, 0x8c, 0xed, 0x4d, 0x38, 0xa1, 0xd2, 0x4a, 0xef, 0x5f, 0x76, 0x1c, + 0x74, 0xe2, 0x9e, 0x4a, 0x09, 0x1b, 0xfd, 0x3b, 0xb4, 0x89, 0xad, 0x60, 0xe3, 0xbc, 0xa1, 0x57, 0xab, 0xda, 0xc3, + 0x38, 0xf6, 0xf9, 0x15, 0x74, 0x70, 0xc0, 0xd5, 0x33, 0x30, 0xe3, 0x65, 0x71, 0x23, 0x3c, 0x7c, 0xff, 0xa9, 0x9d, + 0xd6, 0x7f, 0x9b, 0x73, 0x35, 0x0d, 0x0e, 0xba, 0x87, 0xb5, 0xfc, 0x9d, 0x2b, 0xd1, 0xd3, 0x29, 0x77, 0x6b, 0xfd, + 0x77, 0x65, 0x24, 0xbd, 0xf5, 0x44, 0xd3, 0xc1, 0x01, 0xaf, 0x02, 0x25, 0x45, 0x3f, 0x44, 0xa8, 0x67, 0x64, 0x90, + 0x67, 0xb9, 0xa4, 0x70, 0x23, 0x0a, 0x57, 0x0c, 0x69, 0x83, 0x1f, 0x69, 0xfc, 0x87, 0xfc, 0xff, 0xd4, 0xc8, 0xa1, + 0x4e, 0x1b, 0x3c, 0x10, 0xc0, 0x42, 0x56, 0xa8, 0x0a, 0x51, 0x68, 0x20, 0x1d, 0xda, 0x3c, 0xa3, 0xf2, 0x30, 0xa7, + 0xf3, 0x79, 0x7e, 0x67, 0x5e, 0xa9, 0x0a, 0x38, 0xaa, 0xea, 0xa2, 0xc9, 0xc5, 0x87, 0xc3, 0x05, 0xf0, 0xf4, 0x80, + 0x7b, 0xc8, 0xf8, 0x77, 0x96, 0x97, 0xdb, 0x02, 0x81, 0x64, 0xa6, 0x88, 0x6c, 0xb6, 0xbb, 0xea, 0x12, 0xe4, 0xb2, + 0x66, 0x13, 0x69, 0x17, 0x36, 0x1b, 0x73, 0x90, 0xc9, 0x94, 0xf5, 0xe1, 0xdc, 0xb3, 0x05, 0x41, 0x72, 0x93, 0x46, + 0x64, 0xdb, 0x5d, 0x8a, 0x8f, 0x63, 0x40, 0x23, 0x64, 0x05, 0xbe, 0x50, 0x58, 0xe4, 0xc0, 0x75, 0x16, 0xbe, 0xe3, + 0x6f, 0xb4, 0x54, 0xf4, 0xd5, 0x60, 0x80, 0x0b, 0xf3, 0x30, 0x43, 0x39, 0x9f, 0x42, 0x05, 0x0f, 0xfd, 0x04, 0x22, + 0x0a, 0x5f, 0xad, 0xf6, 0xe1, 0x1d, 0x1d, 0xd7, 0x26, 0x38, 0x7d, 0xba, 0x9f, 0xd5, 0x9b, 0x19, 0x30, 0x0e, 0x46, + 0x5a, 0xe6, 0xa2, 0xd0, 0xc9, 0x9b, 0xec, 0x42, 0x74, 0x1b, 0x0d, 0x66, 0x42, 0x1c, 0x11, 0x88, 0x67, 0x06, 0x1e, + 0x79, 0xf0, 0xc7, 0x46, 0x2d, 0x52, 0xcc, 0xc6, 0x7e, 0x83, 0xa0, 0xd4, 0xb5, 0x84, 0xd5, 0x4a, 0xd9, 0xd8, 0x22, + 0x26, 0xc7, 0x46, 0x19, 0x29, 0xfb, 0x29, 0x83, 0x98, 0x56, 0x66, 0x1c, 0xdc, 0x6d, 0xf5, 0xb7, 0xd5, 0x7e, 0xde, + 0xe3, 0xf6, 0x1a, 0x8f, 0x1b, 0x8f, 0x7d, 0x03, 0xa8, 0xe5, 0xc6, 0x06, 0xb7, 0x16, 0xe6, 0xb1, 0x35, 0x87, 0x65, + 0x9b, 0x10, 0x14, 0xa5, 0x87, 0xba, 0xbd, 0xb9, 0xf5, 0x11, 0xfb, 0x94, 0x99, 0x93, 0x42, 0xba, 0x0f, 0x72, 0xf4, + 0x80, 0x40, 0xe7, 0xf6, 0x67, 0x45, 0x17, 0x2a, 0x99, 0xb8, 0x1c, 0xe3, 0x2f, 0xc1, 0x6d, 0x5e, 0x3f, 0xba, 0xbe, + 0x36, 0x9b, 0xfc, 0xfa, 0x3a, 0xc2, 0xa1, 0x59, 0x77, 0x14, 0xf0, 0x82, 0xd1, 0xa0, 0x0c, 0xea, 0x64, 0x36, 0x7e, + 0xb3, 0x5d, 0x35, 0xf6, 0x9e, 0x56, 0x78, 0x07, 0xcb, 0x63, 0x1a, 0xdf, 0x72, 0x83, 0xec, 0x73, 0x80, 0x37, 0xeb, + 0xf3, 0x41, 0xf7, 0x4d, 0xac, 0xd0, 0xc1, 0xc1, 0x9b, 0x58, 0xa2, 0xde, 0x15, 0x33, 0x77, 0x6e, 0xe0, 0x07, 0xdd, + 0xe7, 0x66, 0xf8, 0x32, 0x40, 0x80, 0x2b, 0xb6, 0x29, 0xd9, 0xbc, 0x35, 0x51, 0x27, 0x52, 0x88, 0x6a, 0x0d, 0xb1, + 0x75, 0x1d, 0x48, 0xa0, 0xd7, 0x37, 0x21, 0xb4, 0xbb, 0x8c, 0x30, 0x60, 0xe1, 0x4b, 0x2f, 0x35, 0x96, 0xcc, 0x58, + 0x31, 0x61, 0xc5, 0x6a, 0xf5, 0x9e, 0x5a, 0xcf, 0xb3, 0x8d, 0x20, 0x89, 0xaa, 0xdb, 0x68, 0x50, 0x33, 0x7e, 0x10, + 0x1f, 0xe8, 0x00, 0xef, 0xbf, 0x89, 0x0b, 0x84, 0xc0, 0xc2, 0x88, 0x8b, 0x85, 0xf7, 0xb2, 0xca, 0x6a, 0xeb, 0x52, + 0xa0, 0xb2, 0x91, 0x9c, 0xb4, 0xf0, 0x94, 0x64, 0xe5, 0x1a, 0x5d, 0x4c, 0xbb, 0x8d, 0x46, 0x8e, 0x64, 0x9c, 0xf5, + 0xf3, 0x01, 0xe6, 0xb8, 0x80, 0xcb, 0xd4, 0xed, 0x75, 0x98, 0xb3, 0x1a, 0xe5, 0x72, 0xf3, 0x5d, 0xda, 0xb1, 0xa6, + 0x8f, 0xe8, 0x3a, 0x00, 0xc6, 0x23, 0x1a, 0x10, 0x89, 0x5d, 0x40, 0x16, 0x16, 0xc8, 0xca, 0x03, 0x59, 0x18, 0x20, + 0x2b, 0xd4, 0x9b, 0x43, 0xb8, 0x20, 0x85, 0xd2, 0x2d, 0x8a, 0x5e, 0x0f, 0x6c, 0xe9, 0x9c, 0x26, 0x30, 0x37, 0xb1, + 0x15, 0xdc, 0x72, 0x80, 0x03, 0x85, 0xf3, 0xc3, 0x53, 0x64, 0x19, 0x45, 0x26, 0xc6, 0x2b, 0xbe, 0x35, 0x7f, 0x92, + 0x5b, 0x7c, 0x67, 0x7f, 0xdc, 0x05, 0xca, 0xa4, 0xe7, 0x35, 0x6d, 0x03, 0x77, 0x11, 0xd1, 0xa2, 0x24, 0x02, 0xb4, + 0x76, 0xe1, 0xfd, 0x44, 0xfd, 0xc5, 0x33, 0x65, 0x03, 0x31, 0x88, 0x06, 0x51, 0x58, 0x04, 0xa4, 0xf3, 0xcf, 0x3f, + 0x23, 0xd4, 0x13, 0x10, 0x47, 0xc7, 0x9d, 0x6c, 0xcd, 0x36, 0x6a, 0x44, 0x49, 0x94, 0xc6, 0x3e, 0x4c, 0x03, 0xec, + 0x8c, 0x28, 0x0a, 0x5e, 0x3b, 0x29, 0x87, 0xf1, 0xa1, 0x36, 0x0c, 0x33, 0xa8, 0x2a, 0xf0, 0xc4, 0xe5, 0x72, 0x33, + 0xcc, 0x8f, 0x81, 0xaa, 0x30, 0x31, 0x56, 0x90, 0x7d, 0x02, 0x8c, 0x11, 0x76, 0x70, 0xc0, 0xfa, 0x62, 0x10, 0xbc, + 0xe9, 0x55, 0x5d, 0x87, 0xeb, 0x70, 0xe1, 0x62, 0x0a, 0x71, 0xd6, 0x57, 0x2b, 0xfb, 0x97, 0x7c, 0x30, 0xd2, 0x0c, + 0x3c, 0xce, 0x16, 0x9c, 0xb1, 0x62, 0xb7, 0x2c, 0x96, 0x68, 0xf9, 0x3b, 0x98, 0xed, 0xb9, 0xa8, 0x79, 0xdc, 0x4d, + 0xb5, 0xed, 0xa1, 0x3e, 0x37, 0x1a, 0x85, 0x20, 0x66, 0x6d, 0x75, 0xa4, 0xe1, 0xb9, 0x0e, 0xf3, 0x6a, 0xb1, 0x67, + 0x33, 0x55, 0x86, 0x10, 0x85, 0x23, 0x25, 0x01, 0xbb, 0x6d, 0x43, 0x27, 0xe1, 0x47, 0x9d, 0x4a, 0x3a, 0x16, 0x12, + 0xa0, 0xc0, 0x91, 0xb9, 0x9c, 0x37, 0x21, 0xe2, 0x19, 0xda, 0x41, 0xe4, 0x02, 0x13, 0x9a, 0xba, 0x6c, 0xe9, 0x62, + 0x39, 0x45, 0x33, 0xb9, 0x50, 0x6c, 0x31, 0x87, 0xf3, 0xbd, 0x4c, 0xcb, 0x72, 0x9e, 0x7d, 0xae, 0xa7, 0x80, 0xfd, + 0xe5, 0xad, 0x9e, 0x31, 0xb1, 0x88, 0xdc, 0x3c, 0xbf, 0x5a, 0x71, 0xff, 0xcd, 0x0b, 0xfc, 0x88, 0x74, 0x0e, 0xbf, + 0xe2, 0x8f, 0x94, 0x3c, 0x6a, 0x7c, 0xc5, 0x13, 0x4e, 0x2c, 0x6f, 0x90, 0xbc, 0x79, 0x7d, 0xf5, 0xe2, 0xdd, 0x8b, + 0xf7, 0x4f, 0xaf, 0x5f, 0xbc, 0x7a, 0xf6, 0xe2, 0xd5, 0x8b, 0x77, 0x1f, 0xf1, 0x3f, 0x94, 0x7c, 0x3d, 0x6a, 0x9f, + 0xb7, 0xf0, 0x07, 0xf2, 0xf5, 0xa8, 0x83, 0x6f, 0x35, 0xf9, 0x7a, 0x74, 0x82, 0x73, 0x45, 0xbe, 0x1e, 0x76, 0x8e, + 0x8e, 0xf1, 0x42, 0xdb, 0x26, 0x73, 0x39, 0x69, 0xb7, 0xf0, 0x3f, 0xee, 0x0b, 0xc4, 0xfb, 0x6a, 0x16, 0x13, 0xb6, + 0x61, 0xfc, 0x60, 0xca, 0xd0, 0xa1, 0x32, 0x86, 0x28, 0x17, 0x01, 0x3a, 0x4d, 0x55, 0x88, 0x4e, 0x36, 0x88, 0x31, + 0xd8, 0x30, 0x02, 0x5a, 0x71, 0xe2, 0xda, 0xe1, 0x47, 0x6d, 0x76, 0x0c, 0xf4, 0x89, 0x97, 0xc2, 0x71, 0xa9, 0xc2, + 0x69, 0x3b, 0x2d, 0xc6, 0x38, 0x97, 0xb2, 0x88, 0x17, 0xc0, 0x08, 0x18, 0xad, 0x05, 0x3f, 0x2a, 0xa3, 0x25, 0x89, + 0x0b, 0xd2, 0xee, 0xb5, 0x53, 0x71, 0x41, 0x3a, 0xbd, 0x0e, 0xfc, 0x39, 0xed, 0x9d, 0xa6, 0xed, 0x16, 0x3a, 0x0c, + 0xc6, 0xf1, 0x47, 0x0d, 0xad, 0xfb, 0x03, 0xec, 0xba, 0x50, 0xff, 0x14, 0xda, 0xab, 0xf4, 0x84, 0x53, 0xc7, 0xb6, + 0xbb, 0xe2, 0x82, 0x19, 0x3d, 0x2c, 0xff, 0x01, 0x50, 0xdb, 0x38, 0x74, 0x94, 0x1b, 0xc7, 0xfd, 0xe2, 0x47, 0x02, + 0xd5, 0x42, 0xb2, 0xc4, 0x6c, 0xd5, 0x42, 0xc0, 0x34, 0x9a, 0x6c, 0x30, 0x07, 0x4a, 0x94, 0x2c, 0xb4, 0x0f, 0x2b, + 0xaf, 0x9a, 0x12, 0x25, 0x73, 0x39, 0x8f, 0x6b, 0xaa, 0x86, 0x5f, 0x03, 0x33, 0xc7, 0x7d, 0xae, 0x5e, 0xd1, 0x57, + 0x71, 0x8d, 0xe7, 0x09, 0x59, 0xbb, 0x70, 0x5b, 0xfc, 0xe2, 0xac, 0x28, 0x6a, 0xe0, 0x2a, 0x01, 0xeb, 0x47, 0xd5, + 0xd4, 0x17, 0xf0, 0x7e, 0x1e, 0x6b, 0xe8, 0x4b, 0x12, 0x50, 0xcf, 0x9f, 0x4a, 0x33, 0xae, 0x52, 0x19, 0xed, 0x15, + 0xd1, 0xc6, 0x2c, 0xc8, 0x2b, 0xa2, 0x2f, 0x94, 0x01, 0x82, 0x24, 0xbc, 0x2f, 0x06, 0x70, 0xe0, 0xdb, 0x01, 0x4a, + 0x43, 0xe7, 0x40, 0xad, 0x54, 0x99, 0x09, 0x99, 0x4f, 0x13, 0x1c, 0x00, 0x34, 0x4f, 0x95, 0x0a, 0xca, 0x7c, 0x62, + 0x89, 0x82, 0xa1, 0xff, 0x16, 0x6e, 0x80, 0xc3, 0xd8, 0xa0, 0x62, 0x90, 0x7d, 0x4f, 0xd4, 0xf3, 0xdb, 0xe7, 0xad, + 0xa3, 0xaf, 0x41, 0xfe, 0x48, 0x79, 0x7b, 0x8f, 0xbf, 0x03, 0x4a, 0x6e, 0xc3, 0x59, 0xb5, 0xb1, 0x8f, 0x44, 0xd6, + 0x0d, 0x01, 0x72, 0xa8, 0xd1, 0x91, 0x79, 0x4a, 0xb0, 0x8b, 0xf4, 0x21, 0x69, 0xb7, 0x20, 0x7c, 0xd8, 0x0e, 0xca, + 0xf7, 0xd3, 0x06, 0x4c, 0x75, 0x72, 0xdb, 0x04, 0x5a, 0x0d, 0xaf, 0x0b, 0xdd, 0x35, 0x79, 0x72, 0x87, 0x55, 0x80, + 0x33, 0xec, 0x90, 0x35, 0xc4, 0xa1, 0x40, 0x2e, 0xec, 0xaa, 0xdd, 0x00, 0x9a, 0x8a, 0x8e, 0x7d, 0xe5, 0xce, 0x1b, + 0x47, 0x5d, 0x34, 0x93, 0xd3, 0xc3, 0xaf, 0x07, 0x07, 0xb1, 0x6c, 0x90, 0x47, 0x08, 0x2f, 0x29, 0x58, 0x31, 0x83, + 0xd7, 0x17, 0xb7, 0x4c, 0x7c, 0xaa, 0x02, 0xea, 0xb8, 0x50, 0xb5, 0x63, 0xad, 0xea, 0xac, 0xdc, 0x0d, 0x7e, 0x4c, + 0x1d, 0xd4, 0x08, 0xd2, 0xec, 0xe8, 0x3a, 0x35, 0x28, 0xd7, 0x5c, 0xb4, 0x60, 0x5b, 0x36, 0x3e, 0x52, 0xf4, 0xc3, + 0xa3, 0xe6, 0xd7, 0x60, 0xc2, 0x35, 0xd3, 0xa4, 0x47, 0x8d, 0x47, 0xe8, 0x87, 0x47, 0x81, 0x93, 0x1d, 0xaf, 0xd8, + 0x13, 0xcf, 0x8d, 0xfc, 0x64, 0xb9, 0xd2, 0x9f, 0x40, 0xb2, 0x2f, 0xc8, 0x4f, 0x80, 0xe5, 0x94, 0xfc, 0x14, 0xcb, + 0x26, 0x04, 0x1f, 0x24, 0x3f, 0xc5, 0x05, 0xfc, 0xc8, 0xc9, 0x4f, 0x31, 0x60, 0x3b, 0x9e, 0x9a, 0x1f, 0x45, 0x09, + 0x0c, 0x70, 0xec, 0x92, 0xd6, 0xbf, 0xab, 0x58, 0xad, 0xc4, 0xc1, 0x81, 0xb4, 0xbf, 0xe8, 0x65, 0x76, 0x70, 0x90, + 0x5f, 0x4c, 0xab, 0xbe, 0x99, 0xde, 0x45, 0x5f, 0x0c, 0x42, 0xe1, 0xc0, 0x34, 0x8d, 0x87, 0x33, 0xfe, 0x14, 0x52, + 0x56, 0xd3, 0x40, 0xf3, 0xb8, 0x73, 0xff, 0xec, 0x1c, 0xc3, 0xbf, 0xf7, 0x83, 0x82, 0x3f, 0x97, 0x7c, 0x17, 0x69, + 0xb3, 0xe6, 0x59, 0x85, 0x6c, 0x97, 0x01, 0x3e, 0x63, 0x86, 0x9a, 0xe2, 0xe0, 0x80, 0x5f, 0x04, 0xb8, 0x8c, 0x19, + 0x6a, 0x04, 0x16, 0x7b, 0x0f, 0x4b, 0x7b, 0x32, 0xc3, 0x35, 0xc1, 0xb3, 0xb2, 0xbc, 0x5f, 0x0c, 0x2e, 0xb4, 0xa3, + 0x26, 0x61, 0xf0, 0x69, 0x45, 0x5a, 0x6e, 0x93, 0x75, 0x45, 0x53, 0x5d, 0xb6, 0xbb, 0x48, 0x12, 0xd5, 0x10, 0x97, + 0x97, 0x6d, 0x0c, 0x2a, 0xf9, 0x9e, 0x22, 0x32, 0x15, 0xc4, 0x3b, 0xc8, 0x2d, 0x73, 0x99, 0x2a, 0x3c, 0xe5, 0xa9, + 0xf0, 0x72, 0xf6, 0x6b, 0x6f, 0x3d, 0x6d, 0x5c, 0x16, 0x4d, 0xcf, 0x0c, 0x8b, 0x9e, 0x2a, 0x5d, 0xed, 0x60, 0x93, + 0xaa, 0x01, 0xbc, 0xda, 0x57, 0x62, 0x1e, 0xb3, 0xfe, 0x65, 0x0c, 0xa2, 0x22, 0xab, 0x46, 0x1b, 0x32, 0xe1, 0x73, + 0x9d, 0x2a, 0x18, 0xa8, 0x29, 0x7c, 0x01, 0x64, 0x2a, 0xab, 0x0c, 0xb3, 0x7d, 0xc3, 0x50, 0x40, 0x40, 0x81, 0x4b, + 0xc2, 0x02, 0x09, 0x1e, 0x6e, 0x3f, 0x02, 0xc2, 0x51, 0x27, 0x17, 0x76, 0x72, 0x17, 0x0a, 0xba, 0x13, 0x83, 0x0b, + 0xdd, 0x45, 0xa2, 0xd1, 0x70, 0xdc, 0xf6, 0xa5, 0x30, 0x83, 0x68, 0xb6, 0x07, 0x97, 0xac, 0x8b, 0x54, 0xb3, 0x59, + 0x1a, 0x40, 0x5e, 0xb6, 0x56, 0x2b, 0x75, 0xe1, 0x1b, 0xe9, 0xf9, 0x73, 0xdc, 0xf0, 0x5d, 0x5e, 0xf0, 0xfc, 0x4d, + 0x92, 0x7e, 0x04, 0x54, 0x15, 0xf8, 0x6c, 0x39, 0x8f, 0x70, 0x64, 0x1e, 0x74, 0x83, 0xbf, 0xe6, 0x21, 0xae, 0x08, + 0x47, 0xee, 0x8d, 0xb7, 0x68, 0x50, 0x0d, 0x96, 0x67, 0x65, 0x78, 0x72, 0x9e, 0x5c, 0x03, 0xe3, 0xa0, 0xff, 0x56, + 0x68, 0x59, 0xfd, 0x4e, 0x72, 0x17, 0xa8, 0x43, 0xf9, 0x67, 0xc7, 0xdc, 0xa8, 0xd6, 0xbb, 0x5d, 0x23, 0x39, 0x8e, + 0x7c, 0x55, 0x08, 0xdf, 0xff, 0x9d, 0x77, 0x0f, 0xdb, 0xee, 0xb9, 0xed, 0x65, 0xd9, 0x03, 0x70, 0xde, 0xeb, 0x35, + 0xc2, 0xbf, 0xc9, 0x9d, 0x6f, 0xef, 0x46, 0xd7, 0x52, 0x3c, 0xa1, 0x9a, 0x46, 0x8d, 0x37, 0xc6, 0xf0, 0xcd, 0xca, + 0x59, 0xdd, 0x6f, 0x8d, 0x83, 0xfd, 0x5b, 0xdd, 0x43, 0xe8, 0x84, 0xda, 0x33, 0x41, 0x56, 0xf6, 0x35, 0x01, 0x33, + 0x64, 0x60, 0xfa, 0xb6, 0x03, 0x1e, 0x7e, 0x8c, 0x14, 0x1c, 0x7a, 0x2d, 0x9f, 0x44, 0x21, 0x26, 0x69, 0xcd, 0x8d, + 0x18, 0x52, 0x6c, 0x1f, 0xc6, 0xe5, 0x74, 0x8d, 0x42, 0xae, 0x7b, 0xac, 0xea, 0xc4, 0xb4, 0xea, 0xc6, 0x48, 0x1d, + 0x6c, 0x93, 0x05, 0x67, 0x55, 0xef, 0x46, 0x42, 0xa9, 0x5e, 0x54, 0x33, 0xaf, 0x62, 0x36, 0xdb, 0xe6, 0x99, 0x61, + 0xfb, 0xee, 0x9a, 0x02, 0x43, 0xde, 0xfd, 0x32, 0x5c, 0xd4, 0x25, 0x1c, 0xbb, 0x71, 0x00, 0x59, 0x49, 0x2e, 0x97, + 0xee, 0x4d, 0x34, 0xde, 0x97, 0x83, 0x75, 0xf9, 0x42, 0x5a, 0x80, 0x07, 0xd5, 0x48, 0x45, 0x16, 0x72, 0x06, 0xfe, + 0x79, 0xc1, 0x9a, 0x7e, 0x88, 0x7f, 0x85, 0x03, 0xbe, 0x42, 0xd2, 0xd4, 0xaa, 0x9f, 0xe0, 0xe5, 0x22, 0x50, 0x78, + 0xdb, 0xba, 0x9f, 0x64, 0xe8, 0x22, 0x5a, 0xd7, 0xa9, 0x58, 0x2f, 0xcc, 0xba, 0x62, 0xa5, 0x2c, 0x1c, 0x1c, 0x77, + 0x31, 0x5a, 0xa7, 0xce, 0x63, 0xd3, 0x3d, 0x77, 0xf4, 0x50, 0xf0, 0x99, 0x71, 0xa4, 0x7b, 0x56, 0x40, 0xfc, 0xaa, + 0x50, 0x9f, 0xf6, 0xb3, 0x0c, 0xdf, 0xf3, 0xed, 0xc3, 0x3d, 0x61, 0xc9, 0x73, 0x96, 0x6f, 0x50, 0xc3, 0x02, 0x29, + 0xa0, 0x50, 0x0a, 0x8b, 0xd5, 0x2a, 0x16, 0x26, 0xaa, 0x81, 0x0b, 0x6a, 0xeb, 0x5e, 0xaf, 0x30, 0xfa, 0x3b, 0xa8, + 0x8b, 0xbd, 0x7a, 0xc4, 0x98, 0xb0, 0xa2, 0xf0, 0xd2, 0x49, 0x65, 0x41, 0x5f, 0xbb, 0xfa, 0x10, 0xd5, 0x94, 0x7b, + 0xb1, 0xd1, 0xf7, 0xbe, 0xe3, 0x33, 0x26, 0x17, 0xf0, 0x6c, 0x10, 0x66, 0x44, 0x31, 0xed, 0xbf, 0x81, 0x82, 0xc0, + 0xdb, 0x33, 0x3c, 0xc4, 0x47, 0xe0, 0xab, 0x3c, 0xad, 0x93, 0x99, 0x7f, 0x8c, 0x22, 0x32, 0xc1, 0x22, 0xa3, 0x5e, + 0x04, 0x5e, 0x43, 0x20, 0x42, 0x11, 0x12, 0x31, 0x31, 0x8a, 0x7a, 0x91, 0x71, 0x52, 0x8a, 0xc0, 0x6a, 0x0c, 0x94, + 0xdc, 0x11, 0x9e, 0xab, 0x8a, 0x88, 0x85, 0x35, 0x75, 0x50, 0x89, 0xa5, 0xc6, 0x4c, 0xfb, 0xa8, 0x53, 0x81, 0xb0, + 0xc8, 0x36, 0x05, 0x65, 0xbd, 0xa1, 0x2e, 0xc0, 0x92, 0x18, 0xd3, 0x5b, 0x9e, 0x5c, 0x03, 0x37, 0xc7, 0x46, 0xae, + 0xe8, 0x92, 0x5f, 0x81, 0x7a, 0x3a, 0x2d, 0xf0, 0xb5, 0x61, 0xd8, 0x46, 0x29, 0x5d, 0x13, 0x8e, 0x33, 0x52, 0x24, + 0xf4, 0x16, 0xa2, 0x3a, 0xcc, 0xb8, 0x48, 0x73, 0x3c, 0xa3, 0xb7, 0xe9, 0x14, 0xcf, 0xb8, 0x78, 0x62, 0x97, 0x3d, + 0x1d, 0x41, 0x92, 0xff, 0x58, 0xac, 0x89, 0x79, 0x94, 0xea, 0x77, 0xc5, 0x8a, 0x47, 0xc0, 0xab, 0xa8, 0x18, 0x75, + 0x47, 0xc6, 0xa6, 0x9c, 0xe9, 0xca, 0x78, 0xfd, 0xb5, 0x8e, 0x29, 0xce, 0x70, 0x8e, 0x92, 0x5c, 0x62, 0xd6, 0x13, + 0xe9, 0x6b, 0x88, 0xe8, 0x9c, 0x61, 0xfb, 0xa0, 0x15, 0xbf, 0x65, 0xf9, 0x33, 0x59, 0xbc, 0x37, 0x5b, 0x3e, 0x47, + 0x50, 0x08, 0x5c, 0x54, 0x44, 0x13, 0x6e, 0xf7, 0x16, 0x3d, 0x59, 0x35, 0x45, 0x6f, 0x6d, 0x53, 0x6e, 0x88, 0x53, + 0x08, 0x85, 0x9b, 0x4c, 0x79, 0xa3, 0x8d, 0x59, 0xaf, 0xf5, 0x9d, 0x46, 0xa7, 0xa8, 0x2c, 0x89, 0x30, 0xac, 0x55, + 0x53, 0xa5, 0x92, 0x88, 0xa6, 0x72, 0x12, 0xde, 0xd2, 0x00, 0x3b, 0x55, 0x38, 0x93, 0x0b, 0xa1, 0x53, 0x19, 0xe0, + 0x0d, 0xad, 0x36, 0xd7, 0xf2, 0xd6, 0x42, 0x4c, 0xe3, 0x3b, 0xfb, 0x83, 0xe1, 0x6b, 0xa3, 0xe2, 0x7f, 0x0b, 0x86, + 0x3d, 0x2a, 0x15, 0x00, 0x3f, 0x30, 0x9c, 0x05, 0xc8, 0x59, 0x7e, 0xf2, 0x16, 0xc0, 0x67, 0x59, 0xc8, 0x3b, 0x48, + 0x65, 0x26, 0xf5, 0x0e, 0x52, 0x19, 0xa4, 0x1a, 0x5f, 0xee, 0x7d, 0x51, 0x29, 0x8b, 0xc2, 0x06, 0x89, 0xc2, 0xa5, + 0x3a, 0x58, 0x12, 0x91, 0x40, 0xbb, 0x46, 0x94, 0x9b, 0x71, 0x01, 0x41, 0xfd, 0xa0, 0x71, 0xfb, 0x4d, 0x6f, 0xe1, + 0xfb, 0xce, 0xe6, 0x33, 0x9f, 0x7f, 0x67, 0xf3, 0x4d, 0x47, 0x1e, 0xe3, 0xeb, 0xb7, 0x9d, 0xc6, 0x32, 0x5e, 0x3a, + 0xac, 0xfd, 0x50, 0x3e, 0xa1, 0xd2, 0x32, 0x4f, 0x55, 0x93, 0x36, 0x9e, 0x04, 0x48, 0xd9, 0xac, 0x78, 0xb8, 0x0e, + 0x6e, 0xb7, 0x0e, 0x63, 0xde, 0x24, 0x6d, 0x84, 0x0e, 0x9d, 0x70, 0x25, 0x62, 0x23, 0x39, 0x1d, 0x3e, 0x3a, 0x82, + 0xbb, 0x97, 0x99, 0xda, 0xf0, 0x95, 0xb2, 0xd5, 0x9a, 0xed, 0xd6, 0x21, 0xdf, 0x59, 0xa5, 0xd1, 0xc6, 0x33, 0x46, + 0x96, 0xe0, 0x5c, 0x46, 0x0b, 0xab, 0x6a, 0x00, 0x27, 0xce, 0x17, 0xe2, 0xb7, 0x05, 0x1d, 0x99, 0xef, 0x43, 0x9b, + 0xf2, 0x7a, 0xa1, 0x7d, 0x52, 0x93, 0xc3, 0x20, 0x3a, 0xc8, 0x95, 0x0c, 0x72, 0x62, 0x7e, 0x44, 0x92, 0x53, 0x74, + 0xd1, 0xee, 0x25, 0xa7, 0x87, 0xfc, 0x90, 0xa7, 0xc0, 0xc3, 0xc6, 0x4d, 0x5f, 0xa1, 0xd9, 0xf6, 0x75, 0x1e, 0x2f, + 0x86, 0x3c, 0x73, 0xcd, 0x57, 0x1d, 0x94, 0xa9, 0x76, 0x8e, 0x90, 0x05, 0x28, 0xe6, 0x7b, 0x09, 0xb2, 0xeb, 0xdd, + 0x1c, 0xf2, 0x14, 0xfa, 0x81, 0x5a, 0x1d, 0x5b, 0xab, 0x1c, 0xdc, 0x6f, 0x0b, 0x40, 0x30, 0xdf, 0x51, 0x6d, 0x2e, + 0x36, 0xbd, 0x19, 0x57, 0x9d, 0x1d, 0xf2, 0x6a, 0x84, 0x61, 0x99, 0xed, 0xfe, 0xfc, 0xd4, 0xaa, 0x2e, 0x0f, 0x03, + 0x88, 0xfc, 0xb6, 0xe0, 0x22, 0xec, 0x34, 0xec, 0xd6, 0xe5, 0x84, 0x9d, 0xd6, 0x67, 0x19, 0x14, 0xd9, 0xee, 0x75, + 0x6b, 0xa6, 0xf5, 0xd9, 0x5e, 0x81, 0x8f, 0x20, 0x4c, 0xca, 0xac, 0x74, 0x06, 0x57, 0xe8, 0x87, 0x1f, 0x90, 0x6b, + 0xfd, 0xf5, 0x42, 0xfb, 0xfc, 0x12, 0x11, 0x20, 0xbb, 0xea, 0xba, 0xac, 0x0e, 0x7d, 0x94, 0x4d, 0x7c, 0x3d, 0xe4, + 0xc1, 0xca, 0x3d, 0xbd, 0x9d, 0xcb, 0xd4, 0xe3, 0x6b, 0xaf, 0x95, 0x6e, 0x21, 0x27, 0x10, 0x0f, 0xd7, 0x5d, 0x58, + 0x16, 0xe4, 0xec, 0xe6, 0x16, 0x4a, 0x86, 0x13, 0xf7, 0xa5, 0x3f, 0x30, 0x7b, 0xdd, 0xc0, 0x2f, 0x92, 0x53, 0x98, + 0xfa, 0x66, 0x0f, 0x87, 0x1d, 0xe8, 0xc3, 0xc0, 0x61, 0xb3, 0x41, 0x9f, 0x59, 0x41, 0xe4, 0x31, 0x2f, 0x2c, 0x9e, + 0x5d, 0x92, 0x76, 0x8f, 0xa7, 0x6e, 0x33, 0x19, 0xd1, 0xa8, 0xdd, 0xe4, 0xc1, 0xcc, 0x00, 0xbf, 0x5c, 0xd9, 0xb0, + 0x88, 0x5f, 0xa7, 0x00, 0x4a, 0xbe, 0x58, 0xb5, 0x3e, 0x15, 0xbc, 0xea, 0x0d, 0xa7, 0x9b, 0xe9, 0x7e, 0xdd, 0xe0, + 0x76, 0xd7, 0xc3, 0x13, 0x9e, 0x40, 0xb1, 0x68, 0xed, 0x27, 0x3e, 0x01, 0x0e, 0x28, 0x69, 0xdd, 0x3f, 0x05, 0x17, + 0xca, 0x12, 0x96, 0xdb, 0xe5, 0x66, 0x5b, 0xe5, 0x2c, 0x1c, 0x6d, 0xc9, 0x80, 0x3b, 0xd8, 0x84, 0x28, 0x74, 0x70, + 0xd8, 0xc1, 0x49, 0xbb, 0xdd, 0x39, 0xc5, 0xc9, 0xc9, 0x29, 0x0c, 0xb4, 0x91, 0x9c, 0x1e, 0xce, 0x94, 0x05, 0x60, + 0x90, 0xb3, 0x76, 0xed, 0x3e, 0x82, 0x70, 0x49, 0xa1, 0x78, 0xcd, 0x0f, 0xe3, 0xb8, 0x9d, 0xdc, 0x6f, 0xb5, 0x4f, + 0xcf, 0x1b, 0x00, 0xa0, 0xa6, 0xfb, 0x70, 0x35, 0x5e, 0x2f, 0x74, 0xbd, 0x4a, 0x89, 0xf0, 0xf5, 0x6a, 0x0d, 0x5f, + 0xad, 0xd1, 0x5e, 0x57, 0x53, 0xf0, 0x55, 0x9d, 0x70, 0x6e, 0x8b, 0x78, 0xa5, 0x4d, 0xb8, 0x2d, 0x62, 0x3b, 0x90, + 0x18, 0xa4, 0xf3, 0xe4, 0xb4, 0x73, 0x8a, 0xec, 0x58, 0xb4, 0xc3, 0x8f, 0x72, 0x9f, 0x6c, 0x15, 0x69, 0x68, 0x40, + 0x92, 0x72, 0x76, 0x72, 0x01, 0x12, 0x35, 0x27, 0x97, 0xed, 0xe6, 0x8c, 0x25, 0x7e, 0x02, 0x26, 0x15, 0x96, 0xb3, + 0x5c, 0x05, 0x97, 0x14, 0x00, 0xe2, 0x02, 0x8c, 0x8b, 0xee, 0x9f, 0xf6, 0xee, 0x27, 0xa7, 0x67, 0x1d, 0x4b, 0xf4, + 0xf8, 0x45, 0xa7, 0x96, 0x66, 0xa6, 0x9e, 0x9c, 0x9a, 0x34, 0xe8, 0x3a, 0xb9, 0x7f, 0x0a, 0x65, 0x5c, 0x4a, 0x58, + 0x0a, 0xc2, 0x3c, 0x54, 0xc5, 0x20, 0xb6, 0x43, 0x5a, 0xcb, 0x3d, 0xab, 0x65, 0x9f, 0x9f, 0x1c, 0xdf, 0x3f, 0x0d, + 0xa1, 0x56, 0xce, 0xc2, 0x2c, 0xb4, 0x9b, 0x88, 0x9f, 0x1d, 0x2c, 0x2d, 0x3a, 0x4c, 0x4e, 0xd3, 0xad, 0x09, 0xda, + 0x4d, 0x73, 0x68, 0x70, 0x20, 0x50, 0x38, 0x3e, 0x15, 0x4e, 0x5f, 0x12, 0xdc, 0x8f, 0x55, 0x86, 0x26, 0xa1, 0xc2, + 0xd9, 0xdf, 0x53, 0x06, 0x2f, 0x39, 0x86, 0x57, 0x95, 0x8f, 0xa9, 0xf8, 0x42, 0xd5, 0x1b, 0x0a, 0xb1, 0x2b, 0xc4, + 0x20, 0x72, 0x91, 0xb5, 0xeb, 0xb9, 0x3f, 0x81, 0x8b, 0x30, 0x13, 0x70, 0xa1, 0xe9, 0x95, 0xa0, 0x15, 0x2f, 0x30, + 0x0c, 0x1d, 0x6a, 0xcd, 0xb0, 0x7a, 0x3c, 0x75, 0x26, 0x05, 0xa1, 0x6e, 0xeb, 0x39, 0xff, 0x5e, 0xb9, 0xa4, 0xbc, + 0xca, 0x4e, 0x4e, 0x51, 0xe2, 0x2e, 0xcb, 0x93, 0x36, 0x4a, 0x02, 0x13, 0x12, 0x77, 0x24, 0x67, 0x19, 0xe9, 0x47, + 0xb7, 0x11, 0x8e, 0xee, 0x22, 0x1c, 0x59, 0x1f, 0xe6, 0x0f, 0xe0, 0x3c, 0x1f, 0xe1, 0xc8, 0xba, 0x32, 0x47, 0x38, + 0xd2, 0x4c, 0x40, 0x48, 0xab, 0x68, 0x80, 0x73, 0x28, 0x6d, 0x3c, 0xab, 0xcb, 0xd2, 0x8f, 0xfd, 0x57, 0xe9, 0x7a, + 0x6d, 0x53, 0x02, 0x29, 0x73, 0x6a, 0x76, 0xa8, 0x7d, 0x92, 0x39, 0xa2, 0x9e, 0x59, 0x8f, 0x30, 0x08, 0x20, 0xf4, + 0xce, 0x3f, 0xe9, 0x56, 0x45, 0xc3, 0x60, 0xc7, 0xb0, 0xd2, 0xe0, 0x67, 0x1e, 0x85, 0x67, 0x58, 0x84, 0xc7, 0xc2, + 0x17, 0x06, 0xb1, 0xc2, 0xff, 0xce, 0xa5, 0x9c, 0xfb, 0xdf, 0x5a, 0x96, 0xbf, 0xe0, 0x21, 0x10, 0x67, 0xd1, 0x02, + 0x96, 0x5b, 0x36, 0xf8, 0xce, 0x90, 0xd5, 0x47, 0x70, 0x3d, 0x76, 0x01, 0xd2, 0x40, 0x22, 0xbc, 0x36, 0x02, 0x95, + 0x97, 0x0f, 0xaf, 0x6d, 0xb0, 0x1e, 0xf3, 0x09, 0xd1, 0xba, 0x20, 0x20, 0xaf, 0x84, 0x0b, 0x8d, 0x49, 0xc1, 0x94, + 0x8a, 0x6c, 0x14, 0xbb, 0x48, 0x0a, 0xff, 0x2c, 0xa1, 0x4f, 0x19, 0x8b, 0xc8, 0x74, 0x58, 0x9f, 0xad, 0x15, 0x87, + 0x73, 0x59, 0xa8, 0xd4, 0xbe, 0x51, 0xe2, 0xc1, 0x58, 0x3d, 0x55, 0x9f, 0xe6, 0xd9, 0x1a, 0xdb, 0x3b, 0xec, 0xb2, + 0x90, 0xbb, 0xd2, 0x0e, 0x4b, 0x65, 0xd9, 0xfa, 0x5b, 0x13, 0x52, 0xb5, 0x19, 0x05, 0x13, 0xad, 0x06, 0x54, 0x85, + 0xb2, 0x80, 0xc2, 0x36, 0x1c, 0x4a, 0xba, 0x2c, 0x4b, 0xa6, 0xcb, 0x72, 0x19, 0x4e, 0x5a, 0xad, 0xf5, 0x1a, 0x17, + 0xcc, 0x84, 0x65, 0xd9, 0x59, 0x02, 0xf2, 0xd5, 0x54, 0xde, 0x04, 0xb9, 0x2a, 0x2d, 0x67, 0x69, 0x96, 0x28, 0x0a, + 0x8c, 0x60, 0xa3, 0x35, 0xfe, 0xc2, 0x15, 0x07, 0x78, 0xba, 0xd9, 0x0d, 0xa5, 0xcc, 0x19, 0x85, 0xe8, 0x5d, 0x41, + 0x93, 0x6b, 0x3c, 0xe5, 0x23, 0xb6, 0xbb, 0x4d, 0x30, 0x63, 0xfe, 0xf7, 0x5a, 0xf4, 0x08, 0x64, 0xd9, 0x3d, 0x83, + 0x3a, 0xb0, 0x88, 0x2b, 0xe8, 0x20, 0x94, 0xc1, 0x47, 0x21, 0x6e, 0xe6, 0xf4, 0x4e, 0x2e, 0x34, 0xc0, 0x65, 0xa1, + 0xe5, 0x1b, 0x17, 0xeb, 0x60, 0xbf, 0x85, 0x7d, 0xd8, 0x83, 0x25, 0x84, 0x0c, 0x68, 0x61, 0x1b, 0x23, 0xa2, 0x85, + 0x87, 0x52, 0x6b, 0x39, 0x4b, 0x5b, 0xd8, 0x04, 0x6c, 0x68, 0xad, 0xcb, 0xa8, 0x5a, 0xd7, 0xe5, 0x63, 0x8e, 0xd5, + 0x26, 0x58, 0x38, 0xe9, 0x50, 0x13, 0x1d, 0xdc, 0x1e, 0x32, 0xc2, 0x1b, 0x3f, 0x5f, 0xbd, 0x7e, 0xe5, 0x62, 0x26, + 0xf3, 0x31, 0xb8, 0x6c, 0x3a, 0xd5, 0xd8, 0xb5, 0x79, 0x05, 0x29, 0xae, 0x14, 0xa5, 0x56, 0x38, 0x85, 0x96, 0x5f, + 0x08, 0x9d, 0x27, 0xf6, 0xf2, 0xe2, 0x99, 0x2c, 0x66, 0xd4, 0xde, 0x18, 0xe1, 0x6b, 0xe5, 0x9e, 0x3d, 0x37, 0x2f, + 0xab, 0x54, 0x93, 0x7c, 0xb7, 0x79, 0x15, 0xb1, 0xc8, 0x8c, 0xfc, 0x0a, 0xda, 0x00, 0x53, 0xb9, 0x7c, 0xb5, 0xb6, + 0x20, 0x2e, 0xf2, 0x7c, 0x40, 0x5e, 0xde, 0x5a, 0xea, 0x12, 0x45, 0x0d, 0x6e, 0xf0, 0x93, 0x15, 0x3c, 0x0b, 0xae, + 0x0b, 0x0d, 0x7b, 0xe4, 0xc4, 0x8b, 0xa8, 0x15, 0xd5, 0x5f, 0x7d, 0x35, 0xaa, 0x04, 0x1f, 0xb5, 0x34, 0xc9, 0x25, + 0x88, 0x1e, 0xe5, 0x03, 0x73, 0x1c, 0x44, 0x13, 0x7f, 0xf7, 0x7c, 0xd9, 0xf6, 0x74, 0x36, 0xaf, 0xd4, 0x89, 0xe5, + 0x95, 0x09, 0x78, 0x38, 0xda, 0x27, 0x5c, 0x10, 0x0e, 0x12, 0x59, 0xa9, 0x3d, 0xf4, 0xb9, 0xa8, 0x1b, 0xe7, 0x17, + 0x6d, 0xd6, 0x3c, 0x59, 0xad, 0xf2, 0xcb, 0x36, 0x6b, 0x9f, 0xda, 0x07, 0xdf, 0x22, 0x95, 0x01, 0xcd, 0xe5, 0x63, + 0x9e, 0x45, 0xa0, 0x9d, 0x1d, 0x67, 0x26, 0x9c, 0x82, 0x0f, 0x51, 0x4c, 0x16, 0xba, 0xea, 0x4b, 0x82, 0x71, 0x29, + 0xb1, 0x7a, 0xfc, 0x02, 0xf5, 0xda, 0xe9, 0xb6, 0xab, 0x74, 0xb3, 0x7d, 0x18, 0x5c, 0xb8, 0x14, 0x08, 0x77, 0x20, + 0xe4, 0x01, 0xe8, 0x77, 0x97, 0x02, 0x4c, 0x83, 0x00, 0x95, 0x15, 0x88, 0xb4, 0x7c, 0xb6, 0x98, 0x3d, 0x2b, 0xa8, + 0x59, 0x86, 0x27, 0x7c, 0xc2, 0xb5, 0x4a, 0x29, 0x48, 0xb7, 0xbb, 0xd2, 0xd7, 0xbb, 0x25, 0xa8, 0xac, 0x16, 0xf9, + 0x35, 0xd1, 0x3c, 0xfb, 0xac, 0xdc, 0xc2, 0x21, 0x6c, 0x56, 0x56, 0xe0, 0x0c, 0xad, 0x71, 0x2e, 0x27, 0xb4, 0xe0, + 0x7a, 0x3a, 0xfb, 0xb7, 0x56, 0x87, 0xf5, 0xf5, 0xc0, 0x5c, 0x58, 0x01, 0x48, 0xa8, 0x18, 0xad, 0x56, 0xfc, 0xe8, + 0xfb, 0xf7, 0x49, 0xde, 0x27, 0xbc, 0x8d, 0x3b, 0xf8, 0x18, 0x9f, 0xe2, 0x76, 0x0b, 0xb7, 0x4f, 0xe1, 0xea, 0x3e, + 0xcb, 0x17, 0x23, 0xa6, 0x62, 0x78, 0xf9, 0x4b, 0x5f, 0x26, 0xe7, 0x87, 0x65, 0xbc, 0x7b, 0x5d, 0x24, 0x0e, 0x5d, + 0x82, 0xb0, 0xeb, 0x2e, 0x5e, 0x5d, 0x14, 0x85, 0xc1, 0xd2, 0xc6, 0xa1, 0xea, 0xa4, 0xd4, 0x2f, 0x5c, 0x1e, 0xf7, + 0xc0, 0x9e, 0xdb, 0xae, 0x6c, 0x13, 0xcc, 0xbe, 0xed, 0xcf, 0xb4, 0xfa, 0xd9, 0xd4, 0x25, 0x62, 0x78, 0xe8, 0x55, + 0xe8, 0x81, 0x2e, 0x49, 0xfb, 0xe0, 0x00, 0xac, 0x8e, 0x82, 0xd9, 0x70, 0x1b, 0xfd, 0x80, 0x37, 0x6b, 0x69, 0x10, + 0xac, 0x00, 0x8c, 0x3b, 0xdf, 0x70, 0xb2, 0xb4, 0xb0, 0xd5, 0x40, 0x85, 0x75, 0x11, 0x46, 0x74, 0x0b, 0x49, 0x85, + 0x11, 0xa2, 0xe1, 0x08, 0x73, 0x91, 0x4e, 0xf6, 0x5b, 0x58, 0x8e, 0xc7, 0x8a, 0x69, 0x38, 0x3a, 0x0a, 0xf6, 0x85, + 0x15, 0xca, 0x9c, 0x22, 0x43, 0x36, 0xe1, 0xe2, 0xa1, 0xfe, 0xc4, 0x0a, 0x69, 0x3e, 0x8d, 0x06, 0x23, 0x8d, 0xcc, + 0x2a, 0x46, 0x38, 0xcb, 0xf9, 0x1c, 0xaa, 0x4e, 0x0a, 0x70, 0xfa, 0x81, 0xbf, 0x7c, 0x94, 0x86, 0x6d, 0x02, 0xf9, + 0xfa, 0x60, 0x83, 0xd9, 0xe0, 0x51, 0x41, 0x6f, 0x5e, 0x8b, 0xc7, 0xb0, 0xa3, 0x1e, 0x16, 0x8c, 0x42, 0x36, 0x24, + 0xbd, 0x83, 0xa6, 0xe0, 0x03, 0xda, 0x7c, 0x69, 0x00, 0x97, 0x9e, 0x9b, 0x0f, 0x5b, 0xd1, 0x47, 0x0d, 0x4c, 0xca, + 0xb6, 0x4c, 0xa6, 0x39, 0xa5, 0xab, 0x4c, 0x1b, 0x97, 0xa9, 0x9c, 0xc2, 0x1a, 0xbb, 0xa8, 0x27, 0xe1, 0x60, 0x46, + 0x54, 0x4d, 0xd3, 0xfe, 0xc0, 0xfc, 0x7d, 0x6d, 0x4b, 0xb6, 0xb0, 0x0b, 0xb5, 0xb3, 0xc6, 0xe6, 0xc9, 0xce, 0xa0, + 0x7c, 0x1b, 0xc3, 0x3d, 0x2c, 0xbc, 0x1b, 0x59, 0x23, 0x9f, 0x27, 0x9e, 0x6c, 0x9e, 0xac, 0xd7, 0x66, 0x20, 0x2a, + 0x05, 0x3d, 0xd0, 0x5b, 0xbf, 0x6d, 0x5a, 0xb0, 0x3d, 0xca, 0xaf, 0xd3, 0x16, 0x9e, 0x71, 0x78, 0x06, 0xd3, 0xb7, + 0x77, 0xa5, 0x0b, 0xf9, 0xd9, 0x81, 0xa4, 0x15, 0xa4, 0xd8, 0xe9, 0x04, 0x9d, 0x1d, 0xe3, 0x60, 0xe4, 0x40, 0xcf, + 0xaf, 0x3e, 0x5b, 0x58, 0xfb, 0xdf, 0x6f, 0xca, 0x82, 0x39, 0x1d, 0xb2, 0xbc, 0x9c, 0x50, 0xe6, 0xcf, 0xcf, 0x37, + 0x3c, 0xa9, 0x50, 0xc1, 0xbd, 0x1f, 0x05, 0x7b, 0xda, 0x86, 0x98, 0x9c, 0xd1, 0xbf, 0xed, 0x0f, 0x1b, 0x11, 0xa8, + 0xd4, 0xb2, 0x65, 0x85, 0x54, 0xea, 0xa1, 0x4d, 0xb3, 0x47, 0x0f, 0x1c, 0x91, 0x2f, 0xa1, 0x0b, 0xe0, 0xf5, 0x47, + 0x85, 0x9c, 0x1b, 0x44, 0x70, 0xbf, 0xdd, 0xb8, 0x8d, 0xaf, 0x00, 0x78, 0x3b, 0xec, 0x55, 0xff, 0xb4, 0x80, 0xfd, + 0x8d, 0xca, 0x92, 0x7e, 0xbc, 0x1d, 0x7b, 0xfc, 0x17, 0x12, 0xe2, 0x95, 0x5b, 0x3c, 0x4c, 0x1c, 0x3a, 0x95, 0xac, + 0x59, 0xf9, 0x73, 0xab, 0x24, 0x60, 0x58, 0xbd, 0x60, 0xc8, 0xc6, 0x6d, 0x15, 0xb7, 0x99, 0xff, 0x41, 0x05, 0x83, + 0x05, 0xdf, 0x1a, 0x49, 0xc5, 0xb2, 0xf8, 0xed, 0x53, 0xe7, 0xbf, 0xea, 0x1c, 0xd7, 0xbe, 0xae, 0xbd, 0x51, 0x39, + 0x34, 0xf1, 0x81, 0x23, 0x74, 0x70, 0xb0, 0x91, 0x41, 0xc7, 0x00, 0x78, 0xe4, 0xd8, 0x2f, 0xbf, 0x7c, 0x9e, 0x1d, + 0x33, 0x9a, 0xc7, 0x22, 0x0a, 0x99, 0x3b, 0xcf, 0xcd, 0xd9, 0x89, 0x3c, 0xa1, 0x6a, 0xea, 0x0b, 0x03, 0x1c, 0x1f, + 0x6d, 0xa5, 0x02, 0xbe, 0x47, 0xeb, 0x1d, 0x13, 0xd8, 0xe0, 0xb7, 0xec, 0xa4, 0x76, 0x15, 0xf4, 0x0b, 0xb4, 0xdc, + 0xc5, 0x54, 0x6e, 0x2c, 0x70, 0xb4, 0x39, 0x91, 0x9d, 0x43, 0xdf, 0xa8, 0x53, 0xb2, 0x1e, 0x4f, 0x76, 0x1b, 0x7d, + 0x49, 0xb1, 0x2b, 0xb9, 0xa2, 0x6d, 0x43, 0x56, 0xbd, 0x53, 0xab, 0x2b, 0x53, 0xa7, 0xea, 0x9a, 0xb7, 0xb2, 0xb4, + 0x29, 0xed, 0x92, 0xec, 0xdd, 0x16, 0x0b, 0xaf, 0xc2, 0x1b, 0x8d, 0xf2, 0x22, 0x14, 0xec, 0xb1, 0xc4, 0xa0, 0xcb, + 0x09, 0x5c, 0x2f, 0xac, 0x56, 0x31, 0xfc, 0xd9, 0x35, 0x86, 0x5d, 0xa6, 0x4b, 0x1f, 0xf8, 0x06, 0xbf, 0x12, 0x84, + 0xca, 0x75, 0x76, 0x90, 0x60, 0xdd, 0xe5, 0x06, 0x0d, 0xc7, 0x89, 0xff, 0x82, 0x87, 0x9a, 0xb5, 0x77, 0x39, 0x98, + 0x64, 0xdf, 0x78, 0xdc, 0xad, 0x64, 0x2d, 0x6b, 0x71, 0xd6, 0x37, 0x24, 0x18, 0x62, 0x37, 0xa5, 0x73, 0xdc, 0x4a, + 0xda, 0x28, 0x72, 0xc5, 0x2a, 0xf4, 0xff, 0x56, 0x91, 0xcc, 0x66, 0xfe, 0xd7, 0xd9, 0xd9, 0x99, 0x4b, 0x71, 0x36, + 0x7f, 0xca, 0x78, 0xc0, 0x99, 0x04, 0xf6, 0x85, 0x67, 0xcc, 0xe8, 0x90, 0xdf, 0xc2, 0x50, 0x88, 0x20, 0x97, 0xc2, + 0xb1, 0x4b, 0xf0, 0xce, 0x20, 0x50, 0x1e, 0x60, 0xff, 0x9e, 0x6c, 0x94, 0xf3, 0x0f, 0x15, 0xf9, 0x40, 0xbe, 0x65, + 0x83, 0xec, 0x8b, 0xf9, 0xec, 0x5b, 0x33, 0x19, 0x88, 0xcd, 0x1f, 0x61, 0xfb, 0xdb, 0xb0, 0xb4, 0xce, 0x52, 0x06, + 0x47, 0x5a, 0x2e, 0xb2, 0xa9, 0xd5, 0xfc, 0xbb, 0x0f, 0x53, 0xd6, 0x3d, 0x72, 0x03, 0x41, 0xb9, 0xc8, 0xd2, 0xc5, + 0xa3, 0x8c, 0x7e, 0x2c, 0x43, 0x4f, 0xee, 0xbd, 0x62, 0x0b, 0xf6, 0x23, 0xde, 0xab, 0x52, 0xe0, 0xe3, 0x61, 0xc1, + 0x69, 0xfe, 0x23, 0xde, 0xab, 0x42, 0x50, 0x82, 0x2b, 0xa4, 0x89, 0xe2, 0x88, 0xcd, 0x83, 0xce, 0x69, 0x24, 0x80, + 0x82, 0xe6, 0x91, 0x39, 0xc8, 0x9e, 0xbb, 0xa8, 0x85, 0x49, 0x07, 0xbb, 0xb8, 0x5f, 0x36, 0x16, 0xa9, 0x0d, 0xe1, + 0x0d, 0x91, 0xdc, 0xca, 0xd9, 0x98, 0xaf, 0x47, 0x1b, 0x0b, 0x62, 0x94, 0xc9, 0xe4, 0xf2, 0x39, 0x8f, 0xb7, 0x16, + 0x0b, 0x85, 0xd5, 0x82, 0x05, 0xaa, 0x55, 0xa9, 0xd2, 0xc3, 0xe2, 0xdb, 0x05, 0xb3, 0xa0, 0x88, 0xd9, 0x7a, 0x0f, + 0x6f, 0xb9, 0x22, 0x20, 0x25, 0xbb, 0x24, 0x78, 0x93, 0xdb, 0x60, 0xaa, 0x7f, 0x82, 0x1d, 0x08, 0x3d, 0x53, 0x3a, + 0xc2, 0x26, 0x4f, 0x41, 0x24, 0xb1, 0xfd, 0x16, 0x76, 0xac, 0xd1, 0x0b, 0xe1, 0x85, 0x14, 0x38, 0x57, 0x4d, 0x13, + 0x33, 0xca, 0x4d, 0x74, 0xb1, 0x87, 0x6a, 0xce, 0x32, 0x6d, 0x11, 0x60, 0xdf, 0xa1, 0xa1, 0x14, 0xcf, 0x0d, 0x28, + 0xcc, 0x63, 0xd2, 0x2e, 0xe5, 0x31, 0x2c, 0x5e, 0x90, 0x02, 0x44, 0x8d, 0x8b, 0x49, 0x59, 0x67, 0x9e, 0x2f, 0x26, + 0x5c, 0x54, 0xc8, 0x50, 0x30, 0x35, 0x97, 0x02, 0xde, 0x72, 0x28, 0x8b, 0x18, 0x3a, 0x54, 0xc3, 0x77, 0x4b, 0xc2, + 0xca, 0x3a, 0xe6, 0x98, 0xe2, 0xa2, 0xaa, 0x01, 0xcc, 0xc5, 0xc3, 0xf0, 0xd1, 0x77, 0xf5, 0x5a, 0xbc, 0x93, 0xf3, + 0x2a, 0xdf, 0xd3, 0x38, 0x1f, 0x32, 0xdd, 0xd9, 0x0d, 0xa3, 0xb5, 0x79, 0x6e, 0x29, 0xd8, 0xbe, 0x1f, 0x78, 0xf5, + 0x04, 0xd9, 0xda, 0x3c, 0xd8, 0x54, 0x66, 0x0d, 0x59, 0xf9, 0x3a, 0x41, 0xd5, 0x5e, 0xbd, 0xaa, 0x14, 0xb6, 0x22, + 0x40, 0xa5, 0xe0, 0xa3, 0xad, 0xfc, 0x27, 0xda, 0xe6, 0xdb, 0x73, 0xa8, 0x0c, 0x0f, 0xe4, 0xc9, 0x50, 0xd5, 0x03, + 0x2e, 0xca, 0x0f, 0x01, 0x2c, 0x7e, 0x64, 0x22, 0xd7, 0xee, 0xba, 0x40, 0xe6, 0x4c, 0xc5, 0x12, 0x2f, 0xfb, 0x74, + 0x90, 0x5a, 0x79, 0x28, 0x95, 0x60, 0xdb, 0x73, 0x53, 0x70, 0xed, 0x43, 0xe4, 0xe2, 0x3e, 0x1b, 0xa4, 0xcb, 0x7a, + 0x18, 0x5d, 0x1b, 0xc8, 0xd7, 0x9b, 0x73, 0x9a, 0xb8, 0xb3, 0x74, 0x80, 0x73, 0x02, 0xb6, 0xc7, 0x9e, 0x3d, 0x7d, + 0x13, 0x67, 0xa8, 0x57, 0xe7, 0xf0, 0x97, 0x6b, 0x9c, 0xe3, 0x0c, 0xa5, 0x0f, 0x63, 0xb8, 0xc0, 0x5a, 0x63, 0x00, + 0x5f, 0x66, 0x49, 0x15, 0x78, 0xa4, 0x66, 0x46, 0x62, 0x75, 0x17, 0x81, 0x68, 0xa9, 0xc3, 0xdb, 0x71, 0xe6, 0x03, + 0x51, 0x1b, 0xee, 0xf5, 0x99, 0x11, 0x0e, 0x27, 0x59, 0x5c, 0x3b, 0x67, 0x38, 0xb9, 0xdc, 0xe7, 0xb5, 0x13, 0x13, + 0xac, 0xbd, 0xc3, 0x53, 0x05, 0xf4, 0x68, 0x70, 0xaa, 0x58, 0x1a, 0x02, 0x31, 0x13, 0xc0, 0x9b, 0x39, 0x3c, 0xda, + 0x02, 0x9c, 0x8f, 0xd6, 0x38, 0xf8, 0x4a, 0x6b, 0x5d, 0x6d, 0x2a, 0x51, 0xd6, 0x6b, 0xdc, 0x9f, 0x66, 0x78, 0x94, + 0xe1, 0x79, 0x36, 0x08, 0x8e, 0x9b, 0x59, 0x16, 0x9a, 0x74, 0xad, 0x56, 0x4f, 0x9d, 0x19, 0x21, 0xb2, 0x3f, 0x2d, + 0xfd, 0x41, 0x3d, 0x40, 0xf8, 0x14, 0xb2, 0x80, 0x96, 0xf4, 0xdc, 0xdf, 0x86, 0x7d, 0xa7, 0x1a, 0x35, 0x62, 0x9e, + 0x58, 0x32, 0xd2, 0xf3, 0x3f, 0xca, 0x2c, 0xdb, 0x5a, 0x23, 0x9a, 0xdf, 0xee, 0x45, 0x0d, 0xdf, 0x5e, 0xa0, 0x65, + 0x2b, 0xcd, 0x76, 0x00, 0x51, 0xac, 0x71, 0x92, 0x0e, 0xd6, 0x48, 0xae, 0x56, 0xb1, 0x4d, 0x21, 0x3c, 0x99, 0x31, + 0xaa, 0x16, 0x85, 0x79, 0xba, 0x2d, 0x56, 0x28, 0x31, 0xfc, 0x2e, 0x76, 0x36, 0xa2, 0xf0, 0x52, 0x9a, 0x04, 0xc3, + 0x8d, 0x58, 0x10, 0x59, 0x13, 0xb9, 0x87, 0x59, 0x65, 0x19, 0x24, 0x88, 0x30, 0x22, 0xbf, 0xbd, 0x2e, 0x15, 0xf6, + 0x71, 0x38, 0xfb, 0xc7, 0xf8, 0x02, 0xc2, 0xcd, 0xdb, 0x84, 0x16, 0x43, 0x3a, 0x01, 0x36, 0x16, 0xe2, 0x10, 0x6e, + 0x25, 0xac, 0x56, 0xfd, 0x41, 0x57, 0x18, 0xf2, 0xec, 0x9e, 0xae, 0x2b, 0x1b, 0xda, 0xdd, 0x00, 0x5c, 0x75, 0x5b, + 0x6a, 0xae, 0x8d, 0xee, 0x87, 0x9a, 0xd7, 0xb5, 0xb8, 0x4b, 0x72, 0x0f, 0x64, 0x54, 0x6f, 0x60, 0xd7, 0x2c, 0xc0, + 0x4d, 0xe8, 0x2a, 0x3c, 0xc2, 0x0b, 0x6b, 0xc3, 0x69, 0x9e, 0x52, 0xa2, 0xe6, 0x05, 0x25, 0x78, 0xb8, 0x99, 0xb0, + 0x7e, 0x36, 0xc0, 0x23, 0x1f, 0x68, 0x7b, 0xff, 0x6d, 0x3c, 0x42, 0xa8, 0x20, 0x06, 0xa6, 0xd6, 0x65, 0x7b, 0x54, + 0xd9, 0xed, 0x9b, 0x4c, 0xc3, 0x30, 0x18, 0x23, 0xe6, 0x51, 0x68, 0xc4, 0x9c, 0x37, 0x1a, 0x68, 0x41, 0x46, 0x60, + 0xc4, 0xbc, 0x08, 0x5a, 0x5b, 0xd8, 0x67, 0x36, 0x83, 0xf6, 0x16, 0x08, 0x75, 0x39, 0xd0, 0x34, 0x0d, 0x0f, 0x6a, + 0x54, 0x0f, 0x9a, 0xfb, 0xe7, 0x9d, 0x8e, 0x3a, 0xa0, 0x48, 0x18, 0x5f, 0xfa, 0x49, 0x58, 0xd7, 0x70, 0x3b, 0xee, + 0xb1, 0x19, 0xb7, 0xb3, 0x6d, 0x50, 0x7d, 0xd9, 0xcf, 0x06, 0x83, 0xae, 0xf4, 0x56, 0x12, 0x2d, 0x3c, 0xae, 0x9e, + 0xe0, 0xa8, 0x16, 0xef, 0x8b, 0xde, 0xbc, 0xf2, 0xe6, 0xfe, 0x65, 0xcf, 0xcd, 0xf3, 0x18, 0x38, 0xa0, 0x7d, 0xb8, + 0x1f, 0xaa, 0xe2, 0x83, 0x1d, 0x75, 0x20, 0x0a, 0x5a, 0xda, 0xaa, 0x09, 0xa4, 0xd6, 0xcc, 0x2e, 0xd6, 0x4d, 0x85, + 0x0e, 0x05, 0x84, 0x21, 0x53, 0x55, 0x77, 0x77, 0x2a, 0x50, 0x0d, 0x71, 0x38, 0xf5, 0x1f, 0x5b, 0x23, 0xd6, 0x38, + 0xea, 0x8c, 0x22, 0x63, 0x24, 0x69, 0x97, 0x0f, 0x5e, 0xdd, 0x01, 0x2b, 0x01, 0x1f, 0xfd, 0xd8, 0x24, 0x19, 0x43, + 0x82, 0xb7, 0x2c, 0xd3, 0x86, 0x0f, 0xe1, 0x0e, 0x41, 0x79, 0x62, 0x63, 0x6d, 0xba, 0x4a, 0x16, 0x72, 0x55, 0x97, + 0xd7, 0x01, 0x7a, 0xde, 0x95, 0xbf, 0xb1, 0xe1, 0xc8, 0x82, 0x81, 0x65, 0x5b, 0xfb, 0x04, 0x3c, 0xf2, 0x71, 0x85, + 0x20, 0x7e, 0x29, 0x74, 0x62, 0x22, 0x45, 0x5f, 0xc1, 0x06, 0xc5, 0x73, 0x70, 0x10, 0x74, 0x12, 0x1c, 0x06, 0xef, + 0x32, 0xab, 0x49, 0x36, 0xb8, 0x35, 0x23, 0xf1, 0x7c, 0xb5, 0x6a, 0xa1, 0xc3, 0x7f, 0xcc, 0x63, 0xc8, 0xe3, 0x52, + 0xe1, 0x3e, 0xae, 0x14, 0xee, 0x60, 0x09, 0x48, 0xc6, 0x81, 0xae, 0x1d, 0xcb, 0x50, 0x8d, 0x0e, 0x71, 0xba, 0x5f, + 0x40, 0xd4, 0x66, 0x77, 0x2c, 0x81, 0x9e, 0x7d, 0xab, 0x80, 0xd5, 0xb5, 0x97, 0x25, 0x90, 0x11, 0xdc, 0xfd, 0x26, + 0x30, 0x2a, 0x44, 0xe3, 0xf3, 0x67, 0xde, 0x53, 0xe0, 0x89, 0xf3, 0xe7, 0x9a, 0x19, 0xd6, 0xbd, 0xa0, 0x37, 0xa6, + 0xf9, 0x78, 0x8c, 0x9b, 0x63, 0x0b, 0xce, 0xa3, 0x0e, 0xfc, 0xb4, 0x10, 0x3d, 0xea, 0x60, 0x97, 0x8a, 0xc7, 0x25, + 0x90, 0x43, 0xf4, 0x74, 0x06, 0x52, 0xc0, 0x4a, 0xc7, 0x56, 0x8b, 0x34, 0x41, 0xab, 0xd5, 0xe4, 0x82, 0xb4, 0x10, + 0x5a, 0xaa, 0x1b, 0xae, 0xb3, 0x29, 0xf8, 0x48, 0x83, 0x62, 0xe0, 0x0d, 0xd5, 0xd3, 0x18, 0xe1, 0x31, 0x5a, 0x8e, + 0xd8, 0x98, 0x2e, 0x72, 0x9d, 0xaa, 0x1e, 0x4f, 0x6c, 0x28, 0x5b, 0x66, 0x23, 0xc1, 0x1d, 0x75, 0xf0, 0xc4, 0xf0, + 0x97, 0x8f, 0x8c, 0x39, 0x48, 0x91, 0x99, 0xe4, 0x89, 0x49, 0xc0, 0x3c, 0xc9, 0x72, 0xa9, 0x98, 0x6d, 0xa6, 0x6b, + 0x6d, 0xcb, 0x21, 0x18, 0x76, 0xa4, 0x0b, 0x6e, 0xac, 0x28, 0xa3, 0x74, 0x4a, 0x54, 0x4f, 0x1d, 0x75, 0xd2, 0x09, + 0xe6, 0x09, 0x70, 0x7a, 0xef, 0x64, 0xcc, 0x1a, 0xe5, 0xad, 0xe8, 0x0c, 0x1d, 0x4e, 0xb1, 0xa8, 0x2e, 0x51, 0x67, + 0xe8, 0x70, 0x82, 0xf0, 0xac, 0x41, 0x72, 0x05, 0x1e, 0xc3, 0x5c, 0xfc, 0x1f, 0x29, 0xff, 0xcd, 0x61, 0x43, 0xd0, + 0xe5, 0xb7, 0xb0, 0x53, 0xd8, 0x28, 0x4a, 0x73, 0x02, 0x5e, 0x8b, 0xed, 0x33, 0x9c, 0x91, 0x49, 0x33, 0xf7, 0x01, + 0xf7, 0x4c, 0x2b, 0x8d, 0x5b, 0x8d, 0x0e, 0x33, 0x3c, 0xda, 0x4c, 0x8a, 0xcd, 0x5c, 0x9b, 0x79, 0x9a, 0xc1, 0xf9, + 0x5e, 0x8d, 0xc2, 0x95, 0x5f, 0x6c, 0x26, 0x85, 0xe5, 0x1d, 0x70, 0x9b, 0x23, 0x2c, 0x9a, 0x14, 0xe7, 0x78, 0xd6, + 0xfc, 0x8a, 0x67, 0xcd, 0x0f, 0x65, 0x46, 0x63, 0x81, 0x05, 0x04, 0xef, 0x83, 0x44, 0x3c, 0xab, 0x92, 0x47, 0x58, + 0x34, 0x4c, 0x79, 0x3c, 0x6b, 0x54, 0xa5, 0x9b, 0x0b, 0x2c, 0x1a, 0xa6, 0x74, 0xe3, 0x03, 0x9e, 0x35, 0xbe, 0xfe, + 0x8b, 0x49, 0x47, 0x29, 0xa0, 0xcb, 0x1c, 0x2d, 0x33, 0x3b, 0xc4, 0xab, 0xdf, 0xde, 0xbe, 0x6b, 0x5f, 0x77, 0x0e, + 0x27, 0xd8, 0xaf, 0x5f, 0x66, 0x70, 0x2c, 0xd3, 0x31, 0x6b, 0x02, 0x44, 0x33, 0xdc, 0x39, 0x9c, 0xe2, 0xce, 0x61, + 0xe6, 0x9a, 0x5a, 0xcf, 0x1a, 0xe4, 0x56, 0x87, 0x50, 0xd4, 0x51, 0x1a, 0xc2, 0xc7, 0x4f, 0x36, 0x9d, 0xa0, 0x1a, + 0x28, 0xd1, 0xe1, 0xa4, 0x06, 0x2a, 0xf8, 0x5e, 0xd4, 0xbe, 0xab, 0x7a, 0x15, 0x06, 0x59, 0x28, 0xa1, 0x70, 0xcd, + 0x0d, 0x78, 0x6a, 0x29, 0x06, 0x32, 0x61, 0x8a, 0x05, 0xca, 0x77, 0x40, 0x61, 0x94, 0x27, 0x66, 0xe8, 0xc1, 0x74, + 0x4c, 0xe2, 0xff, 0xcf, 0x93, 0x29, 0x87, 0x5e, 0x6e, 0x99, 0xad, 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, + 0x3f, 0xac, 0xa0, 0xfb, 0x62, 0xab, 0xfb, 0xc2, 0x74, 0x1f, 0x36, 0x6d, 0x54, 0x39, 0x69, 0x55, 0xc9, 0x92, 0xff, + 0x3a, 0xdd, 0xda, 0x02, 0x8d, 0xa8, 0xd1, 0xb3, 0x49, 0xd8, 0xe0, 0x7e, 0x3b, 0xdd, 0x81, 0xcc, 0x6b, 0x6e, 0xdf, + 0xe6, 0x84, 0xc3, 0x37, 0xb8, 0x53, 0xbd, 0x6c, 0x81, 0xf7, 0xa6, 0x32, 0xfa, 0xca, 0x38, 0xb4, 0x1c, 0x2c, 0x36, + 0x4d, 0xb9, 0x8d, 0xb1, 0x74, 0x72, 0x8a, 0x8d, 0x2b, 0x22, 0x54, 0xba, 0xbd, 0x04, 0xa5, 0xf8, 0x58, 0x37, 0x99, + 0xf9, 0xba, 0xd0, 0x89, 0xb9, 0x84, 0x6a, 0x98, 0xcf, 0xbb, 0x4b, 0x9d, 0x68, 0x39, 0xb7, 0x79, 0x77, 0x17, 0xd0, + 0x27, 0x68, 0x58, 0x1b, 0x81, 0xdd, 0x3e, 0x2b, 0x9c, 0x7e, 0xa7, 0x3a, 0x04, 0xc3, 0x03, 0xc8, 0x91, 0x16, 0xdb, + 0x07, 0x36, 0xad, 0x61, 0xd7, 0x45, 0xb3, 0x4c, 0xb4, 0xad, 0x36, 0x4d, 0xae, 0xdd, 0xc3, 0x7c, 0x1e, 0xf2, 0x14, + 0xbc, 0xb0, 0xfa, 0xf1, 0x1d, 0xec, 0xc6, 0x6d, 0x8d, 0x91, 0xa8, 0x2b, 0x99, 0x4a, 0xe8, 0x27, 0xb7, 0x98, 0x25, + 0x77, 0xc6, 0x8b, 0x51, 0x19, 0x7f, 0x1f, 0x13, 0xa9, 0x3e, 0xaa, 0x24, 0x39, 0xb0, 0xec, 0x6f, 0xb0, 0xe4, 0x16, + 0xcc, 0x13, 0xcb, 0x6a, 0x12, 0xeb, 0xe4, 0x2e, 0x58, 0x44, 0x69, 0x1a, 0x59, 0x1b, 0x06, 0xd4, 0x34, 0x63, 0xd5, + 0x83, 0xfb, 0x10, 0xe8, 0xa1, 0x57, 0x96, 0xd2, 0xae, 0xb3, 0xb4, 0xd6, 0xbd, 0x36, 0xdd, 0x6f, 0x0e, 0x28, 0xe0, + 0x0b, 0x03, 0xae, 0xe9, 0x5f, 0x4d, 0x22, 0x19, 0xb2, 0xaf, 0x9c, 0x15, 0x8f, 0x17, 0x85, 0xc1, 0x34, 0xd1, 0xd3, + 0x49, 0x36, 0x6f, 0x83, 0xa9, 0x5e, 0x36, 0xef, 0xdc, 0x62, 0xf7, 0x7d, 0x67, 0xbf, 0xef, 0xb0, 0xe8, 0x31, 0x93, + 0x91, 0x32, 0x53, 0xcc, 0x7f, 0xdf, 0xd9, 0xef, 0x3b, 0xbc, 0x3d, 0x98, 0x1b, 0x7f, 0xa1, 0x58, 0xb2, 0x33, 0x5c, + 0x82, 0x09, 0x79, 0xc0, 0xdd, 0xd4, 0xb2, 0x4c, 0x10, 0xd8, 0x5a, 0x02, 0xc4, 0xf9, 0x7c, 0x1a, 0x57, 0xbc, 0x1a, + 0x02, 0xee, 0xd3, 0xbb, 0xb6, 0x57, 0xa9, 0xc0, 0x63, 0x82, 0x46, 0xc4, 0xc4, 0xb6, 0x31, 0xef, 0x6a, 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, 0x79, 0x13, 0x79, 0xec, 0x0b, 0xb3, 0x9f, + 0x99, 0x9e, 0x16, 0x72, 0x31, 0x99, 0x82, 0x0f, 0x2d, 0xb0, 0x0c, 0x85, 0xa9, 0x57, 0xd9, 0xfa, 0xd7, 0x24, 0x37, + 0x01, 0x14, 0x4e, 0x37, 0x65, 0x42, 0x33, 0xbd, 0xa0, 0xb9, 0xb1, 0x24, 0xe5, 0x62, 0xf2, 0x48, 0xde, 0xbe, 0x04, + 0xec, 0xa6, 0x44, 0x37, 0x76, 0xe4, 0xbd, 0x85, 0x1d, 0x80, 0x33, 0xc2, 0x76, 0x55, 0x7c, 0xa8, 0x40, 0xe7, 0x8f, + 0x73, 0xc2, 0x76, 0x55, 0x7d, 0xc2, 0x6c, 0xf6, 0x94, 0x6c, 0x0c, 0xb7, 0x17, 0x67, 0x8d, 0x1c, 0x1d, 0x75, 0xd2, + 0xbc, 0xeb, 0x89, 0x81, 0x05, 0x68, 0x00, 0xdc, 0xad, 0xed, 0x59, 0xde, 0xdd, 0x10, 0xd0, 0xbb, 0x64, 0xd2, 0x5e, + 0x97, 0x9b, 0x94, 0xd5, 0xaa, 0x53, 0x51, 0xc1, 0x02, 0x4f, 0x83, 0xbd, 0x40, 0xed, 0xd7, 0x0e, 0x8a, 0x73, 0x95, + 0x6d, 0x9a, 0x9e, 0x97, 0x7d, 0x77, 0x77, 0x2c, 0x32, 0xb6, 0x69, 0x6f, 0x77, 0x10, 0x09, 0xcb, 0x09, 0xeb, 0x80, + 0x13, 0xae, 0x6a, 0x07, 0x04, 0xe8, 0x3a, 0x10, 0xb9, 0xb1, 0x24, 0xcb, 0x75, 0x65, 0x74, 0x1f, 0xf8, 0xdd, 0x52, + 0x22, 0xdd, 0x68, 0x4b, 0x82, 0xe9, 0x13, 0x8c, 0x9a, 0xce, 0x3c, 0x8a, 0x5c, 0x7b, 0xef, 0x77, 0x53, 0xb4, 0xf5, + 0xaf, 0x0f, 0x63, 0xb3, 0x3d, 0x4c, 0x0c, 0x65, 0x10, 0x03, 0xbd, 0x8f, 0x78, 0xb7, 0xd1, 0xc8, 0x10, 0x28, 0x64, + 0xb2, 0x01, 0x96, 0x89, 0xd7, 0xa2, 0x1f, 0x1c, 0x18, 0x78, 0x54, 0x09, 0x08, 0x53, 0x10, 0x42, 0xc2, 0xae, 0x0d, + 0xc2, 0x86, 0xcb, 0x55, 0xcb, 0x85, 0x8d, 0x54, 0x1b, 0x3a, 0xf8, 0x7f, 0x85, 0xcb, 0x56, 0xcf, 0x2c, 0x17, 0xc5, + 0xe0, 0x66, 0x6e, 0xc0, 0x22, 0x41, 0x7a, 0xb4, 0xd9, 0x1e, 0x8a, 0xbb, 0x73, 0xb1, 0xd9, 0x10, 0x90, 0x98, 0xc3, + 0x04, 0x45, 0xc3, 0xb9, 0x31, 0xc6, 0x2a, 0xa9, 0xb4, 0xac, 0x35, 0x89, 0x39, 0xf0, 0xa5, 0x0b, 0xd7, 0x7d, 0x79, + 0x9b, 0x32, 0x7c, 0x97, 0x0a, 0x7c, 0x03, 0x9e, 0x34, 0xa9, 0xc4, 0xee, 0xf1, 0x82, 0x62, 0x4d, 0x74, 0xd7, 0xb3, + 0xb7, 0x05, 0xac, 0xb3, 0xd9, 0x23, 0x22, 0xf8, 0x5d, 0xfd, 0x6a, 0x83, 0xef, 0x16, 0xfe, 0x0a, 0xd6, 0xcf, 0xc1, + 0x49, 0x8a, 0x45, 0x43, 0x36, 0x0b, 0x77, 0x64, 0x40, 0xb9, 0x8a, 0x5f, 0x0e, 0x53, 0xb7, 0x8a, 0xe1, 0xda, 0xc7, + 0x57, 0xfc, 0x61, 0xa3, 0xdd, 0x86, 0x2a, 0x8b, 0xdb, 0xbd, 0x29, 0x1a, 0xb2, 0x6a, 0x7a, 0x47, 0xe6, 0x46, 0x4a, + 0xfd, 0xeb, 0x03, 0x6e, 0x6d, 0xb5, 0xef, 0xa7, 0xf9, 0xd6, 0xa3, 0x73, 0xd5, 0xb4, 0x4f, 0xad, 0x15, 0xc1, 0xc1, + 0xcf, 0x16, 0x6e, 0x6e, 0x0d, 0x38, 0x80, 0x9f, 0xbf, 0xa3, 0x79, 0x9c, 0x41, 0x74, 0x7a, 0xab, 0x19, 0x5f, 0xc5, + 0x7f, 0x8e, 0x1a, 0x71, 0x2f, 0xfd, 0x33, 0xf9, 0x73, 0xd4, 0x40, 0x3d, 0x14, 0xcf, 0x6f, 0x57, 0x6c, 0xb6, 0x82, + 0x60, 0x6b, 0xf7, 0x8e, 0xf0, 0xeb, 0xb0, 0x24, 0xd7, 0x34, 0xe7, 0xd9, 0xca, 0x3d, 0x45, 0xb7, 0x72, 0xef, 0xf4, + 0xac, 0xcc, 0xeb, 0x4a, 0xab, 0x58, 0x0e, 0x73, 0x08, 0x2c, 0x1c, 0xef, 0x35, 0x7b, 0xfd, 0x56, 0xf3, 0xc1, 0xc0, + 0xfe, 0x6b, 0x22, 0xdc, 0xa3, 0x5a, 0xc4, 0xb6, 0x37, 0x1b, 0x5b, 0x3f, 0x06, 0xc3, 0x0e, 0x08, 0x05, 0x0e, 0x72, + 0xe9, 0xe3, 0x0c, 0x59, 0xdf, 0x93, 0xd5, 0x8a, 0xb9, 0x68, 0xd6, 0x4e, 0x83, 0x5f, 0xc6, 0x66, 0x3a, 0x6c, 0x27, + 0x9d, 0xae, 0x17, 0x63, 0x49, 0x03, 0x22, 0x4d, 0x63, 0x06, 0x81, 0xa4, 0x96, 0x86, 0xc3, 0x9a, 0xdf, 0x46, 0x69, + 0x75, 0x7f, 0x04, 0x29, 0x3f, 0x44, 0x29, 0x3f, 0x22, 0x10, 0x40, 0xdb, 0x32, 0x47, 0x65, 0x43, 0xde, 0x77, 0xe9, + 0x9e, 0x71, 0x66, 0x68, 0xf0, 0xd5, 0xaa, 0x55, 0x0d, 0x53, 0x14, 0xf5, 0x61, 0x2e, 0xd7, 0x58, 0x90, 0x37, 0xa0, + 0x6b, 0x56, 0x44, 0xf4, 0x42, 0x57, 0x79, 0x78, 0x89, 0x17, 0x4b, 0x02, 0x4e, 0xfa, 0x3d, 0xd1, 0x2b, 0xc8, 0xe5, + 0xc3, 0x18, 0x7c, 0xcc, 0x30, 0xef, 0xeb, 0x7e, 0x31, 0x18, 0xa0, 0xd4, 0x39, 0x9d, 0xa5, 0x26, 0xe2, 0x4a, 0xe0, + 0x97, 0x5c, 0x80, 0x5f, 0xb2, 0x42, 0xac, 0x5f, 0x0c, 0xc8, 0xbd, 0x2c, 0x96, 0xe0, 0x94, 0xbf, 0xc3, 0xe7, 0xf1, + 0x61, 0x68, 0x60, 0x6a, 0x86, 0x65, 0x2e, 0xb2, 0xc1, 0x62, 0xce, 0x5a, 0x02, 0xc1, 0xcd, 0x80, 0xbb, 0xd4, 0x86, + 0x44, 0x63, 0x0d, 0x14, 0xdd, 0x46, 0xa1, 0x99, 0xd1, 0xd3, 0xad, 0x36, 0xfa, 0x91, 0xc3, 0x0b, 0x73, 0x0d, 0x63, + 0x11, 0xc8, 0x5c, 0xae, 0x7a, 0xec, 0x2f, 0x3f, 0x6c, 0x56, 0x18, 0xbc, 0xc2, 0x98, 0xec, 0x94, 0x56, 0x89, 0x66, + 0x7c, 0x95, 0x27, 0x8e, 0x21, 0xc8, 0xc4, 0x52, 0xe9, 0x86, 0x63, 0xe2, 0x4a, 0xfa, 0x4c, 0x0c, 0xd9, 0x6e, 0x78, + 0x66, 0x2e, 0x74, 0xb3, 0xfd, 0xc3, 0xb9, 0x9d, 0x73, 0xc2, 0x8d, 0x56, 0xd2, 0x68, 0xa3, 0x9e, 0x19, 0xaa, 0xea, + 0x82, 0xf9, 0x3d, 0x74, 0x5a, 0x5a, 0xec, 0x5c, 0xbd, 0xbb, 0xe1, 0xbb, 0x70, 0x65, 0xfc, 0x2d, 0x56, 0x85, 0x56, + 0x64, 0xb8, 0xdd, 0x42, 0xde, 0x9c, 0xe9, 0xa1, 0x57, 0xe4, 0x42, 0x75, 0xf8, 0x8b, 0xba, 0xc2, 0x3c, 0x15, 0x19, + 0x35, 0x84, 0x47, 0xbf, 0xd7, 0x19, 0x28, 0xff, 0x60, 0x62, 0x32, 0x67, 0xc9, 0x0d, 0x2d, 0x44, 0xfc, 0xe3, 0x0b, + 0x61, 0x62, 0x55, 0xed, 0xc1, 0x40, 0xf6, 0x4c, 0xc5, 0x3d, 0xb8, 0x35, 0xe1, 0x63, 0xce, 0x46, 0xe9, 0x5e, 0xf4, + 0x63, 0x43, 0x34, 0x7e, 0x8c, 0x7e, 0x04, 0x77, 0x67, 0xf7, 0x2e, 0x61, 0x19, 0x17, 0xc2, 0xdf, 0x63, 0x3d, 0x2c, + 0x55, 0xca, 0x58, 0x7b, 0xdd, 0x72, 0x78, 0x21, 0xf5, 0x26, 0x8b, 0x1f, 0x3a, 0x62, 0x6d, 0x53, 0xb0, 0x0e, 0x29, + 0x29, 0x3c, 0xbb, 0x62, 0x6e, 0xb5, 0x98, 0xbb, 0xd4, 0x12, 0xfe, 0xfa, 0xea, 0x61, 0xa9, 0x82, 0x86, 0x83, 0xd0, + 0x95, 0xb6, 0x90, 0x00, 0x03, 0x97, 0xd2, 0xa7, 0xd3, 0x9d, 0x49, 0x64, 0x96, 0xc5, 0xf0, 0xee, 0x41, 0x05, 0xf3, + 0xdf, 0xd9, 0x46, 0x58, 0x15, 0xb8, 0x5c, 0xa9, 0xa2, 0x5e, 0x4a, 0x02, 0x01, 0xe8, 0x4b, 0xef, 0x41, 0x79, 0x51, + 0x74, 0x1b, 0x0d, 0x09, 0x5a, 0x58, 0x6a, 0xae, 0x55, 0x31, 0xdd, 0x0f, 0xdf, 0xd3, 0x0b, 0x3e, 0xbc, 0x43, 0xda, + 0xc6, 0xa3, 0x96, 0x94, 0x50, 0xbb, 0x83, 0xf6, 0xc1, 0x2a, 0x3b, 0x28, 0xff, 0x36, 0xa6, 0xc8, 0xe6, 0xf7, 0xd9, + 0x0f, 0xd4, 0x75, 0x38, 0x70, 0x05, 0xab, 0x5e, 0xca, 0x28, 0x18, 0xc2, 0x3e, 0x60, 0x1f, 0x8b, 0x24, 0xa3, 0xd9, + 0x94, 0x81, 0xba, 0xdf, 0x16, 0xad, 0xe6, 0xf6, 0xa4, 0xee, 0x37, 0x64, 0x9c, 0x7d, 0x84, 0x71, 0xf6, 0x51, 0xe0, + 0xc5, 0x22, 0xc9, 0x1f, 0x32, 0xd6, 0x38, 0x56, 0x4d, 0x81, 0x8e, 0x3a, 0xc0, 0x9d, 0x81, 0x03, 0x0f, 0xd8, 0xa2, + 0x1c, 0x1c, 0x50, 0x67, 0x71, 0x4f, 0x1b, 0x99, 0xf7, 0xf6, 0x84, 0xda, 0x45, 0x2c, 0x70, 0xb3, 0x66, 0xa6, 0x05, + 0xad, 0x15, 0xc6, 0x79, 0x3c, 0xe0, 0x6d, 0x9e, 0xd5, 0xe2, 0x27, 0x6c, 0x58, 0x53, 0xd5, 0x6f, 0xa0, 0x39, 0xaa, + 0x05, 0xb9, 0x79, 0x62, 0xbc, 0x55, 0x49, 0x3f, 0x8a, 0x06, 0x96, 0x53, 0x21, 0x86, 0x64, 0xf4, 0x5b, 0x83, 0xe0, + 0x56, 0x7b, 0xb5, 0xe2, 0x1e, 0xf1, 0x45, 0xcd, 0x5b, 0xcd, 0xdc, 0x02, 0xd0, 0x22, 0x8e, 0xca, 0x7b, 0x93, 0x08, + 0xbc, 0x6f, 0xcb, 0x08, 0x69, 0xcb, 0xbe, 0x7d, 0x34, 0xb1, 0x54, 0x6c, 0xbe, 0xa3, 0x93, 0x41, 0x1a, 0xd9, 0x11, + 0x45, 0xf8, 0xba, 0x84, 0x24, 0x5c, 0x25, 0x5d, 0xab, 0x4c, 0xce, 0x99, 0x4a, 0x39, 0xbe, 0x2e, 0xa4, 0xd4, 0x57, + 0xf6, 0x4b, 0xe2, 0xea, 0x4e, 0x46, 0xe0, 0xeb, 0x09, 0xd3, 0xef, 0x68, 0x31, 0x61, 0xe0, 0x57, 0xe4, 0x6f, 0xc7, + 0x52, 0x4a, 0x2e, 0x9f, 0x88, 0xb8, 0x4f, 0x31, 0xbc, 0xf8, 0x39, 0xc0, 0xda, 0x84, 0x40, 0x29, 0x71, 0x11, 0x2e, + 0x88, 0xde, 0x14, 0xf2, 0xf6, 0x2e, 0x2e, 0xb0, 0x73, 0x00, 0x2c, 0x9d, 0x26, 0x01, 0xfe, 0xe5, 0x63, 0x3e, 0x56, + 0x63, 0x4e, 0x8d, 0xae, 0xdf, 0xfd, 0x4e, 0xae, 0x81, 0xde, 0x96, 0x8e, 0x82, 0xfd, 0xd6, 0x00, 0x72, 0xe1, 0x2e, + 0x0c, 0x2e, 0xbe, 0xc2, 0xda, 0xb2, 0x30, 0xde, 0x58, 0x00, 0xbd, 0xbf, 0x33, 0xb0, 0x60, 0xc3, 0x1c, 0x53, 0x78, + 0x2e, 0x75, 0xc2, 0x74, 0x10, 0x15, 0xe4, 0x49, 0xf9, 0x20, 0x66, 0xad, 0xf6, 0x5b, 0x36, 0x86, 0x3b, 0x8c, 0xe4, + 0xdb, 0x85, 0x13, 0x07, 0x1e, 0x90, 0x69, 0x32, 0xdb, 0xec, 0x1b, 0x1f, 0x79, 0xe4, 0xf5, 0x38, 0xde, 0xd5, 0x52, + 0x98, 0x6f, 0x56, 0x74, 0x8d, 0x21, 0x14, 0x45, 0xd8, 0xef, 0x17, 0x15, 0x53, 0x54, 0x19, 0xb4, 0x41, 0xc3, 0xf2, + 0x46, 0xfc, 0x02, 0x67, 0x0c, 0xad, 0x17, 0xb2, 0x77, 0x74, 0xd6, 0xe1, 0xcc, 0x61, 0xc6, 0x94, 0xc0, 0xa8, 0xb4, + 0x2c, 0xe8, 0x04, 0x1c, 0x9d, 0xab, 0x0f, 0xa2, 0xe2, 0xea, 0x58, 0x01, 0x78, 0x92, 0x29, 0xfc, 0x93, 0x6f, 0x82, + 0x75, 0xbf, 0x55, 0x33, 0x4c, 0xfd, 0x45, 0x6f, 0xbb, 0x96, 0x2f, 0x43, 0x1c, 0x69, 0x63, 0x08, 0xad, 0x73, 0x7b, + 0x07, 0x28, 0xe2, 0x82, 0x5e, 0xa4, 0x1a, 0x5f, 0xab, 0xc5, 0xd0, 0xac, 0xaf, 0x71, 0x1d, 0xd3, 0x06, 0x51, 0xac, + 0xbb, 0x26, 0xbe, 0xae, 0xde, 0x1f, 0x55, 0xa9, 0x82, 0x33, 0x48, 0x20, 0xac, 0xca, 0xcb, 0x86, 0x54, 0x92, 0x4b, + 0xd3, 0xa9, 0x34, 0x9d, 0x56, 0x08, 0xe5, 0xd2, 0x93, 0xf2, 0xfe, 0x15, 0x42, 0x18, 0x98, 0x32, 0x3b, 0xb0, 0x4a, + 0x6d, 0x61, 0x15, 0xbc, 0x7a, 0xb1, 0x81, 0x55, 0x12, 0x8e, 0xe7, 0x12, 0x8d, 0x8a, 0x0a, 0x87, 0x0c, 0xe9, 0x0b, + 0xb1, 0x08, 0x12, 0x00, 0x8b, 0xde, 0x65, 0x2e, 0xef, 0x7b, 0x38, 0x14, 0xf6, 0x24, 0x93, 0x70, 0xba, 0x09, 0xcd, + 0xe1, 0x61, 0x5a, 0xd5, 0xf3, 0x08, 0x01, 0x4b, 0xcf, 0x31, 0x3c, 0x48, 0xfc, 0xfd, 0x87, 0x50, 0x9d, 0x05, 0x79, + 0xfa, 0x2f, 0x51, 0x12, 0x1a, 0xfb, 0xcf, 0xf1, 0xd0, 0x21, 0x61, 0x38, 0xf0, 0xcd, 0x11, 0x56, 0x38, 0xb8, 0x55, + 0xc4, 0x67, 0x70, 0x87, 0x8f, 0x75, 0xe8, 0x01, 0x60, 0x09, 0xc5, 0x21, 0xc8, 0x37, 0x50, 0xcc, 0xe0, 0x80, 0x26, + 0xcb, 0xf0, 0x02, 0x17, 0xac, 0x16, 0xca, 0xfb, 0xdb, 0x96, 0x97, 0xd2, 0x6a, 0x97, 0xbc, 0xc6, 0x1c, 0xa8, 0xfc, + 0x0c, 0x2f, 0x7c, 0x85, 0x79, 0x29, 0xd9, 0x7d, 0xe1, 0x6b, 0x07, 0xf4, 0x14, 0x02, 0x46, 0xba, 0xdf, 0x6b, 0xc2, + 0x3d, 0x45, 0x2f, 0x73, 0x71, 0xd8, 0x76, 0xd0, 0xbd, 0xc0, 0x5c, 0x5d, 0x55, 0x59, 0x73, 0x30, 0x85, 0x06, 0x07, + 0x55, 0x38, 0x23, 0x30, 0x57, 0x2f, 0xca, 0x82, 0x73, 0x10, 0xef, 0x7b, 0xc2, 0xe4, 0x94, 0xd1, 0x00, 0x5e, 0x64, + 0xe5, 0xa3, 0x53, 0x3d, 0x0e, 0x2e, 0xe3, 0x86, 0x4d, 0x7c, 0x21, 0x7c, 0x2a, 0xb0, 0x92, 0xd6, 0x38, 0x34, 0xa2, + 0x23, 0x3a, 0x07, 0xb3, 0x0d, 0xa0, 0xe0, 0xee, 0x7c, 0xd8, 0x58, 0xa8, 0xe0, 0x31, 0xd8, 0xda, 0xdb, 0xcd, 0x84, + 0x38, 0x93, 0xa6, 0xe0, 0x6e, 0xdb, 0x20, 0x83, 0x37, 0xbf, 0xfd, 0xb7, 0xc2, 0x22, 0xc1, 0x80, 0x4a, 0x4d, 0x12, + 0x84, 0x27, 0x28, 0x8d, 0x74, 0x2b, 0x37, 0x13, 0x48, 0x27, 0xa2, 0x66, 0xd4, 0xbd, 0x71, 0xbe, 0x3a, 0x6a, 0x20, + 0x2a, 0x6a, 0xa0, 0x02, 0x6a, 0x20, 0xeb, 0xdb, 0xbf, 0x80, 0x85, 0xb0, 0x11, 0xaa, 0x44, 0x10, 0x10, 0x61, 0xae, + 0x0d, 0x1f, 0x50, 0x24, 0x21, 0xe4, 0x0d, 0xa0, 0x62, 0x4a, 0x5e, 0x82, 0xd1, 0x38, 0xbc, 0xde, 0x03, 0xee, 0x97, + 0x96, 0x61, 0xf0, 0x9c, 0x82, 0xc9, 0x7f, 0xeb, 0xf3, 0xa1, 0x7a, 0xb9, 0x3a, 0x08, 0xe1, 0x17, 0x10, 0x2b, 0xc2, + 0xf1, 0x17, 0xbf, 0x00, 0xd9, 0x54, 0x58, 0x1e, 0x1c, 0x48, 0x10, 0xf8, 0x21, 0x8a, 0x70, 0xc0, 0x33, 0xbc, 0xcc, + 0x36, 0x88, 0x9e, 0x9f, 0x95, 0xaa, 0x66, 0x25, 0x83, 0x59, 0x15, 0x9e, 0xc6, 0xd1, 0x35, 0x61, 0x20, 0xb8, 0x50, + 0xbb, 0x6f, 0x10, 0x02, 0x65, 0xcb, 0x8d, 0xa1, 0x4b, 0x4f, 0xc1, 0x7c, 0x34, 0x8e, 0xde, 0x32, 0x78, 0xd2, 0xd6, + 0x98, 0xfc, 0x33, 0x6d, 0x1e, 0xb8, 0x4f, 0xf7, 0xa2, 0x46, 0xe0, 0xa4, 0x4e, 0x51, 0xf2, 0xb7, 0xe4, 0x22, 0x8e, + 0x9a, 0x97, 0x11, 0x6a, 0xc0, 0xbf, 0x0d, 0x8e, 0xba, 0x34, 0xa1, 0xa3, 0x91, 0x0f, 0x7e, 0x93, 0x11, 0xb3, 0xc9, + 0x56, 0x2b, 0x51, 0x11, 0xf4, 0xc4, 0x6e, 0x30, 0x60, 0x25, 0x5e, 0x00, 0xfb, 0x60, 0x39, 0x58, 0xf2, 0x4e, 0xc4, + 0xca, 0x9f, 0x52, 0x18, 0xac, 0x9e, 0x33, 0x84, 0x70, 0x16, 0xc4, 0x6c, 0xfc, 0xcf, 0x67, 0x1a, 0xae, 0x9f, 0x9f, + 0xaf, 0x63, 0x44, 0xa4, 0x0f, 0x22, 0x57, 0x63, 0x47, 0x44, 0x10, 0xb6, 0x4c, 0xf7, 0x5d, 0x99, 0x1f, 0xbc, 0x75, + 0xf5, 0xc0, 0x86, 0x8b, 0x03, 0x03, 0x6a, 0x14, 0x18, 0xad, 0xe0, 0x9c, 0x94, 0x03, 0x07, 0x25, 0x84, 0x66, 0x45, + 0x3c, 0x25, 0x97, 0x10, 0x09, 0x2f, 0x43, 0x5d, 0x30, 0x2c, 0x08, 0x24, 0xa8, 0x29, 0x48, 0x50, 0x99, 0xaf, 0x3d, + 0x82, 0x59, 0xe7, 0x66, 0xb6, 0x53, 0xd4, 0x75, 0x41, 0x7e, 0x7e, 0xd1, 0xf1, 0x08, 0x58, 0xda, 0x83, 0x83, 0x02, + 0x22, 0x88, 0x01, 0x05, 0x2f, 0x25, 0xc0, 0x40, 0x03, 0x5e, 0x6c, 0x68, 0xc0, 0xe7, 0xda, 0x78, 0x1d, 0x18, 0x5b, + 0x9f, 0x32, 0xc8, 0xc5, 0xb3, 0x6a, 0x4f, 0x13, 0x42, 0xf6, 0x5b, 0x3d, 0x9d, 0x6e, 0x47, 0x48, 0xec, 0x7d, 0xd4, + 0x26, 0xd0, 0x98, 0x23, 0xdd, 0xd5, 0xc6, 0xfc, 0x5a, 0xd3, 0x23, 0x56, 0x93, 0x90, 0x2e, 0x48, 0x97, 0xe7, 0xd3, + 0x9e, 0xc1, 0x15, 0xab, 0x34, 0x72, 0x70, 0x01, 0xfa, 0x6c, 0x40, 0x80, 0x02, 0x95, 0xa6, 0x12, 0x45, 0x11, 0x17, + 0x49, 0xc9, 0x86, 0x61, 0x06, 0x61, 0x0a, 0xab, 0x95, 0xa0, 0x1b, 0x6b, 0x00, 0xbc, 0x33, 0xb3, 0x7f, 0x4a, 0x1f, + 0x6c, 0xba, 0xf6, 0xe6, 0x11, 0x40, 0x40, 0xf6, 0xdb, 0x25, 0xbb, 0x2e, 0x36, 0x2a, 0xb3, 0xb0, 0x96, 0xb1, 0x95, + 0xdb, 0xf6, 0x18, 0x7b, 0x27, 0xb6, 0xf9, 0x04, 0x08, 0x51, 0x5b, 0x32, 0x8d, 0x10, 0x21, 0xb1, 0x88, 0x75, 0x6d, + 0xc8, 0x46, 0x1b, 0xda, 0x37, 0x4f, 0xc2, 0x43, 0xec, 0x03, 0x50, 0xbc, 0x39, 0x2e, 0xc1, 0x21, 0xbc, 0xf0, 0x08, + 0x7f, 0x0b, 0x2c, 0x52, 0x81, 0x19, 0x96, 0xab, 0x15, 0xd4, 0xf3, 0x78, 0x9f, 0x6d, 0x06, 0x27, 0x95, 0x1b, 0x63, + 0x97, 0x76, 0xe2, 0x71, 0xd9, 0x84, 0xc4, 0x19, 0xf4, 0xeb, 0x2b, 0xa2, 0xde, 0x7e, 0x3b, 0x7d, 0xe2, 0xdf, 0x2b, + 0x73, 0x3b, 0x10, 0x1b, 0xd6, 0x1b, 0xac, 0x3e, 0x80, 0x96, 0xbf, 0xca, 0xfc, 0x43, 0x65, 0xc1, 0x4d, 0x82, 0xda, + 0x5c, 0xc4, 0x2e, 0xeb, 0x22, 0x46, 0x6a, 0x8b, 0xbb, 0x43, 0x88, 0x7f, 0xb5, 0x15, 0xc5, 0x80, 0x27, 0x15, 0xff, + 0x1c, 0xa3, 0x2e, 0x84, 0xa2, 0xb6, 0x1e, 0x36, 0x40, 0x69, 0x97, 0xeb, 0x4a, 0x8c, 0x0c, 0x09, 0xe4, 0x5b, 0x17, + 0x5e, 0xd0, 0x9c, 0x44, 0x0a, 0xe4, 0xe4, 0x20, 0x2a, 0x69, 0xb6, 0x21, 0xcc, 0x75, 0xb7, 0x70, 0xcc, 0x5c, 0x6d, + 0xd0, 0x22, 0x7e, 0x01, 0xec, 0x0c, 0x37, 0x92, 0xa5, 0x03, 0x9f, 0xaa, 0x81, 0xcf, 0xaf, 0xb9, 0xa1, 0x28, 0x0a, + 0xf5, 0xde, 0xd9, 0x47, 0xe6, 0xe0, 0x77, 0x1a, 0x88, 0x8f, 0xd4, 0xe9, 0x48, 0x36, 0x42, 0xad, 0x39, 0x3b, 0x5e, + 0xb6, 0x19, 0x61, 0x50, 0xd8, 0xe8, 0x7d, 0x15, 0xb2, 0x8a, 0x9d, 0x9d, 0x8a, 0x60, 0x4e, 0x5f, 0x54, 0xe5, 0x9c, + 0xca, 0x2d, 0xa3, 0x5a, 0x6a, 0x1a, 0x20, 0xc2, 0x95, 0x4f, 0x24, 0xef, 0x33, 0x13, 0xfe, 0xc1, 0x60, 0x5c, 0x3d, + 0x52, 0xf8, 0xfb, 0x5d, 0xb1, 0x43, 0xb6, 0xa3, 0xc3, 0x6d, 0x04, 0xcd, 0x0b, 0x15, 0x3c, 0xe0, 0xa8, 0x64, 0x09, + 0x91, 0x22, 0x97, 0xfb, 0xaa, 0x66, 0xca, 0x76, 0x1d, 0x21, 0x84, 0xb4, 0xc7, 0x59, 0x37, 0xb4, 0x7a, 0xe8, 0x91, + 0x2a, 0xca, 0xe1, 0x16, 0xcd, 0x75, 0x01, 0x2a, 0x8c, 0x40, 0xba, 0xfc, 0xcc, 0xee, 0x52, 0x09, 0xd1, 0xcb, 0xd7, + 0x2e, 0x84, 0xb1, 0xb3, 0xb2, 0xc4, 0x85, 0x19, 0xb5, 0x0d, 0xa3, 0xeb, 0x36, 0x86, 0xb3, 0x81, 0x31, 0xd3, 0xa0, + 0xa4, 0x05, 0xa1, 0xae, 0xbb, 0xf4, 0x22, 0x33, 0x81, 0x1e, 0x73, 0x42, 0x1b, 0x0c, 0x4f, 0x89, 0x06, 0xcb, 0xa6, + 0x02, 0x2c, 0xf8, 0x96, 0x45, 0x6a, 0x6d, 0x36, 0x59, 0xfc, 0x51, 0xc7, 0xe6, 0x69, 0xbf, 0xbc, 0x62, 0x9e, 0x0b, + 0x47, 0xdd, 0x9e, 0x67, 0x3e, 0x1e, 0xdd, 0xd3, 0x37, 0x57, 0x2f, 0x5e, 0xbe, 0x7e, 0xb5, 0x5a, 0xb5, 0x59, 0xb3, + 0x7d, 0x82, 0x7f, 0xd2, 0x65, 0x3c, 0xd8, 0x32, 0x0a, 0xd0, 0xc1, 0xc1, 0x3e, 0x37, 0x2e, 0x3c, 0x9f, 0xf9, 0x1c, + 0xe2, 0x06, 0xe9, 0x01, 0xce, 0x8a, 0x32, 0x26, 0xc8, 0x6d, 0xd4, 0x8b, 0xee, 0x22, 0x50, 0x42, 0x55, 0xe4, 0xef, + 0xc3, 0xe6, 0xec, 0xf7, 0x20, 0x30, 0x11, 0xd4, 0x87, 0x08, 0x20, 0x10, 0xaf, 0x14, 0x17, 0x84, 0xf9, 0x04, 0x88, + 0xe2, 0xbd, 0x00, 0xce, 0xd4, 0x44, 0xad, 0x5a, 0xa8, 0xb8, 0x00, 0x92, 0x68, 0xc3, 0x51, 0xd2, 0x23, 0x13, 0xc0, + 0x1b, 0x82, 0x52, 0xda, 0x5f, 0xdd, 0xdc, 0xb9, 0x4b, 0xe5, 0xa8, 0xd7, 0x4a, 0x73, 0x3c, 0x75, 0x9f, 0x53, 0xf8, + 0x9c, 0x76, 0xfd, 0xe9, 0x20, 0x0e, 0x73, 0xbc, 0x20, 0xe2, 0xd0, 0x3f, 0x8b, 0xb8, 0x9c, 0x17, 0xec, 0x0b, 0x97, + 0x0b, 0x95, 0x2e, 0x6f, 0x53, 0x99, 0xdc, 0x36, 0x47, 0x87, 0x71, 0x91, 0xdc, 0x36, 0x55, 0x72, 0x8b, 0xf0, 0x5d, + 0x2a, 0x93, 0x3b, 0x9b, 0x72, 0xd7, 0x54, 0x70, 0xf3, 0x85, 0x05, 0x1c, 0x8a, 0xb6, 0x68, 0x63, 0xb1, 0x59, 0xd4, + 0xa6, 0xb8, 0xa2, 0x01, 0x06, 0xff, 0xbe, 0x63, 0xe3, 0x87, 0xe1, 0x4b, 0x70, 0x69, 0xd2, 0x44, 0x7e, 0x02, 0xe9, + 0xa7, 0x55, 0x19, 0xb8, 0x4f, 0x49, 0xab, 0x3b, 0xbd, 0x10, 0xcd, 0x76, 0xb7, 0xd1, 0x98, 0xc2, 0xde, 0xcd, 0x48, + 0xee, 0x8b, 0x4d, 0x1b, 0x26, 0xbe, 0xce, 0x7e, 0xb6, 0x5a, 0xed, 0xe7, 0xc8, 0x6c, 0xb8, 0x09, 0x8b, 0x75, 0x7f, + 0x3a, 0xc0, 0x2d, 0xfc, 0x3c, 0x43, 0x68, 0xc9, 0xfa, 0xd3, 0x01, 0x61, 0xfd, 0x69, 0xa3, 0x3d, 0xb0, 0x86, 0x76, + 0x66, 0x2b, 0xae, 0x21, 0x84, 0xe6, 0x74, 0x70, 0x64, 0x4a, 0x4a, 0x97, 0x6f, 0xbf, 0x68, 0x15, 0xd0, 0x4f, 0xd5, + 0x82, 0x97, 0x49, 0xdc, 0x81, 0xbe, 0xe8, 0x85, 0x7d, 0xba, 0xb5, 0x20, 0xc7, 0x47, 0x95, 0xab, 0x3d, 0x45, 0xd8, + 0xf4, 0xa4, 0x0e, 0x8b, 0x43, 0xd3, 0x8c, 0xeb, 0x52, 0xba, 0xef, 0x50, 0x33, 0xf2, 0xd1, 0xc1, 0x02, 0x10, 0xa4, + 0x82, 0x47, 0x56, 0xb8, 0x70, 0x4a, 0x21, 0x5c, 0x1c, 0x54, 0xb6, 0x60, 0x92, 0x93, 0x56, 0x37, 0x37, 0x96, 0xfe, + 0xb9, 0x8b, 0x68, 0x4a, 0x31, 0x25, 0x99, 0x2f, 0x99, 0x1b, 0xb0, 0xd0, 0x4d, 0xca, 0x33, 0x05, 0xbd, 0xd2, 0x00, + 0x8f, 0x08, 0xc4, 0x43, 0xea, 0x16, 0xc6, 0xc0, 0x2b, 0x9e, 0x36, 0x8b, 0x3e, 0x1b, 0xa0, 0xa3, 0x63, 0x4c, 0xfb, + 0x7f, 0x65, 0xf3, 0x36, 0x3c, 0x16, 0xf8, 0xd7, 0x80, 0x4c, 0x9b, 0xb2, 0x4c, 0x10, 0x90, 0x30, 0x6a, 0xca, 0x43, + 0xd8, 0x4b, 0x08, 0x67, 0xb6, 0x62, 0xd6, 0x67, 0x83, 0xe6, 0xb4, 0xac, 0xd8, 0xf1, 0x15, 0x1b, 0xb2, 0x4c, 0xb0, + 0x15, 0x1b, 0xae, 0x62, 0xf8, 0x3a, 0x83, 0x01, 0x41, 0x08, 0x00, 0x06, 0x00, 0xd0, 0x28, 0x88, 0xe6, 0x8b, 0x15, + 0xf1, 0x9b, 0xdd, 0xde, 0xe3, 0xb7, 0xc0, 0x02, 0xad, 0xb6, 0xff, 0x77, 0xa1, 0x0c, 0xd8, 0x53, 0x16, 0x26, 0x66, + 0x6e, 0x61, 0x55, 0x74, 0x00, 0x95, 0x12, 0x61, 0x0a, 0x03, 0x99, 0xfd, 0xcc, 0x40, 0x2d, 0xd0, 0x1a, 0xe4, 0x7d, + 0x3d, 0x68, 0x66, 0x70, 0xc4, 0xc0, 0x3b, 0x34, 0x64, 0x6a, 0x8c, 0x09, 0xe3, 0x1c, 0xa6, 0x98, 0x19, 0xf0, 0x4c, + 0xd3, 0xd6, 0x5a, 0x1a, 0x59, 0xae, 0x97, 0xf7, 0xfe, 0xd1, 0xb1, 0xea, 0x17, 0xcd, 0xf6, 0x00, 0xed, 0x13, 0x62, + 0x3f, 0x06, 0xb0, 0xc9, 0x5c, 0x6a, 0xc3, 0x7c, 0x1f, 0x75, 0x52, 0xfb, 0x09, 0x7f, 0x06, 0x6b, 0xb3, 0x03, 0x40, + 0x47, 0x86, 0xcd, 0xfa, 0xcb, 0x9a, 0xca, 0xeb, 0xe3, 0xce, 0x28, 0x95, 0xbb, 0xde, 0x9d, 0x0e, 0x34, 0xc5, 0xa1, + 0xb7, 0x1e, 0x2e, 0x1f, 0xea, 0x21, 0x60, 0xc6, 0x60, 0x6e, 0x99, 0xd1, 0xf7, 0x42, 0x24, 0x17, 0x44, 0x62, 0x69, + 0xb0, 0x86, 0xc1, 0xde, 0x3a, 0x38, 0x30, 0xd5, 0x58, 0x03, 0x9e, 0x27, 0x45, 0x20, 0x18, 0xf8, 0x08, 0xca, 0x80, + 0x26, 0xca, 0xdc, 0x86, 0x93, 0x8f, 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, 0xdd, 0xcd, 0x74, + 0xca, 0x66, 0x3a, 0xdb, 0xcd, 0x84, 0x9a, 0x99, 0x6f, 0x59, 0x45, 0x9a, 0x93, 0x35, 0x51, 0x73, 0x2a, 0x7e, 0xa2, + 0x73, 0xd0, 0x8e, 0x72, 0x7b, 0xaf, 0x0a, 0x27, 0x57, 0x4e, 0x2e, 0xf7, 0x73, 0x43, 0x5c, 0x91, 0xb9, 0x50, 0x87, + 0x00, 0x2f, 0x2f, 0xca, 0xc7, 0x07, 0xb8, 0x14, 0xbf, 0xca, 0x91, 0x8b, 0x72, 0x2a, 0xa4, 0x96, 0x82, 0x45, 0xc8, + 0xa0, 0xaa, 0x8b, 0x81, 0xbd, 0xb4, 0x7b, 0x4f, 0xf4, 0x78, 0xbf, 0x8a, 0x98, 0x37, 0x30, 0xcf, 0x7d, 0x7c, 0x4f, + 0x53, 0xec, 0xd4, 0xc4, 0x19, 0xf9, 0x90, 0xc5, 0x39, 0xc8, 0x66, 0xfd, 0xea, 0xb5, 0xdf, 0x46, 0x1b, 0x17, 0xcd, + 0x58, 0xf4, 0xcc, 0x13, 0x27, 0x3f, 0x14, 0xc6, 0x38, 0xc0, 0x3a, 0xfa, 0x23, 0x4c, 0x2d, 0xd8, 0xb3, 0xc4, 0x53, + 0xe8, 0xe4, 0xd6, 0xa6, 0xdd, 0x85, 0x69, 0x77, 0x26, 0xad, 0x03, 0xe5, 0x80, 0x34, 0xbb, 0x32, 0x9d, 0x3b, 0xff, + 0x7d, 0x07, 0x2f, 0xdd, 0xae, 0x21, 0x12, 0xf7, 0xfc, 0x91, 0x31, 0x86, 0x78, 0x03, 0x36, 0xa2, 0xea, 0xe0, 0xe0, + 0x0f, 0xe7, 0x7d, 0x5b, 0xc9, 0x7d, 0xdf, 0x0a, 0x07, 0xb6, 0xc1, 0x54, 0xba, 0xbc, 0x91, 0xcc, 0x16, 0x60, 0xd7, + 0xb9, 0xff, 0x8d, 0x78, 0xf8, 0x22, 0x64, 0x5a, 0xac, 0xab, 0xf8, 0x2b, 0x39, 0x2a, 0x3d, 0x44, 0x35, 0x44, 0x20, + 0xad, 0xac, 0x4b, 0x43, 0xd3, 0xd1, 0xab, 0x29, 0x1d, 0xc9, 0x9b, 0xb7, 0x52, 0xea, 0x81, 0x7d, 0x91, 0x5b, 0x27, + 0xf0, 0x68, 0x61, 0x8d, 0xa1, 0xb9, 0x2b, 0xbd, 0x93, 0x6c, 0x40, 0xd4, 0xfa, 0xb8, 0x43, 0x49, 0x24, 0x16, 0xd5, + 0x5d, 0x08, 0x87, 0xbb, 0x10, 0xcc, 0xcb, 0xa0, 0x6d, 0x10, 0xbb, 0xdd, 0x05, 0x6d, 0x03, 0xa7, 0x6e, 0x1b, 0xb8, + 0x3d, 0x18, 0x2c, 0xec, 0x7d, 0x78, 0x39, 0x96, 0x63, 0xe1, 0xaf, 0xc9, 0xec, 0x03, 0x40, 0xa0, 0xf6, 0x61, 0xc5, + 0x13, 0x07, 0x82, 0xc4, 0x19, 0x8e, 0xbe, 0xe7, 0xec, 0xc6, 0x5a, 0x0e, 0xcf, 0xe6, 0x0b, 0xcd, 0x46, 0xe6, 0x8e, + 0x1a, 0x54, 0x7c, 0x75, 0x3f, 0xaf, 0x9f, 0xb2, 0x9a, 0x6e, 0xfc, 0x1e, 0x84, 0x91, 0x70, 0xca, 0x0e, 0xa3, 0x90, + 0xb0, 0xc1, 0xac, 0xca, 0x78, 0x6d, 0xbf, 0x41, 0xbc, 0x07, 0x6d, 0xc2, 0x09, 0x16, 0xb5, 0x0b, 0xaa, 0x08, 0xdb, + 0x78, 0x63, 0x41, 0x94, 0x87, 0x37, 0x5b, 0x46, 0xd3, 0xcb, 0x35, 0x04, 0x3a, 0xee, 0x45, 0xcd, 0xa8, 0xc1, 0x52, + 0x17, 0x94, 0xd9, 0x47, 0x18, 0x57, 0x17, 0x27, 0x26, 0x4e, 0x7b, 0xa9, 0x57, 0xff, 0x2d, 0x03, 0x03, 0x7c, 0x01, + 0x5e, 0x62, 0x61, 0x74, 0xd7, 0xbe, 0x6e, 0x40, 0x7d, 0xd9, 0x60, 0x03, 0xb4, 0x5a, 0xb5, 0xca, 0x67, 0xa0, 0xdc, + 0x35, 0x97, 0xb0, 0xd7, 0x5c, 0xc2, 0x5d, 0x73, 0x09, 0x7f, 0xcd, 0x25, 0xcc, 0x35, 0x97, 0xf0, 0xd7, 0x5c, 0x1e, + 0x84, 0x9f, 0x82, 0x38, 0x8e, 0x31, 0x87, 0xb8, 0x8a, 0xda, 0x46, 0xc6, 0x83, 0x0b, 0xcf, 0x7d, 0x96, 0xa8, 0x72, + 0xf9, 0xc3, 0x18, 0x72, 0x5b, 0xb6, 0x12, 0xc6, 0x6d, 0x8a, 0x29, 0x88, 0x9c, 0x7e, 0x70, 0x50, 0xba, 0x3b, 0x83, + 0x8f, 0x7a, 0xca, 0xf1, 0xd2, 0x3a, 0xd1, 0xfe, 0x01, 0x3a, 0x79, 0xf3, 0xeb, 0x63, 0x2a, 0xd7, 0x44, 0x38, 0x93, + 0xfb, 0xfd, 0xb6, 0xa7, 0x14, 0x9f, 0x32, 0x13, 0x9e, 0x9c, 0x27, 0xda, 0x88, 0x20, 0x08, 0x51, 0xa2, 0x70, 0x46, + 0xa4, 0xdd, 0xef, 0xde, 0x15, 0xde, 0xa8, 0xa2, 0xbc, 0x59, 0xc9, 0xe3, 0x1c, 0x9c, 0xd8, 0x8d, 0x15, 0x06, 0xea, + 0x82, 0x0b, 0x41, 0x66, 0x12, 0xfe, 0x68, 0xe6, 0x96, 0x9c, 0x65, 0x65, 0xd2, 0xc7, 0x66, 0x6e, 0x08, 0x58, 0x41, + 0xf6, 0x3d, 0xcc, 0x96, 0xb7, 0x29, 0xc5, 0x77, 0x69, 0x86, 0x87, 0xf2, 0x36, 0x2d, 0x42, 0x5b, 0x10, 0x7f, 0xf1, + 0x37, 0x8e, 0x23, 0x41, 0xc1, 0xdf, 0x27, 0xe2, 0x62, 0x8f, 0x6f, 0x78, 0x01, 0x2e, 0x33, 0x63, 0x51, 0x9d, 0x32, + 0xfc, 0x0d, 0x4b, 0x78, 0x08, 0x4e, 0xa6, 0xb1, 0x22, 0xf7, 0x38, 0xb0, 0x13, 0x92, 0x80, 0xc3, 0xd5, 0xed, 0x15, + 0xff, 0x0a, 0x17, 0x5f, 0xa5, 0xb3, 0x65, 0x73, 0x28, 0x6f, 0x23, 0x5c, 0x90, 0x37, 0xf0, 0xfa, 0xd6, 0xff, 0xcb, + 0xde, 0xdb, 0x36, 0xb7, 0x6d, 0x64, 0xeb, 0xa2, 0x7f, 0x45, 0x62, 0xd9, 0x0c, 0x60, 0x36, 0x29, 0xca, 0xe7, 0xcc, + 0x54, 0x5d, 0x50, 0x6d, 0x96, 0x63, 0xc7, 0x13, 0x67, 0x22, 0xdb, 0x63, 0x79, 0x32, 0xc9, 0xb0, 0x78, 0x19, 0x08, + 0x68, 0x0a, 0x70, 0x40, 0x80, 0x01, 0x40, 0x89, 0x34, 0x89, 0xff, 0x7e, 0x6a, 0xad, 0xd5, 0xaf, 0x20, 0x28, 0x7b, + 0xf6, 0x3e, 0xfb, 0xd3, 0xbd, 0x5f, 0x6c, 0xb1, 0xd1, 0x68, 0xf4, 0x7b, 0xaf, 0x5e, 0x2f, 0xcf, 0xd3, 0x93, 0xb1, + 0xba, 0x3d, 0x70, 0xd6, 0xa5, 0x14, 0x1d, 0x6f, 0x8a, 0xc3, 0xdb, 0xf3, 0xd9, 0x7e, 0x1b, 0x44, 0x6c, 0x17, 0x64, + 0x58, 0xeb, 0xa4, 0xe1, 0x3f, 0xd1, 0xd6, 0xc1, 0x62, 0x84, 0xfd, 0x5f, 0xd6, 0x03, 0x2f, 0x21, 0x35, 0x14, 0xb8, + 0x18, 0x6c, 0x38, 0x5a, 0xdb, 0x65, 0x1a, 0xb8, 0xa9, 0x41, 0xaf, 0xef, 0x29, 0x44, 0x79, 0xc9, 0x68, 0x6e, 0x04, + 0xeb, 0xc6, 0x90, 0x8b, 0xc3, 0x71, 0xb3, 0x1c, 0xf2, 0x92, 0xa6, 0xd3, 0x20, 0x94, 0xee, 0x2c, 0x6b, 0x48, 0xa2, + 0xec, 0x83, 0x50, 0xbb, 0xb6, 0xec, 0xb7, 0x81, 0xed, 0xcb, 0x1f, 0x0d, 0x63, 0xff, 0x62, 0xf9, 0x4c, 0x48, 0x17, + 0xf1, 0x1c, 0x04, 0x51, 0xfb, 0x79, 0x36, 0xdc, 0xf8, 0x17, 0xeb, 0x67, 0x42, 0xf9, 0x8d, 0xe7, 0xb6, 0x1c, 0x52, + 0x67, 0x2d, 0x7c, 0x61, 0x3c, 0x3c, 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, 0x01, 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, 0xee, 0x52, 0xa6, 0xcb, 0x80, 0x4b, 0xfa, 0x5d, 0xaa, 0x94, 0xc2, 0x7f, 0x22, 0x00, 0x9d, 0x83, 0x7b, 0x7c, + 0x39, 0x06, 0xd2, 0x0c, 0x0b, 0xbf, 0x35, 0x3b, 0xbe, 0x26, 0xe1, 0x36, 0x09, 0x2e, 0x06, 0x38, 0x47, 0x57, 0x61, + 0x79, 0x97, 0x42, 0x04, 0x55, 0x09, 0xf5, 0xad, 0x4c, 0x83, 0xd2, 0x56, 0x83, 0xb0, 0x26, 0xa1, 0xce, 0x24, 0x1b, + 0x95, 0xb6, 0x1b, 0x85, 0xd9, 0x22, 0xae, 0x67, 0x84, 0x35, 0x67, 0x33, 0xd5, 0xc0, 0xa4, 0xe1, 0xb8, 0x69, 0xb4, + 0x16, 0x15, 0x6a, 0x0a, 0xf3, 0x1a, 0x57, 0x95, 0xaa, 0xee, 0xe6, 0xd4, 0x52, 0x5a, 0xb6, 0x57, 0xdd, 0x24, 0x1b, + 0x72, 0x19, 0xca, 0x30, 0xd8, 0xc8, 0x11, 0x4c, 0x20, 0x49, 0xce, 0xfc, 0x8d, 0xfc, 0x43, 0x6d, 0xba, 0x16, 0x30, + 0xc7, 0x98, 0x65, 0xc3, 0x82, 0x5e, 0x81, 0x7b, 0xa0, 0x95, 0x9e, 0x4f, 0xb3, 0x8b, 0x3c, 0x48, 0x86, 0x85, 0x5e, + 0x36, 0x19, 0xff, 0x53, 0x18, 0x69, 0x32, 0x63, 0x25, 0x8b, 0x6c, 0x57, 0xa7, 0xc4, 0x79, 0x9c, 0xc0, 0xf6, 0x68, + 0x7a, 0xcb, 0xf7, 0x19, 0x44, 0x05, 0x81, 0x82, 0x19, 0xf3, 0x65, 0x17, 0xcf, 0x7d, 0x9f, 0x59, 0xa6, 0xee, 0xc3, + 0xc1, 0x98, 0xb1, 0xfd, 0x7e, 0x3f, 0xef, 0xf7, 0xd5, 0x7c, 0xeb, 0xf7, 0x93, 0x17, 0xe6, 0x6f, 0x0f, 0x18, 0x14, + 0xe4, 0x44, 0x34, 0x15, 0x22, 0xf8, 0x87, 0xe4, 0x19, 0x92, 0xd1, 0x1d, 0xf7, 0xb9, 0xe5, 0x6c, 0x59, 0x1d, 0x81, + 0x60, 0x1e, 0x0e, 0x97, 0x0a, 0xec, 0x5a, 0xa2, 0x48, 0xc8, 0xf2, 0x9f, 0x81, 0xf1, 0xcc, 0x7d, 0x80, 0x25, 0x03, + 0x10, 0xb6, 0xca, 0xd3, 0xf5, 0x9e, 0xaf, 0x82, 0x77, 0x3a, 0xde, 0x35, 0x56, 0x64, 0x20, 0x6e, 0x81, 0x8d, 0x58, + 0x6b, 0x0f, 0xc8, 0x99, 0x02, 0x1c, 0x2f, 0x0e, 0x87, 0x73, 0xf9, 0x4b, 0x37, 0x5b, 0x27, 0x50, 0x29, 0x70, 0x7b, + 0x74, 0x72, 0xf0, 0xdf, 0x81, 0x66, 0x50, 0x0e, 0xf3, 0x7a, 0xfb, 0x3b, 0x73, 0xf2, 0xd3, 0x53, 0xfc, 0x13, 0x1e, + 0xa2, 0xd3, 0x6f, 0xf7, 0xe6, 0x0f, 0x8a, 0xca, 0xc3, 0x41, 0x2d, 0xfe, 0x73, 0xce, 0x2b, 0xf8, 0x85, 0x6f, 0x02, + 0xb3, 0xc9, 0xd4, 0x3b, 0xf9, 0x26, 0xcf, 0x99, 0x7a, 0x8d, 0x57, 0x4c, 0xbe, 0xc3, 0xe1, 0x5c, 0x8c, 0xea, 0xed, + 0xc8, 0x89, 0x76, 0xca, 0x31, 0x0e, 0x06, 0xff, 0x45, 0xb4, 0x4d, 0x08, 0x30, 0xa4, 0x6e, 0x49, 0x33, 0x1b, 0x57, + 0x96, 0x78, 0x96, 0xce, 0x2f, 0x27, 0x75, 0xb9, 0xd3, 0x8a, 0xa7, 0x3d, 0xb0, 0xb8, 0xad, 0xc1, 0x0b, 0xe0, 0xde, + 0x62, 0xeb, 0x4a, 0xc1, 0xe1, 0x02, 0xe2, 0x14, 0x27, 0x20, 0x82, 0xf6, 0xfb, 0x12, 0xef, 0x15, 0xf4, 0x49, 0x3f, + 0x40, 0x30, 0xe4, 0xcf, 0x12, 0x70, 0xd7, 0xeb, 0xd5, 0x18, 0xdf, 0x4b, 0x21, 0xb8, 0x3e, 0xd3, 0x00, 0xb4, 0xe0, + 0x77, 0xf9, 0x58, 0x4e, 0xbf, 0x89, 0xc0, 0xb3, 0x65, 0x6f, 0xa2, 0xdc, 0x6d, 0x78, 0xda, 0x3f, 0x5a, 0x08, 0xc0, + 0x52, 0x3c, 0x53, 0x82, 0x05, 0x39, 0xc5, 0x5c, 0xfc, 0xbf, 0xe0, 0x23, 0xe6, 0x7b, 0xd2, 0x45, 0x6c, 0xbd, 0x7d, + 0x72, 0x61, 0x20, 0x81, 0xa6, 0x03, 0xf0, 0xe3, 0x55, 0x40, 0x57, 0xc6, 0xcf, 0xcf, 0xb2, 0x1e, 0xeb, 0xe3, 0x3f, + 0x05, 0xf7, 0xe9, 0x67, 0x0a, 0x1f, 0x1d, 0x8e, 0xab, 0x74, 0xb4, 0xa3, 0x14, 0x44, 0x47, 0xb7, 0xcf, 0xa7, 0x3c, + 0xfb, 0xa6, 0x02, 0x72, 0xcb, 0x51, 0x7b, 0x2a, 0x00, 0x8b, 0x2d, 0x1d, 0x81, 0x4f, 0xb3, 0x7c, 0x42, 0xbe, 0xd7, + 0x53, 0x71, 0x75, 0xa9, 0xd3, 0xc5, 0x8b, 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, 0x75, 0x8d, 0x82, 0x95, 0x80, 0x33, 0xed, 0x1a, 0x0c, 0x36, 0xb0, + 0x6e, 0x59, 0x06, 0x7f, 0xc3, 0x35, 0x4d, 0xe0, 0x86, 0x45, 0xd6, 0x7b, 0x83, 0xad, 0x74, 0x0d, 0x8e, 0x96, 0x89, + 0x73, 0x29, 0xc9, 0xca, 0x16, 0x19, 0x57, 0x8f, 0x42, 0xaa, 0xa6, 0xfb, 0x5b, 0x51, 0x3f, 0x08, 0x91, 0x07, 0xab, + 0x94, 0x45, 0xc5, 0x0a, 0x64, 0xf6, 0xe0, 0x1f, 0x21, 0x23, 0x47, 0x39, 0x70, 0x14, 0xfa, 0x5b, 0x13, 0xe8, 0x3c, + 0x3f, 0x85, 0x3a, 0x8f, 0x04, 0x5b, 0xa9, 0x87, 0xc2, 0xca, 0x0b, 0x88, 0x0e, 0xb6, 0x30, 0x56, 0x79, 0x12, 0x2a, + 0x36, 0x65, 0x22, 0x8f, 0x83, 0x5a, 0x02, 0xc6, 0x0a, 0x82, 0x39, 0xcb, 0xa5, 0x0b, 0x52, 0xd5, 0xe8, 0x61, 0x91, + 0xb9, 0x9f, 0x0a, 0xca, 0xff, 0x54, 0xe5, 0x84, 0xeb, 0xcb, 0x10, 0xe0, 0x68, 0x9f, 0x82, 0x28, 0x31, 0xd6, 0x2f, + 0x5a, 0xbc, 0x93, 0x99, 0xb3, 0xa9, 0xed, 0x25, 0xc8, 0xd8, 0x0e, 0xbf, 0x42, 0x68, 0xb5, 0x50, 0x64, 0xd1, 0x70, + 0xc1, 0x74, 0x7b, 0x4a, 0xab, 0xee, 0x61, 0xc3, 0xb3, 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, 0x69, + 0x34, 0x9f, 0xe5, 0x73, 0x1f, 0x15, 0x17, 0x93, 0xc1, 0x60, 0xe3, 0x67, 0xc3, 0x21, 0x4b, 0x86, 0xc3, 0x49, 0xf6, + 0x14, 0x5e, 0x7b, 0xca, 0x23, 0xb5, 0xa4, 0x92, 0xab, 0x0c, 0xf6, 0xf7, 0x01, 0x8f, 0x7c, 0xd6, 0xf9, 0x69, 0xd9, + 0x74, 0xe9, 0x7e, 0x66, 0xc7, 0x5d, 0xe8, 0x0e, 0xb0, 0xf1, 0xb6, 0x41, 0x47, 0xfe, 0xf5, 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, 0x07, 0xf7, 0x85, 0x15, 0x05, + 0xfe, 0xdf, 0xb2, 0x05, 0xbb, 0x97, 0xc7, 0xc0, 0x35, 0x3a, 0x26, 0xc1, 0x05, 0xe2, 0x9e, 0xdd, 0x82, 0x1d, 0x16, + 0xfe, 0x82, 0xeb, 0xe4, 0x98, 0xed, 0xf0, 0x51, 0xe8, 0x15, 0xec, 0xd6, 0x27, 0xa0, 0x5d, 0xb0, 0x35, 0x40, 0x36, + 0xb6, 0xc5, 0x47, 0x77, 0x87, 0xc3, 0xb5, 0xe7, 0xb3, 0x07, 0xfc, 0x71, 0x7e, 0x77, 0x38, 0xec, 0x3c, 0xa3, 0xde, + 0xbb, 0xe1, 0x09, 0x7b, 0xcf, 0x93, 0xc9, 0xcd, 0x15, 0x8f, 0x27, 0x83, 0xc1, 0x8d, 0xbf, 0xe0, 0xf5, 0xec, 0x06, + 0xb4, 0x03, 0xe7, 0x0b, 0xa9, 0x6b, 0xf6, 0x6e, 0x79, 0xe6, 0x2d, 0x70, 0x6c, 0x6e, 0xe1, 0xe8, 0xed, 0xf7, 0xbd, + 0x3b, 0x1e, 0x79, 0xb7, 0xa4, 0x62, 0x5a, 0x71, 0xc5, 0xf1, 0xb6, 0xc5, 0xfd, 0x74, 0xc5, 0x43, 0x78, 0x84, 0x55, + 0x99, 0xde, 0x04, 0xef, 0x7d, 0xb6, 0xd2, 0x2c, 0x70, 0x0f, 0x98, 0x63, 0x4d, 0x76, 0x42, 0x33, 0xf1, 0x57, 0xd8, + 0x3f, 0x37, 0xaa, 0x7f, 0x68, 0xfe, 0x97, 0xba, 0x9f, 0xc0, 0xed, 0x8b, 0x2c, 0x48, 0xec, 0x3d, 0xbf, 0x61, 0xf7, + 0xdc, 0xb0, 0xcd, 0x9e, 0x99, 0xb2, 0x4f, 0x94, 0x1a, 0x3f, 0x52, 0xea, 0xda, 0x32, 0xac, 0x64, 0xee, 0xbe, 0x8c, + 0xc0, 0xe1, 0x80, 0xfc, 0x74, 0x87, 0x38, 0x08, 0xad, 0x9b, 0xac, 0xe6, 0x8a, 0x72, 0x2e, 0xb4, 0x65, 0xe6, 0xe5, + 0xc0, 0x62, 0x96, 0x52, 0x68, 0x2c, 0x00, 0x10, 0x4c, 0x0a, 0xad, 0xbd, 0x97, 0x01, 0xe4, 0x04, 0x0d, 0x7f, 0x6c, + 0xae, 0x8a, 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, 0xa7, + 0xbc, 0x66, 0x82, 0xc8, 0x36, 0x2a, 0x7f, 0x52, 0xbc, 0x40, 0x32, 0x82, 0xe2, 0x69, 0xad, 0x32, 0x16, 0x86, 0x79, + 0xa0, 0x80, 0xbc, 0x7b, 0x77, 0xea, 0x5b, 0xfb, 0x63, 0xc7, 0x9e, 0xad, 0x55, 0xa8, 0x85, 0x9a, 0xc2, 0x25, 0x87, + 0xe8, 0x0a, 0x32, 0x50, 0xc8, 0x78, 0xf2, 0x7a, 0x70, 0x39, 0x89, 0xae, 0xb8, 0x40, 0x67, 0x7c, 0x7d, 0xd3, 0x4d, + 0x67, 0xd1, 0xd3, 0x6a, 0x3e, 0x21, 0x25, 0xd9, 0xe1, 0x90, 0x8d, 0xaa, 0xba, 0x58, 0x4f, 0x43, 0xf9, 0xd3, 0x43, + 0xf0, 0xf5, 0x82, 0x7a, 0x4d, 0x56, 0xa9, 0x7e, 0x4a, 0x95, 0xf2, 0xa2, 0xe1, 0xa5, 0xff, 0xb4, 0x92, 0xfb, 0x1e, + 0x90, 0xd6, 0xf2, 0x92, 0xcb, 0xf7, 0x23, 0xc4, 0x18, 0xf1, 0x03, 0xaf, 0xe4, 0x11, 0x0b, 0xd5, 0x14, 0xae, 0x79, + 0x84, 0x20, 0x6f, 0x99, 0x0e, 0xfe, 0xd6, 0x13, 0xa7, 0xfb, 0x13, 0xa5, 0x5d, 0x7c, 0x61, 0x51, 0xf7, 0x64, 0x6d, + 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, 0xf9, 0xb0, 0xe1, 0x11, 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, 0xfb, 0xb9, 0x80, 0x20, 0x88, 0x92, 0x78, 0x7c, 0xc0, 0xfb, 0xb2, 0x1a, 0x6a, 0x94, 0x7c, 0x2c, + 0x1b, 0xa9, 0xf4, 0x4a, 0xf4, 0x77, 0x63, 0x2e, 0x31, 0xe0, 0x75, 0xd5, 0x16, 0x14, 0xce, 0xf3, 0xc3, 0xe1, 0x3c, + 0x1f, 0x19, 0xcf, 0x32, 0x50, 0xad, 0x4c, 0xeb, 0x20, 0x36, 0xf3, 0xc5, 0xc2, 0x5f, 0xec, 0x9c, 0x44, 0x44, 0x41, + 0x60, 0x47, 0xc2, 0x83, 0x48, 0xfd, 0xaa, 0xf2, 0x74, 0xa7, 0xfa, 0x6c, 0xbf, 0xb0, 0x89, 0xf4, 0x82, 0x92, 0xc9, + 0x27, 0xc1, 0x5e, 0xf5, 0x77, 0x10, 0x36, 0x84, 0x37, 0xaf, 0x7a, 0x9d, 0x65, 0x6a, 0x56, 0x82, 0x84, 0x19, 0x73, + 0x04, 0x8f, 0xc3, 0x4e, 0x63, 0x1b, 0x1e, 0x5b, 0x70, 0x74, 0xde, 0x9a, 0xdd, 0xb1, 0x15, 0xbb, 0x55, 0x75, 0x5a, + 0xf0, 0x70, 0x3a, 0xbc, 0x0c, 0x70, 0xf5, 0xad, 0xcf, 0x39, 0xbf, 0xa3, 0x13, 0x6c, 0x3d, 0xe0, 0xd1, 0x44, 0xcc, + 0xd6, 0x4f, 0x23, 0xb5, 0x78, 0xd6, 0x43, 0xbe, 0xa0, 0xf5, 0x27, 0x66, 0x77, 0x26, 0xf9, 0x6e, 0xc0, 0x17, 0x93, + 0xf5, 0xd3, 0x08, 0x5e, 0x7d, 0x0a, 0x56, 0x8c, 0xcc, 0x99, 0x65, 0xeb, 0xa7, 0x11, 0x8e, 0xd9, 0xdd, 0xd3, 0x88, + 0x46, 0x6d, 0x25, 0xf7, 0xa5, 0xdb, 0x06, 0x84, 0x95, 0x5b, 0x16, 0xc3, 0x6b, 0x20, 0x9e, 0x69, 0x23, 0xe9, 0x5a, + 0x1a, 0x7a, 0x63, 0x1e, 0x4e, 0xe3, 0x60, 0x4d, 0xad, 0x90, 0x67, 0x86, 0x98, 0xc5, 0x4f, 0xa3, 0x39, 0x5b, 0x61, + 0x45, 0x36, 0x3c, 0x1e, 0x5c, 0x4e, 0x36, 0x57, 0x7c, 0x0d, 0xe4, 0x67, 0x93, 0x8d, 0xd9, 0xa2, 0x6e, 0xb9, 0x98, + 0x6d, 0x9e, 0x46, 0xf3, 0xc9, 0x0a, 0x7a, 0xd6, 0x1e, 0x30, 0xef, 0x0d, 0x88, 0x50, 0x12, 0x52, 0x53, 0x6e, 0x7a, + 0x3d, 0xb6, 0x1e, 0x07, 0x77, 0x6c, 0x7d, 0x19, 0xdc, 0xb2, 0xf5, 0x18, 0x88, 0x38, 0xa8, 0xdf, 0xbd, 0x0d, 0x2c, + 0xbe, 0x88, 0xad, 0x2f, 0x4d, 0xda, 0xe6, 0x69, 0xc4, 0xdc, 0xc1, 0x69, 0xe0, 0x82, 0xb5, 0xc9, 0xbc, 0x15, 0x83, + 0x4b, 0xc8, 0xd2, 0x8b, 0xd9, 0x66, 0x78, 0xc9, 0xd6, 0x23, 0x9c, 0xea, 0x89, 0xcf, 0xee, 0xf8, 0x2d, 0x4b, 0xf8, + 0xaa, 0x89, 0xaf, 0x36, 0xa0, 0x11, 0x3d, 0xca, 0xa0, 0xaf, 0xa0, 0x66, 0xe6, 0xbc, 0xb2, 0x30, 0x2a, 0xf7, 0x2d, + 0x38, 0xa0, 0x20, 0x6d, 0x03, 0x04, 0x49, 0x3c, 0xbb, 0x57, 0xe1, 0xfa, 0x46, 0x0a, 0x03, 0x6e, 0x02, 0x33, 0x60, + 0x60, 0xfa, 0x19, 0xfc, 0xb0, 0xd2, 0x25, 0x42, 0x9c, 0xfd, 0x94, 0x92, 0x64, 0x9e, 0x9f, 0x8a, 0x34, 0x77, 0x0b, + 0xd7, 0x29, 0xcc, 0x8a, 0x02, 0xd5, 0x4f, 0x49, 0x69, 0x60, 0xa1, 0x12, 0x99, 0x4a, 0xc1, 0x2f, 0x9b, 0xf3, 0x28, + 0x3b, 0x46, 0xe7, 0x3a, 0xbf, 0x9c, 0x38, 0xa7, 0x93, 0xbe, 0xff, 0xc0, 0x31, 0x6c, 0x21, 0x03, 0x17, 0xfe, 0xd4, + 0x13, 0xc6, 0xa9, 0x15, 0x88, 0xa9, 0xe4, 0xd9, 0x53, 0xf8, 0x4c, 0x68, 0x75, 0x74, 0xe1, 0xfb, 0x41, 0xa1, 0x4d, + 0xd2, 0x2d, 0x48, 0x52, 0xf0, 0x14, 0x3d, 0xe7, 0xbc, 0x0d, 0x54, 0x8a, 0x11, 0x2d, 0x88, 0xb4, 0xb5, 0xcc, 0x1c, + 0xa4, 0x2d, 0xcd, 0x77, 0x4d, 0xfc, 0x1c, 0x16, 0x70, 0x11, 0x2d, 0x6c, 0x0d, 0x8f, 0xaa, 0x58, 0xb9, 0x37, 0x79, + 0x8e, 0x70, 0x46, 0x97, 0x32, 0x01, 0x70, 0xbd, 0x5f, 0x87, 0xb5, 0xc2, 0x2b, 0x6a, 0x16, 0x79, 0x51, 0xd3, 0x27, + 0x5b, 0xe0, 0x3e, 0x16, 0x25, 0x0a, 0x9c, 0xb5, 0x60, 0xc0, 0x56, 0x58, 0xb2, 0x93, 0xc2, 0xa6, 0x68, 0x09, 0xbd, + 0x3d, 0x7e, 0x3a, 0xa8, 0x99, 0x0c, 0xa0, 0x09, 0xa0, 0xf1, 0xf8, 0x17, 0x80, 0x9a, 0xde, 0xd4, 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, 0x83, 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, 0x8b, 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, 0xb5, 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, 0x4e, 0x6e, 0x61, 0xcb, 0x4c, + 0x56, 0xf3, 0x7d, 0xc5, 0x1d, 0x94, 0x6f, 0xb6, 0xce, 0xf8, 0x5e, 0x22, 0x7b, 0xb7, 0x81, 0x12, 0x5e, 0x8c, 0xfe, + 0x82, 0xf4, 0xdb, 0x0c, 0xe3, 0x94, 0xdb, 0x4a, 0x5a, 0x80, 0xd3, 0x3f, 0x1c, 0xde, 0x57, 0x18, 0x34, 0x38, 0xc2, + 0x38, 0xb2, 0x7e, 0xff, 0xb6, 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, 0x9f, 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, 0x3a, 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, 0xeb, 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, 0x4f, 0x9f, + 0x03, 0x69, 0x59, 0xbf, 0x1f, 0xbd, 0xb8, 0x9c, 0x3e, 0x1f, 0x46, 0x01, 0x38, 0x76, 0xd9, 0xcb, 0xcb, 0x98, 0xaf, + 0x2e, 0x99, 0x65, 0x0a, 0x8b, 0x7c, 0x33, 0xa0, 0xba, 0x64, 0xb5, 0x74, 0xbd, 0x02, 0x2c, 0x5d, 0x7e, 0xf3, 0x10, + 0xa6, 0x06, 0x34, 0xb2, 0xe6, 0xee, 0x34, 0xd7, 0x02, 0xa5, 0x9e, 0xf7, 0x33, 0x43, 0xbe, 0x2e, 0x83, 0xae, 0x20, + 0xdd, 0xf3, 0x88, 0xf4, 0x72, 0x2f, 0x9d, 0xee, 0xf7, 0xa5, 0x00, 0x4b, 0x7d, 0x29, 0x3e, 0x83, 0xc2, 0xa2, 0xf1, + 0x8d, 0x00, 0x6d, 0x0d, 0xd5, 0xb4, 0x57, 0x8a, 0xaa, 0x17, 0xf4, 0x4a, 0xf1, 0xb9, 0xa7, 0x87, 0xca, 0x7c, 0x59, + 0x3a, 0xfa, 0x9f, 0x50, 0x73, 0xc1, 0x09, 0x31, 0x13, 0x73, 0x00, 0x95, 0xa0, 0x8d, 0x6f, 0x75, 0xb4, 0xf1, 0xa9, + 0x5e, 0xc5, 0x4d, 0x9f, 0xd7, 0xd6, 0x32, 0x27, 0x84, 0x4d, 0xf7, 0x12, 0xa0, 0x22, 0xaf, 0x84, 0x47, 0xb0, 0xfc, + 0xf2, 0x87, 0x3c, 0x5d, 0x21, 0x5a, 0xc7, 0x3d, 0xcb, 0x5c, 0x1a, 0xfb, 0x37, 0x06, 0xd3, 0xd7, 0xb7, 0xdb, 0x22, + 0x3f, 0x35, 0x31, 0x61, 0x3d, 0x56, 0xf4, 0xcd, 0xbb, 0x70, 0x25, 0x50, 0xe0, 0x50, 0x22, 0xb1, 0x4d, 0x15, 0x8a, + 0x78, 0x90, 0xf4, 0xe9, 0xa2, 0xf5, 0x69, 0x80, 0xa9, 0xb5, 0x1c, 0x98, 0x43, 0xb8, 0x8a, 0x0b, 0x1f, 0x3d, 0x7d, + 0x8b, 0x59, 0x38, 0x9f, 0x78, 0x1f, 0xbd, 0x62, 0x64, 0x3e, 0xee, 0xa3, 0x52, 0x49, 0xff, 0x3c, 0x1c, 0x66, 0xd5, + 0xdc, 0x77, 0xe8, 0x23, 0x3d, 0x54, 0xb9, 0xa0, 0xec, 0x8d, 0x31, 0x89, 0x40, 0x69, 0x8c, 0xf7, 0x71, 0x70, 0x9c, + 0xf7, 0x69, 0x00, 0xa9, 0x7d, 0xe2, 0x3d, 0x29, 0x39, 0x3c, 0xe7, 0x98, 0x13, 0x4a, 0x2b, 0xc2, 0x2a, 0xbe, 0xc8, + 0x50, 0xae, 0x3b, 0xa5, 0x60, 0x92, 0x43, 0x82, 0xe1, 0xaf, 0x9a, 0x37, 0xb1, 0x02, 0x61, 0xd7, 0xcc, 0xab, 0xd1, + 0x93, 0x2a, 0x09, 0x4b, 0x01, 0x47, 0x65, 0xe6, 0x19, 0xf6, 0x86, 0x27, 0x86, 0x91, 0x83, 0xe5, 0xfe, 0xa8, 0x4e, + 0x44, 0xee, 0xd1, 0x05, 0x46, 0x65, 0xe1, 0x79, 0x43, 0x57, 0x1a, 0x54, 0x92, 0x1d, 0x7f, 0xc5, 0x35, 0xa0, 0xb6, + 0xc6, 0x88, 0xa1, 0x80, 0x51, 0xf0, 0xda, 0xfe, 0x10, 0xb2, 0x28, 0x5b, 0xbf, 0xc1, 0x31, 0x9f, 0x95, 0xdc, 0xf5, + 0x0e, 0x67, 0xa1, 0x25, 0xe4, 0xc9, 0x1d, 0x83, 0x34, 0x8d, 0xa5, 0x11, 0x70, 0x22, 0x92, 0x6d, 0x2c, 0x85, 0x23, + 0x80, 0x80, 0x40, 0x37, 0x65, 0x86, 0x31, 0x1d, 0x8c, 0x3c, 0x4f, 0x7a, 0xc6, 0x7b, 0x15, 0x9e, 0x42, 0x9a, 0x6c, + 0x5f, 0xcf, 0xdf, 0x1b, 0x41, 0x56, 0x6e, 0x39, 0xc7, 0xc3, 0xe2, 0x1b, 0x67, 0x5f, 0xe5, 0xe4, 0x29, 0x66, 0x19, + 0xe9, 0x9d, 0x62, 0x5e, 0xc0, 0x9f, 0xca, 0x52, 0x9f, 0xa3, 0xf4, 0x96, 0xf9, 0x64, 0x15, 0x49, 0x97, 0xde, 0xa6, + 0xdf, 0x8f, 0x47, 0xea, 0x50, 0xf3, 0xf7, 0xf1, 0x48, 0x9e, 0x61, 0x1b, 0x96, 0xb0, 0xd0, 0x2a, 0x18, 0x03, 0x48, + 0x62, 0x23, 0xa2, 0xc1, 0x68, 0x6f, 0x0e, 0x87, 0xf3, 0x8d, 0x39, 0x4b, 0xf6, 0xe0, 0xfa, 0xca, 0x13, 0xf3, 0x0e, + 0x7c, 0x99, 0xc7, 0x04, 0x11, 0x9b, 0x79, 0x1b, 0x56, 0x83, 0x07, 0x3b, 0xb8, 0x3e, 0x62, 0x8b, 0x62, 0xad, 0x63, + 0xa9, 0xac, 0x83, 0xd3, 0x3a, 0x36, 0xcd, 0x48, 0x29, 0xb2, 0xcf, 0xb1, 0xbf, 0x77, 0x83, 0xab, 0x6b, 0x63, 0x50, + 0x6b, 0xdc, 0x61, 0xee, 0x9c, 0x0a, 0xa8, 0xc7, 0x74, 0x05, 0xd5, 0xb3, 0x9c, 0x7c, 0xf9, 0xad, 0x9d, 0x03, 0x82, + 0x46, 0x20, 0x70, 0xd1, 0x40, 0xab, 0x76, 0x29, 0xe7, 0x5d, 0x40, 0x88, 0x6f, 0x52, 0xd0, 0xa7, 0x33, 0xd8, 0xc4, + 0xe6, 0x13, 0x88, 0x45, 0xd3, 0x7d, 0xae, 0x35, 0xf3, 0xc5, 0x88, 0x76, 0x66, 0xdd, 0x2d, 0x72, 0xab, 0x85, 0x48, + 0x46, 0xcf, 0x36, 0x13, 0x2e, 0x3a, 0x94, 0x33, 0x12, 0x30, 0x41, 0x6b, 0x2b, 0x25, 0x9f, 0xeb, 0x5e, 0x27, 0x68, + 0x0f, 0x24, 0xad, 0xfb, 0x37, 0x8b, 0xce, 0x28, 0x39, 0xb9, 0xde, 0xe4, 0x0c, 0x52, 0xb0, 0x60, 0x7b, 0x99, 0x13, + 0x6e, 0x80, 0x4f, 0x6c, 0x96, 0x9c, 0xa6, 0x41, 0x1e, 0x0b, 0xe3, 0x91, 0xd7, 0xe6, 0x97, 0x05, 0x74, 0x28, 0x59, + 0x34, 0x42, 0x3c, 0xc0, 0xce, 0x21, 0xb9, 0x2a, 0x50, 0x37, 0x0d, 0x74, 0xe5, 0xca, 0x99, 0x62, 0x0a, 0x5c, 0x08, + 0x05, 0x51, 0x3b, 0x3a, 0x89, 0xca, 0x79, 0x9f, 0x54, 0x97, 0xf9, 0xb4, 0x90, 0xa6, 0x81, 0x7c, 0x5a, 0x39, 0xe6, + 0x81, 0x9d, 0x6d, 0x5c, 0x13, 0x18, 0xe8, 0xd4, 0xbe, 0x16, 0xe5, 0x1c, 0xab, 0x88, 0xde, 0xe7, 0x1f, 0x2a, 0x7b, + 0xfa, 0x20, 0xc2, 0x46, 0x05, 0x1a, 0x4b, 0x89, 0xb1, 0x91, 0xe3, 0xdf, 0x12, 0x65, 0x43, 0x86, 0x80, 0x10, 0xd2, + 0x46, 0x4e, 0x3f, 0xac, 0x2f, 0x6f, 0x33, 0xed, 0xff, 0x49, 0xe2, 0xb7, 0xc1, 0x5e, 0x4e, 0xfd, 0xa9, 0x47, 0x3c, + 0x5e, 0x6b, 0xf4, 0x98, 0x92, 0x6e, 0x83, 0x3c, 0x55, 0x9e, 0x82, 0x64, 0xc2, 0x58, 0x42, 0xb0, 0x28, 0x17, 0x3c, + 0xe7, 0x15, 0x97, 0x70, 0x1f, 0xb5, 0xac, 0x88, 0x50, 0x95, 0xc8, 0xe9, 0xf3, 0x15, 0xf0, 0x4c, 0x40, 0xa0, 0x63, + 0x8c, 0x34, 0xaa, 0xe0, 0x4b, 0x60, 0xac, 0x03, 0x65, 0xa7, 0x19, 0x09, 0x2e, 0xbb, 0x37, 0x48, 0x94, 0xfa, 0x9a, + 0x94, 0xa4, 0xd7, 0xa2, 0xc6, 0x2b, 0xb1, 0x8a, 0x48, 0x20, 0x43, 0x0d, 0x11, 0xab, 0xea, 0xa9, 0x7b, 0x55, 0x4c, + 0x06, 0x83, 0xca, 0x97, 0xd3, 0x13, 0x6f, 0x68, 0xa8, 0xbc, 0xeb, 0x8a, 0x76, 0x7a, 0xa2, 0x95, 0xf2, 0x16, 0xd2, + 0x12, 0x34, 0x0d, 0x23, 0xcd, 0xa1, 0xd4, 0x95, 0x74, 0x37, 0x06, 0xf1, 0x25, 0x13, 0x3d, 0xdb, 0xa9, 0x1d, 0xa5, + 0x2d, 0x69, 0x0f, 0x21, 0x3d, 0x77, 0xc9, 0xc7, 0x2c, 0xe4, 0xea, 0x4e, 0x39, 0x29, 0xaf, 0x42, 0x74, 0x72, 0xdf, + 0x63, 0x48, 0x04, 0xfa, 0x9c, 0x63, 0x58, 0x17, 0x0d, 0x75, 0x0e, 0x2b, 0xc4, 0x6c, 0xa1, 0x84, 0xf9, 0x92, 0xf1, + 0x54, 0x32, 0x68, 0x00, 0x64, 0xc0, 0x67, 0x2f, 0x03, 0xcb, 0x5f, 0x41, 0xfc, 0x68, 0xe3, 0xc3, 0xe1, 0xcf, 0x9a, + 0x42, 0x6c, 0xff, 0x84, 0xcd, 0x10, 0x1e, 0xd5, 0x03, 0x9e, 0xf9, 0x26, 0x4e, 0xd0, 0x0a, 0x48, 0xca, 0xec, 0x68, + 0x22, 0x7b, 0xd5, 0x43, 0x38, 0x95, 0x15, 0xa8, 0xa3, 0xac, 0xb3, 0x12, 0x7e, 0x84, 0xa9, 0x6e, 0x25, 0xd6, 0x02, + 0x6d, 0xae, 0x56, 0xac, 0x05, 0x70, 0xe0, 0xe7, 0x10, 0x3c, 0x91, 0xcf, 0xc1, 0xc5, 0xa0, 0x00, 0x9f, 0x03, 0xe0, + 0x45, 0xee, 0xc2, 0x83, 0x79, 0x64, 0x59, 0x8d, 0x30, 0x1c, 0x55, 0xc4, 0xfa, 0x35, 0xdb, 0x91, 0x0f, 0xdc, 0x8e, + 0xf1, 0xb9, 0xf6, 0x58, 0xb2, 0x1c, 0x8c, 0x32, 0xf7, 0x6a, 0x89, 0x9e, 0x37, 0x69, 0xdc, 0x8c, 0x9e, 0xec, 0x6b, + 0xf9, 0xbf, 0xa0, 0x97, 0x41, 0x7f, 0x0b, 0xb7, 0xbc, 0xe6, 0x77, 0x0b, 0x22, 0xcd, 0xf4, 0x0a, 0x22, 0x65, 0xd4, + 0x88, 0x8c, 0x21, 0x6c, 0x52, 0xdd, 0xdc, 0x26, 0xd5, 0x85, 0x80, 0xa7, 0x23, 0x52, 0x5d, 0x0b, 0x69, 0x23, 0x9f, + 0xd6, 0x81, 0x8c, 0x45, 0x7a, 0xf7, 0xc3, 0xdf, 0x5e, 0x7e, 0x7a, 0xfb, 0xcb, 0x0f, 0x8b, 0xb7, 0xef, 0xde, 0xbc, + 0x7d, 0xf7, 0xf6, 0xd3, 0x6f, 0x04, 0xe1, 0x31, 0x15, 0x2a, 0xc3, 0x87, 0xf7, 0x37, 0x6f, 0x9d, 0x0c, 0xb6, 0x37, + 0x43, 0xd6, 0xbe, 0x91, 0x83, 0x21, 0x10, 0xd9, 0x20, 0x64, 0x90, 0x9d, 0xda, 0xf6, 0x67, 0x62, 0x8e, 0xb1, 0x77, + 0x02, 0x93, 0x2d, 0xe0, 0x1c, 0xcb, 0xbc, 0x64, 0x44, 0xae, 0x0a, 0xad, 0x1f, 0xd0, 0x82, 0x6b, 0x70, 0x91, 0x49, + 0xf3, 0xbb, 0x5f, 0x08, 0x62, 0x9f, 0x56, 0x52, 0xee, 0xab, 0x6d, 0xcd, 0xf3, 0xed, 0xfd, 0x5e, 0xc2, 0xf9, 0xcf, + 0xa5, 0x11, 0xb5, 0x00, 0x07, 0xe0, 0x73, 0xf8, 0xe3, 0x4a, 0x5b, 0xd2, 0x64, 0x16, 0xed, 0x67, 0x0c, 0x41, 0x97, + 0x06, 0x1f, 0xc4, 0x1e, 0x79, 0xa9, 0x4f, 0x16, 0x12, 0xb8, 0x23, 0x86, 0x4f, 0x2b, 0x82, 0x5e, 0x31, 0xa2, 0xb8, + 0xe4, 0x0a, 0x95, 0x52, 0xf2, 0x6f, 0x94, 0x5d, 0x54, 0xc8, 0x59, 0xc1, 0xee, 0x15, 0x39, 0x32, 0x7e, 0x10, 0x4c, + 0x7c, 0x39, 0xb8, 0xff, 0x12, 0xef, 0x70, 0xa6, 0x38, 0x92, 0x13, 0xfe, 0x90, 0x61, 0x60, 0x7f, 0x0e, 0x3e, 0xaf, + 0x0e, 0xf3, 0xf2, 0x46, 0x9f, 0x72, 0x4b, 0x3e, 0x9e, 0x2c, 0xaf, 0xc0, 0x60, 0xbf, 0x54, 0xcd, 0x5d, 0xf3, 0x7a, + 0xb6, 0x9c, 0xb3, 0xfd, 0x2c, 0x9a, 0x07, 0x77, 0x6c, 0x96, 0xcd, 0x83, 0x55, 0xc3, 0xd7, 0xec, 0x96, 0xaf, 0xad, + 0xaa, 0xad, 0xed, 0xaa, 0x4d, 0x36, 0xfc, 0x16, 0x24, 0x84, 0x9b, 0xcc, 0x03, 0xde, 0xe3, 0x3b, 0x9f, 0x6d, 0x40, + 0xa2, 0x5d, 0xb1, 0x0d, 0x5c, 0xc4, 0xd6, 0xfc, 0x87, 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, 0x7d, 0x5a, 0x6d, 0xc2, + 0x0c, 0x3d, 0xcb, 0xe1, 0xa3, 0xad, 0x14, 0xfc, 0xf4, 0x02, 0xbf, 0x64, 0x47, 0x6d, 0xa5, 0x6d, 0xbb, 0x2a, 0xb1, + 0x15, 0xb4, 0x28, 0xb2, 0x5a, 0xe1, 0x81, 0x39, 0x7f, 0x01, 0x0b, 0x18, 0x7b, 0x8e, 0x73, 0x5e, 0xfb, 0x23, 0x64, + 0xbc, 0x77, 0x00, 0xd0, 0x32, 0xc7, 0x01, 0x1e, 0xb1, 0x62, 0x14, 0x0d, 0xde, 0xf9, 0xa5, 0xb2, 0x5a, 0x69, 0x4e, + 0x42, 0xdb, 0x88, 0x55, 0xcb, 0x91, 0xaa, 0x19, 0x91, 0x3e, 0x48, 0xcf, 0xfb, 0x1e, 0x51, 0x0d, 0xf6, 0x64, 0x5e, + 0x07, 0xf6, 0xe9, 0x55, 0x6b, 0x55, 0x77, 0x7e, 0x4f, 0x95, 0x2e, 0x39, 0xb2, 0xe5, 0xa7, 0xcb, 0xf0, 0x41, 0xfd, + 0x29, 0xb9, 0x3e, 0x14, 0x38, 0xc2, 0x63, 0x15, 0x70, 0xbe, 0x5e, 0x89, 0x76, 0x27, 0xc2, 0xae, 0x5c, 0x02, 0x42, + 0x7c, 0x49, 0xd3, 0x1c, 0x8f, 0x23, 0x9a, 0x88, 0xb0, 0x89, 0xd1, 0x5f, 0xd8, 0x7d, 0x28, 0xb1, 0x9c, 0xe7, 0x1a, + 0x94, 0x5c, 0x32, 0x78, 0x4f, 0xda, 0x6b, 0xd0, 0x2c, 0xaf, 0x4a, 0x4d, 0x26, 0x72, 0x50, 0x3e, 0x1c, 0x0a, 0xd8, + 0x4b, 0x8d, 0x9f, 0x26, 0xfc, 0x84, 0xe5, 0xad, 0xbd, 0x35, 0xa5, 0xa8, 0xa4, 0x01, 0x2a, 0xf0, 0x31, 0x83, 0xff, + 0xdd, 0x19, 0x62, 0xc1, 0x14, 0x1d, 0x3f, 0x9c, 0x89, 0xb9, 0xf5, 0xdc, 0x2a, 0xeb, 0x28, 0x5b, 0xa3, 0x9c, 0x80, + 0x7f, 0x4b, 0x75, 0x9c, 0x24, 0xc2, 0xa9, 0xf7, 0x88, 0x8b, 0xba, 0x97, 0x43, 0xd4, 0x0d, 0x7b, 0x5b, 0xe9, 0x60, + 0xcb, 0x69, 0x1a, 0x1c, 0x89, 0x5f, 0xa9, 0xcf, 0xde, 0x67, 0x16, 0x8f, 0x3a, 0xb2, 0x11, 0x25, 0x69, 0x1c, 0x8b, + 0x1c, 0xb6, 0xf7, 0x85, 0xdc, 0xff, 0xfb, 0x7d, 0x08, 0x27, 0xad, 0x82, 0xa4, 0xf4, 0x04, 0x22, 0xc2, 0xd1, 0xe1, + 0x47, 0x84, 0x27, 0x52, 0x55, 0xf8, 0xa4, 0x3e, 0x71, 0x63, 0x76, 0x2f, 0xcc, 0x51, 0xbd, 0x05, 0x18, 0xc6, 0x7a, + 0x6b, 0x11, 0x92, 0x68, 0xa5, 0x19, 0x6d, 0x3d, 0x20, 0x46, 0xbc, 0x5f, 0x5b, 0x64, 0x30, 0xd6, 0x96, 0x44, 0x02, + 0xf8, 0x1d, 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, 0xeb, 0xa3, 0x74, 0x92, 0x58, 0xdf, + 0x77, 0x95, 0x0a, 0x36, 0x9b, 0x1b, 0xd4, 0x97, 0x1d, 0x25, 0xbf, 0x02, 0x27, 0x1d, 0x27, 0x59, 0xe4, 0x20, 0x6a, + 0x51, 0x39, 0x37, 0x49, 0x58, 0xda, 0xd5, 0xa9, 0x36, 0xeb, 0x75, 0x51, 0xd6, 0xd5, 0x6b, 0x11, 0x29, 0x7a, 0x1f, + 0xf5, 0xe8, 0x89, 0x84, 0x54, 0x68, 0x55, 0x6a, 0x97, 0x47, 0xe0, 0xb6, 0xa9, 0x15, 0xdb, 0x72, 0x09, 0x4b, 0xd4, + 0xf8, 0x4f, 0xd0, 0x47, 0xb9, 0x78, 0x90, 0x01, 0x1a, 0x1d, 0x4f, 0xcd, 0x5b, 0x8f, 0xbc, 0x72, 0x94, 0x5f, 0x5a, + 0x6d, 0xd2, 0x2f, 0x80, 0xcc, 0x68, 0xff, 0x68, 0x29, 0x81, 0xcc, 0xc0, 0x4c, 0x5a, 0x1a, 0x12, 0x39, 0x8a, 0x59, + 0x9a, 0xff, 0x81, 0x2b, 0xb6, 0x42, 0xa4, 0x61, 0x35, 0xf7, 0xf8, 0xcb, 0xca, 0xab, 0xe5, 0x5a, 0x66, 0x9a, 0x9b, + 0x25, 0x8e, 0x15, 0x8b, 0x8b, 0x7a, 0x5d, 0x89, 0x2c, 0x10, 0xe2, 0x08, 0xd3, 0x58, 0x4f, 0xbd, 0x51, 0x5a, 0x7d, + 0x40, 0x42, 0x99, 0x1f, 0xb0, 0xb7, 0x63, 0xaf, 0x07, 0x59, 0x88, 0x63, 0xcb, 0xc1, 0x66, 0xeb, 0x7d, 0x2a, 0x53, + 0x11, 0x9f, 0xd5, 0xc5, 0xd9, 0xa6, 0x12, 0x67, 0x75, 0x22, 0xce, 0xbe, 0x83, 0x9c, 0xdf, 0x9d, 0x51, 0xd1, 0x67, + 0x0f, 0x69, 0x9d, 0x14, 0x9b, 0x9a, 0x9e, 0xbc, 0xc1, 0x32, 0xbe, 0x3b, 0x23, 0xae, 0x9a, 0x33, 0x1a, 0xc9, 0x78, + 0x74, 0xf6, 0x21, 0x03, 0x92, 0xd7, 0xb3, 0x74, 0x05, 0x83, 0x77, 0x16, 0xe6, 0xf1, 0x59, 0x29, 0xee, 0xc0, 0xe2, + 0x54, 0x76, 0xbe, 0x07, 0x19, 0x56, 0xe1, 0x1f, 0xe2, 0x0c, 0xa0, 0x5d, 0xcf, 0xd2, 0xfa, 0x2c, 0xad, 0xce, 0xf2, + 0xa2, 0x3e, 0x53, 0x52, 0x38, 0x84, 0xf1, 0xc3, 0x7b, 0xfa, 0xca, 0x2e, 0x6f, 0xb3, 0xb8, 0xcb, 0x22, 0x7f, 0x8a, + 0x5e, 0x45, 0xc4, 0xa4, 0x51, 0x09, 0xaf, 0xdd, 0xdf, 0x36, 0xf7, 0x0f, 0xaf, 0x1b, 0xbb, 0x9f, 0xdd, 0x31, 0xa2, + 0x0b, 0xea, 0xf1, 0x4a, 0x52, 0x2a, 0x28, 0x20, 0x70, 0xa2, 0x59, 0xe3, 0xc1, 0x1d, 0x07, 0xbc, 0x1a, 0xd8, 0x92, + 0xad, 0x7d, 0xfe, 0x22, 0x96, 0x61, 0xda, 0x9b, 0x00, 0xff, 0x2a, 0x7b, 0xd3, 0x75, 0xb0, 0xc4, 0xfb, 0x16, 0xb2, + 0x0d, 0xbd, 0x7d, 0xcd, 0x5f, 0x7a, 0xb9, 0xfa, 0x9b, 0xfd, 0x13, 0x80, 0x30, 0x20, 0x66, 0xd5, 0x47, 0x13, 0xf7, + 0xce, 0xca, 0xb2, 0x73, 0xb2, 0xec, 0x7a, 0xe8, 0xd7, 0x24, 0x46, 0xa5, 0x95, 0xa5, 0x74, 0xb2, 0x94, 0x90, 0x05, + 0x7c, 0x62, 0x34, 0xb5, 0x11, 0x40, 0xd8, 0x8e, 0x52, 0xf9, 0x42, 0xe5, 0x45, 0x14, 0xce, 0x09, 0x9e, 0x27, 0x62, + 0x74, 0x6f, 0x25, 0x03, 0x86, 0x43, 0x08, 0xe6, 0xa0, 0x2d, 0xf6, 0x86, 0x6e, 0x22, 0xfe, 0x7a, 0x53, 0x94, 0x6f, + 0x63, 0xf2, 0x29, 0xd8, 0x9d, 0x7c, 0x5c, 0xc2, 0xe3, 0xf2, 0xe4, 0xe3, 0x10, 0x3d, 0x12, 0x4e, 0x3e, 0x06, 0xdf, + 0x23, 0x39, 0xaf, 0xbb, 0x1e, 0x27, 0xc8, 0x2d, 0xa4, 0xfb, 0xdb, 0x31, 0x09, 0xd0, 0xbc, 0x86, 0xe5, 0xa8, 0xa9, + 0xb8, 0x66, 0x66, 0x8c, 0xe7, 0x8d, 0xde, 0x1f, 0x3b, 0xde, 0x32, 0x85, 0x62, 0x16, 0xf3, 0x1a, 0x7e, 0xcf, 0xaa, + 0x40, 0xdd, 0xf5, 0x36, 0xc9, 0x2d, 0xb3, 0x7a, 0x8e, 0x76, 0xdf, 0xf7, 0x75, 0x22, 0xa8, 0xfd, 0x1d, 0xf6, 0x3c, + 0xb3, 0xde, 0x55, 0x31, 0x70, 0xa9, 0x92, 0x1d, 0x32, 0x55, 0x4d, 0x0f, 0x54, 0x4a, 0x83, 0xa7, 0x97, 0xd6, 0xe5, + 0x4b, 0xa5, 0x8d, 0x3c, 0xd3, 0xfc, 0x06, 0xf0, 0x62, 0xea, 0xb2, 0xd8, 0x7d, 0x75, 0x5f, 0xc1, 0x6d, 0xbc, 0xdf, + 0x5f, 0x56, 0x9e, 0xf9, 0x89, 0x0b, 0xc0, 0xde, 0x54, 0x68, 0x9d, 0x40, 0xa9, 0x61, 0x1d, 0xbe, 0x4a, 0x44, 0xf4, + 0x47, 0xbb, 0x5c, 0x67, 0xae, 0x03, 0x46, 0x14, 0xf1, 0xdb, 0x78, 0xf4, 0x07, 0x28, 0xae, 0x8d, 0x3d, 0x20, 0xac, + 0x43, 0x42, 0x9f, 0x11, 0x80, 0xd4, 0x63, 0x8e, 0x12, 0xd0, 0xac, 0x68, 0xee, 0x98, 0xfc, 0x5c, 0x5f, 0x29, 0xfd, + 0xfd, 0xb2, 0xf2, 0xc8, 0x9c, 0xd2, 0x36, 0xd3, 0x58, 0xad, 0xa9, 0x04, 0xc2, 0x2b, 0x2a, 0x59, 0x85, 0xcf, 0xe6, + 0x8d, 0xe8, 0xf7, 0xe5, 0x11, 0x9e, 0x56, 0x3f, 0x6c, 0x31, 0xbe, 0x15, 0x10, 0x8d, 0x04, 0x40, 0x3f, 0x01, 0xcc, + 0x8b, 0x6c, 0x66, 0xf7, 0x71, 0x40, 0x95, 0x12, 0x4d, 0xe3, 0x6c, 0x9e, 0xdf, 0xd2, 0x9b, 0xb2, 0x83, 0x4e, 0x9d, + 0x2a, 0x70, 0xc1, 0x55, 0xc9, 0x78, 0x65, 0x3d, 0x91, 0xcf, 0x6f, 0x6e, 0x37, 0x69, 0x16, 0xbf, 0x2f, 0xff, 0x89, + 0x63, 0xab, 0xeb, 0xf0, 0xc8, 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, 0x4d, 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, 0x1e, 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, 0x45, 0x85, 0x3a, 0x27, 0x96, 0xf1, 0x1a, 0x80, 0xb5, 0x73, 0xd5, 0xcf, + 0xb3, 0x1a, 0x3c, 0x69, 0x88, 0xcf, 0xc7, 0x68, 0x7b, 0x65, 0x73, 0x50, 0x6d, 0xa7, 0xb3, 0xf2, 0x8a, 0xe9, 0x72, + 0x60, 0xdc, 0x37, 0xbc, 0xa2, 0x38, 0xc3, 0x8f, 0x1e, 0x6c, 0x71, 0xfe, 0x74, 0x43, 0xed, 0xc7, 0xdc, 0xa8, 0x87, + 0x81, 0xd6, 0x82, 0x37, 0x05, 0xb1, 0xfe, 0x7e, 0xe8, 0xc8, 0xf6, 0x5e, 0x8b, 0x8c, 0x26, 0x9f, 0xfd, 0xfc, 0x43, + 0x99, 0xae, 0x52, 0xb8, 0x2f, 0x39, 0x59, 0x34, 0xf3, 0x10, 0xd8, 0x1b, 0x62, 0xb8, 0x3e, 0x2a, 0x3c, 0xa2, 0xac, + 0xdf, 0x87, 0xdf, 0x57, 0x19, 0x98, 0x62, 0xe0, 0xba, 0x42, 0x30, 0x1e, 0x02, 0x41, 0x3c, 0x4c, 0xa3, 0x93, 0x41, + 0x0d, 0xda, 0xf0, 0x0d, 0x40, 0x66, 0x80, 0x47, 0xe6, 0xd2, 0x23, 0xe0, 0x2e, 0x70, 0xed, 0xc9, 0x78, 0xec, 0x4f, + 0x4c, 0x43, 0xa3, 0xa6, 0x34, 0xd3, 0x73, 0xe3, 0x37, 0x1d, 0xd5, 0x72, 0xed, 0xfc, 0xc7, 0x97, 0xfc, 0x06, 0xbd, + 0xa0, 0xe5, 0xe5, 0x3e, 0x52, 0x97, 0xfb, 0x8c, 0xe2, 0x32, 0x91, 0x1c, 0x16, 0xc4, 0xb2, 0x84, 0x03, 0x8f, 0x51, + 0xc9, 0x62, 0x4b, 0x8f, 0x55, 0xd1, 0xf2, 0x45, 0xb9, 0x41, 0x3a, 0x74, 0x42, 0xb0, 0x44, 0x05, 0xc1, 0x12, 0x18, + 0x17, 0xb1, 0xe6, 0x9b, 0x41, 0xce, 0xe2, 0xd9, 0x66, 0xce, 0x91, 0xb0, 0x2e, 0x39, 0x1c, 0x0a, 0x09, 0x36, 0x93, + 0xcd, 0xd6, 0x73, 0xb6, 0xf6, 0x19, 0x28, 0x01, 0x4a, 0x99, 0x26, 0x28, 0x4d, 0x2b, 0xb6, 0xe2, 0xa6, 0x35, 0x58, + 0xad, 0xa6, 0x6c, 0x55, 0x53, 0x76, 0x4e, 0x53, 0x8e, 0x2a, 0x28, 0x39, 0xa1, 0x14, 0x65, 0x18, 0xc0, 0x88, 0x4d, + 0xa2, 0xab, 0x0c, 0x7d, 0xbc, 0x13, 0x1e, 0x41, 0x15, 0x11, 0xf9, 0x84, 0x21, 0x04, 0x26, 0xa2, 0xb8, 0x50, 0x85, + 0x62, 0x80, 0x8c, 0x48, 0x20, 0x98, 0xa8, 0xd4, 0x29, 0x30, 0x1f, 0x4d, 0x15, 0xc3, 0xa6, 0x3d, 0x51, 0xbe, 0xa5, + 0x8e, 0x7b, 0x94, 0x6d, 0xfe, 0x2e, 0x76, 0x41, 0x88, 0xdc, 0x8d, 0x3b, 0xf5, 0x33, 0xe2, 0xbd, 0xdd, 0x11, 0xc6, + 0x4f, 0x76, 0xdc, 0x22, 0x5c, 0x11, 0x6c, 0xa9, 0xe6, 0x10, 0x8b, 0x79, 0x35, 0x49, 0x50, 0xcb, 0x92, 0xf8, 0x1b, + 0x9e, 0x0c, 0x72, 0xb6, 0x04, 0x0f, 0xda, 0x39, 0xcb, 0x00, 0x7f, 0xc5, 0x6a, 0xd1, 0x6f, 0xb5, 0xb7, 0x04, 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, 0x8f, 0xbd, 0x04, 0x3b, 0x07, 0xbc, 0x81, 0xb4, 0x81, + 0x37, 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, 0x22, 0x01, + 0xc0, 0xa4, 0xce, 0x81, 0x38, 0x33, 0xc1, 0x2e, 0x4d, 0x22, 0xcb, 0xc7, 0x30, 0xbf, 0x13, 0x6f, 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, 0x52, 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, 0xd7, 0x90, 0x74, 0x6c, + 0xe0, 0xb4, 0xfa, 0x14, 0x7c, 0x90, 0xe4, 0x60, 0xa2, 0x0e, 0x5e, 0xee, 0x2f, 0xfd, 0x3e, 0x6c, 0xd9, 0xb9, 0x94, + 0xea, 0x58, 0xa9, 0xb7, 0x6d, 0xed, 0x07, 0xd1, 0x16, 0x1c, 0x59, 0xc4, 0xdf, 0x67, 0x88, 0x08, 0x66, 0x06, 0x11, + 0x76, 0x2d, 0xd4, 0xdd, 0x9e, 0x52, 0xcb, 0xa2, 0xde, 0xf6, 0x94, 0x52, 0xb7, 0x61, 0xf8, 0x6e, 0x82, 0x99, 0xe2, + 0x86, 0xff, 0x91, 0x79, 0xa1, 0xde, 0x78, 0x2c, 0x0a, 0x74, 0xcf, 0xdf, 0x2f, 0x79, 0x35, 0xdb, 0x28, 0x13, 0xe6, + 0x1d, 0x5f, 0xce, 0x42, 0xd9, 0xd5, 0xd2, 0xb8, 0xf3, 0xd9, 0x5b, 0xaa, 0xf9, 0xe0, 0x1f, 0x0e, 0x09, 0xc4, 0x1b, + 0xc5, 0x57, 0x77, 0x8d, 0xdc, 0xba, 0x26, 0x9b, 0xab, 0x12, 0x50, 0xbf, 0xcf, 0xd7, 0xb8, 0xdf, 0x62, 0xfd, 0xbb, + 0xa7, 0x41, 0xc6, 0x6a, 0x86, 0x2b, 0xa6, 0xf0, 0x29, 0x00, 0x0c, 0x0e, 0xa7, 0x82, 0xb4, 0xc0, 0x1b, 0x5e, 0x0e, + 0x2f, 0x27, 0x1b, 0x32, 0xe9, 0x6e, 0x7c, 0xe4, 0xce, 0x02, 0x55, 0xef, 0x37, 0x14, 0x27, 0x0d, 0x12, 0x8d, 0xbd, + 0x06, 0x5f, 0x66, 0x19, 0xe5, 0xa2, 0x89, 0xfb, 0x98, 0x7c, 0xa5, 0x07, 0x30, 0x57, 0xa1, 0x04, 0x88, 0x7e, 0x63, + 0x59, 0x6c, 0x44, 0xdb, 0x62, 0x03, 0x4b, 0xa9, 0x9a, 0xeb, 0xd5, 0xf4, 0xd9, 0x2b, 0xd1, 0xbc, 0x8f, 0x66, 0x9c, + 0xd2, 0x68, 0xc0, 0x71, 0x1a, 0x85, 0xdb, 0xf7, 0xf7, 0xa2, 0x5c, 0x66, 0x60, 0xc9, 0x56, 0xe1, 0x14, 0x97, 0x8d, + 0x3a, 0x23, 0x5e, 0xe6, 0xb1, 0x02, 0xe8, 0x78, 0x4c, 0x00, 0x54, 0x17, 0x04, 0x54, 0x44, 0x4b, 0xe9, 0xad, 0xd0, + 0x62, 0xa1, 0xde, 0x70, 0x94, 0xc2, 0x1f, 0xe9, 0xcf, 0x83, 0x7c, 0x0a, 0x40, 0xec, 0xfa, 0x38, 0x7a, 0x53, 0x94, + 0xf4, 0xa9, 0x62, 0x96, 0xcb, 0xc1, 0x04, 0x76, 0x75, 0x22, 0x43, 0xad, 0x20, 0x6f, 0xd5, 0x95, 0xb7, 0x32, 0x79, + 0x1b, 0xe3, 0x94, 0xfc, 0xc8, 0x4d, 0xc7, 0x1a, 0x31, 0xf0, 0xca, 0xd3, 0x3a, 0x4d, 0x90, 0x26, 0x17, 0xc0, 0x30, + 0xc4, 0xb7, 0x99, 0xf7, 0xd2, 0x73, 0xa4, 0x2a, 0x48, 0x66, 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, 0xcb, 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, 0xb5, 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, 0x17, 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, 0x57, 0x99, 0xbe, 0x85, 0x98, 0x28, 0xa7, 0x1a, 0x21, 0x71, 0xa5, 0x24, 0x11, 0x1f, + 0x2f, 0x5a, 0x56, 0x8c, 0xca, 0xf0, 0x81, 0x57, 0xaa, 0x7c, 0x75, 0xaa, 0xf2, 0x62, 0xa4, 0x6d, 0x09, 0xbc, 0x26, + 0xff, 0x10, 0xb9, 0xe6, 0xad, 0xaf, 0xbb, 0xca, 0xd0, 0x6b, 0x59, 0x81, 0x8e, 0x60, 0x2b, 0x4b, 0xc9, 0x01, 0x9f, + 0x54, 0x77, 0xd5, 0xaa, 0xf5, 0x39, 0x65, 0x1b, 0xe1, 0x26, 0xbf, 0x8e, 0x1d, 0x1c, 0x29, 0xbf, 0xc1, 0x73, 0x01, + 0xec, 0x35, 0x60, 0x6f, 0xce, 0x59, 0xd1, 0x3c, 0x3a, 0xa4, 0x6d, 0x81, 0x46, 0x66, 0x6e, 0xe7, 0xea, 0xbe, 0x2d, + 0x8f, 0xd2, 0x18, 0x22, 0xd3, 0x1e, 0x99, 0x0e, 0x36, 0xa3, 0xfc, 0xb7, 0x94, 0xdf, 0x2a, 0x1c, 0x03, 0xdf, 0x4e, + 0xbd, 0x03, 0xa8, 0x7a, 0xda, 0x20, 0x63, 0xcd, 0x30, 0xb4, 0xb2, 0xcb, 0xa5, 0xd0, 0x12, 0xb4, 0xd4, 0x4d, 0x10, + 0x9c, 0x1f, 0x11, 0xe5, 0x08, 0x40, 0x17, 0x29, 0x60, 0x82, 0x9f, 0xd2, 0x76, 0xf7, 0xfb, 0xeb, 0xd4, 0x23, 0xf7, + 0xae, 0x50, 0xa3, 0x84, 0x12, 0x8c, 0xfd, 0x44, 0x63, 0x06, 0x1d, 0x5d, 0x91, 0x13, 0x9e, 0xb5, 0x3a, 0xac, 0xeb, + 0xa6, 0x0c, 0xca, 0xe2, 0x98, 0x57, 0xd3, 0xd9, 0xef, 0x4f, 0xf6, 0x75, 0x83, 0x2c, 0xe4, 0xbf, 0xb3, 0x1e, 0x92, + 0x41, 0xf7, 0x20, 0x14, 0xa2, 0x37, 0x0f, 0x66, 0xf8, 0x1f, 0xdb, 0xf0, 0xec, 0x1b, 0x6e, 0xd4, 0x09, 0x60, 0x8e, + 0xb8, 0x5e, 0x7a, 0x8a, 0xb6, 0x1e, 0x6e, 0x81, 0x6c, 0x8d, 0x97, 0xb7, 0xf6, 0x1a, 0xc8, 0x29, 0x8e, 0xff, 0x8e, + 0x67, 0x6a, 0x65, 0x83, 0x9f, 0x9e, 0xb2, 0x1d, 0x78, 0x78, 0x11, 0x02, 0x8a, 0x61, 0xd9, 0xf8, 0x3b, 0xcb, 0x71, + 0x46, 0xff, 0xcd, 0x23, 0x86, 0xc1, 0x22, 0xf2, 0xe3, 0xcb, 0x52, 0x88, 0x2f, 0xc2, 0x7b, 0x5b, 0x79, 0x77, 0xe4, + 0x94, 0x79, 0xa7, 0x87, 0xd1, 0x75, 0x49, 0xfa, 0x26, 0xf9, 0xd8, 0x1a, 0xb6, 0xdf, 0xb5, 0xfb, 0xcd, 0x10, 0x41, + 0x08, 0xe5, 0xf8, 0x39, 0xa3, 0x13, 0x1a, 0x1f, 0x56, 0xb3, 0xd3, 0xeb, 0xf7, 0xce, 0xf1, 0x82, 0xad, 0xd1, 0x00, + 0x8f, 0x87, 0x2e, 0xe6, 0x89, 0x1a, 0x3a, 0x5d, 0xd7, 0xce, 0xc1, 0x03, 0x83, 0x2c, 0x4f, 0xbe, 0x61, 0x58, 0x62, + 0x7f, 0x12, 0xf1, 0xa4, 0xad, 0xda, 0xd8, 0x1c, 0xa9, 0x36, 0x6a, 0x06, 0x7e, 0xf0, 0x0a, 0x0a, 0x8c, 0x2e, 0x48, + 0x2b, 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, 0x6f, 0xa9, 0x57, 0xfb, 0x32, 0x66, 0x85, 0x7a, 0x7d, 0x61, 0xda, 0xf5, 0x5a, 0x5a, 0x14, 0x50, + 0x71, 0xdb, 0xaa, 0xed, 0x91, 0x9c, 0xff, 0xf8, 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, 0x6f, + 0xa9, 0x57, 0xb5, 0xa9, 0xea, 0xc1, 0x1b, 0x2f, 0x70, 0xf6, 0x4e, 0x6b, 0x01, 0x01, 0x14, 0xb6, 0x96, 0xe5, 0xe0, + 0xdc, 0xed, 0xaa, 0x96, 0x8a, 0x32, 0xea, 0xf7, 0xcf, 0x7f, 0x4b, 0x51, 0x11, 0x7b, 0xaa, 0x38, 0x65, 0xfd, 0x76, + 0xcb, 0x5c, 0x54, 0x96, 0xbc, 0x41, 0x15, 0xad, 0xd5, 0x51, 0x53, 0xb9, 0x6e, 0xae, 0x5a, 0x32, 0x41, 0x8c, 0xee, + 0xd3, 0xb5, 0xce, 0x9d, 0x7a, 0xef, 0x55, 0x1c, 0x31, 0x10, 0xdc, 0x74, 0x8f, 0x0f, 0x0e, 0x42, 0xa3, 0xa2, 0x5c, + 0x70, 0xa3, 0xb4, 0xaa, 0xa4, 0x14, 0xf2, 0x56, 0x45, 0x73, 0xa6, 0x8f, 0x00, 0x88, 0x00, 0xab, 0x44, 0xfd, 0x1f, + 0xbe, 0x34, 0xc6, 0x83, 0x07, 0xbe, 0x26, 0xd7, 0xb1, 0xf5, 0xfe, 0x69, 0x8d, 0xb4, 0xda, 0x38, 0x26, 0xb5, 0xea, + 0x65, 0xab, 0x78, 0xd9, 0xbd, 0x4e, 0xc5, 0xe0, 0xf9, 0xff, 0xdc, 0x07, 0xa8, 0x11, 0x2d, 0x65, 0x70, 0xeb, 0x6a, + 0x80, 0xc6, 0x87, 0x63, 0xe1, 0x1b, 0x3f, 0x64, 0x9c, 0x0f, 0x66, 0xe8, 0xa8, 0x36, 0x07, 0x07, 0x04, 0x47, 0x75, + 0x8f, 0xc6, 0x84, 0x59, 0x38, 0xf7, 0x20, 0x50, 0x7d, 0xe2, 0x3e, 0xe3, 0xda, 0x0b, 0xda, 0x04, 0x3e, 0x59, 0xd7, + 0x35, 0x45, 0x80, 0x8b, 0xd8, 0x98, 0x88, 0x21, 0x2e, 0x9b, 0x44, 0xea, 0x9b, 0x31, 0x28, 0x00, 0x8a, 0x17, 0x15, + 0xc9, 0xa5, 0x8b, 0x34, 0xaf, 0x44, 0x59, 0xeb, 0x66, 0x54, 0xac, 0x18, 0x02, 0xc0, 0x43, 0x50, 0x5c, 0x55, 0x66, + 0x42, 0x23, 0x36, 0x90, 0xca, 0x52, 0xb0, 0x6a, 0x58, 0xf8, 0x4d, 0xfb, 0x4d, 0x72, 0xd2, 0x3b, 0x1f, 0xb7, 0xce, + 0x1d, 0xfb, 0xde, 0x51, 0x48, 0x69, 0x0f, 0xc5, 0x04, 0x41, 0xf0, 0xd3, 0x3a, 0x9c, 0x3f, 0xe3, 0x2f, 0x08, 0x4c, + 0x45, 0x36, 0x63, 0xc0, 0x41, 0x88, 0xc8, 0x8c, 0xdf, 0x73, 0xf8, 0x82, 0x97, 0x93, 0x70, 0x38, 0xf4, 0x41, 0x1f, + 0xca, 0xb3, 0x59, 0x38, 0x14, 0x73, 0xe9, 0xbd, 0x0e, 0xd6, 0xba, 0x90, 0xd7, 0x93, 0x10, 0xd1, 0x42, 0x43, 0x1f, + 0x9c, 0xd7, 0x5d, 0x73, 0x84, 0x25, 0x00, 0x4d, 0x1c, 0x7d, 0x59, 0xbf, 0x1f, 0x79, 0xda, 0xd0, 0x22, 0xc5, 0x45, + 0xa3, 0xcc, 0x66, 0xb9, 0xec, 0x84, 0x8d, 0x6b, 0xb7, 0x40, 0x28, 0x1e, 0xa6, 0x2d, 0x54, 0xad, 0xa7, 0x7a, 0x3d, + 0x37, 0xed, 0xbe, 0x7b, 0x54, 0xad, 0x72, 0xa4, 0xb3, 0x36, 0x5d, 0xa9, 0xd5, 0x2d, 0xa3, 0x6a, 0x9d, 0xa5, 0x11, + 0x55, 0x6e, 0x92, 0xbb, 0x46, 0x2d, 0xf8, 0x64, 0x43, 0x97, 0x29, 0x3b, 0x5b, 0x83, 0x13, 0x47, 0x9e, 0x4b, 0x6e, + 0xf9, 0xee, 0xbc, 0xa2, 0xbb, 0x53, 0xed, 0x5b, 0x80, 0x7b, 0x33, 0x6c, 0xc8, 0x9c, 0xd7, 0xd8, 0x69, 0x10, 0x26, + 0x81, 0x1f, 0xb1, 0x8f, 0x19, 0xb2, 0xc1, 0x80, 0x8e, 0x42, 0xfa, 0x5f, 0x5b, 0xe6, 0x48, 0xc0, 0xe4, 0xaf, 0xe7, + 0x7e, 0xb3, 0x28, 0x72, 0x58, 0x8c, 0x1f, 0x36, 0x18, 0x69, 0xac, 0xd6, 0x60, 0x58, 0xde, 0x21, 0xf2, 0xa7, 0x76, + 0xc7, 0x34, 0xd5, 0xf1, 0x66, 0xbd, 0xd6, 0xfc, 0xea, 0xe9, 0x53, 0x5d, 0x9f, 0xff, 0xf6, 0xfd, 0x65, 0x58, 0x33, + 0xfb, 0x43, 0x10, 0x4a, 0xbb, 0x77, 0x8b, 0x73, 0x47, 0xa2, 0x77, 0xac, 0x34, 0xb3, 0x4b, 0xbb, 0x64, 0x97, 0xa6, + 0xb4, 0x1b, 0x72, 0xbd, 0xfa, 0x4a, 0x79, 0x63, 0xe7, 0x15, 0xd3, 0xfd, 0x7b, 0xa1, 0x77, 0x94, 0x53, 0x35, 0x81, + 0x88, 0x26, 0xed, 0x48, 0xdc, 0xee, 0x95, 0xe1, 0xf3, 0x49, 0xde, 0x2e, 0xe1, 0xa8, 0x6b, 0x58, 0x6e, 0xbe, 0xfd, + 0xcf, 0xbc, 0xea, 0xac, 0x70, 0xfb, 0xa5, 0x31, 0x6b, 0x7f, 0x0a, 0xe2, 0xaa, 0xfe, 0xf0, 0x9e, 0xd4, 0x4c, 0xc9, + 0xff, 0x55, 0x8f, 0x81, 0xab, 0x9f, 0x4c, 0x3b, 0xba, 0xa7, 0x10, 0x36, 0x98, 0xfd, 0xfc, 0xf8, 0xa1, 0x05, 0xab, + 0xea, 0x02, 0x45, 0x72, 0x00, 0x9d, 0xbb, 0x64, 0x84, 0xf7, 0x3b, 0xc6, 0xb9, 0x7f, 0xf5, 0xbd, 0x9a, 0x1c, 0x21, + 0xa2, 0x5d, 0x84, 0x03, 0x80, 0xb8, 0xd3, 0x54, 0xd6, 0xa1, 0x06, 0xe8, 0x03, 0x02, 0xeb, 0xd0, 0xb7, 0x19, 0xc0, + 0x41, 0x1f, 0x6d, 0x9e, 0x45, 0x20, 0xaf, 0x7b, 0xf7, 0xec, 0x9a, 0xed, 0x7c, 0xfe, 0x62, 0x95, 0x7a, 0xf7, 0xe8, + 0x10, 0x7c, 0x3e, 0xf6, 0xa7, 0x97, 0x81, 0xc1, 0x85, 0x66, 0xd7, 0xcf, 0x04, 0xdb, 0xb1, 0xdd, 0x33, 0x44, 0x2a, + 0xea, 0xce, 0x3f, 0xbc, 0x34, 0xd1, 0xf3, 0xce, 0x0b, 0x77, 0x7c, 0x09, 0xe0, 0x81, 0x2c, 0x06, 0x14, 0x9f, 0xa5, + 0xf7, 0x2f, 0x96, 0x80, 0x9a, 0xfc, 0x96, 0xaf, 0xbd, 0x2f, 0x94, 0xba, 0x80, 0x3f, 0x07, 0x94, 0x3e, 0xc9, 0xb9, + 0x77, 0x37, 0xbc, 0xf5, 0x2f, 0x9e, 0x83, 0xf3, 0xc4, 0x6a, 0xb8, 0x80, 0xbf, 0x0a, 0x3e, 0xf4, 0xee, 0x06, 0x98, + 0x58, 0xf2, 0xa1, 0xb7, 0x1a, 0x40, 0xaa, 0xc2, 0x85, 0xc4, 0xd8, 0x87, 0x5f, 0x83, 0x9c, 0xe1, 0x1f, 0xbf, 0x69, + 0x0c, 0xd6, 0x5f, 0x83, 0x42, 0xa3, 0xb1, 0x96, 0x2a, 0x64, 0x29, 0x16, 0x67, 0x02, 0x6c, 0xc2, 0x71, 0xb7, 0x2f, + 0x56, 0xb5, 0x59, 0x0b, 0xfa, 0xf3, 0x11, 0xdf, 0xa3, 0xb1, 0xba, 0x2a, 0xe7, 0xa2, 0xfc, 0x88, 0xf4, 0xa9, 0x8e, + 0x8f, 0x51, 0xb1, 0xa9, 0xbb, 0xd3, 0xa9, 0x56, 0x1d, 0x69, 0xbf, 0x29, 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, 0x2f, 0x06, 0xb9, 0x0c, 0x8d, 0xf9, 0x80, 0x6c, 0x18, 0xca, 0x87, 0x16, 0x19, 0x12, 0x22, 0xde, 0x43, + 0x25, 0x60, 0xdb, 0x82, 0x32, 0x29, 0xe0, 0x2c, 0x1a, 0xfc, 0x56, 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, 0x1f, 0xae, 0xf2, 0x4f, 0xd1, 0x52, 0x0f, 0xff, 0x9f, 0x31, 0x85, 0xd2, + 0xbf, 0x4a, 0xcb, 0x68, 0xb3, 0x5a, 0x8a, 0x52, 0xe4, 0x91, 0x38, 0xf9, 0x5a, 0x64, 0xe7, 0xf2, 0x9d, 0x4f, 0xa1, + 0x5f, 0x00, 0x5a, 0xf6, 0x09, 0x32, 0xfa, 0x7b, 0x26, 0xf8, 0xf0, 0x7b, 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, 0x7b, 0x83, 0x90, 0xe2, 0xf9, 0x03, 0x5b, 0xad, 0x8b, 0x8b, 0xc4, 0x2b, 0x64, + 0xa2, 0x05, 0xb1, 0x14, 0x81, 0x19, 0x2f, 0x34, 0x8d, 0x30, 0x41, 0x99, 0x12, 0x2c, 0x5a, 0xa3, 0x43, 0xfb, 0xc3, + 0x12, 0x76, 0x8f, 0x31, 0x02, 0x04, 0xaa, 0x4c, 0x9f, 0xc3, 0xd6, 0x84, 0xd9, 0xd4, 0xc5, 0x06, 0x68, 0xab, 0x18, + 0x1a, 0x84, 0xb5, 0x21, 0xe6, 0x63, 0x9a, 0xdf, 0xfd, 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, 0xee, 0x1a, 0xfe, 0x21, 0xf3, 0x62, 0x96, 0x80, 0x7e, 0x77, 0xc5, 0x55, 0x83, 0xa0, 0x19, 0x1b, 0x76, + 0x0b, 0xbf, 0x25, 0xd6, 0x6e, 0xe9, 0x5f, 0x2c, 0xd9, 0xc2, 0xf4, 0x81, 0x6e, 0x1d, 0x60, 0x19, 0x51, 0x93, 0xef, + 0x91, 0x77, 0xd3, 0x59, 0x51, 0xb8, 0x3d, 0xb1, 0x85, 0xcf, 0xae, 0xcd, 0x9b, 0xf7, 0xcf, 0x22, 0xc8, 0xbd, 0xe3, + 0xde, 0xfd, 0xf0, 0xda, 0xbf, 0xd0, 0x2d, 0x90, 0x93, 0x59, 0xce, 0x40, 0xea, 0x88, 0x4f, 0x10, 0xad, 0xec, 0x29, + 0xdf, 0x09, 0xb9, 0xb3, 0xad, 0x9f, 0xdd, 0xbb, 0xdb, 0xda, 0xdd, 0xb3, 0x7b, 0x56, 0x8d, 0x28, 0x56, 0x9c, 0xa6, + 0x48, 0x98, 0x45, 0x1b, 0xe0, 0xa9, 0x97, 0xef, 0x77, 0xec, 0x98, 0xc3, 0xdd, 0xb3, 0x8e, 0x8e, 0x97, 0x73, 0xc0, + 0xee, 0xfe, 0xa3, 0x4d, 0xd8, 0x58, 0xe9, 0x5a, 0x85, 0x0e, 0x77, 0xcf, 0x32, 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, 0x2b, 0x2e, 0xbe, 0x3f, 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, 0x9c, 0xc5, 0x90, 0x08, 0xb0, 0xdd, 0xa1, 0x62, 0x5b, 0xb8, 0x78, + 0xce, 0x36, 0xbc, 0xe8, 0xf7, 0x33, 0xd5, 0x29, 0x64, 0xdd, 0x59, 0xf2, 0x8d, 0x6a, 0x8e, 0x35, 0xd4, 0x6c, 0x6d, + 0x92, 0xad, 0x71, 0x6e, 0x2b, 0x3e, 0xee, 0xda, 0x8a, 0x8f, 0x95, 0xb5, 0x2e, 0xdd, 0xeb, 0x3d, 0xaa, 0x0b, 0x60, + 0xeb, 0xbf, 0x3d, 0x5e, 0xb9, 0x9e, 0xcf, 0x08, 0xe0, 0x6b, 0xc1, 0xc7, 0x93, 0x05, 0x7a, 0x95, 0x2c, 0xfc, 0xdb, + 0x81, 0x1a, 0x7f, 0xa7, 0x73, 0x17, 0x00, 0x5d, 0x49, 0x79, 0x05, 0xe4, 0x1d, 0xe4, 0x98, 0x5b, 0x76, 0xe5, 0xfd, + 0xc9, 0x77, 0xd8, 0x35, 0xaf, 0x67, 0x8b, 0x39, 0xdb, 0x81, 0x53, 0x41, 0x32, 0xb0, 0x97, 0x15, 0xdb, 0x05, 0xb1, + 0x9d, 0xf0, 0x1b, 0x01, 0x53, 0xbe, 0x84, 0x20, 0xae, 0xe0, 0x16, 0xe2, 0xf0, 0xe4, 0x9f, 0x83, 0xfb, 0xd6, 0x66, + 0x7d, 0xcf, 0xac, 0xce, 0x09, 0xd6, 0xcc, 0xea, 0xc1, 0x60, 0xd9, 0x4c, 0x56, 0xfd, 0xbe, 0xb7, 0xd3, 0x8e, 0x4f, + 0x77, 0x52, 0x27, 0x76, 0x5a, 0xab, 0xb5, 0x60, 0xd7, 0x52, 0xeb, 0x62, 0x0c, 0x3d, 0x40, 0xfc, 0x74, 0x3b, 0xe0, + 0xf7, 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, 0xc7, 0x6c, 0xc7, 0xb8, + 0xf9, 0xe9, 0xe5, 0x0f, 0x4e, 0x58, 0xb2, 0x62, 0xb5, 0x3f, 0xfd, 0xfe, 0x99, 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, 0x99, 0xfa, 0xc0, 0x88, 0x25, 0x81, 0xda, 0x5e, + 0x66, 0xe9, 0x1d, 0xa8, 0xf0, 0x7b, 0xb8, 0x9a, 0x88, 0xfd, 0xdc, 0x92, 0xa2, 0x22, 0x1b, 0xe9, 0x0d, 0xad, 0xc1, + 0x23, 0xb4, 0xa6, 0x7c, 0xef, 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, 0xd7, 0x24, 0x61, 0x4f, 0x0c, + 0x3a, 0x85, 0xaa, 0xdc, 0xee, 0x8e, 0xb6, 0xc0, 0x75, 0xcc, 0x52, 0xf4, 0xd2, 0x16, 0xb9, 0x5b, 0xfe, 0xdd, 0x73, + 0x45, 0xce, 0x7e, 0x09, 0x08, 0x4e, 0xcd, 0x57, 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, 0xe6, 0x2e, 0xc9, 0x37, 0xe0, + 0xcc, 0x40, 0xa9, 0x96, 0x7e, 0xe0, 0x58, 0x2d, 0xa0, 0xc2, 0xc1, 0xec, 0xa4, 0x5e, 0x58, 0x46, 0x3d, 0xa6, 0xcf, + 0xcf, 0x60, 0xef, 0x08, 0x09, 0x80, 0xfb, 0x65, 0x1f, 0x90, 0x80, 0x87, 0xce, 0xec, 0x80, 0x70, 0xc2, 0x2c, 0xaa, + 0x02, 0x89, 0xe4, 0x48, 0x3f, 0x7b, 0xcc, 0x44, 0xf2, 0x07, 0xb3, 0x9e, 0x73, 0x4a, 0xf4, 0x58, 0x4f, 0x1d, 0x21, + 0x3d, 0xd6, 0xb3, 0x8e, 0x88, 0x1e, 0xeb, 0x59, 0xc7, 0x47, 0x8f, 0xf5, 0xcc, 0xb1, 0xd3, 0x83, 0xc0, 0x04, 0x88, + 0x3c, 0x60, 0x3d, 0x9a, 0x4c, 0x3d, 0xc5, 0x3d, 0x40, 0x34, 0x08, 0xac, 0x27, 0x85, 0xf3, 0x1e, 0x20, 0x8f, 0x91, + 0x58, 0x1d, 0xf4, 0xfe, 0x32, 0x7e, 0xda, 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, + 0x07, 0x51, 0xf3, 0xb4, 0xd5, 0x56, 0xc1, 0xfe, 0x0e, 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, 0x1f, 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, 0x7f, 0x95, 0xa5, 0xc6, 0x39, 0x32, 0x97, 0xeb, 0xbb, 0x2e, 0xee, 0xee, 0x68, 0x9b, 0xb0, 0x0a, 0x11, + 0xea, 0xb6, 0xa1, 0x72, 0x29, 0xcc, 0xc6, 0xa6, 0x69, 0x80, 0x2f, 0x14, 0x95, 0x4a, 0x55, 0x6a, 0x2b, 0x95, 0x9c, + 0xf0, 0xae, 0xaf, 0x6a, 0x91, 0xba, 0x22, 0xd8, 0xc6, 0x0c, 0xf5, 0x50, 0x6e, 0xd4, 0xd8, 0xd7, 0x1d, 0xab, 0xf4, + 0x0e, 0x13, 0xe4, 0x8c, 0xbc, 0xc8, 0xc1, 0x45, 0x49, 0x41, 0xe6, 0x6a, 0x08, 0xf3, 0x47, 0x0d, 0x9f, 0x16, 0x96, + 0x7b, 0x28, 0x01, 0xb3, 0xa3, 0x86, 0x97, 0x11, 0x02, 0x11, 0x97, 0xca, 0xbe, 0x62, 0xe2, 0xf7, 0x14, 0xcc, 0x92, + 0x09, 0xdd, 0x8b, 0x58, 0x18, 0xa1, 0x8d, 0x4f, 0x92, 0x64, 0xea, 0x69, 0x0a, 0x6e, 0xe4, 0x32, 0xcc, 0xd1, 0x08, + 0x2d, 0xf9, 0xc8, 0x81, 0xf4, 0xb5, 0x9c, 0x4a, 0xf0, 0x11, 0x75, 0x0a, 0x38, 0x9e, 0x9f, 0x17, 0xd6, 0x4f, 0x96, + 0x4b, 0xcc, 0x65, 0x6d, 0xfe, 0xcb, 0x8e, 0x8e, 0xc1, 0x2e, 0x4f, 0x13, 0xc7, 0xd5, 0x7f, 0x54, 0x25, 0xc5, 0xc3, + 0xcf, 0x69, 0x0e, 0x28, 0x82, 0x99, 0x3d, 0xc5, 0xf8, 0xd8, 0x67, 0x99, 0x02, 0xfe, 0x76, 0xbd, 0xb5, 0x64, 0x62, + 0x97, 0xb4, 0x9b, 0x2b, 0xe3, 0x97, 0xda, 0xb0, 0xe3, 0xe0, 0xdc, 0x00, 0x14, 0x67, 0x8d, 0x0e, 0xcb, 0x6b, 0xdd, + 0xb6, 0x2a, 0x54, 0xa0, 0xd6, 0xff, 0xd9, 0x2d, 0x4c, 0x79, 0x9b, 0x97, 0xca, 0xdb, 0x3c, 0x34, 0x01, 0x02, 0x91, + 0x19, 0xf2, 0xac, 0xe9, 0x98, 0x24, 0xee, 0x1d, 0x29, 0x69, 0xdf, 0x91, 0xe2, 0x47, 0xef, 0x48, 0xc8, 0xb7, 0x84, + 0x8e, 0xec, 0x4b, 0x4e, 0x4e, 0xa0, 0xcc, 0x60, 0x2f, 0xaf, 0x99, 0xec, 0x1f, 0xd0, 0x5e, 0x38, 0x97, 0xe5, 0x15, + 0xbf, 0x16, 0xde, 0xda, 0x9f, 0xae, 0x4f, 0xbb, 0xaa, 0xde, 0x7e, 0x65, 0x66, 0x1e, 0x0e, 0xc5, 0xe1, 0x50, 0x99, + 0xa0, 0xdd, 0x05, 0x17, 0x83, 0x9c, 0xdd, 0xbb, 0xf1, 0xf1, 0xd7, 0x1c, 0x45, 0x6c, 0xa5, 0x3c, 0x92, 0x2e, 0x54, + 0x62, 0x78, 0x69, 0xe0, 0x61, 0x76, 0x7c, 0x3c, 0xd9, 0x5d, 0xdd, 0x4f, 0x06, 0x83, 0x9d, 0xea, 0xdb, 0x2d, 0xaf, + 0x67, 0xbb, 0x39, 0x7b, 0xe0, 0xb7, 0xd3, 0x6d, 0xb0, 0x6f, 0x60, 0xdb, 0xdd, 0x5d, 0x89, 0xc3, 0x61, 0xf7, 0x82, + 0x2f, 0xfc, 0xfd, 0x03, 0x02, 0x3a, 0xf3, 0xf3, 0x71, 0x1b, 0xe3, 0xe7, 0xa6, 0xed, 0xaa, 0xb5, 0x03, 0x78, 0xfa, + 0x1f, 0xbc, 0x9b, 0xd9, 0x72, 0xee, 0xb3, 0x27, 0xfc, 0x01, 0xfc, 0xf3, 0x71, 0x93, 0x44, 0xea, 0x13, 0xed, 0x32, + 0x79, 0x03, 0x0e, 0xe4, 0x3b, 0x9f, 0xbd, 0xe5, 0x0f, 0xb3, 0xe5, 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, 0x76, 0xc3, + 0x22, 0x3f, 0x80, 0x0f, 0xb2, 0x9d, 0x3f, 0x91, 0x35, 0xa5, 0xfb, 0xc5, 0x13, 0xff, 0x70, 0xa0, 0xbf, 0xde, 0xfa, + 0x87, 0xc3, 0x7b, 0xf6, 0x80, 0xe0, 0xe8, 0x7c, 0x07, 0xfd, 0xa3, 0x6f, 0x1d, 0x50, 0x95, 0xe1, 0xf5, 0x6c, 0x33, + 0xf7, 0x5f, 0xac, 0xd8, 0x1d, 0x70, 0xa1, 0x28, 0x2f, 0xb4, 0x1b, 0xf6, 0x80, 0x5e, 0x67, 0xe4, 0x44, 0x34, 0xdb, + 0xcd, 0x7d, 0x16, 0xe3, 0x73, 0x75, 0x5f, 0x4c, 0xbe, 0x7a, 0x5f, 0xdc, 0xb1, 0x6d, 0xf7, 0x7d, 0x51, 0xbe, 0xe9, + 0xae, 0x9f, 0x2d, 0xdb, 0xb1, 0x07, 0x98, 0x61, 0xd7, 0xfc, 0xa6, 0x39, 0x76, 0x8c, 0xfd, 0xea, 0x8d, 0x11, 0x40, + 0x99, 0x2d, 0x58, 0x2c, 0x38, 0x28, 0xd5, 0xaa, 0x6d, 0x49, 0xe4, 0x95, 0x0e, 0x54, 0x9b, 0x11, 0xdc, 0x57, 0x0b, + 0x39, 0xf3, 0xcc, 0x40, 0xdf, 0x56, 0x88, 0x16, 0x0e, 0x1b, 0xf0, 0x57, 0xda, 0x3a, 0xc6, 0x30, 0xcd, 0x6a, 0xa6, + 0x6d, 0x51, 0x97, 0xdf, 0xf6, 0x9e, 0xc9, 0x6f, 0x64, 0x60, 0x0b, 0x91, 0x14, 0x8e, 0xe3, 0x8b, 0xe7, 0x27, 0xfc, + 0x57, 0x2d, 0x8f, 0x5a, 0xed, 0x17, 0x4a, 0x7d, 0xfa, 0x8a, 0x8e, 0x68, 0xe2, 0x5e, 0xb4, 0x65, 0x58, 0xa3, 0xac, + 0xa9, 0xa5, 0xc3, 0x30, 0xae, 0x61, 0x5f, 0x1e, 0x38, 0xf4, 0x1d, 0x10, 0x68, 0xab, 0x54, 0x0a, 0xb4, 0x70, 0x0c, + 0xa3, 0x30, 0x0b, 0x29, 0x8f, 0x0b, 0xb3, 0x94, 0xf7, 0x58, 0xa0, 0xc5, 0xad, 0xba, 0xc7, 0xd4, 0x76, 0x0b, 0x22, + 0xac, 0xde, 0x32, 0xce, 0x2f, 0x1b, 0x55, 0xb8, 0x2d, 0x40, 0x51, 0x04, 0x65, 0xb0, 0x27, 0xb9, 0x6d, 0xa1, 0xa4, + 0xd9, 0x28, 0xac, 0xc5, 0x5d, 0x51, 0xee, 0x7a, 0x0d, 0x5b, 0xe0, 0x05, 0x55, 0x3f, 0x21, 0x6c, 0xcb, 0x9e, 0x75, + 0x28, 0x17, 0xe9, 0x7f, 0x64, 0xe9, 0xf9, 0x76, 0x6b, 0xce, 0xff, 0xf4, 0x15, 0x7d, 0x54, 0xfe, 0xe7, 0x97, 0xf4, + 0x93, 0xc1, 0x32, 0x72, 0x4a, 0x7d, 0x1f, 0x8d, 0x6e, 0xd3, 0x9c, 0x30, 0xb6, 0x7c, 0xfd, 0xf4, 0x1b, 0x64, 0x0a, + 0x92, 0x43, 0x29, 0x55, 0x39, 0xd9, 0x43, 0x5f, 0x78, 0xdd, 0x87, 0x99, 0x60, 0x00, 0xc2, 0x6b, 0xb4, 0xa9, 0x26, + 0x4c, 0xe2, 0xd1, 0x15, 0xfc, 0xdf, 0x08, 0x62, 0xd0, 0x3e, 0x51, 0xd4, 0xb1, 0x6d, 0xa4, 0xeb, 0xb6, 0x73, 0x90, + 0xdc, 0xa9, 0x2b, 0x7f, 0x54, 0x4e, 0xfe, 0x13, 0x0d, 0x91, 0x57, 0x5c, 0x21, 0x56, 0x16, 0x5c, 0x62, 0x31, 0x54, + 0xa4, 0x00, 0xd7, 0x10, 0x44, 0xca, 0xa2, 0xa4, 0x70, 0xcb, 0x41, 0x55, 0x04, 0x60, 0x5c, 0xad, 0x8e, 0x3a, 0x11, + 0x3e, 0x6e, 0xad, 0x45, 0x08, 0x56, 0x34, 0x6a, 0x65, 0xad, 0xc0, 0x17, 0xa4, 0x2f, 0x1d, 0x0a, 0x62, 0x7a, 0x14, + 0x52, 0x55, 0x3a, 0x14, 0x48, 0x73, 0xa8, 0xf8, 0xc6, 0x60, 0xa3, 0xa8, 0x48, 0xcf, 0x5f, 0x9a, 0x94, 0x5c, 0x1a, + 0x33, 0x3e, 0x88, 0x32, 0x12, 0x79, 0x1d, 0xde, 0x89, 0x69, 0x81, 0x7c, 0xa3, 0xc7, 0x0f, 0x82, 0x4b, 0x78, 0x37, + 0xe4, 0x5e, 0x01, 0xb6, 0x04, 0xec, 0x00, 0xf7, 0xca, 0x8c, 0x72, 0x9d, 0xd6, 0xf5, 0x5b, 0xeb, 0xa1, 0x18, 0x86, + 0xcf, 0x2c, 0x81, 0xed, 0x68, 0x1d, 0x1d, 0xe9, 0xe1, 0xc3, 0xff, 0xba, 0xaa, 0x39, 0xea, 0x54, 0x2e, 0x67, 0xc7, + 0x13, 0x96, 0x22, 0x66, 0xd0, 0xfd, 0x75, 0xfb, 0x4a, 0x00, 0xdd, 0x2e, 0x8b, 0x79, 0x36, 0xda, 0xc9, 0xbf, 0xa5, + 0x1b, 0x2b, 0x4a, 0x9b, 0x78, 0x97, 0xf5, 0xc6, 0xfe, 0x70, 0xf4, 0x97, 0x67, 0x5f, 0x26, 0x84, 0xaa, 0xb3, 0x61, + 0x6b, 0x1d, 0xe7, 0xf2, 0xbf, 0xfe, 0x3a, 0x26, 0x2b, 0x08, 0x0a, 0xc2, 0xb2, 0x53, 0x4c, 0x54, 0x30, 0x8a, 0x14, + 0x6b, 0x3e, 0x9e, 0xac, 0x51, 0x27, 0xbc, 0xf6, 0x97, 0x5a, 0x27, 0x4c, 0x8c, 0xac, 0x54, 0xfe, 0x9a, 0x55, 0xec, + 0x4e, 0x65, 0x16, 0x90, 0x79, 0x90, 0x4f, 0xd6, 0x46, 0x83, 0xb9, 0xe2, 0xf5, 0x6c, 0x3d, 0x97, 0xca, 0x67, 0x30, + 0xe5, 0x2c, 0x07, 0x27, 0x4b, 0x61, 0xf7, 0x24, 0x50, 0xb4, 0x66, 0xe8, 0xda, 0x9f, 0x62, 0xab, 0x5e, 0xa7, 0x55, + 0x0d, 0xf0, 0x80, 0x10, 0x03, 0x43, 0xed, 0xd5, 0xc2, 0x43, 0x6b, 0x01, 0xac, 0xfd, 0x51, 0xe9, 0x07, 0xe3, 0xc9, + 0x92, 0x2f, 0x90, 0x7f, 0x39, 0x72, 0xd4, 0xee, 0xfd, 0xbe, 0x77, 0x0f, 0x52, 0x70, 0xe4, 0x5a, 0x28, 0x90, 0x08, + 0x68, 0xc1, 0x37, 0xbe, 0xf2, 0xc1, 0xb8, 0x46, 0x6d, 0x35, 0x28, 0xa8, 0x1d, 0xdd, 0xf2, 0xd8, 0xd1, 0x3b, 0xdf, + 0x9f, 0xd0, 0x57, 0x2f, 0xb4, 0x70, 0xfc, 0x95, 0x33, 0x72, 0xcd, 0x56, 0x1d, 0x72, 0x44, 0x33, 0xe9, 0x10, 0x22, + 0x56, 0x6c, 0xcd, 0xae, 0x49, 0xe5, 0xdc, 0x39, 0x64, 0xa7, 0x8f, 0x50, 0xa5, 0xd7, 0x7a, 0x7c, 0x3b, 0x51, 0xba, + 0xdb, 0xe3, 0xdd, 0xe4, 0x5b, 0x36, 0x11, 0x31, 0x18, 0xd0, 0x06, 0xe1, 0x8c, 0xac, 0x43, 0xa4, 0xd2, 0x01, 0x42, + 0xe0, 0x98, 0x80, 0xa6, 0xff, 0xf8, 0x9a, 0x44, 0x01, 0x47, 0xda, 0x08, 0x59, 0xcb, 0x0e, 0x87, 0x1c, 0x34, 0xca, + 0xcd, 0x1f, 0x5e, 0xa1, 0x4e, 0x73, 0x60, 0x9e, 0x2e, 0x61, 0xcf, 0xc1, 0x23, 0xbd, 0x38, 0x3e, 0xd2, 0xff, 0x3b, + 0x9a, 0xa8, 0xf1, 0x7f, 0xae, 0x89, 0x52, 0x5a, 0x24, 0x47, 0xb5, 0xf4, 0x4d, 0xea, 0x28, 0xb8, 0xc8, 0x3b, 0x6a, + 0x21, 0x7b, 0x96, 0x8d, 0x1b, 0xd5, 0xbc, 0xff, 0x5f, 0x2b, 0xf3, 0xff, 0x35, 0xad, 0x0c, 0x53, 0xb2, 0x63, 0xa9, + 0x66, 0x1e, 0x68, 0x15, 0xc3, 0xec, 0x67, 0x92, 0x10, 0x19, 0x2e, 0x0d, 0xf8, 0x51, 0x05, 0xfb, 0x38, 0xad, 0xd6, + 0x59, 0xb8, 0x43, 0x25, 0xea, 0xad, 0xb8, 0x4b, 0xf3, 0x97, 0xf5, 0xbf, 0x45, 0x59, 0xc0, 0xd4, 0xbe, 0x2b, 0xd3, + 0x38, 0x20, 0x0b, 0x7f, 0x16, 0x96, 0x38, 0xb9, 0xb1, 0x8d, 0x3f, 0xcb, 0xf1, 0xb4, 0x5f, 0x75, 0x66, 0x1e, 0x48, + 0xa0, 0x06, 0xe2, 0x8f, 0x9c, 0xcb, 0xca, 0xe2, 0x01, 0xa1, 0x9b, 0x7f, 0x28, 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, 0xa7, 0xb1, 0x88, 0x47, 0x3d, 0x45, 0xc9, 0xf2, 0x26, 0x77, 0xe5, 0x5c, 0x7f, + 0xff, 0x07, 0x05, 0xb0, 0x1b, 0x30, 0xdb, 0x16, 0xd8, 0x01, 0x40, 0x82, 0x02, 0xd9, 0x42, 0x9d, 0x46, 0x67, 0x6a, + 0xa9, 0xc0, 0x7b, 0xae, 0x07, 0xf8, 0x9b, 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, 0xb7, 0x53, 0x45, 0x1e, 0x1f, 0xa5, 0x21, 0xaf, + 0xc0, 0x93, 0x8c, 0x23, 0x49, 0x94, 0x08, 0xde, 0xe4, 0x8d, 0x19, 0x87, 0x97, 0x6d, 0xca, 0xa9, 0xbd, 0x59, 0x2f, + 0x00, 0xe7, 0x09, 0xda, 0x32, 0xc0, 0x58, 0xc0, 0xe0, 0x5c, 0x88, 0x25, 0x4f, 0x11, 0xfc, 0xd2, 0x89, 0x14, 0xc6, + 0x5d, 0x0e, 0xc3, 0x3c, 0x28, 0x7a, 0x97, 0xd4, 0x1f, 0xfd, 0x3e, 0x6a, 0x93, 0xc1, 0x10, 0x54, 0x02, 0xa8, 0xac, + 0x1b, 0x24, 0x06, 0x56, 0xa5, 0x85, 0xc4, 0x25, 0xc4, 0xcb, 0x7c, 0x35, 0xad, 0xa3, 0xe0, 0x7d, 0x3d, 0x21, 0x84, + 0x13, 0x8c, 0x0f, 0x71, 0x03, 0x04, 0x0c, 0x56, 0x71, 0x81, 0x41, 0xf2, 0x5c, 0xa2, 0xfb, 0xe3, 0xf9, 0x8e, 0x01, + 0xae, 0x9c, 0xf7, 0x54, 0xbb, 0x7a, 0x60, 0x2f, 0x57, 0xe9, 0x92, 0x11, 0xc2, 0x8a, 0xff, 0x8b, 0xc8, 0xfb, 0x76, + 0x98, 0x80, 0xda, 0x46, 0xfe, 0x18, 0x24, 0xe6, 0x32, 0x51, 0x04, 0xf1, 0x28, 0x2b, 0x58, 0x92, 0x06, 0x9b, 0x51, + 0x92, 0x82, 0x46, 0x13, 0x63, 0xc8, 0x54, 0x68, 0x87, 0xa4, 0xd1, 0x6c, 0x4c, 0xf6, 0x31, 0xe4, 0x35, 0x5c, 0x2c, + 0x16, 0x78, 0xdf, 0xcf, 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, 0xcb, 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, 0x86, 0xd2, 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, 0xb3, 0xac, 0xc9, 0x5c, 0xbc, 0x2e, 0x1e, 0xbc, + 0x82, 0x3d, 0xf7, 0x07, 0xfa, 0x57, 0xc9, 0x9e, 0xfb, 0x36, 0x93, 0xeb, 0x9f, 0x69, 0xd7, 0x68, 0xcc, 0x74, 0xbc, + 0x76, 0x05, 0x56, 0x68, 0x80, 0xfc, 0x82, 0x1d, 0xed, 0x6d, 0x0e, 0x02, 0x01, 0xba, 0x97, 0xe0, 0x28, 0x0a, 0x88, + 0x9a, 0x56, 0x95, 0x47, 0xa7, 0x7b, 0x7f, 0x8f, 0x6f, 0x94, 0x80, 0x4d, 0x9e, 0x5a, 0xf7, 0x96, 0xb1, 0x7f, 0x38, + 0x40, 0x08, 0xbd, 0x9c, 0x7e, 0xa3, 0x2d, 0xab, 0x47, 0x3b, 0x96, 0xfb, 0x86, 0x51, 0x4f, 0xc1, 0x18, 0x86, 0x2e, + 0xac, 0x62, 0x24, 0xcf, 0x80, 0xac, 0xf1, 0x1b, 0x44, 0x17, 0xb0, 0xe8, 0xf5, 0x5e, 0x1f, 0xd1, 0x20, 0x02, 0x2a, + 0xbd, 0xe6, 0x2f, 0x45, 0x3e, 0x57, 0x85, 0xe8, 0xbd, 0xb7, 0x76, 0xde, 0xcc, 0x48, 0x96, 0x49, 0x23, 0xd5, 0x6e, + 0x65, 0xb1, 0xae, 0xbc, 0xd9, 0x09, 0xe9, 0x62, 0x8e, 0xa1, 0x32, 0x78, 0x1c, 0x80, 0xd2, 0xf3, 0x6f, 0xa1, 0x57, + 0x32, 0x64, 0x9a, 0x25, 0x9a, 0xd9, 0x5d, 0xe3, 0x4f, 0x56, 0xa9, 0x17, 0x23, 0x62, 0x36, 0xb0, 0x85, 0xb8, 0x2d, + 0x2a, 0xdd, 0x16, 0x85, 0xb2, 0x45, 0x91, 0x3e, 0xd4, 0xce, 0x74, 0x67, 0x16, 0x3e, 0xab, 0x4c, 0xfb, 0xde, 0x66, + 0x66, 0x6c, 0x80, 0xb6, 0x8b, 0xf0, 0x0d, 0x74, 0xa0, 0x42, 0xc8, 0x7f, 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, 0x5f, 0x53, + 0xb7, 0x67, 0xe5, 0x64, 0x2f, 0x3a, 0x27, 0xfb, 0x74, 0x36, 0x0f, 0x04, 0x97, 0x3b, 0xf7, 0x79, 0x3e, 0xd5, 0xd3, + 0xae, 0xf2, 0x83, 0xd6, 0x10, 0x99, 0x2f, 0x7c, 0xaa, 0xba, 0xd7, 0x15, 0x2c, 0x60, 0x09, 0xee, 0xd6, 0x4b, 0xf3, + 0x5f, 0xb1, 0xfb, 0x7b, 0x41, 0x2f, 0xcd, 0x7f, 0xa3, 0x3f, 0x29, 0x80, 0x03, 0xd0, 0x98, 0xda, 0x2d, 0xf0, 0x10, + 0x43, 0x05, 0x85, 0xbb, 0x59, 0x39, 0xf7, 0x6a, 0x80, 0xc3, 0x24, 0x7d, 0x43, 0xab, 0x57, 0x5a, 0xec, 0x7a, 0x99, + 0xec, 0x15, 0xe0, 0xa1, 0x0a, 0x79, 0x78, 0x38, 0x44, 0x1d, 0xc3, 0x0e, 0xea, 0x08, 0x18, 0xf6, 0x10, 0x1a, 0x5b, + 0xe0, 0xf9, 0xf8, 0x29, 0xe3, 0x7b, 0x01, 0x6a, 0x23, 0x84, 0xc7, 0xab, 0x45, 0x19, 0x62, 0xcb, 0xde, 0x22, 0x95, + 0xd4, 0xcf, 0x02, 0x51, 0x46, 0xab, 0x80, 0xb6, 0xda, 0x63, 0x96, 0xc6, 0x1b, 0x08, 0x15, 0x4b, 0x7d, 0x0c, 0xa1, + 0x81, 0xc3, 0xef, 0x70, 0x00, 0x09, 0xbe, 0xe4, 0x9a, 0x6c, 0xee, 0x6d, 0x7e, 0x4f, 0xfb, 0xfc, 0xe1, 0x70, 0x7e, + 0x89, 0xa0, 0x74, 0x29, 0x7c, 0xa4, 0x12, 0x51, 0x3d, 0xc5, 0x4d, 0x09, 0xd9, 0x2c, 0x59, 0xe9, 0x07, 0xbf, 0xaa, + 0x5f, 0x00, 0x20, 0x0b, 0x81, 0x36, 0x91, 0xd9, 0x9f, 0xce, 0x54, 0x74, 0x01, 0x70, 0x88, 0x3f, 0x7e, 0x82, 0xe8, + 0x1b, 0x5a, 0xa6, 0xe5, 0xe3, 0x84, 0x87, 0xa0, 0xb5, 0x25, 0x9d, 0x44, 0xac, 0x14, 0xd8, 0x10, 0x09, 0xdf, 0xef, + 0x9f, 0xc7, 0x92, 0x0e, 0x34, 0x6a, 0x75, 0x6f, 0xdc, 0xea, 0x5e, 0xf9, 0xba, 0xee, 0xe4, 0xc6, 0x07, 0x45, 0xfb, + 0x6c, 0xde, 0xa8, 0x7c, 0xdf, 0xd6, 0x39, 0xbb, 0xd3, 0xbd, 0x23, 0xe7, 0xc4, 0xb7, 0xf7, 0x10, 0x8a, 0x1e, 0x9a, + 0x22, 0xcb, 0x92, 0x30, 0xa0, 0xb5, 0x76, 0xed, 0x59, 0x46, 0x07, 0xaf, 0x7d, 0x43, 0x88, 0xc8, 0x53, 0x7c, 0x12, + 0x72, 0x8b, 0xe3, 0x83, 0x02, 0xfd, 0x33, 0xe3, 0xcf, 0x9c, 0xf8, 0x61, 0xab, 0x5f, 0x00, 0xe7, 0xa6, 0x7b, 0xef, + 0x4e, 0xcc, 0x7a, 0x0c, 0xa5, 0x6c, 0xfc, 0xdf, 0xef, 0x13, 0x59, 0xa0, 0xd3, 0x11, 0x0d, 0x03, 0xc1, 0x5d, 0x54, + 0xff, 0xf7, 0x8a, 0xd7, 0x3d, 0x6b, 0x75, 0xbe, 0xfc, 0xd4, 0xe9, 0x49, 0xaf, 0x5e, 0xc6, 0x3d, 0xa0, 0x42, 0x07, + 0x08, 0xe7, 0x75, 0xbf, 0x61, 0xbb, 0x6f, 0x7e, 0x79, 0x77, 0xf4, 0x32, 0xb0, 0x49, 0x91, 0xd8, 0x56, 0xf2, 0x59, + 0x0f, 0x14, 0x7e, 0x3d, 0xd6, 0xab, 0x8b, 0x75, 0x8f, 0xf5, 0x50, 0x0b, 0x88, 0x1e, 0x16, 0xa0, 0xfe, 0xeb, 0xd9, + 0xa7, 0xa1, 0x70, 0x90, 0x8d, 0x53, 0x05, 0x8a, 0x2c, 0xf8, 0x0b, 0x31, 0x5a, 0x17, 0x04, 0x88, 0x6c, 0x09, 0x69, + 0xd5, 0xc9, 0xec, 0x71, 0xa9, 0x25, 0x19, 0x7c, 0x13, 0x90, 0xd9, 0x81, 0x95, 0x13, 0x94, 0x8e, 0x5b, 0x03, 0xae, + 0x6c, 0xf1, 0x68, 0xb7, 0x3f, 0x0d, 0xb2, 0xb3, 0xe6, 0xa4, 0xd1, 0x3e, 0xec, 0xd3, 0x3c, 0x40, 0x20, 0x92, 0xa9, + 0x08, 0x72, 0xcd, 0xbd, 0x25, 0x7d, 0x74, 0x38, 0xe7, 0x85, 0xfc, 0x73, 0x2a, 0x75, 0x88, 0x43, 0x89, 0x35, 0x10, + 0xa8, 0x3c, 0x43, 0x95, 0xc3, 0x06, 0x39, 0xfe, 0xd9, 0x91, 0xcc, 0x24, 0x26, 0x8b, 0xdc, 0xad, 0x99, 0x0a, 0x3f, + 0x10, 0x7c, 0xcc, 0x72, 0x0e, 0x5c, 0x60, 0xb3, 0xb9, 0xaf, 0xa6, 0xb8, 0xb8, 0x02, 0x7f, 0x4c, 0xe1, 0x57, 0x3c, + 0x85, 0x9d, 0x76, 0xbf, 0x2e, 0xaa, 0x14, 0x75, 0x1b, 0x85, 0x45, 0x25, 0x0b, 0xa6, 0x35, 0xa4, 0x89, 0x0e, 0xa3, + 0x3f, 0xc8, 0x19, 0x28, 0x08, 0xf9, 0x65, 0xd3, 0x00, 0x23, 0x95, 0x5c, 0x1e, 0x54, 0x49, 0xe0, 0x05, 0xd8, 0x06, + 0x15, 0x5b, 0x17, 0x10, 0x64, 0x9b, 0x14, 0x65, 0xfa, 0xa5, 0xc8, 0xeb, 0x30, 0x0b, 0xaa, 0x51, 0x5a, 0xfd, 0xa8, + 0x7f, 0x02, 0xf3, 0x36, 0x15, 0xa3, 0x5a, 0xc5, 0xe4, 0x37, 0xfa, 0xfd, 0x62, 0xd0, 0xfa, 0x90, 0xc1, 0x47, 0xaf, + 0x4d, 0x83, 0x3f, 0x3a, 0x0d, 0x76, 0x98, 0x68, 0x04, 0x40, 0x32, 0xa7, 0x96, 0x3c, 0x14, 0xfd, 0x11, 0xe4, 0x58, + 0xa3, 0xca, 0x29, 0x18, 0xac, 0xff, 0x78, 0xb4, 0x03, 0x53, 0x2f, 0x8e, 0xb6, 0x64, 0x07, 0xad, 0x7c, 0x03, 0xdc, + 0xaf, 0x91, 0x2d, 0x66, 0x39, 0x40, 0xb3, 0xd7, 0x88, 0x8c, 0x4f, 0x5e, 0x00, 0x63, 0xb6, 0xce, 0xc2, 0x48, 0xc4, + 0xc1, 0x58, 0x35, 0x66, 0xcc, 0xc0, 0xc0, 0x05, 0xba, 0x96, 0x49, 0x49, 0x1a, 0xd2, 0xc1, 0x80, 0x95, 0xb2, 0x85, + 0x03, 0x5e, 0x34, 0xc7, 0xed, 0x78, 0xd3, 0xa2, 0xf1, 0xc0, 0x76, 0xb1, 0xfd, 0xfd, 0xf7, 0xc5, 0xf6, 0x3a, 0xdc, + 0x92, 0x5e, 0x21, 0x67, 0x09, 0xfd, 0xfc, 0x51, 0xf6, 0x59, 0xc3, 0xc9, 0xa9, 0xd0, 0x0c, 0x2d, 0x45, 0x42, 0x29, + 0xde, 0xe9, 0x49, 0x81, 0xb1, 0x8c, 0x85, 0xbf, 0x07, 0xce, 0xe9, 0x42, 0x11, 0xb9, 0x03, 0xc7, 0xf1, 0x0d, 0x54, + 0x30, 0x6a, 0x38, 0x78, 0x19, 0xc3, 0xb6, 0x28, 0x66, 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, + 0xe5, 0x41, 0x04, 0x90, 0xcf, 0xe1, 0x7d, 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, 0x8b, 0x33, 0xd8, 0x38, + 0xd7, 0x99, 0xe0, 0xc0, 0x8b, 0xa4, 0xd6, 0x6b, 0xc6, 0x5f, 0x64, 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, 0xfe, 0x5c, 0x49, 0x1c, 0x5a, 0x16, 0xc9, 0xbf, 0x77, 0x3d, + 0x7d, 0x85, 0xd4, 0x9d, 0x2c, 0x90, 0x19, 0xe3, 0x65, 0x1e, 0x7f, 0x02, 0xc2, 0x6c, 0xd0, 0x46, 0x45, 0x21, 0x84, + 0x6c, 0x10, 0x83, 0xc6, 0xcb, 0x3c, 0xfe, 0x5e, 0xd1, 0x78, 0xc8, 0x47, 0x91, 0xaf, 0xfe, 0x2a, 0xf5, 0x5f, 0xa1, + 0xcf, 0x4c, 0xf0, 0x08, 0xd5, 0x44, 0xff, 0xee, 0xf9, 0xec, 0x1e, 0xd4, 0x86, 0x51, 0x98, 0x99, 0xf2, 0x2b, 0xdf, + 0x14, 0x67, 0xaf, 0xbf, 0xa2, 0xab, 0x6c, 0xeb, 0x7e, 0xf4, 0xf1, 0x88, 0xc0, 0xda, 0x18, 0x5d, 0x71, 0x63, 0x00, + 0x39, 0x4c, 0xde, 0xaf, 0x28, 0x2d, 0x87, 0x34, 0x08, 0x1d, 0x34, 0x04, 0xbd, 0x92, 0xe8, 0x03, 0x89, 0x45, 0x8c, + 0xe1, 0x85, 0x78, 0x46, 0x6a, 0x32, 0xd1, 0x10, 0xaf, 0x88, 0xfd, 0x10, 0x2d, 0x39, 0x35, 0xd1, 0x8d, 0x30, 0xc5, + 0x40, 0x62, 0x67, 0x90, 0x9c, 0x24, 0xb5, 0xf2, 0x8b, 0x67, 0x92, 0xb0, 0xc4, 0xce, 0x43, 0x0c, 0x26, 0xb5, 0x74, + 0xa7, 0x37, 0x55, 0x7a, 0x77, 0xa4, 0xe5, 0xa0, 0x7d, 0x00, 0x76, 0x29, 0xe9, 0xfd, 0x93, 0x42, 0x11, 0x1f, 0xc2, + 0x38, 0x86, 0xf0, 0x2d, 0xa2, 0xba, 0x02, 0xe7, 0x5a, 0x81, 0xc6, 0x6a, 0xe0, 0xa1, 0x99, 0x55, 0xf3, 0x21, 0xa7, + 0x9f, 0x4a, 0xcb, 0x1f, 0x23, 0x1a, 0x1b, 0xad, 0x9b, 0xc3, 0x61, 0x4f, 0xab, 0x5e, 0x3a, 0x07, 0x5d, 0x36, 0x93, + 0x98, 0xb8, 0x81, 0x74, 0xfd, 0xe8, 0x37, 0x13, 0xf6, 0x22, 0x2a, 0xe4, 0x52, 0x08, 0x0a, 0x5a, 0x1d, 0x08, 0x1c, + 0x0a, 0x6f, 0x51, 0xe6, 0x8b, 0x98, 0x36, 0x10, 0x06, 0x9f, 0x1f, 0xc8, 0xcf, 0x37, 0x05, 0xa9, 0xd8, 0xb1, 0xae, + 0xfd, 0xfe, 0xa6, 0xf4, 0x00, 0x4f, 0xce, 0x24, 0x79, 0xda, 0x0c, 0x61, 0x45, 0x00, 0x8d, 0x59, 0x4d, 0x16, 0x27, + 0x5c, 0x99, 0xc3, 0x8f, 0x95, 0x57, 0xb2, 0x94, 0xa9, 0xf3, 0x54, 0x2f, 0x80, 0xa8, 0xe3, 0x0d, 0x5a, 0x91, 0xfa, + 0x15, 0x3a, 0x7b, 0xcd, 0x4a, 0xc8, 0x78, 0x78, 0xce, 0x79, 0x3a, 0x7a, 0x60, 0x09, 0x8f, 0xf0, 0xaf, 0x64, 0xa2, + 0x0f, 0xbf, 0x07, 0x0e, 0x37, 0xe3, 0x84, 0x47, 0x6e, 0xb3, 0xf7, 0x55, 0xb8, 0x82, 0x9b, 0x69, 0x01, 0x48, 0x6e, + 0x41, 0xd2, 0x04, 0x94, 0x90, 0xc8, 0x84, 0xcc, 0x9a, 0x92, 0x9f, 0x5b, 0xda, 0x06, 0x6b, 0x98, 0x74, 0x1e, 0xf0, + 0xa2, 0xd5, 0x47, 0xab, 0x89, 0x76, 0x99, 0xe5, 0xf3, 0x21, 0xce, 0x50, 0xcd, 0x71, 0x77, 0x06, 0x3f, 0x07, 0xbc, + 0x62, 0x55, 0x93, 0x8e, 0x76, 0x03, 0x2e, 0x3c, 0xb9, 0xce, 0xd3, 0xd1, 0x16, 0x7f, 0xc9, 0xfd, 0x01, 0xa0, 0x83, + 0xa9, 0x4b, 0xe0, 0x4f, 0xd5, 0x56, 0x53, 0xa9, 0x5f, 0x5a, 0xfb, 0x75, 0xdd, 0x59, 0xad, 0xdc, 0xb3, 0x2e, 0x43, + 0x7b, 0x64, 0xc8, 0x19, 0x33, 0xe0, 0xcf, 0x19, 0x4b, 0xfe, 0x9c, 0xb1, 0xe2, 0xcf, 0x19, 0x37, 0x46, 0x06, 0x50, + 0x82, 0x7b, 0xc9, 0x5f, 0xec, 0x11, 0x33, 0xc4, 0x6a, 0x50, 0x09, 0xac, 0x2c, 0xe5, 0xdc, 0x47, 0x4e, 0x31, 0xe5, + 0x94, 0xe1, 0xa5, 0xd3, 0x99, 0x3b, 0x90, 0xf3, 0x60, 0xe6, 0x0e, 0x93, 0xb3, 0x3e, 0xc5, 0xb1, 0x34, 0x26, 0x45, 0x05, 0xe9, 0x9c, 0x0e, 0x37, 0xaf, 0x8e, 0xf3, 0x84, 0x65, 0x7c, 0xdc, 0x3e, 0x53, 0x20, 0xc4, 0x16, 0xcf, 0x90, - 0x48, 0xa9, 0x9a, 0xe5, 0x36, 0x7f, 0x3c, 0xd6, 0xa3, 0x07, 0xbd, 0xd3, 0xc3, 0xaf, 0x84, 0xfd, 0x92, 0x79, 0xf6, - 0x09, 0x02, 0x98, 0x24, 0xf2, 0x4c, 0xc2, 0xd1, 0x8f, 0xe5, 0xe8, 0x6f, 0x1b, 0xfe, 0x25, 0x43, 0x75, 0x77, 0x08, - 0x4c, 0x6c, 0xd9, 0x91, 0x43, 0x70, 0xba, 0xaa, 0x44, 0x02, 0x0e, 0x36, 0x5b, 0x16, 0xe9, 0x3d, 0x1e, 0xe2, 0x7c, - 0x50, 0xf8, 0x08, 0x0d, 0x33, 0x7a, 0xbf, 0xbf, 0x15, 0x5e, 0x2e, 0x5b, 0x79, 0x3c, 0x26, 0xd6, 0x5d, 0xd8, 0xd1, - 0xc7, 0xd1, 0x1e, 0x25, 0xd4, 0x7e, 0x54, 0xeb, 0x4d, 0xa5, 0x1e, 0x54, 0x66, 0x17, 0x12, 0x83, 0x9c, 0xa5, 0xfa, - 0xf4, 0x4a, 0xf5, 0xa1, 0x66, 0x9d, 0xdf, 0xf9, 0x69, 0x9f, 0x8a, 0xd1, 0x46, 0x4e, 0x08, 0x70, 0x1d, 0x24, 0x1a, - 0x1d, 0x00, 0xe3, 0x6c, 0xb3, 0xe5, 0xa5, 0xb6, 0x4e, 0x94, 0x8e, 0xe3, 0x4a, 0x1f, 0xc7, 0xc7, 0xa3, 0x14, 0x33, - 0xae, 0x4f, 0xc4, 0x8c, 0xeb, 0x06, 0xe0, 0xcd, 0x3a, 0x0f, 0xea, 0xe3, 0xf1, 0x9a, 0x2e, 0x45, 0xa6, 0xb3, 0x8d, - 0xf2, 0xb3, 0x1e, 0x3d, 0x3c, 0x4d, 0xd0, 0xdc, 0x5b, 0x61, 0xef, 0x45, 0xb2, 0x3d, 0x93, 0x4d, 0xea, 0x65, 0xe4, - 0xd3, 0x0b, 0xf7, 0xec, 0x92, 0xab, 0x1f, 0x56, 0x5f, 0x4f, 0x7f, 0x15, 0x5e, 0xc4, 0x72, 0xda, 0xad, 0x4b, 0x26, - 0xec, 0x2d, 0x25, 0x97, 0x56, 0x79, 0xf9, 0x74, 0xeb, 0x07, 0x98, 0x99, 0xf6, 0xf4, 0x41, 0x36, 0xa2, 0xfa, 0xb3, + 0x48, 0xa9, 0x9a, 0xe5, 0x36, 0x7f, 0x38, 0xd4, 0xa3, 0x07, 0xbd, 0xd3, 0xc3, 0xaf, 0x84, 0xfd, 0x92, 0x79, 0xf6, + 0x09, 0x02, 0x98, 0x24, 0xf2, 0x4c, 0xc2, 0xd1, 0x8f, 0xe5, 0xe8, 0x6f, 0x1a, 0xfe, 0x2e, 0x43, 0x75, 0x77, 0x08, + 0x4c, 0x6c, 0xd9, 0x81, 0x43, 0x70, 0xba, 0xaa, 0x44, 0x02, 0x0e, 0x36, 0x1b, 0x16, 0xe9, 0x3d, 0x1e, 0xe2, 0x7c, + 0x50, 0xf8, 0x08, 0x0d, 0x33, 0x7a, 0xbf, 0xbf, 0x11, 0x5e, 0x25, 0x5b, 0x79, 0x38, 0x24, 0xd6, 0x5d, 0xd8, 0xd1, + 0xc7, 0xd1, 0x1e, 0x25, 0xd4, 0x7e, 0x54, 0xeb, 0x4d, 0xa5, 0x1e, 0xe4, 0x66, 0x17, 0x12, 0x83, 0x8a, 0xa5, 0xfa, + 0xf4, 0x4a, 0xf5, 0xa1, 0x66, 0x9d, 0xdf, 0xd5, 0x71, 0x9f, 0x8a, 0xd1, 0x5a, 0x4e, 0x08, 0x70, 0x1d, 0x24, 0x1a, + 0x1d, 0x00, 0xe3, 0x6c, 0xb3, 0xe5, 0xa5, 0xb6, 0x4e, 0x94, 0x8e, 0xe3, 0x5c, 0x1f, 0xc7, 0x87, 0x83, 0x14, 0x33, + 0x2e, 0x8f, 0xc4, 0x8c, 0xcb, 0x06, 0xe0, 0xcd, 0x3a, 0x0f, 0xea, 0xc3, 0xe1, 0x92, 0x2e, 0x45, 0xa6, 0xb3, 0x8d, + 0xf2, 0xb3, 0x1e, 0x3d, 0x3c, 0x4b, 0xd0, 0xdc, 0x5b, 0x61, 0xef, 0x45, 0xb2, 0x3d, 0x93, 0x75, 0xea, 0x65, 0xe4, + 0xd3, 0x0b, 0xf7, 0xec, 0x92, 0xab, 0x1f, 0x56, 0x5f, 0x4f, 0x7f, 0x15, 0x5e, 0xc4, 0x2a, 0xda, 0xad, 0x4b, 0x26, + 0xec, 0x2d, 0xa5, 0x92, 0x56, 0x79, 0xf9, 0x74, 0xe3, 0x07, 0x98, 0x99, 0xf6, 0xf4, 0x41, 0x36, 0xa2, 0xfa, 0xb3, 0x12, 0xb5, 0x32, 0x4c, 0x16, 0xce, 0x4b, 0xa6, 0x9e, 0x0c, 0x78, 0xcc, 0x4a, 0x1e, 0xc9, 0x4e, 0x6f, 0x0c, 0x82, - 0x00, 0xd6, 0x39, 0x69, 0xd5, 0x19, 0x47, 0xa3, 0x55, 0xe5, 0xe2, 0x7c, 0x95, 0x0b, 0x0c, 0xb7, 0xdb, 0xb0, 0xad, - 0xaa, 0xb3, 0xdc, 0xd4, 0x72, 0xe5, 0x3b, 0x80, 0x8f, 0x65, 0x95, 0x0b, 0x3a, 0xa6, 0x4c, 0x9d, 0xb7, 0x10, 0x8c, - 0xad, 0x6a, 0x5c, 0x38, 0x35, 0x2e, 0x78, 0x44, 0xed, 0x6e, 0x9a, 0x7a, 0xb4, 0x03, 0x96, 0xd2, 0xd1, 0x9e, 0x97, - 0xa8, 0x52, 0xf8, 0x9b, 0xe0, 0x87, 0x30, 0x8e, 0x7f, 0x28, 0x76, 0xea, 0x40, 0xbc, 0x2b, 0x76, 0x48, 0xfb, 0x22, + 0x00, 0xd6, 0x39, 0x69, 0xd5, 0x19, 0x47, 0xa3, 0x55, 0xe5, 0xe2, 0x74, 0x95, 0x0b, 0x0c, 0xb7, 0x5b, 0xb3, 0x8d, + 0xaa, 0xb3, 0xdc, 0xd4, 0x2a, 0xe5, 0x3b, 0x80, 0x8f, 0x65, 0x95, 0x0b, 0x3a, 0xa6, 0x4c, 0x9d, 0x37, 0x10, 0x8c, + 0xad, 0x6a, 0x5c, 0x38, 0x35, 0x2e, 0x78, 0x44, 0xed, 0x6e, 0x9a, 0x7a, 0xb4, 0x05, 0x96, 0xd2, 0xd1, 0x8e, 0x97, + 0xa8, 0x52, 0xf8, 0xbb, 0xe0, 0xfb, 0x30, 0x8e, 0xbf, 0x2f, 0xb6, 0xea, 0x40, 0xbc, 0x2d, 0xb6, 0x48, 0xfb, 0x22, 0xff, 0x42, 0x1c, 0xf0, 0x5a, 0xd7, 0x94, 0xd7, 0xd6, 0x9c, 0x06, 0xb6, 0x86, 0x91, 0x92, 0xc2, 0xb9, 0xf9, 0xf3, - 0x78, 0xa4, 0x95, 0x5d, 0xab, 0xbb, 0x42, 0xad, 0xc7, 0x1c, 0x36, 0xec, 0x45, 0x16, 0xee, 0x45, 0x09, 0x7e, 0x13, - 0xf2, 0xaf, 0xe3, 0x51, 0xab, 0x2c, 0xd5, 0x91, 0x3e, 0x3b, 0x7c, 0x09, 0xc6, 0x0c, 0x5d, 0x9a, 0x80, 0x65, 0x63, + 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, 0x09, 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, 0xd7, 0x13, 0x71, 0x49, 0x97, 0x24, 0xf5, 0x54, 0x42, - 0x49, 0x08, 0x76, 0xed, 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, 0xcb, - 0x79, 0x58, 0x1b, 0x26, 0xb9, 0x51, 0x16, 0xee, 0x8b, 0x6d, 0xad, 0x96, 0xa7, 0xe3, 0x30, 0x02, 0x33, 0x82, 0x02, - 0x64, 0x5d, 0xb7, 0x11, 0x31, 0xcc, 0xe5, 0x32, 0x21, 0x9f, 0x10, 0x90, 0x45, 0xa9, 0x71, 0x3e, 0x6e, 0x81, 0x4a, - 0x04, 0x83, 0xd3, 0xd0, 0x5a, 0x75, 0x93, 0xbf, 0xaa, 0x6c, 0x6c, 0x05, 0xe4, 0x90, 0x64, 0xb2, 0x58, 0x8d, 0xee, - 0xc4, 0xb2, 0x28, 0xc5, 0xcf, 0x58, 0x0f, 0xd7, 0x6c, 0xe1, 0x3e, 0x03, 0x42, 0xfb, 0x89, 0xd2, 0xde, 0x44, 0x9a, - 0xa0, 0x7b, 0xc5, 0xd6, 0x00, 0x32, 0x80, 0xa2, 0xae, 0x76, 0xeb, 0x73, 0x7e, 0x8e, 0xa4, 0x19, 0x0e, 0xa3, 0xdb, - 0xa7, 0xab, 0x60, 0x35, 0xb8, 0x46, 0xad, 0xf4, 0x35, 0x8b, 0x5b, 0x18, 0x54, 0x07, 0xb3, 0x84, 0x83, 0x9a, 0x59, - 0x6b, 0x23, 0x10, 0x4c, 0xf6, 0x50, 0x90, 0x33, 0x57, 0xb0, 0x0f, 0x0a, 0xd6, 0x92, 0xd7, 0xc1, 0xe1, 0xd6, 0xbe, - 0xac, 0x14, 0x57, 0xcf, 0xae, 0x92, 0xd6, 0x85, 0xa5, 0xbc, 0x7a, 0xd6, 0x80, 0xc1, 0xe5, 0x04, 0x9b, 0x2a, 0xf7, - 0x27, 0x5b, 0x00, 0xdd, 0x0a, 0x29, 0xe2, 0x45, 0x29, 0x6c, 0x5b, 0xf9, 0xcc, 0x09, 0x1b, 0x6c, 0xd9, 0x03, 0xdc, - 0x2b, 0x83, 0x92, 0xc1, 0x85, 0x18, 0xb7, 0x9b, 0x7d, 0x80, 0x2b, 0x18, 0x0a, 0x63, 0x1b, 0xfe, 0x3a, 0xf3, 0x22, - 0x25, 0xe0, 0x66, 0x88, 0xf2, 0xb5, 0x85, 0x93, 0x49, 0x4f, 0xae, 0x25, 0x8b, 0x01, 0x0b, 0x1a, 0x7c, 0x47, 0xad, - 0xbf, 0x33, 0xf9, 0x37, 0x9e, 0x1e, 0xfa, 0xc1, 0xe7, 0xcc, 0x5b, 0xfa, 0xec, 0x75, 0x2e, 0xa3, 0x35, 0x49, 0x94, - 0x57, 0x0f, 0x97, 0x20, 0x37, 0x2c, 0x47, 0x0f, 0x6c, 0x09, 0xe2, 0xc4, 0x72, 0x94, 0x50, 0x46, 0x57, 0xb8, 0x57, - 0x99, 0x2d, 0x13, 0x81, 0x14, 0x07, 0x96, 0x52, 0xee, 0x2d, 0x36, 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, 0xa1, - 0x61, 0x7f, 0xf5, 0x42, 0xcb, 0xfe, 0xb0, 0xd2, 0x9a, 0x86, 0x35, 0x5f, 0xc1, 0xb4, 0x98, 0xb8, 0x7d, 0xb9, 0xb6, - 0xab, 0xe2, 0xb3, 0xb5, 0x3a, 0xbb, 0xa9, 0x21, 0x09, 0xfb, 0x8a, 0xac, 0x02, 0x1c, 0xac, 0x8a, 0xb8, 0x67, 0x59, - 0x1e, 0xc2, 0xe8, 0xcf, 0x6d, 0x5a, 0x0a, 0x0b, 0x55, 0xd2, 0x3f, 0x34, 0xa5, 0x40, 0x2a, 0x13, 0x9d, 0x68, 0x21, - 0xb8, 0x02, 0x83, 0xc0, 0xbd, 0xc8, 0x6b, 0x00, 0x8c, 0x01, 0x97, 0x02, 0x65, 0xd9, 0x96, 0x10, 0x52, 0xdd, 0xcf, - 0x40, 0x6d, 0x27, 0xee, 0xd3, 0x88, 0xac, 0x85, 0xe8, 0xab, 0x60, 0xcc, 0x9c, 0xd7, 0xd2, 0x2d, 0x36, 0x5d, 0x6f, - 0xd7, 0xb7, 0xe8, 0x5c, 0xda, 0x72, 0xf3, 0x13, 0xb6, 0x58, 0x2b, 0x50, 0x36, 0x21, 0x69, 0xbb, 0xe2, 0x15, 0xca, - 0x26, 0xb4, 0xb4, 0x0f, 0xd4, 0xa3, 0x42, 0x75, 0xb2, 0xf5, 0x52, 0x3e, 0xb5, 0x08, 0xab, 0xc5, 0x55, 0xee, 0x07, - 0xa0, 0x9b, 0x4a, 0xab, 0x17, 0x75, 0x8d, 0xa6, 0x50, 0xab, 0x85, 0xe3, 0x46, 0x3b, 0x9b, 0x2e, 0xd3, 0x15, 0xe2, - 0xac, 0x4a, 0x3b, 0xf4, 0x0f, 0x99, 0x76, 0xbd, 0xec, 0xe8, 0x37, 0xe3, 0xea, 0x02, 0x17, 0x62, 0x03, 0x3e, 0xe7, - 0xfe, 0xf2, 0x7a, 0xcf, 0xe2, 0x1e, 0x44, 0x3c, 0x03, 0x7b, 0x52, 0xfb, 0x43, 0xf5, 0xa9, 0x2b, 0x18, 0xb2, 0x30, - 0x4a, 0xfd, 0x45, 0xca, 0x7b, 0x4f, 0x70, 0xdc, 0x3f, 0x57, 0x3d, 0xf6, 0xd7, 0x8c, 0x1f, 0xea, 0x62, 0x1b, 0x25, - 0x14, 0xd5, 0xd0, 0x5b, 0x17, 0xdb, 0x4a, 0xc4, 0xc5, 0x43, 0xde, 0x63, 0x98, 0x0c, 0x63, 0x21, 0x53, 0xe1, 0x4f, - 0x99, 0x0a, 0x1e, 0x21, 0x94, 0xb8, 0xdd, 0xf4, 0x48, 0xbb, 0x09, 0x71, 0x4a, 0xb5, 0x28, 0x65, 0x32, 0xfe, 0xad, - 0x9f, 0x40, 0x79, 0x4e, 0xd1, 0x32, 0xfd, 0xa4, 0x70, 0x99, 0xbe, 0xdd, 0x9c, 0x96, 0x9e, 0x89, 0x50, 0x67, 0x2e, - 0xb6, 0xb5, 0x4e, 0xc7, 0xd8, 0x29, 0x9d, 0xda, 0xb0, 0x77, 0xb9, 0xe2, 0xb2, 0xa2, 0xf0, 0x6f, 0x24, 0xb2, 0xea, - 0x19, 0x71, 0xfc, 0x9f, 0x59, 0xfb, 0x0c, 0xab, 0xc0, 0x2f, 0x03, 0x79, 0xbf, 0x00, 0xf8, 0xb8, 0xae, 0xcb, 0xf4, - 0x6e, 0x0b, 0xb4, 0x21, 0x34, 0xfc, 0x3d, 0x1f, 0x19, 0x30, 0xdd, 0x47, 0x38, 0x43, 0x7a, 0xa8, 0x73, 0x4e, 0x67, - 0x65, 0x3a, 0xe7, 0x2a, 0xac, 0x25, 0x38, 0xc8, 0x49, 0x53, 0xc9, 0x75, 0x09, 0x6a, 0x26, 0x70, 0xfb, 0xd0, 0x1e, - 0x11, 0x42, 0x6d, 0xca, 0x6a, 0x7a, 0x09, 0x35, 0xef, 0xe4, 0xb4, 0xa3, 0x49, 0x09, 0xae, 0x1a, 0x3a, 0x2b, 0xd7, - 0x7f, 0x1d, 0x8f, 0xbd, 0xbb, 0xac, 0x88, 0xfe, 0xe8, 0xa1, 0xbf, 0xe3, 0xee, 0x36, 0xfd, 0x02, 0xd1, 0x32, 0xd6, - 0xdf, 0x90, 0x01, 0x1d, 0x4f, 0x86, 0x77, 0xc5, 0xae, 0xc7, 0xde, 0xe5, 0x78, 0x81, 0x55, 0xd7, 0x8f, 0x3f, 0x40, - 0x42, 0xd5, 0xb5, 0x2f, 0x2c, 0x9e, 0x30, 0x4f, 0x89, 0xb6, 0x85, 0x0f, 0x61, 0xa1, 0xef, 0x72, 0xd8, 0x84, 0xa1, - 0x79, 0xd4, 0x3d, 0x4a, 0xda, 0x85, 0xbe, 0xf4, 0xb5, 0xec, 0x2b, 0xdf, 0xb9, 0x02, 0x58, 0xd9, 0x67, 0x36, 0xdc, - 0x93, 0xfe, 0x94, 0xea, 0xc3, 0xf6, 0xb7, 0x64, 0x01, 0x85, 0x16, 0xd6, 0x53, 0x39, 0x3b, 0x37, 0x25, 0x4f, 0xb3, - 0xe9, 0x61, 0x03, 0x7b, 0xd4, 0x3d, 0x7a, 0x4d, 0x05, 0x97, 0xd7, 0x66, 0xf4, 0xfe, 0x61, 0x28, 0x54, 0x47, 0x9d, - 0x3b, 0xc8, 0xa6, 0xb4, 0x2e, 0x39, 0xbf, 0x59, 0xb9, 0xa3, 0x30, 0xbf, 0x0f, 0xc1, 0x33, 0xac, 0x7b, 0x77, 0x71, - 0xde, 0xfb, 0xb3, 0x35, 0x47, 0xfe, 0x9a, 0xcd, 0x52, 0xc4, 0x22, 0x99, 0x83, 0xd5, 0x0f, 0xfd, 0x3c, 0x0e, 0xbb, - 0xa0, 0x82, 0xe3, 0xa6, 0x01, 0x1d, 0x36, 0x64, 0xd6, 0xbe, 0x44, 0xe0, 0x54, 0x23, 0x48, 0x53, 0x13, 0xd4, 0x2c, - 0x0f, 0x91, 0xd8, 0x2e, 0x65, 0xbb, 0xc0, 0xd0, 0xb6, 0x4d, 0x89, 0xf6, 0x0c, 0xde, 0x37, 0x69, 0x39, 0x51, 0xa1, - 0x59, 0xa4, 0xad, 0x92, 0xf1, 0xef, 0x44, 0x9b, 0x29, 0xd9, 0x63, 0x6b, 0xe0, 0xbd, 0x04, 0xe5, 0x64, 0x98, 0x62, - 0xf8, 0x8e, 0xaf, 0x77, 0x1e, 0x73, 0xcf, 0x39, 0x65, 0x9b, 0x94, 0x1d, 0xc1, 0x72, 0x22, 0x1b, 0xdf, 0x52, 0xbc, - 0xe1, 0xfb, 0xbb, 0x4a, 0x94, 0x00, 0x7a, 0x59, 0xf0, 0xe7, 0xd2, 0xe6, 0x0a, 0xdd, 0xee, 0xde, 0x51, 0x0a, 0xbf, - 0xe4, 0xe5, 0xf1, 0xb8, 0x4b, 0xbd, 0x10, 0x3a, 0x5f, 0xc4, 0xef, 0xc0, 0x1c, 0xc6, 0x10, 0x9b, 0x11, 0x20, 0xcc, - 0xf1, 0x01, 0x75, 0xb0, 0x7e, 0x04, 0xa0, 0x71, 0x02, 0x05, 0x18, 0x7d, 0xb5, 0x2d, 0xe8, 0x5b, 0x5e, 0x5c, 0x44, - 0x88, 0x1a, 0x05, 0x98, 0x28, 0x69, 0x16, 0xc3, 0x70, 0xa0, 0xf3, 0xfb, 0xf6, 0xae, 0x2e, 0x05, 0x0e, 0xbd, 0x63, - 0x19, 0xfe, 0xdb, 0xff, 0x58, 0x5b, 0x5a, 0x55, 0xb6, 0x5b, 0xe3, 0x34, 0xf3, 0xbf, 0xdd, 0x16, 0xfa, 0xfe, 0x4b, - 0xa1, 0x78, 0xde, 0xf1, 0xba, 0xfd, 0x05, 0xa2, 0xf7, 0x75, 0x2b, 0x57, 0xa5, 0x76, 0xc3, 0x4c, 0xf9, 0x43, 0x9a, - 0xc7, 0xc5, 0xc3, 0x28, 0x6e, 0x1d, 0x79, 0x93, 0xf4, 0x92, 0xf3, 0x2f, 0xe0, 0x6c, 0xfd, 0x05, 0xc8, 0x78, 0x5f, - 0x0a, 0xe3, 0x88, 0x49, 0x1c, 0x7c, 0x07, 0x31, 0x8a, 0xb6, 0x25, 0x6c, 0xc8, 0xed, 0xd3, 0x12, 0x34, 0x33, 0xfd, - 0x3e, 0x4a, 0x94, 0xd6, 0x7c, 0xff, 0x8b, 0x9c, 0xef, 0x2f, 0x85, 0xbc, 0x59, 0xc9, 0x0f, 0x9f, 0xac, 0x30, 0xf0, - 0x3d, 0x4e, 0xbf, 0x88, 0x1e, 0x5b, 0x95, 0x3e, 0x7c, 0x57, 0x5a, 0xfa, 0xac, 0xa2, 0xfe, 0x8e, 0x8a, 0x9a, 0x97, - 0x62, 0x44, 0xc4, 0x83, 0xa0, 0x9d, 0x6d, 0x97, 0xda, 0xb5, 0x04, 0xed, 0x82, 0x4d, 0x61, 0xff, 0x7a, 0x6c, 0xc8, - 0xab, 0x7e, 0xff, 0xe7, 0xca, 0x6b, 0xf1, 0xba, 0xeb, 0xd0, 0x94, 0x9f, 0x0a, 0x0f, 0x21, 0x80, 0xb5, 0x0c, 0x94, - 0xf1, 0x1c, 0x60, 0xd2, 0x45, 0x5e, 0xa3, 0x6c, 0x3a, 0x11, 0xf8, 0x98, 0x65, 0x37, 0x4e, 0x32, 0x0d, 0x30, 0xa3, - 0x9a, 0x62, 0xcc, 0x8a, 0x78, 0xb8, 0xf8, 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, 0xee, 0x33, 0x1c, 0x96, 0xc2, 0x31, - 0xe2, 0xff, 0x2d, 0x55, 0x3d, 0x22, 0xd0, 0xab, 0x32, 0xad, 0xa2, 0x22, 0xcf, 0x45, 0x84, 0x08, 0xd5, 0xd2, 0x39, - 0x1c, 0xfa, 0xb1, 0xdf, 0xc7, 0x81, 0x30, 0x2f, 0xfe, 0xf4, 0x58, 0x57, 0xfe, 0x54, 0xe0, 0x5a, 0x49, 0x81, 0x53, - 0x51, 0x23, 0x44, 0x08, 0xef, 0x4f, 0xe0, 0x59, 0x4d, 0x7d, 0xbf, 0xb1, 0x4c, 0x74, 0xff, 0xc8, 0x80, 0xf2, 0x07, - 0xe4, 0xeb, 0x5c, 0x8a, 0x33, 0x75, 0xf2, 0x98, 0x38, 0xe3, 0x00, 0xc4, 0x7c, 0x5d, 0xa2, 0xd1, 0xd8, 0xff, 0x80, - 0x04, 0x43, 0xf5, 0x83, 0x9d, 0x6e, 0xea, 0xfd, 0x33, 0x93, 0x38, 0x8a, 0x3e, 0x6d, 0x93, 0xa7, 0x92, 0xa5, 0xd1, - 0xc2, 0xd1, 0x7b, 0xc4, 0x30, 0x0e, 0xa7, 0xf3, 0x29, 0xc9, 0x36, 0x26, 0xab, 0x00, 0xd2, 0xc9, 0x4c, 0x1d, 0x53, - 0xea, 0x68, 0x9c, 0xeb, 0x05, 0x55, 0xe8, 0xb1, 0x2e, 0x79, 0x05, 0xd6, 0x93, 0x1f, 0xbd, 0xd2, 0x9f, 0x0a, 0x39, - 0x87, 0x8d, 0x44, 0x50, 0xf8, 0x01, 0xae, 0x06, 0x2b, 0x05, 0x0c, 0xa6, 0xbe, 0x85, 0xaf, 0x89, 0xe7, 0x28, 0x78, - 0x14, 0x76, 0x31, 0xb6, 0xe6, 0xbe, 0xf3, 0x49, 0x41, 0xb9, 0x67, 0xc5, 0x9c, 0xe7, 0xc0, 0xb9, 0x0c, 0x0a, 0x61, - 0x3a, 0x9e, 0xe5, 0xff, 0x4c, 0xf2, 0x7a, 0x62, 0x43, 0x80, 0x0c, 0xfe, 0x9c, 0x38, 0x2d, 0xdd, 0xa1, 0x3b, 0x0f, - 0x3d, 0x8b, 0x38, 0x6c, 0xf4, 0x64, 0x53, 0x16, 0xbb, 0x14, 0xf5, 0x12, 0xe6, 0x07, 0xf2, 0xf3, 0x96, 0xfc, 0x10, - 0xa2, 0x78, 0x1b, 0xfc, 0x9a, 0xb1, 0x58, 0xe0, 0x5f, 0x7f, 0xcb, 0x18, 0x4d, 0xb4, 0xe0, 0x5f, 0x59, 0x83, 0x44, - 0xc5, 0x3f, 0x65, 0x93, 0x1c, 0xb8, 0x4c, 0xd5, 0x87, 0xcf, 0x89, 0xf1, 0xd6, 0x6c, 0x78, 0xe4, 0x9b, 0x39, 0xe8, - 0xd4, 0xe7, 0xee, 0xca, 0xf6, 0x54, 0x35, 0xfe, 0x96, 0xea, 0x6a, 0xa4, 0xaa, 0x1a, 0x7f, 0x4b, 0xa9, 0x1a, 0xbf, - 0x65, 0x14, 0xbf, 0x93, 0xfb, 0x0c, 0x99, 0x93, 0x4d, 0x4c, 0xd2, 0xf9, 0x7b, 0xc3, 0x99, 0x5d, 0xf6, 0xab, 0xb7, - 0x89, 0xcc, 0x44, 0x0a, 0xb9, 0x37, 0x00, 0x35, 0x13, 0x7f, 0xae, 0x0c, 0xa7, 0xc4, 0xe5, 0xa5, 0x87, 0x2b, 0x36, - 0xad, 0x5e, 0xd2, 0x82, 0x05, 0x36, 0x2f, 0xb3, 0x3c, 0x45, 0x02, 0xdb, 0xa6, 0xcc, 0xfa, 0xa9, 0xf2, 0x00, 0x82, - 0x99, 0xd4, 0x04, 0x80, 0xb4, 0x10, 0x95, 0x42, 0xe4, 0x2f, 0x71, 0x56, 0x5f, 0xf2, 0xde, 0x36, 0x8f, 0x89, 0xb4, - 0xba, 0xd7, 0xef, 0xa7, 0x17, 0x69, 0x4e, 0x41, 0x0d, 0xa7, 0x59, 0xa7, 0x3f, 0x64, 0x41, 0x9d, 0xc8, 0x55, 0xfa, - 0x77, 0x37, 0xc8, 0xcb, 0xf8, 0xbe, 0xee, 0x7a, 0xfe, 0x44, 0xfd, 0xbd, 0xb7, 0xfe, 0xb6, 0x40, 0x70, 0x27, 0xa7, - 0x7e, 0xb2, 0x2a, 0xe5, 0x89, 0x71, 0x69, 0xef, 0xf9, 0x4d, 0x5d, 0x14, 0x59, 0x9d, 0x6e, 0x3e, 0x48, 0x3d, 0x8d, - 0xee, 0x8b, 0x03, 0x18, 0x83, 0xf7, 0x00, 0x78, 0xa6, 0x43, 0x03, 0xa4, 0xef, 0x19, 0x79, 0xb8, 0xcf, 0x2d, 0xf9, - 0x49, 0x65, 0x6d, 0x92, 0xb0, 0xa2, 0xd8, 0x0c, 0x63, 0x84, 0x92, 0x71, 0x1a, 0x3b, 0xbf, 0xdf, 0x57, 0x7f, 0xef, - 0x31, 0x8a, 0x8a, 0x8a, 0x3b, 0x45, 0xa3, 0xb2, 0xaa, 0x47, 0xdb, 0xc1, 0xf1, 0x78, 0x59, 0xd9, 0x38, 0xda, 0x7a, - 0x05, 0x1c, 0xac, 0x50, 0x29, 0x7b, 0x25, 0xc2, 0xf2, 0xc3, 0x95, 0xdf, 0xef, 0xc3, 0xbf, 0x32, 0xd2, 0xc2, 0xf3, - 0xa7, 0xf8, 0x6b, 0x51, 0x17, 0x18, 0x9e, 0x41, 0x6b, 0x34, 0x87, 0x60, 0x82, 0xbf, 0x77, 0xa0, 0x5e, 0x5a, 0x69, - 0x1f, 0x41, 0xb7, 0x02, 0x3d, 0xa8, 0x87, 0x3e, 0x4d, 0xda, 0x17, 0x12, 0x75, 0x7b, 0xab, 0xd3, 0xe8, 0x8f, 0x0a, - 0x2e, 0xa7, 0x30, 0x39, 0xdc, 0xd0, 0xa7, 0x75, 0xb8, 0xfb, 0x04, 0x4f, 0x7f, 0x06, 0xca, 0xad, 0xe3, 0x11, 0xc5, - 0x16, 0x70, 0xf3, 0x58, 0x87, 0x9f, 0x8b, 0x52, 0x46, 0xd4, 0xc7, 0xd3, 0x02, 0xb4, 0x77, 0x01, 0x3a, 0x60, 0x69, - 0x10, 0xaf, 0x90, 0x3c, 0x67, 0x23, 0x80, 0x65, 0x07, 0x96, 0xb3, 0x8c, 0x53, 0x98, 0x67, 0xf9, 0x5c, 0xad, 0xb4, - 0x8b, 0x32, 0xf1, 0x6a, 0x96, 0x81, 0xb3, 0xc0, 0x55, 0xee, 0xb3, 0x4c, 0xab, 0x9e, 0xf2, 0x04, 0x7d, 0x5e, 0xc9, - 0x09, 0xae, 0x04, 0x27, 0x1b, 0x90, 0x5f, 0x80, 0x24, 0x4d, 0x29, 0x6b, 0xca, 0xe7, 0xd7, 0x74, 0x43, 0x46, 0xcf, - 0x79, 0xcf, 0x8b, 0x86, 0xa1, 0x7f, 0xe5, 0x95, 0x10, 0xbe, 0x89, 0xdb, 0x36, 0x4a, 0x61, 0x7f, 0x11, 0x58, 0x7c, - 0xc2, 0x7e, 0xf4, 0x96, 0xfe, 0x74, 0x1c, 0x84, 0x43, 0xe4, 0x86, 0x8a, 0x39, 0xb0, 0xa7, 0x01, 0x8b, 0x4d, 0x7c, - 0xb3, 0x9d, 0xc4, 0x83, 0x81, 0xaf, 0x33, 0x16, 0xb3, 0x18, 0x68, 0x90, 0xe3, 0xc1, 0xf5, 0x5c, 0x9f, 0x10, 0xfa, - 0x61, 0x44, 0xe5, 0xa8, 0x40, 0xe7, 0x20, 0x1a, 0x2c, 0x01, 0x4f, 0xbd, 0x95, 0x0d, 0x92, 0x8c, 0x49, 0x26, 0x71, - 0xad, 0x49, 0xaa, 0xc3, 0x09, 0xad, 0x03, 0x1d, 0x57, 0x17, 0xd0, 0xf9, 0xb8, 0xee, 0x7d, 0xbc, 0x1a, 0x2e, 0xa8, - 0xf4, 0x2b, 0x31, 0xf0, 0xea, 0xe9, 0x38, 0xb8, 0xa6, 0x5b, 0xe1, 0x62, 0x1d, 0xee, 0x7e, 0x96, 0x0f, 0x1c, 0x77, - 0x54, 0xd2, 0x10, 0x18, 0xbc, 0x3d, 0x74, 0x37, 0x33, 0x34, 0xd4, 0x49, 0xfb, 0x30, 0x0e, 0xe5, 0x10, 0xab, 0x56, - 0x5c, 0x49, 0x6f, 0x04, 0xdf, 0x2e, 0x14, 0x63, 0xd9, 0xd8, 0xb5, 0xa1, 0x28, 0xfc, 0x15, 0xc0, 0x0e, 0xb5, 0xbf, - 0x52, 0xc9, 0xc7, 0xc8, 0xa8, 0xa6, 0x81, 0x8e, 0x01, 0x58, 0xb2, 0x34, 0x91, 0x54, 0x91, 0x46, 0xe2, 0x8f, 0xcc, - 0x58, 0x47, 0x4d, 0xd7, 0x17, 0x4c, 0x55, 0x8b, 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, 0x99, 0xb4, 0x7d, 0x59, - 0x91, 0x2d, 0x08, 0xa6, 0x27, 0xd1, 0x07, 0x49, 0xd0, 0xba, 0x48, 0xa4, 0x19, 0x21, 0xc0, 0x8f, 0x27, 0xe5, 0x8d, - 0xfe, 0x1c, 0x34, 0xad, 0x04, 0x2f, 0x19, 0x24, 0x8f, 0xc4, 0xcf, 0xa4, 0x60, 0x16, 0x63, 0xf9, 0x60, 0x80, 0xe5, - 0xe4, 0x4f, 0x1d, 0x93, 0xf4, 0x5f, 0x3a, 0x9d, 0xb0, 0x5f, 0x78, 0x95, 0xad, 0xe5, 0x4d, 0x73, 0xef, 0x85, 0x97, - 0xb3, 0x54, 0xc3, 0x32, 0xe8, 0xbf, 0x26, 0xda, 0x05, 0x5b, 0x5b, 0xc6, 0x84, 0x55, 0x3f, 0x80, 0xb4, 0x47, 0xba, - 0xbc, 0x7c, 0x58, 0x31, 0xc1, 0xa3, 0x2b, 0x6b, 0x1e, 0x44, 0x57, 0xc2, 0x47, 0x2e, 0xbb, 0x49, 0x72, 0x33, 0x9e, - 0xf8, 0xe1, 0x60, 0xa0, 0x00, 0x68, 0x69, 0x9d, 0x14, 0x83, 0xf0, 0xa9, 0x90, 0x03, 0x69, 0x74, 0x54, 0x05, 0x58, - 0x2c, 0xb3, 0x9b, 0x72, 0x92, 0x0d, 0x06, 0x3e, 0x88, 0x8d, 0x89, 0xdd, 0xd0, 0x6c, 0xee, 0xb3, 0x33, 0x05, 0x59, - 0x6d, 0x0e, 0x5b, 0x33, 0xdd, 0x02, 0x03, 0x80, 0x41, 0x44, 0xb0, 0xdc, 0x67, 0x46, 0x3e, 0xa2, 0x4e, 0x4f, 0x61, - 0x04, 0x04, 0xbf, 0x9e, 0x08, 0x44, 0x2e, 0x12, 0xa8, 0x07, 0x98, 0x09, 0x30, 0xa3, 0x8a, 0xe1, 0x35, 0xb0, 0x8b, - 0x57, 0xe6, 0x15, 0x83, 0xfe, 0x45, 0x93, 0x2c, 0xd1, 0x54, 0xe2, 0x68, 0x8c, 0x9c, 0x4a, 0x63, 0x64, 0x40, 0xec, - 0xe2, 0xf8, 0xf7, 0x94, 0x1e, 0x05, 0x29, 0xfb, 0x9c, 0x1b, 0xe2, 0x70, 0x14, 0x5f, 0xc1, 0xaa, 0x71, 0x3c, 0xd6, - 0xe6, 0xf5, 0x74, 0x56, 0xcf, 0x07, 0x22, 0x80, 0xff, 0x86, 0x82, 0xfd, 0xa2, 0xa9, 0xc8, 0x0d, 0x52, 0xe7, 0xf1, - 0x98, 0x82, 0x7c, 0xaa, 0x9b, 0xfc, 0x43, 0xee, 0xee, 0xa7, 0xb3, 0xb9, 0x35, 0x47, 0xaf, 0x6a, 0x5c, 0xb7, 0x56, - 0x37, 0x14, 0x12, 0xad, 0x69, 0x52, 0xdc, 0xe4, 0x93, 0x62, 0xc0, 0x2b, 0x5f, 0xa8, 0x2e, 0xb6, 0x46, 0xb0, 0xf0, - 0xe7, 0x16, 0x08, 0x93, 0x71, 0x2f, 0x3e, 0x59, 0xc8, 0x29, 0xed, 0xda, 0x6a, 0xb7, 0xb5, 0x49, 0xd3, 0x58, 0x35, - 0xbc, 0x86, 0x5d, 0x3a, 0x45, 0xb4, 0xed, 0x92, 0xe0, 0x0b, 0xd0, 0xb2, 0xba, 0x10, 0x79, 0x4c, 0xbf, 0x42, 0x7e, - 0x2d, 0x86, 0xff, 0x29, 0xdd, 0x9b, 0x53, 0x1b, 0xe4, 0x00, 0xb6, 0x7b, 0x0f, 0xb7, 0x63, 0xf4, 0x40, 0x06, 0x6f, - 0x04, 0x10, 0x8d, 0xaf, 0xa7, 0xd6, 0x8c, 0x89, 0x86, 0x05, 0x2b, 0x87, 0x91, 0x1f, 0x20, 0xe3, 0xe5, 0x14, 0x58, - 0xd9, 0x4f, 0x8a, 0xb8, 0xf6, 0x87, 0x91, 0x7f, 0xf5, 0x2c, 0xc8, 0xb8, 0x17, 0x0d, 0x3b, 0xbe, 0x00, 0x7b, 0xf5, - 0xd5, 0x33, 0x16, 0x0d, 0x78, 0x7e, 0x53, 0x4f, 0xb3, 0x60, 0x98, 0xb1, 0xe8, 0xa6, 0x18, 0x82, 0x0f, 0xed, 0xf3, - 0x72, 0x10, 0xfa, 0xbe, 0xd9, 0x39, 0x74, 0x37, 0x24, 0xf2, 0x08, 0xfb, 0x2b, 0xb8, 0xed, 0x6a, 0x89, 0x19, 0xe0, - 0x06, 0x56, 0x11, 0x33, 0xd8, 0xf2, 0x57, 0xcf, 0x0c, 0x97, 0x50, 0xfe, 0x5c, 0x6a, 0x36, 0x0a, 0x34, 0x27, 0xe7, - 0x68, 0x4e, 0x56, 0x42, 0x2d, 0xf9, 0xa4, 0xc2, 0xa9, 0x3a, 0x9f, 0x68, 0xbb, 0xd1, 0x18, 0x03, 0x17, 0xed, 0xb9, - 0x2d, 0x8c, 0xcc, 0x74, 0x91, 0xa2, 0x01, 0x0b, 0xcf, 0xc4, 0x29, 0x8d, 0x01, 0xed, 0xcb, 0x81, 0xa5, 0x0d, 0xf9, - 0xab, 0x9c, 0x19, 0x68, 0x1b, 0x52, 0x1a, 0x35, 0x03, 0x7f, 0xa6, 0x26, 0xcc, 0xaf, 0x60, 0x25, 0x82, 0xa8, 0x2e, - 0xc0, 0x24, 0xa9, 0xc8, 0x68, 0xa4, 0xac, 0x44, 0x72, 0x0e, 0x78, 0x1f, 0xc1, 0x93, 0x45, 0xec, 0x6a, 0x7f, 0x4a, - 0xff, 0xab, 0xc3, 0xe7, 0xda, 0x7f, 0x2a, 0x80, 0x85, 0x5c, 0x1a, 0x44, 0x06, 0x0a, 0x87, 0xd4, 0x54, 0x22, 0x4e, - 0x1c, 0xcf, 0xc0, 0xd7, 0x70, 0x81, 0xa6, 0x80, 0xfe, 0xa0, 0x66, 0x14, 0x91, 0x85, 0xbf, 0x7a, 0x76, 0x53, 0xb7, - 0x7a, 0x9e, 0x39, 0xaf, 0x41, 0x33, 0x03, 0x21, 0x3d, 0x4e, 0xd5, 0xdb, 0x90, 0xe8, 0xbc, 0xbc, 0xd4, 0x2f, 0x13, - 0x22, 0x59, 0x11, 0x79, 0xfa, 0x3e, 0x07, 0xf3, 0x88, 0x22, 0x74, 0x70, 0x65, 0x1e, 0x8f, 0x97, 0x82, 0xc2, 0x77, - 0x94, 0xe7, 0x03, 0x4e, 0xb3, 0x28, 0x01, 0x6d, 0x20, 0xab, 0x4c, 0x99, 0x9b, 0xa4, 0x65, 0xea, 0x3e, 0x80, 0x95, - 0x20, 0x47, 0x37, 0xa7, 0xa0, 0x50, 0x46, 0x82, 0x52, 0x5a, 0x0d, 0x42, 0xa9, 0x0e, 0x8b, 0x20, 0x72, 0xc8, 0x42, - 0xc0, 0xcd, 0x54, 0x34, 0x5a, 0xd2, 0xf0, 0x08, 0xe7, 0x06, 0x0a, 0x01, 0x48, 0xec, 0xa9, 0xa2, 0x8c, 0xcb, 0x61, - 0xce, 0xd6, 0x3c, 0x1c, 0xe2, 0xac, 0x49, 0x5b, 0x9e, 0x83, 0x38, 0x96, 0x4b, 0xbe, 0xc9, 0x11, 0x0c, 0x22, 0xf4, - 0x19, 0xf2, 0x27, 0xcb, 0xf9, 0x77, 0xe7, 0x30, 0xed, 0x08, 0x1f, 0x76, 0xb5, 0x05, 0x17, 0xb3, 0xbb, 0xf9, 0x04, - 0xe2, 0x5b, 0xee, 0xe6, 0xa7, 0x18, 0x22, 0x0b, 0x7f, 0xb0, 0x1a, 0x4a, 0xae, 0x28, 0x74, 0x59, 0x8f, 0x48, 0x91, - 0x3d, 0xdd, 0x70, 0x04, 0xc1, 0x81, 0x56, 0x0d, 0x32, 0x34, 0x12, 0x5f, 0x3d, 0x83, 0xac, 0xc1, 0x86, 0x7f, 0xce, - 0xc9, 0x59, 0xdd, 0x9f, 0x6c, 0xa1, 0x9a, 0x64, 0xb2, 0x56, 0x54, 0xce, 0x5f, 0xaf, 0xca, 0xf2, 0x6c, 0x55, 0x86, - 0xeb, 0x41, 0x57, 0x55, 0x96, 0x1c, 0xa9, 0x0d, 0xd0, 0x9a, 0xae, 0x10, 0x43, 0x21, 0x6b, 0xb0, 0xb4, 0xaa, 0xb2, - 0xa1, 0x3e, 0x81, 0x40, 0x1f, 0x60, 0x19, 0x35, 0xfb, 0xe9, 0xf0, 0x9f, 0xc1, 0x3f, 0x55, 0xc8, 0x52, 0x9d, 0xd6, - 0x99, 0xf8, 0x35, 0x58, 0x32, 0xfc, 0xe3, 0xb7, 0x60, 0x03, 0x58, 0x02, 0x64, 0xb9, 0xdb, 0xda, 0x68, 0xbd, 0xf2, - 0x0a, 0xf1, 0xae, 0xd6, 0x17, 0xfd, 0xd6, 0x6d, 0xa2, 0x56, 0x80, 0x11, 0x0a, 0x2d, 0x02, 0x6c, 0xf5, 0xc0, 0x3d, - 0x05, 0x3f, 0x10, 0xc3, 0xb9, 0x26, 0xad, 0xa9, 0x13, 0x5e, 0x67, 0xe3, 0x48, 0x44, 0xf5, 0x0e, 0x2e, 0xee, 0xf5, - 0xce, 0xe2, 0x6f, 0x54, 0x20, 0x00, 0xb2, 0x98, 0x62, 0xe3, 0xbc, 0x21, 0xbd, 0x32, 0xec, 0x24, 0xf4, 0xde, 0xb0, - 0x13, 0xc8, 0x8b, 0xc3, 0x4e, 0xa1, 0x4b, 0xb4, 0x9d, 0x22, 0x35, 0xd1, 0x76, 0xd2, 0x62, 0x1d, 0x96, 0x10, 0xfc, - 0xaa, 0xbd, 0x75, 0x94, 0xed, 0x8b, 0x2c, 0x61, 0xda, 0x02, 0x46, 0xb9, 0x55, 0x9f, 0x39, 0x45, 0xac, 0x95, 0xbd, - 0xd3, 0x49, 0x95, 0xbb, 0xc8, 0xa7, 0x56, 0x53, 0x64, 0xf2, 0x0f, 0xa7, 0x2d, 0x92, 0x4f, 0x7e, 0x6e, 0x37, 0x4c, - 0xa6, 0x7f, 0x3c, 0xf9, 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, 0x57, 0xbf, 0x84, 0x2b, 0x36, 0x3f, 0x34, 0x8a, - 0x9e, 0x5c, 0x9f, 0xa2, 0x6e, 0xc5, 0xd5, 0x69, 0xda, 0x6a, 0x8e, 0x1d, 0x67, 0xc8, 0xc1, 0xb3, 0x82, 0x60, 0x3b, - 0x2a, 0x51, 0xbe, 0x6d, 0x37, 0x1d, 0x13, 0x5b, 0xfd, 0xb3, 0xa8, 0xb6, 0x2b, 0xa8, 0x88, 0x88, 0x4f, 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, 0xe7, 0x77, 0xf5, 0x82, 0x93, 0xc9, 0x7e, 0x72, 0x9a, - 0xbb, 0x5d, 0xa4, 0xfd, 0xc4, 0xb7, 0x61, 0xfe, 0xf5, 0x0d, 0x62, 0x25, 0xea, 0x7f, 0x54, 0x00, 0x34, 0xb8, 0xcd, - 0x63, 0x89, 0x52, 0x7f, 0x50, 0xd5, 0x0f, 0x6a, 0xa6, 0x6a, 0x1a, 0x08, 0xe6, 0x54, 0x0a, 0xf8, 0xc3, 0xed, 0xc2, - 0x15, 0x8f, 0xb8, 0x61, 0x61, 0xfc, 0xd3, 0xab, 0xd9, 0xb9, 0xa0, 0x32, 0x70, 0x33, 0xfe, 0xd3, 0x13, 0xec, 0x1c, - 0xd6, 0x0a, 0xc8, 0x0a, 0x7f, 0x7a, 0xd5, 0x23, 0xef, 0xe7, 0xfc, 0x4f, 0x2f, 0x7f, 0xe4, 0x7d, 0xc4, 0x79, 0xf9, - 0x13, 0x49, 0x9d, 0x10, 0xd5, 0xe5, 0x4f, 0xc2, 0x14, 0x5b, 0xa7, 0xf9, 0x2b, 0x52, 0xf8, 0x04, 0x9f, 0x81, 0xef, - 0x70, 0x1d, 0xee, 0xcc, 0x6f, 0xf0, 0xd8, 0xb1, 0xd8, 0x76, 0xa9, 0x2f, 0xa0, 0x1c, 0x81, 0x45, 0x54, 0xf6, 0xdb, - 0xb9, 0xfd, 0x6a, 0x61, 0x94, 0x31, 0x76, 0x5f, 0xb2, 0x12, 0xa5, 0xb3, 0x7e, 0xbf, 0x90, 0x82, 0x91, 0x5d, 0x58, - 0xa3, 0x3d, 0x4a, 0xd5, 0xab, 0x6f, 0xc3, 0x3a, 0x4a, 0xd2, 0x7c, 0x25, 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, 0x01, 0x23, 0xa7, 0xb0, 0x54, 0x1e, 0xac, 0xc4, 0xb9, 0xe8, 0xb3, 0xe2, 0x78, 0xf4, 0x2c, 0x34, 0xf3, - 0x0a, 0x1e, 0x84, 0x3b, 0x0b, 0x23, 0x15, 0x2e, 0x84, 0xe2, 0x79, 0x85, 0xb1, 0x15, 0x15, 0x70, 0x20, 0xc3, 0x0f, - 0x08, 0xbc, 0x97, 0xfd, 0x2b, 0x18, 0x0c, 0x13, 0xdc, 0xc8, 0xa8, 0x93, 0x2b, 0xf6, 0x27, 0x06, 0x66, 0x50, 0x4f, - 0x6a, 0xf7, 0xd9, 0x83, 0x0a, 0xec, 0x85, 0x33, 0xa0, 0xbd, 0x1b, 0xa3, 0x9f, 0x55, 0xb1, 0x71, 0xd2, 0x3f, 0x15, - 0x1b, 0x48, 0xa6, 0xc3, 0xe2, 0x64, 0x9b, 0x86, 0x47, 0xf2, 0xe4, 0x38, 0xdd, 0xf4, 0x8f, 0xc7, 0x31, 0x7e, 0x1c, - 0xe5, 0xd7, 0x16, 0xf0, 0x2a, 0x6e, 0x21, 0x8d, 0x45, 0x8a, 0xde, 0x81, 0x98, 0x43, 0xd1, 0x4b, 0xf6, 0x5b, 0xc6, - 0xcb, 0x89, 0xa0, 0x94, 0x24, 0x36, 0xbc, 0x23, 0x3d, 0x4d, 0xeb, 0xd1, 0x4e, 0x06, 0xec, 0xd7, 0xa3, 0x3d, 0xfd, - 0x05, 0x8a, 0x47, 0x0b, 0x7f, 0x49, 0x7f, 0x17, 0x77, 0x73, 0xcf, 0xf9, 0xa6, 0xf1, 0x1d, 0x71, 0x81, 0x62, 0xcd, - 0xee, 0xaf, 0x69, 0xe9, 0xac, 0x03, 0xc1, 0x01, 0x6f, 0xb1, 0x8b, 0xf6, 0xfd, 0xc6, 0x75, 0x7a, 0x3a, 0x7c, 0xeb, - 0xd6, 0x28, 0xdf, 0xfb, 0x87, 0x44, 0x39, 0x38, 0xbc, 0x72, 0xd1, 0xfc, 0xed, 0xa7, 0x0c, 0x49, 0x85, 0xe6, 0x06, - 0xdb, 0xc9, 0x16, 0x61, 0x6d, 0x8c, 0x83, 0x9c, 0xad, 0xca, 0x30, 0x02, 0x06, 0x75, 0xec, 0x7f, 0xf4, 0xd9, 0xb4, - 0x21, 0xfb, 0x00, 0x50, 0xb9, 0x0a, 0x01, 0x7b, 0x00, 0x4e, 0x34, 0xc2, 0x0d, 0x70, 0xab, 0xd1, 0x92, 0x0e, 0xea, - 0xb6, 0x60, 0x20, 0x5a, 0xc2, 0xc6, 0x09, 0x5d, 0xdf, 0x57, 0x84, 0x8f, 0xca, 0xb7, 0x0f, 0xe5, 0xaf, 0x9e, 0xb3, - 0xff, 0xde, 0x61, 0x4d, 0x4d, 0xb9, 0x05, 0xcc, 0x9c, 0xb5, 0xc8, 0x2b, 0x84, 0x4e, 0x91, 0xdf, 0xab, 0xba, 0x12, - 0xc3, 0x65, 0x2d, 0xca, 0xce, 0xec, 0xd6, 0x89, 0xde, 0x39, 0x05, 0xb5, 0x54, 0x36, 0x20, 0x01, 0x6e, 0x20, 0xc5, - 0xb6, 0xc0, 0x92, 0xce, 0x06, 0x28, 0xfe, 0x0d, 0x2a, 0xed, 0xfe, 0xdf, 0x39, 0x13, 0xd4, 0x6c, 0xa3, 0xba, 0xbf, - 0xd2, 0x4f, 0x55, 0x4d, 0x62, 0x01, 0x2e, 0x27, 0x69, 0xde, 0xf1, 0x08, 0xab, 0x7f, 0x9a, 0x2c, 0x45, 0xa0, 0x57, - 0x11, 0xed, 0x4a, 0x40, 0x82, 0x76, 0x76, 0x16, 0x2a, 0x02, 0x05, 0xfa, 0xfa, 0x0f, 0xdb, 0x34, 0x8b, 0xe5, 0x6a, - 0xb6, 0x87, 0x89, 0xb2, 0x58, 0x0f, 0x11, 0xe4, 0xcc, 0xd4, 0xc1, 0x7e, 0x4f, 0x33, 0x9a, 0x85, 0x37, 0xa6, 0x04, - 0x97, 0xe2, 0x2a, 0x2a, 0x72, 0xf0, 0x39, 0xc4, 0x17, 0x3e, 0x15, 0x72, 0x83, 0x88, 0xa6, 0x3f, 0xe4, 0x9e, 0x79, - 0x83, 0x85, 0x92, 0x9f, 0x10, 0x7f, 0xc9, 0xda, 0x18, 0xf7, 0x4b, 0xa7, 0xda, 0x2f, 0x15, 0x82, 0xfb, 0xcf, 0xb6, - 0xd8, 0xa8, 0xf2, 0x44, 0x8f, 0x3e, 0xc5, 0xfa, 0x9f, 0x2d, 0xa0, 0x54, 0xf7, 0x6d, 0x70, 0x2a, 0x1e, 0x85, 0xdb, - 0xba, 0xb8, 0x45, 0x68, 0x81, 0x72, 0x54, 0x15, 0xdb, 0x32, 0x22, 0x4e, 0xd8, 0x6d, 0x5d, 0xf4, 0x34, 0x07, 0x3a, - 0x75, 0x58, 0x9a, 0xc8, 0x13, 0xa1, 0xdd, 0x82, 0xee, 0x69, 0x8e, 0x95, 0x78, 0x21, 0x4b, 0x07, 0x59, 0x27, 0xd2, - 0x84, 0xca, 0x5d, 0x5d, 0x75, 0x52, 0x2a, 0x75, 0xc3, 0xeb, 0x54, 0x33, 0xfe, 0x2e, 0xcd, 0x9f, 0x58, 0xf6, 0xeb, - 0xd6, 0x6f, 0xb5, 0xda, 0x1b, 0xab, 0x47, 0x25, 0x6b, 0x8e, 0xb3, 0x09, 0x49, 0xe9, 0x13, 0xb6, 0x9b, 0x49, 0xd7, - 0x3a, 0xf0, 0x24, 0xb8, 0x1c, 0x7a, 0x02, 0x2a, 0x06, 0x4d, 0xbc, 0xdd, 0x05, 0xea, 0x11, 0x78, 0x06, 0xaa, 0x19, - 0x24, 0xd7, 0x01, 0xbf, 0xac, 0xb5, 0x3c, 0x65, 0x84, 0x61, 0xb5, 0xb3, 0x68, 0x39, 0x58, 0x49, 0x78, 0xae, 0x08, - 0x5c, 0xbb, 0x12, 0x78, 0x35, 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, 0x43, 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, 0x7a, 0xf5, 0xeb, 0xba, 0xc3, 0x75, 0xde, 0x04, 0xc7, 0x4d, 0xd7, 0xb6, 0xda, 0xd9, 0xcf, 0xdd, 0xbd, 0xb5, - 0x88, 0xc2, 0x2c, 0xfb, 0x6b, 0x51, 0xfc, 0x51, 0xe9, 0x3b, 0x02, 0x1d, 0xdd, 0x79, 0x51, 0xa7, 0xcb, 0xfd, 0x07, - 0xc2, 0x78, 0xf2, 0xea, 0x13, 0xa2, 0x5b, 0xdf, 0x67, 0xee, 0x57, 0x80, 0x1b, 0xc1, 0x1d, 0x44, 0x7b, 0xb7, 0xd4, - 0x27, 0xb5, 0xfa, 0x5a, 0xaf, 0x9d, 0xa7, 0xe7, 0x37, 0x9d, 0xdb, 0xef, 0xa1, 0x39, 0xd9, 0x7a, 0x4f, 0x0b, 0x6b, - 0x65, 0xe9, 0xa9, 0x2a, 0xd8, 0x9b, 0xe5, 0xb9, 0x2a, 0x98, 0x3c, 0xf0, 0x9a, 0xfd, 0x82, 0x06, 0x57, 0x3a, 0xd9, - 0x78, 0xcf, 0xd4, 0xc0, 0x2d, 0x0a, 0x4b, 0x87, 0x5f, 0x72, 0x33, 0x79, 0x89, 0xfb, 0x4b, 0x45, 0x2e, 0xf6, 0x9d, - 0x33, 0xba, 0x33, 0xb3, 0xee, 0x55, 0x85, 0xab, 0x05, 0xb9, 0x3a, 0xb0, 0xb5, 0xec, 0xe2, 0x70, 0xc3, 0x22, 0x0a, - 0x10, 0x88, 0xe9, 0x95, 0x5a, 0xfb, 0x13, 0x1a, 0x84, 0x6a, 0x30, 0xf0, 0x0b, 0x0c, 0x56, 0x05, 0x0a, 0x1f, 0x28, - 0x92, 0xbf, 0xf2, 0x04, 0xec, 0xe2, 0x19, 0xa0, 0x5b, 0xb1, 0x59, 0x31, 0x42, 0x84, 0x4c, 0x56, 0xb1, 0x9a, 0xce, - 0x20, 0x9f, 0xfa, 0xe2, 0x1b, 0x5b, 0x75, 0x3e, 0x6f, 0x6b, 0xaa, 0x9c, 0x3b, 0x14, 0xba, 0xbb, 0xa9, 0x3b, 0xb7, - 0x2e, 0xf2, 0xdc, 0x21, 0xe4, 0x4a, 0xc5, 0x4a, 0x4c, 0x43, 0xcd, 0x93, 0x34, 0xa3, 0xfe, 0x62, 0x9f, 0x8a, 0x1a, - 0x85, 0x53, 0xfe, 0x74, 0x0c, 0xaa, 0x70, 0x55, 0x43, 0x1c, 0x4b, 0x55, 0x3c, 0xb2, 0x41, 0xa0, 0x79, 0x75, 0xa7, - 0x92, 0x26, 0x64, 0x72, 0x23, 0x7c, 0x6a, 0x52, 0xca, 0xd3, 0xb4, 0x49, 0x2b, 0x45, 0xea, 0xe0, 0x83, 0x3a, 0xd5, - 0x78, 0x6e, 0xe6, 0xcf, 0x01, 0xcc, 0xb8, 0xba, 0xe1, 0xd7, 0x8a, 0xcb, 0xa8, 0xad, 0xcc, 0xa4, 0xfd, 0xc9, 0xd1, - 0xd8, 0x28, 0x56, 0xe3, 0x46, 0x19, 0x61, 0xa5, 0x34, 0x27, 0xc5, 0x72, 0x3c, 0xff, 0x80, 0xc1, 0x9a, 0x27, 0xb0, - 0x83, 0x89, 0x4a, 0x79, 0x1f, 0x01, 0xf1, 0x75, 0x92, 0xae, 0x12, 0x48, 0x91, 0xfe, 0xa5, 0x4b, 0xee, 0x32, 0x36, - 0x10, 0x63, 0x56, 0xcc, 0x8c, 0xfe, 0x07, 0x77, 0x49, 0x7f, 0x12, 0x02, 0xe0, 0x26, 0x9a, 0x42, 0xa7, 0xce, 0x93, - 0xab, 0x2a, 0x58, 0x5e, 0x79, 0x68, 0xc5, 0x88, 0x07, 0xff, 0xf9, 0x3c, 0x44, 0x10, 0x73, 0x4c, 0xf1, 0xf4, 0x0b, - 0xa3, 0xff, 0x08, 0xae, 0x31, 0x82, 0xd0, 0xdd, 0x3b, 0x87, 0x21, 0xdc, 0xec, 0x41, 0x06, 0xf5, 0x87, 0x3a, 0x24, - 0x6a, 0xf8, 0xd7, 0xdc, 0x83, 0xfe, 0xaf, 0x33, 0x61, 0xa9, 0xfd, 0xf4, 0x74, 0x00, 0x15, 0xbc, 0xaf, 0x78, 0x1b, - 0x11, 0xdf, 0x27, 0x7e, 0x1a, 0x0f, 0xb6, 0x4f, 0xb7, 0x60, 0xad, 0xfb, 0x50, 0x19, 0xeb, 0x2a, 0x61, 0x03, 0x01, - 0x5f, 0xa3, 0xa8, 0x3d, 0xaf, 0xdd, 0xee, 0xc1, 0x7f, 0xfa, 0x57, 0x21, 0x03, 0x26, 0x4e, 0xdf, 0x67, 0x4e, 0xd6, - 0xe8, 0x2a, 0x93, 0xe9, 0x43, 0x27, 0x7d, 0xab, 0xd3, 0x7d, 0x27, 0xfc, 0x23, 0x67, 0x16, 0x1f, 0x6e, 0xe9, 0x2b, - 0x4d, 0x8a, 0x3b, 0x60, 0x65, 0xf3, 0xa8, 0x20, 0xd4, 0xb9, 0x88, 0xbe, 0x32, 0xe5, 0x5b, 0x42, 0xcd, 0xa1, 0xb1, - 0xa4, 0x94, 0xee, 0x35, 0xf4, 0x3a, 0xad, 0xf5, 0xdb, 0x28, 0xc1, 0x98, 0xe8, 0x78, 0xf2, 0x32, 0x1e, 0x2b, 0xef, - 0xe3, 0x71, 0x23, 0x15, 0xf2, 0x00, 0x44, 0xa0, 0x62, 0xfc, 0xe9, 0xca, 0x53, 0x91, 0x5e, 0x18, 0xaf, 0x42, 0x29, - 0x28, 0x0c, 0xe8, 0x0a, 0xa4, 0x80, 0x47, 0xed, 0x89, 0xce, 0xc2, 0x2e, 0xe1, 0x1e, 0xdd, 0x04, 0x8c, 0xf5, 0xf9, - 0xaf, 0xb9, 0x97, 0x33, 0xe1, 0x0e, 0x2f, 0x06, 0xa8, 0x4d, 0xbd, 0xba, 0xfb, 0xb8, 0x56, 0xe7, 0x70, 0x08, 0x0e, - 0x56, 0x83, 0x08, 0x4e, 0xe7, 0x73, 0x47, 0xb3, 0x2c, 0x40, 0xe5, 0x64, 0x95, 0x91, 0x37, 0x4f, 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, 0xd7, 0x47, 0xf5, 0xd3, 0x67, 0x6c, 0xc3, 0x25, 0xea, 0xa4, 0x33, 0x11, 0x80, - 0xd8, 0x53, 0xb3, 0x8a, 0x6e, 0x80, 0xa4, 0x4e, 0xb3, 0x8a, 0x6e, 0xa8, 0xd9, 0xc6, 0x38, 0x00, 0xca, 0x58, 0xc0, - 0xbe, 0x9b, 0x8e, 0x83, 0xf5, 0xd3, 0x58, 0x5e, 0x87, 0x56, 0x4f, 0xb7, 0xca, 0x67, 0x50, 0xb7, 0xda, 0x18, 0x13, - 0xdb, 0xcd, 0x97, 0x73, 0xfd, 0x6e, 0xb0, 0xf4, 0xed, 0xa0, 0x39, 0xa7, 0xec, 0x95, 0x2e, 0x7b, 0x6d, 0x97, 0x4d, - 0x3d, 0x77, 0x52, 0xb4, 0x1a, 0x03, 0x7a, 0x03, 0x0b, 0xd6, 0xe7, 0x22, 0xcd, 0x56, 0xa5, 0x2a, 0x01, 0x2f, 0x8c, - 0x35, 0x5b, 0xf9, 0x8d, 0xcc, 0x90, 0x84, 0x79, 0x9c, 0x89, 0xb7, 0x74, 0xaf, 0x85, 0xc9, 0x71, 0x2a, 0x92, 0x29, - 0xa1, 0x53, 0xba, 0xb3, 0x0d, 0x9d, 0xab, 0x30, 0x8a, 0x68, 0xad, 0xa4, 0xd2, 0x48, 0x60, 0x6a, 0x06, 0x28, 0x99, - 0x2b, 0x70, 0x4a, 0x97, 0xfb, 0xdf, 0x89, 0x18, 0x67, 0xbe, 0x28, 0x99, 0x01, 0xdd, 0xf2, 0xeb, 0x62, 0xd3, 0x4a, - 0x91, 0x11, 0xe6, 0xcd, 0x69, 0x7b, 0x5d, 0x1f, 0x02, 0xb9, 0x5a, 0x0e, 0x28, 0x1a, 0x07, 0x85, 0x0e, 0x97, 0x2a, - 0x01, 0xf6, 0x45, 0xe2, 0x67, 0x84, 0x2d, 0xed, 0x81, 0xdc, 0x1e, 0x9d, 0x09, 0x73, 0xc9, 0x49, 0x59, 0x76, 0x29, - 0xcd, 0xe0, 0x72, 0xe2, 0x4a, 0x70, 0x91, 0xde, 0xae, 0xa7, 0x49, 0x4b, 0xdb, 0xc7, 0x86, 0x73, 0x34, 0xb4, 0x0d, - 0xba, 0x63, 0x7f, 0x68, 0x2e, 0x16, 0xb1, 0x75, 0xb1, 0x18, 0x76, 0x66, 0x3f, 0x59, 0x2c, 0x40, 0x0e, 0x00, 0x47, - 0xdd, 0x96, 0x8f, 0xd9, 0x12, 0x38, 0xad, 0xa6, 0xd9, 0xd4, 0xdb, 0xf2, 0xfc, 0xa9, 0xea, 0xe9, 0x25, 0xaf, 0x9e, - 0x0a, 0x33, 0x16, 0x5b, 0x5e, 0x3d, 0xb5, 0x8e, 0x9c, 0xfc, 0xa9, 0x50, 0xa2, 0x75, 0x01, 0xcd, 0xc0, 0x6b, 0x0a, - 0x18, 0xb1, 0x64, 0x32, 0xa5, 0x8a, 0x3c, 0xee, 0x4d, 0xb7, 0x6a, 0xf0, 0x82, 0xc2, 0x21, 0x90, 0xd2, 0xe9, 0x57, - 0xcf, 0x98, 0x7e, 0xef, 0xea, 0x59, 0x87, 0xac, 0x6d, 0x98, 0x2e, 0xb7, 0xc3, 0x64, 0x50, 0xfa, 0x4f, 0xcd, 0xc4, - 0xb8, 0xb2, 0x26, 0x09, 0x20, 0xfe, 0x8d, 0xfd, 0x0e, 0x29, 0xdc, 0xbc, 0xbf, 0x1c, 0xc6, 0x8f, 0xbc, 0x1f, 0x23, - 0x7b, 0x92, 0x66, 0x88, 0x35, 0x93, 0x0a, 0xb9, 0xfb, 0x6a, 0xfd, 0x63, 0x62, 0x37, 0xd9, 0x03, 0x0b, 0x40, 0x6c, - 0x4d, 0x5b, 0xdd, 0xf2, 0x7e, 0xdf, 0x33, 0x45, 0x80, 0x1f, 0x94, 0x7f, 0x72, 0x67, 0x48, 0x06, 0x65, 0xd7, 0x0d, - 0x21, 0x1e, 0x94, 0x4d, 0xd3, 0x5e, 0x6f, 0x07, 0x67, 0x1e, 0xab, 0xeb, 0xb4, 0xb3, 0xb8, 0x5a, 0x64, 0x90, 0x56, - 0x1f, 0xb2, 0xd3, 0xcc, 0x3e, 0x3b, 0x59, 0x2a, 0xdd, 0xef, 0x43, 0x44, 0xdc, 0x49, 0xd6, 0xf6, 0xdb, 0x2d, 0xb8, - 0x86, 0x93, 0x41, 0xe8, 0xca, 0xde, 0x2e, 0xa3, 0x8d, 0x0b, 0x71, 0xda, 0x33, 0x9d, 0x2f, 0xf8, 0xf2, 0x28, 0xed, - 0x3c, 0x38, 0xd5, 0x13, 0x7d, 0x6e, 0xba, 0xab, 0x4c, 0xae, 0x75, 0x58, 0x8d, 0x41, 0x6d, 0x16, 0xb6, 0x70, 0x17, - 0xb6, 0xd1, 0x41, 0x6b, 0x5f, 0x16, 0xfc, 0x53, 0x06, 0xe0, 0x4b, 0xcf, 0x96, 0x5d, 0xaf, 0x49, 0xab, 0xd7, 0x32, - 0x0a, 0xb1, 0xa5, 0xed, 0xd5, 0xa7, 0xa3, 0x7c, 0xdc, 0x9c, 0x51, 0x5c, 0xc8, 0x51, 0x7e, 0xf4, 0x1a, 0xa2, 0xae, - 0x75, 0x1d, 0x17, 0x8b, 0x0e, 0x37, 0xae, 0xba, 0xed, 0xc6, 0xf5, 0x23, 0xe2, 0xad, 0xd1, 0x26, 0x85, 0x5a, 0x19, - 0x3b, 0x82, 0x97, 0x55, 0xc3, 0x21, 0x13, 0xc3, 0xa1, 0x84, 0x4c, 0x7d, 0xec, 0xde, 0xd0, 0xb4, 0xcf, 0x4f, 0x5b, - 0x3f, 0x62, 0xa9, 0x71, 0x14, 0x1b, 0xde, 0xf9, 0x3b, 0x8f, 0xad, 0x71, 0x25, 0x5f, 0x06, 0xb3, 0x5d, 0x41, 0xb5, - 0x35, 0xde, 0xb0, 0x57, 0xf1, 0x1f, 0x72, 0xa9, 0xe4, 0x6f, 0x7f, 0x86, 0x6b, 0x78, 0x6b, 0x4b, 0x07, 0x4d, 0x35, - 0xab, 0x98, 0xb9, 0x17, 0x9c, 0x7e, 0xdc, 0xbd, 0x22, 0x18, 0xfc, 0x9e, 0x8e, 0x82, 0x5c, 0x2c, 0xd5, 0x1a, 0x50, - 0x90, 0x4e, 0xec, 0x98, 0xca, 0x02, 0xc3, 0x00, 0xde, 0x90, 0x01, 0xf2, 0x98, 0xc2, 0xdd, 0x50, 0xe1, 0x85, 0xbf, - 0xe4, 0x64, 0x97, 0xc0, 0xb6, 0x66, 0x7c, 0xcc, 0x70, 0x07, 0x21, 0xff, 0x08, 0xb6, 0x62, 0x6b, 0x76, 0xc7, 0x16, - 0x0c, 0xc9, 0xc6, 0x71, 0x18, 0x63, 0x3e, 0x9e, 0xc4, 0x37, 0x62, 0x12, 0x0f, 0x78, 0x84, 0x8e, 0x11, 0x1b, 0x5e, - 0xcf, 0x62, 0x39, 0x80, 0x6c, 0xc5, 0x95, 0x0e, 0x08, 0xa1, 0xb1, 0xa1, 0x25, 0xaf, 0x0b, 0x83, 0x8b, 0x1d, 0xfb, - 0x2c, 0x47, 0x91, 0x8c, 0x43, 0xb0, 0x68, 0x55, 0x03, 0x0b, 0x13, 0xbb, 0xe3, 0xc5, 0x6c, 0x3d, 0xc7, 0x7f, 0x8e, - 0x47, 0x04, 0xc0, 0x0e, 0x0e, 0x0d, 0x5b, 0x45, 0x88, 0xf4, 0xb6, 0xe0, 0x2b, 0xcb, 0xd3, 0x85, 0xdd, 0xf3, 0xb7, - 0x7c, 0xcc, 0x2e, 0x7f, 0xf4, 0x20, 0x72, 0xf6, 0xf2, 0x23, 0xa0, 0x21, 0xde, 0xf3, 0xbb, 0xd4, 0xcb, 0xd9, 0x1d, - 0x51, 0x10, 0xde, 0x81, 0x33, 0xd0, 0x3d, 0x44, 0xc0, 0xbe, 0xe5, 0x0b, 0x8c, 0x15, 0xbb, 0x48, 0x97, 0x1e, 0x66, - 0x84, 0xda, 0xd3, 0xf9, 0xb2, 0x51, 0x93, 0x70, 0x7b, 0xb3, 0x9c, 0x0c, 0x06, 0x5b, 0x7f, 0xcf, 0x37, 0xc0, 0x07, - 0x73, 0xf9, 0xa3, 0xb7, 0xa7, 0x72, 0xe1, 0x3f, 0xaf, 0xb3, 0xe4, 0xbd, 0xcf, 0xde, 0x0e, 0xf8, 0x02, 0xf0, 0x96, - 0xd0, 0x81, 0xeb, 0xde, 0x67, 0x12, 0xaf, 0xed, 0xad, 0xbe, 0x46, 0x20, 0x91, 0x2f, 0x00, 0x23, 0x26, 0xe6, 0xf7, - 0x5b, 0x88, 0xc0, 0x48, 0xc0, 0xb7, 0x55, 0x7b, 0xc4, 0xef, 0xb8, 0x01, 0xfc, 0xca, 0x7c, 0xf6, 0xc0, 0x43, 0xfd, - 0x33, 0xf1, 0xd9, 0x2d, 0x7f, 0xcf, 0x9f, 0x7b, 0x52, 0x92, 0x2e, 0x67, 0xef, 0xe7, 0x70, 0x3d, 0x94, 0xf2, 0x74, - 0x48, 0x3f, 0x1b, 0x83, 0x01, 0x84, 0x42, 0xe6, 0xad, 0x07, 0xac, 0x49, 0x21, 0xfe, 0x05, 0x7c, 0x3b, 0x4a, 0xd8, - 0xbc, 0xf5, 0x76, 0xbe, 0x96, 0x37, 0x6f, 0xbd, 0x07, 0x9f, 0xa2, 0x00, 0xab, 0xa0, 0x94, 0x05, 0x56, 0x41, 0xd8, - 0x68, 0x23, 0x8c, 0x81, 0xab, 0x77, 0x8d, 0xa1, 0xae, 0xe7, 0x88, 0x6d, 0x2b, 0x7d, 0x17, 0xbe, 0x83, 0x0c, 0xf8, - 0xe0, 0x75, 0x51, 0x12, 0x7d, 0x4e, 0x4d, 0x91, 0xb4, 0xee, 0xb9, 0xdf, 0x5a, 0x77, 0xb4, 0xa6, 0xd4, 0x47, 0x6e, - 0xc6, 0xc7, 0x63, 0xfd, 0x5c, 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, 0xd7, 0xc3, 0xda, - 0x9f, 0x38, 0xb5, 0xb0, 0xb4, 0x9a, 0x83, 0xfa, 0xa9, 0x2d, 0xc7, 0xa9, 0xaa, 0xfd, 0x4b, 0x92, 0x54, 0xbb, 0x4a, - 0xcb, 0xe9, 0xbd, 0x7d, 0xd3, 0x65, 0x82, 0x8d, 0xfd, 0x80, 0xaa, 0x23, 0xab, 0x61, 0xf7, 0x85, 0xfa, 0xa2, 0xa7, - 0x64, 0x42, 0xf3, 0x51, 0x45, 0xf3, 0xec, 0x7e, 0xb3, 0xa3, 0xfe, 0xd3, 0xeb, 0xa1, 0x08, 0x90, 0xac, 0xd2, 0x62, - 0x29, 0x72, 0x36, 0xf6, 0xd3, 0x61, 0x92, 0xa9, 0xf0, 0x82, 0x74, 0x74, 0xf7, 0x1b, 0xf7, 0xb7, 0xdc, 0x40, 0xd6, - 0x68, 0xd5, 0x06, 0x63, 0xa5, 0x68, 0x19, 0xac, 0x6f, 0xc6, 0xfd, 0xbe, 0xb8, 0x19, 0x4f, 0x45, 0x50, 0x03, 0x71, - 0x91, 0x78, 0x3e, 0x9e, 0xd6, 0xc4, 0x92, 0xda, 0x15, 0x18, 0xa3, 0xc7, 0x55, 0x51, 0xfb, 0xd4, 0xcf, 0x21, 0x14, - 0xa9, 0xd6, 0xcc, 0xb1, 0xc6, 0x8d, 0x11, 0x71, 0x87, 0x95, 0x6b, 0xa7, 0xf6, 0x3a, 0x00, 0xcb, 0xab, 0x71, 0x41, - 0xd8, 0x26, 0xa7, 0xce, 0x05, 0xac, 0x46, 0x43, 0xaa, 0xdd, 0x70, 0xeb, 0x65, 0xe7, 0x37, 0x8f, 0x13, 0x5b, 0x1b, - 0xe1, 0x96, 0x02, 0xca, 0x28, 0xbf, 0xb1, 0x9c, 0xb0, 0x3b, 0xd5, 0x3b, 0x52, 0xb5, 0x23, 0xce, 0x5c, 0xc0, 0x2a, - 0xc3, 0x53, 0xab, 0x6f, 0x62, 0x70, 0x22, 0xe4, 0xad, 0x74, 0xbc, 0xf6, 0x23, 0xee, 0x57, 0xf7, 0x75, 0xaf, 0x04, - 0x3f, 0x09, 0x79, 0xfd, 0x96, 0x77, 0x00, 0x58, 0xf1, 0x21, 0x2f, 0xa6, 0x85, 0xa3, 0x75, 0x19, 0x94, 0x01, 0x22, - 0x34, 0x03, 0xa0, 0x93, 0xab, 0x83, 0x28, 0x0d, 0x5c, 0x71, 0x87, 0x08, 0x3f, 0x8d, 0x9e, 0x56, 0xcf, 0xc3, 0xa7, - 0xf9, 0x34, 0xbc, 0xaa, 0x82, 0xe8, 0x2a, 0x0f, 0xa2, 0xa7, 0xf9, 0x4d, 0xf8, 0xb4, 0x9a, 0x46, 0x57, 0x55, 0x10, - 0x5e, 0xe5, 0x8d, 0x7d, 0xd7, 0xee, 0xee, 0x09, 0x79, 0xdb, 0xd5, 0x1f, 0xb9, 0x54, 0xf6, 0x94, 0xe9, 0xe5, 0x65, - 0xad, 0x57, 0x6a, 0xb7, 0xb9, 0x5e, 0xa3, 0x66, 0xea, 0xa3, 0xec, 0x2f, 0xb6, 0xb1, 0xf0, 0x64, 0x0e, 0xa1, 0xcf, - 0x48, 0x8b, 0xb9, 0xc7, 0xb9, 0xde, 0x1c, 0x48, 0x61, 0x60, 0xc4, 0xa4, 0x92, 0x91, 0xd3, 0x0b, 0x5c, 0x84, 0x72, - 0xc4, 0xb0, 0x96, 0xae, 0xf6, 0x59, 0x97, 0xde, 0x40, 0x5d, 0x53, 0xec, 0x6b, 0xc8, 0xc0, 0x8b, 0xa6, 0xd7, 0xc1, - 0x18, 0x90, 0x23, 0xf0, 0x8e, 0xcf, 0x96, 0x70, 0x60, 0x6e, 0x00, 0xfa, 0xe6, 0x51, 0x5f, 0x97, 0x15, 0xdf, 0xa8, - 0xbe, 0x99, 0x6e, 0x46, 0x4a, 0xf9, 0xb1, 0xe6, 0xab, 0xab, 0x67, 0xec, 0x8e, 0x6b, 0x54, 0x94, 0x5f, 0xf4, 0x62, - 0xbd, 0x07, 0xae, 0xba, 0x5f, 0xe0, 0x36, 0x8b, 0xc7, 0xae, 0x3c, 0x60, 0xd9, 0x8e, 0x3d, 0xb0, 0x5b, 0xf6, 0x9e, - 0x3d, 0x61, 0x6f, 0xd8, 0x17, 0xf6, 0x13, 0xaa, 0x36, 0x94, 0x90, 0xe7, 0x2f, 0xf8, 0x9d, 0x34, 0x3d, 0x4a, 0x54, - 0xb2, 0x07, 0xdb, 0x4c, 0x33, 0xdc, 0xb2, 0xf7, 0x7c, 0x31, 0x5c, 0xb3, 0x37, 0x90, 0x0d, 0x65, 0xe2, 0xc1, 0x9a, - 0xfd, 0xc4, 0x15, 0x88, 0x99, 0x3e, 0x0b, 0x4b, 0x4b, 0x54, 0x34, 0x65, 0xa2, 0x0c, 0xfd, 0x86, 0xe3, 0x8b, 0xec, - 0x27, 0x2c, 0x42, 0x7e, 0x66, 0xb8, 0x66, 0x0f, 0x7c, 0x31, 0x58, 0xb3, 0xf7, 0xda, 0x40, 0x34, 0xd8, 0xba, 0xa5, - 0x11, 0x92, 0x95, 0x2e, 0x4b, 0x4a, 0xd3, 0x3b, 0xfb, 0x1a, 0xb8, 0x65, 0xb7, 0x58, 0xbb, 0x27, 0x58, 0x34, 0x0a, - 0xfc, 0x83, 0x35, 0xfb, 0xc2, 0x25, 0x80, 0x9a, 0x5b, 0x9e, 0xf4, 0x0a, 0xd5, 0x05, 0xd2, 0xfd, 0xe0, 0x09, 0xa7, - 0x17, 0xd9, 0x17, 0x2c, 0x83, 0xbe, 0x32, 0x5c, 0xb3, 0x1d, 0xd6, 0xee, 0xd6, 0x58, 0xb6, 0xac, 0xea, 0x49, 0x44, - 0x60, 0x14, 0x54, 0x4a, 0xcb, 0xbf, 0x11, 0xcb, 0xa6, 0x6e, 0x1a, 0xd4, 0x86, 0xfe, 0x7c, 0x30, 0xfa, 0x0f, 0x5f, - 0xbf, 0xfb, 0xc1, 0x2b, 0xf5, 0xb5, 0xf7, 0x17, 0xc7, 0xb5, 0xb2, 0x44, 0xd7, 0xca, 0x5f, 0x79, 0x39, 0xfb, 0x65, - 0x3e, 0xd1, 0xb5, 0xa4, 0x1d, 0x86, 0x7c, 0x4d, 0x67, 0xbf, 0x74, 0x38, 0x5b, 0xfe, 0xea, 0xfb, 0x8d, 0xe9, 0x62, - 0xf5, 0x59, 0xdd, 0xbb, 0x0f, 0x83, 0x6d, 0xe3, 0xd4, 0x7b, 0x7f, 0xbe, 0xde, 0xd8, 0xcc, 0x5a, 0x7b, 0x66, 0xfe, - 0x0f, 0x57, 0x7a, 0x87, 0x43, 0x77, 0xcb, 0x77, 0xc3, 0xad, 0x3d, 0x0a, 0xf2, 0xfb, 0x52, 0x69, 0x9c, 0xd5, 0xfc, - 0x85, 0x97, 0x77, 0x49, 0xb1, 0x80, 0x68, 0xf4, 0xc9, 0x48, 0x42, 0xd7, 0xcc, 0xc4, 0x33, 0xc4, 0x57, 0x19, 0x20, - 0x73, 0x81, 0x68, 0x76, 0xcf, 0xc7, 0x93, 0xfb, 0x9b, 0x78, 0x72, 0x3f, 0xe0, 0x9f, 0x4c, 0x0b, 0xda, 0x8b, 0xed, - 0xde, 0x67, 0xbf, 0xf2, 0xc2, 0x5e, 0x8e, 0xbf, 0xf8, 0xec, 0x9d, 0x70, 0x57, 0xe8, 0x2f, 0x3e, 0xfb, 0x22, 0xf8, - 0xaf, 0x23, 0x4d, 0x94, 0xc1, 0xbe, 0xd4, 0xfc, 0xd7, 0x11, 0x32, 0x7e, 0xb0, 0xcf, 0x82, 0xbf, 0x03, 0xdf, 0xef, - 0x2a, 0x41, 0xab, 0xf8, 0xe7, 0x5a, 0xfd, 0x7c, 0x2f, 0xe3, 0x72, 0xe0, 0x4d, 0x68, 0x05, 0xbd, 0x79, 0x57, 0xcb, - 0x9f, 0xc4, 0xc3, 0x91, 0xaa, 0xa7, 0x86, 0x7f, 0x16, 0x8b, 0x59, 0xd4, 0x27, 0xe9, 0x54, 0xde, 0xe4, 0x2d, 0xcf, - 0xa4, 0x75, 0xf9, 0x1e, 0x42, 0x81, 0xdf, 0xda, 0x10, 0x05, 0x7b, 0x8e, 0x1b, 0xc1, 0x5b, 0x06, 0xf0, 0x91, 0xd9, - 0x74, 0xc7, 0x6f, 0xf9, 0x13, 0xfe, 0x85, 0xef, 0x83, 0x07, 0xfe, 0x9e, 0xbf, 0xe1, 0x3f, 0xf1, 0x3d, 0x5b, 0x4a, - 0xb4, 0xd3, 0x7a, 0x77, 0x1d, 0xec, 0x58, 0xbd, 0xbf, 0x0e, 0x1e, 0x58, 0xbd, 0x7b, 0x16, 0xdc, 0xb2, 0x7a, 0xff, - 0x2c, 0x78, 0xcf, 0x76, 0xd7, 0xc1, 0x13, 0xb6, 0xbf, 0x0e, 0xde, 0xb0, 0xdd, 0xb3, 0xe0, 0x0b, 0xdb, 0x3f, 0x0b, - 0x7e, 0x92, 0x18, 0x0f, 0x5f, 0x84, 0xe4, 0x38, 0xf9, 0x52, 0x33, 0xc3, 0xa7, 0x1b, 0x7c, 0x16, 0xd6, 0x2f, 0xaa, - 0x63, 0xf0, 0xb9, 0x66, 0xba, 0xc5, 0x81, 0x10, 0x4c, 0xb7, 0x37, 0xb8, 0xa3, 0x27, 0xa6, 0x55, 0x41, 0x2a, 0x58, - 0x57, 0x3b, 0x83, 0x45, 0xdd, 0xb4, 0xce, 0x64, 0xc7, 0x2f, 0x31, 0xee, 0xf0, 0x4b, 0x5c, 0xb0, 0x65, 0xd3, 0xe9, - 0xa4, 0x73, 0xfe, 0x24, 0xd0, 0x9b, 0xbf, 0xde, 0xf5, 0x73, 0xe9, 0x3b, 0x53, 0x34, 0x5c, 0x6b, 0x8d, 0x5b, 0x3b, - 0x7d, 0x68, 0xed, 0xf4, 0x4c, 0xaa, 0xd0, 0x22, 0x16, 0x95, 0x45, 0x55, 0x21, 0x93, 0x78, 0x90, 0x69, 0x7d, 0x5a, - 0xc2, 0x48, 0x91, 0x09, 0x68, 0xf4, 0x05, 0x1d, 0x03, 0x15, 0x59, 0x14, 0xd8, 0x92, 0x6f, 0x07, 0x09, 0xdb, 0xf0, - 0x78, 0x3a, 0x4c, 0x82, 0x25, 0x5b, 0xf1, 0x61, 0xb7, 0x40, 0xb0, 0x56, 0x01, 0x4c, 0xfa, 0xe2, 0xd4, 0xde, 0xd7, - 0x79, 0x6f, 0x9d, 0xc6, 0x71, 0x26, 0x50, 0xd9, 0x96, 0xeb, 0x0d, 0x7e, 0xe7, 0xec, 0xe7, 0x1b, 0xb5, 0xbf, 0x83, - 0xa4, 0xf0, 0x2b, 0x30, 0xec, 0x10, 0xe1, 0x1d, 0x54, 0x18, 0x79, 0x96, 0xcc, 0xa2, 0xcf, 0xed, 0x2d, 0x7d, 0x67, - 0xb6, 0xe9, 0x7f, 0xb7, 0x08, 0xda, 0xc7, 0x65, 0xe7, 0x7f, 0x32, 0xaf, 0xfe, 0xd6, 0xf1, 0xea, 0xd6, 0x9f, 0x3c, - 0xf0, 0x4f, 0x18, 0x96, 0x80, 0x89, 0x6c, 0xcf, 0x3f, 0x8d, 0x76, 0x8d, 0x53, 0x9e, 0xdc, 0xc7, 0xff, 0xaf, 0x14, - 0x68, 0xef, 0xe4, 0xb9, 0xbd, 0x23, 0xee, 0x78, 0xc7, 0x3e, 0xbe, 0xb4, 0x36, 0x44, 0x03, 0x4d, 0xf2, 0x89, 0xbb, - 0xd1, 0xd0, 0xb0, 0x21, 0xfe, 0xc2, 0xf3, 0xd9, 0xa7, 0xf9, 0x64, 0xc7, 0x4f, 0xb7, 0xc3, 0x4f, 0x1d, 0xdb, 0xe1, - 0x2f, 0xfe, 0x60, 0xd9, 0x7c, 0xad, 0x57, 0x3b, 0xb7, 0x71, 0xa7, 0xd2, 0x7b, 0x7e, 0xba, 0x89, 0x0f, 0xff, 0xed, - 0x4a, 0xef, 0xbf, 0xb9, 0xd2, 0x76, 0x95, 0xbb, 0x3b, 0xdf, 0x74, 0x7c, 0x23, 0x6b, 0x8d, 0x71, 0x66, 0x46, 0xb3, + 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, 0x58, 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, 0x1f, 0x55, 0x36, 0x76, 0x07, 0xe4, 0x90, 0x64, 0xb2, 0xb8, 0x1b, 0xdd, + 0x8a, 0x65, 0x51, 0x8a, 0x9f, 0xb1, 0x1e, 0xae, 0xd9, 0xc2, 0x7d, 0x06, 0x84, 0xf6, 0x13, 0xa5, 0xbd, 0x89, 0x34, + 0x41, 0xf7, 0x1d, 0x5b, 0x01, 0xc8, 0x00, 0x8a, 0xba, 0xda, 0xad, 0xcf, 0xf9, 0x39, 0x92, 0x66, 0x38, 0x8c, 0x6e, + 0x9f, 0xde, 0x05, 0x77, 0x83, 0x4b, 0xd4, 0x4a, 0x5f, 0xb2, 0xb8, 0x85, 0x41, 0xb5, 0x37, 0x4b, 0x38, 0xa8, 0x99, + 0xb5, 0x36, 0x02, 0xc1, 0x64, 0x0f, 0x05, 0x15, 0x73, 0x05, 0xfb, 0xa0, 0x60, 0x2d, 0x79, 0x1d, 0x1c, 0x6e, 0xed, + 0xcb, 0x4a, 0x71, 0xf1, 0xfc, 0x22, 0x69, 0x5d, 0x58, 0xca, 0x8b, 0xe7, 0x0d, 0x18, 0x5c, 0x8e, 0xb0, 0xa9, 0x2a, + 0x7f, 0xb2, 0x01, 0xd0, 0xad, 0x90, 0x22, 0x5e, 0x94, 0xc2, 0xb6, 0x95, 0xcf, 0x9c, 0xb0, 0xc1, 0x86, 0x3d, 0xc0, + 0xbd, 0x32, 0x28, 0x19, 0x5c, 0x88, 0x71, 0xbb, 0xd9, 0x05, 0xb8, 0x82, 0xa1, 0x30, 0xb6, 0xe6, 0x6f, 0x32, 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, 0x7c, 0xce, 0xbc, 0xa5, 0xcf, 0xde, 0x54, 0x32, 0x5a, 0x93, 0x44, + 0x79, 0xf5, 0x70, 0x09, 0x72, 0xc3, 0x72, 0xf4, 0xc0, 0x96, 0x20, 0x4e, 0x2c, 0x47, 0x09, 0x65, 0x74, 0x85, 0x7b, + 0x95, 0xd9, 0x32, 0x11, 0x48, 0x71, 0x60, 0x29, 0xe5, 0xde, 0x62, 0x1d, 0x2c, 0x71, 0x7f, 0x22, 0xb9, 0x80, 0x92, + 0x07, 0x50, 0xae, 0x14, 0x10, 0xf0, 0xe9, 0x00, 0xca, 0x97, 0xf2, 0x22, 0xfc, 0x89, 0x13, 0x35, 0x58, 0x8e, 0x1e, + 0x1a, 0xf6, 0xa3, 0x17, 0x5a, 0xf6, 0x87, 0x3b, 0xad, 0x69, 0x58, 0xf1, 0x3b, 0x98, 0x16, 0x13, 0xb7, 0x2f, 0x57, + 0x76, 0x55, 0x7c, 0xb6, 0x52, 0x67, 0x37, 0x35, 0x24, 0x61, 0x5f, 0x91, 0x55, 0x80, 0x83, 0x55, 0x11, 0xf7, 0x2c, + 0xcb, 0x7d, 0x18, 0xfd, 0xb9, 0x49, 0x4b, 0x61, 0xa1, 0x4a, 0xfa, 0xfb, 0xa6, 0x14, 0x48, 0x65, 0xa2, 0x13, 0x2d, + 0x04, 0x57, 0x60, 0x10, 0xb8, 0x17, 0x79, 0x0d, 0x80, 0x31, 0xe0, 0x52, 0xa0, 0x2c, 0xdb, 0x12, 0x42, 0xaa, 0xfb, + 0x19, 0xa8, 0xed, 0xc4, 0x7d, 0x1a, 0x91, 0xb5, 0x10, 0x7d, 0x15, 0x8c, 0x99, 0xf3, 0x52, 0xba, 0xc5, 0xa6, 0xab, + 0xcd, 0xea, 0x06, 0x9d, 0x4b, 0x5b, 0x6e, 0x7e, 0xc2, 0x16, 0x6b, 0x05, 0xca, 0x26, 0x24, 0x6d, 0xe7, 0x3c, 0x47, + 0xd9, 0x84, 0x96, 0xf6, 0x9e, 0x7a, 0x54, 0xa8, 0x4e, 0xb6, 0x5e, 0xaa, 0xa6, 0x16, 0x61, 0xb5, 0xb8, 0xa8, 0xfc, + 0x00, 0x74, 0x53, 0x69, 0xf5, 0xb2, 0xae, 0xd1, 0x14, 0x6a, 0xb5, 0x70, 0xdc, 0x68, 0x67, 0xd3, 0x65, 0x7a, 0x87, + 0x38, 0xab, 0xd2, 0x0e, 0xfd, 0x7d, 0xa6, 0x5d, 0x2f, 0x3b, 0xfa, 0xcd, 0xb8, 0xba, 0xc0, 0x85, 0xd8, 0x80, 0xcf, + 0xb9, 0xbf, 0xbc, 0xde, 0xf3, 0xb8, 0xe7, 0x1f, 0x0e, 0xc8, 0x9e, 0xd4, 0xfe, 0x50, 0x7d, 0xec, 0x0a, 0x86, 0x2c, + 0x8c, 0x52, 0x7f, 0x91, 0xf2, 0xde, 0x13, 0x1c, 0xf7, 0xcf, 0x55, 0x8f, 0xfd, 0x98, 0xf1, 0x7d, 0x5d, 0x6c, 0xa2, + 0x84, 0xa2, 0x1a, 0x7a, 0xab, 0x62, 0x53, 0x89, 0xb8, 0x78, 0xc8, 0x7b, 0x0c, 0x93, 0x61, 0x2c, 0x64, 0x2a, 0xfc, + 0x29, 0x53, 0xc1, 0x23, 0x84, 0x12, 0x37, 0xeb, 0x1e, 0x69, 0x37, 0x21, 0x4e, 0xa9, 0x16, 0xa5, 0x4c, 0xc6, 0xbf, + 0xf5, 0x13, 0x28, 0xcf, 0x29, 0x5a, 0xa6, 0x1f, 0x15, 0x2e, 0xd3, 0x37, 0xeb, 0xe3, 0xd2, 0x33, 0x11, 0xea, 0xcc, + 0xc5, 0xa6, 0xd6, 0xe9, 0x18, 0x3b, 0xa5, 0x53, 0x1b, 0xf6, 0xa5, 0x52, 0x5c, 0x56, 0x14, 0xfe, 0x8d, 0x44, 0x56, + 0x3d, 0x23, 0x8e, 0xff, 0x2b, 0x6b, 0x9f, 0x61, 0x15, 0xf8, 0x65, 0x20, 0xef, 0x17, 0x00, 0x1f, 0xd7, 0x75, 0x99, + 0xde, 0x6e, 0x80, 0x36, 0x84, 0x86, 0xbf, 0xe7, 0x23, 0x03, 0xa6, 0xfb, 0x08, 0x67, 0x48, 0x0f, 0x75, 0xce, 0xe9, + 0xac, 0x4c, 0xe7, 0x5c, 0x85, 0xb5, 0x04, 0x7b, 0x39, 0x69, 0x72, 0xb9, 0x2e, 0x41, 0xcd, 0x04, 0x6e, 0x1f, 0xda, + 0x23, 0x42, 0xa8, 0x4d, 0x59, 0x4d, 0x2f, 0xa1, 0xe6, 0x9d, 0x9c, 0x76, 0x34, 0x29, 0xc1, 0x55, 0x43, 0x67, 0xe5, + 0xfa, 0xaf, 0xc3, 0xa1, 0x77, 0x9b, 0x15, 0xd1, 0x1f, 0x3d, 0xf4, 0x77, 0xdc, 0xde, 0xa4, 0x5f, 0x20, 0x5a, 0xc6, + 0xfa, 0x1b, 0x32, 0xa0, 0xe3, 0xc9, 0xf0, 0xb6, 0xd8, 0xf6, 0xd8, 0x17, 0xd4, 0x60, 0xe9, 0xeb, 0xc7, 0x1f, 0x20, + 0xa1, 0xea, 0xda, 0x17, 0x16, 0x4f, 0x98, 0xa7, 0x44, 0xdb, 0xc2, 0x87, 0xb0, 0xd0, 0x2f, 0x10, 0x19, 0x09, 0xe1, + 0xa6, 0xb2, 0x7b, 0x94, 0xb4, 0x0b, 0x7d, 0xe9, 0x6b, 0xd9, 0x57, 0xbe, 0x73, 0x01, 0xb0, 0xb2, 0xcf, 0x6d, 0xb8, + 0x27, 0xfd, 0x29, 0xd5, 0x87, 0xed, 0x6f, 0xc9, 0x02, 0x0a, 0x2d, 0xac, 0xa7, 0x72, 0x76, 0xae, 0x4b, 0x9e, 0x66, + 0xd3, 0xfd, 0x1a, 0xf6, 0xa8, 0x7b, 0xf4, 0x9a, 0x0a, 0xce, 0x2f, 0xcd, 0xe8, 0xfd, 0xd3, 0x50, 0xa8, 0x8e, 0x3a, + 0x77, 0x90, 0x75, 0x69, 0x5d, 0x72, 0x7e, 0xb3, 0x72, 0x47, 0x61, 0x7e, 0x1f, 0x82, 0x67, 0x58, 0xf7, 0xee, 0xe2, + 0xbc, 0xf7, 0x67, 0x6b, 0x8e, 0xfc, 0x98, 0xcd, 0x52, 0xc4, 0x22, 0x99, 0x83, 0xd5, 0x0f, 0xfd, 0x3c, 0xf6, 0xdb, + 0x20, 0x87, 0xe3, 0xa6, 0x01, 0x1d, 0x36, 0x64, 0xd6, 0xbe, 0x44, 0xe0, 0x54, 0x23, 0x48, 0x53, 0x13, 0xd4, 0x2c, + 0x0f, 0x91, 0xd8, 0x2e, 0x65, 0xdb, 0x20, 0xd7, 0x5d, 0x30, 0xcd, 0x91, 0xf6, 0x0c, 0xde, 0x37, 0x69, 0x92, 0x0a, + 0xcd, 0x22, 0x6d, 0x95, 0x8c, 0x7f, 0x47, 0xda, 0x4c, 0xc9, 0x1e, 0x5b, 0x03, 0xef, 0x25, 0x28, 0x27, 0xc3, 0x14, + 0xc3, 0x77, 0x7c, 0xbd, 0xf3, 0x98, 0x7b, 0xce, 0x31, 0xdb, 0xa4, 0xec, 0x08, 0x26, 0xc9, 0xc6, 0x37, 0x14, 0x6f, + 0xf8, 0xfe, 0xb6, 0x12, 0x25, 0x80, 0x5e, 0x16, 0xfc, 0x85, 0xb4, 0xb9, 0x42, 0xb7, 0xbb, 0x77, 0x94, 0xc2, 0x2f, + 0x79, 0x79, 0x38, 0x6c, 0x53, 0x2f, 0x84, 0xce, 0x17, 0xf1, 0x3b, 0x30, 0x87, 0x31, 0xc4, 0x66, 0x04, 0x08, 0x73, + 0x7c, 0x40, 0x1d, 0xac, 0x1f, 0x01, 0x68, 0x9c, 0x40, 0x01, 0x46, 0x5f, 0x6d, 0x0b, 0xfa, 0x96, 0x17, 0x17, 0x11, + 0xa2, 0x46, 0x01, 0x26, 0x4a, 0x9a, 0xc5, 0x30, 0x1c, 0xe8, 0xfc, 0xbe, 0xb9, 0xad, 0x4b, 0x81, 0x43, 0xef, 0x58, + 0x86, 0xff, 0xfe, 0x3f, 0xd6, 0x96, 0x56, 0x95, 0xed, 0xd6, 0x38, 0xcd, 0xfc, 0x6f, 0xb7, 0x85, 0xbe, 0xff, 0x4a, + 0x28, 0x9e, 0x77, 0xbc, 0x6e, 0xbf, 0x83, 0xe8, 0x7d, 0xdd, 0xca, 0xbb, 0x52, 0xbb, 0x61, 0xa6, 0xfc, 0x21, 0xcd, + 0xe3, 0xe2, 0x61, 0x14, 0xb7, 0x8e, 0xbc, 0x49, 0x7a, 0xce, 0xf9, 0xbb, 0xaa, 0xdf, 0xf7, 0xde, 0x01, 0x19, 0xef, + 0x2b, 0x61, 0x1c, 0x31, 0x89, 0x83, 0x6f, 0x2f, 0x46, 0xd1, 0xa6, 0x84, 0x0d, 0xb9, 0x7d, 0x5a, 0x82, 0x66, 0xa6, + 0xdf, 0x47, 0x89, 0xd2, 0x9a, 0xef, 0x7f, 0x93, 0xf3, 0xfd, 0x95, 0x90, 0x37, 0x2b, 0xf9, 0xe1, 0xa3, 0x15, 0x06, + 0xbe, 0xc7, 0xe9, 0x17, 0xd1, 0x63, 0x77, 0xa5, 0x0f, 0xdf, 0x95, 0x96, 0x3e, 0xab, 0xa8, 0x7f, 0xa0, 0xa2, 0xe6, + 0x95, 0x18, 0x11, 0xf1, 0x20, 0x68, 0x67, 0xdb, 0xa5, 0x76, 0x2d, 0x41, 0xbb, 0x60, 0x53, 0xd8, 0xbf, 0x1f, 0x1d, + 0xf2, 0x7e, 0xff, 0x63, 0xee, 0xb5, 0x78, 0xdd, 0x75, 0x68, 0xca, 0x4f, 0x85, 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, 0x11, 0xeb, 0xa6, 0xa7, 0x55, 0x68, 0xf9, 0x1a, 0x82, 0x75, 0x91, 0x65, 0x1c, 0xc5, + 0x4c, 0x00, 0xb0, 0xf9, 0x08, 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, + 0x7b, 0xaa, 0x7a, 0x44, 0xa0, 0x57, 0x65, 0x5a, 0x45, 0x45, 0x9e, 0x8b, 0x08, 0x11, 0xaa, 0xa5, 0x73, 0x38, 0xf4, + 0x63, 0xbf, 0x8f, 0x03, 0x61, 0x5e, 0xfc, 0xe9, 0xb1, 0xae, 0xfc, 0xa9, 0xc0, 0xb5, 0x92, 0x02, 0xa7, 0xa2, 0x46, + 0x88, 0x10, 0xde, 0x9f, 0xc0, 0xb3, 0x9a, 0xfa, 0x7e, 0x63, 0x99, 0xe8, 0xfe, 0x99, 0x01, 0xe5, 0x0f, 0xc8, 0xd7, + 0x95, 0x14, 0x67, 0xea, 0xe4, 0x31, 0x71, 0xc6, 0x01, 0x88, 0xf9, 0xba, 0x44, 0xa3, 0xb1, 0xff, 0x01, 0x09, 0x86, + 0xea, 0x07, 0x3b, 0xdd, 0xd4, 0xfb, 0x57, 0x26, 0x71, 0x14, 0x7d, 0xda, 0x26, 0x8f, 0x25, 0x4b, 0xa3, 0x85, 0xa3, + 0xf7, 0x88, 0x61, 0x1c, 0x4e, 0xe7, 0x63, 0x92, 0x6d, 0x4c, 0x56, 0x01, 0xa4, 0x93, 0x99, 0x3a, 0xa6, 0xd4, 0xd1, + 0x38, 0xd7, 0x0b, 0xaa, 0xd0, 0x63, 0x5d, 0xf2, 0x1c, 0xac, 0x27, 0x3f, 0x78, 0xa5, 0x3f, 0x15, 0x72, 0x0e, 0x1b, + 0x89, 0xa0, 0xf0, 0x03, 0x5c, 0x0d, 0x56, 0x0a, 0x18, 0x4c, 0x7d, 0x0b, 0x5f, 0x13, 0xcf, 0x51, 0xf0, 0x28, 0xec, + 0x62, 0x6c, 0xad, 0x7c, 0xe7, 0x93, 0x82, 0x72, 0xcf, 0x8a, 0x39, 0xaf, 0x80, 0x73, 0x19, 0x14, 0xc2, 0x74, 0x3c, + 0xcb, 0xff, 0x99, 0xe4, 0xf5, 0xc4, 0x86, 0x00, 0x19, 0xfc, 0x29, 0x71, 0x5a, 0xba, 0x43, 0x77, 0x1e, 0x7a, 0x16, + 0x71, 0xd8, 0xe8, 0xc9, 0xba, 0x2c, 0xb6, 0x29, 0xea, 0x25, 0xcc, 0x0f, 0xe4, 0xe7, 0x2d, 0xf9, 0x3e, 0x44, 0xf1, + 0x36, 0xf8, 0x35, 0x63, 0xb1, 0xc0, 0xbf, 0xfe, 0x9e, 0x31, 0x9a, 0x68, 0xc1, 0xbf, 0xb3, 0x06, 0x89, 0x8a, 0x7f, + 0xca, 0x26, 0x00, 0xeb, 0xc8, 0xd5, 0x87, 0x4f, 0x89, 0xf1, 0xd6, 0x6c, 0x78, 0xe4, 0x9b, 0x15, 0xe8, 0xd4, 0xe7, + 0xee, 0xca, 0xf6, 0x54, 0x35, 0xfe, 0x9e, 0xea, 0x6a, 0xa4, 0xaa, 0x1a, 0x7f, 0x4f, 0xa9, 0x1a, 0xbf, 0x65, 0x14, + 0xbf, 0x53, 0xf9, 0x0c, 0x99, 0x93, 0x4d, 0x4c, 0xd2, 0xe9, 0x7b, 0xc3, 0x89, 0x5d, 0xf6, 0xab, 0xb7, 0x89, 0xcc, + 0x44, 0x0a, 0xb9, 0x37, 0x00, 0x6d, 0xbf, 0xcb, 0x0d, 0xa7, 0xc4, 0xf9, 0xb9, 0x87, 0x2b, 0x36, 0xad, 0x5e, 0xd1, + 0x82, 0x05, 0x36, 0x2f, 0xb3, 0x3c, 0x45, 0x02, 0xdb, 0xa6, 0xcc, 0xfa, 0x73, 0xee, 0x01, 0x04, 0x33, 0xa9, 0x09, + 0x00, 0x69, 0x21, 0x2a, 0x85, 0xc8, 0x5f, 0xe1, 0xac, 0x3e, 0xe7, 0xbd, 0x4d, 0x1e, 0x13, 0x69, 0x75, 0xaf, 0xdf, + 0x4f, 0xcf, 0xd2, 0x9c, 0x82, 0x1a, 0x8e, 0xb3, 0x4e, 0xbf, 0xcf, 0x82, 0x3a, 0x91, 0xab, 0xf4, 0x1f, 0x6e, 0x90, + 0x97, 0xf1, 0x7d, 0xdd, 0xf6, 0xfc, 0x89, 0xfa, 0x7b, 0x67, 0xfd, 0x6d, 0x81, 0xe0, 0x4e, 0x8e, 0xfd, 0x64, 0x55, + 0xca, 0x13, 0xe3, 0xd2, 0xde, 0xf3, 0x9b, 0xba, 0x28, 0xb2, 0x3a, 0x5d, 0x7f, 0x90, 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, 0xe8, 0x40, 0xbd, 0xb4, 0xd2, 0x3e, 0x82, 0x6e, + 0x05, 0x7a, 0x50, 0x0f, 0x7d, 0x9a, 0xb4, 0x2f, 0x24, 0xea, 0xf6, 0x56, 0xa7, 0xd1, 0x1f, 0x15, 0x5c, 0x4e, 0x61, + 0x72, 0xb8, 0xa1, 0x4f, 0xab, 0x70, 0xfb, 0x09, 0x9e, 0xfe, 0x0c, 0x94, 0x5b, 0x87, 0x43, 0x0e, 0x62, 0x0b, 0xb8, + 0x79, 0xac, 0xc2, 0xcf, 0x45, 0x29, 0x23, 0xea, 0xe3, 0x69, 0x01, 0xda, 0xbb, 0x00, 0x1d, 0xb0, 0x34, 0x88, 0x57, + 0x48, 0x9e, 0xb3, 0x11, 0xc0, 0xb2, 0x03, 0xcb, 0x59, 0xc6, 0x29, 0xcc, 0xb3, 0x7c, 0xa1, 0x56, 0xda, 0x59, 0x99, + 0x78, 0x35, 0xcb, 0xc0, 0x59, 0xe0, 0xa2, 0xf2, 0x59, 0xa6, 0x55, 0x4f, 0x55, 0x82, 0x3e, 0xaf, 0xe4, 0x04, 0x57, + 0x82, 0x93, 0x0d, 0xc8, 0x2f, 0x40, 0x92, 0xa6, 0x94, 0x35, 0xe5, 0x8b, 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, 0x3f, + 0x78, 0x4b, 0x7f, 0x3a, 0x0e, 0xc2, 0x21, 0x72, 0x43, 0xc5, 0x1c, 0xd8, 0xd3, 0x80, 0xc5, 0x26, 0xbe, 0xda, 0x4c, + 0xe2, 0xc1, 0xc0, 0xd7, 0x19, 0x8b, 0x59, 0x0c, 0x34, 0xc8, 0xf1, 0xe0, 0x72, 0xae, 0x4f, 0x08, 0xfd, 0x30, 0xa2, + 0x72, 0x54, 0xa0, 0x73, 0x10, 0x0d, 0x96, 0x80, 0xa7, 0xde, 0xca, 0x06, 0x49, 0xc6, 0x24, 0x93, 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, 0x3f, 0xcb, 0x07, 0x8e, 0x3b, 0x2a, 0x69, + 0x08, 0x0c, 0xde, 0x1e, 0xba, 0x9b, 0x19, 0x1a, 0xea, 0xa4, 0x7d, 0x18, 0x87, 0x72, 0x88, 0x55, 0x2b, 0x2e, 0xa4, + 0x37, 0x82, 0x6f, 0x17, 0x8a, 0xb1, 0x6c, 0xec, 0xd2, 0x50, 0x14, 0xfe, 0x0a, 0x60, 0x87, 0xda, 0x5f, 0xa9, 0xe4, + 0x63, 0x64, 0x54, 0xd3, 0x40, 0xc7, 0x00, 0x2c, 0x59, 0x9a, 0x48, 0xaa, 0x48, 0x23, 0xf1, 0x47, 0x66, 0xac, 0xa3, + 0xa6, 0xeb, 0x0b, 0xa6, 0xaa, 0x45, 0xd2, 0xed, 0x4c, 0x62, 0x39, 0x91, 0xa4, 0xb6, 0xfb, 0x88, 0x18, 0x0c, 0x7c, + 0xb0, 0x11, 0xd3, 0x4c, 0x84, 0x23, 0x1e, 0x95, 0xc8, 0xa2, 0xcb, 0x6f, 0xa3, 0x4c, 0xda, 0xbe, 0xac, 0xc8, 0x16, + 0x04, 0xd3, 0x93, 0xe8, 0x83, 0x24, 0xe5, 0x54, 0x24, 0xd2, 0x8c, 0x10, 0xe0, 0xc7, 0x93, 0xf2, 0x4a, 0x7f, 0x0e, + 0x9a, 0x56, 0x82, 0x97, 0x0c, 0x92, 0x47, 0xe2, 0x67, 0x52, 0x30, 0x8b, 0xb1, 0x6a, 0x30, 0xc0, 0x72, 0xaa, 0x67, + 0x8e, 0x49, 0xfa, 0x6f, 0x9d, 0x4e, 0xd8, 0x2f, 0xbd, 0xdc, 0xd6, 0xf2, 0xa6, 0xb9, 0xf7, 0xd2, 0xab, 0x58, 0xaa, + 0x61, 0x19, 0xf4, 0x5f, 0x13, 0xed, 0x82, 0xad, 0x2d, 0x63, 0xc2, 0xaa, 0x1f, 0x40, 0xda, 0x23, 0x5d, 0x5e, 0x35, + 0xcc, 0x99, 0xe0, 0xd1, 0x85, 0x35, 0x0f, 0xa2, 0x0b, 0xe1, 0x23, 0x97, 0xdd, 0x24, 0xb9, 0x1a, 0x4f, 0xfc, 0x70, + 0x30, 0x50, 0x00, 0xb4, 0xb4, 0x4e, 0x8a, 0x41, 0xf8, 0x4c, 0xc8, 0x81, 0x34, 0x3a, 0xaa, 0x02, 0x2c, 0x96, 0xd9, + 0x55, 0x39, 0xc9, 0x06, 0x03, 0x1f, 0xc4, 0xc6, 0xc4, 0x6e, 0x68, 0x36, 0xf7, 0xd9, 0x89, 0x82, 0xac, 0x36, 0x87, + 0xad, 0x99, 0x6e, 0x81, 0x01, 0xc0, 0x20, 0x22, 0x58, 0xee, 0x73, 0x23, 0x1f, 0x51, 0xa7, 0xa7, 0x30, 0x02, 0x82, + 0x5f, 0x4e, 0x04, 0x22, 0x17, 0x09, 0xd4, 0x03, 0xcc, 0x04, 0x98, 0x51, 0xc5, 0xf0, 0x12, 0xd8, 0xc5, 0x73, 0xf3, + 0x8a, 0x41, 0xff, 0xa2, 0x49, 0x96, 0x68, 0x2a, 0x71, 0x34, 0x46, 0x4e, 0xa5, 0x31, 0x32, 0x20, 0x76, 0x71, 0xfc, + 0x7b, 0x4a, 0x8f, 0x82, 0x94, 0x7d, 0xae, 0x0c, 0x71, 0x38, 0x8a, 0xaf, 0x60, 0xd5, 0x38, 0x1c, 0x6a, 0xf3, 0x7a, + 0x3a, 0xab, 0xe7, 0x03, 0x11, 0xc0, 0x7f, 0x43, 0xc1, 0x7e, 0xd1, 0x54, 0xe4, 0x06, 0xa9, 0xf3, 0x70, 0x48, 0x41, + 0x3e, 0xd5, 0x4d, 0xfe, 0xbe, 0x72, 0xf7, 0xd3, 0xd9, 0xdc, 0x9a, 0xa3, 0x17, 0x35, 0xae, 0x5b, 0xab, 0x1b, 0x0a, + 0x89, 0xd6, 0x34, 0x29, 0xae, 0xaa, 0x49, 0x31, 0xe0, 0xb9, 0x2f, 0x54, 0x17, 0x5b, 0x23, 0x58, 0xf8, 0x73, 0x0b, + 0x84, 0xc9, 0xb8, 0x17, 0x1f, 0x2d, 0xe4, 0x94, 0x76, 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, 0xf3, 0x20, 0xe3, 0x5e, 0x34, 0xec, 0xf8, 0x02, 0xec, 0xd5, 0x17, 0xcf, + 0x59, 0x34, 0xe0, 0xd5, 0x55, 0x3d, 0xcd, 0x82, 0x61, 0xc6, 0xa2, 0xab, 0x62, 0x08, 0x3e, 0xb4, 0x2f, 0xca, 0x41, + 0xe8, 0xfb, 0x66, 0xe7, 0xd0, 0xdd, 0x90, 0xc8, 0x23, 0xec, 0x47, 0x70, 0xdb, 0xd5, 0x12, 0x33, 0x98, 0x6c, 0xee, + 0x22, 0x66, 0xb0, 0xe5, 0x2f, 0x9e, 0x1b, 0x2e, 0xa1, 0xea, 0x85, 0xd4, 0x6c, 0x14, 0x68, 0x4e, 0xae, 0xd0, 0x9c, + 0xac, 0x84, 0x5a, 0xf2, 0x49, 0x85, 0x13, 0x76, 0x3e, 0xc9, 0x95, 0xdd, 0x68, 0x8c, 0x81, 0x8b, 0xf6, 0xdc, 0x16, + 0x46, 0x66, 0x3a, 0x4b, 0xd1, 0x80, 0x85, 0x67, 0xe2, 0x94, 0xc6, 0x80, 0xf6, 0xe5, 0xc0, 0xd2, 0x86, 0xfc, 0x28, + 0x67, 0x06, 0xda, 0x86, 0x94, 0x46, 0xcd, 0xc0, 0x9f, 0xa9, 0x09, 0xf3, 0x2b, 0x58, 0x89, 0x20, 0xaa, 0x0b, 0x30, + 0x49, 0x72, 0x32, 0x1a, 0x29, 0x2b, 0x91, 0x9c, 0x03, 0xde, 0x47, 0xf0, 0x64, 0x11, 0xdb, 0xda, 0x9f, 0xd2, 0xff, + 0xea, 0xf0, 0xb9, 0xf4, 0x9f, 0x09, 0x60, 0x21, 0x97, 0x06, 0x91, 0x81, 0xc2, 0x21, 0x35, 0x95, 0x88, 0x13, 0xc7, + 0x33, 0xf0, 0x0d, 0x5c, 0xa0, 0x29, 0xa0, 0x3f, 0xa8, 0x19, 0x45, 0x64, 0xe1, 0xaf, 0x9e, 0xdd, 0xd4, 0x8d, 0x9e, + 0x67, 0xce, 0x6b, 0xd0, 0xcc, 0x40, 0x48, 0x8f, 0x53, 0xf5, 0x36, 0x24, 0x3a, 0x2f, 0x2f, 0xf5, 0xcb, 0x84, 0x48, + 0x56, 0x44, 0x9e, 0xbe, 0xcf, 0xc1, 0x3c, 0xa2, 0x08, 0x1d, 0x5c, 0x99, 0x87, 0xc3, 0xb9, 0xa0, 0xf0, 0x1d, 0xe5, + 0xf9, 0x80, 0xd3, 0x2c, 0x4a, 0x40, 0x1b, 0xc8, 0x72, 0x53, 0xe6, 0x3a, 0x69, 0x99, 0xba, 0xf7, 0x60, 0x25, 0xa8, + 0xd0, 0xcd, 0x29, 0x28, 0x94, 0x91, 0xa0, 0x94, 0x56, 0x83, 0x50, 0xaa, 0xc3, 0x22, 0x88, 0x1c, 0xb2, 0x10, 0x70, + 0x33, 0x15, 0x8d, 0x96, 0x34, 0x3c, 0xc2, 0xb9, 0x81, 0x42, 0x00, 0x12, 0x7b, 0xaa, 0x28, 0xe3, 0x72, 0x08, 0xf8, + 0x28, 0xe1, 0x10, 0x67, 0x4d, 0xda, 0xf2, 0x1c, 0xc4, 0xb1, 0x5c, 0xf2, 0x75, 0x85, 0x60, 0x10, 0xa1, 0xcf, 0x90, + 0x3f, 0x59, 0xce, 0xbf, 0x5b, 0x87, 0x69, 0x47, 0xf8, 0xb0, 0xab, 0x2d, 0xb8, 0x98, 0xdd, 0xce, 0x27, 0x10, 0xdf, + 0x72, 0x3b, 0x3f, 0xc6, 0x10, 0x59, 0xf8, 0x83, 0xbb, 0xa1, 0xe4, 0x8a, 0x42, 0x97, 0xf5, 0x88, 0x14, 0xd9, 0xd3, + 0x35, 0x47, 0x10, 0x1c, 0x68, 0xd5, 0x20, 0x43, 0x23, 0xf1, 0xc5, 0x73, 0xc8, 0x1a, 0xac, 0xf9, 0xe7, 0x8a, 0x9c, + 0xd5, 0xfd, 0xc9, 0x06, 0xaa, 0x49, 0x26, 0x6b, 0x45, 0xe5, 0xfc, 0xf5, 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, 0xff, 0x15, 0xfc, 0x4b, 0x85, 0x2c, 0xd5, 0x69, 0x9d, 0x89, + 0x5f, 0x83, 0x25, 0xc3, 0x3f, 0x7e, 0x0b, 0xd6, 0x80, 0x25, 0x40, 0x96, 0xbb, 0x8d, 0x8d, 0xd6, 0x2b, 0xaf, 0x10, + 0x5f, 0x6a, 0x7d, 0xd1, 0x6f, 0xdd, 0x26, 0x6a, 0x05, 0x18, 0xa1, 0xd0, 0x22, 0xc0, 0x56, 0x0f, 0xdc, 0x53, 0xf0, + 0x03, 0x31, 0x9c, 0x6b, 0xd2, 0x9a, 0x3a, 0xe1, 0x75, 0x36, 0x8e, 0x44, 0x54, 0x6f, 0xe1, 0xe2, 0x5e, 0x6f, 0x2d, + 0xfe, 0x46, 0x05, 0x02, 0x20, 0x8b, 0x29, 0xd6, 0xce, 0x1b, 0xd2, 0x2b, 0xc3, 0x4e, 0x42, 0xef, 0x0d, 0x3b, 0x81, + 0xbc, 0x38, 0xec, 0x14, 0xba, 0x44, 0xdb, 0x29, 0x52, 0x13, 0x6d, 0x27, 0x2d, 0x56, 0x61, 0x09, 0xc1, 0xaf, 0xda, + 0x5b, 0x47, 0xd9, 0xbe, 0xc8, 0x12, 0xa6, 0x2d, 0x60, 0x94, 0x5b, 0xf5, 0x99, 0x53, 0xc4, 0x4a, 0xd9, 0x3b, 0x9d, + 0x54, 0xb9, 0x8b, 0x7c, 0x6a, 0x35, 0x45, 0x26, 0x7f, 0x7f, 0xdc, 0x22, 0xf9, 0xe4, 0xe7, 0x76, 0xc3, 0x64, 0xfa, + 0xc7, 0xa3, 0x2f, 0xa0, 0x2b, 0xb2, 0xd3, 0x27, 0x10, 0x90, 0xa9, 0xa0, 0x5a, 0xdd, 0x2a, 0xa6, 0x79, 0xbb, 0xca, + 0x6e, 0x2f, 0x94, 0x18, 0x4e, 0x67, 0x27, 0xe1, 0xd1, 0x66, 0xc8, 0xc0, 0x21, 0x08, 0x14, 0x42, 0x45, 0x31, 0x3c, + 0x02, 0xb5, 0x46, 0xf2, 0x01, 0x7e, 0xb4, 0x3b, 0x15, 0x44, 0x6a, 0x37, 0x15, 0x37, 0x4e, 0x6e, 0xba, 0x5e, 0x0a, + 0xd4, 0x3a, 0x25, 0x2b, 0x80, 0x12, 0xa2, 0xfe, 0x24, 0xb6, 0xf5, 0x2b, 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, 0x75, 0xbb, 0xe9, 0x98, 0xd8, 0xea, 0x9f, 0x45, 0xb5, 0xb9, 0x83, 0x8a, 0x88, 0xf8, 0x28, 0xbb, 0x79, 0xd2, + 0x7e, 0x07, 0x7b, 0xac, 0xd5, 0x20, 0xb2, 0xcf, 0xe0, 0x2a, 0xd7, 0x69, 0x91, 0xdb, 0x32, 0x38, 0xff, 0xf0, 0x6a, + 0x57, 0x61, 0x93, 0x63, 0x5d, 0x5d, 0xcd, 0x54, 0x27, 0x15, 0x1b, 0x18, 0x6b, 0x5a, 0x4b, 0x35, 0x8f, 0x21, 0xe9, + 0xae, 0x2c, 0xce, 0xaa, 0xa4, 0x9b, 0x9e, 0x1b, 0x67, 0x0a, 0x31, 0x70, 0xb6, 0x1a, 0x2d, 0x67, 0x18, 0xa2, 0xeb, + 0xc3, 0x2c, 0xf1, 0x5b, 0x3d, 0xe5, 0x3e, 0x0f, 0xb7, 0x7e, 0x57, 0x2f, 0x38, 0x99, 0xec, 0x27, 0xc7, 0xb9, 0xdb, + 0x45, 0xda, 0x4f, 0x7c, 0x1b, 0xe6, 0x5f, 0xdf, 0x20, 0xee, 0x44, 0xfd, 0xcf, 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, 0x7f, 0x7a, 0x35, 0x3b, 0x15, 0x54, 0x06, 0x6e, 0xc6, 0x7f, 0x7a, 0x82, 0x9d, 0xc2, 0x5a, + 0x01, 0x59, 0xe1, 0x4f, 0x2f, 0x7f, 0xe4, 0xfd, 0x8a, 0xff, 0xe9, 0x55, 0x8f, 0xbc, 0x8f, 0x38, 0x2f, 0x7f, 0x22, + 0xa9, 0x13, 0xa2, 0xba, 0xfc, 0x49, 0x98, 0x62, 0xab, 0x34, 0x7f, 0x4d, 0x0a, 0x9f, 0xe0, 0x33, 0xf0, 0x1d, 0xae, + 0xc2, 0xad, 0xf9, 0x0d, 0x1e, 0x3b, 0x16, 0xdb, 0x2e, 0xf5, 0x05, 0x94, 0x23, 0xb0, 0x88, 0xdc, 0x7e, 0xbb, 0xb2, + 0x5f, 0x2d, 0x8c, 0x32, 0xc6, 0xee, 0x4b, 0x56, 0xa2, 0x74, 0xd6, 0xef, 0x17, 0x52, 0x30, 0xb2, 0x0b, 0x6b, 0xb4, + 0x47, 0xa9, 0x7a, 0xf5, 0x3a, 0xac, 0xa3, 0x24, 0xcd, 0xef, 0x64, 0xf4, 0x91, 0x0c, 0x3b, 0xd2, 0x57, 0x52, 0xa2, + 0xbd, 0x56, 0x61, 0x39, 0x9a, 0xfd, 0xba, 0xe4, 0x40, 0x79, 0xdd, 0x0a, 0xca, 0x57, 0x4d, 0x00, 0xbd, 0x52, 0xed, + 0x33, 0xd0, 0x0a, 0x0a, 0x4b, 0xe5, 0xc1, 0x4a, 0x9c, 0x8b, 0x3e, 0x2b, 0x0e, 0x07, 0x75, 0x31, 0x24, 0x14, 0xa8, + 0x12, 0x27, 0xa1, 0x11, 0xcf, 0xe1, 0x42, 0x28, 0x5e, 0xe4, 0x18, 0x5b, 0x91, 0x03, 0x07, 0x32, 0xfc, 0x80, 0xc0, + 0x7b, 0xd9, 0xbf, 0x82, 0xc1, 0x30, 0xc1, 0x8d, 0x8c, 0x3a, 0x39, 0x67, 0x7f, 0x62, 0x60, 0x06, 0xf5, 0xa4, 0x76, + 0x9f, 0xdd, 0xab, 0xc0, 0x5e, 0x38, 0x03, 0xda, 0xbb, 0x31, 0xfa, 0x59, 0x15, 0x6b, 0x27, 0xfd, 0x53, 0xb1, 0x86, + 0x64, 0x3a, 0x2c, 0x8e, 0xb6, 0x69, 0x78, 0x24, 0x4f, 0x8e, 0xe3, 0x4d, 0xff, 0x70, 0x18, 0xe3, 0xc7, 0x51, 0x7e, + 0x6d, 0x01, 0xaf, 0xe2, 0x16, 0xd2, 0x58, 0xa4, 0xe8, 0x1d, 0x88, 0x39, 0x14, 0xbd, 0x64, 0xbf, 0x65, 0xbc, 0x9c, + 0x08, 0x4a, 0x49, 0x62, 0xc3, 0x3b, 0xd2, 0xd3, 0xb4, 0x1e, 0x6d, 0x65, 0xc0, 0x7e, 0x3d, 0xda, 0xd1, 0x5f, 0xa0, + 0x78, 0xb4, 0xf0, 0x97, 0xf4, 0x77, 0x71, 0x37, 0xf7, 0x9c, 0x6f, 0x1a, 0xdf, 0x11, 0x17, 0x28, 0xd6, 0xec, 0xfe, + 0x9a, 0x96, 0xce, 0x3a, 0x10, 0x1c, 0xf0, 0x16, 0xbb, 0x68, 0xdf, 0x6f, 0x5c, 0xa7, 0xa7, 0xfd, 0xb7, 0x6e, 0x8d, + 0xf2, 0xbd, 0x7f, 0x4a, 0x94, 0x83, 0xfd, 0x6b, 0x17, 0xcd, 0xdf, 0x7e, 0xca, 0x90, 0x54, 0x68, 0x6e, 0xb0, 0x9d, + 0x6c, 0x11, 0xd6, 0xc6, 0x38, 0xa8, 0xd8, 0x5d, 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, 0x5f, 0x11, 0x3e, 0xd4, 0x4e, 0x4a, 0x87, 0xf2, 0x57, 0xcf, 0xd9, + 0xff, 0xec, 0xb0, 0xa6, 0xa6, 0xdc, 0x00, 0x66, 0xce, 0x4a, 0xe4, 0x15, 0x42, 0xa7, 0xc8, 0xef, 0x55, 0x5d, 0x89, + 0xe1, 0xb2, 0x16, 0x65, 0x67, 0x76, 0xeb, 0x44, 0xef, 0x9c, 0x82, 0x5a, 0x2a, 0x1b, 0xe4, 0x24, 0xd5, 0xe6, 0x23, + 0x6b, 0x05, 0x25, 0xea, 0x1a, 0x05, 0x8e, 0x4f, 0xb9, 0x76, 0xff, 0xef, 0x9c, 0x09, 0x6a, 0xb6, 0x51, 0xdd, 0x5f, + 0xeb, 0xa7, 0xaa, 0x26, 0xb1, 0x00, 0x97, 0x93, 0x34, 0xef, 0x78, 0x84, 0xd5, 0x3f, 0x4e, 0x96, 0x22, 0xd0, 0xeb, + 0x88, 0x76, 0x25, 0x20, 0x41, 0x3b, 0x39, 0x0b, 0x15, 0x81, 0x02, 0x7d, 0xfd, 0xfb, 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, 0x0a, 0xb9, 0x41, 0x44, 0xd3, 0xef, 0x25, 0xaa, 0x1d, + 0x29, 0x90, 0x43, 0xc9, 0x4f, 0x88, 0xbf, 0x64, 0x6d, 0x8c, 0xfb, 0xa5, 0x53, 0xed, 0x57, 0x0a, 0xc1, 0xfd, 0x67, + 0x5b, 0x6c, 0x54, 0x79, 0xa2, 0x47, 0x9f, 0x62, 0xfd, 0x4f, 0x16, 0x50, 0xaa, 0xfb, 0x36, 0x38, 0x15, 0x8f, 0xc2, + 0x4d, 0x5d, 0xdc, 0x20, 0xb4, 0x40, 0x39, 0xaa, 0x8a, 0x4d, 0x19, 0x11, 0x27, 0xec, 0xa6, 0x2e, 0x7a, 0x9a, 0x03, + 0x9d, 0x3a, 0x2c, 0x4d, 0xe4, 0x89, 0xd0, 0x6e, 0x41, 0xf7, 0x34, 0xc7, 0x4a, 0xbc, 0x94, 0xa5, 0x83, 0xac, 0x13, + 0x69, 0x42, 0xe5, 0xae, 0xae, 0x3a, 0x2a, 0x95, 0xba, 0xe1, 0x4d, 0xaa, 0x19, 0x7f, 0x97, 0xe6, 0x4f, 0x2c, 0xfb, + 0x4d, 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, 0xb1, 0x28, 0xfe, 0xa8, 0xf4, 0x1d, 0x81, 0x8e, 0xee, 0xbc, 0xa8, 0xd3, 0xe5, 0xee, 0x03, 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, 0xbc, 0xc2, 0xfd, 0xa5, 0x22, 0x17, 0xfb, 0xce, 0x19, + 0xdd, 0x99, 0x59, 0xf7, 0xaa, 0xc2, 0xd5, 0x82, 0x5c, 0x1d, 0xd8, 0x5a, 0x76, 0x71, 0xb8, 0x61, 0x11, 0x05, 0x08, + 0xc4, 0xf4, 0x4a, 0xad, 0xfd, 0x11, 0x0d, 0x42, 0x3e, 0x18, 0xf8, 0x05, 0x06, 0xab, 0x02, 0x85, 0x0f, 0x14, 0xc9, + 0x5f, 0x7b, 0x02, 0x76, 0xf1, 0x0c, 0xd0, 0xad, 0xd8, 0xac, 0x18, 0x21, 0x42, 0x26, 0xcb, 0x59, 0x4d, 0x67, 0x90, + 0x4f, 0x7d, 0xf1, 0x8d, 0xad, 0x3a, 0x9d, 0xb7, 0x35, 0x55, 0x4e, 0x1d, 0x0a, 0xdd, 0xdd, 0xd4, 0x9d, 0x5b, 0x17, + 0x79, 0xea, 0x10, 0x72, 0xa5, 0x62, 0x25, 0xa6, 0xa1, 0xe6, 0x49, 0x9a, 0x51, 0x7f, 0xb1, 0xf7, 0x7b, 0x8d, 0xc2, + 0x29, 0x7f, 0x3a, 0x06, 0x55, 0xb8, 0xaa, 0x21, 0x8e, 0xa5, 0x2a, 0x1e, 0xd9, 0x20, 0xd0, 0xbc, 0xba, 0x55, 0x49, + 0x13, 0x32, 0xb9, 0x11, 0x3e, 0x35, 0x29, 0xe5, 0x69, 0xda, 0xa4, 0x95, 0x22, 0x75, 0xf0, 0x41, 0x9d, 0x6a, 0x3c, + 0x37, 0xab, 0x17, 0x00, 0x66, 0x9c, 0x5f, 0xf1, 0x4b, 0xc5, 0x65, 0xd4, 0x56, 0x66, 0xd2, 0xfe, 0xe4, 0x68, 0x6c, + 0xd4, 0xe5, 0xb4, 0x51, 0x46, 0x58, 0x29, 0xcd, 0x49, 0xb1, 0x1c, 0xcf, 0x3f, 0x60, 0xb0, 0xe6, 0x09, 0xec, 0x60, + 0xa2, 0x52, 0xde, 0x47, 0x40, 0x7c, 0x9d, 0xa4, 0x77, 0x09, 0xa4, 0x48, 0xff, 0xd2, 0x25, 0x77, 0x19, 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, 0xbe, 0x08, 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, 0xac, 0x3c, 0xe8, 0xff, 0x3a, 0x13, 0x96, 0xda, 0x4f, 0x4f, 0x07, 0x50, 0xc1, 0xfb, 0x8a, 0xb7, 0x11, 0xf1, + 0x7d, 0xe2, 0x67, 0xf1, 0x60, 0xf3, 0x6c, 0x03, 0xd6, 0xba, 0x27, 0xb9, 0xb1, 0xae, 0x12, 0x36, 0x10, 0xf0, 0x35, + 0x8a, 0xda, 0xf3, 0xda, 0xed, 0x1e, 0xfc, 0xd5, 0xbf, 0x08, 0x19, 0x30, 0x71, 0xfa, 0x3e, 0x73, 0xb2, 0x46, 0x17, + 0x99, 0x4c, 0x1f, 0x3a, 0xe9, 0x1b, 0x9d, 0xee, 0x3b, 0xe1, 0x1f, 0x15, 0xb3, 0xf8, 0x70, 0x4b, 0x5f, 0x69, 0x52, + 0xdc, 0x01, 0x2b, 0x9b, 0x47, 0x05, 0xa1, 0xce, 0x45, 0xf4, 0x95, 0x29, 0xdf, 0x12, 0x6a, 0xf6, 0x8d, 0x25, 0xa5, + 0x74, 0xaf, 0xa1, 0x37, 0x69, 0xad, 0xdf, 0x46, 0x09, 0xc6, 0x44, 0xc7, 0x93, 0x97, 0xf1, 0x58, 0x79, 0x1f, 0x8f, + 0x1b, 0xa9, 0x90, 0x07, 0x20, 0x02, 0x15, 0xe3, 0x4f, 0x57, 0x9e, 0x9c, 0xf4, 0xc2, 0x78, 0x15, 0x4a, 0x41, 0x61, + 0x40, 0x57, 0x20, 0x05, 0x3c, 0x6a, 0x4f, 0x74, 0x16, 0x76, 0x09, 0xf7, 0xe8, 0x26, 0x60, 0xac, 0xcf, 0x3f, 0x02, + 0x9a, 0xbb, 0x70, 0x87, 0x17, 0x03, 0xd4, 0xa6, 0x5e, 0xdd, 0x7d, 0x5c, 0xab, 0x73, 0x38, 0x04, 0x07, 0xab, 0x41, + 0x04, 0xa7, 0xf3, 0xa9, 0xa3, 0x59, 0x16, 0xa0, 0x72, 0xb2, 0xdc, 0xc8, 0x9b, 0x47, 0x8b, 0x5e, 0xdd, 0xf7, 0x96, + 0x69, 0x59, 0xd5, 0x41, 0xc6, 0xb2, 0xb0, 0x02, 0x5c, 0x1d, 0x5a, 0x3f, 0x08, 0x97, 0x85, 0xf3, 0x07, 0x42, 0x10, + 0xbb, 0x57, 0xdb, 0x92, 0xe7, 0x6a, 0x0e, 0x3f, 0x7b, 0xce, 0xd6, 0x5c, 0xa2, 0x4e, 0x3a, 0x13, 0x01, 0x88, 0x3d, + 0x35, 0xab, 0xe8, 0x1a, 0x48, 0xea, 0x34, 0xab, 0xe8, 0x9a, 0x9a, 0x6d, 0x8c, 0x03, 0xf9, 0x68, 0x95, 0x02, 0xf6, + 0xdd, 0x74, 0x1c, 0xac, 0x9e, 0xc5, 0xf2, 0x3a, 0x74, 0xf7, 0x6c, 0xa3, 0x7c, 0x06, 0x75, 0xab, 0x8d, 0x31, 0xb1, + 0xdd, 0x7c, 0x39, 0xd7, 0x6f, 0x07, 0x4b, 0xdf, 0x0e, 0x9a, 0x73, 0xca, 0xbe, 0xd3, 0x65, 0xaf, 0xec, 0xb2, 0xa9, + 0xe7, 0x8e, 0x8a, 0x56, 0x63, 0x40, 0x6f, 0x60, 0xc1, 0xfa, 0x5c, 0xa4, 0xd9, 0xaa, 0x54, 0x25, 0xe0, 0x85, 0xb1, + 0x62, 0x77, 0x7e, 0x23, 0x33, 0x24, 0x61, 0x1e, 0x67, 0xe2, 0x9a, 0xee, 0xb5, 0x30, 0x39, 0x8e, 0x45, 0x32, 0x25, + 0x74, 0x4a, 0x77, 0xb6, 0xa1, 0x73, 0x15, 0x46, 0x11, 0xad, 0x95, 0x54, 0x1a, 0x09, 0x4c, 0xcd, 0x00, 0x25, 0x73, + 0x05, 0x4e, 0xe9, 0x72, 0xff, 0x3b, 0x12, 0xe3, 0xcc, 0x17, 0x25, 0x33, 0xa0, 0x5b, 0x7e, 0x5d, 0xac, 0x5b, 0x29, + 0x32, 0xc2, 0xbc, 0x39, 0x6e, 0xaf, 0xeb, 0x43, 0x20, 0x57, 0xcb, 0x1e, 0x45, 0xe3, 0xa0, 0xd0, 0xe1, 0x52, 0x25, + 0xc0, 0xbe, 0x48, 0xfc, 0x8c, 0xb0, 0xa5, 0x3d, 0x90, 0xdb, 0xa3, 0x33, 0x61, 0xce, 0x39, 0x29, 0xcb, 0xce, 0xa5, + 0x19, 0x5c, 0x4e, 0x5c, 0x09, 0x2e, 0xd2, 0xdb, 0xf6, 0x34, 0x69, 0x69, 0xfb, 0xd8, 0x70, 0x8e, 0x86, 0xb6, 0x41, + 0x77, 0xec, 0x0f, 0xcd, 0xc5, 0x22, 0xb6, 0x2e, 0x16, 0xc3, 0xce, 0xec, 0x47, 0x8b, 0x05, 0xc8, 0x01, 0xe0, 0xa8, + 0xdb, 0xf0, 0x31, 0x5b, 0x02, 0xa7, 0xd5, 0x34, 0x9b, 0x7a, 0x1b, 0x5e, 0x3d, 0x53, 0x3d, 0xbd, 0xe4, 0xf9, 0x33, + 0x61, 0xc6, 0x62, 0xc3, 0xf3, 0x67, 0xd6, 0x91, 0x53, 0x3d, 0x13, 0x4a, 0xb4, 0x2e, 0xa0, 0x19, 0x78, 0x4d, 0x01, + 0x23, 0x96, 0x4c, 0xa6, 0x54, 0x91, 0xc7, 0xbd, 0xe9, 0x46, 0x0d, 0x5e, 0x50, 0x38, 0x04, 0x52, 0x3a, 0xfd, 0xe2, + 0x39, 0xd3, 0xef, 0x5d, 0x3c, 0xef, 0x90, 0xb5, 0x0d, 0xd3, 0xe5, 0x66, 0x98, 0x0c, 0x4a, 0xff, 0x99, 0x99, 0x18, + 0x17, 0xd6, 0x24, 0x01, 0xc4, 0xbf, 0xb1, 0xdf, 0x21, 0x85, 0x9b, 0xf7, 0x97, 0xc3, 0xf8, 0x91, 0xf7, 0x63, 0x64, + 0x4f, 0xd2, 0x0c, 0xb1, 0x66, 0x52, 0x21, 0x77, 0x5f, 0xad, 0x7f, 0x4c, 0xec, 0x26, 0x7b, 0x60, 0x01, 0x88, 0xad, + 0x69, 0xab, 0x5b, 0xde, 0xef, 0x7b, 0xa6, 0x08, 0xf0, 0x83, 0xf2, 0x8f, 0xee, 0x0c, 0xc9, 0xa0, 0xec, 0xba, 0x21, + 0xc4, 0x83, 0xb2, 0x69, 0xda, 0xeb, 0x6d, 0xef, 0xcc, 0x63, 0x75, 0x9d, 0x76, 0x16, 0x57, 0x8b, 0x0c, 0xd2, 0xea, + 0x43, 0x76, 0x9c, 0xd9, 0x67, 0x47, 0x4b, 0xa5, 0xfb, 0x7d, 0x88, 0x88, 0x3b, 0xca, 0xda, 0x7e, 0xbb, 0x05, 0xd7, + 0x70, 0x34, 0x08, 0x5d, 0xd9, 0xdb, 0x65, 0xb4, 0x71, 0x21, 0x8e, 0x7b, 0xa6, 0xf3, 0x05, 0x5f, 0x1e, 0xa5, 0x9d, + 0x07, 0xa7, 0x7a, 0xa2, 0xcf, 0x4d, 0x77, 0x95, 0xc9, 0xb5, 0x0e, 0xab, 0x31, 0xa8, 0xcd, 0xc2, 0x16, 0xee, 0xc2, + 0x36, 0x3a, 0x68, 0xed, 0xcb, 0x82, 0x7f, 0xca, 0x00, 0x7c, 0xe9, 0xd9, 0xb2, 0xed, 0x35, 0x69, 0xf5, 0x46, 0x46, + 0x21, 0xb6, 0xb4, 0xbd, 0xfa, 0x74, 0x94, 0x8f, 0x9b, 0x13, 0x8a, 0x0b, 0x39, 0xca, 0x8f, 0x5e, 0x43, 0xd4, 0xb5, + 0xae, 0xe3, 0x62, 0xd1, 0xe1, 0xc6, 0x55, 0xb7, 0xdd, 0xb8, 0x7e, 0x40, 0xbc, 0x35, 0xda, 0xa4, 0x50, 0x2b, 0x63, + 0x47, 0xf0, 0xb2, 0x7c, 0x38, 0x64, 0x62, 0x38, 0x94, 0x90, 0xa9, 0x8f, 0xdd, 0x1b, 0x9a, 0xf6, 0xf9, 0x69, 0xeb, + 0x47, 0x2c, 0x35, 0x8e, 0x62, 0xc3, 0x3b, 0x7d, 0xe7, 0xb1, 0x35, 0xae, 0xe4, 0xcb, 0x60, 0xb6, 0x2b, 0xa8, 0xb6, + 0xc6, 0x1b, 0xf6, 0x72, 0xfe, 0x7d, 0x25, 0x95, 0xfc, 0xed, 0xcf, 0x70, 0x0d, 0x6f, 0x6d, 0xe9, 0xa0, 0xa9, 0x66, + 0x39, 0xcb, 0xf5, 0xbd, 0xe0, 0xf8, 0xe3, 0xee, 0x15, 0xc1, 0xe0, 0xf7, 0x74, 0x14, 0xe4, 0x62, 0xa9, 0xd6, 0x80, + 0x82, 0x74, 0x64, 0xc7, 0x54, 0x16, 0x18, 0x06, 0xf0, 0x86, 0x0c, 0x90, 0xc7, 0x14, 0xee, 0x86, 0x0a, 0x2f, 0xfc, + 0xa5, 0x22, 0xbb, 0x04, 0xb6, 0x35, 0xe3, 0x63, 0x86, 0x3b, 0x08, 0xf9, 0x47, 0xb0, 0x3b, 0xb6, 0x62, 0xb7, 0x6c, + 0xc1, 0x90, 0x6c, 0x1c, 0x87, 0x31, 0xe6, 0xe3, 0x49, 0x7c, 0x25, 0x26, 0xf1, 0x80, 0x47, 0xe8, 0x18, 0xb1, 0xe6, + 0xf5, 0x2c, 0x96, 0x03, 0xc8, 0xee, 0xb8, 0xd2, 0x01, 0x21, 0x34, 0x36, 0xb4, 0xe4, 0x4d, 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, 0xdd, 0x45, 0x88, 0xf4, 0xb6, 0xe0, 0x77, 0x96, 0xa7, 0x0b, 0xbb, 0xe7, 0xd7, + 0x7c, 0xcc, 0xce, 0x7f, 0xf0, 0x20, 0x72, 0xf6, 0xfc, 0x23, 0xa0, 0x21, 0xde, 0xf3, 0xdb, 0xd4, 0xab, 0xd8, 0x2d, + 0x51, 0x10, 0xde, 0x82, 0x33, 0xd0, 0x3d, 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, 0xff, 0xc1, 0xdb, 0x51, 0xb9, 0xf0, 0x9f, 0xd7, 0x59, 0xf2, 0xce, 0x67, 0xd7, 0x03, 0xbe, 0x00, 0xbc, 0x25, + 0x74, 0xe0, 0xba, 0xf7, 0x99, 0xc4, 0x6b, 0xbb, 0xd6, 0xd7, 0x08, 0x24, 0xf2, 0x05, 0x60, 0xc4, 0xc4, 0xfc, 0xbe, + 0x86, 0x08, 0x8c, 0x04, 0x7c, 0x5b, 0xb5, 0x47, 0xfc, 0x96, 0x1b, 0xc0, 0xaf, 0xcc, 0x67, 0x0f, 0x3c, 0xd4, 0x3f, + 0x13, 0x9f, 0xdd, 0xf0, 0xf7, 0xfc, 0x85, 0x27, 0x25, 0xe9, 0x72, 0xf6, 0x7e, 0x0e, 0xd7, 0x43, 0x29, 0x4f, 0x87, + 0xf4, 0xb3, 0x31, 0x18, 0x40, 0x28, 0x64, 0xde, 0x78, 0xc0, 0x9a, 0x14, 0xe2, 0x5f, 0xc0, 0xb7, 0xa3, 0x84, 0xcd, + 0x1b, 0x6f, 0xeb, 0x6b, 0x79, 0xf3, 0xc6, 0x7b, 0xf0, 0x29, 0x0a, 0xb0, 0x0a, 0x4a, 0x59, 0x60, 0x15, 0x84, 0x8d, + 0x36, 0xc2, 0x18, 0xb8, 0x7a, 0xd7, 0x18, 0xea, 0x7a, 0x8e, 0xd8, 0xb6, 0xd2, 0x77, 0xe1, 0x3b, 0xc8, 0x80, 0x0f, + 0xde, 0x14, 0x25, 0xd1, 0xe7, 0xd4, 0x14, 0x49, 0xeb, 0x9e, 0xfb, 0xad, 0x75, 0x47, 0x6b, 0x4a, 0x7d, 0xe4, 0x6a, + 0x7c, 0x38, 0xd4, 0x2f, 0x84, 0x16, 0x09, 0xa6, 0xa0, 0x71, 0x0d, 0xda, 0x02, 0x04, 0x7d, 0x1e, 0x20, 0x6b, 0x49, + 0xb1, 0xe0, 0xdb, 0x5f, 0x21, 0x06, 0xaf, 0x4c, 0xef, 0x5c, 0xae, 0x32, 0x12, 0xb6, 0x17, 0x7e, 0x39, 0xac, 0xfd, + 0x89, 0x53, 0x0b, 0x4b, 0xab, 0x39, 0xa8, 0x9f, 0xd9, 0x72, 0x9c, 0xaa, 0xda, 0xbf, 0x25, 0x49, 0xb5, 0xab, 0xb4, + 0x9c, 0xde, 0xdb, 0x37, 0x5d, 0x26, 0xd8, 0xd8, 0x0f, 0xa8, 0x3a, 0xb2, 0x1a, 0x76, 0x5f, 0xa8, 0x2f, 0x7a, 0x4a, + 0x26, 0x34, 0x1f, 0x55, 0x34, 0xcf, 0xee, 0x37, 0x3b, 0xea, 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, 0x17, 0xe3, 0x69, 0x4d, 0x2c, 0xa9, 0x5d, 0x81, 0x31, 0x7a, 0x5c, 0x15, 0xb5, 0x4f, 0xfd, 0x02, 0x42, 0x91, + 0x6a, 0xcd, 0x1c, 0x6b, 0xdc, 0x18, 0x11, 0x77, 0x58, 0xb9, 0x76, 0x6a, 0xaf, 0x03, 0xb0, 0xbc, 0x1a, 0x17, 0x84, + 0x4d, 0x72, 0xec, 0x5c, 0xc0, 0x6a, 0x34, 0xa4, 0xda, 0x0d, 0xb7, 0x5e, 0x76, 0x7e, 0xf3, 0x38, 0xb1, 0xb5, 0x11, + 0x6e, 0x29, 0xa0, 0x8c, 0xf2, 0x1b, 0xcb, 0x09, 0xbb, 0x53, 0xbd, 0x23, 0x55, 0x3b, 0xe2, 0xc4, 0x05, 0x2c, 0x37, + 0x3c, 0xb5, 0xfa, 0x26, 0x06, 0x27, 0x42, 0xd5, 0x4a, 0xc7, 0x6b, 0x3f, 0xe2, 0x7e, 0x75, 0x5f, 0xf7, 0x4a, 0xf0, + 0x93, 0x90, 0xd7, 0x6f, 0x79, 0x07, 0x80, 0x15, 0x1f, 0xf2, 0x62, 0x5a, 0x38, 0x5a, 0x97, 0x41, 0x19, 0x20, 0x42, + 0x33, 0x00, 0x3a, 0xb9, 0x3a, 0x88, 0xd2, 0xc0, 0x15, 0x77, 0x88, 0xf0, 0xd3, 0xe8, 0x59, 0xfe, 0x22, 0x7c, 0x56, + 0x4d, 0xc3, 0x8b, 0x3c, 0x88, 0x2e, 0xaa, 0x20, 0x7a, 0x56, 0x5d, 0x85, 0xcf, 0xf2, 0x69, 0x74, 0x91, 0x07, 0xe1, + 0x45, 0xd5, 0xd8, 0x77, 0xed, 0xee, 0x9e, 0x90, 0xb7, 0x5d, 0xfd, 0x91, 0x73, 0x65, 0x4f, 0x99, 0x9e, 0x9f, 0xd7, + 0x7a, 0xa5, 0x76, 0x9b, 0xeb, 0x35, 0x6a, 0xa6, 0x3e, 0xca, 0xfe, 0x66, 0x1b, 0x0b, 0x8f, 0xe6, 0x10, 0xfa, 0x8c, + 0xb4, 0x98, 0x7b, 0x9c, 0xeb, 0xcd, 0x9e, 0x14, 0x06, 0x46, 0x4c, 0x2a, 0x19, 0x39, 0xbd, 0xc0, 0x45, 0xa8, 0x42, + 0x0c, 0x6b, 0xe9, 0x6a, 0x9f, 0x75, 0xe9, 0x0d, 0xd4, 0x35, 0xc5, 0xbe, 0x86, 0x0c, 0xbc, 0x68, 0x7a, 0x19, 0x8c, + 0x01, 0x39, 0x02, 0xef, 0xf8, 0x6c, 0x09, 0x07, 0xe6, 0x1a, 0xa0, 0x6f, 0x1e, 0xf5, 0x75, 0xb9, 0xe3, 0x6b, 0xd5, + 0x37, 0xd3, 0xf5, 0x48, 0x29, 0x3f, 0x56, 0xfc, 0xee, 0xe2, 0x39, 0xbb, 0xe5, 0x1a, 0x15, 0xe5, 0x17, 0xbd, 0x58, + 0xef, 0x81, 0xab, 0xee, 0x17, 0xb8, 0xcd, 0xe2, 0xb1, 0x2b, 0x0f, 0x58, 0xb6, 0x65, 0x0f, 0xec, 0x86, 0xbd, 0x67, + 0x4f, 0xd8, 0x5b, 0xf6, 0x8e, 0xfd, 0x84, 0xaa, 0x0d, 0x25, 0xe4, 0xf9, 0x0b, 0x7e, 0x2b, 0x4d, 0x8f, 0x12, 0x95, + 0xec, 0xc1, 0x36, 0xd3, 0x0c, 0x37, 0xec, 0x3d, 0x5f, 0x0c, 0x57, 0xec, 0x2d, 0x64, 0x43, 0x99, 0x78, 0xb0, 0x62, + 0x3f, 0x71, 0x05, 0x62, 0xa6, 0xcf, 0xc2, 0xd2, 0x12, 0x15, 0x4d, 0x99, 0x28, 0x43, 0xbf, 0xe5, 0xf8, 0x22, 0xfb, + 0x09, 0x8b, 0x90, 0x9f, 0x19, 0xae, 0xd8, 0x03, 0x5f, 0x0c, 0x56, 0xec, 0xbd, 0x36, 0x10, 0x0d, 0x36, 0x6e, 0x69, + 0x84, 0x64, 0xa5, 0xcb, 0x92, 0xd2, 0xf4, 0xd6, 0xbe, 0x06, 0x6e, 0xd8, 0x0d, 0xd6, 0xee, 0x09, 0x16, 0x8d, 0x02, + 0xff, 0x60, 0xc5, 0xde, 0x71, 0x09, 0xa0, 0xe6, 0x96, 0x27, 0xbd, 0x42, 0x75, 0x81, 0x74, 0x3f, 0x78, 0xc2, 0xe9, + 0x45, 0xf6, 0x0e, 0xcb, 0xa0, 0xaf, 0x0c, 0x57, 0x6c, 0x8b, 0xb5, 0xbb, 0x31, 0x96, 0x2d, 0xab, 0x7a, 0x12, 0x11, + 0x18, 0x05, 0x95, 0xd2, 0xf2, 0x6f, 0xc4, 0xb2, 0xa9, 0x9b, 0x06, 0xb5, 0xa1, 0x3f, 0x1f, 0x8c, 0xfe, 0xe2, 0xeb, + 0x77, 0x3f, 0x78, 0xa5, 0xbe, 0xf6, 0xfe, 0xe2, 0xb8, 0x56, 0x96, 0xe8, 0x5a, 0xf9, 0x2b, 0x2f, 0x67, 0xbf, 0xcc, + 0x27, 0xba, 0x96, 0xb4, 0xc3, 0x90, 0xaf, 0xe9, 0xec, 0x97, 0x0e, 0x67, 0xcb, 0x5f, 0x7d, 0xbf, 0x31, 0x5d, 0xac, + 0x3e, 0xab, 0x7b, 0xf7, 0x61, 0xb0, 0x69, 0x9c, 0x7a, 0xef, 0x4e, 0xd7, 0x1b, 0x9b, 0x59, 0x6b, 0xcf, 0xcc, 0xff, + 0xe1, 0x4a, 0x6f, 0x71, 0xe8, 0x6e, 0xf8, 0x76, 0xb8, 0xb1, 0x47, 0x41, 0x7e, 0x5f, 0x2a, 0x8d, 0xb3, 0x9a, 0xbf, + 0xf4, 0x3a, 0xa5, 0x58, 0x40, 0x34, 0xfa, 0x64, 0x24, 0xa1, 0x4b, 0x66, 0xe2, 0x19, 0xe2, 0x8b, 0x0c, 0x90, 0xb9, + 0x40, 0x34, 0xbb, 0xe7, 0xe3, 0xc9, 0xfd, 0x55, 0x3c, 0xb9, 0x1f, 0xf0, 0x4f, 0xa6, 0x05, 0xed, 0xc5, 0x76, 0xef, + 0xb3, 0x5f, 0x79, 0x61, 0x2f, 0xc7, 0x5f, 0x7c, 0xf6, 0x45, 0xb8, 0x2b, 0xf4, 0x17, 0x9f, 0xbd, 0x13, 0xfc, 0xd7, + 0x91, 0x26, 0xca, 0x60, 0xef, 0x6a, 0xfe, 0xeb, 0x08, 0x19, 0x3f, 0xd8, 0x67, 0xc1, 0xbf, 0x80, 0xef, 0x77, 0x95, + 0xa0, 0x55, 0xfc, 0x73, 0xad, 0x7e, 0xbe, 0x97, 0x71, 0x39, 0xf0, 0x26, 0xb4, 0x82, 0xde, 0xbc, 0xad, 0xe5, 0x4f, + 0xe2, 0xe1, 0x48, 0xd5, 0x53, 0xc3, 0x3f, 0x8b, 0xc5, 0x2c, 0xea, 0xa3, 0x74, 0x2a, 0x6f, 0x72, 0xcd, 0x33, 0x69, + 0x5d, 0xbe, 0x87, 0x50, 0xe0, 0x6b, 0x1b, 0xa2, 0x60, 0xc7, 0x71, 0x23, 0xb8, 0x66, 0xef, 0x84, 0xcf, 0xb2, 0xe9, + 0x96, 0xdf, 0xf0, 0x27, 0xfc, 0x1d, 0xdf, 0x05, 0x0f, 0xfc, 0x3d, 0x7f, 0xcb, 0x7f, 0xe2, 0x3b, 0xb6, 0x94, 0x68, + 0xa7, 0xf5, 0xf6, 0x32, 0xd8, 0xb2, 0x7a, 0x77, 0x19, 0x3c, 0xb0, 0x7a, 0xfb, 0x3c, 0xb8, 0x61, 0xf5, 0xee, 0x79, + 0xf0, 0x9e, 0x6d, 0x2f, 0x83, 0x27, 0x6c, 0x77, 0x19, 0xbc, 0x65, 0xdb, 0xe7, 0xc1, 0x3b, 0xb6, 0x7b, 0x1e, 0xfc, + 0x24, 0x31, 0x1e, 0xde, 0x09, 0xc9, 0x71, 0xf2, 0xae, 0x66, 0x86, 0x4f, 0x37, 0xf8, 0x2c, 0xac, 0x5f, 0x54, 0xc7, + 0xe0, 0x73, 0xcd, 0x74, 0x8b, 0x03, 0x21, 0x98, 0x6e, 0x6f, 0x70, 0x4b, 0x4f, 0x4c, 0xab, 0x82, 0x54, 0xb0, 0xae, + 0x76, 0x06, 0x8b, 0xba, 0x69, 0x9d, 0xc9, 0x8e, 0x5f, 0x62, 0xdc, 0xe1, 0x97, 0xb8, 0x60, 0xcb, 0xa6, 0xd3, 0x49, + 0xe7, 0xf4, 0x49, 0xa0, 0x37, 0x7f, 0xbd, 0xeb, 0x57, 0xd2, 0x77, 0xa6, 0x68, 0x78, 0xae, 0xb4, 0xc6, 0xad, 0x9d, + 0x3e, 0xb4, 0x76, 0x7a, 0x26, 0x55, 0x68, 0x11, 0x8b, 0xca, 0xa2, 0xaa, 0x90, 0x49, 0x3c, 0xc8, 0xb4, 0x3e, 0x2d, + 0x61, 0xa4, 0xc8, 0x04, 0x34, 0xfa, 0x82, 0x8e, 0x81, 0x9c, 0x2c, 0x0a, 0x6c, 0xc9, 0x37, 0x83, 0x84, 0xad, 0x79, + 0x3c, 0x1d, 0x26, 0xc1, 0x92, 0xdd, 0xf1, 0x61, 0xb7, 0x40, 0xb0, 0x52, 0x01, 0x4c, 0xfa, 0xe2, 0xd4, 0xde, 0xd7, + 0x79, 0x6f, 0x95, 0xc6, 0x71, 0x26, 0x50, 0xd9, 0x56, 0xe9, 0x0d, 0x7e, 0xeb, 0xec, 0xe7, 0x6b, 0xb5, 0xbf, 0x83, + 0xa4, 0xf0, 0x2b, 0x30, 0xec, 0x10, 0xe1, 0x1d, 0x54, 0x18, 0x79, 0x96, 0xcc, 0xa2, 0xaf, 0xec, 0x2d, 0x7d, 0x6b, + 0xb6, 0xe9, 0xff, 0xb4, 0x08, 0xda, 0xc7, 0x65, 0xe7, 0x7f, 0x32, 0xaf, 0xfe, 0xd6, 0xf1, 0xea, 0xc6, 0x9f, 0x3c, + 0xf0, 0x4f, 0x18, 0x96, 0x80, 0x89, 0x6c, 0xc7, 0x3f, 0x8d, 0xb6, 0x8d, 0x53, 0x9e, 0xdc, 0xc7, 0xff, 0xaf, 0x14, + 0x68, 0xef, 0xe4, 0x95, 0xbd, 0x23, 0x6e, 0x79, 0xc7, 0x3e, 0xbe, 0xb4, 0x36, 0x44, 0x03, 0x4d, 0xf2, 0x89, 0xbb, + 0xd1, 0xd0, 0xb0, 0x21, 0xfe, 0xc2, 0xab, 0xd9, 0xa7, 0xf9, 0x64, 0xcb, 0x8f, 0xb7, 0xc3, 0x4f, 0x1d, 0xdb, 0xe1, + 0x2f, 0xfe, 0x60, 0xd9, 0x7c, 0xad, 0x57, 0x3b, 0xb7, 0x71, 0xa7, 0xd2, 0x3b, 0x7e, 0xbc, 0x89, 0x0f, 0xff, 0xe3, + 0x4a, 0xef, 0xbe, 0xb9, 0xd2, 0x76, 0x95, 0xbb, 0x3b, 0xdf, 0x74, 0x7c, 0x23, 0x6b, 0x8d, 0x71, 0x66, 0x46, 0xb3, 0xf8, 0x13, 0xcd, 0xd2, 0x20, 0xb2, 0x14, 0x8a, 0x3f, 0x99, 0x69, 0xa7, 0xee, 0x54, 0x59, 0xdd, 0x2d, 0xdf, 0xe2, - 0x1e, 0x7f, 0xc7, 0xc7, 0x6c, 0x61, 0x3c, 0x35, 0xef, 0x6e, 0x16, 0x93, 0xc1, 0xe0, 0xce, 0x3f, 0xdc, 0xf3, 0x70, - 0x76, 0x37, 0x67, 0x6f, 0xf9, 0x3d, 0x2d, 0xa6, 0x89, 0x6a, 0x7a, 0xf1, 0x98, 0xe0, 0x75, 0xe7, 0xfb, 0x13, 0x8b, - 0xff, 0xd5, 0xbe, 0x68, 0xde, 0xf9, 0x03, 0x69, 0x8d, 0x96, 0xbb, 0xfa, 0xfb, 0xc7, 0x15, 0x13, 0x77, 0x20, 0x5e, - 0xbc, 0xb7, 0x35, 0x0d, 0x6f, 0xf8, 0x47, 0xef, 0xad, 0x3f, 0x7d, 0xab, 0x63, 0x6e, 0x26, 0xea, 0x48, 0x7a, 0x73, - 0xf5, 0x8c, 0xfd, 0xca, 0x3f, 0xc9, 0xe3, 0xe4, 0x9d, 0x90, 0x93, 0xf6, 0x16, 0xb9, 0x9b, 0xe8, 0x94, 0xf8, 0xe2, - 0x26, 0x12, 0x16, 0x04, 0xc2, 0x70, 0xd4, 0xfc, 0x61, 0x52, 0x4e, 0xbd, 0x3d, 0x70, 0xbb, 0x72, 0x5b, 0xff, 0x7c, - 0xc7, 0x39, 0x5f, 0x0c, 0xaf, 0xa7, 0x5f, 0xba, 0x5d, 0x7a, 0x54, 0x34, 0x9b, 0x0a, 0x74, 0xbb, 0xc3, 0xd8, 0xab, - 0xb3, 0x99, 0x65, 0x2e, 0xf9, 0xd2, 0x97, 0xda, 0xcc, 0x3c, 0xa6, 0xf7, 0x9b, 0x69, 0x86, 0x44, 0xbe, 0x40, 0xc8, - 0x74, 0x3c, 0xae, 0x2e, 0xb1, 0x3c, 0x3e, 0x7c, 0xf3, 0xf4, 0xc9, 0xe0, 0x09, 0x46, 0x6e, 0x59, 0xd1, 0x20, 0x5f, - 0xf8, 0x30, 0xab, 0x5b, 0xb7, 0x8d, 0xab, 0x67, 0xc3, 0x5f, 0x20, 0x6f, 0xd0, 0xf5, 0xd0, 0x14, 0xd1, 0x2a, 0xbf, - 0xa3, 0xe8, 0x33, 0x25, 0x07, 0x1d, 0x4f, 0xa0, 0x76, 0x48, 0x81, 0xfb, 0xe5, 0x29, 0x07, 0xfd, 0x06, 0x96, 0xda, - 0xef, 0x5f, 0x7e, 0x22, 0x1e, 0x69, 0x18, 0xef, 0x1f, 0xc2, 0xe8, 0x8f, 0xb8, 0x2c, 0x36, 0x70, 0xba, 0x0e, 0xe0, - 0x73, 0x4f, 0xf5, 0xed, 0x6b, 0xe5, 0xfb, 0x7e, 0xe0, 0xed, 0xf8, 0x2d, 0xfb, 0xc2, 0xbd, 0xeb, 0xe1, 0x1b, 0xff, - 0xe9, 0x13, 0x10, 0x9d, 0x60, 0x5c, 0x3e, 0x63, 0x24, 0x6c, 0x47, 0x31, 0x6a, 0x15, 0x7e, 0xae, 0x21, 0x44, 0xeb, - 0x13, 0x32, 0x76, 0x41, 0xfa, 0x07, 0x05, 0xe8, 0x27, 0x04, 0x56, 0x93, 0xd4, 0x28, 0x30, 0x89, 0xef, 0x6a, 0x48, - 0x20, 0x05, 0x0b, 0x84, 0xde, 0x40, 0xf1, 0xa9, 0xe0, 0x5f, 0x86, 0x9f, 0x49, 0xf2, 0x5b, 0xd4, 0x7c, 0x0c, 0x7f, - 0xc3, 0xd0, 0x4c, 0xaa, 0x87, 0xb4, 0x8e, 0x12, 0xef, 0x27, 0xff, 0x10, 0x85, 0x95, 0x50, 0xc7, 0x42, 0x90, 0x8a, - 0x21, 0x17, 0xe2, 0xea, 0xd9, 0xe4, 0xae, 0x14, 0xe1, 0x1f, 0x13, 0x7c, 0x26, 0x17, 0x9a, 0x7c, 0x46, 0x4f, 0x1a, - 0xf9, 0xfe, 0x83, 0x7c, 0x5f, 0x76, 0x6a, 0xb0, 0xa8, 0x87, 0xfc, 0xae, 0x76, 0xdf, 0x97, 0x53, 0x82, 0x1e, 0xd9, - 0x0f, 0x68, 0x0a, 0x06, 0x6a, 0x02, 0x52, 0x86, 0xe0, 0x0e, 0xae, 0xfa, 0x9e, 0x2a, 0xc8, 0x97, 0xdf, 0xfb, 0x2c, - 0x64, 0xb8, 0xca, 0x82, 0x90, 0xe4, 0x52, 0x21, 0x85, 0x8d, 0xbb, 0x7a, 0xf0, 0x59, 0x63, 0x92, 0x48, 0xc8, 0x29, - 0x01, 0x49, 0xd2, 0xde, 0x40, 0x92, 0x88, 0xe9, 0x3f, 0x5c, 0x27, 0x4d, 0xb3, 0x96, 0xd2, 0x0d, 0x71, 0xaa, 0xbe, - 0x45, 0x9a, 0xb3, 0xe0, 0x3d, 0x83, 0xa5, 0x23, 0xc5, 0x8a, 0x2f, 0xc6, 0x60, 0xac, 0x83, 0x85, 0x56, 0xb2, 0xb8, - 0x5f, 0x25, 0x61, 0x1a, 0x89, 0x2a, 0xef, 0x84, 0xfc, 0xf9, 0x4f, 0x25, 0xfe, 0xe8, 0x2d, 0x0d, 0x44, 0x20, 0xf8, - 0x01, 0x5a, 0x0f, 0x58, 0xe3, 0xc1, 0x4f, 0xac, 0x2e, 0xc3, 0xbc, 0xca, 0xa8, 0xbc, 0xd9, 0x9e, 0xed, 0xe6, 0x4c, - 0x55, 0x2d, 0xf8, 0x2c, 0x0c, 0x2d, 0xda, 0xc5, 0xba, 0x39, 0xbb, 0xcd, 0x1b, 0x7c, 0x67, 0x92, 0x44, 0x6a, 0x29, - 0x89, 0xb4, 0xd5, 0xf5, 0xe9, 0xd2, 0xeb, 0x16, 0x15, 0x34, 0x46, 0x80, 0x5e, 0x92, 0xee, 0x2a, 0x9f, 0x50, 0xbc, - 0xb2, 0x1a, 0x56, 0xc3, 0x4b, 0x87, 0x22, 0x8c, 0xb5, 0x37, 0xe7, 0xf2, 0xec, 0x0e, 0xac, 0x47, 0x68, 0xed, 0xca, - 0xd5, 0x21, 0x6c, 0x3f, 0xd1, 0x7b, 0x4e, 0xae, 0xfe, 0x06, 0x54, 0x81, 0x73, 0x47, 0x43, 0x7d, 0xd2, 0x4e, 0x21, - 0xdb, 0x79, 0xb0, 0x24, 0xa8, 0x4a, 0xc9, 0x4d, 0xb9, 0x16, 0xa5, 0x94, 0x29, 0x5f, 0xcb, 0x6c, 0x65, 0xf7, 0xc9, - 0x00, 0xe2, 0xd9, 0xa0, 0x40, 0x72, 0x51, 0x5b, 0xcd, 0x41, 0xfa, 0x68, 0x96, 0x38, 0xd6, 0x0e, 0x0a, 0x2f, 0xcb, - 0xc1, 0xcc, 0x65, 0x2e, 0x97, 0x83, 0x82, 0x55, 0x7a, 0xab, 0x99, 0x66, 0xaa, 0x2f, 0x2a, 0x7b, 0x9b, 0xf1, 0x32, - 0xfd, 0x37, 0x4b, 0x06, 0x3c, 0xba, 0x7a, 0xe6, 0x07, 0x90, 0x26, 0x79, 0x1d, 0x20, 0x09, 0x36, 0x07, 0xbb, 0xd8, - 0x61, 0xd8, 0x2a, 0x56, 0xf6, 0xe4, 0xf9, 0x72, 0x87, 0xa6, 0x5c, 0xc2, 0x48, 0x4e, 0xcc, 0xa5, 0xd4, 0xf7, 0x25, - 0xd5, 0x0d, 0x05, 0x27, 0x9b, 0x26, 0xa0, 0x14, 0xd0, 0x6e, 0xc1, 0x7f, 0xe1, 0x53, 0x43, 0xa7, 0x05, 0x58, 0x6a, - 0xbb, 0x01, 0xff, 0x85, 0x7e, 0xb1, 0x7d, 0x44, 0xfd, 0xc0, 0x3c, 0x38, 0x98, 0xb5, 0x95, 0x31, 0x20, 0x22, 0x71, - 0x05, 0x79, 0x24, 0xf8, 0x41, 0xb1, 0xa7, 0xcb, 0xc4, 0x81, 0x33, 0xc5, 0xc5, 0x52, 0x6a, 0x33, 0xf3, 0xda, 0x6f, - 0xa9, 0x89, 0x37, 0x51, 0x12, 0x15, 0xb6, 0x43, 0x1a, 0xbd, 0xa4, 0x8c, 0xa9, 0x82, 0x0d, 0xd1, 0x7d, 0xdd, 0x04, - 0x53, 0xe0, 0x4d, 0x55, 0x05, 0x44, 0xa8, 0xbd, 0xc8, 0xf2, 0xfc, 0xa6, 0x0b, 0xac, 0x2e, 0xf8, 0xd4, 0x98, 0x66, - 0x17, 0xac, 0xe4, 0x6a, 0x26, 0x7d, 0xe6, 0xed, 0x40, 0x0b, 0x79, 0x97, 0x97, 0x45, 0x2b, 0x74, 0x3d, 0x88, 0x16, - 0xfe, 0x41, 0x73, 0x3c, 0x7a, 0xb6, 0xad, 0xa6, 0x36, 0xfb, 0x5a, 0x8b, 0x05, 0x32, 0x10, 0x0d, 0x7d, 0xa1, 0x62, - 0x14, 0xee, 0x2a, 0xcd, 0xd5, 0x6a, 0x5f, 0x95, 0x41, 0x02, 0x13, 0x41, 0xd6, 0xb2, 0xf0, 0x1e, 0xdd, 0xab, 0x47, - 0x9a, 0x57, 0x12, 0x3c, 0x73, 0xf1, 0x17, 0x00, 0x42, 0x79, 0x92, 0x90, 0x03, 0x72, 0x00, 0x7f, 0x4b, 0x51, 0x2a, - 0x0d, 0xf0, 0xcf, 0xea, 0x72, 0x6c, 0xeb, 0xfb, 0x3b, 0xad, 0x62, 0x70, 0xfd, 0xf9, 0xba, 0xeb, 0x59, 0x3b, 0xc4, - 0x39, 0xb7, 0xd5, 0x6b, 0xcb, 0x34, 0x8f, 0x91, 0xba, 0x06, 0xe0, 0x4e, 0xa4, 0x47, 0x20, 0x92, 0x99, 0x68, 0x90, - 0xb3, 0xe7, 0x7c, 0x3c, 0x15, 0x8f, 0x49, 0x7b, 0xb9, 0xef, 0x9b, 0x0b, 0x7d, 0x30, 0xc6, 0xbe, 0x05, 0x0d, 0xe2, - 0xa3, 0xd5, 0xd6, 0x0a, 0xc4, 0x7a, 0xa7, 0xd4, 0x87, 0x6e, 0x8c, 0x82, 0x0e, 0x1e, 0x71, 0x23, 0x17, 0x1c, 0xdb, - 0x5d, 0x5b, 0x4f, 0xe9, 0x2b, 0x00, 0x73, 0x1d, 0xa8, 0x64, 0x18, 0xa4, 0x2e, 0x13, 0x85, 0x49, 0x7e, 0x99, 0x90, - 0x84, 0x88, 0xea, 0x6c, 0x39, 0x4a, 0x95, 0x69, 0x01, 0x97, 0x19, 0x19, 0x60, 0x36, 0x69, 0xd6, 0x4f, 0x2e, 0x5f, - 0x62, 0x18, 0x01, 0xf1, 0x33, 0xfa, 0xb1, 0x56, 0x89, 0x97, 0x8c, 0xee, 0x1c, 0x75, 0x83, 0x2a, 0xc9, 0x5c, 0xbf, - 0xb9, 0x9d, 0x45, 0xca, 0xbc, 0x60, 0xb8, 0x5d, 0xa5, 0xf9, 0x87, 0xb0, 0x4e, 0xf0, 0xdb, 0x00, 0x95, 0xf4, 0xa9, - 0xf0, 0xa2, 0x11, 0x40, 0xa8, 0xef, 0x55, 0x19, 0x9f, 0x0a, 0x2f, 0x1b, 0xed, 0x58, 0x46, 0x29, 0x54, 0x17, 0xcc, - 0x6e, 0x4d, 0x17, 0xa2, 0x5b, 0x55, 0x03, 0x6d, 0xe0, 0xda, 0x15, 0x52, 0xba, 0x81, 0x6a, 0x57, 0x6e, 0x58, 0x80, - 0x68, 0x33, 0x11, 0x18, 0x2e, 0xff, 0x3e, 0x7f, 0xa9, 0x62, 0x78, 0xfa, 0xfd, 0xd0, 0x3b, 0xec, 0x82, 0x68, 0xb4, - 0xbb, 0x66, 0xfb, 0x20, 0x1a, 0xed, 0xaf, 0x1b, 0x46, 0xbf, 0x9f, 0xd1, 0xef, 0x67, 0x0d, 0xe8, 0x48, 0x84, 0x09, - 0xb3, 0xd7, 0x6f, 0xd4, 0xf2, 0x95, 0x5a, 0xbf, 0x53, 0xcb, 0x97, 0x6a, 0x78, 0xeb, 0x40, 0x12, 0x41, 0x64, 0xa9, - 0x6a, 0x1e, 0x24, 0x45, 0xaa, 0xa5, 0xcb, 0x31, 0x5a, 0x8c, 0xa8, 0xa5, 0xac, 0x39, 0xd5, 0x89, 0xb4, 0x73, 0x50, - 0x32, 0xc0, 0xd1, 0xe2, 0xaa, 0xc6, 0x74, 0xb3, 0xa2, 0x25, 0x10, 0x23, 0xac, 0x6c, 0xcb, 0xc5, 0x4d, 0xea, 0xa3, - 0x2b, 0xf2, 0x6d, 0xcb, 0x95, 0x6f, 0x5b, 0xc1, 0xab, 0xaf, 0x28, 0x94, 0x4b, 0xae, 0x95, 0xed, 0xd3, 0x42, 0x29, - 0x94, 0x71, 0x0d, 0xb6, 0xf6, 0x4d, 0x60, 0xc8, 0x7c, 0xa4, 0xa8, 0xb1, 0xbd, 0x68, 0x94, 0x43, 0x90, 0xad, 0x83, - 0x51, 0xa7, 0x2c, 0x58, 0x7c, 0xbb, 0x43, 0x06, 0x32, 0xd0, 0x51, 0xd5, 0xc6, 0xab, 0x9d, 0x95, 0xfe, 0xb0, 0xbc, - 0x7a, 0xc6, 0x12, 0x2b, 0x9d, 0xfc, 0xa6, 0x42, 0x7f, 0x10, 0xa2, 0x6f, 0xca, 0x96, 0x83, 0x17, 0x5d, 0x6c, 0x65, - 0x40, 0xbc, 0x61, 0x7a, 0x6f, 0x6b, 0x25, 0xcb, 0x5d, 0x53, 0xbe, 0x98, 0xf1, 0x84, 0xe3, 0xe8, 0xcb, 0xd5, 0x22, - 0xac, 0xd5, 0x22, 0x3b, 0x01, 0x1e, 0x5a, 0xab, 0xa5, 0x90, 0xab, 0x45, 0x38, 0x33, 0x5d, 0xa8, 0x99, 0x9e, 0x81, - 0xe6, 0x51, 0xa8, 0x59, 0x9e, 0x00, 0x16, 0xbc, 0x30, 0x33, 0x5c, 0x98, 0x19, 0x8e, 0x43, 0x6a, 0x9c, 0x1e, 0xf4, - 0x5e, 0xe7, 0x9e, 0x5b, 0xee, 0x46, 0xa7, 0x61, 0xde, 0x4e, 0x36, 0x98, 0xd3, 0x83, 0x70, 0x02, 0xf1, 0x81, 0x25, - 0x02, 0xf4, 0x68, 0x58, 0x1d, 0x35, 0x54, 0x8e, 0xe2, 0xcb, 0x02, 0x90, 0x2c, 0x09, 0x40, 0xf2, 0xa0, 0xc6, 0xb9, - 0xb4, 0xfc, 0xba, 0x4a, 0x42, 0x8e, 0xc8, 0x78, 0x29, 0xed, 0xee, 0x09, 0x2f, 0x47, 0x46, 0x68, 0x9e, 0x2c, 0x52, - 0xaf, 0x62, 0x19, 0x1b, 0x23, 0x70, 0x51, 0xe8, 0x37, 0x79, 0xbf, 0x9f, 0x96, 0x5e, 0x45, 0xed, 0xfc, 0x04, 0xfe, - 0x96, 0xe7, 0xce, 0x22, 0x47, 0xc8, 0xab, 0x91, 0x49, 0x58, 0x5e, 0x2a, 0xf5, 0xf4, 0x25, 0xcc, 0xa0, 0xee, 0xde, - 0x28, 0x00, 0xd7, 0x42, 0x39, 0xd5, 0x96, 0x70, 0x65, 0xaa, 0x0c, 0xf6, 0x79, 0xc8, 0x65, 0x68, 0x87, 0x44, 0x1e, - 0x29, 0xac, 0xfb, 0xf6, 0xd5, 0xb3, 0x89, 0xeb, 0xc3, 0x62, 0xa3, 0x11, 0x1c, 0x8f, 0x00, 0x73, 0x30, 0xf5, 0xa2, - 0x01, 0x2f, 0xd5, 0x9c, 0xf9, 0xe8, 0x55, 0x84, 0x8d, 0x01, 0x6a, 0x8a, 0x81, 0x53, 0xd6, 0x53, 0xf9, 0xc8, 0xf8, - 0x96, 0xf9, 0x7e, 0x80, 0xef, 0xd6, 0x85, 0x84, 0x7c, 0x50, 0xa8, 0x04, 0x99, 0x42, 0x25, 0x48, 0x0c, 0x2a, 0x41, - 0x6c, 0x50, 0x09, 0xb6, 0x0d, 0xdf, 0x48, 0xe5, 0x6d, 0x04, 0x1c, 0x11, 0x3e, 0xf4, 0x2c, 0x6c, 0xac, 0x50, 0x3c, - 0x1b, 0xb3, 0x31, 0x2b, 0xd4, 0xce, 0x53, 0xc9, 0xa9, 0xd8, 0x59, 0x8c, 0x75, 0x13, 0x59, 0x26, 0x5e, 0x48, 0xd0, - 0x71, 0xce, 0x85, 0x44, 0x5d, 0xfd, 0xdc, 0x7b, 0x49, 0xc6, 0x92, 0x79, 0x43, 0xa3, 0x06, 0xf3, 0xb2, 0xeb, 0x00, - 0xa6, 0x25, 0xdf, 0x16, 0x34, 0x98, 0x4e, 0x95, 0x47, 0xa4, 0x49, 0x50, 0x3b, 0x97, 0x49, 0x91, 0x13, 0xc2, 0x24, - 0xe8, 0x95, 0xe0, 0x37, 0x12, 0xda, 0xff, 0xab, 0x9e, 0xef, 0x80, 0xc1, 0x44, 0xab, 0xe4, 0x0b, 0x58, 0x2d, 0x2b, - 0xfe, 0x42, 0x7a, 0x62, 0x23, 0xfe, 0x62, 0x99, 0xc6, 0xa3, 0x2f, 0x6c, 0x88, 0x78, 0x56, 0x2f, 0xd0, 0xb4, 0x04, - 0x75, 0x80, 0x47, 0xf4, 0xd7, 0xe8, 0x8b, 0xe1, 0x4d, 0xe9, 0x6a, 0xa4, 0xae, 0xd9, 0x25, 0xe7, 0xef, 0x6a, 0x43, - 0x84, 0x8c, 0x69, 0x53, 0x20, 0x19, 0x10, 0x48, 0x32, 0x10, 0x00, 0x98, 0x9a, 0xce, 0xec, 0x15, 0x40, 0x34, 0x10, - 0xc0, 0xe3, 0xaa, 0xe3, 0xf1, 0x23, 0xfd, 0x55, 0x9c, 0xf6, 0x4e, 0xd3, 0xb0, 0xc3, 0x17, 0xa0, 0x29, 0x86, 0x72, - 0x3c, 0xdf, 0x29, 0x48, 0xf6, 0x28, 0x65, 0xe9, 0xaa, 0x89, 0xec, 0x50, 0xac, 0x4f, 0x73, 0xce, 0x42, 0xda, 0x96, - 0x63, 0xb4, 0xc5, 0xfa, 0x31, 0xf2, 0xde, 0xca, 0xa8, 0xc8, 0x07, 0x3d, 0xb8, 0xbd, 0xbd, 0x79, 0xd5, 0x63, 0x36, - 0xc9, 0x8a, 0x45, 0xae, 0x22, 0xce, 0x9c, 0xd6, 0x21, 0x07, 0x0c, 0xc8, 0x49, 0x08, 0x4c, 0x63, 0x5c, 0x2a, 0xd0, - 0x41, 0xc9, 0x72, 0x59, 0x03, 0xb5, 0x2c, 0x22, 0x6b, 0x80, 0xa8, 0xa6, 0xf9, 0x57, 0x0d, 0xf9, 0x49, 0xde, 0x9c, - 0x53, 0xa8, 0x7d, 0xc5, 0xc3, 0xea, 0xfc, 0x89, 0x55, 0x9b, 0x18, 0xeb, 0x5f, 0x6b, 0x4f, 0xd0, 0x56, 0xd2, 0x40, - 0x7c, 0xe7, 0xab, 0x74, 0x45, 0xa1, 0x3b, 0xce, 0x4c, 0x3c, 0x57, 0x81, 0xb1, 0x6f, 0xed, 0x08, 0x0a, 0x87, 0xa6, - 0xeb, 0x80, 0xc3, 0x34, 0x3a, 0x61, 0xf1, 0x4f, 0xe9, 0x38, 0x79, 0x55, 0x2b, 0x44, 0x92, 0xbf, 0x0b, 0x17, 0x86, - 0xc4, 0x82, 0xbc, 0x24, 0xd4, 0x11, 0x19, 0xb1, 0x1a, 0x15, 0x1b, 0xa1, 0xa2, 0xe2, 0x14, 0x8f, 0xb7, 0x0a, 0x8a, - 0x4b, 0x51, 0xaa, 0x94, 0x8a, 0xdc, 0xa8, 0x14, 0x10, 0xcb, 0x06, 0xde, 0x2d, 0xe0, 0x00, 0x08, 0x3a, 0xcb, 0xfd, - 0xc6, 0x76, 0xb7, 0x91, 0xf9, 0xcc, 0x34, 0x4f, 0xab, 0x0f, 0xea, 0xef, 0xf7, 0x4b, 0x8c, 0xad, 0xf1, 0xf4, 0xf7, - 0x6d, 0x5a, 0x70, 0xf3, 0x37, 0x0c, 0xd1, 0x0a, 0x10, 0x31, 0x4b, 0x7b, 0x28, 0x64, 0xc1, 0x84, 0x65, 0xa8, 0xca, - 0x53, 0x8e, 0x7a, 0xd5, 0xe4, 0x0e, 0x20, 0xd4, 0xd0, 0xaf, 0x8d, 0x4e, 0x75, 0x55, 0x82, 0xf0, 0x7d, 0x57, 0xa8, - 0xc7, 0xe6, 0x80, 0x27, 0x03, 0xe0, 0xaf, 0xc8, 0x6b, 0x3d, 0xb6, 0x7f, 0xd0, 0x1b, 0xf5, 0x06, 0x08, 0xa2, 0x73, - 0x59, 0xf8, 0x27, 0x9c, 0xeb, 0xd4, 0x9f, 0x71, 0x21, 0x88, 0x6f, 0x3d, 0x09, 0xef, 0xc5, 0x45, 0x1a, 0x07, 0x17, - 0xbd, 0x81, 0xb9, 0x08, 0x14, 0x17, 0x69, 0x7e, 0x01, 0x61, 0xf9, 0x88, 0x89, 0x58, 0xb3, 0x15, 0xc0, 0x04, 0x96, - 0x3a, 0x0e, 0x59, 0x75, 0x6c, 0xbf, 0xff, 0x7a, 0x64, 0xc8, 0xd2, 0x11, 0x06, 0x46, 0xff, 0x06, 0x14, 0xa1, 0x12, - 0x96, 0x99, 0xed, 0xc1, 0xa4, 0xab, 0x3d, 0xab, 0xe7, 0xcd, 0x36, 0xef, 0xea, 0x1d, 0xab, 0x69, 0x15, 0x35, 0x2d, - 0xb7, 0x9a, 0x36, 0xa9, 0xa0, 0x66, 0xa2, 0xdf, 0xd7, 0xa0, 0xa8, 0xd5, 0x1c, 0xc0, 0xd8, 0x30, 0xf9, 0xf5, 0x2c, - 0x9f, 0xf7, 0xfb, 0x9e, 0x7c, 0x04, 0xbf, 0x90, 0xad, 0xcc, 0xad, 0xb1, 0x7c, 0xfa, 0x8a, 0x48, 0xcc, 0x0c, 0xcc, - 0xd1, 0xea, 0x04, 0xdf, 0xeb, 0x56, 0x78, 0x1d, 0x73, 0x85, 0xcd, 0xc4, 0xf4, 0x35, 0x0c, 0x9e, 0x27, 0x7c, 0x70, - 0x91, 0xa3, 0xbf, 0x91, 0xc3, 0x4c, 0x61, 0x41, 0xce, 0xfd, 0xc9, 0x6b, 0xc4, 0x4b, 0x46, 0x78, 0x07, 0x9d, 0x4e, - 0x78, 0x90, 0xfd, 0xfe, 0x1a, 0x3a, 0xb3, 0x95, 0x4a, 0xd9, 0xaa, 0xa8, 0x4c, 0x37, 0x75, 0x51, 0x56, 0xd0, 0xb1, - 0xf4, 0xf3, 0x4e, 0xc8, 0xcc, 0xfa, 0x99, 0x05, 0xf7, 0xb4, 0x96, 0x00, 0x53, 0xb6, 0x6d, 0xa2, 0x36, 0xf0, 0xb2, - 0x2e, 0x3e, 0x17, 0x78, 0x74, 0xd6, 0x5e, 0x6f, 0x84, 0xda, 0x67, 0xb8, 0xcf, 0x6f, 0x3c, 0xf0, 0x83, 0x99, 0xa5, - 0x73, 0x45, 0x9c, 0x51, 0xf9, 0xa3, 0xcf, 0x45, 0x9a, 0x53, 0x1e, 0xe0, 0x3e, 0x14, 0x73, 0xfb, 0x2d, 0x90, 0x7e, - 0xe8, 0x2d, 0x90, 0x7d, 0x74, 0xce, 0xc9, 0x6b, 0x40, 0xa4, 0x43, 0x18, 0xdc, 0x9c, 0x04, 0x1d, 0xab, 0x86, 0x77, - 0x16, 0xd8, 0x69, 0x2f, 0x8d, 0x7b, 0x69, 0x7e, 0x91, 0xf6, 0xfb, 0x06, 0x35, 0x33, 0x45, 0x38, 0x78, 0x9c, 0x91, - 0x8b, 0xa4, 0x05, 0x5b, 0x4a, 0xfb, 0xaf, 0x06, 0x8e, 0xa8, 0x10, 0xa0, 0xf9, 0xef, 0xc2, 0x7b, 0x02, 0x10, 0x9b, - 0xb4, 0x01, 0x57, 0x3d, 0xa6, 0xa3, 0xb1, 0x25, 0x51, 0xab, 0xce, 0x06, 0x48, 0x9c, 0x2a, 0xad, 0xa7, 0xdc, 0xac, - 0x29, 0x0c, 0x52, 0x65, 0xa1, 0x7e, 0x63, 0x3d, 0x99, 0xac, 0x72, 0x91, 0x11, 0x47, 0x65, 0x7a, 0x57, 0x33, 0x82, - 0xe9, 0xd2, 0xcf, 0x17, 0xb0, 0x64, 0xe3, 0x8f, 0x38, 0x79, 0x4b, 0xc0, 0xb1, 0x9d, 0xb5, 0xab, 0x6a, 0x97, 0xe3, - 0xd6, 0x6e, 0x0e, 0xf0, 0xbd, 0xde, 0x68, 0x34, 0xd2, 0xce, 0x71, 0x02, 0x86, 0xaa, 0xa7, 0x96, 0x42, 0x8f, 0xd5, - 0x0a, 0x50, 0xb7, 0x23, 0x97, 0x59, 0x32, 0x98, 0x2f, 0x8c, 0xe3, 0x97, 0xe6, 0xa3, 0x8f, 0x97, 0xca, 0xda, 0x75, - 0xc4, 0xd7, 0x7f, 0x94, 0xd5, 0xfa, 0x96, 0x77, 0x55, 0x13, 0xf0, 0x45, 0x15, 0x50, 0xfa, 0x0d, 0xef, 0xc9, 0xde, - 0xc5, 0xd7, 0x6e, 0xb1, 0x4b, 0xbe, 0xe5, 0x2d, 0xea, 0x3c, 0x5f, 0x39, 0xb8, 0x51, 0xa5, 0xdb, 0x7b, 0xc9, 0x02, - 0xd7, 0xde, 0x49, 0xd3, 0x58, 0xcf, 0xfc, 0xe8, 0x61, 0x11, 0xb2, 0x9d, 0x8f, 0xbd, 0xaf, 0x9a, 0xa7, 0x67, 0x0d, - 0xbd, 0x49, 0x0d, 0x7d, 0xec, 0x45, 0xd9, 0x3e, 0x35, 0x8d, 0xe8, 0x35, 0x6c, 0xe8, 0x63, 0x6f, 0xc9, 0xc9, 0x21, - 0x11, 0xe0, 0xd4, 0x98, 0x3f, 0x3e, 0x9c, 0xce, 0xf0, 0x77, 0x0c, 0xa8, 0x04, 0x62, 0x3e, 0x3f, 0xa6, 0x1d, 0x05, - 0x98, 0x51, 0xa5, 0xb7, 0xcf, 0x0f, 0x6c, 0xc7, 0xcb, 0x7a, 0x68, 0xe9, 0xdd, 0xb3, 0xa3, 0xdb, 0xf1, 0xaa, 0x1a, - 0x5f, 0xca, 0x21, 0xcf, 0xf3, 0xd9, 0x68, 0x34, 0x12, 0x06, 0x92, 0x3b, 0xd7, 0x1b, 0x58, 0x81, 0xb4, 0x2d, 0xaa, - 0x0f, 0xe5, 0xd2, 0xdb, 0xab, 0x43, 0x3b, 0xf7, 0x27, 0xd5, 0xf1, 0x58, 0x8c, 0xcc, 0x31, 0x9e, 0xfb, 0xc7, 0x63, - 0xa1, 0xe4, 0x28, 0x59, 0x4b, 0x10, 0x9d, 0xd2, 0x78, 0x2a, 0xeb, 0xb5, 0x13, 0x91, 0x57, 0x23, 0xce, 0x43, 0xf0, - 0x57, 0x2f, 0x67, 0xa5, 0xfe, 0x54, 0xf8, 0xe8, 0xa7, 0x4a, 0xe9, 0x05, 0xaf, 0x0a, 0x08, 0x11, 0xfb, 0xbb, 0x81, - 0x76, 0x50, 0x82, 0x43, 0x09, 0xf7, 0x1e, 0xaf, 0x93, 0xaf, 0xbc, 0x6a, 0x26, 0x63, 0x94, 0x7b, 0x83, 0x7c, 0xce, - 0x00, 0xa6, 0xd2, 0x67, 0xe0, 0x77, 0x09, 0x50, 0xa7, 0xf8, 0x14, 0x9d, 0xea, 0xcd, 0xc3, 0xa6, 0xeb, 0xd3, 0x12, - 0x45, 0x11, 0xdd, 0xf9, 0xf9, 0x18, 0x10, 0x3b, 0xbb, 0x36, 0x23, 0xed, 0xda, 0x6f, 0xd0, 0x60, 0x95, 0x26, 0xad, - 0x95, 0x53, 0xc2, 0x6e, 0x57, 0x23, 0x5b, 0xfa, 0x51, 0x0a, 0xc4, 0xca, 0x71, 0x22, 0x91, 0x3d, 0xd8, 0xc8, 0x09, - 0xdc, 0xa2, 0xbd, 0xa3, 0x03, 0x50, 0xb9, 0x51, 0x90, 0x5f, 0xcd, 0x89, 0xdc, 0xf1, 0x7d, 0xef, 0xfb, 0x41, 0x3d, - 0xf8, 0xbe, 0x77, 0x91, 0x92, 0xdc, 0x11, 0x5e, 0xa8, 0x29, 0x21, 0xe2, 0x8b, 0xef, 0x07, 0xd5, 0x00, 0xcf, 0x12, - 0x2d, 0xd2, 0x22, 0xa1, 0x5a, 0x5d, 0xe3, 0x26, 0xbc, 0x48, 0x24, 0xf7, 0xd0, 0xbe, 0xf3, 0x88, 0x58, 0x00, 0x32, - 0x16, 0x9f, 0xcd, 0x1b, 0x0a, 0x75, 0x37, 0x31, 0x5b, 0x74, 0x97, 0xc5, 0x7e, 0x7f, 0x93, 0xa7, 0x75, 0x4f, 0xc7, - 0xc7, 0xe0, 0x0b, 0x52, 0x4d, 0x80, 0x47, 0xfb, 0x2b, 0x73, 0xbc, 0x7a, 0xb5, 0x39, 0x52, 0x16, 0xaa, 0x44, 0xfd, - 0x16, 0xab, 0x59, 0x0f, 0x61, 0xb8, 0xb3, 0xcc, 0x58, 0xdb, 0x0b, 0x9e, 0xcb, 0x59, 0x15, 0xdb, 0xe5, 0xf8, 0x8a, - 0xa5, 0x36, 0x97, 0xa8, 0x1c, 0xad, 0xc7, 0xda, 0x14, 0x23, 0xbf, 0x52, 0x48, 0x94, 0x45, 0xc7, 0xd6, 0x42, 0x01, - 0xf1, 0x02, 0xf4, 0x25, 0x7b, 0xd3, 0x00, 0xeb, 0x8d, 0x5e, 0x45, 0x84, 0x96, 0x8f, 0x54, 0x78, 0x9b, 0x9b, 0x2a, - 0xb3, 0xb2, 0x59, 0xb4, 0xfb, 0x29, 0xe7, 0x39, 0x82, 0xd5, 0x1b, 0xb5, 0x47, 0x01, 0x6a, 0x0f, 0x2d, 0x94, 0x01, - 0xa4, 0x34, 0xcd, 0x00, 0x90, 0x01, 0x40, 0xa6, 0x8a, 0xf8, 0x4c, 0x80, 0x4a, 0x5b, 0xdd, 0x28, 0x70, 0x22, 0xbd, - 0x02, 0x9a, 0x05, 0x56, 0xfa, 0x48, 0x41, 0x06, 0x8b, 0x2d, 0x02, 0xb0, 0x72, 0xe4, 0x0c, 0xd3, 0x18, 0xb2, 0x8d, - 0x26, 0x2e, 0x49, 0xf3, 0xfb, 0x30, 0x4b, 0x25, 0x9e, 0xc4, 0x8f, 0xb2, 0xc6, 0x08, 0x00, 0xa4, 0xef, 0xd3, 0x8b, - 0x22, 0x8b, 0x09, 0x07, 0xce, 0x7a, 0xea, 0xa0, 0xa8, 0xc9, 0xb9, 0xd6, 0xb4, 0x7a, 0x56, 0x9b, 0x3c, 0x64, 0x81, - 0xce, 0x1e, 0x8c, 0x49, 0x2d, 0xdf, 0xf3, 0xc8, 0xfe, 0xca, 0xe9, 0x8c, 0xf0, 0x5d, 0x77, 0x70, 0xea, 0xbf, 0xdb, - 0x1a, 0x98, 0x98, 0x12, 0x80, 0x8d, 0xc1, 0xd1, 0x84, 0xf8, 0x9d, 0x8e, 0xc9, 0xd4, 0x26, 0x45, 0x20, 0xf0, 0x10, - 0xbc, 0x82, 0xeb, 0x0b, 0x19, 0x30, 0x20, 0x68, 0x3b, 0x8b, 0x3c, 0x4d, 0x00, 0x4e, 0xbc, 0xe0, 0x3b, 0x80, 0xe3, - 0xd4, 0xab, 0x42, 0xf6, 0xec, 0xa5, 0x98, 0xce, 0xe6, 0xc1, 0x43, 0x42, 0xfb, 0x17, 0x13, 0x7e, 0xd3, 0x5d, 0x25, - 0x57, 0xa6, 0xd6, 0xbd, 0x89, 0xae, 0x72, 0x95, 0xd3, 0xa7, 0x39, 0xc7, 0x30, 0x67, 0xb0, 0x0a, 0xc8, 0x39, 0x1b, - 0xf2, 0xe7, 0x97, 0x00, 0xd8, 0xb2, 0x16, 0x5e, 0xc4, 0x9f, 0x87, 0xb2, 0x5a, 0x00, 0xf7, 0xc8, 0x79, 0x64, 0x7e, - 0xf9, 0x6a, 0x3b, 0x94, 0x73, 0x8a, 0xc2, 0x58, 0xce, 0x4d, 0x4b, 0x8a, 0xd3, 0xa1, 0xa7, 0x60, 0x32, 0xb5, 0xe5, - 0xef, 0x5d, 0xe2, 0x32, 0x7b, 0x33, 0x09, 0xe7, 0xeb, 0xc8, 0xb6, 0xb5, 0xea, 0x1e, 0xba, 0x21, 0x18, 0xf4, 0x31, - 0x82, 0x96, 0xd5, 0x9b, 0x5f, 0x31, 0x18, 0x28, 0x6c, 0xdf, 0x9a, 0x6e, 0x5a, 0x74, 0x8a, 0x03, 0xce, 0xac, 0x75, - 0x8d, 0x4a, 0x55, 0x71, 0xe8, 0x25, 0xef, 0x96, 0x95, 0xdb, 0x65, 0xe9, 0x85, 0x20, 0x35, 0xea, 0x2a, 0x42, 0xa4, - 0x54, 0xec, 0xf0, 0x9e, 0xfc, 0x1a, 0x98, 0x78, 0x66, 0xe5, 0x28, 0x8d, 0xe7, 0x00, 0x13, 0xa4, 0xd0, 0x37, 0xe5, - 0x57, 0x80, 0x1b, 0xba, 0x88, 0xc2, 0xec, 0x4d, 0x5c, 0x05, 0xb5, 0xd5, 0xf4, 0x7b, 0x07, 0x27, 0xf6, 0xb2, 0xee, - 0xf7, 0x53, 0xa2, 0xf1, 0xc3, 0xd0, 0x0b, 0xfc, 0x7b, 0x3c, 0x3d, 0x34, 0x41, 0x6a, 0x5e, 0x79, 0x80, 0x57, 0x74, - 0xb9, 0xb5, 0x29, 0x57, 0x34, 0x2e, 0xe6, 0x35, 0x22, 0xc2, 0xa7, 0x8e, 0x62, 0xbb, 0xcd, 0x8f, 0x53, 0x1b, 0x83, - 0x41, 0x08, 0xf7, 0xad, 0x8c, 0xdf, 0x27, 0x5e, 0x35, 0x8b, 0xe6, 0xa0, 0x28, 0xcd, 0x34, 0x49, 0x48, 0x21, 0xbd, - 0x04, 0xe8, 0xa3, 0x41, 0xa8, 0xd5, 0x95, 0x7f, 0x24, 0x5e, 0xaa, 0xa6, 0xb5, 0x79, 0x8a, 0x35, 0x0a, 0xc4, 0x2c, - 0x9a, 0x37, 0x2c, 0xa3, 0x43, 0x52, 0x5d, 0x2e, 0x4d, 0x33, 0xfe, 0xb0, 0x9a, 0xa1, 0x5a, 0x71, 0xd2, 0x04, 0x35, - 0x4a, 0xb7, 0x70, 0x01, 0xfc, 0x1b, 0xdd, 0x71, 0x54, 0xa3, 0x48, 0xd1, 0x80, 0x4f, 0x20, 0xa6, 0xab, 0x30, 0x9b, - 0x27, 0xac, 0x35, 0x75, 0xcd, 0xe8, 0xf7, 0x65, 0x9c, 0x90, 0x49, 0x42, 0x72, 0x3e, 0x5c, 0xae, 0x1f, 0x49, 0x75, - 0x01, 0xa4, 0xca, 0x39, 0x9b, 0xf5, 0x7a, 0x73, 0xc0, 0xe8, 0x85, 0xf5, 0x0b, 0x1b, 0x57, 0x70, 0x79, 0x4d, 0x98, - 0xbb, 0xea, 0x47, 0x98, 0x65, 0x50, 0x05, 0xa4, 0xf9, 0xb1, 0xa0, 0xd3, 0x2b, 0x17, 0x88, 0xfa, 0xf5, 0x48, 0x5d, - 0x50, 0x66, 0xe9, 0xdc, 0x22, 0x02, 0x01, 0xaf, 0x61, 0xf5, 0x04, 0x92, 0x7d, 0xf9, 0xd8, 0xa7, 0x19, 0x05, 0xaa, - 0x23, 0x00, 0x65, 0xb3, 0x7e, 0x08, 0xfb, 0x07, 0x84, 0x13, 0xea, 0x6f, 0xde, 0xca, 0x59, 0x43, 0xf2, 0x40, 0xaa, - 0x09, 0x8f, 0xe1, 0xd4, 0x58, 0xe0, 0x4b, 0x8b, 0xde, 0x54, 0xf0, 0x9a, 0xe0, 0xb8, 0x17, 0x68, 0xed, 0x5b, 0xc0, - 0x11, 0x22, 0xb8, 0x0c, 0x4d, 0x9c, 0xf6, 0xf6, 0xbd, 0x00, 0x09, 0xcd, 0x2d, 0x9c, 0xeb, 0xb7, 0x2e, 0x68, 0x71, - 0x8a, 0x9c, 0x2c, 0xba, 0xc0, 0x40, 0x17, 0x64, 0xde, 0xf8, 0x67, 0x0e, 0x2b, 0x17, 0x20, 0x7b, 0xa9, 0x58, 0x49, - 0xc4, 0xb6, 0x57, 0x7f, 0x94, 0xca, 0x7e, 0x7b, 0x61, 0x4d, 0xe0, 0x97, 0x89, 0xfd, 0x12, 0x99, 0x7c, 0xd3, 0x53, - 0x93, 0xaf, 0x8c, 0x85, 0x4e, 0x2d, 0x83, 0x73, 0x7a, 0x62, 0x70, 0xee, 0xed, 0xad, 0xda, 0x94, 0x30, 0x14, 0x24, - 0x81, 0xa6, 0x4b, 0x0f, 0xeb, 0xa6, 0x3f, 0x3f, 0x69, 0xf1, 0x6b, 0xd5, 0xbe, 0x75, 0x3f, 0x0e, 0xb1, 0x8b, 0x5f, - 0x26, 0x9e, 0x61, 0x1f, 0xf5, 0x81, 0x03, 0x4c, 0x46, 0x4c, 0x5c, 0xf7, 0xfb, 0x50, 0xd8, 0x6c, 0x3c, 0x1f, 0xd5, - 0xc5, 0xcf, 0xc5, 0x03, 0x40, 0x39, 0x54, 0x60, 0x97, 0x43, 0x19, 0xca, 0x88, 0x4d, 0x6d, 0xb9, 0xe7, 0xf7, 0x97, - 0x61, 0x0e, 0xf2, 0x8e, 0xc6, 0xc4, 0xb9, 0x00, 0x31, 0x0c, 0xbe, 0xfe, 0xfd, 0x93, 0x43, 0xda, 0x7c, 0x7f, 0x01, - 0xdf, 0x1d, 0x5d, 0x7c, 0x40, 0x8e, 0x9b, 0x8b, 0x4d, 0x59, 0xdc, 0xa7, 0xb1, 0xb8, 0xf8, 0x1e, 0x52, 0xbf, 0xbf, - 0x28, 0xca, 0x8b, 0xef, 0x55, 0x65, 0xbe, 0xbf, 0xa0, 0x05, 0x37, 0xfa, 0xdd, 0x9a, 0x78, 0xff, 0xc8, 0x35, 0xed, - 0xd9, 0x12, 0xc2, 0xb1, 0xb4, 0xfa, 0x11, 0x94, 0x88, 0x8a, 0x14, 0x55, 0x86, 0xb2, 0x5a, 0x3b, 0xce, 0xfb, 0x44, - 0xc3, 0x63, 0xd3, 0x84, 0xc4, 0xd5, 0x12, 0xd6, 0xa1, 0x9e, 0x9d, 0x36, 0xc9, 0x8e, 0xf3, 0x40, 0x1d, 0x10, 0x15, - 0x7f, 0x5e, 0x8d, 0x76, 0xf4, 0x35, 0xf8, 0xd6, 0xf1, 0x58, 0x8d, 0xf6, 0xe6, 0xa7, 0x4f, 0xd6, 0x4a, 0x19, 0x6c, - 0xa4, 0x18, 0x85, 0x90, 0x28, 0x6e, 0xd7, 0x63, 0x00, 0xfc, 0xef, 0x1f, 0x8f, 0xf4, 0x7b, 0x2f, 0x7f, 0xab, 0xdd, - 0xd2, 0xaa, 0xe7, 0x87, 0x16, 0x61, 0xc6, 0xab, 0xda, 0xb0, 0xb3, 0x1d, 0x24, 0xa0, 0xf4, 0xa1, 0x69, 0x50, 0x53, - 0x44, 0x3f, 0x61, 0x35, 0xb1, 0x9c, 0xc3, 0x82, 0x94, 0x38, 0xc4, 0x70, 0x8c, 0x76, 0xe8, 0x71, 0xba, 0xa8, 0x79, - 0x2a, 0xdf, 0x21, 0xe3, 0xd6, 0xf7, 0x01, 0xc9, 0xa5, 0x70, 0xf9, 0xc1, 0x0b, 0x0d, 0x26, 0x7a, 0x91, 0x57, 0x45, - 0x26, 0x46, 0x82, 0x46, 0xf9, 0x0d, 0x89, 0x33, 0x17, 0x58, 0x8b, 0x0b, 0x85, 0x10, 0x16, 0x12, 0x2a, 0x77, 0x51, - 0x52, 0x7a, 0x70, 0xf1, 0xe4, 0x50, 0x36, 0xbf, 0x13, 0x26, 0xc4, 0x68, 0x01, 0x34, 0x38, 0xfb, 0x76, 0x79, 0x0f, - 0x61, 0x99, 0x7b, 0xbf, 0xbf, 0x59, 0xe5, 0x05, 0xc4, 0x65, 0x5e, 0x48, 0xc5, 0x6a, 0x79, 0x01, 0x34, 0x79, 0x22, - 0xbe, 0x08, 0x2b, 0x39, 0x0d, 0xaa, 0x8e, 0x62, 0xd5, 0x36, 0x5e, 0x56, 0x1e, 0xf0, 0x7a, 0xbf, 0x4f, 0x80, 0xc0, - 0xdd, 0x67, 0xaf, 0x95, 0x5b, 0x2a, 0xe9, 0x91, 0xe7, 0x18, 0x22, 0x99, 0x00, 0xaf, 0x33, 0x04, 0x47, 0x0a, 0xab, - 0xe7, 0x26, 0xc8, 0x3f, 0xbe, 0x39, 0xa3, 0xf8, 0xa2, 0x79, 0x14, 0x35, 0x2c, 0x64, 0x09, 0x1c, 0x0f, 0xc9, 0x2c, - 0x9b, 0x23, 0x35, 0x79, 0xda, 0x9e, 0x22, 0x1d, 0x9d, 0x58, 0xe2, 0xb7, 0x35, 0xa9, 0x5e, 0xa4, 0xc2, 0x2e, 0x69, - 0x67, 0x2b, 0x2a, 0x2f, 0x84, 0xa1, 0x4a, 0xb8, 0xf7, 0xaa, 0x9e, 0x85, 0x72, 0x53, 0xb4, 0x2a, 0x66, 0x0f, 0x53, - 0x62, 0x86, 0x29, 0xd6, 0x5f, 0xd8, 0xf2, 0xdb, 0xc4, 0x8b, 0xc1, 0x70, 0xbd, 0xe4, 0xe5, 0x6c, 0x6b, 0x16, 0xc2, - 0xf1, 0xb8, 0x9d, 0x14, 0xb3, 0x25, 0xc4, 0xb6, 0x2e, 0xe7, 0xc7, 0x63, 0x57, 0xcb, 0x36, 0xc2, 0x83, 0x87, 0xaa, - 0x85, 0xdb, 0x86, 0x55, 0xf0, 0x33, 0x99, 0xc5, 0xd8, 0xbe, 0xc6, 0x67, 0xf6, 0xe7, 0x8b, 0xee, 0x59, 0x82, 0x8c, - 0x1b, 0x1b, 0xe0, 0x1a, 0x9b, 0xb5, 0x3b, 0x5c, 0x8d, 0x80, 0xe4, 0x71, 0x37, 0xfa, 0xbb, 0xb2, 0x93, 0x9c, 0x04, - 0x09, 0xa3, 0x15, 0xc2, 0xef, 0xa1, 0xf1, 0x27, 0x5a, 0xec, 0x41, 0xbb, 0x8d, 0x2d, 0x21, 0xaa, 0x69, 0xcf, 0xe5, - 0x4a, 0xb1, 0x34, 0x6f, 0xa5, 0x0d, 0x99, 0x0f, 0xeb, 0xf3, 0xd0, 0xc8, 0x81, 0x82, 0x31, 0xe2, 0xa9, 0x75, 0x10, - 0xcd, 0xe6, 0xc0, 0x7d, 0x81, 0xe6, 0x11, 0x9e, 0x5a, 0x90, 0xa0, 0xcc, 0xda, 0xb0, 0x9f, 0x24, 0x67, 0xcb, 0xe3, - 0xf0, 0x2d, 0xfc, 0xcb, 0x67, 0xd8, 0x24, 0xa6, 0x28, 0x1e, 0x7f, 0xcb, 0x15, 0xff, 0x1d, 0x5b, 0x10, 0xc1, 0xda, - 0xad, 0xa8, 0x0d, 0x7f, 0xc3, 0xbf, 0x84, 0x7d, 0x84, 0xfd, 0x96, 0xe3, 0x4d, 0xd2, 0x10, 0x90, 0x09, 0xc4, 0x85, - 0x85, 0x20, 0xc1, 0xdf, 0x72, 0xc9, 0x3f, 0x27, 0x7c, 0xb6, 0x28, 0x81, 0xac, 0x0e, 0xa3, 0xf8, 0x84, 0x62, 0xa2, - 0x10, 0x86, 0x5b, 0x42, 0xef, 0xe8, 0xbf, 0x11, 0x25, 0xd9, 0xa4, 0xb2, 0x62, 0x3d, 0x90, 0x49, 0x12, 0x4c, 0xb0, - 0xf2, 0x42, 0xf9, 0xc2, 0xbd, 0x50, 0x6a, 0xad, 0x05, 0xad, 0x5f, 0xfe, 0x24, 0xf1, 0x0c, 0xe8, 0x1e, 0xc8, 0x18, - 0x74, 0x1b, 0x51, 0x4d, 0x72, 0x4c, 0x1f, 0xa5, 0xf3, 0x0c, 0x54, 0x40, 0x17, 0x9b, 0x2c, 0xac, 0x97, 0x45, 0xb9, - 0x6e, 0x85, 0x87, 0xca, 0xd2, 0x47, 0xea, 0x31, 0xe6, 0x85, 0x79, 0x72, 0x26, 0x1f, 0x3c, 0x02, 0x34, 0x3c, 0xca, - 0xd3, 0xaa, 0xa3, 0xb4, 0x7e, 0x60, 0x19, 0x30, 0x02, 0x67, 0xca, 0x80, 0x47, 0x58, 0x06, 0xe6, 0x69, 0x97, 0xa1, - 0x06, 0xb1, 0x46, 0xd5, 0x95, 0xda, 0x60, 0xce, 0x14, 0x25, 0x9f, 0x62, 0x69, 0x85, 0x31, 0x34, 0x75, 0xe5, 0x91, - 0xf5, 0x92, 0x13, 0xf6, 0x6c, 0x37, 0x90, 0x6e, 0x61, 0xab, 0xc0, 0x05, 0x5d, 0xcb, 0x12, 0xe5, 0xa2, 0x5b, 0x46, - 0x94, 0x89, 0x90, 0xfa, 0xd9, 0xc3, 0x99, 0x56, 0xfb, 0x8d, 0x9d, 0x74, 0x68, 0x8f, 0x14, 0xbd, 0x60, 0x20, 0x3e, - 0xed, 0x91, 0x52, 0xcf, 0x1a, 0xb9, 0x0c, 0x6c, 0xe9, 0x52, 0xd5, 0xf3, 0x5f, 0xa0, 0x7c, 0x07, 0x33, 0xe3, 0x6c, - 0xf6, 0xbb, 0xde, 0xdc, 0x9e, 0x1c, 0xea, 0xe6, 0x77, 0xd6, 0xeb, 0xc1, 0xd6, 0x20, 0x13, 0x5f, 0x28, 0xea, 0x29, - 0xab, 0x10, 0x2b, 0x32, 0xfb, 0x5f, 0xc2, 0xfb, 0x1d, 0xde, 0x1a, 0xa1, 0x59, 0x19, 0x0f, 0xf3, 0xd1, 0x93, 0x83, - 0x68, 0x7e, 0xef, 0x2c, 0xdb, 0xca, 0x55, 0xc9, 0x6c, 0xbf, 0x9f, 0x24, 0xcd, 0xd9, 0xe3, 0x35, 0x92, 0x3a, 0xc0, - 0xc7, 0xeb, 0x33, 0x7c, 0xa4, 0x12, 0x4a, 0x2d, 0xa8, 0x6a, 0xd0, 0xfa, 0xd8, 0xef, 0xad, 0xe7, 0xf4, 0xf1, 0x53, - 0x39, 0xdd, 0x92, 0x22, 0x8c, 0x1f, 0x18, 0x4c, 0xd9, 0x89, 0x53, 0x97, 0xaa, 0x19, 0xd2, 0xbb, 0x6e, 0x95, 0xd4, - 0x65, 0x8f, 0x12, 0x41, 0xa8, 0x83, 0xf5, 0x8b, 0xfd, 0x10, 0x66, 0xb6, 0xe8, 0x0f, 0x9b, 0xd5, 0x9c, 0x50, 0x10, - 0x01, 0xa2, 0x55, 0xde, 0x07, 0x4e, 0x49, 0xc2, 0xac, 0xb9, 0x21, 0xdd, 0x7a, 0x2b, 0xa5, 0xbd, 0x92, 0x02, 0xfa, - 0x65, 0x7e, 0x3c, 0xa2, 0xf9, 0xcd, 0xec, 0x5c, 0x95, 0xb4, 0xe5, 0x00, 0x22, 0x75, 0xde, 0xb4, 0x2f, 0x1d, 0x0e, - 0xfe, 0x83, 0xba, 0x12, 0xe5, 0x44, 0xd0, 0x51, 0xb4, 0x60, 0xb4, 0x5a, 0xb5, 0xab, 0xc8, 0xa6, 0x42, 0xb6, 0x24, - 0xc2, 0x89, 0x92, 0xbd, 0x12, 0xea, 0xa3, 0x5c, 0xed, 0x99, 0x86, 0xf8, 0x33, 0x01, 0x9b, 0x36, 0xf8, 0x5b, 0xe0, - 0x5e, 0x06, 0x67, 0xa6, 0x7d, 0x1a, 0x46, 0x40, 0x64, 0x0e, 0xc1, 0x7e, 0x7e, 0xd7, 0x83, 0x1c, 0x1e, 0x74, 0xa4, - 0xbf, 0xaa, 0x67, 0x05, 0x9e, 0xb9, 0x67, 0x9e, 0xbf, 0x3e, 0x93, 0x9e, 0x57, 0xf0, 0x40, 0x73, 0x1f, 0x66, 0xfc, - 0x45, 0x59, 0x86, 0xfb, 0xd1, 0xb2, 0x2c, 0xd6, 0x5e, 0xa4, 0xf7, 0xf1, 0x4c, 0x8a, 0x81, 0x44, 0x87, 0x99, 0xd1, - 0x55, 0xac, 0xe3, 0x1c, 0xc6, 0xbd, 0x3d, 0x09, 0x2b, 0xb4, 0x7f, 0x96, 0xd8, 0xeb, 0x02, 0x00, 0x1c, 0xb2, 0x06, - 0xad, 0xf0, 0x4e, 0xb7, 0xb7, 0x7b, 0x5c, 0x52, 0xa2, 0xb8, 0x51, 0xf3, 0xb3, 0x1a, 0x5a, 0x26, 0xa8, 0x65, 0xd6, - 0x9d, 0x4c, 0xa6, 0x48, 0x02, 0xdf, 0x86, 0xbd, 0x66, 0x79, 0x35, 0x6f, 0xe4, 0xf6, 0xf0, 0x2e, 0x5c, 0x8b, 0x58, - 0x5b, 0xd0, 0x49, 0x47, 0xc6, 0xe1, 0x5e, 0x68, 0x6e, 0xa4, 0x87, 0x27, 0x55, 0x12, 0x96, 0x22, 0x86, 0x5b, 0x20, - 0x3b, 0xa8, 0x6d, 0x25, 0x28, 0x81, 0x04, 0xf6, 0x43, 0x29, 0x96, 0xe9, 0x4e, 0x00, 0x98, 0x03, 0xff, 0x53, 0x1a, - 0xbb, 0xdd, 0x9d, 0x87, 0x78, 0xd5, 0xc8, 0xfb, 0x06, 0x21, 0xd8, 0x5f, 0x81, 0x9c, 0x06, 0x0c, 0x22, 0xc5, 0x48, - 0x16, 0x0c, 0x24, 0x00, 0x15, 0xdf, 0x80, 0x49, 0x6e, 0x5a, 0x79, 0x7e, 0x50, 0xe9, 0x0e, 0xa6, 0x7d, 0xd0, 0xbd, - 0xb8, 0xd6, 0x0c, 0x90, 0x7f, 0x27, 0x11, 0xff, 0x5b, 0xed, 0x95, 0xac, 0x62, 0x99, 0xdf, 0x98, 0x8b, 0x4e, 0x06, - 0x57, 0x0d, 0xe1, 0x17, 0xb3, 0x6c, 0xce, 0xa3, 0x59, 0xa6, 0x43, 0xfd, 0x8b, 0xe6, 0xa4, 0x14, 0xc0, 0x50, 0xc7, - 0x0b, 0xb0, 0xc6, 0xbb, 0xd2, 0x4d, 0x2b, 0x1e, 0x69, 0x8c, 0x51, 0x50, 0xa1, 0x83, 0xd0, 0xdf, 0x6a, 0x80, 0xd7, - 0x60, 0x92, 0x1b, 0x21, 0xf7, 0xc1, 0x05, 0xdd, 0xd0, 0x2d, 0xe7, 0x2e, 0x41, 0x4d, 0xaa, 0x96, 0x5f, 0x85, 0x50, - 0xef, 0x6a, 0xc9, 0xa5, 0xda, 0x7c, 0x6a, 0x94, 0x35, 0x82, 0x4c, 0x8e, 0xd2, 0xef, 0x53, 0x2e, 0xdc, 0xdc, 0x98, - 0xac, 0x8f, 0x47, 0xaf, 0xe0, 0xa6, 0xc6, 0x3f, 0x56, 0x92, 0x45, 0xd4, 0x1a, 0x12, 0x61, 0x6b, 0xb7, 0x42, 0xf7, - 0x1e, 0x37, 0x4a, 0xf3, 0x28, 0xdb, 0xc6, 0xa2, 0xf2, 0x7a, 0x09, 0x58, 0x8b, 0x7b, 0x40, 0x86, 0x4a, 0x4b, 0x3f, - 0x67, 0x05, 0x40, 0x06, 0x48, 0x61, 0xe3, 0x47, 0xa4, 0xbd, 0xfa, 0xe0, 0xa5, 0x7e, 0xbf, 0x6f, 0x4c, 0xf9, 0xef, - 0x1f, 0x72, 0x60, 0x26, 0x14, 0x65, 0xbd, 0x87, 0x09, 0x54, 0x79, 0xa9, 0x4f, 0xda, 0xb3, 0x9a, 0x3f, 0xdf, 0xd4, - 0x1e, 0x90, 0x5a, 0xf9, 0x16, 0x73, 0xd5, 0x2b, 0xfb, 0x62, 0x73, 0x48, 0xab, 0x5b, 0xa3, 0x71, 0x10, 0x2c, 0xad, - 0xde, 0x68, 0x95, 0x43, 0xd5, 0xf0, 0x1c, 0x44, 0x2a, 0xeb, 0xea, 0x9a, 0x3b, 0x57, 0xd7, 0x82, 0x23, 0x81, 0x6c, - 0xc9, 0x21, 0x2c, 0x8d, 0x85, 0xdc, 0x2b, 0x8f, 0xc7, 0xc2, 0xef, 0xf7, 0xd3, 0x59, 0x8e, 0x97, 0x16, 0xa0, 0x4c, - 0xdb, 0xd4, 0x5e, 0xe8, 0x1f, 0x8f, 0x3f, 0x82, 0xd7, 0x88, 0x7f, 0x3c, 0x96, 0xfd, 0xfe, 0x47, 0x73, 0x93, 0xb9, - 0x1c, 0x2b, 0xa5, 0xec, 0x35, 0x2a, 0xdd, 0xdf, 0x24, 0xbc, 0xf7, 0xbf, 0x47, 0xff, 0x7b, 0x74, 0xdd, 0x53, 0x01, - 0x60, 0x09, 0x9f, 0xe1, 0x0d, 0x9d, 0xa9, 0xcb, 0x39, 0x93, 0xee, 0xee, 0xca, 0x0f, 0xbd, 0xa7, 0xf1, 0xe1, 0x7b, - 0x73, 0xd3, 0xc6, 0x5f, 0xf3, 0x13, 0x4d, 0x42, 0xc7, 0x45, 0xff, 0x78, 0xfc, 0x94, 0x68, 0x7d, 0x5a, 0xaa, 0xf4, - 0x69, 0x0a, 0x3c, 0xc9, 0xb0, 0xe1, 0xba, 0x85, 0xe9, 0x68, 0x7e, 0xdc, 0x7c, 0x95, 0xbc, 0x38, 0x4b, 0xe1, 0xda, - 0x0b, 0x3a, 0x97, 0x29, 0x58, 0x57, 0x86, 0xe0, 0x66, 0x10, 0x40, 0xea, 0x10, 0xd2, 0xac, 0x69, 0xf8, 0x97, 0xdc, - 0x15, 0xbc, 0xb5, 0xc7, 0xbb, 0xc1, 0x88, 0x52, 0x47, 0xfa, 0xa4, 0x0d, 0xa1, 0x4b, 0x2a, 0xf9, 0x8f, 0x22, 0x8f, - 0x31, 0x66, 0xe3, 0x15, 0x91, 0x7d, 0x16, 0xf9, 0xcb, 0x02, 0x00, 0x8b, 0x00, 0x01, 0x39, 0x9d, 0x3b, 0x92, 0xf8, - 0xcf, 0xc9, 0xb7, 0x7f, 0x4c, 0x97, 0xf6, 0xa1, 0x2c, 0x56, 0xa5, 0xa8, 0xaa, 0x93, 0xd2, 0xf6, 0xb6, 0x5c, 0x0f, - 0xf4, 0xa1, 0xfd, 0xbe, 0xa4, 0x0f, 0x4d, 0x31, 0x14, 0x05, 0x6e, 0x8d, 0xbd, 0x69, 0xca, 0x15, 0x4d, 0xf5, 0xc8, - 0x58, 0x3f, 0x7f, 0xd8, 0xbf, 0x89, 0xbd, 0xd4, 0x0f, 0x52, 0x10, 0x84, 0x35, 0x7e, 0x52, 0x8a, 0x24, 0x70, 0x3e, - 0xc3, 0x54, 0xe2, 0xd3, 0xa5, 0x54, 0xf9, 0xc3, 0x48, 0xf3, 0x61, 0x0a, 0x7a, 0xd9, 0xbf, 0xe7, 0x30, 0xff, 0x75, - 0x7b, 0xb0, 0x3e, 0xad, 0xcb, 0x34, 0xaa, 0x88, 0x2a, 0x2f, 0x4c, 0xb5, 0x09, 0x44, 0xf0, 0xe7, 0xc2, 0x22, 0xf9, - 0xf5, 0xc9, 0x91, 0xa0, 0x31, 0x93, 0xe5, 0xe3, 0x89, 0xfb, 0x85, 0x7d, 0xe5, 0x3a, 0x9d, 0xff, 0x95, 0x99, 0xff, - 0x03, 0x8c, 0x49, 0x28, 0x9e, 0x73, 0xcb, 0x60, 0x81, 0xb3, 0x5f, 0xba, 0x7a, 0xc0, 0xdf, 0xcc, 0x13, 0xcf, 0x81, - 0x83, 0xf9, 0x39, 0xba, 0x2a, 0xa6, 0xb3, 0x62, 0x00, 0x04, 0xb6, 0x7e, 0x63, 0xcd, 0x89, 0xd7, 0x16, 0xcf, 0x95, - 0x5c, 0x10, 0xfa, 0xba, 0x0a, 0xb3, 0x71, 0x5d, 0x6c, 0x2b, 0x51, 0x6c, 0x21, 0x6c, 0x04, 0xd4, 0xb2, 0xd5, 0xb4, - 0xb6, 0x15, 0xb2, 0x3f, 0x89, 0x16, 0x6d, 0x97, 0xa1, 0x9a, 0x8c, 0xb2, 0x74, 0x33, 0x05, 0x52, 0xbd, 0x00, 0xce, - 0x22, 0xf3, 0xca, 0x3b, 0x67, 0x0f, 0xd8, 0xa1, 0xf1, 0x14, 0x18, 0x51, 0xe9, 0x8f, 0xaa, 0x31, 0x3a, 0x3d, 0xd1, - 0xef, 0x57, 0x53, 0x0a, 0xf9, 0xfa, 0x09, 0x30, 0xb9, 0x6a, 0xb9, 0x00, 0x7d, 0x19, 0xea, 0xa0, 0x12, 0xa5, 0x56, - 0x0c, 0x23, 0x16, 0x7e, 0x12, 0xc8, 0xde, 0x4c, 0x41, 0xcd, 0x2a, 0x4a, 0x42, 0x25, 0x2a, 0x25, 0x5b, 0x13, 0xd4, - 0xd2, 0xfb, 0xa2, 0xa8, 0x0f, 0x15, 0x38, 0x4a, 0x46, 0xda, 0x2c, 0xa7, 0xcc, 0xb8, 0x28, 0x73, 0xd1, 0x0f, 0xf6, - 0x2f, 0xc0, 0xf8, 0x92, 0xf9, 0x2c, 0xf7, 0x1d, 0x9d, 0xd3, 0x76, 0x5c, 0xa0, 0xcc, 0x2d, 0xa7, 0xad, 0x96, 0x3c, - 0x26, 0xef, 0x59, 0xb0, 0xed, 0xbf, 0x48, 0x90, 0x57, 0x11, 0xe6, 0x13, 0xaa, 0x6c, 0xfe, 0x9e, 0x7b, 0xc4, 0x3e, - 0xda, 0xe1, 0xc2, 0x44, 0xa4, 0xb7, 0x60, 0x49, 0x0c, 0xb3, 0x52, 0x84, 0xf1, 0x1e, 0xbc, 0x7f, 0xb6, 0x95, 0x18, - 0x5d, 0xa0, 0x93, 0xfb, 0xc5, 0x43, 0x5a, 0x27, 0x17, 0x6f, 0x5e, 0x5d, 0x7c, 0xdf, 0x1b, 0x14, 0xa3, 0x34, 0x1e, - 0xf4, 0xbe, 0xbf, 0x58, 0x6f, 0x01, 0x22, 0x53, 0x5c, 0xc4, 0x64, 0x4a, 0x13, 0xf1, 0x05, 0x19, 0x06, 0x2f, 0xea, - 0x44, 0x5c, 0xd0, 0xc4, 0x74, 0x5f, 0xa3, 0x34, 0xf9, 0x76, 0x14, 0xe6, 0xf0, 0x72, 0x29, 0xb6, 0x95, 0x88, 0xc1, - 0x4e, 0xa9, 0xe6, 0xd9, 0xc9, 0x59, 0x2c, 0x3d, 0x06, 0x5d, 0x59, 0xa5, 0x03, 0x74, 0x7b, 0x22, 0xed, 0xaa, 0x74, - 0x05, 0x84, 0x1e, 0xf0, 0xcc, 0xcf, 0xe3, 0x51, 0x24, 0x10, 0x6a, 0xc1, 0x9c, 0x4c, 0x23, 0xba, 0x21, 0xbd, 0xc4, - 0x3e, 0x03, 0xb3, 0x90, 0xd2, 0x3c, 0xb8, 0xb9, 0x5a, 0xb4, 0xdc, 0x39, 0x2b, 0x47, 0x61, 0xb5, 0x11, 0x51, 0x8d, - 0x54, 0xc7, 0xe0, 0xbc, 0x03, 0x11, 0x00, 0x8a, 0x11, 0x3c, 0xe3, 0x51, 0xbf, 0x1f, 0xa9, 0xa0, 0x9c, 0x84, 0x7e, - 0x51, 0xe8, 0x97, 0xc6, 0xa0, 0x8c, 0xf9, 0x97, 0x50, 0x13, 0x03, 0xd4, 0x3b, 0x1e, 0x2a, 0x8e, 0x00, 0x5c, 0xce, - 0x11, 0x33, 0xce, 0x7b, 0xdc, 0x45, 0xe3, 0x54, 0xbc, 0x13, 0xea, 0x3a, 0x58, 0x2a, 0xd4, 0x79, 0x53, 0x1f, 0xe9, - 0x39, 0x69, 0x12, 0x34, 0x88, 0x1b, 0x78, 0xbc, 0x1a, 0x02, 0xaa, 0xb5, 0x90, 0x7a, 0x0b, 0x9d, 0x52, 0xd5, 0x21, - 0xb0, 0x06, 0xb8, 0x44, 0x61, 0x3b, 0x61, 0x72, 0x44, 0xdb, 0xb2, 0x14, 0xf9, 0x09, 0x1b, 0xb4, 0x4b, 0x46, 0xa6, - 0x0e, 0x2e, 0x97, 0xcb, 0x89, 0xa8, 0x7f, 0xcd, 0xb7, 0x00, 0xce, 0x0b, 0xf9, 0xad, 0xdd, 0x6c, 0x99, 0x64, 0xbb, - 0xfe, 0x3f, 0xbc, 0x7d, 0x09, 0x77, 0xdb, 0x46, 0xb2, 0xee, 0x5f, 0x11, 0xf1, 0x1c, 0x06, 0x6d, 0x36, 0x29, 0x52, - 0xb1, 0x33, 0x09, 0xa8, 0x16, 0xaf, 0xe2, 0x25, 0x71, 0x26, 0x5e, 0x62, 0x39, 0x99, 0xcc, 0xf0, 0xf1, 0x2a, 0x10, - 0xd0, 0x12, 0x11, 0x43, 0x68, 0x06, 0x00, 0xb5, 0x84, 0xc4, 0x7f, 0x7f, 0xa7, 0xaa, 0x77, 0x10, 0x94, 0x3d, 0xf3, - 0xee, 0x7b, 0xc7, 0xe7, 0x58, 0x44, 0xa3, 0xd1, 0x7b, 0x57, 0x57, 0xd7, 0xf2, 0x55, 0x65, 0x63, 0x96, 0x94, 0xbc, - 0x5a, 0x89, 0xa2, 0xca, 0x6e, 0xf8, 0x4f, 0xe6, 0xa5, 0x1f, 0x40, 0x0a, 0xed, 0x48, 0x5f, 0xb7, 0xbb, 0xa3, 0xc4, - 0x38, 0xa6, 0x1c, 0xd7, 0x52, 0xe9, 0x5e, 0x8d, 0xaa, 0x13, 0x37, 0x5b, 0xe5, 0x5a, 0x66, 0x69, 0xca, 0x8b, 0x57, - 0x45, 0x9a, 0x25, 0x4e, 0x72, 0xac, 0x02, 0x54, 0xdb, 0xc8, 0x57, 0x36, 0x36, 0xf2, 0xf3, 0xac, 0xc2, 0x80, 0xc1, - 0x5e, 0xa3, 0x5a, 0xa1, 0xa6, 0x74, 0xe0, 0x0b, 0xf1, 0x1e, 0x23, 0x6e, 0xb3, 0x22, 0x01, 0x86, 0x1f, 0x13, 0xd5, - 0x25, 0x3d, 0x85, 0x28, 0x0f, 0x32, 0x1e, 0xf7, 0x73, 0x8e, 0x88, 0xd7, 0x46, 0x65, 0x0e, 0x4c, 0xb6, 0x52, 0x41, - 0x22, 0xd8, 0x5d, 0x36, 0x57, 0x8b, 0x68, 0x21, 0xef, 0x42, 0xbd, 0x78, 0xbb, 0xed, 0x25, 0x92, 0x0e, 0x58, 0xf9, - 0x69, 0xf0, 0x32, 0xce, 0x72, 0x9e, 0x1e, 0xd4, 0xe2, 0x40, 0x6e, 0xa8, 0x03, 0xe9, 0xcc, 0x01, 0x3b, 0xef, 0xcb, - 0xfa, 0x40, 0xad, 0xe9, 0x03, 0xd5, 0xce, 0x03, 0xb8, 0x60, 0xe0, 0xce, 0xbd, 0xca, 0x6e, 0x78, 0x71, 0x00, 0xca, - 0x40, 0x63, 0x3c, 0xd0, 0x54, 0xf5, 0x48, 0x4e, 0x8c, 0x0a, 0x5c, 0x9d, 0xa8, 0x83, 0x39, 0xa0, 0xdf, 0x03, 0x52, - 0x54, 0xeb, 0xed, 0x4a, 0x1d, 0xb4, 0x01, 0xfd, 0x69, 0xa9, 0xfb, 0xa0, 0xa2, 0xc5, 0xcb, 0x90, 0xc0, 0xde, 0x90, - 0x2a, 0xa4, 0x56, 0x2d, 0xab, 0x40, 0xf1, 0x86, 0xb3, 0x78, 0x77, 0xae, 0x25, 0x1b, 0xe7, 0x25, 0x02, 0x7b, 0x65, - 0x45, 0x1d, 0x67, 0xc5, 0xa9, 0x93, 0xca, 0x1b, 0xe5, 0x24, 0x53, 0x69, 0xdf, 0xb2, 0x82, 0xba, 0x3b, 0x44, 0xdf, - 0x22, 0xf5, 0x61, 0xf0, 0x22, 0xac, 0xc9, 0x8c, 0xf7, 0xfb, 0x62, 0x26, 0xa2, 0x62, 0x56, 0x1d, 0x16, 0x91, 0x44, - 0x68, 0xdb, 0x27, 0x02, 0x7a, 0x50, 0x02, 0xe4, 0x0a, 0x80, 0xea, 0x87, 0x84, 0x3f, 0x0f, 0x49, 0x7d, 0x3a, 0x85, - 0x3e, 0xa5, 0xb2, 0x5e, 0x71, 0x0a, 0xaa, 0x1b, 0x6f, 0x64, 0xbd, 0x0a, 0x5a, 0x3c, 0x96, 0x63, 0xb5, 0xa1, 0x6d, - 0x4e, 0x8d, 0x77, 0xbd, 0xde, 0x60, 0xd2, 0xe6, 0x42, 0xae, 0xc2, 0x90, 0x44, 0xb7, 0x85, 0x13, 0x3e, 0xc4, 0x60, - 0x65, 0xb5, 0x36, 0xbf, 0x8e, 0xfd, 0x91, 0x15, 0x29, 0xee, 0x67, 0x43, 0x9c, 0xbb, 0x78, 0x3c, 0xa7, 0xfa, 0x46, - 0x49, 0x8b, 0x74, 0x9b, 0xef, 0xd5, 0x65, 0x48, 0x51, 0x51, 0x4d, 0x1a, 0x55, 0x66, 0xd0, 0x7d, 0xdb, 0xbc, 0x55, - 0x3d, 0xc2, 0x04, 0x78, 0xa5, 0x32, 0xa8, 0x46, 0xe3, 0x81, 0x58, 0xd5, 0xa3, 0x72, 0x5d, 0x14, 0x88, 0x36, 0x0c, - 0x39, 0x66, 0x86, 0x90, 0x64, 0x7f, 0xf1, 0xef, 0x64, 0x70, 0x85, 0x32, 0xbe, 0xd5, 0x70, 0xde, 0xb5, 0xf1, 0xec, - 0x6e, 0x22, 0x37, 0x27, 0x16, 0xd6, 0xb8, 0x0f, 0xfe, 0x51, 0xab, 0x9d, 0x05, 0x94, 0x35, 0xad, 0x6a, 0x38, 0xdc, - 0xa3, 0x3a, 0x16, 0xa5, 0x06, 0x24, 0x76, 0xc8, 0x72, 0xd9, 0x3a, 0x66, 0xd0, 0x80, 0xfe, 0x2e, 0xbb, 0x5e, 0x5f, - 0x23, 0x6a, 0x5b, 0x81, 0xac, 0x93, 0x90, 0xfe, 0x25, 0xed, 0x51, 0x57, 0xf6, 0x54, 0xee, 0xb7, 0x6d, 0xaa, 0x1c, - 0x1a, 0x20, 0x79, 0xec, 0xe6, 0x2c, 0x90, 0x1d, 0x09, 0xa2, 0x40, 0x6e, 0xbd, 0x60, 0xea, 0x9c, 0x32, 0x65, 0x07, - 0xf2, 0x73, 0xa9, 0xcf, 0xb0, 0xcf, 0x38, 0x62, 0xf4, 0x52, 0x89, 0xc1, 0xd4, 0x47, 0x1b, 0xd5, 0xb4, 0x56, 0x80, - 0xaa, 0x9f, 0x6e, 0xe0, 0x4f, 0x54, 0x36, 0x68, 0xa8, 0x35, 0x12, 0x85, 0xa4, 0x89, 0x12, 0x3a, 0x96, 0x96, 0x2a, - 0x98, 0x42, 0x27, 0x91, 0x30, 0x04, 0x34, 0x4c, 0x88, 0x4a, 0x2a, 0xf1, 0xd6, 0x00, 0xce, 0x7c, 0xbc, 0xa8, 0xd6, - 0xa5, 0x32, 0x98, 0xfb, 0x21, 0xbe, 0xe1, 0xaf, 0x9e, 0x5b, 0xa3, 0xfa, 0x96, 0xb5, 0xbe, 0xa3, 0x05, 0xf9, 0x21, - 0xe4, 0x14, 0x1d, 0x98, 0xd8, 0xc9, 0x06, 0x0f, 0xe6, 0xa2, 0x51, 0xa1, 0x2e, 0xde, 0xaa, 0xf8, 0x2b, 0xca, 0x04, - 0xef, 0x01, 0x4f, 0x11, 0x65, 0x78, 0x58, 0x69, 0xab, 0x6a, 0x7c, 0x2a, 0x58, 0x4b, 0x0f, 0x56, 0xf2, 0x74, 0x9d, - 0xf0, 0x10, 0xf4, 0x48, 0x84, 0x9d, 0x84, 0xe5, 0x3c, 0x5e, 0xc0, 0x71, 0x52, 0x12, 0x50, 0x3b, 0xa8, 0x2b, 0xf8, - 0x7c, 0x81, 0xee, 0xaf, 0x02, 0x3d, 0xc0, 0xd0, 0x82, 0xd8, 0x0f, 0x7d, 0x3a, 0xba, 0x8e, 0x57, 0x9e, 0x8a, 0x84, - 0xcf, 0x4b, 0xb0, 0x1d, 0x92, 0xea, 0x29, 0xd0, 0x42, 0x25, 0x52, 0x3f, 0x0c, 0x7c, 0x87, 0x02, 0xbe, 0x56, 0x3a, - 0x40, 0x4d, 0x3f, 0x63, 0x9a, 0x1a, 0x67, 0xa8, 0x7c, 0xe6, 0xdc, 0x33, 0xa3, 0xe5, 0xcc, 0x80, 0x31, 0xa8, 0xdb, - 0x68, 0x8a, 0xe2, 0x9c, 0x7c, 0x16, 0x94, 0x71, 0x9a, 0xc5, 0x39, 0xf8, 0x6d, 0xc6, 0x25, 0x66, 0x4c, 0xe2, 0x9a, - 0x5f, 0x89, 0x12, 0xb4, 0xdd, 0xb9, 0x4c, 0x6d, 0x1a, 0x10, 0x90, 0xfd, 0x00, 0x56, 0x2f, 0x9e, 0x8e, 0xca, 0x7a, - 0x77, 0x29, 0x53, 0x88, 0xb2, 0x0a, 0xc1, 0xa6, 0x99, 0x2e, 0xd9, 0x69, 0x28, 0xb5, 0x39, 0x10, 0xdf, 0x08, 0x8d, - 0xfb, 0xa7, 0x61, 0x6c, 0x34, 0xc5, 0xc6, 0xee, 0x6d, 0xbb, 0xfd, 0xad, 0x70, 0xd2, 0x69, 0x4e, 0x7a, 0x8c, 0xfd, - 0x56, 0x84, 0xe5, 0xc8, 0x74, 0x84, 0xc0, 0x92, 0x73, 0x3e, 0x75, 0x5f, 0xd1, 0x62, 0x9e, 0x80, 0xe9, 0x88, 0x8a, - 0x90, 0x0b, 0x94, 0x1d, 0xa3, 0xb8, 0x03, 0x83, 0x0b, 0x66, 0x42, 0x10, 0x4b, 0x4f, 0x5d, 0x48, 0x96, 0x24, 0x65, - 0xf0, 0x3c, 0x75, 0x30, 0xe0, 0xd7, 0x4c, 0x9a, 0xbb, 0x48, 0xeb, 0xd3, 0x25, 0x99, 0xa6, 0xc8, 0x40, 0xac, 0xc3, - 0x4d, 0x96, 0x46, 0x89, 0x14, 0x91, 0x2d, 0xd1, 0x3f, 0x52, 0x53, 0x2c, 0x15, 0xae, 0x17, 0xa9, 0x12, 0xa1, 0xd5, - 0x3c, 0xc5, 0x93, 0x3a, 0x6d, 0xd2, 0x11, 0xc6, 0x9b, 0x04, 0xa5, 0x5c, 0x03, 0x03, 0x55, 0x50, 0xb5, 0x14, 0x36, - 0xe5, 0x76, 0xab, 0x2e, 0x56, 0xd5, 0x3c, 0x5e, 0xe0, 0xcb, 0x0a, 0x47, 0xf1, 0xef, 0xdc, 0x89, 0x35, 0x25, 0xb7, - 0x07, 0x35, 0x23, 0x4a, 0xe8, 0xdf, 0x39, 0x5c, 0x24, 0xbe, 0x13, 0x2a, 0xee, 0x1f, 0x5a, 0x84, 0x9c, 0xcb, 0x83, - 0x54, 0x73, 0x43, 0x3b, 0xc2, 0x7f, 0xcd, 0xf5, 0x69, 0x67, 0x74, 0x5f, 0xcd, 0xa8, 0xf0, 0x7b, 0x1d, 0x3c, 0x63, - 0xd4, 0x67, 0x03, 0x87, 0x15, 0xa2, 0xd0, 0x86, 0x9d, 0x14, 0x52, 0xb4, 0x30, 0x14, 0xf2, 0x2f, 0xa1, 0xd5, 0x09, - 0xb7, 0x66, 0x94, 0x05, 0xe3, 0xd3, 0xe2, 0xb8, 0x9a, 0x0e, 0x06, 0x05, 0xa9, 0xb5, 0x85, 0x1e, 0x5c, 0x0f, 0x1c, - 0xff, 0x1e, 0xb8, 0x85, 0x38, 0x70, 0xc8, 0xd5, 0x90, 0x6b, 0x70, 0xfc, 0x16, 0x27, 0x57, 0x8f, 0x2a, 0x19, 0xbc, - 0x9a, 0xc8, 0x16, 0xfc, 0xbd, 0x08, 0x03, 0xf4, 0x49, 0x0a, 0xc0, 0x64, 0x30, 0xe5, 0x77, 0x20, 0x51, 0x3a, 0x97, - 0x37, 0xa4, 0x5f, 0x8a, 0x92, 0x5f, 0xf2, 0x92, 0x17, 0x89, 0x2d, 0xc0, 0xf0, 0x0e, 0xa6, 0xd7, 0x51, 0x4d, 0x25, - 0x10, 0xaf, 0xee, 0x71, 0xc4, 0xb5, 0xf7, 0x9f, 0xee, 0xb1, 0x01, 0x6a, 0x35, 0x8e, 0x0d, 0x2e, 0x73, 0x0c, 0x2e, - 0xe8, 0x4a, 0x62, 0xab, 0xa9, 0x86, 0x11, 0x81, 0x81, 0x0b, 0x38, 0x08, 0x4b, 0x24, 0xc7, 0x56, 0xf1, 0x9a, 0x78, - 0x52, 0xda, 0x07, 0x86, 0xa3, 0x4d, 0x72, 0x5c, 0x9b, 0x65, 0x3b, 0x81, 0xf3, 0x45, 0xe7, 0xa4, 0xe9, 0x58, 0x36, - 0x78, 0x9f, 0xd7, 0xe7, 0xd7, 0xfe, 0x21, 0xa1, 0x32, 0xd8, 0x0d, 0x6f, 0x07, 0xbb, 0xb1, 0xc2, 0xaf, 0x79, 0xb5, - 0x50, 0xf1, 0x59, 0xf4, 0x25, 0xcb, 0x6d, 0xad, 0x73, 0x4b, 0x12, 0x4a, 0x01, 0xed, 0xb2, 0x2c, 0xa8, 0x89, 0x00, - 0x74, 0x3f, 0xfc, 0x05, 0x42, 0x67, 0xf8, 0xdb, 0x63, 0x70, 0x45, 0x0a, 0xf7, 0x0e, 0x41, 0x65, 0x4c, 0x37, 0x77, - 0x6a, 0x03, 0xbe, 0x18, 0xf7, 0x67, 0x4c, 0x1d, 0xfd, 0x36, 0x13, 0xbb, 0xba, 0x6e, 0x87, 0x2c, 0xc3, 0x47, 0xb8, - 0x52, 0x00, 0x2c, 0x13, 0xfe, 0x62, 0x6c, 0x49, 0xf9, 0x09, 0xc0, 0xa9, 0xa9, 0x88, 0x3e, 0x41, 0xa0, 0xe1, 0x94, - 0x68, 0x39, 0xba, 0x91, 0x8e, 0x68, 0x1a, 0x69, 0x4d, 0xb5, 0x42, 0x7b, 0xeb, 0x61, 0x91, 0xd6, 0x34, 0x9c, 0xb8, - 0x0f, 0x8a, 0x79, 0x95, 0x40, 0x00, 0xad, 0x8c, 0xe0, 0xad, 0xf5, 0x51, 0x1f, 0x21, 0x2e, 0x61, 0x49, 0x14, 0x61, - 0x71, 0x4c, 0xf1, 0x63, 0x42, 0x37, 0xbe, 0xb6, 0xe9, 0x03, 0xd2, 0x5f, 0x5c, 0xb3, 0x6e, 0xca, 0xb2, 0x71, 0xed, - 0xa1, 0xe2, 0xc5, 0xd4, 0x0f, 0x7e, 0x98, 0xc8, 0x62, 0xdc, 0x2f, 0x6a, 0x57, 0x6a, 0x05, 0x30, 0xcc, 0x5d, 0xf5, - 0xf4, 0xfb, 0x7e, 0xb6, 0x1c, 0x08, 0x95, 0xdb, 0x19, 0x24, 0x7d, 0x2a, 0x9e, 0x1f, 0x1c, 0xd1, 0xca, 0x42, 0xcf, - 0x1d, 0x97, 0xc6, 0x87, 0xca, 0x6b, 0x53, 0x23, 0x5a, 0x23, 0x43, 0x65, 0xea, 0x80, 0xf5, 0xfd, 0x43, 0xb8, 0xbb, - 0xa8, 0x69, 0xa8, 0x74, 0xcf, 0x5d, 0x8b, 0x82, 0x13, 0x77, 0x80, 0xb1, 0xb8, 0x90, 0x34, 0x2a, 0x08, 0x93, 0x7a, - 0x34, 0x38, 0xc9, 0x5e, 0x5d, 0x9d, 0x9c, 0x29, 0xe6, 0x09, 0x6c, 0x54, 0xcb, 0xb6, 0xbf, 0xa2, 0x54, 0x97, 0x72, - 0x73, 0x45, 0xf1, 0x3d, 0xa4, 0xcd, 0x55, 0x9c, 0xb7, 0x05, 0x17, 0xfc, 0x33, 0x05, 0x17, 0xc6, 0xc1, 0xba, 0xe3, - 0x4e, 0xd9, 0x73, 0x45, 0x99, 0xc6, 0x06, 0x77, 0xed, 0x31, 0x26, 0xda, 0x7e, 0x77, 0xc9, 0x93, 0x8f, 0xc8, 0x82, - 0x7f, 0x97, 0x15, 0xe0, 0x99, 0x6c, 0x5f, 0xc9, 0xfc, 0x3f, 0xb8, 0x57, 0x5b, 0xf3, 0xce, 0x98, 0x7f, 0x3a, 0xd6, - 0xc3, 0x9d, 0xc3, 0xe4, 0x06, 0xe8, 0x0c, 0xe8, 0xe6, 0x5a, 0xa4, 0x1c, 0x90, 0x01, 0x8c, 0x45, 0x32, 0x1a, 0xf0, - 0xa1, 0x95, 0x65, 0xdb, 0x77, 0x5a, 0x5e, 0x10, 0xf6, 0x12, 0xb8, 0xe9, 0xfe, 0xda, 0xf4, 0xcc, 0xa9, 0x5a, 0x89, - 0xa2, 0x4b, 0x63, 0x63, 0x59, 0x2a, 0x81, 0xdd, 0xf7, 0x9e, 0x64, 0xd3, 0xfc, 0x78, 0x39, 0xcd, 0x0d, 0x75, 0xdb, - 0xd8, 0x65, 0x03, 0x40, 0x88, 0x5d, 0x6b, 0x2b, 0x07, 0x90, 0xdc, 0x1e, 0x84, 0xf0, 0x35, 0x22, 0xf4, 0x54, 0x8a, - 0xd0, 0xa7, 0xa9, 0xdf, 0x07, 0xb3, 0xaa, 0xd6, 0x5e, 0x9c, 0xa3, 0x41, 0xaa, 0x18, 0xf9, 0xb7, 0x37, 0xbc, 0xbc, - 0xcc, 0xc5, 0x2d, 0x60, 0x20, 0x93, 0x46, 0x2b, 0x2c, 0xaf, 0xc1, 0x9d, 0x1f, 0x1d, 0xc7, 0x19, 0xc0, 0x26, 0x41, - 0xb0, 0x56, 0x84, 0x47, 0x56, 0x89, 0x33, 0x00, 0x41, 0x76, 0x27, 0x4d, 0xc5, 0x73, 0x2d, 0x31, 0xa6, 0x2f, 0x70, - 0x57, 0x39, 0x3b, 0xd9, 0xe4, 0x66, 0xd1, 0xfb, 0x33, 0xac, 0x3a, 0x52, 0x19, 0x1b, 0x8b, 0xae, 0x3b, 0x58, 0x6b, - 0x06, 0x4d, 0x11, 0x52, 0x3e, 0x64, 0x4f, 0xda, 0xbf, 0x02, 0x1a, 0x9c, 0x67, 0xe9, 0x9d, 0xb1, 0xca, 0xdf, 0x28, - 0x21, 0x4e, 0x14, 0x53, 0x2b, 0xbe, 0x89, 0x12, 0x75, 0x7e, 0x26, 0xda, 0x0d, 0x04, 0x52, 0x7f, 0xc0, 0xa0, 0x1a, - 0x65, 0x98, 0xc0, 0x75, 0x20, 0x8a, 0xcd, 0x89, 0xea, 0x2d, 0x47, 0xd0, 0x09, 0x21, 0xde, 0x01, 0x50, 0xef, 0xd8, - 0xfa, 0x08, 0x68, 0x96, 0xbe, 0x69, 0xad, 0x73, 0x4d, 0x28, 0xb4, 0x13, 0x98, 0x64, 0x90, 0xe4, 0x59, 0x67, 0x98, - 0xa0, 0xda, 0x8c, 0x49, 0xe7, 0x7d, 0x80, 0xee, 0xae, 0x45, 0x5d, 0x7c, 0xd3, 0xb9, 0x83, 0xf6, 0x71, 0xfd, 0x4a, - 0x8b, 0xec, 0xf1, 0xe7, 0x2d, 0x11, 0x16, 0x81, 0xb3, 0x56, 0xe7, 0xab, 0x47, 0x38, 0x30, 0x15, 0x99, 0x86, 0xbd, - 0x44, 0x2a, 0x59, 0xb6, 0xdb, 0x5e, 0x6f, 0xaf, 0x88, 0xab, 0xc7, 0x58, 0xed, 0xdc, 0xcc, 0xcd, 0x9d, 0x6a, 0x5d, - 0xec, 0xde, 0xb4, 0xdd, 0x14, 0x33, 0x6a, 0xad, 0xdd, 0xae, 0x39, 0x21, 0x4f, 0xbe, 0x15, 0xd5, 0x4a, 0x9d, 0xae, - 0x0d, 0xda, 0x21, 0x9e, 0x75, 0x91, 0xc1, 0x8d, 0xf2, 0xb9, 0x15, 0x3a, 0xc9, 0x38, 0xab, 0x56, 0x5d, 0xb0, 0xb9, - 0xe6, 0xf5, 0x52, 0xa4, 0x51, 0x45, 0xd1, 0xe6, 0x3c, 0x2a, 0x68, 0x22, 0xd6, 0x45, 0x1d, 0x89, 0x06, 0xf5, 0xa2, - 0x46, 0x63, 0x80, 0x80, 0x4c, 0xe7, 0xbe, 0x07, 0x55, 0x30, 0x1b, 0x8a, 0x48, 0x4c, 0xdf, 0x83, 0xa5, 0x7d, 0x01, - 0xfb, 0xa2, 0xd9, 0x57, 0x67, 0x8b, 0x6f, 0x75, 0x84, 0x60, 0x12, 0xb3, 0x07, 0xc2, 0xc0, 0xf9, 0xc6, 0x90, 0xd3, - 0x2e, 0x71, 0x99, 0xef, 0x96, 0xb0, 0x87, 0xdb, 0x15, 0xec, 0xc4, 0xce, 0x93, 0xe2, 0xe6, 0x4a, 0x76, 0x52, 0xce, - 0xc7, 0xa0, 0xfd, 0x12, 0xf2, 0xda, 0xa5, 0xb8, 0xf5, 0x78, 0x10, 0xd0, 0x60, 0x50, 0x6a, 0xfe, 0x75, 0xa2, 0x3d, - 0x3c, 0x69, 0x40, 0x90, 0x94, 0x83, 0x8b, 0xb6, 0x63, 0xf8, 0x3e, 0x99, 0x8a, 0x63, 0x8e, 0x16, 0xef, 0xd0, 0xea, - 0x04, 0xa2, 0x78, 0x81, 0xbd, 0x9b, 0x56, 0x15, 0x6a, 0x11, 0x94, 0xa3, 0xe5, 0x2f, 0x64, 0x75, 0x08, 0x28, 0xa4, - 0x7c, 0x45, 0xa1, 0x6c, 0x9d, 0x18, 0xea, 0xe1, 0x17, 0xf3, 0xc9, 0x42, 0xcd, 0xc0, 0x40, 0xcc, 0x8f, 0x16, 0x6a, - 0x16, 0x06, 0x62, 0xfe, 0xd5, 0xa2, 0xb1, 0xeb, 0x40, 0x11, 0x10, 0xc7, 0x85, 0xa3, 0x93, 0xd2, 0xca, 0x6c, 0x01, - 0xdd, 0x3c, 0x44, 0xd0, 0xff, 0x6e, 0x0e, 0x41, 0x2b, 0x17, 0xda, 0x91, 0x1b, 0xd0, 0x76, 0x1c, 0x02, 0x73, 0xc5, - 0xa4, 0x95, 0x0e, 0x40, 0x74, 0xcc, 0xc6, 0x60, 0x88, 0x2d, 0x3f, 0x38, 0x66, 0xe3, 0xa9, 0x4b, 0x82, 0x80, 0xd1, - 0xfd, 0x41, 0x43, 0x82, 0xdf, 0xe1, 0x55, 0xfa, 0x64, 0x83, 0xbe, 0x66, 0xce, 0xdd, 0xd0, 0xb9, 0xb8, 0x82, 0x53, - 0xb5, 0xbd, 0x27, 0xa1, 0x9b, 0x4c, 0x3b, 0x40, 0xaf, 0x26, 0x6e, 0xc8, 0xaf, 0x8c, 0x46, 0xa3, 0x62, 0x64, 0x00, - 0x20, 0x88, 0xe6, 0x1c, 0xfc, 0x9c, 0x86, 0xcb, 0x97, 0xb7, 0x9e, 0x4d, 0x31, 0x02, 0x5a, 0xc8, 0x44, 0xf3, 0x00, - 0x65, 0x55, 0x63, 0x68, 0x86, 0xde, 0x21, 0xc7, 0x0f, 0x0f, 0xbe, 0xce, 0xf8, 0x89, 0xc3, 0xb5, 0x87, 0x73, 0xe1, - 0xba, 0xac, 0x69, 0x99, 0x43, 0xe7, 0xd9, 0xc7, 0xf1, 0x1e, 0xc6, 0xc9, 0xa7, 0x59, 0x28, 0x67, 0xbc, 0xa6, 0xff, - 0x51, 0xe9, 0x7e, 0x87, 0x43, 0x4e, 0x57, 0xb0, 0xe2, 0x66, 0x75, 0xa8, 0xf9, 0x59, 0xe4, 0x8d, 0x23, 0xde, 0x90, - 0xa8, 0xee, 0x3e, 0xef, 0x4d, 0x98, 0xd2, 0x8e, 0x71, 0x00, 0x70, 0xa2, 0x56, 0x0d, 0xbb, 0xd2, 0xb8, 0x56, 0x07, - 0x31, 0x0c, 0x25, 0x6c, 0x95, 0x38, 0xaa, 0xa4, 0xbf, 0x01, 0x08, 0x8b, 0xa1, 0x38, 0xde, 0x1a, 0xd6, 0x07, 0xd8, - 0x0f, 0x55, 0xa0, 0x6e, 0x4e, 0x21, 0x67, 0x00, 0x90, 0x04, 0xdc, 0xd1, 0x53, 0x4d, 0x43, 0x65, 0x9b, 0xe3, 0xa1, - 0x65, 0x74, 0x05, 0x0f, 0xf4, 0xd4, 0x96, 0x0c, 0x8c, 0xab, 0x3c, 0xf6, 0x36, 0xfb, 0xdb, 0xa3, 0x54, 0xe4, 0x3b, - 0x9b, 0xd4, 0x34, 0xab, 0x46, 0x63, 0x1f, 0x47, 0xe8, 0x69, 0x05, 0x68, 0xbd, 0xb6, 0x54, 0xb4, 0xdf, 0x47, 0x31, - 0x6a, 0x5c, 0x4a, 0xb0, 0x0a, 0x1d, 0x09, 0x0e, 0x11, 0x46, 0x08, 0xfd, 0xbe, 0x08, 0x37, 0xae, 0x20, 0x83, 0x28, - 0xb8, 0x16, 0x15, 0x7f, 0xc8, 0xf2, 0xa2, 0x6d, 0xa9, 0xaa, 0x3e, 0x69, 0xda, 0x12, 0x78, 0x1d, 0x0e, 0xb0, 0x9d, - 0x7f, 0xea, 0x89, 0x5c, 0x2b, 0x1b, 0x25, 0x7c, 0x47, 0x5c, 0x0b, 0xa2, 0x9b, 0x46, 0xd7, 0xeb, 0xd9, 0x21, 0x5a, - 0x9a, 0xe2, 0xd0, 0x21, 0xfb, 0xdc, 0x3d, 0xb7, 0x65, 0x7c, 0xfb, 0x09, 0x72, 0xe7, 0x3b, 0x7b, 0x49, 0xc2, 0x20, - 0x6f, 0xd9, 0x40, 0xb1, 0x8e, 0xad, 0xa0, 0x00, 0xa3, 0xb6, 0xfc, 0x05, 0x74, 0x6c, 0x30, 0xa8, 0x09, 0x3e, 0x49, - 0x6c, 0x1b, 0x8f, 0xfc, 0x11, 0xe7, 0x86, 0x0e, 0xaf, 0x0d, 0x79, 0x20, 0x4e, 0x61, 0x9f, 0x28, 0x61, 0xff, 0x82, - 0x82, 0xee, 0x48, 0x2f, 0x57, 0x89, 0xab, 0xe2, 0x01, 0xaa, 0xec, 0x78, 0xae, 0xf9, 0x92, 0x16, 0x5a, 0x69, 0x64, - 0x15, 0x1d, 0x11, 0xb7, 0x60, 0x32, 0x66, 0xab, 0x6a, 0x54, 0x71, 0x2c, 0x50, 0xa4, 0x63, 0xce, 0x76, 0x0e, 0xd6, - 0x00, 0x78, 0x0a, 0x9b, 0x8b, 0x33, 0x2c, 0x28, 0xed, 0xb2, 0xa5, 0x2f, 0x81, 0x55, 0xf3, 0x30, 0xce, 0xcb, 0x8e, - 0x2f, 0x77, 0x47, 0xdb, 0x7b, 0xe8, 0x8d, 0xe8, 0x8d, 0xd7, 0xe7, 0x51, 0xd3, 0xcf, 0x9e, 0xe1, 0xda, 0x50, 0x90, - 0x07, 0x9a, 0xea, 0x10, 0x46, 0x8b, 0xc0, 0x34, 0xe5, 0x27, 0x6c, 0x3c, 0x1d, 0x0e, 0x35, 0x19, 0x74, 0x9a, 0x89, - 0xf1, 0xbf, 0x3e, 0x83, 0xd6, 0xe9, 0x89, 0xf3, 0x3e, 0x6d, 0x5f, 0x41, 0xeb, 0x3b, 0x94, 0xc9, 0x9d, 0x83, 0xe1, - 0x03, 0x2d, 0x98, 0x84, 0xa9, 0xc2, 0x1b, 0x22, 0x15, 0xec, 0xcd, 0xd2, 0x38, 0xec, 0x9b, 0x85, 0x42, 0x4b, 0x45, - 0xfc, 0x6a, 0x4d, 0xfc, 0xe4, 0x75, 0xe6, 0xdf, 0xa6, 0x7d, 0x72, 0x10, 0x4b, 0x43, 0x62, 0x24, 0xe2, 0x17, 0xa7, - 0xd2, 0x76, 0x42, 0x05, 0xc4, 0x43, 0xd7, 0xba, 0x71, 0x24, 0x64, 0xec, 0x49, 0x8d, 0xa7, 0x86, 0xfb, 0x5e, 0xc7, - 0xac, 0xc3, 0x2c, 0x76, 0xb3, 0x46, 0x42, 0x61, 0x9c, 0x9a, 0xe0, 0x94, 0x62, 0x15, 0xc9, 0xe8, 0x78, 0xa6, 0x30, - 0x88, 0x2a, 0x29, 0x21, 0xd6, 0x94, 0xad, 0x85, 0x89, 0x5d, 0x67, 0x0b, 0x53, 0xd4, 0x45, 0xa8, 0x37, 0x03, 0x9d, - 0x05, 0x0d, 0xf9, 0x1d, 0x1a, 0xad, 0xa8, 0x9a, 0x04, 0x0c, 0xe3, 0x28, 0xd5, 0xf8, 0xb7, 0x08, 0xb5, 0x1e, 0x06, - 0x00, 0xb6, 0x79, 0x27, 0xb2, 0xa2, 0x7e, 0x55, 0x20, 0x04, 0x9a, 0xb5, 0x9f, 0x2a, 0xeb, 0x9d, 0x59, 0xd0, 0x8a, - 0x76, 0x73, 0xe5, 0x73, 0x81, 0x13, 0xaa, 0x53, 0x79, 0x81, 0x7a, 0x29, 0xca, 0xd7, 0x22, 0xe5, 0xad, 0xb8, 0x98, - 0x07, 0x82, 0x7d, 0xc8, 0x47, 0x70, 0x5e, 0xa1, 0x53, 0xb9, 0xde, 0x26, 0xd2, 0x2c, 0x49, 0x30, 0x16, 0x68, 0x9b, - 0x97, 0x60, 0x26, 0x14, 0x33, 0x86, 0x5f, 0x43, 0x70, 0xb1, 0x9d, 0x93, 0x70, 0xb3, 0x9f, 0x07, 0x86, 0xd0, 0xe4, - 0x55, 0x4b, 0x34, 0x6c, 0xec, 0x78, 0x1d, 0xb9, 0x26, 0xdc, 0x87, 0xb5, 0x58, 0x93, 0x31, 0xc6, 0x95, 0xb9, 0x91, - 0xf1, 0xa3, 0x05, 0x1e, 0x8c, 0x49, 0xeb, 0x4f, 0x20, 0xd3, 0x52, 0xca, 0x3a, 0x5f, 0x68, 0x31, 0x93, 0x4c, 0x74, - 0x6e, 0xdf, 0xf8, 0x2c, 0xef, 0x22, 0xf2, 0xb7, 0xf2, 0x7b, 0x92, 0x0f, 0xf7, 0xee, 0x83, 0xc4, 0x1a, 0x94, 0x46, - 0x5c, 0x5a, 0x94, 0xa7, 0x0f, 0x74, 0xdd, 0xa4, 0x88, 0xd3, 0xf3, 0x55, 0x5c, 0x56, 0x3c, 0x85, 0x4a, 0x15, 0x75, - 0x8b, 0x7a, 0x13, 0xb0, 0x37, 0x44, 0x92, 0x64, 0x2c, 0x8d, 0x8d, 0xd8, 0xc5, 0x23, 0x3d, 0x7b, 0xc3, 0x2c, 0xbd, - 0xac, 0xd1, 0x90, 0x96, 0x3a, 0x67, 0xa1, 0x94, 0xf9, 0x4b, 0xfe, 0x33, 0x68, 0x24, 0xe8, 0xa8, 0x4f, 0x31, 0x9e, - 0x01, 0x23, 0xbe, 0x1b, 0xc1, 0xea, 0x01, 0xe2, 0xa2, 0x08, 0x4a, 0xb3, 0x23, 0x76, 0xfc, 0xd4, 0xe4, 0xe1, 0x5d, - 0xc8, 0x3a, 0x83, 0x4f, 0x1f, 0x66, 0x89, 0x5a, 0xeb, 0xa8, 0x1a, 0xc9, 0x19, 0x40, 0xd3, 0x41, 0x91, 0xf3, 0xb8, - 0x08, 0x66, 0x3d, 0x9d, 0x18, 0xf5, 0xb8, 0xfa, 0x05, 0x1a, 0x6a, 0xb7, 0x59, 0x59, 0x9e, 0xd5, 0xf7, 0x9f, 0xc3, - 0x81, 0x4d, 0x4d, 0x05, 0x3d, 0xde, 0xd4, 0xe2, 0xea, 0x4a, 0x76, 0xdb, 0x2d, 0x44, 0xcb, 0xe9, 0xbc, 0x6b, 0xe9, - 0xbc, 0x5e, 0xb0, 0x5e, 0x77, 0xba, 0x5e, 0xdc, 0x7e, 0x19, 0x1e, 0xc2, 0xda, 0xce, 0x27, 0x8a, 0x3f, 0xf3, 0xdb, - 0xee, 0xe2, 0x2d, 0x54, 0xb3, 0x00, 0x00, 0xd2, 0x83, 0x28, 0x58, 0x66, 0x29, 0x0f, 0xa8, 0xd8, 0xc7, 0x51, 0x96, - 0x52, 0x2f, 0x67, 0x18, 0x3f, 0x65, 0x1a, 0x6b, 0x9c, 0x15, 0xaa, 0xd0, 0xd8, 0xe8, 0x4e, 0x57, 0x19, 0x62, 0xfb, - 0x09, 0x9c, 0x2d, 0xc0, 0xfd, 0xd1, 0x43, 0xa1, 0xee, 0x4d, 0x5a, 0x9a, 0xa8, 0xf9, 0xae, 0x3d, 0x83, 0x8c, 0xe2, - 0x64, 0x95, 0x57, 0xd0, 0x8d, 0x3a, 0x6b, 0xa3, 0x4a, 0xdf, 0x43, 0xd4, 0xab, 0x18, 0x3c, 0xca, 0x5d, 0x5e, 0x1b, - 0x9d, 0x4c, 0x8b, 0x48, 0xb9, 0xf3, 0x93, 0x66, 0x99, 0xa5, 0x4a, 0x87, 0xed, 0x32, 0xec, 0xad, 0x31, 0xe9, 0x4d, - 0x48, 0x03, 0x23, 0xf1, 0xe9, 0x8c, 0x0a, 0x21, 0xa0, 0x2d, 0xc7, 0xdf, 0xe1, 0x33, 0x34, 0x4d, 0x81, 0xa5, 0x8a, - 0x5b, 0xd8, 0x0e, 0x9f, 0xff, 0x64, 0xd4, 0x02, 0x10, 0xc1, 0xca, 0xd5, 0xbb, 0x38, 0x25, 0x34, 0xe7, 0xca, 0x0c, - 0x00, 0x59, 0x50, 0xca, 0x2d, 0x3f, 0x25, 0xd3, 0xc1, 0x12, 0x45, 0xd9, 0xcb, 0xa9, 0x1b, 0x1d, 0x1b, 0x3f, 0xa4, - 0xe7, 0x02, 0xb6, 0x0b, 0xf9, 0xad, 0xbd, 0x7a, 0x89, 0x9a, 0x34, 0xa6, 0x59, 0x0f, 0xf0, 0xe5, 0x1a, 0x4d, 0x42, - 0x0b, 0xca, 0xa4, 0x29, 0x80, 0xc6, 0x4d, 0xd5, 0x0a, 0x26, 0xa5, 0x46, 0xc2, 0x96, 0x3a, 0x92, 0x65, 0xdf, 0x07, - 0xa7, 0xde, 0x23, 0xe8, 0x01, 0xf3, 0x08, 0xf4, 0xf4, 0x5f, 0xba, 0x6a, 0xff, 0x92, 0xa3, 0x93, 0xab, 0x26, 0x6a, - 0xfa, 0xbd, 0xb2, 0x23, 0x43, 0xca, 0xa5, 0x19, 0x08, 0x26, 0x1d, 0xf3, 0xd4, 0xd8, 0x3a, 0x46, 0x44, 0x0f, 0x9c, - 0x7d, 0xba, 0x5b, 0x4d, 0x2d, 0x00, 0xd1, 0xf1, 0xeb, 0x27, 0xaf, 0xae, 0xe3, 0x2b, 0x8d, 0xa2, 0xe4, 0x59, 0xc4, - 0x48, 0xd3, 0xbe, 0x5a, 0xc0, 0xe0, 0xfd, 0xf2, 0xfe, 0x27, 0x99, 0xa5, 0x71, 0x7b, 0xb0, 0x31, 0xa2, 0xaa, 0x5f, - 0x2a, 0x5e, 0xfa, 0x02, 0xac, 0x7d, 0x96, 0x28, 0x90, 0xfb, 0xbd, 0x49, 0xd3, 0xdf, 0x44, 0xde, 0xcd, 0x86, 0xf5, - 0xc6, 0x4d, 0xbb, 0xd4, 0x96, 0xec, 0xc8, 0x48, 0xe4, 0xf4, 0x62, 0xd0, 0xe3, 0x47, 0x2b, 0x8d, 0xd2, 0xb0, 0x41, - 0x55, 0x2a, 0x7e, 0xaf, 0x45, 0x70, 0xf2, 0x58, 0x95, 0x18, 0xd3, 0x80, 0xd9, 0x56, 0x36, 0x0a, 0xd4, 0x41, 0x2a, - 0x6d, 0x75, 0x14, 0xb6, 0xdf, 0x58, 0x49, 0xf5, 0xef, 0x7f, 0x6a, 0x43, 0x3e, 0x5f, 0x0a, 0x2a, 0x08, 0xd8, 0x19, - 0x78, 0x3d, 0x95, 0xc2, 0x40, 0x2a, 0xd8, 0x49, 0x05, 0x28, 0x5f, 0x44, 0x8e, 0xd5, 0x6e, 0x5f, 0xad, 0x1a, 0xa3, - 0x2d, 0x20, 0x34, 0x90, 0x1e, 0x5d, 0xf6, 0x71, 0x1b, 0xe3, 0x40, 0xe2, 0xc0, 0x09, 0xb6, 0x73, 0x75, 0x8d, 0x46, - 0x42, 0xf3, 0x87, 0x46, 0x03, 0x5e, 0xd3, 0x1a, 0x14, 0xea, 0x39, 0x8e, 0x86, 0xca, 0x0e, 0x29, 0x88, 0xd8, 0xa0, - 0x84, 0x7d, 0x7b, 0x3e, 0xd4, 0xfb, 0x7a, 0x9e, 0x2c, 0x48, 0x43, 0x85, 0xfd, 0xdc, 0x2e, 0x21, 0x63, 0xd5, 0x21, - 0xad, 0x3c, 0xc0, 0xf1, 0x42, 0xca, 0xfc, 0x2d, 0x26, 0x35, 0x4a, 0x63, 0x42, 0x6d, 0xc4, 0x02, 0x96, 0x04, 0xed, - 0xf5, 0x40, 0xdd, 0x32, 0x08, 0x75, 0x4c, 0x4f, 0x04, 0x3e, 0xa5, 0x5c, 0x7e, 0x5a, 0x92, 0x66, 0x5a, 0x32, 0x0b, - 0x7a, 0xe9, 0x5a, 0xf9, 0x15, 0xde, 0x47, 0xbb, 0x7b, 0x57, 0x5f, 0x58, 0xc7, 0x10, 0x0c, 0xbb, 0x72, 0x9b, 0xd3, - 0x50, 0x00, 0x36, 0x3c, 0x55, 0x65, 0xb9, 0x46, 0x4d, 0x64, 0x16, 0x87, 0x24, 0x02, 0xc9, 0xb6, 0xbf, 0xb9, 0xb5, - 0x60, 0xdb, 0x59, 0xa8, 0x9e, 0xfa, 0xcb, 0xd9, 0xee, 0x7b, 0x86, 0x97, 0x3b, 0x72, 0x6f, 0xdf, 0x86, 0xf2, 0x87, - 0xfd, 0xab, 0xe4, 0xff, 0xaa, 0x92, 0xfd, 0x56, 0x99, 0x4d, 0x5b, 0xbc, 0xdf, 0x75, 0xdc, 0x72, 0x8c, 0x06, 0x81, - 0x35, 0x05, 0x1a, 0xd2, 0x93, 0xc6, 0x34, 0x51, 0x21, 0x95, 0x19, 0xd3, 0x78, 0x74, 0x01, 0x9a, 0xc3, 0x74, 0x9e, - 0xc7, 0x00, 0x1c, 0xe0, 0x1e, 0x79, 0x84, 0xba, 0xa7, 0xf3, 0x3c, 0x38, 0x0f, 0x06, 0xc5, 0x20, 0x50, 0x9f, 0xd8, - 0xe6, 0x04, 0x0b, 0xd0, 0xb9, 0xc5, 0x0c, 0x82, 0x4d, 0x1a, 0x33, 0x87, 0xf8, 0x38, 0x99, 0x0e, 0x06, 0x31, 0xd9, - 0x00, 0x48, 0x5f, 0xbc, 0x30, 0xce, 0x41, 0xa5, 0x5a, 0x90, 0xad, 0xba, 0x4b, 0xbf, 0x62, 0xa7, 0xda, 0x69, 0xde, - 0xef, 0xe7, 0xf3, 0x62, 0x10, 0x78, 0x15, 0x96, 0xda, 0xfb, 0x8f, 0xfa, 0x5f, 0x6a, 0x9d, 0x34, 0xc1, 0x30, 0xb5, - 0xa7, 0xa8, 0x5e, 0x71, 0x34, 0xa3, 0xde, 0xed, 0x58, 0x2a, 0x5f, 0x40, 0x14, 0x0f, 0x0c, 0x59, 0x2b, 0xef, 0xce, - 0xc1, 0x6b, 0x73, 0xe3, 0xcd, 0x11, 0x05, 0xd8, 0xbe, 0x30, 0x4e, 0x28, 0x2e, 0xba, 0x6c, 0x88, 0x63, 0xb0, 0xd3, - 0xd5, 0x5b, 0x81, 0x56, 0xe3, 0xbd, 0x78, 0xd7, 0x6c, 0xfc, 0x8d, 0x38, 0x50, 0x65, 0x1e, 0x5c, 0x02, 0xe2, 0xec, - 0x41, 0x5c, 0x1f, 0x60, 0xa9, 0x07, 0xc1, 0xc0, 0x20, 0x87, 0xb4, 0xab, 0x55, 0x43, 0x11, 0xc9, 0xf3, 0x18, 0x0c, - 0x98, 0x74, 0x43, 0x1a, 0x32, 0xed, 0x95, 0x12, 0xd2, 0xc6, 0x58, 0x0b, 0x28, 0xc3, 0xe1, 0x6a, 0xc7, 0x6e, 0xd8, - 0x9e, 0x6e, 0x1d, 0x0a, 0x25, 0x8c, 0x5e, 0xdd, 0xf8, 0x87, 0x9a, 0xe7, 0x89, 0xa0, 0x06, 0x55, 0x6b, 0x3f, 0x1d, - 0x94, 0x27, 0xe5, 0xb1, 0x00, 0x17, 0x3d, 0x7c, 0xf9, 0xa2, 0xc0, 0x8b, 0xf6, 0x0e, 0xf2, 0x9c, 0xfe, 0x54, 0xfa, - 0x20, 0x7a, 0x6e, 0x19, 0x2e, 0xb4, 0x8f, 0x6b, 0x05, 0x32, 0x69, 0x3a, 0x9a, 0xda, 0xda, 0x1d, 0xde, 0x31, 0x81, - 0x7e, 0x53, 0x96, 0x52, 0x26, 0xba, 0x96, 0x25, 0x3b, 0xe9, 0xe5, 0xd2, 0x1b, 0x2a, 0x65, 0x27, 0xcb, 0x36, 0xe7, - 0x97, 0x7a, 0x09, 0xfd, 0xbe, 0x72, 0x07, 0xc2, 0x37, 0x72, 0xbd, 0x21, 0x2f, 0x1b, 0x22, 0x96, 0x43, 0xcc, 0xc0, - 0xf1, 0x42, 0x48, 0xd7, 0xee, 0xd2, 0x57, 0xd5, 0xed, 0x6c, 0xe5, 0x92, 0x16, 0x78, 0x2b, 0x05, 0x56, 0x91, 0x5a, - 0xbd, 0x9e, 0x4c, 0xdc, 0xf7, 0x51, 0x6c, 0x3e, 0x02, 0xb6, 0xd1, 0x3b, 0x1a, 0xbd, 0x5b, 0xc4, 0x06, 0x5f, 0x45, - 0x35, 0x2d, 0x39, 0x40, 0x70, 0xb7, 0x25, 0xb5, 0x34, 0xb3, 0x88, 0xfb, 0x92, 0x07, 0x68, 0xdf, 0xc5, 0xe1, 0x4c, - 0x2a, 0xc1, 0xb6, 0xae, 0x75, 0xce, 0x2a, 0x39, 0xa0, 0x9f, 0xe8, 0xf8, 0xa7, 0xd5, 0xa3, 0x22, 0x86, 0x55, 0x36, - 0x92, 0x56, 0x68, 0x0f, 0x4a, 0x97, 0x70, 0xf1, 0x05, 0x78, 0xd9, 0xde, 0xaf, 0xec, 0x3e, 0x5f, 0x62, 0xff, 0x30, - 0xaf, 0x9c, 0xe0, 0x91, 0xd3, 0x78, 0x73, 0x0f, 0xab, 0x3e, 0x57, 0x0a, 0xe1, 0x54, 0x4a, 0x43, 0x01, 0xc0, 0x20, - 0x09, 0x6a, 0xb8, 0xd2, 0xb6, 0x19, 0xa4, 0x34, 0x86, 0xdd, 0xad, 0xde, 0xe8, 0xff, 0x94, 0x0a, 0x17, 0xa0, 0x94, - 0x0d, 0xdc, 0x90, 0x75, 0xaa, 0xe5, 0x3a, 0xa6, 0xe0, 0xf9, 0x2e, 0x39, 0x02, 0x85, 0x1d, 0x18, 0x99, 0xd1, 0x84, - 0xfd, 0x82, 0xb7, 0xa1, 0x9c, 0xbd, 0x34, 0x92, 0x27, 0xbb, 0x2f, 0x69, 0x45, 0x13, 0x32, 0xad, 0xcc, 0xfe, 0x6d, - 0x6d, 0xd8, 0xe7, 0xa1, 0x18, 0x89, 0x02, 0x17, 0x07, 0x9d, 0x03, 0xd8, 0x1f, 0xe4, 0xd2, 0x36, 0x9f, 0x49, 0xbf, - 0x2f, 0xdf, 0x3f, 0xcb, 0xb3, 0xe4, 0xe3, 0xce, 0x7b, 0xcd, 0xd3, 0x2c, 0x19, 0x50, 0x89, 0x98, 0x1a, 0x57, 0xc5, - 0x70, 0xa9, 0x5c, 0x8c, 0x3d, 0x92, 0x11, 0xef, 0xa5, 0x0e, 0x31, 0x62, 0x7c, 0x91, 0x1d, 0x92, 0x92, 0xd3, 0x65, - 0xd3, 0xd9, 0x73, 0x25, 0x9a, 0x41, 0x63, 0xb8, 0x1d, 0xef, 0x25, 0xb5, 0x02, 0x64, 0x54, 0xe8, 0x9e, 0x01, 0xae, - 0xe1, 0xfe, 0x92, 0xf0, 0xb6, 0xf4, 0xb4, 0x25, 0x1a, 0xd8, 0x2b, 0x13, 0x12, 0x72, 0xe3, 0x00, 0x8b, 0xd8, 0x34, - 0x1f, 0x43, 0x01, 0x40, 0xad, 0x1a, 0xe9, 0x95, 0xbe, 0x24, 0x54, 0x26, 0x21, 0x18, 0x5d, 0x91, 0xf0, 0x2a, 0xa0, - 0x71, 0xa6, 0x13, 0x0d, 0x6c, 0x70, 0x40, 0x9f, 0xd7, 0x3a, 0x51, 0xdb, 0x90, 0x07, 0xb4, 0x36, 0x69, 0x00, 0x83, - 0x0f, 0x92, 0x24, 0xfa, 0x6a, 0xa9, 0x93, 0x40, 0x50, 0x82, 0xf2, 0x0d, 0xfa, 0x73, 0xe1, 0xf8, 0x58, 0x82, 0xff, - 0x91, 0x26, 0x82, 0x3f, 0x84, 0x02, 0x64, 0x8a, 0xaa, 0x62, 0x9a, 0xb1, 0x93, 0xac, 0xdb, 0x98, 0xc4, 0xf1, 0xb4, - 0xbb, 0x2b, 0xa5, 0x4b, 0x17, 0xf8, 0x95, 0x65, 0x88, 0x63, 0xfd, 0x2c, 0x5e, 0xb1, 0xd3, 0x90, 0x2b, 0xbc, 0xf4, - 0x67, 0xf1, 0x0a, 0x67, 0x88, 0xd6, 0xad, 0x04, 0x22, 0xfd, 0x57, 0x4d, 0xe0, 0x10, 0xfb, 0x09, 0x06, 0xb9, 0xa8, - 0x9d, 0x07, 0x02, 0x79, 0x5b, 0x41, 0x44, 0xfc, 0xec, 0x2a, 0x8c, 0x48, 0xbd, 0x93, 0xa4, 0xbf, 0xfc, 0x51, 0x64, - 0x85, 0xf3, 0x0d, 0x3c, 0xfa, 0xcd, 0x32, 0x29, 0xfa, 0x0b, 0x19, 0xcc, 0xc1, 0x7e, 0x22, 0xe3, 0x52, 0xd4, 0xee, - 0x13, 0x76, 0xc1, 0x89, 0xf1, 0xe0, 0xf4, 0x1a, 0x01, 0xf6, 0x6b, 0xf7, 0xc9, 0x19, 0xb3, 0xbf, 0x8c, 0x1b, 0x5f, - 0xa6, 0x23, 0x3e, 0xf0, 0xd1, 0x1d, 0xe5, 0xa3, 0x7b, 0x27, 0xd3, 0x1f, 0x1e, 0x94, 0xc8, 0xa8, 0xaa, 0xf9, 0x6a, - 0xc5, 0xd3, 0xd9, 0x5d, 0x12, 0x65, 0xa3, 0x9a, 0x17, 0x30, 0xbd, 0xe0, 0x78, 0x97, 0xac, 0x2f, 0xb2, 0xe4, 0x15, - 0xc4, 0x1e, 0x58, 0x09, 0x89, 0xc5, 0x0f, 0xcb, 0x4c, 0x2e, 0xe6, 0x42, 0xd4, 0xa2, 0xe0, 0xc1, 0xec, 0x26, 0x89, - 0xfe, 0x5a, 0x3a, 0x48, 0x6a, 0x7a, 0xca, 0x36, 0x8d, 0x25, 0xd4, 0xda, 0xd7, 0x91, 0x6e, 0x94, 0x05, 0x00, 0xdc, - 0xb3, 0x8b, 0x34, 0x12, 0xac, 0x1a, 0x4e, 0x1a, 0xc6, 0x75, 0x7a, 0x89, 0xa9, 0x71, 0xc3, 0x6a, 0x9a, 0x58, 0x0b, - 0x19, 0xd0, 0xfb, 0x03, 0x5e, 0x0e, 0x3e, 0x67, 0x45, 0x28, 0xa4, 0x35, 0x70, 0x71, 0x5c, 0xf6, 0xfb, 0xe2, 0xb8, - 0xdc, 0x6e, 0x8b, 0x93, 0xb8, 0xdf, 0x17, 0x27, 0xb1, 0xe6, 0x1f, 0xa4, 0x62, 0x5b, 0x9b, 0x1b, 0x24, 0x34, 0x17, - 0x10, 0xb5, 0x68, 0x04, 0x7f, 0x68, 0x96, 0xf3, 0x22, 0xca, 0x8f, 0x93, 0x7e, 0xbf, 0xb7, 0x9c, 0x55, 0x83, 0x7c, - 0x98, 0x44, 0xf9, 0x30, 0x71, 0x9c, 0x10, 0x7f, 0x75, 0x9c, 0x10, 0x25, 0x0d, 0x5c, 0xc1, 0x99, 0x01, 0x88, 0x02, - 0x2e, 0xfd, 0xa3, 0xaa, 0x96, 0x52, 0xd5, 0x12, 0xcb, 0x5a, 0x12, 0x55, 0x41, 0xc3, 0x6e, 0xca, 0xb0, 0xc0, 0x52, - 0xe8, 0x92, 0xfd, 0xb1, 0x04, 0x9e, 0x28, 0xe7, 0xf5, 0x06, 0x18, 0xd8, 0x08, 0xef, 0x1c, 0x3a, 0x9c, 0xc4, 0xba, - 0x61, 0x12, 0x32, 0xe9, 0x92, 0xae, 0xe8, 0x15, 0xf2, 0xb3, 0x97, 0x60, 0xb0, 0x74, 0xcc, 0xf2, 0xe9, 0x60, 0x70, - 0x49, 0x56, 0xac, 0x98, 0x87, 0xf1, 0x20, 0x5c, 0xcf, 0xf2, 0xe1, 0x65, 0x74, 0x49, 0xc8, 0x17, 0xe5, 0x82, 0xf6, - 0x56, 0xa3, 0xea, 0x63, 0x06, 0xc1, 0xfd, 0xd2, 0x59, 0x98, 0xe9, 0x38, 0x1f, 0xab, 0xd1, 0x1d, 0x5d, 0x41, 0xfc, - 0x1a, 0xb8, 0x91, 0x90, 0x08, 0x3a, 0x72, 0x45, 0x57, 0x74, 0x4d, 0x85, 0x9e, 0x61, 0x0c, 0xd1, 0x6d, 0x8e, 0x93, - 0x04, 0x1c, 0x93, 0x6d, 0xf1, 0xd1, 0x58, 0x16, 0xde, 0xf5, 0x1d, 0xa1, 0xbd, 0x5e, 0x62, 0x07, 0xe9, 0xbb, 0xf6, - 0x20, 0x01, 0x23, 0x32, 0x92, 0x03, 0xa5, 0x47, 0x46, 0x50, 0x3d, 0xa9, 0x38, 0x24, 0xb1, 0x3b, 0x24, 0x72, 0x1c, - 0x12, 0x77, 0x1c, 0x72, 0x35, 0x0e, 0xc8, 0xdd, 0x2f, 0xd9, 0x98, 0xa6, 0x6c, 0x4c, 0xd7, 0x72, 0x54, 0xe8, 0x35, - 0xbd, 0x50, 0xd4, 0xf1, 0x9c, 0xbd, 0x86, 0x03, 0x7b, 0x10, 0xe6, 0xb3, 0x78, 0xf8, 0x3a, 0x7a, 0x4d, 0xc8, 0x17, - 0x82, 0xde, 0xc8, 0x4b, 0x19, 0x84, 0x41, 0xbc, 0x06, 0xe7, 0x52, 0x1b, 0xea, 0xe4, 0x5a, 0xef, 0x38, 0x7c, 0xba, - 0xf2, 0x9e, 0x2e, 0x20, 0xa2, 0x0f, 0x5a, 0xa9, 0xf4, 0xfb, 0xe1, 0x25, 0x2b, 0xe6, 0xe7, 0xe1, 0x98, 0x00, 0x0e, - 0x8f, 0x1a, 0xce, 0xcb, 0xd1, 0x1d, 0xbd, 0x1c, 0xdd, 0x13, 0xb0, 0xf0, 0x1a, 0x4f, 0xd7, 0xc7, 0x2c, 0x9e, 0x0e, - 0x06, 0x6b, 0xa4, 0xea, 0x32, 0xf7, 0x9a, 0x2c, 0xe8, 0x25, 0x4e, 0x04, 0x01, 0x86, 0x3e, 0x2b, 0xd6, 0x9a, 0x86, - 0xbf, 0x66, 0xf0, 0xf1, 0x3d, 0xbb, 0x1c, 0xdd, 0xd3, 0x3b, 0xf6, 0x7a, 0x3b, 0x9e, 0x02, 0x33, 0xb5, 0x9a, 0x85, - 0xf7, 0xc7, 0x57, 0xb3, 0x2b, 0x76, 0x1f, 0xdd, 0x9f, 0x40, 0x43, 0xaf, 0xd9, 0x3d, 0x02, 0x2e, 0xa5, 0x8f, 0x97, - 0x83, 0xd7, 0xe4, 0x70, 0x30, 0x48, 0x49, 0x14, 0xde, 0x84, 0x4e, 0x2b, 0x5f, 0xd3, 0x7b, 0x42, 0x57, 0xec, 0x0e, - 0x47, 0xe3, 0x8a, 0xe1, 0x07, 0x17, 0xec, 0xbe, 0xb9, 0x09, 0x9d, 0xdd, 0x1c, 0x57, 0x9d, 0x20, 0x46, 0xe8, 0x6b, - 0x60, 0x69, 0x96, 0x0d, 0x33, 0x01, 0x4f, 0xfa, 0x22, 0xa3, 0x44, 0xa1, 0x19, 0x88, 0xb3, 0x12, 0x10, 0x4b, 0xa2, - 0xee, 0x37, 0x1b, 0x9d, 0xc3, 0x72, 0xee, 0xf7, 0x7b, 0xb5, 0xa6, 0x07, 0x88, 0x9c, 0xd9, 0x49, 0x0f, 0x7a, 0x2e, - 0x3d, 0xc0, 0x4f, 0xd4, 0xaa, 0x41, 0x9c, 0xcc, 0xef, 0x96, 0xd1, 0xaf, 0x0e, 0x7d, 0xf8, 0xa1, 0x9b, 0xf2, 0x54, - 0xf9, 0xbf, 0x4f, 0x79, 0x8a, 0x3c, 0x7a, 0x5d, 0x3b, 0x20, 0x78, 0xce, 0x9a, 0x94, 0x1a, 0x89, 0x7a, 0x74, 0xbe, - 0x8a, 0x41, 0x1b, 0x89, 0xda, 0x06, 0xf5, 0x84, 0x16, 0x56, 0x10, 0x21, 0xe7, 0xe8, 0x39, 0x18, 0xa4, 0x42, 0xa8, - 0x1c, 0xb9, 0x28, 0xd1, 0x10, 0x24, 0x17, 0x15, 0x97, 0xe1, 0x73, 0x08, 0x95, 0xa7, 0x8f, 0x35, 0x11, 0xd6, 0xf4, - 0x18, 0x0c, 0xb0, 0x2d, 0xfc, 0xdb, 0x0e, 0xb9, 0xa8, 0xf8, 0x15, 0x9e, 0xcd, 0x6d, 0x82, 0x51, 0xb2, 0xb8, 0x15, - 0xda, 0x06, 0xb1, 0x1f, 0x0b, 0x82, 0xf5, 0x08, 0x1a, 0x8f, 0x2a, 0x7d, 0x44, 0xb8, 0x51, 0x7c, 0x24, 0x3d, 0x8d, - 0x35, 0x89, 0xe4, 0x48, 0x22, 0xf9, 0x00, 0x08, 0x27, 0x41, 0x7f, 0x71, 0xdb, 0x64, 0xdb, 0x42, 0xa2, 0xd1, 0x9f, - 0x96, 0x4c, 0xc9, 0xee, 0x65, 0x8f, 0x5d, 0x45, 0x90, 0x3d, 0xa6, 0xff, 0x74, 0xfa, 0xf0, 0xcf, 0x25, 0xce, 0xa0, - 0xf1, 0x7c, 0x91, 0x9d, 0x99, 0x39, 0x83, 0x1b, 0x39, 0x5d, 0x56, 0xae, 0xcb, 0x97, 0xfc, 0x80, 0xdf, 0xd5, 0xbc, - 0x48, 0xab, 0x83, 0x9f, 0xeb, 0x36, 0x9e, 0x53, 0xb5, 0x5e, 0xd9, 0x38, 0x2b, 0xd2, 0x38, 0xd5, 0x91, 0xba, 0x68, - 0x6b, 0x58, 0xcf, 0xef, 0x11, 0x75, 0x25, 0x2d, 0x47, 0x4f, 0x21, 0x56, 0x7e, 0xca, 0xe5, 0x3a, 0xcf, 0x7f, 0xda, - 0x49, 0xc5, 0x29, 0xf6, 0x53, 0x90, 0x2a, 0xb5, 0x5c, 0x40, 0xd5, 0x1c, 0xb5, 0xdc, 0x2d, 0xf5, 0x0e, 0xb0, 0x6e, - 0x9b, 0xf2, 0x63, 0x69, 0x76, 0xe1, 0x24, 0x7b, 0xf7, 0x27, 0x5d, 0x86, 0x01, 0xa3, 0x50, 0x66, 0xd5, 0xb5, 0xb2, - 0x2f, 0x34, 0x4e, 0xc3, 0x70, 0xe5, 0xc7, 0x0b, 0x48, 0x17, 0x30, 0x8e, 0x13, 0x25, 0x13, 0xe3, 0xf6, 0xa8, 0xad, - 0x50, 0x7d, 0xce, 0x56, 0x20, 0x60, 0xae, 0xe1, 0xec, 0xba, 0x8e, 0xb6, 0x3b, 0xe2, 0x94, 0x51, 0xb5, 0x8a, 0x8b, - 0xef, 0xe3, 0x55, 0x35, 0xb3, 0x43, 0x1b, 0xf9, 0x63, 0x3a, 0xfd, 0x7b, 0x12, 0xba, 0x85, 0x50, 0xb8, 0xe5, 0x16, - 0x46, 0x9e, 0xdc, 0x1e, 0x96, 0x71, 0x83, 0x5e, 0x89, 0x2b, 0xd5, 0x37, 0x2d, 0x85, 0x54, 0x23, 0x5f, 0xfb, 0x02, - 0x7a, 0x3d, 0xf6, 0x7e, 0x2a, 0xcc, 0xdb, 0x9e, 0x31, 0x97, 0x08, 0x56, 0xb2, 0xec, 0xf6, 0x9d, 0x1a, 0x53, 0x31, - 0x83, 0x2e, 0xb6, 0x9d, 0x45, 0xa7, 0x1b, 0xf9, 0xa7, 0x99, 0xfb, 0x65, 0xde, 0xe1, 0xae, 0xa8, 0xde, 0x02, 0x17, - 0x9a, 0x95, 0x55, 0xdd, 0x96, 0x0d, 0x9b, 0xc6, 0x6b, 0x59, 0x28, 0x36, 0xc0, 0xb0, 0xe7, 0xae, 0x85, 0x07, 0x88, - 0x9b, 0x70, 0xcf, 0x2e, 0x1a, 0xb8, 0x31, 0x7c, 0x5e, 0x49, 0xae, 0x2b, 0x8d, 0xbe, 0xf4, 0xc9, 0xd2, 0xaa, 0xe1, - 0x64, 0x31, 0xe2, 0x45, 0xba, 0x68, 0x32, 0xb3, 0x16, 0x3e, 0xe1, 0x65, 0x38, 0xe7, 0x0b, 0xad, 0x9b, 0x52, 0xa5, - 0x97, 0x2c, 0x56, 0x9d, 0xde, 0xac, 0x14, 0x56, 0x4a, 0xc4, 0x8d, 0x59, 0x26, 0x50, 0x96, 0xa2, 0x91, 0xc2, 0x9b, - 0xb2, 0x65, 0x2b, 0xa9, 0xe5, 0x3d, 0x73, 0x70, 0x1f, 0xfb, 0x01, 0x31, 0x91, 0x75, 0x60, 0x52, 0x34, 0x74, 0x40, - 0xbb, 0xea, 0xd2, 0x35, 0xa3, 0x1e, 0x0c, 0x72, 0x43, 0x12, 0xb1, 0x82, 0x14, 0x2b, 0x58, 0x37, 0xac, 0x9c, 0xe7, - 0x0b, 0x7a, 0xc9, 0xc4, 0x3c, 0x5d, 0xd0, 0x15, 0x13, 0xf3, 0x35, 0xde, 0x84, 0x2e, 0xe1, 0x84, 0x24, 0x9b, 0x58, - 0x2a, 0x60, 0x2f, 0xf1, 0xf2, 0x86, 0x67, 0xaa, 0xa2, 0x65, 0x57, 0x92, 0x03, 0x8c, 0x2f, 0xaa, 0x30, 0x2c, 0x86, - 0x97, 0x60, 0x2d, 0x71, 0x18, 0xae, 0xe6, 0x7c, 0x21, 0x7f, 0x43, 0xc0, 0xf9, 0x24, 0x94, 0xec, 0x82, 0xd9, 0x0b, - 0x64, 0x7a, 0x3d, 0xe7, 0x0b, 0x39, 0x12, 0xaa, 0xe0, 0x6b, 0x63, 0x6c, 0x12, 0x3b, 0x82, 0x96, 0x59, 0x3c, 0x1f, - 0x2f, 0xa2, 0xb8, 0x81, 0x65, 0x78, 0x26, 0x67, 0xa6, 0x25, 0xff, 0xd1, 0x76, 0x52, 0xea, 0x06, 0x2b, 0xc9, 0x1f, - 0x1e, 0x1f, 0x5d, 0x02, 0x19, 0x33, 0xbb, 0x82, 0xe9, 0x0f, 0x5d, 0x1f, 0x19, 0xdc, 0x73, 0x53, 0xce, 0xb8, 0x0c, - 0x12, 0xa5, 0x05, 0x0e, 0x72, 0x96, 0xb4, 0xb5, 0x08, 0xdf, 0x3d, 0x2a, 0xca, 0x3e, 0x13, 0xba, 0x01, 0xdd, 0x47, - 0x82, 0x3e, 0xd0, 0x7b, 0xa5, 0x0a, 0x97, 0xd5, 0x36, 0x13, 0x70, 0x17, 0x09, 0xf2, 0x5b, 0xa1, 0x53, 0x35, 0x06, - 0x55, 0x34, 0x8b, 0x58, 0xb8, 0xf7, 0x11, 0x37, 0xca, 0xe6, 0x9f, 0xfa, 0x1e, 0x2f, 0x25, 0x0c, 0x6e, 0x48, 0x4d, - 0x9f, 0xcc, 0x9b, 0x2b, 0xf6, 0x1e, 0x3a, 0xea, 0x50, 0x6b, 0xbc, 0xaf, 0x5e, 0x72, 0x0a, 0x31, 0x4a, 0x28, 0x3a, - 0x09, 0x06, 0x70, 0xbb, 0x84, 0x14, 0x7b, 0x83, 0xdd, 0xf8, 0xd7, 0xbc, 0x28, 0xb8, 0x58, 0xd7, 0x75, 0xe0, 0x06, - 0x34, 0x9c, 0x2f, 0x76, 0x43, 0x18, 0x8e, 0x69, 0xeb, 0x1a, 0x06, 0x61, 0xc6, 0x30, 0x12, 0x82, 0xd3, 0xbf, 0xe8, - 0x2b, 0x9a, 0xc4, 0xab, 0xef, 0xf8, 0x5f, 0x19, 0x2f, 0x25, 0x91, 0x06, 0x11, 0x52, 0x37, 0xf1, 0x8d, 0x74, 0x93, - 0x02, 0x0a, 0x01, 0x46, 0x01, 0x95, 0x58, 0xd3, 0x54, 0xfc, 0x2d, 0x17, 0x1f, 0xfc, 0x54, 0x74, 0x3c, 0x1a, 0x37, - 0xad, 0xce, 0xc8, 0xa0, 0x33, 0xd0, 0xa3, 0x56, 0xd4, 0xd3, 0xa0, 0x95, 0xa0, 0x1b, 0xa9, 0xdf, 0xda, 0x87, 0xc0, - 0x29, 0xd3, 0xe0, 0x9d, 0x07, 0x74, 0x73, 0xee, 0x82, 0x27, 0x8f, 0xe9, 0xb9, 0x45, 0x4f, 0xae, 0xd9, 0x49, 0xdd, - 0x43, 0xed, 0xbd, 0x1e, 0xa1, 0xa0, 0xdf, 0xc7, 0x14, 0xe8, 0x46, 0xd0, 0x38, 0x57, 0xf7, 0x1f, 0x8b, 0x5d, 0x0e, - 0xdf, 0x72, 0x96, 0x1b, 0xc0, 0x52, 0x11, 0x8d, 0x04, 0x8f, 0x02, 0xd4, 0xa5, 0x2a, 0x84, 0x2d, 0x66, 0x71, 0xa8, - 0xcc, 0x56, 0xad, 0x87, 0x82, 0x1c, 0x17, 0x23, 0x70, 0x08, 0x5d, 0x57, 0x83, 0x62, 0xb4, 0xcc, 0xea, 0xf7, 0xf8, - 0x5b, 0xb1, 0x0e, 0x49, 0xb6, 0x8f, 0x75, 0xe0, 0x86, 0x75, 0x98, 0x7e, 0xd4, 0x48, 0x01, 0x68, 0xb2, 0x11, 0xd8, - 0x04, 0xe0, 0xbd, 0xdd, 0x47, 0x84, 0x5a, 0x99, 0xee, 0x65, 0x2c, 0xe4, 0xf7, 0x5e, 0x12, 0x94, 0xe0, 0x27, 0xd4, - 0x96, 0xa5, 0xe0, 0x9d, 0x47, 0x3a, 0x27, 0x4d, 0x56, 0xbc, 0x07, 0x71, 0x5a, 0xf8, 0xc0, 0xde, 0x82, 0xe0, 0x9c, - 0x25, 0xbd, 0xc7, 0xdb, 0xac, 0x92, 0xda, 0xa8, 0x81, 0x02, 0xf8, 0xdd, 0xe0, 0x1e, 0x41, 0xbe, 0xbc, 0xe1, 0x5a, - 0x89, 0xdb, 0x90, 0x0f, 0x4b, 0x7a, 0x44, 0x06, 0xe6, 0xb9, 0x1a, 0xc6, 0xf4, 0x88, 0x1c, 0x9b, 0x67, 0x61, 0x07, - 0x70, 0x20, 0xd4, 0xa8, 0xd2, 0x23, 0x68, 0xd0, 0x6f, 0xa6, 0x45, 0x86, 0x64, 0xfd, 0xa8, 0x1b, 0x8c, 0x88, 0xbf, - 0x20, 0xa2, 0x2e, 0xfe, 0xf9, 0x60, 0xae, 0x7b, 0xcc, 0x05, 0xc2, 0x1c, 0x0c, 0x38, 0x88, 0xdb, 0x20, 0xd4, 0x07, - 0xcc, 0xe6, 0x2e, 0xaa, 0xe8, 0xbd, 0x31, 0xcc, 0xec, 0xe8, 0x0f, 0x37, 0x12, 0x7c, 0x9d, 0xb5, 0x41, 0x9d, 0x17, - 0x87, 0x40, 0x10, 0xdc, 0x17, 0xaa, 0x9a, 0xab, 0x1e, 0xd8, 0x78, 0xcb, 0x7e, 0x6c, 0xb7, 0xe3, 0x69, 0x65, 0xaf, - 0xfd, 0x15, 0x85, 0x93, 0x4f, 0xca, 0xbf, 0xde, 0xeb, 0x0c, 0x16, 0x8c, 0x0c, 0x5f, 0x3a, 0xfb, 0x17, 0xbe, 0x56, - 0xd2, 0xbd, 0x6a, 0x50, 0x90, 0xc7, 0x47, 0x92, 0xfe, 0xed, 0x95, 0x95, 0x4f, 0xcd, 0xf4, 0x6f, 0xb7, 0x7a, 0x7d, - 0x1e, 0x8f, 0x26, 0xdb, 0x6d, 0x4f, 0x19, 0xb8, 0x52, 0x1d, 0x43, 0x08, 0x9d, 0xeb, 0xc9, 0xe1, 0x11, 0x44, 0x45, - 0xf0, 0xe3, 0x6e, 0x16, 0x9e, 0x44, 0xc6, 0x8d, 0xd3, 0x59, 0x78, 0x82, 0x1d, 0xee, 0x44, 0x25, 0x2e, 0x46, 0xad, - 0x0d, 0x4e, 0xcf, 0x93, 0x10, 0x42, 0x39, 0x60, 0x65, 0x77, 0xf2, 0xcf, 0xbd, 0x34, 0x13, 0x92, 0x93, 0xd5, 0xed, - 0x94, 0xee, 0x60, 0x9a, 0x1f, 0xe8, 0x11, 0x1c, 0x70, 0x67, 0x7f, 0x35, 0x1f, 0xc3, 0x24, 0x53, 0xe4, 0x14, 0xc9, - 0x2f, 0xd2, 0x53, 0x48, 0xda, 0xa1, 0xa7, 0x92, 0x00, 0x4e, 0xa8, 0xf9, 0x18, 0x7e, 0xc3, 0xb8, 0x7f, 0xe7, 0xbf, - 0xb6, 0x53, 0x11, 0x3d, 0xa1, 0x58, 0xa6, 0x22, 0xa7, 0x49, 0x56, 0x26, 0x10, 0xb5, 0x51, 0x36, 0x23, 0xfa, 0xca, - 0xc6, 0x7c, 0x94, 0x84, 0xcf, 0xa9, 0xf5, 0x7f, 0x86, 0xf0, 0x69, 0x74, 0x46, 0x80, 0xcb, 0x2b, 0xaf, 0x2e, 0xc2, - 0xa7, 0x4f, 0xe8, 0xc1, 0xe4, 0xeb, 0x23, 0x7a, 0x70, 0xf4, 0xd5, 0x53, 0x02, 0xb0, 0x68, 0x57, 0x17, 0xe1, 0xd1, - 0xd3, 0xa7, 0xf4, 0xe0, 0xdb, 0x6f, 0xe9, 0xc1, 0xe4, 0xab, 0x23, 0x2f, 0x6d, 0xf2, 0xf4, 0x5b, 0x7a, 0xf0, 0xf5, - 0x13, 0x2f, 0xed, 0x68, 0xfc, 0x94, 0x1e, 0x7c, 0xf3, 0xb5, 0x4e, 0xfb, 0x1b, 0x64, 0xfb, 0xf6, 0x08, 0xff, 0xd3, - 0x69, 0x93, 0xa7, 0x5f, 0xd1, 0x83, 0xc9, 0x18, 0x2a, 0x79, 0x6a, 0x2b, 0x19, 0x4f, 0xe0, 0xe3, 0xaf, 0xe0, 0xbf, - 0xbf, 0x91, 0x60, 0x41, 0x6b, 0xc1, 0x92, 0x0a, 0xf5, 0x67, 0x28, 0xe2, 0x44, 0xd5, 0x44, 0xc2, 0x43, 0xcc, 0x2c, - 0xbf, 0x89, 0xc3, 0x80, 0xd8, 0x74, 0x28, 0x88, 0x1e, 0x8c, 0x47, 0x4f, 0x49, 0xe0, 0xc2, 0xd3, 0xdd, 0xba, 0x20, - 0x63, 0x49, 0x35, 0xcf, 0xbe, 0x48, 0x34, 0x63, 0xe0, 0x00, 0x58, 0x7d, 0x74, 0x73, 0xd5, 0x62, 0x9e, 0x7d, 0x51, - 0x8b, 0xdd, 0x5c, 0xbf, 0xb5, 0x00, 0xe5, 0xdd, 0x55, 0xcb, 0x6e, 0x4b, 0x19, 0x3a, 0xad, 0x35, 0xfa, 0xec, 0x23, - 0xa6, 0x0f, 0x06, 0xce, 0x0d, 0xfb, 0xef, 0x3b, 0xe5, 0xb4, 0xbe, 0x51, 0x28, 0xd4, 0xa8, 0x3c, 0x24, 0xec, 0x04, - 0x8a, 0x1e, 0x0c, 0x80, 0x27, 0x70, 0x70, 0xdf, 0xfe, 0xcd, 0x32, 0x3e, 0x76, 0x94, 0xf1, 0x33, 0xca, 0x10, 0xd0, - 0xa8, 0x87, 0x99, 0x4d, 0x0f, 0x1b, 0xdd, 0xe8, 0x25, 0x0b, 0x79, 0x32, 0xf9, 0x9e, 0xc1, 0xae, 0xd6, 0xb5, 0x38, - 0xd0, 0xa2, 0x68, 0x71, 0x79, 0x90, 0xf2, 0x59, 0xcd, 0xfe, 0xbe, 0x44, 0xf5, 0x56, 0xe4, 0xbd, 0x11, 0xd9, 0xac, - 0x66, 0xdf, 0xeb, 0x37, 0xc0, 0xcd, 0xb0, 0xdf, 0xe4, 0x93, 0x1b, 0x38, 0x83, 0x0b, 0xd3, 0x1e, 0x69, 0x62, 0x04, - 0x58, 0x01, 0x19, 0x38, 0xf0, 0x00, 0xe8, 0xa0, 0x3b, 0xda, 0xdb, 0xad, 0x4c, 0xf1, 0xfb, 0x6c, 0x60, 0x00, 0x35, - 0xf3, 0x36, 0xb1, 0x65, 0xff, 0xcb, 0x93, 0x97, 0xa0, 0x70, 0xcb, 0x2f, 0x6f, 0xa7, 0x30, 0x84, 0x10, 0xfc, 0x71, - 0xc9, 0x00, 0x70, 0x20, 0xc0, 0x60, 0xac, 0x55, 0x40, 0xf5, 0x96, 0x8f, 0x36, 0x5c, 0xaa, 0x27, 0x81, 0x33, 0xb8, - 0x14, 0x65, 0xc2, 0xdf, 0x2a, 0xb1, 0x3f, 0x5a, 0x3f, 0xba, 0xbe, 0x3d, 0x0e, 0xac, 0x7d, 0x8f, 0x8f, 0xd4, 0x67, - 0xde, 0x75, 0x60, 0xd3, 0xf2, 0x8d, 0xaf, 0x1a, 0x23, 0xf1, 0x28, 0x80, 0x37, 0xd0, 0x11, 0x29, 0x34, 0x52, 0x2d, - 0x70, 0x0c, 0x85, 0xb4, 0x40, 0x1c, 0x79, 0x75, 0x83, 0x2d, 0x88, 0x08, 0xc1, 0xc3, 0xed, 0x5f, 0x4b, 0x19, 0x38, - 0xaa, 0xdf, 0xe7, 0xc2, 0x75, 0x7b, 0xd2, 0x76, 0xe4, 0x38, 0xf5, 0x53, 0x07, 0xdf, 0x9c, 0x34, 0x8d, 0xb6, 0x5c, - 0x49, 0x99, 0x61, 0x59, 0xd8, 0x49, 0xa8, 0xe4, 0x1e, 0xb5, 0x03, 0xc9, 0x17, 0x72, 0x88, 0x64, 0x81, 0x51, 0x28, - 0xc8, 0x70, 0x42, 0xc1, 0x66, 0xaa, 0x5a, 0x66, 0x97, 0x75, 0xb8, 0x91, 0x0a, 0x65, 0x4e, 0xd1, 0xb7, 0x1b, 0x1c, - 0x48, 0x48, 0x94, 0x55, 0x6f, 0xe2, 0x37, 0x21, 0x82, 0xd5, 0x71, 0x65, 0x0b, 0xc5, 0x9d, 0xfd, 0xc9, 0xd3, 0x2e, - 0xfe, 0x48, 0xbb, 0x80, 0xda, 0x58, 0x4c, 0xc3, 0x89, 0x89, 0x7d, 0x63, 0xbf, 0x30, 0x9a, 0x1e, 0x80, 0xfa, 0xae, - 0xa4, 0x18, 0x41, 0x7e, 0xa5, 0xed, 0x63, 0x7b, 0x8c, 0x89, 0x19, 0xc4, 0x1a, 0x96, 0x39, 0x33, 0xd9, 0x37, 0xc2, - 0x4e, 0x00, 0xb8, 0x11, 0x5a, 0x23, 0x21, 0xf0, 0x78, 0x1d, 0xe2, 0x79, 0x29, 0xc3, 0xb7, 0x66, 0x84, 0x8e, 0xc1, - 0x9b, 0xca, 0x34, 0x32, 0x13, 0xae, 0x60, 0x50, 0x1f, 0xdb, 0x2a, 0x0a, 0xab, 0xa9, 0x2c, 0x3b, 0x01, 0xb8, 0x81, - 0xec, 0x58, 0x5f, 0x3c, 0x67, 0xf5, 0x3c, 0x5b, 0x44, 0x3a, 0x28, 0x60, 0x5e, 0x19, 0x06, 0xed, 0xcd, 0x1e, 0xd9, - 0x8e, 0x45, 0xe8, 0x86, 0xfb, 0x08, 0xc6, 0xd3, 0xf6, 0x05, 0x2b, 0x88, 0x46, 0x88, 0x87, 0x19, 0x33, 0xf8, 0x5e, - 0x69, 0xca, 0x53, 0xd9, 0x12, 0x08, 0x1c, 0x85, 0x50, 0x17, 0xbb, 0x46, 0x09, 0x36, 0x93, 0x17, 0xcc, 0x60, 0xc7, - 0x8e, 0xd4, 0x74, 0xc9, 0x3a, 0x1d, 0xca, 0x29, 0x2d, 0xd4, 0x94, 0x2a, 0x5f, 0xc3, 0x6a, 0x5e, 0xa0, 0x87, 0x1e, - 0xb8, 0x1e, 0x28, 0x87, 0xbc, 0x82, 0x4e, 0x74, 0x04, 0x9d, 0x56, 0x9b, 0xb0, 0x73, 0x23, 0xd5, 0xb2, 0x06, 0x79, - 0xc7, 0x50, 0xef, 0x88, 0x17, 0x4e, 0xa0, 0x2e, 0x84, 0x08, 0xd9, 0xdb, 0x22, 0x7d, 0x44, 0xb3, 0xac, 0x7a, 0x09, - 0x65, 0x71, 0xc4, 0xd6, 0x05, 0x2b, 0x6d, 0x34, 0xb9, 0xe4, 0x11, 0x4f, 0x11, 0x11, 0xf0, 0x54, 0x6a, 0xd7, 0x77, - 0x5a, 0x42, 0x68, 0x96, 0x02, 0x71, 0xb3, 0x51, 0x9c, 0x1b, 0x13, 0xc8, 0x02, 0xe8, 0xdb, 0x4f, 0xd9, 0xb5, 0x13, - 0x0e, 0x76, 0x73, 0x9d, 0x15, 0xcf, 0xf9, 0x65, 0x56, 0xf0, 0x14, 0xc1, 0xae, 0xee, 0xf4, 0x03, 0xb7, 0x6c, 0x1b, - 0x58, 0xbe, 0x7d, 0x07, 0x0b, 0xa6, 0x0a, 0x95, 0x52, 0x22, 0x2b, 0xa2, 0x0a, 0x32, 0xbb, 0xcc, 0xdd, 0xeb, 0xac, - 0x78, 0x1d, 0xdf, 0x81, 0x37, 0x85, 0xc7, 0x4f, 0x8f, 0x2e, 0xf0, 0x4b, 0x44, 0x12, 0x85, 0x18, 0xb6, 0x18, 0x11, - 0x0b, 0x91, 0x63, 0xc7, 0x84, 0x72, 0x29, 0x68, 0x6d, 0x0d, 0x81, 0x13, 0x7f, 0x5a, 0x76, 0xef, 0x3a, 0x2b, 0xb4, - 0x7d, 0xc6, 0x75, 0x7c, 0xc7, 0x0a, 0x09, 0x66, 0x81, 0x71, 0xee, 0xdb, 0x52, 0x92, 0xeb, 0xac, 0xd0, 0x02, 0x92, - 0xeb, 0xf8, 0x8e, 0xfa, 0x32, 0x0e, 0x65, 0x45, 0xe7, 0xc4, 0xf9, 0xdd, 0x1d, 0x7e, 0x81, 0xa1, 0x56, 0xc6, 0xfd, - 0x3e, 0x48, 0xcc, 0x84, 0x69, 0xca, 0x4c, 0x44, 0x42, 0xa1, 0x85, 0xd4, 0x94, 0x0f, 0x26, 0x64, 0x77, 0xa5, 0x1a, - 0x46, 0xd4, 0x7c, 0x15, 0x56, 0xb3, 0x71, 0x34, 0x21, 0x74, 0xd2, 0xb1, 0xde, 0x75, 0x6b, 0x21, 0xd3, 0xe8, 0x69, - 0xe4, 0xf8, 0x74, 0x96, 0xac, 0x9e, 0x96, 0xc7, 0x8c, 0x4f, 0xcb, 0xc1, 0x80, 0xa8, 0xd0, 0xc1, 0x1b, 0xac, 0x07, - 0x4c, 0x69, 0x6c, 0xbc, 0x35, 0xdd, 0xea, 0x97, 0x42, 0x86, 0xa4, 0x77, 0x0c, 0x48, 0x32, 0x61, 0x83, 0xdd, 0x82, - 0x44, 0xd1, 0xf1, 0xbf, 0x93, 0x5b, 0x70, 0xd7, 0x83, 0xd1, 0x8f, 0xee, 0xeb, 0x18, 0xff, 0xa1, 0xb6, 0x05, 0x51, - 0x9f, 0x2a, 0xd6, 0xeb, 0x48, 0x94, 0x21, 0x17, 0xe1, 0x67, 0x47, 0x43, 0x34, 0x51, 0xed, 0xb1, 0xa0, 0x58, 0x5f, - 0x5f, 0xf0, 0x12, 0xa7, 0x9f, 0xd9, 0xcb, 0x15, 0x6c, 0x0b, 0x5a, 0x6b, 0x1a, 0xf5, 0x26, 0x7e, 0x13, 0x99, 0xcb, - 0x82, 0x2a, 0xf2, 0x39, 0x0a, 0x59, 0xf3, 0x30, 0xac, 0x87, 0xed, 0x41, 0x24, 0x87, 0xed, 0x49, 0xf0, 0x1a, 0x03, - 0x0b, 0x64, 0x87, 0x46, 0xe0, 0x22, 0x34, 0xf2, 0xb7, 0x63, 0x70, 0xe1, 0x32, 0x88, 0x2c, 0x43, 0x15, 0xbf, 0xa9, - 0xdd, 0x04, 0xd9, 0x2b, 0x74, 0x9a, 0xc2, 0xaa, 0xa4, 0x49, 0x3e, 0xfc, 0x7a, 0x29, 0x4a, 0xcc, 0xe4, 0x74, 0xd9, - 0xa1, 0xaf, 0xed, 0xf6, 0x0e, 0x74, 0xc1, 0xaa, 0x4f, 0xce, 0xd7, 0x8f, 0x3b, 0x7b, 0x02, 0x46, 0xb1, 0x32, 0x87, - 0x2f, 0xa4, 0x54, 0x3e, 0x28, 0xcd, 0xc7, 0x30, 0xaf, 0x14, 0xc7, 0x6e, 0x00, 0x93, 0x80, 0x7d, 0x86, 0x54, 0x87, - 0x69, 0xc7, 0x3e, 0x47, 0x1b, 0x58, 0x12, 0x70, 0xf8, 0x47, 0x99, 0x68, 0xdc, 0xab, 0x7b, 0x95, 0xfa, 0x21, 0x5b, - 0xe6, 0x0b, 0xe0, 0xf3, 0x61, 0xd7, 0x46, 0x05, 0xca, 0x26, 0x22, 0x41, 0x61, 0xcb, 0x63, 0x90, 0xf6, 0x28, 0xa6, - 0xab, 0x92, 0x27, 0x19, 0x4a, 0x29, 0x12, 0xe5, 0x13, 0x9c, 0xc3, 0x1b, 0xdc, 0x8f, 0x32, 0x20, 0xbc, 0x0c, 0x39, - 0x1d, 0xa5, 0x54, 0x59, 0xc0, 0x48, 0xea, 0x01, 0xa2, 0xbc, 0x0c, 0xe4, 0x78, 0xdb, 0xed, 0x84, 0xae, 0xd8, 0x72, - 0x38, 0xa1, 0x48, 0x4a, 0xae, 0xb0, 0xdc, 0x6b, 0xd0, 0x79, 0x5c, 0xb0, 0xde, 0x0b, 0xc0, 0x22, 0x38, 0x87, 0xbf, - 0x31, 0xa1, 0x37, 0xf0, 0x37, 0x27, 0xf4, 0x35, 0x0b, 0xaf, 0x87, 0x57, 0xe4, 0x30, 0x4c, 0x07, 0x13, 0x29, 0x18, - 0xbb, 0x67, 0xcb, 0x22, 0x94, 0x89, 0xab, 0xc3, 0x4b, 0xf2, 0xf8, 0x92, 0xde, 0xd1, 0x5b, 0x7a, 0x46, 0xdf, 0x02, - 0xe1, 0xbf, 0x3f, 0x9e, 0xf0, 0xe1, 0xe4, 0x49, 0xbf, 0xdf, 0xbb, 0xe8, 0xf7, 0x7b, 0xe7, 0xda, 0x80, 0x42, 0xed, - 0xa2, 0xab, 0x86, 0xaa, 0x5f, 0xd7, 0xcd, 0x62, 0xfa, 0x56, 0x6e, 0xdc, 0x84, 0x67, 0x79, 0x78, 0x7d, 0x78, 0x4f, - 0x86, 0xf8, 0x78, 0x99, 0x0b, 0x51, 0x86, 0x57, 0x87, 0xf7, 0x84, 0xbe, 0x3d, 0x01, 0xbd, 0x29, 0xd6, 0xf7, 0xf6, - 0xf1, 0xbd, 0xaa, 0x8d, 0xd0, 0x17, 0x61, 0x02, 0xdb, 0xe4, 0x8e, 0x99, 0xbb, 0xf6, 0x64, 0x0c, 0xb1, 0x4c, 0xee, - 0x9d, 0xf2, 0xee, 0x1f, 0xdf, 0x91, 0xc3, 0x3b, 0xf0, 0x14, 0x35, 0xe4, 0x6f, 0x16, 0xde, 0xb2, 0x56, 0x0d, 0x8f, - 0xef, 0xe9, 0x59, 0xab, 0x11, 0x8f, 0xef, 0x49, 0x14, 0xde, 0xb2, 0x2b, 0x7a, 0xc6, 0xae, 0x09, 0xbd, 0xe8, 0xf7, - 0xcf, 0xfb, 0x7d, 0xd1, 0xef, 0xff, 0x3d, 0x0e, 0xc3, 0x78, 0x58, 0x92, 0x43, 0x41, 0xef, 0x0f, 0x27, 0xfc, 0x2b, - 0x32, 0x0b, 0x55, 0xf3, 0xe5, 0x82, 0x33, 0x2a, 0x6f, 0x99, 0xeb, 0x9e, 0x82, 0xb5, 0xc2, 0x3d, 0x93, 0x4f, 0x6f, - 0xe9, 0x2d, 0x2b, 0xe9, 0x19, 0x8b, 0x49, 0x74, 0x03, 0xad, 0xb8, 0x98, 0x95, 0xd1, 0x2d, 0x3d, 0x63, 0xe7, 0xb3, - 0x38, 0x3a, 0xa3, 0x6f, 0x59, 0x3e, 0x9c, 0x40, 0xde, 0xb3, 0xe1, 0x2d, 0x39, 0x7c, 0x4b, 0xa2, 0xf0, 0xad, 0xfa, - 0x7d, 0x4f, 0xaf, 0x78, 0xf8, 0x96, 0x3a, 0xd5, 0xbc, 0x25, 0xba, 0x7a, 0xaf, 0xf6, 0xb7, 0x24, 0x72, 0x07, 0xf3, - 0xad, 0xb1, 0xa7, 0x79, 0x64, 0x69, 0x63, 0x5a, 0x84, 0xa0, 0x6f, 0x2e, 0xc2, 0x5b, 0x42, 0xa6, 0xfe, 0xd8, 0xc1, - 0x80, 0xce, 0x1e, 0x45, 0x09, 0xa1, 0xb7, 0x6e, 0xa9, 0xb7, 0x38, 0x86, 0x7a, 0x84, 0x64, 0xda, 0x19, 0xa6, 0xe1, - 0x3a, 0x78, 0xa5, 0xc0, 0x3a, 0x2e, 0xfa, 0xfd, 0x70, 0xdd, 0xef, 0x43, 0xa4, 0xfb, 0x72, 0xa6, 0x63, 0xbb, 0x59, - 0xb2, 0x49, 0x6f, 0x41, 0xfb, 0xff, 0x6a, 0x30, 0x80, 0xce, 0x38, 0x25, 0x85, 0xb7, 0x83, 0x57, 0x8f, 0xef, 0x89, - 0xac, 0xa3, 0xa4, 0x95, 0x08, 0x4b, 0xfa, 0x9a, 0x66, 0x00, 0xf8, 0xf5, 0x6a, 0x30, 0x20, 0x91, 0xfe, 0x8c, 0x4c, - 0x5f, 0x1d, 0xbf, 0x9d, 0x0e, 0x06, 0xaf, 0xf4, 0x36, 0xf9, 0x8b, 0xed, 0x29, 0x05, 0xd6, 0xdf, 0x79, 0xbf, 0xff, - 0xd7, 0x49, 0x4c, 0x2e, 0x4a, 0x1e, 0x7f, 0x9c, 0xfa, 0x6d, 0xf9, 0xcb, 0x46, 0x55, 0x3b, 0xef, 0xf7, 0xd7, 0xfd, - 0xfe, 0x19, 0x60, 0x17, 0xcd, 0xac, 0xaf, 0x27, 0x48, 0x5b, 0xe6, 0x96, 0x22, 0x29, 0x92, 0x43, 0x63, 0x68, 0x5b, - 0x2c, 0xdb, 0x36, 0xeb, 0xc8, 0xc0, 0xe2, 0xc8, 0xaf, 0x28, 0x6e, 0x48, 0x14, 0xf6, 0xce, 0xb7, 0xdb, 0x33, 0xc6, - 0x58, 0x4c, 0x40, 0xfa, 0xe1, 0xbe, 0x3e, 0x6b, 0xbc, 0x18, 0x62, 0x95, 0x40, 0x66, 0x73, 0xb3, 0x34, 0x87, 0x40, - 0xc4, 0x61, 0xd3, 0xbf, 0xd7, 0xf7, 0xf2, 0xaa, 0xb1, 0x7c, 0xeb, 0xcf, 0x00, 0x42, 0x24, 0x58, 0xc8, 0x67, 0x38, - 0x06, 0x55, 0x06, 0xc0, 0xbf, 0x91, 0x9c, 0x79, 0x01, 0xa0, 0xe6, 0x64, 0xbb, 0x1d, 0x8d, 0xc7, 0x13, 0x5a, 0xb2, - 0xd1, 0xdf, 0x9e, 0x3e, 0xae, 0x1f, 0x87, 0x41, 0x30, 0xc8, 0x48, 0x4b, 0x4f, 0x61, 0x16, 0x6b, 0x7d, 0x08, 0x46, - 0xf0, 0x8a, 0x7d, 0xbc, 0xc9, 0x3e, 0x9b, 0x7d, 0x44, 0xc2, 0xea, 0x31, 0x8e, 0xbc, 0x48, 0x5b, 0x7a, 0xbb, 0x3d, - 0x0c, 0x26, 0x2f, 0xd2, 0x4f, 0xb0, 0x9d, 0x2e, 0xff, 0xe6, 0xc0, 0x78, 0xc2, 0xc1, 0x68, 0x2f, 0x0a, 0xea, 0x4c, - 0xdb, 0x6e, 0x6b, 0xf7, 0x12, 0xf8, 0x06, 0x53, 0x41, 0xc7, 0x66, 0x58, 0xb8, 0x41, 0x4d, 0xe4, 0xd1, 0x32, 0xa8, - 0x1b, 0x69, 0x3b, 0x07, 0xd4, 0x12, 0xab, 0xd2, 0x71, 0x0b, 0x34, 0x43, 0x86, 0xba, 0xdc, 0xd3, 0xfa, 0x5f, 0xbc, - 0x14, 0x1a, 0x3e, 0xc3, 0x8a, 0x08, 0x1d, 0x6e, 0x8d, 0xbb, 0xdc, 0x5a, 0xf5, 0x09, 0x6e, 0xad, 0x40, 0x12, 0xab, - 0x61, 0x49, 0xf5, 0xe5, 0x28, 0x61, 0x27, 0x05, 0xe3, 0x33, 0xa0, 0xe3, 0x31, 0x3c, 0x08, 0x56, 0xcd, 0x44, 0x94, - 0xa0, 0x7d, 0xa2, 0x8d, 0x30, 0xf8, 0x27, 0x60, 0xf6, 0xd3, 0x1c, 0xfe, 0x0a, 0x32, 0x4d, 0x8e, 0x21, 0x20, 0xc4, - 0xf1, 0x78, 0x16, 0x87, 0x63, 0x12, 0x25, 0x27, 0xf0, 0x04, 0xff, 0x95, 0xe1, 0x98, 0x34, 0xea, 0x0e, 0x23, 0xe4, - 0xe5, 0x36, 0x61, 0x00, 0x57, 0x36, 0x9e, 0x4d, 0x22, 0x23, 0xdd, 0x15, 0x8f, 0x47, 0xe3, 0xa7, 0x64, 0x1a, 0x87, - 0x62, 0x90, 0x10, 0x0a, 0xde, 0xbd, 0x61, 0x31, 0x4c, 0x14, 0x3c, 0x1b, 0xb0, 0x79, 0x85, 0x65, 0xf3, 0x04, 0x9c, - 0x80, 0x30, 0x4c, 0xc8, 0xb1, 0xee, 0x41, 0x4a, 0x51, 0xe7, 0x39, 0xf6, 0x53, 0x1d, 0x41, 0x98, 0x1d, 0xb5, 0x54, - 0x7c, 0x05, 0x40, 0x97, 0x38, 0x38, 0xd4, 0x20, 0x61, 0x54, 0xb3, 0xb0, 0x70, 0xa8, 0x94, 0xae, 0xee, 0xb0, 0xf2, - 0x28, 0xbf, 0x6e, 0xd0, 0x61, 0x45, 0x06, 0x13, 0x5a, 0x9c, 0x4c, 0xf8, 0x57, 0x10, 0xc0, 0xc3, 0x8b, 0xf8, 0x25, - 0x71, 0x62, 0x20, 0xbc, 0x0a, 0x32, 0x50, 0x69, 0x23, 0x1b, 0x33, 0x32, 0x15, 0x1f, 0x40, 0x98, 0x94, 0x83, 0x5b, - 0xb1, 0xce, 0x53, 0x88, 0x0a, 0xb6, 0xce, 0xeb, 0x83, 0x2b, 0xb0, 0x64, 0x8f, 0x6b, 0x88, 0x13, 0xb6, 0x5e, 0x01, - 0x76, 0xee, 0xa3, 0x4d, 0xd1, 0x1c, 0xc8, 0xef, 0x0e, 0xb0, 0xe5, 0xf0, 0xaa, 0x16, 0x07, 0x93, 0xf1, 0x78, 0x3c, - 0xfa, 0x1d, 0x8e, 0x0e, 0x20, 0xb4, 0x24, 0xd2, 0x7c, 0x32, 0x40, 0xe3, 0xae, 0x6b, 0xee, 0x8c, 0x0b, 0x45, 0x59, - 0xe9, 0x64, 0x42, 0x40, 0xfc, 0xac, 0xfb, 0x06, 0xfb, 0x8a, 0xab, 0xf8, 0x27, 0xbb, 0x9f, 0xe8, 0x15, 0x2d, 0x57, - 0xea, 0xe8, 0xdd, 0xdb, 0xb3, 0x57, 0x1f, 0x5e, 0xfd, 0xfa, 0xe2, 0xfc, 0xd5, 0x9b, 0x97, 0xaf, 0xde, 0xbc, 0xfa, - 0xf0, 0xcf, 0x07, 0x18, 0x6c, 0xd7, 0x56, 0xc4, 0x8c, 0xbd, 0x73, 0x8f, 0x71, 0x6a, 0x71, 0x85, 0xb3, 0x47, 0xf6, - 0x16, 0x0b, 0xb0, 0x09, 0x9a, 0x5b, 0xa8, 0xa8, 0x62, 0x34, 0x6a, 0x75, 0x4f, 0x40, 0x46, 0xa3, 0x46, 0x36, 0x1e, - 0x56, 0x6c, 0x8d, 0x5c, 0xbc, 0x65, 0x38, 0xf8, 0xc8, 0xfc, 0x96, 0x9c, 0x09, 0x37, 0xa3, 0xad, 0x58, 0x11, 0xf0, - 0xf9, 0x5a, 0x17, 0xb5, 0xc3, 0x85, 0xc8, 0xbd, 0x6d, 0x9e, 0x43, 0x42, 0x1d, 0x22, 0xd7, 0xc1, 0xfb, 0x7a, 0x64, - 0x8f, 0x8f, 0x9c, 0x27, 0xe9, 0x19, 0xea, 0x72, 0x34, 0x7c, 0xe4, 0x3d, 0xa3, 0x13, 0x73, 0xa3, 0x75, 0xa8, 0xe7, - 0x25, 0xec, 0x6f, 0x29, 0xc6, 0x86, 0x68, 0x0f, 0x29, 0x62, 0x7d, 0x58, 0xdd, 0xef, 0xee, 0xcd, 0xe8, 0x7b, 0x38, - 0x7e, 0xa4, 0x6a, 0x02, 0x69, 0x51, 0x20, 0x75, 0x65, 0xc8, 0x6d, 0xcf, 0xc2, 0x52, 0xff, 0x0c, 0x3d, 0x02, 0x68, - 0x2e, 0x3b, 0x86, 0x04, 0xea, 0xc5, 0x6b, 0x5c, 0xff, 0x9c, 0x7c, 0x59, 0xd1, 0xce, 0x17, 0xdf, 0x41, 0x88, 0x61, - 0xf7, 0x8a, 0xe0, 0x4d, 0xb8, 0x9d, 0x64, 0x7b, 0x69, 0xd1, 0xf7, 0xaa, 0xeb, 0x18, 0x8f, 0xbb, 0x3d, 0x57, 0x0a, - 0xff, 0xd6, 0x05, 0xf6, 0x40, 0xfe, 0x75, 0xbc, 0x60, 0x21, 0x60, 0x33, 0x1e, 0x9a, 0x45, 0x62, 0xfd, 0xde, 0xe9, - 0x84, 0x1c, 0x1e, 0x4d, 0xf9, 0x90, 0x15, 0xb4, 0x1a, 0xb0, 0xa2, 0xd9, 0xa1, 0xe6, 0xbc, 0x4d, 0xc8, 0xab, 0x5d, - 0x1a, 0x5e, 0x0d, 0xf9, 0x43, 0x97, 0xa4, 0x0f, 0xdc, 0x73, 0xa8, 0x36, 0xcd, 0xc5, 0x90, 0xa6, 0x9c, 0xee, 0x52, - 0x19, 0x10, 0x22, 0x5d, 0xc7, 0x35, 0x69, 0xd4, 0x51, 0xb5, 0xb4, 0x92, 0x8e, 0x9b, 0x6c, 0xf3, 0x89, 0x4b, 0xb6, - 0xbc, 0x5d, 0xbb, 0xd7, 0xea, 0xf6, 0x85, 0x19, 0xc8, 0xdf, 0x1f, 0x88, 0x6a, 0xa2, 0x21, 0xba, 0x80, 0x0a, 0xfe, - 0x01, 0x5e, 0x9e, 0x3c, 0x52, 0x0a, 0xd0, 0x7d, 0x67, 0x47, 0xd7, 0x1e, 0xf7, 0x66, 0xb1, 0xb5, 0xc4, 0x39, 0xab, - 0x5d, 0x67, 0x79, 0x59, 0xb6, 0x44, 0xd7, 0xa9, 0xd8, 0xcf, 0x61, 0x47, 0xdf, 0x9d, 0x6d, 0x00, 0x44, 0x29, 0xac, - 0xed, 0xd9, 0x5f, 0x39, 0x67, 0x7f, 0x65, 0xce, 0x7e, 0xb3, 0x09, 0xa4, 0x0f, 0x2b, 0xb4, 0xec, 0xa5, 0x28, 0x6a, - 0xdd, 0xe4, 0xb1, 0xaf, 0xcb, 0x42, 0x5a, 0xcc, 0x0f, 0x0d, 0xed, 0x7a, 0x32, 0xa6, 0x02, 0xd5, 0x23, 0x3f, 0x60, - 0xab, 0x0e, 0x0b, 0xf2, 0xf0, 0x3d, 0xf3, 0x7f, 0xf6, 0x06, 0xb9, 0xef, 0x6e, 0xf7, 0x7f, 0x73, 0xa1, 0x83, 0xdb, - 0xda, 0xb2, 0x72, 0xd4, 0xd5, 0x71, 0x89, 0x77, 0xb5, 0xe5, 0xc3, 0x77, 0xb5, 0x77, 0x99, 0x5a, 0x76, 0x35, 0xa0, - 0x06, 0x15, 0xeb, 0x6b, 0x5e, 0x66, 0x49, 0x63, 0x14, 0x1a, 0x6f, 0x39, 0x84, 0xf6, 0x70, 0x0e, 0x2e, 0x90, 0xc3, - 0x12, 0x42, 0x3f, 0xd6, 0x5a, 0x00, 0xe8, 0xb2, 0xd8, 0x6f, 0x79, 0x98, 0x91, 0x81, 0x2b, 0xf1, 0x2b, 0x84, 0x2b, - 0x2e, 0x3e, 0xdc, 0xc9, 0x4c, 0xd0, 0xab, 0xc4, 0x46, 0xcd, 0x15, 0xed, 0x98, 0x1f, 0xee, 0x17, 0x18, 0x0d, 0xc2, - 0x69, 0x4b, 0x76, 0x58, 0x75, 0xcc, 0x72, 0x0d, 0x47, 0x6d, 0x61, 0xcb, 0x2c, 0x5a, 0xd7, 0xcf, 0x7a, 0x98, 0xa9, - 0x33, 0xe5, 0x2d, 0xc8, 0xbe, 0x90, 0xbb, 0x9f, 0xaa, 0x8a, 0x2b, 0x72, 0x32, 0x19, 0x4f, 0x49, 0x35, 0x18, 0xb4, - 0x92, 0x8f, 0x31, 0x79, 0x38, 0xdc, 0x61, 0x2e, 0x2b, 0xd5, 0x0f, 0xa7, 0x0f, 0x50, 0x9f, 0xb7, 0x25, 0xc9, 0xa6, - 0x66, 0x7f, 0x82, 0x59, 0x2c, 0x10, 0x47, 0x0b, 0xbf, 0x38, 0x5f, 0x00, 0xc8, 0x32, 0x2c, 0x33, 0x25, 0x2c, 0x82, - 0x2b, 0x3d, 0x74, 0xb2, 0x64, 0xe2, 0x78, 0x3c, 0x73, 0x7b, 0x6e, 0x19, 0x1c, 0x42, 0xa2, 0x89, 0x31, 0x7e, 0x71, - 0xb3, 0x60, 0x1c, 0x87, 0xe2, 0x44, 0x78, 0xdf, 0x15, 0x24, 0x1a, 0x6b, 0x53, 0x65, 0x75, 0x95, 0xa8, 0x87, 0x09, - 0x79, 0x5c, 0x92, 0xc3, 0x92, 0x2e, 0xdd, 0xb1, 0xc4, 0xf4, 0xc3, 0xf8, 0x70, 0x32, 0x26, 0x8f, 0xe3, 0xc7, 0x13, - 0x0d, 0x37, 0xec, 0xe6, 0xc8, 0x87, 0x4b, 0x72, 0xe8, 0x57, 0x09, 0xa6, 0xa8, 0xba, 0x67, 0x6e, 0x25, 0xc9, 0x60, - 0x39, 0x48, 0x1f, 0xb7, 0xf2, 0x62, 0xad, 0x6a, 0xbc, 0xd7, 0xc7, 0x7c, 0x4a, 0x2a, 0xef, 0xc6, 0xb0, 0xa6, 0xd7, - 0xf1, 0x1f, 0xa2, 0x8c, 0x0a, 0x01, 0x88, 0x84, 0xa0, 0xde, 0xce, 0x2e, 0xb3, 0x24, 0x2e, 0xd2, 0x28, 0x6d, 0x08, - 0x4d, 0x4f, 0xd8, 0x64, 0x3c, 0x4b, 0x59, 0x7a, 0x3c, 0x79, 0x3a, 0x9b, 0x3c, 0x8d, 0x8e, 0xc6, 0x51, 0x3a, 0x18, - 0x40, 0xf2, 0xd1, 0x18, 0x5c, 0xec, 0xe0, 0x37, 0x3b, 0x82, 0xa1, 0x3b, 0x41, 0x96, 0xb0, 0x84, 0xa6, 0x7d, 0x5e, - 0x93, 0xd4, 0x70, 0x5e, 0xca, 0x9e, 0xc4, 0x77, 0x74, 0xed, 0x38, 0xb8, 0xb8, 0x2d, 0xbc, 0xb4, 0x2d, 0xbc, 0xdc, - 0x6d, 0xa1, 0xb6, 0x20, 0x28, 0xc5, 0xff, 0x8f, 0x1b, 0xc6, 0xbe, 0xbb, 0x84, 0x5e, 0x5c, 0x37, 0xd9, 0x68, 0x55, - 0x8a, 0x5a, 0xc0, 0x6d, 0x42, 0x8a, 0xc2, 0x46, 0xf1, 0x6a, 0x95, 0x2b, 0x17, 0xb1, 0x79, 0x4d, 0x01, 0xdc, 0x05, - 0xce, 0x56, 0x60, 0xa1, 0xb5, 0x81, 0xdc, 0x5f, 0xbc, 0x14, 0xcc, 0xa8, 0x7d, 0xf4, 0x3d, 0xf2, 0x8f, 0x10, 0xc1, - 0x96, 0x4e, 0xc6, 0xb3, 0x0a, 0x11, 0x2d, 0x3e, 0x25, 0xef, 0xfd, 0x37, 0x8e, 0x22, 0x73, 0x34, 0x8f, 0x51, 0xa1, - 0x65, 0x3c, 0xe2, 0xcc, 0xc9, 0xe4, 0x64, 0xe0, 0x6e, 0x06, 0x23, 0xfd, 0xb5, 0xb7, 0x19, 0x63, 0xdb, 0xa3, 0x7a, - 0xa1, 0x85, 0xa2, 0x7f, 0xe1, 0x3b, 0x5d, 0x2f, 0xe0, 0x12, 0xca, 0x81, 0x5d, 0x5f, 0x5d, 0xf1, 0x0a, 0x40, 0x84, - 0xb2, 0xa2, 0xdf, 0xef, 0xfd, 0xa1, 0xa1, 0x49, 0x2b, 0x5e, 0xbe, 0xce, 0x0a, 0xe3, 0x8c, 0x03, 0x4d, 0x05, 0xea, - 0xff, 0xb1, 0x36, 0xcf, 0x74, 0x4c, 0x66, 0xee, 0xe3, 0x70, 0x42, 0x22, 0xff, 0x35, 0xf9, 0xc4, 0x69, 0xfa, 0x89, - 0x2b, 0xda, 0x7f, 0x20, 0x33, 0xd7, 0x1c, 0x32, 0xd4, 0x5f, 0x58, 0xe6, 0x49, 0xeb, 0x75, 0x62, 0x76, 0x52, 0xb1, - 0x7a, 0x06, 0xe8, 0xe9, 0x25, 0x3c, 0xc8, 0x6b, 0x59, 0x3c, 0x85, 0xd9, 0x07, 0x35, 0x62, 0x75, 0xcc, 0xc6, 0xb3, - 0x50, 0x84, 0x13, 0xb0, 0xef, 0x9d, 0x8c, 0xe1, 0x3e, 0x20, 0xc2, 0x8f, 0x75, 0x58, 0x51, 0x94, 0x92, 0x97, 0xf0, - 0x1b, 0x14, 0x13, 0x00, 0x11, 0x08, 0x79, 0xfb, 0x7d, 0x21, 0x93, 0xf0, 0x75, 0x81, 0x29, 0xa5, 0xfc, 0xe0, 0x3f, - 0x91, 0xaa, 0x5b, 0xa6, 0x5f, 0xae, 0x1f, 0x77, 0x26, 0x24, 0x9f, 0x6e, 0x53, 0xe2, 0x3b, 0x08, 0xee, 0x2c, 0x40, - 0x07, 0x51, 0xa3, 0x19, 0xdb, 0xc3, 0xfc, 0x6e, 0xb5, 0x9f, 0xdf, 0xad, 0xfe, 0xdf, 0xf1, 0xbb, 0xd5, 0x43, 0x8c, - 0x61, 0x6d, 0xa0, 0xe1, 0x67, 0xc1, 0x38, 0x88, 0xfe, 0x73, 0x3e, 0x71, 0x2f, 0x4f, 0x7d, 0x9d, 0x15, 0xd3, 0x3d, - 0x4c, 0xb3, 0x4b, 0x50, 0x10, 0x56, 0x71, 0x97, 0x9e, 0xac, 0x6b, 0x73, 0x6b, 0x25, 0x43, 0xcc, 0xf3, 0x00, 0x6b, - 0x14, 0xd6, 0x0e, 0xd0, 0x3d, 0xaa, 0x36, 0x88, 0x15, 0xc1, 0xc3, 0x98, 0x19, 0xe9, 0xfb, 0x76, 0xab, 0x55, 0x98, - 0x0f, 0x72, 0x51, 0x90, 0x5d, 0x7f, 0x3c, 0x1b, 0x47, 0x21, 0x36, 0xe0, 0x3f, 0x66, 0xac, 0x3c, 0xd9, 0x7c, 0x27, - 0x23, 0xb5, 0x63, 0xf2, 0x34, 0xd9, 0x25, 0xbd, 0x03, 0xde, 0x21, 0x3f, 0x6f, 0x3e, 0x86, 0xa5, 0xd0, 0xfc, 0x96, - 0xb8, 0x8a, 0xcb, 0xac, 0x5e, 0x5e, 0x67, 0x09, 0x32, 0x5d, 0xf0, 0xe2, 0xb3, 0x99, 0x2e, 0xe7, 0x63, 0x75, 0xc0, - 0x38, 0x4a, 0xf1, 0xc6, 0x13, 0xa5, 0xa7, 0x2d, 0xcf, 0x0a, 0x79, 0x79, 0x92, 0x31, 0xdb, 0xb3, 0x0a, 0x9c, 0x4e, - 0xc1, 0x04, 0x5f, 0xfd, 0xb4, 0xbd, 0x8f, 0x01, 0x17, 0x14, 0x6a, 0x4e, 0x4b, 0xb1, 0xd2, 0x58, 0x4e, 0x06, 0xba, - 0x13, 0x30, 0x43, 0x45, 0x81, 0x17, 0x28, 0xf8, 0x8b, 0x06, 0x46, 0xf4, 0xa5, 0xfd, 0x4d, 0x06, 0x1a, 0xe9, 0x52, - 0x9f, 0x08, 0x63, 0xcb, 0xed, 0x94, 0x69, 0x2b, 0xca, 0x19, 0x67, 0xef, 0xe5, 0x95, 0x02, 0x0c, 0xf0, 0x36, 0xb7, - 0xd1, 0x45, 0x82, 0x5e, 0x0b, 0x52, 0xe7, 0x0d, 0xdc, 0xcd, 0x32, 0xd2, 0xc2, 0xc5, 0xc7, 0xb5, 0xc3, 0x82, 0x3b, - 0xf6, 0x0b, 0xb1, 0xd0, 0x9a, 0x69, 0x30, 0x66, 0x73, 0x82, 0x05, 0x56, 0x32, 0x50, 0x60, 0x31, 0x53, 0x96, 0xa6, - 0xf5, 0x90, 0x1f, 0x1e, 0xa1, 0xb5, 0x69, 0x3d, 0xe0, 0x87, 0x47, 0x4d, 0x94, 0x1d, 0x43, 0x96, 0x13, 0x37, 0x83, - 0x7c, 0xdd, 0x44, 0x3a, 0x45, 0x67, 0x77, 0xeb, 0x4b, 0xdd, 0x51, 0xdd, 0x80, 0xeb, 0x07, 0x20, 0x80, 0x0d, 0xc0, - 0x21, 0x50, 0x0e, 0x96, 0x42, 0x04, 0x8b, 0x32, 0x89, 0xf6, 0x35, 0x74, 0xde, 0x28, 0xf8, 0x2f, 0x70, 0x17, 0x11, - 0x2b, 0xf7, 0x13, 0x04, 0xfe, 0x8a, 0x32, 0xa5, 0x4c, 0x71, 0x3f, 0x51, 0xea, 0x15, 0xca, 0x99, 0x6f, 0xcd, 0x07, - 0xd1, 0x9a, 0x08, 0x55, 0x8c, 0x21, 0xf8, 0xb7, 0xb2, 0x4c, 0x59, 0xaa, 0x4a, 0xf5, 0xa1, 0xf6, 0x5a, 0x2b, 0xad, - 0xe5, 0xe3, 0xc8, 0x79, 0x8d, 0xa1, 0x63, 0x13, 0x6b, 0x29, 0x27, 0x53, 0x67, 0x6f, 0x0e, 0x45, 0x64, 0x01, 0xa7, - 0x13, 0x36, 0x9e, 0x26, 0xc7, 0x62, 0x9a, 0x58, 0xc8, 0xfc, 0x9c, 0x61, 0x64, 0x55, 0x0d, 0xc2, 0x22, 0x6d, 0x28, - 0x4d, 0x01, 0x3a, 0x39, 0x21, 0x64, 0x8a, 0xa1, 0x28, 0xf2, 0x91, 0xea, 0x87, 0xf1, 0x66, 0xb5, 0x5f, 0xbc, 0x53, - 0x00, 0xa7, 0x61, 0x02, 0x81, 0xc0, 0xcb, 0xf8, 0x36, 0x2b, 0xae, 0xc0, 0x63, 0x78, 0x00, 0x5f, 0x82, 0x9b, 0x5c, - 0xca, 0x7e, 0xab, 0xc3, 0x1c, 0xd7, 0x16, 0x30, 0x68, 0xb0, 0x7a, 0x10, 0x1d, 0x2e, 0xa5, 0x7e, 0x57, 0x01, 0x62, - 0x63, 0x0a, 0xff, 0xb3, 0xb5, 0x61, 0xcf, 0xbe, 0x97, 0x4d, 0x43, 0xeb, 0x84, 0xd3, 0xe2, 0x2a, 0x87, 0x28, 0x2a, - 0x83, 0x18, 0xdc, 0x91, 0x1c, 0x3e, 0xef, 0x5d, 0x15, 0x5e, 0x12, 0x70, 0x2b, 0x8b, 0x45, 0xb8, 0xa2, 0xcb, 0xd1, - 0x1d, 0x5d, 0x8f, 0x6e, 0xe9, 0x98, 0x4e, 0xbe, 0x19, 0x83, 0x45, 0xb6, 0x4a, 0xbd, 0xa7, 0xeb, 0xd1, 0x92, 0x7e, - 0x3b, 0xa6, 0x47, 0x7f, 0x03, 0x13, 0x3e, 0x3c, 0x4c, 0xe8, 0x25, 0x38, 0x76, 0x91, 0x06, 0x3d, 0x35, 0x5d, 0x83, - 0xc3, 0x7a, 0x94, 0x0f, 0xf9, 0x28, 0xa7, 0x7c, 0x54, 0x0e, 0xeb, 0x11, 0x78, 0x3a, 0xd6, 0x43, 0x3e, 0xaa, 0x29, - 0x1f, 0x5d, 0x0c, 0xeb, 0xd1, 0x05, 0xf1, 0x9b, 0xfe, 0xaa, 0xe6, 0xd7, 0x15, 0x4b, 0x61, 0x5b, 0xc0, 0xf2, 0xb5, - 0xab, 0x2c, 0x49, 0xdd, 0x55, 0xad, 0x4f, 0x66, 0xc3, 0xd9, 0x9b, 0xeb, 0x2e, 0x27, 0x06, 0x8f, 0xdb, 0xa4, 0xc3, - 0xd5, 0x97, 0x13, 0x79, 0xd2, 0x4b, 0xe4, 0x87, 0xf1, 0x54, 0x9d, 0x43, 0x60, 0x26, 0x31, 0x0b, 0x63, 0x86, 0xcd, - 0x54, 0x69, 0xa0, 0xc0, 0xc9, 0x46, 0x8e, 0x8b, 0x62, 0x36, 0xca, 0x29, 0xbc, 0x8f, 0x09, 0x89, 0xf0, 0xac, 0x3a, - 0xa9, 0x47, 0x25, 0xc4, 0x1c, 0x61, 0x21, 0x3e, 0x42, 0xbf, 0xe4, 0x47, 0x0e, 0x12, 0x78, 0x86, 0x7d, 0x2d, 0x07, - 0x31, 0x1c, 0xf1, 0xa6, 0xb2, 0x7a, 0x16, 0x26, 0x50, 0x59, 0x3d, 0x2c, 0x74, 0x65, 0x25, 0xcd, 0x46, 0xb5, 0x5b, - 0x59, 0x8d, 0x63, 0x94, 0x10, 0x12, 0x15, 0xaa, 0x32, 0x50, 0x9f, 0x24, 0x2c, 0x2c, 0x54, 0x65, 0x17, 0xf2, 0xa3, - 0x0b, 0xb7, 0xb2, 0x0b, 0x70, 0x21, 0x1d, 0x24, 0xee, 0x55, 0x2a, 0x4f, 0xdb, 0xd7, 0x41, 0x6f, 0x55, 0xd1, 0x0d, - 0xbf, 0xab, 0xcb, 0x38, 0x2a, 0xa8, 0x8d, 0x01, 0x8d, 0x0b, 0x23, 0x12, 0x54, 0xad, 0x51, 0xf0, 0x87, 0x04, 0x51, - 0x69, 0x0c, 0x5e, 0x9d, 0x49, 0xd7, 0x4a, 0xad, 0x69, 0x35, 0x28, 0x06, 0x25, 0xdc, 0x9f, 0xf2, 0xd6, 0x42, 0xfa, - 0x1e, 0x22, 0x2a, 0x43, 0x79, 0x83, 0x7f, 0x60, 0xf0, 0x64, 0xb6, 0x4a, 0xc3, 0x64, 0x74, 0x4f, 0xe3, 0xd1, 0x12, - 0xe1, 0x60, 0xd8, 0x3a, 0x95, 0x78, 0xeb, 0x97, 0x90, 0x7e, 0x47, 0xe3, 0xd1, 0x2d, 0x4d, 0x8d, 0xcd, 0xa9, 0x86, - 0xba, 0xea, 0x8d, 0xe9, 0x5d, 0x04, 0xaf, 0xef, 0xa3, 0x25, 0x85, 0xad, 0x74, 0x9a, 0x67, 0x57, 0x45, 0x94, 0x52, - 0x44, 0x20, 0x5c, 0x23, 0x72, 0xe0, 0x52, 0xa1, 0x0d, 0xae, 0x07, 0x50, 0x86, 0x82, 0x0b, 0x5c, 0x0e, 0xe2, 0xd1, - 0xd2, 0x21, 0x53, 0x4b, 0x75, 0x91, 0x45, 0xf8, 0x68, 0x6b, 0xa3, 0x25, 0x79, 0x46, 0x2c, 0x8c, 0x4b, 0x18, 0x42, - 0x55, 0x58, 0xa1, 0x0b, 0x12, 0x36, 0x70, 0x64, 0x2f, 0x2c, 0xeb, 0x70, 0x03, 0xa6, 0x45, 0xf7, 0x60, 0x1e, 0x05, - 0x0a, 0x07, 0x9b, 0x20, 0xdc, 0x84, 0xa2, 0x9d, 0xa3, 0xd0, 0x39, 0x9c, 0x09, 0x4a, 0x77, 0x26, 0x08, 0x69, 0x57, - 0x37, 0xd9, 0x12, 0xae, 0xc1, 0xf6, 0x0e, 0x9d, 0x8a, 0x4a, 0xaa, 0xce, 0x2d, 0x98, 0x2c, 0xe1, 0x11, 0xb6, 0x84, - 0xa9, 0x99, 0x4e, 0xe1, 0x06, 0x7c, 0x78, 0xb4, 0x33, 0xdf, 0xe5, 0xec, 0xcd, 0x21, 0xd8, 0x76, 0x4a, 0x1f, 0x10, - 0x43, 0xec, 0x96, 0x6c, 0x3c, 0x5d, 0x1e, 0x17, 0xd3, 0x25, 0x12, 0x3b, 0x4d, 0xb7, 0x18, 0x9f, 0x2f, 0x17, 0x34, - 0xc1, 0xb3, 0x8d, 0xd5, 0xf3, 0xa5, 0x46, 0x4b, 0x49, 0x19, 0xae, 0xb7, 0x25, 0xfa, 0xff, 0xcb, 0x8b, 0x5f, 0x0a, - 0xf0, 0x12, 0x8c, 0x05, 0x80, 0x70, 0x0f, 0xa6, 0x05, 0xa9, 0x89, 0xb2, 0xb1, 0x4c, 0xc3, 0x14, 0x17, 0x81, 0x4e, - 0xe9, 0xf7, 0xc3, 0x9c, 0xa5, 0xc4, 0x81, 0x0e, 0x35, 0xa3, 0xb4, 0x4e, 0x5d, 0x21, 0x08, 0xf0, 0x48, 0xf2, 0x1c, - 0x9b, 0x7c, 0x33, 0x9e, 0x05, 0x72, 0x20, 0x82, 0x28, 0x3b, 0xc6, 0x47, 0x0c, 0x5c, 0x14, 0xa9, 0xb8, 0x9d, 0xb6, - 0x88, 0xcb, 0xdd, 0x63, 0x16, 0xe2, 0x24, 0x61, 0xae, 0x59, 0x36, 0x64, 0x75, 0x84, 0x09, 0xaa, 0x30, 0x30, 0xcb, - 0x1b, 0xb2, 0xfa, 0xf0, 0x08, 0x22, 0xb5, 0x9a, 0x32, 0x56, 0x5d, 0x65, 0x7c, 0x0b, 0x40, 0xd6, 0x8c, 0xb1, 0xa3, - 0xbf, 0x8d, 0x67, 0xf2, 0x9b, 0x28, 0xe4, 0x27, 0x47, 0x7f, 0x83, 0xe4, 0xe3, 0x6f, 0x91, 0x99, 0x83, 0x64, 0xaf, - 0xa0, 0x2b, 0x7f, 0xd6, 0x15, 0x94, 0x26, 0xae, 0xbd, 0x42, 0xad, 0x3d, 0xa1, 0xd7, 0x5e, 0x89, 0xee, 0xd4, 0x9a, - 0xf7, 0x90, 0xb6, 0xb3, 0x60, 0x82, 0x8e, 0x66, 0x77, 0xa0, 0x83, 0xb7, 0x8a, 0xa0, 0x17, 0x49, 0xa8, 0x3d, 0x42, - 0xa5, 0x51, 0x2f, 0xec, 0xc8, 0x6e, 0xd6, 0x25, 0x73, 0x0c, 0x98, 0x63, 0x73, 0x0e, 0x55, 0xc3, 0x5c, 0x1e, 0xd4, - 0x29, 0x2b, 0x86, 0x39, 0x1e, 0xc0, 0x6b, 0x26, 0x86, 0xd5, 0x20, 0x57, 0x28, 0xdf, 0x97, 0xac, 0x1c, 0x16, 0x83, - 0x5c, 0x71, 0x33, 0x53, 0x3f, 0x36, 0x6d, 0xa2, 0xc2, 0x33, 0xaf, 0xd8, 0xc9, 0xaa, 0x07, 0x7c, 0x2c, 0x78, 0x32, - 0xbb, 0x9e, 0x8f, 0xaf, 0x81, 0x93, 0xd9, 0xdc, 0x45, 0x4b, 0x7a, 0x1f, 0xa5, 0xf4, 0x36, 0x5a, 0xd3, 0x65, 0x74, - 0xa9, 0x4d, 0x8c, 0x93, 0x06, 0xce, 0x01, 0x68, 0x15, 0x40, 0xe2, 0xc9, 0x5f, 0xef, 0x79, 0x52, 0x87, 0x4b, 0x9a, - 0x82, 0xdb, 0xb0, 0x6b, 0x9f, 0x79, 0xed, 0x4a, 0xa4, 0x36, 0x88, 0xb1, 0x66, 0x0c, 0x15, 0x37, 0xce, 0xba, 0x8f, - 0xaa, 0x06, 0x76, 0xae, 0x8d, 0x4d, 0x54, 0x0f, 0x27, 0xd3, 0x02, 0x10, 0x5b, 0x8b, 0xe1, 0xd0, 0x1e, 0x21, 0xbb, - 0xc7, 0x8f, 0x0a, 0xf4, 0xdc, 0x13, 0x06, 0xdb, 0xb6, 0xe5, 0x0f, 0x0c, 0x61, 0x4a, 0x3f, 0x7d, 0xe4, 0x17, 0x84, - 0x4c, 0xaf, 0xe0, 0x6c, 0x04, 0xea, 0x68, 0x84, 0x4e, 0xbf, 0xd5, 0x61, 0xa9, 0x0e, 0xf0, 0xcd, 0x5d, 0x94, 0xd0, - 0xfb, 0x28, 0x77, 0xc8, 0xda, 0xb2, 0x61, 0x62, 0x7a, 0x9e, 0x85, 0xbc, 0x7d, 0xa0, 0x17, 0x0b, 0x00, 0xd1, 0x1a, - 0xc4, 0xae, 0xd4, 0xf5, 0x08, 0x9c, 0x86, 0xd0, 0x24, 0x34, 0x82, 0xab, 0x0a, 0xc2, 0x08, 0xd8, 0x92, 0xf0, 0x37, - 0x98, 0xa8, 0xc0, 0x17, 0xe0, 0x22, 0x93, 0xa6, 0x39, 0x0f, 0x1a, 0x77, 0x24, 0xcf, 0xca, 0xb6, 0xb7, 0x2b, 0x8c, - 0x26, 0x18, 0x7b, 0xa2, 0x7d, 0x1e, 0x29, 0x46, 0x71, 0x99, 0x84, 0xd9, 0xe8, 0x4e, 0x9e, 0xe7, 0x34, 0x1b, 0xdd, - 0xab, 0x5f, 0x35, 0x1d, 0xd3, 0xef, 0x54, 0x40, 0x1b, 0x29, 0x7d, 0xeb, 0x38, 0x1b, 0xd0, 0x7a, 0xb1, 0xd0, 0xfe, - 0xd7, 0x62, 0x74, 0x47, 0xc5, 0xe8, 0xde, 0xb5, 0xa4, 0x9a, 0x4c, 0xcb, 0xe3, 0x0a, 0x0d, 0xa9, 0x3a, 0xbf, 0x2f, - 0x81, 0x9f, 0x2b, 0xb4, 0xef, 0xb4, 0xfe, 0xde, 0x69, 0xff, 0x45, 0x27, 0x4f, 0x20, 0x59, 0xa2, 0x92, 0xd5, 0x23, - 0xb0, 0x63, 0x5f, 0xe7, 0x71, 0xa9, 0x47, 0x29, 0xa6, 0xc6, 0xa4, 0x1f, 0x03, 0x57, 0x4c, 0x7b, 0x25, 0xb8, 0x5a, - 0x6e, 0xb7, 0x32, 0x86, 0x26, 0xec, 0xd9, 0x31, 0x44, 0x3d, 0xd7, 0x8e, 0x51, 0xc2, 0x73, 0x0f, 0x88, 0x95, 0xcc, - 0x5b, 0xba, 0x04, 0x24, 0xf0, 0xd6, 0xc1, 0xa4, 0x28, 0x46, 0x29, 0xc0, 0x4f, 0xa8, 0x3c, 0x0e, 0xfa, 0x84, 0x7c, - 0xa1, 0x50, 0x27, 0x84, 0xb7, 0x25, 0x70, 0xfc, 0x61, 0x7d, 0x54, 0x08, 0x5e, 0xe5, 0xb8, 0xfe, 0x0a, 0xe3, 0xfa, - 0x4b, 0x85, 0xe3, 0x8e, 0x65, 0xbb, 0x7e, 0xde, 0xa6, 0x46, 0x2f, 0xc1, 0xc2, 0x77, 0x23, 0xcd, 0x23, 0xb9, 0x41, - 0x48, 0x95, 0x60, 0xa5, 0x76, 0x21, 0xc1, 0xfc, 0x4b, 0x39, 0x5b, 0x9d, 0xb9, 0xea, 0x91, 0x07, 0xe5, 0x6c, 0x6a, - 0xfa, 0x3d, 0x09, 0xda, 0x7d, 0x47, 0x9a, 0xc3, 0x5b, 0x74, 0xf8, 0xec, 0x1a, 0x4b, 0xcc, 0x9d, 0x44, 0xc9, 0xf3, - 0x49, 0x60, 0xab, 0xe7, 0xd9, 0xb5, 0xf4, 0xb1, 0xda, 0xc5, 0xf1, 0xd3, 0xe7, 0x4f, 0x5c, 0x87, 0x69, 0xe5, 0x29, - 0x41, 0xc0, 0x9b, 0x43, 0xdb, 0x15, 0xca, 0x80, 0x86, 0xfa, 0x06, 0x8e, 0x73, 0x35, 0xac, 0x15, 0x01, 0x53, 0x52, - 0x1e, 0x15, 0xe0, 0x50, 0xe7, 0x91, 0xbb, 0x69, 0x58, 0x6b, 0xba, 0xe6, 0xf5, 0xb9, 0xad, 0x74, 0xc6, 0x9b, 0x0d, - 0x3f, 0x3c, 0x1a, 0xd4, 0xf8, 0x93, 0xf8, 0xa3, 0xd1, 0xce, 0x0d, 0x77, 0x9a, 0x0a, 0x33, 0xd7, 0x62, 0x45, 0x76, - 0x47, 0xc9, 0xc9, 0xef, 0xe8, 0x85, 0xb1, 0x3f, 0xff, 0xb9, 0x98, 0x70, 0xd2, 0x12, 0x13, 0xa2, 0xa5, 0x83, 0x12, - 0x1d, 0xec, 0x28, 0xaf, 0xcc, 0x4b, 0xbc, 0x74, 0x8e, 0xff, 0x7d, 0x3d, 0xd6, 0xae, 0x02, 0xa1, 0xd5, 0xc9, 0xc3, - 0xf6, 0x64, 0x81, 0xa8, 0x01, 0xd5, 0xec, 0xb2, 0x1c, 0x69, 0xda, 0x59, 0x93, 0x8d, 0x27, 0x73, 0xdd, 0xcd, 0xe2, - 0xd9, 0x4c, 0x76, 0x2c, 0x2c, 0x3d, 0x0c, 0xc6, 0x4e, 0x15, 0x7d, 0x0e, 0x5a, 0x7e, 0x04, 0xcf, 0x7d, 0xe5, 0x99, - 0xcb, 0x66, 0x69, 0xf1, 0x02, 0x9d, 0x73, 0xaa, 0x21, 0x87, 0x1c, 0x80, 0xe3, 0x02, 0x8d, 0x25, 0x8a, 0x28, 0x08, - 0x1a, 0x13, 0x84, 0x5d, 0x95, 0xee, 0x48, 0x9f, 0x76, 0xf1, 0x69, 0x2b, 0xf4, 0x3d, 0xde, 0x67, 0x20, 0x31, 0x75, - 0x24, 0x0f, 0xb5, 0xd7, 0x1c, 0x95, 0x3c, 0x8b, 0x53, 0x85, 0xcf, 0x2f, 0x65, 0x67, 0xfe, 0xdd, 0x6a, 0x4c, 0xf1, - 0x1f, 0x69, 0xda, 0x77, 0x2e, 0x4d, 0x13, 0xdd, 0xb5, 0x3c, 0x68, 0x29, 0x2c, 0x38, 0x6e, 0x1b, 0x77, 0xfd, 0xfa, - 0x39, 0xaa, 0x61, 0x61, 0x73, 0x38, 0x13, 0x3a, 0xb4, 0x77, 0x95, 0x9d, 0xb9, 0x3e, 0xa2, 0x56, 0x5d, 0xac, 0xda, - 0x80, 0x92, 0x25, 0xe7, 0xd6, 0xe9, 0x88, 0x95, 0xbe, 0x3b, 0x0c, 0x77, 0xe6, 0x51, 0xb1, 0xbb, 0xdb, 0xed, 0x84, - 0xb4, 0xed, 0x83, 0xf1, 0xbe, 0x84, 0x85, 0x58, 0xef, 0xb0, 0x83, 0xef, 0xc3, 0xfa, 0x31, 0x1f, 0xfc, 0x1c, 0xca, - 0x75, 0x55, 0x3f, 0xcf, 0xa4, 0xa1, 0xcf, 0xcb, 0x52, 0x5c, 0xcb, 0x4e, 0xb9, 0x42, 0xb7, 0x96, 0xa9, 0xf7, 0x9b, - 0xf8, 0x4d, 0x2b, 0x40, 0x8c, 0xd3, 0x15, 0x23, 0xc5, 0x1b, 0x1a, 0x61, 0x9c, 0x87, 0xdb, 0x64, 0x51, 0x4b, 0x95, - 0x40, 0xd4, 0xe6, 0x27, 0x8f, 0x79, 0xa4, 0xd5, 0x99, 0xf0, 0xdd, 0x63, 0xee, 0x4a, 0xd7, 0x76, 0x9b, 0xf8, 0xa9, - 0xa6, 0x1d, 0xee, 0x0e, 0x74, 0x47, 0xeb, 0x1e, 0x6e, 0x9e, 0xc9, 0xcf, 0x23, 0xfd, 0xc5, 0x00, 0x9b, 0xb5, 0xcb, - 0xb8, 0xec, 0x18, 0xee, 0x3b, 0xd3, 0x83, 0xb1, 0x80, 0x40, 0x62, 0x86, 0x5e, 0x06, 0x36, 0x70, 0x81, 0xbd, 0xc2, - 0x80, 0x21, 0xae, 0x6e, 0xc9, 0xb9, 0xb2, 0xb2, 0x75, 0x91, 0xb7, 0x51, 0x21, 0xd8, 0x34, 0x1d, 0x37, 0x49, 0x0e, - 0xc1, 0x09, 0x5b, 0xee, 0x7d, 0xed, 0xb5, 0x33, 0xfc, 0xc7, 0xa0, 0xb2, 0x6e, 0x89, 0x8e, 0x51, 0xdb, 0x63, 0xa5, - 0xee, 0xd5, 0xbc, 0xca, 0x7d, 0xe4, 0x58, 0xbf, 0xe9, 0x97, 0x9a, 0x7d, 0xc1, 0x6b, 0x29, 0x38, 0x34, 0xb6, 0x5b, - 0x61, 0x17, 0x8b, 0x73, 0xb4, 0x1a, 0x59, 0x6b, 0xab, 0xbd, 0x46, 0x2a, 0xba, 0x7f, 0xcd, 0x71, 0x62, 0x2d, 0x85, - 0xcd, 0x87, 0x0f, 0x17, 0x6c, 0x9b, 0x00, 0x06, 0x2d, 0x3a, 0x0b, 0x94, 0x20, 0x93, 0x95, 0xaa, 0xdd, 0x4c, 0x89, - 0x5b, 0xee, 0x67, 0x5d, 0x66, 0x3b, 0x8f, 0x5f, 0x3b, 0x69, 0x9f, 0xf8, 0x1c, 0xfd, 0x30, 0xbf, 0x33, 0x4e, 0x4a, - 0xd6, 0x30, 0xae, 0xe5, 0xff, 0x57, 0xd3, 0xab, 0x32, 0x4b, 0xa3, 0x8d, 0xe6, 0xc1, 0x4c, 0xa8, 0x4d, 0x17, 0x1a, - 0xa3, 0xb6, 0xcb, 0x46, 0x12, 0xd1, 0xfa, 0x0e, 0x04, 0x33, 0x92, 0xfb, 0xaa, 0xda, 0xbc, 0x52, 0x6d, 0xe0, 0x1d, - 0x3e, 0xb1, 0xd1, 0x3d, 0xdb, 0x13, 0x42, 0xf9, 0xee, 0x69, 0xa1, 0x57, 0x2d, 0xad, 0x3c, 0xb6, 0xab, 0x72, 0x2e, - 0x46, 0xb5, 0x7a, 0xc2, 0x64, 0xc3, 0x82, 0xc9, 0xfe, 0x7f, 0x5f, 0x66, 0x69, 0x9b, 0xa2, 0x03, 0xd3, 0xe9, 0xfb, - 0x74, 0xd2, 0x0d, 0xae, 0x33, 0x60, 0x11, 0xc1, 0x96, 0x0a, 0xc7, 0xa3, 0x50, 0x6e, 0x90, 0x30, 0x11, 0x5c, 0x47, - 0xbd, 0xec, 0x68, 0x99, 0x94, 0x55, 0x01, 0xcf, 0x2f, 0x5d, 0x65, 0x3a, 0x8e, 0x86, 0x7e, 0xff, 0x3a, 0xd5, 0xa1, - 0x5f, 0x69, 0xe1, 0x9c, 0x23, 0xcb, 0xcc, 0x51, 0x75, 0xc8, 0x30, 0x46, 0x4b, 0x9a, 0xc2, 0x31, 0x98, 0x5d, 0x86, - 0x29, 0x5e, 0xce, 0x36, 0x09, 0xfb, 0x8c, 0x81, 0x5c, 0x2a, 0x83, 0x7a, 0x45, 0x89, 0xd6, 0xac, 0xbd, 0x99, 0x53, - 0x42, 0x2f, 0x59, 0xe1, 0xde, 0x85, 0xd6, 0x20, 0x50, 0x14, 0x7e, 0xca, 0xf4, 0x42, 0xb5, 0xf3, 0x92, 0x26, 0xb4, - 0xa4, 0x2b, 0xd2, 0x80, 0xbe, 0xd7, 0xca, 0xd9, 0xd1, 0xc9, 0x4e, 0xcf, 0x7a, 0xcc, 0xca, 0xe1, 0x64, 0x1a, 0xc3, - 0x35, 0x2d, 0xb6, 0xd7, 0xb4, 0xa5, 0x7f, 0xe3, 0xf2, 0x36, 0x8e, 0x47, 0xbb, 0x40, 0xda, 0xa6, 0xb8, 0xfd, 0xd4, - 0xe1, 0xf6, 0xd7, 0x0d, 0x5b, 0x4e, 0x7b, 0xeb, 0xed, 0xb6, 0x97, 0x82, 0x8d, 0xa8, 0xc3, 0xc7, 0xaf, 0xa5, 0x74, - 0xdd, 0x70, 0xf9, 0x29, 0x3c, 0x3b, 0x7c, 0xfd, 0xd2, 0x05, 0x97, 0xa3, 0x75, 0x9b, 0xbb, 0x5f, 0xee, 0x22, 0xcb, - 0x7d, 0xd6, 0xd0, 0x72, 0x35, 0x43, 0x3e, 0x79, 0xd6, 0xda, 0x3b, 0xd4, 0x82, 0xe5, 0xac, 0x9b, 0xf0, 0xc4, 0x60, - 0xc7, 0x5e, 0x7b, 0x9b, 0xa3, 0xd6, 0x97, 0x2c, 0x8f, 0x04, 0xba, 0x24, 0x4f, 0x37, 0xfd, 0x83, 0x08, 0xf3, 0xd1, - 0x1d, 0xcd, 0x01, 0x57, 0xac, 0x36, 0x97, 0x0c, 0xd2, 0xd4, 0xed, 0x25, 0x2e, 0x7d, 0x85, 0x43, 0xb2, 0xc1, 0x27, - 0xcd, 0x54, 0x7d, 0x72, 0xc9, 0x83, 0xff, 0xb7, 0x51, 0xab, 0xf4, 0xec, 0x24, 0x7b, 0x8e, 0x7f, 0x9d, 0xb4, 0x7d, - 0x4c, 0x34, 0x12, 0xf0, 0xd4, 0x2c, 0x86, 0x7a, 0x54, 0x97, 0x71, 0x51, 0xe5, 0x3a, 0xe6, 0xd8, 0xde, 0xae, 0xa1, - 0x83, 0x32, 0xf8, 0x75, 0xc3, 0x27, 0xfa, 0x0e, 0x6c, 0x04, 0x3a, 0x2a, 0x51, 0x5f, 0x86, 0x99, 0xbe, 0x0c, 0xd3, - 0xae, 0xad, 0x02, 0xc3, 0x2b, 0xb7, 0x4a, 0x22, 0x5d, 0x8d, 0x7a, 0x5c, 0xcf, 0x92, 0xdf, 0x8b, 0xbc, 0x7b, 0x4d, - 0x3a, 0x12, 0x7f, 0xba, 0x74, 0xe4, 0xf5, 0x30, 0x20, 0xe2, 0x73, 0x96, 0x86, 0x6d, 0x14, 0x04, 0xa7, 0x96, 0x3b, - 0x90, 0xe6, 0x23, 0x40, 0xe6, 0xc7, 0x69, 0xf8, 0x4e, 0x89, 0x73, 0xc8, 0x46, 0x6a, 0x9c, 0xd8, 0x52, 0xab, 0x87, - 0xe0, 0xce, 0x7b, 0xcd, 0x63, 0x08, 0x7c, 0xf8, 0x01, 0x37, 0x83, 0x8c, 0x6e, 0x4b, 0x74, 0x94, 0x36, 0x87, 0xba, - 0xe5, 0x23, 0x4f, 0xa8, 0x64, 0x64, 0x78, 0x31, 0xb4, 0x77, 0x47, 0x60, 0x54, 0x5b, 0x81, 0xcc, 0xb0, 0x3c, 0x3c, - 0x1a, 0xa6, 0x52, 0x50, 0x34, 0x14, 0xc3, 0x25, 0xca, 0x01, 0x31, 0x09, 0x04, 0x46, 0xe5, 0x20, 0x55, 0x95, 0xc9, - 0x17, 0x83, 0x54, 0xdd, 0xaa, 0x48, 0x73, 0x9e, 0x85, 0x35, 0x55, 0x2d, 0xa2, 0x63, 0x3a, 0x14, 0x74, 0xa9, 0x77, - 0x6a, 0xae, 0xa4, 0x17, 0x72, 0x39, 0x3e, 0x53, 0x69, 0x30, 0x8a, 0x67, 0x36, 0x45, 0xbd, 0x95, 0xfb, 0xd9, 0x7d, - 0x8b, 0x29, 0x0d, 0x62, 0x53, 0x3b, 0x8b, 0x18, 0x56, 0xed, 0x87, 0xac, 0xce, 0x41, 0xbb, 0x0b, 0xca, 0xc6, 0x5a, - 0x3b, 0xcf, 0x7b, 0xc1, 0xcc, 0x41, 0xdb, 0x58, 0xfb, 0x3e, 0xf4, 0x5a, 0x8c, 0xda, 0x1b, 0x53, 0x85, 0x7b, 0x02, - 0x3f, 0x4d, 0xd0, 0x74, 0x27, 0xf2, 0x1c, 0x75, 0xc8, 0xbb, 0xfb, 0x99, 0x25, 0x3b, 0x93, 0x4f, 0x62, 0x99, 0x34, - 0xed, 0x63, 0x12, 0xa3, 0x96, 0x18, 0x46, 0x17, 0x6e, 0x64, 0x52, 0xfb, 0xb9, 0x33, 0xfd, 0x88, 0x67, 0xf2, 0xb0, - 0x1d, 0x1a, 0x75, 0xa5, 0x61, 0x2d, 0x29, 0xa2, 0xba, 0xa0, 0xb7, 0xa6, 0x3a, 0x3a, 0xa2, 0x4e, 0x47, 0x60, 0x75, - 0x45, 0x1b, 0xd4, 0x00, 0x4c, 0xc6, 0x8d, 0xa9, 0xcd, 0xe5, 0x60, 0x1a, 0xa3, 0x2a, 0x78, 0x4a, 0x77, 0x85, 0xd2, - 0xbd, 0x49, 0xd3, 0xb4, 0x86, 0xd8, 0x00, 0x06, 0x04, 0x76, 0xf4, 0xe4, 0xf4, 0x07, 0x3e, 0x2a, 0x00, 0x0d, 0xbc, - 0xdb, 0x99, 0xca, 0x91, 0xa8, 0x77, 0x72, 0xd3, 0xfa, 0xa9, 0x4e, 0x55, 0x2e, 0x80, 0x8a, 0x3b, 0x4b, 0xe7, 0x97, - 0x7a, 0xc4, 0x02, 0x18, 0xf7, 0xc0, 0x9a, 0xea, 0x9d, 0x66, 0x60, 0x3d, 0x91, 0xe7, 0x59, 0xc5, 0x13, 0x51, 0xc0, - 0x8c, 0x88, 0xeb, 0x6b, 0x51, 0xc0, 0x30, 0xc8, 0x01, 0x40, 0x8b, 0xe6, 0x2a, 0x9a, 0xf0, 0xaf, 0x1a, 0xba, 0x2f, - 0x0f, 0xff, 0x4a, 0xe5, 0xfa, 0x7a, 0xdc, 0x80, 0xa1, 0xf2, 0xba, 0xe6, 0x3b, 0x99, 0xbe, 0xe6, 0x4f, 0x9c, 0x4c, - 0x4b, 0xb1, 0x2e, 0x77, 0xb2, 0x7c, 0xf5, 0x35, 0x7f, 0xaa, 0xf2, 0x1c, 0x3d, 0x69, 0x68, 0x1a, 0xdf, 0xef, 0x64, - 0xf9, 0xe6, 0xeb, 0x27, 0x26, 0xcf, 0x57, 0xe3, 0x86, 0xde, 0x72, 0xfe, 0xd1, 0x66, 0x9a, 0xa8, 0xaa, 0xc6, 0x4f, - 0xbe, 0x31, 0xb9, 0x9e, 0x34, 0xf4, 0x5a, 0x14, 0xf5, 0x72, 0xa7, 0xa8, 0xa3, 0xaf, 0x8f, 0xbe, 0xe1, 0x5f, 0xeb, - 0xee, 0x1d, 0x35, 0xf4, 0xcf, 0x75, 0x5c, 0xd6, 0xbc, 0xdc, 0x29, 0xee, 0x6f, 0xdf, 0x7c, 0xf3, 0xc4, 0x64, 0x7c, - 0xd2, 0xd0, 0x7b, 0x1e, 0x77, 0xb4, 0x7d, 0xf2, 0xf4, 0x09, 0xff, 0x5b, 0xd3, 0xd0, 0x5f, 0x98, 0x1b, 0x1c, 0xf5, - 0x34, 0x73, 0xf4, 0xf0, 0x89, 0xf0, 0x51, 0x03, 0x86, 0x0e, 0x1a, 0x40, 0x2e, 0x8c, 0x9a, 0x66, 0x8f, 0x57, 0x2e, - 0xb8, 0x7d, 0x9f, 0xc7, 0x69, 0xbc, 0x82, 0x83, 0x60, 0x83, 0xc6, 0x59, 0x25, 0x70, 0xaa, 0xc0, 0x7b, 0x46, 0x05, - 0xcd, 0x2a, 0xf1, 0x0f, 0xce, 0x3f, 0xc2, 0xa0, 0x21, 0xa4, 0x8d, 0x8c, 0x0c, 0xf4, 0x76, 0xa5, 0x22, 0x1b, 0xa1, - 0xff, 0xa6, 0x1f, 0x07, 0xc7, 0x85, 0xd1, 0xeb, 0xf7, 0xc3, 0x92, 0x55, 0x61, 0x49, 0x08, 0xfd, 0x23, 0x2c, 0xc1, - 0xa1, 0xa4, 0x64, 0x4e, 0x3e, 0xed, 0x7b, 0xae, 0x8c, 0xc2, 0x42, 0x10, 0xdd, 0x45, 0xe6, 0x01, 0x55, 0x8f, 0xae, - 0x43, 0x37, 0xc4, 0xcb, 0x0a, 0x4b, 0x86, 0x0e, 0x66, 0x30, 0x43, 0x50, 0xfc, 0x6b, 0x1e, 0x0a, 0xf0, 0x89, 0x07, - 0xf8, 0xe8, 0x31, 0x99, 0x71, 0x79, 0xad, 0x7d, 0x7b, 0x19, 0x96, 0x34, 0x50, 0x6d, 0x87, 0xa0, 0x03, 0x91, 0xfb, - 0x02, 0x3c, 0x05, 0x06, 0x2e, 0x2c, 0xec, 0x52, 0xec, 0xfa, 0xab, 0xff, 0xa2, 0x59, 0x47, 0x1b, 0x7e, 0xf4, 0x17, - 0xe3, 0xc2, 0x9e, 0x91, 0xa9, 0x38, 0x2e, 0x86, 0x93, 0xe9, 0x60, 0x20, 0x6c, 0x1c, 0xb7, 0xd3, 0x6c, 0xfe, 0xcb, - 0x5c, 0x2c, 0x16, 0xa8, 0xfb, 0xc6, 0x79, 0x9d, 0xa9, 0xbf, 0x91, 0x72, 0x3e, 0x78, 0x7d, 0xfa, 0xdb, 0xf9, 0xd9, - 0xe9, 0x4b, 0x70, 0x3e, 0xf8, 0xf0, 0xe2, 0xfb, 0x17, 0xef, 0x65, 0x70, 0x77, 0x39, 0xe7, 0xfd, 0xbe, 0x95, 0xfa, - 0x84, 0x7c, 0x58, 0x93, 0xc3, 0x30, 0x7e, 0x5c, 0x4a, 0xa3, 0x07, 0x72, 0xcc, 0x0c, 0x14, 0x32, 0x54, 0xd1, 0x98, - 0xdf, 0xc5, 0x70, 0xe2, 0x80, 0x59, 0xdc, 0x7b, 0x22, 0x5c, 0xb7, 0xe5, 0x26, 0xc8, 0x9a, 0x38, 0x71, 0xfa, 0xc1, - 0xc9, 0x54, 0x58, 0xb6, 0xb0, 0x64, 0x50, 0x36, 0xb4, 0xe9, 0x34, 0x9b, 0x97, 0x0b, 0xd3, 0x2e, 0xbb, 0x40, 0x46, - 0x69, 0x76, 0x79, 0x19, 0x4a, 0xe8, 0xea, 0x13, 0xd0, 0x00, 0xe8, 0x46, 0x95, 0xb6, 0x45, 0x7c, 0xe6, 0x96, 0x1f, - 0x8d, 0x9d, 0xe6, 0xdd, 0xa1, 0xee, 0x49, 0x37, 0xab, 0xf6, 0x06, 0x74, 0x30, 0xa1, 0xdc, 0x0e, 0xba, 0x0e, 0x26, - 0x23, 0xdb, 0xf2, 0xcb, 0xbc, 0x5e, 0xe8, 0xe6, 0xd8, 0x61, 0xa8, 0x9d, 0x92, 0xd7, 0xc2, 0x43, 0x64, 0x20, 0x19, - 0x86, 0x3d, 0x1a, 0xa3, 0x48, 0xfd, 0x60, 0xd7, 0x3b, 0x7e, 0x93, 0x0b, 0x88, 0xa6, 0x98, 0x81, 0x74, 0xfe, 0x51, - 0x25, 0x9d, 0xcb, 0x05, 0xe3, 0xf3, 0x6a, 0x71, 0x02, 0x6e, 0xe7, 0xf3, 0x6a, 0x11, 0x61, 0x50, 0xbe, 0x0c, 0x62, - 0x95, 0x80, 0xdd, 0x8b, 0x85, 0xf0, 0xed, 0x84, 0x36, 0x30, 0x1b, 0x48, 0xb0, 0x41, 0x61, 0x56, 0x1a, 0xa2, 0xdc, - 0x49, 0x8f, 0x36, 0x88, 0x3c, 0xc4, 0xea, 0x79, 0xdd, 0xf6, 0x64, 0xd3, 0x17, 0x13, 0x5c, 0x65, 0x31, 0x13, 0xd3, - 0xf8, 0x98, 0x95, 0xd3, 0x18, 0x4a, 0x89, 0xd3, 0x34, 0x8c, 0xe9, 0x84, 0x56, 0x84, 0x24, 0x8c, 0xcf, 0xe3, 0x05, - 0x4d, 0x50, 0x4a, 0x10, 0x42, 0xc8, 0x8f, 0x11, 0xda, 0xe6, 0xc0, 0x92, 0x37, 0xdb, 0xcf, 0xd1, 0xcf, 0xed, 0x18, - 0x2e, 0xa3, 0x22, 0x74, 0x83, 0xce, 0x1a, 0xee, 0x8d, 0xa8, 0xa4, 0x31, 0x56, 0x0c, 0x41, 0xc0, 0x4b, 0x8c, 0x4a, - 0x58, 0x92, 0x98, 0xd5, 0x10, 0x45, 0xa0, 0x98, 0xc7, 0x0b, 0x56, 0x52, 0xdf, 0xe6, 0x34, 0x56, 0x26, 0x41, 0x3d, - 0x8b, 0xa5, 0x76, 0x20, 0xa4, 0x0a, 0xb1, 0xc7, 0x67, 0x55, 0x74, 0xa3, 0x0c, 0x0d, 0x00, 0x05, 0x4a, 0xca, 0xc5, - 0x6f, 0x3f, 0xdf, 0xc3, 0x4d, 0x42, 0xff, 0xb3, 0x8d, 0x8e, 0x76, 0x96, 0xcb, 0x43, 0x6f, 0xbe, 0xa0, 0x71, 0x9e, - 0x43, 0x28, 0x36, 0x8d, 0x40, 0x5e, 0x64, 0x35, 0x44, 0xb4, 0xb8, 0x0f, 0x74, 0x48, 0x38, 0x68, 0xd3, 0x2f, 0x90, - 0xea, 0x89, 0xc9, 0xa5, 0x27, 0x06, 0xc6, 0xed, 0x90, 0x09, 0x05, 0x1c, 0xe9, 0x79, 0xf6, 0x97, 0x8f, 0xb1, 0xa6, - 0xa8, 0x99, 0x8e, 0xb7, 0x21, 0x11, 0x0d, 0x5a, 0x10, 0xcd, 0xe0, 0xfd, 0x73, 0xcd, 0xf1, 0xaa, 0x03, 0x3f, 0xe0, - 0x9d, 0x8d, 0x33, 0x2f, 0x67, 0x1e, 0x91, 0x53, 0x1f, 0xe5, 0x88, 0x7e, 0xc9, 0xc3, 0x7a, 0xa4, 0x92, 0x31, 0x56, - 0x12, 0x07, 0xbd, 0x0d, 0x16, 0xcc, 0x09, 0x5d, 0xf1, 0xd0, 0xf0, 0xf1, 0x2f, 0x91, 0xc9, 0xa8, 0x68, 0xa1, 0xd8, - 0x8d, 0xca, 0x60, 0xc4, 0x39, 0x0d, 0x33, 0x34, 0x59, 0xd2, 0xc5, 0x52, 0x91, 0xe6, 0x4a, 0x9a, 0x06, 0xb8, 0x04, - 0x1a, 0x3c, 0x1f, 0xf4, 0x43, 0x43, 0x3d, 0x84, 0x86, 0xdd, 0x21, 0xe0, 0x23, 0xfb, 0xd0, 0xe1, 0xff, 0xe7, 0xd8, - 0x05, 0x22, 0xed, 0xcd, 0x75, 0x64, 0x3c, 0xd2, 0x78, 0x38, 0x28, 0xda, 0xc7, 0xde, 0x4f, 0xfc, 0xcc, 0x19, 0x7d, - 0x48, 0x2a, 0xdf, 0xe1, 0x83, 0xe5, 0x8e, 0x37, 0xd5, 0xb3, 0x32, 0x82, 0xf5, 0xb0, 0xdd, 0xe2, 0x82, 0x68, 0xbb, - 0x00, 0x52, 0xc7, 0x78, 0xb5, 0x74, 0x8d, 0x57, 0xe3, 0x3d, 0xc6, 0xab, 0xf6, 0x4c, 0x0d, 0x73, 0xb2, 0x41, 0x7d, - 0x96, 0x94, 0xe7, 0xe7, 0x28, 0x13, 0xf4, 0x5d, 0xce, 0x0a, 0x2a, 0x53, 0x09, 0xed, 0xc5, 0x6e, 0xc6, 0xf8, 0x8e, - 0x60, 0x9c, 0x15, 0x8b, 0x91, 0x40, 0x65, 0x2a, 0x69, 0xc2, 0x5e, 0x09, 0xea, 0x31, 0x78, 0xaf, 0x31, 0x44, 0xb5, - 0x8c, 0x5d, 0xb7, 0x81, 0xd0, 0x50, 0x5b, 0x8f, 0xf6, 0x8c, 0xf5, 0xe8, 0x76, 0x5b, 0x6b, 0x7f, 0x3b, 0xb1, 0x2e, - 0x13, 0x44, 0x15, 0x96, 0xa3, 0x09, 0xf0, 0xa6, 0x89, 0xb9, 0x2d, 0x59, 0xa5, 0x05, 0x86, 0xcf, 0xfe, 0x23, 0x2c, - 0xac, 0x4a, 0xa2, 0x20, 0xb3, 0x22, 0x1a, 0xd8, 0x73, 0xf0, 0x79, 0x5c, 0xc3, 0x1a, 0x80, 0x48, 0x8e, 0xe8, 0xe1, - 0xfa, 0x47, 0x28, 0x6c, 0x66, 0x41, 0x66, 0x02, 0x32, 0xf3, 0x22, 0x6d, 0x67, 0x1d, 0x4c, 0xac, 0x49, 0xad, 0x33, - 0x16, 0x62, 0xa8, 0x91, 0x1f, 0x40, 0x19, 0x62, 0xf1, 0xc9, 0x07, 0x13, 0x2a, 0x64, 0x28, 0x55, 0xaf, 0x9b, 0xdd, - 0xc0, 0x2b, 0x1f, 0xb2, 0x6b, 0x5e, 0xd5, 0xf1, 0xf5, 0x4a, 0x5b, 0x12, 0x73, 0xb6, 0xcf, 0x6d, 0x8f, 0x56, 0xfa, - 0xd5, 0x9b, 0x17, 0xdf, 0x9f, 0x7a, 0xaf, 0x76, 0x11, 0x47, 0x43, 0xb0, 0xad, 0x18, 0x63, 0xf4, 0x16, 0x97, 0x06, - 0x13, 0xe9, 0x1a, 0x81, 0xde, 0xa5, 0xa0, 0xdf, 0xfe, 0x5c, 0x4f, 0xc0, 0x6b, 0xae, 0x96, 0x5f, 0xf2, 0x11, 0xb0, - 0x44, 0xf5, 0xac, 0x30, 0x3b, 0x2b, 0xb3, 0xbd, 0xdd, 0x8a, 0xf4, 0xb4, 0x4b, 0x8d, 0x0c, 0xc4, 0xab, 0xed, 0x30, - 0x16, 0x2e, 0x6c, 0xd3, 0xcd, 0x60, 0xd7, 0x4b, 0xc7, 0x12, 0x79, 0xbb, 0x2d, 0xa0, 0x43, 0x66, 0xc0, 0x9d, 0x97, - 0xf1, 0x1d, 0xbc, 0x2c, 0x9c, 0x6e, 0xfa, 0xc1, 0x13, 0xc0, 0x4c, 0xb8, 0xb4, 0x96, 0xc5, 0x31, 0xe3, 0x09, 0xcc, - 0x1f, 0x2d, 0x7d, 0x91, 0xb7, 0x24, 0xb4, 0x7a, 0x7f, 0x85, 0xd5, 0x08, 0xec, 0x4e, 0xce, 0x3e, 0x66, 0xab, 0xd9, - 0x12, 0x50, 0xf3, 0xaf, 0xb3, 0x02, 0x68, 0xae, 0x59, 0x0b, 0xa6, 0x29, 0xd4, 0x5f, 0xd7, 0xcf, 0xe2, 0x55, 0x9c, - 0x80, 0xea, 0x06, 0xbc, 0x45, 0xee, 0x95, 0xe8, 0x4a, 0xa3, 0x8b, 0xd2, 0x07, 0xca, 0x31, 0xa4, 0xd0, 0xd2, 0xf7, - 0x5e, 0x25, 0xcf, 0x3d, 0x0d, 0xb8, 0xa4, 0x50, 0xf3, 0x64, 0x4b, 0x19, 0x0b, 0x80, 0x85, 0x0e, 0x66, 0x92, 0x6c, - 0x45, 0x77, 0x1a, 0x93, 0x02, 0xde, 0x6a, 0xe0, 0x8f, 0x22, 0xab, 0xe5, 0x5d, 0xb1, 0x0a, 0x0b, 0xc7, 0xfe, 0xba, - 0xdf, 0x8f, 0x1d, 0xfb, 0xeb, 0x4b, 0x45, 0xeb, 0xe2, 0x76, 0x03, 0x48, 0x83, 0x01, 0x44, 0x4e, 0xd5, 0x40, 0xe8, - 0x88, 0x62, 0xbe, 0xef, 0xdf, 0xa9, 0xce, 0x22, 0x41, 0xe8, 0x77, 0xea, 0x75, 0xa4, 0x24, 0xa0, 0x53, 0xab, 0xd9, - 0xc9, 0x40, 0x99, 0x7d, 0x40, 0x40, 0x54, 0x37, 0x23, 0x9b, 0x2f, 0xa4, 0x73, 0xb1, 0x0c, 0x1f, 0x3e, 0xa6, 0x10, - 0x50, 0xb8, 0xa3, 0x46, 0xeb, 0x6d, 0x88, 0x04, 0xca, 0x08, 0x45, 0x8c, 0x79, 0xb1, 0x92, 0x84, 0xcc, 0xc7, 0x0b, - 0x14, 0x5c, 0x59, 0x60, 0x57, 0xce, 0x26, 0xc3, 0x22, 0xe2, 0x2c, 0xdc, 0xff, 0xcd, 0x64, 0x41, 0x50, 0x73, 0xe5, - 0x06, 0x72, 0xdc, 0xc9, 0xe4, 0xed, 0x29, 0xaf, 0x86, 0x8a, 0x89, 0x08, 0x02, 0xc3, 0x0d, 0x3f, 0xe3, 0xe3, 0xa3, - 0x05, 0x01, 0x15, 0x99, 0x31, 0x0b, 0xd1, 0x2f, 0x8e, 0xbf, 0x02, 0xd4, 0x98, 0xd1, 0xd1, 0x53, 0x00, 0x85, 0x85, - 0x80, 0xe8, 0x63, 0x90, 0xd1, 0x56, 0xf0, 0xbb, 0x92, 0xbf, 0x5b, 0x27, 0xbe, 0x0b, 0xfd, 0x5a, 0xd1, 0xcb, 0x18, - 0x18, 0x8e, 0x68, 0x72, 0x18, 0xf2, 0xc1, 0x64, 0x00, 0xda, 0x12, 0x67, 0xf7, 0xb5, 0xb4, 0xe2, 0xfa, 0x74, 0xe9, - 0x74, 0xff, 0xa4, 0x3e, 0x48, 0x22, 0x15, 0xac, 0x90, 0xc4, 0x00, 0x42, 0x59, 0xca, 0x6d, 0xb2, 0x04, 0xcb, 0x0a, - 0xbd, 0xa4, 0xb9, 0x46, 0x49, 0xdc, 0xdd, 0x0c, 0x1c, 0xa3, 0x66, 0x9d, 0x86, 0x45, 0xcb, 0x8d, 0x1a, 0xe0, 0x73, - 0x12, 0x56, 0x9a, 0x1b, 0xce, 0x4c, 0x38, 0x67, 0x3a, 0x5c, 0x1d, 0x73, 0xf6, 0x9a, 0x23, 0x18, 0x47, 0x82, 0x37, - 0x1e, 0xba, 0x64, 0x0a, 0x2a, 0x32, 0x65, 0x1c, 0x4c, 0x7b, 0x80, 0x7b, 0xcf, 0xc1, 0x38, 0x8c, 0x0d, 0x6a, 0x43, - 0xea, 0x53, 0xe7, 0x2e, 0x04, 0x82, 0xb4, 0xd6, 0xcb, 0x7c, 0x86, 0xa7, 0x67, 0x84, 0xb2, 0x3f, 0xe4, 0xf0, 0x01, - 0xf0, 0xb2, 0x24, 0x27, 0x13, 0xfe, 0xf4, 0xf1, 0x6e, 0xa0, 0x2a, 0x3e, 0x08, 0x0e, 0xe2, 0x22, 0x3d, 0x08, 0x06, - 0x15, 0xfc, 0x2a, 0xf9, 0x41, 0x2d, 0xc4, 0xc1, 0x65, 0x5c, 0x1e, 0xc4, 0xab, 0xb8, 0xac, 0x0f, 0x6e, 0xb3, 0x7a, - 0x79, 0xa0, 0x3b, 0x04, 0xd0, 0xbc, 0xc1, 0x20, 0x1e, 0x04, 0x07, 0xc1, 0xa0, 0xd4, 0x53, 0xbb, 0x62, 0x85, 0x77, - 0x9c, 0xe9, 0x10, 0x65, 0x81, 0x1f, 0x20, 0xcc, 0x3b, 0x0d, 0x80, 0x4f, 0x5d, 0xb3, 0x94, 0x5e, 0x62, 0xb8, 0x81, - 0x6a, 0xba, 0x86, 0x3e, 0x00, 0x8f, 0xbc, 0xa6, 0x31, 0x2c, 0x81, 0xcb, 0xc1, 0x80, 0xac, 0x21, 0x72, 0xc1, 0x9a, - 0x9a, 0x20, 0x0e, 0xe1, 0x5a, 0xda, 0x69, 0x17, 0x3b, 0x14, 0x76, 0xbb, 0x05, 0x44, 0xe5, 0x09, 0xe9, 0xf7, 0xcd, - 0x37, 0xd4, 0xbd, 0x60, 0x2f, 0xc1, 0xfe, 0xaa, 0xac, 0xc3, 0x44, 0x48, 0xcd, 0xf7, 0x15, 0x3b, 0x19, 0xc8, 0x88, - 0xc3, 0x3b, 0x8e, 0x14, 0x6d, 0x54, 0x2e, 0xc3, 0x9e, 0x2c, 0x3d, 0x5f, 0x89, 0x6b, 0x6e, 0xfd, 0xb8, 0x6a, 0x21, - 0xf2, 0x3a, 0x5b, 0x49, 0xf6, 0x6f, 0xc6, 0x15, 0xf7, 0x07, 0xd6, 0x9f, 0xfe, 0x2b, 0xb8, 0xb6, 0x3a, 0xef, 0x7c, - 0xae, 0x11, 0x39, 0x4b, 0x28, 0x97, 0x34, 0x26, 0x0f, 0x6f, 0xe9, 0xfb, 0xdc, 0xea, 0xdb, 0x4c, 0xa7, 0xf6, 0x59, - 0x85, 0x85, 0x0b, 0xd1, 0x8a, 0xe0, 0xd0, 0x10, 0x0b, 0xff, 0x08, 0xd0, 0xd7, 0x3e, 0x53, 0x41, 0x49, 0x9a, 0xf3, - 0x1a, 0xbd, 0x5b, 0x21, 0xe1, 0xa5, 0x62, 0x97, 0x1e, 0x06, 0x52, 0xc6, 0xed, 0xa1, 0x24, 0x4c, 0x4a, 0x5e, 0x84, - 0xf7, 0x5e, 0x7d, 0x93, 0x7b, 0x1e, 0x62, 0xf4, 0x22, 0xc7, 0x4e, 0x40, 0x5b, 0x77, 0x89, 0xce, 0x86, 0x27, 0x6e, - 0xc3, 0x73, 0xd6, 0xa2, 0xd1, 0x74, 0xc9, 0x92, 0x7e, 0x3f, 0x06, 0x13, 0xef, 0x94, 0xe5, 0xf0, 0x2b, 0x5f, 0xd0, - 0x35, 0x03, 0x4c, 0x31, 0x7a, 0x09, 0x09, 0x29, 0x22, 0x91, 0xac, 0xe5, 0x49, 0xf2, 0x89, 0xee, 0x42, 0x70, 0x84, - 0xcb, 0x59, 0x1a, 0x2d, 0xf7, 0x9a, 0x59, 0x20, 0x79, 0x86, 0xbe, 0xab, 0x60, 0x7b, 0x63, 0x17, 0xa4, 0x9c, 0x1f, - 0x57, 0xd3, 0xc1, 0x80, 0x13, 0x05, 0x37, 0x5e, 0x48, 0x71, 0xad, 0x6a, 0x71, 0xc7, 0x30, 0x16, 0xea, 0xb6, 0x88, - 0xc1, 0x01, 0xbb, 0x68, 0x65, 0xb7, 0x0f, 0xb0, 0xab, 0x1c, 0xef, 0x52, 0x65, 0x77, 0x7a, 0xcc, 0xf8, 0xcb, 0x56, - 0x91, 0x4e, 0x5a, 0xed, 0x27, 0xf2, 0x3e, 0x77, 0xd0, 0xe5, 0x72, 0xac, 0x78, 0xcb, 0x41, 0x45, 0x1e, 0xf3, 0x91, - 0xa4, 0xba, 0x9f, 0xe1, 0x08, 0xf3, 0x60, 0xdd, 0xfa, 0x93, 0x43, 0x5d, 0xe0, 0x10, 0x79, 0x52, 0xaf, 0x29, 0xa0, - 0x7b, 0xaf, 0x1e, 0x77, 0xf5, 0xdb, 0xd0, 0x5d, 0xa0, 0x44, 0x3b, 0x15, 0x7b, 0x7e, 0x4c, 0xd4, 0xea, 0x4c, 0x3d, - 0xa1, 0x7f, 0xad, 0xc5, 0xfd, 0x85, 0x76, 0x15, 0xf7, 0xbd, 0xcb, 0x67, 0x1c, 0xea, 0xec, 0x86, 0x50, 0x00, 0xae, - 0xda, 0xd1, 0xa9, 0x6b, 0x43, 0x7a, 0xa9, 0x44, 0x37, 0xc1, 0xc1, 0xf6, 0xfa, 0x8c, 0xa3, 0xe8, 0x47, 0xab, 0x91, - 0x6f, 0xa3, 0xea, 0xb1, 0x18, 0xc4, 0x8f, 0x4b, 0xba, 0x8c, 0xaa, 0xc7, 0xe5, 0x20, 0x7e, 0x2c, 0x9a, 0x66, 0xf7, - 0x5c, 0xd9, 0xdf, 0x47, 0xe4, 0x59, 0x77, 0xf6, 0x52, 0x01, 0x1b, 0x03, 0xcf, 0xae, 0x05, 0x84, 0x53, 0x70, 0x44, - 0xb6, 0x86, 0x3e, 0x74, 0x6e, 0xf7, 0xb1, 0x61, 0x92, 0x20, 0xe8, 0x79, 0x9b, 0x4d, 0xa2, 0xd8, 0x59, 0xff, 0xe8, - 0xc3, 0x29, 0x10, 0xd0, 0xed, 0xb6, 0x59, 0x57, 0x6b, 0x40, 0x31, 0x0d, 0xc7, 0xfc, 0xb0, 0x1c, 0xdd, 0xba, 0xee, - 0xfa, 0x87, 0xe5, 0x68, 0x49, 0x86, 0x13, 0x3d, 0xf9, 0xf1, 0xc9, 0x78, 0x16, 0x47, 0x93, 0xa6, 0xe3, 0xb4, 0x50, - 0xf8, 0xa7, 0xce, 0x2d, 0x14, 0x81, 0x53, 0x31, 0x82, 0x23, 0xa7, 0xca, 0x49, 0xc9, 0xc3, 0xf0, 0x3f, 0xa8, 0x77, - 0xb4, 0x69, 0xaf, 0xe3, 0x3a, 0x59, 0x66, 0xc5, 0x95, 0x0a, 0x1f, 0xae, 0xa2, 0x8b, 0x9b, 0x80, 0x76, 0xce, 0x65, - 0xda, 0xf2, 0xeb, 0xc4, 0xa3, 0x27, 0xb6, 0x66, 0x06, 0xdc, 0xba, 0x1b, 0xa1, 0x19, 0x02, 0xa3, 0xe5, 0xf9, 0x3b, - 0xc4, 0xdc, 0xfe, 0x55, 0xda, 0xfc, 0x4a, 0xda, 0x67, 0xc9, 0x48, 0xd1, 0x26, 0x23, 0x35, 0x18, 0x61, 0x8a, 0x22, - 0x89, 0xeb, 0xb0, 0x80, 0x20, 0xd8, 0x9f, 0x51, 0x5c, 0x8b, 0xa5, 0x77, 0x1a, 0x84, 0x09, 0xa6, 0x0b, 0xca, 0xaf, - 0x6e, 0xe7, 0xb6, 0xd2, 0x62, 0x8f, 0xe4, 0xf7, 0xb9, 0xb5, 0x5d, 0x51, 0xe4, 0xef, 0xf3, 0x06, 0xd4, 0x03, 0xa2, - 0xdc, 0xd7, 0x47, 0x29, 0x70, 0xd2, 0xe2, 0x86, 0x02, 0xa3, 0x17, 0x74, 0x75, 0x22, 0x77, 0xec, 0xd4, 0x9c, 0xa9, - 0x98, 0xc9, 0xb8, 0xf2, 0x7e, 0xcf, 0xdc, 0x07, 0x4d, 0x41, 0x2b, 0x30, 0xf0, 0xd6, 0x67, 0x3c, 0x3a, 0xd0, 0xdd, - 0x6a, 0x9d, 0x16, 0x6c, 0x16, 0xd4, 0x65, 0xdd, 0xb6, 0xf1, 0xa0, 0x11, 0x07, 0x45, 0xb2, 0x2a, 0x54, 0x4b, 0x78, - 0x22, 0x10, 0x30, 0x65, 0xd7, 0x3c, 0xd2, 0x82, 0x9a, 0xde, 0x84, 0xc2, 0x86, 0x82, 0xbf, 0x52, 0x54, 0xd3, 0x9b, - 0x50, 0x9f, 0x89, 0x53, 0x0c, 0x22, 0x98, 0x11, 0x9b, 0xfd, 0x16, 0x50, 0x7f, 0x6b, 0x46, 0x9b, 0xa6, 0x31, 0xda, - 0x2a, 0xe4, 0x92, 0x22, 0x69, 0xf9, 0x6f, 0xd5, 0x54, 0x50, 0x52, 0xcb, 0x45, 0x6f, 0xe2, 0xbb, 0xe8, 0xf1, 0x4c, - 0x4b, 0x02, 0xa5, 0x5b, 0xee, 0x18, 0xfd, 0x21, 0x0c, 0xf0, 0x88, 0x8e, 0x13, 0x0b, 0xe6, 0x56, 0x27, 0x2c, 0x9b, - 0x57, 0x8b, 0xd1, 0x4a, 0x40, 0xd8, 0xe0, 0x63, 0x96, 0xcd, 0x0b, 0xf5, 0x10, 0xba, 0xc2, 0xd2, 0xb7, 0x60, 0x17, - 0x1b, 0xac, 0x44, 0x15, 0x80, 0xef, 0x05, 0xdd, 0xac, 0x44, 0x15, 0x09, 0xd9, 0xfd, 0xb8, 0xc1, 0x12, 0x64, 0x5a, - 0x29, 0xd3, 0x92, 0x06, 0x0b, 0x02, 0x5f, 0x55, 0x55, 0x3e, 0x24, 0xdb, 0x0a, 0xe4, 0x53, 0x47, 0x0d, 0x38, 0x05, - 0xb2, 0x0a, 0x2c, 0x48, 0x80, 0xca, 0xd0, 0x56, 0x81, 0x69, 0x25, 0xa6, 0xe9, 0x2a, 0x6c, 0x94, 0xd9, 0xa1, 0xd0, - 0xeb, 0x25, 0x9f, 0xc5, 0x83, 0x30, 0x19, 0xc6, 0xe4, 0x31, 0x42, 0xed, 0x1f, 0xe6, 0x51, 0xac, 0xe4, 0x92, 0x2b, - 0xeb, 0x17, 0x7f, 0xfb, 0x09, 0x7b, 0xdd, 0x73, 0x0c, 0x16, 0x60, 0x2d, 0x6d, 0xaf, 0xb3, 0xe2, 0x9d, 0x68, 0x05, - 0xc7, 0xc1, 0x2c, 0xd2, 0x61, 0xd5, 0x91, 0x23, 0xea, 0x8b, 0x5c, 0x7b, 0x17, 0x21, 0x72, 0x90, 0xde, 0x63, 0x80, - 0xdd, 0x08, 0x5f, 0x87, 0xc6, 0xe6, 0x56, 0x55, 0x88, 0xbf, 0x51, 0x22, 0xf1, 0x93, 0x10, 0x1f, 0xd7, 0x2b, 0x99, - 0xab, 0xd6, 0x78, 0xac, 0xaa, 0x19, 0x3c, 0x53, 0xbe, 0xc7, 0xca, 0xbf, 0xb5, 0xdd, 0x1c, 0xe7, 0x3d, 0x78, 0xd0, - 0xba, 0xdf, 0x3a, 0x12, 0x42, 0x73, 0xe5, 0x24, 0x4d, 0x47, 0x8d, 0x8e, 0x99, 0xac, 0x16, 0x95, 0x30, 0xb9, 0x3b, - 0xa5, 0x63, 0xa0, 0xa2, 0x03, 0xb8, 0x96, 0xa8, 0x0e, 0x7a, 0x52, 0xb2, 0x31, 0x1c, 0x71, 0x06, 0x07, 0xed, 0x38, - 0x46, 0xf1, 0x72, 0x2e, 0xc5, 0xcb, 0xf9, 0x09, 0xe3, 0x00, 0xad, 0x05, 0x48, 0xf5, 0x0a, 0xf6, 0x33, 0x97, 0xb0, - 0xc0, 0xfa, 0xce, 0x77, 0x64, 0x80, 0x0c, 0x71, 0xb2, 0x39, 0x4e, 0xf6, 0xb8, 0x51, 0x73, 0x5f, 0xe1, 0xe3, 0xa4, - 0x59, 0x38, 0x75, 0x15, 0xed, 0xba, 0x96, 0xac, 0x98, 0x97, 0x83, 0x09, 0x04, 0x65, 0x29, 0xe6, 0xe5, 0x70, 0xb2, - 0xa0, 0x39, 0xfc, 0x58, 0x78, 0xe8, 0x10, 0xcb, 0x41, 0x02, 0x97, 0xce, 0x1e, 0x03, 0xde, 0x50, 0x28, 0x71, 0x37, - 0xd6, 0x91, 0x63, 0x1d, 0xe5, 0x61, 0x18, 0x03, 0xae, 0xac, 0x15, 0x78, 0xef, 0xbf, 0x3e, 0xfa, 0x80, 0xac, 0xca, - 0x15, 0x5e, 0x8e, 0x72, 0xd7, 0x95, 0x46, 0x5d, 0x52, 0x7a, 0x95, 0x13, 0x3c, 0x95, 0x6c, 0xb7, 0x3d, 0x63, 0x4f, - 0xe5, 0x20, 0xf1, 0x8e, 0x11, 0xbd, 0x98, 0x7a, 0x99, 0x39, 0x81, 0x33, 0xdb, 0x5e, 0xb6, 0x31, 0x3f, 0x76, 0x80, - 0x83, 0x45, 0x10, 0x12, 0x37, 0x84, 0x61, 0x62, 0x27, 0xc5, 0x50, 0x09, 0xe1, 0xba, 0x16, 0x5e, 0xc7, 0x69, 0x19, - 0x83, 0x8b, 0xb4, 0xb2, 0x4d, 0xdc, 0x43, 0xd7, 0x1d, 0x3f, 0xe6, 0x56, 0xc7, 0x68, 0xcb, 0x7c, 0xb8, 0xa3, 0xd3, - 0x07, 0x16, 0x03, 0x50, 0xf7, 0x60, 0x56, 0xb7, 0xcf, 0x24, 0xae, 0x4f, 0xbb, 0x8a, 0x90, 0x08, 0x44, 0x51, 0x2a, - 0x23, 0x4c, 0xff, 0x4e, 0x73, 0x59, 0x4d, 0xeb, 0x07, 0x79, 0xe6, 0x90, 0x67, 0xa1, 0xb3, 0x3d, 0x68, 0xed, 0xef, - 0x06, 0xed, 0xc4, 0x6d, 0xf7, 0xce, 0xff, 0x5b, 0xd6, 0xb5, 0xd5, 0x9a, 0xea, 0x71, 0xbb, 0xfa, 0x81, 0xb7, 0x57, - 0x7b, 0x32, 0x06, 0xcc, 0x4a, 0x38, 0x67, 0x54, 0xc5, 0xcb, 0x8c, 0x57, 0x78, 0x52, 0xad, 0x3c, 0x1f, 0xef, 0xdb, - 0x6c, 0xa4, 0x1f, 0xc8, 0x14, 0x10, 0xcf, 0x6f, 0x53, 0xad, 0x3e, 0x4e, 0x51, 0x02, 0xfe, 0x4e, 0xc5, 0x37, 0xa2, - 0x1f, 0xcd, 0x8b, 0x2b, 0x5e, 0xbf, 0xbd, 0x2d, 0xf4, 0x8b, 0xe7, 0x46, 0xe7, 0x4f, 0x5f, 0x97, 0x2e, 0x74, 0x38, - 0x6a, 0xef, 0xa0, 0xc8, 0x82, 0x55, 0x27, 0x13, 0x2d, 0x6b, 0xab, 0x66, 0x1f, 0x25, 0x5c, 0x4c, 0x54, 0xa3, 0x67, - 0x9d, 0x39, 0x61, 0x4a, 0xd0, 0x37, 0x8e, 0x51, 0xc9, 0x18, 0x96, 0x0c, 0xd4, 0x69, 0x52, 0x88, 0x1e, 0x56, 0x33, - 0x8c, 0x57, 0x0c, 0xa0, 0x30, 0xa5, 0x04, 0x51, 0xb4, 0x06, 0xc1, 0x40, 0x13, 0xfa, 0xfd, 0xdb, 0x54, 0x65, 0xa0, - 0x45, 0x33, 0x15, 0x20, 0xaa, 0x83, 0x68, 0xab, 0xbc, 0x0c, 0x7f, 0x5c, 0xd2, 0x22, 0xa3, 0x79, 0x45, 0x97, 0x15, - 0x4d, 0x32, 0x7a, 0xc9, 0xa5, 0xa8, 0x78, 0x5d, 0x31, 0x49, 0xdb, 0x35, 0x61, 0xff, 0x97, 0x47, 0xd7, 0x5b, 0xb1, - 0xd6, 0xd0, 0xee, 0x04, 0x19, 0xa1, 0xf9, 0x42, 0x05, 0x21, 0x43, 0xe5, 0x24, 0x74, 0xad, 0x56, 0x78, 0x05, 0x36, - 0x99, 0x66, 0xa3, 0x65, 0x5c, 0x85, 0x81, 0xf9, 0x2a, 0x30, 0x98, 0x1c, 0x98, 0x74, 0xb6, 0xbe, 0x78, 0x26, 0xae, - 0x57, 0xa2, 0xe0, 0x45, 0x2d, 0x21, 0xfa, 0x35, 0xee, 0xbb, 0x8e, 0xab, 0xce, 0xfc, 0x5a, 0xe9, 0x43, 0xdf, 0xba, - 0xac, 0x8d, 0xfd, 0x42, 0xe3, 0x18, 0xec, 0x7c, 0x44, 0x34, 0xa4, 0x41, 0xad, 0x5a, 0x1c, 0xea, 0x00, 0x5d, 0x2a, - 0xa4, 0x90, 0x21, 0x53, 0x99, 0x2c, 0x41, 0xc6, 0x37, 0x7e, 0x2f, 0x44, 0x3d, 0xfa, 0x73, 0xcd, 0xcb, 0xfb, 0x33, - 0x9e, 0x73, 0x1c, 0xa3, 0x20, 0x89, 0x8b, 0x9b, 0xb8, 0x0a, 0x88, 0x6b, 0x79, 0x15, 0x1c, 0xa5, 0x3a, 0x6c, 0xcc, - 0x4e, 0xd5, 0xa8, 0xf5, 0x12, 0xe8, 0x2b, 0x23, 0x7d, 0x63, 0x30, 0x34, 0x11, 0x95, 0xd0, 0xf7, 0x4a, 0xdd, 0xd3, - 0xea, 0x86, 0x01, 0xc4, 0x9f, 0x4b, 0xbd, 0x50, 0xeb, 0xb5, 0x1f, 0x73, 0x43, 0x47, 0x08, 0x1a, 0x7d, 0xd5, 0x2c, - 0x1a, 0xc7, 0x2d, 0x4d, 0x46, 0xc6, 0x8d, 0x36, 0x39, 0xbf, 0x02, 0x19, 0x9f, 0x35, 0x17, 0x9a, 0x34, 0x0d, 0x95, - 0x50, 0x85, 0xd1, 0xe6, 0xce, 0x4b, 0xa7, 0xf7, 0xe0, 0xce, 0xa6, 0xcd, 0x8e, 0x94, 0x4b, 0x63, 0x43, 0x4b, 0x5e, - 0xad, 0x44, 0x51, 0x41, 0x18, 0xe7, 0xde, 0x98, 0x5e, 0xc7, 0x59, 0x51, 0xc7, 0x59, 0x71, 0x5a, 0xad, 0x78, 0x52, - 0xbf, 0x87, 0x5b, 0x9c, 0xb4, 0xba, 0x69, 0x2a, 0xb8, 0xd2, 0x25, 0x07, 0x18, 0x4c, 0x4d, 0xc6, 0x3d, 0xb6, 0x06, - 0x17, 0xf5, 0xef, 0xd1, 0x52, 0x60, 0x2c, 0x54, 0x55, 0x7c, 0x7c, 0x51, 0x89, 0x7c, 0x5d, 0x83, 0x76, 0xf7, 0xb2, - 0x8e, 0x8e, 0x9e, 0xac, 0xee, 0xa6, 0xf2, 0x06, 0x13, 0x3d, 0x39, 0x5a, 0xdd, 0xf5, 0xb2, 0xeb, 0x95, 0x28, 0xeb, - 0xb8, 0xa8, 0xa7, 0x12, 0x91, 0x2c, 0x89, 0xf3, 0x24, 0x9c, 0x8c, 0xc7, 0x5f, 0x1c, 0x0c, 0x0f, 0x20, 0x03, 0x99, - 0xfe, 0x35, 0x94, 0x2e, 0x47, 0xc3, 0xc9, 0x78, 0x3c, 0x15, 0xf2, 0x6e, 0x17, 0x8d, 0x26, 0x0d, 0xd6, 0x33, 0x4c, - 0xd4, 0xcc, 0x8c, 0xf8, 0xdd, 0x2a, 0x2e, 0x52, 0x88, 0x5f, 0xa7, 0x8a, 0x3f, 0x7a, 0x32, 0xf6, 0xca, 0x37, 0x9f, - 0x3e, 0x6d, 0x7e, 0x6f, 0x74, 0x58, 0x6b, 0xdd, 0xee, 0x67, 0xbf, 0x1f, 0xcb, 0xf9, 0x3e, 0x39, 0x3e, 0x54, 0x3f, - 0x7e, 0x6f, 0x9a, 0xe9, 0xeb, 0x32, 0x9c, 0xff, 0x33, 0x94, 0xf3, 0x79, 0x5a, 0x96, 0xf1, 0x7d, 0x43, 0x16, 0x74, - 0x5d, 0x59, 0x6f, 0x12, 0xea, 0x6c, 0x03, 0x7a, 0x44, 0xa6, 0xeb, 0x8a, 0xc1, 0x37, 0xef, 0xeb, 0x30, 0xe0, 0xd5, - 0x6a, 0xc8, 0x8b, 0x3a, 0xab, 0xef, 0x87, 0x98, 0x27, 0xc0, 0x4f, 0x35, 0x6f, 0xf6, 0xac, 0xd4, 0xc4, 0xe6, 0xb2, - 0xe4, 0xfc, 0x2f, 0x1e, 0x4a, 0xe3, 0xe8, 0x31, 0x1a, 0x47, 0x8f, 0xa9, 0x1c, 0x8c, 0xc9, 0xd7, 0x54, 0x75, 0x66, - 0xf2, 0x35, 0x98, 0x20, 0x65, 0xed, 0x6f, 0xa4, 0x71, 0x62, 0x34, 0xa6, 0x37, 0x2f, 0xf3, 0x6c, 0x05, 0x4c, 0xf0, - 0x52, 0xfd, 0x68, 0x08, 0x7d, 0xcf, 0xdb, 0xd9, 0x47, 0xa3, 0xd1, 0xb3, 0x92, 0x8e, 0x46, 0xa3, 0x8f, 0x59, 0x43, - 0xe8, 0x65, 0xd5, 0xf1, 0xfe, 0x3d, 0xa7, 0x17, 0x22, 0xbd, 0x8f, 0x82, 0x80, 0x2e, 0xb3, 0x34, 0xe5, 0x85, 0x2c, - 0xeb, 0x2c, 0x6d, 0xe7, 0x95, 0x2d, 0x44, 0xe0, 0x1f, 0xd5, 0x46, 0x84, 0x20, 0x22, 0xf4, 0xed, 0x4e, 0xcf, 0x46, - 0xa3, 0xd1, 0x59, 0xaa, 0xab, 0xb5, 0x0c, 0xf9, 0x6b, 0x34, 0x1f, 0xb0, 0x76, 0xf9, 0x60, 0x7d, 0xa3, 0xa3, 0x9d, - 0x1c, 0xfe, 0xf7, 0x70, 0x36, 0x1f, 0x0f, 0xbf, 0x1d, 0x2d, 0x1e, 0x1f, 0xd2, 0x20, 0x70, 0x41, 0xab, 0x43, 0x65, - 0xcd, 0x31, 0x2d, 0x8e, 0xc7, 0x53, 0x52, 0x0c, 0xd8, 0x13, 0xe3, 0x4b, 0xf3, 0xc5, 0x13, 0x40, 0x22, 0x45, 0x11, - 0x6a, 0x60, 0xa5, 0x7f, 0x78, 0x15, 0x79, 0x55, 0x00, 0x3e, 0x9a, 0x89, 0x64, 0xa0, 0xb5, 0x80, 0xe3, 0x08, 0xca, - 0x6b, 0x8c, 0x69, 0x44, 0x8f, 0xb1, 0x4c, 0x47, 0x05, 0x1d, 0x4f, 0xab, 0xdb, 0xac, 0x4e, 0x96, 0x18, 0xd8, 0x28, - 0xae, 0x78, 0xf0, 0x45, 0x10, 0x15, 0xec, 0xe8, 0xe9, 0x54, 0xc2, 0xfb, 0x62, 0x52, 0xca, 0xaf, 0x20, 0xf1, 0xdb, - 0x31, 0x42, 0xa0, 0x12, 0xe5, 0xb1, 0x88, 0x35, 0xbe, 0xcc, 0x45, 0x0c, 0x1e, 0x9c, 0x95, 0xe2, 0x59, 0xcc, 0x49, - 0x60, 0xec, 0x2f, 0x5a, 0xcd, 0x11, 0xd0, 0x9c, 0x50, 0x30, 0x71, 0x58, 0x50, 0xf1, 0xc5, 0x04, 0xbd, 0x82, 0xc0, - 0xad, 0x3a, 0x82, 0xe3, 0xce, 0x58, 0x36, 0xa8, 0xe5, 0x93, 0xb2, 0xc3, 0xf9, 0xff, 0xae, 0xe8, 0x62, 0x70, 0x68, - 0x87, 0xe6, 0xad, 0x72, 0x5f, 0xad, 0x91, 0x51, 0xaa, 0xc3, 0x67, 0x29, 0x31, 0xc6, 0xa7, 0x9c, 0x9d, 0x6c, 0x74, - 0x77, 0x46, 0x75, 0x99, 0x5d, 0x87, 0x44, 0xf5, 0xca, 0x82, 0x62, 0x06, 0x51, 0x36, 0xc2, 0xf5, 0x03, 0xd6, 0x22, - 0x4e, 0x27, 0x6f, 0x78, 0x59, 0x67, 0x89, 0x7c, 0x7f, 0xe3, 0xbd, 0x07, 0x6a, 0x20, 0x1b, 0xf4, 0xae, 0x64, 0x30, - 0xcf, 0x6f, 0x4b, 0x00, 0xed, 0xac, 0x78, 0x79, 0xc3, 0x5d, 0xba, 0x11, 0x04, 0x8d, 0x6d, 0xe6, 0x95, 0x17, 0x6c, - 0x02, 0xbe, 0x7a, 0x57, 0x02, 0xe6, 0x46, 0x08, 0x52, 0x53, 0x08, 0x85, 0x03, 0x17, 0xf8, 0xba, 0x2e, 0xb3, 0x8b, - 0x75, 0xcd, 0x31, 0xd8, 0x47, 0x61, 0xb5, 0x98, 0xd2, 0x09, 0x8f, 0x87, 0x01, 0xfe, 0x08, 0xa8, 0x0c, 0xb8, 0xa1, - 0x3d, 0xec, 0xe0, 0x85, 0xfc, 0x65, 0xdf, 0xc8, 0x3d, 0xc2, 0x5e, 0xa7, 0x21, 0x04, 0xd7, 0xc1, 0x87, 0x00, 0x96, - 0x14, 0xa1, 0x6f, 0xf1, 0x54, 0x0d, 0x83, 0xcb, 0x3c, 0x5b, 0xa9, 0xa4, 0x7a, 0xd4, 0xd1, 0x7c, 0x28, 0xb5, 0x23, - 0x39, 0xa0, 0x4e, 0x7a, 0x8c, 0xe9, 0xa5, 0x4c, 0x97, 0x45, 0x59, 0x23, 0x94, 0x77, 0x6a, 0x62, 0x6c, 0x98, 0x3e, - 0x0e, 0x91, 0x5f, 0xde, 0x95, 0x32, 0xf4, 0x0b, 0x5f, 0x00, 0xf8, 0x15, 0xdc, 0xee, 0x77, 0xe3, 0xbb, 0xc8, 0xec, - 0xe7, 0x9c, 0x1d, 0xfe, 0xf7, 0x3c, 0x1e, 0xfe, 0x35, 0x1e, 0x7e, 0xbb, 0x18, 0x84, 0x43, 0xf3, 0x93, 0x3c, 0x7e, - 0x74, 0x48, 0x5f, 0x72, 0xc3, 0x95, 0xc0, 0xc2, 0xf7, 0x82, 0xdb, 0xc8, 0x95, 0x10, 0x44, 0x01, 0xde, 0x28, 0xec, - 0x6a, 0x9c, 0x00, 0xc0, 0x5f, 0xf0, 0x5f, 0x01, 0x1a, 0x09, 0xd9, 0x8b, 0x06, 0xe8, 0x07, 0xe4, 0xef, 0x93, 0xaf, - 0x3c, 0x03, 0x39, 0x10, 0x4f, 0xc8, 0x18, 0x28, 0x44, 0x95, 0x31, 0x91, 0xb0, 0xbf, 0x26, 0xfb, 0x76, 0xdb, 0x6b, - 0x4b, 0x7e, 0xf0, 0x4b, 0x37, 0xd3, 0x44, 0xcf, 0x3b, 0xdc, 0x50, 0x56, 0x62, 0x15, 0x22, 0x36, 0x9e, 0xfa, 0x95, - 0x33, 0x88, 0x35, 0x79, 0x93, 0x81, 0x0f, 0x83, 0xf9, 0x62, 0x3c, 0x03, 0x69, 0x11, 0xdc, 0x71, 0x4a, 0x7e, 0x99, - 0x81, 0x5b, 0x73, 0x11, 0xe3, 0x05, 0xdb, 0x2c, 0x89, 0x7e, 0xbf, 0x97, 0x67, 0x61, 0xae, 0x70, 0x96, 0xf3, 0x46, - 0x8b, 0xdd, 0x51, 0x27, 0x0c, 0xe2, 0x76, 0x35, 0x04, 0x43, 0x39, 0x04, 0x65, 0x47, 0x5b, 0x6c, 0xbd, 0xa6, 0x9e, - 0x52, 0xf7, 0x56, 0xd6, 0x57, 0x8e, 0xfe, 0x10, 0x59, 0x81, 0x85, 0xb4, 0x6b, 0x8e, 0x55, 0xcd, 0x31, 0xd2, 0x9e, - 0x7e, 0xbf, 0xf2, 0xc8, 0x4f, 0x67, 0xe1, 0x41, 0x20, 0x4b, 0x15, 0x3b, 0x65, 0x51, 0x6e, 0x4a, 0x73, 0xc6, 0xb0, - 0xa1, 0x79, 0x66, 0xe2, 0xba, 0xcc, 0x7a, 0xbd, 0x30, 0x44, 0x87, 0x46, 0x2c, 0x15, 0x6b, 0x83, 0xf0, 0x3e, 0x3a, - 0x61, 0x74, 0x0d, 0xb2, 0xba, 0xf0, 0x9c, 0x13, 0xe4, 0xcb, 0xc0, 0x64, 0x4d, 0x56, 0xeb, 0xe4, 0x84, 0x47, 0x2f, - 0x5f, 0x36, 0x82, 0x06, 0x39, 0x49, 0x51, 0x6f, 0x62, 0x77, 0xec, 0xa3, 0x16, 0x52, 0xe3, 0xa6, 0x99, 0xf6, 0x14, - 0xa9, 0xe8, 0xb1, 0x5e, 0x2d, 0x7f, 0x81, 0x65, 0x81, 0x21, 0x1f, 0x84, 0xf6, 0x14, 0xad, 0xc0, 0x0c, 0x37, 0x26, - 0x83, 0xa6, 0x1f, 0x16, 0x6d, 0x11, 0x3a, 0x23, 0xb7, 0x25, 0x84, 0x6d, 0x1b, 0x84, 0xb5, 0xf3, 0x44, 0xbe, 0x78, - 0xe2, 0x30, 0xc2, 0x21, 0xd7, 0x9b, 0xb9, 0xf2, 0x30, 0xcc, 0xaf, 0x85, 0xdf, 0x3c, 0xd5, 0x5c, 0x27, 0x2a, 0x66, - 0x05, 0xdb, 0xed, 0xb2, 0x22, 0xf8, 0xf7, 0x63, 0x36, 0xc3, 0xbf, 0x59, 0xbf, 0xdf, 0x0b, 0xf1, 0x17, 0xc7, 0xe0, - 0x3d, 0xf3, 0x6a, 0xc1, 0x3e, 0x82, 0x4c, 0x85, 0x44, 0x98, 0x2a, 0x8d, 0xdf, 0x58, 0x0d, 0x16, 0x70, 0xfa, 0x03, - 0x99, 0x0b, 0x33, 0x99, 0xcb, 0x8b, 0x6d, 0xc8, 0x69, 0x6b, 0x9c, 0xb2, 0x51, 0x96, 0x48, 0xd7, 0x85, 0x6c, 0x14, - 0xe7, 0x59, 0x5c, 0xf1, 0x6a, 0xbb, 0x55, 0x87, 0x63, 0x52, 0x72, 0xf4, 0x2b, 0x40, 0x2a, 0x55, 0xb0, 0x8e, 0x54, - 0x3b, 0xfe, 0x22, 0x2c, 0x71, 0x9f, 0xf2, 0x79, 0xb9, 0x30, 0x7b, 0x6b, 0x5e, 0x2e, 0x98, 0xbc, 0x95, 0xf6, 0xc2, - 0x12, 0x9a, 0x57, 0x10, 0xb2, 0xc1, 0x54, 0xc7, 0xa2, 0x35, 0x66, 0xd5, 0xbc, 0x5c, 0x40, 0x18, 0x99, 0x72, 0x01, - 0x36, 0x53, 0xbc, 0x00, 0x2f, 0x92, 0x18, 0x60, 0xe2, 0x62, 0x32, 0x85, 0x78, 0xe6, 0xb2, 0x9c, 0x78, 0xa1, 0xef, - 0x97, 0x89, 0x45, 0xca, 0x80, 0x57, 0x8d, 0x46, 0x13, 0x33, 0x0d, 0x47, 0x9d, 0x20, 0x27, 0x3a, 0xbf, 0x9b, 0x5a, - 0x11, 0x62, 0x4f, 0x1c, 0x01, 0x97, 0x15, 0xd3, 0x85, 0x17, 0x1d, 0x88, 0x31, 0x72, 0x70, 0x8a, 0x4f, 0x0c, 0x8e, - 0xc2, 0xe0, 0xdc, 0x38, 0x27, 0x48, 0x19, 0xc6, 0x64, 0x23, 0xd8, 0xb5, 0x08, 0xab, 0x79, 0xbc, 0x00, 0x65, 0x5d, - 0xbc, 0x00, 0xcb, 0x1a, 0x6d, 0x80, 0x09, 0xf2, 0x2a, 0xee, 0x84, 0x7e, 0xa2, 0xb8, 0x42, 0x84, 0x63, 0xe5, 0xfa, - 0xa8, 0x6c, 0x87, 0xbe, 0xc0, 0xeb, 0xbd, 0x34, 0xc7, 0xcd, 0x7a, 0x2c, 0x10, 0xd8, 0x10, 0x30, 0x36, 0x52, 0x69, - 0xb2, 0xb5, 0xf6, 0x8d, 0x9e, 0x07, 0x3e, 0xcd, 0x46, 0x85, 0xa8, 0xcf, 0x2f, 0x41, 0x84, 0xe2, 0xa2, 0xc1, 0x23, - 0xbf, 0x88, 0x3b, 0x4b, 0xbf, 0x35, 0x2d, 0x2a, 0xd8, 0xc9, 0x06, 0x40, 0xfa, 0x54, 0xb4, 0x28, 0x29, 0xa7, 0x28, - 0x48, 0x63, 0x37, 0x05, 0xac, 0x24, 0x77, 0x01, 0x43, 0xb0, 0xb1, 0x83, 0xca, 0xea, 0x14, 0x11, 0x49, 0x02, 0x91, - 0x15, 0xc3, 0x82, 0xe2, 0xd8, 0x16, 0x88, 0xfa, 0x69, 0xca, 0x32, 0x83, 0xa1, 0xa3, 0xe2, 0x3e, 0x4f, 0x1d, 0x4a, - 0x14, 0x04, 0x54, 0x0d, 0x39, 0x48, 0x6c, 0x4d, 0x03, 0xe1, 0x01, 0x79, 0x44, 0x67, 0xac, 0xbf, 0xcf, 0x3a, 0xcf, - 0x2e, 0x34, 0x47, 0xe5, 0x6a, 0x57, 0xe8, 0x31, 0xc2, 0x93, 0x4c, 0xc3, 0xe4, 0x3b, 0xe7, 0x99, 0x56, 0x53, 0xf4, - 0x1c, 0x7c, 0xb2, 0x53, 0x8c, 0x48, 0xb7, 0x67, 0xd0, 0x75, 0xf0, 0xaa, 0x0e, 0x1b, 0xed, 0x5a, 0x42, 0x48, 0xe8, - 0x5a, 0x14, 0x31, 0xeb, 0x19, 0x03, 0xea, 0xed, 0xb6, 0xa7, 0xe6, 0x6a, 0xff, 0xdc, 0x6d, 0xb7, 0x3d, 0xec, 0xd6, - 0xf3, 0xb4, 0xdb, 0x0a, 0xbc, 0x96, 0x1f, 0xb4, 0xc7, 0x9f, 0xdb, 0xf1, 0xe7, 0x1a, 0xc9, 0xa3, 0xb0, 0x34, 0xd3, - 0xd4, 0x07, 0xe1, 0x70, 0xd3, 0x7b, 0xaf, 0x49, 0xdf, 0x67, 0xa1, 0xa0, 0x97, 0x95, 0x57, 0x5d, 0x63, 0x4d, 0x2a, - 0x1f, 0x5c, 0xff, 0x0f, 0xaf, 0x02, 0x3c, 0xe2, 0xe4, 0xce, 0xde, 0xdb, 0xa0, 0xd2, 0x6b, 0x0b, 0x47, 0x8a, 0xd0, - 0x03, 0x92, 0xb0, 0xaf, 0x65, 0x2d, 0x6e, 0xf3, 0x2c, 0x7b, 0x98, 0x3e, 0xbd, 0x4a, 0x5d, 0xab, 0x7b, 0xbb, 0xcc, - 0x32, 0x7d, 0xe0, 0xd5, 0x14, 0x07, 0x34, 0xea, 0xa2, 0x7d, 0xd7, 0x59, 0x55, 0x81, 0x97, 0x07, 0x5c, 0x9f, 0xcf, - 0xb8, 0x0b, 0x37, 0x77, 0x55, 0xfb, 0x9b, 0xf4, 0x2c, 0x9b, 0x67, 0x8b, 0xed, 0x36, 0xc4, 0xbf, 0x5d, 0x2d, 0xb2, - 0x34, 0x79, 0x0e, 0x3a, 0x3c, 0x8c, 0xdc, 0xc3, 0x54, 0xe3, 0x9c, 0xcd, 0xff, 0xb2, 0xf2, 0x9c, 0x04, 0x4e, 0x81, - 0x5e, 0xcc, 0x1e, 0x81, 0x0c, 0x46, 0x3b, 0xf5, 0x57, 0x33, 0xb5, 0x66, 0x20, 0xfa, 0x56, 0x15, 0x01, 0x8e, 0x2e, - 0x36, 0x12, 0x8d, 0x2c, 0x38, 0x69, 0x08, 0x58, 0x6c, 0x9a, 0xf2, 0x3e, 0x18, 0xda, 0x56, 0x97, 0xf7, 0xce, 0x92, - 0xe6, 0xb8, 0x0e, 0xac, 0x6d, 0xbf, 0x1e, 0x62, 0x5d, 0x76, 0xbd, 0x40, 0xee, 0x97, 0x37, 0xb4, 0x37, 0x6e, 0x12, - 0x98, 0xb5, 0x4d, 0x63, 0x18, 0x3f, 0x53, 0xfa, 0x4f, 0x6a, 0x70, 0xa5, 0xf1, 0xd3, 0x5c, 0x5b, 0x25, 0x98, 0x7d, - 0xe3, 0xf8, 0x0e, 0x40, 0x38, 0x36, 0x97, 0x1e, 0x9f, 0x65, 0x0e, 0x3d, 0x06, 0xa2, 0xa3, 0x3f, 0x2a, 0xec, 0x47, - 0x66, 0xf7, 0xba, 0x01, 0xf0, 0xe6, 0x75, 0xbb, 0xa0, 0x79, 0xb1, 0x80, 0x40, 0xa2, 0x4e, 0x79, 0xa5, 0xe1, 0x33, - 0x63, 0x76, 0x05, 0x64, 0xa8, 0x24, 0x60, 0x93, 0xd4, 0x75, 0x2e, 0xc4, 0xb2, 0xc3, 0xd2, 0x7c, 0x24, 0x61, 0x27, - 0x21, 0xa0, 0xbd, 0x06, 0xc1, 0x2c, 0xf8, 0xaf, 0x60, 0x50, 0x0c, 0x82, 0x28, 0x88, 0x82, 0x80, 0x0c, 0x4a, 0xf8, - 0x85, 0x38, 0x63, 0x04, 0x63, 0x94, 0x40, 0x87, 0xdf, 0x71, 0xe6, 0x32, 0x22, 0x2f, 0xbc, 0x30, 0x96, 0x76, 0x00, - 0x2e, 0x84, 0xc8, 0x79, 0x8c, 0x3e, 0x16, 0xef, 0x38, 0xcb, 0x08, 0x7d, 0xe7, 0x9c, 0xca, 0x8f, 0xb8, 0x17, 0xdc, - 0x6e, 0x77, 0xd8, 0x5e, 0xf2, 0x30, 0xa3, 0xbd, 0x31, 0x7d, 0xc7, 0x49, 0x94, 0x79, 0xce, 0xc3, 0x1c, 0x7a, 0x56, - 0x1b, 0xd6, 0x8a, 0x6a, 0x72, 0x83, 0x62, 0x5d, 0x64, 0x99, 0xac, 0x0c, 0x57, 0xce, 0x69, 0x85, 0xeb, 0xce, 0xac, - 0x17, 0x90, 0x94, 0x55, 0x8a, 0xa5, 0x33, 0xe1, 0xab, 0x4d, 0xcb, 0x9e, 0xb7, 0x4e, 0x21, 0xa7, 0x21, 0x32, 0xfa, - 0xa1, 0x25, 0xa0, 0x9a, 0x56, 0x5c, 0xd5, 0xe0, 0xb2, 0xab, 0xdb, 0xc3, 0x75, 0x7b, 0x74, 0x33, 0x3e, 0x40, 0x8c, - 0x38, 0x8e, 0x2d, 0x03, 0xbb, 0x09, 0x8b, 0x67, 0x63, 0x7d, 0x5f, 0x76, 0xe9, 0xad, 0xad, 0xc5, 0x21, 0xac, 0x3d, - 0x67, 0x85, 0x84, 0x00, 0x69, 0xa9, 0x2b, 0xdd, 0x6e, 0x83, 0x00, 0x06, 0xb8, 0xdf, 0xef, 0x01, 0xd7, 0xaa, 0xd9, - 0x49, 0x7d, 0x6b, 0x36, 0xc4, 0x5e, 0x52, 0x78, 0x0c, 0x44, 0xa9, 0xf8, 0xcf, 0x20, 0xa0, 0x78, 0xee, 0x86, 0x60, - 0x5f, 0xc9, 0x4e, 0x36, 0x65, 0xbf, 0xff, 0xbc, 0xc4, 0x07, 0x94, 0x83, 0x82, 0x58, 0x57, 0xc5, 0xad, 0xd0, 0xec, - 0x93, 0xfc, 0x10, 0xc7, 0x22, 0xcf, 0x42, 0x4b, 0x58, 0x6a, 0x4d, 0x58, 0xb8, 0x64, 0xa4, 0x83, 0x38, 0x68, 0x48, - 0xe7, 0x60, 0xd5, 0x36, 0xd8, 0x70, 0xaf, 0xf7, 0xb2, 0x0a, 0x2b, 0x9a, 0x39, 0xc3, 0xf2, 0xde, 0x01, 0x00, 0xeb, - 0xf5, 0x70, 0xa1, 0x38, 0x64, 0xc2, 0x43, 0x9f, 0xc4, 0x97, 0x86, 0x5d, 0x9f, 0x29, 0x59, 0xc9, 0x68, 0x34, 0xaa, - 0x1b, 0x29, 0xf9, 0x30, 0xdf, 0xbd, 0x69, 0xa1, 0x56, 0x8a, 0x38, 0xe5, 0x29, 0x58, 0x7a, 0x6b, 0x4a, 0x37, 0x5f, - 0xd0, 0x15, 0x2f, 0x52, 0xf9, 0xd3, 0x41, 0x9b, 0xf4, 0x88, 0x6b, 0xe6, 0xeb, 0x2c, 0xcc, 0xf0, 0x43, 0xc0, 0x47, - 0xf3, 0x30, 0xb3, 0xe9, 0x0a, 0x96, 0x16, 0xc4, 0x91, 0x71, 0xc9, 0x43, 0x9b, 0x07, 0xb0, 0xfe, 0xf4, 0x21, 0x89, - 0x9f, 0xc2, 0xcf, 0x99, 0x4e, 0xeb, 0xf8, 0x0c, 0x67, 0x33, 0x2a, 0xe4, 0x8d, 0xa0, 0xfd, 0x1a, 0x12, 0x89, 0x46, - 0x36, 0xf6, 0x18, 0x8a, 0xd6, 0xdd, 0x06, 0xae, 0xfc, 0x86, 0xde, 0xb9, 0x34, 0x08, 0xb0, 0xad, 0xb1, 0x18, 0x38, - 0xe3, 0xf1, 0x07, 0xaa, 0x6a, 0xf4, 0x15, 0x45, 0x37, 0x4c, 0x26, 0x9a, 0x3b, 0x8e, 0xed, 0xa8, 0x76, 0x95, 0xad, - 0x58, 0x61, 0x6c, 0x79, 0xed, 0x5b, 0x5a, 0x9a, 0x12, 0x50, 0x0d, 0x86, 0x3b, 0x01, 0x7c, 0x46, 0x84, 0x3c, 0x10, - 0x44, 0xf7, 0xc1, 0x41, 0x73, 0x96, 0xe0, 0x79, 0x18, 0xc2, 0x1f, 0x58, 0x38, 0xb0, 0x2c, 0x65, 0x3f, 0x97, 0xd3, - 0x18, 0xce, 0xdd, 0x5c, 0xee, 0xf0, 0xd9, 0x12, 0x14, 0x79, 0x72, 0x4e, 0xf5, 0xe5, 0x2b, 0xf7, 0xf6, 0x7b, 0x4c, - 0x30, 0x8f, 0x9e, 0x6d, 0xf8, 0xad, 0xa6, 0xdb, 0xf8, 0xc2, 0xda, 0x81, 0x13, 0xe6, 0xc2, 0x69, 0x2e, 0xb6, 0x4b, - 0x0d, 0x71, 0xd7, 0x78, 0x42, 0x84, 0x57, 0x8a, 0x58, 0x64, 0x9e, 0x4c, 0xc7, 0x60, 0x63, 0xc8, 0x36, 0x95, 0xcf, - 0x94, 0x42, 0xbc, 0x9a, 0xca, 0x0b, 0x53, 0x2b, 0x95, 0x55, 0x1a, 0x61, 0xa6, 0x80, 0x45, 0x95, 0x81, 0xcf, 0x7e, - 0x8d, 0x14, 0xd7, 0xd4, 0xf3, 0x17, 0x2e, 0xdf, 0x4c, 0xb7, 0xd9, 0x7c, 0xfa, 0x32, 0x8f, 0xaf, 0xb6, 0xdb, 0xb0, - 0xfb, 0x05, 0x98, 0x5f, 0x56, 0x52, 0xa3, 0x06, 0x4e, 0x0f, 0x21, 0xfa, 0x39, 0xef, 0xc9, 0x39, 0xb1, 0x9c, 0x5c, - 0xbb, 0x79, 0xb3, 0x9d, 0x14, 0x2d, 0xb0, 0x80, 0x13, 0x17, 0xe9, 0x40, 0x4b, 0x05, 0xa7, 0x2c, 0xe3, 0x9d, 0x4d, - 0x6f, 0x29, 0x15, 0x5e, 0x2d, 0x14, 0x09, 0xa9, 0xed, 0xbd, 0xc4, 0x8c, 0x1a, 0x70, 0x4e, 0xf2, 0x0e, 0x02, 0x4e, - 0x6a, 0xaa, 0xb1, 0x46, 0x71, 0xaa, 0x13, 0x9c, 0x57, 0x6a, 0xe8, 0x12, 0xe5, 0xc4, 0x6d, 0xb7, 0x55, 0xd1, 0x42, - 0x7d, 0x3c, 0xc8, 0x59, 0x22, 0x8f, 0x07, 0x14, 0xba, 0xc8, 0xa3, 0x21, 0x5f, 0x90, 0x52, 0xad, 0x1c, 0xa5, 0x5a, - 0xdd, 0x95, 0x0c, 0x14, 0x72, 0x15, 0xe4, 0x0d, 0x31, 0xee, 0x5a, 0x99, 0xb7, 0xb8, 0x72, 0x42, 0x4a, 0x93, 0xf0, - 0xb9, 0xa5, 0x18, 0x58, 0xc1, 0xde, 0x98, 0xba, 0xc2, 0x25, 0x42, 0xdb, 0xdd, 0x86, 0x98, 0x64, 0xb0, 0x6e, 0xb6, - 0xdb, 0x57, 0x65, 0x38, 0xcf, 0x16, 0x54, 0x8c, 0xb2, 0x14, 0x21, 0xc4, 0xb4, 0x87, 0xae, 0xe9, 0x82, 0x9e, 0x18, - 0x6a, 0xdb, 0xe3, 0x24, 0xe9, 0x62, 0x4d, 0x92, 0x18, 0xc5, 0x17, 0xa2, 0x94, 0x6b, 0x8d, 0x10, 0x3c, 0xdc, 0xff, - 0x48, 0x21, 0x86, 0x9b, 0x5e, 0x77, 0xbf, 0xee, 0xdc, 0x10, 0xff, 0x80, 0x40, 0x02, 0x05, 0x7b, 0x55, 0x8e, 0x2e, - 0xb2, 0x22, 0xc5, 0x9d, 0x2a, 0xa3, 0xe2, 0xca, 0x75, 0xe0, 0xb7, 0xdc, 0xf0, 0xaf, 0x86, 0x28, 0x40, 0x5c, 0xe3, - 0x4a, 0x31, 0x9e, 0xb5, 0xb5, 0x14, 0xc9, 0x28, 0x36, 0x24, 0x2a, 0x9c, 0xa8, 0xe8, 0x2e, 0x4f, 0xa3, 0x7b, 0x68, - 0xd7, 0x20, 0xb8, 0x6a, 0xee, 0x6c, 0xa4, 0xf9, 0x82, 0x10, 0x39, 0x01, 0x02, 0x36, 0xaa, 0x3e, 0xb5, 0x56, 0xd5, - 0xc3, 0xac, 0xf2, 0xb9, 0x3a, 0x88, 0x57, 0x15, 0xf0, 0xb0, 0xce, 0xf6, 0xbe, 0xaa, 0x1c, 0xd6, 0x06, 0xdf, 0x6e, - 0xb7, 0xab, 0x6a, 0x1e, 0x04, 0x0e, 0xa3, 0xf9, 0x9d, 0x94, 0x98, 0xf7, 0xc6, 0x14, 0x56, 0xbc, 0xeb, 0xd2, 0xd6, - 0x4d, 0x6a, 0x8d, 0x05, 0xea, 0x0e, 0xd7, 0x07, 0x3c, 0x4f, 0x81, 0xa3, 0x1d, 0x15, 0x53, 0x61, 0x74, 0xe5, 0xd8, - 0x95, 0x0a, 0x03, 0x43, 0xff, 0x90, 0xb2, 0x0d, 0x98, 0xe3, 0x81, 0xb5, 0x0d, 0xfa, 0x29, 0x49, 0x2d, 0xcc, 0x18, - 0x8d, 0x59, 0xc4, 0xba, 0x8e, 0x8e, 0xb8, 0x8a, 0xde, 0xce, 0xa3, 0xbf, 0x3d, 0x1d, 0xd3, 0x32, 0x2e, 0x52, 0x71, - 0x0d, 0x2a, 0x08, 0x50, 0x86, 0xa0, 0xe1, 0xbf, 0xa2, 0x06, 0xa0, 0x41, 0xb0, 0x03, 0xf0, 0x8f, 0x4e, 0xa7, 0x41, - 0x53, 0x93, 0x8b, 0x49, 0x2a, 0x8b, 0x9c, 0xb5, 0xa1, 0xcc, 0x64, 0x72, 0x48, 0x1e, 0x17, 0x80, 0xe7, 0x88, 0xcd, - 0x92, 0x36, 0x17, 0x72, 0xb3, 0xc9, 0xd7, 0x92, 0x1d, 0xb9, 0xf3, 0x8a, 0xd6, 0x6b, 0x51, 0xd9, 0x49, 0xcc, 0x17, - 0xd3, 0x3b, 0x23, 0x0c, 0x9c, 0xea, 0xd6, 0xdc, 0xee, 0x40, 0xa7, 0x99, 0xfa, 0x74, 0x6e, 0x02, 0xc4, 0x01, 0x86, - 0xeb, 0x6e, 0x7e, 0xbb, 0x20, 0xf4, 0x8e, 0xdd, 0x19, 0xb1, 0xea, 0xad, 0x91, 0x8b, 0xe8, 0xb4, 0xdb, 0xc1, 0x04, - 0x2e, 0xe3, 0xac, 0x34, 0x2f, 0x94, 0xba, 0xa1, 0xec, 0x68, 0x9b, 0x30, 0x9f, 0x77, 0xb4, 0x1b, 0x2e, 0xf8, 0x46, - 0xac, 0x63, 0xdd, 0x90, 0xa6, 0x12, 0x3d, 0x3a, 0x50, 0xdb, 0x21, 0xa0, 0x39, 0x1b, 0xd3, 0x25, 0x40, 0x6d, 0xc2, - 0x7e, 0x59, 0x83, 0x59, 0xca, 0x25, 0xf4, 0xb5, 0xdb, 0x27, 0xf9, 0x52, 0xf6, 0xa4, 0x72, 0x96, 0x28, 0xf8, 0x72, - 0xa4, 0xe0, 0x95, 0x95, 0xf3, 0x58, 0xcf, 0x21, 0xe0, 0xb1, 0xc8, 0x12, 0x9d, 0x93, 0xe2, 0x0a, 0x94, 0xa9, 0x70, - 0x04, 0xea, 0xaa, 0x11, 0x4b, 0x38, 0xc0, 0xed, 0xc5, 0xd3, 0x80, 0x50, 0x90, 0xea, 0xae, 0xcd, 0x8a, 0xbc, 0x63, - 0x27, 0x9b, 0x3b, 0x30, 0x8b, 0xad, 0xd7, 0x55, 0xeb, 0x2b, 0x93, 0x6c, 0x3f, 0x6e, 0x08, 0xb6, 0xdd, 0x91, 0xf2, - 0x85, 0x77, 0xf4, 0x96, 0x6c, 0x6e, 0xfb, 0xfd, 0x10, 0xfa, 0x43, 0xa8, 0xea, 0xd0, 0x5d, 0x67, 0x87, 0xee, 0x5c, - 0xe6, 0xd7, 0xe8, 0xf9, 0xa4, 0x37, 0xc4, 0x07, 0x34, 0xd1, 0xa2, 0xab, 0xf8, 0x1e, 0x36, 0x75, 0x54, 0x53, 0x59, - 0x79, 0x94, 0x50, 0x50, 0x01, 0x67, 0xbc, 0x3a, 0xe3, 0x18, 0xdb, 0x54, 0x3d, 0xbd, 0x53, 0xbc, 0xda, 0x5a, 0xaf, - 0xcd, 0x6a, 0x7d, 0x01, 0x16, 0x01, 0x17, 0x3c, 0xba, 0x56, 0xb4, 0xe4, 0xca, 0x61, 0xea, 0xcf, 0x71, 0x54, 0x82, - 0xcb, 0x38, 0xcb, 0x79, 0x1a, 0xd0, 0x4b, 0xbf, 0xff, 0xa1, 0xb2, 0x95, 0x5a, 0x7a, 0x67, 0xee, 0x4d, 0x48, 0x36, - 0xff, 0x63, 0x03, 0xf5, 0x3a, 0xc4, 0x88, 0xa8, 0x7a, 0x41, 0xbf, 0x65, 0x10, 0x1b, 0x33, 0xa8, 0xd6, 0x49, 0xc2, - 0xab, 0x2a, 0xd0, 0x4a, 0xad, 0x35, 0x5b, 0xeb, 0xf3, 0xec, 0x11, 0x3b, 0x79, 0xd4, 0x63, 0xec, 0x8e, 0xd0, 0x44, - 0xe9, 0x84, 0x74, 0x8d, 0x91, 0xa3, 0x05, 0x52, 0x1d, 0x8a, 0xb2, 0xcb, 0xf0, 0x2d, 0x0a, 0x59, 0xda, 0xfb, 0x5c, - 0x9f, 0xc8, 0xf2, 0x1b, 0x65, 0x74, 0x11, 0xc9, 0x44, 0x90, 0x8d, 0xdf, 0x22, 0x60, 0x2f, 0x34, 0x3b, 0x20, 0x9b, - 0x25, 0x3b, 0xa3, 0xe7, 0xc6, 0x04, 0x06, 0x5e, 0xbf, 0x95, 0x89, 0x7a, 0x94, 0x25, 0xd1, 0x95, 0x46, 0x2e, 0xf7, - 0x21, 0x89, 0xce, 0x43, 0xe2, 0xe6, 0x86, 0xa5, 0x75, 0x13, 0xa2, 0x98, 0x59, 0x6f, 0x78, 0xd9, 0xdd, 0x47, 0xde, - 0xb6, 0xd2, 0x3e, 0xd5, 0x77, 0x26, 0x8d, 0x4c, 0xa1, 0xaf, 0xc3, 0x49, 0xbf, 0x0f, 0x7f, 0x15, 0xfd, 0xc0, 0x5b, - 0x0a, 0xfe, 0x62, 0x8f, 0x48, 0x93, 0xb0, 0x00, 0xe0, 0x08, 0x73, 0x5e, 0xfb, 0x13, 0xf8, 0x88, 0x9d, 0x6c, 0x1e, - 0x85, 0x67, 0xde, 0xcc, 0xdd, 0x87, 0x78, 0xa9, 0x4a, 0x7a, 0xce, 0x3c, 0xe9, 0x81, 0x58, 0x85, 0x7a, 0xbf, 0xde, - 0x31, 0xa3, 0x4f, 0x00, 0x22, 0x75, 0x67, 0x1c, 0x4a, 0xf1, 0x63, 0xdd, 0x65, 0xb2, 0x49, 0x59, 0x9b, 0x89, 0x92, - 0x2a, 0x12, 0x7f, 0x11, 0x40, 0xbf, 0x61, 0x38, 0x1a, 0x80, 0xf7, 0x56, 0x63, 0xaf, 0x87, 0xc6, 0x19, 0x53, 0x4d, - 0xcf, 0x36, 0x6a, 0x79, 0x5b, 0x0a, 0xa1, 0xc7, 0x22, 0xba, 0xb3, 0xc7, 0x62, 0x78, 0x46, 0xdf, 0x42, 0x85, 0xaf, - 0x43, 0x8c, 0xa6, 0x4b, 0x9a, 0x66, 0xba, 0x96, 0x5b, 0xe9, 0x96, 0xd0, 0x1c, 0xa3, 0xf8, 0x38, 0x6d, 0xbb, 0xa7, - 0x5a, 0x68, 0x4f, 0x28, 0x0f, 0xef, 0x68, 0x4d, 0x6f, 0x0d, 0x8b, 0x60, 0x91, 0x96, 0x9d, 0xfc, 0x84, 0x5e, 0x38, - 0x02, 0x93, 0xb2, 0xad, 0x01, 0xfc, 0x01, 0xf5, 0xc3, 0x59, 0x33, 0x35, 0x52, 0x0e, 0x47, 0xe1, 0x4b, 0x36, 0x20, - 0x57, 0x50, 0x8b, 0x35, 0x66, 0x27, 0x31, 0xe8, 0xa0, 0x76, 0x76, 0x87, 0x33, 0x29, 0x88, 0x64, 0x44, 0x73, 0x0b, - 0xf1, 0xf4, 0x0f, 0xd0, 0xf4, 0x41, 0x5a, 0x98, 0xd2, 0x35, 0x0a, 0x78, 0x40, 0xdf, 0xd4, 0xef, 0xe7, 0xf8, 0xdc, - 0x38, 0x96, 0x58, 0xd8, 0xe3, 0x25, 0xa1, 0x4b, 0x27, 0x6e, 0x14, 0x48, 0x9b, 0x2d, 0xab, 0x00, 0xac, 0x48, 0x02, - 0x8d, 0x48, 0xd0, 0x52, 0xc7, 0x8a, 0xcb, 0x36, 0x68, 0x40, 0x12, 0x15, 0x14, 0xb2, 0x44, 0x02, 0xf8, 0x61, 0x04, - 0x21, 0x8a, 0x62, 0x10, 0xf7, 0xaa, 0xe5, 0x15, 0x37, 0x54, 0x83, 0x13, 0x45, 0x30, 0xc1, 0x2a, 0x9d, 0x02, 0xb1, - 0x2d, 0xd6, 0x2b, 0xf0, 0xbc, 0xb4, 0x17, 0x49, 0x64, 0x09, 0xd0, 0x20, 0xcd, 0x95, 0x4e, 0xdb, 0xe5, 0xed, 0x88, - 0x96, 0x6a, 0x36, 0x77, 0x5e, 0x2c, 0x0c, 0xf7, 0x58, 0xbb, 0xdb, 0x81, 0xf6, 0xc2, 0x7a, 0x47, 0x44, 0x0d, 0x56, - 0x76, 0x6d, 0xbb, 0x36, 0x94, 0x86, 0xaa, 0x5e, 0x59, 0x26, 0xa0, 0xa6, 0xab, 0xb8, 0x5e, 0x46, 0xd9, 0x08, 0xfe, - 0x6c, 0xb7, 0xc1, 0x61, 0x00, 0x16, 0x90, 0xbf, 0xbc, 0xff, 0x29, 0xc2, 0xf0, 0x4c, 0xbf, 0xbc, 0xff, 0x69, 0xbb, - 0x7d, 0x3a, 0x1e, 0x6b, 0xae, 0xc0, 0xaa, 0x75, 0x80, 0x3f, 0xd0, 0x6c, 0x83, 0x59, 0xb2, 0xdb, 0xed, 0x53, 0xe0, - 0x20, 0x24, 0xdb, 0xa0, 0x77, 0xb1, 0x74, 0xe4, 0x92, 0xac, 0x86, 0xda, 0x91, 0x80, 0x55, 0xb7, 0xc3, 0x52, 0xec, - 0x52, 0x1f, 0x19, 0x82, 0x51, 0x2d, 0xfa, 0x17, 0x9d, 0x02, 0x4b, 0x0a, 0xa6, 0xab, 0xc1, 0xb2, 0xae, 0x57, 0x55, - 0x74, 0x78, 0x18, 0xaf, 0xb2, 0x51, 0x95, 0xc1, 0x36, 0xaf, 0x6e, 0xae, 0x00, 0x50, 0x21, 0xa0, 0xde, 0xbb, 0x75, - 0x91, 0xe9, 0x17, 0x0b, 0xba, 0xcc, 0x70, 0x4d, 0x82, 0xd9, 0x41, 0xce, 0x8d, 0x6e, 0x72, 0x4a, 0xcc, 0x03, 0xd8, - 0x1c, 0x6e, 0xb7, 0x1e, 0xbf, 0x70, 0x32, 0x7a, 0x3a, 0x5b, 0x66, 0xca, 0xa0, 0x93, 0xeb, 0xfd, 0x4f, 0x22, 0x27, - 0x0d, 0x15, 0x9f, 0x64, 0xfa, 0x22, 0x03, 0x3e, 0x8f, 0xbd, 0xa9, 0x42, 0x97, 0xe5, 0xf2, 0x5a, 0x03, 0x6c, 0x6c, - 0x76, 0x79, 0x3f, 0x4a, 0x39, 0x44, 0xa4, 0x08, 0x8c, 0xba, 0x66, 0x99, 0x11, 0xd7, 0xa6, 0xe2, 0xbe, 0xa5, 0x0a, - 0x7b, 0x53, 0x39, 0xce, 0x2a, 0x5c, 0x3b, 0xca, 0xf4, 0x26, 0x51, 0xf8, 0x02, 0x85, 0xa8, 0x1c, 0x8d, 0xe9, 0xac, - 0x40, 0x2a, 0x73, 0x98, 0x50, 0xcc, 0x61, 0xdf, 0xfd, 0x92, 0x5a, 0x73, 0x19, 0x57, 0xb8, 0xf7, 0xc2, 0x95, 0x99, - 0xdc, 0x09, 0x00, 0x45, 0x92, 0xb5, 0xff, 0xfc, 0x09, 0xa9, 0xf1, 0x3f, 0x53, 0xa5, 0x01, 0xe8, 0xfd, 0x0c, 0x35, - 0x59, 0x82, 0x80, 0xad, 0x98, 0xba, 0x68, 0xfa, 0x46, 0x32, 0xff, 0x01, 0x75, 0x3b, 0x15, 0xdb, 0xc8, 0xf8, 0x39, - 0x51, 0x4d, 0x4b, 0x9e, 0xae, 0x8b, 0x34, 0x2e, 0x92, 0xfb, 0x88, 0x37, 0x53, 0x2c, 0x89, 0x55, 0x9a, 0x02, 0xfd, - 0xec, 0x77, 0xe1, 0xa7, 0xd2, 0x33, 0x01, 0xa7, 0x85, 0xbb, 0xad, 0x9c, 0xcd, 0x64, 0x18, 0x67, 0x64, 0xca, 0x25, - 0x62, 0xb7, 0xd1, 0xf7, 0xe8, 0x13, 0xfc, 0xc9, 0xd1, 0x13, 0x42, 0xef, 0xc4, 0xb4, 0x40, 0x50, 0xba, 0x22, 0x35, - 0xae, 0x9a, 0xd8, 0xaf, 0x29, 0x44, 0x71, 0xa8, 0x18, 0x84, 0xee, 0xd4, 0xed, 0x93, 0x7c, 0x9f, 0x29, 0xfb, 0x8d, - 0x2e, 0x5b, 0x90, 0x4d, 0x05, 0x1d, 0x13, 0xd6, 0xdb, 0xd3, 0xd9, 0xb3, 0x33, 0xe7, 0x37, 0x68, 0xc2, 0x41, 0x75, - 0x03, 0xed, 0x2a, 0xc9, 0x34, 0x46, 0xb1, 0x59, 0x8c, 0xb5, 0x1b, 0x13, 0x11, 0x04, 0x9d, 0x2e, 0x66, 0x61, 0xbb, - 0x9d, 0x10, 0x5f, 0x02, 0x09, 0x14, 0xb8, 0x72, 0x51, 0x4e, 0x42, 0x22, 0x2f, 0x64, 0x6a, 0xb2, 0x6e, 0x04, 0x0b, - 0xd4, 0x1a, 0x3b, 0x0a, 0xe8, 0x29, 0x37, 0x4f, 0x01, 0x7d, 0x5f, 0xb2, 0x53, 0x3e, 0x08, 0x86, 0x18, 0x5f, 0x35, - 0xa0, 0xb7, 0x42, 0x3e, 0x82, 0x87, 0x30, 0xb0, 0x5c, 0xf4, 0x65, 0xc9, 0x10, 0x56, 0xe8, 0xcf, 0x94, 0x4d, 0xbe, - 0xfe, 0xc6, 0xce, 0xef, 0xb5, 0x12, 0xb3, 0x83, 0x50, 0xdc, 0x5c, 0x4f, 0x80, 0xf8, 0xd5, 0xfc, 0x1a, 0xac, 0xab, - 0x95, 0xc4, 0xdb, 0x91, 0x3c, 0x54, 0xae, 0x1c, 0xdd, 0x7c, 0x52, 0xe9, 0x4f, 0x20, 0x48, 0x8d, 0x95, 0x94, 0xdb, - 0xef, 0x3e, 0x0a, 0x5b, 0x11, 0x8c, 0x16, 0x20, 0xd6, 0xed, 0xad, 0xe4, 0xc2, 0x17, 0xfe, 0x63, 0x9d, 0xef, 0x31, - 0x76, 0x88, 0x38, 0xc3, 0xe9, 0xf7, 0xc1, 0xb0, 0xbd, 0x5b, 0x99, 0x36, 0x24, 0xba, 0x96, 0x1f, 0x01, 0xfd, 0x1f, - 0xab, 0xf1, 0x3b, 0x45, 0x49, 0x5f, 0x12, 0xe7, 0x08, 0x57, 0xc4, 0x2b, 0x34, 0xd5, 0xeb, 0x8d, 0x1b, 0xfa, 0xa6, - 0xd4, 0x2f, 0x94, 0x82, 0xc3, 0xbc, 0xd5, 0x0a, 0x0f, 0x3c, 0xf3, 0xfe, 0xa8, 0x3c, 0x41, 0xf7, 0x6f, 0xb8, 0x37, - 0xfe, 0xa8, 0x58, 0x86, 0x37, 0xe5, 0x2c, 0xd3, 0x77, 0xb8, 0xdb, 0xac, 0x48, 0xc5, 0x2d, 0x63, 0xc1, 0xba, 0x90, - 0xe6, 0xab, 0x69, 0x30, 0xdb, 0x34, 0x91, 0x4c, 0xb6, 0xdf, 0xff, 0xe5, 0x9d, 0xb0, 0xd9, 0x20, 0x38, 0xab, 0x45, - 0x19, 0x5f, 0xf1, 0x60, 0xaa, 0x54, 0x14, 0x59, 0xd6, 0xef, 0x67, 0x80, 0x0c, 0x63, 0xb5, 0x77, 0xf0, 0x64, 0xa8, - 0x99, 0x0e, 0x71, 0x6d, 0x74, 0x16, 0xf0, 0x56, 0x8f, 0xe6, 0x69, 0x0d, 0xbb, 0xcc, 0x55, 0x52, 0xfc, 0xd1, 0x92, - 0x64, 0x63, 0xfd, 0x9e, 0x0c, 0xdb, 0xc8, 0x67, 0xae, 0x01, 0x63, 0xe6, 0x56, 0xc8, 0x20, 0x77, 0x3d, 0x60, 0x84, - 0x90, 0x08, 0x54, 0xd6, 0x62, 0xe2, 0xbc, 0xd2, 0xe1, 0x1f, 0x6d, 0x60, 0x9c, 0x18, 0x03, 0xe3, 0x7c, 0x14, 0x21, - 0xa7, 0xa7, 0x7c, 0x90, 0x78, 0xb3, 0xf5, 0x97, 0x2c, 0x91, 0xde, 0x08, 0x42, 0x2f, 0xe0, 0xf7, 0xb8, 0xc5, 0x03, - 0x79, 0xc1, 0x29, 0xed, 0xcd, 0xe9, 0xf0, 0x65, 0x49, 0x86, 0x7f, 0x82, 0x77, 0x57, 0x6c, 0x2e, 0xcb, 0x09, 0x2c, - 0xee, 0xd8, 0x29, 0x9e, 0xe6, 0xb2, 0xc5, 0x09, 0x71, 0x88, 0x45, 0xee, 0x12, 0x0b, 0x18, 0x51, 0xcd, 0x68, 0xfc, - 0x78, 0xf6, 0xf6, 0x8d, 0xc2, 0x6c, 0xca, 0xdd, 0x0f, 0x60, 0x44, 0x95, 0xb4, 0xdd, 0x0c, 0xf8, 0x72, 0x84, 0x06, - 0xdb, 0xa9, 0x1d, 0xec, 0x7e, 0x5f, 0xa7, 0x9d, 0x14, 0x4e, 0x36, 0x2b, 0x06, 0xdd, 0x51, 0xda, 0x2c, 0xa5, 0x41, - 0x6d, 0x57, 0xe1, 0x68, 0x3e, 0xab, 0xc5, 0xaa, 0xce, 0x87, 0xe1, 0x92, 0xc6, 0x46, 0x56, 0x6e, 0x76, 0x13, 0x8e, - 0x6c, 0x02, 0x5c, 0x9f, 0x84, 0xb2, 0xf2, 0xe7, 0xa0, 0x05, 0x9d, 0x09, 0x1c, 0xd1, 0x76, 0x1b, 0x42, 0x04, 0x8e, - 0x72, 0x38, 0x99, 0x85, 0xe5, 0x70, 0x28, 0x07, 0xbe, 0x24, 0x24, 0x7a, 0x53, 0xce, 0xb3, 0x85, 0x44, 0xec, 0x71, - 0x77, 0xd2, 0xaf, 0xa5, 0xe4, 0x94, 0x7b, 0x7f, 0x54, 0x64, 0xf3, 0x5b, 0x8a, 0x31, 0x07, 0xad, 0x66, 0x33, 0x03, - 0x09, 0xeb, 0x69, 0x4d, 0xe4, 0x3a, 0x32, 0xb3, 0x01, 0xaa, 0x58, 0x34, 0x85, 0x05, 0x75, 0x8b, 0x23, 0xd6, 0xd3, - 0x7a, 0x0f, 0x2a, 0x40, 0x54, 0x0b, 0x76, 0x63, 0xb8, 0xd6, 0x5e, 0x56, 0xa1, 0xa0, 0x9c, 0xf8, 0xcc, 0x8c, 0x11, - 0x0d, 0x96, 0x20, 0x24, 0x8d, 0xab, 0xfa, 0xb5, 0x48, 0xb3, 0xcb, 0x0c, 0x10, 0x13, 0xac, 0xff, 0x9c, 0xf0, 0xde, - 0x3c, 0x93, 0xf3, 0xd2, 0x95, 0x38, 0x33, 0x30, 0x1f, 0x5d, 0x6f, 0x69, 0x49, 0xa2, 0x12, 0x68, 0x94, 0xab, 0xe5, - 0xf9, 0xfb, 0x8e, 0x55, 0xc8, 0xee, 0x87, 0x53, 0x69, 0x3b, 0xc4, 0x4f, 0x58, 0x4d, 0x9c, 0xd3, 0xba, 0x96, 0x22, - 0x8d, 0x8e, 0xb6, 0x01, 0x31, 0x6c, 0xd9, 0xb7, 0xc8, 0xe1, 0x03, 0x83, 0x0a, 0x2b, 0xf9, 0x29, 0x70, 0xf8, 0x8c, - 0x81, 0xa4, 0xab, 0x45, 0x70, 0x35, 0x3a, 0xc2, 0x8a, 0x32, 0xb5, 0xc4, 0x14, 0x12, 0xdd, 0x7a, 0xa1, 0x35, 0x86, - 0x51, 0x76, 0x15, 0xf9, 0xdf, 0xab, 0xee, 0xfd, 0x51, 0x6d, 0xb7, 0x30, 0xc9, 0x8e, 0xc7, 0x15, 0x6c, 0x6a, 0xd4, - 0x0a, 0xe1, 0xec, 0x9c, 0xd6, 0xa8, 0x1d, 0xeb, 0x85, 0x05, 0x90, 0x07, 0xb0, 0x15, 0xf1, 0x28, 0x83, 0x60, 0x6f, - 0xca, 0x79, 0xb5, 0xb0, 0xa2, 0x1c, 0x21, 0xf1, 0xbe, 0xc4, 0x28, 0xe5, 0x70, 0x15, 0x0b, 0x4b, 0x86, 0xfc, 0xea, - 0xe8, 0xb2, 0x14, 0xd7, 0x20, 0x29, 0xd1, 0x0c, 0x95, 0xe1, 0x75, 0x71, 0xd5, 0x16, 0x84, 0xf6, 0x2e, 0x2a, 0x50, - 0x47, 0x82, 0xe0, 0xc5, 0xab, 0x21, 0x66, 0x1b, 0xb9, 0xbb, 0xa2, 0xbd, 0xe4, 0x80, 0x5a, 0xdd, 0xb5, 0x5d, 0x6f, - 0xd2, 0x36, 0xdb, 0x88, 0x0b, 0xff, 0x82, 0xd2, 0x4f, 0xf9, 0xa0, 0x74, 0xa9, 0x04, 0x6e, 0x7c, 0xb9, 0xc9, 0xb2, - 0xcb, 0x7b, 0x5c, 0xfa, 0xb5, 0x37, 0x7e, 0xfd, 0x7e, 0x4f, 0x2e, 0x04, 0x2f, 0x15, 0x98, 0x6f, 0x97, 0x99, 0xaa, - 0xb5, 0xa6, 0xd4, 0x5c, 0x82, 0x6b, 0x6b, 0x3f, 0x82, 0x8a, 0xb8, 0xae, 0xc8, 0x64, 0x72, 0x80, 0x0e, 0x9c, 0xac, - 0x70, 0x2b, 0x0b, 0xf0, 0xd8, 0x09, 0xc8, 0x76, 0xcb, 0xc3, 0x40, 0x1d, 0x3a, 0x81, 0xbb, 0x25, 0xcf, 0x90, 0x59, - 0x33, 0x8f, 0x3f, 0x2b, 0xc1, 0x3f, 0xb6, 0xe0, 0x27, 0x14, 0x77, 0x1a, 0x99, 0x7f, 0x2b, 0xad, 0x5b, 0xdc, 0xbf, - 0x93, 0x69, 0x42, 0x51, 0x99, 0xd0, 0xb8, 0x95, 0xfe, 0x4b, 0x07, 0x4b, 0x92, 0xd9, 0x3f, 0x08, 0xf8, 0x60, 0xe6, - 0x3d, 0x31, 0xef, 0x49, 0x73, 0xba, 0xb5, 0x82, 0x21, 0x40, 0xa1, 0x9f, 0x93, 0xb9, 0xa6, 0xea, 0xf9, 0xe7, 0x35, - 0x5f, 0x73, 0xbf, 0xc5, 0x26, 0xe9, 0x81, 0x06, 0x3b, 0x79, 0x14, 0xa5, 0xb0, 0x12, 0x75, 0xae, 0x25, 0xea, 0x55, - 0xc3, 0x32, 0x54, 0x27, 0x38, 0x35, 0x4f, 0xd5, 0xb0, 0xfb, 0x89, 0x68, 0xad, 0x24, 0x2d, 0x31, 0x60, 0xad, 0x23, - 0x0f, 0xc9, 0xed, 0x5a, 0xc7, 0x9d, 0x86, 0xba, 0x34, 0x89, 0x12, 0x60, 0x84, 0x0b, 0x70, 0x04, 0xfd, 0x54, 0x86, - 0x1c, 0xae, 0xa9, 0x52, 0xbf, 0xa0, 0x28, 0x79, 0xe2, 0x28, 0x6a, 0x95, 0x22, 0xdd, 0x7c, 0x94, 0x63, 0x37, 0x5c, - 0xe3, 0x84, 0x9c, 0x68, 0xa1, 0xbf, 0x3d, 0x96, 0x72, 0x86, 0x16, 0x0f, 0xf2, 0x04, 0xeb, 0xe5, 0x2d, 0x05, 0x8a, - 0x3e, 0xba, 0x8c, 0xba, 0xe6, 0x15, 0xda, 0xbe, 0x2c, 0xfb, 0xfd, 0xdc, 0xd4, 0x93, 0xb2, 0x93, 0xcd, 0x52, 0xef, - 0x43, 0x54, 0x4c, 0xe1, 0xae, 0x4f, 0x14, 0x7f, 0x15, 0xaa, 0xab, 0xb6, 0xc8, 0xf9, 0x88, 0x23, 0x2e, 0x46, 0x4e, - 0x9a, 0x9f, 0xe5, 0xd4, 0x4b, 0x71, 0xbf, 0xac, 0xe4, 0xd7, 0x4a, 0x5b, 0x31, 0x5a, 0xa0, 0xfe, 0x54, 0xaa, 0xbc, - 0x5f, 0x94, 0x00, 0xf7, 0x54, 0xb1, 0x37, 0x60, 0x5f, 0xa1, 0x10, 0x7e, 0x5b, 0x02, 0xfe, 0x8d, 0xe4, 0x06, 0x8c, - 0x02, 0x03, 0x8c, 0x26, 0xdb, 0x73, 0x9a, 0xc0, 0x01, 0x57, 0x29, 0x15, 0x05, 0xad, 0xf4, 0xd0, 0x50, 0x53, 0x18, - 0x3d, 0x43, 0x19, 0xb7, 0xcc, 0xec, 0xdc, 0x18, 0x3b, 0x2d, 0xf0, 0x3c, 0x7f, 0x3e, 0x27, 0xf4, 0xb0, 0x56, 0x07, - 0xa9, 0xd1, 0x49, 0x74, 0x7f, 0xec, 0xc2, 0xc9, 0xf5, 0xc2, 0x59, 0x36, 0x2c, 0x81, 0xee, 0xc0, 0x05, 0x31, 0xee, - 0xf7, 0x73, 0x38, 0x32, 0xf5, 0xc8, 0x97, 0x2c, 0xa7, 0x31, 0x5b, 0x52, 0xe5, 0x69, 0x77, 0x55, 0x87, 0x39, 0x5d, - 0x1a, 0x19, 0x6f, 0xca, 0x8a, 0x79, 0x0e, 0x1a, 0x49, 0xf8, 0xd3, 0x6d, 0xed, 0x92, 0xce, 0x97, 0x90, 0x01, 0xfe, - 0x80, 0x44, 0x14, 0xb1, 0xaf, 0xff, 0xad, 0xc6, 0x49, 0x3d, 0x51, 0xda, 0xb0, 0x84, 0xae, 0x99, 0xaa, 0x9f, 0x5e, - 0xb2, 0xb5, 0xb7, 0x14, 0xb6, 0xdb, 0xd0, 0x4f, 0x60, 0x8a, 0x73, 0x25, 0xd3, 0x4b, 0xd4, 0x49, 0x01, 0x15, 0x0b, - 0x2f, 0x71, 0xf9, 0xa5, 0x84, 0x42, 0x73, 0xe7, 0xcb, 0x85, 0x56, 0x62, 0x42, 0xab, 0xc4, 0xe7, 0x0f, 0x95, 0xfe, - 0x5a, 0x7b, 0xc4, 0xfd, 0x2b, 0x0d, 0x13, 0x5d, 0x24, 0x2a, 0x44, 0x67, 0xbf, 0x82, 0x2c, 0xa7, 0x02, 0x1c, 0xcb, - 0x33, 0xd1, 0xd0, 0x1f, 0x53, 0x88, 0x83, 0x0e, 0x0d, 0x7a, 0x57, 0x8a, 0xeb, 0xac, 0xe2, 0x21, 0xde, 0x13, 0x1c, - 0xcd, 0xe8, 0x7e, 0x83, 0x0f, 0x65, 0xed, 0xd1, 0xab, 0xc8, 0xc6, 0x51, 0xee, 0x37, 0xbf, 0x56, 0xe1, 0x1c, 0xa2, - 0x55, 0x2e, 0xa8, 0x52, 0x57, 0x5b, 0x00, 0x2a, 0xc7, 0xf6, 0xea, 0x11, 0x9c, 0x6e, 0xea, 0xfa, 0x56, 0x87, 0xd6, - 0x1c, 0x40, 0x98, 0x43, 0xb2, 0x69, 0xb8, 0xda, 0x01, 0xf6, 0x48, 0xac, 0xd7, 0x40, 0x63, 0xed, 0xd6, 0xec, 0xb4, - 0x47, 0x71, 0x98, 0xc8, 0x4c, 0x5b, 0xa4, 0x68, 0x73, 0xb7, 0x4e, 0x8b, 0xa2, 0x0d, 0x9a, 0x21, 0xec, 0xde, 0x75, - 0xf8, 0xba, 0x15, 0x61, 0x7d, 0xbf, 0xed, 0x0b, 0x8c, 0x86, 0x36, 0xd7, 0xee, 0x39, 0x86, 0x6e, 0xd8, 0x60, 0x13, - 0x39, 0x0f, 0x91, 0x0f, 0x33, 0x79, 0x20, 0x8a, 0xc6, 0x18, 0xb0, 0x3d, 0xe2, 0x6a, 0xd3, 0x4a, 0x7e, 0x5e, 0xc6, - 0x9c, 0xed, 0x19, 0xe3, 0x94, 0xd6, 0xd7, 0xb8, 0xe6, 0xb8, 0x2c, 0xa4, 0x6a, 0x8c, 0x67, 0x3c, 0x0c, 0x3b, 0x5f, - 0xe0, 0xce, 0xac, 0x31, 0x78, 0x11, 0x96, 0x4a, 0x76, 0x2a, 0x57, 0x9f, 0xc3, 0x16, 0x47, 0xb3, 0x31, 0xa7, 0xbf, - 0xff, 0x72, 0xc5, 0x17, 0xe8, 0xa6, 0x66, 0xfd, 0x08, 0x82, 0xac, 0x40, 0x87, 0x2c, 0xa9, 0x7a, 0xfc, 0xae, 0x04, - 0x6a, 0x0f, 0xf3, 0xf0, 0x5d, 0xc9, 0x8a, 0xf8, 0x26, 0xbb, 0x8a, 0x6b, 0x51, 0x8e, 0x6e, 0x78, 0x91, 0x8a, 0xd2, - 0x48, 0x8d, 0x83, 0xd3, 0xd5, 0x2a, 0xe7, 0x01, 0x98, 0xca, 0x1b, 0x46, 0xd9, 0x54, 0x96, 0xa9, 0xc1, 0x55, 0xf2, - 0xf4, 0x5a, 0x89, 0xce, 0xab, 0x9b, 0xab, 0x20, 0xc2, 0x5f, 0x17, 0xfa, 0xc7, 0x75, 0x5c, 0x7d, 0x0c, 0x22, 0x63, - 0x53, 0xa7, 0x7f, 0xa0, 0x54, 0x1e, 0xfc, 0xa7, 0x40, 0xa6, 0xfb, 0x5d, 0x09, 0x96, 0xd9, 0xa6, 0xe2, 0xe3, 0x18, - 0x6b, 0x1d, 0x4e, 0xc8, 0x4c, 0x96, 0xe8, 0xbc, 0x4b, 0xd6, 0x25, 0x58, 0xfb, 0x49, 0x2c, 0x63, 0x99, 0x6b, 0x86, - 0x95, 0xc9, 0x8a, 0xf4, 0xac, 0xac, 0xd9, 0x61, 0x68, 0x9c, 0x68, 0xe6, 0xe8, 0x2d, 0xa0, 0x1e, 0xc8, 0xe1, 0x15, - 0x2d, 0xd6, 0xcc, 0xf1, 0xb1, 0xf1, 0x5e, 0x3f, 0x3a, 0xbc, 0x72, 0x04, 0x4a, 0xe6, 0x4e, 0x8e, 0xc2, 0x44, 0xf0, - 0xac, 0xd5, 0xe3, 0x8b, 0x3c, 0x2b, 0x60, 0xe5, 0x4c, 0xc6, 0x63, 0xea, 0x2c, 0xad, 0xd6, 0xcd, 0xd1, 0x22, 0xb9, - 0x66, 0x8f, 0xeb, 0xc7, 0x9c, 0x1c, 0xf2, 0x96, 0xa9, 0x6d, 0xdb, 0x3a, 0xce, 0xd1, 0xe4, 0x4b, 0xd3, 0xfd, 0x6a, - 0x6d, 0x22, 0xa2, 0x4b, 0xe7, 0x3e, 0xeb, 0x15, 0xdc, 0xfa, 0xa6, 0xd0, 0xf4, 0x5a, 0x00, 0x10, 0x9d, 0x32, 0xe0, - 0x2f, 0x59, 0xb1, 0x1e, 0xd5, 0xbc, 0xaa, 0x41, 0xc2, 0x82, 0x22, 0xbc, 0x29, 0xf6, 0xa6, 0xb4, 0x37, 0x4e, 0xc7, - 0x61, 0x07, 0x2e, 0xa6, 0xe8, 0x8e, 0x03, 0x76, 0xfd, 0x5a, 0x2b, 0x1a, 0xa9, 0x5f, 0xb6, 0x2f, 0xb1, 0xea, 0x8b, - 0x52, 0xe6, 0x99, 0x9c, 0x12, 0x8b, 0xdd, 0x56, 0x2e, 0xac, 0xa8, 0xdf, 0x30, 0xe1, 0xd2, 0x95, 0x20, 0x20, 0xd3, - 0x92, 0xf5, 0x4a, 0xbd, 0x8b, 0xc4, 0x1a, 0x08, 0x19, 0x18, 0xbe, 0x06, 0xeb, 0xa2, 0xe2, 0xda, 0x0a, 0xd6, 0xb9, - 0xe7, 0xab, 0x84, 0x42, 0x14, 0x3c, 0xb0, 0x13, 0xf4, 0x43, 0xeb, 0xe6, 0x6d, 0x29, 0x51, 0x06, 0xf1, 0xb8, 0x95, - 0x53, 0x0e, 0x12, 0x08, 0xc0, 0x3d, 0x95, 0x21, 0x38, 0x24, 0xc8, 0x3a, 0xb8, 0x9a, 0x71, 0x04, 0x57, 0x97, 0xce, - 0x5c, 0x5c, 0x03, 0xac, 0x4b, 0x7f, 0x2e, 0x13, 0x5c, 0x58, 0x8d, 0xa8, 0x34, 0x67, 0x9c, 0x62, 0x10, 0x23, 0x43, - 0xd0, 0x57, 0x86, 0xd2, 0x5e, 0x81, 0xa6, 0xf1, 0x9a, 0xad, 0xa4, 0x0f, 0x00, 0xbd, 0x60, 0x2b, 0x69, 0xec, 0x8f, - 0x5f, 0x9f, 0xb3, 0x95, 0x92, 0x06, 0x4f, 0xaf, 0x67, 0x17, 0xb3, 0xf3, 0x01, 0x3b, 0x8a, 0x42, 0x65, 0xc0, 0x10, - 0x58, 0x24, 0xfe, 0x60, 0x10, 0x16, 0xb2, 0x11, 0x83, 0x42, 0x46, 0xc1, 0x72, 0x78, 0x6c, 0xc4, 0xcd, 0x0a, 0xc7, - 0xc3, 0x02, 0x43, 0x5e, 0x79, 0x2f, 0x48, 0x40, 0xa8, 0x2e, 0x0d, 0x5d, 0x1e, 0xc3, 0xe1, 0xe4, 0x60, 0x02, 0xa9, - 0x98, 0x99, 0xc9, 0xc2, 0xd8, 0x98, 0x44, 0x10, 0xef, 0xb4, 0xb3, 0x5e, 0x28, 0xb7, 0xbb, 0xc6, 0x42, 0x8d, 0xc3, - 0xe0, 0xb3, 0x2a, 0x9e, 0x1c, 0x0c, 0xbb, 0x2a, 0xc6, 0x51, 0xb8, 0xd1, 0xca, 0xb7, 0xf3, 0x63, 0x00, 0xaf, 0x3d, - 0x1f, 0xba, 0x72, 0x89, 0xf3, 0xc3, 0x27, 0xe4, 0xf1, 0x13, 0x42, 0xcf, 0xd9, 0xf9, 0x17, 0x4f, 0xe8, 0xb9, 0x24, - 0x27, 0x07, 0x93, 0xe8, 0x86, 0xe9, 0x06, 0x1c, 0x1e, 0xc9, 0x26, 0xd0, 0xab, 0xd1, 0xba, 0x90, 0x0b, 0x4c, 0x39, - 0x34, 0x85, 0xdf, 0x8e, 0x0f, 0x82, 0xc1, 0x4d, 0xbb, 0xe9, 0x37, 0xed, 0xb6, 0x3a, 0x5e, 0x5d, 0x07, 0x47, 0xd1, - 0x6e, 0x31, 0x93, 0x6f, 0xc6, 0x07, 0x76, 0x0e, 0xb0, 0xbe, 0x87, 0xc7, 0x44, 0x37, 0x69, 0x67, 0x54, 0xdc, 0x9a, - 0xbe, 0xc2, 0x3e, 0xf8, 0x45, 0x76, 0xf4, 0x61, 0xf8, 0x6f, 0x75, 0xa2, 0x39, 0xff, 0xe2, 0x08, 0xc8, 0x11, 0xc8, - 0x40, 0xb1, 0x44, 0x30, 0xc3, 0x81, 0xa6, 0x80, 0x82, 0x4c, 0x8d, 0x3b, 0x55, 0xc3, 0x2f, 0x47, 0x4d, 0xce, 0xc8, - 0x0d, 0x4c, 0x0d, 0xb6, 0x05, 0x3f, 0x90, 0xdd, 0x50, 0xdf, 0x28, 0x74, 0x23, 0xe5, 0x64, 0xa6, 0x5f, 0x52, 0xfd, - 0x83, 0xdd, 0x40, 0x00, 0x63, 0x0b, 0x2f, 0x28, 0xd8, 0x97, 0xc7, 0x57, 0x07, 0xb8, 0x8a, 0x00, 0x25, 0x8b, 0x05, - 0x5f, 0x0e, 0xae, 0xd4, 0xe6, 0x3e, 0x08, 0xc8, 0xe0, 0xcb, 0xe0, 0xe4, 0xcb, 0x81, 0x18, 0x04, 0xc7, 0x87, 0x57, - 0x27, 0x81, 0x35, 0xee, 0x87, 0x10, 0x8f, 0xb2, 0xa2, 0x98, 0x69, 0x34, 0x1f, 0xf4, 0x82, 0x92, 0x89, 0xb9, 0xa9, - 0x57, 0x1a, 0x9f, 0xd1, 0x74, 0x6a, 0x90, 0xbf, 0xc3, 0x94, 0xc5, 0xfa, 0x77, 0x30, 0xe1, 0xd7, 0x41, 0x64, 0x83, - 0xa0, 0xce, 0xf2, 0x28, 0xa6, 0x4b, 0x76, 0x5f, 0x85, 0x29, 0x4d, 0x0e, 0x73, 0x42, 0xa2, 0x70, 0x29, 0xc1, 0xf3, - 0xe4, 0xeb, 0x04, 0xe2, 0xb8, 0xda, 0xcf, 0x01, 0xd7, 0x8d, 0xe6, 0x87, 0x09, 0x69, 0x15, 0x61, 0x23, 0xb2, 0x6c, - 0x1a, 0x7a, 0xc9, 0xc2, 0x15, 0xbd, 0x02, 0x66, 0x4a, 0xac, 0xc3, 0x2b, 0xe0, 0xf2, 0xd6, 0xf3, 0xd5, 0x82, 0x5d, - 0x79, 0xd2, 0x37, 0xcd, 0x17, 0x5f, 0x1a, 0x9f, 0x3c, 0xe0, 0x21, 0xad, 0x1f, 0x5e, 0x0a, 0x36, 0x00, 0x37, 0x19, - 0xbf, 0xfd, 0x4e, 0xdc, 0xa9, 0x79, 0x69, 0x4f, 0x31, 0xce, 0x4c, 0x3b, 0x31, 0x69, 0x27, 0xe4, 0xee, 0x7d, 0x7b, - 0x13, 0xeb, 0x93, 0xbd, 0x8a, 0xd6, 0xd2, 0x65, 0xd5, 0x30, 0x24, 0xe5, 0x9a, 0x21, 0x7f, 0x8f, 0x92, 0x53, 0x23, - 0xf0, 0x64, 0x97, 0xbc, 0x4e, 0x96, 0xee, 0x41, 0x65, 0xac, 0x06, 0xcc, 0x31, 0x62, 0x58, 0x28, 0x1c, 0xfb, 0xd7, - 0x19, 0x2b, 0xd7, 0xae, 0x40, 0x23, 0x46, 0xee, 0xed, 0x75, 0xc6, 0x9c, 0x98, 0xab, 0xc9, 0xda, 0x09, 0x55, 0xe7, - 0xa4, 0xe7, 0x2d, 0xde, 0xcb, 0x2a, 0x35, 0xb4, 0x44, 0xf4, 0x60, 0x2c, 0xcd, 0x28, 0x65, 0xa2, 0xd2, 0xa0, 0x91, - 0x8a, 0x8d, 0x6d, 0xf0, 0x4b, 0x70, 0x42, 0xe5, 0x8e, 0x3a, 0xdb, 0xb5, 0x53, 0x2a, 0x1c, 0x60, 0x59, 0xaa, 0x55, - 0xe5, 0x76, 0x99, 0x09, 0x56, 0x0f, 0x82, 0xd1, 0x1f, 0x95, 0x28, 0x66, 0x78, 0x67, 0x64, 0xc1, 0x14, 0xac, 0x04, - 0x65, 0x2d, 0xc3, 0x62, 0xc8, 0x51, 0x8b, 0xa7, 0x7d, 0x52, 0x85, 0xfa, 0xd1, 0x11, 0x24, 0x77, 0xb9, 0x6e, 0x05, - 0xc9, 0x7d, 0x32, 0x7e, 0xa2, 0x06, 0x3a, 0x5d, 0x2b, 0xc7, 0x43, 0x97, 0xdf, 0x46, 0x7c, 0x6d, 0xd5, 0x7b, 0xaa, - 0xb4, 0x0a, 0x55, 0xa0, 0xc4, 0x8a, 0xd2, 0x95, 0x5a, 0xd0, 0xfd, 0x2e, 0x02, 0x60, 0x11, 0x1b, 0xb3, 0xf1, 0xae, - 0x6d, 0x56, 0x08, 0x1a, 0x5d, 0x76, 0xb2, 0x89, 0x07, 0x2c, 0x51, 0xad, 0x1d, 0x4c, 0x68, 0x7c, 0xc2, 0x8a, 0x7e, - 0x3f, 0x3f, 0x01, 0x7a, 0xaa, 0x8c, 0x98, 0x4a, 0x38, 0xf2, 0x3f, 0xb7, 0x22, 0x5d, 0x14, 0xd8, 0xac, 0xc9, 0xbb, - 0x35, 0x96, 0x91, 0xa8, 0xcb, 0x94, 0x2a, 0xaf, 0x72, 0x0c, 0x98, 0xd6, 0xeb, 0x96, 0xe3, 0xca, 0xae, 0xe2, 0xc8, - 0x51, 0x61, 0x19, 0x71, 0x5e, 0x8d, 0xe3, 0xad, 0xc6, 0x37, 0x38, 0xd4, 0x6c, 0xda, 0xa5, 0x3b, 0x84, 0xb0, 0x10, - 0x5e, 0x67, 0x70, 0x1b, 0x51, 0x76, 0x12, 0xa8, 0xbc, 0xd1, 0xd7, 0x09, 0x69, 0x73, 0xbb, 0x5e, 0x3b, 0x06, 0xe9, - 0x44, 0x1f, 0x28, 0xf5, 0x08, 0x5a, 0xa3, 0x58, 0x50, 0x39, 0xe2, 0x91, 0xe5, 0xe1, 0xad, 0x41, 0xac, 0x92, 0x2f, - 0x29, 0x2a, 0x45, 0x03, 0xf4, 0xbf, 0xe4, 0xb7, 0x07, 0xbf, 0xbc, 0xff, 0xe9, 0x8c, 0xc7, 0x65, 0xb2, 0x7c, 0x17, - 0x97, 0xf1, 0x75, 0x15, 0x6e, 0xe4, 0x18, 0xc5, 0x0d, 0x99, 0x56, 0x03, 0x26, 0xf4, 0x4a, 0xf2, 0x77, 0xa5, 0x22, - 0xc4, 0x58, 0x67, 0xb2, 0xae, 0x6a, 0x71, 0xed, 0x55, 0xba, 0x2e, 0x33, 0xfc, 0xb8, 0xe5, 0x73, 0x7a, 0x08, 0x40, - 0x9e, 0xda, 0x85, 0x34, 0x12, 0xaa, 0x10, 0x6d, 0x2e, 0xe2, 0x74, 0x7d, 0x3c, 0xf6, 0xba, 0x5e, 0xb0, 0xa7, 0xe3, - 0xaf, 0xa6, 0xaf, 0xb3, 0x30, 0x1b, 0x54, 0x64, 0x54, 0x2f, 0x79, 0xd1, 0x32, 0xe5, 0x94, 0x26, 0x01, 0xe8, 0xe3, - 0xd9, 0x63, 0xec, 0x68, 0x3c, 0x26, 0x9b, 0xb6, 0x78, 0x80, 0x87, 0xcb, 0x75, 0x58, 0x92, 0x99, 0xaa, 0x23, 0x0a, - 0x0a, 0x7e, 0x57, 0x07, 0x80, 0xe4, 0x68, 0xaa, 0xd2, 0x5c, 0x1a, 0x7b, 0x3a, 0x9e, 0x50, 0x81, 0xdd, 0x0e, 0x49, - 0xe3, 0x54, 0x68, 0x67, 0x5e, 0xb8, 0x1e, 0x45, 0x42, 0xbb, 0x2c, 0xed, 0x54, 0x2a, 0xe4, 0x9e, 0x99, 0xd9, 0xae, - 0x41, 0x0c, 0x86, 0x50, 0xd5, 0x5d, 0x38, 0x75, 0xef, 0x36, 0xd7, 0x98, 0xed, 0x80, 0xf7, 0x1a, 0x34, 0x43, 0xca, - 0x5b, 0xf4, 0x5b, 0x5b, 0x44, 0x43, 0x57, 0x6b, 0x30, 0x2b, 0x46, 0xd9, 0x52, 0x94, 0xae, 0x29, 0x28, 0x05, 0xa3, - 0xcb, 0xb5, 0xb3, 0x70, 0x5f, 0x0b, 0xef, 0xc2, 0x92, 0xa9, 0xd5, 0x22, 0xa5, 0x84, 0xf2, 0xa6, 0xa2, 0xa5, 0x84, - 0x91, 0xd4, 0xf0, 0xd4, 0xae, 0x17, 0x78, 0x9c, 0xe7, 0x41, 0xd4, 0xf2, 0x02, 0x3b, 0xad, 0xc9, 0x29, 0x38, 0x7a, - 0xe9, 0x9c, 0x9a, 0x02, 0xff, 0x98, 0x49, 0x10, 0xd3, 0xa1, 0xbc, 0xdf, 0xe0, 0xe6, 0xff, 0x47, 0xc9, 0x02, 0x87, - 0x6f, 0xbd, 0xc2, 0x6d, 0xf4, 0x8f, 0xd2, 0xa5, 0xa5, 0xcf, 0x84, 0xeb, 0xea, 0xe2, 0x48, 0x7b, 0xb3, 0x51, 0xb2, - 0xcc, 0xf2, 0xf4, 0x8d, 0x48, 0x79, 0x45, 0xa4, 0x09, 0x46, 0xc5, 0x4e, 0x2a, 0xef, 0x86, 0x07, 0x46, 0x8c, 0xde, - 0x8d, 0xef, 0xc7, 0x0c, 0x64, 0xc3, 0x60, 0xf5, 0xcd, 0x52, 0x91, 0xac, 0xaf, 0x01, 0x53, 0x44, 0xca, 0x4f, 0x5e, - 0xe4, 0x1c, 0x9e, 0x42, 0x75, 0xfd, 0x02, 0xb7, 0xb9, 0xca, 0xf5, 0x39, 0xff, 0x31, 0xa3, 0x3f, 0x22, 0xd0, 0x49, - 0xbc, 0x02, 0xb9, 0xc7, 0x33, 0xa8, 0x1b, 0x61, 0x6a, 0x39, 0x06, 0x07, 0x42, 0x34, 0x90, 0xa2, 0x66, 0x81, 0x84, - 0xba, 0xd0, 0xc0, 0x1a, 0xf2, 0x82, 0x39, 0xbc, 0xc8, 0x45, 0xf2, 0x71, 0xaa, 0x7d, 0xe6, 0x87, 0x31, 0xc6, 0x4c, - 0x0e, 0x06, 0x61, 0x3d, 0x0b, 0x86, 0xe3, 0xd1, 0xe4, 0xe8, 0x29, 0x9c, 0xdb, 0xc1, 0x38, 0x20, 0x83, 0xa0, 0xa9, - 0x56, 0x71, 0x41, 0xab, 0x9b, 0x2b, 0x53, 0x06, 0x7e, 0xdc, 0x04, 0x83, 0x7f, 0x94, 0x8e, 0xe2, 0x1d, 0x34, 0x27, - 0xe7, 0x22, 0x04, 0x1b, 0xfb, 0x35, 0x01, 0x49, 0x59, 0x4f, 0xf1, 0x93, 0xea, 0x70, 0x63, 0x52, 0xfb, 0xa7, 0x0f, - 0x2f, 0x38, 0xec, 0x90, 0x40, 0x81, 0x34, 0x9e, 0x66, 0xa3, 0x57, 0x52, 0x91, 0xfb, 0xae, 0xe4, 0x70, 0x67, 0xee, - 0x59, 0xd3, 0x23, 0xab, 0x90, 0xf0, 0xb3, 0x80, 0x1b, 0xf9, 0xab, 0xe2, 0x26, 0xce, 0xb3, 0xf4, 0xc0, 0x7f, 0x73, - 0x50, 0xdd, 0x17, 0x75, 0x7c, 0x37, 0x0a, 0xb4, 0x35, 0x21, 0x77, 0x55, 0x4f, 0x80, 0x9e, 0x00, 0x5b, 0x00, 0x0c, - 0x88, 0x77, 0xcc, 0x4c, 0x66, 0x3c, 0x02, 0x8f, 0x40, 0xdf, 0x07, 0xb2, 0xbc, 0xb7, 0x2e, 0x49, 0xee, 0x66, 0x2a, - 0xcc, 0x55, 0xaf, 0xd8, 0x29, 0xc8, 0x78, 0xb5, 0x15, 0xbb, 0x6e, 0x7d, 0xe6, 0x4d, 0x87, 0x57, 0xe0, 0x85, 0x00, - 0xb7, 0xc8, 0x7e, 0xdf, 0x17, 0x54, 0x56, 0x5a, 0x45, 0xbc, 0x93, 0xdc, 0xa0, 0x7f, 0xbb, 0x33, 0x36, 0x92, 0xe4, - 0x56, 0x0f, 0x0f, 0xa0, 0xca, 0xe4, 0x5c, 0x71, 0x3b, 0x87, 0xa8, 0xad, 0xbb, 0x71, 0xc0, 0x6a, 0x83, 0x76, 0x59, - 0x73, 0x04, 0x17, 0x5e, 0x1c, 0x64, 0x90, 0x13, 0x67, 0x65, 0x24, 0xd5, 0xb8, 0x9a, 0xd4, 0x82, 0x4f, 0xf2, 0x74, - 0x0f, 0x59, 0xea, 0x09, 0x50, 0xe4, 0x38, 0x16, 0x43, 0xba, 0xf1, 0x26, 0xf0, 0xf8, 0xbd, 0x08, 0x41, 0x9a, 0xb6, - 0xdd, 0xfa, 0x23, 0x50, 0x74, 0x0f, 0x4c, 0x41, 0x9a, 0x46, 0x9b, 0x1a, 0x28, 0xa8, 0x3d, 0xd4, 0x48, 0x45, 0x9c, - 0x9d, 0xbc, 0x06, 0x1d, 0x22, 0xf8, 0x7e, 0xa7, 0x59, 0xd5, 0xf1, 0x62, 0x42, 0xf0, 0xe4, 0x7d, 0x71, 0x97, 0x55, - 0x75, 0x15, 0xbd, 0x4f, 0xd1, 0x10, 0x2a, 0x11, 0x45, 0xf4, 0x12, 0xe2, 0xe9, 0x55, 0xf8, 0xbb, 0x8a, 0x7e, 0x4a, - 0x69, 0x9c, 0xa6, 0x98, 0xfe, 0xbc, 0x84, 0x9f, 0xcf, 0x00, 0xd5, 0x11, 0x77, 0x42, 0x74, 0x21, 0xc0, 0x5e, 0x0d, - 0xa2, 0x59, 0xd5, 0x1c, 0x30, 0x34, 0xa3, 0xfb, 0x8a, 0x22, 0x46, 0x1b, 0x66, 0xff, 0xa1, 0x44, 0xa1, 0x90, 0x2c, - 0xe6, 0xd7, 0xca, 0x3c, 0x44, 0x3f, 0x62, 0x91, 0xa7, 0xef, 0x5e, 0xe9, 0x21, 0x8d, 0xee, 0x05, 0x55, 0x5b, 0x1b, - 0x8f, 0x2d, 0x0c, 0x5c, 0x16, 0x5d, 0xad, 0xe9, 0x79, 0xbc, 0xca, 0xa2, 0x0d, 0xe0, 0x4f, 0xbc, 0x7b, 0xf5, 0x4c, - 0x5a, 0x98, 0x3c, 0xcf, 0x40, 0x71, 0x70, 0xfa, 0xee, 0xd5, 0x6b, 0x91, 0xae, 0x73, 0x1e, 0x9d, 0x0b, 0x24, 0xad, - 0xa7, 0xef, 0x5e, 0xfd, 0x8c, 0xe6, 0x5e, 0x3f, 0x95, 0xf0, 0xfe, 0x25, 0xf0, 0x96, 0x51, 0xbc, 0x86, 0x3e, 0xc9, - 0xdf, 0xc9, 0x1a, 0x3b, 0xe5, 0xd4, 0x5a, 0x45, 0xbf, 0xa4, 0x8d, 0x23, 0xad, 0xfa, 0x67, 0xe9, 0x52, 0x3b, 0x47, - 0xc0, 0x73, 0x97, 0x67, 0xc5, 0xc7, 0xc8, 0x88, 0x76, 0x82, 0xe8, 0xcb, 0x83, 0xbb, 0xeb, 0xbc, 0xa8, 0x22, 0x7c, - 0xc1, 0xd0, 0x2e, 0x28, 0x3a, 0x3c, 0xbc, 0xbd, 0xbd, 0x1d, 0xdd, 0x7e, 0x35, 0x12, 0xe5, 0xd5, 0xe1, 0xe4, 0xdb, - 0x6f, 0xbf, 0x3d, 0xc4, 0xb7, 0xc1, 0x97, 0x6d, 0xb7, 0xf7, 0x9a, 0xf0, 0x01, 0x0b, 0x10, 0xa1, 0xfa, 0x4b, 0xb8, - 0xa2, 0x80, 0x16, 0x6e, 0xf0, 0x65, 0xf0, 0xa5, 0x3a, 0x74, 0xbe, 0x3c, 0xae, 0x6e, 0xae, 0x64, 0xf9, 0x5d, 0x25, - 0x1f, 0x8d, 0xc7, 0xe3, 0x43, 0x90, 0x40, 0x7d, 0x39, 0xe0, 0x83, 0xe0, 0x24, 0x18, 0x64, 0x70, 0xa1, 0xa9, 0x6e, - 0xae, 0x4e, 0x02, 0xc7, 0x34, 0xd7, 0x63, 0x11, 0x2d, 0x88, 0x4b, 0x70, 0x78, 0x45, 0x83, 0x2f, 0x03, 0x62, 0x53, - 0xbe, 0x80, 0x94, 0x2f, 0x8e, 0x9e, 0xba, 0x69, 0xff, 0x4b, 0xa6, 0x7d, 0xe5, 0xa6, 0x1d, 0x63, 0xda, 0x57, 0xcf, - 0xdc, 0xb4, 0x13, 0x99, 0xf6, 0xc2, 0x4d, 0xfb, 0xdf, 0xd5, 0x00, 0x52, 0x0f, 0x5c, 0xeb, 0xbf, 0x0b, 0xa7, 0x35, - 0x78, 0x0a, 0x45, 0xd9, 0x75, 0x7c, 0xc5, 0xa1, 0xd1, 0x83, 0xbb, 0xeb, 0x9c, 0x06, 0x03, 0x6c, 0xaf, 0x63, 0xe4, - 0xe1, 0x7c, 0xf0, 0xe5, 0xba, 0xcc, 0xc3, 0xe0, 0xcb, 0x01, 0x16, 0x32, 0xf8, 0x32, 0x20, 0x5f, 0xaa, 0x23, 0xed, - 0xae, 0x62, 0x9b, 0xc0, 0x86, 0x22, 0x1d, 0x9a, 0x00, 0x61, 0xae, 0x34, 0xae, 0xa1, 0x7f, 0x96, 0xdd, 0xd9, 0xf0, - 0x96, 0x28, 0xdd, 0x74, 0x83, 0x86, 0xbe, 0x05, 0xef, 0x04, 0x68, 0x54, 0x14, 0xdc, 0xc4, 0x65, 0x38, 0x1c, 0x56, - 0x37, 0x57, 0x04, 0xec, 0x32, 0x57, 0x3c, 0xae, 0xa3, 0xa0, 0x10, 0x43, 0xf9, 0x33, 0x90, 0x91, 0xaf, 0x02, 0x04, - 0x44, 0x82, 0xff, 0x82, 0x86, 0xbe, 0x13, 0x6c, 0x13, 0x0c, 0x6f, 0xf9, 0xc5, 0xc7, 0xac, 0x1e, 0x4a, 0xd1, 0xe2, - 0x5d, 0x45, 0xe1, 0x07, 0xfc, 0xb5, 0x55, 0x47, 0x7f, 0x82, 0x1b, 0xb7, 0xaf, 0x61, 0x7f, 0x27, 0x2c, 0x8b, 0xfa, - 0x4e, 0xcc, 0xb3, 0xc5, 0xb4, 0x75, 0xa0, 0xbf, 0x15, 0xa4, 0x9e, 0x67, 0x83, 0x60, 0x18, 0x0c, 0xf8, 0x82, 0xbd, - 0x15, 0x73, 0xee, 0x98, 0x4f, 0x3d, 0x12, 0xee, 0x34, 0xcf, 0xb2, 0x01, 0xf8, 0xa6, 0x20, 0x3f, 0x72, 0xf8, 0xdf, - 0xf3, 0x21, 0x0a, 0x0f, 0x07, 0x8f, 0x0e, 0xc9, 0x2c, 0x58, 0xdd, 0xa1, 0x47, 0x67, 0x14, 0x64, 0xc5, 0x92, 0x97, - 0x59, 0xed, 0x2c, 0x95, 0xfb, 0x75, 0xdb, 0xcb, 0x63, 0xef, 0xd9, 0xbc, 0x8a, 0x8b, 0x40, 0x9e, 0x73, 0xa0, 0x78, - 0x43, 0xd9, 0x53, 0xe1, 0x4b, 0x48, 0x95, 0x21, 0x6f, 0x58, 0x0c, 0x58, 0x70, 0xdc, 0x1b, 0x0e, 0x0f, 0x82, 0x81, - 0x55, 0xe7, 0x0e, 0x82, 0x83, 0xe1, 0xf0, 0x24, 0xb0, 0xf7, 0xa1, 0x6c, 0x64, 0xef, 0x8c, 0xb4, 0x64, 0xff, 0x2c, - 0xc3, 0x82, 0x82, 0x78, 0x4c, 0x28, 0xf1, 0x97, 0x02, 0x97, 0x19, 0x00, 0xf4, 0x91, 0x94, 0x80, 0x69, 0x58, 0x99, - 0x01, 0x84, 0xe6, 0xa6, 0x31, 0x3b, 0x07, 0xe6, 0x91, 0x26, 0x20, 0xde, 0x03, 0x8a, 0x01, 0x88, 0x25, 0x01, 0xce, - 0x5d, 0x10, 0xc5, 0xaa, 0x90, 0x47, 0x00, 0x7a, 0x8f, 0x3f, 0x89, 0x2e, 0x05, 0x93, 0x54, 0xac, 0x42, 0x10, 0xc4, - 0xf1, 0xd9, 0x5d, 0xd5, 0x9a, 0x9c, 0x25, 0x3a, 0x98, 0x91, 0x04, 0xd8, 0x10, 0x0d, 0x3b, 0x07, 0xf7, 0x73, 0x50, - 0x7a, 0x18, 0xbd, 0x13, 0x72, 0xc1, 0xf7, 0xdc, 0xb2, 0x50, 0x77, 0x70, 0xf5, 0x84, 0x83, 0xe0, 0x9e, 0x2b, 0x16, - 0x60, 0x54, 0x97, 0xeb, 0xaa, 0xe6, 0xe9, 0x87, 0xfb, 0x15, 0xc4, 0xbe, 0xc3, 0x01, 0x7d, 0x27, 0xf2, 0x2c, 0xb9, - 0x0f, 0xad, 0x3d, 0xd7, 0x46, 0xa6, 0xff, 0xf0, 0xe1, 0xf5, 0x4f, 0x11, 0x88, 0x1c, 0x1b, 0x4d, 0xe9, 0xef, 0x39, - 0x9e, 0x4d, 0x6e, 0x84, 0x27, 0x77, 0x63, 0xdf, 0x73, 0x73, 0x7a, 0xf4, 0xfb, 0x50, 0x37, 0xbd, 0xe7, 0xb3, 0x7b, - 0x3e, 0xb2, 0xc5, 0xa1, 0xba, 0xc2, 0x7e, 0x7d, 0xbb, 0x76, 0x8d, 0x90, 0x1e, 0x9e, 0x67, 0xca, 0xbd, 0xf9, 0x51, - 0x0e, 0x86, 0x41, 0x30, 0x55, 0x42, 0x49, 0x88, 0xba, 0xc1, 0xa4, 0x80, 0x21, 0x3a, 0x50, 0xcb, 0x6a, 0x8a, 0x9c, - 0x9b, 0x1c, 0x59, 0x78, 0x3f, 0x60, 0x4a, 0xe8, 0xe0, 0xe5, 0x90, 0x7e, 0x70, 0x38, 0x61, 0xcc, 0xc0, 0x6f, 0x15, - 0x30, 0xfd, 0x72, 0x51, 0x59, 0x07, 0xd1, 0x03, 0x30, 0xc6, 0x2d, 0x78, 0x09, 0x5d, 0x61, 0x37, 0x6b, 0x19, 0x15, - 0x03, 0xc1, 0xe3, 0x90, 0x03, 0x74, 0xb0, 0x0b, 0x5a, 0x56, 0x96, 0xf2, 0x56, 0x65, 0x2d, 0x55, 0xe4, 0x65, 0x28, - 0xab, 0x62, 0x89, 0xf9, 0x5e, 0xb0, 0x1f, 0x4a, 0xf4, 0x2c, 0x9f, 0x56, 0x5d, 0xf0, 0x42, 0x28, 0xc1, 0xb2, 0x5d, - 0xef, 0x44, 0x20, 0xea, 0x4c, 0x75, 0xae, 0xfa, 0x0a, 0xc7, 0x8e, 0xa7, 0xaf, 0x45, 0xca, 0x95, 0x09, 0x85, 0xe2, - 0xf3, 0x85, 0xab, 0x98, 0x28, 0xd9, 0x2d, 0xf4, 0xab, 0x6d, 0xa3, 0xcf, 0xee, 0xd7, 0x6a, 0x33, 0x48, 0xd1, 0x31, - 0x6f, 0x50, 0x70, 0x2d, 0x15, 0x0a, 0x5a, 0x7b, 0x1b, 0x7f, 0x82, 0x23, 0x37, 0xba, 0x3d, 0xf4, 0x7e, 0xab, 0xe3, - 0xab, 0x37, 0xe8, 0xdb, 0x69, 0x7e, 0x8e, 0x6a, 0xf1, 0xcb, 0x6a, 0x05, 0x3e, 0x54, 0x10, 0x59, 0xc4, 0xe0, 0xd2, - 0x42, 0x3d, 0x67, 0xef, 0x4e, 0xdf, 0x80, 0x1f, 0x25, 0xfe, 0xfe, 0xf5, 0xfb, 0xa0, 0x21, 0xd3, 0x78, 0x56, 0xea, - 0x0f, 0x4d, 0x0e, 0x08, 0x4d, 0x62, 0xd3, 0xcc, 0xfb, 0x59, 0xec, 0xb3, 0xef, 0x8a, 0xad, 0xa7, 0xa5, 0x8f, 0x24, - 0xa5, 0xb9, 0x7d, 0x30, 0x20, 0x50, 0x07, 0x88, 0xe4, 0xec, 0x4b, 0x1a, 0x43, 0x9a, 0xcb, 0xec, 0xbb, 0x11, 0xf1, - 0x5e, 0xec, 0x84, 0x10, 0xe3, 0x12, 0x8b, 0x46, 0x0d, 0xf9, 0x8c, 0x47, 0xd2, 0xb0, 0xe8, 0x3d, 0x26, 0x10, 0x6b, - 0x38, 0x2d, 0xdf, 0x23, 0xe6, 0x31, 0xde, 0x0d, 0x94, 0xec, 0x21, 0xca, 0xa8, 0xcd, 0xee, 0x59, 0x7c, 0x7f, 0x5c, - 0x87, 0x99, 0xb1, 0xbc, 0x1c, 0xc2, 0xdf, 0x40, 0x19, 0x80, 0x53, 0x8e, 0x2c, 0x5f, 0xad, 0x37, 0xba, 0x5c, 0x62, - 0x6a, 0x13, 0x41, 0x2c, 0x1e, 0x95, 0x0e, 0x6b, 0x57, 0xa5, 0xaa, 0x5d, 0x6d, 0x7d, 0x26, 0x7a, 0x35, 0x68, 0xe5, - 0xda, 0xf6, 0x78, 0x08, 0x77, 0xa9, 0xa4, 0x15, 0x26, 0xb0, 0x5e, 0x65, 0x15, 0x2a, 0xd8, 0x9c, 0x80, 0x06, 0xd7, - 0x22, 0x05, 0xe0, 0x2c, 0xa5, 0x46, 0xa3, 0x5a, 0xd8, 0x67, 0xe4, 0x7c, 0x16, 0x5b, 0x0b, 0xf1, 0xb4, 0x00, 0x0c, - 0xd7, 0xc7, 0xa0, 0xe4, 0xdd, 0x18, 0x94, 0xd3, 0x8f, 0x12, 0xde, 0x3a, 0x38, 0xaf, 0x96, 0x71, 0x2a, 0x6e, 0x01, - 0x8b, 0x31, 0x70, 0x53, 0xb1, 0x54, 0x27, 0x21, 0x59, 0xf2, 0xe4, 0x23, 0x5a, 0x6d, 0xa4, 0x01, 0x70, 0x95, 0x53, - 0x6d, 0xb9, 0x27, 0x41, 0x42, 0x6d, 0x29, 0x32, 0x21, 0xae, 0xeb, 0x38, 0x59, 0x9e, 0x61, 0x6a, 0xb8, 0x81, 0x5e, - 0x44, 0x81, 0x58, 0xf1, 0x02, 0x48, 0x7a, 0xce, 0xfe, 0x95, 0x29, 0xac, 0xf1, 0x67, 0x02, 0x05, 0x4c, 0x0a, 0x35, - 0x18, 0x2b, 0x65, 0x2f, 0x84, 0x8e, 0xf6, 0x16, 0x04, 0x8d, 0x7d, 0xf9, 0x27, 0xd4, 0xfd, 0x0c, 0x5a, 0x11, 0x7a, - 0x60, 0x88, 0xe2, 0x02, 0x77, 0x68, 0x6a, 0x96, 0x9c, 0x03, 0x8c, 0x58, 0x18, 0xef, 0xb3, 0xc6, 0x6c, 0xf5, 0x67, - 0x4b, 0xc0, 0x36, 0x4d, 0xb5, 0x4f, 0x61, 0x98, 0x10, 0x1d, 0x1b, 0xd8, 0x28, 0x2b, 0xcd, 0x86, 0xd2, 0xed, 0xa4, - 0x4b, 0xe6, 0xb4, 0x70, 0x9a, 0xf7, 0x18, 0x5b, 0x8e, 0x64, 0xee, 0x7e, 0x3f, 0xd4, 0x3f, 0x59, 0x4e, 0x9f, 0xa9, - 0x90, 0xcd, 0xce, 0x78, 0xd0, 0x9c, 0x28, 0x75, 0x55, 0x47, 0x3f, 0xa0, 0x03, 0x30, 0xd3, 0x06, 0x20, 0xd3, 0x06, - 0x9b, 0x76, 0x95, 0xa8, 0xb8, 0x24, 0x61, 0xa9, 0x24, 0xb0, 0xb3, 0x7d, 0xc9, 0xce, 0x26, 0x20, 0x8e, 0xe1, 0xae, - 0xa3, 0xc5, 0x4e, 0x88, 0x0f, 0x6f, 0x71, 0x90, 0x80, 0xa8, 0x43, 0x56, 0x97, 0x90, 0x8d, 0x36, 0x74, 0x71, 0x2f, - 0x4a, 0x61, 0xc2, 0x5a, 0x26, 0x55, 0x89, 0x0e, 0x82, 0x54, 0xed, 0xb6, 0x08, 0x2c, 0x51, 0xb0, 0x03, 0xd8, 0x7b, - 0x3b, 0xea, 0x7a, 0xd4, 0x64, 0x75, 0xf2, 0x25, 0xf8, 0x38, 0xcd, 0xba, 0x0a, 0xd2, 0x0b, 0xbb, 0x2e, 0xd7, 0x3c, - 0x50, 0xb1, 0xa9, 0xa4, 0x31, 0x71, 0x97, 0x16, 0x19, 0xe2, 0x01, 0x63, 0x2c, 0x5d, 0x08, 0xe4, 0x9b, 0xed, 0x8e, - 0x9b, 0x9a, 0x20, 0xf4, 0x13, 0xd6, 0x94, 0xc0, 0x4e, 0x67, 0x7b, 0x6a, 0xfc, 0x7c, 0x40, 0xc4, 0x61, 0x40, 0x81, - 0x64, 0xe3, 0x90, 0xe6, 0x48, 0x5f, 0x90, 0x34, 0x61, 0x60, 0x68, 0xc9, 0x73, 0x82, 0xac, 0x28, 0x74, 0x6c, 0x5d, - 0x95, 0x71, 0xae, 0x08, 0x73, 0xb4, 0xe4, 0x94, 0xf8, 0x9c, 0x20, 0x13, 0xdb, 0xd3, 0x36, 0x3d, 0x19, 0x96, 0x92, - 0x05, 0xfa, 0x57, 0x10, 0x25, 0xf6, 0x4c, 0x33, 0x2a, 0x07, 0xed, 0x02, 0x16, 0x28, 0xe5, 0x7b, 0xd0, 0x78, 0x6b, - 0x68, 0xa3, 0x60, 0x88, 0xed, 0xfe, 0x04, 0xfb, 0xb5, 0x76, 0x5a, 0x97, 0x29, 0x96, 0x93, 0x29, 0x44, 0x7b, 0x21, - 0xfd, 0x1b, 0x45, 0xa2, 0x3b, 0x45, 0x68, 0x12, 0xd6, 0x51, 0xf6, 0xa4, 0x4d, 0x0d, 0xa0, 0xa7, 0x4e, 0xc0, 0xf3, - 0xce, 0xb5, 0x0c, 0xbb, 0x48, 0xf5, 0x57, 0x06, 0x9f, 0x52, 0x0d, 0x82, 0x14, 0xb5, 0x49, 0xc1, 0x9c, 0xd7, 0xa1, - 0xa4, 0xce, 0x9c, 0xb6, 0xcc, 0xa8, 0x3a, 0x2a, 0x42, 0xca, 0x09, 0xfe, 0x93, 0x57, 0x42, 0x11, 0x9b, 0x30, 0xc1, - 0x03, 0x1f, 0xe6, 0x19, 0x36, 0xf0, 0x76, 0xfb, 0x2e, 0x0d, 0x93, 0x36, 0xdb, 0x90, 0x82, 0xb4, 0x42, 0xc7, 0xc5, - 0x80, 0xca, 0x5e, 0xe1, 0x7e, 0xc1, 0x76, 0xd2, 0x14, 0x3c, 0x08, 0xbd, 0x06, 0x26, 0x76, 0x75, 0xf1, 0x75, 0x98, - 0xd0, 0x70, 0x49, 0x95, 0xb3, 0x93, 0x92, 0x34, 0xb7, 0xd7, 0xe5, 0xa5, 0xe9, 0x83, 0x8a, 0x1d, 0xd6, 0x35, 0x3c, - 0xd0, 0x3c, 0xbf, 0x8b, 0x2b, 0xa6, 0x68, 0xa2, 0xb6, 0x1e, 0x92, 0x96, 0x1c, 0xeb, 0x66, 0xba, 0xc2, 0xd5, 0x32, - 0x53, 0xc0, 0xee, 0x02, 0x2f, 0xf4, 0x80, 0x87, 0x1d, 0xae, 0x48, 0x74, 0x89, 0xcd, 0x66, 0xab, 0x86, 0x4c, 0xf3, - 0x7d, 0xd9, 0x72, 0x1d, 0x10, 0xce, 0x50, 0xdf, 0xdc, 0x25, 0xc7, 0x8a, 0xb6, 0xb9, 0x49, 0x80, 0xe3, 0xed, 0x14, - 0x90, 0x74, 0x2c, 0x41, 0x1b, 0xdf, 0xd2, 0x1d, 0x44, 0xaa, 0xa7, 0x82, 0xee, 0x9d, 0x2f, 0xd2, 0xf8, 0x5f, 0x80, - 0x6d, 0xd4, 0x46, 0x9b, 0x66, 0x65, 0xeb, 0x30, 0x91, 0x16, 0xd6, 0xc8, 0x42, 0x2e, 0xc1, 0x07, 0x73, 0xb7, 0xa9, - 0xd3, 0xd3, 0x0e, 0x22, 0xec, 0x76, 0xd1, 0xe1, 0x11, 0xc6, 0x92, 0x35, 0x48, 0x34, 0xab, 0xb0, 0xa6, 0xfe, 0x72, - 0x88, 0x72, 0xaa, 0x97, 0x4c, 0xb4, 0xa4, 0x2e, 0xa5, 0x88, 0x52, 0x30, 0x37, 0x9e, 0x16, 0x9e, 0x29, 0x21, 0x42, - 0x56, 0x08, 0x0b, 0x54, 0x6b, 0xa0, 0xa5, 0x7c, 0xd0, 0xeb, 0xd0, 0xc9, 0x42, 0x63, 0x0a, 0xa2, 0x8f, 0x48, 0x73, - 0x23, 0x96, 0x8c, 0xee, 0x8e, 0x51, 0x4c, 0x20, 0x54, 0xb5, 0x93, 0x17, 0x56, 0x9f, 0x92, 0x6d, 0x75, 0x10, 0xd7, - 0x98, 0x26, 0x7b, 0x08, 0x6a, 0x8c, 0x82, 0x36, 0xab, 0x1b, 0xfd, 0xa5, 0x0c, 0x5d, 0xbb, 0x70, 0xec, 0x46, 0x49, - 0x04, 0x44, 0x60, 0x75, 0x9a, 0x8a, 0x01, 0x59, 0xe7, 0xb1, 0x8d, 0xd0, 0xa4, 0xba, 0x85, 0x28, 0x6f, 0x54, 0x34, - 0x1f, 0xd7, 0x21, 0xd9, 0x6e, 0xb1, 0x2c, 0xf0, 0x65, 0x3f, 0x5b, 0xef, 0x81, 0xfc, 0x7e, 0xbd, 0xfe, 0x24, 0xe4, - 0xf7, 0xab, 0xec, 0x73, 0x20, 0xbf, 0x5f, 0xaf, 0xff, 0xa7, 0x21, 0xbf, 0xcf, 0xd6, 0x0e, 0xe4, 0xb7, 0x1c, 0x8c, - 0xdf, 0x4a, 0x16, 0xbc, 0x7d, 0x13, 0xd0, 0xe7, 0x82, 0x05, 0x6f, 0x5f, 0xbe, 0x74, 0x84, 0xe9, 0xdf, 0xe9, 0x38, - 0x2f, 0x5a, 0x16, 0x8c, 0xb8, 0x2d, 0xf0, 0x0a, 0xb5, 0x4e, 0x2e, 0x50, 0x51, 0x06, 0xc0, 0xeb, 0xd5, 0x3f, 0xb2, - 0x7a, 0x19, 0x06, 0x87, 0x01, 0x99, 0x59, 0x48, 0xd0, 0xe1, 0x04, 0x6e, 0x6f, 0x68, 0x64, 0x59, 0x7f, 0x16, 0x7c, - 0xf8, 0x68, 0x34, 0x8a, 0xcb, 0x2b, 0xbc, 0xd4, 0xe9, 0x8d, 0x84, 0x80, 0xc7, 0x19, 0xaf, 0x4c, 0x88, 0x88, 0x65, - 0x5c, 0x9d, 0xab, 0xd8, 0x2c, 0x95, 0xd9, 0x8a, 0x10, 0x71, 0xfe, 0x1c, 0x70, 0xea, 0xcd, 0xde, 0x8c, 0xb1, 0x1f, - 0x92, 0x23, 0x56, 0x01, 0x64, 0x9f, 0xad, 0xd5, 0xbb, 0x8b, 0xb8, 0xe2, 0xef, 0xe2, 0x7a, 0xc9, 0xa0, 0x97, 0x70, - 0x17, 0x29, 0x78, 0x52, 0x3b, 0x6c, 0x93, 0x04, 0x2a, 0xcf, 0x14, 0x50, 0x79, 0xc7, 0x7b, 0x1a, 0x9a, 0x61, 0x51, - 0x3e, 0xc0, 0x5a, 0xba, 0x9c, 0x81, 0xd1, 0xe2, 0x8b, 0x1b, 0x5e, 0xd4, 0x3f, 0x01, 0x9e, 0x7a, 0xc1, 0x4b, 0xb8, - 0x25, 0x20, 0x17, 0xeb, 0x39, 0x21, 0xd0, 0xca, 0xf5, 0xec, 0x90, 0x51, 0x63, 0xb4, 0x68, 0xc2, 0xeb, 0x37, 0xde, - 0x84, 0xd0, 0xbb, 0x13, 0x74, 0x45, 0x18, 0x09, 0xef, 0xcf, 0x35, 0x3f, 0xcf, 0xc0, 0x7c, 0xbe, 0x02, 0x28, 0x0d, - 0x84, 0x43, 0x65, 0x52, 0x6e, 0x81, 0x09, 0x1b, 0x6d, 0xae, 0x94, 0xa5, 0x0e, 0x52, 0x29, 0x95, 0x70, 0xba, 0x15, - 0x4d, 0x05, 0xe0, 0x70, 0x47, 0x02, 0xc0, 0x4c, 0x4d, 0x61, 0x10, 0xdd, 0x36, 0xa5, 0x59, 0x1a, 0x59, 0x45, 0x9a, - 0xc5, 0x27, 0xa5, 0x12, 0x74, 0xfa, 0x3c, 0x89, 0x6b, 0x7e, 0x25, 0x4a, 0x08, 0x85, 0xdb, 0x4a, 0x69, 0x0c, 0x16, - 0x80, 0x3c, 0xee, 0xac, 0xcd, 0xd6, 0xac, 0x94, 0x29, 0xe7, 0xc5, 0xfa, 0x9a, 0x97, 0x59, 0x72, 0xbe, 0xcc, 0xaa, - 0x5a, 0x94, 0xf7, 0x6c, 0xae, 0xb2, 0x2e, 0xa2, 0x6a, 0xa4, 0x24, 0x5e, 0xe7, 0x35, 0xbf, 0x5e, 0x41, 0xe8, 0x87, - 0x75, 0x09, 0xac, 0xe7, 0xde, 0x2f, 0x65, 0x64, 0xd2, 0xb0, 0xf3, 0x3b, 0xb2, 0x00, 0xbd, 0x2b, 0xac, 0x11, 0xb9, - 0x00, 0x98, 0x5e, 0x33, 0xa7, 0x92, 0xaa, 0x94, 0xfe, 0x6b, 0x8d, 0x33, 0xef, 0x2f, 0xaa, 0x71, 0x6b, 0xed, 0x19, - 0xad, 0xad, 0x9f, 0x2a, 0xe1, 0x94, 0x80, 0x12, 0xb1, 0x13, 0x5c, 0x31, 0x29, 0x5d, 0x1b, 0xb4, 0x16, 0xb0, 0xac, - 0xc0, 0x1c, 0x59, 0x71, 0x75, 0x7e, 0x2b, 0x65, 0x35, 0x3d, 0x49, 0xcd, 0xd2, 0x28, 0x96, 0x28, 0x42, 0x4b, 0x16, - 0xae, 0x59, 0xb2, 0x27, 0xd7, 0x3a, 0x4a, 0x3c, 0x3c, 0xb0, 0xb8, 0x3d, 0xe8, 0xc7, 0x49, 0x3b, 0x65, 0xbb, 0xdd, - 0xc9, 0x04, 0x6c, 0x48, 0x2b, 0x09, 0x22, 0x83, 0x2c, 0x67, 0xc3, 0x49, 0x04, 0x70, 0x2d, 0x8a, 0x84, 0xfe, 0xb9, - 0xe6, 0x1a, 0xd0, 0x3e, 0x54, 0x5e, 0x85, 0x72, 0x15, 0xcd, 0xc1, 0xce, 0xcb, 0xed, 0x35, 0x04, 0x96, 0xe9, 0x9c, - 0x97, 0xc5, 0xfe, 0x35, 0xa0, 0xcc, 0x91, 0xd5, 0x0b, 0xb2, 0x6f, 0xc6, 0x55, 0xb6, 0x07, 0xa7, 0xb7, 0x35, 0x07, - 0x7b, 0x5b, 0xa3, 0x50, 0x7a, 0x13, 0x1e, 0x0e, 0x9f, 0x8e, 0x8d, 0x3f, 0x03, 0xae, 0x72, 0xf3, 0x5b, 0xee, 0x04, - 0xfb, 0x6c, 0x76, 0x03, 0xf5, 0x5d, 0x22, 0xda, 0x35, 0xd2, 0x6a, 0xcf, 0xb8, 0x35, 0xa4, 0xb1, 0x2b, 0xcd, 0x88, - 0xb9, 0x7e, 0x97, 0x47, 0xeb, 0xf9, 0xa3, 0x4d, 0xa6, 0xaa, 0x6c, 0x7e, 0xcf, 0x4c, 0x50, 0x3c, 0x8f, 0x4c, 0x35, - 0x6a, 0x0d, 0xba, 0x98, 0x74, 0x1d, 0xd9, 0xd4, 0x8c, 0xb2, 0xac, 0x93, 0xd6, 0x8d, 0xe4, 0x23, 0x97, 0x31, 0xc2, - 0xba, 0xb3, 0xf0, 0x3b, 0x9e, 0x84, 0x5d, 0x0d, 0x93, 0xd7, 0x10, 0xdd, 0x05, 0x84, 0xe9, 0x04, 0xe5, 0x43, 0xf8, - 0xfb, 0xa3, 0x8d, 0x4f, 0x3b, 0x9b, 0x43, 0xe7, 0x33, 0xfc, 0x9d, 0xa5, 0xf0, 0xb7, 0x6e, 0x7e, 0xa7, 0x9b, 0x6b, - 0x5e, 0x2f, 0x45, 0x1a, 0x05, 0xef, 0xde, 0x9e, 0x7d, 0x08, 0x14, 0xfc, 0x3b, 0x5e, 0x82, 0xb4, 0xda, 0x5b, 0x03, - 0x4d, 0x81, 0x1a, 0x28, 0x17, 0x57, 0x88, 0x80, 0xa8, 0x20, 0xf4, 0xcf, 0x96, 0xe2, 0xf6, 0x34, 0xcf, 0x5d, 0x4e, - 0x5d, 0x53, 0x77, 0xc5, 0xbc, 0x7a, 0xa4, 0x31, 0x04, 0x81, 0xe3, 0x28, 0xab, 0xce, 0x95, 0x8a, 0x28, 0x3d, 0xbf, - 0xb8, 0x3f, 0x57, 0x62, 0x28, 0x03, 0x41, 0xf9, 0xec, 0xf7, 0xe3, 0x34, 0xbb, 0x39, 0xc0, 0x23, 0x88, 0x05, 0x60, - 0xbf, 0x9f, 0xf3, 0x8b, 0x75, 0x5d, 0x8b, 0x62, 0x58, 0x8a, 0xdb, 0xe0, 0xe4, 0x58, 0x3e, 0xe8, 0x0c, 0xb1, 0x7c, - 0x0c, 0x0e, 0xfe, 0x2b, 0xc9, 0xb3, 0xe4, 0x23, 0x0b, 0x1e, 0x6d, 0x32, 0x76, 0xd2, 0x3a, 0x68, 0xc6, 0x4d, 0x70, - 0x02, 0x6d, 0x3d, 0x38, 0xcd, 0xf3, 0xe3, 0x43, 0xf9, 0xc5, 0xc9, 0xf1, 0x61, 0x9a, 0xdd, 0x9c, 0x38, 0xd1, 0x00, - 0xac, 0x71, 0x2f, 0xe2, 0xae, 0xd9, 0xcb, 0x3b, 0x78, 0xf1, 0x26, 0x3c, 0x34, 0xec, 0x0e, 0x88, 0x8c, 0x74, 0x2c, - 0x15, 0x14, 0x33, 0x85, 0x31, 0x1c, 0xee, 0xdb, 0x6d, 0x68, 0x2c, 0x8f, 0x12, 0x07, 0x96, 0xa7, 0x04, 0x76, 0x08, - 0xb3, 0xd0, 0x84, 0xd0, 0xa4, 0x21, 0xa1, 0x06, 0x0f, 0x8a, 0x09, 0x2d, 0x1b, 0x0a, 0xe7, 0xdd, 0xeb, 0x78, 0xa5, - 0x25, 0x6d, 0x4a, 0x72, 0xa1, 0x5b, 0x3f, 0xf3, 0xc6, 0x31, 0x6a, 0x8f, 0xaa, 0x86, 0xf3, 0xea, 0x15, 0xfb, 0x06, - 0x16, 0x84, 0xab, 0x61, 0x4d, 0x83, 0x16, 0x69, 0x01, 0xe1, 0xa8, 0x2b, 0xd3, 0xe3, 0x34, 0x9c, 0x17, 0x54, 0x2c, - 0x08, 0x3b, 0x09, 0x37, 0xc8, 0xdb, 0x17, 0x54, 0xb2, 0xfa, 0xa2, 0xb1, 0xd8, 0x9a, 0x72, 0x76, 0x4e, 0x1e, 0x6d, - 0x64, 0xcc, 0xde, 0x82, 0x9d, 0xf8, 0xf3, 0x55, 0xc7, 0x17, 0xc3, 0x25, 0x07, 0x27, 0xa0, 0xe0, 0xe0, 0xbf, 0xd2, - 0x8b, 0xdc, 0x4c, 0x8a, 0x5c, 0x91, 0xcb, 0xb8, 0x48, 0x73, 0xfe, 0x21, 0xbe, 0xf8, 0x01, 0xf3, 0x3c, 0xbf, 0xc8, - 0x9f, 0x41, 0x86, 0x26, 0x38, 0x79, 0xb4, 0x49, 0xea, 0xd1, 0x8b, 0x37, 0x1f, 0x5e, 0x7d, 0xf8, 0xe7, 0xf9, 0xb3, - 0xd3, 0x0f, 0x2f, 0xbe, 0x7f, 0xfb, 0xfe, 0xd5, 0x8b, 0xb3, 0xb9, 0xf1, 0xba, 0x95, 0x60, 0x6e, 0x64, 0xb1, 0xdd, - 0xda, 0x7c, 0xbf, 0xbc, 0x79, 0xfe, 0xe2, 0xe5, 0xab, 0x37, 0x2f, 0x9e, 0x37, 0x72, 0x2e, 0xdb, 0x0d, 0x81, 0x1d, - 0x1a, 0x67, 0x05, 0x2f, 0xa1, 0x78, 0x75, 0xbb, 0xc3, 0x66, 0x2b, 0x0c, 0x42, 0xbf, 0xe9, 0x2a, 0x5c, 0x03, 0x2c, - 0xb2, 0x03, 0xb5, 0x59, 0xa0, 0xe1, 0x42, 0x6f, 0x1c, 0x77, 0x89, 0xb9, 0xbd, 0x79, 0x81, 0xdf, 0xbd, 0x17, 0xb7, - 0xba, 0x2b, 0x6a, 0x84, 0x24, 0xbc, 0xd8, 0xec, 0xd9, 0xef, 0xc7, 0xae, 0x48, 0x0f, 0xe5, 0x1e, 0xb2, 0x5c, 0xf8, - 0xd5, 0x04, 0x07, 0xca, 0xbc, 0x30, 0x80, 0xe8, 0x18, 0xc1, 0xc9, 0xf1, 0xa1, 0x9b, 0xfb, 0xe4, 0xf7, 0xe8, 0x27, - 0xa7, 0x73, 0x58, 0x2a, 0x8c, 0x83, 0x9f, 0xb6, 0x73, 0x2c, 0x02, 0x7d, 0xb6, 0x07, 0xa7, 0x5c, 0x41, 0x9a, 0x5c, - 0x09, 0x12, 0x99, 0x49, 0x94, 0x66, 0x33, 0xba, 0xb4, 0xdf, 0xd5, 0x5f, 0xdb, 0x67, 0x14, 0x43, 0xf0, 0xa2, 0x12, - 0x25, 0xd8, 0xb8, 0x38, 0x89, 0x49, 0x0e, 0x82, 0x0f, 0x1e, 0x40, 0xef, 0xda, 0xa1, 0x2e, 0x0e, 0x9c, 0x90, 0x32, - 0xd8, 0xcf, 0x4e, 0xa2, 0x0f, 0xe3, 0x74, 0xd8, 0xfe, 0xd4, 0xe9, 0xee, 0xef, 0xc4, 0xfe, 0x38, 0x50, 0x5d, 0x6c, - 0x11, 0x1d, 0xd3, 0xec, 0xfd, 0x21, 0x49, 0xe6, 0x6f, 0xff, 0x4f, 0x73, 0x4f, 0xbb, 0xdd, 0xb6, 0x71, 0xe5, 0xff, - 0x3e, 0x05, 0x0c, 0xbb, 0x0e, 0x60, 0x03, 0x10, 0x40, 0x8a, 0x92, 0x4c, 0x8a, 0x52, 0x13, 0xdb, 0x39, 0x51, 0xaa, - 0xd4, 0x39, 0x8e, 0xea, 0x6d, 0xa3, 0xe8, 0x98, 0x43, 0x70, 0x48, 0xa2, 0x02, 0x01, 0x1e, 0x00, 0x94, 0xa8, 0xd0, - 0xe8, 0x53, 0xec, 0xff, 0xed, 0x73, 0xec, 0xfe, 0xeb, 0x13, 0xed, 0x23, 0xec, 0xb9, 0x77, 0x3e, 0x30, 0xf8, 0x22, - 0xa9, 0xc4, 0x69, 0xf7, 0xa4, 0xaa, 0x89, 0xc1, 0xcc, 0x60, 0xe6, 0xce, 0xcc, 0x9d, 0xfb, 0x7d, 0x03, 0xeb, 0x3f, - 0x62, 0x6b, 0x46, 0xac, 0x05, 0xb1, 0x6e, 0xd3, 0x9b, 0xbc, 0x71, 0xcd, 0x64, 0xba, 0x1b, 0x4c, 0x89, 0x68, 0x18, - 0x10, 0x37, 0x83, 0x73, 0x33, 0x9c, 0xc6, 0x0f, 0xc4, 0x05, 0x77, 0x45, 0x92, 0x19, 0x15, 0x89, 0x66, 0xc4, 0xdb, - 0x8c, 0x43, 0xc6, 0x2c, 0xc1, 0xcb, 0x30, 0xe8, 0xe3, 0xba, 0xa1, 0x6a, 0x37, 0x02, 0xc2, 0x18, 0x43, 0xf3, 0x09, - 0xb7, 0xac, 0x08, 0x1c, 0x3f, 0x4b, 0xc2, 0x3f, 0xd2, 0x07, 0x20, 0x5e, 0xd3, 0x2c, 0x5e, 0x02, 0xcb, 0x42, 0x66, - 0x5c, 0x04, 0x65, 0x19, 0xe9, 0x7e, 0x1f, 0x84, 0x64, 0x59, 0xb8, 0xe9, 0x81, 0xee, 0x75, 0xb2, 0x78, 0x36, 0x0b, - 0xa9, 0xa1, 0x8b, 0x1c, 0x2a, 0xba, 0x25, 0x3f, 0x73, 0xfe, 0xc4, 0x15, 0x81, 0x4b, 0xcd, 0xbc, 0xed, 0xf0, 0x0a, - 0xe8, 0x51, 0x19, 0xd9, 0x8f, 0x11, 0xf0, 0x28, 0xa2, 0xbe, 0x43, 0x2d, 0x0f, 0x5f, 0xe3, 0x02, 0x39, 0xd8, 0x93, - 0x78, 0x35, 0x0e, 0xa9, 0x8d, 0x07, 0x0a, 0x3e, 0xb9, 0x19, 0xaf, 0xc6, 0x63, 0x48, 0x56, 0xf3, 0xc4, 0xb5, 0x20, - 0xfc, 0x4e, 0x9c, 0x22, 0x5b, 0x9c, 0x9b, 0x03, 0x80, 0xa2, 0x93, 0x95, 0x87, 0xcf, 0xb2, 0x77, 0x82, 0xc4, 0x8b, - 0x7d, 0x20, 0x03, 0x16, 0xb8, 0x01, 0x2f, 0x0c, 0xf5, 0x1f, 0x60, 0x7f, 0xa7, 0xfa, 0xa0, 0x09, 0xb9, 0x0c, 0xaf, - 0xf5, 0x1f, 0x70, 0xb1, 0x30, 0x89, 0xf3, 0x6b, 0x76, 0x3e, 0x74, 0x4b, 0x67, 0xba, 0xff, 0x15, 0xa6, 0x73, 0x00, - 0xd9, 0xf7, 0x9b, 0x80, 0xcc, 0xa2, 0x38, 0xcd, 0x02, 0x5f, 0xbf, 0x19, 0x5c, 0x04, 0xc6, 0xf5, 0x22, 0x33, 0xcc, - 0x1b, 0xcb, 0xcf, 0xd4, 0x4c, 0x30, 0x02, 0x25, 0x63, 0x22, 0x98, 0xb6, 0x4a, 0xea, 0x19, 0xdd, 0x5a, 0x51, 0x20, - 0x7f, 0xac, 0xe4, 0x67, 0x43, 0xa8, 0x57, 0x49, 0x2b, 0x83, 0xf9, 0xb1, 0x74, 0x6c, 0x69, 0x0e, 0x18, 0xc3, 0xf6, - 0x7a, 0xb5, 0x41, 0x62, 0x21, 0x2b, 0xee, 0x63, 0x0c, 0x85, 0x2c, 0xfc, 0x87, 0xd8, 0xf3, 0x13, 0xd5, 0xf6, 0xb5, - 0x74, 0xb3, 0x8f, 0xbe, 0x2c, 0x53, 0x1e, 0x40, 0x21, 0x80, 0xe1, 0x49, 0x14, 0x67, 0x1a, 0xc4, 0xf7, 0x81, 0x2f, - 0x8e, 0xaa, 0xb6, 0x72, 0xbc, 0x57, 0xc3, 0xcc, 0x39, 0xba, 0xf9, 0x0a, 0xaf, 0x57, 0x83, 0x47, 0x79, 0x2b, 0x05, - 0xf2, 0x60, 0x3c, 0x53, 0x0a, 0x0b, 0x98, 0xc5, 0x97, 0xf1, 0x7d, 0x55, 0x1d, 0xf4, 0x7a, 0xb4, 0xfb, 0x76, 0x37, - 0x04, 0x05, 0x2f, 0x92, 0x1b, 0x1a, 0x3c, 0x3f, 0xab, 0x20, 0xa5, 0x2a, 0xa7, 0x0a, 0xed, 0x5f, 0x04, 0x95, 0x94, - 0x81, 0xb9, 0x1c, 0xde, 0x36, 0x80, 0xf4, 0x38, 0x21, 0x30, 0xca, 0x91, 0x6c, 0x95, 0xc9, 0x9f, 0x84, 0xc3, 0x4b, - 0x79, 0xdc, 0xe9, 0x10, 0xa5, 0xb2, 0xf3, 0x60, 0x36, 0xd7, 0xcf, 0x33, 0xbe, 0x23, 0x55, 0x7a, 0xf7, 0x23, 0xbc, - 0xea, 0x37, 0xbd, 0x81, 0x84, 0x54, 0x0d, 0xf5, 0xc3, 0xf8, 0x1e, 0xbc, 0xd9, 0x8b, 0x5e, 0x39, 0x35, 0xdd, 0xda, - 0xb9, 0xf9, 0x52, 0xd6, 0x80, 0xac, 0xe2, 0x66, 0x7f, 0x4b, 0x83, 0xf6, 0x6f, 0x56, 0x7b, 0xb1, 0xe2, 0x47, 0x8d, - 0xc1, 0xfe, 0x2c, 0x63, 0xa8, 0xf4, 0x32, 0x88, 0x86, 0xd1, 0x99, 0x2c, 0x5a, 0x90, 0x35, 0x36, 0x30, 0xcf, 0xeb, - 0x45, 0xfd, 0xc8, 0x8a, 0x87, 0xf1, 0x9e, 0x75, 0x63, 0x6e, 0x78, 0x4c, 0xcf, 0x47, 0x29, 0xcd, 0xce, 0x1b, 0xc6, - 0x02, 0x1b, 0x61, 0xf8, 0x6c, 0x13, 0xe5, 0xa3, 0x7e, 0x4b, 0x15, 0xf6, 0xd6, 0x22, 0xbb, 0x3b, 0x89, 0xb7, 0x76, - 0x12, 0xe7, 0xa3, 0xc7, 0x6c, 0x73, 0x9f, 0xef, 0xf2, 0x70, 0xe0, 0x37, 0x61, 0xfa, 0xb0, 0x71, 0xcf, 0x43, 0x30, - 0xda, 0xd2, 0x6e, 0x4f, 0x70, 0xb7, 0xff, 0xef, 0x7f, 0xfd, 0xe7, 0x7f, 0x17, 0x64, 0xef, 0x38, 0x39, 0x3b, 0xc5, - 0x8c, 0x64, 0x40, 0xc5, 0xe5, 0xa7, 0x07, 0xec, 0x37, 0x16, 0xff, 0x8b, 0x46, 0x45, 0xc4, 0xa8, 0xfe, 0x47, 0x3d, - 0x83, 0x22, 0x8b, 0xbb, 0xc8, 0xa1, 0xae, 0x90, 0xe0, 0x40, 0x43, 0x45, 0xcb, 0x55, 0x86, 0x51, 0xbf, 0x61, 0x1c, - 0x34, 0xd7, 0x35, 0x8c, 0x22, 0x0c, 0xb4, 0x58, 0xc1, 0x0c, 0xe6, 0xba, 0x16, 0x4c, 0xea, 0x65, 0x9c, 0xc9, 0x05, - 0x62, 0x04, 0xa9, 0x38, 0x94, 0x99, 0xc3, 0x63, 0xc2, 0xa7, 0xe3, 0x5b, 0x45, 0xca, 0x0c, 0xc3, 0x47, 0xdd, 0x72, - 0xc3, 0xfd, 0xec, 0xb3, 0x7e, 0x06, 0xfb, 0x4e, 0x73, 0x04, 0xf0, 0x3d, 0x87, 0xed, 0x33, 0x7c, 0xb6, 0x21, 0xc0, - 0xaf, 0xe5, 0x3a, 0x4c, 0xb4, 0xf0, 0x19, 0x2c, 0xa6, 0x07, 0x88, 0x9d, 0x95, 0x6b, 0x68, 0x34, 0x34, 0xe4, 0xa6, - 0x41, 0xcb, 0x24, 0x58, 0x90, 0xe4, 0x81, 0x59, 0x12, 0x59, 0xaa, 0xb9, 0x91, 0xa9, 0x6b, 0x8c, 0x7a, 0x63, 0xf3, - 0x65, 0x84, 0x9c, 0xae, 0xfd, 0x41, 0x96, 0x51, 0x3e, 0x39, 0x81, 0xbe, 0x74, 0xf8, 0xd6, 0x47, 0xfd, 0x25, 0x75, - 0x26, 0x34, 0x23, 0x41, 0xc8, 0x9a, 0x0c, 0x8c, 0xa8, 0x65, 0x36, 0x51, 0x79, 0x36, 0x69, 0x19, 0x65, 0xe3, 0x64, - 0x18, 0x05, 0xc7, 0xc6, 0x8d, 0x33, 0x43, 0x14, 0xda, 0xbc, 0x80, 0xec, 0x9d, 0xb2, 0x97, 0x00, 0xf8, 0x49, 0x7d, - 0x17, 0xe5, 0xed, 0x4b, 0xd4, 0x50, 0xfb, 0xb7, 0x59, 0x36, 0x0a, 0xcb, 0x96, 0xc2, 0xb2, 0xd1, 0xc8, 0x8f, 0x27, - 0xf4, 0xcf, 0xef, 0x2f, 0x64, 0xa6, 0x3f, 0x10, 0x5a, 0x8f, 0xf8, 0x25, 0x12, 0x21, 0x37, 0x91, 0x20, 0x27, 0xc1, - 0x72, 0xf2, 0x69, 0x72, 0xab, 0x25, 0xb9, 0xae, 0x9d, 0xb3, 0x49, 0xd3, 0x09, 0x9b, 0xc9, 0x30, 0xc6, 0x56, 0x49, - 0x7e, 0x7a, 0xc0, 0x6a, 0x33, 0x2a, 0x97, 0x55, 0x02, 0xf8, 0x25, 0x30, 0xeb, 0x02, 0x7c, 0x90, 0x94, 0x78, 0xe8, - 0x15, 0xe2, 0x05, 0x67, 0x81, 0xaa, 0x41, 0xef, 0xbc, 0xcc, 0xb8, 0x60, 0x2b, 0xbd, 0x38, 0xd4, 0x31, 0x04, 0x26, - 0x12, 0xe7, 0x5a, 0xab, 0x9c, 0x9c, 0xa2, 0x13, 0x21, 0xf2, 0xe9, 0xf3, 0x0e, 0x1e, 0x75, 0xa4, 0x00, 0x6b, 0x43, - 0x29, 0xc9, 0x75, 0x6d, 0xc1, 0x19, 0x25, 0x1e, 0x01, 0x0d, 0xc2, 0xa3, 0xb8, 0x70, 0xcf, 0xea, 0xda, 0x82, 0xac, - 0x71, 0xe6, 0xe2, 0x0d, 0x59, 0x1b, 0x1e, 0x7f, 0x55, 0x9c, 0xc9, 0xa8, 0xbc, 0xe0, 0x02, 0xc5, 0x80, 0xef, 0x93, - 0x14, 0xd0, 0xcd, 0xd1, 0xa6, 0xa4, 0x61, 0x71, 0xe7, 0x62, 0x71, 0x27, 0x2d, 0x8b, 0x3b, 0xd9, 0xb2, 0xb8, 0x21, - 0x5f, 0x48, 0x4d, 0x82, 0x2e, 0x41, 0x7f, 0xd6, 0x02, 0x29, 0x32, 0x06, 0xa3, 0xcf, 0x0f, 0x28, 0xc2, 0xc9, 0x4e, - 0x43, 0xb0, 0xe7, 0x6c, 0x81, 0x55, 0x13, 0x5c, 0x14, 0x40, 0xd4, 0x27, 0x2e, 0x8f, 0xab, 0x44, 0xad, 0xd6, 0x1c, - 0xb6, 0xaa, 0x5f, 0xa5, 0x79, 0x43, 0xd6, 0xd0, 0x32, 0xe6, 0x2d, 0x33, 0x9d, 0x6f, 0x99, 0xa9, 0x5f, 0x3a, 0xf3, - 0x7c, 0xda, 0xec, 0xf4, 0xaa, 0x93, 0x62, 0xa4, 0xd0, 0x3a, 0xc3, 0x2d, 0x53, 0xde, 0x87, 0xed, 0xb8, 0x58, 0xd9, - 0x51, 0x4b, 0x92, 0xa6, 0xf7, 0x71, 0x02, 0x4a, 0x62, 0xe8, 0xe6, 0x71, 0x5b, 0x6a, 0x11, 0x44, 0x3c, 0xfe, 0x54, - 0xeb, 0x66, 0x2a, 0xde, 0xab, 0x5b, 0xaa, 0xd3, 0xeb, 0xb1, 0x1a, 0x4b, 0x92, 0x65, 0x34, 0x41, 0xa0, 0x13, 0x48, - 0x54, 0xf0, 0xff, 0x64, 0x9b, 0x35, 0xe0, 0x90, 0xd0, 0x2c, 0xae, 0x03, 0x44, 0xed, 0x4b, 0xe0, 0x83, 0x12, 0x41, - 0x34, 0x2b, 0xb1, 0x2c, 0x13, 0x09, 0x78, 0x4e, 0xdf, 0x24, 0x8a, 0xb7, 0xa5, 0x77, 0x64, 0x3a, 0x4b, 0x32, 0xf9, - 0x01, 0x6c, 0x11, 0x8c, 0x8e, 0x05, 0x7e, 0x05, 0x6a, 0xe4, 0xca, 0x84, 0x31, 0x66, 0x7e, 0x81, 0x24, 0x11, 0x4b, - 0x72, 0xab, 0x4d, 0x70, 0xf8, 0x26, 0xf6, 0xf4, 0x66, 0xd3, 0xc9, 0x0f, 0x66, 0x81, 0x59, 0xc3, 0x9a, 0x80, 0xda, - 0xc2, 0xe1, 0x99, 0x94, 0xc0, 0x84, 0x96, 0x77, 0x64, 0x82, 0xb2, 0xea, 0x1a, 0x52, 0x30, 0xbb, 0x42, 0xbc, 0x35, - 0x4a, 0xe0, 0x76, 0xbb, 0x76, 0x6f, 0xf2, 0xe7, 0x33, 0xfc, 0xe5, 0xdd, 0xe4, 0xcf, 0xc7, 0xf8, 0xab, 0x73, 0x83, - 0xc9, 0x36, 0x1b, 0xc4, 0x7a, 0xca, 0x9c, 0xf5, 0xb3, 0xd2, 0x7e, 0x62, 0x26, 0xb3, 0x8f, 0xd8, 0x36, 0x7c, 0x81, - 0x9f, 0x3e, 0xdb, 0x44, 0xe0, 0x24, 0xae, 0xce, 0x21, 0x75, 0x12, 0x33, 0x6f, 0x2c, 0x9f, 0xb5, 0x94, 0x8f, 0xcd, - 0x7f, 0x31, 0x81, 0x80, 0xbb, 0x24, 0x2e, 0xee, 0x94, 0xb2, 0x50, 0xf2, 0xe3, 0x38, 0x88, 0x48, 0xf2, 0xf0, 0x91, - 0xc9, 0x14, 0x0c, 0xc1, 0x67, 0x4b, 0x61, 0x2b, 0x63, 0x05, 0xcb, 0x1a, 0xfa, 0x4c, 0xd1, 0x49, 0x3d, 0x70, 0x0a, - 0x61, 0xf8, 0x97, 0x44, 0xa1, 0x3d, 0x4b, 0xe2, 0x28, 0xbe, 0x20, 0xa5, 0x0f, 0x7d, 0x7c, 0xb6, 0x31, 0x68, 0xbd, - 0x9b, 0x9a, 0xb8, 0xa2, 0x44, 0x10, 0xc0, 0xf2, 0xa0, 0x68, 0x6b, 0x31, 0x09, 0xfa, 0xa8, 0x82, 0x1f, 0xc7, 0x6b, - 0xfb, 0xd9, 0x26, 0x3b, 0xd7, 0x17, 0x24, 0xb9, 0xa5, 0x13, 0xdb, 0x0f, 0x12, 0x3f, 0xa4, 0x7a, 0x5f, 0x1f, 0x87, - 0x24, 0xba, 0xe5, 0x8f, 0x76, 0xbc, 0xca, 0xd0, 0xa8, 0x66, 0xa7, 0x24, 0x4c, 0xc0, 0x84, 0x09, 0xf0, 0x91, 0x41, - 0x6b, 0x80, 0x82, 0xf6, 0x5a, 0x8a, 0xbf, 0x0b, 0x82, 0xb2, 0xa8, 0x65, 0x81, 0x4d, 0x38, 0xd8, 0xf9, 0x80, 0x93, - 0xbd, 0xa5, 0xe3, 0x7a, 0xe9, 0x96, 0x3a, 0x55, 0xa6, 0xf7, 0x90, 0x59, 0x62, 0x3f, 0x62, 0x0f, 0xbf, 0xfc, 0x73, - 0x50, 0xf2, 0x98, 0xcf, 0x71, 0xe2, 0xb0, 0xfd, 0x83, 0x6a, 0x63, 0x92, 0xa6, 0xab, 0x05, 0x9d, 0x30, 0x7b, 0x82, - 0xf3, 0x62, 0x28, 0x65, 0x46, 0x5c, 0x1d, 0xce, 0x4f, 0xab, 0xce, 0xf1, 0xe1, 0x6b, 0xb0, 0x73, 0x02, 0x62, 0x30, - 0x9e, 0x4e, 0xf5, 0x42, 0xbc, 0xb6, 0xa3, 0x99, 0x77, 0xf8, 0xd3, 0xea, 0xeb, 0xb7, 0xee, 0xd7, 0xb2, 0x71, 0xa4, - 0x9b, 0xf9, 0x48, 0x18, 0x6d, 0x70, 0x9a, 0x56, 0x19, 0xaf, 0x98, 0xd1, 0x94, 0x44, 0xed, 0xd3, 0xb9, 0x2e, 0xed, - 0xb2, 0x25, 0xa5, 0x13, 0xb0, 0xe7, 0xb7, 0x6a, 0xa5, 0x1f, 0x43, 0x7a, 0x47, 0xa5, 0x41, 0x48, 0xfd, 0x63, 0x0d, - 0x2d, 0x30, 0x62, 0x25, 0x37, 0x34, 0xe1, 0x84, 0x95, 0x32, 0xa5, 0x11, 0xce, 0x81, 0xcf, 0x5c, 0xdd, 0xe5, 0x95, - 0x5d, 0x3d, 0xb2, 0x74, 0x65, 0x00, 0xad, 0x23, 0x3b, 0x6f, 0x29, 0xef, 0x63, 0xba, 0xfa, 0xe6, 0xb1, 0x59, 0x9e, - 0xd9, 0x87, 0x08, 0xff, 0x1c, 0x4e, 0x21, 0x6c, 0x7e, 0x43, 0x4a, 0x22, 0x07, 0x6d, 0x10, 0x6b, 0x92, 0x5a, 0xeb, - 0x4c, 0xf0, 0x29, 0x6c, 0xa4, 0xd1, 0x59, 0x40, 0x08, 0x86, 0x1b, 0xd7, 0x46, 0x2b, 0xcf, 0x7c, 0x8c, 0x69, 0xa0, - 0x23, 0x9a, 0xa6, 0xad, 0x00, 0x93, 0x8b, 0x6e, 0xe9, 0x45, 0xed, 0x32, 0x3c, 0x8a, 0x72, 0xcb, 0xb5, 0xe0, 0x56, - 0xc6, 0x09, 0x56, 0xbf, 0x85, 0x18, 0xfe, 0xe3, 0x82, 0x5b, 0xb9, 0x25, 0xb3, 0xb1, 0xce, 0x2d, 0x90, 0xda, 0xde, - 0xdf, 0xeb, 0x7c, 0x50, 0xa5, 0x9b, 0xb2, 0x71, 0x68, 0x46, 0x09, 0xfb, 0xd5, 0xc4, 0xb4, 0xd8, 0x81, 0x18, 0x53, - 0x05, 0xc5, 0xd1, 0xe9, 0x94, 0xfa, 0x59, 0x6a, 0x0a, 0x59, 0xab, 0x8c, 0x39, 0x0d, 0xbe, 0x86, 0x4f, 0x86, 0xfa, - 0x9f, 0x20, 0xf2, 0x86, 0x08, 0xcd, 0xc6, 0x07, 0x24, 0xf8, 0x9d, 0x66, 0x30, 0xb1, 0x1e, 0xcb, 0x20, 0xe2, 0x5f, - 0xf9, 0xf4, 0x49, 0x98, 0x48, 0x94, 0xca, 0x71, 0x68, 0xfc, 0x0a, 0x28, 0xf6, 0x45, 0x2c, 0x6d, 0xe1, 0xb6, 0x23, - 0xa0, 0x6d, 0xc7, 0x77, 0xe3, 0x7d, 0xdd, 0xf3, 0xdc, 0x5c, 0xb7, 0xc0, 0xe3, 0xf3, 0x76, 0xdf, 0x43, 0x8f, 0xad, - 0xba, 0xd0, 0x6a, 0x15, 0x3d, 0xa6, 0x5d, 0xc7, 0x7b, 0xe5, 0xe9, 0x16, 0x33, 0xb4, 0x55, 0x70, 0x9b, 0x1f, 0xdf, - 0xd1, 0xe4, 0x57, 0x4f, 0xa5, 0xdc, 0xf9, 0x7e, 0xe3, 0x39, 0xf2, 0x5c, 0x40, 0xc2, 0x59, 0xbc, 0x7c, 0xc4, 0x14, - 0xba, 0xba, 0xa5, 0xfb, 0x61, 0x9c, 0x52, 0x75, 0x0e, 0x4c, 0x5e, 0xf1, 0x2b, 0x27, 0xf1, 0xfd, 0xfb, 0xb7, 0x3f, - 0xfc, 0xa0, 0x5b, 0x98, 0x3f, 0x38, 0x55, 0x7b, 0xe7, 0x1b, 0x6a, 0x07, 0xf6, 0x6f, 0xdc, 0x77, 0xec, 0x86, 0x61, - 0x7c, 0x65, 0x79, 0xcf, 0xb1, 0xb2, 0xda, 0x96, 0xe3, 0x37, 0x0f, 0xff, 0x32, 0x63, 0x06, 0xf7, 0x9a, 0x57, 0x03, - 0x6e, 0xd8, 0x7e, 0xbd, 0x95, 0x4a, 0x16, 0x41, 0xf4, 0xb1, 0xa1, 0x94, 0xac, 0x1b, 0x4a, 0x51, 0x36, 0x58, 0xc5, - 0x1f, 0xab, 0x78, 0xa1, 0xdc, 0xce, 0x90, 0xfe, 0x7d, 0x17, 0xb8, 0x14, 0x96, 0xe6, 0x57, 0x0c, 0x9a, 0xe7, 0x7f, - 0xa8, 0x8e, 0xba, 0xa1, 0x98, 0xf3, 0x21, 0x12, 0xb6, 0x5c, 0x97, 0xa3, 0xaa, 0xc9, 0xcb, 0x94, 0x9b, 0xda, 0xb8, - 0x59, 0x60, 0xfa, 0xa4, 0x70, 0xbe, 0xd9, 0x51, 0x19, 0x84, 0xb4, 0xb2, 0x76, 0x41, 0x13, 0x6c, 0xed, 0x3d, 0xff, - 0xe7, 0x3f, 0x1c, 0xe7, 0x9f, 0xff, 0xd8, 0x59, 0x15, 0xfa, 0xce, 0x81, 0x1d, 0xde, 0x55, 0x33, 0x1f, 0xa1, 0xd0, - 0x29, 0x1b, 0xbe, 0x1e, 0x8d, 0x06, 0x46, 0x09, 0x64, 0xe0, 0x33, 0x72, 0x5e, 0x2b, 0xe1, 0x78, 0xb5, 0xef, 0x9a, - 0x18, 0xcc, 0x01, 0x1a, 0xca, 0xeb, 0xab, 0x75, 0xb3, 0x33, 0xa7, 0x84, 0x5a, 0x5f, 0xb5, 0x9d, 0x0e, 0xa5, 0x98, - 0xb8, 0x2e, 0x1f, 0x99, 0x3c, 0xc7, 0x00, 0x8c, 0x8b, 0xab, 0x0f, 0x4a, 0x2b, 0x07, 0x7e, 0x36, 0x59, 0x79, 0x7c, - 0xbc, 0xac, 0x32, 0x42, 0xba, 0xd7, 0x08, 0x59, 0xdb, 0xf2, 0x18, 0x79, 0x7f, 0xb5, 0x51, 0xb2, 0x72, 0x31, 0x4e, - 0x0b, 0x45, 0x66, 0x3c, 0xca, 0x08, 0x67, 0x9a, 0xb8, 0x4a, 0xb0, 0xa4, 0xf6, 0xad, 0xa8, 0x2e, 0x94, 0x21, 0xec, - 0x5e, 0xf6, 0x73, 0x3d, 0x8c, 0xef, 0xd1, 0x59, 0x4f, 0xd5, 0x27, 0x73, 0x61, 0xc8, 0x69, 0x9a, 0x25, 0x71, 0x34, - 0x3b, 0xab, 0x5c, 0xde, 0x75, 0x3b, 0x1f, 0x90, 0x60, 0xb1, 0xaa, 0x65, 0xb1, 0x89, 0x3a, 0xca, 0xed, 0x5b, 0xea, - 0x7c, 0xc7, 0x4c, 0x98, 0x6a, 0x42, 0xb9, 0x1c, 0x45, 0xd7, 0x0d, 0x6a, 0x70, 0x95, 0x94, 0x2b, 0xbf, 0x96, 0x8f, - 0x07, 0x1c, 0xae, 0x67, 0xa3, 0x1c, 0x93, 0x1d, 0xbd, 0x6b, 0x33, 0x10, 0xfd, 0x7e, 0xb7, 0x81, 0xe8, 0xd5, 0x5e, - 0x06, 0xa2, 0xdf, 0x7f, 0x76, 0x03, 0xd1, 0x77, 0xaa, 0x81, 0x28, 0x6c, 0xe9, 0xb7, 0x74, 0x2f, 0xab, 0x4d, 0x61, - 0x0d, 0x15, 0xdf, 0xa7, 0x43, 0x8f, 0x53, 0xa6, 0xa9, 0x3f, 0xa7, 0xc0, 0x6d, 0xf3, 0x6d, 0x1a, 0xc6, 0x33, 0xb0, - 0xe0, 0xfc, 0xed, 0x6d, 0x2d, 0xc3, 0x78, 0xa6, 0x5a, 0x5a, 0xa6, 0x3c, 0xdc, 0x73, 0x11, 0xc2, 0x8d, 0x59, 0x37, - 0xba, 0x96, 0x38, 0x7b, 0xf6, 0xa1, 0xa9, 0xa4, 0xb4, 0x97, 0xa6, 0xab, 0x1d, 0x61, 0xff, 0xd8, 0x47, 0xd3, 0x49, - 0xd9, 0xb0, 0xf3, 0x32, 0x96, 0x49, 0x7b, 0x8a, 0x1e, 0xa4, 0x8b, 0x00, 0x0b, 0x12, 0xb3, 0xd1, 0x7f, 0x5a, 0x7b, - 0x5f, 0x5d, 0x7b, 0x83, 0xae, 0x07, 0x91, 0x19, 0x80, 0x57, 0xc3, 0x02, 0x77, 0xd0, 0xed, 0x42, 0xc1, 0xbd, 0x52, - 0xd0, 0x81, 0x82, 0x40, 0x29, 0xe8, 0x41, 0x81, 0xaf, 0x14, 0x1c, 0x41, 0xc1, 0x44, 0x29, 0x38, 0x86, 0x82, 0x3b, - 0x3d, 0xbf, 0x2e, 0x12, 0x39, 0x1d, 0x9b, 0x37, 0x16, 0xe3, 0x0d, 0x44, 0xd9, 0xb1, 0xe5, 0x81, 0x19, 0x23, 0x99, - 0xf5, 0x63, 0x8b, 0xc9, 0xe9, 0xfa, 0x89, 0x75, 0x3f, 0xa7, 0x2c, 0x4a, 0xfc, 0x1b, 0xbc, 0x3a, 0x9c, 0x2c, 0x06, - 0xa7, 0x09, 0x11, 0x7d, 0x45, 0xc0, 0x41, 0xd3, 0x4d, 0x10, 0xbd, 0x0c, 0xe4, 0xca, 0x89, 0x08, 0x36, 0xca, 0x5a, - 0x16, 0xef, 0xd8, 0xe7, 0x6c, 0xb9, 0x05, 0x0a, 0x4b, 0x2e, 0x43, 0x95, 0xef, 0x7d, 0x0e, 0x7b, 0x9e, 0x37, 0x74, - 0xbc, 0x9a, 0x69, 0x97, 0xf1, 0x6c, 0xa7, 0x69, 0x8e, 0xfa, 0x0a, 0x46, 0xa9, 0x33, 0x0d, 0x88, 0x2d, 0xb6, 0x25, - 0xff, 0x16, 0x7b, 0xcc, 0xcb, 0xf5, 0x33, 0x18, 0x9b, 0x96, 0x31, 0xc3, 0x30, 0xf8, 0x0e, 0xc0, 0x48, 0x39, 0xf5, - 0x97, 0x00, 0x67, 0xe5, 0xf9, 0x8a, 0x28, 0xe3, 0x39, 0xfb, 0x8e, 0xa6, 0x29, 0x99, 0x89, 0xfa, 0xf5, 0x71, 0x82, - 0x31, 0x9c, 0x64, 0xa3, 0x10, 0x80, 0x20, 0x13, 0x0b, 0x6a, 0x36, 0x4f, 0x49, 0x7c, 0xaf, 0x81, 0x55, 0x1d, 0x6c, - 0xa8, 0xc2, 0xfe, 0x27, 0x70, 0x60, 0x09, 0xcb, 0x38, 0x08, 0x0e, 0xff, 0x1d, 0x0d, 0xab, 0x85, 0x19, 0x99, 0x55, - 0x8b, 0xd8, 0x3e, 0xc8, 0xd5, 0xb1, 0x49, 0x93, 0x98, 0x52, 0xe1, 0xaf, 0xb1, 0xcb, 0x08, 0xe3, 0xd9, 0x6f, 0x6a, - 0x94, 0xb1, 0xc5, 0x30, 0xe7, 0x36, 0xb5, 0x82, 0x6c, 0xe4, 0x20, 0x8c, 0x35, 0x07, 0x40, 0xd8, 0x8f, 0xb2, 0xb9, - 0x8d, 0x7e, 0xa5, 0x46, 0x27, 0x32, 0x2d, 0x07, 0xd7, 0x76, 0x53, 0xf5, 0xa6, 0xef, 0x27, 0xb3, 0x31, 0x31, 0xbc, - 0xce, 0xb1, 0x25, 0xfe, 0x1c, 0xb7, 0x67, 0xe6, 0xd8, 0x83, 0x36, 0x09, 0xee, 0x36, 0xd3, 0x38, 0xca, 0xec, 0x29, - 0x59, 0x04, 0xe1, 0x43, 0x7f, 0x11, 0x47, 0x71, 0xba, 0x24, 0x3e, 0x1d, 0x14, 0x7c, 0xf1, 0x00, 0xe3, 0xb4, 0x70, - 0x57, 0x61, 0xcf, 0xe9, 0x24, 0x74, 0xc1, 0x5a, 0xcb, 0x30, 0x2c, 0xd3, 0x90, 0xae, 0x73, 0xfe, 0xf9, 0x52, 0x65, - 0x56, 0x15, 0xb7, 0x1c, 0x6b, 0x01, 0x84, 0x25, 0x8f, 0xf1, 0x02, 0x91, 0xcd, 0x06, 0x4b, 0x32, 0xc1, 0xb0, 0xa4, - 0x4e, 0xa7, 0x97, 0xd0, 0x85, 0xe6, 0xf4, 0x5a, 0x3b, 0x4f, 0xe2, 0xfb, 0x33, 0x18, 0x2d, 0x36, 0xb6, 0x53, 0x1a, - 0x4e, 0xf1, 0x8d, 0x8d, 0x6e, 0x65, 0xa2, 0x1f, 0x1b, 0xf9, 0x69, 0xe8, 0x8d, 0x2e, 0x06, 0xf0, 0xba, 0xdf, 0xd1, - 0xdc, 0xc1, 0x22, 0x88, 0x6c, 0x36, 0x9d, 0x63, 0x77, 0xa9, 0xf4, 0xa5, 0xc2, 0xcf, 0xdc, 0x60, 0x75, 0x4f, 0x73, - 0x07, 0xc0, 0x73, 0x4d, 0xc3, 0xf8, 0xbe, 0x3f, 0x0f, 0x26, 0x13, 0x1a, 0x0d, 0x70, 0xcc, 0xb2, 0x90, 0x86, 0x61, - 0xb0, 0x4c, 0x83, 0x74, 0xb0, 0x20, 0x6b, 0xde, 0xeb, 0x61, 0x5b, 0xaf, 0x5d, 0xde, 0x6b, 0x77, 0xef, 0x5e, 0x95, - 0x6e, 0xc0, 0x85, 0x8d, 0xf5, 0xc3, 0x87, 0xd6, 0xd3, 0xdc, 0xca, 0x3c, 0xf7, 0xee, 0x75, 0x99, 0xd0, 0xcd, 0x82, - 0x24, 0xb3, 0x20, 0xea, 0xbb, 0xb9, 0x73, 0xb7, 0x61, 0x1b, 0xe3, 0xe9, 0xc9, 0xc9, 0x49, 0xee, 0x4c, 0xc4, 0x93, - 0x3b, 0x99, 0xe4, 0x8e, 0x2f, 0x9e, 0xa6, 0x53, 0xd7, 0x9d, 0x4e, 0x73, 0x27, 0x10, 0x05, 0xdd, 0x8e, 0x3f, 0xe9, - 0x76, 0x72, 0xe7, 0x5e, 0xa9, 0x91, 0x3b, 0x94, 0x3f, 0x25, 0x74, 0x32, 0xc0, 0x8d, 0xc4, 0xec, 0xbc, 0xfb, 0xc7, - 0xae, 0x9b, 0x23, 0x06, 0xb8, 0x2e, 0xe1, 0x26, 0x14, 0xd9, 0xdc, 0x6c, 0xf6, 0xae, 0xa9, 0x15, 0x9f, 0xf3, 0xfd, - 0xc6, 0x7a, 0x13, 0x92, 0xdc, 0xde, 0x68, 0xca, 0x2c, 0x08, 0x61, 0xd5, 0x36, 0x02, 0x0c, 0xf6, 0xba, 0x0f, 0xf1, - 0xfa, 0x06, 0xe3, 0x38, 0x81, 0x33, 0x9b, 0x90, 0x49, 0xb0, 0x4a, 0xfb, 0x5e, 0x67, 0xb9, 0x16, 0x45, 0x7c, 0xaf, - 0x17, 0x05, 0x78, 0xf6, 0xfa, 0x69, 0x1c, 0x06, 0x13, 0x51, 0xd4, 0x76, 0x96, 0xbc, 0x8e, 0x39, 0xc0, 0x68, 0x15, - 0x01, 0xc6, 0x5c, 0x21, 0x61, 0xa8, 0x39, 0xdd, 0x54, 0xa3, 0x24, 0x45, 0x49, 0xad, 0xe6, 0xa6, 0x0c, 0x2e, 0x18, - 0x99, 0xc2, 0x3b, 0x5c, 0xae, 0xe5, 0x9e, 0xf7, 0x8e, 0x96, 0xeb, 0xfc, 0x0f, 0x0b, 0x3a, 0x09, 0x88, 0x66, 0x14, - 0xbb, 0xc9, 0x73, 0x41, 0x9a, 0x6b, 0x6e, 0x5a, 0xb6, 0xa9, 0x38, 0x16, 0x10, 0xd7, 0xf4, 0x49, 0xb0, 0x58, 0xc6, - 0x49, 0x46, 0xa2, 0x2c, 0xcf, 0x47, 0x37, 0x79, 0x3e, 0xb8, 0x0a, 0x8c, 0xeb, 0xbf, 0x1a, 0xec, 0x9e, 0x66, 0xda, - 0x8f, 0xdc, 0xbc, 0xb1, 0xde, 0x52, 0xd5, 0x52, 0x0a, 0xae, 0x31, 0xb4, 0x92, 0x52, 0x2b, 0xb3, 0x5b, 0xb2, 0x5e, - 0x99, 0x01, 0x59, 0x56, 0x67, 0x96, 0x57, 0xe5, 0x2a, 0x78, 0x03, 0x41, 0x85, 0xb7, 0x74, 0x78, 0xa5, 0x58, 0x5d, - 0x01, 0xb1, 0x82, 0x95, 0x99, 0x53, 0xd1, 0xb3, 0x36, 0x9a, 0xf1, 0xcb, 0xdd, 0x34, 0xe3, 0x8f, 0xd9, 0x3e, 0x34, - 0xe3, 0x97, 0x9f, 0x9d, 0x66, 0x7c, 0x56, 0x77, 0x2a, 0xba, 0x88, 0x87, 0xba, 0x94, 0xd5, 0xc3, 0xd5, 0x94, 0xb0, - 0x70, 0x5d, 0x17, 0xbf, 0xd8, 0x07, 0x48, 0xf4, 0xc6, 0x12, 0x50, 0xb2, 0x9b, 0x1b, 0x68, 0xf1, 0x77, 0xd1, 0xf0, - 0x2f, 0x89, 0xfa, 0x3c, 0x9d, 0x0e, 0xdf, 0xc4, 0x4a, 0x81, 0x7c, 0xe2, 0xf6, 0x0f, 0xa5, 0xd0, 0x2a, 0xec, 0x8d, - 0xb0, 0x6e, 0xc6, 0xe4, 0x33, 0x10, 0x99, 0x81, 0x59, 0xf3, 0x4f, 0xa4, 0xfd, 0xe6, 0xa0, 0x3c, 0x04, 0x43, 0x9a, - 0x52, 0x0b, 0xff, 0xbb, 0x9a, 0x44, 0x70, 0x46, 0x33, 0xee, 0x30, 0xff, 0xd5, 0xc3, 0xc5, 0xc4, 0xb8, 0x88, 0xcd, - 0x3c, 0x48, 0xdf, 0x55, 0xbd, 0xdf, 0xb8, 0x16, 0x65, 0xa8, 0x4e, 0x27, 0xe7, 0x76, 0x93, 0x6a, 0x76, 0x79, 0x78, - 0xcd, 0x9a, 0x9f, 0x97, 0x66, 0xda, 0x57, 0x1b, 0x72, 0x0e, 0xb4, 0x76, 0x19, 0x73, 0xd7, 0xa3, 0x0d, 0xa7, 0x00, - 0x31, 0x71, 0x1f, 0x06, 0x0d, 0x98, 0xb0, 0xe6, 0xc1, 0x24, 0xcf, 0xcd, 0x81, 0x00, 0x84, 0x72, 0xd1, 0xd2, 0x5d, - 0x44, 0x5c, 0x7a, 0x2f, 0xad, 0x03, 0xb8, 0xae, 0x8d, 0x29, 0xd2, 0x2e, 0x40, 0x35, 0xcd, 0xd5, 0x6e, 0x1c, 0x66, - 0xba, 0xc6, 0xc0, 0xc7, 0x4c, 0x16, 0x94, 0x09, 0x81, 0x2e, 0x55, 0xc2, 0x5f, 0xbc, 0x12, 0x05, 0x75, 0xdb, 0x68, - 0x06, 0x1c, 0xd4, 0xad, 0x43, 0x88, 0x0f, 0x21, 0x9e, 0x66, 0x68, 0x87, 0xd7, 0xc1, 0x87, 0x5c, 0x97, 0xb4, 0x1f, - 0x6e, 0x3f, 0x60, 0xcf, 0x96, 0x24, 0xaa, 0xf0, 0x92, 0xbb, 0x6c, 0x7c, 0x81, 0x94, 0x48, 0xef, 0x2d, 0x27, 0xbd, - 0xd7, 0x5e, 0x6c, 0x44, 0x78, 0x9c, 0x8c, 0x2c, 0x6d, 0xe0, 0x1c, 0x11, 0xf7, 0x72, 0x8c, 0xa7, 0x44, 0xe2, 0x19, - 0xac, 0x52, 0xc0, 0x8d, 0xc8, 0x70, 0x22, 0xfe, 0x19, 0xf8, 0xab, 0x24, 0x8d, 0x93, 0xfe, 0x32, 0x0e, 0xa2, 0x8c, - 0x26, 0x39, 0x82, 0xea, 0x1a, 0xe1, 0x23, 0xc0, 0x73, 0xb3, 0x89, 0x97, 0xc4, 0x0f, 0xb2, 0x87, 0xbe, 0xcb, 0x49, - 0x0a, 0x77, 0xc0, 0xa9, 0x03, 0xb7, 0xb1, 0x7e, 0x9f, 0x43, 0xf3, 0x25, 0x12, 0x7e, 0x49, 0x9d, 0x9c, 0x51, 0xb7, - 0xf9, 0x40, 0x79, 0xcb, 0x02, 0x04, 0x01, 0xf9, 0x41, 0x12, 0x7b, 0x06, 0x58, 0x1e, 0x96, 0xda, 0x9d, 0xd0, 0x99, - 0x85, 0x58, 0x1b, 0xc4, 0xeb, 0xe2, 0xcf, 0xe9, 0x99, 0x9a, 0xdb, 0x5c, 0x0c, 0x14, 0x8f, 0xb9, 0xcf, 0xc8, 0xfa, - 0x04, 0xd2, 0xe9, 0x59, 0xfb, 0xd4, 0x1c, 0xd3, 0x69, 0x9c, 0x50, 0x16, 0x4c, 0xda, 0x3b, 0x59, 0xae, 0xf7, 0xef, - 0x7e, 0xfb, 0xf4, 0x9b, 0xfb, 0x89, 0xe2, 0xcc, 0x10, 0x9d, 0x99, 0x3b, 0x7a, 0xab, 0xdf, 0x67, 0x40, 0x1a, 0x32, - 0xc8, 0xfb, 0x2c, 0x6e, 0x5f, 0x5f, 0xd7, 0x07, 0x8d, 0x31, 0xfb, 0x96, 0x31, 0xbf, 0xf3, 0x12, 0x1a, 0x92, 0x2c, - 0xb8, 0x13, 0x34, 0x63, 0xf7, 0x68, 0xb9, 0x16, 0x6b, 0x8c, 0x17, 0xde, 0x23, 0x16, 0xa9, 0x32, 0x14, 0xb1, 0x48, - 0xd5, 0x62, 0x5c, 0xa4, 0x41, 0x6d, 0x36, 0x22, 0x8c, 0x4d, 0xe5, 0xa6, 0xef, 0x2d, 0xd7, 0xea, 0x15, 0x5d, 0x34, - 0x93, 0x37, 0x75, 0x35, 0xfe, 0xe0, 0x22, 0x98, 0x4c, 0x42, 0x9a, 0x97, 0x16, 0xba, 0xbc, 0x96, 0x0a, 0x70, 0x24, - 0x1c, 0xc8, 0x38, 0x8d, 0xc3, 0x55, 0x46, 0x9b, 0xc1, 0xc5, 0x80, 0xd3, 0x71, 0x0b, 0xe0, 0xe0, 0xef, 0xf2, 0x58, - 0x7b, 0x40, 0x6e, 0xc3, 0x36, 0x71, 0x07, 0x10, 0x6e, 0xdc, 0xee, 0x96, 0x87, 0x0e, 0xaf, 0xe4, 0xa0, 0xad, 0x86, - 0x89, 0x58, 0x70, 0x2d, 0x31, 0xec, 0xad, 0x39, 0x1e, 0x2f, 0x93, 0x21, 0x97, 0x65, 0x51, 0x5e, 0x9e, 0xcc, 0x6f, - 0x73, 0xc6, 0x5e, 0x35, 0x9f, 0xb1, 0x57, 0xe2, 0x8c, 0x6d, 0xdf, 0x99, 0x4f, 0xa7, 0x1e, 0xfc, 0x37, 0x28, 0x26, - 0xd4, 0x77, 0xb5, 0xee, 0x72, 0xad, 0x79, 0xcb, 0xb5, 0x66, 0x77, 0x96, 0x6b, 0x0d, 0xbb, 0x46, 0xcb, 0x0a, 0xcb, - 0xe9, 0x98, 0x96, 0xab, 0x41, 0x21, 0xfc, 0xb9, 0xa5, 0x57, 0xde, 0x21, 0xbc, 0x83, 0x56, 0xbd, 0xfa, 0xbb, 0xce, - 0xf6, 0xa3, 0xce, 0xce, 0x92, 0x40, 0xda, 0xa6, 0x93, 0x91, 0xf1, 0x98, 0x4e, 0xfa, 0xd3, 0xd8, 0x5f, 0xa5, 0x7f, - 0xe7, 0xe3, 0xe7, 0x40, 0xdc, 0x8a, 0x08, 0x2a, 0xfd, 0x88, 0xa6, 0xa0, 0xef, 0xb8, 0xa3, 0xa2, 0x87, 0x8d, 0x5c, - 0xa7, 0x3e, 0x8b, 0x8d, 0xde, 0x71, 0x0e, 0x1b, 0x36, 0x79, 0x33, 0xa0, 0x7f, 0xb3, 0x55, 0x6a, 0x47, 0x31, 0xbf, - 0x02, 0x2c, 0x5b, 0xc1, 0xf1, 0x78, 0x68, 0xf0, 0xd5, 0x74, 0x4f, 0x9a, 0x87, 0x7b, 0x2d, 0xbe, 0x74, 0x23, 0x2e, - 0x15, 0x7e, 0x6f, 0x71, 0x87, 0xaf, 0xed, 0xbd, 0xb6, 0xed, 0x91, 0x5a, 0xaf, 0x5b, 0x2e, 0x84, 0xa2, 0xee, 0x9e, - 0x58, 0xfe, 0xe9, 0xab, 0x43, 0xf8, 0x8f, 0x51, 0xf5, 0x3f, 0x66, 0x4d, 0x84, 0xfa, 0x45, 0xd9, 0xff, 0x81, 0x91, - 0x4a, 0x48, 0x88, 0xef, 0x5f, 0x7f, 0x3a, 0x7d, 0x5c, 0x83, 0xbd, 0x6b, 0x33, 0xa3, 0xa4, 0x6a, 0xed, 0xaf, 0xe2, - 0x18, 0xf2, 0xf6, 0xd6, 0xab, 0x0b, 0xf0, 0x30, 0x17, 0x8f, 0x6c, 0x08, 0x8d, 0x04, 0x1f, 0xc1, 0x94, 0xf1, 0x3a, - 0xb6, 0x61, 0xac, 0xc4, 0xdb, 0x36, 0x56, 0xe2, 0xcd, 0x6e, 0x56, 0xe2, 0xdb, 0xbd, 0x58, 0x89, 0x37, 0x9f, 0x9d, - 0x95, 0x78, 0x5b, 0x67, 0x25, 0xae, 0x62, 0x61, 0x89, 0x6a, 0x5d, 0xac, 0xf8, 0xcf, 0x0f, 0x4c, 0xb7, 0x76, 0x19, - 0x0f, 0x7b, 0x2e, 0x8b, 0x77, 0x7e, 0xf5, 0x8b, 0x19, 0x0b, 0xdc, 0x88, 0xef, 0xd1, 0x30, 0xab, 0x60, 0x2d, 0x38, - 0x66, 0xc7, 0xef, 0x28, 0xc5, 0x61, 0x1c, 0xcd, 0xbe, 0x07, 0xdd, 0x2a, 0x88, 0x03, 0x13, 0xe5, 0x45, 0x90, 0x7e, - 0x1f, 0x2f, 0x57, 0xcb, 0x0b, 0xe8, 0xeb, 0x43, 0x90, 0x06, 0xe3, 0x90, 0xca, 0x30, 0x04, 0xcc, 0x90, 0x8c, 0xcb, - 0xc4, 0xc1, 0x76, 0x53, 0xfc, 0x24, 0x6b, 0xf1, 0x13, 0xad, 0x3b, 0xf9, 0x6f, 0x66, 0xa1, 0xa6, 0x37, 0x33, 0x22, - 0x10, 0xb0, 0xab, 0x32, 0xe8, 0xc7, 0x33, 0x23, 0x57, 0xb1, 0xd9, 0x30, 0x4b, 0x61, 0xb6, 0xd0, 0xda, 0x0f, 0xad, - 0x31, 0x35, 0x2b, 0xd3, 0x92, 0xf1, 0xf7, 0xea, 0x62, 0xf8, 0x45, 0xbc, 0x4a, 0xe9, 0x24, 0xbe, 0x8f, 0x74, 0x2b, - 0x95, 0xae, 0x35, 0xa0, 0xa8, 0x94, 0x6d, 0x30, 0x73, 0xac, 0xd4, 0xcc, 0xe8, 0x90, 0xb8, 0x78, 0xb5, 0xb4, 0x99, - 0xc6, 0xd8, 0xc6, 0x29, 0xea, 0x32, 0xc5, 0xd9, 0x13, 0xc3, 0x88, 0x87, 0x8f, 0x6b, 0x29, 0x2c, 0x2e, 0x62, 0x87, - 0x4b, 0x85, 0x53, 0x23, 0x15, 0xc2, 0x45, 0x11, 0x04, 0xa7, 0x61, 0xe1, 0xf8, 0x1b, 0xe6, 0x12, 0x5e, 0xbc, 0x85, - 0x10, 0x42, 0xf9, 0x8a, 0xaf, 0x07, 0x0f, 0x09, 0xc3, 0x1e, 0x5f, 0x2b, 0x60, 0x7c, 0x77, 0x47, 0x93, 0x90, 0x3c, - 0x18, 0x66, 0x1e, 0x47, 0xdf, 0x01, 0x00, 0xde, 0xc4, 0xf7, 0x91, 0x5a, 0x01, 0x33, 0x35, 0x35, 0xec, 0xa5, 0xc6, - 0xe0, 0x45, 0xe0, 0xae, 0xa5, 0x8c, 0x00, 0x72, 0x64, 0xcf, 0xe8, 0x5f, 0x2c, 0xf6, 0xef, 0x5f, 0xcd, 0xdc, 0xba, - 0x8c, 0xe5, 0x87, 0xfe, 0xbc, 0xdc, 0xe3, 0x33, 0xcf, 0x9f, 0x3f, 0x69, 0x9f, 0xb6, 0x01, 0xe9, 0xc2, 0x45, 0xe6, - 0x6b, 0xa3, 0xa1, 0xb5, 0xd9, 0x7a, 0x0a, 0x60, 0x14, 0x57, 0xf1, 0xca, 0x9f, 0xa3, 0xc9, 0xe8, 0xe7, 0x9b, 0x6f, - 0x06, 0x7d, 0x62, 0x8a, 0x62, 0x39, 0xf5, 0x4a, 0x51, 0x01, 0x05, 0xfc, 0xfe, 0x5b, 0x88, 0xbe, 0xfb, 0x6f, 0x04, - 0x43, 0x7d, 0xd7, 0x70, 0x2e, 0x3e, 0x78, 0xdc, 0xe6, 0x1d, 0x40, 0x26, 0x5d, 0x1e, 0xd7, 0x46, 0x28, 0xd7, 0x9a, - 0x91, 0x4c, 0x5e, 0x05, 0x9a, 0x1a, 0x43, 0xb2, 0x2d, 0x3c, 0xa6, 0xf8, 0x0a, 0x75, 0x18, 0x9b, 0xce, 0x4d, 0xf6, - 0x2d, 0xca, 0xb1, 0x55, 0x05, 0xc9, 0x70, 0xcb, 0x05, 0x8a, 0xe8, 0xab, 0xfa, 0x6e, 0x11, 0x44, 0x16, 0xa6, 0x80, - 0xa8, 0xbf, 0x21, 0x6b, 0x08, 0x82, 0x0e, 0xc8, 0xad, 0xfa, 0x0a, 0x0a, 0x2d, 0xaa, 0x78, 0x8b, 0x42, 0x9e, 0x37, - 0xbd, 0x11, 0x12, 0x42, 0x8b, 0x37, 0xfa, 0x9d, 0xa6, 0x69, 0x9a, 0x64, 0x23, 0x34, 0xc9, 0x47, 0x60, 0x39, 0xb2, - 0x03, 0xa0, 0x2d, 0xc9, 0x97, 0x6b, 0x56, 0x02, 0x9c, 0x01, 0x98, 0x78, 0xc8, 0x02, 0x1e, 0xe7, 0xb3, 0xe7, 0x8a, - 0x02, 0xc1, 0xd0, 0x43, 0x8c, 0x46, 0x92, 0x40, 0x38, 0xf0, 0xbe, 0x86, 0x0c, 0x3b, 0xbe, 0xe5, 0x92, 0x60, 0xcd, - 0x65, 0x8f, 0xa3, 0x01, 0x6d, 0x0e, 0x08, 0x99, 0x2a, 0x58, 0x10, 0xb4, 0x0e, 0x95, 0xf8, 0xee, 0x16, 0x6d, 0xc0, - 0x8d, 0xc8, 0x17, 0xad, 0xb3, 0x05, 0x8d, 0x56, 0x3a, 0x26, 0x84, 0xc3, 0xe0, 0xe2, 0x50, 0xe7, 0x0d, 0x23, 0xb6, - 0x00, 0xdb, 0x34, 0xb7, 0x9c, 0xb3, 0xbb, 0x30, 0xe2, 0x28, 0x95, 0x58, 0x3e, 0x57, 0x6c, 0x46, 0x1c, 0xb7, 0x55, - 0x6f, 0x08, 0xbe, 0xa4, 0x71, 0xd5, 0x7d, 0x91, 0xd9, 0x14, 0x43, 0x1f, 0x2c, 0x34, 0x0e, 0x17, 0x17, 0x09, 0xb0, - 0x1b, 0xa4, 0xba, 0x68, 0x52, 0x23, 0x43, 0x2a, 0x82, 0xa2, 0xc4, 0xac, 0x77, 0xc3, 0xc7, 0x09, 0x51, 0xc9, 0x5a, - 0xfb, 0xf1, 0x6b, 0xfd, 0xb4, 0x4c, 0xfa, 0x96, 0x3e, 0xb0, 0x8b, 0x84, 0x81, 0xea, 0x96, 0x3e, 0x80, 0x09, 0xdf, - 0x5b, 0x90, 0xa6, 0xe8, 0x5b, 0xd0, 0xb5, 0x05, 0x79, 0x3e, 0x7c, 0x88, 0x54, 0xb7, 0xe5, 0x00, 0xb9, 0xf9, 0x16, - 0x2c, 0x8e, 0x20, 0x86, 0x94, 0xee, 0xe2, 0x10, 0x73, 0x63, 0x79, 0xa3, 0x11, 0xc6, 0x76, 0xc3, 0xd1, 0x30, 0x5f, - 0x78, 0xae, 0x7b, 0x50, 0xab, 0x0f, 0x82, 0xec, 0xa6, 0xda, 0xa6, 0x95, 0x0d, 0x3d, 0xd7, 0x0e, 0x5e, 0x38, 0x9d, - 0x41, 0xed, 0x8e, 0x56, 0x02, 0xc9, 0x8e, 0x50, 0xfc, 0x75, 0xf6, 0x6c, 0x63, 0xa4, 0x2d, 0xe0, 0x2d, 0x8c, 0xcf, - 0x71, 0x6c, 0x39, 0x97, 0x7f, 0x8d, 0xea, 0x57, 0x3f, 0x0b, 0x63, 0xcb, 0x92, 0x1a, 0x8d, 0x20, 0x14, 0xba, 0x01, - 0xc7, 0xe8, 0xf7, 0xda, 0x4b, 0xcd, 0x60, 0xc7, 0xc7, 0x34, 0x47, 0x03, 0x81, 0x51, 0x84, 0x5b, 0x97, 0xda, 0x41, - 0xe5, 0x8b, 0x51, 0x15, 0xc3, 0xf1, 0xa0, 0xcb, 0xb4, 0xd0, 0xe8, 0x6d, 0xa5, 0x16, 0xb0, 0xff, 0x96, 0xeb, 0xd3, - 0x19, 0x43, 0xbc, 0x0f, 0xa8, 0x01, 0x89, 0x13, 0x76, 0x76, 0xb8, 0x5a, 0x96, 0xbb, 0x2b, 0x5f, 0x92, 0xfb, 0x77, - 0x86, 0x97, 0x0e, 0xea, 0xd0, 0x64, 0x7f, 0xcd, 0xd7, 0xdd, 0x23, 0xbb, 0xa4, 0xd1, 0xa4, 0xdc, 0x61, 0xe5, 0xfe, - 0xda, 0xbf, 0xbb, 0x12, 0x46, 0x81, 0x8c, 0x22, 0x71, 0x03, 0x46, 0xc9, 0xe3, 0x08, 0x37, 0x3f, 0x3b, 0x6e, 0xc1, - 0x5e, 0x54, 0x0c, 0x36, 0x60, 0xe1, 0x00, 0x65, 0x33, 0x45, 0x28, 0x0e, 0x61, 0xeb, 0xd1, 0x19, 0xde, 0x10, 0x84, - 0x68, 0xeb, 0x4e, 0xcc, 0x84, 0x69, 0x60, 0xd1, 0x26, 0xe0, 0x81, 0x68, 0xf7, 0x95, 0x5a, 0x07, 0xbb, 0xa5, 0xd6, - 0xd9, 0x2e, 0xa9, 0x35, 0x73, 0x4c, 0xba, 0x4f, 0xc8, 0x52, 0xf1, 0x6d, 0x13, 0xc4, 0xb9, 0xea, 0xe2, 0x56, 0x12, - 0x75, 0xa3, 0x1f, 0x93, 0x68, 0x55, 0xeb, 0x8d, 0x19, 0xfb, 0xa1, 0xf8, 0x5b, 0x61, 0x50, 0x84, 0x42, 0x5d, 0x95, - 0x8d, 0x5f, 0x15, 0xb2, 0x71, 0xc6, 0xd5, 0x14, 0x2e, 0x29, 0x82, 0xfa, 0x57, 0xdc, 0xbd, 0x24, 0x77, 0x50, 0xb8, - 0x7d, 0x15, 0x23, 0x55, 0x1c, 0x99, 0x0a, 0x46, 0x43, 0x71, 0x8f, 0x13, 0x5c, 0x46, 0xd9, 0x4b, 0xae, 0x5c, 0xb5, - 0xf0, 0x63, 0x2a, 0xca, 0x41, 0xea, 0x8e, 0x43, 0x96, 0xc5, 0xea, 0xb6, 0x29, 0x3b, 0xb2, 0xa8, 0xaf, 0x95, 0x4d, - 0x22, 0x3d, 0x4e, 0x18, 0x80, 0x85, 0x98, 0xbe, 0xa2, 0xd7, 0x96, 0x36, 0x10, 0x38, 0xc8, 0x06, 0x07, 0xb9, 0xdd, - 0xd2, 0x79, 0x96, 0x2c, 0xa5, 0xd0, 0xc2, 0xab, 0x32, 0x08, 0x84, 0xef, 0xcd, 0xa6, 0xe1, 0x96, 0xc7, 0x4b, 0x9e, - 0xdf, 0xef, 0x20, 0x5e, 0xd4, 0x5c, 0x55, 0x91, 0x8f, 0x27, 0xd3, 0x66, 0x56, 0xb6, 0x58, 0xb5, 0xde, 0x29, 0x13, - 0xe2, 0x6c, 0xb8, 0x8f, 0x49, 0x59, 0x46, 0xcf, 0x6b, 0xf4, 0xc5, 0x77, 0xf9, 0xd6, 0x49, 0x56, 0x11, 0x26, 0xb6, - 0xb0, 0xb3, 0x84, 0xf8, 0xb7, 0xca, 0x90, 0x85, 0x9c, 0x13, 0x64, 0xc0, 0x65, 0x4d, 0xc1, 0x80, 0x60, 0x1c, 0x58, - 0xda, 0x77, 0x3a, 0xa9, 0x22, 0x7d, 0xe9, 0x3f, 0x75, 0xbb, 0xe4, 0xd5, 0xf4, 0xb0, 0x22, 0x14, 0xed, 0xf4, 0xca, - 0x22, 0xf3, 0x96, 0x71, 0x64, 0xf3, 0xd5, 0x62, 0xbc, 0x51, 0x65, 0xab, 0x8a, 0xc8, 0xb5, 0x2e, 0x66, 0x55, 0x3f, - 0x3b, 0x9d, 0x4e, 0xcb, 0x82, 0x46, 0x57, 0x3b, 0x44, 0x61, 0xe1, 0x53, 0xd7, 0x75, 0xab, 0x63, 0xdf, 0x0e, 0x76, - 0x1b, 0xe5, 0xb6, 0x27, 0x8d, 0x23, 0x46, 0xd8, 0xee, 0x82, 0x5f, 0x1d, 0x1c, 0xb9, 0x53, 0x9c, 0xec, 0x92, 0x59, - 0xc4, 0x80, 0x19, 0x43, 0x04, 0x19, 0x5d, 0xa4, 0x7d, 0x9f, 0xa2, 0x0e, 0xc6, 0x51, 0x0e, 0x34, 0x1a, 0x0e, 0xd8, - 0x33, 0x30, 0x15, 0xf1, 0xc4, 0xae, 0x70, 0x35, 0x94, 0x87, 0xd7, 0x84, 0xf7, 0xe2, 0x23, 0x78, 0x50, 0x36, 0x75, - 0x99, 0x36, 0x4e, 0xab, 0xe7, 0xfe, 0xbe, 0x54, 0x4f, 0x83, 0x0b, 0x70, 0x23, 0x14, 0xda, 0x4c, 0x3e, 0x8b, 0xff, - 0x2f, 0xe5, 0xff, 0xaf, 0x96, 0xeb, 0xb2, 0xfd, 0xc8, 0x09, 0x48, 0xb4, 0x8b, 0xd3, 0xc2, 0x46, 0xdd, 0xb4, 0x07, - 0xa4, 0x95, 0xc1, 0x54, 0x55, 0xa0, 0x83, 0x92, 0xbe, 0x94, 0xfd, 0xa7, 0x41, 0xfc, 0x8e, 0x14, 0x33, 0x2c, 0x71, - 0x21, 0x42, 0x2c, 0x72, 0x57, 0xc2, 0x1c, 0xac, 0x97, 0x27, 0xa8, 0x3f, 0x28, 0xed, 0x09, 0xd0, 0xc6, 0xd7, 0xe6, - 0xb6, 0x97, 0xb8, 0xbf, 0xaa, 0xd7, 0x12, 0x1d, 0x03, 0xc8, 0x3c, 0x38, 0x84, 0x68, 0x48, 0xa0, 0x55, 0x36, 0x37, - 0x1b, 0xa5, 0x7c, 0xab, 0xea, 0xd9, 0xc4, 0xc0, 0xb0, 0xbb, 0xe6, 0x2a, 0xac, 0x6f, 0xa1, 0x2d, 0x80, 0xc9, 0xf2, - 0xed, 0x87, 0xcf, 0x36, 0x2c, 0xb1, 0xba, 0x1f, 0x3d, 0x5c, 0x72, 0xdc, 0xbf, 0x36, 0xde, 0x9d, 0x29, 0x3b, 0xff, - 0x28, 0x5f, 0xfc, 0xb6, 0x51, 0xa0, 0x77, 0x55, 0x92, 0xd0, 0x71, 0xa3, 0xef, 0x8e, 0xb9, 0x57, 0xed, 0x45, 0x10, - 0xed, 0x5f, 0x97, 0xac, 0xf7, 0xae, 0x0b, 0x17, 0xc6, 0xde, 0x95, 0xe1, 0xc6, 0x61, 0x96, 0x0b, 0xd9, 0xf0, 0x5b, - 0x45, 0xa0, 0xa8, 0xfa, 0xef, 0xea, 0xd8, 0x8a, 0x51, 0xf9, 0x57, 0x2b, 0x20, 0x3e, 0xf7, 0xca, 0xee, 0xa2, 0x89, - 0x04, 0x8d, 0xfa, 0xb1, 0x76, 0xa2, 0x1d, 0x77, 0xb5, 0x23, 0x57, 0x67, 0x5c, 0xd8, 0x50, 0xef, 0x75, 0x0a, 0xbf, - 0xbc, 0x43, 0x57, 0x3f, 0x3b, 0x9d, 0x89, 0x4b, 0x62, 0x1a, 0x84, 0x21, 0x43, 0x15, 0x60, 0xfe, 0x7b, 0x4b, 0xcb, - 0x6a, 0x16, 0x56, 0xc6, 0x8d, 0x40, 0x3a, 0xe2, 0x11, 0xce, 0x8e, 0x4f, 0x96, 0x7d, 0x3c, 0x1b, 0x6a, 0x21, 0x18, - 0x70, 0xb2, 0x52, 0xfc, 0x04, 0xdc, 0xc1, 0x63, 0xfd, 0xec, 0x14, 0xe2, 0x97, 0x6a, 0x93, 0xa1, 0xfe, 0x5d, 0xe7, - 0x58, 0xf3, 0x7a, 0x77, 0x76, 0xd7, 0x77, 0x6d, 0xcf, 0x39, 0xd4, 0x5c, 0xe7, 0xc8, 0xee, 0x38, 0xc7, 0x5a, 0xc7, - 0xe9, 0xc1, 0xbf, 0xbe, 0xe7, 0xbc, 0xd2, 0x5c, 0x78, 0xd2, 0x3c, 0xa7, 0x8b, 0xff, 0x76, 0x9c, 0xe3, 0xbb, 0x2e, - 0xbb, 0xe9, 0x89, 0xf4, 0x8e, 0xaa, 0x8c, 0x02, 0x7c, 0x39, 0xf4, 0x83, 0xb3, 0xd3, 0x55, 0x4a, 0xb5, 0xf5, 0x50, - 0x7f, 0xa5, 0x6b, 0xf3, 0x84, 0x4e, 0x87, 0xfa, 0x53, 0xa2, 0x94, 0x7a, 0x27, 0x8d, 0xc5, 0x9d, 0xe3, 0xc6, 0xe2, - 0xee, 0x51, 0x63, 0xf1, 0x61, 0xaf, 0x5c, 0x7c, 0x30, 0x63, 0xaf, 0x94, 0xf4, 0xa1, 0x0b, 0x92, 0x25, 0xc1, 0xda, - 0xf0, 0x34, 0x40, 0xd7, 0x36, 0xfc, 0x73, 0xdc, 0x31, 0x65, 0xab, 0x31, 0xb4, 0x92, 0xd0, 0x38, 0x3e, 0xd1, 0xbc, - 0xa3, 0x6f, 0x3a, 0x47, 0x3e, 0xd4, 0x83, 0x64, 0xb7, 0xf0, 0x77, 0xd7, 0x3d, 0xf1, 0x5d, 0x0d, 0x1a, 0x7a, 0xf0, - 0xdf, 0xbc, 0xd7, 0xf1, 0xd9, 0x83, 0x0b, 0xef, 0x3f, 0x78, 0xc7, 0xa9, 0x6b, 0x7b, 0xf0, 0xdf, 0xcf, 0x52, 0xe5, - 0x0e, 0x0a, 0x7f, 0xb5, 0xdf, 0x43, 0x57, 0xeb, 0x9e, 0xcc, 0x3b, 0xce, 0xab, 0xbb, 0x63, 0xe7, 0x64, 0xee, 0x1d, - 0x7f, 0x60, 0x4f, 0xa1, 0xdd, 0x71, 0x5e, 0xc1, 0xdf, 0x87, 0xae, 0x3b, 0xb7, 0x3d, 0xe7, 0xe4, 0xae, 0xeb, 0x74, - 0x43, 0xfb, 0xc8, 0x39, 0x81, 0xbf, 0x9f, 0x01, 0xbc, 0x00, 0x57, 0x9e, 0x9d, 0x58, 0x83, 0x8d, 0x51, 0xb1, 0xdf, - 0x50, 0x3f, 0xd2, 0x39, 0xd4, 0x7a, 0x87, 0xdf, 0x9c, 0xdc, 0xd9, 0x87, 0x73, 0xaf, 0x73, 0x67, 0xb7, 0xfe, 0xfc, - 0x00, 0x90, 0xdf, 0xbe, 0x70, 0x00, 0x46, 0x4c, 0x47, 0xf4, 0xbb, 0x91, 0x75, 0xd9, 0x26, 0x46, 0x7f, 0xbf, 0x5b, - 0x8c, 0xfe, 0xf5, 0x6a, 0x1f, 0x31, 0xfa, 0xfb, 0xcf, 0x2e, 0x46, 0xbf, 0xac, 0x5a, 0x71, 0xbf, 0xaf, 0xa6, 0x4d, - 0xf8, 0x71, 0x53, 0x25, 0x92, 0x03, 0x62, 0x5c, 0x5f, 0xad, 0x6e, 0x20, 0xe2, 0xd5, 0xfb, 0x78, 0xf8, 0xf5, 0xaa, - 0x64, 0xa2, 0x14, 0x03, 0x06, 0x78, 0x1f, 0x33, 0x0c, 0xf0, 0xa7, 0xd5, 0x10, 0xec, 0x22, 0xf8, 0xad, 0x19, 0x4c, - 0xec, 0x39, 0x09, 0xa7, 0xf2, 0xc6, 0x85, 0x92, 0x01, 0x16, 0x83, 0xdd, 0x3d, 0x5c, 0x26, 0xa0, 0xac, 0x59, 0x2d, - 0xa2, 0xb4, 0x7f, 0xe4, 0x02, 0x9a, 0xef, 0x4c, 0x93, 0xbc, 0xd2, 0xd8, 0x11, 0x31, 0xc2, 0x3e, 0x72, 0xcb, 0xfc, - 0xd6, 0xf7, 0x68, 0xb2, 0xd6, 0xdc, 0xbb, 0x57, 0xef, 0x57, 0x03, 0x5b, 0x10, 0x61, 0xd2, 0x07, 0xc4, 0x46, 0xd3, - 0xfb, 0xb2, 0xe1, 0x58, 0xc5, 0x54, 0xb0, 0x7d, 0xa4, 0x30, 0x92, 0x6a, 0x7b, 0xaf, 0x6c, 0x78, 0xb6, 0x6b, 0x9a, - 0x0d, 0x9f, 0x2f, 0x35, 0xdf, 0x62, 0xf5, 0x26, 0x3b, 0xae, 0x82, 0xaa, 0x92, 0xf4, 0xaf, 0x11, 0x20, 0x05, 0xed, - 0x59, 0x98, 0xc6, 0x15, 0x84, 0x8f, 0xab, 0xe1, 0x6d, 0xec, 0x2a, 0xef, 0x4a, 0x7d, 0xaa, 0xe6, 0x74, 0x2f, 0x36, - 0x48, 0x0f, 0x06, 0x3f, 0x03, 0x61, 0xc3, 0xef, 0xe3, 0x71, 0xac, 0xc2, 0x79, 0xa3, 0xf4, 0xcb, 0x48, 0xed, 0x7c, - 0xee, 0x6d, 0xea, 0xa4, 0x4d, 0xab, 0x21, 0xad, 0x47, 0x17, 0xe2, 0x8e, 0xc6, 0xcf, 0x33, 0xb3, 0xd5, 0x9c, 0x99, - 0x16, 0xa3, 0x65, 0xee, 0xb6, 0xce, 0x44, 0xbd, 0xa7, 0xb0, 0x89, 0x2d, 0xfe, 0xa0, 0xfa, 0x7f, 0x6f, 0xa6, 0x90, - 0xa0, 0xbd, 0x8f, 0x44, 0x84, 0x42, 0x41, 0x75, 0xd0, 0xc6, 0x76, 0xb0, 0xc5, 0xfc, 0x43, 0xed, 0x98, 0x77, 0x82, - 0xb6, 0xba, 0xdb, 0x2c, 0x46, 0xa4, 0x6b, 0xc3, 0xa6, 0xa4, 0x40, 0xf5, 0x7a, 0xc7, 0x96, 0x77, 0x64, 0x39, 0xc7, - 0x3d, 0x33, 0x17, 0x07, 0x4e, 0xed, 0xb2, 0x04, 0x10, 0x30, 0xd9, 0x95, 0xc3, 0x0c, 0xa2, 0x20, 0x0b, 0x48, 0x98, - 0x03, 0xaa, 0x2f, 0xd3, 0xbc, 0x7f, 0x5b, 0xa5, 0x19, 0xcc, 0x51, 0x90, 0x64, 0x68, 0xae, 0x6c, 0x8f, 0x69, 0x76, - 0x4f, 0x69, 0xd4, 0xa2, 0xca, 0xad, 0x5a, 0x3f, 0xff, 0x76, 0xb6, 0xa0, 0x39, 0xb3, 0xb3, 0x18, 0x67, 0x11, 0xdf, - 0x1f, 0xc2, 0x54, 0x37, 0x1f, 0x59, 0x3f, 0xb7, 0x21, 0xdc, 0xbf, 0xed, 0x46, 0xb8, 0x19, 0xdd, 0x07, 0xe1, 0xfe, - 0xed, 0xb3, 0x23, 0xdc, 0x9f, 0x55, 0x84, 0x5b, 0xf2, 0x54, 0x29, 0x64, 0xa2, 0x3f, 0xe0, 0xb3, 0x01, 0xf1, 0xc6, - 0x5f, 0xea, 0x07, 0x8c, 0xbc, 0xd4, 0x95, 0x3c, 0xd0, 0x1f, 0x4a, 0x89, 0xad, 0x90, 0x65, 0xc7, 0xd0, 0xc3, 0x2c, - 0x89, 0x0e, 0xe4, 0x48, 0x76, 0x85, 0xfb, 0x21, 0xf4, 0x79, 0x11, 0x65, 0xa1, 0xf3, 0x9e, 0xb3, 0x25, 0xa0, 0x82, - 0xf8, 0x3a, 0x4e, 0x16, 0x04, 0x83, 0x22, 0xea, 0x98, 0x10, 0x13, 0x1e, 0x5c, 0x70, 0x18, 0xf3, 0xe3, 0x68, 0x22, - 0xe5, 0xe8, 0x74, 0x78, 0xcd, 0xe8, 0x41, 0xfd, 0x81, 0x92, 0x44, 0xb7, 0xd8, 0x6b, 0x58, 0xdc, 0x17, 0x5d, 0xf7, - 0x45, 0xe7, 0xf0, 0xc5, 0x91, 0x0b, 0xff, 0xf3, 0x68, 0x37, 0xb7, 0x78, 0xc5, 0x45, 0x1c, 0x41, 0x4e, 0x1e, 0x51, - 0xb3, 0xad, 0xda, 0x3d, 0xa5, 0xb7, 0x45, 0xad, 0xe3, 0xe6, 0x4a, 0x13, 0xf2, 0x50, 0xd4, 0x69, 0xac, 0x31, 0x8f, - 0x57, 0xca, 0xb0, 0x1a, 0x46, 0x13, 0x44, 0x2b, 0x90, 0x0c, 0x29, 0x35, 0xd4, 0xd7, 0x7c, 0xba, 0xc5, 0xbc, 0x68, - 0x37, 0xbf, 0x29, 0x12, 0x7f, 0x89, 0x04, 0x44, 0x3b, 0x21, 0xc8, 0x85, 0xea, 0x2e, 0xa6, 0x0d, 0xc0, 0x68, 0x6f, - 0x1a, 0xa4, 0xdd, 0x14, 0x0b, 0x44, 0xd8, 0x02, 0x65, 0xc9, 0x2a, 0xf2, 0x0d, 0xfc, 0x49, 0xc6, 0xa9, 0x11, 0x1c, - 0x40, 0x4c, 0x5e, 0xfc, 0xb0, 0x89, 0xab, 0x46, 0xce, 0xdc, 0x22, 0x4b, 0x4a, 0x24, 0x56, 0x85, 0xbc, 0xc8, 0xac, - 0x84, 0xe5, 0x56, 0xc6, 0xa5, 0xb5, 0x87, 0xe4, 0x85, 0x6c, 0xf8, 0x22, 0xb3, 0x20, 0xbf, 0x31, 0x2c, 0xf7, 0xf3, - 0xe7, 0xac, 0x16, 0x64, 0x1c, 0x65, 0xd3, 0x3a, 0xf7, 0x65, 0x96, 0x42, 0x5d, 0x23, 0xb3, 0x58, 0xc7, 0x2c, 0x85, - 0x7d, 0xdf, 0x8a, 0x5f, 0xbe, 0x3c, 0x1b, 0x7a, 0x26, 0xcf, 0x97, 0x5b, 0x4a, 0xee, 0x76, 0xb9, 0x9f, 0x6a, 0xdc, - 0x6c, 0x74, 0xda, 0x5a, 0x06, 0xd1, 0x4c, 0x68, 0xa6, 0x25, 0xf6, 0x82, 0x64, 0x2b, 0x4c, 0x05, 0x46, 0x84, 0x8a, - 0x5a, 0xd4, 0xb9, 0xa3, 0x09, 0xe4, 0xfa, 0x1d, 0xea, 0x5d, 0xc7, 0x75, 0x5c, 0x5d, 0x36, 0x9c, 0x06, 0xb3, 0xe1, - 0x26, 0xce, 0x08, 0xa4, 0xad, 0x0a, 0xe3, 0x19, 0x78, 0x7e, 0x64, 0x41, 0x16, 0x42, 0x0e, 0x24, 0x70, 0x01, 0x59, - 0x30, 0xae, 0x31, 0xe7, 0xf6, 0xb8, 0x24, 0xb9, 0xc5, 0x3c, 0x98, 0xc2, 0xe9, 0x0b, 0x23, 0xcb, 0x7c, 0x07, 0x97, - 0xa1, 0xa1, 0x1b, 0x90, 0x85, 0x95, 0x26, 0xa9, 0xad, 0xda, 0xb7, 0xf7, 0x35, 0x68, 0x63, 0xea, 0x7c, 0x12, 0xd3, - 0x84, 0x2c, 0x20, 0x5d, 0xc0, 0x26, 0xb7, 0x38, 0xa6, 0xd5, 0x39, 0xaa, 0xd5, 0xbc, 0x57, 0x47, 0x96, 0xd6, 0xf1, - 0x2c, 0xcd, 0x05, 0x74, 0xab, 0xe7, 0xd6, 0x26, 0xbf, 0x19, 0xec, 0x52, 0xd1, 0x31, 0xfc, 0xf2, 0x94, 0xcd, 0x83, - 0x29, 0xe7, 0xb8, 0xf0, 0x33, 0x63, 0x41, 0x3d, 0x0d, 0x25, 0x90, 0x7f, 0xc0, 0xc4, 0xf4, 0x57, 0x74, 0x9d, 0x99, - 0x98, 0x23, 0x88, 0x57, 0x09, 0xcc, 0x0d, 0xba, 0xa6, 0x05, 0x91, 0x16, 0x7c, 0xfa, 0x64, 0x04, 0x60, 0x7e, 0x3f, - 0x54, 0xe0, 0x03, 0xcf, 0x66, 0x09, 0x60, 0x41, 0xa1, 0x58, 0x42, 0x60, 0x81, 0x6f, 0x0c, 0xfc, 0x5b, 0x14, 0x8b, - 0x1f, 0x5c, 0xb1, 0xe7, 0x84, 0x24, 0x9a, 0x01, 0x4a, 0x23, 0xd1, 0xac, 0x66, 0x40, 0xc0, 0xbc, 0xeb, 0x2a, 0xa5, - 0x45, 0x57, 0x85, 0x72, 0x3f, 0xfd, 0xea, 0xe1, 0x8a, 0xe5, 0x40, 0x33, 0x74, 0xb8, 0xe5, 0xd0, 0x15, 0xac, 0xd0, - 0x3d, 0xbc, 0x1c, 0x7e, 0x71, 0xba, 0xa0, 0x19, 0x61, 0x82, 0x4b, 0x60, 0xf1, 0x80, 0x1c, 0xd0, 0x7c, 0x91, 0xbf, - 0x98, 0x31, 0x78, 0x13, 0x7a, 0x17, 0xf8, 0x9c, 0x4f, 0xb3, 0x34, 0x7e, 0x4f, 0xd9, 0x68, 0xa3, 0x34, 0xf4, 0x2c, - 0x66, 0x22, 0xeb, 0x13, 0x0c, 0xfd, 0x39, 0x8c, 0x62, 0xfd, 0xec, 0x0b, 0xe9, 0x4d, 0xd4, 0xb6, 0x08, 0x90, 0x88, - 0xf4, 0x3a, 0xa1, 0xe1, 0xdf, 0x87, 0x5f, 0xc0, 0xc5, 0xfd, 0xc5, 0x8d, 0x6e, 0x0e, 0x32, 0x07, 0xf9, 0x98, 0x2f, - 0x1a, 0x12, 0x72, 0x22, 0x8f, 0xca, 0x99, 0xcd, 0xae, 0xc2, 0x6c, 0xc2, 0xef, 0xdd, 0xac, 0x2b, 0xb8, 0xa9, 0x3e, - 0x84, 0xf4, 0x0c, 0xb8, 0x8b, 0x4d, 0x89, 0xe7, 0xf4, 0x06, 0xc8, 0xa0, 0x8e, 0x43, 0xe2, 0xdf, 0x0a, 0x0e, 0x55, - 0x7d, 0xd8, 0x87, 0x17, 0x95, 0x94, 0x5d, 0xe3, 0x5e, 0xc6, 0xad, 0xbc, 0xc1, 0x2f, 0xe3, 0xa7, 0xee, 0xe7, 0x41, - 0x26, 0x99, 0x61, 0x7c, 0xc8, 0xd1, 0x37, 0x16, 0xc6, 0x57, 0xb0, 0x3f, 0xc0, 0xa0, 0x7a, 0x27, 0xdf, 0xf4, 0xee, - 0x3c, 0x77, 0xde, 0xf1, 0x1c, 0x60, 0x73, 0xe6, 0x5d, 0xe7, 0x38, 0xb4, 0xbb, 0xce, 0x31, 0xfc, 0x7d, 0x00, 0xd6, - 0xcb, 0xee, 0x38, 0x87, 0x1f, 0xbc, 0x4e, 0x68, 0x9f, 0x38, 0xc7, 0xf0, 0x77, 0xc9, 0x5a, 0xfd, 0x88, 0x4c, 0x0f, - 0x30, 0x3c, 0x5f, 0x94, 0xb0, 0x80, 0xf2, 0x5b, 0x6a, 0x11, 0xac, 0xd2, 0xf5, 0xd6, 0xa0, 0x89, 0x00, 0x94, 0xa1, - 0x5b, 0x22, 0x4a, 0x60, 0x3a, 0x30, 0xd2, 0x21, 0xcf, 0x6d, 0x21, 0x0c, 0x32, 0x84, 0xd7, 0xa4, 0xc8, 0xbc, 0xd0, - 0x78, 0x8c, 0x78, 0x9b, 0xe6, 0x30, 0xfb, 0x22, 0x69, 0x1a, 0x53, 0x5d, 0xfc, 0x79, 0x89, 0xf1, 0x71, 0xa8, 0x59, - 0xc3, 0x4a, 0x45, 0xe2, 0xce, 0x7c, 0xf7, 0xc0, 0xd1, 0x6f, 0x94, 0xca, 0xc4, 0x51, 0x9f, 0xb5, 0x6f, 0xae, 0xce, - 0x90, 0xbd, 0xff, 0xd2, 0x7e, 0x30, 0x5f, 0x32, 0xeb, 0x47, 0x44, 0xd8, 0x9d, 0x04, 0x89, 0x1c, 0x9e, 0x82, 0xa2, - 0xbd, 0xe6, 0xfc, 0x04, 0x26, 0x64, 0xd8, 0xb9, 0x00, 0x2a, 0xf9, 0x8e, 0x84, 0x8a, 0xe9, 0x85, 0xd2, 0xf2, 0x89, - 0xc4, 0xfc, 0xcf, 0x9f, 0x17, 0x83, 0xb3, 0x2b, 0xe3, 0x3e, 0xf5, 0x7a, 0x70, 0xed, 0xf6, 0x68, 0x77, 0xab, 0x15, - 0xd0, 0xee, 0x10, 0xcd, 0x45, 0x3c, 0x49, 0xa1, 0xe9, 0x17, 0x3a, 0xc6, 0x56, 0x53, 0xa4, 0x9a, 0x86, 0x11, 0xc2, - 0x5b, 0x57, 0x58, 0x1d, 0xdd, 0x1c, 0xa4, 0xfb, 0x84, 0xa5, 0xe6, 0xbc, 0x98, 0x0e, 0xa0, 0xd9, 0x32, 0x8f, 0x1d, - 0x2e, 0x8d, 0xff, 0xee, 0x49, 0xa0, 0x7b, 0x11, 0x68, 0xf8, 0x2a, 0xa7, 0xb5, 0xe4, 0x6e, 0x22, 0xef, 0x55, 0x76, - 0xa1, 0xd2, 0xf4, 0x5c, 0x87, 0x22, 0x48, 0xbd, 0x86, 0xd9, 0x16, 0xa5, 0x79, 0x93, 0xbc, 0x2d, 0x8a, 0x02, 0x2b, - 0x80, 0xc8, 0xef, 0x86, 0x70, 0x75, 0x32, 0x9f, 0x3f, 0x6f, 0xbd, 0x84, 0x98, 0x3a, 0x59, 0x4d, 0x3a, 0xab, 0xab, - 0xf8, 0x4d, 0x57, 0x51, 0x8c, 0xec, 0x17, 0xb1, 0x86, 0xb0, 0xca, 0x62, 0x7b, 0x0f, 0x7f, 0x8e, 0x29, 0xc9, 0x1c, - 0xae, 0x07, 0x31, 0x94, 0xcb, 0xdd, 0xf2, 0x68, 0x17, 0xec, 0xb1, 0x78, 0x18, 0x2d, 0x1e, 0x33, 0xee, 0xd9, 0xe6, - 0xc3, 0x8a, 0xfb, 0x21, 0x43, 0x1f, 0x9f, 0xdc, 0x22, 0x06, 0xca, 0xbb, 0x8c, 0xb0, 0x40, 0x19, 0xea, 0x95, 0x1b, - 0x67, 0x44, 0xa4, 0x38, 0x02, 0xba, 0x7c, 0xd0, 0xa8, 0x30, 0x54, 0x7c, 0x95, 0xcf, 0xde, 0x5d, 0x7d, 0xa9, 0xf1, - 0xfd, 0xcf, 0xf4, 0x5b, 0xc8, 0xc8, 0xb0, 0x5c, 0x17, 0x43, 0x96, 0xeb, 0x42, 0xe3, 0x59, 0x67, 0x20, 0x63, 0x44, - 0x7e, 0xc0, 0x20, 0xa8, 0x6b, 0x34, 0xf2, 0x99, 0xd6, 0x6f, 0xb1, 0x0a, 0xb3, 0x60, 0x49, 0x92, 0xec, 0x00, 0x9a, - 0xda, 0x80, 0xe4, 0xf4, 0x36, 0x0f, 0x66, 0xa6, 0x38, 0x14, 0x42, 0xb5, 0x2c, 0x12, 0x9a, 0xc3, 0x69, 0x10, 0x4a, - 0xc5, 0xa1, 0xf8, 0x00, 0xf1, 0x7d, 0xba, 0xcc, 0x86, 0x3a, 0x59, 0x42, 0xce, 0x13, 0x0c, 0x63, 0x7a, 0x10, 0xfb, - 0x19, 0xcd, 0xec, 0x34, 0x4b, 0x28, 0x59, 0xe8, 0x32, 0x64, 0x67, 0xbd, 0xbf, 0x74, 0x35, 0x5e, 0x04, 0x99, 0x8c, - 0x79, 0xc7, 0x26, 0x08, 0x2a, 0x3c, 0x18, 0x22, 0x84, 0x33, 0x60, 0x20, 0xbc, 0x8c, 0x67, 0x95, 0x1d, 0x55, 0x50, - 0x2e, 0xe7, 0x4a, 0x5c, 0x09, 0x10, 0x8e, 0xfa, 0x71, 0xf8, 0x91, 0x7b, 0x5d, 0xcb, 0xd0, 0x7c, 0xfa, 0xd9, 0x29, - 0x67, 0x6f, 0x35, 0x0c, 0x14, 0xa0, 0xf7, 0x5c, 0x08, 0x36, 0xdb, 0xe6, 0x8f, 0x7d, 0xc0, 0x2b, 0xab, 0x91, 0x15, - 0xfa, 0x97, 0x7c, 0x2c, 0x57, 0x40, 0x08, 0x95, 0x54, 0xbc, 0x73, 0xef, 0x4c, 0x3a, 0x00, 0xe1, 0xa8, 0x90, 0x56, - 0xfa, 0xf4, 0xe9, 0xf5, 0xe8, 0x9f, 0xff, 0x80, 0x14, 0x04, 0x73, 0x4f, 0x78, 0x41, 0x5f, 0xab, 0xb5, 0x38, 0xf5, - 0x69, 0x8d, 0x50, 0xbd, 0x4f, 0x27, 0x22, 0x2a, 0x8c, 0xd8, 0x5a, 0xf9, 0xe8, 0x46, 0x44, 0x6c, 0x82, 0x34, 0x23, - 0xa6, 0xf0, 0xd5, 0x1e, 0xc1, 0xf2, 0x8e, 0x44, 0x88, 0x00, 0xed, 0xa7, 0xf5, 0x57, 0xc7, 0x9a, 0x5e, 0xe4, 0x0e, - 0x68, 0xd0, 0x41, 0xb3, 0x3d, 0x74, 0x76, 0x4a, 0xb8, 0xf0, 0x15, 0xc8, 0x8f, 0xb4, 0x7f, 0x00, 0xd3, 0x9c, 0xc7, - 0x0b, 0xea, 0x04, 0xf1, 0xc1, 0x3d, 0x1d, 0xdb, 0x64, 0x19, 0x30, 0xf9, 0x32, 0xca, 0xdd, 0x34, 0x46, 0xf9, 0x49, - 0x05, 0x2d, 0xa3, 0xaf, 0xf3, 0x02, 0x94, 0x71, 0x01, 0x28, 0xf8, 0x49, 0xce, 0xca, 0x71, 0xf8, 0x1c, 0x91, 0x17, - 0xa2, 0x8c, 0xe5, 0xcf, 0x59, 0x38, 0x3d, 0x11, 0x39, 0xaf, 0x78, 0xb0, 0xe3, 0xe9, 0x54, 0x8d, 0x9d, 0xe7, 0x94, - 0xbf, 0x2f, 0xa1, 0x52, 0xec, 0xd9, 0x78, 0xc9, 0xbe, 0x54, 0xff, 0x84, 0xfc, 0x09, 0xb1, 0x40, 0x78, 0x98, 0x45, - 0x38, 0xcf, 0xb5, 0x18, 0x7c, 0x12, 0x24, 0x4f, 0x59, 0x25, 0x8e, 0x28, 0xaa, 0xd1, 0xd9, 0x5b, 0x48, 0x93, 0x27, - 0xc3, 0x21, 0xc3, 0x63, 0x55, 0x74, 0x06, 0x50, 0x6a, 0xc8, 0x91, 0x01, 0x93, 0xcd, 0xa0, 0xa1, 0xcd, 0x3c, 0xb8, - 0xb0, 0x51, 0x75, 0x3a, 0xf5, 0x31, 0x1e, 0x10, 0xb1, 0xbf, 0x4a, 0x3b, 0x10, 0x76, 0x16, 0x5f, 0x58, 0x40, 0xe0, - 0xa2, 0x9f, 0x0a, 0x1e, 0xd7, 0xfe, 0xc0, 0x50, 0xb6, 0x1d, 0x92, 0x87, 0x58, 0xd1, 0xac, 0x73, 0x27, 0xfb, 0x4b, - 0x2c, 0xbd, 0x12, 0xce, 0x6d, 0xb5, 0x93, 0x24, 0xb3, 0x00, 0xd4, 0x4f, 0x93, 0x1a, 0xb6, 0x7f, 0xd7, 0x61, 0x52, - 0xeb, 0x96, 0x27, 0x83, 0xd8, 0x31, 0x2f, 0x0e, 0x5a, 0xe9, 0x25, 0x9e, 0xfb, 0xfc, 0xf4, 0x00, 0xe6, 0x07, 0x81, - 0x01, 0x4a, 0x94, 0x51, 0x60, 0x42, 0xf4, 0x01, 0x92, 0x32, 0xeb, 0x80, 0x8b, 0x89, 0x20, 0xea, 0x90, 0x73, 0x94, - 0x41, 0x3e, 0x4b, 0x55, 0xea, 0xc4, 0x8a, 0xdb, 0x4c, 0xe5, 0xed, 0xce, 0xc0, 0xf1, 0xa7, 0x15, 0xa6, 0xdf, 0xc8, - 0x07, 0x19, 0x15, 0x7e, 0xb7, 0x97, 0x59, 0x8b, 0x6b, 0x6e, 0x5b, 0x15, 0x46, 0xb0, 0x6e, 0xa9, 0x50, 0xec, 0xe3, - 0x6d, 0xb5, 0x0a, 0xd2, 0x48, 0x56, 0x5b, 0x12, 0x43, 0x7f, 0x8a, 0x3b, 0xbe, 0x56, 0x1b, 0x4b, 0xa1, 0xde, 0x65, - 0x36, 0x84, 0xaa, 0x42, 0xd8, 0x4e, 0x96, 0x4b, 0x56, 0xd9, 0x1c, 0x9c, 0x1e, 0x30, 0xbe, 0xf3, 0x8c, 0xed, 0xb0, - 0xb3, 0x53, 0xb0, 0x2e, 0x64, 0x8b, 0x4e, 0x96, 0x4b, 0xbe, 0xa4, 0xec, 0x17, 0x7b, 0x73, 0x30, 0xcf, 0x16, 0xe1, - 0xd9, 0xff, 0x01, 0xff, 0xd7, 0x9f, 0x05, 0x1b, 0x5f, 0x03, 0x00}; + 0x1e, 0x7f, 0xcb, 0xc7, 0x6c, 0x61, 0x3c, 0x35, 0x6f, 0xaf, 0x16, 0x93, 0xc1, 0xe0, 0xd6, 0xdf, 0xdf, 0xf3, 0x70, + 0x76, 0x3b, 0x67, 0xd7, 0xfc, 0x9e, 0x16, 0xd3, 0x44, 0x35, 0xbd, 0x78, 0x4c, 0xf0, 0xba, 0xf5, 0xfd, 0x89, 0xc5, + 0xff, 0x6a, 0x5f, 0x34, 0x6f, 0xfd, 0x81, 0xb4, 0x46, 0xcb, 0x5d, 0xfd, 0xfd, 0xe3, 0x8a, 0x89, 0x5b, 0x10, 0x2f, + 0xde, 0xdb, 0x9a, 0x86, 0xb7, 0xfc, 0xa3, 0x77, 0xed, 0x4f, 0xaf, 0x75, 0xcc, 0xcd, 0x44, 0x1d, 0x49, 0x6f, 0x2f, + 0x9e, 0xb3, 0x5f, 0xf9, 0x27, 0x79, 0x9c, 0x7c, 0x11, 0x72, 0xd2, 0xde, 0x20, 0x77, 0x13, 0x9d, 0x12, 0xef, 0xdc, + 0x44, 0xc2, 0x82, 0x40, 0x18, 0x8e, 0x9a, 0x3f, 0x4c, 0xca, 0xa9, 0xb7, 0x03, 0x6e, 0x57, 0x6e, 0xeb, 0x9f, 0x6f, + 0x39, 0xe7, 0x8b, 0xe1, 0xe5, 0xf4, 0x5d, 0xb7, 0x4b, 0x8f, 0x8a, 0x66, 0x53, 0x81, 0x6e, 0xb7, 0x18, 0x7b, 0x75, + 0x32, 0xb3, 0xcc, 0x25, 0x5f, 0x7a, 0x57, 0x9b, 0x99, 0xc7, 0xf4, 0x7e, 0x33, 0xcd, 0x90, 0xc8, 0x17, 0x08, 0x99, + 0x0e, 0x87, 0xbb, 0x73, 0x2c, 0x8f, 0x0f, 0xdf, 0x3e, 0x7b, 0x32, 0x78, 0x82, 0x91, 0x5b, 0x56, 0x34, 0xc8, 0x3b, + 0x3e, 0xcc, 0xea, 0xd6, 0x6d, 0xe3, 0xe2, 0xf9, 0xf0, 0x17, 0xc8, 0x1b, 0x74, 0x3d, 0x34, 0x45, 0xb4, 0xca, 0xef, + 0x28, 0xfa, 0x44, 0xc9, 0x41, 0xc7, 0x13, 0xa8, 0x1d, 0x52, 0xe0, 0xbe, 0x7b, 0xc6, 0x41, 0xbf, 0x81, 0xa5, 0xf6, + 0xfb, 0xe7, 0x9f, 0x88, 0x47, 0x1a, 0xc6, 0xfb, 0xfb, 0x30, 0xfa, 0x23, 0x2e, 0x8b, 0x35, 0x9c, 0xae, 0x03, 0xf8, + 0xdc, 0x33, 0x7d, 0xfb, 0xba, 0xf3, 0x7d, 0x3f, 0xf0, 0xb6, 0xfc, 0x86, 0xbd, 0xe3, 0xde, 0xe5, 0xf0, 0xad, 0xff, + 0xec, 0x09, 0x88, 0x4e, 0x30, 0x2e, 0x9f, 0x31, 0x12, 0xb6, 0xa3, 0x18, 0xb5, 0x0a, 0x3f, 0xd7, 0x10, 0xa2, 0xf5, + 0x09, 0x19, 0xbb, 0x20, 0xfd, 0x83, 0x02, 0xf4, 0x13, 0x02, 0xab, 0x49, 0x6a, 0x14, 0x98, 0xc4, 0xb7, 0x35, 0x24, + 0x90, 0x82, 0x05, 0x42, 0x6f, 0xa0, 0xf8, 0x54, 0xf0, 0x77, 0xc3, 0xcf, 0x24, 0xf9, 0x2d, 0x6a, 0x3e, 0x86, 0xbf, + 0x61, 0x68, 0x26, 0xd5, 0x43, 0x5a, 0x47, 0x89, 0xf7, 0x93, 0xbf, 0x8f, 0xc2, 0x4a, 0xa8, 0x63, 0x21, 0x48, 0xc5, + 0x90, 0x0b, 0x71, 0xf1, 0x7c, 0x72, 0x5b, 0x8a, 0xf0, 0x8f, 0x09, 0x3e, 0x93, 0x0b, 0x4d, 0x3e, 0xa3, 0x27, 0x8d, + 0x7c, 0xff, 0x41, 0xbe, 0x2f, 0x3b, 0x35, 0x58, 0xd4, 0x43, 0x7e, 0x5b, 0xbb, 0xef, 0xcb, 0x29, 0x41, 0x8f, 0xec, + 0x07, 0x34, 0x05, 0x03, 0x35, 0x01, 0x29, 0x43, 0x70, 0x0b, 0x57, 0x7d, 0x4f, 0x15, 0xe4, 0xcb, 0xef, 0x7d, 0x16, + 0x32, 0x5c, 0x65, 0x41, 0x48, 0x72, 0xa9, 0x90, 0xc2, 0xc6, 0x6d, 0x3d, 0xf8, 0xac, 0x31, 0x49, 0x24, 0xe4, 0x94, + 0x80, 0x24, 0x69, 0x6f, 0x20, 0x49, 0xc4, 0xf4, 0x1f, 0xae, 0x93, 0xa6, 0x59, 0x49, 0xe9, 0x86, 0x38, 0x55, 0xaf, + 0x91, 0xe6, 0x2c, 0x78, 0xcf, 0x60, 0xe9, 0x48, 0xb1, 0xe2, 0x9d, 0x31, 0x18, 0xeb, 0x60, 0xa1, 0x3b, 0x59, 0xdc, + 0xaf, 0x92, 0x30, 0x8d, 0x44, 0x95, 0x2f, 0x42, 0xfe, 0xfc, 0x97, 0x12, 0x7f, 0xf4, 0x96, 0x06, 0x22, 0x10, 0xfc, + 0x00, 0xad, 0x07, 0xac, 0xf1, 0xe0, 0x27, 0x56, 0x97, 0x61, 0x5e, 0x65, 0x54, 0xde, 0x6c, 0xc7, 0xb6, 0x73, 0xa6, + 0xaa, 0x16, 0x7c, 0x16, 0x86, 0x16, 0xed, 0x6c, 0xd5, 0x9c, 0xdc, 0xe6, 0x0d, 0xbe, 0x33, 0x49, 0x22, 0xb5, 0x94, + 0x44, 0xda, 0xea, 0xfa, 0x74, 0xe9, 0x75, 0x8b, 0x0a, 0x1a, 0x23, 0x40, 0x2f, 0x49, 0x77, 0x95, 0x4f, 0x28, 0x5e, + 0x59, 0x0d, 0xab, 0xe1, 0xa5, 0x43, 0x11, 0xc6, 0xda, 0x9b, 0x2b, 0x79, 0x76, 0x07, 0xd6, 0x23, 0xb4, 0x76, 0x55, + 0xea, 0x10, 0xb6, 0x9f, 0xe8, 0x3d, 0xa7, 0x52, 0x7f, 0x03, 0xaa, 0xc0, 0xa9, 0xa3, 0xa1, 0x3e, 0x6a, 0xa7, 0x90, + 0xed, 0xdc, 0x5b, 0x12, 0x54, 0xae, 0xe4, 0xa6, 0x4a, 0x8b, 0x52, 0xca, 0x94, 0xaf, 0x65, 0xb6, 0xb2, 0xfb, 0x64, + 0x00, 0xf1, 0x6c, 0x50, 0x20, 0xb9, 0xa8, 0xad, 0xe6, 0x20, 0x7d, 0x34, 0x4b, 0x1c, 0x6b, 0x07, 0x85, 0x97, 0x55, + 0x60, 0xe6, 0x32, 0x97, 0xcb, 0x41, 0xc1, 0x72, 0xbd, 0xd5, 0x4c, 0x33, 0xd5, 0x17, 0xb9, 0xbd, 0xcd, 0x78, 0x99, + 0xfe, 0x9b, 0x25, 0x03, 0x1e, 0x5d, 0x3c, 0xf7, 0x03, 0x48, 0x93, 0xbc, 0x0e, 0x90, 0x04, 0x9b, 0x83, 0x5d, 0xec, + 0x30, 0x6c, 0x15, 0x2b, 0x7b, 0xf2, 0x74, 0xb9, 0x43, 0x53, 0x2e, 0x61, 0x24, 0x27, 0xe6, 0x52, 0xea, 0xfb, 0x92, + 0xea, 0x86, 0x82, 0x93, 0x4d, 0x13, 0x50, 0x0a, 0x68, 0xb7, 0xe0, 0xbf, 0xf0, 0xa9, 0xa1, 0xd3, 0x02, 0x2c, 0xb5, + 0xdd, 0x80, 0xff, 0x42, 0xbf, 0xd8, 0x3e, 0xa2, 0x7e, 0x60, 0x1e, 0xec, 0xcd, 0xda, 0xca, 0x18, 0x10, 0x91, 0xb8, + 0x82, 0x3c, 0x12, 0xfc, 0xa0, 0xd8, 0xd3, 0x65, 0xe2, 0xc0, 0x99, 0xe2, 0x62, 0x29, 0xb5, 0x99, 0x79, 0xed, 0xb7, + 0xd4, 0xc4, 0x9b, 0x28, 0x89, 0x0a, 0xdb, 0x21, 0x8d, 0x5e, 0x52, 0xc6, 0x54, 0xc1, 0x86, 0xe8, 0xbe, 0x6e, 0x82, + 0x29, 0xf0, 0xa6, 0xaa, 0x02, 0x22, 0xd4, 0x5e, 0x64, 0x79, 0x7e, 0xd3, 0x05, 0x56, 0x17, 0x7c, 0x6c, 0x4c, 0xb3, + 0x0b, 0x56, 0x72, 0x35, 0x93, 0x3e, 0xf3, 0x76, 0xa0, 0x85, 0xbc, 0xcb, 0xcb, 0xa2, 0x15, 0xba, 0x1e, 0x44, 0x0b, + 0x7f, 0xaf, 0x39, 0x1e, 0x3d, 0xdb, 0x56, 0x53, 0x9b, 0x7d, 0xad, 0xc5, 0x02, 0x19, 0x88, 0x86, 0xbe, 0x90, 0x33, + 0x0a, 0x77, 0x95, 0xe6, 0x6a, 0xb5, 0xaf, 0xca, 0x20, 0x81, 0x89, 0x20, 0x6b, 0x59, 0x78, 0x8f, 0xee, 0xd5, 0x23, + 0xcd, 0x2b, 0x09, 0x9e, 0xb9, 0xf8, 0x0b, 0x00, 0xa1, 0x3c, 0x49, 0xc8, 0x01, 0x39, 0x80, 0xbf, 0xa5, 0x28, 0x95, + 0x06, 0xf8, 0x67, 0x75, 0x39, 0xb6, 0xf5, 0xfd, 0x9d, 0x56, 0x31, 0xb8, 0xfe, 0x7c, 0xdd, 0xf5, 0xac, 0x1d, 0xe2, + 0x5c, 0xd9, 0xea, 0xb5, 0x65, 0x9a, 0xc7, 0x48, 0x5d, 0x03, 0x70, 0x27, 0xd2, 0x23, 0x10, 0xc9, 0x4c, 0x34, 0xc8, + 0xd9, 0x0b, 0x3e, 0x9e, 0x8a, 0xc7, 0xa4, 0xbd, 0xca, 0xf7, 0xcd, 0x85, 0x3e, 0x18, 0x63, 0xdf, 0x82, 0x06, 0xf1, + 0xd1, 0x6a, 0x6b, 0x05, 0x62, 0xbd, 0x55, 0xea, 0x43, 0x37, 0x46, 0x41, 0x07, 0x8f, 0xb8, 0x91, 0x0b, 0x8e, 0xed, + 0xae, 0xad, 0xa7, 0xf4, 0x15, 0x80, 0xb9, 0x0e, 0x54, 0x32, 0x0c, 0x52, 0xe7, 0x89, 0xc2, 0x24, 0x3f, 0x4f, 0x48, + 0x42, 0x44, 0x75, 0xb6, 0x1c, 0xa5, 0xdc, 0xb4, 0x80, 0xcb, 0x8c, 0x0c, 0x30, 0x9b, 0x34, 0xeb, 0x27, 0x97, 0x2f, + 0x41, 0x2a, 0x0d, 0x11, 0xdc, 0xb0, 0xbd, 0x64, 0x74, 0xeb, 0xa8, 0x1b, 0x54, 0x49, 0xe6, 0xfa, 0xcd, 0xed, 0x2c, + 0x52, 0xe6, 0xcd, 0x47, 0x18, 0x6b, 0xf2, 0x21, 0xac, 0x13, 0xfc, 0x36, 0x40, 0x25, 0x7d, 0x2a, 0xbc, 0x68, 0x04, + 0x10, 0xea, 0x3b, 0x55, 0xc6, 0xa7, 0xc2, 0xcb, 0x46, 0x5b, 0x96, 0x51, 0x0a, 0xd5, 0x05, 0xb3, 0x5b, 0xd3, 0x85, + 0xe8, 0x56, 0xd5, 0x40, 0x1b, 0xb8, 0x76, 0x1d, 0x28, 0xa0, 0xa1, 0xda, 0x95, 0x1b, 0x16, 0x80, 0xd5, 0x4c, 0x04, + 0x86, 0xcb, 0xbf, 0xcf, 0x5f, 0xa9, 0x18, 0x9e, 0x7e, 0x3f, 0xf4, 0xf6, 0xdb, 0x20, 0x1a, 0x6d, 0x2f, 0xd9, 0x2e, + 0x88, 0x46, 0xbb, 0xcb, 0x86, 0xd1, 0xef, 0xe7, 0xf4, 0xfb, 0x79, 0x03, 0x3a, 0x12, 0x61, 0xc2, 0xec, 0xf5, 0x1b, + 0xb5, 0x7c, 0xa5, 0xd6, 0xef, 0xd4, 0xf2, 0xa5, 0x1a, 0xde, 0xda, 0x93, 0x44, 0x10, 0x59, 0xaa, 0x9a, 0x07, 0x49, + 0x91, 0x6a, 0xe9, 0x72, 0x8c, 0x16, 0x23, 0x6a, 0x29, 0x6b, 0x8e, 0x75, 0x22, 0xed, 0x1c, 0x94, 0x0c, 0x70, 0xb4, + 0xb8, 0xaa, 0x31, 0xdd, 0xac, 0x68, 0x09, 0xc4, 0x08, 0x2b, 0xdb, 0x72, 0x71, 0x93, 0xfa, 0xe8, 0x9c, 0x7c, 0xdb, + 0x2a, 0xe5, 0xdb, 0x56, 0xf0, 0xfc, 0x2b, 0x0a, 0xe5, 0x92, 0x6b, 0xd7, 0xb2, 0x69, 0xa1, 0x14, 0xca, 0xb8, 0x06, + 0x5b, 0xfb, 0x26, 0x30, 0x64, 0x3e, 0x52, 0xd4, 0xd8, 0x5e, 0x34, 0xca, 0x21, 0xc8, 0xd6, 0xc1, 0xa8, 0x53, 0x16, + 0x2c, 0xbe, 0xdd, 0x21, 0x03, 0x19, 0xe8, 0xa8, 0x6a, 0xe3, 0xd5, 0xce, 0x4a, 0x7f, 0x58, 0x5e, 0x3c, 0x67, 0x89, + 0x95, 0x4e, 0x7e, 0x53, 0xa1, 0x3f, 0x08, 0xd1, 0x37, 0x65, 0xc3, 0xc1, 0x8b, 0x2e, 0xb6, 0x32, 0x20, 0xde, 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, 0xf3, 0x28, 0xd4, + 0x2c, 0x4f, 0x00, 0x0b, 0x5e, 0x98, 0x19, 0x2e, 0xcc, 0x0c, 0xc7, 0x21, 0x35, 0x4e, 0x0f, 0x7a, 0xaf, 0x73, 0xcf, + 0x2d, 0x77, 0xa3, 0xd3, 0x30, 0x6f, 0x47, 0x1b, 0xcc, 0xf1, 0x41, 0x38, 0x81, 0xf8, 0xc0, 0x12, 0x01, 0x7a, 0x34, + 0xac, 0x8e, 0x1a, 0x2a, 0x47, 0xf1, 0x65, 0x01, 0x48, 0x96, 0x04, 0x20, 0xb9, 0x57, 0xe3, 0x5c, 0x5a, 0x7e, 0x5d, + 0x25, 0x21, 0x47, 0x64, 0xbc, 0x94, 0x76, 0xf7, 0x84, 0x97, 0x23, 0x23, 0x34, 0x4f, 0x16, 0xa9, 0x97, 0xb3, 0x8c, + 0x8d, 0x11, 0xb8, 0x28, 0xf4, 0x9b, 0xaa, 0xdf, 0x4f, 0x4b, 0x2f, 0xa7, 0x76, 0x7e, 0x02, 0x7f, 0xcb, 0x53, 0x67, + 0x91, 0x23, 0xe4, 0xd5, 0xc8, 0x24, 0x2c, 0x2f, 0x95, 0x7a, 0xfa, 0x12, 0x66, 0x50, 0x77, 0x6f, 0x14, 0x80, 0x6b, + 0x91, 0x4b, 0xa7, 0xda, 0x12, 0xae, 0x4c, 0xb9, 0xc1, 0x3e, 0x0f, 0x79, 0x4e, 0x42, 0xa8, 0x44, 0x1e, 0x29, 0xac, + 0xfb, 0xf6, 0xc5, 0xf3, 0x89, 0xeb, 0xc3, 0x62, 0xa3, 0x11, 0x1c, 0x0e, 0x00, 0x73, 0x30, 0xf5, 0xa2, 0x01, 0x2f, + 0xd5, 0x9c, 0xf9, 0xe8, 0xe5, 0x84, 0x8d, 0x01, 0x6a, 0x8a, 0x81, 0x53, 0xd6, 0x33, 0xf9, 0xc8, 0xf8, 0x96, 0xf9, + 0x7e, 0x80, 0xef, 0xd6, 0x85, 0x84, 0x7c, 0x50, 0xa8, 0x04, 0x99, 0x42, 0x25, 0x48, 0x0c, 0x2a, 0x41, 0x6c, 0x50, + 0x09, 0x36, 0x0d, 0x5f, 0x4b, 0xe5, 0x6d, 0x04, 0x1c, 0x11, 0x3e, 0xf4, 0x2c, 0x6c, 0xac, 0x50, 0x3c, 0x1b, 0xb3, + 0x31, 0x2b, 0xd4, 0xce, 0x93, 0xcb, 0xa9, 0xd8, 0x59, 0x8c, 0x75, 0x13, 0x59, 0x26, 0x5e, 0x48, 0xd0, 0x71, 0xce, + 0x85, 0x44, 0x5d, 0xfd, 0xdc, 0x7b, 0x49, 0xc6, 0x92, 0x79, 0x43, 0xa3, 0x06, 0xf3, 0xb2, 0xeb, 0x00, 0xa6, 0x25, + 0xdf, 0x16, 0x34, 0x98, 0x4e, 0x95, 0x47, 0xa4, 0x49, 0x50, 0x3b, 0x97, 0x49, 0x91, 0x13, 0xc2, 0x24, 0xe8, 0x95, + 0xe0, 0x37, 0x12, 0xda, 0xff, 0xab, 0x9e, 0xef, 0x80, 0xc1, 0x44, 0xab, 0xe4, 0x0b, 0x58, 0x2d, 0x73, 0xfe, 0x52, + 0x7a, 0x62, 0x23, 0xfe, 0x62, 0x99, 0xc6, 0xa3, 0x2f, 0x6c, 0x88, 0x78, 0x56, 0x2f, 0xd1, 0xb4, 0x04, 0x75, 0x80, + 0x47, 0xf4, 0xd7, 0xe8, 0x8b, 0xe1, 0x4d, 0xe9, 0x6a, 0xa4, 0xae, 0xd9, 0x39, 0xe7, 0x5f, 0x6a, 0x43, 0x84, 0x8c, + 0x69, 0x53, 0x20, 0x19, 0x10, 0x48, 0x32, 0x10, 0x00, 0x98, 0x9a, 0xce, 0xec, 0x15, 0x40, 0x34, 0x10, 0xc0, 0xe3, + 0xbc, 0xe3, 0xf1, 0x23, 0xfd, 0x55, 0x1c, 0xf7, 0x4e, 0xd3, 0xb0, 0xfd, 0x17, 0xa0, 0x29, 0x86, 0x72, 0x3c, 0xdf, + 0x29, 0x48, 0xf6, 0x28, 0x65, 0xe9, 0xaa, 0x89, 0xec, 0x50, 0xac, 0x4f, 0x73, 0xca, 0x42, 0xda, 0x96, 0x63, 0xb4, + 0xc5, 0xfa, 0x31, 0xf2, 0xde, 0xdc, 0xa8, 0xc8, 0x07, 0x3d, 0xb8, 0xbd, 0xbd, 0x7d, 0xdd, 0x63, 0x36, 0xc9, 0x8a, + 0x45, 0xae, 0x22, 0x4e, 0x9c, 0xd6, 0x21, 0x07, 0x0c, 0xc8, 0x49, 0x08, 0x4c, 0x63, 0x5c, 0x2a, 0xd0, 0x41, 0xc9, + 0x72, 0x5e, 0x03, 0xb5, 0x2c, 0x22, 0x6b, 0x80, 0xa8, 0xa6, 0xf9, 0x57, 0x0d, 0xf9, 0x49, 0xd5, 0x9c, 0x52, 0xa8, + 0x7d, 0xc5, 0xc3, 0xea, 0xf4, 0x89, 0x55, 0x9b, 0x18, 0xeb, 0x5f, 0x6b, 0x4f, 0xd0, 0x56, 0xd2, 0x40, 0x7c, 0xe7, + 0xeb, 0xf4, 0x8e, 0x42, 0x77, 0x9c, 0x99, 0x78, 0xaa, 0x02, 0x63, 0xdf, 0xda, 0x11, 0x14, 0x0e, 0x4d, 0xd7, 0x01, + 0x87, 0x69, 0x74, 0xc2, 0xe2, 0x9f, 0xd2, 0x71, 0xf2, 0xa2, 0x56, 0x88, 0x24, 0xff, 0x10, 0x2e, 0x0c, 0x89, 0x05, + 0x79, 0x49, 0xa8, 0x23, 0x32, 0x62, 0x35, 0x2a, 0xd6, 0x42, 0x45, 0xc5, 0x29, 0x1e, 0x6f, 0x15, 0x14, 0x97, 0xa2, + 0x54, 0x29, 0x15, 0xb9, 0x51, 0x29, 0x20, 0x96, 0x0d, 0xbc, 0x5b, 0xc0, 0x01, 0x10, 0x74, 0x96, 0xbb, 0xb5, 0xed, + 0x6e, 0x23, 0xf3, 0x99, 0x69, 0x9e, 0x56, 0x1f, 0xd4, 0xdf, 0xef, 0x97, 0x18, 0x5b, 0xe3, 0xe9, 0xef, 0xdb, 0xb4, + 0xe0, 0xe6, 0x6f, 0x18, 0xa2, 0x3b, 0x40, 0xc4, 0x2c, 0xed, 0xa1, 0x90, 0x05, 0x13, 0x96, 0xa1, 0x2a, 0x4f, 0x39, + 0xea, 0xe5, 0x93, 0x5b, 0x80, 0x50, 0x43, 0xbf, 0x36, 0x3a, 0xd5, 0x55, 0x09, 0xc2, 0xf7, 0x5d, 0xa1, 0x1e, 0x9b, + 0x03, 0x9e, 0x0c, 0x80, 0xbf, 0x22, 0xaf, 0xf5, 0xd8, 0xfe, 0x41, 0x6f, 0xd4, 0x1b, 0x20, 0x88, 0xce, 0x79, 0xe1, + 0x1f, 0x71, 0xae, 0x53, 0x7f, 0xc6, 0x85, 0x20, 0xbe, 0xf5, 0x24, 0xbc, 0x17, 0x67, 0x69, 0x1c, 0x9c, 0xf5, 0x06, + 0xe6, 0x22, 0x50, 0x9c, 0xa5, 0xf9, 0x19, 0x88, 0xe5, 0x88, 0x89, 0x58, 0xb3, 0x3b, 0x80, 0x09, 0x2c, 0x75, 0x1c, + 0xb2, 0xea, 0xd8, 0x7e, 0xff, 0xcd, 0xc8, 0x90, 0xa5, 0x23, 0x0c, 0x8c, 0xfe, 0x5d, 0x81, 0x00, 0x05, 0xcb, 0xcc, + 0xf6, 0x60, 0xd2, 0xd5, 0x9e, 0xd5, 0xf3, 0x66, 0x93, 0x77, 0xf5, 0x8e, 0xd5, 0xb4, 0x9c, 0x9a, 0x56, 0x59, 0x4d, + 0x9b, 0xe4, 0x50, 0x33, 0xd1, 0xef, 0x6b, 0x50, 0xd4, 0x7c, 0x0e, 0x60, 0x6c, 0x98, 0xfc, 0x66, 0x56, 0xcd, 0xfb, + 0x7d, 0x4f, 0x3e, 0x82, 0x5f, 0xc8, 0x56, 0xe6, 0xd6, 0x58, 0x3e, 0x7d, 0x4d, 0x24, 0x66, 0x06, 0xe6, 0xe8, 0xee, + 0x08, 0xdf, 0xeb, 0x46, 0x78, 0x1d, 0x73, 0x85, 0xcd, 0xc4, 0xf4, 0x0d, 0x0c, 0x9e, 0x27, 0x7c, 0x70, 0x91, 0xa3, + 0xbf, 0x91, 0xc3, 0x4c, 0x61, 0x41, 0xce, 0xfd, 0xc9, 0x1b, 0xc4, 0x4b, 0x46, 0x78, 0x07, 0x9d, 0x4e, 0x78, 0x90, + 0xfd, 0xfe, 0x0a, 0x3a, 0xb3, 0x95, 0x4a, 0xd9, 0xaa, 0xa8, 0x4c, 0xd7, 0x75, 0x51, 0x56, 0xd0, 0xb1, 0xf4, 0xf3, + 0x56, 0xc8, 0xcc, 0xfa, 0x99, 0x05, 0xf7, 0xb4, 0x92, 0x00, 0x53, 0xb6, 0x6d, 0xa2, 0x36, 0xf0, 0xb2, 0x2e, 0x3e, + 0x17, 0x78, 0x74, 0xd6, 0x5e, 0x6f, 0x84, 0xda, 0xe7, 0x7c, 0xb4, 0x2e, 0xd6, 0x1e, 0xf8, 0xc1, 0xcc, 0xd2, 0xb9, + 0x22, 0xce, 0xc8, 0xfd, 0xd1, 0xe7, 0x22, 0xcd, 0x29, 0x0f, 0x70, 0x1f, 0x8a, 0xb9, 0xfd, 0x16, 0x48, 0x3f, 0xf4, + 0x16, 0xc8, 0x3e, 0x3a, 0xe7, 0xe4, 0x0d, 0x20, 0xd2, 0x21, 0x0c, 0x6e, 0x45, 0x82, 0x8e, 0x55, 0xc3, 0x5b, 0x0b, + 0xec, 0xb4, 0x97, 0xc6, 0xbd, 0x34, 0x3f, 0x4b, 0xfb, 0x7d, 0x83, 0x9a, 0x99, 0x22, 0x1c, 0x3c, 0xce, 0xc8, 0x45, + 0xd2, 0x82, 0x2d, 0xa5, 0xfd, 0x57, 0x03, 0x47, 0x10, 0xf2, 0xf7, 0x3f, 0x84, 0xf7, 0x04, 0x20, 0x36, 0x69, 0x03, + 0xae, 0x7a, 0x4c, 0x47, 0x63, 0x4b, 0xa2, 0x56, 0x9d, 0x0d, 0x90, 0x38, 0x55, 0x5a, 0x4f, 0xb9, 0x59, 0x53, 0x18, + 0xa4, 0xca, 0x42, 0xfd, 0xc6, 0x7a, 0x32, 0x59, 0xe5, 0x22, 0x23, 0x8e, 0xca, 0xf4, 0xa5, 0x66, 0x04, 0xd3, 0xa5, + 0x9f, 0x2f, 0x60, 0xc9, 0xc6, 0x1f, 0x71, 0xf2, 0x96, 0x80, 0x63, 0x3b, 0x6b, 0x57, 0xd5, 0x2e, 0xc7, 0xad, 0xdd, + 0x1c, 0xe0, 0x7b, 0xbd, 0xd1, 0x68, 0xa4, 0x9d, 0xe3, 0x04, 0x0c, 0x55, 0x4f, 0x2d, 0x85, 0x1e, 0xab, 0x15, 0xa0, + 0x6e, 0x47, 0x2e, 0xb3, 0x64, 0x30, 0x5f, 0x18, 0xc7, 0xaf, 0xcc, 0x47, 0x1f, 0x2f, 0x95, 0xb5, 0xeb, 0x88, 0xaf, + 0xff, 0x20, 0xab, 0xf5, 0x2d, 0xef, 0xaa, 0x26, 0xe0, 0x8b, 0x2a, 0xa0, 0xf4, 0x1b, 0xde, 0x93, 0xbd, 0x8b, 0xaf, + 0xdd, 0x60, 0x97, 0x7c, 0xcb, 0x5b, 0xd4, 0x79, 0xbe, 0x72, 0x70, 0xa3, 0x4a, 0xb7, 0xf7, 0x92, 0x05, 0xae, 0xbd, + 0xa3, 0xa6, 0xb1, 0x9e, 0xf9, 0xd1, 0xc3, 0x22, 0x64, 0x3b, 0x1f, 0x7b, 0x5f, 0x35, 0x4f, 0xcf, 0x1a, 0x7a, 0x93, + 0x1a, 0xfa, 0xd8, 0x8b, 0xb2, 0x7d, 0x6a, 0x1a, 0xd1, 0x6b, 0xd8, 0xd0, 0xc7, 0xde, 0x92, 0x93, 0x43, 0x22, 0xc0, + 0xa9, 0x31, 0x7f, 0x7c, 0x38, 0x9d, 0xe1, 0xef, 0x18, 0x50, 0x09, 0xc4, 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, 0x24, 0x77, 0xa5, 0x37, 0xb0, 0x02, 0x69, 0x5b, 0x54, 0x1f, 0xca, + 0xa5, 0xb7, 0x53, 0x87, 0x76, 0xe5, 0x4f, 0xf2, 0xc3, 0xa1, 0x18, 0x99, 0x63, 0x1c, 0xc0, 0x4d, 0x0a, 0x25, 0x47, + 0xc9, 0x5a, 0x82, 0xe8, 0x94, 0xc6, 0x53, 0x59, 0xaf, 0xad, 0x88, 0xbc, 0x1a, 0x71, 0x1e, 0x82, 0x1f, 0x3d, 0x50, + 0x8b, 0xbf, 0xd0, 0x82, 0xd8, 0x63, 0x9f, 0x2a, 0xa5, 0x17, 0xbc, 0x2a, 0x20, 0x44, 0xec, 0xef, 0x06, 0xda, 0x41, + 0x09, 0x0e, 0x25, 0xdc, 0x07, 0x84, 0x85, 0x7e, 0xed, 0xe5, 0x33, 0x19, 0xa3, 0xdc, 0x1b, 0x54, 0x73, 0x06, 0x30, + 0x95, 0x3e, 0x03, 0xbf, 0x4b, 0x80, 0x3a, 0xc5, 0xa7, 0xe8, 0x54, 0x6f, 0x1e, 0x36, 0x5d, 0x9f, 0x96, 0x28, 0x8a, + 0xe8, 0xce, 0xcf, 0xc7, 0x80, 0xd8, 0xd9, 0xb5, 0x19, 0x69, 0xd7, 0x7e, 0x83, 0x06, 0x2b, 0x25, 0x89, 0x76, 0x4e, + 0x09, 0xbb, 0x9d, 0x8f, 0x6c, 0xe9, 0x47, 0x29, 0x10, 0x73, 0xc7, 0x89, 0x44, 0xf6, 0x60, 0x23, 0x27, 0x70, 0x8b, + 0xf6, 0x8e, 0x0e, 0x40, 0xe5, 0x46, 0x41, 0x7e, 0x35, 0x47, 0x72, 0xc7, 0x77, 0xbd, 0xef, 0x06, 0xf5, 0xe0, 0xbb, + 0xde, 0x59, 0x4a, 0x72, 0x47, 0x78, 0xa6, 0xa6, 0x84, 0x88, 0xcf, 0xbe, 0x1b, 0xe4, 0x03, 0x3c, 0x4b, 0xb4, 0x48, + 0x8b, 0x84, 0x6a, 0x75, 0x8d, 0x9b, 0xf0, 0x22, 0x91, 0xdc, 0x43, 0xbb, 0xce, 0x23, 0x62, 0x01, 0xc8, 0x58, 0x7c, + 0x36, 0x6f, 0x28, 0xd4, 0xdd, 0xc4, 0x6c, 0xd1, 0x5d, 0x16, 0xfb, 0xfd, 0x6d, 0x9e, 0xd6, 0x3d, 0x1d, 0x1f, 0x83, + 0x2f, 0x48, 0x35, 0x01, 0x1e, 0xed, 0xaf, 0xcd, 0xf1, 0xea, 0xd5, 0xe6, 0x48, 0x59, 0xa8, 0x12, 0xf5, 0x5b, 0xac, + 0x66, 0x3d, 0x84, 0xe1, 0xce, 0x32, 0x63, 0x6d, 0x2f, 0x78, 0x25, 0x67, 0x55, 0x6c, 0x97, 0xe3, 0x2b, 0x96, 0xda, + 0x4a, 0xa2, 0x72, 0xb4, 0x1e, 0x6b, 0x53, 0x8c, 0xfc, 0x4a, 0x21, 0x51, 0x16, 0x1d, 0x5b, 0x0b, 0x05, 0xc4, 0x0b, + 0xd0, 0x97, 0xec, 0x4c, 0x03, 0xac, 0x37, 0x7a, 0x15, 0x11, 0x5a, 0x3e, 0x52, 0xe1, 0x4d, 0x6e, 0xaa, 0xcc, 0xca, + 0x66, 0xd1, 0xee, 0xa7, 0x8a, 0x57, 0x08, 0x56, 0x6f, 0xd4, 0x1e, 0x05, 0xa8, 0x3d, 0xb4, 0x50, 0x06, 0x90, 0xd2, + 0x34, 0x03, 0x40, 0x06, 0x00, 0x99, 0x2a, 0xe2, 0x33, 0x01, 0x2a, 0x6d, 0x75, 0xa3, 0xc0, 0x89, 0xf4, 0x1a, 0x68, + 0x16, 0x58, 0xe9, 0x23, 0x05, 0x19, 0x2c, 0xb6, 0x08, 0xc0, 0xca, 0x91, 0x33, 0x4c, 0x63, 0xc8, 0x36, 0x9a, 0xb8, + 0x24, 0xcd, 0xef, 0xc3, 0x2c, 0x95, 0x78, 0x12, 0x3f, 0xc8, 0x1a, 0x23, 0x00, 0x90, 0xbe, 0x4f, 0x2f, 0x8a, 0x2c, + 0x26, 0x1c, 0x38, 0xeb, 0xa9, 0x83, 0xa2, 0x26, 0xe7, 0x5a, 0xd3, 0xea, 0x59, 0x6d, 0xf2, 0x90, 0x05, 0x3a, 0x7b, + 0x30, 0x26, 0xb5, 0x7c, 0xcf, 0x23, 0xfb, 0x2b, 0xc7, 0x33, 0xc2, 0x77, 0xdd, 0xc1, 0xa9, 0xff, 0x6e, 0x6a, 0x60, + 0x62, 0x4a, 0x00, 0x36, 0x06, 0x47, 0x13, 0xe2, 0x77, 0x3a, 0x26, 0x53, 0x9b, 0x14, 0x81, 0xc0, 0x43, 0xf0, 0x0a, + 0x9e, 0x1b, 0x2e, 0xb7, 0xdc, 0xd8, 0x59, 0xe4, 0x69, 0x02, 0x70, 0xe2, 0x05, 0xdf, 0x02, 0x1c, 0xa7, 0x5e, 0x15, + 0xb2, 0x67, 0xcf, 0xc5, 0x74, 0x36, 0x0f, 0x1e, 0x12, 0xda, 0xbf, 0x98, 0xf0, 0x9b, 0xee, 0x2a, 0xb9, 0x32, 0xb5, + 0xee, 0x4d, 0x74, 0x95, 0xcb, 0x9d, 0x3e, 0xad, 0x38, 0x86, 0x39, 0x83, 0x55, 0x40, 0xce, 0xd9, 0x90, 0xbf, 0x38, + 0x07, 0xc0, 0x96, 0x95, 0xf0, 0x22, 0xfe, 0x22, 0x94, 0xd5, 0x02, 0xb8, 0x47, 0xce, 0x23, 0xf3, 0xcb, 0x57, 0xdb, + 0xa1, 0x9c, 0x53, 0x14, 0xc6, 0x72, 0x6a, 0x5a, 0x52, 0x9c, 0x0e, 0x3d, 0x05, 0x93, 0xa9, 0x2d, 0x7f, 0x6f, 0x13, + 0x97, 0xd9, 0x9b, 0x49, 0x38, 0x5f, 0x47, 0xb6, 0xad, 0x55, 0xf7, 0xd0, 0x0d, 0xc1, 0xa0, 0x8f, 0x11, 0xb4, 0x6c, + 0xae, 0xef, 0xd6, 0x83, 0x81, 0xc2, 0xf6, 0xad, 0xe9, 0xa6, 0x45, 0xa7, 0x38, 0xe0, 0xcc, 0x5a, 0xd7, 0xa8, 0x54, + 0x15, 0x87, 0x5e, 0xf2, 0x6e, 0x59, 0x95, 0x5d, 0x96, 0x5e, 0x08, 0x52, 0xa3, 0xae, 0x22, 0x44, 0x4a, 0xc5, 0x0e, + 0xef, 0xc9, 0xaf, 0x81, 0x89, 0x67, 0x56, 0x8e, 0xd2, 0x78, 0x0e, 0x30, 0x41, 0x0a, 0x7d, 0x53, 0x7e, 0x05, 0xb8, + 0xa1, 0x8b, 0x28, 0xcc, 0xde, 0xc6, 0x55, 0x50, 0x5b, 0x4d, 0xbf, 0x77, 0x70, 0x62, 0xcf, 0xeb, 0x7e, 0x3f, 0x25, + 0x1a, 0x3f, 0x0c, 0xbd, 0xc0, 0xbf, 0xc7, 0xd3, 0x7d, 0x13, 0xa4, 0xe6, 0x95, 0x07, 0x78, 0x45, 0x97, 0x5b, 0x9b, + 0x72, 0x45, 0xe3, 0x62, 0x5e, 0x23, 0x22, 0x7c, 0xea, 0x28, 0xb6, 0xdb, 0xfc, 0x38, 0xb5, 0x31, 0x18, 0x84, 0x70, + 0xdf, 0xca, 0xf8, 0x7d, 0xe2, 0xe5, 0xb3, 0x68, 0x0e, 0x8a, 0xd2, 0x4c, 0x93, 0x84, 0x14, 0xd2, 0x4b, 0x80, 0x3e, + 0x1a, 0x84, 0x5a, 0x5d, 0xf9, 0x47, 0xe2, 0xa5, 0x6a, 0x5a, 0x9b, 0xa7, 0x58, 0xa3, 0x40, 0xcc, 0xa2, 0x79, 0xc3, + 0x32, 0x3a, 0x24, 0xd5, 0xe5, 0xd2, 0x34, 0xe3, 0x0f, 0xab, 0x19, 0xaa, 0x15, 0x47, 0x4d, 0x50, 0xa3, 0x74, 0x03, + 0x17, 0xc0, 0xbf, 0xd3, 0x1d, 0x47, 0x35, 0x8a, 0x14, 0x0d, 0xf8, 0x04, 0x81, 0x61, 0xcd, 0xe6, 0x09, 0x6b, 0x4d, + 0x5d, 0x33, 0xfa, 0x7d, 0x19, 0x27, 0x64, 0x92, 0x90, 0x9c, 0x0f, 0x97, 0xeb, 0x47, 0x52, 0x5d, 0x00, 0xa9, 0x72, + 0xc5, 0x66, 0xbd, 0xde, 0x1c, 0x30, 0x7a, 0x61, 0xfd, 0xc2, 0xc6, 0x15, 0x9c, 0x5f, 0x12, 0xe6, 0xae, 0xfa, 0x11, + 0x66, 0x19, 0x54, 0x01, 0x69, 0x7e, 0x2c, 0x78, 0xf3, 0xdc, 0x05, 0xa2, 0x7e, 0x33, 0x52, 0x17, 0x94, 0x59, 0x3a, + 0xb7, 0x88, 0x40, 0xc0, 0x6b, 0x58, 0x3d, 0x81, 0x64, 0x5f, 0x3e, 0xf6, 0x69, 0x46, 0x81, 0xea, 0x08, 0x40, 0xd9, + 0xac, 0x1f, 0xc2, 0xfe, 0x01, 0xe1, 0x84, 0xfa, 0x9b, 0x37, 0x72, 0xd6, 0x90, 0x3c, 0x90, 0x6a, 0xc2, 0x63, 0x38, + 0x35, 0x16, 0xf8, 0xd2, 0xa2, 0x37, 0x15, 0xbc, 0x26, 0x38, 0xee, 0x05, 0x5a, 0xfb, 0x16, 0x70, 0x84, 0x08, 0x2e, + 0x43, 0x13, 0xa7, 0xbd, 0x5d, 0x2f, 0x40, 0x42, 0x73, 0x0b, 0xe7, 0xfa, 0xda, 0x05, 0x2d, 0x4e, 0x91, 0x93, 0x45, + 0x17, 0x18, 0xe8, 0x82, 0xcc, 0x1b, 0xff, 0xaa, 0x60, 0xe5, 0x02, 0x64, 0x2f, 0x15, 0x2b, 0x89, 0xd8, 0x76, 0xea, + 0x8f, 0x52, 0xd9, 0x6f, 0xcf, 0xac, 0x09, 0xfc, 0x2a, 0xb1, 0x5f, 0x22, 0x93, 0x6f, 0x7a, 0x6c, 0xf2, 0x95, 0xb1, + 0xd0, 0xa9, 0x65, 0x70, 0x4e, 0x8f, 0x0c, 0xce, 0xbd, 0x9d, 0x55, 0x9b, 0x10, 0x86, 0x82, 0x24, 0xd0, 0x74, 0xe9, + 0x61, 0xdd, 0xf4, 0xe7, 0x27, 0x2d, 0x7e, 0xad, 0xda, 0xb7, 0xee, 0xc7, 0x21, 0x76, 0xf1, 0xab, 0xc4, 0x33, 0xec, + 0xa3, 0x3e, 0x70, 0x80, 0xc9, 0x88, 0x89, 0xcb, 0x7e, 0x1f, 0x0a, 0x9b, 0x8d, 0xe7, 0xa3, 0xba, 0xf8, 0xb9, 0x78, + 0x00, 0x28, 0x87, 0x0a, 0xec, 0x72, 0x28, 0x43, 0x19, 0xb1, 0xa9, 0x2d, 0xf7, 0xfc, 0xfe, 0x2a, 0xcc, 0x41, 0xde, + 0xd1, 0x98, 0x38, 0x67, 0x20, 0x86, 0xc1, 0xd7, 0xbf, 0x7b, 0xb2, 0x4f, 0x9b, 0xef, 0xce, 0xe0, 0xbb, 0xa3, 0xb3, + 0x0f, 0xc8, 0x71, 0x73, 0xb6, 0x2e, 0x8b, 0xfb, 0x34, 0x16, 0x67, 0xdf, 0x41, 0xea, 0x77, 0x67, 0x45, 0x79, 0xf6, + 0x9d, 0xaa, 0xcc, 0x77, 0x67, 0xb4, 0xe0, 0x46, 0xbf, 0x5b, 0x13, 0xef, 0x9f, 0x95, 0xa6, 0x3d, 0x5b, 0x42, 0x38, + 0x96, 0x56, 0x3f, 0x82, 0x12, 0x51, 0x91, 0xa2, 0xca, 0x50, 0x56, 0x6b, 0xc7, 0x79, 0x9f, 0x68, 0x78, 0x6c, 0x9a, + 0x90, 0xb8, 0x5a, 0xc2, 0x3a, 0xd4, 0xb3, 0xd3, 0x26, 0xd9, 0x71, 0x1e, 0xa8, 0x03, 0x22, 0xe7, 0x2f, 0xf2, 0xd1, + 0x96, 0xbe, 0x06, 0xdf, 0x3a, 0x1c, 0xf2, 0xd1, 0xce, 0xfc, 0xf4, 0xc9, 0x5a, 0x29, 0x83, 0x8d, 0x14, 0xa3, 0x10, + 0x12, 0xc5, 0x6d, 0x7b, 0x0c, 0x80, 0xff, 0xfd, 0xc3, 0x81, 0x7e, 0xef, 0xe4, 0x6f, 0xb5, 0x5b, 0x5a, 0xf5, 0xfc, + 0xd0, 0x22, 0xcc, 0x78, 0x5d, 0x1b, 0x76, 0xb6, 0xbd, 0x04, 0x94, 0xde, 0x37, 0x0d, 0x6a, 0x8a, 0xe8, 0x27, 0xac, + 0x26, 0x56, 0x71, 0x58, 0x90, 0x12, 0x87, 0x18, 0x8e, 0xd1, 0x0e, 0x3d, 0x4e, 0x17, 0x35, 0x4f, 0xee, 0x3b, 0x64, + 0xdc, 0xfa, 0x3e, 0x20, 0xb9, 0x14, 0xce, 0x3f, 0x78, 0xa1, 0xc1, 0x44, 0x2f, 0xf2, 0xaa, 0xc8, 0xc4, 0x48, 0xd0, + 0x28, 0xbf, 0x25, 0x71, 0xe6, 0x0c, 0x6b, 0x71, 0xa6, 0x10, 0xc2, 0x42, 0x42, 0xe5, 0x2e, 0x4a, 0x4a, 0x0f, 0xce, + 0x9e, 0xec, 0xcb, 0xe6, 0x77, 0xc2, 0x84, 0x18, 0x2d, 0x80, 0x06, 0x67, 0xd7, 0x2e, 0xef, 0x21, 0x2c, 0x73, 0xef, + 0xf7, 0xb7, 0x77, 0x79, 0x01, 0x71, 0x99, 0x67, 0x52, 0xb1, 0x5a, 0x9e, 0x01, 0x4d, 0x9e, 0x88, 0xcf, 0xc2, 0x4a, + 0x4e, 0x83, 0xaa, 0xa3, 0x58, 0xbd, 0x8d, 0xe7, 0x1e, 0xf0, 0x7a, 0xbf, 0x4f, 0x80, 0xc0, 0xdd, 0x67, 0x6f, 0x94, + 0x5b, 0x2a, 0xe9, 0x91, 0xe7, 0x18, 0x22, 0x99, 0x00, 0xaf, 0x33, 0x04, 0x47, 0x0a, 0xab, 0xe7, 0x26, 0xc8, 0x3f, + 0xbe, 0x3e, 0xa1, 0xf8, 0xa2, 0x79, 0x14, 0x35, 0x2c, 0x64, 0x09, 0x1c, 0x0f, 0xc9, 0x2c, 0x9b, 0x23, 0x35, 0x79, + 0xda, 0x9e, 0x22, 0x1d, 0x9d, 0x58, 0xe2, 0xb7, 0x35, 0xa9, 0x5e, 0xa4, 0xc2, 0x2e, 0x69, 0x67, 0x2b, 0x73, 0x2f, + 0x84, 0xa1, 0x4a, 0xb8, 0xf7, 0xba, 0x9e, 0x85, 0x72, 0x53, 0xb4, 0x2a, 0x66, 0x0f, 0x53, 0x62, 0x86, 0x29, 0xd6, + 0x5f, 0xd8, 0xf0, 0x9b, 0xc4, 0x8b, 0xc1, 0x70, 0xbd, 0xe4, 0xe5, 0x6c, 0x63, 0x16, 0xc2, 0xe1, 0xb0, 0x99, 0x14, + 0xb3, 0x25, 0xc4, 0xb6, 0x2e, 0xe7, 0x87, 0x43, 0x57, 0xcb, 0xd6, 0xc2, 0x83, 0x87, 0xaa, 0x85, 0x9b, 0x86, 0xe5, + 0xf0, 0x33, 0x99, 0xc5, 0xd8, 0xbe, 0xc6, 0x67, 0xf6, 0xe7, 0x8b, 0xee, 0x59, 0x82, 0x8c, 0x1b, 0x6b, 0xe0, 0x1a, + 0x9b, 0xb5, 0x3b, 0x5c, 0x8d, 0x80, 0xe4, 0x71, 0x37, 0xfa, 0xbb, 0xb2, 0x93, 0x9c, 0x04, 0x09, 0xa3, 0x15, 0xc2, + 0xef, 0xbe, 0xf1, 0x27, 0x5a, 0xec, 0x41, 0xbb, 0x8d, 0x2d, 0x21, 0xaa, 0x69, 0xcf, 0xe5, 0x4a, 0xb1, 0x34, 0x6f, + 0xa5, 0x0d, 0x99, 0x0f, 0xeb, 0x73, 0xdf, 0xc8, 0x81, 0x82, 0x31, 0xe2, 0xa9, 0x75, 0x10, 0xcd, 0xe6, 0xc0, 0x7d, + 0x81, 0xe6, 0x11, 0x9e, 0x5a, 0x90, 0xa0, 0xcc, 0xda, 0xb0, 0x9f, 0x24, 0x27, 0xcb, 0xe3, 0xf0, 0x2d, 0xfc, 0xcb, + 0x67, 0xd8, 0x24, 0xa6, 0x28, 0x1e, 0x7f, 0xab, 0x14, 0xff, 0x1d, 0x5b, 0x10, 0xc1, 0xda, 0x8d, 0xa8, 0x0d, 0x7f, + 0xc3, 0xbf, 0x85, 0x7d, 0x84, 0xfd, 0x86, 0x26, 0x08, 0x03, 0x58, 0x7f, 0x26, 0x10, 0x17, 0x16, 0x82, 0x04, 0x7f, + 0xab, 0x24, 0xff, 0x9c, 0xf0, 0xd9, 0xa2, 0x04, 0xb2, 0x3a, 0x8c, 0xe2, 0x13, 0x8a, 0x89, 0x42, 0x18, 0x6e, 0x09, + 0xbd, 0xa3, 0xff, 0x46, 0x94, 0x64, 0x93, 0xdc, 0x8a, 0xf5, 0x40, 0x26, 0x49, 0x30, 0xc1, 0xca, 0x0b, 0xe5, 0x4b, + 0xf7, 0x42, 0xa9, 0xb5, 0x16, 0xb4, 0x7e, 0xf9, 0x93, 0xc4, 0x33, 0xa0, 0x7b, 0x20, 0x63, 0xd0, 0x6d, 0x44, 0x35, + 0xc9, 0x31, 0x7d, 0x94, 0xce, 0x33, 0x50, 0x01, 0x9d, 0xad, 0xb3, 0xb0, 0x5e, 0x16, 0xe5, 0xaa, 0x15, 0x1e, 0x2a, + 0x4b, 0x1f, 0xa9, 0xc7, 0x98, 0x17, 0xe6, 0xc9, 0x89, 0x7c, 0xf0, 0x08, 0xd0, 0xf0, 0x28, 0x4f, 0xab, 0x8e, 0xd2, + 0xfa, 0x81, 0x65, 0xc0, 0x08, 0x9c, 0x28, 0x03, 0x1e, 0x61, 0x19, 0x98, 0xa7, 0x5d, 0x86, 0x1a, 0xc4, 0x1a, 0x55, + 0x57, 0x6a, 0x83, 0x39, 0x51, 0x94, 0x7c, 0x8a, 0xa5, 0x15, 0xc6, 0xd0, 0xd4, 0x95, 0x47, 0xd6, 0x4b, 0x4e, 0xd8, + 0x93, 0xdd, 0x40, 0xba, 0x85, 0x8d, 0x02, 0x17, 0x74, 0x2d, 0x4b, 0x94, 0x8b, 0x6e, 0x19, 0x51, 0x26, 0x42, 0xea, + 0x67, 0x0f, 0x67, 0x5a, 0xed, 0x37, 0x76, 0xd2, 0xbe, 0x3d, 0x52, 0xf4, 0x82, 0x81, 0xf8, 0xb4, 0x47, 0x4a, 0x3d, + 0x6b, 0xe4, 0x32, 0xb0, 0xa5, 0x4b, 0x55, 0xcf, 0x7f, 0x83, 0xf2, 0x1d, 0xcc, 0x8c, 0xb3, 0xd9, 0xef, 0x7a, 0x73, + 0x7b, 0xb2, 0xaf, 0x9b, 0xdf, 0x59, 0xaf, 0x07, 0x5b, 0x83, 0x4c, 0x7c, 0xa9, 0xa8, 0xa7, 0xac, 0x42, 0xac, 0xc8, + 0xec, 0x7f, 0x0b, 0xef, 0x77, 0x78, 0x6b, 0x84, 0x66, 0x65, 0x3c, 0xcc, 0x47, 0x4f, 0xf6, 0xa2, 0xf9, 0xbd, 0xb3, + 0x6c, 0x2b, 0x57, 0x25, 0xb3, 0xfd, 0x7e, 0x94, 0x34, 0x67, 0x8f, 0xd7, 0x48, 0xea, 0x00, 0x1f, 0xaf, 0xcf, 0xf0, + 0x91, 0x4a, 0x28, 0xb5, 0xa0, 0xaa, 0x41, 0xeb, 0x63, 0xbf, 0xb7, 0x9e, 0xd3, 0xc7, 0x8f, 0xe5, 0x74, 0x4b, 0x8a, + 0x30, 0x7e, 0x60, 0x30, 0x65, 0x27, 0x4e, 0x5d, 0xf2, 0x66, 0x48, 0xef, 0xba, 0x55, 0x52, 0x97, 0x3d, 0x4a, 0x04, + 0xa1, 0x0e, 0xd6, 0x2f, 0xf6, 0x43, 0x98, 0xd9, 0xa2, 0x3f, 0x6c, 0x56, 0x73, 0x42, 0x41, 0x04, 0x88, 0x56, 0x79, + 0x1f, 0x38, 0x26, 0x09, 0xb3, 0xe6, 0x86, 0x74, 0xeb, 0xcd, 0x95, 0xf6, 0x4a, 0x0a, 0xe8, 0xe7, 0x20, 0x73, 0xfb, + 0xe8, 0x96, 0xab, 0x96, 0x79, 0x2e, 0x6d, 0x39, 0x60, 0xd1, 0x42, 0x74, 0x66, 0xe7, 0xd2, 0xe1, 0xe0, 0x3f, 0xa8, + 0x2b, 0x51, 0x45, 0x04, 0x1d, 0x45, 0x0b, 0x46, 0xab, 0x55, 0xbb, 0x9c, 0x6c, 0x2a, 0x64, 0x4b, 0x22, 0x9c, 0x28, + 0xd9, 0x2b, 0xa1, 0x3e, 0xca, 0xd5, 0x9e, 0x69, 0x88, 0x3f, 0x13, 0xb0, 0x69, 0x83, 0xbf, 0x05, 0xee, 0x65, 0x70, + 0x66, 0xda, 0xa7, 0x61, 0x04, 0x44, 0xe6, 0x10, 0xec, 0xe7, 0x77, 0x3d, 0xa8, 0xe0, 0x41, 0x47, 0xfa, 0xeb, 0x7a, + 0x56, 0xe0, 0x99, 0x7b, 0xe2, 0xf9, 0x9b, 0x13, 0xe9, 0x45, 0x0e, 0x0f, 0x34, 0xf7, 0x61, 0xc6, 0x5f, 0x96, 0x65, + 0xb8, 0x1b, 0x2d, 0xcb, 0x62, 0xe5, 0x45, 0x7a, 0x1f, 0xcf, 0xa4, 0x18, 0x48, 0x74, 0x98, 0x19, 0x5d, 0xc5, 0x3a, + 0xce, 0x61, 0xdc, 0xdb, 0x93, 0xb0, 0x42, 0xfb, 0x67, 0x89, 0xbd, 0x2e, 0x00, 0xc0, 0x21, 0x6b, 0xd0, 0x0a, 0xef, + 0x74, 0x7b, 0xbb, 0xc7, 0x25, 0x25, 0x8a, 0x1b, 0x35, 0x3f, 0xab, 0xa1, 0x65, 0x82, 0x5a, 0x66, 0xdd, 0xc9, 0x64, + 0x8a, 0x24, 0xf0, 0x6d, 0xd8, 0x1b, 0x56, 0xe4, 0xf3, 0x46, 0x6e, 0x0f, 0xef, 0xc2, 0x95, 0x88, 0xb5, 0x05, 0x9d, + 0x74, 0x64, 0x1c, 0xee, 0x85, 0xe6, 0x46, 0xba, 0x7f, 0x52, 0x25, 0x61, 0x29, 0x62, 0xb8, 0x05, 0xb2, 0xbd, 0xda, + 0x56, 0x82, 0x12, 0x48, 0x60, 0x3f, 0x94, 0x62, 0x99, 0x6e, 0x05, 0x80, 0x39, 0xf0, 0x3f, 0x25, 0x0c, 0xa1, 0xbb, + 0xf3, 0x10, 0xaf, 0x1a, 0x79, 0xdf, 0x20, 0x04, 0xfb, 0x6b, 0x90, 0xd3, 0x80, 0x41, 0xa4, 0x18, 0xc9, 0x82, 0x81, + 0x04, 0x20, 0xe7, 0x6b, 0x30, 0xc9, 0x4d, 0x73, 0xcf, 0x0f, 0x72, 0xdd, 0xc1, 0xb4, 0x0f, 0xba, 0x17, 0xd7, 0x9a, + 0xe5, 0xe0, 0x15, 0x13, 0xf1, 0xbf, 0xd7, 0x5e, 0xc9, 0x72, 0x96, 0xf9, 0x8d, 0xb9, 0xe8, 0x64, 0x70, 0xd5, 0x10, + 0x7e, 0x31, 0xcb, 0xe6, 0x3c, 0x9a, 0x65, 0x3a, 0xd4, 0xbf, 0x68, 0x8e, 0x4a, 0x01, 0x0c, 0x75, 0xbc, 0x00, 0x6b, + 0xbc, 0x2b, 0xdd, 0xb4, 0xe2, 0x91, 0xc6, 0x18, 0x05, 0x15, 0x3a, 0x08, 0xfd, 0xbd, 0x06, 0x78, 0x0d, 0x26, 0xb9, + 0x11, 0x2a, 0x1f, 0x5c, 0xd0, 0x0d, 0xdd, 0x72, 0xe5, 0x12, 0xd4, 0xa4, 0x6a, 0xf9, 0xe5, 0x08, 0xf5, 0xae, 0x96, + 0x5c, 0xaa, 0xcd, 0xa7, 0x46, 0x59, 0x23, 0xc8, 0xe4, 0x28, 0xfd, 0x3e, 0xe5, 0xc2, 0xad, 0x8c, 0xc9, 0xfa, 0x70, + 0xf0, 0x0a, 0x6e, 0x6a, 0xfc, 0x3a, 0x27, 0x16, 0x51, 0x7b, 0x48, 0x84, 0xad, 0xdd, 0x0a, 0xdd, 0x7b, 0xdc, 0x28, + 0xcd, 0xa3, 0x6c, 0x13, 0x8b, 0xca, 0xeb, 0x25, 0x60, 0x2d, 0xee, 0x01, 0x19, 0x2a, 0x2d, 0xfd, 0x8a, 0x15, 0x00, + 0x19, 0x20, 0x85, 0x8d, 0x1f, 0x90, 0xf6, 0xea, 0x83, 0x97, 0xfa, 0xfd, 0xbe, 0x31, 0xe5, 0xbf, 0x7f, 0xc8, 0x81, + 0x99, 0x50, 0x94, 0xf5, 0x0e, 0x26, 0x10, 0x5c, 0x3b, 0x49, 0x7b, 0x56, 0xf3, 0x17, 0xeb, 0xda, 0x03, 0x52, 0x2b, + 0xdf, 0x62, 0xae, 0x7a, 0x6d, 0x5f, 0x6c, 0xf6, 0x69, 0x75, 0x63, 0x34, 0x0e, 0x82, 0xa5, 0xd5, 0x5b, 0xad, 0x72, + 0xc8, 0x1b, 0x5e, 0x81, 0x48, 0x65, 0x5d, 0x5d, 0x2b, 0xe7, 0xea, 0x5a, 0x70, 0x24, 0x90, 0x2d, 0x79, 0x0e, 0xff, + 0x85, 0xdc, 0x2b, 0x0f, 0x87, 0xc2, 0xef, 0xf7, 0xd3, 0x19, 0x69, 0x65, 0x81, 0x32, 0x6d, 0x5d, 0x7b, 0xa1, 0x7f, + 0x38, 0xfc, 0x00, 0x5e, 0x23, 0xfe, 0xe1, 0x50, 0xf6, 0xfb, 0x1f, 0xcd, 0x4d, 0xe6, 0x7c, 0xac, 0x94, 0xb2, 0x97, + 0xa8, 0x74, 0x7f, 0x9b, 0xf0, 0xde, 0xff, 0x1e, 0xfd, 0xef, 0xd1, 0x65, 0x4f, 0x05, 0x80, 0x25, 0x7c, 0x86, 0x37, + 0x74, 0xa6, 0x2e, 0xe7, 0x4c, 0xba, 0xbb, 0x2b, 0x3f, 0xf4, 0x9e, 0xc6, 0x87, 0xef, 0xcd, 0x4d, 0x1b, 0x7f, 0xad, + 0x8e, 0x34, 0x09, 0x1d, 0x17, 0xfd, 0xc3, 0xe1, 0x53, 0xa2, 0xf5, 0x69, 0xa9, 0xd2, 0xa7, 0x29, 0xf0, 0x24, 0xc3, + 0x86, 0xeb, 0x16, 0xa6, 0xa3, 0xf9, 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, 0x5b, 0xe5, 0x0a, 0xde, 0xda, + 0xe3, 0xdd, 0x60, 0x44, 0xa9, 0x23, 0x7d, 0xd2, 0x86, 0xd0, 0x25, 0x95, 0xfc, 0x47, 0x91, 0xc7, 0x18, 0xb3, 0xf1, + 0x9a, 0xc8, 0x3e, 0x8b, 0xfc, 0x55, 0x01, 0x80, 0x45, 0x80, 0x80, 0x9c, 0xce, 0x1d, 0x49, 0xfc, 0xe7, 0xe4, 0xdb, + 0x3f, 0xa6, 0x4b, 0xfb, 0x50, 0x16, 0x77, 0xa5, 0xa8, 0xaa, 0xa3, 0xd2, 0x76, 0xb6, 0x5c, 0x0f, 0xf4, 0xa1, 0xfd, + 0xbe, 0xa4, 0x0f, 0x4d, 0x31, 0x14, 0x05, 0x6e, 0x8d, 0xbd, 0x69, 0xca, 0x15, 0x4d, 0xf5, 0xc8, 0x58, 0x3f, 0xbf, + 0xdf, 0xbd, 0x8d, 0xbd, 0xd4, 0x0f, 0x52, 0x10, 0x84, 0x35, 0x7e, 0x52, 0x8a, 0x24, 0x70, 0x3e, 0xc3, 0x54, 0xe2, + 0xd3, 0xa5, 0x54, 0xf9, 0xc3, 0x48, 0xf3, 0x61, 0x0a, 0x7a, 0xd9, 0x7f, 0x54, 0x30, 0xff, 0x75, 0x7b, 0xb0, 0x3e, + 0xad, 0xcb, 0x34, 0xaa, 0x88, 0x2a, 0x2f, 0x4c, 0xb5, 0x09, 0x44, 0xf0, 0x17, 0xc2, 0x22, 0xf9, 0xf5, 0xc9, 0x91, + 0xa0, 0x31, 0x93, 0xe5, 0xe3, 0x91, 0xfb, 0x85, 0x7d, 0xe5, 0x3a, 0x9e, 0xff, 0xb9, 0x99, 0xff, 0x03, 0x74, 0x86, + 0x2c, 0x5e, 0x70, 0xcb, 0x60, 0x81, 0xb3, 0x5f, 0xba, 0x7a, 0xc0, 0xdf, 0xcc, 0x13, 0x2f, 0x80, 0x83, 0xf9, 0x05, + 0xba, 0x2a, 0xa6, 0xb3, 0x62, 0x00, 0x04, 0xb6, 0x7e, 0x63, 0xcd, 0x89, 0x37, 0x16, 0xcf, 0x95, 0x5c, 0x10, 0xfa, + 0xba, 0x0a, 0xb3, 0x71, 0x55, 0x6c, 0x2a, 0x51, 0x6c, 0xea, 0x1e, 0xa9, 0x65, 0xf3, 0x69, 0x6d, 0x2b, 0x64, 0x7f, + 0x12, 0x2d, 0xda, 0x2e, 0x43, 0x35, 0x19, 0x65, 0xe9, 0x7a, 0x0a, 0xa4, 0x7a, 0x01, 0x9c, 0x45, 0xe6, 0x95, 0x2f, + 0xce, 0x1e, 0xb0, 0x45, 0xe3, 0x29, 0x30, 0xa2, 0xd2, 0x1f, 0x79, 0x63, 0x74, 0x7a, 0xa2, 0xdf, 0xcf, 0xa7, 0x14, + 0xf2, 0xf5, 0x13, 0x60, 0x72, 0xd5, 0x72, 0x01, 0xfa, 0x32, 0xd4, 0x41, 0x25, 0x4a, 0xad, 0x18, 0x46, 0x2c, 0xfc, + 0x24, 0x90, 0xbd, 0x99, 0x82, 0x9a, 0x55, 0x94, 0x84, 0x4a, 0x54, 0x4a, 0xb6, 0x26, 0xa8, 0xa5, 0xf7, 0x45, 0x51, + 0xef, 0x2b, 0x70, 0x94, 0x8c, 0xb4, 0x59, 0x4e, 0x99, 0x71, 0x51, 0xe6, 0xa2, 0x1f, 0xec, 0xdf, 0x95, 0xe7, 0x37, + 0x32, 0x9f, 0xe5, 0xbe, 0xa3, 0x73, 0xda, 0x8e, 0x0b, 0x94, 0xb9, 0xe5, 0xb4, 0xd5, 0x92, 0xc7, 0xe4, 0x3d, 0x0b, + 0xb6, 0xfd, 0x97, 0x09, 0xf2, 0x2a, 0xc2, 0x7c, 0x42, 0x95, 0xcd, 0x3f, 0x20, 0xcc, 0x16, 0x07, 0xf6, 0xd8, 0x85, + 0x89, 0x48, 0x6f, 0xc1, 0x92, 0x18, 0x66, 0xa5, 0x08, 0xe3, 0x1d, 0x78, 0xff, 0x6c, 0x2a, 0x31, 0x3a, 0x43, 0x27, + 0xf7, 0xb3, 0x87, 0xb4, 0x4e, 0xce, 0xde, 0xbe, 0x3e, 0xfb, 0xae, 0x37, 0x28, 0x46, 0x69, 0x3c, 0xe8, 0x7d, 0x77, + 0xb6, 0xda, 0x00, 0x44, 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, 0x74, 0x7b, 0x22, 0xed, 0xaa, 0x74, 0x05, 0x84, 0x1e, + 0x00, 0x27, 0x5d, 0xf9, 0xf3, 0x70, 0x10, 0x09, 0x84, 0x5a, 0x30, 0x27, 0xd3, 0x88, 0x6e, 0x48, 0xaf, 0xb0, 0xcf, + 0xc0, 0x2c, 0xa4, 0x34, 0x0f, 0x6e, 0xae, 0x16, 0x2d, 0x77, 0xc5, 0xca, 0x51, 0x58, 0xad, 0x45, 0x54, 0x23, 0xd5, + 0x31, 0x38, 0xef, 0x40, 0x04, 0x80, 0x62, 0x04, 0xcf, 0x78, 0xd4, 0xef, 0x47, 0x2a, 0x28, 0x27, 0xa1, 0x5f, 0x14, + 0xfa, 0xa5, 0x31, 0x28, 0x63, 0xfe, 0x2e, 0xd4, 0xc4, 0x00, 0xf5, 0x96, 0x87, 0x8a, 0x23, 0x00, 0x97, 0x73, 0xc4, + 0x8c, 0xf3, 0x1e, 0x77, 0xd1, 0x38, 0x15, 0xef, 0x84, 0xba, 0x0e, 0x96, 0x0a, 0x75, 0xde, 0xd4, 0x47, 0x7a, 0x4e, + 0x9a, 0x04, 0x0d, 0xe2, 0x06, 0x1e, 0xaf, 0x86, 0x80, 0x6a, 0x25, 0xa4, 0xde, 0x42, 0xa7, 0x54, 0x75, 0x08, 0xac, + 0x01, 0x2e, 0x51, 0xd8, 0x56, 0x98, 0x1c, 0xd1, 0xa6, 0x2c, 0x45, 0x7e, 0xc4, 0x06, 0xed, 0x92, 0x91, 0xa9, 0x83, + 0xcb, 0xe5, 0x72, 0x22, 0xea, 0x5f, 0xf3, 0x2d, 0x80, 0xf3, 0x42, 0x7e, 0x6b, 0x37, 0x5b, 0x26, 0xd9, 0xae, 0x2b, + 0xc3, 0x59, 0x52, 0x8a, 0x6a, 0x5d, 0xe4, 0x55, 0x7a, 0x2f, 0x7e, 0xd6, 0x0f, 0x5d, 0x02, 0x29, 0xf4, 0x23, 0xbd, + 0x6e, 0x37, 0x47, 0xaa, 0x71, 0x74, 0x39, 0xb6, 0xa7, 0xd2, 0x4e, 0xf6, 0xaa, 0xc5, 0x9b, 0x2d, 0x73, 0x25, 0x69, + 0x1c, 0x8b, 0xfc, 0x6d, 0x1e, 0xa7, 0x91, 0x95, 0x1c, 0xfe, 0x1f, 0xde, 0xbe, 0x85, 0xbb, 0x6d, 0x1b, 0x5b, 0xf7, + 0xaf, 0x58, 0xbc, 0xa9, 0x4a, 0x44, 0x90, 0x2c, 0x39, 0x49, 0x67, 0x4a, 0x19, 0xd6, 0x71, 0xf3, 0x68, 0xd3, 0x36, + 0x71, 0x1a, 0xa7, 0x9d, 0xce, 0xe8, 0xea, 0xb8, 0x34, 0x09, 0x5b, 0x6c, 0x68, 0x40, 0x25, 0x29, 0x3f, 0x22, 0xf1, + 0xbf, 0xdf, 0xb5, 0x37, 0x9e, 0xa4, 0x68, 0x27, 0x33, 0xf7, 0xdc, 0xbb, 0xb2, 0x56, 0x2c, 0x82, 0x20, 0xde, 0xd8, + 0xd8, 0xd8, 0x8f, 0x6f, 0xeb, 0x00, 0xd5, 0x2e, 0xf2, 0x95, 0x8b, 0x8d, 0xfc, 0x22, 0x2b, 0x31, 0x60, 0x70, 0xa3, + 0x51, 0xad, 0x50, 0x53, 0x26, 0xf0, 0x85, 0x7c, 0x8f, 0x11, 0xb7, 0x59, 0x99, 0x00, 0xc3, 0x8f, 0x89, 0xfa, 0x92, + 0x9e, 0x42, 0x94, 0x07, 0x15, 0x8f, 0xfb, 0x05, 0x47, 0xc4, 0x6b, 0xab, 0x32, 0x07, 0x26, 0x5b, 0xab, 0x20, 0x11, + 0xec, 0x2e, 0x9b, 0xeb, 0x45, 0xb4, 0x50, 0x77, 0xa1, 0x5e, 0xbc, 0xdd, 0xf6, 0x12, 0x45, 0x07, 0x9c, 0xfc, 0x34, + 0x78, 0x15, 0x67, 0x39, 0x4f, 0xf7, 0x2a, 0xb9, 0xa7, 0x36, 0xd4, 0x9e, 0x72, 0xe6, 0x80, 0x9d, 0xf7, 0x75, 0xb5, + 0xa7, 0xd7, 0xf4, 0x9e, 0x6e, 0xe7, 0x1e, 0x5c, 0x30, 0x70, 0xe7, 0x5e, 0x66, 0xd7, 0x5c, 0xec, 0x81, 0x32, 0xd0, + 0x1a, 0x0f, 0xd4, 0xa2, 0x1a, 0xa9, 0x89, 0xd1, 0x81, 0xab, 0x13, 0x7d, 0x30, 0x07, 0xf4, 0x7b, 0x88, 0x15, 0xde, + 0x7a, 0xbb, 0xd2, 0x07, 0x6d, 0x40, 0x7f, 0x5e, 0x9a, 0x3e, 0xe8, 0x68, 0xf1, 0x2a, 0x24, 0x70, 0x63, 0x48, 0x35, + 0x52, 0xab, 0x91, 0x55, 0xa0, 0x78, 0xc3, 0x5b, 0xbc, 0x3b, 0xd7, 0x92, 0x8d, 0xf7, 0x12, 0x81, 0xbd, 0x32, 0x51, + 0xc5, 0x99, 0x38, 0xf6, 0x52, 0x79, 0xad, 0x9d, 0x64, 0x84, 0xf1, 0x2d, 0x2b, 0xa9, 0xbf, 0x43, 0xcc, 0x2d, 0xd2, + 0x1c, 0x06, 0x2f, 0xc3, 0x8a, 0xcc, 0x78, 0xbf, 0x2f, 0x67, 0x32, 0x2a, 0x67, 0x62, 0xbf, 0x8c, 0x14, 0x42, 0xdb, + 0x7d, 0x22, 0xa0, 0x07, 0x25, 0x40, 0xbe, 0x00, 0xa8, 0x7a, 0x48, 0xf8, 0xf3, 0x90, 0xd4, 0xa7, 0x53, 0xe8, 0x53, + 0x68, 0xeb, 0x15, 0xaf, 0xa0, 0xaa, 0x6e, 0x8c, 0x6c, 0xa3, 0x82, 0x16, 0x8f, 0xe5, 0x59, 0x6d, 0x18, 0x9b, 0x53, + 0xeb, 0x5d, 0x6f, 0x36, 0x98, 0xb2, 0xb9, 0x50, 0xab, 0x30, 0x24, 0xd1, 0x4d, 0xe9, 0x85, 0x0f, 0xb1, 0x58, 0x59, + 0xad, 0xcd, 0x6f, 0x62, 0x7f, 0x64, 0x22, 0xc5, 0xfd, 0x6c, 0x89, 0x73, 0x17, 0x8f, 0xe7, 0x55, 0x5f, 0x6b, 0x69, + 0x91, 0x69, 0xf3, 0x9d, 0xbe, 0x0c, 0x69, 0x2a, 0x6a, 0x48, 0xa3, 0xce, 0x0c, 0xba, 0x6f, 0x97, 0x57, 0x54, 0x23, + 0x4c, 0x80, 0x57, 0x3a, 0x83, 0x6e, 0x34, 0x1e, 0x88, 0xa2, 0x1a, 0x15, 0x6b, 0x21, 0x10, 0x6d, 0x18, 0x72, 0xcc, + 0x2c, 0x21, 0xc9, 0x3e, 0xf1, 0xef, 0x54, 0x70, 0x85, 0x22, 0xbe, 0x31, 0x70, 0xde, 0x95, 0xf5, 0xec, 0xae, 0x23, + 0x3f, 0x27, 0x16, 0x56, 0xfb, 0x0f, 0xcd, 0xa3, 0xd6, 0x38, 0x0b, 0x68, 0x6b, 0x5a, 0xdd, 0x70, 0xb8, 0x47, 0x75, + 0x2c, 0x4a, 0x03, 0x48, 0xec, 0x91, 0xe5, 0xa2, 0x75, 0xcc, 0xa0, 0x01, 0xfd, 0x6d, 0x76, 0xb5, 0xbe, 0x42, 0xd4, + 0xb6, 0x12, 0x59, 0x27, 0xa9, 0xfc, 0x4b, 0xda, 0xa3, 0xae, 0xed, 0xa9, 0xfc, 0x6f, 0xdb, 0x54, 0x39, 0xb4, 0x40, + 0xf2, 0xd8, 0xcd, 0x59, 0xa0, 0x3a, 0x12, 0x44, 0x81, 0xda, 0x7a, 0xc1, 0xd4, 0x3b, 0x65, 0x8a, 0x0e, 0xe4, 0xe7, + 0xc2, 0x9c, 0x61, 0x5f, 0x70, 0xc4, 0x98, 0xa5, 0x12, 0x83, 0xa9, 0x8f, 0x31, 0xaa, 0x69, 0xad, 0x00, 0x5d, 0x3f, + 0xdd, 0xc0, 0x9f, 0xa8, 0xa8, 0xd1, 0x50, 0x6b, 0x24, 0x85, 0xa2, 0x89, 0x0a, 0x3a, 0x96, 0x16, 0x3a, 0x98, 0x42, + 0x27, 0x91, 0xb0, 0x04, 0x34, 0x4c, 0x88, 0x4e, 0x2a, 0xf0, 0xd6, 0x00, 0xce, 0x7c, 0x5c, 0x94, 0xeb, 0x42, 0x1b, + 0xcc, 0xfd, 0x10, 0x5f, 0xf3, 0xd7, 0x2f, 0x9c, 0x51, 0x7d, 0xcb, 0x5a, 0xdf, 0xd3, 0x82, 0xfc, 0x10, 0x72, 0x8a, + 0x0e, 0x4c, 0xec, 0x68, 0x83, 0xc6, 0x18, 0x65, 0xad, 0x43, 0x5d, 0x9c, 0xe8, 0xf8, 0x2b, 0xda, 0x04, 0xef, 0x01, + 0x4f, 0x11, 0x6d, 0x78, 0x28, 0x8c, 0x55, 0x35, 0x3e, 0x95, 0xac, 0xa5, 0x07, 0x2b, 0x78, 0xba, 0x4e, 0x78, 0x08, + 0x7a, 0x24, 0xc2, 0x8e, 0xc2, 0x62, 0x1e, 0x2f, 0xe0, 0x38, 0x29, 0x08, 0xa8, 0x1d, 0xf4, 0x15, 0x7c, 0xbe, 0x40, + 0xf7, 0x57, 0x89, 0x1e, 0x60, 0x68, 0x41, 0xdc, 0x0c, 0x7d, 0x3a, 0xba, 0x8a, 0x57, 0x0d, 0x15, 0x09, 0x9f, 0x17, + 0x60, 0x3b, 0xa4, 0xd4, 0x53, 0xa0, 0x85, 0x4a, 0x94, 0x7e, 0x18, 0xf8, 0x0e, 0x0d, 0x7c, 0xad, 0x75, 0x80, 0x86, + 0x7e, 0xc6, 0x34, 0xb5, 0xce, 0x50, 0xf9, 0xcc, 0xbb, 0x67, 0x46, 0xcb, 0x99, 0x05, 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, 0xe3, 0x50, 0x69, 0x73, 0x20, 0xbe, 0x11, 0x1a, 0xf7, 0x4f, + 0xc3, 0xd8, 0x6a, 0x8a, 0xad, 0xdd, 0xdb, 0x76, 0xfb, 0x7b, 0xe9, 0xa5, 0xd3, 0x9c, 0xf4, 0x18, 0xfb, 0xbd, 0x0c, + 0x8b, 0x91, 0xed, 0x08, 0x81, 0x25, 0xe7, 0x7d, 0xea, 0xbf, 0xa2, 0xe5, 0x3c, 0x01, 0xd3, 0x11, 0x1d, 0x21, 0x17, + 0x28, 0x3b, 0x46, 0x71, 0x07, 0x06, 0x57, 0xf4, 0xfb, 0x60, 0x95, 0x61, 0x2e, 0x24, 0x4b, 0x92, 0x32, 0x78, 0x9e, + 0x7a, 0x18, 0xf0, 0x6b, 0xa6, 0xcc, 0x5d, 0x94, 0xf5, 0xe9, 0x92, 0x4c, 0x53, 0x64, 0x20, 0xd6, 0xe1, 0x26, 0x4b, + 0xa3, 0x44, 0x89, 0xc8, 0x96, 0xe8, 0x1f, 0x69, 0x28, 0x96, 0x0e, 0xd7, 0x8b, 0x54, 0x89, 0x50, 0x31, 0x4f, 0xf1, + 0xa4, 0x4e, 0xeb, 0x74, 0x84, 0xf1, 0x26, 0x41, 0x29, 0x57, 0xc3, 0x40, 0x95, 0x54, 0x2f, 0x85, 0x4d, 0xb1, 0xdd, + 0xea, 0x8b, 0x95, 0x98, 0xc7, 0x0b, 0x7c, 0x29, 0x70, 0x14, 0x7f, 0xe2, 0x5e, 0xac, 0x29, 0xb5, 0x3d, 0xa8, 0x1d, + 0x51, 0x42, 0x7f, 0xe2, 0x70, 0x91, 0xf8, 0x4e, 0xea, 0xb8, 0x7f, 0x68, 0x11, 0x72, 0xa6, 0x0e, 0x52, 0xc3, 0x0d, + 0xed, 0x08, 0xff, 0x0d, 0xd7, 0x67, 0x9c, 0xd1, 0x9b, 0x6a, 0x46, 0x8d, 0xdf, 0xeb, 0xe1, 0x19, 0xa3, 0x3e, 0x1b, + 0x38, 0xac, 0x10, 0x85, 0x36, 0xec, 0xa8, 0x54, 0xa2, 0x85, 0xa1, 0x54, 0x7f, 0x09, 0x15, 0x47, 0xdc, 0x99, 0x51, + 0x96, 0x8c, 0x4f, 0xcb, 0x43, 0x31, 0x1d, 0x0c, 0x4a, 0x52, 0x19, 0x0b, 0x3d, 0xb8, 0x1e, 0x78, 0xfe, 0x3d, 0x70, + 0x0b, 0xf1, 0xe0, 0x90, 0xc5, 0x90, 0x1b, 0x70, 0xfc, 0x16, 0x27, 0x57, 0x8d, 0x4a, 0x15, 0xbc, 0x9a, 0xa8, 0x16, + 0xfc, 0x54, 0x86, 0x01, 0xfa, 0x24, 0x05, 0x60, 0x32, 0x98, 0xf2, 0x5b, 0x90, 0x28, 0x9d, 0xa9, 0x1b, 0xd2, 0xaf, + 0xa2, 0xe0, 0x17, 0xbc, 0xe0, 0x22, 0x71, 0x05, 0x58, 0xde, 0xc1, 0xf6, 0x3a, 0xaa, 0xa8, 0x02, 0xe2, 0x35, 0x3d, + 0x8e, 0xb8, 0xf1, 0xfe, 0x33, 0x3d, 0xb6, 0x40, 0xad, 0xd6, 0xb1, 0xc1, 0x67, 0x8e, 0xc1, 0x05, 0x5d, 0x4b, 0x6c, + 0x0d, 0xd5, 0xb0, 0x22, 0x30, 0x70, 0x01, 0x07, 0x61, 0x89, 0xe2, 0xd8, 0x4a, 0x5e, 0x91, 0x86, 0x94, 0xf6, 0x81, + 0xe1, 0x68, 0x93, 0x1c, 0xdf, 0x66, 0xd9, 0x4d, 0xe0, 0x7c, 0xd1, 0x39, 0x69, 0x26, 0x96, 0x0d, 0xde, 0xe7, 0xcd, + 0xf9, 0x75, 0xff, 0x90, 0x50, 0x15, 0xec, 0x86, 0xb7, 0x83, 0xdd, 0x38, 0xe1, 0xd7, 0x5c, 0x2c, 0x74, 0x7c, 0x16, + 0x73, 0xc9, 0xf2, 0x5b, 0xeb, 0xdd, 0x92, 0xa4, 0x56, 0x40, 0xfb, 0x2c, 0x0b, 0x6a, 0x22, 0x00, 0xdd, 0x0f, 0x7f, + 0x81, 0xd0, 0x19, 0xfe, 0xf6, 0x18, 0x5c, 0x91, 0xc2, 0x7b, 0x87, 0x40, 0x58, 0xd3, 0xcd, 0x9d, 0xda, 0x80, 0x2f, + 0xc6, 0xfd, 0x19, 0x53, 0x4f, 0xbf, 0xcd, 0xe4, 0xae, 0xae, 0xdb, 0x23, 0xcb, 0xf0, 0x11, 0xae, 0x14, 0x00, 0xcb, + 0x84, 0xbf, 0x18, 0x5b, 0x52, 0x7d, 0x02, 0x70, 0x6a, 0x3a, 0xa2, 0x4f, 0x10, 0x18, 0x38, 0x25, 0x5a, 0x8c, 0xae, + 0x95, 0x23, 0x9a, 0x41, 0x5a, 0xd3, 0xad, 0x30, 0xde, 0x7a, 0xd0, 0x42, 0xcf, 0x34, 0x9c, 0xf8, 0x0f, 0x9a, 0x79, + 0x55, 0x40, 0x00, 0xad, 0x8c, 0xe0, 0xad, 0xf5, 0xd1, 0x1c, 0x21, 0x3e, 0x61, 0x49, 0x34, 0x61, 0xf1, 0x4c, 0xf1, + 0x63, 0x42, 0x37, 0x4d, 0x6d, 0xd3, 0x07, 0xa4, 0xbf, 0xb8, 0x66, 0xfd, 0x94, 0x65, 0xed, 0xdb, 0x43, 0xc5, 0x8b, + 0x69, 0x33, 0xf8, 0x61, 0xa2, 0x8a, 0xf1, 0xbf, 0xa8, 0x7c, 0xa9, 0x15, 0xc0, 0x30, 0x77, 0xd5, 0xd3, 0xef, 0x37, + 0xb3, 0xe5, 0x40, 0xa8, 0xfc, 0xce, 0x20, 0xe9, 0xd3, 0xf1, 0xfc, 0xc0, 0x26, 0x51, 0x5b, 0xe8, 0xf9, 0xe3, 0x52, + 0x37, 0xa1, 0xf2, 0xda, 0xd4, 0x88, 0x56, 0xc8, 0x50, 0xd9, 0x3a, 0x60, 0x7d, 0xff, 0x10, 0xee, 0x2e, 0x6a, 0x1a, + 0x6a, 0xdd, 0x73, 0xd7, 0xa2, 0xe0, 0xc4, 0x1f, 0x60, 0x2c, 0x2e, 0x24, 0xb5, 0x0e, 0xc2, 0xa4, 0x1f, 0x2d, 0x4e, + 0x72, 0xa3, 0xae, 0x4e, 0xce, 0x14, 0xf3, 0x04, 0x2e, 0xaa, 0x65, 0xdb, 0x5f, 0x51, 0xa9, 0x4b, 0xb9, 0xbd, 0xa2, + 0x34, 0x3d, 0xa4, 0xed, 0x55, 0x9c, 0xb7, 0x05, 0x17, 0xfc, 0x0b, 0x05, 0x17, 0xd6, 0xc1, 0xba, 0xe3, 0x4e, 0xd9, + 0x13, 0x9e, 0x28, 0xd3, 0xda, 0xe0, 0xae, 0x1b, 0x8c, 0x89, 0xb1, 0xdf, 0x5d, 0xf2, 0xe4, 0x23, 0xb2, 0xe0, 0xdf, + 0x65, 0x02, 0x3c, 0x93, 0xdd, 0x2b, 0x95, 0xff, 0x07, 0xff, 0x6a, 0x6b, 0xdf, 0x59, 0xf3, 0x4f, 0xcf, 0x7a, 0xb8, + 0x73, 0x98, 0xfc, 0x00, 0x9d, 0x01, 0xdd, 0x5c, 0xc9, 0x94, 0x03, 0x32, 0x80, 0xb5, 0x48, 0x46, 0x03, 0x3e, 0xb4, + 0xb2, 0x6c, 0xfb, 0x4e, 0xab, 0x0b, 0xc2, 0xbd, 0x04, 0x6e, 0x7a, 0x7f, 0x6d, 0x66, 0xe6, 0x74, 0xad, 0x44, 0xd3, + 0xa5, 0xb1, 0xb5, 0x2c, 0x55, 0xc0, 0xee, 0xf7, 0x9e, 0x64, 0xd3, 0xfc, 0x70, 0x39, 0xcd, 0x2d, 0x75, 0xdb, 0xb8, + 0x65, 0x03, 0x40, 0x88, 0x5d, 0x6b, 0x2b, 0x07, 0x90, 0xdc, 0x1e, 0x84, 0xf0, 0xb5, 0x22, 0xf4, 0x54, 0x89, 0xd0, + 0xa7, 0x69, 0xb3, 0x0f, 0x76, 0x55, 0xad, 0x1b, 0x71, 0x8e, 0x06, 0xa9, 0x66, 0xe4, 0x4f, 0xae, 0x79, 0x71, 0x91, + 0xcb, 0x1b, 0xc0, 0x40, 0x26, 0xb5, 0x51, 0x58, 0x5e, 0x81, 0x3b, 0x3f, 0x3a, 0x8e, 0x33, 0x31, 0xca, 0x31, 0x58, + 0x2b, 0xc2, 0x23, 0xeb, 0xc4, 0x19, 0x80, 0x20, 0xfb, 0x93, 0xa6, 0xe3, 0xb9, 0x16, 0x18, 0xd3, 0x17, 0xb8, 0xab, + 0x9c, 0x1d, 0x6d, 0x72, 0xbb, 0xe8, 0x9b, 0x33, 0xac, 0x3b, 0x52, 0x5a, 0x1b, 0x8b, 0xae, 0x3b, 0x58, 0x6b, 0x06, + 0x6d, 0x11, 0x4a, 0x3e, 0xe4, 0x4e, 0xda, 0x4f, 0x01, 0x0d, 0xce, 0xb2, 0xf4, 0xd6, 0x5a, 0xe5, 0x6f, 0xb4, 0x10, + 0x27, 0x8a, 0xa9, 0x13, 0xdf, 0x44, 0x89, 0x3e, 0x3f, 0x13, 0xe3, 0x06, 0x02, 0xa9, 0x3f, 0x60, 0x50, 0x8d, 0x22, + 0x4c, 0xe0, 0x3a, 0x10, 0xc5, 0xf6, 0x44, 0x6d, 0x2c, 0x47, 0xd0, 0x09, 0x21, 0xde, 0x41, 0x19, 0xc6, 0xea, 0xe2, + 0x40, 0x1b, 0x2c, 0x7d, 0xdd, 0x5a, 0xe7, 0x86, 0x50, 0x18, 0x27, 0x30, 0xc5, 0x20, 0xa9, 0xb3, 0xce, 0x32, 0x41, + 0x95, 0x1d, 0x93, 0xce, 0xfb, 0x00, 0xdd, 0x5d, 0x8b, 0xa6, 0xf8, 0xba, 0x73, 0x07, 0xdd, 0xc7, 0xf5, 0x6b, 0x2d, + 0x72, 0x83, 0x3f, 0x6f, 0x89, 0xb0, 0x08, 0x9c, 0xb5, 0x26, 0x5f, 0x35, 0xc2, 0x81, 0x29, 0xc9, 0x34, 0xec, 0x25, + 0xca, 0xa6, 0x7b, 0xbb, 0xed, 0xf5, 0xee, 0x15, 0x71, 0xf5, 0x18, 0xab, 0xbc, 0x9b, 0xb9, 0xbd, 0x53, 0xad, 0xc5, + 0xee, 0x4d, 0xdb, 0x4f, 0xb1, 0xa3, 0xd6, 0xda, 0xed, 0x86, 0x13, 0x6a, 0xc8, 0xb7, 0xa2, 0x4a, 0xab, 0xd3, 0x8d, + 0x41, 0x3b, 0xc4, 0xb3, 0x16, 0x19, 0xdc, 0x28, 0x5f, 0x38, 0xa1, 0x93, 0x8a, 0xb3, 0xea, 0xd4, 0x05, 0x9b, 0x2b, + 0x5e, 0x2d, 0x65, 0x1a, 0x09, 0x8a, 0x36, 0xe7, 0x51, 0x49, 0x13, 0xb9, 0x16, 0x55, 0x24, 0x6b, 0xd4, 0x8b, 0x5a, + 0x8d, 0x01, 0x02, 0x32, 0x9d, 0x35, 0x3d, 0xa8, 0x82, 0xd9, 0x50, 0x46, 0x72, 0xfa, 0x1e, 0x2c, 0xed, 0x91, 0x63, + 0xad, 0xef, 0xab, 0xb3, 0xc5, 0xb7, 0x7a, 0x42, 0x30, 0x85, 0xd9, 0x03, 0x61, 0xe0, 0x9a, 0xc6, 0x90, 0xd3, 0x2e, + 0x71, 0x59, 0xd3, 0x2d, 0xe1, 0x1e, 0x6e, 0x57, 0xb2, 0x23, 0x37, 0x4f, 0x9a, 0x9b, 0x2b, 0xd8, 0x51, 0x31, 0x1f, + 0x83, 0xf6, 0x4b, 0xaa, 0x6b, 0x97, 0xe6, 0xd6, 0xe3, 0x41, 0x40, 0x83, 0x41, 0x61, 0xf8, 0xd7, 0x89, 0xf1, 0xf0, + 0xa4, 0x01, 0x41, 0x52, 0x2e, 0xc2, 0xb1, 0x6f, 0x44, 0x3f, 0x99, 0xca, 0x43, 0x8e, 0x16, 0xef, 0xd0, 0xea, 0x04, + 0xa2, 0x78, 0x89, 0x50, 0x12, 0xa3, 0x2a, 0x34, 0x22, 0x28, 0x4f, 0xcb, 0x5f, 0xaa, 0xea, 0x10, 0x50, 0x48, 0xfb, + 0x8a, 0x42, 0xd9, 0x26, 0x31, 0x34, 0xc3, 0x2f, 0xe7, 0x93, 0x85, 0x9e, 0x81, 0x81, 0x9c, 0x1f, 0x2c, 0xf4, 0x2c, + 0x0c, 0xe4, 0xfc, 0xc9, 0xa2, 0x76, 0xeb, 0x40, 0x13, 0x10, 0xcf, 0x85, 0xa3, 0x93, 0xd2, 0xaa, 0x6c, 0x01, 0xdd, + 0x3c, 0x44, 0xd0, 0x7f, 0xb2, 0x87, 0xa0, 0x93, 0x0b, 0xed, 0xc8, 0x0d, 0x68, 0x3b, 0x0e, 0x81, 0xbd, 0x62, 0x52, + 0x61, 0x02, 0x10, 0x1d, 0xb2, 0x31, 0x18, 0x62, 0xab, 0x0f, 0x0e, 0xd9, 0x78, 0xea, 0x93, 0x20, 0x60, 0x74, 0x7f, + 0x30, 0x90, 0xe0, 0xb7, 0x78, 0x95, 0x3e, 0xda, 0x08, 0x74, 0xd3, 0x77, 0x77, 0x43, 0xef, 0xe2, 0x0a, 0x4e, 0xd5, + 0xee, 0x9e, 0x84, 0x6e, 0x32, 0xed, 0x00, 0xbd, 0x86, 0xb8, 0x21, 0xbf, 0x32, 0x1a, 0x8d, 0x6c, 0x4a, 0x48, 0x88, + 0xe1, 0x1c, 0x9a, 0x39, 0x2d, 0x97, 0xaf, 0x6e, 0x3d, 0x1b, 0x90, 0x61, 0xa6, 0xb7, 0x4c, 0xd6, 0x0f, 0x50, 0x56, + 0x3d, 0x86, 0x76, 0xe8, 0x3d, 0x72, 0xfc, 0xf0, 0xe0, 0x9b, 0x8c, 0x9f, 0x39, 0x5c, 0x7b, 0x38, 0x17, 0xbe, 0xcb, + 0x9a, 0x91, 0x39, 0x74, 0x9e, 0x7d, 0x1c, 0xef, 0x61, 0x9c, 0x7c, 0x9e, 0x85, 0xf2, 0xc6, 0x6b, 0xfa, 0x1f, 0x95, + 0xde, 0xec, 0x70, 0xc8, 0xe9, 0x0a, 0x56, 0xdc, 0xac, 0x0a, 0x0d, 0x3f, 0x8b, 0xbc, 0x71, 0xc4, 0x6b, 0x12, 0x55, + 0xdd, 0xe7, 0xbd, 0x0d, 0x53, 0xda, 0x31, 0x0e, 0x00, 0x4e, 0xd4, 0xaa, 0x61, 0x57, 0x1a, 0xd7, 0xea, 0x20, 0x86, + 0xa1, 0x84, 0xad, 0x12, 0x47, 0x42, 0xf9, 0x1b, 0x80, 0xb0, 0x18, 0x8a, 0xe3, 0xad, 0x61, 0x7d, 0x80, 0xfd, 0xd0, + 0x05, 0x9a, 0xe6, 0x94, 0x6a, 0x06, 0x00, 0x49, 0xc0, 0x1f, 0x3d, 0xdd, 0x34, 0x54, 0xb6, 0x79, 0x1e, 0x5a, 0x56, + 0x57, 0xf0, 0x40, 0x4f, 0x5d, 0xc9, 0xc0, 0xb8, 0xaa, 0x63, 0x6f, 0x73, 0x7f, 0x7b, 0xb4, 0x8a, 0x7c, 0x67, 0x93, + 0xda, 0x66, 0x55, 0x68, 0xec, 0xe3, 0x09, 0x3d, 0x9d, 0x00, 0xad, 0xd7, 0x96, 0x8a, 0xf6, 0xfb, 0x28, 0x46, 0x8d, + 0x0b, 0x05, 0x56, 0x61, 0x22, 0xc1, 0x21, 0xc2, 0x08, 0xa1, 0xdf, 0x97, 0xe1, 0xc6, 0x17, 0x64, 0x10, 0x0d, 0xd7, + 0xa2, 0xe3, 0x0f, 0x39, 0x5e, 0xb4, 0x2d, 0x55, 0x35, 0x27, 0x4d, 0x5b, 0x02, 0x6f, 0xc2, 0x01, 0xb6, 0xf3, 0x4f, + 0x1b, 0x22, 0x57, 0xe1, 0xa2, 0x84, 0xef, 0x88, 0x6b, 0x41, 0x74, 0x53, 0x9b, 0x7a, 0x1b, 0x76, 0x88, 0x8e, 0xa6, + 0x78, 0x74, 0xc8, 0x3d, 0x77, 0xcf, 0x6d, 0x11, 0xdf, 0x7c, 0x86, 0xdc, 0x35, 0x9d, 0xbd, 0x14, 0x61, 0x50, 0xb7, + 0x6c, 0xa0, 0x58, 0x87, 0x4e, 0x50, 0x80, 0x51, 0x5b, 0x3e, 0x01, 0x1d, 0x1b, 0x0c, 0x2a, 0x82, 0x4f, 0x0a, 0xdb, + 0xa6, 0x41, 0xfe, 0x88, 0x77, 0x43, 0x87, 0xd7, 0x96, 0x3c, 0x10, 0xaf, 0xb0, 0xcf, 0x94, 0x70, 0xff, 0x82, 0x82, + 0xee, 0x28, 0x2f, 0x57, 0x85, 0xab, 0xd2, 0x00, 0x54, 0xd9, 0xf1, 0x5c, 0x6b, 0x4a, 0x5a, 0xc0, 0x4a, 0x49, 0xdd, + 0xf9, 0x4d, 0x44, 0xdc, 0x92, 0xa9, 0x98, 0xad, 0xba, 0x51, 0xe5, 0xa1, 0x44, 0x91, 0x8e, 0x3d, 0xdb, 0x39, 0x58, + 0x03, 0xe0, 0x29, 0x6c, 0x2f, 0xce, 0xb0, 0xa0, 0x8c, 0xcb, 0x96, 0xb9, 0x04, 0x8a, 0xfa, 0x61, 0x9c, 0x97, 0x1d, + 0x5f, 0xee, 0x8e, 0xb6, 0xf7, 0xd0, 0x1b, 0xb1, 0x31, 0x5e, 0x5f, 0x46, 0x4d, 0xbf, 0x78, 0x86, 0x2b, 0x4b, 0x41, + 0x1e, 0x68, 0xaa, 0x47, 0x18, 0x1d, 0x02, 0xd3, 0x94, 0x1f, 0xb1, 0xf1, 0x74, 0x38, 0x34, 0x64, 0xd0, 0x6b, 0x26, + 0xc6, 0xff, 0xfa, 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, 0x58, 0x12, 0xa3, 0x10, 0xbf, 0x38, + 0x55, 0xb6, 0x13, 0x42, 0x05, 0xc4, 0x43, 0xd7, 0xba, 0x71, 0x24, 0x55, 0xec, 0x49, 0xa1, 0xf1, 0xd4, 0x70, 0xdf, + 0x0b, 0x1d, 0xb3, 0x0e, 0xb3, 0xb8, 0xcd, 0x1a, 0x49, 0x8d, 0x71, 0x2a, 0x4c, 0x70, 0x4a, 0xb9, 0x8a, 0x04, 0x46, + 0xc7, 0xb3, 0x85, 0x41, 0x54, 0x49, 0x4c, 0x32, 0xb6, 0x16, 0xc2, 0xc4, 0xae, 0x73, 0x85, 0x69, 0xea, 0x22, 0xf5, + 0x9b, 0x81, 0xc9, 0x82, 0x86, 0xfc, 0x1e, 0x8d, 0xd6, 0x54, 0x4d, 0x01, 0x86, 0x71, 0x94, 0x6a, 0xfc, 0x5b, 0x84, + 0xda, 0x0c, 0x03, 0x00, 0xdb, 0xbc, 0x93, 0x99, 0xa8, 0x5e, 0x0b, 0x84, 0x40, 0x73, 0xf6, 0x53, 0x45, 0xb5, 0x33, + 0x0b, 0x46, 0xd1, 0x6e, 0xaf, 0x7c, 0x3e, 0x70, 0x42, 0x79, 0xac, 0x2e, 0x50, 0xaf, 0x64, 0xf1, 0x46, 0xa6, 0xbc, + 0x15, 0x17, 0x73, 0x4f, 0xb2, 0x0f, 0xf9, 0x08, 0xce, 0x2b, 0x74, 0x2a, 0x37, 0xdb, 0x44, 0x99, 0x25, 0x49, 0xc6, + 0x02, 0x63, 0xf3, 0x12, 0xcc, 0xa4, 0x66, 0xc6, 0xf0, 0x6b, 0x08, 0x2e, 0xb6, 0x73, 0x12, 0x6e, 0xee, 0xe7, 0x81, + 0x21, 0x34, 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, 0xe1, 0xce, 0x7f, 0x50, 0x58, + 0x83, 0xca, 0x88, 0xcb, 0x88, 0xf2, 0xcc, 0x81, 0x6e, 0x9a, 0x14, 0x71, 0x7a, 0xb6, 0x8a, 0x8b, 0x92, 0xa7, 0x50, + 0xa9, 0xa6, 0x6e, 0x51, 0x6f, 0x02, 0xf6, 0x86, 0x48, 0x92, 0xac, 0xa5, 0xb1, 0x15, 0xbb, 0x34, 0x48, 0xcf, 0xbd, + 0x61, 0x96, 0x5e, 0x55, 0x68, 0x48, 0x4b, 0xbd, 0xb3, 0x50, 0xc9, 0xfc, 0x15, 0xff, 0x19, 0xd4, 0x0a, 0x74, 0xb4, + 0x49, 0x31, 0x9e, 0x03, 0x23, 0xbe, 0x1b, 0xc1, 0xea, 0x01, 0xe2, 0xa2, 0x09, 0x4a, 0xbd, 0x23, 0x76, 0xfc, 0xdc, + 0xe4, 0xe1, 0x5d, 0xc8, 0x39, 0x83, 0x4f, 0x1f, 0x66, 0x89, 0x5a, 0xeb, 0x48, 0x8c, 0xd4, 0x0c, 0xa0, 0xe9, 0xa0, + 0xcc, 0x79, 0x2c, 0x82, 0x59, 0xcf, 0x24, 0x46, 0x3d, 0xae, 0x7f, 0x81, 0x86, 0xda, 0x6f, 0x56, 0x96, 0x67, 0xd5, + 0xdd, 0x97, 0x70, 0x60, 0x53, 0x5b, 0x41, 0x8f, 0xd7, 0x95, 0xbc, 0xbc, 0x54, 0xdd, 0xf6, 0x0b, 0x31, 0x72, 0xba, + 0xc6, 0xb5, 0x74, 0x5e, 0x2d, 0x58, 0xaf, 0x3b, 0xdd, 0x2c, 0xee, 0x66, 0x19, 0x0d, 0x84, 0xb5, 0x9d, 0x4f, 0x34, + 0x7f, 0xd6, 0x6c, 0xbb, 0x8f, 0xb7, 0x20, 0x66, 0x01, 0x00, 0xa4, 0x07, 0x51, 0xb0, 0xcc, 0x52, 0x1e, 0x50, 0x79, + 0x1f, 0x47, 0x59, 0x28, 0xbd, 0x9c, 0x65, 0xfc, 0xb4, 0x69, 0xac, 0x75, 0x56, 0x28, 0x43, 0x6b, 0xa3, 0x3b, 0x5d, + 0x65, 0x88, 0xed, 0x27, 0x71, 0xb6, 0x00, 0xf7, 0xc7, 0x0c, 0x85, 0x86, 0xce, 0x32, 0xd2, 0x44, 0xc3, 0x77, 0xdd, + 0x33, 0xc8, 0x28, 0x4e, 0xd6, 0x79, 0x25, 0xdd, 0xe8, 0xb3, 0x36, 0x12, 0xe6, 0x1e, 0xa2, 0x5f, 0xc5, 0xe0, 0x51, + 0xee, 0xf3, 0xda, 0xe8, 0x64, 0x5a, 0x46, 0xda, 0x9d, 0x9f, 0xd4, 0xcb, 0x2c, 0xd5, 0x3a, 0x6c, 0x9f, 0x61, 0x6f, + 0x8d, 0x49, 0x6f, 0x42, 0x6a, 0x18, 0x89, 0xcf, 0x67, 0xd4, 0x08, 0x01, 0x6d, 0x39, 0xfe, 0x0e, 0x9f, 0x61, 0x68, + 0x0a, 0x2c, 0x55, 0xdc, 0xc2, 0x6e, 0xf8, 0x9a, 0x4f, 0x56, 0x2d, 0x00, 0x11, 0xac, 0x7c, 0xbd, 0x8b, 0x57, 0x42, + 0x7d, 0xa6, 0xcd, 0x00, 0x90, 0x05, 0xa5, 0xdc, 0xf1, 0x53, 0x2a, 0x1d, 0x2c, 0x51, 0xb4, 0xbd, 0x9c, 0xbe, 0xd1, + 0xb1, 0xf1, 0x43, 0x7a, 0x2e, 0x60, 0xbb, 0x90, 0xdf, 0xba, 0x57, 0x2f, 0x51, 0x91, 0xda, 0x36, 0xeb, 0x01, 0xbe, + 0xdc, 0xa0, 0x49, 0x18, 0x41, 0x99, 0x32, 0x05, 0x30, 0xb8, 0xa9, 0x46, 0xc1, 0xa4, 0xd5, 0x48, 0xd8, 0x52, 0x4f, + 0xb2, 0xdc, 0xf4, 0xc1, 0xa9, 0xee, 0x11, 0xf4, 0x68, 0x87, 0x93, 0x96, 0xfd, 0x5a, 0xc1, 0xd1, 0xc9, 0xd5, 0x10, + 0x35, 0xf3, 0x5e, 0xdb, 0x91, 0x21, 0xe5, 0x32, 0x0c, 0x04, 0x53, 0x8e, 0x79, 0x7a, 0x6c, 0x3d, 0x23, 0xa2, 0x07, + 0xce, 0x3e, 0xd3, 0xad, 0xba, 0x92, 0x80, 0xe8, 0xf8, 0xcd, 0xd3, 0xd7, 0x57, 0xf1, 0xa5, 0x41, 0x51, 0x6a, 0x58, + 0xc4, 0x28, 0xd3, 0xbe, 0x4a, 0xc2, 0xe0, 0xfd, 0xfa, 0xfe, 0x67, 0x95, 0xa5, 0xf6, 0x7b, 0xb0, 0xb1, 0xa2, 0xaa, + 0x5f, 0x4b, 0x5e, 0x34, 0x05, 0x58, 0xf7, 0x59, 0xa2, 0x40, 0xee, 0xf7, 0x36, 0xcd, 0x7c, 0x13, 0x35, 0x6e, 0x36, + 0xac, 0x37, 0xae, 0xdb, 0xa5, 0xb6, 0x64, 0x47, 0x56, 0x22, 0x67, 0x16, 0x83, 0x19, 0x3f, 0x2a, 0x0c, 0x4a, 0xc3, + 0x06, 0x55, 0xa9, 0xf8, 0xbd, 0x11, 0xc1, 0xa9, 0x63, 0x55, 0x61, 0x4c, 0x03, 0x66, 0x5b, 0x51, 0x6b, 0x50, 0x07, + 0xa5, 0xb4, 0x35, 0x51, 0xd8, 0x7e, 0x67, 0x05, 0x35, 0xbf, 0xff, 0x69, 0x0c, 0xf9, 0x9a, 0x52, 0x50, 0x49, 0xc0, + 0xce, 0xa0, 0xd1, 0x53, 0x25, 0x0c, 0xa4, 0x20, 0x78, 0x02, 0x94, 0x2f, 0xa2, 0xc6, 0x6a, 0xb7, 0xaf, 0x4e, 0x8d, + 0xd1, 0x16, 0x10, 0x5a, 0x48, 0x8f, 0x2e, 0xfb, 0xb8, 0x8d, 0x75, 0x20, 0xf1, 0xe0, 0x04, 0xdb, 0xb9, 0xba, 0x46, + 0x23, 0xa1, 0xf9, 0x43, 0xa3, 0x01, 0xaf, 0x69, 0x05, 0x0a, 0xf5, 0x1c, 0x47, 0x43, 0x67, 0x87, 0x14, 0x44, 0x6c, + 0xd0, 0xc2, 0xbe, 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, 0x82, 0x61, 0x0b, 0xbf, + 0x39, 0x35, 0x05, 0x60, 0xc3, 0x63, 0x5d, 0x96, 0x6f, 0xd4, 0x44, 0x66, 0x71, 0x48, 0x22, 0x90, 0x6c, 0x37, 0x37, + 0xb7, 0x11, 0x6c, 0x7b, 0x0b, 0xb5, 0xa1, 0xfe, 0xf2, 0xb6, 0xfb, 0x3d, 0xc3, 0xcb, 0x3d, 0xb9, 0x77, 0xd3, 0x86, + 0xf2, 0x87, 0xfb, 0x57, 0xc9, 0xff, 0x55, 0x25, 0xf7, 0x5b, 0x65, 0xd6, 0x6d, 0xf1, 0x7e, 0xd7, 0x71, 0xcb, 0x31, + 0x1a, 0x04, 0xd6, 0x14, 0x18, 0x48, 0x4f, 0x1a, 0xd3, 0x44, 0x87, 0x54, 0x66, 0xcc, 0xe0, 0xd1, 0x05, 0x68, 0x0e, + 0xd3, 0x79, 0x1e, 0x03, 0x70, 0x80, 0x7f, 0xe4, 0x11, 0xea, 0x9f, 0xce, 0xf3, 0xe0, 0x2c, 0x18, 0x94, 0x83, 0x40, + 0x7f, 0xe2, 0x9a, 0x13, 0x2c, 0x40, 0xe7, 0x16, 0x33, 0x08, 0x36, 0x69, 0xcd, 0x1c, 0xe2, 0xc3, 0x64, 0x3a, 0x18, + 0xc4, 0x64, 0x03, 0x20, 0x7d, 0xf1, 0xc2, 0x3a, 0x07, 0x15, 0x7a, 0x41, 0xb6, 0xea, 0x2e, 0x9a, 0x15, 0x7b, 0xd5, + 0x4e, 0xf3, 0x7e, 0x3f, 0x9f, 0x97, 0x83, 0xa0, 0x51, 0x61, 0x61, 0xbc, 0xff, 0x68, 0xf3, 0x4b, 0xa3, 0x93, 0x26, + 0x18, 0xa6, 0xf6, 0x18, 0xd5, 0x2b, 0x9e, 0x66, 0xb4, 0x71, 0x3b, 0x56, 0xca, 0x17, 0x10, 0xc5, 0x03, 0x43, 0xd6, + 0xca, 0xbb, 0x73, 0xf0, 0xba, 0xdc, 0x78, 0x73, 0x44, 0x01, 0x76, 0x53, 0x18, 0x27, 0x35, 0x17, 0x5d, 0xd4, 0xc4, + 0x33, 0xd8, 0xe9, 0xea, 0xad, 0x44, 0xab, 0xf1, 0x5e, 0xbc, 0x6b, 0x36, 0xfe, 0x56, 0xee, 0xe9, 0x32, 0xf7, 0x2e, + 0x00, 0x71, 0x76, 0x2f, 0xae, 0xf6, 0xb0, 0xd4, 0xbd, 0x60, 0x60, 0x91, 0x43, 0xda, 0xd5, 0xea, 0xa1, 0x88, 0xd4, + 0x79, 0x0c, 0x06, 0x4c, 0xa6, 0x21, 0x35, 0x99, 0xf6, 0x0a, 0x05, 0x69, 0x63, 0xad, 0x05, 0xb4, 0xe1, 0xb0, 0xd8, + 0xb1, 0x1b, 0x76, 0xa7, 0x5b, 0x87, 0x42, 0x09, 0xa3, 0x57, 0xd7, 0xcd, 0x43, 0xad, 0xe1, 0x89, 0xa0, 0x07, 0xd5, + 0x68, 0x3f, 0x3d, 0x94, 0x27, 0xed, 0xb1, 0x00, 0x17, 0x3d, 0x7c, 0xf9, 0x52, 0xe0, 0x45, 0x7b, 0x07, 0x79, 0xce, + 0x7c, 0xaa, 0x7c, 0x10, 0x1b, 0x6e, 0x19, 0x3e, 0xb4, 0x8f, 0x6f, 0x05, 0x32, 0xa9, 0x3b, 0x9a, 0xda, 0xda, 0x1d, + 0x8d, 0x63, 0x02, 0xfd, 0xa6, 0x1c, 0xa5, 0x4c, 0x4c, 0x2d, 0x4b, 0x76, 0xd4, 0xcb, 0x95, 0x37, 0x54, 0xca, 0x8e, + 0x96, 0x6d, 0xce, 0x2f, 0x6d, 0x24, 0xf4, 0xfb, 0xda, 0x1d, 0x08, 0xdf, 0xa8, 0xf5, 0x86, 0xbc, 0x6c, 0x88, 0x58, + 0x0e, 0x31, 0x03, 0xc7, 0x0b, 0xa9, 0x5c, 0xbb, 0x8b, 0xa6, 0xaa, 0x6e, 0x67, 0x2b, 0x17, 0xb4, 0xc4, 0x5b, 0x29, + 0xb0, 0x8a, 0xd4, 0xe9, 0xf5, 0x54, 0xe2, 0x7d, 0x1f, 0xc5, 0xf6, 0x23, 0x60, 0x1b, 0x1b, 0x47, 0x63, 0xe3, 0x16, + 0xb1, 0xc1, 0x57, 0x51, 0x45, 0x0b, 0x0e, 0x10, 0xdc, 0x6d, 0x49, 0x2d, 0xcd, 0x1c, 0xe2, 0xbe, 0xe2, 0x01, 0xda, + 0x77, 0x71, 0xc4, 0xa9, 0x00, 0xdb, 0xba, 0xd6, 0x39, 0xab, 0xe5, 0x80, 0xcd, 0x44, 0xcf, 0x3f, 0xad, 0x1a, 0x89, + 0x18, 0x56, 0xd9, 0x48, 0x59, 0xa1, 0x3d, 0x28, 0x5d, 0xc2, 0xc5, 0x17, 0xe0, 0x65, 0xfb, 0x7e, 0x65, 0xf7, 0xd9, + 0x12, 0xfb, 0x87, 0x79, 0xd5, 0x04, 0x8f, 0xbc, 0xc6, 0xdb, 0x7b, 0x98, 0xf8, 0x52, 0x29, 0x84, 0x57, 0x29, 0x0d, + 0x25, 0x00, 0x83, 0x24, 0xa8, 0xe1, 0x4a, 0xdb, 0x66, 0x90, 0xca, 0x18, 0x76, 0xb7, 0x7a, 0xab, 0xff, 0xd3, 0x2a, + 0x5c, 0x54, 0xb2, 0x18, 0x93, 0x40, 0xe7, 0x54, 0xcb, 0x4d, 0x4c, 0xc1, 0xb3, 0x5d, 0x72, 0x04, 0x0a, 0x3b, 0x01, + 0xdc, 0x50, 0xc2, 0x7e, 0xc5, 0xdb, 0x50, 0xce, 0x5e, 0x59, 0xc9, 0x93, 0xdb, 0x97, 0x54, 0xd0, 0x84, 0x4c, 0x85, + 0xdd, 0xbf, 0xad, 0x0d, 0xfb, 0x22, 0x94, 0x23, 0x29, 0x70, 0x71, 0xd0, 0x39, 0x80, 0xfd, 0x41, 0x2e, 0x63, 0xf3, + 0x99, 0xf4, 0xfb, 0xea, 0xfd, 0xf3, 0x3c, 0x4b, 0x3e, 0xee, 0xbc, 0x37, 0x3c, 0xcd, 0x92, 0x01, 0x95, 0x88, 0xa9, + 0x75, 0x55, 0x0c, 0x97, 0xda, 0xc5, 0xb8, 0x41, 0x32, 0xe2, 0x7b, 0xa9, 0x43, 0x8c, 0x18, 0x5f, 0x64, 0x87, 0xa4, + 0xe4, 0x74, 0x59, 0x77, 0xf6, 0x5c, 0x8b, 0x66, 0xd0, 0x18, 0x6e, 0xc7, 0x7b, 0x49, 0xaf, 0x00, 0x15, 0x15, 0xba, + 0x67, 0x81, 0x6b, 0x78, 0x73, 0x49, 0x34, 0xb6, 0xf4, 0xb4, 0x25, 0x1a, 0xb8, 0x57, 0x26, 0x24, 0xd5, 0xc6, 0x01, + 0x16, 0xb1, 0xae, 0x3f, 0x86, 0x12, 0x80, 0x5a, 0x0d, 0xd2, 0x2b, 0x7d, 0x45, 0xa8, 0x4a, 0x42, 0x30, 0x3a, 0x91, + 0xf0, 0x32, 0xa0, 0x71, 0x66, 0x12, 0x2d, 0x6c, 0x70, 0x40, 0x5f, 0x54, 0x26, 0xd1, 0xd8, 0x90, 0x07, 0xb4, 0xb2, + 0x69, 0x00, 0x83, 0x0f, 0x92, 0x24, 0xfa, 0x7a, 0x69, 0x92, 0x40, 0x50, 0x82, 0xf2, 0x0d, 0xfa, 0x4b, 0xe9, 0xf9, + 0x58, 0xfe, 0xcb, 0x3b, 0x94, 0x7e, 0x08, 0x25, 0xc8, 0x14, 0x75, 0xc5, 0x34, 0x63, 0x47, 0x59, 0xb7, 0x31, 0x89, + 0xe7, 0x69, 0x77, 0x5b, 0x28, 0x97, 0x2e, 0xf0, 0x2b, 0xcb, 0x10, 0xc7, 0xfa, 0x79, 0xbc, 0x62, 0xc7, 0x21, 0xd7, + 0x78, 0xe9, 0xcf, 0xe3, 0x15, 0xce, 0x10, 0xad, 0x5a, 0x09, 0x44, 0xf9, 0xaf, 0xda, 0xc0, 0x21, 0xee, 0x13, 0x0c, + 0x72, 0x51, 0x79, 0x0f, 0x04, 0xf2, 0xb6, 0x82, 0x88, 0x34, 0xb3, 0xeb, 0x30, 0x22, 0xd5, 0x4e, 0x92, 0xf9, 0xf2, + 0x47, 0x99, 0x09, 0xef, 0x1b, 0x78, 0x6c, 0x36, 0xcb, 0xa6, 0x98, 0x2f, 0x54, 0x30, 0x07, 0xf7, 0x89, 0x8a, 0x4b, + 0x51, 0xf9, 0x4f, 0xd8, 0x05, 0x2f, 0xc6, 0x83, 0xd7, 0x6b, 0x04, 0xd8, 0xaf, 0xfc, 0x27, 0x6f, 0xcc, 0xde, 0x5a, + 0x37, 0xbe, 0xcc, 0x44, 0x7c, 0xe0, 0xa3, 0x5b, 0xca, 0x47, 0x77, 0x5e, 0xa6, 0x3f, 0x1b, 0x50, 0x22, 0xa3, 0xb2, + 0xe2, 0xab, 0x15, 0x4f, 0x67, 0xb7, 0x49, 0x94, 0x8d, 0x2a, 0x2e, 0x60, 0x7a, 0xc1, 0xf1, 0x2e, 0x59, 0x9f, 0x67, + 0xc9, 0x6b, 0x88, 0x3d, 0xb0, 0x92, 0x0a, 0x8b, 0x1f, 0x96, 0x99, 0x5a, 0xcc, 0x42, 0x56, 0x52, 0xf0, 0x60, 0x76, + 0x9d, 0x44, 0x6f, 0x97, 0x1e, 0x92, 0x9a, 0x99, 0xb2, 0x4d, 0xed, 0x08, 0xb5, 0xf1, 0x75, 0xa4, 0x1b, 0x6d, 0x01, + 0x00, 0xf7, 0x6c, 0x91, 0x46, 0x92, 0x89, 0xe1, 0xa4, 0x66, 0xdc, 0xa4, 0x17, 0x98, 0x1a, 0xd7, 0xac, 0xa2, 0x89, + 0xb3, 0x90, 0x01, 0xbd, 0x3f, 0xe0, 0xe5, 0xe0, 0x73, 0x06, 0xf7, 0x1f, 0xb4, 0x06, 0x2e, 0x0f, 0x8b, 0x7e, 0x5f, + 0x1e, 0x16, 0xdb, 0x6d, 0x79, 0x14, 0xf7, 0xfb, 0xf2, 0x28, 0x36, 0xfc, 0x83, 0x52, 0x6c, 0x1b, 0x73, 0x83, 0x84, + 0xe6, 0x12, 0xa2, 0x16, 0x8d, 0xe0, 0x0f, 0xcd, 0x72, 0x2e, 0xa2, 0xfc, 0x30, 0xe9, 0xf7, 0x7b, 0xcb, 0x99, 0x18, + 0xe4, 0xc3, 0x24, 0xca, 0x87, 0x89, 0xe7, 0x84, 0xf8, 0x9b, 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, 0x5d, 0x84, 0x25, + 0x96, 0x42, 0x97, 0xec, 0xcf, 0x25, 0xf0, 0x44, 0x39, 0xaf, 0x36, 0xc0, 0xc0, 0x46, 0x78, 0xe7, 0x30, 0xe1, 0x24, + 0xd6, 0x35, 0xa0, 0x9d, 0x6e, 0x6a, 0x7a, 0x41, 0x57, 0xf4, 0x12, 0xf9, 0xd9, 0x0b, 0x30, 0x58, 0x3a, 0x64, 0xf9, + 0x74, 0x30, 0xb8, 0x20, 0x2b, 0x56, 0xce, 0xc3, 0x78, 0x10, 0xae, 0x67, 0xf9, 0xf0, 0x22, 0xba, 0x20, 0xe4, 0xab, + 0x62, 0x41, 0x7b, 0xab, 0x51, 0xf9, 0x31, 0x83, 0xe0, 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, 0x86, 0xe8, + 0xb6, 0xc7, 0x49, 0x02, 0x8e, 0xc9, 0xae, 0xf8, 0x68, 0xac, 0x0a, 0xef, 0xfa, 0x8e, 0xd0, 0x5e, 0x2f, 0x71, 0x83, + 0xf4, 0x5d, 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, 0xde, 0xc0, 0x81, 0x3d, 0x08, 0xf3, 0x59, 0x3c, 0x7c, 0x13, 0xbd, + 0x21, 0xe4, 0x2b, 0x49, 0xaf, 0xd5, 0xa5, 0x0c, 0xc2, 0x20, 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, 0xdd, 0x11, 0xb0, 0xf0, 0x1a, 0x4f, 0xd7, 0x87, + 0x2c, 0x9e, 0x0e, 0x06, 0x6b, 0xa4, 0xea, 0x2a, 0xf7, 0x9a, 0x2c, 0xe8, 0x05, 0x4e, 0x04, 0x01, 0x86, 0x3e, 0x13, + 0x6b, 0x43, 0xc3, 0xdf, 0x30, 0xf8, 0xf8, 0x8e, 0x5d, 0x8c, 0xee, 0xe8, 0x2d, 0x7b, 0xb3, 0x1d, 0x4f, 0x81, 0x99, + 0x5a, 0xcd, 0xc2, 0xbb, 0xc3, 0xcb, 0xd9, 0x25, 0xbb, 0x8b, 0xee, 0x8e, 0xa0, 0xa1, 0x57, 0xec, 0x0e, 0x01, 0x97, + 0xd2, 0xc7, 0xcb, 0xc1, 0x1b, 0xb2, 0x3f, 0x18, 0xa4, 0x24, 0x0a, 0xaf, 0x43, 0xaf, 0x95, 0x6f, 0xe8, 0x1d, 0xa1, + 0x2b, 0x76, 0x8b, 0xa3, 0x71, 0xc9, 0xf0, 0x83, 0x73, 0x76, 0x57, 0x5f, 0x87, 0xde, 0x6e, 0x4e, 0x44, 0x27, 0x88, + 0x11, 0xfa, 0x1a, 0x38, 0x9a, 0xe5, 0xc2, 0x4c, 0xc0, 0x93, 0xb9, 0xc8, 0x68, 0x51, 0x68, 0x06, 0xe2, 0xac, 0x04, + 0xc4, 0x92, 0xa8, 0xfb, 0xcd, 0x46, 0x67, 0xb0, 0x9c, 0xfb, 0xfd, 0x5e, 0x65, 0xe8, 0x01, 0x22, 0x67, 0x76, 0xd2, + 0x83, 0x9e, 0x4f, 0x0f, 0xf0, 0x13, 0xbd, 0x6a, 0x10, 0x27, 0xf3, 0xbb, 0x65, 0xf4, 0x9b, 0x47, 0x1f, 0x7e, 0xe8, + 0xa6, 0x3c, 0x22, 0xff, 0xf7, 0x29, 0x4f, 0x99, 0x47, 0x6f, 0x2a, 0x0f, 0x04, 0xcf, 0x5b, 0x93, 0x4a, 0x23, 0x51, + 0x8d, 0xce, 0x56, 0x31, 0x68, 0x23, 0x51, 0xdb, 0xa0, 0x9f, 0xd0, 0xc2, 0x0a, 0x22, 0xe4, 0x1c, 0xbc, 0x00, 0x83, + 0x54, 0x08, 0x95, 0xa3, 0x16, 0x25, 0x1a, 0x82, 0xe4, 0xb2, 0xe4, 0x2a, 0x7c, 0x0e, 0xa1, 0xea, 0xf4, 0x71, 0x26, + 0xc2, 0x86, 0x1e, 0x87, 0x3e, 0x00, 0xfc, 0xaf, 0x3b, 0xe4, 0xa2, 0xe4, 0x97, 0x78, 0x36, 0xb7, 0x09, 0x46, 0xc1, + 0x12, 0xd1, 0x0c, 0x6d, 0x83, 0xd8, 0x8f, 0x25, 0xc1, 0x7a, 0x24, 0x8d, 0x47, 0xa5, 0x39, 0x22, 0xfc, 0x28, 0x3e, + 0x8a, 0x9e, 0xc6, 0x86, 0x44, 0x72, 0x24, 0x91, 0x7c, 0x00, 0x84, 0x93, 0xa0, 0xbf, 0xb8, 0x6b, 0xb2, 0x6b, 0x21, + 0x31, 0xe8, 0x4f, 0x4b, 0xa6, 0x65, 0xf7, 0xaa, 0xc7, 0xbe, 0x22, 0xc8, 0x1d, 0xd3, 0x7f, 0x79, 0x7d, 0xf8, 0xe7, + 0x12, 0x67, 0xd0, 0x7a, 0xbe, 0xa8, 0xce, 0xcc, 0xbc, 0xc1, 0x8d, 0xbc, 0x2e, 0x6b, 0xd7, 0xe5, 0x0b, 0xbe, 0xc7, + 0x6f, 0x2b, 0x2e, 0xd2, 0x72, 0xef, 0x97, 0xaa, 0x8d, 0xe7, 0x54, 0xae, 0x57, 0x2e, 0xce, 0x8a, 0x32, 0x4e, 0xf5, + 0xa4, 0x2e, 0xc6, 0x1a, 0xb6, 0xe1, 0xf7, 0x88, 0xba, 0x92, 0x96, 0xa3, 0xa7, 0x94, 0xab, 0x66, 0xca, 0xc5, 0x3a, + 0xcf, 0x7f, 0xde, 0x49, 0xc5, 0x29, 0x6e, 0xa6, 0x20, 0x55, 0x6a, 0xb9, 0x80, 0xea, 0x39, 0x6a, 0xb9, 0x5b, 0x9a, + 0x1d, 0xe0, 0xdc, 0x36, 0xd5, 0xc7, 0xca, 0xec, 0xc2, 0x4b, 0x6e, 0xdc, 0x9f, 0x4c, 0x19, 0x16, 0x8c, 0x42, 0x9b, + 0x55, 0x57, 0xda, 0xbe, 0xd0, 0x3a, 0x0d, 0xc3, 0x95, 0x1f, 0x2f, 0x20, 0x5d, 0xc0, 0x38, 0x5e, 0x94, 0x4c, 0x8c, + 0xdb, 0xa3, 0xb7, 0x82, 0xf8, 0x92, 0xad, 0x40, 0xc0, 0x5c, 0xc3, 0xdb, 0x75, 0x1d, 0x6d, 0xf7, 0xc4, 0x29, 0xa3, + 0x72, 0x15, 0x8b, 0xef, 0xe3, 0x95, 0x81, 0x4c, 0x56, 0xc7, 0x63, 0x63, 0x4c, 0xa7, 0x3f, 0x25, 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, 0x9e, 0x31, 0x57, 0x08, 0x56, 0xaa, 0xec, 0xf6, + 0x9d, 0x1a, 0x53, 0x31, 0x83, 0x29, 0xb6, 0x9d, 0xc5, 0xa4, 0x5b, 0xf9, 0xa7, 0x9d, 0xfb, 0x65, 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, 0x59, 0x49, 0xbe, 0x2b, 0x8d, 0xb9, 0xf4, + 0xa9, 0xd2, 0xc4, 0x70, 0xb2, 0x18, 0x71, 0x91, 0x2e, 0xea, 0xcc, 0xae, 0x85, 0xcf, 0x78, 0x19, 0xce, 0xf9, 0xc2, + 0xe8, 0xa6, 0x74, 0xe9, 0x05, 0x8b, 0x75, 0xa7, 0x37, 0x2b, 0x8d, 0x95, 0x12, 0x71, 0x6b, 0x96, 0x09, 0x94, 0xa5, + 0xac, 0x95, 0xf0, 0xa6, 0x68, 0xd9, 0x4a, 0x1a, 0x79, 0xcf, 0x1c, 0xdc, 0xc7, 0x7e, 0x40, 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, 0x26, 0x56, 0x0a, 0xd8, 0x0b, 0xbc, 0xbc, 0xe1, 0x99, 0xaa, 0x69, 0xd9, 0xa5, 0xe2, 0x00, 0xe3, 0xf3, + 0x32, 0x0c, 0xcb, 0xe1, 0x05, 0x58, 0x4b, 0xec, 0x87, 0xab, 0x39, 0x5f, 0xa8, 0xdf, 0x10, 0x70, 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, 0x9e, 0xaa, 0x99, 0x69, 0xc9, 0x7f, 0x12, 0xb5, 0xa1, 0x89, + 0xbe, 0xc1, 0x2a, 0xf2, 0x87, 0xc7, 0x47, 0x97, 0x40, 0xc6, 0xce, 0xae, 0x64, 0xe6, 0x43, 0xdf, 0x47, 0x06, 0xf7, + 0xdc, 0x94, 0x33, 0xae, 0x82, 0x44, 0x19, 0xb8, 0x7b, 0x35, 0x4b, 0xc6, 0x5a, 0x84, 0xef, 0x1e, 0x15, 0x45, 0x9f, + 0x49, 0xd3, 0x80, 0xee, 0x23, 0xc1, 0x1c, 0xe8, 0xbd, 0x42, 0x87, 0xcb, 0x6a, 0x9b, 0x09, 0xf8, 0x8b, 0x04, 0xf9, + 0xad, 0xd0, 0xab, 0x1a, 0x83, 0x2a, 0xda, 0x45, 0x2c, 0xfd, 0xfb, 0x88, 0x1f, 0x65, 0xf3, 0x2f, 0x73, 0x8f, 0x57, + 0x12, 0x06, 0x3f, 0xa4, 0x66, 0x93, 0xcc, 0xdb, 0x2b, 0xf6, 0x3d, 0x74, 0xd4, 0xa3, 0xd6, 0x78, 0x5f, 0xbd, 0xe0, + 0x14, 0x62, 0x94, 0x50, 0x74, 0x12, 0x0c, 0xe0, 0x76, 0x09, 0x29, 0xee, 0x06, 0xbb, 0x69, 0x5e, 0xf3, 0xa2, 0xe0, + 0x7c, 0x5d, 0x55, 0x81, 0x1f, 0xd0, 0x70, 0xbe, 0xd8, 0x0d, 0x61, 0x38, 0xa6, 0xad, 0x6b, 0x18, 0x84, 0x19, 0xc3, + 0x48, 0x08, 0x5e, 0xff, 0xa2, 0x27, 0x34, 0x89, 0x57, 0xdf, 0xf1, 0x4f, 0x19, 0x2f, 0x14, 0x91, 0x06, 0x11, 0x52, + 0x37, 0xf1, 0x8d, 0x4c, 0x93, 0x02, 0x0a, 0x01, 0x46, 0x01, 0x95, 0xd8, 0xd0, 0x54, 0xfc, 0xad, 0x16, 0x1f, 0xfc, + 0xd4, 0x74, 0x3c, 0x1a, 0xd7, 0xad, 0xce, 0xa8, 0xa0, 0x33, 0xd0, 0xa3, 0x56, 0xd4, 0xd3, 0xa0, 0x95, 0x60, 0x1a, + 0x69, 0xde, 0xba, 0x87, 0xc0, 0x2b, 0xd3, 0xe2, 0x9d, 0x07, 0x74, 0x73, 0xe6, 0x83, 0x27, 0x8f, 0xe9, 0x99, 0x43, + 0x4f, 0xae, 0xd8, 0x51, 0xd5, 0x43, 0xed, 0xbd, 0x19, 0xa1, 0xa0, 0xdf, 0xc7, 0x14, 0xe8, 0x46, 0x50, 0x7b, 0x57, + 0xf7, 0x1f, 0xcb, 0x5d, 0x0e, 0xdf, 0x71, 0x96, 0x1b, 0xc0, 0x52, 0x91, 0xb5, 0x02, 0x8f, 0x02, 0xd4, 0xa5, 0x32, + 0x84, 0x2d, 0xe6, 0x70, 0xa8, 0xec, 0x56, 0xad, 0x86, 0x92, 0x1c, 0x96, 0x23, 0x70, 0x08, 0x5d, 0x97, 0x83, 0x72, + 0xb4, 0xcc, 0xaa, 0xf7, 0xf8, 0x5b, 0xb3, 0x0e, 0x49, 0x76, 0x1f, 0xeb, 0xc0, 0x2d, 0xeb, 0x30, 0xfd, 0x68, 0x90, + 0x02, 0xd0, 0x64, 0x23, 0x70, 0x09, 0xc0, 0x7b, 0xfb, 0x8f, 0x08, 0xb5, 0x32, 0xbd, 0x97, 0xb1, 0x50, 0xdf, 0x37, + 0x92, 0xa0, 0x84, 0x66, 0x42, 0xe5, 0x58, 0x0a, 0xde, 0x79, 0xa4, 0x73, 0x52, 0x67, 0xe2, 0x3d, 0x88, 0xd3, 0xc2, + 0x07, 0xf6, 0x16, 0x04, 0xe7, 0x2c, 0xe8, 0x1d, 0xde, 0x66, 0xb5, 0xd4, 0x46, 0x0f, 0x14, 0xc0, 0xef, 0x06, 0x77, + 0x08, 0xf2, 0xd5, 0x18, 0xae, 0x95, 0xbc, 0x09, 0xf9, 0xb0, 0xa0, 0x07, 0x64, 0x60, 0x9f, 0xc5, 0x30, 0xa6, 0x07, + 0xe4, 0xd0, 0x3e, 0x4b, 0x37, 0x80, 0x03, 0xa9, 0x47, 0x95, 0x1e, 0x40, 0x83, 0x7e, 0xb7, 0x2d, 0xb2, 0x24, 0xeb, + 0xc7, 0xd2, 0x28, 0x62, 0xa0, 0x4a, 0x10, 0x51, 0x8b, 0x7f, 0x3e, 0x98, 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, 0xbd, 0xc9, 0xe0, 0xc0, 0xc8, 0xf0, + 0xa5, 0xb7, 0x7f, 0xe1, 0x6b, 0x2d, 0xdd, 0x13, 0x83, 0x92, 0x3c, 0x3e, 0x50, 0xf4, 0xef, 0x5e, 0x59, 0xf9, 0xd4, + 0x4e, 0xff, 0x76, 0x6b, 0xd6, 0xe7, 0xe1, 0x68, 0xb2, 0xdd, 0xf6, 0xb4, 0x81, 0x2b, 0xd5, 0x2a, 0x04, 0xec, 0x42, + 0x49, 0xf6, 0x0f, 0x20, 0x2a, 0x42, 0x33, 0xee, 0x66, 0xd9, 0x90, 0xc8, 0xf8, 0x71, 0x3a, 0xcb, 0x86, 0x60, 0x87, + 0x7b, 0x51, 0x89, 0xcb, 0x51, 0x6b, 0x83, 0xd3, 0xb3, 0x24, 0x84, 0x50, 0x0e, 0x58, 0xd9, 0xad, 0xfa, 0x73, 0xa7, + 0xcc, 0x84, 0xd4, 0x64, 0x75, 0x3b, 0xa5, 0x7b, 0x98, 0xe6, 0x7b, 0x66, 0x04, 0x07, 0xdc, 0xdb, 0x5f, 0xf5, 0xc7, + 0x30, 0xc9, 0x34, 0x39, 0x45, 0xf2, 0x8b, 0xf4, 0x14, 0x92, 0x76, 0xe8, 0xa9, 0x22, 0x80, 0x13, 0x6a, 0x3f, 0x86, + 0xdf, 0x30, 0xee, 0xdf, 0x35, 0x5f, 0xbb, 0xa9, 0x88, 0x9e, 0x52, 0x2c, 0x53, 0x93, 0xd3, 0x24, 0x2b, 0x12, 0x88, + 0xda, 0xa8, 0x9a, 0x11, 0x3d, 0x71, 0x31, 0x1f, 0x15, 0xe1, 0xf3, 0x6a, 0xfd, 0x9f, 0x21, 0x7c, 0x46, 0xe1, 0x06, + 0x70, 0x79, 0xc5, 0xe5, 0x79, 0xf8, 0xec, 0x29, 0xdd, 0x9b, 0x7c, 0x73, 0x40, 0xf7, 0x0e, 0x9e, 0x3c, 0x23, 0x00, + 0x8b, 0x76, 0x79, 0x1e, 0x1e, 0x3c, 0x7b, 0x46, 0xf7, 0xbe, 0xfd, 0x96, 0xee, 0x4d, 0x9e, 0x1c, 0x34, 0xd2, 0x26, + 0xcf, 0xbe, 0xa5, 0x7b, 0xdf, 0x3c, 0x6d, 0xa4, 0x1d, 0x8c, 0x9f, 0xd1, 0xbd, 0xbf, 0x7f, 0x63, 0xd2, 0xfe, 0x06, + 0xd9, 0xbe, 0x3d, 0xc0, 0xff, 0x4c, 0xda, 0xe4, 0xd9, 0x13, 0xba, 0x37, 0x19, 0x43, 0x25, 0xcf, 0x5c, 0x25, 0xe3, + 0x09, 0x7c, 0xfc, 0x04, 0xfe, 0xfb, 0x1b, 0x09, 0x16, 0xb4, 0x92, 0x2c, 0x17, 0xa8, 0x3f, 0x43, 0x11, 0x27, 0xaa, + 0x26, 0x12, 0x1e, 0x62, 0x66, 0xf5, 0x4d, 0x1c, 0x06, 0xc4, 0xa5, 0x43, 0x41, 0x74, 0x6f, 0x3c, 0x7a, 0x46, 0x02, + 0x1f, 0x9e, 0xee, 0xc6, 0x07, 0x19, 0xcb, 0xc5, 0x3c, 0xfb, 0x2a, 0x37, 0xb1, 0x15, 0x3c, 0x00, 0xab, 0x8f, 0x7e, + 0xae, 0x4a, 0xce, 0xb3, 0xaf, 0x2a, 0xb9, 0x9b, 0xeb, 0xf7, 0x16, 0xa0, 0xbc, 0xbf, 0x6a, 0xd9, 0x4d, 0xa1, 0x42, + 0xa7, 0xb5, 0x46, 0x9f, 0x7d, 0xc4, 0xf4, 0xc1, 0xc0, 0xbb, 0x61, 0xff, 0xb4, 0x53, 0x4e, 0xeb, 0x1b, 0x8d, 0x42, + 0x8d, 0xca, 0x43, 0xc2, 0x8e, 0xa0, 0xe8, 0xc1, 0x00, 0x78, 0x02, 0x0f, 0xf7, 0xed, 0xdf, 0x2c, 0xe3, 0x63, 0x47, + 0x19, 0xbf, 0xa0, 0x0c, 0x01, 0x8d, 0x7a, 0x98, 0xdd, 0xf4, 0xb0, 0xd1, 0xad, 0x5e, 0xb2, 0x54, 0x27, 0x53, 0xd3, + 0x33, 0xd8, 0xd7, 0xba, 0x96, 0x7b, 0x46, 0x14, 0x2d, 0x2f, 0xf6, 0x52, 0x3e, 0xab, 0xd8, 0x4f, 0x4b, 0x54, 0x6f, + 0x45, 0x8d, 0x37, 0x32, 0x9b, 0x55, 0xec, 0x7b, 0xf3, 0x06, 0xb8, 0x19, 0xf6, 0xbb, 0x7a, 0xf2, 0x03, 0x67, 0x70, + 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, 0x5c, 0xd9, 0xff, 0x6a, 0xc8, 0x4b, 0x50, 0xb8, 0xd5, 0x2c, 0x6f, + 0xa7, 0x30, 0x84, 0x10, 0xfc, 0x71, 0xc9, 0x00, 0x70, 0x20, 0xc0, 0x60, 0xac, 0x65, 0x40, 0xcd, 0x96, 0x8f, 0x36, + 0x5c, 0xa9, 0x27, 0x81, 0x33, 0xb8, 0x90, 0x45, 0xc2, 0x4f, 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, 0xb0, 0x05, 0x91, 0x21, + 0x78, 0xb8, 0xfd, 0x6b, 0xa9, 0x02, 0x47, 0xf5, 0xfb, 0x5c, 0xfa, 0x6e, 0x4f, 0xc6, 0x8e, 0x1c, 0xa7, 0x7e, 0x2a, + 0x1c, 0xfc, 0x37, 0xa9, 0x6b, 0x63, 0xb9, 0x92, 0x32, 0xcb, 0xb2, 0xb0, 0xa3, 0x50, 0xcb, 0x3d, 0x2a, 0x0f, 0x92, + 0x2f, 0xe4, 0x10, 0xc9, 0x02, 0xa3, 0x50, 0x90, 0xe1, 0x84, 0x8a, 0xd1, 0x5a, 0x94, 0xcb, 0xec, 0xa2, 0x0a, 0x37, + 0x4a, 0xa1, 0xcc, 0x29, 0xfa, 0x76, 0x83, 0x03, 0x09, 0x89, 0xb2, 0xf2, 0x6d, 0xfc, 0x36, 0x44, 0xb0, 0x3a, 0xae, + 0x6d, 0xa1, 0xb8, 0xb7, 0x3f, 0x79, 0xda, 0xc5, 0x1f, 0x19, 0x17, 0x50, 0x17, 0x8b, 0x69, 0x38, 0xb1, 0xb1, 0x6f, + 0xdc, 0x17, 0x56, 0xd3, 0x03, 0x50, 0xdf, 0xa5, 0x12, 0x23, 0xa8, 0xaf, 0x8c, 0x7d, 0x6c, 0x8f, 0x31, 0x39, 0x83, + 0x58, 0xc3, 0x2a, 0x67, 0xa6, 0xfa, 0x46, 0xd8, 0x11, 0x00, 0x37, 0x42, 0x6b, 0x14, 0x04, 0x1e, 0xaf, 0x42, 0x3c, + 0x2f, 0x55, 0xf8, 0xd6, 0x8c, 0xd0, 0x31, 0x78, 0x53, 0xd9, 0x46, 0x66, 0xd2, 0x17, 0x0c, 0x9a, 0x63, 0x5b, 0x47, + 0x61, 0xb5, 0x95, 0x65, 0x47, 0x00, 0x37, 0x90, 0x1d, 0x9a, 0x8b, 0xe7, 0xac, 0x9a, 0x67, 0x8b, 0xc8, 0x04, 0x05, + 0x5c, 0x0a, 0xcb, 0xa0, 0x7d, 0xba, 0x47, 0xb6, 0xe3, 0x10, 0xba, 0xe1, 0x3e, 0x82, 0xf1, 0xb4, 0x9b, 0x82, 0x15, + 0x44, 0x23, 0xc4, 0xc3, 0x8c, 0x59, 0x7c, 0xaf, 0x34, 0xe5, 0xa9, 0x6a, 0x09, 0x04, 0x8e, 0x42, 0xa8, 0x8b, 0x5d, + 0xa3, 0x04, 0x97, 0xa9, 0x11, 0xcc, 0x60, 0xc7, 0x8e, 0xd4, 0x76, 0xc9, 0x39, 0x1d, 0xaa, 0x29, 0x2d, 0xf5, 0x94, + 0x6a, 0x5f, 0x43, 0x31, 0x2f, 0xd1, 0x43, 0x0f, 0x5c, 0x0f, 0xb4, 0x43, 0x5e, 0x49, 0x27, 0x26, 0x82, 0x4e, 0xab, + 0x4d, 0xd8, 0xb9, 0x91, 0x6e, 0x59, 0x8d, 0xbc, 0x63, 0x68, 0x76, 0xc4, 0x4b, 0x3f, 0x50, 0x17, 0x40, 0x84, 0xdc, + 0xdb, 0x22, 0x73, 0x44, 0xb3, 0xac, 0x7c, 0x05, 0x65, 0x71, 0xc4, 0xd6, 0x15, 0x70, 0x2d, 0x05, 0x93, 0x4b, 0x1e, + 0xf1, 0x14, 0x11, 0x01, 0x8f, 0x95, 0x76, 0x7d, 0xa7, 0x25, 0x84, 0x66, 0x29, 0x10, 0x37, 0x17, 0xc5, 0xb9, 0xb6, + 0x81, 0x2c, 0x80, 0xbe, 0xfd, 0x9c, 0x5d, 0x79, 0xe1, 0x60, 0x37, 0x57, 0x99, 0x78, 0xc1, 0x2f, 0x32, 0xc1, 0x53, + 0x04, 0xbb, 0xba, 0x35, 0x0f, 0xdc, 0xb1, 0x6d, 0x60, 0xf9, 0xf6, 0x1d, 0x2c, 0x98, 0x32, 0xd4, 0x4a, 0x89, 0x4c, + 0x44, 0x02, 0x32, 0xfb, 0xcc, 0xdd, 0x9b, 0x4c, 0xbc, 0x89, 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, 0x0e, 0xbf, 0xc4, 0x50, 0x2b, 0xe3, 0x7e, 0x1f, 0x24, 0x66, 0xd2, 0x36, 0x65, 0x26, 0x23, 0xa9, 0xd1, 0x42, + 0x2a, 0xca, 0x07, 0x13, 0xb2, 0xbb, 0x52, 0x2d, 0x23, 0x6a, 0xbf, 0x0a, 0xc5, 0x6c, 0x1c, 0x4d, 0x08, 0x9d, 0x74, + 0xac, 0x77, 0xd3, 0x5a, 0xc8, 0x34, 0x7a, 0x16, 0x79, 0x3e, 0x9d, 0x05, 0xab, 0xa6, 0xc5, 0x21, 0xe3, 0xd3, 0x62, + 0x30, 0x20, 0xda, 0xa5, 0x70, 0x83, 0xf5, 0x80, 0x29, 0x8d, 0x8b, 0xb7, 0x66, 0x5a, 0xfd, 0x4a, 0xaa, 0x90, 0xf4, + 0x9e, 0x01, 0x49, 0x26, 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, 0xde, 0xc6, 0x6f, 0x23, 0x7b, 0x59, 0xd0, 0x45, 0xbe, 0x40, 0x21, 0x6b, 0x1e, 0x86, 0xd5, 0xb0, 0x3d, + 0x88, 0x64, 0xbf, 0x3d, 0x09, 0x8d, 0xc6, 0xc0, 0x02, 0xd9, 0xa1, 0x11, 0xb8, 0x08, 0xad, 0xfc, 0xed, 0x10, 0x5c, + 0xb8, 0x2c, 0x22, 0xcb, 0x50, 0xc7, 0x6f, 0x6a, 0x37, 0x41, 0xf5, 0x0a, 0x9d, 0xa6, 0xb0, 0x2a, 0x65, 0x92, 0x0f, + 0xbf, 0x5e, 0xc9, 0x02, 0x33, 0x79, 0x5d, 0xf6, 0xe8, 0x6b, 0xbb, 0xbd, 0x03, 0x53, 0xb0, 0xee, 0x93, 0xf7, 0xf5, + 0xe3, 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, 0xa3, 0x4c, + 0xd6, 0xfe, 0xd5, 0x5d, 0xa4, 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, 0x86, 0x85, 0x57, 0xc3, + 0x4b, 0xb2, 0x1f, 0xa6, 0x83, 0x89, 0x12, 0x8c, 0xdd, 0xb1, 0x65, 0x19, 0xaa, 0xc4, 0xd5, 0xfe, 0x05, 0x79, 0x7c, + 0x41, 0x6f, 0xe9, 0x0d, 0x3d, 0xa5, 0x27, 0x40, 0xf8, 0xef, 0x0e, 0x27, 0x7c, 0x38, 0x79, 0xda, 0xef, 0xf7, 0xce, + 0xfb, 0xfd, 0xde, 0x99, 0x31, 0xa0, 0xd0, 0xbb, 0xe8, 0xb2, 0xa6, 0xfa, 0xd7, 0x55, 0xbd, 0x98, 0x9e, 0xa8, 0x8d, + 0x9b, 0xf0, 0x2c, 0x0f, 0xaf, 0xf6, 0xef, 0xc8, 0x10, 0x1f, 0x2f, 0x72, 0x29, 0x8b, 0xf0, 0x72, 0xff, 0x8e, 0xd0, + 0x93, 0x23, 0xd0, 0x9b, 0x62, 0x7d, 0x27, 0x8f, 0xef, 0x74, 0x6d, 0x84, 0xbe, 0x0c, 0x13, 0xd8, 0x26, 0xb7, 0xcc, + 0xde, 0xb5, 0x27, 0x63, 0x88, 0x65, 0x72, 0xe7, 0x95, 0x77, 0xf7, 0xf8, 0x96, 0xec, 0xdf, 0x82, 0xa7, 0xa8, 0x25, + 0x7f, 0xb3, 0xf0, 0x86, 0xb5, 0x6a, 0x78, 0x7c, 0x47, 0x4f, 0x5b, 0x8d, 0x78, 0x7c, 0x47, 0xa2, 0xf0, 0x86, 0x5d, + 0xd2, 0x53, 0x76, 0x45, 0xe8, 0x79, 0xbf, 0x7f, 0xd6, 0xef, 0xcb, 0x7e, 0xff, 0xa7, 0x38, 0x0c, 0xe3, 0x61, 0x41, + 0xf6, 0x25, 0xbd, 0xdb, 0x9f, 0xf0, 0x27, 0x64, 0x16, 0xea, 0xe6, 0xab, 0x05, 0x67, 0x55, 0xde, 0x2a, 0xd7, 0x1d, + 0x05, 0x6b, 0x85, 0x3b, 0xa6, 0x9e, 0x4e, 0xe8, 0x0d, 0x2b, 0xe8, 0x29, 0x8b, 0x49, 0x74, 0x0d, 0xad, 0x38, 0x9f, + 0x15, 0xd1, 0x0d, 0x3d, 0x65, 0x67, 0xb3, 0x38, 0x3a, 0xa5, 0x27, 0x2c, 0x1f, 0x4e, 0x20, 0xef, 0xe9, 0xf0, 0x86, + 0xec, 0x9f, 0x90, 0x28, 0x3c, 0xd1, 0xbf, 0xef, 0xe8, 0x25, 0x0f, 0x4f, 0xa8, 0x57, 0xcd, 0x09, 0x31, 0xd5, 0x37, + 0x6a, 0x3f, 0x21, 0x91, 0x3f, 0x98, 0x27, 0xd6, 0x9e, 0xe6, 0x91, 0xa3, 0x8d, 0x69, 0x19, 0x82, 0xbe, 0xb9, 0x0c, + 0x6f, 0x08, 0x99, 0x36, 0xc7, 0x0e, 0x06, 0x74, 0xf6, 0x28, 0x4a, 0x08, 0xbd, 0xf1, 0x4b, 0xbd, 0xc1, 0x31, 0x34, + 0x23, 0xa4, 0xd2, 0x4e, 0x31, 0x0d, 0xd7, 0xc1, 0x6b, 0x0d, 0xd6, 0x71, 0xde, 0xef, 0x87, 0xeb, 0x7e, 0x1f, 0x22, + 0xdd, 0x17, 0x33, 0x13, 0xdb, 0xcd, 0x91, 0x4d, 0x7a, 0x03, 0xda, 0xff, 0xd7, 0x83, 0x01, 0x74, 0xc6, 0x2b, 0x29, + 0xbc, 0x19, 0xbc, 0x7e, 0x7c, 0x47, 0x54, 0x1d, 0x05, 0x15, 0x32, 0x2c, 0xe8, 0x1b, 0x9a, 0x01, 0xe0, 0xd7, 0xeb, + 0xc1, 0x80, 0x44, 0xe6, 0x33, 0x32, 0x7d, 0x7d, 0x78, 0x32, 0x1d, 0x0c, 0x5e, 0x9b, 0x6d, 0xf2, 0x96, 0xdd, 0x53, + 0x0a, 0xac, 0xbf, 0xb3, 0x7e, 0xff, 0xed, 0x51, 0x4c, 0xce, 0x0b, 0x1e, 0x7f, 0x9c, 0x36, 0xdb, 0xf2, 0xd6, 0x45, + 0x55, 0x3b, 0xeb, 0xf7, 0xd7, 0xfd, 0xfe, 0x29, 0x60, 0x17, 0xcd, 0x9c, 0xaf, 0x27, 0x48, 0x5b, 0xe6, 0x8e, 0x22, + 0x69, 0x92, 0x43, 0x63, 0x68, 0x5b, 0xac, 0xda, 0x36, 0xeb, 0xc8, 0xc0, 0xe2, 0xa8, 0x59, 0x51, 0x5c, 0x93, 0x28, + 0xec, 0x9d, 0x6d, 0xb7, 0xa7, 0x8c, 0xb1, 0x98, 0x80, 0xf4, 0xc3, 0x7f, 0x7d, 0x5a, 0x37, 0x62, 0x88, 0x09, 0x89, + 0xcc, 0xe6, 0x66, 0x69, 0x0f, 0x81, 0x88, 0xc3, 0xa6, 0x7f, 0x6f, 0xee, 0xe5, 0xa2, 0x76, 0x7c, 0xeb, 0x2f, 0x00, + 0x42, 0x24, 0x59, 0xc8, 0x67, 0x38, 0x06, 0x65, 0x06, 0x40, 0xe6, 0x91, 0x9a, 0x79, 0x09, 0x20, 0xc0, 0x64, 0xbb, + 0x1d, 0x8d, 0xc7, 0x13, 0x5a, 0xb0, 0xd1, 0xdf, 0x9e, 0x3d, 0xae, 0x1e, 0x87, 0x41, 0x30, 0xc8, 0x48, 0x4b, 0x4f, + 0x61, 0x17, 0x6b, 0xb5, 0x0f, 0x46, 0xf0, 0x9a, 0x7d, 0xbc, 0xce, 0xbe, 0x98, 0x7d, 0x44, 0xc2, 0xda, 0x60, 0x1c, + 0xb9, 0x48, 0x5b, 0x7a, 0xbb, 0x7b, 0x18, 0x4c, 0x2e, 0xd2, 0xcf, 0xb0, 0x9d, 0x3e, 0xff, 0xe6, 0xc1, 0x78, 0xc2, + 0xc1, 0xe8, 0x2e, 0x0a, 0xfa, 0x4c, 0xdb, 0x6e, 0x2b, 0xff, 0x12, 0xf8, 0x16, 0x53, 0x41, 0xc7, 0x66, 0x59, 0xb8, + 0x41, 0x45, 0xd4, 0xd1, 0x32, 0xa8, 0x6a, 0x65, 0x3b, 0x07, 0xd4, 0x12, 0xab, 0x32, 0x71, 0x0b, 0x0c, 0x43, 0x86, + 0xba, 0xdc, 0xe3, 0xea, 0x5f, 0xbc, 0x90, 0x06, 0x3e, 0xc3, 0x89, 0x08, 0x3d, 0x6e, 0x8d, 0xfb, 0xdc, 0x9a, 0xf8, + 0x0c, 0xb7, 0x56, 0x22, 0x89, 0x35, 0xb0, 0xa4, 0xe6, 0x72, 0x94, 0xb0, 0xa3, 0x92, 0xf1, 0x59, 0x19, 0x25, 0x34, + 0x86, 0x07, 0xc9, 0xc4, 0x4c, 0x46, 0x09, 0xda, 0x27, 0xba, 0x08, 0x83, 0x7f, 0x01, 0x66, 0x3f, 0xcd, 0xe1, 0xaf, + 0x24, 0xd3, 0xe4, 0x10, 0x02, 0x42, 0x1c, 0x8e, 0x67, 0x71, 0x38, 0x26, 0x51, 0x72, 0x04, 0x4f, 0xf0, 0x5f, 0x11, + 0x8e, 0x49, 0xad, 0xef, 0x30, 0x52, 0x5d, 0x6e, 0x13, 0x06, 0x70, 0x65, 0xe3, 0xd9, 0x24, 0xb2, 0xd2, 0x5d, 0xf9, + 0x78, 0x34, 0x7e, 0x46, 0xa6, 0x71, 0x28, 0x07, 0x09, 0xa1, 0xe0, 0xdd, 0x1b, 0x96, 0xc3, 0x44, 0xc3, 0xb3, 0x01, + 0x9b, 0x57, 0x3a, 0x36, 0x4f, 0xc2, 0x09, 0x08, 0xc3, 0x84, 0x1c, 0xeb, 0x3d, 0x48, 0x29, 0xfa, 0x3c, 0xc7, 0x7e, + 0xea, 0x23, 0x08, 0xb3, 0xa3, 0x96, 0x8a, 0xaf, 0x00, 0xe8, 0x12, 0x07, 0x87, 0xda, 0x33, 0x5f, 0xcc, 0xc2, 0xd2, + 0xa3, 0x52, 0xa6, 0xba, 0x7d, 0xd1, 0xa0, 0xfc, 0xa6, 0x41, 0xfb, 0x82, 0x0c, 0x26, 0xb4, 0x3c, 0x9a, 0xf0, 0x27, + 0x10, 0xc0, 0xa3, 0x11, 0xf1, 0x4b, 0xe1, 0xc4, 0x40, 0x78, 0x15, 0x64, 0xa0, 0xd2, 0x5a, 0x35, 0x66, 0x64, 0x2b, + 0xde, 0x83, 0x30, 0x29, 0x7b, 0x37, 0x72, 0x9d, 0xa7, 0x10, 0x15, 0x6c, 0x9d, 0x57, 0x7b, 0x97, 0x60, 0xc9, 0x1e, + 0x57, 0x10, 0x27, 0x6c, 0xbd, 0x02, 0xec, 0xdc, 0x47, 0x9b, 0xb2, 0xde, 0x53, 0xdf, 0xed, 0x61, 0xcb, 0xe1, 0x55, + 0x25, 0xf7, 0x26, 0xe3, 0xf1, 0x78, 0xf4, 0x07, 0x1c, 0x1d, 0x40, 0x68, 0x49, 0x64, 0xf8, 0x64, 0x80, 0xc6, 0x5d, + 0x57, 0xdc, 0x1b, 0x17, 0x8a, 0xb2, 0xd2, 0xc9, 0x84, 0x80, 0xf8, 0xd9, 0xf4, 0x0d, 0xf6, 0x15, 0xd7, 0xf1, 0x4f, + 0x76, 0x3f, 0x31, 0x2b, 0x5a, 0xad, 0xd4, 0xd1, 0xbb, 0x93, 0xd3, 0xd7, 0x1f, 0x5e, 0xff, 0xf6, 0xf2, 0xec, 0xf5, + 0xdb, 0x57, 0xaf, 0xdf, 0xbe, 0xfe, 0xf0, 0xcf, 0x07, 0x18, 0x6c, 0xdf, 0x56, 0xc4, 0x8e, 0xbd, 0x77, 0x8f, 0xf1, + 0x6a, 0xf1, 0x85, 0xb3, 0x07, 0xee, 0x16, 0x0b, 0xb0, 0x09, 0x86, 0x5b, 0x10, 0x54, 0x33, 0x1a, 0x95, 0xbe, 0x27, + 0x20, 0xa3, 0x51, 0x21, 0x1b, 0x0f, 0x2b, 0xb6, 0x42, 0x2e, 0xde, 0x31, 0x1c, 0x7c, 0x64, 0x7f, 0x2b, 0xce, 0x84, + 0xdb, 0xd1, 0xd6, 0xac, 0x08, 0xf8, 0x7c, 0xad, 0x45, 0xe5, 0x71, 0x21, 0x6a, 0x6f, 0xdb, 0xe7, 0x90, 0x50, 0x8f, + 0xc8, 0x75, 0xf0, 0xbe, 0x0d, 0xb2, 0xc7, 0x47, 0xde, 0x93, 0xf2, 0x0c, 0xf5, 0x39, 0x1a, 0x3e, 0x6a, 0x3c, 0xa3, + 0x13, 0x73, 0x6d, 0x74, 0xa8, 0x67, 0x05, 0xec, 0x6f, 0x25, 0xc6, 0x86, 0x68, 0x0f, 0x29, 0x62, 0x7d, 0x38, 0xdd, + 0xef, 0xee, 0xcd, 0xe8, 0x7b, 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, 0xf7, 0x5c, 0x29, 0x9a, 0xb7, 0x2e, 0xb0, 0x07, 0x6a, 0x5e, 0xc7, 0x4b, 0x16, 0x02, 0x36, 0xe3, + 0xbe, 0x5d, 0x24, 0xce, 0xef, 0x9d, 0x4e, 0xc8, 0xfe, 0xc1, 0x94, 0x0f, 0x59, 0x49, 0xc5, 0x80, 0x95, 0xf5, 0x0e, + 0x35, 0xe7, 0x6d, 0x42, 0x2e, 0x76, 0x69, 0xb8, 0x18, 0xf2, 0x87, 0x2e, 0x49, 0x1f, 0x78, 0xc3, 0xa1, 0xda, 0x36, + 0x17, 0x43, 0x9a, 0x72, 0xba, 0x4b, 0x65, 0x40, 0x88, 0x74, 0x15, 0x57, 0xa4, 0xd6, 0x47, 0x55, 0xea, 0x24, 0x1d, + 0xd7, 0xd9, 0xe6, 0x33, 0x97, 0x6c, 0x75, 0xbb, 0xf6, 0xaf, 0xd5, 0xed, 0x0b, 0x33, 0x90, 0xbf, 0x3f, 0x11, 0xd5, + 0xc4, 0x40, 0x74, 0x01, 0x15, 0xfc, 0x13, 0xbc, 0x3c, 0x79, 0xa4, 0x15, 0xa0, 0xf7, 0x9d, 0x1d, 0x5d, 0x7b, 0xbc, + 0x31, 0x8b, 0xad, 0x25, 0xce, 0x59, 0xe5, 0x3b, 0xcb, 0xab, 0xb2, 0x15, 0xba, 0x8e, 0x60, 0xbf, 0x84, 0x1d, 0x7d, + 0xf7, 0xb6, 0x01, 0x10, 0xa5, 0xb0, 0x72, 0x67, 0xbf, 0xf0, 0xce, 0x7e, 0x61, 0xcf, 0x7e, 0xbb, 0x09, 0x94, 0x0f, + 0x2b, 0xb4, 0xec, 0x95, 0x14, 0x95, 0x69, 0xf2, 0xb8, 0xa9, 0xcb, 0x42, 0x5a, 0xcc, 0xf7, 0x2d, 0xed, 0x7a, 0x3a, + 0xa6, 0x12, 0xd5, 0x23, 0x3f, 0x60, 0xab, 0xf6, 0x4b, 0xf2, 0xf0, 0x3d, 0xf3, 0x7f, 0xf6, 0x06, 0x79, 0xdf, 0xdd, + 0xee, 0xff, 0xe6, 0x42, 0x07, 0xb7, 0xb5, 0x54, 0x78, 0xea, 0xea, 0xb8, 0xc0, 0xbb, 0x5a, 0xfa, 0xf0, 0x5d, 0xed, + 0x5d, 0xa6, 0x97, 0x5d, 0x05, 0xa8, 0x41, 0x62, 0x7d, 0xc5, 0x8b, 0x2c, 0xa9, 0xad, 0x42, 0xe3, 0x84, 0x43, 0x68, + 0x0f, 0xef, 0xe0, 0x02, 0x39, 0x2c, 0x21, 0xf4, 0x63, 0x65, 0x04, 0x80, 0x3e, 0x8b, 0x7d, 0xc2, 0xc3, 0x8c, 0x0c, + 0x7c, 0x89, 0x5f, 0x29, 0x7d, 0x71, 0xf1, 0xfe, 0x4e, 0x66, 0x82, 0x5e, 0x25, 0x36, 0xbb, 0x94, 0xed, 0x98, 0x1f, + 0xfe, 0x17, 0x18, 0x0d, 0xc2, 0x6b, 0x4b, 0xb6, 0x2f, 0x3a, 0x66, 0xb9, 0x82, 0xa3, 0xb6, 0x74, 0x65, 0x96, 0xad, + 0xeb, 0x67, 0x35, 0xcc, 0xf4, 0x99, 0x72, 0x02, 0xb2, 0x2f, 0xe4, 0xee, 0xa7, 0xba, 0x62, 0x41, 0x8e, 0x26, 0xe3, + 0x29, 0x11, 0x83, 0x41, 0x2b, 0xf9, 0x10, 0x93, 0x87, 0xc3, 0x1d, 0xe6, 0x52, 0xe8, 0x7e, 0x78, 0x7d, 0x80, 0xfa, + 0x1a, 0x5b, 0x92, 0x6c, 0x2a, 0xf6, 0x17, 0x98, 0xc5, 0x02, 0x71, 0x74, 0xf0, 0x8b, 0xf3, 0x05, 0x80, 0x2c, 0xc3, + 0x32, 0xd3, 0xc2, 0xa2, 0x32, 0x55, 0x3e, 0xb2, 0x05, 0x93, 0x87, 0xe3, 0x99, 0xdf, 0x73, 0xc7, 0xe0, 0x10, 0x12, + 0x4d, 0xac, 0xf1, 0x8b, 0x9f, 0x05, 0xe3, 0x38, 0x94, 0x47, 0xb2, 0xf1, 0x5d, 0x49, 0xa2, 0xb1, 0x31, 0x55, 0xd6, + 0x57, 0x89, 0x6a, 0x98, 0x90, 0xc7, 0x05, 0xd9, 0x2f, 0xe8, 0xd2, 0x1f, 0x4b, 0x4c, 0xdf, 0x8f, 0xf7, 0x27, 0x63, + 0xf2, 0x38, 0x7e, 0x3c, 0x31, 0x70, 0xc3, 0x7e, 0x8e, 0x7c, 0xb8, 0x24, 0xfb, 0xcd, 0x2a, 0xc1, 0x14, 0xd5, 0xf4, + 0xcc, 0xaf, 0x24, 0x19, 0x2c, 0x07, 0xe9, 0xe3, 0x56, 0x5e, 0xac, 0x55, 0x8f, 0xf7, 0xfa, 0x90, 0x4f, 0x89, 0x68, + 0xdc, 0x18, 0xd6, 0xf4, 0x2a, 0xfe, 0x53, 0x16, 0x51, 0x29, 0x01, 0x91, 0x10, 0xd4, 0xdb, 0xd9, 0x45, 0x96, 0xc4, + 0x22, 0x8d, 0xd2, 0x9a, 0xd0, 0xf4, 0x88, 0x4d, 0xc6, 0xb3, 0x94, 0xa5, 0x87, 0x93, 0x67, 0xb3, 0xc9, 0xb3, 0xe8, + 0x60, 0x1c, 0xa5, 0x83, 0x01, 0x24, 0x1f, 0x8c, 0xc1, 0xc5, 0x0e, 0x7e, 0xb3, 0x03, 0x18, 0xba, 0x23, 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, 0x0b, 0xf9, 0xff, 0xe3, 0x86, 0x71, 0xdf, 0x5d, 0xc2, 0x2c, + 0xae, 0xeb, 0x6c, 0xb4, 0x2a, 0x64, 0x25, 0xe1, 0x36, 0xa1, 0x44, 0x61, 0xa3, 0x78, 0xb5, 0xca, 0xb5, 0x8b, 0xd8, + 0xbc, 0xa2, 0x00, 0xee, 0x02, 0x71, 0x8a, 0x81, 0x85, 0x36, 0x06, 0x72, 0x9f, 0x78, 0x21, 0x99, 0x55, 0xfb, 0x98, + 0x7b, 0xe4, 0x9f, 0x21, 0x18, 0xa3, 0x8a, 0xa3, 0xf1, 0x4c, 0x61, 0x5d, 0x7c, 0x4e, 0xde, 0xfb, 0x6f, 0x1c, 0x45, + 0xf6, 0x68, 0x06, 0x3d, 0x41, 0xe4, 0x3c, 0xe2, 0xec, 0xc9, 0xe4, 0x65, 0xe0, 0x7e, 0x06, 0x2b, 0xfd, 0x75, 0xb7, + 0x19, 0x6b, 0xdb, 0xa3, 0x7b, 0x61, 0x84, 0xa2, 0x9f, 0xf0, 0x9d, 0xa9, 0x17, 0x70, 0x09, 0xd5, 0xc0, 0xae, 0x2f, + 0x2f, 0x79, 0x09, 0x20, 0x42, 0x99, 0xe8, 0xf7, 0x7b, 0x7f, 0x1a, 0x68, 0xd2, 0x92, 0x17, 0x6f, 0x32, 0x61, 0x9d, + 0x71, 0xa0, 0xa9, 0x40, 0xfd, 0x3f, 0x56, 0xf6, 0x99, 0x8e, 0xc9, 0xcc, 0x7f, 0x1c, 0x4e, 0x48, 0xd4, 0x7c, 0x4d, + 0x3e, 0x73, 0x9a, 0x7e, 0xe6, 0x8a, 0xf6, 0x1f, 0xc8, 0xcc, 0x0d, 0x87, 0x0c, 0xf5, 0x97, 0x8e, 0x79, 0x32, 0x7a, + 0x9d, 0x98, 0x1d, 0x09, 0x56, 0xcd, 0x20, 0x0a, 0x7b, 0x01, 0x0f, 0xea, 0x5a, 0x16, 0x4f, 0x61, 0xf6, 0x41, 0x8d, + 0x28, 0x0e, 0xd9, 0x78, 0x16, 0xca, 0x70, 0x02, 0xf6, 0xbd, 0x93, 0x31, 0xdc, 0x07, 0x64, 0xf8, 0xb1, 0x0a, 0xb1, + 0x73, 0x90, 0xf6, 0xb1, 0x42, 0xc5, 0x04, 0x40, 0x04, 0x42, 0xde, 0x7e, 0x5f, 0xaa, 0x24, 0x7c, 0x5d, 0x62, 0x4a, + 0xa1, 0x3e, 0xf8, 0x4f, 0xa4, 0xea, 0x8e, 0xe9, 0x57, 0xeb, 0xc7, 0x9f, 0x09, 0xc5, 0xa7, 0xbb, 0x94, 0xf8, 0x16, + 0x82, 0x3b, 0x4b, 0xd0, 0x41, 0x54, 0x68, 0xc6, 0xf6, 0x30, 0xbf, 0x2b, 0xee, 0xe7, 0x77, 0xc5, 0xff, 0x3b, 0x7e, + 0x57, 0x3c, 0xc4, 0x18, 0x56, 0x16, 0x1a, 0x7e, 0x16, 0x8c, 0x83, 0xe8, 0x3f, 0xe7, 0x13, 0xef, 0xe5, 0xa9, 0xaf, + 0x32, 0x31, 0xbd, 0x87, 0x69, 0xf6, 0x09, 0x0a, 0xc2, 0x2a, 0xee, 0xd2, 0x93, 0x75, 0x65, 0x6f, 0xad, 0x64, 0x88, + 0x79, 0x1e, 0x60, 0x8d, 0xc2, 0xca, 0x03, 0xba, 0x47, 0xd5, 0x06, 0x71, 0x22, 0x78, 0x18, 0x33, 0x2b, 0x7d, 0xdf, + 0x6e, 0x8d, 0x0a, 0xf3, 0x41, 0x2e, 0x0a, 0xb2, 0x9b, 0x8f, 0x67, 0xe3, 0x28, 0xc4, 0x06, 0xfc, 0xc7, 0x8c, 0x55, + 0x43, 0x36, 0xdf, 0xc9, 0x48, 0xed, 0x98, 0x3c, 0x4d, 0x76, 0x49, 0xef, 0x80, 0x77, 0xc8, 0xcf, 0xeb, 0x8f, 0x61, + 0x21, 0x0d, 0xbf, 0x25, 0x2f, 0xe3, 0x22, 0xab, 0x96, 0x57, 0x59, 0x82, 0x4c, 0x17, 0xbc, 0xf8, 0x62, 0xa6, 0xcb, + 0xfb, 0x58, 0x1f, 0x30, 0x9e, 0x52, 0xbc, 0x6e, 0x88, 0xd2, 0xd7, 0x2d, 0xcf, 0x0a, 0x75, 0x79, 0x52, 0x31, 0xdb, + 0xb3, 0x12, 0x9c, 0x4e, 0xc1, 0x04, 0x5f, 0xff, 0x74, 0xbd, 0x8f, 0x01, 0x17, 0x14, 0x6a, 0x4e, 0x0b, 0xb9, 0x32, + 0x58, 0x4e, 0x16, 0xba, 0x13, 0x30, 0x43, 0xa5, 0xc0, 0x0b, 0x14, 0xfc, 0x45, 0x03, 0x23, 0xfa, 0xca, 0xfd, 0x26, + 0x03, 0x83, 0x74, 0x69, 0x4e, 0x84, 0xb1, 0xe3, 0x76, 0x8a, 0xb4, 0x15, 0xe5, 0x8c, 0xb3, 0xf7, 0xea, 0x4a, 0x01, + 0x06, 0x78, 0x9b, 0x9b, 0xe8, 0x3c, 0x41, 0xaf, 0x05, 0xa5, 0xf3, 0x06, 0xee, 0x66, 0x19, 0x19, 0xe1, 0xe2, 0xe3, + 0xca, 0x63, 0xc1, 0x3d, 0xfb, 0x85, 0x58, 0x1a, 0xcd, 0x34, 0x18, 0xb3, 0x79, 0xc1, 0x02, 0x85, 0x0a, 0x14, 0x58, + 0xce, 0xb4, 0xa5, 0x69, 0x35, 0xe4, 0xfb, 0x07, 0x68, 0x6d, 0x5a, 0x0d, 0xf8, 0xfe, 0x41, 0x1d, 0x65, 0x87, 0x90, + 0xe5, 0xc8, 0xcf, 0xa0, 0x5e, 0xd7, 0x91, 0x49, 0x31, 0xd9, 0xfd, 0xfa, 0x52, 0x7f, 0x54, 0x37, 0xe0, 0xfa, 0x01, + 0x08, 0x60, 0x03, 0x70, 0x08, 0x54, 0x83, 0xa5, 0x11, 0xc1, 0xa2, 0x4c, 0xa1, 0x7d, 0x0d, 0xbd, 0x37, 0x1a, 0xfe, + 0x0b, 0xdc, 0x45, 0xe4, 0xca, 0xff, 0x04, 0x81, 0xbf, 0xa2, 0x4c, 0x2b, 0x53, 0xfc, 0x4f, 0xb4, 0x7a, 0x85, 0x72, + 0xd6, 0xb4, 0xe6, 0x83, 0x68, 0x4d, 0x84, 0x6a, 0xc6, 0x10, 0xfc, 0x5b, 0x59, 0xa6, 0x2d, 0x55, 0x95, 0xfa, 0xd0, + 0x78, 0xad, 0x15, 0xce, 0xf2, 0x71, 0xe4, 0xbd, 0xc6, 0xd0, 0xb1, 0x89, 0xb3, 0x94, 0x53, 0xa9, 0xb3, 0x4f, 0xfb, + 0x32, 0x72, 0x80, 0xd3, 0x09, 0x1b, 0x4f, 0x93, 0x43, 0x39, 0x4d, 0x1c, 0x64, 0x7e, 0xce, 0x30, 0xb2, 0xaa, 0x01, + 0x61, 0x51, 0x36, 0x94, 0xb6, 0x00, 0x93, 0x9c, 0x10, 0x32, 0xc5, 0x50, 0x14, 0xf9, 0x48, 0xf7, 0xc3, 0x7a, 0xb3, + 0xba, 0x2f, 0xde, 0x69, 0x80, 0xd3, 0x30, 0x81, 0x40, 0xe0, 0x45, 0x7c, 0x93, 0x89, 0x4b, 0xf0, 0x18, 0x1e, 0xc0, + 0x97, 0xe0, 0x26, 0x97, 0xb2, 0xdf, 0xab, 0x30, 0xc7, 0xb5, 0x05, 0x0c, 0x1a, 0xac, 0x1e, 0x44, 0x87, 0x4b, 0x69, + 0xb3, 0xab, 0x00, 0xb1, 0x31, 0x85, 0x58, 0x16, 0x6c, 0x6d, 0xd9, 0xb3, 0xef, 0x55, 0xd3, 0xd0, 0x3a, 0xe1, 0x58, + 0x5c, 0xe6, 0x10, 0x45, 0x65, 0x10, 0x83, 0x3b, 0x92, 0xc7, 0xe7, 0x3d, 0x12, 0xe1, 0x05, 0x01, 0xb7, 0xb2, 0x58, + 0x86, 0x2b, 0xba, 0x1c, 0xdd, 0xd2, 0xf5, 0xe8, 0x86, 0x8e, 0xe9, 0xe4, 0xef, 0x63, 0xb0, 0xc8, 0xd6, 0xa9, 0x77, + 0x74, 0x3d, 0x5a, 0xd2, 0x6f, 0xc7, 0xf4, 0xe0, 0x6f, 0x60, 0xc2, 0x87, 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, 0xae, 0xf8, 0x55, 0xc9, 0x52, + 0xd8, 0x16, 0xb0, 0x7c, 0x3d, 0xaf, 0xa8, 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, 0x8e, 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, 0xca, 0xd3, 0xf6, + 0x75, 0xb0, 0xb1, 0xaa, 0xe8, 0x86, 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, 0xbe, 0x87, 0x88, 0xca, 0x50, 0xde, 0xe0, 0x1f, 0x18, 0x3c, 0x99, 0xad, 0xd2, 0x30, + 0x19, 0xdd, 0xd1, 0x78, 0xb4, 0x44, 0x38, 0x18, 0xb6, 0x4e, 0x15, 0xde, 0xfa, 0x05, 0xa4, 0xdf, 0xd2, 0x78, 0x74, + 0x43, 0x53, 0x6b, 0x73, 0x6a, 0xa0, 0xae, 0x7a, 0x63, 0x7a, 0x1b, 0xc1, 0xeb, 0xbb, 0x68, 0x49, 0x61, 0x2b, 0x1d, + 0xe7, 0xd9, 0xa5, 0x88, 0x52, 0x8a, 0x08, 0x84, 0x6b, 0x44, 0x0e, 0x5c, 0x6a, 0xb4, 0xc1, 0xf5, 0x00, 0xca, 0xd0, + 0x70, 0x81, 0xcb, 0x41, 0x3c, 0x5a, 0x7a, 0x64, 0x6a, 0xa9, 0x2f, 0xb2, 0x08, 0x1f, 0xed, 0x6c, 0xb4, 0x14, 0xcf, + 0x88, 0x85, 0x71, 0x05, 0x43, 0xa8, 0x0b, 0x2b, 0x4d, 0x41, 0xd2, 0x05, 0x8e, 0xec, 0x85, 0x45, 0x15, 0x6e, 0xc0, + 0xb4, 0xe8, 0x0e, 0xcc, 0xa3, 0x40, 0xe1, 0xe0, 0x12, 0xa4, 0x9f, 0x50, 0xb6, 0x73, 0x94, 0x26, 0x87, 0x37, 0x41, + 0xe9, 0xce, 0x04, 0x21, 0xed, 0xea, 0x26, 0x5b, 0xd2, 0x37, 0xd8, 0xde, 0xa1, 0x53, 0x51, 0x41, 0xf5, 0xb9, 0x05, + 0x93, 0x25, 0x1b, 0x84, 0x2d, 0x61, 0x7a, 0xa6, 0xd7, 0x80, 0x3d, 0xbd, 0x7f, 0xb0, 0x33, 0xdf, 0xc5, 0xec, 0xd3, + 0x7e, 0x19, 0x8d, 0x95, 0x05, 0x6f, 0x6e, 0x89, 0xdd, 0x92, 0x8d, 0xa7, 0xcb, 0xc3, 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, + 0x96, 0x69, 0x98, 0xe2, 0x22, 0x30, 0x29, 0xfd, 0x7e, 0x98, 0xb3, 0x94, 0x78, 0xd0, 0xa1, 0xee, 0xd4, 0x4e, 0x7d, + 0x21, 0x08, 0xf0, 0x48, 0xea, 0x1c, 0x9b, 0xfc, 0x7d, 0x3c, 0x0b, 0xd4, 0x40, 0x04, 0x51, 0x76, 0x88, 0x8f, 0x18, + 0xb8, 0x28, 0xd2, 0x71, 0x3b, 0x5d, 0x11, 0x17, 0xbb, 0xc7, 0x2c, 0xc4, 0x49, 0xc2, 0x5c, 0xb3, 0x6c, 0xc8, 0xaa, + 0x08, 0x13, 0x74, 0x61, 0x60, 0x96, 0x37, 0x64, 0xd5, 0xfe, 0x01, 0x44, 0x6a, 0xb5, 0x65, 0xac, 0xba, 0xca, 0xf8, + 0x16, 0x80, 0xac, 0x19, 0x63, 0x07, 0x7f, 0x1b, 0xcf, 0xd4, 0x37, 0x51, 0xc8, 0x8f, 0x0e, 0xfe, 0x06, 0xc9, 0x87, + 0xdf, 0x22, 0x33, 0x07, 0xc9, 0x8d, 0x82, 0x2e, 0x9b, 0xb3, 0xae, 0xa1, 0x34, 0x71, 0xed, 0x95, 0x7a, 0xed, 0x49, + 0xb3, 0xf6, 0x0a, 0x74, 0xa7, 0x36, 0xbc, 0x87, 0xb2, 0x9d, 0x05, 0x13, 0x74, 0x34, 0xbb, 0x03, 0x1d, 0xbc, 0x53, + 0x04, 0xbd, 0x4c, 0x42, 0xe3, 0x11, 0xaa, 0x8c, 0x7a, 0x61, 0x47, 0x76, 0xb3, 0x2e, 0x99, 0x67, 0xc0, 0x1c, 0xdb, + 0x73, 0x48, 0x0c, 0x73, 0x75, 0x50, 0xa7, 0xac, 0x1c, 0xe6, 0x78, 0x00, 0xaf, 0x99, 0x1c, 0x8a, 0x41, 0xae, 0x51, + 0xbe, 0x2f, 0x58, 0x31, 0x2c, 0x07, 0xb9, 0xe6, 0x66, 0xa6, 0xcd, 0xd8, 0xb4, 0x89, 0x0e, 0xcf, 0xbc, 0x62, 0x47, + 0xab, 0x1e, 0xf0, 0xb1, 0xe0, 0xc9, 0xec, 0x7b, 0x3e, 0xbe, 0x01, 0x4e, 0x66, 0x73, 0x1b, 0x2d, 0xe9, 0x5d, 0x94, + 0xd2, 0x9b, 0x68, 0x4d, 0x97, 0xd1, 0x85, 0x31, 0x31, 0x4e, 0x6a, 0x38, 0x07, 0xa0, 0x55, 0x00, 0x89, 0xa7, 0x7e, + 0xbd, 0xe7, 0x49, 0x15, 0x2e, 0x69, 0x0a, 0x6e, 0xc3, 0xbe, 0x7d, 0xe6, 0x95, 0x2f, 0x91, 0xda, 0x20, 0xc6, 0x9a, + 0x35, 0x54, 0xdc, 0x78, 0xeb, 0x3e, 0x12, 0x35, 0xec, 0x5c, 0x17, 0x9b, 0xa8, 0x1a, 0x4e, 0xa6, 0x25, 0x20, 0xb6, + 0x96, 0xc3, 0xa1, 0x3b, 0x42, 0x76, 0x8f, 0x1f, 0x1d, 0xe8, 0xb9, 0x27, 0x2d, 0xb6, 0x6d, 0xcb, 0x1f, 0x18, 0xc2, + 0x94, 0x7e, 0xfe, 0xc8, 0x07, 0xc4, 0x8a, 0x4b, 0x38, 0x1b, 0x81, 0x3a, 0x5a, 0xa1, 0xd3, 0xef, 0x55, 0x58, 0xe8, + 0x03, 0x7c, 0x73, 0x1b, 0x25, 0xf4, 0x2e, 0xca, 0x3d, 0xb2, 0xb6, 0xac, 0x99, 0x9c, 0x9e, 0x65, 0x21, 0x6f, 0x1f, + 0xe8, 0xe5, 0x02, 0x40, 0xb4, 0x06, 0xb1, 0x2f, 0x75, 0x3d, 0x00, 0xa7, 0x21, 0x34, 0x09, 0x8d, 0xe0, 0xaa, 0x82, + 0x30, 0x02, 0xae, 0x24, 0xfc, 0x0d, 0x26, 0x2a, 0xf0, 0x05, 0xb8, 0xc8, 0xa4, 0x69, 0xce, 0x83, 0xda, 0x1f, 0xc9, + 0xd3, 0xa2, 0xed, 0xed, 0x0a, 0xa3, 0x09, 0xc6, 0x9e, 0x68, 0x9f, 0x47, 0xca, 0x51, 0x5c, 0x24, 0x61, 0x36, 0xba, + 0x55, 0xe7, 0x39, 0xcd, 0x46, 0x77, 0xfa, 0x57, 0x45, 0xc7, 0xf4, 0x3b, 0x1d, 0xd0, 0x46, 0x49, 0xdf, 0x3a, 0xce, + 0x06, 0xb4, 0x5e, 0x2c, 0x8d, 0xff, 0xb5, 0x1c, 0xdd, 0x52, 0x39, 0xba, 0xf3, 0x2d, 0xa9, 0x26, 0xd3, 0xe2, 0x50, + 0xa0, 0x21, 0x55, 0xe7, 0xf7, 0x05, 0xf0, 0x73, 0xa5, 0xf1, 0x9d, 0x36, 0xdf, 0x7b, 0xed, 0x3f, 0xef, 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, 0xcb, 0xed, 0x56, 0xc5, 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, 0x5c, 0xd7, 0xcf, 0xda, 0xd4, 0xe8, 0x15, 0x58, 0xf8, + 0x6e, 0x94, 0x79, 0x24, 0xb7, 0x08, 0xa9, 0x0a, 0xac, 0xd4, 0x2d, 0x24, 0x98, 0x7f, 0x25, 0x67, 0xab, 0x32, 0x5f, + 0x3d, 0xf2, 0xa0, 0x9c, 0x4d, 0x4f, 0x7f, 0x43, 0x82, 0x76, 0xd7, 0x91, 0xe6, 0xf1, 0x16, 0x1d, 0x3e, 0xbb, 0xd6, + 0x12, 0x73, 0x27, 0x51, 0xf1, 0x7c, 0x0a, 0xd8, 0xea, 0x45, 0x76, 0xa5, 0x7c, 0xac, 0x76, 0x71, 0xfc, 0xcc, 0xf9, + 0x13, 0x57, 0xe1, 0x5a, 0x34, 0x94, 0x20, 0xe0, 0xcd, 0x61, 0xec, 0x0a, 0x55, 0x40, 0x43, 0x73, 0x03, 0xc7, 0xb9, + 0x1a, 0x56, 0x9a, 0x80, 0x69, 0x29, 0x8f, 0x0e, 0x70, 0x68, 0xf2, 0xa8, 0xdd, 0x34, 0xac, 0x0c, 0x5d, 0x6b, 0xf4, + 0xb9, 0xad, 0x74, 0xc6, 0x9b, 0x0d, 0xdf, 0x3f, 0x18, 0x54, 0xf8, 0x93, 0x34, 0x47, 0xa3, 0x9d, 0x1b, 0xee, 0x34, + 0x02, 0x33, 0x57, 0x72, 0x45, 0x76, 0x47, 0xc9, 0xcb, 0xef, 0xe9, 0x85, 0x05, 0xf4, 0xe7, 0x3f, 0x17, 0x13, 0x4e, + 0x5a, 0x62, 0x42, 0xb4, 0x74, 0xd0, 0xa2, 0x83, 0x1d, 0xe5, 0x95, 0x7d, 0x89, 0x97, 0xce, 0xf1, 0xbf, 0xaf, 0xc7, + 0xda, 0x55, 0x20, 0xb4, 0x3a, 0xb9, 0xdf, 0x9e, 0x2c, 0x10, 0x35, 0xa0, 0x9a, 0x5d, 0x95, 0xa3, 0x4c, 0x3b, 0x2b, + 0xb2, 0x69, 0xc8, 0x5c, 0x77, 0xb3, 0x34, 0x6c, 0x26, 0x3b, 0x16, 0x96, 0x19, 0x06, 0x6b, 0xa7, 0x8a, 0x3e, 0x07, + 0x2d, 0x3f, 0x82, 0x17, 0x4d, 0xe5, 0x99, 0xcf, 0x66, 0x19, 0xf1, 0x02, 0x9d, 0x73, 0x2a, 0x16, 0x4d, 0xe9, 0x58, + 0xb9, 0xdd, 0x96, 0x68, 0x2c, 0x51, 0x46, 0x41, 0x50, 0xdb, 0x20, 0xec, 0xba, 0x74, 0x4f, 0xfa, 0xb4, 0x8b, 0x4f, + 0x2b, 0xd0, 0xf7, 0xf8, 0x3e, 0x03, 0x89, 0xa9, 0x27, 0x79, 0xa8, 0x1a, 0xcd, 0xd1, 0xc9, 0xb3, 0x38, 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, 0x07, 0xd4, 0xa9, 0x8b, 0x75, 0x1b, 0x50, 0xb2, 0xe4, 0xdd, 0x3a, 0x3d, 0xb1, 0xd2, 0x77, 0xfb, + 0xe1, 0xce, 0x3c, 0x6a, 0x76, 0x77, 0xbb, 0x9d, 0x90, 0xb6, 0x7d, 0x30, 0xde, 0x97, 0xb0, 0x10, 0xe7, 0x1d, 0xb6, + 0xf7, 0x7d, 0x58, 0x3d, 0xe6, 0x83, 0x5f, 0x70, 0x9c, 0x61, 0xf4, 0x33, 0x65, 0xe8, 0xf3, 0xaa, 0x90, 0x57, 0xaa, + 0x53, 0xbe, 0xd0, 0xad, 0x65, 0xea, 0xfd, 0x36, 0x7e, 0xdb, 0x0a, 0x10, 0xe3, 0x75, 0xc5, 0x4a, 0xf1, 0x86, 0x56, + 0x18, 0xd7, 0xc0, 0x6d, 0x72, 0xa8, 0xa5, 0x5a, 0x20, 0xea, 0xf2, 0x93, 0xc7, 0x3c, 0x32, 0xea, 0x4c, 0xf8, 0xee, + 0x31, 0xf7, 0xa5, 0x6b, 0xbb, 0x4d, 0xfc, 0x5c, 0xd3, 0xf6, 0x77, 0x07, 0xba, 0xa3, 0x75, 0x0f, 0x37, 0xcf, 0xe6, + 0xe7, 0x91, 0xf9, 0x62, 0x80, 0xcd, 0xda, 0x65, 0x5c, 0x76, 0x0c, 0xf7, 0xbd, 0xe9, 0xc1, 0x58, 0x40, 0x20, 0x31, + 0x43, 0x2f, 0x03, 0x17, 0xb8, 0xc0, 0x5d, 0x61, 0xc0, 0x10, 0xd7, 0xb4, 0xe4, 0x4c, 0x5b, 0xd9, 0xfa, 0xc8, 0xdb, + 0xa8, 0x10, 0xac, 0xeb, 0x8e, 0x9b, 0x24, 0x87, 0xe0, 0x84, 0x2d, 0xf7, 0xbe, 0xf6, 0xda, 0x19, 0xfe, 0x63, 0x20, + 0x9c, 0x5b, 0xa2, 0x67, 0xd4, 0xf6, 0x58, 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, 0xde, 0xbf, 0xe6, 0x38, 0x71, 0x96, 0xc2, 0xf6, 0xc3, 0x87, 0x0b, 0x76, 0x4d, 0x00, 0x83, 0x16, 0x93, 0x05, + 0x4a, 0x50, 0xc9, 0x5a, 0xd5, 0x6e, 0xa7, 0xc4, 0x2f, 0xf7, 0x8b, 0x2e, 0xb3, 0x9d, 0xc7, 0xaf, 0x9b, 0xb4, 0xcf, + 0x7c, 0x8e, 0x7e, 0x98, 0xdf, 0x59, 0x27, 0x25, 0x67, 0x18, 0xd7, 0xf2, 0xff, 0xab, 0xe8, 0x65, 0x91, 0xa5, 0xd1, + 0xc6, 0xf0, 0x60, 0x36, 0xd4, 0xa6, 0x0f, 0x8d, 0x51, 0xb9, 0x65, 0xa3, 0x88, 0x68, 0x75, 0x0b, 0x82, 0x19, 0xc5, + 0x7d, 0x89, 0x36, 0xaf, 0x54, 0x59, 0x78, 0x87, 0xcf, 0x6c, 0xf4, 0x86, 0xed, 0x09, 0xa1, 0x7c, 0xf7, 0xb4, 0x30, + 0xab, 0x96, 0x8a, 0x06, 0xdb, 0x25, 0xbc, 0x8b, 0x51, 0xa5, 0x9f, 0x30, 0xd9, 0xb2, 0x60, 0xaa, 0xff, 0xdf, 0x17, + 0x59, 0xda, 0xa6, 0xe8, 0xc0, 0x74, 0x36, 0x7d, 0x3a, 0xe9, 0x06, 0xd7, 0x19, 0xb0, 0x88, 0x60, 0x4b, 0x85, 0xe3, + 0x51, 0x6a, 0x37, 0x48, 0x98, 0x08, 0x6e, 0xa2, 0x5e, 0x76, 0xb4, 0x4c, 0xc9, 0xaa, 0x80, 0xe7, 0x57, 0xae, 0x32, + 0x1d, 0x47, 0x43, 0xbf, 0x7f, 0x95, 0x9a, 0xd0, 0xaf, 0xd4, 0x4b, 0x55, 0x9c, 0x87, 0x51, 0x75, 0xa8, 0x30, 0x46, + 0x4b, 0x9a, 0xc2, 0x31, 0x98, 0x5d, 0x84, 0x29, 0x5e, 0xce, 0x36, 0x09, 0xfb, 0x82, 0x81, 0x5c, 0x6a, 0x83, 0x7a, + 0x4d, 0x89, 0xd6, 0xac, 0xbd, 0x99, 0x53, 0x42, 0x2f, 0x58, 0xe9, 0xdf, 0x85, 0xd6, 0x20, 0x50, 0x94, 0xcd, 0x94, + 0xe9, 0xb9, 0x6e, 0xe7, 0x05, 0x4d, 0x68, 0x41, 0x57, 0xa4, 0x06, 0x7d, 0xaf, 0x93, 0xb3, 0xa3, 0x93, 0x9d, 0x99, + 0xf5, 0x98, 0x15, 0xc3, 0xc9, 0x34, 0x86, 0x6b, 0x5a, 0xec, 0xae, 0x69, 0xcb, 0xe6, 0x8d, 0xab, 0xb1, 0x71, 0x1a, + 0xb4, 0x0b, 0xa4, 0x6d, 0x9a, 0xdb, 0x4f, 0x3d, 0x6e, 0x7f, 0x5d, 0xb3, 0xe5, 0xb4, 0xb7, 0xde, 0x6e, 0x7b, 0x29, + 0xd8, 0x88, 0x7a, 0x7c, 0xfc, 0x5a, 0x49, 0xd7, 0x2d, 0x97, 0x9f, 0xc2, 0xb3, 0xc7, 0xd7, 0x2f, 0x7d, 0x70, 0x39, + 0x5a, 0xb5, 0xb9, 0xfb, 0xe5, 0x2e, 0xb2, 0xdc, 0x17, 0x0d, 0x2d, 0xd7, 0x33, 0xd4, 0x24, 0xcf, 0x46, 0x7b, 0x87, + 0x5a, 0xb0, 0x9c, 0x75, 0x13, 0x9e, 0x18, 0xec, 0xd8, 0xab, 0xc6, 0xe6, 0xa8, 0xcc, 0x25, 0xab, 0x41, 0x02, 0x7d, + 0x92, 0x67, 0x9a, 0xfe, 0x41, 0x86, 0xf9, 0xe8, 0x96, 0xe6, 0x80, 0x2b, 0x56, 0xd9, 0x4b, 0x06, 0xa9, 0xab, 0xf6, + 0x12, 0x57, 0xbe, 0xc2, 0x21, 0xd9, 0xe0, 0x93, 0x61, 0xaa, 0x3e, 0xbb, 0xe4, 0xc1, 0xff, 0xdb, 0xaa, 0x55, 0x7a, + 0x6e, 0x92, 0x1b, 0x8e, 0x7f, 0x9d, 0xb4, 0x7d, 0x4c, 0x0c, 0x12, 0xf0, 0xd4, 0x2e, 0x86, 0x6a, 0x54, 0x15, 0xb1, + 0x28, 0x73, 0x13, 0x73, 0xec, 0xde, 0xae, 0xa1, 0x83, 0x32, 0xf8, 0x75, 0xc3, 0x27, 0xe6, 0x0e, 0x6c, 0x05, 0x3a, + 0x3a, 0xd1, 0x5c, 0x86, 0x99, 0xb9, 0x0c, 0xd3, 0xae, 0xad, 0x02, 0xc3, 0xab, 0xb6, 0x4a, 0xa2, 0x5c, 0x8d, 0x7a, + 0xdc, 0xcc, 0x52, 0xb3, 0x17, 0x79, 0xf7, 0x9a, 0xf4, 0x24, 0xfe, 0x74, 0xe9, 0xc9, 0xeb, 0x61, 0x40, 0xe4, 0x97, + 0x2c, 0x0d, 0xd7, 0x28, 0x08, 0x4e, 0xad, 0x76, 0x20, 0xcd, 0x47, 0x80, 0xcc, 0x8f, 0xd3, 0xf0, 0x9d, 0x16, 0xe7, + 0x90, 0x8d, 0xd2, 0x38, 0xb1, 0xa5, 0x51, 0x0f, 0xc1, 0x9d, 0xf7, 0x8a, 0xc7, 0x10, 0xf8, 0xf0, 0x03, 0x6e, 0x06, + 0x15, 0xdd, 0x96, 0x98, 0x28, 0x6d, 0x1e, 0x75, 0xcb, 0x47, 0x0d, 0xa1, 0x92, 0x95, 0xe1, 0xc5, 0xd0, 0xde, 0x1d, + 0x81, 0x51, 0xe5, 0x04, 0x32, 0xc3, 0x62, 0xff, 0x60, 0x98, 0x2a, 0x41, 0xd1, 0x50, 0x0e, 0x97, 0x28, 0x07, 0xc4, + 0x24, 0x10, 0x18, 0x15, 0x83, 0x54, 0x57, 0xa6, 0x5e, 0x0c, 0x52, 0x7d, 0xab, 0x22, 0xf5, 0x59, 0x16, 0x56, 0x54, + 0xb7, 0x88, 0x8e, 0xe9, 0x50, 0xd2, 0xa5, 0xd9, 0xa9, 0xb9, 0x96, 0x5e, 0xa8, 0xe5, 0xf8, 0x5c, 0xa7, 0xc1, 0x28, + 0x9e, 0xba, 0x14, 0xfd, 0x56, 0xed, 0x67, 0xff, 0x2d, 0xa6, 0xd4, 0x88, 0x4d, 0xed, 0x2d, 0x62, 0x58, 0xb5, 0x1f, + 0xb2, 0x2a, 0x07, 0xed, 0x2e, 0x28, 0x1b, 0x2b, 0xe3, 0x3c, 0xdf, 0x08, 0x66, 0x0e, 0xda, 0xc6, 0xaa, 0xe9, 0x43, + 0x6f, 0xc4, 0xa8, 0xbd, 0x31, 0xd5, 0xb8, 0x27, 0xf0, 0xd3, 0x06, 0x4d, 0xf7, 0x22, 0xcf, 0x51, 0x8f, 0xbc, 0xfb, + 0x9f, 0x39, 0xb2, 0x33, 0xf9, 0x2c, 0x96, 0x49, 0xdd, 0x3e, 0x26, 0xc1, 0x42, 0xd5, 0x31, 0xba, 0x70, 0x23, 0x53, + 0xda, 0xcf, 0x9d, 0xe9, 0x47, 0x3c, 0x93, 0x87, 0xed, 0xd0, 0xa8, 0x2f, 0x0d, 0x6b, 0x49, 0x11, 0xf5, 0x05, 0xbd, + 0x35, 0xd5, 0xd1, 0x01, 0xf5, 0x3a, 0x02, 0xab, 0x2b, 0xda, 0xa0, 0x06, 0x60, 0x32, 0xae, 0x6d, 0x6d, 0x3e, 0x07, + 0x53, 0x5b, 0x55, 0xc1, 0x33, 0xba, 0x2b, 0x94, 0xee, 0x4d, 0xea, 0xba, 0x35, 0xc4, 0x16, 0x30, 0x20, 0x70, 0xa3, + 0xa7, 0xa6, 0x3f, 0x68, 0xa2, 0x02, 0xd0, 0xa0, 0x71, 0x3b, 0xd3, 0x39, 0x12, 0xfd, 0x4e, 0x6d, 0xda, 0x66, 0xaa, + 0x57, 0x95, 0x0f, 0xa0, 0xe2, 0xcf, 0xd2, 0xd9, 0x85, 0x19, 0xb1, 0x00, 0xc6, 0x3d, 0x70, 0xa6, 0x7a, 0xc7, 0x19, + 0x58, 0x4f, 0xe4, 0x79, 0x56, 0xf2, 0x44, 0x0a, 0x98, 0x11, 0x79, 0x75, 0x25, 0x05, 0x0c, 0x83, 0x1a, 0x00, 0xb4, + 0x68, 0x2e, 0xa3, 0x09, 0x7f, 0x52, 0xd3, 0xfb, 0xf2, 0xf0, 0x27, 0x3a, 0xd7, 0x37, 0xe3, 0x1a, 0x0c, 0x95, 0xd7, + 0x15, 0xdf, 0xc9, 0xf4, 0x0d, 0x7f, 0xea, 0x65, 0x5a, 0xca, 0x75, 0xb1, 0x93, 0xe5, 0xc9, 0x37, 0xfc, 0x99, 0xce, + 0x73, 0xf0, 0xb4, 0xa6, 0x69, 0x7c, 0xb7, 0x93, 0xe5, 0xef, 0xdf, 0x3c, 0xb5, 0x79, 0x9e, 0x8c, 0x6b, 0x7a, 0xc3, + 0xf9, 0x47, 0x97, 0x69, 0xa2, 0xab, 0x1a, 0x3f, 0xfd, 0xbb, 0xcd, 0xf5, 0xb4, 0xa6, 0x57, 0x52, 0x54, 0xcb, 0x9d, + 0xa2, 0x0e, 0xbe, 0x39, 0xf8, 0x3b, 0xff, 0xc6, 0x74, 0xef, 0xa0, 0xa6, 0x7f, 0xad, 0xe3, 0xa2, 0xe2, 0xc5, 0x4e, + 0x71, 0x7f, 0xfb, 0xfb, 0xdf, 0x9f, 0xda, 0x8c, 0x4f, 0x6b, 0x7a, 0xc7, 0xe3, 0x8e, 0xb6, 0x4f, 0x9e, 0x3d, 0xe5, + 0x7f, 0xab, 0x6b, 0xfa, 0x2b, 0xf3, 0x83, 0xa3, 0x1e, 0x67, 0x9e, 0x1e, 0x3e, 0x91, 0x4d, 0xd4, 0x80, 0xa1, 0x87, + 0x06, 0x90, 0x4b, 0xab, 0xa6, 0xb9, 0xc7, 0x2b, 0x17, 0xdc, 0xbe, 0xcf, 0xe2, 0x34, 0x5e, 0xc1, 0x41, 0xb0, 0x41, + 0xe3, 0xac, 0x02, 0x38, 0x55, 0xe0, 0x3d, 0xa3, 0x92, 0x66, 0xa5, 0xfc, 0x07, 0xe7, 0x1f, 0x61, 0xd0, 0x10, 0xd2, + 0x46, 0x45, 0x06, 0x3a, 0x59, 0xe9, 0xc8, 0x46, 0xe8, 0xbf, 0xd9, 0x8c, 0x83, 0xe3, 0xc3, 0xe8, 0xf5, 0xfb, 0x61, + 0xc1, 0x44, 0x58, 0x10, 0x42, 0xff, 0x0c, 0x0b, 0x70, 0x28, 0x29, 0x98, 0x97, 0xcf, 0xf8, 0x9e, 0x6b, 0xa3, 0xb0, + 0x10, 0x44, 0x77, 0x91, 0x7d, 0x40, 0xd5, 0xa3, 0xef, 0xd0, 0x0d, 0xf1, 0xb2, 0xc2, 0x82, 0xa1, 0x55, 0x0d, 0xcc, + 0x10, 0x14, 0xff, 0x86, 0x87, 0x12, 0x7c, 0xe2, 0x01, 0x3e, 0x7a, 0x4c, 0x66, 0x5c, 0x5d, 0x6b, 0x4f, 0x2e, 0xc2, + 0x82, 0x06, 0xba, 0xed, 0x10, 0x74, 0x20, 0xf2, 0x5f, 0x80, 0xa7, 0xc0, 0xc0, 0x87, 0x85, 0x5d, 0xca, 0x5d, 0x7f, + 0xf5, 0x5f, 0x0d, 0xeb, 0xe8, 0xc2, 0x8f, 0xfe, 0x6a, 0x5d, 0xd8, 0x33, 0x32, 0x95, 0x87, 0xe5, 0x70, 0x32, 0x1d, + 0x0c, 0xa4, 0x8b, 0xe3, 0x76, 0x9c, 0xcd, 0x7f, 0x9d, 0xcb, 0xc5, 0x02, 0x75, 0xdf, 0x38, 0xaf, 0x33, 0xfd, 0x37, + 0xd2, 0xce, 0x07, 0x6f, 0x8e, 0x7f, 0x3f, 0x3b, 0x3d, 0x7e, 0x05, 0xce, 0x07, 0x1f, 0x5e, 0x7e, 0xff, 0xf2, 0xbd, + 0x0a, 0xee, 0xae, 0xe6, 0xbc, 0xdf, 0x77, 0x52, 0x9f, 0x90, 0x0f, 0x2b, 0xb2, 0x1f, 0xc6, 0x8f, 0x0b, 0x65, 0xf4, + 0x40, 0x0e, 0x99, 0x85, 0x42, 0x86, 0x2a, 0x6a, 0xfb, 0xbb, 0x1c, 0x4e, 0x3c, 0x30, 0x8b, 0xbb, 0x86, 0x08, 0xd7, + 0x6f, 0xb9, 0x0d, 0xb2, 0x26, 0x8f, 0xbc, 0x7e, 0x70, 0x32, 0x95, 0x8e, 0x2d, 0x2c, 0x18, 0x94, 0x0d, 0x6d, 0x3a, + 0xce, 0xe6, 0xc5, 0xc2, 0xb6, 0xcb, 0x2d, 0x90, 0x51, 0x9a, 0x5d, 0x5c, 0x84, 0x0a, 0xba, 0xfa, 0x08, 0x34, 0x00, + 0xa6, 0x51, 0x85, 0x6b, 0x11, 0x9f, 0xf9, 0xe5, 0x47, 0x63, 0xaf, 0x79, 0xb7, 0xa8, 0x7b, 0x32, 0xcd, 0xaa, 0x1a, + 0x03, 0x3a, 0x98, 0x50, 0xee, 0x06, 0xdd, 0x04, 0x93, 0x51, 0x6d, 0xf9, 0x75, 0x5e, 0x2d, 0x4c, 0x73, 0xdc, 0x30, + 0x54, 0x5e, 0xc9, 0x6b, 0xd9, 0x40, 0x64, 0x20, 0x19, 0x86, 0x3d, 0x1a, 0xa3, 0x48, 0x7d, 0x6f, 0xd7, 0x3b, 0x7e, + 0x93, 0x4b, 0x88, 0xa6, 0x98, 0x81, 0x74, 0xfe, 0x58, 0x28, 0xe7, 0x72, 0xc9, 0xf8, 0x5c, 0x2c, 0x8e, 0xc0, 0xed, + 0x7c, 0x2e, 0x16, 0x11, 0x06, 0xe5, 0xcb, 0x20, 0x56, 0x09, 0xd8, 0xbd, 0x38, 0x08, 0xdf, 0x4e, 0x68, 0x03, 0xbb, + 0x81, 0x24, 0x1b, 0x94, 0x76, 0xa5, 0x21, 0xca, 0x9d, 0xf2, 0x68, 0x83, 0xc8, 0x43, 0xac, 0x9a, 0x57, 0x6d, 0x4f, + 0x36, 0x73, 0x31, 0xc1, 0x55, 0x16, 0x33, 0x39, 0x8d, 0x0f, 0x59, 0x31, 0x8d, 0xa1, 0x94, 0x38, 0x4d, 0xc3, 0x98, + 0x4e, 0xa8, 0x20, 0x24, 0x61, 0x7c, 0x1e, 0x2f, 0x68, 0x82, 0x52, 0x82, 0x10, 0x42, 0x7e, 0x8c, 0xd0, 0x36, 0x07, + 0x96, 0xbc, 0xdd, 0x7e, 0x9e, 0x7e, 0x6e, 0xc7, 0x70, 0x19, 0x15, 0xa1, 0x1b, 0x74, 0xd6, 0xf0, 0x6f, 0x44, 0x05, + 0x8d, 0xb1, 0x62, 0x08, 0x02, 0x5e, 0x60, 0x54, 0xc2, 0x82, 0xc4, 0xac, 0x82, 0x28, 0x02, 0xe5, 0x3c, 0x5e, 0xb0, + 0x82, 0x36, 0x6d, 0x4e, 0x63, 0x6d, 0x12, 0xd4, 0x73, 0x58, 0x6a, 0x7b, 0x52, 0xa9, 0x10, 0x7b, 0x7c, 0x26, 0xa2, + 0x6b, 0x6d, 0x68, 0x00, 0x28, 0x50, 0x4a, 0x2e, 0x7e, 0xf3, 0xe5, 0x1e, 0x6e, 0x0a, 0xfa, 0x9f, 0x6d, 0x4c, 0xb4, + 0xb3, 0x5c, 0x1d, 0x7a, 0xf3, 0x05, 0x8d, 0xf3, 0x1c, 0x42, 0xb1, 0x19, 0x04, 0x72, 0x91, 0x55, 0x10, 0xd1, 0xe2, + 0x2e, 0x30, 0x21, 0xe1, 0xa0, 0x4d, 0xbf, 0x42, 0x6a, 0x43, 0x4c, 0xae, 0x3c, 0x31, 0xb0, 0xdb, 0x2a, 0x41, 0xc0, + 0x91, 0x9e, 0x67, 0x9f, 0x9a, 0x18, 0x6b, 0x9a, 0x9a, 0x99, 0x78, 0x1b, 0x0a, 0xd1, 0xa0, 0x05, 0xd1, 0x0c, 0xde, + 0x3f, 0x57, 0x1c, 0xaf, 0x3a, 0xf0, 0x03, 0xde, 0xb9, 0x38, 0xf3, 0x6a, 0xe6, 0x11, 0x39, 0xf5, 0x51, 0x8e, 0xe8, + 0x97, 0x3c, 0xac, 0x46, 0x3a, 0x19, 0x63, 0x25, 0x71, 0xd0, 0xdb, 0x60, 0xc1, 0x9c, 0xd0, 0x15, 0x0f, 0x2d, 0x1f, + 0xff, 0x0a, 0x99, 0x8c, 0x92, 0x1a, 0x2b, 0xba, 0xd2, 0x62, 0xc4, 0x79, 0x0d, 0xb3, 0x34, 0x59, 0xd1, 0xc5, 0x42, + 0x93, 0x66, 0xa1, 0x4c, 0x03, 0x7c, 0x02, 0x2d, 0x46, 0xee, 0xa1, 0xa6, 0x0d, 0x84, 0x86, 0xdd, 0x21, 0xe0, 0x23, + 0xf7, 0xd0, 0xe1, 0xff, 0xe7, 0xd9, 0x05, 0x22, 0xed, 0xcd, 0x4d, 0x64, 0x3c, 0x52, 0x37, 0x70, 0x50, 0x8c, 0x8f, + 0x7d, 0x33, 0xf1, 0x0b, 0x67, 0xf4, 0x21, 0xa9, 0x7c, 0x87, 0x0f, 0x96, 0x3f, 0xde, 0xd4, 0xcc, 0xca, 0x08, 0xd6, + 0xc3, 0x76, 0x8b, 0x0b, 0xa2, 0xed, 0x02, 0x48, 0x3d, 0xe3, 0xd5, 0xc2, 0x37, 0x5e, 0x8d, 0xef, 0x31, 0x5e, 0x75, + 0x67, 0x6a, 0x98, 0x93, 0x0d, 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, 0x6e, + 0xb7, 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, 0x5f, 0xc4, 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, 0x21, 0xbb, 0xe2, 0x65, 0x15, 0x5f, 0xad, 0x8c, 0x25, 0x31, + 0x67, 0xf7, 0xb9, 0xed, 0x51, 0x61, 0x5e, 0xbd, 0x7d, 0xf9, 0xfd, 0x71, 0xe3, 0xd5, 0x2e, 0xe2, 0x68, 0x08, 0xb6, + 0x15, 0x63, 0x8c, 0xde, 0xe2, 0xd3, 0x60, 0xa2, 0x5c, 0x23, 0xd0, 0xbb, 0x14, 0xf4, 0xdb, 0x5f, 0xea, 0x09, 0x78, + 0xc5, 0xf5, 0xf2, 0x4b, 0x3e, 0x02, 0x96, 0xa8, 0xd0, 0xb3, 0xc2, 0xdc, 0xac, 0xcc, 0xee, 0xed, 0x56, 0x64, 0xa6, + 0x5d, 0x69, 0x64, 0x20, 0x5e, 0x6d, 0x87, 0xb1, 0x70, 0xe9, 0x9a, 0x6e, 0x07, 0xbb, 0x5a, 0x7a, 0x96, 0xc8, 0xdb, + 0x6d, 0x09, 0x1d, 0xb2, 0x03, 0xee, 0xbd, 0x8c, 0x6f, 0xe1, 0x65, 0xe9, 0x75, 0xb3, 0x19, 0x3c, 0x01, 0xcc, 0x84, + 0x0b, 0x67, 0x59, 0x1c, 0x33, 0x9e, 0x84, 0x2a, 0x36, 0x57, 0x43, 0xe4, 0xad, 0x08, 0xad, 0xd9, 0x5f, 0xa1, 0x18, + 0x81, 0xdd, 0xc9, 0xe9, 0xc7, 0x6c, 0x35, 0x5b, 0x02, 0x6a, 0xfe, 0x55, 0x26, 0x80, 0xe6, 0xda, 0xb5, 0x60, 0x9b, + 0x42, 0x9b, 0xeb, 0xfa, 0x79, 0xbc, 0x8a, 0x13, 0x50, 0xdd, 0x80, 0xb7, 0xc8, 0x9d, 0x16, 0x5d, 0x19, 0x74, 0x51, + 0xfa, 0x40, 0x39, 0x96, 0x14, 0x3a, 0xfa, 0xde, 0x13, 0xea, 0xdc, 0x33, 0x80, 0x4b, 0x1a, 0x35, 0x4f, 0xb5, 0x94, + 0xb1, 0x00, 0x58, 0xe8, 0x60, 0xa6, 0xc8, 0x56, 0x74, 0x6b, 0x30, 0x29, 0xe0, 0xad, 0x01, 0xfe, 0x10, 0x59, 0xa5, + 0xee, 0x8a, 0x65, 0x58, 0x7a, 0xf6, 0xd7, 0xfd, 0x7e, 0xec, 0xd9, 0x5f, 0x5f, 0x68, 0x5a, 0x17, 0xb7, 0x1b, 0x40, + 0x6a, 0x0c, 0x20, 0x72, 0xac, 0x07, 0xc2, 0x44, 0x14, 0x6b, 0xfa, 0xfe, 0x1d, 0x9b, 0x2c, 0x0a, 0x84, 0x7e, 0xa7, + 0x5e, 0x4f, 0x4a, 0x02, 0x3a, 0xb5, 0x8a, 0x1d, 0x0d, 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, + 0xfb, 0xbf, 0x99, 0x2c, 0x08, 0x6a, 0xae, 0xfc, 0x40, 0x8e, 0x3b, 0x99, 0x1a, 0x7b, 0xaa, 0x51, 0x83, 0x60, 0x32, + 0x82, 0xc0, 0x70, 0xc3, 0x2f, 0xf8, 0xf8, 0x60, 0x41, 0x40, 0x45, 0x66, 0xcd, 0x42, 0xcc, 0x8b, 0xc3, 0x27, 0x80, + 0x1a, 0x33, 0x3a, 0x78, 0x06, 0xa0, 0xb0, 0x10, 0x10, 0x7d, 0x0c, 0x32, 0x5a, 0x01, 0xbf, 0x85, 0xfa, 0xdd, 0x3a, + 0xf1, 0x7d, 0xe8, 0x57, 0x41, 0x2f, 0x62, 0x60, 0x38, 0xa2, 0xc9, 0x7e, 0xc8, 0x07, 0x93, 0x01, 0x68, 0x4b, 0xbc, + 0xdd, 0xd7, 0xd2, 0x8a, 0x9b, 0xd3, 0xa5, 0xd3, 0xfd, 0x93, 0x36, 0x41, 0x12, 0xa9, 0x64, 0xa5, 0x22, 0x06, 0x10, + 0xca, 0x52, 0x6d, 0x93, 0x25, 0x58, 0x56, 0x98, 0x25, 0xcd, 0x0d, 0x4a, 0xe2, 0xee, 0x66, 0xe0, 0x18, 0x35, 0xeb, + 0x38, 0x2c, 0x5b, 0x6e, 0xd4, 0x00, 0x9f, 0x93, 0xb0, 0xc2, 0xde, 0x70, 0x66, 0xd2, 0x3b, 0xd3, 0xe1, 0xea, 0x98, + 0xb3, 0x37, 0x1c, 0xc1, 0x38, 0x12, 0xbc, 0xf1, 0xd0, 0x25, 0xd3, 0x50, 0x91, 0x29, 0xe3, 0x60, 0xda, 0x03, 0xdc, + 0x7b, 0x0e, 0xc6, 0x61, 0x6c, 0x50, 0x59, 0x52, 0x9f, 0x7a, 0x77, 0x21, 0x10, 0xa4, 0xb5, 0x5e, 0xe6, 0x33, 0x3c, + 0x3d, 0x23, 0x94, 0xfd, 0x21, 0x87, 0x2f, 0xc0, 0x8e, 0x82, 0x1c, 0x4d, 0xf8, 0xb3, 0xc7, 0xbb, 0x81, 0xaa, 0xf8, + 0x20, 0xd8, 0x8b, 0x45, 0xba, 0x17, 0x0c, 0x04, 0xfc, 0x2a, 0xf8, 0x5e, 0x25, 0xe5, 0xde, 0x45, 0x5c, 0xec, 0xc5, + 0xab, 0xb8, 0xa8, 0xf6, 0x6e, 0xb2, 0x6a, 0xb9, 0x67, 0x3a, 0x04, 0xd0, 0xbc, 0xc1, 0x20, 0x1e, 0x04, 0x7b, 0xc1, + 0xa0, 0x30, 0x53, 0xbb, 0x62, 0x65, 0xe3, 0x38, 0x33, 0x21, 0xca, 0x82, 0x66, 0x80, 0xb0, 0xc6, 0x69, 0x00, 0x7c, + 0xea, 0x9a, 0xa5, 0xf4, 0x02, 0xc3, 0x0d, 0x88, 0xe9, 0x1a, 0xfa, 0x00, 0x3c, 0xf2, 0x9a, 0xc6, 0xb0, 0x04, 0x2e, + 0x06, 0x03, 0xb2, 0x86, 0xc8, 0x05, 0x6b, 0x6a, 0x83, 0x38, 0x84, 0x6b, 0x65, 0xa7, 0xbd, 0x0b, 0xcc, 0xb4, 0xdd, + 0x02, 0xa2, 0xf2, 0x84, 0xf4, 0xfb, 0xf6, 0x1b, 0xea, 0x5f, 0xb0, 0x97, 0x60, 0x7f, 0x55, 0x54, 0x61, 0x22, 0x95, + 0xe6, 0xfb, 0x92, 0x1d, 0x0d, 0x54, 0xc4, 0xe1, 0x1d, 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, 0xaf, 0x34, 0xbb, 0xf4, 0x30, 0x90, 0x32, + 0x6e, 0x0f, 0x2d, 0x61, 0xd2, 0xf2, 0x22, 0xbc, 0xf7, 0x9a, 0x9b, 0xdc, 0x8b, 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, 0xcf, 0x74, 0x17, 0x80, 0xd1, 0x2f, 0x66, 0x69, 0xb4, 0xbc, 0xd7, 0xcc, 0x02, 0xc9, 0x33, 0xf4, 0x5d, + 0x07, 0xdb, 0x1b, 0xfb, 0x20, 0xe5, 0xfc, 0x50, 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, 0x3f, 0x91, 0x6f, 0x72, 0x07, 0x5d, 0x2e, 0xc7, + 0x9a, 0xb7, 0x1c, 0x80, 0x8a, 0x7e, 0xa4, 0xa8, 0xee, 0x17, 0x38, 0xc2, 0x3c, 0x58, 0xb7, 0xf9, 0x64, 0xdf, 0x14, + 0x38, 0x44, 0x9e, 0xb4, 0xd1, 0x14, 0xd0, 0xbd, 0x8b, 0xc7, 0x5d, 0xfd, 0xb6, 0x74, 0x17, 0x28, 0xd1, 0x4e, 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, + 0xeb, 0x33, 0x8e, 0xa2, 0x1f, 0xa3, 0x46, 0xbe, 0x89, 0xc4, 0x63, 0x39, 0x88, 0x1f, 0x17, 0x74, 0x19, 0x89, 0xc7, + 0xc5, 0x20, 0x7e, 0x2c, 0xeb, 0x7a, 0xf7, 0x5c, 0xb9, 0xbf, 0x8f, 0xc8, 0xb3, 0xee, 0xec, 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, 0xfd, 0x62, 0x74, 0xe3, 0xbb, 0xeb, 0xef, 0x17, 0xa3, 0x25, 0x19, 0x4e, 0xcc, 0xe4, 0xc7, 0x47, 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, 0xdf, 0xab, 0x76, 0xb4, 0x69, 0x6f, 0xe2, 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, 0x4d, 0xd9, 0xfc, 0x2a, 0xda, 0xe7, 0xc8, 0x48, + 0xd9, 0x26, 0x23, 0x15, 0x18, 0x61, 0x4a, 0x91, 0xc4, 0x55, 0x08, 0x81, 0xec, 0xbf, 0xa4, 0xb8, 0x16, 0x4b, 0xef, + 0x35, 0x08, 0x13, 0x6c, 0x17, 0xb4, 0x5f, 0xdd, 0xce, 0x6d, 0xa5, 0xc5, 0x1e, 0xa9, 0xef, 0x73, 0x67, 0xbb, 0xa2, + 0xc9, 0xdf, 0x97, 0x0d, 0x68, 0x03, 0x88, 0xf2, 0xbe, 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, 0x80, + 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, 0x53, 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, 0x11, 0xcb, 0xe6, 0x62, 0x31, 0x5a, 0x49, 0x08, 0x1b, 0x7c, 0xc8, 0xb2, 0x79, 0xa9, + 0x1f, 0x42, 0x5f, 0x58, 0x7a, 0x02, 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, 0x23, 0xd4, + 0xfe, 0x7e, 0x1e, 0xc5, 0x5a, 0x2e, 0xb9, 0x72, 0x7e, 0xf1, 0x37, 0x9f, 0xb1, 0xd7, 0x3d, 0xc3, 0x60, 0x01, 0xce, + 0xd2, 0xf6, 0x2a, 0x13, 0xef, 0x64, 0x2b, 0x38, 0x0e, 0x66, 0x51, 0x0e, 0xab, 0x9e, 0x1c, 0xd1, 0x5c, 0xe4, 0xda, + 0xbb, 0x08, 0x91, 0x83, 0xcc, 0x1e, 0x03, 0xec, 0x46, 0xf8, 0x3a, 0xb4, 0x36, 0xb7, 0xba, 0x42, 0xfc, 0x8d, 0x12, + 0x89, 0x9f, 0xa5, 0xfc, 0xb8, 0x5e, 0xa9, 0x5c, 0x95, 0xc1, 0x63, 0xd5, 0xcd, 0xe0, 0x99, 0xf6, 0x3d, 0xd6, 0xfe, + 0xad, 0xed, 0xe6, 0x78, 0xef, 0xc1, 0x83, 0xd6, 0xff, 0xd6, 0x93, 0x10, 0xda, 0x2b, 0x27, 0xa9, 0x3b, 0x6a, 0xf4, + 0xcc, 0x64, 0x8d, 0xa8, 0x84, 0xa9, 0xdd, 0xa9, 0x1c, 0x03, 0x35, 0x1d, 0xc0, 0xb5, 0x44, 0x4d, 0xd0, 0x93, 0x82, + 0x8d, 0xe1, 0x88, 0xb3, 0x38, 0x68, 0x87, 0x31, 0x8a, 0x97, 0x73, 0x25, 0x5e, 0xce, 0x8f, 0x18, 0x07, 0x68, 0x2d, + 0x40, 0xaa, 0xd7, 0xb0, 0x9f, 0xb9, 0x82, 0x05, 0x36, 0x77, 0xbe, 0x03, 0x0b, 0x64, 0x88, 0x93, 0xcd, 0x71, 0xb2, + 0xc7, 0xb5, 0x9e, 0x7b, 0x81, 0x8f, 0x93, 0x7a, 0xe1, 0xd5, 0x55, 0xb6, 0xeb, 0x5a, 0xb2, 0x72, 0x5e, 0x0c, 0x26, + 0x10, 0x94, 0xa5, 0x9c, 0x17, 0xc3, 0xc9, 0x82, 0xe6, 0xf0, 0x63, 0xd1, 0x40, 0x87, 0x58, 0x0e, 0x12, 0xb8, 0x74, + 0xf6, 0x18, 0xf0, 0x86, 0x52, 0x8b, 0xbb, 0xb1, 0x8e, 0x1c, 0xeb, 0x28, 0xf6, 0xc3, 0x18, 0x70, 0x65, 0x9d, 0xc0, + 0xfb, 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, 0x1d, 0x95, 0x43, + 0x2d, 0x84, 0xeb, 0x5a, 0x78, 0x1d, 0xa7, 0x65, 0x0c, 0x2e, 0xd2, 0xda, 0x36, 0xf1, 0x1e, 0xba, 0xee, 0xf9, 0x31, + 0xb7, 0x3a, 0x46, 0x5b, 0x48, 0xbf, 0x1d, 0x9d, 0xde, 0x73, 0x18, 0x80, 0xa6, 0x07, 0xb3, 0xaa, 0x7d, 0x26, 0x71, + 0x73, 0xda, 0x09, 0x42, 0x22, 0x10, 0x45, 0xe9, 0x8c, 0x30, 0xfd, 0x3b, 0xcd, 0x65, 0x15, 0xad, 0x1e, 0xe4, 0x99, + 0x43, 0x9e, 0x85, 0xde, 0xf6, 0xa0, 0x55, 0x73, 0x37, 0x18, 0x27, 0x6e, 0xb7, 0x77, 0xfe, 0xdf, 0xb2, 0xae, 0xad, + 0xd6, 0x88, 0xc7, 0xed, 0xea, 0x07, 0x8d, 0xbd, 0xda, 0x53, 0x31, 0x60, 0x56, 0xd2, 0x3b, 0xa3, 0x4a, 0x5e, 0x64, + 0xbc, 0xc4, 0x93, 0x6a, 0xd5, 0xf0, 0xf1, 0xbe, 0xc9, 0x46, 0xe6, 0x81, 0x4c, 0x01, 0xf1, 0xfc, 0x26, 0x35, 0xea, + 0xe3, 0x14, 0x25, 0xe0, 0xef, 0x74, 0x7c, 0x23, 0xfa, 0xd1, 0xbe, 0xb8, 0xe4, 0xd5, 0xc9, 0x8d, 0x30, 0x2f, 0x5e, + 0x58, 0x9d, 0x3f, 0x7d, 0x53, 0xf8, 0xd0, 0xe1, 0xa8, 0xbd, 0x83, 0x22, 0x4b, 0x26, 0x8e, 0x26, 0x46, 0xd6, 0x26, + 0x66, 0x1f, 0x15, 0x5c, 0x4c, 0x54, 0xa1, 0x67, 0x9d, 0x3d, 0x61, 0x0a, 0xd0, 0x37, 0x8e, 0x51, 0xc9, 0x18, 0x16, + 0x0c, 0xd4, 0x69, 0x4a, 0x88, 0x1e, 0x8a, 0x19, 0xc6, 0x2b, 0x06, 0x50, 0x98, 0x42, 0x81, 0x28, 0x3a, 0xfb, 0x70, + 0xa0, 0x09, 0xfd, 0xfe, 0x4d, 0xaa, 0x33, 0xd0, 0xb2, 0x9e, 0x4a, 0x10, 0xd5, 0x41, 0xb4, 0x55, 0x5e, 0x84, 0x3f, + 0x2e, 0x69, 0x99, 0xd1, 0xa5, 0xa0, 0xa9, 0xa0, 0x49, 0x46, 0x2f, 0xb8, 0x12, 0x15, 0x5f, 0x08, 0xa6, 0x68, 0xbb, + 0x21, 0xec, 0xff, 0x6a, 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, 0x9d, 0xae, 0xcf, 0x9f, 0xcb, 0xab, 0x95, 0x14, 0x5c, 0x54, 0x0a, 0xa2, 0xdf, 0xe0, 0xbe, 0x9b, 0xb8, + 0xea, 0xac, 0x59, 0x2b, 0x7d, 0xe8, 0x5b, 0x9f, 0xb5, 0x71, 0x5f, 0x18, 0x1c, 0x83, 0x9d, 0x8f, 0x88, 0x81, 0x34, + 0xa8, 0x74, 0x8b, 0x43, 0x13, 0xa0, 0x4b, 0x87, 0x14, 0xb2, 0x64, 0x2a, 0x53, 0x25, 0xa8, 0xf8, 0xc6, 0xef, 0xa5, + 0xac, 0x46, 0x7f, 0xad, 0x79, 0x71, 0x77, 0xca, 0x73, 0x8e, 0x63, 0x14, 0x24, 0xb1, 0xb8, 0x8e, 0xcb, 0x80, 0xf8, + 0x96, 0x57, 0xc1, 0x41, 0x6a, 0xc2, 0xc6, 0xec, 0x54, 0x8d, 0x5a, 0x2f, 0x89, 0xbe, 0x32, 0xca, 0x37, 0x06, 0x43, + 0x13, 0x51, 0x05, 0x7d, 0xaf, 0xd5, 0x3d, 0xad, 0x6e, 0x58, 0x40, 0xfc, 0xb9, 0xd2, 0x0b, 0xb5, 0x5e, 0x37, 0x63, + 0x6e, 0x98, 0x08, 0x41, 0xa3, 0x27, 0xf5, 0xa2, 0xf6, 0xdc, 0xd2, 0x54, 0x64, 0xdc, 0x68, 0x93, 0xf3, 0x4b, 0x90, + 0xf1, 0x39, 0x73, 0xa1, 0x49, 0x5d, 0x53, 0x05, 0x55, 0x18, 0x6d, 0x6e, 0x1b, 0xe9, 0xf4, 0x0e, 0xdc, 0xd9, 0x8c, + 0xd9, 0x91, 0x76, 0x69, 0xac, 0x69, 0xc1, 0xcb, 0x95, 0x14, 0x25, 0x84, 0x71, 0xee, 0x8d, 0xe9, 0x55, 0x9c, 0x89, + 0x2a, 0xce, 0xc4, 0x71, 0xb9, 0xe2, 0x49, 0xf5, 0x1e, 0x6e, 0x71, 0xca, 0xea, 0xa6, 0x2e, 0xe1, 0x4a, 0x97, 0xec, + 0x61, 0x30, 0x35, 0x15, 0xf7, 0xd8, 0x19, 0x5c, 0x54, 0x7f, 0x44, 0x4b, 0x89, 0xb1, 0x50, 0x75, 0xf1, 0xf1, 0x79, + 0x29, 0xf3, 0x75, 0x05, 0xda, 0xdd, 0x8b, 0x2a, 0x3a, 0x78, 0xba, 0xba, 0x9d, 0xaa, 0x1b, 0x4c, 0xf4, 0xf4, 0x60, + 0x75, 0xdb, 0xcb, 0xae, 0x56, 0xb2, 0xa8, 0x62, 0x51, 0x4d, 0x15, 0x22, 0x59, 0x12, 0xe7, 0x49, 0x38, 0x19, 0x8f, + 0xbf, 0xda, 0x1b, 0xee, 0x41, 0x06, 0x32, 0xfd, 0x34, 0x54, 0x2e, 0x47, 0xc3, 0xc9, 0x78, 0x3c, 0x95, 0xea, 0x6e, + 0x17, 0x8d, 0x26, 0x35, 0xd6, 0x33, 0x4c, 0xf4, 0xcc, 0x8c, 0xf8, 0xed, 0x2a, 0x16, 0x29, 0xc4, 0xaf, 0xd3, 0xc5, + 0x1f, 0x3c, 0x1d, 0x37, 0xca, 0xb7, 0x9f, 0x3e, 0xab, 0xff, 0xa8, 0x4d, 0x58, 0x6b, 0xd3, 0xee, 0xe7, 0x7f, 0x1c, + 0xaa, 0xf9, 0x3e, 0x3a, 0xdc, 0xd7, 0x3f, 0xfe, 0xa8, 0xeb, 0xe9, 0x9b, 0x22, 0x9c, 0xff, 0x33, 0x54, 0xf3, 0x79, + 0x5c, 0x14, 0xf1, 0x5d, 0x0d, 0x91, 0x3c, 0x85, 0xf3, 0x26, 0xa1, 0xde, 0x36, 0xa0, 0x07, 0x64, 0x7a, 0x21, 0x18, + 0x7c, 0xf3, 0xbe, 0x0a, 0x03, 0x5e, 0xae, 0x86, 0x5c, 0x54, 0x59, 0x75, 0x37, 0xc4, 0x3c, 0x01, 0x7e, 0x6a, 0x78, + 0xb3, 0xe7, 0x85, 0x21, 0x36, 0x17, 0x05, 0xe7, 0x9f, 0x78, 0xa8, 0x8c, 0xa3, 0xc7, 0x68, 0x1c, 0x3d, 0xa6, 0x6a, + 0x30, 0x26, 0xdf, 0x50, 0xdd, 0x99, 0xc9, 0x37, 0x60, 0x82, 0x94, 0xb5, 0xbf, 0x51, 0xc6, 0x89, 0xd1, 0x98, 0x5e, + 0xbf, 0xca, 0xb3, 0x15, 0x30, 0xc1, 0x4b, 0xfd, 0xa3, 0x26, 0xf4, 0x3d, 0x6f, 0x67, 0x1f, 0x8d, 0x46, 0xcf, 0x0b, + 0x3a, 0x1a, 0x8d, 0x3e, 0x66, 0x35, 0xa1, 0x2b, 0xd1, 0xf1, 0xfe, 0x3d, 0xa7, 0xe7, 0x32, 0xbd, 0x8b, 0x82, 0x80, + 0x2e, 0xb3, 0x34, 0xe5, 0x42, 0x95, 0x75, 0x9a, 0xb6, 0xf3, 0xaa, 0x16, 0x22, 0xf0, 0x8f, 0x6e, 0x23, 0x42, 0x10, + 0x11, 0x7a, 0xb2, 0xd3, 0xb3, 0xd1, 0x68, 0x74, 0x9a, 0x9a, 0x6a, 0x1d, 0x43, 0xfe, 0x06, 0xcd, 0x07, 0x9c, 0x5d, + 0x3e, 0x58, 0xdf, 0x98, 0x68, 0x27, 0xfb, 0xff, 0x3d, 0x9c, 0xcd, 0xc7, 0xc3, 0x6f, 0x47, 0x8b, 0xc7, 0xfb, 0x34, + 0x08, 0x7c, 0xd0, 0xea, 0x50, 0x5b, 0x73, 0x4c, 0xcb, 0xc3, 0xf1, 0x94, 0x94, 0x03, 0xf6, 0xd4, 0xfa, 0xd2, 0x7c, + 0xf5, 0x14, 0x90, 0x48, 0x51, 0x84, 0x1a, 0x38, 0xe9, 0x1f, 0x5e, 0x45, 0x5e, 0x0b, 0xc0, 0x47, 0xb3, 0x91, 0x0c, + 0x8c, 0x16, 0x70, 0x1c, 0x41, 0x79, 0xb5, 0x35, 0x8d, 0xe8, 0x31, 0x96, 0x99, 0xa8, 0xa0, 0xe3, 0x69, 0x79, 0x93, + 0x55, 0xc9, 0x12, 0x03, 0x1b, 0xc5, 0x25, 0x0f, 0xbe, 0x0a, 0xa2, 0x92, 0x1d, 0x3c, 0x9b, 0x2a, 0x78, 0x5f, 0x4c, + 0x4a, 0xf9, 0x25, 0x24, 0x7e, 0x3b, 0x46, 0x08, 0x54, 0xa2, 0x3d, 0x16, 0xb1, 0xc6, 0x57, 0xb9, 0x8c, 0xc1, 0x83, + 0xb3, 0xd4, 0x3c, 0x8b, 0x3d, 0x09, 0xac, 0xfd, 0x45, 0xab, 0x39, 0x12, 0x9a, 0x13, 0x4a, 0x26, 0xf7, 0x4b, 0x2a, + 0xbf, 0x9a, 0xa0, 0x57, 0x10, 0xb8, 0x55, 0x47, 0x70, 0xdc, 0x59, 0xcb, 0x06, 0xbd, 0x7c, 0x52, 0xb6, 0x3f, 0xff, + 0xdf, 0x25, 0x5d, 0x0c, 0xf6, 0xdd, 0xd0, 0x9c, 0x68, 0xf7, 0xd5, 0x0a, 0x19, 0xa5, 0x2a, 0x7c, 0x9e, 0x12, 0x6b, + 0x7c, 0xca, 0xd9, 0xd1, 0xc6, 0x74, 0x67, 0x54, 0x15, 0xd9, 0x55, 0x48, 0x74, 0xaf, 0x1c, 0x28, 0x66, 0x10, 0x65, + 0x23, 0x5c, 0x3f, 0x60, 0x2d, 0xe2, 0x75, 0xf2, 0x9a, 0x17, 0x55, 0x96, 0xa8, 0xf7, 0xd7, 0x8d, 0xf7, 0x40, 0x0d, + 0x54, 0x83, 0xde, 0x15, 0x0c, 0xe6, 0xf9, 0xa4, 0x00, 0xd0, 0xce, 0x92, 0x17, 0xd7, 0xdc, 0xa7, 0x1b, 0x41, 0x50, + 0xbb, 0x66, 0x5e, 0x36, 0x82, 0x4d, 0xc0, 0x57, 0xef, 0x0a, 0xc0, 0xdc, 0x08, 0x41, 0x6a, 0x0a, 0xa1, 0x70, 0xe0, + 0x02, 0x5f, 0x55, 0x45, 0x76, 0xbe, 0xae, 0x38, 0x06, 0xfb, 0xf0, 0xe2, 0x26, 0x2a, 0x27, 0x3c, 0x1e, 0x06, 0xf8, + 0x23, 0xa0, 0x2a, 0xe0, 0x86, 0xf1, 0xb0, 0x83, 0x17, 0xea, 0x97, 0x7b, 0xa3, 0xf6, 0x08, 0x7b, 0x93, 0x86, 0x10, + 0x5c, 0x07, 0x1f, 0x02, 0x58, 0x52, 0x84, 0x9e, 0xe0, 0xa9, 0x1a, 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, 0x28, 0xef, + 0xf4, 0xc4, 0xb8, 0x30, 0x7d, 0x1c, 0x22, 0xbf, 0xbc, 0x2b, 0x54, 0xe8, 0x17, 0xbe, 0x00, 0xf0, 0x2b, 0xb8, 0xdd, + 0xef, 0xc6, 0x77, 0x51, 0xd9, 0xcf, 0x38, 0xdb, 0xff, 0xef, 0x79, 0x3c, 0xfc, 0x34, 0x1e, 0x7e, 0xbb, 0x18, 0x84, + 0x43, 0xfb, 0x93, 0x3c, 0x7e, 0xb4, 0x4f, 0x5f, 0x71, 0xcb, 0x95, 0xc0, 0xc2, 0x6f, 0x04, 0xb7, 0x51, 0x2b, 0x21, + 0x88, 0x02, 0xbc, 0x51, 0xb8, 0xd5, 0x38, 0x01, 0x80, 0xbf, 0xe0, 0xbf, 0x02, 0x34, 0x12, 0x72, 0x17, 0x0d, 0xd0, + 0x0f, 0xa8, 0xdf, 0x47, 0x4f, 0x1a, 0x06, 0x72, 0x20, 0x9e, 0x50, 0x31, 0x50, 0x88, 0x2e, 0x63, 0xa2, 0x60, 0x7f, + 0x6d, 0xf6, 0xed, 0xb6, 0xd7, 0x96, 0xfc, 0xe0, 0x97, 0x7e, 0xa6, 0x89, 0x99, 0x77, 0xb8, 0xa1, 0xac, 0xe4, 0x2a, + 0x44, 0x6c, 0x3c, 0xfd, 0x2b, 0x67, 0x10, 0x6b, 0xf2, 0x3a, 0x03, 0x1f, 0x06, 0xfb, 0xc5, 0x78, 0x06, 0x6c, 0x03, + 0xdc, 0x71, 0x0a, 0x7e, 0x91, 0x81, 0x5b, 0xb3, 0x88, 0xf1, 0x82, 0x6d, 0x97, 0x44, 0xbf, 0xdf, 0xcb, 0xb3, 0x30, + 0xd7, 0x38, 0xcb, 0x79, 0x6d, 0xc4, 0xee, 0xa8, 0x13, 0x06, 0x71, 0xbb, 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, 0xb8, 0x2e, 0xb3, 0x5e, 0x2f, 0x0c, 0xd1, 0xa1, 0x11, 0x4b, 0xc5, + 0xda, 0x20, 0xbc, 0x8f, 0x49, 0x18, 0x5d, 0x81, 0xac, 0x2e, 0x3c, 0xe3, 0x04, 0xf9, 0x32, 0x30, 0x59, 0x53, 0xd5, + 0x7a, 0x39, 0xe1, 0xb1, 0x91, 0x2f, 0x1b, 0x41, 0x83, 0xbc, 0xa4, 0xa8, 0x37, 0x71, 0x3b, 0xf6, 0x51, 0x0b, 0xa9, + 0x71, 0x53, 0x4f, 0x7b, 0x9a, 0x54, 0xf4, 0x58, 0xaf, 0x52, 0xbf, 0xc0, 0xb2, 0xc0, 0x92, 0x0f, 0x42, 0x7b, 0x9a, + 0x56, 0x60, 0x86, 0x6b, 0x9b, 0xc1, 0xd0, 0x0f, 0x87, 0xb6, 0x08, 0x9d, 0x51, 0xdb, 0x12, 0xc2, 0xb6, 0x0d, 0xc2, + 0xca, 0x7b, 0x22, 0x5f, 0x3d, 0xf5, 0x18, 0xe1, 0x90, 0x9b, 0xcd, 0x2c, 0x1a, 0x18, 0xe6, 0x57, 0xb2, 0xd9, 0x3c, + 0xdd, 0x5c, 0x2f, 0x2a, 0xa6, 0x80, 0xed, 0xb6, 0x12, 0x04, 0xff, 0x7e, 0xcc, 0x66, 0xf8, 0x37, 0xeb, 0xf7, 0x7b, + 0x21, 0xfe, 0xe2, 0x18, 0xbc, 0x67, 0x2e, 0x16, 0xec, 0x23, 0xc8, 0x54, 0x48, 0x84, 0xa9, 0xca, 0xf8, 0x8d, 0x55, + 0x60, 0x01, 0x67, 0x3e, 0x50, 0xb9, 0x30, 0x93, 0xbd, 0xbc, 0xb8, 0x86, 0x1c, 0xb7, 0xc6, 0x29, 0x1b, 0x65, 0x89, + 0x72, 0x5d, 0xc8, 0x46, 0x71, 0x9e, 0xc5, 0x25, 0x2f, 0xb7, 0x5b, 0x7d, 0x38, 0x26, 0x05, 0x07, 0xf6, 0x54, 0x51, + 0xa9, 0x92, 0x75, 0xa4, 0xba, 0xf1, 0x97, 0x61, 0x81, 0xfb, 0x94, 0xcf, 0x0b, 0x43, 0x23, 0xf6, 0xe0, 0xf2, 0xce, + 0xd4, 0xad, 0xb4, 0x17, 0x16, 0xd0, 0xbc, 0x92, 0x90, 0x0d, 0xa6, 0x7a, 0x16, 0xad, 0x31, 0x13, 0xf3, 0x62, 0x01, + 0x61, 0x64, 0x8a, 0x05, 0xd8, 0x4c, 0x71, 0x01, 0x5e, 0x24, 0x31, 0xc0, 0xc4, 0xc5, 0x64, 0x0a, 0xf1, 0xcc, 0x55, + 0x39, 0xf1, 0xc2, 0xdc, 0x2f, 0x13, 0x87, 0x94, 0x01, 0xaf, 0x6a, 0x83, 0x26, 0x66, 0x1b, 0x8e, 0x3a, 0x41, 0x4e, + 0x4c, 0x7e, 0x3f, 0x55, 0x10, 0xe2, 0x4e, 0x1c, 0x09, 0x97, 0x15, 0xdb, 0x85, 0x97, 0x1d, 0x88, 0x31, 0x6a, 0x70, + 0xca, 0xcf, 0x0c, 0x8e, 0xc6, 0xe0, 0xdc, 0x78, 0x27, 0x48, 0x11, 0xc6, 0x64, 0x23, 0xd9, 0x95, 0x0c, 0xc5, 0x3c, + 0x5e, 0x80, 0xb2, 0x2e, 0x5e, 0x80, 0x65, 0x8d, 0x31, 0xc0, 0x04, 0x79, 0x15, 0xf7, 0x42, 0x3f, 0x51, 0x5c, 0x21, + 0xd2, 0xb3, 0x72, 0x7d, 0x54, 0xb4, 0x43, 0x5f, 0xe0, 0xf5, 0x5e, 0x99, 0xe3, 0x66, 0x3d, 0x16, 0x48, 0x6c, 0x08, + 0x18, 0x1b, 0xe9, 0x34, 0xd5, 0x5a, 0xf7, 0xc6, 0xcc, 0x03, 0x9f, 0x66, 0x23, 0x21, 0xab, 0xb3, 0x0b, 0x10, 0xa1, + 0xf8, 0x68, 0xf0, 0xc8, 0x2f, 0xe2, 0xce, 0x32, 0x6f, 0x6d, 0x8b, 0x4a, 0x76, 0xb4, 0x01, 0x90, 0x3e, 0x1d, 0x2d, + 0x4a, 0xc9, 0x29, 0x4a, 0x52, 0xbb, 0x4d, 0x01, 0x2b, 0xc9, 0x5f, 0xc0, 0x10, 0x6c, 0x6c, 0x4f, 0x38, 0x9d, 0x22, + 0xc4, 0x27, 0x9a, 0x22, 0xb2, 0x62, 0x58, 0x52, 0x1c, 0xdb, 0x12, 0x51, 0x3f, 0x6d, 0x59, 0x76, 0x30, 0x4c, 0x54, + 0xdc, 0x17, 0xa9, 0x47, 0x89, 0x82, 0x80, 0xea, 0x21, 0x07, 0x89, 0xad, 0x6d, 0x20, 0x3c, 0x20, 0x8f, 0xe8, 0x8d, + 0xf5, 0xf7, 0x59, 0xe7, 0xd9, 0x85, 0xe6, 0xa8, 0x5c, 0xef, 0x0a, 0x33, 0x46, 0x78, 0x92, 0x19, 0x98, 0x7c, 0xef, + 0x3c, 0x33, 0x6a, 0x8a, 0x9e, 0x87, 0x4f, 0x76, 0x8c, 0x11, 0xe9, 0xee, 0x19, 0x74, 0x13, 0xbc, 0xaa, 0xc3, 0x46, + 0xbb, 0x52, 0x10, 0x12, 0xa6, 0x16, 0x4d, 0xcc, 0x7a, 0xd6, 0x80, 0x7a, 0xbb, 0xed, 0xe9, 0xb9, 0xba, 0x7f, 0xee, + 0xb6, 0xdb, 0x1e, 0x76, 0xeb, 0x45, 0xda, 0x6d, 0x05, 0x5e, 0xa9, 0x0f, 0xda, 0xe3, 0xcf, 0xdd, 0xf8, 0x73, 0x83, + 0xe4, 0x51, 0x3a, 0x9a, 0x69, 0xeb, 0x83, 0x70, 0xb8, 0xe9, 0x5d, 0xa3, 0x49, 0xdf, 0x67, 0xa1, 0xa4, 0x2b, 0xd1, + 0xa8, 0xae, 0x76, 0x26, 0x95, 0x0f, 0xae, 0xff, 0x87, 0x57, 0x01, 0x1e, 0x71, 0x6a, 0x67, 0xdf, 0xdb, 0xa0, 0xa2, + 0xd1, 0x16, 0x8e, 0x14, 0xa1, 0x07, 0x24, 0xe1, 0xbe, 0x96, 0xb5, 0xb8, 0xcd, 0xd3, 0xec, 0x61, 0xfa, 0xf4, 0x3a, + 0xf5, 0xad, 0xee, 0xdd, 0x32, 0xcb, 0xcc, 0x81, 0x57, 0x51, 0x1c, 0xd0, 0xa8, 0x8b, 0xf6, 0x5d, 0x65, 0x65, 0x09, + 0x5e, 0x1e, 0x70, 0x7d, 0x3e, 0xe5, 0x3e, 0xdc, 0xdc, 0x65, 0xd5, 0xdc, 0xa4, 0xa7, 0xd9, 0x3c, 0x5b, 0x6c, 0xb7, + 0x21, 0xfe, 0xed, 0x6a, 0x91, 0xa3, 0xc9, 0x73, 0xd0, 0xe1, 0x61, 0xe4, 0x1e, 0xa6, 0x1b, 0xe7, 0x6d, 0xfe, 0x4f, + 0xa2, 0xe1, 0x24, 0x70, 0x0c, 0xf4, 0x62, 0xf6, 0x08, 0x64, 0x30, 0xc6, 0xa9, 0x5f, 0xcc, 0xf4, 0x9a, 0x81, 0xe8, + 0x5b, 0x22, 0x02, 0x1c, 0x5d, 0x6c, 0x24, 0x1a, 0x59, 0x70, 0x52, 0x13, 0xb0, 0xd8, 0xb4, 0xe5, 0x7d, 0xb0, 0xb4, + 0xad, 0x2a, 0xee, 0xbc, 0x25, 0xcd, 0x71, 0x1d, 0x38, 0xdb, 0x7e, 0x33, 0xc4, 0xa6, 0xec, 0x6a, 0x81, 0xdc, 0x2f, + 0xaf, 0x69, 0x6f, 0x5c, 0x27, 0x30, 0x6b, 0x9b, 0xda, 0x32, 0x7e, 0xb6, 0xf4, 0x9f, 0xf5, 0xe0, 0x2a, 0xe3, 0xa7, + 0xb9, 0xb1, 0x4a, 0xb0, 0xfb, 0xc6, 0xf3, 0x1d, 0x80, 0x70, 0x6c, 0x3e, 0x3d, 0x3e, 0xcd, 0x3c, 0x7a, 0x0c, 0x44, + 0xc7, 0x7c, 0x54, 0xba, 0x8f, 0xec, 0xee, 0xf5, 0x03, 0xe0, 0xcd, 0xab, 0x76, 0x41, 0xf3, 0x72, 0x01, 0x81, 0x44, + 0xbd, 0xf2, 0x0a, 0xcb, 0x67, 0xc6, 0xec, 0x12, 0xc8, 0x50, 0x41, 0xc0, 0x26, 0xa9, 0xeb, 0x5c, 0x88, 0x55, 0x87, + 0x95, 0xf9, 0x48, 0xc2, 0x8e, 0x42, 0x34, 0xe7, 0x0c, 0x66, 0xc1, 0x7f, 0x05, 0x83, 0x72, 0x10, 0x44, 0x41, 0x14, + 0x04, 0x64, 0x50, 0xc0, 0x2f, 0xc4, 0x19, 0x23, 0x18, 0xa3, 0x04, 0x3a, 0xfc, 0x8e, 0x33, 0x9f, 0x11, 0x79, 0xd9, + 0x08, 0x63, 0xe9, 0x06, 0xe0, 0x5c, 0xca, 0x9c, 0xc7, 0xe8, 0x63, 0xf1, 0x8e, 0xb3, 0x8c, 0xd0, 0x77, 0xde, 0xa9, + 0xfc, 0x88, 0x37, 0x82, 0xdb, 0xed, 0x0e, 0xdb, 0x2b, 0x1e, 0x66, 0xb4, 0x37, 0xa6, 0xef, 0x38, 0x89, 0xb2, 0x86, + 0xf3, 0x30, 0x87, 0x9e, 0x55, 0x96, 0xb5, 0xa2, 0x86, 0xdc, 0xa0, 0x58, 0x17, 0x59, 0x26, 0x27, 0xc3, 0x55, 0x73, + 0x2a, 0x70, 0xdd, 0xd9, 0xf5, 0x02, 0x92, 0x32, 0xa1, 0x59, 0x3a, 0x1b, 0xbe, 0xda, 0xb6, 0xec, 0x45, 0xeb, 0x14, + 0xf2, 0x1a, 0xa2, 0xa2, 0x1f, 0x3a, 0x02, 0x6a, 0x68, 0xc5, 0x65, 0x05, 0x2e, 0xbb, 0xa6, 0x3d, 0xdc, 0xb4, 0xc7, + 0x34, 0xe3, 0x03, 0xc4, 0x88, 0xe3, 0xd8, 0x32, 0xb0, 0x9b, 0x70, 0x78, 0x36, 0xce, 0xf7, 0x65, 0x97, 0xde, 0xba, + 0x5a, 0x3c, 0xc2, 0xda, 0xf3, 0x56, 0x48, 0x08, 0x90, 0x96, 0xa6, 0xd2, 0xed, 0x36, 0x08, 0x60, 0x80, 0xfb, 0xfd, + 0x1e, 0x70, 0xad, 0x86, 0x9d, 0x34, 0xb7, 0x66, 0x4b, 0xec, 0x15, 0x85, 0xc7, 0x40, 0x94, 0x9a, 0xff, 0x0c, 0x02, + 0x8a, 0xe7, 0x6e, 0x08, 0xf6, 0x95, 0xec, 0x68, 0x53, 0xf4, 0xfb, 0x2f, 0x0a, 0x7c, 0x40, 0x39, 0x28, 0x88, 0x75, + 0x75, 0xdc, 0x0a, 0xc3, 0x3e, 0xa9, 0x0f, 0x71, 0x2c, 0xf2, 0x2c, 0x74, 0x84, 0xa5, 0x32, 0x84, 0x85, 0x2b, 0x46, + 0x3a, 0x88, 0x83, 0x9a, 0x74, 0x0e, 0x56, 0xe5, 0x82, 0x0d, 0xf7, 0x7a, 0x9f, 0x00, 0x16, 0x3c, 0xf3, 0x86, 0xe5, + 0xbd, 0x07, 0x00, 0xd6, 0xeb, 0xe1, 0x42, 0x71, 0x2f, 0x5f, 0x35, 0xd0, 0x27, 0xf1, 0xa5, 0x65, 0xd7, 0x67, 0x5a, + 0x56, 0x32, 0x1a, 0x8d, 0xaa, 0x5a, 0x49, 0x3e, 0x1c, 0x79, 0x69, 0xa1, 0x56, 0xca, 0x38, 0xe5, 0x29, 0x58, 0x7a, + 0x1b, 0x4a, 0x37, 0x5f, 0xd0, 0x15, 0x17, 0xa9, 0xfa, 0xe9, 0xa1, 0x4d, 0x36, 0x88, 0x6b, 0xd6, 0xd4, 0x59, 0xd8, + 0xe1, 0x87, 0x80, 0x8f, 0xf6, 0x61, 0xe6, 0xd2, 0x35, 0x2c, 0x2d, 0x88, 0x23, 0xe3, 0x82, 0x87, 0x2e, 0x0f, 0x60, + 0xfd, 0x99, 0x43, 0x12, 0x3f, 0x85, 0x9f, 0x33, 0x93, 0xd6, 0xf1, 0x19, 0xce, 0x66, 0x54, 0xaa, 0x1b, 0x41, 0xfb, + 0x35, 0x24, 0x12, 0x83, 0x6c, 0xdc, 0x60, 0x28, 0x5a, 0x77, 0x1b, 0xb8, 0xf2, 0x5b, 0x7a, 0xe7, 0xd3, 0x20, 0xc0, + 0xb6, 0xc6, 0x62, 0x00, 0x30, 0x14, 0x7f, 0xa0, 0xaa, 0xc6, 0x5c, 0x51, 0x4c, 0xc3, 0x54, 0xa2, 0xbd, 0xe3, 0xb8, + 0x8e, 0x1a, 0x57, 0x59, 0xc1, 0x4a, 0x6b, 0xcb, 0xeb, 0xde, 0xd2, 0xc2, 0x96, 0x80, 0x6a, 0x30, 0xdc, 0x09, 0xe0, + 0x33, 0x22, 0xd5, 0x81, 0x20, 0xbb, 0x0f, 0x0e, 0x9a, 0xb3, 0x04, 0xcf, 0xc3, 0x10, 0xfe, 0xc0, 0xc2, 0x81, 0x65, + 0xa9, 0xfa, 0xb9, 0x9c, 0xc6, 0x70, 0xee, 0xe6, 0x6a, 0x87, 0xcf, 0x96, 0xa0, 0xc8, 0x53, 0x73, 0x6a, 0x2e, 0x5f, + 0x79, 0x63, 0xbf, 0xc7, 0x04, 0xf3, 0x98, 0xd9, 0x86, 0xdf, 0x7a, 0xba, 0xad, 0x2f, 0xac, 0x1b, 0x38, 0x69, 0x2f, + 0x9c, 0xf6, 0x62, 0xbb, 0x34, 0x10, 0x77, 0x75, 0x43, 0x88, 0xf0, 0x5a, 0x13, 0x8b, 0xac, 0x21, 0xd3, 0xb1, 0xd8, + 0x18, 0xaa, 0x4d, 0xc5, 0x73, 0xad, 0x10, 0x2f, 0xa7, 0xea, 0xc2, 0xd4, 0x4a, 0x65, 0xc2, 0x20, 0xcc, 0x94, 0xb0, + 0xa8, 0x32, 0xf0, 0xd9, 0xaf, 0x90, 0xe2, 0xda, 0x7a, 0xde, 0xe2, 0xf2, 0xcd, 0x4c, 0x9b, 0xed, 0xa7, 0xaf, 0xf2, + 0xf8, 0x72, 0xbb, 0x0d, 0xbb, 0x5f, 0x80, 0xf9, 0x65, 0xa9, 0x34, 0x6a, 0xe0, 0xf4, 0x10, 0xa2, 0x9f, 0xf3, 0x3d, + 0x39, 0x27, 0x8e, 0x93, 0x6b, 0x37, 0x6f, 0xb6, 0x93, 0x62, 0x04, 0x16, 0x70, 0xe2, 0x22, 0x1d, 0x68, 0xa9, 0xe0, + 0xb4, 0x65, 0xbc, 0xb7, 0xe9, 0x1d, 0xa5, 0xc2, 0xab, 0x85, 0x26, 0x21, 0x95, 0xbb, 0x97, 0xd8, 0x51, 0x03, 0xce, + 0x49, 0xdd, 0x41, 0xc0, 0x49, 0x4d, 0x37, 0xd6, 0x2a, 0x4e, 0x4d, 0x82, 0xf7, 0x4a, 0x0f, 0x5d, 0xa2, 0x9d, 0xb8, + 0xdd, 0xb6, 0x2a, 0x5b, 0xa8, 0x8f, 0x7b, 0x39, 0x4b, 0xd4, 0xf1, 0x80, 0x42, 0x17, 0x75, 0x34, 0xe4, 0x0b, 0x52, + 0xe8, 0x95, 0xa3, 0x55, 0xab, 0xbb, 0x92, 0x81, 0x52, 0xad, 0x82, 0xbc, 0x26, 0xd6, 0x5d, 0x2b, 0x6b, 0x2c, 0xae, + 0x9c, 0x90, 0xc2, 0x26, 0x7c, 0x69, 0x29, 0x16, 0x56, 0xb0, 0x37, 0xa6, 0xbe, 0x70, 0x89, 0xd0, 0x76, 0xb7, 0x21, + 0x26, 0x19, 0xac, 0x9b, 0xed, 0xf6, 0x75, 0x11, 0xce, 0xb3, 0x05, 0x95, 0xa3, 0x2c, 0x45, 0x08, 0x31, 0xe3, 0xa1, + 0x6b, 0xbb, 0x60, 0x26, 0x86, 0xba, 0xf6, 0x78, 0x49, 0xa6, 0x58, 0x9b, 0x24, 0x47, 0xf1, 0xb9, 0x2c, 0xd4, 0x5a, + 0x23, 0x04, 0x0f, 0xf7, 0x3f, 0x53, 0x88, 0xe1, 0x66, 0xd6, 0xdd, 0x6f, 0x3b, 0x37, 0xc4, 0x3f, 0x21, 0x90, 0x40, + 0xc9, 0x5e, 0x17, 0xa3, 0xf3, 0x4c, 0xa4, 0xb8, 0x53, 0x55, 0x54, 0x5c, 0xb5, 0x0e, 0x9a, 0x2d, 0xb7, 0xf7, 0x62, + 0x4b, 0x14, 0x20, 0xae, 0xb1, 0xd0, 0x8c, 0x67, 0xe5, 0x2c, 0x45, 0x32, 0x8a, 0x0d, 0x89, 0x4a, 0x2f, 0x2a, 0xba, + 0xcf, 0xd3, 0x98, 0x1e, 0xba, 0x35, 0x08, 0xae, 0x9a, 0x3b, 0x1b, 0x69, 0xbe, 0x20, 0x44, 0x4d, 0x80, 0x84, 0x8d, + 0x6a, 0x4e, 0xad, 0x4b, 0xf1, 0x30, 0xab, 0x7c, 0xa6, 0x0f, 0xe2, 0x4b, 0x01, 0x3c, 0xac, 0xb7, 0xbd, 0xaf, 0x84, + 0xc7, 0xda, 0xe0, 0xdb, 0xed, 0xf6, 0x52, 0xcc, 0x83, 0xc0, 0x63, 0x34, 0xbf, 0x53, 0x12, 0xf3, 0xde, 0x98, 0xc2, + 0x8a, 0xf7, 0x5d, 0xda, 0xba, 0x49, 0xad, 0xb5, 0x40, 0xdd, 0xe1, 0xfa, 0x80, 0xe7, 0x29, 0x71, 0xb4, 0xa3, 0x72, + 0x2a, 0xad, 0xae, 0x1c, 0xbb, 0x22, 0x30, 0x30, 0xf4, 0x0f, 0x29, 0xdb, 0x80, 0x39, 0x1e, 0x58, 0xdb, 0xa0, 0x9f, + 0x92, 0xd2, 0xc2, 0x8c, 0xd1, 0x98, 0x45, 0xae, 0xab, 0xe8, 0x80, 0xeb, 0xe8, 0xed, 0x3c, 0xfa, 0xdb, 0xb3, 0x31, + 0x2d, 0x62, 0x91, 0xca, 0x2b, 0x50, 0x41, 0x80, 0x32, 0x04, 0x0d, 0xff, 0x35, 0x35, 0x00, 0x0d, 0x82, 0x1b, 0x80, + 0x7f, 0x74, 0x3a, 0x0d, 0xda, 0x9a, 0x7c, 0x4c, 0x52, 0x55, 0xe4, 0xac, 0x0d, 0x65, 0xa6, 0x92, 0x43, 0xf2, 0xb8, + 0x04, 0x3c, 0x47, 0x6c, 0x96, 0xb2, 0xb9, 0x50, 0x9b, 0x4d, 0xbd, 0x56, 0xec, 0xc8, 0x6d, 0xa3, 0x68, 0xb3, 0x16, + 0xb5, 0x9d, 0xc4, 0x7c, 0x31, 0xbd, 0xb5, 0xc2, 0xc0, 0xa9, 0x69, 0xcd, 0xcd, 0x0e, 0x74, 0x9a, 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, 0x0d, 0x69, 0xaa, 0xd0, 0xa3, 0x03, 0xbd, 0x1d, 0x02, 0x9a, 0xb3, 0x31, + 0x5d, 0xd2, 0x14, 0x2f, 0xd0, 0x74, 0x0d, 0x66, 0x29, 0x17, 0xd0, 0xd7, 0x6e, 0x9f, 0xe4, 0x0b, 0xd5, 0x13, 0xe1, + 0x2d, 0x51, 0xf0, 0xe5, 0x48, 0xc1, 0x2b, 0x2b, 0xe7, 0xb1, 0x99, 0x43, 0xc0, 0x63, 0x51, 0x25, 0x7a, 0x27, 0xc5, + 0x25, 0x28, 0x53, 0xe1, 0x08, 0x34, 0x55, 0x23, 0x96, 0x70, 0x80, 0xdb, 0x8b, 0xa7, 0x01, 0xa1, 0x20, 0xd5, 0x5d, + 0xdb, 0x15, 0x79, 0xcb, 0x8e, 0x36, 0xb7, 0x60, 0x16, 0x5b, 0xad, 0xcb, 0xd6, 0x57, 0x36, 0xd9, 0x7d, 0x5c, 0x13, + 0x6c, 0xbb, 0xb7, 0x41, 0xc2, 0x5b, 0x7a, 0x43, 0x36, 0x37, 0xfd, 0x7e, 0x08, 0xfd, 0x21, 0x54, 0x77, 0xe8, 0xb6, + 0xb3, 0x43, 0xb7, 0x3e, 0xf3, 0x6b, 0xf5, 0x7c, 0xca, 0x1b, 0xe2, 0x03, 0x9a, 0x68, 0xd1, 0x55, 0x7c, 0x07, 0x9b, + 0x3a, 0xaa, 0xa8, 0xaa, 0x3c, 0x4a, 0x28, 0xa8, 0x80, 0x33, 0x5e, 0x9e, 0x72, 0x8c, 0x6d, 0xaa, 0x9f, 0xde, 0x69, + 0x5e, 0x6d, 0x6d, 0xd6, 0x66, 0xb9, 0x3e, 0x07, 0x8b, 0x80, 0x73, 0x1e, 0x5d, 0x69, 0x5a, 0x72, 0xe9, 0x31, 0xf5, + 0x67, 0x38, 0x2a, 0xc1, 0x45, 0x9c, 0xe5, 0x3c, 0x0d, 0xe8, 0x45, 0xb3, 0xff, 0xa1, 0xb6, 0x95, 0x5a, 0x36, 0xce, + 0xdc, 0xeb, 0x90, 0x6c, 0xfe, 0xc7, 0x06, 0xea, 0x4d, 0x88, 0x11, 0x51, 0xcd, 0x82, 0x3e, 0x61, 0x10, 0x1b, 0x33, + 0x28, 0xd7, 0x49, 0xc2, 0xcb, 0x32, 0x30, 0x4a, 0xad, 0x35, 0x5b, 0x9b, 0xf3, 0xec, 0x11, 0x3b, 0x7a, 0xd4, 0x63, + 0xec, 0x96, 0xd0, 0x44, 0xeb, 0x84, 0x4c, 0x8d, 0x91, 0xa7, 0x05, 0xd2, 0x1d, 0x8a, 0xb2, 0x8b, 0xf0, 0x04, 0x85, + 0x2c, 0xed, 0x7d, 0x6e, 0x4e, 0x64, 0xf5, 0x8d, 0x36, 0xba, 0x88, 0x54, 0x22, 0xc8, 0xc6, 0x6f, 0x10, 0xb0, 0x17, + 0x9a, 0x1d, 0x90, 0xcd, 0x92, 0x9d, 0xd2, 0x33, 0x6b, 0x02, 0x03, 0xaf, 0x4f, 0x54, 0xa2, 0x19, 0x65, 0x45, 0x74, + 0x95, 0x91, 0xcb, 0x5d, 0x48, 0xa2, 0xb3, 0x90, 0xf8, 0xb9, 0x61, 0x69, 0x5d, 0x87, 0x28, 0x66, 0x36, 0x1b, 0x5e, + 0x75, 0xf7, 0x51, 0x63, 0x5b, 0x19, 0x9f, 0xea, 0x5b, 0x9b, 0x46, 0xa6, 0xd0, 0xd7, 0xe1, 0xa4, 0xdf, 0x87, 0xbf, + 0x9a, 0x7e, 0xe0, 0x2d, 0x05, 0x7f, 0xb1, 0x47, 0xa4, 0x4e, 0x58, 0x00, 0x70, 0x84, 0x39, 0xaf, 0x9a, 0x13, 0xf8, + 0x88, 0x1d, 0x6d, 0x1e, 0x85, 0xa7, 0x8d, 0x99, 0xbb, 0x0b, 0xf1, 0x52, 0x95, 0xf4, 0xbc, 0x79, 0x32, 0x03, 0xb1, + 0x0a, 0xcd, 0x7e, 0xbd, 0x65, 0x56, 0x9f, 0x00, 0x44, 0xea, 0xd6, 0x3a, 0x94, 0xe2, 0xc7, 0xa6, 0xcb, 0x64, 0x93, + 0xb2, 0x36, 0x13, 0xa5, 0x54, 0x24, 0xcd, 0x45, 0x00, 0xfd, 0x86, 0xe1, 0xa8, 0x01, 0xde, 0x5b, 0x8f, 0xbd, 0x19, + 0x1a, 0x6f, 0x4c, 0x0d, 0x3d, 0xdb, 0xe8, 0xe5, 0xed, 0x28, 0x84, 0x19, 0x8b, 0xe8, 0xd6, 0x1d, 0x8b, 0xe1, 0x29, + 0x3d, 0x81, 0x0a, 0xdf, 0x84, 0x18, 0x4d, 0x97, 0xd4, 0xf5, 0x74, 0xad, 0xb6, 0xd2, 0x0d, 0xa1, 0x39, 0x46, 0xf1, + 0xf1, 0xda, 0x76, 0x47, 0x8d, 0xd0, 0x9e, 0x50, 0x1e, 0xde, 0xd2, 0x8a, 0xde, 0x58, 0x16, 0xc1, 0xc9, 0x8f, 0xbd, + 0xfc, 0x84, 0x9e, 0x7b, 0x02, 0x93, 0xa2, 0xad, 0x01, 0xfc, 0x01, 0xf5, 0xc3, 0x59, 0x3d, 0xb5, 0x52, 0x0e, 0x4f, + 0xe1, 0x4b, 0x36, 0x20, 0x57, 0xd0, 0x8b, 0x35, 0x66, 0x47, 0x31, 0xe8, 0xa0, 0x76, 0x76, 0x87, 0x37, 0x29, 0x65, + 0x88, 0xd6, 0x77, 0x0e, 0xe2, 0xe9, 0x1f, 0xa0, 0xe9, 0x83, 0xb4, 0x30, 0xa5, 0x6b, 0x14, 0xf0, 0x80, 0xbe, 0xa9, + 0xdf, 0xcf, 0xf1, 0xb9, 0xf6, 0x2c, 0xb1, 0xb0, 0xc7, 0x4b, 0x42, 0x97, 0x5e, 0xdc, 0x28, 0x90, 0x36, 0x3b, 0x56, + 0x01, 0x58, 0x91, 0x04, 0x1a, 0x91, 0x80, 0xa5, 0x8e, 0x27, 0x2e, 0xdb, 0xa0, 0x01, 0x49, 0x54, 0x52, 0xc8, 0x12, + 0x49, 0xe0, 0x87, 0x11, 0x84, 0x28, 0x8a, 0x41, 0xdc, 0xab, 0x97, 0x57, 0x5c, 0x53, 0x03, 0x4e, 0x14, 0xc1, 0x04, + 0xeb, 0x74, 0x0a, 0xc4, 0x56, 0xac, 0x57, 0xe0, 0x79, 0xe9, 0x38, 0x71, 0x64, 0x09, 0xd0, 0x20, 0xcd, 0x97, 0x4e, + 0xbb, 0xe5, 0xed, 0x89, 0x96, 0x2a, 0x36, 0xf7, 0x5e, 0x2c, 0x2c, 0xf7, 0x58, 0xf9, 0xdb, 0x81, 0xf6, 0xc2, 0x6a, + 0x47, 0x44, 0x0d, 0x56, 0x76, 0x6d, 0xbb, 0x36, 0x94, 0x86, 0xea, 0x5e, 0x39, 0x26, 0xa0, 0xa2, 0xab, 0xb8, 0x5a, + 0x46, 0xd9, 0x08, 0xfe, 0x6c, 0xb7, 0xc1, 0x7e, 0x00, 0x16, 0x90, 0xbf, 0xbe, 0xff, 0x39, 0xc2, 0xf0, 0x4c, 0xbf, + 0xbe, 0xff, 0x79, 0xbb, 0x7d, 0x36, 0x1e, 0x1b, 0xae, 0xc0, 0xa9, 0x75, 0x80, 0x3f, 0x30, 0x6c, 0x83, 0x5d, 0xb2, + 0xdb, 0xed, 0x33, 0xe0, 0x20, 0x14, 0xdb, 0x60, 0x76, 0xb1, 0x72, 0xe4, 0x52, 0xac, 0x86, 0xde, 0x91, 0x80, 0x55, + 0xb7, 0xc3, 0x52, 0xec, 0x52, 0x1f, 0x15, 0x82, 0x51, 0x2f, 0xfa, 0x97, 0x9d, 0x02, 0x4b, 0x0a, 0xa6, 0xab, 0xc1, + 0xb2, 0xaa, 0x56, 0x65, 0xb4, 0xbf, 0x1f, 0xaf, 0xb2, 0x51, 0x99, 0xc1, 0x36, 0x2f, 0xaf, 0x2f, 0x01, 0x50, 0x21, + 0xa0, 0x8d, 0x77, 0x6b, 0x91, 0x99, 0x17, 0x0b, 0xba, 0xcc, 0x70, 0x4d, 0x82, 0xd9, 0x41, 0xce, 0xad, 0x6e, 0x72, + 0x4a, 0xec, 0x03, 0xd8, 0x1c, 0x6e, 0xb7, 0x0d, 0x7e, 0xe1, 0x68, 0xf4, 0x6c, 0xb6, 0xcc, 0xb4, 0x41, 0x27, 0x37, + 0xfb, 0x9f, 0x44, 0x5e, 0x1a, 0x2a, 0x3e, 0xc9, 0xf4, 0x65, 0x06, 0x7c, 0x1e, 0x7b, 0x2b, 0x42, 0x9f, 0xe5, 0x6a, + 0xb4, 0x06, 0xd8, 0xd8, 0xec, 0xe2, 0x6e, 0x94, 0x72, 0x88, 0x48, 0x11, 0x58, 0x75, 0xcd, 0x32, 0x23, 0xbe, 0x4d, + 0xc5, 0x5d, 0x4b, 0x15, 0xf6, 0x56, 0x78, 0xce, 0x2a, 0xdc, 0x38, 0xca, 0xf4, 0x26, 0x51, 0xf8, 0x12, 0x85, 0xa8, + 0x1c, 0x8d, 0xe9, 0x9c, 0x40, 0x2a, 0xf3, 0x98, 0x50, 0xcc, 0xe1, 0xde, 0xfd, 0x9a, 0x3a, 0x73, 0x19, 0x5f, 0xb8, + 0xf7, 0xd2, 0x97, 0x99, 0xdc, 0x4a, 0x00, 0x45, 0x52, 0xb5, 0xff, 0xf2, 0x19, 0xa9, 0xf1, 0x3f, 0x53, 0xad, 0x01, + 0xe8, 0xfd, 0x02, 0x35, 0x39, 0x82, 0x80, 0xad, 0x98, 0xfa, 0x68, 0xfa, 0x56, 0x32, 0xff, 0x01, 0x75, 0x3b, 0x82, + 0x6d, 0x54, 0xfc, 0x9c, 0xa8, 0xa2, 0x05, 0x4f, 0xd7, 0x22, 0x8d, 0x45, 0x72, 0x17, 0xf1, 0x7a, 0x8a, 0x25, 0x31, + 0x1b, 0x21, 0xeb, 0x97, 0x66, 0x17, 0x7e, 0x2e, 0x1a, 0x26, 0xe0, 0xb4, 0xf4, 0xb7, 0x95, 0xb7, 0x99, 0x2c, 0xe3, + 0x8c, 0x4c, 0xb9, 0x42, 0xec, 0xb6, 0xfa, 0x1e, 0x73, 0x82, 0x3f, 0x3d, 0x78, 0x4a, 0xe8, 0xad, 0x9c, 0x96, 0x08, + 0x4a, 0x27, 0x52, 0xeb, 0xaa, 0x89, 0xfd, 0x9a, 0x42, 0x14, 0x07, 0xc1, 0x20, 0x74, 0xa7, 0x69, 0x9f, 0xe2, 0xfb, + 0x6c, 0xd9, 0x6f, 0x4d, 0xd9, 0x92, 0x6c, 0x04, 0x74, 0x4c, 0x3a, 0x6f, 0x4f, 0x6f, 0xcf, 0xce, 0xbc, 0xdf, 0xa0, + 0x09, 0x07, 0xd5, 0x0d, 0xb4, 0xab, 0x20, 0xd3, 0x18, 0xc5, 0x66, 0x31, 0xd6, 0x6e, 0x4d, 0x44, 0x10, 0x74, 0xba, + 0x9c, 0x85, 0xed, 0x76, 0x42, 0x7c, 0x09, 0x24, 0x50, 0xe0, 0xca, 0x45, 0x39, 0x09, 0x89, 0xba, 0x90, 0xe9, 0xc9, + 0xba, 0x96, 0x2c, 0xd0, 0x6b, 0xec, 0x20, 0xa0, 0xc7, 0xdc, 0x3e, 0x05, 0xf4, 0x7d, 0xc1, 0x8e, 0xf9, 0x20, 0x18, + 0x62, 0x7c, 0xd5, 0x80, 0xde, 0x48, 0xf5, 0x08, 0x1e, 0xc2, 0xc0, 0x72, 0xd1, 0x57, 0x05, 0x43, 0x58, 0xa1, 0xbf, + 0x52, 0x36, 0xf9, 0xe6, 0xef, 0x6e, 0x7e, 0xcf, 0xb5, 0x98, 0x1d, 0x84, 0xe2, 0xf6, 0x7a, 0x02, 0xc4, 0xaf, 0xe2, + 0x57, 0x60, 0x5d, 0xad, 0x25, 0xde, 0x6e, 0x7a, 0xfe, 0x14, 0xbe, 0x1c, 0xdd, 0x7e, 0x52, 0x9a, 0x4f, 0x20, 0x48, + 0x8d, 0x93, 0x94, 0xbb, 0xef, 0x3e, 0x4a, 0x57, 0x11, 0x8c, 0x16, 0x20, 0xd6, 0xdd, 0x5b, 0xc9, 0x59, 0x53, 0xf8, + 0x8f, 0x75, 0xbe, 0xc7, 0xd8, 0x21, 0xf2, 0x14, 0xa7, 0xbf, 0x01, 0x86, 0x7d, 0xe7, 0xdf, 0xca, 0xac, 0x21, 0xd1, + 0xb9, 0xfa, 0x08, 0xe8, 0xff, 0x58, 0x8f, 0xdf, 0x31, 0x4a, 0xfa, 0x92, 0x38, 0x47, 0xb8, 0x22, 0x5e, 0xa2, 0xa9, + 0x5e, 0x6f, 0x5c, 0xd3, 0x4f, 0x85, 0x79, 0xa1, 0x15, 0x1c, 0xf6, 0xad, 0x51, 0x78, 0xe0, 0x99, 0xf7, 0x9b, 0x68, + 0x08, 0xba, 0x7f, 0xc7, 0xbd, 0xf1, 0x9b, 0x60, 0x19, 0xde, 0x94, 0xb3, 0xcc, 0xdc, 0xe1, 0x6e, 0x32, 0x91, 0xca, + 0x1b, 0xc6, 0x82, 0xb5, 0x50, 0xe6, 0xab, 0x69, 0x30, 0xdb, 0xd4, 0x91, 0x4a, 0x76, 0xdf, 0xbf, 0x6d, 0x9c, 0xb0, + 0xd9, 0x20, 0x38, 0xad, 0x64, 0x11, 0x5f, 0xf2, 0x60, 0xaa, 0x55, 0x14, 0x59, 0xd6, 0xef, 0x67, 0x80, 0x0c, 0xe3, + 0xb4, 0x77, 0xf0, 0x64, 0xa9, 0x99, 0x09, 0x71, 0x6d, 0x75, 0x16, 0xf0, 0xd6, 0x8c, 0xe6, 0x71, 0x05, 0xbb, 0xcc, + 0x57, 0x52, 0xfc, 0xd9, 0x92, 0x64, 0x63, 0xfd, 0x0d, 0x19, 0xb6, 0x95, 0xcf, 0x9c, 0x03, 0xc6, 0xcc, 0x8d, 0x54, + 0x41, 0xee, 0x7a, 0xc0, 0x08, 0x21, 0x11, 0x10, 0xce, 0x62, 0xe2, 0x4e, 0x98, 0xf0, 0x8f, 0x2e, 0x30, 0x4e, 0x8c, + 0x81, 0x71, 0x3e, 0xca, 0x90, 0xd3, 0x63, 0x3e, 0x48, 0x1a, 0xb3, 0xf5, 0xa7, 0x2a, 0x91, 0x5e, 0x4b, 0x42, 0xcf, + 0xe0, 0xf7, 0xb8, 0xc5, 0x03, 0x35, 0x82, 0x53, 0xba, 0x9b, 0xd3, 0xfe, 0xab, 0x82, 0x0c, 0xff, 0x02, 0xef, 0xae, + 0xd8, 0x5e, 0x96, 0x13, 0x58, 0xdc, 0xb1, 0x57, 0x3c, 0xcd, 0x55, 0x8b, 0x13, 0xe2, 0x11, 0x8b, 0xdc, 0x27, 0x16, + 0x30, 0xa2, 0x86, 0xd1, 0xf8, 0xf1, 0xf4, 0xe4, 0xad, 0xc6, 0x6c, 0xca, 0xfd, 0x0f, 0x60, 0x44, 0xb5, 0xb4, 0xdd, + 0x0e, 0xf8, 0x72, 0x84, 0x06, 0xdb, 0xa9, 0x1b, 0xec, 0x7e, 0xdf, 0xa4, 0x1d, 0x95, 0x5e, 0x36, 0x27, 0x06, 0xdd, + 0x51, 0xda, 0x2c, 0x95, 0x41, 0x6d, 0x57, 0xe1, 0x68, 0x3e, 0x6b, 0xc4, 0xaa, 0xde, 0x87, 0xe1, 0x92, 0xc6, 0x56, + 0x56, 0x6e, 0x77, 0x13, 0x8e, 0x6c, 0x02, 0x5c, 0x9f, 0x82, 0xb2, 0x6a, 0xce, 0x41, 0x0b, 0x3a, 0x13, 0x38, 0xa2, + 0xed, 0x36, 0x84, 0x08, 0x1c, 0xc5, 0x70, 0x32, 0x0b, 0x8b, 0xe1, 0x50, 0x0d, 0x7c, 0x41, 0x48, 0xf4, 0xa9, 0x98, + 0x67, 0x0b, 0x85, 0xd8, 0xe3, 0xef, 0xa4, 0xdf, 0x0a, 0xc5, 0x29, 0xf7, 0x7e, 0x13, 0x64, 0xf3, 0x7b, 0x8a, 0x31, + 0x07, 0x9d, 0x66, 0x33, 0x03, 0x09, 0xeb, 0x71, 0x45, 0xd4, 0x3a, 0xb2, 0xb3, 0x01, 0xaa, 0x58, 0x34, 0x85, 0x05, + 0x75, 0x8b, 0x27, 0xd6, 0x33, 0x7a, 0x0f, 0x2a, 0x41, 0x54, 0x0b, 0x76, 0x63, 0xb8, 0xd6, 0x3e, 0x89, 0x50, 0x52, + 0x4e, 0x9a, 0xcc, 0x8c, 0x15, 0x0d, 0x16, 0x20, 0x24, 0x8d, 0xcb, 0xea, 0x8d, 0x4c, 0xb3, 0x8b, 0x0c, 0x10, 0x13, + 0x9c, 0xff, 0x9c, 0x6c, 0xbc, 0x79, 0xae, 0xe6, 0xa5, 0x2b, 0x71, 0x66, 0x61, 0x3e, 0xba, 0xde, 0xd2, 0x82, 0x44, + 0x05, 0xd0, 0x28, 0x5f, 0xcb, 0xf3, 0xd3, 0x8e, 0x55, 0xc8, 0xee, 0x87, 0x53, 0x65, 0x3b, 0xc4, 0x8f, 0x58, 0x45, + 0xbc, 0xd3, 0xba, 0x52, 0x22, 0x8d, 0x8e, 0xb6, 0x01, 0x31, 0x6c, 0xd9, 0xb7, 0xa8, 0xe1, 0x83, 0x30, 0x83, 0x4e, + 0xf2, 0x83, 0x9e, 0xd1, 0xb1, 0x35, 0x90, 0xf4, 0xb5, 0x08, 0xbe, 0x46, 0x47, 0x3a, 0x51, 0xa6, 0x91, 0x98, 0x42, + 0xa2, 0x5f, 0x2f, 0xb4, 0xc6, 0x32, 0xca, 0xbe, 0x22, 0xff, 0x7b, 0xdd, 0xbd, 0xdf, 0xc4, 0x76, 0x0b, 0x93, 0xec, + 0x79, 0x5c, 0xc1, 0xa6, 0x46, 0xad, 0x10, 0xce, 0xce, 0x71, 0x85, 0xda, 0xb1, 0x5e, 0x58, 0x02, 0x79, 0x00, 0x5b, + 0x91, 0x06, 0x65, 0x90, 0xec, 0x53, 0x31, 0x17, 0x0b, 0x27, 0xca, 0x91, 0x0a, 0xef, 0x4b, 0x8e, 0x52, 0x0e, 0x57, + 0xb1, 0xb0, 0x60, 0xc8, 0xaf, 0x8e, 0x2e, 0x0a, 0x79, 0x05, 0x92, 0x12, 0xc3, 0x50, 0x59, 0x5e, 0x17, 0x57, 0x6d, + 0x49, 0x68, 0xef, 0x0c, 0x40, 0x58, 0x0a, 0x10, 0xbc, 0x34, 0x6a, 0x88, 0xd9, 0x46, 0xed, 0xae, 0xe8, 0x5e, 0x72, + 0x40, 0x9d, 0xee, 0xda, 0xad, 0x37, 0x65, 0x9b, 0x6d, 0xc5, 0x85, 0x7f, 0x42, 0xe9, 0xc7, 0x7c, 0x50, 0xf8, 0x54, + 0x02, 0x37, 0xbe, 0xda, 0x64, 0xd9, 0xc5, 0x1d, 0x2e, 0xfd, 0xaa, 0x31, 0x7e, 0xfd, 0x7e, 0x4f, 0x2d, 0x84, 0x46, + 0x2a, 0x30, 0xdf, 0x3e, 0x33, 0x55, 0x19, 0x4d, 0xa9, 0xbd, 0x04, 0x57, 0xce, 0x7e, 0x04, 0x15, 0x71, 0x5d, 0x91, + 0xc9, 0xd4, 0x00, 0xed, 0x79, 0x59, 0xe1, 0x56, 0x16, 0xe0, 0xb1, 0x13, 0x90, 0xed, 0x96, 0x87, 0x81, 0x3e, 0x74, + 0x02, 0x7f, 0x4b, 0x9e, 0x22, 0xb3, 0x66, 0x1f, 0x7f, 0xd1, 0x82, 0x7f, 0x6c, 0xc1, 0xcf, 0x28, 0xee, 0xb4, 0x32, + 0xff, 0x56, 0x5a, 0xb7, 0xb8, 0x7f, 0x27, 0xd3, 0x84, 0xa2, 0x32, 0xa1, 0xf6, 0x2b, 0xfd, 0x97, 0x09, 0x96, 0xa4, + 0xb2, 0x7f, 0x90, 0xf0, 0xc1, 0xac, 0xf1, 0xc4, 0x1a, 0x4f, 0x86, 0xd3, 0xad, 0x34, 0x0c, 0x01, 0x0a, 0xfd, 0xbc, + 0xcc, 0x15, 0xd5, 0xcf, 0xbf, 0xac, 0xf9, 0x9a, 0x37, 0x5b, 0x6c, 0x93, 0x1e, 0x68, 0xb0, 0x97, 0x47, 0x53, 0x0a, + 0x27, 0x51, 0xe7, 0x46, 0xa2, 0x2e, 0x6a, 0x96, 0xa1, 0x3a, 0xc1, 0xab, 0x79, 0xaa, 0x87, 0xbd, 0x99, 0x88, 0xd6, + 0x4a, 0xca, 0x12, 0x03, 0xd6, 0x3a, 0xf2, 0x90, 0xdc, 0xad, 0x75, 0xdc, 0x69, 0xa8, 0x4b, 0x53, 0x28, 0x01, 0x56, + 0xb8, 0x00, 0x47, 0xd0, 0xcf, 0x45, 0xc8, 0xe1, 0x9a, 0xaa, 0xf4, 0x0b, 0x9a, 0x92, 0x27, 0x9e, 0xa2, 0x56, 0x2b, + 0xd2, 0xed, 0x47, 0x39, 0x76, 0xc3, 0x37, 0x4e, 0xc8, 0x89, 0x11, 0xfa, 0xbb, 0x63, 0x29, 0x67, 0x68, 0xf1, 0xa0, + 0x4e, 0xb0, 0x5e, 0xde, 0x52, 0xa0, 0x98, 0xa3, 0xcb, 0xaa, 0x6b, 0x5e, 0xa3, 0xed, 0xcb, 0xb2, 0xdf, 0xcf, 0x6d, + 0x3d, 0x29, 0x3b, 0xda, 0x2c, 0xcd, 0x3e, 0x44, 0xc5, 0x14, 0xee, 0xfa, 0x44, 0xf3, 0x57, 0xa1, 0xbe, 0x6a, 0xcb, + 0x9c, 0x8f, 0x38, 0xe2, 0x62, 0xe4, 0xa4, 0xfe, 0x45, 0x4d, 0xbd, 0x12, 0xf7, 0xab, 0x4a, 0xbe, 0x13, 0xc6, 0x8a, + 0xd1, 0x01, 0xf5, 0xa7, 0x4a, 0xe5, 0xfd, 0xb2, 0x00, 0xb8, 0x27, 0xc1, 0x3e, 0x81, 0x7d, 0x85, 0x46, 0xf8, 0x6d, + 0x09, 0xf8, 0x37, 0x8a, 0x1b, 0xb0, 0x0a, 0x0c, 0x30, 0x9a, 0x6c, 0xcf, 0x69, 0x02, 0x07, 0x9c, 0xd0, 0x2a, 0x0a, + 0x2a, 0xcc, 0xd0, 0x50, 0x5b, 0x18, 0x3d, 0x45, 0x19, 0xb7, 0xca, 0xec, 0xdd, 0x18, 0x3b, 0x2d, 0xf0, 0x1a, 0xfe, + 0x7c, 0x5e, 0xe8, 0x61, 0xa3, 0x0e, 0xd2, 0xa3, 0x93, 0x98, 0xfe, 0xb8, 0x85, 0x93, 0x9b, 0x85, 0xb3, 0xac, 0x59, + 0x02, 0xdd, 0x81, 0x0b, 0x62, 0xdc, 0xef, 0xe7, 0x70, 0x64, 0x9a, 0x91, 0x2f, 0x58, 0x4e, 0x63, 0xb6, 0xa4, 0xda, + 0xd3, 0xee, 0xb2, 0x0a, 0x73, 0xba, 0xb4, 0x32, 0xde, 0x94, 0x81, 0xca, 0x68, 0xbb, 0x0d, 0xe1, 0x4f, 0xb7, 0xb5, + 0x4b, 0x3a, 0x5f, 0x42, 0x06, 0xf8, 0x03, 0x12, 0x51, 0xc4, 0xbe, 0xfe, 0xb7, 0x1a, 0xa7, 0xf4, 0x44, 0x69, 0xcd, + 0x12, 0xba, 0x66, 0xba, 0x7e, 0x7a, 0xc1, 0xd6, 0x8d, 0xa5, 0xb0, 0xdd, 0x86, 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, 0xf9, 0x50, 0x99, 0xaf, 0x8d, 0x47, 0xdc, 0xbf, 0xd2, 0x30, 0x31, 0x45, 0xa2, 0x42, 0x74, 0xf6, + 0x1b, 0xc8, 0x72, 0x04, 0xe0, 0x58, 0x9e, 0xca, 0x9a, 0xfe, 0x98, 0x42, 0x1c, 0x74, 0x68, 0xd0, 0xbb, 0x42, 0x5e, + 0x65, 0x25, 0x0f, 0xf1, 0x9e, 0xe0, 0x69, 0x46, 0xef, 0x37, 0xf8, 0xd0, 0xd6, 0x1e, 0x3d, 0x41, 0x36, 0x9e, 0x72, + 0xbf, 0xfe, 0x4e, 0x84, 0x73, 0x88, 0x56, 0xb9, 0xa0, 0x5a, 0x5d, 0xed, 0x00, 0xa8, 0x3c, 0xdb, 0xab, 0x47, 0x70, + 0xba, 0xe9, 0xeb, 0x5b, 0x15, 0x3a, 0x73, 0x00, 0x69, 0x0f, 0xc9, 0xba, 0xe6, 0x7a, 0x07, 0xb8, 0x23, 0xb1, 0x5a, + 0x03, 0x8d, 0x75, 0x5b, 0xb3, 0xd3, 0x1e, 0xc5, 0x63, 0x22, 0x33, 0x63, 0x91, 0x62, 0xcc, 0xdd, 0x3a, 0x2d, 0x8a, + 0x36, 0x68, 0x86, 0xb0, 0x7b, 0xd7, 0xe1, 0xeb, 0x56, 0x84, 0xf5, 0xfb, 0x6d, 0x5f, 0x60, 0x34, 0x8c, 0xb9, 0x76, + 0xcf, 0x33, 0x74, 0xc3, 0x06, 0xdb, 0xc8, 0x79, 0x88, 0x7c, 0x98, 0xa9, 0x03, 0x51, 0xd6, 0xd6, 0x80, 0xed, 0x11, + 0xd7, 0x9b, 0x56, 0xf1, 0xf3, 0x2a, 0xe6, 0x6c, 0xcf, 0x1a, 0xa7, 0xb4, 0xbe, 0xc6, 0x35, 0xc7, 0x55, 0x21, 0xa2, + 0xb6, 0x9e, 0xf1, 0x30, 0xec, 0x7c, 0x81, 0x3b, 0xb3, 0xc2, 0xe0, 0x45, 0x58, 0x2a, 0xd9, 0xa9, 0x5c, 0x7f, 0x0e, + 0x5b, 0x1c, 0xa4, 0xf2, 0xa5, 0xd7, 0xdf, 0x7f, 0xf9, 0xe2, 0x0b, 0x74, 0x53, 0x73, 0x7e, 0x04, 0x41, 0x26, 0xd0, + 0x21, 0x4b, 0xa9, 0x1e, 0xbf, 0x2b, 0x80, 0xda, 0xc3, 0x3c, 0x7c, 0x57, 0x30, 0x11, 0x5f, 0x67, 0x97, 0x71, 0x25, + 0x8b, 0xd1, 0x35, 0x17, 0xa9, 0x2c, 0xac, 0xd4, 0x38, 0x38, 0x5e, 0xad, 0x72, 0x1e, 0x80, 0xa9, 0xbc, 0x65, 0x94, + 0x6d, 0x65, 0x99, 0x1e, 0x5c, 0x2d, 0x4f, 0xaf, 0xb4, 0xe8, 0xbc, 0xbc, 0xbe, 0x0c, 0x22, 0xfc, 0x75, 0x6e, 0x7e, + 0x5c, 0xc5, 0xe5, 0xc7, 0x20, 0xb2, 0x36, 0x75, 0xe6, 0x07, 0x4a, 0xe5, 0xc1, 0x7f, 0x0a, 0x64, 0xba, 0xdf, 0x15, + 0x60, 0x99, 0x6d, 0x2b, 0x3e, 0x8c, 0xb1, 0xd6, 0xe1, 0x84, 0xcc, 0x54, 0x89, 0xde, 0xbb, 0x64, 0x5d, 0x80, 0xb5, + 0x9f, 0xc2, 0x32, 0x56, 0xb9, 0x66, 0x58, 0x99, 0xaa, 0xc8, 0xcc, 0xca, 0x9a, 0xed, 0x87, 0xd6, 0x89, 0x66, 0x8e, + 0xde, 0x02, 0xfa, 0x81, 0xec, 0x5f, 0xd2, 0x72, 0xcd, 0x3c, 0x1f, 0x9b, 0xc6, 0xeb, 0x47, 0xfb, 0x97, 0x6e, 0xc1, + 0xde, 0xda, 0x3b, 0x39, 0x0a, 0x13, 0xc1, 0xb3, 0xd6, 0x8c, 0x2f, 0xf2, 0xac, 0x80, 0x95, 0x33, 0x19, 0x8f, 0xa9, + 0xb7, 0xb4, 0x5a, 0x37, 0x47, 0x87, 0xe4, 0x9a, 0x3d, 0xae, 0x1e, 0x73, 0xb2, 0xcf, 0x5b, 0xa6, 0xb6, 0x6d, 0xeb, + 0x38, 0x4f, 0x93, 0xaf, 0x4c, 0xf7, 0xc5, 0xda, 0x46, 0x44, 0x57, 0xce, 0x7d, 0xce, 0x2b, 0xb8, 0xf5, 0x4d, 0x69, + 0xe8, 0xb5, 0x04, 0x20, 0x3a, 0x6d, 0xc0, 0x5f, 0xb0, 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, 0xb1, 0xbb, 0xca, 0xa5, 0x13, 0xf5, + 0x5b, 0x26, 0x5c, 0xb9, 0x12, 0x04, 0x64, 0x5a, 0xb0, 0x5e, 0x61, 0x76, 0x91, 0x5c, 0x03, 0x21, 0x03, 0xc3, 0xd7, + 0x60, 0x2d, 0x4a, 0x6e, 0xac, 0x60, 0xbd, 0x7b, 0xbe, 0x4e, 0x10, 0x52, 0xf0, 0xc0, 0x4d, 0xd0, 0x0f, 0xad, 0x9b, + 0xb7, 0xa3, 0x44, 0x19, 0xc4, 0xe3, 0xd6, 0x4e, 0x39, 0x48, 0x20, 0x00, 0xf7, 0x54, 0x85, 0xe0, 0x50, 0x20, 0xeb, + 0xe0, 0x6a, 0xc6, 0x11, 0x5c, 0x5d, 0x39, 0x73, 0x71, 0x03, 0xb0, 0xae, 0xfc, 0xb9, 0x6c, 0x70, 0x61, 0x3d, 0xa2, + 0xca, 0x9c, 0x71, 0x8a, 0x41, 0x8c, 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, 0x20, 0x0a, 0xb5, 0x01, 0x43, 0xe0, 0x90, 0xf8, 0x83, 0x41, 0xa8, 0xf1, 0x4e, 0x06, 0x2a, 0x20, 0x16, + 0xf1, 0x78, 0x6c, 0xc4, 0xcd, 0x0a, 0xc7, 0x43, 0x0c, 0x7e, 0xd5, 0x7c, 0x41, 0x02, 0x42, 0x4d, 0x69, 0xe8, 0xf2, + 0x18, 0x0e, 0x27, 0x7b, 0x13, 0x48, 0xc5, 0xcc, 0x4c, 0x15, 0xc6, 0xc6, 0x24, 0x82, 0x78, 0xa7, 0x9d, 0xf5, 0x42, + 0xb9, 0xdd, 0x35, 0x1a, 0xc8, 0x95, 0xc1, 0x17, 0x55, 0x3c, 0xd9, 0x1b, 0x76, 0x55, 0x8c, 0xa3, 0x70, 0x6d, 0x94, + 0x6f, 0x67, 0x87, 0x00, 0x5e, 0x7b, 0x36, 0xf4, 0xe5, 0x12, 0x67, 0xfb, 0x4f, 0xc9, 0xe3, 0xa7, 0x84, 0x9e, 0xb1, + 0xb3, 0xaf, 0x9e, 0xd2, 0x33, 0x45, 0x4e, 0xf6, 0x26, 0xd1, 0x35, 0xb3, 0x98, 0x2f, 0x07, 0xaa, 0x09, 0xf4, 0x72, + 0xb4, 0x16, 0x6a, 0x81, 0x69, 0x87, 0xa6, 0xf0, 0xdb, 0xf1, 0x5e, 0x30, 0xb8, 0x6e, 0x37, 0xfd, 0xba, 0xdd, 0x56, + 0xcf, 0xab, 0x6b, 0xef, 0x20, 0xda, 0x2d, 0x66, 0xf2, 0xf7, 0xf1, 0x9e, 0x9b, 0x03, 0xac, 0xef, 0xe1, 0x31, 0x31, + 0x4d, 0xda, 0x19, 0x15, 0xbf, 0xa6, 0x27, 0xd8, 0x87, 0x66, 0x91, 0x1d, 0x7d, 0x18, 0xfe, 0x5b, 0x9d, 0xa8, 0xcf, + 0xbe, 0x3a, 0x00, 0x72, 0x04, 0x32, 0x50, 0x2c, 0x11, 0xcc, 0x70, 0xa0, 0x29, 0xa0, 0x20, 0xd3, 0xe3, 0x4e, 0xf5, + 0xf0, 0xab, 0x51, 0x53, 0x33, 0x72, 0x0d, 0x53, 0x83, 0x6d, 0xc1, 0x0f, 0x54, 0x37, 0xf4, 0x37, 0x1a, 0xdd, 0x48, + 0x3b, 0x99, 0x99, 0x97, 0xd4, 0xc6, 0x75, 0xbb, 0x86, 0x00, 0xc6, 0x0e, 0x5e, 0x50, 0xb2, 0xaf, 0x0f, 0x2f, 0xf7, + 0x70, 0x15, 0x01, 0x4a, 0x16, 0x0b, 0xbe, 0x1e, 0x5c, 0xea, 0xcd, 0xbd, 0x17, 0x90, 0xc1, 0xd7, 0xc1, 0xd1, 0xd7, + 0x03, 0x39, 0x08, 0x0e, 0xf7, 0x2f, 0x8f, 0x02, 0x67, 0xdc, 0x0f, 0x21, 0x1e, 0x55, 0x45, 0x31, 0x13, 0xa6, 0x8a, + 0xc4, 0xd6, 0x9e, 0xdb, 0x7a, 0x95, 0xf1, 0x19, 0x4d, 0xa7, 0x16, 0xf9, 0x3b, 0x4c, 0x59, 0x6c, 0x7e, 0x07, 0x13, + 0x7e, 0x15, 0x44, 0x2e, 0x08, 0xea, 0x2c, 0x8f, 0x62, 0xba, 0x64, 0xb7, 0x22, 0x4c, 0x69, 0xb2, 0x9f, 0x13, 0x12, + 0x85, 0x4b, 0x05, 0x9e, 0xa7, 0x5e, 0x27, 0x10, 0xc7, 0xd5, 0x7d, 0x7e, 0x2b, 0xc2, 0x25, 0xcd, 0xf7, 0x13, 0xd2, + 0x2a, 0xc2, 0x45, 0x64, 0xd9, 0xd4, 0xf4, 0x82, 0x85, 0x2b, 0x7a, 0x09, 0xcc, 0x94, 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, 0xed, 0x4d, 0x6c, 0x4e, 0xf6, 0x32, 0x5a, 0x2b, 0x97, 0x55, 0xcb, 0x90, 0x14, 0x6b, 0x86, + 0xfc, 0x3d, 0x4a, 0x4e, 0xad, 0xc0, 0x93, 0x5d, 0xf0, 0x2a, 0x59, 0xfa, 0x07, 0x95, 0xb5, 0x1a, 0xb0, 0xc7, 0x88, + 0x65, 0xa1, 0x70, 0xec, 0xdf, 0x64, 0xac, 0x58, 0xfb, 0x02, 0x8d, 0x18, 0xb9, 0xb7, 0x37, 0x19, 0xf3, 0x62, 0xae, + 0x26, 0x6b, 0x2f, 0x54, 0x9d, 0x97, 0x9e, 0xb7, 0x78, 0x2f, 0xa7, 0xd4, 0x30, 0x12, 0xd1, 0xbd, 0xb1, 0x32, 0xa3, + 0x54, 0x89, 0x5a, 0x83, 0x46, 0x04, 0x1b, 0xbb, 0xe0, 0x97, 0xe0, 0x84, 0xca, 0x3d, 0x75, 0xb6, 0x6f, 0xa7, 0x54, + 0x7a, 0xc0, 0xb2, 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, + 0x24, 0x77, 0xb9, 0x6e, 0x05, 0xc9, 0x7d, 0x3a, 0x7e, 0xaa, 0x07, 0x3a, 0x5d, 0x6b, 0xc7, 0x43, 0x9f, 0xdf, 0x46, + 0x7c, 0x6d, 0xdd, 0x7b, 0xaa, 0xb5, 0x0a, 0x65, 0xa0, 0xc5, 0x8a, 0xca, 0x95, 0x5a, 0xd2, 0xfb, 0x5d, 0x04, 0xc0, + 0x22, 0x36, 0x66, 0xe3, 0x5d, 0xdb, 0xac, 0x10, 0x34, 0xba, 0xec, 0x68, 0x13, 0x0f, 0x58, 0xa2, 0x5b, 0x3b, 0x98, + 0xd0, 0xf8, 0x88, 0x95, 0xfd, 0x7e, 0x7e, 0x04, 0xf4, 0x54, 0x1b, 0x31, 0x15, 0x70, 0xe4, 0x7f, 0x69, 0x45, 0xa6, + 0x28, 0xb0, 0x59, 0x53, 0x77, 0x6b, 0x2c, 0x23, 0xd1, 0x97, 0x29, 0x5d, 0x9e, 0xf0, 0x0c, 0x98, 0xd6, 0xeb, 0x96, + 0xe3, 0xca, 0xae, 0xe2, 0xc8, 0x53, 0x61, 0x59, 0x71, 0x5e, 0x85, 0xe3, 0xad, 0xc7, 0x37, 0xd8, 0x37, 0x6c, 0xda, + 0x85, 0x3f, 0x84, 0xb0, 0x10, 0xde, 0x64, 0x70, 0x1b, 0xd1, 0x76, 0x12, 0xa8, 0xbc, 0x31, 0xd7, 0x09, 0x65, 0x73, + 0xbb, 0x5e, 0x7b, 0x06, 0xe9, 0xc4, 0x1c, 0x28, 0xd5, 0x08, 0x5a, 0xa3, 0x59, 0x50, 0x35, 0xe2, 0x91, 0xe3, 0xe1, + 0x9d, 0x41, 0xac, 0x96, 0x2f, 0x69, 0x2a, 0x45, 0x03, 0x30, 0x2e, 0x80, 0xcb, 0xd3, 0xaf, 0xef, 0x7f, 0x3e, 0xe5, + 0x71, 0x91, 0x2c, 0xdf, 0xc5, 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, 0xdd, 0x07, 0x20, 0x4f, 0xe3, 0x42, 0x1a, 0x49, 0x5d, 0x88, 0x31, 0x17, 0xf1, 0xba, 0x3e, 0x1e, 0x37, + 0xba, 0x5e, 0xb2, 0x67, 0xe3, 0x27, 0xd3, 0x37, 0x59, 0x98, 0x0d, 0x04, 0x19, 0x55, 0x4b, 0x2e, 0x5a, 0xa6, 0x9c, + 0xca, 0x24, 0x00, 0x7d, 0x3c, 0x7b, 0x8c, 0x1d, 0x8c, 0xc7, 0x64, 0xd3, 0x16, 0x0f, 0xf0, 0x70, 0xb9, 0x0e, 0x0b, + 0x32, 0xd3, 0x75, 0x44, 0x81, 0xe0, 0xb7, 0x55, 0x00, 0x48, 0x8e, 0xb6, 0x2a, 0xc3, 0xa5, 0xb1, 0x67, 0xe3, 0x09, + 0x95, 0xd8, 0xed, 0x90, 0xd4, 0x5e, 0x85, 0x6e, 0xe6, 0xa5, 0xef, 0x51, 0x24, 0x8d, 0xcb, 0xd2, 0x4e, 0xa5, 0x52, + 0xed, 0x99, 0x99, 0xeb, 0x1a, 0xc4, 0x60, 0x08, 0x75, 0xdd, 0xa5, 0x57, 0xf7, 0x6e, 0x73, 0xad, 0xd9, 0x0e, 0x78, + 0xaf, 0x41, 0x33, 0x94, 0xbc, 0xc5, 0xbc, 0x75, 0x45, 0xd4, 0x74, 0xb5, 0x06, 0xb3, 0x62, 0x94, 0x2d, 0x45, 0xe9, + 0x9a, 0x82, 0x52, 0x30, 0xba, 0x58, 0x7b, 0x0b, 0xf7, 0x8d, 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, 0xc7, + 0x15, 0x39, 0x06, 0x47, 0x2f, 0x93, 0xd3, 0x50, 0xe0, 0x1f, 0x33, 0x05, 0x62, 0x3a, 0x54, 0xf7, 0x1b, 0xdc, 0xfc, + 0xff, 0x28, 0x58, 0xe0, 0xf1, 0xad, 0x97, 0xb8, 0x8d, 0xfe, 0x51, 0xf8, 0xb4, 0xf4, 0xb9, 0xf4, 0x5d, 0x5d, 0x3c, + 0x69, 0x6f, 0x36, 0x4a, 0x96, 0x59, 0x9e, 0xbe, 0x95, 0x29, 0x07, 0x91, 0x19, 0x5a, 0x83, 0xb2, 0x23, 0xd1, 0xb8, + 0xe1, 0x81, 0x11, 0x63, 0xe3, 0xc6, 0xf7, 0x63, 0x06, 0xb2, 0x61, 0xb0, 0xfa, 0x66, 0xa9, 0x4c, 0xd6, 0x57, 0x80, + 0x29, 0xa2, 0xe4, 0x27, 0x2f, 0x73, 0x0e, 0x4f, 0xa1, 0xbe, 0x7e, 0x81, 0xdb, 0x5c, 0xe9, 0xfb, 0x9c, 0xff, 0x98, + 0xd1, 0x1f, 0x11, 0xe8, 0x24, 0x5e, 0x81, 0xdc, 0xe3, 0x39, 0xd4, 0x8d, 0x30, 0xb5, 0x1c, 0x83, 0x03, 0x21, 0x1a, + 0x88, 0xa8, 0x58, 0xa0, 0xa0, 0x2e, 0x0c, 0xb0, 0x86, 0xba, 0x60, 0x0e, 0xcf, 0x73, 0x99, 0x7c, 0x9c, 0x1a, 0x9f, + 0xf9, 0x61, 0x8c, 0x31, 0x93, 0x83, 0x41, 0x58, 0xcd, 0x82, 0xe1, 0x78, 0x34, 0x39, 0x78, 0x06, 0xe7, 0x76, 0x30, + 0x0e, 0xc8, 0x20, 0xa8, 0xcb, 0x55, 0x2c, 0x68, 0x79, 0x7d, 0x69, 0xcb, 0xc0, 0x8f, 0xeb, 0x60, 0xf0, 0x8f, 0xc2, + 0x53, 0xbc, 0x83, 0xe6, 0xe4, 0x4c, 0x86, 0x60, 0x63, 0xbf, 0x26, 0x20, 0x29, 0xeb, 0x69, 0x7e, 0x52, 0x1f, 0x6e, + 0x4c, 0x69, 0xff, 0xcc, 0xe1, 0x05, 0x87, 0x1d, 0x12, 0x28, 0x90, 0xc6, 0xd3, 0x6c, 0xf4, 0x5a, 0x29, 0x72, 0xdf, + 0x15, 0x1c, 0xee, 0xcc, 0x3d, 0x67, 0x7a, 0xe4, 0x14, 0x12, 0xcd, 0x2c, 0xe0, 0x46, 0xfe, 0x5a, 0x5c, 0xc7, 0x79, + 0x96, 0xee, 0x35, 0xdf, 0xec, 0x95, 0x77, 0xa2, 0x8a, 0x6f, 0x47, 0x81, 0xb1, 0x26, 0xe4, 0xbe, 0xea, 0x09, 0xd0, + 0x13, 0x60, 0x0b, 0x80, 0x01, 0xf1, 0x8e, 0x99, 0xc9, 0x8c, 0x47, 0xe0, 0x11, 0xd8, 0xf4, 0x81, 0x2c, 0xee, 0x9c, + 0x4b, 0x92, 0xbf, 0x99, 0x4a, 0x7b, 0xd5, 0x2b, 0x77, 0x0a, 0xb2, 0x5e, 0x6d, 0xe5, 0xae, 0x5b, 0x9f, 0x7d, 0xd3, + 0xe1, 0x15, 0x78, 0x2e, 0xc1, 0x2d, 0xb2, 0xdf, 0x6f, 0x0a, 0x2a, 0x85, 0x51, 0x11, 0xef, 0x24, 0xd7, 0xe8, 0xdf, + 0xee, 0x8d, 0x8d, 0x22, 0xb9, 0xe5, 0xc3, 0x03, 0xa8, 0x33, 0x79, 0x57, 0xdc, 0xce, 0x21, 0x6a, 0xeb, 0x6e, 0x3c, + 0xb0, 0xda, 0xa0, 0x5d, 0xd6, 0x1c, 0xc1, 0x85, 0x17, 0x7b, 0x19, 0x8c, 0x05, 0xce, 0xca, 0x48, 0xa9, 0x71, 0x0d, + 0xa9, 0x05, 0x9f, 0xe4, 0xe9, 0x3d, 0x64, 0xa9, 0x27, 0x41, 0x91, 0xe3, 0x59, 0x0c, 0x99, 0xc6, 0xdb, 0xc0, 0xe3, + 0x77, 0x32, 0x04, 0x69, 0xda, 0x76, 0xdb, 0x1c, 0x81, 0xb2, 0x7b, 0x60, 0x4a, 0x52, 0xd7, 0xc6, 0xd4, 0x40, 0x43, + 0xed, 0xa1, 0x46, 0x2a, 0xe2, 0xec, 0xe8, 0x0d, 0xe8, 0x10, 0xc1, 0xf7, 0x3b, 0xcd, 0xca, 0x8e, 0x17, 0x13, 0x82, + 0x27, 0xef, 0xcb, 0xdb, 0xac, 0xac, 0xca, 0xe8, 0x7d, 0x8a, 0x86, 0x50, 0x89, 0x14, 0xd1, 0x2b, 0x88, 0xa7, 0x57, + 0xe2, 0xef, 0x32, 0xfa, 0x39, 0xa5, 0x71, 0x9a, 0x62, 0xfa, 0x8b, 0x02, 0x7e, 0x3e, 0x07, 0x54, 0x47, 0xdc, 0x09, + 0xd1, 0xb9, 0x04, 0x7b, 0x35, 0x88, 0x66, 0x55, 0x71, 0xc0, 0xd0, 0x8c, 0x6e, 0x05, 0x45, 0x8c, 0x36, 0xcc, 0xfe, + 0x43, 0x81, 0x42, 0x21, 0x55, 0xcc, 0x77, 0xc2, 0x3e, 0x44, 0x3f, 0x62, 0x91, 0xc7, 0xef, 0x5e, 0x9b, 0x21, 0x8d, + 0xee, 0x24, 0xd5, 0x5b, 0x1b, 0x8f, 0x2d, 0x0c, 0x5c, 0x16, 0x5d, 0xae, 0xe9, 0x59, 0xbc, 0xca, 0xa2, 0x0d, 0xe0, + 0x4f, 0xbc, 0x7b, 0xfd, 0x5c, 0x59, 0x98, 0xbc, 0xc8, 0x40, 0x71, 0x70, 0xfc, 0xee, 0xf5, 0x1b, 0x99, 0xae, 0x73, + 0x1e, 0x9d, 0x49, 0x24, 0xad, 0xc7, 0xef, 0x5e, 0xff, 0x82, 0xe6, 0x5e, 0x3f, 0x17, 0xf0, 0xfe, 0x15, 0xf0, 0x96, + 0x51, 0xbc, 0x86, 0x3e, 0xa9, 0xdf, 0xc9, 0x1a, 0x3b, 0xe5, 0xd5, 0x5a, 0x46, 0xbf, 0xa6, 0xb5, 0x27, 0xad, 0xfa, + 0x67, 0xe1, 0x53, 0x3b, 0x4f, 0xc0, 0x73, 0x9b, 0x67, 0xe2, 0x63, 0x64, 0x45, 0x3b, 0x41, 0xf4, 0xf5, 0xde, 0xed, + 0x55, 0x2e, 0xca, 0x08, 0x5f, 0x30, 0xb4, 0x0b, 0x8a, 0xf6, 0xf7, 0x6f, 0x6e, 0x6e, 0x46, 0x37, 0x4f, 0x46, 0xb2, + 0xb8, 0xdc, 0x9f, 0x7c, 0xfb, 0xed, 0xb7, 0xfb, 0xf8, 0x36, 0xf8, 0xba, 0xed, 0xf6, 0x5e, 0x11, 0x3e, 0x60, 0x01, + 0x22, 0x54, 0x7f, 0x0d, 0x57, 0x14, 0xd0, 0xc2, 0x0d, 0xbe, 0x0e, 0xbe, 0xd6, 0x87, 0xce, 0xd7, 0x87, 0xe5, 0xf5, + 0xa5, 0x2a, 0xbf, 0xab, 0xe4, 0x83, 0xf1, 0x78, 0xbc, 0x0f, 0x12, 0xa8, 0xaf, 0x07, 0x7c, 0x10, 0x1c, 0x05, 0x83, + 0x0c, 0x2e, 0x34, 0xe5, 0xf5, 0xe5, 0x51, 0xe0, 0x99, 0xe6, 0x36, 0x58, 0x44, 0x07, 0xe2, 0x12, 0xec, 0x5f, 0xd2, + 0xe0, 0xeb, 0x80, 0xb8, 0x94, 0xaf, 0x20, 0xe5, 0xab, 0x83, 0x67, 0x7e, 0xda, 0xff, 0x52, 0x69, 0x4f, 0xfc, 0xb4, + 0x43, 0x4c, 0x7b, 0xf2, 0xdc, 0x4f, 0x3b, 0x52, 0x69, 0x2f, 0xfd, 0xb4, 0xff, 0x5d, 0x0e, 0x20, 0x75, 0xcf, 0xb7, + 0xfe, 0x3b, 0xf7, 0x5a, 0x83, 0xa7, 0x50, 0x94, 0x5d, 0xc5, 0x97, 0x1c, 0x1a, 0x3d, 0xb8, 0xbd, 0xca, 0x69, 0x30, + 0xc0, 0xf6, 0x7a, 0x26, 0x21, 0xde, 0x07, 0x5f, 0xaf, 0x8b, 0x3c, 0x0c, 0xbe, 0x1e, 0x60, 0x21, 0x83, 0xaf, 0x03, + 0xf2, 0xb5, 0x31, 0x90, 0x11, 0x6c, 0x13, 0xb8, 0x50, 0xa4, 0x43, 0x1b, 0x20, 0xcc, 0x97, 0xc6, 0xd5, 0xf4, 0xaf, + 0xa2, 0x3b, 0x1b, 0xde, 0x12, 0x95, 0x9b, 0x6e, 0x50, 0xd3, 0x13, 0xf0, 0x4e, 0x80, 0x46, 0x45, 0xc1, 0x75, 0x5c, + 0x84, 0xc3, 0x61, 0x79, 0x7d, 0x49, 0xc0, 0x2e, 0x73, 0xc5, 0xe3, 0x2a, 0x0a, 0x84, 0x1c, 0xaa, 0x9f, 0x81, 0x8a, + 0x7c, 0x15, 0x20, 0x20, 0x12, 0xfc, 0x17, 0xd4, 0xf4, 0x9d, 0x64, 0x9b, 0x60, 0x78, 0xc3, 0xcf, 0x3f, 0x66, 0xd5, + 0x50, 0x89, 0x16, 0xaf, 0x05, 0x85, 0x1f, 0xf0, 0xd7, 0x55, 0x1d, 0xfd, 0x05, 0x6e, 0xdc, 0x4d, 0x0d, 0xfb, 0x3b, + 0xe9, 0x58, 0xd4, 0x77, 0x72, 0x9e, 0x2d, 0xa6, 0xad, 0x03, 0xfd, 0x44, 0x92, 0x6a, 0x9e, 0x0d, 0x82, 0x61, 0x30, + 0xe0, 0x0b, 0x76, 0x22, 0xe7, 0xdc, 0x33, 0x9f, 0x7a, 0x24, 0xfd, 0x69, 0x9e, 0x65, 0x03, 0xf0, 0x4d, 0x41, 0x7e, + 0x64, 0xff, 0xbf, 0xe7, 0x43, 0x14, 0x1e, 0x0e, 0x1e, 0xed, 0x93, 0x59, 0xb0, 0xba, 0x45, 0x8f, 0xce, 0x28, 0xc8, + 0xc4, 0x92, 0x17, 0x59, 0xe5, 0x2d, 0x95, 0xbb, 0x75, 0xdb, 0xcb, 0xe3, 0xde, 0xb3, 0x79, 0x15, 0x8b, 0x40, 0x9d, + 0x73, 0xa0, 0x78, 0x43, 0xd9, 0x53, 0xd9, 0x94, 0x90, 0x6a, 0x43, 0xde, 0xb0, 0x1c, 0xb0, 0xe0, 0xb0, 0x37, 0x1c, + 0xee, 0x05, 0x03, 0xa7, 0xce, 0x1d, 0x04, 0x7b, 0xc3, 0xe1, 0x51, 0xe0, 0xee, 0x43, 0xd9, 0xc8, 0xdd, 0x19, 0x69, + 0xc1, 0xfe, 0x59, 0x84, 0x25, 0x05, 0xf1, 0x98, 0xd4, 0xe2, 0x2f, 0x0d, 0x2e, 0x33, 0x00, 0xe8, 0x23, 0x25, 0x01, + 0x33, 0xb0, 0x32, 0x03, 0x08, 0xcd, 0x4d, 0x63, 0x76, 0x06, 0xcc, 0x23, 0x70, 0xcc, 0x23, 0x64, 0x1c, 0x00, 0xb1, + 0x24, 0xc0, 0xb9, 0x0b, 0xa2, 0x58, 0x17, 0xf2, 0x08, 0x40, 0xef, 0xf1, 0x27, 0x31, 0xa5, 0x60, 0x92, 0x8e, 0x55, + 0x08, 0x82, 0x38, 0x3e, 0xbb, 0x16, 0xad, 0xc9, 0x59, 0xa2, 0x83, 0x19, 0x49, 0x80, 0x0d, 0x31, 0xb0, 0x73, 0x70, + 0x3f, 0x07, 0xa5, 0x87, 0xd5, 0x3b, 0x21, 0x17, 0x7c, 0xc7, 0x3d, 0xd9, 0x2c, 0x5c, 0x3d, 0xe1, 0x20, 0xb8, 0xe3, + 0x9a, 0x05, 0x18, 0x55, 0xc5, 0xba, 0xac, 0x78, 0xfa, 0xe1, 0x6e, 0x05, 0xb1, 0xef, 0x70, 0x40, 0xdf, 0xc9, 0x3c, + 0x4b, 0xee, 0x42, 0x67, 0xcf, 0xb5, 0x51, 0xe9, 0x3f, 0x7c, 0x78, 0xf3, 0x73, 0x04, 0x22, 0xc7, 0xda, 0x50, 0xfa, + 0x3b, 0x8e, 0x67, 0x93, 0x1f, 0xe1, 0xc9, 0xdf, 0xd8, 0x77, 0xdc, 0x9e, 0x1e, 0xfd, 0x3e, 0xd4, 0x4d, 0xef, 0xf8, + 0xec, 0x8e, 0x8f, 0x5c, 0x71, 0xa8, 0xae, 0x70, 0x5f, 0xdf, 0xac, 0x7d, 0x23, 0xa4, 0x87, 0xe7, 0x99, 0xf2, 0xc6, + 0xfc, 0x68, 0x07, 0xc3, 0x20, 0x98, 0x6a, 0xa1, 0x24, 0x44, 0xdd, 0x60, 0x4a, 0xc0, 0x10, 0xed, 0xe9, 0x65, 0x35, + 0x45, 0xce, 0x4d, 0x8d, 0x2c, 0xbc, 0x1f, 0x30, 0x2d, 0x74, 0x68, 0xe4, 0x50, 0x7e, 0x70, 0x38, 0x61, 0xcc, 0xc2, + 0x6f, 0x95, 0x30, 0xfd, 0x6a, 0x51, 0x39, 0x07, 0xd1, 0x3d, 0x30, 0xc6, 0x15, 0xbc, 0x80, 0xae, 0xb0, 0xeb, 0xb5, + 0x8a, 0x8a, 0x81, 0xe0, 0x71, 0xc8, 0x01, 0x7a, 0xd8, 0x05, 0x2d, 0x2b, 0x4b, 0x75, 0xab, 0x72, 0x96, 0x2a, 0xea, + 0x32, 0x94, 0x95, 0xb1, 0xc2, 0x7c, 0x2f, 0xd9, 0x0f, 0x05, 0x7a, 0x96, 0x4f, 0x45, 0x17, 0xbc, 0x10, 0x4a, 0xb0, + 0x5c, 0xd7, 0x3b, 0x11, 0x88, 0x3a, 0x3f, 0xf4, 0xae, 0xfa, 0x1a, 0xc7, 0x8e, 0xa7, 0x6f, 0x64, 0xca, 0xb5, 0x09, + 0x85, 0xe6, 0xf3, 0xa5, 0xaf, 0x98, 0x28, 0xd8, 0x0d, 0xf4, 0xab, 0x6d, 0xa3, 0xcf, 0xee, 0xd6, 0x7a, 0x33, 0x28, + 0xd1, 0x31, 0xaf, 0x51, 0x70, 0xad, 0x14, 0x0a, 0x46, 0x7b, 0x1b, 0x7f, 0x86, 0x23, 0xb7, 0xba, 0x3d, 0xf4, 0x7e, + 0xab, 0xe2, 0xcb, 0xb7, 0xe8, 0xdb, 0x69, 0x7f, 0x8e, 0x2a, 0xf9, 0xeb, 0x6a, 0x05, 0x3e, 0x54, 0x10, 0x59, 0xc4, + 0xe2, 0xd2, 0x42, 0x3d, 0xa7, 0xef, 0x8e, 0xdf, 0x82, 0x1f, 0x25, 0xfe, 0xfe, 0xed, 0xfb, 0xa0, 0x26, 0xd3, 0x78, + 0x56, 0x98, 0x0f, 0x6d, 0x0e, 0x08, 0x4d, 0xe2, 0xd2, 0xec, 0xfb, 0x59, 0xdc, 0x64, 0xdf, 0x35, 0x5b, 0x4f, 0x8b, + 0x26, 0x92, 0x94, 0xe1, 0xf6, 0xc1, 0x80, 0x40, 0x1f, 0x20, 0x8a, 0xb3, 0x2f, 0x68, 0x0c, 0x69, 0x3e, 0xb3, 0xef, + 0x47, 0xc4, 0x7b, 0xb9, 0x13, 0x42, 0x8c, 0x2b, 0x2c, 0x1a, 0x3d, 0xe4, 0x33, 0x1e, 0x29, 0xc3, 0xa2, 0xf7, 0x98, + 0x40, 0x9c, 0xe1, 0xb4, 0x7a, 0x8f, 0x98, 0xc7, 0x78, 0x37, 0xd0, 0xb2, 0x87, 0x28, 0xa3, 0x2e, 0x7b, 0xc3, 0xe2, + 0xfb, 0xe3, 0x3a, 0xcc, 0xac, 0xe5, 0xe5, 0x10, 0xfe, 0x06, 0xda, 0x00, 0x9c, 0x72, 0x64, 0xf9, 0x2a, 0xb3, 0xd1, + 0xd5, 0x12, 0xd3, 0x9b, 0x08, 0x62, 0xf1, 0xe8, 0x74, 0x58, 0xbb, 0x3a, 0x55, 0xef, 0x6a, 0xe7, 0x33, 0xd1, 0xab, + 0x40, 0x2b, 0xd7, 0xb6, 0xc7, 0x43, 0xb8, 0x4b, 0x2d, 0xad, 0xb0, 0x11, 0xe5, 0x5c, 0x3c, 0xdd, 0x39, 0x36, 0x27, + 0xa0, 0xc1, 0x95, 0x4c, 0x01, 0x38, 0x4b, 0xab, 0xd1, 0xa8, 0x11, 0xf6, 0x59, 0x39, 0x9f, 0xc3, 0xd6, 0x42, 0x3c, + 0x2d, 0x00, 0xc3, 0x6d, 0x62, 0x50, 0xf2, 0x6e, 0x0c, 0xca, 0xe9, 0x47, 0x05, 0x6f, 0x1d, 0x9c, 0x95, 0xcb, 0x38, + 0x95, 0x37, 0x80, 0xc5, 0x18, 0xf8, 0xa9, 0x58, 0xaa, 0x97, 0x90, 0x2c, 0x79, 0xf2, 0x11, 0xad, 0x36, 0xd2, 0x00, + 0xb8, 0xca, 0xa9, 0xb1, 0xdc, 0x53, 0x20, 0xa1, 0xae, 0x14, 0x95, 0x10, 0x57, 0x55, 0x9c, 0x2c, 0x4f, 0x31, 0x35, + 0xdc, 0x40, 0x2f, 0xa2, 0x40, 0xae, 0xb8, 0x00, 0x92, 0x9e, 0xb3, 0x7f, 0x65, 0x1a, 0x6b, 0xfc, 0xb9, 0x44, 0x01, + 0x93, 0x46, 0x0d, 0xc6, 0x4a, 0xd9, 0x4b, 0x69, 0xa2, 0xbd, 0x05, 0x41, 0xed, 0x5e, 0xfe, 0x05, 0x75, 0x3f, 0x87, + 0x56, 0x84, 0x0d, 0x30, 0x44, 0x79, 0x8e, 0x3b, 0x34, 0xb5, 0x4b, 0xce, 0x03, 0x46, 0x74, 0xde, 0x67, 0xb5, 0xdd, + 0xea, 0xcf, 0x97, 0x80, 0x6d, 0x9a, 0x1a, 0x9f, 0xc2, 0x30, 0x21, 0x26, 0x36, 0xb0, 0x55, 0x56, 0xda, 0x0d, 0x65, + 0xda, 0x49, 0x97, 0xcc, 0x6b, 0xe1, 0x34, 0xef, 0x31, 0xb6, 0x1c, 0xa9, 0xdc, 0xfd, 0x7e, 0x68, 0x7e, 0xb2, 0x9c, + 0x3e, 0xd7, 0x21, 0x9b, 0xbd, 0xf1, 0xa0, 0x39, 0xd1, 0xea, 0xaa, 0x8e, 0x7e, 0x40, 0x07, 0x60, 0xa6, 0x2d, 0x40, + 0xa6, 0x0b, 0x36, 0xed, 0x2b, 0x51, 0x71, 0x49, 0xc2, 0x52, 0x49, 0x60, 0x67, 0x37, 0x25, 0x3b, 0x9b, 0x80, 0x78, + 0x86, 0xbb, 0x9e, 0x16, 0x3b, 0x21, 0x4d, 0x78, 0x8b, 0xbd, 0x04, 0x44, 0x1d, 0xaa, 0xba, 0x84, 0x6c, 0x8c, 0xa1, + 0x8b, 0x7f, 0x51, 0x0a, 0x13, 0xd6, 0x32, 0xa9, 0x4a, 0x4c, 0x10, 0xa4, 0x72, 0xb7, 0x45, 0x60, 0x89, 0x82, 0x1d, + 0xc0, 0xde, 0xbb, 0x51, 0x37, 0xa3, 0xa6, 0xaa, 0x53, 0x2f, 0xc1, 0xc7, 0x69, 0xd6, 0x55, 0x90, 0x59, 0xd8, 0x55, + 0xb1, 0xe6, 0x81, 0x8e, 0x4d, 0xa5, 0x8c, 0x89, 0xbb, 0xb4, 0xc8, 0x10, 0x0f, 0x18, 0x63, 0xe9, 0x42, 0x20, 0xdf, + 0x6c, 0x77, 0xdc, 0xf4, 0x04, 0xa1, 0x9f, 0xb0, 0xa1, 0x04, 0x6e, 0x3a, 0xdb, 0x53, 0xd3, 0xcc, 0x07, 0x44, 0x1c, + 0x06, 0x14, 0x48, 0x36, 0x0e, 0x69, 0x8e, 0xf4, 0x05, 0x49, 0x13, 0x06, 0x86, 0x56, 0x3c, 0x27, 0xc8, 0x8a, 0x42, + 0xcf, 0xd6, 0x55, 0x1b, 0xe7, 0xca, 0x30, 0x47, 0x4b, 0x4e, 0x85, 0xcf, 0x09, 0x32, 0xb1, 0x7b, 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, 0x68, 0x18, 0x62, 0xb7, 0x3f, 0xc1, 0x7e, 0xad, 0x9d, 0xd6, 0x65, 0x8a, 0xe5, 0x65, 0x0a, + 0xd1, 0x5e, 0xc8, 0xfc, 0x46, 0x91, 0xe8, 0x4e, 0x11, 0x86, 0x84, 0x75, 0x94, 0x3d, 0x69, 0x53, 0x03, 0xe8, 0xa9, + 0x17, 0xf0, 0xbc, 0x73, 0x2d, 0xc3, 0x2e, 0xd2, 0xfd, 0x55, 0xc1, 0xa7, 0x74, 0x83, 0x20, 0x45, 0x6f, 0x52, 0x30, + 0xe7, 0xf5, 0x28, 0xa9, 0x37, 0xa7, 0x2d, 0x33, 0xaa, 0x8e, 0x8a, 0x90, 0x72, 0x82, 0xff, 0xe4, 0xa5, 0xd4, 0xc4, + 0x26, 0x4c, 0xf0, 0xc0, 0x87, 0x79, 0x86, 0x0d, 0xbc, 0xdd, 0xbe, 0x4b, 0xc3, 0xa4, 0xcd, 0x36, 0xa4, 0x20, 0xad, + 0x30, 0x71, 0x31, 0xa0, 0xb2, 0xd7, 0xb8, 0x5f, 0xb0, 0x9d, 0x34, 0x05, 0x0f, 0xc2, 0x46, 0x03, 0x13, 0xb7, 0xba, + 0xf8, 0x3a, 0x4c, 0x68, 0xb8, 0xa4, 0xda, 0xd9, 0x49, 0x4b, 0x9a, 0xdb, 0xeb, 0xf2, 0xc2, 0xf6, 0x41, 0xc7, 0x0e, + 0xeb, 0x1a, 0x1e, 0x68, 0x5e, 0xb3, 0x8b, 0x2b, 0xa6, 0x69, 0xa2, 0xb1, 0x1e, 0x52, 0x96, 0x1c, 0xeb, 0x7a, 0xba, + 0xc2, 0xd5, 0x32, 0xd3, 0xc0, 0xee, 0x12, 0x2f, 0xf4, 0x80, 0x87, 0x1d, 0xae, 0x48, 0x74, 0x81, 0xcd, 0x66, 0xab, + 0x9a, 0x4c, 0xf3, 0xfb, 0xb2, 0xe5, 0x26, 0x20, 0x9c, 0xa5, 0xbe, 0xb9, 0x4f, 0x8e, 0x35, 0x6d, 0xf3, 0x93, 0x00, + 0xc7, 0xdb, 0x2b, 0x20, 0xe9, 0x58, 0x82, 0x2e, 0xbe, 0xa5, 0x3f, 0x88, 0xd4, 0x4c, 0x05, 0xbd, 0x77, 0xbe, 0x48, + 0xdd, 0xfc, 0x02, 0x6c, 0xa3, 0x36, 0xc6, 0x34, 0x2b, 0x5b, 0x87, 0x89, 0xb2, 0xb0, 0x46, 0x16, 0x72, 0x09, 0x3e, + 0x98, 0xbb, 0x4d, 0x9d, 0x1e, 0x77, 0x10, 0x61, 0xbf, 0x8b, 0x1e, 0x8f, 0x30, 0x56, 0xac, 0x41, 0x62, 0x58, 0x85, + 0x35, 0x6d, 0x2e, 0x87, 0x28, 0xa7, 0x66, 0xc9, 0x44, 0x4b, 0xea, 0x53, 0x8a, 0x28, 0x05, 0x73, 0xe3, 0x69, 0xd9, + 0x30, 0x25, 0x44, 0xc8, 0x0a, 0xe9, 0x80, 0x6a, 0x2d, 0xb4, 0x54, 0x13, 0xf4, 0x3a, 0xf4, 0xb2, 0xd0, 0x98, 0x82, + 0xe8, 0x23, 0x32, 0xdc, 0x88, 0x23, 0xa3, 0xbb, 0x63, 0x14, 0x13, 0x08, 0x55, 0xed, 0xe5, 0x85, 0xd5, 0xa7, 0x65, + 0x5b, 0x1d, 0xc4, 0x15, 0x22, 0xdf, 0x77, 0x13, 0xd4, 0x18, 0x05, 0x6d, 0x4e, 0x37, 0xfa, 0x6b, 0x11, 0xfa, 0x76, + 0xe1, 0xd8, 0x8d, 0x82, 0x48, 0x88, 0xc0, 0xea, 0x35, 0x15, 0x03, 0xb2, 0xce, 0x63, 0x17, 0xa1, 0x49, 0x77, 0x0b, + 0x51, 0xde, 0xa8, 0xac, 0x3f, 0xae, 0x43, 0xb2, 0xdd, 0x62, 0x59, 0xe0, 0xcb, 0x7e, 0xba, 0xbe, 0x07, 0xf2, 0xfb, + 0xcd, 0xfa, 0xb3, 0x90, 0xdf, 0xaf, 0xb3, 0x2f, 0x81, 0xfc, 0x7e, 0xb3, 0xfe, 0x9f, 0x86, 0xfc, 0x3e, 0x5d, 0x7b, + 0x90, 0xdf, 0x6a, 0x30, 0x7e, 0x2f, 0x58, 0x70, 0xf2, 0x36, 0xa0, 0x2f, 0x24, 0x0b, 0x4e, 0x5e, 0xbd, 0xf2, 0x8d, + 0x40, 0x84, 0x46, 0xae, 0x37, 0xb2, 0x60, 0xc4, 0x6d, 0x81, 0x57, 0xa8, 0x75, 0xf2, 0x81, 0x8a, 0x32, 0x00, 0x5e, + 0x2f, 0xff, 0x91, 0x55, 0xcb, 0x30, 0xd8, 0x0f, 0xc8, 0xcc, 0x41, 0x82, 0x0e, 0x27, 0x70, 0x7b, 0x43, 0x23, 0xcb, + 0xea, 0x8b, 0xe0, 0xc3, 0x47, 0xa3, 0x51, 0x5c, 0x5c, 0xe2, 0xa5, 0xce, 0x6c, 0x24, 0x04, 0x3c, 0xce, 0x78, 0x69, + 0x43, 0x44, 0x2c, 0xe3, 0xf2, 0x4c, 0xc7, 0x66, 0x29, 0xed, 0x56, 0x84, 0x88, 0xf3, 0x67, 0x80, 0x53, 0x6f, 0xf7, + 0x66, 0x8c, 0xfd, 0x50, 0x1c, 0xb1, 0x0e, 0x20, 0xfb, 0x7c, 0xad, 0xdf, 0x9d, 0xc7, 0x25, 0x7f, 0x17, 0x57, 0x4b, + 0x06, 0xbd, 0x84, 0xbb, 0x88, 0xe0, 0x49, 0xe5, 0xb1, 0x4d, 0x0a, 0xa8, 0x3c, 0xd3, 0x40, 0xe5, 0x1d, 0xef, 0x69, + 0x68, 0x87, 0x45, 0xfb, 0x00, 0x1b, 0xe9, 0x72, 0x06, 0x46, 0x8b, 0x2f, 0xaf, 0xb9, 0xa8, 0x7e, 0x06, 0x3c, 0x75, + 0xc1, 0x0b, 0xb8, 0x25, 0x20, 0x17, 0xdb, 0x70, 0x42, 0xa0, 0xc2, 0xf7, 0xec, 0x50, 0x51, 0x63, 0x8c, 0x68, 0xa2, + 0xd1, 0x6f, 0xbc, 0x09, 0xa1, 0x77, 0x27, 0xe8, 0x8a, 0x30, 0x12, 0xde, 0x5f, 0x6b, 0x7e, 0x96, 0x81, 0xf9, 0xbc, + 0x00, 0x28, 0x0d, 0x84, 0x43, 0x65, 0x4a, 0x6e, 0x81, 0x09, 0x1b, 0x63, 0xae, 0x94, 0xa5, 0x1e, 0x52, 0x29, 0x55, + 0x70, 0xba, 0x82, 0xa6, 0x12, 0x70, 0xb8, 0x23, 0x09, 0x60, 0xa6, 0xb6, 0x30, 0x88, 0x6e, 0x9b, 0xd2, 0x2c, 0x8d, + 0x9c, 0x22, 0xcd, 0xe1, 0x93, 0x52, 0x05, 0x3a, 0x7d, 0x96, 0xc4, 0x15, 0xbf, 0x94, 0x05, 0x84, 0xc2, 0x6d, 0xa5, + 0x50, 0xa4, 0xdf, 0x67, 0x62, 0x7d, 0xc5, 0x8b, 0x2c, 0x39, 0x5b, 0x66, 0x65, 0x05, 0xf9, 0xe6, 0xfa, 0xf4, 0x5b, + 0xd4, 0xd3, 0x02, 0xe7, 0x4d, 0x4d, 0x0a, 0x33, 0xf3, 0x78, 0xac, 0x76, 0x3a, 0xa8, 0x57, 0xbd, 0xd7, 0x06, 0xfb, + 0xbd, 0x39, 0xd1, 0xe3, 0xd6, 0x7a, 0xb0, 0x9a, 0xd4, 0x66, 0xaa, 0x82, 0x38, 0x02, 0xea, 0xc0, 0x8e, 0x70, 0x16, + 0x53, 0xba, 0xb6, 0x08, 0x2a, 0x60, 0xed, 0x80, 0x39, 0x32, 0x71, 0x79, 0x76, 0xa3, 0xe4, 0x27, 0x3d, 0x45, 0x61, + 0xd2, 0x28, 0x56, 0xc8, 0x3e, 0x4b, 0x16, 0xae, 0x59, 0x72, 0x4f, 0xae, 0x75, 0x94, 0x34, 0x30, 0xba, 0xe2, 0xf6, + 0x40, 0x1c, 0x26, 0xed, 0x94, 0xed, 0x76, 0x27, 0x13, 0xb0, 0x06, 0xad, 0x24, 0x88, 0xd6, 0xb1, 0x9c, 0x0d, 0x27, + 0x11, 0x40, 0xa8, 0x68, 0xb2, 0xf6, 0xd7, 0x9a, 0x1b, 0x90, 0xf9, 0x50, 0x7b, 0xfa, 0x39, 0x91, 0xbc, 0x1e, 0x59, + 0xcf, 0x38, 0x4e, 0x4f, 0xfb, 0x1c, 0x0c, 0xb3, 0xfc, 0x21, 0x81, 0x48, 0x30, 0x9d, 0xd3, 0xb3, 0x98, 0x6a, 0x33, + 0x61, 0xc3, 0xa3, 0xd0, 0x2f, 0xfb, 0x4e, 0x03, 0xe0, 0x26, 0x3c, 0x1c, 0x3e, 0x1b, 0x93, 0x5a, 0xdb, 0xac, 0xe3, + 0x02, 0xb2, 0xbf, 0xd5, 0x22, 0x73, 0xcf, 0x76, 0xa1, 0xd1, 0xa6, 0xb7, 0x41, 0xbb, 0x46, 0x2a, 0xee, 0xe9, 0x7e, + 0x4d, 0x6a, 0xb7, 0x60, 0xac, 0x04, 0xe9, 0x0f, 0x75, 0x6a, 0x9d, 0x3d, 0xda, 0x64, 0xba, 0xca, 0xfa, 0x8f, 0xcc, + 0xc6, 0x9b, 0x6b, 0x50, 0x80, 0x5a, 0x2f, 0x25, 0x1f, 0xee, 0xad, 0x23, 0x9b, 0x9e, 0x18, 0x96, 0x75, 0x92, 0x91, + 0x91, 0x7a, 0xe4, 0x2a, 0xfc, 0x56, 0x77, 0x16, 0x7e, 0xcb, 0x93, 0xb0, 0xab, 0x61, 0x8a, 0xc3, 0x37, 0x5d, 0x40, + 0x04, 0x4c, 0x90, 0xeb, 0x87, 0x7f, 0x3c, 0xda, 0x34, 0xc9, 0x52, 0xbd, 0xef, 0x7d, 0x86, 0xbf, 0xb3, 0x14, 0xfe, + 0x56, 0xf5, 0x1f, 0x74, 0x73, 0xc5, 0xab, 0xa5, 0x4c, 0xa3, 0xe0, 0xdd, 0xc9, 0xe9, 0x87, 0x40, 0x23, 0xab, 0xe3, + 0xfd, 0xc2, 0x68, 0x94, 0x0d, 0x86, 0x13, 0x68, 0x58, 0x72, 0x79, 0x89, 0xe0, 0x82, 0x1a, 0x9d, 0xfe, 0x74, 0x29, + 0x6f, 0x8e, 0xf3, 0xdc, 0x67, 0x82, 0x0d, 0xe1, 0xd4, 0x7c, 0x61, 0x83, 0xea, 0x84, 0x20, 0xcb, 0x1b, 0x65, 0xe5, + 0x99, 0xd6, 0xbe, 0xa4, 0x67, 0xe7, 0x77, 0x67, 0x5a, 0xc2, 0x63, 0xd1, 0x1d, 0x9f, 0xff, 0x71, 0x98, 0x66, 0xd7, + 0x7b, 0x48, 0xdd, 0x59, 0x00, 0xa6, 0xf1, 0x39, 0x3f, 0x5f, 0x57, 0x95, 0x14, 0xc3, 0x42, 0xde, 0x04, 0x47, 0x87, + 0xea, 0xc1, 0x64, 0x88, 0xd5, 0x63, 0xb0, 0xf7, 0x5f, 0x49, 0x9e, 0x25, 0x1f, 0x59, 0xf0, 0x68, 0x93, 0xb1, 0xa3, + 0x16, 0x0d, 0x1f, 0xd7, 0xc1, 0x11, 0xb4, 0x75, 0xef, 0x38, 0xcf, 0x0f, 0xf7, 0xd5, 0x17, 0x47, 0x87, 0xfb, 0x69, + 0x76, 0x7d, 0xe4, 0x01, 0xed, 0x3b, 0xbb, 0x59, 0x84, 0x34, 0x73, 0xf7, 0x62, 0x70, 0x90, 0x4d, 0x78, 0x68, 0x39, + 0x09, 0x90, 0xc6, 0x98, 0x30, 0x25, 0x28, 0xc1, 0x09, 0x63, 0x38, 0x37, 0xb7, 0xdb, 0xd0, 0x1a, 0xf5, 0x24, 0x1e, + 0xe2, 0x4d, 0x01, 0x9c, 0x06, 0x66, 0xa1, 0x09, 0xa1, 0x49, 0x4d, 0x42, 0x83, 0xcb, 0x13, 0x13, 0x5a, 0xd4, 0x14, + 0x8e, 0x92, 0x37, 0xf1, 0xca, 0x08, 0xb1, 0xb4, 0x50, 0xc0, 0xb4, 0x7e, 0xd6, 0x18, 0xc7, 0xa8, 0x3d, 0xaa, 0x06, + 0x29, 0xab, 0x57, 0xde, 0x37, 0xb0, 0x20, 0xb7, 0x0c, 0x2b, 0x1a, 0xb4, 0x28, 0x04, 0xc8, 0x1d, 0x7d, 0x71, 0x19, + 0xa7, 0xe1, 0xbc, 0xa4, 0x72, 0x41, 0xd8, 0x51, 0xb8, 0x41, 0xb6, 0xb9, 0x54, 0x54, 0x38, 0x92, 0xb5, 0x83, 0xad, + 0x54, 0xb3, 0x73, 0xf4, 0x68, 0x23, 0x10, 0x29, 0xb1, 0x64, 0x47, 0xcd, 0xf9, 0xaa, 0xe2, 0xf3, 0xe1, 0x92, 0x83, + 0x7f, 0x4d, 0xb0, 0xf7, 0x5f, 0xe9, 0x79, 0x6e, 0x27, 0x45, 0xad, 0xc8, 0x65, 0x2c, 0xd2, 0x9c, 0x7f, 0x88, 0xcf, + 0x7f, 0xc0, 0x3c, 0x2f, 0xce, 0xf3, 0xe7, 0x90, 0xa1, 0x0e, 0x8e, 0x1e, 0x6d, 0x92, 0x6a, 0xf4, 0xf2, 0xed, 0x87, + 0xd7, 0x1f, 0xfe, 0x79, 0xf6, 0xfc, 0xf8, 0xc3, 0xcb, 0xef, 0x4f, 0xde, 0xbf, 0x7e, 0x79, 0x3a, 0xb7, 0x0e, 0xad, + 0x0a, 0x27, 0x8d, 0x2c, 0xb6, 0x5b, 0x97, 0xef, 0xd7, 0xb7, 0x2f, 0x5e, 0xbe, 0x7a, 0xfd, 0xf6, 0xe5, 0x8b, 0x5a, + 0xcd, 0x65, 0xbb, 0x21, 0xb0, 0x43, 0xe3, 0x4c, 0xf0, 0x02, 0x8a, 0xd7, 0xd1, 0x1a, 0xb1, 0xd9, 0x1a, 0xde, 0xaf, + 0xd9, 0x74, 0x1d, 0x09, 0x01, 0x16, 0xd9, 0x9e, 0xde, 0x2c, 0xd0, 0x70, 0x69, 0x36, 0x8e, 0xbf, 0xc4, 0xfc, 0xde, + 0xbc, 0xc4, 0xef, 0xde, 0xcb, 0x1b, 0xd3, 0x15, 0x3d, 0x42, 0x0a, 0xb9, 0x6b, 0xf6, 0xfc, 0x8f, 0x43, 0x5f, 0x5a, + 0x86, 0x22, 0x05, 0x55, 0x2e, 0xfc, 0xaa, 0x83, 0x3d, 0x6d, 0xb9, 0x17, 0x40, 0xe0, 0x89, 0xe0, 0xe8, 0x70, 0xdf, + 0xcf, 0x7d, 0xf4, 0x47, 0xf4, 0xb3, 0xd7, 0x39, 0x2c, 0x15, 0xc6, 0xa1, 0x99, 0xb6, 0x73, 0xba, 0x41, 0x68, 0x24, + 0x77, 0xfe, 0xa9, 0x15, 0x64, 0xc8, 0x95, 0x24, 0x91, 0x9d, 0x44, 0x65, 0x91, 0x62, 0x4a, 0xfb, 0x43, 0xff, 0x75, + 0x7d, 0xc6, 0x1b, 0x3e, 0x17, 0xa5, 0x2c, 0x02, 0xe8, 0x47, 0x3b, 0x5e, 0xc4, 0x9e, 0x17, 0x97, 0x05, 0x7b, 0xd4, + 0x49, 0xde, 0x61, 0x44, 0xf6, 0xdb, 0x9f, 0x7a, 0x1d, 0xfb, 0x83, 0xb8, 0x1f, 0x7b, 0xba, 0x33, 0x2d, 0xf2, 0x62, + 0x1b, 0x78, 0x7f, 0x5c, 0x8f, 0xf9, 0x49, 0x46, 0xff, 0x21, 0xe9, 0x65, 0x4c, 0xaf, 0x62, 0x7a, 0x2a, 0x16, 0x75, + 0xe7, 0xec, 0xd8, 0x98, 0x31, 0x94, 0x4f, 0x43, 0x40, 0x9e, 0xd0, 0xf7, 0x01, 0xcd, 0x25, 0x67, 0x23, 0xad, 0x2b, + 0xfb, 0x10, 0x17, 0x97, 0xdc, 0x84, 0x6a, 0x31, 0x6f, 0x2b, 0x3d, 0x2a, 0xc4, 0x1b, 0x16, 0x80, 0x65, 0xe9, 0x69, + 0x93, 0x82, 0x6c, 0x94, 0x54, 0x45, 0xfe, 0x13, 0xbf, 0x03, 0xae, 0xad, 0xac, 0xe4, 0x0a, 0x78, 0xf5, 0xff, 0xd3, + 0xdc, 0xb3, 0x2e, 0xb7, 0x6d, 0x5c, 0xfd, 0xbf, 0x4f, 0x01, 0xc3, 0xae, 0x03, 0xd8, 0x00, 0x04, 0x90, 0xa2, 0x28, + 0x93, 0x22, 0x95, 0xc4, 0x76, 0xa6, 0xea, 0x28, 0x71, 0xc6, 0x56, 0x3d, 0x6d, 0x14, 0x8d, 0x08, 0x82, 0x4b, 0x12, + 0x35, 0x08, 0x60, 0x00, 0x50, 0xa2, 0x42, 0xa3, 0xcf, 0xd2, 0x67, 0xe9, 0x93, 0x7d, 0x73, 0xce, 0x5e, 0xb0, 0xb8, + 0x91, 0x54, 0xec, 0xb4, 0xdf, 0xa4, 0xaa, 0x89, 0xc5, 0xee, 0x62, 0xf7, 0xec, 0xee, 0xd9, 0x73, 0x3f, 0xee, 0x82, + 0xc9, 0x5e, 0x0c, 0x8d, 0x1c, 0xf6, 0xb9, 0xcf, 0x9f, 0x89, 0x85, 0x5b, 0x12, 0x08, 0x3e, 0x2b, 0x8b, 0x16, 0x8b, + 0x80, 0x68, 0x2a, 0x4f, 0x1e, 0xa2, 0x1a, 0xe2, 0x33, 0xe7, 0x4f, 0x6c, 0x1e, 0xb1, 0x53, 0xcf, 0xdb, 0x8e, 0x16, + 0x9f, 0x31, 0x11, 0x21, 0xed, 0x28, 0xe5, 0x8a, 0xb2, 0xd9, 0x3b, 0x54, 0x6f, 0xb0, 0x75, 0x29, 0x8e, 0xae, 0x39, + 0x8b, 0xd6, 0xd3, 0x80, 0x98, 0xb8, 0xdd, 0xe1, 0x93, 0xdb, 0xe9, 0x7a, 0x3a, 0x85, 0x2c, 0x2d, 0x4f, 0x6c, 0x03, + 0xe2, 0xce, 0x44, 0x29, 0xf2, 0x83, 0xb9, 0x3e, 0x84, 0x49, 0x59, 0x59, 0x75, 0xf8, 0x60, 0x2b, 0x02, 0xa2, 0x1e, + 0xfa, 0x81, 0x0c, 0x78, 0xbf, 0x86, 0x53, 0x3b, 0x52, 0x3f, 0xc0, 0xee, 0x4b, 0xd5, 0x61, 0xd3, 0xd1, 0x1f, 0x5d, + 0xab, 0x1f, 0x10, 0xc6, 0x98, 0xbd, 0xf8, 0x35, 0xdd, 0xbd, 0xaa, 0xa1, 0x52, 0xa5, 0xf7, 0x1a, 0xf3, 0x18, 0x80, + 0xd0, 0xf7, 0x8d, 0xef, 0x2e, 0xc2, 0x28, 0xcd, 0x7c, 0x4f, 0xbd, 0x19, 0x5e, 0xf8, 0xda, 0xf5, 0x2a, 0xd3, 0xf4, + 0x1b, 0xc3, 0xcb, 0xe4, 0x14, 0x28, 0x1c, 0x61, 0x62, 0x06, 0x94, 0xb6, 0x4a, 0xf2, 0x09, 0xda, 0x59, 0x91, 0xa3, + 0x66, 0xac, 0xe4, 0x65, 0x23, 0xa8, 0x57, 0xc9, 0xa7, 0x82, 0x89, 0xa1, 0x54, 0x6c, 0xa9, 0x0f, 0x29, 0xa7, 0xf2, + 0x7a, 0xbd, 0xc5, 0xab, 0x3c, 0x2b, 0x6e, 0x4b, 0x8c, 0x01, 0xcc, 0x1d, 0x67, 0xe8, 0xf3, 0x13, 0xd9, 0xe8, 0xb3, + 0x74, 0xef, 0x4e, 0xbe, 0x2b, 0xd3, 0x05, 0x70, 0x7f, 0x83, 0xc5, 0x45, 0x18, 0x65, 0x0a, 0x04, 0xb6, 0x81, 0x2f, + 0x4e, 0xaa, 0x46, 0x62, 0xac, 0x57, 0x4d, 0xcf, 0x19, 0x32, 0xf8, 0x1e, 0x2f, 0x3f, 0x8d, 0x85, 0x37, 0x2b, 0x45, + 0xb0, 0xa0, 0xcc, 0x42, 0x08, 0x0b, 0x98, 0x45, 0x97, 0xd1, 0x7d, 0x55, 0x0f, 0xf2, 0x7a, 0xb2, 0xff, 0xee, 0xd5, + 0x38, 0x99, 0xcc, 0xb3, 0xfa, 0x69, 0x2c, 0x31, 0x29, 0x27, 0x74, 0x2a, 0x67, 0x0a, 0x0d, 0x3f, 0x38, 0x0d, 0x93, + 0x81, 0x9d, 0x18, 0xde, 0x05, 0x80, 0x92, 0xd8, 0x35, 0x3d, 0xc9, 0x6f, 0x79, 0xea, 0x64, 0x9e, 0xb8, 0x58, 0xba, + 0x9c, 0x01, 0xbb, 0x86, 0xf1, 0x3a, 0xc3, 0x50, 0xbb, 0x30, 0x00, 0x92, 0xab, 0x0a, 0x86, 0xee, 0x04, 0x2c, 0x5d, + 0x90, 0x89, 0xb9, 0xaa, 0xf8, 0xb3, 0x7a, 0x19, 0x23, 0x7a, 0x01, 0x79, 0x21, 0x7e, 0x47, 0x41, 0x15, 0x3c, 0x26, + 0x6c, 0x1a, 0x9e, 0x51, 0xc4, 0xa9, 0xd7, 0x3c, 0x54, 0xe8, 0x34, 0x60, 0x06, 0x8f, 0xf6, 0x33, 0xd4, 0x82, 0xc6, + 0xc9, 0x42, 0xf8, 0xcd, 0xd2, 0x34, 0x27, 0xcf, 0xb6, 0x61, 0x7e, 0xfe, 0x6c, 0x9b, 0xe6, 0xa3, 0x67, 0x5b, 0x17, + 0x28, 0xb9, 0x5c, 0x85, 0x89, 0x16, 0x8e, 0x3a, 0xc5, 0xf4, 0x60, 0x53, 0xd1, 0x72, 0x05, 0x35, 0xf5, 0x23, 0xa6, + 0x8f, 0x8f, 0x13, 0x7f, 0xe5, 0x26, 0x0f, 0x54, 0x7d, 0x6f, 0xc8, 0x3a, 0x7e, 0x5d, 0x55, 0x28, 0x5e, 0xa7, 0xf3, + 0xa5, 0x28, 0x5e, 0x55, 0xbe, 0x15, 0x65, 0x84, 0x4d, 0x4e, 0xe8, 0x30, 0xe1, 0x5b, 0xb7, 0xea, 0x4b, 0x62, 0xcd, + 0x48, 0xe6, 0xfa, 0x01, 0x6d, 0x32, 0xe4, 0xc9, 0xe9, 0x6b, 0xb3, 0x49, 0xcb, 0xb3, 0x09, 0xcb, 0xdb, 0x05, 0x27, + 0x43, 0x31, 0x3e, 0x1d, 0x37, 0xce, 0x0c, 0x93, 0x56, 0x35, 0x2f, 0x20, 0x7d, 0xf7, 0x5f, 0x85, 0x3e, 0x01, 0xe8, + 0x87, 0x00, 0x7d, 0x12, 0x7a, 0xd1, 0x8c, 0xfc, 0xed, 0xfd, 0x85, 0xc8, 0x92, 0x05, 0x02, 0x9f, 0x09, 0xdb, 0x87, + 0x29, 0x92, 0x0b, 0x09, 0x92, 0x0a, 0x34, 0x9f, 0x95, 0x22, 0x76, 0x4c, 0x92, 0xab, 0xca, 0x39, 0x1d, 0x3b, 0x99, + 0xd1, 0x51, 0x8f, 0x22, 0x6c, 0x95, 0xe4, 0x67, 0x47, 0xb4, 0x36, 0xbd, 0xdc, 0x68, 0x25, 0x00, 0x43, 0x02, 0x33, + 0x2c, 0xa0, 0x00, 0x09, 0x3d, 0x47, 0x4e, 0xc1, 0x3f, 0x58, 0x2b, 0x14, 0xab, 0x3b, 0xe7, 0x65, 0xca, 0x04, 0x5b, + 0xa9, 0xe3, 0x33, 0x4c, 0xd1, 0x05, 0xd7, 0x33, 0x04, 0xf5, 0x38, 0x3b, 0xa2, 0x8f, 0x4a, 0xe5, 0x00, 0x14, 0x9d, + 0x70, 0x4e, 0x6e, 0xc0, 0x3a, 0x78, 0xd4, 0xc9, 0x80, 0x8c, 0xf0, 0x50, 0xea, 0xe6, 0xaa, 0xb2, 0x62, 0x94, 0x10, + 0x8b, 0x1e, 0x04, 0xa1, 0x05, 0x6c, 0x38, 0xaa, 0xaa, 0xb2, 0x72, 0x37, 0x38, 0x73, 0xfe, 0xc6, 0xdd, 0x68, 0x0e, + 0x7b, 0x55, 0x1c, 0xad, 0xb4, 0x7c, 0xb4, 0x3c, 0xb6, 0xb8, 0xe0, 0x37, 0x20, 0x18, 0xe9, 0x25, 0xea, 0x63, 0x1b, + 0x16, 0x77, 0xc9, 0x17, 0x77, 0xd6, 0xb2, 0xb8, 0xb3, 0x1d, 0x8b, 0x1b, 0xb0, 0x85, 0x54, 0x04, 0xe8, 0x12, 0xf4, + 0x05, 0x13, 0xc0, 0x63, 0x74, 0xc5, 0x80, 0x9d, 0x33, 0x84, 0x93, 0x99, 0x06, 0x60, 0x0b, 0xd5, 0x02, 0xab, 0x26, + 0xb8, 0x48, 0x80, 0xa8, 0x4f, 0x5c, 0x9c, 0x3a, 0x3e, 0x6f, 0x48, 0xb9, 0xa9, 0x05, 0xd5, 0xf9, 0xc2, 0x2e, 0xa5, + 0xe9, 0xc4, 0xb5, 0x65, 0xcb, 0x4c, 0x97, 0x3b, 0x66, 0xea, 0x95, 0x8e, 0x2e, 0x9b, 0x36, 0x3d, 0x84, 0xf2, 0xa4, + 0x60, 0x0f, 0x82, 0x7d, 0x28, 0x6e, 0x99, 0xf2, 0x3e, 0x6c, 0x47, 0xa9, 0xd2, 0x8e, 0x8a, 0xdd, 0x34, 0xbd, 0x8f, + 0x12, 0x50, 0xb0, 0x40, 0x37, 0x8f, 0xdb, 0x52, 0x2b, 0x3f, 0x64, 0xb1, 0x5b, 0x5a, 0x37, 0x53, 0xf1, 0x5e, 0xde, + 0x52, 0x9d, 0x5e, 0x8f, 0xd6, 0x88, 0xdd, 0x2c, 0x23, 0x09, 0x02, 0xdd, 0x85, 0x20, 0xdf, 0xff, 0x4f, 0xb6, 0x59, + 0x03, 0x0e, 0x09, 0xf4, 0x02, 0xab, 0x23, 0x86, 0x8e, 0x81, 0x94, 0x4a, 0xf8, 0xbd, 0x2b, 0xc5, 0x81, 0x4b, 0x04, + 0xe0, 0x7f, 0xc2, 0xe3, 0xaa, 0x25, 0x92, 0xa7, 0x92, 0x73, 0xa2, 0x5b, 0xb1, 0x3b, 0xfb, 0x00, 0x7a, 0x3c, 0xad, + 0x63, 0x80, 0x4d, 0xae, 0x1c, 0xf5, 0x2d, 0xa1, 0xb4, 0x9d, 0x57, 0x20, 0x49, 0xc4, 0x92, 0xcc, 0xe2, 0x09, 0x9c, + 0x25, 0x5d, 0x73, 0x7e, 0xb3, 0xed, 0xe4, 0x47, 0x0b, 0x5f, 0xaf, 0x61, 0x4d, 0x40, 0x6d, 0xc1, 0x68, 0x2c, 0x58, + 0xac, 0xc0, 0x70, 0x4e, 0x74, 0x10, 0xf4, 0x5e, 0x43, 0xfa, 0x52, 0x9b, 0xf3, 0xaf, 0x93, 0x04, 0x2e, 0xa9, 0x6b, + 0xfb, 0x26, 0x7f, 0xbe, 0xc0, 0x5f, 0xce, 0x4d, 0xfe, 0x7c, 0x8a, 0xbf, 0x3a, 0x37, 0x98, 0xa8, 0xae, 0x81, 0x6f, + 0x97, 0xe6, 0xac, 0x8e, 0x4b, 0xfb, 0x89, 0x9a, 0x9b, 0x3d, 0x62, 0xdb, 0xb0, 0x05, 0x7e, 0xfa, 0x6c, 0x9b, 0x82, + 0x83, 0xa5, 0x3c, 0x87, 0xd0, 0x4a, 0xf4, 0xbc, 0xb1, 0x7c, 0xd1, 0x52, 0x3e, 0xd5, 0xff, 0xcb, 0xf7, 0x3c, 0xee, + 0x92, 0xa8, 0xb8, 0x53, 0xca, 0x52, 0x87, 0xdb, 0xa9, 0x1f, 0xba, 0xc9, 0xc3, 0x2d, 0xe5, 0x26, 0x34, 0x4e, 0xaa, + 0x0b, 0x69, 0x0a, 0xa5, 0x26, 0xcb, 0xda, 0xad, 0x4c, 0x92, 0xe7, 0x3e, 0xb0, 0x8b, 0x7e, 0xf4, 0xf7, 0x44, 0xa2, + 0xd2, 0x4a, 0xfc, 0x26, 0x5b, 0x90, 0xd2, 0x87, 0x6e, 0x9f, 0x6d, 0x35, 0x52, 0xef, 0xa6, 0x32, 0xdb, 0x0a, 0x19, + 0x08, 0xcb, 0x83, 0xbc, 0xeb, 0x6a, 0xe6, 0x0f, 0x50, 0x7d, 0x35, 0x8d, 0x36, 0xe6, 0xb3, 0x6d, 0x76, 0xae, 0xae, + 0xdc, 0xe4, 0x13, 0x99, 0x99, 0x9e, 0x9f, 0x78, 0x01, 0x51, 0x07, 0xea, 0x34, 0x70, 0xc3, 0x4f, 0xec, 0xd1, 0x8c, + 0xd6, 0x19, 0x2a, 0xa4, 0xf7, 0xb2, 0xba, 0x1c, 0x26, 0x54, 0x42, 0x87, 0xb4, 0x69, 0x03, 0x14, 0x94, 0xd7, 0x42, + 0xbe, 0x55, 0xd0, 0x85, 0x45, 0x2d, 0x03, 0xec, 0x29, 0x41, 0x47, 0x0e, 0x0e, 0xaa, 0x86, 0x8a, 0xeb, 0xa5, 0x1a, + 0xf2, 0x54, 0xa9, 0x6c, 0x52, 0x64, 0x58, 0xbc, 0xc5, 0x1e, 0x7e, 0xff, 0xe7, 0x68, 0xee, 0xeb, 0xc3, 0x3f, 0xc7, + 0x68, 0xbc, 0xf6, 0x0f, 0xca, 0x8d, 0xdd, 0x34, 0x5d, 0xaf, 0xc8, 0x8c, 0xea, 0xe2, 0xce, 0x8b, 0xa1, 0x94, 0x69, + 0x79, 0x79, 0x38, 0xbf, 0xae, 0x3b, 0xfd, 0xe3, 0xd7, 0x60, 0x23, 0x00, 0x34, 0x5d, 0x34, 0x9f, 0xab, 0x05, 0x57, + 0xbd, 0xa7, 0x99, 0x73, 0xfc, 0xeb, 0xfa, 0x87, 0xb7, 0xf6, 0x0f, 0xa2, 0x71, 0xa8, 0xea, 0xf9, 0x84, 0x2b, 0x3c, + 0x19, 0x69, 0x2a, 0x8d, 0x97, 0xcf, 0x68, 0xee, 0x86, 0xed, 0xd3, 0xb9, 0x2e, 0xed, 0xb2, 0x98, 0x90, 0x19, 0xd8, + 0xc2, 0x1a, 0xb5, 0xd2, 0xdb, 0x80, 0xdc, 0x11, 0xa1, 0x4c, 0xad, 0x7f, 0xac, 0xa1, 0x05, 0x46, 0x7b, 0x63, 0x4a, + 0x5a, 0x46, 0x58, 0x49, 0x53, 0x9a, 0xe0, 0x1c, 0xd8, 0xcc, 0xe5, 0x5d, 0x5e, 0xd9, 0xd5, 0x13, 0x43, 0x95, 0x06, + 0xd0, 0x3a, 0xb2, 0xf3, 0x96, 0xf2, 0x01, 0xa6, 0x7a, 0x6e, 0x1e, 0x9b, 0xe1, 0xe8, 0x03, 0x88, 0x8e, 0xcd, 0xe0, + 0x14, 0xc0, 0xe6, 0xd7, 0x0a, 0x01, 0x44, 0x1b, 0xc4, 0x9a, 0xc4, 0x52, 0x2a, 0x95, 0x77, 0x70, 0xfb, 0x42, 0x34, + 0xb4, 0xe5, 0x92, 0x9f, 0xc6, 0xb5, 0x51, 0xca, 0x33, 0x9f, 0x62, 0x0a, 0xd5, 0x90, 0xa4, 0x69, 0x2b, 0xc0, 0xc4, + 0xa2, 0x1b, 0x6a, 0x51, 0xbb, 0x0c, 0x8f, 0xa2, 0xdc, 0xb0, 0x0d, 0xb8, 0x95, 0x71, 0x82, 0xd5, 0x6f, 0x21, 0x86, + 0xbf, 0x5d, 0x31, 0x0b, 0x91, 0x64, 0x31, 0x55, 0x99, 0xf6, 0xbe, 0xed, 0xfd, 0xbd, 0xca, 0x06, 0x55, 0xba, 0x29, + 0x1b, 0x87, 0xa6, 0x95, 0xb0, 0x5f, 0x4d, 0x40, 0x83, 0x1d, 0xf0, 0x31, 0x55, 0x50, 0x1c, 0x99, 0xcf, 0x89, 0x97, + 0xa5, 0x3a, 0x17, 0xd7, 0x88, 0x78, 0xad, 0xe0, 0xa7, 0xf3, 0x64, 0xa4, 0xfe, 0x04, 0x5e, 0xeb, 0x3c, 0xac, 0x11, + 0x1b, 0x10, 0x67, 0x5b, 0x9a, 0xc1, 0x44, 0x7b, 0x2c, 0x83, 0x88, 0x7d, 0x05, 0xd2, 0x71, 0x37, 0x94, 0xe3, 0xd0, + 0xd8, 0x15, 0x50, 0xec, 0x8b, 0x48, 0xd8, 0x91, 0xec, 0x46, 0x40, 0xbb, 0x8e, 0xef, 0xd6, 0xf9, 0xa1, 0xe7, 0xd8, + 0xb9, 0x6a, 0x80, 0xb7, 0xd4, 0xa7, 0x43, 0x0f, 0x3d, 0xb6, 0xea, 0x42, 0xab, 0x75, 0xf8, 0x98, 0x76, 0x1d, 0xe7, + 0x95, 0xa3, 0x1a, 0xd4, 0x48, 0x4d, 0xc2, 0x6d, 0x5e, 0x74, 0x47, 0x92, 0x2f, 0x9e, 0x4a, 0xb9, 0xf3, 0xc3, 0xc6, + 0x73, 0xe2, 0xd8, 0x80, 0x84, 0xb3, 0x28, 0x7e, 0xc4, 0x14, 0xba, 0xaa, 0xa1, 0x7a, 0x41, 0x94, 0x12, 0x79, 0x0e, + 0x54, 0xec, 0xf0, 0x85, 0x93, 0xf8, 0xf9, 0xfd, 0xdb, 0x0f, 0x1f, 0x54, 0x03, 0x73, 0x6f, 0xa6, 0x72, 0xef, 0x6c, + 0x43, 0xed, 0xc1, 0xfe, 0x8d, 0xfb, 0x8e, 0xde, 0x30, 0x94, 0xaf, 0x2c, 0xef, 0x39, 0x5a, 0x56, 0xdb, 0x72, 0xec, + 0xe6, 0x61, 0x5f, 0xa6, 0xcc, 0xe0, 0x41, 0xf3, 0x6a, 0xc0, 0x0d, 0xbb, 0xaf, 0xb7, 0x52, 0xc9, 0xca, 0x0f, 0x6f, + 0x1b, 0x4a, 0xdd, 0x4d, 0x43, 0x29, 0x70, 0x53, 0x35, 0x5c, 0xb5, 0x8e, 0x56, 0xd2, 0xed, 0x0c, 0xa9, 0x93, 0xf7, + 0x81, 0x4b, 0x62, 0x69, 0xbe, 0x60, 0xd0, 0x2c, 0x76, 0x7a, 0x75, 0xd4, 0x0d, 0xc5, 0x8c, 0x0f, 0x11, 0xb0, 0xf5, + 0x02, 0x30, 0xb1, 0x23, 0xb2, 0x1e, 0xac, 0x4c, 0xb9, 0x09, 0x03, 0x59, 0xa9, 0x13, 0x4a, 0x61, 0xde, 0x66, 0x64, + 0x15, 0x93, 0xc4, 0xcd, 0xd6, 0x09, 0xb9, 0x0d, 0xa2, 0xfb, 0x27, 0x85, 0x01, 0xfb, 0x9e, 0xca, 0x4b, 0x7f, 0xb1, + 0x14, 0xb5, 0xcf, 0x35, 0x32, 0x12, 0x0b, 0xb8, 0xf3, 0x03, 0xf9, 0x7f, 0xfe, 0x6d, 0x59, 0xff, 0xf9, 0xf7, 0xde, + 0xaa, 0xd0, 0x7d, 0x3e, 0x31, 0xb2, 0xd1, 0x01, 0xfb, 0xa2, 0xf9, 0x4b, 0x65, 0x98, 0x37, 0xd7, 0xa9, 0x2d, 0x02, + 0xbc, 0xaf, 0x2d, 0x41, 0xad, 0xb0, 0xbc, 0x6f, 0x1e, 0x35, 0x30, 0x98, 0xd7, 0xde, 0x91, 0x41, 0xa5, 0x2f, 0x1a, + 0xda, 0x44, 0x1f, 0x1c, 0xb4, 0x22, 0xbf, 0x1f, 0xc2, 0xfb, 0xe6, 0xf0, 0x85, 0xc3, 0x67, 0xa2, 0xc1, 0xd7, 0x93, + 0x89, 0xc8, 0xe6, 0x26, 0x37, 0x05, 0xa3, 0xfa, 0xf3, 0x5a, 0x09, 0xbb, 0x3c, 0x07, 0xb6, 0x4e, 0xbd, 0xdd, 0x47, + 0xaf, 0x27, 0x68, 0xfe, 0x75, 0x36, 0x4d, 0x0a, 0x62, 0xa5, 0x15, 0xb5, 0x51, 0xf3, 0xed, 0x5a, 0xa7, 0x35, 0xbc, + 0x06, 0xa5, 0x98, 0xe2, 0x2b, 0x9f, 0xe8, 0xc6, 0xeb, 0x09, 0x93, 0xed, 0x30, 0x8b, 0xd3, 0x41, 0x75, 0x6b, 0x33, + 0xc9, 0x68, 0x09, 0xe8, 0x86, 0x42, 0x35, 0x2e, 0x58, 0x99, 0x14, 0xa2, 0x34, 0x14, 0xa9, 0x03, 0x53, 0x3f, 0xc9, + 0x31, 0xc3, 0xc8, 0xbb, 0x36, 0xab, 0xac, 0x9f, 0xf7, 0x5b, 0x65, 0x5d, 0x1d, 0x64, 0x95, 0xf5, 0xf3, 0x57, 0xb7, + 0xca, 0x7a, 0x27, 0x5b, 0x65, 0xc1, 0x22, 0xbe, 0x25, 0x07, 0x99, 0x4a, 0x71, 0x3b, 0x89, 0xe8, 0x3e, 0x1d, 0x39, + 0x8c, 0xa4, 0x4d, 0xbd, 0x25, 0x01, 0x36, 0x9d, 0xad, 0x4a, 0x10, 0x2d, 0xc0, 0x6c, 0xea, 0x8f, 0x37, 0x70, 0x0a, + 0xa2, 0x85, 0x6c, 0xde, 0x14, 0xb2, 0x18, 0xab, 0x45, 0xdc, 0x24, 0x6a, 0x52, 0x64, 0x1b, 0x3c, 0xca, 0x92, 0x79, + 0xac, 0x4b, 0x79, 0xa4, 0x85, 0xbd, 0x58, 0x87, 0x1b, 0x1d, 0x0d, 0xd0, 0x5e, 0x49, 0x34, 0xec, 0xbc, 0xe4, 0xd1, + 0x24, 0xe4, 0x1e, 0x84, 0x5d, 0x2e, 0x8d, 0xcc, 0xb0, 0x55, 0x7f, 0xdd, 0x38, 0xdf, 0x5f, 0x3b, 0xc3, 0xae, 0x03, + 0xee, 0xd0, 0xc0, 0xe4, 0x61, 0x81, 0x3d, 0xec, 0x76, 0xa1, 0xe0, 0x5e, 0x2a, 0xe8, 0x40, 0x81, 0x2f, 0x15, 0xf4, + 0xa0, 0xc0, 0x93, 0x0a, 0x4e, 0xa0, 0x60, 0x26, 0x15, 0xf4, 0xa1, 0xe0, 0x4e, 0xcd, 0xaf, 0x43, 0x31, 0xdc, 0xbe, + 0x7e, 0x63, 0x50, 0xa6, 0x82, 0x97, 0xf5, 0x0d, 0x07, 0xec, 0x94, 0xdc, 0xc5, 0x20, 0x32, 0xa8, 0x80, 0x6f, 0x90, + 0x18, 0xf7, 0x4b, 0x42, 0x43, 0x33, 0xbf, 0xc1, 0x3b, 0xc7, 0xca, 0x22, 0xb0, 0x54, 0xe6, 0x21, 0x0f, 0x38, 0x1c, + 0x14, 0x55, 0x07, 0x99, 0xcd, 0x50, 0xac, 0x1c, 0x0f, 0x1b, 0x21, 0xad, 0x65, 0xf1, 0x8e, 0x7e, 0xce, 0x14, 0x5b, + 0xa0, 0xb0, 0xf1, 0xd0, 0x64, 0xc1, 0xe0, 0xd7, 0xd0, 0xf4, 0xbf, 0x21, 0xd3, 0xf5, 0x42, 0xb9, 0x8c, 0x16, 0x7b, + 0x95, 0xf6, 0xf2, 0x2b, 0x18, 0xa5, 0x4a, 0x35, 0x20, 0x26, 0xdf, 0x96, 0xec, 0x5b, 0xf4, 0x31, 0x2f, 0xd7, 0xcf, + 0x60, 0x6c, 0x4a, 0x46, 0x4d, 0x46, 0xe0, 0x3b, 0x00, 0x23, 0x49, 0x6b, 0x7e, 0x09, 0x70, 0x96, 0x9e, 0xaf, 0x5c, + 0x69, 0x3c, 0xe3, 0x1f, 0x49, 0x9a, 0xba, 0x0b, 0x5e, 0xbf, 0x3e, 0x4e, 0x30, 0x93, 0x11, 0xfc, 0x17, 0x02, 0x10, + 0x84, 0x69, 0x7e, 0xcd, 0x1a, 0x22, 0x89, 0xee, 0x15, 0xb0, 0xb7, 0x81, 0x0d, 0x55, 0x58, 0x06, 0xf8, 0x16, 0x2c, + 0x61, 0x59, 0x87, 0x0f, 0x87, 0xff, 0x8e, 0x04, 0xd5, 0xc2, 0xcc, 0x5d, 0x54, 0x8b, 0xe8, 0x3e, 0xc8, 0xe5, 0xb1, + 0x09, 0x15, 0x7a, 0xa9, 0xf0, 0x4b, 0x74, 0xc2, 0x41, 0xb4, 0xf8, 0x43, 0x15, 0xc2, 0x3b, 0x14, 0xf9, 0x1f, 0x42, + 0xc3, 0xcf, 0x26, 0x16, 0xc2, 0x58, 0xb1, 0x00, 0x84, 0x83, 0x30, 0x5b, 0x9a, 0xe8, 0xcc, 0xa5, 0x75, 0x42, 0xdd, + 0xb0, 0x70, 0x6d, 0xb7, 0x55, 0x17, 0xd6, 0x41, 0xb2, 0x98, 0xba, 0x9a, 0xd3, 0xe9, 0x1b, 0xfc, 0xcf, 0xb2, 0x7b, + 0x7a, 0x8e, 0x3d, 0x28, 0x33, 0xff, 0x6e, 0x3b, 0x8f, 0xc2, 0xcc, 0x9c, 0xbb, 0x2b, 0x3f, 0x78, 0x18, 0xac, 0xa2, + 0x30, 0x4a, 0x63, 0xd7, 0x23, 0xc3, 0x82, 0xa1, 0x1e, 0x62, 0x70, 0x04, 0xe6, 0x9f, 0xe7, 0x58, 0x9d, 0x84, 0xac, + 0x68, 0x6b, 0x11, 0xfb, 0x60, 0x1e, 0x90, 0x4d, 0xce, 0x3e, 0x5f, 0xaa, 0x4c, 0xab, 0xe2, 0x96, 0xa3, 0x2d, 0x80, + 0x22, 0x65, 0x81, 0x15, 0x20, 0x9c, 0xd0, 0x30, 0x76, 0x67, 0x18, 0x0b, 0xd0, 0xea, 0xf4, 0x12, 0xb2, 0x52, 0xac, + 0x5e, 0x6b, 0xe7, 0x49, 0x74, 0x3f, 0x86, 0xd1, 0x62, 0x63, 0x33, 0x25, 0xc1, 0x1c, 0xdf, 0x98, 0xe8, 0xcb, 0xc1, + 0xfb, 0x31, 0x91, 0x11, 0x87, 0xde, 0xc8, 0x6a, 0x08, 0xaf, 0x07, 0x1d, 0xc5, 0x1e, 0xae, 0xfc, 0xd0, 0xa4, 0xd3, + 0xe9, 0xdb, 0xb1, 0xd4, 0x97, 0x0c, 0x3f, 0x7d, 0x8b, 0xd5, 0x1d, 0xc5, 0x1e, 0x02, 0xb3, 0x36, 0x0f, 0xa2, 0xfb, + 0xc1, 0xd2, 0x9f, 0xcd, 0x48, 0x38, 0xc4, 0x31, 0x8b, 0x42, 0x12, 0x04, 0x7e, 0x9c, 0xfa, 0xe9, 0x70, 0xe5, 0x6e, + 0x58, 0xaf, 0xc7, 0x6d, 0xbd, 0x76, 0x59, 0xaf, 0xdd, 0x83, 0x7b, 0x95, 0xba, 0x01, 0xbf, 0x11, 0xda, 0x0f, 0x1b, + 0x5a, 0x4f, 0xb1, 0x2b, 0xf3, 0x3c, 0xb8, 0xd7, 0x38, 0x21, 0xdb, 0x95, 0x9b, 0x2c, 0xfc, 0x70, 0x60, 0xe7, 0xd6, + 0xdd, 0x96, 0x6e, 0x8c, 0xa7, 0xa7, 0xa7, 0xa7, 0xb9, 0x35, 0xe3, 0x4f, 0xf6, 0x6c, 0x96, 0x5b, 0x1e, 0x7f, 0x9a, + 0xcf, 0x6d, 0x7b, 0x3e, 0xcf, 0x2d, 0x9f, 0x17, 0x74, 0x3b, 0xde, 0xac, 0xdb, 0xc9, 0xad, 0x7b, 0xa9, 0x46, 0x6e, + 0x11, 0xf6, 0x94, 0x90, 0xd9, 0x10, 0x37, 0x12, 0x35, 0xe4, 0x1c, 0xf4, 0x6d, 0x3b, 0x47, 0x0c, 0x70, 0x5d, 0xc2, + 0x4d, 0x28, 0xeb, 0xb9, 0xd9, 0x1e, 0x5c, 0x53, 0x29, 0x3e, 0xe7, 0x79, 0x8d, 0xf5, 0x66, 0x6e, 0xf2, 0xe9, 0x46, + 0x91, 0x66, 0xe1, 0xba, 0xb4, 0xda, 0x96, 0x83, 0xc1, 0xdc, 0x0c, 0x20, 0x48, 0xd6, 0x70, 0x1a, 0x25, 0x70, 0x66, + 0x13, 0x77, 0xe6, 0xaf, 0xd3, 0x81, 0xd3, 0x89, 0x37, 0xbc, 0x88, 0xed, 0xf5, 0xa2, 0x00, 0xcf, 0xde, 0x20, 0x8d, + 0x02, 0x7f, 0xc6, 0x8b, 0xda, 0xce, 0x92, 0xd3, 0xd1, 0x87, 0xe8, 0x22, 0xee, 0x63, 0xa0, 0x03, 0x37, 0x08, 0x14, + 0xab, 0x9b, 0x2a, 0xc4, 0x4d, 0x51, 0xc4, 0xab, 0xd8, 0x29, 0x85, 0x0b, 0xba, 0x83, 0x3b, 0xc7, 0xf1, 0x46, 0xec, + 0x79, 0xe7, 0x24, 0xde, 0xe4, 0xdf, 0xae, 0xc8, 0xcc, 0x77, 0x15, 0xad, 0xd8, 0x4d, 0x8e, 0x0d, 0x62, 0x60, 0x7d, + 0xdb, 0xb2, 0x4d, 0xf9, 0xb1, 0x80, 0x60, 0x82, 0x4f, 0xfc, 0x55, 0x1c, 0x25, 0x99, 0x1b, 0x66, 0x79, 0x3e, 0xb9, + 0xc9, 0xf3, 0xe1, 0x95, 0xaf, 0x5d, 0xff, 0x43, 0xa3, 0xf7, 0x34, 0x55, 0x9b, 0xe4, 0xfa, 0x8d, 0xf1, 0x96, 0xc8, + 0x56, 0x1a, 0x70, 0x8d, 0xa1, 0x85, 0x86, 0x5c, 0x99, 0xde, 0x92, 0xf5, 0xca, 0x14, 0xc8, 0xa2, 0x3a, 0xb5, 0xfa, + 0x28, 0x57, 0xc1, 0x1b, 0x08, 0x2a, 0xbc, 0x25, 0xa3, 0x2b, 0xc9, 0xe2, 0x03, 0x88, 0x15, 0xac, 0x4c, 0x2d, 0xf9, + 0x9f, 0xb5, 0xd1, 0x8c, 0xdf, 0xed, 0xa7, 0x19, 0x7f, 0xc9, 0x0e, 0xa1, 0x19, 0xbf, 0xfb, 0xea, 0x34, 0xe3, 0xb3, + 0xba, 0x25, 0xff, 0x45, 0x34, 0x52, 0x85, 0x90, 0x1f, 0xae, 0xa6, 0x84, 0xc6, 0xc8, 0xb9, 0xf8, 0xdd, 0x86, 0xf7, + 0xbc, 0x37, 0x9a, 0xf5, 0x8d, 0xde, 0xdc, 0x20, 0x8f, 0x7d, 0x17, 0x8e, 0xfe, 0x9e, 0xc8, 0xcf, 0xf3, 0xf9, 0xe8, + 0x4d, 0x24, 0x15, 0x88, 0x27, 0x66, 0xff, 0x50, 0x8a, 0x67, 0x40, 0xdf, 0x70, 0xbb, 0x47, 0xcc, 0xf8, 0x00, 0xee, + 0xd0, 0xd4, 0xce, 0x77, 0x26, 0xec, 0xbd, 0x86, 0xe5, 0x21, 0x68, 0xc2, 0xc8, 0x92, 0x3b, 0xbd, 0xd4, 0x44, 0x89, + 0x0b, 0x92, 0x31, 0x2f, 0xd5, 0xef, 0x1f, 0x2e, 0x66, 0xda, 0x45, 0xa4, 0xe7, 0x7e, 0xfa, 0xae, 0xea, 0x72, 0xc2, + 0xd4, 0x2f, 0x23, 0x79, 0x3a, 0x39, 0xb3, 0xd9, 0x92, 0x53, 0x3a, 0xc3, 0x6b, 0xda, 0xfc, 0xbc, 0x34, 0xd3, 0x81, + 0xdc, 0x90, 0xa5, 0x96, 0xaa, 0x5d, 0xc6, 0xcc, 0xde, 0x7f, 0xcb, 0x28, 0x40, 0xcc, 0x96, 0x85, 0x9e, 0xba, 0x33, + 0xda, 0xdc, 0x9f, 0xe5, 0xb9, 0x3e, 0xe4, 0x80, 0x90, 0x2e, 0x5a, 0xb2, 0x8f, 0x88, 0x4b, 0xef, 0x85, 0x59, 0x01, + 0x53, 0xd2, 0x51, 0x0d, 0xdc, 0x05, 0xe8, 0xb4, 0x99, 0xbe, 0x8e, 0xc1, 0x4c, 0x55, 0x28, 0xf8, 0xa8, 0xad, 0x83, + 0x34, 0x21, 0x50, 0xc2, 0x0a, 0xf8, 0xf3, 0x57, 0xbc, 0xa0, 0x6e, 0x35, 0x49, 0x81, 0x83, 0x4a, 0x79, 0xf0, 0xab, + 0xe7, 0x72, 0x6d, 0x8a, 0x76, 0x58, 0x1d, 0x7c, 0xc8, 0x55, 0x41, 0xfb, 0xe1, 0xf6, 0x1b, 0x9f, 0x1d, 0x41, 0x83, + 0x71, 0x45, 0x77, 0xbf, 0xc7, 0x26, 0x10, 0x48, 0x89, 0xf4, 0xde, 0xb0, 0xd2, 0x7b, 0xe5, 0xc5, 0x96, 0xc7, 0xa4, + 0xc8, 0xdc, 0xd8, 0x04, 0x16, 0x1f, 0x71, 0x2f, 0xc3, 0x78, 0x52, 0xf8, 0x8b, 0xe1, 0x3a, 0x05, 0xdc, 0x88, 0x8c, + 0x2a, 0xe2, 0x9f, 0xa1, 0xb7, 0x4e, 0xd2, 0x28, 0x19, 0xc4, 0x91, 0x1f, 0x66, 0x24, 0xc9, 0x11, 0x54, 0xd7, 0x08, + 0x1f, 0x0e, 0x9e, 0x9b, 0x6d, 0x14, 0xbb, 0x9e, 0x9f, 0x3d, 0x0c, 0x6c, 0x46, 0x52, 0xd8, 0x43, 0x46, 0x1d, 0xd8, + 0x8d, 0xf5, 0x07, 0x0c, 0x9a, 0x2f, 0x91, 0xf0, 0x4b, 0xea, 0xe4, 0x8c, 0xbc, 0xcd, 0x87, 0xd2, 0x5b, 0x1a, 0x95, + 0x03, 0xc8, 0x0f, 0x37, 0x31, 0x17, 0x80, 0xe5, 0x61, 0xa9, 0xed, 0x19, 0x59, 0x18, 0x88, 0xb5, 0x41, 0x2e, 0xcf, + 0xff, 0xac, 0x9e, 0xae, 0xd8, 0xcd, 0xc5, 0x40, 0xf1, 0xe8, 0x87, 0x8c, 0x6c, 0xe0, 0x42, 0x0e, 0x2b, 0xe3, 0x90, + 0x9a, 0x53, 0x32, 0x8f, 0x12, 0x42, 0x23, 0xb8, 0x3a, 0xa7, 0xf1, 0xe6, 0xf0, 0xee, 0x77, 0x4f, 0xbf, 0xb9, 0x9f, + 0x30, 0xca, 0x34, 0xde, 0x99, 0xbe, 0xa7, 0xb7, 0xfa, 0x7d, 0x06, 0xa4, 0x21, 0x85, 0xbc, 0x47, 0x83, 0x65, 0x0d, + 0x54, 0x75, 0xd8, 0x18, 0x28, 0x2b, 0x8e, 0xd8, 0x9d, 0x97, 0x90, 0xc0, 0xcd, 0xfc, 0x3b, 0x4e, 0x33, 0x76, 0x4f, + 0xe2, 0x0d, 0x5f, 0x63, 0xbc, 0xf0, 0x1e, 0xb1, 0x48, 0x95, 0xa1, 0xf0, 0x45, 0xaa, 0x16, 0xe3, 0x22, 0x0d, 0x6b, + 0xb3, 0xe1, 0xb1, 0x23, 0x2a, 0x37, 0x7d, 0x2f, 0xde, 0xc8, 0x57, 0x74, 0xd1, 0x4c, 0xdc, 0xd4, 0xd5, 0xa0, 0x5f, + 0x2b, 0x7f, 0x36, 0x0b, 0x48, 0x5e, 0x5a, 0xe8, 0xf2, 0x5a, 0x4a, 0xc0, 0x11, 0x70, 0x70, 0xa7, 0x69, 0x14, 0xac, + 0x33, 0xd2, 0x0c, 0x2e, 0x0a, 0x9c, 0x8e, 0x5d, 0x00, 0x07, 0x7f, 0x97, 0xc7, 0xda, 0x03, 0x72, 0x1b, 0xb6, 0x89, + 0x3d, 0x84, 0x18, 0xbf, 0x66, 0xb7, 0x3c, 0x74, 0x78, 0x25, 0x06, 0x6d, 0x34, 0x4c, 0xc4, 0x80, 0x6b, 0x89, 0x62, + 0x6f, 0xc5, 0x72, 0x58, 0x99, 0x88, 0x73, 0x2a, 0x8a, 0xf2, 0xf2, 0x64, 0xfe, 0x98, 0x33, 0xf6, 0xaa, 0xf9, 0x8c, + 0xbd, 0xe2, 0x67, 0x6c, 0xf7, 0xce, 0x7c, 0x3a, 0x77, 0xe0, 0xbf, 0x61, 0x31, 0xa1, 0x81, 0xad, 0x74, 0xe3, 0x8d, + 0xe2, 0xc4, 0x1b, 0xc5, 0xec, 0xc4, 0x1b, 0x05, 0xbb, 0x46, 0x93, 0x0c, 0xc3, 0xea, 0xe8, 0x86, 0xad, 0x40, 0x21, + 0xfc, 0xd9, 0xa5, 0x57, 0xce, 0x31, 0xbc, 0x83, 0x56, 0xbd, 0xfa, 0xbb, 0xce, 0xee, 0xa3, 0x4e, 0xcf, 0x12, 0x47, + 0xda, 0xba, 0x95, 0xb9, 0xd3, 0x29, 0x99, 0x0d, 0xe6, 0x91, 0xb7, 0x4e, 0xff, 0xc5, 0xc6, 0xcf, 0x80, 0xb8, 0x13, + 0x11, 0x54, 0xfa, 0xe1, 0x4d, 0x41, 0x51, 0x72, 0x47, 0x78, 0x0f, 0x5b, 0xb1, 0x4e, 0x03, 0x1a, 0x90, 0xb8, 0x63, + 0x1d, 0x37, 0x6c, 0xf2, 0x66, 0x40, 0xff, 0x61, 0xab, 0xd4, 0x8e, 0x62, 0xbe, 0x00, 0x2c, 0x3b, 0xc1, 0xf1, 0x78, + 0x68, 0xb0, 0xd5, 0xb4, 0x4f, 0x9b, 0x87, 0x7b, 0xcd, 0xbf, 0x74, 0xc3, 0x2f, 0x15, 0x76, 0x6f, 0x31, 0x57, 0x90, + 0xdd, 0xbd, 0xb6, 0xed, 0x91, 0x5a, 0xaf, 0x3b, 0x2e, 0x84, 0xa2, 0xee, 0x81, 0x58, 0xfe, 0xe9, 0xab, 0x63, 0xf8, + 0x8f, 0x52, 0xf5, 0xbf, 0x64, 0x4d, 0x84, 0xfa, 0x45, 0xd9, 0xf6, 0x9a, 0x92, 0x4a, 0x48, 0x88, 0x1f, 0x5e, 0x7f, + 0x3e, 0x7f, 0x5c, 0x83, 0x83, 0x6b, 0x53, 0x6b, 0xa6, 0x6a, 0xed, 0xef, 0xa3, 0x08, 0x92, 0x65, 0xd6, 0xab, 0x73, + 0xf0, 0x50, 0xf3, 0xf2, 0x6c, 0x04, 0x8d, 0x38, 0x1f, 0x41, 0xb5, 0xf8, 0x2a, 0xb6, 0xa1, 0xac, 0xc4, 0xdb, 0x36, + 0x56, 0xe2, 0xcd, 0x7e, 0x56, 0xe2, 0xaf, 0x07, 0xb1, 0x12, 0x6f, 0xbe, 0x3a, 0x2b, 0xf1, 0xb6, 0xce, 0x4a, 0x5c, + 0x45, 0xdc, 0x84, 0xd5, 0xb8, 0x58, 0xb3, 0x9f, 0x1f, 0xa9, 0x52, 0xee, 0x32, 0x1a, 0xf5, 0x6c, 0x1a, 0x64, 0xf8, + 0xea, 0x77, 0x33, 0x16, 0xb8, 0x11, 0xdf, 0xa3, 0x45, 0x57, 0xc1, 0x5a, 0x30, 0xcc, 0x8e, 0xdf, 0x91, 0x8a, 0x83, + 0x28, 0x5c, 0xfc, 0x0c, 0x4a, 0x59, 0x10, 0x07, 0x26, 0xd2, 0x0b, 0x3f, 0xfd, 0x39, 0x8a, 0xd7, 0xf1, 0x05, 0xf4, + 0xf5, 0xd1, 0x4f, 0xfd, 0x69, 0x40, 0x84, 0xef, 0x2f, 0xb5, 0x40, 0x63, 0x32, 0x71, 0x30, 0xfa, 0xe4, 0x3f, 0xdd, + 0x0d, 0xff, 0x89, 0x66, 0xa1, 0xec, 0x37, 0x35, 0x6d, 0x53, 0x9b, 0x19, 0x11, 0xae, 0x04, 0x94, 0x06, 0xfd, 0x78, + 0x66, 0xe4, 0x2a, 0xd2, 0x1b, 0x66, 0xc9, 0xed, 0x1d, 0x5a, 0xfb, 0x21, 0x35, 0xa6, 0x66, 0xad, 0x1b, 0x22, 0xe8, + 0x55, 0x5d, 0x0c, 0xbf, 0x8a, 0xd6, 0x29, 0x99, 0x45, 0xf7, 0xa1, 0x6a, 0x84, 0xc2, 0xac, 0x1f, 0x34, 0x9c, 0xa2, + 0x0d, 0xa6, 0x6b, 0xfc, 0x80, 0x84, 0x72, 0x94, 0x68, 0x2a, 0x64, 0x0b, 0x5d, 0xc7, 0x26, 0x55, 0x35, 0x9b, 0x38, + 0x45, 0x55, 0xe4, 0x15, 0x7a, 0xa2, 0x69, 0xd1, 0xe8, 0x71, 0x2d, 0xb9, 0xa9, 0x46, 0x64, 0x31, 0xa9, 0x70, 0xaa, + 0x85, 0x5c, 0xb8, 0xc8, 0x23, 0x4f, 0x34, 0x2c, 0x1c, 0x7b, 0x43, 0x9d, 0x45, 0x8b, 0xb7, 0x10, 0xb7, 0x23, 0x5f, + 0xb3, 0xf5, 0x60, 0x71, 0x18, 0xe8, 0xe3, 0x6b, 0x09, 0x8c, 0xef, 0xee, 0x48, 0x12, 0xb8, 0x0f, 0x9a, 0x9e, 0x47, + 0xe1, 0x8f, 0x00, 0x80, 0x37, 0xd1, 0x7d, 0x28, 0x57, 0xc0, 0xf4, 0x28, 0x0d, 0x7b, 0xa9, 0x31, 0x62, 0x08, 0xb8, + 0x8a, 0x48, 0x23, 0x80, 0xc4, 0xb4, 0x0b, 0xf2, 0x77, 0x83, 0xfe, 0xfb, 0x0f, 0x3d, 0x37, 0x2e, 0x23, 0xf1, 0xa1, + 0xbf, 0xc5, 0x07, 0x7c, 0xe6, 0xf9, 0xf3, 0x27, 0xed, 0xd3, 0x2e, 0x27, 0x44, 0x6f, 0x68, 0xad, 0xb7, 0x9e, 0x02, + 0x18, 0xc5, 0x55, 0xb4, 0xf6, 0x96, 0x68, 0x6b, 0xfa, 0xf5, 0xe6, 0x9b, 0x41, 0x9f, 0x98, 0x17, 0x54, 0x4c, 0xbd, + 0x52, 0x54, 0x40, 0x01, 0xbf, 0xff, 0x16, 0x42, 0x5e, 0xfe, 0x0f, 0xc1, 0x50, 0xdf, 0x35, 0x8c, 0x8b, 0xf7, 0x1f, + 0xb7, 0x79, 0x87, 0x90, 0xbe, 0x92, 0x05, 0x93, 0xe0, 0xca, 0xb5, 0x66, 0x24, 0x93, 0x57, 0x81, 0x26, 0x07, 0x6e, + 0x6b, 0x8b, 0x49, 0xc7, 0xbf, 0x42, 0x2c, 0xca, 0xa6, 0x33, 0x5b, 0x7f, 0x83, 0x30, 0x6c, 0x55, 0x41, 0x32, 0xcc, + 0xe4, 0x81, 0x20, 0xfa, 0xaa, 0xbe, 0x5b, 0xf9, 0xa1, 0x81, 0x71, 0xd7, 0xeb, 0x6f, 0xdc, 0x0d, 0x44, 0x1e, 0x06, + 0xe4, 0x56, 0x7d, 0x05, 0x85, 0x86, 0xec, 0xa9, 0x06, 0xc9, 0x95, 0xd4, 0x46, 0x48, 0x70, 0x2d, 0xde, 0xe4, 0x4f, + 0x8a, 0xa2, 0x28, 0x82, 0x8d, 0x50, 0x04, 0x1f, 0x81, 0xe5, 0xc8, 0x0e, 0x80, 0xb6, 0x24, 0x8f, 0x37, 0xb4, 0x04, + 0x38, 0x03, 0xd4, 0xc9, 0xf2, 0x02, 0x16, 0x5c, 0xaf, 0x67, 0xf3, 0x02, 0xce, 0xd0, 0x43, 0x60, 0x34, 0x37, 0x81, + 0x18, 0xbc, 0x03, 0x05, 0x19, 0x76, 0x7c, 0xcb, 0x24, 0xc1, 0x8a, 0x4d, 0x1f, 0x27, 0x43, 0xd2, 0x1c, 0x85, 0x2d, + 0x94, 0xb0, 0x20, 0x68, 0x1d, 0x2a, 0x41, 0x95, 0x0d, 0xd2, 0x80, 0x1b, 0x91, 0x2f, 0xda, 0x64, 0x2b, 0x12, 0xae, + 0x55, 0xcc, 0xc2, 0x84, 0x51, 0xf1, 0xa0, 0xce, 0x1b, 0x4a, 0x6c, 0x01, 0xb6, 0x69, 0x6e, 0xb9, 0xa4, 0x77, 0x61, + 0xca, 0x50, 0xaa, 0x6b, 0x78, 0x4c, 0xb1, 0x99, 0x32, 0xdc, 0x56, 0xbd, 0x21, 0xd8, 0x92, 0x46, 0x55, 0xd7, 0x29, + 0x6a, 0x8c, 0x0c, 0x7d, 0xd0, 0x78, 0x14, 0x4c, 0x5c, 0xc4, 0xc1, 0xae, 0xb9, 0xd5, 0x45, 0x13, 0x1a, 0x19, 0xb7, + 0x22, 0x28, 0x4a, 0xf4, 0x7a, 0x37, 0x6c, 0x9c, 0x10, 0x0a, 0xa8, 0xb5, 0x1f, 0xaf, 0xd6, 0x4f, 0xcb, 0xa4, 0x3f, + 0x91, 0x07, 0x7a, 0x91, 0x50, 0x50, 0x7d, 0x22, 0x0f, 0x60, 0xfb, 0xf7, 0x16, 0xa4, 0x29, 0xea, 0x0e, 0x74, 0x6d, + 0x40, 0x70, 0x7d, 0x0f, 0xc2, 0x43, 0xed, 0x38, 0x40, 0x76, 0xbe, 0x03, 0x8b, 0x23, 0x88, 0x21, 0x8f, 0x32, 0x3f, + 0xc4, 0xcc, 0xca, 0x5e, 0x6b, 0x84, 0xb1, 0xd9, 0x70, 0x34, 0xf4, 0x17, 0x8e, 0x6d, 0x1f, 0xd5, 0xea, 0x83, 0x20, + 0xbb, 0xa9, 0xb6, 0x6e, 0x64, 0x23, 0xc7, 0x36, 0xfd, 0x17, 0x56, 0x67, 0x58, 0xbb, 0xa3, 0xa5, 0xe8, 0x8d, 0x13, + 0x14, 0x7f, 0x8d, 0x9f, 0x6d, 0xb5, 0xda, 0x81, 0xd4, 0xab, 0x56, 0xeb, 0x38, 0xb6, 0x9c, 0xc9, 0xbf, 0x26, 0xf5, + 0xab, 0x9f, 0xc6, 0x8e, 0xa4, 0x99, 0x44, 0x26, 0x10, 0x7f, 0x58, 0x83, 0x63, 0xf4, 0x67, 0xe5, 0xa5, 0xa2, 0xd1, + 0xe3, 0xa3, 0xeb, 0x13, 0x91, 0xa0, 0x9a, 0xbb, 0x75, 0xc9, 0x1d, 0x54, 0xbe, 0x98, 0x56, 0x31, 0x1c, 0x8b, 0x74, + 0x4a, 0x0a, 0x8d, 0xde, 0x4e, 0x6a, 0x01, 0xfb, 0x6f, 0xb9, 0x3e, 0xad, 0x29, 0x44, 0x02, 0x80, 0x1a, 0x10, 0xad, + 0x7c, 0x6f, 0x87, 0xeb, 0xb8, 0xdc, 0x5d, 0xf9, 0x92, 0x3c, 0xbc, 0x33, 0xbc, 0x74, 0x50, 0x87, 0x26, 0xfa, 0x6b, + 0xbe, 0xee, 0x1e, 0xd9, 0x25, 0x09, 0x67, 0xe5, 0x0e, 0x2b, 0xf7, 0xd7, 0xe1, 0xdd, 0x95, 0x30, 0x0a, 0x84, 0xf1, + 0x8f, 0x1a, 0x30, 0x4a, 0x1e, 0x85, 0xb8, 0xf9, 0xe9, 0x71, 0xf3, 0x0f, 0xa2, 0x62, 0xb0, 0x01, 0x8d, 0xc1, 0x25, + 0x9a, 0x49, 0x42, 0x71, 0x88, 0x15, 0x8d, 0x8e, 0xb8, 0x1a, 0x27, 0x44, 0x5b, 0x77, 0x62, 0xc6, 0x6d, 0x0a, 0x8b, + 0x36, 0x3e, 0x8b, 0xfe, 0x78, 0xa8, 0xd4, 0xda, 0xdf, 0x2f, 0xb5, 0xce, 0xf6, 0x49, 0xad, 0xa9, 0x47, 0xd3, 0x7d, + 0xe2, 0xc6, 0x92, 0x53, 0x1c, 0x27, 0xce, 0x65, 0xdf, 0xb8, 0x92, 0xa8, 0x1b, 0x1d, 0xa0, 0x78, 0xab, 0x5a, 0x6f, + 0xd4, 0x4a, 0x10, 0xc5, 0xdf, 0x12, 0x83, 0xc2, 0x15, 0xea, 0xb2, 0x6c, 0xfc, 0xaa, 0x90, 0x8d, 0x53, 0xae, 0xa6, + 0xf0, 0x65, 0xe1, 0xd4, 0xbf, 0xe4, 0x27, 0x26, 0xb8, 0x83, 0xc2, 0x5f, 0xac, 0x18, 0xa9, 0xe4, 0x01, 0x55, 0x30, + 0x1a, 0x92, 0x5f, 0x1d, 0xe7, 0x32, 0xca, 0xee, 0x75, 0xe5, 0xaa, 0x85, 0x03, 0x54, 0x51, 0x0e, 0x52, 0x77, 0x1c, + 0xb2, 0x28, 0x96, 0xb7, 0x4d, 0xd9, 0x03, 0x46, 0x7e, 0x2d, 0x6d, 0x12, 0xe1, 0xaa, 0x42, 0x01, 0xcc, 0xc5, 0xf4, + 0x15, 0xbd, 0xb6, 0xb0, 0x81, 0xc0, 0x41, 0x36, 0x78, 0xd6, 0xed, 0x97, 0xce, 0xd3, 0x0c, 0x05, 0x85, 0x16, 0x5e, + 0x96, 0x41, 0x20, 0x7c, 0x6f, 0xb6, 0x0d, 0xb7, 0x3c, 0x5e, 0xf2, 0xec, 0x7e, 0x07, 0xf1, 0xa2, 0x62, 0xcb, 0x8a, + 0x7c, 0x3c, 0x99, 0x26, 0x35, 0xcf, 0xc5, 0xaa, 0xf5, 0x4e, 0xa9, 0x10, 0x67, 0xcb, 0x9c, 0x53, 0xca, 0x32, 0x7a, + 0x56, 0x63, 0xc0, 0xbf, 0xcb, 0xb6, 0x4e, 0xb2, 0x0e, 0x31, 0x9a, 0xbc, 0x99, 0x25, 0xae, 0xf7, 0x49, 0x1a, 0x32, + 0x97, 0x73, 0x82, 0x0c, 0xb8, 0xac, 0x29, 0x18, 0xba, 0x18, 0x7c, 0x91, 0x0c, 0xac, 0x4e, 0x2a, 0x49, 0x5f, 0x06, + 0x4f, 0xed, 0xae, 0xfb, 0x6a, 0x7e, 0x5c, 0x11, 0x8a, 0x76, 0x7a, 0x65, 0x91, 0x79, 0xcb, 0x38, 0xb2, 0xe5, 0x7a, + 0x35, 0xdd, 0xca, 0xb2, 0x55, 0x49, 0xe4, 0x5a, 0x17, 0xb3, 0xca, 0x9f, 0x9d, 0xcf, 0xe7, 0x65, 0x41, 0xa3, 0xad, + 0x1c, 0xa3, 0xb0, 0xf0, 0xa9, 0x6d, 0xdb, 0xd5, 0xb1, 0xef, 0x06, 0xbb, 0x89, 0x72, 0xdb, 0xd3, 0xc6, 0x11, 0x23, + 0x6c, 0xf7, 0xc1, 0xaf, 0x0e, 0x8e, 0xdc, 0x2a, 0x4e, 0x76, 0xc9, 0x2c, 0x62, 0x48, 0x8d, 0x21, 0xfc, 0x8c, 0xac, + 0xd2, 0x81, 0x47, 0x50, 0x07, 0x63, 0x49, 0x07, 0x1a, 0x0d, 0x07, 0xcc, 0x05, 0x98, 0x8a, 0x38, 0x7c, 0x57, 0xd8, + 0x0a, 0xca, 0xc3, 0x6b, 0xc2, 0x7b, 0xfe, 0x11, 0x3c, 0x28, 0xdb, 0xba, 0x4c, 0x1b, 0xa7, 0xd5, 0xb3, 0xff, 0x5c, + 0xaa, 0xa7, 0xc0, 0x05, 0xb8, 0xe5, 0x0a, 0x6d, 0x2a, 0x9f, 0xc5, 0xff, 0x17, 0xf2, 0xff, 0x57, 0xf1, 0xa6, 0x6c, + 0x3f, 0x72, 0x0a, 0x12, 0xed, 0xe2, 0xb4, 0xd0, 0x51, 0x37, 0xed, 0x01, 0x61, 0x65, 0x30, 0x97, 0x15, 0xe8, 0xa0, + 0xa4, 0x2f, 0xa5, 0xdc, 0x68, 0x10, 0xbf, 0x23, 0xc5, 0x0c, 0x4b, 0x5c, 0x88, 0x10, 0x8b, 0x84, 0x71, 0x30, 0x07, + 0xe3, 0xe5, 0x29, 0xea, 0x0f, 0x4a, 0x7b, 0x02, 0xb4, 0xf1, 0xb5, 0xb9, 0x1d, 0x24, 0xee, 0xaf, 0xea, 0xb5, 0x78, + 0xc7, 0x00, 0x32, 0x07, 0x0e, 0x21, 0x1a, 0x12, 0x28, 0x95, 0xcd, 0x4d, 0x47, 0x29, 0xde, 0xca, 0x7a, 0x36, 0x3e, + 0x30, 0xec, 0xae, 0xb9, 0x0a, 0xed, 0x9b, 0x6b, 0x0b, 0x60, 0xb2, 0x6c, 0xfb, 0xe1, 0xb3, 0x09, 0x4b, 0x2c, 0xef, + 0x47, 0x07, 0x97, 0x1c, 0xf7, 0xaf, 0x89, 0x77, 0x67, 0x4a, 0xcf, 0x3f, 0xca, 0x17, 0xff, 0xda, 0x28, 0xd0, 0xbb, + 0x2a, 0x49, 0xe8, 0x98, 0xb5, 0x78, 0x47, 0x3f, 0xa8, 0xf6, 0xca, 0x0f, 0x0f, 0xaf, 0xeb, 0x6e, 0x0e, 0xae, 0x0b, + 0x17, 0xc6, 0xc1, 0x95, 0xe1, 0xc6, 0xa1, 0x96, 0x0b, 0xd9, 0xe8, 0xaf, 0x92, 0x40, 0x51, 0x76, 0xfc, 0x55, 0xb1, + 0x15, 0xa5, 0xf2, 0xaf, 0xd6, 0x40, 0x7c, 0x1e, 0x94, 0x52, 0x41, 0xe1, 0x59, 0xd1, 0xd4, 0xbe, 0x72, 0xaa, 0xf4, + 0xbb, 0xca, 0x89, 0xad, 0x52, 0x2e, 0x6c, 0xa4, 0xf6, 0x3a, 0x85, 0x43, 0xdf, 0xb1, 0xad, 0x8e, 0xcf, 0x16, 0xfc, + 0x92, 0x98, 0xfb, 0x41, 0x40, 0x51, 0x45, 0x9a, 0x25, 0xd1, 0x27, 0x52, 0x56, 0xb3, 0xd0, 0x32, 0x66, 0x04, 0xd2, + 0xe1, 0x8f, 0x70, 0x76, 0x3c, 0x37, 0x1e, 0xe0, 0xd9, 0x90, 0x0b, 0xc1, 0x80, 0x93, 0x96, 0xe2, 0x27, 0xe0, 0x0e, + 0x9e, 0xaa, 0xe3, 0x33, 0x08, 0x1a, 0xa8, 0xcc, 0x46, 0xea, 0x8f, 0x9d, 0xbe, 0xe2, 0xf4, 0xee, 0xcc, 0xae, 0x67, + 0x9b, 0x8e, 0x75, 0xac, 0xd8, 0xd6, 0x89, 0xd9, 0xb1, 0xfa, 0x4a, 0xc7, 0xea, 0xc1, 0xbf, 0x9e, 0x63, 0xbd, 0x52, + 0x6c, 0x78, 0x52, 0x1c, 0xab, 0x8b, 0xff, 0x76, 0xac, 0xfe, 0x5d, 0x97, 0xde, 0xf4, 0xae, 0x70, 0xab, 0xaa, 0x8c, + 0x02, 0x9c, 0x40, 0xd4, 0xa3, 0xf1, 0xd9, 0x3a, 0x25, 0xca, 0x66, 0xa4, 0xbe, 0x52, 0x95, 0x65, 0x42, 0xe6, 0x23, + 0xf5, 0xa9, 0x2b, 0x95, 0x3a, 0xa7, 0x8d, 0xc5, 0x9d, 0x7e, 0x63, 0x71, 0xf7, 0xa4, 0xb1, 0xf8, 0xb8, 0x57, 0x2e, + 0x3e, 0x5a, 0xd0, 0x57, 0x52, 0xce, 0xbe, 0x95, 0x9b, 0x25, 0xfe, 0x46, 0x73, 0x14, 0x40, 0xd7, 0x26, 0xfc, 0xd3, + 0xef, 0xe8, 0xa2, 0xd5, 0x14, 0x5a, 0x09, 0x68, 0xf4, 0x4f, 0x15, 0xe7, 0xe4, 0x2f, 0x9d, 0x13, 0x0f, 0xea, 0x41, + 0x86, 0x49, 0xf8, 0xbb, 0xeb, 0x9e, 0x7a, 0xb6, 0x02, 0x0d, 0x1d, 0xf8, 0x6f, 0xd9, 0xeb, 0x78, 0xf4, 0xc1, 0x86, + 0xf7, 0x1f, 0x9d, 0x7e, 0x6a, 0x9b, 0x0e, 0xfc, 0xf7, 0x9b, 0x50, 0xb9, 0x83, 0xc2, 0x5f, 0xee, 0xf7, 0xd8, 0x56, + 0xba, 0xa7, 0xcb, 0x8e, 0xf5, 0xea, 0xae, 0x6f, 0x9d, 0x2e, 0x9d, 0xfe, 0x47, 0xfa, 0x14, 0x98, 0x1d, 0xeb, 0x15, + 0xfc, 0x7d, 0xec, 0xda, 0x4b, 0xd3, 0xb1, 0x4e, 0xef, 0xba, 0x56, 0x37, 0x30, 0x4f, 0xac, 0x53, 0xf8, 0xfb, 0x0d, + 0xc0, 0x0b, 0x70, 0x65, 0x29, 0x41, 0x15, 0xd8, 0x18, 0x15, 0xfb, 0x0d, 0xf9, 0x23, 0x9d, 0x63, 0xa5, 0x77, 0xfc, + 0x97, 0xd3, 0x3b, 0xf3, 0x78, 0xe9, 0x74, 0xee, 0xcc, 0xd6, 0x9f, 0x1f, 0x01, 0xf2, 0xbb, 0x17, 0x0e, 0xc0, 0x88, + 0x39, 0x40, 0xfe, 0x34, 0x31, 0x2e, 0xdb, 0xc4, 0xe8, 0xef, 0xf7, 0x8b, 0xd1, 0x7f, 0x58, 0x1f, 0x22, 0x46, 0x7f, + 0xff, 0xd5, 0xc5, 0xe8, 0x97, 0x55, 0x2b, 0xee, 0xf7, 0xd5, 0x58, 0xe5, 0xbf, 0x6c, 0xab, 0x44, 0xb2, 0xef, 0x6a, + 0xd7, 0x57, 0xeb, 0x1b, 0x88, 0xb6, 0xf3, 0x3e, 0x1a, 0xfd, 0xb0, 0x2e, 0x99, 0x28, 0x45, 0x80, 0x01, 0xde, 0x47, + 0x14, 0x03, 0xfc, 0xb6, 0x1e, 0x81, 0x5d, 0x04, 0xbb, 0x35, 0xfd, 0x99, 0xb9, 0x74, 0x83, 0xb9, 0xb8, 0x71, 0xa1, + 0x64, 0x88, 0xc5, 0x60, 0x33, 0x0f, 0x97, 0x09, 0x28, 0x6b, 0xd6, 0xab, 0x30, 0x1d, 0x9c, 0xd8, 0x80, 0xe6, 0x3b, + 0xf3, 0x24, 0xaf, 0x34, 0xb6, 0x78, 0x7c, 0xa2, 0x5b, 0x66, 0xd3, 0xdf, 0xfa, 0x1e, 0x4d, 0xd6, 0x9a, 0x7b, 0x77, + 0xea, 0xfd, 0x2a, 0x60, 0x0b, 0xc2, 0x4d, 0xfa, 0x80, 0xd8, 0x68, 0x7a, 0x5f, 0x36, 0x1c, 0xab, 0x98, 0x0a, 0xb6, + 0x8f, 0x14, 0x46, 0x52, 0x6d, 0xef, 0x94, 0x0d, 0xcf, 0xf6, 0x4d, 0xb3, 0xe1, 0xf3, 0xa5, 0xe6, 0x3b, 0xac, 0xde, + 0x44, 0xc7, 0x55, 0x50, 0x55, 0x32, 0x6d, 0x35, 0x02, 0xa4, 0xa0, 0x3d, 0x0b, 0xd3, 0xb8, 0x82, 0xf0, 0xb1, 0x15, + 0xbc, 0x8d, 0x6d, 0xe9, 0x5d, 0xa9, 0x4f, 0xd9, 0x9c, 0xee, 0xc5, 0x16, 0xe9, 0x41, 0xff, 0x37, 0x20, 0x6c, 0xd8, + 0x7d, 0x3c, 0x8d, 0x64, 0x38, 0x6f, 0xa5, 0x7e, 0x29, 0xa9, 0x9d, 0x2f, 0x9d, 0x6d, 0x9d, 0xb4, 0x69, 0x35, 0xa4, + 0x75, 0xc8, 0x8a, 0xdf, 0xd1, 0xf8, 0x79, 0x6a, 0xb6, 0x9a, 0x53, 0xd3, 0x62, 0xb4, 0xcc, 0xdd, 0xd5, 0x19, 0xaf, + 0xf7, 0x14, 0x36, 0xb1, 0xc1, 0x1e, 0x64, 0xc7, 0xf1, 0xed, 0x1c, 0xb2, 0x22, 0x0f, 0x90, 0x88, 0x90, 0x28, 0xa8, + 0x0e, 0xda, 0xd8, 0x0e, 0x77, 0x98, 0x7f, 0xc8, 0x1d, 0xb3, 0x4e, 0xd0, 0x56, 0x77, 0x97, 0xc5, 0x88, 0x70, 0x6d, + 0xd8, 0x96, 0x14, 0xa8, 0x4e, 0xaf, 0x6f, 0x38, 0x27, 0x86, 0xd5, 0xef, 0xe9, 0x39, 0x3f, 0x70, 0x72, 0x97, 0x25, + 0x80, 0x80, 0xc9, 0xae, 0x18, 0xa6, 0x1f, 0xfa, 0x99, 0xef, 0x06, 0x39, 0xa0, 0xfa, 0x32, 0xcd, 0xfb, 0xcf, 0x75, + 0x9a, 0xc1, 0x1c, 0x39, 0x49, 0x86, 0xe6, 0xca, 0xe6, 0x94, 0x64, 0xf7, 0x84, 0x84, 0x2d, 0xaa, 0xdc, 0xaa, 0xf5, + 0xf3, 0x1f, 0x67, 0x0b, 0x9a, 0x53, 0x3b, 0x8b, 0x69, 0x16, 0xb2, 0xfd, 0xc1, 0x4d, 0x75, 0xf3, 0x89, 0xf1, 0x53, + 0x1b, 0xc2, 0xfd, 0xe7, 0x7e, 0x84, 0x9b, 0x91, 0x43, 0x10, 0xee, 0x3f, 0xbf, 0x3a, 0xc2, 0xfd, 0x49, 0x46, 0xb8, + 0x25, 0x4f, 0x95, 0x42, 0x26, 0xfa, 0x01, 0x9f, 0x35, 0x08, 0xf2, 0xfb, 0x52, 0x3d, 0xa2, 0xe4, 0xa5, 0x2a, 0x25, + 0x5f, 0xfd, 0x58, 0xca, 0x26, 0x83, 0x2c, 0x3b, 0x06, 0x25, 0xa5, 0x99, 0x2b, 0x20, 0x31, 0xa9, 0x48, 0xb1, 0x0d, + 0x7d, 0x5e, 0x84, 0x59, 0x60, 0xbd, 0x67, 0x6c, 0x09, 0xa8, 0x20, 0x7e, 0x88, 0x92, 0x95, 0x8b, 0x01, 0xd9, 0x54, + 0xcc, 0x42, 0x07, 0x0f, 0x36, 0x78, 0x47, 0x79, 0x51, 0x38, 0x13, 0x72, 0x74, 0x32, 0xba, 0xa6, 0xf4, 0xa0, 0xfa, + 0x40, 0xdc, 0x44, 0x35, 0xe8, 0x6b, 0x58, 0xdc, 0x17, 0x5d, 0xfb, 0x45, 0xe7, 0xf8, 0xc5, 0x89, 0x0d, 0xff, 0x73, + 0x48, 0x37, 0x37, 0x58, 0xc5, 0x55, 0x14, 0x42, 0x22, 0x0c, 0x5e, 0xb3, 0xad, 0xda, 0x3d, 0x21, 0x9f, 0x8a, 0x5a, + 0xfd, 0xe6, 0x4a, 0x33, 0xf7, 0xa1, 0xa8, 0xd3, 0x58, 0x63, 0x19, 0xad, 0xa5, 0x61, 0x35, 0x8c, 0xc6, 0x0f, 0xd7, + 0x20, 0x19, 0x92, 0x6a, 0xc8, 0xaf, 0xd9, 0x74, 0x8b, 0x79, 0x91, 0x6e, 0x7e, 0x53, 0x64, 0xdb, 0xe1, 0x59, 0x3f, + 0xf6, 0x42, 0x90, 0x09, 0xd5, 0x6d, 0x8c, 0xd5, 0x8d, 0xf9, 0x66, 0x14, 0xc8, 0x75, 0x57, 0xa4, 0x54, 0xc7, 0x05, + 0xca, 0x92, 0x75, 0xe8, 0xd1, 0xac, 0xe9, 0xee, 0x34, 0xd5, 0xfc, 0x23, 0x88, 0xd6, 0x89, 0x1f, 0xd6, 0x71, 0xd5, + 0xdc, 0xb1, 0x5d, 0xa4, 0x26, 0x48, 0xf9, 0xaa, 0xb8, 0x2f, 0x32, 0x23, 0xa1, 0x09, 0x4d, 0x71, 0x69, 0xcd, 0x91, + 0xfb, 0x42, 0x34, 0x7c, 0x91, 0x19, 0x90, 0x54, 0x14, 0x96, 0xfb, 0xf9, 0x73, 0x5a, 0x0b, 0xd2, 0xfc, 0xd1, 0x69, + 0x9d, 0x7b, 0x22, 0x35, 0x98, 0xaa, 0xb8, 0x8b, 0x48, 0xc5, 0xd4, 0x60, 0x03, 0xcf, 0x88, 0x5e, 0xbe, 0x1c, 0x8f, + 0x1c, 0x9d, 0x25, 0xa9, 0x2c, 0x65, 0x54, 0xba, 0x3c, 0x4c, 0x35, 0xae, 0x37, 0x3a, 0x6d, 0xc5, 0x7e, 0xb8, 0xe0, + 0x9a, 0x69, 0x81, 0xbd, 0x20, 0xc3, 0x01, 0x55, 0x81, 0xb9, 0x5c, 0x45, 0xcd, 0xeb, 0xdc, 0x91, 0x04, 0x12, 0x6c, + 0x8e, 0xd4, 0xae, 0x65, 0x5b, 0xb6, 0x2a, 0x1a, 0xce, 0xfd, 0xc5, 0x68, 0x1b, 0x65, 0x2e, 0xe4, 0x8a, 0x09, 0xa2, + 0x05, 0x78, 0x7e, 0x64, 0x7e, 0x16, 0x40, 0xe2, 0x11, 0x70, 0x01, 0x59, 0x51, 0xae, 0x31, 0x67, 0xf6, 0xb8, 0x6e, + 0xf2, 0x09, 0x93, 0xcf, 0x71, 0xa7, 0x2f, 0x0c, 0x49, 0xf3, 0x23, 0x5c, 0x86, 0x9a, 0xaa, 0x41, 0xea, 0x43, 0x92, + 0xa4, 0xa6, 0x6c, 0xdf, 0x3e, 0x50, 0xa0, 0x0d, 0xa4, 0x25, 0xc7, 0x0e, 0xe6, 0x89, 0xbb, 0x82, 0x18, 0xdd, 0xdb, + 0xdc, 0x60, 0x98, 0x56, 0x65, 0xa8, 0x56, 0x71, 0x5e, 0x9d, 0x18, 0x4a, 0xc7, 0x31, 0x14, 0x1b, 0xd0, 0xad, 0x9a, + 0x1b, 0xdb, 0xfc, 0x66, 0xb8, 0x4f, 0x45, 0x47, 0xf1, 0xcb, 0x53, 0x3a, 0x0f, 0xaa, 0x9c, 0x63, 0xc2, 0xcf, 0x8c, + 0x06, 0x14, 0xd4, 0xa4, 0xe8, 0xd9, 0x3e, 0x15, 0xd3, 0x5f, 0x91, 0x4d, 0xa6, 0x63, 0x62, 0x0e, 0x56, 0xc5, 0xd7, + 0xb7, 0xe8, 0x9a, 0xe6, 0x87, 0x8a, 0xff, 0xf9, 0xb3, 0xe6, 0x83, 0xf9, 0xfd, 0x48, 0x82, 0x0f, 0x3c, 0xeb, 0x25, + 0x80, 0xf9, 0x85, 0x62, 0x09, 0x81, 0x05, 0xbe, 0x31, 0xf0, 0x6f, 0x51, 0xcc, 0x7f, 0x30, 0xc5, 0x9e, 0x15, 0xb8, + 0xe1, 0x02, 0x50, 0x9a, 0x1b, 0x2e, 0x6a, 0x06, 0x04, 0xd4, 0xbb, 0xae, 0x52, 0x5a, 0x74, 0x55, 0x28, 0xf7, 0xd3, + 0xef, 0x1f, 0xae, 0x68, 0xe2, 0x21, 0x48, 0x72, 0xed, 0xce, 0xd0, 0x15, 0xac, 0xd0, 0x3d, 0xbc, 0x1c, 0x7d, 0x73, + 0xb6, 0x22, 0x99, 0x4b, 0x05, 0x97, 0xc0, 0xe2, 0x01, 0x39, 0xa0, 0x78, 0x3c, 0x69, 0x28, 0x65, 0xf0, 0x66, 0xe4, + 0xce, 0xf7, 0x18, 0x9f, 0x66, 0x28, 0xec, 0x9e, 0x32, 0xd1, 0x46, 0x69, 0xe4, 0x18, 0xd4, 0x44, 0xd6, 0x73, 0x31, + 0xec, 0xe0, 0x28, 0x8c, 0xd4, 0xf1, 0x37, 0xc2, 0x9b, 0xa8, 0x6d, 0x11, 0x20, 0xfb, 0xdf, 0x75, 0x42, 0x82, 0x7f, + 0x8d, 0xbe, 0x81, 0x8b, 0xfb, 0x9b, 0x1b, 0x55, 0x1f, 0x66, 0x16, 0xf2, 0x31, 0xdf, 0x34, 0x64, 0xc1, 0x43, 0x1e, + 0x95, 0x31, 0x9b, 0x5d, 0x89, 0xd9, 0x84, 0xdf, 0xfb, 0x59, 0xd7, 0xf1, 0x19, 0x5e, 0x68, 0x63, 0xe0, 0x2e, 0xb6, + 0x25, 0x9e, 0xd3, 0x19, 0x22, 0x83, 0x3a, 0x0d, 0x5c, 0xef, 0x13, 0xe7, 0x50, 0xe5, 0x87, 0x43, 0x78, 0x51, 0x41, + 0xd9, 0x35, 0xee, 0x65, 0xdc, 0xca, 0x5b, 0xfc, 0x32, 0x7e, 0xea, 0x7e, 0xe9, 0x67, 0x82, 0x19, 0xc6, 0x87, 0x1c, + 0xb4, 0x39, 0x38, 0xbe, 0x82, 0xfd, 0x01, 0x06, 0xd5, 0x39, 0xfd, 0x4b, 0xef, 0xce, 0xb1, 0x97, 0x1d, 0xc7, 0x02, + 0x36, 0x67, 0xd9, 0xb5, 0xfa, 0x81, 0xd9, 0xb5, 0xfa, 0xf0, 0xf7, 0x11, 0x58, 0x2f, 0xb3, 0x63, 0x1d, 0x7f, 0x74, + 0x3a, 0x81, 0x79, 0x6a, 0xf5, 0xe1, 0xef, 0x92, 0xb6, 0xfa, 0x05, 0x99, 0x1e, 0x60, 0x78, 0xbe, 0x29, 0x61, 0x01, + 0xe9, 0xb7, 0xd0, 0x22, 0x18, 0xa5, 0xeb, 0xad, 0x41, 0x13, 0x01, 0x28, 0x43, 0x35, 0x78, 0x94, 0xc0, 0x70, 0xa8, + 0x41, 0x5a, 0x6e, 0x0c, 0x28, 0xcf, 0x0d, 0x32, 0xc2, 0x22, 0xc5, 0x7c, 0xfb, 0x31, 0x62, 0x6d, 0x9a, 0x03, 0x70, + 0xf3, 0x4c, 0x45, 0x54, 0x75, 0xf1, 0xb7, 0x18, 0x03, 0xeb, 0xf0, 0x90, 0xe1, 0x12, 0x56, 0x2a, 0xb2, 0xe5, 0xe5, + 0xfb, 0x07, 0x8e, 0x7e, 0xa3, 0x44, 0x64, 0x6b, 0xf9, 0xaa, 0x7d, 0x33, 0x75, 0x86, 0xe8, 0xfd, 0xf7, 0xf6, 0x83, + 0x49, 0x4a, 0x69, 0x3f, 0x3c, 0xba, 0xe7, 0xcc, 0x4f, 0xc4, 0xf0, 0x24, 0x14, 0xed, 0x34, 0x47, 0x2e, 0xd7, 0x21, + 0xad, 0xc5, 0x05, 0x50, 0xc9, 0x77, 0x6e, 0x20, 0x99, 0x5e, 0x48, 0x2d, 0x9f, 0x08, 0xcc, 0xff, 0xfc, 0x79, 0x31, + 0x38, 0xb3, 0x32, 0xee, 0x33, 0xa7, 0x07, 0xd7, 0x6e, 0x8f, 0x74, 0x77, 0x5a, 0x01, 0xed, 0x0f, 0x0f, 0x5b, 0xc4, + 0x93, 0xe4, 0x9a, 0x7e, 0xae, 0x63, 0x6c, 0x35, 0x45, 0xaa, 0x69, 0x18, 0x21, 0xb0, 0x6e, 0x85, 0xd5, 0x51, 0xf5, + 0x61, 0xc8, 0x15, 0x66, 0xe1, 0x8e, 0x90, 0xb8, 0x8c, 0x17, 0x53, 0x01, 0x34, 0x3b, 0xe6, 0xb1, 0xc7, 0xa5, 0xf1, + 0x7f, 0x3d, 0x09, 0x74, 0x2f, 0x02, 0x0d, 0x5f, 0xe5, 0xb4, 0x96, 0xdc, 0x4d, 0xc4, 0xbd, 0x4a, 0x2f, 0x54, 0x92, + 0x9e, 0xab, 0x50, 0x04, 0xf9, 0x8e, 0x30, 0xc5, 0x99, 0x30, 0x6f, 0x12, 0xb7, 0x45, 0x51, 0x60, 0xf8, 0x10, 0x13, + 0x5a, 0xe3, 0xae, 0x4e, 0xfa, 0xf3, 0xe7, 0xad, 0x97, 0x10, 0x55, 0x27, 0xcb, 0x99, 0x1e, 0x55, 0x19, 0xbf, 0xa9, + 0x32, 0x8a, 0x11, 0xfd, 0x22, 0xd6, 0xe0, 0x56, 0x59, 0x74, 0xef, 0xe1, 0xcf, 0x29, 0x71, 0x33, 0x8b, 0xe9, 0x41, + 0x34, 0xe9, 0x72, 0x37, 0x1c, 0xd2, 0x05, 0x7b, 0x2c, 0x16, 0x7f, 0x8b, 0x05, 0x9b, 0x7b, 0xb6, 0xfd, 0xb8, 0x66, + 0x7e, 0xc8, 0xd0, 0xc7, 0x67, 0xbb, 0x08, 0x9e, 0xf2, 0x2e, 0x73, 0x69, 0x84, 0x0d, 0xf9, 0xca, 0x8d, 0x32, 0x97, + 0xe7, 0x15, 0x01, 0xba, 0x7c, 0xd8, 0xa8, 0x30, 0x94, 0x7c, 0x95, 0xc7, 0xef, 0xae, 0xbe, 0x53, 0xd8, 0xfe, 0xa7, + 0xfa, 0x2d, 0x64, 0x64, 0x68, 0x14, 0xfc, 0x11, 0x8d, 0x82, 0xaf, 0xb0, 0xb4, 0x12, 0x10, 0x4b, 0x3e, 0x3f, 0xa2, + 0x10, 0x54, 0x15, 0x12, 0x7a, 0x54, 0xeb, 0xb7, 0x5a, 0x07, 0x99, 0x1f, 0xbb, 0x49, 0x76, 0x04, 0x4d, 0x4d, 0x40, + 0x72, 0x6a, 0x9b, 0x07, 0x33, 0x55, 0x1c, 0x72, 0xa1, 0x5a, 0x16, 0x72, 0xcd, 0xe1, 0xdc, 0x0f, 0x84, 0xe2, 0x90, + 0x7f, 0xc0, 0xf5, 0x3c, 0x12, 0x67, 0x23, 0xd5, 0x8d, 0x21, 0x1b, 0x02, 0xc6, 0x37, 0x3e, 0x8a, 0xbc, 0x8c, 0x64, + 0x66, 0x9a, 0x25, 0xc4, 0x5d, 0xa9, 0x22, 0xd6, 0x67, 0xbd, 0xbf, 0x74, 0x3d, 0x5d, 0xf9, 0x99, 0x08, 0x96, 0x47, + 0x27, 0x08, 0x2a, 0x3c, 0x18, 0xe2, 0x78, 0x92, 0x33, 0x10, 0x5e, 0x46, 0x8b, 0xca, 0x8e, 0x2a, 0x28, 0x97, 0x73, + 0x0c, 0xc5, 0xca, 0x22, 0xe0, 0xcf, 0xd0, 0x23, 0xe7, 0x96, 0x79, 0x5d, 0x8b, 0x98, 0x7e, 0xea, 0xf8, 0x8c, 0xb1, + 0xb7, 0x0a, 0x06, 0x0a, 0x50, 0x7b, 0x36, 0x04, 0x9b, 0x6d, 0xf3, 0xc7, 0x3e, 0x62, 0x95, 0xe1, 0x6a, 0xa2, 0x3d, + 0x63, 0xdc, 0x6f, 0x3a, 0x96, 0x2b, 0x20, 0x84, 0x4a, 0x2a, 0xde, 0xa5, 0x33, 0x16, 0x0e, 0x40, 0x38, 0x2a, 0xa4, + 0x95, 0x3e, 0x7f, 0x7e, 0x3d, 0xf9, 0xcf, 0xbf, 0x21, 0x38, 0xf9, 0xd2, 0xe1, 0x5e, 0xd0, 0xd7, 0x72, 0x2d, 0x46, + 0x7d, 0x1a, 0x13, 0x54, 0xef, 0x93, 0x19, 0x0f, 0x0b, 0xc2, 0xb7, 0x56, 0x3e, 0xb9, 0xe1, 0xa1, 0x9e, 0x20, 0x01, + 0x81, 0xce, 0x7d, 0xb5, 0x27, 0xb0, 0xbc, 0x13, 0x1e, 0x22, 0x40, 0xf9, 0x75, 0xf3, 0x7d, 0x1f, 0xb2, 0xf4, 0xd6, + 0xf2, 0x02, 0x48, 0x03, 0xc4, 0x3d, 0x34, 0x3e, 0x73, 0x99, 0xf0, 0x15, 0xc8, 0x8f, 0x74, 0x70, 0x04, 0xd3, 0x5c, + 0x46, 0x2b, 0x62, 0xf9, 0xd1, 0xd1, 0x3d, 0x99, 0x9a, 0x6e, 0xec, 0x53, 0xf9, 0x32, 0xca, 0xdd, 0x14, 0x4a, 0xf9, + 0x09, 0x05, 0x2d, 0xa5, 0xaf, 0xf3, 0x02, 0x94, 0x51, 0x01, 0x28, 0xf8, 0xe9, 0x8e, 0xcb, 0x01, 0xfc, 0x2c, 0x1e, + 0x31, 0xbe, 0x8c, 0xe5, 0xcf, 0x69, 0x1c, 0x3e, 0x1e, 0x72, 0xaf, 0x78, 0x30, 0xa3, 0xf9, 0x5c, 0x0e, 0xba, 0x67, + 0x95, 0xbf, 0x2f, 0xa0, 0x52, 0xec, 0xd9, 0x28, 0xa6, 0x5f, 0xaa, 0x7f, 0x42, 0xfc, 0x84, 0x6c, 0xb9, 0x2c, 0x3e, + 0x23, 0x9c, 0xe7, 0x5a, 0xf0, 0x3e, 0x01, 0x92, 0xa7, 0xb4, 0x12, 0x43, 0x14, 0xd5, 0xc8, 0xd0, 0x2d, 0xa4, 0xc9, + 0x93, 0xd1, 0x88, 0xe2, 0xb1, 0x2a, 0x3a, 0x03, 0x28, 0x35, 0x44, 0xcf, 0x87, 0xc9, 0x66, 0xd0, 0xd0, 0xa4, 0x1e, + 0x5c, 0xd8, 0xa8, 0x3a, 0x9d, 0xfa, 0x18, 0x8f, 0x5c, 0xbe, 0xbf, 0x4a, 0x3b, 0x10, 0x76, 0x16, 0x5b, 0x58, 0x40, + 0xe0, 0xbc, 0x9f, 0x0a, 0x1e, 0x57, 0xbe, 0xa5, 0x28, 0xdb, 0x0c, 0xdc, 0x87, 0x48, 0xd2, 0xac, 0x33, 0x27, 0xfb, + 0x4b, 0x2c, 0xbd, 0xe2, 0xce, 0x6d, 0xb5, 0x93, 0x24, 0x22, 0x90, 0xd7, 0x4f, 0x93, 0x1c, 0x32, 0x7c, 0xdf, 0x61, + 0x92, 0xeb, 0x96, 0x27, 0x83, 0xd8, 0x31, 0x2f, 0x0e, 0x5a, 0xe9, 0x25, 0x9e, 0xfb, 0xfc, 0xec, 0x08, 0xe6, 0x07, + 0x81, 0x01, 0x4a, 0x94, 0x91, 0xaf, 0x43, 0xf4, 0x01, 0x37, 0xa5, 0xd6, 0x01, 0x17, 0x33, 0x4e, 0xd4, 0x21, 0xe7, + 0x28, 0xa2, 0x83, 0x96, 0xaa, 0xd4, 0x89, 0x15, 0xbb, 0x99, 0xca, 0xdb, 0x1f, 0xb1, 0xff, 0xb7, 0x35, 0x86, 0xeb, + 0xcf, 0x87, 0x19, 0xe1, 0x7e, 0xb7, 0x97, 0x59, 0x8b, 0x6b, 0x6e, 0x5b, 0x15, 0x4a, 0xb0, 0xee, 0xa8, 0x50, 0xec, + 0xe3, 0x5d, 0xb5, 0x0a, 0xd2, 0x48, 0x54, 0x8b, 0x5d, 0x4d, 0x7d, 0x8a, 0x3b, 0xbe, 0x56, 0x1b, 0x4b, 0xa1, 0xde, + 0x65, 0x36, 0x82, 0xaa, 0x5c, 0xd8, 0xee, 0xc6, 0x31, 0xad, 0xac, 0x0f, 0xcf, 0x8e, 0x28, 0xdf, 0x39, 0xa6, 0x3b, + 0x6c, 0x7c, 0x06, 0xd6, 0x85, 0x74, 0xd1, 0xdd, 0x38, 0x66, 0x4b, 0x4a, 0x7f, 0xd1, 0x37, 0x47, 0xcb, 0x6c, 0x15, + 0x8c, 0xff, 0x0f, 0x00, 0xa3, 0x9b, 0x76, 0x11, 0x5a, 0x03, 0x00}; } // namespace web_server } // namespace esphome From 2eebee1de7d4f8b38ee84e15ff29500f0ca5eb57 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 20 May 2024 01:49:00 -1000 Subject: [PATCH 1487/2101] Revert "Fix MQTT dashboard discovery (Exception in MqttStatusThread)." (#6782) --- esphome/dashboard/status/mqtt.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/dashboard/status/mqtt.py b/esphome/dashboard/status/mqtt.py index 0e53c21679..8c35dd2535 100644 --- a/esphome/dashboard/status/mqtt.py +++ b/esphome/dashboard/status/mqtt.py @@ -18,7 +18,7 @@ class MqttStatusThread(threading.Thread): """Run the status thread.""" dashboard = DASHBOARD entries = dashboard.entries - current_entries = entries.async_all() + current_entries = entries.all() config = mqtt.config_from_env() topic = "esphome/discover/#" @@ -33,7 +33,7 @@ class MqttStatusThread(threading.Thread): return for entry in current_entries: if entry.name == data["name"]: - entries.async_set_state(entry, EntryState.ONLINE) + entries.set_state(entry, EntryState.ONLINE) return def on_connect(client, userdata, flags, return_code): @@ -53,11 +53,11 @@ class MqttStatusThread(threading.Thread): client.loop_start() while not dashboard.stop_event.wait(2): - current_entries = entries.async_all() + current_entries = entries.all() # will be set to true on on_message for entry in current_entries: if entry.no_mdns: - entries.async_set_state(entry, EntryState.OFFLINE) + entries.set_state(entry, EntryState.OFFLINE) client.publish("esphome/discover", None, retain=False) dashboard.mqtt_ping_request.wait() From efde677ca905548986d4ed02d7154bc7b17e3249 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 20 May 2024 01:52:24 -1000 Subject: [PATCH 1488/2101] Fix DashboardEntries.all() call (#6783) --- esphome/dashboard/entries.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/dashboard/entries.py b/esphome/dashboard/entries.py index cd318ba8a7..7a9bff4ec1 100644 --- a/esphome/dashboard/entries.py +++ b/esphome/dashboard/entries.py @@ -103,7 +103,7 @@ class DashboardEntries: def all(self) -> list[DashboardEntry]: """Return all entries.""" - return asyncio.run_coroutine_threadsafe(self._async_all, self._loop).result() + return asyncio.run_coroutine_threadsafe(self._async_all(), self._loop).result() def async_all(self) -> list[DashboardEntry]: """Return all entries.""" From cd0f55794053cb19d2f966e2489cd67ec6d45786 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 21 May 2024 10:53:16 +1200 Subject: [PATCH 1489/2101] [remote_receiver] Add better error message for tolerance breaking change (#6784) --- esphome/components/remote_receiver/__init__.py | 8 +++++++- tests/components/remote_receiver/esp32-common.yaml | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/esphome/components/remote_receiver/__init__.py b/esphome/components/remote_receiver/__init__.py index 6fe20153f4..e5085bb33c 100644 --- a/esphome/components/remote_receiver/__init__.py +++ b/esphome/components/remote_receiver/__init__.py @@ -63,7 +63,13 @@ def validate_tolerance(value): if "%" in str(value): type_ = TYPE_PERCENTAGE else: - type_ = TYPE_TIME + try: + cv.positive_time_period_microseconds(value) + type_ = TYPE_TIME + except cv.Invalid as exc: + raise cv.Invalid( + "Tolerance must be a percentage or time. Configurations made before 2024.5.0 treated the value as a percentage." + ) from exc return TOLERANCE_SCHEMA( { diff --git a/tests/components/remote_receiver/esp32-common.yaml b/tests/components/remote_receiver/esp32-common.yaml index 0e71143fc3..ad76bf51f0 100644 --- a/tests/components/remote_receiver/esp32-common.yaml +++ b/tests/components/remote_receiver/esp32-common.yaml @@ -3,6 +3,7 @@ remote_receiver: pin: ${pin} rmt_channel: ${rmt_channel} dump: all + tolerance: 25% on_abbwelcome: then: - logger.log: From 5eb8efd8b3e3d6d626a869126cced35606082262 Mon Sep 17 00:00:00 2001 From: esphomebot Date: Tue, 21 May 2024 10:55:56 +1200 Subject: [PATCH 1490/2101] Update webserver local assets to 20240519-215627 (#6779) --- .../components/web_server/server_index_v3.h | 7970 ++++++++--------- 1 file changed, 3977 insertions(+), 3993 deletions(-) diff --git a/esphome/components/web_server/server_index_v3.h b/esphome/components/web_server/server_index_v3.h index 66cd9de47a..f2f278b08f 100644 --- a/esphome/components/web_server/server_index_v3.h +++ b/esphome/components/web_server/server_index_v3.h @@ -10,4004 +10,3988 @@ namespace esphome { namespace web_server { const uint8_t INDEX_GZ[] PROGMEM = { - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xcc, 0xbd, 0x6d, 0x7b, 0xdb, 0xb6, 0xb2, 0x28, 0xfa, - 0xf9, 0x9e, 0x5f, 0x61, 0x73, 0xa7, 0x2e, 0x61, 0x41, 0xb4, 0x24, 0x5b, 0x8e, 0x43, 0x19, 0xd6, 0x71, 0x9c, 0xa4, - 0x49, 0x9b, 0x26, 0x69, 0x9c, 0x26, 0x4d, 0x54, 0x6d, 0x07, 0x22, 0x21, 0x09, 0x0d, 0x45, 0xa8, 0x04, 0x14, 0xdb, - 0x95, 0xf4, 0xdf, 0xef, 0x33, 0x78, 0x21, 0x41, 0x49, 0xc9, 0x5a, 0xeb, 0xdc, 0x73, 0xee, 0x73, 0x76, 0xf7, 0x8a, - 0x45, 0xbc, 0x63, 0x30, 0x18, 0xcc, 0x0c, 0x66, 0x06, 0xe7, 0xfb, 0xa9, 0x48, 0xd4, 0xfd, 0x9c, 0xed, 0x4d, 0xd5, - 0x2c, 0xbb, 0x38, 0xb7, 0xff, 0x32, 0x9a, 0x5e, 0x9c, 0x67, 0x3c, 0xff, 0xb2, 0x57, 0xb0, 0x8c, 0xf0, 0x44, 0xe4, - 0x7b, 0xd3, 0x82, 0x8d, 0x49, 0x4a, 0x15, 0x8d, 0xf9, 0x8c, 0x4e, 0xd8, 0xde, 0xd1, 0xc5, 0xf9, 0x8c, 0x29, 0xba, - 0x97, 0x4c, 0x69, 0x21, 0x99, 0x22, 0xbf, 0xbf, 0x7b, 0xd6, 0x3c, 0xbb, 0x38, 0x97, 0x49, 0xc1, 0xe7, 0x6a, 0x0f, - 0x9a, 0x24, 0x33, 0x91, 0x2e, 0x32, 0x76, 0x71, 0x74, 0x74, 0x7b, 0x7b, 0x1b, 0xfd, 0x25, 0xff, 0xc7, 0x57, 0x5a, - 0xec, 0xfd, 0x52, 0x90, 0xd7, 0xa3, 0xbf, 0x58, 0xa2, 0xa2, 0x94, 0x8d, 0x79, 0xce, 0xde, 0x14, 0x62, 0xce, 0x0a, - 0x75, 0xdf, 0x83, 0xcc, 0x9f, 0x0a, 0x12, 0x72, 0xac, 0x30, 0x43, 0xe4, 0x42, 0xed, 0xf1, 0x7c, 0x8f, 0xf7, 0x7f, - 0x29, 0x74, 0xca, 0x92, 0xe5, 0x8b, 0x19, 0x2b, 0xe8, 0x28, 0x63, 0xf1, 0x7e, 0x0b, 0x27, 0x22, 0x1f, 0xf3, 0xc9, - 0xa2, 0xfc, 0xbe, 0x2d, 0xb8, 0x72, 0xbf, 0xbf, 0xd2, 0x6c, 0xc1, 0x62, 0xb6, 0x46, 0x31, 0x1f, 0xa8, 0x21, 0x61, - 0xba, 0xe5, 0x2f, 0x55, 0xc3, 0xe1, 0x4f, 0xba, 0xc9, 0xfb, 0x39, 0x13, 0xe3, 0x3d, 0xb5, 0x4f, 0x02, 0x79, 0x3f, - 0x1b, 0x89, 0x2c, 0xe8, 0xab, 0x46, 0x10, 0xc4, 0x50, 0x06, 0x33, 0xd4, 0x4b, 0x44, 0x2e, 0xd5, 0x9e, 0xe4, 0xe4, - 0x96, 0xe7, 0xa9, 0xb8, 0xc5, 0x5f, 0x25, 0x91, 0x3c, 0xba, 0x9e, 0xd2, 0x54, 0xdc, 0xbe, 0x15, 0x42, 0x1d, 0x1c, - 0x84, 0xf6, 0xfb, 0xfe, 0xea, 0xfa, 0x9a, 0x10, 0xf2, 0x55, 0xf0, 0x74, 0xaf, 0xb5, 0x5a, 0x79, 0xa9, 0x51, 0x4e, - 0x15, 0xff, 0xca, 0x4c, 0x25, 0x74, 0x70, 0x10, 0xd0, 0x54, 0xcc, 0x15, 0x4b, 0xaf, 0xd5, 0x7d, 0xc6, 0xae, 0xa7, - 0x8c, 0x29, 0x19, 0xf0, 0x7c, 0xef, 0x89, 0x48, 0x16, 0x33, 0x96, 0xab, 0x68, 0x5e, 0x08, 0x25, 0x60, 0x60, 0x07, - 0x07, 0x41, 0xc1, 0xe6, 0x19, 0x4d, 0x18, 0xe4, 0x5f, 0x5d, 0x5f, 0x57, 0x35, 0xaa, 0x42, 0xf8, 0x56, 0x92, 0x6b, - 0x3d, 0xf4, 0x10, 0xe1, 0xe7, 0x92, 0xe4, 0xec, 0x76, 0xef, 0x03, 0xa3, 0x5f, 0x7e, 0xa5, 0xf3, 0x5e, 0x92, 0x51, - 0x29, 0xf7, 0x9e, 0x89, 0xa5, 0x9e, 0x46, 0xb1, 0x48, 0x94, 0x28, 0x42, 0x85, 0x19, 0x96, 0x68, 0xc9, 0xc7, 0xa1, - 0x9a, 0x72, 0x19, 0xdd, 0x3c, 0x48, 0xa4, 0x7c, 0xcb, 0xe4, 0x22, 0x53, 0x0f, 0xc8, 0x7e, 0x0b, 0xcb, 0x7d, 0x42, - 0x6e, 0x25, 0x52, 0xd3, 0x42, 0xdc, 0xee, 0x3d, 0x2d, 0x0a, 0x51, 0x84, 0xc1, 0xd5, 0xf5, 0xb5, 0x29, 0xb1, 0xc7, - 0xe5, 0x5e, 0x2e, 0xd4, 0x5e, 0xd9, 0x1e, 0x40, 0x3b, 0xda, 0xfb, 0x5d, 0xb2, 0xbd, 0xcf, 0x8b, 0x5c, 0xd2, 0x31, - 0xbb, 0xba, 0xbe, 0xfe, 0xbc, 0x27, 0x8a, 0xbd, 0xcf, 0x89, 0x94, 0x9f, 0xf7, 0x78, 0x2e, 0x15, 0xa3, 0x69, 0x14, - 0xa0, 0x9e, 0xee, 0x2c, 0x91, 0xf2, 0x1d, 0xbb, 0x53, 0x44, 0x61, 0xfd, 0xa9, 0x08, 0x5b, 0x4f, 0x98, 0xda, 0x93, - 0xe5, 0xbc, 0x42, 0xb4, 0xcc, 0x98, 0xda, 0x53, 0x44, 0xe7, 0x0b, 0x0b, 0x7f, 0x66, 0x3e, 0x55, 0x8f, 0x8f, 0xc3, - 0xaf, 0xf2, 0xe0, 0x40, 0x95, 0x80, 0x46, 0x4b, 0xbb, 0x42, 0x84, 0xed, 0xbb, 0xb4, 0x83, 0x03, 0x16, 0x65, 0x2c, - 0x9f, 0xa8, 0x29, 0x21, 0xa4, 0xdd, 0x93, 0x07, 0x07, 0xa1, 0x22, 0xcf, 0x65, 0x34, 0x61, 0x2a, 0x64, 0x08, 0xe1, - 0xaa, 0xf6, 0xc1, 0x41, 0x68, 0x80, 0x20, 0x88, 0xd2, 0x80, 0xab, 0xc1, 0x18, 0x45, 0x16, 0xfa, 0xd7, 0xf7, 0x79, - 0x12, 0xfa, 0xe3, 0x47, 0x58, 0x1e, 0x1c, 0x3c, 0x97, 0x91, 0x84, 0x16, 0xb1, 0x42, 0x68, 0x5d, 0x30, 0xb5, 0x28, - 0xf2, 0x3d, 0xb5, 0x56, 0xe2, 0x5a, 0x15, 0x3c, 0x9f, 0x84, 0x68, 0xe9, 0xd2, 0xbc, 0x8a, 0xeb, 0xb5, 0x19, 0xee, - 0x6f, 0x05, 0xe1, 0xe4, 0x02, 0x7a, 0x7c, 0x26, 0x42, 0x8b, 0x83, 0x9c, 0x90, 0x40, 0xea, 0xba, 0x41, 0x9f, 0xc7, - 0xbc, 0x11, 0x04, 0xd8, 0x8c, 0x12, 0xdf, 0x4a, 0x84, 0xb9, 0x02, 0xd4, 0x8d, 0xa2, 0x48, 0x21, 0x72, 0xb1, 0x74, - 0x60, 0xe1, 0xde, 0x44, 0xfb, 0x7c, 0xd0, 0x1a, 0xc6, 0x2a, 0x2a, 0x58, 0xba, 0x48, 0x58, 0x18, 0x4a, 0x9c, 0x63, - 0x81, 0xc8, 0x85, 0x6c, 0x84, 0x05, 0xb9, 0x80, 0xf5, 0x2e, 0xea, 0x8b, 0x4d, 0xc8, 0x7e, 0x0b, 0xd9, 0x41, 0x16, - 0x6e, 0x84, 0x00, 0x62, 0x3b, 0xa0, 0x82, 0x90, 0x20, 0x5f, 0xcc, 0x46, 0xac, 0x08, 0xca, 0x62, 0xbd, 0x1a, 0x5e, - 0x2c, 0x24, 0xdb, 0x4b, 0xa4, 0xdc, 0x1b, 0x2f, 0xf2, 0x44, 0x71, 0x91, 0xef, 0x05, 0x8d, 0xa2, 0x11, 0x18, 0x7c, - 0x28, 0xd1, 0x21, 0x40, 0x6b, 0x14, 0xe6, 0xa8, 0xc1, 0x07, 0xa2, 0xd1, 0x1e, 0x62, 0x18, 0x25, 0xea, 0xd9, 0xf6, - 0x2c, 0x04, 0x18, 0xe6, 0x30, 0xc9, 0x35, 0xfe, 0x64, 0x76, 0x3e, 0x4c, 0xf1, 0xab, 0xec, 0xf3, 0x68, 0x7b, 0xa7, - 0x10, 0x15, 0xcd, 0xe8, 0x3c, 0x64, 0xe4, 0x82, 0x69, 0xec, 0xa2, 0x79, 0x02, 0x63, 0xad, 0x2d, 0x5c, 0x9f, 0xc5, - 0x2c, 0xaa, 0x70, 0x0a, 0xc5, 0x2a, 0x1a, 0x8b, 0xe2, 0x29, 0x4d, 0xa6, 0x50, 0xaf, 0xc4, 0x98, 0xd4, 0x6d, 0xb8, - 0xa4, 0x60, 0x54, 0xb1, 0xa7, 0x19, 0x83, 0xaf, 0x30, 0xd0, 0x35, 0x03, 0x84, 0x73, 0xd8, 0xea, 0x19, 0x57, 0xaf, - 0x44, 0x9e, 0xb0, 0x5e, 0xee, 0xe1, 0x97, 0x5e, 0xf9, 0x4b, 0xa5, 0x0a, 0x3e, 0x5a, 0x28, 0x16, 0x06, 0x39, 0x94, - 0x08, 0x70, 0x8e, 0xb0, 0x8c, 0x14, 0xbb, 0x53, 0x57, 0x22, 0x57, 0x2c, 0x57, 0x84, 0x39, 0xa8, 0x62, 0x1e, 0xd1, - 0xf9, 0x9c, 0xe5, 0xe9, 0xd5, 0x94, 0x67, 0x69, 0x28, 0xd1, 0x1a, 0xad, 0xf1, 0x07, 0x49, 0x60, 0x92, 0xe4, 0x82, - 0xc7, 0xf0, 0xcf, 0xb7, 0xa7, 0x13, 0x2a, 0x72, 0xa1, 0xb7, 0x05, 0x23, 0x41, 0xd0, 0x1b, 0x8b, 0x22, 0xb4, 0x53, - 0xd8, 0x03, 0xd2, 0x05, 0x7d, 0xbc, 0x5d, 0x64, 0x4c, 0x22, 0xd6, 0x20, 0x25, 0xa6, 0x39, 0x08, 0xff, 0x56, 0x84, - 0x0c, 0x16, 0x80, 0xa3, 0x98, 0x6b, 0x12, 0xf8, 0x92, 0xdb, 0x4d, 0x95, 0x96, 0x44, 0xed, 0x77, 0x49, 0x52, 0x1e, - 0xa9, 0x62, 0x21, 0x15, 0x4b, 0xdf, 0xdd, 0xcf, 0x99, 0xc4, 0x3f, 0x17, 0xe4, 0x77, 0xd9, 0xff, 0x5d, 0x46, 0x6c, - 0x36, 0x57, 0xf7, 0xd7, 0x9a, 0x9a, 0xc7, 0x41, 0x80, 0x3f, 0xea, 0xa2, 0x05, 0xa3, 0x09, 0x90, 0x34, 0x0b, 0xb2, - 0x37, 0x22, 0xbb, 0x1f, 0xf3, 0x2c, 0xbb, 0x5e, 0xcc, 0xe7, 0xa2, 0x50, 0x58, 0x49, 0xb2, 0x54, 0xa2, 0x82, 0x0f, - 0xac, 0xe8, 0x52, 0xde, 0x72, 0x95, 0x4c, 0x43, 0x85, 0x96, 0x09, 0x95, 0x6c, 0xef, 0xb1, 0x10, 0x19, 0xa3, 0x79, - 0xcc, 0x09, 0xef, 0xff, 0x5c, 0xc4, 0xf9, 0x22, 0xcb, 0x7a, 0xa3, 0x82, 0xd1, 0x2f, 0x3d, 0x9d, 0x6d, 0x0e, 0x87, - 0x58, 0xff, 0xbe, 0x2c, 0x0a, 0x7a, 0x0f, 0x05, 0x09, 0x81, 0x62, 0x7d, 0x1e, 0xff, 0x7c, 0xfd, 0xfa, 0x55, 0x64, - 0xf6, 0x0a, 0x1f, 0xdf, 0x87, 0xbc, 0xdc, 0x7f, 0x7c, 0x8d, 0xc7, 0x85, 0x98, 0x6d, 0x74, 0x6d, 0x40, 0xc7, 0x7b, - 0xdf, 0x18, 0x02, 0x23, 0x7c, 0xdf, 0x34, 0xed, 0x8f, 0xe0, 0x95, 0xc6, 0x7c, 0xc8, 0x24, 0xb6, 0x5f, 0xf8, 0x27, - 0x36, 0xc9, 0x21, 0x47, 0xdf, 0x1f, 0xad, 0x2a, 0xee, 0x97, 0x8c, 0xe8, 0x71, 0xce, 0xe1, 0x60, 0x84, 0x31, 0x26, - 0x54, 0x25, 0xd3, 0x25, 0xd3, 0x8d, 0xad, 0xdd, 0x88, 0xd9, 0x7a, 0x8d, 0x5f, 0x09, 0x87, 0xf5, 0x6a, 0x9f, 0x10, - 0xae, 0xe9, 0x15, 0x51, 0xab, 0x15, 0x27, 0x84, 0x23, 0xfc, 0x96, 0x93, 0x25, 0x75, 0x13, 0x82, 0x93, 0x0d, 0xb6, - 0x67, 0x6c, 0xa8, 0x0c, 0x9c, 0x80, 0x5f, 0x59, 0xa1, 0x58, 0x11, 0x2b, 0x89, 0x0b, 0x36, 0xce, 0x60, 0x1c, 0xfb, - 0x6d, 0x3c, 0xa5, 0xf2, 0x6a, 0x4a, 0xf3, 0x09, 0x4b, 0xe3, 0x57, 0x62, 0x8d, 0x99, 0x24, 0xc1, 0x98, 0xe7, 0x34, - 0xe3, 0xff, 0xb0, 0x34, 0xb0, 0xe7, 0xc2, 0x63, 0xb5, 0xc7, 0xee, 0x14, 0xcb, 0x53, 0xb9, 0xf7, 0xfc, 0xdd, 0xaf, - 0x2f, 0xed, 0x62, 0xd6, 0xce, 0x0a, 0xb4, 0x94, 0x8b, 0x39, 0x2b, 0x42, 0x84, 0xed, 0x59, 0xf1, 0x94, 0x6b, 0x3a, - 0xf9, 0x2b, 0x9d, 0x9b, 0x14, 0x2e, 0x7f, 0x9f, 0xa7, 0x54, 0xb1, 0x37, 0x2c, 0x4f, 0x79, 0x3e, 0x21, 0xfb, 0x6d, - 0x93, 0x3e, 0xa5, 0x36, 0x23, 0x2d, 0x93, 0x6e, 0x1e, 0x3c, 0xcd, 0xf4, 0xdc, 0xcb, 0xcf, 0x45, 0x88, 0xd6, 0x52, - 0x51, 0xc5, 0x93, 0x3d, 0x9a, 0xa6, 0x2f, 0x72, 0xae, 0xb8, 0x1e, 0x61, 0x01, 0x4b, 0x04, 0xb8, 0xca, 0xcc, 0xa9, - 0xe1, 0x46, 0x1e, 0x22, 0x1c, 0x86, 0xf6, 0x2c, 0x98, 0x22, 0xbb, 0x66, 0x07, 0x07, 0x15, 0xe5, 0xef, 0xb3, 0xd8, - 0x64, 0x92, 0xc1, 0x10, 0x45, 0xf3, 0x85, 0x84, 0xc5, 0x76, 0x5d, 0xc0, 0x41, 0x23, 0x46, 0x92, 0x15, 0x5f, 0x59, - 0x5a, 0x22, 0x88, 0x0c, 0xd1, 0x72, 0xa3, 0x0f, 0xbb, 0x3d, 0x14, 0x19, 0x0c, 0x7b, 0x3e, 0x09, 0x67, 0x16, 0xd9, - 0x0d, 0xa7, 0xc2, 0x99, 0x2c, 0x89, 0x4a, 0x08, 0x07, 0x6a, 0x49, 0x58, 0x72, 0xe2, 0xe6, 0x37, 0x0f, 0x25, 0xf0, - 0x10, 0x3e, 0xe5, 0x70, 0x67, 0xee, 0xd3, 0xaf, 0xfa, 0xf0, 0xc8, 0xb1, 0x44, 0x58, 0x99, 0x91, 0xe6, 0x08, 0xad, - 0x11, 0x56, 0x6e, 0xb8, 0x86, 0x28, 0x39, 0xbe, 0x08, 0x4e, 0x6d, 0xf2, 0x96, 0xeb, 0x63, 0x1b, 0x68, 0x1b, 0x55, - 0xec, 0xe0, 0x20, 0x64, 0x51, 0x89, 0x18, 0x64, 0xbf, 0x6d, 0x17, 0xc9, 0x83, 0xd6, 0x37, 0xc6, 0x0d, 0x3d, 0x6b, - 0x06, 0x67, 0x9f, 0x45, 0xb9, 0xb8, 0x4c, 0x12, 0x26, 0xa5, 0x28, 0x0e, 0x0e, 0xf6, 0x75, 0xf9, 0x92, 0xb3, 0x80, - 0x45, 0x7c, 0x7d, 0x9b, 0x57, 0x43, 0x40, 0xd5, 0x69, 0xeb, 0xf8, 0x26, 0x52, 0xf1, 0x4d, 0x8e, 0x09, 0x89, 0x83, - 0x9b, 0x9b, 0xa0, 0xa1, 0xb0, 0x85, 0xc3, 0x84, 0xb9, 0xae, 0xef, 0x9f, 0x30, 0xc3, 0x16, 0x6a, 0x26, 0x64, 0x0b, - 0x34, 0x3b, 0xf9, 0xc1, 0xb0, 0x3e, 0x24, 0xac, 0x70, 0x8e, 0xd6, 0xde, 0x8a, 0xee, 0x6c, 0x5a, 0xf3, 0x37, 0x66, - 0xe9, 0x96, 0x13, 0xcd, 0x53, 0x78, 0xeb, 0x38, 0x60, 0xc3, 0x35, 0xd6, 0xb0, 0x77, 0xb3, 0x11, 0x7a, 0xa0, 0x03, - 0x35, 0xec, 0xd9, 0x7c, 0x92, 0x1b, 0xc8, 0x15, 0xec, 0xef, 0x05, 0x93, 0xca, 0x20, 0x72, 0xa8, 0xb0, 0xc0, 0x70, - 0x46, 0x6d, 0x32, 0x9d, 0x35, 0x96, 0x74, 0xd7, 0xd8, 0x5e, 0xcf, 0xe1, 0x6c, 0x94, 0x80, 0xd4, 0xdf, 0xc7, 0x27, - 0x18, 0xab, 0x42, 0xab, 0xd5, 0x5b, 0xee, 0x5a, 0xa9, 0xd6, 0xb2, 0xe4, 0xd7, 0x36, 0x16, 0x85, 0x49, 0x64, 0x0f, - 0xe7, 0xfd, 0xb6, 0x1d, 0xbf, 0x1c, 0x92, 0xfd, 0x56, 0x89, 0xc5, 0x16, 0xac, 0x66, 0x3c, 0x06, 0x8a, 0xaf, 0x4d, - 0x53, 0x48, 0x9f, 0xf5, 0x35, 0x7c, 0x89, 0xa6, 0x5b, 0xb8, 0x3a, 0x25, 0x03, 0xe0, 0x3a, 0xa2, 0xe9, 0xf0, 0x5b, - 0xf8, 0xe4, 0x28, 0x42, 0xa8, 0xb6, 0xf3, 0x2a, 0xc2, 0xf1, 0xb5, 0x4e, 0x38, 0x36, 0xa6, 0x11, 0xcc, 0xcb, 0x2a, - 0x41, 0x89, 0x66, 0x76, 0xab, 0x57, 0x59, 0x58, 0xea, 0xc1, 0x54, 0x53, 0xf2, 0x9a, 0x78, 0x45, 0x67, 0x4c, 0x86, - 0x0c, 0xe1, 0x6f, 0x15, 0x30, 0xf8, 0x09, 0x45, 0x86, 0xde, 0x19, 0x9a, 0xc3, 0x19, 0x0a, 0xec, 0x2e, 0x30, 0x69, - 0xf5, 0x2d, 0x97, 0x63, 0x36, 0xc8, 0x87, 0x15, 0x6f, 0xe7, 0x4d, 0x5e, 0x1f, 0xce, 0x92, 0xd4, 0xf6, 0x9b, 0x49, - 0x33, 0x40, 0xd3, 0x2c, 0x84, 0x44, 0x78, 0xbf, 0xb5, 0xb9, 0x92, 0xae, 0x54, 0x35, 0xc7, 0xc1, 0x10, 0xd6, 0x41, - 0x1f, 0x1b, 0x11, 0x97, 0xfa, 0x6f, 0x6d, 0xab, 0x01, 0xd8, 0xae, 0x01, 0x33, 0xa2, 0x71, 0x46, 0x55, 0xd8, 0x3e, - 0x6a, 0x01, 0x63, 0xfa, 0x95, 0xc1, 0xa9, 0x82, 0xd0, 0xf6, 0x54, 0x58, 0xb4, 0xc8, 0xe5, 0x94, 0x8f, 0x55, 0xf8, - 0x41, 0x6a, 0xa2, 0xc2, 0x32, 0xc9, 0x40, 0xc2, 0xf1, 0xd8, 0x63, 0x4d, 0x70, 0x3e, 0xc0, 0x30, 0x4a, 0x56, 0x8c, - 0xb9, 0x91, 0x6a, 0xc2, 0x05, 0xe4, 0xa1, 0x62, 0xad, 0x2b, 0x32, 0xe3, 0x4a, 0x4b, 0xe0, 0x1e, 0xdb, 0x7d, 0xd3, - 0x62, 0x6c, 0xa9, 0x81, 0xf4, 0x38, 0x58, 0x19, 0xfb, 0x24, 0xc2, 0x26, 0xaa, 0x48, 0x89, 0x97, 0xe2, 0x96, 0x15, - 0x57, 0x14, 0x06, 0x1f, 0x9b, 0xea, 0x6b, 0x73, 0x14, 0x68, 0x8a, 0xaf, 0x7a, 0x0e, 0x5f, 0x6e, 0xf4, 0xc4, 0xdf, - 0x14, 0x62, 0xc6, 0x25, 0x03, 0xbe, 0xcd, 0xc0, 0x3f, 0x87, 0x8d, 0xa6, 0x77, 0x24, 0x1c, 0x37, 0xac, 0xc4, 0xaf, - 0xcb, 0x97, 0x75, 0xfc, 0xba, 0x79, 0xf0, 0x74, 0xe2, 0x28, 0x60, 0x7d, 0x1f, 0x23, 0x1c, 0x5a, 0xf1, 0xc2, 0x3b, - 0xe9, 0xa2, 0x29, 0xb2, 0xc7, 0xfc, 0x6a, 0xa5, 0x3c, 0x31, 0xae, 0xc6, 0x39, 0x32, 0xb3, 0x6d, 0xd0, 0x9a, 0xa6, - 0x29, 0xb0, 0x78, 0x85, 0xc8, 0x32, 0xef, 0xb0, 0xc2, 0xb2, 0x57, 0x1e, 0x4f, 0x37, 0x0f, 0x9e, 0x5e, 0x7f, 0xef, - 0x84, 0x82, 0x7c, 0xff, 0x90, 0x72, 0x03, 0xcd, 0x53, 0x56, 0x80, 0x5c, 0xe9, 0xad, 0x96, 0x3d, 0x67, 0xaf, 0x44, - 0x9e, 0xb3, 0x44, 0xb1, 0x14, 0x84, 0x16, 0x60, 0x83, 0xa7, 0x42, 0xaa, 0x32, 0xb1, 0x1a, 0xbd, 0xf4, 0x85, 0xd0, - 0x28, 0xa1, 0x59, 0x16, 0x1a, 0x01, 0x65, 0x26, 0xbe, 0xb2, 0x1d, 0xa3, 0xee, 0xd5, 0x86, 0x5c, 0x36, 0xc3, 0xbc, - 0x66, 0x58, 0x24, 0xe7, 0x19, 0x4f, 0x58, 0x79, 0x78, 0x5d, 0x47, 0x3c, 0x4f, 0xd9, 0x1d, 0xd0, 0x11, 0x74, 0x71, - 0x71, 0xd1, 0xc2, 0x6d, 0xb4, 0x36, 0x00, 0x5f, 0x6e, 0x01, 0xf6, 0x3b, 0xc7, 0xa6, 0x11, 0xc4, 0x97, 0x3b, 0xc9, - 0x1a, 0xf2, 0xce, 0x4a, 0xee, 0x04, 0x2d, 0x43, 0x9e, 0x11, 0x4e, 0x59, 0xc6, 0x14, 0x73, 0xe4, 0x1c, 0x98, 0x69, - 0xb3, 0x75, 0xdf, 0x96, 0xf0, 0x2b, 0xd1, 0xc9, 0xed, 0x32, 0xb7, 0xe6, 0xb2, 0x14, 0xdd, 0xab, 0xe5, 0xa9, 0xa0, - 0xdd, 0x57, 0x66, 0x79, 0xa8, 0x52, 0x34, 0x99, 0x1a, 0x89, 0x3d, 0xdc, 0x9a, 0x52, 0xd5, 0x86, 0x25, 0xed, 0xe5, - 0x26, 0xfa, 0x54, 0xd8, 0x61, 0xee, 0x02, 0xc1, 0xb5, 0x25, 0x0a, 0x0c, 0x84, 0x40, 0xb3, 0x6c, 0x57, 0x34, 0xcb, - 0x46, 0x34, 0xf9, 0x52, 0xc7, 0xfe, 0x0a, 0x0d, 0xc8, 0x26, 0x35, 0xf6, 0xb2, 0x3c, 0x92, 0xe5, 0xcf, 0xdb, 0x51, - 0xe9, 0xda, 0x46, 0x09, 0xf7, 0x5b, 0x15, 0xda, 0xd7, 0x17, 0xfa, 0x9b, 0xd8, 0xae, 0x47, 0x24, 0xed, 0xcc, 0x42, - 0xa0, 0x02, 0xff, 0x12, 0xe3, 0x1c, 0x3d, 0xb0, 0x78, 0x07, 0x82, 0xc7, 0x7a, 0x63, 0x20, 0x0a, 0x2d, 0xd7, 0x29, - 0x97, 0xdf, 0x86, 0xc0, 0xff, 0x96, 0x51, 0x3e, 0xf1, 0x7a, 0xf8, 0x77, 0x07, 0x5a, 0xd2, 0x38, 0xcb, 0x38, 0x97, - 0x23, 0xb3, 0x0c, 0x85, 0x23, 0x34, 0xbf, 0x00, 0xf3, 0xa2, 0xf1, 0xfd, 0xb5, 0xc9, 0xd2, 0x7c, 0x19, 0x0c, 0x23, - 0xef, 0xf9, 0x0c, 0x45, 0x0d, 0x05, 0x2c, 0x51, 0x35, 0x67, 0xae, 0xa8, 0x89, 0x92, 0x96, 0x6b, 0x37, 0xe2, 0xb8, - 0xa5, 0xb9, 0x05, 0x09, 0xc3, 0x30, 0x27, 0xba, 0x0d, 0xc3, 0xdf, 0x57, 0xb3, 0xc8, 0xb7, 0x66, 0x91, 0x47, 0x9e, - 0xb4, 0x85, 0x2a, 0x64, 0xf6, 0xaa, 0xc7, 0x4a, 0x22, 0xbf, 0x14, 0xb0, 0xac, 0x11, 0x50, 0x68, 0x54, 0x12, 0xdc, - 0x8c, 0x28, 0x5c, 0x58, 0x51, 0xc7, 0xe2, 0x1a, 0x90, 0x8c, 0xaa, 0x8a, 0x40, 0x66, 0x73, 0xd4, 0x64, 0x5f, 0x81, - 0x0b, 0xb4, 0xc1, 0xdf, 0xaf, 0xd7, 0x16, 0x4a, 0x0c, 0xd9, 0xd5, 0xa9, 0x31, 0xc6, 0x1e, 0x58, 0xb0, 0x20, 0xb9, - 0x61, 0x86, 0x0d, 0xeb, 0xb3, 0x09, 0x9c, 0xb2, 0xdd, 0x7d, 0x42, 0x44, 0x05, 0x9b, 0x3c, 0xda, 0xc1, 0x5d, 0x09, - 0x84, 0xa9, 0x63, 0x4b, 0x8b, 0x6a, 0xe2, 0x84, 0x04, 0x4e, 0x3b, 0x11, 0xf4, 0x97, 0x35, 0xe1, 0x30, 0xf6, 0x8a, - 0xad, 0x63, 0x20, 0xaa, 0xc5, 0x2e, 0x78, 0xef, 0xc2, 0x9a, 0x5a, 0x3b, 0x1e, 0xc4, 0x8b, 0x1a, 0xc4, 0x3d, 0xd0, - 0x0a, 0x43, 0xbc, 0xc4, 0x90, 0xd0, 0x7a, 0xe5, 0x90, 0xe1, 0xc2, 0x2c, 0xc4, 0x16, 0x14, 0x37, 0xd9, 0x4f, 0x8d, - 0x85, 0x20, 0xcb, 0xe6, 0xc0, 0xdf, 0xf9, 0x47, 0x44, 0x08, 0x83, 0x97, 0xab, 0xd5, 0x16, 0xda, 0xed, 0xe4, 0x42, - 0x51, 0x54, 0x49, 0x87, 0xab, 0xd5, 0x2b, 0x81, 0x42, 0xcb, 0xff, 0x62, 0x86, 0xfa, 0x8e, 0xe8, 0x5e, 0xbe, 0x84, - 0x52, 0x9a, 0x1d, 0xad, 0x52, 0x4a, 0xc1, 0xa1, 0x8e, 0xb5, 0xf5, 0x85, 0x52, 0x1e, 0xe5, 0xbe, 0xda, 0x22, 0x60, - 0x3a, 0xd1, 0x9e, 0xd4, 0xd5, 0x94, 0xaf, 0x6c, 0xd3, 0x12, 0x21, 0x14, 0xe7, 0x5a, 0x96, 0xd9, 0xdf, 0x25, 0x5f, - 0x1e, 0x1c, 0xe4, 0x5e, 0x43, 0x37, 0x25, 0xa5, 0xf8, 0x2b, 0x84, 0x53, 0x59, 0xde, 0xe7, 0x9a, 0x7d, 0xf9, 0xcb, - 0x9d, 0x43, 0x5b, 0xd2, 0x69, 0xab, 0x07, 0x82, 0x39, 0xbd, 0xa5, 0x5c, 0xed, 0x95, 0xad, 0x18, 0xc1, 0x3c, 0x64, - 0x68, 0x69, 0xb9, 0x8d, 0xa8, 0x60, 0xc0, 0x3f, 0x02, 0x59, 0x70, 0x5c, 0xb4, 0x41, 0xfc, 0x64, 0xca, 0x40, 0x95, - 0xed, 0x18, 0x89, 0x52, 0x3c, 0xdc, 0xb7, 0x07, 0x89, 0x6d, 0x78, 0xf7, 0xd8, 0xd7, 0x9b, 0xd5, 0x6b, 0xd2, 0xc0, - 0x9c, 0x15, 0x63, 0x51, 0xcc, 0x5c, 0xde, 0x7a, 0xe3, 0xdb, 0x12, 0x47, 0x3e, 0x0e, 0x77, 0xb6, 0x6d, 0x45, 0x80, - 0xde, 0x86, 0xec, 0x5d, 0x49, 0xed, 0xb5, 0xd3, 0xb4, 0x3c, 0x80, 0x8d, 0x82, 0xd0, 0x61, 0x66, 0xee, 0x4b, 0xf9, - 0x56, 0xbd, 0xda, 0x33, 0xba, 0x93, 0xfd, 0x76, 0xaf, 0x94, 0xfc, 0x1c, 0x36, 0xf4, 0x8c, 0x8e, 0xc3, 0x9e, 0xaa, - 0x62, 0x91, 0xa5, 0x76, 0xb0, 0x70, 0xc4, 0x59, 0x3c, 0xba, 0xe5, 0x59, 0x56, 0xa5, 0xfe, 0x27, 0xa4, 0x3d, 0xb7, - 0xa4, 0x5d, 0x38, 0xd2, 0x0e, 0xa4, 0x02, 0x48, 0xbb, 0x69, 0xae, 0xaa, 0x2e, 0xb6, 0xb6, 0xa7, 0x30, 0x44, 0x3d, - 0xd7, 0xe2, 0x34, 0xf4, 0xb7, 0x70, 0x23, 0x40, 0x25, 0xf3, 0xf5, 0x25, 0xb4, 0xfa, 0x18, 0x10, 0x03, 0x8d, 0x4e, - 0x93, 0xf9, 0x9a, 0x8a, 0x2f, 0x21, 0xc2, 0xf9, 0x9a, 0x95, 0x98, 0x7d, 0xf9, 0x14, 0x94, 0x76, 0xde, 0x74, 0xe0, - 0x1c, 0xd3, 0xc9, 0xff, 0x11, 0x1f, 0xe5, 0x66, 0x27, 0xed, 0xec, 0x72, 0x37, 0x3b, 0xa0, 0xf5, 0xd5, 0xec, 0xd2, - 0xef, 0x53, 0x7b, 0x3d, 0x3d, 0x59, 0x4e, 0xaf, 0x5a, 0xef, 0xd5, 0x2a, 0xdc, 0x48, 0x01, 0x8d, 0xbe, 0x95, 0x52, - 0x8a, 0xb2, 0x75, 0xa0, 0x01, 0x3e, 0x64, 0x20, 0x61, 0x6d, 0x26, 0x5d, 0x9e, 0x72, 0x2f, 0xff, 0x95, 0x9e, 0x47, - 0x2b, 0xee, 0x4d, 0xfd, 0x2b, 0x31, 0x9b, 0x03, 0x43, 0xb6, 0x81, 0xd2, 0x13, 0x66, 0x3b, 0xac, 0xf2, 0xd7, 0x3b, - 0xd2, 0x6a, 0x75, 0xf4, 0x7e, 0xac, 0x61, 0x53, 0x29, 0x35, 0xef, 0xb7, 0xd6, 0x8b, 0x32, 0xa9, 0x24, 0x1c, 0xbb, - 0x74, 0x2b, 0x57, 0x9b, 0x9a, 0x19, 0x97, 0xf1, 0x3a, 0x94, 0x86, 0x0e, 0x4b, 0xa0, 0x75, 0x1e, 0xf9, 0x71, 0xe8, - 0xee, 0xaf, 0xff, 0xba, 0x02, 0xce, 0x72, 0xbd, 0x01, 0xbe, 0xe5, 0x7a, 0xfd, 0x58, 0x59, 0x49, 0x1b, 0x3f, 0xde, - 0x21, 0xf7, 0x96, 0xd0, 0xab, 0x32, 0xad, 0xcc, 0x38, 0x18, 0x42, 0xda, 0x16, 0x0b, 0x49, 0x96, 0x33, 0x91, 0xb2, - 0x38, 0x10, 0x73, 0x96, 0x07, 0x6b, 0xd0, 0xb3, 0x5a, 0x04, 0xf8, 0x28, 0xc3, 0xe5, 0xdb, 0xba, 0xbe, 0x35, 0x7e, - 0xac, 0xd6, 0xa0, 0x0a, 0x7b, 0xc9, 0x77, 0x28, 0x63, 0xdf, 0xb3, 0x42, 0x6a, 0x9e, 0xb4, 0x64, 0x6f, 0x5f, 0xf2, - 0xea, 0x80, 0x7a, 0xc9, 0xe3, 0x6f, 0x57, 0xa9, 0x04, 0x92, 0xa0, 0x1d, 0x9d, 0x46, 0xc7, 0x01, 0xd2, 0x1a, 0xe3, - 0x67, 0x4e, 0x63, 0xbc, 0x28, 0x35, 0xc6, 0xcf, 0x15, 0x59, 0x6c, 0x68, 0x8c, 0xff, 0x96, 0xe4, 0xb9, 0xea, 0x3f, - 0x77, 0xda, 0xf4, 0x37, 0x22, 0xe3, 0xc9, 0x7d, 0x18, 0x64, 0x5c, 0x35, 0xe1, 0x36, 0x31, 0xc0, 0x4b, 0x93, 0x01, - 0xaa, 0x46, 0xad, 0xef, 0x5e, 0x3b, 0xf9, 0x0f, 0x73, 0x49, 0x82, 0x07, 0x19, 0x57, 0x0f, 0x02, 0x3c, 0x55, 0xe4, - 0x33, 0xfc, 0x7a, 0xb0, 0x0c, 0x7f, 0xa5, 0x6a, 0x1a, 0x15, 0x34, 0x4f, 0xc5, 0x2c, 0x44, 0x8d, 0x20, 0x40, 0x91, - 0xd4, 0x42, 0xc8, 0x23, 0xb4, 0x7e, 0xf0, 0x19, 0xff, 0x23, 0x48, 0xd0, 0x0f, 0x1a, 0x53, 0x85, 0x15, 0x25, 0x9f, - 0xcf, 0x1f, 0x2c, 0xff, 0x11, 0xeb, 0x8b, 0xcf, 0xf8, 0xa9, 0x2a, 0xd5, 0xfa, 0xf8, 0x8e, 0x91, 0x10, 0x91, 0x8b, - 0xa7, 0x6e, 0x48, 0x57, 0x62, 0x66, 0x14, 0xfc, 0x01, 0xc2, 0x5f, 0x41, 0xaf, 0x7b, 0xc1, 0x2b, 0x22, 0x64, 0xef, - 0x60, 0xf6, 0x49, 0x20, 0xb4, 0xf2, 0x20, 0x38, 0x38, 0xf0, 0xd2, 0x4a, 0x16, 0x02, 0xff, 0x25, 0x48, 0x4d, 0x54, - 0xc7, 0x8c, 0x42, 0x4b, 0x7f, 0x89, 0x90, 0x23, 0xd7, 0x4c, 0xe8, 0x34, 0xd5, 0x76, 0xc7, 0xf2, 0x81, 0xd1, 0x3d, - 0x44, 0x5c, 0xb1, 0x82, 0x2a, 0x51, 0x0c, 0x91, 0xcf, 0x96, 0xe0, 0x57, 0x9c, 0x7c, 0x1e, 0xec, 0xfd, 0x3f, 0xff, - 0xe3, 0xcf, 0xf1, 0x9f, 0xc5, 0xf0, 0x33, 0x96, 0x8c, 0x1c, 0x9d, 0x87, 0xfd, 0x38, 0xdc, 0x6f, 0x36, 0x57, 0x7f, - 0x1e, 0x0d, 0xfe, 0x9b, 0x36, 0xff, 0xb9, 0x6c, 0x7e, 0x1a, 0xa2, 0x55, 0xf8, 0xe7, 0x51, 0x7f, 0x60, 0xbf, 0x06, - 0xff, 0x7d, 0xf1, 0xa7, 0x1c, 0x1e, 0x9a, 0xc4, 0x07, 0x08, 0x1d, 0x4d, 0xf0, 0x1f, 0x92, 0x1c, 0x35, 0x9b, 0x17, - 0x47, 0x13, 0xfc, 0x8b, 0x24, 0x47, 0xf0, 0xf7, 0x5e, 0x91, 0xb7, 0x6c, 0xf2, 0xf4, 0x6e, 0x1e, 0x7e, 0xbe, 0x58, - 0x3d, 0x58, 0xbe, 0xe2, 0x6b, 0x68, 0x77, 0xf0, 0xdf, 0x7f, 0xfe, 0x29, 0x83, 0x1f, 0x2f, 0xc8, 0xd1, 0xb0, 0x81, - 0x42, 0x9d, 0x7c, 0x48, 0xcc, 0x9f, 0xb0, 0x1f, 0x0f, 0xfe, 0xdb, 0x0e, 0x25, 0xf8, 0xf1, 0xcf, 0xcf, 0xe7, 0x17, - 0x64, 0xb8, 0x0a, 0x83, 0xd5, 0x8f, 0x68, 0x85, 0xd0, 0xea, 0x01, 0xfa, 0x8c, 0x83, 0x49, 0x80, 0xf0, 0x4f, 0x92, - 0x1c, 0xfd, 0x78, 0x34, 0xc1, 0xbf, 0x49, 0x72, 0x14, 0x1c, 0x4d, 0xf0, 0x7b, 0x41, 0x8e, 0xfe, 0x3b, 0xec, 0xc7, - 0x46, 0x09, 0xb7, 0xd2, 0xea, 0x8f, 0x15, 0xdc, 0x84, 0xd0, 0x82, 0xd1, 0x95, 0xe2, 0x2a, 0x63, 0xe8, 0xc1, 0x11, - 0xc7, 0x8f, 0x05, 0x00, 0x2b, 0x54, 0xa0, 0xa4, 0xd1, 0x97, 0xb0, 0xcb, 0x1b, 0x58, 0x78, 0xc0, 0xa0, 0x07, 0x31, - 0xc7, 0x46, 0x4f, 0x20, 0x63, 0x65, 0x6e, 0x6f, 0x25, 0x5c, 0xdf, 0xe2, 0x2b, 0xf2, 0x58, 0x84, 0x6d, 0x84, 0x39, - 0x85, 0x1f, 0x1d, 0x84, 0x3f, 0x28, 0x7b, 0xe1, 0x09, 0xdb, 0xdc, 0x60, 0x58, 0x2e, 0x0c, 0x3f, 0x13, 0x20, 0xfc, - 0x72, 0x47, 0xa6, 0x9a, 0x82, 0xfa, 0x01, 0xe1, 0x4f, 0xb5, 0xeb, 0x51, 0x7c, 0xa5, 0x48, 0x89, 0x1c, 0xef, 0x0a, - 0xc6, 0x3e, 0xd0, 0xec, 0x0b, 0x2b, 0xc2, 0xa7, 0x0a, 0xb7, 0x3b, 0x8f, 0xb0, 0x56, 0x55, 0xef, 0xb7, 0x51, 0xaf, - 0xbc, 0xdd, 0x7a, 0x2e, 0xcc, 0x7d, 0x02, 0x9c, 0xc2, 0x75, 0x7d, 0x0d, 0xac, 0xfd, 0x3e, 0xdf, 0x52, 0x6a, 0x15, - 0xf4, 0x36, 0x40, 0xf5, 0xab, 0x54, 0x9e, 0x7f, 0xa5, 0x19, 0x4f, 0xf7, 0x14, 0x9b, 0xcd, 0x33, 0xaa, 0xd8, 0x9e, - 0x9d, 0xf3, 0x1e, 0x85, 0x86, 0x82, 0x92, 0xa7, 0xf8, 0x5b, 0x56, 0x9b, 0xf6, 0x6f, 0x27, 0xe7, 0xc1, 0xde, 0x09, - 0xe1, 0x3e, 0xcb, 0xf2, 0x25, 0x92, 0x96, 0xd7, 0x65, 0x9b, 0x37, 0x82, 0xcd, 0x36, 0x28, 0xcb, 0x86, 0xfa, 0xfc, - 0xce, 0x31, 0xdc, 0x6f, 0x12, 0xd2, 0xe9, 0x07, 0xe7, 0xf2, 0xeb, 0xe4, 0x22, 0x80, 0x9b, 0x9c, 0x82, 0x48, 0xa6, - 0x95, 0x47, 0x50, 0x82, 0x92, 0x56, 0x8f, 0x9e, 0xb3, 0x1e, 0x6d, 0x34, 0x1c, 0x9b, 0x9d, 0x10, 0x3e, 0xa0, 0xa6, - 0x7e, 0x86, 0xa7, 0x38, 0x25, 0xcd, 0x36, 0x5e, 0x90, 0x96, 0xae, 0xd2, 0x5b, 0x9c, 0x27, 0xb6, 0x9f, 0x83, 0x83, - 0xb0, 0x88, 0x32, 0x2a, 0xd5, 0x0b, 0xd0, 0x08, 0x90, 0x05, 0x9e, 0x92, 0x22, 0x62, 0x77, 0x2c, 0x09, 0x13, 0x84, - 0xa7, 0x96, 0x06, 0xa1, 0x1e, 0x5a, 0x10, 0xaf, 0x18, 0xc8, 0x19, 0x44, 0xb2, 0xfe, 0x74, 0xd0, 0x1e, 0x12, 0x42, - 0x82, 0xfd, 0x66, 0x33, 0xe8, 0x17, 0xe4, 0x0f, 0x19, 0x43, 0x8a, 0xc7, 0x4e, 0x93, 0x5f, 0x20, 0xa9, 0xe3, 0x25, - 0x85, 0xef, 0x45, 0xa4, 0x98, 0x54, 0x21, 0x24, 0x83, 0x92, 0x20, 0x77, 0x18, 0x1e, 0x9c, 0x1f, 0x05, 0x0d, 0x48, - 0xd5, 0x28, 0x8a, 0x70, 0x41, 0xee, 0x15, 0x8a, 0xa7, 0x83, 0xe3, 0xa1, 0x7f, 0x46, 0x98, 0x54, 0xe8, 0xff, 0x5e, - 0xf5, 0xa7, 0x83, 0x96, 0xee, 0xff, 0x22, 0xe8, 0x87, 0x05, 0xc9, 0xf7, 0xed, 0x3d, 0x4f, 0x2c, 0x99, 0x9e, 0x2f, - 0x8a, 0xed, 0x00, 0x6d, 0xdf, 0x29, 0x69, 0x76, 0xe2, 0x30, 0xf5, 0x67, 0xd2, 0x84, 0x0e, 0x2d, 0x28, 0x70, 0x46, - 0xa0, 0x3c, 0x2e, 0x08, 0x74, 0x5a, 0x55, 0xbb, 0x57, 0xb1, 0x4d, 0xf8, 0x31, 0xf8, 0xb1, 0xff, 0x9b, 0x8c, 0x7f, - 0x92, 0x66, 0x04, 0xbf, 0xc9, 0xd5, 0x0a, 0xfe, 0xfe, 0x24, 0xfb, 0x30, 0x2c, 0x9d, 0xf6, 0x87, 0x4d, 0xfb, 0x05, - 0xd2, 0x24, 0x8b, 0xf5, 0x80, 0x71, 0x5e, 0xf2, 0x63, 0x66, 0x71, 0xc6, 0xc4, 0xcc, 0xe0, 0xe0, 0x80, 0x0f, 0x68, - 0xa3, 0x3d, 0x84, 0x1b, 0x81, 0x42, 0xc9, 0x0f, 0x5c, 0x4d, 0xc3, 0xe0, 0xe8, 0x22, 0x40, 0xfd, 0x60, 0x0f, 0x56, - 0xb9, 0x27, 0x1a, 0xc4, 0xc2, 0x3a, 0x69, 0x28, 0x1a, 0xa7, 0x17, 0xa4, 0xd5, 0x0f, 0xa5, 0x21, 0xf2, 0x19, 0xc2, - 0x89, 0xa5, 0xa9, 0x2d, 0x9c, 0xa2, 0x06, 0x97, 0x0d, 0xf7, 0x9d, 0xa2, 0xc6, 0x54, 0x35, 0xc6, 0x28, 0x4e, 0xe0, - 0x6f, 0x98, 0x12, 0x42, 0x9a, 0x9d, 0xb2, 0xa2, 0x3b, 0x2c, 0x29, 0x8a, 0xc7, 0x4e, 0x3d, 0x3a, 0xd0, 0x9b, 0x43, - 0x34, 0x42, 0x3e, 0x60, 0xc3, 0xd5, 0x2a, 0x38, 0xef, 0x5f, 0x04, 0xa8, 0x11, 0x3a, 0xb4, 0x3b, 0x72, 0x78, 0x87, - 0x10, 0x96, 0xc3, 0xb5, 0xbd, 0x81, 0xba, 0x65, 0xb5, 0xdb, 0xa6, 0x65, 0xb5, 0xff, 0x3d, 0xb2, 0xc0, 0xd6, 0xa5, - 0xdc, 0x63, 0xf8, 0xdb, 0x39, 0x4c, 0xd5, 0xe1, 0xb6, 0x20, 0x2d, 0x5c, 0x10, 0xa7, 0xee, 0xa6, 0x44, 0x55, 0xf8, - 0x9f, 0x90, 0xaa, 0x38, 0x1e, 0x64, 0x78, 0x3a, 0x24, 0x92, 0x6a, 0xf9, 0xa5, 0xe7, 0x94, 0xe9, 0x2c, 0x23, 0xb7, - 0x6c, 0xe3, 0xfe, 0x37, 0x83, 0x3b, 0x99, 0x2b, 0x15, 0x25, 0x8b, 0xa2, 0x60, 0xb9, 0x7a, 0x25, 0x52, 0xcb, 0xd8, - 0xb1, 0x0c, 0x64, 0x2b, 0xb8, 0xd8, 0xc5, 0xc0, 0xd5, 0x75, 0xdc, 0x4e, 0x49, 0xb7, 0xb2, 0x17, 0x24, 0x35, 0x0c, - 0x97, 0xbe, 0xee, 0xed, 0x2d, 0xac, 0x28, 0x1d, 0x22, 0x9c, 0xda, 0x7b, 0xe0, 0x30, 0x8a, 0xa2, 0x45, 0x94, 0x40, - 0x36, 0x74, 0x20, 0xd1, 0x5a, 0xef, 0xab, 0x30, 0x27, 0x57, 0x2a, 0xca, 0xd9, 0x9d, 0xee, 0x36, 0x44, 0xd5, 0x21, - 0xee, 0xf6, 0xdb, 0x39, 0xed, 0x69, 0x02, 0x94, 0x47, 0xb9, 0x48, 0x19, 0x40, 0x08, 0xee, 0xfe, 0x6d, 0xd2, 0x94, - 0x4a, 0xff, 0x66, 0xab, 0x1a, 0xe0, 0xc0, 0x57, 0x79, 0x2f, 0x40, 0x4f, 0xac, 0x65, 0xe8, 0xb2, 0xb0, 0x51, 0x9e, - 0x23, 0xc4, 0xc7, 0xe1, 0x22, 0x82, 0x1b, 0x41, 0x8d, 0x49, 0x5c, 0xa2, 0xd5, 0x6a, 0xe1, 0xe3, 0xd6, 0xb4, 0x52, - 0x4c, 0x8f, 0xc9, 0x74, 0x50, 0x34, 0x1a, 0x5a, 0x79, 0x9d, 0x1a, 0xbc, 0x58, 0x20, 0x3c, 0x2e, 0xf7, 0x9a, 0x2b, - 0x37, 0x27, 0xf5, 0xae, 0xc2, 0x71, 0x5d, 0x09, 0xdc, 0xe0, 0x12, 0x69, 0xfd, 0xa2, 0x82, 0xd6, 0xf1, 0x84, 0x1c, - 0x85, 0x83, 0xa8, 0xff, 0x3f, 0x87, 0xa8, 0x1f, 0x46, 0x87, 0xe8, 0xc8, 0xd0, 0x92, 0x31, 0xea, 0x25, 0xa6, 0x8f, - 0xa5, 0xbe, 0xfd, 0x6c, 0x63, 0xad, 0x80, 0x8c, 0x05, 0xce, 0xe9, 0x8c, 0xc5, 0x13, 0xd8, 0xf5, 0x0e, 0x79, 0xe6, - 0x18, 0x90, 0x29, 0x9e, 0x58, 0xda, 0x12, 0x05, 0x7d, 0x41, 0xcb, 0xaf, 0x7e, 0xd0, 0xa7, 0xd5, 0xd7, 0xff, 0x0c, - 0xfa, 0x09, 0x8d, 0xaf, 0xf8, 0xda, 0x2a, 0xc9, 0x6b, 0x7d, 0x9c, 0xba, 0x3e, 0xd6, 0x66, 0x71, 0x3c, 0xe0, 0xa5, - 0x28, 0xdf, 0xd2, 0x8e, 0x2c, 0xd0, 0x9a, 0x8f, 0x4b, 0xea, 0x94, 0x47, 0x8a, 0x4e, 0x00, 0xaa, 0xde, 0x22, 0xe4, - 0xbe, 0x6d, 0x80, 0x37, 0x65, 0xc0, 0x16, 0x87, 0xb4, 0x00, 0xcd, 0xc5, 0x45, 0x0b, 0x2d, 0x6b, 0x85, 0x2d, 0x67, - 0x55, 0xbf, 0x8b, 0x2f, 0x89, 0xf7, 0x18, 0xa8, 0xf2, 0xf9, 0xa2, 0x37, 0x6e, 0x34, 0x50, 0xee, 0xf0, 0x2b, 0x1d, - 0x8c, 0x87, 0xf8, 0x0e, 0x50, 0x08, 0xd7, 0x30, 0x0a, 0xd7, 0xe6, 0xd8, 0xb1, 0x73, 0x6c, 0x34, 0xc4, 0x1a, 0xf5, - 0xbc, 0xca, 0x0b, 0x5b, 0x79, 0xbd, 0x36, 0x90, 0xd9, 0xc4, 0xb8, 0x33, 0xa4, 0x53, 0xc0, 0x10, 0x8c, 0x10, 0xf2, - 0x8f, 0x40, 0x3b, 0x9b, 0x85, 0x46, 0xa1, 0xba, 0xde, 0xbd, 0x40, 0x51, 0xcd, 0xe9, 0x11, 0x02, 0x2c, 0xa0, 0x6a, - 0xa9, 0x46, 0x9e, 0x2a, 0x9c, 0x36, 0xda, 0x1a, 0xdd, 0x9b, 0xed, 0x5e, 0xbd, 0xb1, 0x87, 0x55, 0x63, 0x38, 0x6d, - 0x90, 0x69, 0xb5, 0xc3, 0xd7, 0xa2, 0xd1, 0x58, 0xd7, 0xef, 0x4b, 0xdd, 0x26, 0xae, 0xdd, 0x5f, 0x3c, 0xdd, 0x32, - 0xf1, 0x70, 0xa7, 0x6f, 0x75, 0xde, 0xca, 0x88, 0xe7, 0x39, 0x2b, 0xe0, 0x84, 0x25, 0x0a, 0xcb, 0xf5, 0xba, 0x3c, - 0xf5, 0x7f, 0x57, 0xc6, 0x66, 0x8c, 0x70, 0xa0, 0x43, 0x5a, 0x6a, 0xc3, 0x02, 0x17, 0x98, 0x6a, 0x2a, 0x42, 0x08, - 0xf9, 0xa0, 0x9c, 0x79, 0x8c, 0xd2, 0x24, 0x29, 0x21, 0xde, 0xd9, 0x1d, 0xe6, 0x84, 0x45, 0x37, 0x0f, 0xae, 0xc4, - 0x77, 0x45, 0xba, 0x81, 0x1c, 0xc6, 0xba, 0x58, 0x66, 0x09, 0x59, 0x46, 0xbe, 0x82, 0x9c, 0x53, 0x5e, 0xb0, 0x44, - 0x9a, 0x20, 0x3e, 0xe1, 0x05, 0xd3, 0x8c, 0xfb, 0x03, 0x27, 0x37, 0x26, 0x75, 0x4e, 0x33, 0xf1, 0xb5, 0x3f, 0x00, - 0xcd, 0x0c, 0x94, 0x43, 0x82, 0x6c, 0x15, 0xbb, 0x79, 0x70, 0xf9, 0x7a, 0x97, 0x0c, 0xbd, 0x5a, 0x59, 0xe9, 0x39, - 0x01, 0xd6, 0x07, 0x67, 0xd5, 0x50, 0x13, 0xfb, 0x23, 0x0e, 0x13, 0xcd, 0x44, 0x65, 0x21, 0x07, 0x64, 0xba, 0x79, - 0x70, 0xf9, 0x2e, 0xe4, 0x5a, 0x37, 0x85, 0xb0, 0x3f, 0xef, 0xb0, 0x20, 0x21, 0x25, 0x0c, 0x99, 0xc9, 0x97, 0x74, - 0xac, 0xf0, 0x4e, 0xf7, 0x98, 0xea, 0x4c, 0x10, 0x3b, 0x06, 0x72, 0x48, 0x12, 0x0b, 0x02, 0x92, 0x20, 0x9c, 0xd4, - 0xe4, 0x3a, 0xa2, 0xd7, 0x40, 0x77, 0x76, 0x0d, 0x8b, 0x11, 0x19, 0xf6, 0x10, 0xe1, 0x44, 0x77, 0xab, 0xd6, 0xe6, - 0x38, 0xc9, 0xe9, 0xa6, 0xa1, 0x5b, 0x25, 0xcf, 0xbe, 0x07, 0xc1, 0xcb, 0x7d, 0xbc, 0xb2, 0x6d, 0x97, 0x09, 0x4f, - 0x9c, 0x45, 0xda, 0xcd, 0x83, 0xcb, 0x5f, 0xad, 0x51, 0xda, 0x9c, 0x3a, 0xf2, 0xbf, 0x25, 0xa3, 0x5e, 0xfe, 0x1a, - 0x55, 0xb9, 0xba, 0xf0, 0xcd, 0x83, 0xcb, 0xdf, 0x77, 0x15, 0x83, 0xf4, 0xf5, 0xa2, 0x52, 0x12, 0xe8, 0xf1, 0x2d, - 0x59, 0x16, 0x2f, 0xed, 0x59, 0x11, 0xcb, 0x35, 0xd6, 0x27, 0x54, 0x9c, 0xaf, 0x4b, 0xdd, 0xca, 0x13, 0x2c, 0x88, - 0xbe, 0x4a, 0xaa, 0x2f, 0x9b, 0x45, 0x63, 0x2e, 0xf2, 0xeb, 0x44, 0xcc, 0xd9, 0x37, 0xee, 0x97, 0x9e, 0x2a, 0x14, - 0xf1, 0x19, 0x18, 0xe2, 0xe8, 0xb1, 0x4b, 0xbc, 0xdf, 0x42, 0xbd, 0x8d, 0xf3, 0x4c, 0x68, 0x44, 0x2d, 0xea, 0x87, - 0x0d, 0xa6, 0xa4, 0x85, 0x13, 0xd2, 0xc2, 0x19, 0xc9, 0x07, 0x2d, 0x73, 0x62, 0xf4, 0xb2, 0xb2, 0x69, 0x73, 0xee, - 0xc0, 0x76, 0xcf, 0xcc, 0xbe, 0x35, 0x87, 0xf2, 0xb4, 0x97, 0x69, 0xfd, 0xa5, 0x3e, 0xe8, 0xa7, 0x1a, 0x35, 0x9e, - 0xb0, 0xb0, 0xc0, 0x85, 0x6e, 0xf9, 0x9a, 0x8f, 0x32, 0xb0, 0x53, 0x81, 0x99, 0x61, 0x85, 0xe2, 0xb2, 0x6c, 0xdb, - 0x96, 0xcd, 0x22, 0xbd, 0x56, 0x05, 0xce, 0x22, 0x20, 0xe5, 0x38, 0xb3, 0x76, 0x3d, 0x72, 0xbb, 0xca, 0xe9, 0xc1, - 0x41, 0x68, 0x2b, 0xd1, 0xb0, 0x70, 0xf9, 0xd5, 0x0d, 0xe0, 0x7b, 0x43, 0x35, 0xa6, 0x48, 0x4f, 0xa0, 0xd1, 0x48, - 0x86, 0x6b, 0xba, 0x4f, 0x48, 0x98, 0xd5, 0xa1, 0xe8, 0x46, 0xaf, 0x99, 0xc1, 0x0d, 0x00, 0x34, 0x1a, 0xe5, 0x75, - 0xef, 0x06, 0xc4, 0x9e, 0x2a, 0x2c, 0xd6, 0x5f, 0xc3, 0xd2, 0x9a, 0xa8, 0xb5, 0x65, 0x87, 0xe5, 0x46, 0x81, 0xa4, - 0x8f, 0xbb, 0xd2, 0xcd, 0xc7, 0xdb, 0x1a, 0xba, 0xdc, 0x0b, 0x6b, 0x03, 0x81, 0xb5, 0xd5, 0x96, 0x2d, 0xe4, 0x48, - 0x5b, 0x07, 0xc5, 0xae, 0x10, 0x5c, 0x70, 0x41, 0xa1, 0xc6, 0xda, 0x62, 0xf9, 0x13, 0xb6, 0x6d, 0xce, 0x89, 0x73, - 0x64, 0xb5, 0x65, 0x7a, 0x18, 0x1a, 0x60, 0x9d, 0x12, 0x30, 0xcf, 0xc9, 0xcb, 0x6f, 0xa3, 0xfe, 0xa5, 0x87, 0xfa, - 0x8f, 0x09, 0xf3, 0xb6, 0x81, 0x59, 0x82, 0x48, 0x58, 0x05, 0x45, 0xee, 0xb2, 0xae, 0xe6, 0x04, 0xb4, 0x71, 0x75, - 0xa8, 0xe6, 0xfe, 0x15, 0xe5, 0x37, 0x28, 0x8b, 0xbf, 0x53, 0xb4, 0x3e, 0x13, 0xbb, 0xfb, 0xe4, 0xb0, 0xba, 0xa0, - 0x83, 0xae, 0x77, 0x29, 0x07, 0x7d, 0x52, 0x78, 0xf9, 0xfb, 0xf7, 0xef, 0x56, 0xaf, 0xe6, 0xdb, 0x3b, 0xd8, 0x33, - 0x2b, 0x85, 0x59, 0x7b, 0x1b, 0xb8, 0x6e, 0x64, 0x0a, 0xfd, 0x97, 0x77, 0xe2, 0x75, 0x2a, 0xb4, 0xb1, 0x19, 0xdd, - 0x71, 0x08, 0xa3, 0x6d, 0xb7, 0x75, 0x09, 0xe6, 0x35, 0x0b, 0x74, 0xc9, 0x18, 0xb7, 0xd2, 0xe2, 0x1b, 0x64, 0xe4, - 0x52, 0x17, 0x60, 0x79, 0xba, 0x3b, 0xfb, 0xf1, 0xda, 0xe2, 0x89, 0x19, 0x1a, 0x5a, 0x6a, 0x42, 0x68, 0xf0, 0x1e, - 0x30, 0xc7, 0x1c, 0x11, 0x00, 0xa2, 0x97, 0x1a, 0x52, 0x15, 0xc8, 0x82, 0xa0, 0x52, 0xe4, 0x3f, 0xdf, 0x27, 0xe4, - 0x65, 0xa5, 0xc8, 0x7c, 0x5b, 0x19, 0x73, 0x01, 0x62, 0xa0, 0x18, 0x2e, 0x12, 0xca, 0x04, 0x73, 0x19, 0xfa, 0x41, - 0xb9, 0xf2, 0x5a, 0xda, 0x8c, 0x2a, 0x6e, 0xdc, 0xbb, 0x29, 0xd5, 0x2a, 0x3e, 0x93, 0xef, 0x20, 0xb1, 0x91, 0xfb, - 0x00, 0x72, 0x19, 0xd5, 0x83, 0x84, 0xef, 0x77, 0xba, 0xb4, 0x6b, 0x77, 0xfd, 0x65, 0xd3, 0x22, 0x66, 0x63, 0x5d, - 0x22, 0x9e, 0x4b, 0x56, 0xa8, 0xc7, 0x6c, 0x2c, 0x0a, 0xb8, 0xff, 0x28, 0xc1, 0x82, 0xd6, 0x0f, 0x3c, 0x1d, 0xa0, - 0x9e, 0xa0, 0x77, 0xe9, 0xb0, 0x31, 0x43, 0xfd, 0xeb, 0x8b, 0xbe, 0x03, 0xbf, 0xd9, 0xac, 0xf5, 0xf2, 0xe0, 0xe0, - 0x2b, 0xab, 0x00, 0x65, 0x87, 0xa9, 0x87, 0xe1, 0x11, 0x2f, 0xc3, 0xe5, 0xd8, 0x9b, 0xe1, 0x07, 0x61, 0xa5, 0x32, - 0x70, 0x84, 0xc3, 0x27, 0x42, 0xcf, 0x89, 0x5a, 0x4f, 0x36, 0xe9, 0xbd, 0xd5, 0x66, 0x48, 0x5f, 0xac, 0x01, 0x72, - 0x0f, 0x72, 0xb9, 0x51, 0x32, 0xe5, 0x95, 0xad, 0x6d, 0x39, 0x88, 0x2b, 0x00, 0x57, 0x98, 0x83, 0x90, 0xe2, 0xa1, - 0x61, 0xbe, 0x53, 0x68, 0x79, 0x2e, 0x80, 0xfd, 0xc7, 0x79, 0x04, 0x22, 0x2d, 0xaa, 0x6d, 0x5c, 0x84, 0x70, 0xae, - 0x25, 0x1e, 0xcf, 0x38, 0xe1, 0xf2, 0xf9, 0x2e, 0x0d, 0xb5, 0x43, 0x6d, 0xa6, 0xcf, 0x20, 0x28, 0x21, 0x50, 0x59, - 0x21, 0xfa, 0x1a, 0x4a, 0xcb, 0xcd, 0x95, 0xf7, 0x70, 0xec, 0x76, 0x2f, 0xa7, 0xa1, 0xb9, 0xdb, 0x82, 0xe3, 0xa3, - 0x88, 0x16, 0x61, 0xad, 0xeb, 0x5e, 0xa1, 0xab, 0x61, 0x0b, 0x3a, 0xea, 0xc3, 0xa9, 0xd0, 0xf7, 0x84, 0x57, 0x15, - 0x49, 0xfd, 0x64, 0x2d, 0xa0, 0x1c, 0x31, 0xac, 0x4c, 0x53, 0xbc, 0xf9, 0x7f, 0xb2, 0xe6, 0x6b, 0xe5, 0x31, 0xc1, - 0xf4, 0x30, 0x6e, 0xcd, 0x2a, 0xb0, 0x35, 0xe0, 0xd8, 0xf2, 0x2f, 0xe1, 0x2d, 0xaa, 0x53, 0x8a, 0xeb, 0x4e, 0x3d, - 0x26, 0xe0, 0x2d, 0x58, 0xcf, 0x6c, 0x6e, 0xfd, 0xe7, 0xfa, 0x60, 0x94, 0x38, 0xaf, 0x11, 0x78, 0xa1, 0x09, 0x3c, - 0x02, 0xc6, 0xcd, 0x99, 0x96, 0xf7, 0xad, 0x11, 0x8d, 0x74, 0x27, 0x9e, 0xc5, 0x33, 0xc3, 0x72, 0x6f, 0x7d, 0x6c, - 0xac, 0x48, 0x2c, 0x09, 0xd8, 0x16, 0x61, 0x4b, 0xe4, 0x05, 0xc2, 0x79, 0xa3, 0xd1, 0xcb, 0xcf, 0x59, 0xa5, 0x55, - 0xa9, 0x86, 0x29, 0xe1, 0x96, 0x18, 0xf0, 0xbe, 0x76, 0xa2, 0xe6, 0x08, 0x97, 0x66, 0xee, 0x39, 0xa8, 0xef, 0x2f, - 0xdf, 0x86, 0x3e, 0x7d, 0xf3, 0xcb, 0x96, 0x17, 0xb1, 0x30, 0xa5, 0xb0, 0xba, 0xc3, 0x79, 0xf3, 0x7d, 0xb3, 0x11, - 0x18, 0xf7, 0x7e, 0x1b, 0x83, 0x8d, 0x1b, 0xea, 0x29, 0x43, 0x1a, 0xca, 0x4d, 0xd8, 0x43, 0x95, 0xbd, 0xa3, 0xdf, - 0x59, 0x4f, 0x55, 0xd2, 0xae, 0x22, 0xf9, 0x7a, 0x2d, 0x59, 0x65, 0x34, 0xb0, 0x61, 0xd8, 0xa9, 0x8f, 0x99, 0x6d, - 0x05, 0xfe, 0xd5, 0x9c, 0x28, 0xec, 0x21, 0xeb, 0x9b, 0x6f, 0x5d, 0xa7, 0x54, 0xc3, 0x84, 0xed, 0x6d, 0xcf, 0xc7, - 0x2b, 0xbe, 0xeb, 0x7c, 0xc4, 0xc2, 0x6e, 0x7d, 0x7d, 0x36, 0xb6, 0xff, 0x8d, 0xb3, 0xd1, 0xaa, 0xed, 0xdd, 0xf1, - 0x08, 0xdc, 0x49, 0xed, 0x78, 0xcc, 0xeb, 0xc7, 0xa3, 0xc0, 0xee, 0xf4, 0xbe, 0xe8, 0xac, 0x56, 0x72, 0xd0, 0x02, - 0xb5, 0x53, 0x10, 0xc0, 0xcf, 0xb6, 0xf9, 0xe9, 0x91, 0x64, 0xa3, 0x43, 0x0e, 0xcb, 0xf3, 0xbe, 0x8d, 0x22, 0x30, - 0xa0, 0x0e, 0xb5, 0xad, 0x97, 0x46, 0x6c, 0x8b, 0x43, 0x16, 0xcb, 0x89, 0x2c, 0xaf, 0xae, 0x60, 0xc4, 0xfa, 0xd8, - 0xb0, 0x02, 0x66, 0xb8, 0xd3, 0xaa, 0xd0, 0x89, 0x9f, 0xff, 0x9a, 0x39, 0xad, 0x1d, 0x31, 0x86, 0x93, 0xa8, 0x59, - 0x31, 0xd8, 0x11, 0x58, 0x86, 0x71, 0x5f, 0x4b, 0xa8, 0xd5, 0xa9, 0x8e, 0x6a, 0x47, 0x12, 0x6e, 0x81, 0xda, 0x6d, - 0x5f, 0x9f, 0x4b, 0xab, 0xd5, 0xce, 0x83, 0x05, 0x17, 0x1e, 0x6e, 0x3f, 0x27, 0xaa, 0x46, 0x52, 0x28, 0xb1, 0x12, - 0x14, 0xce, 0x34, 0xaa, 0x2a, 0x22, 0x06, 0xad, 0x21, 0xf0, 0xa4, 0xbd, 0xe4, 0x5c, 0x54, 0x42, 0x72, 0xd2, 0x68, - 0xa0, 0xac, 0xec, 0x98, 0x0e, 0x64, 0x23, 0x19, 0x62, 0x86, 0x13, 0x23, 0xb0, 0xc0, 0xe9, 0x15, 0x66, 0x55, 0xd7, - 0x83, 0x64, 0x88, 0x70, 0xb1, 0x5a, 0x85, 0x66, 0x68, 0x19, 0x5a, 0xad, 0x32, 0x7f, 0x68, 0x3a, 0x1f, 0x2a, 0xbe, - 0xec, 0x2b, 0xf2, 0x52, 0x9f, 0x87, 0x2f, 0x61, 0x90, 0x0d, 0x12, 0x66, 0x56, 0x25, 0x98, 0x81, 0xe6, 0xaa, 0x21, - 0x06, 0x49, 0xa3, 0x3d, 0xf4, 0x68, 0xd8, 0x20, 0x19, 0x92, 0x6c, 0x0d, 0x96, 0xb3, 0xb9, 0x3d, 0x30, 0xff, 0x82, - 0x83, 0xed, 0x2f, 0x7d, 0xce, 0x98, 0x06, 0xfd, 0x35, 0xd9, 0x54, 0x19, 0x94, 0x78, 0x65, 0x17, 0xd7, 0x95, 0xab, - 0x19, 0x58, 0x94, 0x85, 0xb0, 0xbd, 0x66, 0xee, 0x83, 0xf0, 0x5f, 0x62, 0xbb, 0xa0, 0xa5, 0x11, 0xf7, 0x06, 0xe2, - 0x3b, 0xdb, 0xed, 0x28, 0x8a, 0x68, 0x31, 0xd1, 0x57, 0x22, 0x8e, 0x12, 0xeb, 0x3d, 0x70, 0x6c, 0xc7, 0xe9, 0xf5, - 0x3c, 0x28, 0x3b, 0x1b, 0x12, 0x33, 0x7e, 0xc7, 0xec, 0x38, 0xc7, 0x95, 0x82, 0xee, 0xd6, 0x45, 0x98, 0xc1, 0xd0, - 0xff, 0xe5, 0xc1, 0x9c, 0xd8, 0xc1, 0x18, 0x34, 0xd9, 0x80, 0xdb, 0x37, 0xe0, 0x51, 0xd0, 0x0d, 0xb8, 0x7d, 0x1b, - 0xbe, 0x0e, 0x5a, 0xc9, 0x37, 0x07, 0xe8, 0x91, 0x09, 0x33, 0xd2, 0x2a, 0xc1, 0x1b, 0x66, 0x77, 0x93, 0x23, 0x33, - 0x64, 0x15, 0x0e, 0x57, 0x45, 0x42, 0xb9, 0xb1, 0x17, 0x2a, 0x26, 0xd5, 0xe3, 0xfe, 0x65, 0xfc, 0x12, 0xf9, 0x4a, - 0x83, 0xba, 0x71, 0x0c, 0x60, 0x95, 0xd5, 0xd6, 0xbf, 0x3c, 0x38, 0x00, 0xf3, 0x68, 0x60, 0xed, 0xa2, 0x84, 0xce, - 0xd5, 0xa2, 0x00, 0xfe, 0x2a, 0x77, 0xbf, 0x21, 0x19, 0xdc, 0x4e, 0x74, 0x1a, 0xfc, 0x80, 0x84, 0x39, 0x95, 0x92, - 0x7f, 0x35, 0x69, 0xf6, 0x37, 0x2e, 0x88, 0xc3, 0xe8, 0xdc, 0x70, 0x8a, 0x02, 0xf5, 0x84, 0x45, 0xd7, 0x3a, 0xe4, - 0x9e, 0x7e, 0x65, 0xb9, 0x7a, 0xc9, 0xa5, 0x62, 0x39, 0x00, 0xa0, 0x42, 0x3c, 0x98, 0x52, 0x8e, 0x60, 0xeb, 0xd6, - 0x6a, 0xd1, 0x34, 0xfd, 0x6e, 0x15, 0x55, 0x67, 0x8b, 0xa6, 0x34, 0x4f, 0x33, 0xd3, 0x89, 0x6f, 0x33, 0xe9, 0xec, - 0x44, 0xcb, 0x92, 0xbe, 0xc5, 0x4e, 0xc5, 0x7e, 0x68, 0x5a, 0x1f, 0x4a, 0xe2, 0xce, 0x05, 0x77, 0x96, 0x7e, 0x97, - 0x8f, 0x81, 0x2b, 0xf5, 0x6f, 0xac, 0x82, 0x3f, 0x13, 0xac, 0x3c, 0xf2, 0x1a, 0xd5, 0xc7, 0xe9, 0x50, 0x27, 0xdb, - 0x52, 0x2e, 0x94, 0x46, 0x61, 0x1b, 0x27, 0x85, 0xc6, 0x94, 0xd3, 0x6f, 0x4b, 0x5c, 0xbf, 0xba, 0x63, 0xc4, 0x1d, - 0x1d, 0xf2, 0xdf, 0xa5, 0xd2, 0x68, 0x59, 0x22, 0x18, 0x72, 0x3b, 0xf2, 0x67, 0x09, 0x57, 0xb1, 0x19, 0x57, 0xcf, - 0xd5, 0x2c, 0xdb, 0xf0, 0xc4, 0xe9, 0xfd, 0x5c, 0x5e, 0x23, 0xff, 0x2c, 0xc3, 0x5b, 0x86, 0x9f, 0x30, 0xb8, 0x37, - 0x7e, 0xc6, 0xbd, 0x2a, 0xdb, 0xf7, 0xc5, 0xcf, 0xbc, 0xfb, 0xe2, 0x67, 0x3c, 0xde, 0x2e, 0xea, 0xdd, 0x13, 0x77, - 0xa2, 0xb3, 0xa8, 0x15, 0x38, 0x3e, 0x6a, 0x4a, 0x2b, 0xff, 0x4a, 0xb3, 0x35, 0x70, 0x65, 0x13, 0x07, 0xc6, 0x79, - 0x75, 0x11, 0x8a, 0x59, 0x73, 0x46, 0xc3, 0xe1, 0x7f, 0x6b, 0x9d, 0xec, 0xc9, 0x23, 0x8c, 0x14, 0xf2, 0x86, 0x16, - 0xea, 0x01, 0x6c, 0xb8, 0x62, 0xcb, 0x07, 0x90, 0x12, 0x50, 0xb6, 0xfd, 0x7b, 0x5d, 0x54, 0x8e, 0x07, 0xfd, 0xdc, - 0x38, 0x1f, 0xf9, 0xed, 0x93, 0xa2, 0xe4, 0xea, 0xea, 0x42, 0xc8, 0x9d, 0xd6, 0x12, 0x20, 0x4c, 0x9d, 0x6b, 0x1e, - 0xb3, 0x34, 0x99, 0xc5, 0xcb, 0x75, 0xa9, 0x3a, 0x28, 0x0c, 0x57, 0xc7, 0x11, 0x2e, 0xd6, 0xfa, 0x06, 0xfd, 0x1f, - 0x8e, 0xff, 0xe2, 0x96, 0x46, 0x7e, 0x2a, 0x29, 0xd0, 0xe3, 0xdd, 0xbe, 0x36, 0x3b, 0x48, 0xa4, 0x99, 0x43, 0x69, - 0x29, 0x00, 0x58, 0xad, 0xf1, 0x75, 0xed, 0x70, 0xea, 0x89, 0xb0, 0xb3, 0xf9, 0xa6, 0x21, 0x2c, 0x66, 0xa5, 0x05, - 0x8f, 0xee, 0x66, 0x87, 0xe5, 0xa8, 0x93, 0xc5, 0x55, 0xb9, 0xc7, 0x6a, 0xfd, 0xa2, 0x6f, 0x80, 0xb2, 0x32, 0x44, - 0x5b, 0xad, 0xc2, 0x3a, 0xbc, 0x89, 0xf4, 0xae, 0x41, 0x10, 0x96, 0x9e, 0x01, 0x47, 0x8d, 0xf1, 0x36, 0x75, 0x42, - 0xb4, 0x69, 0xbf, 0xe4, 0x58, 0xf7, 0xda, 0x38, 0x7c, 0x45, 0x83, 0xa9, 0xee, 0x6b, 0x1e, 0xb0, 0x99, 0x5d, 0xd9, - 0x91, 0x07, 0xa1, 0x29, 0x75, 0xc6, 0xb9, 0x95, 0x15, 0xed, 0x0e, 0xf8, 0xa2, 0xef, 0x98, 0xe7, 0x5a, 0xd0, 0x6d, - 0xe7, 0x7b, 0xb6, 0x4d, 0x4f, 0xc4, 0xb7, 0x6c, 0x9b, 0x6a, 0x9c, 0xf0, 0x7e, 0x0b, 0x7d, 0xdf, 0x10, 0xd6, 0xf4, - 0xb5, 0xbb, 0xc8, 0xff, 0x42, 0x77, 0x6d, 0x40, 0x4f, 0x03, 0x66, 0x47, 0x63, 0x3e, 0xa8, 0xf5, 0xfa, 0x53, 0xe9, - 0xbf, 0xa0, 0x6d, 0x85, 0x3e, 0x99, 0x5d, 0x60, 0xc5, 0x4a, 0xed, 0x10, 0x1c, 0xfe, 0xc3, 0xc9, 0x24, 0x13, 0x23, - 0x9a, 0xbd, 0x83, 0x1e, 0xab, 0xdc, 0xe7, 0xf7, 0x69, 0x41, 0x15, 0xb3, 0xb4, 0xa6, 0x1a, 0xc5, 0x3f, 0xdc, 0x1b, - 0xc6, 0x3f, 0xdc, 0x50, 0xee, 0xaa, 0x05, 0xbc, 0x7c, 0x59, 0x36, 0x11, 0x7f, 0x5a, 0x97, 0xfe, 0x56, 0xf9, 0xee, - 0x5e, 0x36, 0x49, 0x9a, 0xca, 0xcb, 0xd9, 0xe6, 0xe1, 0x66, 0x53, 0x61, 0xf8, 0xd7, 0x37, 0x06, 0xbb, 0x4d, 0xe6, - 0xfe, 0xf2, 0xc8, 0xdc, 0x5f, 0x3c, 0xfe, 0x6e, 0x2d, 0x8f, 0xe2, 0x1d, 0x47, 0xc7, 0xda, 0x32, 0xc6, 0x8c, 0xfa, - 0xad, 0x02, 0x83, 0x06, 0x45, 0x2e, 0x3c, 0x6f, 0x87, 0xea, 0xf4, 0x72, 0xf6, 0x47, 0x61, 0xb2, 0x90, 0x4a, 0xcc, - 0x6c, 0xa3, 0xd2, 0xfa, 0x38, 0xe9, 0x4c, 0x50, 0x60, 0xeb, 0x3b, 0xfc, 0xb8, 0xee, 0x46, 0xb6, 0xfc, 0xc2, 0xf3, - 0x34, 0xce, 0xb1, 0x3d, 0x5b, 0x64, 0x2c, 0xd6, 0xc4, 0x99, 0x39, 0x6f, 0xe7, 0xe1, 0x31, 0xcf, 0xb9, 0x9c, 0xb2, - 0x22, 0x2c, 0xd0, 0xf2, 0x5b, 0x9d, 0x15, 0x70, 0x9b, 0x63, 0x3a, 0xc3, 0x69, 0x69, 0x39, 0xa0, 0x22, 0x68, 0x0d, - 0x74, 0x46, 0x33, 0xa6, 0xa6, 0x22, 0x05, 0xc3, 0x97, 0x28, 0x2d, 0xdd, 0xa9, 0x0e, 0x0e, 0xf6, 0xc3, 0x40, 0xeb, - 0x2f, 0xc0, 0x07, 0xdd, 0xcf, 0x41, 0xfd, 0x25, 0x38, 0x06, 0x55, 0x5d, 0x33, 0xb4, 0x64, 0x9b, 0x3e, 0x34, 0x2a, - 0xfa, 0xc2, 0xee, 0x31, 0x47, 0xeb, 0x75, 0x6c, 0x46, 0x1d, 0x8c, 0x39, 0xcb, 0xd2, 0x00, 0x7f, 0x61, 0xf7, 0x71, - 0xe9, 0xb6, 0xae, 0xbd, 0xac, 0xf5, 0x22, 0x06, 0xe2, 0x36, 0x0f, 0x70, 0xd5, 0x49, 0xbc, 0x5c, 0x63, 0x51, 0xf0, - 0x09, 0xe0, 0xe8, 0x2f, 0xec, 0x3e, 0xb6, 0xed, 0x79, 0xae, 0x82, 0x68, 0xe9, 0x40, 0x1f, 0x79, 0xc9, 0xfe, 0x32, - 0x58, 0x81, 0x63, 0xa0, 0xeb, 0x0e, 0x49, 0xad, 0x5c, 0x25, 0x42, 0x22, 0xb4, 0xfe, 0x77, 0xa7, 0x82, 0x17, 0xfe, - 0x39, 0xa7, 0x6a, 0x16, 0xb7, 0x1b, 0x95, 0x18, 0x54, 0xa8, 0x2c, 0x48, 0x3e, 0x86, 0xdc, 0xed, 0x3e, 0xeb, 0xfd, - 0xe0, 0xe9, 0xcc, 0x16, 0xd4, 0x36, 0x1a, 0xa7, 0xfa, 0x17, 0xaa, 0xee, 0xa0, 0x66, 0xaa, 0xaa, 0xb8, 0xf7, 0x31, - 0x04, 0xc0, 0x83, 0xb5, 0x0c, 0xd5, 0x0e, 0xa1, 0x6b, 0x67, 0xa6, 0x3a, 0xa6, 0x24, 0x5c, 0xba, 0x39, 0xc4, 0xdc, - 0x07, 0xa3, 0x5a, 0x03, 0x1a, 0x5a, 0x04, 0x33, 0x96, 0x87, 0x7c, 0x1c, 0xca, 0xad, 0x33, 0x54, 0xe8, 0x33, 0x34, - 0xf2, 0x40, 0xfe, 0x8d, 0x33, 0x93, 0x69, 0x68, 0x68, 0xde, 0x52, 0x1f, 0x80, 0x76, 0x75, 0x2d, 0x0e, 0xf9, 0x2b, - 0x5a, 0x3a, 0xef, 0x99, 0x45, 0x17, 0xb5, 0x61, 0x85, 0xba, 0x1d, 0xb4, 0x8e, 0x61, 0x4a, 0xcc, 0x14, 0x58, 0x3b, - 0xbd, 0x0f, 0x77, 0x76, 0xb5, 0x61, 0x11, 0xb9, 0x69, 0x11, 0x07, 0x93, 0x90, 0xa2, 0x25, 0x0f, 0x29, 0x16, 0x60, - 0x07, 0x59, 0xac, 0xcb, 0xf1, 0x33, 0x7f, 0x39, 0x6a, 0x56, 0xd2, 0xbb, 0x1d, 0x0c, 0x81, 0xcb, 0x57, 0x60, 0x1b, - 0x8a, 0xb9, 0x23, 0x2c, 0x3c, 0xd4, 0x9e, 0x7e, 0xde, 0xba, 0xcd, 0xcd, 0x82, 0xb8, 0x15, 0x18, 0xd3, 0x70, 0xe9, - 0xcd, 0xc2, 0x77, 0x2a, 0xb7, 0x0e, 0x87, 0xf6, 0x9a, 0xb0, 0x32, 0x5e, 0x0d, 0x73, 0xb2, 0x71, 0xf4, 0x7c, 0xdf, - 0xc6, 0xf3, 0xef, 0x05, 0x2b, 0xee, 0xaf, 0x19, 0xd8, 0x58, 0x0b, 0x70, 0x37, 0xae, 0x96, 0xa1, 0x32, 0x90, 0xef, - 0x0b, 0xcd, 0xba, 0xac, 0xf1, 0x77, 0xa3, 0x62, 0xac, 0xf5, 0x3d, 0xa5, 0xa7, 0xad, 0x31, 0xdb, 0x85, 0x7d, 0xd3, - 0x75, 0x93, 0xf5, 0xb4, 0x22, 0xae, 0x82, 0xb4, 0xbd, 0x5b, 0xc0, 0x85, 0xef, 0x0f, 0x3b, 0xc8, 0x87, 0x9b, 0xaa, - 0x1b, 0x48, 0x82, 0x6b, 0x3f, 0xf1, 0xed, 0xa9, 0xee, 0xb2, 0xd6, 0xfd, 0xf6, 0x54, 0x6b, 0x97, 0x85, 0xda, 0x90, - 0x08, 0xdb, 0x7e, 0x4a, 0xff, 0x69, 0xb9, 0x5e, 0xa3, 0x35, 0x0c, 0xef, 0x3d, 0xef, 0x85, 0xe1, 0x7b, 0x67, 0xa1, - 0x18, 0xc1, 0x45, 0xee, 0x75, 0x26, 0x1c, 0x21, 0xaf, 0x46, 0xf0, 0x9e, 0x6f, 0x0d, 0xe1, 0x3d, 0xf7, 0x9c, 0x5e, - 0x41, 0x6a, 0x9a, 0xe4, 0x2c, 0x75, 0xf4, 0x13, 0x19, 0x24, 0xd4, 0x7c, 0xdc, 0x6b, 0x4e, 0xb8, 0xfa, 0x1c, 0x03, - 0xff, 0x85, 0x47, 0x0b, 0xa5, 0x44, 0x8e, 0x79, 0x3e, 0x5f, 0x28, 0x2c, 0xf5, 0xe8, 0x97, 0x63, 0x91, 0xab, 0xe6, - 0x98, 0xce, 0x78, 0x76, 0x1f, 0x2f, 0x78, 0x73, 0x26, 0x72, 0x21, 0xe7, 0x34, 0x61, 0x58, 0xde, 0x4b, 0xc5, 0x66, - 0xcd, 0x05, 0xc7, 0xcf, 0x59, 0xf6, 0x95, 0x29, 0x9e, 0x50, 0xfc, 0x56, 0x8c, 0x84, 0x12, 0xf8, 0xf5, 0xdd, 0xfd, - 0x84, 0xe5, 0xf8, 0xf7, 0xd1, 0x22, 0x57, 0x0b, 0x2c, 0x69, 0x2e, 0x9b, 0x92, 0x15, 0x7c, 0xdc, 0x6b, 0x36, 0xe7, - 0x05, 0x9f, 0xd1, 0xe2, 0xbe, 0x99, 0x88, 0x4c, 0x14, 0xf1, 0x7f, 0xb5, 0x8e, 0xe9, 0xa3, 0xf1, 0x49, 0x4f, 0x15, - 0x34, 0x97, 0x1c, 0x16, 0x26, 0xa6, 0x59, 0xb6, 0x77, 0xdc, 0x6d, 0xcd, 0xe4, 0xbe, 0xb9, 0xf0, 0xa3, 0xb9, 0x5a, - 0x7f, 0xc6, 0x1f, 0x04, 0x8c, 0x32, 0x1a, 0xa9, 0xdc, 0x0e, 0x72, 0x99, 0x2c, 0x0a, 0x29, 0x8a, 0x78, 0x2e, 0x78, - 0xae, 0x58, 0xd1, 0x1b, 0x89, 0x22, 0x65, 0x45, 0xb3, 0xa0, 0x29, 0x5f, 0xc8, 0xf8, 0x64, 0x7e, 0xd7, 0xab, 0xf7, - 0x60, 0xf2, 0xe3, 0x5c, 0xe4, 0xac, 0x07, 0xfc, 0xc6, 0xa4, 0x10, 0x8b, 0x3c, 0xb5, 0xc3, 0x58, 0xe4, 0x92, 0xa9, - 0xde, 0x9c, 0xa6, 0x60, 0x07, 0x1c, 0x9f, 0xcd, 0xef, 0x7a, 0x7a, 0xd6, 0xb7, 0x8c, 0x4f, 0xa6, 0x2a, 0xee, 0xb6, - 0x5a, 0xe6, 0x5b, 0xf2, 0x7f, 0x58, 0xdc, 0xee, 0x44, 0x9d, 0xee, 0xfc, 0x0e, 0x38, 0x78, 0xc5, 0x8a, 0x26, 0xc0, - 0x02, 0x2a, 0xb5, 0xa3, 0xd6, 0xa3, 0xe3, 0x87, 0x90, 0x01, 0x36, 0x0e, 0x4d, 0x3d, 0x21, 0x30, 0x76, 0x8f, 0x17, - 0xf3, 0x39, 0x2b, 0xc0, 0x8b, 0xbe, 0x37, 0xa3, 0xc5, 0x84, 0xe7, 0xcd, 0x42, 0x37, 0xda, 0x3c, 0x9b, 0xdf, 0xad, - 0x61, 0x3e, 0xb1, 0x31, 0x5b, 0xb5, 0xd3, 0xb2, 0x5f, 0x4b, 0x6f, 0x88, 0x3a, 0x26, 0x4d, 0x5c, 0x4c, 0x46, 0x34, - 0x6c, 0x77, 0x1e, 0x62, 0xf7, 0xbf, 0xa8, 0x83, 0x3c, 0xb0, 0x35, 0xd3, 0x45, 0xa1, 0x6f, 0x51, 0xe3, 0xb6, 0x34, - 0xcd, 0x4e, 0xc5, 0x57, 0x56, 0xb8, 0x56, 0xf5, 0xc7, 0x72, 0x6b, 0xde, 0xff, 0x49, 0xa3, 0x9f, 0xf1, 0x84, 0xc2, - 0x1a, 0x68, 0xe4, 0x18, 0x68, 0x79, 0x10, 0x66, 0x3a, 0x5c, 0xde, 0xf2, 0x54, 0x4d, 0xe3, 0x76, 0xab, 0xf5, 0x43, - 0xb5, 0x62, 0xbd, 0xa9, 0x01, 0x5d, 0xbb, 0x60, 0xb3, 0xda, 0x3a, 0xce, 0x68, 0x89, 0x6d, 0xcb, 0xb9, 0xb0, 0x4b, - 0x5e, 0xb0, 0x4c, 0x47, 0x93, 0x59, 0x5b, 0x94, 0xdb, 0x1a, 0x27, 0xcf, 0xa7, 0xac, 0xe0, 0xaa, 0x57, 0xff, 0xaa, - 0x3a, 0xde, 0x5e, 0xfd, 0xb5, 0x91, 0x43, 0x97, 0xa6, 0x86, 0xbd, 0xf4, 0xbc, 0x82, 0x8f, 0xed, 0xd5, 0xff, 0x4a, - 0x8b, 0x70, 0x03, 0x31, 0xb1, 0x5f, 0x03, 0xad, 0xbd, 0x39, 0x17, 0x60, 0x92, 0x39, 0xc4, 0xdf, 0x80, 0x42, 0x42, - 0xb3, 0x24, 0x84, 0x11, 0xed, 0x35, 0xf7, 0x8e, 0x0b, 0x36, 0x43, 0x0e, 0x10, 0xd1, 0xc3, 0x6e, 0xc1, 0x66, 0xeb, - 0x48, 0x57, 0x5f, 0x6a, 0x14, 0xa1, 0x19, 0x9f, 0xe4, 0x71, 0xc2, 0x00, 0x7d, 0xd7, 0x11, 0xcb, 0x15, 0x57, 0xf7, - 0xcd, 0x42, 0xdc, 0x2e, 0x53, 0x2e, 0xe7, 0x19, 0xbd, 0x8f, 0xc7, 0x19, 0xbb, 0xeb, 0xe9, 0x52, 0x4d, 0xae, 0xd8, - 0x4c, 0xda, 0xb2, 0x3d, 0x48, 0x6f, 0xa6, 0xc6, 0x6c, 0x02, 0xa0, 0x27, 0x6e, 0x37, 0xf7, 0x4f, 0x74, 0x2c, 0xf7, - 0x18, 0x95, 0xac, 0x29, 0x16, 0x6a, 0xaf, 0x25, 0x7b, 0x33, 0x9e, 0x37, 0xed, 0x40, 0x4e, 0x5a, 0xf3, 0xbb, 0xde, - 0x36, 0xe4, 0xbd, 0xfe, 0x23, 0x76, 0x37, 0xa7, 0x79, 0xca, 0xd2, 0xa5, 0x57, 0xad, 0x03, 0xf5, 0xfc, 0x52, 0x71, - 0xae, 0xa6, 0x4d, 0x6d, 0xeb, 0x15, 0x76, 0x72, 0xf4, 0x0d, 0xd4, 0x7a, 0xd4, 0xc2, 0xe6, 0xff, 0xa3, 0x36, 0xf2, - 0x2b, 0xef, 0x41, 0xd8, 0x25, 0x3e, 0xbe, 0x6f, 0xc2, 0xdf, 0x25, 0xf8, 0x16, 0xf1, 0x84, 0x66, 0x16, 0x22, 0x33, - 0x9e, 0xa6, 0x59, 0x6d, 0x44, 0x17, 0x5e, 0x67, 0x6d, 0xb4, 0x84, 0xf9, 0xc7, 0xad, 0xbd, 0xd6, 0x9e, 0x9e, 0x8b, - 0xdd, 0xe6, 0x27, 0x27, 0x0f, 0x8f, 0x1f, 0xb1, 0x5e, 0xc6, 0x73, 0x56, 0x9b, 0xea, 0x77, 0x41, 0xed, 0x37, 0xdc, - 0xb1, 0x0d, 0xb7, 0xf7, 0xda, 0x7b, 0x27, 0xad, 0x1f, 0xdc, 0x6e, 0xcd, 0xd8, 0x58, 0xc5, 0xed, 0xd3, 0xf9, 0x5d, - 0x7d, 0xfb, 0x9e, 0xb9, 0xa6, 0x6f, 0x0b, 0x3a, 0x8f, 0x73, 0x01, 0x7f, 0x7a, 0xb0, 0xc9, 0xc6, 0x99, 0xb8, 0x8d, - 0xa7, 0x3c, 0x4d, 0x59, 0x6e, 0x0a, 0x94, 0x89, 0x2c, 0xcb, 0xf8, 0x5c, 0x72, 0xb3, 0x1a, 0x16, 0x77, 0xbb, 0x1b, - 0x50, 0xf5, 0x07, 0x74, 0xec, 0x0d, 0xa8, 0x5b, 0x0d, 0xa8, 0xea, 0xdf, 0x1f, 0x61, 0x67, 0x63, 0xae, 0xba, 0x54, - 0xaf, 0x86, 0x49, 0x7f, 0x2d, 0xa4, 0x02, 0x98, 0x97, 0x46, 0x1a, 0x40, 0xc5, 0x9b, 0x23, 0xa6, 0x6e, 0x19, 0xcb, - 0xbf, 0x3d, 0x88, 0x8b, 0x58, 0xe4, 0xd9, 0xbd, 0xf9, 0x5c, 0xfa, 0x5d, 0xd2, 0x85, 0x12, 0xeb, 0x68, 0xc4, 0x73, - 0x5a, 0xdc, 0xdf, 0x48, 0x96, 0x4b, 0x51, 0xdc, 0x88, 0xf1, 0x78, 0xf9, 0x2d, 0xd2, 0xf2, 0x10, 0xad, 0x23, 0xc9, - 0xf3, 0x49, 0xc6, 0x0c, 0x51, 0xd2, 0x88, 0x60, 0x89, 0xb9, 0x69, 0x57, 0x37, 0x59, 0x1b, 0xb4, 0xbf, 0xf3, 0x74, - 0xbb, 0xc3, 0x38, 0x6e, 0xde, 0xb2, 0xd1, 0x17, 0xae, 0x0c, 0x9e, 0x35, 0xe5, 0x2d, 0x78, 0xbc, 0xe8, 0x65, 0x98, - 0xb3, 0x62, 0xe9, 0x68, 0x78, 0xcb, 0xa3, 0x3a, 0x51, 0x92, 0xf1, 0x19, 0x55, 0xcc, 0xa3, 0x54, 0x65, 0x27, 0x93, - 0x82, 0xa7, 0xdb, 0x38, 0xd2, 0x83, 0xe4, 0xa6, 0x33, 0xa8, 0x82, 0x9e, 0x16, 0xb3, 0x5c, 0xc6, 0x05, 0x9b, 0x33, - 0xaa, 0xc2, 0x63, 0xdc, 0x1e, 0x17, 0xa8, 0x37, 0xa1, 0xf3, 0x18, 0xf0, 0xc2, 0x75, 0xd9, 0x86, 0x25, 0xd8, 0xde, - 0xae, 0xeb, 0xcf, 0xf8, 0x8b, 0xd4, 0x87, 0x97, 0xa2, 0xa3, 0x26, 0x84, 0x1f, 0x63, 0x45, 0xb9, 0xc5, 0x79, 0xae, - 0x11, 0x56, 0xaf, 0xcf, 0xe6, 0x26, 0xf5, 0x8f, 0xa0, 0x93, 0x56, 0xcb, 0xf5, 0xd3, 0x34, 0x75, 0xe2, 0x76, 0xd4, - 0x65, 0xb3, 0x5d, 0xe4, 0xa1, 0x4e, 0x0b, 0xdb, 0x9d, 0xf9, 0xdd, 0x9e, 0xfe, 0xa7, 0xb5, 0xd7, 0xda, 0xa6, 0x7d, - 0xdb, 0xcb, 0x74, 0x8c, 0x1c, 0x62, 0x29, 0x31, 0x8f, 0xdb, 0x6c, 0xd6, 0x5b, 0x48, 0x38, 0xe7, 0x34, 0x69, 0xd6, - 0xe7, 0xe7, 0x5a, 0xcf, 0x04, 0xd0, 0x88, 0xf2, 0x1c, 0x8e, 0x15, 0x73, 0xb4, 0x42, 0x1f, 0x52, 0x80, 0x1d, 0xf8, - 0xce, 0x46, 0xeb, 0xc3, 0x6a, 0xed, 0x55, 0x03, 0x83, 0x7f, 0xd6, 0x9f, 0x2b, 0xc6, 0xf4, 0x05, 0xf3, 0x04, 0x03, - 0xde, 0x88, 0xba, 0xab, 0x96, 0x15, 0x06, 0x52, 0x55, 0xc9, 0x28, 0xda, 0x95, 0x62, 0x46, 0xef, 0x8c, 0x4f, 0xc5, - 0x8c, 0xe7, 0x60, 0xb1, 0x85, 0xb0, 0xf2, 0x6c, 0xdb, 0xa7, 0x7e, 0x43, 0xa9, 0x0a, 0xa1, 0xe1, 0xc3, 0x4e, 0xd4, - 0xed, 0x22, 0xdc, 0xc2, 0x9d, 0x6e, 0xd7, 0x13, 0x46, 0xc6, 0x6a, 0x57, 0xd1, 0x5d, 0x25, 0xf3, 0x1d, 0x25, 0x8f, - 0x74, 0xa3, 0x47, 0xed, 0x56, 0x0b, 0x6b, 0xbf, 0xf1, 0xb2, 0x30, 0xcb, 0x77, 0x34, 0xdb, 0x6e, 0xb5, 0xa0, 0x59, - 0xf8, 0x63, 0xe7, 0xf5, 0x0b, 0x59, 0xb6, 0xe2, 0x16, 0x6e, 0xc7, 0x6d, 0xdc, 0x89, 0x3b, 0xf8, 0x38, 0x3e, 0xc6, - 0x27, 0xf1, 0x09, 0xee, 0xc6, 0x5d, 0x7c, 0x1a, 0x9f, 0xe2, 0x87, 0xf1, 0x43, 0x7c, 0x16, 0x9f, 0xe1, 0x47, 0xf1, - 0x23, 0x7c, 0x19, 0xb7, 0x5b, 0xf8, 0x71, 0xdc, 0x6e, 0xe3, 0xab, 0xb8, 0xdd, 0xc1, 0x4f, 0xe2, 0xf6, 0x31, 0x7e, - 0x1a, 0xb7, 0x4f, 0xf0, 0xb3, 0xb8, 0xdd, 0xc5, 0x14, 0x72, 0x47, 0x90, 0x9b, 0x40, 0x6e, 0x0a, 0xb9, 0x0c, 0x72, - 0xc7, 0x71, 0xbb, 0xbb, 0xc6, 0xd2, 0xc4, 0x9a, 0x08, 0x5a, 0xed, 0xce, 0xf1, 0x49, 0xf7, 0xf4, 0xe1, 0xd9, 0xa3, - 0xcb, 0xc7, 0x57, 0x4f, 0x9e, 0x3e, 0x0b, 0x86, 0x78, 0xa4, 0x5d, 0x3e, 0xa4, 0x1c, 0xf0, 0x83, 0x76, 0x77, 0x88, - 0x6f, 0xdc, 0x67, 0xc8, 0x0f, 0x3a, 0x27, 0x2d, 0x74, 0x71, 0x71, 0x32, 0x6c, 0x94, 0xb9, 0xef, 0xb5, 0xa7, 0x49, - 0x95, 0x45, 0x08, 0x09, 0x21, 0x07, 0xe1, 0x7b, 0x5d, 0xef, 0x3d, 0x0b, 0x79, 0x54, 0xa0, 0x83, 0x03, 0xfd, 0x63, - 0xe2, 0x7e, 0x8c, 0xdc, 0x0f, 0xea, 0x2d, 0xd2, 0x1d, 0x0d, 0xad, 0xab, 0xb1, 0x2a, 0x0d, 0xfd, 0x4b, 0x1b, 0x9a, - 0x3d, 0x6e, 0xad, 0xd9, 0xff, 0x2b, 0x30, 0xd6, 0x2a, 0xe4, 0xc4, 0x68, 0x84, 0xba, 0x7d, 0x46, 0x96, 0x45, 0xdc, - 0xe9, 0x76, 0x0f, 0x7e, 0x19, 0xf0, 0x41, 0x7b, 0x38, 0x3c, 0x6c, 0x3f, 0xc4, 0x93, 0x32, 0xa1, 0x63, 0x12, 0x46, - 0x65, 0xc2, 0xb1, 0x49, 0xa0, 0xb1, 0xa9, 0x0d, 0x49, 0x27, 0x3a, 0x09, 0x4a, 0xac, 0x63, 0xdd, 0xf6, 0x43, 0xd3, - 0xf6, 0x23, 0x30, 0xa3, 0xd2, 0xcd, 0xdb, 0xa6, 0xcf, 0xcf, 0x4f, 0x56, 0xb6, 0x51, 0x3c, 0x89, 0x6d, 0x6b, 0x2e, - 0xf1, 0x64, 0x38, 0xc4, 0x23, 0x9d, 0xd8, 0xad, 0x12, 0x4f, 0x87, 0x43, 0xdb, 0xd5, 0x23, 0xdd, 0xd5, 0xc3, 0x2a, - 0xeb, 0x6c, 0x38, 0xd4, 0x5d, 0x22, 0xeb, 0x34, 0x2f, 0xd5, 0xde, 0xd7, 0x52, 0x71, 0xc1, 0xcf, 0x3b, 0xdd, 0x6e, - 0x1f, 0x30, 0x4c, 0x1b, 0xc3, 0x3a, 0x18, 0xdd, 0x7a, 0x30, 0xba, 0x87, 0xdf, 0xfd, 0x11, 0x8d, 0x6f, 0x68, 0x09, - 0xa4, 0x7e, 0xf0, 0x5f, 0x41, 0x43, 0x69, 0x98, 0xeb, 0x3f, 0x13, 0xf3, 0x67, 0x84, 0x1a, 0x5f, 0x29, 0x80, 0x1b, - 0x54, 0x31, 0x4e, 0x97, 0xaa, 0x7b, 0xfc, 0x42, 0xc1, 0xb7, 0x65, 0x2a, 0x33, 0xda, 0x5f, 0x4d, 0x6f, 0x47, 0xab, - 0xa9, 0xfc, 0x8a, 0xfe, 0x0c, 0xff, 0x94, 0x87, 0xe1, 0xa0, 0xd9, 0x88, 0xd8, 0x9f, 0x29, 0x38, 0xd1, 0xf4, 0xe3, - 0x94, 0x4d, 0x50, 0x7f, 0xf0, 0xa7, 0xc4, 0xc3, 0x86, 0x97, 0xf1, 0xc3, 0x76, 0x0a, 0xb8, 0xd8, 0x6c, 0x26, 0x86, - 0x3f, 0xa0, 0x3e, 0xea, 0xff, 0x29, 0x0f, 0xff, 0x44, 0x0f, 0x8e, 0xaa, 0xb9, 0xfc, 0x2e, 0xec, 0x16, 0xae, 0xe2, - 0xee, 0x1c, 0x96, 0x5b, 0x98, 0xe1, 0x76, 0x93, 0x41, 0x94, 0x32, 0xf0, 0xc1, 0x26, 0xa1, 0x68, 0xf0, 0xa3, 0xe3, - 0x16, 0xfa, 0xa1, 0xdd, 0x01, 0xad, 0x42, 0x53, 0x1e, 0x6e, 0x6f, 0xfa, 0xa2, 0x79, 0x8c, 0x1f, 0x35, 0x0b, 0xdc, - 0x46, 0xb8, 0xd9, 0x76, 0xea, 0xde, 0x41, 0x1e, 0xb6, 0x10, 0xce, 0xc3, 0x33, 0xf8, 0xe7, 0x04, 0x0d, 0xab, 0x0d, - 0x79, 0x4d, 0x37, 0x7b, 0x07, 0x87, 0x51, 0x12, 0xe6, 0x0d, 0x7e, 0x74, 0xda, 0x42, 0x3f, 0x9c, 0xea, 0x8e, 0xd8, - 0xa1, 0xda, 0xd1, 0x95, 0xc0, 0x27, 0x4d, 0x01, 0x1d, 0xb5, 0xca, 0x7e, 0x64, 0xd8, 0x45, 0x58, 0x86, 0xc7, 0xf0, - 0x4f, 0xdb, 0xef, 0xe7, 0xd7, 0xad, 0x7e, 0xf4, 0xbc, 0xdb, 0x38, 0xea, 0x1a, 0xff, 0xd3, 0xdc, 0x5c, 0x06, 0x37, - 0xd8, 0x45, 0x5b, 0xdf, 0x62, 0xb5, 0x8f, 0xe0, 0x03, 0x61, 0x75, 0x48, 0x72, 0xcc, 0x0e, 0xc1, 0x71, 0x15, 0xec, - 0x35, 0xf2, 0xf3, 0xe3, 0x5e, 0xde, 0x68, 0x20, 0x90, 0x0f, 0x0f, 0x49, 0xbb, 0xa9, 0x9a, 0x0c, 0xc3, 0xef, 0x06, - 0x29, 0xa3, 0xa1, 0xc9, 0xaa, 0xd7, 0x2b, 0xdb, 0xab, 0xb9, 0xf2, 0x76, 0xd8, 0x01, 0x62, 0x62, 0x3f, 0x54, 0x4d, - 0x86, 0x8e, 0x64, 0x23, 0x54, 0xe7, 0xac, 0x7f, 0x1a, 0xb7, 0x90, 0xc6, 0xce, 0xbc, 0x1f, 0xb2, 0x26, 0x87, 0xf4, - 0x4e, 0x1c, 0xf2, 0xa6, 0x82, 0x5f, 0x27, 0x1e, 0xb4, 0x24, 0xe0, 0x5d, 0xe5, 0x86, 0x53, 0x1c, 0x75, 0xba, 0x5d, - 0x2c, 0x09, 0x8f, 0x26, 0xfa, 0x57, 0x4e, 0x78, 0x34, 0xd2, 0xbf, 0x04, 0x29, 0xe1, 0x65, 0x7a, 0xc7, 0x05, 0xf1, - 0x56, 0x55, 0xa7, 0x50, 0x58, 0xd0, 0x02, 0x1d, 0x75, 0xdc, 0x7d, 0x38, 0x9e, 0xba, 0x39, 0x80, 0xfc, 0x5f, 0x68, - 0x53, 0x48, 0xd1, 0x2c, 0x70, 0x46, 0xe8, 0x45, 0xd4, 0xed, 0x4f, 0x8f, 0xc2, 0x4e, 0x53, 0x34, 0x0b, 0x14, 0x4f, - 0x8f, 0x74, 0x4d, 0x9c, 0x90, 0x2b, 0x6a, 0x5a, 0xc3, 0x53, 0xb8, 0xc4, 0x4c, 0x48, 0x72, 0x78, 0xda, 0x6a, 0x44, - 0x5d, 0x84, 0x07, 0xc9, 0xaa, 0x85, 0xb3, 0xd5, 0xaa, 0x85, 0xa9, 0xbf, 0x0c, 0xd2, 0x01, 0xa4, 0x54, 0x51, 0x6d, - 0x06, 0xa5, 0xe9, 0xf3, 0x50, 0xc1, 0x85, 0xbc, 0x02, 0x37, 0x17, 0x05, 0x0e, 0x38, 0x31, 0xb7, 0x37, 0x61, 0x48, - 0x87, 0xe5, 0x1b, 0xfb, 0x4a, 0xab, 0x2b, 0xe9, 0xd6, 0xd5, 0x8e, 0xfc, 0x57, 0x19, 0xfe, 0x2e, 0xb0, 0x49, 0xab, - 0x8a, 0xbd, 0xa6, 0xdb, 0xc5, 0x7e, 0xa5, 0x5b, 0xc5, 0xde, 0xec, 0x28, 0x76, 0xbd, 0x5d, 0xec, 0xa3, 0xf0, 0x54, - 0x6c, 0xfc, 0x87, 0xe3, 0xd3, 0x56, 0xe3, 0x18, 0x90, 0xf5, 0xf8, 0xb4, 0x55, 0x15, 0x7a, 0x40, 0xab, 0xb5, 0x52, - 0xe4, 0x0b, 0x35, 0x4e, 0x06, 0xdc, 0x79, 0x3b, 0xeb, 0x85, 0x33, 0xbe, 0xd6, 0xa5, 0x63, 0xf5, 0xa0, 0x0b, 0x46, - 0x1c, 0x52, 0x53, 0x3b, 0x35, 0x38, 0x1d, 0xf6, 0xa7, 0x2c, 0x6c, 0x40, 0x2a, 0x8a, 0xc7, 0xca, 0xfe, 0x42, 0xe5, - 0x5d, 0xee, 0x47, 0x01, 0x49, 0x9d, 0x21, 0xc2, 0x82, 0x34, 0xd4, 0xe0, 0x78, 0xa8, 0xcf, 0xbb, 0x02, 0x7e, 0x9f, - 0xe8, 0xdf, 0xa5, 0x26, 0xc5, 0x7a, 0x22, 0x4c, 0x6f, 0x47, 0x41, 0x5f, 0x92, 0xd7, 0x34, 0xd4, 0xc6, 0xe5, 0x28, - 0x2e, 0x33, 0xe4, 0x57, 0xc8, 0x78, 0x53, 0x66, 0x48, 0x72, 0x25, 0xed, 0x6f, 0xbc, 0x2c, 0x62, 0x30, 0x34, 0xc1, - 0x93, 0x18, 0x8c, 0x4c, 0xf0, 0x28, 0x96, 0xe0, 0x08, 0x41, 0x63, 0xe6, 0x99, 0xaf, 0x5f, 0x5a, 0xd5, 0x95, 0xbe, - 0x6e, 0x25, 0x1a, 0x4b, 0x7b, 0x0c, 0x4e, 0x8a, 0x8f, 0x22, 0x84, 0xbf, 0x0d, 0x85, 0x30, 0x83, 0x36, 0x19, 0xc2, - 0x3c, 0x2a, 0x08, 0xa4, 0x61, 0x1e, 0x4d, 0x08, 0x83, 0x26, 0x79, 0x34, 0x22, 0x6c, 0xd0, 0xf1, 0xd0, 0xe4, 0xa9, - 0x86, 0x1d, 0x00, 0x87, 0xd7, 0x6f, 0xb0, 0x95, 0x69, 0x1c, 0xae, 0xc6, 0xa1, 0x09, 0x49, 0x58, 0x1e, 0xc2, 0x2c, - 0x60, 0x73, 0xea, 0x9f, 0x9d, 0x2a, 0xee, 0x23, 0x8f, 0xa8, 0xa6, 0xde, 0x9f, 0x81, 0xac, 0x86, 0x0f, 0x96, 0x6c, - 0x8d, 0xf7, 0x1e, 0x2c, 0xe5, 0xfa, 0x07, 0xf8, 0x93, 0xdb, 0x3f, 0x4a, 0x9f, 0x7e, 0x6b, 0xf4, 0x39, 0x86, 0x62, - 0x3b, 0x4a, 0xa1, 0xcf, 0xce, 0x0f, 0x2e, 0x27, 0xcb, 0xbb, 0x38, 0x48, 0x69, 0xf1, 0x25, 0xc0, 0x9f, 0xe2, 0x20, - 0x03, 0x46, 0x30, 0xc0, 0x1f, 0xe3, 0xa0, 0x60, 0x01, 0xfe, 0x23, 0x0e, 0x46, 0xd9, 0x22, 0xc0, 0x1f, 0xe2, 0x60, - 0x52, 0x04, 0xf8, 0x3d, 0x68, 0x29, 0x53, 0xbe, 0x98, 0x05, 0xf8, 0xf7, 0x38, 0x90, 0xda, 0x0d, 0x00, 0x5f, 0xc6, - 0x01, 0x63, 0x01, 0x7e, 0x17, 0x07, 0x22, 0x0b, 0xf0, 0x75, 0x1c, 0x88, 0x22, 0xc0, 0x8f, 0xe3, 0xa0, 0xa0, 0x01, - 0xbe, 0x8a, 0x03, 0x28, 0x34, 0x09, 0xf0, 0x93, 0x38, 0x80, 0x96, 0x65, 0x80, 0xdf, 0xc6, 0x01, 0xcf, 0x03, 0xfc, - 0x5b, 0x1c, 0xa8, 0x45, 0xf1, 0xf7, 0x42, 0x70, 0x19, 0xe0, 0xa7, 0x71, 0x30, 0xe5, 0x01, 0x7e, 0x13, 0x07, 0x85, - 0x08, 0xf0, 0xeb, 0x38, 0xa0, 0x59, 0x80, 0x5f, 0xc5, 0x41, 0xc6, 0x02, 0xfc, 0x6b, 0x1c, 0xa4, 0x2c, 0xc0, 0x2f, - 0xe3, 0xe0, 0x9e, 0x65, 0x99, 0x08, 0xf0, 0xb3, 0x38, 0x60, 0x79, 0x80, 0x7f, 0x89, 0x83, 0x64, 0x1a, 0xe0, 0x9f, - 0xe2, 0x80, 0x16, 0x5f, 0x64, 0x80, 0x9f, 0xc7, 0x01, 0xa3, 0x01, 0x7e, 0x61, 0x3a, 0x9a, 0x04, 0xf8, 0xe7, 0x38, - 0xb8, 0x9d, 0x06, 0x6b, 0x9c, 0xe7, 0x64, 0xf9, 0x9a, 0x27, 0xec, 0x0f, 0x16, 0x07, 0xe3, 0xd6, 0xf8, 0x6c, 0x3c, - 0x0e, 0x30, 0xcd, 0x15, 0xff, 0x7b, 0xc1, 0x6e, 0x9f, 0x2a, 0x48, 0xa4, 0x6c, 0x94, 0x3e, 0x0c, 0x30, 0xfd, 0x7b, - 0x41, 0xe3, 0x60, 0x3c, 0xd6, 0x05, 0xfe, 0x5e, 0xd0, 0x19, 0x2d, 0xde, 0xb2, 0x38, 0x78, 0x38, 0x1e, 0x8f, 0xd3, - 0x93, 0x00, 0xd3, 0x7f, 0x16, 0x1f, 0x75, 0x0b, 0xba, 0xc0, 0x88, 0xf1, 0x09, 0xd4, 0xed, 0x8e, 0xbb, 0x69, 0x12, - 0xe0, 0x11, 0x97, 0x7f, 0x2f, 0xe0, 0x7b, 0xcc, 0x4e, 0x92, 0x93, 0x00, 0x8f, 0x32, 0x9a, 0x7c, 0x89, 0x83, 0x96, - 0xfe, 0x95, 0xff, 0xc2, 0xd2, 0xd7, 0x33, 0xa1, 0x75, 0xf8, 0x63, 0x36, 0x4a, 0xd2, 0x00, 0xeb, 0xc1, 0x8c, 0xe1, - 0xef, 0x57, 0xfe, 0x8e, 0xa9, 0x38, 0x38, 0xa3, 0x9d, 0x11, 0xeb, 0x04, 0x78, 0xf4, 0xe6, 0x36, 0x8f, 0x03, 0xda, - 0xed, 0xd0, 0x0e, 0x0d, 0xf0, 0x68, 0x51, 0x64, 0xf7, 0xb7, 0x42, 0xa4, 0x00, 0x84, 0xd1, 0xd9, 0xd9, 0xc3, 0x00, - 0x27, 0xf4, 0x57, 0x05, 0xb5, 0xbb, 0xe3, 0x47, 0x8c, 0xb6, 0x02, 0xfc, 0x0b, 0x2d, 0xd4, 0xc7, 0x85, 0xb4, 0x03, - 0x6d, 0x41, 0x8a, 0x48, 0xde, 0x81, 0x7e, 0x3b, 0x48, 0x3b, 0xa7, 0x8f, 0xda, 0x2c, 0xc0, 0xc9, 0xf5, 0x6b, 0xe8, - 0xed, 0xe1, 0xb8, 0xdb, 0x82, 0x8f, 0x1c, 0x04, 0x45, 0x56, 0x40, 0x23, 0xa7, 0x27, 0x8f, 0xba, 0x2c, 0xd5, 0x89, - 0x92, 0x67, 0x5f, 0xf4, 0xec, 0xcf, 0x60, 0x3e, 0x49, 0xc1, 0x67, 0x52, 0xe4, 0x71, 0x90, 0x26, 0xed, 0x93, 0x63, - 0x48, 0xb8, 0xa7, 0xb9, 0x03, 0xce, 0x1d, 0x54, 0x3d, 0x1b, 0x05, 0xf8, 0xce, 0xa4, 0x9e, 0x8d, 0xf4, 0xc7, 0xe4, - 0xdd, 0xaf, 0xf9, 0x9b, 0x34, 0x0e, 0x46, 0x67, 0x67, 0xa7, 0x2d, 0x48, 0xf8, 0x40, 0xef, 0xe3, 0x80, 0x3e, 0x82, - 0xff, 0x20, 0xfb, 0xe3, 0x33, 0xe8, 0x10, 0x46, 0x78, 0x37, 0xf9, 0xe8, 0xe7, 0x7c, 0x99, 0xd2, 0x2f, 0x3c, 0x0e, - 0x46, 0xe9, 0xe8, 0xe1, 0x29, 0xd4, 0x9b, 0xd1, 0xc9, 0x33, 0x45, 0xa1, 0xdd, 0x56, 0x4b, 0xb7, 0xfc, 0x8e, 0x7f, - 0x65, 0xba, 0x7a, 0xb7, 0x7b, 0x3a, 0xea, 0xc0, 0x08, 0xae, 0x41, 0xc3, 0x01, 0xe3, 0x39, 0x4b, 0x74, 0x83, 0xd7, - 0xc9, 0xd3, 0x34, 0x0e, 0x1e, 0x3d, 0x3a, 0xee, 0x24, 0x49, 0x80, 0xef, 0x3e, 0xa6, 0xa6, 0xb6, 0xce, 0x93, 0x00, - 0xfb, 0x38, 0x60, 0x8f, 0x1e, 0x9d, 0x3e, 0xa4, 0xf0, 0xfd, 0x5c, 0xb7, 0x75, 0x36, 0x1e, 0x25, 0x67, 0xd0, 0xd6, - 0xef, 0x30, 0x9d, 0x93, 0xb3, 0xe3, 0x54, 0xf7, 0xf5, 0xbb, 0x1e, 0x75, 0x67, 0x7c, 0x32, 0x3e, 0xd1, 0x99, 0x7a, - 0xa8, 0xe5, 0xe7, 0x6f, 0x2c, 0x0e, 0x12, 0x96, 0xb6, 0x03, 0x7c, 0x67, 0x17, 0xee, 0xd1, 0x49, 0xab, 0x95, 0x1e, - 0x07, 0x38, 0xbd, 0x9c, 0xcf, 0xdf, 0x6a, 0x08, 0xb6, 0x4f, 0x1e, 0x99, 0x6f, 0xf9, 0xe5, 0x1e, 0x9a, 0x1e, 0x69, - 0xa0, 0xa5, 0x7c, 0xa6, 0x5b, 0x3e, 0x7d, 0x04, 0xff, 0xe9, 0x6f, 0xdd, 0x74, 0xf9, 0x2d, 0xd2, 0x89, 0x59, 0x94, - 0x36, 0x7b, 0xd4, 0x82, 0x1a, 0x63, 0xfe, 0x71, 0x54, 0x70, 0x40, 0xa3, 0x51, 0x07, 0xfe, 0x2f, 0xc0, 0xe3, 0xec, - 0xfa, 0xb5, 0xc5, 0xd9, 0xf1, 0x98, 0x8e, 0x5b, 0x01, 0x1e, 0x8b, 0x8f, 0x52, 0x7d, 0xb8, 0xcc, 0xe3, 0xa0, 0xd3, - 0x39, 0x1b, 0xe9, 0x32, 0x8b, 0x5f, 0x24, 0xd7, 0x78, 0xdc, 0xd2, 0xad, 0x4c, 0xe8, 0x5b, 0x39, 0xba, 0x16, 0xb0, - 0x92, 0xf0, 0x5f, 0x80, 0x27, 0xa0, 0x16, 0xb3, 0xad, 0x9c, 0x99, 0xed, 0x30, 0x79, 0xa7, 0x51, 0x33, 0x7d, 0x08, - 0xf0, 0x72, 0xcb, 0x98, 0x52, 0xda, 0xed, 0xb4, 0x02, 0xac, 0x47, 0x7d, 0xd6, 0x82, 0xff, 0x02, 0x6c, 0x20, 0xa7, - 0xe1, 0x3a, 0xf9, 0xf8, 0xec, 0xe5, 0x6d, 0x1c, 0xd0, 0x74, 0x3c, 0x86, 0x25, 0xd1, 0x93, 0x71, 0xc5, 0xa6, 0x22, - 0x67, 0xf7, 0xbf, 0xde, 0xda, 0xed, 0xa2, 0x13, 0x94, 0x85, 0xce, 0xe9, 0xa3, 0xd1, 0x49, 0x80, 0xdf, 0xa6, 0x9c, - 0xe6, 0xb0, 0x4a, 0x49, 0xda, 0x4d, 0xba, 0x89, 0x4e, 0x98, 0x88, 0x38, 0x38, 0x81, 0x25, 0xef, 0x04, 0x98, 0x7f, - 0xbd, 0xbe, 0x37, 0xe8, 0x06, 0xb5, 0x2d, 0x82, 0x8c, 0x5b, 0xec, 0xf4, 0x2c, 0x09, 0x70, 0x46, 0xbf, 0x3e, 0xfb, - 0xb5, 0x88, 0x03, 0x76, 0xca, 0x4e, 0xc7, 0xd4, 0x7d, 0xff, 0x21, 0xa7, 0xba, 0x46, 0x6b, 0xdc, 0x85, 0xa4, 0xdb, - 0x5c, 0x8f, 0xf5, 0x61, 0x32, 0xd6, 0x18, 0xf2, 0x6a, 0x26, 0xf2, 0xe4, 0xe9, 0x78, 0x2c, 0x0c, 0x16, 0x53, 0xd8, - 0x84, 0x9f, 0x00, 0xda, 0x34, 0x4d, 0xcf, 0xd8, 0x69, 0x80, 0x3f, 0x99, 0x5d, 0x62, 0x27, 0xf0, 0xc9, 0x60, 0x36, - 0xb3, 0xbb, 0xfd, 0x93, 0x01, 0x0a, 0xcc, 0x77, 0x4c, 0xc7, 0x34, 0xed, 0x04, 0xf8, 0x93, 0x86, 0x4b, 0x7a, 0x0c, - 0xff, 0x41, 0x01, 0xe8, 0xec, 0x51, 0x8b, 0xb1, 0x47, 0x2d, 0xfd, 0xe5, 0xe7, 0xd9, 0x99, 0x8f, 0x4e, 0x93, 0x76, - 0x80, 0x3f, 0x59, 0x74, 0x1c, 0x8f, 0x69, 0x0b, 0xd0, 0xf1, 0x93, 0x45, 0xc7, 0x4e, 0x6b, 0xd4, 0xa1, 0xfa, 0xdb, - 0x60, 0xcd, 0xd9, 0xc3, 0x84, 0xc1, 0xe4, 0x3e, 0x19, 0x84, 0x7c, 0xf8, 0xf0, 0xec, 0xec, 0xd1, 0x23, 0xf8, 0xd4, - 0x6d, 0x97, 0x9f, 0x52, 0x5d, 0x66, 0x1a, 0xc9, 0x5a, 0xc9, 0x09, 0xd0, 0xc9, 0x4f, 0x7a, 0x8c, 0xe3, 0xf1, 0x98, - 0xb5, 0x02, 0x9c, 0xf1, 0x19, 0x33, 0x98, 0x60, 0x7e, 0xeb, 0x8e, 0x8e, 0x3b, 0x49, 0x7a, 0xdc, 0x09, 0x70, 0xf6, - 0xf6, 0x99, 0x9e, 0x4d, 0x0b, 0x66, 0xef, 0xb6, 0x9c, 0xc3, 0x9a, 0x19, 0x7d, 0x03, 0x83, 0x84, 0x95, 0x86, 0xca, - 0xef, 0x3d, 0x7a, 0x78, 0x7a, 0x9a, 0xa4, 0x30, 0xd0, 0xf7, 0xd0, 0x2d, 0x80, 0xf1, 0xbd, 0xd9, 0x7c, 0x23, 0xda, - 0xed, 0xc2, 0x74, 0xdf, 0xcf, 0x17, 0xc5, 0xfc, 0x55, 0x1c, 0x3c, 0x3a, 0x7e, 0xd8, 0x4a, 0x47, 0x01, 0x7e, 0x6f, - 0x27, 0x78, 0x9c, 0x8c, 0x8e, 0x1f, 0xb6, 0x03, 0xfc, 0x5e, 0xef, 0xb7, 0x87, 0xa3, 0xd3, 0x33, 0x38, 0x37, 0xde, - 0xcb, 0x79, 0xf1, 0x76, 0xa2, 0x0b, 0x8c, 0xe9, 0x23, 0x68, 0xf6, 0x37, 0xbd, 0x1b, 0xd3, 0x36, 0x6c, 0xe4, 0xf7, - 0x7a, 0x93, 0x69, 0x3c, 0x79, 0xd8, 0xee, 0x9e, 0x75, 0x03, 0x3c, 0xe3, 0x69, 0x0e, 0x04, 0x5e, 0x6f, 0x94, 0x47, - 0xed, 0x47, 0x0f, 0x5b, 0x01, 0x9e, 0xbd, 0x55, 0xc9, 0x47, 0x3a, 0xd3, 0xd4, 0x78, 0x0c, 0x30, 0x9b, 0x71, 0xa9, - 0xee, 0xdf, 0x48, 0x4b, 0x8f, 0x59, 0x3b, 0xc0, 0x33, 0x91, 0x24, 0x54, 0xbe, 0x35, 0x09, 0xa3, 0x6e, 0x80, 0x73, - 0xfa, 0x95, 0xfe, 0x25, 0xdc, 0x66, 0x4a, 0x19, 0x4d, 0x75, 0x9a, 0xc6, 0xe1, 0x00, 0xbf, 0x4b, 0xe1, 0x16, 0x2e, - 0x0e, 0xc6, 0xe9, 0xb8, 0x0b, 0xe0, 0x01, 0x02, 0x64, 0xb0, 0x1b, 0xa0, 0x01, 0x5f, 0xe9, 0xe3, 0x51, 0x1c, 0x9c, - 0x8e, 0xce, 0x58, 0xe7, 0x38, 0xc0, 0x25, 0x35, 0xa2, 0x5d, 0xc8, 0xd7, 0x9f, 0x1f, 0xf5, 0x96, 0x3a, 0x31, 0x09, - 0x1a, 0x40, 0x29, 0x7d, 0xd8, 0x4a, 0x4f, 0x03, 0x3c, 0x7f, 0xcd, 0xdc, 0x1e, 0x63, 0x8c, 0x9d, 0x01, 0x2c, 0x21, - 0x49, 0x23, 0xd0, 0xd9, 0x78, 0xf4, 0xe8, 0x4c, 0x7f, 0x03, 0x18, 0xe8, 0x98, 0x31, 0x00, 0xd2, 0xfc, 0x35, 0x2b, - 0x01, 0x91, 0x8e, 0x1e, 0xb6, 0x80, 0xbe, 0xcc, 0xe9, 0x9c, 0xde, 0xd3, 0xdb, 0xa7, 0x73, 0x3d, 0xa7, 0x71, 0xda, - 0x0d, 0xf0, 0xfc, 0xf9, 0x2f, 0xf3, 0xc5, 0x78, 0xac, 0x27, 0x44, 0x47, 0x8f, 0x02, 0x3c, 0x67, 0xc5, 0x02, 0xd6, - 0xe8, 0xac, 0x7b, 0x3c, 0x0e, 0xb0, 0x45, 0xc3, 0xa4, 0x95, 0x8c, 0xe0, 0x9a, 0x71, 0x31, 0x8b, 0x83, 0x34, 0xa5, - 0xad, 0x14, 0x2e, 0x1d, 0xc5, 0xed, 0xaf, 0x85, 0x41, 0x23, 0xa6, 0xf1, 0xc1, 0xae, 0x21, 0xcc, 0x17, 0xe0, 0xf1, - 0x71, 0xc4, 0x92, 0x84, 0xda, 0xc4, 0xd3, 0xd3, 0xe3, 0x63, 0xc0, 0x3d, 0x33, 0x43, 0x83, 0x20, 0x6f, 0xe4, 0xfd, - 0xa8, 0x10, 0x70, 0x74, 0x01, 0x51, 0x05, 0xb2, 0xfa, 0xe6, 0xfe, 0xb5, 0xa6, 0xab, 0xed, 0xd3, 0x47, 0xb0, 0x00, - 0x92, 0xa6, 0xe9, 0x2b, 0x73, 0xb8, 0x9d, 0x8d, 0x4e, 0xba, 0xed, 0xe3, 0x00, 0xbb, 0x8d, 0x40, 0xcf, 0x5a, 0x0f, - 0x3b, 0x50, 0x22, 0x4f, 0xef, 0x4d, 0x89, 0xf1, 0x09, 0x3d, 0x39, 0x6d, 0x05, 0xd8, 0x6d, 0x0d, 0x76, 0x36, 0xea, - 0x3e, 0x84, 0x4f, 0x39, 0x65, 0x59, 0xa6, 0xf1, 0xbb, 0x0b, 0x70, 0x91, 0xfc, 0x59, 0x4e, 0xe3, 0x80, 0xb6, 0xba, - 0x9d, 0x4e, 0x0a, 0x9f, 0xd9, 0x57, 0x56, 0xc4, 0x41, 0xd2, 0x82, 0xff, 0x02, 0xec, 0xed, 0x24, 0x36, 0x0a, 0xb0, - 0xc6, 0xbb, 0x53, 0xda, 0xd5, 0x7b, 0xdf, 0xee, 0xaa, 0xd6, 0x59, 0x0b, 0x36, 0xac, 0xdd, 0x54, 0xf6, 0x4b, 0xe6, - 0xe2, 0xd6, 0x92, 0x58, 0x1a, 0x60, 0x0f, 0x41, 0xc7, 0x0f, 0xc7, 0x01, 0x76, 0x3b, 0xee, 0xe4, 0xf4, 0xac, 0x03, - 0xa4, 0x4c, 0x01, 0xa1, 0x48, 0x3b, 0xa3, 0x13, 0x20, 0x4d, 0x8a, 0xbd, 0x36, 0x78, 0x12, 0x60, 0xf5, 0x54, 0xaa, - 0x57, 0x71, 0x90, 0x9e, 0x8d, 0xc6, 0xe9, 0x59, 0x80, 0x95, 0x98, 0x51, 0x25, 0x34, 0x05, 0x3c, 0x3e, 0x79, 0x18, - 0x60, 0x8d, 0xe6, 0x2d, 0xd6, 0x4a, 0x5b, 0x01, 0xb6, 0x47, 0x09, 0x63, 0x67, 0x1d, 0x98, 0xd6, 0xcf, 0xcf, 0x15, - 0xe0, 0x72, 0xca, 0x46, 0xc7, 0x01, 0x2e, 0xe9, 0xbd, 0x26, 0x44, 0xf0, 0x25, 0x67, 0xe2, 0x8b, 0x65, 0x3d, 0x80, - 0xd4, 0xb9, 0x0d, 0x0f, 0xcb, 0xf0, 0xf2, 0xd6, 0xa0, 0x11, 0xd5, 0x5b, 0xdc, 0xbb, 0x86, 0x7d, 0x42, 0x43, 0xc7, - 0xb6, 0x73, 0xb2, 0x5c, 0xe3, 0x32, 0xba, 0xe9, 0x17, 0x76, 0x2f, 0xc3, 0x1c, 0x4c, 0xe2, 0x6b, 0x29, 0x32, 0x47, - 0xce, 0x9e, 0xdf, 0xba, 0x6c, 0x82, 0x20, 0x29, 0x49, 0xab, 0x27, 0xcf, 0x9d, 0x1b, 0x69, 0x4f, 0x42, 0xcc, 0x03, - 0x48, 0x2f, 0x08, 0x25, 0x0a, 0x42, 0xc3, 0x18, 0x61, 0xd2, 0x59, 0xd7, 0x6b, 0x99, 0x52, 0x18, 0x7b, 0x7d, 0x4a, - 0xa8, 0x0b, 0x0a, 0x0f, 0x77, 0xc4, 0xf9, 0x40, 0x0c, 0x51, 0x4f, 0x10, 0x1d, 0xe2, 0xf9, 0x45, 0xae, 0xc2, 0x3c, - 0x1f, 0x14, 0x43, 0xdc, 0x3e, 0x45, 0x18, 0x82, 0x27, 0x90, 0x81, 0xb8, 0xb8, 0x68, 0x9f, 0x1e, 0x68, 0xa1, 0xef, - 0xe2, 0xe2, 0xcc, 0xfc, 0x80, 0x7f, 0x87, 0x55, 0xc0, 0x6a, 0x18, 0xdf, 0x63, 0xe6, 0x69, 0xf4, 0x34, 0x7f, 0xfd, - 0x98, 0xad, 0x56, 0xe1, 0x63, 0x46, 0x60, 0xc6, 0xf8, 0x31, 0x8b, 0xf4, 0xa5, 0x85, 0x71, 0x8d, 0x21, 0x03, 0xd0, - 0x9c, 0xb5, 0x30, 0x84, 0x51, 0x77, 0x9c, 0xf7, 0x63, 0x36, 0xe0, 0x75, 0xb7, 0xea, 0x2a, 0x76, 0xf1, 0xc1, 0xc1, - 0xb2, 0x88, 0x95, 0x11, 0x13, 0x94, 0x11, 0x13, 0x94, 0x11, 0x13, 0x54, 0x15, 0x3d, 0xfe, 0xa4, 0x0f, 0x52, 0x8a, - 0x56, 0xb6, 0x58, 0x9e, 0xfa, 0x1d, 0xa8, 0x3d, 0x40, 0x3b, 0xd9, 0xaf, 0x94, 0x1d, 0xa5, 0xae, 0x62, 0xa7, 0x02, - 0x63, 0x67, 0xa2, 0xd5, 0x76, 0x1c, 0xfd, 0x3b, 0xea, 0x8e, 0x97, 0x35, 0xb1, 0xec, 0xdd, 0x4e, 0xb1, 0x0c, 0x56, - 0x52, 0x8b, 0x66, 0xfb, 0x26, 0x10, 0x87, 0x1a, 0x3c, 0xd4, 0x82, 0x59, 0x15, 0x1d, 0xae, 0x01, 0x49, 0x3d, 0x90, - 0x42, 0xce, 0xb4, 0x94, 0x56, 0xa0, 0x38, 0x55, 0x61, 0x01, 0x1a, 0x4a, 0xa7, 0xa0, 0x2c, 0x83, 0x98, 0x36, 0x34, - 0x40, 0x72, 0x23, 0xa3, 0x19, 0x59, 0xad, 0x0b, 0xa2, 0x0b, 0x68, 0xc2, 0xb4, 0xc4, 0x02, 0x0d, 0x48, 0xdd, 0x80, - 0xb4, 0x95, 0x41, 0x9c, 0xb1, 0xd9, 0x27, 0x3a, 0x3b, 0xd7, 0xd9, 0x79, 0x99, 0x2d, 0x5c, 0xb6, 0x11, 0x12, 0x85, - 0xce, 0x16, 0x65, 0x36, 0xc8, 0x6c, 0x78, 0x12, 0xe7, 0x78, 0x14, 0x0b, 0x23, 0xaa, 0x55, 0xb2, 0xd5, 0x5b, 0xea, - 0x6b, 0x73, 0x0f, 0x0e, 0xc2, 0x52, 0x4e, 0xd2, 0x6a, 0xe2, 0x07, 0x4b, 0x1e, 0x15, 0x5a, 0x06, 0xe2, 0xd1, 0xc4, - 0xfe, 0x1d, 0xad, 0x37, 0x65, 0xa5, 0x62, 0x32, 0xfa, 0x46, 0x49, 0xf4, 0xd9, 0x29, 0x51, 0x1f, 0x73, 0x1d, 0xfe, - 0xe6, 0x9c, 0x44, 0xad, 0xd6, 0x71, 0xfb, 0xb8, 0x75, 0xd6, 0xe7, 0x87, 0xed, 0x4e, 0xf4, 0xa8, 0x13, 0x6b, 0x45, - 0xc4, 0x5c, 0xdc, 0x82, 0x02, 0xe6, 0xa8, 0x13, 0x9d, 0xa0, 0xc3, 0x76, 0xd4, 0xea, 0x76, 0x9b, 0xf0, 0x0f, 0x7e, - 0xaf, 0xca, 0x6a, 0x27, 0xad, 0x93, 0x6e, 0x9f, 0x1f, 0x6d, 0x54, 0x0a, 0x79, 0x03, 0x0a, 0xa2, 0x23, 0x5d, 0x09, - 0x43, 0xfd, 0x6a, 0x79, 0x9f, 0x6d, 0xe9, 0x79, 0xde, 0xab, 0x30, 0x37, 0xaa, 0x38, 0x80, 0xaa, 0xfb, 0x9a, 0x68, - 0x20, 0xba, 0xaf, 0x51, 0x19, 0xa2, 0x76, 0x59, 0x80, 0xa8, 0xfd, 0x98, 0x87, 0xb2, 0xc1, 0x0e, 0x43, 0x93, 0xaf, - 0xa0, 0x6e, 0x13, 0xc2, 0xc6, 0xe1, 0x89, 0xcd, 0xcd, 0xfd, 0xdc, 0x09, 0x42, 0xcd, 0x1c, 0x72, 0x47, 0x36, 0x57, - 0xf8, 0xb9, 0x23, 0x84, 0x9a, 0x02, 0x72, 0x69, 0xcc, 0x23, 0x0a, 0x39, 0x2a, 0xa2, 0x4d, 0x0d, 0xc9, 0x6a, 0x51, - 0x9e, 0x33, 0x37, 0x6c, 0x3e, 0x86, 0xe5, 0xd1, 0x04, 0xc5, 0x0a, 0xd2, 0x10, 0x35, 0xaf, 0xd2, 0xe6, 0xb4, 0x70, - 0xa9, 0xc6, 0x81, 0x8c, 0x06, 0xfc, 0x73, 0xc8, 0xf4, 0x7b, 0x13, 0xad, 0xfe, 0xf1, 0x69, 0x2b, 0x6e, 0x83, 0x8f, - 0x34, 0xc8, 0xda, 0xd2, 0xc8, 0xda, 0xd2, 0xc9, 0xda, 0xd2, 0xc9, 0xda, 0x20, 0xc0, 0x7b, 0x7d, 0xff, 0x2d, 0x6a, - 0x76, 0x27, 0xbc, 0x34, 0x62, 0x31, 0x56, 0x0a, 0xa1, 0x5a, 0xad, 0x96, 0x6b, 0x30, 0x31, 0x2a, 0x6b, 0x88, 0xbc, - 0x52, 0x7f, 0x2e, 0x8b, 0xb8, 0x85, 0x27, 0x31, 0x68, 0xb9, 0x5b, 0x98, 0xea, 0xcd, 0xed, 0xa8, 0xc2, 0x66, 0xf8, - 0x9a, 0xbe, 0x53, 0x27, 0x5f, 0x90, 0x63, 0xad, 0x3d, 0x5e, 0x16, 0x31, 0x37, 0x34, 0x83, 0x1b, 0x9a, 0xc1, 0x0d, - 0xcd, 0x80, 0x46, 0x70, 0x59, 0x58, 0x97, 0x8d, 0x28, 0x81, 0x2b, 0x81, 0xc1, 0xf1, 0x10, 0xa2, 0xf7, 0x85, 0x8a, - 0xe8, 0x51, 0x6f, 0x74, 0xde, 0x86, 0x68, 0x65, 0xa6, 0xa4, 0x8a, 0xa8, 0x76, 0xda, 0x2e, 0xc7, 0xfc, 0xaa, 0x86, - 0xf6, 0x11, 0x3c, 0x25, 0x73, 0xa9, 0xc2, 0x16, 0xd8, 0x6c, 0x04, 0x45, 0xd0, 0xd7, 0x64, 0x21, 0xd6, 0x3a, 0x1b, - 0x6b, 0x8b, 0xfd, 0x65, 0xc3, 0x05, 0xd6, 0x50, 0x02, 0xff, 0x01, 0x85, 0x2f, 0xac, 0xf2, 0xc9, 0x2f, 0x4d, 0x4d, - 0xad, 0x9d, 0x98, 0x39, 0x12, 0x7a, 0x60, 0x2f, 0xee, 0x82, 0x3d, 0xf5, 0x25, 0x11, 0xb9, 0xf6, 0x56, 0x24, 0x55, - 0xb8, 0x62, 0xf0, 0xde, 0x25, 0x77, 0x54, 0xfb, 0xb2, 0xbc, 0x30, 0x7f, 0x5e, 0x51, 0xcf, 0xd9, 0xaf, 0x98, 0x8c, - 0x9c, 0x8f, 0xec, 0x8d, 0x0e, 0xea, 0x43, 0xf6, 0xf7, 0x8d, 0x29, 0xb7, 0xfe, 0xda, 0xb4, 0xe5, 0xd6, 0x89, 0x3a, - 0x1b, 0x76, 0xa8, 0x5b, 0xa3, 0xbf, 0x9d, 0xab, 0x5a, 0x31, 0x19, 0x21, 0x8f, 0x66, 0x6b, 0xb0, 0xe6, 0x15, 0xb0, - 0xa4, 0xad, 0x57, 0x7a, 0x30, 0x42, 0xef, 0x7a, 0xcc, 0xeb, 0x62, 0x32, 0xda, 0xf9, 0xe6, 0x88, 0xe9, 0xb1, 0xff, - 0x96, 0x7a, 0x3d, 0x38, 0xd5, 0xf6, 0x94, 0xdd, 0x7d, 0xaf, 0xce, 0xed, 0xce, 0x3a, 0x32, 0xfb, 0x5e, 0x9d, 0xa7, - 0xbb, 0xea, 0xcc, 0xf8, 0x5d, 0xe8, 0xf6, 0x8e, 0xf2, 0xd4, 0xd8, 0xda, 0x3e, 0x68, 0x32, 0x82, 0x20, 0xf1, 0xf0, - 0xd7, 0x84, 0x72, 0xe9, 0x39, 0x12, 0x0e, 0xab, 0x20, 0xfa, 0x51, 0x37, 0x66, 0x98, 0x92, 0xce, 0x61, 0xa1, 0x83, - 0xb9, 0xc8, 0x88, 0x36, 0xf3, 0x88, 0xe2, 0x8c, 0x84, 0x21, 0x3d, 0x4c, 0x20, 0x24, 0x4d, 0xbb, 0x4f, 0xe3, 0x90, - 0x36, 0x12, 0x74, 0x14, 0xb6, 0x1b, 0xf4, 0x30, 0x41, 0xa8, 0xd1, 0x06, 0x9d, 0xa9, 0x20, 0xed, 0x66, 0x06, 0x41, - 0x2a, 0x35, 0x29, 0xce, 0x0e, 0x65, 0x54, 0x34, 0xc4, 0x61, 0x1e, 0x15, 0x8d, 0xa8, 0x8b, 0x65, 0x34, 0x29, 0x93, - 0x27, 0x3a, 0x79, 0x62, 0x92, 0x47, 0x65, 0xf2, 0x48, 0x27, 0x8f, 0x4c, 0x32, 0x25, 0xc5, 0xa1, 0x8c, 0x68, 0x23, - 0x6c, 0x37, 0x0b, 0x74, 0x08, 0x23, 0x70, 0xa3, 0x27, 0xd2, 0x8f, 0x0d, 0xbe, 0xd6, 0xc6, 0x35, 0x73, 0x91, 0xd9, - 0x68, 0x9d, 0x15, 0x90, 0x4a, 0x8f, 0x27, 0xa8, 0xf3, 0xcc, 0x03, 0x13, 0x56, 0xe6, 0x8f, 0x8b, 0x45, 0xb7, 0x4e, - 0x32, 0x91, 0x7b, 0x1e, 0x5d, 0x60, 0x84, 0xfe, 0xc5, 0xfa, 0xb1, 0x00, 0x54, 0xd7, 0x34, 0x9b, 0x4f, 0xe9, 0x96, - 0xdb, 0x6c, 0x31, 0x19, 0xd9, 0x9d, 0x55, 0x36, 0xc3, 0x68, 0x61, 0x62, 0x3c, 0xd7, 0x1d, 0x1c, 0x01, 0xd4, 0xce, - 0xa9, 0x32, 0xa2, 0x5a, 0x49, 0x6e, 0x6a, 0x4c, 0x0a, 0x76, 0x2f, 0x13, 0x9a, 0xb1, 0xb0, 0x3a, 0x80, 0xab, 0x61, - 0x32, 0xf2, 0x02, 0x4c, 0xe1, 0x8b, 0xc3, 0xe8, 0xb8, 0xa1, 0xa2, 0xc9, 0x61, 0xd4, 0x7d, 0xd4, 0x50, 0xd1, 0xe8, - 0x30, 0x6a, 0xb7, 0x2b, 0x9c, 0x8d, 0x0a, 0xa2, 0xa2, 0x09, 0x51, 0xa0, 0x31, 0x34, 0x8d, 0x8a, 0x39, 0x05, 0xdb, - 0xae, 0x7f, 0x63, 0x18, 0x0d, 0x3b, 0x8c, 0x9c, 0x4d, 0x4c, 0xb8, 0xcb, 0xad, 0x31, 0xf8, 0xdd, 0x74, 0xba, 0xdd, - 0xa6, 0x8a, 0x0a, 0xac, 0xcc, 0x4a, 0x36, 0x55, 0x34, 0xc1, 0xca, 0x2c, 0x5f, 0x53, 0x45, 0x23, 0xd3, 0x94, 0xd6, - 0x01, 0x82, 0xde, 0xb1, 0x04, 0xd6, 0x73, 0xe6, 0x41, 0xbe, 0xe3, 0xbc, 0x53, 0xd6, 0xa0, 0x35, 0xfc, 0x5e, 0xb9, - 0xa6, 0x2b, 0x28, 0xa9, 0x02, 0x1b, 0x1f, 0xf6, 0xad, 0xa2, 0xed, 0xaa, 0x49, 0xf6, 0xaf, 0xcb, 0x96, 0xcd, 0x16, - 0x42, 0xd5, 0x0b, 0x5e, 0xd6, 0x30, 0xc4, 0x96, 0xb2, 0x07, 0xf7, 0x3f, 0x94, 0x84, 0x10, 0xd4, 0x4e, 0x9f, 0x42, - 0x9c, 0x38, 0x3d, 0x32, 0x24, 0xf1, 0x46, 0x63, 0x8d, 0x42, 0xef, 0xbc, 0x7d, 0xea, 0x53, 0xd5, 0xad, 0x48, 0x77, - 0x84, 0x04, 0x8b, 0xdc, 0xd8, 0x42, 0xa6, 0x81, 0xc7, 0x82, 0x58, 0xed, 0x6e, 0xed, 0x80, 0x38, 0x38, 0xd8, 0x3c, - 0x2f, 0xdc, 0x9b, 0x03, 0x5b, 0xef, 0x0c, 0x54, 0x86, 0x74, 0xee, 0x25, 0x24, 0x63, 0x62, 0xcb, 0x3d, 0x44, 0x71, - 0x31, 0xa7, 0x1e, 0x6a, 0x0a, 0x3f, 0xa8, 0x02, 0xee, 0xd9, 0x9c, 0xe6, 0xa9, 0xce, 0xd0, 0x7d, 0x0d, 0xbd, 0xb1, - 0xbd, 0xf1, 0x27, 0x54, 0x1a, 0x09, 0xfe, 0xcb, 0x8e, 0xbd, 0x4e, 0xec, 0x4b, 0x2d, 0x7e, 0xa3, 0x7f, 0xf9, 0x26, - 0xb9, 0x15, 0x6c, 0xac, 0x33, 0xf6, 0x6a, 0x55, 0x7b, 0x97, 0xc7, 0xbc, 0xfe, 0x82, 0x0e, 0x0e, 0xb8, 0x7c, 0x06, - 0x56, 0xc4, 0x2c, 0x6c, 0xf8, 0x87, 0xef, 0xdf, 0xb5, 0xd3, 0xfa, 0x2f, 0x7d, 0xae, 0xc6, 0xde, 0x41, 0x77, 0x59, - 0xcb, 0xdf, 0xb9, 0x12, 0x7d, 0x15, 0x73, 0xbb, 0xd6, 0x7f, 0x55, 0x36, 0xda, 0x5b, 0x2f, 0x44, 0x1d, 0x1c, 0xf0, - 0x2a, 0x4e, 0x53, 0xf0, 0x43, 0x80, 0xfa, 0x5a, 0x06, 0x79, 0x96, 0x09, 0x0a, 0x37, 0xa2, 0x70, 0xc5, 0x10, 0x37, - 0xf8, 0x91, 0xc2, 0x7f, 0x88, 0xff, 0x4f, 0x8d, 0x1c, 0xaa, 0xb8, 0xc1, 0x3d, 0x01, 0xcc, 0x67, 0x85, 0xaa, 0x08, - 0x89, 0x1a, 0xd2, 0xbe, 0xc9, 0x35, 0x2a, 0x0f, 0x73, 0x3a, 0x9f, 0x67, 0xf7, 0xfa, 0x91, 0x2c, 0x8f, 0xa3, 0xaa, - 0x2e, 0x9a, 0x6c, 0x78, 0x3a, 0x5c, 0x00, 0x4f, 0x0f, 0xb8, 0x87, 0xb4, 0x7b, 0x69, 0x79, 0xb9, 0x2d, 0x11, 0x48, - 0x66, 0x39, 0x11, 0xcd, 0x76, 0x2f, 0xbf, 0x00, 0xb9, 0xac, 0xd9, 0x44, 0xca, 0x46, 0xed, 0xc6, 0x1c, 0x64, 0xb2, - 0xdc, 0xb8, 0x90, 0xee, 0x99, 0x82, 0x20, 0xb9, 0x09, 0x2d, 0xb2, 0xed, 0x2e, 0xc5, 0xc7, 0x21, 0xa0, 0x11, 0x32, - 0x02, 0x9f, 0x2f, 0x2c, 0x72, 0xe0, 0x3a, 0x0b, 0xd7, 0xf1, 0x37, 0x5a, 0x2a, 0x06, 0xf9, 0x70, 0x88, 0x0b, 0xfd, - 0x2e, 0x44, 0x39, 0x1f, 0xb8, 0x69, 0x2a, 0xdf, 0x19, 0xf2, 0x44, 0x14, 0xbe, 0x5a, 0xed, 0xc3, 0x33, 0x3e, 0xb6, - 0x4d, 0xf0, 0x39, 0xb5, 0x3f, 0xab, 0x27, 0x3b, 0x60, 0x1c, 0x8c, 0xb4, 0xf4, 0x45, 0xa1, 0x95, 0x37, 0xd9, 0xb9, - 0xec, 0x35, 0x1a, 0x4c, 0x47, 0x58, 0x22, 0x10, 0x4e, 0x0d, 0x1c, 0x02, 0xe1, 0x8f, 0x09, 0x9a, 0x24, 0x99, 0x09, - 0x3d, 0x07, 0x31, 0xb1, 0x6b, 0x09, 0xab, 0x55, 0x6e, 0x42, 0x9b, 0xe8, 0x1c, 0x13, 0xe4, 0xa4, 0xec, 0xa7, 0x8c, - 0xa1, 0x5a, 0x99, 0x71, 0x70, 0xbb, 0xd5, 0xdf, 0x56, 0xfb, 0x79, 0x8f, 0x9b, 0x6b, 0x3c, 0xae, 0x03, 0x06, 0x68, - 0x40, 0x2d, 0x37, 0x36, 0xb8, 0x31, 0x70, 0x0f, 0x8d, 0x35, 0x2e, 0xdb, 0x84, 0xa0, 0x2c, 0x1d, 0xe4, 0xcd, 0xcd, - 0xad, 0x0b, 0x18, 0x98, 0xeb, 0x39, 0xe5, 0x48, 0x0d, 0x40, 0x8e, 0x1e, 0x12, 0xe8, 0xdc, 0xfc, 0xac, 0xe8, 0x42, - 0x25, 0x13, 0x97, 0x63, 0xfc, 0xc5, 0xbb, 0xcd, 0x1b, 0x04, 0x37, 0x37, 0x7a, 0x93, 0xdf, 0xdc, 0x04, 0xd8, 0xb7, - 0x2a, 0x0f, 0x3c, 0x5e, 0x30, 0x18, 0x96, 0x31, 0xa5, 0xf4, 0xc6, 0x6f, 0xb6, 0xab, 0xc6, 0xde, 0xd3, 0x0a, 0xef, - 0x60, 0x79, 0x74, 0xe3, 0x5b, 0x5e, 0x98, 0x03, 0x0e, 0xf0, 0x66, 0x03, 0x3e, 0xec, 0xbd, 0x09, 0x73, 0x74, 0x70, - 0xf0, 0x26, 0x14, 0xa8, 0x7f, 0xcd, 0xf4, 0x9d, 0x1b, 0xb8, 0x61, 0x0f, 0xb8, 0x1e, 0xbe, 0xf0, 0x10, 0xe0, 0x9a, - 0x6d, 0x4a, 0x36, 0x6f, 0x75, 0xd0, 0x8b, 0x18, 0x82, 0x6a, 0x43, 0x68, 0x5f, 0x0b, 0x12, 0xe8, 0xf5, 0x8d, 0x0f, - 0xed, 0x1e, 0x23, 0x0c, 0x58, 0xf8, 0xd2, 0x49, 0x8e, 0x45, 0x33, 0x56, 0x4c, 0x58, 0xb1, 0x5a, 0xbd, 0xa7, 0xc6, - 0xf1, 0x6d, 0x23, 0x46, 0x63, 0xde, 0x6b, 0x34, 0xa8, 0x1e, 0x3f, 0x88, 0x0f, 0x74, 0x88, 0xf7, 0xdf, 0x84, 0x05, - 0x42, 0x60, 0x61, 0xc4, 0xf3, 0x85, 0x73, 0xf2, 0x4a, 0x6a, 0xeb, 0x52, 0xa0, 0xb2, 0x91, 0x8c, 0xb4, 0xf0, 0x94, - 0x24, 0xe5, 0x1a, 0x9d, 0x4f, 0x7b, 0x8d, 0x46, 0x86, 0x44, 0x98, 0x0c, 0xb2, 0x21, 0xe6, 0xb8, 0x80, 0xcb, 0xd4, - 0xed, 0x75, 0x98, 0xb3, 0x1a, 0xe5, 0xb2, 0xf3, 0x5d, 0x9a, 0xb1, 0xc6, 0x8f, 0xe9, 0xda, 0x03, 0xc6, 0x63, 0xea, - 0x11, 0x89, 0x5d, 0x40, 0x96, 0x06, 0xc8, 0xb9, 0x03, 0xb2, 0xd4, 0x40, 0xce, 0x51, 0x7f, 0x0e, 0xd1, 0x8a, 0x72, - 0x14, 0x6f, 0x51, 0xf4, 0x7a, 0x5c, 0x4d, 0xeb, 0xb3, 0x81, 0xb9, 0x0e, 0xed, 0x60, 0x97, 0x03, 0x1e, 0x3a, 0xb1, - 0x6e, 0x80, 0x39, 0x59, 0x06, 0x81, 0x0e, 0x31, 0x8b, 0xef, 0xf4, 0x9f, 0xe8, 0x0e, 0xdf, 0x9b, 0x1f, 0xf7, 0x9e, - 0x32, 0xe9, 0x79, 0x4d, 0xdb, 0xc0, 0x6d, 0x40, 0xb6, 0x20, 0x0a, 0x00, 0xad, 0x6d, 0x74, 0x41, 0x59, 0x7f, 0x70, - 0x2d, 0x37, 0x71, 0x20, 0x64, 0x83, 0xe4, 0x58, 0x7a, 0xa4, 0xf3, 0xcf, 0x3f, 0x03, 0xd4, 0x97, 0x10, 0xc6, 0xc7, - 0x9e, 0x6c, 0xcd, 0x36, 0x6a, 0x04, 0x51, 0x10, 0x87, 0x2e, 0x4a, 0x04, 0xec, 0x8c, 0x20, 0xf0, 0x1e, 0x5b, 0x29, - 0x87, 0xf1, 0xa1, 0x36, 0x0c, 0x3d, 0xa8, 0x2a, 0xee, 0xc5, 0xc5, 0x72, 0x33, 0xca, 0x90, 0x86, 0xaa, 0xd4, 0x21, - 0x5e, 0x90, 0x79, 0x81, 0x8c, 0x11, 0x76, 0x70, 0xc0, 0x06, 0x72, 0xe8, 0x3d, 0x29, 0x56, 0x5d, 0x87, 0x2b, 0x7f, - 0xe1, 0x42, 0x9a, 0x0f, 0xd4, 0x70, 0xb5, 0x32, 0x7f, 0xc9, 0x07, 0x2d, 0xcd, 0xc0, 0xdb, 0x70, 0xde, 0x6d, 0xbc, - 0xdc, 0x2d, 0x8b, 0x45, 0x4a, 0xfc, 0x0e, 0x56, 0x83, 0x2e, 0x68, 0x9f, 0x9d, 0x6a, 0xdb, 0x41, 0x7d, 0xae, 0x35, - 0x0a, 0x5e, 0xc8, 0xdc, 0xea, 0x48, 0xc3, 0x73, 0xe5, 0xe7, 0xd5, 0x42, 0xdf, 0x26, 0x79, 0x19, 0xc1, 0x14, 0x8e, - 0x94, 0x08, 0xcc, 0xc6, 0x35, 0x9d, 0x84, 0x1f, 0x75, 0x2a, 0x69, 0x59, 0x48, 0x80, 0x02, 0x47, 0xfa, 0x72, 0x5e, - 0x47, 0xa8, 0x67, 0x68, 0x07, 0x91, 0xf3, 0x4c, 0x68, 0xea, 0xb2, 0xa5, 0x0d, 0x25, 0x15, 0xcc, 0xc4, 0x42, 0xb2, - 0xc5, 0x1c, 0xce, 0xf7, 0x32, 0x2d, 0xc9, 0x78, 0xf2, 0xa5, 0x9e, 0x02, 0xe6, 0x9f, 0x77, 0x6a, 0xc6, 0xf2, 0x45, - 0x60, 0xe7, 0xf9, 0xca, 0x88, 0xfb, 0x6f, 0x5e, 0xe0, 0xc7, 0xa4, 0x73, 0xf8, 0x0a, 0x7f, 0xa4, 0xe4, 0x71, 0xe3, - 0x15, 0x9e, 0x70, 0x62, 0x78, 0x83, 0xe8, 0xcd, 0xeb, 0xeb, 0x17, 0xef, 0x5e, 0xbc, 0x7f, 0x7a, 0xf3, 0xe2, 0xd5, - 0xb3, 0x17, 0xaf, 0x5e, 0xbc, 0xfb, 0x88, 0xff, 0xa6, 0xe4, 0xd5, 0x51, 0xfb, 0xac, 0x85, 0x3f, 0x90, 0x57, 0x47, - 0x1d, 0x7c, 0xa7, 0xc8, 0xab, 0xa3, 0x13, 0x9c, 0xe5, 0xe4, 0xd5, 0x61, 0xe7, 0xe8, 0x18, 0x2f, 0x94, 0x69, 0x32, - 0x13, 0x93, 0x76, 0x0b, 0xff, 0x6d, 0xbf, 0x40, 0xbc, 0xaf, 0x66, 0x31, 0x61, 0x9b, 0xc6, 0x0f, 0x50, 0x86, 0x8e, - 0xa4, 0x36, 0x44, 0x39, 0xf7, 0xd0, 0x69, 0x9a, 0xfb, 0xe8, 0x64, 0x62, 0x28, 0x83, 0x0d, 0x23, 0xa0, 0x15, 0x27, - 0xb6, 0x1d, 0x7e, 0xd4, 0x66, 0xc7, 0x40, 0x9f, 0x78, 0x29, 0x1c, 0x97, 0x2a, 0x9c, 0xb6, 0xd5, 0x62, 0x8c, 0x33, - 0x21, 0x8a, 0x70, 0x01, 0x8c, 0x80, 0xd6, 0x5a, 0xf0, 0xa3, 0x32, 0x58, 0x93, 0x3c, 0x27, 0xed, 0x7e, 0x3b, 0x96, - 0xe7, 0xa4, 0xd3, 0xef, 0xc0, 0x9f, 0x6e, 0xbf, 0x1b, 0xb7, 0x5b, 0xe8, 0xd0, 0x1b, 0xc7, 0x1f, 0x35, 0xb4, 0x1e, - 0x0c, 0xb1, 0xed, 0x42, 0xfe, 0x5d, 0x28, 0xa7, 0xd2, 0x93, 0x56, 0x1d, 0xdb, 0xee, 0xc9, 0x73, 0xa6, 0xf5, 0xb0, - 0xfc, 0x07, 0x40, 0x6d, 0xed, 0x4f, 0x52, 0x6e, 0x1c, 0xfb, 0x8b, 0x1f, 0x49, 0x54, 0x8b, 0x08, 0x13, 0xb2, 0x55, - 0x0b, 0x01, 0xd3, 0xa8, 0xb3, 0xc1, 0x1c, 0x28, 0x92, 0xa2, 0x50, 0x2e, 0xaa, 0x7d, 0xde, 0x14, 0x28, 0x9a, 0x8b, - 0x79, 0x58, 0x53, 0x35, 0xfc, 0xea, 0x99, 0x39, 0xee, 0x73, 0xf9, 0x8a, 0xbe, 0x0a, 0x6b, 0x3c, 0x8f, 0xcf, 0xda, - 0xf9, 0xdb, 0xe2, 0x17, 0x6b, 0x45, 0x51, 0x03, 0x57, 0x09, 0x58, 0x37, 0xaa, 0xa6, 0x3a, 0x87, 0xe7, 0xfb, 0x58, - 0x43, 0x5d, 0x10, 0x8f, 0x7a, 0xfe, 0x54, 0x9a, 0x71, 0x95, 0xca, 0x68, 0xa7, 0x88, 0xd6, 0x66, 0x41, 0x4e, 0x11, - 0x7d, 0x9e, 0x6b, 0x20, 0x08, 0xc2, 0x07, 0x72, 0x08, 0x07, 0xbe, 0x19, 0xa0, 0xd0, 0x74, 0x0e, 0xd4, 0x4a, 0x95, - 0x99, 0x90, 0xfe, 0xd4, 0xb1, 0x09, 0x40, 0xf3, 0x54, 0xa9, 0xa0, 0xf4, 0x27, 0x16, 0xc8, 0x1b, 0xfa, 0x6f, 0xfe, - 0x06, 0x38, 0x0c, 0x35, 0x2a, 0xfa, 0x76, 0x35, 0xb2, 0x9e, 0xdf, 0x3e, 0x6b, 0x1d, 0xbd, 0xf2, 0xf2, 0xd3, 0xdc, - 0xd9, 0x7b, 0xfc, 0xe5, 0x51, 0x72, 0x13, 0x4d, 0xab, 0x8d, 0x5d, 0x20, 0xb4, 0x9e, 0x0f, 0x90, 0x43, 0x85, 0x8e, - 0xf4, 0x4b, 0x86, 0x3d, 0xa4, 0x0e, 0x49, 0xbb, 0x05, 0xd1, 0xcb, 0x76, 0x50, 0xbe, 0x9f, 0x36, 0x60, 0xaa, 0xa2, - 0xbb, 0x26, 0xd0, 0x6a, 0x78, 0xdc, 0xe8, 0xbe, 0xc9, 0xa3, 0x7b, 0x9c, 0x7b, 0x38, 0xc3, 0x0e, 0x59, 0x43, 0x1e, - 0x4a, 0x64, 0xa3, 0xbe, 0x9a, 0x0d, 0xa0, 0x68, 0xde, 0x31, 0x8f, 0xec, 0x39, 0xe3, 0xa8, 0xf3, 0x66, 0xd4, 0x3d, - 0x7c, 0x75, 0x70, 0x10, 0x8a, 0x06, 0x79, 0x8c, 0xf0, 0x92, 0x82, 0x11, 0x35, 0x38, 0x9d, 0x71, 0xc3, 0xc4, 0xc7, - 0xb9, 0x47, 0x1d, 0x17, 0x79, 0xed, 0x58, 0xab, 0x3a, 0x2b, 0x77, 0x83, 0x1b, 0x53, 0x07, 0x35, 0xbc, 0x34, 0x33, - 0xba, 0x4e, 0x0d, 0xca, 0x35, 0x0f, 0x31, 0xd8, 0x96, 0x8d, 0x8f, 0x14, 0xfd, 0xf0, 0xb8, 0xf9, 0xca, 0x9b, 0x70, - 0xcd, 0x34, 0xe9, 0x71, 0xe3, 0x31, 0xfa, 0xe1, 0xb1, 0xe7, 0xe3, 0xc7, 0x2b, 0xf6, 0xc4, 0x71, 0x23, 0x3f, 0x19, - 0xae, 0xf4, 0x27, 0x90, 0xec, 0x0b, 0xf2, 0x13, 0x60, 0x39, 0x25, 0x3f, 0x85, 0xa2, 0x99, 0x83, 0x41, 0xd7, 0x4f, - 0x61, 0x01, 0x3f, 0x32, 0xf2, 0x53, 0x08, 0xd8, 0x8e, 0xa7, 0xfa, 0x47, 0x51, 0xbd, 0xae, 0x0a, 0x6a, 0x14, 0xe3, - 0x5e, 0x56, 0xac, 0x56, 0xf2, 0xe0, 0x40, 0x98, 0x5f, 0xf4, 0x22, 0x39, 0x38, 0xc8, 0xce, 0xa7, 0x9e, 0xed, 0xad, - 0xda, 0x45, 0x5f, 0x34, 0x42, 0x61, 0xcf, 0x34, 0x8d, 0xfb, 0x33, 0xfe, 0xe4, 0x53, 0x56, 0xdd, 0x40, 0xf3, 0xb8, - 0xf3, 0xf0, 0xf4, 0x0c, 0xc3, 0xbf, 0x0f, 0xbd, 0x82, 0x3f, 0x97, 0x7c, 0x17, 0x69, 0xb3, 0xe6, 0x69, 0x85, 0x6c, - 0x17, 0x1e, 0x3e, 0x63, 0x86, 0x9a, 0xf2, 0xe0, 0x80, 0x9f, 0x7b, 0xb8, 0x8c, 0x19, 0x6a, 0x78, 0x16, 0x7b, 0x0f, - 0x4a, 0x7b, 0x32, 0xcd, 0x35, 0xc1, 0xab, 0xb6, 0x7c, 0x50, 0x0c, 0xcf, 0x95, 0xa5, 0x26, 0x7e, 0xec, 0xeb, 0x9c, - 0xb4, 0xec, 0x26, 0xeb, 0xc9, 0x66, 0x7e, 0xd1, 0xee, 0x21, 0x41, 0xf2, 0x86, 0xbc, 0xb8, 0x68, 0x63, 0x50, 0xc9, - 0xf7, 0x73, 0x22, 0x62, 0x49, 0x9c, 0x7f, 0xde, 0x32, 0x13, 0x71, 0x8e, 0xa7, 0x3c, 0x2e, 0xe5, 0xec, 0xd7, 0xce, - 0x7a, 0x5a, 0x7b, 0x4c, 0xea, 0x9e, 0x19, 0x96, 0xfd, 0xbc, 0xf4, 0xf4, 0x83, 0x4d, 0x9a, 0x0f, 0xe1, 0xd1, 0xc0, - 0x12, 0xf3, 0x98, 0x71, 0x6f, 0x63, 0x10, 0x94, 0x39, 0x6f, 0xb4, 0x21, 0x13, 0x3e, 0xd7, 0x71, 0x0e, 0x03, 0xd5, - 0x85, 0xcf, 0x81, 0x4c, 0x25, 0x95, 0x61, 0xb6, 0x6b, 0x18, 0x0a, 0x48, 0x28, 0x70, 0x41, 0x98, 0x27, 0xc1, 0xc3, - 0xed, 0x87, 0x47, 0x38, 0xea, 0xe4, 0xc2, 0x4c, 0xee, 0x3c, 0x87, 0xee, 0xe4, 0xf0, 0x5c, 0xf5, 0x90, 0x6c, 0x34, - 0x2c, 0xb7, 0x7d, 0x21, 0xf5, 0x20, 0x9a, 0xed, 0xe1, 0x05, 0xeb, 0xa1, 0xbc, 0xd9, 0x2c, 0x0d, 0x20, 0x2f, 0x5a, - 0xab, 0x55, 0x7e, 0xee, 0x1a, 0xe9, 0xbb, 0x73, 0x5c, 0xf3, 0x5d, 0x4e, 0xf0, 0xfc, 0x4d, 0x90, 0x41, 0x00, 0x54, - 0x15, 0xf8, 0x6c, 0x31, 0x0f, 0x70, 0xa0, 0xdf, 0x93, 0x83, 0xbf, 0xfa, 0x1d, 0xb0, 0x00, 0x07, 0xf6, 0x89, 0xb9, - 0x60, 0x58, 0x0d, 0x96, 0x27, 0x65, 0x74, 0x74, 0x1e, 0xdd, 0x00, 0xe3, 0xa0, 0xfe, 0x02, 0x4e, 0xbb, 0xfc, 0x1d, - 0x65, 0x36, 0x4e, 0x88, 0x74, 0xaf, 0x9e, 0xd9, 0x51, 0xad, 0x77, 0x7b, 0x66, 0x72, 0x1c, 0xb8, 0xaa, 0xf0, 0x7a, - 0xc0, 0x77, 0x9e, 0x5d, 0x6c, 0xdb, 0xd7, 0xbe, 0x97, 0x65, 0x0f, 0xc0, 0x79, 0xaf, 0xd7, 0x08, 0xff, 0x26, 0x76, - 0x3e, 0xfd, 0x1b, 0xdc, 0x88, 0xfc, 0x09, 0x55, 0x34, 0x68, 0xbc, 0xd6, 0x86, 0x6f, 0x46, 0xce, 0xea, 0x7d, 0x6b, - 0x1c, 0xec, 0xdf, 0xea, 0x1e, 0x22, 0x37, 0xd4, 0x5e, 0x29, 0x32, 0xb2, 0xaf, 0x8e, 0xd7, 0x21, 0x3c, 0xd3, 0xb7, - 0x1d, 0xf0, 0x70, 0x63, 0xa4, 0xe0, 0x4f, 0x6c, 0xf8, 0x24, 0x0a, 0x21, 0x51, 0x6b, 0x5e, 0xcc, 0x90, 0x62, 0xfa, - 0xd0, 0x1e, 0xaf, 0x6b, 0xe4, 0x73, 0xdd, 0xe3, 0xbc, 0x4e, 0x4c, 0xab, 0x6e, 0xb4, 0xd4, 0xc1, 0x36, 0x59, 0x70, - 0x56, 0xf5, 0xae, 0x25, 0x94, 0xea, 0x41, 0x37, 0xfd, 0x28, 0x67, 0xb3, 0xad, 0x5f, 0x39, 0x36, 0xcf, 0xbe, 0xe5, - 0x60, 0xc8, 0xbb, 0x5f, 0x46, 0xab, 0xba, 0x80, 0x63, 0x37, 0xf4, 0x20, 0x2b, 0xc8, 0xc5, 0xd2, 0x3e, 0xc9, 0xc6, - 0x07, 0x62, 0xb8, 0x2e, 0x1f, 0x68, 0xf3, 0xf0, 0xa0, 0x1a, 0xa9, 0x4c, 0x7c, 0xce, 0xc0, 0xbd, 0x6e, 0x58, 0xd3, - 0x0f, 0xf1, 0x7f, 0xe0, 0x80, 0xaf, 0x90, 0x34, 0x36, 0xea, 0x27, 0x78, 0x38, 0x09, 0x14, 0xde, 0xa6, 0xee, 0x27, - 0xe1, 0x7b, 0xa8, 0xd6, 0x75, 0x2a, 0xc6, 0x09, 0xb4, 0xae, 0x58, 0x29, 0x0b, 0x7b, 0xc7, 0x5d, 0x88, 0xd6, 0xb1, - 0x75, 0x18, 0xb5, 0xaf, 0x2d, 0x5d, 0xe6, 0xe0, 0xff, 0xc2, 0x45, 0xfe, 0xac, 0x80, 0xf0, 0x59, 0xbe, 0x3e, 0xed, - 0x67, 0xe1, 0x3f, 0x27, 0x3c, 0x80, 0x7b, 0xc2, 0x92, 0xe7, 0x2c, 0x9f, 0xc0, 0x86, 0x05, 0xca, 0x81, 0x42, 0xe5, - 0x58, 0xae, 0x56, 0xa1, 0xd4, 0x41, 0x15, 0x6c, 0x4c, 0x5d, 0xfb, 0x78, 0x86, 0xd6, 0xdf, 0x41, 0x5d, 0xec, 0xd4, - 0x23, 0xda, 0x84, 0x15, 0xf9, 0x97, 0x4e, 0x79, 0xe2, 0xf5, 0xb5, 0xab, 0x0f, 0x59, 0x4d, 0xb9, 0x1f, 0x6a, 0x7d, - 0xef, 0x3b, 0x3e, 0x63, 0x62, 0x01, 0xaf, 0x16, 0x61, 0x46, 0x24, 0x53, 0xee, 0x1b, 0x28, 0x08, 0x84, 0x9c, 0xe3, - 0x3e, 0x3e, 0x02, 0x5f, 0xe5, 0x68, 0x9d, 0x48, 0xdc, 0x5b, 0x18, 0x81, 0x8e, 0x55, 0x19, 0xf4, 0x03, 0x70, 0x5a, - 0x02, 0x11, 0x8a, 0x90, 0x80, 0xe5, 0x69, 0xd0, 0x0f, 0xb4, 0x8f, 0x54, 0x00, 0x56, 0x63, 0xa0, 0xe4, 0x0e, 0xf0, - 0x3c, 0xaf, 0x88, 0x98, 0x5f, 0x53, 0x79, 0x95, 0x58, 0xac, 0xcd, 0xb4, 0x8f, 0x3a, 0x15, 0x08, 0x8b, 0x64, 0x53, - 0x50, 0x56, 0x1b, 0xea, 0x02, 0x2c, 0x88, 0xc6, 0x58, 0x1e, 0xdd, 0x00, 0x37, 0xc7, 0x52, 0x5b, 0x74, 0xc9, 0xaf, - 0x41, 0x3d, 0x1d, 0x17, 0xf8, 0x46, 0x33, 0x6c, 0x69, 0x4c, 0xd7, 0x84, 0xe3, 0x84, 0x14, 0x11, 0xbd, 0x83, 0xa0, - 0x12, 0x33, 0x9e, 0xc7, 0x19, 0x9e, 0xd1, 0xbb, 0x78, 0x8a, 0x67, 0x3c, 0x7f, 0x62, 0x96, 0x3d, 0x4e, 0x21, 0xc9, - 0x7d, 0x2c, 0xd6, 0x44, 0xbf, 0x89, 0xf5, 0xbb, 0x64, 0xc5, 0x63, 0xe0, 0x55, 0x64, 0x88, 0x7a, 0xa9, 0xb6, 0x29, - 0x67, 0xaa, 0x32, 0x5e, 0x7f, 0xad, 0x42, 0x8a, 0x13, 0x9c, 0xa1, 0x28, 0x13, 0x98, 0xf5, 0x65, 0xfc, 0x1a, 0x02, - 0x4a, 0x27, 0xd8, 0xbc, 0xa7, 0xc5, 0xef, 0x58, 0xf6, 0x4c, 0x14, 0xef, 0xf5, 0x96, 0xcf, 0x10, 0x14, 0x02, 0x17, - 0x15, 0xd9, 0x84, 0xdb, 0xbd, 0x45, 0x5f, 0x54, 0x4d, 0xd1, 0x3b, 0xd3, 0x94, 0x1d, 0xe2, 0x14, 0x22, 0xf1, 0x46, - 0x53, 0xde, 0x68, 0x63, 0xd6, 0x6f, 0x7d, 0xa7, 0xd1, 0x29, 0x2a, 0x4b, 0x22, 0x0c, 0x4f, 0x04, 0x37, 0xf3, 0x58, - 0x10, 0xd9, 0xcc, 0xad, 0x84, 0xb7, 0xd4, 0xc0, 0x8e, 0x73, 0x9c, 0x88, 0x45, 0xae, 0x62, 0xe1, 0xe1, 0x0d, 0xad, - 0x36, 0xd7, 0xf2, 0xce, 0x40, 0x4c, 0xe1, 0x7b, 0xf3, 0x83, 0xe1, 0x1b, 0xad, 0xe2, 0x7f, 0x0b, 0x86, 0x3d, 0x32, - 0x96, 0x00, 0x3f, 0x30, 0x9c, 0x05, 0xc8, 0x19, 0x7e, 0xf2, 0x0e, 0xc0, 0x67, 0x58, 0xc8, 0x7b, 0x48, 0x65, 0x3a, - 0xf5, 0x1e, 0x52, 0x19, 0xa4, 0x6a, 0x57, 0xf2, 0x7d, 0x59, 0x29, 0x8b, 0xfc, 0x06, 0x49, 0x8e, 0x4b, 0x75, 0xb0, - 0x20, 0x32, 0x82, 0x76, 0xb5, 0x28, 0x37, 0xe3, 0x39, 0xc4, 0x14, 0x84, 0xc6, 0xcd, 0x37, 0xbd, 0x83, 0xef, 0x7b, - 0x93, 0xcf, 0x5c, 0xfe, 0xbd, 0xc9, 0xd7, 0x1d, 0x39, 0x8c, 0xaf, 0xdf, 0x76, 0x6a, 0xcb, 0x78, 0x61, 0xb1, 0xf6, - 0x43, 0xf9, 0x82, 0x4b, 0x4b, 0xbf, 0x94, 0x4d, 0xda, 0x78, 0xe2, 0x21, 0x65, 0xb3, 0xe2, 0xe1, 0x3a, 0xb8, 0xdd, - 0x3a, 0x0c, 0x79, 0x93, 0xb4, 0x11, 0x3a, 0xb4, 0xc2, 0x55, 0x1e, 0x6a, 0xc9, 0xe9, 0xf0, 0xf1, 0x11, 0xdc, 0xbd, - 0xcc, 0xf2, 0x0d, 0x5f, 0x29, 0x53, 0xad, 0xd9, 0x6e, 0x1d, 0xf2, 0x9d, 0x55, 0x1a, 0x6d, 0x3c, 0x63, 0x64, 0x09, - 0xce, 0x65, 0xb4, 0x30, 0xaa, 0x06, 0xf0, 0x21, 0x7d, 0x91, 0xff, 0xb6, 0xa0, 0xa9, 0xfe, 0x3e, 0x34, 0x29, 0xaf, - 0x17, 0xca, 0x25, 0x35, 0x39, 0x0c, 0xa2, 0x83, 0x6c, 0x49, 0x2f, 0x27, 0xe4, 0x47, 0x24, 0xea, 0xa2, 0xf3, 0x76, - 0x3f, 0xea, 0x1e, 0xf2, 0x43, 0x1e, 0x03, 0x0f, 0x1b, 0x36, 0x5d, 0x85, 0x66, 0xdb, 0xd5, 0xb9, 0x5a, 0x8c, 0x78, - 0x62, 0x9b, 0xaf, 0x3a, 0x28, 0x53, 0xcd, 0x1c, 0x21, 0x0b, 0x50, 0xcc, 0xf5, 0xe2, 0x65, 0xd7, 0xbb, 0x39, 0xe4, - 0x31, 0xf4, 0x03, 0xb5, 0x3a, 0xa6, 0x56, 0x39, 0xb8, 0xdf, 0x16, 0x80, 0x60, 0xae, 0xa3, 0xda, 0x5c, 0x4c, 0x7a, - 0x33, 0xac, 0x3a, 0x3b, 0xe4, 0xd5, 0x08, 0xfd, 0x32, 0xdb, 0xfd, 0xb9, 0xa9, 0x55, 0x5d, 0x1e, 0x7a, 0x10, 0xf9, - 0x6d, 0xc1, 0x73, 0xbf, 0x53, 0xbf, 0x5b, 0x9b, 0xe3, 0x77, 0x5a, 0x9f, 0xa5, 0x57, 0x64, 0xbb, 0xd7, 0xad, 0x99, - 0xd6, 0x67, 0x7b, 0x0d, 0x3e, 0x82, 0x30, 0x29, 0xbd, 0xd2, 0x89, 0x90, 0x21, 0x3f, 0xfc, 0x80, 0x6c, 0xeb, 0xaf, - 0x17, 0xca, 0xe5, 0x97, 0x88, 0x00, 0xd9, 0x55, 0xd7, 0x65, 0x75, 0xe8, 0xa3, 0x6c, 0xe2, 0xd5, 0x21, 0xf7, 0x56, - 0xee, 0xe9, 0xdd, 0x5c, 0xc4, 0x0e, 0x5f, 0xfb, 0xad, 0x78, 0x0b, 0x39, 0x81, 0x78, 0xd8, 0xee, 0xfc, 0xb2, 0x20, - 0x67, 0x37, 0xb7, 0x50, 0xd2, 0x9f, 0xb8, 0x2b, 0xfd, 0x81, 0x99, 0xeb, 0x06, 0x7e, 0x1e, 0x75, 0x61, 0xea, 0x9b, - 0x3d, 0x1c, 0x76, 0xa0, 0x0f, 0x0d, 0x87, 0xcd, 0x06, 0x5d, 0x66, 0x05, 0x91, 0x2b, 0x5e, 0x18, 0x3c, 0xbb, 0x20, - 0xed, 0x3e, 0x8f, 0xed, 0x66, 0xd2, 0xa2, 0x51, 0xbb, 0xc9, 0xbd, 0x99, 0x01, 0x7e, 0xd9, 0xb2, 0x7e, 0x11, 0xb7, - 0x4e, 0x1e, 0x94, 0x5c, 0xb1, 0x6a, 0x7d, 0x2a, 0x78, 0xd5, 0x1b, 0x8e, 0x37, 0xd3, 0xdd, 0xba, 0xc1, 0xed, 0xae, - 0x83, 0x27, 0xbc, 0xc0, 0x62, 0xd0, 0xda, 0x4d, 0x7c, 0x02, 0x1c, 0x50, 0xd4, 0x7a, 0xd8, 0x05, 0x17, 0xca, 0x12, - 0x96, 0xdb, 0xe5, 0x66, 0x5b, 0xe5, 0x0c, 0x1c, 0x4d, 0x49, 0x8f, 0x3b, 0xd8, 0x84, 0x28, 0x74, 0x70, 0xd8, 0xc1, - 0x51, 0xbb, 0xdd, 0xe9, 0xe2, 0xe8, 0xa4, 0x0b, 0x03, 0x6d, 0x44, 0xdd, 0xc3, 0x59, 0x6e, 0x00, 0xe8, 0xe5, 0xac, - 0x6d, 0xbb, 0x8f, 0x21, 0x5a, 0x93, 0x2f, 0x5e, 0xf3, 0xc3, 0x30, 0x6c, 0x47, 0x0f, 0x5b, 0xed, 0xee, 0x59, 0x03, - 0x00, 0xd4, 0xb4, 0x1f, 0xb6, 0xc6, 0xeb, 0x85, 0xaa, 0x57, 0x29, 0x11, 0xbe, 0x5e, 0xad, 0xe1, 0xaa, 0x35, 0xda, - 0xeb, 0x6a, 0x0a, 0xae, 0xaa, 0x15, 0xce, 0x4d, 0x11, 0xa7, 0xb4, 0xf1, 0xb7, 0x45, 0x68, 0x06, 0x12, 0x82, 0x74, - 0x1e, 0x75, 0x3b, 0x5d, 0x64, 0xc6, 0xa2, 0x2c, 0x7e, 0x94, 0xfb, 0x64, 0xab, 0x48, 0x43, 0x01, 0x92, 0x94, 0xb3, - 0x13, 0x0b, 0x90, 0xa8, 0x39, 0xb9, 0x68, 0x37, 0x67, 0x2c, 0x72, 0x13, 0xd0, 0xa9, 0xb0, 0x9c, 0xe5, 0x2a, 0xd8, - 0x24, 0x0f, 0x10, 0xe7, 0x60, 0x5c, 0xf4, 0xb0, 0xdb, 0x7f, 0x18, 0x75, 0x4f, 0x3b, 0x86, 0xe8, 0xf1, 0xf3, 0x4e, - 0x2d, 0x4d, 0x4f, 0x3d, 0xea, 0xea, 0x34, 0xe8, 0x3a, 0x7a, 0xd8, 0x85, 0x32, 0x36, 0xc5, 0x2f, 0x05, 0x51, 0x26, - 0xaa, 0x62, 0x10, 0x5a, 0x22, 0xae, 0xe5, 0x9e, 0xd6, 0xb2, 0xcf, 0x4e, 0x8e, 0x1f, 0x76, 0x7d, 0xa8, 0x95, 0xb3, - 0xd0, 0x0b, 0x6d, 0x27, 0xe2, 0x66, 0x07, 0x4b, 0x8b, 0x0e, 0xa3, 0x6e, 0xbc, 0x35, 0x41, 0xb3, 0x69, 0x0e, 0x35, - 0x0e, 0x78, 0x0a, 0xc7, 0x4b, 0x69, 0xf5, 0x25, 0xde, 0xfd, 0x58, 0x65, 0x68, 0xe2, 0x2b, 0x9c, 0xdd, 0x3d, 0xa5, - 0xf7, 0x90, 0xa4, 0x7f, 0x55, 0x79, 0x45, 0xf3, 0xaf, 0x54, 0xbe, 0xa1, 0x10, 0x3a, 0x23, 0x1f, 0x06, 0x36, 0xb0, - 0x77, 0x3d, 0xf7, 0x27, 0x70, 0x11, 0x66, 0x39, 0x5c, 0x68, 0x3a, 0x25, 0x68, 0xc5, 0x0b, 0x8c, 0x7c, 0x56, 0x57, - 0x0f, 0xab, 0xcf, 0x63, 0x6b, 0x52, 0xe0, 0xeb, 0xb6, 0x9e, 0xf3, 0xef, 0x95, 0x8b, 0xca, 0xab, 0xec, 0xa8, 0x8b, - 0x22, 0x7b, 0x59, 0x1e, 0xb5, 0x51, 0xe4, 0x99, 0x90, 0xd8, 0x23, 0x39, 0x49, 0xc8, 0x20, 0xb8, 0x0b, 0x70, 0x70, - 0x1f, 0xe0, 0xc0, 0xf8, 0x30, 0x7f, 0x00, 0x37, 0xf2, 0x00, 0x07, 0xc6, 0x95, 0x39, 0xc0, 0x81, 0x62, 0x39, 0x44, - 0xd4, 0x0a, 0x86, 0x38, 0x83, 0xd2, 0xda, 0xb3, 0xba, 0x2c, 0x7d, 0xe5, 0xbe, 0x4a, 0xd7, 0x6b, 0x93, 0xe2, 0x49, - 0x99, 0x53, 0xbd, 0x43, 0xcd, 0x8b, 0xd0, 0x01, 0x75, 0xcc, 0x7a, 0x80, 0x41, 0x00, 0xa1, 0xf7, 0xee, 0x45, 0xb9, - 0x2a, 0x18, 0x07, 0x3b, 0x86, 0x95, 0x06, 0x9f, 0xf3, 0xc0, 0x3f, 0xc3, 0x02, 0x3c, 0xce, 0x5d, 0x61, 0x10, 0x2b, - 0xdc, 0xef, 0x4c, 0x88, 0xb9, 0xfb, 0xad, 0x44, 0xf9, 0x0b, 0xde, 0x21, 0xb1, 0x16, 0x2d, 0x60, 0xb9, 0x65, 0x62, - 0xff, 0x8c, 0x58, 0x7d, 0x04, 0x37, 0x63, 0x1b, 0x9f, 0x0d, 0x24, 0xc2, 0x1b, 0x2d, 0x50, 0x39, 0xf9, 0xf0, 0xc6, - 0xc4, 0x0a, 0xd2, 0x9f, 0x10, 0x2c, 0x0c, 0xe2, 0x01, 0x0b, 0xb8, 0xd0, 0x98, 0x14, 0x4c, 0xca, 0xc0, 0x04, 0xd1, - 0x0b, 0x44, 0xee, 0x5e, 0x45, 0x74, 0x29, 0xe3, 0x3c, 0xd0, 0x1d, 0xd6, 0x67, 0x6b, 0xc4, 0xe1, 0x4c, 0x14, 0x32, - 0x36, 0x4f, 0xa4, 0x38, 0x30, 0xce, 0xcb, 0xf7, 0x07, 0xe3, 0x2c, 0x59, 0x63, 0x73, 0x87, 0x5d, 0x16, 0xb2, 0x57, - 0xda, 0x7e, 0xa9, 0x24, 0x59, 0x7f, 0x6b, 0x42, 0xb2, 0x36, 0x23, 0x6f, 0xa2, 0xd5, 0x80, 0xaa, 0x48, 0x1a, 0x50, - 0xd8, 0x44, 0x63, 0x89, 0x97, 0x65, 0xc9, 0x78, 0x59, 0x2e, 0xc3, 0x49, 0xab, 0xb5, 0x5e, 0xe3, 0x82, 0xe9, 0xa8, - 0x30, 0x3b, 0x4b, 0x40, 0xbe, 0x9c, 0x8a, 0x5b, 0x2f, 0x57, 0xc6, 0xe5, 0x2c, 0xf5, 0x12, 0x05, 0x9e, 0x11, 0x6c, - 0xb0, 0xc6, 0x5f, 0xb9, 0xe4, 0x00, 0x4f, 0x3b, 0xbb, 0x91, 0x10, 0x19, 0xa3, 0x10, 0x3c, 0xcc, 0x6b, 0x72, 0x8d, - 0xa7, 0x3c, 0x65, 0xbb, 0xdb, 0x04, 0x33, 0xe6, 0x7f, 0xaf, 0x45, 0x87, 0x40, 0x86, 0xdd, 0xd3, 0xa8, 0x03, 0x8b, - 0xb8, 0x82, 0x0e, 0x7c, 0x19, 0x3c, 0xf5, 0x71, 0x33, 0xa3, 0xf7, 0x62, 0xa1, 0x00, 0x2e, 0x0b, 0x25, 0xde, 0xd8, - 0xb8, 0x07, 0xfb, 0x2d, 0xec, 0x42, 0x20, 0x2c, 0x21, 0x64, 0x40, 0x0b, 0x9b, 0x10, 0x15, 0x2d, 0x3c, 0x12, 0x4a, - 0x89, 0x59, 0xdc, 0xc2, 0x3a, 0x5e, 0x44, 0x6b, 0x5d, 0x06, 0xf5, 0xba, 0xc9, 0xdd, 0x5b, 0x92, 0xd5, 0x26, 0x58, - 0x58, 0xe9, 0x50, 0x11, 0xe5, 0xdd, 0x1e, 0x32, 0xc2, 0x1b, 0x3f, 0x5f, 0xbf, 0x7e, 0x65, 0x43, 0x36, 0xf3, 0x31, - 0xb8, 0x6c, 0x5a, 0xd5, 0xd8, 0x8d, 0x7e, 0x84, 0x29, 0xac, 0x14, 0xa5, 0x46, 0x38, 0x85, 0x96, 0x5f, 0xe4, 0x2a, - 0x8b, 0xcc, 0xe5, 0xc5, 0x33, 0x51, 0xcc, 0xa8, 0xb9, 0x31, 0xc2, 0x37, 0xb9, 0x7d, 0x75, 0x5d, 0x3f, 0xec, 0x52, - 0x4d, 0xf2, 0xdd, 0xe6, 0x55, 0xc4, 0x22, 0xd1, 0xf2, 0x2b, 0x68, 0x03, 0x74, 0xe5, 0xf2, 0xd1, 0xdc, 0x82, 0xd8, - 0xc0, 0xf7, 0x1e, 0x79, 0x79, 0x6b, 0xa8, 0x4b, 0x10, 0x34, 0xb8, 0xc6, 0x4f, 0x56, 0xf0, 0xc4, 0xbb, 0x2e, 0xd4, - 0xec, 0x91, 0x15, 0x2f, 0x82, 0x56, 0x50, 0x7f, 0x74, 0x56, 0xab, 0x12, 0x5c, 0xd0, 0xd4, 0x28, 0x13, 0x20, 0x7a, - 0x94, 0xef, 0xdb, 0x71, 0x10, 0x4d, 0xdc, 0xdd, 0xf3, 0x45, 0xdb, 0xd1, 0xd9, 0xac, 0x52, 0x27, 0x96, 0x57, 0x26, - 0xe0, 0xe1, 0x68, 0x5e, 0x90, 0x41, 0xd8, 0x4b, 0x64, 0xa5, 0xf6, 0xd0, 0xe5, 0xa2, 0x5e, 0x98, 0x9d, 0xb7, 0x59, - 0xf3, 0x64, 0xb5, 0xca, 0x2e, 0xda, 0xac, 0xdd, 0x35, 0xef, 0xcd, 0x05, 0x32, 0x01, 0x9a, 0xcb, 0xc7, 0x3c, 0x09, - 0x40, 0x3b, 0x3b, 0x4e, 0x74, 0x38, 0x05, 0x17, 0x21, 0x99, 0x2c, 0x54, 0xd5, 0x97, 0x00, 0xe3, 0x52, 0x62, 0xf4, - 0xf8, 0x05, 0xea, 0xb7, 0xe3, 0x6d, 0x57, 0xe9, 0x66, 0xfb, 0xd0, 0xbb, 0x70, 0x29, 0x10, 0xee, 0x40, 0xc8, 0x03, - 0xd0, 0xef, 0x2e, 0x73, 0x30, 0x0d, 0x02, 0x54, 0xce, 0x41, 0xa4, 0xe5, 0xb3, 0xc5, 0xec, 0x59, 0x41, 0xf5, 0x32, - 0x3c, 0xe1, 0x13, 0xae, 0x64, 0x4c, 0x41, 0xba, 0xdd, 0x95, 0xbe, 0xde, 0x2d, 0x41, 0x25, 0xb5, 0xc0, 0xb3, 0x91, - 0xe2, 0xc9, 0x17, 0x69, 0x17, 0x0e, 0x61, 0xbd, 0xb2, 0x12, 0x27, 0x68, 0x8d, 0x33, 0x31, 0xa1, 0x05, 0x57, 0xd3, - 0xd9, 0xbf, 0xb5, 0x3a, 0x6c, 0xa0, 0x86, 0xfa, 0xc2, 0x0a, 0x40, 0x42, 0xf3, 0x74, 0xb5, 0xe2, 0x47, 0xdf, 0xbf, - 0x4f, 0x72, 0x3e, 0xe1, 0x6d, 0xdc, 0xc1, 0xc7, 0xb8, 0x8b, 0xdb, 0x2d, 0xdc, 0xee, 0xc2, 0xd5, 0x7d, 0x92, 0x2d, - 0x52, 0x06, 0xf6, 0xb1, 0xab, 0x95, 0xba, 0x88, 0xce, 0x0e, 0xcb, 0x70, 0xfb, 0xaa, 0x88, 0x2c, 0xba, 0x78, 0x51, - 0xdf, 0x6d, 0xb8, 0xbc, 0x20, 0xf0, 0x63, 0xb5, 0x8d, 0x7d, 0xd5, 0x49, 0xa9, 0x5f, 0xb8, 0x38, 0xee, 0x83, 0x3d, - 0xb7, 0x59, 0xd9, 0x26, 0x98, 0x7d, 0x9b, 0x9f, 0x71, 0xf5, 0xb3, 0xa9, 0x4a, 0xc4, 0x70, 0xd0, 0xab, 0xd0, 0x03, - 0x5d, 0x90, 0xf6, 0xc1, 0x01, 0x58, 0x1d, 0x79, 0xb3, 0xe1, 0x26, 0xfa, 0x01, 0x6f, 0xd6, 0xd2, 0x20, 0x58, 0x01, - 0x18, 0x77, 0xbe, 0xe1, 0x64, 0x69, 0x60, 0xab, 0x80, 0x0a, 0xab, 0xc2, 0x0f, 0x28, 0xe7, 0x93, 0x0a, 0x2d, 0x44, - 0xc3, 0x11, 0x66, 0x23, 0x9d, 0xec, 0xb7, 0xb0, 0x18, 0x8f, 0x25, 0x53, 0x70, 0x74, 0x14, 0xec, 0x2b, 0x2b, 0xa4, - 0x3e, 0x45, 0x46, 0x6c, 0xc2, 0xf3, 0x4b, 0xf5, 0x89, 0x15, 0x42, 0x7f, 0x6a, 0x0d, 0x46, 0x1c, 0xe8, 0x55, 0x0c, - 0x70, 0x92, 0xf1, 0x39, 0x54, 0x9d, 0x14, 0xe0, 0xf4, 0x03, 0x7f, 0x79, 0x1a, 0xfb, 0x6d, 0x02, 0xf9, 0xfa, 0x60, - 0xc2, 0xba, 0xe0, 0xb4, 0xa0, 0xb7, 0xaf, 0xf3, 0x2b, 0xd8, 0x51, 0x97, 0x05, 0xa3, 0x90, 0x0d, 0x49, 0xef, 0xa0, - 0x29, 0xf8, 0x80, 0x36, 0x5f, 0x6a, 0xc0, 0xc5, 0x67, 0xfa, 0xc3, 0x54, 0x74, 0x41, 0x0b, 0xa3, 0xb2, 0x2d, 0x9d, - 0xa9, 0x4f, 0xe9, 0x2a, 0xd3, 0x84, 0x85, 0x2a, 0xa7, 0xb0, 0xc6, 0x36, 0xea, 0x89, 0x3f, 0x98, 0x94, 0xca, 0x69, - 0x3c, 0x18, 0xea, 0xbf, 0xaf, 0x4d, 0xc9, 0x16, 0xb6, 0x41, 0x67, 0xd6, 0x58, 0xbf, 0x18, 0xea, 0x95, 0x6f, 0x63, - 0xb8, 0x87, 0x85, 0x67, 0x2b, 0x6b, 0xe4, 0xf3, 0xc4, 0x91, 0xcd, 0x93, 0xf5, 0x5a, 0x0f, 0x44, 0xc6, 0xa0, 0x07, - 0x7a, 0xeb, 0xb6, 0x4d, 0x0b, 0xb6, 0x47, 0xf9, 0xd5, 0x6d, 0xe1, 0x19, 0x87, 0x57, 0x38, 0x5d, 0x7b, 0xd7, 0xaa, - 0x10, 0x5f, 0x2c, 0x48, 0x5a, 0x5e, 0x8a, 0x99, 0x8e, 0xd7, 0xd9, 0x31, 0xf6, 0x46, 0x0e, 0xf4, 0xfc, 0xfa, 0x8b, - 0x81, 0xb5, 0xfb, 0xfd, 0xa6, 0x2c, 0x98, 0xd1, 0x11, 0xcb, 0xca, 0x09, 0x25, 0xee, 0xfc, 0x7c, 0xc3, 0xa3, 0x0a, - 0x15, 0xec, 0xf3, 0x55, 0xb0, 0xa7, 0x4d, 0x84, 0xcb, 0x19, 0xfd, 0xcb, 0xfc, 0x30, 0x81, 0x75, 0x4a, 0x2d, 0x5b, - 0x52, 0x08, 0x29, 0x2f, 0x4d, 0x9a, 0x39, 0x7a, 0xe0, 0x88, 0x7c, 0x09, 0x5d, 0x00, 0xaf, 0x9f, 0x16, 0x62, 0xae, - 0x11, 0xc1, 0xfe, 0xb6, 0xe3, 0xd6, 0xbe, 0x02, 0xe0, 0xed, 0xb0, 0x57, 0xfd, 0xd3, 0x02, 0xf6, 0x37, 0x28, 0x4b, - 0xba, 0xf1, 0x76, 0xcc, 0xf1, 0x5f, 0x08, 0x08, 0x97, 0x6e, 0xf0, 0x30, 0xb2, 0xe8, 0x54, 0xb2, 0x66, 0xe5, 0xcf, - 0xad, 0x92, 0x80, 0x61, 0xf5, 0x82, 0x3e, 0x1b, 0xb7, 0x55, 0xdc, 0x64, 0xfe, 0x07, 0x15, 0x34, 0x16, 0x7c, 0x6b, - 0x24, 0x15, 0xcb, 0xe2, 0xb6, 0x4f, 0x9d, 0xff, 0xaa, 0x73, 0x5c, 0xfb, 0xaa, 0xf6, 0x44, 0xe6, 0x48, 0x87, 0x27, - 0x0e, 0xd0, 0xc1, 0xc1, 0x46, 0x06, 0x1d, 0x03, 0xe0, 0x91, 0x65, 0xbf, 0xdc, 0xf2, 0x39, 0x76, 0x4c, 0x6b, 0x1e, - 0x8b, 0xc0, 0x67, 0xee, 0x1c, 0x37, 0x67, 0x26, 0xf2, 0x84, 0xca, 0xa9, 0x2b, 0x0c, 0x70, 0x7c, 0xbc, 0x95, 0x0a, - 0xf8, 0x1e, 0xac, 0x77, 0x4c, 0x60, 0x83, 0xdf, 0x32, 0x93, 0xda, 0x55, 0xd0, 0x2d, 0xd0, 0x72, 0x17, 0x53, 0xb9, - 0xb1, 0xc0, 0xc1, 0xe6, 0x44, 0x76, 0x0e, 0x7d, 0xa3, 0x4e, 0xc9, 0x7a, 0x3c, 0xd9, 0x6d, 0xf4, 0x95, 0xcb, 0x5d, - 0xc9, 0x15, 0x6d, 0x1b, 0xb1, 0xea, 0x99, 0x5c, 0x55, 0x99, 0x3a, 0x55, 0xd7, 0xbc, 0x95, 0xa5, 0x4d, 0x69, 0x97, - 0x64, 0xee, 0xb6, 0x98, 0x7f, 0x15, 0xde, 0x68, 0x94, 0x17, 0xa1, 0x60, 0x8f, 0x25, 0x87, 0x3d, 0x4e, 0xe0, 0x7a, - 0x61, 0xb5, 0x0a, 0xe1, 0xcf, 0xae, 0x31, 0xec, 0x32, 0x5d, 0xfa, 0xc0, 0x37, 0xf8, 0x15, 0x2f, 0x52, 0xaf, 0xb5, - 0x83, 0x04, 0xeb, 0x2e, 0x3b, 0x68, 0x38, 0x4e, 0xdc, 0x17, 0xbc, 0x13, 0xad, 0x9c, 0xcb, 0xc1, 0x24, 0xf9, 0xc6, - 0xdb, 0x72, 0x25, 0x6b, 0x59, 0x0b, 0xf3, 0xbe, 0x21, 0xc1, 0x10, 0xb3, 0x29, 0xad, 0xe3, 0x56, 0xd4, 0x46, 0x81, - 0x2d, 0x56, 0xa1, 0xff, 0xb7, 0x8a, 0x24, 0x26, 0xf3, 0xbf, 0x4e, 0x4f, 0x4f, 0x6d, 0x8a, 0xb5, 0xf9, 0x93, 0xda, - 0x03, 0x4e, 0x27, 0xb0, 0xaf, 0x3c, 0x61, 0x5a, 0x87, 0xfc, 0x16, 0x86, 0x42, 0x24, 0xb9, 0x70, 0xec, 0x12, 0x44, - 0xe5, 0x02, 0xca, 0x03, 0xec, 0xdf, 0x93, 0x8d, 0x72, 0xee, 0x9d, 0x24, 0x17, 0x47, 0xb8, 0x6c, 0x90, 0x7d, 0xd5, - 0x9f, 0x03, 0x63, 0x26, 0x03, 0x4f, 0x03, 0x04, 0xd8, 0xfc, 0xd6, 0x2c, 0xad, 0xb5, 0x94, 0xc1, 0x81, 0x12, 0x8b, - 0x64, 0x6a, 0x34, 0xff, 0xf6, 0x43, 0x97, 0xb5, 0x6f, 0xec, 0x40, 0x50, 0x2e, 0xb2, 0xb4, 0xe1, 0x30, 0x83, 0x1f, - 0xcb, 0xc8, 0x97, 0x7b, 0xaf, 0xd8, 0x82, 0xfd, 0x88, 0xf7, 0xaa, 0x14, 0xf8, 0xb8, 0x2c, 0x38, 0xcd, 0x7e, 0xc4, - 0x7b, 0x55, 0x04, 0x4c, 0x70, 0x85, 0xd4, 0x41, 0x24, 0xb1, 0x7e, 0x4f, 0x3a, 0x0e, 0x72, 0xa0, 0xa0, 0x59, 0xa0, - 0x0f, 0xb2, 0xe7, 0x36, 0x68, 0x62, 0xd4, 0xc1, 0x36, 0xee, 0x97, 0x09, 0x85, 0x6a, 0x22, 0x88, 0x43, 0x20, 0xb9, - 0x72, 0x36, 0xfa, 0xeb, 0xf1, 0xc6, 0x82, 0x68, 0x65, 0x32, 0xb9, 0x78, 0xce, 0xc3, 0x7c, 0x73, 0xb1, 0x90, 0x5f, - 0xcd, 0x5b, 0xa0, 0x5a, 0x95, 0x2a, 0xdd, 0x2f, 0xbe, 0x5d, 0x30, 0xf1, 0x8a, 0xe8, 0xad, 0x77, 0x79, 0x07, 0xcf, - 0x9d, 0xdf, 0x05, 0x2e, 0x09, 0x9e, 0x04, 0xd7, 0x98, 0xea, 0x5e, 0x80, 0x07, 0x42, 0xcf, 0xa4, 0x0a, 0xb0, 0xce, - 0x93, 0x10, 0x49, 0x6c, 0xbf, 0x85, 0x2d, 0x6b, 0xf4, 0x22, 0x77, 0x42, 0x0a, 0x9c, 0xab, 0xba, 0x89, 0x19, 0xe5, - 0x3a, 0xba, 0xd8, 0xa5, 0x9c, 0xb3, 0x44, 0x19, 0x04, 0xd8, 0xb7, 0x68, 0x28, 0xf2, 0xe7, 0x1a, 0x14, 0xfa, 0x2d, - 0x6b, 0x9b, 0x72, 0x05, 0x8b, 0xe7, 0xa5, 0x00, 0x51, 0xe3, 0xf9, 0xa4, 0xac, 0x33, 0xcf, 0x16, 0x13, 0x9e, 0x57, - 0xc8, 0x50, 0x30, 0x39, 0x17, 0x39, 0x3c, 0x25, 0x51, 0x16, 0xd1, 0x74, 0xa8, 0x86, 0xef, 0x86, 0x84, 0x95, 0x75, - 0xf4, 0x31, 0xc5, 0xf3, 0xaa, 0x06, 0x30, 0x17, 0x97, 0xfe, 0x9b, 0xf3, 0xf2, 0x75, 0xfe, 0x4e, 0xcc, 0xab, 0x7c, - 0x47, 0xe3, 0x5c, 0xc4, 0x76, 0x6b, 0x37, 0x8c, 0xd6, 0xfa, 0xb5, 0x27, 0x6f, 0xfb, 0x7e, 0xe0, 0xd5, 0x0b, 0x68, - 0x6b, 0xfd, 0x5e, 0x54, 0x99, 0x35, 0x62, 0xe5, 0xe3, 0x08, 0x55, 0x7b, 0xf5, 0xaa, 0xb9, 0xad, 0x08, 0x50, 0x29, - 0x78, 0xba, 0x95, 0xff, 0x44, 0x99, 0x7c, 0x73, 0x0e, 0x95, 0xe1, 0x81, 0x1c, 0x19, 0xaa, 0x7a, 0xc0, 0x45, 0xf9, - 0xa1, 0x9f, 0xbe, 0x0a, 0x74, 0xe0, 0xdc, 0x5d, 0x17, 0xc8, 0x9c, 0xc9, 0x50, 0xe0, 0xe5, 0x80, 0x0e, 0x63, 0x23, - 0x0f, 0xc5, 0x02, 0x6c, 0x7b, 0x6e, 0x0b, 0xae, 0x5c, 0x84, 0x5e, 0x3c, 0x60, 0xc3, 0x78, 0x59, 0x8f, 0xe2, 0x6b, - 0xe2, 0x08, 0x3b, 0x73, 0x4e, 0x1d, 0xf6, 0x96, 0x0e, 0x71, 0x46, 0xc0, 0xf6, 0xd8, 0xb1, 0xa7, 0x6f, 0xc2, 0x04, - 0xf5, 0xeb, 0x1c, 0xfe, 0x72, 0x8d, 0x33, 0x9c, 0xa0, 0xf8, 0x32, 0x84, 0x0b, 0xac, 0x35, 0x06, 0xf0, 0x25, 0x86, - 0x54, 0x81, 0x47, 0x6a, 0xa2, 0x25, 0x56, 0x7b, 0x11, 0x88, 0x96, 0xca, 0xbf, 0x1d, 0x67, 0x2e, 0x0e, 0xb6, 0xe6, - 0x5e, 0x9f, 0x69, 0xe1, 0x70, 0x92, 0x84, 0xb5, 0x73, 0x86, 0x93, 0x8b, 0x7d, 0x5e, 0x3b, 0x31, 0xc1, 0xda, 0xdb, - 0x3f, 0x55, 0x40, 0x8f, 0x06, 0xa7, 0x8a, 0xa1, 0x21, 0x10, 0x33, 0x01, 0xbc, 0x99, 0xfd, 0xa3, 0xcd, 0xc3, 0xf9, - 0x60, 0x8d, 0xbd, 0xaf, 0xb8, 0xd6, 0xd5, 0xa6, 0x12, 0x65, 0xbd, 0xc6, 0x83, 0x69, 0x82, 0xd3, 0x04, 0xcf, 0x93, - 0xa1, 0x77, 0xdc, 0xcc, 0x12, 0xdf, 0xa4, 0x6b, 0xb5, 0x7a, 0x6a, 0xcd, 0x08, 0x91, 0xf9, 0x69, 0xe8, 0x0f, 0xea, - 0x03, 0xc2, 0xc7, 0x90, 0x05, 0xb4, 0xa4, 0x6f, 0xff, 0x36, 0xcc, 0x33, 0xd9, 0xa8, 0x11, 0xf2, 0xc8, 0x90, 0x91, - 0xbe, 0xfb, 0x51, 0x66, 0x99, 0xd6, 0x1a, 0xc1, 0xfc, 0x6e, 0x2f, 0x68, 0xb8, 0xf6, 0x3c, 0x2d, 0x5b, 0x69, 0xb6, - 0x03, 0x88, 0x62, 0x8c, 0x93, 0x94, 0xb7, 0x46, 0x62, 0xb5, 0x0a, 0x4d, 0x0a, 0xe1, 0xd1, 0x8c, 0x51, 0xb9, 0x28, - 0xf4, 0xcb, 0x71, 0x61, 0x8e, 0x22, 0xcd, 0xef, 0x62, 0x6b, 0x23, 0x9a, 0x83, 0xdb, 0x23, 0x18, 0x6e, 0x84, 0x92, - 0x88, 0x9a, 0xc8, 0x3d, 0x4a, 0x2a, 0xcb, 0x20, 0x49, 0xa4, 0x16, 0xf9, 0xcd, 0x75, 0xa9, 0x39, 0x0c, 0xec, 0x1f, - 0xed, 0x0b, 0x08, 0x37, 0x6f, 0x13, 0x5a, 0x8c, 0xe8, 0x04, 0xd8, 0x58, 0x88, 0x43, 0xb8, 0x95, 0xb0, 0x5a, 0x0d, - 0x86, 0x3d, 0x43, 0x9e, 0xed, 0xcb, 0x79, 0x65, 0x43, 0xbb, 0x1b, 0x80, 0xab, 0x6e, 0x43, 0xcd, 0x95, 0xd6, 0xfd, - 0x50, 0xfd, 0xb8, 0x17, 0xb7, 0x49, 0xf6, 0x7d, 0x8e, 0xea, 0x09, 0xee, 0x9a, 0x05, 0xb8, 0x0e, 0x5d, 0x85, 0x53, - 0xbc, 0x30, 0x36, 0x9c, 0xfa, 0x25, 0x27, 0xaa, 0x1f, 0x70, 0x82, 0x77, 0xa3, 0x09, 0x1b, 0x24, 0x43, 0x9c, 0xba, - 0x38, 0xdf, 0xfb, 0x6f, 0xc3, 0x14, 0xa1, 0x82, 0x68, 0x98, 0x1a, 0x97, 0xed, 0xb4, 0xb2, 0xdb, 0xd7, 0x99, 0x9a, - 0x61, 0xd0, 0x46, 0xcc, 0xa9, 0x6f, 0xc4, 0x9c, 0x35, 0x1a, 0x68, 0x41, 0x52, 0x30, 0x62, 0x5e, 0x78, 0xad, 0x2d, - 0xcc, 0x2b, 0x9f, 0x5e, 0x7b, 0x0b, 0x84, 0x7a, 0x1c, 0x68, 0x9a, 0x82, 0xf7, 0x3c, 0xaa, 0xf7, 0xd4, 0xdd, 0xeb, - 0x52, 0x47, 0x1d, 0x50, 0x24, 0x8c, 0x2f, 0xdc, 0x24, 0x8c, 0x6b, 0xb8, 0x19, 0xf7, 0x58, 0x8f, 0xdb, 0xda, 0x36, - 0xe4, 0x03, 0x31, 0x48, 0x86, 0xc3, 0x9e, 0x70, 0x56, 0x12, 0x2d, 0x3c, 0xae, 0x5e, 0x00, 0xa9, 0x16, 0xef, 0xab, - 0xda, 0xbc, 0xf2, 0xe6, 0xee, 0x61, 0xd1, 0xcd, 0xf3, 0x18, 0x38, 0xa0, 0x7d, 0xb8, 0x1f, 0xaa, 0xe2, 0x83, 0x1d, - 0x75, 0x20, 0x0a, 0x5a, 0xdc, 0xaa, 0x09, 0xa4, 0xc6, 0xcc, 0x2e, 0x54, 0xcd, 0x1c, 0x1d, 0x4a, 0x08, 0x43, 0x96, - 0x57, 0xdd, 0xdd, 0xe7, 0x9e, 0x6a, 0x88, 0xc3, 0xa9, 0x7f, 0x65, 0x8c, 0x58, 0xc3, 0xa0, 0x93, 0x06, 0xda, 0x48, - 0xd2, 0x2c, 0x1f, 0x3c, 0xfa, 0x03, 0x56, 0x02, 0x2e, 0xf8, 0xb2, 0x4e, 0xd2, 0x86, 0x04, 0x6f, 0x59, 0xa2, 0x34, - 0x1f, 0xc2, 0x2d, 0x82, 0xf2, 0xc8, 0xc4, 0xda, 0xb4, 0x95, 0x0c, 0xe4, 0xaa, 0x2e, 0x6f, 0x3c, 0xf4, 0xbc, 0x4f, - 0xaa, 0xdd, 0x00, 0x1c, 0x99, 0x37, 0xb0, 0x64, 0x6b, 0x9f, 0x80, 0x47, 0x3e, 0xae, 0x10, 0xc4, 0x2d, 0x85, 0x8a, - 0x74, 0xa0, 0xea, 0x6b, 0xd8, 0xa0, 0x78, 0x0e, 0x0e, 0x82, 0x56, 0x82, 0xc3, 0xe0, 0x5d, 0x66, 0x34, 0xc9, 0x1a, - 0xb7, 0x66, 0x24, 0x9c, 0xaf, 0x56, 0x2d, 0x74, 0xf8, 0xb7, 0x7e, 0x8b, 0x79, 0x5c, 0x2a, 0xdc, 0xc7, 0x95, 0xc2, - 0x1d, 0x2c, 0x01, 0xc9, 0xd8, 0xd3, 0xb5, 0x63, 0xe1, 0xab, 0xd1, 0x21, 0x4c, 0xf8, 0x0b, 0x08, 0x1a, 0x6d, 0x8f, - 0x25, 0xd0, 0xb3, 0x6f, 0x15, 0x30, 0xba, 0xf6, 0xb2, 0x04, 0xd2, 0x82, 0xbb, 0xdb, 0x04, 0x5a, 0x85, 0xa8, 0x7d, - 0xfe, 0xf4, 0x73, 0x0e, 0x3c, 0xb2, 0xfe, 0x5c, 0x33, 0xcd, 0xba, 0x17, 0xf4, 0x56, 0x37, 0x1f, 0x8e, 0x71, 0x73, - 0x6c, 0xc0, 0x79, 0xd4, 0x81, 0x9f, 0x06, 0xa2, 0x47, 0x1d, 0x6c, 0x53, 0xf1, 0xb8, 0x04, 0xb2, 0x8f, 0x9e, 0xd6, - 0x40, 0x0a, 0x58, 0xe9, 0xd0, 0x68, 0x91, 0x26, 0x68, 0xb5, 0x9a, 0x9c, 0x93, 0x16, 0x42, 0x4b, 0x79, 0xcb, 0x55, - 0x32, 0x05, 0x1f, 0x69, 0x50, 0x0c, 0xbc, 0xa1, 0x6a, 0x1a, 0x22, 0x3c, 0x46, 0xcb, 0x94, 0x8d, 0xe9, 0x22, 0x53, - 0x71, 0xde, 0xe7, 0x91, 0x89, 0xa4, 0xcb, 0x4c, 0x24, 0xb8, 0xa3, 0x0e, 0x9e, 0x68, 0xfe, 0xf2, 0xb1, 0x36, 0x07, - 0x29, 0x12, 0x9d, 0x3c, 0xd1, 0x09, 0x98, 0x47, 0x49, 0x26, 0x24, 0x33, 0xcd, 0xf4, 0x8c, 0x6d, 0x39, 0xc4, 0xe2, - 0x0e, 0x54, 0xc1, 0xb5, 0x15, 0x65, 0x10, 0x4f, 0x49, 0xde, 0xcf, 0x8f, 0x3a, 0xf1, 0x04, 0xf3, 0x08, 0x38, 0xbd, - 0x77, 0x22, 0x64, 0x8d, 0xf2, 0x56, 0x74, 0x86, 0x0e, 0xa7, 0x58, 0x56, 0x97, 0xa8, 0x33, 0x74, 0x38, 0x41, 0x78, - 0xd6, 0x20, 0x59, 0x0e, 0x1e, 0xc3, 0x3c, 0xff, 0x3f, 0x52, 0xfe, 0x9b, 0xc3, 0x86, 0x98, 0xcf, 0x6f, 0x61, 0xa7, - 0xb0, 0x34, 0x88, 0x33, 0x02, 0x5e, 0x8b, 0xed, 0x53, 0x9c, 0x90, 0x49, 0x33, 0x73, 0x01, 0xf7, 0x74, 0x2b, 0x8d, - 0x3b, 0x85, 0x0e, 0x13, 0x9c, 0x6e, 0x26, 0x85, 0x7a, 0xae, 0xcd, 0x2c, 0x4e, 0xe0, 0x7c, 0xaf, 0x46, 0x61, 0xcb, - 0x2f, 0x36, 0x93, 0xfc, 0xf2, 0x16, 0xb8, 0xcd, 0x14, 0xcb, 0x26, 0xc5, 0x19, 0x9e, 0x35, 0x5f, 0xe1, 0x59, 0xf3, - 0x43, 0x99, 0xd1, 0x58, 0x60, 0x09, 0xc1, 0xfb, 0x20, 0x11, 0xcf, 0xaa, 0xe4, 0x14, 0xcb, 0x86, 0x2e, 0x8f, 0x67, - 0x8d, 0xaa, 0x74, 0x73, 0x81, 0x65, 0x43, 0x97, 0x6e, 0x7c, 0xc0, 0xb3, 0xc6, 0xab, 0x7f, 0x31, 0xe9, 0x20, 0x06, - 0x74, 0x99, 0xa3, 0x65, 0x62, 0x86, 0x78, 0xfd, 0xdb, 0xdb, 0x77, 0xed, 0x9b, 0xce, 0xe1, 0x04, 0xbb, 0xf5, 0x4b, - 0x34, 0x8e, 0x25, 0x2a, 0x64, 0x4d, 0x80, 0x68, 0x82, 0x3b, 0x87, 0x53, 0xdc, 0x39, 0x4c, 0x6c, 0x53, 0xeb, 0x59, - 0x83, 0xdc, 0x29, 0x1f, 0x8a, 0x2a, 0x88, 0x7d, 0xf8, 0xb8, 0xc9, 0xc6, 0x13, 0x54, 0x03, 0x25, 0x3a, 0x9c, 0xd4, - 0x40, 0x05, 0xdf, 0x8b, 0xda, 0x77, 0x55, 0xaf, 0xc2, 0x20, 0x03, 0x25, 0xe4, 0xaf, 0xb9, 0x06, 0x4f, 0x2d, 0x45, - 0x43, 0xc6, 0x4f, 0x31, 0x40, 0xf9, 0x0e, 0x28, 0xb4, 0xf2, 0x44, 0x0f, 0xdd, 0x9b, 0x8e, 0x4e, 0xfc, 0xff, 0x79, - 0x32, 0xe5, 0xd0, 0xcb, 0x2d, 0xb3, 0x35, 0x3d, 0x3b, 0x19, 0x7f, 0xf8, 0xc0, 0x63, 0xfd, 0x5f, 0x3b, 0x50, 0xac, - 0x41, 0x8a, 0xff, 0x2f, 0x1d, 0x9d, 0x0f, 0x46, 0xc8, 0x0a, 0xe2, 0xc2, 0x22, 0xfe, 0xf7, 0x87, 0xe5, 0x75, 0x5f, - 0x6c, 0x75, 0x5f, 0xe8, 0xee, 0xfd, 0xa6, 0xb5, 0x2a, 0x27, 0xae, 0x2a, 0x19, 0xf2, 0x5f, 0xa7, 0x5b, 0x5b, 0xa0, - 0x91, 0x35, 0x7a, 0x36, 0xf1, 0x1b, 0xdc, 0x6f, 0xc7, 0x3b, 0x90, 0x79, 0xcd, 0xcd, 0xd3, 0xa0, 0x70, 0xf8, 0x7a, - 0x77, 0xaa, 0x17, 0x2d, 0xf0, 0xde, 0x94, 0x5a, 0x5f, 0x19, 0xfa, 0x96, 0x83, 0xc5, 0xa6, 0x29, 0xb7, 0x36, 0x96, - 0x8e, 0xba, 0x58, 0xbb, 0x22, 0x42, 0xa5, 0xbb, 0x0b, 0x50, 0x8a, 0x8f, 0x55, 0x93, 0xe9, 0xaf, 0x73, 0x15, 0xe9, - 0x4b, 0xa8, 0x86, 0xfe, 0xbc, 0xbf, 0x50, 0x91, 0x12, 0x73, 0x93, 0x77, 0x7f, 0x0e, 0x7d, 0x82, 0x86, 0xb5, 0xe1, - 0xd9, 0xed, 0xb3, 0xc2, 0xea, 0x77, 0xaa, 0x43, 0xd0, 0x3f, 0x80, 0x2c, 0x69, 0x31, 0x7d, 0x60, 0xdd, 0x1a, 0xb6, - 0x5d, 0x34, 0xcb, 0x44, 0xd3, 0x6a, 0x53, 0xe7, 0x9a, 0x3d, 0xcc, 0xe7, 0x3e, 0x4f, 0xc1, 0x0b, 0xa3, 0x1f, 0xdf, - 0xc1, 0x6e, 0xdc, 0xd5, 0x18, 0x89, 0xba, 0x92, 0xa9, 0x84, 0x7e, 0x74, 0x87, 0x59, 0x74, 0xaf, 0xbd, 0x18, 0x73, - 0xed, 0xef, 0xa3, 0x03, 0xe5, 0x07, 0x95, 0x24, 0x07, 0x96, 0xfd, 0x0d, 0x16, 0xdd, 0x81, 0x79, 0x62, 0x59, 0x4d, - 0x60, 0x15, 0xdd, 0x7b, 0x8b, 0x28, 0x74, 0x23, 0x6b, 0xcd, 0x80, 0xea, 0x66, 0x8c, 0x7a, 0x70, 0x1f, 0x02, 0x3d, - 0xf4, 0xcb, 0x52, 0xca, 0x76, 0x16, 0xd7, 0xba, 0x57, 0xba, 0xfb, 0xcd, 0x01, 0x79, 0x7c, 0xa1, 0xc7, 0x35, 0xfd, - 0xab, 0x49, 0x44, 0x23, 0xf6, 0x0f, 0x67, 0xc5, 0xd5, 0xa2, 0xd0, 0x98, 0x26, 0xfb, 0x2a, 0x4a, 0xe6, 0x6d, 0x30, - 0xd5, 0x4b, 0xe6, 0x9d, 0x3b, 0x6c, 0xbf, 0xef, 0xcd, 0xf7, 0x3d, 0x96, 0x7d, 0xa6, 0x33, 0x62, 0xa6, 0x8b, 0xb9, - 0xef, 0x7b, 0xf3, 0x7d, 0x8f, 0xb7, 0x07, 0x73, 0xeb, 0x2e, 0x14, 0x4b, 0x76, 0x86, 0x0b, 0x30, 0x2c, 0xf7, 0xb8, - 0x9b, 0x5a, 0x96, 0x0e, 0x02, 0x5b, 0x4b, 0x80, 0x38, 0x9f, 0x4f, 0xc3, 0x8a, 0x57, 0x43, 0xc0, 0x7d, 0x3a, 0xd7, - 0xf6, 0x2a, 0x15, 0x78, 0x4c, 0xd0, 0x88, 0xe8, 0xd8, 0x36, 0xfa, 0x59, 0x2f, 0xe0, 0xf2, 0x88, 0x2a, 0xf5, 0x24, - 0x11, 0xf0, 0xaa, 0x5a, 0xe5, 0xad, 0x8b, 0x94, 0x5f, 0xc4, 0xcb, 0x71, 0xc5, 0x1e, 0x53, 0xc9, 0x00, 0x56, 0x65, - 0x49, 0x97, 0x40, 0xea, 0xf9, 0xde, 0x44, 0xbf, 0x6c, 0x22, 0x4f, 0xae, 0x6f, 0x4b, 0xbf, 0x30, 0x35, 0x2d, 0xc4, - 0x62, 0x32, 0x05, 0x1f, 0x5a, 0x60, 0x19, 0x0a, 0x5d, 0xaf, 0xb2, 0xf5, 0xaf, 0x49, 0x6e, 0x12, 0x28, 0x9c, 0x6a, - 0x8a, 0x88, 0x26, 0x6a, 0x41, 0x33, 0x6d, 0x49, 0xca, 0xf3, 0xc9, 0x63, 0x71, 0xf7, 0x12, 0xb0, 0x9b, 0x12, 0xd5, - 0xd8, 0x91, 0xf7, 0x16, 0x76, 0x00, 0x4e, 0x08, 0xdb, 0x55, 0xf1, 0x52, 0x82, 0xce, 0x1f, 0x67, 0x84, 0xed, 0xaa, - 0xfa, 0x84, 0x99, 0xec, 0x29, 0xd9, 0x18, 0x6e, 0x3f, 0x4c, 0x1a, 0x19, 0x3a, 0xea, 0xc4, 0x59, 0xcf, 0x11, 0x03, - 0x03, 0x50, 0x0f, 0xb8, 0x5b, 0xdb, 0xb3, 0xbc, 0xbb, 0x21, 0x79, 0x94, 0xb2, 0x44, 0x98, 0xeb, 0x72, 0x9d, 0xb2, - 0x5a, 0x75, 0x2a, 0x2a, 0x58, 0xe0, 0xa9, 0xb7, 0x17, 0xa8, 0xf9, 0xda, 0x41, 0x71, 0xae, 0x93, 0x4d, 0xd3, 0xf3, - 0xb2, 0xef, 0xde, 0x8e, 0x45, 0xc6, 0x26, 0xed, 0xed, 0x0e, 0x22, 0x61, 0x38, 0x61, 0xe5, 0x71, 0xc2, 0x55, 0x6d, - 0x8f, 0x00, 0xdd, 0x78, 0x22, 0x37, 0x16, 0x64, 0xb9, 0xae, 0x8c, 0xee, 0x3d, 0xbf, 0x5b, 0x4a, 0x84, 0x1d, 0x6d, - 0x49, 0x30, 0x5d, 0x82, 0x56, 0xd3, 0xe9, 0x37, 0x99, 0x6b, 0xcf, 0x0d, 0x6f, 0x8a, 0xb6, 0xb9, 0xbd, 0x49, 0xc7, - 0x7a, 0x7b, 0xe8, 0x18, 0xca, 0x20, 0x06, 0x3a, 0x1f, 0xf1, 0x5e, 0xa3, 0x91, 0x20, 0x50, 0xc8, 0x24, 0x43, 0x2c, - 0x22, 0xa7, 0x45, 0x3f, 0x38, 0xd0, 0xf0, 0xa8, 0x12, 0x10, 0xa6, 0x20, 0x84, 0xf8, 0x5d, 0x6b, 0x84, 0xf5, 0x97, - 0xab, 0x96, 0x0b, 0x1b, 0xa9, 0x36, 0x74, 0xf0, 0xff, 0xf2, 0x97, 0xad, 0x9e, 0x59, 0x2e, 0x8a, 0xc6, 0xcd, 0x4c, - 0x83, 0x45, 0x80, 0xf4, 0x68, 0xb2, 0x1d, 0x14, 0x77, 0xe7, 0x62, 0xbd, 0x21, 0x20, 0x31, 0x83, 0x09, 0xca, 0x86, - 0x75, 0x63, 0x0c, 0xf3, 0xa8, 0xd2, 0xb2, 0xd6, 0x24, 0x66, 0xcf, 0x97, 0xce, 0x5f, 0xf7, 0xe5, 0x5d, 0xcc, 0xf0, - 0x7d, 0x2c, 0xf1, 0x2d, 0x78, 0xd2, 0xc4, 0x02, 0xdb, 0xc7, 0x0b, 0x8a, 0x35, 0x51, 0x3d, 0xc7, 0xde, 0x16, 0xb0, - 0xce, 0x7a, 0x8f, 0x48, 0xef, 0x77, 0xf5, 0xab, 0x0d, 0xbe, 0x5b, 0xf8, 0x15, 0x58, 0x3f, 0x7b, 0x27, 0x29, 0x96, - 0x0d, 0xd1, 0x2c, 0xec, 0x91, 0x01, 0xe5, 0x2a, 0x7e, 0xd9, 0x4f, 0xdd, 0x2a, 0x86, 0x6b, 0x1f, 0xaf, 0xf0, 0x87, - 0x8d, 0x76, 0x1b, 0x79, 0x59, 0xdc, 0xec, 0x4d, 0xd9, 0x10, 0x55, 0xd3, 0x3b, 0x32, 0x37, 0x52, 0xea, 0x5f, 0x1f, - 0x70, 0x6b, 0xab, 0x7d, 0x37, 0xcd, 0xb7, 0x0e, 0x9d, 0xab, 0xa6, 0x5d, 0x6a, 0xad, 0x08, 0xf6, 0x7e, 0xb6, 0x70, - 0x73, 0x6b, 0xc0, 0x1e, 0xfc, 0xdc, 0x1d, 0xcd, 0x55, 0x02, 0xd1, 0xe9, 0x8d, 0x66, 0x7c, 0x15, 0xfe, 0x99, 0x36, - 0xc2, 0x7e, 0xfc, 0x67, 0xf4, 0x67, 0xda, 0x40, 0x7d, 0x14, 0xce, 0xef, 0x56, 0x6c, 0xb6, 0x82, 0x60, 0x6b, 0x0f, - 0x8e, 0xf0, 0x6b, 0xbf, 0x24, 0x57, 0x34, 0xe3, 0xc9, 0xca, 0xbe, 0x84, 0xb7, 0xb2, 0xcf, 0x04, 0xad, 0xf4, 0xe3, - 0x4e, 0xab, 0x50, 0x8c, 0x32, 0x08, 0x2c, 0x1c, 0xee, 0x35, 0xfb, 0x83, 0x56, 0xf3, 0xd1, 0xd0, 0xfc, 0xab, 0x23, - 0xdc, 0xa3, 0x5a, 0xc4, 0xb6, 0x37, 0x1b, 0x5b, 0x3f, 0x04, 0xc3, 0x0e, 0x08, 0x05, 0x0e, 0x72, 0xe9, 0x55, 0x82, - 0x8c, 0xef, 0xc9, 0x6a, 0xc5, 0x6c, 0x34, 0x6b, 0xab, 0xc1, 0x2f, 0x63, 0x33, 0x1d, 0xb6, 0xa3, 0x4e, 0xcf, 0x89, - 0xb1, 0xa4, 0x01, 0x91, 0xa6, 0x31, 0x83, 0x40, 0x52, 0x4b, 0xcd, 0x61, 0xcd, 0xef, 0x82, 0xb8, 0xba, 0x3f, 0x82, - 0x94, 0x1f, 0x82, 0x98, 0x1f, 0x11, 0x08, 0xa0, 0x6d, 0x98, 0xa3, 0xb2, 0x21, 0xe7, 0xbb, 0xf4, 0x40, 0x3b, 0x33, - 0x34, 0xf8, 0x6a, 0xd5, 0xaa, 0x86, 0x29, 0x8b, 0xfa, 0x30, 0x97, 0x6b, 0x2c, 0xc9, 0x1b, 0xd0, 0x35, 0xe7, 0x44, - 0xf6, 0x7d, 0x57, 0x79, 0x78, 0x08, 0x18, 0x0b, 0x02, 0x4e, 0xfa, 0x7d, 0xd9, 0x2f, 0xc8, 0xc5, 0x65, 0x08, 0x3e, - 0x66, 0x98, 0x0f, 0xd4, 0xa0, 0x18, 0x0e, 0x51, 0x6c, 0x9d, 0xce, 0x62, 0x1d, 0x71, 0xc5, 0xf3, 0x4b, 0x2e, 0xc0, - 0x2f, 0x39, 0x47, 0x6c, 0x50, 0x0c, 0xc9, 0x83, 0x24, 0x14, 0xe0, 0x94, 0xbf, 0xc3, 0xe7, 0xf1, 0xd2, 0x37, 0x30, - 0xd5, 0xc3, 0xd2, 0x17, 0xd9, 0x60, 0x31, 0x67, 0x2c, 0x81, 0xe0, 0x66, 0xc0, 0x5e, 0x6a, 0x43, 0xa2, 0xb6, 0x06, - 0x0a, 0xee, 0x02, 0xdf, 0xcc, 0xe8, 0xe9, 0x56, 0x1b, 0x83, 0xc0, 0xe2, 0x85, 0xbe, 0x86, 0x31, 0x08, 0xa4, 0x2f, - 0x57, 0x1d, 0xf6, 0x97, 0x1f, 0x26, 0xcb, 0x0f, 0x5e, 0xa1, 0x4d, 0x76, 0x4a, 0xab, 0x44, 0x3d, 0xbe, 0xca, 0x13, - 0x47, 0x13, 0x64, 0x62, 0xa8, 0x74, 0xc3, 0x32, 0x71, 0x25, 0x7d, 0x26, 0x9a, 0x6c, 0x37, 0x1c, 0x33, 0xe7, 0xbb, - 0xd9, 0xfe, 0x61, 0xdd, 0xce, 0x39, 0xe1, 0x5a, 0x2b, 0xa9, 0xb5, 0x51, 0xcf, 0x34, 0x55, 0xb5, 0xc1, 0xfc, 0x2e, - 0xad, 0x96, 0x16, 0x5b, 0x57, 0xef, 0x9e, 0xff, 0x2c, 0x5d, 0x19, 0x7f, 0x8b, 0x55, 0xa1, 0x15, 0x19, 0x6e, 0xb7, - 0x90, 0x33, 0x67, 0xba, 0x74, 0x8a, 0x5c, 0xa8, 0x0e, 0x7f, 0x51, 0x4f, 0xea, 0x97, 0x2a, 0x83, 0x86, 0x74, 0xe8, - 0xf7, 0x3a, 0x01, 0xe5, 0x1f, 0x4c, 0x4c, 0x64, 0x2c, 0xba, 0xa5, 0x45, 0x1e, 0xfe, 0xf8, 0x22, 0xd7, 0xb1, 0xaa, - 0xf6, 0x60, 0x20, 0x7b, 0xba, 0xe2, 0x1e, 0xdc, 0x9a, 0xf0, 0x31, 0x67, 0x69, 0xbc, 0x17, 0xfc, 0xd8, 0x90, 0x8d, - 0x1f, 0x83, 0x1f, 0xc1, 0xdd, 0xd9, 0x3e, 0x8b, 0x58, 0xc6, 0x85, 0x70, 0xf7, 0x58, 0x97, 0xa5, 0x4a, 0x19, 0x2b, - 0xa7, 0x5b, 0xf6, 0x2f, 0xa4, 0xde, 0x24, 0xe1, 0xa5, 0x25, 0xd6, 0x26, 0x05, 0x2b, 0x9f, 0x92, 0xc2, 0xb3, 0x2b, - 0xfa, 0x56, 0x8b, 0xd9, 0x4b, 0x2d, 0xe9, 0xae, 0xaf, 0x2e, 0x4b, 0x15, 0x34, 0x1c, 0x84, 0xb6, 0xb4, 0x81, 0x04, - 0x18, 0xb8, 0x94, 0x3e, 0x9d, 0xf6, 0x4c, 0x22, 0xb3, 0x24, 0x84, 0x77, 0x0f, 0x2a, 0x98, 0xff, 0xce, 0x36, 0xc2, - 0xaa, 0xc0, 0xe5, 0x4a, 0x15, 0xf5, 0x52, 0x10, 0x08, 0x40, 0x5f, 0x7a, 0x0f, 0x8a, 0xf3, 0xa2, 0xd7, 0x68, 0x08, - 0xd0, 0xc2, 0x52, 0x7d, 0xad, 0x8a, 0xe9, 0xbe, 0xff, 0x9c, 0x9f, 0xf7, 0xe1, 0x1c, 0xd2, 0x36, 0xde, 0xd4, 0xa4, - 0x84, 0x9a, 0x1d, 0xb4, 0x0f, 0x56, 0xd9, 0x5e, 0xf9, 0xb7, 0x21, 0x45, 0x26, 0x7f, 0xc0, 0x7e, 0xa0, 0xb6, 0xc3, - 0xa1, 0x2d, 0x58, 0xf5, 0x52, 0x46, 0xc1, 0x80, 0x95, 0x03, 0x6e, 0x4f, 0x46, 0x09, 0x4d, 0xa6, 0x0c, 0xd4, 0xfd, - 0xa6, 0x68, 0x35, 0xb7, 0x27, 0x75, 0xbf, 0x21, 0xed, 0xec, 0x23, 0xb5, 0xb3, 0x4f, 0x0e, 0x5e, 0x2c, 0x82, 0xfc, - 0x21, 0x42, 0x85, 0xc3, 0xbc, 0x29, 0xd1, 0x51, 0x07, 0xb8, 0x33, 0x70, 0xe0, 0x01, 0x5b, 0x94, 0x83, 0x03, 0x6a, - 0x2d, 0xee, 0x69, 0x23, 0x71, 0xde, 0x9e, 0x50, 0xbb, 0x08, 0x25, 0x6e, 0xd6, 0xcc, 0xb4, 0xa0, 0xb5, 0x42, 0x3b, - 0x8f, 0x7b, 0xbc, 0xcd, 0xb3, 0x5a, 0xfc, 0x84, 0x0d, 0x6b, 0xaa, 0xfa, 0x0d, 0x34, 0x47, 0xb5, 0x20, 0x37, 0x4f, - 0xb5, 0xb7, 0x2a, 0x19, 0x04, 0xc1, 0xd0, 0x70, 0x2a, 0x44, 0x93, 0x8c, 0x41, 0x6b, 0xe8, 0xdd, 0x6a, 0xaf, 0x56, - 0xdc, 0x21, 0xbe, 0xac, 0x79, 0xab, 0xe9, 0x5b, 0x00, 0x5a, 0x84, 0x41, 0x79, 0x6f, 0x12, 0x80, 0xf7, 0x6d, 0x19, - 0x21, 0x6d, 0x39, 0x30, 0x6f, 0x36, 0x96, 0x8a, 0xcd, 0x77, 0x74, 0x32, 0x8c, 0x03, 0x33, 0xa2, 0x00, 0xdf, 0x94, - 0x90, 0x84, 0xab, 0xa4, 0x1b, 0x99, 0x88, 0x39, 0x93, 0x31, 0xc7, 0x37, 0x85, 0x10, 0xea, 0xda, 0x7c, 0x09, 0x5c, - 0xdd, 0xc9, 0x48, 0x7c, 0x33, 0x61, 0xea, 0x1d, 0x2d, 0x26, 0x0c, 0xfc, 0x8a, 0xdc, 0xed, 0x58, 0x4c, 0xc9, 0xc5, - 0x53, 0x19, 0x0e, 0x28, 0x86, 0x07, 0x47, 0x87, 0x58, 0xe9, 0x10, 0x28, 0x15, 0x2e, 0xb2, 0xdb, 0xbd, 0x37, 0x85, - 0xb8, 0xbb, 0x0f, 0x0b, 0x6c, 0x1d, 0x00, 0x4b, 0xa7, 0x49, 0x80, 0x7f, 0xf9, 0x98, 0x8f, 0xd1, 0x98, 0x53, 0xad, - 0xeb, 0xb7, 0xbf, 0xa3, 0x1b, 0xa0, 0xb7, 0xa5, 0xa3, 0xe0, 0xa0, 0x35, 0x84, 0x5c, 0xb8, 0x0b, 0x83, 0x8b, 0x2f, - 0xbf, 0xb6, 0x28, 0xb4, 0x37, 0x16, 0x40, 0xef, 0xaf, 0x04, 0x2c, 0xd8, 0x30, 0xc7, 0x14, 0x5e, 0x6b, 0x9d, 0x30, - 0xe5, 0x45, 0x05, 0x79, 0x52, 0xbe, 0xc7, 0x59, 0xab, 0xfd, 0x96, 0x8d, 0xe1, 0x0e, 0x23, 0xfa, 0x76, 0xe1, 0xc8, - 0x82, 0x07, 0x64, 0x9a, 0xc4, 0x34, 0xfb, 0xc6, 0x45, 0x1e, 0x79, 0x3d, 0x0e, 0x77, 0xb5, 0xe4, 0xe7, 0xeb, 0x15, - 0x5d, 0x63, 0x08, 0x45, 0xe1, 0xf7, 0xfb, 0x15, 0x1e, 0x28, 0xad, 0x0c, 0xda, 0xa0, 0x61, 0x71, 0x9b, 0xff, 0x02, - 0x67, 0x0c, 0xad, 0x17, 0x32, 0x77, 0x74, 0xc6, 0xe1, 0xcc, 0x62, 0xc6, 0x94, 0xc0, 0xa8, 0x94, 0x28, 0xe8, 0x04, - 0x1c, 0x9d, 0xab, 0x0f, 0x92, 0x87, 0xd5, 0xb1, 0x02, 0xf0, 0x24, 0x53, 0xf8, 0x27, 0xdb, 0x04, 0xeb, 0x7e, 0xab, - 0x66, 0x98, 0xfa, 0x8b, 0xda, 0x76, 0x2d, 0x5f, 0xfa, 0x38, 0xd2, 0xc6, 0x10, 0x5a, 0xe7, 0xee, 0x1e, 0x50, 0xc4, - 0x06, 0xbd, 0x88, 0x15, 0xbe, 0x91, 0x8b, 0x91, 0x5e, 0x5f, 0xed, 0x3a, 0xa6, 0x00, 0x51, 0xac, 0xbb, 0x26, 0xbe, - 0xa9, 0x9e, 0x3f, 0x95, 0x71, 0x0e, 0x67, 0x10, 0x84, 0x38, 0x29, 0x2f, 0x1b, 0x62, 0x41, 0x2e, 0x74, 0xa7, 0x42, - 0x77, 0x5a, 0x21, 0x94, 0x4d, 0x8f, 0xca, 0xfb, 0x57, 0x08, 0x61, 0xa0, 0xcb, 0xec, 0xc0, 0xaa, 0x7c, 0x0b, 0xab, - 0xe0, 0xd5, 0x8b, 0x0d, 0xac, 0x12, 0x70, 0x3c, 0x97, 0x68, 0x54, 0x54, 0x38, 0xa4, 0x49, 0x9f, 0x8f, 0x45, 0x90, - 0x00, 0x58, 0xf4, 0x2e, 0xb1, 0x79, 0xdf, 0xc3, 0x21, 0xbf, 0x27, 0x11, 0xf9, 0xd3, 0x8d, 0x68, 0x06, 0xef, 0xe2, - 0xca, 0xbe, 0x43, 0x08, 0x58, 0x7a, 0x8e, 0xe1, 0x3d, 0xe4, 0xef, 0xbf, 0xc3, 0x6a, 0x2d, 0xc8, 0xe3, 0x7f, 0x89, - 0x92, 0xd0, 0xd8, 0x7f, 0x8e, 0x87, 0x16, 0x09, 0xfd, 0x81, 0x6f, 0x8e, 0xb0, 0xc2, 0xc1, 0xad, 0x22, 0x2e, 0x83, - 0x5b, 0x7c, 0xac, 0x43, 0x0f, 0x00, 0x4b, 0x28, 0xf6, 0x41, 0xbe, 0x81, 0x62, 0x1a, 0x07, 0x14, 0x59, 0xfa, 0x17, - 0xb8, 0x60, 0xb5, 0x50, 0xde, 0xdf, 0xb6, 0x9c, 0x94, 0x56, 0xbb, 0xe4, 0xd5, 0xe6, 0x40, 0xe5, 0xa7, 0x7f, 0xe1, - 0x2b, 0xf5, 0x43, 0xcd, 0xf6, 0x0b, 0xdf, 0x58, 0xa0, 0xc7, 0xa0, 0x08, 0xb0, 0xbf, 0xd7, 0x84, 0x3b, 0x8a, 0x5e, - 0xe6, 0x62, 0xbf, 0x6d, 0xaf, 0x7b, 0x89, 0xb9, 0xbc, 0xae, 0xb2, 0xe6, 0x60, 0x0a, 0x0d, 0x0e, 0xaa, 0x70, 0x46, - 0x60, 0x2e, 0x5f, 0x94, 0x05, 0xe7, 0x20, 0xde, 0xf7, 0xa5, 0xce, 0x29, 0xa3, 0x01, 0xbc, 0x48, 0xca, 0x47, 0xa7, - 0xfa, 0x1c, 0x5c, 0xc6, 0x35, 0x9b, 0xf8, 0x44, 0xba, 0x54, 0x60, 0x25, 0x8d, 0x71, 0x68, 0x40, 0x53, 0x3a, 0x07, - 0xb3, 0x0d, 0xa0, 0xe0, 0xf6, 0x7c, 0xd8, 0x58, 0x28, 0xef, 0x2d, 0xda, 0xda, 0xd3, 0xd1, 0x84, 0x58, 0x93, 0x26, - 0xef, 0x6e, 0x5b, 0x23, 0x83, 0x33, 0xbf, 0xfd, 0xb7, 0xc2, 0x22, 0xc1, 0x80, 0x4a, 0x4d, 0x12, 0x84, 0x27, 0x28, - 0x8d, 0x74, 0x2b, 0x37, 0x13, 0x48, 0x27, 0xb2, 0x66, 0xd4, 0xbd, 0x71, 0xbe, 0x5a, 0x6a, 0x20, 0x2b, 0x6a, 0x90, - 0x7b, 0xd4, 0x40, 0xd4, 0xb7, 0x7f, 0x01, 0x0b, 0x61, 0x22, 0x54, 0x49, 0x2f, 0x20, 0xc2, 0x5c, 0x69, 0x3e, 0xa0, - 0x88, 0x7c, 0xc8, 0x6b, 0x40, 0x85, 0x94, 0xbc, 0x04, 0xa3, 0x71, 0x78, 0xbd, 0x07, 0xdc, 0x2f, 0x0d, 0xc3, 0xe0, - 0x38, 0x05, 0x9d, 0xff, 0xd6, 0xe5, 0x43, 0xf5, 0x72, 0x75, 0x10, 0xc2, 0x4f, 0x24, 0x64, 0x98, 0x46, 0x7e, 0x01, - 0xb2, 0x99, 0x63, 0x71, 0x70, 0x20, 0x40, 0xe0, 0x87, 0x28, 0xc2, 0x1e, 0xcf, 0xf0, 0x32, 0xd9, 0x20, 0x7a, 0x6e, - 0x56, 0x79, 0x35, 0x2b, 0xe1, 0xcd, 0xaa, 0x70, 0x34, 0x8e, 0xae, 0x09, 0x03, 0xc1, 0x85, 0x9a, 0x7d, 0x83, 0x10, - 0x28, 0x5b, 0x6e, 0x35, 0x5d, 0x7a, 0x0a, 0xe6, 0xa3, 0x61, 0xf0, 0x96, 0xc1, 0x8b, 0xba, 0xda, 0xe4, 0x9f, 0x29, - 0x96, 0x28, 0xcd, 0x3c, 0x36, 0x3c, 0x27, 0x75, 0x8a, 0xa2, 0xbf, 0x04, 0xcf, 0xc3, 0xa0, 0x79, 0x11, 0xa0, 0x06, - 0xfc, 0xdb, 0xe0, 0xa8, 0x47, 0x23, 0x9a, 0xa6, 0x2e, 0xf8, 0x4d, 0x42, 0xf4, 0x26, 0x5b, 0xad, 0x64, 0x45, 0xd0, - 0x23, 0xb3, 0xc1, 0x80, 0x95, 0x78, 0x02, 0x3b, 0xd6, 0x70, 0xb0, 0xe4, 0x85, 0x0c, 0x73, 0x77, 0x4a, 0xe1, 0x1c, - 0x43, 0x3a, 0xc2, 0x89, 0x17, 0xb3, 0xf1, 0x3f, 0x9f, 0xa9, 0xbf, 0x7e, 0x6e, 0xbe, 0x96, 0x11, 0x11, 0x2e, 0x88, - 0x5c, 0x8d, 0x1d, 0x91, 0x5e, 0xd8, 0x32, 0x35, 0xb0, 0x65, 0x7e, 0x70, 0xd6, 0xd5, 0x43, 0x13, 0x2e, 0x0e, 0x0c, - 0xa8, 0x91, 0x67, 0xb4, 0x82, 0x33, 0x52, 0x0e, 0x1c, 0x94, 0x10, 0x8a, 0x15, 0xe1, 0x94, 0x5c, 0x40, 0x24, 0xbc, - 0x04, 0xf5, 0xc0, 0xb0, 0xc0, 0x93, 0xa0, 0xa6, 0x20, 0x41, 0x25, 0xae, 0x76, 0x0a, 0xb3, 0xce, 0xf4, 0x6c, 0xa7, - 0xa8, 0x67, 0x83, 0xfc, 0xfc, 0xa2, 0xc2, 0x14, 0x58, 0xda, 0x83, 0x83, 0x02, 0x22, 0x88, 0x01, 0x05, 0x2f, 0x25, - 0x40, 0x4f, 0x03, 0x5e, 0x6c, 0x68, 0xc0, 0xe7, 0x4a, 0x7b, 0x1d, 0x68, 0x5b, 0x9f, 0x32, 0xc8, 0xc5, 0xb3, 0x6a, - 0x4f, 0x13, 0x42, 0xf6, 0x5b, 0x7d, 0x15, 0x6f, 0x47, 0x48, 0xec, 0x7f, 0x54, 0x3a, 0xd0, 0x98, 0x25, 0xdd, 0xd5, - 0xc6, 0x7c, 0x55, 0xd3, 0x23, 0x56, 0x93, 0x10, 0x36, 0x48, 0x97, 0xe3, 0xd3, 0x9e, 0xc1, 0x15, 0xab, 0xd0, 0x72, - 0x70, 0x01, 0xfa, 0x6c, 0x40, 0x80, 0x02, 0x95, 0xa6, 0x12, 0x45, 0x11, 0x16, 0x51, 0xc9, 0x86, 0x61, 0x06, 0x61, - 0x0a, 0xab, 0x95, 0xa0, 0x1b, 0x6b, 0x00, 0xbc, 0x33, 0x33, 0x7f, 0x4a, 0x1f, 0x6c, 0xba, 0x76, 0xe6, 0x11, 0x40, - 0x40, 0xf6, 0xdb, 0x25, 0xbb, 0x2e, 0x37, 0x2a, 0x33, 0xbf, 0x96, 0xb6, 0x95, 0xdb, 0xf6, 0x18, 0x7b, 0x21, 0xb7, - 0xf9, 0x04, 0x08, 0x51, 0x5b, 0x32, 0x8d, 0x10, 0x21, 0xb1, 0x08, 0x55, 0x6d, 0xc8, 0x5a, 0x1b, 0x3a, 0xd0, 0x2f, - 0xd2, 0x43, 0xec, 0x03, 0x50, 0xbc, 0x59, 0x2e, 0xc1, 0x22, 0xbc, 0x74, 0x08, 0x7f, 0x97, 0x83, 0x33, 0x3c, 0x66, - 0x58, 0xac, 0x56, 0x50, 0xcf, 0xe1, 0x7d, 0xb2, 0x19, 0x9c, 0x54, 0x6c, 0x8c, 0x5d, 0x98, 0x89, 0x87, 0x65, 0x13, - 0x02, 0x27, 0xd0, 0xaf, 0xab, 0x88, 0xfa, 0xfb, 0xed, 0xf8, 0xa9, 0x0c, 0x6b, 0x3b, 0x10, 0x6b, 0xd6, 0x1b, 0xac, - 0x3e, 0x80, 0x96, 0xff, 0x93, 0xb8, 0x87, 0xca, 0xbc, 0x9b, 0x84, 0x7c, 0x73, 0x11, 0x7b, 0xac, 0x87, 0x18, 0xa9, - 0x2d, 0xee, 0x0e, 0x21, 0xfe, 0x9f, 0xad, 0x28, 0x06, 0x3c, 0xaa, 0xf8, 0xe7, 0x10, 0xf5, 0x20, 0x14, 0xb5, 0xf1, - 0xb0, 0x01, 0x4a, 0xbb, 0x5c, 0x57, 0x62, 0xa4, 0x4f, 0x20, 0xdf, 0xda, 0xf0, 0x82, 0xfa, 0x24, 0xca, 0x41, 0x4e, - 0xf6, 0xa2, 0x92, 0x26, 0x1b, 0xc2, 0x5c, 0x6f, 0x0b, 0xc7, 0xf4, 0xd5, 0x06, 0x2d, 0xc2, 0x17, 0xc0, 0xce, 0x70, - 0x2d, 0x59, 0x5a, 0xf0, 0xe5, 0x35, 0xf0, 0xb9, 0x35, 0xd7, 0x14, 0x25, 0x47, 0xfd, 0x17, 0x52, 0xdf, 0xfa, 0xc3, - 0xef, 0xd8, 0x13, 0x1f, 0xa9, 0xd5, 0x91, 0x6c, 0x84, 0x5a, 0xb3, 0x76, 0xbc, 0x6c, 0x33, 0xc2, 0xa0, 0x34, 0xd1, - 0xfb, 0x2a, 0x64, 0x95, 0x3b, 0x3b, 0x95, 0xde, 0x9c, 0xbe, 0xe6, 0x95, 0x73, 0x2a, 0x37, 0x8c, 0x6a, 0xa9, 0x69, - 0x80, 0x08, 0x57, 0x2e, 0x91, 0xbc, 0x4f, 0x74, 0xf8, 0x07, 0x8d, 0x71, 0xf5, 0x48, 0xe1, 0xef, 0x77, 0xc5, 0x0e, - 0xd9, 0x8e, 0x0e, 0xb7, 0x11, 0x34, 0xcf, 0x57, 0xf0, 0x80, 0xa3, 0x92, 0x21, 0x44, 0x39, 0xb9, 0xd8, 0xcf, 0x6b, - 0xa6, 0x6c, 0x37, 0x01, 0x42, 0x48, 0x39, 0x9c, 0x75, 0x0e, 0x91, 0xb5, 0xd0, 0x23, 0x55, 0x94, 0xc3, 0x2d, 0x9a, - 0x6b, 0x03, 0x54, 0x68, 0x81, 0x74, 0xf9, 0x85, 0xdd, 0xc7, 0x02, 0xa2, 0x97, 0xaf, 0x6d, 0x08, 0x63, 0x6b, 0x65, - 0x89, 0x0b, 0x3d, 0x6a, 0x13, 0x46, 0xd7, 0x6e, 0x0c, 0x6b, 0x03, 0xa3, 0xa7, 0x41, 0x49, 0x0b, 0x42, 0x5d, 0xf7, - 0xe8, 0x79, 0xa2, 0x03, 0x3d, 0x66, 0x84, 0x36, 0x18, 0x9e, 0x12, 0x05, 0x96, 0x4d, 0x05, 0x58, 0xf0, 0x2d, 0x8b, - 0x38, 0xd7, 0x36, 0x9b, 0x2c, 0xfc, 0xa8, 0x42, 0xfd, 0xb4, 0x5f, 0x56, 0x31, 0xcf, 0x85, 0xa5, 0x6e, 0xcf, 0x13, - 0x17, 0x8f, 0xee, 0xe9, 0x9b, 0xeb, 0x17, 0x2f, 0x5f, 0xbf, 0x5a, 0xad, 0xda, 0xac, 0xd9, 0x3e, 0xc1, 0x3f, 0xa9, - 0x32, 0x1e, 0x6c, 0x19, 0x05, 0xe8, 0xe0, 0x60, 0x9f, 0x6b, 0x17, 0x9e, 0x2f, 0x7c, 0x0e, 0x71, 0x83, 0xd4, 0x10, - 0x27, 0x45, 0x19, 0x13, 0xe4, 0x2e, 0xe8, 0x07, 0xf7, 0x01, 0x28, 0xa1, 0x2a, 0xf2, 0xf7, 0x61, 0x73, 0xf6, 0x7b, - 0x10, 0x98, 0x08, 0xea, 0x43, 0x04, 0x10, 0x88, 0x57, 0x8a, 0x0b, 0xc2, 0x5c, 0x02, 0x44, 0xf1, 0x5e, 0xc0, 0x9b, - 0x90, 0x3a, 0x6a, 0xd5, 0x22, 0x0f, 0x0b, 0x20, 0x89, 0x26, 0x1c, 0x25, 0x3d, 0xd2, 0x01, 0xbc, 0x21, 0x28, 0xa5, - 0xf9, 0xd5, 0xcb, 0xac, 0xbb, 0x54, 0x86, 0xfa, 0xad, 0x38, 0xc3, 0x53, 0xfb, 0x39, 0x85, 0xcf, 0x69, 0xcf, 0x9d, - 0x0e, 0xf2, 0x30, 0xc3, 0x0b, 0x22, 0x0f, 0xdd, 0xb3, 0x88, 0xcb, 0x79, 0xc1, 0xbe, 0x72, 0xb1, 0x90, 0xf1, 0xf2, - 0x2e, 0x16, 0xd1, 0x5d, 0x33, 0x3d, 0x0c, 0x8b, 0xe8, 0xae, 0x99, 0x47, 0x77, 0x08, 0xdf, 0xc7, 0x22, 0xba, 0x37, - 0x29, 0xf7, 0xcd, 0x1c, 0x6e, 0xbe, 0x70, 0x0e, 0x87, 0xa2, 0x29, 0xda, 0x58, 0x6c, 0x16, 0x35, 0x29, 0xb6, 0xa8, - 0x87, 0xc1, 0xbf, 0xef, 0xd8, 0xf8, 0x7e, 0xf8, 0x12, 0x5c, 0x9a, 0x34, 0x91, 0x9f, 0x40, 0xfa, 0x69, 0x55, 0x06, - 0xee, 0x53, 0xd2, 0xea, 0x4d, 0xcf, 0x65, 0xb3, 0xdd, 0x6b, 0x34, 0xa6, 0xb0, 0x77, 0x13, 0x92, 0xb9, 0x62, 0xd3, - 0x86, 0x8e, 0xaf, 0xb3, 0x9f, 0xac, 0x56, 0xfb, 0x19, 0xd2, 0x1b, 0x6e, 0xc2, 0x42, 0x35, 0x98, 0x0e, 0x71, 0x0b, - 0x3f, 0x4f, 0x10, 0x5a, 0xb2, 0xc1, 0x74, 0x48, 0xd8, 0x60, 0xda, 0x68, 0x0f, 0x8d, 0xa1, 0x9d, 0xde, 0x8a, 0x6b, - 0x08, 0xa1, 0x39, 0x1d, 0x1e, 0xe9, 0x92, 0xc2, 0xe6, 0x9b, 0x2f, 0x5a, 0x05, 0xf4, 0xcb, 0x6b, 0xc1, 0xcb, 0x04, - 0xee, 0x40, 0x5f, 0xf4, 0xdc, 0x3c, 0xdd, 0x5a, 0x90, 0xe3, 0xa3, 0xca, 0xd5, 0x9e, 0x22, 0xac, 0x7b, 0xca, 0x0f, - 0x8b, 0x43, 0xdd, 0x8c, 0xed, 0x52, 0xd8, 0x6f, 0x5f, 0x33, 0xf2, 0xd1, 0xc2, 0x02, 0x10, 0xa4, 0x82, 0x47, 0x52, - 0xd8, 0x70, 0x4a, 0x3e, 0x5c, 0x2c, 0x54, 0xb6, 0x60, 0x92, 0x91, 0x56, 0x2f, 0xd3, 0x96, 0xfe, 0x99, 0x8d, 0x68, - 0x4a, 0x31, 0x25, 0x89, 0x2b, 0x99, 0x69, 0xb0, 0xd0, 0x4d, 0xca, 0x33, 0x05, 0xbd, 0xd2, 0x10, 0xa7, 0x04, 0xe2, - 0x21, 0xf5, 0x0a, 0x6d, 0xe0, 0x15, 0x4e, 0x9b, 0xc5, 0x80, 0x0d, 0xd1, 0xd1, 0x31, 0xa6, 0x83, 0xcf, 0xc9, 0xbc, - 0x0d, 0x8f, 0x05, 0x7e, 0x1e, 0x92, 0x69, 0x53, 0x94, 0x09, 0x12, 0x12, 0xd2, 0xa6, 0x38, 0x84, 0xbd, 0x84, 0x70, - 0x62, 0x2a, 0x26, 0x03, 0x36, 0x6c, 0x4e, 0xcb, 0x8a, 0x1d, 0x57, 0xb1, 0x21, 0xca, 0x04, 0x53, 0xb1, 0x61, 0x2b, - 0xfa, 0xaf, 0x33, 0x68, 0x10, 0xf8, 0x00, 0x60, 0x00, 0x00, 0x85, 0xbc, 0x68, 0xbe, 0x38, 0x27, 0x6e, 0xb3, 0x9b, - 0x7b, 0xfc, 0x16, 0x58, 0xa0, 0xd5, 0xf6, 0xff, 0x2e, 0x94, 0x01, 0x7b, 0xca, 0x42, 0xc7, 0xcc, 0x2d, 0x8c, 0x8a, - 0x0e, 0xa0, 0x52, 0x22, 0x4c, 0xa1, 0x21, 0xb3, 0x9f, 0x68, 0xa8, 0x79, 0x5a, 0x83, 0x6c, 0xa0, 0x86, 0xcd, 0x04, - 0x8e, 0x18, 0x78, 0x87, 0x86, 0x4c, 0xb5, 0x31, 0x61, 0x98, 0xc1, 0x14, 0x13, 0x0d, 0x9e, 0x69, 0xdc, 0x5a, 0x0b, - 0x2d, 0xcb, 0xf5, 0xb3, 0xfe, 0xdf, 0x2a, 0xcc, 0x07, 0x45, 0xb3, 0x3d, 0x44, 0xfb, 0x84, 0x98, 0x8f, 0x21, 0x6c, - 0x32, 0x9b, 0xda, 0xd0, 0xdf, 0x47, 0x9d, 0xd8, 0x7c, 0xc2, 0x9f, 0xe1, 0x5a, 0xef, 0x00, 0x1d, 0x78, 0x50, 0xaf, - 0xbf, 0xa8, 0xa9, 0xbc, 0x3e, 0xee, 0x8c, 0x52, 0xb9, 0xeb, 0xdd, 0x69, 0x4f, 0x53, 0xec, 0x7b, 0xeb, 0xe1, 0xf2, - 0xa1, 0x1e, 0x02, 0x66, 0x0c, 0xfa, 0x96, 0x19, 0x7d, 0x2f, 0x44, 0x72, 0x41, 0x04, 0x16, 0x1a, 0x6b, 0x18, 0xec, - 0xad, 0x83, 0x03, 0x5d, 0x8d, 0x35, 0xe0, 0x79, 0x52, 0x04, 0x82, 0x81, 0x8b, 0xa0, 0x0c, 0x68, 0x92, 0xeb, 0xdb, - 0x70, 0xf2, 0x91, 0xd9, 0x5f, 0xb8, 0xbc, 0x7d, 0x2c, 0x8c, 0xb6, 0x55, 0x27, 0xdf, 0x97, 0x05, 0xee, 0xcb, 0x7b, - 0x49, 0xa3, 0xe0, 0x46, 0xe6, 0x26, 0x2f, 0xd7, 0x77, 0xeb, 0xae, 0x54, 0x67, 0x77, 0x33, 0x9d, 0xb2, 0x99, 0xce, - 0x76, 0x33, 0xbe, 0x66, 0xe6, 0x5b, 0x56, 0x91, 0xfa, 0x64, 0x8d, 0xe4, 0x9c, 0xe6, 0x3f, 0xd1, 0x39, 0x18, 0x05, - 0x73, 0x73, 0xaf, 0x0a, 0x27, 0x57, 0x46, 0x2e, 0xf6, 0x33, 0x4d, 0x5c, 0x91, 0xbe, 0x50, 0x87, 0x00, 0x2f, 0x2f, - 0xca, 0xc7, 0x07, 0xb8, 0xc8, 0x7f, 0x15, 0xa9, 0x8d, 0x72, 0x9a, 0x0b, 0x25, 0x72, 0x16, 0x20, 0x8d, 0xaa, 0x36, - 0x06, 0xf6, 0xd2, 0xec, 0x3d, 0xd9, 0xe7, 0x83, 0x2a, 0x62, 0xde, 0x50, 0x3f, 0xf7, 0xf1, 0x3d, 0x4d, 0xb1, 0x55, - 0x13, 0x27, 0xe4, 0x43, 0x12, 0x66, 0x20, 0x9b, 0x0d, 0xaa, 0xd7, 0x7e, 0x1b, 0x6d, 0x5c, 0x34, 0x43, 0xd9, 0xd7, - 0x4f, 0x9c, 0xfc, 0x50, 0x68, 0xe3, 0x00, 0xe3, 0xe8, 0x8f, 0x30, 0x35, 0x60, 0x4f, 0x22, 0x47, 0xa1, 0xa3, 0x3b, - 0x93, 0x76, 0xef, 0xa7, 0xdd, 0xeb, 0xb4, 0x0e, 0x94, 0x03, 0xd2, 0x6c, 0xcb, 0x74, 0xee, 0xdd, 0xf7, 0x3d, 0xbc, - 0x74, 0xbb, 0x86, 0x48, 0xdc, 0xf3, 0xc7, 0xda, 0x18, 0xe2, 0x0d, 0xd8, 0x88, 0xca, 0x83, 0x83, 0x3f, 0xac, 0xf7, - 0x6d, 0x25, 0xcb, 0xca, 0x6f, 0x84, 0x03, 0xdb, 0x60, 0x2a, 0x6d, 0x5e, 0x2a, 0x92, 0x05, 0xd8, 0x75, 0xee, 0xef, - 0x8e, 0x87, 0xff, 0x52, 0xfa, 0x4c, 0x8b, 0x71, 0x15, 0x7f, 0x25, 0xd2, 0xd2, 0x43, 0x54, 0x41, 0x04, 0xd2, 0xca, - 0xba, 0xd4, 0x37, 0x1d, 0xbd, 0x9e, 0xd2, 0x54, 0xdc, 0xbe, 0x15, 0x42, 0x0d, 0xcd, 0x8b, 0xdc, 0x2a, 0x82, 0x47, - 0x0b, 0x6b, 0x0c, 0xcd, 0x7d, 0xe9, 0x9d, 0x64, 0x02, 0xa2, 0xd6, 0xc7, 0xed, 0x4b, 0x22, 0xa1, 0xac, 0xee, 0x42, - 0x38, 0xdc, 0x85, 0x60, 0x5e, 0x06, 0x6d, 0x83, 0xd8, 0xed, 0x36, 0x68, 0x5b, 0x28, 0x89, 0x34, 0x81, 0xdb, 0xbd, - 0xc1, 0xc2, 0xde, 0x87, 0x97, 0x63, 0x39, 0x96, 0xee, 0x9a, 0xcc, 0x3c, 0x00, 0x04, 0x6a, 0x1f, 0x56, 0x3c, 0xb1, - 0x20, 0x88, 0xac, 0xe1, 0xe8, 0x7b, 0xce, 0x6e, 0x8d, 0xe5, 0xf0, 0x6c, 0xbe, 0x50, 0x2c, 0xd5, 0x77, 0xd4, 0x80, - 0x3f, 0x75, 0x3f, 0xaf, 0x9f, 0x92, 0x9a, 0x6e, 0xfc, 0x01, 0x84, 0x91, 0xb0, 0xca, 0x0e, 0xad, 0x90, 0x30, 0xc1, - 0xac, 0xca, 0x78, 0x6d, 0xbf, 0x41, 0xbc, 0x07, 0xa5, 0xc3, 0x09, 0x16, 0xb5, 0x0b, 0xaa, 0x00, 0x9b, 0x78, 0x63, - 0x5e, 0x94, 0x87, 0x37, 0x5b, 0x46, 0xd3, 0xcb, 0x35, 0x04, 0x3a, 0xee, 0x07, 0xcd, 0xa0, 0xc1, 0x62, 0x1b, 0x94, - 0xd9, 0x45, 0x18, 0xcf, 0xcf, 0x4f, 0x74, 0x9c, 0xf6, 0x52, 0xaf, 0xfe, 0x5b, 0x02, 0x06, 0xf8, 0x12, 0xbc, 0xc4, - 0xfc, 0xe8, 0xae, 0x03, 0xd5, 0x80, 0xfa, 0xa2, 0xc1, 0x86, 0x68, 0xb5, 0x6a, 0x95, 0xcf, 0x40, 0xd9, 0x6b, 0x2e, - 0x69, 0xae, 0xb9, 0xa4, 0xbd, 0xe6, 0x92, 0xee, 0x9a, 0x4b, 0xea, 0x6b, 0x2e, 0xe9, 0xae, 0xb9, 0x1c, 0x08, 0x3f, - 0x79, 0x71, 0x1c, 0x43, 0x0e, 0x71, 0x15, 0x95, 0x89, 0x8c, 0x07, 0x17, 0x9e, 0xfb, 0x2c, 0x92, 0xe5, 0xf2, 0xfb, - 0x31, 0xe4, 0xb6, 0x6c, 0x25, 0xb4, 0xdb, 0x14, 0x93, 0x10, 0x39, 0xfd, 0xe0, 0xa0, 0x74, 0x77, 0x06, 0x1f, 0xf5, - 0x98, 0xe3, 0xa5, 0x71, 0xa2, 0xfd, 0x03, 0x74, 0xf2, 0xfa, 0xd7, 0xc7, 0x58, 0xac, 0x89, 0xb4, 0x26, 0xf7, 0xfb, - 0x6d, 0x47, 0x29, 0x3e, 0x25, 0x3a, 0x3c, 0x39, 0x8f, 0x94, 0x16, 0x41, 0x10, 0xa2, 0x24, 0xc7, 0x09, 0x11, 0x66, - 0xbf, 0x3b, 0x57, 0x78, 0xad, 0x8a, 0x72, 0x66, 0x25, 0x57, 0x19, 0x38, 0xb1, 0x6b, 0x2b, 0x0c, 0xd4, 0x03, 0x17, - 0x82, 0x44, 0x27, 0xfc, 0xd1, 0xcc, 0x0c, 0x39, 0x4b, 0xca, 0xa4, 0x8f, 0xcd, 0x4c, 0x13, 0xb0, 0x82, 0xec, 0x3b, - 0x98, 0x2d, 0xef, 0x62, 0x8a, 0xef, 0xe3, 0x04, 0xff, 0xbf, 0xec, 0xbd, 0xeb, 0x92, 0xdb, 0x46, 0x96, 0x2e, 0xfa, - 0x2a, 0x55, 0x0c, 0x99, 0x06, 0xc4, 0x24, 0x8b, 0xa5, 0xbd, 0x67, 0x22, 0x0e, 0x58, 0x29, 0x86, 0x2c, 0x59, 0xdd, - 0x72, 0x5b, 0x97, 0x56, 0xa9, 0xdd, 0x76, 0x33, 0x78, 0x68, 0x14, 0x90, 0x24, 0x20, 0x83, 0x00, 0x0d, 0x80, 0x55, - 0xa4, 0x48, 0xbc, 0xfb, 0x8e, 0xb5, 0x56, 0x5e, 0x41, 0xb0, 0xa4, 0x9e, 0xd9, 0xf3, 0xeb, 0x9c, 0x3f, 0x52, 0x31, - 0x91, 0x48, 0xe4, 0x3d, 0x57, 0xae, 0xcb, 0xf7, 0xdd, 0x15, 0xbb, 0xa0, 0xb4, 0x7d, 0x41, 0x94, 0xe1, 0x6f, 0xe9, - 0xf5, 0xf2, 0x10, 0xe2, 0x7d, 0x7a, 0x69, 0x7e, 0x91, 0xb6, 0xa2, 0x00, 0x0f, 0x11, 0x7a, 0x54, 0x07, 0x82, 0x9d, - 0xf1, 0x84, 0x07, 0x70, 0xb2, 0x9a, 0xe5, 0xfc, 0x49, 0x0a, 0xe2, 0x44, 0xc1, 0x21, 0xe0, 0x6a, 0x77, 0x9b, 0x7e, - 0x01, 0xc3, 0x97, 0x0e, 0xb6, 0x1c, 0xde, 0x15, 0xbb, 0x1e, 0x2b, 0xf9, 0x07, 0x60, 0xdf, 0xea, 0xc9, 0x58, 0xdd, - 0x1e, 0x38, 0xeb, 0x52, 0x8a, 0x8e, 0x37, 0xc5, 0xe1, 0xed, 0xf9, 0xec, 0xb0, 0x0b, 0x22, 0xb6, 0x0f, 0x32, 0xac, - 0x75, 0xd2, 0xf0, 0x9f, 0x68, 0xeb, 0x60, 0x31, 0xc2, 0xfe, 0x2f, 0xeb, 0x81, 0x97, 0x90, 0x1a, 0x0a, 0x5c, 0x0c, - 0xb6, 0x1c, 0xad, 0xed, 0x32, 0x0d, 0xdc, 0xd4, 0xa0, 0xd7, 0x0f, 0x14, 0xa2, 0xbc, 0x64, 0x34, 0x37, 0x82, 0x4d, - 0x63, 0xc8, 0xc5, 0xe1, 0xb8, 0x59, 0x0e, 0x79, 0x49, 0xd3, 0x69, 0x10, 0x4a, 0x77, 0x96, 0x0d, 0x24, 0x51, 0xf6, - 0x41, 0xa8, 0x5d, 0x5b, 0x0e, 0xbb, 0xc0, 0xf6, 0xe5, 0x8f, 0x86, 0xb1, 0x7f, 0xb5, 0x7c, 0x2a, 0xa4, 0x8b, 0x78, - 0x05, 0x82, 0xa8, 0xfd, 0x3c, 0x1b, 0x6e, 0xfd, 0xab, 0xcd, 0x53, 0xa1, 0xfc, 0xc6, 0x2b, 0x5b, 0x0e, 0xa9, 0xb3, - 0x16, 0xbe, 0x30, 0x1e, 0x1e, 0x5c, 0x19, 0xda, 0x8e, 0x47, 0xa1, 0xff, 0x36, 0x6b, 0x04, 0x37, 0x36, 0xb4, 0xcf, - 0x17, 0x3e, 0x6c, 0x6d, 0x34, 0xd6, 0x14, 0xd3, 0x2d, 0xf4, 0x6f, 0x32, 0x5b, 0xda, 0xd3, 0xa8, 0xe4, 0xc5, 0xb9, - 0x69, 0xc4, 0x42, 0x18, 0x30, 0xf4, 0x93, 0xf9, 0x00, 0xaa, 0xb9, 0xd3, 0x11, 0xc8, 0xe4, 0x03, 0x3d, 0x58, 0x93, - 0x5a, 0xf5, 0xd7, 0x30, 0x93, 0xff, 0x47, 0x2a, 0x2c, 0x46, 0x77, 0xdb, 0x30, 0x53, 0x7f, 0x44, 0xf2, 0x0f, 0x56, - 0xf1, 0x7d, 0xea, 0x85, 0xda, 0x8f, 0x85, 0x15, 0x18, 0x94, 0xa8, 0x1a, 0xd0, 0x03, 0x11, 0x54, 0x65, 0x90, 0x66, - 0x58, 0x9d, 0x83, 0x7e, 0xf7, 0xb4, 0xea, 0x48, 0x0e, 0x69, 0xad, 0x86, 0x54, 0x30, 0x55, 0x6a, 0x50, 0x1d, 0x8f, - 0xab, 0x94, 0xe9, 0x32, 0xe0, 0x92, 0xbe, 0x4a, 0x95, 0x52, 0xf8, 0x4f, 0x04, 0xa0, 0x73, 0x70, 0x8f, 0xaf, 0xc7, - 0x40, 0x9a, 0x61, 0xe1, 0xb7, 0x66, 0xa7, 0xd7, 0x24, 0xdc, 0x26, 0xc1, 0xc5, 0x00, 0xe7, 0xe8, 0x3a, 0x2c, 0x57, - 0x29, 0x44, 0x50, 0x95, 0x50, 0xdf, 0xdc, 0x34, 0x28, 0x6d, 0x35, 0x08, 0x6b, 0x12, 0xea, 0x4c, 0xb2, 0x51, 0x69, - 0xbb, 0x51, 0x98, 0x2d, 0xe2, 0x7a, 0x46, 0x58, 0x73, 0x36, 0x53, 0x0d, 0x4c, 0x1a, 0x8e, 0x9b, 0x46, 0x6b, 0x51, - 0xa1, 0xa6, 0x30, 0xaf, 0x71, 0x55, 0xa9, 0xea, 0x6e, 0xcf, 0x2d, 0xa5, 0x65, 0x7b, 0xd5, 0x4d, 0xb2, 0x21, 0x97, - 0xa1, 0x0c, 0x83, 0xad, 0x1c, 0xc1, 0x04, 0x92, 0xe4, 0xcc, 0xdf, 0xca, 0x3f, 0xd4, 0xa6, 0x6b, 0x01, 0x73, 0x8c, - 0x59, 0x36, 0x2c, 0xe8, 0x15, 0xb8, 0x07, 0x5a, 0xe9, 0xd5, 0x34, 0xbb, 0xaa, 0x82, 0x64, 0x58, 0xe8, 0x65, 0x93, - 0xf1, 0x3f, 0x85, 0x91, 0x26, 0x33, 0x56, 0xb2, 0xc8, 0x76, 0x75, 0x4a, 0x9c, 0xc7, 0x09, 0x6c, 0x8f, 0xa6, 0xb7, - 0x7c, 0x9f, 0x41, 0x54, 0x10, 0x28, 0x98, 0x31, 0x5f, 0x76, 0xf5, 0xcc, 0xf7, 0x99, 0x65, 0xea, 0x3e, 0x1e, 0x8d, - 0x19, 0xdb, 0xef, 0xf7, 0xab, 0x7e, 0x5f, 0xcd, 0xb7, 0x7e, 0x3f, 0x79, 0x6e, 0xfe, 0xf6, 0x80, 0x41, 0x41, 0x4e, - 0x44, 0x53, 0x21, 0x82, 0x7f, 0x48, 0x9e, 0x22, 0x19, 0xdd, 0x69, 0x9f, 0x5b, 0xce, 0x96, 0xf9, 0x09, 0x08, 0xe6, - 0xf1, 0x78, 0xad, 0xc0, 0xae, 0x25, 0x8a, 0x84, 0x2c, 0xff, 0x29, 0x18, 0xcf, 0xdc, 0x07, 0x58, 0x32, 0x00, 0x61, - 0xab, 0x3c, 0x5d, 0xef, 0xf9, 0x2a, 0x78, 0xa7, 0xe3, 0x5d, 0x63, 0x45, 0x06, 0xe2, 0x16, 0xd8, 0x88, 0xb5, 0xf6, - 0x80, 0x9c, 0x29, 0xc0, 0xf1, 0xe2, 0x78, 0xbc, 0x94, 0xbf, 0x74, 0xb3, 0x75, 0x02, 0x95, 0x02, 0xb7, 0x47, 0x27, - 0x07, 0xff, 0x1d, 0x68, 0x06, 0xe5, 0x30, 0x6f, 0x76, 0xbf, 0x33, 0x27, 0x3f, 0x3d, 0xc5, 0x3f, 0xe1, 0x21, 0x3a, - 0xfd, 0x76, 0x6f, 0xfe, 0xa0, 0xa8, 0x3c, 0x1e, 0xd5, 0xe2, 0x07, 0x9e, 0x1f, 0xf8, 0x85, 0x6f, 0x02, 0xb3, 0xc9, - 0xd4, 0x3b, 0xfb, 0x26, 0xaf, 0x98, 0x7a, 0x8d, 0xe7, 0x4c, 0xbe, 0xc3, 0xe1, 0x5c, 0x8c, 0xea, 0xdd, 0xc8, 0x89, - 0x76, 0xaa, 0x30, 0x0e, 0x06, 0xff, 0x45, 0xb4, 0x4d, 0x08, 0x30, 0xa4, 0x6e, 0x49, 0x33, 0x1b, 0x57, 0x96, 0x78, - 0x96, 0x2e, 0xaf, 0x27, 0x75, 0xb9, 0xd7, 0x8a, 0xa7, 0x03, 0xb0, 0xb8, 0x6d, 0xc0, 0x0b, 0xe0, 0xde, 0x62, 0xeb, - 0x4a, 0xc1, 0xe1, 0x02, 0xe2, 0x14, 0x27, 0x20, 0x82, 0xf6, 0xfb, 0x12, 0xef, 0x15, 0xf4, 0x49, 0x3f, 0x42, 0x30, - 0xe4, 0xcf, 0x12, 0x70, 0xd7, 0xeb, 0xd5, 0x18, 0xdf, 0x4b, 0x21, 0xb8, 0x3e, 0xd3, 0x00, 0xb4, 0xe0, 0x77, 0xf9, - 0x58, 0x4e, 0xbf, 0x89, 0xc0, 0xb3, 0xe5, 0x60, 0xa2, 0xdc, 0x6d, 0x78, 0xda, 0x3f, 0x5a, 0x08, 0xc0, 0x52, 0x3c, - 0x53, 0x82, 0x05, 0x39, 0xc5, 0x5c, 0xfd, 0xbf, 0xe0, 0x23, 0xe6, 0x7b, 0xd2, 0x45, 0x6c, 0xb3, 0x7b, 0x72, 0x65, - 0x20, 0x81, 0xa6, 0x03, 0xe0, 0x21, 0x54, 0x40, 0x57, 0xc6, 0xcf, 0xcf, 0xb2, 0x1e, 0xeb, 0xe3, 0x3f, 0x05, 0xf7, - 0xe9, 0xa7, 0x0a, 0x1f, 0x1d, 0x8e, 0xab, 0x74, 0xb4, 0xa7, 0x14, 0x44, 0x47, 0xb7, 0xcf, 0xa7, 0x2a, 0xfb, 0xa6, - 0x02, 0x2a, 0xcb, 0x51, 0x7b, 0x2a, 0x00, 0x8b, 0x2d, 0x1d, 0x81, 0x4f, 0xb3, 0x7c, 0x42, 0xbe, 0xd7, 0x53, 0x71, - 0x73, 0xad, 0xd3, 0xc5, 0xf3, 0xf1, 0x14, 0xfe, 0x07, 0x62, 0x0f, 0xcb, 0x14, 0xd9, 0xb1, 0xeb, 0xe2, 0x07, 0xf1, - 0xb6, 0xb6, 0xa7, 0x3f, 0xf6, 0x10, 0xe9, 0x78, 0x20, 0x17, 0xea, 0x6b, 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, 0x56, 0xb6, 0xc8, 0xb8, 0x7a, 0x14, 0x52, 0x35, 0x3d, 0xdc, 0x89, 0xfa, 0x41, 0x88, 0x3c, 0x58, 0xa7, 0x2c, - 0x2a, 0xd6, 0x20, 0xb3, 0x07, 0x7f, 0x0f, 0x19, 0x39, 0xca, 0x81, 0xa3, 0xd0, 0x5f, 0x9a, 0x40, 0xe7, 0xf9, 0x29, - 0xd4, 0x79, 0x24, 0xd8, 0x4a, 0x3d, 0x14, 0x56, 0x5e, 0x40, 0x74, 0xb0, 0x85, 0xb1, 0xdc, 0x93, 0x50, 0xb1, 0x29, - 0x13, 0x79, 0x1c, 0xd4, 0x12, 0x30, 0x56, 0x10, 0xcc, 0x59, 0x25, 0x5d, 0x90, 0xf2, 0x46, 0x0f, 0x8b, 0xcc, 0xfd, - 0x9d, 0xa0, 0xfc, 0xdf, 0xa9, 0x9c, 0x70, 0x7d, 0x19, 0x02, 0x1c, 0xed, 0x77, 0x20, 0x4a, 0x8c, 0xf5, 0x8b, 0x16, - 0xef, 0x64, 0xe6, 0x6c, 0x6a, 0x07, 0x09, 0x32, 0xb6, 0xc7, 0xaf, 0x10, 0x5a, 0x2d, 0x14, 0x59, 0x34, 0x5c, 0x30, - 0xdd, 0x9e, 0xd2, 0xaa, 0x7b, 0xd8, 0xf0, 0xac, 0xf4, 0x50, 0xa9, 0x6f, 0x63, 0x02, 0xcb, 0x2a, 0x65, 0xf8, 0x76, - 0x42, 0xd5, 0x89, 0x41, 0xc5, 0xba, 0x65, 0x4b, 0x38, 0xc4, 0x62, 0xd2, 0x58, 0x67, 0x03, 0x1e, 0xb1, 0x04, 0xfe, - 0xd9, 0xf2, 0x31, 0x5b, 0xf2, 0x68, 0xb2, 0xbd, 0x59, 0xf6, 0xfb, 0xa5, 0x17, 0x7a, 0xf5, 0x2c, 0xfb, 0x2e, 0x9a, - 0xcf, 0xaa, 0xb9, 0x8f, 0x8a, 0x8b, 0xc9, 0x60, 0xb0, 0xf5, 0xb3, 0xe1, 0x90, 0x25, 0xc3, 0xe1, 0x24, 0xfb, 0x0e, - 0x5e, 0xfb, 0x8e, 0x47, 0x6a, 0x49, 0x25, 0x37, 0x19, 0xec, 0xef, 0x03, 0x1e, 0xf9, 0xac, 0xf3, 0xd3, 0xb2, 0xe9, - 0xd2, 0xfd, 0xcc, 0x8e, 0xbb, 0xd0, 0x1d, 0x60, 0xe3, 0x6d, 0x83, 0x8e, 0xfc, 0xeb, 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, 0x65, 0xe5, 0x96, 0x0d, 0xd7, 0xc3, 0xc1, 0x36, 0x8a, 0xcb, 0x66, 0x05, 0xf7, 0x85, 0x35, 0x05, 0xfe, - 0xdf, 0xb1, 0x05, 0xbb, 0x97, 0xc7, 0xc0, 0x5b, 0x74, 0x4c, 0x82, 0x0b, 0xc4, 0x3d, 0xbb, 0x03, 0x3b, 0x2c, 0xfc, - 0x05, 0xd7, 0xc9, 0x31, 0xdb, 0xe3, 0xa3, 0xd0, 0x2b, 0xd8, 0x9d, 0x4f, 0x40, 0xbb, 0x60, 0x6b, 0x80, 0x6c, 0x6c, - 0x87, 0x8f, 0x56, 0xc7, 0xe3, 0x5b, 0xcf, 0x67, 0x0f, 0xf8, 0xe3, 0x72, 0x75, 0x3c, 0xee, 0x3d, 0xa3, 0xde, 0xbb, - 0xe5, 0x09, 0x7b, 0xcf, 0x93, 0xc9, 0xed, 0x0d, 0x8f, 0x27, 0x83, 0xc1, 0xad, 0xbf, 0xe0, 0xf5, 0xec, 0x16, 0xb4, - 0x03, 0x97, 0x0b, 0xa9, 0x6b, 0xf6, 0xee, 0x78, 0xe6, 0x2d, 0x70, 0x6c, 0xee, 0xe0, 0xe8, 0xed, 0xf7, 0xbd, 0x15, - 0x8f, 0xbc, 0x3b, 0x52, 0x31, 0xad, 0xb9, 0xe2, 0x78, 0xdb, 0xe1, 0x7e, 0xba, 0xe6, 0x21, 0x3c, 0xc2, 0xaa, 0x4c, - 0x6f, 0x83, 0xf7, 0x3e, 0x5b, 0x6b, 0x16, 0xb8, 0x07, 0xcc, 0xb1, 0x21, 0x3b, 0xa1, 0x99, 0xf8, 0x6b, 0xec, 0x9f, - 0x5b, 0xd5, 0x3f, 0x34, 0xff, 0x4b, 0xdd, 0x4f, 0xe0, 0xf6, 0x45, 0x16, 0x24, 0xf6, 0x9e, 0xdf, 0xb2, 0x7b, 0x6e, - 0xd8, 0x66, 0x2f, 0x4c, 0xd9, 0x67, 0x4a, 0x8d, 0x1f, 0x29, 0x75, 0x63, 0x19, 0x56, 0x32, 0x77, 0x5f, 0x46, 0xe0, - 0x70, 0x40, 0x7e, 0x5a, 0x21, 0x0e, 0x42, 0xeb, 0x26, 0xab, 0xb9, 0xa2, 0x9c, 0x0b, 0x6d, 0x99, 0x79, 0x15, 0xb0, - 0x98, 0xa5, 0x14, 0x1a, 0x0b, 0x00, 0x04, 0x93, 0x42, 0x6b, 0xef, 0x65, 0x00, 0x39, 0x41, 0xc3, 0x9f, 0x9a, 0xab, - 0xa2, 0xac, 0x65, 0x4b, 0x42, 0x94, 0xed, 0x7a, 0x78, 0x8d, 0x90, 0x69, 0xfd, 0xfe, 0x25, 0x91, 0xac, 0x4d, 0xf2, - 0x9b, 0x1a, 0x2d, 0x01, 0x39, 0x59, 0x02, 0x26, 0x7e, 0xae, 0xf9, 0x04, 0xe0, 0x49, 0xc7, 0x83, 0xfc, 0x3b, 0x5e, - 0x33, 0x41, 0x64, 0x1b, 0xb9, 0x3f, 0x29, 0x9e, 0x23, 0x19, 0x41, 0xf1, 0x5d, 0xad, 0x32, 0x16, 0x86, 0x79, 0xa0, - 0x80, 0xbc, 0x07, 0x77, 0xea, 0x5b, 0xfb, 0x63, 0xc7, 0x9e, 0xad, 0x55, 0xa8, 0x85, 0x9a, 0xc2, 0x25, 0x87, 0xe8, - 0x0a, 0x32, 0x50, 0xc8, 0x78, 0xf2, 0x7a, 0x70, 0x3d, 0x89, 0x6e, 0xb8, 0x40, 0x67, 0x7c, 0x7d, 0xd3, 0x4d, 0x67, - 0xd1, 0x77, 0xf9, 0x7c, 0x42, 0x4a, 0xb2, 0xe3, 0x31, 0x1b, 0x55, 0x75, 0xb1, 0x99, 0x86, 0xf2, 0xa7, 0x87, 0xe0, - 0xeb, 0x05, 0xf5, 0x9a, 0xac, 0x52, 0xfd, 0x1d, 0x55, 0xca, 0x8b, 0x86, 0xd7, 0xfe, 0x77, 0xb9, 0xdc, 0xf7, 0x80, - 0xb4, 0x96, 0x97, 0x5c, 0xbe, 0x1f, 0x21, 0xc6, 0x88, 0x1f, 0x78, 0x25, 0x8f, 0x58, 0xa8, 0xa6, 0x70, 0xcd, 0x23, - 0x04, 0x79, 0xcb, 0x74, 0xf0, 0xb7, 0x9e, 0x38, 0xdd, 0x9f, 0x28, 0xed, 0xe2, 0x0b, 0x8b, 0xba, 0x27, 0x6b, 0xeb, - 0x06, 0xe4, 0x60, 0xc3, 0x74, 0x51, 0x90, 0x6d, 0x4a, 0x23, 0x68, 0xa3, 0xe5, 0xc0, 0x86, 0x93, 0xab, 0x0d, 0x67, - 0xae, 0x21, 0xb8, 0x2f, 0x2f, 0xd3, 0xd1, 0x02, 0x3e, 0xa4, 0xba, 0xbd, 0xc4, 0xcf, 0x87, 0x0d, 0x8f, 0x80, 0xcc, - 0x8e, 0xf8, 0xcc, 0x26, 0x92, 0x4e, 0xea, 0x52, 0x01, 0xbb, 0x5d, 0xbc, 0x05, 0x39, 0x62, 0xe6, 0xbe, 0x42, 0xf5, - 0x2d, 0x1a, 0x70, 0x65, 0xac, 0x7d, 0x4d, 0x32, 0x16, 0xde, 0x94, 0xd3, 0x70, 0x90, 0xc3, 0x73, 0xfa, 0xda, 0x72, - 0x9b, 0x65, 0x3f, 0x17, 0x10, 0x04, 0x51, 0x12, 0x8f, 0x0f, 0x78, 0x5f, 0xe6, 0x43, 0x8d, 0x92, 0x8f, 0x65, 0x23, - 0x95, 0x5e, 0x89, 0xfe, 0x6e, 0xcc, 0x25, 0x06, 0x7c, 0x9b, 0xb7, 0x05, 0x85, 0xcb, 0xea, 0x78, 0xbc, 0xac, 0x46, - 0xc6, 0xb3, 0x0c, 0x54, 0x2b, 0xd3, 0x3a, 0x88, 0xcd, 0x7c, 0xb1, 0xf0, 0x17, 0x3b, 0x27, 0x11, 0x51, 0x10, 0xd8, - 0x91, 0xf0, 0x20, 0x52, 0xbf, 0xcc, 0x3d, 0xdd, 0xa9, 0x3e, 0x3b, 0x2c, 0x6c, 0x22, 0xbd, 0xa0, 0x64, 0xf2, 0x49, - 0x70, 0x50, 0xfd, 0x1d, 0x84, 0x0d, 0xe1, 0xcd, 0xab, 0x5e, 0x67, 0x99, 0x9a, 0x95, 0x20, 0x61, 0xc6, 0x1c, 0xc1, - 0xe3, 0xb0, 0xd3, 0xd8, 0x96, 0xc7, 0x16, 0x1c, 0x9d, 0xb7, 0x61, 0x2b, 0xb6, 0x66, 0x77, 0xaa, 0x4e, 0x0b, 0x1e, - 0x4e, 0x87, 0xd7, 0x01, 0xae, 0xbe, 0xcd, 0x25, 0xe7, 0x2b, 0x3a, 0xc1, 0x36, 0x03, 0x1e, 0x4d, 0xc4, 0x6c, 0xf3, - 0x5d, 0xa4, 0x16, 0xcf, 0x66, 0xc8, 0x17, 0xb4, 0xfe, 0xc4, 0x6c, 0x65, 0x92, 0x57, 0x03, 0xbe, 0x98, 0x6c, 0xbe, - 0x8b, 0xe0, 0xd5, 0xef, 0xc0, 0x8a, 0x91, 0x39, 0xb3, 0x6c, 0xf3, 0x5d, 0x84, 0x63, 0xb6, 0xfa, 0x2e, 0xa2, 0x51, - 0x5b, 0xcb, 0x7d, 0xe9, 0xae, 0x01, 0x61, 0xe5, 0x8e, 0xc5, 0xf0, 0x1a, 0x88, 0x67, 0xda, 0x48, 0xba, 0x91, 0x86, - 0xde, 0x98, 0x87, 0xd3, 0x38, 0xd8, 0x50, 0x2b, 0xe4, 0x99, 0x21, 0x66, 0xf1, 0x77, 0xd1, 0x9c, 0xad, 0xb1, 0x22, - 0x5b, 0x1e, 0x0f, 0xae, 0x27, 0xdb, 0x1b, 0xbe, 0x01, 0xf2, 0xb3, 0xc9, 0xd6, 0x6c, 0x51, 0x77, 0x5c, 0xcc, 0xb6, - 0xdf, 0x45, 0xf3, 0xc9, 0x1a, 0x7a, 0xd6, 0x1e, 0x30, 0xef, 0x35, 0x88, 0x50, 0x12, 0x52, 0x53, 0x6e, 0x7a, 0x3d, - 0xb6, 0x19, 0x07, 0x2b, 0xb6, 0xb9, 0x0e, 0xee, 0xd8, 0x66, 0x0c, 0x44, 0x1c, 0xd4, 0xef, 0xde, 0x16, 0x16, 0x5f, - 0xc4, 0x36, 0xd7, 0x26, 0x6d, 0xfb, 0x5d, 0xc4, 0xdc, 0xc1, 0x69, 0xe0, 0x82, 0xb5, 0xcd, 0xbc, 0x35, 0x83, 0x4b, - 0xc8, 0xd2, 0x8b, 0xd9, 0x76, 0x78, 0xcd, 0x36, 0x23, 0x9c, 0xea, 0x89, 0xcf, 0x56, 0xfc, 0x8e, 0x25, 0x7c, 0xdd, - 0xc4, 0x37, 0x5b, 0xd0, 0x88, 0x9e, 0x64, 0xd0, 0x57, 0x50, 0x33, 0x73, 0x5e, 0x5a, 0x50, 0xb9, 0x87, 0x16, 0x1c, - 0x50, 0x90, 0xb6, 0x01, 0x82, 0x24, 0x9e, 0xdd, 0xcb, 0x70, 0x73, 0x2b, 0x85, 0x01, 0x37, 0x81, 0x19, 0x30, 0x30, - 0xfd, 0x0c, 0x7e, 0x58, 0xe9, 0x12, 0x21, 0xce, 0x7e, 0x4a, 0x49, 0x32, 0xcf, 0x4f, 0x45, 0x9a, 0xbb, 0x85, 0xeb, - 0x14, 0x66, 0x45, 0x81, 0xea, 0xa7, 0xa4, 0x34, 0xb0, 0x50, 0x89, 0x4c, 0xa5, 0xe0, 0x97, 0xcd, 0x79, 0x94, 0x9d, - 0xa2, 0x73, 0x5d, 0x5e, 0x4f, 0x9c, 0xd3, 0x49, 0xdf, 0x7f, 0xe0, 0x18, 0xb6, 0x90, 0x81, 0x0b, 0x7f, 0xea, 0x09, - 0xe3, 0xd4, 0x0a, 0xc4, 0x54, 0xf2, 0xec, 0x29, 0x7c, 0x26, 0xb4, 0x3a, 0xba, 0xf0, 0xfd, 0xa0, 0xd0, 0x26, 0xe9, - 0x16, 0x24, 0x29, 0x78, 0x8a, 0x5e, 0x72, 0xde, 0x06, 0x2a, 0xc5, 0x88, 0x16, 0x44, 0xda, 0x5a, 0x66, 0x0e, 0xd2, - 0x96, 0xe6, 0xbb, 0x26, 0x7e, 0x0e, 0x0b, 0xb8, 0x88, 0x16, 0x76, 0xa5, 0xe0, 0x51, 0x15, 0x2b, 0xf7, 0x36, 0xcf, - 0x11, 0xce, 0xe8, 0x5a, 0x26, 0x00, 0xae, 0xf7, 0xab, 0xb0, 0x56, 0x78, 0x45, 0xcd, 0x22, 0x2f, 0x6a, 0xfa, 0x64, - 0x0b, 0xdc, 0xc7, 0xa2, 0x44, 0x81, 0xb3, 0x16, 0x0c, 0xd8, 0x0a, 0x4b, 0x76, 0x52, 0xd8, 0x14, 0x2d, 0xa1, 0x77, - 0xc0, 0x4f, 0x07, 0x35, 0x93, 0x01, 0x34, 0x01, 0x34, 0x1e, 0xff, 0x02, 0x50, 0xd3, 0xdb, 0x5a, 0x6c, 0xaa, 0xa0, - 0x54, 0xca, 0x4d, 0xf8, 0x19, 0x18, 0x66, 0xf8, 0xa1, 0x90, 0xdb, 0x44, 0x89, 0x9c, 0x1f, 0x8b, 0x52, 0x2c, 0x4b, - 0x51, 0x25, 0xed, 0x86, 0x82, 0x47, 0x84, 0xdb, 0xa0, 0x31, 0x73, 0x7b, 0xa2, 0x8b, 0x56, 0x84, 0x72, 0x6c, 0x37, - 0x31, 0xd2, 0x28, 0xb3, 0xb3, 0x5d, 0x27, 0x0b, 0xed, 0xf7, 0x55, 0x0e, 0x59, 0x07, 0xac, 0x91, 0x7c, 0xbd, 0xe6, - 0xd0, 0x6d, 0xa3, 0xbc, 0x78, 0xf0, 0x7c, 0x05, 0xa7, 0x39, 0x9e, 0xd8, 0x5d, 0xaf, 0x3b, 0x45, 0x22, 0x5e, 0xe1, - 0xa4, 0xaa, 0x46, 0xb2, 0x70, 0xdc, 0xb9, 0xd3, 0x5a, 0xac, 0x95, 0x4c, 0xe3, 0x72, 0xd0, 0x00, 0xd0, 0x0c, 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, 0xf3, 0x4a, - 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, 0xce, 0x00, 0x3f, 0x0a, 0xc8, 0x47, 0x09, 0xb8, 0x19, 0x20, 0x7b, 0x64, 0x09, 0x20, 0x56, - 0x8c, 0x4e, 0x26, 0x9f, 0xfb, 0x5e, 0xa4, 0xe0, 0x9d, 0x7d, 0x56, 0xa9, 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, - 0x94, 0x64, 0x9b, 0x86, 0x48, 0x06, 0xcc, 0x88, 0x11, 0x41, 0x65, 0xb9, 0xf0, 0xbf, 0x07, 0x59, 0x14, 0x38, 0x80, - 0xab, 0x99, 0x0c, 0x5e, 0xbb, 0x30, 0x2a, 0x00, 0xce, 0x69, 0xe8, 0x94, 0x0e, 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, 0x4f, 0x5f, - 0xa7, 0xe9, 0xa4, 0xc4, 0x5d, 0xe1, 0x37, 0xe0, 0xa2, 0xd9, 0xe6, 0x43, 0x3f, 0x7d, 0x41, 0x11, 0x17, 0x35, 0xb8, - 0xf2, 0xce, 0xf5, 0x95, 0xea, 0x23, 0xa8, 0x85, 0x27, 0x46, 0xd6, 0xc2, 0x93, 0x4b, 0xd6, 0x5a, 0x10, 0xcc, 0x6c, - 0x0e, 0x5c, 0xc8, 0xaf, 0x94, 0x22, 0xde, 0x46, 0x42, 0x2d, 0x06, 0xad, 0xc7, 0xac, 0x58, 0x3e, 0x5a, 0xa8, 0xcc, - 0x08, 0xed, 0xdb, 0x5a, 0x74, 0x7e, 0x23, 0x3f, 0xe5, 0xa9, 0x7d, 0xd9, 0x1e, 0xe7, 0xd3, 0x3d, 0xba, 0xab, 0xce, - 0x32, 0x93, 0x32, 0x3e, 0x99, 0x25, 0x28, 0xdc, 0x25, 0xd8, 0x80, 0x24, 0xfb, 0xb5, 0x0e, 0x90, 0x51, 0x7b, 0xed, - 0x77, 0x9d, 0xe5, 0x5b, 0xa9, 0x66, 0x6b, 0x28, 0x2a, 0xb5, 0x92, 0x14, 0x07, 0x19, 0xae, 0xdb, 0xdc, 0x87, 0xcd, - 0x14, 0xf4, 0x8c, 0x91, 0xc8, 0x3c, 0x7f, 0x22, 0x5f, 0x82, 0x73, 0xc6, 0x59, 0x21, 0x30, 0x61, 0xac, 0xde, 0xb5, - 0x96, 0x4a, 0x43, 0x8a, 0xb1, 0x93, 0x51, 0x96, 0x55, 0x96, 0x2e, 0xb3, 0xb5, 0x84, 0x2d, 0xab, 0xc8, 0x2d, 0x6c, - 0x99, 0xc9, 0x6a, 0xbe, 0xcf, 0xb9, 0x83, 0xf2, 0xcd, 0x36, 0x19, 0x3f, 0x48, 0x64, 0xef, 0x36, 0x50, 0xc2, 0xf3, - 0xd1, 0x7f, 0x20, 0xfd, 0x36, 0xc3, 0x38, 0xe5, 0xb6, 0x92, 0x16, 0xe0, 0xf4, 0x8f, 0xc7, 0xf7, 0x39, 0x06, 0x0d, - 0x8e, 0x30, 0x8e, 0xac, 0xdf, 0xbf, 0xcb, 0xbd, 0x1a, 0x13, 0x75, 0xf4, 0x42, 0xbf, 0x9f, 0xd3, 0xc3, 0x69, 0x3e, - 0x5a, 0xa7, 0x3b, 0x64, 0x27, 0xb4, 0xb1, 0xf2, 0x83, 0x5a, 0x01, 0xb3, 0xb7, 0x3e, 0x9f, 0x0e, 0x40, 0xc7, 0x02, - 0x24, 0x9a, 0xcd, 0x44, 0x62, 0x4e, 0xba, 0x27, 0xe1, 0xe9, 0x81, 0x05, 0x0e, 0x30, 0x39, 0xff, 0x87, 0xf0, 0x66, - 0x60, 0x83, 0x46, 0x89, 0xbe, 0x46, 0x57, 0xb5, 0xb9, 0xd1, 0xf1, 0xd2, 0x53, 0x48, 0x64, 0x05, 0xcb, 0xe7, 0xbe, - 0xdc, 0xc0, 0x69, 0x0f, 0x35, 0x87, 0xca, 0x12, 0x3c, 0x3d, 0x97, 0xf9, 0xf1, 0xb8, 0xc9, 0xa0, 0xb0, 0xfd, 0x46, - 0x68, 0x6f, 0xcc, 0x52, 0x0d, 0x15, 0xe1, 0xa0, 0xf3, 0xb5, 0x98, 0xd5, 0x23, 0xfa, 0x7b, 0x7e, 0x3c, 0xae, 0x09, - 0x0c, 0x38, 0x2c, 0x65, 0x26, 0x5a, 0x28, 0x96, 0xd6, 0xd9, 0x8c, 0xea, 0xc0, 0x03, 0x13, 0x73, 0x16, 0xee, 0x01, - 0xb4, 0x49, 0xad, 0x02, 0xbd, 0x8a, 0xe8, 0x27, 0xee, 0xd7, 0xf6, 0xeb, 0xf5, 0xc8, 0x2c, 0x1d, 0xb9, 0x31, 0x16, - 0x00, 0x1c, 0x78, 0x59, 0x93, 0x3c, 0x27, 0x5f, 0x43, 0xbb, 0x27, 0x17, 0xf2, 0x27, 0x28, 0x5b, 0x78, 0xa5, 0x9a, - 0x56, 0x16, 0x6b, 0xae, 0xaa, 0x57, 0x17, 0x3c, 0x37, 0x99, 0xd6, 0x69, 0x25, 0x54, 0xac, 0x5f, 0x43, 0x5d, 0xe2, - 0xb5, 0xa6, 0x19, 0xa5, 0x36, 0xea, 0x4c, 0xd4, 0x80, 0x0d, 0xf6, 0x53, 0xb5, 0xd1, 0xc9, 0xb9, 0x7c, 0x79, 0x6d, - 0x1c, 0x3e, 0xed, 0xea, 0xcd, 0x4c, 0xe5, 0xc0, 0x5f, 0xab, 0x1a, 0x5a, 0x3d, 0x06, 0x3a, 0x20, 0xa7, 0x3f, 0x86, - 0xc5, 0xc4, 0xee, 0xd0, 0xaa, 0xdd, 0x5d, 0x56, 0x17, 0xe9, 0x9d, 0xa6, 0x64, 0x56, 0x6f, 0xf9, 0xcc, 0xea, 0xd1, - 0x01, 0x2f, 0x1e, 0xeb, 0xbd, 0xc2, 0x4c, 0x22, 0xb8, 0x18, 0xaa, 0x49, 0x64, 0x77, 0xa0, 0x35, 0x8f, 0x72, 0x26, - 0xc0, 0x0f, 0x4a, 0xad, 0xe9, 0x83, 0xdd, 0x15, 0xea, 0x94, 0xc2, 0xe3, 0xd6, 0x92, 0x1f, 0x98, 0x3b, 0xed, 0x5a, - 0xe7, 0xe3, 0xe5, 0xb5, 0xef, 0x37, 0xf2, 0x84, 0x36, 0x3b, 0x93, 0xd3, 0x3f, 0x55, 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, 0xc7, 0xa3, 0xb8, 0xa9, 0x7c, 0x76, 0xd9, 0x35, 0xb2, 0x72, 0x00, 0x73, 0x88, - 0x82, 0x71, 0x6b, 0x3e, 0xb6, 0x41, 0xba, 0xc4, 0xcd, 0xf8, 0xf4, 0x0d, 0xc5, 0x32, 0xd9, 0x44, 0x5c, 0x5c, 0x55, - 0xdf, 0x3d, 0x03, 0xd2, 0xb2, 0x7e, 0x3f, 0x7a, 0x7e, 0x3d, 0x7d, 0x36, 0x8c, 0x02, 0x70, 0xec, 0xb2, 0x97, 0x97, - 0x31, 0x5f, 0x5d, 0x33, 0xcb, 0x14, 0x16, 0xf9, 0x66, 0x40, 0x75, 0xc9, 0x6a, 0xe9, 0x7a, 0x05, 0x58, 0xba, 0xfc, - 0xe6, 0x21, 0x4c, 0x0d, 0x68, 0x64, 0xcd, 0xdd, 0x69, 0xae, 0x05, 0x4a, 0x3d, 0xef, 0x67, 0x86, 0x7c, 0x5d, 0x06, - 0x5d, 0x41, 0xba, 0xe7, 0x11, 0xe9, 0xe5, 0x41, 0x3a, 0xdd, 0x1f, 0x4a, 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, 0xa3, 0xe6, 0x82, 0x13, 0x62, 0x26, 0xe6, 0x00, 0x2a, 0x41, 0x1b, 0xdf, 0xfa, 0x64, - 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, 0xaf, 0x0d, 0xa6, 0xaf, 0x6f, - 0xb7, 0x45, 0x7e, 0x6a, 0x62, 0xc2, 0x7a, 0xac, 0xe8, 0x9b, 0x77, 0xe1, 0x5a, 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, 0x7a, 0xc5, 0xc8, 0x7c, 0xdc, 0x47, 0xa5, 0x92, 0xfe, 0x79, 0x3c, - 0xce, 0xf2, 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, 0x7b, 0x52, 0x72, 0x78, 0xce, 0x31, 0x27, 0x94, 0x56, 0x84, 0xe5, - 0x7c, 0x91, 0xa1, 0x5c, 0x77, 0x4e, 0xc1, 0x24, 0x87, 0x04, 0xc3, 0x5f, 0x35, 0x6f, 0x62, 0x05, 0xc2, 0xae, 0x91, - 0x33, 0x47, 0x4f, 0xaa, 0x24, 0x2c, 0x05, 0x1c, 0x95, 0x99, 0x67, 0xd8, 0x1b, 0x9e, 0x18, 0x46, 0x0e, 0x56, 0xf9, - 0xa3, 0x3a, 0x11, 0xb9, 0x47, 0x17, 0x18, 0x95, 0x85, 0x57, 0x0d, 0x5d, 0x69, 0x50, 0x49, 0x76, 0xfa, 0x15, 0xd7, - 0x80, 0xda, 0x1a, 0x23, 0x96, 0x83, 0x80, 0x51, 0xf0, 0xda, 0xfe, 0x10, 0xb2, 0x28, 0x5b, 0xbf, 0xc1, 0x31, 0x9f, - 0x95, 0xdc, 0xf5, 0x0e, 0x67, 0xa1, 0x25, 0xe4, 0xc9, 0x1d, 0x83, 0x34, 0x8d, 0xa5, 0x11, 0x70, 0x22, 0x92, 0x6d, - 0x2c, 0x85, 0x23, 0x80, 0x80, 0x40, 0x37, 0x65, 0x86, 0x31, 0x1d, 0x8c, 0x3c, 0x4f, 0x7a, 0xc6, 0x7b, 0x15, 0x9e, - 0x42, 0x9a, 0x6c, 0x5f, 0xcf, 0x3f, 0xe4, 0x5a, 0x90, 0x95, 0x5b, 0xce, 0xe9, 0xb0, 0xf8, 0xc6, 0xd9, 0x57, 0x39, - 0x79, 0x8a, 0x59, 0x46, 0x7a, 0xa7, 0x98, 0x17, 0xf0, 0xa7, 0xb2, 0xd4, 0x93, 0xf4, 0x96, 0xf9, 0x64, 0x15, 0x49, - 0x97, 0xde, 0xb6, 0xdf, 0x8f, 0x47, 0xea, 0x50, 0xf3, 0x0f, 0xf1, 0x48, 0x9e, 0x61, 0x5b, 0x96, 0xb0, 0xd0, 0x2a, - 0x18, 0x03, 0x48, 0x62, 0x23, 0xa2, 0xc1, 0x68, 0x6f, 0x8f, 0xc7, 0xcb, 0xad, 0x39, 0x4b, 0x0e, 0xe0, 0xfa, 0xca, - 0x13, 0xf3, 0x0e, 0x7c, 0x99, 0xc7, 0x04, 0x11, 0x9b, 0x79, 0x5b, 0x56, 0x83, 0x07, 0x3b, 0xb8, 0x3e, 0x62, 0x8b, - 0x62, 0xad, 0x63, 0xc9, 0xad, 0x83, 0xd3, 0x3a, 0x36, 0xcd, 0x48, 0x29, 0xb2, 0xcf, 0xb1, 0x7f, 0x70, 0x83, 0xab, - 0x6b, 0x63, 0x50, 0x6b, 0xdc, 0x61, 0xee, 0x9c, 0x0a, 0xa8, 0xc7, 0x74, 0x05, 0xd5, 0x8b, 0x8a, 0x7c, 0xf9, 0xad, - 0x9d, 0x03, 0x82, 0x46, 0x20, 0x70, 0xd1, 0x40, 0xab, 0x76, 0x29, 0xe7, 0x5d, 0x40, 0x88, 0x6f, 0x52, 0xd0, 0xa7, - 0x33, 0xd8, 0xc4, 0xe6, 0x13, 0x88, 0x45, 0xd3, 0x7d, 0xae, 0x35, 0xf3, 0xc5, 0x88, 0x76, 0x66, 0xdd, 0x2d, 0x72, - 0xab, 0x85, 0x48, 0x46, 0xcf, 0x36, 0x13, 0x2e, 0x3a, 0x94, 0x33, 0x12, 0x30, 0x41, 0x6b, 0x2b, 0x25, 0x9f, 0xeb, - 0x41, 0x27, 0x68, 0x0f, 0x24, 0xad, 0xfb, 0x37, 0x8b, 0xce, 0x28, 0x39, 0xb9, 0xde, 0xe4, 0x0c, 0x52, 0xb0, 0x60, - 0x07, 0x99, 0x13, 0x6e, 0x80, 0x4f, 0x6c, 0x96, 0x9c, 0xa6, 0x41, 0x1e, 0x0b, 0xe3, 0x91, 0xd7, 0xe6, 0x97, 0x05, - 0x74, 0x28, 0x59, 0x34, 0x42, 0x3c, 0xc0, 0xce, 0x21, 0xb9, 0x2a, 0x50, 0x37, 0x0d, 0x74, 0xe5, 0xca, 0x99, 0x62, - 0x0a, 0x5c, 0x08, 0x05, 0x51, 0x3b, 0x3a, 0x89, 0xca, 0x79, 0x9f, 0x54, 0x97, 0xd5, 0xb4, 0x90, 0xa6, 0x81, 0x6a, - 0x9a, 0x3b, 0xe6, 0x81, 0xbd, 0x6d, 0x5c, 0x13, 0x18, 0xe8, 0xd4, 0xbe, 0x16, 0x55, 0xfc, 0x83, 0x74, 0x2f, 0xce, - 0xe1, 0x2f, 0x6b, 0xfa, 0x20, 0xc2, 0x46, 0x0e, 0x1a, 0x4b, 0x89, 0xb1, 0x51, 0xe1, 0xdf, 0x12, 0x65, 0x43, 0x86, - 0x80, 0x10, 0xd2, 0x46, 0x45, 0x3f, 0xac, 0x2f, 0xef, 0x32, 0xed, 0xff, 0x49, 0xe2, 0xb7, 0xc1, 0x5e, 0x4e, 0xfd, - 0xa9, 0x47, 0x3c, 0x5e, 0x1b, 0xf4, 0x98, 0x92, 0x6e, 0x83, 0x3c, 0x55, 0x9e, 0x82, 0x64, 0xc2, 0x58, 0x42, 0xb0, - 0x28, 0x17, 0xbc, 0xe2, 0x39, 0x97, 0x70, 0x1f, 0xb5, 0xac, 0x88, 0x50, 0x95, 0xa8, 0xe8, 0xf3, 0x39, 0xf0, 0x4c, - 0x40, 0xa0, 0x63, 0x8c, 0x34, 0xaa, 0xe0, 0x4b, 0x60, 0xac, 0x03, 0x65, 0xa7, 0x19, 0x09, 0x2e, 0xbb, 0xb7, 0x48, - 0x94, 0xfa, 0x8a, 0x94, 0xa4, 0x6f, 0x45, 0x8d, 0x57, 0x62, 0x15, 0x91, 0x40, 0x86, 0x1a, 0x22, 0x56, 0xd5, 0x53, - 0xf7, 0xa6, 0x98, 0x0c, 0x06, 0xb9, 0x2f, 0xa7, 0x27, 0xde, 0xd0, 0x50, 0x79, 0xd7, 0x15, 0xed, 0xf4, 0x44, 0x2b, - 0xe5, 0x2d, 0xa4, 0x25, 0x68, 0x1a, 0x46, 0x9a, 0x43, 0xa9, 0x6b, 0xe9, 0x6e, 0x0c, 0xe2, 0x4b, 0x26, 0x7a, 0xb6, - 0x53, 0x3b, 0x4a, 0x5b, 0xd2, 0x1e, 0x42, 0x7a, 0xee, 0x92, 0x8f, 0x21, 0x42, 0x4c, 0x55, 0xa5, 0xbc, 0x09, 0xd1, - 0xc9, 0xfd, 0x80, 0x21, 0x11, 0xe8, 0x73, 0x8e, 0x61, 0x5d, 0x34, 0xd4, 0x18, 0x6c, 0x6d, 0xb6, 0x50, 0xc2, 0x7c, - 0xc9, 0x78, 0x2a, 0x19, 0x34, 0x00, 0x32, 0xe0, 0xb3, 0x97, 0x81, 0xe5, 0xaf, 0x20, 0x7e, 0xb4, 0xf1, 0xf1, 0xf8, - 0x67, 0x4d, 0x21, 0xb6, 0x7f, 0xc2, 0x66, 0x08, 0x8f, 0xea, 0x01, 0xcf, 0x7c, 0x13, 0x27, 0x68, 0x05, 0x24, 0x65, - 0x76, 0x34, 0x91, 0xbd, 0xea, 0x21, 0x9c, 0xca, 0x0a, 0xd4, 0x51, 0xd6, 0x59, 0x09, 0x3f, 0xc2, 0x54, 0xb7, 0x12, - 0x6b, 0x81, 0x36, 0x57, 0x2b, 0xd6, 0x02, 0x38, 0xf0, 0x2b, 0x08, 0x9e, 0xa8, 0xe6, 0xe0, 0x62, 0x50, 0x80, 0xcf, - 0x01, 0xf0, 0x22, 0x77, 0xe1, 0xc1, 0x3c, 0xb2, 0xac, 0x46, 0x18, 0x8e, 0x2a, 0x62, 0xfd, 0x9a, 0xed, 0xc8, 0x07, - 0x6e, 0xc7, 0xf8, 0x5c, 0x7b, 0x2c, 0x59, 0x0e, 0x46, 0x99, 0x7b, 0xb5, 0x44, 0xcf, 0x9b, 0x34, 0x6e, 0x46, 0x4f, - 0x0e, 0xb5, 0xfc, 0x5f, 0xd0, 0xcb, 0xa0, 0xbf, 0x85, 0x5b, 0x5e, 0xf3, 0xbb, 0x05, 0x91, 0x66, 0x7a, 0x05, 0x91, - 0x32, 0x6a, 0x44, 0xc6, 0x10, 0x36, 0xa9, 0x6e, 0x65, 0x93, 0xea, 0x42, 0xc0, 0xd3, 0x09, 0xa9, 0xae, 0x85, 0xb4, - 0x51, 0x4d, 0xeb, 0x40, 0xc6, 0x22, 0xbd, 0xfb, 0xf1, 0x2f, 0x2f, 0x3e, 0xbd, 0xf9, 0xe5, 0xc7, 0xc5, 0x9b, 0x77, - 0xaf, 0xdf, 0xbc, 0x7b, 0xf3, 0xe9, 0x37, 0x82, 0xf0, 0x98, 0x0a, 0x95, 0xe1, 0xc3, 0xfb, 0xdb, 0x37, 0x4e, 0x06, - 0xdb, 0x9b, 0x21, 0x6b, 0xdf, 0xc8, 0xc1, 0x10, 0x88, 0x6c, 0x10, 0x32, 0xc8, 0x4e, 0x6d, 0xfb, 0x33, 0x31, 0xc7, - 0xd8, 0x3b, 0x81, 0xc9, 0x16, 0x24, 0x87, 0x65, 0x5e, 0x32, 0x22, 0x57, 0x8e, 0xd6, 0x0f, 0x68, 0xc1, 0x5b, 0x70, - 0x91, 0x49, 0xf3, 0xd5, 0x2f, 0x04, 0xb1, 0x4f, 0x2b, 0xa9, 0xf2, 0xd5, 0xb6, 0xe6, 0xf9, 0xf6, 0x7e, 0x9f, 0xd3, - 0x8a, 0x99, 0x4b, 0x23, 0x6a, 0x01, 0x0e, 0xc0, 0x97, 0xf0, 0xc7, 0x8d, 0xb6, 0xa4, 0xc9, 0x2c, 0xfa, 0x2c, 0x84, - 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, 0xf7, 0x8a, 0x1c, 0x19, 0x3f, - 0x08, 0x26, 0xbe, 0x0a, 0xdc, 0x7f, 0x89, 0x77, 0x38, 0x53, 0x1c, 0xc9, 0x09, 0x7f, 0xc8, 0x30, 0xb0, 0xbf, 0x02, - 0x9f, 0x57, 0x87, 0x79, 0x79, 0xab, 0x4f, 0xb9, 0x25, 0x1f, 0x4f, 0x96, 0x37, 0x60, 0xb0, 0x5f, 0xaa, 0xe6, 0x6e, - 0x78, 0x3d, 0x5b, 0xce, 0xd9, 0x61, 0x16, 0xcd, 0x83, 0x15, 0x9b, 0x65, 0xf3, 0x60, 0xdd, 0xf0, 0x0d, 0xbb, 0xe3, - 0x1b, 0xab, 0x6a, 0x1b, 0xbb, 0x6a, 0x93, 0x2d, 0xbf, 0x03, 0x09, 0xe1, 0x36, 0xf3, 0x72, 0x96, 0xb0, 0x95, 0xcf, - 0xb6, 0x20, 0xd1, 0xae, 0xd9, 0x16, 0x2e, 0x62, 0x1b, 0xfe, 0x63, 0xee, 0x6d, 0x59, 0xc9, 0x2e, 0xc7, 0xac, 0xc2, - 0xf9, 0xe7, 0xc3, 0x03, 0xda, 0x0b, 0xf5, 0xb3, 0x6b, 0xf5, 0x6c, 0xa2, 0xec, 0x66, 0xdb, 0xd1, 0xe2, 0x3e, 0xad, - 0xb6, 0x61, 0x86, 0x9e, 0xe5, 0xf0, 0xd1, 0x56, 0x0a, 0x7e, 0x7a, 0x81, 0x5f, 0xb2, 0xa3, 0xb6, 0xd2, 0xb6, 0x5d, - 0x95, 0xd8, 0x0a, 0x5a, 0x14, 0x59, 0xad, 0xf0, 0xc0, 0x8a, 0x3f, 0x87, 0x05, 0x8c, 0x3d, 0xc7, 0x39, 0xaf, 0xfd, - 0x11, 0x32, 0xde, 0x3b, 0x00, 0x68, 0x99, 0xe3, 0x00, 0x8f, 0x58, 0x31, 0x8a, 0x06, 0xef, 0xf2, 0x5a, 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, 0xb2, 0xb5, 0xaa, 0x3b, 0xbf, 0xa7, 0x4a, 0x97, 0x1c, 0xd9, 0xf2, 0xd3, 0x65, 0xf8, - 0xa0, 0xfe, 0x94, 0x5c, 0x1f, 0x0a, 0x1c, 0xe1, 0xb1, 0x0a, 0x38, 0x5f, 0xcf, 0x45, 0xbb, 0x13, 0x61, 0x57, 0x2e, - 0x01, 0x21, 0xbe, 0xa4, 0x69, 0x8e, 0xc7, 0x11, 0x4d, 0x44, 0xd8, 0xc4, 0xe8, 0x2f, 0xec, 0x3e, 0x94, 0x58, 0x2e, - 0x2b, 0x0d, 0x4a, 0x2e, 0x19, 0xbc, 0x27, 0xed, 0x35, 0x68, 0x96, 0x57, 0xae, 0x26, 0x13, 0x39, 0x28, 0x1f, 0x8f, - 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, 0x4e, 0x1f, 0xce, 0xc4, 0xdc, 0x7a, 0x6e, 0x95, 0x75, 0x92, 0xad, 0x51, - 0x4e, 0xc0, 0xbf, 0xa5, 0x3a, 0x4e, 0x12, 0xe1, 0xd4, 0x7b, 0xc4, 0x45, 0xdd, 0xcb, 0x21, 0xea, 0x86, 0xbd, 0xc9, - 0x75, 0xb0, 0xe5, 0x34, 0x0d, 0x4e, 0xc4, 0xaf, 0xd4, 0x67, 0xef, 0x33, 0x8b, 0x47, 0x1d, 0xd9, 0x88, 0x92, 0x34, - 0x8e, 0x45, 0x0e, 0xdb, 0xfb, 0x42, 0xee, 0xff, 0xfd, 0x3e, 0x84, 0x93, 0x56, 0x41, 0x52, 0x7a, 0x02, 0x11, 0xe1, - 0xe8, 0xf0, 0x23, 0xc2, 0x13, 0xa9, 0x2a, 0x7c, 0x52, 0x9f, 0xb9, 0x31, 0xbb, 0x17, 0xe6, 0xa8, 0xde, 0x01, 0x0c, - 0x63, 0xbd, 0xb3, 0x08, 0x49, 0xb4, 0xd2, 0x8c, 0xb6, 0x1e, 0x10, 0x23, 0xde, 0x6f, 0x2c, 0x32, 0x18, 0x6b, 0x4b, - 0x22, 0x01, 0x7c, 0x45, 0x42, 0x86, 0xb6, 0x8d, 0xc0, 0x8c, 0xe1, 0xed, 0xac, 0xb8, 0x74, 0x1d, 0xb6, 0x39, 0x87, - 0x2f, 0x64, 0xa1, 0x59, 0x47, 0x94, 0x26, 0x08, 0xf9, 0x07, 0x9c, 0x2c, 0x14, 0x46, 0xf3, 0xea, 0x24, 0x9d, 0x24, - 0xd6, 0xf7, 0x5d, 0xa5, 0x82, 0xcd, 0xe6, 0x16, 0xf5, 0x65, 0x27, 0xc9, 0x2f, 0xc1, 0x49, 0xc7, 0x49, 0x16, 0x39, - 0x88, 0x5a, 0x54, 0xce, 0x6d, 0x12, 0x96, 0x76, 0x75, 0xaa, 0xed, 0x66, 0x53, 0x94, 0x75, 0xf5, 0x4a, 0x44, 0x8a, - 0xde, 0x47, 0x3d, 0x7a, 0x22, 0x21, 0x15, 0x5a, 0x95, 0xda, 0xe7, 0x11, 0xb8, 0x6d, 0x6a, 0xc5, 0xb6, 0x5c, 0xc2, - 0x12, 0x35, 0xfe, 0x13, 0xf4, 0x51, 0x2e, 0x1e, 0x64, 0x80, 0x46, 0xc7, 0x53, 0xf3, 0xd6, 0x23, 0xaf, 0x9c, 0xe4, - 0x97, 0x56, 0x9b, 0xf4, 0x0b, 0x20, 0x33, 0xda, 0x3f, 0x5a, 0x4a, 0x20, 0x33, 0x30, 0x93, 0x96, 0x86, 0x44, 0x8e, - 0x62, 0x96, 0xe6, 0x7f, 0xe0, 0x8a, 0xad, 0x10, 0x69, 0x58, 0xcd, 0x3d, 0xfe, 0x22, 0xf7, 0x6a, 0xb9, 0x96, 0x99, - 0xe6, 0x66, 0x89, 0x63, 0xc5, 0xe2, 0xa2, 0x5e, 0x57, 0x22, 0x0b, 0x84, 0x38, 0xc2, 0x34, 0xd6, 0x53, 0x6f, 0x94, - 0x56, 0x1f, 0x90, 0x50, 0xe6, 0x47, 0xec, 0xed, 0xd8, 0xeb, 0x41, 0x16, 0xe2, 0xd8, 0x72, 0xb0, 0xd9, 0x7a, 0x9f, - 0xca, 0x54, 0xc4, 0x17, 0x75, 0x71, 0xb1, 0xad, 0xc4, 0x45, 0x9d, 0x88, 0x8b, 0xef, 0x21, 0xe7, 0xf7, 0x17, 0x54, - 0xf4, 0xc5, 0x43, 0x5a, 0x27, 0xc5, 0xb6, 0xa6, 0x27, 0xaf, 0xb1, 0x8c, 0xef, 0x2f, 0x88, 0xab, 0xe6, 0x82, 0x46, - 0x32, 0x1e, 0x5d, 0x7c, 0xc8, 0x80, 0xe4, 0xf5, 0x22, 0x5d, 0xc3, 0xe0, 0x5d, 0x84, 0x79, 0x7c, 0x51, 0x8a, 0x15, - 0x58, 0x9c, 0xca, 0xce, 0xf7, 0x20, 0xc3, 0x3a, 0xfc, 0x43, 0x5c, 0x00, 0xb4, 0xeb, 0x45, 0x5a, 0x5f, 0xa4, 0xd5, - 0x45, 0x5e, 0xd4, 0x17, 0x4a, 0x0a, 0x87, 0x30, 0x7e, 0x78, 0x4f, 0x5f, 0xd9, 0xe5, 0x6d, 0x16, 0x77, 0x59, 0xe4, - 0x4f, 0xd1, 0xab, 0x88, 0x98, 0x34, 0x72, 0xe1, 0xb5, 0xfb, 0xdb, 0xe6, 0xfe, 0xe1, 0x75, 0x63, 0xf7, 0xb3, 0x3b, - 0x46, 0x74, 0x41, 0x3d, 0x5d, 0x49, 0x4a, 0x05, 0x05, 0x04, 0x4e, 0x34, 0x6b, 0x3c, 0xb8, 0xe3, 0x80, 0x57, 0x03, - 0x5b, 0xb2, 0x8d, 0xcf, 0x9f, 0xc7, 0x32, 0x4c, 0x7b, 0x1b, 0xe0, 0x5f, 0x65, 0x6f, 0xba, 0x09, 0x96, 0x78, 0xdf, - 0x42, 0xb6, 0xa1, 0x37, 0xaf, 0xf8, 0x0b, 0xaf, 0x52, 0x7f, 0xb3, 0x7f, 0x00, 0x10, 0x06, 0xc4, 0xac, 0xfa, 0x68, - 0xe2, 0xde, 0x5b, 0x59, 0xf6, 0x4e, 0x96, 0x7d, 0x0f, 0xfd, 0x9a, 0xc4, 0xa8, 0xb4, 0xb2, 0x94, 0x4e, 0x96, 0x12, - 0xb2, 0x80, 0x4f, 0x8c, 0xa6, 0x36, 0x02, 0x08, 0xdb, 0x51, 0x2a, 0x5f, 0x00, 0xc2, 0x49, 0x02, 0x12, 0x62, 0x09, - 0x17, 0xa3, 0x7b, 0x2b, 0x19, 0x30, 0x1c, 0x42, 0x30, 0x07, 0xed, 0xb0, 0x37, 0x74, 0x13, 0xf1, 0xd7, 0xeb, 0xa2, - 0x7c, 0x13, 0x93, 0x4f, 0xc1, 0xfe, 0xec, 0xe3, 0x12, 0x1e, 0x97, 0x67, 0x1f, 0x87, 0xe8, 0x91, 0x70, 0xf6, 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, 0xfe, 0xab, 0xfb, 0x0a, 0x6e, 0xe3, - 0xfd, 0xfe, 0x32, 0xf7, 0xcc, 0x4f, 0x5c, 0x00, 0xf6, 0xa6, 0x42, 0xeb, 0x04, 0x4a, 0x0d, 0xeb, 0xf0, 0x65, 0x22, - 0xa2, 0x3f, 0xda, 0xe5, 0x3a, 0x73, 0x1d, 0x30, 0xa2, 0x88, 0xdf, 0xc6, 0xa3, 0x3f, 0x40, 0x71, 0x6d, 0xec, 0x01, - 0x61, 0x1d, 0x12, 0xfa, 0x8c, 0x00, 0xa4, 0x1e, 0x73, 0x94, 0x80, 0x66, 0x45, 0x73, 0xc7, 0xc0, 0xc1, 0x2f, 0xaf, - 0x94, 0xfe, 0x61, 0x99, 0x7b, 0x64, 0x4e, 0x69, 0x9b, 0x69, 0xac, 0xd6, 0xe4, 0x02, 0xe1, 0x15, 0x95, 0xac, 0xc2, - 0x67, 0xf3, 0x46, 0xf4, 0xfb, 0xf2, 0x08, 0x4f, 0xab, 0x1f, 0x77, 0x18, 0xdf, 0x0a, 0x88, 0x46, 0x02, 0xa0, 0x9f, - 0x00, 0xe6, 0x45, 0x36, 0xb3, 0xfb, 0x38, 0xa0, 0x4a, 0x89, 0xa6, 0x71, 0x36, 0xcf, 0x6f, 0xe9, 0x4d, 0xd9, 0x41, - 0xe7, 0x4e, 0x15, 0xb8, 0xe0, 0xaa, 0x64, 0xbc, 0xb2, 0x9e, 0xc9, 0xe7, 0x37, 0x77, 0xdb, 0x34, 0x8b, 0xdf, 0x97, - 0xff, 0xc0, 0xb1, 0xd5, 0x75, 0x78, 0x64, 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, 0xca, 0x8b, 0x2e, - 0x06, 0x6b, 0x5f, 0x8e, 0x59, 0x0e, 0x5d, 0xaa, 0x1e, 0xab, 0x87, 0xc6, 0x66, 0x0e, 0x3d, 0x6b, 0x55, 0x9e, 0x79, - 0xf9, 0xf1, 0x88, 0xf8, 0x30, 0xfa, 0x4b, 0x7e, 0xbf, 0xff, 0x8a, 0xe6, 0x1f, 0x13, 0x6a, 0xfc, 0x6c, 0x33, 0x40, - 0xd7, 0xbe, 0x2b, 0x0f, 0x44, 0x3d, 0xd7, 0x2a, 0x41, 0x88, 0x37, 0x88, 0x89, 0x66, 0xc4, 0x1c, 0x9c, 0x76, 0xa8, - 0xf9, 0x27, 0xa9, 0x01, 0x21, 0x4a, 0xbc, 0x8e, 0x29, 0x0b, 0x72, 0xda, 0xc4, 0x91, 0x7e, 0x14, 0x4e, 0xe4, 0x47, - 0x51, 0x15, 0xd9, 0x3d, 0x5c, 0x30, 0x98, 0x7a, 0x4f, 0xfb, 0x25, 0xfa, 0x2d, 0xe1, 0xc8, 0x39, 0x5a, 0x15, 0x82, - 0xc8, 0x19, 0x61, 0xad, 0x21, 0x4c, 0x10, 0x1b, 0xc4, 0xcb, 0xbe, 0x4b, 0x32, 0x1c, 0x29, 0xb8, 0xac, 0x63, 0xc7, - 0x98, 0xab, 0xa3, 0xea, 0x35, 0x80, 0xf1, 0xaa, 0x10, 0x34, 0x1b, 0x45, 0x76, 0x09, 0x51, 0x45, 0x8e, 0x27, 0xa0, - 0x76, 0x50, 0x1a, 0x9b, 0xe9, 0xe5, 0x38, 0x80, 0x09, 0x8e, 0x3a, 0x27, 0x96, 0xf1, 0x1a, 0x80, 0xb5, 0x2b, 0xd5, - 0xcf, 0xb3, 0x1a, 0x3c, 0x69, 0x88, 0xcf, 0xc7, 0x68, 0x7b, 0x65, 0x73, 0x50, 0x6d, 0xa7, 0xb3, 0xf2, 0x9c, 0xe9, - 0x72, 0x60, 0xdc, 0xb7, 0x3c, 0xa7, 0x38, 0xc3, 0x8f, 0x5e, 0x3e, 0xab, 0xe7, 0xfe, 0x74, 0x4b, 0xed, 0xc7, 0xdc, - 0xa8, 0x87, 0x81, 0xd6, 0x82, 0x37, 0x05, 0xb1, 0xfe, 0x7e, 0xe8, 0xc8, 0xf6, 0x5e, 0x8b, 0x8c, 0x26, 0x9f, 0xfd, - 0xfc, 0x43, 0x99, 0xae, 0x53, 0xb8, 0x2f, 0x39, 0x59, 0x34, 0xf3, 0x10, 0xd8, 0x1b, 0x62, 0xb8, 0x3e, 0x2a, 0x3c, - 0xa2, 0xac, 0xdf, 0x87, 0xdf, 0x37, 0x19, 0x98, 0x62, 0xe0, 0xba, 0x42, 0x30, 0x1e, 0x02, 0x41, 0x3c, 0x4c, 0xa3, - 0x93, 0x41, 0x0d, 0xda, 0xf0, 0x2d, 0x40, 0x66, 0x80, 0x47, 0xe6, 0xd2, 0x23, 0xe0, 0x2e, 0x70, 0xed, 0xc9, 0x78, - 0xec, 0x4f, 0x4c, 0x43, 0xa3, 0xa6, 0x34, 0xd3, 0x73, 0xeb, 0x37, 0x1d, 0xd5, 0x72, 0xed, 0xfc, 0xa7, 0x97, 0xfc, - 0x06, 0xbd, 0xa0, 0xe5, 0xe5, 0x3e, 0x52, 0x97, 0xfb, 0x8c, 0xe2, 0x32, 0x91, 0x1c, 0x16, 0xc4, 0xb2, 0x84, 0x03, - 0x8f, 0x51, 0xc9, 0x62, 0x4b, 0x8f, 0x95, 0xd3, 0xf2, 0x45, 0xb9, 0x41, 0x3a, 0x74, 0x42, 0xb0, 0x44, 0x0e, 0xc1, - 0x12, 0x18, 0x17, 0xb1, 0xe1, 0xdb, 0x41, 0xc5, 0xe2, 0xd9, 0x76, 0xce, 0x91, 0xb0, 0x2e, 0x39, 0x1e, 0x0b, 0x09, - 0x36, 0x93, 0xcd, 0x36, 0x73, 0xb6, 0xf1, 0x19, 0x28, 0x01, 0x4a, 0x99, 0x26, 0x28, 0x4d, 0x2b, 0xb6, 0xe2, 0xa6, - 0x35, 0x58, 0xad, 0xa6, 0xec, 0x54, 0x53, 0xf6, 0x4e, 0x53, 0x4e, 0x2a, 0x28, 0x39, 0xa1, 0x14, 0x65, 0x18, 0xc0, - 0x88, 0x4d, 0xa2, 0x9b, 0x0c, 0x7d, 0xbc, 0x13, 0x1e, 0x41, 0x15, 0x11, 0xf9, 0x84, 0x21, 0x04, 0x26, 0xa2, 0xb8, - 0x50, 0x85, 0x62, 0x80, 0x8c, 0x48, 0x20, 0x98, 0xa8, 0xd4, 0x29, 0x30, 0x1f, 0x4d, 0x15, 0xc3, 0xa6, 0x3d, 0x51, - 0xbe, 0xa5, 0x8e, 0x07, 0x94, 0x6d, 0xfe, 0x26, 0xf6, 0x41, 0x88, 0xdc, 0x8d, 0x7b, 0xf5, 0x33, 0xe2, 0xbd, 0xfd, - 0x09, 0xc6, 0x4f, 0x76, 0xda, 0x22, 0x5c, 0x11, 0x6c, 0xa9, 0xe6, 0x10, 0x8c, 0xca, 0x24, 0x41, 0x2d, 0x4b, 0xe2, - 0x6f, 0x79, 0x32, 0xa8, 0xd8, 0x12, 0x3c, 0x68, 0xe7, 0x2c, 0x03, 0xfc, 0x15, 0xab, 0x45, 0xbf, 0xd5, 0xde, 0x12, - 0xe4, 0xa7, 0xad, 0xdd, 0x28, 0x4c, 0x8c, 0x20, 0x51, 0xb7, 0x2b, 0x03, 0xf9, 0xe1, 0x03, 0x4e, 0xc7, 0x53, 0x4f, - 0x19, 0x73, 0x2b, 0xd3, 0xcb, 0x74, 0xae, 0xe4, 0x1b, 0xb9, 0x97, 0x3e, 0xf6, 0x12, 0xec, 0x1c, 0xf0, 0x06, 0xd2, - 0x06, 0xde, 0xc2, 0x76, 0xe1, 0xb5, 0x41, 0xc2, 0x8c, 0x00, 0x5b, 0x9c, 0x1e, 0x23, 0x25, 0x30, 0x84, 0xe3, 0x2c, - 0x05, 0x60, 0x1a, 0x7d, 0x99, 0xcd, 0xed, 0xcb, 0xac, 0xd6, 0x6c, 0xa9, 0x9c, 0xee, 0x9d, 0x5b, 0xb7, 0xf3, 0x89, - 0x04, 0x00, 0x93, 0x3a, 0x07, 0xe2, 0xcc, 0x04, 0xbb, 0x34, 0x89, 0x2c, 0x1f, 0xc3, 0x7c, 0x25, 0x5e, 0x97, 0xc5, - 0x5a, 0x75, 0x45, 0xdb, 0x67, 0xa6, 0x9a, 0x91, 0x4e, 0x42, 0x05, 0x14, 0x14, 0x72, 0xad, 0x4f, 0xdf, 0x85, 0xef, - 0x82, 0x42, 0x03, 0xb3, 0xe5, 0xb8, 0xa7, 0xc9, 0x1a, 0xa9, 0x37, 0xf2, 0x7e, 0x9f, 0x5c, 0x03, 0xa9, 0xce, 0x1c, - 0x5a, 0xf6, 0x04, 0x9d, 0x64, 0x4f, 0x6e, 0xca, 0x52, 0xa8, 0x03, 0xa9, 0x07, 0x0c, 0x21, 0xda, 0xa6, 0x8f, 0x3f, - 0x19, 0x12, 0x5d, 0x80, 0x2d, 0x44, 0x1b, 0xf8, 0xf1, 0x27, 0xd8, 0x67, 0x41, 0x78, 0x4c, 0xf3, 0xb7, 0x90, 0x74, - 0x6a, 0xe0, 0xb4, 0xfa, 0x14, 0x7c, 0x90, 0xe4, 0x60, 0xa2, 0x0e, 0x5e, 0xee, 0x2f, 0xfd, 0x3e, 0x6c, 0xd9, 0x95, - 0x94, 0xea, 0x00, 0x6d, 0x4a, 0xb9, 0xab, 0x2b, 0x3f, 0x88, 0xb6, 0xe0, 0xc8, 0x22, 0xfe, 0x3e, 0x43, 0x44, 0x30, - 0x33, 0x88, 0xb0, 0x6b, 0xa1, 0xee, 0xf6, 0x9c, 0x5a, 0x16, 0xf5, 0xb6, 0xe7, 0x94, 0xba, 0x0d, 0xc3, 0x77, 0x13, - 0xcc, 0x14, 0x37, 0xfc, 0x8f, 0xcc, 0x0b, 0xf5, 0xc6, 0x63, 0x51, 0xa0, 0x7b, 0xfe, 0x61, 0xc9, 0xf3, 0xd9, 0x56, - 0x99, 0x30, 0x57, 0x7c, 0x39, 0x0b, 0x65, 0x57, 0x4b, 0xe3, 0xce, 0x67, 0x6f, 0xa9, 0xe6, 0x83, 0x7f, 0x3c, 0x26, - 0x10, 0x6f, 0x14, 0xdf, 0xac, 0x1a, 0xb9, 0x75, 0x4d, 0xb6, 0x37, 0x25, 0xa0, 0x7e, 0x5f, 0x6e, 0x70, 0xbf, 0xc5, - 0xfa, 0x77, 0x4f, 0x83, 0x8c, 0xd5, 0x0c, 0x57, 0x4c, 0xe1, 0x53, 0x00, 0x18, 0x1c, 0x4e, 0x05, 0x69, 0x81, 0xb7, - 0xbc, 0x1c, 0x5e, 0x4f, 0xb6, 0x64, 0xd2, 0xdd, 0xfa, 0xc8, 0x9d, 0x05, 0xaa, 0xde, 0x6f, 0x28, 0x4e, 0x1a, 0x24, - 0x1a, 0x7b, 0x0d, 0xbe, 0xc8, 0x32, 0xca, 0x45, 0x13, 0xf7, 0x31, 0xf9, 0x4a, 0x0f, 0x60, 0xa5, 0x42, 0x09, 0x10, - 0xfd, 0xc6, 0xb2, 0xd8, 0x88, 0xb6, 0xc5, 0x06, 0x96, 0x52, 0x3e, 0xd7, 0xab, 0xe9, 0xb3, 0x57, 0xa2, 0x79, 0x1f, - 0xcd, 0x38, 0xa5, 0xd1, 0x80, 0xe3, 0x34, 0x0a, 0x77, 0xef, 0xef, 0x45, 0xb9, 0xcc, 0xc0, 0x92, 0xad, 0xc2, 0x29, - 0xae, 0x1b, 0x75, 0x46, 0xbc, 0xc8, 0x63, 0x05, 0xd0, 0xf1, 0x98, 0x00, 0xa8, 0x2e, 0x08, 0xa8, 0x88, 0x96, 0xd2, - 0x5b, 0xa1, 0xc5, 0x42, 0xbd, 0xe1, 0x28, 0x85, 0x3f, 0xd2, 0x9f, 0x07, 0xd5, 0x14, 0x80, 0xd8, 0xf5, 0x71, 0xf4, - 0xba, 0x28, 0xe9, 0x53, 0xc5, 0xac, 0x92, 0x83, 0x09, 0xec, 0xea, 0x44, 0x86, 0x9a, 0x43, 0xde, 0xbc, 0x2b, 0x6f, - 0x6e, 0xf2, 0x36, 0xc6, 0x29, 0xf9, 0x91, 0x9b, 0x8e, 0x35, 0x62, 0xe0, 0x95, 0xa7, 0x75, 0x9a, 0x20, 0x4d, 0x2e, - 0x80, 0x61, 0x88, 0xef, 0x32, 0xef, 0x85, 0xe7, 0x48, 0x55, 0x90, 0xcc, 0xf6, 0x99, 0xa7, 0x2e, 0xa2, 0xfa, 0xca, - 0xa9, 0xa5, 0x33, 0xa7, 0x1f, 0x01, 0xbc, 0xc7, 0xd4, 0xa4, 0x21, 0x1f, 0xe1, 0xb6, 0x14, 0x5f, 0xef, 0xd4, 0x35, - 0x5e, 0x1a, 0x9d, 0xbb, 0x97, 0x2f, 0xdd, 0x69, 0xd0, 0x4f, 0x41, 0x50, 0xce, 0x17, 0xa5, 0x80, 0x3d, 0x65, 0x36, - 0xd7, 0xab, 0x55, 0x2b, 0xb4, 0x8e, 0xc7, 0xb1, 0x76, 0x14, 0xd2, 0xea, 0x2c, 0x60, 0xab, 0x91, 0x4e, 0x09, 0x10, - 0x82, 0xe3, 0x34, 0xec, 0x0c, 0xe3, 0x2e, 0x9d, 0x46, 0x64, 0xbd, 0x52, 0x92, 0x2e, 0xcc, 0x20, 0xf9, 0x27, 0x79, - 0x3d, 0x03, 0x5a, 0x02, 0x38, 0x14, 0xb1, 0x84, 0x87, 0x93, 0xe4, 0x06, 0xa0, 0xd3, 0xe1, 0xa0, 0xd2, 0xd0, 0x9c, - 0xf9, 0x2c, 0x99, 0x4f, 0x62, 0xa9, 0xaa, 0x3c, 0x1e, 0x3d, 0xe5, 0x66, 0xd0, 0xef, 0x67, 0xd3, 0x52, 0xb9, 0x00, - 0x04, 0xb1, 0x2e, 0x0c, 0x10, 0x8f, 0xb4, 0xf0, 0x64, 0xd1, 0xa7, 0x24, 0x7e, 0x39, 0x4b, 0xe6, 0x26, 0x1b, 0xde, - 0x81, 0x11, 0x6c, 0xc6, 0x75, 0x49, 0x99, 0xf6, 0xa8, 0xfc, 0x9e, 0xd1, 0x53, 0xdb, 0xd7, 0x5a, 0x6d, 0x11, 0xeb, - 0x3a, 0xb8, 0x2a, 0x51, 0x4f, 0xf1, 0x41, 0x49, 0x82, 0xf7, 0x2b, 0xe7, 0x66, 0xa4, 0x7c, 0x2d, 0x2a, 0x3f, 0x68, - 0x67, 0x6a, 0xe5, 0xc0, 0x11, 0xa8, 0xb0, 0x8a, 0x4a, 0x5e, 0xef, 0x3a, 0x04, 0x4f, 0xee, 0x4a, 0x05, 0xca, 0xc1, - 0xcf, 0x41, 0x8c, 0xae, 0x6f, 0x3a, 0x6b, 0xa8, 0x99, 0x46, 0x95, 0x47, 0xd0, 0xb9, 0x03, 0x78, 0x52, 0xf0, 0x52, - 0xab, 0x1f, 0x8f, 0x47, 0xcf, 0xfc, 0xe0, 0x2f, 0x33, 0x7d, 0x0b, 0x31, 0x51, 0x4e, 0x35, 0x42, 0xe2, 0x4a, 0x49, - 0x22, 0x3e, 0x5d, 0xb4, 0xac, 0x18, 0x95, 0xe1, 0x03, 0xb0, 0x00, 0x51, 0xf9, 0xea, 0x54, 0xe5, 0xc5, 0x48, 0xdb, - 0x12, 0x78, 0x4d, 0xfe, 0x21, 0x72, 0xcd, 0x5b, 0x5f, 0x77, 0x95, 0xa1, 0x6f, 0x65, 0x05, 0x3a, 0x82, 0xad, 0x2c, - 0x25, 0x07, 0x7c, 0x52, 0xdf, 0x55, 0x5b, 0x9f, 0x53, 0xb6, 0x11, 0x6e, 0xf2, 0xeb, 0xd8, 0xc1, 0x91, 0xf2, 0x1b, - 0xbc, 0x14, 0xc0, 0x5e, 0x03, 0xf6, 0xe6, 0x8a, 0x15, 0xcd, 0xa3, 0x43, 0xda, 0x16, 0x68, 0x64, 0xe6, 0x76, 0xae, - 0xee, 0xdb, 0xf2, 0x28, 0x8d, 0x21, 0x32, 0xed, 0x91, 0xe9, 0x60, 0x33, 0xca, 0x7f, 0x4b, 0xf9, 0xad, 0xc2, 0x31, - 0xf0, 0xed, 0xdc, 0x3b, 0x80, 0xaa, 0xa7, 0x0d, 0x32, 0xd6, 0x0c, 0x43, 0x2b, 0xbb, 0x5c, 0x0a, 0x2d, 0x41, 0x4b, - 0xdd, 0x04, 0xc1, 0xf9, 0x11, 0x51, 0x8e, 0x00, 0x74, 0x91, 0x02, 0x26, 0xf8, 0x39, 0x6d, 0x77, 0xbf, 0xbf, 0x49, - 0x3d, 0x72, 0xef, 0x0a, 0x95, 0xcd, 0xf2, 0x4d, 0x8e, 0x30, 0xf6, 0x13, 0x8d, 0x19, 0x74, 0x72, 0x45, 0x4e, 0x78, - 0xd6, 0xea, 0xb0, 0xae, 0x9b, 0x32, 0x28, 0x8b, 0x63, 0x9e, 0x4f, 0x67, 0xbf, 0x3f, 0x39, 0xd4, 0x0d, 0xb2, 0x90, - 0xff, 0xce, 0x7a, 0x48, 0x06, 0xdd, 0x83, 0x50, 0x88, 0xde, 0x3c, 0x98, 0xe1, 0x7f, 0x6c, 0xcb, 0xb3, 0x6f, 0xb8, - 0x51, 0x27, 0x80, 0x39, 0xe2, 0x7a, 0xe9, 0x29, 0xda, 0x7a, 0xb8, 0x05, 0xb2, 0x0d, 0x5e, 0xde, 0xda, 0x6b, 0xa0, - 0xa2, 0x38, 0xfe, 0x15, 0xcf, 0xd4, 0xca, 0x06, 0x3f, 0x3d, 0x65, 0x3b, 0xf0, 0xf0, 0x22, 0x04, 0x14, 0xc3, 0xb2, - 0xf1, 0x2b, 0xcb, 0x71, 0x46, 0xff, 0xcd, 0x23, 0x86, 0xc1, 0x22, 0xf2, 0xe3, 0xcb, 0x52, 0x88, 0x2f, 0xc2, 0x7b, - 0x93, 0x7b, 0x2b, 0x72, 0xca, 0x5c, 0xe9, 0x61, 0x74, 0x5d, 0x92, 0xbe, 0x49, 0x3e, 0xb6, 0x86, 0xed, 0x77, 0xed, - 0x7e, 0x33, 0x44, 0x10, 0x42, 0x39, 0x7e, 0xce, 0xe8, 0x84, 0xc6, 0x87, 0x35, 0xd7, 0x3b, 0xbd, 0x7e, 0xef, 0x12, - 0x2f, 0xd8, 0x1a, 0x0d, 0xf0, 0x74, 0xe8, 0x62, 0x9e, 0xa8, 0xa1, 0xd3, 0x75, 0xed, 0x1c, 0x3c, 0x30, 0xc8, 0xf2, - 0xe4, 0x1b, 0x86, 0x25, 0xf6, 0x27, 0x11, 0x4f, 0xda, 0xaa, 0x8d, 0xed, 0x89, 0x6a, 0xa3, 0x66, 0xe0, 0x07, 0xaf, - 0xa0, 0xc0, 0xe8, 0x82, 0xb4, 0x06, 0xe3, 0x70, 0x04, 0x20, 0x2b, 0xc6, 0xf1, 0xc8, 0x60, 0x02, 0x43, 0xba, 0xa1, - 0x28, 0x00, 0x0f, 0x8f, 0xd3, 0x41, 0xc8, 0x00, 0xd2, 0x05, 0x0f, 0x0d, 0xdb, 0x24, 0xa4, 0xfc, 0x3c, 0x2f, 0x6b, - 0x35, 0x84, 0xbe, 0xb3, 0x50, 0x1d, 0xfb, 0x91, 0xf6, 0x8a, 0x75, 0xad, 0x4a, 0x27, 0xb6, 0x3a, 0x40, 0xdf, 0x90, - 0x81, 0x6f, 0x1d, 0x5b, 0x00, 0x44, 0x4b, 0xfc, 0x96, 0x7a, 0xb5, 0x2f, 0x63, 0x56, 0xa8, 0xd7, 0x17, 0xa6, 0x5d, - 0xaf, 0xa4, 0x45, 0x01, 0x15, 0xb7, 0xad, 0xda, 0x9e, 0xc8, 0xf9, 0x8f, 0xef, 0x3a, 0xda, 0xf1, 0xd9, 0xa9, 0xb1, - 0x25, 0x94, 0xb9, 0xc5, 0x13, 0x59, 0x1d, 0x6d, 0xa9, 0x4e, 0xf5, 0x01, 0x97, 0x9a, 0x54, 0x67, 0xda, 0xa7, 0xc9, - 0x12, 0xa0, 0xdc, 0x42, 0x24, 0x8d, 0xc3, 0xc1, 0xf9, 0x64, 0x50, 0x30, 0xb7, 0x48, 0x40, 0x02, 0xdb, 0xda, 0xda, - 0x45, 0x73, 0xfd, 0xfa, 0x2d, 0xf5, 0xf2, 0x36, 0x55, 0x3d, 0x78, 0xe3, 0x05, 0xce, 0xde, 0x69, 0x2d, 0x20, 0x80, - 0xc2, 0xd6, 0xb2, 0x1c, 0x9c, 0xbb, 0x5d, 0xd5, 0x52, 0x51, 0x46, 0xfd, 0xfe, 0xe5, 0x6f, 0x29, 0x2a, 0x62, 0xcf, - 0x15, 0xa7, 0xac, 0xdf, 0x6e, 0x99, 0x8b, 0xca, 0x92, 0x37, 0xa8, 0xa2, 0xb5, 0x3a, 0x6a, 0x72, 0xd7, 0xcd, 0x55, - 0x4b, 0x26, 0x88, 0xd1, 0x7d, 0xbe, 0xd6, 0x95, 0x53, 0xef, 0x83, 0x8a, 0x23, 0x06, 0x82, 0x9b, 0xee, 0xf1, 0xc1, - 0x41, 0x68, 0x54, 0x94, 0x0b, 0x6e, 0x94, 0x56, 0x95, 0x94, 0x42, 0xde, 0xaa, 0x68, 0xc5, 0xf4, 0x11, 0x00, 0x11, - 0x60, 0x95, 0xa8, 0xff, 0xcd, 0x97, 0xc6, 0x78, 0xf0, 0xc0, 0xd7, 0xe4, 0x3a, 0xb6, 0xde, 0x3f, 0xaf, 0x91, 0x56, - 0x1b, 0xc7, 0xa4, 0x56, 0xbd, 0x6c, 0x15, 0x2f, 0xbb, 0xd7, 0xa9, 0x18, 0x3c, 0xff, 0x9f, 0xfb, 0x00, 0x35, 0xa2, - 0xa5, 0x0c, 0x6e, 0x5d, 0x0d, 0xd0, 0xf8, 0x70, 0x2a, 0x7c, 0xe3, 0x87, 0x8c, 0xf3, 0xc1, 0x0c, 0x1d, 0xd5, 0xe6, - 0xe0, 0x80, 0xe0, 0xa8, 0xee, 0xd1, 0x98, 0x30, 0x0b, 0xe7, 0x1e, 0x04, 0xaa, 0x4f, 0xdc, 0x67, 0x5c, 0x7b, 0x41, - 0x9b, 0xc0, 0x27, 0xeb, 0xba, 0xa6, 0x08, 0x70, 0x11, 0x1b, 0x13, 0x31, 0xc4, 0x65, 0x93, 0x48, 0x7d, 0x33, 0x06, - 0x05, 0x40, 0xf1, 0x3c, 0x27, 0xb9, 0x74, 0x91, 0xe6, 0x95, 0x28, 0x6b, 0xdd, 0x8c, 0x9c, 0x15, 0xc3, 0x9c, 0xd5, - 0x7e, 0x50, 0xdc, 0xe4, 0x66, 0x42, 0x23, 0x36, 0x90, 0xca, 0x52, 0xb0, 0x7c, 0x58, 0xf8, 0x4d, 0xfb, 0x4d, 0x72, - 0xd2, 0xbb, 0x1c, 0xb7, 0xce, 0x1d, 0xfb, 0xde, 0x51, 0x48, 0x69, 0x0f, 0xc5, 0x04, 0x41, 0xf0, 0xd3, 0x3a, 0x9c, - 0x3f, 0xe3, 0xcf, 0x09, 0x4c, 0x45, 0x36, 0x63, 0xc0, 0x41, 0x88, 0xc8, 0x8c, 0xdf, 0x73, 0xf8, 0x9c, 0x97, 0x93, - 0x70, 0x38, 0xf4, 0x41, 0x1f, 0xca, 0xb3, 0x59, 0x38, 0x14, 0x73, 0xe9, 0xbd, 0x0e, 0xd6, 0xba, 0x90, 0xd7, 0x93, - 0x10, 0xd1, 0x42, 0x43, 0x1f, 0x9c, 0xd7, 0x5d, 0x73, 0x84, 0x25, 0x00, 0x4d, 0x1c, 0x7d, 0x59, 0xbf, 0x1f, 0x79, - 0xda, 0xd0, 0x22, 0xc5, 0x45, 0xa3, 0xcc, 0x66, 0x95, 0xec, 0x84, 0xad, 0x6b, 0xb7, 0x40, 0x28, 0x1e, 0xa6, 0x2d, - 0x54, 0xad, 0xa7, 0x7a, 0x3d, 0x37, 0xed, 0xbe, 0x7b, 0x54, 0xad, 0x72, 0xa2, 0xb3, 0x36, 0x5d, 0xa9, 0xd5, 0x2d, - 0xa3, 0x6a, 0x93, 0xa5, 0x11, 0x55, 0x6e, 0x52, 0xb9, 0x46, 0x2d, 0xf8, 0x64, 0x43, 0xcd, 0xb5, 0xb3, 0x35, 0x38, - 0x71, 0xe4, 0xb9, 0xe4, 0x96, 0xef, 0xce, 0x2b, 0xba, 0x3b, 0xd5, 0xbe, 0x05, 0xb8, 0x37, 0xc3, 0x86, 0xcc, 0x79, - 0x8d, 0x9d, 0x06, 0x61, 0x12, 0xf8, 0x11, 0xfb, 0x98, 0x21, 0x1b, 0x0c, 0xe8, 0x28, 0xa4, 0x26, 0xc0, 0x32, 0x47, - 0x02, 0x26, 0x7f, 0x3d, 0xf7, 0x9b, 0x45, 0x91, 0xc3, 0x62, 0xfc, 0xb0, 0xc5, 0x48, 0x63, 0xb5, 0x06, 0xc3, 0x72, - 0x85, 0xc8, 0x9f, 0xda, 0x33, 0xd4, 0x54, 0xc7, 0x9b, 0xf5, 0x5a, 0xf3, 0xab, 0xa7, 0x4f, 0x75, 0x7d, 0xfe, 0xdb, - 0xf7, 0x97, 0x61, 0xcd, 0xec, 0x0f, 0x41, 0x28, 0xed, 0xc1, 0x2d, 0xce, 0x1d, 0x89, 0xde, 0xa9, 0xd2, 0xcc, 0x2e, - 0xed, 0x9a, 0x5d, 0x9b, 0xd2, 0x6e, 0xc9, 0xf5, 0xea, 0x2b, 0xe5, 0x8d, 0x9d, 0x57, 0x4c, 0xf7, 0x1f, 0x84, 0xde, - 0x51, 0xce, 0xd5, 0x04, 0x22, 0x9a, 0xb4, 0x23, 0x71, 0xbb, 0x57, 0x86, 0xcf, 0x26, 0x55, 0xbb, 0x84, 0x93, 0xae, - 0x61, 0x95, 0xf9, 0xf6, 0x3f, 0xf2, 0xaa, 0xb3, 0xc2, 0xed, 0x97, 0xc6, 0xac, 0xfd, 0x29, 0x88, 0xab, 0xfa, 0xc3, - 0x7b, 0x52, 0x33, 0x25, 0xff, 0x57, 0x3d, 0x06, 0xae, 0x7e, 0x32, 0xed, 0xe4, 0x9e, 0x42, 0xd8, 0x60, 0xf6, 0xf3, - 0xd3, 0x87, 0x16, 0xac, 0xaa, 0x0b, 0x14, 0xc9, 0x01, 0x74, 0xee, 0x9a, 0x11, 0xde, 0xef, 0x18, 0xe7, 0xfe, 0xcd, - 0x0f, 0x6a, 0x72, 0x84, 0x88, 0x76, 0x11, 0x0e, 0x00, 0xe2, 0x4e, 0x53, 0x59, 0x87, 0x1a, 0xa0, 0x0f, 0x08, 0xac, - 0x43, 0xdf, 0x66, 0x00, 0x07, 0x7d, 0xb4, 0x79, 0x16, 0x81, 0xbc, 0xee, 0xdd, 0xb3, 0xb7, 0x6c, 0xef, 0xf3, 0xe7, - 0xeb, 0xd4, 0xbb, 0x47, 0x87, 0xe0, 0xcb, 0xb1, 0x3f, 0xbd, 0x0e, 0x0c, 0x2e, 0x34, 0x7b, 0xfb, 0x54, 0xb0, 0x3d, - 0xdb, 0x3f, 0x45, 0xa4, 0xa2, 0xee, 0xfc, 0xc3, 0x6b, 0x13, 0x3d, 0xef, 0xbc, 0xb0, 0xe2, 0x4b, 0x00, 0x0f, 0x64, - 0x31, 0xa0, 0xf8, 0x2c, 0xbd, 0x7f, 0xb2, 0x04, 0xd4, 0xe4, 0x77, 0x7c, 0xe3, 0xbd, 0xa3, 0xd4, 0x05, 0xfc, 0x39, - 0xa0, 0xf4, 0x49, 0xc5, 0xbd, 0xd5, 0xf0, 0xce, 0xbf, 0x7a, 0x06, 0xce, 0x13, 0xeb, 0xe1, 0x02, 0xfe, 0x2a, 0xf8, - 0xd0, 0x5b, 0x0d, 0x30, 0xb1, 0xe4, 0x43, 0x6f, 0x3d, 0x80, 0x54, 0x85, 0x0b, 0x89, 0xb1, 0x0f, 0xbf, 0x06, 0x15, - 0xc3, 0x3f, 0x7e, 0xd3, 0x18, 0xac, 0xbf, 0x06, 0x85, 0x46, 0x63, 0x2d, 0x55, 0xc8, 0x52, 0x2c, 0x2e, 0x04, 0xd8, - 0x84, 0xe3, 0x6e, 0x5f, 0xac, 0x6a, 0xbb, 0x11, 0xf4, 0xe7, 0x23, 0xbe, 0x47, 0x63, 0x75, 0x55, 0xce, 0x45, 0xf9, - 0x11, 0xe9, 0x53, 0x1d, 0x1f, 0xa3, 0x62, 0x5b, 0x77, 0xa7, 0x53, 0xad, 0x3a, 0xd2, 0x7e, 0x53, 0xae, 0xc1, 0x8e, - 0xd7, 0xc9, 0x89, 0xa5, 0xf0, 0xa2, 0xc3, 0xce, 0x4b, 0xa7, 0x44, 0x87, 0x61, 0xbc, 0xdb, 0xaa, 0x67, 0x0c, 0xe5, - 0x95, 0xc1, 0x98, 0x2e, 0x78, 0xc4, 0x9f, 0x0f, 0x2a, 0x19, 0x1a, 0xf3, 0x01, 0xd9, 0x30, 0x94, 0x0f, 0x2d, 0x32, - 0x24, 0x44, 0xbc, 0x87, 0x4a, 0xc0, 0xb6, 0x05, 0x65, 0x52, 0xc0, 0x59, 0x34, 0xf8, 0xad, 0xf6, 0x2a, 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, 0x28, 0x59, 0xa7, 0x8d, 0x27, 0xc6, 0xdf, 0x5d, 0xe5, 0x9f, 0xa2, 0xa5, 0x1e, 0xfe, - 0x3f, 0x63, 0x0a, 0xa5, 0x7f, 0x99, 0x96, 0xd1, 0x76, 0xbd, 0x14, 0xa5, 0xc8, 0x23, 0x71, 0xf6, 0xb5, 0xc8, 0xce, - 0xe5, 0x3b, 0x9f, 0x42, 0xbf, 0x00, 0xb4, 0xec, 0x13, 0x64, 0xf4, 0x0f, 0x4c, 0xf0, 0xe1, 0x0f, 0xda, 0xb9, 0xb6, - 0xe2, 0xe3, 0x49, 0x75, 0x63, 0xed, 0xdd, 0x8e, 0x17, 0x89, 0x51, 0x8c, 0x55, 0xbe, 0xea, 0x66, 0xe5, 0x44, 0x25, - 0x07, 0x46, 0xba, 0x26, 0x7b, 0x95, 0x92, 0x75, 0x3b, 0xdd, 0x4a, 0x20, 0xa2, 0x0a, 0xbc, 0xc7, 0xb8, 0x8a, 0x7d, - 0x04, 0xd3, 0x75, 0xc7, 0x65, 0xb4, 0xe3, 0x3d, 0xe3, 0xd5, 0x89, 0xb2, 0x82, 0xdb, 0x8d, 0x68, 0x4f, 0xe8, 0xe8, - 0xa7, 0x49, 0x6d, 0x59, 0x38, 0x00, 0xb9, 0x4b, 0x18, 0xcb, 0x86, 0x60, 0xc5, 0xa0, 0xf4, 0xf5, 0x9a, 0x92, 0x65, - 0x01, 0x16, 0x9d, 0x5d, 0x46, 0x20, 0x86, 0x75, 0xd3, 0x9c, 0xd1, 0xf1, 0xd2, 0xc5, 0xf9, 0xa0, 0x55, 0xa4, 0xe0, - 0x19, 0x2d, 0x3a, 0xe6, 0xa6, 0x23, 0xdd, 0x18, 0xed, 0xed, 0x0f, 0x06, 0x21, 0xc5, 0xf3, 0x07, 0xb6, 0x5a, 0x17, - 0x17, 0x89, 0x57, 0xc8, 0x44, 0x0b, 0x62, 0x29, 0x02, 0x33, 0x5e, 0x68, 0x1a, 0x61, 0x82, 0x32, 0x25, 0x58, 0xb4, - 0x46, 0x87, 0xf6, 0x87, 0x25, 0xec, 0x1e, 0x63, 0x04, 0x08, 0x54, 0x99, 0x3e, 0x87, 0xad, 0x09, 0xb3, 0xad, 0x8b, - 0x2d, 0xd0, 0x56, 0x31, 0x34, 0x08, 0x6b, 0x43, 0xcc, 0xc7, 0x34, 0x5f, 0xfd, 0x13, 0x8b, 0xb1, 0x3d, 0x81, 0xd8, - 0xc1, 0xed, 0x9a, 0x84, 0xe9, 0x5e, 0x8b, 0x1b, 0xeb, 0xe5, 0xf6, 0x94, 0x63, 0x6a, 0xc7, 0xda, 0xaa, 0x1d, 0x6b, - 0xa9, 0x77, 0xac, 0x8d, 0xde, 0xb1, 0x56, 0x0d, 0xff, 0x90, 0x79, 0x31, 0x4b, 0x40, 0xbf, 0xbb, 0xe6, 0xaa, 0x41, - 0xd0, 0x8c, 0x2d, 0xbb, 0x83, 0xdf, 0x12, 0x6b, 0xb7, 0xf4, 0xaf, 0x96, 0x6c, 0x61, 0xfa, 0x40, 0xb7, 0x0e, 0xb0, - 0x8c, 0xa8, 0xc9, 0xf7, 0xc8, 0xbb, 0xe9, 0xac, 0x28, 0xdc, 0x9e, 0xd8, 0xc2, 0x67, 0x6f, 0xcd, 0x9b, 0xf7, 0x4f, - 0x23, 0xc8, 0xbd, 0xe7, 0xde, 0xfd, 0xf0, 0xad, 0x7f, 0xa5, 0x5b, 0x20, 0x27, 0xb3, 0x9c, 0x81, 0xd4, 0x11, 0x9f, - 0x20, 0x5a, 0xd9, 0x53, 0xbe, 0x13, 0x72, 0x67, 0xdb, 0x3c, 0xbd, 0x77, 0xb7, 0xb5, 0xd5, 0xd3, 0x7b, 0x96, 0x8f, - 0x28, 0x56, 0x9c, 0xa6, 0x48, 0x98, 0x45, 0x5b, 0xe0, 0xa9, 0x97, 0xef, 0x77, 0xec, 0x98, 0xc3, 0xfd, 0xd3, 0x8e, - 0x8e, 0x97, 0x73, 0xc0, 0xee, 0xfe, 0x93, 0x4d, 0xd8, 0x58, 0xe9, 0x5a, 0x85, 0x0e, 0xf7, 0x4f, 0x33, 0x8d, 0xe7, - 0x70, 0x22, 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, 0xba, 0xe4, 0xb1, 0xef, 0xd3, 0x2c, 0xad, 0xf7, 0xa8, 0xb5, 0xc8, 0x2d, 0xcb, 0xb0, 0xf6, 0x7e, 0xd0, 0x8a, - 0x61, 0xa9, 0xe9, 0x9f, 0x8e, 0x03, 0xb7, 0xb3, 0xdd, 0xca, 0xd8, 0x65, 0x3c, 0x2d, 0xae, 0x7e, 0x38, 0x2f, 0x94, - 0x6b, 0x37, 0x6f, 0xe3, 0x37, 0xad, 0x96, 0x2c, 0xad, 0xf5, 0x90, 0x97, 0x96, 0x45, 0x04, 0x02, 0x18, 0x4e, 0x94, - 0x5d, 0x2c, 0xe1, 0x1e, 0x61, 0x75, 0x0f, 0x42, 0xc9, 0xbc, 0x70, 0xf5, 0x8c, 0xc5, 0x90, 0x08, 0xb0, 0xdd, 0xa1, - 0x62, 0x5b, 0xb8, 0x7a, 0xc6, 0xb6, 0xbc, 0xe8, 0xf7, 0x33, 0xd5, 0x29, 0x64, 0xdd, 0x59, 0xf2, 0xad, 0x6a, 0x8e, - 0x35, 0xd4, 0x6c, 0x63, 0x92, 0xad, 0x71, 0x6e, 0x2b, 0x3e, 0x56, 0x6d, 0xc5, 0xc7, 0xda, 0x5a, 0x97, 0xee, 0xf5, - 0x1e, 0xd5, 0x05, 0xb0, 0xf5, 0xdf, 0x9d, 0xae, 0x5c, 0xcf, 0x67, 0x04, 0xf0, 0xb5, 0xe0, 0xe3, 0xc9, 0x02, 0xbd, - 0x4a, 0x16, 0xfe, 0xdd, 0x40, 0x8d, 0xbf, 0xd3, 0xb9, 0x0b, 0x80, 0xae, 0xa4, 0xbc, 0x02, 0xf2, 0x0e, 0x2a, 0xcc, - 0x2d, 0xbb, 0xf2, 0xfe, 0xec, 0x3b, 0xec, 0x2d, 0xaf, 0x67, 0x8b, 0x39, 0xdb, 0x83, 0x53, 0x41, 0x32, 0xb0, 0x97, - 0x15, 0xdb, 0x07, 0xb1, 0x9d, 0xf0, 0x1b, 0x01, 0x53, 0xbe, 0x80, 0x20, 0xae, 0xe0, 0x0e, 0xe2, 0xf0, 0xe4, 0x9f, - 0x83, 0xfb, 0xd6, 0x66, 0x7d, 0xcf, 0xac, 0xce, 0x09, 0x36, 0xcc, 0xea, 0xc1, 0x60, 0xd9, 0x4c, 0xd6, 0xfd, 0xbe, - 0xb7, 0xd7, 0x8e, 0x4f, 0x2b, 0xa9, 0x13, 0x3b, 0xaf, 0xd5, 0x5a, 0xb0, 0xb7, 0x52, 0xeb, 0x62, 0x0c, 0x3d, 0x80, - 0x5f, 0x70, 0x37, 0xe0, 0xf7, 0x1d, 0x6b, 0xcb, 0x7b, 0xcb, 0x16, 0x6c, 0x0f, 0x97, 0xa0, 0xa6, 0xbd, 0xec, 0xcf, - 0x2a, 0x17, 0xb4, 0x63, 0x97, 0xc4, 0xc3, 0x19, 0xb3, 0x5c, 0x99, 0x59, 0x27, 0xf9, 0x8d, 0xe8, 0x8c, 0xe9, 0xac, - 0xf5, 0x7c, 0xce, 0xe7, 0x93, 0x42, 0x83, 0xfa, 0x5d, 0x12, 0x1f, 0x51, 0xd1, 0x79, 0x02, 0x5b, 0xcb, 0x0a, 0xc8, - 0xbd, 0x2e, 0xc1, 0x5a, 0xab, 0x5d, 0xfa, 0xbd, 0x6a, 0xc0, 0x6d, 0xca, 0x61, 0x4d, 0x40, 0xd0, 0x9c, 0x59, 0x51, - 0x8f, 0xd9, 0x8e, 0x71, 0xf3, 0xd3, 0xcb, 0x1f, 0x9c, 0xb0, 0x64, 0xc5, 0x6a, 0x7f, 0xfa, 0xc3, 0x53, 0x4f, 0x7f, - 0xa7, 0xf6, 0xaf, 0x84, 0x1f, 0x8c, 0xff, 0x5d, 0xbb, 0xaf, 0xb5, 0x18, 0x95, 0xad, 0x72, 0x84, 0xc6, 0xdd, 0x4a, - 0x9a, 0x2c, 0x3f, 0x09, 0x4f, 0x58, 0x0b, 0x9e, 0x99, 0x33, 0x20, 0x2b, 0x60, 0x85, 0xb5, 0x4c, 0xc2, 0x39, 0xc6, - 0x6a, 0x69, 0xab, 0x6f, 0xd1, 0x34, 0xa7, 0x87, 0x73, 0x6d, 0x50, 0xa6, 0x9c, 0x9d, 0x11, 0xab, 0xe1, 0x32, 0x2c, - 0x4d, 0x28, 0x42, 0xf6, 0x60, 0x07, 0x37, 0x76, 0xca, 0x52, 0xca, 0x70, 0x8e, 0xc1, 0x84, 0x27, 0x62, 0x54, 0xee, - 0xfb, 0x87, 0x92, 0x57, 0x6d, 0x39, 0x28, 0x47, 0xd8, 0x47, 0x12, 0x25, 0x70, 0x2b, 0xd2, 0x42, 0x91, 0xb2, 0xf8, - 0xdb, 0x01, 0xba, 0xc0, 0x0b, 0xa8, 0xab, 0x51, 0xb7, 0x3f, 0x1c, 0xf1, 0xf0, 0x91, 0xa9, 0x0f, 0x8c, 0x58, 0x12, - 0xa8, 0xed, 0x45, 0x96, 0xae, 0x40, 0x85, 0xdf, 0xc3, 0xd5, 0x44, 0xec, 0xe7, 0x96, 0x14, 0x15, 0xd9, 0x48, 0x6f, - 0x68, 0x0d, 0x1e, 0xa1, 0x35, 0xe5, 0x07, 0x27, 0xd5, 0x26, 0x9d, 0x77, 0x84, 0x1c, 0xab, 0x6f, 0x2d, 0x61, 0xb4, - 0x2b, 0x7a, 0xf1, 0xe0, 0xe8, 0x3d, 0xcf, 0x57, 0xbd, 0xf2, 0x27, 0xae, 0x98, 0x27, 0xb7, 0x11, 0xa8, 0x5b, 0x41, - 0x75, 0x7b, 0xaf, 0x12, 0x2c, 0x58, 0xd2, 0xee, 0xe3, 0xb7, 0xb3, 0x76, 0x20, 0x2a, 0x63, 0x95, 0xbe, 0x26, 0x09, - 0x7b, 0x62, 0xd0, 0x29, 0x54, 0x55, 0x76, 0x77, 0xb4, 0x05, 0xae, 0x53, 0x96, 0xa2, 0x17, 0xb6, 0xc8, 0xdd, 0xf2, - 0xef, 0x9e, 0x2b, 0x72, 0xf6, 0x6b, 0x40, 0x70, 0x6a, 0xbe, 0x22, 0xbe, 0x9c, 0xe0, 0x51, 0x75, 0x0b, 0x1c, 0xe7, - 0xef, 0x00, 0xfe, 0xf1, 0x78, 0x0d, 0x9a, 0x80, 0x58, 0xb0, 0x5e, 0x1a, 0xf7, 0x58, 0x2f, 0x2e, 0xb6, 0xab, 0x24, - 0xdf, 0x82, 0x33, 0x03, 0xa5, 0x5a, 0xfa, 0x81, 0x53, 0xb5, 0x80, 0x0a, 0x07, 0xb3, 0x93, 0x7a, 0x61, 0x19, 0xf5, - 0x98, 0x3e, 0x3f, 0x83, 0x83, 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, 0x8f, 0xf1, 0x77, 0x3d, 0x23, 0x23, 0x8f, 0x5b, 0x87, 0xd5, 0xff, 0xfa, 0x4f, - 0x08, 0x80, 0xc3, 0xb3, 0xa9, 0x77, 0x3d, 0x86, 0xac, 0xb2, 0x8c, 0x40, 0xf2, 0x13, 0x83, 0x2f, 0x5f, 0x00, 0x54, - 0x7d, 0xa6, 0x6b, 0x35, 0x39, 0x6a, 0x8f, 0x39, 0x74, 0xc5, 0x00, 0xb0, 0x0d, 0x4b, 0x54, 0xd5, 0xc2, 0x26, 0x2c, - 0x6e, 0x3f, 0xc3, 0x68, 0x2e, 0x9b, 0x5e, 0xd0, 0x40, 0x3d, 0x42, 0xf0, 0x4b, 0xeb, 0xa1, 0xb5, 0x96, 0x29, 0x87, - 0xae, 0x8d, 0xa2, 0xca, 0x86, 0xba, 0x84, 0xd5, 0x46, 0x44, 0x35, 0x51, 0xa4, 0x5c, 0x33, 0x8a, 0x62, 0xa9, 0x82, - 0x43, 0x26, 0x56, 0x10, 0x35, 0x4f, 0x5b, 0x6d, 0x15, 0x1c, 0x56, 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, 0x8a, 0x20, 0xb2, 0x00, 0x01, 0x1c, 0x37, 0x10, 0xf8, 0xbc, 0xc6, 0x27, 0xd0, 0x28, 0x04, - 0xf2, 0x03, 0xeb, 0x70, 0xe3, 0x21, 0x2d, 0xb5, 0x46, 0x44, 0x89, 0xf8, 0xc9, 0xd5, 0x73, 0x6c, 0x5f, 0x3d, 0x8d, - 0xb5, 0xa5, 0x34, 0x41, 0xfc, 0xc4, 0x62, 0x0b, 0x31, 0x41, 0x54, 0x87, 0xe8, 0x04, 0x96, 0x13, 0x42, 0x14, 0xfe, - 0x10, 0xfa, 0xa9, 0x81, 0xbf, 0x64, 0xcb, 0x22, 0xaf, 0x09, 0x16, 0x33, 0x67, 0x80, 0x56, 0x45, 0xe0, 0x99, 0xce, - 0x96, 0xca, 0x9c, 0xe6, 0xd1, 0x91, 0x1d, 0x5c, 0x76, 0x1d, 0xec, 0xa5, 0x2f, 0x63, 0x27, 0xcb, 0xa6, 0x51, 0x1b, - 0x1b, 0x22, 0xe1, 0x15, 0xf9, 0xcb, 0x2c, 0x35, 0xce, 0x91, 0x6a, 0x7d, 0xd7, 0xc5, 0x6a, 0x45, 0xdb, 0x84, 0x55, - 0x88, 0x50, 0xb7, 0x0d, 0x95, 0x4b, 0x61, 0x36, 0x36, 0x4d, 0x03, 0x7c, 0xa1, 0xa8, 0x54, 0xca, 0x53, 0x5b, 0xa9, - 0xe4, 0x84, 0x77, 0x7d, 0x55, 0x8b, 0xd4, 0x15, 0xc1, 0x36, 0x66, 0xa8, 0x87, 0x72, 0xa3, 0xc6, 0xbe, 0xee, 0x58, - 0xa5, 0x77, 0x98, 0xa0, 0x62, 0xe4, 0x45, 0x0e, 0x2e, 0x4a, 0x0a, 0x32, 0x57, 0x43, 0x98, 0x3f, 0x6a, 0xf8, 0xb4, - 0xb0, 0xdc, 0x43, 0x09, 0x98, 0x1d, 0x35, 0xbc, 0x8c, 0x10, 0x88, 0xb8, 0x54, 0xf6, 0x15, 0x13, 0xbf, 0xa7, 0x60, - 0x96, 0x4c, 0xe8, 0x5e, 0xc4, 0xc2, 0x08, 0x6d, 0x7c, 0x92, 0x24, 0x53, 0xb9, 0x3e, 0x41, 0x17, 0x2a, 0x5c, 0x20, - 0x23, 0xb4, 0x48, 0xf3, 0x4f, 0x87, 0x53, 0x09, 0x3e, 0xa2, 0x4e, 0x01, 0xc7, 0xf3, 0xcb, 0xc2, 0xfa, 0xc9, 0x2a, - 0x89, 0xb9, 0xac, 0xcd, 0x7f, 0xd9, 0xc9, 0x31, 0xd8, 0xe5, 0x69, 0xe2, 0xb8, 0xfa, 0x8f, 0xaa, 0xa4, 0x78, 0xf8, - 0x39, 0xcd, 0x01, 0x45, 0x30, 0xb3, 0xa7, 0x18, 0x1f, 0xfb, 0x2c, 0x53, 0xc0, 0xdf, 0xae, 0xb7, 0x96, 0x4c, 0xec, - 0x92, 0x76, 0x2b, 0x65, 0xfc, 0x52, 0x1b, 0x76, 0x1c, 0x5c, 0x1a, 0x80, 0xe2, 0xac, 0xd1, 0x61, 0x79, 0xad, 0xdb, - 0x56, 0x8e, 0x0a, 0xd4, 0xfa, 0xdf, 0xbb, 0x85, 0x29, 0x6f, 0xf3, 0x52, 0x79, 0x9b, 0x87, 0x26, 0x40, 0x20, 0x32, - 0x43, 0x9e, 0x35, 0x1d, 0x93, 0xc4, 0xbd, 0x23, 0x25, 0xed, 0x3b, 0x52, 0xfc, 0xe8, 0x1d, 0x09, 0xf9, 0x96, 0xd0, - 0x91, 0x7d, 0xc9, 0xc9, 0x09, 0x94, 0x19, 0xec, 0xe5, 0x0d, 0x93, 0xfd, 0x03, 0xda, 0x0b, 0xe7, 0xb2, 0xbc, 0xe6, - 0x6f, 0x85, 0xb7, 0xf1, 0xa7, 0x9b, 0xf3, 0xae, 0xaa, 0x77, 0x5f, 0x99, 0x99, 0xc7, 0x63, 0x71, 0x3c, 0xe6, 0x26, - 0x68, 0x77, 0xc1, 0xc5, 0xa0, 0x62, 0xf7, 0x6e, 0x7c, 0xfc, 0x5b, 0x8e, 0x22, 0xb6, 0x52, 0x1e, 0x49, 0x17, 0x2a, - 0x31, 0xbc, 0x36, 0xf0, 0x30, 0x7b, 0x3e, 0x9e, 0xec, 0x6f, 0xee, 0x27, 0x83, 0xc1, 0x5e, 0xf5, 0xed, 0x8e, 0xd7, - 0xb3, 0xfd, 0x9c, 0x3d, 0xf0, 0xbb, 0xe9, 0x2e, 0x38, 0x34, 0xb0, 0xed, 0xee, 0x6f, 0xc4, 0xf1, 0xb8, 0x7f, 0xce, - 0x17, 0xfe, 0xe1, 0x01, 0x01, 0x9d, 0xf9, 0xe5, 0xb8, 0x8d, 0xf1, 0x73, 0xdb, 0x76, 0xd5, 0xda, 0x03, 0x3c, 0xfd, - 0x8f, 0xde, 0xed, 0x6c, 0x39, 0xf7, 0xd9, 0x13, 0xfe, 0x00, 0xfe, 0xf9, 0xb8, 0x49, 0x22, 0xf5, 0x89, 0x76, 0x99, - 0xbc, 0x05, 0x07, 0xf2, 0xbd, 0xcf, 0xde, 0xf0, 0x87, 0xd9, 0x72, 0xce, 0x8b, 0xe3, 0xf1, 0xfd, 0x34, 0x44, 0xb2, - 0xa6, 0xb0, 0x22, 0x96, 0x14, 0xcf, 0x0f, 0xc2, 0xd3, 0xf7, 0x22, 0x32, 0x44, 0x5a, 0xee, 0xdd, 0x21, 0xbb, 0x65, - 0x91, 0x1f, 0xc0, 0x07, 0xd9, 0xde, 0x9f, 0xc8, 0x9a, 0xd2, 0xfd, 0xe2, 0x89, 0x7f, 0x3c, 0xd2, 0x5f, 0x6f, 0xfc, - 0xe3, 0xf1, 0x3d, 0x7b, 0x40, 0x70, 0x74, 0xbe, 0x87, 0xfe, 0xd1, 0xb7, 0x0e, 0xa8, 0xca, 0xf0, 0xed, 0x6c, 0x3b, - 0xf7, 0x9f, 0xaf, 0xd9, 0x0a, 0xb8, 0x50, 0x94, 0x17, 0xda, 0x2d, 0x7b, 0x40, 0xaf, 0x33, 0x72, 0x22, 0x9a, 0xed, - 0xe7, 0x3e, 0x8b, 0xf1, 0xb9, 0xba, 0x2f, 0x26, 0x5f, 0xbd, 0x2f, 0xee, 0xd9, 0xae, 0xfb, 0xbe, 0x28, 0xdf, 0x74, - 0xd7, 0xcf, 0x8e, 0xed, 0xd9, 0x03, 0xcc, 0xb0, 0xb7, 0xfc, 0xb6, 0x39, 0x75, 0x8c, 0xfd, 0xea, 0x8d, 0x11, 0x40, - 0x99, 0x2d, 0x58, 0x2c, 0x38, 0x28, 0xd5, 0xaa, 0x6d, 0x49, 0xe4, 0xb9, 0x0e, 0x54, 0x9b, 0x11, 0xdc, 0x97, 0xde, - 0xa2, 0xd4, 0x45, 0x4f, 0xfb, 0x14, 0xe4, 0x88, 0x16, 0x0e, 0x1b, 0xf0, 0x57, 0xda, 0x3a, 0xc6, 0x30, 0xcd, 0x7c, - 0xa6, 0x1d, 0x3d, 0xaf, 0xbf, 0xed, 0x3d, 0x93, 0xdf, 0xc8, 0xc0, 0x16, 0x22, 0x29, 0x1c, 0xc7, 0x57, 0xcf, 0xce, - 0xf8, 0xaf, 0x5a, 0x1e, 0xb5, 0xda, 0x2f, 0x94, 0xfa, 0xf4, 0x25, 0x1d, 0xd1, 0xc4, 0xbd, 0x68, 0xcb, 0xb0, 0x46, - 0x59, 0x53, 0x4b, 0x87, 0x61, 0x5c, 0xc3, 0xbe, 0x3c, 0x70, 0xe8, 0x3b, 0x20, 0xd0, 0xe6, 0xa9, 0x14, 0x68, 0xe1, - 0x18, 0x46, 0x61, 0x16, 0x52, 0x1e, 0x17, 0x66, 0x29, 0xef, 0xa9, 0x40, 0x8b, 0x5b, 0x75, 0x8f, 0xa9, 0xed, 0x16, - 0x44, 0x58, 0xbd, 0x65, 0x5c, 0x5e, 0x37, 0xaa, 0x70, 0x5b, 0x80, 0xa2, 0x08, 0xca, 0xe0, 0x40, 0x72, 0xdb, 0x42, - 0x49, 0xb3, 0x51, 0x58, 0x8b, 0x55, 0x51, 0xee, 0x7b, 0x0d, 0x5b, 0xe0, 0x05, 0x55, 0x3f, 0x21, 0x6c, 0xcb, 0x9e, - 0x75, 0x28, 0x17, 0xe9, 0xbf, 0x65, 0xe9, 0xf9, 0x76, 0x6b, 0xce, 0xff, 0xf4, 0x15, 0x7d, 0x54, 0xfe, 0xfb, 0x97, - 0xf4, 0xb3, 0xc1, 0x32, 0x72, 0x4a, 0xfd, 0x10, 0x8d, 0xee, 0xd2, 0x9c, 0x30, 0xb6, 0x7c, 0xfd, 0xf4, 0x1b, 0x64, - 0x0a, 0x92, 0x43, 0x29, 0x55, 0x39, 0xd9, 0x43, 0x5f, 0x78, 0xdd, 0x87, 0x99, 0x60, 0x00, 0xc2, 0x6b, 0xb4, 0xa9, - 0x26, 0x4c, 0xe2, 0xd1, 0x15, 0xfc, 0xdf, 0x08, 0x62, 0xd0, 0x3e, 0x51, 0xd4, 0xb1, 0x6d, 0xa4, 0xeb, 0xb6, 0x73, - 0x90, 0xdc, 0xa9, 0x73, 0x7f, 0x54, 0x4e, 0xfe, 0x1d, 0x0d, 0x91, 0x57, 0xdc, 0x20, 0x56, 0x16, 0x5c, 0x62, 0x31, - 0x54, 0xa4, 0x00, 0xd7, 0x10, 0x44, 0xca, 0xa2, 0xa4, 0x70, 0xc7, 0x41, 0x55, 0x04, 0x60, 0x5c, 0xad, 0x8e, 0x3a, - 0x13, 0x3e, 0x6e, 0xad, 0x45, 0x88, 0x3a, 0x34, 0x6a, 0x65, 0xad, 0xc0, 0x17, 0xa4, 0x2f, 0x1d, 0x0a, 0x62, 0x7a, - 0x14, 0x52, 0x55, 0x3a, 0x14, 0x48, 0x73, 0xa8, 0xf8, 0xc6, 0x60, 0xa3, 0xc8, 0x49, 0xcf, 0x5f, 0x9a, 0x14, 0x65, - 0xcc, 0xf8, 0x20, 0xca, 0x48, 0xe4, 0x75, 0xb8, 0x12, 0xd3, 0x02, 0xf9, 0x46, 0x4f, 0x1f, 0x04, 0xd7, 0xf0, 0x6e, - 0xc8, 0xbd, 0x02, 0x6c, 0x09, 0xd8, 0x01, 0xee, 0x95, 0x19, 0xe5, 0x3a, 0xad, 0xeb, 0xb7, 0xd6, 0x43, 0x31, 0x0c, - 0x9f, 0x5a, 0x02, 0xdb, 0xc9, 0x3a, 0x3a, 0xd1, 0xc3, 0x87, 0xff, 0x75, 0x55, 0x73, 0xd4, 0xa9, 0x5c, 0xce, 0x4e, - 0x27, 0x2c, 0x45, 0xcc, 0xa0, 0xfb, 0xeb, 0xee, 0xa5, 0x00, 0xba, 0x5d, 0x16, 0xf3, 0x6c, 0xb4, 0x97, 0x7f, 0x4b, - 0x37, 0x56, 0x94, 0x36, 0xf1, 0x2e, 0xeb, 0x8d, 0xfd, 0xe1, 0xe8, 0x3f, 0x9e, 0xbe, 0x9b, 0x10, 0xaa, 0xce, 0x96, - 0x6d, 0x74, 0x9c, 0xcb, 0xff, 0xfa, 0xcf, 0x31, 0x59, 0x41, 0x50, 0x10, 0x96, 0x9d, 0x62, 0xa2, 0x82, 0x51, 0xa4, - 0xd8, 0xf0, 0xf1, 0x64, 0x83, 0x3a, 0xe1, 0x8d, 0xbf, 0xd4, 0x3a, 0x61, 0x62, 0x64, 0xa5, 0xf2, 0x37, 0x2c, 0x67, - 0x2b, 0x95, 0x59, 0x40, 0xe6, 0x41, 0x35, 0xd9, 0x18, 0x0d, 0xe6, 0x9a, 0xd7, 0xb3, 0xcd, 0x5c, 0x2a, 0x9f, 0xc1, - 0x94, 0xb3, 0x1c, 0x9c, 0x2d, 0x85, 0xdd, 0x93, 0x40, 0xd1, 0x9a, 0xa1, 0x1b, 0x7f, 0x8a, 0xad, 0x7a, 0x95, 0x56, - 0x35, 0xc0, 0x03, 0x42, 0x0c, 0x0c, 0xb5, 0x57, 0x0b, 0x0f, 0xad, 0x05, 0xb0, 0xf1, 0x47, 0xa5, 0x1f, 0x8c, 0x27, - 0x4b, 0xbe, 0x40, 0xfe, 0xe5, 0xc8, 0x51, 0xbb, 0xf7, 0xfb, 0xde, 0x3d, 0x48, 0xc1, 0x91, 0x6b, 0xa1, 0x40, 0x22, - 0xa0, 0x05, 0xdf, 0xfa, 0xca, 0x07, 0xe3, 0x2d, 0x6a, 0xab, 0x41, 0x41, 0xed, 0xe8, 0x96, 0xc7, 0x8e, 0xde, 0xf9, - 0xfe, 0x8c, 0xbe, 0x7a, 0xa1, 0x85, 0xe3, 0xaf, 0x9c, 0x91, 0x1b, 0xb6, 0xee, 0x90, 0x23, 0x9a, 0x49, 0x87, 0x10, - 0xb1, 0x66, 0x1b, 0xf6, 0x96, 0x54, 0xce, 0x9d, 0x43, 0x76, 0xfe, 0x08, 0x55, 0x7a, 0xad, 0xc7, 0xb7, 0x13, 0xa5, - 0xbb, 0x3d, 0xdd, 0x4d, 0xbe, 0x65, 0x13, 0x11, 0x83, 0x01, 0x6d, 0x10, 0xce, 0xc8, 0x3a, 0x44, 0x2a, 0x1d, 0x20, - 0x04, 0x8e, 0x09, 0x68, 0xfa, 0xf7, 0xaf, 0x49, 0x14, 0x70, 0xa4, 0x8d, 0x90, 0xb5, 0xec, 0x78, 0xac, 0x40, 0xa3, - 0xdc, 0xfc, 0xe1, 0x15, 0xea, 0x34, 0x07, 0xe6, 0xe9, 0x12, 0xf6, 0x1c, 0x3c, 0xd2, 0x8b, 0xd3, 0x23, 0xfd, 0xbf, - 0xa3, 0x89, 0x1a, 0xff, 0xfb, 0x9a, 0x28, 0xa5, 0x45, 0x72, 0x54, 0x4b, 0xdf, 0xa4, 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, 0x7e, 0x26, 0x09, 0x91, 0xe1, 0xd2, 0x80, 0x1f, 0x55, 0x70, 0x88, 0xd3, 0x6a, - 0x93, 0x85, 0x7b, 0x54, 0xa2, 0xde, 0x89, 0x55, 0x9a, 0xbf, 0xa8, 0xff, 0x25, 0xca, 0x02, 0xa6, 0xf6, 0xaa, 0x4c, - 0xe3, 0x80, 0x2c, 0xfc, 0x59, 0x58, 0xe2, 0xe4, 0xc6, 0x36, 0xfe, 0x2c, 0xc7, 0xd3, 0x7e, 0xd5, 0x99, 0x79, 0x20, - 0x81, 0x1a, 0x88, 0x3f, 0x72, 0x2e, 0x2b, 0x8b, 0x07, 0x84, 0x6e, 0xfe, 0xb1, 0x2c, 0x8b, 0xd2, 0xeb, 0x7d, 0x4a, - 0xd2, 0xea, 0x62, 0x2d, 0xea, 0xa4, 0x88, 0x15, 0x94, 0x4d, 0x0a, 0x30, 0xfa, 0xb0, 0xf2, 0x44, 0x1c, 0x5c, 0x20, - 0x50, 0xc3, 0x45, 0x9d, 0x84, 0x00, 0x34, 0xac, 0x10, 0xf6, 0x2f, 0xa0, 0x85, 0x17, 0x61, 0x1c, 0x6e, 0x00, 0x26, - 0x27, 0xad, 0x2e, 0x36, 0x65, 0x71, 0x9f, 0xc6, 0x22, 0x1e, 0xf5, 0x14, 0x25, 0xcb, 0xc7, 0xca, 0x95, 0x73, 0xfd, - 0xc3, 0x1f, 0x14, 0xc0, 0x6e, 0xc0, 0x6c, 0x5b, 0x60, 0x07, 0x00, 0x09, 0x0a, 0x64, 0x0b, 0x75, 0x1a, 0x5d, 0xa8, - 0xa5, 0x02, 0xef, 0xb9, 0x1e, 0xe0, 0x1f, 0x2b, 0xc0, 0x32, 0xae, 0x0b, 0x19, 0x30, 0x82, 0x00, 0x46, 0xe0, 0xa0, - 0x04, 0x0c, 0x9d, 0x61, 0x6d, 0xf1, 0xb8, 0x43, 0x73, 0xa5, 0xdb, 0x92, 0x9b, 0x46, 0x39, 0x5b, 0x89, 0x00, 0xfa, - 0xea, 0xa6, 0xc4, 0xe9, 0x72, 0xd9, 0x4a, 0xc2, 0xbe, 0x7d, 0xdf, 0x4e, 0x15, 0x79, 0x7c, 0x92, 0x86, 0xbc, 0x02, - 0x4f, 0x32, 0x8e, 0x24, 0x51, 0x22, 0xf8, 0x58, 0x35, 0x66, 0x1c, 0x5e, 0xb4, 0x29, 0xa7, 0x0e, 0x66, 0xbd, 0x00, - 0x9c, 0x27, 0x68, 0xcb, 0x00, 0x63, 0x01, 0x83, 0x73, 0x21, 0x96, 0x3c, 0x45, 0xf0, 0x4b, 0x27, 0x52, 0x18, 0x77, - 0x39, 0x0c, 0xf3, 0xa0, 0xe8, 0x5d, 0x52, 0x7f, 0xf4, 0xfb, 0xa8, 0x4d, 0x06, 0x43, 0x50, 0x09, 0xa0, 0xb2, 0x6e, - 0x90, 0x18, 0x58, 0x95, 0x16, 0x12, 0x97, 0x10, 0x2f, 0xf3, 0xd5, 0xb4, 0x8e, 0x82, 0xf7, 0xf5, 0x84, 0x10, 0x4e, - 0x30, 0x3e, 0xc4, 0x0d, 0x10, 0x30, 0x58, 0xc5, 0x05, 0x06, 0xc9, 0x73, 0x89, 0xee, 0x8f, 0xe7, 0x3b, 0x06, 0xb8, - 0x72, 0xde, 0x53, 0xed, 0xea, 0x81, 0xbd, 0x5c, 0xa5, 0x4b, 0x46, 0x08, 0x2b, 0xfe, 0x2f, 0x22, 0xef, 0xdb, 0x61, - 0x02, 0x6a, 0x1b, 0xf9, 0x63, 0x90, 0x98, 0xcb, 0x44, 0x11, 0xc4, 0xa3, 0xac, 0x60, 0x49, 0x1a, 0x6c, 0x47, 0x49, - 0x0a, 0x1a, 0x4d, 0x8c, 0x21, 0x53, 0xa1, 0x1d, 0x92, 0x46, 0xb3, 0x31, 0xd9, 0xc7, 0x90, 0xd7, 0x70, 0xb1, 0x58, - 0xe0, 0x7d, 0x3f, 0x0b, 0xd5, 0xc1, 0xb6, 0x34, 0x87, 0x80, 0x93, 0x04, 0x7b, 0xea, 0x8a, 0x94, 0x84, 0xd9, 0xe8, - 0x53, 0xc8, 0xb9, 0x01, 0x1d, 0x27, 0x8d, 0xa1, 0xfa, 0xc0, 0x24, 0xbc, 0x89, 0xd0, 0x49, 0x59, 0x21, 0x2c, 0xe0, - 0xbe, 0x91, 0xd1, 0x68, 0x25, 0x0d, 0x02, 0x6f, 0x33, 0x6c, 0x05, 0x36, 0xa1, 0xe1, 0x2f, 0x32, 0x0f, 0xd3, 0x6a, - 0x56, 0x82, 0x39, 0xdf, 0x40, 0x25, 0xc6, 0x93, 0xe5, 0x0d, 0xdf, 0xba, 0x58, 0x89, 0xc9, 0x6c, 0x39, 0x9f, 0x6c, - 0x24, 0xd5, 0x1c, 0x08, 0x19, 0x19, 0x5b, 0xc2, 0xfe, 0x61, 0x60, 0x28, 0x1d, 0xd8, 0xd1, 0x54, 0xd3, 0x26, 0x01, - 0x26, 0xd3, 0x25, 0xe7, 0xc3, 0x6b, 0x44, 0x93, 0xd5, 0xa9, 0x7b, 0x99, 0xaa, 0x76, 0x70, 0x4d, 0xce, 0xe4, 0xf4, - 0x48, 0x3d, 0xd5, 0xba, 0x97, 0x6a, 0xb4, 0x1b, 0xe6, 0xa3, 0x9d, 0x1f, 0x80, 0x5b, 0xa7, 0xb0, 0xd3, 0xf7, 0xc3, - 0x7c, 0xb4, 0xf7, 0x35, 0xec, 0x2e, 0x29, 0x04, 0xaa, 0x3f, 0xcb, 0x9a, 0xcc, 0xc5, 0x9b, 0xe2, 0xc1, 0x2b, 0xd8, - 0x33, 0x7f, 0xa0, 0x7f, 0x95, 0xec, 0x99, 0x6f, 0x33, 0xb9, 0xfe, 0x99, 0x76, 0x8d, 0xc6, 0x4c, 0xc7, 0x6b, 0xe7, - 0x60, 0x85, 0x06, 0xc8, 0x2f, 0xd8, 0xd1, 0xde, 0xe4, 0x20, 0x10, 0xa0, 0x7b, 0x09, 0x8e, 0xa2, 0x80, 0xa8, 0x69, - 0x55, 0x79, 0x74, 0xba, 0xf7, 0x0f, 0xf8, 0x46, 0x09, 0xd8, 0xe4, 0xa9, 0x75, 0x6f, 0x19, 0xfb, 0xc7, 0x23, 0x84, - 0xd0, 0xcb, 0xe9, 0x37, 0xda, 0xb1, 0x7a, 0xb4, 0x67, 0x12, 0xfc, 0x1c, 0x31, 0xe9, 0x15, 0x8c, 0x61, 0xe8, 0xc2, - 0x2a, 0x46, 0xf2, 0x0c, 0xc8, 0x1a, 0xbf, 0x41, 0x74, 0x01, 0x8b, 0x5e, 0xef, 0xd5, 0x09, 0x0d, 0x22, 0xa0, 0xd2, - 0x6b, 0xfe, 0x52, 0xe4, 0x73, 0x55, 0x88, 0xde, 0x07, 0x6b, 0xe7, 0xcd, 0x8c, 0x64, 0x99, 0x34, 0x52, 0xed, 0x56, - 0x16, 0x9b, 0xca, 0x9b, 0x9d, 0x91, 0x2e, 0xe6, 0x18, 0x2a, 0x83, 0xc7, 0x01, 0x28, 0x3d, 0xff, 0x12, 0x7a, 0x25, - 0x43, 0xa6, 0x59, 0xa2, 0x99, 0xdd, 0x37, 0xfe, 0x64, 0x9d, 0x7a, 0x31, 0x22, 0x66, 0x03, 0x5b, 0x88, 0xdb, 0xa2, - 0xd2, 0x6d, 0x51, 0x28, 0x5b, 0x14, 0xe9, 0x43, 0xed, 0x42, 0x77, 0x66, 0xe1, 0xb3, 0xdc, 0xb4, 0xef, 0x4d, 0x66, - 0xc6, 0x06, 0x68, 0xbb, 0x08, 0xdf, 0x40, 0x07, 0x2a, 0x84, 0xfc, 0x47, 0x44, 0x44, 0x22, 0x60, 0x97, 0x73, 0x77, - 0x62, 0xd3, 0x21, 0x99, 0x87, 0x98, 0x15, 0x6a, 0x94, 0x97, 0x3c, 0x39, 0x19, 0x90, 0x9c, 0x50, 0xb7, 0xfb, 0xfd, - 0xcb, 0xa5, 0x0b, 0x6a, 0xbf, 0xa1, 0xd8, 0x31, 0xba, 0x29, 0xe0, 0x5c, 0xf0, 0x28, 0xef, 0xa5, 0x77, 0x09, 0x68, - 0x8e, 0xed, 0x29, 0xb2, 0x01, 0x9c, 0xde, 0x76, 0x21, 0xc0, 0xf6, 0x59, 0xb3, 0x8d, 0x3f, 0x59, 0xdf, 0x44, 0x53, - 0xaf, 0xe4, 0x33, 0xdd, 0x45, 0x89, 0xdb, 0x45, 0xb1, 0xec, 0xa2, 0x6d, 0x03, 0xc1, 0x8e, 0x6b, 0x3f, 0x00, 0xde, - 0xd0, 0xa8, 0xdf, 0x2f, 0x5b, 0x3d, 0x7b, 0xf6, 0xb5, 0xd3, 0x9e, 0xcd, 0x7c, 0x56, 0x9a, 0x9e, 0xfd, 0x35, 0x75, - 0x7b, 0x56, 0x4e, 0xf6, 0xa2, 0x73, 0xb2, 0x4f, 0x67, 0xf3, 0x40, 0x70, 0xb9, 0x73, 0x5f, 0x56, 0x53, 0x3d, 0xed, - 0x72, 0x3f, 0x68, 0x0d, 0x91, 0xf9, 0xc2, 0xa7, 0xbc, 0x7b, 0x5d, 0xc1, 0x02, 0x96, 0xe0, 0x6e, 0xbd, 0x34, 0xff, - 0x15, 0xbb, 0xbf, 0x17, 0xf4, 0xd2, 0xfc, 0x37, 0xfa, 0x93, 0x02, 0x38, 0x00, 0x8d, 0xa9, 0xdd, 0x02, 0x0f, 0x31, - 0x54, 0x50, 0xb8, 0x9b, 0x95, 0x73, 0xaf, 0x06, 0x38, 0x4c, 0xd2, 0x37, 0xb4, 0x7a, 0xa5, 0xc5, 0xae, 0x97, 0xc9, - 0x5e, 0x01, 0x1e, 0xaa, 0x90, 0x87, 0xc7, 0x63, 0xd4, 0x31, 0xec, 0xa0, 0x8e, 0x80, 0x61, 0x0f, 0xa1, 0xb1, 0x05, - 0x9e, 0x8f, 0x9f, 0x32, 0x7e, 0x10, 0xa0, 0x36, 0x42, 0x78, 0xbc, 0x5a, 0x94, 0x21, 0xb6, 0xec, 0x0d, 0x52, 0x49, - 0xfd, 0x2c, 0x10, 0x65, 0xb4, 0x0a, 0x68, 0xab, 0x3d, 0x65, 0x69, 0xbc, 0x85, 0x50, 0xb1, 0xd4, 0xc7, 0x10, 0x1a, - 0x38, 0xfc, 0x8e, 0x47, 0x90, 0xe0, 0x4b, 0xae, 0xc9, 0xe6, 0xde, 0xe4, 0xf7, 0xb4, 0xcf, 0x1f, 0x8f, 0x97, 0xd7, - 0x08, 0x4a, 0x97, 0xc2, 0x47, 0x2a, 0x11, 0xd5, 0x53, 0xdc, 0x94, 0x90, 0xcd, 0x92, 0x95, 0x7e, 0xf0, 0xab, 0xfa, - 0x05, 0x00, 0xb2, 0x10, 0x68, 0x13, 0x99, 0xfd, 0xe9, 0x42, 0x45, 0x17, 0x00, 0x87, 0xf8, 0xe3, 0x27, 0x88, 0xbe, - 0xa1, 0x65, 0x5a, 0x3e, 0x4e, 0x78, 0x08, 0x5a, 0x5b, 0xd2, 0x49, 0xc4, 0x4a, 0x81, 0x0d, 0x91, 0xf0, 0xfd, 0xfe, - 0x65, 0x2c, 0xe9, 0x40, 0xa3, 0x56, 0xf7, 0xc6, 0xad, 0xee, 0x95, 0xaf, 0xeb, 0x4e, 0x6e, 0x7c, 0x50, 0xb4, 0xcf, - 0xe6, 0x8d, 0xca, 0xf7, 0x6d, 0x9d, 0xb3, 0x3f, 0xdf, 0x3b, 0x72, 0x4e, 0x7c, 0x7b, 0x0f, 0xa1, 0xe8, 0xa1, 0x29, - 0xb2, 0x2c, 0x09, 0x03, 0x5a, 0x6b, 0xd7, 0x9e, 0x65, 0x74, 0xf0, 0xda, 0x37, 0x84, 0x88, 0x3c, 0xc5, 0x27, 0x21, - 0xb7, 0x38, 0x3e, 0x28, 0xd0, 0x3f, 0x33, 0xfe, 0xcc, 0x89, 0x1f, 0xb6, 0xfa, 0x05, 0x70, 0x6e, 0xba, 0xf7, 0xee, - 0xc4, 0xac, 0xc7, 0x50, 0xca, 0xc6, 0xff, 0xfd, 0x3e, 0x91, 0x05, 0x3a, 0x1d, 0xd1, 0x30, 0x10, 0xdc, 0x45, 0xf5, - 0x7f, 0xaf, 0x78, 0xdd, 0xb3, 0x56, 0xe7, 0xcb, 0x4f, 0x9d, 0x9f, 0xf4, 0xea, 0x65, 0xdc, 0x03, 0x72, 0x74, 0x80, - 0x70, 0x5e, 0xf7, 0x1b, 0xb6, 0xff, 0xe6, 0x97, 0xf7, 0x27, 0x2f, 0x03, 0x9b, 0x14, 0x89, 0x6d, 0x25, 0x9f, 0xf5, - 0x40, 0xe1, 0xd7, 0x63, 0xbd, 0xba, 0xd8, 0xf4, 0x58, 0x0f, 0xb5, 0x80, 0xe8, 0x61, 0x01, 0xea, 0xbf, 0x9e, 0x7d, - 0x1a, 0x0a, 0x07, 0xd9, 0x38, 0x55, 0xa0, 0xc8, 0x82, 0x3f, 0x17, 0xa3, 0x4d, 0x41, 0x80, 0xc8, 0x96, 0x90, 0x96, - 0x9f, 0xcd, 0x1e, 0x97, 0x5a, 0x92, 0xc1, 0x37, 0x01, 0x99, 0x1d, 0x58, 0x39, 0x41, 0xe9, 0xb8, 0x33, 0xe0, 0xca, - 0x16, 0x8f, 0x76, 0xfb, 0xd3, 0x20, 0x3b, 0x6b, 0x4e, 0x1a, 0xed, 0xc3, 0x3e, 0x05, 0x4e, 0x1a, 0x10, 0x7b, 0x44, - 0xa0, 0xef, 0xb6, 0xb9, 0xf4, 0xd1, 0xe1, 0x9c, 0x17, 0xf2, 0xcf, 0xa9, 0xc4, 0xe0, 0x1e, 0x4a, 0xac, 0x81, 0x40, - 0xe5, 0x19, 0xaa, 0x1c, 0x36, 0xc8, 0xf1, 0xcf, 0x8e, 0x64, 0x26, 0x31, 0x59, 0xe4, 0x6e, 0xcd, 0x54, 0xf8, 0x81, - 0x00, 0xfe, 0x73, 0x0e, 0x5c, 0x60, 0xb3, 0xb9, 0xaf, 0xa6, 0xb8, 0xb8, 0x01, 0x7f, 0x4c, 0xe1, 0xe7, 0x3c, 0x85, - 0x9d, 0xf6, 0xb0, 0x29, 0xaa, 0x14, 0x75, 0x1b, 0x85, 0x45, 0x25, 0x0b, 0xa6, 0x35, 0xa4, 0x89, 0x0e, 0xa3, 0x3f, - 0xc8, 0x19, 0x28, 0x08, 0xf9, 0x75, 0xd3, 0x00, 0x23, 0x95, 0x5c, 0x1e, 0x54, 0x49, 0xe0, 0x05, 0xd8, 0x05, 0x39, - 0xdb, 0x14, 0x10, 0x64, 0x9b, 0x14, 0x65, 0xfa, 0xa5, 0xc8, 0xeb, 0x30, 0x0b, 0xf2, 0x51, 0x5a, 0xfd, 0x55, 0xff, - 0x04, 0xe6, 0x6d, 0x2a, 0x46, 0xb5, 0x8a, 0xc9, 0x6f, 0xf4, 0xfb, 0xc5, 0xa0, 0xf5, 0x21, 0x83, 0x8f, 0x5e, 0x9b, - 0x06, 0x7f, 0x74, 0x1a, 0xec, 0x30, 0xd1, 0x08, 0x80, 0x64, 0x4e, 0x2d, 0x79, 0x28, 0xfa, 0x23, 0xa8, 0xb0, 0x46, - 0xb9, 0x53, 0x30, 0x58, 0xff, 0xf1, 0x68, 0x07, 0xa6, 0x5e, 0x1c, 0x6d, 0xc9, 0x0e, 0x9a, 0xfb, 0x06, 0xb8, 0x5f, - 0x23, 0x5b, 0xcc, 0x2a, 0x80, 0x66, 0xaf, 0x11, 0x19, 0x9f, 0xbc, 0x00, 0xc6, 0x6c, 0x93, 0x85, 0x91, 0x88, 0x83, - 0xb1, 0x6a, 0xcc, 0x98, 0x81, 0x81, 0x0b, 0x74, 0x2d, 0x93, 0x92, 0x34, 0xa4, 0x83, 0x01, 0x2b, 0x65, 0x0b, 0x07, - 0xbc, 0x68, 0x4e, 0xdb, 0xf1, 0xba, 0x45, 0xe3, 0x81, 0xed, 0x62, 0x87, 0xfb, 0x1f, 0x8a, 0xdd, 0xdb, 0x70, 0x47, - 0x7a, 0x85, 0x8a, 0x25, 0xf4, 0xf3, 0xaf, 0xb2, 0xcf, 0x1a, 0x4e, 0x4e, 0x85, 0x66, 0x68, 0x29, 0x12, 0x4a, 0xf1, - 0x4e, 0x4f, 0x0a, 0x8c, 0x65, 0x2c, 0xfc, 0x03, 0x70, 0x4e, 0x17, 0x8a, 0xc8, 0x1d, 0x38, 0x8e, 0x6f, 0xa1, 0x82, - 0x51, 0xc3, 0xc1, 0xcb, 0x18, 0xb6, 0x45, 0x31, 0x0b, 0x09, 0xa7, 0x10, 0x2e, 0x56, 0x59, 0xbf, 0x2f, 0x7f, 0x51, - 0x17, 0x5d, 0x65, 0xb2, 0xee, 0x93, 0x70, 0x64, 0xc6, 0x72, 0xea, 0x85, 0xe4, 0x79, 0xcf, 0x93, 0x69, 0xf2, 0xb4, - 0x0a, 0x22, 0x80, 0x7c, 0x0e, 0xef, 0xc3, 0x34, 0x03, 0xab, 0x34, 0x29, 0x3f, 0x42, 0xe9, 0x8b, 0xcf, 0x73, 0x3f, - 0xd0, 0xd9, 0x2b, 0x93, 0x0c, 0x6f, 0xe6, 0xad, 0x37, 0xa9, 0x75, 0x5d, 0x3c, 0xe0, 0xef, 0x9c, 0xc1, 0xc6, 0xb9, - 0xce, 0x04, 0x07, 0x5e, 0x24, 0xb5, 0x5e, 0x33, 0xfe, 0x3c, 0xc3, 0x75, 0xa9, 0xda, 0xe8, 0xa3, 0x10, 0x5d, 0x41, - 0xa6, 0x02, 0x14, 0x8a, 0xb4, 0x7f, 0x50, 0x6a, 0x6e, 0x52, 0x69, 0x23, 0x01, 0x74, 0x0f, 0x93, 0x06, 0x5b, 0x0c, - 0x65, 0x2c, 0x4d, 0xa2, 0xdc, 0x69, 0x10, 0x57, 0xf6, 0xe7, 0x5c, 0xe2, 0xd0, 0xb2, 0x48, 0xfe, 0xbd, 0xef, 0xe9, - 0x2b, 0xa4, 0xee, 0x64, 0x81, 0xcc, 0x18, 0x2f, 0xf2, 0xf8, 0x13, 0x10, 0x66, 0x83, 0x36, 0x2a, 0x0a, 0x21, 0x64, - 0x83, 0x18, 0x34, 0x5e, 0xe4, 0xf1, 0x0f, 0x8a, 0xc6, 0x43, 0x3e, 0x8a, 0x7c, 0xf5, 0x57, 0xa9, 0xff, 0x0a, 0x7d, - 0x66, 0x82, 0x47, 0xa8, 0x26, 0xfa, 0x77, 0xcf, 0x67, 0xf7, 0xa0, 0x36, 0x8c, 0xc2, 0xcc, 0x94, 0x9f, 0xfb, 0xa6, - 0x38, 0x7b, 0xfd, 0x15, 0x5d, 0x65, 0x5b, 0xf7, 0xa3, 0x8f, 0x27, 0x04, 0xd6, 0xc6, 0xe8, 0x8a, 0x1b, 0x03, 0xc8, - 0x61, 0xf2, 0x7e, 0x45, 0x69, 0x15, 0xa4, 0x41, 0xe8, 0xa0, 0x21, 0xe8, 0x95, 0x44, 0x1f, 0x48, 0x2c, 0x62, 0x0c, - 0x2f, 0xc4, 0x33, 0x52, 0x93, 0x89, 0x86, 0x78, 0x45, 0xec, 0x87, 0x68, 0xc9, 0xa9, 0x89, 0x6e, 0x84, 0x29, 0x06, - 0x12, 0x3b, 0x83, 0xe4, 0x24, 0xa9, 0x95, 0x5f, 0x3c, 0x93, 0x84, 0x25, 0x76, 0x1e, 0x62, 0x30, 0xa9, 0xa5, 0x3b, - 0xbd, 0xa9, 0xd2, 0x97, 0x13, 0x2d, 0x07, 0xed, 0x03, 0xb0, 0x4b, 0x49, 0xef, 0x9f, 0x14, 0x8a, 0xf8, 0x10, 0xc6, - 0x31, 0x84, 0x6f, 0x11, 0xd5, 0x15, 0x38, 0xd7, 0x0a, 0x34, 0x56, 0x03, 0x0f, 0xcd, 0x2c, 0x9f, 0x0f, 0x39, 0xfd, - 0x54, 0x5a, 0xfe, 0x18, 0xd1, 0xd8, 0x68, 0xdd, 0x1c, 0x8f, 0x07, 0x5a, 0xf5, 0xd2, 0x39, 0xe8, 0xba, 0x99, 0xc4, - 0xc4, 0x0d, 0xa4, 0xeb, 0x47, 0xbf, 0x99, 0xb0, 0x17, 0x51, 0x21, 0x97, 0x42, 0x50, 0xd0, 0xea, 0x40, 0xe0, 0x50, - 0x78, 0x8b, 0x32, 0x5f, 0xc5, 0xb4, 0x81, 0x30, 0xf8, 0xfc, 0x40, 0x7e, 0xbe, 0x29, 0x48, 0xc5, 0x8e, 0x75, 0xed, - 0xf7, 0xb7, 0xa5, 0x07, 0x78, 0x72, 0x26, 0xc9, 0xd3, 0x66, 0x08, 0x2b, 0x02, 0x68, 0xcc, 0x6a, 0xb2, 0x38, 0xe1, - 0xca, 0x1c, 0x7e, 0xcc, 0xbd, 0x92, 0xa5, 0x4c, 0x9d, 0xa7, 0x7a, 0x01, 0x44, 0x1d, 0x6f, 0xd0, 0x8a, 0xd4, 0xaf, - 0xd0, 0xd9, 0x6b, 0x56, 0x42, 0xc6, 0xc3, 0x4b, 0xce, 0xd3, 0xd1, 0x03, 0x4b, 0x78, 0x84, 0x7f, 0x25, 0x13, 0x7d, - 0xf8, 0x3d, 0x70, 0xb8, 0x19, 0x27, 0x3c, 0x72, 0x9b, 0x7d, 0xa8, 0xc2, 0x35, 0xdc, 0x4c, 0x0b, 0x40, 0x72, 0x0b, - 0x92, 0x26, 0xa0, 0x84, 0x44, 0x26, 0x64, 0xd6, 0x94, 0xfc, 0xdc, 0xd2, 0x36, 0x58, 0xc3, 0xa4, 0xf3, 0x80, 0x17, - 0xad, 0x3e, 0x5a, 0x4d, 0xb4, 0xcb, 0xac, 0x9a, 0x0f, 0x71, 0x86, 0x6a, 0x8e, 0xbb, 0x0b, 0xf8, 0x39, 0xe0, 0x39, - 0xcb, 0x9b, 0x74, 0xb4, 0x1f, 0x70, 0xe1, 0xc9, 0x75, 0x9e, 0x8e, 0x76, 0xf8, 0x4b, 0xee, 0x0f, 0x00, 0x1d, 0x4c, - 0x5d, 0x02, 0x7f, 0xaa, 0xb6, 0x9a, 0x4a, 0xfd, 0xd2, 0xda, 0xaf, 0xeb, 0xce, 0x6a, 0xc1, 0x19, 0xa2, 0x2f, 0x43, - 0x07, 0x64, 0xc8, 0x19, 0x33, 0xe0, 0xcf, 0x19, 0x4b, 0xfe, 0x9c, 0xb1, 0xe2, 0xcf, 0x19, 0x37, 0x46, 0x06, 0x50, - 0x82, 0x7b, 0xc9, 0x9f, 0x1f, 0x10, 0x33, 0xc4, 0x6a, 0x50, 0x09, 0xac, 0x2c, 0xe5, 0xdc, 0x47, 0x4e, 0x31, 0xe5, - 0x94, 0xe1, 0xa5, 0xd3, 0x99, 0x3b, 0x90, 0xf3, 0x60, 0xe6, 0x0e, 0x93, 0xb3, 0x3e, 0xc5, 0xa9, 0x34, 0x26, 0x45, + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xcc, 0xbd, 0xeb, 0x7a, 0x1b, 0xb7, 0xb2, 0x20, 0xfa, + 0xfb, 0xcc, 0x53, 0x48, 0xbd, 0x1d, 0xa5, 0x21, 0x82, 0x2d, 0x92, 0xba, 0x58, 0x6e, 0x0a, 0xe2, 0xf8, 0x1a, 0x3b, + 0x71, 0x6c, 0xc7, 0x72, 0xec, 0xd8, 0x0c, 0xb7, 0x02, 0x36, 0x41, 0x12, 0x71, 0x13, 0x60, 0x1a, 0xa0, 0x25, 0x99, + 0xe4, 0xbb, 0x9f, 0xaf, 0x70, 0xe9, 0x46, 0x93, 0xb4, 0xd7, 0x5a, 0x73, 0x66, 0xce, 0x37, 0x3b, 0x7b, 0x59, 0x6c, + 0xdc, 0x51, 0x28, 0x14, 0xaa, 0x0a, 0x55, 0x85, 0x8b, 0xfd, 0x91, 0xcc, 0xf4, 0xdd, 0x9c, 0xed, 0x4d, 0xf5, 0x2c, + 0xbf, 0xbc, 0x70, 0xff, 0x32, 0x3a, 0xba, 0xbc, 0xc8, 0xb9, 0xf8, 0xbc, 0x57, 0xb0, 0x9c, 0xf0, 0x4c, 0x8a, 0xbd, + 0x69, 0xc1, 0xc6, 0x64, 0x44, 0x35, 0x4d, 0xf9, 0x8c, 0x4e, 0xd8, 0xde, 0xd1, 0xe5, 0xc5, 0x8c, 0x69, 0xba, 0x97, + 0x4d, 0x69, 0xa1, 0x98, 0x26, 0xbf, 0xbf, 0x7b, 0xd6, 0x3c, 0xbf, 0xbc, 0x50, 0x59, 0xc1, 0xe7, 0x7a, 0x0f, 0x9a, + 0x24, 0x33, 0x39, 0x5a, 0xe4, 0xec, 0xf2, 0xe8, 0xe8, 0xe6, 0xe6, 0x26, 0xf9, 0x5b, 0xfd, 0x8f, 0x2f, 0xb4, 0xd8, + 0xfb, 0xa5, 0x20, 0xaf, 0x87, 0x7f, 0xb3, 0x4c, 0x27, 0x23, 0x36, 0xe6, 0x82, 0xbd, 0x29, 0xe4, 0x9c, 0x15, 0xfa, + 0xae, 0x0b, 0x99, 0x3f, 0x15, 0x24, 0xe6, 0x58, 0x63, 0x86, 0xc8, 0xa5, 0xde, 0xe3, 0x62, 0x8f, 0xf7, 0x7e, 0x29, + 0x4c, 0xca, 0x92, 0x89, 0xc5, 0x8c, 0x15, 0x74, 0x98, 0xb3, 0x74, 0xbf, 0x85, 0x33, 0x29, 0xc6, 0x7c, 0xb2, 0x28, + 0xbf, 0x6f, 0x0a, 0xae, 0xfd, 0xef, 0x2f, 0x34, 0x5f, 0xb0, 0x94, 0xad, 0x51, 0xca, 0xfb, 0x7a, 0x40, 0x98, 0x69, + 0xf9, 0x73, 0xd5, 0x70, 0xfc, 0x93, 0x69, 0xf2, 0x6e, 0xce, 0xe4, 0x78, 0x4f, 0xef, 0x93, 0x48, 0xdd, 0xcd, 0x86, + 0x32, 0x8f, 0x7a, 0xba, 0x11, 0x45, 0x29, 0x94, 0xc1, 0x0c, 0x75, 0x33, 0x29, 0x94, 0xde, 0x13, 0x9c, 0xdc, 0x70, + 0x31, 0x92, 0x37, 0xf8, 0x46, 0x10, 0xc1, 0x93, 0xab, 0x29, 0x1d, 0xc9, 0x9b, 0xb7, 0x52, 0xea, 0x83, 0x83, 0xd8, + 0x7d, 0xdf, 0x3d, 0xbe, 0xba, 0x22, 0x84, 0x7c, 0x91, 0x7c, 0xb4, 0xd7, 0x5a, 0xad, 0x82, 0xd4, 0x44, 0x50, 0xcd, + 0xbf, 0x30, 0x5b, 0x09, 0x1d, 0x1c, 0x44, 0x74, 0x24, 0xe7, 0x9a, 0x8d, 0xae, 0xf4, 0x5d, 0xce, 0xae, 0xa6, 0x8c, + 0x69, 0x15, 0x71, 0xb1, 0xf7, 0x44, 0x66, 0x8b, 0x19, 0x13, 0x3a, 0x99, 0x17, 0x52, 0x4b, 0x18, 0xd8, 0xc1, 0x41, + 0x54, 0xb0, 0x79, 0x4e, 0x33, 0x06, 0xf9, 0x8f, 0xaf, 0xae, 0xaa, 0x1a, 0x55, 0x21, 0xfc, 0x59, 0x90, 0x2b, 0x33, + 0xf4, 0x18, 0xe1, 0x0f, 0x82, 0x08, 0x76, 0xb3, 0xf7, 0x81, 0xd1, 0xcf, 0xbf, 0xd2, 0x79, 0x37, 0xcb, 0xa9, 0x52, + 0x7b, 0xcf, 0xe4, 0xd2, 0x4c, 0xa3, 0x58, 0x64, 0x5a, 0x16, 0xb1, 0xc6, 0x0c, 0x0b, 0xb4, 0xe4, 0xe3, 0x58, 0x4f, + 0xb9, 0x4a, 0xae, 0xef, 0x65, 0x4a, 0xbd, 0x65, 0x6a, 0x91, 0xeb, 0x7b, 0x64, 0xbf, 0x85, 0xc5, 0x3e, 0x21, 0x9f, + 0x05, 0xd2, 0xd3, 0x42, 0xde, 0xec, 0x3d, 0x2d, 0x0a, 0x59, 0xc4, 0xd1, 0xe3, 0xab, 0x2b, 0x5b, 0x62, 0x8f, 0xab, + 0x3d, 0x21, 0xf5, 0x5e, 0xd9, 0x1e, 0x40, 0x3b, 0xd9, 0xfb, 0x5d, 0xb1, 0xbd, 0xbf, 0x16, 0x42, 0xd1, 0x31, 0x7b, + 0x7c, 0x75, 0xf5, 0xd7, 0x9e, 0x2c, 0xf6, 0xfe, 0xca, 0x94, 0xfa, 0x6b, 0x8f, 0x0b, 0xa5, 0x19, 0x1d, 0x25, 0x11, + 0xea, 0x9a, 0xce, 0x32, 0xa5, 0xde, 0xb1, 0x5b, 0x4d, 0x34, 0x36, 0x9f, 0x9a, 0xb0, 0xf5, 0x84, 0xe9, 0x3d, 0x55, + 0xce, 0x2b, 0x46, 0xcb, 0x9c, 0xe9, 0x3d, 0x4d, 0x4c, 0xbe, 0x74, 0xf0, 0x67, 0xf6, 0x53, 0x77, 0xf9, 0x38, 0xbe, + 0x11, 0x07, 0x07, 0xba, 0x04, 0x34, 0x5a, 0xba, 0x15, 0x22, 0x6c, 0xdf, 0xa7, 0x1d, 0x1c, 0xb0, 0x24, 0x67, 0x62, + 0xa2, 0xa7, 0x84, 0x90, 0x76, 0x57, 0x1c, 0x1c, 0xc4, 0x9a, 0x7c, 0x10, 0xc9, 0x84, 0xe9, 0x98, 0x21, 0x84, 0xab, + 0xda, 0x07, 0x07, 0xb1, 0x05, 0x82, 0x24, 0xda, 0x00, 0xae, 0x06, 0x63, 0x94, 0x38, 0xe8, 0x5f, 0xdd, 0x89, 0x2c, + 0x0e, 0xc7, 0x8f, 0xb0, 0x38, 0x38, 0xf8, 0x20, 0x12, 0x05, 0x2d, 0x62, 0x8d, 0xd0, 0xba, 0x60, 0x7a, 0x51, 0x88, + 0x3d, 0xbd, 0xd6, 0xf2, 0x4a, 0x17, 0x5c, 0x4c, 0x62, 0xb4, 0xf4, 0x69, 0x41, 0xc5, 0xf5, 0xda, 0x0e, 0xf7, 0xb7, + 0x82, 0x70, 0x72, 0x09, 0x3d, 0x3e, 0x93, 0xb1, 0xc3, 0x41, 0x4e, 0x48, 0xa4, 0x4c, 0xdd, 0xa8, 0xc7, 0x53, 0xde, + 0x88, 0x22, 0x6c, 0x47, 0x89, 0x3f, 0x0b, 0x84, 0xb9, 0x06, 0xd4, 0x4d, 0x92, 0x44, 0x23, 0x72, 0xb9, 0xf4, 0x60, + 0xe1, 0xc1, 0x44, 0x7b, 0xbc, 0xdf, 0x1a, 0xa4, 0x3a, 0x29, 0xd8, 0x68, 0x91, 0xb1, 0x38, 0x16, 0x58, 0x61, 0x89, + 0xc8, 0xa5, 0x68, 0xc4, 0x05, 0xb9, 0x84, 0xf5, 0x2e, 0xea, 0x8b, 0x4d, 0xc8, 0x7e, 0x0b, 0xb9, 0x41, 0x16, 0x7e, + 0x84, 0x00, 0x62, 0x37, 0xa0, 0x82, 0x90, 0x48, 0x2c, 0x66, 0x43, 0x56, 0x44, 0x65, 0xb1, 0x6e, 0x0d, 0x2f, 0x16, + 0x8a, 0xed, 0x65, 0x4a, 0xed, 0x8d, 0x17, 0x22, 0xd3, 0x5c, 0x8a, 0xbd, 0xa8, 0x51, 0x34, 0x22, 0x8b, 0x0f, 0x25, + 0x3a, 0x44, 0x68, 0x8d, 0x62, 0x85, 0x1a, 0xbc, 0x2f, 0x1b, 0xed, 0x01, 0x86, 0x51, 0xa2, 0xae, 0x6b, 0xcf, 0x41, + 0x80, 0x61, 0x0e, 0x93, 0x5c, 0xe3, 0x4f, 0x76, 0xe7, 0xc3, 0x14, 0x6f, 0x44, 0x8f, 0x27, 0xdb, 0x3b, 0x85, 0xe8, + 0x64, 0x46, 0xe7, 0x31, 0x23, 0x97, 0xcc, 0x60, 0x17, 0x15, 0x19, 0x8c, 0xb5, 0xb6, 0x70, 0x3d, 0x96, 0xb2, 0xa4, + 0xc2, 0x29, 0x94, 0xea, 0x64, 0x2c, 0x8b, 0xa7, 0x34, 0x9b, 0x42, 0xbd, 0x12, 0x63, 0x46, 0x7e, 0xc3, 0x65, 0x05, + 0xa3, 0x9a, 0x3d, 0xcd, 0x19, 0x7c, 0xc5, 0x91, 0xa9, 0x19, 0x21, 0xac, 0x60, 0xab, 0xe7, 0x5c, 0xbf, 0x92, 0x22, + 0x63, 0x5d, 0x15, 0xe0, 0x97, 0x59, 0xf9, 0x87, 0x5a, 0x17, 0x7c, 0xb8, 0xd0, 0x2c, 0x8e, 0x04, 0x94, 0x88, 0xb0, + 0x42, 0x58, 0x24, 0x9a, 0xdd, 0xea, 0xc7, 0x52, 0x68, 0x26, 0x34, 0x61, 0x1e, 0xaa, 0x98, 0x27, 0x74, 0x3e, 0x67, + 0x62, 0xf4, 0x78, 0xca, 0xf3, 0x51, 0x2c, 0xd0, 0x1a, 0xad, 0xf1, 0xef, 0x82, 0xc0, 0x24, 0xc9, 0x25, 0x4f, 0xe1, + 0x9f, 0x6f, 0x4f, 0x27, 0xd6, 0xe4, 0xd2, 0x6c, 0x0b, 0x46, 0xa2, 0xa8, 0x3b, 0x96, 0x45, 0xec, 0xa6, 0xb0, 0x07, + 0xa4, 0x0b, 0xfa, 0x78, 0xbb, 0xc8, 0x99, 0x42, 0xac, 0x41, 0x44, 0xb9, 0x8e, 0x0e, 0xc2, 0xbf, 0x15, 0x31, 0x83, + 0x05, 0xe0, 0x28, 0xe5, 0x86, 0x04, 0xbe, 0xe4, 0x6e, 0x53, 0x8d, 0x4a, 0xa2, 0xf6, 0x51, 0x90, 0x11, 0x4f, 0x74, + 0xb1, 0x50, 0x9a, 0x8d, 0xde, 0xdd, 0xcd, 0x99, 0xc2, 0x3f, 0x17, 0xe4, 0xa3, 0xe8, 0x7d, 0x14, 0x09, 0x9b, 0xcd, + 0xf5, 0xdd, 0x95, 0xa1, 0xe6, 0x69, 0x14, 0xe1, 0x7f, 0x4c, 0xd1, 0x82, 0xd1, 0x0c, 0x48, 0x9a, 0x03, 0xd9, 0x1b, + 0x99, 0xdf, 0x8d, 0x79, 0x9e, 0x5f, 0x2d, 0xe6, 0x73, 0x59, 0x68, 0xac, 0x05, 0x59, 0x6a, 0x59, 0xc1, 0x07, 0x56, + 0x74, 0xa9, 0x6e, 0xb8, 0xce, 0xa6, 0xb1, 0x46, 0xcb, 0x8c, 0x2a, 0xb6, 0xf7, 0x48, 0xca, 0x9c, 0x51, 0x91, 0x72, + 0xc2, 0x7b, 0x3f, 0x17, 0xa9, 0x58, 0xe4, 0x79, 0x77, 0x58, 0x30, 0xfa, 0xb9, 0x6b, 0xb2, 0xed, 0xe1, 0x90, 0x9a, + 0xdf, 0x0f, 0x8b, 0x82, 0xde, 0x41, 0x41, 0x42, 0xa0, 0x58, 0x8f, 0xa7, 0x3f, 0x5f, 0xbd, 0x7e, 0x95, 0xd8, 0xbd, + 0xc2, 0xc7, 0x77, 0x31, 0x2f, 0xf7, 0x1f, 0x5f, 0xe3, 0x71, 0x21, 0x67, 0x1b, 0x5d, 0x5b, 0xd0, 0xf1, 0xee, 0x37, + 0x86, 0xc0, 0x08, 0xdf, 0xb7, 0x4d, 0x87, 0x23, 0x78, 0x65, 0x30, 0x1f, 0x32, 0x89, 0xeb, 0x17, 0xfe, 0x49, 0x6d, + 0x72, 0xcc, 0xd1, 0xf7, 0x47, 0xab, 0x8b, 0xbb, 0x25, 0x23, 0x66, 0x9c, 0x73, 0x38, 0x18, 0x61, 0x8c, 0x19, 0xd5, + 0xd9, 0x74, 0xc9, 0x4c, 0x63, 0x6b, 0x3f, 0x62, 0xb6, 0x5e, 0xe3, 0xaf, 0xd2, 0x63, 0xbd, 0xde, 0x27, 0x84, 0x1b, + 0x7a, 0x45, 0xf4, 0x6a, 0xc5, 0x09, 0xe1, 0x08, 0xbf, 0xe5, 0x64, 0x49, 0xfd, 0x84, 0xe0, 0x64, 0x83, 0xed, 0x99, + 0x5a, 0x2a, 0x03, 0x27, 0xe0, 0x17, 0x56, 0x68, 0x56, 0xa4, 0x5a, 0xe0, 0x82, 0x8d, 0x73, 0x18, 0xc7, 0x7e, 0x1b, + 0x4f, 0xa9, 0x7a, 0x3c, 0xa5, 0x62, 0xc2, 0x46, 0xe9, 0x57, 0xb9, 0xc6, 0x4c, 0x90, 0x68, 0xcc, 0x05, 0xcd, 0xf9, + 0x57, 0x36, 0x8a, 0xdc, 0xb9, 0xf0, 0x48, 0xef, 0xb1, 0x5b, 0xcd, 0xc4, 0x48, 0xed, 0x3d, 0x7f, 0xf7, 0xeb, 0x4b, + 0xb7, 0x98, 0xb5, 0xb3, 0x02, 0x2d, 0xd5, 0x62, 0xce, 0x8a, 0x18, 0x61, 0x77, 0x56, 0x3c, 0xe5, 0x86, 0x4e, 0xfe, + 0x4a, 0xe7, 0x36, 0x85, 0xab, 0xdf, 0xe7, 0x23, 0xaa, 0xd9, 0x1b, 0x26, 0x46, 0x5c, 0x4c, 0xc8, 0x7e, 0xdb, 0xa6, + 0x4f, 0xa9, 0xcb, 0x18, 0x95, 0x49, 0xd7, 0xf7, 0x9e, 0xe6, 0x66, 0xee, 0xe5, 0xe7, 0x22, 0x46, 0x6b, 0xa5, 0xa9, + 0xe6, 0xd9, 0x1e, 0x1d, 0x8d, 0x5e, 0x08, 0xae, 0xb9, 0x19, 0x61, 0x01, 0x4b, 0x04, 0xb8, 0xca, 0xec, 0xa9, 0xe1, + 0x47, 0x1e, 0x23, 0x1c, 0xc7, 0xee, 0x2c, 0x98, 0x22, 0xb7, 0x66, 0x07, 0x07, 0x15, 0xe5, 0xef, 0xb1, 0xd4, 0x66, + 0x92, 0xfe, 0x00, 0x25, 0xf3, 0x85, 0x82, 0xc5, 0xf6, 0x5d, 0xc0, 0x41, 0x23, 0x87, 0x8a, 0x15, 0x5f, 0xd8, 0xa8, + 0x44, 0x10, 0x15, 0xa3, 0xe5, 0x46, 0x1f, 0x6e, 0x7b, 0x68, 0xd2, 0x1f, 0x74, 0x43, 0x12, 0xce, 0x1c, 0xb2, 0x5b, + 0x4e, 0x85, 0x33, 0x55, 0x12, 0x95, 0x18, 0x0e, 0xd4, 0x92, 0xb0, 0x28, 0xe2, 0xe7, 0x37, 0x8f, 0x05, 0xf0, 0x10, + 0x21, 0xe5, 0xf0, 0x67, 0xee, 0xd3, 0x2f, 0xe6, 0xf0, 0x50, 0x58, 0x20, 0xac, 0xed, 0x48, 0x15, 0x42, 0x6b, 0x84, + 0xb5, 0x1f, 0xae, 0x25, 0x4a, 0x9e, 0x2f, 0x82, 0x53, 0x9b, 0xbc, 0xe5, 0xe6, 0xd8, 0x06, 0xda, 0x46, 0x35, 0x3b, + 0x38, 0x88, 0x59, 0x52, 0x22, 0x06, 0xd9, 0x6f, 0xbb, 0x45, 0x0a, 0xa0, 0xf5, 0x8d, 0x71, 0x43, 0xcf, 0x86, 0xc1, + 0xd9, 0x67, 0x89, 0x90, 0x0f, 0xb3, 0x8c, 0x29, 0x25, 0x8b, 0x83, 0x83, 0x7d, 0x53, 0xbe, 0xe4, 0x2c, 0x60, 0x11, + 0x5f, 0xdf, 0x88, 0x6a, 0x08, 0xa8, 0x3a, 0x6d, 0x3d, 0xdf, 0x44, 0x2a, 0xbe, 0xc9, 0x33, 0x21, 0x69, 0x74, 0x7d, + 0x1d, 0x35, 0x34, 0x76, 0x70, 0x98, 0x30, 0xdf, 0xf5, 0xdd, 0x13, 0x66, 0xd9, 0x42, 0xc3, 0x84, 0x6c, 0x81, 0x66, + 0x27, 0x3f, 0x18, 0xd7, 0x87, 0x84, 0x35, 0x56, 0x68, 0x1d, 0xac, 0xe8, 0xce, 0xa6, 0x0d, 0x7f, 0x63, 0x97, 0x6e, + 0x39, 0x31, 0x3c, 0x45, 0xb0, 0x8e, 0x7d, 0x36, 0x58, 0x63, 0x03, 0x7b, 0x3f, 0x1b, 0x69, 0x06, 0xda, 0xd7, 0x83, + 0xae, 0xcb, 0x27, 0xca, 0x42, 0xae, 0x60, 0xff, 0x2c, 0x98, 0xd2, 0x16, 0x91, 0x63, 0x8d, 0x25, 0x86, 0x33, 0x6a, + 0x93, 0xe9, 0xac, 0xb1, 0xa4, 0xbb, 0xc6, 0xf6, 0x7a, 0x0e, 0x67, 0xa3, 0x02, 0xa4, 0xfe, 0x3e, 0x3e, 0xc1, 0x58, + 0x35, 0x5a, 0xad, 0xde, 0x72, 0xdf, 0x4a, 0xb5, 0x96, 0x25, 0xbf, 0xb6, 0xb1, 0x28, 0x4c, 0x20, 0x77, 0x38, 0xef, + 0xb7, 0xdd, 0xf8, 0xc5, 0x80, 0xec, 0xb7, 0x4a, 0x2c, 0x76, 0x60, 0xb5, 0xe3, 0xb1, 0x50, 0x7c, 0x6d, 0x9b, 0x42, + 0xe6, 0xac, 0xaf, 0xe1, 0x4b, 0x32, 0xdd, 0xc2, 0xd5, 0x29, 0xe9, 0x03, 0xd7, 0x91, 0x4c, 0x07, 0xdf, 0xc2, 0x27, + 0x4f, 0x11, 0x62, 0xbd, 0x9d, 0x57, 0x11, 0x8e, 0x2f, 0x75, 0xc2, 0xb1, 0x31, 0x8d, 0x68, 0x5e, 0x56, 0x89, 0x4a, + 0x34, 0x73, 0x5b, 0xbd, 0xca, 0xc2, 0xc2, 0x0c, 0xa6, 0x9a, 0x52, 0xd0, 0xc4, 0x2b, 0x3a, 0x63, 0x2a, 0x66, 0x08, + 0x7f, 0xab, 0x80, 0xc5, 0x4f, 0x28, 0x32, 0x08, 0xce, 0x50, 0x05, 0x67, 0x28, 0xb0, 0xbb, 0xc0, 0xa4, 0xd5, 0xb7, + 0x9c, 0xc2, 0xac, 0xaf, 0x06, 0x15, 0x6f, 0x17, 0x4c, 0xde, 0x1c, 0xce, 0x0e, 0xc1, 0x3d, 0xfc, 0x6c, 0x9a, 0x05, + 0x9a, 0x61, 0x21, 0x14, 0xc2, 0xfb, 0xad, 0xcd, 0x95, 0xf4, 0xa5, 0xaa, 0x39, 0xf6, 0x07, 0xb0, 0x0e, 0xe6, 0xd8, + 0x48, 0xb8, 0x32, 0x7f, 0x6b, 0x5b, 0x0d, 0xc0, 0x76, 0x05, 0x98, 0x91, 0x8c, 0x73, 0xaa, 0xe3, 0xf6, 0x51, 0x0b, + 0x18, 0xd3, 0x2f, 0x0c, 0x4e, 0x15, 0x84, 0xb6, 0xa7, 0xc2, 0x92, 0x85, 0x50, 0x53, 0x3e, 0xd6, 0xf1, 0xef, 0xc2, + 0x10, 0x15, 0x96, 0x2b, 0x06, 0x12, 0x4e, 0xc0, 0x1e, 0x1b, 0x82, 0xf3, 0xbb, 0x80, 0x7e, 0xba, 0xe5, 0x41, 0xe4, + 0x46, 0x6a, 0x08, 0x17, 0x90, 0x87, 0x8a, 0xb5, 0xae, 0xc8, 0x4c, 0xc9, 0xb8, 0x01, 0xf7, 0xd8, 0xee, 0xd9, 0x16, + 0x53, 0x47, 0x0d, 0x44, 0xc0, 0xc1, 0x8a, 0x34, 0x24, 0x11, 0x2e, 0x51, 0x27, 0x5a, 0xbe, 0x94, 0x37, 0xac, 0x78, + 0x4c, 0x61, 0xf0, 0xa9, 0xad, 0xbe, 0xb6, 0x47, 0x81, 0xa1, 0xf8, 0xba, 0xeb, 0xf1, 0xe5, 0xda, 0x4c, 0xfc, 0x4d, + 0x21, 0x67, 0x5c, 0x31, 0xe0, 0xdb, 0x2c, 0xfc, 0x05, 0x6c, 0x34, 0xb3, 0x23, 0xe1, 0xb8, 0x61, 0x25, 0x7e, 0x3d, + 0x7c, 0x59, 0xc7, 0xaf, 0xeb, 0x7b, 0x4f, 0x27, 0x9e, 0x02, 0xd6, 0xf7, 0x31, 0xc2, 0xb1, 0x13, 0x2f, 0x82, 0x93, + 0x2e, 0x99, 0x22, 0x77, 0xcc, 0xaf, 0x56, 0x3a, 0x10, 0xe3, 0x6a, 0x9c, 0x23, 0xb3, 0xdb, 0x06, 0xad, 0xe9, 0x68, + 0x04, 0x2c, 0x5e, 0x21, 0xf3, 0x3c, 0x38, 0xac, 0xb0, 0xe8, 0x96, 0xc7, 0xd3, 0xf5, 0xbd, 0xa7, 0x57, 0xdf, 0x3b, + 0xa1, 0x20, 0x3f, 0x3c, 0xa4, 0xfc, 0x40, 0xc5, 0x88, 0x15, 0x20, 0x57, 0x06, 0xab, 0xe5, 0xce, 0xd9, 0xc7, 0x52, + 0x08, 0x96, 0x69, 0x36, 0x02, 0xa1, 0x45, 0x10, 0x9d, 0x4c, 0xa5, 0xd2, 0x65, 0x62, 0x35, 0x7a, 0x11, 0x0a, 0xa1, + 0x49, 0x46, 0xf3, 0x3c, 0xb6, 0x02, 0xca, 0x4c, 0x7e, 0x61, 0x3b, 0x46, 0xdd, 0xad, 0x0d, 0xb9, 0x6c, 0x86, 0x05, + 0xcd, 0xb0, 0x44, 0xcd, 0x73, 0x9e, 0xb1, 0xf2, 0xf0, 0xba, 0x4a, 0xb8, 0x18, 0xb1, 0x5b, 0xa0, 0x23, 0xe8, 0xf2, + 0xf2, 0xb2, 0x85, 0xdb, 0x68, 0x6d, 0x01, 0xbe, 0xdc, 0x02, 0xec, 0x77, 0x8e, 0x4d, 0x2b, 0x88, 0x2f, 0x77, 0x92, + 0x35, 0x14, 0x9c, 0x95, 0xdc, 0x0b, 0x5a, 0x96, 0x3c, 0x23, 0x3c, 0x62, 0x39, 0xd3, 0xcc, 0x93, 0x73, 0x60, 0xa6, + 0xed, 0xd6, 0x7d, 0x5b, 0xc2, 0xaf, 0x44, 0x27, 0xbf, 0xcb, 0xfc, 0x9a, 0xab, 0x52, 0x74, 0xaf, 0x96, 0xa7, 0x82, + 0x76, 0x4f, 0xdb, 0xe5, 0xa1, 0x5a, 0xd3, 0x6c, 0x6a, 0x25, 0xf6, 0x78, 0x6b, 0x4a, 0x55, 0x1b, 0x8e, 0xb4, 0x97, + 0x9b, 0xe8, 0x53, 0xe1, 0x86, 0xb9, 0x0b, 0x04, 0x57, 0x8e, 0x28, 0x30, 0x10, 0x02, 0xed, 0xb2, 0x3d, 0xa6, 0x79, + 0x3e, 0xa4, 0xd9, 0xe7, 0x3a, 0xf6, 0x57, 0x68, 0x40, 0x36, 0xa9, 0x71, 0x90, 0x15, 0x90, 0xac, 0x70, 0xde, 0x9e, + 0x4a, 0xd7, 0x36, 0x4a, 0xbc, 0xdf, 0xaa, 0xd0, 0xbe, 0xbe, 0xd0, 0xdf, 0xc4, 0x76, 0x33, 0x22, 0xe1, 0x66, 0x16, + 0x03, 0x15, 0xf8, 0x97, 0x18, 0xe7, 0xe9, 0x81, 0xc3, 0x3b, 0x10, 0x3c, 0xd6, 0x1b, 0x03, 0xd1, 0x68, 0xb9, 0x1e, + 0x71, 0xf5, 0x6d, 0x08, 0xfc, 0x6f, 0x19, 0xe5, 0x93, 0xa0, 0x87, 0x7f, 0x77, 0xa0, 0x25, 0x8d, 0x73, 0x8c, 0x73, + 0x39, 0x32, 0xc7, 0x50, 0x78, 0x42, 0xf3, 0x0b, 0x30, 0x2f, 0x06, 0xdf, 0x5f, 0xdb, 0x2c, 0xc3, 0x97, 0xc1, 0x30, + 0x54, 0x37, 0x64, 0x28, 0x6a, 0x28, 0xe0, 0x88, 0xaa, 0x30, 0x67, 0xae, 0xac, 0x89, 0x92, 0x8e, 0x6b, 0xb7, 0xe2, + 0xb8, 0xa3, 0xb9, 0x05, 0x89, 0xe3, 0x58, 0x81, 0x34, 0xe7, 0xf9, 0xfb, 0x6a, 0x16, 0x6a, 0x6b, 0x16, 0x2a, 0x09, + 0xa4, 0x2d, 0x54, 0x21, 0x73, 0x50, 0x3d, 0xd5, 0x02, 0x85, 0xa5, 0x80, 0x65, 0x4d, 0x80, 0x42, 0xa3, 0x92, 0xe0, + 0xe6, 0x44, 0xe3, 0xc2, 0x89, 0x3a, 0x0e, 0xd7, 0x80, 0x64, 0x54, 0x55, 0x24, 0xb2, 0x9b, 0xa3, 0x26, 0xfb, 0x4a, + 0x5c, 0xa0, 0x0d, 0xfe, 0x7e, 0xbd, 0x76, 0x50, 0x62, 0xc8, 0xad, 0x4e, 0x8d, 0x31, 0x0e, 0xc0, 0x82, 0x25, 0x71, + 0xcc, 0xb0, 0x65, 0x7d, 0x36, 0x81, 0x53, 0xb6, 0xbb, 0x4f, 0x88, 0xac, 0x60, 0x53, 0x63, 0x2a, 0x3d, 0x77, 0x25, + 0x11, 0xa6, 0x9e, 0x2d, 0x2d, 0xaa, 0x89, 0x13, 0x12, 0x79, 0xed, 0x44, 0xd4, 0x5b, 0xd6, 0x84, 0xc3, 0x34, 0x28, + 0xb6, 0x4e, 0x81, 0xa8, 0x16, 0xbb, 0xe0, 0xbd, 0x0b, 0x6b, 0x6a, 0xed, 0x04, 0x10, 0x2f, 0x6a, 0x10, 0x0f, 0x40, + 0x2b, 0x2d, 0xf1, 0x92, 0x03, 0x42, 0xeb, 0x95, 0x63, 0x86, 0x0b, 0xbb, 0x10, 0x5b, 0x50, 0xdc, 0x64, 0x3f, 0x0d, + 0x16, 0x82, 0x2c, 0xab, 0x80, 0xbf, 0x0b, 0x8f, 0x88, 0x18, 0x06, 0x2f, 0x56, 0xab, 0x2d, 0xb4, 0xdb, 0xc9, 0x85, + 0xa2, 0xa4, 0x92, 0x0e, 0x57, 0xab, 0xaf, 0x12, 0xc5, 0x8e, 0xff, 0xc5, 0x0c, 0xf5, 0x3c, 0xd1, 0x7d, 0xf8, 0x12, + 0x4a, 0x19, 0x76, 0xb4, 0x4a, 0x29, 0x05, 0x87, 0x3a, 0xd6, 0xd6, 0x17, 0x4a, 0x07, 0x94, 0xfb, 0xf1, 0x16, 0x01, + 0x33, 0x89, 0xee, 0xa4, 0xae, 0xa6, 0xfc, 0xd8, 0x35, 0x2d, 0x10, 0x42, 0xa9, 0x32, 0xb2, 0xcc, 0xfe, 0x2e, 0xf9, + 0xf2, 0xe0, 0x40, 0x05, 0x0d, 0x5d, 0x97, 0x94, 0xe2, 0xef, 0x18, 0x4e, 0x65, 0x75, 0x27, 0x0c, 0xfb, 0xf2, 0xb7, + 0x3f, 0x87, 0xb6, 0xa4, 0xd3, 0x56, 0x17, 0x04, 0x73, 0x7a, 0x43, 0xb9, 0xde, 0x2b, 0x5b, 0xb1, 0x82, 0x79, 0xcc, + 0xd0, 0xd2, 0x71, 0x1b, 0x49, 0xc1, 0x80, 0x7f, 0x04, 0xb2, 0xe0, 0xb9, 0x68, 0x8b, 0xf8, 0xd9, 0x94, 0x81, 0x2a, + 0xdb, 0x33, 0x12, 0xa5, 0x78, 0xb8, 0xef, 0x0e, 0x12, 0xd7, 0xf0, 0xee, 0xb1, 0xaf, 0x37, 0xab, 0xd7, 0xa4, 0x81, + 0x39, 0x2b, 0xc6, 0xb2, 0x98, 0xf9, 0xbc, 0xf5, 0xc6, 0xb7, 0x23, 0x8e, 0x7c, 0x1c, 0xef, 0x6c, 0xdb, 0x89, 0x00, + 0xdd, 0x0d, 0xd9, 0xbb, 0x92, 0xda, 0x6b, 0xa7, 0x69, 0x79, 0x00, 0x5b, 0x05, 0xa1, 0xc7, 0x4c, 0x15, 0x4a, 0xf9, + 0x4e, 0xbd, 0xda, 0xb5, 0xba, 0x93, 0xfd, 0x76, 0xb7, 0x94, 0xfc, 0x3c, 0x36, 0x74, 0xad, 0x8e, 0xc3, 0x9d, 0xaa, + 0x72, 0x91, 0x8f, 0xdc, 0x60, 0x05, 0xc2, 0xcc, 0xe1, 0xd1, 0x0d, 0xcf, 0xf3, 0x2a, 0xf5, 0x3f, 0x21, 0xed, 0xca, + 0x91, 0x76, 0xe9, 0x49, 0x3b, 0x90, 0x0a, 0x20, 0xed, 0xb6, 0xb9, 0xaa, 0xba, 0xdc, 0xda, 0x9e, 0xd2, 0x12, 0x75, + 0x65, 0xc4, 0x69, 0xe8, 0x6f, 0xe1, 0x47, 0x80, 0x4a, 0xe6, 0xeb, 0x73, 0xec, 0xf4, 0x31, 0x20, 0x06, 0x5a, 0x9d, + 0x26, 0x0b, 0x35, 0x15, 0x9f, 0x63, 0x84, 0xd5, 0x9a, 0x95, 0x98, 0xfd, 0xf0, 0x29, 0x28, 0xed, 0x82, 0xe9, 0xc0, + 0x39, 0x66, 0x92, 0xff, 0x23, 0x3e, 0xca, 0xcf, 0x4e, 0xb8, 0xd9, 0x29, 0x3f, 0x3b, 0xa0, 0xf5, 0xd5, 0xec, 0x46, + 0xdf, 0xa7, 0xf6, 0x66, 0x7a, 0xa2, 0x9c, 0x5e, 0xb5, 0xde, 0xab, 0x55, 0xbc, 0x91, 0x02, 0x1a, 0x7d, 0x27, 0xa5, + 0x14, 0x65, 0xeb, 0x40, 0x03, 0x42, 0xc8, 0x40, 0xc2, 0xda, 0x4e, 0xba, 0x3c, 0xe5, 0x5e, 0xfe, 0x2b, 0x3d, 0x8f, + 0x51, 0xdc, 0xdb, 0xfa, 0x8f, 0xe5, 0x6c, 0x0e, 0x0c, 0xd9, 0x06, 0x4a, 0x4f, 0x98, 0xeb, 0xb0, 0xca, 0x5f, 0xef, + 0x48, 0xab, 0xd5, 0x31, 0xfb, 0xb1, 0x86, 0x4d, 0xa5, 0xd4, 0xbc, 0xdf, 0x5a, 0x2f, 0xca, 0xa4, 0x92, 0x70, 0xec, + 0xd2, 0xad, 0x3c, 0xde, 0xd4, 0xcc, 0xf8, 0x8c, 0xd7, 0xb1, 0xb0, 0x74, 0x58, 0x00, 0xad, 0x0b, 0xc8, 0x8f, 0x47, + 0xf7, 0x70, 0xfd, 0xd7, 0x15, 0x70, 0x96, 0xeb, 0x0d, 0xf0, 0x2d, 0xd7, 0xeb, 0x47, 0xda, 0x49, 0xda, 0xf8, 0xd1, + 0x0e, 0xb9, 0xb7, 0x84, 0x5e, 0x95, 0xe9, 0x64, 0xc6, 0xfe, 0x00, 0xd2, 0xb6, 0x58, 0x48, 0xb2, 0x9c, 0xc9, 0x11, + 0x4b, 0x23, 0x39, 0x67, 0x22, 0x5a, 0x83, 0x9e, 0xd5, 0x21, 0xc0, 0x3f, 0x22, 0x5e, 0xbe, 0xad, 0xeb, 0x5b, 0xd3, + 0x47, 0x7a, 0x0d, 0xaa, 0xb0, 0x97, 0x7c, 0x87, 0x32, 0xf6, 0x3d, 0x2b, 0x94, 0xe1, 0x49, 0x4b, 0xf6, 0xf6, 0x25, + 0xaf, 0x0e, 0xa8, 0x97, 0x3c, 0xfd, 0x76, 0x95, 0x4a, 0x20, 0x89, 0xda, 0xc9, 0x59, 0x72, 0x1c, 0x21, 0xa3, 0x31, + 0x7e, 0xe6, 0x35, 0xc6, 0x8b, 0x52, 0x63, 0xfc, 0x5c, 0x93, 0xc5, 0x86, 0xc6, 0xf8, 0x0f, 0x41, 0x9e, 0xeb, 0xde, + 0x73, 0xaf, 0x4d, 0x7f, 0x23, 0x73, 0x9e, 0xdd, 0xc5, 0x51, 0xce, 0x75, 0x13, 0x6e, 0x13, 0x23, 0xbc, 0xb4, 0x19, + 0xa0, 0x6a, 0x34, 0xfa, 0xee, 0xb5, 0x97, 0xff, 0xb0, 0x10, 0x24, 0xba, 0x97, 0x73, 0x7d, 0x2f, 0xc2, 0x53, 0x4d, + 0xfe, 0x82, 0x5f, 0xf7, 0x96, 0xf1, 0xaf, 0x54, 0x4f, 0x93, 0x82, 0x8a, 0x91, 0x9c, 0xc5, 0xa8, 0x11, 0x45, 0x28, + 0x51, 0x46, 0x08, 0x79, 0x80, 0xd6, 0xf7, 0xfe, 0xc2, 0xaf, 0x24, 0x89, 0x7a, 0x51, 0x63, 0xaa, 0xb1, 0xa6, 0xe4, + 0xaf, 0x8b, 0x7b, 0xcb, 0x57, 0x72, 0x7d, 0xf9, 0x17, 0x7e, 0xaa, 0x4b, 0xb5, 0x3e, 0xbe, 0x65, 0x24, 0x46, 0xe4, + 0xf2, 0xa9, 0x1f, 0xd2, 0x63, 0x39, 0xb3, 0x0a, 0xfe, 0x08, 0xe1, 0x2f, 0xa0, 0xd7, 0xbd, 0xe4, 0x15, 0x11, 0x72, + 0x77, 0x30, 0xfb, 0x24, 0x92, 0x46, 0x79, 0x10, 0x1d, 0x1c, 0x04, 0x69, 0x25, 0x0b, 0x81, 0xff, 0x96, 0xa4, 0x26, + 0xaa, 0x63, 0x46, 0xa1, 0xa5, 0xbf, 0x65, 0xcc, 0x91, 0x6f, 0x26, 0xf6, 0x9a, 0x6a, 0xb7, 0x63, 0x79, 0xdf, 0xea, + 0x1e, 0x12, 0xae, 0x59, 0x41, 0xb5, 0x2c, 0x06, 0x28, 0x64, 0x4b, 0xf0, 0x57, 0x4e, 0xfe, 0xea, 0xef, 0xfd, 0x3f, + 0xff, 0xe3, 0xcf, 0xf1, 0x9f, 0xc5, 0xe0, 0x2f, 0x2c, 0x18, 0x39, 0xba, 0x88, 0x7b, 0x69, 0xbc, 0xdf, 0x6c, 0xae, + 0xfe, 0x3c, 0xea, 0xff, 0x37, 0x6d, 0x7e, 0x7d, 0xd8, 0xfc, 0x34, 0x40, 0xab, 0xf8, 0xcf, 0xa3, 0x5e, 0xdf, 0x7d, + 0xf5, 0xff, 0xfb, 0xf2, 0x4f, 0x35, 0x38, 0xb4, 0x89, 0xf7, 0x10, 0x3a, 0x9a, 0xe0, 0x5f, 0x04, 0x39, 0x6a, 0x36, + 0x2f, 0x8f, 0x26, 0xf8, 0x27, 0x41, 0x8e, 0xe0, 0xef, 0x9d, 0x26, 0x6f, 0xd9, 0xe4, 0xe9, 0xed, 0x3c, 0xfe, 0xeb, + 0x72, 0x75, 0x6f, 0xf9, 0x95, 0xaf, 0xa1, 0xdd, 0xfe, 0x7f, 0xff, 0xf9, 0xa7, 0x8a, 0x7e, 0xbc, 0x24, 0x47, 0x83, + 0x06, 0x8a, 0x4d, 0xf2, 0x21, 0xb1, 0x7f, 0xe2, 0x5e, 0xda, 0xff, 0x6f, 0x37, 0x94, 0xe8, 0xc7, 0x3f, 0xff, 0xba, + 0xb8, 0x24, 0x83, 0x55, 0x1c, 0xad, 0x7e, 0x44, 0x2b, 0x84, 0x56, 0xf7, 0xd0, 0x5f, 0x38, 0x9a, 0x44, 0x08, 0xff, + 0x26, 0xc8, 0xd1, 0x8f, 0x47, 0x13, 0xfc, 0x49, 0x90, 0xa3, 0xe8, 0x68, 0x82, 0xdf, 0x4b, 0x72, 0xf4, 0xdf, 0x71, + 0x2f, 0xb5, 0x4a, 0xb8, 0x95, 0x51, 0x7f, 0xac, 0xe0, 0x26, 0x84, 0x16, 0x8c, 0xae, 0x34, 0xd7, 0x39, 0x43, 0xf7, + 0x8e, 0x38, 0x7e, 0x24, 0x01, 0x58, 0xb1, 0x06, 0x25, 0x8d, 0xb9, 0x84, 0x5d, 0x5e, 0xc3, 0xc2, 0x03, 0x06, 0xdd, + 0x4b, 0x39, 0xb6, 0x7a, 0x02, 0x95, 0x6a, 0x7b, 0x7b, 0xab, 0xe0, 0xfa, 0x16, 0x3f, 0x26, 0x8f, 0x64, 0xdc, 0x46, + 0x98, 0x53, 0xf8, 0xd1, 0x41, 0xf8, 0x83, 0x76, 0x17, 0x9e, 0xb0, 0xcd, 0x2d, 0x86, 0x09, 0x69, 0xf9, 0x99, 0x08, + 0xe1, 0x97, 0x3b, 0x32, 0xf5, 0x14, 0xd4, 0x0f, 0x08, 0xff, 0x5c, 0xbb, 0x1e, 0xc5, 0x8f, 0x35, 0x29, 0x91, 0xe3, + 0x5d, 0xc1, 0xd8, 0x07, 0x9a, 0x7f, 0x66, 0x45, 0xfc, 0x54, 0xe3, 0x76, 0xe7, 0x01, 0x36, 0xaa, 0xea, 0xfd, 0x36, + 0xea, 0x96, 0xb7, 0x5b, 0xcf, 0xa5, 0xbd, 0x4f, 0x80, 0x53, 0xb8, 0xae, 0xaf, 0x81, 0xb5, 0xdf, 0xe7, 0x5b, 0x4a, + 0xad, 0x82, 0xde, 0x44, 0xa8, 0x7e, 0x95, 0xca, 0xc5, 0x17, 0x9a, 0xf3, 0xd1, 0x9e, 0x66, 0xb3, 0x79, 0x4e, 0x35, + 0xdb, 0x73, 0x73, 0xde, 0xa3, 0xd0, 0x50, 0x54, 0xf2, 0x14, 0x7f, 0x88, 0x6a, 0xd3, 0xfe, 0x21, 0x92, 0x6a, 0xef, + 0xc4, 0x70, 0x9f, 0xe5, 0xf8, 0x12, 0x41, 0xcb, 0xeb, 0xb2, 0xcd, 0x1b, 0xc1, 0x66, 0x1b, 0x94, 0x65, 0x03, 0x73, + 0x7e, 0x2b, 0x0c, 0xf7, 0x9b, 0x84, 0x74, 0x7a, 0xd1, 0x85, 0xfa, 0x32, 0xb9, 0x8c, 0xe0, 0x26, 0xa7, 0x20, 0x82, + 0x19, 0xe5, 0x11, 0x94, 0xa0, 0xa4, 0xd5, 0xa5, 0x17, 0xac, 0x4b, 0x1b, 0x0d, 0xcf, 0x66, 0x67, 0x84, 0xf7, 0xa9, + 0xad, 0x9f, 0xe3, 0x29, 0x1e, 0x91, 0x66, 0x1b, 0x2f, 0x48, 0xcb, 0x54, 0xe9, 0x2e, 0x2e, 0x32, 0xd7, 0xcf, 0xc1, + 0x41, 0x5c, 0x24, 0x39, 0x55, 0xfa, 0x05, 0x68, 0x04, 0xc8, 0x02, 0x4f, 0x49, 0x91, 0xb0, 0x5b, 0x96, 0xc5, 0x19, + 0xc2, 0x53, 0x47, 0x83, 0x50, 0x17, 0x2d, 0x48, 0x50, 0x0c, 0xe4, 0x0c, 0x22, 0x58, 0x6f, 0xda, 0x6f, 0x0f, 0x08, + 0x21, 0xd1, 0x7e, 0xb3, 0x19, 0xf5, 0x0a, 0xf2, 0x8b, 0x48, 0x21, 0x25, 0x60, 0xa7, 0xc9, 0x4f, 0x90, 0xd4, 0x09, + 0x92, 0xe2, 0xf7, 0x32, 0xd1, 0x4c, 0xe9, 0x18, 0x92, 0x41, 0x49, 0xa0, 0x3c, 0x86, 0x47, 0x17, 0x47, 0x51, 0x03, + 0x52, 0x0d, 0x8a, 0x22, 0x5c, 0x90, 0x3b, 0x8d, 0xd2, 0x69, 0xff, 0x78, 0x10, 0x9e, 0x11, 0x36, 0x15, 0xfa, 0xbf, + 0xd3, 0xbd, 0x69, 0xbf, 0x65, 0xfa, 0xbf, 0x8c, 0x7a, 0x71, 0x41, 0x94, 0x65, 0xe3, 0x7a, 0x2a, 0x15, 0xcc, 0xcc, + 0x17, 0xa5, 0x6e, 0x80, 0xae, 0xef, 0x11, 0x69, 0x76, 0xd2, 0x78, 0x14, 0xce, 0xa4, 0x09, 0x1d, 0x3a, 0x50, 0xe0, + 0x9c, 0x40, 0x79, 0x5c, 0x10, 0xe8, 0xb4, 0xaa, 0x76, 0xa7, 0x53, 0x97, 0xf0, 0x63, 0xf4, 0x63, 0xef, 0x93, 0x48, + 0x7f, 0x13, 0x76, 0x04, 0x9f, 0xc4, 0x6a, 0x05, 0x7f, 0x7f, 0x13, 0x3d, 0x18, 0x96, 0x49, 0xfb, 0xc5, 0xa5, 0xfd, + 0x04, 0x69, 0x82, 0xa5, 0x66, 0xc0, 0x58, 0x95, 0xfc, 0x98, 0x5d, 0x9c, 0x31, 0xb1, 0x33, 0x38, 0x38, 0xe0, 0x7d, + 0xda, 0x68, 0x0f, 0xe0, 0x46, 0xa0, 0xd0, 0xea, 0x03, 0xd7, 0xd3, 0x38, 0x3a, 0xba, 0x8c, 0x50, 0x2f, 0xda, 0x83, + 0x55, 0xee, 0xca, 0x06, 0x71, 0xb0, 0xce, 0x1a, 0x9a, 0xa6, 0xa3, 0x4b, 0xd2, 0xea, 0xc5, 0xc2, 0x12, 0xf9, 0x1c, + 0xe1, 0xcc, 0xd1, 0xd4, 0x16, 0x1e, 0xa1, 0x86, 0x10, 0x0d, 0xff, 0x3d, 0x42, 0x8d, 0xa9, 0x6e, 0x8c, 0x51, 0x9a, + 0xc1, 0xdf, 0x78, 0x44, 0x08, 0x69, 0x76, 0xca, 0x8a, 0xfe, 0xb0, 0xa4, 0x28, 0x1d, 0x7b, 0xf5, 0x68, 0xdf, 0x6c, + 0x0e, 0xd9, 0x88, 0x79, 0x9f, 0x0d, 0x56, 0xab, 0xe8, 0xa2, 0x77, 0x19, 0xa1, 0x46, 0xec, 0xd1, 0xee, 0xc8, 0xe3, + 0x1d, 0x42, 0x58, 0x0c, 0xd6, 0xee, 0x06, 0xea, 0x86, 0xd5, 0x6e, 0x9b, 0x96, 0xd5, 0xfe, 0x0f, 0xc8, 0x02, 0x5b, + 0x97, 0x72, 0x8f, 0xe5, 0x6f, 0xe7, 0x30, 0x55, 0x8f, 0xdb, 0x92, 0xb4, 0x70, 0x41, 0xbc, 0xba, 0x9b, 0x12, 0x5d, + 0xe1, 0x7f, 0x46, 0xaa, 0xe2, 0xb8, 0x9f, 0xe3, 0xe9, 0x80, 0x08, 0x6a, 0xe4, 0x97, 0xae, 0x57, 0xa6, 0xb3, 0x9c, + 0xdc, 0xb0, 0x8d, 0xfb, 0xdf, 0x1c, 0xee, 0x64, 0x1e, 0xeb, 0x24, 0x5b, 0x14, 0x05, 0x13, 0xfa, 0x95, 0x1c, 0x39, + 0xc6, 0x8e, 0xe5, 0x20, 0x5b, 0xc1, 0xc5, 0x2e, 0x06, 0xae, 0xae, 0xe3, 0x77, 0xca, 0x68, 0x2b, 0x7b, 0x41, 0x46, + 0x96, 0xe1, 0x32, 0xd7, 0xbd, 0xdd, 0x85, 0x13, 0xa5, 0x63, 0x84, 0x47, 0xee, 0x1e, 0x38, 0x4e, 0x92, 0x64, 0x91, + 0x64, 0x90, 0x0d, 0x1d, 0x28, 0xb4, 0x36, 0xfb, 0x2a, 0x56, 0xe4, 0xb1, 0x4e, 0x04, 0xbb, 0x35, 0xdd, 0xc6, 0xa8, + 0x3a, 0xc4, 0xfd, 0x7e, 0xbb, 0xa0, 0x5d, 0x43, 0x80, 0x54, 0x22, 0xe4, 0x88, 0x01, 0x84, 0xe0, 0xee, 0xdf, 0x25, + 0x4d, 0xa9, 0x0a, 0x6f, 0xb6, 0xaa, 0x01, 0xf6, 0x43, 0x95, 0xf7, 0x02, 0xf4, 0xc4, 0x86, 0x3d, 0x2b, 0x0b, 0x5b, + 0xe5, 0x39, 0x42, 0x7c, 0x1c, 0x2f, 0x12, 0xb8, 0x11, 0x34, 0x98, 0x24, 0x04, 0x5a, 0xad, 0x16, 0x21, 0x6e, 0x4d, + 0x2b, 0xc5, 0xf4, 0x98, 0x4c, 0xfb, 0x45, 0xa3, 0x61, 0x94, 0xd7, 0x23, 0x8b, 0x17, 0x0b, 0x84, 0xc7, 0xe5, 0x5e, + 0xf3, 0xe5, 0xe6, 0xa4, 0xde, 0x55, 0x3c, 0xae, 0x2b, 0x81, 0x1b, 0x42, 0x20, 0xa3, 0x5f, 0xd4, 0xd0, 0x3a, 0x9e, + 0x90, 0xa3, 0xb8, 0x9f, 0xf4, 0xfe, 0xe7, 0x00, 0xf5, 0xe2, 0xe4, 0x10, 0x1d, 0x59, 0x5a, 0x32, 0x46, 0xdd, 0xcc, + 0xf6, 0xb1, 0x34, 0xb7, 0x9f, 0x6d, 0x6c, 0x14, 0x90, 0xa9, 0xc4, 0x82, 0xce, 0x58, 0x3a, 0x81, 0x5d, 0xef, 0x91, + 0x67, 0x8e, 0x01, 0x99, 0xd2, 0x89, 0xa3, 0x2d, 0x49, 0xd4, 0x93, 0xb4, 0xfc, 0xea, 0x45, 0x3d, 0x5a, 0x7d, 0xfd, + 0xcf, 0xa8, 0x97, 0xd1, 0xf4, 0x31, 0x5f, 0x3b, 0x25, 0x79, 0xad, 0x8f, 0x33, 0xdf, 0xc7, 0xda, 0x2e, 0x4e, 0x00, + 0xbc, 0x11, 0xda, 0xd6, 0x8e, 0x2c, 0xd0, 0x9a, 0x8f, 0x4b, 0xea, 0xa4, 0x12, 0x4d, 0x27, 0x00, 0xd5, 0x60, 0x11, + 0x54, 0x68, 0x1b, 0x10, 0x4c, 0x19, 0xb0, 0xc5, 0x23, 0x2d, 0x40, 0x73, 0x71, 0xd9, 0x42, 0xcb, 0x5a, 0x61, 0xc7, + 0x59, 0xd5, 0xef, 0xe2, 0x4b, 0xe2, 0x3d, 0x06, 0xaa, 0x7c, 0xb1, 0xe8, 0x8e, 0x1b, 0x0d, 0xa4, 0x3c, 0x7e, 0x8d, + 0xfa, 0xe3, 0x01, 0xbe, 0x05, 0x14, 0xc2, 0x35, 0x8c, 0xc2, 0xb5, 0x39, 0x76, 0xdc, 0x1c, 0x1b, 0x0d, 0xb9, 0x46, + 0xdd, 0xa0, 0xf2, 0xc2, 0x55, 0x5e, 0xaf, 0x2d, 0x64, 0x36, 0x31, 0xee, 0x1c, 0x99, 0x14, 0x30, 0x04, 0x23, 0x84, + 0xbc, 0x92, 0x68, 0x67, 0xb3, 0xd0, 0x28, 0x54, 0x37, 0xbb, 0x17, 0x28, 0xaa, 0x3d, 0x3d, 0x62, 0x80, 0x05, 0x54, + 0x2d, 0xd5, 0xc8, 0x53, 0x8d, 0x47, 0x8d, 0xb6, 0x41, 0xf7, 0x66, 0xbb, 0x5b, 0x6f, 0xec, 0x7e, 0xd5, 0x18, 0x1e, + 0x35, 0xc8, 0xb4, 0xda, 0xe1, 0x6b, 0xd9, 0x68, 0xac, 0xeb, 0xf7, 0xa5, 0x7e, 0x13, 0xd7, 0xee, 0x2f, 0x9e, 0x6e, + 0x99, 0x78, 0xf8, 0xd3, 0xb7, 0x3a, 0x6f, 0x45, 0xc2, 0x85, 0x60, 0x05, 0x9c, 0xb0, 0x44, 0x63, 0xb1, 0x5e, 0x97, + 0xa7, 0xfe, 0xef, 0xda, 0xda, 0x8c, 0x11, 0x0e, 0x74, 0xc8, 0x48, 0x6d, 0x58, 0xe2, 0x02, 0x53, 0x43, 0x45, 0x08, + 0x21, 0x1f, 0xb4, 0x37, 0x8f, 0xd1, 0x86, 0x24, 0x65, 0x24, 0x38, 0xbb, 0x63, 0x45, 0x58, 0x72, 0x7d, 0xef, 0xb1, + 0xfc, 0xae, 0x48, 0xd7, 0x17, 0x83, 0xd4, 0x14, 0xcb, 0x1d, 0x21, 0xcb, 0xc9, 0x17, 0x90, 0x73, 0xca, 0x0b, 0x96, + 0xc4, 0x10, 0xc4, 0x27, 0xbc, 0x60, 0x86, 0x71, 0xbf, 0xe7, 0xe5, 0xc6, 0xac, 0xce, 0x69, 0x66, 0xa1, 0xf6, 0x07, + 0xa0, 0x99, 0x83, 0x72, 0x48, 0x92, 0xad, 0x62, 0xd7, 0xf7, 0x1e, 0xbe, 0xde, 0x25, 0x43, 0xaf, 0x56, 0x4e, 0x7a, + 0xce, 0x80, 0xf5, 0xc1, 0x79, 0x35, 0xd4, 0xcc, 0xfd, 0x48, 0xe3, 0xcc, 0x30, 0x51, 0x79, 0xcc, 0x01, 0x99, 0xae, + 0xef, 0x3d, 0x7c, 0x17, 0x73, 0xa3, 0x9b, 0x42, 0x38, 0x9c, 0x77, 0x5c, 0x90, 0x98, 0x12, 0x86, 0xec, 0xe4, 0x4b, + 0x3a, 0x56, 0x04, 0xa7, 0x7b, 0x4a, 0x4d, 0x26, 0x88, 0x1d, 0x7d, 0x31, 0x20, 0x99, 0x03, 0x01, 0xc9, 0x10, 0xce, + 0x6a, 0x72, 0x1d, 0x31, 0x6b, 0x60, 0x3a, 0xbb, 0x82, 0xc5, 0x48, 0x2c, 0x7b, 0x88, 0x70, 0x66, 0xba, 0xd5, 0x6b, + 0x7b, 0x9c, 0x28, 0xba, 0x69, 0xe8, 0x56, 0xc9, 0xb3, 0xef, 0x41, 0xf0, 0xf2, 0x1f, 0xaf, 0x5c, 0xdb, 0x65, 0xc2, + 0x13, 0x6f, 0x91, 0x76, 0x7d, 0xef, 0xe1, 0xaf, 0xce, 0x28, 0x6d, 0x4e, 0x3d, 0xf9, 0xdf, 0x92, 0x51, 0x1f, 0xfe, + 0x9a, 0x54, 0xb9, 0xa6, 0xf0, 0xf5, 0xbd, 0x87, 0xbf, 0xef, 0x2a, 0x06, 0xe9, 0xeb, 0x45, 0xa5, 0x24, 0x30, 0xe3, + 0x5b, 0xb2, 0x3c, 0x5d, 0xba, 0xb3, 0x22, 0x15, 0x6b, 0x6c, 0x4e, 0xa8, 0x54, 0xad, 0x4b, 0xdd, 0xca, 0x13, 0x2c, + 0x89, 0xb9, 0x4a, 0xaa, 0x2f, 0x9b, 0x43, 0x63, 0x2e, 0xc5, 0x55, 0x26, 0xe7, 0xec, 0x1b, 0xf7, 0x4b, 0x4f, 0x35, + 0x4a, 0xf8, 0x0c, 0x0c, 0x71, 0xcc, 0xd8, 0x05, 0xde, 0x6f, 0xa1, 0xee, 0xc6, 0x79, 0x26, 0x0d, 0xa2, 0x16, 0xf5, + 0xc3, 0x06, 0x53, 0xd2, 0xc2, 0x19, 0x69, 0xe1, 0x9c, 0xa8, 0x7e, 0xcb, 0x9e, 0x18, 0xdd, 0xbc, 0x6c, 0xda, 0x9e, + 0x3b, 0xb0, 0xdd, 0x73, 0xbb, 0x6f, 0xed, 0xa1, 0x3c, 0xed, 0xe6, 0x46, 0x7f, 0x69, 0x0e, 0xfa, 0xa9, 0x41, 0x8d, + 0x27, 0x2c, 0x2e, 0x70, 0x61, 0x5a, 0xbe, 0xe2, 0xc3, 0x1c, 0xec, 0x54, 0x60, 0x66, 0x58, 0xa3, 0xb4, 0x2c, 0xdb, + 0x76, 0x65, 0xf3, 0xc4, 0xac, 0x55, 0x81, 0xf3, 0x04, 0x48, 0x39, 0xce, 0x9d, 0x5d, 0x8f, 0xda, 0xae, 0x72, 0x76, + 0x70, 0x10, 0xbb, 0x4a, 0x34, 0x2e, 0x7c, 0x7e, 0x75, 0x03, 0xf8, 0xde, 0x52, 0x8d, 0x29, 0x32, 0x13, 0x68, 0x34, + 0xb2, 0xc1, 0x9a, 0xee, 0x13, 0x12, 0xe7, 0x75, 0x28, 0xfa, 0xd1, 0x1b, 0x66, 0x70, 0x03, 0x00, 0x8d, 0x46, 0x79, + 0xdd, 0xbb, 0x01, 0xb1, 0xa7, 0x1a, 0xcb, 0xf5, 0x97, 0xb8, 0xb4, 0x26, 0x6a, 0x6d, 0xd9, 0x61, 0xf9, 0x51, 0x20, + 0x11, 0xe2, 0xae, 0xf0, 0xf3, 0x09, 0xb6, 0x86, 0x80, 0x72, 0x2f, 0x9c, 0x0d, 0x04, 0x36, 0x56, 0x5b, 0xae, 0x90, + 0x27, 0x6d, 0x1d, 0x94, 0xfa, 0x42, 0x70, 0xc1, 0x05, 0x85, 0x1a, 0x6b, 0x87, 0xe5, 0x4f, 0xd8, 0xb6, 0x39, 0x27, + 0x56, 0xc8, 0x69, 0xcb, 0xcc, 0x30, 0x0c, 0xc0, 0x3a, 0x25, 0x60, 0x9e, 0x93, 0x97, 0xdf, 0x46, 0xfd, 0x87, 0x01, + 0xea, 0x3f, 0x22, 0x2c, 0xd8, 0x06, 0x56, 0x57, 0x92, 0x48, 0xa7, 0xa0, 0x50, 0x3e, 0xeb, 0xf1, 0x9c, 0x80, 0x36, + 0xae, 0x0e, 0xd5, 0xda, 0x15, 0xe5, 0x37, 0x28, 0x4b, 0xb8, 0x53, 0x8c, 0x3e, 0x13, 0xfb, 0xfb, 0xe4, 0xb8, 0xba, + 0xa0, 0x83, 0xae, 0x77, 0x29, 0x07, 0x43, 0x52, 0xf8, 0xf0, 0xf7, 0xef, 0xdf, 0xad, 0x3e, 0x9e, 0x6f, 0xef, 0xe0, + 0xc0, 0xac, 0x14, 0x66, 0x1d, 0x6c, 0xe0, 0xba, 0x91, 0x29, 0xf4, 0x5f, 0xde, 0x89, 0xd7, 0xa9, 0xd0, 0xc6, 0x66, + 0xf4, 0xc7, 0x21, 0x8c, 0xb6, 0xdd, 0x36, 0x25, 0x58, 0xd0, 0x2c, 0xd0, 0x25, 0x6b, 0xdc, 0x4a, 0x8b, 0x6f, 0x90, + 0x91, 0x87, 0xa6, 0x00, 0x13, 0xa3, 0xdd, 0xd9, 0x8f, 0xd6, 0x0e, 0x4f, 0xec, 0xd0, 0xd0, 0xd2, 0x10, 0x42, 0x8b, + 0xf7, 0x80, 0x39, 0xf6, 0x88, 0x00, 0x10, 0xbd, 0x34, 0x90, 0xaa, 0x40, 0x16, 0x45, 0x95, 0x22, 0xff, 0xf9, 0x3e, + 0x21, 0x2f, 0x2b, 0x45, 0xe6, 0xdb, 0xca, 0x98, 0x0b, 0x10, 0x03, 0xa5, 0x70, 0x91, 0x50, 0x26, 0xd8, 0xcb, 0xd0, + 0x0f, 0xda, 0x97, 0x37, 0xd2, 0x66, 0x52, 0x71, 0xe3, 0xc1, 0x4d, 0xa9, 0x51, 0xf1, 0xd9, 0x7c, 0x0f, 0x89, 0x8d, + 0xdc, 0x7b, 0x90, 0xcb, 0xa8, 0x19, 0x24, 0x7c, 0xbf, 0x33, 0xa5, 0x7d, 0xbb, 0xeb, 0xcf, 0x9b, 0x16, 0x31, 0x1b, + 0xeb, 0x92, 0x70, 0xa1, 0x58, 0xa1, 0x1f, 0xb1, 0xb1, 0x2c, 0xe0, 0xfe, 0xa3, 0x04, 0x0b, 0x5a, 0xdf, 0x0b, 0x74, + 0x80, 0x66, 0x82, 0xc1, 0xa5, 0xc3, 0xc6, 0x0c, 0xcd, 0xaf, 0xcf, 0xe6, 0x0e, 0xfc, 0x7a, 0xb3, 0xd6, 0xcb, 0x83, + 0x83, 0x2f, 0xac, 0x02, 0x94, 0x1b, 0xa6, 0x19, 0x46, 0x40, 0xbc, 0x2c, 0x97, 0xe3, 0x6e, 0x86, 0xef, 0xc5, 0x95, + 0xca, 0xc0, 0x13, 0x8e, 0x90, 0x08, 0x3d, 0x27, 0x7a, 0x3d, 0xd9, 0xa4, 0xf7, 0x4e, 0x9b, 0x21, 0x42, 0xb1, 0x06, + 0xc8, 0x3d, 0xc8, 0xe5, 0x56, 0xc9, 0xa4, 0x2a, 0x5b, 0xdb, 0x72, 0x10, 0x8f, 0x01, 0x5c, 0xb1, 0x11, 0x52, 0x02, + 0x34, 0xdc, 0x2d, 0xb4, 0x3c, 0x97, 0xc0, 0xfe, 0x63, 0x95, 0x80, 0x48, 0x8b, 0x6a, 0x1b, 0x17, 0x21, 0x6c, 0x4d, + 0x7d, 0x02, 0xe3, 0x84, 0x87, 0xcf, 0x77, 0x69, 0xa8, 0x3d, 0x6a, 0x33, 0x73, 0x06, 0x41, 0x09, 0x89, 0xca, 0x0a, + 0xc9, 0x97, 0x58, 0x38, 0x6e, 0xce, 0xdf, 0xc3, 0x01, 0x29, 0x56, 0x34, 0xb6, 0x77, 0x5b, 0x70, 0x7c, 0x14, 0xc9, + 0x22, 0xae, 0x75, 0xdd, 0x2d, 0x4c, 0x35, 0xec, 0x40, 0x47, 0x43, 0x38, 0x15, 0xe6, 0x9e, 0xf0, 0x71, 0x45, 0x52, + 0x7f, 0xb6, 0x26, 0xda, 0xda, 0x13, 0xc3, 0xca, 0x34, 0x25, 0x98, 0xff, 0xcf, 0xd6, 0xea, 0xba, 0x2c, 0x84, 0x99, + 0x19, 0xc6, 0x8d, 0x5d, 0x05, 0xb6, 0x06, 0x1c, 0x5b, 0xfe, 0x2d, 0x83, 0x45, 0xf5, 0x4a, 0x71, 0xd3, 0x69, 0xc0, + 0x04, 0xbc, 0x05, 0xeb, 0x99, 0xcd, 0xad, 0xff, 0xdc, 0x1c, 0x8c, 0x02, 0xab, 0x1a, 0x81, 0x97, 0x86, 0xc0, 0x23, + 0x60, 0xdc, 0xbc, 0x69, 0x79, 0xcf, 0x19, 0xd1, 0x08, 0x7f, 0xe2, 0x39, 0x3c, 0xb3, 0x2c, 0xf7, 0xd6, 0xc7, 0xc6, + 0x8a, 0xa4, 0x82, 0x80, 0x6d, 0x11, 0x76, 0x44, 0x5e, 0x22, 0xac, 0x1a, 0x8d, 0xae, 0xba, 0x60, 0x95, 0x56, 0xa5, + 0x1a, 0xa6, 0x80, 0x5b, 0x62, 0xc0, 0xfb, 0xda, 0x89, 0x0a, 0x86, 0x04, 0xde, 0xfa, 0x5b, 0x81, 0xfa, 0xfe, 0xe1, + 0xdb, 0x38, 0xa4, 0x6f, 0x61, 0xd9, 0xf2, 0x22, 0x16, 0xa6, 0x14, 0x57, 0x77, 0x38, 0x6f, 0xbe, 0x6f, 0x36, 0x02, + 0xe3, 0xde, 0x6f, 0x63, 0xb0, 0x71, 0x43, 0x5d, 0x6d, 0x49, 0x43, 0xb9, 0x09, 0xbb, 0xa8, 0xb2, 0x77, 0x0c, 0x3b, + 0xeb, 0xea, 0x4a, 0xda, 0xd5, 0x44, 0xad, 0xd7, 0x8a, 0x55, 0x46, 0x03, 0x1b, 0x86, 0x9d, 0xe6, 0x98, 0xd9, 0x56, + 0xe0, 0x3f, 0x9e, 0x13, 0x8d, 0x03, 0x64, 0x7d, 0xf3, 0xad, 0xeb, 0x94, 0x6a, 0x98, 0xb0, 0xbd, 0xdd, 0xf9, 0xf8, + 0x98, 0xef, 0x3a, 0x1f, 0xb1, 0x74, 0x5b, 0xdf, 0x9c, 0x8d, 0xed, 0x7f, 0xe3, 0x6c, 0x74, 0x6a, 0x7b, 0x7f, 0x3c, + 0x02, 0x77, 0x52, 0x3b, 0x1e, 0xeb, 0x6b, 0x4a, 0x24, 0x16, 0x6e, 0x39, 0x2e, 0x3b, 0xab, 0x95, 0xe8, 0xb7, 0x40, + 0xed, 0x14, 0x45, 0xf0, 0xb3, 0x6d, 0x7f, 0x06, 0x24, 0xd9, 0xea, 0x90, 0x63, 0x51, 0x8a, 0x32, 0x28, 0x01, 0x03, + 0xea, 0xd8, 0xd8, 0x7a, 0x19, 0xc4, 0x76, 0x38, 0xe4, 0xb0, 0x9c, 0x88, 0xf2, 0xea, 0x0a, 0x46, 0x6c, 0x8e, 0x0d, + 0x27, 0x60, 0xc6, 0x3b, 0xad, 0x0a, 0xbd, 0xf8, 0xf9, 0xaf, 0x99, 0xd3, 0xda, 0x11, 0x63, 0x39, 0x89, 0x9a, 0x15, + 0x83, 0x1b, 0x81, 0x63, 0x18, 0xf7, 0x8d, 0x84, 0x5a, 0x9d, 0xea, 0xa8, 0x76, 0x24, 0xe1, 0x16, 0xa8, 0xdd, 0xf6, + 0xcd, 0xb9, 0xb4, 0x5a, 0xed, 0x3c, 0x58, 0x70, 0x11, 0xe0, 0xf6, 0x73, 0xa2, 0x6b, 0x24, 0x85, 0x12, 0x27, 0x41, + 0xe1, 0xdc, 0xa0, 0xaa, 0x26, 0xb2, 0xdf, 0x1a, 0x00, 0x4f, 0xda, 0xcd, 0x2e, 0x64, 0x25, 0x24, 0x67, 0x8d, 0x06, + 0xca, 0xcb, 0x8e, 0x69, 0x5f, 0x34, 0xb2, 0x01, 0x66, 0x38, 0xb3, 0x02, 0x0b, 0x9c, 0x5e, 0x71, 0x5e, 0x75, 0xdd, + 0xcf, 0x06, 0x08, 0x17, 0xab, 0x55, 0x6c, 0x87, 0x96, 0xa3, 0xd5, 0x2a, 0x0f, 0x87, 0x66, 0xf2, 0xa1, 0xe2, 0xcb, + 0x9e, 0x26, 0x2f, 0xcd, 0x79, 0xf8, 0x12, 0x06, 0xd9, 0x20, 0x71, 0xee, 0x54, 0x82, 0x39, 0x68, 0xae, 0x1a, 0xb2, + 0x9f, 0x35, 0xda, 0x83, 0x80, 0x86, 0xf5, 0xb3, 0x01, 0xc9, 0xd7, 0x60, 0x39, 0xab, 0xdc, 0x81, 0xf9, 0x37, 0x1c, + 0x6c, 0x7f, 0x9b, 0x73, 0xc6, 0x36, 0x18, 0xae, 0xc9, 0xa6, 0xca, 0xa0, 0xc4, 0x2b, 0xb7, 0xb8, 0xbe, 0x5c, 0xcd, + 0xc0, 0xa2, 0x2c, 0x84, 0xdd, 0x35, 0x73, 0x0f, 0x84, 0xff, 0x12, 0xdb, 0x25, 0x2d, 0x8d, 0xb8, 0x37, 0x10, 0xdf, + 0xdb, 0x6e, 0x27, 0x49, 0x42, 0x8b, 0x89, 0xb9, 0x12, 0xf1, 0x37, 0xbc, 0x66, 0x0f, 0x1c, 0xbb, 0x71, 0x06, 0x3d, + 0xf7, 0xcb, 0xce, 0x06, 0xc4, 0x8e, 0xdf, 0x33, 0x3b, 0xde, 0x71, 0xa5, 0xa0, 0xbb, 0x75, 0x11, 0x76, 0x30, 0xf4, + 0x7f, 0x79, 0x30, 0x27, 0x6e, 0x30, 0x16, 0x4d, 0x36, 0xe0, 0xf6, 0x0d, 0x78, 0x14, 0x74, 0x03, 0x6e, 0xdf, 0x86, + 0xaf, 0x87, 0x56, 0xf6, 0xcd, 0x01, 0x06, 0x64, 0xc2, 0x8e, 0xb4, 0x4a, 0x08, 0x86, 0x79, 0xba, 0xc9, 0x91, 0x59, + 0xb2, 0x0a, 0x87, 0xab, 0x26, 0xb1, 0xd8, 0xd8, 0x0b, 0x15, 0x93, 0x1a, 0x08, 0xc6, 0x22, 0x7d, 0x89, 0x42, 0xa5, + 0x41, 0xdd, 0x38, 0x06, 0xb0, 0xca, 0x69, 0xeb, 0x5f, 0x1e, 0x1c, 0x80, 0xd0, 0x00, 0xac, 0x5d, 0x92, 0xd1, 0xb9, + 0x5e, 0x14, 0xc0, 0x5f, 0x29, 0xff, 0x1b, 0x92, 0xc1, 0xed, 0xc4, 0xa4, 0xc1, 0x0f, 0x48, 0x98, 0x53, 0xa5, 0xf8, + 0x17, 0x9b, 0xe6, 0x7e, 0xe3, 0x82, 0x78, 0x8c, 0x56, 0x96, 0x53, 0x94, 0xa8, 0x2b, 0x1d, 0xba, 0xd6, 0x21, 0xf7, + 0xf4, 0x0b, 0x13, 0xfa, 0x25, 0x57, 0x9a, 0x09, 0x00, 0x40, 0x85, 0x78, 0x30, 0x25, 0x85, 0x60, 0xeb, 0xd6, 0x6a, + 0xd1, 0xd1, 0xe8, 0xbb, 0x55, 0x74, 0x9d, 0x2d, 0x9a, 0x52, 0x31, 0xca, 0x6d, 0x27, 0xa1, 0xcd, 0xa4, 0xb7, 0x13, + 0x2d, 0x4b, 0x86, 0x16, 0x3b, 0x15, 0xfb, 0x61, 0x68, 0x7d, 0x2c, 0x88, 0x3f, 0x17, 0xfc, 0x59, 0xfa, 0x5d, 0x3e, + 0x06, 0xae, 0xd4, 0xbf, 0xb1, 0x0a, 0xe1, 0x4c, 0xb0, 0x0e, 0xc8, 0x6b, 0x52, 0x1f, 0xa7, 0x47, 0x9d, 0x7c, 0x4b, + 0xb9, 0x50, 0x1a, 0x85, 0x6d, 0x9c, 0x14, 0x06, 0x53, 0xce, 0xbe, 0x2d, 0x71, 0xfd, 0xea, 0x8f, 0x11, 0x7f, 0x74, + 0x88, 0x7f, 0x97, 0x4a, 0xa3, 0x65, 0x89, 0x60, 0xc8, 0xef, 0x48, 0xad, 0xe0, 0x2a, 0x36, 0xe7, 0xfa, 0xb9, 0x9e, + 0xe5, 0x1b, 0x9e, 0x38, 0x5d, 0xad, 0x4a, 0xa9, 0x40, 0xc5, 0x37, 0x0c, 0x3f, 0x61, 0x70, 0x6f, 0xfc, 0x8c, 0x07, + 0x55, 0xb6, 0xef, 0x8b, 0x9f, 0x05, 0xf7, 0xc5, 0xcf, 0x78, 0xba, 0x5d, 0x34, 0xb8, 0x27, 0xee, 0x24, 0xe7, 0x49, + 0x2b, 0xf2, 0x7c, 0xd4, 0x94, 0x56, 0xfe, 0x95, 0x76, 0x6b, 0xe0, 0xca, 0x26, 0x0e, 0x8c, 0xf3, 0xea, 0x22, 0x14, + 0x73, 0xe6, 0x8c, 0x96, 0xc3, 0xff, 0xd6, 0x3a, 0xb9, 0x93, 0x47, 0x5a, 0x29, 0xe4, 0x0d, 0x2d, 0xf4, 0x3d, 0xd8, + 0x70, 0xc5, 0x96, 0x0f, 0x20, 0x25, 0xa0, 0x6c, 0xfb, 0xf7, 0xba, 0x08, 0xc4, 0x71, 0x65, 0x9d, 0x8f, 0xc2, 0xf6, + 0x49, 0x51, 0x72, 0x75, 0x75, 0x21, 0xe4, 0xd6, 0x68, 0x09, 0x10, 0xa6, 0xde, 0x35, 0x8f, 0x39, 0x9a, 0xcc, 0xd2, + 0xe5, 0xba, 0x54, 0x1d, 0x14, 0x96, 0xab, 0xe3, 0x08, 0x17, 0x6b, 0x73, 0x83, 0xfe, 0x8a, 0xe3, 0xbf, 0xb9, 0xa3, + 0x91, 0x9f, 0x4a, 0x0a, 0xf4, 0x68, 0xb7, 0xaf, 0xcd, 0x0e, 0x12, 0x69, 0xe7, 0x50, 0x5a, 0x0a, 0x00, 0x56, 0x1b, + 0x7c, 0x5d, 0x7b, 0x9c, 0x7a, 0x22, 0xdd, 0x6c, 0xbe, 0x69, 0x08, 0x8b, 0x59, 0x69, 0xc1, 0x63, 0xba, 0xd9, 0x61, + 0x39, 0xea, 0x65, 0x71, 0x5d, 0xee, 0xb1, 0x5a, 0xbf, 0xe8, 0x1b, 0xa0, 0xac, 0x0c, 0xd1, 0x56, 0xab, 0xb8, 0x0e, + 0x6f, 0x22, 0x82, 0x6b, 0x10, 0x84, 0x45, 0x60, 0xc0, 0x51, 0x63, 0xbc, 0x6d, 0x9d, 0x18, 0x6d, 0xda, 0x2f, 0x79, + 0xd6, 0xbd, 0x36, 0x8e, 0x50, 0xd1, 0x60, 0xab, 0x87, 0x9a, 0x07, 0x6c, 0x67, 0x57, 0x76, 0x14, 0x40, 0x68, 0x4a, + 0xbd, 0x71, 0x6e, 0x65, 0x45, 0xbb, 0x03, 0xbe, 0xe8, 0x3b, 0xe6, 0xb9, 0x0e, 0x74, 0xdb, 0xf9, 0x81, 0x6d, 0xd3, + 0x13, 0xf9, 0x2d, 0xdb, 0xa6, 0x1a, 0x27, 0xbc, 0xdf, 0x42, 0xdf, 0x37, 0x84, 0xb5, 0x7d, 0xed, 0x2e, 0xf2, 0xbf, + 0xd0, 0x5d, 0x1b, 0xd0, 0xd3, 0x82, 0xd9, 0xd3, 0x98, 0x0f, 0x7a, 0xbd, 0xfe, 0x54, 0xfa, 0x2f, 0x18, 0x5b, 0xa1, + 0x4f, 0x76, 0x17, 0x38, 0xb1, 0xd2, 0x38, 0x04, 0xc7, 0xaf, 0x38, 0x99, 0xe4, 0x72, 0x48, 0xf3, 0x77, 0xd0, 0x63, + 0x95, 0xfb, 0xfc, 0x6e, 0x54, 0x50, 0xcd, 0x1c, 0xad, 0xa9, 0x46, 0xf1, 0x8a, 0x07, 0xc3, 0x78, 0xc5, 0x2d, 0xe5, + 0xae, 0x5a, 0xc0, 0xcb, 0x97, 0x65, 0x13, 0xe9, 0xa7, 0x75, 0x29, 0x83, 0xa9, 0xdd, 0xbd, 0x6c, 0x92, 0x34, 0x56, + 0x92, 0x34, 0xa6, 0xe2, 0xcd, 0xa6, 0xe2, 0xf8, 0xef, 0x6f, 0x0c, 0x76, 0x9b, 0xcc, 0xfd, 0x1d, 0x90, 0xb9, 0xbf, + 0x79, 0xfa, 0xdd, 0x5a, 0x01, 0xc5, 0x3b, 0x4e, 0x8e, 0x8d, 0x65, 0x8c, 0x1d, 0xf5, 0x5b, 0x0d, 0x06, 0x0d, 0x9a, + 0x5c, 0x06, 0xde, 0x0e, 0xd5, 0xe9, 0xe5, 0xed, 0x8f, 0xe2, 0x6c, 0xa1, 0xb4, 0x9c, 0xb9, 0x46, 0x95, 0xf3, 0x71, + 0x32, 0x99, 0xa0, 0xc0, 0x36, 0x77, 0xf8, 0x69, 0xdd, 0x8d, 0x6c, 0xf9, 0x99, 0x8b, 0x51, 0xaa, 0xb0, 0x3b, 0x5b, + 0x54, 0x2a, 0xd7, 0xc4, 0x9b, 0x39, 0x6f, 0xe7, 0xe1, 0x31, 0x17, 0x5c, 0x4d, 0x59, 0x11, 0x17, 0x68, 0xf9, 0xad, + 0xce, 0x0a, 0xb8, 0xcd, 0xb1, 0x9d, 0xe1, 0x51, 0x69, 0x39, 0xa0, 0x13, 0x68, 0x0d, 0x74, 0x46, 0x33, 0xa6, 0xa7, + 0x72, 0x04, 0x86, 0x2f, 0xc9, 0xa8, 0x74, 0xa7, 0x3a, 0x38, 0xd8, 0x8f, 0x23, 0xa3, 0xbf, 0x00, 0x1f, 0xf4, 0x30, + 0x07, 0xf5, 0x96, 0xe0, 0x18, 0x54, 0x75, 0xcd, 0xd0, 0x92, 0x6d, 0xfa, 0xd0, 0xe8, 0xe4, 0x33, 0xbb, 0xc3, 0x1c, + 0xad, 0xd7, 0xa9, 0x1d, 0x75, 0x34, 0xe6, 0x2c, 0x1f, 0x45, 0xf8, 0x33, 0xbb, 0x4b, 0x4b, 0xb7, 0x75, 0xe3, 0x65, + 0x6d, 0x16, 0x31, 0x92, 0x37, 0x22, 0xc2, 0x55, 0x27, 0xe9, 0x72, 0x8d, 0x65, 0xc1, 0x27, 0x80, 0xa3, 0xbf, 0xb0, + 0xbb, 0xd4, 0xb5, 0x17, 0xb8, 0x0a, 0xa2, 0xa5, 0x07, 0x7d, 0x12, 0x24, 0x87, 0xcb, 0xe0, 0x04, 0x8e, 0xbe, 0xa9, + 0x3b, 0x20, 0xb5, 0x72, 0x95, 0x08, 0x89, 0xd0, 0xfa, 0xdf, 0x9d, 0x0a, 0x5e, 0x84, 0xe7, 0x9c, 0xae, 0x59, 0xdc, + 0x6e, 0x54, 0x62, 0x50, 0xa1, 0xb2, 0x20, 0xf9, 0x18, 0x73, 0xbf, 0xfb, 0x9c, 0xf7, 0x43, 0xa0, 0x33, 0x5b, 0x50, + 0xd7, 0x68, 0x3a, 0x32, 0xbf, 0x50, 0x75, 0x07, 0x35, 0xd3, 0x55, 0xc5, 0xbd, 0x8f, 0x31, 0x00, 0x1e, 0xac, 0x65, + 0xa8, 0x71, 0x08, 0x5d, 0x7b, 0x33, 0xd5, 0x31, 0x25, 0xf1, 0xd2, 0xcf, 0x21, 0xe5, 0x21, 0x18, 0xf5, 0x1a, 0xd0, + 0xd0, 0x21, 0x98, 0xb5, 0x3c, 0xe4, 0xe3, 0x58, 0x6c, 0x9d, 0xa1, 0xd2, 0x9c, 0xa1, 0x49, 0x00, 0xf2, 0x6f, 0x9c, + 0x99, 0xcc, 0x40, 0xc3, 0xf0, 0x96, 0xe6, 0x00, 0x74, 0xab, 0xeb, 0x70, 0x28, 0x5c, 0xd1, 0xd2, 0x79, 0xcf, 0x2e, + 0xba, 0xac, 0x0d, 0x2b, 0x36, 0xed, 0xa0, 0x75, 0x0a, 0x53, 0x62, 0xb6, 0xc0, 0xda, 0xeb, 0x7d, 0xb8, 0xb7, 0xab, + 0x8d, 0x8b, 0xc4, 0x4f, 0x8b, 0x78, 0x98, 0xc4, 0x14, 0x2d, 0x79, 0x4c, 0xb1, 0x04, 0x3b, 0xc8, 0x62, 0x5d, 0x8e, + 0x9f, 0x85, 0xcb, 0x51, 0xb3, 0x92, 0xde, 0xed, 0x60, 0x08, 0x5c, 0xbe, 0x06, 0xdb, 0x50, 0xcc, 0x3d, 0x61, 0xe1, + 0xb1, 0xf1, 0xf4, 0x0b, 0xd6, 0x6d, 0x6e, 0x17, 0xc4, 0xaf, 0xc0, 0x98, 0xc6, 0xcb, 0x60, 0x16, 0xa1, 0x53, 0xb9, + 0x73, 0x38, 0x74, 0xd7, 0x84, 0x95, 0xf1, 0x6a, 0xac, 0xc8, 0xc6, 0xd1, 0xf3, 0x7d, 0x1b, 0xcf, 0x7f, 0x16, 0xac, + 0xb8, 0xbb, 0x62, 0x60, 0x63, 0x2d, 0xc1, 0xdd, 0xb8, 0x5a, 0x86, 0xca, 0x40, 0xbe, 0x27, 0x0d, 0xeb, 0xb2, 0xc6, + 0xdf, 0x8d, 0x8a, 0xb1, 0x36, 0xf7, 0x94, 0x81, 0xb6, 0xc6, 0x6e, 0x17, 0xf6, 0x4d, 0xd7, 0x4d, 0xd6, 0x35, 0x8a, + 0xb8, 0x0a, 0xd2, 0xee, 0x6e, 0x01, 0x17, 0xa1, 0x3f, 0x6c, 0x5f, 0x0d, 0x36, 0x55, 0x37, 0x90, 0x04, 0xd7, 0x7e, + 0xf2, 0xdb, 0x53, 0xdd, 0x65, 0xad, 0xfb, 0xed, 0xa9, 0xd6, 0x2e, 0x0b, 0x8d, 0x21, 0x11, 0x76, 0xfd, 0x94, 0xfe, + 0xd3, 0x62, 0xbd, 0x46, 0x6b, 0x18, 0xde, 0x7b, 0xde, 0x8d, 0xe3, 0xf7, 0xde, 0x42, 0x31, 0x81, 0x8b, 0xdc, 0xab, + 0x5c, 0x7a, 0x42, 0x5e, 0x8d, 0xe0, 0x3d, 0xdf, 0x1a, 0xc2, 0x7b, 0x1e, 0x38, 0xbd, 0x82, 0xd4, 0x34, 0x11, 0x6c, + 0xe4, 0xe9, 0x27, 0xb2, 0x48, 0x68, 0xf8, 0xb8, 0xd7, 0x9c, 0x70, 0xfd, 0x57, 0x0a, 0xfc, 0x17, 0x1e, 0x2e, 0xb4, + 0x96, 0x02, 0x73, 0x31, 0x5f, 0x68, 0xac, 0xcc, 0xe8, 0x97, 0x63, 0x29, 0x74, 0x73, 0x4c, 0x67, 0x3c, 0xbf, 0x4b, + 0x17, 0xbc, 0x39, 0x93, 0x42, 0xaa, 0x39, 0xcd, 0x18, 0x56, 0x77, 0x4a, 0xb3, 0x59, 0x73, 0xc1, 0xf1, 0x73, 0x96, + 0x7f, 0x61, 0x9a, 0x67, 0x14, 0xbf, 0x95, 0x43, 0xa9, 0x25, 0x7e, 0x7d, 0x7b, 0x37, 0x61, 0x02, 0xff, 0x3e, 0x5c, + 0x08, 0xbd, 0xc0, 0x8a, 0x0a, 0xd5, 0x54, 0xac, 0xe0, 0xe3, 0x6e, 0xb3, 0x39, 0x2f, 0xf8, 0x8c, 0x16, 0x77, 0xcd, + 0x4c, 0xe6, 0xb2, 0x48, 0xff, 0xab, 0x75, 0x4c, 0x1f, 0x8c, 0x4f, 0xba, 0xba, 0xa0, 0x42, 0x71, 0x58, 0x98, 0x94, + 0xe6, 0xf9, 0xde, 0xf1, 0x69, 0x6b, 0xa6, 0xf6, 0xed, 0x85, 0x1f, 0x15, 0x7a, 0xfd, 0x17, 0xfe, 0x20, 0x61, 0x94, + 0xc9, 0x50, 0x0b, 0x37, 0xc8, 0x65, 0xb6, 0x28, 0x94, 0x2c, 0xd2, 0xb9, 0xe4, 0x42, 0xb3, 0xa2, 0x3b, 0x94, 0xc5, + 0x88, 0x15, 0xcd, 0x82, 0x8e, 0xf8, 0x42, 0xa5, 0x27, 0xf3, 0xdb, 0x6e, 0xbd, 0x07, 0x9b, 0x9f, 0x0a, 0x29, 0x58, + 0x17, 0xf8, 0x8d, 0x49, 0x21, 0x17, 0x62, 0xe4, 0x86, 0xb1, 0x10, 0x8a, 0xe9, 0xee, 0x9c, 0x8e, 0xc0, 0x0e, 0x38, + 0x3d, 0x9f, 0xdf, 0x76, 0xcd, 0xac, 0x6f, 0x18, 0x9f, 0x4c, 0x75, 0x7a, 0xda, 0x6a, 0xd9, 0x6f, 0xc5, 0xbf, 0xb2, + 0xb4, 0xdd, 0x49, 0x3a, 0xa7, 0xf3, 0x5b, 0xe0, 0xe0, 0x35, 0x2b, 0x9a, 0x00, 0x0b, 0xa8, 0xd4, 0x4e, 0x5a, 0x0f, + 0x8e, 0xef, 0x43, 0x06, 0xd8, 0x38, 0x34, 0xcd, 0x84, 0xc0, 0xd8, 0x3d, 0x5d, 0xcc, 0xe7, 0xac, 0x00, 0x2f, 0xfa, + 0xee, 0x8c, 0x16, 0x13, 0x2e, 0x9a, 0x85, 0x69, 0xb4, 0x79, 0x3e, 0xbf, 0x5d, 0xc3, 0x7c, 0x52, 0x6b, 0xb6, 0xea, + 0xa6, 0xe5, 0xbe, 0x96, 0xc1, 0x10, 0x4d, 0x4c, 0x9a, 0xb4, 0x98, 0x0c, 0x69, 0xdc, 0xee, 0xdc, 0xc7, 0xfe, 0x7f, + 0x49, 0x07, 0x05, 0x60, 0x6b, 0x8e, 0x16, 0x85, 0xb9, 0x45, 0x4d, 0xdb, 0xca, 0x36, 0x3b, 0x95, 0x5f, 0x58, 0xe1, + 0x5b, 0x35, 0x1f, 0xcb, 0xad, 0x79, 0xff, 0x27, 0x8d, 0xfe, 0x85, 0x27, 0x14, 0xd6, 0xc0, 0x20, 0x47, 0xdf, 0xc8, + 0x83, 0x30, 0xd3, 0xc1, 0xf2, 0x86, 0x8f, 0xf4, 0x34, 0x6d, 0xb7, 0x5a, 0x3f, 0x54, 0x2b, 0xd6, 0x9d, 0x5a, 0xd0, + 0xb5, 0x0b, 0x36, 0xab, 0xad, 0xe3, 0x8c, 0x96, 0xd8, 0xb6, 0x9c, 0x4b, 0xb7, 0xe4, 0x05, 0xcb, 0x4d, 0x34, 0x99, + 0xb5, 0x43, 0xb9, 0xad, 0x71, 0x72, 0x31, 0x65, 0x05, 0xd7, 0xdd, 0xfa, 0x57, 0xd5, 0xf1, 0xf6, 0xea, 0xaf, 0xad, + 0x1c, 0xba, 0xb4, 0x35, 0xdc, 0xa5, 0xe7, 0x63, 0xf8, 0xd8, 0x5e, 0xfd, 0x2f, 0xb4, 0x88, 0x37, 0x10, 0x13, 0x87, + 0x35, 0xd0, 0x3a, 0x98, 0x73, 0x01, 0x26, 0x99, 0x03, 0xfc, 0x0d, 0x28, 0x64, 0x34, 0xcf, 0x62, 0x18, 0xd1, 0x5e, + 0x73, 0xef, 0xb8, 0x60, 0x33, 0xe4, 0x01, 0x91, 0xdc, 0x3f, 0x2d, 0xd8, 0x6c, 0x9d, 0x98, 0xea, 0x4b, 0x83, 0x22, + 0x34, 0xe7, 0x13, 0x91, 0x66, 0x0c, 0xd0, 0x77, 0x9d, 0x30, 0xa1, 0xb9, 0xbe, 0x6b, 0x16, 0xf2, 0x66, 0x39, 0xe2, + 0x6a, 0x9e, 0xd3, 0xbb, 0x74, 0x9c, 0xb3, 0xdb, 0xae, 0x29, 0xd5, 0xe4, 0x9a, 0xcd, 0x94, 0x2b, 0xdb, 0x85, 0xf4, + 0xe6, 0xc8, 0x9a, 0x4d, 0x00, 0xf4, 0xe4, 0xcd, 0xe6, 0xfe, 0x49, 0x8e, 0xd5, 0x1e, 0xa3, 0x8a, 0x35, 0xe5, 0x42, + 0xef, 0xb5, 0x54, 0x77, 0xc6, 0x45, 0xd3, 0x0d, 0xe4, 0xa4, 0x35, 0xbf, 0xed, 0x6e, 0x43, 0x3e, 0xe8, 0x3f, 0x61, + 0xb7, 0x73, 0x2a, 0x46, 0x6c, 0xb4, 0x0c, 0xaa, 0x75, 0xa0, 0x5e, 0x58, 0x2a, 0x15, 0x7a, 0xda, 0x34, 0xb6, 0x5e, + 0x71, 0x47, 0xa0, 0x6f, 0xa0, 0xd6, 0x83, 0x16, 0xb6, 0xff, 0x9f, 0xb4, 0x51, 0x58, 0x79, 0x0f, 0xc2, 0x2e, 0xf1, + 0xf1, 0x5d, 0x13, 0xfe, 0x2e, 0xc1, 0xb7, 0x88, 0x67, 0x34, 0x77, 0x10, 0x99, 0xf1, 0xd1, 0x28, 0xaf, 0x8d, 0xe8, + 0x32, 0xe8, 0xac, 0x8d, 0x96, 0x30, 0xff, 0xb4, 0xb5, 0xd7, 0xda, 0x33, 0x73, 0x71, 0xdb, 0xfc, 0xe4, 0xe4, 0xfe, + 0xf1, 0x03, 0xd6, 0xcd, 0xb9, 0x60, 0xb5, 0xa9, 0x7e, 0x17, 0xd4, 0x61, 0xc3, 0x1d, 0xd7, 0x70, 0x7b, 0xaf, 0xbd, + 0x77, 0xd2, 0xfa, 0xc1, 0xef, 0xd6, 0x9c, 0x8d, 0x75, 0xda, 0x3e, 0x9b, 0xdf, 0xd6, 0xb7, 0xef, 0xb9, 0x6f, 0xfa, + 0xa6, 0xa0, 0xf3, 0x54, 0x48, 0xf8, 0xd3, 0x85, 0x4d, 0x36, 0xce, 0xe5, 0x4d, 0x3a, 0xe5, 0xa3, 0x11, 0x13, 0xb6, + 0x40, 0x99, 0xc8, 0xf2, 0x9c, 0xcf, 0x15, 0xb7, 0xab, 0xe1, 0x70, 0xf7, 0x74, 0x03, 0xaa, 0xe1, 0x80, 0x8e, 0x83, + 0x01, 0x9d, 0x56, 0x03, 0xaa, 0xfa, 0x0f, 0x47, 0xd8, 0xd9, 0x98, 0xab, 0x29, 0xd5, 0xad, 0x61, 0xd2, 0xdf, 0x0b, + 0xa5, 0x01, 0xe6, 0xde, 0x48, 0xc3, 0x50, 0xf1, 0xe6, 0x90, 0xe9, 0x1b, 0xc6, 0xc4, 0xb7, 0x07, 0x71, 0x99, 0x4a, + 0x91, 0xdf, 0xd9, 0xcf, 0x65, 0xd8, 0x25, 0x5d, 0x68, 0xb9, 0x4e, 0x86, 0x5c, 0xd0, 0xe2, 0xee, 0x5a, 0x31, 0xa1, + 0x64, 0x71, 0x2d, 0xc7, 0xe3, 0xe5, 0xb7, 0x48, 0xcb, 0x7d, 0xb4, 0x4e, 0x14, 0x17, 0x93, 0x9c, 0x59, 0xa2, 0x64, + 0x10, 0xc1, 0x11, 0x73, 0xdb, 0xae, 0x69, 0xb2, 0x36, 0xe8, 0x70, 0xe7, 0x99, 0x76, 0x07, 0x69, 0xda, 0xbc, 0x61, + 0xc3, 0xcf, 0x5c, 0x5b, 0x3c, 0x6b, 0xaa, 0x1b, 0xf0, 0x78, 0x31, 0xcb, 0x30, 0x67, 0xc5, 0xd2, 0xd3, 0xf0, 0x56, + 0x8d, 0xea, 0x5c, 0x09, 0x73, 0x7a, 0x68, 0x3a, 0x6c, 0x42, 0xfc, 0x2f, 0x56, 0x94, 0x7b, 0x8c, 0x0b, 0x83, 0x31, + 0x06, 0x40, 0x9b, 0xbb, 0x24, 0x3c, 0x03, 0x4e, 0x5a, 0x2d, 0x7f, 0x3e, 0x34, 0x6d, 0x9d, 0xb4, 0x9d, 0x9c, 0xb2, + 0xd9, 0xae, 0xfd, 0x59, 0x27, 0x46, 0xed, 0xce, 0xfc, 0x76, 0xcf, 0xfc, 0xd3, 0xda, 0x6b, 0x6d, 0x13, 0x9f, 0x6d, + 0x38, 0x1d, 0x23, 0xbf, 0xb2, 0x5a, 0xce, 0xd3, 0x36, 0x9b, 0x75, 0x17, 0x0a, 0x0e, 0x1a, 0x43, 0x1b, 0xcd, 0x01, + 0xb6, 0x36, 0x33, 0x81, 0x75, 0xa4, 0x5c, 0x00, 0x5d, 0xb7, 0x67, 0x1b, 0xf4, 0xa1, 0x24, 0x18, 0x62, 0xef, 0x6c, + 0xb4, 0x3e, 0xac, 0xd6, 0x5e, 0x35, 0x30, 0xf8, 0x67, 0xfd, 0x57, 0xc5, 0x19, 0xbe, 0x60, 0x01, 0x67, 0xce, 0x1b, + 0xc9, 0xe9, 0xaa, 0xe5, 0xb8, 0xf1, 0x91, 0xae, 0x84, 0x04, 0xe3, 0xcb, 0x30, 0xa3, 0xb7, 0xd6, 0xa9, 0x61, 0xc6, + 0x05, 0x98, 0x4c, 0x21, 0xac, 0x03, 0xe3, 0xf2, 0x69, 0xd8, 0xd0, 0x48, 0xc7, 0xd0, 0xf0, 0x61, 0x27, 0x39, 0x3d, + 0x45, 0xb8, 0x85, 0x3b, 0xa7, 0xa7, 0x81, 0x34, 0x30, 0xd6, 0xbb, 0x8a, 0xee, 0x2a, 0xa9, 0x76, 0x94, 0x3c, 0x32, + 0x8d, 0x1e, 0xb5, 0x5b, 0x2d, 0x6c, 0x1c, 0xb7, 0xcb, 0xc2, 0x5c, 0xed, 0x68, 0xb6, 0xdd, 0x6a, 0x41, 0xb3, 0xf0, + 0xc7, 0xcd, 0xeb, 0x17, 0xb2, 0x6c, 0xa5, 0x2d, 0xdc, 0x4e, 0xdb, 0xb8, 0x93, 0x76, 0xf0, 0x71, 0x7a, 0x8c, 0x4f, + 0xd2, 0x13, 0x7c, 0x9a, 0x9e, 0xe2, 0xb3, 0xf4, 0x0c, 0xdf, 0x4f, 0xef, 0xe3, 0xf3, 0xf4, 0x1c, 0x3f, 0x48, 0x1f, + 0xe0, 0x87, 0x69, 0xbb, 0x85, 0x1f, 0xa5, 0xed, 0x36, 0x7e, 0x9c, 0xb6, 0x3b, 0xf8, 0x49, 0xda, 0x3e, 0xc6, 0x4f, + 0xd3, 0xf6, 0x09, 0x7e, 0x96, 0xb6, 0x4f, 0x31, 0x85, 0xdc, 0x21, 0xe4, 0x66, 0x90, 0x3b, 0x82, 0x5c, 0x06, 0xb9, + 0xe3, 0xb4, 0x7d, 0xba, 0xc6, 0xca, 0x06, 0x7b, 0x88, 0x5a, 0xed, 0xce, 0xf1, 0xc9, 0xe9, 0xd9, 0xfd, 0xf3, 0x07, + 0x0f, 0x1f, 0x3d, 0x7e, 0xf2, 0xf4, 0x59, 0x34, 0xc0, 0x43, 0xe3, 0x73, 0xa1, 0x44, 0x9f, 0x1f, 0xb4, 0x4f, 0x07, + 0xf8, 0xda, 0x7f, 0xc6, 0xfc, 0xa0, 0x73, 0xd2, 0x42, 0x97, 0x97, 0x27, 0x83, 0x46, 0x99, 0xfb, 0xde, 0xb8, 0x7a, + 0x54, 0x59, 0x84, 0x90, 0x18, 0x72, 0x10, 0xbe, 0x33, 0xf5, 0xde, 0xb3, 0x98, 0x27, 0x05, 0x3a, 0x38, 0x30, 0x3f, + 0x26, 0xfe, 0xc7, 0xd0, 0xff, 0xa0, 0xc1, 0x22, 0xdd, 0xd2, 0xd8, 0xf9, 0xfa, 0xea, 0xd2, 0xd2, 0xbe, 0x34, 0x62, + 0xd9, 0xe3, 0xce, 0x9c, 0xfc, 0xbf, 0x22, 0x6b, 0x2e, 0x42, 0x4e, 0xac, 0x4a, 0xe6, 0xb4, 0xc7, 0xc8, 0xb2, 0x48, + 0x3b, 0xa7, 0xa7, 0x07, 0xbf, 0xf4, 0x79, 0xbf, 0x3d, 0x18, 0x1c, 0xb6, 0xef, 0xe3, 0x49, 0x99, 0xd0, 0xb1, 0x09, + 0xc3, 0x32, 0xe1, 0xd8, 0x26, 0xd0, 0xd4, 0xd6, 0x86, 0xa4, 0x13, 0x93, 0x04, 0x25, 0xd6, 0xa9, 0x69, 0xfb, 0xbe, + 0x6d, 0xfb, 0x01, 0xd8, 0x31, 0x99, 0xe6, 0x5d, 0xd3, 0x17, 0x17, 0x27, 0x2b, 0xd7, 0x28, 0x9e, 0xa4, 0xae, 0x35, + 0x9f, 0x78, 0x32, 0x18, 0xe0, 0xa1, 0x49, 0x3c, 0xad, 0x12, 0xcf, 0x06, 0x03, 0xd7, 0xd5, 0x03, 0xd3, 0xd5, 0xfd, + 0x2a, 0xeb, 0x7c, 0x30, 0x30, 0x5d, 0x22, 0xe7, 0xb5, 0xae, 0xf4, 0xde, 0x97, 0x52, 0x73, 0xc0, 0x2f, 0x3a, 0xa7, + 0xa7, 0x3d, 0xc0, 0x30, 0x63, 0x8d, 0xea, 0x61, 0x74, 0x13, 0xc0, 0xe8, 0x0e, 0x7e, 0xf7, 0x86, 0x34, 0xbd, 0xa6, + 0x25, 0x90, 0x7a, 0xd1, 0x7f, 0x45, 0x0d, 0x6d, 0x60, 0x6e, 0xfe, 0x4c, 0xec, 0x9f, 0x21, 0x6a, 0x7c, 0xa1, 0x00, + 0x6e, 0xd0, 0x85, 0x78, 0x65, 0xa6, 0xe9, 0xf1, 0x33, 0x05, 0xe7, 0x92, 0xa9, 0xca, 0x69, 0x6f, 0x35, 0xbd, 0x19, + 0xae, 0xa6, 0xea, 0x0b, 0xfa, 0x33, 0xfe, 0x53, 0x1d, 0xc6, 0xfd, 0x66, 0x23, 0x61, 0x7f, 0x8e, 0xc0, 0x8b, 0xa5, + 0x97, 0x8e, 0xd8, 0x04, 0xf5, 0xfa, 0x7f, 0x2a, 0x3c, 0x68, 0x04, 0x19, 0x3f, 0x6c, 0xa7, 0x80, 0x8f, 0xcb, 0x66, + 0x62, 0xfc, 0x03, 0xea, 0xa1, 0xde, 0x9f, 0xea, 0xf0, 0x4f, 0x74, 0xef, 0xa8, 0x9a, 0xcb, 0xef, 0xd2, 0x6d, 0xe1, + 0x2a, 0xf0, 0xcd, 0x61, 0xb9, 0x85, 0x19, 0x6e, 0x37, 0x19, 0x84, 0x09, 0x03, 0x27, 0x68, 0x12, 0xcb, 0x06, 0x3f, + 0x3a, 0x6e, 0xa1, 0x1f, 0xda, 0x1d, 0x10, 0xeb, 0x9b, 0xe2, 0x70, 0x7b, 0xd3, 0x17, 0xcd, 0x63, 0xfc, 0xa0, 0x59, + 0xe0, 0x36, 0xc2, 0xcd, 0xb6, 0xd7, 0xb7, 0xf6, 0x55, 0xdc, 0x42, 0x58, 0xc5, 0xe7, 0xf0, 0xcf, 0x09, 0x1a, 0x54, + 0x1b, 0xf2, 0x8a, 0x6e, 0xf6, 0x0e, 0x1e, 0x9b, 0x24, 0x56, 0x0d, 0x7e, 0x74, 0xd6, 0x42, 0x3f, 0x9c, 0x99, 0x8e, + 0xd8, 0xa1, 0xde, 0xd1, 0x95, 0xc4, 0x27, 0x4d, 0x09, 0x1d, 0xb5, 0xca, 0x7e, 0x44, 0x7c, 0x8a, 0xb0, 0x88, 0x8f, + 0xe1, 0x9f, 0x76, 0xd8, 0xcf, 0xaf, 0x5b, 0xfd, 0x98, 0x79, 0xb7, 0x71, 0x72, 0x6a, 0x1d, 0x40, 0x95, 0xbd, 0x8d, + 0x6d, 0xb0, 0xcb, 0xb6, 0xb9, 0x46, 0x6a, 0x1f, 0xc1, 0x07, 0xc2, 0xfa, 0x90, 0x28, 0xcc, 0x0e, 0xc1, 0x73, 0x14, + 0x0c, 0x26, 0xd4, 0xc5, 0x71, 0x57, 0x35, 0x1a, 0x48, 0xf4, 0xd5, 0xe0, 0x90, 0xb4, 0x9b, 0xba, 0xc9, 0x30, 0xfc, + 0x6e, 0x90, 0x32, 0x1c, 0x99, 0xa8, 0x7a, 0x7d, 0xec, 0x7a, 0xb5, 0x77, 0xce, 0x1e, 0x3b, 0x08, 0x21, 0xaa, 0x17, + 0xeb, 0x26, 0x43, 0x47, 0xa2, 0x11, 0xeb, 0x0b, 0xd6, 0x3b, 0x4b, 0x5b, 0xc8, 0x60, 0xa7, 0xea, 0xc5, 0xac, 0xc9, + 0x21, 0xbd, 0x93, 0xc6, 0xbc, 0xa9, 0xe1, 0xd7, 0x49, 0x30, 0x0b, 0x01, 0x78, 0x57, 0xf9, 0xc1, 0x14, 0x47, 0x9d, + 0xd3, 0x53, 0x2c, 0x08, 0x4f, 0x26, 0xe6, 0x97, 0x22, 0x3c, 0x19, 0x9a, 0x5f, 0x92, 0x94, 0xf0, 0xb2, 0xbd, 0xe3, + 0x82, 0x04, 0xab, 0x6a, 0x52, 0x28, 0x2c, 0x68, 0x81, 0x8e, 0x3a, 0xfe, 0x42, 0x1a, 0x4f, 0xfd, 0x1c, 0x40, 0x00, + 0x2f, 0x8c, 0x2d, 0xa2, 0x6c, 0x16, 0x38, 0x27, 0xf4, 0x32, 0x39, 0xed, 0x4d, 0x8f, 0xe2, 0x4e, 0x53, 0x36, 0x0b, + 0x94, 0x4e, 0x8f, 0x4c, 0x4d, 0x9c, 0x91, 0xc7, 0xd4, 0xb6, 0x86, 0xa7, 0x70, 0x8b, 0x98, 0x91, 0xec, 0xf0, 0xac, + 0xd5, 0x48, 0x4e, 0x11, 0xee, 0x67, 0xab, 0x16, 0xce, 0x57, 0xab, 0x16, 0xa6, 0xc1, 0x32, 0x3c, 0x16, 0x1e, 0x20, + 0xa5, 0x8e, 0x68, 0x33, 0x2a, 0x4c, 0x8f, 0xc7, 0x1a, 0x6e, 0xc4, 0x35, 0xf8, 0x99, 0x68, 0xf0, 0x80, 0x49, 0xb9, + 0xbb, 0x8a, 0x42, 0x26, 0x2e, 0xde, 0x38, 0xd4, 0x1a, 0xbd, 0x16, 0x7e, 0x5d, 0xbd, 0x4d, 0xa3, 0x88, 0x7f, 0x97, + 0xd8, 0xa6, 0x05, 0xc5, 0xe8, 0x76, 0xb1, 0x5f, 0xe9, 0x56, 0xb1, 0x37, 0x3b, 0x8a, 0x5d, 0x6d, 0x17, 0xfb, 0x28, + 0x03, 0x1d, 0x17, 0xff, 0xe1, 0xf8, 0xac, 0xd5, 0x38, 0x06, 0x64, 0x3d, 0x3e, 0x6b, 0x55, 0x85, 0xee, 0xd1, 0x6a, + 0xad, 0x34, 0xf9, 0x4c, 0xad, 0x95, 0x3f, 0xf7, 0xee, 0xc6, 0x66, 0xe1, 0xac, 0xb3, 0x73, 0xe9, 0xd9, 0xdc, 0x3f, + 0x05, 0x2b, 0x0a, 0x61, 0xa8, 0x9d, 0xee, 0x9f, 0x0d, 0x7a, 0x53, 0x16, 0x37, 0x20, 0x15, 0xa5, 0x63, 0xed, 0x7e, + 0xa1, 0xf2, 0x32, 0xf5, 0xa3, 0x84, 0xa4, 0xce, 0x00, 0x61, 0x49, 0x1a, 0xba, 0x7f, 0x3c, 0x30, 0xe7, 0x5d, 0x01, + 0xbf, 0x4f, 0xcc, 0xef, 0x52, 0x95, 0xe1, 0x5c, 0x01, 0xa6, 0x37, 0xc3, 0xa8, 0x27, 0xc8, 0x6b, 0x1a, 0x1b, 0xeb, + 0x6e, 0x94, 0x96, 0x19, 0xea, 0x0b, 0x64, 0xbc, 0x29, 0x33, 0x04, 0x79, 0x2d, 0xdc, 0x6f, 0xbc, 0x2c, 0x52, 0xb0, + 0xf4, 0xc0, 0x93, 0x14, 0xac, 0x3c, 0xf0, 0x30, 0x15, 0xe0, 0x89, 0x40, 0x53, 0x16, 0xd8, 0x8f, 0x3f, 0x74, 0xba, + 0x23, 0x73, 0xdf, 0x49, 0x0c, 0x96, 0x76, 0x19, 0x9c, 0x14, 0x1f, 0x65, 0x0c, 0x7f, 0x1b, 0x1a, 0x61, 0x06, 0x6d, + 0x32, 0x84, 0x79, 0x52, 0x10, 0x48, 0xc3, 0x3c, 0x99, 0x10, 0x06, 0x4d, 0xf2, 0x64, 0x48, 0x58, 0xbf, 0x13, 0xa0, + 0xc9, 0x53, 0x03, 0x3b, 0x00, 0x0e, 0xaf, 0x5f, 0x21, 0x6b, 0xdb, 0x38, 0xdc, 0x4d, 0x43, 0x13, 0x82, 0x70, 0x15, + 0xc3, 0x2c, 0x60, 0x73, 0x9a, 0x9f, 0x9d, 0x2a, 0xf0, 0x22, 0x4f, 0xa8, 0xa1, 0xde, 0x7f, 0x01, 0x59, 0x8d, 0xef, + 0x2d, 0xd9, 0x1a, 0xef, 0xdd, 0x5b, 0x8a, 0xf5, 0x0f, 0xf0, 0x47, 0xb9, 0x3f, 0xda, 0x9c, 0x7e, 0x6b, 0xf4, 0x57, + 0x0a, 0xc5, 0x76, 0x94, 0x42, 0x7f, 0x79, 0x47, 0x34, 0x45, 0x96, 0xb7, 0x69, 0x34, 0xa2, 0xc5, 0xe7, 0x08, 0x7f, + 0x4a, 0xa3, 0x1c, 0x18, 0xc1, 0x08, 0x7f, 0x4c, 0xa3, 0x82, 0x45, 0xf8, 0x8f, 0x34, 0x1a, 0xe6, 0x8b, 0x08, 0x7f, + 0x48, 0xa3, 0x49, 0x11, 0xe1, 0xf7, 0xa0, 0x26, 0x1c, 0xf1, 0xc5, 0x2c, 0xc2, 0xbf, 0xa7, 0x91, 0x32, 0x76, 0xf8, + 0xf8, 0x61, 0x1a, 0x31, 0x16, 0xe1, 0x77, 0x69, 0x24, 0xf3, 0x08, 0x5f, 0xa5, 0x91, 0x2c, 0x22, 0xfc, 0x28, 0x8d, + 0x0a, 0x1a, 0xe1, 0xc7, 0x69, 0x04, 0x85, 0x26, 0x11, 0x7e, 0x92, 0x46, 0xd0, 0xb2, 0x8a, 0xf0, 0xdb, 0x34, 0xe2, + 0x22, 0xc2, 0xbf, 0xa5, 0x91, 0x5e, 0x14, 0xff, 0x2c, 0x24, 0x57, 0x11, 0x7e, 0x9a, 0x46, 0x53, 0x1e, 0xe1, 0x37, + 0x69, 0x54, 0xc8, 0x08, 0xbf, 0x4e, 0x23, 0x9a, 0x47, 0xf8, 0x55, 0x1a, 0xe5, 0x2c, 0xc2, 0xbf, 0xa6, 0xd1, 0x88, + 0x45, 0xf8, 0x65, 0x1a, 0xdd, 0xb1, 0x3c, 0x97, 0x11, 0x7e, 0x96, 0x46, 0x4c, 0x44, 0xf8, 0x97, 0x34, 0xca, 0xa6, + 0x11, 0xfe, 0x29, 0x8d, 0x68, 0xf1, 0x59, 0x45, 0xf8, 0x79, 0x1a, 0x31, 0x1a, 0xe1, 0x17, 0xb6, 0xa3, 0x49, 0x84, + 0x7f, 0x4e, 0xa3, 0x9b, 0x69, 0xb4, 0xc6, 0x4a, 0x91, 0xe5, 0x6b, 0x9e, 0xb1, 0x3f, 0x58, 0x1a, 0x8d, 0x5b, 0xe3, + 0xf3, 0xf1, 0x38, 0xc2, 0x54, 0x68, 0xfe, 0xcf, 0x82, 0xdd, 0x3c, 0xd5, 0x90, 0x48, 0xd9, 0x70, 0x74, 0x3f, 0xc2, + 0xf4, 0x9f, 0x05, 0x4d, 0xa3, 0xf1, 0xd8, 0x14, 0xf8, 0x67, 0x41, 0x67, 0xb4, 0x78, 0xcb, 0xd2, 0xe8, 0xfe, 0x78, + 0x3c, 0x1e, 0x9d, 0x44, 0x98, 0x7e, 0x5d, 0x7c, 0x34, 0x2d, 0x98, 0x02, 0x43, 0xc6, 0x27, 0x50, 0xf7, 0x74, 0x7c, + 0x3a, 0xca, 0x22, 0x3c, 0xe4, 0xea, 0x9f, 0x05, 0x7c, 0x8f, 0xd9, 0x49, 0x76, 0x12, 0xe1, 0x61, 0x4e, 0xb3, 0xcf, + 0x69, 0xd4, 0x32, 0xbf, 0xc4, 0x2f, 0x6c, 0xf4, 0x7a, 0x26, 0x8d, 0x12, 0x7d, 0xcc, 0x86, 0xd9, 0x28, 0xc2, 0x66, + 0x30, 0x63, 0xf8, 0xfb, 0x85, 0xbf, 0x63, 0x3a, 0x8d, 0xce, 0x69, 0x67, 0xc8, 0x3a, 0x11, 0x1e, 0xbe, 0xb9, 0x11, + 0x69, 0x44, 0x4f, 0x3b, 0xb4, 0x43, 0x23, 0x3c, 0x5c, 0x14, 0xf9, 0xdd, 0x8d, 0x94, 0x23, 0x00, 0xc2, 0xf0, 0xfc, + 0xfc, 0x7e, 0x84, 0x33, 0xfa, 0xab, 0x86, 0xda, 0xa7, 0xe3, 0x07, 0x8c, 0xb6, 0x22, 0xfc, 0x0b, 0x2d, 0xf4, 0xc7, + 0x85, 0x72, 0x03, 0x6d, 0x41, 0x8a, 0xcc, 0xde, 0x81, 0x82, 0x39, 0x1a, 0x75, 0xce, 0x1e, 0xb4, 0x59, 0x84, 0xb3, + 0xab, 0xd7, 0xd0, 0xdb, 0xfd, 0xf1, 0x69, 0x0b, 0x3e, 0x04, 0x48, 0x6a, 0xac, 0x80, 0x46, 0xce, 0x4e, 0x1e, 0x9c, + 0xb2, 0x91, 0x49, 0x54, 0x3c, 0xff, 0x6c, 0x66, 0x7f, 0x0e, 0xf3, 0xc9, 0x0a, 0x3e, 0x53, 0x52, 0xa4, 0xd1, 0x28, + 0x6b, 0x9f, 0x1c, 0x43, 0xc2, 0x1d, 0x15, 0x1e, 0x38, 0xb7, 0x50, 0xf5, 0x7c, 0x18, 0xe1, 0x5b, 0x9b, 0x7a, 0x3e, + 0x34, 0x1f, 0x93, 0x77, 0xbf, 0x8a, 0x37, 0xa3, 0x34, 0x1a, 0x9e, 0x9f, 0x9f, 0xb5, 0x20, 0xe1, 0x03, 0xbd, 0x4b, + 0x23, 0xfa, 0x00, 0xfe, 0x83, 0xec, 0x8f, 0xcf, 0xa0, 0x43, 0x18, 0xe1, 0xed, 0xe4, 0x63, 0x98, 0xf3, 0x79, 0x4a, + 0x3f, 0xf3, 0x34, 0x1a, 0x8e, 0x86, 0xf7, 0xcf, 0xa0, 0xde, 0x8c, 0x4e, 0x9e, 0x69, 0x0a, 0xed, 0xb6, 0x5a, 0xa6, + 0xe5, 0x77, 0xfc, 0x0b, 0x33, 0xd5, 0x4f, 0x4f, 0xcf, 0x86, 0x1d, 0x18, 0xc1, 0x15, 0xa8, 0x18, 0x60, 0x3c, 0xe7, + 0x99, 0x69, 0xf0, 0x2a, 0x7b, 0x3a, 0x4a, 0xa3, 0x07, 0x0f, 0x8e, 0x3b, 0x59, 0x16, 0xe1, 0xdb, 0x8f, 0x23, 0x5b, + 0xdb, 0xe4, 0x29, 0x80, 0x7d, 0x1a, 0xb1, 0x07, 0x0f, 0xce, 0xee, 0x53, 0xf8, 0x7e, 0x6e, 0xda, 0x3a, 0x1f, 0x0f, + 0xb3, 0x73, 0x68, 0xeb, 0x77, 0x98, 0xce, 0xc9, 0xf9, 0xf1, 0xc8, 0xf4, 0xf5, 0xbb, 0x19, 0x75, 0x67, 0x7c, 0x32, + 0x3e, 0x31, 0x99, 0x66, 0xa8, 0xe5, 0xe7, 0x6f, 0x2c, 0x8d, 0x32, 0x36, 0x6a, 0x47, 0xf8, 0xd6, 0x2d, 0xdc, 0x83, + 0x93, 0x56, 0x6b, 0x74, 0x1c, 0xe1, 0xd1, 0xc3, 0xf9, 0xfc, 0xad, 0x81, 0x60, 0xfb, 0xe4, 0x81, 0xfd, 0x56, 0x9f, + 0xef, 0xa0, 0xe9, 0xa1, 0x01, 0xda, 0x88, 0xcf, 0x4c, 0xcb, 0x67, 0x0f, 0xe0, 0x3f, 0xf3, 0x6d, 0x9a, 0x2e, 0xbf, + 0xe5, 0x68, 0x62, 0x17, 0xa5, 0xcd, 0x1e, 0xb4, 0xa0, 0xc6, 0x98, 0x7f, 0x1c, 0x16, 0x1c, 0xd0, 0x68, 0xd8, 0x81, + 0xff, 0x8b, 0xf0, 0x38, 0xbf, 0x7a, 0xed, 0x70, 0x76, 0x3c, 0xa6, 0xe3, 0x56, 0x84, 0xc7, 0xf2, 0xa3, 0xd2, 0x1f, + 0x1e, 0x8a, 0x34, 0xea, 0x74, 0xce, 0x87, 0xa6, 0xcc, 0xe2, 0x17, 0xc5, 0x0d, 0x1e, 0xb7, 0x4c, 0x2b, 0x13, 0xfa, + 0x56, 0x0d, 0xaf, 0x24, 0xac, 0x24, 0xfc, 0x17, 0xe1, 0x09, 0xe8, 0xa5, 0x5c, 0x2b, 0xe7, 0x76, 0x3b, 0x4c, 0xde, + 0x19, 0xd4, 0x1c, 0xdd, 0x07, 0x78, 0xf9, 0x65, 0x1c, 0x51, 0x7a, 0xda, 0x69, 0x45, 0xd8, 0x8c, 0xfa, 0xbc, 0x05, + 0xff, 0x45, 0xd8, 0x42, 0xce, 0xc0, 0x75, 0xf2, 0xf1, 0xd9, 0xcb, 0x9b, 0x34, 0xa2, 0xa3, 0xf1, 0x18, 0x96, 0xc4, + 0x4c, 0xc6, 0x17, 0x9b, 0x4a, 0xc1, 0xee, 0x7e, 0xbd, 0x71, 0xdb, 0xc5, 0x24, 0x68, 0x07, 0x9d, 0xb3, 0x07, 0xc3, + 0x93, 0x08, 0xbf, 0x1d, 0x71, 0x2a, 0x60, 0x95, 0xb2, 0xd1, 0x69, 0x76, 0x9a, 0x99, 0x84, 0x89, 0x4c, 0xa3, 0x13, + 0x58, 0xf2, 0x4e, 0x84, 0xf9, 0x97, 0xab, 0x3b, 0x8b, 0x6e, 0x50, 0xdb, 0x21, 0xc8, 0xb8, 0xc5, 0xce, 0xce, 0xb3, + 0x08, 0xe7, 0xf4, 0xcb, 0xb3, 0x5f, 0x8b, 0x34, 0x62, 0x67, 0xec, 0x6c, 0x4c, 0xfd, 0xf7, 0x1f, 0x6a, 0x6a, 0x6a, + 0xb4, 0xc6, 0xa7, 0x90, 0x74, 0x23, 0xcc, 0x58, 0xef, 0x67, 0x63, 0x83, 0x21, 0xaf, 0x66, 0x52, 0x64, 0x4f, 0xc7, + 0x63, 0x69, 0xb1, 0x98, 0xc2, 0x26, 0xfc, 0x04, 0xd0, 0xa6, 0xa3, 0xd1, 0x39, 0x3b, 0x8b, 0xf0, 0x27, 0xbb, 0x4b, + 0xdc, 0x04, 0x3e, 0x59, 0xcc, 0x66, 0x6e, 0xb7, 0x7f, 0xb2, 0x40, 0x81, 0xf9, 0x8e, 0xe9, 0x98, 0x8e, 0x3a, 0x11, + 0xfe, 0x64, 0xe0, 0x32, 0x3a, 0x86, 0xff, 0xa0, 0x00, 0x74, 0xf6, 0xa0, 0xc5, 0xd8, 0x83, 0x96, 0xf9, 0x0a, 0xf3, + 0xdc, 0xcc, 0x87, 0x67, 0x59, 0x3b, 0xc2, 0x9f, 0x1c, 0x3a, 0x8e, 0xc7, 0xb4, 0x05, 0xe8, 0xf8, 0xc9, 0xa1, 0x63, + 0xa7, 0x35, 0xec, 0x50, 0xf3, 0x6d, 0xb1, 0xe6, 0xfc, 0x7e, 0xc6, 0x60, 0x72, 0x9f, 0x2c, 0x42, 0xde, 0xbf, 0x7f, + 0x7e, 0xfe, 0xe0, 0x01, 0x7c, 0x9a, 0xb6, 0xcb, 0x4f, 0xa5, 0x1f, 0xe6, 0x06, 0xc9, 0x5a, 0xd9, 0x09, 0xd0, 0xc9, + 0x4f, 0x66, 0x8c, 0xe3, 0xf1, 0x98, 0xb5, 0x22, 0x9c, 0xf3, 0x19, 0xb3, 0x98, 0x60, 0x7f, 0x9b, 0x8e, 0x8e, 0x3b, + 0xd9, 0xe8, 0xb8, 0x13, 0xe1, 0xfc, 0xed, 0x33, 0x33, 0x9b, 0x16, 0xcc, 0xde, 0x6f, 0x39, 0x8f, 0x35, 0x33, 0xfa, + 0x06, 0x06, 0x09, 0x2b, 0x0d, 0x95, 0xdf, 0x07, 0xf4, 0xf0, 0xec, 0x2c, 0x1b, 0xc1, 0x40, 0xdf, 0x43, 0xb7, 0x00, + 0xc6, 0xf7, 0x76, 0xf3, 0x0d, 0xe9, 0xe9, 0x29, 0x4c, 0xf7, 0xfd, 0x7c, 0x51, 0xcc, 0x5f, 0xa5, 0xd1, 0x83, 0xe3, + 0xfb, 0xad, 0xd1, 0x30, 0xc2, 0xef, 0xdd, 0x04, 0x8f, 0xb3, 0xe1, 0xf1, 0xfd, 0x76, 0x84, 0xdf, 0x9b, 0xfd, 0x76, + 0x7f, 0x78, 0x76, 0x0e, 0xe7, 0xc6, 0x7b, 0x35, 0x2f, 0xde, 0x4e, 0x4c, 0x81, 0x31, 0x7d, 0x00, 0xcd, 0xfe, 0x66, + 0x76, 0xe3, 0xa8, 0x0d, 0x1b, 0xf9, 0xbd, 0xd9, 0x64, 0x06, 0x4f, 0xee, 0xb7, 0x4f, 0xcf, 0x4f, 0x23, 0x3c, 0xe3, + 0x23, 0x01, 0x04, 0xde, 0x6c, 0x94, 0x07, 0xed, 0x07, 0xf7, 0x5b, 0x11, 0x9e, 0xbd, 0xd5, 0xd9, 0x47, 0x3a, 0x33, + 0xd4, 0x78, 0x0c, 0x30, 0x9b, 0x71, 0xa5, 0xef, 0xde, 0x28, 0x47, 0x8f, 0x59, 0x3b, 0xc2, 0x33, 0x99, 0x65, 0x54, + 0xbd, 0xb5, 0x09, 0xc3, 0xd3, 0x08, 0x0b, 0xfa, 0x85, 0xfe, 0x2d, 0xfd, 0x66, 0x1a, 0x31, 0x3a, 0x32, 0x69, 0x06, + 0x87, 0x23, 0xfc, 0x6e, 0x04, 0xd7, 0x60, 0x69, 0x34, 0x1e, 0x8d, 0x4f, 0x01, 0x3c, 0x40, 0x80, 0x2c, 0x76, 0x03, + 0x34, 0xe0, 0x6b, 0xf4, 0x68, 0x98, 0x46, 0x67, 0xc3, 0x73, 0xd6, 0x39, 0x8e, 0x70, 0x49, 0x8d, 0xe8, 0x29, 0xe4, + 0x9b, 0xcf, 0x8f, 0x66, 0x4b, 0x9d, 0xd8, 0x04, 0x03, 0xa0, 0x11, 0xbd, 0xdf, 0x1a, 0x9d, 0x45, 0x78, 0xfe, 0x9a, + 0xf9, 0x3d, 0xc6, 0x18, 0x3b, 0x07, 0x58, 0x42, 0x92, 0x41, 0xa0, 0xf3, 0xf1, 0xf0, 0xc1, 0xb9, 0xf9, 0x06, 0x30, + 0xd0, 0x31, 0x63, 0x00, 0xa4, 0xf9, 0x6b, 0x56, 0x02, 0x62, 0x34, 0xbc, 0xdf, 0x02, 0xfa, 0x32, 0xa7, 0x73, 0x7a, + 0x47, 0x6f, 0x9e, 0xce, 0xcd, 0x9c, 0xc6, 0xa3, 0xd3, 0x08, 0xcf, 0x9f, 0xff, 0x32, 0x5f, 0x8c, 0xc7, 0x66, 0x42, + 0x74, 0xf8, 0x20, 0xc2, 0x73, 0x56, 0x2c, 0x60, 0x8d, 0xce, 0x4f, 0x8f, 0xc7, 0x11, 0x76, 0x68, 0x98, 0xb5, 0xb2, + 0x21, 0xdc, 0xf3, 0x2d, 0x66, 0x69, 0x34, 0x1a, 0xd1, 0xd6, 0x08, 0x6e, 0xfd, 0xe4, 0xcd, 0xaf, 0x85, 0x45, 0x23, + 0x66, 0xf0, 0xc1, 0xad, 0x21, 0xcc, 0x17, 0xe0, 0xf1, 0x71, 0xc8, 0xb2, 0x8c, 0xba, 0xc4, 0xb3, 0xb3, 0xe3, 0x63, + 0xc0, 0x3d, 0x3b, 0x43, 0x8b, 0x20, 0x6f, 0xd4, 0xdd, 0xb0, 0x90, 0x70, 0x74, 0x01, 0x51, 0x05, 0xb2, 0xfa, 0xe6, + 0xee, 0xb5, 0xa1, 0xab, 0xed, 0xb3, 0x07, 0xb0, 0x00, 0x8a, 0x8e, 0x46, 0xaf, 0xec, 0xe1, 0x76, 0x3e, 0x3c, 0x39, + 0x6d, 0x1f, 0x47, 0xd8, 0x6f, 0x04, 0x7a, 0xde, 0xba, 0xdf, 0x81, 0x12, 0x62, 0x74, 0x67, 0x4b, 0x8c, 0x4f, 0xe8, + 0xc9, 0x59, 0x2b, 0xc2, 0x7e, 0x6b, 0xb0, 0xf3, 0xe1, 0xe9, 0x7d, 0xf8, 0x54, 0x53, 0x96, 0xe7, 0x06, 0xbf, 0x4f, + 0x01, 0x2e, 0x8a, 0x3f, 0x13, 0x34, 0x8d, 0x68, 0xeb, 0xb4, 0xd3, 0x19, 0xc1, 0x67, 0xfe, 0x85, 0x15, 0x69, 0x94, + 0xb5, 0xe0, 0xbf, 0x08, 0x07, 0x3b, 0x89, 0x0d, 0x23, 0x6c, 0xf0, 0xee, 0x8c, 0x9e, 0x9a, 0xbd, 0xef, 0x76, 0x55, + 0xeb, 0xbc, 0x05, 0x1b, 0xd6, 0x6d, 0x2a, 0xf7, 0xa5, 0x84, 0xbc, 0x71, 0x24, 0x96, 0x46, 0x38, 0x40, 0xd0, 0xf1, + 0xfd, 0x71, 0x84, 0xfd, 0x8e, 0x3b, 0x39, 0x3b, 0xef, 0x00, 0x29, 0xd3, 0x40, 0x28, 0x46, 0x9d, 0xe1, 0x09, 0x90, + 0x26, 0xcd, 0x5e, 0x5b, 0x3c, 0x89, 0xb0, 0x7e, 0xaa, 0xf4, 0xab, 0x34, 0x1a, 0x9d, 0x0f, 0xc7, 0xa3, 0xf3, 0x08, + 0x6b, 0x39, 0xa3, 0x5a, 0x1a, 0x0a, 0x78, 0x7c, 0x72, 0x3f, 0xc2, 0x06, 0xcd, 0x5b, 0xac, 0x35, 0x6a, 0x45, 0xd8, + 0x1d, 0x25, 0x8c, 0x9d, 0x77, 0x60, 0x5a, 0x3f, 0x3f, 0xd7, 0x80, 0xcb, 0x23, 0x36, 0x3c, 0x8e, 0x70, 0x49, 0xef, + 0x0d, 0x21, 0x82, 0x2f, 0x35, 0x93, 0x9f, 0x1d, 0xeb, 0x01, 0xa4, 0xce, 0x6f, 0x78, 0x58, 0x86, 0x97, 0x37, 0x16, + 0x8d, 0xa8, 0xd9, 0xe2, 0xc1, 0x3d, 0xe8, 0x13, 0x1a, 0x7b, 0xb6, 0x9d, 0x93, 0xe5, 0x1a, 0x97, 0xe1, 0x45, 0x3f, + 0xb3, 0x3b, 0x15, 0x2b, 0x65, 0x38, 0xd9, 0x20, 0x05, 0x5c, 0x00, 0x9c, 0x41, 0xbd, 0xf3, 0x99, 0x04, 0x41, 0x52, + 0x90, 0x56, 0x57, 0x5c, 0x78, 0x3f, 0xce, 0xae, 0x80, 0xa0, 0x03, 0x90, 0x5e, 0x10, 0x4a, 0x34, 0xc4, 0x66, 0xb1, + 0xc2, 0xa4, 0x37, 0x6f, 0x37, 0x32, 0xa5, 0xb4, 0x06, 0xf3, 0x94, 0x50, 0x1f, 0x95, 0x1d, 0x2e, 0x69, 0x21, 0x6e, + 0x11, 0xea, 0x4a, 0x62, 0x62, 0x2c, 0xbf, 0x10, 0x3a, 0x56, 0xaa, 0x5f, 0x0c, 0x70, 0xfb, 0x0c, 0x61, 0x88, 0x5e, + 0x40, 0xfa, 0xf2, 0xf2, 0xb2, 0x7d, 0x76, 0x60, 0x84, 0xbe, 0xcb, 0xcb, 0x73, 0xfb, 0x03, 0xfe, 0x1d, 0x54, 0x11, + 0xa3, 0x61, 0x7c, 0x8f, 0x58, 0xa0, 0xd1, 0x33, 0xfc, 0xf5, 0x23, 0xb6, 0x5a, 0xc5, 0x8f, 0x18, 0x81, 0x19, 0xe3, + 0x47, 0x2c, 0x31, 0xb7, 0x06, 0xd6, 0x37, 0x85, 0xf4, 0x41, 0x73, 0xd6, 0xc2, 0x10, 0xc7, 0xdc, 0x73, 0xde, 0x8f, + 0x58, 0x9f, 0xd7, 0xfd, 0x9a, 0xab, 0xe0, 0xc1, 0x07, 0x07, 0xcb, 0x22, 0xd5, 0x56, 0x4c, 0xd0, 0x56, 0x4c, 0xd0, + 0x56, 0x4c, 0xd0, 0x55, 0xf8, 0xf6, 0x93, 0x1e, 0x48, 0x29, 0x46, 0xd9, 0xe2, 0x78, 0xea, 0x77, 0xa0, 0xf6, 0x00, + 0xed, 0x64, 0xaf, 0x52, 0x76, 0x94, 0xba, 0x8a, 0x9d, 0x0a, 0x8c, 0x9d, 0x89, 0x4e, 0xdb, 0x71, 0xf4, 0xef, 0xa8, + 0x3b, 0x5e, 0xd6, 0xc4, 0xb2, 0x77, 0x3b, 0xc5, 0x32, 0x58, 0x49, 0x23, 0x9a, 0xed, 0xdb, 0x48, 0x18, 0xba, 0x7f, + 0xdf, 0x08, 0x66, 0x55, 0x78, 0xb6, 0x06, 0x24, 0x75, 0x41, 0x0a, 0x39, 0x37, 0x52, 0x5a, 0x81, 0xd2, 0x91, 0x8e, + 0x0b, 0xd0, 0x50, 0x7a, 0x05, 0x65, 0x19, 0x45, 0xb4, 0x61, 0x00, 0xa2, 0xac, 0x8c, 0x66, 0x65, 0xb5, 0x53, 0x10, + 0x5d, 0x40, 0x13, 0x66, 0x24, 0x16, 0x68, 0x40, 0x98, 0x06, 0x84, 0xab, 0x0c, 0xe2, 0x8c, 0xcb, 0x3e, 0x31, 0xd9, + 0xca, 0x64, 0xab, 0x32, 0x5b, 0xfa, 0x6c, 0x2b, 0x24, 0x4a, 0x93, 0x2d, 0xcb, 0x6c, 0x90, 0xd9, 0xf0, 0x24, 0x55, + 0x78, 0x98, 0x4a, 0x2b, 0xaa, 0x55, 0xb2, 0xd5, 0x5b, 0x1a, 0x6a, 0x73, 0x0f, 0x0e, 0xe2, 0x52, 0x4e, 0x32, 0x6a, + 0xe2, 0x7b, 0x4b, 0x9e, 0x14, 0x46, 0x06, 0xe2, 0xc9, 0xc4, 0xfd, 0x1d, 0xae, 0x37, 0x65, 0xa5, 0x62, 0x32, 0xfc, + 0x46, 0x49, 0xf4, 0x97, 0x57, 0xa2, 0x3e, 0xe2, 0x26, 0xfe, 0xcc, 0x05, 0x49, 0x5a, 0xad, 0xe3, 0xf6, 0x71, 0xeb, + 0xbc, 0xc7, 0x0f, 0xdb, 0x9d, 0xe4, 0x41, 0x27, 0x35, 0x8a, 0x88, 0xb9, 0xbc, 0x01, 0x05, 0xcc, 0x51, 0x27, 0x39, + 0x41, 0x87, 0xed, 0xa4, 0x75, 0x7a, 0xda, 0x84, 0x7f, 0xf0, 0x7b, 0x5d, 0x56, 0x3b, 0x69, 0x9d, 0x9c, 0xf6, 0xf8, + 0xd1, 0x46, 0xa5, 0x98, 0x37, 0xa0, 0x20, 0x3a, 0x32, 0x95, 0x30, 0xd4, 0xaf, 0x96, 0xf7, 0xd9, 0x96, 0x9e, 0xe7, + 0xbd, 0x8e, 0x95, 0x55, 0xc5, 0x01, 0x54, 0xfd, 0xd7, 0xc4, 0x00, 0xd1, 0x7f, 0x0d, 0xcb, 0x18, 0xb1, 0xcb, 0x02, + 0x44, 0xed, 0x47, 0x3c, 0x16, 0x0d, 0x76, 0x18, 0xdb, 0x7c, 0x0d, 0x75, 0x9b, 0x10, 0xb7, 0x0d, 0x4f, 0x5c, 0xae, + 0x0a, 0x73, 0x27, 0x08, 0x35, 0x15, 0xe4, 0x0e, 0x5d, 0xae, 0x0c, 0x73, 0x87, 0x08, 0x35, 0x25, 0xe4, 0xd2, 0x94, + 0x27, 0x14, 0x72, 0x74, 0x42, 0x9b, 0x06, 0x92, 0xd5, 0xa2, 0x3c, 0x67, 0x7e, 0xd8, 0x7c, 0x0c, 0xcb, 0x63, 0x08, + 0x8a, 0x13, 0xa4, 0x05, 0xbc, 0xed, 0x51, 0x6a, 0x73, 0x5a, 0xb8, 0x54, 0xe3, 0x40, 0x46, 0x03, 0xfe, 0x39, 0x64, + 0xe6, 0xc1, 0x87, 0x56, 0xef, 0xf8, 0xac, 0x95, 0xb6, 0xc1, 0x49, 0x19, 0x64, 0x6d, 0x61, 0x65, 0x6d, 0xe1, 0x65, + 0x6d, 0xe1, 0x65, 0x6d, 0x10, 0xe0, 0x83, 0xbe, 0xff, 0x91, 0x35, 0xc3, 0x0f, 0x5e, 0x5a, 0x91, 0x58, 0x33, 0x81, + 0x58, 0xaf, 0x56, 0xcb, 0x35, 0xd8, 0xf8, 0x94, 0x35, 0xa4, 0xaa, 0xd4, 0x9f, 0xcb, 0x22, 0x6d, 0xe1, 0x49, 0x0a, + 0x5a, 0xee, 0x16, 0xa6, 0x66, 0x73, 0x7b, 0xaa, 0xb0, 0x19, 0x3f, 0xa6, 0xe7, 0xd5, 0xc9, 0x97, 0xe4, 0xd8, 0x68, + 0x8f, 0x97, 0x45, 0xca, 0x2d, 0xcd, 0xe0, 0x96, 0x66, 0x70, 0x4b, 0x33, 0xa0, 0x11, 0x5c, 0x16, 0x36, 0x65, 0x13, + 0x4a, 0xe0, 0x4a, 0xa0, 0x7f, 0x3c, 0x80, 0xf0, 0x79, 0xb1, 0x26, 0x66, 0xd4, 0x1b, 0x9d, 0xb7, 0x21, 0x5c, 0x98, + 0x2d, 0xa9, 0x13, 0x6a, 0xbc, 0xa6, 0xcb, 0x31, 0x7f, 0xad, 0xa1, 0x7d, 0x02, 0x6f, 0xb9, 0x3c, 0xd4, 0x71, 0x0b, + 0x8c, 0x26, 0xa2, 0x22, 0xea, 0x19, 0xb2, 0x90, 0x1a, 0x9d, 0x8d, 0x33, 0x86, 0xfe, 0xbc, 0xe1, 0x83, 0x6a, 0x29, + 0x41, 0xf8, 0x82, 0xc1, 0x67, 0x56, 0x39, 0xc5, 0x97, 0xb6, 0x9e, 0xce, 0x50, 0xcb, 0x1e, 0x09, 0x5d, 0x30, 0xd8, + 0xf6, 0xd1, 0x96, 0x7a, 0x82, 0x48, 0x65, 0xdc, 0x05, 0x49, 0x15, 0x2f, 0x18, 0xdc, 0x67, 0xc9, 0x2d, 0x35, 0xce, + 0x24, 0x2f, 0xec, 0x9f, 0xaf, 0x34, 0xf0, 0xb6, 0x2b, 0x26, 0x43, 0xef, 0xa4, 0x7a, 0x6d, 0xa2, 0xea, 0x90, 0xfd, + 0x7d, 0x6b, 0x4b, 0x6d, 0xbe, 0x36, 0x8d, 0xa9, 0x4d, 0xa2, 0xc9, 0x86, 0x1d, 0xea, 0xd7, 0xe8, 0x1f, 0xef, 0x2b, + 0x56, 0x4c, 0x86, 0x28, 0xa0, 0xd9, 0x06, 0xac, 0xaa, 0x02, 0x96, 0x72, 0xf5, 0x4a, 0x17, 0x42, 0xe8, 0xdd, 0x8c, + 0x79, 0x5d, 0x4c, 0x86, 0x3b, 0x1f, 0xfd, 0xb0, 0x3d, 0xf6, 0xde, 0xd2, 0xa0, 0x07, 0xaf, 0xda, 0x9e, 0xb2, 0xdb, + 0xef, 0xd5, 0xb9, 0xd9, 0x59, 0x47, 0xe5, 0xdf, 0xab, 0xf3, 0x74, 0x57, 0x9d, 0x19, 0xbf, 0x8d, 0xfd, 0xde, 0xd1, + 0x81, 0x1a, 0xdb, 0x18, 0xe8, 0x4c, 0x86, 0x10, 0xa5, 0x1d, 0xfe, 0xda, 0x58, 0x2a, 0x5d, 0x4f, 0xc2, 0x61, 0x15, + 0x64, 0x2f, 0x39, 0x4d, 0x19, 0xa6, 0xa4, 0x73, 0x58, 0x98, 0x68, 0x2a, 0x22, 0xa1, 0x4d, 0x95, 0x50, 0x9c, 0x93, + 0x38, 0xa6, 0x87, 0x19, 0xc4, 0x84, 0x69, 0xf7, 0x68, 0x1a, 0xd3, 0x46, 0x86, 0x8e, 0xe2, 0x76, 0x83, 0x1e, 0x66, + 0x08, 0x35, 0xda, 0xa0, 0x33, 0x95, 0xa4, 0xdd, 0xcc, 0x21, 0x4a, 0xa4, 0x21, 0xc5, 0xf9, 0xa1, 0x48, 0x8a, 0x86, + 0x3c, 0x54, 0x49, 0xd1, 0x48, 0x4e, 0xb1, 0x48, 0x26, 0x65, 0xf2, 0xc4, 0x24, 0x4f, 0x6c, 0xf2, 0xb0, 0x4c, 0x1e, + 0x9a, 0xe4, 0xa1, 0x4d, 0xa6, 0xa4, 0x38, 0x14, 0x09, 0x6d, 0xc4, 0xed, 0x66, 0x81, 0x0e, 0x61, 0x04, 0x7e, 0xf4, + 0x44, 0x84, 0xc1, 0xb9, 0xd7, 0xc6, 0xba, 0x65, 0x2e, 0x73, 0x17, 0x2e, 0xb3, 0x02, 0x52, 0xe9, 0x72, 0x04, 0x75, + 0x9e, 0x05, 0x60, 0xc2, 0xda, 0xfe, 0xf1, 0xc1, 0xe0, 0xd6, 0x59, 0x2e, 0x45, 0xe0, 0x52, 0x05, 0x56, 0xe0, 0x9f, + 0x9d, 0x23, 0x09, 0x40, 0x75, 0x4d, 0xf3, 0xf9, 0x94, 0x6e, 0xf9, 0xad, 0x16, 0x93, 0xa1, 0xdb, 0x59, 0x65, 0x33, + 0x8c, 0x16, 0x36, 0xc8, 0x72, 0xdd, 0xc3, 0x10, 0x40, 0xed, 0xbd, 0x1a, 0x13, 0x6a, 0x94, 0xe4, 0xb6, 0xc6, 0xa4, + 0x60, 0x77, 0x2a, 0xa3, 0x39, 0x8b, 0xab, 0x03, 0xb8, 0x1a, 0x26, 0x23, 0x2f, 0xc0, 0x16, 0xbd, 0x38, 0x4c, 0x8e, + 0x1b, 0x3a, 0x99, 0x1c, 0x26, 0xa7, 0x0f, 0x1a, 0x3a, 0x19, 0x1e, 0x26, 0xed, 0x76, 0x85, 0xb3, 0x49, 0x41, 0x74, + 0x32, 0x21, 0x1a, 0x34, 0x86, 0xb6, 0x51, 0x39, 0xa7, 0x60, 0x5c, 0xf5, 0x6f, 0x0c, 0xa3, 0xe1, 0x86, 0x21, 0xd8, + 0xc4, 0xc6, 0x9b, 0xdc, 0x1a, 0x43, 0xd8, 0x4d, 0xe7, 0xf4, 0xb4, 0xa9, 0x93, 0x02, 0x6b, 0xbb, 0x92, 0x4d, 0x9d, + 0x4c, 0xb0, 0xb6, 0xcb, 0xd7, 0xd4, 0xc9, 0xd0, 0x36, 0x65, 0x74, 0x80, 0x4c, 0x04, 0xc0, 0x7a, 0xce, 0x02, 0xc8, + 0x77, 0xbc, 0x7b, 0xc8, 0x1a, 0xb4, 0x86, 0xdf, 0x2b, 0xd7, 0xf4, 0x05, 0x15, 0xd5, 0x60, 0x64, 0xc3, 0xbe, 0x55, + 0xb4, 0x5d, 0x35, 0xc9, 0xfe, 0x75, 0xd9, 0xb2, 0xd9, 0x42, 0xea, 0x7a, 0xc1, 0x87, 0x35, 0x0c, 0x71, 0xa5, 0xdc, + 0xc1, 0xfd, 0x8a, 0x92, 0x18, 0xa2, 0xca, 0x99, 0x53, 0x88, 0x13, 0xaf, 0x47, 0x86, 0x24, 0xde, 0x68, 0xac, 0x51, + 0x1c, 0x9c, 0xb7, 0x4f, 0x43, 0xaa, 0xba, 0x15, 0x6a, 0x8e, 0x90, 0x68, 0x21, 0xac, 0x31, 0xe2, 0x28, 0x0a, 0x58, + 0x10, 0xa7, 0xdd, 0xad, 0x1d, 0x10, 0x07, 0x07, 0x9b, 0xe7, 0x85, 0x0f, 0xfa, 0xbf, 0x15, 0xe8, 0xbf, 0xb2, 0x64, + 0xf3, 0x4f, 0x11, 0x59, 0x1b, 0x57, 0x1e, 0x20, 0x8a, 0x0f, 0xfa, 0x74, 0xdf, 0x50, 0xf8, 0x7e, 0x15, 0xf1, 0xce, + 0xe5, 0x34, 0xcf, 0x4c, 0x86, 0xe9, 0x6b, 0x10, 0x8c, 0xed, 0x4d, 0x38, 0xa1, 0xd2, 0x4a, 0xef, 0x5f, 0x76, 0x1c, + 0x74, 0xe2, 0x9e, 0x4a, 0x09, 0x1b, 0xfd, 0x3b, 0xb4, 0x89, 0xad, 0x60, 0xe3, 0xbc, 0xa1, 0x57, 0xab, 0xda, 0xc3, + 0x38, 0xf6, 0xf9, 0x15, 0x74, 0x70, 0xc0, 0xd5, 0x33, 0x30, 0xe3, 0x65, 0x71, 0x23, 0x3c, 0x7c, 0xff, 0xa9, 0x9d, + 0xd6, 0x7f, 0x9b, 0x73, 0x35, 0x0d, 0x0e, 0xba, 0x87, 0xb5, 0xfc, 0x9d, 0x2b, 0xd1, 0xd3, 0x29, 0x77, 0x6b, 0xfd, + 0x77, 0x65, 0x24, 0xbd, 0xf5, 0x44, 0xd3, 0xc1, 0x01, 0xaf, 0x02, 0x25, 0x45, 0x3f, 0x44, 0xa8, 0x67, 0x64, 0x90, + 0x67, 0xb9, 0xa4, 0x70, 0x23, 0x0a, 0x57, 0x0c, 0x69, 0x83, 0x1f, 0x69, 0xfc, 0x87, 0xfc, 0xff, 0xd4, 0xc8, 0xa1, + 0x4e, 0x1b, 0x3c, 0x10, 0xc0, 0x42, 0x56, 0xa8, 0x0a, 0x51, 0x68, 0x20, 0x1d, 0xda, 0x3c, 0xa3, 0xf2, 0x30, 0xa7, + 0xf3, 0x79, 0x7e, 0x67, 0x5e, 0xa9, 0x0a, 0x38, 0xaa, 0xea, 0xa2, 0xc9, 0xc5, 0x87, 0xc3, 0x05, 0xf0, 0xf4, 0x80, + 0x7b, 0xc8, 0xf8, 0x77, 0x96, 0x97, 0xdb, 0x02, 0x81, 0x64, 0xa6, 0x88, 0x6c, 0xb6, 0xbb, 0xea, 0x12, 0xe4, 0xb2, + 0x66, 0x13, 0x69, 0x17, 0x36, 0x1b, 0x73, 0x90, 0xc9, 0x94, 0xf5, 0xe1, 0xdc, 0xb3, 0x05, 0x41, 0x72, 0x93, 0x46, + 0x64, 0xdb, 0x5d, 0x8a, 0x8f, 0x63, 0x40, 0x23, 0x64, 0x05, 0xbe, 0x50, 0x58, 0xe4, 0xc0, 0x75, 0x16, 0xbe, 0xe3, + 0x6f, 0xb4, 0x54, 0xf4, 0xd5, 0x60, 0x80, 0x0b, 0xf3, 0x30, 0x43, 0x39, 0x9f, 0x42, 0x05, 0x0f, 0xfd, 0x04, 0x22, + 0x0a, 0x5f, 0xad, 0xf6, 0xe1, 0x1d, 0x1d, 0xd7, 0x26, 0x38, 0x7d, 0xba, 0x9f, 0xd5, 0x9b, 0x19, 0x30, 0x0e, 0x46, + 0x5a, 0xe6, 0xa2, 0xd0, 0xc9, 0x9b, 0xec, 0x42, 0x74, 0x1b, 0x0d, 0x66, 0x42, 0x1c, 0x11, 0x88, 0x67, 0x06, 0x1e, + 0x79, 0xf0, 0xc7, 0x46, 0x2d, 0x52, 0xcc, 0xc6, 0x7e, 0x83, 0xa0, 0xd4, 0xb5, 0x84, 0xd5, 0x4a, 0xd9, 0xd8, 0x22, + 0x26, 0xc7, 0x46, 0x19, 0x29, 0xfb, 0x29, 0x83, 0x98, 0x56, 0x66, 0x1c, 0xdc, 0x6d, 0xf5, 0xb7, 0xd5, 0x7e, 0xde, + 0xe3, 0xf6, 0x1a, 0x8f, 0x1b, 0x8f, 0x7d, 0x03, 0xa8, 0xe5, 0xc6, 0x06, 0xb7, 0x16, 0xe6, 0xb1, 0x35, 0x87, 0x65, + 0x9b, 0x10, 0x14, 0xa5, 0x87, 0xba, 0xbd, 0xb9, 0xf5, 0x11, 0xfb, 0x94, 0x99, 0x93, 0x42, 0xba, 0x0f, 0x72, 0xf4, + 0x80, 0x40, 0xe7, 0xf6, 0x67, 0x45, 0x17, 0x2a, 0x99, 0xb8, 0x1c, 0xe3, 0x2f, 0xc1, 0x6d, 0x5e, 0x3f, 0xba, 0xbe, + 0x36, 0x9b, 0xfc, 0xfa, 0x3a, 0xc2, 0xa1, 0x59, 0x77, 0x14, 0xf0, 0x82, 0xd1, 0xa0, 0x0c, 0xea, 0x64, 0x36, 0x7e, + 0xb3, 0x5d, 0x35, 0xf6, 0x9e, 0x56, 0x78, 0x07, 0xcb, 0x63, 0x1a, 0xdf, 0x72, 0x83, 0xec, 0x73, 0x80, 0x37, 0xeb, + 0xf3, 0x41, 0xf7, 0x4d, 0xac, 0xd0, 0xc1, 0xc1, 0x9b, 0x58, 0xa2, 0xde, 0x15, 0x33, 0x77, 0x6e, 0xe0, 0x07, 0xdd, + 0xe7, 0x66, 0xf8, 0x32, 0x40, 0x80, 0x2b, 0xb6, 0x29, 0xd9, 0xbc, 0x35, 0x51, 0x27, 0x52, 0x88, 0x6a, 0x0d, 0xb1, + 0x75, 0x1d, 0x48, 0xa0, 0xd7, 0x37, 0x21, 0xb4, 0xbb, 0x8c, 0x30, 0x60, 0xe1, 0x4b, 0x2f, 0x35, 0x96, 0xcc, 0x58, + 0x31, 0x61, 0xc5, 0x6a, 0xf5, 0x9e, 0x5a, 0xcf, 0xb3, 0x8d, 0x20, 0x89, 0xaa, 0xdb, 0x68, 0x50, 0x33, 0x7e, 0x10, + 0x1f, 0xe8, 0x00, 0xef, 0xbf, 0x89, 0x0b, 0x84, 0xc0, 0xc2, 0x88, 0x8b, 0x85, 0xf7, 0xb2, 0xca, 0x6a, 0xeb, 0x52, + 0xa0, 0xb2, 0x91, 0x9c, 0xb4, 0xf0, 0x94, 0x64, 0xe5, 0x1a, 0x5d, 0x4c, 0xbb, 0x8d, 0x46, 0x8e, 0x64, 0x9c, 0xf5, + 0xf3, 0x01, 0xe6, 0xb8, 0x80, 0xcb, 0xd4, 0xed, 0x75, 0x98, 0xb3, 0x1a, 0xe5, 0x72, 0xf3, 0x5d, 0xda, 0xb1, 0xa6, + 0x8f, 0xe8, 0x3a, 0x00, 0xc6, 0x23, 0x1a, 0x10, 0x89, 0x5d, 0x40, 0x16, 0x16, 0xc8, 0xca, 0x03, 0x59, 0x18, 0x20, + 0x2b, 0xd4, 0x9b, 0x43, 0xb8, 0x20, 0x85, 0xd2, 0x2d, 0x8a, 0x5e, 0x0f, 0x6c, 0xe9, 0x9c, 0x26, 0x30, 0x37, 0xb1, + 0x15, 0xdc, 0x72, 0x80, 0x03, 0x85, 0xf3, 0xc3, 0x53, 0x64, 0x19, 0x45, 0x26, 0xc6, 0x2b, 0xbe, 0x35, 0x7f, 0x92, + 0x5b, 0x7c, 0x67, 0x7f, 0xdc, 0x05, 0xca, 0xa4, 0xe7, 0x35, 0x6d, 0x03, 0x77, 0x11, 0xd1, 0xa2, 0x24, 0x02, 0xb4, + 0x76, 0xe1, 0xfd, 0x44, 0xfd, 0xc5, 0x33, 0x65, 0x03, 0x31, 0x88, 0x06, 0x51, 0x58, 0x04, 0xa4, 0xf3, 0xcf, 0x3f, + 0x23, 0xd4, 0x13, 0x10, 0x47, 0xc7, 0x9d, 0x6c, 0xcd, 0x36, 0x6a, 0x44, 0x49, 0x94, 0xc6, 0x3e, 0x4c, 0x03, 0xec, + 0x8c, 0x28, 0x0a, 0x5e, 0x3b, 0x29, 0x87, 0xf1, 0xa1, 0x36, 0x0c, 0x33, 0xa8, 0x2a, 0xf0, 0xc4, 0xe5, 0x72, 0x33, + 0xcc, 0x8f, 0x81, 0xaa, 0x30, 0x31, 0x56, 0x90, 0x7d, 0x02, 0x8c, 0x11, 0x76, 0x70, 0xc0, 0xfa, 0x62, 0x10, 0xbc, + 0xe9, 0x55, 0x5d, 0x87, 0xeb, 0x70, 0xe1, 0x62, 0x0a, 0x71, 0xd6, 0x57, 0x2b, 0xfb, 0x97, 0x7c, 0x30, 0xd2, 0x0c, + 0x3c, 0xce, 0x16, 0x9c, 0xb1, 0x62, 0xb7, 0x2c, 0x96, 0x68, 0xf9, 0x3b, 0x98, 0xed, 0xb9, 0xa8, 0x79, 0xdc, 0x4d, + 0xb5, 0xed, 0xa1, 0x3e, 0x37, 0x1a, 0x85, 0x20, 0x66, 0x6d, 0x75, 0xa4, 0xe1, 0xb9, 0x0e, 0xf3, 0x6a, 0xb1, 0x67, + 0x33, 0x55, 0x86, 0x10, 0x85, 0x23, 0x25, 0x01, 0xbb, 0x6d, 0x43, 0x27, 0xe1, 0x47, 0x9d, 0x4a, 0x3a, 0x16, 0x12, + 0xa0, 0xc0, 0x91, 0xb9, 0x9c, 0x37, 0x21, 0xe2, 0x19, 0xda, 0x41, 0xe4, 0x02, 0x13, 0x9a, 0xba, 0x6c, 0xe9, 0x62, + 0x39, 0x45, 0x33, 0xb9, 0x50, 0x6c, 0x31, 0x87, 0xf3, 0xbd, 0x4c, 0xcb, 0x72, 0x9e, 0x7d, 0xae, 0xa7, 0x80, 0xfd, + 0xe5, 0xad, 0x9e, 0x31, 0xb1, 0x88, 0xdc, 0x3c, 0xbf, 0x5a, 0x71, 0xff, 0xcd, 0x0b, 0xfc, 0x88, 0x74, 0x0e, 0xbf, + 0xe2, 0x8f, 0x94, 0x3c, 0x6a, 0x7c, 0xc5, 0x13, 0x4e, 0x2c, 0x6f, 0x90, 0xbc, 0x79, 0x7d, 0xf5, 0xe2, 0xdd, 0x8b, + 0xf7, 0x4f, 0xaf, 0x5f, 0xbc, 0x7a, 0xf6, 0xe2, 0xd5, 0x8b, 0x77, 0x1f, 0xf1, 0x3f, 0x94, 0x7c, 0x3d, 0x6a, 0x9f, + 0xb7, 0xf0, 0x07, 0xf2, 0xf5, 0xa8, 0x83, 0x6f, 0x35, 0xf9, 0x7a, 0x74, 0x82, 0x73, 0x45, 0xbe, 0x1e, 0x76, 0x8e, + 0x8e, 0xf1, 0x42, 0xdb, 0x26, 0x73, 0x39, 0x69, 0xb7, 0xf0, 0x3f, 0xee, 0x0b, 0xc4, 0xfb, 0x6a, 0x16, 0x13, 0xb6, + 0x61, 0xfc, 0x60, 0xca, 0xd0, 0xa1, 0x32, 0x86, 0x28, 0x17, 0x01, 0x3a, 0x4d, 0x55, 0x88, 0x4e, 0x36, 0x88, 0x31, + 0xd8, 0x30, 0x02, 0x5a, 0x71, 0xe2, 0xda, 0xe1, 0x47, 0x6d, 0x76, 0x0c, 0xf4, 0x89, 0x97, 0xc2, 0x71, 0xa9, 0xc2, + 0x69, 0x3b, 0x2d, 0xc6, 0x38, 0x97, 0xb2, 0x88, 0x17, 0xc0, 0x08, 0x18, 0xad, 0x05, 0x3f, 0x2a, 0xa3, 0x25, 0x89, + 0x0b, 0xd2, 0xee, 0xb5, 0x53, 0x71, 0x41, 0x3a, 0xbd, 0x0e, 0xfc, 0x39, 0xed, 0x9d, 0xa6, 0xed, 0x16, 0x3a, 0x0c, + 0xc6, 0xf1, 0x47, 0x0d, 0xad, 0xfb, 0x03, 0xec, 0xba, 0x50, 0xff, 0x14, 0xda, 0xab, 0xf4, 0x84, 0x53, 0xc7, 0xb6, + 0xbb, 0xe2, 0x82, 0x19, 0x3d, 0x2c, 0xff, 0x01, 0x50, 0xdb, 0x38, 0x74, 0x94, 0x1b, 0xc7, 0xfd, 0xe2, 0x47, 0x02, + 0xd5, 0x42, 0xb2, 0xc4, 0x6c, 0xd5, 0x42, 0xc0, 0x34, 0x9a, 0x6c, 0x30, 0x07, 0x4a, 0x94, 0x2c, 0xb4, 0x0f, 0x2b, + 0xaf, 0x9a, 0x12, 0x25, 0x73, 0x39, 0x8f, 0x6b, 0xaa, 0x86, 0x5f, 0x03, 0x33, 0xc7, 0x7d, 0xae, 0x5e, 0xd1, 0x57, + 0x71, 0x8d, 0xe7, 0x09, 0x59, 0xbb, 0x70, 0x5b, 0xfc, 0xe2, 0xac, 0x28, 0x6a, 0xe0, 0x2a, 0x01, 0xeb, 0x47, 0xd5, + 0xd4, 0x17, 0xf0, 0x7e, 0x1e, 0x6b, 0xe8, 0x4b, 0x12, 0x50, 0xcf, 0x9f, 0x4a, 0x33, 0xae, 0x52, 0x19, 0xed, 0x15, + 0xd1, 0xc6, 0x2c, 0xc8, 0x2b, 0xa2, 0x2f, 0x94, 0x01, 0x82, 0x24, 0xbc, 0x2f, 0x06, 0x70, 0xe0, 0xdb, 0x01, 0x4a, + 0x43, 0xe7, 0x40, 0xad, 0x54, 0x99, 0x09, 0x99, 0x4f, 0x13, 0x1c, 0x00, 0x34, 0x4f, 0x95, 0x0a, 0xca, 0x7c, 0x62, + 0x89, 0x82, 0xa1, 0xff, 0x16, 0x6e, 0x80, 0xc3, 0xd8, 0xa0, 0x62, 0x90, 0x7d, 0x4f, 0xd4, 0xf3, 0xdb, 0xe7, 0xad, + 0xa3, 0xaf, 0x41, 0xfe, 0x48, 0x79, 0x7b, 0x8f, 0xbf, 0x03, 0x4a, 0x6e, 0xc3, 0x59, 0xb5, 0xb1, 0x8f, 0x44, 0xd6, + 0x0d, 0x01, 0x72, 0xa8, 0xd1, 0x91, 0x79, 0x4a, 0xb0, 0x8b, 0xf4, 0x21, 0x69, 0xb7, 0x20, 0x7c, 0xd8, 0x0e, 0xca, + 0xf7, 0xd3, 0x06, 0x4c, 0x75, 0x72, 0xdb, 0x04, 0x5a, 0x0d, 0xaf, 0x0b, 0xdd, 0x35, 0x79, 0x72, 0x87, 0x55, 0x80, + 0x33, 0xec, 0x90, 0x35, 0xc4, 0xa1, 0x40, 0x2e, 0xec, 0xaa, 0xdd, 0x00, 0x9a, 0x8a, 0x8e, 0x7d, 0xe5, 0xce, 0x1b, + 0x47, 0x5d, 0x34, 0x93, 0xd3, 0xc3, 0xaf, 0x07, 0x07, 0xb1, 0x6c, 0x90, 0x47, 0x08, 0x2f, 0x29, 0x58, 0x31, 0x83, + 0xd7, 0x17, 0xb7, 0x4c, 0x7c, 0xaa, 0x02, 0xea, 0xb8, 0x50, 0xb5, 0x63, 0xad, 0xea, 0xac, 0xdc, 0x0d, 0x7e, 0x4c, + 0x1d, 0xd4, 0x08, 0xd2, 0xec, 0xe8, 0x3a, 0x35, 0x28, 0xd7, 0x5c, 0xb4, 0x60, 0x5b, 0x36, 0x3e, 0x52, 0xf4, 0xc3, + 0xa3, 0xe6, 0xd7, 0x60, 0xc2, 0x35, 0xd3, 0xa4, 0x47, 0x8d, 0x47, 0xe8, 0x87, 0x47, 0x81, 0x93, 0x1d, 0xaf, 0xd8, + 0x13, 0xcf, 0x8d, 0xfc, 0x64, 0xb9, 0xd2, 0x9f, 0x40, 0xb2, 0x2f, 0xc8, 0x4f, 0x80, 0xe5, 0x94, 0xfc, 0x14, 0xcb, + 0x26, 0x04, 0x1f, 0x24, 0x3f, 0xc5, 0x05, 0xfc, 0xc8, 0xc9, 0x4f, 0x31, 0x60, 0x3b, 0x9e, 0x9a, 0x1f, 0x45, 0x09, + 0x0c, 0x70, 0xec, 0x92, 0xd6, 0xbf, 0xab, 0x58, 0xad, 0xc4, 0xc1, 0x81, 0xb4, 0xbf, 0xe8, 0x65, 0x76, 0x70, 0x90, + 0x5f, 0x4c, 0xab, 0xbe, 0x99, 0xde, 0x45, 0x5f, 0x0c, 0x42, 0xe1, 0xc0, 0x34, 0x8d, 0x87, 0x33, 0xfe, 0x14, 0x52, + 0x56, 0xd3, 0x40, 0xf3, 0xb8, 0x73, 0xff, 0xec, 0x1c, 0xc3, 0xbf, 0xf7, 0x83, 0x82, 0x3f, 0x97, 0x7c, 0x17, 0x69, + 0xb3, 0xe6, 0x59, 0x85, 0x6c, 0x97, 0x01, 0x3e, 0x63, 0x86, 0x9a, 0xe2, 0xe0, 0x80, 0x5f, 0x04, 0xb8, 0x8c, 0x19, + 0x6a, 0x04, 0x16, 0x7b, 0x0f, 0x4b, 0x7b, 0x32, 0xc3, 0x35, 0xc1, 0xb3, 0xb2, 0xbc, 0x5f, 0x0c, 0x2e, 0xb4, 0xa3, + 0x26, 0x61, 0xf0, 0x69, 0x45, 0x5a, 0x6e, 0x93, 0x75, 0x45, 0x53, 0x5d, 0xb6, 0xbb, 0x48, 0x12, 0xd5, 0x10, 0x97, + 0x97, 0x6d, 0x0c, 0x2a, 0xf9, 0x9e, 0x22, 0x32, 0x15, 0xc4, 0x3b, 0xc8, 0x2d, 0x73, 0x99, 0x2a, 0x3c, 0xe5, 0xa9, + 0xf0, 0x72, 0xf6, 0x6b, 0x6f, 0x3d, 0x6d, 0x5c, 0x16, 0x4d, 0xcf, 0x0c, 0x8b, 0x9e, 0x2a, 0x5d, 0xed, 0x60, 0x93, + 0xaa, 0x01, 0xbc, 0xda, 0x57, 0x62, 0x1e, 0xb3, 0xfe, 0x65, 0x0c, 0xa2, 0x22, 0xab, 0x46, 0x1b, 0x32, 0xe1, 0x73, + 0x9d, 0x2a, 0x18, 0xa8, 0x29, 0x7c, 0x01, 0x64, 0x2a, 0xab, 0x0c, 0xb3, 0x7d, 0xc3, 0x50, 0x40, 0x40, 0x81, 0x4b, + 0xc2, 0x02, 0x09, 0x1e, 0x6e, 0x3f, 0x02, 0xc2, 0x51, 0x27, 0x17, 0x76, 0x72, 0x17, 0x0a, 0xba, 0x13, 0x83, 0x0b, + 0xdd, 0x45, 0xa2, 0xd1, 0x70, 0xdc, 0xf6, 0xa5, 0x30, 0x83, 0x68, 0xb6, 0x07, 0x97, 0xac, 0x8b, 0x54, 0xb3, 0x59, + 0x1a, 0x40, 0x5e, 0xb6, 0x56, 0x2b, 0x75, 0xe1, 0x1b, 0xe9, 0xf9, 0x73, 0xdc, 0xf0, 0x5d, 0x5e, 0xf0, 0xfc, 0x4d, + 0x92, 0x7e, 0x04, 0x54, 0x15, 0xf8, 0x6c, 0x39, 0x8f, 0x70, 0x64, 0x1e, 0x74, 0x83, 0xbf, 0xe6, 0x21, 0xae, 0x08, + 0x47, 0xee, 0x8d, 0xb7, 0x68, 0x50, 0x0d, 0x96, 0x67, 0x65, 0x78, 0x72, 0x9e, 0x5c, 0x03, 0xe3, 0xa0, 0xff, 0x56, + 0x68, 0x59, 0xfd, 0x4e, 0x72, 0x17, 0xa8, 0x43, 0xf9, 0x67, 0xc7, 0xdc, 0xa8, 0xd6, 0xbb, 0x5d, 0x23, 0x39, 0x8e, + 0x7c, 0x55, 0x08, 0xdf, 0xff, 0x9d, 0x77, 0x0f, 0xdb, 0xee, 0xb9, 0xed, 0x65, 0xd9, 0x03, 0x70, 0xde, 0xeb, 0x35, + 0xc2, 0xbf, 0xc9, 0x9d, 0x6f, 0xef, 0x46, 0xd7, 0x52, 0x3c, 0xa1, 0x9a, 0x46, 0x8d, 0x37, 0xc6, 0xf0, 0xcd, 0xca, + 0x59, 0xdd, 0x6f, 0x8d, 0x83, 0xfd, 0x5b, 0xdd, 0x43, 0xe8, 0x84, 0xda, 0x33, 0x41, 0x56, 0xf6, 0x35, 0x01, 0x33, + 0x64, 0x60, 0xfa, 0xb6, 0x03, 0x1e, 0x7e, 0x8c, 0x14, 0x1c, 0x7a, 0x2d, 0x9f, 0x44, 0x21, 0x26, 0x69, 0xcd, 0x8d, + 0x18, 0x52, 0x6c, 0x1f, 0xc6, 0xe5, 0x74, 0x8d, 0x42, 0xae, 0x7b, 0xac, 0xea, 0xc4, 0xb4, 0xea, 0xc6, 0x48, 0x1d, + 0x6c, 0x93, 0x05, 0x67, 0x55, 0xef, 0x46, 0x42, 0xa9, 0x5e, 0x54, 0x33, 0xaf, 0x62, 0x36, 0xdb, 0xe6, 0x99, 0x61, + 0xfb, 0xee, 0x9a, 0x02, 0x43, 0xde, 0xfd, 0x32, 0x5c, 0xd4, 0x25, 0x1c, 0xbb, 0x71, 0x00, 0x59, 0x49, 0x2e, 0x97, + 0xee, 0x4d, 0x34, 0xde, 0x97, 0x83, 0x75, 0xf9, 0x42, 0x5a, 0x80, 0x07, 0xd5, 0x48, 0x45, 0x16, 0x72, 0x06, 0xfe, + 0x79, 0xc1, 0x9a, 0x7e, 0x88, 0x7f, 0x85, 0x03, 0xbe, 0x42, 0xd2, 0xd4, 0xaa, 0x9f, 0xe0, 0xe5, 0x22, 0x50, 0x78, + 0xdb, 0xba, 0x9f, 0x64, 0xe8, 0x22, 0x5a, 0xd7, 0xa9, 0x58, 0x2f, 0xcc, 0xba, 0x62, 0xa5, 0x2c, 0x1c, 0x1c, 0x77, + 0x31, 0x5a, 0xa7, 0xce, 0x63, 0xd3, 0x3d, 0x77, 0xf4, 0x50, 0xf0, 0x99, 0x71, 0xa4, 0x7b, 0x56, 0x40, 0xfc, 0xaa, + 0x50, 0x9f, 0xf6, 0xb3, 0x0c, 0xdf, 0xf3, 0xed, 0xc3, 0x3d, 0x61, 0xc9, 0x73, 0x96, 0x6f, 0x50, 0xc3, 0x02, 0x29, + 0xa0, 0x50, 0x0a, 0x8b, 0xd5, 0x2a, 0x16, 0x26, 0xaa, 0x81, 0x0b, 0x6a, 0xeb, 0x5e, 0xaf, 0x30, 0xfa, 0x3b, 0xa8, + 0x8b, 0xbd, 0x7a, 0xc4, 0x98, 0xb0, 0xa2, 0xf0, 0xd2, 0x49, 0x65, 0x41, 0x5f, 0xbb, 0xfa, 0x10, 0xd5, 0x94, 0x7b, + 0xb1, 0xd1, 0xf7, 0xbe, 0xe3, 0x33, 0x26, 0x17, 0xf0, 0x6c, 0x10, 0x66, 0x44, 0x31, 0xed, 0xbf, 0x81, 0x82, 0xc0, + 0xdb, 0x33, 0x3c, 0xc4, 0x47, 0xe0, 0xab, 0x3c, 0xad, 0x93, 0x99, 0x7f, 0x8c, 0x22, 0x32, 0xc1, 0x22, 0xa3, 0x5e, + 0x04, 0x5e, 0x43, 0x20, 0x42, 0x11, 0x12, 0x31, 0x31, 0x8a, 0x7a, 0x91, 0x71, 0x52, 0x8a, 0xc0, 0x6a, 0x0c, 0x94, + 0xdc, 0x11, 0x9e, 0xab, 0x8a, 0x88, 0x85, 0x35, 0x75, 0x50, 0x89, 0xa5, 0xc6, 0x4c, 0xfb, 0xa8, 0x53, 0x81, 0xb0, + 0xc8, 0x36, 0x05, 0x65, 0xbd, 0xa1, 0x2e, 0xc0, 0x92, 0x18, 0xd3, 0x5b, 0x9e, 0x5c, 0x03, 0x37, 0xc7, 0x46, 0xae, + 0xe8, 0x92, 0x5f, 0x81, 0x7a, 0x3a, 0x2d, 0xf0, 0xb5, 0x61, 0xd8, 0x46, 0x29, 0x5d, 0x13, 0x8e, 0x33, 0x52, 0x24, + 0xf4, 0x16, 0xa2, 0x3a, 0xcc, 0xb8, 0x48, 0x73, 0x3c, 0xa3, 0xb7, 0xe9, 0x14, 0xcf, 0xb8, 0x78, 0x62, 0x97, 0x3d, + 0x1d, 0x41, 0x92, 0xff, 0x58, 0xac, 0x89, 0x79, 0x94, 0xea, 0x77, 0xc5, 0x8a, 0x47, 0xc0, 0xab, 0xa8, 0x18, 0x75, + 0x47, 0xc6, 0xa6, 0x9c, 0xe9, 0xca, 0x78, 0xfd, 0xb5, 0x8e, 0x29, 0xce, 0x70, 0x8e, 0x92, 0x5c, 0x62, 0xd6, 0x13, + 0xe9, 0x6b, 0x88, 0xe8, 0x9c, 0x61, 0xfb, 0xa0, 0x15, 0xbf, 0x65, 0xf9, 0x33, 0x59, 0xbc, 0x37, 0x5b, 0x3e, 0x47, + 0x50, 0x08, 0x5c, 0x54, 0x44, 0x13, 0x6e, 0xf7, 0x16, 0x3d, 0x59, 0x35, 0x45, 0x6f, 0x6d, 0x53, 0x6e, 0x88, 0x53, + 0x08, 0x85, 0x9b, 0x4c, 0x79, 0xa3, 0x8d, 0x59, 0xaf, 0xf5, 0x9d, 0x46, 0xa7, 0xa8, 0x2c, 0x89, 0x30, 0xac, 0x55, + 0x53, 0xa5, 0x92, 0x88, 0xa6, 0x72, 0x12, 0xde, 0xd2, 0x00, 0x3b, 0x55, 0x38, 0x93, 0x0b, 0xa1, 0x53, 0x19, 0xe0, + 0x0d, 0xad, 0x36, 0xd7, 0xf2, 0xd6, 0x42, 0x4c, 0xe3, 0x3b, 0xfb, 0x83, 0xe1, 0x6b, 0xa3, 0xe2, 0x7f, 0x0b, 0x86, + 0x3d, 0x2a, 0x15, 0x00, 0x3f, 0x30, 0x9c, 0x05, 0xc8, 0x59, 0x7e, 0xf2, 0x16, 0xc0, 0x67, 0x59, 0xc8, 0x3b, 0x48, + 0x65, 0x26, 0xf5, 0x0e, 0x52, 0x19, 0xa4, 0x1a, 0x5f, 0xee, 0x7d, 0x51, 0x29, 0x8b, 0xc2, 0x06, 0x89, 0xc2, 0xa5, + 0x3a, 0x58, 0x12, 0x91, 0x40, 0xbb, 0x46, 0x94, 0x9b, 0x71, 0x01, 0x41, 0xfd, 0xa0, 0x71, 0xfb, 0x4d, 0x6f, 0xe1, + 0xfb, 0xce, 0xe6, 0x33, 0x9f, 0x7f, 0x67, 0xf3, 0x4d, 0x47, 0x1e, 0xe3, 0xeb, 0xb7, 0x9d, 0xc6, 0x32, 0x5e, 0x3a, + 0xac, 0xfd, 0x50, 0x3e, 0xa1, 0xd2, 0x32, 0x4f, 0x55, 0x93, 0x36, 0x9e, 0x04, 0x48, 0xd9, 0xac, 0x78, 0xb8, 0x0e, + 0x6e, 0xb7, 0x0e, 0x63, 0xde, 0x24, 0x6d, 0x84, 0x0e, 0x9d, 0x70, 0x25, 0x62, 0x23, 0x39, 0x1d, 0x3e, 0x3a, 0x82, + 0xbb, 0x97, 0x99, 0xda, 0xf0, 0x95, 0xb2, 0xd5, 0x9a, 0xed, 0xd6, 0x21, 0xdf, 0x59, 0xa5, 0xd1, 0xc6, 0x33, 0x46, + 0x96, 0xe0, 0x5c, 0x46, 0x0b, 0xab, 0x6a, 0x00, 0x27, 0xce, 0x17, 0xe2, 0xb7, 0x05, 0x1d, 0x99, 0xef, 0x43, 0x9b, + 0xf2, 0x7a, 0xa1, 0x7d, 0x52, 0x93, 0xc3, 0x20, 0x3a, 0xc8, 0x95, 0x0c, 0x72, 0x62, 0x7e, 0x44, 0x92, 0x53, 0x74, + 0xd1, 0xee, 0x25, 0xa7, 0x87, 0xfc, 0x90, 0xa7, 0xc0, 0xc3, 0xc6, 0x4d, 0x5f, 0xa1, 0xd9, 0xf6, 0x75, 0x1e, 0x2f, + 0x86, 0x3c, 0x73, 0xcd, 0x57, 0x1d, 0x94, 0xa9, 0x76, 0x8e, 0x90, 0x05, 0x28, 0xe6, 0x7b, 0x09, 0xb2, 0xeb, 0xdd, + 0x1c, 0xf2, 0x14, 0xfa, 0x81, 0x5a, 0x1d, 0x5b, 0xab, 0x1c, 0xdc, 0x6f, 0x0b, 0x40, 0x30, 0xdf, 0x51, 0x6d, 0x2e, + 0x36, 0xbd, 0x19, 0x57, 0x9d, 0x1d, 0xf2, 0x6a, 0x84, 0x61, 0x99, 0xed, 0xfe, 0xfc, 0xd4, 0xaa, 0x2e, 0x0f, 0x03, + 0x88, 0xfc, 0xb6, 0xe0, 0x22, 0xec, 0x34, 0xec, 0xd6, 0xe5, 0x84, 0x9d, 0xd6, 0x67, 0x19, 0x14, 0xd9, 0xee, 0x75, + 0x6b, 0xa6, 0xf5, 0xd9, 0x5e, 0x81, 0x8f, 0x20, 0x4c, 0xca, 0xac, 0x74, 0x06, 0x57, 0xe8, 0x87, 0x1f, 0x90, 0x6b, + 0xfd, 0xf5, 0x42, 0xfb, 0xfc, 0x12, 0x11, 0x20, 0xbb, 0xea, 0xba, 0xac, 0x0e, 0x7d, 0x94, 0x4d, 0x7c, 0x3d, 0xe4, + 0xc1, 0xca, 0x3d, 0xbd, 0x9d, 0xcb, 0xd4, 0xe3, 0x6b, 0xaf, 0x95, 0x6e, 0x21, 0x27, 0x10, 0x0f, 0xd7, 0x5d, 0x58, + 0x16, 0xe4, 0xec, 0xe6, 0x16, 0x4a, 0x86, 0x13, 0xf7, 0xa5, 0x3f, 0x30, 0x7b, 0xdd, 0xc0, 0x2f, 0x92, 0x53, 0x98, + 0xfa, 0x66, 0x0f, 0x87, 0x1d, 0xe8, 0xc3, 0xc0, 0x61, 0xb3, 0x41, 0x9f, 0x59, 0x41, 0xe4, 0x31, 0x2f, 0x2c, 0x9e, + 0x5d, 0x92, 0x76, 0x8f, 0xa7, 0x6e, 0x33, 0x19, 0xd1, 0xa8, 0xdd, 0xe4, 0xc1, 0xcc, 0x00, 0xbf, 0x5c, 0xd9, 0xb0, + 0x88, 0x5f, 0xa7, 0x00, 0x4a, 0xbe, 0x58, 0xb5, 0x3e, 0x15, 0xbc, 0xea, 0x0d, 0xa7, 0x9b, 0xe9, 0x7e, 0xdd, 0xe0, + 0x76, 0xd7, 0xc3, 0x13, 0x9e, 0x40, 0xb1, 0x68, 0xed, 0x27, 0x3e, 0x01, 0x0e, 0x28, 0x69, 0xdd, 0x3f, 0x05, 0x17, + 0xca, 0x12, 0x96, 0xdb, 0xe5, 0x66, 0x5b, 0xe5, 0x2c, 0x1c, 0x6d, 0xc9, 0x80, 0x3b, 0xd8, 0x84, 0x28, 0x74, 0x70, + 0xd8, 0xc1, 0x49, 0xbb, 0xdd, 0x39, 0xc5, 0xc9, 0xc9, 0x29, 0x0c, 0xb4, 0x91, 0x9c, 0x1e, 0xce, 0x94, 0x05, 0x60, + 0x90, 0xb3, 0x76, 0xed, 0x3e, 0x82, 0x70, 0x49, 0xa1, 0x78, 0xcd, 0x0f, 0xe3, 0xb8, 0x9d, 0xdc, 0x6f, 0xb5, 0x4f, + 0xcf, 0x1b, 0x00, 0xa0, 0xa6, 0xfb, 0x70, 0x35, 0x5e, 0x2f, 0x74, 0xbd, 0x4a, 0x89, 0xf0, 0xf5, 0x6a, 0x0d, 0x5f, + 0xad, 0xd1, 0x5e, 0x57, 0x53, 0xf0, 0x55, 0x9d, 0x70, 0x6e, 0x8b, 0x78, 0xa5, 0x4d, 0xb8, 0x2d, 0x62, 0x3b, 0x90, + 0x18, 0xa4, 0xf3, 0xe4, 0xb4, 0x73, 0x8a, 0xec, 0x58, 0xb4, 0xc3, 0x8f, 0x72, 0x9f, 0x6c, 0x15, 0x69, 0x68, 0x40, + 0x92, 0x72, 0x76, 0x72, 0x01, 0x12, 0x35, 0x27, 0x97, 0xed, 0xe6, 0x8c, 0x25, 0x7e, 0x02, 0x26, 0x15, 0x96, 0xb3, + 0x5c, 0x05, 0x97, 0x14, 0x00, 0xe2, 0x02, 0x8c, 0x8b, 0xee, 0x9f, 0xf6, 0xee, 0x27, 0xa7, 0x67, 0x1d, 0x4b, 0xf4, + 0xf8, 0x45, 0xa7, 0x96, 0x66, 0xa6, 0x9e, 0x9c, 0x9a, 0x34, 0xe8, 0x3a, 0xb9, 0x7f, 0x0a, 0x65, 0x5c, 0x4a, 0x58, + 0x0a, 0xc2, 0x3c, 0x54, 0xc5, 0x20, 0xb6, 0x43, 0x5a, 0xcb, 0x3d, 0xab, 0x65, 0x9f, 0x9f, 0x1c, 0xdf, 0x3f, 0x0d, + 0xa1, 0x56, 0xce, 0xc2, 0x2c, 0xb4, 0x9b, 0x88, 0x9f, 0x1d, 0x2c, 0x2d, 0x3a, 0x4c, 0x4e, 0xd3, 0xad, 0x09, 0xda, + 0x4d, 0x73, 0x68, 0x70, 0x20, 0x50, 0x38, 0x3e, 0x15, 0x4e, 0x5f, 0x12, 0xdc, 0x8f, 0x55, 0x86, 0x26, 0xa1, 0xc2, + 0xd9, 0xdf, 0x53, 0x06, 0x2f, 0x39, 0x86, 0x57, 0x95, 0x8f, 0xa9, 0xf8, 0x42, 0xd5, 0x1b, 0x0a, 0xb1, 0x2b, 0xc4, + 0x20, 0x72, 0x91, 0xb5, 0xeb, 0xb9, 0x3f, 0x81, 0x8b, 0x30, 0x13, 0x70, 0xa1, 0xe9, 0x95, 0xa0, 0x15, 0x2f, 0x30, + 0x0c, 0x1d, 0x6a, 0xcd, 0xb0, 0x7a, 0x3c, 0x75, 0x26, 0x05, 0xa1, 0x6e, 0xeb, 0x39, 0xff, 0x5e, 0xb9, 0xa4, 0xbc, + 0xca, 0x4e, 0x4e, 0x51, 0xe2, 0x2e, 0xcb, 0x93, 0x36, 0x4a, 0x02, 0x13, 0x12, 0x77, 0x24, 0x67, 0x19, 0xe9, 0x47, + 0xb7, 0x11, 0x8e, 0xee, 0x22, 0x1c, 0x59, 0x1f, 0xe6, 0x0f, 0xe0, 0x3c, 0x1f, 0xe1, 0xc8, 0xba, 0x32, 0x47, 0x38, + 0xd2, 0x4c, 0x40, 0x48, 0xab, 0x68, 0x80, 0x73, 0x28, 0x6d, 0x3c, 0xab, 0xcb, 0xd2, 0x8f, 0xfd, 0x57, 0xe9, 0x7a, + 0x6d, 0x53, 0x02, 0x29, 0x73, 0x6a, 0x76, 0xa8, 0x7d, 0x92, 0x39, 0xa2, 0x9e, 0x59, 0x8f, 0x30, 0x08, 0x20, 0xf4, + 0xce, 0x3f, 0xe9, 0x56, 0x45, 0xc3, 0x60, 0xc7, 0xb0, 0xd2, 0xe0, 0x67, 0x1e, 0x85, 0x67, 0x58, 0x84, 0xc7, 0xc2, + 0x17, 0x06, 0xb1, 0xc2, 0xff, 0xce, 0xa5, 0x9c, 0xfb, 0xdf, 0x5a, 0x96, 0xbf, 0xe0, 0x21, 0x10, 0x67, 0xd1, 0x02, + 0x96, 0x5b, 0x36, 0xf8, 0xce, 0x90, 0xd5, 0x47, 0x70, 0x3d, 0x76, 0x01, 0xd2, 0x40, 0x22, 0xbc, 0x36, 0x02, 0x95, + 0x97, 0x0f, 0xaf, 0x6d, 0xb0, 0x1e, 0xf3, 0x09, 0xd1, 0xba, 0x20, 0x20, 0xaf, 0x84, 0x0b, 0x8d, 0x49, 0xc1, 0x94, + 0x8a, 0x6c, 0x14, 0xbb, 0x48, 0x0a, 0xff, 0x2c, 0xa1, 0x4f, 0x19, 0x8b, 0xc8, 0x74, 0x58, 0x9f, 0xad, 0x15, 0x87, + 0x73, 0x59, 0xa8, 0xd4, 0xbe, 0x51, 0xe2, 0xc1, 0x58, 0x3d, 0x55, 0x9f, 0xe6, 0xd9, 0x1a, 0xdb, 0x3b, 0xec, 0xb2, + 0x90, 0xbb, 0xd2, 0x0e, 0x4b, 0x65, 0xd9, 0xfa, 0x5b, 0x13, 0x52, 0xb5, 0x19, 0x05, 0x13, 0xad, 0x06, 0x54, 0x85, + 0xb2, 0x80, 0xc2, 0x36, 0x1c, 0x4a, 0xba, 0x2c, 0x4b, 0xa6, 0xcb, 0x72, 0x19, 0x4e, 0x5a, 0xad, 0xf5, 0x1a, 0x17, + 0xcc, 0x84, 0x65, 0xd9, 0x59, 0x02, 0xf2, 0xd5, 0x54, 0xde, 0x04, 0xb9, 0x2a, 0x2d, 0x67, 0x69, 0x96, 0x28, 0x0a, + 0x8c, 0x60, 0xa3, 0x35, 0xfe, 0xc2, 0x15, 0x07, 0x78, 0xba, 0xd9, 0x0d, 0xa5, 0xcc, 0x19, 0x85, 0xe8, 0x5d, 0x41, + 0x93, 0x6b, 0x3c, 0xe5, 0x23, 0xb6, 0xbb, 0x4d, 0x30, 0x63, 0xfe, 0xf7, 0x5a, 0xf4, 0x08, 0x64, 0xd9, 0x3d, 0x83, + 0x3a, 0xb0, 0x88, 0x2b, 0xe8, 0x20, 0x94, 0xc1, 0x47, 0x21, 0x6e, 0xe6, 0xf4, 0x4e, 0x2e, 0x34, 0xc0, 0x65, 0xa1, + 0xe5, 0x1b, 0x17, 0xeb, 0x60, 0xbf, 0x85, 0x7d, 0xd8, 0x83, 0x25, 0x84, 0x0c, 0x68, 0x61, 0x1b, 0x23, 0xa2, 0x85, + 0x87, 0x52, 0x6b, 0x39, 0x4b, 0x5b, 0xd8, 0x04, 0x6c, 0x68, 0xad, 0xcb, 0xa8, 0x5a, 0xd7, 0xe5, 0x63, 0x8e, 0xd5, + 0x26, 0x58, 0x38, 0xe9, 0x50, 0x13, 0x1d, 0xdc, 0x1e, 0x32, 0xc2, 0x1b, 0x3f, 0x5f, 0xbd, 0x7e, 0xe5, 0x62, 0x26, + 0xf3, 0x31, 0xb8, 0x6c, 0x3a, 0xd5, 0xd8, 0xb5, 0x79, 0x05, 0x29, 0xae, 0x14, 0xa5, 0x56, 0x38, 0x85, 0x96, 0x5f, + 0x08, 0x9d, 0x27, 0xf6, 0xf2, 0xe2, 0x99, 0x2c, 0x66, 0xd4, 0xde, 0x18, 0xe1, 0x6b, 0xe5, 0x9e, 0x3d, 0x37, 0x2f, + 0xab, 0x54, 0x93, 0x7c, 0xb7, 0x79, 0x15, 0xb1, 0xc8, 0x8c, 0xfc, 0x0a, 0xda, 0x00, 0x53, 0xb9, 0x7c, 0xb5, 0xb6, + 0x20, 0x2e, 0xf2, 0x7c, 0x40, 0x5e, 0xde, 0x5a, 0xea, 0x12, 0x45, 0x0d, 0x6e, 0xf0, 0x93, 0x15, 0x3c, 0x0b, 0xae, + 0x0b, 0x0d, 0x7b, 0xe4, 0xc4, 0x8b, 0xa8, 0x15, 0xd5, 0x5f, 0x7d, 0x35, 0xaa, 0x04, 0x1f, 0xb5, 0x34, 0xc9, 0x25, + 0x88, 0x1e, 0xe5, 0x03, 0x73, 0x1c, 0x44, 0x13, 0x7f, 0xf7, 0x7c, 0xd9, 0xf6, 0x74, 0x36, 0xaf, 0xd4, 0x89, 0xe5, + 0x95, 0x09, 0x78, 0x38, 0xda, 0x27, 0x5c, 0x10, 0x0e, 0x12, 0x59, 0xa9, 0x3d, 0xf4, 0xb9, 0xa8, 0x1b, 0xe7, 0x17, + 0x6d, 0xd6, 0x3c, 0x59, 0xad, 0xf2, 0xcb, 0x36, 0x6b, 0x9f, 0xda, 0x07, 0xdf, 0x22, 0x95, 0x01, 0xcd, 0xe5, 0x63, + 0x9e, 0x45, 0xa0, 0x9d, 0x1d, 0x67, 0x26, 0x9c, 0x82, 0x0f, 0x51, 0x4c, 0x16, 0xba, 0xea, 0x4b, 0x82, 0x71, 0x29, + 0xb1, 0x7a, 0xfc, 0x02, 0xf5, 0xda, 0xe9, 0xb6, 0xab, 0x74, 0xb3, 0x7d, 0x18, 0x5c, 0xb8, 0x14, 0x08, 0x77, 0x20, + 0xe4, 0x01, 0xe8, 0x77, 0x97, 0x02, 0x4c, 0x83, 0x00, 0x95, 0x15, 0x88, 0xb4, 0x7c, 0xb6, 0x98, 0x3d, 0x2b, 0xa8, + 0x59, 0x86, 0x27, 0x7c, 0xc2, 0xb5, 0x4a, 0x29, 0x48, 0xb7, 0xbb, 0xd2, 0xd7, 0xbb, 0x25, 0xa8, 0xac, 0x16, 0xf9, + 0x35, 0xd1, 0x3c, 0xfb, 0xac, 0xdc, 0xc2, 0x21, 0x6c, 0x56, 0x56, 0xe0, 0x0c, 0xad, 0x71, 0x2e, 0x27, 0xb4, 0xe0, + 0x7a, 0x3a, 0xfb, 0xb7, 0x56, 0x87, 0xf5, 0xf5, 0xc0, 0x5c, 0x58, 0x01, 0x48, 0xa8, 0x18, 0xad, 0x56, 0xfc, 0xe8, + 0xfb, 0xf7, 0x49, 0xde, 0x27, 0xbc, 0x8d, 0x3b, 0xf8, 0x18, 0x9f, 0xe2, 0x76, 0x0b, 0xb7, 0x4f, 0xe1, 0xea, 0x3e, + 0xcb, 0x17, 0x23, 0xa6, 0x62, 0x78, 0xf9, 0x4b, 0x5f, 0x26, 0xe7, 0x87, 0x65, 0xbc, 0x7b, 0x5d, 0x24, 0x0e, 0x5d, + 0x82, 0xb0, 0xeb, 0x2e, 0x5e, 0x5d, 0x14, 0x85, 0xc1, 0xd2, 0xc6, 0xa1, 0xea, 0xa4, 0xd4, 0x2f, 0x5c, 0x1e, 0xf7, + 0xc0, 0x9e, 0xdb, 0xae, 0x6c, 0x13, 0xcc, 0xbe, 0xed, 0xcf, 0xb4, 0xfa, 0xd9, 0xd4, 0x25, 0x62, 0x78, 0xe8, 0x55, + 0xe8, 0x81, 0x2e, 0x49, 0xfb, 0xe0, 0x00, 0xac, 0x8e, 0x82, 0xd9, 0x70, 0x1b, 0xfd, 0x80, 0x37, 0x6b, 0x69, 0x10, + 0xac, 0x00, 0x8c, 0x3b, 0xdf, 0x70, 0xb2, 0xb4, 0xb0, 0xd5, 0x40, 0x85, 0x75, 0x11, 0x46, 0x74, 0x0b, 0x49, 0x85, + 0x11, 0xa2, 0xe1, 0x08, 0x73, 0x91, 0x4e, 0xf6, 0x5b, 0x58, 0x8e, 0xc7, 0x8a, 0x69, 0x38, 0x3a, 0x0a, 0xf6, 0x85, + 0x15, 0xca, 0x9c, 0x22, 0x43, 0x36, 0xe1, 0xe2, 0xa1, 0xfe, 0xc4, 0x0a, 0x69, 0x3e, 0x8d, 0x06, 0x23, 0x8d, 0xcc, + 0x2a, 0x46, 0x38, 0xcb, 0xf9, 0x1c, 0xaa, 0x4e, 0x0a, 0x70, 0xfa, 0x81, 0xbf, 0x7c, 0x94, 0x86, 0x6d, 0x02, 0xf9, + 0xfa, 0x60, 0x83, 0xd9, 0xe0, 0x51, 0x41, 0x6f, 0x5e, 0x8b, 0xc7, 0xb0, 0xa3, 0x1e, 0x16, 0x8c, 0x42, 0x36, 0x24, + 0xbd, 0x83, 0xa6, 0xe0, 0x03, 0xda, 0x7c, 0x69, 0x00, 0x97, 0x9e, 0x9b, 0x0f, 0x5b, 0xd1, 0x47, 0x0d, 0x4c, 0xca, + 0xb6, 0x4c, 0xa6, 0x39, 0xa5, 0xab, 0x4c, 0x1b, 0x97, 0xa9, 0x9c, 0xc2, 0x1a, 0xbb, 0xa8, 0x27, 0xe1, 0x60, 0x46, + 0x54, 0x4d, 0xd3, 0xfe, 0xc0, 0xfc, 0x7d, 0x6d, 0x4b, 0xb6, 0xb0, 0x0b, 0xb5, 0xb3, 0xc6, 0xe6, 0xc9, 0xce, 0xa0, + 0x7c, 0x1b, 0xc3, 0x3d, 0x2c, 0xbc, 0x1b, 0x59, 0x23, 0x9f, 0x27, 0x9e, 0x6c, 0x9e, 0xac, 0xd7, 0x66, 0x20, 0x2a, + 0x05, 0x3d, 0xd0, 0x5b, 0xbf, 0x6d, 0x5a, 0xb0, 0x3d, 0xca, 0xaf, 0xd3, 0x16, 0x9e, 0x71, 0x78, 0x06, 0xd3, 0xb7, + 0x77, 0xa5, 0x0b, 0xf9, 0xd9, 0x81, 0xa4, 0x15, 0xa4, 0xd8, 0xe9, 0x04, 0x9d, 0x1d, 0xe3, 0x60, 0xe4, 0x40, 0xcf, + 0xaf, 0x3e, 0x5b, 0x58, 0xfb, 0xdf, 0x6f, 0xca, 0x82, 0x39, 0x1d, 0xb2, 0xbc, 0x9c, 0x50, 0xe6, 0xcf, 0xcf, 0x37, + 0x3c, 0xa9, 0x50, 0xc1, 0xbd, 0x1f, 0x05, 0x7b, 0xda, 0x86, 0x98, 0x9c, 0xd1, 0xbf, 0xed, 0x0f, 0x1b, 0x11, 0xa8, + 0xd4, 0xb2, 0x65, 0x85, 0x54, 0xea, 0xa1, 0x4d, 0xb3, 0x47, 0x0f, 0x1c, 0x91, 0x2f, 0xa1, 0x0b, 0xe0, 0xf5, 0x47, + 0x85, 0x9c, 0x1b, 0x44, 0x70, 0xbf, 0xdd, 0xb8, 0x8d, 0xaf, 0x00, 0x78, 0x3b, 0xec, 0x55, 0xff, 0xb4, 0x80, 0xfd, + 0x8d, 0xca, 0x92, 0x7e, 0xbc, 0x1d, 0x7b, 0xfc, 0x17, 0x12, 0xe2, 0x95, 0x5b, 0x3c, 0x4c, 0x1c, 0x3a, 0x95, 0xac, + 0x59, 0xf9, 0x73, 0xab, 0x24, 0x60, 0x58, 0xbd, 0x60, 0xc8, 0xc6, 0x6d, 0x15, 0xb7, 0x99, 0xff, 0x41, 0x05, 0x83, + 0x05, 0xdf, 0x1a, 0x49, 0xc5, 0xb2, 0xf8, 0xed, 0x53, 0xe7, 0xbf, 0xea, 0x1c, 0xd7, 0xbe, 0xae, 0xbd, 0x51, 0x39, + 0x34, 0xf1, 0x81, 0x23, 0x74, 0x70, 0xb0, 0x91, 0x41, 0xc7, 0x00, 0x78, 0xe4, 0xd8, 0x2f, 0xbf, 0x7c, 0x9e, 0x1d, + 0x33, 0x9a, 0xc7, 0x22, 0x0a, 0x99, 0x3b, 0xcf, 0xcd, 0xd9, 0x89, 0x3c, 0xa1, 0x6a, 0xea, 0x0b, 0x03, 0x1c, 0x1f, + 0x6d, 0xa5, 0x02, 0xbe, 0x47, 0xeb, 0x1d, 0x13, 0xd8, 0xe0, 0xb7, 0xec, 0xa4, 0x76, 0x15, 0xf4, 0x0b, 0xb4, 0xdc, + 0xc5, 0x54, 0x6e, 0x2c, 0x70, 0xb4, 0x39, 0x91, 0x9d, 0x43, 0xdf, 0xa8, 0x53, 0xb2, 0x1e, 0x4f, 0x76, 0x1b, 0x7d, + 0x49, 0xb1, 0x2b, 0xb9, 0xa2, 0x6d, 0x43, 0x56, 0xbd, 0x53, 0xab, 0x2b, 0x53, 0xa7, 0xea, 0x9a, 0xb7, 0xb2, 0xb4, + 0x29, 0xed, 0x92, 0xec, 0xdd, 0x16, 0x0b, 0xaf, 0xc2, 0x1b, 0x8d, 0xf2, 0x22, 0x14, 0xec, 0xb1, 0xc4, 0xa0, 0xcb, + 0x09, 0x5c, 0x2f, 0xac, 0x56, 0x31, 0xfc, 0xd9, 0x35, 0x86, 0x5d, 0xa6, 0x4b, 0x1f, 0xf8, 0x06, 0xbf, 0x12, 0x84, + 0xca, 0x75, 0x76, 0x90, 0x60, 0xdd, 0xe5, 0x06, 0x0d, 0xc7, 0x89, 0xff, 0x82, 0x87, 0x9a, 0xb5, 0x77, 0x39, 0x98, + 0x64, 0xdf, 0x78, 0xdc, 0xad, 0x64, 0x2d, 0x6b, 0x71, 0xd6, 0x37, 0x24, 0x18, 0x62, 0x37, 0xa5, 0x73, 0xdc, 0x4a, + 0xda, 0x28, 0x72, 0xc5, 0x2a, 0xf4, 0xff, 0x56, 0x91, 0xcc, 0x66, 0xfe, 0xd7, 0xd9, 0xd9, 0x99, 0x4b, 0x71, 0x36, + 0x7f, 0xca, 0x78, 0xc0, 0x99, 0x04, 0xf6, 0x85, 0x67, 0xcc, 0xe8, 0x90, 0xdf, 0xc2, 0x50, 0x88, 0x20, 0x97, 0xc2, + 0xb1, 0x4b, 0xf0, 0xce, 0x20, 0x50, 0x1e, 0x60, 0xff, 0x9e, 0x6c, 0x94, 0xf3, 0x0f, 0x15, 0xf9, 0x40, 0xbe, 0x65, + 0x83, 0xec, 0x8b, 0xf9, 0xec, 0x5b, 0x33, 0x19, 0x88, 0xcd, 0x1f, 0x61, 0xfb, 0xdb, 0xb0, 0xb4, 0xce, 0x52, 0x06, + 0x47, 0x5a, 0x2e, 0xb2, 0xa9, 0xd5, 0xfc, 0xbb, 0x0f, 0x53, 0xd6, 0x3d, 0x72, 0x03, 0x41, 0xb9, 0xc8, 0xd2, 0xc5, + 0xa3, 0x8c, 0x7e, 0x2c, 0x43, 0x4f, 0xee, 0xbd, 0x62, 0x0b, 0xf6, 0x23, 0xde, 0xab, 0x52, 0xe0, 0xe3, 0x61, 0xc1, + 0x69, 0xfe, 0x23, 0xde, 0xab, 0x42, 0x50, 0x82, 0x2b, 0xa4, 0x89, 0xe2, 0x88, 0xcd, 0x83, 0xce, 0x69, 0x24, 0x80, + 0x82, 0xe6, 0x91, 0x39, 0xc8, 0x9e, 0xbb, 0xa8, 0x85, 0x49, 0x07, 0xbb, 0xb8, 0x5f, 0x36, 0x16, 0xa9, 0x0d, 0xe1, + 0x0d, 0x91, 0xdc, 0xca, 0xd9, 0x98, 0xaf, 0x47, 0x1b, 0x0b, 0x62, 0x94, 0xc9, 0xe4, 0xf2, 0x39, 0x8f, 0xb7, 0x16, + 0x0b, 0x85, 0xd5, 0x82, 0x05, 0xaa, 0x55, 0xa9, 0xd2, 0xc3, 0xe2, 0xdb, 0x05, 0xb3, 0xa0, 0x88, 0xd9, 0x7a, 0x0f, + 0x6f, 0xb9, 0x22, 0x20, 0x25, 0xbb, 0x24, 0x78, 0x93, 0xdb, 0x60, 0xaa, 0x7f, 0x82, 0x1d, 0x08, 0x3d, 0x53, 0x3a, + 0xc2, 0x26, 0x4f, 0x41, 0x24, 0xb1, 0xfd, 0x16, 0x76, 0xac, 0xd1, 0x0b, 0xe1, 0x85, 0x14, 0x38, 0x57, 0x4d, 0x13, + 0x33, 0xca, 0x4d, 0x74, 0xb1, 0x87, 0x6a, 0xce, 0x32, 0x6d, 0x11, 0x60, 0xdf, 0xa1, 0xa1, 0x14, 0xcf, 0x0d, 0x28, + 0xcc, 0x63, 0xd2, 0x2e, 0xe5, 0x31, 0x2c, 0x5e, 0x90, 0x02, 0x44, 0x8d, 0x8b, 0x49, 0x59, 0x67, 0x9e, 0x2f, 0x26, + 0x5c, 0x54, 0xc8, 0x50, 0x30, 0x35, 0x97, 0x02, 0xde, 0x72, 0x28, 0x8b, 0x18, 0x3a, 0x54, 0xc3, 0x77, 0x4b, 0xc2, + 0xca, 0x3a, 0xe6, 0x98, 0xe2, 0xa2, 0xaa, 0x01, 0xcc, 0xc5, 0xc3, 0xf0, 0xd1, 0x77, 0xf5, 0x5a, 0xbc, 0x93, 0xf3, + 0x2a, 0xdf, 0xd3, 0x38, 0x1f, 0x32, 0xdd, 0xd9, 0x0d, 0xa3, 0xb5, 0x79, 0x6e, 0x29, 0xd8, 0xbe, 0x1f, 0x78, 0xf5, + 0x04, 0xd9, 0xda, 0x3c, 0xd8, 0x54, 0x66, 0x0d, 0x59, 0xf9, 0x3a, 0x41, 0xd5, 0x5e, 0xbd, 0xaa, 0x14, 0xb6, 0x22, + 0x40, 0xa5, 0xe0, 0xa3, 0xad, 0xfc, 0x27, 0xda, 0xe6, 0xdb, 0x73, 0xa8, 0x0c, 0x0f, 0xe4, 0xc9, 0x50, 0xd5, 0x03, + 0x2e, 0xca, 0x0f, 0x01, 0x2c, 0x7e, 0x64, 0x22, 0xd7, 0xee, 0xba, 0x40, 0xe6, 0x4c, 0xc5, 0x12, 0x2f, 0xfb, 0x74, + 0x90, 0x5a, 0x79, 0x28, 0x95, 0x60, 0xdb, 0x73, 0x53, 0x70, 0xed, 0x43, 0xe4, 0xe2, 0x3e, 0x1b, 0xa4, 0xcb, 0x7a, + 0x18, 0x5d, 0x1b, 0xc8, 0xd7, 0x9b, 0x73, 0x9a, 0xb8, 0xb3, 0x74, 0x80, 0x73, 0x02, 0xb6, 0xc7, 0x9e, 0x3d, 0x7d, + 0x13, 0x67, 0xa8, 0x57, 0xe7, 0xf0, 0x97, 0x6b, 0x9c, 0xe3, 0x0c, 0xa5, 0x0f, 0x63, 0xb8, 0xc0, 0x5a, 0x63, 0x00, + 0x5f, 0x66, 0x49, 0x15, 0x78, 0xa4, 0x66, 0x46, 0x62, 0x75, 0x17, 0x81, 0x68, 0xa9, 0xc3, 0xdb, 0x71, 0xe6, 0x03, + 0x51, 0x1b, 0xee, 0xf5, 0x99, 0x11, 0x0e, 0x27, 0x59, 0x5c, 0x3b, 0x67, 0x38, 0xb9, 0xdc, 0xe7, 0xb5, 0x13, 0x13, + 0xac, 0xbd, 0xc3, 0x53, 0x05, 0xf4, 0x68, 0x70, 0xaa, 0x58, 0x1a, 0x02, 0x31, 0x13, 0xc0, 0x9b, 0x39, 0x3c, 0xda, + 0x02, 0x9c, 0x8f, 0xd6, 0x38, 0xf8, 0x4a, 0x6b, 0x5d, 0x6d, 0x2a, 0x51, 0xd6, 0x6b, 0xdc, 0x9f, 0x66, 0x78, 0x94, + 0xe1, 0x79, 0x36, 0x08, 0x8e, 0x9b, 0x59, 0x16, 0x9a, 0x74, 0xad, 0x56, 0x4f, 0x9d, 0x19, 0x21, 0xb2, 0x3f, 0x2d, + 0xfd, 0x41, 0x3d, 0x40, 0xf8, 0x14, 0xb2, 0x80, 0x96, 0xf4, 0xdc, 0xdf, 0x86, 0x7d, 0xa7, 0x1a, 0x35, 0x62, 0x9e, + 0x58, 0x32, 0xd2, 0xf3, 0x3f, 0xca, 0x2c, 0xdb, 0x5a, 0x23, 0x9a, 0xdf, 0xee, 0x45, 0x0d, 0xdf, 0x5e, 0xa0, 0x65, + 0x2b, 0xcd, 0x76, 0x00, 0x51, 0xac, 0x71, 0x92, 0x0e, 0xd6, 0x48, 0xae, 0x56, 0xb1, 0x4d, 0x21, 0x3c, 0x99, 0x31, + 0xaa, 0x16, 0x85, 0x79, 0xba, 0x2d, 0x56, 0x28, 0x31, 0xfc, 0x2e, 0x76, 0x36, 0xa2, 0xf0, 0x52, 0x9a, 0x04, 0xc3, + 0x8d, 0x58, 0x10, 0x59, 0x13, 0xb9, 0x87, 0x59, 0x65, 0x19, 0x24, 0x88, 0x30, 0x22, 0xbf, 0xbd, 0x2e, 0x15, 0xf6, + 0x71, 0x38, 0xfb, 0xc7, 0xf8, 0x02, 0xc2, 0xcd, 0xdb, 0x84, 0x16, 0x43, 0x3a, 0x01, 0x36, 0x16, 0xe2, 0x10, 0x6e, + 0x25, 0xac, 0x56, 0xfd, 0x41, 0x57, 0x18, 0xf2, 0xec, 0x9e, 0xae, 0x2b, 0x1b, 0xda, 0xdd, 0x00, 0x5c, 0x75, 0x5b, + 0x6a, 0xae, 0x8d, 0xee, 0x87, 0x9a, 0xd7, 0xb5, 0xb8, 0x4b, 0x72, 0x0f, 0x64, 0x54, 0x6f, 0x60, 0xd7, 0x2c, 0xc0, + 0x4d, 0xe8, 0x2a, 0x3c, 0xc2, 0x0b, 0x6b, 0xc3, 0x69, 0x9e, 0x52, 0xa2, 0xe6, 0x05, 0x25, 0x78, 0xb8, 0x99, 0xb0, + 0x7e, 0x36, 0xc0, 0x23, 0x1f, 0x68, 0x7b, 0xff, 0x6d, 0x3c, 0x42, 0xa8, 0x20, 0x06, 0xa6, 0xd6, 0x65, 0x7b, 0x54, + 0xd9, 0xed, 0x9b, 0x4c, 0xc3, 0x30, 0x18, 0x23, 0xe6, 0x51, 0x68, 0xc4, 0x9c, 0x37, 0x1a, 0x68, 0x41, 0x46, 0x60, + 0xc4, 0xbc, 0x08, 0x5a, 0x5b, 0xd8, 0x67, 0x36, 0x83, 0xf6, 0x16, 0x08, 0x75, 0x39, 0xd0, 0x34, 0x0d, 0x0f, 0x6a, + 0x54, 0x0f, 0x9a, 0xfb, 0xe7, 0x9d, 0x8e, 0x3a, 0xa0, 0x48, 0x18, 0x5f, 0xfa, 0x49, 0x58, 0xd7, 0x70, 0x3b, 0xee, + 0xb1, 0x19, 0xb7, 0xb3, 0x6d, 0x50, 0x7d, 0xd9, 0xcf, 0x06, 0x83, 0xae, 0xf4, 0x56, 0x12, 0x2d, 0x3c, 0xae, 0x9e, + 0xe0, 0xa8, 0x16, 0xef, 0x8b, 0xde, 0xbc, 0xf2, 0xe6, 0xfe, 0x65, 0xcf, 0xcd, 0xf3, 0x18, 0x38, 0xa0, 0x7d, 0xb8, + 0x1f, 0xaa, 0xe2, 0x83, 0x1d, 0x75, 0x20, 0x0a, 0x5a, 0xda, 0xaa, 0x09, 0xa4, 0xd6, 0xcc, 0x2e, 0xd6, 0x4d, 0x85, + 0x0e, 0x05, 0x84, 0x21, 0x53, 0x55, 0x77, 0x77, 0x2a, 0x50, 0x0d, 0x71, 0x38, 0xf5, 0x1f, 0x5b, 0x23, 0xd6, 0x38, + 0xea, 0x8c, 0x22, 0x63, 0x24, 0x69, 0x97, 0x0f, 0x5e, 0xdd, 0x01, 0x2b, 0x01, 0x1f, 0xfd, 0xd8, 0x24, 0x19, 0x43, + 0x82, 0xb7, 0x2c, 0xd3, 0x86, 0x0f, 0xe1, 0x0e, 0x41, 0x79, 0x62, 0x63, 0x6d, 0xba, 0x4a, 0x16, 0x72, 0x55, 0x97, + 0xd7, 0x01, 0x7a, 0xde, 0x95, 0xbf, 0xb1, 0xe1, 0xc8, 0x82, 0x81, 0x65, 0x5b, 0xfb, 0x04, 0x3c, 0xf2, 0x71, 0x85, + 0x20, 0x7e, 0x29, 0x74, 0x62, 0x22, 0x45, 0x5f, 0xc1, 0x06, 0xc5, 0x73, 0x70, 0x10, 0x74, 0x12, 0x1c, 0x06, 0xef, + 0x32, 0xab, 0x49, 0x36, 0xb8, 0x35, 0x23, 0xf1, 0x7c, 0xb5, 0x6a, 0xa1, 0xc3, 0x7f, 0xcc, 0x63, 0xc8, 0xe3, 0x52, + 0xe1, 0x3e, 0xae, 0x14, 0xee, 0x60, 0x09, 0x48, 0xc6, 0x81, 0xae, 0x1d, 0xcb, 0x50, 0x8d, 0x0e, 0x71, 0xba, 0x5f, + 0x40, 0xd4, 0x66, 0x77, 0x2c, 0x81, 0x9e, 0x7d, 0xab, 0x80, 0xd5, 0xb5, 0x97, 0x25, 0x90, 0x11, 0xdc, 0xfd, 0x26, + 0x30, 0x2a, 0x44, 0xe3, 0xf3, 0x67, 0xde, 0x53, 0xe0, 0x89, 0xf3, 0xe7, 0x9a, 0x19, 0xd6, 0xbd, 0xa0, 0x37, 0xa6, + 0xf9, 0x78, 0x8c, 0x9b, 0x63, 0x0b, 0xce, 0xa3, 0x0e, 0xfc, 0xb4, 0x10, 0x3d, 0xea, 0x60, 0x97, 0x8a, 0xc7, 0x25, + 0x90, 0x43, 0xf4, 0x74, 0x06, 0x52, 0xc0, 0x4a, 0xc7, 0x56, 0x8b, 0x34, 0x41, 0xab, 0xd5, 0xe4, 0x82, 0xb4, 0x10, + 0x5a, 0xaa, 0x1b, 0xae, 0xb3, 0x29, 0xf8, 0x48, 0x83, 0x62, 0xe0, 0x0d, 0xd5, 0xd3, 0x18, 0xe1, 0x31, 0x5a, 0x8e, + 0xd8, 0x98, 0x2e, 0x72, 0x9d, 0xaa, 0x1e, 0x4f, 0x6c, 0x28, 0x5b, 0x66, 0x23, 0xc1, 0x1d, 0x75, 0xf0, 0xc4, 0xf0, + 0x97, 0x8f, 0x8c, 0x39, 0x48, 0x91, 0x99, 0xe4, 0x89, 0x49, 0xc0, 0x3c, 0xc9, 0x72, 0xa9, 0x98, 0x6d, 0xa6, 0x6b, + 0x6d, 0xcb, 0x21, 0x18, 0x76, 0xa4, 0x0b, 0x6e, 0xac, 0x28, 0xa3, 0x74, 0x4a, 0x54, 0x4f, 0x1d, 0x75, 0xd2, 0x09, + 0xe6, 0x09, 0x70, 0x7a, 0xef, 0x64, 0xcc, 0x1a, 0xe5, 0xad, 0xe8, 0x0c, 0x1d, 0x4e, 0xb1, 0xa8, 0x2e, 0x51, 0x67, + 0xe8, 0x70, 0x82, 0xf0, 0xac, 0x41, 0x72, 0x05, 0x1e, 0xc3, 0x5c, 0xfc, 0x1f, 0x29, 0xff, 0xcd, 0x61, 0x43, 0xd0, + 0xe5, 0xb7, 0xb0, 0x53, 0xd8, 0x28, 0x4a, 0x73, 0x02, 0x5e, 0x8b, 0xed, 0x33, 0x9c, 0x91, 0x49, 0x33, 0xf7, 0x01, + 0xf7, 0x4c, 0x2b, 0x8d, 0x5b, 0x8d, 0x0e, 0x33, 0x3c, 0xda, 0x4c, 0x8a, 0xcd, 0x5c, 0x9b, 0x79, 0x9a, 0xc1, 0xf9, + 0x5e, 0x8d, 0xc2, 0x95, 0x5f, 0x6c, 0x26, 0x85, 0xe5, 0x1d, 0x70, 0x9b, 0x23, 0x2c, 0x9a, 0x14, 0xe7, 0x78, 0xd6, + 0xfc, 0x8a, 0x67, 0xcd, 0x0f, 0x65, 0x46, 0x63, 0x81, 0x05, 0x04, 0xef, 0x83, 0x44, 0x3c, 0xab, 0x92, 0x47, 0x58, + 0x34, 0x4c, 0x79, 0x3c, 0x6b, 0x54, 0xa5, 0x9b, 0x0b, 0x2c, 0x1a, 0xa6, 0x74, 0xe3, 0x03, 0x9e, 0x35, 0xbe, 0xfe, + 0x8b, 0x49, 0x47, 0x29, 0xa0, 0xcb, 0x1c, 0x2d, 0x33, 0x3b, 0xc4, 0xab, 0xdf, 0xde, 0xbe, 0x6b, 0x5f, 0x77, 0x0e, + 0x27, 0xd8, 0xaf, 0x5f, 0x66, 0x70, 0x2c, 0xd3, 0x31, 0x6b, 0x02, 0x44, 0x33, 0xdc, 0x39, 0x9c, 0xe2, 0xce, 0x61, + 0xe6, 0x9a, 0x5a, 0xcf, 0x1a, 0xe4, 0x56, 0x87, 0x50, 0xd4, 0x51, 0x1a, 0xc2, 0xc7, 0x4f, 0x36, 0x9d, 0xa0, 0x1a, + 0x28, 0xd1, 0xe1, 0xa4, 0x06, 0x2a, 0xf8, 0x5e, 0xd4, 0xbe, 0xab, 0x7a, 0x15, 0x06, 0x59, 0x28, 0xa1, 0x70, 0xcd, + 0x0d, 0x78, 0x6a, 0x29, 0x06, 0x32, 0x61, 0x8a, 0x05, 0xca, 0x77, 0x40, 0x61, 0x94, 0x27, 0x66, 0xe8, 0xc1, 0x74, + 0x4c, 0xe2, 0xff, 0xcf, 0x93, 0x29, 0x87, 0x5e, 0x6e, 0x99, 0xad, 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, + 0x3f, 0xac, 0xa0, 0xfb, 0x62, 0xab, 0xfb, 0xc2, 0x74, 0x1f, 0x36, 0x6d, 0x54, 0x39, 0x69, 0x55, 0xc9, 0x92, 0xff, + 0x3a, 0xdd, 0xda, 0x02, 0x8d, 0xa8, 0xd1, 0xb3, 0x49, 0xd8, 0xe0, 0x7e, 0x3b, 0xdd, 0x81, 0xcc, 0x6b, 0x6e, 0xdf, + 0xe6, 0x84, 0xc3, 0x37, 0xb8, 0x53, 0xbd, 0x6c, 0x81, 0xf7, 0xa6, 0x32, 0xfa, 0xca, 0x38, 0xb4, 0x1c, 0x2c, 0x36, + 0x4d, 0xb9, 0x8d, 0xb1, 0x74, 0x72, 0x8a, 0x8d, 0x2b, 0x22, 0x54, 0xba, 0xbd, 0x04, 0xa5, 0xf8, 0x58, 0x37, 0x99, + 0xf9, 0xba, 0xd0, 0x89, 0xb9, 0x84, 0x6a, 0x98, 0xcf, 0xbb, 0x4b, 0x9d, 0x68, 0x39, 0xb7, 0x79, 0x77, 0x17, 0xd0, + 0x27, 0x68, 0x58, 0x1b, 0x81, 0xdd, 0x3e, 0x2b, 0x9c, 0x7e, 0xa7, 0x3a, 0x04, 0xc3, 0x03, 0xc8, 0x91, 0x16, 0xdb, + 0x07, 0x36, 0xad, 0x61, 0xd7, 0x45, 0xb3, 0x4c, 0xb4, 0xad, 0x36, 0x4d, 0xae, 0xdd, 0xc3, 0x7c, 0x1e, 0xf2, 0x14, + 0xbc, 0xb0, 0xfa, 0xf1, 0x1d, 0xec, 0xc6, 0x6d, 0x8d, 0x91, 0xa8, 0x2b, 0x99, 0x4a, 0xe8, 0x27, 0xb7, 0x98, 0x25, + 0x77, 0xc6, 0x8b, 0x51, 0x19, 0x7f, 0x1f, 0x13, 0xa9, 0x3e, 0xaa, 0x24, 0x39, 0xb0, 0xec, 0x6f, 0xb0, 0xe4, 0x16, + 0xcc, 0x13, 0xcb, 0x6a, 0x12, 0xeb, 0xe4, 0x2e, 0x58, 0x44, 0x69, 0x1a, 0x59, 0x1b, 0x06, 0xd4, 0x34, 0x63, 0xd5, + 0x83, 0xfb, 0x10, 0xe8, 0xa1, 0x57, 0x96, 0xd2, 0xae, 0xb3, 0xb4, 0xd6, 0xbd, 0x36, 0xdd, 0x6f, 0x0e, 0x28, 0xe0, + 0x0b, 0x03, 0xae, 0xe9, 0x5f, 0x4d, 0x22, 0x19, 0xb2, 0xaf, 0x9c, 0x15, 0x8f, 0x17, 0x85, 0xc1, 0x34, 0xd1, 0xd3, + 0x49, 0x36, 0x6f, 0x83, 0xa9, 0x5e, 0x36, 0xef, 0xdc, 0x62, 0xf7, 0x7d, 0x67, 0xbf, 0xef, 0xb0, 0xe8, 0x31, 0x93, + 0x91, 0x32, 0x53, 0xcc, 0x7f, 0xdf, 0xd9, 0xef, 0x3b, 0xbc, 0x3d, 0x98, 0x1b, 0x7f, 0xa1, 0x58, 0xb2, 0x33, 0x5c, + 0x82, 0x09, 0x79, 0xc0, 0xdd, 0xd4, 0xb2, 0x4c, 0x10, 0xd8, 0x5a, 0x02, 0xc4, 0xf9, 0x7c, 0x1a, 0x57, 0xbc, 0x1a, + 0x02, 0xee, 0xd3, 0xbb, 0xb6, 0x57, 0xa9, 0xc0, 0x63, 0x82, 0x46, 0xc4, 0xc4, 0xb6, 0x31, 0xef, 0x6a, 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, 0x79, 0x13, 0x79, 0xec, 0x0b, 0xb3, 0x9f, + 0x99, 0x9e, 0x16, 0x72, 0x31, 0x99, 0x82, 0x0f, 0x2d, 0xb0, 0x0c, 0x85, 0xa9, 0x57, 0xd9, 0xfa, 0xd7, 0x24, 0x37, + 0x01, 0x14, 0x4e, 0x37, 0x65, 0x42, 0x33, 0xbd, 0xa0, 0xb9, 0xb1, 0x24, 0xe5, 0x62, 0xf2, 0x48, 0xde, 0xbe, 0x04, + 0xec, 0xa6, 0x44, 0x37, 0x76, 0xe4, 0xbd, 0x85, 0x1d, 0x80, 0x33, 0xc2, 0x76, 0x55, 0x7c, 0xa8, 0x40, 0xe7, 0x8f, + 0x73, 0xc2, 0x76, 0x55, 0x7d, 0xc2, 0x6c, 0xf6, 0x94, 0x6c, 0x0c, 0xb7, 0x17, 0x67, 0x8d, 0x1c, 0x1d, 0x75, 0xd2, + 0xbc, 0xeb, 0x89, 0x81, 0x05, 0x68, 0x00, 0xdc, 0xad, 0xed, 0x59, 0xde, 0xdd, 0x10, 0xd0, 0xbb, 0x64, 0xd2, 0x5e, + 0x97, 0x9b, 0x94, 0xd5, 0xaa, 0x53, 0x51, 0xc1, 0x02, 0x4f, 0x83, 0xbd, 0x40, 0xed, 0xd7, 0x0e, 0x8a, 0x73, 0x95, + 0x6d, 0x9a, 0x9e, 0x97, 0x7d, 0x77, 0x77, 0x2c, 0x32, 0xb6, 0x69, 0x6f, 0x77, 0x10, 0x09, 0xcb, 0x09, 0xeb, 0x80, + 0x13, 0xae, 0x6a, 0x07, 0x04, 0xe8, 0x3a, 0x10, 0xb9, 0xb1, 0x24, 0xcb, 0x75, 0x65, 0x74, 0x1f, 0xf8, 0xdd, 0x52, + 0x22, 0xdd, 0x68, 0x4b, 0x82, 0xe9, 0x13, 0x8c, 0x9a, 0xce, 0x3c, 0x8a, 0x5c, 0x7b, 0xef, 0x77, 0x53, 0xb4, 0xf5, + 0xaf, 0x0f, 0x63, 0xb3, 0x3d, 0x4c, 0x0c, 0x65, 0x10, 0x03, 0xbd, 0x8f, 0x78, 0xb7, 0xd1, 0xc8, 0x10, 0x28, 0x64, + 0xb2, 0x01, 0x96, 0x89, 0xd7, 0xa2, 0x1f, 0x1c, 0x18, 0x78, 0x54, 0x09, 0x08, 0x53, 0x10, 0x42, 0xc2, 0xae, 0x0d, + 0xc2, 0x86, 0xcb, 0x55, 0xcb, 0x85, 0x8d, 0x54, 0x1b, 0x3a, 0xf8, 0x7f, 0x85, 0xcb, 0x56, 0xcf, 0x2c, 0x17, 0xc5, + 0xe0, 0x66, 0x6e, 0xc0, 0x22, 0x41, 0x7a, 0xb4, 0xd9, 0x1e, 0x8a, 0xbb, 0x73, 0xb1, 0xd9, 0x10, 0x90, 0x98, 0xc3, + 0x04, 0x45, 0xc3, 0xb9, 0x31, 0xc6, 0x2a, 0xa9, 0xb4, 0xac, 0x35, 0x89, 0x39, 0xf0, 0xa5, 0x0b, 0xd7, 0x7d, 0x79, + 0x9b, 0x32, 0x7c, 0x97, 0x0a, 0x7c, 0x03, 0x9e, 0x34, 0xa9, 0xc4, 0xee, 0xf1, 0x82, 0x62, 0x4d, 0x74, 0xd7, 0xb3, + 0xb7, 0x05, 0xac, 0xb3, 0xd9, 0x23, 0x22, 0xf8, 0x5d, 0xfd, 0x6a, 0x83, 0xef, 0x16, 0xfe, 0x0a, 0xd6, 0xcf, 0xc1, + 0x49, 0x8a, 0x45, 0x43, 0x36, 0x0b, 0x77, 0x64, 0x40, 0xb9, 0x8a, 0x5f, 0x0e, 0x53, 0xb7, 0x8a, 0xe1, 0xda, 0xc7, + 0x57, 0xfc, 0x61, 0xa3, 0xdd, 0x86, 0x2a, 0x8b, 0xdb, 0xbd, 0x29, 0x1a, 0xb2, 0x6a, 0x7a, 0x47, 0xe6, 0x46, 0x4a, + 0xfd, 0xeb, 0x03, 0x6e, 0x6d, 0xb5, 0xef, 0xa7, 0xf9, 0xd6, 0xa3, 0x73, 0xd5, 0xb4, 0x4f, 0xad, 0x15, 0xc1, 0xc1, + 0xcf, 0x16, 0x6e, 0x6e, 0x0d, 0x38, 0x80, 0x9f, 0xbf, 0xa3, 0x79, 0x9c, 0x41, 0x74, 0x7a, 0xab, 0x19, 0x5f, 0xc5, + 0x7f, 0x8e, 0x1a, 0x71, 0x2f, 0xfd, 0x33, 0xf9, 0x73, 0xd4, 0x40, 0x3d, 0x14, 0xcf, 0x6f, 0x57, 0x6c, 0xb6, 0x82, + 0x60, 0x6b, 0xf7, 0x8e, 0xf0, 0xeb, 0xb0, 0x24, 0xd7, 0x34, 0xe7, 0xd9, 0xca, 0x3d, 0x45, 0xb7, 0x72, 0xef, 0xf4, + 0xac, 0xcc, 0xeb, 0x4a, 0xab, 0x58, 0x0e, 0x73, 0x08, 0x2c, 0x1c, 0xef, 0x35, 0x7b, 0xfd, 0x56, 0xf3, 0xc1, 0xc0, + 0xfe, 0x6b, 0x22, 0xdc, 0xa3, 0x5a, 0xc4, 0xb6, 0x37, 0x1b, 0x5b, 0x3f, 0x06, 0xc3, 0x0e, 0x08, 0x05, 0x0e, 0x72, + 0xe9, 0xe3, 0x0c, 0x59, 0xdf, 0x93, 0xd5, 0x8a, 0xb9, 0x68, 0xd6, 0x4e, 0x83, 0x5f, 0xc6, 0x66, 0x3a, 0x6c, 0x27, + 0x9d, 0xae, 0x17, 0x63, 0x49, 0x03, 0x22, 0x4d, 0x63, 0x06, 0x81, 0xa4, 0x96, 0x86, 0xc3, 0x9a, 0xdf, 0x46, 0x69, + 0x75, 0x7f, 0x04, 0x29, 0x3f, 0x44, 0x29, 0x3f, 0x22, 0x10, 0x40, 0xdb, 0x32, 0x47, 0x65, 0x43, 0xde, 0x77, 0xe9, + 0x9e, 0x71, 0x66, 0x68, 0xf0, 0xd5, 0xaa, 0x55, 0x0d, 0x53, 0x14, 0xf5, 0x61, 0x2e, 0xd7, 0x58, 0x90, 0x37, 0xa0, + 0x6b, 0x56, 0x44, 0xf4, 0x42, 0x57, 0x79, 0x78, 0x89, 0x17, 0x4b, 0x02, 0x4e, 0xfa, 0x3d, 0xd1, 0x2b, 0xc8, 0xe5, + 0xc3, 0x18, 0x7c, 0xcc, 0x30, 0xef, 0xeb, 0x7e, 0x31, 0x18, 0xa0, 0xd4, 0x39, 0x9d, 0xa5, 0x26, 0xe2, 0x4a, 0xe0, + 0x97, 0x5c, 0x80, 0x5f, 0xb2, 0x42, 0xac, 0x5f, 0x0c, 0xc8, 0xbd, 0x2c, 0x96, 0xe0, 0x94, 0xbf, 0xc3, 0xe7, 0xf1, + 0x61, 0x68, 0x60, 0x6a, 0x86, 0x65, 0x2e, 0xb2, 0xc1, 0x62, 0xce, 0x5a, 0x02, 0xc1, 0xcd, 0x80, 0xbb, 0xd4, 0x86, + 0x44, 0x63, 0x0d, 0x14, 0xdd, 0x46, 0xa1, 0x99, 0xd1, 0xd3, 0xad, 0x36, 0xfa, 0x91, 0xc3, 0x0b, 0x73, 0x0d, 0x63, + 0x11, 0xc8, 0x5c, 0xae, 0x7a, 0xec, 0x2f, 0x3f, 0x6c, 0x56, 0x18, 0xbc, 0xc2, 0x98, 0xec, 0x94, 0x56, 0x89, 0x66, + 0x7c, 0x95, 0x27, 0x8e, 0x21, 0xc8, 0xc4, 0x52, 0xe9, 0x86, 0x63, 0xe2, 0x4a, 0xfa, 0x4c, 0x0c, 0xd9, 0x6e, 0x78, + 0x66, 0x2e, 0x74, 0xb3, 0xfd, 0xc3, 0xb9, 0x9d, 0x73, 0xc2, 0x8d, 0x56, 0xd2, 0x68, 0xa3, 0x9e, 0x19, 0xaa, 0xea, + 0x82, 0xf9, 0x3d, 0x74, 0x5a, 0x5a, 0xec, 0x5c, 0xbd, 0xbb, 0xe1, 0xbb, 0x70, 0x65, 0xfc, 0x2d, 0x56, 0x85, 0x56, + 0x64, 0xb8, 0xdd, 0x42, 0xde, 0x9c, 0xe9, 0xa1, 0x57, 0xe4, 0x42, 0x75, 0xf8, 0x8b, 0xba, 0xc2, 0x3c, 0x15, 0x19, + 0x35, 0x84, 0x47, 0xbf, 0xd7, 0x19, 0x28, 0xff, 0x60, 0x62, 0x32, 0x67, 0xc9, 0x0d, 0x2d, 0x44, 0xfc, 0xe3, 0x0b, + 0x61, 0x62, 0x55, 0xed, 0xc1, 0x40, 0xf6, 0x4c, 0xc5, 0x3d, 0xb8, 0x35, 0xe1, 0x63, 0xce, 0x46, 0xe9, 0x5e, 0xf4, + 0x63, 0x43, 0x34, 0x7e, 0x8c, 0x7e, 0x04, 0x77, 0x67, 0xf7, 0x2e, 0x61, 0x19, 0x17, 0xc2, 0xdf, 0x63, 0x3d, 0x2c, + 0x55, 0xca, 0x58, 0x7b, 0xdd, 0x72, 0x78, 0x21, 0xf5, 0x26, 0x8b, 0x1f, 0x3a, 0x62, 0x6d, 0x53, 0xb0, 0x0e, 0x29, + 0x29, 0x3c, 0xbb, 0x62, 0x6e, 0xb5, 0x98, 0xbb, 0xd4, 0x12, 0xfe, 0xfa, 0xea, 0x61, 0xa9, 0x82, 0x86, 0x83, 0xd0, + 0x95, 0xb6, 0x90, 0x00, 0x03, 0x97, 0xd2, 0xa7, 0xd3, 0x9d, 0x49, 0x64, 0x96, 0xc5, 0xf0, 0xee, 0x41, 0x05, 0xf3, + 0xdf, 0xd9, 0x46, 0x58, 0x15, 0xb8, 0x5c, 0xa9, 0xa2, 0x5e, 0x4a, 0x02, 0x01, 0xe8, 0x4b, 0xef, 0x41, 0x79, 0x51, + 0x74, 0x1b, 0x0d, 0x09, 0x5a, 0x58, 0x6a, 0xae, 0x55, 0x31, 0xdd, 0x0f, 0xdf, 0xd3, 0x0b, 0x3e, 0xbc, 0x43, 0xda, + 0xc6, 0xa3, 0x96, 0x94, 0x50, 0xbb, 0x83, 0xf6, 0xc1, 0x2a, 0x3b, 0x28, 0xff, 0x36, 0xa6, 0xc8, 0xe6, 0xf7, 0xd9, + 0x0f, 0xd4, 0x75, 0x38, 0x70, 0x05, 0xab, 0x5e, 0xca, 0x28, 0x18, 0xc2, 0x3e, 0x60, 0x1f, 0x8b, 0x24, 0xa3, 0xd9, + 0x94, 0x81, 0xba, 0xdf, 0x16, 0xad, 0xe6, 0xf6, 0xa4, 0xee, 0x37, 0x64, 0x9c, 0x7d, 0x84, 0x71, 0xf6, 0x51, 0xe0, + 0xc5, 0x22, 0xc9, 0x1f, 0x32, 0xd6, 0x38, 0x56, 0x4d, 0x81, 0x8e, 0x3a, 0xc0, 0x9d, 0x81, 0x03, 0x0f, 0xd8, 0xa2, + 0x1c, 0x1c, 0x50, 0x67, 0x71, 0x4f, 0x1b, 0x99, 0xf7, 0xf6, 0x84, 0xda, 0x45, 0x2c, 0x70, 0xb3, 0x66, 0xa6, 0x05, + 0xad, 0x15, 0xc6, 0x79, 0x3c, 0xe0, 0x6d, 0x9e, 0xd5, 0xe2, 0x27, 0x6c, 0x58, 0x53, 0xd5, 0x6f, 0xa0, 0x39, 0xaa, + 0x05, 0xb9, 0x79, 0x62, 0xbc, 0x55, 0x49, 0x3f, 0x8a, 0x06, 0x96, 0x53, 0x21, 0x86, 0x64, 0xf4, 0x5b, 0x83, 0xe0, + 0x56, 0x7b, 0xb5, 0xe2, 0x1e, 0xf1, 0x45, 0xcd, 0x5b, 0xcd, 0xdc, 0x02, 0xd0, 0x22, 0x8e, 0xca, 0x7b, 0x93, 0x08, + 0xbc, 0x6f, 0xcb, 0x08, 0x69, 0xcb, 0xbe, 0x7d, 0x34, 0xb1, 0x54, 0x6c, 0xbe, 0xa3, 0x93, 0x41, 0x1a, 0xd9, 0x11, + 0x45, 0xf8, 0xba, 0x84, 0x24, 0x5c, 0x25, 0x5d, 0xab, 0x4c, 0xce, 0x99, 0x4a, 0x39, 0xbe, 0x2e, 0xa4, 0xd4, 0x57, + 0xf6, 0x4b, 0xe2, 0xea, 0x4e, 0x46, 0xe0, 0xeb, 0x09, 0xd3, 0xef, 0x68, 0x31, 0x61, 0xe0, 0x57, 0xe4, 0x6f, 0xc7, + 0x52, 0x4a, 0x2e, 0x9f, 0x88, 0xb8, 0x4f, 0x31, 0xbc, 0xf8, 0x39, 0xc0, 0xda, 0x84, 0x40, 0x29, 0x71, 0x11, 0x2e, + 0x88, 0xde, 0x14, 0xf2, 0xf6, 0x2e, 0x2e, 0xb0, 0x73, 0x00, 0x2c, 0x9d, 0x26, 0x01, 0xfe, 0xe5, 0x63, 0x3e, 0x56, + 0x63, 0x4e, 0x8d, 0xae, 0xdf, 0xfd, 0x4e, 0xae, 0x81, 0xde, 0x96, 0x8e, 0x82, 0xfd, 0xd6, 0x00, 0x72, 0xe1, 0x2e, + 0x0c, 0x2e, 0xbe, 0xc2, 0xda, 0xb2, 0x30, 0xde, 0x58, 0x00, 0xbd, 0xbf, 0x33, 0xb0, 0x60, 0xc3, 0x1c, 0x53, 0x78, + 0x2e, 0x75, 0xc2, 0x74, 0x10, 0x15, 0xe4, 0x49, 0xf9, 0x20, 0x66, 0xad, 0xf6, 0x5b, 0x36, 0x86, 0x3b, 0x8c, 0xe4, + 0xdb, 0x85, 0x13, 0x07, 0x1e, 0x90, 0x69, 0x32, 0xdb, 0xec, 0x1b, 0x1f, 0x79, 0xe4, 0xf5, 0x38, 0xde, 0xd5, 0x52, + 0x98, 0x6f, 0x56, 0x74, 0x8d, 0x21, 0x14, 0x45, 0xd8, 0xef, 0x17, 0x15, 0x53, 0x54, 0x19, 0xb4, 0x41, 0xc3, 0xf2, + 0x46, 0xfc, 0x02, 0x67, 0x0c, 0xad, 0x17, 0xb2, 0x77, 0x74, 0xd6, 0xe1, 0xcc, 0x61, 0xc6, 0x94, 0xc0, 0xa8, 0xb4, + 0x2c, 0xe8, 0x04, 0x1c, 0x9d, 0xab, 0x0f, 0xa2, 0xe2, 0xea, 0x58, 0x01, 0x78, 0x92, 0x29, 0xfc, 0x93, 0x6f, 0x82, + 0x75, 0xbf, 0x55, 0x33, 0x4c, 0xfd, 0x45, 0x6f, 0xbb, 0x96, 0x2f, 0x43, 0x1c, 0x69, 0x63, 0x08, 0xad, 0x73, 0x7b, + 0x07, 0x28, 0xe2, 0x82, 0x5e, 0xa4, 0x1a, 0x5f, 0xab, 0xc5, 0xd0, 0xac, 0xaf, 0x71, 0x1d, 0xd3, 0x06, 0x51, 0xac, + 0xbb, 0x26, 0xbe, 0xae, 0xde, 0x1f, 0x55, 0xa9, 0x82, 0x33, 0x48, 0x20, 0xac, 0xca, 0xcb, 0x86, 0x54, 0x92, 0x4b, + 0xd3, 0xa9, 0x34, 0x9d, 0x56, 0x08, 0xe5, 0xd2, 0x93, 0xf2, 0xfe, 0x15, 0x42, 0x18, 0x98, 0x32, 0x3b, 0xb0, 0x4a, + 0x6d, 0x61, 0x15, 0xbc, 0x7a, 0xb1, 0x81, 0x55, 0x12, 0x8e, 0xe7, 0x12, 0x8d, 0x8a, 0x0a, 0x87, 0x0c, 0xe9, 0x0b, + 0xb1, 0x08, 0x12, 0x00, 0x8b, 0xde, 0x65, 0x2e, 0xef, 0x7b, 0x38, 0x14, 0xf6, 0x24, 0x93, 0x70, 0xba, 0x09, 0xcd, + 0xe1, 0x61, 0x5a, 0xd5, 0xf3, 0x08, 0x01, 0x4b, 0xcf, 0x31, 0x3c, 0x48, 0xfc, 0xfd, 0x87, 0x50, 0x9d, 0x05, 0x79, + 0xfa, 0x2f, 0x51, 0x12, 0x1a, 0xfb, 0xcf, 0xf1, 0xd0, 0x21, 0x61, 0x38, 0xf0, 0xcd, 0x11, 0x56, 0x38, 0xb8, 0x55, + 0xc4, 0x67, 0x70, 0x87, 0x8f, 0x75, 0xe8, 0x01, 0x60, 0x09, 0xc5, 0x21, 0xc8, 0x37, 0x50, 0xcc, 0xe0, 0x80, 0x26, + 0xcb, 0xf0, 0x02, 0x17, 0xac, 0x16, 0xca, 0xfb, 0xdb, 0x96, 0x97, 0xd2, 0x6a, 0x97, 0xbc, 0xc6, 0x1c, 0xa8, 0xfc, + 0x0c, 0x2f, 0x7c, 0x85, 0x79, 0x29, 0xd9, 0x7d, 0xe1, 0x6b, 0x07, 0xf4, 0x14, 0x02, 0x46, 0xba, 0xdf, 0x6b, 0xc2, + 0x3d, 0x45, 0x2f, 0x73, 0x71, 0xd8, 0x76, 0xd0, 0xbd, 0xc0, 0x5c, 0x5d, 0x55, 0x59, 0x73, 0x30, 0x85, 0x06, 0x07, + 0x55, 0x38, 0x23, 0x30, 0x57, 0x2f, 0xca, 0x82, 0x73, 0x10, 0xef, 0x7b, 0xc2, 0xe4, 0x94, 0xd1, 0x00, 0x5e, 0x64, + 0xe5, 0xa3, 0x53, 0x3d, 0x0e, 0x2e, 0xe3, 0x86, 0x4d, 0x7c, 0x21, 0x7c, 0x2a, 0xb0, 0x92, 0xd6, 0x38, 0x34, 0xa2, + 0x23, 0x3a, 0x07, 0xb3, 0x0d, 0xa0, 0xe0, 0xee, 0x7c, 0xd8, 0x58, 0xa8, 0xe0, 0x31, 0xd8, 0xda, 0xdb, 0xcd, 0x84, + 0x38, 0x93, 0xa6, 0xe0, 0x6e, 0xdb, 0x20, 0x83, 0x37, 0xbf, 0xfd, 0xb7, 0xc2, 0x22, 0xc1, 0x80, 0x4a, 0x4d, 0x12, + 0x84, 0x27, 0x28, 0x8d, 0x74, 0x2b, 0x37, 0x13, 0x48, 0x27, 0xa2, 0x66, 0xd4, 0xbd, 0x71, 0xbe, 0x3a, 0x6a, 0x20, + 0x2a, 0x6a, 0xa0, 0x02, 0x6a, 0x20, 0xeb, 0xdb, 0xbf, 0x80, 0x85, 0xb0, 0x11, 0xaa, 0x44, 0x10, 0x10, 0x61, 0xae, + 0x0d, 0x1f, 0x50, 0x24, 0x21, 0xe4, 0x0d, 0xa0, 0x62, 0x4a, 0x5e, 0x82, 0xd1, 0x38, 0xbc, 0xde, 0x03, 0xee, 0x97, + 0x96, 0x61, 0xf0, 0x9c, 0x82, 0xc9, 0x7f, 0xeb, 0xf3, 0xa1, 0x7a, 0xb9, 0x3a, 0x08, 0xe1, 0x17, 0x10, 0x2b, 0xc2, + 0xf1, 0x17, 0xbf, 0x00, 0xd9, 0x54, 0x58, 0x1e, 0x1c, 0x48, 0x10, 0xf8, 0x21, 0x8a, 0x70, 0xc0, 0x33, 0xbc, 0xcc, + 0x36, 0x88, 0x9e, 0x9f, 0x95, 0xaa, 0x66, 0x25, 0x83, 0x59, 0x15, 0x9e, 0xc6, 0xd1, 0x35, 0x61, 0x20, 0xb8, 0x50, + 0xbb, 0x6f, 0x10, 0x02, 0x65, 0xcb, 0x8d, 0xa1, 0x4b, 0x4f, 0xc1, 0x7c, 0x34, 0x8e, 0xde, 0x32, 0x78, 0xd2, 0xd6, + 0x98, 0xfc, 0x33, 0x6d, 0x1e, 0xb8, 0x4f, 0xf7, 0xa2, 0x46, 0xe0, 0xa4, 0x4e, 0x51, 0xf2, 0xb7, 0xe4, 0x22, 0x8e, + 0x9a, 0x97, 0x11, 0x6a, 0xc0, 0xbf, 0x0d, 0x8e, 0xba, 0x34, 0xa1, 0xa3, 0x91, 0x0f, 0x7e, 0x93, 0x11, 0xb3, 0xc9, + 0x56, 0x2b, 0x51, 0x11, 0xf4, 0xc4, 0x6e, 0x30, 0x60, 0x25, 0x5e, 0x00, 0xfb, 0x60, 0x39, 0x58, 0xf2, 0x4e, 0xc4, + 0xca, 0x9f, 0x52, 0x18, 0xac, 0x9e, 0x33, 0x84, 0x70, 0x16, 0xc4, 0x6c, 0xfc, 0xcf, 0x67, 0x1a, 0xae, 0x9f, 0x9f, + 0xaf, 0x63, 0x44, 0xa4, 0x0f, 0x22, 0x57, 0x63, 0x47, 0x44, 0x10, 0xb6, 0x4c, 0xf7, 0x5d, 0x99, 0x1f, 0xbc, 0x75, + 0xf5, 0xc0, 0x86, 0x8b, 0x03, 0x03, 0x6a, 0x14, 0x18, 0xad, 0xe0, 0x9c, 0x94, 0x03, 0x07, 0x25, 0x84, 0x66, 0x45, + 0x3c, 0x25, 0x97, 0x10, 0x09, 0x2f, 0x43, 0x5d, 0x30, 0x2c, 0x08, 0x24, 0xa8, 0x29, 0x48, 0x50, 0x99, 0xaf, 0x3d, + 0x82, 0x59, 0xe7, 0x66, 0xb6, 0x53, 0xd4, 0x75, 0x41, 0x7e, 0x7e, 0xd1, 0xf1, 0x08, 0x58, 0xda, 0x83, 0x83, 0x02, + 0x22, 0x88, 0x01, 0x05, 0x2f, 0x25, 0xc0, 0x40, 0x03, 0x5e, 0x6c, 0x68, 0xc0, 0xe7, 0xda, 0x78, 0x1d, 0x18, 0x5b, + 0x9f, 0x32, 0xc8, 0xc5, 0xb3, 0x6a, 0x4f, 0x13, 0x42, 0xf6, 0x5b, 0x3d, 0x9d, 0x6e, 0x47, 0x48, 0xec, 0x7d, 0xd4, + 0x26, 0xd0, 0x98, 0x23, 0xdd, 0xd5, 0xc6, 0xfc, 0x5a, 0xd3, 0x23, 0x56, 0x93, 0x90, 0x2e, 0x48, 0x97, 0xe7, 0xd3, + 0x9e, 0xc1, 0x15, 0xab, 0x34, 0x72, 0x70, 0x01, 0xfa, 0x6c, 0x40, 0x80, 0x02, 0x95, 0xa6, 0x12, 0x45, 0x11, 0x17, + 0x49, 0xc9, 0x86, 0x61, 0x06, 0x61, 0x0a, 0xab, 0x95, 0xa0, 0x1b, 0x6b, 0x00, 0xbc, 0x33, 0xb3, 0x7f, 0x4a, 0x1f, + 0x6c, 0xba, 0xf6, 0xe6, 0x11, 0x40, 0x40, 0xf6, 0xdb, 0x25, 0xbb, 0x2e, 0x36, 0x2a, 0xb3, 0xb0, 0x96, 0xb1, 0x95, + 0xdb, 0xf6, 0x18, 0x7b, 0x27, 0xb6, 0xf9, 0x04, 0x08, 0x51, 0x5b, 0x32, 0x8d, 0x10, 0x21, 0xb1, 0x88, 0x75, 0x6d, + 0xc8, 0x46, 0x1b, 0xda, 0x37, 0x4f, 0xc2, 0x43, 0xec, 0x03, 0x50, 0xbc, 0x39, 0x2e, 0xc1, 0x21, 0xbc, 0xf0, 0x08, + 0x7f, 0x0b, 0x2c, 0x52, 0x81, 0x19, 0x96, 0xab, 0x15, 0xd4, 0xf3, 0x78, 0x9f, 0x6d, 0x06, 0x27, 0x95, 0x1b, 0x63, + 0x97, 0x76, 0xe2, 0x71, 0xd9, 0x84, 0xc4, 0x19, 0xf4, 0xeb, 0x2b, 0xa2, 0xde, 0x7e, 0x3b, 0x7d, 0xe2, 0xdf, 0x2b, + 0x73, 0x3b, 0x10, 0x1b, 0xd6, 0x1b, 0xac, 0x3e, 0x80, 0x96, 0xbf, 0xca, 0xfc, 0x43, 0x65, 0xc1, 0x4d, 0x82, 0xda, + 0x5c, 0xc4, 0x2e, 0xeb, 0x22, 0x46, 0x6a, 0x8b, 0xbb, 0x43, 0x88, 0x7f, 0xb5, 0x15, 0xc5, 0x80, 0x27, 0x15, 0xff, + 0x1c, 0xa3, 0x2e, 0x84, 0xa2, 0xb6, 0x1e, 0x36, 0x40, 0x69, 0x97, 0xeb, 0x4a, 0x8c, 0x0c, 0x09, 0xe4, 0x5b, 0x17, + 0x5e, 0xd0, 0x9c, 0x44, 0x0a, 0xe4, 0xe4, 0x20, 0x2a, 0x69, 0xb6, 0x21, 0xcc, 0x75, 0xb7, 0x70, 0xcc, 0x5c, 0x6d, + 0xd0, 0x22, 0x7e, 0x01, 0xec, 0x0c, 0x37, 0x92, 0xa5, 0x03, 0x9f, 0xaa, 0x81, 0xcf, 0xaf, 0xb9, 0xa1, 0x28, 0x0a, + 0xf5, 0xde, 0xd9, 0x47, 0xe6, 0xe0, 0x77, 0x1a, 0x88, 0x8f, 0xd4, 0xe9, 0x48, 0x36, 0x42, 0xad, 0x39, 0x3b, 0x5e, + 0xb6, 0x19, 0x61, 0x50, 0xd8, 0xe8, 0x7d, 0x15, 0xb2, 0x8a, 0x9d, 0x9d, 0x8a, 0x60, 0x4e, 0x5f, 0x54, 0xe5, 0x9c, + 0xca, 0x2d, 0xa3, 0x5a, 0x6a, 0x1a, 0x20, 0xc2, 0x95, 0x4f, 0x24, 0xef, 0x33, 0x13, 0xfe, 0xc1, 0x60, 0x5c, 0x3d, + 0x52, 0xf8, 0xfb, 0x5d, 0xb1, 0x43, 0xb6, 0xa3, 0xc3, 0x6d, 0x04, 0xcd, 0x0b, 0x15, 0x3c, 0xe0, 0xa8, 0x64, 0x09, + 0x91, 0x22, 0x97, 0xfb, 0xaa, 0x66, 0xca, 0x76, 0x1d, 0x21, 0x84, 0xb4, 0xc7, 0x59, 0x37, 0xb4, 0x7a, 0xe8, 0x91, + 0x2a, 0xca, 0xe1, 0x16, 0xcd, 0x75, 0x01, 0x2a, 0x8c, 0x40, 0xba, 0xfc, 0xcc, 0xee, 0x52, 0x09, 0xd1, 0xcb, 0xd7, + 0x2e, 0x84, 0xb1, 0xb3, 0xb2, 0xc4, 0x85, 0x19, 0xb5, 0x0d, 0xa3, 0xeb, 0x36, 0x86, 0xb3, 0x81, 0x31, 0xd3, 0xa0, + 0xa4, 0x05, 0xa1, 0xae, 0xbb, 0xf4, 0x22, 0x33, 0x81, 0x1e, 0x73, 0x42, 0x1b, 0x0c, 0x4f, 0x89, 0x06, 0xcb, 0xa6, + 0x02, 0x2c, 0xf8, 0x96, 0x45, 0x6a, 0x6d, 0x36, 0x59, 0xfc, 0x51, 0xc7, 0xe6, 0x69, 0xbf, 0xbc, 0x62, 0x9e, 0x0b, + 0x47, 0xdd, 0x9e, 0x67, 0x3e, 0x1e, 0xdd, 0xd3, 0x37, 0x57, 0x2f, 0x5e, 0xbe, 0x7e, 0xb5, 0x5a, 0xb5, 0x59, 0xb3, + 0x7d, 0x82, 0x7f, 0xd2, 0x65, 0x3c, 0xd8, 0x32, 0x0a, 0xd0, 0xc1, 0xc1, 0x3e, 0x37, 0x2e, 0x3c, 0x9f, 0xf9, 0x1c, + 0xe2, 0x06, 0xe9, 0x01, 0xce, 0x8a, 0x32, 0x26, 0xc8, 0x6d, 0xd4, 0x8b, 0xee, 0x22, 0x50, 0x42, 0x55, 0xe4, 0xef, + 0xc3, 0xe6, 0xec, 0xf7, 0x20, 0x30, 0x11, 0xd4, 0x87, 0x08, 0x20, 0x10, 0xaf, 0x14, 0x17, 0x84, 0xf9, 0x04, 0x88, + 0xe2, 0xbd, 0x00, 0xce, 0xd4, 0x44, 0xad, 0x5a, 0xa8, 0xb8, 0x00, 0x92, 0x68, 0xc3, 0x51, 0xd2, 0x23, 0x13, 0xc0, + 0x1b, 0x82, 0x52, 0xda, 0x5f, 0xdd, 0xdc, 0xb9, 0x4b, 0xe5, 0xa8, 0xd7, 0x4a, 0x73, 0x3c, 0x75, 0x9f, 0x53, 0xf8, + 0x9c, 0x76, 0xfd, 0xe9, 0x20, 0x0e, 0x73, 0xbc, 0x20, 0xe2, 0xd0, 0x3f, 0x8b, 0xb8, 0x9c, 0x17, 0xec, 0x0b, 0x97, + 0x0b, 0x95, 0x2e, 0x6f, 0x53, 0x99, 0xdc, 0x36, 0x47, 0x87, 0x71, 0x91, 0xdc, 0x36, 0x55, 0x72, 0x8b, 0xf0, 0x5d, + 0x2a, 0x93, 0x3b, 0x9b, 0x72, 0xd7, 0x54, 0x70, 0xf3, 0x85, 0x05, 0x1c, 0x8a, 0xb6, 0x68, 0x63, 0xb1, 0x59, 0xd4, + 0xa6, 0xb8, 0xa2, 0x01, 0x06, 0xff, 0xbe, 0x63, 0xe3, 0x87, 0xe1, 0x4b, 0x70, 0x69, 0xd2, 0x44, 0x7e, 0x02, 0xe9, + 0xa7, 0x55, 0x19, 0xb8, 0x4f, 0x49, 0xab, 0x3b, 0xbd, 0x10, 0xcd, 0x76, 0xb7, 0xd1, 0x98, 0xc2, 0xde, 0xcd, 0x48, + 0xee, 0x8b, 0x4d, 0x1b, 0x26, 0xbe, 0xce, 0x7e, 0xb6, 0x5a, 0xed, 0xe7, 0xc8, 0x6c, 0xb8, 0x09, 0x8b, 0x75, 0x7f, + 0x3a, 0xc0, 0x2d, 0xfc, 0x3c, 0x43, 0x68, 0xc9, 0xfa, 0xd3, 0x01, 0x61, 0xfd, 0x69, 0xa3, 0x3d, 0xb0, 0x86, 0x76, + 0x66, 0x2b, 0xae, 0x21, 0x84, 0xe6, 0x74, 0x70, 0x64, 0x4a, 0x4a, 0x97, 0x6f, 0xbf, 0x68, 0x15, 0xd0, 0x4f, 0xd5, + 0x82, 0x97, 0x49, 0xdc, 0x81, 0xbe, 0xe8, 0x85, 0x7d, 0xba, 0xb5, 0x20, 0xc7, 0x47, 0x95, 0xab, 0x3d, 0x45, 0xd8, + 0xf4, 0xa4, 0x0e, 0x8b, 0x43, 0xd3, 0x8c, 0xeb, 0x52, 0xba, 0xef, 0x50, 0x33, 0xf2, 0xd1, 0xc1, 0x02, 0x10, 0xa4, + 0x82, 0x47, 0x56, 0xb8, 0x70, 0x4a, 0x21, 0x5c, 0x1c, 0x54, 0xb6, 0x60, 0x92, 0x93, 0x56, 0x37, 0x37, 0x96, 0xfe, + 0xb9, 0x8b, 0x68, 0x4a, 0x31, 0x25, 0x99, 0x2f, 0x99, 0x1b, 0xb0, 0xd0, 0x4d, 0xca, 0x33, 0x05, 0xbd, 0xd2, 0x00, + 0x8f, 0x08, 0xc4, 0x43, 0xea, 0x16, 0xc6, 0xc0, 0x2b, 0x9e, 0x36, 0x8b, 0x3e, 0x1b, 0xa0, 0xa3, 0x63, 0x4c, 0xfb, + 0x7f, 0x65, 0xf3, 0x36, 0x3c, 0x16, 0xf8, 0xd7, 0x80, 0x4c, 0x9b, 0xb2, 0x4c, 0x10, 0x90, 0x30, 0x6a, 0xca, 0x43, + 0xd8, 0x4b, 0x08, 0x67, 0xb6, 0x62, 0xd6, 0x67, 0x83, 0xe6, 0xb4, 0xac, 0xd8, 0xf1, 0x15, 0x1b, 0xb2, 0x4c, 0xb0, + 0x15, 0x1b, 0xae, 0x62, 0xf8, 0x3a, 0x83, 0x01, 0x41, 0x08, 0x00, 0x06, 0x00, 0xd0, 0x28, 0x88, 0xe6, 0x8b, 0x15, + 0xf1, 0x9b, 0xdd, 0xde, 0xe3, 0xb7, 0xc0, 0x02, 0xad, 0xb6, 0xff, 0x77, 0xa1, 0x0c, 0xd8, 0x53, 0x16, 0x26, 0x66, + 0x6e, 0x61, 0x55, 0x74, 0x00, 0x95, 0x12, 0x61, 0x0a, 0x03, 0x99, 0xfd, 0xcc, 0x40, 0x2d, 0xd0, 0x1a, 0xe4, 0x7d, + 0x3d, 0x68, 0x66, 0x70, 0xc4, 0xc0, 0x3b, 0x34, 0x64, 0x6a, 0x8c, 0x09, 0xe3, 0x1c, 0xa6, 0x98, 0x19, 0xf0, 0x4c, + 0xd3, 0xd6, 0x5a, 0x1a, 0x59, 0xae, 0x97, 0xf7, 0xfe, 0xd1, 0xb1, 0xea, 0x17, 0xcd, 0xf6, 0x00, 0xed, 0x13, 0x62, + 0x3f, 0x06, 0xb0, 0xc9, 0x5c, 0x6a, 0xc3, 0x7c, 0x1f, 0x75, 0x52, 0xfb, 0x09, 0x7f, 0x06, 0x6b, 0xb3, 0x03, 0x40, + 0x47, 0x86, 0xcd, 0xfa, 0xcb, 0x9a, 0xca, 0xeb, 0xe3, 0xce, 0x28, 0x95, 0xbb, 0xde, 0x9d, 0x0e, 0x34, 0xc5, 0xa1, + 0xb7, 0x1e, 0x2e, 0x1f, 0xea, 0x21, 0x60, 0xc6, 0x60, 0x6e, 0x99, 0xd1, 0xf7, 0x42, 0x24, 0x17, 0x44, 0x62, 0x69, + 0xb0, 0x86, 0xc1, 0xde, 0x3a, 0x38, 0x30, 0xd5, 0x58, 0x03, 0x9e, 0x27, 0x45, 0x20, 0x18, 0xf8, 0x08, 0xca, 0x80, + 0x26, 0xca, 0xdc, 0x86, 0x93, 0x8f, 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, 0xdd, 0xcd, 0x74, + 0xca, 0x66, 0x3a, 0xdb, 0xcd, 0x84, 0x9a, 0x99, 0x6f, 0x59, 0x45, 0x9a, 0x93, 0x35, 0x51, 0x73, 0x2a, 0x7e, 0xa2, + 0x73, 0xd0, 0x8e, 0x72, 0x7b, 0xaf, 0x0a, 0x27, 0x57, 0x4e, 0x2e, 0xf7, 0x73, 0x43, 0x5c, 0x91, 0xb9, 0x50, 0x87, + 0x00, 0x2f, 0x2f, 0xca, 0xc7, 0x07, 0xb8, 0x14, 0xbf, 0xca, 0x91, 0x8b, 0x72, 0x2a, 0xa4, 0x96, 0x82, 0x45, 0xc8, + 0xa0, 0xaa, 0x8b, 0x81, 0xbd, 0xb4, 0x7b, 0x4f, 0xf4, 0x78, 0xbf, 0x8a, 0x98, 0x37, 0x30, 0xcf, 0x7d, 0x7c, 0x4f, + 0x53, 0xec, 0xd4, 0xc4, 0x19, 0xf9, 0x90, 0xc5, 0x39, 0xc8, 0x66, 0xfd, 0xea, 0xb5, 0xdf, 0x46, 0x1b, 0x17, 0xcd, + 0x58, 0xf4, 0xcc, 0x13, 0x27, 0x3f, 0x14, 0xc6, 0x38, 0xc0, 0x3a, 0xfa, 0x23, 0x4c, 0x2d, 0xd8, 0xb3, 0xc4, 0x53, + 0xe8, 0xe4, 0xd6, 0xa6, 0xdd, 0x85, 0x69, 0x77, 0x26, 0xad, 0x03, 0xe5, 0x80, 0x34, 0xbb, 0x32, 0x9d, 0x3b, 0xff, + 0x7d, 0x07, 0x2f, 0xdd, 0xae, 0x21, 0x12, 0xf7, 0xfc, 0x91, 0x31, 0x86, 0x78, 0x03, 0x36, 0xa2, 0xea, 0xe0, 0xe0, + 0x0f, 0xe7, 0x7d, 0x5b, 0xc9, 0x7d, 0xdf, 0x0a, 0x07, 0xb6, 0xc1, 0x54, 0xba, 0xbc, 0x91, 0xcc, 0x16, 0x60, 0xd7, + 0xb9, 0xff, 0x8d, 0x78, 0xf8, 0x22, 0x64, 0x5a, 0xac, 0xab, 0xf8, 0x2b, 0x39, 0x2a, 0x3d, 0x44, 0x35, 0x44, 0x20, + 0xad, 0xac, 0x4b, 0x43, 0xd3, 0xd1, 0xab, 0x29, 0x1d, 0xc9, 0x9b, 0xb7, 0x52, 0xea, 0x81, 0x7d, 0x91, 0x5b, 0x27, + 0xf0, 0x68, 0x61, 0x8d, 0xa1, 0xb9, 0x2b, 0xbd, 0x93, 0x6c, 0x40, 0xd4, 0xfa, 0xb8, 0x43, 0x49, 0x24, 0x16, 0xd5, + 0x5d, 0x08, 0x87, 0xbb, 0x10, 0xcc, 0xcb, 0xa0, 0x6d, 0x10, 0xbb, 0xdd, 0x05, 0x6d, 0x03, 0xa7, 0x6e, 0x1b, 0xb8, + 0x3d, 0x18, 0x2c, 0xec, 0x7d, 0x78, 0x39, 0x96, 0x63, 0xe1, 0xaf, 0xc9, 0xec, 0x03, 0x40, 0xa0, 0xf6, 0x61, 0xc5, + 0x13, 0x07, 0x82, 0xc4, 0x19, 0x8e, 0xbe, 0xe7, 0xec, 0xc6, 0x5a, 0x0e, 0xcf, 0xe6, 0x0b, 0xcd, 0x46, 0xe6, 0x8e, + 0x1a, 0x54, 0x7c, 0x75, 0x3f, 0xaf, 0x9f, 0xb2, 0x9a, 0x6e, 0xfc, 0x1e, 0x84, 0x91, 0x70, 0xca, 0x0e, 0xa3, 0x90, + 0xb0, 0xc1, 0xac, 0xca, 0x78, 0x6d, 0xbf, 0x41, 0xbc, 0x07, 0x6d, 0xc2, 0x09, 0x16, 0xb5, 0x0b, 0xaa, 0x08, 0xdb, + 0x78, 0x63, 0x41, 0x94, 0x87, 0x37, 0x5b, 0x46, 0xd3, 0xcb, 0x35, 0x04, 0x3a, 0xee, 0x45, 0xcd, 0xa8, 0xc1, 0x52, + 0x17, 0x94, 0xd9, 0x47, 0x18, 0x57, 0x17, 0x27, 0x26, 0x4e, 0x7b, 0xa9, 0x57, 0xff, 0x2d, 0x03, 0x03, 0x7c, 0x01, + 0x5e, 0x62, 0x61, 0x74, 0xd7, 0xbe, 0x6e, 0x40, 0x7d, 0xd9, 0x60, 0x03, 0xb4, 0x5a, 0xb5, 0xca, 0x67, 0xa0, 0xdc, + 0x35, 0x97, 0xb0, 0xd7, 0x5c, 0xc2, 0x5d, 0x73, 0x09, 0x7f, 0xcd, 0x25, 0xcc, 0x35, 0x97, 0xf0, 0xd7, 0x5c, 0x1e, + 0x84, 0x9f, 0x82, 0x38, 0x8e, 0x31, 0x87, 0xb8, 0x8a, 0xda, 0x46, 0xc6, 0x83, 0x0b, 0xcf, 0x7d, 0x96, 0xa8, 0x72, + 0xf9, 0xc3, 0x18, 0x72, 0x5b, 0xb6, 0x12, 0xc6, 0x6d, 0x8a, 0x29, 0x88, 0x9c, 0x7e, 0x70, 0x50, 0xba, 0x3b, 0x83, + 0x8f, 0x7a, 0xca, 0xf1, 0xd2, 0x3a, 0xd1, 0xfe, 0x01, 0x3a, 0x79, 0xf3, 0xeb, 0x63, 0x2a, 0xd7, 0x44, 0x38, 0x93, + 0xfb, 0xfd, 0xb6, 0xa7, 0x14, 0x9f, 0x32, 0x13, 0x9e, 0x9c, 0x27, 0xda, 0x88, 0x20, 0x08, 0x51, 0xa2, 0x70, 0x46, + 0xa4, 0xdd, 0xef, 0xde, 0x15, 0xde, 0xa8, 0xa2, 0xbc, 0x59, 0xc9, 0xe3, 0x1c, 0x9c, 0xd8, 0x8d, 0x15, 0x06, 0xea, + 0x82, 0x0b, 0x41, 0x66, 0x12, 0xfe, 0x68, 0xe6, 0x96, 0x9c, 0x65, 0x65, 0xd2, 0xc7, 0x66, 0x6e, 0x08, 0x58, 0x41, + 0xf6, 0x3d, 0xcc, 0x96, 0xb7, 0x29, 0xc5, 0x77, 0x69, 0x86, 0x87, 0xf2, 0x36, 0x2d, 0x42, 0x5b, 0x10, 0x7f, 0xf1, + 0x37, 0x8e, 0x23, 0x41, 0xc1, 0xdf, 0x27, 0xe2, 0x62, 0x8f, 0x6f, 0x78, 0x01, 0x2e, 0x33, 0x63, 0x51, 0x9d, 0x32, + 0xfc, 0x0d, 0x4b, 0x78, 0x08, 0x4e, 0xa6, 0xb1, 0x22, 0xf7, 0x38, 0xb0, 0x13, 0x92, 0x80, 0xc3, 0xd5, 0xed, 0x15, + 0xff, 0x0a, 0x17, 0x5f, 0xa5, 0xb3, 0x65, 0x73, 0x28, 0x6f, 0x23, 0x5c, 0x90, 0x37, 0xf0, 0xfa, 0xd6, 0xff, 0xcb, + 0xde, 0xdb, 0x36, 0xb7, 0x6d, 0x64, 0xeb, 0xa2, 0x7f, 0x45, 0x62, 0xd9, 0x0c, 0x60, 0x36, 0x29, 0xca, 0xe7, 0xcc, + 0x54, 0x5d, 0x50, 0x6d, 0x96, 0x63, 0xc7, 0x13, 0x67, 0x22, 0xdb, 0x63, 0x79, 0x32, 0xc9, 0xb0, 0x78, 0x19, 0x08, + 0x68, 0x0a, 0x70, 0x40, 0x80, 0x01, 0x40, 0x89, 0x34, 0x89, 0xff, 0x7e, 0x6a, 0xad, 0xd5, 0xaf, 0x20, 0x28, 0x7b, + 0xf6, 0x3e, 0xfb, 0xd3, 0xbd, 0x5f, 0x6c, 0xb1, 0xd1, 0x68, 0xf4, 0x7b, 0xaf, 0x5e, 0x2f, 0xcf, 0xd3, 0x93, 0xb1, + 0xba, 0x3d, 0x70, 0xd6, 0xa5, 0x14, 0x1d, 0x6f, 0x8a, 0xc3, 0xdb, 0xf3, 0xd9, 0x7e, 0x1b, 0x44, 0x6c, 0x17, 0x64, + 0x58, 0xeb, 0xa4, 0xe1, 0x3f, 0xd1, 0xd6, 0xc1, 0x62, 0x84, 0xfd, 0x5f, 0xd6, 0x03, 0x2f, 0x21, 0x35, 0x14, 0xb8, + 0x18, 0x6c, 0x38, 0x5a, 0xdb, 0x65, 0x1a, 0xb8, 0xa9, 0x41, 0xaf, 0xef, 0x29, 0x44, 0x79, 0xc9, 0x68, 0x6e, 0x04, + 0xeb, 0xc6, 0x90, 0x8b, 0xc3, 0x71, 0xb3, 0x1c, 0xf2, 0x92, 0xa6, 0xd3, 0x20, 0x94, 0xee, 0x2c, 0x6b, 0x48, 0xa2, + 0xec, 0x83, 0x50, 0xbb, 0xb6, 0xec, 0xb7, 0x81, 0xed, 0xcb, 0x1f, 0x0d, 0x63, 0xff, 0x62, 0xf9, 0x4c, 0x48, 0x17, + 0xf1, 0x1c, 0x04, 0x51, 0xfb, 0x79, 0x36, 0xdc, 0xf8, 0x17, 0xeb, 0x67, 0x42, 0xf9, 0x8d, 0xe7, 0xb6, 0x1c, 0x52, + 0x67, 0x2d, 0x7c, 0x61, 0x3c, 0x3c, 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, 0x01, 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, 0xee, 0x52, 0xa6, 0xcb, 0x80, 0x4b, 0xfa, 0x5d, 0xaa, 0x94, 0xc2, 0x7f, 0x22, 0x00, 0x9d, 0x83, 0x7b, 0x7c, + 0x39, 0x06, 0xd2, 0x0c, 0x0b, 0xbf, 0x35, 0x3b, 0xbe, 0x26, 0xe1, 0x36, 0x09, 0x2e, 0x06, 0x38, 0x47, 0x57, 0x61, + 0x79, 0x97, 0x42, 0x04, 0x55, 0x09, 0xf5, 0xad, 0x4c, 0x83, 0xd2, 0x56, 0x83, 0xb0, 0x26, 0xa1, 0xce, 0x24, 0x1b, + 0x95, 0xb6, 0x1b, 0x85, 0xd9, 0x22, 0xae, 0x67, 0x84, 0x35, 0x67, 0x33, 0xd5, 0xc0, 0xa4, 0xe1, 0xb8, 0x69, 0xb4, + 0x16, 0x15, 0x6a, 0x0a, 0xf3, 0x1a, 0x57, 0x95, 0xaa, 0xee, 0xe6, 0xd4, 0x52, 0x5a, 0xb6, 0x57, 0xdd, 0x24, 0x1b, + 0x72, 0x19, 0xca, 0x30, 0xd8, 0xc8, 0x11, 0x4c, 0x20, 0x49, 0xce, 0xfc, 0x8d, 0xfc, 0x43, 0x6d, 0xba, 0x16, 0x30, + 0xc7, 0x98, 0x65, 0xc3, 0x82, 0x5e, 0x81, 0x7b, 0xa0, 0x95, 0x9e, 0x4f, 0xb3, 0x8b, 0x3c, 0x48, 0x86, 0x85, 0x5e, + 0x36, 0x19, 0xff, 0x53, 0x18, 0x69, 0x32, 0x63, 0x25, 0x8b, 0x6c, 0x57, 0xa7, 0xc4, 0x79, 0x9c, 0xc0, 0xf6, 0x68, + 0x7a, 0xcb, 0xf7, 0x19, 0x44, 0x05, 0x81, 0x82, 0x19, 0xf3, 0x65, 0x17, 0xcf, 0x7d, 0x9f, 0x59, 0xa6, 0xee, 0xc3, + 0xc1, 0x98, 0xb1, 0xfd, 0x7e, 0x3f, 0xef, 0xf7, 0xd5, 0x7c, 0xeb, 0xf7, 0x93, 0x17, 0xe6, 0x6f, 0x0f, 0x18, 0x14, + 0xe4, 0x44, 0x34, 0x15, 0x22, 0xf8, 0x87, 0xe4, 0x19, 0x92, 0xd1, 0x1d, 0xf7, 0xb9, 0xe5, 0x6c, 0x59, 0x1d, 0x81, + 0x60, 0x1e, 0x0e, 0x97, 0x0a, 0xec, 0x5a, 0xa2, 0x48, 0xc8, 0xf2, 0x9f, 0x81, 0xf1, 0xcc, 0x7d, 0x80, 0x25, 0x03, + 0x10, 0xb6, 0xca, 0xd3, 0xf5, 0x9e, 0xaf, 0x82, 0x77, 0x3a, 0xde, 0x35, 0x56, 0x64, 0x20, 0x6e, 0x81, 0x8d, 0x58, + 0x6b, 0x0f, 0xc8, 0x99, 0x02, 0x1c, 0x2f, 0x0e, 0x87, 0x73, 0xf9, 0x4b, 0x37, 0x5b, 0x27, 0x50, 0x29, 0x70, 0x7b, + 0x74, 0x72, 0xf0, 0xdf, 0x81, 0x66, 0x50, 0x0e, 0xf3, 0x7a, 0xfb, 0x3b, 0x73, 0xf2, 0xd3, 0x53, 0xfc, 0x13, 0x1e, + 0xa2, 0xd3, 0x6f, 0xf7, 0xe6, 0x0f, 0x8a, 0xca, 0xc3, 0x41, 0x2d, 0xfe, 0x73, 0xce, 0x2b, 0xf8, 0x85, 0x6f, 0x02, + 0xb3, 0xc9, 0xd4, 0x3b, 0xf9, 0x26, 0xcf, 0x99, 0x7a, 0x8d, 0x57, 0x4c, 0xbe, 0xc3, 0xe1, 0x5c, 0x8c, 0xea, 0xed, + 0xc8, 0x89, 0x76, 0xca, 0x31, 0x0e, 0x06, 0xff, 0x45, 0xb4, 0x4d, 0x08, 0x30, 0xa4, 0x6e, 0x49, 0x33, 0x1b, 0x57, + 0x96, 0x78, 0x96, 0xce, 0x2f, 0x27, 0x75, 0xb9, 0xd3, 0x8a, 0xa7, 0x3d, 0xb0, 0xb8, 0xad, 0xc1, 0x0b, 0xe0, 0xde, + 0x62, 0xeb, 0x4a, 0xc1, 0xe1, 0x02, 0xe2, 0x14, 0x27, 0x20, 0x82, 0xf6, 0xfb, 0x12, 0xef, 0x15, 0xf4, 0x49, 0x3f, + 0x40, 0x30, 0xe4, 0xcf, 0x12, 0x70, 0xd7, 0xeb, 0xd5, 0x18, 0xdf, 0x4b, 0x21, 0xb8, 0x3e, 0xd3, 0x00, 0xb4, 0xe0, + 0x77, 0xf9, 0x58, 0x4e, 0xbf, 0x89, 0xc0, 0xb3, 0x65, 0x6f, 0xa2, 0xdc, 0x6d, 0x78, 0xda, 0x3f, 0x5a, 0x08, 0xc0, + 0x52, 0x3c, 0x53, 0x82, 0x05, 0x39, 0xc5, 0x5c, 0xfc, 0xbf, 0xe0, 0x23, 0xe6, 0x7b, 0xd2, 0x45, 0x6c, 0xbd, 0x7d, + 0x72, 0x61, 0x20, 0x81, 0xa6, 0x03, 0xf0, 0xe3, 0x55, 0x40, 0x57, 0xc6, 0xcf, 0xcf, 0xb2, 0x1e, 0xeb, 0xe3, 0x3f, + 0x05, 0xf7, 0xe9, 0x67, 0x0a, 0x1f, 0x1d, 0x8e, 0xab, 0x74, 0xb4, 0xa3, 0x14, 0x44, 0x47, 0xb7, 0xcf, 0xa7, 0x3c, + 0xfb, 0xa6, 0x02, 0x72, 0xcb, 0x51, 0x7b, 0x2a, 0x00, 0x8b, 0x2d, 0x1d, 0x81, 0x4f, 0xb3, 0x7c, 0x42, 0xbe, 0xd7, + 0x53, 0x71, 0x75, 0xa9, 0xd3, 0xc5, 0x8b, 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, 0x75, 0x8d, 0x82, 0x95, 0x80, 0x33, 0xed, 0x1a, 0x0c, 0x36, 0xb0, + 0x6e, 0x59, 0x06, 0x7f, 0xc3, 0x35, 0x4d, 0xe0, 0x86, 0x45, 0xd6, 0x7b, 0x83, 0xad, 0x74, 0x0d, 0x8e, 0x96, 0x89, + 0x73, 0x29, 0xc9, 0xca, 0x16, 0x19, 0x57, 0x8f, 0x42, 0xaa, 0xa6, 0xfb, 0x5b, 0x51, 0x3f, 0x08, 0x91, 0x07, 0xab, + 0x94, 0x45, 0xc5, 0x0a, 0x64, 0xf6, 0xe0, 0x1f, 0x21, 0x23, 0x47, 0x39, 0x70, 0x14, 0xfa, 0x5b, 0x13, 0xe8, 0x3c, + 0x3f, 0x85, 0x3a, 0x8f, 0x04, 0x5b, 0xa9, 0x87, 0xc2, 0xca, 0x0b, 0x88, 0x0e, 0xb6, 0x30, 0x56, 0x79, 0x12, 0x2a, + 0x36, 0x65, 0x22, 0x8f, 0x83, 0x5a, 0x02, 0xc6, 0x0a, 0x82, 0x39, 0xcb, 0xa5, 0x0b, 0x52, 0xd5, 0xe8, 0x61, 0x91, + 0xb9, 0x9f, 0x0a, 0xca, 0xff, 0x54, 0xe5, 0x84, 0xeb, 0xcb, 0x10, 0xe0, 0x68, 0x9f, 0x82, 0x28, 0x31, 0xd6, 0x2f, + 0x5a, 0xbc, 0x93, 0x99, 0xb3, 0xa9, 0xed, 0x25, 0xc8, 0xd8, 0x0e, 0xbf, 0x42, 0x68, 0xb5, 0x50, 0x64, 0xd1, 0x70, + 0xc1, 0x74, 0x7b, 0x4a, 0xab, 0xee, 0x61, 0xc3, 0xb3, 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, 0x69, + 0x34, 0x9f, 0xe5, 0x73, 0x1f, 0x15, 0x17, 0x93, 0xc1, 0x60, 0xe3, 0x67, 0xc3, 0x21, 0x4b, 0x86, 0xc3, 0x49, 0xf6, + 0x14, 0x5e, 0x7b, 0xca, 0x23, 0xb5, 0xa4, 0x92, 0xab, 0x0c, 0xf6, 0xf7, 0x01, 0x8f, 0x7c, 0xd6, 0xf9, 0x69, 0xd9, + 0x74, 0xe9, 0x7e, 0x66, 0xc7, 0x5d, 0xe8, 0x0e, 0xb0, 0xf1, 0xb6, 0x41, 0x47, 0xfe, 0xf5, 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, 0x07, 0xf7, 0x85, 0x15, 0x05, + 0xfe, 0xdf, 0xb2, 0x05, 0xbb, 0x97, 0xc7, 0xc0, 0x35, 0x3a, 0x26, 0xc1, 0x05, 0xe2, 0x9e, 0xdd, 0x82, 0x1d, 0x16, + 0xfe, 0x82, 0xeb, 0xe4, 0x98, 0xed, 0xf0, 0x51, 0xe8, 0x15, 0xec, 0xd6, 0x27, 0xa0, 0x5d, 0xb0, 0x35, 0x40, 0x36, + 0xb6, 0xc5, 0x47, 0x77, 0x87, 0xc3, 0xb5, 0xe7, 0xb3, 0x07, 0xfc, 0x71, 0x7e, 0x77, 0x38, 0xec, 0x3c, 0xa3, 0xde, + 0xbb, 0xe1, 0x09, 0x7b, 0xcf, 0x93, 0xc9, 0xcd, 0x15, 0x8f, 0x27, 0x83, 0xc1, 0x8d, 0xbf, 0xe0, 0xf5, 0xec, 0x06, + 0xb4, 0x03, 0xe7, 0x0b, 0xa9, 0x6b, 0xf6, 0x6e, 0x79, 0xe6, 0x2d, 0x70, 0x6c, 0x6e, 0xe1, 0xe8, 0xed, 0xf7, 0xbd, + 0x3b, 0x1e, 0x79, 0xb7, 0xa4, 0x62, 0x5a, 0x71, 0xc5, 0xf1, 0xb6, 0xc5, 0xfd, 0x74, 0xc5, 0x43, 0x78, 0x84, 0x55, + 0x99, 0xde, 0x04, 0xef, 0x7d, 0xb6, 0xd2, 0x2c, 0x70, 0x0f, 0x98, 0x63, 0x4d, 0x76, 0x42, 0x33, 0xf1, 0x57, 0xd8, + 0x3f, 0x37, 0xaa, 0x7f, 0x68, 0xfe, 0x97, 0xba, 0x9f, 0xc0, 0xed, 0x8b, 0x2c, 0x48, 0xec, 0x3d, 0xbf, 0x61, 0xf7, + 0xdc, 0xb0, 0xcd, 0x9e, 0x99, 0xb2, 0x4f, 0x94, 0x1a, 0x3f, 0x52, 0xea, 0xda, 0x32, 0xac, 0x64, 0xee, 0xbe, 0x8c, + 0xc0, 0xe1, 0x80, 0xfc, 0x74, 0x87, 0x38, 0x08, 0xad, 0x9b, 0xac, 0xe6, 0x8a, 0x72, 0x2e, 0xb4, 0x65, 0xe6, 0xe5, + 0xc0, 0x62, 0x96, 0x52, 0x68, 0x2c, 0x00, 0x10, 0x4c, 0x0a, 0xad, 0xbd, 0x97, 0x01, 0xe4, 0x04, 0x0d, 0x7f, 0x6c, + 0xae, 0x8a, 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, 0xa7, + 0xbc, 0x66, 0x82, 0xc8, 0x36, 0x2a, 0x7f, 0x52, 0xbc, 0x40, 0x32, 0x82, 0xe2, 0x69, 0xad, 0x32, 0x16, 0x86, 0x79, + 0xa0, 0x80, 0xbc, 0x7b, 0x77, 0xea, 0x5b, 0xfb, 0x63, 0xc7, 0x9e, 0xad, 0x55, 0xa8, 0x85, 0x9a, 0xc2, 0x25, 0x87, + 0xe8, 0x0a, 0x32, 0x50, 0xc8, 0x78, 0xf2, 0x7a, 0x70, 0x39, 0x89, 0xae, 0xb8, 0x40, 0x67, 0x7c, 0x7d, 0xd3, 0x4d, + 0x67, 0xd1, 0xd3, 0x6a, 0x3e, 0x21, 0x25, 0xd9, 0xe1, 0x90, 0x8d, 0xaa, 0xba, 0x58, 0x4f, 0x43, 0xf9, 0xd3, 0x43, + 0xf0, 0xf5, 0x82, 0x7a, 0x4d, 0x56, 0xa9, 0x7e, 0x4a, 0x95, 0xf2, 0xa2, 0xe1, 0xa5, 0xff, 0xb4, 0x92, 0xfb, 0x1e, + 0x90, 0xd6, 0xf2, 0x92, 0xcb, 0xf7, 0x23, 0xc4, 0x18, 0xf1, 0x03, 0xaf, 0xe4, 0x11, 0x0b, 0xd5, 0x14, 0xae, 0x79, + 0x84, 0x20, 0x6f, 0x99, 0x0e, 0xfe, 0xd6, 0x13, 0xa7, 0xfb, 0x13, 0xa5, 0x5d, 0x7c, 0x61, 0x51, 0xf7, 0x64, 0x6d, + 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, 0xf9, 0xb0, 0xe1, 0x11, 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, 0xfb, 0xb9, 0x80, 0x20, 0x88, 0x92, 0x78, 0x7c, 0xc0, 0xfb, 0xb2, 0x1a, 0x6a, 0x94, 0x7c, 0x2c, + 0x1b, 0xa9, 0xf4, 0x4a, 0xf4, 0x77, 0x63, 0x2e, 0x31, 0xe0, 0x75, 0xd5, 0x16, 0x14, 0xce, 0xf3, 0xc3, 0xe1, 0x3c, + 0x1f, 0x19, 0xcf, 0x32, 0x50, 0xad, 0x4c, 0xeb, 0x20, 0x36, 0xf3, 0xc5, 0xc2, 0x5f, 0xec, 0x9c, 0x44, 0x44, 0x41, + 0x60, 0x47, 0xc2, 0x83, 0x48, 0xfd, 0xaa, 0xf2, 0x74, 0xa7, 0xfa, 0x6c, 0xbf, 0xb0, 0x89, 0xf4, 0x82, 0x92, 0xc9, + 0x27, 0xc1, 0x5e, 0xf5, 0x77, 0x10, 0x36, 0x84, 0x37, 0xaf, 0x7a, 0x9d, 0x65, 0x6a, 0x56, 0x82, 0x84, 0x19, 0x73, + 0x04, 0x8f, 0xc3, 0x4e, 0x63, 0x1b, 0x1e, 0x5b, 0x70, 0x74, 0xde, 0x9a, 0xdd, 0xb1, 0x15, 0xbb, 0x55, 0x75, 0x5a, + 0xf0, 0x70, 0x3a, 0xbc, 0x0c, 0x70, 0xf5, 0xad, 0xcf, 0x39, 0xbf, 0xa3, 0x13, 0x6c, 0x3d, 0xe0, 0xd1, 0x44, 0xcc, + 0xd6, 0x4f, 0x23, 0xb5, 0x78, 0xd6, 0x43, 0xbe, 0xa0, 0xf5, 0x27, 0x66, 0x77, 0x26, 0xf9, 0x6e, 0xc0, 0x17, 0x93, + 0xf5, 0xd3, 0x08, 0x5e, 0x7d, 0x0a, 0x56, 0x8c, 0xcc, 0x99, 0x65, 0xeb, 0xa7, 0x11, 0x8e, 0xd9, 0xdd, 0xd3, 0x88, + 0x46, 0x6d, 0x25, 0xf7, 0xa5, 0xdb, 0x06, 0x84, 0x95, 0x5b, 0x16, 0xc3, 0x6b, 0x20, 0x9e, 0x69, 0x23, 0xe9, 0x5a, + 0x1a, 0x7a, 0x63, 0x1e, 0x4e, 0xe3, 0x60, 0x4d, 0xad, 0x90, 0x67, 0x86, 0x98, 0xc5, 0x4f, 0xa3, 0x39, 0x5b, 0x61, + 0x45, 0x36, 0x3c, 0x1e, 0x5c, 0x4e, 0x36, 0x57, 0x7c, 0x0d, 0xe4, 0x67, 0x93, 0x8d, 0xd9, 0xa2, 0x6e, 0xb9, 0x98, + 0x6d, 0x9e, 0x46, 0xf3, 0xc9, 0x0a, 0x7a, 0xd6, 0x1e, 0x30, 0xef, 0x0d, 0x88, 0x50, 0x12, 0x52, 0x53, 0x6e, 0x7a, + 0x3d, 0xb6, 0x1e, 0x07, 0x77, 0x6c, 0x7d, 0x19, 0xdc, 0xb2, 0xf5, 0x18, 0x88, 0x38, 0xa8, 0xdf, 0xbd, 0x0d, 0x2c, + 0xbe, 0x88, 0xad, 0x2f, 0x4d, 0xda, 0xe6, 0x69, 0xc4, 0xdc, 0xc1, 0x69, 0xe0, 0x82, 0xb5, 0xc9, 0xbc, 0x15, 0x83, + 0x4b, 0xc8, 0xd2, 0x8b, 0xd9, 0x66, 0x78, 0xc9, 0xd6, 0x23, 0x9c, 0xea, 0x89, 0xcf, 0xee, 0xf8, 0x2d, 0x4b, 0xf8, + 0xaa, 0x89, 0xaf, 0x36, 0xa0, 0x11, 0x3d, 0xca, 0xa0, 0xaf, 0xa0, 0x66, 0xe6, 0xbc, 0xb2, 0x30, 0x2a, 0xf7, 0x2d, + 0x38, 0xa0, 0x20, 0x6d, 0x03, 0x04, 0x49, 0x3c, 0xbb, 0x57, 0xe1, 0xfa, 0x46, 0x0a, 0x03, 0x6e, 0x02, 0x33, 0x60, + 0x60, 0xfa, 0x19, 0xfc, 0xb0, 0xd2, 0x25, 0x42, 0x9c, 0xfd, 0x94, 0x92, 0x64, 0x9e, 0x9f, 0x8a, 0x34, 0x77, 0x0b, + 0xd7, 0x29, 0xcc, 0x8a, 0x02, 0xd5, 0x4f, 0x49, 0x69, 0x60, 0xa1, 0x12, 0x99, 0x4a, 0xc1, 0x2f, 0x9b, 0xf3, 0x28, + 0x3b, 0x46, 0xe7, 0x3a, 0xbf, 0x9c, 0x38, 0xa7, 0x93, 0xbe, 0xff, 0xc0, 0x31, 0x6c, 0x21, 0x03, 0x17, 0xfe, 0xd4, + 0x13, 0xc6, 0xa9, 0x15, 0x88, 0xa9, 0xe4, 0xd9, 0x53, 0xf8, 0x4c, 0x68, 0x75, 0x74, 0xe1, 0xfb, 0x41, 0xa1, 0x4d, + 0xd2, 0x2d, 0x48, 0x52, 0xf0, 0x14, 0x3d, 0xe7, 0xbc, 0x0d, 0x54, 0x8a, 0x11, 0x2d, 0x88, 0xb4, 0xb5, 0xcc, 0x1c, + 0xa4, 0x2d, 0xcd, 0x77, 0x4d, 0xfc, 0x1c, 0x16, 0x70, 0x11, 0x2d, 0x6c, 0x0d, 0x8f, 0xaa, 0x58, 0xb9, 0x37, 0x79, + 0x8e, 0x70, 0x46, 0x97, 0x32, 0x01, 0x70, 0xbd, 0x5f, 0x87, 0xb5, 0xc2, 0x2b, 0x6a, 0x16, 0x79, 0x51, 0xd3, 0x27, + 0x5b, 0xe0, 0x3e, 0x16, 0x25, 0x0a, 0x9c, 0xb5, 0x60, 0xc0, 0x56, 0x58, 0xb2, 0x93, 0xc2, 0xa6, 0x68, 0x09, 0xbd, + 0x3d, 0x7e, 0x3a, 0xa8, 0x99, 0x0c, 0xa0, 0x09, 0xa0, 0xf1, 0xf8, 0x17, 0x80, 0x9a, 0xde, 0xd4, 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, 0x83, 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, 0x8b, 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, 0xb5, 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, 0x4e, 0x6e, 0x61, 0xcb, 0x4c, + 0x56, 0xf3, 0x7d, 0xc5, 0x1d, 0x94, 0x6f, 0xb6, 0xce, 0xf8, 0x5e, 0x22, 0x7b, 0xb7, 0x81, 0x12, 0x5e, 0x8c, 0xfe, + 0x82, 0xf4, 0xdb, 0x0c, 0xe3, 0x94, 0xdb, 0x4a, 0x5a, 0x80, 0xd3, 0x3f, 0x1c, 0xde, 0x57, 0x18, 0x34, 0x38, 0xc2, + 0x38, 0xb2, 0x7e, 0xff, 0xb6, 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, 0x9f, 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, 0x3a, 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, 0xeb, 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, 0x4f, 0x9f, + 0x03, 0x69, 0x59, 0xbf, 0x1f, 0xbd, 0xb8, 0x9c, 0x3e, 0x1f, 0x46, 0x01, 0x38, 0x76, 0xd9, 0xcb, 0xcb, 0x98, 0xaf, + 0x2e, 0x99, 0x65, 0x0a, 0x8b, 0x7c, 0x33, 0xa0, 0xba, 0x64, 0xb5, 0x74, 0xbd, 0x02, 0x2c, 0x5d, 0x7e, 0xf3, 0x10, + 0xa6, 0x06, 0x34, 0xb2, 0xe6, 0xee, 0x34, 0xd7, 0x02, 0xa5, 0x9e, 0xf7, 0x33, 0x43, 0xbe, 0x2e, 0x83, 0xae, 0x20, + 0xdd, 0xf3, 0x88, 0xf4, 0x72, 0x2f, 0x9d, 0xee, 0xf7, 0xa5, 0x00, 0x4b, 0x7d, 0x29, 0x3e, 0x83, 0xc2, 0xa2, 0xf1, + 0x8d, 0x00, 0x6d, 0x0d, 0xd5, 0xb4, 0x57, 0x8a, 0xaa, 0x17, 0xf4, 0x4a, 0xf1, 0xb9, 0xa7, 0x87, 0xca, 0x7c, 0x59, + 0x3a, 0xfa, 0x9f, 0x50, 0x73, 0xc1, 0x09, 0x31, 0x13, 0x73, 0x00, 0x95, 0xa0, 0x8d, 0x6f, 0x75, 0xb4, 0xf1, 0xa9, + 0x5e, 0xc5, 0x4d, 0x9f, 0xd7, 0xd6, 0x32, 0x27, 0x84, 0x4d, 0xf7, 0x12, 0xa0, 0x22, 0xaf, 0x84, 0x47, 0xb0, 0xfc, + 0xf2, 0x87, 0x3c, 0x5d, 0x21, 0x5a, 0xc7, 0x3d, 0xcb, 0x5c, 0x1a, 0xfb, 0x37, 0x06, 0xd3, 0xd7, 0xb7, 0xdb, 0x22, + 0x3f, 0x35, 0x31, 0x61, 0x3d, 0x56, 0xf4, 0xcd, 0xbb, 0x70, 0x25, 0x50, 0xe0, 0x50, 0x22, 0xb1, 0x4d, 0x15, 0x8a, + 0x78, 0x90, 0xf4, 0xe9, 0xa2, 0xf5, 0x69, 0x80, 0xa9, 0xb5, 0x1c, 0x98, 0x43, 0xb8, 0x8a, 0x0b, 0x1f, 0x3d, 0x7d, + 0x8b, 0x59, 0x38, 0x9f, 0x78, 0x1f, 0xbd, 0x62, 0x64, 0x3e, 0xee, 0xa3, 0x52, 0x49, 0xff, 0x3c, 0x1c, 0x66, 0xd5, + 0xdc, 0x77, 0xe8, 0x23, 0x3d, 0x54, 0xb9, 0xa0, 0xec, 0x8d, 0x31, 0x89, 0x40, 0x69, 0x8c, 0xf7, 0x71, 0x70, 0x9c, + 0xf7, 0x69, 0x00, 0xa9, 0x7d, 0xe2, 0x3d, 0x29, 0x39, 0x3c, 0xe7, 0x98, 0x13, 0x4a, 0x2b, 0xc2, 0x2a, 0xbe, 0xc8, + 0x50, 0xae, 0x3b, 0xa5, 0x60, 0x92, 0x43, 0x82, 0xe1, 0xaf, 0x9a, 0x37, 0xb1, 0x02, 0x61, 0xd7, 0xcc, 0xab, 0xd1, + 0x93, 0x2a, 0x09, 0x4b, 0x01, 0x47, 0x65, 0xe6, 0x19, 0xf6, 0x86, 0x27, 0x86, 0x91, 0x83, 0xe5, 0xfe, 0xa8, 0x4e, + 0x44, 0xee, 0xd1, 0x05, 0x46, 0x65, 0xe1, 0x79, 0x43, 0x57, 0x1a, 0x54, 0x92, 0x1d, 0x7f, 0xc5, 0x35, 0xa0, 0xb6, + 0xc6, 0x88, 0xa1, 0x80, 0x51, 0xf0, 0xda, 0xfe, 0x10, 0xb2, 0x28, 0x5b, 0xbf, 0xc1, 0x31, 0x9f, 0x95, 0xdc, 0xf5, + 0x0e, 0x67, 0xa1, 0x25, 0xe4, 0xc9, 0x1d, 0x83, 0x34, 0x8d, 0xa5, 0x11, 0x70, 0x22, 0x92, 0x6d, 0x2c, 0x85, 0x23, + 0x80, 0x80, 0x40, 0x37, 0x65, 0x86, 0x31, 0x1d, 0x8c, 0x3c, 0x4f, 0x7a, 0xc6, 0x7b, 0x15, 0x9e, 0x42, 0x9a, 0x6c, + 0x5f, 0xcf, 0xdf, 0x1b, 0x41, 0x56, 0x6e, 0x39, 0xc7, 0xc3, 0xe2, 0x1b, 0x67, 0x5f, 0xe5, 0xe4, 0x29, 0x66, 0x19, + 0xe9, 0x9d, 0x62, 0x5e, 0xc0, 0x9f, 0xca, 0x52, 0x9f, 0xa3, 0xf4, 0x96, 0xf9, 0x64, 0x15, 0x49, 0x97, 0xde, 0xa6, + 0xdf, 0x8f, 0x47, 0xea, 0x50, 0xf3, 0xf7, 0xf1, 0x48, 0x9e, 0x61, 0x1b, 0x96, 0xb0, 0xd0, 0x2a, 0x18, 0x03, 0x48, + 0x62, 0x23, 0xa2, 0xc1, 0x68, 0x6f, 0x0e, 0x87, 0xf3, 0x8d, 0x39, 0x4b, 0xf6, 0xe0, 0xfa, 0xca, 0x13, 0xf3, 0x0e, + 0x7c, 0x99, 0xc7, 0x04, 0x11, 0x9b, 0x79, 0x1b, 0x56, 0x83, 0x07, 0x3b, 0xb8, 0x3e, 0x62, 0x8b, 0x62, 0xad, 0x63, + 0xa9, 0xac, 0x83, 0xd3, 0x3a, 0x36, 0xcd, 0x48, 0x29, 0xb2, 0xcf, 0xb1, 0xbf, 0x77, 0x83, 0xab, 0x6b, 0x63, 0x50, + 0x6b, 0xdc, 0x61, 0xee, 0x9c, 0x0a, 0xa8, 0xc7, 0x74, 0x05, 0xd5, 0xb3, 0x9c, 0x7c, 0xf9, 0xad, 0x9d, 0x03, 0x82, + 0x46, 0x20, 0x70, 0xd1, 0x40, 0xab, 0x76, 0x29, 0xe7, 0x5d, 0x40, 0x88, 0x6f, 0x52, 0xd0, 0xa7, 0x33, 0xd8, 0xc4, + 0xe6, 0x13, 0x88, 0x45, 0xd3, 0x7d, 0xae, 0x35, 0xf3, 0xc5, 0x88, 0x76, 0x66, 0xdd, 0x2d, 0x72, 0xab, 0x85, 0x48, + 0x46, 0xcf, 0x36, 0x13, 0x2e, 0x3a, 0x94, 0x33, 0x12, 0x30, 0x41, 0x6b, 0x2b, 0x25, 0x9f, 0xeb, 0x5e, 0x27, 0x68, + 0x0f, 0x24, 0xad, 0xfb, 0x37, 0x8b, 0xce, 0x28, 0x39, 0xb9, 0xde, 0xe4, 0x0c, 0x52, 0xb0, 0x60, 0x7b, 0x99, 0x13, + 0x6e, 0x80, 0x4f, 0x6c, 0x96, 0x9c, 0xa6, 0x41, 0x1e, 0x0b, 0xe3, 0x91, 0xd7, 0xe6, 0x97, 0x05, 0x74, 0x28, 0x59, + 0x34, 0x42, 0x3c, 0xc0, 0xce, 0x21, 0xb9, 0x2a, 0x50, 0x37, 0x0d, 0x74, 0xe5, 0xca, 0x99, 0x62, 0x0a, 0x5c, 0x08, + 0x05, 0x51, 0x3b, 0x3a, 0x89, 0xca, 0x79, 0x9f, 0x54, 0x97, 0xf9, 0xb4, 0x90, 0xa6, 0x81, 0x7c, 0x5a, 0x39, 0xe6, + 0x81, 0x9d, 0x6d, 0x5c, 0x13, 0x18, 0xe8, 0xd4, 0xbe, 0x16, 0xe5, 0x1c, 0xab, 0x88, 0xde, 0xe7, 0x1f, 0x2a, 0x7b, + 0xfa, 0x20, 0xc2, 0x46, 0x05, 0x1a, 0x4b, 0x89, 0xb1, 0x91, 0xe3, 0xdf, 0x12, 0x65, 0x43, 0x86, 0x80, 0x10, 0xd2, + 0x46, 0x4e, 0x3f, 0xac, 0x2f, 0x6f, 0x33, 0xed, 0xff, 0x49, 0xe2, 0xb7, 0xc1, 0x5e, 0x4e, 0xfd, 0xa9, 0x47, 0x3c, + 0x5e, 0x6b, 0xf4, 0x98, 0x92, 0x6e, 0x83, 0x3c, 0x55, 0x9e, 0x82, 0x64, 0xc2, 0x58, 0x42, 0xb0, 0x28, 0x17, 0x3c, + 0xe7, 0x15, 0x97, 0x70, 0x1f, 0xb5, 0xac, 0x88, 0x50, 0x95, 0xc8, 0xe9, 0xf3, 0x15, 0xf0, 0x4c, 0x40, 0xa0, 0x63, + 0x8c, 0x34, 0xaa, 0xe0, 0x4b, 0x60, 0xac, 0x03, 0x65, 0xa7, 0x19, 0x09, 0x2e, 0xbb, 0x37, 0x48, 0x94, 0xfa, 0x9a, + 0x94, 0xa4, 0xd7, 0xa2, 0xc6, 0x2b, 0xb1, 0x8a, 0x48, 0x20, 0x43, 0x0d, 0x11, 0xab, 0xea, 0xa9, 0x7b, 0x55, 0x4c, + 0x06, 0x83, 0xca, 0x97, 0xd3, 0x13, 0x6f, 0x68, 0xa8, 0xbc, 0xeb, 0x8a, 0x76, 0x7a, 0xa2, 0x95, 0xf2, 0x16, 0xd2, + 0x12, 0x34, 0x0d, 0x23, 0xcd, 0xa1, 0xd4, 0x95, 0x74, 0x37, 0x06, 0xf1, 0x25, 0x13, 0x3d, 0xdb, 0xa9, 0x1d, 0xa5, + 0x2d, 0x69, 0x0f, 0x21, 0x3d, 0x77, 0xc9, 0xc7, 0x2c, 0xe4, 0xea, 0x4e, 0x39, 0x29, 0xaf, 0x42, 0x74, 0x72, 0xdf, + 0x63, 0x48, 0x04, 0xfa, 0x9c, 0x63, 0x58, 0x17, 0x0d, 0x75, 0x0e, 0x2b, 0xc4, 0x6c, 0xa1, 0x84, 0xf9, 0x92, 0xf1, + 0x54, 0x32, 0x68, 0x00, 0x64, 0xc0, 0x67, 0x2f, 0x03, 0xcb, 0x5f, 0x41, 0xfc, 0x68, 0xe3, 0xc3, 0xe1, 0xcf, 0x9a, + 0x42, 0x6c, 0xff, 0x84, 0xcd, 0x10, 0x1e, 0xd5, 0x03, 0x9e, 0xf9, 0x26, 0x4e, 0xd0, 0x0a, 0x48, 0xca, 0xec, 0x68, + 0x22, 0x7b, 0xd5, 0x43, 0x38, 0x95, 0x15, 0xa8, 0xa3, 0xac, 0xb3, 0x12, 0x7e, 0x84, 0xa9, 0x6e, 0x25, 0xd6, 0x02, + 0x6d, 0xae, 0x56, 0xac, 0x05, 0x70, 0xe0, 0xe7, 0x10, 0x3c, 0x91, 0xcf, 0xc1, 0xc5, 0xa0, 0x00, 0x9f, 0x03, 0xe0, + 0x45, 0xee, 0xc2, 0x83, 0x79, 0x64, 0x59, 0x8d, 0x30, 0x1c, 0x55, 0xc4, 0xfa, 0x35, 0xdb, 0x91, 0x0f, 0xdc, 0x8e, + 0xf1, 0xb9, 0xf6, 0x58, 0xb2, 0x1c, 0x8c, 0x32, 0xf7, 0x6a, 0x89, 0x9e, 0x37, 0x69, 0xdc, 0x8c, 0x9e, 0xec, 0x6b, + 0xf9, 0xbf, 0xa0, 0x97, 0x41, 0x7f, 0x0b, 0xb7, 0xbc, 0xe6, 0x77, 0x0b, 0x22, 0xcd, 0xf4, 0x0a, 0x22, 0x65, 0xd4, + 0x88, 0x8c, 0x21, 0x6c, 0x52, 0xdd, 0xdc, 0x26, 0xd5, 0x85, 0x80, 0xa7, 0x23, 0x52, 0x5d, 0x0b, 0x69, 0x23, 0x9f, + 0xd6, 0x81, 0x8c, 0x45, 0x7a, 0xf7, 0xc3, 0xdf, 0x5e, 0x7e, 0x7a, 0xfb, 0xcb, 0x0f, 0x8b, 0xb7, 0xef, 0xde, 0xbc, + 0x7d, 0xf7, 0xf6, 0xd3, 0x6f, 0x04, 0xe1, 0x31, 0x15, 0x2a, 0xc3, 0x87, 0xf7, 0x37, 0x6f, 0x9d, 0x0c, 0xb6, 0x37, + 0x43, 0xd6, 0xbe, 0x91, 0x83, 0x21, 0x10, 0xd9, 0x20, 0x64, 0x90, 0x9d, 0xda, 0xf6, 0x67, 0x62, 0x8e, 0xb1, 0x77, + 0x02, 0x93, 0x2d, 0xe0, 0x1c, 0xcb, 0xbc, 0x64, 0x44, 0xae, 0x0a, 0xad, 0x1f, 0xd0, 0x82, 0x6b, 0x70, 0x91, 0x49, + 0xf3, 0xbb, 0x5f, 0x08, 0x62, 0x9f, 0x56, 0x52, 0xee, 0xab, 0x6d, 0xcd, 0xf3, 0xed, 0xfd, 0x5e, 0xc2, 0xf9, 0xcf, + 0xa5, 0x11, 0xb5, 0x00, 0x07, 0xe0, 0x73, 0xf8, 0xe3, 0x4a, 0x5b, 0xd2, 0x64, 0x16, 0xed, 0x67, 0x0c, 0x41, 0x97, + 0x06, 0x1f, 0xc4, 0x1e, 0x79, 0xa9, 0x4f, 0x16, 0x12, 0xb8, 0x23, 0x86, 0x4f, 0x2b, 0x82, 0x5e, 0x31, 0xa2, 0xb8, + 0xe4, 0x0a, 0x95, 0x52, 0xf2, 0x6f, 0x94, 0x5d, 0x54, 0xc8, 0x59, 0xc1, 0xee, 0x15, 0x39, 0x32, 0x7e, 0x10, 0x4c, + 0x7c, 0x39, 0xb8, 0xff, 0x12, 0xef, 0x70, 0xa6, 0x38, 0x92, 0x13, 0xfe, 0x90, 0x61, 0x60, 0x7f, 0x0e, 0x3e, 0xaf, + 0x0e, 0xf3, 0xf2, 0x46, 0x9f, 0x72, 0x4b, 0x3e, 0x9e, 0x2c, 0xaf, 0xc0, 0x60, 0xbf, 0x54, 0xcd, 0x5d, 0xf3, 0x7a, + 0xb6, 0x9c, 0xb3, 0xfd, 0x2c, 0x9a, 0x07, 0x77, 0x6c, 0x96, 0xcd, 0x83, 0x55, 0xc3, 0xd7, 0xec, 0x96, 0xaf, 0xad, + 0xaa, 0xad, 0xed, 0xaa, 0x4d, 0x36, 0xfc, 0x16, 0x24, 0x84, 0x9b, 0xcc, 0x03, 0xde, 0xe3, 0x3b, 0x9f, 0x6d, 0x40, + 0xa2, 0x5d, 0xb1, 0x0d, 0x5c, 0xc4, 0xd6, 0xfc, 0x87, 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, 0x7d, 0x5a, 0x6d, 0xc2, + 0x0c, 0x3d, 0xcb, 0xe1, 0xa3, 0xad, 0x14, 0xfc, 0xf4, 0x02, 0xbf, 0x64, 0x47, 0x6d, 0xa5, 0x6d, 0xbb, 0x2a, 0xb1, + 0x15, 0xb4, 0x28, 0xb2, 0x5a, 0xe1, 0x81, 0x39, 0x7f, 0x01, 0x0b, 0x18, 0x7b, 0x8e, 0x73, 0x5e, 0xfb, 0x23, 0x64, + 0xbc, 0x77, 0x00, 0xd0, 0x32, 0xc7, 0x01, 0x1e, 0xb1, 0x62, 0x14, 0x0d, 0xde, 0xf9, 0xa5, 0xb2, 0x5a, 0x69, 0x4e, + 0x42, 0xdb, 0x88, 0x55, 0xcb, 0x91, 0xaa, 0x19, 0x91, 0x3e, 0x48, 0xcf, 0xfb, 0x1e, 0x51, 0x0d, 0xf6, 0x64, 0x5e, + 0x07, 0xf6, 0xe9, 0x55, 0x6b, 0x55, 0x77, 0x7e, 0x4f, 0x95, 0x2e, 0x39, 0xb2, 0xe5, 0xa7, 0xcb, 0xf0, 0x41, 0xfd, + 0x29, 0xb9, 0x3e, 0x14, 0x38, 0xc2, 0x63, 0x15, 0x70, 0xbe, 0x5e, 0x89, 0x76, 0x27, 0xc2, 0xae, 0x5c, 0x02, 0x42, + 0x7c, 0x49, 0xd3, 0x1c, 0x8f, 0x23, 0x9a, 0x88, 0xb0, 0x89, 0xd1, 0x5f, 0xd8, 0x7d, 0x28, 0xb1, 0x9c, 0xe7, 0x1a, + 0x94, 0x5c, 0x32, 0x78, 0x4f, 0xda, 0x6b, 0xd0, 0x2c, 0xaf, 0x4a, 0x4d, 0x26, 0x72, 0x50, 0x3e, 0x1c, 0x0a, 0xd8, + 0x4b, 0x8d, 0x9f, 0x26, 0xfc, 0x84, 0xe5, 0xad, 0xbd, 0x35, 0xa5, 0xa8, 0xa4, 0x01, 0x2a, 0xf0, 0x31, 0x83, 0xff, + 0xdd, 0x19, 0x62, 0xc1, 0x14, 0x1d, 0x3f, 0x9c, 0x89, 0xb9, 0xf5, 0xdc, 0x2a, 0xeb, 0x28, 0x5b, 0xa3, 0x9c, 0x80, + 0x7f, 0x4b, 0x75, 0x9c, 0x24, 0xc2, 0xa9, 0xf7, 0x88, 0x8b, 0xba, 0x97, 0x43, 0xd4, 0x0d, 0x7b, 0x5b, 0xe9, 0x60, + 0xcb, 0x69, 0x1a, 0x1c, 0x89, 0x5f, 0xa9, 0xcf, 0xde, 0x67, 0x16, 0x8f, 0x3a, 0xb2, 0x11, 0x25, 0x69, 0x1c, 0x8b, + 0x1c, 0xb6, 0xf7, 0x85, 0xdc, 0xff, 0xfb, 0x7d, 0x08, 0x27, 0xad, 0x82, 0xa4, 0xf4, 0x04, 0x22, 0xc2, 0xd1, 0xe1, + 0x47, 0x84, 0x27, 0x52, 0x55, 0xf8, 0xa4, 0x3e, 0x71, 0x63, 0x76, 0x2f, 0xcc, 0x51, 0xbd, 0x05, 0x18, 0xc6, 0x7a, + 0x6b, 0x11, 0x92, 0x68, 0xa5, 0x19, 0x6d, 0x3d, 0x20, 0x46, 0xbc, 0x5f, 0x5b, 0x64, 0x30, 0xd6, 0x96, 0x44, 0x02, + 0xf8, 0x1d, 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, 0xeb, 0xa3, 0x74, 0x92, 0x58, 0xdf, + 0x77, 0x95, 0x0a, 0x36, 0x9b, 0x1b, 0xd4, 0x97, 0x1d, 0x25, 0xbf, 0x02, 0x27, 0x1d, 0x27, 0x59, 0xe4, 0x20, 0x6a, + 0x51, 0x39, 0x37, 0x49, 0x58, 0xda, 0xd5, 0xa9, 0x36, 0xeb, 0x75, 0x51, 0xd6, 0xd5, 0x6b, 0x11, 0x29, 0x7a, 0x1f, + 0xf5, 0xe8, 0x89, 0x84, 0x54, 0x68, 0x55, 0x6a, 0x97, 0x47, 0xe0, 0xb6, 0xa9, 0x15, 0xdb, 0x72, 0x09, 0x4b, 0xd4, + 0xf8, 0x4f, 0xd0, 0x47, 0xb9, 0x78, 0x90, 0x01, 0x1a, 0x1d, 0x4f, 0xcd, 0x5b, 0x8f, 0xbc, 0x72, 0x94, 0x5f, 0x5a, + 0x6d, 0xd2, 0x2f, 0x80, 0xcc, 0x68, 0xff, 0x68, 0x29, 0x81, 0xcc, 0xc0, 0x4c, 0x5a, 0x1a, 0x12, 0x39, 0x8a, 0x59, + 0x9a, 0xff, 0x81, 0x2b, 0xb6, 0x42, 0xa4, 0x61, 0x35, 0xf7, 0xf8, 0xcb, 0xca, 0xab, 0xe5, 0x5a, 0x66, 0x9a, 0x9b, + 0x25, 0x8e, 0x15, 0x8b, 0x8b, 0x7a, 0x5d, 0x89, 0x2c, 0x10, 0xe2, 0x08, 0xd3, 0x58, 0x4f, 0xbd, 0x51, 0x5a, 0x7d, + 0x40, 0x42, 0x99, 0x1f, 0xb0, 0xb7, 0x63, 0xaf, 0x07, 0x59, 0x88, 0x63, 0xcb, 0xc1, 0x66, 0xeb, 0x7d, 0x2a, 0x53, + 0x11, 0x9f, 0xd5, 0xc5, 0xd9, 0xa6, 0x12, 0x67, 0x75, 0x22, 0xce, 0xbe, 0x83, 0x9c, 0xdf, 0x9d, 0x51, 0xd1, 0x67, + 0x0f, 0x69, 0x9d, 0x14, 0x9b, 0x9a, 0x9e, 0xbc, 0xc1, 0x32, 0xbe, 0x3b, 0x23, 0xae, 0x9a, 0x33, 0x1a, 0xc9, 0x78, + 0x74, 0xf6, 0x21, 0x03, 0x92, 0xd7, 0xb3, 0x74, 0x05, 0x83, 0x77, 0x16, 0xe6, 0xf1, 0x59, 0x29, 0xee, 0xc0, 0xe2, + 0x54, 0x76, 0xbe, 0x07, 0x19, 0x56, 0xe1, 0x1f, 0xe2, 0x0c, 0xa0, 0x5d, 0xcf, 0xd2, 0xfa, 0x2c, 0xad, 0xce, 0xf2, + 0xa2, 0x3e, 0x53, 0x52, 0x38, 0x84, 0xf1, 0xc3, 0x7b, 0xfa, 0xca, 0x2e, 0x6f, 0xb3, 0xb8, 0xcb, 0x22, 0x7f, 0x8a, + 0x5e, 0x45, 0xc4, 0xa4, 0x51, 0x09, 0xaf, 0xdd, 0xdf, 0x36, 0xf7, 0x0f, 0xaf, 0x1b, 0xbb, 0x9f, 0xdd, 0x31, 0xa2, + 0x0b, 0xea, 0xf1, 0x4a, 0x52, 0x2a, 0x28, 0x20, 0x70, 0xa2, 0x59, 0xe3, 0xc1, 0x1d, 0x07, 0xbc, 0x1a, 0xd8, 0x92, + 0xad, 0x7d, 0xfe, 0x22, 0x96, 0x61, 0xda, 0x9b, 0x00, 0xff, 0x2a, 0x7b, 0xd3, 0x75, 0xb0, 0xc4, 0xfb, 0x16, 0xb2, + 0x0d, 0xbd, 0x7d, 0xcd, 0x5f, 0x7a, 0xb9, 0xfa, 0x9b, 0xfd, 0x13, 0x80, 0x30, 0x20, 0x66, 0xd5, 0x47, 0x13, 0xf7, + 0xce, 0xca, 0xb2, 0x73, 0xb2, 0xec, 0x7a, 0xe8, 0xd7, 0x24, 0x46, 0xa5, 0x95, 0xa5, 0x74, 0xb2, 0x94, 0x90, 0x05, + 0x7c, 0x62, 0x34, 0xb5, 0x11, 0x40, 0xd8, 0x8e, 0x52, 0xf9, 0x42, 0xe5, 0x45, 0x14, 0xce, 0x09, 0x9e, 0x27, 0x62, + 0x74, 0x6f, 0x25, 0x03, 0x86, 0x43, 0x08, 0xe6, 0xa0, 0x2d, 0xf6, 0x86, 0x6e, 0x22, 0xfe, 0x7a, 0x53, 0x94, 0x6f, + 0x63, 0xf2, 0x29, 0xd8, 0x9d, 0x7c, 0x5c, 0xc2, 0xe3, 0xf2, 0xe4, 0xe3, 0x10, 0x3d, 0x12, 0x4e, 0x3e, 0x06, 0xdf, + 0x23, 0x39, 0xaf, 0xbb, 0x1e, 0x27, 0xc8, 0x2d, 0xa4, 0xfb, 0xdb, 0x31, 0x09, 0xd0, 0xbc, 0x86, 0xe5, 0xa8, 0xa9, + 0xb8, 0x66, 0x66, 0x8c, 0xe7, 0x8d, 0xde, 0x1f, 0x3b, 0xde, 0x32, 0x85, 0x62, 0x16, 0xf3, 0x1a, 0x7e, 0xcf, 0xaa, + 0x40, 0xdd, 0xf5, 0x36, 0xc9, 0x2d, 0xb3, 0x7a, 0x8e, 0x76, 0xdf, 0xf7, 0x75, 0x22, 0xa8, 0xfd, 0x1d, 0xf6, 0x3c, + 0xb3, 0xde, 0x55, 0x31, 0x70, 0xa9, 0x92, 0x1d, 0x32, 0x55, 0x4d, 0x0f, 0x54, 0x4a, 0x83, 0xa7, 0x97, 0xd6, 0xe5, + 0x4b, 0xa5, 0x8d, 0x3c, 0xd3, 0xfc, 0x06, 0xf0, 0x62, 0xea, 0xb2, 0xd8, 0x7d, 0x75, 0x5f, 0xc1, 0x6d, 0xbc, 0xdf, + 0x5f, 0x56, 0x9e, 0xf9, 0x89, 0x0b, 0xc0, 0xde, 0x54, 0x68, 0x9d, 0x40, 0xa9, 0x61, 0x1d, 0xbe, 0x4a, 0x44, 0xf4, + 0x47, 0xbb, 0x5c, 0x67, 0xae, 0x03, 0x46, 0x14, 0xf1, 0xdb, 0x78, 0xf4, 0x07, 0x28, 0xae, 0x8d, 0x3d, 0x20, 0xac, + 0x43, 0x42, 0x9f, 0x11, 0x80, 0xd4, 0x63, 0x8e, 0x12, 0xd0, 0xac, 0x68, 0xee, 0x98, 0xfc, 0x5c, 0x5f, 0x29, 0xfd, + 0xfd, 0xb2, 0xf2, 0xc8, 0x9c, 0xd2, 0x36, 0xd3, 0x58, 0xad, 0xa9, 0x04, 0xc2, 0x2b, 0x2a, 0x59, 0x85, 0xcf, 0xe6, + 0x8d, 0xe8, 0xf7, 0xe5, 0x11, 0x9e, 0x56, 0x3f, 0x6c, 0x31, 0xbe, 0x15, 0x10, 0x8d, 0x04, 0x40, 0x3f, 0x01, 0xcc, + 0x8b, 0x6c, 0x66, 0xf7, 0x71, 0x40, 0x95, 0x12, 0x4d, 0xe3, 0x6c, 0x9e, 0xdf, 0xd2, 0x9b, 0xb2, 0x83, 0x4e, 0x9d, + 0x2a, 0x70, 0xc1, 0x55, 0xc9, 0x78, 0x65, 0x3d, 0x91, 0xcf, 0x6f, 0x6e, 0x37, 0x69, 0x16, 0xbf, 0x2f, 0xff, 0x89, + 0x63, 0xab, 0xeb, 0xf0, 0xc8, 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, 0x4d, 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, 0x1e, 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, 0x45, 0x85, 0x3a, 0x27, 0x96, 0xf1, 0x1a, 0x80, 0xb5, 0x73, 0xd5, 0xcf, + 0xb3, 0x1a, 0x3c, 0x69, 0x88, 0xcf, 0xc7, 0x68, 0x7b, 0x65, 0x73, 0x50, 0x6d, 0xa7, 0xb3, 0xf2, 0x8a, 0xe9, 0x72, + 0x60, 0xdc, 0x37, 0xbc, 0xa2, 0x38, 0xc3, 0x8f, 0x1e, 0x6c, 0x71, 0xfe, 0x74, 0x43, 0xed, 0xc7, 0xdc, 0xa8, 0x87, + 0x81, 0xd6, 0x82, 0x37, 0x05, 0xb1, 0xfe, 0x7e, 0xe8, 0xc8, 0xf6, 0x5e, 0x8b, 0x8c, 0x26, 0x9f, 0xfd, 0xfc, 0x43, + 0x99, 0xae, 0x52, 0xb8, 0x2f, 0x39, 0x59, 0x34, 0xf3, 0x10, 0xd8, 0x1b, 0x62, 0xb8, 0x3e, 0x2a, 0x3c, 0xa2, 0xac, + 0xdf, 0x87, 0xdf, 0x57, 0x19, 0x98, 0x62, 0xe0, 0xba, 0x42, 0x30, 0x1e, 0x02, 0x41, 0x3c, 0x4c, 0xa3, 0x93, 0x41, + 0x0d, 0xda, 0xf0, 0x0d, 0x40, 0x66, 0x80, 0x47, 0xe6, 0xd2, 0x23, 0xe0, 0x2e, 0x70, 0xed, 0xc9, 0x78, 0xec, 0x4f, + 0x4c, 0x43, 0xa3, 0xa6, 0x34, 0xd3, 0x73, 0xe3, 0x37, 0x1d, 0xd5, 0x72, 0xed, 0xfc, 0xc7, 0x97, 0xfc, 0x06, 0xbd, + 0xa0, 0xe5, 0xe5, 0x3e, 0x52, 0x97, 0xfb, 0x8c, 0xe2, 0x32, 0x91, 0x1c, 0x16, 0xc4, 0xb2, 0x84, 0x03, 0x8f, 0x51, + 0xc9, 0x62, 0x4b, 0x8f, 0x55, 0xd1, 0xf2, 0x45, 0xb9, 0x41, 0x3a, 0x74, 0x42, 0xb0, 0x44, 0x05, 0xc1, 0x12, 0x18, + 0x17, 0xb1, 0xe6, 0x9b, 0x41, 0xce, 0xe2, 0xd9, 0x66, 0xce, 0x91, 0xb0, 0x2e, 0x39, 0x1c, 0x0a, 0x09, 0x36, 0x93, + 0xcd, 0xd6, 0x73, 0xb6, 0xf6, 0x19, 0x28, 0x01, 0x4a, 0x99, 0x26, 0x28, 0x4d, 0x2b, 0xb6, 0xe2, 0xa6, 0x35, 0x58, + 0xad, 0xa6, 0x6c, 0x55, 0x53, 0x76, 0x4e, 0x53, 0x8e, 0x2a, 0x28, 0x39, 0xa1, 0x14, 0x65, 0x18, 0xc0, 0x88, 0x4d, + 0xa2, 0xab, 0x0c, 0x7d, 0xbc, 0x13, 0x1e, 0x41, 0x15, 0x11, 0xf9, 0x84, 0x21, 0x04, 0x26, 0xa2, 0xb8, 0x50, 0x85, + 0x62, 0x80, 0x8c, 0x48, 0x20, 0x98, 0xa8, 0xd4, 0x29, 0x30, 0x1f, 0x4d, 0x15, 0xc3, 0xa6, 0x3d, 0x51, 0xbe, 0xa5, + 0x8e, 0x7b, 0x94, 0x6d, 0xfe, 0x2e, 0x76, 0x41, 0x88, 0xdc, 0x8d, 0x3b, 0xf5, 0x33, 0xe2, 0xbd, 0xdd, 0x11, 0xc6, + 0x4f, 0x76, 0xdc, 0x22, 0x5c, 0x11, 0x6c, 0xa9, 0xe6, 0x10, 0x8b, 0x79, 0x35, 0x49, 0x50, 0xcb, 0x92, 0xf8, 0x1b, + 0x9e, 0x0c, 0x72, 0xb6, 0x04, 0x0f, 0xda, 0x39, 0xcb, 0x00, 0x7f, 0xc5, 0x6a, 0xd1, 0x6f, 0xb5, 0xb7, 0x04, 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, 0x8f, 0xbd, 0x04, 0x3b, 0x07, 0xbc, 0x81, 0xb4, 0x81, + 0x37, 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, 0x22, 0x01, + 0xc0, 0xa4, 0xce, 0x81, 0x38, 0x33, 0xc1, 0x2e, 0x4d, 0x22, 0xcb, 0xc7, 0x30, 0xbf, 0x13, 0x6f, 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, 0x52, 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, 0xd7, 0x90, 0x74, 0x6c, + 0xe0, 0xb4, 0xfa, 0x14, 0x7c, 0x90, 0xe4, 0x60, 0xa2, 0x0e, 0x5e, 0xee, 0x2f, 0xfd, 0x3e, 0x6c, 0xd9, 0xb9, 0x94, + 0xea, 0x58, 0xa9, 0xb7, 0x6d, 0xed, 0x07, 0xd1, 0x16, 0x1c, 0x59, 0xc4, 0xdf, 0x67, 0x88, 0x08, 0x66, 0x06, 0x11, + 0x76, 0x2d, 0xd4, 0xdd, 0x9e, 0x52, 0xcb, 0xa2, 0xde, 0xf6, 0x94, 0x52, 0xb7, 0x61, 0xf8, 0x6e, 0x82, 0x99, 0xe2, + 0x86, 0xff, 0x91, 0x79, 0xa1, 0xde, 0x78, 0x2c, 0x0a, 0x74, 0xcf, 0xdf, 0x2f, 0x79, 0x35, 0xdb, 0x28, 0x13, 0xe6, + 0x1d, 0x5f, 0xce, 0x42, 0xd9, 0xd5, 0xd2, 0xb8, 0xf3, 0xd9, 0x5b, 0xaa, 0xf9, 0xe0, 0x1f, 0x0e, 0x09, 0xc4, 0x1b, + 0xc5, 0x57, 0x77, 0x8d, 0xdc, 0xba, 0x26, 0x9b, 0xab, 0x12, 0x50, 0xbf, 0xcf, 0xd7, 0xb8, 0xdf, 0x62, 0xfd, 0xbb, + 0xa7, 0x41, 0xc6, 0x6a, 0x86, 0x2b, 0xa6, 0xf0, 0x29, 0x00, 0x0c, 0x0e, 0xa7, 0x82, 0xb4, 0xc0, 0x1b, 0x5e, 0x0e, + 0x2f, 0x27, 0x1b, 0x32, 0xe9, 0x6e, 0x7c, 0xe4, 0xce, 0x02, 0x55, 0xef, 0x37, 0x14, 0x27, 0x0d, 0x12, 0x8d, 0xbd, + 0x06, 0x5f, 0x66, 0x19, 0xe5, 0xa2, 0x89, 0xfb, 0x98, 0x7c, 0xa5, 0x07, 0x30, 0x57, 0xa1, 0x04, 0x88, 0x7e, 0x63, + 0x59, 0x6c, 0x44, 0xdb, 0x62, 0x03, 0x4b, 0xa9, 0x9a, 0xeb, 0xd5, 0xf4, 0xd9, 0x2b, 0xd1, 0xbc, 0x8f, 0x66, 0x9c, + 0xd2, 0x68, 0xc0, 0x71, 0x1a, 0x85, 0xdb, 0xf7, 0xf7, 0xa2, 0x5c, 0x66, 0x60, 0xc9, 0x56, 0xe1, 0x14, 0x97, 0x8d, + 0x3a, 0x23, 0x5e, 0xe6, 0xb1, 0x02, 0xe8, 0x78, 0x4c, 0x00, 0x54, 0x17, 0x04, 0x54, 0x44, 0x4b, 0xe9, 0xad, 0xd0, + 0x62, 0xa1, 0xde, 0x70, 0x94, 0xc2, 0x1f, 0xe9, 0xcf, 0x83, 0x7c, 0x0a, 0x40, 0xec, 0xfa, 0x38, 0x7a, 0x53, 0x94, + 0xf4, 0xa9, 0x62, 0x96, 0xcb, 0xc1, 0x04, 0x76, 0x75, 0x22, 0x43, 0xad, 0x20, 0x6f, 0xd5, 0x95, 0xb7, 0x32, 0x79, + 0x1b, 0xe3, 0x94, 0xfc, 0xc8, 0x4d, 0xc7, 0x1a, 0x31, 0xf0, 0xca, 0xd3, 0x3a, 0x4d, 0x90, 0x26, 0x17, 0xc0, 0x30, + 0xc4, 0xb7, 0x99, 0xf7, 0xd2, 0x73, 0xa4, 0x2a, 0x48, 0x66, 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, 0xcb, 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, 0xb5, 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, 0x17, 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, 0x57, 0x99, 0xbe, 0x85, 0x98, 0x28, 0xa7, 0x1a, 0x21, 0x71, 0xa5, 0x24, 0x11, 0x1f, + 0x2f, 0x5a, 0x56, 0x8c, 0xca, 0xf0, 0x81, 0x57, 0xaa, 0x7c, 0x75, 0xaa, 0xf2, 0x62, 0xa4, 0x6d, 0x09, 0xbc, 0x26, + 0xff, 0x10, 0xb9, 0xe6, 0xad, 0xaf, 0xbb, 0xca, 0xd0, 0x6b, 0x59, 0x81, 0x8e, 0x60, 0x2b, 0x4b, 0xc9, 0x01, 0x9f, + 0x54, 0x77, 0xd5, 0xaa, 0xf5, 0x39, 0x65, 0x1b, 0xe1, 0x26, 0xbf, 0x8e, 0x1d, 0x1c, 0x29, 0xbf, 0xc1, 0x73, 0x01, + 0xec, 0x35, 0x60, 0x6f, 0xce, 0x59, 0xd1, 0x3c, 0x3a, 0xa4, 0x6d, 0x81, 0x46, 0x66, 0x6e, 0xe7, 0xea, 0xbe, 0x2d, + 0x8f, 0xd2, 0x18, 0x22, 0xd3, 0x1e, 0x99, 0x0e, 0x36, 0xa3, 0xfc, 0xb7, 0x94, 0xdf, 0x2a, 0x1c, 0x03, 0xdf, 0x4e, + 0xbd, 0x03, 0xa8, 0x7a, 0xda, 0x20, 0x63, 0xcd, 0x30, 0xb4, 0xb2, 0xcb, 0xa5, 0xd0, 0x12, 0xb4, 0xd4, 0x4d, 0x10, + 0x9c, 0x1f, 0x11, 0xe5, 0x08, 0x40, 0x17, 0x29, 0x60, 0x82, 0x9f, 0xd2, 0x76, 0xf7, 0xfb, 0xeb, 0xd4, 0x23, 0xf7, + 0xae, 0x50, 0xa3, 0x84, 0x12, 0x8c, 0xfd, 0x44, 0x63, 0x06, 0x1d, 0x5d, 0x91, 0x13, 0x9e, 0xb5, 0x3a, 0xac, 0xeb, + 0xa6, 0x0c, 0xca, 0xe2, 0x98, 0x57, 0xd3, 0xd9, 0xef, 0x4f, 0xf6, 0x75, 0x83, 0x2c, 0xe4, 0xbf, 0xb3, 0x1e, 0x92, + 0x41, 0xf7, 0x20, 0x14, 0xa2, 0x37, 0x0f, 0x66, 0xf8, 0x1f, 0xdb, 0xf0, 0xec, 0x1b, 0x6e, 0xd4, 0x09, 0x60, 0x8e, + 0xb8, 0x5e, 0x7a, 0x8a, 0xb6, 0x1e, 0x6e, 0x81, 0x6c, 0x8d, 0x97, 0xb7, 0xf6, 0x1a, 0xc8, 0x29, 0x8e, 0xff, 0x8e, + 0x67, 0x6a, 0x65, 0x83, 0x9f, 0x9e, 0xb2, 0x1d, 0x78, 0x78, 0x11, 0x02, 0x8a, 0x61, 0xd9, 0xf8, 0x3b, 0xcb, 0x71, + 0x46, 0xff, 0xcd, 0x23, 0x86, 0xc1, 0x22, 0xf2, 0xe3, 0xcb, 0x52, 0x88, 0x2f, 0xc2, 0x7b, 0x5b, 0x79, 0x77, 0xe4, + 0x94, 0x79, 0xa7, 0x87, 0xd1, 0x75, 0x49, 0xfa, 0x26, 0xf9, 0xd8, 0x1a, 0xb6, 0xdf, 0xb5, 0xfb, 0xcd, 0x10, 0x41, + 0x08, 0xe5, 0xf8, 0x39, 0xa3, 0x13, 0x1a, 0x1f, 0x56, 0xb3, 0xd3, 0xeb, 0xf7, 0xce, 0xf1, 0x82, 0xad, 0xd1, 0x00, + 0x8f, 0x87, 0x2e, 0xe6, 0x89, 0x1a, 0x3a, 0x5d, 0xd7, 0xce, 0xc1, 0x03, 0x83, 0x2c, 0x4f, 0xbe, 0x61, 0x58, 0x62, + 0x7f, 0x12, 0xf1, 0xa4, 0xad, 0xda, 0xd8, 0x1c, 0xa9, 0x36, 0x6a, 0x06, 0x7e, 0xf0, 0x0a, 0x0a, 0x8c, 0x2e, 0x48, + 0x2b, 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, 0x6f, 0xa9, 0x57, 0xfb, 0x32, 0x66, 0x85, 0x7a, 0x7d, 0x61, 0xda, 0xf5, 0x5a, 0x5a, 0x14, 0x50, + 0x71, 0xdb, 0xaa, 0xed, 0x91, 0x9c, 0xff, 0xf8, 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, 0x6f, + 0xa9, 0x57, 0xb5, 0xa9, 0xea, 0xc1, 0x1b, 0x2f, 0x70, 0xf6, 0x4e, 0x6b, 0x01, 0x01, 0x14, 0xb6, 0x96, 0xe5, 0xe0, + 0xdc, 0xed, 0xaa, 0x96, 0x8a, 0x32, 0xea, 0xf7, 0xcf, 0x7f, 0x4b, 0x51, 0x11, 0x7b, 0xaa, 0x38, 0x65, 0xfd, 0x76, + 0xcb, 0x5c, 0x54, 0x96, 0xbc, 0x41, 0x15, 0xad, 0xd5, 0x51, 0x53, 0xb9, 0x6e, 0xae, 0x5a, 0x32, 0x41, 0x8c, 0xee, + 0xd3, 0xb5, 0xce, 0x9d, 0x7a, 0xef, 0x55, 0x1c, 0x31, 0x10, 0xdc, 0x74, 0x8f, 0x0f, 0x0e, 0x42, 0xa3, 0xa2, 0x5c, + 0x70, 0xa3, 0xb4, 0xaa, 0xa4, 0x14, 0xf2, 0x56, 0x45, 0x73, 0xa6, 0x8f, 0x00, 0x88, 0x00, 0xab, 0x44, 0xfd, 0x1f, + 0xbe, 0x34, 0xc6, 0x83, 0x07, 0xbe, 0x26, 0xd7, 0xb1, 0xf5, 0xfe, 0x69, 0x8d, 0xb4, 0xda, 0x38, 0x26, 0xb5, 0xea, + 0x65, 0xab, 0x78, 0xd9, 0xbd, 0x4e, 0xc5, 0xe0, 0xf9, 0xff, 0xdc, 0x07, 0xa8, 0x11, 0x2d, 0x65, 0x70, 0xeb, 0x6a, + 0x80, 0xc6, 0x87, 0x63, 0xe1, 0x1b, 0x3f, 0x64, 0x9c, 0x0f, 0x66, 0xe8, 0xa8, 0x36, 0x07, 0x07, 0x04, 0x47, 0x75, + 0x8f, 0xc6, 0x84, 0x59, 0x38, 0xf7, 0x20, 0x50, 0x7d, 0xe2, 0x3e, 0xe3, 0xda, 0x0b, 0xda, 0x04, 0x3e, 0x59, 0xd7, + 0x35, 0x45, 0x80, 0x8b, 0xd8, 0x98, 0x88, 0x21, 0x2e, 0x9b, 0x44, 0xea, 0x9b, 0x31, 0x28, 0x00, 0x8a, 0x17, 0x15, + 0xc9, 0xa5, 0x8b, 0x34, 0xaf, 0x44, 0x59, 0xeb, 0x66, 0x54, 0xac, 0x18, 0x02, 0xc0, 0x43, 0x50, 0x5c, 0x55, 0x66, + 0x42, 0x23, 0x36, 0x90, 0xca, 0x52, 0xb0, 0x6a, 0x58, 0xf8, 0x4d, 0xfb, 0x4d, 0x72, 0xd2, 0x3b, 0x1f, 0xb7, 0xce, + 0x1d, 0xfb, 0xde, 0x51, 0x48, 0x69, 0x0f, 0xc5, 0x04, 0x41, 0xf0, 0xd3, 0x3a, 0x9c, 0x3f, 0xe3, 0x2f, 0x08, 0x4c, + 0x45, 0x36, 0x63, 0xc0, 0x41, 0x88, 0xc8, 0x8c, 0xdf, 0x73, 0xf8, 0x82, 0x97, 0x93, 0x70, 0x38, 0xf4, 0x41, 0x1f, + 0xca, 0xb3, 0x59, 0x38, 0x14, 0x73, 0xe9, 0xbd, 0x0e, 0xd6, 0xba, 0x90, 0xd7, 0x93, 0x10, 0xd1, 0x42, 0x43, 0x1f, + 0x9c, 0xd7, 0x5d, 0x73, 0x84, 0x25, 0x00, 0x4d, 0x1c, 0x7d, 0x59, 0xbf, 0x1f, 0x79, 0xda, 0xd0, 0x22, 0xc5, 0x45, + 0xa3, 0xcc, 0x66, 0xb9, 0xec, 0x84, 0x8d, 0x6b, 0xb7, 0x40, 0x28, 0x1e, 0xa6, 0x2d, 0x54, 0xad, 0xa7, 0x7a, 0x3d, + 0x37, 0xed, 0xbe, 0x7b, 0x54, 0xad, 0x72, 0xa4, 0xb3, 0x36, 0x5d, 0xa9, 0xd5, 0x2d, 0xa3, 0x6a, 0x9d, 0xa5, 0x11, + 0x55, 0x6e, 0x92, 0xbb, 0x46, 0x2d, 0xf8, 0x64, 0x43, 0x97, 0x29, 0x3b, 0x5b, 0x83, 0x13, 0x47, 0x9e, 0x4b, 0x6e, + 0xf9, 0xee, 0xbc, 0xa2, 0xbb, 0x53, 0xed, 0x5b, 0x80, 0x7b, 0x33, 0x6c, 0xc8, 0x9c, 0xd7, 0xd8, 0x69, 0x10, 0x26, + 0x81, 0x1f, 0xb1, 0x8f, 0x19, 0xb2, 0xc1, 0x80, 0x8e, 0x42, 0xfa, 0x5f, 0x5b, 0xe6, 0x48, 0xc0, 0xe4, 0xaf, 0xe7, + 0x7e, 0xb3, 0x28, 0x72, 0x58, 0x8c, 0x1f, 0x36, 0x18, 0x69, 0xac, 0xd6, 0x60, 0x58, 0xde, 0x21, 0xf2, 0xa7, 0x76, + 0xc7, 0x34, 0xd5, 0xf1, 0x66, 0xbd, 0xd6, 0xfc, 0xea, 0xe9, 0x53, 0x5d, 0x9f, 0xff, 0xf6, 0xfd, 0x65, 0x58, 0x33, + 0xfb, 0x43, 0x10, 0x4a, 0xbb, 0x77, 0x8b, 0x73, 0x47, 0xa2, 0x77, 0xac, 0x34, 0xb3, 0x4b, 0xbb, 0x64, 0x97, 0xa6, + 0xb4, 0x1b, 0x72, 0xbd, 0xfa, 0x4a, 0x79, 0x63, 0xe7, 0x15, 0xd3, 0xfd, 0x7b, 0xa1, 0x77, 0x94, 0x53, 0x35, 0x81, + 0x88, 0x26, 0xed, 0x48, 0xdc, 0xee, 0x95, 0xe1, 0xf3, 0x49, 0xde, 0x2e, 0xe1, 0xa8, 0x6b, 0x58, 0x6e, 0xbe, 0xfd, + 0xcf, 0xbc, 0xea, 0xac, 0x70, 0xfb, 0xa5, 0x31, 0x6b, 0x7f, 0x0a, 0xe2, 0xaa, 0xfe, 0xf0, 0x9e, 0xd4, 0x4c, 0xc9, + 0xff, 0x55, 0x8f, 0x81, 0xab, 0x9f, 0x4c, 0x3b, 0xba, 0xa7, 0x10, 0x36, 0x98, 0xfd, 0xfc, 0xf8, 0xa1, 0x05, 0xab, + 0xea, 0x02, 0x45, 0x72, 0x00, 0x9d, 0xbb, 0x64, 0x84, 0xf7, 0x3b, 0xc6, 0xb9, 0x7f, 0xf5, 0xbd, 0x9a, 0x1c, 0x21, + 0xa2, 0x5d, 0x84, 0x03, 0x80, 0xb8, 0xd3, 0x54, 0xd6, 0xa1, 0x06, 0xe8, 0x03, 0x02, 0xeb, 0xd0, 0xb7, 0x19, 0xc0, + 0x41, 0x1f, 0x6d, 0x9e, 0x45, 0x20, 0xaf, 0x7b, 0xf7, 0xec, 0x9a, 0xed, 0x7c, 0xfe, 0x62, 0x95, 0x7a, 0xf7, 0xe8, + 0x10, 0x7c, 0x3e, 0xf6, 0xa7, 0x97, 0x81, 0xc1, 0x85, 0x66, 0xd7, 0xcf, 0x04, 0xdb, 0xb1, 0xdd, 0x33, 0x44, 0x2a, + 0xea, 0xce, 0x3f, 0xbc, 0x34, 0xd1, 0xf3, 0xce, 0x0b, 0x77, 0x7c, 0x09, 0xe0, 0x81, 0x2c, 0x06, 0x14, 0x9f, 0xa5, + 0xf7, 0x2f, 0x96, 0x80, 0x9a, 0xfc, 0x96, 0xaf, 0xbd, 0x2f, 0x94, 0xba, 0x80, 0x3f, 0x07, 0x94, 0x3e, 0xc9, 0xb9, + 0x77, 0x37, 0xbc, 0xf5, 0x2f, 0x9e, 0x83, 0xf3, 0xc4, 0x6a, 0xb8, 0x80, 0xbf, 0x0a, 0x3e, 0xf4, 0xee, 0x06, 0x98, + 0x58, 0xf2, 0xa1, 0xb7, 0x1a, 0x40, 0xaa, 0xc2, 0x85, 0xc4, 0xd8, 0x87, 0x5f, 0x83, 0x9c, 0xe1, 0x1f, 0xbf, 0x69, + 0x0c, 0xd6, 0x5f, 0x83, 0x42, 0xa3, 0xb1, 0x96, 0x2a, 0x64, 0x29, 0x16, 0x67, 0x02, 0x6c, 0xc2, 0x71, 0xb7, 0x2f, + 0x56, 0xb5, 0x59, 0x0b, 0xfa, 0xf3, 0x11, 0xdf, 0xa3, 0xb1, 0xba, 0x2a, 0xe7, 0xa2, 0xfc, 0x88, 0xf4, 0xa9, 0x8e, + 0x8f, 0x51, 0xb1, 0xa9, 0xbb, 0xd3, 0xa9, 0x56, 0x1d, 0x69, 0xbf, 0x29, 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, 0x2f, 0x06, 0xb9, 0x0c, 0x8d, 0xf9, 0x80, 0x6c, 0x18, 0xca, 0x87, 0x16, 0x19, 0x12, 0x22, 0xde, 0x43, + 0x25, 0x60, 0xdb, 0x82, 0x32, 0x29, 0xe0, 0x2c, 0x1a, 0xfc, 0x56, 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, 0x1f, 0xae, 0xf2, 0x4f, 0xd1, 0x52, 0x0f, 0xff, 0x9f, 0x31, 0x85, 0xd2, + 0xbf, 0x4a, 0xcb, 0x68, 0xb3, 0x5a, 0x8a, 0x52, 0xe4, 0x91, 0x38, 0xf9, 0x5a, 0x64, 0xe7, 0xf2, 0x9d, 0x4f, 0xa1, + 0x5f, 0x00, 0x5a, 0xf6, 0x09, 0x32, 0xfa, 0x7b, 0x26, 0xf8, 0xf0, 0x7b, 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, 0x7b, 0x83, 0x90, 0xe2, 0xf9, 0x03, 0x5b, 0xad, 0x8b, 0x8b, 0xc4, 0x2b, 0x64, + 0xa2, 0x05, 0xb1, 0x14, 0x81, 0x19, 0x2f, 0x34, 0x8d, 0x30, 0x41, 0x99, 0x12, 0x2c, 0x5a, 0xa3, 0x43, 0xfb, 0xc3, + 0x12, 0x76, 0x8f, 0x31, 0x02, 0x04, 0xaa, 0x4c, 0x9f, 0xc3, 0xd6, 0x84, 0xd9, 0xd4, 0xc5, 0x06, 0x68, 0xab, 0x18, + 0x1a, 0x84, 0xb5, 0x21, 0xe6, 0x63, 0x9a, 0xdf, 0xfd, 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, 0xee, 0x1a, 0xfe, 0x21, 0xf3, 0x62, 0x96, 0x80, 0x7e, 0x77, 0xc5, 0x55, 0x83, 0xa0, 0x19, 0x1b, 0x76, + 0x0b, 0xbf, 0x25, 0xd6, 0x6e, 0xe9, 0x5f, 0x2c, 0xd9, 0xc2, 0xf4, 0x81, 0x6e, 0x1d, 0x60, 0x19, 0x51, 0x93, 0xef, + 0x91, 0x77, 0xd3, 0x59, 0x51, 0xb8, 0x3d, 0xb1, 0x85, 0xcf, 0xae, 0xcd, 0x9b, 0xf7, 0xcf, 0x22, 0xc8, 0xbd, 0xe3, + 0xde, 0xfd, 0xf0, 0xda, 0xbf, 0xd0, 0x2d, 0x90, 0x93, 0x59, 0xce, 0x40, 0xea, 0x88, 0x4f, 0x10, 0xad, 0xec, 0x29, + 0xdf, 0x09, 0xb9, 0xb3, 0xad, 0x9f, 0xdd, 0xbb, 0xdb, 0xda, 0xdd, 0xb3, 0x7b, 0x56, 0x8d, 0x28, 0x56, 0x9c, 0xa6, + 0x48, 0x98, 0x45, 0x1b, 0xe0, 0xa9, 0x97, 0xef, 0x77, 0xec, 0x98, 0xc3, 0xdd, 0xb3, 0x8e, 0x8e, 0x97, 0x73, 0xc0, + 0xee, 0xfe, 0xa3, 0x4d, 0xd8, 0x58, 0xe9, 0x5a, 0x85, 0x0e, 0x77, 0xcf, 0x32, 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, 0x2b, 0x2e, 0xbe, 0x3f, 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, 0x9c, 0xc5, 0x90, 0x08, 0xb0, 0xdd, 0xa1, 0x62, 0x5b, 0xb8, 0x78, + 0xce, 0x36, 0xbc, 0xe8, 0xf7, 0x33, 0xd5, 0x29, 0x64, 0xdd, 0x59, 0xf2, 0x8d, 0x6a, 0x8e, 0x35, 0xd4, 0x6c, 0x6d, + 0x92, 0xad, 0x71, 0x6e, 0x2b, 0x3e, 0xee, 0xda, 0x8a, 0x8f, 0x95, 0xb5, 0x2e, 0xdd, 0xeb, 0x3d, 0xaa, 0x0b, 0x60, + 0xeb, 0xbf, 0x3d, 0x5e, 0xb9, 0x9e, 0xcf, 0x08, 0xe0, 0x6b, 0xc1, 0xc7, 0x93, 0x05, 0x7a, 0x95, 0x2c, 0xfc, 0xdb, + 0x81, 0x1a, 0x7f, 0xa7, 0x73, 0x17, 0x00, 0x5d, 0x49, 0x79, 0x05, 0xe4, 0x1d, 0xe4, 0x98, 0x5b, 0x76, 0xe5, 0xfd, + 0xc9, 0x77, 0xd8, 0x35, 0xaf, 0x67, 0x8b, 0x39, 0xdb, 0x81, 0x53, 0x41, 0x32, 0xb0, 0x97, 0x15, 0xdb, 0x05, 0xb1, + 0x9d, 0xf0, 0x1b, 0x01, 0x53, 0xbe, 0x84, 0x20, 0xae, 0xe0, 0x16, 0xe2, 0xf0, 0xe4, 0x9f, 0x83, 0xfb, 0xd6, 0x66, + 0x7d, 0xcf, 0xac, 0xce, 0x09, 0xd6, 0xcc, 0xea, 0xc1, 0x60, 0xd9, 0x4c, 0x56, 0xfd, 0xbe, 0xb7, 0xd3, 0x8e, 0x4f, + 0x77, 0x52, 0x27, 0x76, 0x5a, 0xab, 0xb5, 0x60, 0xd7, 0x52, 0xeb, 0x62, 0x0c, 0x3d, 0x40, 0xfc, 0x74, 0x3b, 0xe0, + 0xf7, 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, 0xc7, 0x6c, 0xc7, 0xb8, + 0xf9, 0xe9, 0xe5, 0x0f, 0x4e, 0x58, 0xb2, 0x62, 0xb5, 0x3f, 0xfd, 0xfe, 0x99, 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, 0x99, 0xfa, 0xc0, 0x88, 0x25, 0x81, 0xda, 0x5e, + 0x66, 0xe9, 0x1d, 0xa8, 0xf0, 0x7b, 0xb8, 0x9a, 0x88, 0xfd, 0xdc, 0x92, 0xa2, 0x22, 0x1b, 0xe9, 0x0d, 0xad, 0xc1, + 0x23, 0xb4, 0xa6, 0x7c, 0xef, 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, 0xd7, 0x24, 0x61, 0x4f, 0x0c, + 0x3a, 0x85, 0xaa, 0xdc, 0xee, 0x8e, 0xb6, 0xc0, 0x75, 0xcc, 0x52, 0xf4, 0xd2, 0x16, 0xb9, 0x5b, 0xfe, 0xdd, 0x73, + 0x45, 0xce, 0x7e, 0x09, 0x08, 0x4e, 0xcd, 0x57, 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, 0xe6, 0x2e, 0xc9, 0x37, 0xe0, + 0xcc, 0x40, 0xa9, 0x96, 0x7e, 0xe0, 0x58, 0x2d, 0xa0, 0xc2, 0xc1, 0xec, 0xa4, 0x5e, 0x58, 0x46, 0x3d, 0xa6, 0xcf, + 0xcf, 0x60, 0xef, 0x08, 0x09, 0x80, 0xfb, 0x65, 0x1f, 0x90, 0x80, 0x87, 0xce, 0xec, 0x80, 0x70, 0xc2, 0x2c, 0xaa, + 0x02, 0x89, 0xe4, 0x48, 0x3f, 0x7b, 0xcc, 0x44, 0xf2, 0x07, 0xb3, 0x9e, 0x73, 0x4a, 0xf4, 0x58, 0x4f, 0x1d, 0x21, + 0x3d, 0xd6, 0xb3, 0x8e, 0x88, 0x1e, 0xeb, 0x59, 0xc7, 0x47, 0x8f, 0xf5, 0xcc, 0xb1, 0xd3, 0x83, 0xc0, 0x04, 0x88, + 0x3c, 0x60, 0x3d, 0x9a, 0x4c, 0x3d, 0xc5, 0x3d, 0x40, 0x34, 0x08, 0xac, 0x27, 0x85, 0xf3, 0x1e, 0x20, 0x8f, 0x91, + 0x58, 0x1d, 0xf4, 0xfe, 0x32, 0x7e, 0xda, 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, + 0x07, 0x51, 0xf3, 0xb4, 0xd5, 0x56, 0xc1, 0xfe, 0x0e, 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, 0x1f, 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, 0x7f, 0x95, 0xa5, 0xc6, 0x39, 0x32, 0x97, 0xeb, 0xbb, 0x2e, 0xee, 0xee, 0x68, 0x9b, 0xb0, 0x0a, 0x11, + 0xea, 0xb6, 0xa1, 0x72, 0x29, 0xcc, 0xc6, 0xa6, 0x69, 0x80, 0x2f, 0x14, 0x95, 0x4a, 0x55, 0x6a, 0x2b, 0x95, 0x9c, + 0xf0, 0xae, 0xaf, 0x6a, 0x91, 0xba, 0x22, 0xd8, 0xc6, 0x0c, 0xf5, 0x50, 0x6e, 0xd4, 0xd8, 0xd7, 0x1d, 0xab, 0xf4, + 0x0e, 0x13, 0xe4, 0x8c, 0xbc, 0xc8, 0xc1, 0x45, 0x49, 0x41, 0xe6, 0x6a, 0x08, 0xf3, 0x47, 0x0d, 0x9f, 0x16, 0x96, + 0x7b, 0x28, 0x01, 0xb3, 0xa3, 0x86, 0x97, 0x11, 0x02, 0x11, 0x97, 0xca, 0xbe, 0x62, 0xe2, 0xf7, 0x14, 0xcc, 0x92, + 0x09, 0xdd, 0x8b, 0x58, 0x18, 0xa1, 0x8d, 0x4f, 0x92, 0x64, 0xea, 0x69, 0x0a, 0x6e, 0xe4, 0x32, 0xcc, 0xd1, 0x08, + 0x2d, 0xf9, 0xc8, 0x81, 0xf4, 0xb5, 0x9c, 0x4a, 0xf0, 0x11, 0x75, 0x0a, 0x38, 0x9e, 0x9f, 0x17, 0xd6, 0x4f, 0x96, + 0x4b, 0xcc, 0x65, 0x6d, 0xfe, 0xcb, 0x8e, 0x8e, 0xc1, 0x2e, 0x4f, 0x13, 0xc7, 0xd5, 0x7f, 0x54, 0x25, 0xc5, 0xc3, + 0xcf, 0x69, 0x0e, 0x28, 0x82, 0x99, 0x3d, 0xc5, 0xf8, 0xd8, 0x67, 0x99, 0x02, 0xfe, 0x76, 0xbd, 0xb5, 0x64, 0x62, + 0x97, 0xb4, 0x9b, 0x2b, 0xe3, 0x97, 0xda, 0xb0, 0xe3, 0xe0, 0xdc, 0x00, 0x14, 0x67, 0x8d, 0x0e, 0xcb, 0x6b, 0xdd, + 0xb6, 0x2a, 0x54, 0xa0, 0xd6, 0xff, 0xd9, 0x2d, 0x4c, 0x79, 0x9b, 0x97, 0xca, 0xdb, 0x3c, 0x34, 0x01, 0x02, 0x91, + 0x19, 0xf2, 0xac, 0xe9, 0x98, 0x24, 0xee, 0x1d, 0x29, 0x69, 0xdf, 0x91, 0xe2, 0x47, 0xef, 0x48, 0xc8, 0xb7, 0x84, + 0x8e, 0xec, 0x4b, 0x4e, 0x4e, 0xa0, 0xcc, 0x60, 0x2f, 0xaf, 0x99, 0xec, 0x1f, 0xd0, 0x5e, 0x38, 0x97, 0xe5, 0x15, + 0xbf, 0x16, 0xde, 0xda, 0x9f, 0xae, 0x4f, 0xbb, 0xaa, 0xde, 0x7e, 0x65, 0x66, 0x1e, 0x0e, 0xc5, 0xe1, 0x50, 0x99, + 0xa0, 0xdd, 0x05, 0x17, 0x83, 0x9c, 0xdd, 0xbb, 0xf1, 0xf1, 0xd7, 0x1c, 0x45, 0x6c, 0xa5, 0x3c, 0x92, 0x2e, 0x54, + 0x62, 0x78, 0x69, 0xe0, 0x61, 0x76, 0x7c, 0x3c, 0xd9, 0x5d, 0xdd, 0x4f, 0x06, 0x83, 0x9d, 0xea, 0xdb, 0x2d, 0xaf, + 0x67, 0xbb, 0x39, 0x7b, 0xe0, 0xb7, 0xd3, 0x6d, 0xb0, 0x6f, 0x60, 0xdb, 0xdd, 0x5d, 0x89, 0xc3, 0x61, 0xf7, 0x82, + 0x2f, 0xfc, 0xfd, 0x03, 0x02, 0x3a, 0xf3, 0xf3, 0x71, 0x1b, 0xe3, 0xe7, 0xa6, 0xed, 0xaa, 0xb5, 0x03, 0x78, 0xfa, + 0x1f, 0xbc, 0x9b, 0xd9, 0x72, 0xee, 0xb3, 0x27, 0xfc, 0x01, 0xfc, 0xf3, 0x71, 0x93, 0x44, 0xea, 0x13, 0xed, 0x32, + 0x79, 0x03, 0x0e, 0xe4, 0x3b, 0x9f, 0xbd, 0xe5, 0x0f, 0xb3, 0xe5, 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, 0x76, 0xc3, + 0x22, 0x3f, 0x80, 0x0f, 0xb2, 0x9d, 0x3f, 0x91, 0x35, 0xa5, 0xfb, 0xc5, 0x13, 0xff, 0x70, 0xa0, 0xbf, 0xde, 0xfa, + 0x87, 0xc3, 0x7b, 0xf6, 0x80, 0xe0, 0xe8, 0x7c, 0x07, 0xfd, 0xa3, 0x6f, 0x1d, 0x50, 0x95, 0xe1, 0xf5, 0x6c, 0x33, + 0xf7, 0x5f, 0xac, 0xd8, 0x1d, 0x70, 0xa1, 0x28, 0x2f, 0xb4, 0x1b, 0xf6, 0x80, 0x5e, 0x67, 0xe4, 0x44, 0x34, 0xdb, + 0xcd, 0x7d, 0x16, 0xe3, 0x73, 0x75, 0x5f, 0x4c, 0xbe, 0x7a, 0x5f, 0xdc, 0xb1, 0x6d, 0xf7, 0x7d, 0x51, 0xbe, 0xe9, + 0xae, 0x9f, 0x2d, 0xdb, 0xb1, 0x07, 0x98, 0x61, 0xd7, 0xfc, 0xa6, 0x39, 0x76, 0x8c, 0xfd, 0xea, 0x8d, 0x11, 0x40, + 0x99, 0x2d, 0x58, 0x2c, 0x38, 0x28, 0xd5, 0xaa, 0x6d, 0x49, 0xe4, 0x95, 0x0e, 0x54, 0x9b, 0x11, 0xdc, 0x57, 0x0b, + 0x39, 0xf3, 0xcc, 0x40, 0xdf, 0x56, 0x88, 0x16, 0x0e, 0x1b, 0xf0, 0x57, 0xda, 0x3a, 0xc6, 0x30, 0xcd, 0x6a, 0xa6, + 0x6d, 0x51, 0x97, 0xdf, 0xf6, 0x9e, 0xc9, 0x6f, 0x64, 0x60, 0x0b, 0x91, 0x14, 0x8e, 0xe3, 0x8b, 0xe7, 0x27, 0xfc, + 0x57, 0x2d, 0x8f, 0x5a, 0xed, 0x17, 0x4a, 0x7d, 0xfa, 0x8a, 0x8e, 0x68, 0xe2, 0x5e, 0xb4, 0x65, 0x58, 0xa3, 0xac, + 0xa9, 0xa5, 0xc3, 0x30, 0xae, 0x61, 0x5f, 0x1e, 0x38, 0xf4, 0x1d, 0x10, 0x68, 0xab, 0x54, 0x0a, 0xb4, 0x70, 0x0c, + 0xa3, 0x30, 0x0b, 0x29, 0x8f, 0x0b, 0xb3, 0x94, 0xf7, 0x58, 0xa0, 0xc5, 0xad, 0xba, 0xc7, 0xd4, 0x76, 0x0b, 0x22, + 0xac, 0xde, 0x32, 0xce, 0x2f, 0x1b, 0x55, 0xb8, 0x2d, 0x40, 0x51, 0x04, 0x65, 0xb0, 0x27, 0xb9, 0x6d, 0xa1, 0xa4, + 0xd9, 0x28, 0xac, 0xc5, 0x5d, 0x51, 0xee, 0x7a, 0x0d, 0x5b, 0xe0, 0x05, 0x55, 0x3f, 0x21, 0x6c, 0xcb, 0x9e, 0x75, + 0x28, 0x17, 0xe9, 0x7f, 0x64, 0xe9, 0xf9, 0x76, 0x6b, 0xce, 0xff, 0xf4, 0x15, 0x7d, 0x54, 0xfe, 0xe7, 0x97, 0xf4, + 0x93, 0xc1, 0x32, 0x72, 0x4a, 0x7d, 0x1f, 0x8d, 0x6e, 0xd3, 0x9c, 0x30, 0xb6, 0x7c, 0xfd, 0xf4, 0x1b, 0x64, 0x0a, + 0x92, 0x43, 0x29, 0x55, 0x39, 0xd9, 0x43, 0x5f, 0x78, 0xdd, 0x87, 0x99, 0x60, 0x00, 0xc2, 0x6b, 0xb4, 0xa9, 0x26, + 0x4c, 0xe2, 0xd1, 0x15, 0xfc, 0xdf, 0x08, 0x62, 0xd0, 0x3e, 0x51, 0xd4, 0xb1, 0x6d, 0xa4, 0xeb, 0xb6, 0x73, 0x90, + 0xdc, 0xa9, 0x2b, 0x7f, 0x54, 0x4e, 0xfe, 0x13, 0x0d, 0x91, 0x57, 0x5c, 0x21, 0x56, 0x16, 0x5c, 0x62, 0x31, 0x54, + 0xa4, 0x00, 0xd7, 0x10, 0x44, 0xca, 0xa2, 0xa4, 0x70, 0xcb, 0x41, 0x55, 0x04, 0x60, 0x5c, 0xad, 0x8e, 0x3a, 0x11, + 0x3e, 0x6e, 0xad, 0x45, 0x08, 0x56, 0x34, 0x6a, 0x65, 0xad, 0xc0, 0x17, 0xa4, 0x2f, 0x1d, 0x0a, 0x62, 0x7a, 0x14, + 0x52, 0x55, 0x3a, 0x14, 0x48, 0x73, 0xa8, 0xf8, 0xc6, 0x60, 0xa3, 0xa8, 0x48, 0xcf, 0x5f, 0x9a, 0x94, 0x5c, 0x1a, + 0x33, 0x3e, 0x88, 0x32, 0x12, 0x79, 0x1d, 0xde, 0x89, 0x69, 0x81, 0x7c, 0xa3, 0xc7, 0x0f, 0x82, 0x4b, 0x78, 0x37, + 0xe4, 0x5e, 0x01, 0xb6, 0x04, 0xec, 0x00, 0xf7, 0xca, 0x8c, 0x72, 0x9d, 0xd6, 0xf5, 0x5b, 0xeb, 0xa1, 0x18, 0x86, + 0xcf, 0x2c, 0x81, 0xed, 0x68, 0x1d, 0x1d, 0xe9, 0xe1, 0xc3, 0xff, 0xba, 0xaa, 0x39, 0xea, 0x54, 0x2e, 0x67, 0xc7, + 0x13, 0x96, 0x22, 0x66, 0xd0, 0xfd, 0x75, 0xfb, 0x4a, 0x00, 0xdd, 0x2e, 0x8b, 0x79, 0x36, 0xda, 0xc9, 0xbf, 0xa5, + 0x1b, 0x2b, 0x4a, 0x9b, 0x78, 0x97, 0xf5, 0xc6, 0xfe, 0x70, 0xf4, 0x97, 0x67, 0x5f, 0x26, 0x84, 0xaa, 0xb3, 0x61, + 0x6b, 0x1d, 0xe7, 0xf2, 0xbf, 0xfe, 0x3a, 0x26, 0x2b, 0x08, 0x0a, 0xc2, 0xb2, 0x53, 0x4c, 0x54, 0x30, 0x8a, 0x14, + 0x6b, 0x3e, 0x9e, 0xac, 0x51, 0x27, 0xbc, 0xf6, 0x97, 0x5a, 0x27, 0x4c, 0x8c, 0xac, 0x54, 0xfe, 0x9a, 0x55, 0xec, + 0x4e, 0x65, 0x16, 0x90, 0x79, 0x90, 0x4f, 0xd6, 0x46, 0x83, 0xb9, 0xe2, 0xf5, 0x6c, 0x3d, 0x97, 0xca, 0x67, 0x30, + 0xe5, 0x2c, 0x07, 0x27, 0x4b, 0x61, 0xf7, 0x24, 0x50, 0xb4, 0x66, 0xe8, 0xda, 0x9f, 0x62, 0xab, 0x5e, 0xa7, 0x55, + 0x0d, 0xf0, 0x80, 0x10, 0x03, 0x43, 0xed, 0xd5, 0xc2, 0x43, 0x6b, 0x01, 0xac, 0xfd, 0x51, 0xe9, 0x07, 0xe3, 0xc9, + 0x92, 0x2f, 0x90, 0x7f, 0x39, 0x72, 0xd4, 0xee, 0xfd, 0xbe, 0x77, 0x0f, 0x52, 0x70, 0xe4, 0x5a, 0x28, 0x90, 0x08, + 0x68, 0xc1, 0x37, 0xbe, 0xf2, 0xc1, 0xb8, 0x46, 0x6d, 0x35, 0x28, 0xa8, 0x1d, 0xdd, 0xf2, 0xd8, 0xd1, 0x3b, 0xdf, + 0x9f, 0xd0, 0x57, 0x2f, 0xb4, 0x70, 0xfc, 0x95, 0x33, 0x72, 0xcd, 0x56, 0x1d, 0x72, 0x44, 0x33, 0xe9, 0x10, 0x22, + 0x56, 0x6c, 0xcd, 0xae, 0x49, 0xe5, 0xdc, 0x39, 0x64, 0xa7, 0x8f, 0x50, 0xa5, 0xd7, 0x7a, 0x7c, 0x3b, 0x51, 0xba, + 0xdb, 0xe3, 0xdd, 0xe4, 0x5b, 0x36, 0x11, 0x31, 0x18, 0xd0, 0x06, 0xe1, 0x8c, 0xac, 0x43, 0xa4, 0xd2, 0x01, 0x42, + 0xe0, 0x98, 0x80, 0xa6, 0xff, 0xf8, 0x9a, 0x44, 0x01, 0x47, 0xda, 0x08, 0x59, 0xcb, 0x0e, 0x87, 0x1c, 0x34, 0xca, + 0xcd, 0x1f, 0x5e, 0xa1, 0x4e, 0x73, 0x60, 0x9e, 0x2e, 0x61, 0xcf, 0xc1, 0x23, 0xbd, 0x38, 0x3e, 0xd2, 0xff, 0x3b, + 0x9a, 0xa8, 0xf1, 0x7f, 0xae, 0x89, 0x52, 0x5a, 0x24, 0x47, 0xb5, 0xf4, 0x4d, 0xea, 0x28, 0xb8, 0xc8, 0x3b, 0x6a, + 0x21, 0x7b, 0x96, 0x8d, 0x1b, 0xd5, 0xbc, 0xff, 0x5f, 0x2b, 0xf3, 0xff, 0x35, 0xad, 0x0c, 0x53, 0xb2, 0x63, 0xa9, + 0x66, 0x1e, 0x68, 0x15, 0xc3, 0xec, 0x67, 0x92, 0x10, 0x19, 0x2e, 0x0d, 0xf8, 0x51, 0x05, 0xfb, 0x38, 0xad, 0xd6, + 0x59, 0xb8, 0x43, 0x25, 0xea, 0xad, 0xb8, 0x4b, 0xf3, 0x97, 0xf5, 0xbf, 0x45, 0x59, 0xc0, 0xd4, 0xbe, 0x2b, 0xd3, + 0x38, 0x20, 0x0b, 0x7f, 0x16, 0x96, 0x38, 0xb9, 0xb1, 0x8d, 0x3f, 0xcb, 0xf1, 0xb4, 0x5f, 0x75, 0x66, 0x1e, 0x48, + 0xa0, 0x06, 0xe2, 0x8f, 0x9c, 0xcb, 0xca, 0xe2, 0x01, 0xa1, 0x9b, 0x7f, 0x28, 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, 0xa7, 0xb1, 0x88, 0x47, 0x3d, 0x45, 0xc9, 0xf2, 0x26, 0x77, 0xe5, 0x5c, 0x7f, + 0xff, 0x07, 0x05, 0xb0, 0x1b, 0x30, 0xdb, 0x16, 0xd8, 0x01, 0x40, 0x82, 0x02, 0xd9, 0x42, 0x9d, 0x46, 0x67, 0x6a, + 0xa9, 0xc0, 0x7b, 0xae, 0x07, 0xf8, 0x9b, 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, 0xb7, 0x53, 0x45, 0x1e, 0x1f, 0xa5, 0x21, 0xaf, + 0xc0, 0x93, 0x8c, 0x23, 0x49, 0x94, 0x08, 0xde, 0xe4, 0x8d, 0x19, 0x87, 0x97, 0x6d, 0xca, 0xa9, 0xbd, 0x59, 0x2f, + 0x00, 0xe7, 0x09, 0xda, 0x32, 0xc0, 0x58, 0xc0, 0xe0, 0x5c, 0x88, 0x25, 0x4f, 0x11, 0xfc, 0xd2, 0x89, 0x14, 0xc6, + 0x5d, 0x0e, 0xc3, 0x3c, 0x28, 0x7a, 0x97, 0xd4, 0x1f, 0xfd, 0x3e, 0x6a, 0x93, 0xc1, 0x10, 0x54, 0x02, 0xa8, 0xac, + 0x1b, 0x24, 0x06, 0x56, 0xa5, 0x85, 0xc4, 0x25, 0xc4, 0xcb, 0x7c, 0x35, 0xad, 0xa3, 0xe0, 0x7d, 0x3d, 0x21, 0x84, + 0x13, 0x8c, 0x0f, 0x71, 0x03, 0x04, 0x0c, 0x56, 0x71, 0x81, 0x41, 0xf2, 0x5c, 0xa2, 0xfb, 0xe3, 0xf9, 0x8e, 0x01, + 0xae, 0x9c, 0xf7, 0x54, 0xbb, 0x7a, 0x60, 0x2f, 0x57, 0xe9, 0x92, 0x11, 0xc2, 0x8a, 0xff, 0x8b, 0xc8, 0xfb, 0x76, + 0x98, 0x80, 0xda, 0x46, 0xfe, 0x18, 0x24, 0xe6, 0x32, 0x51, 0x04, 0xf1, 0x28, 0x2b, 0x58, 0x92, 0x06, 0x9b, 0x51, + 0x92, 0x82, 0x46, 0x13, 0x63, 0xc8, 0x54, 0x68, 0x87, 0xa4, 0xd1, 0x6c, 0x4c, 0xf6, 0x31, 0xe4, 0x35, 0x5c, 0x2c, + 0x16, 0x78, 0xdf, 0xcf, 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, 0xcb, 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, 0x86, 0xd2, 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, 0xb3, 0xac, 0xc9, 0x5c, 0xbc, 0x2e, 0x1e, 0xbc, + 0x82, 0x3d, 0xf7, 0x07, 0xfa, 0x57, 0xc9, 0x9e, 0xfb, 0x36, 0x93, 0xeb, 0x9f, 0x69, 0xd7, 0x68, 0xcc, 0x74, 0xbc, + 0x76, 0x05, 0x56, 0x68, 0x80, 0xfc, 0x82, 0x1d, 0xed, 0x6d, 0x0e, 0x02, 0x01, 0xba, 0x97, 0xe0, 0x28, 0x0a, 0x88, + 0x9a, 0x56, 0x95, 0x47, 0xa7, 0x7b, 0x7f, 0x8f, 0x6f, 0x94, 0x80, 0x4d, 0x9e, 0x5a, 0xf7, 0x96, 0xb1, 0x7f, 0x38, + 0x40, 0x08, 0xbd, 0x9c, 0x7e, 0xa3, 0x2d, 0xab, 0x47, 0x3b, 0x96, 0xfb, 0x86, 0x51, 0x4f, 0xc1, 0x18, 0x86, 0x2e, + 0xac, 0x62, 0x24, 0xcf, 0x80, 0xac, 0xf1, 0x1b, 0x44, 0x17, 0xb0, 0xe8, 0xf5, 0x5e, 0x1f, 0xd1, 0x20, 0x02, 0x2a, + 0xbd, 0xe6, 0x2f, 0x45, 0x3e, 0x57, 0x85, 0xe8, 0xbd, 0xb7, 0x76, 0xde, 0xcc, 0x48, 0x96, 0x49, 0x23, 0xd5, 0x6e, + 0x65, 0xb1, 0xae, 0xbc, 0xd9, 0x09, 0xe9, 0x62, 0x8e, 0xa1, 0x32, 0x78, 0x1c, 0x80, 0xd2, 0xf3, 0x6f, 0xa1, 0x57, + 0x32, 0x64, 0x9a, 0x25, 0x9a, 0xd9, 0x5d, 0xe3, 0x4f, 0x56, 0xa9, 0x17, 0x23, 0x62, 0x36, 0xb0, 0x85, 0xb8, 0x2d, + 0x2a, 0xdd, 0x16, 0x85, 0xb2, 0x45, 0x91, 0x3e, 0xd4, 0xce, 0x74, 0x67, 0x16, 0x3e, 0xab, 0x4c, 0xfb, 0xde, 0x66, + 0x66, 0x6c, 0x80, 0xb6, 0x8b, 0xf0, 0x0d, 0x74, 0xa0, 0x42, 0xc8, 0x7f, 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, 0x5f, 0x53, + 0xb7, 0x67, 0xe5, 0x64, 0x2f, 0x3a, 0x27, 0xfb, 0x74, 0x36, 0x0f, 0x04, 0x97, 0x3b, 0xf7, 0x79, 0x3e, 0xd5, 0xd3, + 0xae, 0xf2, 0x83, 0xd6, 0x10, 0x99, 0x2f, 0x7c, 0xaa, 0xba, 0xd7, 0x15, 0x2c, 0x60, 0x09, 0xee, 0xd6, 0x4b, 0xf3, + 0x5f, 0xb1, 0xfb, 0x7b, 0x41, 0x2f, 0xcd, 0x7f, 0xa3, 0x3f, 0x29, 0x80, 0x03, 0xd0, 0x98, 0xda, 0x2d, 0xf0, 0x10, + 0x43, 0x05, 0x85, 0xbb, 0x59, 0x39, 0xf7, 0x6a, 0x80, 0xc3, 0x24, 0x7d, 0x43, 0xab, 0x57, 0x5a, 0xec, 0x7a, 0x99, + 0xec, 0x15, 0xe0, 0xa1, 0x0a, 0x79, 0x78, 0x38, 0x44, 0x1d, 0xc3, 0x0e, 0xea, 0x08, 0x18, 0xf6, 0x10, 0x1a, 0x5b, + 0xe0, 0xf9, 0xf8, 0x29, 0xe3, 0x7b, 0x01, 0x6a, 0x23, 0x84, 0xc7, 0xab, 0x45, 0x19, 0x62, 0xcb, 0xde, 0x22, 0x95, + 0xd4, 0xcf, 0x02, 0x51, 0x46, 0xab, 0x80, 0xb6, 0xda, 0x63, 0x96, 0xc6, 0x1b, 0x08, 0x15, 0x4b, 0x7d, 0x0c, 0xa1, + 0x81, 0xc3, 0xef, 0x70, 0x00, 0x09, 0xbe, 0xe4, 0x9a, 0x6c, 0xee, 0x6d, 0x7e, 0x4f, 0xfb, 0xfc, 0xe1, 0x70, 0x7e, + 0x89, 0xa0, 0x74, 0x29, 0x7c, 0xa4, 0x12, 0x51, 0x3d, 0xc5, 0x4d, 0x09, 0xd9, 0x2c, 0x59, 0xe9, 0x07, 0xbf, 0xaa, + 0x5f, 0x00, 0x20, 0x0b, 0x81, 0x36, 0x91, 0xd9, 0x9f, 0xce, 0x54, 0x74, 0x01, 0x70, 0x88, 0x3f, 0x7e, 0x82, 0xe8, + 0x1b, 0x5a, 0xa6, 0xe5, 0xe3, 0x84, 0x87, 0xa0, 0xb5, 0x25, 0x9d, 0x44, 0xac, 0x14, 0xd8, 0x10, 0x09, 0xdf, 0xef, + 0x9f, 0xc7, 0x92, 0x0e, 0x34, 0x6a, 0x75, 0x6f, 0xdc, 0xea, 0x5e, 0xf9, 0xba, 0xee, 0xe4, 0xc6, 0x07, 0x45, 0xfb, + 0x6c, 0xde, 0xa8, 0x7c, 0xdf, 0xd6, 0x39, 0xbb, 0xd3, 0xbd, 0x23, 0xe7, 0xc4, 0xb7, 0xf7, 0x10, 0x8a, 0x1e, 0x9a, + 0x22, 0xcb, 0x92, 0x30, 0xa0, 0xb5, 0x76, 0xed, 0x59, 0x46, 0x07, 0xaf, 0x7d, 0x43, 0x88, 0xc8, 0x53, 0x7c, 0x12, + 0x72, 0x8b, 0xe3, 0x83, 0x02, 0xfd, 0x33, 0xe3, 0xcf, 0x9c, 0xf8, 0x61, 0xab, 0x5f, 0x00, 0xe7, 0xa6, 0x7b, 0xef, + 0x4e, 0xcc, 0x7a, 0x0c, 0xa5, 0x6c, 0xfc, 0xdf, 0xef, 0x13, 0x59, 0xa0, 0xd3, 0x11, 0x0d, 0x03, 0xc1, 0x5d, 0x54, + 0xff, 0xf7, 0x8a, 0xd7, 0x3d, 0x6b, 0x75, 0xbe, 0xfc, 0xd4, 0xe9, 0x49, 0xaf, 0x5e, 0xc6, 0x3d, 0xa0, 0x42, 0x07, + 0x08, 0xe7, 0x75, 0xbf, 0x61, 0xbb, 0x6f, 0x7e, 0x79, 0x77, 0xf4, 0x32, 0xb0, 0x49, 0x91, 0xd8, 0x56, 0xf2, 0x59, + 0x0f, 0x14, 0x7e, 0x3d, 0xd6, 0xab, 0x8b, 0x75, 0x8f, 0xf5, 0x50, 0x0b, 0x88, 0x1e, 0x16, 0xa0, 0xfe, 0xeb, 0xd9, + 0xa7, 0xa1, 0x70, 0x90, 0x8d, 0x53, 0x05, 0x8a, 0x2c, 0xf8, 0x0b, 0x31, 0x5a, 0x17, 0x04, 0x88, 0x6c, 0x09, 0x69, + 0xd5, 0xc9, 0xec, 0x71, 0xa9, 0x25, 0x19, 0x7c, 0x13, 0x90, 0xd9, 0x81, 0x95, 0x13, 0x94, 0x8e, 0x5b, 0x03, 0xae, + 0x6c, 0xf1, 0x68, 0xb7, 0x3f, 0x0d, 0xb2, 0xb3, 0xe6, 0xa4, 0xd1, 0x3e, 0xec, 0xd3, 0x3c, 0x40, 0x20, 0x92, 0xa9, + 0x08, 0x72, 0xcd, 0xbd, 0x25, 0x7d, 0x74, 0x38, 0xe7, 0x85, 0xfc, 0x73, 0x2a, 0x75, 0x88, 0x43, 0x89, 0x35, 0x10, + 0xa8, 0x3c, 0x43, 0x95, 0xc3, 0x06, 0x39, 0xfe, 0xd9, 0x91, 0xcc, 0x24, 0x26, 0x8b, 0xdc, 0xad, 0x99, 0x0a, 0x3f, + 0x10, 0x7c, 0xcc, 0x72, 0x0e, 0x5c, 0x60, 0xb3, 0xb9, 0xaf, 0xa6, 0xb8, 0xb8, 0x02, 0x7f, 0x4c, 0xe1, 0x57, 0x3c, + 0x85, 0x9d, 0x76, 0xbf, 0x2e, 0xaa, 0x14, 0x75, 0x1b, 0x85, 0x45, 0x25, 0x0b, 0xa6, 0x35, 0xa4, 0x89, 0x0e, 0xa3, + 0x3f, 0xc8, 0x19, 0x28, 0x08, 0xf9, 0x65, 0xd3, 0x00, 0x23, 0x95, 0x5c, 0x1e, 0x54, 0x49, 0xe0, 0x05, 0xd8, 0x06, + 0x15, 0x5b, 0x17, 0x10, 0x64, 0x9b, 0x14, 0x65, 0xfa, 0xa5, 0xc8, 0xeb, 0x30, 0x0b, 0xaa, 0x51, 0x5a, 0xfd, 0xa8, + 0x7f, 0x02, 0xf3, 0x36, 0x15, 0xa3, 0x5a, 0xc5, 0xe4, 0x37, 0xfa, 0xfd, 0x62, 0xd0, 0xfa, 0x90, 0xc1, 0x47, 0xaf, + 0x4d, 0x83, 0x3f, 0x3a, 0x0d, 0x76, 0x98, 0x68, 0x04, 0x40, 0x32, 0xa7, 0x96, 0x3c, 0x14, 0xfd, 0x11, 0xe4, 0x58, + 0xa3, 0xca, 0x29, 0x18, 0xac, 0xff, 0x78, 0xb4, 0x03, 0x53, 0x2f, 0x8e, 0xb6, 0x64, 0x07, 0xad, 0x7c, 0x03, 0xdc, + 0xaf, 0x91, 0x2d, 0x66, 0x39, 0x40, 0xb3, 0xd7, 0x88, 0x8c, 0x4f, 0x5e, 0x00, 0x63, 0xb6, 0xce, 0xc2, 0x48, 0xc4, + 0xc1, 0x58, 0x35, 0x66, 0xcc, 0xc0, 0xc0, 0x05, 0xba, 0x96, 0x49, 0x49, 0x1a, 0xd2, 0xc1, 0x80, 0x95, 0xb2, 0x85, + 0x03, 0x5e, 0x34, 0xc7, 0xed, 0x78, 0xd3, 0xa2, 0xf1, 0xc0, 0x76, 0xb1, 0xfd, 0xfd, 0xf7, 0xc5, 0xf6, 0x3a, 0xdc, + 0x92, 0x5e, 0x21, 0x67, 0x09, 0xfd, 0xfc, 0x51, 0xf6, 0x59, 0xc3, 0xc9, 0xa9, 0xd0, 0x0c, 0x2d, 0x45, 0x42, 0x29, + 0xde, 0xe9, 0x49, 0x81, 0xb1, 0x8c, 0x85, 0xbf, 0x07, 0xce, 0xe9, 0x42, 0x11, 0xb9, 0x03, 0xc7, 0xf1, 0x0d, 0x54, + 0x30, 0x6a, 0x38, 0x78, 0x19, 0xc3, 0xb6, 0x28, 0x66, 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, + 0xe5, 0x41, 0x04, 0x90, 0xcf, 0xe1, 0x7d, 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, 0x8b, 0x33, 0xd8, 0x38, + 0xd7, 0x99, 0xe0, 0xc0, 0x8b, 0xa4, 0xd6, 0x6b, 0xc6, 0x5f, 0x64, 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, 0xfe, 0x5c, 0x49, 0x1c, 0x5a, 0x16, 0xc9, 0xbf, 0x77, 0x3d, + 0x7d, 0x85, 0xd4, 0x9d, 0x2c, 0x90, 0x19, 0xe3, 0x65, 0x1e, 0x7f, 0x02, 0xc2, 0x6c, 0xd0, 0x46, 0x45, 0x21, 0x84, + 0x6c, 0x10, 0x83, 0xc6, 0xcb, 0x3c, 0xfe, 0x5e, 0xd1, 0x78, 0xc8, 0x47, 0x91, 0xaf, 0xfe, 0x2a, 0xf5, 0x5f, 0xa1, + 0xcf, 0x4c, 0xf0, 0x08, 0xd5, 0x44, 0xff, 0xee, 0xf9, 0xec, 0x1e, 0xd4, 0x86, 0x51, 0x98, 0x99, 0xf2, 0x2b, 0xdf, + 0x14, 0x67, 0xaf, 0xbf, 0xa2, 0xab, 0x6c, 0xeb, 0x7e, 0xf4, 0xf1, 0x88, 0xc0, 0xda, 0x18, 0x5d, 0x71, 0x63, 0x00, + 0x39, 0x4c, 0xde, 0xaf, 0x28, 0x2d, 0x87, 0x34, 0x08, 0x1d, 0x34, 0x04, 0xbd, 0x92, 0xe8, 0x03, 0x89, 0x45, 0x8c, + 0xe1, 0x85, 0x78, 0x46, 0x6a, 0x32, 0xd1, 0x10, 0xaf, 0x88, 0xfd, 0x10, 0x2d, 0x39, 0x35, 0xd1, 0x8d, 0x30, 0xc5, + 0x40, 0x62, 0x67, 0x90, 0x9c, 0x24, 0xb5, 0xf2, 0x8b, 0x67, 0x92, 0xb0, 0xc4, 0xce, 0x43, 0x0c, 0x26, 0xb5, 0x74, + 0xa7, 0x37, 0x55, 0x7a, 0x77, 0xa4, 0xe5, 0xa0, 0x7d, 0x00, 0x76, 0x29, 0xe9, 0xfd, 0x93, 0x42, 0x11, 0x1f, 0xc2, + 0x38, 0x86, 0xf0, 0x2d, 0xa2, 0xba, 0x02, 0xe7, 0x5a, 0x81, 0xc6, 0x6a, 0xe0, 0xa1, 0x99, 0x55, 0xf3, 0x21, 0xa7, + 0x9f, 0x4a, 0xcb, 0x1f, 0x23, 0x1a, 0x1b, 0xad, 0x9b, 0xc3, 0x61, 0x4f, 0xab, 0x5e, 0x3a, 0x07, 0x5d, 0x36, 0x93, + 0x98, 0xb8, 0x81, 0x74, 0xfd, 0xe8, 0x37, 0x13, 0xf6, 0x22, 0x2a, 0xe4, 0x52, 0x08, 0x0a, 0x5a, 0x1d, 0x08, 0x1c, + 0x0a, 0x6f, 0x51, 0xe6, 0x8b, 0x98, 0x36, 0x10, 0x06, 0x9f, 0x1f, 0xc8, 0xcf, 0x37, 0x05, 0xa9, 0xd8, 0xb1, 0xae, + 0xfd, 0xfe, 0xa6, 0xf4, 0x00, 0x4f, 0xce, 0x24, 0x79, 0xda, 0x0c, 0x61, 0x45, 0x00, 0x8d, 0x59, 0x4d, 0x16, 0x27, + 0x5c, 0x99, 0xc3, 0x8f, 0x95, 0x57, 0xb2, 0x94, 0xa9, 0xf3, 0x54, 0x2f, 0x80, 0xa8, 0xe3, 0x0d, 0x5a, 0x91, 0xfa, + 0x15, 0x3a, 0x7b, 0xcd, 0x4a, 0xc8, 0x78, 0x78, 0xce, 0x79, 0x3a, 0x7a, 0x60, 0x09, 0x8f, 0xf0, 0xaf, 0x64, 0xa2, + 0x0f, 0xbf, 0x07, 0x0e, 0x37, 0xe3, 0x84, 0x47, 0x6e, 0xb3, 0xf7, 0x55, 0xb8, 0x82, 0x9b, 0x69, 0x01, 0x48, 0x6e, + 0x41, 0xd2, 0x04, 0x94, 0x90, 0xc8, 0x84, 0xcc, 0x9a, 0x92, 0x9f, 0x5b, 0xda, 0x06, 0x6b, 0x98, 0x74, 0x1e, 0xf0, + 0xa2, 0xd5, 0x47, 0xab, 0x89, 0x76, 0x99, 0xe5, 0xf3, 0x21, 0xce, 0x50, 0xcd, 0x71, 0x77, 0x06, 0x3f, 0x07, 0xbc, + 0x62, 0x55, 0x93, 0x8e, 0x76, 0x03, 0x2e, 0x3c, 0xb9, 0xce, 0xd3, 0xd1, 0x16, 0x7f, 0xc9, 0xfd, 0x01, 0xa0, 0x83, + 0xa9, 0x4b, 0xe0, 0x4f, 0xd5, 0x56, 0x53, 0xa9, 0x5f, 0x5a, 0xfb, 0x75, 0xdd, 0x59, 0xad, 0xdc, 0xb3, 0x2e, 0x43, + 0x7b, 0x64, 0xc8, 0x19, 0x33, 0xe0, 0xcf, 0x19, 0x4b, 0xfe, 0x9c, 0xb1, 0xe2, 0xcf, 0x19, 0x37, 0x46, 0x06, 0x50, + 0x82, 0x7b, 0xc9, 0x5f, 0xec, 0x11, 0x33, 0xc4, 0x6a, 0x50, 0x09, 0xac, 0x2c, 0xe5, 0xdc, 0x47, 0x4e, 0x31, 0xe5, + 0x94, 0xe1, 0xa5, 0xd3, 0x99, 0x3b, 0x90, 0xf3, 0x60, 0xe6, 0x0e, 0x93, 0xb3, 0x3e, 0xc5, 0xb1, 0x34, 0x26, 0x45, 0x05, 0xe9, 0x9c, 0x0e, 0x37, 0xaf, 0x8e, 0xf3, 0x84, 0x65, 0x7c, 0xdc, 0x3e, 0x53, 0x20, 0xc4, 0x16, 0xcf, 0x90, - 0x48, 0xa9, 0x9a, 0xe5, 0x36, 0x7f, 0x3c, 0xd6, 0xa3, 0x07, 0xbd, 0xd3, 0xc3, 0xaf, 0x84, 0xfd, 0x92, 0x79, 0xf6, - 0x09, 0x02, 0x98, 0x24, 0xf2, 0x4c, 0xc2, 0xd1, 0x8f, 0xe5, 0xe8, 0x6f, 0x1b, 0xfe, 0x25, 0x43, 0x75, 0x77, 0x08, - 0x4c, 0x6c, 0xd9, 0x91, 0x43, 0x70, 0xba, 0xaa, 0x44, 0x02, 0x0e, 0x36, 0x5b, 0x16, 0xe9, 0x3d, 0x1e, 0xe2, 0x7c, - 0x50, 0xf8, 0x08, 0x0d, 0x33, 0x7a, 0xbf, 0xbf, 0x15, 0x5e, 0x2e, 0x5b, 0x79, 0x3c, 0x26, 0xd6, 0x5d, 0xd8, 0xd1, - 0xc7, 0xd1, 0x1e, 0x25, 0xd4, 0x7e, 0x54, 0xeb, 0x4d, 0xa5, 0x1e, 0x54, 0x66, 0x17, 0x12, 0x83, 0x9c, 0xa5, 0xfa, - 0xf4, 0x4a, 0xf5, 0xa1, 0x66, 0x9d, 0xdf, 0xf9, 0x69, 0x9f, 0x8a, 0xd1, 0x46, 0x4e, 0x08, 0x70, 0x1d, 0x24, 0x1a, - 0x1d, 0x00, 0xe3, 0x6c, 0xb3, 0xe5, 0xa5, 0xb6, 0x4e, 0x94, 0x8e, 0xe3, 0x4a, 0x1f, 0xc7, 0xc7, 0xa3, 0x14, 0x33, - 0xae, 0x4f, 0xc4, 0x8c, 0xeb, 0x06, 0xe0, 0xcd, 0x3a, 0x0f, 0xea, 0xe3, 0xf1, 0x9a, 0x2e, 0x45, 0xa6, 0xb3, 0x8d, - 0xf2, 0xb3, 0x1e, 0x3d, 0x3c, 0x4d, 0xd0, 0xdc, 0x5b, 0x61, 0xef, 0x45, 0xb2, 0x3d, 0x93, 0x4d, 0xea, 0x65, 0xe4, - 0xd3, 0x0b, 0xf7, 0xec, 0x92, 0xab, 0x1f, 0x56, 0x5f, 0x4f, 0x7f, 0x15, 0x5e, 0xc4, 0x72, 0xda, 0xad, 0x4b, 0x26, - 0xec, 0x2d, 0x25, 0x97, 0x56, 0x79, 0xf9, 0x74, 0xeb, 0x07, 0x98, 0x99, 0xf6, 0xf4, 0x41, 0x36, 0xa2, 0xfa, 0xb3, + 0x48, 0xa9, 0x9a, 0xe5, 0x36, 0x7f, 0x38, 0xd4, 0xa3, 0x07, 0xbd, 0xd3, 0xc3, 0xaf, 0x84, 0xfd, 0x92, 0x79, 0xf6, + 0x09, 0x02, 0x98, 0x24, 0xf2, 0x4c, 0xc2, 0xd1, 0x8f, 0xe5, 0xe8, 0x6f, 0x1a, 0xfe, 0x2e, 0x43, 0x75, 0x77, 0x08, + 0x4c, 0x6c, 0xd9, 0x81, 0x43, 0x70, 0xba, 0xaa, 0x44, 0x02, 0x0e, 0x36, 0x1b, 0x16, 0xe9, 0x3d, 0x1e, 0xe2, 0x7c, + 0x50, 0xf8, 0x08, 0x0d, 0x33, 0x7a, 0xbf, 0xbf, 0x11, 0x5e, 0x25, 0x5b, 0x79, 0x38, 0x24, 0xd6, 0x5d, 0xd8, 0xd1, + 0xc7, 0xd1, 0x1e, 0x25, 0xd4, 0x7e, 0x54, 0xeb, 0x4d, 0xa5, 0x1e, 0xe4, 0x66, 0x17, 0x12, 0x83, 0x8a, 0xa5, 0xfa, + 0xf4, 0x4a, 0xf5, 0xa1, 0x66, 0x9d, 0xdf, 0xd5, 0x71, 0x9f, 0x8a, 0xd1, 0x5a, 0x4e, 0x08, 0x70, 0x1d, 0x24, 0x1a, + 0x1d, 0x00, 0xe3, 0x6c, 0xb3, 0xe5, 0xa5, 0xb6, 0x4e, 0x94, 0x8e, 0xe3, 0x5c, 0x1f, 0xc7, 0x87, 0x83, 0x14, 0x33, + 0x2e, 0x8f, 0xc4, 0x8c, 0xcb, 0x06, 0xe0, 0xcd, 0x3a, 0x0f, 0xea, 0xc3, 0xe1, 0x92, 0x2e, 0x45, 0xa6, 0xb3, 0x8d, + 0xf2, 0xb3, 0x1e, 0x3d, 0x3c, 0x4b, 0xd0, 0xdc, 0x5b, 0x61, 0xef, 0x45, 0xb2, 0x3d, 0x93, 0x75, 0xea, 0x65, 0xe4, + 0xd3, 0x0b, 0xf7, 0xec, 0x92, 0xab, 0x1f, 0x56, 0x5f, 0x4f, 0x7f, 0x15, 0x5e, 0xc4, 0x2a, 0xda, 0xad, 0x4b, 0x26, + 0xec, 0x2d, 0xa5, 0x92, 0x56, 0x79, 0xf9, 0x74, 0xe3, 0x07, 0x98, 0x99, 0xf6, 0xf4, 0x41, 0x36, 0xa2, 0xfa, 0xb3, 0x12, 0xb5, 0x32, 0x4c, 0x16, 0xce, 0x4b, 0xa6, 0x9e, 0x0c, 0x78, 0xcc, 0x4a, 0x1e, 0xc9, 0x4e, 0x6f, 0x0c, 0x82, - 0x00, 0xd6, 0x39, 0x69, 0xd5, 0x19, 0x47, 0xa3, 0x55, 0xe5, 0xe2, 0x7c, 0x95, 0x0b, 0x0c, 0xb7, 0xdb, 0xb0, 0xad, - 0xaa, 0xb3, 0xdc, 0xd4, 0x72, 0xe5, 0x3b, 0x80, 0x8f, 0x65, 0x95, 0x0b, 0x3a, 0xa6, 0x4c, 0x9d, 0xb7, 0x10, 0x8c, - 0xad, 0x6a, 0x5c, 0x38, 0x35, 0x2e, 0x78, 0x44, 0xed, 0x6e, 0x9a, 0x7a, 0xb4, 0x03, 0x96, 0xd2, 0xd1, 0x9e, 0x97, - 0xa8, 0x52, 0xf8, 0x9b, 0xe0, 0x87, 0x30, 0x8e, 0x7f, 0x28, 0x76, 0xea, 0x40, 0xbc, 0x2b, 0x76, 0x48, 0xfb, 0x22, + 0x00, 0xd6, 0x39, 0x69, 0xd5, 0x19, 0x47, 0xa3, 0x55, 0xe5, 0xe2, 0x74, 0x95, 0x0b, 0x0c, 0xb7, 0x5b, 0xb3, 0x8d, + 0xaa, 0xb3, 0xdc, 0xd4, 0x2a, 0xe5, 0x3b, 0x80, 0x8f, 0x65, 0x95, 0x0b, 0x3a, 0xa6, 0x4c, 0x9d, 0x37, 0x10, 0x8c, + 0xad, 0x6a, 0x5c, 0x38, 0x35, 0x2e, 0x78, 0x44, 0xed, 0x6e, 0x9a, 0x7a, 0xb4, 0x05, 0x96, 0xd2, 0xd1, 0x8e, 0x97, + 0xa8, 0x52, 0xf8, 0xbb, 0xe0, 0xfb, 0x30, 0x8e, 0xbf, 0x2f, 0xb6, 0xea, 0x40, 0xbc, 0x2d, 0xb6, 0x48, 0xfb, 0x22, 0xff, 0x42, 0x1c, 0xf0, 0x5a, 0xd7, 0x94, 0xd7, 0xd6, 0x9c, 0x06, 0xb6, 0x86, 0x91, 0x92, 0xc2, 0xb9, 0xf9, 0xf3, - 0x78, 0xa4, 0x95, 0x5d, 0xab, 0xbb, 0x42, 0xad, 0xc7, 0x1c, 0x36, 0xec, 0x45, 0x16, 0xee, 0x45, 0x09, 0x7e, 0x13, - 0xf2, 0xaf, 0xe3, 0x51, 0xab, 0x2c, 0xd5, 0x91, 0x3e, 0x3b, 0x7c, 0x09, 0xc6, 0x0c, 0x5d, 0x9a, 0x80, 0x65, 0x63, + 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, 0x09, 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, 0xd7, 0x13, 0x71, 0x49, 0x97, 0x24, 0xf5, 0x54, 0x42, - 0x49, 0x08, 0x76, 0xed, 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, 0xcb, - 0x79, 0x58, 0x1b, 0x26, 0xb9, 0x51, 0x16, 0xee, 0x8b, 0x6d, 0xad, 0x96, 0xa7, 0xe3, 0x30, 0x02, 0x33, 0x82, 0x02, - 0x64, 0x5d, 0xb7, 0x11, 0x31, 0xcc, 0xe5, 0x32, 0x21, 0x9f, 0x10, 0x90, 0x45, 0xa9, 0x71, 0x3e, 0x6e, 0x81, 0x4a, - 0x04, 0x83, 0xd3, 0xd0, 0x5a, 0x75, 0x93, 0xbf, 0xaa, 0x6c, 0x6c, 0x05, 0xe4, 0x90, 0x64, 0xb2, 0x58, 0x8d, 0xee, - 0xc4, 0xb2, 0x28, 0xc5, 0xcf, 0x58, 0x0f, 0xd7, 0x6c, 0xe1, 0x3e, 0x03, 0x42, 0xfb, 0x89, 0xd2, 0xde, 0x44, 0x9a, - 0xa0, 0x7b, 0xc5, 0xd6, 0x00, 0x32, 0x80, 0xa2, 0xae, 0x76, 0xeb, 0x73, 0x7e, 0x8e, 0xa4, 0x19, 0x0e, 0xa3, 0xdb, - 0xa7, 0xab, 0x60, 0x35, 0xb8, 0x46, 0xad, 0xf4, 0x35, 0x8b, 0x5b, 0x18, 0x54, 0x07, 0xb3, 0x84, 0x83, 0x9a, 0x59, - 0x6b, 0x23, 0x10, 0x4c, 0xf6, 0x50, 0x90, 0x33, 0x57, 0xb0, 0x0f, 0x0a, 0xd6, 0x92, 0xd7, 0xc1, 0xe1, 0xd6, 0xbe, - 0xac, 0x14, 0x57, 0xcf, 0xae, 0x92, 0xd6, 0x85, 0xa5, 0xbc, 0x7a, 0xd6, 0x80, 0xc1, 0xe5, 0x04, 0x9b, 0x2a, 0xf7, - 0x27, 0x5b, 0x00, 0xdd, 0x0a, 0x29, 0xe2, 0x45, 0x29, 0x6c, 0x5b, 0xf9, 0xcc, 0x09, 0x1b, 0x6c, 0xd9, 0x03, 0xdc, - 0x2b, 0x83, 0x92, 0xc1, 0x85, 0x18, 0xb7, 0x9b, 0x7d, 0x80, 0x2b, 0x18, 0x0a, 0x63, 0x1b, 0xfe, 0x3a, 0xf3, 0x22, - 0x25, 0xe0, 0x66, 0x88, 0xf2, 0xb5, 0x85, 0x93, 0x49, 0x4f, 0xae, 0x25, 0x8b, 0x01, 0x0b, 0x1a, 0x7c, 0x47, 0xad, - 0xbf, 0x33, 0xf9, 0x37, 0x9e, 0x1e, 0xfa, 0xc1, 0xe7, 0xcc, 0x5b, 0xfa, 0xec, 0x75, 0x2e, 0xa3, 0x35, 0x49, 0x94, - 0x57, 0x0f, 0x97, 0x20, 0x37, 0x2c, 0x47, 0x0f, 0x6c, 0x09, 0xe2, 0xc4, 0x72, 0x94, 0x50, 0x46, 0x57, 0xb8, 0x57, - 0x99, 0x2d, 0x13, 0x81, 0x14, 0x07, 0x96, 0x52, 0xee, 0x2d, 0x36, 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, 0xa1, - 0x61, 0x7f, 0xf5, 0x42, 0xcb, 0xfe, 0xb0, 0xd2, 0x9a, 0x86, 0x35, 0x5f, 0xc1, 0xb4, 0x98, 0xb8, 0x7d, 0xb9, 0xb6, - 0xab, 0xe2, 0xb3, 0xb5, 0x3a, 0xbb, 0xa9, 0x21, 0x09, 0xfb, 0x8a, 0xac, 0x02, 0x1c, 0xac, 0x8a, 0xb8, 0x67, 0x59, - 0x1e, 0xc2, 0xe8, 0xcf, 0x6d, 0x5a, 0x0a, 0x0b, 0x55, 0xd2, 0x3f, 0x34, 0xa5, 0x40, 0x2a, 0x13, 0x9d, 0x68, 0x21, - 0xb8, 0x02, 0x83, 0xc0, 0xbd, 0xc8, 0x6b, 0x00, 0x8c, 0x01, 0x97, 0x02, 0x65, 0xd9, 0x96, 0x10, 0x52, 0xdd, 0xcf, - 0x40, 0x6d, 0x27, 0xee, 0xd3, 0x88, 0xac, 0x85, 0xe8, 0xab, 0x60, 0xcc, 0x9c, 0xd7, 0xd2, 0x2d, 0x36, 0x5d, 0x6f, - 0xd7, 0xb7, 0xe8, 0x5c, 0xda, 0x72, 0xf3, 0x13, 0xb6, 0x58, 0x2b, 0x50, 0x36, 0x21, 0x69, 0xbb, 0xe2, 0x15, 0xca, - 0x26, 0xb4, 0xb4, 0x0f, 0xd4, 0xa3, 0x42, 0x75, 0xb2, 0xf5, 0x52, 0x3e, 0xb5, 0x08, 0xab, 0xc5, 0x55, 0xee, 0x07, - 0xa0, 0x9b, 0x4a, 0xab, 0x17, 0x75, 0x8d, 0xa6, 0x50, 0xab, 0x85, 0xe3, 0x46, 0x3b, 0x9b, 0x2e, 0xd3, 0x15, 0xe2, - 0xac, 0x4a, 0x3b, 0xf4, 0x0f, 0x99, 0x76, 0xbd, 0xec, 0xe8, 0x37, 0xe3, 0xea, 0x02, 0x17, 0x62, 0x03, 0x3e, 0xe7, - 0xfe, 0xf2, 0x7a, 0xcf, 0xe2, 0x1e, 0x44, 0x3c, 0x03, 0x7b, 0x52, 0xfb, 0x43, 0xf5, 0xa9, 0x2b, 0x18, 0xb2, 0x30, - 0x4a, 0xfd, 0x45, 0xca, 0x7b, 0x4f, 0x70, 0xdc, 0x3f, 0x57, 0x3d, 0xf6, 0xd7, 0x8c, 0x1f, 0xea, 0x62, 0x1b, 0x25, - 0x14, 0xd5, 0xd0, 0x5b, 0x17, 0xdb, 0x4a, 0xc4, 0xc5, 0x43, 0xde, 0x63, 0x98, 0x0c, 0x63, 0x21, 0x53, 0xe1, 0x4f, - 0x99, 0x0a, 0x1e, 0x21, 0x94, 0xb8, 0xdd, 0xf4, 0x48, 0xbb, 0x09, 0x71, 0x4a, 0xb5, 0x28, 0x65, 0x32, 0xfe, 0xad, - 0x9f, 0x40, 0x79, 0x4e, 0xd1, 0x32, 0xfd, 0xa4, 0x70, 0x99, 0xbe, 0xdd, 0x9c, 0x96, 0x9e, 0x89, 0x50, 0x67, 0x2e, - 0xb6, 0xb5, 0x4e, 0xc7, 0xd8, 0x29, 0x9d, 0xda, 0xb0, 0x77, 0xb9, 0xe2, 0xb2, 0xa2, 0xf0, 0x6f, 0x24, 0xb2, 0xea, - 0x19, 0x71, 0xfc, 0x9f, 0x59, 0xfb, 0x0c, 0xab, 0xc0, 0x2f, 0x03, 0x79, 0xbf, 0x00, 0xf8, 0xb8, 0xae, 0xcb, 0xf4, - 0x6e, 0x0b, 0xb4, 0x21, 0x34, 0xfc, 0x3d, 0x1f, 0x19, 0x30, 0xdd, 0x47, 0x38, 0x43, 0x7a, 0xa8, 0x73, 0x4e, 0x67, - 0x65, 0x3a, 0xe7, 0x2a, 0xac, 0x25, 0x38, 0xc8, 0x49, 0x53, 0xc9, 0x75, 0x09, 0x6a, 0x26, 0x70, 0xfb, 0xd0, 0x1e, - 0x11, 0x42, 0x6d, 0xca, 0x6a, 0x7a, 0x09, 0x35, 0xef, 0xe4, 0xb4, 0xa3, 0x49, 0x09, 0xae, 0x1a, 0x3a, 0x2b, 0xd7, - 0x7f, 0x1d, 0x8f, 0xbd, 0xbb, 0xac, 0x88, 0xfe, 0xe8, 0xa1, 0xbf, 0xe3, 0xee, 0x36, 0xfd, 0x02, 0xd1, 0x32, 0xd6, - 0xdf, 0x90, 0x01, 0x1d, 0x4f, 0x86, 0x77, 0xc5, 0xae, 0xc7, 0xde, 0xe5, 0x78, 0x81, 0x55, 0xd7, 0x8f, 0x3f, 0x40, - 0x42, 0xd5, 0xb5, 0x2f, 0x2c, 0x9e, 0x30, 0x4f, 0x89, 0xb6, 0x85, 0x0f, 0x61, 0xa1, 0xef, 0x72, 0xd8, 0x84, 0xa1, - 0x79, 0xd4, 0x3d, 0x4a, 0xda, 0x85, 0xbe, 0xf4, 0xb5, 0xec, 0x2b, 0xdf, 0xb9, 0x02, 0x58, 0xd9, 0x67, 0x36, 0xdc, - 0x93, 0xfe, 0x94, 0xea, 0xc3, 0xf6, 0xb7, 0x64, 0x01, 0x85, 0x16, 0xd6, 0x53, 0x39, 0x3b, 0x37, 0x25, 0x4f, 0xb3, - 0xe9, 0x61, 0x03, 0x7b, 0xd4, 0x3d, 0x7a, 0x4d, 0x05, 0x97, 0xd7, 0x66, 0xf4, 0xfe, 0x61, 0x28, 0x54, 0x47, 0x9d, - 0x3b, 0xc8, 0xa6, 0xb4, 0x2e, 0x39, 0xbf, 0x59, 0xb9, 0xa3, 0x30, 0xbf, 0x0f, 0xc1, 0x33, 0xac, 0x7b, 0x77, 0x71, - 0xde, 0xfb, 0xb3, 0x35, 0x47, 0xfe, 0x9a, 0xcd, 0x52, 0xc4, 0x22, 0x99, 0x83, 0xd5, 0x0f, 0xfd, 0x3c, 0x0e, 0xbb, - 0xa0, 0x82, 0xe3, 0xa6, 0x01, 0x1d, 0x36, 0x64, 0xd6, 0xbe, 0x44, 0xe0, 0x54, 0x23, 0x48, 0x53, 0x13, 0xd4, 0x2c, - 0x0f, 0x91, 0xd8, 0x2e, 0x65, 0xbb, 0xc0, 0xd0, 0xb6, 0x4d, 0x89, 0xf6, 0x0c, 0xde, 0x37, 0x69, 0x39, 0x51, 0xa1, - 0x59, 0xa4, 0xad, 0x92, 0xf1, 0xef, 0x44, 0x9b, 0x29, 0xd9, 0x63, 0x6b, 0xe0, 0xbd, 0x04, 0xe5, 0x64, 0x98, 0x62, - 0xf8, 0x8e, 0xaf, 0x77, 0x1e, 0x73, 0xcf, 0x39, 0x65, 0x9b, 0x94, 0x1d, 0xc1, 0x72, 0x22, 0x1b, 0xdf, 0x52, 0xbc, - 0xe1, 0xfb, 0xbb, 0x4a, 0x94, 0x00, 0x7a, 0x59, 0xf0, 0xe7, 0xd2, 0xe6, 0x0a, 0xdd, 0xee, 0xde, 0x51, 0x0a, 0xbf, - 0xe4, 0xe5, 0xf1, 0xb8, 0x4b, 0xbd, 0x10, 0x3a, 0x5f, 0xc4, 0xef, 0xc0, 0x1c, 0xc6, 0x10, 0x9b, 0x11, 0x20, 0xcc, - 0xf1, 0x01, 0x75, 0xb0, 0x7e, 0x04, 0xa0, 0x71, 0x02, 0x05, 0x18, 0x7d, 0xb5, 0x2d, 0xe8, 0x5b, 0x5e, 0x5c, 0x44, - 0x88, 0x1a, 0x05, 0x98, 0x28, 0x69, 0x16, 0xc3, 0x70, 0xa0, 0xf3, 0xfb, 0xf6, 0xae, 0x2e, 0x05, 0x0e, 0xbd, 0x63, - 0x19, 0xfe, 0xdb, 0xff, 0x58, 0x5b, 0x5a, 0x55, 0xb6, 0x5b, 0xe3, 0x34, 0xf3, 0xbf, 0xdd, 0x16, 0xfa, 0xfe, 0x4b, - 0xa1, 0x78, 0xde, 0xf1, 0xba, 0xfd, 0x05, 0xa2, 0xf7, 0x75, 0x2b, 0x57, 0xa5, 0x76, 0xc3, 0x4c, 0xf9, 0x43, 0x9a, - 0xc7, 0xc5, 0xc3, 0x28, 0x6e, 0x1d, 0x79, 0x93, 0xf4, 0x92, 0xf3, 0x2f, 0xe0, 0x6c, 0xfd, 0x05, 0xc8, 0x78, 0x5f, - 0x0a, 0xe3, 0x88, 0x49, 0x1c, 0x7c, 0x07, 0x31, 0x8a, 0xb6, 0x25, 0x6c, 0xc8, 0xed, 0xd3, 0x12, 0x34, 0x33, 0xfd, - 0x3e, 0x4a, 0x94, 0xd6, 0x7c, 0xff, 0x8b, 0x9c, 0xef, 0x2f, 0x85, 0xbc, 0x59, 0xc9, 0x0f, 0x9f, 0xac, 0x30, 0xf0, - 0x3d, 0x4e, 0xbf, 0x88, 0x1e, 0x5b, 0x95, 0x3e, 0x7c, 0x57, 0x5a, 0xfa, 0xac, 0xa2, 0xfe, 0x8e, 0x8a, 0x9a, 0x97, - 0x62, 0x44, 0xc4, 0x83, 0xa0, 0x9d, 0x6d, 0x97, 0xda, 0xb5, 0x04, 0xed, 0x82, 0x4d, 0x61, 0xff, 0x7a, 0x6c, 0xc8, - 0xab, 0x7e, 0xff, 0xe7, 0xca, 0x6b, 0xf1, 0xba, 0xeb, 0xd0, 0x94, 0x9f, 0x0a, 0x0f, 0x21, 0x80, 0xb5, 0x0c, 0x94, - 0xf1, 0x1c, 0x60, 0xd2, 0x45, 0x5e, 0xa3, 0x6c, 0x3a, 0x11, 0xf8, 0x98, 0x65, 0x37, 0x4e, 0x32, 0x0d, 0x30, 0xa3, - 0x9a, 0x62, 0xcc, 0x8a, 0x78, 0xb8, 0xf8, 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, 0xee, 0x33, 0x1c, 0x96, 0xc2, 0x31, - 0xe2, 0xff, 0x2d, 0x55, 0x3d, 0x22, 0xd0, 0xab, 0x32, 0xad, 0xa2, 0x22, 0xcf, 0x45, 0x84, 0x08, 0xd5, 0xd2, 0x39, - 0x1c, 0xfa, 0xb1, 0xdf, 0xc7, 0x81, 0x30, 0x2f, 0xfe, 0xf4, 0x58, 0x57, 0xfe, 0x54, 0xe0, 0x5a, 0x49, 0x81, 0x53, - 0x51, 0x23, 0x44, 0x08, 0xef, 0x4f, 0xe0, 0x59, 0x4d, 0x7d, 0xbf, 0xb1, 0x4c, 0x74, 0xff, 0xc8, 0x80, 0xf2, 0x07, - 0xe4, 0xeb, 0x5c, 0x8a, 0x33, 0x75, 0xf2, 0x98, 0x38, 0xe3, 0x00, 0xc4, 0x7c, 0x5d, 0xa2, 0xd1, 0xd8, 0xff, 0x80, - 0x04, 0x43, 0xf5, 0x83, 0x9d, 0x6e, 0xea, 0xfd, 0x33, 0x93, 0x38, 0x8a, 0x3e, 0x6d, 0x93, 0xa7, 0x92, 0xa5, 0xd1, - 0xc2, 0xd1, 0x7b, 0xc4, 0x30, 0x0e, 0xa7, 0xf3, 0x29, 0xc9, 0x36, 0x26, 0xab, 0x00, 0xd2, 0xc9, 0x4c, 0x1d, 0x53, - 0xea, 0x68, 0x9c, 0xeb, 0x05, 0x55, 0xe8, 0xb1, 0x2e, 0x79, 0x05, 0xd6, 0x93, 0x1f, 0xbd, 0xd2, 0x9f, 0x0a, 0x39, - 0x87, 0x8d, 0x44, 0x50, 0xf8, 0x01, 0xae, 0x06, 0x2b, 0x05, 0x0c, 0xa6, 0xbe, 0x85, 0xaf, 0x89, 0xe7, 0x28, 0x78, - 0x14, 0x76, 0x31, 0xb6, 0xe6, 0xbe, 0xf3, 0x49, 0x41, 0xb9, 0x67, 0xc5, 0x9c, 0xe7, 0xc0, 0xb9, 0x0c, 0x0a, 0x61, - 0x3a, 0x9e, 0xe5, 0xff, 0x4c, 0xf2, 0x7a, 0x62, 0x43, 0x80, 0x0c, 0xfe, 0x9c, 0x38, 0x2d, 0xdd, 0xa1, 0x3b, 0x0f, - 0x3d, 0x8b, 0x38, 0x6c, 0xf4, 0x64, 0x53, 0x16, 0xbb, 0x14, 0xf5, 0x12, 0xe6, 0x07, 0xf2, 0xf3, 0x96, 0xfc, 0x10, - 0xa2, 0x78, 0x1b, 0xfc, 0x9a, 0xb1, 0x58, 0xe0, 0x5f, 0x7f, 0xcb, 0x18, 0x4d, 0xb4, 0xe0, 0x5f, 0x59, 0x83, 0x44, - 0xc5, 0x3f, 0x65, 0x93, 0x1c, 0xb8, 0x4c, 0xd5, 0x87, 0xcf, 0x89, 0xf1, 0xd6, 0x6c, 0x78, 0xe4, 0x9b, 0x39, 0xe8, - 0xd4, 0xe7, 0xee, 0xca, 0xf6, 0x54, 0x35, 0xfe, 0x96, 0xea, 0x6a, 0xa4, 0xaa, 0x1a, 0x7f, 0x4b, 0xa9, 0x1a, 0xbf, - 0x65, 0x14, 0xbf, 0x93, 0xfb, 0x0c, 0x99, 0x93, 0x4d, 0x4c, 0xd2, 0xf9, 0x7b, 0xc3, 0x99, 0x5d, 0xf6, 0xab, 0xb7, - 0x89, 0xcc, 0x44, 0x0a, 0xb9, 0x37, 0x00, 0x35, 0x13, 0x7f, 0xae, 0x0c, 0xa7, 0xc4, 0xe5, 0xa5, 0x87, 0x2b, 0x36, - 0xad, 0x5e, 0xd2, 0x82, 0x05, 0x36, 0x2f, 0xb3, 0x3c, 0x45, 0x02, 0xdb, 0xa6, 0xcc, 0xfa, 0xa9, 0xf2, 0x00, 0x82, - 0x99, 0xd4, 0x04, 0x80, 0xb4, 0x10, 0x95, 0x42, 0xe4, 0x2f, 0x71, 0x56, 0x5f, 0xf2, 0xde, 0x36, 0x8f, 0x89, 0xb4, - 0xba, 0xd7, 0xef, 0xa7, 0x17, 0x69, 0x4e, 0x41, 0x0d, 0xa7, 0x59, 0xa7, 0x3f, 0x64, 0x41, 0x9d, 0xc8, 0x55, 0xfa, - 0x77, 0x37, 0xc8, 0xcb, 0xf8, 0xbe, 0xee, 0x7a, 0xfe, 0x44, 0xfd, 0xbd, 0xb7, 0xfe, 0xb6, 0x40, 0x70, 0x27, 0xa7, - 0x7e, 0xb2, 0x2a, 0xe5, 0x89, 0x71, 0x69, 0xef, 0xf9, 0x4d, 0x5d, 0x14, 0x59, 0x9d, 0x6e, 0x3e, 0x48, 0x3d, 0x8d, - 0xee, 0x8b, 0x03, 0x18, 0x83, 0xf7, 0x00, 0x78, 0xa6, 0x43, 0x03, 0xa4, 0xef, 0x19, 0x79, 0xb8, 0xcf, 0x2d, 0xf9, - 0x49, 0x65, 0x6d, 0x92, 0xb0, 0xa2, 0xd8, 0x0c, 0x63, 0x84, 0x92, 0x71, 0x1a, 0x3b, 0xbf, 0xdf, 0x57, 0x7f, 0xef, - 0x31, 0x8a, 0x8a, 0x8a, 0x3b, 0x45, 0xa3, 0xb2, 0xaa, 0x47, 0xdb, 0xc1, 0xf1, 0x78, 0x59, 0xd9, 0x38, 0xda, 0x7a, - 0x05, 0x1c, 0xac, 0x50, 0x29, 0x7b, 0x25, 0xc2, 0xf2, 0xc3, 0x95, 0xdf, 0xef, 0xc3, 0xbf, 0x32, 0xd2, 0xc2, 0xf3, - 0xa7, 0xf8, 0x6b, 0x51, 0x17, 0x18, 0x9e, 0x41, 0x6b, 0x34, 0x87, 0x60, 0x82, 0xbf, 0x77, 0xa0, 0x5e, 0x5a, 0x69, - 0x1f, 0x41, 0xb7, 0x02, 0x3d, 0xa8, 0x87, 0x3e, 0x4d, 0xda, 0x17, 0x12, 0x75, 0x7b, 0xab, 0xd3, 0xe8, 0x8f, 0x0a, - 0x2e, 0xa7, 0x30, 0x39, 0xdc, 0xd0, 0xa7, 0x75, 0xb8, 0xfb, 0x04, 0x4f, 0x7f, 0x06, 0xca, 0xad, 0xe3, 0x11, 0xc5, - 0x16, 0x70, 0xf3, 0x58, 0x87, 0x9f, 0x8b, 0x52, 0x46, 0xd4, 0xc7, 0xd3, 0x02, 0xb4, 0x77, 0x01, 0x3a, 0x60, 0x69, - 0x10, 0xaf, 0x90, 0x3c, 0x67, 0x23, 0x80, 0x65, 0x07, 0x96, 0xb3, 0x8c, 0x53, 0x98, 0x67, 0xf9, 0x5c, 0xad, 0xb4, - 0x8b, 0x32, 0xf1, 0x6a, 0x96, 0x81, 0xb3, 0xc0, 0x55, 0xee, 0xb3, 0x4c, 0xab, 0x9e, 0xf2, 0x04, 0x7d, 0x5e, 0xc9, - 0x09, 0xae, 0x04, 0x27, 0x1b, 0x90, 0x5f, 0x80, 0x24, 0x4d, 0x29, 0x6b, 0xca, 0xe7, 0xd7, 0x74, 0x43, 0x46, 0xcf, - 0x79, 0xcf, 0x8b, 0x86, 0xa1, 0x7f, 0xe5, 0x95, 0x10, 0xbe, 0x89, 0xdb, 0x36, 0x4a, 0x61, 0x7f, 0x11, 0x58, 0x7c, - 0xc2, 0x7e, 0xf4, 0x96, 0xfe, 0x74, 0x1c, 0x84, 0x43, 0xe4, 0x86, 0x8a, 0x39, 0xb0, 0xa7, 0x01, 0x8b, 0x4d, 0x7c, - 0xb3, 0x9d, 0xc4, 0x83, 0x81, 0xaf, 0x33, 0x16, 0xb3, 0x18, 0x68, 0x90, 0xe3, 0xc1, 0xf5, 0x5c, 0x9f, 0x10, 0xfa, - 0x61, 0x44, 0xe5, 0xa8, 0x40, 0xe7, 0x20, 0x1a, 0x2c, 0x01, 0x4f, 0xbd, 0x95, 0x0d, 0x92, 0x8c, 0x49, 0x26, 0x71, - 0xad, 0x49, 0xaa, 0xc3, 0x09, 0xad, 0x03, 0x1d, 0x57, 0x17, 0xd0, 0xf9, 0xb8, 0xee, 0x7d, 0xbc, 0x1a, 0x2e, 0xa8, - 0xf4, 0x2b, 0x31, 0xf0, 0xea, 0xe9, 0x38, 0xb8, 0xa6, 0x5b, 0xe1, 0x62, 0x1d, 0xee, 0x7e, 0x96, 0x0f, 0x1c, 0x77, - 0x54, 0xd2, 0x10, 0x18, 0xbc, 0x3d, 0x74, 0x37, 0x33, 0x34, 0xd4, 0x49, 0xfb, 0x30, 0x0e, 0xe5, 0x10, 0xab, 0x56, - 0x5c, 0x49, 0x6f, 0x04, 0xdf, 0x2e, 0x14, 0x63, 0xd9, 0xd8, 0xb5, 0xa1, 0x28, 0xfc, 0x15, 0xc0, 0x0e, 0xb5, 0xbf, - 0x52, 0xc9, 0xc7, 0xc8, 0xa8, 0xa6, 0x81, 0x8e, 0x01, 0x58, 0xb2, 0x34, 0x91, 0x54, 0x91, 0x46, 0xe2, 0x8f, 0xcc, - 0x58, 0x47, 0x4d, 0xd7, 0x17, 0x4c, 0x55, 0x8b, 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, 0x99, 0xb4, 0x7d, 0x59, - 0x91, 0x2d, 0x08, 0xa6, 0x27, 0xd1, 0x07, 0x49, 0xd0, 0xba, 0x48, 0xa4, 0x19, 0x21, 0xc0, 0x8f, 0x27, 0xe5, 0x8d, - 0xfe, 0x1c, 0x34, 0xad, 0x04, 0x2f, 0x19, 0x24, 0x8f, 0xc4, 0xcf, 0xa4, 0x60, 0x16, 0x63, 0xf9, 0x60, 0x80, 0xe5, - 0xe4, 0x4f, 0x1d, 0x93, 0xf4, 0x5f, 0x3a, 0x9d, 0xb0, 0x5f, 0x78, 0x95, 0xad, 0xe5, 0x4d, 0x73, 0xef, 0x85, 0x97, - 0xb3, 0x54, 0xc3, 0x32, 0xe8, 0xbf, 0x26, 0xda, 0x05, 0x5b, 0x5b, 0xc6, 0x84, 0x55, 0x3f, 0x80, 0xb4, 0x47, 0xba, - 0xbc, 0x7c, 0x58, 0x31, 0xc1, 0xa3, 0x2b, 0x6b, 0x1e, 0x44, 0x57, 0xc2, 0x47, 0x2e, 0xbb, 0x49, 0x72, 0x33, 0x9e, - 0xf8, 0xe1, 0x60, 0xa0, 0x00, 0x68, 0x69, 0x9d, 0x14, 0x83, 0xf0, 0xa9, 0x90, 0x03, 0x69, 0x74, 0x54, 0x05, 0x58, - 0x2c, 0xb3, 0x9b, 0x72, 0x92, 0x0d, 0x06, 0x3e, 0x88, 0x8d, 0x89, 0xdd, 0xd0, 0x6c, 0xee, 0xb3, 0x33, 0x05, 0x59, - 0x6d, 0x0e, 0x5b, 0x33, 0xdd, 0x02, 0x03, 0x80, 0x41, 0x44, 0xb0, 0xdc, 0x67, 0x46, 0x3e, 0xa2, 0x4e, 0x4f, 0x61, - 0x04, 0x04, 0xbf, 0x9e, 0x08, 0x44, 0x2e, 0x12, 0xa8, 0x07, 0x98, 0x09, 0x30, 0xa3, 0x8a, 0xe1, 0x35, 0xb0, 0x8b, - 0x57, 0xe6, 0x15, 0x83, 0xfe, 0x45, 0x93, 0x2c, 0xd1, 0x54, 0xe2, 0x68, 0x8c, 0x9c, 0x4a, 0x63, 0x64, 0x40, 0xec, - 0xe2, 0xf8, 0xf7, 0x94, 0x1e, 0x05, 0x29, 0xfb, 0x9c, 0x1b, 0xe2, 0x70, 0x14, 0x5f, 0xc1, 0xaa, 0x71, 0x3c, 0xd6, - 0xe6, 0xf5, 0x74, 0x56, 0xcf, 0x07, 0x22, 0x80, 0xff, 0x86, 0x82, 0xfd, 0xa2, 0xa9, 0xc8, 0x0d, 0x52, 0xe7, 0xf1, - 0x98, 0x82, 0x7c, 0xaa, 0x9b, 0xfc, 0x43, 0xee, 0xee, 0xa7, 0xb3, 0xb9, 0x35, 0x47, 0xaf, 0x6a, 0x5c, 0xb7, 0x56, - 0x37, 0x14, 0x12, 0xad, 0x69, 0x52, 0xdc, 0xe4, 0x93, 0x62, 0xc0, 0x2b, 0x5f, 0xa8, 0x2e, 0xb6, 0x46, 0xb0, 0xf0, - 0xe7, 0x16, 0x08, 0x93, 0x71, 0x2f, 0x3e, 0x59, 0xc8, 0x29, 0xed, 0xda, 0x6a, 0xb7, 0xb5, 0x49, 0xd3, 0x58, 0x35, - 0xbc, 0x86, 0x5d, 0x3a, 0x45, 0xb4, 0xed, 0x92, 0xe0, 0x0b, 0xd0, 0xb2, 0xba, 0x10, 0x79, 0x4c, 0xbf, 0x42, 0x7e, - 0x2d, 0x86, 0xff, 0x29, 0xdd, 0x9b, 0x53, 0x1b, 0xe4, 0x00, 0xb6, 0x7b, 0x0f, 0xb7, 0x63, 0xf4, 0x40, 0x06, 0x6f, - 0x04, 0x10, 0x8d, 0xaf, 0xa7, 0xd6, 0x8c, 0x89, 0x86, 0x05, 0x2b, 0x87, 0x91, 0x1f, 0x20, 0xe3, 0xe5, 0x14, 0x58, - 0xd9, 0x4f, 0x8a, 0xb8, 0xf6, 0x87, 0x91, 0x7f, 0xf5, 0x2c, 0xc8, 0xb8, 0x17, 0x0d, 0x3b, 0xbe, 0x00, 0x7b, 0xf5, - 0xd5, 0x33, 0x16, 0x0d, 0x78, 0x7e, 0x53, 0x4f, 0xb3, 0x60, 0x98, 0xb1, 0xe8, 0xa6, 0x18, 0x82, 0x0f, 0xed, 0xf3, - 0x72, 0x10, 0xfa, 0xbe, 0xd9, 0x39, 0x74, 0x37, 0x24, 0xf2, 0x08, 0xfb, 0x2b, 0xb8, 0xed, 0x6a, 0x89, 0x19, 0xe0, - 0x06, 0x56, 0x11, 0x33, 0xd8, 0xf2, 0x57, 0xcf, 0x0c, 0x97, 0x50, 0xfe, 0x5c, 0x6a, 0x36, 0x0a, 0x34, 0x27, 0xe7, - 0x68, 0x4e, 0x56, 0x42, 0x2d, 0xf9, 0xa4, 0xc2, 0xa9, 0x3a, 0x9f, 0x68, 0xbb, 0xd1, 0x18, 0x03, 0x17, 0xed, 0xb9, - 0x2d, 0x8c, 0xcc, 0x74, 0x91, 0xa2, 0x01, 0x0b, 0xcf, 0xc4, 0x29, 0x8d, 0x01, 0xed, 0xcb, 0x81, 0xa5, 0x0d, 0xf9, - 0xab, 0x9c, 0x19, 0x68, 0x1b, 0x52, 0x1a, 0x35, 0x03, 0x7f, 0xa6, 0x26, 0xcc, 0xaf, 0x60, 0x25, 0x82, 0xa8, 0x2e, - 0xc0, 0x24, 0xa9, 0xc8, 0x68, 0xa4, 0xac, 0x44, 0x72, 0x0e, 0x78, 0x1f, 0xc1, 0x93, 0x45, 0xec, 0x6a, 0x7f, 0x4a, - 0xff, 0xab, 0xc3, 0xe7, 0xda, 0x7f, 0x2a, 0x80, 0x85, 0x5c, 0x1a, 0x44, 0x06, 0x0a, 0x87, 0xd4, 0x54, 0x22, 0x4e, - 0x1c, 0xcf, 0xc0, 0xd7, 0x70, 0x81, 0xa6, 0x80, 0xfe, 0xa0, 0x66, 0x14, 0x91, 0x85, 0xbf, 0x7a, 0x76, 0x53, 0xb7, - 0x7a, 0x9e, 0x39, 0xaf, 0x41, 0x33, 0x03, 0x21, 0x3d, 0x4e, 0xd5, 0xdb, 0x90, 0xe8, 0xbc, 0xbc, 0xd4, 0x2f, 0x13, - 0x22, 0x59, 0x11, 0x79, 0xfa, 0x3e, 0x07, 0xf3, 0x88, 0x22, 0x74, 0x70, 0x65, 0x1e, 0x8f, 0x97, 0x82, 0xc2, 0x77, - 0x94, 0xe7, 0x03, 0x4e, 0xb3, 0x28, 0x01, 0x6d, 0x20, 0xab, 0x4c, 0x99, 0x9b, 0xa4, 0x65, 0xea, 0x3e, 0x80, 0x95, - 0x20, 0x47, 0x37, 0xa7, 0xa0, 0x50, 0x46, 0x82, 0x52, 0x5a, 0x0d, 0x42, 0xa9, 0x0e, 0x8b, 0x20, 0x72, 0xc8, 0x42, - 0xc0, 0xcd, 0x54, 0x34, 0x5a, 0xd2, 0xf0, 0x08, 0xe7, 0x06, 0x0a, 0x01, 0x48, 0xec, 0xa9, 0xa2, 0x8c, 0xcb, 0x61, - 0xce, 0xd6, 0x3c, 0x1c, 0xe2, 0xac, 0x49, 0x5b, 0x9e, 0x83, 0x38, 0x96, 0x4b, 0xbe, 0xc9, 0x11, 0x0c, 0x22, 0xf4, - 0x19, 0xf2, 0x27, 0xcb, 0xf9, 0x77, 0xe7, 0x30, 0xed, 0x08, 0x1f, 0x76, 0xb5, 0x05, 0x17, 0xb3, 0xbb, 0xf9, 0x04, - 0xe2, 0x5b, 0xee, 0xe6, 0xa7, 0x18, 0x22, 0x0b, 0x7f, 0xb0, 0x1a, 0x4a, 0xae, 0x28, 0x74, 0x59, 0x8f, 0x48, 0x91, - 0x3d, 0xdd, 0x70, 0x04, 0xc1, 0x81, 0x56, 0x0d, 0x32, 0x34, 0x12, 0x5f, 0x3d, 0x83, 0xac, 0xc1, 0x86, 0x7f, 0xce, - 0xc9, 0x59, 0xdd, 0x9f, 0x6c, 0xa1, 0x9a, 0x64, 0xb2, 0x56, 0x54, 0xce, 0x5f, 0xaf, 0xca, 0xf2, 0x6c, 0x55, 0x86, - 0xeb, 0x41, 0x57, 0x55, 0x96, 0x1c, 0xa9, 0x0d, 0xd0, 0x9a, 0xae, 0x10, 0x43, 0x21, 0x6b, 0xb0, 0xb4, 0xaa, 0xb2, - 0xa1, 0x3e, 0x81, 0x40, 0x1f, 0x60, 0x19, 0x35, 0xfb, 0xe9, 0xf0, 0x9f, 0xc1, 0x3f, 0x55, 0xc8, 0x52, 0x9d, 0xd6, - 0x99, 0xf8, 0x35, 0x58, 0x32, 0xfc, 0xe3, 0xb7, 0x60, 0x03, 0x58, 0x02, 0x64, 0xb9, 0xdb, 0xda, 0x68, 0xbd, 0xf2, - 0x0a, 0xf1, 0xae, 0xd6, 0x17, 0xfd, 0xd6, 0x6d, 0xa2, 0x56, 0x80, 0x11, 0x0a, 0x2d, 0x02, 0x6c, 0xf5, 0xc0, 0x3d, - 0x05, 0x3f, 0x10, 0xc3, 0xb9, 0x26, 0xad, 0xa9, 0x13, 0x5e, 0x67, 0xe3, 0x48, 0x44, 0xf5, 0x0e, 0x2e, 0xee, 0xf5, - 0xce, 0xe2, 0x6f, 0x54, 0x20, 0x00, 0xb2, 0x98, 0x62, 0xe3, 0xbc, 0x21, 0xbd, 0x32, 0xec, 0x24, 0xf4, 0xde, 0xb0, - 0x13, 0xc8, 0x8b, 0xc3, 0x4e, 0xa1, 0x4b, 0xb4, 0x9d, 0x22, 0x35, 0xd1, 0x76, 0xd2, 0x62, 0x1d, 0x96, 0x10, 0xfc, - 0xaa, 0xbd, 0x75, 0x94, 0xed, 0x8b, 0x2c, 0x61, 0xda, 0x02, 0x46, 0xb9, 0x55, 0x9f, 0x39, 0x45, 0xac, 0x95, 0xbd, - 0xd3, 0x49, 0x95, 0xbb, 0xc8, 0xa7, 0x56, 0x53, 0x64, 0xf2, 0x0f, 0xa7, 0x2d, 0x92, 0x4f, 0x7e, 0x6e, 0x37, 0x4c, - 0xa6, 0x7f, 0x3c, 0xf9, 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, 0x57, 0xbf, 0x84, 0x2b, 0x36, 0x3f, 0x34, 0x8a, - 0x9e, 0x5c, 0x9f, 0xa2, 0x6e, 0xc5, 0xd5, 0x69, 0xda, 0x6a, 0x8e, 0x1d, 0x67, 0xc8, 0xc1, 0xb3, 0x82, 0x60, 0x3b, - 0x2a, 0x51, 0xbe, 0x6d, 0x37, 0x1d, 0x13, 0x5b, 0xfd, 0xb3, 0xa8, 0xb6, 0x2b, 0xa8, 0x88, 0x88, 0x4f, 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, 0xe7, 0x77, 0xf5, 0x82, 0x93, 0xc9, 0x7e, 0x72, 0x9a, - 0xbb, 0x5d, 0xa4, 0xfd, 0xc4, 0xb7, 0x61, 0xfe, 0xf5, 0x0d, 0x62, 0x25, 0xea, 0x7f, 0x54, 0x00, 0x34, 0xb8, 0xcd, - 0x63, 0x89, 0x52, 0x7f, 0x50, 0xd5, 0x0f, 0x6a, 0xa6, 0x6a, 0x1a, 0x08, 0xe6, 0x54, 0x0a, 0xf8, 0xc3, 0xed, 0xc2, - 0x15, 0x8f, 0xb8, 0x61, 0x61, 0xfc, 0xd3, 0xab, 0xd9, 0xb9, 0xa0, 0x32, 0x70, 0x33, 0xfe, 0xd3, 0x13, 0xec, 0x1c, - 0xd6, 0x0a, 0xc8, 0x0a, 0x7f, 0x7a, 0xd5, 0x23, 0xef, 0xe7, 0xfc, 0x4f, 0x2f, 0x7f, 0xe4, 0x7d, 0xc4, 0x79, 0xf9, - 0x13, 0x49, 0x9d, 0x10, 0xd5, 0xe5, 0x4f, 0xc2, 0x14, 0x5b, 0xa7, 0xf9, 0x2b, 0x52, 0xf8, 0x04, 0x9f, 0x81, 0xef, - 0x70, 0x1d, 0xee, 0xcc, 0x6f, 0xf0, 0xd8, 0xb1, 0xd8, 0x76, 0xa9, 0x2f, 0xa0, 0x1c, 0x81, 0x45, 0x54, 0xf6, 0xdb, - 0xb9, 0xfd, 0x6a, 0x61, 0x94, 0x31, 0x76, 0x5f, 0xb2, 0x12, 0xa5, 0xb3, 0x7e, 0xbf, 0x90, 0x82, 0x91, 0x5d, 0x58, - 0xa3, 0x3d, 0x4a, 0xd5, 0xab, 0x6f, 0xc3, 0x3a, 0x4a, 0xd2, 0x7c, 0x25, 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, 0x01, 0x23, 0xa7, 0xb0, 0x54, 0x1e, 0xac, 0xc4, 0xb9, 0xe8, 0xb3, 0xe2, 0x78, 0xf4, 0x2c, 0x34, 0xf3, - 0x0a, 0x1e, 0x84, 0x3b, 0x0b, 0x23, 0x15, 0x2e, 0x84, 0xe2, 0x79, 0x85, 0xb1, 0x15, 0x15, 0x70, 0x20, 0xc3, 0x0f, - 0x08, 0xbc, 0x97, 0xfd, 0x2b, 0x18, 0x0c, 0x13, 0xdc, 0xc8, 0xa8, 0x93, 0x2b, 0xf6, 0x27, 0x06, 0x66, 0x50, 0x4f, - 0x6a, 0xf7, 0xd9, 0x83, 0x0a, 0xec, 0x85, 0x33, 0xa0, 0xbd, 0x1b, 0xa3, 0x9f, 0x55, 0xb1, 0x71, 0xd2, 0x3f, 0x15, - 0x1b, 0x48, 0xa6, 0xc3, 0xe2, 0x64, 0x9b, 0x86, 0x47, 0xf2, 0xe4, 0x38, 0xdd, 0xf4, 0x8f, 0xc7, 0x31, 0x7e, 0x1c, - 0xe5, 0xd7, 0x16, 0xf0, 0x2a, 0x6e, 0x21, 0x8d, 0x45, 0x8a, 0xde, 0x81, 0x98, 0x43, 0xd1, 0x4b, 0xf6, 0x5b, 0xc6, - 0xcb, 0x89, 0xa0, 0x94, 0x24, 0x36, 0xbc, 0x23, 0x3d, 0x4d, 0xeb, 0xd1, 0x4e, 0x06, 0xec, 0xd7, 0xa3, 0x3d, 0xfd, - 0x05, 0x8a, 0x47, 0x0b, 0x7f, 0x49, 0x7f, 0x17, 0x77, 0x73, 0xcf, 0xf9, 0xa6, 0xf1, 0x1d, 0x71, 0x81, 0x62, 0xcd, - 0xee, 0xaf, 0x69, 0xe9, 0xac, 0x03, 0xc1, 0x01, 0x6f, 0xb1, 0x8b, 0xf6, 0xfd, 0xc6, 0x75, 0x7a, 0x3a, 0x7c, 0xeb, - 0xd6, 0x28, 0xdf, 0xfb, 0x87, 0x44, 0x39, 0x38, 0xbc, 0x72, 0xd1, 0xfc, 0xed, 0xa7, 0x0c, 0x49, 0x85, 0xe6, 0x06, - 0xdb, 0xc9, 0x16, 0x61, 0x6d, 0x8c, 0x83, 0x9c, 0xad, 0xca, 0x30, 0x02, 0x06, 0x75, 0xec, 0x7f, 0xf4, 0xd9, 0xb4, - 0x21, 0xfb, 0x00, 0x50, 0xb9, 0x0a, 0x01, 0x7b, 0x00, 0x4e, 0x34, 0xc2, 0x0d, 0x70, 0xab, 0xd1, 0x92, 0x0e, 0xea, - 0xb6, 0x60, 0x20, 0x5a, 0xc2, 0xc6, 0x09, 0x5d, 0xdf, 0x57, 0x84, 0x8f, 0xca, 0xb7, 0x0f, 0xe5, 0xaf, 0x9e, 0xb3, - 0xff, 0xde, 0x61, 0x4d, 0x4d, 0xb9, 0x05, 0xcc, 0x9c, 0xb5, 0xc8, 0x2b, 0x84, 0x4e, 0x91, 0xdf, 0xab, 0xba, 0x12, - 0xc3, 0x65, 0x2d, 0xca, 0xce, 0xec, 0xd6, 0x89, 0xde, 0x39, 0x05, 0xb5, 0x54, 0x36, 0x20, 0x01, 0x6e, 0x20, 0xc5, - 0xb6, 0xc0, 0x92, 0xce, 0x06, 0x28, 0xfe, 0x0d, 0x2a, 0xed, 0xfe, 0xdf, 0x39, 0x13, 0xd4, 0x6c, 0xa3, 0xba, 0xbf, - 0xd2, 0x4f, 0x55, 0x4d, 0x62, 0x01, 0x2e, 0x27, 0x69, 0xde, 0xf1, 0x08, 0xab, 0x7f, 0x9a, 0x2c, 0x45, 0xa0, 0x57, - 0x11, 0xed, 0x4a, 0x40, 0x82, 0x76, 0x76, 0x16, 0x2a, 0x02, 0x05, 0xfa, 0xfa, 0x0f, 0xdb, 0x34, 0x8b, 0xe5, 0x6a, - 0xb6, 0x87, 0x89, 0xb2, 0x58, 0x0f, 0x11, 0xe4, 0xcc, 0xd4, 0xc1, 0x7e, 0x4f, 0x33, 0x9a, 0x85, 0x37, 0xa6, 0x04, - 0x97, 0xe2, 0x2a, 0x2a, 0x72, 0xf0, 0x39, 0xc4, 0x17, 0x3e, 0x15, 0x72, 0x83, 0x88, 0xa6, 0x3f, 0xe4, 0x9e, 0x79, - 0x83, 0x85, 0x92, 0x9f, 0x10, 0x7f, 0xc9, 0xda, 0x18, 0xf7, 0x4b, 0xa7, 0xda, 0x2f, 0x15, 0x82, 0xfb, 0xcf, 0xb6, - 0xd8, 0xa8, 0xf2, 0x44, 0x8f, 0x3e, 0xc5, 0xfa, 0x9f, 0x2d, 0xa0, 0x54, 0xf7, 0x6d, 0x70, 0x2a, 0x1e, 0x85, 0xdb, - 0xba, 0xb8, 0x45, 0x68, 0x81, 0x72, 0x54, 0x15, 0xdb, 0x32, 0x22, 0x4e, 0xd8, 0x6d, 0x5d, 0xf4, 0x34, 0x07, 0x3a, - 0x75, 0x58, 0x9a, 0xc8, 0x13, 0xa1, 0xdd, 0x82, 0xee, 0x69, 0x8e, 0x95, 0x78, 0x21, 0x4b, 0x07, 0x59, 0x27, 0xd2, - 0x84, 0xca, 0x5d, 0x5d, 0x75, 0x52, 0x2a, 0x75, 0xc3, 0xeb, 0x54, 0x33, 0xfe, 0x2e, 0xcd, 0x9f, 0x58, 0xf6, 0xeb, - 0xd6, 0x6f, 0xb5, 0xda, 0x1b, 0xab, 0x47, 0x25, 0x6b, 0x8e, 0xb3, 0x09, 0x49, 0xe9, 0x13, 0xb6, 0x9b, 0x49, 0xd7, - 0x3a, 0xf0, 0x24, 0xb8, 0x1c, 0x7a, 0x02, 0x2a, 0x06, 0x4d, 0xbc, 0xdd, 0x05, 0xea, 0x11, 0x78, 0x06, 0xaa, 0x19, - 0x24, 0xd7, 0x01, 0xbf, 0xac, 0xb5, 0x3c, 0x65, 0x84, 0x61, 0xb5, 0xb3, 0x68, 0x39, 0x58, 0x49, 0x78, 0xae, 0x08, - 0x5c, 0xbb, 0x12, 0x78, 0x35, 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, 0x43, 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, 0x7a, 0xf5, 0xeb, 0xba, 0xc3, 0x75, 0xde, 0x04, 0xc7, 0x4d, 0xd7, 0xb6, 0xda, 0xd9, 0xcf, 0xdd, 0xbd, 0xb5, - 0x88, 0xc2, 0x2c, 0xfb, 0x6b, 0x51, 0xfc, 0x51, 0xe9, 0x3b, 0x02, 0x1d, 0xdd, 0x79, 0x51, 0xa7, 0xcb, 0xfd, 0x07, - 0xc2, 0x78, 0xf2, 0xea, 0x13, 0xa2, 0x5b, 0xdf, 0x67, 0xee, 0x57, 0x80, 0x1b, 0xc1, 0x1d, 0x44, 0x7b, 0xb7, 0xd4, - 0x27, 0xb5, 0xfa, 0x5a, 0xaf, 0x9d, 0xa7, 0xe7, 0x37, 0x9d, 0xdb, 0xef, 0xa1, 0x39, 0xd9, 0x7a, 0x4f, 0x0b, 0x6b, - 0x65, 0xe9, 0xa9, 0x2a, 0xd8, 0x9b, 0xe5, 0xb9, 0x2a, 0x98, 0x3c, 0xf0, 0x9a, 0xfd, 0x82, 0x06, 0x57, 0x3a, 0xd9, - 0x78, 0xcf, 0xd4, 0xc0, 0x2d, 0x0a, 0x4b, 0x87, 0x5f, 0x72, 0x33, 0x79, 0x89, 0xfb, 0x4b, 0x45, 0x2e, 0xf6, 0x9d, - 0x33, 0xba, 0x33, 0xb3, 0xee, 0x55, 0x85, 0xab, 0x05, 0xb9, 0x3a, 0xb0, 0xb5, 0xec, 0xe2, 0x70, 0xc3, 0x22, 0x0a, - 0x10, 0x88, 0xe9, 0x95, 0x5a, 0xfb, 0x13, 0x1a, 0x84, 0x6a, 0x30, 0xf0, 0x0b, 0x0c, 0x56, 0x05, 0x0a, 0x1f, 0x28, - 0x92, 0xbf, 0xf2, 0x04, 0xec, 0xe2, 0x19, 0xa0, 0x5b, 0xb1, 0x59, 0x31, 0x42, 0x84, 0x4c, 0x56, 0xb1, 0x9a, 0xce, - 0x20, 0x9f, 0xfa, 0xe2, 0x1b, 0x5b, 0x75, 0x3e, 0x6f, 0x6b, 0xaa, 0x9c, 0x3b, 0x14, 0xba, 0xbb, 0xa9, 0x3b, 0xb7, - 0x2e, 0xf2, 0xdc, 0x21, 0xe4, 0x4a, 0xc5, 0x4a, 0x4c, 0x43, 0xcd, 0x93, 0x34, 0xa3, 0xfe, 0x62, 0x9f, 0x8a, 0x1a, - 0x85, 0x53, 0xfe, 0x74, 0x0c, 0xaa, 0x70, 0x55, 0x43, 0x1c, 0x4b, 0x55, 0x3c, 0xb2, 0x41, 0xa0, 0x79, 0x75, 0xa7, - 0x92, 0x26, 0x64, 0x72, 0x23, 0x7c, 0x6a, 0x52, 0xca, 0xd3, 0xb4, 0x49, 0x2b, 0x45, 0xea, 0xe0, 0x83, 0x3a, 0xd5, - 0x78, 0x6e, 0xe6, 0xcf, 0x01, 0xcc, 0xb8, 0xba, 0xe1, 0xd7, 0x8a, 0xcb, 0xa8, 0xad, 0xcc, 0xa4, 0xfd, 0xc9, 0xd1, - 0xd8, 0x28, 0x56, 0xe3, 0x46, 0x19, 0x61, 0xa5, 0x34, 0x27, 0xc5, 0x72, 0x3c, 0xff, 0x80, 0xc1, 0x9a, 0x27, 0xb0, - 0x83, 0x89, 0x4a, 0x79, 0x1f, 0x01, 0xf1, 0x75, 0x92, 0xae, 0x12, 0x48, 0x91, 0xfe, 0xa5, 0x4b, 0xee, 0x32, 0x36, - 0x10, 0x63, 0x56, 0xcc, 0x8c, 0xfe, 0x07, 0x77, 0x49, 0x7f, 0x12, 0x02, 0xe0, 0x26, 0x9a, 0x42, 0xa7, 0xce, 0x93, - 0xab, 0x2a, 0x58, 0x5e, 0x79, 0x68, 0xc5, 0x88, 0x07, 0xff, 0xf9, 0x3c, 0x44, 0x10, 0x73, 0x4c, 0xf1, 0xf4, 0x0b, - 0xa3, 0xff, 0x08, 0xae, 0x31, 0x82, 0xd0, 0xdd, 0x3b, 0x87, 0x21, 0xdc, 0xec, 0x41, 0x06, 0xf5, 0x87, 0x3a, 0x24, - 0x6a, 0xf8, 0xd7, 0xdc, 0x83, 0xfe, 0xaf, 0x33, 0x61, 0xa9, 0xfd, 0xf4, 0x74, 0x00, 0x15, 0xbc, 0xaf, 0x78, 0x1b, - 0x11, 0xdf, 0x27, 0x7e, 0x1a, 0x0f, 0xb6, 0x4f, 0xb7, 0x60, 0xad, 0xfb, 0x50, 0x19, 0xeb, 0x2a, 0x61, 0x03, 0x01, - 0x5f, 0xa3, 0xa8, 0x3d, 0xaf, 0xdd, 0xee, 0xc1, 0x7f, 0xfa, 0x57, 0x21, 0x03, 0x26, 0x4e, 0xdf, 0x67, 0x4e, 0xd6, - 0xe8, 0x2a, 0x93, 0xe9, 0x43, 0x27, 0x7d, 0xab, 0xd3, 0x7d, 0x27, 0xfc, 0x23, 0x67, 0x16, 0x1f, 0x6e, 0xe9, 0x2b, - 0x4d, 0x8a, 0x3b, 0x60, 0x65, 0xf3, 0xa8, 0x20, 0xd4, 0xb9, 0x88, 0xbe, 0x32, 0xe5, 0x5b, 0x42, 0xcd, 0xa1, 0xb1, - 0xa4, 0x94, 0xee, 0x35, 0xf4, 0x3a, 0xad, 0xf5, 0xdb, 0x28, 0xc1, 0x98, 0xe8, 0x78, 0xf2, 0x32, 0x1e, 0x2b, 0xef, - 0xe3, 0x71, 0x23, 0x15, 0xf2, 0x00, 0x44, 0xa0, 0x62, 0xfc, 0xe9, 0xca, 0x53, 0x91, 0x5e, 0x18, 0xaf, 0x42, 0x29, - 0x28, 0x0c, 0xe8, 0x0a, 0xa4, 0x80, 0x47, 0xed, 0x89, 0xce, 0xc2, 0x2e, 0xe1, 0x1e, 0xdd, 0x04, 0x8c, 0xf5, 0xf9, - 0xaf, 0xb9, 0x97, 0x33, 0xe1, 0x0e, 0x2f, 0x06, 0xa8, 0x4d, 0xbd, 0xba, 0xfb, 0xb8, 0x56, 0xe7, 0x70, 0x08, 0x0e, - 0x56, 0x83, 0x08, 0x4e, 0xe7, 0x73, 0x47, 0xb3, 0x2c, 0x40, 0xe5, 0x64, 0x95, 0x91, 0x37, 0x4f, 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, 0xd7, 0x47, 0xf5, 0xd3, 0x67, 0x6c, 0xc3, 0x25, 0xea, 0xa4, 0x33, 0x11, 0x80, - 0xd8, 0x53, 0xb3, 0x8a, 0x6e, 0x80, 0xa4, 0x4e, 0xb3, 0x8a, 0x6e, 0xa8, 0xd9, 0xc6, 0x38, 0x00, 0xca, 0x58, 0xc0, - 0xbe, 0x9b, 0x8e, 0x83, 0xf5, 0xd3, 0x58, 0x5e, 0x87, 0x56, 0x4f, 0xb7, 0xca, 0x67, 0x50, 0xb7, 0xda, 0x18, 0x13, - 0xdb, 0xcd, 0x97, 0x73, 0xfd, 0x6e, 0xb0, 0xf4, 0xed, 0xa0, 0x39, 0xa7, 0xec, 0x95, 0x2e, 0x7b, 0x6d, 0x97, 0x4d, - 0x3d, 0x77, 0x52, 0xb4, 0x1a, 0x03, 0x7a, 0x03, 0x0b, 0xd6, 0xe7, 0x22, 0xcd, 0x56, 0xa5, 0x2a, 0x01, 0x2f, 0x8c, - 0x35, 0x5b, 0xf9, 0x8d, 0xcc, 0x90, 0x84, 0x79, 0x9c, 0x89, 0xb7, 0x74, 0xaf, 0x85, 0xc9, 0x71, 0x2a, 0x92, 0x29, - 0xa1, 0x53, 0xba, 0xb3, 0x0d, 0x9d, 0xab, 0x30, 0x8a, 0x68, 0xad, 0xa4, 0xd2, 0x48, 0x60, 0x6a, 0x06, 0x28, 0x99, - 0x2b, 0x70, 0x4a, 0x97, 0xfb, 0xdf, 0x89, 0x18, 0x67, 0xbe, 0x28, 0x99, 0x01, 0xdd, 0xf2, 0xeb, 0x62, 0xd3, 0x4a, - 0x91, 0x11, 0xe6, 0xcd, 0x69, 0x7b, 0x5d, 0x1f, 0x02, 0xb9, 0x5a, 0x0e, 0x28, 0x1a, 0x07, 0x85, 0x0e, 0x97, 0x2a, - 0x01, 0xf6, 0x45, 0xe2, 0x67, 0x84, 0x2d, 0xed, 0x81, 0xdc, 0x1e, 0x9d, 0x09, 0x73, 0xc9, 0x49, 0x59, 0x76, 0x29, - 0xcd, 0xe0, 0x72, 0xe2, 0x4a, 0x70, 0x91, 0xde, 0xae, 0xa7, 0x49, 0x4b, 0xdb, 0xc7, 0x86, 0x73, 0x34, 0xb4, 0x0d, - 0xba, 0x63, 0x7f, 0x68, 0x2e, 0x16, 0xb1, 0x75, 0xb1, 0x18, 0x76, 0x66, 0x3f, 0x59, 0x2c, 0x40, 0x0e, 0x00, 0x47, - 0xdd, 0x96, 0x8f, 0xd9, 0x12, 0x38, 0xad, 0xa6, 0xd9, 0xd4, 0xdb, 0xf2, 0xfc, 0xa9, 0xea, 0xe9, 0x25, 0xaf, 0x9e, - 0x0a, 0x33, 0x16, 0x5b, 0x5e, 0x3d, 0xb5, 0x8e, 0x9c, 0xfc, 0xa9, 0x50, 0xa2, 0x75, 0x01, 0xcd, 0xc0, 0x6b, 0x0a, - 0x18, 0xb1, 0x64, 0x32, 0xa5, 0x8a, 0x3c, 0xee, 0x4d, 0xb7, 0x6a, 0xf0, 0x82, 0xc2, 0x21, 0x90, 0xd2, 0xe9, 0x57, - 0xcf, 0x98, 0x7e, 0xef, 0xea, 0x59, 0x87, 0xac, 0x6d, 0x98, 0x2e, 0xb7, 0xc3, 0x64, 0x50, 0xfa, 0x4f, 0xcd, 0xc4, - 0xb8, 0xb2, 0x26, 0x09, 0x20, 0xfe, 0x8d, 0xfd, 0x0e, 0x29, 0xdc, 0xbc, 0xbf, 0x1c, 0xc6, 0x8f, 0xbc, 0x1f, 0x23, - 0x7b, 0x92, 0x66, 0x88, 0x35, 0x93, 0x0a, 0xb9, 0xfb, 0x6a, 0xfd, 0x63, 0x62, 0x37, 0xd9, 0x03, 0x0b, 0x40, 0x6c, - 0x4d, 0x5b, 0xdd, 0xf2, 0x7e, 0xdf, 0x33, 0x45, 0x80, 0x1f, 0x94, 0x7f, 0x72, 0x67, 0x48, 0x06, 0x65, 0xd7, 0x0d, - 0x21, 0x1e, 0x94, 0x4d, 0xd3, 0x5e, 0x6f, 0x07, 0x67, 0x1e, 0xab, 0xeb, 0xb4, 0xb3, 0xb8, 0x5a, 0x64, 0x90, 0x56, - 0x1f, 0xb2, 0xd3, 0xcc, 0x3e, 0x3b, 0x59, 0x2a, 0xdd, 0xef, 0x43, 0x44, 0xdc, 0x49, 0xd6, 0xf6, 0xdb, 0x2d, 0xb8, - 0x86, 0x93, 0x41, 0xe8, 0xca, 0xde, 0x2e, 0xa3, 0x8d, 0x0b, 0x71, 0xda, 0x33, 0x9d, 0x2f, 0xf8, 0xf2, 0x28, 0xed, - 0x3c, 0x38, 0xd5, 0x13, 0x7d, 0x6e, 0xba, 0xab, 0x4c, 0xae, 0x75, 0x58, 0x8d, 0x41, 0x6d, 0x16, 0xb6, 0x70, 0x17, - 0xb6, 0xd1, 0x41, 0x6b, 0x5f, 0x16, 0xfc, 0x53, 0x06, 0xe0, 0x4b, 0xcf, 0x96, 0x5d, 0xaf, 0x49, 0xab, 0xd7, 0x32, - 0x0a, 0xb1, 0xa5, 0xed, 0xd5, 0xa7, 0xa3, 0x7c, 0xdc, 0x9c, 0x51, 0x5c, 0xc8, 0x51, 0x7e, 0xf4, 0x1a, 0xa2, 0xae, - 0x75, 0x1d, 0x17, 0x8b, 0x0e, 0x37, 0xae, 0xba, 0xed, 0xc6, 0xf5, 0x23, 0xe2, 0xad, 0xd1, 0x26, 0x85, 0x5a, 0x19, - 0x3b, 0x82, 0x97, 0x55, 0xc3, 0x21, 0x13, 0xc3, 0xa1, 0x84, 0x4c, 0x7d, 0xec, 0xde, 0xd0, 0xb4, 0xcf, 0x4f, 0x5b, - 0x3f, 0x62, 0xa9, 0x71, 0x14, 0x1b, 0xde, 0xf9, 0x3b, 0x8f, 0xad, 0x71, 0x25, 0x5f, 0x06, 0xb3, 0x5d, 0x41, 0xb5, - 0x35, 0xde, 0xb0, 0x57, 0xf1, 0x1f, 0x72, 0xa9, 0xe4, 0x6f, 0x7f, 0x86, 0x6b, 0x78, 0x6b, 0x4b, 0x07, 0x4d, 0x35, - 0xab, 0x98, 0xb9, 0x17, 0x9c, 0x7e, 0xdc, 0xbd, 0x22, 0x18, 0xfc, 0x9e, 0x8e, 0x82, 0x5c, 0x2c, 0xd5, 0x1a, 0x50, - 0x90, 0x4e, 0xec, 0x98, 0xca, 0x02, 0xc3, 0x00, 0xde, 0x90, 0x01, 0xf2, 0x98, 0xc2, 0xdd, 0x50, 0xe1, 0x85, 0xbf, - 0xe4, 0x64, 0x97, 0xc0, 0xb6, 0x66, 0x7c, 0xcc, 0x70, 0x07, 0x21, 0xff, 0x08, 0xb6, 0x62, 0x6b, 0x76, 0xc7, 0x16, - 0x0c, 0xc9, 0xc6, 0x71, 0x18, 0x63, 0x3e, 0x9e, 0xc4, 0x37, 0x62, 0x12, 0x0f, 0x78, 0x84, 0x8e, 0x11, 0x1b, 0x5e, - 0xcf, 0x62, 0x39, 0x80, 0x6c, 0xc5, 0x95, 0x0e, 0x08, 0xa1, 0xb1, 0xa1, 0x25, 0xaf, 0x0b, 0x83, 0x8b, 0x1d, 0xfb, - 0x2c, 0x47, 0x91, 0x8c, 0x43, 0xb0, 0x68, 0x55, 0x03, 0x0b, 0x13, 0xbb, 0xe3, 0xc5, 0x6c, 0x3d, 0xc7, 0x7f, 0x8e, - 0x47, 0x04, 0xc0, 0x0e, 0x0e, 0x0d, 0x5b, 0x45, 0x88, 0xf4, 0xb6, 0xe0, 0x2b, 0xcb, 0xd3, 0x85, 0xdd, 0xf3, 0xb7, - 0x7c, 0xcc, 0x2e, 0x7f, 0xf4, 0x20, 0x72, 0xf6, 0xf2, 0x23, 0xa0, 0x21, 0xde, 0xf3, 0xbb, 0xd4, 0xcb, 0xd9, 0x1d, - 0x51, 0x10, 0xde, 0x81, 0x33, 0xd0, 0x3d, 0x44, 0xc0, 0xbe, 0xe5, 0x0b, 0x8c, 0x15, 0xbb, 0x48, 0x97, 0x1e, 0x66, - 0x84, 0xda, 0xd3, 0xf9, 0xb2, 0x51, 0x93, 0x70, 0x7b, 0xb3, 0x9c, 0x0c, 0x06, 0x5b, 0x7f, 0xcf, 0x37, 0xc0, 0x07, - 0x73, 0xf9, 0xa3, 0xb7, 0xa7, 0x72, 0xe1, 0x3f, 0xaf, 0xb3, 0xe4, 0xbd, 0xcf, 0xde, 0x0e, 0xf8, 0x02, 0xf0, 0x96, - 0xd0, 0x81, 0xeb, 0xde, 0x67, 0x12, 0xaf, 0xed, 0xad, 0xbe, 0x46, 0x20, 0x91, 0x2f, 0x00, 0x23, 0x26, 0xe6, 0xf7, - 0x5b, 0x88, 0xc0, 0x48, 0xc0, 0xb7, 0x55, 0x7b, 0xc4, 0xef, 0xb8, 0x01, 0xfc, 0xca, 0x7c, 0xf6, 0xc0, 0x43, 0xfd, - 0x33, 0xf1, 0xd9, 0x2d, 0x7f, 0xcf, 0x9f, 0x7b, 0x52, 0x92, 0x2e, 0x67, 0xef, 0xe7, 0x70, 0x3d, 0x94, 0xf2, 0x74, - 0x48, 0x3f, 0x1b, 0x83, 0x01, 0x84, 0x42, 0xe6, 0xad, 0x07, 0xac, 0x49, 0x21, 0xfe, 0x05, 0x7c, 0x3b, 0x4a, 0xd8, - 0xbc, 0xf5, 0x76, 0xbe, 0x96, 0x37, 0x6f, 0xbd, 0x07, 0x9f, 0xa2, 0x00, 0xab, 0xa0, 0x94, 0x05, 0x56, 0x41, 0xd8, - 0x68, 0x23, 0x8c, 0x81, 0xab, 0x77, 0x8d, 0xa1, 0xae, 0xe7, 0x88, 0x6d, 0x2b, 0x7d, 0x17, 0xbe, 0x83, 0x0c, 0xf8, - 0xe0, 0x75, 0x51, 0x12, 0x7d, 0x4e, 0x4d, 0x91, 0xb4, 0xee, 0xb9, 0xdf, 0x5a, 0x77, 0xb4, 0xa6, 0xd4, 0x47, 0x6e, - 0xc6, 0xc7, 0x63, 0xfd, 0x5c, 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, 0xd7, 0xc3, 0xda, - 0x9f, 0x38, 0xb5, 0xb0, 0xb4, 0x9a, 0x83, 0xfa, 0xa9, 0x2d, 0xc7, 0xa9, 0xaa, 0xfd, 0x4b, 0x92, 0x54, 0xbb, 0x4a, - 0xcb, 0xe9, 0xbd, 0x7d, 0xd3, 0x65, 0x82, 0x8d, 0xfd, 0x80, 0xaa, 0x23, 0xab, 0x61, 0xf7, 0x85, 0xfa, 0xa2, 0xa7, - 0x64, 0x42, 0xf3, 0x51, 0x45, 0xf3, 0xec, 0x7e, 0xb3, 0xa3, 0xfe, 0xd3, 0xeb, 0xa1, 0x08, 0x90, 0xac, 0xd2, 0x62, - 0x29, 0x72, 0x36, 0xf6, 0xd3, 0x61, 0x92, 0xa9, 0xf0, 0x82, 0x74, 0x74, 0xf7, 0x1b, 0xf7, 0xb7, 0xdc, 0x40, 0xd6, - 0x68, 0xd5, 0x06, 0x63, 0xa5, 0x68, 0x19, 0xac, 0x6f, 0xc6, 0xfd, 0xbe, 0xb8, 0x19, 0x4f, 0x45, 0x50, 0x03, 0x71, - 0x91, 0x78, 0x3e, 0x9e, 0xd6, 0xc4, 0x92, 0xda, 0x15, 0x18, 0xa3, 0xc7, 0x55, 0x51, 0xfb, 0xd4, 0xcf, 0x21, 0x14, - 0xa9, 0xd6, 0xcc, 0xb1, 0xc6, 0x8d, 0x11, 0x71, 0x87, 0x95, 0x6b, 0xa7, 0xf6, 0x3a, 0x00, 0xcb, 0xab, 0x71, 0x41, - 0xd8, 0x26, 0xa7, 0xce, 0x05, 0xac, 0x46, 0x43, 0xaa, 0xdd, 0x70, 0xeb, 0x65, 0xe7, 0x37, 0x8f, 0x13, 0x5b, 0x1b, - 0xe1, 0x96, 0x02, 0xca, 0x28, 0xbf, 0xb1, 0x9c, 0xb0, 0x3b, 0xd5, 0x3b, 0x52, 0xb5, 0x23, 0xce, 0x5c, 0xc0, 0x2a, - 0xc3, 0x53, 0xab, 0x6f, 0x62, 0x70, 0x22, 0xe4, 0xad, 0x74, 0xbc, 0xf6, 0x23, 0xee, 0x57, 0xf7, 0x75, 0xaf, 0x04, - 0x3f, 0x09, 0x79, 0xfd, 0x96, 0x77, 0x00, 0x58, 0xf1, 0x21, 0x2f, 0xa6, 0x85, 0xa3, 0x75, 0x19, 0x94, 0x01, 0x22, - 0x34, 0x03, 0xa0, 0x93, 0xab, 0x83, 0x28, 0x0d, 0x5c, 0x71, 0x87, 0x08, 0x3f, 0x8d, 0x9e, 0x56, 0xcf, 0xc3, 0xa7, - 0xf9, 0x34, 0xbc, 0xaa, 0x82, 0xe8, 0x2a, 0x0f, 0xa2, 0xa7, 0xf9, 0x4d, 0xf8, 0xb4, 0x9a, 0x46, 0x57, 0x55, 0x10, - 0x5e, 0xe5, 0x8d, 0x7d, 0xd7, 0xee, 0xee, 0x09, 0x79, 0xdb, 0xd5, 0x1f, 0xb9, 0x54, 0xf6, 0x94, 0xe9, 0xe5, 0x65, - 0xad, 0x57, 0x6a, 0xb7, 0xb9, 0x5e, 0xa3, 0x66, 0xea, 0xa3, 0xec, 0x2f, 0xb6, 0xb1, 0xf0, 0x64, 0x0e, 0xa1, 0xcf, - 0x48, 0x8b, 0xb9, 0xc7, 0xb9, 0xde, 0x1c, 0x48, 0x61, 0x60, 0xc4, 0xa4, 0x92, 0x91, 0xd3, 0x0b, 0x5c, 0x84, 0x72, - 0xc4, 0xb0, 0x96, 0xae, 0xf6, 0x59, 0x97, 0xde, 0x40, 0x5d, 0x53, 0xec, 0x6b, 0xc8, 0xc0, 0x8b, 0xa6, 0xd7, 0xc1, - 0x18, 0x90, 0x23, 0xf0, 0x8e, 0xcf, 0x96, 0x70, 0x60, 0x6e, 0x00, 0xfa, 0xe6, 0x51, 0x5f, 0x97, 0x15, 0xdf, 0xa8, - 0xbe, 0x99, 0x6e, 0x46, 0x4a, 0xf9, 0xb1, 0xe6, 0xab, 0xab, 0x67, 0xec, 0x8e, 0x6b, 0x54, 0x94, 0x5f, 0xf4, 0x62, - 0xbd, 0x07, 0xae, 0xba, 0x5f, 0xe0, 0x36, 0x8b, 0xc7, 0xae, 0x3c, 0x60, 0xd9, 0x8e, 0x3d, 0xb0, 0x5b, 0xf6, 0x9e, - 0x3d, 0x61, 0x6f, 0xd8, 0x17, 0xf6, 0x13, 0xaa, 0x36, 0x94, 0x90, 0xe7, 0x2f, 0xf8, 0x9d, 0x34, 0x3d, 0x4a, 0x54, - 0xb2, 0x07, 0xdb, 0x4c, 0x33, 0xdc, 0xb2, 0xf7, 0x7c, 0x31, 0x5c, 0xb3, 0x37, 0x90, 0x0d, 0x65, 0xe2, 0xc1, 0x9a, - 0xfd, 0xc4, 0x15, 0x88, 0x99, 0x3e, 0x0b, 0x4b, 0x4b, 0x54, 0x34, 0x65, 0xa2, 0x0c, 0xfd, 0x86, 0xe3, 0x8b, 0xec, - 0x27, 0x2c, 0x42, 0x7e, 0x66, 0xb8, 0x66, 0x0f, 0x7c, 0x31, 0x58, 0xb3, 0xf7, 0xda, 0x40, 0x34, 0xd8, 0xba, 0xa5, - 0x11, 0x92, 0x95, 0x2e, 0x4b, 0x4a, 0xd3, 0x3b, 0xfb, 0x1a, 0xb8, 0x65, 0xb7, 0x58, 0xbb, 0x27, 0x58, 0x34, 0x0a, - 0xfc, 0x83, 0x35, 0xfb, 0xc2, 0x25, 0x80, 0x9a, 0x5b, 0x9e, 0xf4, 0x0a, 0xd5, 0x05, 0xd2, 0xfd, 0xe0, 0x09, 0xa7, - 0x17, 0xd9, 0x17, 0x2c, 0x83, 0xbe, 0x32, 0x5c, 0xb3, 0x1d, 0xd6, 0xee, 0xd6, 0x58, 0xb6, 0xac, 0xea, 0x49, 0x44, - 0x60, 0x14, 0x54, 0x4a, 0xcb, 0xbf, 0x11, 0xcb, 0xa6, 0x6e, 0x1a, 0xd4, 0x86, 0xfe, 0x7c, 0x30, 0xfa, 0x0f, 0x5f, - 0xbf, 0xfb, 0xc1, 0x2b, 0xf5, 0xb5, 0xf7, 0x17, 0xc7, 0xb5, 0xb2, 0x44, 0xd7, 0xca, 0x5f, 0x79, 0x39, 0xfb, 0x65, - 0x3e, 0xd1, 0xb5, 0xa4, 0x1d, 0x86, 0x7c, 0x4d, 0x67, 0xbf, 0x74, 0x38, 0x5b, 0xfe, 0xea, 0xfb, 0x8d, 0xe9, 0x62, - 0xf5, 0x59, 0xdd, 0xbb, 0x0f, 0x83, 0x6d, 0xe3, 0xd4, 0x7b, 0x7f, 0xbe, 0xde, 0xd8, 0xcc, 0x5a, 0x7b, 0x66, 0xfe, - 0x0f, 0x57, 0x7a, 0x87, 0x43, 0x77, 0xcb, 0x77, 0xc3, 0xad, 0x3d, 0x0a, 0xf2, 0xfb, 0x52, 0x69, 0x9c, 0xd5, 0xfc, - 0x85, 0x97, 0x77, 0x49, 0xb1, 0x80, 0x68, 0xf4, 0xc9, 0x48, 0x42, 0xd7, 0xcc, 0xc4, 0x33, 0xc4, 0x57, 0x19, 0x20, - 0x73, 0x81, 0x68, 0x76, 0xcf, 0xc7, 0x93, 0xfb, 0x9b, 0x78, 0x72, 0x3f, 0xe0, 0x9f, 0x4c, 0x0b, 0xda, 0x8b, 0xed, - 0xde, 0x67, 0xbf, 0xf2, 0xc2, 0x5e, 0x8e, 0xbf, 0xf8, 0xec, 0x9d, 0x70, 0x57, 0xe8, 0x2f, 0x3e, 0xfb, 0x22, 0xf8, - 0xaf, 0x23, 0x4d, 0x94, 0xc1, 0xbe, 0xd4, 0xfc, 0xd7, 0x11, 0x32, 0x7e, 0xb0, 0xcf, 0x82, 0xbf, 0x03, 0xdf, 0xef, - 0x2a, 0x41, 0xab, 0xf8, 0xe7, 0x5a, 0xfd, 0x7c, 0x2f, 0xe3, 0x72, 0xe0, 0x4d, 0x68, 0x05, 0xbd, 0x79, 0x57, 0xcb, - 0x9f, 0xc4, 0xc3, 0x91, 0xaa, 0xa7, 0x86, 0x7f, 0x16, 0x8b, 0x59, 0xd4, 0x27, 0xe9, 0x54, 0xde, 0xe4, 0x2d, 0xcf, - 0xa4, 0x75, 0xf9, 0x1e, 0x42, 0x81, 0xdf, 0xda, 0x10, 0x05, 0x7b, 0x8e, 0x1b, 0xc1, 0x5b, 0x06, 0xf0, 0x91, 0xd9, - 0x74, 0xc7, 0x6f, 0xf9, 0x13, 0xfe, 0x85, 0xef, 0x83, 0x07, 0xfe, 0x9e, 0xbf, 0xe1, 0x3f, 0xf1, 0x3d, 0x5b, 0x4a, - 0xb4, 0xd3, 0x7a, 0x77, 0x1d, 0xec, 0x58, 0xbd, 0xbf, 0x0e, 0x1e, 0x58, 0xbd, 0x7b, 0x16, 0xdc, 0xb2, 0x7a, 0xff, - 0x2c, 0x78, 0xcf, 0x76, 0xd7, 0xc1, 0x13, 0xb6, 0xbf, 0x0e, 0xde, 0xb0, 0xdd, 0xb3, 0xe0, 0x0b, 0xdb, 0x3f, 0x0b, - 0x7e, 0x92, 0x18, 0x0f, 0x5f, 0x84, 0xe4, 0x38, 0xf9, 0x52, 0x33, 0xc3, 0xa7, 0x1b, 0x7c, 0x16, 0xd6, 0x2f, 0xaa, - 0x63, 0xf0, 0xb9, 0x66, 0xba, 0xc5, 0x81, 0x10, 0x4c, 0xb7, 0x37, 0xb8, 0xa3, 0x27, 0xa6, 0x55, 0x41, 0x2a, 0x58, - 0x57, 0x3b, 0x83, 0x45, 0xdd, 0xb4, 0xce, 0x64, 0xc7, 0x2f, 0x31, 0xee, 0xf0, 0x4b, 0x5c, 0xb0, 0x65, 0xd3, 0xe9, - 0xa4, 0x73, 0xfe, 0x24, 0xd0, 0x9b, 0xbf, 0xde, 0xf5, 0x73, 0xe9, 0x3b, 0x53, 0x34, 0x5c, 0x6b, 0x8d, 0x5b, 0x3b, - 0x7d, 0x68, 0xed, 0xf4, 0x4c, 0xaa, 0xd0, 0x22, 0x16, 0x95, 0x45, 0x55, 0x21, 0x93, 0x78, 0x90, 0x69, 0x7d, 0x5a, - 0xc2, 0x48, 0x91, 0x09, 0x68, 0xf4, 0x05, 0x1d, 0x03, 0x15, 0x59, 0x14, 0xd8, 0x92, 0x6f, 0x07, 0x09, 0xdb, 0xf0, - 0x78, 0x3a, 0x4c, 0x82, 0x25, 0x5b, 0xf1, 0x61, 0xb7, 0x40, 0xb0, 0x56, 0x01, 0x4c, 0xfa, 0xe2, 0xd4, 0xde, 0xd7, - 0x79, 0x6f, 0x9d, 0xc6, 0x71, 0x26, 0x50, 0xd9, 0x96, 0xeb, 0x0d, 0x7e, 0xe7, 0xec, 0xe7, 0x1b, 0xb5, 0xbf, 0x83, - 0xa4, 0xf0, 0x2b, 0x30, 0xec, 0x10, 0xe1, 0x1d, 0x54, 0x18, 0x79, 0x96, 0xcc, 0xa2, 0xcf, 0xed, 0x2d, 0x7d, 0x67, - 0xb6, 0xe9, 0x7f, 0xb7, 0x08, 0xda, 0xc7, 0x65, 0xe7, 0x7f, 0x32, 0xaf, 0xfe, 0xd6, 0xf1, 0xea, 0xd6, 0x9f, 0x3c, - 0xf0, 0x4f, 0x18, 0x96, 0x80, 0x89, 0x6c, 0xcf, 0x3f, 0x8d, 0x76, 0x8d, 0x53, 0x9e, 0xdc, 0xc7, 0xff, 0xaf, 0x14, - 0x68, 0xef, 0xe4, 0xb9, 0xbd, 0x23, 0xee, 0x78, 0xc7, 0x3e, 0xbe, 0xb4, 0x36, 0x44, 0x03, 0x4d, 0xf2, 0x89, 0xbb, - 0xd1, 0xd0, 0xb0, 0x21, 0xfe, 0xc2, 0xf3, 0xd9, 0xa7, 0xf9, 0x64, 0xc7, 0x4f, 0xb7, 0xc3, 0x4f, 0x1d, 0xdb, 0xe1, - 0x2f, 0xfe, 0x60, 0xd9, 0x7c, 0xad, 0x57, 0x3b, 0xb7, 0x71, 0xa7, 0xd2, 0x7b, 0x7e, 0xba, 0x89, 0x0f, 0xff, 0xed, - 0x4a, 0xef, 0xbf, 0xb9, 0xd2, 0x76, 0x95, 0xbb, 0x3b, 0xdf, 0x74, 0x7c, 0x23, 0x6b, 0x8d, 0x71, 0x66, 0x46, 0xb3, + 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, 0x58, 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, 0x1f, 0x55, 0x36, 0x76, 0x07, 0xe4, 0x90, 0x64, 0xb2, 0xb8, 0x1b, 0xdd, + 0x8a, 0x65, 0x51, 0x8a, 0x9f, 0xb1, 0x1e, 0xae, 0xd9, 0xc2, 0x7d, 0x06, 0x84, 0xf6, 0x13, 0xa5, 0xbd, 0x89, 0x34, + 0x41, 0xf7, 0x1d, 0x5b, 0x01, 0xc8, 0x00, 0x8a, 0xba, 0xda, 0xad, 0xcf, 0xf9, 0x39, 0x92, 0x66, 0x38, 0x8c, 0x6e, + 0x9f, 0xde, 0x05, 0x77, 0x83, 0x4b, 0xd4, 0x4a, 0x5f, 0xb2, 0xb8, 0x85, 0x41, 0xb5, 0x37, 0x4b, 0x38, 0xa8, 0x99, + 0xb5, 0x36, 0x02, 0xc1, 0x64, 0x0f, 0x05, 0x15, 0x73, 0x05, 0xfb, 0xa0, 0x60, 0x2d, 0x79, 0x1d, 0x1c, 0x6e, 0xed, + 0xcb, 0x4a, 0x71, 0xf1, 0xfc, 0x22, 0x69, 0x5d, 0x58, 0xca, 0x8b, 0xe7, 0x0d, 0x18, 0x5c, 0x8e, 0xb0, 0xa9, 0x2a, + 0x7f, 0xb2, 0x01, 0xd0, 0xad, 0x90, 0x22, 0x5e, 0x94, 0xc2, 0xb6, 0x95, 0xcf, 0x9c, 0xb0, 0xc1, 0x86, 0x3d, 0xc0, + 0xbd, 0x32, 0x28, 0x19, 0x5c, 0x88, 0x71, 0xbb, 0xd9, 0x05, 0xb8, 0x82, 0xa1, 0x30, 0xb6, 0xe6, 0x6f, 0x32, 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, 0x7c, 0xce, 0xbc, 0xa5, 0xcf, 0xde, 0x54, 0x32, 0x5a, 0x93, 0x44, + 0x79, 0xf5, 0x70, 0x09, 0x72, 0xc3, 0x72, 0xf4, 0xc0, 0x96, 0x20, 0x4e, 0x2c, 0x47, 0x09, 0x65, 0x74, 0x85, 0x7b, + 0x95, 0xd9, 0x32, 0x11, 0x48, 0x71, 0x60, 0x29, 0xe5, 0xde, 0x62, 0x1d, 0x2c, 0x71, 0x7f, 0x22, 0xb9, 0x80, 0x92, + 0x07, 0x50, 0xae, 0x14, 0x10, 0xf0, 0xe9, 0x00, 0xca, 0x97, 0xf2, 0x22, 0xfc, 0x89, 0x13, 0x35, 0x58, 0x8e, 0x1e, + 0x1a, 0xf6, 0xa3, 0x17, 0x5a, 0xf6, 0x87, 0x3b, 0xad, 0x69, 0x58, 0xf1, 0x3b, 0x98, 0x16, 0x13, 0xb7, 0x2f, 0x57, + 0x76, 0x55, 0x7c, 0xb6, 0x52, 0x67, 0x37, 0x35, 0x24, 0x61, 0x5f, 0x91, 0x55, 0x80, 0x83, 0x55, 0x11, 0xf7, 0x2c, + 0xcb, 0x7d, 0x18, 0xfd, 0xb9, 0x49, 0x4b, 0x61, 0xa1, 0x4a, 0xfa, 0xfb, 0xa6, 0x14, 0x48, 0x65, 0xa2, 0x13, 0x2d, + 0x04, 0x57, 0x60, 0x10, 0xb8, 0x17, 0x79, 0x0d, 0x80, 0x31, 0xe0, 0x52, 0xa0, 0x2c, 0xdb, 0x12, 0x42, 0xaa, 0xfb, + 0x19, 0xa8, 0xed, 0xc4, 0x7d, 0x1a, 0x91, 0xb5, 0x10, 0x7d, 0x15, 0x8c, 0x99, 0xf3, 0x52, 0xba, 0xc5, 0xa6, 0xab, + 0xcd, 0xea, 0x06, 0x9d, 0x4b, 0x5b, 0x6e, 0x7e, 0xc2, 0x16, 0x6b, 0x05, 0xca, 0x26, 0x24, 0x6d, 0xe7, 0x3c, 0x47, + 0xd9, 0x84, 0x96, 0xf6, 0x9e, 0x7a, 0x54, 0xa8, 0x4e, 0xb6, 0x5e, 0xaa, 0xa6, 0x16, 0x61, 0xb5, 0xb8, 0xa8, 0xfc, + 0x00, 0x74, 0x53, 0x69, 0xf5, 0xb2, 0xae, 0xd1, 0x14, 0x6a, 0xb5, 0x70, 0xdc, 0x68, 0x67, 0xd3, 0x65, 0x7a, 0x87, + 0x38, 0xab, 0xd2, 0x0e, 0xfd, 0x7d, 0xa6, 0x5d, 0x2f, 0x3b, 0xfa, 0xcd, 0xb8, 0xba, 0xc0, 0x85, 0xd8, 0x80, 0xcf, + 0xb9, 0xbf, 0xbc, 0xde, 0xf3, 0xb8, 0xe7, 0x1f, 0x0e, 0xc8, 0x9e, 0xd4, 0xfe, 0x50, 0x7d, 0xec, 0x0a, 0x86, 0x2c, + 0x8c, 0x52, 0x7f, 0x91, 0xf2, 0xde, 0x13, 0x1c, 0xf7, 0xcf, 0x55, 0x8f, 0xfd, 0x98, 0xf1, 0x7d, 0x5d, 0x6c, 0xa2, + 0x84, 0xa2, 0x1a, 0x7a, 0xab, 0x62, 0x53, 0x89, 0xb8, 0x78, 0xc8, 0x7b, 0x0c, 0x93, 0x61, 0x2c, 0x64, 0x2a, 0xfc, + 0x29, 0x53, 0xc1, 0x23, 0x84, 0x12, 0x37, 0xeb, 0x1e, 0x69, 0x37, 0x21, 0x4e, 0xa9, 0x16, 0xa5, 0x4c, 0xc6, 0xbf, + 0xf5, 0x13, 0x28, 0xcf, 0x29, 0x5a, 0xa6, 0x1f, 0x15, 0x2e, 0xd3, 0x37, 0xeb, 0xe3, 0xd2, 0x33, 0x11, 0xea, 0xcc, + 0xc5, 0xa6, 0xd6, 0xe9, 0x18, 0x3b, 0xa5, 0x53, 0x1b, 0xf6, 0xa5, 0x52, 0x5c, 0x56, 0x14, 0xfe, 0x8d, 0x44, 0x56, + 0x3d, 0x23, 0x8e, 0xff, 0x2b, 0x6b, 0x9f, 0x61, 0x15, 0xf8, 0x65, 0x20, 0xef, 0x17, 0x00, 0x1f, 0xd7, 0x75, 0x99, + 0xde, 0x6e, 0x80, 0x36, 0x84, 0x86, 0xbf, 0xe7, 0x23, 0x03, 0xa6, 0xfb, 0x08, 0x67, 0x48, 0x0f, 0x75, 0xce, 0xe9, + 0xac, 0x4c, 0xe7, 0x5c, 0x85, 0xb5, 0x04, 0x7b, 0x39, 0x69, 0x72, 0xb9, 0x2e, 0x41, 0xcd, 0x04, 0x6e, 0x1f, 0xda, + 0x23, 0x42, 0xa8, 0x4d, 0x59, 0x4d, 0x2f, 0xa1, 0xe6, 0x9d, 0x9c, 0x76, 0x34, 0x29, 0xc1, 0x55, 0x43, 0x67, 0xe5, + 0xfa, 0xaf, 0xc3, 0xa1, 0x77, 0x9b, 0x15, 0xd1, 0x1f, 0x3d, 0xf4, 0x77, 0xdc, 0xde, 0xa4, 0x5f, 0x20, 0x5a, 0xc6, + 0xfa, 0x1b, 0x32, 0xa0, 0xe3, 0xc9, 0xf0, 0xb6, 0xd8, 0xf6, 0xd8, 0x17, 0xd4, 0x60, 0xe9, 0xeb, 0xc7, 0x1f, 0x20, + 0xa1, 0xea, 0xda, 0x17, 0x16, 0x4f, 0x98, 0xa7, 0x44, 0xdb, 0xc2, 0x87, 0xb0, 0xd0, 0x2f, 0x10, 0x19, 0x09, 0xe1, + 0xa6, 0xb2, 0x7b, 0x94, 0xb4, 0x0b, 0x7d, 0xe9, 0x6b, 0xd9, 0x57, 0xbe, 0x73, 0x01, 0xb0, 0xb2, 0xcf, 0x6d, 0xb8, + 0x27, 0xfd, 0x29, 0xd5, 0x87, 0xed, 0x6f, 0xc9, 0x02, 0x0a, 0x2d, 0xac, 0xa7, 0x72, 0x76, 0xae, 0x4b, 0x9e, 0x66, + 0xd3, 0xfd, 0x1a, 0xf6, 0xa8, 0x7b, 0xf4, 0x9a, 0x0a, 0xce, 0x2f, 0xcd, 0xe8, 0xfd, 0xd3, 0x50, 0xa8, 0x8e, 0x3a, + 0x77, 0x90, 0x75, 0x69, 0x5d, 0x72, 0x7e, 0xb3, 0x72, 0x47, 0x61, 0x7e, 0x1f, 0x82, 0x67, 0x58, 0xf7, 0xee, 0xe2, + 0xbc, 0xf7, 0x67, 0x6b, 0x8e, 0xfc, 0x98, 0xcd, 0x52, 0xc4, 0x22, 0x99, 0x83, 0xd5, 0x0f, 0xfd, 0x3c, 0xf6, 0xdb, + 0x20, 0x87, 0xe3, 0xa6, 0x01, 0x1d, 0x36, 0x64, 0xd6, 0xbe, 0x44, 0xe0, 0x54, 0x23, 0x48, 0x53, 0x13, 0xd4, 0x2c, + 0x0f, 0x91, 0xd8, 0x2e, 0x65, 0xdb, 0x20, 0xd7, 0x5d, 0x30, 0xcd, 0x91, 0xf6, 0x0c, 0xde, 0x37, 0x69, 0x92, 0x0a, + 0xcd, 0x22, 0x6d, 0x95, 0x8c, 0x7f, 0x47, 0xda, 0x4c, 0xc9, 0x1e, 0x5b, 0x03, 0xef, 0x25, 0x28, 0x27, 0xc3, 0x14, + 0xc3, 0x77, 0x7c, 0xbd, 0xf3, 0x98, 0x7b, 0xce, 0x31, 0xdb, 0xa4, 0xec, 0x08, 0x26, 0xc9, 0xc6, 0x37, 0x14, 0x6f, + 0xf8, 0xfe, 0xb6, 0x12, 0x25, 0x80, 0x5e, 0x16, 0xfc, 0x85, 0xb4, 0xb9, 0x42, 0xb7, 0xbb, 0x77, 0x94, 0xc2, 0x2f, + 0x79, 0x79, 0x38, 0x6c, 0x53, 0x2f, 0x84, 0xce, 0x17, 0xf1, 0x3b, 0x30, 0x87, 0x31, 0xc4, 0x66, 0x04, 0x08, 0x73, + 0x7c, 0x40, 0x1d, 0xac, 0x1f, 0x01, 0x68, 0x9c, 0x40, 0x01, 0x46, 0x5f, 0x6d, 0x0b, 0xfa, 0x96, 0x17, 0x17, 0x11, + 0xa2, 0x46, 0x01, 0x26, 0x4a, 0x9a, 0xc5, 0x30, 0x1c, 0xe8, 0xfc, 0xbe, 0xb9, 0xad, 0x4b, 0x81, 0x43, 0xef, 0x58, + 0x86, 0xff, 0xfe, 0x3f, 0xd6, 0x96, 0x56, 0x95, 0xed, 0xd6, 0x38, 0xcd, 0xfc, 0x6f, 0xb7, 0x85, 0xbe, 0xff, 0x4a, + 0x28, 0x9e, 0x77, 0xbc, 0x6e, 0xbf, 0x83, 0xe8, 0x7d, 0xdd, 0xca, 0xbb, 0x52, 0xbb, 0x61, 0xa6, 0xfc, 0x21, 0xcd, + 0xe3, 0xe2, 0x61, 0x14, 0xb7, 0x8e, 0xbc, 0x49, 0x7a, 0xce, 0xf9, 0xbb, 0xaa, 0xdf, 0xf7, 0xde, 0x01, 0x19, 0xef, + 0x2b, 0x61, 0x1c, 0x31, 0x89, 0x83, 0x6f, 0x2f, 0x46, 0xd1, 0xa6, 0x84, 0x0d, 0xb9, 0x7d, 0x5a, 0x82, 0x66, 0xa6, + 0xdf, 0x47, 0x89, 0xd2, 0x9a, 0xef, 0x7f, 0x93, 0xf3, 0xfd, 0x95, 0x90, 0x37, 0x2b, 0xf9, 0xe1, 0xa3, 0x15, 0x06, + 0xbe, 0xc7, 0xe9, 0x17, 0xd1, 0x63, 0x77, 0xa5, 0x0f, 0xdf, 0x95, 0x96, 0x3e, 0xab, 0xa8, 0x7f, 0xa0, 0xa2, 0xe6, + 0x95, 0x18, 0x11, 0xf1, 0x20, 0x68, 0x67, 0xdb, 0xa5, 0x76, 0x2d, 0x41, 0xbb, 0x60, 0x53, 0xd8, 0xbf, 0x1f, 0x1d, + 0xf2, 0x7e, 0xff, 0x63, 0xee, 0xb5, 0x78, 0xdd, 0x75, 0x68, 0xca, 0x4f, 0x85, 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, 0x11, 0xeb, 0xa6, 0xa7, 0x55, 0x68, 0xf9, 0x1a, 0x82, 0x75, 0x91, 0x65, 0x1c, 0xc5, + 0x4c, 0x00, 0xb0, 0xf9, 0x08, 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, + 0x7b, 0xaa, 0x7a, 0x44, 0xa0, 0x57, 0x65, 0x5a, 0x45, 0x45, 0x9e, 0x8b, 0x08, 0x11, 0xaa, 0xa5, 0x73, 0x38, 0xf4, + 0x63, 0xbf, 0x8f, 0x03, 0x61, 0x5e, 0xfc, 0xe9, 0xb1, 0xae, 0xfc, 0xa9, 0xc0, 0xb5, 0x92, 0x02, 0xa7, 0xa2, 0x46, + 0x88, 0x10, 0xde, 0x9f, 0xc0, 0xb3, 0x9a, 0xfa, 0x7e, 0x63, 0x99, 0xe8, 0xfe, 0x99, 0x01, 0xe5, 0x0f, 0xc8, 0xd7, + 0x95, 0x14, 0x67, 0xea, 0xe4, 0x31, 0x71, 0xc6, 0x01, 0x88, 0xf9, 0xba, 0x44, 0xa3, 0xb1, 0xff, 0x01, 0x09, 0x86, + 0xea, 0x07, 0x3b, 0xdd, 0xd4, 0xfb, 0x57, 0x26, 0x71, 0x14, 0x7d, 0xda, 0x26, 0x8f, 0x25, 0x4b, 0xa3, 0x85, 0xa3, + 0xf7, 0x88, 0x61, 0x1c, 0x4e, 0xe7, 0x63, 0x92, 0x6d, 0x4c, 0x56, 0x01, 0xa4, 0x93, 0x99, 0x3a, 0xa6, 0xd4, 0xd1, + 0x38, 0xd7, 0x0b, 0xaa, 0xd0, 0x63, 0x5d, 0xf2, 0x1c, 0xac, 0x27, 0x3f, 0x78, 0xa5, 0x3f, 0x15, 0x72, 0x0e, 0x1b, + 0x89, 0xa0, 0xf0, 0x03, 0x5c, 0x0d, 0x56, 0x0a, 0x18, 0x4c, 0x7d, 0x0b, 0x5f, 0x13, 0xcf, 0x51, 0xf0, 0x28, 0xec, + 0x62, 0x6c, 0xad, 0x7c, 0xe7, 0x93, 0x82, 0x72, 0xcf, 0x8a, 0x39, 0xaf, 0x80, 0x73, 0x19, 0x14, 0xc2, 0x74, 0x3c, + 0xcb, 0xff, 0x99, 0xe4, 0xf5, 0xc4, 0x86, 0x00, 0x19, 0xfc, 0x29, 0x71, 0x5a, 0xba, 0x43, 0x77, 0x1e, 0x7a, 0x16, + 0x71, 0xd8, 0xe8, 0xc9, 0xba, 0x2c, 0xb6, 0x29, 0xea, 0x25, 0xcc, 0x0f, 0xe4, 0xe7, 0x2d, 0xf9, 0x3e, 0x44, 0xf1, + 0x36, 0xf8, 0x35, 0x63, 0xb1, 0xc0, 0xbf, 0xfe, 0x9e, 0x31, 0x9a, 0x68, 0xc1, 0xbf, 0xb3, 0x06, 0x89, 0x8a, 0x7f, + 0xca, 0x26, 0x00, 0xeb, 0xc8, 0xd5, 0x87, 0x4f, 0x89, 0xf1, 0xd6, 0x6c, 0x78, 0xe4, 0x9b, 0x15, 0xe8, 0xd4, 0xe7, + 0xee, 0xca, 0xf6, 0x54, 0x35, 0xfe, 0x9e, 0xea, 0x6a, 0xa4, 0xaa, 0x1a, 0x7f, 0x4f, 0xa9, 0x1a, 0xbf, 0x65, 0x14, + 0xbf, 0x53, 0xf9, 0x0c, 0x99, 0x93, 0x4d, 0x4c, 0xd2, 0xe9, 0x7b, 0xc3, 0x89, 0x5d, 0xf6, 0xab, 0xb7, 0x89, 0xcc, + 0x44, 0x0a, 0xb9, 0x37, 0x00, 0x6d, 0xbf, 0xcb, 0x0d, 0xa7, 0xc4, 0xf9, 0xb9, 0x87, 0x2b, 0x36, 0xad, 0x5e, 0xd1, + 0x82, 0x05, 0x36, 0x2f, 0xb3, 0x3c, 0x45, 0x02, 0xdb, 0xa6, 0xcc, 0xfa, 0x73, 0xee, 0x01, 0x04, 0x33, 0xa9, 0x09, + 0x00, 0x69, 0x21, 0x2a, 0x85, 0xc8, 0x5f, 0xe1, 0xac, 0x3e, 0xe7, 0xbd, 0x4d, 0x1e, 0x13, 0x69, 0x75, 0xaf, 0xdf, + 0x4f, 0xcf, 0xd2, 0x9c, 0x82, 0x1a, 0x8e, 0xb3, 0x4e, 0xbf, 0xcf, 0x82, 0x3a, 0x91, 0xab, 0xf4, 0x1f, 0x6e, 0x90, + 0x97, 0xf1, 0x7d, 0xdd, 0xf6, 0xfc, 0x89, 0xfa, 0x7b, 0x67, 0xfd, 0x6d, 0x81, 0xe0, 0x4e, 0x8e, 0xfd, 0x64, 0x55, + 0xca, 0x13, 0xe3, 0xd2, 0xde, 0xf3, 0x9b, 0xba, 0x28, 0xb2, 0x3a, 0x5d, 0x7f, 0x90, 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, 0xe8, 0x40, 0xbd, 0xb4, 0xd2, 0x3e, 0x82, 0x6e, + 0x05, 0x7a, 0x50, 0x0f, 0x7d, 0x9a, 0xb4, 0x2f, 0x24, 0xea, 0xf6, 0x56, 0xa7, 0xd1, 0x1f, 0x15, 0x5c, 0x4e, 0x61, + 0x72, 0xb8, 0xa1, 0x4f, 0xab, 0x70, 0xfb, 0x09, 0x9e, 0xfe, 0x0c, 0x94, 0x5b, 0x87, 0x43, 0x0e, 0x62, 0x0b, 0xb8, + 0x79, 0xac, 0xc2, 0xcf, 0x45, 0x29, 0x23, 0xea, 0xe3, 0x69, 0x01, 0xda, 0xbb, 0x00, 0x1d, 0xb0, 0x34, 0x88, 0x57, + 0x48, 0x9e, 0xb3, 0x11, 0xc0, 0xb2, 0x03, 0xcb, 0x59, 0xc6, 0x29, 0xcc, 0xb3, 0x7c, 0xa1, 0x56, 0xda, 0x59, 0x99, + 0x78, 0x35, 0xcb, 0xc0, 0x59, 0xe0, 0xa2, 0xf2, 0x59, 0xa6, 0x55, 0x4f, 0x55, 0x82, 0x3e, 0xaf, 0xe4, 0x04, 0x57, + 0x82, 0x93, 0x0d, 0xc8, 0x2f, 0x40, 0x92, 0xa6, 0x94, 0x35, 0xe5, 0x8b, 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, 0x3f, + 0x78, 0x4b, 0x7f, 0x3a, 0x0e, 0xc2, 0x21, 0x72, 0x43, 0xc5, 0x1c, 0xd8, 0xd3, 0x80, 0xc5, 0x26, 0xbe, 0xda, 0x4c, + 0xe2, 0xc1, 0xc0, 0xd7, 0x19, 0x8b, 0x59, 0x0c, 0x34, 0xc8, 0xf1, 0xe0, 0x72, 0xae, 0x4f, 0x08, 0xfd, 0x30, 0xa2, + 0x72, 0x54, 0xa0, 0x73, 0x10, 0x0d, 0x96, 0x80, 0xa7, 0xde, 0xca, 0x06, 0x49, 0xc6, 0x24, 0x93, 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, 0x3f, 0xcb, 0x07, 0x8e, 0x3b, 0x2a, 0x69, + 0x08, 0x0c, 0xde, 0x1e, 0xba, 0x9b, 0x19, 0x1a, 0xea, 0xa4, 0x7d, 0x18, 0x87, 0x72, 0x88, 0x55, 0x2b, 0x2e, 0xa4, + 0x37, 0x82, 0x6f, 0x17, 0x8a, 0xb1, 0x6c, 0xec, 0xd2, 0x50, 0x14, 0xfe, 0x0a, 0x60, 0x87, 0xda, 0x5f, 0xa9, 0xe4, + 0x63, 0x64, 0x54, 0xd3, 0x40, 0xc7, 0x00, 0x2c, 0x59, 0x9a, 0x48, 0xaa, 0x48, 0x23, 0xf1, 0x47, 0x66, 0xac, 0xa3, + 0xa6, 0xeb, 0x0b, 0xa6, 0xaa, 0x45, 0xd2, 0xed, 0x4c, 0x62, 0x39, 0x91, 0xa4, 0xb6, 0xfb, 0x88, 0x18, 0x0c, 0x7c, + 0xb0, 0x11, 0xd3, 0x4c, 0x84, 0x23, 0x1e, 0x95, 0xc8, 0xa2, 0xcb, 0x6f, 0xa3, 0x4c, 0xda, 0xbe, 0xac, 0xc8, 0x16, + 0x04, 0xd3, 0x93, 0xe8, 0x83, 0x24, 0xe5, 0x54, 0x24, 0xd2, 0x8c, 0x10, 0xe0, 0xc7, 0x93, 0xf2, 0x4a, 0x7f, 0x0e, + 0x9a, 0x56, 0x82, 0x97, 0x0c, 0x92, 0x47, 0xe2, 0x67, 0x52, 0x30, 0x8b, 0xb1, 0x6a, 0x30, 0xc0, 0x72, 0xaa, 0x67, + 0x8e, 0x49, 0xfa, 0x6f, 0x9d, 0x4e, 0xd8, 0x2f, 0xbd, 0xdc, 0xd6, 0xf2, 0xa6, 0xb9, 0xf7, 0xd2, 0xab, 0x58, 0xaa, + 0x61, 0x19, 0xf4, 0x5f, 0x13, 0xed, 0x82, 0xad, 0x2d, 0x63, 0xc2, 0xaa, 0x1f, 0x40, 0xda, 0x23, 0x5d, 0x5e, 0x35, + 0xcc, 0x99, 0xe0, 0xd1, 0x85, 0x35, 0x0f, 0xa2, 0x0b, 0xe1, 0x23, 0x97, 0xdd, 0x24, 0xb9, 0x1a, 0x4f, 0xfc, 0x70, + 0x30, 0x50, 0x00, 0xb4, 0xb4, 0x4e, 0x8a, 0x41, 0xf8, 0x4c, 0xc8, 0x81, 0x34, 0x3a, 0xaa, 0x02, 0x2c, 0x96, 0xd9, + 0x55, 0x39, 0xc9, 0x06, 0x03, 0x1f, 0xc4, 0xc6, 0xc4, 0x6e, 0x68, 0x36, 0xf7, 0xd9, 0x89, 0x82, 0xac, 0x36, 0x87, + 0xad, 0x99, 0x6e, 0x81, 0x01, 0xc0, 0x20, 0x22, 0x58, 0xee, 0x73, 0x23, 0x1f, 0x51, 0xa7, 0xa7, 0x30, 0x02, 0x82, + 0x5f, 0x4e, 0x04, 0x22, 0x17, 0x09, 0xd4, 0x03, 0xcc, 0x04, 0x98, 0x51, 0xc5, 0xf0, 0x12, 0xd8, 0xc5, 0x73, 0xf3, + 0x8a, 0x41, 0xff, 0xa2, 0x49, 0x96, 0x68, 0x2a, 0x71, 0x34, 0x46, 0x4e, 0xa5, 0x31, 0x32, 0x20, 0x76, 0x71, 0xfc, + 0x7b, 0x4a, 0x8f, 0x82, 0x94, 0x7d, 0xae, 0x0c, 0x71, 0x38, 0x8a, 0xaf, 0x60, 0xd5, 0x38, 0x1c, 0x6a, 0xf3, 0x7a, + 0x3a, 0xab, 0xe7, 0x03, 0x11, 0xc0, 0x7f, 0x43, 0xc1, 0x7e, 0xd1, 0x54, 0xe4, 0x06, 0xa9, 0xf3, 0x70, 0x48, 0x41, + 0x3e, 0xd5, 0x4d, 0xfe, 0xbe, 0x72, 0xf7, 0xd3, 0xd9, 0xdc, 0x9a, 0xa3, 0x17, 0x35, 0xae, 0x5b, 0xab, 0x1b, 0x0a, + 0x89, 0xd6, 0x34, 0x29, 0xae, 0xaa, 0x49, 0x31, 0xe0, 0xb9, 0x2f, 0x54, 0x17, 0x5b, 0x23, 0x58, 0xf8, 0x73, 0x0b, + 0x84, 0xc9, 0xb8, 0x17, 0x1f, 0x2d, 0xe4, 0x94, 0x76, 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, 0xf3, 0x20, 0xe3, 0x5e, 0x34, 0xec, 0xf8, 0x02, 0xec, 0xd5, 0x17, 0xcf, + 0x59, 0x34, 0xe0, 0xd5, 0x55, 0x3d, 0xcd, 0x82, 0x61, 0xc6, 0xa2, 0xab, 0x62, 0x08, 0x3e, 0xb4, 0x2f, 0xca, 0x41, + 0xe8, 0xfb, 0x66, 0xe7, 0xd0, 0xdd, 0x90, 0xc8, 0x23, 0xec, 0x47, 0x70, 0xdb, 0xd5, 0x12, 0x33, 0x98, 0x6c, 0xee, + 0x22, 0x66, 0xb0, 0xe5, 0x2f, 0x9e, 0x1b, 0x2e, 0xa1, 0xea, 0x85, 0xd4, 0x6c, 0x14, 0x68, 0x4e, 0xae, 0xd0, 0x9c, + 0xac, 0x84, 0x5a, 0xf2, 0x49, 0x85, 0x13, 0x76, 0x3e, 0xc9, 0x95, 0xdd, 0x68, 0x8c, 0x81, 0x8b, 0xf6, 0xdc, 0x16, + 0x46, 0x66, 0x3a, 0x4b, 0xd1, 0x80, 0x85, 0x67, 0xe2, 0x94, 0xc6, 0x80, 0xf6, 0xe5, 0xc0, 0xd2, 0x86, 0xfc, 0x28, + 0x67, 0x06, 0xda, 0x86, 0x94, 0x46, 0xcd, 0xc0, 0x9f, 0xa9, 0x09, 0xf3, 0x2b, 0x58, 0x89, 0x20, 0xaa, 0x0b, 0x30, + 0x49, 0x72, 0x32, 0x1a, 0x29, 0x2b, 0x91, 0x9c, 0x03, 0xde, 0x47, 0xf0, 0x64, 0x11, 0xdb, 0xda, 0x9f, 0xd2, 0xff, + 0xea, 0xf0, 0xb9, 0xf4, 0x9f, 0x09, 0x60, 0x21, 0x97, 0x06, 0x91, 0x81, 0xc2, 0x21, 0x35, 0x95, 0x88, 0x13, 0xc7, + 0x33, 0xf0, 0x0d, 0x5c, 0xa0, 0x29, 0xa0, 0x3f, 0xa8, 0x19, 0x45, 0x64, 0xe1, 0xaf, 0x9e, 0xdd, 0xd4, 0x8d, 0x9e, + 0x67, 0xce, 0x6b, 0xd0, 0xcc, 0x40, 0x48, 0x8f, 0x53, 0xf5, 0x36, 0x24, 0x3a, 0x2f, 0x2f, 0xf5, 0xcb, 0x84, 0x48, + 0x56, 0x44, 0x9e, 0xbe, 0xcf, 0xc1, 0x3c, 0xa2, 0x08, 0x1d, 0x5c, 0x99, 0x87, 0xc3, 0xb9, 0xa0, 0xf0, 0x1d, 0xe5, + 0xf9, 0x80, 0xd3, 0x2c, 0x4a, 0x40, 0x1b, 0xc8, 0x72, 0x53, 0xe6, 0x3a, 0x69, 0x99, 0xba, 0xf7, 0x60, 0x25, 0xa8, + 0xd0, 0xcd, 0x29, 0x28, 0x94, 0x91, 0xa0, 0x94, 0x56, 0x83, 0x50, 0xaa, 0xc3, 0x22, 0x88, 0x1c, 0xb2, 0x10, 0x70, + 0x33, 0x15, 0x8d, 0x96, 0x34, 0x3c, 0xc2, 0xb9, 0x81, 0x42, 0x00, 0x12, 0x7b, 0xaa, 0x28, 0xe3, 0x72, 0x08, 0xf8, + 0x28, 0xe1, 0x10, 0x67, 0x4d, 0xda, 0xf2, 0x1c, 0xc4, 0xb1, 0x5c, 0xf2, 0x75, 0x85, 0x60, 0x10, 0xa1, 0xcf, 0x90, + 0x3f, 0x59, 0xce, 0xbf, 0x5b, 0x87, 0x69, 0x47, 0xf8, 0xb0, 0xab, 0x2d, 0xb8, 0x98, 0xdd, 0xce, 0x27, 0x10, 0xdf, + 0x72, 0x3b, 0x3f, 0xc6, 0x10, 0x59, 0xf8, 0x83, 0xbb, 0xa1, 0xe4, 0x8a, 0x42, 0x97, 0xf5, 0x88, 0x14, 0xd9, 0xd3, + 0x35, 0x47, 0x10, 0x1c, 0x68, 0xd5, 0x20, 0x43, 0x23, 0xf1, 0xc5, 0x73, 0xc8, 0x1a, 0xac, 0xf9, 0xe7, 0x8a, 0x9c, + 0xd5, 0xfd, 0xc9, 0x06, 0xaa, 0x49, 0x26, 0x6b, 0x45, 0xe5, 0xfc, 0xf5, 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, 0xff, 0x15, 0xfc, 0x4b, 0x85, 0x2c, 0xd5, 0x69, 0x9d, 0x89, + 0x5f, 0x83, 0x25, 0xc3, 0x3f, 0x7e, 0x0b, 0xd6, 0x80, 0x25, 0x40, 0x96, 0xbb, 0x8d, 0x8d, 0xd6, 0x2b, 0xaf, 0x10, + 0x5f, 0x6a, 0x7d, 0xd1, 0x6f, 0xdd, 0x26, 0x6a, 0x05, 0x18, 0xa1, 0xd0, 0x22, 0xc0, 0x56, 0x0f, 0xdc, 0x53, 0xf0, + 0x03, 0x31, 0x9c, 0x6b, 0xd2, 0x9a, 0x3a, 0xe1, 0x75, 0x36, 0x8e, 0x44, 0x54, 0x6f, 0xe1, 0xe2, 0x5e, 0x6f, 0x2d, + 0xfe, 0x46, 0x05, 0x02, 0x20, 0x8b, 0x29, 0xd6, 0xce, 0x1b, 0xd2, 0x2b, 0xc3, 0x4e, 0x42, 0xef, 0x0d, 0x3b, 0x81, + 0xbc, 0x38, 0xec, 0x14, 0xba, 0x44, 0xdb, 0x29, 0x52, 0x13, 0x6d, 0x27, 0x2d, 0x56, 0x61, 0x09, 0xc1, 0xaf, 0xda, + 0x5b, 0x47, 0xd9, 0xbe, 0xc8, 0x12, 0xa6, 0x2d, 0x60, 0x94, 0x5b, 0xf5, 0x99, 0x53, 0xc4, 0x4a, 0xd9, 0x3b, 0x9d, + 0x54, 0xb9, 0x8b, 0x7c, 0x6a, 0x35, 0x45, 0x26, 0x7f, 0x7f, 0xdc, 0x22, 0xf9, 0xe4, 0xe7, 0x76, 0xc3, 0x64, 0xfa, + 0xc7, 0xa3, 0x2f, 0xa0, 0x2b, 0xb2, 0xd3, 0x27, 0x10, 0x90, 0xa9, 0xa0, 0x5a, 0xdd, 0x2a, 0xa6, 0x79, 0xbb, 0xca, + 0x6e, 0x2f, 0x94, 0x18, 0x4e, 0x67, 0x27, 0xe1, 0xd1, 0x66, 0xc8, 0xc0, 0x21, 0x08, 0x14, 0x42, 0x45, 0x31, 0x3c, + 0x02, 0xb5, 0x46, 0xf2, 0x01, 0x7e, 0xb4, 0x3b, 0x15, 0x44, 0x6a, 0x37, 0x15, 0x37, 0x4e, 0x6e, 0xba, 0x5e, 0x0a, + 0xd4, 0x3a, 0x25, 0x2b, 0x80, 0x12, 0xa2, 0xfe, 0x24, 0xb6, 0xf5, 0x2b, 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, 0x75, 0xbb, 0xe9, 0x98, 0xd8, 0xea, 0x9f, 0x45, 0xb5, 0xb9, 0x83, 0x8a, 0x88, 0xf8, 0x28, 0xbb, 0x79, 0xd2, + 0x7e, 0x07, 0x7b, 0xac, 0xd5, 0x20, 0xb2, 0xcf, 0xe0, 0x2a, 0xd7, 0x69, 0x91, 0xdb, 0x32, 0x38, 0xff, 0xf0, 0x6a, + 0x57, 0x61, 0x93, 0x63, 0x5d, 0x5d, 0xcd, 0x54, 0x27, 0x15, 0x1b, 0x18, 0x6b, 0x5a, 0x4b, 0x35, 0x8f, 0x21, 0xe9, + 0xae, 0x2c, 0xce, 0xaa, 0xa4, 0x9b, 0x9e, 0x1b, 0x67, 0x0a, 0x31, 0x70, 0xb6, 0x1a, 0x2d, 0x67, 0x18, 0xa2, 0xeb, + 0xc3, 0x2c, 0xf1, 0x5b, 0x3d, 0xe5, 0x3e, 0x0f, 0xb7, 0x7e, 0x57, 0x2f, 0x38, 0x99, 0xec, 0x27, 0xc7, 0xb9, 0xdb, + 0x45, 0xda, 0x4f, 0x7c, 0x1b, 0xe6, 0x5f, 0xdf, 0x20, 0xee, 0x44, 0xfd, 0xcf, 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, 0x7f, 0x7a, 0x35, 0x3b, 0x15, 0x54, 0x06, 0x6e, 0xc6, 0x7f, 0x7a, 0x82, 0x9d, 0xc2, 0x5a, + 0x01, 0x59, 0xe1, 0x4f, 0x2f, 0x7f, 0xe4, 0xfd, 0x8a, 0xff, 0xe9, 0x55, 0x8f, 0xbc, 0x8f, 0x38, 0x2f, 0x7f, 0x22, + 0xa9, 0x13, 0xa2, 0xba, 0xfc, 0x49, 0x98, 0x62, 0xab, 0x34, 0x7f, 0x4d, 0x0a, 0x9f, 0xe0, 0x33, 0xf0, 0x1d, 0xae, + 0xc2, 0xad, 0xf9, 0x0d, 0x1e, 0x3b, 0x16, 0xdb, 0x2e, 0xf5, 0x05, 0x94, 0x23, 0xb0, 0x88, 0xdc, 0x7e, 0xbb, 0xb2, + 0x5f, 0x2d, 0x8c, 0x32, 0xc6, 0xee, 0x4b, 0x56, 0xa2, 0x74, 0xd6, 0xef, 0x17, 0x52, 0x30, 0xb2, 0x0b, 0x6b, 0xb4, + 0x47, 0xa9, 0x7a, 0xf5, 0x3a, 0xac, 0xa3, 0x24, 0xcd, 0xef, 0x64, 0xf4, 0x91, 0x0c, 0x3b, 0xd2, 0x57, 0x52, 0xa2, + 0xbd, 0x56, 0x61, 0x39, 0x9a, 0xfd, 0xba, 0xe4, 0x40, 0x79, 0xdd, 0x0a, 0xca, 0x57, 0x4d, 0x00, 0xbd, 0x52, 0xed, + 0x33, 0xd0, 0x0a, 0x0a, 0x4b, 0xe5, 0xc1, 0x4a, 0x9c, 0x8b, 0x3e, 0x2b, 0x0e, 0x07, 0x75, 0x31, 0x24, 0x14, 0xa8, + 0x12, 0x27, 0xa1, 0x11, 0xcf, 0xe1, 0x42, 0x28, 0x5e, 0xe4, 0x18, 0x5b, 0x91, 0x03, 0x07, 0x32, 0xfc, 0x80, 0xc0, + 0x7b, 0xd9, 0xbf, 0x82, 0xc1, 0x30, 0xc1, 0x8d, 0x8c, 0x3a, 0x39, 0x67, 0x7f, 0x62, 0x60, 0x06, 0xf5, 0xa4, 0x76, + 0x9f, 0xdd, 0xab, 0xc0, 0x5e, 0x38, 0x03, 0xda, 0xbb, 0x31, 0xfa, 0x59, 0x15, 0x6b, 0x27, 0xfd, 0x53, 0xb1, 0x86, + 0x64, 0x3a, 0x2c, 0x8e, 0xb6, 0x69, 0x78, 0x24, 0x4f, 0x8e, 0xe3, 0x4d, 0xff, 0x70, 0x18, 0xe3, 0xc7, 0x51, 0x7e, + 0x6d, 0x01, 0xaf, 0xe2, 0x16, 0xd2, 0x58, 0xa4, 0xe8, 0x1d, 0x88, 0x39, 0x14, 0xbd, 0x64, 0xbf, 0x65, 0xbc, 0x9c, + 0x08, 0x4a, 0x49, 0x62, 0xc3, 0x3b, 0xd2, 0xd3, 0xb4, 0x1e, 0x6d, 0x65, 0xc0, 0x7e, 0x3d, 0xda, 0xd1, 0x5f, 0xa0, + 0x78, 0xb4, 0xf0, 0x97, 0xf4, 0x77, 0x71, 0x37, 0xf7, 0x9c, 0x6f, 0x1a, 0xdf, 0x11, 0x17, 0x28, 0xd6, 0xec, 0xfe, + 0x9a, 0x96, 0xce, 0x3a, 0x10, 0x1c, 0xf0, 0x16, 0xbb, 0x68, 0xdf, 0x6f, 0x5c, 0xa7, 0xa7, 0xfd, 0xb7, 0x6e, 0x8d, + 0xf2, 0xbd, 0x7f, 0x4a, 0x94, 0x83, 0xfd, 0x6b, 0x17, 0xcd, 0xdf, 0x7e, 0xca, 0x90, 0x54, 0x68, 0x6e, 0xb0, 0x9d, + 0x6c, 0x11, 0xd6, 0xc6, 0x38, 0xa8, 0xd8, 0x5d, 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, 0x5f, 0x11, 0x3e, 0xd4, 0x4e, 0x4a, 0x87, 0xf2, 0x57, 0xcf, 0xd9, + 0xff, 0xec, 0xb0, 0xa6, 0xa6, 0xdc, 0x00, 0x66, 0xce, 0x4a, 0xe4, 0x15, 0x42, 0xa7, 0xc8, 0xef, 0x55, 0x5d, 0x89, + 0xe1, 0xb2, 0x16, 0x65, 0x67, 0x76, 0xeb, 0x44, 0xef, 0x9c, 0x82, 0x5a, 0x2a, 0x1b, 0xe4, 0x24, 0xd5, 0xe6, 0x23, + 0x6b, 0x05, 0x25, 0xea, 0x1a, 0x05, 0x8e, 0x4f, 0xb9, 0x76, 0xff, 0xef, 0x9c, 0x09, 0x6a, 0xb6, 0x51, 0xdd, 0x5f, + 0xeb, 0xa7, 0xaa, 0x26, 0xb1, 0x00, 0x97, 0x93, 0x34, 0xef, 0x78, 0x84, 0xd5, 0x3f, 0x4e, 0x96, 0x22, 0xd0, 0xeb, + 0x88, 0x76, 0x25, 0x20, 0x41, 0x3b, 0x39, 0x0b, 0x15, 0x81, 0x02, 0x7d, 0xfd, 0xfb, 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, 0x0a, 0xb9, 0x41, 0x44, 0xd3, 0xef, 0x25, 0xaa, 0x1d, + 0x29, 0x90, 0x43, 0xc9, 0x4f, 0x88, 0xbf, 0x64, 0x6d, 0x8c, 0xfb, 0xa5, 0x53, 0xed, 0x57, 0x0a, 0xc1, 0xfd, 0x67, + 0x5b, 0x6c, 0x54, 0x79, 0xa2, 0x47, 0x9f, 0x62, 0xfd, 0x4f, 0x16, 0x50, 0xaa, 0xfb, 0x36, 0x38, 0x15, 0x8f, 0xc2, + 0x4d, 0x5d, 0xdc, 0x20, 0xb4, 0x40, 0x39, 0xaa, 0x8a, 0x4d, 0x19, 0x11, 0x27, 0xec, 0xa6, 0x2e, 0x7a, 0x9a, 0x03, + 0x9d, 0x3a, 0x2c, 0x4d, 0xe4, 0x89, 0xd0, 0x6e, 0x41, 0xf7, 0x34, 0xc7, 0x4a, 0xbc, 0x94, 0xa5, 0x83, 0xac, 0x13, + 0x69, 0x42, 0xe5, 0xae, 0xae, 0x3a, 0x2a, 0x95, 0xba, 0xe1, 0x4d, 0xaa, 0x19, 0x7f, 0x97, 0xe6, 0x4f, 0x2c, 0xfb, + 0x4d, 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, 0xb1, 0x28, 0xfe, 0xa8, 0xf4, 0x1d, 0x81, 0x8e, 0xee, 0xbc, 0xa8, 0xd3, 0xe5, 0xee, 0x03, 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, 0xbc, 0xc2, 0xfd, 0xa5, 0x22, 0x17, 0xfb, 0xce, 0x19, + 0xdd, 0x99, 0x59, 0xf7, 0xaa, 0xc2, 0xd5, 0x82, 0x5c, 0x1d, 0xd8, 0x5a, 0x76, 0x71, 0xb8, 0x61, 0x11, 0x05, 0x08, + 0xc4, 0xf4, 0x4a, 0xad, 0xfd, 0x11, 0x0d, 0x42, 0x3e, 0x18, 0xf8, 0x05, 0x06, 0xab, 0x02, 0x85, 0x0f, 0x14, 0xc9, + 0x5f, 0x7b, 0x02, 0x76, 0xf1, 0x0c, 0xd0, 0xad, 0xd8, 0xac, 0x18, 0x21, 0x42, 0x26, 0xcb, 0x59, 0x4d, 0x67, 0x90, + 0x4f, 0x7d, 0xf1, 0x8d, 0xad, 0x3a, 0x9d, 0xb7, 0x35, 0x55, 0x4e, 0x1d, 0x0a, 0xdd, 0xdd, 0xd4, 0x9d, 0x5b, 0x17, + 0x79, 0xea, 0x10, 0x72, 0xa5, 0x62, 0x25, 0xa6, 0xa1, 0xe6, 0x49, 0x9a, 0x51, 0x7f, 0xb1, 0xf7, 0x7b, 0x8d, 0xc2, + 0x29, 0x7f, 0x3a, 0x06, 0x55, 0xb8, 0xaa, 0x21, 0x8e, 0xa5, 0x2a, 0x1e, 0xd9, 0x20, 0xd0, 0xbc, 0xba, 0x55, 0x49, + 0x13, 0x32, 0xb9, 0x11, 0x3e, 0x35, 0x29, 0xe5, 0x69, 0xda, 0xa4, 0x95, 0x22, 0x75, 0xf0, 0x41, 0x9d, 0x6a, 0x3c, + 0x37, 0xab, 0x17, 0x00, 0x66, 0x9c, 0x5f, 0xf1, 0x4b, 0xc5, 0x65, 0xd4, 0x56, 0x66, 0xd2, 0xfe, 0xe4, 0x68, 0x6c, + 0xd4, 0xe5, 0xb4, 0x51, 0x46, 0x58, 0x29, 0xcd, 0x49, 0xb1, 0x1c, 0xcf, 0x3f, 0x60, 0xb0, 0xe6, 0x09, 0xec, 0x60, + 0xa2, 0x52, 0xde, 0x47, 0x40, 0x7c, 0x9d, 0xa4, 0x77, 0x09, 0xa4, 0x48, 0xff, 0xd2, 0x25, 0x77, 0x19, 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, 0xbe, 0x08, 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, 0xac, 0x3c, 0xe8, 0xff, 0x3a, 0x13, 0x96, 0xda, 0x4f, 0x4f, 0x07, 0x50, 0xc1, 0xfb, 0x8a, 0xb7, 0x11, 0xf1, + 0x7d, 0xe2, 0x67, 0xf1, 0x60, 0xf3, 0x6c, 0x03, 0xd6, 0xba, 0x27, 0xb9, 0xb1, 0xae, 0x12, 0x36, 0x10, 0xf0, 0x35, + 0x8a, 0xda, 0xf3, 0xda, 0xed, 0x1e, 0xfc, 0xd5, 0xbf, 0x08, 0x19, 0x30, 0x71, 0xfa, 0x3e, 0x73, 0xb2, 0x46, 0x17, + 0x99, 0x4c, 0x1f, 0x3a, 0xe9, 0x1b, 0x9d, 0xee, 0x3b, 0xe1, 0x1f, 0x15, 0xb3, 0xf8, 0x70, 0x4b, 0x5f, 0x69, 0x52, + 0xdc, 0x01, 0x2b, 0x9b, 0x47, 0x05, 0xa1, 0xce, 0x45, 0xf4, 0x95, 0x29, 0xdf, 0x12, 0x6a, 0xf6, 0x8d, 0x25, 0xa5, + 0x74, 0xaf, 0xa1, 0x37, 0x69, 0xad, 0xdf, 0x46, 0x09, 0xc6, 0x44, 0xc7, 0x93, 0x97, 0xf1, 0x58, 0x79, 0x1f, 0x8f, + 0x1b, 0xa9, 0x90, 0x07, 0x20, 0x02, 0x15, 0xe3, 0x4f, 0x57, 0x9e, 0x9c, 0xf4, 0xc2, 0x78, 0x15, 0x4a, 0x41, 0x61, + 0x40, 0x57, 0x20, 0x05, 0x3c, 0x6a, 0x4f, 0x74, 0x16, 0x76, 0x09, 0xf7, 0xe8, 0x26, 0x60, 0xac, 0xcf, 0x3f, 0x02, + 0x9a, 0xbb, 0x70, 0x87, 0x17, 0x03, 0xd4, 0xa6, 0x5e, 0xdd, 0x7d, 0x5c, 0xab, 0x73, 0x38, 0x04, 0x07, 0xab, 0x41, + 0x04, 0xa7, 0xf3, 0xa9, 0xa3, 0x59, 0x16, 0xa0, 0x72, 0xb2, 0xdc, 0xc8, 0x9b, 0x47, 0x8b, 0x5e, 0xdd, 0xf7, 0x96, + 0x69, 0x59, 0xd5, 0x41, 0xc6, 0xb2, 0xb0, 0x02, 0x5c, 0x1d, 0x5a, 0x3f, 0x08, 0x97, 0x85, 0xf3, 0x07, 0x42, 0x10, + 0xbb, 0x57, 0xdb, 0x92, 0xe7, 0x6a, 0x0e, 0x3f, 0x7b, 0xce, 0xd6, 0x5c, 0xa2, 0x4e, 0x3a, 0x13, 0x01, 0x88, 0x3d, + 0x35, 0xab, 0xe8, 0x1a, 0x48, 0xea, 0x34, 0xab, 0xe8, 0x9a, 0x9a, 0x6d, 0x8c, 0x03, 0xf9, 0x68, 0x95, 0x02, 0xf6, + 0xdd, 0x74, 0x1c, 0xac, 0x9e, 0xc5, 0xf2, 0x3a, 0x74, 0xf7, 0x6c, 0xa3, 0x7c, 0x06, 0x75, 0xab, 0x8d, 0x31, 0xb1, + 0xdd, 0x7c, 0x39, 0xd7, 0x6f, 0x07, 0x4b, 0xdf, 0x0e, 0x9a, 0x73, 0xca, 0xbe, 0xd3, 0x65, 0xaf, 0xec, 0xb2, 0xa9, + 0xe7, 0x8e, 0x8a, 0x56, 0x63, 0x40, 0x6f, 0x60, 0xc1, 0xfa, 0x5c, 0xa4, 0xd9, 0xaa, 0x54, 0x25, 0xe0, 0x85, 0xb1, + 0x62, 0x77, 0x7e, 0x23, 0x33, 0x24, 0x61, 0x1e, 0x67, 0xe2, 0x9a, 0xee, 0xb5, 0x30, 0x39, 0x8e, 0x45, 0x32, 0x25, + 0x74, 0x4a, 0x77, 0xb6, 0xa1, 0x73, 0x15, 0x46, 0x11, 0xad, 0x95, 0x54, 0x1a, 0x09, 0x4c, 0xcd, 0x00, 0x25, 0x73, + 0x05, 0x4e, 0xe9, 0x72, 0xff, 0x3b, 0x12, 0xe3, 0xcc, 0x17, 0x25, 0x33, 0xa0, 0x5b, 0x7e, 0x5d, 0xac, 0x5b, 0x29, + 0x32, 0xc2, 0xbc, 0x39, 0x6e, 0xaf, 0xeb, 0x43, 0x20, 0x57, 0xcb, 0x1e, 0x45, 0xe3, 0xa0, 0xd0, 0xe1, 0x52, 0x25, + 0xc0, 0xbe, 0x48, 0xfc, 0x8c, 0xb0, 0xa5, 0x3d, 0x90, 0xdb, 0xa3, 0x33, 0x61, 0xce, 0x39, 0x29, 0xcb, 0xce, 0xa5, + 0x19, 0x5c, 0x4e, 0x5c, 0x09, 0x2e, 0xd2, 0xdb, 0xf6, 0x34, 0x69, 0x69, 0xfb, 0xd8, 0x70, 0x8e, 0x86, 0xb6, 0x41, + 0x77, 0xec, 0x0f, 0xcd, 0xc5, 0x22, 0xb6, 0x2e, 0x16, 0xc3, 0xce, 0xec, 0x47, 0x8b, 0x05, 0xc8, 0x01, 0xe0, 0xa8, + 0xdb, 0xf0, 0x31, 0x5b, 0x02, 0xa7, 0xd5, 0x34, 0x9b, 0x7a, 0x1b, 0x5e, 0x3d, 0x53, 0x3d, 0xbd, 0xe4, 0xf9, 0x33, + 0x61, 0xc6, 0x62, 0xc3, 0xf3, 0x67, 0xd6, 0x91, 0x53, 0x3d, 0x13, 0x4a, 0xb4, 0x2e, 0xa0, 0x19, 0x78, 0x4d, 0x01, + 0x23, 0x96, 0x4c, 0xa6, 0x54, 0x91, 0xc7, 0xbd, 0xe9, 0x46, 0x0d, 0x5e, 0x50, 0x38, 0x04, 0x52, 0x3a, 0xfd, 0xe2, + 0x39, 0xd3, 0xef, 0x5d, 0x3c, 0xef, 0x90, 0xb5, 0x0d, 0xd3, 0xe5, 0x66, 0x98, 0x0c, 0x4a, 0xff, 0x99, 0x99, 0x18, + 0x17, 0xd6, 0x24, 0x01, 0xc4, 0xbf, 0xb1, 0xdf, 0x21, 0x85, 0x9b, 0xf7, 0x97, 0xc3, 0xf8, 0x91, 0xf7, 0x63, 0x64, + 0x4f, 0xd2, 0x0c, 0xb1, 0x66, 0x52, 0x21, 0x77, 0x5f, 0xad, 0x7f, 0x4c, 0xec, 0x26, 0x7b, 0x60, 0x01, 0x88, 0xad, + 0x69, 0xab, 0x5b, 0xde, 0xef, 0x7b, 0xa6, 0x08, 0xf0, 0x83, 0xf2, 0x8f, 0xee, 0x0c, 0xc9, 0xa0, 0xec, 0xba, 0x21, + 0xc4, 0x83, 0xb2, 0x69, 0xda, 0xeb, 0x6d, 0xef, 0xcc, 0x63, 0x75, 0x9d, 0x76, 0x16, 0x57, 0x8b, 0x0c, 0xd2, 0xea, + 0x43, 0x76, 0x9c, 0xd9, 0x67, 0x47, 0x4b, 0xa5, 0xfb, 0x7d, 0x88, 0x88, 0x3b, 0xca, 0xda, 0x7e, 0xbb, 0x05, 0xd7, + 0x70, 0x34, 0x08, 0x5d, 0xd9, 0xdb, 0x65, 0xb4, 0x71, 0x21, 0x8e, 0x7b, 0xa6, 0xf3, 0x05, 0x5f, 0x1e, 0xa5, 0x9d, + 0x07, 0xa7, 0x7a, 0xa2, 0xcf, 0x4d, 0x77, 0x95, 0xc9, 0xb5, 0x0e, 0xab, 0x31, 0xa8, 0xcd, 0xc2, 0x16, 0xee, 0xc2, + 0x36, 0x3a, 0x68, 0xed, 0xcb, 0x82, 0x7f, 0xca, 0x00, 0x7c, 0xe9, 0xd9, 0xb2, 0xed, 0x35, 0x69, 0xf5, 0x46, 0x46, + 0x21, 0xb6, 0xb4, 0xbd, 0xfa, 0x74, 0x94, 0x8f, 0x9b, 0x13, 0x8a, 0x0b, 0x39, 0xca, 0x8f, 0x5e, 0x43, 0xd4, 0xb5, + 0xae, 0xe3, 0x62, 0xd1, 0xe1, 0xc6, 0x55, 0xb7, 0xdd, 0xb8, 0x7e, 0x40, 0xbc, 0x35, 0xda, 0xa4, 0x50, 0x2b, 0x63, + 0x47, 0xf0, 0xb2, 0x7c, 0x38, 0x64, 0x62, 0x38, 0x94, 0x90, 0xa9, 0x8f, 0xdd, 0x1b, 0x9a, 0xf6, 0xf9, 0x69, 0xeb, + 0x47, 0x2c, 0x35, 0x8e, 0x62, 0xc3, 0x3b, 0x7d, 0xe7, 0xb1, 0x35, 0xae, 0xe4, 0xcb, 0x60, 0xb6, 0x2b, 0xa8, 0xb6, + 0xc6, 0x1b, 0xf6, 0x72, 0xfe, 0x7d, 0x25, 0x95, 0xfc, 0xed, 0xcf, 0x70, 0x0d, 0x6f, 0x6d, 0xe9, 0xa0, 0xa9, 0x66, + 0x39, 0xcb, 0xf5, 0xbd, 0xe0, 0xf8, 0xe3, 0xee, 0x15, 0xc1, 0xe0, 0xf7, 0x74, 0x14, 0xe4, 0x62, 0xa9, 0xd6, 0x80, + 0x82, 0x74, 0x64, 0xc7, 0x54, 0x16, 0x18, 0x06, 0xf0, 0x86, 0x0c, 0x90, 0xc7, 0x14, 0xee, 0x86, 0x0a, 0x2f, 0xfc, + 0xa5, 0x22, 0xbb, 0x04, 0xb6, 0x35, 0xe3, 0x63, 0x86, 0x3b, 0x08, 0xf9, 0x47, 0xb0, 0x3b, 0xb6, 0x62, 0xb7, 0x6c, + 0xc1, 0x90, 0x6c, 0x1c, 0x87, 0x31, 0xe6, 0xe3, 0x49, 0x7c, 0x25, 0x26, 0xf1, 0x80, 0x47, 0xe8, 0x18, 0xb1, 0xe6, + 0xf5, 0x2c, 0x96, 0x03, 0xc8, 0xee, 0xb8, 0xd2, 0x01, 0x21, 0x34, 0x36, 0xb4, 0xe4, 0x4d, 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, 0xdd, 0x45, 0x88, 0xf4, 0xb6, 0xe0, 0x77, 0x96, 0xa7, 0x0b, 0xbb, 0xe7, 0xd7, + 0x7c, 0xcc, 0xce, 0x7f, 0xf0, 0x20, 0x72, 0xf6, 0xfc, 0x23, 0xa0, 0x21, 0xde, 0xf3, 0xdb, 0xd4, 0xab, 0xd8, 0x2d, + 0x51, 0x10, 0xde, 0x82, 0x33, 0xd0, 0x3d, 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, 0xff, 0xc1, 0xdb, 0x51, 0xb9, 0xf0, 0x9f, 0xd7, 0x59, 0xf2, 0xce, 0x67, 0xd7, 0x03, 0xbe, 0x00, 0xbc, 0x25, + 0x74, 0xe0, 0xba, 0xf7, 0x99, 0xc4, 0x6b, 0xbb, 0xd6, 0xd7, 0x08, 0x24, 0xf2, 0x05, 0x60, 0xc4, 0xc4, 0xfc, 0xbe, + 0x86, 0x08, 0x8c, 0x04, 0x7c, 0x5b, 0xb5, 0x47, 0xfc, 0x96, 0x1b, 0xc0, 0xaf, 0xcc, 0x67, 0x0f, 0x3c, 0xd4, 0x3f, + 0x13, 0x9f, 0xdd, 0xf0, 0xf7, 0xfc, 0x85, 0x27, 0x25, 0xe9, 0x72, 0xf6, 0x7e, 0x0e, 0xd7, 0x43, 0x29, 0x4f, 0x87, + 0xf4, 0xb3, 0x31, 0x18, 0x40, 0x28, 0x64, 0xde, 0x78, 0xc0, 0x9a, 0x14, 0xe2, 0x5f, 0xc0, 0xb7, 0xa3, 0x84, 0xcd, + 0x1b, 0x6f, 0xeb, 0x6b, 0x79, 0xf3, 0xc6, 0x7b, 0xf0, 0x29, 0x0a, 0xb0, 0x0a, 0x4a, 0x59, 0x60, 0x15, 0x84, 0x8d, + 0x36, 0xc2, 0x18, 0xb8, 0x7a, 0xd7, 0x18, 0xea, 0x7a, 0x8e, 0xd8, 0xb6, 0xd2, 0x77, 0xe1, 0x3b, 0xc8, 0x80, 0x0f, + 0xde, 0x14, 0x25, 0xd1, 0xe7, 0xd4, 0x14, 0x49, 0xeb, 0x9e, 0xfb, 0xad, 0x75, 0x47, 0x6b, 0x4a, 0x7d, 0xe4, 0x6a, + 0x7c, 0x38, 0xd4, 0x2f, 0x84, 0x16, 0x09, 0xa6, 0xa0, 0x71, 0x0d, 0xda, 0x02, 0x04, 0x7d, 0x1e, 0x20, 0x6b, 0x49, + 0xb1, 0xe0, 0xdb, 0x5f, 0x21, 0x06, 0xaf, 0x4c, 0xef, 0x5c, 0xae, 0x32, 0x12, 0xb6, 0x17, 0x7e, 0x39, 0xac, 0xfd, + 0x89, 0x53, 0x0b, 0x4b, 0xab, 0x39, 0xa8, 0x9f, 0xd9, 0x72, 0x9c, 0xaa, 0xda, 0xbf, 0x25, 0x49, 0xb5, 0xab, 0xb4, + 0x9c, 0xde, 0xdb, 0x37, 0x5d, 0x26, 0xd8, 0xd8, 0x0f, 0xa8, 0x3a, 0xb2, 0x1a, 0x76, 0x5f, 0xa8, 0x2f, 0x7a, 0x4a, + 0x26, 0x34, 0x1f, 0x55, 0x34, 0xcf, 0xee, 0x37, 0x3b, 0xea, 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, 0x17, 0xe3, 0x69, 0x4d, 0x2c, 0xa9, 0x5d, 0x81, 0x31, 0x7a, 0x5c, 0x15, 0xb5, 0x4f, 0xfd, 0x02, 0x42, 0x91, + 0x6a, 0xcd, 0x1c, 0x6b, 0xdc, 0x18, 0x11, 0x77, 0x58, 0xb9, 0x76, 0x6a, 0xaf, 0x03, 0xb0, 0xbc, 0x1a, 0x17, 0x84, + 0x4d, 0x72, 0xec, 0x5c, 0xc0, 0x6a, 0x34, 0xa4, 0xda, 0x0d, 0xb7, 0x5e, 0x76, 0x7e, 0xf3, 0x38, 0xb1, 0xb5, 0x11, + 0x6e, 0x29, 0xa0, 0x8c, 0xf2, 0x1b, 0xcb, 0x09, 0xbb, 0x53, 0xbd, 0x23, 0x55, 0x3b, 0xe2, 0xc4, 0x05, 0x2c, 0x37, + 0x3c, 0xb5, 0xfa, 0x26, 0x06, 0x27, 0x42, 0xd5, 0x4a, 0xc7, 0x6b, 0x3f, 0xe2, 0x7e, 0x75, 0x5f, 0xf7, 0x4a, 0xf0, + 0x93, 0x90, 0xd7, 0x6f, 0x79, 0x07, 0x80, 0x15, 0x1f, 0xf2, 0x62, 0x5a, 0x38, 0x5a, 0x97, 0x41, 0x19, 0x20, 0x42, + 0x33, 0x00, 0x3a, 0xb9, 0x3a, 0x88, 0xd2, 0xc0, 0x15, 0x77, 0x88, 0xf0, 0xd3, 0xe8, 0x59, 0xfe, 0x22, 0x7c, 0x56, + 0x4d, 0xc3, 0x8b, 0x3c, 0x88, 0x2e, 0xaa, 0x20, 0x7a, 0x56, 0x5d, 0x85, 0xcf, 0xf2, 0x69, 0x74, 0x91, 0x07, 0xe1, + 0x45, 0xd5, 0xd8, 0x77, 0xed, 0xee, 0x9e, 0x90, 0xb7, 0x5d, 0xfd, 0x91, 0x73, 0x65, 0x4f, 0x99, 0x9e, 0x9f, 0xd7, + 0x7a, 0xa5, 0x76, 0x9b, 0xeb, 0x35, 0x6a, 0xa6, 0x3e, 0xca, 0xfe, 0x66, 0x1b, 0x0b, 0x8f, 0xe6, 0x10, 0xfa, 0x8c, + 0xb4, 0x98, 0x7b, 0x9c, 0xeb, 0xcd, 0x9e, 0x14, 0x06, 0x46, 0x4c, 0x2a, 0x19, 0x39, 0xbd, 0xc0, 0x45, 0xa8, 0x42, + 0x0c, 0x6b, 0xe9, 0x6a, 0x9f, 0x75, 0xe9, 0x0d, 0xd4, 0x35, 0xc5, 0xbe, 0x86, 0x0c, 0xbc, 0x68, 0x7a, 0x19, 0x8c, + 0x01, 0x39, 0x02, 0xef, 0xf8, 0x6c, 0x09, 0x07, 0xe6, 0x1a, 0xa0, 0x6f, 0x1e, 0xf5, 0x75, 0xb9, 0xe3, 0x6b, 0xd5, + 0x37, 0xd3, 0xf5, 0x48, 0x29, 0x3f, 0x56, 0xfc, 0xee, 0xe2, 0x39, 0xbb, 0xe5, 0x1a, 0x15, 0xe5, 0x17, 0xbd, 0x58, + 0xef, 0x81, 0xab, 0xee, 0x17, 0xb8, 0xcd, 0xe2, 0xb1, 0x2b, 0x0f, 0x58, 0xb6, 0x65, 0x0f, 0xec, 0x86, 0xbd, 0x67, + 0x4f, 0xd8, 0x5b, 0xf6, 0x8e, 0xfd, 0x84, 0xaa, 0x0d, 0x25, 0xe4, 0xf9, 0x0b, 0x7e, 0x2b, 0x4d, 0x8f, 0x12, 0x95, + 0xec, 0xc1, 0x36, 0xd3, 0x0c, 0x37, 0xec, 0x3d, 0x5f, 0x0c, 0x57, 0xec, 0x2d, 0x64, 0x43, 0x99, 0x78, 0xb0, 0x62, + 0x3f, 0x71, 0x05, 0x62, 0xa6, 0xcf, 0xc2, 0xd2, 0x12, 0x15, 0x4d, 0x99, 0x28, 0x43, 0xbf, 0xe5, 0xf8, 0x22, 0xfb, + 0x09, 0x8b, 0x90, 0x9f, 0x19, 0xae, 0xd8, 0x03, 0x5f, 0x0c, 0x56, 0xec, 0xbd, 0x36, 0x10, 0x0d, 0x36, 0x6e, 0x69, + 0x84, 0x64, 0xa5, 0xcb, 0x92, 0xd2, 0xf4, 0xd6, 0xbe, 0x06, 0x6e, 0xd8, 0x0d, 0xd6, 0xee, 0x09, 0x16, 0x8d, 0x02, + 0xff, 0x60, 0xc5, 0xde, 0x71, 0x09, 0xa0, 0xe6, 0x96, 0x27, 0xbd, 0x42, 0x75, 0x81, 0x74, 0x3f, 0x78, 0xc2, 0xe9, + 0x45, 0xf6, 0x0e, 0xcb, 0xa0, 0xaf, 0x0c, 0x57, 0x6c, 0x8b, 0xb5, 0xbb, 0x31, 0x96, 0x2d, 0xab, 0x7a, 0x12, 0x11, + 0x18, 0x05, 0x95, 0xd2, 0xf2, 0x6f, 0xc4, 0xb2, 0xa9, 0x9b, 0x06, 0xb5, 0xa1, 0x3f, 0x1f, 0x8c, 0xfe, 0xe2, 0xeb, + 0x77, 0x3f, 0x78, 0xa5, 0xbe, 0xf6, 0xfe, 0xe2, 0xb8, 0x56, 0x96, 0xe8, 0x5a, 0xf9, 0x2b, 0x2f, 0x67, 0xbf, 0xcc, + 0x27, 0xba, 0x96, 0xb4, 0xc3, 0x90, 0xaf, 0xe9, 0xec, 0x97, 0x0e, 0x67, 0xcb, 0x5f, 0x7d, 0xbf, 0x31, 0x5d, 0xac, + 0x3e, 0xab, 0x7b, 0xf7, 0x61, 0xb0, 0x69, 0x9c, 0x7a, 0xef, 0x4e, 0xd7, 0x1b, 0x9b, 0x59, 0x6b, 0xcf, 0xcc, 0xff, + 0xe1, 0x4a, 0x6f, 0x71, 0xe8, 0x6e, 0xf8, 0x76, 0xb8, 0xb1, 0x47, 0x41, 0x7e, 0x5f, 0x2a, 0x8d, 0xb3, 0x9a, 0xbf, + 0xf4, 0x3a, 0xa5, 0x58, 0x40, 0x34, 0xfa, 0x64, 0x24, 0xa1, 0x4b, 0x66, 0xe2, 0x19, 0xe2, 0x8b, 0x0c, 0x90, 0xb9, + 0x40, 0x34, 0xbb, 0xe7, 0xe3, 0xc9, 0xfd, 0x55, 0x3c, 0xb9, 0x1f, 0xf0, 0x4f, 0xa6, 0x05, 0xed, 0xc5, 0x76, 0xef, + 0xb3, 0x5f, 0x79, 0x61, 0x2f, 0xc7, 0x5f, 0x7c, 0xf6, 0x45, 0xb8, 0x2b, 0xf4, 0x17, 0x9f, 0xbd, 0x13, 0xfc, 0xd7, + 0x91, 0x26, 0xca, 0x60, 0xef, 0x6a, 0xfe, 0xeb, 0x08, 0x19, 0x3f, 0xd8, 0x67, 0xc1, 0xbf, 0x80, 0xef, 0x77, 0x95, + 0xa0, 0x55, 0xfc, 0x73, 0xad, 0x7e, 0xbe, 0x97, 0x71, 0x39, 0xf0, 0x26, 0xb4, 0x82, 0xde, 0xbc, 0xad, 0xe5, 0x4f, + 0xe2, 0xe1, 0x48, 0xd5, 0x53, 0xc3, 0x3f, 0x8b, 0xc5, 0x2c, 0xea, 0xa3, 0x74, 0x2a, 0x6f, 0x72, 0xcd, 0x33, 0x69, + 0x5d, 0xbe, 0x87, 0x50, 0xe0, 0x6b, 0x1b, 0xa2, 0x60, 0xc7, 0x71, 0x23, 0xb8, 0x66, 0xef, 0x84, 0xcf, 0xb2, 0xe9, + 0x96, 0xdf, 0xf0, 0x27, 0xfc, 0x1d, 0xdf, 0x05, 0x0f, 0xfc, 0x3d, 0x7f, 0xcb, 0x7f, 0xe2, 0x3b, 0xb6, 0x94, 0x68, + 0xa7, 0xf5, 0xf6, 0x32, 0xd8, 0xb2, 0x7a, 0x77, 0x19, 0x3c, 0xb0, 0x7a, 0xfb, 0x3c, 0xb8, 0x61, 0xf5, 0xee, 0x79, + 0xf0, 0x9e, 0x6d, 0x2f, 0x83, 0x27, 0x6c, 0x77, 0x19, 0xbc, 0x65, 0xdb, 0xe7, 0xc1, 0x3b, 0xb6, 0x7b, 0x1e, 0xfc, + 0x24, 0x31, 0x1e, 0xde, 0x09, 0xc9, 0x71, 0xf2, 0xae, 0x66, 0x86, 0x4f, 0x37, 0xf8, 0x2c, 0xac, 0x5f, 0x54, 0xc7, + 0xe0, 0x73, 0xcd, 0x74, 0x8b, 0x03, 0x21, 0x98, 0x6e, 0x6f, 0x70, 0x4b, 0x4f, 0x4c, 0xab, 0x82, 0x54, 0xb0, 0xae, + 0x76, 0x06, 0x8b, 0xba, 0x69, 0x9d, 0xc9, 0x8e, 0x5f, 0x62, 0xdc, 0xe1, 0x97, 0xb8, 0x60, 0xcb, 0xa6, 0xd3, 0x49, + 0xe7, 0xf4, 0x49, 0xa0, 0x37, 0x7f, 0xbd, 0xeb, 0x57, 0xd2, 0x77, 0xa6, 0x68, 0x78, 0xae, 0xb4, 0xc6, 0xad, 0x9d, + 0x3e, 0xb4, 0x76, 0x7a, 0x26, 0x55, 0x68, 0x11, 0x8b, 0xca, 0xa2, 0xaa, 0x90, 0x49, 0x3c, 0xc8, 0xb4, 0x3e, 0x2d, + 0x61, 0xa4, 0xc8, 0x04, 0x34, 0xfa, 0x82, 0x8e, 0x81, 0x9c, 0x2c, 0x0a, 0x6c, 0xc9, 0x37, 0x83, 0x84, 0xad, 0x79, + 0x3c, 0x1d, 0x26, 0xc1, 0x92, 0xdd, 0xf1, 0x61, 0xb7, 0x40, 0xb0, 0x52, 0x01, 0x4c, 0xfa, 0xe2, 0xd4, 0xde, 0xd7, + 0x79, 0x6f, 0x95, 0xc6, 0x71, 0x26, 0x50, 0xd9, 0x56, 0xe9, 0x0d, 0x7e, 0xeb, 0xec, 0xe7, 0x6b, 0xb5, 0xbf, 0x83, + 0xa4, 0xf0, 0x2b, 0x30, 0xec, 0x10, 0xe1, 0x1d, 0x54, 0x18, 0x79, 0x96, 0xcc, 0xa2, 0xaf, 0xec, 0x2d, 0x7d, 0x6b, + 0xb6, 0xe9, 0xff, 0xb4, 0x08, 0xda, 0xc7, 0x65, 0xe7, 0x7f, 0x32, 0xaf, 0xfe, 0xd6, 0xf1, 0xea, 0xc6, 0x9f, 0x3c, + 0xf0, 0x4f, 0x18, 0x96, 0x80, 0x89, 0x6c, 0xc7, 0x3f, 0x8d, 0xb6, 0x8d, 0x53, 0x9e, 0xdc, 0xc7, 0xff, 0xaf, 0x14, + 0x68, 0xef, 0xe4, 0x95, 0xbd, 0x23, 0x6e, 0x79, 0xc7, 0x3e, 0xbe, 0xb4, 0x36, 0x44, 0x03, 0x4d, 0xf2, 0x89, 0xbb, + 0xd1, 0xd0, 0xb0, 0x21, 0xfe, 0xc2, 0xab, 0xd9, 0xa7, 0xf9, 0x64, 0xcb, 0x8f, 0xb7, 0xc3, 0x4f, 0x1d, 0xdb, 0xe1, + 0x2f, 0xfe, 0x60, 0xd9, 0x7c, 0xad, 0x57, 0x3b, 0xb7, 0x71, 0xa7, 0xd2, 0x3b, 0x7e, 0xbc, 0x89, 0x0f, 0xff, 0xe3, + 0x4a, 0xef, 0xbe, 0xb9, 0xd2, 0x76, 0x95, 0xbb, 0x3b, 0xdf, 0x74, 0x7c, 0x23, 0x6b, 0x8d, 0x71, 0x66, 0x46, 0xb3, 0xf8, 0x13, 0xcd, 0xd2, 0x20, 0xb2, 0x14, 0x8a, 0x3f, 0x99, 0x69, 0xa7, 0xee, 0x54, 0x59, 0xdd, 0x2d, 0xdf, 0xe2, - 0x1e, 0x7f, 0xc7, 0xc7, 0x6c, 0x61, 0x3c, 0x35, 0xef, 0x6e, 0x16, 0x93, 0xc1, 0xe0, 0xce, 0x3f, 0xdc, 0xf3, 0x70, - 0x76, 0x37, 0x67, 0x6f, 0xf9, 0x3d, 0x2d, 0xa6, 0x89, 0x6a, 0x7a, 0xf1, 0x98, 0xe0, 0x75, 0xe7, 0xfb, 0x13, 0x8b, - 0xff, 0xd5, 0xbe, 0x68, 0xde, 0xf9, 0x03, 0x69, 0x8d, 0x96, 0xbb, 0xfa, 0xfb, 0xc7, 0x15, 0x13, 0x77, 0x20, 0x5e, - 0xbc, 0xb7, 0x35, 0x0d, 0x6f, 0xf8, 0x47, 0xef, 0xad, 0x3f, 0x7d, 0xab, 0x63, 0x6e, 0x26, 0xea, 0x48, 0x7a, 0x73, - 0xf5, 0x8c, 0xfd, 0xca, 0x3f, 0xc9, 0xe3, 0xe4, 0x9d, 0x90, 0x93, 0xf6, 0x16, 0xb9, 0x9b, 0xe8, 0x94, 0xf8, 0xe2, - 0x26, 0x12, 0x16, 0x04, 0xc2, 0x70, 0xd4, 0xfc, 0x61, 0x52, 0x4e, 0xbd, 0x3d, 0x70, 0xbb, 0x72, 0x5b, 0xff, 0x7c, - 0xc7, 0x39, 0x5f, 0x0c, 0xaf, 0xa7, 0x5f, 0xba, 0x5d, 0x7a, 0x54, 0x34, 0x9b, 0x0a, 0x74, 0xbb, 0xc3, 0xd8, 0xab, - 0xb3, 0x99, 0x65, 0x2e, 0xf9, 0xd2, 0x97, 0xda, 0xcc, 0x3c, 0xa6, 0xf7, 0x9b, 0x69, 0x86, 0x44, 0xbe, 0x40, 0xc8, - 0x74, 0x3c, 0xae, 0x2e, 0xb1, 0x3c, 0x3e, 0x7c, 0xf3, 0xf4, 0xc9, 0xe0, 0x09, 0x46, 0x6e, 0x59, 0xd1, 0x20, 0x5f, - 0xf8, 0x30, 0xab, 0x5b, 0xb7, 0x8d, 0xab, 0x67, 0xc3, 0x5f, 0x20, 0x6f, 0xd0, 0xf5, 0xd0, 0x14, 0xd1, 0x2a, 0xbf, - 0xa3, 0xe8, 0x33, 0x25, 0x07, 0x1d, 0x4f, 0xa0, 0x76, 0x48, 0x81, 0xfb, 0xe5, 0x29, 0x07, 0xfd, 0x06, 0x96, 0xda, - 0xef, 0x5f, 0x7e, 0x22, 0x1e, 0x69, 0x18, 0xef, 0x1f, 0xc2, 0xe8, 0x8f, 0xb8, 0x2c, 0x36, 0x70, 0xba, 0x0e, 0xe0, - 0x73, 0x4f, 0xf5, 0xed, 0x6b, 0xe5, 0xfb, 0x7e, 0xe0, 0xed, 0xf8, 0x2d, 0xfb, 0xc2, 0xbd, 0xeb, 0xe1, 0x1b, 0xff, - 0xe9, 0x13, 0x10, 0x9d, 0x60, 0x5c, 0x3e, 0x63, 0x24, 0x6c, 0x47, 0x31, 0x6a, 0x15, 0x7e, 0xae, 0x21, 0x44, 0xeb, - 0x13, 0x32, 0x76, 0x41, 0xfa, 0x07, 0x05, 0xe8, 0x27, 0x04, 0x56, 0x93, 0xd4, 0x28, 0x30, 0x89, 0xef, 0x6a, 0x48, - 0x20, 0x05, 0x0b, 0x84, 0xde, 0x40, 0xf1, 0xa9, 0xe0, 0x5f, 0x86, 0x9f, 0x49, 0xf2, 0x5b, 0xd4, 0x7c, 0x0c, 0x7f, - 0xc3, 0xd0, 0x4c, 0xaa, 0x87, 0xb4, 0x8e, 0x12, 0xef, 0x27, 0xff, 0x10, 0x85, 0x95, 0x50, 0xc7, 0x42, 0x90, 0x8a, - 0x21, 0x17, 0xe2, 0xea, 0xd9, 0xe4, 0xae, 0x14, 0xe1, 0x1f, 0x13, 0x7c, 0x26, 0x17, 0x9a, 0x7c, 0x46, 0x4f, 0x1a, - 0xf9, 0xfe, 0x83, 0x7c, 0x5f, 0x76, 0x6a, 0xb0, 0xa8, 0x87, 0xfc, 0xae, 0x76, 0xdf, 0x97, 0x53, 0x82, 0x1e, 0xd9, - 0x0f, 0x68, 0x0a, 0x06, 0x6a, 0x02, 0x52, 0x86, 0xe0, 0x0e, 0xae, 0xfa, 0x9e, 0x2a, 0xc8, 0x97, 0xdf, 0xfb, 0x2c, - 0x64, 0xb8, 0xca, 0x82, 0x90, 0xe4, 0x52, 0x21, 0x85, 0x8d, 0xbb, 0x7a, 0xf0, 0x59, 0x63, 0x92, 0x48, 0xc8, 0x29, - 0x01, 0x49, 0xd2, 0xde, 0x40, 0x92, 0x88, 0xe9, 0x3f, 0x5c, 0x27, 0x4d, 0xb3, 0x96, 0xd2, 0x0d, 0x71, 0xaa, 0xbe, - 0x45, 0x9a, 0xb3, 0xe0, 0x3d, 0x83, 0xa5, 0x23, 0xc5, 0x8a, 0x2f, 0xc6, 0x60, 0xac, 0x83, 0x85, 0x56, 0xb2, 0xb8, - 0x5f, 0x25, 0x61, 0x1a, 0x89, 0x2a, 0xef, 0x84, 0xfc, 0xf9, 0x4f, 0x25, 0xfe, 0xe8, 0x2d, 0x0d, 0x44, 0x20, 0xf8, - 0x01, 0x5a, 0x0f, 0x58, 0xe3, 0xc1, 0x4f, 0xac, 0x2e, 0xc3, 0xbc, 0xca, 0xa8, 0xbc, 0xd9, 0x9e, 0xed, 0xe6, 0x4c, - 0x55, 0x2d, 0xf8, 0x2c, 0x0c, 0x2d, 0xda, 0xc5, 0xba, 0x39, 0xbb, 0xcd, 0x1b, 0x7c, 0x67, 0x92, 0x44, 0x6a, 0x29, - 0x89, 0xb4, 0xd5, 0xf5, 0xe9, 0xd2, 0xeb, 0x16, 0x15, 0x34, 0x46, 0x80, 0x5e, 0x92, 0xee, 0x2a, 0x9f, 0x50, 0xbc, - 0xb2, 0x1a, 0x56, 0xc3, 0x4b, 0x87, 0x22, 0x8c, 0xb5, 0x37, 0xe7, 0xf2, 0xec, 0x0e, 0xac, 0x47, 0x68, 0xed, 0xca, - 0xd5, 0x21, 0x6c, 0x3f, 0xd1, 0x7b, 0x4e, 0xae, 0xfe, 0x06, 0x54, 0x81, 0x73, 0x47, 0x43, 0x7d, 0xd2, 0x4e, 0x21, - 0xdb, 0x79, 0xb0, 0x24, 0xa8, 0x4a, 0xc9, 0x4d, 0xb9, 0x16, 0xa5, 0x94, 0x29, 0x5f, 0xcb, 0x6c, 0x65, 0xf7, 0xc9, - 0x00, 0xe2, 0xd9, 0xa0, 0x40, 0x72, 0x51, 0x5b, 0xcd, 0x41, 0xfa, 0x68, 0x96, 0x38, 0xd6, 0x0e, 0x0a, 0x2f, 0xcb, - 0xc1, 0xcc, 0x65, 0x2e, 0x97, 0x83, 0x82, 0x55, 0x7a, 0xab, 0x99, 0x66, 0xaa, 0x2f, 0x2a, 0x7b, 0x9b, 0xf1, 0x32, - 0xfd, 0x37, 0x4b, 0x06, 0x3c, 0xba, 0x7a, 0xe6, 0x07, 0x90, 0x26, 0x79, 0x1d, 0x20, 0x09, 0x36, 0x07, 0xbb, 0xd8, - 0x61, 0xd8, 0x2a, 0x56, 0xf6, 0xe4, 0xf9, 0x72, 0x87, 0xa6, 0x5c, 0xc2, 0x48, 0x4e, 0xcc, 0xa5, 0xd4, 0xf7, 0x25, - 0xd5, 0x0d, 0x05, 0x27, 0x9b, 0x26, 0xa0, 0x14, 0xd0, 0x6e, 0xc1, 0x7f, 0xe1, 0x53, 0x43, 0xa7, 0x05, 0x58, 0x6a, - 0xbb, 0x01, 0xff, 0x85, 0x7e, 0xb1, 0x7d, 0x44, 0xfd, 0xc0, 0x3c, 0x38, 0x98, 0xb5, 0x95, 0x31, 0x20, 0x22, 0x71, - 0x05, 0x79, 0x24, 0xf8, 0x41, 0xb1, 0xa7, 0xcb, 0xc4, 0x81, 0x33, 0xc5, 0xc5, 0x52, 0x6a, 0x33, 0xf3, 0xda, 0x6f, - 0xa9, 0x89, 0x37, 0x51, 0x12, 0x15, 0xb6, 0x43, 0x1a, 0xbd, 0xa4, 0x8c, 0xa9, 0x82, 0x0d, 0xd1, 0x7d, 0xdd, 0x04, - 0x53, 0xe0, 0x4d, 0x55, 0x05, 0x44, 0xa8, 0xbd, 0xc8, 0xf2, 0xfc, 0xa6, 0x0b, 0xac, 0x2e, 0xf8, 0xd4, 0x98, 0x66, - 0x17, 0xac, 0xe4, 0x6a, 0x26, 0x7d, 0xe6, 0xed, 0x40, 0x0b, 0x79, 0x97, 0x97, 0x45, 0x2b, 0x74, 0x3d, 0x88, 0x16, - 0xfe, 0x41, 0x73, 0x3c, 0x7a, 0xb6, 0xad, 0xa6, 0x36, 0xfb, 0x5a, 0x8b, 0x05, 0x32, 0x10, 0x0d, 0x7d, 0xa1, 0x62, - 0x14, 0xee, 0x2a, 0xcd, 0xd5, 0x6a, 0x5f, 0x95, 0x41, 0x02, 0x13, 0x41, 0xd6, 0xb2, 0xf0, 0x1e, 0xdd, 0xab, 0x47, - 0x9a, 0x57, 0x12, 0x3c, 0x73, 0xf1, 0x17, 0x00, 0x42, 0x79, 0x92, 0x90, 0x03, 0x72, 0x00, 0x7f, 0x4b, 0x51, 0x2a, - 0x0d, 0xf0, 0xcf, 0xea, 0x72, 0x6c, 0xeb, 0xfb, 0x3b, 0xad, 0x62, 0x70, 0xfd, 0xf9, 0xba, 0xeb, 0x59, 0x3b, 0xc4, - 0x39, 0xb7, 0xd5, 0x6b, 0xcb, 0x34, 0x8f, 0x91, 0xba, 0x06, 0xe0, 0x4e, 0xa4, 0x47, 0x20, 0x92, 0x99, 0x68, 0x90, - 0xb3, 0xe7, 0x7c, 0x3c, 0x15, 0x8f, 0x49, 0x7b, 0xb9, 0xef, 0x9b, 0x0b, 0x7d, 0x30, 0xc6, 0xbe, 0x05, 0x0d, 0xe2, - 0xa3, 0xd5, 0xd6, 0x0a, 0xc4, 0x7a, 0xa7, 0xd4, 0x87, 0x6e, 0x8c, 0x82, 0x0e, 0x1e, 0x71, 0x23, 0x17, 0x1c, 0xdb, - 0x5d, 0x5b, 0x4f, 0xe9, 0x2b, 0x00, 0x73, 0x1d, 0xa8, 0x64, 0x18, 0xa4, 0x2e, 0x13, 0x85, 0x49, 0x7e, 0x99, 0x90, - 0x84, 0x88, 0xea, 0x6c, 0x39, 0x4a, 0x95, 0x69, 0x01, 0x97, 0x19, 0x19, 0x60, 0x36, 0x69, 0xd6, 0x4f, 0x2e, 0x5f, - 0x62, 0x18, 0x01, 0xf1, 0x33, 0xfa, 0xb1, 0x56, 0x89, 0x97, 0x8c, 0xee, 0x1c, 0x75, 0x83, 0x2a, 0xc9, 0x5c, 0xbf, - 0xb9, 0x9d, 0x45, 0xca, 0xbc, 0x60, 0xb8, 0x5d, 0xa5, 0xf9, 0x87, 0xb0, 0x4e, 0xf0, 0xdb, 0x00, 0x95, 0xf4, 0xa9, - 0xf0, 0xa2, 0x11, 0x40, 0xa8, 0xef, 0x55, 0x19, 0x9f, 0x0a, 0x2f, 0x1b, 0xed, 0x58, 0x46, 0x29, 0x54, 0x17, 0xcc, - 0x6e, 0x4d, 0x17, 0xa2, 0x5b, 0x55, 0x03, 0x6d, 0xe0, 0xda, 0x15, 0x52, 0xba, 0x81, 0x6a, 0x57, 0x6e, 0x58, 0x80, - 0x68, 0x33, 0x11, 0x18, 0x2e, 0xff, 0x3e, 0x7f, 0xa9, 0x62, 0x78, 0xfa, 0xfd, 0xd0, 0x3b, 0xec, 0x82, 0x68, 0xb4, - 0xbb, 0x66, 0xfb, 0x20, 0x1a, 0xed, 0xaf, 0x1b, 0x46, 0xbf, 0x9f, 0xd1, 0xef, 0x67, 0x0d, 0xe8, 0x48, 0x84, 0x09, - 0xb3, 0xd7, 0x6f, 0xd4, 0xf2, 0x95, 0x5a, 0xbf, 0x53, 0xcb, 0x97, 0x6a, 0x78, 0xeb, 0x40, 0x12, 0x41, 0x64, 0xa9, - 0x6a, 0x1e, 0x24, 0x45, 0xaa, 0xa5, 0xcb, 0x31, 0x5a, 0x8c, 0xa8, 0xa5, 0xac, 0x39, 0xd5, 0x89, 0xb4, 0x73, 0x50, - 0x32, 0xc0, 0xd1, 0xe2, 0xaa, 0xc6, 0x74, 0xb3, 0xa2, 0x25, 0x10, 0x23, 0xac, 0x6c, 0xcb, 0xc5, 0x4d, 0xea, 0xa3, - 0x2b, 0xf2, 0x6d, 0xcb, 0x95, 0x6f, 0x5b, 0xc1, 0xab, 0xaf, 0x28, 0x94, 0x4b, 0xae, 0x95, 0xed, 0xd3, 0x42, 0x29, - 0x94, 0x71, 0x0d, 0xb6, 0xf6, 0x4d, 0x60, 0xc8, 0x7c, 0xa4, 0xa8, 0xb1, 0xbd, 0x68, 0x94, 0x43, 0x90, 0xad, 0x83, - 0x51, 0xa7, 0x2c, 0x58, 0x7c, 0xbb, 0x43, 0x06, 0x32, 0xd0, 0x51, 0xd5, 0xc6, 0xab, 0x9d, 0x95, 0xfe, 0xb0, 0xbc, - 0x7a, 0xc6, 0x12, 0x2b, 0x9d, 0xfc, 0xa6, 0x42, 0x7f, 0x10, 0xa2, 0x6f, 0xca, 0x96, 0x83, 0x17, 0x5d, 0x6c, 0x65, - 0x40, 0xbc, 0x61, 0x7a, 0x6f, 0x6b, 0x25, 0xcb, 0x5d, 0x53, 0xbe, 0x98, 0xf1, 0x84, 0xe3, 0xe8, 0xcb, 0xd5, 0x22, - 0xac, 0xd5, 0x22, 0x3b, 0x01, 0x1e, 0x5a, 0xab, 0xa5, 0x90, 0xab, 0x45, 0x38, 0x33, 0x5d, 0xa8, 0x99, 0x9e, 0x81, - 0xe6, 0x51, 0xa8, 0x59, 0x9e, 0x00, 0x16, 0xbc, 0x30, 0x33, 0x5c, 0x98, 0x19, 0x8e, 0x43, 0x6a, 0x9c, 0x1e, 0xf4, - 0x5e, 0xe7, 0x9e, 0x5b, 0xee, 0x46, 0xa7, 0x61, 0xde, 0x4e, 0x36, 0x98, 0xd3, 0x83, 0x70, 0x02, 0xf1, 0x81, 0x25, - 0x02, 0xf4, 0x68, 0x58, 0x1d, 0x35, 0x54, 0x8e, 0xe2, 0xcb, 0x02, 0x90, 0x2c, 0x09, 0x40, 0xf2, 0xa0, 0xc6, 0xb9, - 0xb4, 0xfc, 0xba, 0x4a, 0x42, 0x8e, 0xc8, 0x78, 0x29, 0xed, 0xee, 0x09, 0x2f, 0x47, 0x46, 0x68, 0x9e, 0x2c, 0x52, - 0xaf, 0x62, 0x19, 0x1b, 0x23, 0x70, 0x51, 0xe8, 0x37, 0x79, 0xbf, 0x9f, 0x96, 0x5e, 0x45, 0xed, 0xfc, 0x04, 0xfe, - 0x96, 0xe7, 0xce, 0x22, 0x47, 0xc8, 0xab, 0x91, 0x49, 0x58, 0x5e, 0x2a, 0xf5, 0xf4, 0x25, 0xcc, 0xa0, 0xee, 0xde, - 0x28, 0x00, 0xd7, 0x42, 0x39, 0xd5, 0x96, 0x70, 0x65, 0xaa, 0x0c, 0xf6, 0x79, 0xc8, 0x65, 0x68, 0x87, 0x44, 0x1e, - 0x29, 0xac, 0xfb, 0xf6, 0xd5, 0xb3, 0x89, 0xeb, 0xc3, 0x62, 0xa3, 0x11, 0x1c, 0x8f, 0x00, 0x73, 0x30, 0xf5, 0xa2, - 0x01, 0x2f, 0xd5, 0x9c, 0xf9, 0xe8, 0x55, 0x84, 0x8d, 0x01, 0x6a, 0x8a, 0x81, 0x53, 0xd6, 0x53, 0xf9, 0xc8, 0xf8, - 0x96, 0xf9, 0x7e, 0x80, 0xef, 0xd6, 0x85, 0x84, 0x7c, 0x50, 0xa8, 0x04, 0x99, 0x42, 0x25, 0x48, 0x0c, 0x2a, 0x41, - 0x6c, 0x50, 0x09, 0xb6, 0x0d, 0xdf, 0x48, 0xe5, 0x6d, 0x04, 0x1c, 0x11, 0x3e, 0xf4, 0x2c, 0x6c, 0xac, 0x50, 0x3c, - 0x1b, 0xb3, 0x31, 0x2b, 0xd4, 0xce, 0x53, 0xc9, 0xa9, 0xd8, 0x59, 0x8c, 0x75, 0x13, 0x59, 0x26, 0x5e, 0x48, 0xd0, - 0x71, 0xce, 0x85, 0x44, 0x5d, 0xfd, 0xdc, 0x7b, 0x49, 0xc6, 0x92, 0x79, 0x43, 0xa3, 0x06, 0xf3, 0xb2, 0xeb, 0x00, - 0xa6, 0x25, 0xdf, 0x16, 0x34, 0x98, 0x4e, 0x95, 0x47, 0xa4, 0x49, 0x50, 0x3b, 0x97, 0x49, 0x91, 0x13, 0xc2, 0x24, - 0xe8, 0x95, 0xe0, 0x37, 0x12, 0xda, 0xff, 0xab, 0x9e, 0xef, 0x80, 0xc1, 0x44, 0xab, 0xe4, 0x0b, 0x58, 0x2d, 0x2b, - 0xfe, 0x42, 0x7a, 0x62, 0x23, 0xfe, 0x62, 0x99, 0xc6, 0xa3, 0x2f, 0x6c, 0x88, 0x78, 0x56, 0x2f, 0xd0, 0xb4, 0x04, - 0x75, 0x80, 0x47, 0xf4, 0xd7, 0xe8, 0x8b, 0xe1, 0x4d, 0xe9, 0x6a, 0xa4, 0xae, 0xd9, 0x25, 0xe7, 0xef, 0x6a, 0x43, - 0x84, 0x8c, 0x69, 0x53, 0x20, 0x19, 0x10, 0x48, 0x32, 0x10, 0x00, 0x98, 0x9a, 0xce, 0xec, 0x15, 0x40, 0x34, 0x10, - 0xc0, 0xe3, 0xaa, 0xe3, 0xf1, 0x23, 0xfd, 0x55, 0x9c, 0xf6, 0x4e, 0xd3, 0xb0, 0xc3, 0x17, 0xa0, 0x29, 0x86, 0x72, - 0x3c, 0xdf, 0x29, 0x48, 0xf6, 0x28, 0x65, 0xe9, 0xaa, 0x89, 0xec, 0x50, 0xac, 0x4f, 0x73, 0xce, 0x42, 0xda, 0x96, - 0x63, 0xb4, 0xc5, 0xfa, 0x31, 0xf2, 0xde, 0xca, 0xa8, 0xc8, 0x07, 0x3d, 0xb8, 0xbd, 0xbd, 0x79, 0xd5, 0x63, 0x36, - 0xc9, 0x8a, 0x45, 0xae, 0x22, 0xce, 0x9c, 0xd6, 0x21, 0x07, 0x0c, 0xc8, 0x49, 0x08, 0x4c, 0x63, 0x5c, 0x2a, 0xd0, - 0x41, 0xc9, 0x72, 0x59, 0x03, 0xb5, 0x2c, 0x22, 0x6b, 0x80, 0xa8, 0xa6, 0xf9, 0x57, 0x0d, 0xf9, 0x49, 0xde, 0x9c, - 0x53, 0xa8, 0x7d, 0xc5, 0xc3, 0xea, 0xfc, 0x89, 0x55, 0x9b, 0x18, 0xeb, 0x5f, 0x6b, 0x4f, 0xd0, 0x56, 0xd2, 0x40, - 0x7c, 0xe7, 0xab, 0x74, 0x45, 0xa1, 0x3b, 0xce, 0x4c, 0x3c, 0x57, 0x81, 0xb1, 0x6f, 0xed, 0x08, 0x0a, 0x87, 0xa6, - 0xeb, 0x80, 0xc3, 0x34, 0x3a, 0x61, 0xf1, 0x4f, 0xe9, 0x38, 0x79, 0x55, 0x2b, 0x44, 0x92, 0xbf, 0x0b, 0x17, 0x86, - 0xc4, 0x82, 0xbc, 0x24, 0xd4, 0x11, 0x19, 0xb1, 0x1a, 0x15, 0x1b, 0xa1, 0xa2, 0xe2, 0x14, 0x8f, 0xb7, 0x0a, 0x8a, - 0x4b, 0x51, 0xaa, 0x94, 0x8a, 0xdc, 0xa8, 0x14, 0x10, 0xcb, 0x06, 0xde, 0x2d, 0xe0, 0x00, 0x08, 0x3a, 0xcb, 0xfd, - 0xc6, 0x76, 0xb7, 0x91, 0xf9, 0xcc, 0x34, 0x4f, 0xab, 0x0f, 0xea, 0xef, 0xf7, 0x4b, 0x8c, 0xad, 0xf1, 0xf4, 0xf7, - 0x6d, 0x5a, 0x70, 0xf3, 0x37, 0x0c, 0xd1, 0x0a, 0x10, 0x31, 0x4b, 0x7b, 0x28, 0x64, 0xc1, 0x84, 0x65, 0xa8, 0xca, - 0x53, 0x8e, 0x7a, 0xd5, 0xe4, 0x0e, 0x20, 0xd4, 0xd0, 0xaf, 0x8d, 0x4e, 0x75, 0x55, 0x82, 0xf0, 0x7d, 0x57, 0xa8, - 0xc7, 0xe6, 0x80, 0x27, 0x03, 0xe0, 0xaf, 0xc8, 0x6b, 0x3d, 0xb6, 0x7f, 0xd0, 0x1b, 0xf5, 0x06, 0x08, 0xa2, 0x73, - 0x59, 0xf8, 0x27, 0x9c, 0xeb, 0xd4, 0x9f, 0x71, 0x21, 0x88, 0x6f, 0x3d, 0x09, 0xef, 0xc5, 0x45, 0x1a, 0x07, 0x17, - 0xbd, 0x81, 0xb9, 0x08, 0x14, 0x17, 0x69, 0x7e, 0x01, 0x61, 0xf9, 0x88, 0x89, 0x58, 0xb3, 0x15, 0xc0, 0x04, 0x96, - 0x3a, 0x0e, 0x59, 0x75, 0x6c, 0xbf, 0xff, 0x7a, 0x64, 0xc8, 0xd2, 0x11, 0x06, 0x46, 0xff, 0x06, 0x14, 0xa1, 0x12, - 0x96, 0x99, 0xed, 0xc1, 0xa4, 0xab, 0x3d, 0xab, 0xe7, 0xcd, 0x36, 0xef, 0xea, 0x1d, 0xab, 0x69, 0x15, 0x35, 0x2d, - 0xb7, 0x9a, 0x36, 0xa9, 0xa0, 0x66, 0xa2, 0xdf, 0xd7, 0xa0, 0xa8, 0xd5, 0x1c, 0xc0, 0xd8, 0x30, 0xf9, 0xf5, 0x2c, - 0x9f, 0xf7, 0xfb, 0x9e, 0x7c, 0x04, 0xbf, 0x90, 0xad, 0xcc, 0xad, 0xb1, 0x7c, 0xfa, 0x8a, 0x48, 0xcc, 0x0c, 0xcc, - 0xd1, 0xea, 0x04, 0xdf, 0xeb, 0x56, 0x78, 0x1d, 0x73, 0x85, 0xcd, 0xc4, 0xf4, 0x35, 0x0c, 0x9e, 0x27, 0x7c, 0x70, - 0x91, 0xa3, 0xbf, 0x91, 0xc3, 0x4c, 0x61, 0x41, 0xce, 0xfd, 0xc9, 0x6b, 0xc4, 0x4b, 0x46, 0x78, 0x07, 0x9d, 0x4e, - 0x78, 0x90, 0xfd, 0xfe, 0x1a, 0x3a, 0xb3, 0x95, 0x4a, 0xd9, 0xaa, 0xa8, 0x4c, 0x37, 0x75, 0x51, 0x56, 0xd0, 0xb1, - 0xf4, 0xf3, 0x4e, 0xc8, 0xcc, 0xfa, 0x99, 0x05, 0xf7, 0xb4, 0x96, 0x00, 0x53, 0xb6, 0x6d, 0xa2, 0x36, 0xf0, 0xb2, - 0x2e, 0x3e, 0x17, 0x78, 0x74, 0xd6, 0x5e, 0x6f, 0x84, 0xda, 0x67, 0xb8, 0xcf, 0x6f, 0x3c, 0xf0, 0x83, 0x99, 0xa5, - 0x73, 0x45, 0x9c, 0x51, 0xf9, 0xa3, 0xcf, 0x45, 0x9a, 0x53, 0x1e, 0xe0, 0x3e, 0x14, 0x73, 0xfb, 0x2d, 0x90, 0x7e, - 0xe8, 0x2d, 0x90, 0x7d, 0x74, 0xce, 0xc9, 0x6b, 0x40, 0xa4, 0x43, 0x18, 0xdc, 0x9c, 0x04, 0x1d, 0xab, 0x86, 0x77, - 0x16, 0xd8, 0x69, 0x2f, 0x8d, 0x7b, 0x69, 0x7e, 0x91, 0xf6, 0xfb, 0x06, 0x35, 0x33, 0x45, 0x38, 0x78, 0x9c, 0x91, - 0x8b, 0xa4, 0x05, 0x5b, 0x4a, 0xfb, 0xaf, 0x06, 0x8e, 0xa8, 0x10, 0xa0, 0xf9, 0xef, 0xc2, 0x7b, 0x02, 0x10, 0x9b, - 0xb4, 0x01, 0x57, 0x3d, 0xa6, 0xa3, 0xb1, 0x25, 0x51, 0xab, 0xce, 0x06, 0x48, 0x9c, 0x2a, 0xad, 0xa7, 0xdc, 0xac, - 0x29, 0x0c, 0x52, 0x65, 0xa1, 0x7e, 0x63, 0x3d, 0x99, 0xac, 0x72, 0x91, 0x11, 0x47, 0x65, 0x7a, 0x57, 0x33, 0x82, - 0xe9, 0xd2, 0xcf, 0x17, 0xb0, 0x64, 0xe3, 0x8f, 0x38, 0x79, 0x4b, 0xc0, 0xb1, 0x9d, 0xb5, 0xab, 0x6a, 0x97, 0xe3, - 0xd6, 0x6e, 0x0e, 0xf0, 0xbd, 0xde, 0x68, 0x34, 0xd2, 0xce, 0x71, 0x02, 0x86, 0xaa, 0xa7, 0x96, 0x42, 0x8f, 0xd5, - 0x0a, 0x50, 0xb7, 0x23, 0x97, 0x59, 0x32, 0x98, 0x2f, 0x8c, 0xe3, 0x97, 0xe6, 0xa3, 0x8f, 0x97, 0xca, 0xda, 0x75, - 0xc4, 0xd7, 0x7f, 0x94, 0xd5, 0xfa, 0x96, 0x77, 0x55, 0x13, 0xf0, 0x45, 0x15, 0x50, 0xfa, 0x0d, 0xef, 0xc9, 0xde, - 0xc5, 0xd7, 0x6e, 0xb1, 0x4b, 0xbe, 0xe5, 0x2d, 0xea, 0x3c, 0x5f, 0x39, 0xb8, 0x51, 0xa5, 0xdb, 0x7b, 0xc9, 0x02, - 0xd7, 0xde, 0x49, 0xd3, 0x58, 0xcf, 0xfc, 0xe8, 0x61, 0x11, 0xb2, 0x9d, 0x8f, 0xbd, 0xaf, 0x9a, 0xa7, 0x67, 0x0d, - 0xbd, 0x49, 0x0d, 0x7d, 0xec, 0x45, 0xd9, 0x3e, 0x35, 0x8d, 0xe8, 0x35, 0x6c, 0xe8, 0x63, 0x6f, 0xc9, 0xc9, 0x21, - 0x11, 0xe0, 0xd4, 0x98, 0x3f, 0x3e, 0x9c, 0xce, 0xf0, 0x77, 0x0c, 0xa8, 0x04, 0x62, 0x3e, 0x3f, 0xa6, 0x1d, 0x05, - 0x98, 0x51, 0xa5, 0xb7, 0xcf, 0x0f, 0x6c, 0xc7, 0xcb, 0x7a, 0x68, 0xe9, 0xdd, 0xb3, 0xa3, 0xdb, 0xf1, 0xaa, 0x1a, - 0x5f, 0xca, 0x21, 0xcf, 0xf3, 0xd9, 0x68, 0x34, 0x12, 0x06, 0x92, 0x3b, 0xd7, 0x1b, 0x58, 0x81, 0xb4, 0x2d, 0xaa, - 0x0f, 0xe5, 0xd2, 0xdb, 0xab, 0x43, 0x3b, 0xf7, 0x27, 0xd5, 0xf1, 0x58, 0x8c, 0xcc, 0x31, 0x9e, 0xfb, 0xc7, 0x63, - 0xa1, 0xe4, 0x28, 0x59, 0x4b, 0x10, 0x9d, 0xd2, 0x78, 0x2a, 0xeb, 0xb5, 0x13, 0x91, 0x57, 0x23, 0xce, 0x43, 0xf0, - 0x57, 0x2f, 0x67, 0xa5, 0xfe, 0x54, 0xf8, 0xe8, 0xa7, 0x4a, 0xe9, 0x05, 0xaf, 0x0a, 0x08, 0x11, 0xfb, 0xbb, 0x81, - 0x76, 0x50, 0x82, 0x43, 0x09, 0xf7, 0x1e, 0xaf, 0x93, 0xaf, 0xbc, 0x6a, 0x26, 0x63, 0x94, 0x7b, 0x83, 0x7c, 0xce, - 0x00, 0xa6, 0xd2, 0x67, 0xe0, 0x77, 0x09, 0x50, 0xa7, 0xf8, 0x14, 0x9d, 0xea, 0xcd, 0xc3, 0xa6, 0xeb, 0xd3, 0x12, - 0x45, 0x11, 0xdd, 0xf9, 0xf9, 0x18, 0x10, 0x3b, 0xbb, 0x36, 0x23, 0xed, 0xda, 0x6f, 0xd0, 0x60, 0x95, 0x26, 0xad, - 0x95, 0x53, 0xc2, 0x6e, 0x57, 0x23, 0x5b, 0xfa, 0x51, 0x0a, 0xc4, 0xca, 0x71, 0x22, 0x91, 0x3d, 0xd8, 0xc8, 0x09, - 0xdc, 0xa2, 0xbd, 0xa3, 0x03, 0x50, 0xb9, 0x51, 0x90, 0x5f, 0xcd, 0x89, 0xdc, 0xf1, 0x7d, 0xef, 0xfb, 0x41, 0x3d, - 0xf8, 0xbe, 0x77, 0x91, 0x92, 0xdc, 0x11, 0x5e, 0xa8, 0x29, 0x21, 0xe2, 0x8b, 0xef, 0x07, 0xd5, 0x00, 0xcf, 0x12, - 0x2d, 0xd2, 0x22, 0xa1, 0x5a, 0x5d, 0xe3, 0x26, 0xbc, 0x48, 0x24, 0xf7, 0xd0, 0xbe, 0xf3, 0x88, 0x58, 0x00, 0x32, - 0x16, 0x9f, 0xcd, 0x1b, 0x0a, 0x75, 0x37, 0x31, 0x5b, 0x74, 0x97, 0xc5, 0x7e, 0x7f, 0x93, 0xa7, 0x75, 0x4f, 0xc7, - 0xc7, 0xe0, 0x0b, 0x52, 0x4d, 0x80, 0x47, 0xfb, 0x2b, 0x73, 0xbc, 0x7a, 0xb5, 0x39, 0x52, 0x16, 0xaa, 0x44, 0xfd, - 0x16, 0xab, 0x59, 0x0f, 0x61, 0xb8, 0xb3, 0xcc, 0x58, 0xdb, 0x0b, 0x9e, 0xcb, 0x59, 0x15, 0xdb, 0xe5, 0xf8, 0x8a, - 0xa5, 0x36, 0x97, 0xa8, 0x1c, 0xad, 0xc7, 0xda, 0x14, 0x23, 0xbf, 0x52, 0x48, 0x94, 0x45, 0xc7, 0xd6, 0x42, 0x01, - 0xf1, 0x02, 0xf4, 0x25, 0x7b, 0xd3, 0x00, 0xeb, 0x8d, 0x5e, 0x45, 0x84, 0x96, 0x8f, 0x54, 0x78, 0x9b, 0x9b, 0x2a, - 0xb3, 0xb2, 0x59, 0xb4, 0xfb, 0x29, 0xe7, 0x39, 0x82, 0xd5, 0x1b, 0xb5, 0x47, 0x01, 0x6a, 0x0f, 0x2d, 0x94, 0x01, - 0xa4, 0x34, 0xcd, 0x00, 0x90, 0x01, 0x40, 0xa6, 0x8a, 0xf8, 0x4c, 0x80, 0x4a, 0x5b, 0xdd, 0x28, 0x70, 0x22, 0xbd, - 0x02, 0x9a, 0x05, 0x56, 0xfa, 0x48, 0x41, 0x06, 0x8b, 0x2d, 0x02, 0xb0, 0x72, 0xe4, 0x0c, 0xd3, 0x18, 0xb2, 0x8d, - 0x26, 0x2e, 0x49, 0xf3, 0xfb, 0x30, 0x4b, 0x25, 0x9e, 0xc4, 0x8f, 0xb2, 0xc6, 0x08, 0x00, 0xa4, 0xef, 0xd3, 0x8b, - 0x22, 0x8b, 0x09, 0x07, 0xce, 0x7a, 0xea, 0xa0, 0xa8, 0xc9, 0xb9, 0xd6, 0xb4, 0x7a, 0x56, 0x9b, 0x3c, 0x64, 0x81, - 0xce, 0x1e, 0x8c, 0x49, 0x2d, 0xdf, 0xf3, 0xc8, 0xfe, 0xca, 0xe9, 0x8c, 0xf0, 0x5d, 0x77, 0x70, 0xea, 0xbf, 0xdb, - 0x1a, 0x98, 0x98, 0x12, 0x80, 0x8d, 0xc1, 0xd1, 0x84, 0xf8, 0x9d, 0x8e, 0xc9, 0xd4, 0x26, 0x45, 0x20, 0xf0, 0x10, - 0xbc, 0x82, 0xeb, 0x0b, 0x19, 0x30, 0x20, 0x68, 0x3b, 0x8b, 0x3c, 0x4d, 0x00, 0x4e, 0xbc, 0xe0, 0x3b, 0x80, 0xe3, - 0xd4, 0xab, 0x42, 0xf6, 0xec, 0xa5, 0x98, 0xce, 0xe6, 0xc1, 0x43, 0x42, 0xfb, 0x17, 0x13, 0x7e, 0xd3, 0x5d, 0x25, - 0x57, 0xa6, 0xd6, 0xbd, 0x89, 0xae, 0x72, 0x95, 0xd3, 0xa7, 0x39, 0xc7, 0x30, 0x67, 0xb0, 0x0a, 0xc8, 0x39, 0x1b, - 0xf2, 0xe7, 0x97, 0x00, 0xd8, 0xb2, 0x16, 0x5e, 0xc4, 0x9f, 0x87, 0xb2, 0x5a, 0x00, 0xf7, 0xc8, 0x79, 0x64, 0x7e, - 0xf9, 0x6a, 0x3b, 0x94, 0x73, 0x8a, 0xc2, 0x58, 0xce, 0x4d, 0x4b, 0x8a, 0xd3, 0xa1, 0xa7, 0x60, 0x32, 0xb5, 0xe5, - 0xef, 0x5d, 0xe2, 0x32, 0x7b, 0x33, 0x09, 0xe7, 0xeb, 0xc8, 0xb6, 0xb5, 0xea, 0x1e, 0xba, 0x21, 0x18, 0xf4, 0x31, - 0x82, 0x96, 0xd5, 0x9b, 0x5f, 0x31, 0x18, 0x28, 0x6c, 0xdf, 0x9a, 0x6e, 0x5a, 0x74, 0x8a, 0x03, 0xce, 0xac, 0x75, - 0x8d, 0x4a, 0x55, 0x71, 0xe8, 0x25, 0xef, 0x96, 0x95, 0xdb, 0x65, 0xe9, 0x85, 0x20, 0x35, 0xea, 0x2a, 0x42, 0xa4, - 0x54, 0xec, 0xf0, 0x9e, 0xfc, 0x1a, 0x98, 0x78, 0x66, 0xe5, 0x28, 0x8d, 0xe7, 0x00, 0x13, 0xa4, 0xd0, 0x37, 0xe5, - 0x57, 0x80, 0x1b, 0xba, 0x88, 0xc2, 0xec, 0x4d, 0x5c, 0x05, 0xb5, 0xd5, 0xf4, 0x7b, 0x07, 0x27, 0xf6, 0xb2, 0xee, - 0xf7, 0x53, 0xa2, 0xf1, 0xc3, 0xd0, 0x0b, 0xfc, 0x7b, 0x3c, 0x3d, 0x34, 0x41, 0x6a, 0x5e, 0x79, 0x80, 0x57, 0x74, - 0xb9, 0xb5, 0x29, 0x57, 0x34, 0x2e, 0xe6, 0x35, 0x22, 0xc2, 0xa7, 0x8e, 0x62, 0xbb, 0xcd, 0x8f, 0x53, 0x1b, 0x83, - 0x41, 0x08, 0xf7, 0xad, 0x8c, 0xdf, 0x27, 0x5e, 0x35, 0x8b, 0xe6, 0xa0, 0x28, 0xcd, 0x34, 0x49, 0x48, 0x21, 0xbd, - 0x04, 0xe8, 0xa3, 0x41, 0xa8, 0xd5, 0x95, 0x7f, 0x24, 0x5e, 0xaa, 0xa6, 0xb5, 0x79, 0x8a, 0x35, 0x0a, 0xc4, 0x2c, - 0x9a, 0x37, 0x2c, 0xa3, 0x43, 0x52, 0x5d, 0x2e, 0x4d, 0x33, 0xfe, 0xb0, 0x9a, 0xa1, 0x5a, 0x71, 0xd2, 0x04, 0x35, - 0x4a, 0xb7, 0x70, 0x01, 0xfc, 0x1b, 0xdd, 0x71, 0x54, 0xa3, 0x48, 0xd1, 0x80, 0x4f, 0x20, 0xa6, 0xab, 0x30, 0x9b, - 0x27, 0xac, 0x35, 0x75, 0xcd, 0xe8, 0xf7, 0x65, 0x9c, 0x90, 0x49, 0x42, 0x72, 0x3e, 0x5c, 0xae, 0x1f, 0x49, 0x75, - 0x01, 0xa4, 0xca, 0x39, 0x9b, 0xf5, 0x7a, 0x73, 0xc0, 0xe8, 0x85, 0xf5, 0x0b, 0x1b, 0x57, 0x70, 0x79, 0x4d, 0x98, - 0xbb, 0xea, 0x47, 0x98, 0x65, 0x50, 0x05, 0xa4, 0xf9, 0xb1, 0xa0, 0xd3, 0x2b, 0x17, 0x88, 0xfa, 0xf5, 0x48, 0x5d, - 0x50, 0x66, 0xe9, 0xdc, 0x22, 0x02, 0x01, 0xaf, 0x61, 0xf5, 0x04, 0x92, 0x7d, 0xf9, 0xd8, 0xa7, 0x19, 0x05, 0xaa, - 0x23, 0x00, 0x65, 0xb3, 0x7e, 0x08, 0xfb, 0x07, 0x84, 0x13, 0xea, 0x6f, 0xde, 0xca, 0x59, 0x43, 0xf2, 0x40, 0xaa, - 0x09, 0x8f, 0xe1, 0xd4, 0x58, 0xe0, 0x4b, 0x8b, 0xde, 0x54, 0xf0, 0x9a, 0xe0, 0xb8, 0x17, 0x68, 0xed, 0x5b, 0xc0, - 0x11, 0x22, 0xb8, 0x0c, 0x4d, 0x9c, 0xf6, 0xf6, 0xbd, 0x00, 0x09, 0xcd, 0x2d, 0x9c, 0xeb, 0xb7, 0x2e, 0x68, 0x71, - 0x8a, 0x9c, 0x2c, 0xba, 0xc0, 0x40, 0x17, 0x64, 0xde, 0xf8, 0x67, 0x0e, 0x2b, 0x17, 0x20, 0x7b, 0xa9, 0x58, 0x49, - 0xc4, 0xb6, 0x57, 0x7f, 0x94, 0xca, 0x7e, 0x7b, 0x61, 0x4d, 0xe0, 0x97, 0x89, 0xfd, 0x12, 0x99, 0x7c, 0xd3, 0x53, - 0x93, 0xaf, 0x8c, 0x85, 0x4e, 0x2d, 0x83, 0x73, 0x7a, 0x62, 0x70, 0xee, 0xed, 0xad, 0xda, 0x94, 0x30, 0x14, 0x24, - 0x81, 0xa6, 0x4b, 0x0f, 0xeb, 0xa6, 0x3f, 0x3f, 0x69, 0xf1, 0x6b, 0xd5, 0xbe, 0x75, 0x3f, 0x0e, 0xb1, 0x8b, 0x5f, - 0x26, 0x9e, 0x61, 0x1f, 0xf5, 0x81, 0x03, 0x4c, 0x46, 0x4c, 0x5c, 0xf7, 0xfb, 0x50, 0xd8, 0x6c, 0x3c, 0x1f, 0xd5, - 0xc5, 0xcf, 0xc5, 0x03, 0x40, 0x39, 0x54, 0x60, 0x97, 0x43, 0x19, 0xca, 0x88, 0x4d, 0x6d, 0xb9, 0xe7, 0xf7, 0x97, - 0x61, 0x0e, 0xf2, 0x8e, 0xc6, 0xc4, 0xb9, 0x00, 0x31, 0x0c, 0xbe, 0xfe, 0xfd, 0x93, 0x43, 0xda, 0x7c, 0x7f, 0x01, - 0xdf, 0x1d, 0x5d, 0x7c, 0x40, 0x8e, 0x9b, 0x8b, 0x4d, 0x59, 0xdc, 0xa7, 0xb1, 0xb8, 0xf8, 0x1e, 0x52, 0xbf, 0xbf, - 0x28, 0xca, 0x8b, 0xef, 0x55, 0x65, 0xbe, 0xbf, 0xa0, 0x05, 0x37, 0xfa, 0xdd, 0x9a, 0x78, 0xff, 0xc8, 0x35, 0xed, - 0xd9, 0x12, 0xc2, 0xb1, 0xb4, 0xfa, 0x11, 0x94, 0x88, 0x8a, 0x14, 0x55, 0x86, 0xb2, 0x5a, 0x3b, 0xce, 0xfb, 0x44, - 0xc3, 0x63, 0xd3, 0x84, 0xc4, 0xd5, 0x12, 0xd6, 0xa1, 0x9e, 0x9d, 0x36, 0xc9, 0x8e, 0xf3, 0x40, 0x1d, 0x10, 0x15, - 0x7f, 0x5e, 0x8d, 0x76, 0xf4, 0x35, 0xf8, 0xd6, 0xf1, 0x58, 0x8d, 0xf6, 0xe6, 0xa7, 0x4f, 0xd6, 0x4a, 0x19, 0x6c, - 0xa4, 0x18, 0x85, 0x90, 0x28, 0x6e, 0xd7, 0x63, 0x00, 0xfc, 0xef, 0x1f, 0x8f, 0xf4, 0x7b, 0x2f, 0x7f, 0xab, 0xdd, - 0xd2, 0xaa, 0xe7, 0x87, 0x16, 0x61, 0xc6, 0xab, 0xda, 0xb0, 0xb3, 0x1d, 0x24, 0xa0, 0xf4, 0xa1, 0x69, 0x50, 0x53, - 0x44, 0x3f, 0x61, 0x35, 0xb1, 0x9c, 0xc3, 0x82, 0x94, 0x38, 0xc4, 0x70, 0x8c, 0x76, 0xe8, 0x71, 0xba, 0xa8, 0x79, - 0x2a, 0xdf, 0x21, 0xe3, 0xd6, 0xf7, 0x01, 0xc9, 0xa5, 0x70, 0xf9, 0xc1, 0x0b, 0x0d, 0x26, 0x7a, 0x91, 0x57, 0x45, - 0x26, 0x46, 0x82, 0x46, 0xf9, 0x0d, 0x89, 0x33, 0x17, 0x58, 0x8b, 0x0b, 0x85, 0x10, 0x16, 0x12, 0x2a, 0x77, 0x51, - 0x52, 0x7a, 0x70, 0xf1, 0xe4, 0x50, 0x36, 0xbf, 0x13, 0x26, 0xc4, 0x68, 0x01, 0x34, 0x38, 0xfb, 0x76, 0x79, 0x0f, - 0x61, 0x99, 0x7b, 0xbf, 0xbf, 0x59, 0xe5, 0x05, 0xc4, 0x65, 0x5e, 0x48, 0xc5, 0x6a, 0x79, 0x01, 0x34, 0x79, 0x22, - 0xbe, 0x08, 0x2b, 0x39, 0x0d, 0xaa, 0x8e, 0x62, 0xd5, 0x36, 0x5e, 0x56, 0x1e, 0xf0, 0x7a, 0xbf, 0x4f, 0x80, 0xc0, - 0xdd, 0x67, 0xaf, 0x95, 0x5b, 0x2a, 0xe9, 0x91, 0xe7, 0x18, 0x22, 0x99, 0x00, 0xaf, 0x33, 0x04, 0x47, 0x0a, 0xab, - 0xe7, 0x26, 0xc8, 0x3f, 0xbe, 0x39, 0xa3, 0xf8, 0xa2, 0x79, 0x14, 0x35, 0x2c, 0x64, 0x09, 0x1c, 0x0f, 0xc9, 0x2c, - 0x9b, 0x23, 0x35, 0x79, 0xda, 0x9e, 0x22, 0x1d, 0x9d, 0x58, 0xe2, 0xb7, 0x35, 0xa9, 0x5e, 0xa4, 0xc2, 0x2e, 0x69, - 0x67, 0x2b, 0x2a, 0x2f, 0x84, 0xa1, 0x4a, 0xb8, 0xf7, 0xaa, 0x9e, 0x85, 0x72, 0x53, 0xb4, 0x2a, 0x66, 0x0f, 0x53, - 0x62, 0x86, 0x29, 0xd6, 0x5f, 0xd8, 0xf2, 0xdb, 0xc4, 0x8b, 0xc1, 0x70, 0xbd, 0xe4, 0xe5, 0x6c, 0x6b, 0x16, 0xc2, - 0xf1, 0xb8, 0x9d, 0x14, 0xb3, 0x25, 0xc4, 0xb6, 0x2e, 0xe7, 0xc7, 0x63, 0x57, 0xcb, 0x36, 0xc2, 0x83, 0x87, 0xaa, - 0x85, 0xdb, 0x86, 0x55, 0xf0, 0x33, 0x99, 0xc5, 0xd8, 0xbe, 0xc6, 0x67, 0xf6, 0xe7, 0x8b, 0xee, 0x59, 0x82, 0x8c, - 0x1b, 0x1b, 0xe0, 0x1a, 0x9b, 0xb5, 0x3b, 0x5c, 0x8d, 0x80, 0xe4, 0x71, 0x37, 0xfa, 0xbb, 0xb2, 0x93, 0x9c, 0x04, - 0x09, 0xa3, 0x15, 0xc2, 0xef, 0xa1, 0xf1, 0x27, 0x5a, 0xec, 0x41, 0xbb, 0x8d, 0x2d, 0x21, 0xaa, 0x69, 0xcf, 0xe5, - 0x4a, 0xb1, 0x34, 0x6f, 0xa5, 0x0d, 0x99, 0x0f, 0xeb, 0xf3, 0xd0, 0xc8, 0x81, 0x82, 0x31, 0xe2, 0xa9, 0x75, 0x10, - 0xcd, 0xe6, 0xc0, 0x7d, 0x81, 0xe6, 0x11, 0x9e, 0x5a, 0x90, 0xa0, 0xcc, 0xda, 0xb0, 0x9f, 0x24, 0x67, 0xcb, 0xe3, - 0xf0, 0x2d, 0xfc, 0xcb, 0x67, 0xd8, 0x24, 0xa6, 0x28, 0x1e, 0x7f, 0xcb, 0x15, 0xff, 0x1d, 0x5b, 0x10, 0xc1, 0xda, - 0xad, 0xa8, 0x0d, 0x7f, 0xc3, 0xbf, 0x84, 0x7d, 0x84, 0xfd, 0x96, 0xe3, 0x4d, 0xd2, 0x10, 0x90, 0x09, 0xc4, 0x85, - 0x85, 0x20, 0xc1, 0xdf, 0x72, 0xc9, 0x3f, 0x27, 0x7c, 0xb6, 0x28, 0x81, 0xac, 0x0e, 0xa3, 0xf8, 0x84, 0x62, 0xa2, - 0x10, 0x86, 0x5b, 0x42, 0xef, 0xe8, 0xbf, 0x11, 0x25, 0xd9, 0xa4, 0xb2, 0x62, 0x3d, 0x90, 0x49, 0x12, 0x4c, 0xb0, - 0xf2, 0x42, 0xf9, 0xc2, 0xbd, 0x50, 0x6a, 0xad, 0x05, 0xad, 0x5f, 0xfe, 0x24, 0xf1, 0x0c, 0xe8, 0x1e, 0xc8, 0x18, - 0x74, 0x1b, 0x51, 0x4d, 0x72, 0x4c, 0x1f, 0xa5, 0xf3, 0x0c, 0x54, 0x40, 0x17, 0x9b, 0x2c, 0xac, 0x97, 0x45, 0xb9, - 0x6e, 0x85, 0x87, 0xca, 0xd2, 0x47, 0xea, 0x31, 0xe6, 0x85, 0x79, 0x72, 0x26, 0x1f, 0x3c, 0x02, 0x34, 0x3c, 0xca, - 0xd3, 0xaa, 0xa3, 0xb4, 0x7e, 0x60, 0x19, 0x30, 0x02, 0x67, 0xca, 0x80, 0x47, 0x58, 0x06, 0xe6, 0x69, 0x97, 0xa1, - 0x06, 0xb1, 0x46, 0xd5, 0x95, 0xda, 0x60, 0xce, 0x14, 0x25, 0x9f, 0x62, 0x69, 0x85, 0x31, 0x34, 0x75, 0xe5, 0x91, - 0xf5, 0x92, 0x13, 0xf6, 0x6c, 0x37, 0x90, 0x6e, 0x61, 0xab, 0xc0, 0x05, 0x5d, 0xcb, 0x12, 0xe5, 0xa2, 0x5b, 0x46, - 0x94, 0x89, 0x90, 0xfa, 0xd9, 0xc3, 0x99, 0x56, 0xfb, 0x8d, 0x9d, 0x74, 0x68, 0x8f, 0x14, 0xbd, 0x60, 0x20, 0x3e, - 0xed, 0x91, 0x52, 0xcf, 0x1a, 0xb9, 0x0c, 0x6c, 0xe9, 0x52, 0xd5, 0xf3, 0x5f, 0xa0, 0x7c, 0x07, 0x33, 0xe3, 0x6c, - 0xf6, 0xbb, 0xde, 0xdc, 0x9e, 0x1c, 0xea, 0xe6, 0x77, 0xd6, 0xeb, 0xc1, 0xd6, 0x20, 0x13, 0x5f, 0x28, 0xea, 0x29, - 0xab, 0x10, 0x2b, 0x32, 0xfb, 0x5f, 0xc2, 0xfb, 0x1d, 0xde, 0x1a, 0xa1, 0x59, 0x19, 0x0f, 0xf3, 0xd1, 0x93, 0x83, - 0x68, 0x7e, 0xef, 0x2c, 0xdb, 0xca, 0x55, 0xc9, 0x6c, 0xbf, 0x9f, 0x24, 0xcd, 0xd9, 0xe3, 0x35, 0x92, 0x3a, 0xc0, - 0xc7, 0xeb, 0x33, 0x7c, 0xa4, 0x12, 0x4a, 0x2d, 0xa8, 0x6a, 0xd0, 0xfa, 0xd8, 0xef, 0xad, 0xe7, 0xf4, 0xf1, 0x53, - 0x39, 0xdd, 0x92, 0x22, 0x8c, 0x1f, 0x18, 0x4c, 0xd9, 0x89, 0x53, 0x97, 0xaa, 0x19, 0xd2, 0xbb, 0x6e, 0x95, 0xd4, - 0x65, 0x8f, 0x12, 0x41, 0xa8, 0x83, 0xf5, 0x8b, 0xfd, 0x10, 0x66, 0xb6, 0xe8, 0x0f, 0x9b, 0xd5, 0x9c, 0x50, 0x10, - 0x01, 0xa2, 0x55, 0xde, 0x07, 0x4e, 0x49, 0xc2, 0xac, 0xb9, 0x21, 0xdd, 0x7a, 0x2b, 0xa5, 0xbd, 0x92, 0x02, 0xfa, - 0x65, 0x7e, 0x3c, 0xa2, 0xf9, 0xcd, 0xec, 0x5c, 0x95, 0xb4, 0xe5, 0x00, 0x22, 0x75, 0xde, 0xb4, 0x2f, 0x1d, 0x0e, - 0xfe, 0x83, 0xba, 0x12, 0xe5, 0x44, 0xd0, 0x51, 0xb4, 0x60, 0xb4, 0x5a, 0xb5, 0xab, 0xc8, 0xa6, 0x42, 0xb6, 0x24, - 0xc2, 0x89, 0x92, 0xbd, 0x12, 0xea, 0xa3, 0x5c, 0xed, 0x99, 0x86, 0xf8, 0x33, 0x01, 0x9b, 0x36, 0xf8, 0x5b, 0xe0, - 0x5e, 0x06, 0x67, 0xa6, 0x7d, 0x1a, 0x46, 0x40, 0x64, 0x0e, 0xc1, 0x7e, 0x7e, 0xd7, 0x83, 0x1c, 0x1e, 0x74, 0xa4, - 0xbf, 0xaa, 0x67, 0x05, 0x9e, 0xb9, 0x67, 0x9e, 0xbf, 0x3e, 0x93, 0x9e, 0x57, 0xf0, 0x40, 0x73, 0x1f, 0x66, 0xfc, - 0x45, 0x59, 0x86, 0xfb, 0xd1, 0xb2, 0x2c, 0xd6, 0x5e, 0xa4, 0xf7, 0xf1, 0x4c, 0x8a, 0x81, 0x44, 0x87, 0x99, 0xd1, - 0x55, 0xac, 0xe3, 0x1c, 0xc6, 0xbd, 0x3d, 0x09, 0x2b, 0xb4, 0x7f, 0x96, 0xd8, 0xeb, 0x02, 0x00, 0x1c, 0xb2, 0x06, - 0xad, 0xf0, 0x4e, 0xb7, 0xb7, 0x7b, 0x5c, 0x52, 0xa2, 0xb8, 0x51, 0xf3, 0xb3, 0x1a, 0x5a, 0x26, 0xa8, 0x65, 0xd6, - 0x9d, 0x4c, 0xa6, 0x48, 0x02, 0xdf, 0x86, 0xbd, 0x66, 0x79, 0x35, 0x6f, 0xe4, 0xf6, 0xf0, 0x2e, 0x5c, 0x8b, 0x58, - 0x5b, 0xd0, 0x49, 0x47, 0xc6, 0xe1, 0x5e, 0x68, 0x6e, 0xa4, 0x87, 0x27, 0x55, 0x12, 0x96, 0x22, 0x86, 0x5b, 0x20, - 0x3b, 0xa8, 0x6d, 0x25, 0x28, 0x81, 0x04, 0xf6, 0x43, 0x29, 0x96, 0xe9, 0x4e, 0x00, 0x98, 0x03, 0xff, 0x53, 0x1a, - 0xbb, 0xdd, 0x9d, 0x87, 0x78, 0xd5, 0xc8, 0xfb, 0x06, 0x21, 0xd8, 0x5f, 0x81, 0x9c, 0x06, 0x0c, 0x22, 0xc5, 0x48, - 0x16, 0x0c, 0x24, 0x00, 0x15, 0xdf, 0x80, 0x49, 0x6e, 0x5a, 0x79, 0x7e, 0x50, 0xe9, 0x0e, 0xa6, 0x7d, 0xd0, 0xbd, - 0xb8, 0xd6, 0x0c, 0x90, 0x7f, 0x27, 0x11, 0xff, 0x5b, 0xed, 0x95, 0xac, 0x62, 0x99, 0xdf, 0x98, 0x8b, 0x4e, 0x06, - 0x57, 0x0d, 0xe1, 0x17, 0xb3, 0x6c, 0xce, 0xa3, 0x59, 0xa6, 0x43, 0xfd, 0x8b, 0xe6, 0xa4, 0x14, 0xc0, 0x50, 0xc7, - 0x0b, 0xb0, 0xc6, 0xbb, 0xd2, 0x4d, 0x2b, 0x1e, 0x69, 0x8c, 0x51, 0x50, 0xa1, 0x83, 0xd0, 0xdf, 0x6a, 0x80, 0xd7, - 0x60, 0x92, 0x1b, 0x21, 0xf7, 0xc1, 0x05, 0xdd, 0xd0, 0x2d, 0xe7, 0x2e, 0x41, 0x4d, 0xaa, 0x96, 0x5f, 0x85, 0x50, - 0xef, 0x6a, 0xc9, 0xa5, 0xda, 0x7c, 0x6a, 0x94, 0x35, 0x82, 0x4c, 0x8e, 0xd2, 0xef, 0x53, 0x2e, 0xdc, 0xdc, 0x98, - 0xac, 0x8f, 0x47, 0xaf, 0xe0, 0xa6, 0xc6, 0x3f, 0x56, 0x92, 0x45, 0xd4, 0x1a, 0x12, 0x61, 0x6b, 0xb7, 0x42, 0xf7, - 0x1e, 0x37, 0x4a, 0xf3, 0x28, 0xdb, 0xc6, 0xa2, 0xf2, 0x7a, 0x09, 0x58, 0x8b, 0x7b, 0x40, 0x86, 0x4a, 0x4b, 0x3f, - 0x67, 0x05, 0x40, 0x06, 0x48, 0x61, 0xe3, 0x47, 0xa4, 0xbd, 0xfa, 0xe0, 0xa5, 0x7e, 0xbf, 0x6f, 0x4c, 0xf9, 0xef, - 0x1f, 0x72, 0x60, 0x26, 0x14, 0x65, 0xbd, 0x87, 0x09, 0x54, 0x79, 0xa9, 0x4f, 0xda, 0xb3, 0x9a, 0x3f, 0xdf, 0xd4, - 0x1e, 0x90, 0x5a, 0xf9, 0x16, 0x73, 0xd5, 0x2b, 0xfb, 0x62, 0x73, 0x48, 0xab, 0x5b, 0xa3, 0x71, 0x10, 0x2c, 0xad, - 0xde, 0x68, 0x95, 0x43, 0xd5, 0xf0, 0x1c, 0x44, 0x2a, 0xeb, 0xea, 0x9a, 0x3b, 0x57, 0xd7, 0x82, 0x23, 0x81, 0x6c, - 0xc9, 0x21, 0x2c, 0x8d, 0x85, 0xdc, 0x2b, 0x8f, 0xc7, 0xc2, 0xef, 0xf7, 0xd3, 0x59, 0x8e, 0x97, 0x16, 0xa0, 0x4c, - 0xdb, 0xd4, 0x5e, 0xe8, 0x1f, 0x8f, 0x3f, 0x82, 0xd7, 0x88, 0x7f, 0x3c, 0x96, 0xfd, 0xfe, 0x47, 0x73, 0x93, 0xb9, - 0x1c, 0x2b, 0xa5, 0xec, 0x35, 0x2a, 0xdd, 0xdf, 0x24, 0xbc, 0xf7, 0xbf, 0x47, 0xff, 0x7b, 0x74, 0xdd, 0x53, 0x01, - 0x60, 0x09, 0x9f, 0xe1, 0x0d, 0x9d, 0xa9, 0xcb, 0x39, 0x93, 0xee, 0xee, 0xca, 0x0f, 0xbd, 0xa7, 0xf1, 0xe1, 0x7b, - 0x73, 0xd3, 0xc6, 0x5f, 0xf3, 0x13, 0x4d, 0x42, 0xc7, 0x45, 0xff, 0x78, 0xfc, 0x94, 0x68, 0x7d, 0x5a, 0xaa, 0xf4, - 0x69, 0x0a, 0x3c, 0xc9, 0xb0, 0xe1, 0xba, 0x85, 0xe9, 0x68, 0x7e, 0xdc, 0x7c, 0x95, 0xbc, 0x38, 0x4b, 0xe1, 0xda, - 0x0b, 0x3a, 0x97, 0x29, 0x58, 0x57, 0x86, 0xe0, 0x66, 0x10, 0x40, 0xea, 0x10, 0xd2, 0xac, 0x69, 0xf8, 0x97, 0xdc, - 0x15, 0xbc, 0xb5, 0xc7, 0xbb, 0xc1, 0x88, 0x52, 0x47, 0xfa, 0xa4, 0x0d, 0xa1, 0x4b, 0x2a, 0xf9, 0x8f, 0x22, 0x8f, - 0x31, 0x66, 0xe3, 0x15, 0x91, 0x7d, 0x16, 0xf9, 0xcb, 0x02, 0x00, 0x8b, 0x00, 0x01, 0x39, 0x9d, 0x3b, 0x92, 0xf8, - 0xcf, 0xc9, 0xb7, 0x7f, 0x4c, 0x97, 0xf6, 0xa1, 0x2c, 0x56, 0xa5, 0xa8, 0xaa, 0x93, 0xd2, 0xf6, 0xb6, 0x5c, 0x0f, - 0xf4, 0xa1, 0xfd, 0xbe, 0xa4, 0x0f, 0x4d, 0x31, 0x14, 0x05, 0x6e, 0x8d, 0xbd, 0x69, 0xca, 0x15, 0x4d, 0xf5, 0xc8, - 0x58, 0x3f, 0x7f, 0xd8, 0xbf, 0x89, 0xbd, 0xd4, 0x0f, 0x52, 0x10, 0x84, 0x35, 0x7e, 0x52, 0x8a, 0x24, 0x70, 0x3e, - 0xc3, 0x54, 0xe2, 0xd3, 0xa5, 0x54, 0xf9, 0xc3, 0x48, 0xf3, 0x61, 0x0a, 0x7a, 0xd9, 0xbf, 0xe7, 0x30, 0xff, 0x75, - 0x7b, 0xb0, 0x3e, 0xad, 0xcb, 0x34, 0xaa, 0x88, 0x2a, 0x2f, 0x4c, 0xb5, 0x09, 0x44, 0xf0, 0xe7, 0xc2, 0x22, 0xf9, - 0xf5, 0xc9, 0x91, 0xa0, 0x31, 0x93, 0xe5, 0xe3, 0x89, 0xfb, 0x85, 0x7d, 0xe5, 0x3a, 0x9d, 0xff, 0x95, 0x99, 0xff, - 0x03, 0x8c, 0x49, 0x28, 0x9e, 0x73, 0xcb, 0x60, 0x81, 0xb3, 0x5f, 0xba, 0x7a, 0xc0, 0xdf, 0xcc, 0x13, 0xcf, 0x81, - 0x83, 0xf9, 0x39, 0xba, 0x2a, 0xa6, 0xb3, 0x62, 0x00, 0x04, 0xb6, 0x7e, 0x63, 0xcd, 0x89, 0xd7, 0x16, 0xcf, 0x95, - 0x5c, 0x10, 0xfa, 0xba, 0x0a, 0xb3, 0x71, 0x5d, 0x6c, 0x2b, 0x51, 0x6c, 0x21, 0x6c, 0x04, 0xd4, 0xb2, 0xd5, 0xb4, - 0xb6, 0x15, 0xb2, 0x3f, 0x89, 0x16, 0x6d, 0x97, 0xa1, 0x9a, 0x8c, 0xb2, 0x74, 0x33, 0x05, 0x52, 0xbd, 0x00, 0xce, - 0x22, 0xf3, 0xca, 0x3b, 0x67, 0x0f, 0xd8, 0xa1, 0xf1, 0x14, 0x18, 0x51, 0xe9, 0x8f, 0xaa, 0x31, 0x3a, 0x3d, 0xd1, - 0xef, 0x57, 0x53, 0x0a, 0xf9, 0xfa, 0x09, 0x30, 0xb9, 0x6a, 0xb9, 0x00, 0x7d, 0x19, 0xea, 0xa0, 0x12, 0xa5, 0x56, - 0x0c, 0x23, 0x16, 0x7e, 0x12, 0xc8, 0xde, 0x4c, 0x41, 0xcd, 0x2a, 0x4a, 0x42, 0x25, 0x2a, 0x25, 0x5b, 0x13, 0xd4, - 0xd2, 0xfb, 0xa2, 0xa8, 0x0f, 0x15, 0x38, 0x4a, 0x46, 0xda, 0x2c, 0xa7, 0xcc, 0xb8, 0x28, 0x73, 0xd1, 0x0f, 0xf6, - 0x2f, 0xc0, 0xf8, 0x92, 0xf9, 0x2c, 0xf7, 0x1d, 0x9d, 0xd3, 0x76, 0x5c, 0xa0, 0xcc, 0x2d, 0xa7, 0xad, 0x96, 0x3c, - 0x26, 0xef, 0x59, 0xb0, 0xed, 0xbf, 0x48, 0x90, 0x57, 0x11, 0xe6, 0x13, 0xaa, 0x6c, 0xfe, 0x9e, 0x7b, 0xc4, 0x3e, - 0xda, 0xe1, 0xc2, 0x44, 0xa4, 0xb7, 0x60, 0x49, 0x0c, 0xb3, 0x52, 0x84, 0xf1, 0x1e, 0xbc, 0x7f, 0xb6, 0x95, 0x18, - 0x5d, 0xa0, 0x93, 0xfb, 0xc5, 0x43, 0x5a, 0x27, 0x17, 0x6f, 0x5e, 0x5d, 0x7c, 0xdf, 0x1b, 0x14, 0xa3, 0x34, 0x1e, - 0xf4, 0xbe, 0xbf, 0x58, 0x6f, 0x01, 0x22, 0x53, 0x5c, 0xc4, 0x64, 0x4a, 0x13, 0xf1, 0x05, 0x19, 0x06, 0x2f, 0xea, - 0x44, 0x5c, 0xd0, 0xc4, 0x74, 0x5f, 0xa3, 0x34, 0xf9, 0x76, 0x14, 0xe6, 0xf0, 0x72, 0x29, 0xb6, 0x95, 0x88, 0xc1, - 0x4e, 0xa9, 0xe6, 0xd9, 0xc9, 0x59, 0x2c, 0x3d, 0x06, 0x5d, 0x59, 0xa5, 0x03, 0x74, 0x7b, 0x22, 0xed, 0xaa, 0x74, - 0x05, 0x84, 0x1e, 0xf0, 0xcc, 0xcf, 0xe3, 0x51, 0x24, 0x10, 0x6a, 0xc1, 0x9c, 0x4c, 0x23, 0xba, 0x21, 0xbd, 0xc4, - 0x3e, 0x03, 0xb3, 0x90, 0xd2, 0x3c, 0xb8, 0xb9, 0x5a, 0xb4, 0xdc, 0x39, 0x2b, 0x47, 0x61, 0xb5, 0x11, 0x51, 0x8d, - 0x54, 0xc7, 0xe0, 0xbc, 0x03, 0x11, 0x00, 0x8a, 0x11, 0x3c, 0xe3, 0x51, 0xbf, 0x1f, 0xa9, 0xa0, 0x9c, 0x84, 0x7e, - 0x51, 0xe8, 0x97, 0xc6, 0xa0, 0x8c, 0xf9, 0x97, 0x50, 0x13, 0x03, 0xd4, 0x3b, 0x1e, 0x2a, 0x8e, 0x00, 0x5c, 0xce, - 0x11, 0x33, 0xce, 0x7b, 0xdc, 0x45, 0xe3, 0x54, 0xbc, 0x13, 0xea, 0x3a, 0x58, 0x2a, 0xd4, 0x79, 0x53, 0x1f, 0xe9, - 0x39, 0x69, 0x12, 0x34, 0x88, 0x1b, 0x78, 0xbc, 0x1a, 0x02, 0xaa, 0xb5, 0x90, 0x7a, 0x0b, 0x9d, 0x52, 0xd5, 0x21, - 0xb0, 0x06, 0xb8, 0x44, 0x61, 0x3b, 0x61, 0x72, 0x44, 0xdb, 0xb2, 0x14, 0xf9, 0x09, 0x1b, 0xb4, 0x4b, 0x46, 0xa6, - 0x0e, 0x2e, 0x97, 0xcb, 0x89, 0xa8, 0x7f, 0xcd, 0xb7, 0x00, 0xce, 0x0b, 0xf9, 0xad, 0xdd, 0x6c, 0x99, 0x64, 0xbb, - 0xfe, 0x3f, 0xbc, 0x7d, 0x09, 0x77, 0xdb, 0x46, 0xb2, 0xee, 0x5f, 0x11, 0xf1, 0x1c, 0x06, 0x6d, 0x36, 0x29, 0x52, - 0xb1, 0x33, 0x09, 0xa8, 0x16, 0xaf, 0xe2, 0x25, 0x71, 0x26, 0x5e, 0x62, 0x39, 0x99, 0xcc, 0xf0, 0xf1, 0x2a, 0x10, - 0xd0, 0x12, 0x11, 0x43, 0x68, 0x06, 0x00, 0xb5, 0x84, 0xc4, 0x7f, 0x7f, 0xa7, 0xaa, 0x77, 0x10, 0x94, 0x3d, 0xf3, - 0xee, 0x7b, 0xc7, 0xe7, 0x58, 0x44, 0xa3, 0xd1, 0x7b, 0x57, 0x57, 0xd7, 0xf2, 0x55, 0x65, 0x63, 0x96, 0x94, 0xbc, - 0x5a, 0x89, 0xa2, 0xca, 0x6e, 0xf8, 0x4f, 0xe6, 0xa5, 0x1f, 0x40, 0x0a, 0xed, 0x48, 0x5f, 0xb7, 0xbb, 0xa3, 0xc4, - 0x38, 0xa6, 0x1c, 0xd7, 0x52, 0xe9, 0x5e, 0x8d, 0xaa, 0x13, 0x37, 0x5b, 0xe5, 0x5a, 0x66, 0x69, 0xca, 0x8b, 0x57, - 0x45, 0x9a, 0x25, 0x4e, 0x72, 0xac, 0x02, 0x54, 0xdb, 0xc8, 0x57, 0x36, 0x36, 0xf2, 0xf3, 0xac, 0xc2, 0x80, 0xc1, - 0x5e, 0xa3, 0x5a, 0xa1, 0xa6, 0x74, 0xe0, 0x0b, 0xf1, 0x1e, 0x23, 0x6e, 0xb3, 0x22, 0x01, 0x86, 0x1f, 0x13, 0xd5, - 0x25, 0x3d, 0x85, 0x28, 0x0f, 0x32, 0x1e, 0xf7, 0x73, 0x8e, 0x88, 0xd7, 0x46, 0x65, 0x0e, 0x4c, 0xb6, 0x52, 0x41, - 0x22, 0xd8, 0x5d, 0x36, 0x57, 0x8b, 0x68, 0x21, 0xef, 0x42, 0xbd, 0x78, 0xbb, 0xed, 0x25, 0x92, 0x0e, 0x58, 0xf9, - 0x69, 0xf0, 0x32, 0xce, 0x72, 0x9e, 0x1e, 0xd4, 0xe2, 0x40, 0x6e, 0xa8, 0x03, 0xe9, 0xcc, 0x01, 0x3b, 0xef, 0xcb, - 0xfa, 0x40, 0xad, 0xe9, 0x03, 0xd5, 0xce, 0x03, 0xb8, 0x60, 0xe0, 0xce, 0xbd, 0xca, 0x6e, 0x78, 0x71, 0x00, 0xca, - 0x40, 0x63, 0x3c, 0xd0, 0x54, 0xf5, 0x48, 0x4e, 0x8c, 0x0a, 0x5c, 0x9d, 0xa8, 0x83, 0x39, 0xa0, 0xdf, 0x03, 0x52, - 0x54, 0xeb, 0xed, 0x4a, 0x1d, 0xb4, 0x01, 0xfd, 0x69, 0xa9, 0xfb, 0xa0, 0xa2, 0xc5, 0xcb, 0x90, 0xc0, 0xde, 0x90, - 0x2a, 0xa4, 0x56, 0x2d, 0xab, 0x40, 0xf1, 0x86, 0xb3, 0x78, 0x77, 0xae, 0x25, 0x1b, 0xe7, 0x25, 0x02, 0x7b, 0x65, - 0x45, 0x1d, 0x67, 0xc5, 0xa9, 0x93, 0xca, 0x1b, 0xe5, 0x24, 0x53, 0x69, 0xdf, 0xb2, 0x82, 0xba, 0x3b, 0x44, 0xdf, - 0x22, 0xf5, 0x61, 0xf0, 0x22, 0xac, 0xc9, 0x8c, 0xf7, 0xfb, 0x62, 0x26, 0xa2, 0x62, 0x56, 0x1d, 0x16, 0x91, 0x44, - 0x68, 0xdb, 0x27, 0x02, 0x7a, 0x50, 0x02, 0xe4, 0x0a, 0x80, 0xea, 0x87, 0x84, 0x3f, 0x0f, 0x49, 0x7d, 0x3a, 0x85, - 0x3e, 0xa5, 0xb2, 0x5e, 0x71, 0x0a, 0xaa, 0x1b, 0x6f, 0x64, 0xbd, 0x0a, 0x5a, 0x3c, 0x96, 0x63, 0xb5, 0xa1, 0x6d, - 0x4e, 0x8d, 0x77, 0xbd, 0xde, 0x60, 0xd2, 0xe6, 0x42, 0xae, 0xc2, 0x90, 0x44, 0xb7, 0x85, 0x13, 0x3e, 0xc4, 0x60, - 0x65, 0xb5, 0x36, 0xbf, 0x8e, 0xfd, 0x91, 0x15, 0x29, 0xee, 0x67, 0x43, 0x9c, 0xbb, 0x78, 0x3c, 0xa7, 0xfa, 0x46, - 0x49, 0x8b, 0x74, 0x9b, 0xef, 0xd5, 0x65, 0x48, 0x51, 0x51, 0x4d, 0x1a, 0x55, 0x66, 0xd0, 0x7d, 0xdb, 0xbc, 0x55, - 0x3d, 0xc2, 0x04, 0x78, 0xa5, 0x32, 0xa8, 0x46, 0xe3, 0x81, 0x58, 0xd5, 0xa3, 0x72, 0x5d, 0x14, 0x88, 0x36, 0x0c, - 0x39, 0x66, 0x86, 0x90, 0x64, 0x7f, 0xf1, 0xef, 0x64, 0x70, 0x85, 0x32, 0xbe, 0xd5, 0x70, 0xde, 0xb5, 0xf1, 0xec, - 0x6e, 0x22, 0x37, 0x27, 0x16, 0xd6, 0xb8, 0x0f, 0xfe, 0x51, 0xab, 0x9d, 0x05, 0x94, 0x35, 0xad, 0x6a, 0x38, 0xdc, - 0xa3, 0x3a, 0x16, 0xa5, 0x06, 0x24, 0x76, 0xc8, 0x72, 0xd9, 0x3a, 0x66, 0xd0, 0x80, 0xfe, 0x2e, 0xbb, 0x5e, 0x5f, - 0x23, 0x6a, 0x5b, 0x81, 0xac, 0x93, 0x90, 0xfe, 0x25, 0xed, 0x51, 0x57, 0xf6, 0x54, 0xee, 0xb7, 0x6d, 0xaa, 0x1c, - 0x1a, 0x20, 0x79, 0xec, 0xe6, 0x2c, 0x90, 0x1d, 0x09, 0xa2, 0x40, 0x6e, 0xbd, 0x60, 0xea, 0x9c, 0x32, 0x65, 0x07, - 0xf2, 0x73, 0xa9, 0xcf, 0xb0, 0xcf, 0x38, 0x62, 0xf4, 0x52, 0x89, 0xc1, 0xd4, 0x47, 0x1b, 0xd5, 0xb4, 0x56, 0x80, - 0xaa, 0x9f, 0x6e, 0xe0, 0x4f, 0x54, 0x36, 0x68, 0xa8, 0x35, 0x12, 0x85, 0xa4, 0x89, 0x12, 0x3a, 0x96, 0x96, 0x2a, - 0x98, 0x42, 0x27, 0x91, 0x30, 0x04, 0x34, 0x4c, 0x88, 0x4a, 0x2a, 0xf1, 0xd6, 0x00, 0xce, 0x7c, 0xbc, 0xa8, 0xd6, - 0xa5, 0x32, 0x98, 0xfb, 0x21, 0xbe, 0xe1, 0xaf, 0x9e, 0x5b, 0xa3, 0xfa, 0x96, 0xb5, 0xbe, 0xa3, 0x05, 0xf9, 0x21, - 0xe4, 0x14, 0x1d, 0x98, 0xd8, 0xc9, 0x06, 0x0f, 0xe6, 0xa2, 0x51, 0xa1, 0x2e, 0xde, 0xaa, 0xf8, 0x2b, 0xca, 0x04, - 0xef, 0x01, 0x4f, 0x11, 0x65, 0x78, 0x58, 0x69, 0xab, 0x6a, 0x7c, 0x2a, 0x58, 0x4b, 0x0f, 0x56, 0xf2, 0x74, 0x9d, - 0xf0, 0x10, 0xf4, 0x48, 0x84, 0x9d, 0x84, 0xe5, 0x3c, 0x5e, 0xc0, 0x71, 0x52, 0x12, 0x50, 0x3b, 0xa8, 0x2b, 0xf8, - 0x7c, 0x81, 0xee, 0xaf, 0x02, 0x3d, 0xc0, 0xd0, 0x82, 0xd8, 0x0f, 0x7d, 0x3a, 0xba, 0x8e, 0x57, 0x9e, 0x8a, 0x84, - 0xcf, 0x4b, 0xb0, 0x1d, 0x92, 0xea, 0x29, 0xd0, 0x42, 0x25, 0x52, 0x3f, 0x0c, 0x7c, 0x87, 0x02, 0xbe, 0x56, 0x3a, - 0x40, 0x4d, 0x3f, 0x63, 0x9a, 0x1a, 0x67, 0xa8, 0x7c, 0xe6, 0xdc, 0x33, 0xa3, 0xe5, 0xcc, 0x80, 0x31, 0xa8, 0xdb, - 0x68, 0x8a, 0xe2, 0x9c, 0x7c, 0x16, 0x94, 0x71, 0x9a, 0xc5, 0x39, 0xf8, 0x6d, 0xc6, 0x25, 0x66, 0x4c, 0xe2, 0x9a, - 0x5f, 0x89, 0x12, 0xb4, 0xdd, 0xb9, 0x4c, 0x6d, 0x1a, 0x10, 0x90, 0xfd, 0x00, 0x56, 0x2f, 0x9e, 0x8e, 0xca, 0x7a, - 0x77, 0x29, 0x53, 0x88, 0xb2, 0x0a, 0xc1, 0xa6, 0x99, 0x2e, 0xd9, 0x69, 0x28, 0xb5, 0x39, 0x10, 0xdf, 0x08, 0x8d, - 0xfb, 0xa7, 0x61, 0x6c, 0x34, 0xc5, 0xc6, 0xee, 0x6d, 0xbb, 0xfd, 0xad, 0x70, 0xd2, 0x69, 0x4e, 0x7a, 0x8c, 0xfd, - 0x56, 0x84, 0xe5, 0xc8, 0x74, 0x84, 0xc0, 0x92, 0x73, 0x3e, 0x75, 0x5f, 0xd1, 0x62, 0x9e, 0x80, 0xe9, 0x88, 0x8a, - 0x90, 0x0b, 0x94, 0x1d, 0xa3, 0xb8, 0x03, 0x83, 0x0b, 0x66, 0x42, 0x10, 0x4b, 0x4f, 0x5d, 0x48, 0x96, 0x24, 0x65, - 0xf0, 0x3c, 0x75, 0x30, 0xe0, 0xd7, 0x4c, 0x9a, 0xbb, 0x48, 0xeb, 0xd3, 0x25, 0x99, 0xa6, 0xc8, 0x40, 0xac, 0xc3, - 0x4d, 0x96, 0x46, 0x89, 0x14, 0x91, 0x2d, 0xd1, 0x3f, 0x52, 0x53, 0x2c, 0x15, 0xae, 0x17, 0xa9, 0x12, 0xa1, 0xd5, - 0x3c, 0xc5, 0x93, 0x3a, 0x6d, 0xd2, 0x11, 0xc6, 0x9b, 0x04, 0xa5, 0x5c, 0x03, 0x03, 0x55, 0x50, 0xb5, 0x14, 0x36, - 0xe5, 0x76, 0xab, 0x2e, 0x56, 0xd5, 0x3c, 0x5e, 0xe0, 0xcb, 0x0a, 0x47, 0xf1, 0xef, 0xdc, 0x89, 0x35, 0x25, 0xb7, - 0x07, 0x35, 0x23, 0x4a, 0xe8, 0xdf, 0x39, 0x5c, 0x24, 0xbe, 0x13, 0x2a, 0xee, 0x1f, 0x5a, 0x84, 0x9c, 0xcb, 0x83, - 0x54, 0x73, 0x43, 0x3b, 0xc2, 0x7f, 0xcd, 0xf5, 0x69, 0x67, 0x74, 0x5f, 0xcd, 0xa8, 0xf0, 0x7b, 0x1d, 0x3c, 0x63, - 0xd4, 0x67, 0x03, 0x87, 0x15, 0xa2, 0xd0, 0x86, 0x9d, 0x14, 0x52, 0xb4, 0x30, 0x14, 0xf2, 0x2f, 0xa1, 0xd5, 0x09, - 0xb7, 0x66, 0x94, 0x05, 0xe3, 0xd3, 0xe2, 0xb8, 0x9a, 0x0e, 0x06, 0x05, 0xa9, 0xb5, 0x85, 0x1e, 0x5c, 0x0f, 0x1c, - 0xff, 0x1e, 0xb8, 0x85, 0x38, 0x70, 0xc8, 0xd5, 0x90, 0x6b, 0x70, 0xfc, 0x16, 0x27, 0x57, 0x8f, 0x2a, 0x19, 0xbc, - 0x9a, 0xc8, 0x16, 0xfc, 0xbd, 0x08, 0x03, 0xf4, 0x49, 0x0a, 0xc0, 0x64, 0x30, 0xe5, 0x77, 0x20, 0x51, 0x3a, 0x97, - 0x37, 0xa4, 0x5f, 0x8a, 0x92, 0x5f, 0xf2, 0x92, 0x17, 0x89, 0x2d, 0xc0, 0xf0, 0x0e, 0xa6, 0xd7, 0x51, 0x4d, 0x25, - 0x10, 0xaf, 0xee, 0x71, 0xc4, 0xb5, 0xf7, 0x9f, 0xee, 0xb1, 0x01, 0x6a, 0x35, 0x8e, 0x0d, 0x2e, 0x73, 0x0c, 0x2e, - 0xe8, 0x4a, 0x62, 0xab, 0xa9, 0x86, 0x11, 0x81, 0x81, 0x0b, 0x38, 0x08, 0x4b, 0x24, 0xc7, 0x56, 0xf1, 0x9a, 0x78, - 0x52, 0xda, 0x07, 0x86, 0xa3, 0x4d, 0x72, 0x5c, 0x9b, 0x65, 0x3b, 0x81, 0xf3, 0x45, 0xe7, 0xa4, 0xe9, 0x58, 0x36, - 0x78, 0x9f, 0xd7, 0xe7, 0xd7, 0xfe, 0x21, 0xa1, 0x32, 0xd8, 0x0d, 0x6f, 0x07, 0xbb, 0xb1, 0xc2, 0xaf, 0x79, 0xb5, - 0x50, 0xf1, 0x59, 0xf4, 0x25, 0xcb, 0x6d, 0xad, 0x73, 0x4b, 0x12, 0x4a, 0x01, 0xed, 0xb2, 0x2c, 0xa8, 0x89, 0x00, - 0x74, 0x3f, 0xfc, 0x05, 0x42, 0x67, 0xf8, 0xdb, 0x63, 0x70, 0x45, 0x0a, 0xf7, 0x0e, 0x41, 0x65, 0x4c, 0x37, 0x77, - 0x6a, 0x03, 0xbe, 0x18, 0xf7, 0x67, 0x4c, 0x1d, 0xfd, 0x36, 0x13, 0xbb, 0xba, 0x6e, 0x87, 0x2c, 0xc3, 0x47, 0xb8, - 0x52, 0x00, 0x2c, 0x13, 0xfe, 0x62, 0x6c, 0x49, 0xf9, 0x09, 0xc0, 0xa9, 0xa9, 0x88, 0x3e, 0x41, 0xa0, 0xe1, 0x94, - 0x68, 0x39, 0xba, 0x91, 0x8e, 0x68, 0x1a, 0x69, 0x4d, 0xb5, 0x42, 0x7b, 0xeb, 0x61, 0x91, 0xd6, 0x34, 0x9c, 0xb8, - 0x0f, 0x8a, 0x79, 0x95, 0x40, 0x00, 0xad, 0x8c, 0xe0, 0xad, 0xf5, 0x51, 0x1f, 0x21, 0x2e, 0x61, 0x49, 0x14, 0x61, - 0x71, 0x4c, 0xf1, 0x63, 0x42, 0x37, 0xbe, 0xb6, 0xe9, 0x03, 0xd2, 0x5f, 0x5c, 0xb3, 0x6e, 0xca, 0xb2, 0x71, 0xed, - 0xa1, 0xe2, 0xc5, 0xd4, 0x0f, 0x7e, 0x98, 0xc8, 0x62, 0xdc, 0x2f, 0x6a, 0x57, 0x6a, 0x05, 0x30, 0xcc, 0x5d, 0xf5, - 0xf4, 0xfb, 0x7e, 0xb6, 0x1c, 0x08, 0x95, 0xdb, 0x19, 0x24, 0x7d, 0x2a, 0x9e, 0x1f, 0x1c, 0xd1, 0xca, 0x42, 0xcf, - 0x1d, 0x97, 0xc6, 0x87, 0xca, 0x6b, 0x53, 0x23, 0x5a, 0x23, 0x43, 0x65, 0xea, 0x80, 0xf5, 0xfd, 0x43, 0xb8, 0xbb, - 0xa8, 0x69, 0xa8, 0x74, 0xcf, 0x5d, 0x8b, 0x82, 0x13, 0x77, 0x80, 0xb1, 0xb8, 0x90, 0x34, 0x2a, 0x08, 0x93, 0x7a, - 0x34, 0x38, 0xc9, 0x5e, 0x5d, 0x9d, 0x9c, 0x29, 0xe6, 0x09, 0x6c, 0x54, 0xcb, 0xb6, 0xbf, 0xa2, 0x54, 0x97, 0x72, - 0x73, 0x45, 0xf1, 0x3d, 0xa4, 0xcd, 0x55, 0x9c, 0xb7, 0x05, 0x17, 0xfc, 0x33, 0x05, 0x17, 0xc6, 0xc1, 0xba, 0xe3, - 0x4e, 0xd9, 0x73, 0x45, 0x99, 0xc6, 0x06, 0x77, 0xed, 0x31, 0x26, 0xda, 0x7e, 0x77, 0xc9, 0x93, 0x8f, 0xc8, 0x82, - 0x7f, 0x97, 0x15, 0xe0, 0x99, 0x6c, 0x5f, 0xc9, 0xfc, 0x3f, 0xb8, 0x57, 0x5b, 0xf3, 0xce, 0x98, 0x7f, 0x3a, 0xd6, - 0xc3, 0x9d, 0xc3, 0xe4, 0x06, 0xe8, 0x0c, 0xe8, 0xe6, 0x5a, 0xa4, 0x1c, 0x90, 0x01, 0x8c, 0x45, 0x32, 0x1a, 0xf0, - 0xa1, 0x95, 0x65, 0xdb, 0x77, 0x5a, 0x5e, 0x10, 0xf6, 0x12, 0xb8, 0xe9, 0xfe, 0xda, 0xf4, 0xcc, 0xa9, 0x5a, 0x89, - 0xa2, 0x4b, 0x63, 0x63, 0x59, 0x2a, 0x81, 0xdd, 0xf7, 0x9e, 0x64, 0xd3, 0xfc, 0x78, 0x39, 0xcd, 0x0d, 0x75, 0xdb, - 0xd8, 0x65, 0x03, 0x40, 0x88, 0x5d, 0x6b, 0x2b, 0x07, 0x90, 0xdc, 0x1e, 0x84, 0xf0, 0x35, 0x22, 0xf4, 0x54, 0x8a, - 0xd0, 0xa7, 0xa9, 0xdf, 0x07, 0xb3, 0xaa, 0xd6, 0x5e, 0x9c, 0xa3, 0x41, 0xaa, 0x18, 0xf9, 0xb7, 0x37, 0xbc, 0xbc, - 0xcc, 0xc5, 0x2d, 0x60, 0x20, 0x93, 0x46, 0x2b, 0x2c, 0xaf, 0xc1, 0x9d, 0x1f, 0x1d, 0xc7, 0x19, 0xc0, 0x26, 0x41, - 0xb0, 0x56, 0x84, 0x47, 0x56, 0x89, 0x33, 0x00, 0x41, 0x76, 0x27, 0x4d, 0xc5, 0x73, 0x2d, 0x31, 0xa6, 0x2f, 0x70, - 0x57, 0x39, 0x3b, 0xd9, 0xe4, 0x66, 0xd1, 0xfb, 0x33, 0xac, 0x3a, 0x52, 0x19, 0x1b, 0x8b, 0xae, 0x3b, 0x58, 0x6b, - 0x06, 0x4d, 0x11, 0x52, 0x3e, 0x64, 0x4f, 0xda, 0xbf, 0x02, 0x1a, 0x9c, 0x67, 0xe9, 0x9d, 0xb1, 0xca, 0xdf, 0x28, - 0x21, 0x4e, 0x14, 0x53, 0x2b, 0xbe, 0x89, 0x12, 0x75, 0x7e, 0x26, 0xda, 0x0d, 0x04, 0x52, 0x7f, 0xc0, 0xa0, 0x1a, - 0x65, 0x98, 0xc0, 0x75, 0x20, 0x8a, 0xcd, 0x89, 0xea, 0x2d, 0x47, 0xd0, 0x09, 0x21, 0xde, 0x01, 0x50, 0xef, 0xd8, - 0xfa, 0x08, 0x68, 0x96, 0xbe, 0x69, 0xad, 0x73, 0x4d, 0x28, 0xb4, 0x13, 0x98, 0x64, 0x90, 0xe4, 0x59, 0x67, 0x98, - 0xa0, 0xda, 0x8c, 0x49, 0xe7, 0x7d, 0x80, 0xee, 0xae, 0x45, 0x5d, 0x7c, 0xd3, 0xb9, 0x83, 0xf6, 0x71, 0xfd, 0x4a, - 0x8b, 0xec, 0xf1, 0xe7, 0x2d, 0x11, 0x16, 0x81, 0xb3, 0x56, 0xe7, 0xab, 0x47, 0x38, 0x30, 0x15, 0x99, 0x86, 0xbd, - 0x44, 0x2a, 0x59, 0xb6, 0xdb, 0x5e, 0x6f, 0xaf, 0x88, 0xab, 0xc7, 0x58, 0xed, 0xdc, 0xcc, 0xcd, 0x9d, 0x6a, 0x5d, - 0xec, 0xde, 0xb4, 0xdd, 0x14, 0x33, 0x6a, 0xad, 0xdd, 0xae, 0x39, 0x21, 0x4f, 0xbe, 0x15, 0xd5, 0x4a, 0x9d, 0xae, - 0x0d, 0xda, 0x21, 0x9e, 0x75, 0x91, 0xc1, 0x8d, 0xf2, 0xb9, 0x15, 0x3a, 0xc9, 0x38, 0xab, 0x56, 0x5d, 0xb0, 0xb9, - 0xe6, 0xf5, 0x52, 0xa4, 0x51, 0x45, 0xd1, 0xe6, 0x3c, 0x2a, 0x68, 0x22, 0xd6, 0x45, 0x1d, 0x89, 0x06, 0xf5, 0xa2, - 0x46, 0x63, 0x80, 0x80, 0x4c, 0xe7, 0xbe, 0x07, 0x55, 0x30, 0x1b, 0x8a, 0x48, 0x4c, 0xdf, 0x83, 0xa5, 0x7d, 0x01, - 0xfb, 0xa2, 0xd9, 0x57, 0x67, 0x8b, 0x6f, 0x75, 0x84, 0x60, 0x12, 0xb3, 0x07, 0xc2, 0xc0, 0xf9, 0xc6, 0x90, 0xd3, - 0x2e, 0x71, 0x99, 0xef, 0x96, 0xb0, 0x87, 0xdb, 0x15, 0xec, 0xc4, 0xce, 0x93, 0xe2, 0xe6, 0x4a, 0x76, 0x52, 0xce, - 0xc7, 0xa0, 0xfd, 0x12, 0xf2, 0xda, 0xa5, 0xb8, 0xf5, 0x78, 0x10, 0xd0, 0x60, 0x50, 0x6a, 0xfe, 0x75, 0xa2, 0x3d, - 0x3c, 0x69, 0x40, 0x90, 0x94, 0x83, 0x8b, 0xb6, 0x63, 0xf8, 0x3e, 0x99, 0x8a, 0x63, 0x8e, 0x16, 0xef, 0xd0, 0xea, - 0x04, 0xa2, 0x78, 0x81, 0xbd, 0x9b, 0x56, 0x15, 0x6a, 0x11, 0x94, 0xa3, 0xe5, 0x2f, 0x64, 0x75, 0x08, 0x28, 0xa4, - 0x7c, 0x45, 0xa1, 0x6c, 0x9d, 0x18, 0xea, 0xe1, 0x17, 0xf3, 0xc9, 0x42, 0xcd, 0xc0, 0x40, 0xcc, 0x8f, 0x16, 0x6a, - 0x16, 0x06, 0x62, 0xfe, 0xd5, 0xa2, 0xb1, 0xeb, 0x40, 0x11, 0x10, 0xc7, 0x85, 0xa3, 0x93, 0xd2, 0xca, 0x6c, 0x01, - 0xdd, 0x3c, 0x44, 0xd0, 0xff, 0x6e, 0x0e, 0x41, 0x2b, 0x17, 0xda, 0x91, 0x1b, 0xd0, 0x76, 0x1c, 0x02, 0x73, 0xc5, - 0xa4, 0x95, 0x0e, 0x40, 0x74, 0xcc, 0xc6, 0x60, 0x88, 0x2d, 0x3f, 0x38, 0x66, 0xe3, 0xa9, 0x4b, 0x82, 0x80, 0xd1, - 0xfd, 0x41, 0x43, 0x82, 0xdf, 0xe1, 0x55, 0xfa, 0x64, 0x83, 0xbe, 0x66, 0xce, 0xdd, 0xd0, 0xb9, 0xb8, 0x82, 0x53, - 0xb5, 0xbd, 0x27, 0xa1, 0x9b, 0x4c, 0x3b, 0x40, 0xaf, 0x26, 0x6e, 0xc8, 0xaf, 0x8c, 0x46, 0xa3, 0x62, 0x64, 0x00, - 0x20, 0x88, 0xe6, 0x1c, 0xfc, 0x9c, 0x86, 0xcb, 0x97, 0xb7, 0x9e, 0x4d, 0x31, 0x02, 0x5a, 0xc8, 0x44, 0xf3, 0x00, - 0x65, 0x55, 0x63, 0x68, 0x86, 0xde, 0x21, 0xc7, 0x0f, 0x0f, 0xbe, 0xce, 0xf8, 0x89, 0xc3, 0xb5, 0x87, 0x73, 0xe1, - 0xba, 0xac, 0x69, 0x99, 0x43, 0xe7, 0xd9, 0xc7, 0xf1, 0x1e, 0xc6, 0xc9, 0xa7, 0x59, 0x28, 0x67, 0xbc, 0xa6, 0xff, - 0x51, 0xe9, 0x7e, 0x87, 0x43, 0x4e, 0x57, 0xb0, 0xe2, 0x66, 0x75, 0xa8, 0xf9, 0x59, 0xe4, 0x8d, 0x23, 0xde, 0x90, - 0xa8, 0xee, 0x3e, 0xef, 0x4d, 0x98, 0xd2, 0x8e, 0x71, 0x00, 0x70, 0xa2, 0x56, 0x0d, 0xbb, 0xd2, 0xb8, 0x56, 0x07, - 0x31, 0x0c, 0x25, 0x6c, 0x95, 0x38, 0xaa, 0xa4, 0xbf, 0x01, 0x08, 0x8b, 0xa1, 0x38, 0xde, 0x1a, 0xd6, 0x07, 0xd8, - 0x0f, 0x55, 0xa0, 0x6e, 0x4e, 0x21, 0x67, 0x00, 0x90, 0x04, 0xdc, 0xd1, 0x53, 0x4d, 0x43, 0x65, 0x9b, 0xe3, 0xa1, - 0x65, 0x74, 0x05, 0x0f, 0xf4, 0xd4, 0x96, 0x0c, 0x8c, 0xab, 0x3c, 0xf6, 0x36, 0xfb, 0xdb, 0xa3, 0x54, 0xe4, 0x3b, - 0x9b, 0xd4, 0x34, 0xab, 0x46, 0x63, 0x1f, 0x47, 0xe8, 0x69, 0x05, 0x68, 0xbd, 0xb6, 0x54, 0xb4, 0xdf, 0x47, 0x31, - 0x6a, 0x5c, 0x4a, 0xb0, 0x0a, 0x1d, 0x09, 0x0e, 0x11, 0x46, 0x08, 0xfd, 0xbe, 0x08, 0x37, 0xae, 0x20, 0x83, 0x28, - 0xb8, 0x16, 0x15, 0x7f, 0xc8, 0xf2, 0xa2, 0x6d, 0xa9, 0xaa, 0x3e, 0x69, 0xda, 0x12, 0x78, 0x1d, 0x0e, 0xb0, 0x9d, - 0x7f, 0xea, 0x89, 0x5c, 0x2b, 0x1b, 0x25, 0x7c, 0x47, 0x5c, 0x0b, 0xa2, 0x9b, 0x46, 0xd7, 0xeb, 0xd9, 0x21, 0x5a, - 0x9a, 0xe2, 0xd0, 0x21, 0xfb, 0xdc, 0x3d, 0xb7, 0x65, 0x7c, 0xfb, 0x09, 0x72, 0xe7, 0x3b, 0x7b, 0x49, 0xc2, 0x20, - 0x6f, 0xd9, 0x40, 0xb1, 0x8e, 0xad, 0xa0, 0x00, 0xa3, 0xb6, 0xfc, 0x05, 0x74, 0x6c, 0x30, 0xa8, 0x09, 0x3e, 0x49, - 0x6c, 0x1b, 0x8f, 0xfc, 0x11, 0xe7, 0x86, 0x0e, 0xaf, 0x0d, 0x79, 0x20, 0x4e, 0x61, 0x9f, 0x28, 0x61, 0xff, 0x82, - 0x82, 0xee, 0x48, 0x2f, 0x57, 0x89, 0xab, 0xe2, 0x01, 0xaa, 0xec, 0x78, 0xae, 0xf9, 0x92, 0x16, 0x5a, 0x69, 0x64, - 0x15, 0x1d, 0x11, 0xb7, 0x60, 0x32, 0x66, 0xab, 0x6a, 0x54, 0x71, 0x2c, 0x50, 0xa4, 0x63, 0xce, 0x76, 0x0e, 0xd6, - 0x00, 0x78, 0x0a, 0x9b, 0x8b, 0x33, 0x2c, 0x28, 0xed, 0xb2, 0xa5, 0x2f, 0x81, 0x55, 0xf3, 0x30, 0xce, 0xcb, 0x8e, - 0x2f, 0x77, 0x47, 0xdb, 0x7b, 0xe8, 0x8d, 0xe8, 0x8d, 0xd7, 0xe7, 0x51, 0xd3, 0xcf, 0x9e, 0xe1, 0xda, 0x50, 0x90, - 0x07, 0x9a, 0xea, 0x10, 0x46, 0x8b, 0xc0, 0x34, 0xe5, 0x27, 0x6c, 0x3c, 0x1d, 0x0e, 0x35, 0x19, 0x74, 0x9a, 0x89, - 0xf1, 0xbf, 0x3e, 0x83, 0xd6, 0xe9, 0x89, 0xf3, 0x3e, 0x6d, 0x5f, 0x41, 0xeb, 0x3b, 0x94, 0xc9, 0x9d, 0x83, 0xe1, - 0x03, 0x2d, 0x98, 0x84, 0xa9, 0xc2, 0x1b, 0x22, 0x15, 0xec, 0xcd, 0xd2, 0x38, 0xec, 0x9b, 0x85, 0x42, 0x4b, 0x45, - 0xfc, 0x6a, 0x4d, 0xfc, 0xe4, 0x75, 0xe6, 0xdf, 0xa6, 0x7d, 0x72, 0x10, 0x4b, 0x43, 0x62, 0x24, 0xe2, 0x17, 0xa7, - 0xd2, 0x76, 0x42, 0x05, 0xc4, 0x43, 0xd7, 0xba, 0x71, 0x24, 0x64, 0xec, 0x49, 0x8d, 0xa7, 0x86, 0xfb, 0x5e, 0xc7, - 0xac, 0xc3, 0x2c, 0x76, 0xb3, 0x46, 0x42, 0x61, 0x9c, 0x9a, 0xe0, 0x94, 0x62, 0x15, 0xc9, 0xe8, 0x78, 0xa6, 0x30, - 0x88, 0x2a, 0x29, 0x21, 0xd6, 0x94, 0xad, 0x85, 0x89, 0x5d, 0x67, 0x0b, 0x53, 0xd4, 0x45, 0xa8, 0x37, 0x03, 0x9d, - 0x05, 0x0d, 0xf9, 0x1d, 0x1a, 0xad, 0xa8, 0x9a, 0x04, 0x0c, 0xe3, 0x28, 0xd5, 0xf8, 0xb7, 0x08, 0xb5, 0x1e, 0x06, - 0x00, 0xb6, 0x79, 0x27, 0xb2, 0xa2, 0x7e, 0x55, 0x20, 0x04, 0x9a, 0xb5, 0x9f, 0x2a, 0xeb, 0x9d, 0x59, 0xd0, 0x8a, - 0x76, 0x73, 0xe5, 0x73, 0x81, 0x13, 0xaa, 0x53, 0x79, 0x81, 0x7a, 0x29, 0xca, 0xd7, 0x22, 0xe5, 0xad, 0xb8, 0x98, - 0x07, 0x82, 0x7d, 0xc8, 0x47, 0x70, 0x5e, 0xa1, 0x53, 0xb9, 0xde, 0x26, 0xd2, 0x2c, 0x49, 0x30, 0x16, 0x68, 0x9b, - 0x97, 0x60, 0x26, 0x14, 0x33, 0x86, 0x5f, 0x43, 0x70, 0xb1, 0x9d, 0x93, 0x70, 0xb3, 0x9f, 0x07, 0x86, 0xd0, 0xe4, - 0x55, 0x4b, 0x34, 0x6c, 0xec, 0x78, 0x1d, 0xb9, 0x26, 0xdc, 0x87, 0xb5, 0x58, 0x93, 0x31, 0xc6, 0x95, 0xb9, 0x91, - 0xf1, 0xa3, 0x05, 0x1e, 0x8c, 0x49, 0xeb, 0x4f, 0x20, 0xd3, 0x52, 0xca, 0x3a, 0x5f, 0x68, 0x31, 0x93, 0x4c, 0x74, - 0x6e, 0xdf, 0xf8, 0x2c, 0xef, 0x22, 0xf2, 0xb7, 0xf2, 0x7b, 0x92, 0x0f, 0xf7, 0xee, 0x83, 0xc4, 0x1a, 0x94, 0x46, - 0x5c, 0x5a, 0x94, 0xa7, 0x0f, 0x74, 0xdd, 0xa4, 0x88, 0xd3, 0xf3, 0x55, 0x5c, 0x56, 0x3c, 0x85, 0x4a, 0x15, 0x75, - 0x8b, 0x7a, 0x13, 0xb0, 0x37, 0x44, 0x92, 0x64, 0x2c, 0x8d, 0x8d, 0xd8, 0xc5, 0x23, 0x3d, 0x7b, 0xc3, 0x2c, 0xbd, - 0xac, 0xd1, 0x90, 0x96, 0x3a, 0x67, 0xa1, 0x94, 0xf9, 0x4b, 0xfe, 0x33, 0x68, 0x24, 0xe8, 0xa8, 0x4f, 0x31, 0x9e, - 0x01, 0x23, 0xbe, 0x1b, 0xc1, 0xea, 0x01, 0xe2, 0xa2, 0x08, 0x4a, 0xb3, 0x23, 0x76, 0xfc, 0xd4, 0xe4, 0xe1, 0x5d, - 0xc8, 0x3a, 0x83, 0x4f, 0x1f, 0x66, 0x89, 0x5a, 0xeb, 0xa8, 0x1a, 0xc9, 0x19, 0x40, 0xd3, 0x41, 0x91, 0xf3, 0xb8, - 0x08, 0x66, 0x3d, 0x9d, 0x18, 0xf5, 0xb8, 0xfa, 0x05, 0x1a, 0x6a, 0xb7, 0x59, 0x59, 0x9e, 0xd5, 0xf7, 0x9f, 0xc3, - 0x81, 0x4d, 0x4d, 0x05, 0x3d, 0xde, 0xd4, 0xe2, 0xea, 0x4a, 0x76, 0xdb, 0x2d, 0x44, 0xcb, 0xe9, 0xbc, 0x6b, 0xe9, - 0xbc, 0x5e, 0xb0, 0x5e, 0x77, 0xba, 0x5e, 0xdc, 0x7e, 0x19, 0x1e, 0xc2, 0xda, 0xce, 0x27, 0x8a, 0x3f, 0xf3, 0xdb, - 0xee, 0xe2, 0x2d, 0x54, 0xb3, 0x00, 0x00, 0xd2, 0x83, 0x28, 0x58, 0x66, 0x29, 0x0f, 0xa8, 0xd8, 0xc7, 0x51, 0x96, - 0x52, 0x2f, 0x67, 0x18, 0x3f, 0x65, 0x1a, 0x6b, 0x9c, 0x15, 0xaa, 0xd0, 0xd8, 0xe8, 0x4e, 0x57, 0x19, 0x62, 0xfb, - 0x09, 0x9c, 0x2d, 0xc0, 0xfd, 0xd1, 0x43, 0xa1, 0xee, 0x4d, 0x5a, 0x9a, 0xa8, 0xf9, 0xae, 0x3d, 0x83, 0x8c, 0xe2, - 0x64, 0x95, 0x57, 0xd0, 0x8d, 0x3a, 0x6b, 0xa3, 0x4a, 0xdf, 0x43, 0xd4, 0xab, 0x18, 0x3c, 0xca, 0x5d, 0x5e, 0x1b, - 0x9d, 0x4c, 0x8b, 0x48, 0xb9, 0xf3, 0x93, 0x66, 0x99, 0xa5, 0x4a, 0x87, 0xed, 0x32, 0xec, 0xad, 0x31, 0xe9, 0x4d, - 0x48, 0x03, 0x23, 0xf1, 0xe9, 0x8c, 0x0a, 0x21, 0xa0, 0x2d, 0xc7, 0xdf, 0xe1, 0x33, 0x34, 0x4d, 0x81, 0xa5, 0x8a, - 0x5b, 0xd8, 0x0e, 0x9f, 0xff, 0x64, 0xd4, 0x02, 0x10, 0xc1, 0xca, 0xd5, 0xbb, 0x38, 0x25, 0x34, 0xe7, 0xca, 0x0c, - 0x00, 0x59, 0x50, 0xca, 0x2d, 0x3f, 0x25, 0xd3, 0xc1, 0x12, 0x45, 0xd9, 0xcb, 0xa9, 0x1b, 0x1d, 0x1b, 0x3f, 0xa4, - 0xe7, 0x02, 0xb6, 0x0b, 0xf9, 0xad, 0xbd, 0x7a, 0x89, 0x9a, 0x34, 0xa6, 0x59, 0x0f, 0xf0, 0xe5, 0x1a, 0x4d, 0x42, - 0x0b, 0xca, 0xa4, 0x29, 0x80, 0xc6, 0x4d, 0xd5, 0x0a, 0x26, 0xa5, 0x46, 0xc2, 0x96, 0x3a, 0x92, 0x65, 0xdf, 0x07, - 0xa7, 0xde, 0x23, 0xe8, 0x01, 0xf3, 0x08, 0xf4, 0xf4, 0x5f, 0xba, 0x6a, 0xff, 0x92, 0xa3, 0x93, 0xab, 0x26, 0x6a, - 0xfa, 0xbd, 0xb2, 0x23, 0x43, 0xca, 0xa5, 0x19, 0x08, 0x26, 0x1d, 0xf3, 0xd4, 0xd8, 0x3a, 0x46, 0x44, 0x0f, 0x9c, - 0x7d, 0xba, 0x5b, 0x4d, 0x2d, 0x00, 0xd1, 0xf1, 0xeb, 0x27, 0xaf, 0xae, 0xe3, 0x2b, 0x8d, 0xa2, 0xe4, 0x59, 0xc4, - 0x48, 0xd3, 0xbe, 0x5a, 0xc0, 0xe0, 0xfd, 0xf2, 0xfe, 0x27, 0x99, 0xa5, 0x71, 0x7b, 0xb0, 0x31, 0xa2, 0xaa, 0x5f, - 0x2a, 0x5e, 0xfa, 0x02, 0xac, 0x7d, 0x96, 0x28, 0x90, 0xfb, 0xbd, 0x49, 0xd3, 0xdf, 0x44, 0xde, 0xcd, 0x86, 0xf5, - 0xc6, 0x4d, 0xbb, 0xd4, 0x96, 0xec, 0xc8, 0x48, 0xe4, 0xf4, 0x62, 0xd0, 0xe3, 0x47, 0x2b, 0x8d, 0xd2, 0xb0, 0x41, - 0x55, 0x2a, 0x7e, 0xaf, 0x45, 0x70, 0xf2, 0x58, 0x95, 0x18, 0xd3, 0x80, 0xd9, 0x56, 0x36, 0x0a, 0xd4, 0x41, 0x2a, - 0x6d, 0x75, 0x14, 0xb6, 0xdf, 0x58, 0x49, 0xf5, 0xef, 0x7f, 0x6a, 0x43, 0x3e, 0x5f, 0x0a, 0x2a, 0x08, 0xd8, 0x19, - 0x78, 0x3d, 0x95, 0xc2, 0x40, 0x2a, 0xd8, 0x49, 0x05, 0x28, 0x5f, 0x44, 0x8e, 0xd5, 0x6e, 0x5f, 0xad, 0x1a, 0xa3, - 0x2d, 0x20, 0x34, 0x90, 0x1e, 0x5d, 0xf6, 0x71, 0x1b, 0xe3, 0x40, 0xe2, 0xc0, 0x09, 0xb6, 0x73, 0x75, 0x8d, 0x46, - 0x42, 0xf3, 0x87, 0x46, 0x03, 0x5e, 0xd3, 0x1a, 0x14, 0xea, 0x39, 0x8e, 0x86, 0xca, 0x0e, 0x29, 0x88, 0xd8, 0xa0, - 0x84, 0x7d, 0x7b, 0x3e, 0xd4, 0xfb, 0x7a, 0x9e, 0x2c, 0x48, 0x43, 0x85, 0xfd, 0xdc, 0x2e, 0x21, 0x63, 0xd5, 0x21, - 0xad, 0x3c, 0xc0, 0xf1, 0x42, 0xca, 0xfc, 0x2d, 0x26, 0x35, 0x4a, 0x63, 0x42, 0x6d, 0xc4, 0x02, 0x96, 0x04, 0xed, - 0xf5, 0x40, 0xdd, 0x32, 0x08, 0x75, 0x4c, 0x4f, 0x04, 0x3e, 0xa5, 0x5c, 0x7e, 0x5a, 0x92, 0x66, 0x5a, 0x32, 0x0b, - 0x7a, 0xe9, 0x5a, 0xf9, 0x15, 0xde, 0x47, 0xbb, 0x7b, 0x57, 0x5f, 0x58, 0xc7, 0x10, 0x0c, 0xbb, 0x72, 0x9b, 0xd3, - 0x50, 0x00, 0x36, 0x3c, 0x55, 0x65, 0xb9, 0x46, 0x4d, 0x64, 0x16, 0x87, 0x24, 0x02, 0xc9, 0xb6, 0xbf, 0xb9, 0xb5, - 0x60, 0xdb, 0x59, 0xa8, 0x9e, 0xfa, 0xcb, 0xd9, 0xee, 0x7b, 0x86, 0x97, 0x3b, 0x72, 0x6f, 0xdf, 0x86, 0xf2, 0x87, - 0xfd, 0xab, 0xe4, 0xff, 0xaa, 0x92, 0xfd, 0x56, 0x99, 0x4d, 0x5b, 0xbc, 0xdf, 0x75, 0xdc, 0x72, 0x8c, 0x06, 0x81, - 0x35, 0x05, 0x1a, 0xd2, 0x93, 0xc6, 0x34, 0x51, 0x21, 0x95, 0x19, 0xd3, 0x78, 0x74, 0x01, 0x9a, 0xc3, 0x74, 0x9e, - 0xc7, 0x00, 0x1c, 0xe0, 0x1e, 0x79, 0x84, 0xba, 0xa7, 0xf3, 0x3c, 0x38, 0x0f, 0x06, 0xc5, 0x20, 0x50, 0x9f, 0xd8, - 0xe6, 0x04, 0x0b, 0xd0, 0xb9, 0xc5, 0x0c, 0x82, 0x4d, 0x1a, 0x33, 0x87, 0xf8, 0x38, 0x99, 0x0e, 0x06, 0x31, 0xd9, - 0x00, 0x48, 0x5f, 0xbc, 0x30, 0xce, 0x41, 0xa5, 0x5a, 0x90, 0xad, 0xba, 0x4b, 0xbf, 0x62, 0xa7, 0xda, 0x69, 0xde, - 0xef, 0xe7, 0xf3, 0x62, 0x10, 0x78, 0x15, 0x96, 0xda, 0xfb, 0x8f, 0xfa, 0x5f, 0x6a, 0x9d, 0x34, 0xc1, 0x30, 0xb5, - 0xa7, 0xa8, 0x5e, 0x71, 0x34, 0xa3, 0xde, 0xed, 0x58, 0x2a, 0x5f, 0x40, 0x14, 0x0f, 0x0c, 0x59, 0x2b, 0xef, 0xce, - 0xc1, 0x6b, 0x73, 0xe3, 0xcd, 0x11, 0x05, 0xd8, 0xbe, 0x30, 0x4e, 0x28, 0x2e, 0xba, 0x6c, 0x88, 0x63, 0xb0, 0xd3, - 0xd5, 0x5b, 0x81, 0x56, 0xe3, 0xbd, 0x78, 0xd7, 0x6c, 0xfc, 0x8d, 0x38, 0x50, 0x65, 0x1e, 0x5c, 0x02, 0xe2, 0xec, - 0x41, 0x5c, 0x1f, 0x60, 0xa9, 0x07, 0xc1, 0xc0, 0x20, 0x87, 0xb4, 0xab, 0x55, 0x43, 0x11, 0xc9, 0xf3, 0x18, 0x0c, - 0x98, 0x74, 0x43, 0x1a, 0x32, 0xed, 0x95, 0x12, 0xd2, 0xc6, 0x58, 0x0b, 0x28, 0xc3, 0xe1, 0x6a, 0xc7, 0x6e, 0xd8, - 0x9e, 0x6e, 0x1d, 0x0a, 0x25, 0x8c, 0x5e, 0xdd, 0xf8, 0x87, 0x9a, 0xe7, 0x89, 0xa0, 0x06, 0x55, 0x6b, 0x3f, 0x1d, - 0x94, 0x27, 0xe5, 0xb1, 0x00, 0x17, 0x3d, 0x7c, 0xf9, 0xa2, 0xc0, 0x8b, 0xf6, 0x0e, 0xf2, 0x9c, 0xfe, 0x54, 0xfa, - 0x20, 0x7a, 0x6e, 0x19, 0x2e, 0xb4, 0x8f, 0x6b, 0x05, 0x32, 0x69, 0x3a, 0x9a, 0xda, 0xda, 0x1d, 0xde, 0x31, 0x81, - 0x7e, 0x53, 0x96, 0x52, 0x26, 0xba, 0x96, 0x25, 0x3b, 0xe9, 0xe5, 0xd2, 0x1b, 0x2a, 0x65, 0x27, 0xcb, 0x36, 0xe7, - 0x97, 0x7a, 0x09, 0xfd, 0xbe, 0x72, 0x07, 0xc2, 0x37, 0x72, 0xbd, 0x21, 0x2f, 0x1b, 0x22, 0x96, 0x43, 0xcc, 0xc0, - 0xf1, 0x42, 0x48, 0xd7, 0xee, 0xd2, 0x57, 0xd5, 0xed, 0x6c, 0xe5, 0x92, 0x16, 0x78, 0x2b, 0x05, 0x56, 0x91, 0x5a, - 0xbd, 0x9e, 0x4c, 0xdc, 0xf7, 0x51, 0x6c, 0x3e, 0x02, 0xb6, 0xd1, 0x3b, 0x1a, 0xbd, 0x5b, 0xc4, 0x06, 0x5f, 0x45, - 0x35, 0x2d, 0x39, 0x40, 0x70, 0xb7, 0x25, 0xb5, 0x34, 0xb3, 0x88, 0xfb, 0x92, 0x07, 0x68, 0xdf, 0xc5, 0xe1, 0x4c, - 0x2a, 0xc1, 0xb6, 0xae, 0x75, 0xce, 0x2a, 0x39, 0xa0, 0x9f, 0xe8, 0xf8, 0xa7, 0xd5, 0xa3, 0x22, 0x86, 0x55, 0x36, - 0x92, 0x56, 0x68, 0x0f, 0x4a, 0x97, 0x70, 0xf1, 0x05, 0x78, 0xd9, 0xde, 0xaf, 0xec, 0x3e, 0x5f, 0x62, 0xff, 0x30, - 0xaf, 0x9c, 0xe0, 0x91, 0xd3, 0x78, 0x73, 0x0f, 0xab, 0x3e, 0x57, 0x0a, 0xe1, 0x54, 0x4a, 0x43, 0x01, 0xc0, 0x20, - 0x09, 0x6a, 0xb8, 0xd2, 0xb6, 0x19, 0xa4, 0x34, 0x86, 0xdd, 0xad, 0xde, 0xe8, 0xff, 0x94, 0x0a, 0x17, 0xa0, 0x94, - 0x0d, 0xdc, 0x90, 0x75, 0xaa, 0xe5, 0x3a, 0xa6, 0xe0, 0xf9, 0x2e, 0x39, 0x02, 0x85, 0x1d, 0x18, 0x99, 0xd1, 0x84, - 0xfd, 0x82, 0xb7, 0xa1, 0x9c, 0xbd, 0x34, 0x92, 0x27, 0xbb, 0x2f, 0x69, 0x45, 0x13, 0x32, 0xad, 0xcc, 0xfe, 0x6d, - 0x6d, 0xd8, 0xe7, 0xa1, 0x18, 0x89, 0x02, 0x17, 0x07, 0x9d, 0x03, 0xd8, 0x1f, 0xe4, 0xd2, 0x36, 0x9f, 0x49, 0xbf, - 0x2f, 0xdf, 0x3f, 0xcb, 0xb3, 0xe4, 0xe3, 0xce, 0x7b, 0xcd, 0xd3, 0x2c, 0x19, 0x50, 0x89, 0x98, 0x1a, 0x57, 0xc5, - 0x70, 0xa9, 0x5c, 0x8c, 0x3d, 0x92, 0x11, 0xef, 0xa5, 0x0e, 0x31, 0x62, 0x7c, 0x91, 0x1d, 0x92, 0x92, 0xd3, 0x65, - 0xd3, 0xd9, 0x73, 0x25, 0x9a, 0x41, 0x63, 0xb8, 0x1d, 0xef, 0x25, 0xb5, 0x02, 0x64, 0x54, 0xe8, 0x9e, 0x01, 0xae, - 0xe1, 0xfe, 0x92, 0xf0, 0xb6, 0xf4, 0xb4, 0x25, 0x1a, 0xd8, 0x2b, 0x13, 0x12, 0x72, 0xe3, 0x00, 0x8b, 0xd8, 0x34, - 0x1f, 0x43, 0x01, 0x40, 0xad, 0x1a, 0xe9, 0x95, 0xbe, 0x24, 0x54, 0x26, 0x21, 0x18, 0x5d, 0x91, 0xf0, 0x2a, 0xa0, - 0x71, 0xa6, 0x13, 0x0d, 0x6c, 0x70, 0x40, 0x9f, 0xd7, 0x3a, 0x51, 0xdb, 0x90, 0x07, 0xb4, 0x36, 0x69, 0x00, 0x83, - 0x0f, 0x92, 0x24, 0xfa, 0x6a, 0xa9, 0x93, 0x40, 0x50, 0x82, 0xf2, 0x0d, 0xfa, 0x73, 0xe1, 0xf8, 0x58, 0x82, 0xff, - 0x91, 0x26, 0x82, 0x3f, 0x84, 0x02, 0x64, 0x8a, 0xaa, 0x62, 0x9a, 0xb1, 0x93, 0xac, 0xdb, 0x98, 0xc4, 0xf1, 0xb4, - 0xbb, 0x2b, 0xa5, 0x4b, 0x17, 0xf8, 0x95, 0x65, 0x88, 0x63, 0xfd, 0x2c, 0x5e, 0xb1, 0xd3, 0x90, 0x2b, 0xbc, 0xf4, - 0x67, 0xf1, 0x0a, 0x67, 0x88, 0xd6, 0xad, 0x04, 0x22, 0xfd, 0x57, 0x4d, 0xe0, 0x10, 0xfb, 0x09, 0x06, 0xb9, 0xa8, - 0x9d, 0x07, 0x02, 0x79, 0x5b, 0x41, 0x44, 0xfc, 0xec, 0x2a, 0x8c, 0x48, 0xbd, 0x93, 0xa4, 0xbf, 0xfc, 0x51, 0x64, - 0x85, 0xf3, 0x0d, 0x3c, 0xfa, 0xcd, 0x32, 0x29, 0xfa, 0x0b, 0x19, 0xcc, 0xc1, 0x7e, 0x22, 0xe3, 0x52, 0xd4, 0xee, - 0x13, 0x76, 0xc1, 0x89, 0xf1, 0xe0, 0xf4, 0x1a, 0x01, 0xf6, 0x6b, 0xf7, 0xc9, 0x19, 0xb3, 0xbf, 0x8c, 0x1b, 0x5f, - 0xa6, 0x23, 0x3e, 0xf0, 0xd1, 0x1d, 0xe5, 0xa3, 0x7b, 0x27, 0xd3, 0x1f, 0x1e, 0x94, 0xc8, 0xa8, 0xaa, 0xf9, 0x6a, - 0xc5, 0xd3, 0xd9, 0x5d, 0x12, 0x65, 0xa3, 0x9a, 0x17, 0x30, 0xbd, 0xe0, 0x78, 0x97, 0xac, 0x2f, 0xb2, 0xe4, 0x15, - 0xc4, 0x1e, 0x58, 0x09, 0x89, 0xc5, 0x0f, 0xcb, 0x4c, 0x2e, 0xe6, 0x42, 0xd4, 0xa2, 0xe0, 0xc1, 0xec, 0x26, 0x89, - 0xfe, 0x5a, 0x3a, 0x48, 0x6a, 0x7a, 0xca, 0x36, 0x8d, 0x25, 0xd4, 0xda, 0xd7, 0x91, 0x6e, 0x94, 0x05, 0x00, 0xdc, - 0xb3, 0x8b, 0x34, 0x12, 0xac, 0x1a, 0x4e, 0x1a, 0xc6, 0x75, 0x7a, 0x89, 0xa9, 0x71, 0xc3, 0x6a, 0x9a, 0x58, 0x0b, - 0x19, 0xd0, 0xfb, 0x03, 0x5e, 0x0e, 0x3e, 0x67, 0x45, 0x28, 0xa4, 0x35, 0x70, 0x71, 0x5c, 0xf6, 0xfb, 0xe2, 0xb8, - 0xdc, 0x6e, 0x8b, 0x93, 0xb8, 0xdf, 0x17, 0x27, 0xb1, 0xe6, 0x1f, 0xa4, 0x62, 0x5b, 0x9b, 0x1b, 0x24, 0x34, 0x17, - 0x10, 0xb5, 0x68, 0x04, 0x7f, 0x68, 0x96, 0xf3, 0x22, 0xca, 0x8f, 0x93, 0x7e, 0xbf, 0xb7, 0x9c, 0x55, 0x83, 0x7c, - 0x98, 0x44, 0xf9, 0x30, 0x71, 0x9c, 0x10, 0x7f, 0x75, 0x9c, 0x10, 0x25, 0x0d, 0x5c, 0xc1, 0x99, 0x01, 0x88, 0x02, - 0x2e, 0xfd, 0xa3, 0xaa, 0x96, 0x52, 0xd5, 0x12, 0xcb, 0x5a, 0x12, 0x55, 0x41, 0xc3, 0x6e, 0xca, 0xb0, 0xc0, 0x52, - 0xe8, 0x92, 0xfd, 0xb1, 0x04, 0x9e, 0x28, 0xe7, 0xf5, 0x06, 0x18, 0xd8, 0x08, 0xef, 0x1c, 0x3a, 0x9c, 0xc4, 0xba, - 0x61, 0x12, 0x32, 0xe9, 0x92, 0xae, 0xe8, 0x15, 0xf2, 0xb3, 0x97, 0x60, 0xb0, 0x74, 0xcc, 0xf2, 0xe9, 0x60, 0x70, - 0x49, 0x56, 0xac, 0x98, 0x87, 0xf1, 0x20, 0x5c, 0xcf, 0xf2, 0xe1, 0x65, 0x74, 0x49, 0xc8, 0x17, 0xe5, 0x82, 0xf6, - 0x56, 0xa3, 0xea, 0x63, 0x06, 0xc1, 0xfd, 0xd2, 0x59, 0x98, 0xe9, 0x38, 0x1f, 0xab, 0xd1, 0x1d, 0x5d, 0x41, 0xfc, - 0x1a, 0xb8, 0x91, 0x90, 0x08, 0x3a, 0x72, 0x45, 0x57, 0x74, 0x4d, 0x85, 0x9e, 0x61, 0x0c, 0xd1, 0x6d, 0x8e, 0x93, - 0x04, 0x1c, 0x93, 0x6d, 0xf1, 0xd1, 0x58, 0x16, 0xde, 0xf5, 0x1d, 0xa1, 0xbd, 0x5e, 0x62, 0x07, 0xe9, 0xbb, 0xf6, - 0x20, 0x01, 0x23, 0x32, 0x92, 0x03, 0xa5, 0x47, 0x46, 0x50, 0x3d, 0xa9, 0x38, 0x24, 0xb1, 0x3b, 0x24, 0x72, 0x1c, - 0x12, 0x77, 0x1c, 0x72, 0x35, 0x0e, 0xc8, 0xdd, 0x2f, 0xd9, 0x98, 0xa6, 0x6c, 0x4c, 0xd7, 0x72, 0x54, 0xe8, 0x35, - 0xbd, 0x50, 0xd4, 0xf1, 0x9c, 0xbd, 0x86, 0x03, 0x7b, 0x10, 0xe6, 0xb3, 0x78, 0xf8, 0x3a, 0x7a, 0x4d, 0xc8, 0x17, - 0x82, 0xde, 0xc8, 0x4b, 0x19, 0x84, 0x41, 0xbc, 0x06, 0xe7, 0x52, 0x1b, 0xea, 0xe4, 0x5a, 0xef, 0x38, 0x7c, 0xba, - 0xf2, 0x9e, 0x2e, 0x20, 0xa2, 0x0f, 0x5a, 0xa9, 0xf4, 0xfb, 0xe1, 0x25, 0x2b, 0xe6, 0xe7, 0xe1, 0x98, 0x00, 0x0e, - 0x8f, 0x1a, 0xce, 0xcb, 0xd1, 0x1d, 0xbd, 0x1c, 0xdd, 0x13, 0xb0, 0xf0, 0x1a, 0x4f, 0xd7, 0xc7, 0x2c, 0x9e, 0x0e, - 0x06, 0x6b, 0xa4, 0xea, 0x32, 0xf7, 0x9a, 0x2c, 0xe8, 0x25, 0x4e, 0x04, 0x01, 0x86, 0x3e, 0x2b, 0xd6, 0x9a, 0x86, - 0xbf, 0x66, 0xf0, 0xf1, 0x3d, 0xbb, 0x1c, 0xdd, 0xd3, 0x3b, 0xf6, 0x7a, 0x3b, 0x9e, 0x02, 0x33, 0xb5, 0x9a, 0x85, - 0xf7, 0xc7, 0x57, 0xb3, 0x2b, 0x76, 0x1f, 0xdd, 0x9f, 0x40, 0x43, 0xaf, 0xd9, 0x3d, 0x02, 0x2e, 0xa5, 0x8f, 0x97, - 0x83, 0xd7, 0xe4, 0x70, 0x30, 0x48, 0x49, 0x14, 0xde, 0x84, 0x4e, 0x2b, 0x5f, 0xd3, 0x7b, 0x42, 0x57, 0xec, 0x0e, - 0x47, 0xe3, 0x8a, 0xe1, 0x07, 0x17, 0xec, 0xbe, 0xb9, 0x09, 0x9d, 0xdd, 0x1c, 0x57, 0x9d, 0x20, 0x46, 0xe8, 0x6b, - 0x60, 0x69, 0x96, 0x0d, 0x33, 0x01, 0x4f, 0xfa, 0x22, 0xa3, 0x44, 0xa1, 0x19, 0x88, 0xb3, 0x12, 0x10, 0x4b, 0xa2, - 0xee, 0x37, 0x1b, 0x9d, 0xc3, 0x72, 0xee, 0xf7, 0x7b, 0xb5, 0xa6, 0x07, 0x88, 0x9c, 0xd9, 0x49, 0x0f, 0x7a, 0x2e, - 0x3d, 0xc0, 0x4f, 0xd4, 0xaa, 0x41, 0x9c, 0xcc, 0xef, 0x96, 0xd1, 0xaf, 0x0e, 0x7d, 0xf8, 0xa1, 0x9b, 0xf2, 0x54, - 0xf9, 0xbf, 0x4f, 0x79, 0x8a, 0x3c, 0x7a, 0x5d, 0x3b, 0x20, 0x78, 0xce, 0x9a, 0x94, 0x1a, 0x89, 0x7a, 0x74, 0xbe, - 0x8a, 0x41, 0x1b, 0x89, 0xda, 0x06, 0xf5, 0x84, 0x16, 0x56, 0x10, 0x21, 0xe7, 0xe8, 0x39, 0x18, 0xa4, 0x42, 0xa8, - 0x1c, 0xb9, 0x28, 0xd1, 0x10, 0x24, 0x17, 0x15, 0x97, 0xe1, 0x73, 0x08, 0x95, 0xa7, 0x8f, 0x35, 0x11, 0xd6, 0xf4, - 0x18, 0x0c, 0xb0, 0x2d, 0xfc, 0xdb, 0x0e, 0xb9, 0xa8, 0xf8, 0x15, 0x9e, 0xcd, 0x6d, 0x82, 0x51, 0xb2, 0xb8, 0x15, - 0xda, 0x06, 0xb1, 0x1f, 0x0b, 0x82, 0xf5, 0x08, 0x1a, 0x8f, 0x2a, 0x7d, 0x44, 0xb8, 0x51, 0x7c, 0x24, 0x3d, 0x8d, - 0x35, 0x89, 0xe4, 0x48, 0x22, 0xf9, 0x00, 0x08, 0x27, 0x41, 0x7f, 0x71, 0xdb, 0x64, 0xdb, 0x42, 0xa2, 0xd1, 0x9f, - 0x96, 0x4c, 0xc9, 0xee, 0x65, 0x8f, 0x5d, 0x45, 0x90, 0x3d, 0xa6, 0xff, 0x74, 0xfa, 0xf0, 0xcf, 0x25, 0xce, 0xa0, - 0xf1, 0x7c, 0x91, 0x9d, 0x99, 0x39, 0x83, 0x1b, 0x39, 0x5d, 0x56, 0xae, 0xcb, 0x97, 0xfc, 0x80, 0xdf, 0xd5, 0xbc, - 0x48, 0xab, 0x83, 0x9f, 0xeb, 0x36, 0x9e, 0x53, 0xb5, 0x5e, 0xd9, 0x38, 0x2b, 0xd2, 0x38, 0xd5, 0x91, 0xba, 0x68, - 0x6b, 0x58, 0xcf, 0xef, 0x11, 0x75, 0x25, 0x2d, 0x47, 0x4f, 0x21, 0x56, 0x7e, 0xca, 0xe5, 0x3a, 0xcf, 0x7f, 0xda, - 0x49, 0xc5, 0x29, 0xf6, 0x53, 0x90, 0x2a, 0xb5, 0x5c, 0x40, 0xd5, 0x1c, 0xb5, 0xdc, 0x2d, 0xf5, 0x0e, 0xb0, 0x6e, - 0x9b, 0xf2, 0x63, 0x69, 0x76, 0xe1, 0x24, 0x7b, 0xf7, 0x27, 0x5d, 0x86, 0x01, 0xa3, 0x50, 0x66, 0xd5, 0xb5, 0xb2, - 0x2f, 0x34, 0x4e, 0xc3, 0x70, 0xe5, 0xc7, 0x0b, 0x48, 0x17, 0x30, 0x8e, 0x13, 0x25, 0x13, 0xe3, 0xf6, 0xa8, 0xad, - 0x50, 0x7d, 0xce, 0x56, 0x20, 0x60, 0xae, 0xe1, 0xec, 0xba, 0x8e, 0xb6, 0x3b, 0xe2, 0x94, 0x51, 0xb5, 0x8a, 0x8b, - 0xef, 0xe3, 0x55, 0x35, 0xb3, 0x43, 0x1b, 0xf9, 0x63, 0x3a, 0xfd, 0x7b, 0x12, 0xba, 0x85, 0x50, 0xb8, 0xe5, 0x16, - 0x46, 0x9e, 0xdc, 0x1e, 0x96, 0x71, 0x83, 0x5e, 0x89, 0x2b, 0xd5, 0x37, 0x2d, 0x85, 0x54, 0x23, 0x5f, 0xfb, 0x02, - 0x7a, 0x3d, 0xf6, 0x7e, 0x2a, 0xcc, 0xdb, 0x9e, 0x31, 0x97, 0x08, 0x56, 0xb2, 0xec, 0xf6, 0x9d, 0x1a, 0x53, 0x31, - 0x83, 0x2e, 0xb6, 0x9d, 0x45, 0xa7, 0x1b, 0xf9, 0xa7, 0x99, 0xfb, 0x65, 0xde, 0xe1, 0xae, 0xa8, 0xde, 0x02, 0x17, - 0x9a, 0x95, 0x55, 0xdd, 0x96, 0x0d, 0x9b, 0xc6, 0x6b, 0x59, 0x28, 0x36, 0xc0, 0xb0, 0xe7, 0xae, 0x85, 0x07, 0x88, - 0x9b, 0x70, 0xcf, 0x2e, 0x1a, 0xb8, 0x31, 0x7c, 0x5e, 0x49, 0xae, 0x2b, 0x8d, 0xbe, 0xf4, 0xc9, 0xd2, 0xaa, 0xe1, - 0x64, 0x31, 0xe2, 0x45, 0xba, 0x68, 0x32, 0xb3, 0x16, 0x3e, 0xe1, 0x65, 0x38, 0xe7, 0x0b, 0xad, 0x9b, 0x52, 0xa5, - 0x97, 0x2c, 0x56, 0x9d, 0xde, 0xac, 0x14, 0x56, 0x4a, 0xc4, 0x8d, 0x59, 0x26, 0x50, 0x96, 0xa2, 0x91, 0xc2, 0x9b, - 0xb2, 0x65, 0x2b, 0xa9, 0xe5, 0x3d, 0x73, 0x70, 0x1f, 0xfb, 0x01, 0x31, 0x91, 0x75, 0x60, 0x52, 0x34, 0x74, 0x40, - 0xbb, 0xea, 0xd2, 0x35, 0xa3, 0x1e, 0x0c, 0x72, 0x43, 0x12, 0xb1, 0x82, 0x14, 0x2b, 0x58, 0x37, 0xac, 0x9c, 0xe7, - 0x0b, 0x7a, 0xc9, 0xc4, 0x3c, 0x5d, 0xd0, 0x15, 0x13, 0xf3, 0x35, 0xde, 0x84, 0x2e, 0xe1, 0x84, 0x24, 0x9b, 0x58, - 0x2a, 0x60, 0x2f, 0xf1, 0xf2, 0x86, 0x67, 0xaa, 0xa2, 0x65, 0x57, 0x92, 0x03, 0x8c, 0x2f, 0xaa, 0x30, 0x2c, 0x86, - 0x97, 0x60, 0x2d, 0x71, 0x18, 0xae, 0xe6, 0x7c, 0x21, 0x7f, 0x43, 0xc0, 0xf9, 0x24, 0x94, 0xec, 0x82, 0xd9, 0x0b, - 0x64, 0x7a, 0x3d, 0xe7, 0x0b, 0x39, 0x12, 0xaa, 0xe0, 0x6b, 0x63, 0x6c, 0x12, 0x3b, 0x82, 0x96, 0x59, 0x3c, 0x1f, - 0x2f, 0xa2, 0xb8, 0x81, 0x65, 0x78, 0x26, 0x67, 0xa6, 0x25, 0xff, 0xd1, 0x76, 0x52, 0xea, 0x06, 0x2b, 0xc9, 0x1f, - 0x1e, 0x1f, 0x5d, 0x02, 0x19, 0x33, 0xbb, 0x82, 0xe9, 0x0f, 0x5d, 0x1f, 0x19, 0xdc, 0x73, 0x53, 0xce, 0xb8, 0x0c, - 0x12, 0xa5, 0x05, 0x0e, 0x72, 0x96, 0xb4, 0xb5, 0x08, 0xdf, 0x3d, 0x2a, 0xca, 0x3e, 0x13, 0xba, 0x01, 0xdd, 0x47, - 0x82, 0x3e, 0xd0, 0x7b, 0xa5, 0x0a, 0x97, 0xd5, 0x36, 0x13, 0x70, 0x17, 0x09, 0xf2, 0x5b, 0xa1, 0x53, 0x35, 0x06, - 0x55, 0x34, 0x8b, 0x58, 0xb8, 0xf7, 0x11, 0x37, 0xca, 0xe6, 0x9f, 0xfa, 0x1e, 0x2f, 0x25, 0x0c, 0x6e, 0x48, 0x4d, - 0x9f, 0xcc, 0x9b, 0x2b, 0xf6, 0x1e, 0x3a, 0xea, 0x50, 0x6b, 0xbc, 0xaf, 0x5e, 0x72, 0x0a, 0x31, 0x4a, 0x28, 0x3a, - 0x09, 0x06, 0x70, 0xbb, 0x84, 0x14, 0x7b, 0x83, 0xdd, 0xf8, 0xd7, 0xbc, 0x28, 0xb8, 0x58, 0xd7, 0x75, 0xe0, 0x06, - 0x34, 0x9c, 0x2f, 0x76, 0x43, 0x18, 0x8e, 0x69, 0xeb, 0x1a, 0x06, 0x61, 0xc6, 0x30, 0x12, 0x82, 0xd3, 0xbf, 0xe8, - 0x2b, 0x9a, 0xc4, 0xab, 0xef, 0xf8, 0x5f, 0x19, 0x2f, 0x25, 0x91, 0x06, 0x11, 0x52, 0x37, 0xf1, 0x8d, 0x74, 0x93, - 0x02, 0x0a, 0x01, 0x46, 0x01, 0x95, 0x58, 0xd3, 0x54, 0xfc, 0x2d, 0x17, 0x1f, 0xfc, 0x54, 0x74, 0x3c, 0x1a, 0x37, - 0xad, 0xce, 0xc8, 0xa0, 0x33, 0xd0, 0xa3, 0x56, 0xd4, 0xd3, 0xa0, 0x95, 0xa0, 0x1b, 0xa9, 0xdf, 0xda, 0x87, 0xc0, - 0x29, 0xd3, 0xe0, 0x9d, 0x07, 0x74, 0x73, 0xee, 0x82, 0x27, 0x8f, 0xe9, 0xb9, 0x45, 0x4f, 0xae, 0xd9, 0x49, 0xdd, - 0x43, 0xed, 0xbd, 0x1e, 0xa1, 0xa0, 0xdf, 0xc7, 0x14, 0xe8, 0x46, 0xd0, 0x38, 0x57, 0xf7, 0x1f, 0x8b, 0x5d, 0x0e, - 0xdf, 0x72, 0x96, 0x1b, 0xc0, 0x52, 0x11, 0x8d, 0x04, 0x8f, 0x02, 0xd4, 0xa5, 0x2a, 0x84, 0x2d, 0x66, 0x71, 0xa8, - 0xcc, 0x56, 0xad, 0x87, 0x82, 0x1c, 0x17, 0x23, 0x70, 0x08, 0x5d, 0x57, 0x83, 0x62, 0xb4, 0xcc, 0xea, 0xf7, 0xf8, - 0x5b, 0xb1, 0x0e, 0x49, 0xb6, 0x8f, 0x75, 0xe0, 0x86, 0x75, 0x98, 0x7e, 0xd4, 0x48, 0x01, 0x68, 0xb2, 0x11, 0xd8, - 0x04, 0xe0, 0xbd, 0xdd, 0x47, 0x84, 0x5a, 0x99, 0xee, 0x65, 0x2c, 0xe4, 0xf7, 0x5e, 0x12, 0x94, 0xe0, 0x27, 0xd4, - 0x96, 0xa5, 0xe0, 0x9d, 0x47, 0x3a, 0x27, 0x4d, 0x56, 0xbc, 0x07, 0x71, 0x5a, 0xf8, 0xc0, 0xde, 0x82, 0xe0, 0x9c, - 0x25, 0xbd, 0xc7, 0xdb, 0xac, 0x92, 0xda, 0xa8, 0x81, 0x02, 0xf8, 0xdd, 0xe0, 0x1e, 0x41, 0xbe, 0xbc, 0xe1, 0x5a, - 0x89, 0xdb, 0x90, 0x0f, 0x4b, 0x7a, 0x44, 0x06, 0xe6, 0xb9, 0x1a, 0xc6, 0xf4, 0x88, 0x1c, 0x9b, 0x67, 0x61, 0x07, - 0x70, 0x20, 0xd4, 0xa8, 0xd2, 0x23, 0x68, 0xd0, 0x6f, 0xa6, 0x45, 0x86, 0x64, 0xfd, 0xa8, 0x1b, 0x8c, 0x88, 0xbf, - 0x20, 0xa2, 0x2e, 0xfe, 0xf9, 0x60, 0xae, 0x7b, 0xcc, 0x05, 0xc2, 0x1c, 0x0c, 0x38, 0x88, 0xdb, 0x20, 0xd4, 0x07, - 0xcc, 0xe6, 0x2e, 0xaa, 0xe8, 0xbd, 0x31, 0xcc, 0xec, 0xe8, 0x0f, 0x37, 0x12, 0x7c, 0x9d, 0xb5, 0x41, 0x9d, 0x17, - 0x87, 0x40, 0x10, 0xdc, 0x17, 0xaa, 0x9a, 0xab, 0x1e, 0xd8, 0x78, 0xcb, 0x7e, 0x6c, 0xb7, 0xe3, 0x69, 0x65, 0xaf, - 0xfd, 0x15, 0x85, 0x93, 0x4f, 0xca, 0xbf, 0xde, 0xeb, 0x0c, 0x16, 0x8c, 0x0c, 0x5f, 0x3a, 0xfb, 0x17, 0xbe, 0x56, - 0xd2, 0xbd, 0x6a, 0x50, 0x90, 0xc7, 0x47, 0x92, 0xfe, 0xed, 0x95, 0x95, 0x4f, 0xcd, 0xf4, 0x6f, 0xb7, 0x7a, 0x7d, - 0x1e, 0x8f, 0x26, 0xdb, 0x6d, 0x4f, 0x19, 0xb8, 0x52, 0x1d, 0x43, 0x08, 0x9d, 0xeb, 0xc9, 0xe1, 0x11, 0x44, 0x45, - 0xf0, 0xe3, 0x6e, 0x16, 0x9e, 0x44, 0xc6, 0x8d, 0xd3, 0x59, 0x78, 0x82, 0x1d, 0xee, 0x44, 0x25, 0x2e, 0x46, 0xad, - 0x0d, 0x4e, 0xcf, 0x93, 0x10, 0x42, 0x39, 0x60, 0x65, 0x77, 0xf2, 0xcf, 0xbd, 0x34, 0x13, 0x92, 0x93, 0xd5, 0xed, - 0x94, 0xee, 0x60, 0x9a, 0x1f, 0xe8, 0x11, 0x1c, 0x70, 0x67, 0x7f, 0x35, 0x1f, 0xc3, 0x24, 0x53, 0xe4, 0x14, 0xc9, - 0x2f, 0xd2, 0x53, 0x48, 0xda, 0xa1, 0xa7, 0x92, 0x00, 0x4e, 0xa8, 0xf9, 0x18, 0x7e, 0xc3, 0xb8, 0x7f, 0xe7, 0xbf, - 0xb6, 0x53, 0x11, 0x3d, 0xa1, 0x58, 0xa6, 0x22, 0xa7, 0x49, 0x56, 0x26, 0x10, 0xb5, 0x51, 0x36, 0x23, 0xfa, 0xca, - 0xc6, 0x7c, 0x94, 0x84, 0xcf, 0xa9, 0xf5, 0x7f, 0x86, 0xf0, 0x69, 0x74, 0x46, 0x80, 0xcb, 0x2b, 0xaf, 0x2e, 0xc2, - 0xa7, 0x4f, 0xe8, 0xc1, 0xe4, 0xeb, 0x23, 0x7a, 0x70, 0xf4, 0xd5, 0x53, 0x02, 0xb0, 0x68, 0x57, 0x17, 0xe1, 0xd1, - 0xd3, 0xa7, 0xf4, 0xe0, 0xdb, 0x6f, 0xe9, 0xc1, 0xe4, 0xab, 0x23, 0x2f, 0x6d, 0xf2, 0xf4, 0x5b, 0x7a, 0xf0, 0xf5, - 0x13, 0x2f, 0xed, 0x68, 0xfc, 0x94, 0x1e, 0x7c, 0xf3, 0xb5, 0x4e, 0xfb, 0x1b, 0x64, 0xfb, 0xf6, 0x08, 0xff, 0xd3, - 0x69, 0x93, 0xa7, 0x5f, 0xd1, 0x83, 0xc9, 0x18, 0x2a, 0x79, 0x6a, 0x2b, 0x19, 0x4f, 0xe0, 0xe3, 0xaf, 0xe0, 0xbf, - 0xbf, 0x91, 0x60, 0x41, 0x6b, 0xc1, 0x92, 0x0a, 0xf5, 0x67, 0x28, 0xe2, 0x44, 0xd5, 0x44, 0xc2, 0x43, 0xcc, 0x2c, - 0xbf, 0x89, 0xc3, 0x80, 0xd8, 0x74, 0x28, 0x88, 0x1e, 0x8c, 0x47, 0x4f, 0x49, 0xe0, 0xc2, 0xd3, 0xdd, 0xba, 0x20, - 0x63, 0x49, 0x35, 0xcf, 0xbe, 0x48, 0x34, 0x63, 0xe0, 0x00, 0x58, 0x7d, 0x74, 0x73, 0xd5, 0x62, 0x9e, 0x7d, 0x51, - 0x8b, 0xdd, 0x5c, 0xbf, 0xb5, 0x00, 0xe5, 0xdd, 0x55, 0xcb, 0x6e, 0x4b, 0x19, 0x3a, 0xad, 0x35, 0xfa, 0xec, 0x23, - 0xa6, 0x0f, 0x06, 0xce, 0x0d, 0xfb, 0xef, 0x3b, 0xe5, 0xb4, 0xbe, 0x51, 0x28, 0xd4, 0xa8, 0x3c, 0x24, 0xec, 0x04, - 0x8a, 0x1e, 0x0c, 0x80, 0x27, 0x70, 0x70, 0xdf, 0xfe, 0xcd, 0x32, 0x3e, 0x76, 0x94, 0xf1, 0x33, 0xca, 0x10, 0xd0, - 0xa8, 0x87, 0x99, 0x4d, 0x0f, 0x1b, 0xdd, 0xe8, 0x25, 0x0b, 0x79, 0x32, 0xf9, 0x9e, 0xc1, 0xae, 0xd6, 0xb5, 0x38, - 0xd0, 0xa2, 0x68, 0x71, 0x79, 0x90, 0xf2, 0x59, 0xcd, 0xfe, 0xbe, 0x44, 0xf5, 0x56, 0xe4, 0xbd, 0x11, 0xd9, 0xac, - 0x66, 0xdf, 0xeb, 0x37, 0xc0, 0xcd, 0xb0, 0xdf, 0xe4, 0x93, 0x1b, 0x38, 0x83, 0x0b, 0xd3, 0x1e, 0x69, 0x62, 0x04, - 0x58, 0x01, 0x19, 0x38, 0xf0, 0x00, 0xe8, 0xa0, 0x3b, 0xda, 0xdb, 0xad, 0x4c, 0xf1, 0xfb, 0x6c, 0x60, 0x00, 0x35, - 0xf3, 0x36, 0xb1, 0x65, 0xff, 0xcb, 0x93, 0x97, 0xa0, 0x70, 0xcb, 0x2f, 0x6f, 0xa7, 0x30, 0x84, 0x10, 0xfc, 0x71, - 0xc9, 0x00, 0x70, 0x20, 0xc0, 0x60, 0xac, 0x55, 0x40, 0xf5, 0x96, 0x8f, 0x36, 0x5c, 0xaa, 0x27, 0x81, 0x33, 0xb8, - 0x14, 0x65, 0xc2, 0xdf, 0x2a, 0xb1, 0x3f, 0x5a, 0x3f, 0xba, 0xbe, 0x3d, 0x0e, 0xac, 0x7d, 0x8f, 0x8f, 0xd4, 0x67, - 0xde, 0x75, 0x60, 0xd3, 0xf2, 0x8d, 0xaf, 0x1a, 0x23, 0xf1, 0x28, 0x80, 0x37, 0xd0, 0x11, 0x29, 0x34, 0x52, 0x2d, - 0x70, 0x0c, 0x85, 0xb4, 0x40, 0x1c, 0x79, 0x75, 0x83, 0x2d, 0x88, 0x08, 0xc1, 0xc3, 0xed, 0x5f, 0x4b, 0x19, 0x38, - 0xaa, 0xdf, 0xe7, 0xc2, 0x75, 0x7b, 0xd2, 0x76, 0xe4, 0x38, 0xf5, 0x53, 0x07, 0xdf, 0x9c, 0x34, 0x8d, 0xb6, 0x5c, - 0x49, 0x99, 0x61, 0x59, 0xd8, 0x49, 0xa8, 0xe4, 0x1e, 0xb5, 0x03, 0xc9, 0x17, 0x72, 0x88, 0x64, 0x81, 0x51, 0x28, - 0xc8, 0x70, 0x42, 0xc1, 0x66, 0xaa, 0x5a, 0x66, 0x97, 0x75, 0xb8, 0x91, 0x0a, 0x65, 0x4e, 0xd1, 0xb7, 0x1b, 0x1c, - 0x48, 0x48, 0x94, 0x55, 0x6f, 0xe2, 0x37, 0x21, 0x82, 0xd5, 0x71, 0x65, 0x0b, 0xc5, 0x9d, 0xfd, 0xc9, 0xd3, 0x2e, - 0xfe, 0x48, 0xbb, 0x80, 0xda, 0x58, 0x4c, 0xc3, 0x89, 0x89, 0x7d, 0x63, 0xbf, 0x30, 0x9a, 0x1e, 0x80, 0xfa, 0xae, - 0xa4, 0x18, 0x41, 0x7e, 0xa5, 0xed, 0x63, 0x7b, 0x8c, 0x89, 0x19, 0xc4, 0x1a, 0x96, 0x39, 0x33, 0xd9, 0x37, 0xc2, - 0x4e, 0x00, 0xb8, 0x11, 0x5a, 0x23, 0x21, 0xf0, 0x78, 0x1d, 0xe2, 0x79, 0x29, 0xc3, 0xb7, 0x66, 0x84, 0x8e, 0xc1, - 0x9b, 0xca, 0x34, 0x32, 0x13, 0xae, 0x60, 0x50, 0x1f, 0xdb, 0x2a, 0x0a, 0xab, 0xa9, 0x2c, 0x3b, 0x01, 0xb8, 0x81, - 0xec, 0x58, 0x5f, 0x3c, 0x67, 0xf5, 0x3c, 0x5b, 0x44, 0x3a, 0x28, 0x60, 0x5e, 0x19, 0x06, 0xed, 0xcd, 0x1e, 0xd9, - 0x8e, 0x45, 0xe8, 0x86, 0xfb, 0x08, 0xc6, 0xd3, 0xf6, 0x05, 0x2b, 0x88, 0x46, 0x88, 0x87, 0x19, 0x33, 0xf8, 0x5e, - 0x69, 0xca, 0x53, 0xd9, 0x12, 0x08, 0x1c, 0x85, 0x50, 0x17, 0xbb, 0x46, 0x09, 0x36, 0x93, 0x17, 0xcc, 0x60, 0xc7, - 0x8e, 0xd4, 0x74, 0xc9, 0x3a, 0x1d, 0xca, 0x29, 0x2d, 0xd4, 0x94, 0x2a, 0x5f, 0xc3, 0x6a, 0x5e, 0xa0, 0x87, 0x1e, - 0xb8, 0x1e, 0x28, 0x87, 0xbc, 0x82, 0x4e, 0x74, 0x04, 0x9d, 0x56, 0x9b, 0xb0, 0x73, 0x23, 0xd5, 0xb2, 0x06, 0x79, - 0xc7, 0x50, 0xef, 0x88, 0x17, 0x4e, 0xa0, 0x2e, 0x84, 0x08, 0xd9, 0xdb, 0x22, 0x7d, 0x44, 0xb3, 0xac, 0x7a, 0x09, - 0x65, 0x71, 0xc4, 0xd6, 0x05, 0x2b, 0x6d, 0x34, 0xb9, 0xe4, 0x11, 0x4f, 0x11, 0x11, 0xf0, 0x54, 0x6a, 0xd7, 0x77, - 0x5a, 0x42, 0x68, 0x96, 0x02, 0x71, 0xb3, 0x51, 0x9c, 0x1b, 0x13, 0xc8, 0x02, 0xe8, 0xdb, 0x4f, 0xd9, 0xb5, 0x13, - 0x0e, 0x76, 0x73, 0x9d, 0x15, 0xcf, 0xf9, 0x65, 0x56, 0xf0, 0x14, 0xc1, 0xae, 0xee, 0xf4, 0x03, 0xb7, 0x6c, 0x1b, - 0x58, 0xbe, 0x7d, 0x07, 0x0b, 0xa6, 0x0a, 0x95, 0x52, 0x22, 0x2b, 0xa2, 0x0a, 0x32, 0xbb, 0xcc, 0xdd, 0xeb, 0xac, - 0x78, 0x1d, 0xdf, 0x81, 0x37, 0x85, 0xc7, 0x4f, 0x8f, 0x2e, 0xf0, 0x4b, 0x44, 0x12, 0x85, 0x18, 0xb6, 0x18, 0x11, - 0x0b, 0x91, 0x63, 0xc7, 0x84, 0x72, 0x29, 0x68, 0x6d, 0x0d, 0x81, 0x13, 0x7f, 0x5a, 0x76, 0xef, 0x3a, 0x2b, 0xb4, - 0x7d, 0xc6, 0x75, 0x7c, 0xc7, 0x0a, 0x09, 0x66, 0x81, 0x71, 0xee, 0xdb, 0x52, 0x92, 0xeb, 0xac, 0xd0, 0x02, 0x92, - 0xeb, 0xf8, 0x8e, 0xfa, 0x32, 0x0e, 0x65, 0x45, 0xe7, 0xc4, 0xf9, 0xdd, 0x1d, 0x7e, 0x81, 0xa1, 0x56, 0xc6, 0xfd, - 0x3e, 0x48, 0xcc, 0x84, 0x69, 0xca, 0x4c, 0x44, 0x42, 0xa1, 0x85, 0xd4, 0x94, 0x0f, 0x26, 0x64, 0x77, 0xa5, 0x1a, - 0x46, 0xd4, 0x7c, 0x15, 0x56, 0xb3, 0x71, 0x34, 0x21, 0x74, 0xd2, 0xb1, 0xde, 0x75, 0x6b, 0x21, 0xd3, 0xe8, 0x69, - 0xe4, 0xf8, 0x74, 0x96, 0xac, 0x9e, 0x96, 0xc7, 0x8c, 0x4f, 0xcb, 0xc1, 0x80, 0xa8, 0xd0, 0xc1, 0x1b, 0xac, 0x07, - 0x4c, 0x69, 0x6c, 0xbc, 0x35, 0xdd, 0xea, 0x97, 0x42, 0x86, 0xa4, 0x77, 0x0c, 0x48, 0x32, 0x61, 0x83, 0xdd, 0x82, - 0x44, 0xd1, 0xf1, 0xbf, 0x93, 0x5b, 0x70, 0xd7, 0x83, 0xd1, 0x8f, 0xee, 0xeb, 0x18, 0xff, 0xa1, 0xb6, 0x05, 0x51, - 0x9f, 0x2a, 0xd6, 0xeb, 0x48, 0x94, 0x21, 0x17, 0xe1, 0x67, 0x47, 0x43, 0x34, 0x51, 0xed, 0xb1, 0xa0, 0x58, 0x5f, - 0x5f, 0xf0, 0x12, 0xa7, 0x9f, 0xd9, 0xcb, 0x15, 0x6c, 0x0b, 0x5a, 0x6b, 0x1a, 0xf5, 0x26, 0x7e, 0x13, 0x99, 0xcb, - 0x82, 0x2a, 0xf2, 0x39, 0x0a, 0x59, 0xf3, 0x30, 0xac, 0x87, 0xed, 0x41, 0x24, 0x87, 0xed, 0x49, 0xf0, 0x1a, 0x03, - 0x0b, 0x64, 0x87, 0x46, 0xe0, 0x22, 0x34, 0xf2, 0xb7, 0x63, 0x70, 0xe1, 0x32, 0x88, 0x2c, 0x43, 0x15, 0xbf, 0xa9, - 0xdd, 0x04, 0xd9, 0x2b, 0x74, 0x9a, 0xc2, 0xaa, 0xa4, 0x49, 0x3e, 0xfc, 0x7a, 0x29, 0x4a, 0xcc, 0xe4, 0x74, 0xd9, - 0xa1, 0xaf, 0xed, 0xf6, 0x0e, 0x74, 0xc1, 0xaa, 0x4f, 0xce, 0xd7, 0x8f, 0x3b, 0x7b, 0x02, 0x46, 0xb1, 0x32, 0x87, - 0x2f, 0xa4, 0x54, 0x3e, 0x28, 0xcd, 0xc7, 0x30, 0xaf, 0x14, 0xc7, 0x6e, 0x00, 0x93, 0x80, 0x7d, 0x86, 0x54, 0x87, - 0x69, 0xc7, 0x3e, 0x47, 0x1b, 0x58, 0x12, 0x70, 0xf8, 0x47, 0x99, 0x68, 0xdc, 0xab, 0x7b, 0x95, 0xfa, 0x21, 0x5b, - 0xe6, 0x0b, 0xe0, 0xf3, 0x61, 0xd7, 0x46, 0x05, 0xca, 0x26, 0x22, 0x41, 0x61, 0xcb, 0x63, 0x90, 0xf6, 0x28, 0xa6, - 0xab, 0x92, 0x27, 0x19, 0x4a, 0x29, 0x12, 0xe5, 0x13, 0x9c, 0xc3, 0x1b, 0xdc, 0x8f, 0x32, 0x20, 0xbc, 0x0c, 0x39, - 0x1d, 0xa5, 0x54, 0x59, 0xc0, 0x48, 0xea, 0x01, 0xa2, 0xbc, 0x0c, 0xe4, 0x78, 0xdb, 0xed, 0x84, 0xae, 0xd8, 0x72, - 0x38, 0xa1, 0x48, 0x4a, 0xae, 0xb0, 0xdc, 0x6b, 0xd0, 0x79, 0x5c, 0xb0, 0xde, 0x0b, 0xc0, 0x22, 0x38, 0x87, 0xbf, - 0x31, 0xa1, 0x37, 0xf0, 0x37, 0x27, 0xf4, 0x35, 0x0b, 0xaf, 0x87, 0x57, 0xe4, 0x30, 0x4c, 0x07, 0x13, 0x29, 0x18, - 0xbb, 0x67, 0xcb, 0x22, 0x94, 0x89, 0xab, 0xc3, 0x4b, 0xf2, 0xf8, 0x92, 0xde, 0xd1, 0x5b, 0x7a, 0x46, 0xdf, 0x02, - 0xe1, 0xbf, 0x3f, 0x9e, 0xf0, 0xe1, 0xe4, 0x49, 0xbf, 0xdf, 0xbb, 0xe8, 0xf7, 0x7b, 0xe7, 0xda, 0x80, 0x42, 0xed, - 0xa2, 0xab, 0x86, 0xaa, 0x5f, 0xd7, 0xcd, 0x62, 0xfa, 0x56, 0x6e, 0xdc, 0x84, 0x67, 0x79, 0x78, 0x7d, 0x78, 0x4f, - 0x86, 0xf8, 0x78, 0x99, 0x0b, 0x51, 0x86, 0x57, 0x87, 0xf7, 0x84, 0xbe, 0x3d, 0x01, 0xbd, 0x29, 0xd6, 0xf7, 0xf6, - 0xf1, 0xbd, 0xaa, 0x8d, 0xd0, 0x17, 0x61, 0x02, 0xdb, 0xe4, 0x8e, 0x99, 0xbb, 0xf6, 0x64, 0x0c, 0xb1, 0x4c, 0xee, - 0x9d, 0xf2, 0xee, 0x1f, 0xdf, 0x91, 0xc3, 0x3b, 0xf0, 0x14, 0x35, 0xe4, 0x6f, 0x16, 0xde, 0xb2, 0x56, 0x0d, 0x8f, - 0xef, 0xe9, 0x59, 0xab, 0x11, 0x8f, 0xef, 0x49, 0x14, 0xde, 0xb2, 0x2b, 0x7a, 0xc6, 0xae, 0x09, 0xbd, 0xe8, 0xf7, - 0xcf, 0xfb, 0x7d, 0xd1, 0xef, 0xff, 0x3d, 0x0e, 0xc3, 0x78, 0x58, 0x92, 0x43, 0x41, 0xef, 0x0f, 0x27, 0xfc, 0x2b, - 0x32, 0x0b, 0x55, 0xf3, 0xe5, 0x82, 0x33, 0x2a, 0x6f, 0x99, 0xeb, 0x9e, 0x82, 0xb5, 0xc2, 0x3d, 0x93, 0x4f, 0x6f, - 0xe9, 0x2d, 0x2b, 0xe9, 0x19, 0x8b, 0x49, 0x74, 0x03, 0xad, 0xb8, 0x98, 0x95, 0xd1, 0x2d, 0x3d, 0x63, 0xe7, 0xb3, - 0x38, 0x3a, 0xa3, 0x6f, 0x59, 0x3e, 0x9c, 0x40, 0xde, 0xb3, 0xe1, 0x2d, 0x39, 0x7c, 0x4b, 0xa2, 0xf0, 0xad, 0xfa, - 0x7d, 0x4f, 0xaf, 0x78, 0xf8, 0x96, 0x3a, 0xd5, 0xbc, 0x25, 0xba, 0x7a, 0xaf, 0xf6, 0xb7, 0x24, 0x72, 0x07, 0xf3, - 0xad, 0xb1, 0xa7, 0x79, 0x64, 0x69, 0x63, 0x5a, 0x84, 0xa0, 0x6f, 0x2e, 0xc2, 0x5b, 0x42, 0xa6, 0xfe, 0xd8, 0xc1, - 0x80, 0xce, 0x1e, 0x45, 0x09, 0xa1, 0xb7, 0x6e, 0xa9, 0xb7, 0x38, 0x86, 0x7a, 0x84, 0x64, 0xda, 0x19, 0xa6, 0xe1, - 0x3a, 0x78, 0xa5, 0xc0, 0x3a, 0x2e, 0xfa, 0xfd, 0x70, 0xdd, 0xef, 0x43, 0xa4, 0xfb, 0x72, 0xa6, 0x63, 0xbb, 0x59, - 0xb2, 0x49, 0x6f, 0x41, 0xfb, 0xff, 0x6a, 0x30, 0x80, 0xce, 0x38, 0x25, 0x85, 0xb7, 0x83, 0x57, 0x8f, 0xef, 0x89, - 0xac, 0xa3, 0xa4, 0x95, 0x08, 0x4b, 0xfa, 0x9a, 0x66, 0x00, 0xf8, 0xf5, 0x6a, 0x30, 0x20, 0x91, 0xfe, 0x8c, 0x4c, - 0x5f, 0x1d, 0xbf, 0x9d, 0x0e, 0x06, 0xaf, 0xf4, 0x36, 0xf9, 0x8b, 0xed, 0x29, 0x05, 0xd6, 0xdf, 0x79, 0xbf, 0xff, - 0xd7, 0x49, 0x4c, 0x2e, 0x4a, 0x1e, 0x7f, 0x9c, 0xfa, 0x6d, 0xf9, 0xcb, 0x46, 0x55, 0x3b, 0xef, 0xf7, 0xd7, 0xfd, - 0xfe, 0x19, 0x60, 0x17, 0xcd, 0xac, 0xaf, 0x27, 0x48, 0x5b, 0xe6, 0x96, 0x22, 0x29, 0x92, 0x43, 0x63, 0x68, 0x5b, - 0x2c, 0xdb, 0x36, 0xeb, 0xc8, 0xc0, 0xe2, 0xc8, 0xaf, 0x28, 0x6e, 0x48, 0x14, 0xf6, 0xce, 0xb7, 0xdb, 0x33, 0xc6, - 0x58, 0x4c, 0x40, 0xfa, 0xe1, 0xbe, 0x3e, 0x6b, 0xbc, 0x18, 0x62, 0x95, 0x40, 0x66, 0x73, 0xb3, 0x34, 0x87, 0x40, - 0xc4, 0x61, 0xd3, 0xbf, 0xd7, 0xf7, 0xf2, 0xaa, 0xb1, 0x7c, 0xeb, 0xcf, 0x00, 0x42, 0x24, 0x58, 0xc8, 0x67, 0x38, - 0x06, 0x55, 0x06, 0xc0, 0xbf, 0x91, 0x9c, 0x79, 0x01, 0xa0, 0xe6, 0x64, 0xbb, 0x1d, 0x8d, 0xc7, 0x13, 0x5a, 0xb2, - 0xd1, 0xdf, 0x9e, 0x3e, 0xae, 0x1f, 0x87, 0x41, 0x30, 0xc8, 0x48, 0x4b, 0x4f, 0x61, 0x16, 0x6b, 0x7d, 0x08, 0x46, - 0xf0, 0x8a, 0x7d, 0xbc, 0xc9, 0x3e, 0x9b, 0x7d, 0x44, 0xc2, 0xea, 0x31, 0x8e, 0xbc, 0x48, 0x5b, 0x7a, 0xbb, 0x3d, - 0x0c, 0x26, 0x2f, 0xd2, 0x4f, 0xb0, 0x9d, 0x2e, 0xff, 0xe6, 0xc0, 0x78, 0xc2, 0xc1, 0x68, 0x2f, 0x0a, 0xea, 0x4c, - 0xdb, 0x6e, 0x6b, 0xf7, 0x12, 0xf8, 0x06, 0x53, 0x41, 0xc7, 0x66, 0x58, 0xb8, 0x41, 0x4d, 0xe4, 0xd1, 0x32, 0xa8, - 0x1b, 0x69, 0x3b, 0x07, 0xd4, 0x12, 0xab, 0xd2, 0x71, 0x0b, 0x34, 0x43, 0x86, 0xba, 0xdc, 0xd3, 0xfa, 0x5f, 0xbc, - 0x14, 0x1a, 0x3e, 0xc3, 0x8a, 0x08, 0x1d, 0x6e, 0x8d, 0xbb, 0xdc, 0x5a, 0xf5, 0x09, 0x6e, 0xad, 0x40, 0x12, 0xab, - 0x61, 0x49, 0xf5, 0xe5, 0x28, 0x61, 0x27, 0x05, 0xe3, 0x33, 0xa0, 0xe3, 0x31, 0x3c, 0x08, 0x56, 0xcd, 0x44, 0x94, - 0xa0, 0x7d, 0xa2, 0x8d, 0x30, 0xf8, 0x27, 0x60, 0xf6, 0xd3, 0x1c, 0xfe, 0x0a, 0x32, 0x4d, 0x8e, 0x21, 0x20, 0xc4, - 0xf1, 0x78, 0x16, 0x87, 0x63, 0x12, 0x25, 0x27, 0xf0, 0x04, 0xff, 0x95, 0xe1, 0x98, 0x34, 0xea, 0x0e, 0x23, 0xe4, - 0xe5, 0x36, 0x61, 0x00, 0x57, 0x36, 0x9e, 0x4d, 0x22, 0x23, 0xdd, 0x15, 0x8f, 0x47, 0xe3, 0xa7, 0x64, 0x1a, 0x87, - 0x62, 0x90, 0x10, 0x0a, 0xde, 0xbd, 0x61, 0x31, 0x4c, 0x14, 0x3c, 0x1b, 0xb0, 0x79, 0x85, 0x65, 0xf3, 0x04, 0x9c, - 0x80, 0x30, 0x4c, 0xc8, 0xb1, 0xee, 0x41, 0x4a, 0x51, 0xe7, 0x39, 0xf6, 0x53, 0x1d, 0x41, 0x98, 0x1d, 0xb5, 0x54, - 0x7c, 0x05, 0x40, 0x97, 0x38, 0x38, 0xd4, 0x20, 0x61, 0x54, 0xb3, 0xb0, 0x70, 0xa8, 0x94, 0xae, 0xee, 0xb0, 0xf2, - 0x28, 0xbf, 0x6e, 0xd0, 0x61, 0x45, 0x06, 0x13, 0x5a, 0x9c, 0x4c, 0xf8, 0x57, 0x10, 0xc0, 0xc3, 0x8b, 0xf8, 0x25, - 0x71, 0x62, 0x20, 0xbc, 0x0a, 0x32, 0x50, 0x69, 0x23, 0x1b, 0x33, 0x32, 0x15, 0x1f, 0x40, 0x98, 0x94, 0x83, 0x5b, - 0xb1, 0xce, 0x53, 0x88, 0x0a, 0xb6, 0xce, 0xeb, 0x83, 0x2b, 0xb0, 0x64, 0x8f, 0x6b, 0x88, 0x13, 0xb6, 0x5e, 0x01, - 0x76, 0xee, 0xa3, 0x4d, 0xd1, 0x1c, 0xc8, 0xef, 0x0e, 0xb0, 0xe5, 0xf0, 0xaa, 0x16, 0x07, 0x93, 0xf1, 0x78, 0x3c, - 0xfa, 0x1d, 0x8e, 0x0e, 0x20, 0xb4, 0x24, 0xd2, 0x7c, 0x32, 0x40, 0xe3, 0xae, 0x6b, 0xee, 0x8c, 0x0b, 0x45, 0x59, - 0xe9, 0x64, 0x42, 0x40, 0xfc, 0xac, 0xfb, 0x06, 0xfb, 0x8a, 0xab, 0xf8, 0x27, 0xbb, 0x9f, 0xe8, 0x15, 0x2d, 0x57, - 0xea, 0xe8, 0xdd, 0xdb, 0xb3, 0x57, 0x1f, 0x5e, 0xfd, 0xfa, 0xe2, 0xfc, 0xd5, 0x9b, 0x97, 0xaf, 0xde, 0xbc, 0xfa, - 0xf0, 0xcf, 0x07, 0x18, 0x6c, 0xd7, 0x56, 0xc4, 0x8c, 0xbd, 0x73, 0x8f, 0x71, 0x6a, 0x71, 0x85, 0xb3, 0x47, 0xf6, - 0x16, 0x0b, 0xb0, 0x09, 0x9a, 0x5b, 0xa8, 0xa8, 0x62, 0x34, 0x6a, 0x75, 0x4f, 0x40, 0x46, 0xa3, 0x46, 0x36, 0x1e, - 0x56, 0x6c, 0x8d, 0x5c, 0xbc, 0x65, 0x38, 0xf8, 0xc8, 0xfc, 0x96, 0x9c, 0x09, 0x37, 0xa3, 0xad, 0x58, 0x11, 0xf0, - 0xf9, 0x5a, 0x17, 0xb5, 0xc3, 0x85, 0xc8, 0xbd, 0x6d, 0x9e, 0x43, 0x42, 0x1d, 0x22, 0xd7, 0xc1, 0xfb, 0x7a, 0x64, - 0x8f, 0x8f, 0x9c, 0x27, 0xe9, 0x19, 0xea, 0x72, 0x34, 0x7c, 0xe4, 0x3d, 0xa3, 0x13, 0x73, 0xa3, 0x75, 0xa8, 0xe7, - 0x25, 0xec, 0x6f, 0x29, 0xc6, 0x86, 0x68, 0x0f, 0x29, 0x62, 0x7d, 0x58, 0xdd, 0xef, 0xee, 0xcd, 0xe8, 0x7b, 0x38, - 0x7e, 0xa4, 0x6a, 0x02, 0x69, 0x51, 0x20, 0x75, 0x65, 0xc8, 0x6d, 0xcf, 0xc2, 0x52, 0xff, 0x0c, 0x3d, 0x02, 0x68, - 0x2e, 0x3b, 0x86, 0x04, 0xea, 0xc5, 0x6b, 0x5c, 0xff, 0x9c, 0x7c, 0x59, 0xd1, 0xce, 0x17, 0xdf, 0x41, 0x88, 0x61, - 0xf7, 0x8a, 0xe0, 0x4d, 0xb8, 0x9d, 0x64, 0x7b, 0x69, 0xd1, 0xf7, 0xaa, 0xeb, 0x18, 0x8f, 0xbb, 0x3d, 0x57, 0x0a, - 0xff, 0xd6, 0x05, 0xf6, 0x40, 0xfe, 0x75, 0xbc, 0x60, 0x21, 0x60, 0x33, 0x1e, 0x9a, 0x45, 0x62, 0xfd, 0xde, 0xe9, - 0x84, 0x1c, 0x1e, 0x4d, 0xf9, 0x90, 0x15, 0xb4, 0x1a, 0xb0, 0xa2, 0xd9, 0xa1, 0xe6, 0xbc, 0x4d, 0xc8, 0xab, 0x5d, - 0x1a, 0x5e, 0x0d, 0xf9, 0x43, 0x97, 0xa4, 0x0f, 0xdc, 0x73, 0xa8, 0x36, 0xcd, 0xc5, 0x90, 0xa6, 0x9c, 0xee, 0x52, - 0x19, 0x10, 0x22, 0x5d, 0xc7, 0x35, 0x69, 0xd4, 0x51, 0xb5, 0xb4, 0x92, 0x8e, 0x9b, 0x6c, 0xf3, 0x89, 0x4b, 0xb6, - 0xbc, 0x5d, 0xbb, 0xd7, 0xea, 0xf6, 0x85, 0x19, 0xc8, 0xdf, 0x1f, 0x88, 0x6a, 0xa2, 0x21, 0xba, 0x80, 0x0a, 0xfe, - 0x01, 0x5e, 0x9e, 0x3c, 0x52, 0x0a, 0xd0, 0x7d, 0x67, 0x47, 0xd7, 0x1e, 0xf7, 0x66, 0xb1, 0xb5, 0xc4, 0x39, 0xab, - 0x5d, 0x67, 0x79, 0x59, 0xb6, 0x44, 0xd7, 0xa9, 0xd8, 0xcf, 0x61, 0x47, 0xdf, 0x9d, 0x6d, 0x00, 0x44, 0x29, 0xac, - 0xed, 0xd9, 0x5f, 0x39, 0x67, 0x7f, 0x65, 0xce, 0x7e, 0xb3, 0x09, 0xa4, 0x0f, 0x2b, 0xb4, 0xec, 0xa5, 0x28, 0x6a, - 0xdd, 0xe4, 0xb1, 0xaf, 0xcb, 0x42, 0x5a, 0xcc, 0x0f, 0x0d, 0xed, 0x7a, 0x32, 0xa6, 0x02, 0xd5, 0x23, 0x3f, 0x60, - 0xab, 0x0e, 0x0b, 0xf2, 0xf0, 0x3d, 0xf3, 0x7f, 0xf6, 0x06, 0xb9, 0xef, 0x6e, 0xf7, 0x7f, 0x73, 0xa1, 0x83, 0xdb, - 0xda, 0xb2, 0x72, 0xd4, 0xd5, 0x71, 0x89, 0x77, 0xb5, 0xe5, 0xc3, 0x77, 0xb5, 0x77, 0x99, 0x5a, 0x76, 0x35, 0xa0, - 0x06, 0x15, 0xeb, 0x6b, 0x5e, 0x66, 0x49, 0x63, 0x14, 0x1a, 0x6f, 0x39, 0x84, 0xf6, 0x70, 0x0e, 0x2e, 0x90, 0xc3, - 0x12, 0x42, 0x3f, 0xd6, 0x5a, 0x00, 0xe8, 0xb2, 0xd8, 0x6f, 0x79, 0x98, 0x91, 0x81, 0x2b, 0xf1, 0x2b, 0x84, 0x2b, - 0x2e, 0x3e, 0xdc, 0xc9, 0x4c, 0xd0, 0xab, 0xc4, 0x46, 0xcd, 0x15, 0xed, 0x98, 0x1f, 0xee, 0x17, 0x18, 0x0d, 0xc2, - 0x69, 0x4b, 0x76, 0x58, 0x75, 0xcc, 0x72, 0x0d, 0x47, 0x6d, 0x61, 0xcb, 0x2c, 0x5a, 0xd7, 0xcf, 0x7a, 0x98, 0xa9, - 0x33, 0xe5, 0x2d, 0xc8, 0xbe, 0x90, 0xbb, 0x9f, 0xaa, 0x8a, 0x2b, 0x72, 0x32, 0x19, 0x4f, 0x49, 0x35, 0x18, 0xb4, - 0x92, 0x8f, 0x31, 0x79, 0x38, 0xdc, 0x61, 0x2e, 0x2b, 0xd5, 0x0f, 0xa7, 0x0f, 0x50, 0x9f, 0xb7, 0x25, 0xc9, 0xa6, - 0x66, 0x7f, 0x82, 0x59, 0x2c, 0x10, 0x47, 0x0b, 0xbf, 0x38, 0x5f, 0x00, 0xc8, 0x32, 0x2c, 0x33, 0x25, 0x2c, 0x82, - 0x2b, 0x3d, 0x74, 0xb2, 0x64, 0xe2, 0x78, 0x3c, 0x73, 0x7b, 0x6e, 0x19, 0x1c, 0x42, 0xa2, 0x89, 0x31, 0x7e, 0x71, - 0xb3, 0x60, 0x1c, 0x87, 0xe2, 0x44, 0x78, 0xdf, 0x15, 0x24, 0x1a, 0x6b, 0x53, 0x65, 0x75, 0x95, 0xa8, 0x87, 0x09, - 0x79, 0x5c, 0x92, 0xc3, 0x92, 0x2e, 0xdd, 0xb1, 0xc4, 0xf4, 0xc3, 0xf8, 0x70, 0x32, 0x26, 0x8f, 0xe3, 0xc7, 0x13, - 0x0d, 0x37, 0xec, 0xe6, 0xc8, 0x87, 0x4b, 0x72, 0xe8, 0x57, 0x09, 0xa6, 0xa8, 0xba, 0x67, 0x6e, 0x25, 0xc9, 0x60, - 0x39, 0x48, 0x1f, 0xb7, 0xf2, 0x62, 0xad, 0x6a, 0xbc, 0xd7, 0xc7, 0x7c, 0x4a, 0x2a, 0xef, 0xc6, 0xb0, 0xa6, 0xd7, - 0xf1, 0x1f, 0xa2, 0x8c, 0x0a, 0x01, 0x88, 0x84, 0xa0, 0xde, 0xce, 0x2e, 0xb3, 0x24, 0x2e, 0xd2, 0x28, 0x6d, 0x08, - 0x4d, 0x4f, 0xd8, 0x64, 0x3c, 0x4b, 0x59, 0x7a, 0x3c, 0x79, 0x3a, 0x9b, 0x3c, 0x8d, 0x8e, 0xc6, 0x51, 0x3a, 0x18, - 0x40, 0xf2, 0xd1, 0x18, 0x5c, 0xec, 0xe0, 0x37, 0x3b, 0x82, 0xa1, 0x3b, 0x41, 0x96, 0xb0, 0x84, 0xa6, 0x7d, 0x5e, - 0x93, 0xd4, 0x70, 0x5e, 0xca, 0x9e, 0xc4, 0x77, 0x74, 0xed, 0x38, 0xb8, 0xb8, 0x2d, 0xbc, 0xb4, 0x2d, 0xbc, 0xdc, - 0x6d, 0xa1, 0xb6, 0x20, 0x28, 0xc5, 0xff, 0x8f, 0x1b, 0xc6, 0xbe, 0xbb, 0x84, 0x5e, 0x5c, 0x37, 0xd9, 0x68, 0x55, - 0x8a, 0x5a, 0xc0, 0x6d, 0x42, 0x8a, 0xc2, 0x46, 0xf1, 0x6a, 0x95, 0x2b, 0x17, 0xb1, 0x79, 0x4d, 0x01, 0xdc, 0x05, - 0xce, 0x56, 0x60, 0xa1, 0xb5, 0x81, 0xdc, 0x5f, 0xbc, 0x14, 0xcc, 0xa8, 0x7d, 0xf4, 0x3d, 0xf2, 0x8f, 0x10, 0xc1, - 0x96, 0x4e, 0xc6, 0xb3, 0x0a, 0x11, 0x2d, 0x3e, 0x25, 0xef, 0xfd, 0x37, 0x8e, 0x22, 0x73, 0x34, 0x8f, 0x51, 0xa1, - 0x65, 0x3c, 0xe2, 0xcc, 0xc9, 0xe4, 0x64, 0xe0, 0x6e, 0x06, 0x23, 0xfd, 0xb5, 0xb7, 0x19, 0x63, 0xdb, 0xa3, 0x7a, - 0xa1, 0x85, 0xa2, 0x7f, 0xe1, 0x3b, 0x5d, 0x2f, 0xe0, 0x12, 0xca, 0x81, 0x5d, 0x5f, 0x5d, 0xf1, 0x0a, 0x40, 0x84, - 0xb2, 0xa2, 0xdf, 0xef, 0xfd, 0xa1, 0xa1, 0x49, 0x2b, 0x5e, 0xbe, 0xce, 0x0a, 0xe3, 0x8c, 0x03, 0x4d, 0x05, 0xea, - 0xff, 0xb1, 0x36, 0xcf, 0x74, 0x4c, 0x66, 0xee, 0xe3, 0x70, 0x42, 0x22, 0xff, 0x35, 0xf9, 0xc4, 0x69, 0xfa, 0x89, - 0x2b, 0xda, 0x7f, 0x20, 0x33, 0xd7, 0x1c, 0x32, 0xd4, 0x5f, 0x58, 0xe6, 0x49, 0xeb, 0x75, 0x62, 0x76, 0x52, 0xb1, - 0x7a, 0x06, 0xe8, 0xe9, 0x25, 0x3c, 0xc8, 0x6b, 0x59, 0x3c, 0x85, 0xd9, 0x07, 0x35, 0x62, 0x75, 0xcc, 0xc6, 0xb3, - 0x50, 0x84, 0x13, 0xb0, 0xef, 0x9d, 0x8c, 0xe1, 0x3e, 0x20, 0xc2, 0x8f, 0x75, 0x58, 0x51, 0x94, 0x92, 0x97, 0xf0, - 0x1b, 0x14, 0x13, 0x00, 0x11, 0x08, 0x79, 0xfb, 0x7d, 0x21, 0x93, 0xf0, 0x75, 0x81, 0x29, 0xa5, 0xfc, 0xe0, 0x3f, - 0x91, 0xaa, 0x5b, 0xa6, 0x5f, 0xae, 0x1f, 0x77, 0x26, 0x24, 0x9f, 0x6e, 0x53, 0xe2, 0x3b, 0x08, 0xee, 0x2c, 0x40, - 0x07, 0x51, 0xa3, 0x19, 0xdb, 0xc3, 0xfc, 0x6e, 0xb5, 0x9f, 0xdf, 0xad, 0xfe, 0xdf, 0xf1, 0xbb, 0xd5, 0x43, 0x8c, - 0x61, 0x6d, 0xa0, 0xe1, 0x67, 0xc1, 0x38, 0x88, 0xfe, 0x73, 0x3e, 0x71, 0x2f, 0x4f, 0x7d, 0x9d, 0x15, 0xd3, 0x3d, - 0x4c, 0xb3, 0x4b, 0x50, 0x10, 0x56, 0x71, 0x97, 0x9e, 0xac, 0x6b, 0x73, 0x6b, 0x25, 0x43, 0xcc, 0xf3, 0x00, 0x6b, - 0x14, 0xd6, 0x0e, 0xd0, 0x3d, 0xaa, 0x36, 0x88, 0x15, 0xc1, 0xc3, 0x98, 0x19, 0xe9, 0xfb, 0x76, 0xab, 0x55, 0x98, - 0x0f, 0x72, 0x51, 0x90, 0x5d, 0x7f, 0x3c, 0x1b, 0x47, 0x21, 0x36, 0xe0, 0x3f, 0x66, 0xac, 0x3c, 0xd9, 0x7c, 0x27, - 0x23, 0xb5, 0x63, 0xf2, 0x34, 0xd9, 0x25, 0xbd, 0x03, 0xde, 0x21, 0x3f, 0x6f, 0x3e, 0x86, 0xa5, 0xd0, 0xfc, 0x96, - 0xb8, 0x8a, 0xcb, 0xac, 0x5e, 0x5e, 0x67, 0x09, 0x32, 0x5d, 0xf0, 0xe2, 0xb3, 0x99, 0x2e, 0xe7, 0x63, 0x75, 0xc0, - 0x38, 0x4a, 0xf1, 0xc6, 0x13, 0xa5, 0xa7, 0x2d, 0xcf, 0x0a, 0x79, 0x79, 0x92, 0x31, 0xdb, 0xb3, 0x0a, 0x9c, 0x4e, - 0xc1, 0x04, 0x5f, 0xfd, 0xb4, 0xbd, 0x8f, 0x01, 0x17, 0x14, 0x6a, 0x4e, 0x4b, 0xb1, 0xd2, 0x58, 0x4e, 0x06, 0xba, - 0x13, 0x30, 0x43, 0x45, 0x81, 0x17, 0x28, 0xf8, 0x8b, 0x06, 0x46, 0xf4, 0xa5, 0xfd, 0x4d, 0x06, 0x1a, 0xe9, 0x52, - 0x9f, 0x08, 0x63, 0xcb, 0xed, 0x94, 0x69, 0x2b, 0xca, 0x19, 0x67, 0xef, 0xe5, 0x95, 0x02, 0x0c, 0xf0, 0x36, 0xb7, - 0xd1, 0x45, 0x82, 0x5e, 0x0b, 0x52, 0xe7, 0x0d, 0xdc, 0xcd, 0x32, 0xd2, 0xc2, 0xc5, 0xc7, 0xb5, 0xc3, 0x82, 0x3b, - 0xf6, 0x0b, 0xb1, 0xd0, 0x9a, 0x69, 0x30, 0x66, 0x73, 0x82, 0x05, 0x56, 0x32, 0x50, 0x60, 0x31, 0x53, 0x96, 0xa6, - 0xf5, 0x90, 0x1f, 0x1e, 0xa1, 0xb5, 0x69, 0x3d, 0xe0, 0x87, 0x47, 0x4d, 0x94, 0x1d, 0x43, 0x96, 0x13, 0x37, 0x83, - 0x7c, 0xdd, 0x44, 0x3a, 0x45, 0x67, 0x77, 0xeb, 0x4b, 0xdd, 0x51, 0xdd, 0x80, 0xeb, 0x07, 0x20, 0x80, 0x0d, 0xc0, - 0x21, 0x50, 0x0e, 0x96, 0x42, 0x04, 0x8b, 0x32, 0x89, 0xf6, 0x35, 0x74, 0xde, 0x28, 0xf8, 0x2f, 0x70, 0x17, 0x11, - 0x2b, 0xf7, 0x13, 0x04, 0xfe, 0x8a, 0x32, 0xa5, 0x4c, 0x71, 0x3f, 0x51, 0xea, 0x15, 0xca, 0x99, 0x6f, 0xcd, 0x07, - 0xd1, 0x9a, 0x08, 0x55, 0x8c, 0x21, 0xf8, 0xb7, 0xb2, 0x4c, 0x59, 0xaa, 0x4a, 0xf5, 0xa1, 0xf6, 0x5a, 0x2b, 0xad, - 0xe5, 0xe3, 0xc8, 0x79, 0x8d, 0xa1, 0x63, 0x13, 0x6b, 0x29, 0x27, 0x53, 0x67, 0x6f, 0x0e, 0x45, 0x64, 0x01, 0xa7, - 0x13, 0x36, 0x9e, 0x26, 0xc7, 0x62, 0x9a, 0x58, 0xc8, 0xfc, 0x9c, 0x61, 0x64, 0x55, 0x0d, 0xc2, 0x22, 0x6d, 0x28, - 0x4d, 0x01, 0x3a, 0x39, 0x21, 0x64, 0x8a, 0xa1, 0x28, 0xf2, 0x91, 0xea, 0x87, 0xf1, 0x66, 0xb5, 0x5f, 0xbc, 0x53, - 0x00, 0xa7, 0x61, 0x02, 0x81, 0xc0, 0xcb, 0xf8, 0x36, 0x2b, 0xae, 0xc0, 0x63, 0x78, 0x00, 0x5f, 0x82, 0x9b, 0x5c, - 0xca, 0x7e, 0xab, 0xc3, 0x1c, 0xd7, 0x16, 0x30, 0x68, 0xb0, 0x7a, 0x10, 0x1d, 0x2e, 0xa5, 0x7e, 0x57, 0x01, 0x62, - 0x63, 0x0a, 0xff, 0xb3, 0xb5, 0x61, 0xcf, 0xbe, 0x97, 0x4d, 0x43, 0xeb, 0x84, 0xd3, 0xe2, 0x2a, 0x87, 0x28, 0x2a, - 0x83, 0x18, 0xdc, 0x91, 0x1c, 0x3e, 0xef, 0x5d, 0x15, 0x5e, 0x12, 0x70, 0x2b, 0x8b, 0x45, 0xb8, 0xa2, 0xcb, 0xd1, - 0x1d, 0x5d, 0x8f, 0x6e, 0xe9, 0x98, 0x4e, 0xbe, 0x19, 0x83, 0x45, 0xb6, 0x4a, 0xbd, 0xa7, 0xeb, 0xd1, 0x92, 0x7e, - 0x3b, 0xa6, 0x47, 0x7f, 0x03, 0x13, 0x3e, 0x3c, 0x4c, 0xe8, 0x25, 0x38, 0x76, 0x91, 0x06, 0x3d, 0x35, 0x5d, 0x83, - 0xc3, 0x7a, 0x94, 0x0f, 0xf9, 0x28, 0xa7, 0x7c, 0x54, 0x0e, 0xeb, 0x11, 0x78, 0x3a, 0xd6, 0x43, 0x3e, 0xaa, 0x29, - 0x1f, 0x5d, 0x0c, 0xeb, 0xd1, 0x05, 0xf1, 0x9b, 0xfe, 0xaa, 0xe6, 0xd7, 0x15, 0x4b, 0x61, 0x5b, 0xc0, 0xf2, 0xb5, - 0xab, 0x2c, 0x49, 0xdd, 0x55, 0xad, 0x4f, 0x66, 0xc3, 0xd9, 0x9b, 0xeb, 0x2e, 0x27, 0x06, 0x8f, 0xdb, 0xa4, 0xc3, - 0xd5, 0x97, 0x13, 0x79, 0xd2, 0x4b, 0xe4, 0x87, 0xf1, 0x54, 0x9d, 0x43, 0x60, 0x26, 0x31, 0x0b, 0x63, 0x86, 0xcd, - 0x54, 0x69, 0xa0, 0xc0, 0xc9, 0x46, 0x8e, 0x8b, 0x62, 0x36, 0xca, 0x29, 0xbc, 0x8f, 0x09, 0x89, 0xf0, 0xac, 0x3a, - 0xa9, 0x47, 0x25, 0xc4, 0x1c, 0x61, 0x21, 0x3e, 0x42, 0xbf, 0xe4, 0x47, 0x0e, 0x12, 0x78, 0x86, 0x7d, 0x2d, 0x07, - 0x31, 0x1c, 0xf1, 0xa6, 0xb2, 0x7a, 0x16, 0x26, 0x50, 0x59, 0x3d, 0x2c, 0x74, 0x65, 0x25, 0xcd, 0x46, 0xb5, 0x5b, - 0x59, 0x8d, 0x63, 0x94, 0x10, 0x12, 0x15, 0xaa, 0x32, 0x50, 0x9f, 0x24, 0x2c, 0x2c, 0x54, 0x65, 0x17, 0xf2, 0xa3, - 0x0b, 0xb7, 0xb2, 0x0b, 0x70, 0x21, 0x1d, 0x24, 0xee, 0x55, 0x2a, 0x4f, 0xdb, 0xd7, 0x41, 0x6f, 0x55, 0xd1, 0x0d, - 0xbf, 0xab, 0xcb, 0x38, 0x2a, 0xa8, 0x8d, 0x01, 0x8d, 0x0b, 0x23, 0x12, 0x54, 0xad, 0x51, 0xf0, 0x87, 0x04, 0x51, - 0x69, 0x0c, 0x5e, 0x9d, 0x49, 0xd7, 0x4a, 0xad, 0x69, 0x35, 0x28, 0x06, 0x25, 0xdc, 0x9f, 0xf2, 0xd6, 0x42, 0xfa, - 0x1e, 0x22, 0x2a, 0x43, 0x79, 0x83, 0x7f, 0x60, 0xf0, 0x64, 0xb6, 0x4a, 0xc3, 0x64, 0x74, 0x4f, 0xe3, 0xd1, 0x12, - 0xe1, 0x60, 0xd8, 0x3a, 0x95, 0x78, 0xeb, 0x97, 0x90, 0x7e, 0x47, 0xe3, 0xd1, 0x2d, 0x4d, 0x8d, 0xcd, 0xa9, 0x86, - 0xba, 0xea, 0x8d, 0xe9, 0x5d, 0x04, 0xaf, 0xef, 0xa3, 0x25, 0x85, 0xad, 0x74, 0x9a, 0x67, 0x57, 0x45, 0x94, 0x52, - 0x44, 0x20, 0x5c, 0x23, 0x72, 0xe0, 0x52, 0xa1, 0x0d, 0xae, 0x07, 0x50, 0x86, 0x82, 0x0b, 0x5c, 0x0e, 0xe2, 0xd1, - 0xd2, 0x21, 0x53, 0x4b, 0x75, 0x91, 0x45, 0xf8, 0x68, 0x6b, 0xa3, 0x25, 0x79, 0x46, 0x2c, 0x8c, 0x4b, 0x18, 0x42, - 0x55, 0x58, 0xa1, 0x0b, 0x12, 0x36, 0x70, 0x64, 0x2f, 0x2c, 0xeb, 0x70, 0x03, 0xa6, 0x45, 0xf7, 0x60, 0x1e, 0x05, - 0x0a, 0x07, 0x9b, 0x20, 0xdc, 0x84, 0xa2, 0x9d, 0xa3, 0xd0, 0x39, 0x9c, 0x09, 0x4a, 0x77, 0x26, 0x08, 0x69, 0x57, - 0x37, 0xd9, 0x12, 0xae, 0xc1, 0xf6, 0x0e, 0x9d, 0x8a, 0x4a, 0xaa, 0xce, 0x2d, 0x98, 0x2c, 0xe1, 0x11, 0xb6, 0x84, - 0xa9, 0x99, 0x4e, 0xe1, 0x06, 0x7c, 0x78, 0xb4, 0x33, 0xdf, 0xe5, 0xec, 0xcd, 0x21, 0xd8, 0x76, 0x4a, 0x1f, 0x10, - 0x43, 0xec, 0x96, 0x6c, 0x3c, 0x5d, 0x1e, 0x17, 0xd3, 0x25, 0x12, 0x3b, 0x4d, 0xb7, 0x18, 0x9f, 0x2f, 0x17, 0x34, - 0xc1, 0xb3, 0x8d, 0xd5, 0xf3, 0xa5, 0x46, 0x4b, 0x49, 0x19, 0xae, 0xb7, 0x25, 0xfa, 0xff, 0xcb, 0x8b, 0x5f, 0x0a, - 0xf0, 0x12, 0x8c, 0x05, 0x80, 0x70, 0x0f, 0xa6, 0x05, 0xa9, 0x89, 0xb2, 0xb1, 0x4c, 0xc3, 0x14, 0x17, 0x81, 0x4e, - 0xe9, 0xf7, 0xc3, 0x9c, 0xa5, 0xc4, 0x81, 0x0e, 0x35, 0xa3, 0xb4, 0x4e, 0x5d, 0x21, 0x08, 0xf0, 0x48, 0xf2, 0x1c, - 0x9b, 0x7c, 0x33, 0x9e, 0x05, 0x72, 0x20, 0x82, 0x28, 0x3b, 0xc6, 0x47, 0x0c, 0x5c, 0x14, 0xa9, 0xb8, 0x9d, 0xb6, - 0x88, 0xcb, 0xdd, 0x63, 0x16, 0xe2, 0x24, 0x61, 0xae, 0x59, 0x36, 0x64, 0x75, 0x84, 0x09, 0xaa, 0x30, 0x30, 0xcb, - 0x1b, 0xb2, 0xfa, 0xf0, 0x08, 0x22, 0xb5, 0x9a, 0x32, 0x56, 0x5d, 0x65, 0x7c, 0x0b, 0x40, 0xd6, 0x8c, 0xb1, 0xa3, - 0xbf, 0x8d, 0x67, 0xf2, 0x9b, 0x28, 0xe4, 0x27, 0x47, 0x7f, 0x83, 0xe4, 0xe3, 0x6f, 0x91, 0x99, 0x83, 0x64, 0xaf, - 0xa0, 0x2b, 0x7f, 0xd6, 0x15, 0x94, 0x26, 0xae, 0xbd, 0x42, 0xad, 0x3d, 0xa1, 0xd7, 0x5e, 0x89, 0xee, 0xd4, 0x9a, - 0xf7, 0x90, 0xb6, 0xb3, 0x60, 0x82, 0x8e, 0x66, 0x77, 0xa0, 0x83, 0xb7, 0x8a, 0xa0, 0x17, 0x49, 0xa8, 0x3d, 0x42, - 0xa5, 0x51, 0x2f, 0xec, 0xc8, 0x6e, 0xd6, 0x25, 0x73, 0x0c, 0x98, 0x63, 0x73, 0x0e, 0x55, 0xc3, 0x5c, 0x1e, 0xd4, - 0x29, 0x2b, 0x86, 0x39, 0x1e, 0xc0, 0x6b, 0x26, 0x86, 0xd5, 0x20, 0x57, 0x28, 0xdf, 0x97, 0xac, 0x1c, 0x16, 0x83, - 0x5c, 0x71, 0x33, 0x53, 0x3f, 0x36, 0x6d, 0xa2, 0xc2, 0x33, 0xaf, 0xd8, 0xc9, 0xaa, 0x07, 0x7c, 0x2c, 0x78, 0x32, - 0xbb, 0x9e, 0x8f, 0xaf, 0x81, 0x93, 0xd9, 0xdc, 0x45, 0x4b, 0x7a, 0x1f, 0xa5, 0xf4, 0x36, 0x5a, 0xd3, 0x65, 0x74, - 0xa9, 0x4d, 0x8c, 0x93, 0x06, 0xce, 0x01, 0x68, 0x15, 0x40, 0xe2, 0xc9, 0x5f, 0xef, 0x79, 0x52, 0x87, 0x4b, 0x9a, - 0x82, 0xdb, 0xb0, 0x6b, 0x9f, 0x79, 0xed, 0x4a, 0xa4, 0x36, 0x88, 0xb1, 0x66, 0x0c, 0x15, 0x37, 0xce, 0xba, 0x8f, - 0xaa, 0x06, 0x76, 0xae, 0x8d, 0x4d, 0x54, 0x0f, 0x27, 0xd3, 0x02, 0x10, 0x5b, 0x8b, 0xe1, 0xd0, 0x1e, 0x21, 0xbb, - 0xc7, 0x8f, 0x0a, 0xf4, 0xdc, 0x13, 0x06, 0xdb, 0xb6, 0xe5, 0x0f, 0x0c, 0x61, 0x4a, 0x3f, 0x7d, 0xe4, 0x17, 0x84, - 0x4c, 0xaf, 0xe0, 0x6c, 0x04, 0xea, 0x68, 0x84, 0x4e, 0xbf, 0xd5, 0x61, 0xa9, 0x0e, 0xf0, 0xcd, 0x5d, 0x94, 0xd0, - 0xfb, 0x28, 0x77, 0xc8, 0xda, 0xb2, 0x61, 0x62, 0x7a, 0x9e, 0x85, 0xbc, 0x7d, 0xa0, 0x17, 0x0b, 0x00, 0xd1, 0x1a, - 0xc4, 0xae, 0xd4, 0xf5, 0x08, 0x9c, 0x86, 0xd0, 0x24, 0x34, 0x82, 0xab, 0x0a, 0xc2, 0x08, 0xd8, 0x92, 0xf0, 0x37, - 0x98, 0xa8, 0xc0, 0x17, 0xe0, 0x22, 0x93, 0xa6, 0x39, 0x0f, 0x1a, 0x77, 0x24, 0xcf, 0xca, 0xb6, 0xb7, 0x2b, 0x8c, - 0x26, 0x18, 0x7b, 0xa2, 0x7d, 0x1e, 0x29, 0x46, 0x71, 0x99, 0x84, 0xd9, 0xe8, 0x4e, 0x9e, 0xe7, 0x34, 0x1b, 0xdd, - 0xab, 0x5f, 0x35, 0x1d, 0xd3, 0xef, 0x54, 0x40, 0x1b, 0x29, 0x7d, 0xeb, 0x38, 0x1b, 0xd0, 0x7a, 0xb1, 0xd0, 0xfe, - 0xd7, 0x62, 0x74, 0x47, 0xc5, 0xe8, 0xde, 0xb5, 0xa4, 0x9a, 0x4c, 0xcb, 0xe3, 0x0a, 0x0d, 0xa9, 0x3a, 0xbf, 0x2f, - 0x81, 0x9f, 0x2b, 0xb4, 0xef, 0xb4, 0xfe, 0xde, 0x69, 0xff, 0x45, 0x27, 0x4f, 0x20, 0x59, 0xa2, 0x92, 0xd5, 0x23, - 0xb0, 0x63, 0x5f, 0xe7, 0x71, 0xa9, 0x47, 0x29, 0xa6, 0xc6, 0xa4, 0x1f, 0x03, 0x57, 0x4c, 0x7b, 0x25, 0xb8, 0x5a, - 0x6e, 0xb7, 0x32, 0x86, 0x26, 0xec, 0xd9, 0x31, 0x44, 0x3d, 0xd7, 0x8e, 0x51, 0xc2, 0x73, 0x0f, 0x88, 0x95, 0xcc, - 0x5b, 0xba, 0x04, 0x24, 0xf0, 0xd6, 0xc1, 0xa4, 0x28, 0x46, 0x29, 0xc0, 0x4f, 0xa8, 0x3c, 0x0e, 0xfa, 0x84, 0x7c, - 0xa1, 0x50, 0x27, 0x84, 0xb7, 0x25, 0x70, 0xfc, 0x61, 0x7d, 0x54, 0x08, 0x5e, 0xe5, 0xb8, 0xfe, 0x0a, 0xe3, 0xfa, - 0x4b, 0x85, 0xe3, 0x8e, 0x65, 0xbb, 0x7e, 0xde, 0xa6, 0x46, 0x2f, 0xc1, 0xc2, 0x77, 0x23, 0xcd, 0x23, 0xb9, 0x41, - 0x48, 0x95, 0x60, 0xa5, 0x76, 0x21, 0xc1, 0xfc, 0x4b, 0x39, 0x5b, 0x9d, 0xb9, 0xea, 0x91, 0x07, 0xe5, 0x6c, 0x6a, - 0xfa, 0x3d, 0x09, 0xda, 0x7d, 0x47, 0x9a, 0xc3, 0x5b, 0x74, 0xf8, 0xec, 0x1a, 0x4b, 0xcc, 0x9d, 0x44, 0xc9, 0xf3, - 0x49, 0x60, 0xab, 0xe7, 0xd9, 0xb5, 0xf4, 0xb1, 0xda, 0xc5, 0xf1, 0xd3, 0xe7, 0x4f, 0x5c, 0x87, 0x69, 0xe5, 0x29, - 0x41, 0xc0, 0x9b, 0x43, 0xdb, 0x15, 0xca, 0x80, 0x86, 0xfa, 0x06, 0x8e, 0x73, 0x35, 0xac, 0x15, 0x01, 0x53, 0x52, - 0x1e, 0x15, 0xe0, 0x50, 0xe7, 0x91, 0xbb, 0x69, 0x58, 0x6b, 0xba, 0xe6, 0xf5, 0xb9, 0xad, 0x74, 0xc6, 0x9b, 0x0d, - 0x3f, 0x3c, 0x1a, 0xd4, 0xf8, 0x93, 0xf8, 0xa3, 0xd1, 0xce, 0x0d, 0x77, 0x9a, 0x0a, 0x33, 0xd7, 0x62, 0x45, 0x76, - 0x47, 0xc9, 0xc9, 0xef, 0xe8, 0x85, 0xb1, 0x3f, 0xff, 0xb9, 0x98, 0x70, 0xd2, 0x12, 0x13, 0xa2, 0xa5, 0x83, 0x12, - 0x1d, 0xec, 0x28, 0xaf, 0xcc, 0x4b, 0xbc, 0x74, 0x8e, 0xff, 0x7d, 0x3d, 0xd6, 0xae, 0x02, 0xa1, 0xd5, 0xc9, 0xc3, - 0xf6, 0x64, 0x81, 0xa8, 0x01, 0xd5, 0xec, 0xb2, 0x1c, 0x69, 0xda, 0x59, 0x93, 0x8d, 0x27, 0x73, 0xdd, 0xcd, 0xe2, - 0xd9, 0x4c, 0x76, 0x2c, 0x2c, 0x3d, 0x0c, 0xc6, 0x4e, 0x15, 0x7d, 0x0e, 0x5a, 0x7e, 0x04, 0xcf, 0x7d, 0xe5, 0x99, - 0xcb, 0x66, 0x69, 0xf1, 0x02, 0x9d, 0x73, 0xaa, 0x21, 0x87, 0x1c, 0x80, 0xe3, 0x02, 0x8d, 0x25, 0x8a, 0x28, 0x08, - 0x1a, 0x13, 0x84, 0x5d, 0x95, 0xee, 0x48, 0x9f, 0x76, 0xf1, 0x69, 0x2b, 0xf4, 0x3d, 0xde, 0x67, 0x20, 0x31, 0x75, - 0x24, 0x0f, 0xb5, 0xd7, 0x1c, 0x95, 0x3c, 0x8b, 0x53, 0x85, 0xcf, 0x2f, 0x65, 0x67, 0xfe, 0xdd, 0x6a, 0x4c, 0xf1, - 0x1f, 0x69, 0xda, 0x77, 0x2e, 0x4d, 0x13, 0xdd, 0xb5, 0x3c, 0x68, 0x29, 0x2c, 0x38, 0x6e, 0x1b, 0x77, 0xfd, 0xfa, - 0x39, 0xaa, 0x61, 0x61, 0x73, 0x38, 0x13, 0x3a, 0xb4, 0x77, 0x95, 0x9d, 0xb9, 0x3e, 0xa2, 0x56, 0x5d, 0xac, 0xda, - 0x80, 0x92, 0x25, 0xe7, 0xd6, 0xe9, 0x88, 0x95, 0xbe, 0x3b, 0x0c, 0x77, 0xe6, 0x51, 0xb1, 0xbb, 0xdb, 0xed, 0x84, - 0xb4, 0xed, 0x83, 0xf1, 0xbe, 0x84, 0x85, 0x58, 0xef, 0xb0, 0x83, 0xef, 0xc3, 0xfa, 0x31, 0x1f, 0xfc, 0x1c, 0xca, - 0x75, 0x55, 0x3f, 0xcf, 0xa4, 0xa1, 0xcf, 0xcb, 0x52, 0x5c, 0xcb, 0x4e, 0xb9, 0x42, 0xb7, 0x96, 0xa9, 0xf7, 0x9b, - 0xf8, 0x4d, 0x2b, 0x40, 0x8c, 0xd3, 0x15, 0x23, 0xc5, 0x1b, 0x1a, 0x61, 0x9c, 0x87, 0xdb, 0x64, 0x51, 0x4b, 0x95, - 0x40, 0xd4, 0xe6, 0x27, 0x8f, 0x79, 0xa4, 0xd5, 0x99, 0xf0, 0xdd, 0x63, 0xee, 0x4a, 0xd7, 0x76, 0x9b, 0xf8, 0xa9, - 0xa6, 0x1d, 0xee, 0x0e, 0x74, 0x47, 0xeb, 0x1e, 0x6e, 0x9e, 0xc9, 0xcf, 0x23, 0xfd, 0xc5, 0x00, 0x9b, 0xb5, 0xcb, - 0xb8, 0xec, 0x18, 0xee, 0x3b, 0xd3, 0x83, 0xb1, 0x80, 0x40, 0x62, 0x86, 0x5e, 0x06, 0x36, 0x70, 0x81, 0xbd, 0xc2, - 0x80, 0x21, 0xae, 0x6e, 0xc9, 0xb9, 0xb2, 0xb2, 0x75, 0x91, 0xb7, 0x51, 0x21, 0xd8, 0x34, 0x1d, 0x37, 0x49, 0x0e, - 0xc1, 0x09, 0x5b, 0xee, 0x7d, 0xed, 0xb5, 0x33, 0xfc, 0xc7, 0xa0, 0xb2, 0x6e, 0x89, 0x8e, 0x51, 0xdb, 0x63, 0xa5, - 0xee, 0xd5, 0xbc, 0xca, 0x7d, 0xe4, 0x58, 0xbf, 0xe9, 0x97, 0x9a, 0x7d, 0xc1, 0x6b, 0x29, 0x38, 0x34, 0xb6, 0x5b, - 0x61, 0x17, 0x8b, 0x73, 0xb4, 0x1a, 0x59, 0x6b, 0xab, 0xbd, 0x46, 0x2a, 0xba, 0x7f, 0xcd, 0x71, 0x62, 0x2d, 0x85, - 0xcd, 0x87, 0x0f, 0x17, 0x6c, 0x9b, 0x00, 0x06, 0x2d, 0x3a, 0x0b, 0x94, 0x20, 0x93, 0x95, 0xaa, 0xdd, 0x4c, 0x89, - 0x5b, 0xee, 0x67, 0x5d, 0x66, 0x3b, 0x8f, 0x5f, 0x3b, 0x69, 0x9f, 0xf8, 0x1c, 0xfd, 0x30, 0xbf, 0x33, 0x4e, 0x4a, - 0xd6, 0x30, 0xae, 0xe5, 0xff, 0x57, 0xd3, 0xab, 0x32, 0x4b, 0xa3, 0x8d, 0xe6, 0xc1, 0x4c, 0xa8, 0x4d, 0x17, 0x1a, - 0xa3, 0xb6, 0xcb, 0x46, 0x12, 0xd1, 0xfa, 0x0e, 0x04, 0x33, 0x92, 0xfb, 0xaa, 0xda, 0xbc, 0x52, 0x6d, 0xe0, 0x1d, - 0x3e, 0xb1, 0xd1, 0x3d, 0xdb, 0x13, 0x42, 0xf9, 0xee, 0x69, 0xa1, 0x57, 0x2d, 0xad, 0x3c, 0xb6, 0xab, 0x72, 0x2e, - 0x46, 0xb5, 0x7a, 0xc2, 0x64, 0xc3, 0x82, 0xc9, 0xfe, 0x7f, 0x5f, 0x66, 0x69, 0x9b, 0xa2, 0x03, 0xd3, 0xe9, 0xfb, - 0x74, 0xd2, 0x0d, 0xae, 0x33, 0x60, 0x11, 0xc1, 0x96, 0x0a, 0xc7, 0xa3, 0x50, 0x6e, 0x90, 0x30, 0x11, 0x5c, 0x47, - 0xbd, 0xec, 0x68, 0x99, 0x94, 0x55, 0x01, 0xcf, 0x2f, 0x5d, 0x65, 0x3a, 0x8e, 0x86, 0x7e, 0xff, 0x3a, 0xd5, 0xa1, - 0x5f, 0x69, 0xe1, 0x9c, 0x23, 0xcb, 0xcc, 0x51, 0x75, 0xc8, 0x30, 0x46, 0x4b, 0x9a, 0xc2, 0x31, 0x98, 0x5d, 0x86, - 0x29, 0x5e, 0xce, 0x36, 0x09, 0xfb, 0x8c, 0x81, 0x5c, 0x2a, 0x83, 0x7a, 0x45, 0x89, 0xd6, 0xac, 0xbd, 0x99, 0x53, - 0x42, 0x2f, 0x59, 0xe1, 0xde, 0x85, 0xd6, 0x20, 0x50, 0x14, 0x7e, 0xca, 0xf4, 0x42, 0xb5, 0xf3, 0x92, 0x26, 0xb4, - 0xa4, 0x2b, 0xd2, 0x80, 0xbe, 0xd7, 0xca, 0xd9, 0xd1, 0xc9, 0x4e, 0xcf, 0x7a, 0xcc, 0xca, 0xe1, 0x64, 0x1a, 0xc3, - 0x35, 0x2d, 0xb6, 0xd7, 0xb4, 0xa5, 0x7f, 0xe3, 0xf2, 0x36, 0x8e, 0x47, 0xbb, 0x40, 0xda, 0xa6, 0xb8, 0xfd, 0xd4, - 0xe1, 0xf6, 0xd7, 0x0d, 0x5b, 0x4e, 0x7b, 0xeb, 0xed, 0xb6, 0x97, 0x82, 0x8d, 0xa8, 0xc3, 0xc7, 0xaf, 0xa5, 0x74, - 0xdd, 0x70, 0xf9, 0x29, 0x3c, 0x3b, 0x7c, 0xfd, 0xd2, 0x05, 0x97, 0xa3, 0x75, 0x9b, 0xbb, 0x5f, 0xee, 0x22, 0xcb, - 0x7d, 0xd6, 0xd0, 0x72, 0x35, 0x43, 0x3e, 0x79, 0xd6, 0xda, 0x3b, 0xd4, 0x82, 0xe5, 0xac, 0x9b, 0xf0, 0xc4, 0x60, - 0xc7, 0x5e, 0x7b, 0x9b, 0xa3, 0xd6, 0x97, 0x2c, 0x8f, 0x04, 0xba, 0x24, 0x4f, 0x37, 0xfd, 0x83, 0x08, 0xf3, 0xd1, - 0x1d, 0xcd, 0x01, 0x57, 0xac, 0x36, 0x97, 0x0c, 0xd2, 0xd4, 0xed, 0x25, 0x2e, 0x7d, 0x85, 0x43, 0xb2, 0xc1, 0x27, - 0xcd, 0x54, 0x7d, 0x72, 0xc9, 0x83, 0xff, 0xb7, 0x51, 0xab, 0xf4, 0xec, 0x24, 0x7b, 0x8e, 0x7f, 0x9d, 0xb4, 0x7d, - 0x4c, 0x34, 0x12, 0xf0, 0xd4, 0x2c, 0x86, 0x7a, 0x54, 0x97, 0x71, 0x51, 0xe5, 0x3a, 0xe6, 0xd8, 0xde, 0xae, 0xa1, - 0x83, 0x32, 0xf8, 0x75, 0xc3, 0x27, 0xfa, 0x0e, 0x6c, 0x04, 0x3a, 0x2a, 0x51, 0x5f, 0x86, 0x99, 0xbe, 0x0c, 0xd3, - 0xae, 0xad, 0x02, 0xc3, 0x2b, 0xb7, 0x4a, 0x22, 0x5d, 0x8d, 0x7a, 0x5c, 0xcf, 0x92, 0xdf, 0x8b, 0xbc, 0x7b, 0x4d, - 0x3a, 0x12, 0x7f, 0xba, 0x74, 0xe4, 0xf5, 0x30, 0x20, 0xe2, 0x73, 0x96, 0x86, 0x6d, 0x14, 0x04, 0xa7, 0x96, 0x3b, - 0x90, 0xe6, 0x23, 0x40, 0xe6, 0xc7, 0x69, 0xf8, 0x4e, 0x89, 0x73, 0xc8, 0x46, 0x6a, 0x9c, 0xd8, 0x52, 0xab, 0x87, - 0xe0, 0xce, 0x7b, 0xcd, 0x63, 0x08, 0x7c, 0xf8, 0x01, 0x37, 0x83, 0x8c, 0x6e, 0x4b, 0x74, 0x94, 0x36, 0x87, 0xba, - 0xe5, 0x23, 0x4f, 0xa8, 0x64, 0x64, 0x78, 0x31, 0xb4, 0x77, 0x47, 0x60, 0x54, 0x5b, 0x81, 0xcc, 0xb0, 0x3c, 0x3c, - 0x1a, 0xa6, 0x52, 0x50, 0x34, 0x14, 0xc3, 0x25, 0xca, 0x01, 0x31, 0x09, 0x04, 0x46, 0xe5, 0x20, 0x55, 0x95, 0xc9, - 0x17, 0x83, 0x54, 0xdd, 0xaa, 0x48, 0x73, 0x9e, 0x85, 0x35, 0x55, 0x2d, 0xa2, 0x63, 0x3a, 0x14, 0x74, 0xa9, 0x77, - 0x6a, 0xae, 0xa4, 0x17, 0x72, 0x39, 0x3e, 0x53, 0x69, 0x30, 0x8a, 0x67, 0x36, 0x45, 0xbd, 0x95, 0xfb, 0xd9, 0x7d, - 0x8b, 0x29, 0x0d, 0x62, 0x53, 0x3b, 0x8b, 0x18, 0x56, 0xed, 0x87, 0xac, 0xce, 0x41, 0xbb, 0x0b, 0xca, 0xc6, 0x5a, - 0x3b, 0xcf, 0x7b, 0xc1, 0xcc, 0x41, 0xdb, 0x58, 0xfb, 0x3e, 0xf4, 0x5a, 0x8c, 0xda, 0x1b, 0x53, 0x85, 0x7b, 0x02, - 0x3f, 0x4d, 0xd0, 0x74, 0x27, 0xf2, 0x1c, 0x75, 0xc8, 0xbb, 0xfb, 0x99, 0x25, 0x3b, 0x93, 0x4f, 0x62, 0x99, 0x34, - 0xed, 0x63, 0x12, 0xa3, 0x96, 0x18, 0x46, 0x17, 0x6e, 0x64, 0x52, 0xfb, 0xb9, 0x33, 0xfd, 0x88, 0x67, 0xf2, 0xb0, - 0x1d, 0x1a, 0x75, 0xa5, 0x61, 0x2d, 0x29, 0xa2, 0xba, 0xa0, 0xb7, 0xa6, 0x3a, 0x3a, 0xa2, 0x4e, 0x47, 0x60, 0x75, - 0x45, 0x1b, 0xd4, 0x00, 0x4c, 0xc6, 0x8d, 0xa9, 0xcd, 0xe5, 0x60, 0x1a, 0xa3, 0x2a, 0x78, 0x4a, 0x77, 0x85, 0xd2, - 0xbd, 0x49, 0xd3, 0xb4, 0x86, 0xd8, 0x00, 0x06, 0x04, 0x76, 0xf4, 0xe4, 0xf4, 0x07, 0x3e, 0x2a, 0x00, 0x0d, 0xbc, - 0xdb, 0x99, 0xca, 0x91, 0xa8, 0x77, 0x72, 0xd3, 0xfa, 0xa9, 0x4e, 0x55, 0x2e, 0x80, 0x8a, 0x3b, 0x4b, 0xe7, 0x97, - 0x7a, 0xc4, 0x02, 0x18, 0xf7, 0xc0, 0x9a, 0xea, 0x9d, 0x66, 0x60, 0x3d, 0x91, 0xe7, 0x59, 0xc5, 0x13, 0x51, 0xc0, - 0x8c, 0x88, 0xeb, 0x6b, 0x51, 0xc0, 0x30, 0xc8, 0x01, 0x40, 0x8b, 0xe6, 0x2a, 0x9a, 0xf0, 0xaf, 0x1a, 0xba, 0x2f, - 0x0f, 0xff, 0x4a, 0xe5, 0xfa, 0x7a, 0xdc, 0x80, 0xa1, 0xf2, 0xba, 0xe6, 0x3b, 0x99, 0xbe, 0xe6, 0x4f, 0x9c, 0x4c, - 0x4b, 0xb1, 0x2e, 0x77, 0xb2, 0x7c, 0xf5, 0x35, 0x7f, 0xaa, 0xf2, 0x1c, 0x3d, 0x69, 0x68, 0x1a, 0xdf, 0xef, 0x64, - 0xf9, 0xe6, 0xeb, 0x27, 0x26, 0xcf, 0x57, 0xe3, 0x86, 0xde, 0x72, 0xfe, 0xd1, 0x66, 0x9a, 0xa8, 0xaa, 0xc6, 0x4f, - 0xbe, 0x31, 0xb9, 0x9e, 0x34, 0xf4, 0x5a, 0x14, 0xf5, 0x72, 0xa7, 0xa8, 0xa3, 0xaf, 0x8f, 0xbe, 0xe1, 0x5f, 0xeb, - 0xee, 0x1d, 0x35, 0xf4, 0xcf, 0x75, 0x5c, 0xd6, 0xbc, 0xdc, 0x29, 0xee, 0x6f, 0xdf, 0x7c, 0xf3, 0xc4, 0x64, 0x7c, - 0xd2, 0xd0, 0x7b, 0x1e, 0x77, 0xb4, 0x7d, 0xf2, 0xf4, 0x09, 0xff, 0x5b, 0xd3, 0xd0, 0x5f, 0x98, 0x1b, 0x1c, 0xf5, - 0x34, 0x73, 0xf4, 0xf0, 0x89, 0xf0, 0x51, 0x03, 0x86, 0x0e, 0x1a, 0x40, 0x2e, 0x8c, 0x9a, 0x66, 0x8f, 0x57, 0x2e, - 0xb8, 0x7d, 0x9f, 0xc7, 0x69, 0xbc, 0x82, 0x83, 0x60, 0x83, 0xc6, 0x59, 0x25, 0x70, 0xaa, 0xc0, 0x7b, 0x46, 0x05, - 0xcd, 0x2a, 0xf1, 0x0f, 0xce, 0x3f, 0xc2, 0xa0, 0x21, 0xa4, 0x8d, 0x8c, 0x0c, 0xf4, 0x76, 0xa5, 0x22, 0x1b, 0xa1, - 0xff, 0xa6, 0x1f, 0x07, 0xc7, 0x85, 0xd1, 0xeb, 0xf7, 0xc3, 0x92, 0x55, 0x61, 0x49, 0x08, 0xfd, 0x23, 0x2c, 0xc1, - 0xa1, 0xa4, 0x64, 0x4e, 0x3e, 0xed, 0x7b, 0xae, 0x8c, 0xc2, 0x42, 0x10, 0xdd, 0x45, 0xe6, 0x01, 0x55, 0x8f, 0xae, - 0x43, 0x37, 0xc4, 0xcb, 0x0a, 0x4b, 0x86, 0x0e, 0x66, 0x30, 0x43, 0x50, 0xfc, 0x6b, 0x1e, 0x0a, 0xf0, 0x89, 0x07, - 0xf8, 0xe8, 0x31, 0x99, 0x71, 0x79, 0xad, 0x7d, 0x7b, 0x19, 0x96, 0x34, 0x50, 0x6d, 0x87, 0xa0, 0x03, 0x91, 0xfb, - 0x02, 0x3c, 0x05, 0x06, 0x2e, 0x2c, 0xec, 0x52, 0xec, 0xfa, 0xab, 0xff, 0xa2, 0x59, 0x47, 0x1b, 0x7e, 0xf4, 0x17, - 0xe3, 0xc2, 0x9e, 0x91, 0xa9, 0x38, 0x2e, 0x86, 0x93, 0xe9, 0x60, 0x20, 0x6c, 0x1c, 0xb7, 0xd3, 0x6c, 0xfe, 0xcb, - 0x5c, 0x2c, 0x16, 0xa8, 0xfb, 0xc6, 0x79, 0x9d, 0xa9, 0xbf, 0x91, 0x72, 0x3e, 0x78, 0x7d, 0xfa, 0xdb, 0xf9, 0xd9, - 0xe9, 0x4b, 0x70, 0x3e, 0xf8, 0xf0, 0xe2, 0xfb, 0x17, 0xef, 0x65, 0x70, 0x77, 0x39, 0xe7, 0xfd, 0xbe, 0x95, 0xfa, - 0x84, 0x7c, 0x58, 0x93, 0xc3, 0x30, 0x7e, 0x5c, 0x4a, 0xa3, 0x07, 0x72, 0xcc, 0x0c, 0x14, 0x32, 0x54, 0xd1, 0x98, - 0xdf, 0xc5, 0x70, 0xe2, 0x80, 0x59, 0xdc, 0x7b, 0x22, 0x5c, 0xb7, 0xe5, 0x26, 0xc8, 0x9a, 0x38, 0x71, 0xfa, 0xc1, - 0xc9, 0x54, 0x58, 0xb6, 0xb0, 0x64, 0x50, 0x36, 0xb4, 0xe9, 0x34, 0x9b, 0x97, 0x0b, 0xd3, 0x2e, 0xbb, 0x40, 0x46, - 0x69, 0x76, 0x79, 0x19, 0x4a, 0xe8, 0xea, 0x13, 0xd0, 0x00, 0xe8, 0x46, 0x95, 0xb6, 0x45, 0x7c, 0xe6, 0x96, 0x1f, - 0x8d, 0x9d, 0xe6, 0xdd, 0xa1, 0xee, 0x49, 0x37, 0xab, 0xf6, 0x06, 0x74, 0x30, 0xa1, 0xdc, 0x0e, 0xba, 0x0e, 0x26, - 0x23, 0xdb, 0xf2, 0xcb, 0xbc, 0x5e, 0xe8, 0xe6, 0xd8, 0x61, 0xa8, 0x9d, 0x92, 0xd7, 0xc2, 0x43, 0x64, 0x20, 0x19, - 0x86, 0x3d, 0x1a, 0xa3, 0x48, 0xfd, 0x60, 0xd7, 0x3b, 0x7e, 0x93, 0x0b, 0x88, 0xa6, 0x98, 0x81, 0x74, 0xfe, 0x51, - 0x25, 0x9d, 0xcb, 0x05, 0xe3, 0xf3, 0x6a, 0x71, 0x02, 0x6e, 0xe7, 0xf3, 0x6a, 0x11, 0x61, 0x50, 0xbe, 0x0c, 0x62, - 0x95, 0x80, 0xdd, 0x8b, 0x85, 0xf0, 0xed, 0x84, 0x36, 0x30, 0x1b, 0x48, 0xb0, 0x41, 0x61, 0x56, 0x1a, 0xa2, 0xdc, - 0x49, 0x8f, 0x36, 0x88, 0x3c, 0xc4, 0xea, 0x79, 0xdd, 0xf6, 0x64, 0xd3, 0x17, 0x13, 0x5c, 0x65, 0x31, 0x13, 0xd3, - 0xf8, 0x98, 0x95, 0xd3, 0x18, 0x4a, 0x89, 0xd3, 0x34, 0x8c, 0xe9, 0x84, 0x56, 0x84, 0x24, 0x8c, 0xcf, 0xe3, 0x05, - 0x4d, 0x50, 0x4a, 0x10, 0x42, 0xc8, 0x8f, 0x11, 0xda, 0xe6, 0xc0, 0x92, 0x37, 0xdb, 0xcf, 0xd1, 0xcf, 0xed, 0x18, - 0x2e, 0xa3, 0x22, 0x74, 0x83, 0xce, 0x1a, 0xee, 0x8d, 0xa8, 0xa4, 0x31, 0x56, 0x0c, 0x41, 0xc0, 0x4b, 0x8c, 0x4a, - 0x58, 0x92, 0x98, 0xd5, 0x10, 0x45, 0xa0, 0x98, 0xc7, 0x0b, 0x56, 0x52, 0xdf, 0xe6, 0x34, 0x56, 0x26, 0x41, 0x3d, - 0x8b, 0xa5, 0x76, 0x20, 0xa4, 0x0a, 0xb1, 0xc7, 0x67, 0x55, 0x74, 0xa3, 0x0c, 0x0d, 0x00, 0x05, 0x4a, 0xca, 0xc5, - 0x6f, 0x3f, 0xdf, 0xc3, 0x4d, 0x42, 0xff, 0xb3, 0x8d, 0x8e, 0x76, 0x96, 0xcb, 0x43, 0x6f, 0xbe, 0xa0, 0x71, 0x9e, - 0x43, 0x28, 0x36, 0x8d, 0x40, 0x5e, 0x64, 0x35, 0x44, 0xb4, 0xb8, 0x0f, 0x74, 0x48, 0x38, 0x68, 0xd3, 0x2f, 0x90, - 0xea, 0x89, 0xc9, 0xa5, 0x27, 0x06, 0xc6, 0xed, 0x90, 0x09, 0x05, 0x1c, 0xe9, 0x79, 0xf6, 0x97, 0x8f, 0xb1, 0xa6, - 0xa8, 0x99, 0x8e, 0xb7, 0x21, 0x11, 0x0d, 0x5a, 0x10, 0xcd, 0xe0, 0xfd, 0x73, 0xcd, 0xf1, 0xaa, 0x03, 0x3f, 0xe0, - 0x9d, 0x8d, 0x33, 0x2f, 0x67, 0x1e, 0x91, 0x53, 0x1f, 0xe5, 0x88, 0x7e, 0xc9, 0xc3, 0x7a, 0xa4, 0x92, 0x31, 0x56, - 0x12, 0x07, 0xbd, 0x0d, 0x16, 0xcc, 0x09, 0x5d, 0xf1, 0xd0, 0xf0, 0xf1, 0x2f, 0x91, 0xc9, 0xa8, 0x68, 0xa1, 0xd8, - 0x8d, 0xca, 0x60, 0xc4, 0x39, 0x0d, 0x33, 0x34, 0x59, 0xd2, 0xc5, 0x52, 0x91, 0xe6, 0x4a, 0x9a, 0x06, 0xb8, 0x04, - 0x1a, 0x3c, 0x1f, 0xf4, 0x43, 0x43, 0x3d, 0x84, 0x86, 0xdd, 0x21, 0xe0, 0x23, 0xfb, 0xd0, 0xe1, 0xff, 0xe7, 0xd8, - 0x05, 0x22, 0xed, 0xcd, 0x75, 0x64, 0x3c, 0xd2, 0x78, 0x38, 0x28, 0xda, 0xc7, 0xde, 0x4f, 0xfc, 0xcc, 0x19, 0x7d, - 0x48, 0x2a, 0xdf, 0xe1, 0x83, 0xe5, 0x8e, 0x37, 0xd5, 0xb3, 0x32, 0x82, 0xf5, 0xb0, 0xdd, 0xe2, 0x82, 0x68, 0xbb, - 0x00, 0x52, 0xc7, 0x78, 0xb5, 0x74, 0x8d, 0x57, 0xe3, 0x3d, 0xc6, 0xab, 0xf6, 0x4c, 0x0d, 0x73, 0xb2, 0x41, 0x7d, - 0x96, 0x94, 0xe7, 0xe7, 0x28, 0x13, 0xf4, 0x5d, 0xce, 0x0a, 0x2a, 0x53, 0x09, 0xed, 0xc5, 0x6e, 0xc6, 0xf8, 0x8e, - 0x60, 0x9c, 0x15, 0x8b, 0x91, 0x40, 0x65, 0x2a, 0x69, 0xc2, 0x5e, 0x09, 0xea, 0x31, 0x78, 0xaf, 0x31, 0x44, 0xb5, - 0x8c, 0x5d, 0xb7, 0x81, 0xd0, 0x50, 0x5b, 0x8f, 0xf6, 0x8c, 0xf5, 0xe8, 0x76, 0x5b, 0x6b, 0x7f, 0x3b, 0xb1, 0x2e, - 0x13, 0x44, 0x15, 0x96, 0xa3, 0x09, 0xf0, 0xa6, 0x89, 0xb9, 0x2d, 0x59, 0xa5, 0x05, 0x86, 0xcf, 0xfe, 0x23, 0x2c, - 0xac, 0x4a, 0xa2, 0x20, 0xb3, 0x22, 0x1a, 0xd8, 0x73, 0xf0, 0x79, 0x5c, 0xc3, 0x1a, 0x80, 0x48, 0x8e, 0xe8, 0xe1, - 0xfa, 0x47, 0x28, 0x6c, 0x66, 0x41, 0x66, 0x02, 0x32, 0xf3, 0x22, 0x6d, 0x67, 0x1d, 0x4c, 0xac, 0x49, 0xad, 0x33, - 0x16, 0x62, 0xa8, 0x91, 0x1f, 0x40, 0x19, 0x62, 0xf1, 0xc9, 0x07, 0x13, 0x2a, 0x64, 0x28, 0x55, 0xaf, 0x9b, 0xdd, - 0xc0, 0x2b, 0x1f, 0xb2, 0x6b, 0x5e, 0xd5, 0xf1, 0xf5, 0x4a, 0x5b, 0x12, 0x73, 0xb6, 0xcf, 0x6d, 0x8f, 0x56, 0xfa, - 0xd5, 0x9b, 0x17, 0xdf, 0x9f, 0x7a, 0xaf, 0x76, 0x11, 0x47, 0x43, 0xb0, 0xad, 0x18, 0x63, 0xf4, 0x16, 0x97, 0x06, - 0x13, 0xe9, 0x1a, 0x81, 0xde, 0xa5, 0xa0, 0xdf, 0xfe, 0x5c, 0x4f, 0xc0, 0x6b, 0xae, 0x96, 0x5f, 0xf2, 0x11, 0xb0, - 0x44, 0xf5, 0xac, 0x30, 0x3b, 0x2b, 0xb3, 0xbd, 0xdd, 0x8a, 0xf4, 0xb4, 0x4b, 0x8d, 0x0c, 0xc4, 0xab, 0xed, 0x30, - 0x16, 0x2e, 0x6c, 0xd3, 0xcd, 0x60, 0xd7, 0x4b, 0xc7, 0x12, 0x79, 0xbb, 0x2d, 0xa0, 0x43, 0x66, 0xc0, 0x9d, 0x97, - 0xf1, 0x1d, 0xbc, 0x2c, 0x9c, 0x6e, 0xfa, 0xc1, 0x13, 0xc0, 0x4c, 0xb8, 0xb4, 0x96, 0xc5, 0x31, 0xe3, 0x09, 0xcc, - 0x1f, 0x2d, 0x7d, 0x91, 0xb7, 0x24, 0xb4, 0x7a, 0x7f, 0x85, 0xd5, 0x08, 0xec, 0x4e, 0xce, 0x3e, 0x66, 0xab, 0xd9, - 0x12, 0x50, 0xf3, 0xaf, 0xb3, 0x02, 0x68, 0xae, 0x59, 0x0b, 0xa6, 0x29, 0xd4, 0x5f, 0xd7, 0xcf, 0xe2, 0x55, 0x9c, - 0x80, 0xea, 0x06, 0xbc, 0x45, 0xee, 0x95, 0xe8, 0x4a, 0xa3, 0x8b, 0xd2, 0x07, 0xca, 0x31, 0xa4, 0xd0, 0xd2, 0xf7, - 0x5e, 0x25, 0xcf, 0x3d, 0x0d, 0xb8, 0xa4, 0x50, 0xf3, 0x64, 0x4b, 0x19, 0x0b, 0x80, 0x85, 0x0e, 0x66, 0x92, 0x6c, - 0x45, 0x77, 0x1a, 0x93, 0x02, 0xde, 0x6a, 0xe0, 0x8f, 0x22, 0xab, 0xe5, 0x5d, 0xb1, 0x0a, 0x0b, 0xc7, 0xfe, 0xba, - 0xdf, 0x8f, 0x1d, 0xfb, 0xeb, 0x4b, 0x45, 0xeb, 0xe2, 0x76, 0x03, 0x48, 0x83, 0x01, 0x44, 0x4e, 0xd5, 0x40, 0xe8, - 0x88, 0x62, 0xbe, 0xef, 0xdf, 0xa9, 0xce, 0x22, 0x41, 0xe8, 0x77, 0xea, 0x75, 0xa4, 0x24, 0xa0, 0x53, 0xab, 0xd9, - 0xc9, 0x40, 0x99, 0x7d, 0x40, 0x40, 0x54, 0x37, 0x23, 0x9b, 0x2f, 0xa4, 0x73, 0xb1, 0x0c, 0x1f, 0x3e, 0xa6, 0x10, - 0x50, 0xb8, 0xa3, 0x46, 0xeb, 0x6d, 0x88, 0x04, 0xca, 0x08, 0x45, 0x8c, 0x79, 0xb1, 0x92, 0x84, 0xcc, 0xc7, 0x0b, - 0x14, 0x5c, 0x59, 0x60, 0x57, 0xce, 0x26, 0xc3, 0x22, 0xe2, 0x2c, 0xdc, 0xff, 0xcd, 0x64, 0x41, 0x50, 0x73, 0xe5, - 0x06, 0x72, 0xdc, 0xc9, 0xe4, 0xed, 0x29, 0xaf, 0x86, 0x8a, 0x89, 0x08, 0x02, 0xc3, 0x0d, 0x3f, 0xe3, 0xe3, 0xa3, - 0x05, 0x01, 0x15, 0x99, 0x31, 0x0b, 0xd1, 0x2f, 0x8e, 0xbf, 0x02, 0xd4, 0x98, 0xd1, 0xd1, 0x53, 0x00, 0x85, 0x85, - 0x80, 0xe8, 0x63, 0x90, 0xd1, 0x56, 0xf0, 0xbb, 0x92, 0xbf, 0x5b, 0x27, 0xbe, 0x0b, 0xfd, 0x5a, 0xd1, 0xcb, 0x18, - 0x18, 0x8e, 0x68, 0x72, 0x18, 0xf2, 0xc1, 0x64, 0x00, 0xda, 0x12, 0x67, 0xf7, 0xb5, 0xb4, 0xe2, 0xfa, 0x74, 0xe9, - 0x74, 0xff, 0xa4, 0x3e, 0x48, 0x22, 0x15, 0xac, 0x90, 0xc4, 0x00, 0x42, 0x59, 0xca, 0x6d, 0xb2, 0x04, 0xcb, 0x0a, - 0xbd, 0xa4, 0xb9, 0x46, 0x49, 0xdc, 0xdd, 0x0c, 0x1c, 0xa3, 0x66, 0x9d, 0x86, 0x45, 0xcb, 0x8d, 0x1a, 0xe0, 0x73, - 0x12, 0x56, 0x9a, 0x1b, 0xce, 0x4c, 0x38, 0x67, 0x3a, 0x5c, 0x1d, 0x73, 0xf6, 0x9a, 0x23, 0x18, 0x47, 0x82, 0x37, - 0x1e, 0xba, 0x64, 0x0a, 0x2a, 0x32, 0x65, 0x1c, 0x4c, 0x7b, 0x80, 0x7b, 0xcf, 0xc1, 0x38, 0x8c, 0x0d, 0x6a, 0x43, - 0xea, 0x53, 0xe7, 0x2e, 0x04, 0x82, 0xb4, 0xd6, 0xcb, 0x7c, 0x86, 0xa7, 0x67, 0x84, 0xb2, 0x3f, 0xe4, 0xf0, 0x01, - 0xf0, 0xb2, 0x24, 0x27, 0x13, 0xfe, 0xf4, 0xf1, 0x6e, 0xa0, 0x2a, 0x3e, 0x08, 0x0e, 0xe2, 0x22, 0x3d, 0x08, 0x06, - 0x15, 0xfc, 0x2a, 0xf9, 0x41, 0x2d, 0xc4, 0xc1, 0x65, 0x5c, 0x1e, 0xc4, 0xab, 0xb8, 0xac, 0x0f, 0x6e, 0xb3, 0x7a, - 0x79, 0xa0, 0x3b, 0x04, 0xd0, 0xbc, 0xc1, 0x20, 0x1e, 0x04, 0x07, 0xc1, 0xa0, 0xd4, 0x53, 0xbb, 0x62, 0x85, 0x77, - 0x9c, 0xe9, 0x10, 0x65, 0x81, 0x1f, 0x20, 0xcc, 0x3b, 0x0d, 0x80, 0x4f, 0x5d, 0xb3, 0x94, 0x5e, 0x62, 0xb8, 0x81, - 0x6a, 0xba, 0x86, 0x3e, 0x00, 0x8f, 0xbc, 0xa6, 0x31, 0x2c, 0x81, 0xcb, 0xc1, 0x80, 0xac, 0x21, 0x72, 0xc1, 0x9a, - 0x9a, 0x20, 0x0e, 0xe1, 0x5a, 0xda, 0x69, 0x17, 0x3b, 0x14, 0x76, 0xbb, 0x05, 0x44, 0xe5, 0x09, 0xe9, 0xf7, 0xcd, - 0x37, 0xd4, 0xbd, 0x60, 0x2f, 0xc1, 0xfe, 0xaa, 0xac, 0xc3, 0x44, 0x48, 0xcd, 0xf7, 0x15, 0x3b, 0x19, 0xc8, 0x88, - 0xc3, 0x3b, 0x8e, 0x14, 0x6d, 0x54, 0x2e, 0xc3, 0x9e, 0x2c, 0x3d, 0x5f, 0x89, 0x6b, 0x6e, 0xfd, 0xb8, 0x6a, 0x21, - 0xf2, 0x3a, 0x5b, 0x49, 0xf6, 0x6f, 0xc6, 0x15, 0xf7, 0x07, 0xd6, 0x9f, 0xfe, 0x2b, 0xb8, 0xb6, 0x3a, 0xef, 0x7c, - 0xae, 0x11, 0x39, 0x4b, 0x28, 0x97, 0x34, 0x26, 0x0f, 0x6f, 0xe9, 0xfb, 0xdc, 0xea, 0xdb, 0x4c, 0xa7, 0xf6, 0x59, - 0x85, 0x85, 0x0b, 0xd1, 0x8a, 0xe0, 0xd0, 0x10, 0x0b, 0xff, 0x08, 0xd0, 0xd7, 0x3e, 0x53, 0x41, 0x49, 0x9a, 0xf3, - 0x1a, 0xbd, 0x5b, 0x21, 0xe1, 0xa5, 0x62, 0x97, 0x1e, 0x06, 0x52, 0xc6, 0xed, 0xa1, 0x24, 0x4c, 0x4a, 0x5e, 0x84, - 0xf7, 0x5e, 0x7d, 0x93, 0x7b, 0x1e, 0x62, 0xf4, 0x22, 0xc7, 0x4e, 0x40, 0x5b, 0x77, 0x89, 0xce, 0x86, 0x27, 0x6e, - 0xc3, 0x73, 0xd6, 0xa2, 0xd1, 0x74, 0xc9, 0x92, 0x7e, 0x3f, 0x06, 0x13, 0xef, 0x94, 0xe5, 0xf0, 0x2b, 0x5f, 0xd0, - 0x35, 0x03, 0x4c, 0x31, 0x7a, 0x09, 0x09, 0x29, 0x22, 0x91, 0xac, 0xe5, 0x49, 0xf2, 0x89, 0xee, 0x42, 0x70, 0x84, - 0xcb, 0x59, 0x1a, 0x2d, 0xf7, 0x9a, 0x59, 0x20, 0x79, 0x86, 0xbe, 0xab, 0x60, 0x7b, 0x63, 0x17, 0xa4, 0x9c, 0x1f, - 0x57, 0xd3, 0xc1, 0x80, 0x13, 0x05, 0x37, 0x5e, 0x48, 0x71, 0xad, 0x6a, 0x71, 0xc7, 0x30, 0x16, 0xea, 0xb6, 0x88, - 0xc1, 0x01, 0xbb, 0x68, 0x65, 0xb7, 0x0f, 0xb0, 0xab, 0x1c, 0xef, 0x52, 0x65, 0x77, 0x7a, 0xcc, 0xf8, 0xcb, 0x56, - 0x91, 0x4e, 0x5a, 0xed, 0x27, 0xf2, 0x3e, 0x77, 0xd0, 0xe5, 0x72, 0xac, 0x78, 0xcb, 0x41, 0x45, 0x1e, 0xf3, 0x91, - 0xa4, 0xba, 0x9f, 0xe1, 0x08, 0xf3, 0x60, 0xdd, 0xfa, 0x93, 0x43, 0x5d, 0xe0, 0x10, 0x79, 0x52, 0xaf, 0x29, 0xa0, - 0x7b, 0xaf, 0x1e, 0x77, 0xf5, 0xdb, 0xd0, 0x5d, 0xa0, 0x44, 0x3b, 0x15, 0x7b, 0x7e, 0x4c, 0xd4, 0xea, 0x4c, 0x3d, - 0xa1, 0x7f, 0xad, 0xc5, 0xfd, 0x85, 0x76, 0x15, 0xf7, 0xbd, 0xcb, 0x67, 0x1c, 0xea, 0xec, 0x86, 0x50, 0x00, 0xae, - 0xda, 0xd1, 0xa9, 0x6b, 0x43, 0x7a, 0xa9, 0x44, 0x37, 0xc1, 0xc1, 0xf6, 0xfa, 0x8c, 0xa3, 0xe8, 0x47, 0xab, 0x91, - 0x6f, 0xa3, 0xea, 0xb1, 0x18, 0xc4, 0x8f, 0x4b, 0xba, 0x8c, 0xaa, 0xc7, 0xe5, 0x20, 0x7e, 0x2c, 0x9a, 0x66, 0xf7, - 0x5c, 0xd9, 0xdf, 0x47, 0xe4, 0x59, 0x77, 0xf6, 0x52, 0x01, 0x1b, 0x03, 0xcf, 0xae, 0x05, 0x84, 0x53, 0x70, 0x44, - 0xb6, 0x86, 0x3e, 0x74, 0x6e, 0xf7, 0xb1, 0x61, 0x92, 0x20, 0xe8, 0x79, 0x9b, 0x4d, 0xa2, 0xd8, 0x59, 0xff, 0xe8, - 0xc3, 0x29, 0x10, 0xd0, 0xed, 0xb6, 0x59, 0x57, 0x6b, 0x40, 0x31, 0x0d, 0xc7, 0xfc, 0xb0, 0x1c, 0xdd, 0xba, 0xee, - 0xfa, 0x87, 0xe5, 0x68, 0x49, 0x86, 0x13, 0x3d, 0xf9, 0xf1, 0xc9, 0x78, 0x16, 0x47, 0x93, 0xa6, 0xe3, 0xb4, 0x50, - 0xf8, 0xa7, 0xce, 0x2d, 0x14, 0x81, 0x53, 0x31, 0x82, 0x23, 0xa7, 0xca, 0x49, 0xc9, 0xc3, 0xf0, 0x3f, 0xa8, 0x77, - 0xb4, 0x69, 0xaf, 0xe3, 0x3a, 0x59, 0x66, 0xc5, 0x95, 0x0a, 0x1f, 0xae, 0xa2, 0x8b, 0x9b, 0x80, 0x76, 0xce, 0x65, - 0xda, 0xf2, 0xeb, 0xc4, 0xa3, 0x27, 0xb6, 0x66, 0x06, 0xdc, 0xba, 0x1b, 0xa1, 0x19, 0x02, 0xa3, 0xe5, 0xf9, 0x3b, - 0xc4, 0xdc, 0xfe, 0x55, 0xda, 0xfc, 0x4a, 0xda, 0x67, 0xc9, 0x48, 0xd1, 0x26, 0x23, 0x35, 0x18, 0x61, 0x8a, 0x22, - 0x89, 0xeb, 0xb0, 0x80, 0x20, 0xd8, 0x9f, 0x51, 0x5c, 0x8b, 0xa5, 0x77, 0x1a, 0x84, 0x09, 0xa6, 0x0b, 0xca, 0xaf, - 0x6e, 0xe7, 0xb6, 0xd2, 0x62, 0x8f, 0xe4, 0xf7, 0xb9, 0xb5, 0x5d, 0x51, 0xe4, 0xef, 0xf3, 0x06, 0xd4, 0x03, 0xa2, - 0xdc, 0xd7, 0x47, 0x29, 0x70, 0xd2, 0xe2, 0x86, 0x02, 0xa3, 0x17, 0x74, 0x75, 0x22, 0x77, 0xec, 0xd4, 0x9c, 0xa9, - 0x98, 0xc9, 0xb8, 0xf2, 0x7e, 0xcf, 0xdc, 0x07, 0x4d, 0x41, 0x2b, 0x30, 0xf0, 0xd6, 0x67, 0x3c, 0x3a, 0xd0, 0xdd, - 0x6a, 0x9d, 0x16, 0x6c, 0x16, 0xd4, 0x65, 0xdd, 0xb6, 0xf1, 0xa0, 0x11, 0x07, 0x45, 0xb2, 0x2a, 0x54, 0x4b, 0x78, - 0x22, 0x10, 0x30, 0x65, 0xd7, 0x3c, 0xd2, 0x82, 0x9a, 0xde, 0x84, 0xc2, 0x86, 0x82, 0xbf, 0x52, 0x54, 0xd3, 0x9b, - 0x50, 0x9f, 0x89, 0x53, 0x0c, 0x22, 0x98, 0x11, 0x9b, 0xfd, 0x16, 0x50, 0x7f, 0x6b, 0x46, 0x9b, 0xa6, 0x31, 0xda, - 0x2a, 0xe4, 0x92, 0x22, 0x69, 0xf9, 0x6f, 0xd5, 0x54, 0x50, 0x52, 0xcb, 0x45, 0x6f, 0xe2, 0xbb, 0xe8, 0xf1, 0x4c, - 0x4b, 0x02, 0xa5, 0x5b, 0xee, 0x18, 0xfd, 0x21, 0x0c, 0xf0, 0x88, 0x8e, 0x13, 0x0b, 0xe6, 0x56, 0x27, 0x2c, 0x9b, - 0x57, 0x8b, 0xd1, 0x4a, 0x40, 0xd8, 0xe0, 0x63, 0x96, 0xcd, 0x0b, 0xf5, 0x10, 0xba, 0xc2, 0xd2, 0xb7, 0x60, 0x17, - 0x1b, 0xac, 0x44, 0x15, 0x80, 0xef, 0x05, 0xdd, 0xac, 0x44, 0x15, 0x09, 0xd9, 0xfd, 0xb8, 0xc1, 0x12, 0x64, 0x5a, - 0x29, 0xd3, 0x92, 0x06, 0x0b, 0x02, 0x5f, 0x55, 0x55, 0x3e, 0x24, 0xdb, 0x0a, 0xe4, 0x53, 0x47, 0x0d, 0x38, 0x05, - 0xb2, 0x0a, 0x2c, 0x48, 0x80, 0xca, 0xd0, 0x56, 0x81, 0x69, 0x25, 0xa6, 0xe9, 0x2a, 0x6c, 0x94, 0xd9, 0xa1, 0xd0, - 0xeb, 0x25, 0x9f, 0xc5, 0x83, 0x30, 0x19, 0xc6, 0xe4, 0x31, 0x42, 0xed, 0x1f, 0xe6, 0x51, 0xac, 0xe4, 0x92, 0x2b, - 0xeb, 0x17, 0x7f, 0xfb, 0x09, 0x7b, 0xdd, 0x73, 0x0c, 0x16, 0x60, 0x2d, 0x6d, 0xaf, 0xb3, 0xe2, 0x9d, 0x68, 0x05, - 0xc7, 0xc1, 0x2c, 0xd2, 0x61, 0xd5, 0x91, 0x23, 0xea, 0x8b, 0x5c, 0x7b, 0x17, 0x21, 0x72, 0x90, 0xde, 0x63, 0x80, - 0xdd, 0x08, 0x5f, 0x87, 0xc6, 0xe6, 0x56, 0x55, 0x88, 0xbf, 0x51, 0x22, 0xf1, 0x93, 0x10, 0x1f, 0xd7, 0x2b, 0x99, - 0xab, 0xd6, 0x78, 0xac, 0xaa, 0x19, 0x3c, 0x53, 0xbe, 0xc7, 0xca, 0xbf, 0xb5, 0xdd, 0x1c, 0xe7, 0x3d, 0x78, 0xd0, - 0xba, 0xdf, 0x3a, 0x12, 0x42, 0x73, 0xe5, 0x24, 0x4d, 0x47, 0x8d, 0x8e, 0x99, 0xac, 0x16, 0x95, 0x30, 0xb9, 0x3b, - 0xa5, 0x63, 0xa0, 0xa2, 0x03, 0xb8, 0x96, 0xa8, 0x0e, 0x7a, 0x52, 0xb2, 0x31, 0x1c, 0x71, 0x06, 0x07, 0xed, 0x38, - 0x46, 0xf1, 0x72, 0x2e, 0xc5, 0xcb, 0xf9, 0x09, 0xe3, 0x00, 0xad, 0x05, 0x48, 0xf5, 0x0a, 0xf6, 0x33, 0x97, 0xb0, - 0xc0, 0xfa, 0xce, 0x77, 0x64, 0x80, 0x0c, 0x71, 0xb2, 0x39, 0x4e, 0xf6, 0xb8, 0x51, 0x73, 0x5f, 0xe1, 0xe3, 0xa4, - 0x59, 0x38, 0x75, 0x15, 0xed, 0xba, 0x96, 0xac, 0x98, 0x97, 0x83, 0x09, 0x04, 0x65, 0x29, 0xe6, 0xe5, 0x70, 0xb2, - 0xa0, 0x39, 0xfc, 0x58, 0x78, 0xe8, 0x10, 0xcb, 0x41, 0x02, 0x97, 0xce, 0x1e, 0x03, 0xde, 0x50, 0x28, 0x71, 0x37, - 0xd6, 0x91, 0x63, 0x1d, 0xe5, 0x61, 0x18, 0x03, 0xae, 0xac, 0x15, 0x78, 0xef, 0xbf, 0x3e, 0xfa, 0x80, 0xac, 0xca, - 0x15, 0x5e, 0x8e, 0x72, 0xd7, 0x95, 0x46, 0x5d, 0x52, 0x7a, 0x95, 0x13, 0x3c, 0x95, 0x6c, 0xb7, 0x3d, 0x63, 0x4f, - 0xe5, 0x20, 0xf1, 0x8e, 0x11, 0xbd, 0x98, 0x7a, 0x99, 0x39, 0x81, 0x33, 0xdb, 0x5e, 0xb6, 0x31, 0x3f, 0x76, 0x80, - 0x83, 0x45, 0x10, 0x12, 0x37, 0x84, 0x61, 0x62, 0x27, 0xc5, 0x50, 0x09, 0xe1, 0xba, 0x16, 0x5e, 0xc7, 0x69, 0x19, - 0x83, 0x8b, 0xb4, 0xb2, 0x4d, 0xdc, 0x43, 0xd7, 0x1d, 0x3f, 0xe6, 0x56, 0xc7, 0x68, 0xcb, 0x7c, 0xb8, 0xa3, 0xd3, - 0x07, 0x16, 0x03, 0x50, 0xf7, 0x60, 0x56, 0xb7, 0xcf, 0x24, 0xae, 0x4f, 0xbb, 0x8a, 0x90, 0x08, 0x44, 0x51, 0x2a, - 0x23, 0x4c, 0xff, 0x4e, 0x73, 0x59, 0x4d, 0xeb, 0x07, 0x79, 0xe6, 0x90, 0x67, 0xa1, 0xb3, 0x3d, 0x68, 0xed, 0xef, - 0x06, 0xed, 0xc4, 0x6d, 0xf7, 0xce, 0xff, 0x5b, 0xd6, 0xb5, 0xd5, 0x9a, 0xea, 0x71, 0xbb, 0xfa, 0x81, 0xb7, 0x57, - 0x7b, 0x32, 0x06, 0xcc, 0x4a, 0x38, 0x67, 0x54, 0xc5, 0xcb, 0x8c, 0x57, 0x78, 0x52, 0xad, 0x3c, 0x1f, 0xef, 0xdb, - 0x6c, 0xa4, 0x1f, 0xc8, 0x14, 0x10, 0xcf, 0x6f, 0x53, 0xad, 0x3e, 0x4e, 0x51, 0x02, 0xfe, 0x4e, 0xc5, 0x37, 0xa2, - 0x1f, 0xcd, 0x8b, 0x2b, 0x5e, 0xbf, 0xbd, 0x2d, 0xf4, 0x8b, 0xe7, 0x46, 0xe7, 0x4f, 0x5f, 0x97, 0x2e, 0x74, 0x38, - 0x6a, 0xef, 0xa0, 0xc8, 0x82, 0x55, 0x27, 0x13, 0x2d, 0x6b, 0xab, 0x66, 0x1f, 0x25, 0x5c, 0x4c, 0x54, 0xa3, 0x67, - 0x9d, 0x39, 0x61, 0x4a, 0xd0, 0x37, 0x8e, 0x51, 0xc9, 0x18, 0x96, 0x0c, 0xd4, 0x69, 0x52, 0x88, 0x1e, 0x56, 0x33, - 0x8c, 0x57, 0x0c, 0xa0, 0x30, 0xa5, 0x04, 0x51, 0xb4, 0x06, 0xc1, 0x40, 0x13, 0xfa, 0xfd, 0xdb, 0x54, 0x65, 0xa0, - 0x45, 0x33, 0x15, 0x20, 0xaa, 0x83, 0x68, 0xab, 0xbc, 0x0c, 0x7f, 0x5c, 0xd2, 0x22, 0xa3, 0x79, 0x45, 0x97, 0x15, - 0x4d, 0x32, 0x7a, 0xc9, 0xa5, 0xa8, 0x78, 0x5d, 0x31, 0x49, 0xdb, 0x35, 0x61, 0xff, 0x97, 0x47, 0xd7, 0x5b, 0xb1, - 0xd6, 0xd0, 0xee, 0x04, 0x19, 0xa1, 0xf9, 0x42, 0x05, 0x21, 0x43, 0xe5, 0x24, 0x74, 0xad, 0x56, 0x78, 0x05, 0x36, - 0x99, 0x66, 0xa3, 0x65, 0x5c, 0x85, 0x81, 0xf9, 0x2a, 0x30, 0x98, 0x1c, 0x98, 0x74, 0xb6, 0xbe, 0x78, 0x26, 0xae, - 0x57, 0xa2, 0xe0, 0x45, 0x2d, 0x21, 0xfa, 0x35, 0xee, 0xbb, 0x8e, 0xab, 0xce, 0xfc, 0x5a, 0xe9, 0x43, 0xdf, 0xba, - 0xac, 0x8d, 0xfd, 0x42, 0xe3, 0x18, 0xec, 0x7c, 0x44, 0x34, 0xa4, 0x41, 0xad, 0x5a, 0x1c, 0xea, 0x00, 0x5d, 0x2a, - 0xa4, 0x90, 0x21, 0x53, 0x99, 0x2c, 0x41, 0xc6, 0x37, 0x7e, 0x2f, 0x44, 0x3d, 0xfa, 0x73, 0xcd, 0xcb, 0xfb, 0x33, - 0x9e, 0x73, 0x1c, 0xa3, 0x20, 0x89, 0x8b, 0x9b, 0xb8, 0x0a, 0x88, 0x6b, 0x79, 0x15, 0x1c, 0xa5, 0x3a, 0x6c, 0xcc, - 0x4e, 0xd5, 0xa8, 0xf5, 0x12, 0xe8, 0x2b, 0x23, 0x7d, 0x63, 0x30, 0x34, 0x11, 0x95, 0xd0, 0xf7, 0x4a, 0xdd, 0xd3, - 0xea, 0x86, 0x01, 0xc4, 0x9f, 0x4b, 0xbd, 0x50, 0xeb, 0xb5, 0x1f, 0x73, 0x43, 0x47, 0x08, 0x1a, 0x7d, 0xd5, 0x2c, - 0x1a, 0xc7, 0x2d, 0x4d, 0x46, 0xc6, 0x8d, 0x36, 0x39, 0xbf, 0x02, 0x19, 0x9f, 0x35, 0x17, 0x9a, 0x34, 0x0d, 0x95, - 0x50, 0x85, 0xd1, 0xe6, 0xce, 0x4b, 0xa7, 0xf7, 0xe0, 0xce, 0xa6, 0xcd, 0x8e, 0x94, 0x4b, 0x63, 0x43, 0x4b, 0x5e, - 0xad, 0x44, 0x51, 0x41, 0x18, 0xe7, 0xde, 0x98, 0x5e, 0xc7, 0x59, 0x51, 0xc7, 0x59, 0x71, 0x5a, 0xad, 0x78, 0x52, - 0xbf, 0x87, 0x5b, 0x9c, 0xb4, 0xba, 0x69, 0x2a, 0xb8, 0xd2, 0x25, 0x07, 0x18, 0x4c, 0x4d, 0xc6, 0x3d, 0xb6, 0x06, - 0x17, 0xf5, 0xef, 0xd1, 0x52, 0x60, 0x2c, 0x54, 0x55, 0x7c, 0x7c, 0x51, 0x89, 0x7c, 0x5d, 0x83, 0x76, 0xf7, 0xb2, - 0x8e, 0x8e, 0x9e, 0xac, 0xee, 0xa6, 0xf2, 0x06, 0x13, 0x3d, 0x39, 0x5a, 0xdd, 0xf5, 0xb2, 0xeb, 0x95, 0x28, 0xeb, - 0xb8, 0xa8, 0xa7, 0x12, 0x91, 0x2c, 0x89, 0xf3, 0x24, 0x9c, 0x8c, 0xc7, 0x5f, 0x1c, 0x0c, 0x0f, 0x20, 0x03, 0x99, - 0xfe, 0x35, 0x94, 0x2e, 0x47, 0xc3, 0xc9, 0x78, 0x3c, 0x15, 0xf2, 0x6e, 0x17, 0x8d, 0x26, 0x0d, 0xd6, 0x33, 0x4c, - 0xd4, 0xcc, 0x8c, 0xf8, 0xdd, 0x2a, 0x2e, 0x52, 0x88, 0x5f, 0xa7, 0x8a, 0x3f, 0x7a, 0x32, 0xf6, 0xca, 0x37, 0x9f, - 0x3e, 0x6d, 0x7e, 0x6f, 0x74, 0x58, 0x6b, 0xdd, 0xee, 0x67, 0xbf, 0x1f, 0xcb, 0xf9, 0x3e, 0x39, 0x3e, 0x54, 0x3f, - 0x7e, 0x6f, 0x9a, 0xe9, 0xeb, 0x32, 0x9c, 0xff, 0x33, 0x94, 0xf3, 0x79, 0x5a, 0x96, 0xf1, 0x7d, 0x43, 0x16, 0x74, - 0x5d, 0x59, 0x6f, 0x12, 0xea, 0x6c, 0x03, 0x7a, 0x44, 0xa6, 0xeb, 0x8a, 0xc1, 0x37, 0xef, 0xeb, 0x30, 0xe0, 0xd5, - 0x6a, 0xc8, 0x8b, 0x3a, 0xab, 0xef, 0x87, 0x98, 0x27, 0xc0, 0x4f, 0x35, 0x6f, 0xf6, 0xac, 0xd4, 0xc4, 0xe6, 0xb2, - 0xe4, 0xfc, 0x2f, 0x1e, 0x4a, 0xe3, 0xe8, 0x31, 0x1a, 0x47, 0x8f, 0xa9, 0x1c, 0x8c, 0xc9, 0xd7, 0x54, 0x75, 0x66, - 0xf2, 0x35, 0x98, 0x20, 0x65, 0xed, 0x6f, 0xa4, 0x71, 0x62, 0x34, 0xa6, 0x37, 0x2f, 0xf3, 0x6c, 0x05, 0x4c, 0xf0, - 0x52, 0xfd, 0x68, 0x08, 0x7d, 0xcf, 0xdb, 0xd9, 0x47, 0xa3, 0xd1, 0xb3, 0x92, 0x8e, 0x46, 0xa3, 0x8f, 0x59, 0x43, - 0xe8, 0x65, 0xd5, 0xf1, 0xfe, 0x3d, 0xa7, 0x17, 0x22, 0xbd, 0x8f, 0x82, 0x80, 0x2e, 0xb3, 0x34, 0xe5, 0x85, 0x2c, - 0xeb, 0x2c, 0x6d, 0xe7, 0x95, 0x2d, 0x44, 0xe0, 0x1f, 0xd5, 0x46, 0x84, 0x20, 0x22, 0xf4, 0xed, 0x4e, 0xcf, 0x46, - 0xa3, 0xd1, 0x59, 0xaa, 0xab, 0xb5, 0x0c, 0xf9, 0x6b, 0x34, 0x1f, 0xb0, 0x76, 0xf9, 0x60, 0x7d, 0xa3, 0xa3, 0x9d, - 0x1c, 0xfe, 0xf7, 0x70, 0x36, 0x1f, 0x0f, 0xbf, 0x1d, 0x2d, 0x1e, 0x1f, 0xd2, 0x20, 0x70, 0x41, 0xab, 0x43, 0x65, - 0xcd, 0x31, 0x2d, 0x8e, 0xc7, 0x53, 0x52, 0x0c, 0xd8, 0x13, 0xe3, 0x4b, 0xf3, 0xc5, 0x13, 0x40, 0x22, 0x45, 0x11, - 0x6a, 0x60, 0xa5, 0x7f, 0x78, 0x15, 0x79, 0x55, 0x00, 0x3e, 0x9a, 0x89, 0x64, 0xa0, 0xb5, 0x80, 0xe3, 0x08, 0xca, - 0x6b, 0x8c, 0x69, 0x44, 0x8f, 0xb1, 0x4c, 0x47, 0x05, 0x1d, 0x4f, 0xab, 0xdb, 0xac, 0x4e, 0x96, 0x18, 0xd8, 0x28, - 0xae, 0x78, 0xf0, 0x45, 0x10, 0x15, 0xec, 0xe8, 0xe9, 0x54, 0xc2, 0xfb, 0x62, 0x52, 0xca, 0xaf, 0x20, 0xf1, 0xdb, - 0x31, 0x42, 0xa0, 0x12, 0xe5, 0xb1, 0x88, 0x35, 0xbe, 0xcc, 0x45, 0x0c, 0x1e, 0x9c, 0x95, 0xe2, 0x59, 0xcc, 0x49, - 0x60, 0xec, 0x2f, 0x5a, 0xcd, 0x11, 0xd0, 0x9c, 0x50, 0x30, 0x71, 0x58, 0x50, 0xf1, 0xc5, 0x04, 0xbd, 0x82, 0xc0, - 0xad, 0x3a, 0x82, 0xe3, 0xce, 0x58, 0x36, 0xa8, 0xe5, 0x93, 0xb2, 0xc3, 0xf9, 0xff, 0xae, 0xe8, 0x62, 0x70, 0x68, - 0x87, 0xe6, 0xad, 0x72, 0x5f, 0xad, 0x91, 0x51, 0xaa, 0xc3, 0x67, 0x29, 0x31, 0xc6, 0xa7, 0x9c, 0x9d, 0x6c, 0x74, - 0x77, 0x46, 0x75, 0x99, 0x5d, 0x87, 0x44, 0xf5, 0xca, 0x82, 0x62, 0x06, 0x51, 0x36, 0xc2, 0xf5, 0x03, 0xd6, 0x22, - 0x4e, 0x27, 0x6f, 0x78, 0x59, 0x67, 0x89, 0x7c, 0x7f, 0xe3, 0xbd, 0x07, 0x6a, 0x20, 0x1b, 0xf4, 0xae, 0x64, 0x30, - 0xcf, 0x6f, 0x4b, 0x00, 0xed, 0xac, 0x78, 0x79, 0xc3, 0x5d, 0xba, 0x11, 0x04, 0x8d, 0x6d, 0xe6, 0x95, 0x17, 0x6c, - 0x02, 0xbe, 0x7a, 0x57, 0x02, 0xe6, 0x46, 0x08, 0x52, 0x53, 0x08, 0x85, 0x03, 0x17, 0xf8, 0xba, 0x2e, 0xb3, 0x8b, - 0x75, 0xcd, 0x31, 0xd8, 0x47, 0x61, 0xb5, 0x98, 0xd2, 0x09, 0x8f, 0x87, 0x01, 0xfe, 0x08, 0xa8, 0x0c, 0xb8, 0xa1, - 0x3d, 0xec, 0xe0, 0x85, 0xfc, 0x65, 0xdf, 0xc8, 0x3d, 0xc2, 0x5e, 0xa7, 0x21, 0x04, 0xd7, 0xc1, 0x87, 0x00, 0x96, - 0x14, 0xa1, 0x6f, 0xf1, 0x54, 0x0d, 0x83, 0xcb, 0x3c, 0x5b, 0xa9, 0xa4, 0x7a, 0xd4, 0xd1, 0x7c, 0x28, 0xb5, 0x23, - 0x39, 0xa0, 0x4e, 0x7a, 0x8c, 0xe9, 0xa5, 0x4c, 0x97, 0x45, 0x59, 0x23, 0x94, 0x77, 0x6a, 0x62, 0x6c, 0x98, 0x3e, - 0x0e, 0x91, 0x5f, 0xde, 0x95, 0x32, 0xf4, 0x0b, 0x5f, 0x00, 0xf8, 0x15, 0xdc, 0xee, 0x77, 0xe3, 0xbb, 0xc8, 0xec, - 0xe7, 0x9c, 0x1d, 0xfe, 0xf7, 0x3c, 0x1e, 0xfe, 0x35, 0x1e, 0x7e, 0xbb, 0x18, 0x84, 0x43, 0xf3, 0x93, 0x3c, 0x7e, - 0x74, 0x48, 0x5f, 0x72, 0xc3, 0x95, 0xc0, 0xc2, 0xf7, 0x82, 0xdb, 0xc8, 0x95, 0x10, 0x44, 0x01, 0xde, 0x28, 0xec, - 0x6a, 0x9c, 0x00, 0xc0, 0x5f, 0xf0, 0x5f, 0x01, 0x1a, 0x09, 0xd9, 0x8b, 0x06, 0xe8, 0x07, 0xe4, 0xef, 0x93, 0xaf, - 0x3c, 0x03, 0x39, 0x10, 0x4f, 0xc8, 0x18, 0x28, 0x44, 0x95, 0x31, 0x91, 0xb0, 0xbf, 0x26, 0xfb, 0x76, 0xdb, 0x6b, - 0x4b, 0x7e, 0xf0, 0x4b, 0x37, 0xd3, 0x44, 0xcf, 0x3b, 0xdc, 0x50, 0x56, 0x62, 0x15, 0x22, 0x36, 0x9e, 0xfa, 0x95, - 0x33, 0x88, 0x35, 0x79, 0x93, 0x81, 0x0f, 0x83, 0xf9, 0x62, 0x3c, 0x03, 0x69, 0x11, 0xdc, 0x71, 0x4a, 0x7e, 0x99, - 0x81, 0x5b, 0x73, 0x11, 0xe3, 0x05, 0xdb, 0x2c, 0x89, 0x7e, 0xbf, 0x97, 0x67, 0x61, 0xae, 0x70, 0x96, 0xf3, 0x46, - 0x8b, 0xdd, 0x51, 0x27, 0x0c, 0xe2, 0x76, 0x35, 0x04, 0x43, 0x39, 0x04, 0x65, 0x47, 0x5b, 0x6c, 0xbd, 0xa6, 0x9e, - 0x52, 0xf7, 0x56, 0xd6, 0x57, 0x8e, 0xfe, 0x10, 0x59, 0x81, 0x85, 0xb4, 0x6b, 0x8e, 0x55, 0xcd, 0x31, 0xd2, 0x9e, - 0x7e, 0xbf, 0xf2, 0xc8, 0x4f, 0x67, 0xe1, 0x41, 0x20, 0x4b, 0x15, 0x3b, 0x65, 0x51, 0x6e, 0x4a, 0x73, 0xc6, 0xb0, - 0xa1, 0x79, 0x66, 0xe2, 0xba, 0xcc, 0x7a, 0xbd, 0x30, 0x44, 0x87, 0x46, 0x2c, 0x15, 0x6b, 0x83, 0xf0, 0x3e, 0x3a, - 0x61, 0x74, 0x0d, 0xb2, 0xba, 0xf0, 0x9c, 0x13, 0xe4, 0xcb, 0xc0, 0x64, 0x4d, 0x56, 0xeb, 0xe4, 0x84, 0x47, 0x2f, - 0x5f, 0x36, 0x82, 0x06, 0x39, 0x49, 0x51, 0x6f, 0x62, 0x77, 0xec, 0xa3, 0x16, 0x52, 0xe3, 0xa6, 0x99, 0xf6, 0x14, - 0xa9, 0xe8, 0xb1, 0x5e, 0x2d, 0x7f, 0x81, 0x65, 0x81, 0x21, 0x1f, 0x84, 0xf6, 0x14, 0xad, 0xc0, 0x0c, 0x37, 0x26, - 0x83, 0xa6, 0x1f, 0x16, 0x6d, 0x11, 0x3a, 0x23, 0xb7, 0x25, 0x84, 0x6d, 0x1b, 0x84, 0xb5, 0xf3, 0x44, 0xbe, 0x78, - 0xe2, 0x30, 0xc2, 0x21, 0xd7, 0x9b, 0xb9, 0xf2, 0x30, 0xcc, 0xaf, 0x85, 0xdf, 0x3c, 0xd5, 0x5c, 0x27, 0x2a, 0x66, - 0x05, 0xdb, 0xed, 0xb2, 0x22, 0xf8, 0xf7, 0x63, 0x36, 0xc3, 0xbf, 0x59, 0xbf, 0xdf, 0x0b, 0xf1, 0x17, 0xc7, 0xe0, - 0x3d, 0xf3, 0x6a, 0xc1, 0x3e, 0x82, 0x4c, 0x85, 0x44, 0x98, 0x2a, 0x8d, 0xdf, 0x58, 0x0d, 0x16, 0x70, 0xfa, 0x03, - 0x99, 0x0b, 0x33, 0x99, 0xcb, 0x8b, 0x6d, 0xc8, 0x69, 0x6b, 0x9c, 0xb2, 0x51, 0x96, 0x48, 0xd7, 0x85, 0x6c, 0x14, - 0xe7, 0x59, 0x5c, 0xf1, 0x6a, 0xbb, 0x55, 0x87, 0x63, 0x52, 0x72, 0xf4, 0x2b, 0x40, 0x2a, 0x55, 0xb0, 0x8e, 0x54, - 0x3b, 0xfe, 0x22, 0x2c, 0x71, 0x9f, 0xf2, 0x79, 0xb9, 0x30, 0x7b, 0x6b, 0x5e, 0x2e, 0x98, 0xbc, 0x95, 0xf6, 0xc2, - 0x12, 0x9a, 0x57, 0x10, 0xb2, 0xc1, 0x54, 0xc7, 0xa2, 0x35, 0x66, 0xd5, 0xbc, 0x5c, 0x40, 0x18, 0x99, 0x72, 0x01, - 0x36, 0x53, 0xbc, 0x00, 0x2f, 0x92, 0x18, 0x60, 0xe2, 0x62, 0x32, 0x85, 0x78, 0xe6, 0xb2, 0x9c, 0x78, 0xa1, 0xef, - 0x97, 0x89, 0x45, 0xca, 0x80, 0x57, 0x8d, 0x46, 0x13, 0x33, 0x0d, 0x47, 0x9d, 0x20, 0x27, 0x3a, 0xbf, 0x9b, 0x5a, - 0x11, 0x62, 0x4f, 0x1c, 0x01, 0x97, 0x15, 0xd3, 0x85, 0x17, 0x1d, 0x88, 0x31, 0x72, 0x70, 0x8a, 0x4f, 0x0c, 0x8e, - 0xc2, 0xe0, 0xdc, 0x38, 0x27, 0x48, 0x19, 0xc6, 0x64, 0x23, 0xd8, 0xb5, 0x08, 0xab, 0x79, 0xbc, 0x00, 0x65, 0x5d, - 0xbc, 0x00, 0xcb, 0x1a, 0x6d, 0x80, 0x09, 0xf2, 0x2a, 0xee, 0x84, 0x7e, 0xa2, 0xb8, 0x42, 0x84, 0x63, 0xe5, 0xfa, - 0xa8, 0x6c, 0x87, 0xbe, 0xc0, 0xeb, 0xbd, 0x34, 0xc7, 0xcd, 0x7a, 0x2c, 0x10, 0xd8, 0x10, 0x30, 0x36, 0x52, 0x69, - 0xb2, 0xb5, 0xf6, 0x8d, 0x9e, 0x07, 0x3e, 0xcd, 0x46, 0x85, 0xa8, 0xcf, 0x2f, 0x41, 0x84, 0xe2, 0xa2, 0xc1, 0x23, - 0xbf, 0x88, 0x3b, 0x4b, 0xbf, 0x35, 0x2d, 0x2a, 0xd8, 0xc9, 0x06, 0x40, 0xfa, 0x54, 0xb4, 0x28, 0x29, 0xa7, 0x28, - 0x48, 0x63, 0x37, 0x05, 0xac, 0x24, 0x77, 0x01, 0x43, 0xb0, 0xb1, 0x83, 0xca, 0xea, 0x14, 0x11, 0x49, 0x02, 0x91, - 0x15, 0xc3, 0x82, 0xe2, 0xd8, 0x16, 0x88, 0xfa, 0x69, 0xca, 0x32, 0x83, 0xa1, 0xa3, 0xe2, 0x3e, 0x4f, 0x1d, 0x4a, - 0x14, 0x04, 0x54, 0x0d, 0x39, 0x48, 0x6c, 0x4d, 0x03, 0xe1, 0x01, 0x79, 0x44, 0x67, 0xac, 0xbf, 0xcf, 0x3a, 0xcf, - 0x2e, 0x34, 0x47, 0xe5, 0x6a, 0x57, 0xe8, 0x31, 0xc2, 0x93, 0x4c, 0xc3, 0xe4, 0x3b, 0xe7, 0x99, 0x56, 0x53, 0xf4, - 0x1c, 0x7c, 0xb2, 0x53, 0x8c, 0x48, 0xb7, 0x67, 0xd0, 0x75, 0xf0, 0xaa, 0x0e, 0x1b, 0xed, 0x5a, 0x42, 0x48, 0xe8, - 0x5a, 0x14, 0x31, 0xeb, 0x19, 0x03, 0xea, 0xed, 0xb6, 0xa7, 0xe6, 0x6a, 0xff, 0xdc, 0x6d, 0xb7, 0x3d, 0xec, 0xd6, - 0xf3, 0xb4, 0xdb, 0x0a, 0xbc, 0x96, 0x1f, 0xb4, 0xc7, 0x9f, 0xdb, 0xf1, 0xe7, 0x1a, 0xc9, 0xa3, 0xb0, 0x34, 0xd3, - 0xd4, 0x07, 0xe1, 0x70, 0xd3, 0x7b, 0xaf, 0x49, 0xdf, 0x67, 0xa1, 0xa0, 0x97, 0x95, 0x57, 0x5d, 0x63, 0x4d, 0x2a, - 0x1f, 0x5c, 0xff, 0x0f, 0xaf, 0x02, 0x3c, 0xe2, 0xe4, 0xce, 0xde, 0xdb, 0xa0, 0xd2, 0x6b, 0x0b, 0x47, 0x8a, 0xd0, - 0x03, 0x92, 0xb0, 0xaf, 0x65, 0x2d, 0x6e, 0xf3, 0x2c, 0x7b, 0x98, 0x3e, 0xbd, 0x4a, 0x5d, 0xab, 0x7b, 0xbb, 0xcc, - 0x32, 0x7d, 0xe0, 0xd5, 0x14, 0x07, 0x34, 0xea, 0xa2, 0x7d, 0xd7, 0x59, 0x55, 0x81, 0x97, 0x07, 0x5c, 0x9f, 0xcf, - 0xb8, 0x0b, 0x37, 0x77, 0x55, 0xfb, 0x9b, 0xf4, 0x2c, 0x9b, 0x67, 0x8b, 0xed, 0x36, 0xc4, 0xbf, 0x5d, 0x2d, 0xb2, - 0x34, 0x79, 0x0e, 0x3a, 0x3c, 0x8c, 0xdc, 0xc3, 0x54, 0xe3, 0x9c, 0xcd, 0xff, 0xb2, 0xf2, 0x9c, 0x04, 0x4e, 0x81, - 0x5e, 0xcc, 0x1e, 0x81, 0x0c, 0x46, 0x3b, 0xf5, 0x57, 0x33, 0xb5, 0x66, 0x20, 0xfa, 0x56, 0x15, 0x01, 0x8e, 0x2e, - 0x36, 0x12, 0x8d, 0x2c, 0x38, 0x69, 0x08, 0x58, 0x6c, 0x9a, 0xf2, 0x3e, 0x18, 0xda, 0x56, 0x97, 0xf7, 0xce, 0x92, - 0xe6, 0xb8, 0x0e, 0xac, 0x6d, 0xbf, 0x1e, 0x62, 0x5d, 0x76, 0xbd, 0x40, 0xee, 0x97, 0x37, 0xb4, 0x37, 0x6e, 0x12, - 0x98, 0xb5, 0x4d, 0x63, 0x18, 0x3f, 0x53, 0xfa, 0x4f, 0x6a, 0x70, 0xa5, 0xf1, 0xd3, 0x5c, 0x5b, 0x25, 0x98, 0x7d, - 0xe3, 0xf8, 0x0e, 0x40, 0x38, 0x36, 0x97, 0x1e, 0x9f, 0x65, 0x0e, 0x3d, 0x06, 0xa2, 0xa3, 0x3f, 0x2a, 0xec, 0x47, - 0x66, 0xf7, 0xba, 0x01, 0xf0, 0xe6, 0x75, 0xbb, 0xa0, 0x79, 0xb1, 0x80, 0x40, 0xa2, 0x4e, 0x79, 0xa5, 0xe1, 0x33, - 0x63, 0x76, 0x05, 0x64, 0xa8, 0x24, 0x60, 0x93, 0xd4, 0x75, 0x2e, 0xc4, 0xb2, 0xc3, 0xd2, 0x7c, 0x24, 0x61, 0x27, - 0x21, 0xa0, 0xbd, 0x06, 0xc1, 0x2c, 0xf8, 0xaf, 0x60, 0x50, 0x0c, 0x82, 0x28, 0x88, 0x82, 0x80, 0x0c, 0x4a, 0xf8, - 0x85, 0x38, 0x63, 0x04, 0x63, 0x94, 0x40, 0x87, 0xdf, 0x71, 0xe6, 0x32, 0x22, 0x2f, 0xbc, 0x30, 0x96, 0x76, 0x00, - 0x2e, 0x84, 0xc8, 0x79, 0x8c, 0x3e, 0x16, 0xef, 0x38, 0xcb, 0x08, 0x7d, 0xe7, 0x9c, 0xca, 0x8f, 0xb8, 0x17, 0xdc, - 0x6e, 0x77, 0xd8, 0x5e, 0xf2, 0x30, 0xa3, 0xbd, 0x31, 0x7d, 0xc7, 0x49, 0x94, 0x79, 0xce, 0xc3, 0x1c, 0x7a, 0x56, - 0x1b, 0xd6, 0x8a, 0x6a, 0x72, 0x83, 0x62, 0x5d, 0x64, 0x99, 0xac, 0x0c, 0x57, 0xce, 0x69, 0x85, 0xeb, 0xce, 0xac, - 0x17, 0x90, 0x94, 0x55, 0x8a, 0xa5, 0x33, 0xe1, 0xab, 0x4d, 0xcb, 0x9e, 0xb7, 0x4e, 0x21, 0xa7, 0x21, 0x32, 0xfa, - 0xa1, 0x25, 0xa0, 0x9a, 0x56, 0x5c, 0xd5, 0xe0, 0xb2, 0xab, 0xdb, 0xc3, 0x75, 0x7b, 0x74, 0x33, 0x3e, 0x40, 0x8c, - 0x38, 0x8e, 0x2d, 0x03, 0xbb, 0x09, 0x8b, 0x67, 0x63, 0x7d, 0x5f, 0x76, 0xe9, 0xad, 0xad, 0xc5, 0x21, 0xac, 0x3d, - 0x67, 0x85, 0x84, 0x00, 0x69, 0xa9, 0x2b, 0xdd, 0x6e, 0x83, 0x00, 0x06, 0xb8, 0xdf, 0xef, 0x01, 0xd7, 0xaa, 0xd9, - 0x49, 0x7d, 0x6b, 0x36, 0xc4, 0x5e, 0x52, 0x78, 0x0c, 0x44, 0xa9, 0xf8, 0xcf, 0x20, 0xa0, 0x78, 0xee, 0x86, 0x60, - 0x5f, 0xc9, 0x4e, 0x36, 0x65, 0xbf, 0xff, 0xbc, 0xc4, 0x07, 0x94, 0x83, 0x82, 0x58, 0x57, 0xc5, 0xad, 0xd0, 0xec, - 0x93, 0xfc, 0x10, 0xc7, 0x22, 0xcf, 0x42, 0x4b, 0x58, 0x6a, 0x4d, 0x58, 0xb8, 0x64, 0xa4, 0x83, 0x38, 0x68, 0x48, - 0xe7, 0x60, 0xd5, 0x36, 0xd8, 0x70, 0xaf, 0xf7, 0xb2, 0x0a, 0x2b, 0x9a, 0x39, 0xc3, 0xf2, 0xde, 0x01, 0x00, 0xeb, - 0xf5, 0x70, 0xa1, 0x38, 0x64, 0xc2, 0x43, 0x9f, 0xc4, 0x97, 0x86, 0x5d, 0x9f, 0x29, 0x59, 0xc9, 0x68, 0x34, 0xaa, - 0x1b, 0x29, 0xf9, 0x30, 0xdf, 0xbd, 0x69, 0xa1, 0x56, 0x8a, 0x38, 0xe5, 0x29, 0x58, 0x7a, 0x6b, 0x4a, 0x37, 0x5f, - 0xd0, 0x15, 0x2f, 0x52, 0xf9, 0xd3, 0x41, 0x9b, 0xf4, 0x88, 0x6b, 0xe6, 0xeb, 0x2c, 0xcc, 0xf0, 0x43, 0xc0, 0x47, - 0xf3, 0x30, 0xb3, 0xe9, 0x0a, 0x96, 0x16, 0xc4, 0x91, 0x71, 0xc9, 0x43, 0x9b, 0x07, 0xb0, 0xfe, 0xf4, 0x21, 0x89, - 0x9f, 0xc2, 0xcf, 0x99, 0x4e, 0xeb, 0xf8, 0x0c, 0x67, 0x33, 0x2a, 0xe4, 0x8d, 0xa0, 0xfd, 0x1a, 0x12, 0x89, 0x46, - 0x36, 0xf6, 0x18, 0x8a, 0xd6, 0xdd, 0x06, 0xae, 0xfc, 0x86, 0xde, 0xb9, 0x34, 0x08, 0xb0, 0xad, 0xb1, 0x18, 0x38, - 0xe3, 0xf1, 0x07, 0xaa, 0x6a, 0xf4, 0x15, 0x45, 0x37, 0x4c, 0x26, 0x9a, 0x3b, 0x8e, 0xed, 0xa8, 0x76, 0x95, 0xad, - 0x58, 0x61, 0x6c, 0x79, 0xed, 0x5b, 0x5a, 0x9a, 0x12, 0x50, 0x0d, 0x86, 0x3b, 0x01, 0x7c, 0x46, 0x84, 0x3c, 0x10, - 0x44, 0xf7, 0xc1, 0x41, 0x73, 0x96, 0xe0, 0x79, 0x18, 0xc2, 0x1f, 0x58, 0x38, 0xb0, 0x2c, 0x65, 0x3f, 0x97, 0xd3, - 0x18, 0xce, 0xdd, 0x5c, 0xee, 0xf0, 0xd9, 0x12, 0x14, 0x79, 0x72, 0x4e, 0xf5, 0xe5, 0x2b, 0xf7, 0xf6, 0x7b, 0x4c, - 0x30, 0x8f, 0x9e, 0x6d, 0xf8, 0xad, 0xa6, 0xdb, 0xf8, 0xc2, 0xda, 0x81, 0x13, 0xe6, 0xc2, 0x69, 0x2e, 0xb6, 0x4b, - 0x0d, 0x71, 0xd7, 0x78, 0x42, 0x84, 0x57, 0x8a, 0x58, 0x64, 0x9e, 0x4c, 0xc7, 0x60, 0x63, 0xc8, 0x36, 0x95, 0xcf, - 0x94, 0x42, 0xbc, 0x9a, 0xca, 0x0b, 0x53, 0x2b, 0x95, 0x55, 0x1a, 0x61, 0xa6, 0x80, 0x45, 0x95, 0x81, 0xcf, 0x7e, - 0x8d, 0x14, 0xd7, 0xd4, 0xf3, 0x17, 0x2e, 0xdf, 0x4c, 0xb7, 0xd9, 0x7c, 0xfa, 0x32, 0x8f, 0xaf, 0xb6, 0xdb, 0xb0, - 0xfb, 0x05, 0x98, 0x5f, 0x56, 0x52, 0xa3, 0x06, 0x4e, 0x0f, 0x21, 0xfa, 0x39, 0xef, 0xc9, 0x39, 0xb1, 0x9c, 0x5c, - 0xbb, 0x79, 0xb3, 0x9d, 0x14, 0x2d, 0xb0, 0x80, 0x13, 0x17, 0xe9, 0x40, 0x4b, 0x05, 0xa7, 0x2c, 0xe3, 0x9d, 0x4d, - 0x6f, 0x29, 0x15, 0x5e, 0x2d, 0x14, 0x09, 0xa9, 0xed, 0xbd, 0xc4, 0x8c, 0x1a, 0x70, 0x4e, 0xf2, 0x0e, 0x02, 0x4e, - 0x6a, 0xaa, 0xb1, 0x46, 0x71, 0xaa, 0x13, 0x9c, 0x57, 0x6a, 0xe8, 0x12, 0xe5, 0xc4, 0x6d, 0xb7, 0x55, 0xd1, 0x42, - 0x7d, 0x3c, 0xc8, 0x59, 0x22, 0x8f, 0x07, 0x14, 0xba, 0xc8, 0xa3, 0x21, 0x5f, 0x90, 0x52, 0xad, 0x1c, 0xa5, 0x5a, - 0xdd, 0x95, 0x0c, 0x14, 0x72, 0x15, 0xe4, 0x0d, 0x31, 0xee, 0x5a, 0x99, 0xb7, 0xb8, 0x72, 0x42, 0x4a, 0x93, 0xf0, - 0xb9, 0xa5, 0x18, 0x58, 0xc1, 0xde, 0x98, 0xba, 0xc2, 0x25, 0x42, 0xdb, 0xdd, 0x86, 0x98, 0x64, 0xb0, 0x6e, 0xb6, - 0xdb, 0x57, 0x65, 0x38, 0xcf, 0x16, 0x54, 0x8c, 0xb2, 0x14, 0x21, 0xc4, 0xb4, 0x87, 0xae, 0xe9, 0x82, 0x9e, 0x18, - 0x6a, 0xdb, 0xe3, 0x24, 0xe9, 0x62, 0x4d, 0x92, 0x18, 0xc5, 0x17, 0xa2, 0x94, 0x6b, 0x8d, 0x10, 0x3c, 0xdc, 0xff, - 0x48, 0x21, 0x86, 0x9b, 0x5e, 0x77, 0xbf, 0xee, 0xdc, 0x10, 0xff, 0x80, 0x40, 0x02, 0x05, 0x7b, 0x55, 0x8e, 0x2e, - 0xb2, 0x22, 0xc5, 0x9d, 0x2a, 0xa3, 0xe2, 0xca, 0x75, 0xe0, 0xb7, 0xdc, 0xf0, 0xaf, 0x86, 0x28, 0x40, 0x5c, 0xe3, - 0x4a, 0x31, 0x9e, 0xb5, 0xb5, 0x14, 0xc9, 0x28, 0x36, 0x24, 0x2a, 0x9c, 0xa8, 0xe8, 0x2e, 0x4f, 0xa3, 0x7b, 0x68, - 0xd7, 0x20, 0xb8, 0x6a, 0xee, 0x6c, 0xa4, 0xf9, 0x82, 0x10, 0x39, 0x01, 0x02, 0x36, 0xaa, 0x3e, 0xb5, 0x56, 0xd5, - 0xc3, 0xac, 0xf2, 0xb9, 0x3a, 0x88, 0x57, 0x15, 0xf0, 0xb0, 0xce, 0xf6, 0xbe, 0xaa, 0x1c, 0xd6, 0x06, 0xdf, 0x6e, - 0xb7, 0xab, 0x6a, 0x1e, 0x04, 0x0e, 0xa3, 0xf9, 0x9d, 0x94, 0x98, 0xf7, 0xc6, 0x14, 0x56, 0xbc, 0xeb, 0xd2, 0xd6, - 0x4d, 0x6a, 0x8d, 0x05, 0xea, 0x0e, 0xd7, 0x07, 0x3c, 0x4f, 0x81, 0xa3, 0x1d, 0x15, 0x53, 0x61, 0x74, 0xe5, 0xd8, - 0x95, 0x0a, 0x03, 0x43, 0xff, 0x90, 0xb2, 0x0d, 0x98, 0xe3, 0x81, 0xb5, 0x0d, 0xfa, 0x29, 0x49, 0x2d, 0xcc, 0x18, - 0x8d, 0x59, 0xc4, 0xba, 0x8e, 0x8e, 0xb8, 0x8a, 0xde, 0xce, 0xa3, 0xbf, 0x3d, 0x1d, 0xd3, 0x32, 0x2e, 0x52, 0x71, - 0x0d, 0x2a, 0x08, 0x50, 0x86, 0xa0, 0xe1, 0xbf, 0xa2, 0x06, 0xa0, 0x41, 0xb0, 0x03, 0xf0, 0x8f, 0x4e, 0xa7, 0x41, - 0x53, 0x93, 0x8b, 0x49, 0x2a, 0x8b, 0x9c, 0xb5, 0xa1, 0xcc, 0x64, 0x72, 0x48, 0x1e, 0x17, 0x80, 0xe7, 0x88, 0xcd, - 0x92, 0x36, 0x17, 0x72, 0xb3, 0xc9, 0xd7, 0x92, 0x1d, 0xb9, 0xf3, 0x8a, 0xd6, 0x6b, 0x51, 0xd9, 0x49, 0xcc, 0x17, - 0xd3, 0x3b, 0x23, 0x0c, 0x9c, 0xea, 0xd6, 0xdc, 0xee, 0x40, 0xa7, 0x99, 0xfa, 0x74, 0x6e, 0x02, 0xc4, 0x01, 0x86, - 0xeb, 0x6e, 0x7e, 0xbb, 0x20, 0xf4, 0x8e, 0xdd, 0x19, 0xb1, 0xea, 0xad, 0x91, 0x8b, 0xe8, 0xb4, 0xdb, 0xc1, 0x04, - 0x2e, 0xe3, 0xac, 0x34, 0x2f, 0x94, 0xba, 0xa1, 0xec, 0x68, 0x9b, 0x30, 0x9f, 0x77, 0xb4, 0x1b, 0x2e, 0xf8, 0x46, - 0xac, 0x63, 0xdd, 0x90, 0xa6, 0x12, 0x3d, 0x3a, 0x50, 0xdb, 0x21, 0xa0, 0x39, 0x1b, 0xd3, 0x25, 0x40, 0x6d, 0xc2, - 0x7e, 0x59, 0x83, 0x59, 0xca, 0x25, 0xf4, 0xb5, 0xdb, 0x27, 0xf9, 0x52, 0xf6, 0xa4, 0x72, 0x96, 0x28, 0xf8, 0x72, - 0xa4, 0xe0, 0x95, 0x95, 0xf3, 0x58, 0xcf, 0x21, 0xe0, 0xb1, 0xc8, 0x12, 0x9d, 0x93, 0xe2, 0x0a, 0x94, 0xa9, 0x70, - 0x04, 0xea, 0xaa, 0x11, 0x4b, 0x38, 0xc0, 0xed, 0xc5, 0xd3, 0x80, 0x50, 0x90, 0xea, 0xae, 0xcd, 0x8a, 0xbc, 0x63, - 0x27, 0x9b, 0x3b, 0x30, 0x8b, 0xad, 0xd7, 0x55, 0xeb, 0x2b, 0x93, 0x6c, 0x3f, 0x6e, 0x08, 0xb6, 0xdd, 0x91, 0xf2, - 0x85, 0x77, 0xf4, 0x96, 0x6c, 0x6e, 0xfb, 0xfd, 0x10, 0xfa, 0x43, 0xa8, 0xea, 0xd0, 0x5d, 0x67, 0x87, 0xee, 0x5c, - 0xe6, 0xd7, 0xe8, 0xf9, 0xa4, 0x37, 0xc4, 0x07, 0x34, 0xd1, 0xa2, 0xab, 0xf8, 0x1e, 0x36, 0x75, 0x54, 0x53, 0x59, - 0x79, 0x94, 0x50, 0x50, 0x01, 0x67, 0xbc, 0x3a, 0xe3, 0x18, 0xdb, 0x54, 0x3d, 0xbd, 0x53, 0xbc, 0xda, 0x5a, 0xaf, - 0xcd, 0x6a, 0x7d, 0x01, 0x16, 0x01, 0x17, 0x3c, 0xba, 0x56, 0xb4, 0xe4, 0xca, 0x61, 0xea, 0xcf, 0x71, 0x54, 0x82, - 0xcb, 0x38, 0xcb, 0x79, 0x1a, 0xd0, 0x4b, 0xbf, 0xff, 0xa1, 0xb2, 0x95, 0x5a, 0x7a, 0x67, 0xee, 0x4d, 0x48, 0x36, - 0xff, 0x63, 0x03, 0xf5, 0x3a, 0xc4, 0x88, 0xa8, 0x7a, 0x41, 0xbf, 0x65, 0x10, 0x1b, 0x33, 0xa8, 0xd6, 0x49, 0xc2, - 0xab, 0x2a, 0xd0, 0x4a, 0xad, 0x35, 0x5b, 0xeb, 0xf3, 0xec, 0x11, 0x3b, 0x79, 0xd4, 0x63, 0xec, 0x8e, 0xd0, 0x44, - 0xe9, 0x84, 0x74, 0x8d, 0x91, 0xa3, 0x05, 0x52, 0x1d, 0x8a, 0xb2, 0xcb, 0xf0, 0x2d, 0x0a, 0x59, 0xda, 0xfb, 0x5c, - 0x9f, 0xc8, 0xf2, 0x1b, 0x65, 0x74, 0x11, 0xc9, 0x44, 0x90, 0x8d, 0xdf, 0x22, 0x60, 0x2f, 0x34, 0x3b, 0x20, 0x9b, - 0x25, 0x3b, 0xa3, 0xe7, 0xc6, 0x04, 0x06, 0x5e, 0xbf, 0x95, 0x89, 0x7a, 0x94, 0x25, 0xd1, 0x95, 0x46, 0x2e, 0xf7, - 0x21, 0x89, 0xce, 0x43, 0xe2, 0xe6, 0x86, 0xa5, 0x75, 0x13, 0xa2, 0x98, 0x59, 0x6f, 0x78, 0xd9, 0xdd, 0x47, 0xde, - 0xb6, 0xd2, 0x3e, 0xd5, 0x77, 0x26, 0x8d, 0x4c, 0xa1, 0xaf, 0xc3, 0x49, 0xbf, 0x0f, 0x7f, 0x15, 0xfd, 0xc0, 0x5b, - 0x0a, 0xfe, 0x62, 0x8f, 0x48, 0x93, 0xb0, 0x00, 0xe0, 0x08, 0x73, 0x5e, 0xfb, 0x13, 0xf8, 0x88, 0x9d, 0x6c, 0x1e, - 0x85, 0x67, 0xde, 0xcc, 0xdd, 0x87, 0x78, 0xa9, 0x4a, 0x7a, 0xce, 0x3c, 0xe9, 0x81, 0x58, 0x85, 0x7a, 0xbf, 0xde, - 0x31, 0xa3, 0x4f, 0x00, 0x22, 0x75, 0x67, 0x1c, 0x4a, 0xf1, 0x63, 0xdd, 0x65, 0xb2, 0x49, 0x59, 0x9b, 0x89, 0x92, - 0x2a, 0x12, 0x7f, 0x11, 0x40, 0xbf, 0x61, 0x38, 0x1a, 0x80, 0xf7, 0x56, 0x63, 0xaf, 0x87, 0xc6, 0x19, 0x53, 0x4d, - 0xcf, 0x36, 0x6a, 0x79, 0x5b, 0x0a, 0xa1, 0xc7, 0x22, 0xba, 0xb3, 0xc7, 0x62, 0x78, 0x46, 0xdf, 0x42, 0x85, 0xaf, - 0x43, 0x8c, 0xa6, 0x4b, 0x9a, 0x66, 0xba, 0x96, 0x5b, 0xe9, 0x96, 0xd0, 0x1c, 0xa3, 0xf8, 0x38, 0x6d, 0xbb, 0xa7, - 0x5a, 0x68, 0x4f, 0x28, 0x0f, 0xef, 0x68, 0x4d, 0x6f, 0x0d, 0x8b, 0x60, 0x91, 0x96, 0x9d, 0xfc, 0x84, 0x5e, 0x38, - 0x02, 0x93, 0xb2, 0xad, 0x01, 0xfc, 0x01, 0xf5, 0xc3, 0x59, 0x33, 0x35, 0x52, 0x0e, 0x47, 0xe1, 0x4b, 0x36, 0x20, - 0x57, 0x50, 0x8b, 0x35, 0x66, 0x27, 0x31, 0xe8, 0xa0, 0x76, 0x76, 0x87, 0x33, 0x29, 0x88, 0x64, 0x44, 0x73, 0x0b, - 0xf1, 0xf4, 0x0f, 0xd0, 0xf4, 0x41, 0x5a, 0x98, 0xd2, 0x35, 0x0a, 0x78, 0x40, 0xdf, 0xd4, 0xef, 0xe7, 0xf8, 0xdc, - 0x38, 0x96, 0x58, 0xd8, 0xe3, 0x25, 0xa1, 0x4b, 0x27, 0x6e, 0x14, 0x48, 0x9b, 0x2d, 0xab, 0x00, 0xac, 0x48, 0x02, - 0x8d, 0x48, 0xd0, 0x52, 0xc7, 0x8a, 0xcb, 0x36, 0x68, 0x40, 0x12, 0x15, 0x14, 0xb2, 0x44, 0x02, 0xf8, 0x61, 0x04, - 0x21, 0x8a, 0x62, 0x10, 0xf7, 0xaa, 0xe5, 0x15, 0x37, 0x54, 0x83, 0x13, 0x45, 0x30, 0xc1, 0x2a, 0x9d, 0x02, 0xb1, - 0x2d, 0xd6, 0x2b, 0xf0, 0xbc, 0xb4, 0x17, 0x49, 0x64, 0x09, 0xd0, 0x20, 0xcd, 0x95, 0x4e, 0xdb, 0xe5, 0xed, 0x88, - 0x96, 0x6a, 0x36, 0x77, 0x5e, 0x2c, 0x0c, 0xf7, 0x58, 0xbb, 0xdb, 0x81, 0xf6, 0xc2, 0x7a, 0x47, 0x44, 0x0d, 0x56, - 0x76, 0x6d, 0xbb, 0x36, 0x94, 0x86, 0xaa, 0x5e, 0x59, 0x26, 0xa0, 0xa6, 0xab, 0xb8, 0x5e, 0x46, 0xd9, 0x08, 0xfe, - 0x6c, 0xb7, 0xc1, 0x61, 0x00, 0x16, 0x90, 0xbf, 0xbc, 0xff, 0x29, 0xc2, 0xf0, 0x4c, 0xbf, 0xbc, 0xff, 0x69, 0xbb, - 0x7d, 0x3a, 0x1e, 0x6b, 0xae, 0xc0, 0xaa, 0x75, 0x80, 0x3f, 0xd0, 0x6c, 0x83, 0x59, 0xb2, 0xdb, 0xed, 0x53, 0xe0, - 0x20, 0x24, 0xdb, 0xa0, 0x77, 0xb1, 0x74, 0xe4, 0x92, 0xac, 0x86, 0xda, 0x91, 0x80, 0x55, 0xb7, 0xc3, 0x52, 0xec, - 0x52, 0x1f, 0x19, 0x82, 0x51, 0x2d, 0xfa, 0x17, 0x9d, 0x02, 0x4b, 0x0a, 0xa6, 0xab, 0xc1, 0xb2, 0xae, 0x57, 0x55, - 0x74, 0x78, 0x18, 0xaf, 0xb2, 0x51, 0x95, 0xc1, 0x36, 0xaf, 0x6e, 0xae, 0x00, 0x50, 0x21, 0xa0, 0xde, 0xbb, 0x75, - 0x91, 0xe9, 0x17, 0x0b, 0xba, 0xcc, 0x70, 0x4d, 0x82, 0xd9, 0x41, 0xce, 0x8d, 0x6e, 0x72, 0x4a, 0xcc, 0x03, 0xd8, - 0x1c, 0x6e, 0xb7, 0x1e, 0xbf, 0x70, 0x32, 0x7a, 0x3a, 0x5b, 0x66, 0xca, 0xa0, 0x93, 0xeb, 0xfd, 0x4f, 0x22, 0x27, - 0x0d, 0x15, 0x9f, 0x64, 0xfa, 0x22, 0x03, 0x3e, 0x8f, 0xbd, 0xa9, 0x42, 0x97, 0xe5, 0xf2, 0x5a, 0x03, 0x6c, 0x6c, - 0x76, 0x79, 0x3f, 0x4a, 0x39, 0x44, 0xa4, 0x08, 0x8c, 0xba, 0x66, 0x99, 0x11, 0xd7, 0xa6, 0xe2, 0xbe, 0xa5, 0x0a, - 0x7b, 0x53, 0x39, 0xce, 0x2a, 0x5c, 0x3b, 0xca, 0xf4, 0x26, 0x51, 0xf8, 0x02, 0x85, 0xa8, 0x1c, 0x8d, 0xe9, 0xac, - 0x40, 0x2a, 0x73, 0x98, 0x50, 0xcc, 0x61, 0xdf, 0xfd, 0x92, 0x5a, 0x73, 0x19, 0x57, 0xb8, 0xf7, 0xc2, 0x95, 0x99, - 0xdc, 0x09, 0x00, 0x45, 0x92, 0xb5, 0xff, 0xfc, 0x09, 0xa9, 0xf1, 0x3f, 0x53, 0xa5, 0x01, 0xe8, 0xfd, 0x0c, 0x35, - 0x59, 0x82, 0x80, 0xad, 0x98, 0xba, 0x68, 0xfa, 0x46, 0x32, 0xff, 0x01, 0x75, 0x3b, 0x15, 0xdb, 0xc8, 0xf8, 0x39, - 0x51, 0x4d, 0x4b, 0x9e, 0xae, 0x8b, 0x34, 0x2e, 0x92, 0xfb, 0x88, 0x37, 0x53, 0x2c, 0x89, 0x55, 0x9a, 0x02, 0xfd, - 0xec, 0x77, 0xe1, 0xa7, 0xd2, 0x33, 0x01, 0xa7, 0x85, 0xbb, 0xad, 0x9c, 0xcd, 0x64, 0x18, 0x67, 0x64, 0xca, 0x25, - 0x62, 0xb7, 0xd1, 0xf7, 0xe8, 0x13, 0xfc, 0xc9, 0xd1, 0x13, 0x42, 0xef, 0xc4, 0xb4, 0x40, 0x50, 0xba, 0x22, 0x35, - 0xae, 0x9a, 0xd8, 0xaf, 0x29, 0x44, 0x71, 0xa8, 0x18, 0x84, 0xee, 0xd4, 0xed, 0x93, 0x7c, 0x9f, 0x29, 0xfb, 0x8d, - 0x2e, 0x5b, 0x90, 0x4d, 0x05, 0x1d, 0x13, 0xd6, 0xdb, 0xd3, 0xd9, 0xb3, 0x33, 0xe7, 0x37, 0x68, 0xc2, 0x41, 0x75, - 0x03, 0xed, 0x2a, 0xc9, 0x34, 0x46, 0xb1, 0x59, 0x8c, 0xb5, 0x1b, 0x13, 0x11, 0x04, 0x9d, 0x2e, 0x66, 0x61, 0xbb, - 0x9d, 0x10, 0x5f, 0x02, 0x09, 0x14, 0xb8, 0x72, 0x51, 0x4e, 0x42, 0x22, 0x2f, 0x64, 0x6a, 0xb2, 0x6e, 0x04, 0x0b, - 0xd4, 0x1a, 0x3b, 0x0a, 0xe8, 0x29, 0x37, 0x4f, 0x01, 0x7d, 0x5f, 0xb2, 0x53, 0x3e, 0x08, 0x86, 0x18, 0x5f, 0x35, - 0xa0, 0xb7, 0x42, 0x3e, 0x82, 0x87, 0x30, 0xb0, 0x5c, 0xf4, 0x65, 0xc9, 0x10, 0x56, 0xe8, 0xcf, 0x94, 0x4d, 0xbe, - 0xfe, 0xc6, 0xce, 0xef, 0xb5, 0x12, 0xb3, 0x83, 0x50, 0xdc, 0x5c, 0x4f, 0x80, 0xf8, 0xd5, 0xfc, 0x1a, 0xac, 0xab, - 0x95, 0xc4, 0xdb, 0x91, 0x3c, 0x54, 0xae, 0x1c, 0xdd, 0x7c, 0x52, 0xe9, 0x4f, 0x20, 0x48, 0x8d, 0x95, 0x94, 0xdb, - 0xef, 0x3e, 0x0a, 0x5b, 0x11, 0x8c, 0x16, 0x20, 0xd6, 0xed, 0xad, 0xe4, 0xc2, 0x17, 0xfe, 0x63, 0x9d, 0xef, 0x31, - 0x76, 0x88, 0x38, 0xc3, 0xe9, 0xf7, 0xc1, 0xb0, 0xbd, 0x5b, 0x99, 0x36, 0x24, 0xba, 0x96, 0x1f, 0x01, 0xfd, 0x1f, - 0xab, 0xf1, 0x3b, 0x45, 0x49, 0x5f, 0x12, 0xe7, 0x08, 0x57, 0xc4, 0x2b, 0x34, 0xd5, 0xeb, 0x8d, 0x1b, 0xfa, 0xa6, - 0xd4, 0x2f, 0x94, 0x82, 0xc3, 0xbc, 0xd5, 0x0a, 0x0f, 0x3c, 0xf3, 0xfe, 0xa8, 0x3c, 0x41, 0xf7, 0x6f, 0xb8, 0x37, - 0xfe, 0xa8, 0x58, 0x86, 0x37, 0xe5, 0x2c, 0xd3, 0x77, 0xb8, 0xdb, 0xac, 0x48, 0xc5, 0x2d, 0x63, 0xc1, 0xba, 0x90, - 0xe6, 0xab, 0x69, 0x30, 0xdb, 0x34, 0x91, 0x4c, 0xb6, 0xdf, 0xff, 0xe5, 0x9d, 0xb0, 0xd9, 0x20, 0x38, 0xab, 0x45, - 0x19, 0x5f, 0xf1, 0x60, 0xaa, 0x54, 0x14, 0x59, 0xd6, 0xef, 0x67, 0x80, 0x0c, 0x63, 0xb5, 0x77, 0xf0, 0x64, 0xa8, - 0x99, 0x0e, 0x71, 0x6d, 0x74, 0x16, 0xf0, 0x56, 0x8f, 0xe6, 0x69, 0x0d, 0xbb, 0xcc, 0x55, 0x52, 0xfc, 0xd1, 0x92, - 0x64, 0x63, 0xfd, 0x9e, 0x0c, 0xdb, 0xc8, 0x67, 0xae, 0x01, 0x63, 0xe6, 0x56, 0xc8, 0x20, 0x77, 0x3d, 0x60, 0x84, - 0x90, 0x08, 0x54, 0xd6, 0x62, 0xe2, 0xbc, 0xd2, 0xe1, 0x1f, 0x6d, 0x60, 0x9c, 0x18, 0x03, 0xe3, 0x7c, 0x14, 0x21, - 0xa7, 0xa7, 0x7c, 0x90, 0x78, 0xb3, 0xf5, 0x97, 0x2c, 0x91, 0xde, 0x08, 0x42, 0x2f, 0xe0, 0xf7, 0xb8, 0xc5, 0x03, - 0x79, 0xc1, 0x29, 0xed, 0xcd, 0xe9, 0xf0, 0x65, 0x49, 0x86, 0x7f, 0x82, 0x77, 0x57, 0x6c, 0x2e, 0xcb, 0x09, 0x2c, - 0xee, 0xd8, 0x29, 0x9e, 0xe6, 0xb2, 0xc5, 0x09, 0x71, 0x88, 0x45, 0xee, 0x12, 0x0b, 0x18, 0x51, 0xcd, 0x68, 0xfc, - 0x78, 0xf6, 0xf6, 0x8d, 0xc2, 0x6c, 0xca, 0xdd, 0x0f, 0x60, 0x44, 0x95, 0xb4, 0xdd, 0x0c, 0xf8, 0x72, 0x84, 0x06, - 0xdb, 0xa9, 0x1d, 0xec, 0x7e, 0x5f, 0xa7, 0x9d, 0x14, 0x4e, 0x36, 0x2b, 0x06, 0xdd, 0x51, 0xda, 0x2c, 0xa5, 0x41, - 0x6d, 0x57, 0xe1, 0x68, 0x3e, 0xab, 0xc5, 0xaa, 0xce, 0x87, 0xe1, 0x92, 0xc6, 0x46, 0x56, 0x6e, 0x76, 0x13, 0x8e, - 0x6c, 0x02, 0x5c, 0x9f, 0x84, 0xb2, 0xf2, 0xe7, 0xa0, 0x05, 0x9d, 0x09, 0x1c, 0xd1, 0x76, 0x1b, 0x42, 0x04, 0x8e, - 0x72, 0x38, 0x99, 0x85, 0xe5, 0x70, 0x28, 0x07, 0xbe, 0x24, 0x24, 0x7a, 0x53, 0xce, 0xb3, 0x85, 0x44, 0xec, 0x71, - 0x77, 0xd2, 0xaf, 0xa5, 0xe4, 0x94, 0x7b, 0x7f, 0x54, 0x64, 0xf3, 0x5b, 0x8a, 0x31, 0x07, 0xad, 0x66, 0x33, 0x03, - 0x09, 0xeb, 0x69, 0x4d, 0xe4, 0x3a, 0x32, 0xb3, 0x01, 0xaa, 0x58, 0x34, 0x85, 0x05, 0x75, 0x8b, 0x23, 0xd6, 0xd3, - 0x7a, 0x0f, 0x2a, 0x40, 0x54, 0x0b, 0x76, 0x63, 0xb8, 0xd6, 0x5e, 0x56, 0xa1, 0xa0, 0x9c, 0xf8, 0xcc, 0x8c, 0x11, - 0x0d, 0x96, 0x20, 0x24, 0x8d, 0xab, 0xfa, 0xb5, 0x48, 0xb3, 0xcb, 0x0c, 0x10, 0x13, 0xac, 0xff, 0x9c, 0xf0, 0xde, - 0x3c, 0x93, 0xf3, 0xd2, 0x95, 0x38, 0x33, 0x30, 0x1f, 0x5d, 0x6f, 0x69, 0x49, 0xa2, 0x12, 0x68, 0x94, 0xab, 0xe5, - 0xf9, 0xfb, 0x8e, 0x55, 0xc8, 0xee, 0x87, 0x53, 0x69, 0x3b, 0xc4, 0x4f, 0x58, 0x4d, 0x9c, 0xd3, 0xba, 0x96, 0x22, - 0x8d, 0x8e, 0xb6, 0x01, 0x31, 0x6c, 0xd9, 0xb7, 0xc8, 0xe1, 0x03, 0x83, 0x0a, 0x2b, 0xf9, 0x29, 0x70, 0xf8, 0x8c, - 0x81, 0xa4, 0xab, 0x45, 0x70, 0x35, 0x3a, 0xc2, 0x8a, 0x32, 0xb5, 0xc4, 0x14, 0x12, 0xdd, 0x7a, 0xa1, 0x35, 0x86, - 0x51, 0x76, 0x15, 0xf9, 0xdf, 0xab, 0xee, 0xfd, 0x51, 0x6d, 0xb7, 0x30, 0xc9, 0x8e, 0xc7, 0x15, 0x6c, 0x6a, 0xd4, - 0x0a, 0xe1, 0xec, 0x9c, 0xd6, 0xa8, 0x1d, 0xeb, 0x85, 0x05, 0x90, 0x07, 0xb0, 0x15, 0xf1, 0x28, 0x83, 0x60, 0x6f, - 0xca, 0x79, 0xb5, 0xb0, 0xa2, 0x1c, 0x21, 0xf1, 0xbe, 0xc4, 0x28, 0xe5, 0x70, 0x15, 0x0b, 0x4b, 0x86, 0xfc, 0xea, - 0xe8, 0xb2, 0x14, 0xd7, 0x20, 0x29, 0xd1, 0x0c, 0x95, 0xe1, 0x75, 0x71, 0xd5, 0x16, 0x84, 0xf6, 0x2e, 0x2a, 0x50, - 0x47, 0x82, 0xe0, 0xc5, 0xab, 0x21, 0x66, 0x1b, 0xb9, 0xbb, 0xa2, 0xbd, 0xe4, 0x80, 0x5a, 0xdd, 0xb5, 0x5d, 0x6f, - 0xd2, 0x36, 0xdb, 0x88, 0x0b, 0xff, 0x82, 0xd2, 0x4f, 0xf9, 0xa0, 0x74, 0xa9, 0x04, 0x6e, 0x7c, 0xb9, 0xc9, 0xb2, - 0xcb, 0x7b, 0x5c, 0xfa, 0xb5, 0x37, 0x7e, 0xfd, 0x7e, 0x4f, 0x2e, 0x04, 0x2f, 0x15, 0x98, 0x6f, 0x97, 0x99, 0xaa, - 0xb5, 0xa6, 0xd4, 0x5c, 0x82, 0x6b, 0x6b, 0x3f, 0x82, 0x8a, 0xb8, 0xae, 0xc8, 0x64, 0x72, 0x80, 0x0e, 0x9c, 0xac, - 0x70, 0x2b, 0x0b, 0xf0, 0xd8, 0x09, 0xc8, 0x76, 0xcb, 0xc3, 0x40, 0x1d, 0x3a, 0x81, 0xbb, 0x25, 0xcf, 0x90, 0x59, - 0x33, 0x8f, 0x3f, 0x2b, 0xc1, 0x3f, 0xb6, 0xe0, 0x27, 0x14, 0x77, 0x1a, 0x99, 0x7f, 0x2b, 0xad, 0x5b, 0xdc, 0xbf, - 0x93, 0x69, 0x42, 0x51, 0x99, 0xd0, 0xb8, 0x95, 0xfe, 0x4b, 0x07, 0x4b, 0x92, 0xd9, 0x3f, 0x08, 0xf8, 0x60, 0xe6, - 0x3d, 0x31, 0xef, 0x49, 0x73, 0xba, 0xb5, 0x82, 0x21, 0x40, 0xa1, 0x9f, 0x93, 0xb9, 0xa6, 0xea, 0xf9, 0xe7, 0x35, - 0x5f, 0x73, 0xbf, 0xc5, 0x26, 0xe9, 0x81, 0x06, 0x3b, 0x79, 0x14, 0xa5, 0xb0, 0x12, 0x75, 0xae, 0x25, 0xea, 0x55, - 0xc3, 0x32, 0x54, 0x27, 0x38, 0x35, 0x4f, 0xd5, 0xb0, 0xfb, 0x89, 0x68, 0xad, 0x24, 0x2d, 0x31, 0x60, 0xad, 0x23, - 0x0f, 0xc9, 0xed, 0x5a, 0xc7, 0x9d, 0x86, 0xba, 0x34, 0x89, 0x12, 0x60, 0x84, 0x0b, 0x70, 0x04, 0xfd, 0x54, 0x86, - 0x1c, 0xae, 0xa9, 0x52, 0xbf, 0xa0, 0x28, 0x79, 0xe2, 0x28, 0x6a, 0x95, 0x22, 0xdd, 0x7c, 0x94, 0x63, 0x37, 0x5c, - 0xe3, 0x84, 0x9c, 0x68, 0xa1, 0xbf, 0x3d, 0x96, 0x72, 0x86, 0x16, 0x0f, 0xf2, 0x04, 0xeb, 0xe5, 0x2d, 0x05, 0x8a, - 0x3e, 0xba, 0x8c, 0xba, 0xe6, 0x15, 0xda, 0xbe, 0x2c, 0xfb, 0xfd, 0xdc, 0xd4, 0x93, 0xb2, 0x93, 0xcd, 0x52, 0xef, - 0x43, 0x54, 0x4c, 0xe1, 0xae, 0x4f, 0x14, 0x7f, 0x15, 0xaa, 0xab, 0xb6, 0xc8, 0xf9, 0x88, 0x23, 0x2e, 0x46, 0x4e, - 0x9a, 0x9f, 0xe5, 0xd4, 0x4b, 0x71, 0xbf, 0xac, 0xe4, 0xd7, 0x4a, 0x5b, 0x31, 0x5a, 0xa0, 0xfe, 0x54, 0xaa, 0xbc, - 0x5f, 0x94, 0x00, 0xf7, 0x54, 0xb1, 0x37, 0x60, 0x5f, 0xa1, 0x10, 0x7e, 0x5b, 0x02, 0xfe, 0x8d, 0xe4, 0x06, 0x8c, - 0x02, 0x03, 0x8c, 0x26, 0xdb, 0x73, 0x9a, 0xc0, 0x01, 0x57, 0x29, 0x15, 0x05, 0xad, 0xf4, 0xd0, 0x50, 0x53, 0x18, - 0x3d, 0x43, 0x19, 0xb7, 0xcc, 0xec, 0xdc, 0x18, 0x3b, 0x2d, 0xf0, 0x3c, 0x7f, 0x3e, 0x27, 0xf4, 0xb0, 0x56, 0x07, - 0xa9, 0xd1, 0x49, 0x74, 0x7f, 0xec, 0xc2, 0xc9, 0xf5, 0xc2, 0x59, 0x36, 0x2c, 0x81, 0xee, 0xc0, 0x05, 0x31, 0xee, - 0xf7, 0x73, 0x38, 0x32, 0xf5, 0xc8, 0x97, 0x2c, 0xa7, 0x31, 0x5b, 0x52, 0xe5, 0x69, 0x77, 0x55, 0x87, 0x39, 0x5d, - 0x1a, 0x19, 0x6f, 0xca, 0x8a, 0x79, 0x0e, 0x1a, 0x49, 0xf8, 0xd3, 0x6d, 0xed, 0x92, 0xce, 0x97, 0x90, 0x01, 0xfe, - 0x80, 0x44, 0x14, 0xb1, 0xaf, 0xff, 0xad, 0xc6, 0x49, 0x3d, 0x51, 0xda, 0xb0, 0x84, 0xae, 0x99, 0xaa, 0x9f, 0x5e, - 0xb2, 0xb5, 0xb7, 0x14, 0xb6, 0xdb, 0xd0, 0x4f, 0x60, 0x8a, 0x73, 0x25, 0xd3, 0x4b, 0xd4, 0x49, 0x01, 0x15, 0x0b, - 0x2f, 0x71, 0xf9, 0xa5, 0x84, 0x42, 0x73, 0xe7, 0xcb, 0x85, 0x56, 0x62, 0x42, 0xab, 0xc4, 0xe7, 0x0f, 0x95, 0xfe, - 0x5a, 0x7b, 0xc4, 0xfd, 0x2b, 0x0d, 0x13, 0x5d, 0x24, 0x2a, 0x44, 0x67, 0xbf, 0x82, 0x2c, 0xa7, 0x02, 0x1c, 0xcb, - 0x33, 0xd1, 0xd0, 0x1f, 0x53, 0x88, 0x83, 0x0e, 0x0d, 0x7a, 0x57, 0x8a, 0xeb, 0xac, 0xe2, 0x21, 0xde, 0x13, 0x1c, - 0xcd, 0xe8, 0x7e, 0x83, 0x0f, 0x65, 0xed, 0xd1, 0xab, 0xc8, 0xc6, 0x51, 0xee, 0x37, 0xbf, 0x56, 0xe1, 0x1c, 0xa2, - 0x55, 0x2e, 0xa8, 0x52, 0x57, 0x5b, 0x00, 0x2a, 0xc7, 0xf6, 0xea, 0x11, 0x9c, 0x6e, 0xea, 0xfa, 0x56, 0x87, 0xd6, - 0x1c, 0x40, 0x98, 0x43, 0xb2, 0x69, 0xb8, 0xda, 0x01, 0xf6, 0x48, 0xac, 0xd7, 0x40, 0x63, 0xed, 0xd6, 0xec, 0xb4, - 0x47, 0x71, 0x98, 0xc8, 0x4c, 0x5b, 0xa4, 0x68, 0x73, 0xb7, 0x4e, 0x8b, 0xa2, 0x0d, 0x9a, 0x21, 0xec, 0xde, 0x75, - 0xf8, 0xba, 0x15, 0x61, 0x7d, 0xbf, 0xed, 0x0b, 0x8c, 0x86, 0x36, 0xd7, 0xee, 0x39, 0x86, 0x6e, 0xd8, 0x60, 0x13, - 0x39, 0x0f, 0x91, 0x0f, 0x33, 0x79, 0x20, 0x8a, 0xc6, 0x18, 0xb0, 0x3d, 0xe2, 0x6a, 0xd3, 0x4a, 0x7e, 0x5e, 0xc6, - 0x9c, 0xed, 0x19, 0xe3, 0x94, 0xd6, 0xd7, 0xb8, 0xe6, 0xb8, 0x2c, 0xa4, 0x6a, 0x8c, 0x67, 0x3c, 0x0c, 0x3b, 0x5f, - 0xe0, 0xce, 0xac, 0x31, 0x78, 0x11, 0x96, 0x4a, 0x76, 0x2a, 0x57, 0x9f, 0xc3, 0x16, 0x47, 0xb3, 0x31, 0xa7, 0xbf, - 0xff, 0x72, 0xc5, 0x17, 0xe8, 0xa6, 0x66, 0xfd, 0x08, 0x82, 0xac, 0x40, 0x87, 0x2c, 0xa9, 0x7a, 0xfc, 0xae, 0x04, - 0x6a, 0x0f, 0xf3, 0xf0, 0x5d, 0xc9, 0x8a, 0xf8, 0x26, 0xbb, 0x8a, 0x6b, 0x51, 0x8e, 0x6e, 0x78, 0x91, 0x8a, 0xd2, - 0x48, 0x8d, 0x83, 0xd3, 0xd5, 0x2a, 0xe7, 0x01, 0x98, 0xca, 0x1b, 0x46, 0xd9, 0x54, 0x96, 0xa9, 0xc1, 0x55, 0xf2, - 0xf4, 0x5a, 0x89, 0xce, 0xab, 0x9b, 0xab, 0x20, 0xc2, 0x5f, 0x17, 0xfa, 0xc7, 0x75, 0x5c, 0x7d, 0x0c, 0x22, 0x63, - 0x53, 0xa7, 0x7f, 0xa0, 0x54, 0x1e, 0xfc, 0xa7, 0x40, 0xa6, 0xfb, 0x5d, 0x09, 0x96, 0xd9, 0xa6, 0xe2, 0xe3, 0x18, - 0x6b, 0x1d, 0x4e, 0xc8, 0x4c, 0x96, 0xe8, 0xbc, 0x4b, 0xd6, 0x25, 0x58, 0xfb, 0x49, 0x2c, 0x63, 0x99, 0x6b, 0x86, - 0x95, 0xc9, 0x8a, 0xf4, 0xac, 0xac, 0xd9, 0x61, 0x68, 0x9c, 0x68, 0xe6, 0xe8, 0x2d, 0xa0, 0x1e, 0xc8, 0xe1, 0x15, - 0x2d, 0xd6, 0xcc, 0xf1, 0xb1, 0xf1, 0x5e, 0x3f, 0x3a, 0xbc, 0x72, 0x04, 0x4a, 0xe6, 0x4e, 0x8e, 0xc2, 0x44, 0xf0, - 0xac, 0xd5, 0xe3, 0x8b, 0x3c, 0x2b, 0x60, 0xe5, 0x4c, 0xc6, 0x63, 0xea, 0x2c, 0xad, 0xd6, 0xcd, 0xd1, 0x22, 0xb9, - 0x66, 0x8f, 0xeb, 0xc7, 0x9c, 0x1c, 0xf2, 0x96, 0xa9, 0x6d, 0xdb, 0x3a, 0xce, 0xd1, 0xe4, 0x4b, 0xd3, 0xfd, 0x6a, - 0x6d, 0x22, 0xa2, 0x4b, 0xe7, 0x3e, 0xeb, 0x15, 0xdc, 0xfa, 0xa6, 0xd0, 0xf4, 0x5a, 0x00, 0x10, 0x9d, 0x32, 0xe0, - 0x2f, 0x59, 0xb1, 0x1e, 0xd5, 0xbc, 0xaa, 0x41, 0xc2, 0x82, 0x22, 0xbc, 0x29, 0xf6, 0xa6, 0xb4, 0x37, 0x4e, 0xc7, - 0x61, 0x07, 0x2e, 0xa6, 0xe8, 0x8e, 0x03, 0x76, 0xfd, 0x5a, 0x2b, 0x1a, 0xa9, 0x5f, 0xb6, 0x2f, 0xb1, 0xea, 0x8b, - 0x52, 0xe6, 0x99, 0x9c, 0x12, 0x8b, 0xdd, 0x56, 0x2e, 0xac, 0xa8, 0xdf, 0x30, 0xe1, 0xd2, 0x95, 0x20, 0x20, 0xd3, - 0x92, 0xf5, 0x4a, 0xbd, 0x8b, 0xc4, 0x1a, 0x08, 0x19, 0x18, 0xbe, 0x06, 0xeb, 0xa2, 0xe2, 0xda, 0x0a, 0xd6, 0xb9, - 0xe7, 0xab, 0x84, 0x42, 0x14, 0x3c, 0xb0, 0x13, 0xf4, 0x43, 0xeb, 0xe6, 0x6d, 0x29, 0x51, 0x06, 0xf1, 0xb8, 0x95, - 0x53, 0x0e, 0x12, 0x08, 0xc0, 0x3d, 0x95, 0x21, 0x38, 0x24, 0xc8, 0x3a, 0xb8, 0x9a, 0x71, 0x04, 0x57, 0x97, 0xce, - 0x5c, 0x5c, 0x03, 0xac, 0x4b, 0x7f, 0x2e, 0x13, 0x5c, 0x58, 0x8d, 0xa8, 0x34, 0x67, 0x9c, 0x62, 0x10, 0x23, 0x43, - 0xd0, 0x57, 0x86, 0xd2, 0x5e, 0x81, 0xa6, 0xf1, 0x9a, 0xad, 0xa4, 0x0f, 0x00, 0xbd, 0x60, 0x2b, 0x69, 0xec, 0x8f, - 0x5f, 0x9f, 0xb3, 0x95, 0x92, 0x06, 0x4f, 0xaf, 0x67, 0x17, 0xb3, 0xf3, 0x01, 0x3b, 0x8a, 0x42, 0x65, 0xc0, 0x10, - 0x58, 0x24, 0xfe, 0x60, 0x10, 0x16, 0xb2, 0x11, 0x83, 0x42, 0x46, 0xc1, 0x72, 0x78, 0x6c, 0xc4, 0xcd, 0x0a, 0xc7, - 0xc3, 0x02, 0x43, 0x5e, 0x79, 0x2f, 0x48, 0x40, 0xa8, 0x2e, 0x0d, 0x5d, 0x1e, 0xc3, 0xe1, 0xe4, 0x60, 0x02, 0xa9, - 0x98, 0x99, 0xc9, 0xc2, 0xd8, 0x98, 0x44, 0x10, 0xef, 0xb4, 0xb3, 0x5e, 0x28, 0xb7, 0xbb, 0xc6, 0x42, 0x8d, 0xc3, - 0xe0, 0xb3, 0x2a, 0x9e, 0x1c, 0x0c, 0xbb, 0x2a, 0xc6, 0x51, 0xb8, 0xd1, 0xca, 0xb7, 0xf3, 0x63, 0x00, 0xaf, 0x3d, - 0x1f, 0xba, 0x72, 0x89, 0xf3, 0xc3, 0x27, 0xe4, 0xf1, 0x13, 0x42, 0xcf, 0xd9, 0xf9, 0x17, 0x4f, 0xe8, 0xb9, 0x24, - 0x27, 0x07, 0x93, 0xe8, 0x86, 0xe9, 0x06, 0x1c, 0x1e, 0xc9, 0x26, 0xd0, 0xab, 0xd1, 0xba, 0x90, 0x0b, 0x4c, 0x39, - 0x34, 0x85, 0xdf, 0x8e, 0x0f, 0x82, 0xc1, 0x4d, 0xbb, 0xe9, 0x37, 0xed, 0xb6, 0x3a, 0x5e, 0x5d, 0x07, 0x47, 0xd1, - 0x6e, 0x31, 0x93, 0x6f, 0xc6, 0x07, 0x76, 0x0e, 0xb0, 0xbe, 0x87, 0xc7, 0x44, 0x37, 0x69, 0x67, 0x54, 0xdc, 0x9a, - 0xbe, 0xc2, 0x3e, 0xf8, 0x45, 0x76, 0xf4, 0x61, 0xf8, 0x6f, 0x75, 0xa2, 0x39, 0xff, 0xe2, 0x08, 0xc8, 0x11, 0xc8, - 0x40, 0xb1, 0x44, 0x30, 0xc3, 0x81, 0xa6, 0x80, 0x82, 0x4c, 0x8d, 0x3b, 0x55, 0xc3, 0x2f, 0x47, 0x4d, 0xce, 0xc8, - 0x0d, 0x4c, 0x0d, 0xb6, 0x05, 0x3f, 0x90, 0xdd, 0x50, 0xdf, 0x28, 0x74, 0x23, 0xe5, 0x64, 0xa6, 0x5f, 0x52, 0xfd, - 0x83, 0xdd, 0x40, 0x00, 0x63, 0x0b, 0x2f, 0x28, 0xd8, 0x97, 0xc7, 0x57, 0x07, 0xb8, 0x8a, 0x00, 0x25, 0x8b, 0x05, - 0x5f, 0x0e, 0xae, 0xd4, 0xe6, 0x3e, 0x08, 0xc8, 0xe0, 0xcb, 0xe0, 0xe4, 0xcb, 0x81, 0x18, 0x04, 0xc7, 0x87, 0x57, - 0x27, 0x81, 0x35, 0xee, 0x87, 0x10, 0x8f, 0xb2, 0xa2, 0x98, 0x69, 0x34, 0x1f, 0xf4, 0x82, 0x92, 0x89, 0xb9, 0xa9, - 0x57, 0x1a, 0x9f, 0xd1, 0x74, 0x6a, 0x90, 0xbf, 0xc3, 0x94, 0xc5, 0xfa, 0x77, 0x30, 0xe1, 0xd7, 0x41, 0x64, 0x83, - 0xa0, 0xce, 0xf2, 0x28, 0xa6, 0x4b, 0x76, 0x5f, 0x85, 0x29, 0x4d, 0x0e, 0x73, 0x42, 0xa2, 0x70, 0x29, 0xc1, 0xf3, - 0xe4, 0xeb, 0x04, 0xe2, 0xb8, 0xda, 0xcf, 0x01, 0xd7, 0x8d, 0xe6, 0x87, 0x09, 0x69, 0x15, 0x61, 0x23, 0xb2, 0x6c, - 0x1a, 0x7a, 0xc9, 0xc2, 0x15, 0xbd, 0x02, 0x66, 0x4a, 0xac, 0xc3, 0x2b, 0xe0, 0xf2, 0xd6, 0xf3, 0xd5, 0x82, 0x5d, - 0x79, 0xd2, 0x37, 0xcd, 0x17, 0x5f, 0x1a, 0x9f, 0x3c, 0xe0, 0x21, 0xad, 0x1f, 0x5e, 0x0a, 0x36, 0x00, 0x37, 0x19, - 0xbf, 0xfd, 0x4e, 0xdc, 0xa9, 0x79, 0x69, 0x4f, 0x31, 0xce, 0x4c, 0x3b, 0x31, 0x69, 0x27, 0xe4, 0xee, 0x7d, 0x7b, - 0x13, 0xeb, 0x93, 0xbd, 0x8a, 0xd6, 0xd2, 0x65, 0xd5, 0x30, 0x24, 0xe5, 0x9a, 0x21, 0x7f, 0x8f, 0x92, 0x53, 0x23, - 0xf0, 0x64, 0x97, 0xbc, 0x4e, 0x96, 0xee, 0x41, 0x65, 0xac, 0x06, 0xcc, 0x31, 0x62, 0x58, 0x28, 0x1c, 0xfb, 0xd7, - 0x19, 0x2b, 0xd7, 0xae, 0x40, 0x23, 0x46, 0xee, 0xed, 0x75, 0xc6, 0x9c, 0x98, 0xab, 0xc9, 0xda, 0x09, 0x55, 0xe7, - 0xa4, 0xe7, 0x2d, 0xde, 0xcb, 0x2a, 0x35, 0xb4, 0x44, 0xf4, 0x60, 0x2c, 0xcd, 0x28, 0x65, 0xa2, 0xd2, 0xa0, 0x91, - 0x8a, 0x8d, 0x6d, 0xf0, 0x4b, 0x70, 0x42, 0xe5, 0x8e, 0x3a, 0xdb, 0xb5, 0x53, 0x2a, 0x1c, 0x60, 0x59, 0xaa, 0x55, - 0xe5, 0x76, 0x99, 0x09, 0x56, 0x0f, 0x82, 0xd1, 0x1f, 0x95, 0x28, 0x66, 0x78, 0x67, 0x64, 0xc1, 0x14, 0xac, 0x04, - 0x65, 0x2d, 0xc3, 0x62, 0xc8, 0x51, 0x8b, 0xa7, 0x7d, 0x52, 0x85, 0xfa, 0xd1, 0x11, 0x24, 0x77, 0xb9, 0x6e, 0x05, - 0xc9, 0x7d, 0x32, 0x7e, 0xa2, 0x06, 0x3a, 0x5d, 0x2b, 0xc7, 0x43, 0x97, 0xdf, 0x46, 0x7c, 0x6d, 0xd5, 0x7b, 0xaa, - 0xb4, 0x0a, 0x55, 0xa0, 0xc4, 0x8a, 0xd2, 0x95, 0x5a, 0xd0, 0xfd, 0x2e, 0x02, 0x60, 0x11, 0x1b, 0xb3, 0xf1, 0xae, - 0x6d, 0x56, 0x08, 0x1a, 0x5d, 0x76, 0xb2, 0x89, 0x07, 0x2c, 0x51, 0xad, 0x1d, 0x4c, 0x68, 0x7c, 0xc2, 0x8a, 0x7e, - 0x3f, 0x3f, 0x01, 0x7a, 0xaa, 0x8c, 0x98, 0x4a, 0x38, 0xf2, 0x3f, 0xb7, 0x22, 0x5d, 0x14, 0xd8, 0xac, 0xc9, 0xbb, - 0x35, 0x96, 0x91, 0xa8, 0xcb, 0x94, 0x2a, 0xaf, 0x72, 0x0c, 0x98, 0xd6, 0xeb, 0x96, 0xe3, 0xca, 0xae, 0xe2, 0xc8, - 0x51, 0x61, 0x19, 0x71, 0x5e, 0x8d, 0xe3, 0xad, 0xc6, 0x37, 0x38, 0xd4, 0x6c, 0xda, 0xa5, 0x3b, 0x84, 0xb0, 0x10, - 0x5e, 0x67, 0x70, 0x1b, 0x51, 0x76, 0x12, 0xa8, 0xbc, 0xd1, 0xd7, 0x09, 0x69, 0x73, 0xbb, 0x5e, 0x3b, 0x06, 0xe9, - 0x44, 0x1f, 0x28, 0xf5, 0x08, 0x5a, 0xa3, 0x58, 0x50, 0x39, 0xe2, 0x91, 0xe5, 0xe1, 0xad, 0x41, 0xac, 0x92, 0x2f, - 0x29, 0x2a, 0x45, 0x03, 0xf4, 0xbf, 0xe4, 0xb7, 0x07, 0xbf, 0xbc, 0xff, 0xe9, 0x8c, 0xc7, 0x65, 0xb2, 0x7c, 0x17, - 0x97, 0xf1, 0x75, 0x15, 0x6e, 0xe4, 0x18, 0xc5, 0x0d, 0x99, 0x56, 0x03, 0x26, 0xf4, 0x4a, 0xf2, 0x77, 0xa5, 0x22, - 0xc4, 0x58, 0x67, 0xb2, 0xae, 0x6a, 0x71, 0xed, 0x55, 0xba, 0x2e, 0x33, 0xfc, 0xb8, 0xe5, 0x73, 0x7a, 0x08, 0x40, - 0x9e, 0xda, 0x85, 0x34, 0x12, 0xaa, 0x10, 0x6d, 0x2e, 0xe2, 0x74, 0x7d, 0x3c, 0xf6, 0xba, 0x5e, 0xb0, 0xa7, 0xe3, - 0xaf, 0xa6, 0xaf, 0xb3, 0x30, 0x1b, 0x54, 0x64, 0x54, 0x2f, 0x79, 0xd1, 0x32, 0xe5, 0x94, 0x26, 0x01, 0xe8, 0xe3, - 0xd9, 0x63, 0xec, 0x68, 0x3c, 0x26, 0x9b, 0xb6, 0x78, 0x80, 0x87, 0xcb, 0x75, 0x58, 0x92, 0x99, 0xaa, 0x23, 0x0a, - 0x0a, 0x7e, 0x57, 0x07, 0x80, 0xe4, 0x68, 0xaa, 0xd2, 0x5c, 0x1a, 0x7b, 0x3a, 0x9e, 0x50, 0x81, 0xdd, 0x0e, 0x49, - 0xe3, 0x54, 0x68, 0x67, 0x5e, 0xb8, 0x1e, 0x45, 0x42, 0xbb, 0x2c, 0xed, 0x54, 0x2a, 0xe4, 0x9e, 0x99, 0xd9, 0xae, - 0x41, 0x0c, 0x86, 0x50, 0xd5, 0x5d, 0x38, 0x75, 0xef, 0x36, 0xd7, 0x98, 0xed, 0x80, 0xf7, 0x1a, 0x34, 0x43, 0xca, - 0x5b, 0xf4, 0x5b, 0x5b, 0x44, 0x43, 0x57, 0x6b, 0x30, 0x2b, 0x46, 0xd9, 0x52, 0x94, 0xae, 0x29, 0x28, 0x05, 0xa3, - 0xcb, 0xb5, 0xb3, 0x70, 0x5f, 0x0b, 0xef, 0xc2, 0x92, 0xa9, 0xd5, 0x22, 0xa5, 0x84, 0xf2, 0xa6, 0xa2, 0xa5, 0x84, - 0x91, 0xd4, 0xf0, 0xd4, 0xae, 0x17, 0x78, 0x9c, 0xe7, 0x41, 0xd4, 0xf2, 0x02, 0x3b, 0xad, 0xc9, 0x29, 0x38, 0x7a, - 0xe9, 0x9c, 0x9a, 0x02, 0xff, 0x98, 0x49, 0x10, 0xd3, 0xa1, 0xbc, 0xdf, 0xe0, 0xe6, 0xff, 0x47, 0xc9, 0x02, 0x87, - 0x6f, 0xbd, 0xc2, 0x6d, 0xf4, 0x8f, 0xd2, 0xa5, 0xa5, 0xcf, 0x84, 0xeb, 0xea, 0xe2, 0x48, 0x7b, 0xb3, 0x51, 0xb2, - 0xcc, 0xf2, 0xf4, 0x8d, 0x48, 0x79, 0x45, 0xa4, 0x09, 0x46, 0xc5, 0x4e, 0x2a, 0xef, 0x86, 0x07, 0x46, 0x8c, 0xde, - 0x8d, 0xef, 0xc7, 0x0c, 0x64, 0xc3, 0x60, 0xf5, 0xcd, 0x52, 0x91, 0xac, 0xaf, 0x01, 0x53, 0x44, 0xca, 0x4f, 0x5e, - 0xe4, 0x1c, 0x9e, 0x42, 0x75, 0xfd, 0x02, 0xb7, 0xb9, 0xca, 0xf5, 0x39, 0xff, 0x31, 0xa3, 0x3f, 0x22, 0xd0, 0x49, - 0xbc, 0x02, 0xb9, 0xc7, 0x33, 0xa8, 0x1b, 0x61, 0x6a, 0x39, 0x06, 0x07, 0x42, 0x34, 0x90, 0xa2, 0x66, 0x81, 0x84, - 0xba, 0xd0, 0xc0, 0x1a, 0xf2, 0x82, 0x39, 0xbc, 0xc8, 0x45, 0xf2, 0x71, 0xaa, 0x7d, 0xe6, 0x87, 0x31, 0xc6, 0x4c, - 0x0e, 0x06, 0x61, 0x3d, 0x0b, 0x86, 0xe3, 0xd1, 0xe4, 0xe8, 0x29, 0x9c, 0xdb, 0xc1, 0x38, 0x20, 0x83, 0xa0, 0xa9, - 0x56, 0x71, 0x41, 0xab, 0x9b, 0x2b, 0x53, 0x06, 0x7e, 0xdc, 0x04, 0x83, 0x7f, 0x94, 0x8e, 0xe2, 0x1d, 0x34, 0x27, - 0xe7, 0x22, 0x04, 0x1b, 0xfb, 0x35, 0x01, 0x49, 0x59, 0x4f, 0xf1, 0x93, 0xea, 0x70, 0x63, 0x52, 0xfb, 0xa7, 0x0f, - 0x2f, 0x38, 0xec, 0x90, 0x40, 0x81, 0x34, 0x9e, 0x66, 0xa3, 0x57, 0x52, 0x91, 0xfb, 0xae, 0xe4, 0x70, 0x67, 0xee, - 0x59, 0xd3, 0x23, 0xab, 0x90, 0xf0, 0xb3, 0x80, 0x1b, 0xf9, 0xab, 0xe2, 0x26, 0xce, 0xb3, 0xf4, 0xc0, 0x7f, 0x73, - 0x50, 0xdd, 0x17, 0x75, 0x7c, 0x37, 0x0a, 0xb4, 0x35, 0x21, 0x77, 0x55, 0x4f, 0x80, 0x9e, 0x00, 0x5b, 0x00, 0x0c, - 0x88, 0x77, 0xcc, 0x4c, 0x66, 0x3c, 0x02, 0x8f, 0x40, 0xdf, 0x07, 0xb2, 0xbc, 0xb7, 0x2e, 0x49, 0xee, 0x66, 0x2a, - 0xcc, 0x55, 0xaf, 0xd8, 0x29, 0xc8, 0x78, 0xb5, 0x15, 0xbb, 0x6e, 0x7d, 0xe6, 0x4d, 0x87, 0x57, 0xe0, 0x85, 0x00, - 0xb7, 0xc8, 0x7e, 0xdf, 0x17, 0x54, 0x56, 0x5a, 0x45, 0xbc, 0x93, 0xdc, 0xa0, 0x7f, 0xbb, 0x33, 0x36, 0x92, 0xe4, - 0x56, 0x0f, 0x0f, 0xa0, 0xca, 0xe4, 0x5c, 0x71, 0x3b, 0x87, 0xa8, 0xad, 0xbb, 0x71, 0xc0, 0x6a, 0x83, 0x76, 0x59, - 0x73, 0x04, 0x17, 0x5e, 0x1c, 0x64, 0x90, 0x13, 0x67, 0x65, 0x24, 0xd5, 0xb8, 0x9a, 0xd4, 0x82, 0x4f, 0xf2, 0x74, - 0x0f, 0x59, 0xea, 0x09, 0x50, 0xe4, 0x38, 0x16, 0x43, 0xba, 0xf1, 0x26, 0xf0, 0xf8, 0xbd, 0x08, 0x41, 0x9a, 0xb6, - 0xdd, 0xfa, 0x23, 0x50, 0x74, 0x0f, 0x4c, 0x41, 0x9a, 0x46, 0x9b, 0x1a, 0x28, 0xa8, 0x3d, 0xd4, 0x48, 0x45, 0x9c, - 0x9d, 0xbc, 0x06, 0x1d, 0x22, 0xf8, 0x7e, 0xa7, 0x59, 0xd5, 0xf1, 0x62, 0x42, 0xf0, 0xe4, 0x7d, 0x71, 0x97, 0x55, - 0x75, 0x15, 0xbd, 0x4f, 0xd1, 0x10, 0x2a, 0x11, 0x45, 0xf4, 0x12, 0xe2, 0xe9, 0x55, 0xf8, 0xbb, 0x8a, 0x7e, 0x4a, - 0x69, 0x9c, 0xa6, 0x98, 0xfe, 0xbc, 0x84, 0x9f, 0xcf, 0x00, 0xd5, 0x11, 0x77, 0x42, 0x74, 0x21, 0xc0, 0x5e, 0x0d, - 0xa2, 0x59, 0xd5, 0x1c, 0x30, 0x34, 0xa3, 0xfb, 0x8a, 0x22, 0x46, 0x1b, 0x66, 0xff, 0xa1, 0x44, 0xa1, 0x90, 0x2c, - 0xe6, 0xd7, 0xca, 0x3c, 0x44, 0x3f, 0x62, 0x91, 0xa7, 0xef, 0x5e, 0xe9, 0x21, 0x8d, 0xee, 0x05, 0x55, 0x5b, 0x1b, - 0x8f, 0x2d, 0x0c, 0x5c, 0x16, 0x5d, 0xad, 0xe9, 0x79, 0xbc, 0xca, 0xa2, 0x0d, 0xe0, 0x4f, 0xbc, 0x7b, 0xf5, 0x4c, - 0x5a, 0x98, 0x3c, 0xcf, 0x40, 0x71, 0x70, 0xfa, 0xee, 0xd5, 0x6b, 0x91, 0xae, 0x73, 0x1e, 0x9d, 0x0b, 0x24, 0xad, - 0xa7, 0xef, 0x5e, 0xfd, 0x8c, 0xe6, 0x5e, 0x3f, 0x95, 0xf0, 0xfe, 0x25, 0xf0, 0x96, 0x51, 0xbc, 0x86, 0x3e, 0xc9, - 0xdf, 0xc9, 0x1a, 0x3b, 0xe5, 0xd4, 0x5a, 0x45, 0xbf, 0xa4, 0x8d, 0x23, 0xad, 0xfa, 0x67, 0xe9, 0x52, 0x3b, 0x47, - 0xc0, 0x73, 0x97, 0x67, 0xc5, 0xc7, 0xc8, 0x88, 0x76, 0x82, 0xe8, 0xcb, 0x83, 0xbb, 0xeb, 0xbc, 0xa8, 0x22, 0x7c, - 0xc1, 0xd0, 0x2e, 0x28, 0x3a, 0x3c, 0xbc, 0xbd, 0xbd, 0x1d, 0xdd, 0x7e, 0x35, 0x12, 0xe5, 0xd5, 0xe1, 0xe4, 0xdb, - 0x6f, 0xbf, 0x3d, 0xc4, 0xb7, 0xc1, 0x97, 0x6d, 0xb7, 0xf7, 0x9a, 0xf0, 0x01, 0x0b, 0x10, 0xa1, 0xfa, 0x4b, 0xb8, - 0xa2, 0x80, 0x16, 0x6e, 0xf0, 0x65, 0xf0, 0xa5, 0x3a, 0x74, 0xbe, 0x3c, 0xae, 0x6e, 0xae, 0x64, 0xf9, 0x5d, 0x25, - 0x1f, 0x8d, 0xc7, 0xe3, 0x43, 0x90, 0x40, 0x7d, 0x39, 0xe0, 0x83, 0xe0, 0x24, 0x18, 0x64, 0x70, 0xa1, 0xa9, 0x6e, - 0xae, 0x4e, 0x02, 0xc7, 0x34, 0xd7, 0x63, 0x11, 0x2d, 0x88, 0x4b, 0x70, 0x78, 0x45, 0x83, 0x2f, 0x03, 0x62, 0x53, - 0xbe, 0x80, 0x94, 0x2f, 0x8e, 0x9e, 0xba, 0x69, 0xff, 0x4b, 0xa6, 0x7d, 0xe5, 0xa6, 0x1d, 0x63, 0xda, 0x57, 0xcf, - 0xdc, 0xb4, 0x13, 0x99, 0xf6, 0xc2, 0x4d, 0xfb, 0xdf, 0xd5, 0x00, 0x52, 0x0f, 0x5c, 0xeb, 0xbf, 0x0b, 0xa7, 0x35, - 0x78, 0x0a, 0x45, 0xd9, 0x75, 0x7c, 0xc5, 0xa1, 0xd1, 0x83, 0xbb, 0xeb, 0x9c, 0x06, 0x03, 0x6c, 0xaf, 0x63, 0xe4, - 0xe1, 0x7c, 0xf0, 0xe5, 0xba, 0xcc, 0xc3, 0xe0, 0xcb, 0x01, 0x16, 0x32, 0xf8, 0x32, 0x20, 0x5f, 0xaa, 0x23, 0xed, - 0xae, 0x62, 0x9b, 0xc0, 0x86, 0x22, 0x1d, 0x9a, 0x00, 0x61, 0xae, 0x34, 0xae, 0xa1, 0x7f, 0x96, 0xdd, 0xd9, 0xf0, - 0x96, 0x28, 0xdd, 0x74, 0x83, 0x86, 0xbe, 0x05, 0xef, 0x04, 0x68, 0x54, 0x14, 0xdc, 0xc4, 0x65, 0x38, 0x1c, 0x56, - 0x37, 0x57, 0x04, 0xec, 0x32, 0x57, 0x3c, 0xae, 0xa3, 0xa0, 0x10, 0x43, 0xf9, 0x33, 0x90, 0x91, 0xaf, 0x02, 0x04, - 0x44, 0x82, 0xff, 0x82, 0x86, 0xbe, 0x13, 0x6c, 0x13, 0x0c, 0x6f, 0xf9, 0xc5, 0xc7, 0xac, 0x1e, 0x4a, 0xd1, 0xe2, - 0x5d, 0x45, 0xe1, 0x07, 0xfc, 0xb5, 0x55, 0x47, 0x7f, 0x82, 0x1b, 0xb7, 0xaf, 0x61, 0x7f, 0x27, 0x2c, 0x8b, 0xfa, - 0x4e, 0xcc, 0xb3, 0xc5, 0xb4, 0x75, 0xa0, 0xbf, 0x15, 0xa4, 0x9e, 0x67, 0x83, 0x60, 0x18, 0x0c, 0xf8, 0x82, 0xbd, - 0x15, 0x73, 0xee, 0x98, 0x4f, 0x3d, 0x12, 0xee, 0x34, 0xcf, 0xb2, 0x01, 0xf8, 0xa6, 0x20, 0x3f, 0x72, 0xf8, 0xdf, - 0xf3, 0x21, 0x0a, 0x0f, 0x07, 0x8f, 0x0e, 0xc9, 0x2c, 0x58, 0xdd, 0xa1, 0x47, 0x67, 0x14, 0x64, 0xc5, 0x92, 0x97, - 0x59, 0xed, 0x2c, 0x95, 0xfb, 0x75, 0xdb, 0xcb, 0x63, 0xef, 0xd9, 0xbc, 0x8a, 0x8b, 0x40, 0x9e, 0x73, 0xa0, 0x78, - 0x43, 0xd9, 0x53, 0xe1, 0x4b, 0x48, 0x95, 0x21, 0x6f, 0x58, 0x0c, 0x58, 0x70, 0xdc, 0x1b, 0x0e, 0x0f, 0x82, 0x81, - 0x55, 0xe7, 0x0e, 0x82, 0x83, 0xe1, 0xf0, 0x24, 0xb0, 0xf7, 0xa1, 0x6c, 0x64, 0xef, 0x8c, 0xb4, 0x64, 0xff, 0x2c, - 0xc3, 0x82, 0x82, 0x78, 0x4c, 0x28, 0xf1, 0x97, 0x02, 0x97, 0x19, 0x00, 0xf4, 0x91, 0x94, 0x80, 0x69, 0x58, 0x99, - 0x01, 0x84, 0xe6, 0xa6, 0x31, 0x3b, 0x07, 0xe6, 0x91, 0x26, 0x20, 0xde, 0x03, 0x8a, 0x01, 0x88, 0x25, 0x01, 0xce, - 0x5d, 0x10, 0xc5, 0xaa, 0x90, 0x47, 0x00, 0x7a, 0x8f, 0x3f, 0x89, 0x2e, 0x05, 0x93, 0x54, 0xac, 0x42, 0x10, 0xc4, - 0xf1, 0xd9, 0x5d, 0xd5, 0x9a, 0x9c, 0x25, 0x3a, 0x98, 0x91, 0x04, 0xd8, 0x10, 0x0d, 0x3b, 0x07, 0xf7, 0x73, 0x50, - 0x7a, 0x18, 0xbd, 0x13, 0x72, 0xc1, 0xf7, 0xdc, 0xb2, 0x50, 0x77, 0x70, 0xf5, 0x84, 0x83, 0xe0, 0x9e, 0x2b, 0x16, - 0x60, 0x54, 0x97, 0xeb, 0xaa, 0xe6, 0xe9, 0x87, 0xfb, 0x15, 0xc4, 0xbe, 0xc3, 0x01, 0x7d, 0x27, 0xf2, 0x2c, 0xb9, - 0x0f, 0xad, 0x3d, 0xd7, 0x46, 0xa6, 0xff, 0xf0, 0xe1, 0xf5, 0x4f, 0x11, 0x88, 0x1c, 0x1b, 0x4d, 0xe9, 0xef, 0x39, - 0x9e, 0x4d, 0x6e, 0x84, 0x27, 0x77, 0x63, 0xdf, 0x73, 0x73, 0x7a, 0xf4, 0xfb, 0x50, 0x37, 0xbd, 0xe7, 0xb3, 0x7b, - 0x3e, 0xb2, 0xc5, 0xa1, 0xba, 0xc2, 0x7e, 0x7d, 0xbb, 0x76, 0x8d, 0x90, 0x1e, 0x9e, 0x67, 0xca, 0xbd, 0xf9, 0x51, - 0x0e, 0x86, 0x41, 0x30, 0x55, 0x42, 0x49, 0x88, 0xba, 0xc1, 0xa4, 0x80, 0x21, 0x3a, 0x50, 0xcb, 0x6a, 0x8a, 0x9c, - 0x9b, 0x1c, 0x59, 0x78, 0x3f, 0x60, 0x4a, 0xe8, 0xe0, 0xe5, 0x90, 0x7e, 0x70, 0x38, 0x61, 0xcc, 0xc0, 0x6f, 0x15, - 0x30, 0xfd, 0x72, 0x51, 0x59, 0x07, 0xd1, 0x03, 0x30, 0xc6, 0x2d, 0x78, 0x09, 0x5d, 0x61, 0x37, 0x6b, 0x19, 0x15, - 0x03, 0xc1, 0xe3, 0x90, 0x03, 0x74, 0xb0, 0x0b, 0x5a, 0x56, 0x96, 0xf2, 0x56, 0x65, 0x2d, 0x55, 0xe4, 0x65, 0x28, - 0xab, 0x62, 0x89, 0xf9, 0x5e, 0xb0, 0x1f, 0x4a, 0xf4, 0x2c, 0x9f, 0x56, 0x5d, 0xf0, 0x42, 0x28, 0xc1, 0xb2, 0x5d, - 0xef, 0x44, 0x20, 0xea, 0x4c, 0x75, 0xae, 0xfa, 0x0a, 0xc7, 0x8e, 0xa7, 0xaf, 0x45, 0xca, 0x95, 0x09, 0x85, 0xe2, - 0xf3, 0x85, 0xab, 0x98, 0x28, 0xd9, 0x2d, 0xf4, 0xab, 0x6d, 0xa3, 0xcf, 0xee, 0xd7, 0x6a, 0x33, 0x48, 0xd1, 0x31, - 0x6f, 0x50, 0x70, 0x2d, 0x15, 0x0a, 0x5a, 0x7b, 0x1b, 0x7f, 0x82, 0x23, 0x37, 0xba, 0x3d, 0xf4, 0x7e, 0xab, 0xe3, - 0xab, 0x37, 0xe8, 0xdb, 0x69, 0x7e, 0x8e, 0x6a, 0xf1, 0xcb, 0x6a, 0x05, 0x3e, 0x54, 0x10, 0x59, 0xc4, 0xe0, 0xd2, - 0x42, 0x3d, 0x67, 0xef, 0x4e, 0xdf, 0x80, 0x1f, 0x25, 0xfe, 0xfe, 0xf5, 0xfb, 0xa0, 0x21, 0xd3, 0x78, 0x56, 0xea, - 0x0f, 0x4d, 0x0e, 0x08, 0x4d, 0x62, 0xd3, 0xcc, 0xfb, 0x59, 0xec, 0xb3, 0xef, 0x8a, 0xad, 0xa7, 0xa5, 0x8f, 0x24, - 0xa5, 0xb9, 0x7d, 0x30, 0x20, 0x50, 0x07, 0x88, 0xe4, 0xec, 0x4b, 0x1a, 0x43, 0x9a, 0xcb, 0xec, 0xbb, 0x11, 0xf1, - 0x5e, 0xec, 0x84, 0x10, 0xe3, 0x12, 0x8b, 0x46, 0x0d, 0xf9, 0x8c, 0x47, 0xd2, 0xb0, 0xe8, 0x3d, 0x26, 0x10, 0x6b, - 0x38, 0x2d, 0xdf, 0x23, 0xe6, 0x31, 0xde, 0x0d, 0x94, 0xec, 0x21, 0xca, 0xa8, 0xcd, 0xee, 0x59, 0x7c, 0x7f, 0x5c, - 0x87, 0x99, 0xb1, 0xbc, 0x1c, 0xc2, 0xdf, 0x40, 0x19, 0x80, 0x53, 0x8e, 0x2c, 0x5f, 0xad, 0x37, 0xba, 0x5c, 0x62, - 0x6a, 0x13, 0x41, 0x2c, 0x1e, 0x95, 0x0e, 0x6b, 0x57, 0xa5, 0xaa, 0x5d, 0x6d, 0x7d, 0x26, 0x7a, 0x35, 0x68, 0xe5, - 0xda, 0xf6, 0x78, 0x08, 0x77, 0xa9, 0xa4, 0x15, 0x26, 0xb0, 0x5e, 0x65, 0x15, 0x2a, 0xd8, 0x9c, 0x80, 0x06, 0xd7, - 0x22, 0x05, 0xe0, 0x2c, 0xa5, 0x46, 0xa3, 0x5a, 0xd8, 0x67, 0xe4, 0x7c, 0x16, 0x5b, 0x0b, 0xf1, 0xb4, 0x00, 0x0c, - 0xd7, 0xc7, 0xa0, 0xe4, 0xdd, 0x18, 0x94, 0xd3, 0x8f, 0x12, 0xde, 0x3a, 0x38, 0xaf, 0x96, 0x71, 0x2a, 0x6e, 0x01, - 0x8b, 0x31, 0x70, 0x53, 0xb1, 0x54, 0x27, 0x21, 0x59, 0xf2, 0xe4, 0x23, 0x5a, 0x6d, 0xa4, 0x01, 0x70, 0x95, 0x53, - 0x6d, 0xb9, 0x27, 0x41, 0x42, 0x6d, 0x29, 0x32, 0x21, 0xae, 0xeb, 0x38, 0x59, 0x9e, 0x61, 0x6a, 0xb8, 0x81, 0x5e, - 0x44, 0x81, 0x58, 0xf1, 0x02, 0x48, 0x7a, 0xce, 0xfe, 0x95, 0x29, 0xac, 0xf1, 0x67, 0x02, 0x05, 0x4c, 0x0a, 0x35, - 0x18, 0x2b, 0x65, 0x2f, 0x84, 0x8e, 0xf6, 0x16, 0x04, 0x8d, 0x7d, 0xf9, 0x27, 0xd4, 0xfd, 0x0c, 0x5a, 0x11, 0x7a, - 0x60, 0x88, 0xe2, 0x02, 0x77, 0x68, 0x6a, 0x96, 0x9c, 0x03, 0x8c, 0x58, 0x18, 0xef, 0xb3, 0xc6, 0x6c, 0xf5, 0x67, - 0x4b, 0xc0, 0x36, 0x4d, 0xb5, 0x4f, 0x61, 0x98, 0x10, 0x1d, 0x1b, 0xd8, 0x28, 0x2b, 0xcd, 0x86, 0xd2, 0xed, 0xa4, - 0x4b, 0xe6, 0xb4, 0x70, 0x9a, 0xf7, 0x18, 0x5b, 0x8e, 0x64, 0xee, 0x7e, 0x3f, 0xd4, 0x3f, 0x59, 0x4e, 0x9f, 0xa9, - 0x90, 0xcd, 0xce, 0x78, 0xd0, 0x9c, 0x28, 0x75, 0x55, 0x47, 0x3f, 0xa0, 0x03, 0x30, 0xd3, 0x06, 0x20, 0xd3, 0x06, - 0x9b, 0x76, 0x95, 0xa8, 0xb8, 0x24, 0x61, 0xa9, 0x24, 0xb0, 0xb3, 0x7d, 0xc9, 0xce, 0x26, 0x20, 0x8e, 0xe1, 0xae, - 0xa3, 0xc5, 0x4e, 0x88, 0x0f, 0x6f, 0x71, 0x90, 0x80, 0xa8, 0x43, 0x56, 0x97, 0x90, 0x8d, 0x36, 0x74, 0x71, 0x2f, - 0x4a, 0x61, 0xc2, 0x5a, 0x26, 0x55, 0x89, 0x0e, 0x82, 0x54, 0xed, 0xb6, 0x08, 0x2c, 0x51, 0xb0, 0x03, 0xd8, 0x7b, - 0x3b, 0xea, 0x7a, 0xd4, 0x64, 0x75, 0xf2, 0x25, 0xf8, 0x38, 0xcd, 0xba, 0x0a, 0xd2, 0x0b, 0xbb, 0x2e, 0xd7, 0x3c, - 0x50, 0xb1, 0xa9, 0xa4, 0x31, 0x71, 0x97, 0x16, 0x19, 0xe2, 0x01, 0x63, 0x2c, 0x5d, 0x08, 0xe4, 0x9b, 0xed, 0x8e, - 0x9b, 0x9a, 0x20, 0xf4, 0x13, 0xd6, 0x94, 0xc0, 0x4e, 0x67, 0x7b, 0x6a, 0xfc, 0x7c, 0x40, 0xc4, 0x61, 0x40, 0x81, - 0x64, 0xe3, 0x90, 0xe6, 0x48, 0x5f, 0x90, 0x34, 0x61, 0x60, 0x68, 0xc9, 0x73, 0x82, 0xac, 0x28, 0x74, 0x6c, 0x5d, - 0x95, 0x71, 0xae, 0x08, 0x73, 0xb4, 0xe4, 0x94, 0xf8, 0x9c, 0x20, 0x13, 0xdb, 0xd3, 0x36, 0x3d, 0x19, 0x96, 0x92, - 0x05, 0xfa, 0x57, 0x10, 0x25, 0xf6, 0x4c, 0x33, 0x2a, 0x07, 0xed, 0x02, 0x16, 0x28, 0xe5, 0x7b, 0xd0, 0x78, 0x6b, - 0x68, 0xa3, 0x60, 0x88, 0xed, 0xfe, 0x04, 0xfb, 0xb5, 0x76, 0x5a, 0x97, 0x29, 0x96, 0x93, 0x29, 0x44, 0x7b, 0x21, - 0xfd, 0x1b, 0x45, 0xa2, 0x3b, 0x45, 0x68, 0x12, 0xd6, 0x51, 0xf6, 0xa4, 0x4d, 0x0d, 0xa0, 0xa7, 0x4e, 0xc0, 0xf3, - 0xce, 0xb5, 0x0c, 0xbb, 0x48, 0xf5, 0x57, 0x06, 0x9f, 0x52, 0x0d, 0x82, 0x14, 0xb5, 0x49, 0xc1, 0x9c, 0xd7, 0xa1, - 0xa4, 0xce, 0x9c, 0xb6, 0xcc, 0xa8, 0x3a, 0x2a, 0x42, 0xca, 0x09, 0xfe, 0x93, 0x57, 0x42, 0x11, 0x9b, 0x30, 0xc1, - 0x03, 0x1f, 0xe6, 0x19, 0x36, 0xf0, 0x76, 0xfb, 0x2e, 0x0d, 0x93, 0x36, 0xdb, 0x90, 0x82, 0xb4, 0x42, 0xc7, 0xc5, - 0x80, 0xca, 0x5e, 0xe1, 0x7e, 0xc1, 0x76, 0xd2, 0x14, 0x3c, 0x08, 0xbd, 0x06, 0x26, 0x76, 0x75, 0xf1, 0x75, 0x98, - 0xd0, 0x70, 0x49, 0x95, 0xb3, 0x93, 0x92, 0x34, 0xb7, 0xd7, 0xe5, 0xa5, 0xe9, 0x83, 0x8a, 0x1d, 0xd6, 0x35, 0x3c, - 0xd0, 0x3c, 0xbf, 0x8b, 0x2b, 0xa6, 0x68, 0xa2, 0xb6, 0x1e, 0x92, 0x96, 0x1c, 0xeb, 0x66, 0xba, 0xc2, 0xd5, 0x32, - 0x53, 0xc0, 0xee, 0x02, 0x2f, 0xf4, 0x80, 0x87, 0x1d, 0xae, 0x48, 0x74, 0x89, 0xcd, 0x66, 0xab, 0x86, 0x4c, 0xf3, - 0x7d, 0xd9, 0x72, 0x1d, 0x10, 0xce, 0x50, 0xdf, 0xdc, 0x25, 0xc7, 0x8a, 0xb6, 0xb9, 0x49, 0x80, 0xe3, 0xed, 0x14, - 0x90, 0x74, 0x2c, 0x41, 0x1b, 0xdf, 0xd2, 0x1d, 0x44, 0xaa, 0xa7, 0x82, 0xee, 0x9d, 0x2f, 0xd2, 0xf8, 0x5f, 0x80, - 0x6d, 0xd4, 0x46, 0x9b, 0x66, 0x65, 0xeb, 0x30, 0x91, 0x16, 0xd6, 0xc8, 0x42, 0x2e, 0xc1, 0x07, 0x73, 0xb7, 0xa9, - 0xd3, 0xd3, 0x0e, 0x22, 0xec, 0x76, 0xd1, 0xe1, 0x11, 0xc6, 0x92, 0x35, 0x48, 0x34, 0xab, 0xb0, 0xa6, 0xfe, 0x72, - 0x88, 0x72, 0xaa, 0x97, 0x4c, 0xb4, 0xa4, 0x2e, 0xa5, 0x88, 0x52, 0x30, 0x37, 0x9e, 0x16, 0x9e, 0x29, 0x21, 0x42, - 0x56, 0x08, 0x0b, 0x54, 0x6b, 0xa0, 0xa5, 0x7c, 0xd0, 0xeb, 0xd0, 0xc9, 0x42, 0x63, 0x0a, 0xa2, 0x8f, 0x48, 0x73, - 0x23, 0x96, 0x8c, 0xee, 0x8e, 0x51, 0x4c, 0x20, 0x54, 0xb5, 0x93, 0x17, 0x56, 0x9f, 0x92, 0x6d, 0x75, 0x10, 0xd7, - 0x98, 0x26, 0x7b, 0x08, 0x6a, 0x8c, 0x82, 0x36, 0xab, 0x1b, 0xfd, 0xa5, 0x0c, 0x5d, 0xbb, 0x70, 0xec, 0x46, 0x49, - 0x04, 0x44, 0x60, 0x75, 0x9a, 0x8a, 0x01, 0x59, 0xe7, 0xb1, 0x8d, 0xd0, 0xa4, 0xba, 0x85, 0x28, 0x6f, 0x54, 0x34, - 0x1f, 0xd7, 0x21, 0xd9, 0x6e, 0xb1, 0x2c, 0xf0, 0x65, 0x3f, 0x5b, 0xef, 0x81, 0xfc, 0x7e, 0xbd, 0xfe, 0x24, 0xe4, - 0xf7, 0xab, 0xec, 0x73, 0x20, 0xbf, 0x5f, 0xaf, 0xff, 0xa7, 0x21, 0xbf, 0xcf, 0xd6, 0x0e, 0xe4, 0xb7, 0x1c, 0x8c, - 0xdf, 0x4a, 0x16, 0xbc, 0x7d, 0x13, 0xd0, 0xe7, 0x82, 0x05, 0x6f, 0x5f, 0xbe, 0x74, 0x84, 0xe9, 0xdf, 0xe9, 0x38, - 0x2f, 0x5a, 0x16, 0x8c, 0xb8, 0x2d, 0xf0, 0x0a, 0xb5, 0x4e, 0x2e, 0x50, 0x51, 0x06, 0xc0, 0xeb, 0xd5, 0x3f, 0xb2, - 0x7a, 0x19, 0x06, 0x87, 0x01, 0x99, 0x59, 0x48, 0xd0, 0xe1, 0x04, 0x6e, 0x6f, 0x68, 0x64, 0x59, 0x7f, 0x16, 0x7c, - 0xf8, 0x68, 0x34, 0x8a, 0xcb, 0x2b, 0xbc, 0xd4, 0xe9, 0x8d, 0x84, 0x80, 0xc7, 0x19, 0xaf, 0x4c, 0x88, 0x88, 0x65, - 0x5c, 0x9d, 0xab, 0xd8, 0x2c, 0x95, 0xd9, 0x8a, 0x10, 0x71, 0xfe, 0x1c, 0x70, 0xea, 0xcd, 0xde, 0x8c, 0xb1, 0x1f, - 0x92, 0x23, 0x56, 0x01, 0x64, 0x9f, 0xad, 0xd5, 0xbb, 0x8b, 0xb8, 0xe2, 0xef, 0xe2, 0x7a, 0xc9, 0xa0, 0x97, 0x70, - 0x17, 0x29, 0x78, 0x52, 0x3b, 0x6c, 0x93, 0x04, 0x2a, 0xcf, 0x14, 0x50, 0x79, 0xc7, 0x7b, 0x1a, 0x9a, 0x61, 0x51, - 0x3e, 0xc0, 0x5a, 0xba, 0x9c, 0x81, 0xd1, 0xe2, 0x8b, 0x1b, 0x5e, 0xd4, 0x3f, 0x01, 0x9e, 0x7a, 0xc1, 0x4b, 0xb8, - 0x25, 0x20, 0x17, 0xeb, 0x39, 0x21, 0xd0, 0xca, 0xf5, 0xec, 0x90, 0x51, 0x63, 0xb4, 0x68, 0xc2, 0xeb, 0x37, 0xde, - 0x84, 0xd0, 0xbb, 0x13, 0x74, 0x45, 0x18, 0x09, 0xef, 0xcf, 0x35, 0x3f, 0xcf, 0xc0, 0x7c, 0xbe, 0x02, 0x28, 0x0d, - 0x84, 0x43, 0x65, 0x52, 0x6e, 0x81, 0x09, 0x1b, 0x6d, 0xae, 0x94, 0xa5, 0x0e, 0x52, 0x29, 0x95, 0x70, 0xba, 0x15, - 0x4d, 0x05, 0xe0, 0x70, 0x47, 0x02, 0xc0, 0x4c, 0x4d, 0x61, 0x10, 0xdd, 0x36, 0xa5, 0x59, 0x1a, 0x59, 0x45, 0x9a, - 0xc5, 0x27, 0xa5, 0x12, 0x74, 0xfa, 0x3c, 0x89, 0x6b, 0x7e, 0x25, 0x4a, 0x08, 0x85, 0xdb, 0x4a, 0x69, 0x0c, 0x16, - 0x80, 0x3c, 0xee, 0xac, 0xcd, 0xd6, 0xac, 0x94, 0x29, 0xe7, 0xc5, 0xfa, 0x9a, 0x97, 0x59, 0x72, 0xbe, 0xcc, 0xaa, - 0x5a, 0x94, 0xf7, 0x6c, 0xae, 0xb2, 0x2e, 0xa2, 0x6a, 0xa4, 0x24, 0x5e, 0xe7, 0x35, 0xbf, 0x5e, 0x41, 0xe8, 0x87, - 0x75, 0x09, 0xac, 0xe7, 0xde, 0x2f, 0x65, 0x64, 0xd2, 0xb0, 0xf3, 0x3b, 0xb2, 0x00, 0xbd, 0x2b, 0xac, 0x11, 0xb9, - 0x00, 0x98, 0x5e, 0x33, 0xa7, 0x92, 0xaa, 0x94, 0xfe, 0x6b, 0x8d, 0x33, 0xef, 0x2f, 0xaa, 0x71, 0x6b, 0xed, 0x19, - 0xad, 0xad, 0x9f, 0x2a, 0xe1, 0x94, 0x80, 0x12, 0xb1, 0x13, 0x5c, 0x31, 0x29, 0x5d, 0x1b, 0xb4, 0x16, 0xb0, 0xac, - 0xc0, 0x1c, 0x59, 0x71, 0x75, 0x7e, 0x2b, 0x65, 0x35, 0x3d, 0x49, 0xcd, 0xd2, 0x28, 0x96, 0x28, 0x42, 0x4b, 0x16, - 0xae, 0x59, 0xb2, 0x27, 0xd7, 0x3a, 0x4a, 0x3c, 0x3c, 0xb0, 0xb8, 0x3d, 0xe8, 0xc7, 0x49, 0x3b, 0x65, 0xbb, 0xdd, - 0xc9, 0x04, 0x6c, 0x48, 0x2b, 0x09, 0x22, 0x83, 0x2c, 0x67, 0xc3, 0x49, 0x04, 0x70, 0x2d, 0x8a, 0x84, 0xfe, 0xb9, - 0xe6, 0x1a, 0xd0, 0x3e, 0x54, 0x5e, 0x85, 0x72, 0x15, 0xcd, 0xc1, 0xce, 0xcb, 0xed, 0x35, 0x04, 0x96, 0xe9, 0x9c, - 0x97, 0xc5, 0xfe, 0x35, 0xa0, 0xcc, 0x91, 0xd5, 0x0b, 0xb2, 0x6f, 0xc6, 0x55, 0xb6, 0x07, 0xa7, 0xb7, 0x35, 0x07, - 0x7b, 0x5b, 0xa3, 0x50, 0x7a, 0x13, 0x1e, 0x0e, 0x9f, 0x8e, 0x8d, 0x3f, 0x03, 0xae, 0x72, 0xf3, 0x5b, 0xee, 0x04, - 0xfb, 0x6c, 0x76, 0x03, 0xf5, 0x5d, 0x22, 0xda, 0x35, 0xd2, 0x6a, 0xcf, 0xb8, 0x35, 0xa4, 0xb1, 0x2b, 0xcd, 0x88, - 0xb9, 0x7e, 0x97, 0x47, 0xeb, 0xf9, 0xa3, 0x4d, 0xa6, 0xaa, 0x6c, 0x7e, 0xcf, 0x4c, 0x50, 0x3c, 0x8f, 0x4c, 0x35, - 0x6a, 0x0d, 0xba, 0x98, 0x74, 0x1d, 0xd9, 0xd4, 0x8c, 0xb2, 0xac, 0x93, 0xd6, 0x8d, 0xe4, 0x23, 0x97, 0x31, 0xc2, - 0xba, 0xb3, 0xf0, 0x3b, 0x9e, 0x84, 0x5d, 0x0d, 0x93, 0xd7, 0x10, 0xdd, 0x05, 0x84, 0xe9, 0x04, 0xe5, 0x43, 0xf8, - 0xfb, 0xa3, 0x8d, 0x4f, 0x3b, 0x9b, 0x43, 0xe7, 0x33, 0xfc, 0x9d, 0xa5, 0xf0, 0xb7, 0x6e, 0x7e, 0xa7, 0x9b, 0x6b, - 0x5e, 0x2f, 0x45, 0x1a, 0x05, 0xef, 0xde, 0x9e, 0x7d, 0x08, 0x14, 0xfc, 0x3b, 0x5e, 0x82, 0xb4, 0xda, 0x5b, 0x03, - 0x4d, 0x81, 0x1a, 0x28, 0x17, 0x57, 0x88, 0x80, 0xa8, 0x20, 0xf4, 0xcf, 0x96, 0xe2, 0xf6, 0x34, 0xcf, 0x5d, 0x4e, - 0x5d, 0x53, 0x77, 0xc5, 0xbc, 0x7a, 0xa4, 0x31, 0x04, 0x81, 0xe3, 0x28, 0xab, 0xce, 0x95, 0x8a, 0x28, 0x3d, 0xbf, - 0xb8, 0x3f, 0x57, 0x62, 0x28, 0x03, 0x41, 0xf9, 0xec, 0xf7, 0xe3, 0x34, 0xbb, 0x39, 0xc0, 0x23, 0x88, 0x05, 0x60, - 0xbf, 0x9f, 0xf3, 0x8b, 0x75, 0x5d, 0x8b, 0x62, 0x58, 0x8a, 0xdb, 0xe0, 0xe4, 0x58, 0x3e, 0xe8, 0x0c, 0xb1, 0x7c, - 0x0c, 0x0e, 0xfe, 0x2b, 0xc9, 0xb3, 0xe4, 0x23, 0x0b, 0x1e, 0x6d, 0x32, 0x76, 0xd2, 0x3a, 0x68, 0xc6, 0x4d, 0x70, - 0x02, 0x6d, 0x3d, 0x38, 0xcd, 0xf3, 0xe3, 0x43, 0xf9, 0xc5, 0xc9, 0xf1, 0x61, 0x9a, 0xdd, 0x9c, 0x38, 0xd1, 0x00, - 0xac, 0x71, 0x2f, 0xe2, 0xae, 0xd9, 0xcb, 0x3b, 0x78, 0xf1, 0x26, 0x3c, 0x34, 0xec, 0x0e, 0x88, 0x8c, 0x74, 0x2c, - 0x15, 0x14, 0x33, 0x85, 0x31, 0x1c, 0xee, 0xdb, 0x6d, 0x68, 0x2c, 0x8f, 0x12, 0x07, 0x96, 0xa7, 0x04, 0x76, 0x08, - 0xb3, 0xd0, 0x84, 0xd0, 0xa4, 0x21, 0xa1, 0x06, 0x0f, 0x8a, 0x09, 0x2d, 0x1b, 0x0a, 0xe7, 0xdd, 0xeb, 0x78, 0xa5, - 0x25, 0x6d, 0x4a, 0x72, 0xa1, 0x5b, 0x3f, 0xf3, 0xc6, 0x31, 0x6a, 0x8f, 0xaa, 0x86, 0xf3, 0xea, 0x15, 0xfb, 0x06, - 0x16, 0x84, 0xab, 0x61, 0x4d, 0x83, 0x16, 0x69, 0x01, 0xe1, 0xa8, 0x2b, 0xd3, 0xe3, 0x34, 0x9c, 0x17, 0x54, 0x2c, - 0x08, 0x3b, 0x09, 0x37, 0xc8, 0xdb, 0x17, 0x54, 0xb2, 0xfa, 0xa2, 0xb1, 0xd8, 0x9a, 0x72, 0x76, 0x4e, 0x1e, 0x6d, - 0x64, 0xcc, 0xde, 0x82, 0x9d, 0xf8, 0xf3, 0x55, 0xc7, 0x17, 0xc3, 0x25, 0x07, 0x27, 0xa0, 0xe0, 0xe0, 0xbf, 0xd2, - 0x8b, 0xdc, 0x4c, 0x8a, 0x5c, 0x91, 0xcb, 0xb8, 0x48, 0x73, 0xfe, 0x21, 0xbe, 0xf8, 0x01, 0xf3, 0x3c, 0xbf, 0xc8, - 0x9f, 0x41, 0x86, 0x26, 0x38, 0x79, 0xb4, 0x49, 0xea, 0xd1, 0x8b, 0x37, 0x1f, 0x5e, 0x7d, 0xf8, 0xe7, 0xf9, 0xb3, - 0xd3, 0x0f, 0x2f, 0xbe, 0x7f, 0xfb, 0xfe, 0xd5, 0x8b, 0xb3, 0xb9, 0xf1, 0xba, 0x95, 0x60, 0x6e, 0x64, 0xb1, 0xdd, - 0xda, 0x7c, 0xbf, 0xbc, 0x79, 0xfe, 0xe2, 0xe5, 0xab, 0x37, 0x2f, 0x9e, 0x37, 0x72, 0x2e, 0xdb, 0x0d, 0x81, 0x1d, - 0x1a, 0x67, 0x05, 0x2f, 0xa1, 0x78, 0x75, 0xbb, 0xc3, 0x66, 0x2b, 0x0c, 0x42, 0xbf, 0xe9, 0x2a, 0x5c, 0x03, 0x2c, - 0xb2, 0x03, 0xb5, 0x59, 0xa0, 0xe1, 0x42, 0x6f, 0x1c, 0x77, 0x89, 0xb9, 0xbd, 0x79, 0x81, 0xdf, 0xbd, 0x17, 0xb7, - 0xba, 0x2b, 0x6a, 0x84, 0x24, 0xbc, 0xd8, 0xec, 0xd9, 0xef, 0xc7, 0xae, 0x48, 0x0f, 0xe5, 0x1e, 0xb2, 0x5c, 0xf8, - 0xd5, 0x04, 0x07, 0xca, 0xbc, 0x30, 0x80, 0xe8, 0x18, 0xc1, 0xc9, 0xf1, 0xa1, 0x9b, 0xfb, 0xe4, 0xf7, 0xe8, 0x27, - 0xa7, 0x73, 0x58, 0x2a, 0x8c, 0x83, 0x9f, 0xb6, 0x73, 0x2c, 0x02, 0x7d, 0xb6, 0x07, 0xa7, 0x5c, 0x41, 0x9a, 0x5c, - 0x09, 0x12, 0x99, 0x49, 0x94, 0x66, 0x33, 0xba, 0xb4, 0xdf, 0xd5, 0x5f, 0xdb, 0x67, 0x14, 0x43, 0xf0, 0xa2, 0x12, - 0x25, 0xd8, 0xb8, 0x38, 0x89, 0x49, 0x0e, 0x82, 0x0f, 0x1e, 0x40, 0xef, 0xda, 0xa1, 0x2e, 0x0e, 0x9c, 0x90, 0x32, - 0xd8, 0xcf, 0x4e, 0xa2, 0x0f, 0xe3, 0x74, 0xd8, 0xfe, 0xd4, 0xe9, 0xee, 0xef, 0xc4, 0xfe, 0x38, 0x50, 0x5d, 0x6c, - 0x11, 0x1d, 0xd3, 0xec, 0xfd, 0x21, 0x49, 0xe6, 0x6f, 0xff, 0x4f, 0x73, 0x4f, 0xbb, 0xdd, 0xb6, 0x71, 0xe5, 0xff, - 0x3e, 0x05, 0x0c, 0xbb, 0x0e, 0x60, 0x03, 0x10, 0x40, 0x8a, 0x92, 0x4c, 0x8a, 0x52, 0x13, 0xdb, 0x39, 0x51, 0xaa, - 0xd4, 0x39, 0x8e, 0xea, 0x6d, 0xa3, 0xe8, 0x98, 0x43, 0x70, 0x48, 0xa2, 0x02, 0x01, 0x1e, 0x00, 0x94, 0xa8, 0xd0, - 0xe8, 0x53, 0xec, 0xff, 0xed, 0x73, 0xec, 0xfe, 0xeb, 0x13, 0xed, 0x23, 0xec, 0xb9, 0x77, 0x3e, 0x30, 0xf8, 0x22, - 0xa9, 0xc4, 0x69, 0xf7, 0xa4, 0xaa, 0x89, 0xc1, 0xcc, 0x60, 0xe6, 0xce, 0xcc, 0x9d, 0xfb, 0x7d, 0x03, 0xeb, 0x3f, - 0x62, 0x6b, 0x46, 0xac, 0x05, 0xb1, 0x6e, 0xd3, 0x9b, 0xbc, 0x71, 0xcd, 0x64, 0xba, 0x1b, 0x4c, 0x89, 0x68, 0x18, - 0x10, 0x37, 0x83, 0x73, 0x33, 0x9c, 0xc6, 0x0f, 0xc4, 0x05, 0x77, 0x45, 0x92, 0x19, 0x15, 0x89, 0x66, 0xc4, 0xdb, - 0x8c, 0x43, 0xc6, 0x2c, 0xc1, 0xcb, 0x30, 0xe8, 0xe3, 0xba, 0xa1, 0x6a, 0x37, 0x02, 0xc2, 0x18, 0x43, 0xf3, 0x09, - 0xb7, 0xac, 0x08, 0x1c, 0x3f, 0x4b, 0xc2, 0x3f, 0xd2, 0x07, 0x20, 0x5e, 0xd3, 0x2c, 0x5e, 0x02, 0xcb, 0x42, 0x66, - 0x5c, 0x04, 0x65, 0x19, 0xe9, 0x7e, 0x1f, 0x84, 0x64, 0x59, 0xb8, 0xe9, 0x81, 0xee, 0x75, 0xb2, 0x78, 0x36, 0x0b, - 0xa9, 0xa1, 0x8b, 0x1c, 0x2a, 0xba, 0x25, 0x3f, 0x73, 0xfe, 0xc4, 0x15, 0x81, 0x4b, 0xcd, 0xbc, 0xed, 0xf0, 0x0a, - 0xe8, 0x51, 0x19, 0xd9, 0x8f, 0x11, 0xf0, 0x28, 0xa2, 0xbe, 0x43, 0x2d, 0x0f, 0x5f, 0xe3, 0x02, 0x39, 0xd8, 0x93, - 0x78, 0x35, 0x0e, 0xa9, 0x8d, 0x07, 0x0a, 0x3e, 0xb9, 0x19, 0xaf, 0xc6, 0x63, 0x48, 0x56, 0xf3, 0xc4, 0xb5, 0x20, - 0xfc, 0x4e, 0x9c, 0x22, 0x5b, 0x9c, 0x9b, 0x03, 0x80, 0xa2, 0x93, 0x95, 0x87, 0xcf, 0xb2, 0x77, 0x82, 0xc4, 0x8b, - 0x7d, 0x20, 0x03, 0x16, 0xb8, 0x01, 0x2f, 0x0c, 0xf5, 0x1f, 0x60, 0x7f, 0xa7, 0xfa, 0xa0, 0x09, 0xb9, 0x0c, 0xaf, - 0xf5, 0x1f, 0x70, 0xb1, 0x30, 0x89, 0xf3, 0x6b, 0x76, 0x3e, 0x74, 0x4b, 0x67, 0xba, 0xff, 0x15, 0xa6, 0x73, 0x00, - 0xd9, 0xf7, 0x9b, 0x80, 0xcc, 0xa2, 0x38, 0xcd, 0x02, 0x5f, 0xbf, 0x19, 0x5c, 0x04, 0xc6, 0xf5, 0x22, 0x33, 0xcc, - 0x1b, 0xcb, 0xcf, 0xd4, 0x4c, 0x30, 0x02, 0x25, 0x63, 0x22, 0x98, 0xb6, 0x4a, 0xea, 0x19, 0xdd, 0x5a, 0x51, 0x20, - 0x7f, 0xac, 0xe4, 0x67, 0x43, 0xa8, 0x57, 0x49, 0x2b, 0x83, 0xf9, 0xb1, 0x74, 0x6c, 0x69, 0x0e, 0x18, 0xc3, 0xf6, - 0x7a, 0xb5, 0x41, 0x62, 0x21, 0x2b, 0xee, 0x63, 0x0c, 0x85, 0x2c, 0xfc, 0x87, 0xd8, 0xf3, 0x13, 0xd5, 0xf6, 0xb5, - 0x74, 0xb3, 0x8f, 0xbe, 0x2c, 0x53, 0x1e, 0x40, 0x21, 0x80, 0xe1, 0x49, 0x14, 0x67, 0x1a, 0xc4, 0xf7, 0x81, 0x2f, - 0x8e, 0xaa, 0xb6, 0x72, 0xbc, 0x57, 0xc3, 0xcc, 0x39, 0xba, 0xf9, 0x0a, 0xaf, 0x57, 0x83, 0x47, 0x79, 0x2b, 0x05, - 0xf2, 0x60, 0x3c, 0x53, 0x0a, 0x0b, 0x98, 0xc5, 0x97, 0xf1, 0x7d, 0x55, 0x1d, 0xf4, 0x7a, 0xb4, 0xfb, 0x76, 0x37, - 0x04, 0x05, 0x2f, 0x92, 0x1b, 0x1a, 0x3c, 0x3f, 0xab, 0x20, 0xa5, 0x2a, 0xa7, 0x0a, 0xed, 0x5f, 0x04, 0x95, 0x94, - 0x81, 0xb9, 0x1c, 0xde, 0x36, 0x80, 0xf4, 0x38, 0x21, 0x30, 0xca, 0x91, 0x6c, 0x95, 0xc9, 0x9f, 0x84, 0xc3, 0x4b, - 0x79, 0xdc, 0xe9, 0x10, 0xa5, 0xb2, 0xf3, 0x60, 0x36, 0xd7, 0xcf, 0x33, 0xbe, 0x23, 0x55, 0x7a, 0xf7, 0x23, 0xbc, - 0xea, 0x37, 0xbd, 0x81, 0x84, 0x54, 0x0d, 0xf5, 0xc3, 0xf8, 0x1e, 0xbc, 0xd9, 0x8b, 0x5e, 0x39, 0x35, 0xdd, 0xda, - 0xb9, 0xf9, 0x52, 0xd6, 0x80, 0xac, 0xe2, 0x66, 0x7f, 0x4b, 0x83, 0xf6, 0x6f, 0x56, 0x7b, 0xb1, 0xe2, 0x47, 0x8d, - 0xc1, 0xfe, 0x2c, 0x63, 0xa8, 0xf4, 0x32, 0x88, 0x86, 0xd1, 0x99, 0x2c, 0x5a, 0x90, 0x35, 0x36, 0x30, 0xcf, 0xeb, - 0x45, 0xfd, 0xc8, 0x8a, 0x87, 0xf1, 0x9e, 0x75, 0x63, 0x6e, 0x78, 0x4c, 0xcf, 0x47, 0x29, 0xcd, 0xce, 0x1b, 0xc6, - 0x02, 0x1b, 0x61, 0xf8, 0x6c, 0x13, 0xe5, 0xa3, 0x7e, 0x4b, 0x15, 0xf6, 0xd6, 0x22, 0xbb, 0x3b, 0x89, 0xb7, 0x76, - 0x12, 0xe7, 0xa3, 0xc7, 0x6c, 0x73, 0x9f, 0xef, 0xf2, 0x70, 0xe0, 0x37, 0x61, 0xfa, 0xb0, 0x71, 0xcf, 0x43, 0x30, - 0xda, 0xd2, 0x6e, 0x4f, 0x70, 0xb7, 0xff, 0xef, 0x7f, 0xfd, 0xe7, 0x7f, 0x17, 0x64, 0xef, 0x38, 0x39, 0x3b, 0xc5, - 0x8c, 0x64, 0x40, 0xc5, 0xe5, 0xa7, 0x07, 0xec, 0x37, 0x16, 0xff, 0x8b, 0x46, 0x45, 0xc4, 0xa8, 0xfe, 0x47, 0x3d, - 0x83, 0x22, 0x8b, 0xbb, 0xc8, 0xa1, 0xae, 0x90, 0xe0, 0x40, 0x43, 0x45, 0xcb, 0x55, 0x86, 0x51, 0xbf, 0x61, 0x1c, - 0x34, 0xd7, 0x35, 0x8c, 0x22, 0x0c, 0xb4, 0x58, 0xc1, 0x0c, 0xe6, 0xba, 0x16, 0x4c, 0xea, 0x65, 0x9c, 0xc9, 0x05, - 0x62, 0x04, 0xa9, 0x38, 0x94, 0x99, 0xc3, 0x63, 0xc2, 0xa7, 0xe3, 0x5b, 0x45, 0xca, 0x0c, 0xc3, 0x47, 0xdd, 0x72, - 0xc3, 0xfd, 0xec, 0xb3, 0x7e, 0x06, 0xfb, 0x4e, 0x73, 0x04, 0xf0, 0x3d, 0x87, 0xed, 0x33, 0x7c, 0xb6, 0x21, 0xc0, - 0xaf, 0xe5, 0x3a, 0x4c, 0xb4, 0xf0, 0x19, 0x2c, 0xa6, 0x07, 0x88, 0x9d, 0x95, 0x6b, 0x68, 0x34, 0x34, 0xe4, 0xa6, - 0x41, 0xcb, 0x24, 0x58, 0x90, 0xe4, 0x81, 0x59, 0x12, 0x59, 0xaa, 0xb9, 0x91, 0xa9, 0x6b, 0x8c, 0x7a, 0x63, 0xf3, - 0x65, 0x84, 0x9c, 0xae, 0xfd, 0x41, 0x96, 0x51, 0x3e, 0x39, 0x81, 0xbe, 0x74, 0xf8, 0xd6, 0x47, 0xfd, 0x25, 0x75, - 0x26, 0x34, 0x23, 0x41, 0xc8, 0x9a, 0x0c, 0x8c, 0xa8, 0x65, 0x36, 0x51, 0x79, 0x36, 0x69, 0x19, 0x65, 0xe3, 0x64, - 0x18, 0x05, 0xc7, 0xc6, 0x8d, 0x33, 0x43, 0x14, 0xda, 0xbc, 0x80, 0xec, 0x9d, 0xb2, 0x97, 0x00, 0xf8, 0x49, 0x7d, - 0x17, 0xe5, 0xed, 0x4b, 0xd4, 0x50, 0xfb, 0xb7, 0x59, 0x36, 0x0a, 0xcb, 0x96, 0xc2, 0xb2, 0xd1, 0xc8, 0x8f, 0x27, - 0xf4, 0xcf, 0xef, 0x2f, 0x64, 0xa6, 0x3f, 0x10, 0x5a, 0x8f, 0xf8, 0x25, 0x12, 0x21, 0x37, 0x91, 0x20, 0x27, 0xc1, - 0x72, 0xf2, 0x69, 0x72, 0xab, 0x25, 0xb9, 0xae, 0x9d, 0xb3, 0x49, 0xd3, 0x09, 0x9b, 0xc9, 0x30, 0xc6, 0x56, 0x49, - 0x7e, 0x7a, 0xc0, 0x6a, 0x33, 0x2a, 0x97, 0x55, 0x02, 0xf8, 0x25, 0x30, 0xeb, 0x02, 0x7c, 0x90, 0x94, 0x78, 0xe8, - 0x15, 0xe2, 0x05, 0x67, 0x81, 0xaa, 0x41, 0xef, 0xbc, 0xcc, 0xb8, 0x60, 0x2b, 0xbd, 0x38, 0xd4, 0x31, 0x04, 0x26, - 0x12, 0xe7, 0x5a, 0xab, 0x9c, 0x9c, 0xa2, 0x13, 0x21, 0xf2, 0xe9, 0xf3, 0x0e, 0x1e, 0x75, 0xa4, 0x00, 0x6b, 0x43, - 0x29, 0xc9, 0x75, 0x6d, 0xc1, 0x19, 0x25, 0x1e, 0x01, 0x0d, 0xc2, 0xa3, 0xb8, 0x70, 0xcf, 0xea, 0xda, 0x82, 0xac, - 0x71, 0xe6, 0xe2, 0x0d, 0x59, 0x1b, 0x1e, 0x7f, 0x55, 0x9c, 0xc9, 0xa8, 0xbc, 0xe0, 0x02, 0xc5, 0x80, 0xef, 0x93, - 0x14, 0xd0, 0xcd, 0xd1, 0xa6, 0xa4, 0x61, 0x71, 0xe7, 0x62, 0x71, 0x27, 0x2d, 0x8b, 0x3b, 0xd9, 0xb2, 0xb8, 0x21, - 0x5f, 0x48, 0x4d, 0x82, 0x2e, 0x41, 0x7f, 0xd6, 0x02, 0x29, 0x32, 0x06, 0xa3, 0xcf, 0x0f, 0x28, 0xc2, 0xc9, 0x4e, - 0x43, 0xb0, 0xe7, 0x6c, 0x81, 0x55, 0x13, 0x5c, 0x14, 0x40, 0xd4, 0x27, 0x2e, 0x8f, 0xab, 0x44, 0xad, 0xd6, 0x1c, - 0xb6, 0xaa, 0x5f, 0xa5, 0x79, 0x43, 0xd6, 0xd0, 0x32, 0xe6, 0x2d, 0x33, 0x9d, 0x6f, 0x99, 0xa9, 0x5f, 0x3a, 0xf3, - 0x7c, 0xda, 0xec, 0xf4, 0xaa, 0x93, 0x62, 0xa4, 0xd0, 0x3a, 0xc3, 0x2d, 0x53, 0xde, 0x87, 0xed, 0xb8, 0x58, 0xd9, - 0x51, 0x4b, 0x92, 0xa6, 0xf7, 0x71, 0x02, 0x4a, 0x62, 0xe8, 0xe6, 0x71, 0x5b, 0x6a, 0x11, 0x44, 0x3c, 0xfe, 0x54, - 0xeb, 0x66, 0x2a, 0xde, 0xab, 0x5b, 0xaa, 0xd3, 0xeb, 0xb1, 0x1a, 0x4b, 0x92, 0x65, 0x34, 0x41, 0xa0, 0x13, 0x48, - 0x54, 0xf0, 0xff, 0x64, 0x9b, 0x35, 0xe0, 0x90, 0xd0, 0x2c, 0xae, 0x03, 0x44, 0xed, 0x4b, 0xe0, 0x83, 0x12, 0x41, - 0x34, 0x2b, 0xb1, 0x2c, 0x13, 0x09, 0x78, 0x4e, 0xdf, 0x24, 0x8a, 0xb7, 0xa5, 0x77, 0x64, 0x3a, 0x4b, 0x32, 0xf9, - 0x01, 0x6c, 0x11, 0x8c, 0x8e, 0x05, 0x7e, 0x05, 0x6a, 0xe4, 0xca, 0x84, 0x31, 0x66, 0x7e, 0x81, 0x24, 0x11, 0x4b, - 0x72, 0xab, 0x4d, 0x70, 0xf8, 0x26, 0xf6, 0xf4, 0x66, 0xd3, 0xc9, 0x0f, 0x66, 0x81, 0x59, 0xc3, 0x9a, 0x80, 0xda, - 0xc2, 0xe1, 0x99, 0x94, 0xc0, 0x84, 0x96, 0x77, 0x64, 0x82, 0xb2, 0xea, 0x1a, 0x52, 0x30, 0xbb, 0x42, 0xbc, 0x35, - 0x4a, 0xe0, 0x76, 0xbb, 0x76, 0x6f, 0xf2, 0xe7, 0x33, 0xfc, 0xe5, 0xdd, 0xe4, 0xcf, 0xc7, 0xf8, 0xab, 0x73, 0x83, - 0xc9, 0x36, 0x1b, 0xc4, 0x7a, 0xca, 0x9c, 0xf5, 0xb3, 0xd2, 0x7e, 0x62, 0x26, 0xb3, 0x8f, 0xd8, 0x36, 0x7c, 0x81, - 0x9f, 0x3e, 0xdb, 0x44, 0xe0, 0x24, 0xae, 0xce, 0x21, 0x75, 0x12, 0x33, 0x6f, 0x2c, 0x9f, 0xb5, 0x94, 0x8f, 0xcd, - 0x7f, 0x31, 0x81, 0x80, 0xbb, 0x24, 0x2e, 0xee, 0x94, 0xb2, 0x50, 0xf2, 0xe3, 0x38, 0x88, 0x48, 0xf2, 0xf0, 0x91, - 0xc9, 0x14, 0x0c, 0xc1, 0x67, 0x4b, 0x61, 0x2b, 0x63, 0x05, 0xcb, 0x1a, 0xfa, 0x4c, 0xd1, 0x49, 0x3d, 0x70, 0x0a, - 0x61, 0xf8, 0x97, 0x44, 0xa1, 0x3d, 0x4b, 0xe2, 0x28, 0xbe, 0x20, 0xa5, 0x0f, 0x7d, 0x7c, 0xb6, 0x31, 0x68, 0xbd, - 0x9b, 0x9a, 0xb8, 0xa2, 0x44, 0x10, 0xc0, 0xf2, 0xa0, 0x68, 0x6b, 0x31, 0x09, 0xfa, 0xa8, 0x82, 0x1f, 0xc7, 0x6b, - 0xfb, 0xd9, 0x26, 0x3b, 0xd7, 0x17, 0x24, 0xb9, 0xa5, 0x13, 0xdb, 0x0f, 0x12, 0x3f, 0xa4, 0x7a, 0x5f, 0x1f, 0x87, - 0x24, 0xba, 0xe5, 0x8f, 0x76, 0xbc, 0xca, 0xd0, 0xa8, 0x66, 0xa7, 0x24, 0x4c, 0xc0, 0x84, 0x09, 0xf0, 0x91, 0x41, - 0x6b, 0x80, 0x82, 0xf6, 0x5a, 0x8a, 0xbf, 0x0b, 0x82, 0xb2, 0xa8, 0x65, 0x81, 0x4d, 0x38, 0xd8, 0xf9, 0x80, 0x93, - 0xbd, 0xa5, 0xe3, 0x7a, 0xe9, 0x96, 0x3a, 0x55, 0xa6, 0xf7, 0x90, 0x59, 0x62, 0x3f, 0x62, 0x0f, 0xbf, 0xfc, 0x73, - 0x50, 0xf2, 0x98, 0xcf, 0x71, 0xe2, 0xb0, 0xfd, 0x83, 0x6a, 0x63, 0x92, 0xa6, 0xab, 0x05, 0x9d, 0x30, 0x7b, 0x82, - 0xf3, 0x62, 0x28, 0x65, 0x46, 0x5c, 0x1d, 0xce, 0x4f, 0xab, 0xce, 0xf1, 0xe1, 0x6b, 0xb0, 0x73, 0x02, 0x62, 0x30, - 0x9e, 0x4e, 0xf5, 0x42, 0xbc, 0xb6, 0xa3, 0x99, 0x77, 0xf8, 0xd3, 0xea, 0xeb, 0xb7, 0xee, 0xd7, 0xb2, 0x71, 0xa4, - 0x9b, 0xf9, 0x48, 0x18, 0x6d, 0x70, 0x9a, 0x56, 0x19, 0xaf, 0x98, 0xd1, 0x94, 0x44, 0xed, 0xd3, 0xb9, 0x2e, 0xed, - 0xb2, 0x25, 0xa5, 0x13, 0xb0, 0xe7, 0xb7, 0x6a, 0xa5, 0x1f, 0x43, 0x7a, 0x47, 0xa5, 0x41, 0x48, 0xfd, 0x63, 0x0d, - 0x2d, 0x30, 0x62, 0x25, 0x37, 0x34, 0xe1, 0x84, 0x95, 0x32, 0xa5, 0x11, 0xce, 0x81, 0xcf, 0x5c, 0xdd, 0xe5, 0x95, - 0x5d, 0x3d, 0xb2, 0x74, 0x65, 0x00, 0xad, 0x23, 0x3b, 0x6f, 0x29, 0xef, 0x63, 0xba, 0xfa, 0xe6, 0xb1, 0x59, 0x9e, - 0xd9, 0x87, 0x08, 0xff, 0x1c, 0x4e, 0x21, 0x6c, 0x7e, 0x43, 0x4a, 0x22, 0x07, 0x6d, 0x10, 0x6b, 0x92, 0x5a, 0xeb, - 0x4c, 0xf0, 0x29, 0x6c, 0xa4, 0xd1, 0x59, 0x40, 0x08, 0x86, 0x1b, 0xd7, 0x46, 0x2b, 0xcf, 0x7c, 0x8c, 0x69, 0xa0, - 0x23, 0x9a, 0xa6, 0xad, 0x00, 0x93, 0x8b, 0x6e, 0xe9, 0x45, 0xed, 0x32, 0x3c, 0x8a, 0x72, 0xcb, 0xb5, 0xe0, 0x56, - 0xc6, 0x09, 0x56, 0xbf, 0x85, 0x18, 0xfe, 0xe3, 0x82, 0x5b, 0xb9, 0x25, 0xb3, 0xb1, 0xce, 0x2d, 0x90, 0xda, 0xde, - 0xdf, 0xeb, 0x7c, 0x50, 0xa5, 0x9b, 0xb2, 0x71, 0x68, 0x46, 0x09, 0xfb, 0xd5, 0xc4, 0xb4, 0xd8, 0x81, 0x18, 0x53, - 0x05, 0xc5, 0xd1, 0xe9, 0x94, 0xfa, 0x59, 0x6a, 0x0a, 0x59, 0xab, 0x8c, 0x39, 0x0d, 0xbe, 0x86, 0x4f, 0x86, 0xfa, - 0x9f, 0x20, 0xf2, 0x86, 0x08, 0xcd, 0xc6, 0x07, 0x24, 0xf8, 0x9d, 0x66, 0x30, 0xb1, 0x1e, 0xcb, 0x20, 0xe2, 0x5f, - 0xf9, 0xf4, 0x49, 0x98, 0x48, 0x94, 0xca, 0x71, 0x68, 0xfc, 0x0a, 0x28, 0xf6, 0x45, 0x2c, 0x6d, 0xe1, 0xb6, 0x23, - 0xa0, 0x6d, 0xc7, 0x77, 0xe3, 0x7d, 0xdd, 0xf3, 0xdc, 0x5c, 0xb7, 0xc0, 0xe3, 0xf3, 0x76, 0xdf, 0x43, 0x8f, 0xad, - 0xba, 0xd0, 0x6a, 0x15, 0x3d, 0xa6, 0x5d, 0xc7, 0x7b, 0xe5, 0xe9, 0x16, 0x33, 0xb4, 0x55, 0x70, 0x9b, 0x1f, 0xdf, - 0xd1, 0xe4, 0x57, 0x4f, 0xa5, 0xdc, 0xf9, 0x7e, 0xe3, 0x39, 0xf2, 0x5c, 0x40, 0xc2, 0x59, 0xbc, 0x7c, 0xc4, 0x14, - 0xba, 0xba, 0xa5, 0xfb, 0x61, 0x9c, 0x52, 0x75, 0x0e, 0x4c, 0x5e, 0xf1, 0x2b, 0x27, 0xf1, 0xfd, 0xfb, 0xb7, 0x3f, - 0xfc, 0xa0, 0x5b, 0x98, 0x3f, 0x38, 0x55, 0x7b, 0xe7, 0x1b, 0x6a, 0x07, 0xf6, 0x6f, 0xdc, 0x77, 0xec, 0x86, 0x61, - 0x7c, 0x65, 0x79, 0xcf, 0xb1, 0xb2, 0xda, 0x96, 0xe3, 0x37, 0x0f, 0xff, 0x32, 0x63, 0x06, 0xf7, 0x9a, 0x57, 0x03, - 0x6e, 0xd8, 0x7e, 0xbd, 0x95, 0x4a, 0x16, 0x41, 0xf4, 0xb1, 0xa1, 0x94, 0xac, 0x1b, 0x4a, 0x51, 0x36, 0x58, 0xc5, - 0x1f, 0xab, 0x78, 0xa1, 0xdc, 0xce, 0x90, 0xfe, 0x7d, 0x17, 0xb8, 0x14, 0x96, 0xe6, 0x57, 0x0c, 0x9a, 0xe7, 0x7f, - 0xa8, 0x8e, 0xba, 0xa1, 0x98, 0xf3, 0x21, 0x12, 0xb6, 0x5c, 0x97, 0xa3, 0xaa, 0xc9, 0xcb, 0x94, 0x9b, 0xda, 0xb8, - 0x59, 0x60, 0xfa, 0xa4, 0x70, 0xbe, 0xd9, 0x51, 0x19, 0x84, 0xb4, 0xb2, 0x76, 0x41, 0x13, 0x6c, 0xed, 0x3d, 0xff, - 0xe7, 0x3f, 0x1c, 0xe7, 0x9f, 0xff, 0xd8, 0x59, 0x15, 0xfa, 0xce, 0x81, 0x1d, 0xde, 0x55, 0x33, 0x1f, 0xa1, 0xd0, - 0x29, 0x1b, 0xbe, 0x1e, 0x8d, 0x06, 0x46, 0x09, 0x64, 0xe0, 0x33, 0x72, 0x5e, 0x2b, 0xe1, 0x78, 0xb5, 0xef, 0x9a, - 0x18, 0xcc, 0x01, 0x1a, 0xca, 0xeb, 0xab, 0x75, 0xb3, 0x33, 0xa7, 0x84, 0x5a, 0x5f, 0xb5, 0x9d, 0x0e, 0xa5, 0x98, - 0xb8, 0x2e, 0x1f, 0x99, 0x3c, 0xc7, 0x00, 0x8c, 0x8b, 0xab, 0x0f, 0x4a, 0x2b, 0x07, 0x7e, 0x36, 0x59, 0x79, 0x7c, - 0xbc, 0xac, 0x32, 0x42, 0xba, 0xd7, 0x08, 0x59, 0xdb, 0xf2, 0x18, 0x79, 0x7f, 0xb5, 0x51, 0xb2, 0x72, 0x31, 0x4e, - 0x0b, 0x45, 0x66, 0x3c, 0xca, 0x08, 0x67, 0x9a, 0xb8, 0x4a, 0xb0, 0xa4, 0xf6, 0xad, 0xa8, 0x2e, 0x94, 0x21, 0xec, - 0x5e, 0xf6, 0x73, 0x3d, 0x8c, 0xef, 0xd1, 0x59, 0x4f, 0xd5, 0x27, 0x73, 0x61, 0xc8, 0x69, 0x9a, 0x25, 0x71, 0x34, - 0x3b, 0xab, 0x5c, 0xde, 0x75, 0x3b, 0x1f, 0x90, 0x60, 0xb1, 0xaa, 0x65, 0xb1, 0x89, 0x3a, 0xca, 0xed, 0x5b, 0xea, - 0x7c, 0xc7, 0x4c, 0x98, 0x6a, 0x42, 0xb9, 0x1c, 0x45, 0xd7, 0x0d, 0x6a, 0x70, 0x95, 0x94, 0x2b, 0xbf, 0x96, 0x8f, - 0x07, 0x1c, 0xae, 0x67, 0xa3, 0x1c, 0x93, 0x1d, 0xbd, 0x6b, 0x33, 0x10, 0xfd, 0x7e, 0xb7, 0x81, 0xe8, 0xd5, 0x5e, - 0x06, 0xa2, 0xdf, 0x7f, 0x76, 0x03, 0xd1, 0x77, 0xaa, 0x81, 0x28, 0x6c, 0xe9, 0xb7, 0x74, 0x2f, 0xab, 0x4d, 0x61, - 0x0d, 0x15, 0xdf, 0xa7, 0x43, 0x8f, 0x53, 0xa6, 0xa9, 0x3f, 0xa7, 0xc0, 0x6d, 0xf3, 0x6d, 0x1a, 0xc6, 0x33, 0xb0, - 0xe0, 0xfc, 0xed, 0x6d, 0x2d, 0xc3, 0x78, 0xa6, 0x5a, 0x5a, 0xa6, 0x3c, 0xdc, 0x73, 0x11, 0xc2, 0x8d, 0x59, 0x37, - 0xba, 0x96, 0x38, 0x7b, 0xf6, 0xa1, 0xa9, 0xa4, 0xb4, 0x97, 0xa6, 0xab, 0x1d, 0x61, 0xff, 0xd8, 0x47, 0xd3, 0x49, - 0xd9, 0xb0, 0xf3, 0x32, 0x96, 0x49, 0x7b, 0x8a, 0x1e, 0xa4, 0x8b, 0x00, 0x0b, 0x12, 0xb3, 0xd1, 0x7f, 0x5a, 0x7b, - 0x5f, 0x5d, 0x7b, 0x83, 0xae, 0x07, 0x91, 0x19, 0x80, 0x57, 0xc3, 0x02, 0x77, 0xd0, 0xed, 0x42, 0xc1, 0xbd, 0x52, - 0xd0, 0x81, 0x82, 0x40, 0x29, 0xe8, 0x41, 0x81, 0xaf, 0x14, 0x1c, 0x41, 0xc1, 0x44, 0x29, 0x38, 0x86, 0x82, 0x3b, - 0x3d, 0xbf, 0x2e, 0x12, 0x39, 0x1d, 0x9b, 0x37, 0x16, 0xe3, 0x0d, 0x44, 0xd9, 0xb1, 0xe5, 0x81, 0x19, 0x23, 0x99, - 0xf5, 0x63, 0x8b, 0xc9, 0xe9, 0xfa, 0x89, 0x75, 0x3f, 0xa7, 0x2c, 0x4a, 0xfc, 0x1b, 0xbc, 0x3a, 0x9c, 0x2c, 0x06, - 0xa7, 0x09, 0x11, 0x7d, 0x45, 0xc0, 0x41, 0xd3, 0x4d, 0x10, 0xbd, 0x0c, 0xe4, 0xca, 0x89, 0x08, 0x36, 0xca, 0x5a, - 0x16, 0xef, 0xd8, 0xe7, 0x6c, 0xb9, 0x05, 0x0a, 0x4b, 0x2e, 0x43, 0x95, 0xef, 0x7d, 0x0e, 0x7b, 0x9e, 0x37, 0x74, - 0xbc, 0x9a, 0x69, 0x97, 0xf1, 0x6c, 0xa7, 0x69, 0x8e, 0xfa, 0x0a, 0x46, 0xa9, 0x33, 0x0d, 0x88, 0x2d, 0xb6, 0x25, - 0xff, 0x16, 0x7b, 0xcc, 0xcb, 0xf5, 0x33, 0x18, 0x9b, 0x96, 0x31, 0xc3, 0x30, 0xf8, 0x0e, 0xc0, 0x48, 0x39, 0xf5, - 0x97, 0x00, 0x67, 0xe5, 0xf9, 0x8a, 0x28, 0xe3, 0x39, 0xfb, 0x8e, 0xa6, 0x29, 0x99, 0x89, 0xfa, 0xf5, 0x71, 0x82, - 0x31, 0x9c, 0x64, 0xa3, 0x10, 0x80, 0x20, 0x13, 0x0b, 0x6a, 0x36, 0x4f, 0x49, 0x7c, 0xaf, 0x81, 0x55, 0x1d, 0x6c, - 0xa8, 0xc2, 0xfe, 0x27, 0x70, 0x60, 0x09, 0xcb, 0x38, 0x08, 0x0e, 0xff, 0x1d, 0x0d, 0xab, 0x85, 0x19, 0x99, 0x55, - 0x8b, 0xd8, 0x3e, 0xc8, 0xd5, 0xb1, 0x49, 0x93, 0x98, 0x52, 0xe1, 0xaf, 0xb1, 0xcb, 0x08, 0xe3, 0xd9, 0x6f, 0x6a, - 0x94, 0xb1, 0xc5, 0x30, 0xe7, 0x36, 0xb5, 0x82, 0x6c, 0xe4, 0x20, 0x8c, 0x35, 0x07, 0x40, 0xd8, 0x8f, 0xb2, 0xb9, - 0x8d, 0x7e, 0xa5, 0x46, 0x27, 0x32, 0x2d, 0x07, 0xd7, 0x76, 0x53, 0xf5, 0xa6, 0xef, 0x27, 0xb3, 0x31, 0x31, 0xbc, - 0xce, 0xb1, 0x25, 0xfe, 0x1c, 0xb7, 0x67, 0xe6, 0xd8, 0x83, 0x36, 0x09, 0xee, 0x36, 0xd3, 0x38, 0xca, 0xec, 0x29, - 0x59, 0x04, 0xe1, 0x43, 0x7f, 0x11, 0x47, 0x71, 0xba, 0x24, 0x3e, 0x1d, 0x14, 0x7c, 0xf1, 0x00, 0xe3, 0xb4, 0x70, - 0x57, 0x61, 0xcf, 0xe9, 0x24, 0x74, 0xc1, 0x5a, 0xcb, 0x30, 0x2c, 0xd3, 0x90, 0xae, 0x73, 0xfe, 0xf9, 0x52, 0x65, - 0x56, 0x15, 0xb7, 0x1c, 0x6b, 0x01, 0x84, 0x25, 0x8f, 0xf1, 0x02, 0x91, 0xcd, 0x06, 0x4b, 0x32, 0xc1, 0xb0, 0xa4, - 0x4e, 0xa7, 0x97, 0xd0, 0x85, 0xe6, 0xf4, 0x5a, 0x3b, 0x4f, 0xe2, 0xfb, 0x33, 0x18, 0x2d, 0x36, 0xb6, 0x53, 0x1a, - 0x4e, 0xf1, 0x8d, 0x8d, 0x6e, 0x65, 0xa2, 0x1f, 0x1b, 0xf9, 0x69, 0xe8, 0x8d, 0x2e, 0x06, 0xf0, 0xba, 0xdf, 0xd1, - 0xdc, 0xc1, 0x22, 0x88, 0x6c, 0x36, 0x9d, 0x63, 0x77, 0xa9, 0xf4, 0xa5, 0xc2, 0xcf, 0xdc, 0x60, 0x75, 0x4f, 0x73, - 0x07, 0xc0, 0x73, 0x4d, 0xc3, 0xf8, 0xbe, 0x3f, 0x0f, 0x26, 0x13, 0x1a, 0x0d, 0x70, 0xcc, 0xb2, 0x90, 0x86, 0x61, - 0xb0, 0x4c, 0x83, 0x74, 0xb0, 0x20, 0x6b, 0xde, 0xeb, 0x61, 0x5b, 0xaf, 0x5d, 0xde, 0x6b, 0x77, 0xef, 0x5e, 0x95, - 0x6e, 0xc0, 0x85, 0x8d, 0xf5, 0xc3, 0x87, 0xd6, 0xd3, 0xdc, 0xca, 0x3c, 0xf7, 0xee, 0x75, 0x99, 0xd0, 0xcd, 0x82, - 0x24, 0xb3, 0x20, 0xea, 0xbb, 0xb9, 0x73, 0xb7, 0x61, 0x1b, 0xe3, 0xe9, 0xc9, 0xc9, 0x49, 0xee, 0x4c, 0xc4, 0x93, - 0x3b, 0x99, 0xe4, 0x8e, 0x2f, 0x9e, 0xa6, 0x53, 0xd7, 0x9d, 0x4e, 0x73, 0x27, 0x10, 0x05, 0xdd, 0x8e, 0x3f, 0xe9, - 0x76, 0x72, 0xe7, 0x5e, 0xa9, 0x91, 0x3b, 0x94, 0x3f, 0x25, 0x74, 0x32, 0xc0, 0x8d, 0xc4, 0xec, 0xbc, 0xfb, 0xc7, - 0xae, 0x9b, 0x23, 0x06, 0xb8, 0x2e, 0xe1, 0x26, 0x14, 0xd9, 0xdc, 0x6c, 0xf6, 0xae, 0xa9, 0x15, 0x9f, 0xf3, 0xfd, - 0xc6, 0x7a, 0x13, 0x92, 0xdc, 0xde, 0x68, 0xca, 0x2c, 0x08, 0x61, 0xd5, 0x36, 0x02, 0x0c, 0xf6, 0xba, 0x0f, 0xf1, - 0xfa, 0x06, 0xe3, 0x38, 0x81, 0x33, 0x9b, 0x90, 0x49, 0xb0, 0x4a, 0xfb, 0x5e, 0x67, 0xb9, 0x16, 0x45, 0x7c, 0xaf, - 0x17, 0x05, 0x78, 0xf6, 0xfa, 0x69, 0x1c, 0x06, 0x13, 0x51, 0xd4, 0x76, 0x96, 0xbc, 0x8e, 0x39, 0xc0, 0x68, 0x15, - 0x01, 0xc6, 0x5c, 0x21, 0x61, 0xa8, 0x39, 0xdd, 0x54, 0xa3, 0x24, 0x45, 0x49, 0xad, 0xe6, 0xa6, 0x0c, 0x2e, 0x18, - 0x99, 0xc2, 0x3b, 0x5c, 0xae, 0xe5, 0x9e, 0xf7, 0x8e, 0x96, 0xeb, 0xfc, 0x0f, 0x0b, 0x3a, 0x09, 0x88, 0x66, 0x14, - 0xbb, 0xc9, 0x73, 0x41, 0x9a, 0x6b, 0x6e, 0x5a, 0xb6, 0xa9, 0x38, 0x16, 0x10, 0xd7, 0xf4, 0x49, 0xb0, 0x58, 0xc6, - 0x49, 0x46, 0xa2, 0x2c, 0xcf, 0x47, 0x37, 0x79, 0x3e, 0xb8, 0x0a, 0x8c, 0xeb, 0xbf, 0x1a, 0xec, 0x9e, 0x66, 0xda, - 0x8f, 0xdc, 0xbc, 0xb1, 0xde, 0x52, 0xd5, 0x52, 0x0a, 0xae, 0x31, 0xb4, 0x92, 0x52, 0x2b, 0xb3, 0x5b, 0xb2, 0x5e, - 0x99, 0x01, 0x59, 0x56, 0x67, 0x96, 0x57, 0xe5, 0x2a, 0x78, 0x03, 0x41, 0x85, 0xb7, 0x74, 0x78, 0xa5, 0x58, 0x5d, - 0x01, 0xb1, 0x82, 0x95, 0x99, 0x53, 0xd1, 0xb3, 0x36, 0x9a, 0xf1, 0xcb, 0xdd, 0x34, 0xe3, 0x8f, 0xd9, 0x3e, 0x34, - 0xe3, 0x97, 0x9f, 0x9d, 0x66, 0x7c, 0x56, 0x77, 0x2a, 0xba, 0x88, 0x87, 0xba, 0x94, 0xd5, 0xc3, 0xd5, 0x94, 0xb0, - 0x70, 0x5d, 0x17, 0xbf, 0xd8, 0x07, 0x48, 0xf4, 0xc6, 0x12, 0x50, 0xb2, 0x9b, 0x1b, 0x68, 0xf1, 0x77, 0xd1, 0xf0, - 0x2f, 0x89, 0xfa, 0x3c, 0x9d, 0x0e, 0xdf, 0xc4, 0x4a, 0x81, 0x7c, 0xe2, 0xf6, 0x0f, 0xa5, 0xd0, 0x2a, 0xec, 0x8d, - 0xb0, 0x6e, 0xc6, 0xe4, 0x33, 0x10, 0x99, 0x81, 0x59, 0xf3, 0x4f, 0xa4, 0xfd, 0xe6, 0xa0, 0x3c, 0x04, 0x43, 0x9a, - 0x52, 0x0b, 0xff, 0xbb, 0x9a, 0x44, 0x70, 0x46, 0x33, 0xee, 0x30, 0xff, 0xd5, 0xc3, 0xc5, 0xc4, 0xb8, 0x88, 0xcd, - 0x3c, 0x48, 0xdf, 0x55, 0xbd, 0xdf, 0xb8, 0x16, 0x65, 0xa8, 0x4e, 0x27, 0xe7, 0x76, 0x93, 0x6a, 0x76, 0x79, 0x78, - 0xcd, 0x9a, 0x9f, 0x97, 0x66, 0xda, 0x57, 0x1b, 0x72, 0x0e, 0xb4, 0x76, 0x19, 0x73, 0xd7, 0xa3, 0x0d, 0xa7, 0x00, - 0x31, 0x71, 0x1f, 0x06, 0x0d, 0x98, 0xb0, 0xe6, 0xc1, 0x24, 0xcf, 0xcd, 0x81, 0x00, 0x84, 0x72, 0xd1, 0xd2, 0x5d, - 0x44, 0x5c, 0x7a, 0x2f, 0xad, 0x03, 0xb8, 0xae, 0x8d, 0x29, 0xd2, 0x2e, 0x40, 0x35, 0xcd, 0xd5, 0x6e, 0x1c, 0x66, - 0xba, 0xc6, 0xc0, 0xc7, 0x4c, 0x16, 0x94, 0x09, 0x81, 0x2e, 0x55, 0xc2, 0x5f, 0xbc, 0x12, 0x05, 0x75, 0xdb, 0x68, - 0x06, 0x1c, 0xd4, 0xad, 0x43, 0x88, 0x0f, 0x21, 0x9e, 0x66, 0x68, 0x87, 0xd7, 0xc1, 0x87, 0x5c, 0x97, 0xb4, 0x1f, - 0x6e, 0x3f, 0x60, 0xcf, 0x96, 0x24, 0xaa, 0xf0, 0x92, 0xbb, 0x6c, 0x7c, 0x81, 0x94, 0x48, 0xef, 0x2d, 0x27, 0xbd, - 0xd7, 0x5e, 0x6c, 0x44, 0x78, 0x9c, 0x8c, 0x2c, 0x6d, 0xe0, 0x1c, 0x11, 0xf7, 0x72, 0x8c, 0xa7, 0x44, 0xe2, 0x19, - 0xac, 0x52, 0xc0, 0x8d, 0xc8, 0x70, 0x22, 0xfe, 0x19, 0xf8, 0xab, 0x24, 0x8d, 0x93, 0xfe, 0x32, 0x0e, 0xa2, 0x8c, - 0x26, 0x39, 0x82, 0xea, 0x1a, 0xe1, 0x23, 0xc0, 0x73, 0xb3, 0x89, 0x97, 0xc4, 0x0f, 0xb2, 0x87, 0xbe, 0xcb, 0x49, - 0x0a, 0x77, 0xc0, 0xa9, 0x03, 0xb7, 0xb1, 0x7e, 0x9f, 0x43, 0xf3, 0x25, 0x12, 0x7e, 0x49, 0x9d, 0x9c, 0x51, 0xb7, - 0xf9, 0x40, 0x79, 0xcb, 0x02, 0x04, 0x01, 0xf9, 0x41, 0x12, 0x7b, 0x06, 0x58, 0x1e, 0x96, 0xda, 0x9d, 0xd0, 0x99, - 0x85, 0x58, 0x1b, 0xc4, 0xeb, 0xe2, 0xcf, 0xe9, 0x99, 0x9a, 0xdb, 0x5c, 0x0c, 0x14, 0x8f, 0xb9, 0xcf, 0xc8, 0xfa, - 0x04, 0xd2, 0xe9, 0x59, 0xfb, 0xd4, 0x1c, 0xd3, 0x69, 0x9c, 0x50, 0x16, 0x4c, 0xda, 0x3b, 0x59, 0xae, 0xf7, 0xef, - 0x7e, 0xfb, 0xf4, 0x9b, 0xfb, 0x89, 0xe2, 0xcc, 0x10, 0x9d, 0x99, 0x3b, 0x7a, 0xab, 0xdf, 0x67, 0x40, 0x1a, 0x32, - 0xc8, 0xfb, 0x2c, 0x6e, 0x5f, 0x5f, 0xd7, 0x07, 0x8d, 0x31, 0xfb, 0x96, 0x31, 0xbf, 0xf3, 0x12, 0x1a, 0x92, 0x2c, - 0xb8, 0x13, 0x34, 0x63, 0xf7, 0x68, 0xb9, 0x16, 0x6b, 0x8c, 0x17, 0xde, 0x23, 0x16, 0xa9, 0x32, 0x14, 0xb1, 0x48, - 0xd5, 0x62, 0x5c, 0xa4, 0x41, 0x6d, 0x36, 0x22, 0x8c, 0x4d, 0xe5, 0xa6, 0xef, 0x2d, 0xd7, 0xea, 0x15, 0x5d, 0x34, - 0x93, 0x37, 0x75, 0x35, 0xfe, 0xe0, 0x22, 0x98, 0x4c, 0x42, 0x9a, 0x97, 0x16, 0xba, 0xbc, 0x96, 0x0a, 0x70, 0x24, - 0x1c, 0xc8, 0x38, 0x8d, 0xc3, 0x55, 0x46, 0x9b, 0xc1, 0xc5, 0x80, 0xd3, 0x71, 0x0b, 0xe0, 0xe0, 0xef, 0xf2, 0x58, - 0x7b, 0x40, 0x6e, 0xc3, 0x36, 0x71, 0x07, 0x10, 0x6e, 0xdc, 0xee, 0x96, 0x87, 0x0e, 0xaf, 0xe4, 0xa0, 0xad, 0x86, - 0x89, 0x58, 0x70, 0x2d, 0x31, 0xec, 0xad, 0x39, 0x1e, 0x2f, 0x93, 0x21, 0x97, 0x65, 0x51, 0x5e, 0x9e, 0xcc, 0x6f, - 0x73, 0xc6, 0x5e, 0x35, 0x9f, 0xb1, 0x57, 0xe2, 0x8c, 0x6d, 0xdf, 0x99, 0x4f, 0xa7, 0x1e, 0xfc, 0x37, 0x28, 0x26, - 0xd4, 0x77, 0xb5, 0xee, 0x72, 0xad, 0x79, 0xcb, 0xb5, 0x66, 0x77, 0x96, 0x6b, 0x0d, 0xbb, 0x46, 0xcb, 0x0a, 0xcb, - 0xe9, 0x98, 0x96, 0xab, 0x41, 0x21, 0xfc, 0xb9, 0xa5, 0x57, 0xde, 0x21, 0xbc, 0x83, 0x56, 0xbd, 0xfa, 0xbb, 0xce, - 0xf6, 0xa3, 0xce, 0xce, 0x92, 0x40, 0xda, 0xa6, 0x93, 0x91, 0xf1, 0x98, 0x4e, 0xfa, 0xd3, 0xd8, 0x5f, 0xa5, 0x7f, - 0xe7, 0xe3, 0xe7, 0x40, 0xdc, 0x8a, 0x08, 0x2a, 0xfd, 0x88, 0xa6, 0xa0, 0xef, 0xb8, 0xa3, 0xa2, 0x87, 0x8d, 0x5c, - 0xa7, 0x3e, 0x8b, 0x8d, 0xde, 0x71, 0x0e, 0x1b, 0x36, 0x79, 0x33, 0xa0, 0x7f, 0xb3, 0x55, 0x6a, 0x47, 0x31, 0xbf, - 0x02, 0x2c, 0x5b, 0xc1, 0xf1, 0x78, 0x68, 0xf0, 0xd5, 0x74, 0x4f, 0x9a, 0x87, 0x7b, 0x2d, 0xbe, 0x74, 0x23, 0x2e, - 0x15, 0x7e, 0x6f, 0x71, 0x87, 0xaf, 0xed, 0xbd, 0xb6, 0xed, 0x91, 0x5a, 0xaf, 0x5b, 0x2e, 0x84, 0xa2, 0xee, 0x9e, - 0x58, 0xfe, 0xe9, 0xab, 0x43, 0xf8, 0x8f, 0x51, 0xf5, 0x3f, 0x66, 0x4d, 0x84, 0xfa, 0x45, 0xd9, 0xff, 0x81, 0x91, - 0x4a, 0x48, 0x88, 0xef, 0x5f, 0x7f, 0x3a, 0x7d, 0x5c, 0x83, 0xbd, 0x6b, 0x33, 0xa3, 0xa4, 0x6a, 0xed, 0xaf, 0xe2, - 0x18, 0xf2, 0xf6, 0xd6, 0xab, 0x0b, 0xf0, 0x30, 0x17, 0x8f, 0x6c, 0x08, 0x8d, 0x04, 0x1f, 0xc1, 0x94, 0xf1, 0x3a, - 0xb6, 0x61, 0xac, 0xc4, 0xdb, 0x36, 0x56, 0xe2, 0xcd, 0x6e, 0x56, 0xe2, 0xdb, 0xbd, 0x58, 0x89, 0x37, 0x9f, 0x9d, - 0x95, 0x78, 0x5b, 0x67, 0x25, 0xae, 0x62, 0x61, 0x89, 0x6a, 0x5d, 0xac, 0xf8, 0xcf, 0x0f, 0x4c, 0xb7, 0x76, 0x19, - 0x0f, 0x7b, 0x2e, 0x8b, 0x77, 0x7e, 0xf5, 0x8b, 0x19, 0x0b, 0xdc, 0x88, 0xef, 0xd1, 0x30, 0xab, 0x60, 0x2d, 0x38, - 0x66, 0xc7, 0xef, 0x28, 0xc5, 0x61, 0x1c, 0xcd, 0xbe, 0x07, 0xdd, 0x2a, 0x88, 0x03, 0x13, 0xe5, 0x45, 0x90, 0x7e, - 0x1f, 0x2f, 0x57, 0xcb, 0x0b, 0xe8, 0xeb, 0x43, 0x90, 0x06, 0xe3, 0x90, 0xca, 0x30, 0x04, 0xcc, 0x90, 0x8c, 0xcb, - 0xc4, 0xc1, 0x76, 0x53, 0xfc, 0x24, 0x6b, 0xf1, 0x13, 0xad, 0x3b, 0xf9, 0x6f, 0x66, 0xa1, 0xa6, 0x37, 0x33, 0x22, - 0x10, 0xb0, 0xab, 0x32, 0xe8, 0xc7, 0x33, 0x23, 0x57, 0xb1, 0xd9, 0x30, 0x4b, 0x61, 0xb6, 0xd0, 0xda, 0x0f, 0xad, - 0x31, 0x35, 0x2b, 0xd3, 0x92, 0xf1, 0xf7, 0xea, 0x62, 0xf8, 0x45, 0xbc, 0x4a, 0xe9, 0x24, 0xbe, 0x8f, 0x74, 0x2b, - 0x95, 0xae, 0x35, 0xa0, 0xa8, 0x94, 0x6d, 0x30, 0x73, 0xac, 0xd4, 0xcc, 0xe8, 0x90, 0xb8, 0x78, 0xb5, 0xb4, 0x99, - 0xc6, 0xd8, 0xc6, 0x29, 0xea, 0x32, 0xc5, 0xd9, 0x13, 0xc3, 0x88, 0x87, 0x8f, 0x6b, 0x29, 0x2c, 0x2e, 0x62, 0x87, - 0x4b, 0x85, 0x53, 0x23, 0x15, 0xc2, 0x45, 0x11, 0x04, 0xa7, 0x61, 0xe1, 0xf8, 0x1b, 0xe6, 0x12, 0x5e, 0xbc, 0x85, - 0x10, 0x42, 0xf9, 0x8a, 0xaf, 0x07, 0x0f, 0x09, 0xc3, 0x1e, 0x5f, 0x2b, 0x60, 0x7c, 0x77, 0x47, 0x93, 0x90, 0x3c, - 0x18, 0x66, 0x1e, 0x47, 0xdf, 0x01, 0x00, 0xde, 0xc4, 0xf7, 0x91, 0x5a, 0x01, 0x33, 0x35, 0x35, 0xec, 0xa5, 0xc6, - 0xe0, 0x45, 0xe0, 0xae, 0xa5, 0x8c, 0x00, 0x72, 0x64, 0xcf, 0xe8, 0x5f, 0x2c, 0xf6, 0xef, 0x5f, 0xcd, 0xdc, 0xba, - 0x8c, 0xe5, 0x87, 0xfe, 0xbc, 0xdc, 0xe3, 0x33, 0xcf, 0x9f, 0x3f, 0x69, 0x9f, 0xb6, 0x01, 0xe9, 0xc2, 0x45, 0xe6, - 0x6b, 0xa3, 0xa1, 0xb5, 0xd9, 0x7a, 0x0a, 0x60, 0x14, 0x57, 0xf1, 0xca, 0x9f, 0xa3, 0xc9, 0xe8, 0xe7, 0x9b, 0x6f, - 0x06, 0x7d, 0x62, 0x8a, 0x62, 0x39, 0xf5, 0x4a, 0x51, 0x01, 0x05, 0xfc, 0xfe, 0x5b, 0x88, 0xbe, 0xfb, 0x6f, 0x04, - 0x43, 0x7d, 0xd7, 0x70, 0x2e, 0x3e, 0x78, 0xdc, 0xe6, 0x1d, 0x40, 0x26, 0x5d, 0x1e, 0xd7, 0x46, 0x28, 0xd7, 0x9a, - 0x91, 0x4c, 0x5e, 0x05, 0x9a, 0x1a, 0x43, 0xb2, 0x2d, 0x3c, 0xa6, 0xf8, 0x0a, 0x75, 0x18, 0x9b, 0xce, 0x4d, 0xf6, - 0x2d, 0xca, 0xb1, 0x55, 0x05, 0xc9, 0x70, 0xcb, 0x05, 0x8a, 0xe8, 0xab, 0xfa, 0x6e, 0x11, 0x44, 0x16, 0xa6, 0x80, - 0xa8, 0xbf, 0x21, 0x6b, 0x08, 0x82, 0x0e, 0xc8, 0xad, 0xfa, 0x0a, 0x0a, 0x2d, 0xaa, 0x78, 0x8b, 0x42, 0x9e, 0x37, - 0xbd, 0x11, 0x12, 0x42, 0x8b, 0x37, 0xfa, 0x9d, 0xa6, 0x69, 0x9a, 0x64, 0x23, 0x34, 0xc9, 0x47, 0x60, 0x39, 0xb2, - 0x03, 0xa0, 0x2d, 0xc9, 0x97, 0x6b, 0x56, 0x02, 0x9c, 0x01, 0x98, 0x78, 0xc8, 0x02, 0x1e, 0xe7, 0xb3, 0xe7, 0x8a, - 0x02, 0xc1, 0xd0, 0x43, 0x8c, 0x46, 0x92, 0x40, 0x38, 0xf0, 0xbe, 0x86, 0x0c, 0x3b, 0xbe, 0xe5, 0x92, 0x60, 0xcd, - 0x65, 0x8f, 0xa3, 0x01, 0x6d, 0x0e, 0x08, 0x99, 0x2a, 0x58, 0x10, 0xb4, 0x0e, 0x95, 0xf8, 0xee, 0x16, 0x6d, 0xc0, - 0x8d, 0xc8, 0x17, 0xad, 0xb3, 0x05, 0x8d, 0x56, 0x3a, 0x26, 0x84, 0xc3, 0xe0, 0xe2, 0x50, 0xe7, 0x0d, 0x23, 0xb6, - 0x00, 0xdb, 0x34, 0xb7, 0x9c, 0xb3, 0xbb, 0x30, 0xe2, 0x28, 0x95, 0x58, 0x3e, 0x57, 0x6c, 0x46, 0x1c, 0xb7, 0x55, - 0x6f, 0x08, 0xbe, 0xa4, 0x71, 0xd5, 0x7d, 0x91, 0xd9, 0x14, 0x43, 0x1f, 0x2c, 0x34, 0x0e, 0x17, 0x17, 0x09, 0xb0, - 0x1b, 0xa4, 0xba, 0x68, 0x52, 0x23, 0x43, 0x2a, 0x82, 0xa2, 0xc4, 0xac, 0x77, 0xc3, 0xc7, 0x09, 0x51, 0xc9, 0x5a, - 0xfb, 0xf1, 0x6b, 0xfd, 0xb4, 0x4c, 0xfa, 0x96, 0x3e, 0xb0, 0x8b, 0x84, 0x81, 0xea, 0x96, 0x3e, 0x80, 0x09, 0xdf, - 0x5b, 0x90, 0xa6, 0xe8, 0x5b, 0xd0, 0xb5, 0x05, 0x79, 0x3e, 0x7c, 0x88, 0x54, 0xb7, 0xe5, 0x00, 0xb9, 0xf9, 0x16, - 0x2c, 0x8e, 0x20, 0x86, 0x94, 0xee, 0xe2, 0x10, 0x73, 0x63, 0x79, 0xa3, 0x11, 0xc6, 0x76, 0xc3, 0xd1, 0x30, 0x5f, - 0x78, 0xae, 0x7b, 0x50, 0xab, 0x0f, 0x82, 0xec, 0xa6, 0xda, 0xa6, 0x95, 0x0d, 0x3d, 0xd7, 0x0e, 0x5e, 0x38, 0x9d, - 0x41, 0xed, 0x8e, 0x56, 0x02, 0xc9, 0x8e, 0x50, 0xfc, 0x75, 0xf6, 0x6c, 0x63, 0xa4, 0x2d, 0xe0, 0x2d, 0x8c, 0xcf, - 0x71, 0x6c, 0x39, 0x97, 0x7f, 0x8d, 0xea, 0x57, 0x3f, 0x0b, 0x63, 0xcb, 0x92, 0x1a, 0x8d, 0x20, 0x14, 0xba, 0x01, - 0xc7, 0xe8, 0xf7, 0xda, 0x4b, 0xcd, 0x60, 0xc7, 0xc7, 0x34, 0x47, 0x03, 0x81, 0x51, 0x84, 0x5b, 0x97, 0xda, 0x41, - 0xe5, 0x8b, 0x51, 0x15, 0xc3, 0xf1, 0xa0, 0xcb, 0xb4, 0xd0, 0xe8, 0x6d, 0xa5, 0x16, 0xb0, 0xff, 0x96, 0xeb, 0xd3, - 0x19, 0x43, 0xbc, 0x0f, 0xa8, 0x01, 0x89, 0x13, 0x76, 0x76, 0xb8, 0x5a, 0x96, 0xbb, 0x2b, 0x5f, 0x92, 0xfb, 0x77, - 0x86, 0x97, 0x0e, 0xea, 0xd0, 0x64, 0x7f, 0xcd, 0xd7, 0xdd, 0x23, 0xbb, 0xa4, 0xd1, 0xa4, 0xdc, 0x61, 0xe5, 0xfe, - 0xda, 0xbf, 0xbb, 0x12, 0x46, 0x81, 0x8c, 0x22, 0x71, 0x03, 0x46, 0xc9, 0xe3, 0x08, 0x37, 0x3f, 0x3b, 0x6e, 0xc1, - 0x5e, 0x54, 0x0c, 0x36, 0x60, 0xe1, 0x00, 0x65, 0x33, 0x45, 0x28, 0x0e, 0x61, 0xeb, 0xd1, 0x19, 0xde, 0x10, 0x84, - 0x68, 0xeb, 0x4e, 0xcc, 0x84, 0x69, 0x60, 0xd1, 0x26, 0xe0, 0x81, 0x68, 0xf7, 0x95, 0x5a, 0x07, 0xbb, 0xa5, 0xd6, - 0xd9, 0x2e, 0xa9, 0x35, 0x73, 0x4c, 0xba, 0x4f, 0xc8, 0x52, 0xf1, 0x6d, 0x13, 0xc4, 0xb9, 0xea, 0xe2, 0x56, 0x12, - 0x75, 0xa3, 0x1f, 0x93, 0x68, 0x55, 0xeb, 0x8d, 0x19, 0xfb, 0xa1, 0xf8, 0x5b, 0x61, 0x50, 0x84, 0x42, 0x5d, 0x95, - 0x8d, 0x5f, 0x15, 0xb2, 0x71, 0xc6, 0xd5, 0x14, 0x2e, 0x29, 0x82, 0xfa, 0x57, 0xdc, 0xbd, 0x24, 0x77, 0x50, 0xb8, - 0x7d, 0x15, 0x23, 0x55, 0x1c, 0x99, 0x0a, 0x46, 0x43, 0x71, 0x8f, 0x13, 0x5c, 0x46, 0xd9, 0x4b, 0xae, 0x5c, 0xb5, - 0xf0, 0x63, 0x2a, 0xca, 0x41, 0xea, 0x8e, 0x43, 0x96, 0xc5, 0xea, 0xb6, 0x29, 0x3b, 0xb2, 0xa8, 0xaf, 0x95, 0x4d, - 0x22, 0x3d, 0x4e, 0x18, 0x80, 0x85, 0x98, 0xbe, 0xa2, 0xd7, 0x96, 0x36, 0x10, 0x38, 0xc8, 0x06, 0x07, 0xb9, 0xdd, - 0xd2, 0x79, 0x96, 0x2c, 0xa5, 0xd0, 0xc2, 0xab, 0x32, 0x08, 0x84, 0xef, 0xcd, 0xa6, 0xe1, 0x96, 0xc7, 0x4b, 0x9e, - 0xdf, 0xef, 0x20, 0x5e, 0xd4, 0x5c, 0x55, 0x91, 0x8f, 0x27, 0xd3, 0x66, 0x56, 0xb6, 0x58, 0xb5, 0xde, 0x29, 0x13, - 0xe2, 0x6c, 0xb8, 0x8f, 0x49, 0x59, 0x46, 0xcf, 0x6b, 0xf4, 0xc5, 0x77, 0xf9, 0xd6, 0x49, 0x56, 0x11, 0x26, 0xb6, - 0xb0, 0xb3, 0x84, 0xf8, 0xb7, 0xca, 0x90, 0x85, 0x9c, 0x13, 0x64, 0xc0, 0x65, 0x4d, 0xc1, 0x80, 0x60, 0x1c, 0x58, - 0xda, 0x77, 0x3a, 0xa9, 0x22, 0x7d, 0xe9, 0x3f, 0x75, 0xbb, 0xe4, 0xd5, 0xf4, 0xb0, 0x22, 0x14, 0xed, 0xf4, 0xca, - 0x22, 0xf3, 0x96, 0x71, 0x64, 0xf3, 0xd5, 0x62, 0xbc, 0x51, 0x65, 0xab, 0x8a, 0xc8, 0xb5, 0x2e, 0x66, 0x55, 0x3f, - 0x3b, 0x9d, 0x4e, 0xcb, 0x82, 0x46, 0x57, 0x3b, 0x44, 0x61, 0xe1, 0x53, 0xd7, 0x75, 0xab, 0x63, 0xdf, 0x0e, 0x76, - 0x1b, 0xe5, 0xb6, 0x27, 0x8d, 0x23, 0x46, 0xd8, 0xee, 0x82, 0x5f, 0x1d, 0x1c, 0xb9, 0x53, 0x9c, 0xec, 0x92, 0x59, - 0xc4, 0x80, 0x19, 0x43, 0x04, 0x19, 0x5d, 0xa4, 0x7d, 0x9f, 0xa2, 0x0e, 0xc6, 0x51, 0x0e, 0x34, 0x1a, 0x0e, 0xd8, - 0x33, 0x30, 0x15, 0xf1, 0xc4, 0xae, 0x70, 0x35, 0x94, 0x87, 0xd7, 0x84, 0xf7, 0xe2, 0x23, 0x78, 0x50, 0x36, 0x75, - 0x99, 0x36, 0x4e, 0xab, 0xe7, 0xfe, 0xbe, 0x54, 0x4f, 0x83, 0x0b, 0x70, 0x23, 0x14, 0xda, 0x4c, 0x3e, 0x8b, 0xff, - 0x2f, 0xe5, 0xff, 0xaf, 0x96, 0xeb, 0xb2, 0xfd, 0xc8, 0x09, 0x48, 0xb4, 0x8b, 0xd3, 0xc2, 0x46, 0xdd, 0xb4, 0x07, - 0xa4, 0x95, 0xc1, 0x54, 0x55, 0xa0, 0x83, 0x92, 0xbe, 0x94, 0xfd, 0xa7, 0x41, 0xfc, 0x8e, 0x14, 0x33, 0x2c, 0x71, - 0x21, 0x42, 0x2c, 0x72, 0x57, 0xc2, 0x1c, 0xac, 0x97, 0x27, 0xa8, 0x3f, 0x28, 0xed, 0x09, 0xd0, 0xc6, 0xd7, 0xe6, - 0xb6, 0x97, 0xb8, 0xbf, 0xaa, 0xd7, 0x12, 0x1d, 0x03, 0xc8, 0x3c, 0x38, 0x84, 0x68, 0x48, 0xa0, 0x55, 0x36, 0x37, - 0x1b, 0xa5, 0x7c, 0xab, 0xea, 0xd9, 0xc4, 0xc0, 0xb0, 0xbb, 0xe6, 0x2a, 0xac, 0x6f, 0xa1, 0x2d, 0x80, 0xc9, 0xf2, - 0xed, 0x87, 0xcf, 0x36, 0x2c, 0xb1, 0xba, 0x1f, 0x3d, 0x5c, 0x72, 0xdc, 0xbf, 0x36, 0xde, 0x9d, 0x29, 0x3b, 0xff, - 0x28, 0x5f, 0xfc, 0xb6, 0x51, 0xa0, 0x77, 0x55, 0x92, 0xd0, 0x71, 0xa3, 0xef, 0x8e, 0xb9, 0x57, 0xed, 0x45, 0x10, - 0xed, 0x5f, 0x97, 0xac, 0xf7, 0xae, 0x0b, 0x17, 0xc6, 0xde, 0x95, 0xe1, 0xc6, 0x61, 0x96, 0x0b, 0xd9, 0xf0, 0x5b, - 0x45, 0xa0, 0xa8, 0xfa, 0xef, 0xea, 0xd8, 0x8a, 0x51, 0xf9, 0x57, 0x2b, 0x20, 0x3e, 0xf7, 0xca, 0xee, 0xa2, 0x89, - 0x04, 0x8d, 0xfa, 0xb1, 0x76, 0xa2, 0x1d, 0x77, 0xb5, 0x23, 0x57, 0x67, 0x5c, 0xd8, 0x50, 0xef, 0x75, 0x0a, 0xbf, - 0xbc, 0x43, 0x57, 0x3f, 0x3b, 0x9d, 0x89, 0x4b, 0x62, 0x1a, 0x84, 0x21, 0x43, 0x15, 0x60, 0xfe, 0x7b, 0x4b, 0xcb, - 0x6a, 0x16, 0x56, 0xc6, 0x8d, 0x40, 0x3a, 0xe2, 0x11, 0xce, 0x8e, 0x4f, 0x96, 0x7d, 0x3c, 0x1b, 0x6a, 0x21, 0x18, - 0x70, 0xb2, 0x52, 0xfc, 0x04, 0xdc, 0xc1, 0x63, 0xfd, 0xec, 0x14, 0xe2, 0x97, 0x6a, 0x93, 0xa1, 0xfe, 0x5d, 0xe7, - 0x58, 0xf3, 0x7a, 0x77, 0x76, 0xd7, 0x77, 0x6d, 0xcf, 0x39, 0xd4, 0x5c, 0xe7, 0xc8, 0xee, 0x38, 0xc7, 0x5a, 0xc7, - 0xe9, 0xc1, 0xbf, 0xbe, 0xe7, 0xbc, 0xd2, 0x5c, 0x78, 0xd2, 0x3c, 0xa7, 0x8b, 0xff, 0x76, 0x9c, 0xe3, 0xbb, 0x2e, - 0xbb, 0xe9, 0x89, 0xf4, 0x8e, 0xaa, 0x8c, 0x02, 0x7c, 0x39, 0xf4, 0x83, 0xb3, 0xd3, 0x55, 0x4a, 0xb5, 0xf5, 0x50, - 0x7f, 0xa5, 0x6b, 0xf3, 0x84, 0x4e, 0x87, 0xfa, 0x53, 0xa2, 0x94, 0x7a, 0x27, 0x8d, 0xc5, 0x9d, 0xe3, 0xc6, 0xe2, - 0xee, 0x51, 0x63, 0xf1, 0x61, 0xaf, 0x5c, 0x7c, 0x30, 0x63, 0xaf, 0x94, 0xf4, 0xa1, 0x0b, 0x92, 0x25, 0xc1, 0xda, - 0xf0, 0x34, 0x40, 0xd7, 0x36, 0xfc, 0x73, 0xdc, 0x31, 0x65, 0xab, 0x31, 0xb4, 0x92, 0xd0, 0x38, 0x3e, 0xd1, 0xbc, - 0xa3, 0x6f, 0x3a, 0x47, 0x3e, 0xd4, 0x83, 0x64, 0xb7, 0xf0, 0x77, 0xd7, 0x3d, 0xf1, 0x5d, 0x0d, 0x1a, 0x7a, 0xf0, - 0xdf, 0xbc, 0xd7, 0xf1, 0xd9, 0x83, 0x0b, 0xef, 0x3f, 0x78, 0xc7, 0xa9, 0x6b, 0x7b, 0xf0, 0xdf, 0xcf, 0x52, 0xe5, - 0x0e, 0x0a, 0x7f, 0xb5, 0xdf, 0x43, 0x57, 0xeb, 0x9e, 0xcc, 0x3b, 0xce, 0xab, 0xbb, 0x63, 0xe7, 0x64, 0xee, 0x1d, - 0x7f, 0x60, 0x4f, 0xa1, 0xdd, 0x71, 0x5e, 0xc1, 0xdf, 0x87, 0xae, 0x3b, 0xb7, 0x3d, 0xe7, 0xe4, 0xae, 0xeb, 0x74, - 0x43, 0xfb, 0xc8, 0x39, 0x81, 0xbf, 0x9f, 0x01, 0xbc, 0x00, 0x57, 0x9e, 0x9d, 0x58, 0x83, 0x8d, 0x51, 0xb1, 0xdf, - 0x50, 0x3f, 0xd2, 0x39, 0xd4, 0x7a, 0x87, 0xdf, 0x9c, 0xdc, 0xd9, 0x87, 0x73, 0xaf, 0x73, 0x67, 0xb7, 0xfe, 0xfc, - 0x00, 0x90, 0xdf, 0xbe, 0x70, 0x00, 0x46, 0x4c, 0x47, 0xf4, 0xbb, 0x91, 0x75, 0xd9, 0x26, 0x46, 0x7f, 0xbf, 0x5b, - 0x8c, 0xfe, 0xf5, 0x6a, 0x1f, 0x31, 0xfa, 0xfb, 0xcf, 0x2e, 0x46, 0xbf, 0xac, 0x5a, 0x71, 0xbf, 0xaf, 0xa6, 0x4d, - 0xf8, 0x71, 0x53, 0x25, 0x92, 0x03, 0x62, 0x5c, 0x5f, 0xad, 0x6e, 0x20, 0xe2, 0xd5, 0xfb, 0x78, 0xf8, 0xf5, 0xaa, - 0x64, 0xa2, 0x14, 0x03, 0x06, 0x78, 0x1f, 0x33, 0x0c, 0xf0, 0xa7, 0xd5, 0x10, 0xec, 0x22, 0xf8, 0xad, 0x19, 0x4c, - 0xec, 0x39, 0x09, 0xa7, 0xf2, 0xc6, 0x85, 0x92, 0x01, 0x16, 0x83, 0xdd, 0x3d, 0x5c, 0x26, 0xa0, 0xac, 0x59, 0x2d, - 0xa2, 0xb4, 0x7f, 0xe4, 0x02, 0x9a, 0xef, 0x4c, 0x93, 0xbc, 0xd2, 0xd8, 0x11, 0x31, 0xc2, 0x3e, 0x72, 0xcb, 0xfc, - 0xd6, 0xf7, 0x68, 0xb2, 0xd6, 0xdc, 0xbb, 0x57, 0xef, 0x57, 0x03, 0x5b, 0x10, 0x61, 0xd2, 0x07, 0xc4, 0x46, 0xd3, - 0xfb, 0xb2, 0xe1, 0x58, 0xc5, 0x54, 0xb0, 0x7d, 0xa4, 0x30, 0x92, 0x6a, 0x7b, 0xaf, 0x6c, 0x78, 0xb6, 0x6b, 0x9a, - 0x0d, 0x9f, 0x2f, 0x35, 0xdf, 0x62, 0xf5, 0x26, 0x3b, 0xae, 0x82, 0xaa, 0x92, 0xf4, 0xaf, 0x11, 0x20, 0x05, 0xed, - 0x59, 0x98, 0xc6, 0x15, 0x84, 0x8f, 0xab, 0xe1, 0x6d, 0xec, 0x2a, 0xef, 0x4a, 0x7d, 0xaa, 0xe6, 0x74, 0x2f, 0x36, - 0x48, 0x0f, 0x06, 0x3f, 0x03, 0x61, 0xc3, 0xef, 0xe3, 0x71, 0xac, 0xc2, 0x79, 0xa3, 0xf4, 0xcb, 0x48, 0xed, 0x7c, - 0xee, 0x6d, 0xea, 0xa4, 0x4d, 0xab, 0x21, 0xad, 0x47, 0x17, 0xe2, 0x8e, 0xc6, 0xcf, 0x33, 0xb3, 0xd5, 0x9c, 0x99, - 0x16, 0xa3, 0x65, 0xee, 0xb6, 0xce, 0x44, 0xbd, 0xa7, 0xb0, 0x89, 0x2d, 0xfe, 0xa0, 0xfa, 0x7f, 0x6f, 0xa6, 0x90, - 0xa0, 0xbd, 0x8f, 0x44, 0x84, 0x42, 0x41, 0x75, 0xd0, 0xc6, 0x76, 0xb0, 0xc5, 0xfc, 0x43, 0xed, 0x98, 0x77, 0x82, - 0xb6, 0xba, 0xdb, 0x2c, 0x46, 0xa4, 0x6b, 0xc3, 0xa6, 0xa4, 0x40, 0xf5, 0x7a, 0xc7, 0x96, 0x77, 0x64, 0x39, 0xc7, - 0x3d, 0x33, 0x17, 0x07, 0x4e, 0xed, 0xb2, 0x04, 0x10, 0x30, 0xd9, 0x95, 0xc3, 0x0c, 0xa2, 0x20, 0x0b, 0x48, 0x98, - 0x03, 0xaa, 0x2f, 0xd3, 0xbc, 0x7f, 0x5b, 0xa5, 0x19, 0xcc, 0x51, 0x90, 0x64, 0x68, 0xae, 0x6c, 0x8f, 0x69, 0x76, - 0x4f, 0x69, 0xd4, 0xa2, 0xca, 0xad, 0x5a, 0x3f, 0xff, 0x76, 0xb6, 0xa0, 0x39, 0xb3, 0xb3, 0x18, 0x67, 0x11, 0xdf, - 0x1f, 0xc2, 0x54, 0x37, 0x1f, 0x59, 0x3f, 0xb7, 0x21, 0xdc, 0xbf, 0xed, 0x46, 0xb8, 0x19, 0xdd, 0x07, 0xe1, 0xfe, - 0xed, 0xb3, 0x23, 0xdc, 0x9f, 0x55, 0x84, 0x5b, 0xf2, 0x54, 0x29, 0x64, 0xa2, 0x3f, 0xe0, 0xb3, 0x01, 0xf1, 0xc6, - 0x5f, 0xea, 0x07, 0x8c, 0xbc, 0xd4, 0x95, 0x3c, 0xd0, 0x1f, 0x4a, 0x89, 0xad, 0x90, 0x65, 0xc7, 0xd0, 0xc3, 0x2c, - 0x89, 0x0e, 0xe4, 0x48, 0x76, 0x85, 0xfb, 0x21, 0xf4, 0x79, 0x11, 0x65, 0xa1, 0xf3, 0x9e, 0xb3, 0x25, 0xa0, 0x82, - 0xf8, 0x3a, 0x4e, 0x16, 0x04, 0x83, 0x22, 0xea, 0x98, 0x10, 0x13, 0x1e, 0x5c, 0x70, 0x18, 0xf3, 0xe3, 0x68, 0x22, - 0xe5, 0xe8, 0x74, 0x78, 0xcd, 0xe8, 0x41, 0xfd, 0x81, 0x92, 0x44, 0xb7, 0xd8, 0x6b, 0x58, 0xdc, 0x17, 0x5d, 0xf7, - 0x45, 0xe7, 0xf0, 0xc5, 0x91, 0x0b, 0xff, 0xf3, 0x68, 0x37, 0xb7, 0x78, 0xc5, 0x45, 0x1c, 0x41, 0x4e, 0x1e, 0x51, - 0xb3, 0xad, 0xda, 0x3d, 0xa5, 0xb7, 0x45, 0xad, 0xe3, 0xe6, 0x4a, 0x13, 0xf2, 0x50, 0xd4, 0x69, 0xac, 0x31, 0x8f, - 0x57, 0xca, 0xb0, 0x1a, 0x46, 0x13, 0x44, 0x2b, 0x90, 0x0c, 0x29, 0x35, 0xd4, 0xd7, 0x7c, 0xba, 0xc5, 0xbc, 0x68, - 0x37, 0xbf, 0x29, 0x12, 0x7f, 0x89, 0x04, 0x44, 0x3b, 0x21, 0xc8, 0x85, 0xea, 0x2e, 0xa6, 0x0d, 0xc0, 0x68, 0x6f, - 0x1a, 0xa4, 0xdd, 0x14, 0x0b, 0x44, 0xd8, 0x02, 0x65, 0xc9, 0x2a, 0xf2, 0x0d, 0xfc, 0x49, 0xc6, 0xa9, 0x11, 0x1c, - 0x40, 0x4c, 0x5e, 0xfc, 0xb0, 0x89, 0xab, 0x46, 0xce, 0xdc, 0x22, 0x4b, 0x4a, 0x24, 0x56, 0x85, 0xbc, 0xc8, 0xac, - 0x84, 0xe5, 0x56, 0xc6, 0xa5, 0xb5, 0x87, 0xe4, 0x85, 0x6c, 0xf8, 0x22, 0xb3, 0x20, 0xbf, 0x31, 0x2c, 0xf7, 0xf3, - 0xe7, 0xac, 0x16, 0x64, 0x1c, 0x65, 0xd3, 0x3a, 0xf7, 0x65, 0x96, 0x42, 0x5d, 0x23, 0xb3, 0x58, 0xc7, 0x2c, 0x85, - 0x7d, 0xdf, 0x8a, 0x5f, 0xbe, 0x3c, 0x1b, 0x7a, 0x26, 0xcf, 0x97, 0x5b, 0x4a, 0xee, 0x76, 0xb9, 0x9f, 0x6a, 0xdc, - 0x6c, 0x74, 0xda, 0x5a, 0x06, 0xd1, 0x4c, 0x68, 0xa6, 0x25, 0xf6, 0x82, 0x64, 0x2b, 0x4c, 0x05, 0x46, 0x84, 0x8a, - 0x5a, 0xd4, 0xb9, 0xa3, 0x09, 0xe4, 0xfa, 0x1d, 0xea, 0x5d, 0xc7, 0x75, 0x5c, 0x5d, 0x36, 0x9c, 0x06, 0xb3, 0xe1, - 0x26, 0xce, 0x08, 0xa4, 0xad, 0x0a, 0xe3, 0x19, 0x78, 0x7e, 0x64, 0x41, 0x16, 0x42, 0x0e, 0x24, 0x70, 0x01, 0x59, - 0x30, 0xae, 0x31, 0xe7, 0xf6, 0xb8, 0x24, 0xb9, 0xc5, 0x3c, 0x98, 0xc2, 0xe9, 0x0b, 0x23, 0xcb, 0x7c, 0x07, 0x97, - 0xa1, 0xa1, 0x1b, 0x90, 0x85, 0x95, 0x26, 0xa9, 0xad, 0xda, 0xb7, 0xf7, 0x35, 0x68, 0x63, 0xea, 0x7c, 0x12, 0xd3, - 0x84, 0x2c, 0x20, 0x5d, 0xc0, 0x26, 0xb7, 0x38, 0xa6, 0xd5, 0x39, 0xaa, 0xd5, 0xbc, 0x57, 0x47, 0x96, 0xd6, 0xf1, - 0x2c, 0xcd, 0x05, 0x74, 0xab, 0xe7, 0xd6, 0x26, 0xbf, 0x19, 0xec, 0x52, 0xd1, 0x31, 0xfc, 0xf2, 0x94, 0xcd, 0x83, - 0x29, 0xe7, 0xb8, 0xf0, 0x33, 0x63, 0x41, 0x3d, 0x0d, 0x25, 0x90, 0x7f, 0xc0, 0xc4, 0xf4, 0x57, 0x74, 0x9d, 0x99, - 0x98, 0x23, 0x88, 0x57, 0x09, 0xcc, 0x0d, 0xba, 0xa6, 0x05, 0x91, 0x16, 0x7c, 0xfa, 0x64, 0x04, 0x60, 0x7e, 0x3f, - 0x54, 0xe0, 0x03, 0xcf, 0x66, 0x09, 0x60, 0x41, 0xa1, 0x58, 0x42, 0x60, 0x81, 0x6f, 0x0c, 0xfc, 0x5b, 0x14, 0x8b, - 0x1f, 0x5c, 0xb1, 0xe7, 0x84, 0x24, 0x9a, 0x01, 0x4a, 0x23, 0xd1, 0xac, 0x66, 0x40, 0xc0, 0xbc, 0xeb, 0x2a, 0xa5, - 0x45, 0x57, 0x85, 0x72, 0x3f, 0xfd, 0xea, 0xe1, 0x8a, 0xe5, 0x40, 0x33, 0x74, 0xb8, 0xe5, 0xd0, 0x15, 0xac, 0xd0, - 0x3d, 0xbc, 0x1c, 0x7e, 0x71, 0xba, 0xa0, 0x19, 0x61, 0x82, 0x4b, 0x60, 0xf1, 0x80, 0x1c, 0xd0, 0x7c, 0x91, 0xbf, - 0x98, 0x31, 0x78, 0x13, 0x7a, 0x17, 0xf8, 0x9c, 0x4f, 0xb3, 0x34, 0x7e, 0x4f, 0xd9, 0x68, 0xa3, 0x34, 0xf4, 0x2c, - 0x66, 0x22, 0xeb, 0x13, 0x0c, 0xfd, 0x39, 0x8c, 0x62, 0xfd, 0xec, 0x0b, 0xe9, 0x4d, 0xd4, 0xb6, 0x08, 0x90, 0x88, - 0xf4, 0x3a, 0xa1, 0xe1, 0xdf, 0x87, 0x5f, 0xc0, 0xc5, 0xfd, 0xc5, 0x8d, 0x6e, 0x0e, 0x32, 0x07, 0xf9, 0x98, 0x2f, - 0x1a, 0x12, 0x72, 0x22, 0x8f, 0xca, 0x99, 0xcd, 0xae, 0xc2, 0x6c, 0xc2, 0xef, 0xdd, 0xac, 0x2b, 0xb8, 0xa9, 0x3e, - 0x84, 0xf4, 0x0c, 0xb8, 0x8b, 0x4d, 0x89, 0xe7, 0xf4, 0x06, 0xc8, 0xa0, 0x8e, 0x43, 0xe2, 0xdf, 0x0a, 0x0e, 0x55, - 0x7d, 0xd8, 0x87, 0x17, 0x95, 0x94, 0x5d, 0xe3, 0x5e, 0xc6, 0xad, 0xbc, 0xc1, 0x2f, 0xe3, 0xa7, 0xee, 0xe7, 0x41, - 0x26, 0x99, 0x61, 0x7c, 0xc8, 0xd1, 0x37, 0x16, 0xc6, 0x57, 0xb0, 0x3f, 0xc0, 0xa0, 0x7a, 0x27, 0xdf, 0xf4, 0xee, - 0x3c, 0x77, 0xde, 0xf1, 0x1c, 0x60, 0x73, 0xe6, 0x5d, 0xe7, 0x38, 0xb4, 0xbb, 0xce, 0x31, 0xfc, 0x7d, 0x00, 0xd6, - 0xcb, 0xee, 0x38, 0x87, 0x1f, 0xbc, 0x4e, 0x68, 0x9f, 0x38, 0xc7, 0xf0, 0x77, 0xc9, 0x5a, 0xfd, 0x88, 0x4c, 0x0f, - 0x30, 0x3c, 0x5f, 0x94, 0xb0, 0x80, 0xf2, 0x5b, 0x6a, 0x11, 0xac, 0xd2, 0xf5, 0xd6, 0xa0, 0x89, 0x00, 0x94, 0xa1, - 0x5b, 0x22, 0x4a, 0x60, 0x3a, 0x30, 0xd2, 0x21, 0xcf, 0x6d, 0x21, 0x0c, 0x32, 0x84, 0xd7, 0xa4, 0xc8, 0xbc, 0xd0, - 0x78, 0x8c, 0x78, 0x9b, 0xe6, 0x30, 0xfb, 0x22, 0x69, 0x1a, 0x53, 0x5d, 0xfc, 0x79, 0x89, 0xf1, 0x71, 0xa8, 0x59, - 0xc3, 0x4a, 0x45, 0xe2, 0xce, 0x7c, 0xf7, 0xc0, 0xd1, 0x6f, 0x94, 0xca, 0xc4, 0x51, 0x9f, 0xb5, 0x6f, 0xae, 0xce, - 0x90, 0xbd, 0xff, 0xd2, 0x7e, 0x30, 0x5f, 0x32, 0xeb, 0x47, 0x44, 0xd8, 0x9d, 0x04, 0x89, 0x1c, 0x9e, 0x82, 0xa2, - 0xbd, 0xe6, 0xfc, 0x04, 0x26, 0x64, 0xd8, 0xb9, 0x00, 0x2a, 0xf9, 0x8e, 0x84, 0x8a, 0xe9, 0x85, 0xd2, 0xf2, 0x89, - 0xc4, 0xfc, 0xcf, 0x9f, 0x17, 0x83, 0xb3, 0x2b, 0xe3, 0x3e, 0xf5, 0x7a, 0x70, 0xed, 0xf6, 0x68, 0x77, 0xab, 0x15, - 0xd0, 0xee, 0x10, 0xcd, 0x45, 0x3c, 0x49, 0xa1, 0xe9, 0x17, 0x3a, 0xc6, 0x56, 0x53, 0xa4, 0x9a, 0x86, 0x11, 0xc2, - 0x5b, 0x57, 0x58, 0x1d, 0xdd, 0x1c, 0xa4, 0xfb, 0x84, 0xa5, 0xe6, 0xbc, 0x98, 0x0e, 0xa0, 0xd9, 0x32, 0x8f, 0x1d, - 0x2e, 0x8d, 0xff, 0xee, 0x49, 0xa0, 0x7b, 0x11, 0x68, 0xf8, 0x2a, 0xa7, 0xb5, 0xe4, 0x6e, 0x22, 0xef, 0x55, 0x76, - 0xa1, 0xd2, 0xf4, 0x5c, 0x87, 0x22, 0x48, 0xbd, 0x86, 0xd9, 0x16, 0xa5, 0x79, 0x93, 0xbc, 0x2d, 0x8a, 0x02, 0x2b, - 0x80, 0xc8, 0xef, 0x86, 0x70, 0x75, 0x32, 0x9f, 0x3f, 0x6f, 0xbd, 0x84, 0x98, 0x3a, 0x59, 0x4d, 0x3a, 0xab, 0xab, - 0xf8, 0x4d, 0x57, 0x51, 0x8c, 0xec, 0x17, 0xb1, 0x86, 0xb0, 0xca, 0x62, 0x7b, 0x0f, 0x7f, 0x8e, 0x29, 0xc9, 0x1c, - 0xae, 0x07, 0x31, 0x94, 0xcb, 0xdd, 0xf2, 0x68, 0x17, 0xec, 0xb1, 0x78, 0x18, 0x2d, 0x1e, 0x33, 0xee, 0xd9, 0xe6, - 0xc3, 0x8a, 0xfb, 0x21, 0x43, 0x1f, 0x9f, 0xdc, 0x22, 0x06, 0xca, 0xbb, 0x8c, 0xb0, 0x40, 0x19, 0xea, 0x95, 0x1b, - 0x67, 0x44, 0xa4, 0x38, 0x02, 0xba, 0x7c, 0xd0, 0xa8, 0x30, 0x54, 0x7c, 0x95, 0xcf, 0xde, 0x5d, 0x7d, 0xa9, 0xf1, - 0xfd, 0xcf, 0xf4, 0x5b, 0xc8, 0xc8, 0xb0, 0x5c, 0x17, 0x43, 0x96, 0xeb, 0x42, 0xe3, 0x59, 0x67, 0x20, 0x63, 0x44, - 0x7e, 0xc0, 0x20, 0xa8, 0x6b, 0x34, 0xf2, 0x99, 0xd6, 0x6f, 0xb1, 0x0a, 0xb3, 0x60, 0x49, 0x92, 0xec, 0x00, 0x9a, - 0xda, 0x80, 0xe4, 0xf4, 0x36, 0x0f, 0x66, 0xa6, 0x38, 0x14, 0x42, 0xb5, 0x2c, 0x12, 0x9a, 0xc3, 0x69, 0x10, 0x4a, - 0xc5, 0xa1, 0xf8, 0x00, 0xf1, 0x7d, 0xba, 0xcc, 0x86, 0x3a, 0x59, 0x42, 0xce, 0x13, 0x0c, 0x63, 0x7a, 0x10, 0xfb, - 0x19, 0xcd, 0xec, 0x34, 0x4b, 0x28, 0x59, 0xe8, 0x32, 0x64, 0x67, 0xbd, 0xbf, 0x74, 0x35, 0x5e, 0x04, 0x99, 0x8c, - 0x79, 0xc7, 0x26, 0x08, 0x2a, 0x3c, 0x18, 0x22, 0x84, 0x33, 0x60, 0x20, 0xbc, 0x8c, 0x67, 0x95, 0x1d, 0x55, 0x50, - 0x2e, 0xe7, 0x4a, 0x5c, 0x09, 0x10, 0x8e, 0xfa, 0x71, 0xf8, 0x91, 0x7b, 0x5d, 0xcb, 0xd0, 0x7c, 0xfa, 0xd9, 0x29, - 0x67, 0x6f, 0x35, 0x0c, 0x14, 0xa0, 0xf7, 0x5c, 0x08, 0x36, 0xdb, 0xe6, 0x8f, 0x7d, 0xc0, 0x2b, 0xab, 0x91, 0x15, - 0xfa, 0x97, 0x7c, 0x2c, 0x57, 0x40, 0x08, 0x95, 0x54, 0xbc, 0x73, 0xef, 0x4c, 0x3a, 0x00, 0xe1, 0xa8, 0x90, 0x56, - 0xfa, 0xf4, 0xe9, 0xf5, 0xe8, 0x9f, 0xff, 0x80, 0x14, 0x04, 0x73, 0x4f, 0x78, 0x41, 0x5f, 0xab, 0xb5, 0x38, 0xf5, - 0x69, 0x8d, 0x50, 0xbd, 0x4f, 0x27, 0x22, 0x2a, 0x8c, 0xd8, 0x5a, 0xf9, 0xe8, 0x46, 0x44, 0x6c, 0x82, 0x34, 0x23, - 0xa6, 0xf0, 0xd5, 0x1e, 0xc1, 0xf2, 0x8e, 0x44, 0x88, 0x00, 0xed, 0xa7, 0xf5, 0x57, 0xc7, 0x9a, 0x5e, 0xe4, 0x0e, - 0x68, 0xd0, 0x41, 0xb3, 0x3d, 0x74, 0x76, 0x4a, 0xb8, 0xf0, 0x15, 0xc8, 0x8f, 0xb4, 0x7f, 0x00, 0xd3, 0x9c, 0xc7, - 0x0b, 0xea, 0x04, 0xf1, 0xc1, 0x3d, 0x1d, 0xdb, 0x64, 0x19, 0x30, 0xf9, 0x32, 0xca, 0xdd, 0x34, 0x46, 0xf9, 0x49, - 0x05, 0x2d, 0xa3, 0xaf, 0xf3, 0x02, 0x94, 0x71, 0x01, 0x28, 0xf8, 0x49, 0xce, 0xca, 0x71, 0xf8, 0x1c, 0x91, 0x17, - 0xa2, 0x8c, 0xe5, 0xcf, 0x59, 0x38, 0x3d, 0x11, 0x39, 0xaf, 0x78, 0xb0, 0xe3, 0xe9, 0x54, 0x8d, 0x9d, 0xe7, 0x94, - 0xbf, 0x2f, 0xa1, 0x52, 0xec, 0xd9, 0x78, 0xc9, 0xbe, 0x54, 0xff, 0x84, 0xfc, 0x09, 0xb1, 0x40, 0x78, 0x98, 0x45, - 0x38, 0xcf, 0xb5, 0x18, 0x7c, 0x12, 0x24, 0x4f, 0x59, 0x25, 0x8e, 0x28, 0xaa, 0xd1, 0xd9, 0x5b, 0x48, 0x93, 0x27, - 0xc3, 0x21, 0xc3, 0x63, 0x55, 0x74, 0x06, 0x50, 0x6a, 0xc8, 0x91, 0x01, 0x93, 0xcd, 0xa0, 0xa1, 0xcd, 0x3c, 0xb8, - 0xb0, 0x51, 0x75, 0x3a, 0xf5, 0x31, 0x1e, 0x10, 0xb1, 0xbf, 0x4a, 0x3b, 0x10, 0x76, 0x16, 0x5f, 0x58, 0x40, 0xe0, - 0xa2, 0x9f, 0x0a, 0x1e, 0xd7, 0xfe, 0xc0, 0x50, 0xb6, 0x1d, 0x92, 0x87, 0x58, 0xd1, 0xac, 0x73, 0x27, 0xfb, 0x4b, - 0x2c, 0xbd, 0x12, 0xce, 0x6d, 0xb5, 0x93, 0x24, 0xb3, 0x00, 0xd4, 0x4f, 0x93, 0x1a, 0xb6, 0x7f, 0xd7, 0x61, 0x52, - 0xeb, 0x96, 0x27, 0x83, 0xd8, 0x31, 0x2f, 0x0e, 0x5a, 0xe9, 0x25, 0x9e, 0xfb, 0xfc, 0xf4, 0x00, 0xe6, 0x07, 0x81, - 0x01, 0x4a, 0x94, 0x51, 0x60, 0x42, 0xf4, 0x01, 0x92, 0x32, 0xeb, 0x80, 0x8b, 0x89, 0x20, 0xea, 0x90, 0x73, 0x94, - 0x41, 0x3e, 0x4b, 0x55, 0xea, 0xc4, 0x8a, 0xdb, 0x4c, 0xe5, 0xed, 0xce, 0xc0, 0xf1, 0xa7, 0x15, 0xa6, 0xdf, 0xc8, - 0x07, 0x19, 0x15, 0x7e, 0xb7, 0x97, 0x59, 0x8b, 0x6b, 0x6e, 0x5b, 0x15, 0x46, 0xb0, 0x6e, 0xa9, 0x50, 0xec, 0xe3, - 0x6d, 0xb5, 0x0a, 0xd2, 0x48, 0x56, 0x5b, 0x12, 0x43, 0x7f, 0x8a, 0x3b, 0xbe, 0x56, 0x1b, 0x4b, 0xa1, 0xde, 0x65, - 0x36, 0x84, 0xaa, 0x42, 0xd8, 0x4e, 0x96, 0x4b, 0x56, 0xd9, 0x1c, 0x9c, 0x1e, 0x30, 0xbe, 0xf3, 0x8c, 0xed, 0xb0, - 0xb3, 0x53, 0xb0, 0x2e, 0x64, 0x8b, 0x4e, 0x96, 0x4b, 0xbe, 0xa4, 0xec, 0x17, 0x7b, 0x73, 0x30, 0xcf, 0x16, 0xe1, - 0xd9, 0xff, 0x01, 0xff, 0xd7, 0x9f, 0x05, 0x1b, 0x5f, 0x03, 0x00}; + 0x1e, 0x7f, 0xcb, 0xc7, 0x6c, 0x61, 0x3c, 0x35, 0x6f, 0xaf, 0x16, 0x93, 0xc1, 0xe0, 0xd6, 0xdf, 0xdf, 0xf3, 0x70, + 0x76, 0x3b, 0x67, 0xd7, 0xfc, 0x9e, 0x16, 0xd3, 0x44, 0x35, 0xbd, 0x78, 0x4c, 0xf0, 0xba, 0xf5, 0xfd, 0x89, 0xc5, + 0xff, 0x6a, 0x5f, 0x34, 0x6f, 0xfd, 0x81, 0xb4, 0x46, 0xcb, 0x5d, 0xfd, 0xfd, 0xe3, 0x8a, 0x89, 0x5b, 0x10, 0x2f, + 0xde, 0xdb, 0x9a, 0x86, 0xb7, 0xfc, 0xa3, 0x77, 0xed, 0x4f, 0xaf, 0x75, 0xcc, 0xcd, 0x44, 0x1d, 0x49, 0x6f, 0x2f, + 0x9e, 0xb3, 0x5f, 0xf9, 0x27, 0x79, 0x9c, 0x7c, 0x11, 0x72, 0xd2, 0xde, 0x20, 0x77, 0x13, 0x9d, 0x12, 0xef, 0xdc, + 0x44, 0xc2, 0x82, 0x40, 0x18, 0x8e, 0x9a, 0x3f, 0x4c, 0xca, 0xa9, 0xb7, 0x03, 0x6e, 0x57, 0x6e, 0xeb, 0x9f, 0x6f, + 0x39, 0xe7, 0x8b, 0xe1, 0xe5, 0xf4, 0x5d, 0xb7, 0x4b, 0x8f, 0x8a, 0x66, 0x53, 0x81, 0x6e, 0xb7, 0x18, 0x7b, 0x75, + 0x32, 0xb3, 0xcc, 0x25, 0x5f, 0x7a, 0x57, 0x9b, 0x99, 0xc7, 0xf4, 0x7e, 0x33, 0xcd, 0x90, 0xc8, 0x17, 0x08, 0x99, + 0x0e, 0x87, 0xbb, 0x73, 0x2c, 0x8f, 0x0f, 0xdf, 0x3e, 0x7b, 0x32, 0x78, 0x82, 0x91, 0x5b, 0x56, 0x34, 0xc8, 0x3b, + 0x3e, 0xcc, 0xea, 0xd6, 0x6d, 0xe3, 0xe2, 0xf9, 0xf0, 0x17, 0xc8, 0x1b, 0x74, 0x3d, 0x34, 0x45, 0xb4, 0xca, 0xef, + 0x28, 0xfa, 0x44, 0xc9, 0x41, 0xc7, 0x13, 0xa8, 0x1d, 0x52, 0xe0, 0xbe, 0x7b, 0xc6, 0x41, 0xbf, 0x81, 0xa5, 0xf6, + 0xfb, 0xe7, 0x9f, 0x88, 0x47, 0x1a, 0xc6, 0xfb, 0xfb, 0x30, 0xfa, 0x23, 0x2e, 0x8b, 0x35, 0x9c, 0xae, 0x03, 0xf8, + 0xdc, 0x33, 0x7d, 0xfb, 0xba, 0xf3, 0x7d, 0x3f, 0xf0, 0xb6, 0xfc, 0x86, 0xbd, 0xe3, 0xde, 0xe5, 0xf0, 0xad, 0xff, + 0xec, 0x09, 0x88, 0x4e, 0x30, 0x2e, 0x9f, 0x31, 0x12, 0xb6, 0xa3, 0x18, 0xb5, 0x0a, 0x3f, 0xd7, 0x10, 0xa2, 0xf5, + 0x09, 0x19, 0xbb, 0x20, 0xfd, 0x83, 0x02, 0xf4, 0x13, 0x02, 0xab, 0x49, 0x6a, 0x14, 0x98, 0xc4, 0xb7, 0x35, 0x24, + 0x90, 0x82, 0x05, 0x42, 0x6f, 0xa0, 0xf8, 0x54, 0xf0, 0x77, 0xc3, 0xcf, 0x24, 0xf9, 0x2d, 0x6a, 0x3e, 0x86, 0xbf, + 0x61, 0x68, 0x26, 0xd5, 0x43, 0x5a, 0x47, 0x89, 0xf7, 0x93, 0xbf, 0x8f, 0xc2, 0x4a, 0xa8, 0x63, 0x21, 0x48, 0xc5, + 0x90, 0x0b, 0x71, 0xf1, 0x7c, 0x72, 0x5b, 0x8a, 0xf0, 0x8f, 0x09, 0x3e, 0x93, 0x0b, 0x4d, 0x3e, 0xa3, 0x27, 0x8d, + 0x7c, 0xff, 0x41, 0xbe, 0x2f, 0x3b, 0x35, 0x58, 0xd4, 0x43, 0x7e, 0x5b, 0xbb, 0xef, 0xcb, 0x29, 0x41, 0x8f, 0xec, + 0x07, 0x34, 0x05, 0x03, 0x35, 0x01, 0x29, 0x43, 0x70, 0x0b, 0x57, 0x7d, 0x4f, 0x15, 0xe4, 0xcb, 0xef, 0x7d, 0x16, + 0x32, 0x5c, 0x65, 0x41, 0x48, 0x72, 0xa9, 0x90, 0xc2, 0xc6, 0x6d, 0x3d, 0xf8, 0xac, 0x31, 0x49, 0x24, 0xe4, 0x94, + 0x80, 0x24, 0x69, 0x6f, 0x20, 0x49, 0xc4, 0xf4, 0x1f, 0xae, 0x93, 0xa6, 0x59, 0x49, 0xe9, 0x86, 0x38, 0x55, 0xaf, + 0x91, 0xe6, 0x2c, 0x78, 0xcf, 0x60, 0xe9, 0x48, 0xb1, 0xe2, 0x9d, 0x31, 0x18, 0xeb, 0x60, 0xa1, 0x3b, 0x59, 0xdc, + 0xaf, 0x92, 0x30, 0x8d, 0x44, 0x95, 0x2f, 0x42, 0xfe, 0xfc, 0x97, 0x12, 0x7f, 0xf4, 0x96, 0x06, 0x22, 0x10, 0xfc, + 0x00, 0xad, 0x07, 0xac, 0xf1, 0xe0, 0x27, 0x56, 0x97, 0x61, 0x5e, 0x65, 0x54, 0xde, 0x6c, 0xc7, 0xb6, 0x73, 0xa6, + 0xaa, 0x16, 0x7c, 0x16, 0x86, 0x16, 0xed, 0x6c, 0xd5, 0x9c, 0xdc, 0xe6, 0x0d, 0xbe, 0x33, 0x49, 0x22, 0xb5, 0x94, + 0x44, 0xda, 0xea, 0xfa, 0x74, 0xe9, 0x75, 0x8b, 0x0a, 0x1a, 0x23, 0x40, 0x2f, 0x49, 0x77, 0x95, 0x4f, 0x28, 0x5e, + 0x59, 0x0d, 0xab, 0xe1, 0xa5, 0x43, 0x11, 0xc6, 0xda, 0x9b, 0x2b, 0x79, 0x76, 0x07, 0xd6, 0x23, 0xb4, 0x76, 0x55, + 0xea, 0x10, 0xb6, 0x9f, 0xe8, 0x3d, 0xa7, 0x52, 0x7f, 0x03, 0xaa, 0xc0, 0xa9, 0xa3, 0xa1, 0x3e, 0x6a, 0xa7, 0x90, + 0xed, 0xdc, 0x5b, 0x12, 0x54, 0xae, 0xe4, 0xa6, 0x4a, 0x8b, 0x52, 0xca, 0x94, 0xaf, 0x65, 0xb6, 0xb2, 0xfb, 0x64, + 0x00, 0xf1, 0x6c, 0x50, 0x20, 0xb9, 0xa8, 0xad, 0xe6, 0x20, 0x7d, 0x34, 0x4b, 0x1c, 0x6b, 0x07, 0x85, 0x97, 0x55, + 0x60, 0xe6, 0x32, 0x97, 0xcb, 0x41, 0xc1, 0x72, 0xbd, 0xd5, 0x4c, 0x33, 0xd5, 0x17, 0xb9, 0xbd, 0xcd, 0x78, 0x99, + 0xfe, 0x9b, 0x25, 0x03, 0x1e, 0x5d, 0x3c, 0xf7, 0x03, 0x48, 0x93, 0xbc, 0x0e, 0x90, 0x04, 0x9b, 0x83, 0x5d, 0xec, + 0x30, 0x6c, 0x15, 0x2b, 0x7b, 0xf2, 0x74, 0xb9, 0x43, 0x53, 0x2e, 0x61, 0x24, 0x27, 0xe6, 0x52, 0xea, 0xfb, 0x92, + 0xea, 0x86, 0x82, 0x93, 0x4d, 0x13, 0x50, 0x0a, 0x68, 0xb7, 0xe0, 0xbf, 0xf0, 0xa9, 0xa1, 0xd3, 0x02, 0x2c, 0xb5, + 0xdd, 0x80, 0xff, 0x42, 0xbf, 0xd8, 0x3e, 0xa2, 0x7e, 0x60, 0x1e, 0xec, 0xcd, 0xda, 0xca, 0x18, 0x10, 0x91, 0xb8, + 0x82, 0x3c, 0x12, 0xfc, 0xa0, 0xd8, 0xd3, 0x65, 0xe2, 0xc0, 0x99, 0xe2, 0x62, 0x29, 0xb5, 0x99, 0x79, 0xed, 0xb7, + 0xd4, 0xc4, 0x9b, 0x28, 0x89, 0x0a, 0xdb, 0x21, 0x8d, 0x5e, 0x52, 0xc6, 0x54, 0xc1, 0x86, 0xe8, 0xbe, 0x6e, 0x82, + 0x29, 0xf0, 0xa6, 0xaa, 0x02, 0x22, 0xd4, 0x5e, 0x64, 0x79, 0x7e, 0xd3, 0x05, 0x56, 0x17, 0x7c, 0x6c, 0x4c, 0xb3, + 0x0b, 0x56, 0x72, 0x35, 0x93, 0x3e, 0xf3, 0x76, 0xa0, 0x85, 0xbc, 0xcb, 0xcb, 0xa2, 0x15, 0xba, 0x1e, 0x44, 0x0b, + 0x7f, 0xaf, 0x39, 0x1e, 0x3d, 0xdb, 0x56, 0x53, 0x9b, 0x7d, 0xad, 0xc5, 0x02, 0x19, 0x88, 0x86, 0xbe, 0x90, 0x33, + 0x0a, 0x77, 0x95, 0xe6, 0x6a, 0xb5, 0xaf, 0xca, 0x20, 0x81, 0x89, 0x20, 0x6b, 0x59, 0x78, 0x8f, 0xee, 0xd5, 0x23, + 0xcd, 0x2b, 0x09, 0x9e, 0xb9, 0xf8, 0x0b, 0x00, 0xa1, 0x3c, 0x49, 0xc8, 0x01, 0x39, 0x80, 0xbf, 0xa5, 0x28, 0x95, + 0x06, 0xf8, 0x67, 0x75, 0x39, 0xb6, 0xf5, 0xfd, 0x9d, 0x56, 0x31, 0xb8, 0xfe, 0x7c, 0xdd, 0xf5, 0xac, 0x1d, 0xe2, + 0x5c, 0xd9, 0xea, 0xb5, 0x65, 0x9a, 0xc7, 0x48, 0x5d, 0x03, 0x70, 0x27, 0xd2, 0x23, 0x10, 0xc9, 0x4c, 0x34, 0xc8, + 0xd9, 0x0b, 0x3e, 0x9e, 0x8a, 0xc7, 0xa4, 0xbd, 0xca, 0xf7, 0xcd, 0x85, 0x3e, 0x18, 0x63, 0xdf, 0x82, 0x06, 0xf1, + 0xd1, 0x6a, 0x6b, 0x05, 0x62, 0xbd, 0x55, 0xea, 0x43, 0x37, 0x46, 0x41, 0x07, 0x8f, 0xb8, 0x91, 0x0b, 0x8e, 0xed, + 0xae, 0xad, 0xa7, 0xf4, 0x15, 0x80, 0xb9, 0x0e, 0x54, 0x32, 0x0c, 0x52, 0xe7, 0x89, 0xc2, 0x24, 0x3f, 0x4f, 0x48, + 0x42, 0x44, 0x75, 0xb6, 0x1c, 0xa5, 0xdc, 0xb4, 0x80, 0xcb, 0x8c, 0x0c, 0x30, 0x9b, 0x34, 0xeb, 0x27, 0x97, 0x2f, + 0x41, 0x2a, 0x0d, 0x11, 0xdc, 0xb0, 0xbd, 0x64, 0x74, 0xeb, 0xa8, 0x1b, 0x54, 0x49, 0xe6, 0xfa, 0xcd, 0xed, 0x2c, + 0x52, 0xe6, 0xcd, 0x47, 0x18, 0x6b, 0xf2, 0x21, 0xac, 0x13, 0xfc, 0x36, 0x40, 0x25, 0x7d, 0x2a, 0xbc, 0x68, 0x04, + 0x10, 0xea, 0x3b, 0x55, 0xc6, 0xa7, 0xc2, 0xcb, 0x46, 0x5b, 0x96, 0x51, 0x0a, 0xd5, 0x05, 0xb3, 0x5b, 0xd3, 0x85, + 0xe8, 0x56, 0xd5, 0x40, 0x1b, 0xb8, 0x76, 0x1d, 0x28, 0xa0, 0xa1, 0xda, 0x95, 0x1b, 0x16, 0x80, 0xd5, 0x4c, 0x04, + 0x86, 0xcb, 0xbf, 0xcf, 0x5f, 0xa9, 0x18, 0x9e, 0x7e, 0x3f, 0xf4, 0xf6, 0xdb, 0x20, 0x1a, 0x6d, 0x2f, 0xd9, 0x2e, + 0x88, 0x46, 0xbb, 0xcb, 0x86, 0xd1, 0xef, 0xe7, 0xf4, 0xfb, 0x79, 0x03, 0x3a, 0x12, 0x61, 0xc2, 0xec, 0xf5, 0x1b, + 0xb5, 0x7c, 0xa5, 0xd6, 0xef, 0xd4, 0xf2, 0xa5, 0x1a, 0xde, 0xda, 0x93, 0x44, 0x10, 0x59, 0xaa, 0x9a, 0x07, 0x49, + 0x91, 0x6a, 0xe9, 0x72, 0x8c, 0x16, 0x23, 0x6a, 0x29, 0x6b, 0x8e, 0x75, 0x22, 0xed, 0x1c, 0x94, 0x0c, 0x70, 0xb4, + 0xb8, 0xaa, 0x31, 0xdd, 0xac, 0x68, 0x09, 0xc4, 0x08, 0x2b, 0xdb, 0x72, 0x71, 0x93, 0xfa, 0xe8, 0x9c, 0x7c, 0xdb, + 0x2a, 0xe5, 0xdb, 0x56, 0xf0, 0xfc, 0x2b, 0x0a, 0xe5, 0x92, 0x6b, 0xd7, 0xb2, 0x69, 0xa1, 0x14, 0xca, 0xb8, 0x06, + 0x5b, 0xfb, 0x26, 0x30, 0x64, 0x3e, 0x52, 0xd4, 0xd8, 0x5e, 0x34, 0xca, 0x21, 0xc8, 0xd6, 0xc1, 0xa8, 0x53, 0x16, + 0x2c, 0xbe, 0xdd, 0x21, 0x03, 0x19, 0xe8, 0xa8, 0x6a, 0xe3, 0xd5, 0xce, 0x4a, 0x7f, 0x58, 0x5e, 0x3c, 0x67, 0x89, + 0x95, 0x4e, 0x7e, 0x53, 0xa1, 0x3f, 0x08, 0xd1, 0x37, 0x65, 0xc3, 0xc1, 0x8b, 0x2e, 0xb6, 0x32, 0x20, 0xde, 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, 0xf3, 0x28, 0xd4, + 0x2c, 0x4f, 0x00, 0x0b, 0x5e, 0x98, 0x19, 0x2e, 0xcc, 0x0c, 0xc7, 0x21, 0x35, 0x4e, 0x0f, 0x7a, 0xaf, 0x73, 0xcf, + 0x2d, 0x77, 0xa3, 0xd3, 0x30, 0x6f, 0x47, 0x1b, 0xcc, 0xf1, 0x41, 0x38, 0x81, 0xf8, 0xc0, 0x12, 0x01, 0x7a, 0x34, + 0xac, 0x8e, 0x1a, 0x2a, 0x47, 0xf1, 0x65, 0x01, 0x48, 0x96, 0x04, 0x20, 0xb9, 0x57, 0xe3, 0x5c, 0x5a, 0x7e, 0x5d, + 0x25, 0x21, 0x47, 0x64, 0xbc, 0x94, 0x76, 0xf7, 0x84, 0x97, 0x23, 0x23, 0x34, 0x4f, 0x16, 0xa9, 0x97, 0xb3, 0x8c, + 0x8d, 0x11, 0xb8, 0x28, 0xf4, 0x9b, 0xaa, 0xdf, 0x4f, 0x4b, 0x2f, 0xa7, 0x76, 0x7e, 0x02, 0x7f, 0xcb, 0x53, 0x67, + 0x91, 0x23, 0xe4, 0xd5, 0xc8, 0x24, 0x2c, 0x2f, 0x95, 0x7a, 0xfa, 0x12, 0x66, 0x50, 0x77, 0x6f, 0x14, 0x80, 0x6b, + 0x91, 0x4b, 0xa7, 0xda, 0x12, 0xae, 0x4c, 0xb9, 0xc1, 0x3e, 0x0f, 0x79, 0x4e, 0x42, 0xa8, 0x44, 0x1e, 0x29, 0xac, + 0xfb, 0xf6, 0xc5, 0xf3, 0x89, 0xeb, 0xc3, 0x62, 0xa3, 0x11, 0x1c, 0x0e, 0x00, 0x73, 0x30, 0xf5, 0xa2, 0x01, 0x2f, + 0xd5, 0x9c, 0xf9, 0xe8, 0xe5, 0x84, 0x8d, 0x01, 0x6a, 0x8a, 0x81, 0x53, 0xd6, 0x33, 0xf9, 0xc8, 0xf8, 0x96, 0xf9, + 0x7e, 0x80, 0xef, 0xd6, 0x85, 0x84, 0x7c, 0x50, 0xa8, 0x04, 0x99, 0x42, 0x25, 0x48, 0x0c, 0x2a, 0x41, 0x6c, 0x50, + 0x09, 0x36, 0x0d, 0x5f, 0x4b, 0xe5, 0x6d, 0x04, 0x1c, 0x11, 0x3e, 0xf4, 0x2c, 0x6c, 0xac, 0x50, 0x3c, 0x1b, 0xb3, + 0x31, 0x2b, 0xd4, 0xce, 0x93, 0xcb, 0xa9, 0xd8, 0x59, 0x8c, 0x75, 0x13, 0x59, 0x26, 0x5e, 0x48, 0xd0, 0x71, 0xce, + 0x85, 0x44, 0x5d, 0xfd, 0xdc, 0x7b, 0x49, 0xc6, 0x92, 0x79, 0x43, 0xa3, 0x06, 0xf3, 0xb2, 0xeb, 0x00, 0xa6, 0x25, + 0xdf, 0x16, 0x34, 0x98, 0x4e, 0x95, 0x47, 0xa4, 0x49, 0x50, 0x3b, 0x97, 0x49, 0x91, 0x13, 0xc2, 0x24, 0xe8, 0x95, + 0xe0, 0x37, 0x12, 0xda, 0xff, 0xab, 0x9e, 0xef, 0x80, 0xc1, 0x44, 0xab, 0xe4, 0x0b, 0x58, 0x2d, 0x73, 0xfe, 0x52, + 0x7a, 0x62, 0x23, 0xfe, 0x62, 0x99, 0xc6, 0xa3, 0x2f, 0x6c, 0x88, 0x78, 0x56, 0x2f, 0xd1, 0xb4, 0x04, 0x75, 0x80, + 0x47, 0xf4, 0xd7, 0xe8, 0x8b, 0xe1, 0x4d, 0xe9, 0x6a, 0xa4, 0xae, 0xd9, 0x39, 0xe7, 0x5f, 0x6a, 0x43, 0x84, 0x8c, + 0x69, 0x53, 0x20, 0x19, 0x10, 0x48, 0x32, 0x10, 0x00, 0x98, 0x9a, 0xce, 0xec, 0x15, 0x40, 0x34, 0x10, 0xc0, 0xe3, + 0xbc, 0xe3, 0xf1, 0x23, 0xfd, 0x55, 0x1c, 0xf7, 0x4e, 0xd3, 0xb0, 0xfd, 0x17, 0xa0, 0x29, 0x86, 0x72, 0x3c, 0xdf, + 0x29, 0x48, 0xf6, 0x28, 0x65, 0xe9, 0xaa, 0x89, 0xec, 0x50, 0xac, 0x4f, 0x73, 0xca, 0x42, 0xda, 0x96, 0x63, 0xb4, + 0xc5, 0xfa, 0x31, 0xf2, 0xde, 0xdc, 0xa8, 0xc8, 0x07, 0x3d, 0xb8, 0xbd, 0xbd, 0x7d, 0xdd, 0x63, 0x36, 0xc9, 0x8a, + 0x45, 0xae, 0x22, 0x4e, 0x9c, 0xd6, 0x21, 0x07, 0x0c, 0xc8, 0x49, 0x08, 0x4c, 0x63, 0x5c, 0x2a, 0xd0, 0x41, 0xc9, + 0x72, 0x5e, 0x03, 0xb5, 0x2c, 0x22, 0x6b, 0x80, 0xa8, 0xa6, 0xf9, 0x57, 0x0d, 0xf9, 0x49, 0xd5, 0x9c, 0x52, 0xa8, + 0x7d, 0xc5, 0xc3, 0xea, 0xf4, 0x89, 0x55, 0x9b, 0x18, 0xeb, 0x5f, 0x6b, 0x4f, 0xd0, 0x56, 0xd2, 0x40, 0x7c, 0xe7, + 0xeb, 0xf4, 0x8e, 0x42, 0x77, 0x9c, 0x99, 0x78, 0xaa, 0x02, 0x63, 0xdf, 0xda, 0x11, 0x14, 0x0e, 0x4d, 0xd7, 0x01, + 0x87, 0x69, 0x74, 0xc2, 0xe2, 0x9f, 0xd2, 0x71, 0xf2, 0xa2, 0x56, 0x88, 0x24, 0xff, 0x10, 0x2e, 0x0c, 0x89, 0x05, + 0x79, 0x49, 0xa8, 0x23, 0x32, 0x62, 0x35, 0x2a, 0xd6, 0x42, 0x45, 0xc5, 0x29, 0x1e, 0x6f, 0x15, 0x14, 0x97, 0xa2, + 0x54, 0x29, 0x15, 0xb9, 0x51, 0x29, 0x20, 0x96, 0x0d, 0xbc, 0x5b, 0xc0, 0x01, 0x10, 0x74, 0x96, 0xbb, 0xb5, 0xed, + 0x6e, 0x23, 0xf3, 0x99, 0x69, 0x9e, 0x56, 0x1f, 0xd4, 0xdf, 0xef, 0x97, 0x18, 0x5b, 0xe3, 0xe9, 0xef, 0xdb, 0xb4, + 0xe0, 0xe6, 0x6f, 0x18, 0xa2, 0x3b, 0x40, 0xc4, 0x2c, 0xed, 0xa1, 0x90, 0x05, 0x13, 0x96, 0xa1, 0x2a, 0x4f, 0x39, + 0xea, 0xe5, 0x93, 0x5b, 0x80, 0x50, 0x43, 0xbf, 0x36, 0x3a, 0xd5, 0x55, 0x09, 0xc2, 0xf7, 0x5d, 0xa1, 0x1e, 0x9b, + 0x03, 0x9e, 0x0c, 0x80, 0xbf, 0x22, 0xaf, 0xf5, 0xd8, 0xfe, 0x41, 0x6f, 0xd4, 0x1b, 0x20, 0x88, 0xce, 0x79, 0xe1, + 0x1f, 0x71, 0xae, 0x53, 0x7f, 0xc6, 0x85, 0x20, 0xbe, 0xf5, 0x24, 0xbc, 0x17, 0x67, 0x69, 0x1c, 0x9c, 0xf5, 0x06, + 0xe6, 0x22, 0x50, 0x9c, 0xa5, 0xf9, 0x19, 0x88, 0xe5, 0x88, 0x89, 0x58, 0xb3, 0x3b, 0x80, 0x09, 0x2c, 0x75, 0x1c, + 0xb2, 0xea, 0xd8, 0x7e, 0xff, 0xcd, 0xc8, 0x90, 0xa5, 0x23, 0x0c, 0x8c, 0xfe, 0x5d, 0x81, 0x00, 0x05, 0xcb, 0xcc, + 0xf6, 0x60, 0xd2, 0xd5, 0x9e, 0xd5, 0xf3, 0x66, 0x93, 0x77, 0xf5, 0x8e, 0xd5, 0xb4, 0x9c, 0x9a, 0x56, 0x59, 0x4d, + 0x9b, 0xe4, 0x50, 0x33, 0xd1, 0xef, 0x6b, 0x50, 0xd4, 0x7c, 0x0e, 0x60, 0x6c, 0x98, 0xfc, 0x66, 0x56, 0xcd, 0xfb, + 0x7d, 0x4f, 0x3e, 0x82, 0x5f, 0xc8, 0x56, 0xe6, 0xd6, 0x58, 0x3e, 0x7d, 0x4d, 0x24, 0x66, 0x06, 0xe6, 0xe8, 0xee, + 0x08, 0xdf, 0xeb, 0x46, 0x78, 0x1d, 0x73, 0x85, 0xcd, 0xc4, 0xf4, 0x0d, 0x0c, 0x9e, 0x27, 0x7c, 0x70, 0x91, 0xa3, + 0xbf, 0x91, 0xc3, 0x4c, 0x61, 0x41, 0xce, 0xfd, 0xc9, 0x1b, 0xc4, 0x4b, 0x46, 0x78, 0x07, 0x9d, 0x4e, 0x78, 0x90, + 0xfd, 0xfe, 0x0a, 0x3a, 0xb3, 0x95, 0x4a, 0xd9, 0xaa, 0xa8, 0x4c, 0xd7, 0x75, 0x51, 0x56, 0xd0, 0xb1, 0xf4, 0xf3, + 0x56, 0xc8, 0xcc, 0xfa, 0x99, 0x05, 0xf7, 0xb4, 0x92, 0x00, 0x53, 0xb6, 0x6d, 0xa2, 0x36, 0xf0, 0xb2, 0x2e, 0x3e, + 0x17, 0x78, 0x74, 0xd6, 0x5e, 0x6f, 0x84, 0xda, 0xe7, 0x7c, 0xb4, 0x2e, 0xd6, 0x1e, 0xf8, 0xc1, 0xcc, 0xd2, 0xb9, + 0x22, 0xce, 0xc8, 0xfd, 0xd1, 0xe7, 0x22, 0xcd, 0x29, 0x0f, 0x70, 0x1f, 0x8a, 0xb9, 0xfd, 0x16, 0x48, 0x3f, 0xf4, + 0x16, 0xc8, 0x3e, 0x3a, 0xe7, 0xe4, 0x0d, 0x20, 0xd2, 0x21, 0x0c, 0x6e, 0x45, 0x82, 0x8e, 0x55, 0xc3, 0x5b, 0x0b, + 0xec, 0xb4, 0x97, 0xc6, 0xbd, 0x34, 0x3f, 0x4b, 0xfb, 0x7d, 0x83, 0x9a, 0x99, 0x22, 0x1c, 0x3c, 0xce, 0xc8, 0x45, + 0xd2, 0x82, 0x2d, 0xa5, 0xfd, 0x57, 0x03, 0x47, 0x10, 0xf2, 0xf7, 0x3f, 0x84, 0xf7, 0x04, 0x20, 0x36, 0x69, 0x03, + 0xae, 0x7a, 0x4c, 0x47, 0x63, 0x4b, 0xa2, 0x56, 0x9d, 0x0d, 0x90, 0x38, 0x55, 0x5a, 0x4f, 0xb9, 0x59, 0x53, 0x18, + 0xa4, 0xca, 0x42, 0xfd, 0xc6, 0x7a, 0x32, 0x59, 0xe5, 0x22, 0x23, 0x8e, 0xca, 0xf4, 0xa5, 0x66, 0x04, 0xd3, 0xa5, + 0x9f, 0x2f, 0x60, 0xc9, 0xc6, 0x1f, 0x71, 0xf2, 0x96, 0x80, 0x63, 0x3b, 0x6b, 0x57, 0xd5, 0x2e, 0xc7, 0xad, 0xdd, + 0x1c, 0xe0, 0x7b, 0xbd, 0xd1, 0x68, 0xa4, 0x9d, 0xe3, 0x04, 0x0c, 0x55, 0x4f, 0x2d, 0x85, 0x1e, 0xab, 0x15, 0xa0, + 0x6e, 0x47, 0x2e, 0xb3, 0x64, 0x30, 0x5f, 0x18, 0xc7, 0xaf, 0xcc, 0x47, 0x1f, 0x2f, 0x95, 0xb5, 0xeb, 0x88, 0xaf, + 0xff, 0x20, 0xab, 0xf5, 0x2d, 0xef, 0xaa, 0x26, 0xe0, 0x8b, 0x2a, 0xa0, 0xf4, 0x1b, 0xde, 0x93, 0xbd, 0x8b, 0xaf, + 0xdd, 0x60, 0x97, 0x7c, 0xcb, 0x5b, 0xd4, 0x79, 0xbe, 0x72, 0x70, 0xa3, 0x4a, 0xb7, 0xf7, 0x92, 0x05, 0xae, 0xbd, + 0xa3, 0xa6, 0xb1, 0x9e, 0xf9, 0xd1, 0xc3, 0x22, 0x64, 0x3b, 0x1f, 0x7b, 0x5f, 0x35, 0x4f, 0xcf, 0x1a, 0x7a, 0x93, + 0x1a, 0xfa, 0xd8, 0x8b, 0xb2, 0x7d, 0x6a, 0x1a, 0xd1, 0x6b, 0xd8, 0xd0, 0xc7, 0xde, 0x92, 0x93, 0x43, 0x22, 0xc0, + 0xa9, 0x31, 0x7f, 0x7c, 0x38, 0x9d, 0xe1, 0xef, 0x18, 0x50, 0x09, 0xc4, 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, 0x24, 0x77, 0xa5, 0x37, 0xb0, 0x02, 0x69, 0x5b, 0x54, 0x1f, 0xca, + 0xa5, 0xb7, 0x53, 0x87, 0x76, 0xe5, 0x4f, 0xf2, 0xc3, 0xa1, 0x18, 0x99, 0x63, 0x1c, 0xc0, 0x4d, 0x0a, 0x25, 0x47, + 0xc9, 0x5a, 0x82, 0xe8, 0x94, 0xc6, 0x53, 0x59, 0xaf, 0xad, 0x88, 0xbc, 0x1a, 0x71, 0x1e, 0x82, 0x1f, 0x3d, 0x50, + 0x8b, 0xbf, 0xd0, 0x82, 0xd8, 0x63, 0x9f, 0x2a, 0xa5, 0x17, 0xbc, 0x2a, 0x20, 0x44, 0xec, 0xef, 0x06, 0xda, 0x41, + 0x09, 0x0e, 0x25, 0xdc, 0x07, 0x84, 0x85, 0x7e, 0xed, 0xe5, 0x33, 0x19, 0xa3, 0xdc, 0x1b, 0x54, 0x73, 0x06, 0x30, + 0x95, 0x3e, 0x03, 0xbf, 0x4b, 0x80, 0x3a, 0xc5, 0xa7, 0xe8, 0x54, 0x6f, 0x1e, 0x36, 0x5d, 0x9f, 0x96, 0x28, 0x8a, + 0xe8, 0xce, 0xcf, 0xc7, 0x80, 0xd8, 0xd9, 0xb5, 0x19, 0x69, 0xd7, 0x7e, 0x83, 0x06, 0x2b, 0x25, 0x89, 0x76, 0x4e, + 0x09, 0xbb, 0x9d, 0x8f, 0x6c, 0xe9, 0x47, 0x29, 0x10, 0x73, 0xc7, 0x89, 0x44, 0xf6, 0x60, 0x23, 0x27, 0x70, 0x8b, + 0xf6, 0x8e, 0x0e, 0x40, 0xe5, 0x46, 0x41, 0x7e, 0x35, 0x47, 0x72, 0xc7, 0x77, 0xbd, 0xef, 0x06, 0xf5, 0xe0, 0xbb, + 0xde, 0x59, 0x4a, 0x72, 0x47, 0x78, 0xa6, 0xa6, 0x84, 0x88, 0xcf, 0xbe, 0x1b, 0xe4, 0x03, 0x3c, 0x4b, 0xb4, 0x48, + 0x8b, 0x84, 0x6a, 0x75, 0x8d, 0x9b, 0xf0, 0x22, 0x91, 0xdc, 0x43, 0xbb, 0xce, 0x23, 0x62, 0x01, 0xc8, 0x58, 0x7c, + 0x36, 0x6f, 0x28, 0xd4, 0xdd, 0xc4, 0x6c, 0xd1, 0x5d, 0x16, 0xfb, 0xfd, 0x6d, 0x9e, 0xd6, 0x3d, 0x1d, 0x1f, 0x83, + 0x2f, 0x48, 0x35, 0x01, 0x1e, 0xed, 0xaf, 0xcd, 0xf1, 0xea, 0xd5, 0xe6, 0x48, 0x59, 0xa8, 0x12, 0xf5, 0x5b, 0xac, + 0x66, 0x3d, 0x84, 0xe1, 0xce, 0x32, 0x63, 0x6d, 0x2f, 0x78, 0x25, 0x67, 0x55, 0x6c, 0x97, 0xe3, 0x2b, 0x96, 0xda, + 0x4a, 0xa2, 0x72, 0xb4, 0x1e, 0x6b, 0x53, 0x8c, 0xfc, 0x4a, 0x21, 0x51, 0x16, 0x1d, 0x5b, 0x0b, 0x05, 0xc4, 0x0b, + 0xd0, 0x97, 0xec, 0x4c, 0x03, 0xac, 0x37, 0x7a, 0x15, 0x11, 0x5a, 0x3e, 0x52, 0xe1, 0x4d, 0x6e, 0xaa, 0xcc, 0xca, + 0x66, 0xd1, 0xee, 0xa7, 0x8a, 0x57, 0x08, 0x56, 0x6f, 0xd4, 0x1e, 0x05, 0xa8, 0x3d, 0xb4, 0x50, 0x06, 0x90, 0xd2, + 0x34, 0x03, 0x40, 0x06, 0x00, 0x99, 0x2a, 0xe2, 0x33, 0x01, 0x2a, 0x6d, 0x75, 0xa3, 0xc0, 0x89, 0xf4, 0x1a, 0x68, + 0x16, 0x58, 0xe9, 0x23, 0x05, 0x19, 0x2c, 0xb6, 0x08, 0xc0, 0xca, 0x91, 0x33, 0x4c, 0x63, 0xc8, 0x36, 0x9a, 0xb8, + 0x24, 0xcd, 0xef, 0xc3, 0x2c, 0x95, 0x78, 0x12, 0x3f, 0xc8, 0x1a, 0x23, 0x00, 0x90, 0xbe, 0x4f, 0x2f, 0x8a, 0x2c, + 0x26, 0x1c, 0x38, 0xeb, 0xa9, 0x83, 0xa2, 0x26, 0xe7, 0x5a, 0xd3, 0xea, 0x59, 0x6d, 0xf2, 0x90, 0x05, 0x3a, 0x7b, + 0x30, 0x26, 0xb5, 0x7c, 0xcf, 0x23, 0xfb, 0x2b, 0xc7, 0x33, 0xc2, 0x77, 0xdd, 0xc1, 0xa9, 0xff, 0x6e, 0x6a, 0x60, + 0x62, 0x4a, 0x00, 0x36, 0x06, 0x47, 0x13, 0xe2, 0x77, 0x3a, 0x26, 0x53, 0x9b, 0x14, 0x81, 0xc0, 0x43, 0xf0, 0x0a, + 0x9e, 0x1b, 0x2e, 0xb7, 0xdc, 0xd8, 0x59, 0xe4, 0x69, 0x02, 0x70, 0xe2, 0x05, 0xdf, 0x02, 0x1c, 0xa7, 0x5e, 0x15, + 0xb2, 0x67, 0xcf, 0xc5, 0x74, 0x36, 0x0f, 0x1e, 0x12, 0xda, 0xbf, 0x98, 0xf0, 0x9b, 0xee, 0x2a, 0xb9, 0x32, 0xb5, + 0xee, 0x4d, 0x74, 0x95, 0xcb, 0x9d, 0x3e, 0xad, 0x38, 0x86, 0x39, 0x83, 0x55, 0x40, 0xce, 0xd9, 0x90, 0xbf, 0x38, + 0x07, 0xc0, 0x96, 0x95, 0xf0, 0x22, 0xfe, 0x22, 0x94, 0xd5, 0x02, 0xb8, 0x47, 0xce, 0x23, 0xf3, 0xcb, 0x57, 0xdb, + 0xa1, 0x9c, 0x53, 0x14, 0xc6, 0x72, 0x6a, 0x5a, 0x52, 0x9c, 0x0e, 0x3d, 0x05, 0x93, 0xa9, 0x2d, 0x7f, 0x6f, 0x13, + 0x97, 0xd9, 0x9b, 0x49, 0x38, 0x5f, 0x47, 0xb6, 0xad, 0x55, 0xf7, 0xd0, 0x0d, 0xc1, 0xa0, 0x8f, 0x11, 0xb4, 0x6c, + 0xae, 0xef, 0xd6, 0x83, 0x81, 0xc2, 0xf6, 0xad, 0xe9, 0xa6, 0x45, 0xa7, 0x38, 0xe0, 0xcc, 0x5a, 0xd7, 0xa8, 0x54, + 0x15, 0x87, 0x5e, 0xf2, 0x6e, 0x59, 0x95, 0x5d, 0x96, 0x5e, 0x08, 0x52, 0xa3, 0xae, 0x22, 0x44, 0x4a, 0xc5, 0x0e, + 0xef, 0xc9, 0xaf, 0x81, 0x89, 0x67, 0x56, 0x8e, 0xd2, 0x78, 0x0e, 0x30, 0x41, 0x0a, 0x7d, 0x53, 0x7e, 0x05, 0xb8, + 0xa1, 0x8b, 0x28, 0xcc, 0xde, 0xc6, 0x55, 0x50, 0x5b, 0x4d, 0xbf, 0x77, 0x70, 0x62, 0xcf, 0xeb, 0x7e, 0x3f, 0x25, + 0x1a, 0x3f, 0x0c, 0xbd, 0xc0, 0xbf, 0xc7, 0xd3, 0x7d, 0x13, 0xa4, 0xe6, 0x95, 0x07, 0x78, 0x45, 0x97, 0x5b, 0x9b, + 0x72, 0x45, 0xe3, 0x62, 0x5e, 0x23, 0x22, 0x7c, 0xea, 0x28, 0xb6, 0xdb, 0xfc, 0x38, 0xb5, 0x31, 0x18, 0x84, 0x70, + 0xdf, 0xca, 0xf8, 0x7d, 0xe2, 0xe5, 0xb3, 0x68, 0x0e, 0x8a, 0xd2, 0x4c, 0x93, 0x84, 0x14, 0xd2, 0x4b, 0x80, 0x3e, + 0x1a, 0x84, 0x5a, 0x5d, 0xf9, 0x47, 0xe2, 0xa5, 0x6a, 0x5a, 0x9b, 0xa7, 0x58, 0xa3, 0x40, 0xcc, 0xa2, 0x79, 0xc3, + 0x32, 0x3a, 0x24, 0xd5, 0xe5, 0xd2, 0x34, 0xe3, 0x0f, 0xab, 0x19, 0xaa, 0x15, 0x47, 0x4d, 0x50, 0xa3, 0x74, 0x03, + 0x17, 0xc0, 0xbf, 0xd3, 0x1d, 0x47, 0x35, 0x8a, 0x14, 0x0d, 0xf8, 0x04, 0x81, 0x61, 0xcd, 0xe6, 0x09, 0x6b, 0x4d, + 0x5d, 0x33, 0xfa, 0x7d, 0x19, 0x27, 0x64, 0x92, 0x90, 0x9c, 0x0f, 0x97, 0xeb, 0x47, 0x52, 0x5d, 0x00, 0xa9, 0x72, + 0xc5, 0x66, 0xbd, 0xde, 0x1c, 0x30, 0x7a, 0x61, 0xfd, 0xc2, 0xc6, 0x15, 0x9c, 0x5f, 0x12, 0xe6, 0xae, 0xfa, 0x11, + 0x66, 0x19, 0x54, 0x01, 0x69, 0x7e, 0x2c, 0x78, 0xf3, 0xdc, 0x05, 0xa2, 0x7e, 0x33, 0x52, 0x17, 0x94, 0x59, 0x3a, + 0xb7, 0x88, 0x40, 0xc0, 0x6b, 0x58, 0x3d, 0x81, 0x64, 0x5f, 0x3e, 0xf6, 0x69, 0x46, 0x81, 0xea, 0x08, 0x40, 0xd9, + 0xac, 0x1f, 0xc2, 0xfe, 0x01, 0xe1, 0x84, 0xfa, 0x9b, 0x37, 0x72, 0xd6, 0x90, 0x3c, 0x90, 0x6a, 0xc2, 0x63, 0x38, + 0x35, 0x16, 0xf8, 0xd2, 0xa2, 0x37, 0x15, 0xbc, 0x26, 0x38, 0xee, 0x05, 0x5a, 0xfb, 0x16, 0x70, 0x84, 0x08, 0x2e, + 0x43, 0x13, 0xa7, 0xbd, 0x5d, 0x2f, 0x40, 0x42, 0x73, 0x0b, 0xe7, 0xfa, 0xda, 0x05, 0x2d, 0x4e, 0x91, 0x93, 0x45, + 0x17, 0x18, 0xe8, 0x82, 0xcc, 0x1b, 0xff, 0xaa, 0x60, 0xe5, 0x02, 0x64, 0x2f, 0x15, 0x2b, 0x89, 0xd8, 0x76, 0xea, + 0x8f, 0x52, 0xd9, 0x6f, 0xcf, 0xac, 0x09, 0xfc, 0x2a, 0xb1, 0x5f, 0x22, 0x93, 0x6f, 0x7a, 0x6c, 0xf2, 0x95, 0xb1, + 0xd0, 0xa9, 0x65, 0x70, 0x4e, 0x8f, 0x0c, 0xce, 0xbd, 0x9d, 0x55, 0x9b, 0x10, 0x86, 0x82, 0x24, 0xd0, 0x74, 0xe9, + 0x61, 0xdd, 0xf4, 0xe7, 0x27, 0x2d, 0x7e, 0xad, 0xda, 0xb7, 0xee, 0xc7, 0x21, 0x76, 0xf1, 0xab, 0xc4, 0x33, 0xec, + 0xa3, 0x3e, 0x70, 0x80, 0xc9, 0x88, 0x89, 0xcb, 0x7e, 0x1f, 0x0a, 0x9b, 0x8d, 0xe7, 0xa3, 0xba, 0xf8, 0xb9, 0x78, + 0x00, 0x28, 0x87, 0x0a, 0xec, 0x72, 0x28, 0x43, 0x19, 0xb1, 0xa9, 0x2d, 0xf7, 0xfc, 0xfe, 0x2a, 0xcc, 0x41, 0xde, + 0xd1, 0x98, 0x38, 0x67, 0x20, 0x86, 0xc1, 0xd7, 0xbf, 0x7b, 0xb2, 0x4f, 0x9b, 0xef, 0xce, 0xe0, 0xbb, 0xa3, 0xb3, + 0x0f, 0xc8, 0x71, 0x73, 0xb6, 0x2e, 0x8b, 0xfb, 0x34, 0x16, 0x67, 0xdf, 0x41, 0xea, 0x77, 0x67, 0x45, 0x79, 0xf6, + 0x9d, 0xaa, 0xcc, 0x77, 0x67, 0xb4, 0xe0, 0x46, 0xbf, 0x5b, 0x13, 0xef, 0x9f, 0x95, 0xa6, 0x3d, 0x5b, 0x42, 0x38, + 0x96, 0x56, 0x3f, 0x82, 0x12, 0x51, 0x91, 0xa2, 0xca, 0x50, 0x56, 0x6b, 0xc7, 0x79, 0x9f, 0x68, 0x78, 0x6c, 0x9a, + 0x90, 0xb8, 0x5a, 0xc2, 0x3a, 0xd4, 0xb3, 0xd3, 0x26, 0xd9, 0x71, 0x1e, 0xa8, 0x03, 0x22, 0xe7, 0x2f, 0xf2, 0xd1, + 0x96, 0xbe, 0x06, 0xdf, 0x3a, 0x1c, 0xf2, 0xd1, 0xce, 0xfc, 0xf4, 0xc9, 0x5a, 0x29, 0x83, 0x8d, 0x14, 0xa3, 0x10, + 0x12, 0xc5, 0x6d, 0x7b, 0x0c, 0x80, 0xff, 0xfd, 0xc3, 0x81, 0x7e, 0xef, 0xe4, 0x6f, 0xb5, 0x5b, 0x5a, 0xf5, 0xfc, + 0xd0, 0x22, 0xcc, 0x78, 0x5d, 0x1b, 0x76, 0xb6, 0xbd, 0x04, 0x94, 0xde, 0x37, 0x0d, 0x6a, 0x8a, 0xe8, 0x27, 0xac, + 0x26, 0x56, 0x71, 0x58, 0x90, 0x12, 0x87, 0x18, 0x8e, 0xd1, 0x0e, 0x3d, 0x4e, 0x17, 0x35, 0x4f, 0xee, 0x3b, 0x64, + 0xdc, 0xfa, 0x3e, 0x20, 0xb9, 0x14, 0xce, 0x3f, 0x78, 0xa1, 0xc1, 0x44, 0x2f, 0xf2, 0xaa, 0xc8, 0xc4, 0x48, 0xd0, + 0x28, 0xbf, 0x25, 0x71, 0xe6, 0x0c, 0x6b, 0x71, 0xa6, 0x10, 0xc2, 0x42, 0x42, 0xe5, 0x2e, 0x4a, 0x4a, 0x0f, 0xce, + 0x9e, 0xec, 0xcb, 0xe6, 0x77, 0xc2, 0x84, 0x18, 0x2d, 0x80, 0x06, 0x67, 0xd7, 0x2e, 0xef, 0x21, 0x2c, 0x73, 0xef, + 0xf7, 0xb7, 0x77, 0x79, 0x01, 0x71, 0x99, 0x67, 0x52, 0xb1, 0x5a, 0x9e, 0x01, 0x4d, 0x9e, 0x88, 0xcf, 0xc2, 0x4a, + 0x4e, 0x83, 0xaa, 0xa3, 0x58, 0xbd, 0x8d, 0xe7, 0x1e, 0xf0, 0x7a, 0xbf, 0x4f, 0x80, 0xc0, 0xdd, 0x67, 0x6f, 0x94, + 0x5b, 0x2a, 0xe9, 0x91, 0xe7, 0x18, 0x22, 0x99, 0x00, 0xaf, 0x33, 0x04, 0x47, 0x0a, 0xab, 0xe7, 0x26, 0xc8, 0x3f, + 0xbe, 0x3e, 0xa1, 0xf8, 0xa2, 0x79, 0x14, 0x35, 0x2c, 0x64, 0x09, 0x1c, 0x0f, 0xc9, 0x2c, 0x9b, 0x23, 0x35, 0x79, + 0xda, 0x9e, 0x22, 0x1d, 0x9d, 0x58, 0xe2, 0xb7, 0x35, 0xa9, 0x5e, 0xa4, 0xc2, 0x2e, 0x69, 0x67, 0x2b, 0x73, 0x2f, + 0x84, 0xa1, 0x4a, 0xb8, 0xf7, 0xba, 0x9e, 0x85, 0x72, 0x53, 0xb4, 0x2a, 0x66, 0x0f, 0x53, 0x62, 0x86, 0x29, 0xd6, + 0x5f, 0xd8, 0xf0, 0x9b, 0xc4, 0x8b, 0xc1, 0x70, 0xbd, 0xe4, 0xe5, 0x6c, 0x63, 0x16, 0xc2, 0xe1, 0xb0, 0x99, 0x14, + 0xb3, 0x25, 0xc4, 0xb6, 0x2e, 0xe7, 0x87, 0x43, 0x57, 0xcb, 0xd6, 0xc2, 0x83, 0x87, 0xaa, 0x85, 0x9b, 0x86, 0xe5, + 0xf0, 0x33, 0x99, 0xc5, 0xd8, 0xbe, 0xc6, 0x67, 0xf6, 0xe7, 0x8b, 0xee, 0x59, 0x82, 0x8c, 0x1b, 0x6b, 0xe0, 0x1a, + 0x9b, 0xb5, 0x3b, 0x5c, 0x8d, 0x80, 0xe4, 0x71, 0x37, 0xfa, 0xbb, 0xb2, 0x93, 0x9c, 0x04, 0x09, 0xa3, 0x15, 0xc2, + 0xef, 0xbe, 0xf1, 0x27, 0x5a, 0xec, 0x41, 0xbb, 0x8d, 0x2d, 0x21, 0xaa, 0x69, 0xcf, 0xe5, 0x4a, 0xb1, 0x34, 0x6f, + 0xa5, 0x0d, 0x99, 0x0f, 0xeb, 0x73, 0xdf, 0xc8, 0x81, 0x82, 0x31, 0xe2, 0xa9, 0x75, 0x10, 0xcd, 0xe6, 0xc0, 0x7d, + 0x81, 0xe6, 0x11, 0x9e, 0x5a, 0x90, 0xa0, 0xcc, 0xda, 0xb0, 0x9f, 0x24, 0x27, 0xcb, 0xe3, 0xf0, 0x2d, 0xfc, 0xcb, + 0x67, 0xd8, 0x24, 0xa6, 0x28, 0x1e, 0x7f, 0xab, 0x14, 0xff, 0x1d, 0x5b, 0x10, 0xc1, 0xda, 0x8d, 0xa8, 0x0d, 0x7f, + 0xc3, 0xbf, 0x85, 0x7d, 0x84, 0xfd, 0x86, 0x26, 0x08, 0x03, 0x58, 0x7f, 0x26, 0x10, 0x17, 0x16, 0x82, 0x04, 0x7f, + 0xab, 0x24, 0xff, 0x9c, 0xf0, 0xd9, 0xa2, 0x04, 0xb2, 0x3a, 0x8c, 0xe2, 0x13, 0x8a, 0x89, 0x42, 0x18, 0x6e, 0x09, + 0xbd, 0xa3, 0xff, 0x46, 0x94, 0x64, 0x93, 0xdc, 0x8a, 0xf5, 0x40, 0x26, 0x49, 0x30, 0xc1, 0xca, 0x0b, 0xe5, 0x4b, + 0xf7, 0x42, 0xa9, 0xb5, 0x16, 0xb4, 0x7e, 0xf9, 0x93, 0xc4, 0x33, 0xa0, 0x7b, 0x20, 0x63, 0xd0, 0x6d, 0x44, 0x35, + 0xc9, 0x31, 0x7d, 0x94, 0xce, 0x33, 0x50, 0x01, 0x9d, 0xad, 0xb3, 0xb0, 0x5e, 0x16, 0xe5, 0xaa, 0x15, 0x1e, 0x2a, + 0x4b, 0x1f, 0xa9, 0xc7, 0x98, 0x17, 0xe6, 0xc9, 0x89, 0x7c, 0xf0, 0x08, 0xd0, 0xf0, 0x28, 0x4f, 0xab, 0x8e, 0xd2, + 0xfa, 0x81, 0x65, 0xc0, 0x08, 0x9c, 0x28, 0x03, 0x1e, 0x61, 0x19, 0x98, 0xa7, 0x5d, 0x86, 0x1a, 0xc4, 0x1a, 0x55, + 0x57, 0x6a, 0x83, 0x39, 0x51, 0x94, 0x7c, 0x8a, 0xa5, 0x15, 0xc6, 0xd0, 0xd4, 0x95, 0x47, 0xd6, 0x4b, 0x4e, 0xd8, + 0x93, 0xdd, 0x40, 0xba, 0x85, 0x8d, 0x02, 0x17, 0x74, 0x2d, 0x4b, 0x94, 0x8b, 0x6e, 0x19, 0x51, 0x26, 0x42, 0xea, + 0x67, 0x0f, 0x67, 0x5a, 0xed, 0x37, 0x76, 0xd2, 0xbe, 0x3d, 0x52, 0xf4, 0x82, 0x81, 0xf8, 0xb4, 0x47, 0x4a, 0x3d, + 0x6b, 0xe4, 0x32, 0xb0, 0xa5, 0x4b, 0x55, 0xcf, 0x7f, 0x83, 0xf2, 0x1d, 0xcc, 0x8c, 0xb3, 0xd9, 0xef, 0x7a, 0x73, + 0x7b, 0xb2, 0xaf, 0x9b, 0xdf, 0x59, 0xaf, 0x07, 0x5b, 0x83, 0x4c, 0x7c, 0xa9, 0xa8, 0xa7, 0xac, 0x42, 0xac, 0xc8, + 0xec, 0x7f, 0x0b, 0xef, 0x77, 0x78, 0x6b, 0x84, 0x66, 0x65, 0x3c, 0xcc, 0x47, 0x4f, 0xf6, 0xa2, 0xf9, 0xbd, 0xb3, + 0x6c, 0x2b, 0x57, 0x25, 0xb3, 0xfd, 0x7e, 0x94, 0x34, 0x67, 0x8f, 0xd7, 0x48, 0xea, 0x00, 0x1f, 0xaf, 0xcf, 0xf0, + 0x91, 0x4a, 0x28, 0xb5, 0xa0, 0xaa, 0x41, 0xeb, 0x63, 0xbf, 0xb7, 0x9e, 0xd3, 0xc7, 0x8f, 0xe5, 0x74, 0x4b, 0x8a, + 0x30, 0x7e, 0x60, 0x30, 0x65, 0x27, 0x4e, 0x5d, 0xf2, 0x66, 0x48, 0xef, 0xba, 0x55, 0x52, 0x97, 0x3d, 0x4a, 0x04, + 0xa1, 0x0e, 0xd6, 0x2f, 0xf6, 0x43, 0x98, 0xd9, 0xa2, 0x3f, 0x6c, 0x56, 0x73, 0x42, 0x41, 0x04, 0x88, 0x56, 0x79, + 0x1f, 0x38, 0x26, 0x09, 0xb3, 0xe6, 0x86, 0x74, 0xeb, 0xcd, 0x95, 0xf6, 0x4a, 0x0a, 0xe8, 0xe7, 0x20, 0x73, 0xfb, + 0xe8, 0x96, 0xab, 0x96, 0x79, 0x2e, 0x6d, 0x39, 0x60, 0xd1, 0x42, 0x74, 0x66, 0xe7, 0xd2, 0xe1, 0xe0, 0x3f, 0xa8, + 0x2b, 0x51, 0x45, 0x04, 0x1d, 0x45, 0x0b, 0x46, 0xab, 0x55, 0xbb, 0x9c, 0x6c, 0x2a, 0x64, 0x4b, 0x22, 0x9c, 0x28, + 0xd9, 0x2b, 0xa1, 0x3e, 0xca, 0xd5, 0x9e, 0x69, 0x88, 0x3f, 0x13, 0xb0, 0x69, 0x83, 0xbf, 0x05, 0xee, 0x65, 0x70, + 0x66, 0xda, 0xa7, 0x61, 0x04, 0x44, 0xe6, 0x10, 0xec, 0xe7, 0x77, 0x3d, 0xa8, 0xe0, 0x41, 0x47, 0xfa, 0xeb, 0x7a, + 0x56, 0xe0, 0x99, 0x7b, 0xe2, 0xf9, 0x9b, 0x13, 0xe9, 0x45, 0x0e, 0x0f, 0x34, 0xf7, 0x61, 0xc6, 0x5f, 0x96, 0x65, + 0xb8, 0x1b, 0x2d, 0xcb, 0x62, 0xe5, 0x45, 0x7a, 0x1f, 0xcf, 0xa4, 0x18, 0x48, 0x74, 0x98, 0x19, 0x5d, 0xc5, 0x3a, + 0xce, 0x61, 0xdc, 0xdb, 0x93, 0xb0, 0x42, 0xfb, 0x67, 0x89, 0xbd, 0x2e, 0x00, 0xc0, 0x21, 0x6b, 0xd0, 0x0a, 0xef, + 0x74, 0x7b, 0xbb, 0xc7, 0x25, 0x25, 0x8a, 0x1b, 0x35, 0x3f, 0xab, 0xa1, 0x65, 0x82, 0x5a, 0x66, 0xdd, 0xc9, 0x64, + 0x8a, 0x24, 0xf0, 0x6d, 0xd8, 0x1b, 0x56, 0xe4, 0xf3, 0x46, 0x6e, 0x0f, 0xef, 0xc2, 0x95, 0x88, 0xb5, 0x05, 0x9d, + 0x74, 0x64, 0x1c, 0xee, 0x85, 0xe6, 0x46, 0xba, 0x7f, 0x52, 0x25, 0x61, 0x29, 0x62, 0xb8, 0x05, 0xb2, 0xbd, 0xda, + 0x56, 0x82, 0x12, 0x48, 0x60, 0x3f, 0x94, 0x62, 0x99, 0x6e, 0x05, 0x80, 0x39, 0xf0, 0x3f, 0x25, 0x0c, 0xa1, 0xbb, + 0xf3, 0x10, 0xaf, 0x1a, 0x79, 0xdf, 0x20, 0x04, 0xfb, 0x6b, 0x90, 0xd3, 0x80, 0x41, 0xa4, 0x18, 0xc9, 0x82, 0x81, + 0x04, 0x20, 0xe7, 0x6b, 0x30, 0xc9, 0x4d, 0x73, 0xcf, 0x0f, 0x72, 0xdd, 0xc1, 0xb4, 0x0f, 0xba, 0x17, 0xd7, 0x9a, + 0xe5, 0xe0, 0x15, 0x13, 0xf1, 0xbf, 0xd7, 0x5e, 0xc9, 0x72, 0x96, 0xf9, 0x8d, 0xb9, 0xe8, 0x64, 0x70, 0xd5, 0x10, + 0x7e, 0x31, 0xcb, 0xe6, 0x3c, 0x9a, 0x65, 0x3a, 0xd4, 0xbf, 0x68, 0x8e, 0x4a, 0x01, 0x0c, 0x75, 0xbc, 0x00, 0x6b, + 0xbc, 0x2b, 0xdd, 0xb4, 0xe2, 0x91, 0xc6, 0x18, 0x05, 0x15, 0x3a, 0x08, 0xfd, 0xbd, 0x06, 0x78, 0x0d, 0x26, 0xb9, + 0x11, 0x2a, 0x1f, 0x5c, 0xd0, 0x0d, 0xdd, 0x72, 0xe5, 0x12, 0xd4, 0xa4, 0x6a, 0xf9, 0xe5, 0x08, 0xf5, 0xae, 0x96, + 0x5c, 0xaa, 0xcd, 0xa7, 0x46, 0x59, 0x23, 0xc8, 0xe4, 0x28, 0xfd, 0x3e, 0xe5, 0xc2, 0xad, 0x8c, 0xc9, 0xfa, 0x70, + 0xf0, 0x0a, 0x6e, 0x6a, 0xfc, 0x3a, 0x27, 0x16, 0x51, 0x7b, 0x48, 0x84, 0xad, 0xdd, 0x0a, 0xdd, 0x7b, 0xdc, 0x28, + 0xcd, 0xa3, 0x6c, 0x13, 0x8b, 0xca, 0xeb, 0x25, 0x60, 0x2d, 0xee, 0x01, 0x19, 0x2a, 0x2d, 0xfd, 0x8a, 0x15, 0x00, + 0x19, 0x20, 0x85, 0x8d, 0x1f, 0x90, 0xf6, 0xea, 0x83, 0x97, 0xfa, 0xfd, 0xbe, 0x31, 0xe5, 0xbf, 0x7f, 0xc8, 0x81, + 0x99, 0x50, 0x94, 0xf5, 0x0e, 0x26, 0x10, 0x5c, 0x3b, 0x49, 0x7b, 0x56, 0xf3, 0x17, 0xeb, 0xda, 0x03, 0x52, 0x2b, + 0xdf, 0x62, 0xae, 0x7a, 0x6d, 0x5f, 0x6c, 0xf6, 0x69, 0x75, 0x63, 0x34, 0x0e, 0x82, 0xa5, 0xd5, 0x5b, 0xad, 0x72, + 0xc8, 0x1b, 0x5e, 0x81, 0x48, 0x65, 0x5d, 0x5d, 0x2b, 0xe7, 0xea, 0x5a, 0x70, 0x24, 0x90, 0x2d, 0x79, 0x0e, 0xff, + 0x85, 0xdc, 0x2b, 0x0f, 0x87, 0xc2, 0xef, 0xf7, 0xd3, 0x19, 0x69, 0x65, 0x81, 0x32, 0x6d, 0x5d, 0x7b, 0xa1, 0x7f, + 0x38, 0xfc, 0x00, 0x5e, 0x23, 0xfe, 0xe1, 0x50, 0xf6, 0xfb, 0x1f, 0xcd, 0x4d, 0xe6, 0x7c, 0xac, 0x94, 0xb2, 0x97, + 0xa8, 0x74, 0x7f, 0x9b, 0xf0, 0xde, 0xff, 0x1e, 0xfd, 0xef, 0xd1, 0x65, 0x4f, 0x05, 0x80, 0x25, 0x7c, 0x86, 0x37, + 0x74, 0xa6, 0x2e, 0xe7, 0x4c, 0xba, 0xbb, 0x2b, 0x3f, 0xf4, 0x9e, 0xc6, 0x87, 0xef, 0xcd, 0x4d, 0x1b, 0x7f, 0xad, + 0x8e, 0x34, 0x09, 0x1d, 0x17, 0xfd, 0xc3, 0xe1, 0x53, 0xa2, 0xf5, 0x69, 0xa9, 0xd2, 0xa7, 0x29, 0xf0, 0x24, 0xc3, + 0x86, 0xeb, 0x16, 0xa6, 0xa3, 0xf9, 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, 0x5b, 0xe5, 0x0a, 0xde, 0xda, + 0xe3, 0xdd, 0x60, 0x44, 0xa9, 0x23, 0x7d, 0xd2, 0x86, 0xd0, 0x25, 0x95, 0xfc, 0x47, 0x91, 0xc7, 0x18, 0xb3, 0xf1, + 0x9a, 0xc8, 0x3e, 0x8b, 0xfc, 0x55, 0x01, 0x80, 0x45, 0x80, 0x80, 0x9c, 0xce, 0x1d, 0x49, 0xfc, 0xe7, 0xe4, 0xdb, + 0x3f, 0xa6, 0x4b, 0xfb, 0x50, 0x16, 0x77, 0xa5, 0xa8, 0xaa, 0xa3, 0xd2, 0x76, 0xb6, 0x5c, 0x0f, 0xf4, 0xa1, 0xfd, + 0xbe, 0xa4, 0x0f, 0x4d, 0x31, 0x14, 0x05, 0x6e, 0x8d, 0xbd, 0x69, 0xca, 0x15, 0x4d, 0xf5, 0xc8, 0x58, 0x3f, 0xbf, + 0xdf, 0xbd, 0x8d, 0xbd, 0xd4, 0x0f, 0x52, 0x10, 0x84, 0x35, 0x7e, 0x52, 0x8a, 0x24, 0x70, 0x3e, 0xc3, 0x54, 0xe2, + 0xd3, 0xa5, 0x54, 0xf9, 0xc3, 0x48, 0xf3, 0x61, 0x0a, 0x7a, 0xd9, 0x7f, 0x54, 0x30, 0xff, 0x75, 0x7b, 0xb0, 0x3e, + 0xad, 0xcb, 0x34, 0xaa, 0x88, 0x2a, 0x2f, 0x4c, 0xb5, 0x09, 0x44, 0xf0, 0x17, 0xc2, 0x22, 0xf9, 0xf5, 0xc9, 0x91, + 0xa0, 0x31, 0x93, 0xe5, 0xe3, 0x91, 0xfb, 0x85, 0x7d, 0xe5, 0x3a, 0x9e, 0xff, 0xb9, 0x99, 0xff, 0x03, 0x74, 0x86, + 0x2c, 0x5e, 0x70, 0xcb, 0x60, 0x81, 0xb3, 0x5f, 0xba, 0x7a, 0xc0, 0xdf, 0xcc, 0x13, 0x2f, 0x80, 0x83, 0xf9, 0x05, + 0xba, 0x2a, 0xa6, 0xb3, 0x62, 0x00, 0x04, 0xb6, 0x7e, 0x63, 0xcd, 0x89, 0x37, 0x16, 0xcf, 0x95, 0x5c, 0x10, 0xfa, + 0xba, 0x0a, 0xb3, 0x71, 0x55, 0x6c, 0x2a, 0x51, 0x6c, 0xea, 0x1e, 0xa9, 0x65, 0xf3, 0x69, 0x6d, 0x2b, 0x64, 0x7f, + 0x12, 0x2d, 0xda, 0x2e, 0x43, 0x35, 0x19, 0x65, 0xe9, 0x7a, 0x0a, 0xa4, 0x7a, 0x01, 0x9c, 0x45, 0xe6, 0x95, 0x2f, + 0xce, 0x1e, 0xb0, 0x45, 0xe3, 0x29, 0x30, 0xa2, 0xd2, 0x1f, 0x79, 0x63, 0x74, 0x7a, 0xa2, 0xdf, 0xcf, 0xa7, 0x14, + 0xf2, 0xf5, 0x13, 0x60, 0x72, 0xd5, 0x72, 0x01, 0xfa, 0x32, 0xd4, 0x41, 0x25, 0x4a, 0xad, 0x18, 0x46, 0x2c, 0xfc, + 0x24, 0x90, 0xbd, 0x99, 0x82, 0x9a, 0x55, 0x94, 0x84, 0x4a, 0x54, 0x4a, 0xb6, 0x26, 0xa8, 0xa5, 0xf7, 0x45, 0x51, + 0xef, 0x2b, 0x70, 0x94, 0x8c, 0xb4, 0x59, 0x4e, 0x99, 0x71, 0x51, 0xe6, 0xa2, 0x1f, 0xec, 0xdf, 0x95, 0xe7, 0x37, + 0x32, 0x9f, 0xe5, 0xbe, 0xa3, 0x73, 0xda, 0x8e, 0x0b, 0x94, 0xb9, 0xe5, 0xb4, 0xd5, 0x92, 0xc7, 0xe4, 0x3d, 0x0b, + 0xb6, 0xfd, 0x97, 0x09, 0xf2, 0x2a, 0xc2, 0x7c, 0x42, 0x95, 0xcd, 0x3f, 0x20, 0xcc, 0x16, 0x07, 0xf6, 0xd8, 0x85, + 0x89, 0x48, 0x6f, 0xc1, 0x92, 0x18, 0x66, 0xa5, 0x08, 0xe3, 0x1d, 0x78, 0xff, 0x6c, 0x2a, 0x31, 0x3a, 0x43, 0x27, + 0xf7, 0xb3, 0x87, 0xb4, 0x4e, 0xce, 0xde, 0xbe, 0x3e, 0xfb, 0xae, 0x37, 0x28, 0x46, 0x69, 0x3c, 0xe8, 0x7d, 0x77, + 0xb6, 0xda, 0x00, 0x44, 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, 0x74, 0x7b, 0x22, 0xed, 0xaa, 0x74, 0x05, 0x84, 0x1e, + 0x00, 0x27, 0x5d, 0xf9, 0xf3, 0x70, 0x10, 0x09, 0x84, 0x5a, 0x30, 0x27, 0xd3, 0x88, 0x6e, 0x48, 0xaf, 0xb0, 0xcf, + 0xc0, 0x2c, 0xa4, 0x34, 0x0f, 0x6e, 0xae, 0x16, 0x2d, 0x77, 0xc5, 0xca, 0x51, 0x58, 0xad, 0x45, 0x54, 0x23, 0xd5, + 0x31, 0x38, 0xef, 0x40, 0x04, 0x80, 0x62, 0x04, 0xcf, 0x78, 0xd4, 0xef, 0x47, 0x2a, 0x28, 0x27, 0xa1, 0x5f, 0x14, + 0xfa, 0xa5, 0x31, 0x28, 0x63, 0xfe, 0x2e, 0xd4, 0xc4, 0x00, 0xf5, 0x96, 0x87, 0x8a, 0x23, 0x00, 0x97, 0x73, 0xc4, + 0x8c, 0xf3, 0x1e, 0x77, 0xd1, 0x38, 0x15, 0xef, 0x84, 0xba, 0x0e, 0x96, 0x0a, 0x75, 0xde, 0xd4, 0x47, 0x7a, 0x4e, + 0x9a, 0x04, 0x0d, 0xe2, 0x06, 0x1e, 0xaf, 0x86, 0x80, 0x6a, 0x25, 0xa4, 0xde, 0x42, 0xa7, 0x54, 0x75, 0x08, 0xac, + 0x01, 0x2e, 0x51, 0xd8, 0x56, 0x98, 0x1c, 0xd1, 0xa6, 0x2c, 0x45, 0x7e, 0xc4, 0x06, 0xed, 0x92, 0x91, 0xa9, 0x83, + 0xcb, 0xe5, 0x72, 0x22, 0xea, 0x5f, 0xf3, 0x2d, 0x80, 0xf3, 0x42, 0x7e, 0x6b, 0x37, 0x5b, 0x26, 0xd9, 0xae, 0x2b, + 0xc3, 0x59, 0x52, 0x8a, 0x6a, 0x5d, 0xe4, 0x55, 0x7a, 0x2f, 0x7e, 0xd6, 0x0f, 0x5d, 0x02, 0x29, 0xf4, 0x23, 0xbd, + 0x6e, 0x37, 0x47, 0xaa, 0x71, 0x74, 0x39, 0xb6, 0xa7, 0xd2, 0x4e, 0xf6, 0xaa, 0xc5, 0x9b, 0x2d, 0x73, 0x25, 0x69, + 0x1c, 0x8b, 0xfc, 0x6d, 0x1e, 0xa7, 0x91, 0x95, 0x1c, 0xfe, 0x1f, 0xde, 0xbe, 0x85, 0xbb, 0x6d, 0x1b, 0x5b, 0xf7, + 0xaf, 0x58, 0xbc, 0xa9, 0x4a, 0x44, 0x90, 0x2c, 0x39, 0x49, 0x67, 0x4a, 0x19, 0xd6, 0x71, 0xf3, 0x68, 0xd3, 0x36, + 0x71, 0x1a, 0xa7, 0x9d, 0xce, 0xe8, 0xea, 0xb8, 0x34, 0x09, 0x5b, 0x6c, 0x68, 0x40, 0x25, 0x29, 0x3f, 0x22, 0xf1, + 0xbf, 0xdf, 0xb5, 0x37, 0x9e, 0xa4, 0x68, 0x27, 0x33, 0xf7, 0xdc, 0xbb, 0xb2, 0x56, 0x2c, 0x82, 0x20, 0xde, 0xd8, + 0xd8, 0xd8, 0x8f, 0x6f, 0xeb, 0x00, 0xd5, 0x2e, 0xf2, 0x95, 0x8b, 0x8d, 0xfc, 0x22, 0x2b, 0x31, 0x60, 0x70, 0xa3, + 0x51, 0xad, 0x50, 0x53, 0x26, 0xf0, 0x85, 0x7c, 0x8f, 0x11, 0xb7, 0x59, 0x99, 0x00, 0xc3, 0x8f, 0x89, 0xfa, 0x92, + 0x9e, 0x42, 0x94, 0x07, 0x15, 0x8f, 0xfb, 0x05, 0x47, 0xc4, 0x6b, 0xab, 0x32, 0x07, 0x26, 0x5b, 0xab, 0x20, 0x11, + 0xec, 0x2e, 0x9b, 0xeb, 0x45, 0xb4, 0x50, 0x77, 0xa1, 0x5e, 0xbc, 0xdd, 0xf6, 0x12, 0x45, 0x07, 0x9c, 0xfc, 0x34, + 0x78, 0x15, 0x67, 0x39, 0x4f, 0xf7, 0x2a, 0xb9, 0xa7, 0x36, 0xd4, 0x9e, 0x72, 0xe6, 0x80, 0x9d, 0xf7, 0x75, 0xb5, + 0xa7, 0xd7, 0xf4, 0x9e, 0x6e, 0xe7, 0x1e, 0x5c, 0x30, 0x70, 0xe7, 0x5e, 0x66, 0xd7, 0x5c, 0xec, 0x81, 0x32, 0xd0, + 0x1a, 0x0f, 0xd4, 0xa2, 0x1a, 0xa9, 0x89, 0xd1, 0x81, 0xab, 0x13, 0x7d, 0x30, 0x07, 0xf4, 0x7b, 0x88, 0x15, 0xde, + 0x7a, 0xbb, 0xd2, 0x07, 0x6d, 0x40, 0x7f, 0x5e, 0x9a, 0x3e, 0xe8, 0x68, 0xf1, 0x2a, 0x24, 0x70, 0x63, 0x48, 0x35, + 0x52, 0xab, 0x91, 0x55, 0xa0, 0x78, 0xc3, 0x5b, 0xbc, 0x3b, 0xd7, 0x92, 0x8d, 0xf7, 0x12, 0x81, 0xbd, 0x32, 0x51, + 0xc5, 0x99, 0x38, 0xf6, 0x52, 0x79, 0xad, 0x9d, 0x64, 0x84, 0xf1, 0x2d, 0x2b, 0xa9, 0xbf, 0x43, 0xcc, 0x2d, 0xd2, + 0x1c, 0x06, 0x2f, 0xc3, 0x8a, 0xcc, 0x78, 0xbf, 0x2f, 0x67, 0x32, 0x2a, 0x67, 0x62, 0xbf, 0x8c, 0x14, 0x42, 0xdb, + 0x7d, 0x22, 0xa0, 0x07, 0x25, 0x40, 0xbe, 0x00, 0xa8, 0x7a, 0x48, 0xf8, 0xf3, 0x90, 0xd4, 0xa7, 0x53, 0xe8, 0x53, + 0x68, 0xeb, 0x15, 0xaf, 0xa0, 0xaa, 0x6e, 0x8c, 0x6c, 0xa3, 0x82, 0x16, 0x8f, 0xe5, 0x59, 0x6d, 0x18, 0x9b, 0x53, + 0xeb, 0x5d, 0x6f, 0x36, 0x98, 0xb2, 0xb9, 0x50, 0xab, 0x30, 0x24, 0xd1, 0x4d, 0xe9, 0x85, 0x0f, 0xb1, 0x58, 0x59, + 0xad, 0xcd, 0x6f, 0x62, 0x7f, 0x64, 0x22, 0xc5, 0xfd, 0x6c, 0x89, 0x73, 0x17, 0x8f, 0xe7, 0x55, 0x5f, 0x6b, 0x69, + 0x91, 0x69, 0xf3, 0x9d, 0xbe, 0x0c, 0x69, 0x2a, 0x6a, 0x48, 0xa3, 0xce, 0x0c, 0xba, 0x6f, 0x97, 0x57, 0x54, 0x23, + 0x4c, 0x80, 0x57, 0x3a, 0x83, 0x6e, 0x34, 0x1e, 0x88, 0xa2, 0x1a, 0x15, 0x6b, 0x21, 0x10, 0x6d, 0x18, 0x72, 0xcc, + 0x2c, 0x21, 0xc9, 0x3e, 0xf1, 0xef, 0x54, 0x70, 0x85, 0x22, 0xbe, 0x31, 0x70, 0xde, 0x95, 0xf5, 0xec, 0xae, 0x23, + 0x3f, 0x27, 0x16, 0x56, 0xfb, 0x0f, 0xcd, 0xa3, 0xd6, 0x38, 0x0b, 0x68, 0x6b, 0x5a, 0xdd, 0x70, 0xb8, 0x47, 0x75, + 0x2c, 0x4a, 0x03, 0x48, 0xec, 0x91, 0xe5, 0xa2, 0x75, 0xcc, 0xa0, 0x01, 0xfd, 0x6d, 0x76, 0xb5, 0xbe, 0x42, 0xd4, + 0xb6, 0x12, 0x59, 0x27, 0xa9, 0xfc, 0x4b, 0xda, 0xa3, 0xae, 0xed, 0xa9, 0xfc, 0x6f, 0xdb, 0x54, 0x39, 0xb4, 0x40, + 0xf2, 0xd8, 0xcd, 0x59, 0xa0, 0x3a, 0x12, 0x44, 0x81, 0xda, 0x7a, 0xc1, 0xd4, 0x3b, 0x65, 0x8a, 0x0e, 0xe4, 0xe7, + 0xc2, 0x9c, 0x61, 0x5f, 0x70, 0xc4, 0x98, 0xa5, 0x12, 0x83, 0xa9, 0x8f, 0x31, 0xaa, 0x69, 0xad, 0x00, 0x5d, 0x3f, + 0xdd, 0xc0, 0x9f, 0xa8, 0xa8, 0xd1, 0x50, 0x6b, 0x24, 0x85, 0xa2, 0x89, 0x0a, 0x3a, 0x96, 0x16, 0x3a, 0x98, 0x42, + 0x27, 0x91, 0xb0, 0x04, 0x34, 0x4c, 0x88, 0x4e, 0x2a, 0xf0, 0xd6, 0x00, 0xce, 0x7c, 0x5c, 0x94, 0xeb, 0x42, 0x1b, + 0xcc, 0xfd, 0x10, 0x5f, 0xf3, 0xd7, 0x2f, 0x9c, 0x51, 0x7d, 0xcb, 0x5a, 0xdf, 0xd3, 0x82, 0xfc, 0x10, 0x72, 0x8a, + 0x0e, 0x4c, 0xec, 0x68, 0x83, 0xc6, 0x18, 0x65, 0xad, 0x43, 0x5d, 0x9c, 0xe8, 0xf8, 0x2b, 0xda, 0x04, 0xef, 0x01, + 0x4f, 0x11, 0x6d, 0x78, 0x28, 0x8c, 0x55, 0x35, 0x3e, 0x95, 0xac, 0xa5, 0x07, 0x2b, 0x78, 0xba, 0x4e, 0x78, 0x08, + 0x7a, 0x24, 0xc2, 0x8e, 0xc2, 0x62, 0x1e, 0x2f, 0xe0, 0x38, 0x29, 0x08, 0xa8, 0x1d, 0xf4, 0x15, 0x7c, 0xbe, 0x40, + 0xf7, 0x57, 0x89, 0x1e, 0x60, 0x68, 0x41, 0xdc, 0x0c, 0x7d, 0x3a, 0xba, 0x8a, 0x57, 0x0d, 0x15, 0x09, 0x9f, 0x17, + 0x60, 0x3b, 0xa4, 0xd4, 0x53, 0xa0, 0x85, 0x4a, 0x94, 0x7e, 0x18, 0xf8, 0x0e, 0x0d, 0x7c, 0xad, 0x75, 0x80, 0x86, + 0x7e, 0xc6, 0x34, 0xb5, 0xce, 0x50, 0xf9, 0xcc, 0xbb, 0x67, 0x46, 0xcb, 0x99, 0x05, 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, 0xe3, 0x50, 0x69, 0x73, 0x20, 0xbe, 0x11, 0x1a, 0xf7, 0x4f, + 0xc3, 0xd8, 0x6a, 0x8a, 0xad, 0xdd, 0xdb, 0x76, 0xfb, 0x7b, 0xe9, 0xa5, 0xd3, 0x9c, 0xf4, 0x18, 0xfb, 0xbd, 0x0c, + 0x8b, 0x91, 0xed, 0x08, 0x81, 0x25, 0xe7, 0x7d, 0xea, 0xbf, 0xa2, 0xe5, 0x3c, 0x01, 0xd3, 0x11, 0x1d, 0x21, 0x17, + 0x28, 0x3b, 0x46, 0x71, 0x07, 0x06, 0x57, 0xf4, 0xfb, 0x60, 0x95, 0x61, 0x2e, 0x24, 0x4b, 0x92, 0x32, 0x78, 0x9e, + 0x7a, 0x18, 0xf0, 0x6b, 0xa6, 0xcc, 0x5d, 0x94, 0xf5, 0xe9, 0x92, 0x4c, 0x53, 0x64, 0x20, 0xd6, 0xe1, 0x26, 0x4b, + 0xa3, 0x44, 0x89, 0xc8, 0x96, 0xe8, 0x1f, 0x69, 0x28, 0x96, 0x0e, 0xd7, 0x8b, 0x54, 0x89, 0x50, 0x31, 0x4f, 0xf1, + 0xa4, 0x4e, 0xeb, 0x74, 0x84, 0xf1, 0x26, 0x41, 0x29, 0x57, 0xc3, 0x40, 0x95, 0x54, 0x2f, 0x85, 0x4d, 0xb1, 0xdd, + 0xea, 0x8b, 0x95, 0x98, 0xc7, 0x0b, 0x7c, 0x29, 0x70, 0x14, 0x7f, 0xe2, 0x5e, 0xac, 0x29, 0xb5, 0x3d, 0xa8, 0x1d, + 0x51, 0x42, 0x7f, 0xe2, 0x70, 0x91, 0xf8, 0x4e, 0xea, 0xb8, 0x7f, 0x68, 0x11, 0x72, 0xa6, 0x0e, 0x52, 0xc3, 0x0d, + 0xed, 0x08, 0xff, 0x0d, 0xd7, 0x67, 0x9c, 0xd1, 0x9b, 0x6a, 0x46, 0x8d, 0xdf, 0xeb, 0xe1, 0x19, 0xa3, 0x3e, 0x1b, + 0x38, 0xac, 0x10, 0x85, 0x36, 0xec, 0xa8, 0x54, 0xa2, 0x85, 0xa1, 0x54, 0x7f, 0x09, 0x15, 0x47, 0xdc, 0x99, 0x51, + 0x96, 0x8c, 0x4f, 0xcb, 0x43, 0x31, 0x1d, 0x0c, 0x4a, 0x52, 0x19, 0x0b, 0x3d, 0xb8, 0x1e, 0x78, 0xfe, 0x3d, 0x70, + 0x0b, 0xf1, 0xe0, 0x90, 0xc5, 0x90, 0x1b, 0x70, 0xfc, 0x16, 0x27, 0x57, 0x8d, 0x4a, 0x15, 0xbc, 0x9a, 0xa8, 0x16, + 0xfc, 0x54, 0x86, 0x01, 0xfa, 0x24, 0x05, 0x60, 0x32, 0x98, 0xf2, 0x5b, 0x90, 0x28, 0x9d, 0xa9, 0x1b, 0xd2, 0xaf, + 0xa2, 0xe0, 0x17, 0xbc, 0xe0, 0x22, 0x71, 0x05, 0x58, 0xde, 0xc1, 0xf6, 0x3a, 0xaa, 0xa8, 0x02, 0xe2, 0x35, 0x3d, + 0x8e, 0xb8, 0xf1, 0xfe, 0x33, 0x3d, 0xb6, 0x40, 0xad, 0xd6, 0xb1, 0xc1, 0x67, 0x8e, 0xc1, 0x05, 0x5d, 0x4b, 0x6c, + 0x0d, 0xd5, 0xb0, 0x22, 0x30, 0x70, 0x01, 0x07, 0x61, 0x89, 0xe2, 0xd8, 0x4a, 0x5e, 0x91, 0x86, 0x94, 0xf6, 0x81, + 0xe1, 0x68, 0x93, 0x1c, 0xdf, 0x66, 0xd9, 0x4d, 0xe0, 0x7c, 0xd1, 0x39, 0x69, 0x26, 0x96, 0x0d, 0xde, 0xe7, 0xcd, + 0xf9, 0x75, 0xff, 0x90, 0x50, 0x15, 0xec, 0x86, 0xb7, 0x83, 0xdd, 0x38, 0xe1, 0xd7, 0x5c, 0x2c, 0x74, 0x7c, 0x16, + 0x73, 0xc9, 0xf2, 0x5b, 0xeb, 0xdd, 0x92, 0xa4, 0x56, 0x40, 0xfb, 0x2c, 0x0b, 0x6a, 0x22, 0x00, 0xdd, 0x0f, 0x7f, + 0x81, 0xd0, 0x19, 0xfe, 0xf6, 0x18, 0x5c, 0x91, 0xc2, 0x7b, 0x87, 0x40, 0x58, 0xd3, 0xcd, 0x9d, 0xda, 0x80, 0x2f, + 0xc6, 0xfd, 0x19, 0x53, 0x4f, 0xbf, 0xcd, 0xe4, 0xae, 0xae, 0xdb, 0x23, 0xcb, 0xf0, 0x11, 0xae, 0x14, 0x00, 0xcb, + 0x84, 0xbf, 0x18, 0x5b, 0x52, 0x7d, 0x02, 0x70, 0x6a, 0x3a, 0xa2, 0x4f, 0x10, 0x18, 0x38, 0x25, 0x5a, 0x8c, 0xae, + 0x95, 0x23, 0x9a, 0x41, 0x5a, 0xd3, 0xad, 0x30, 0xde, 0x7a, 0xd0, 0x42, 0xcf, 0x34, 0x9c, 0xf8, 0x0f, 0x9a, 0x79, + 0x55, 0x40, 0x00, 0xad, 0x8c, 0xe0, 0xad, 0xf5, 0xd1, 0x1c, 0x21, 0x3e, 0x61, 0x49, 0x34, 0x61, 0xf1, 0x4c, 0xf1, + 0x63, 0x42, 0x37, 0x4d, 0x6d, 0xd3, 0x07, 0xa4, 0xbf, 0xb8, 0x66, 0xfd, 0x94, 0x65, 0xed, 0xdb, 0x43, 0xc5, 0x8b, + 0x69, 0x33, 0xf8, 0x61, 0xa2, 0x8a, 0xf1, 0xbf, 0xa8, 0x7c, 0xa9, 0x15, 0xc0, 0x30, 0x77, 0xd5, 0xd3, 0xef, 0x37, + 0xb3, 0xe5, 0x40, 0xa8, 0xfc, 0xce, 0x20, 0xe9, 0xd3, 0xf1, 0xfc, 0xc0, 0x26, 0x51, 0x5b, 0xe8, 0xf9, 0xe3, 0x52, + 0x37, 0xa1, 0xf2, 0xda, 0xd4, 0x88, 0x56, 0xc8, 0x50, 0xd9, 0x3a, 0x60, 0x7d, 0xff, 0x10, 0xee, 0x2e, 0x6a, 0x1a, + 0x6a, 0xdd, 0x73, 0xd7, 0xa2, 0xe0, 0xc4, 0x1f, 0x60, 0x2c, 0x2e, 0x24, 0xb5, 0x0e, 0xc2, 0xa4, 0x1f, 0x2d, 0x4e, + 0x72, 0xa3, 0xae, 0x4e, 0xce, 0x14, 0xf3, 0x04, 0x2e, 0xaa, 0x65, 0xdb, 0x5f, 0x51, 0xa9, 0x4b, 0xb9, 0xbd, 0xa2, + 0x34, 0x3d, 0xa4, 0xed, 0x55, 0x9c, 0xb7, 0x05, 0x17, 0xfc, 0x0b, 0x05, 0x17, 0xd6, 0xc1, 0xba, 0xe3, 0x4e, 0xd9, + 0x13, 0x9e, 0x28, 0xd3, 0xda, 0xe0, 0xae, 0x1b, 0x8c, 0x89, 0xb1, 0xdf, 0x5d, 0xf2, 0xe4, 0x23, 0xb2, 0xe0, 0xdf, + 0x65, 0x02, 0x3c, 0x93, 0xdd, 0x2b, 0x95, 0xff, 0x07, 0xff, 0x6a, 0x6b, 0xdf, 0x59, 0xf3, 0x4f, 0xcf, 0x7a, 0xb8, + 0x73, 0x98, 0xfc, 0x00, 0x9d, 0x01, 0xdd, 0x5c, 0xc9, 0x94, 0x03, 0x32, 0x80, 0xb5, 0x48, 0x46, 0x03, 0x3e, 0xb4, + 0xb2, 0x6c, 0xfb, 0x4e, 0xab, 0x0b, 0xc2, 0xbd, 0x04, 0x6e, 0x7a, 0x7f, 0x6d, 0x66, 0xe6, 0x74, 0xad, 0x44, 0xd3, + 0xa5, 0xb1, 0xb5, 0x2c, 0x55, 0xc0, 0xee, 0xf7, 0x9e, 0x64, 0xd3, 0xfc, 0x70, 0x39, 0xcd, 0x2d, 0x75, 0xdb, 0xb8, + 0x65, 0x03, 0x40, 0x88, 0x5d, 0x6b, 0x2b, 0x07, 0x90, 0xdc, 0x1e, 0x84, 0xf0, 0xb5, 0x22, 0xf4, 0x54, 0x89, 0xd0, + 0xa7, 0x69, 0xb3, 0x0f, 0x76, 0x55, 0xad, 0x1b, 0x71, 0x8e, 0x06, 0xa9, 0x66, 0xe4, 0x4f, 0xae, 0x79, 0x71, 0x91, + 0xcb, 0x1b, 0xc0, 0x40, 0x26, 0xb5, 0x51, 0x58, 0x5e, 0x81, 0x3b, 0x3f, 0x3a, 0x8e, 0x33, 0x31, 0xca, 0x31, 0x58, + 0x2b, 0xc2, 0x23, 0xeb, 0xc4, 0x19, 0x80, 0x20, 0xfb, 0x93, 0xa6, 0xe3, 0xb9, 0x16, 0x18, 0xd3, 0x17, 0xb8, 0xab, + 0x9c, 0x1d, 0x6d, 0x72, 0xbb, 0xe8, 0x9b, 0x33, 0xac, 0x3b, 0x52, 0x5a, 0x1b, 0x8b, 0xae, 0x3b, 0x58, 0x6b, 0x06, + 0x6d, 0x11, 0x4a, 0x3e, 0xe4, 0x4e, 0xda, 0x4f, 0x01, 0x0d, 0xce, 0xb2, 0xf4, 0xd6, 0x5a, 0xe5, 0x6f, 0xb4, 0x10, + 0x27, 0x8a, 0xa9, 0x13, 0xdf, 0x44, 0x89, 0x3e, 0x3f, 0x13, 0xe3, 0x06, 0x02, 0xa9, 0x3f, 0x60, 0x50, 0x8d, 0x22, + 0x4c, 0xe0, 0x3a, 0x10, 0xc5, 0xf6, 0x44, 0x6d, 0x2c, 0x47, 0xd0, 0x09, 0x21, 0xde, 0x41, 0x19, 0xc6, 0xea, 0xe2, + 0x40, 0x1b, 0x2c, 0x7d, 0xdd, 0x5a, 0xe7, 0x86, 0x50, 0x18, 0x27, 0x30, 0xc5, 0x20, 0xa9, 0xb3, 0xce, 0x32, 0x41, + 0x95, 0x1d, 0x93, 0xce, 0xfb, 0x00, 0xdd, 0x5d, 0x8b, 0xa6, 0xf8, 0xba, 0x73, 0x07, 0xdd, 0xc7, 0xf5, 0x6b, 0x2d, + 0x72, 0x83, 0x3f, 0x6f, 0x89, 0xb0, 0x08, 0x9c, 0xb5, 0x26, 0x5f, 0x35, 0xc2, 0x81, 0x29, 0xc9, 0x34, 0xec, 0x25, + 0xca, 0xa6, 0x7b, 0xbb, 0xed, 0xf5, 0xee, 0x15, 0x71, 0xf5, 0x18, 0xab, 0xbc, 0x9b, 0xb9, 0xbd, 0x53, 0xad, 0xc5, + 0xee, 0x4d, 0xdb, 0x4f, 0xb1, 0xa3, 0xd6, 0xda, 0xed, 0x86, 0x13, 0x6a, 0xc8, 0xb7, 0xa2, 0x4a, 0xab, 0xd3, 0x8d, + 0x41, 0x3b, 0xc4, 0xb3, 0x16, 0x19, 0xdc, 0x28, 0x5f, 0x38, 0xa1, 0x93, 0x8a, 0xb3, 0xea, 0xd4, 0x05, 0x9b, 0x2b, + 0x5e, 0x2d, 0x65, 0x1a, 0x09, 0x8a, 0x36, 0xe7, 0x51, 0x49, 0x13, 0xb9, 0x16, 0x55, 0x24, 0x6b, 0xd4, 0x8b, 0x5a, + 0x8d, 0x01, 0x02, 0x32, 0x9d, 0x35, 0x3d, 0xa8, 0x82, 0xd9, 0x50, 0x46, 0x72, 0xfa, 0x1e, 0x2c, 0xed, 0x91, 0x63, + 0xad, 0xef, 0xab, 0xb3, 0xc5, 0xb7, 0x7a, 0x42, 0x30, 0x85, 0xd9, 0x03, 0x61, 0xe0, 0x9a, 0xc6, 0x90, 0xd3, 0x2e, + 0x71, 0x59, 0xd3, 0x2d, 0xe1, 0x1e, 0x6e, 0x57, 0xb2, 0x23, 0x37, 0x4f, 0x9a, 0x9b, 0x2b, 0xd8, 0x51, 0x31, 0x1f, + 0x83, 0xf6, 0x4b, 0xaa, 0x6b, 0x97, 0xe6, 0xd6, 0xe3, 0x41, 0x40, 0x83, 0x41, 0x61, 0xf8, 0xd7, 0x89, 0xf1, 0xf0, + 0xa4, 0x01, 0x41, 0x52, 0x2e, 0xc2, 0xb1, 0x6f, 0x44, 0x3f, 0x99, 0xca, 0x43, 0x8e, 0x16, 0xef, 0xd0, 0xea, 0x04, + 0xa2, 0x78, 0x89, 0x50, 0x12, 0xa3, 0x2a, 0x34, 0x22, 0x28, 0x4f, 0xcb, 0x5f, 0xaa, 0xea, 0x10, 0x50, 0x48, 0xfb, + 0x8a, 0x42, 0xd9, 0x26, 0x31, 0x34, 0xc3, 0x2f, 0xe7, 0x93, 0x85, 0x9e, 0x81, 0x81, 0x9c, 0x1f, 0x2c, 0xf4, 0x2c, + 0x0c, 0xe4, 0xfc, 0xc9, 0xa2, 0x76, 0xeb, 0x40, 0x13, 0x10, 0xcf, 0x85, 0xa3, 0x93, 0xd2, 0xaa, 0x6c, 0x01, 0xdd, + 0x3c, 0x44, 0xd0, 0x7f, 0xb2, 0x87, 0xa0, 0x93, 0x0b, 0xed, 0xc8, 0x0d, 0x68, 0x3b, 0x0e, 0x81, 0xbd, 0x62, 0x52, + 0x61, 0x02, 0x10, 0x1d, 0xb2, 0x31, 0x18, 0x62, 0xab, 0x0f, 0x0e, 0xd9, 0x78, 0xea, 0x93, 0x20, 0x60, 0x74, 0x7f, + 0x30, 0x90, 0xe0, 0xb7, 0x78, 0x95, 0x3e, 0xda, 0x08, 0x74, 0xd3, 0x77, 0x77, 0x43, 0xef, 0xe2, 0x0a, 0x4e, 0xd5, + 0xee, 0x9e, 0x84, 0x6e, 0x32, 0xed, 0x00, 0xbd, 0x86, 0xb8, 0x21, 0xbf, 0x32, 0x1a, 0x8d, 0x6c, 0x4a, 0x48, 0x88, + 0xe1, 0x1c, 0x9a, 0x39, 0x2d, 0x97, 0xaf, 0x6e, 0x3d, 0x1b, 0x90, 0x61, 0xa6, 0xb7, 0x4c, 0xd6, 0x0f, 0x50, 0x56, + 0x3d, 0x86, 0x76, 0xe8, 0x3d, 0x72, 0xfc, 0xf0, 0xe0, 0x9b, 0x8c, 0x9f, 0x39, 0x5c, 0x7b, 0x38, 0x17, 0xbe, 0xcb, + 0x9a, 0x91, 0x39, 0x74, 0x9e, 0x7d, 0x1c, 0xef, 0x61, 0x9c, 0x7c, 0x9e, 0x85, 0xf2, 0xc6, 0x6b, 0xfa, 0x1f, 0x95, + 0xde, 0xec, 0x70, 0xc8, 0xe9, 0x0a, 0x56, 0xdc, 0xac, 0x0a, 0x0d, 0x3f, 0x8b, 0xbc, 0x71, 0xc4, 0x6b, 0x12, 0x55, + 0xdd, 0xe7, 0xbd, 0x0d, 0x53, 0xda, 0x31, 0x0e, 0x00, 0x4e, 0xd4, 0xaa, 0x61, 0x57, 0x1a, 0xd7, 0xea, 0x20, 0x86, + 0xa1, 0x84, 0xad, 0x12, 0x47, 0x42, 0xf9, 0x1b, 0x80, 0xb0, 0x18, 0x8a, 0xe3, 0xad, 0x61, 0x7d, 0x80, 0xfd, 0xd0, + 0x05, 0x9a, 0xe6, 0x94, 0x6a, 0x06, 0x00, 0x49, 0xc0, 0x1f, 0x3d, 0xdd, 0x34, 0x54, 0xb6, 0x79, 0x1e, 0x5a, 0x56, + 0x57, 0xf0, 0x40, 0x4f, 0x5d, 0xc9, 0xc0, 0xb8, 0xaa, 0x63, 0x6f, 0x73, 0x7f, 0x7b, 0xb4, 0x8a, 0x7c, 0x67, 0x93, + 0xda, 0x66, 0x55, 0x68, 0xec, 0xe3, 0x09, 0x3d, 0x9d, 0x00, 0xad, 0xd7, 0x96, 0x8a, 0xf6, 0xfb, 0x28, 0x46, 0x8d, + 0x0b, 0x05, 0x56, 0x61, 0x22, 0xc1, 0x21, 0xc2, 0x08, 0xa1, 0xdf, 0x97, 0xe1, 0xc6, 0x17, 0x64, 0x10, 0x0d, 0xd7, + 0xa2, 0xe3, 0x0f, 0x39, 0x5e, 0xb4, 0x2d, 0x55, 0x35, 0x27, 0x4d, 0x5b, 0x02, 0x6f, 0xc2, 0x01, 0xb6, 0xf3, 0x4f, + 0x1b, 0x22, 0x57, 0xe1, 0xa2, 0x84, 0xef, 0x88, 0x6b, 0x41, 0x74, 0x53, 0x9b, 0x7a, 0x1b, 0x76, 0x88, 0x8e, 0xa6, + 0x78, 0x74, 0xc8, 0x3d, 0x77, 0xcf, 0x6d, 0x11, 0xdf, 0x7c, 0x86, 0xdc, 0x35, 0x9d, 0xbd, 0x14, 0x61, 0x50, 0xb7, + 0x6c, 0xa0, 0x58, 0x87, 0x4e, 0x50, 0x80, 0x51, 0x5b, 0x3e, 0x01, 0x1d, 0x1b, 0x0c, 0x2a, 0x82, 0x4f, 0x0a, 0xdb, + 0xa6, 0x41, 0xfe, 0x88, 0x77, 0x43, 0x87, 0xd7, 0x96, 0x3c, 0x10, 0xaf, 0xb0, 0xcf, 0x94, 0x70, 0xff, 0x82, 0x82, + 0xee, 0x28, 0x2f, 0x57, 0x85, 0xab, 0xd2, 0x00, 0x54, 0xd9, 0xf1, 0x5c, 0x6b, 0x4a, 0x5a, 0xc0, 0x4a, 0x49, 0xdd, + 0xf9, 0x4d, 0x44, 0xdc, 0x92, 0xa9, 0x98, 0xad, 0xba, 0x51, 0xe5, 0xa1, 0x44, 0x91, 0x8e, 0x3d, 0xdb, 0x39, 0x58, + 0x03, 0xe0, 0x29, 0x6c, 0x2f, 0xce, 0xb0, 0xa0, 0x8c, 0xcb, 0x96, 0xb9, 0x04, 0x8a, 0xfa, 0x61, 0x9c, 0x97, 0x1d, + 0x5f, 0xee, 0x8e, 0xb6, 0xf7, 0xd0, 0x1b, 0xb1, 0x31, 0x5e, 0x5f, 0x46, 0x4d, 0xbf, 0x78, 0x86, 0x2b, 0x4b, 0x41, + 0x1e, 0x68, 0xaa, 0x47, 0x18, 0x1d, 0x02, 0xd3, 0x94, 0x1f, 0xb1, 0xf1, 0x74, 0x38, 0x34, 0x64, 0xd0, 0x6b, 0x26, + 0xc6, 0xff, 0xfa, 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, 0x58, 0x12, 0xa3, 0x10, 0xbf, 0x38, + 0x55, 0xb6, 0x13, 0x42, 0x05, 0xc4, 0x43, 0xd7, 0xba, 0x71, 0x24, 0x55, 0xec, 0x49, 0xa1, 0xf1, 0xd4, 0x70, 0xdf, + 0x0b, 0x1d, 0xb3, 0x0e, 0xb3, 0xb8, 0xcd, 0x1a, 0x49, 0x8d, 0x71, 0x2a, 0x4c, 0x70, 0x4a, 0xb9, 0x8a, 0x04, 0x46, + 0xc7, 0xb3, 0x85, 0x41, 0x54, 0x49, 0x4c, 0x32, 0xb6, 0x16, 0xc2, 0xc4, 0xae, 0x73, 0x85, 0x69, 0xea, 0x22, 0xf5, + 0x9b, 0x81, 0xc9, 0x82, 0x86, 0xfc, 0x1e, 0x8d, 0xd6, 0x54, 0x4d, 0x01, 0x86, 0x71, 0x94, 0x6a, 0xfc, 0x5b, 0x84, + 0xda, 0x0c, 0x03, 0x00, 0xdb, 0xbc, 0x93, 0x99, 0xa8, 0x5e, 0x0b, 0x84, 0x40, 0x73, 0xf6, 0x53, 0x45, 0xb5, 0x33, + 0x0b, 0x46, 0xd1, 0x6e, 0xaf, 0x7c, 0x3e, 0x70, 0x42, 0x79, 0xac, 0x2e, 0x50, 0xaf, 0x64, 0xf1, 0x46, 0xa6, 0xbc, + 0x15, 0x17, 0x73, 0x4f, 0xb2, 0x0f, 0xf9, 0x08, 0xce, 0x2b, 0x74, 0x2a, 0x37, 0xdb, 0x44, 0x99, 0x25, 0x49, 0xc6, + 0x02, 0x63, 0xf3, 0x12, 0xcc, 0xa4, 0x66, 0xc6, 0xf0, 0x6b, 0x08, 0x2e, 0xb6, 0x73, 0x12, 0x6e, 0xee, 0xe7, 0x81, + 0x21, 0x34, 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, 0xe1, 0xce, 0x7f, 0x50, 0x58, + 0x83, 0xca, 0x88, 0xcb, 0x88, 0xf2, 0xcc, 0x81, 0x6e, 0x9a, 0x14, 0x71, 0x7a, 0xb6, 0x8a, 0x8b, 0x92, 0xa7, 0x50, + 0xa9, 0xa6, 0x6e, 0x51, 0x6f, 0x02, 0xf6, 0x86, 0x48, 0x92, 0xac, 0xa5, 0xb1, 0x15, 0xbb, 0x34, 0x48, 0xcf, 0xbd, + 0x61, 0x96, 0x5e, 0x55, 0x68, 0x48, 0x4b, 0xbd, 0xb3, 0x50, 0xc9, 0xfc, 0x15, 0xff, 0x19, 0xd4, 0x0a, 0x74, 0xb4, + 0x49, 0x31, 0x9e, 0x03, 0x23, 0xbe, 0x1b, 0xc1, 0xea, 0x01, 0xe2, 0xa2, 0x09, 0x4a, 0xbd, 0x23, 0x76, 0xfc, 0xdc, + 0xe4, 0xe1, 0x5d, 0xc8, 0x39, 0x83, 0x4f, 0x1f, 0x66, 0x89, 0x5a, 0xeb, 0x48, 0x8c, 0xd4, 0x0c, 0xa0, 0xe9, 0xa0, + 0xcc, 0x79, 0x2c, 0x82, 0x59, 0xcf, 0x24, 0x46, 0x3d, 0xae, 0x7f, 0x81, 0x86, 0xda, 0x6f, 0x56, 0x96, 0x67, 0xd5, + 0xdd, 0x97, 0x70, 0x60, 0x53, 0x5b, 0x41, 0x8f, 0xd7, 0x95, 0xbc, 0xbc, 0x54, 0xdd, 0xf6, 0x0b, 0x31, 0x72, 0xba, + 0xc6, 0xb5, 0x74, 0x5e, 0x2d, 0x58, 0xaf, 0x3b, 0xdd, 0x2c, 0xee, 0x66, 0x19, 0x0d, 0x84, 0xb5, 0x9d, 0x4f, 0x34, + 0x7f, 0xd6, 0x6c, 0xbb, 0x8f, 0xb7, 0x20, 0x66, 0x01, 0x00, 0xa4, 0x07, 0x51, 0xb0, 0xcc, 0x52, 0x1e, 0x50, 0x79, + 0x1f, 0x47, 0x59, 0x28, 0xbd, 0x9c, 0x65, 0xfc, 0xb4, 0x69, 0xac, 0x75, 0x56, 0x28, 0x43, 0x6b, 0xa3, 0x3b, 0x5d, + 0x65, 0x88, 0xed, 0x27, 0x71, 0xb6, 0x00, 0xf7, 0xc7, 0x0c, 0x85, 0x86, 0xce, 0x32, 0xd2, 0x44, 0xc3, 0x77, 0xdd, + 0x33, 0xc8, 0x28, 0x4e, 0xd6, 0x79, 0x25, 0xdd, 0xe8, 0xb3, 0x36, 0x12, 0xe6, 0x1e, 0xa2, 0x5f, 0xc5, 0xe0, 0x51, + 0xee, 0xf3, 0xda, 0xe8, 0x64, 0x5a, 0x46, 0xda, 0x9d, 0x9f, 0xd4, 0xcb, 0x2c, 0xd5, 0x3a, 0x6c, 0x9f, 0x61, 0x6f, + 0x8d, 0x49, 0x6f, 0x42, 0x6a, 0x18, 0x89, 0xcf, 0x67, 0xd4, 0x08, 0x01, 0x6d, 0x39, 0xfe, 0x0e, 0x9f, 0x61, 0x68, + 0x0a, 0x2c, 0x55, 0xdc, 0xc2, 0x6e, 0xf8, 0x9a, 0x4f, 0x56, 0x2d, 0x00, 0x11, 0xac, 0x7c, 0xbd, 0x8b, 0x57, 0x42, + 0x7d, 0xa6, 0xcd, 0x00, 0x90, 0x05, 0xa5, 0xdc, 0xf1, 0x53, 0x2a, 0x1d, 0x2c, 0x51, 0xb4, 0xbd, 0x9c, 0xbe, 0xd1, + 0xb1, 0xf1, 0x43, 0x7a, 0x2e, 0x60, 0xbb, 0x90, 0xdf, 0xba, 0x57, 0x2f, 0x51, 0x91, 0xda, 0x36, 0xeb, 0x01, 0xbe, + 0xdc, 0xa0, 0x49, 0x18, 0x41, 0x99, 0x32, 0x05, 0x30, 0xb8, 0xa9, 0x46, 0xc1, 0xa4, 0xd5, 0x48, 0xd8, 0x52, 0x4f, + 0xb2, 0xdc, 0xf4, 0xc1, 0xa9, 0xee, 0x11, 0xf4, 0x68, 0x87, 0x93, 0x96, 0xfd, 0x5a, 0xc1, 0xd1, 0xc9, 0xd5, 0x10, + 0x35, 0xf3, 0x5e, 0xdb, 0x91, 0x21, 0xe5, 0x32, 0x0c, 0x04, 0x53, 0x8e, 0x79, 0x7a, 0x6c, 0x3d, 0x23, 0xa2, 0x07, + 0xce, 0x3e, 0xd3, 0xad, 0xba, 0x92, 0x80, 0xe8, 0xf8, 0xcd, 0xd3, 0xd7, 0x57, 0xf1, 0xa5, 0x41, 0x51, 0x6a, 0x58, + 0xc4, 0x28, 0xd3, 0xbe, 0x4a, 0xc2, 0xe0, 0xfd, 0xfa, 0xfe, 0x67, 0x95, 0xa5, 0xf6, 0x7b, 0xb0, 0xb1, 0xa2, 0xaa, + 0x5f, 0x4b, 0x5e, 0x34, 0x05, 0x58, 0xf7, 0x59, 0xa2, 0x40, 0xee, 0xf7, 0x36, 0xcd, 0x7c, 0x13, 0x35, 0x6e, 0x36, + 0xac, 0x37, 0xae, 0xdb, 0xa5, 0xb6, 0x64, 0x47, 0x56, 0x22, 0x67, 0x16, 0x83, 0x19, 0x3f, 0x2a, 0x0c, 0x4a, 0xc3, + 0x06, 0x55, 0xa9, 0xf8, 0xbd, 0x11, 0xc1, 0xa9, 0x63, 0x55, 0x61, 0x4c, 0x03, 0x66, 0x5b, 0x51, 0x6b, 0x50, 0x07, + 0xa5, 0xb4, 0x35, 0x51, 0xd8, 0x7e, 0x67, 0x05, 0x35, 0xbf, 0xff, 0x69, 0x0c, 0xf9, 0x9a, 0x52, 0x50, 0x49, 0xc0, + 0xce, 0xa0, 0xd1, 0x53, 0x25, 0x0c, 0xa4, 0x20, 0x78, 0x02, 0x94, 0x2f, 0xa2, 0xc6, 0x6a, 0xb7, 0xaf, 0x4e, 0x8d, + 0xd1, 0x16, 0x10, 0x5a, 0x48, 0x8f, 0x2e, 0xfb, 0xb8, 0x8d, 0x75, 0x20, 0xf1, 0xe0, 0x04, 0xdb, 0xb9, 0xba, 0x46, + 0x23, 0xa1, 0xf9, 0x43, 0xa3, 0x01, 0xaf, 0x69, 0x05, 0x0a, 0xf5, 0x1c, 0x47, 0x43, 0x67, 0x87, 0x14, 0x44, 0x6c, + 0xd0, 0xc2, 0xbe, 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, 0x82, 0x61, 0x0b, 0xbf, + 0x39, 0x35, 0x05, 0x60, 0xc3, 0x63, 0x5d, 0x96, 0x6f, 0xd4, 0x44, 0x66, 0x71, 0x48, 0x22, 0x90, 0x6c, 0x37, 0x37, + 0xb7, 0x11, 0x6c, 0x7b, 0x0b, 0xb5, 0xa1, 0xfe, 0xf2, 0xb6, 0xfb, 0x3d, 0xc3, 0xcb, 0x3d, 0xb9, 0x77, 0xd3, 0x86, + 0xf2, 0x87, 0xfb, 0x57, 0xc9, 0xff, 0x55, 0x25, 0xf7, 0x5b, 0x65, 0xd6, 0x6d, 0xf1, 0x7e, 0xd7, 0x71, 0xcb, 0x31, + 0x1a, 0x04, 0xd6, 0x14, 0x18, 0x48, 0x4f, 0x1a, 0xd3, 0x44, 0x87, 0x54, 0x66, 0xcc, 0xe0, 0xd1, 0x05, 0x68, 0x0e, + 0xd3, 0x79, 0x1e, 0x03, 0x70, 0x80, 0x7f, 0xe4, 0x11, 0xea, 0x9f, 0xce, 0xf3, 0xe0, 0x2c, 0x18, 0x94, 0x83, 0x40, + 0x7f, 0xe2, 0x9a, 0x13, 0x2c, 0x40, 0xe7, 0x16, 0x33, 0x08, 0x36, 0x69, 0xcd, 0x1c, 0xe2, 0xc3, 0x64, 0x3a, 0x18, + 0xc4, 0x64, 0x03, 0x20, 0x7d, 0xf1, 0xc2, 0x3a, 0x07, 0x15, 0x7a, 0x41, 0xb6, 0xea, 0x2e, 0x9a, 0x15, 0x7b, 0xd5, + 0x4e, 0xf3, 0x7e, 0x3f, 0x9f, 0x97, 0x83, 0xa0, 0x51, 0x61, 0x61, 0xbc, 0xff, 0x68, 0xf3, 0x4b, 0xa3, 0x93, 0x26, + 0x18, 0xa6, 0xf6, 0x18, 0xd5, 0x2b, 0x9e, 0x66, 0xb4, 0x71, 0x3b, 0x56, 0xca, 0x17, 0x10, 0xc5, 0x03, 0x43, 0xd6, + 0xca, 0xbb, 0x73, 0xf0, 0xba, 0xdc, 0x78, 0x73, 0x44, 0x01, 0x76, 0x53, 0x18, 0x27, 0x35, 0x17, 0x5d, 0xd4, 0xc4, + 0x33, 0xd8, 0xe9, 0xea, 0xad, 0x44, 0xab, 0xf1, 0x5e, 0xbc, 0x6b, 0x36, 0xfe, 0x56, 0xee, 0xe9, 0x32, 0xf7, 0x2e, + 0x00, 0x71, 0x76, 0x2f, 0xae, 0xf6, 0xb0, 0xd4, 0xbd, 0x60, 0x60, 0x91, 0x43, 0xda, 0xd5, 0xea, 0xa1, 0x88, 0xd4, + 0x79, 0x0c, 0x06, 0x4c, 0xa6, 0x21, 0x35, 0x99, 0xf6, 0x0a, 0x05, 0x69, 0x63, 0xad, 0x05, 0xb4, 0xe1, 0xb0, 0xd8, + 0xb1, 0x1b, 0x76, 0xa7, 0x5b, 0x87, 0x42, 0x09, 0xa3, 0x57, 0xd7, 0xcd, 0x43, 0xad, 0xe1, 0x89, 0xa0, 0x07, 0xd5, + 0x68, 0x3f, 0x3d, 0x94, 0x27, 0xed, 0xb1, 0x00, 0x17, 0x3d, 0x7c, 0xf9, 0x52, 0xe0, 0x45, 0x7b, 0x07, 0x79, 0xce, + 0x7c, 0xaa, 0x7c, 0x10, 0x1b, 0x6e, 0x19, 0x3e, 0xb4, 0x8f, 0x6f, 0x05, 0x32, 0xa9, 0x3b, 0x9a, 0xda, 0xda, 0x1d, + 0x8d, 0x63, 0x02, 0xfd, 0xa6, 0x1c, 0xa5, 0x4c, 0x4c, 0x2d, 0x4b, 0x76, 0xd4, 0xcb, 0x95, 0x37, 0x54, 0xca, 0x8e, + 0x96, 0x6d, 0xce, 0x2f, 0x6d, 0x24, 0xf4, 0xfb, 0xda, 0x1d, 0x08, 0xdf, 0xa8, 0xf5, 0x86, 0xbc, 0x6c, 0x88, 0x58, + 0x0e, 0x31, 0x03, 0xc7, 0x0b, 0xa9, 0x5c, 0xbb, 0x8b, 0xa6, 0xaa, 0x6e, 0x67, 0x2b, 0x17, 0xb4, 0xc4, 0x5b, 0x29, + 0xb0, 0x8a, 0xd4, 0xe9, 0xf5, 0x54, 0xe2, 0x7d, 0x1f, 0xc5, 0xf6, 0x23, 0x60, 0x1b, 0x1b, 0x47, 0x63, 0xe3, 0x16, + 0xb1, 0xc1, 0x57, 0x51, 0x45, 0x0b, 0x0e, 0x10, 0xdc, 0x6d, 0x49, 0x2d, 0xcd, 0x1c, 0xe2, 0xbe, 0xe2, 0x01, 0xda, + 0x77, 0x71, 0xc4, 0xa9, 0x00, 0xdb, 0xba, 0xd6, 0x39, 0xab, 0xe5, 0x80, 0xcd, 0x44, 0xcf, 0x3f, 0xad, 0x1a, 0x89, + 0x18, 0x56, 0xd9, 0x48, 0x59, 0xa1, 0x3d, 0x28, 0x5d, 0xc2, 0xc5, 0x17, 0xe0, 0x65, 0xfb, 0x7e, 0x65, 0xf7, 0xd9, + 0x12, 0xfb, 0x87, 0x79, 0xd5, 0x04, 0x8f, 0xbc, 0xc6, 0xdb, 0x7b, 0x98, 0xf8, 0x52, 0x29, 0x84, 0x57, 0x29, 0x0d, + 0x25, 0x00, 0x83, 0x24, 0xa8, 0xe1, 0x4a, 0xdb, 0x66, 0x90, 0xca, 0x18, 0x76, 0xb7, 0x7a, 0xab, 0xff, 0xd3, 0x2a, + 0x5c, 0x54, 0xb2, 0x18, 0x93, 0x40, 0xe7, 0x54, 0xcb, 0x4d, 0x4c, 0xc1, 0xb3, 0x5d, 0x72, 0x04, 0x0a, 0x3b, 0x01, + 0xdc, 0x50, 0xc2, 0x7e, 0xc5, 0xdb, 0x50, 0xce, 0x5e, 0x59, 0xc9, 0x93, 0xdb, 0x97, 0x54, 0xd0, 0x84, 0x4c, 0x85, + 0xdd, 0xbf, 0xad, 0x0d, 0xfb, 0x22, 0x94, 0x23, 0x29, 0x70, 0x71, 0xd0, 0x39, 0x80, 0xfd, 0x41, 0x2e, 0x63, 0xf3, + 0x99, 0xf4, 0xfb, 0xea, 0xfd, 0xf3, 0x3c, 0x4b, 0x3e, 0xee, 0xbc, 0x37, 0x3c, 0xcd, 0x92, 0x01, 0x95, 0x88, 0xa9, + 0x75, 0x55, 0x0c, 0x97, 0xda, 0xc5, 0xb8, 0x41, 0x32, 0xe2, 0x7b, 0xa9, 0x43, 0x8c, 0x18, 0x5f, 0x64, 0x87, 0xa4, + 0xe4, 0x74, 0x59, 0x77, 0xf6, 0x5c, 0x8b, 0x66, 0xd0, 0x18, 0x6e, 0xc7, 0x7b, 0x49, 0xaf, 0x00, 0x15, 0x15, 0xba, + 0x67, 0x81, 0x6b, 0x78, 0x73, 0x49, 0x34, 0xb6, 0xf4, 0xb4, 0x25, 0x1a, 0xb8, 0x57, 0x26, 0x24, 0xd5, 0xc6, 0x01, + 0x16, 0xb1, 0xae, 0x3f, 0x86, 0x12, 0x80, 0x5a, 0x0d, 0xd2, 0x2b, 0x7d, 0x45, 0xa8, 0x4a, 0x42, 0x30, 0x3a, 0x91, + 0xf0, 0x32, 0xa0, 0x71, 0x66, 0x12, 0x2d, 0x6c, 0x70, 0x40, 0x5f, 0x54, 0x26, 0xd1, 0xd8, 0x90, 0x07, 0xb4, 0xb2, + 0x69, 0x00, 0x83, 0x0f, 0x92, 0x24, 0xfa, 0x7a, 0x69, 0x92, 0x40, 0x50, 0x82, 0xf2, 0x0d, 0xfa, 0x4b, 0xe9, 0xf9, + 0x58, 0xfe, 0xcb, 0x3b, 0x94, 0x7e, 0x08, 0x25, 0xc8, 0x14, 0x75, 0xc5, 0x34, 0x63, 0x47, 0x59, 0xb7, 0x31, 0x89, + 0xe7, 0x69, 0x77, 0x5b, 0x28, 0x97, 0x2e, 0xf0, 0x2b, 0xcb, 0x10, 0xc7, 0xfa, 0x79, 0xbc, 0x62, 0xc7, 0x21, 0xd7, + 0x78, 0xe9, 0xcf, 0xe3, 0x15, 0xce, 0x10, 0xad, 0x5a, 0x09, 0x44, 0xf9, 0xaf, 0xda, 0xc0, 0x21, 0xee, 0x13, 0x0c, + 0x72, 0x51, 0x79, 0x0f, 0x04, 0xf2, 0xb6, 0x82, 0x88, 0x34, 0xb3, 0xeb, 0x30, 0x22, 0xd5, 0x4e, 0x92, 0xf9, 0xf2, + 0x47, 0x99, 0x09, 0xef, 0x1b, 0x78, 0x6c, 0x36, 0xcb, 0xa6, 0x98, 0x2f, 0x54, 0x30, 0x07, 0xf7, 0x89, 0x8a, 0x4b, + 0x51, 0xf9, 0x4f, 0xd8, 0x05, 0x2f, 0xc6, 0x83, 0xd7, 0x6b, 0x04, 0xd8, 0xaf, 0xfc, 0x27, 0x6f, 0xcc, 0xde, 0x5a, + 0x37, 0xbe, 0xcc, 0x44, 0x7c, 0xe0, 0xa3, 0x5b, 0xca, 0x47, 0x77, 0x5e, 0xa6, 0x3f, 0x1b, 0x50, 0x22, 0xa3, 0xb2, + 0xe2, 0xab, 0x15, 0x4f, 0x67, 0xb7, 0x49, 0x94, 0x8d, 0x2a, 0x2e, 0x60, 0x7a, 0xc1, 0xf1, 0x2e, 0x59, 0x9f, 0x67, + 0xc9, 0x6b, 0x88, 0x3d, 0xb0, 0x92, 0x0a, 0x8b, 0x1f, 0x96, 0x99, 0x5a, 0xcc, 0x42, 0x56, 0x52, 0xf0, 0x60, 0x76, + 0x9d, 0x44, 0x6f, 0x97, 0x1e, 0x92, 0x9a, 0x99, 0xb2, 0x4d, 0xed, 0x08, 0xb5, 0xf1, 0x75, 0xa4, 0x1b, 0x6d, 0x01, + 0x00, 0xf7, 0x6c, 0x91, 0x46, 0x92, 0x89, 0xe1, 0xa4, 0x66, 0xdc, 0xa4, 0x17, 0x98, 0x1a, 0xd7, 0xac, 0xa2, 0x89, + 0xb3, 0x90, 0x01, 0xbd, 0x3f, 0xe0, 0xe5, 0xe0, 0x73, 0x06, 0xf7, 0x1f, 0xb4, 0x06, 0x2e, 0x0f, 0x8b, 0x7e, 0x5f, + 0x1e, 0x16, 0xdb, 0x6d, 0x79, 0x14, 0xf7, 0xfb, 0xf2, 0x28, 0x36, 0xfc, 0x83, 0x52, 0x6c, 0x1b, 0x73, 0x83, 0x84, + 0xe6, 0x12, 0xa2, 0x16, 0x8d, 0xe0, 0x0f, 0xcd, 0x72, 0x2e, 0xa2, 0xfc, 0x30, 0xe9, 0xf7, 0x7b, 0xcb, 0x99, 0x18, + 0xe4, 0xc3, 0x24, 0xca, 0x87, 0x89, 0xe7, 0x84, 0xf8, 0x9b, 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, 0x5d, 0x84, 0x25, + 0x96, 0x42, 0x97, 0xec, 0xcf, 0x25, 0xf0, 0x44, 0x39, 0xaf, 0x36, 0xc0, 0xc0, 0x46, 0x78, 0xe7, 0x30, 0xe1, 0x24, + 0xd6, 0x35, 0xa0, 0x9d, 0x6e, 0x6a, 0x7a, 0x41, 0x57, 0xf4, 0x12, 0xf9, 0xd9, 0x0b, 0x30, 0x58, 0x3a, 0x64, 0xf9, + 0x74, 0x30, 0xb8, 0x20, 0x2b, 0x56, 0xce, 0xc3, 0x78, 0x10, 0xae, 0x67, 0xf9, 0xf0, 0x22, 0xba, 0x20, 0xe4, 0xab, + 0x62, 0x41, 0x7b, 0xab, 0x51, 0xf9, 0x31, 0x83, 0xe0, 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, 0x86, 0xe8, + 0xb6, 0xc7, 0x49, 0x02, 0x8e, 0xc9, 0xae, 0xf8, 0x68, 0xac, 0x0a, 0xef, 0xfa, 0x8e, 0xd0, 0x5e, 0x2f, 0x71, 0x83, + 0xf4, 0x5d, 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, 0xde, 0xc0, 0x81, 0x3d, 0x08, 0xf3, 0x59, 0x3c, 0x7c, 0x13, 0xbd, + 0x21, 0xe4, 0x2b, 0x49, 0xaf, 0xd5, 0xa5, 0x0c, 0xc2, 0x20, 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, 0xdd, 0x11, 0xb0, 0xf0, 0x1a, 0x4f, 0xd7, 0x87, + 0x2c, 0x9e, 0x0e, 0x06, 0x6b, 0xa4, 0xea, 0x2a, 0xf7, 0x9a, 0x2c, 0xe8, 0x05, 0x4e, 0x04, 0x01, 0x86, 0x3e, 0x13, + 0x6b, 0x43, 0xc3, 0xdf, 0x30, 0xf8, 0xf8, 0x8e, 0x5d, 0x8c, 0xee, 0xe8, 0x2d, 0x7b, 0xb3, 0x1d, 0x4f, 0x81, 0x99, + 0x5a, 0xcd, 0xc2, 0xbb, 0xc3, 0xcb, 0xd9, 0x25, 0xbb, 0x8b, 0xee, 0x8e, 0xa0, 0xa1, 0x57, 0xec, 0x0e, 0x01, 0x97, + 0xd2, 0xc7, 0xcb, 0xc1, 0x1b, 0xb2, 0x3f, 0x18, 0xa4, 0x24, 0x0a, 0xaf, 0x43, 0xaf, 0x95, 0x6f, 0xe8, 0x1d, 0xa1, + 0x2b, 0x76, 0x8b, 0xa3, 0x71, 0xc9, 0xf0, 0x83, 0x73, 0x76, 0x57, 0x5f, 0x87, 0xde, 0x6e, 0x4e, 0x44, 0x27, 0x88, + 0x11, 0xfa, 0x1a, 0x38, 0x9a, 0xe5, 0xc2, 0x4c, 0xc0, 0x93, 0xb9, 0xc8, 0x68, 0x51, 0x68, 0x06, 0xe2, 0xac, 0x04, + 0xc4, 0x92, 0xa8, 0xfb, 0xcd, 0x46, 0x67, 0xb0, 0x9c, 0xfb, 0xfd, 0x5e, 0x65, 0xe8, 0x01, 0x22, 0x67, 0x76, 0xd2, + 0x83, 0x9e, 0x4f, 0x0f, 0xf0, 0x13, 0xbd, 0x6a, 0x10, 0x27, 0xf3, 0xbb, 0x65, 0xf4, 0x9b, 0x47, 0x1f, 0x7e, 0xe8, + 0xa6, 0x3c, 0x22, 0xff, 0xf7, 0x29, 0x4f, 0x99, 0x47, 0x6f, 0x2a, 0x0f, 0x04, 0xcf, 0x5b, 0x93, 0x4a, 0x23, 0x51, + 0x8d, 0xce, 0x56, 0x31, 0x68, 0x23, 0x51, 0xdb, 0xa0, 0x9f, 0xd0, 0xc2, 0x0a, 0x22, 0xe4, 0x1c, 0xbc, 0x00, 0x83, + 0x54, 0x08, 0x95, 0xa3, 0x16, 0x25, 0x1a, 0x82, 0xe4, 0xb2, 0xe4, 0x2a, 0x7c, 0x0e, 0xa1, 0xea, 0xf4, 0x71, 0x26, + 0xc2, 0x86, 0x1e, 0x87, 0x3e, 0x00, 0xfc, 0xaf, 0x3b, 0xe4, 0xa2, 0xe4, 0x97, 0x78, 0x36, 0xb7, 0x09, 0x46, 0xc1, + 0x12, 0xd1, 0x0c, 0x6d, 0x83, 0xd8, 0x8f, 0x25, 0xc1, 0x7a, 0x24, 0x8d, 0x47, 0xa5, 0x39, 0x22, 0xfc, 0x28, 0x3e, + 0x8a, 0x9e, 0xc6, 0x86, 0x44, 0x72, 0x24, 0x91, 0x7c, 0x00, 0x84, 0x93, 0xa0, 0xbf, 0xb8, 0x6b, 0xb2, 0x6b, 0x21, + 0x31, 0xe8, 0x4f, 0x4b, 0xa6, 0x65, 0xf7, 0xaa, 0xc7, 0xbe, 0x22, 0xc8, 0x1d, 0xd3, 0x7f, 0x79, 0x7d, 0xf8, 0xe7, + 0x12, 0x67, 0xd0, 0x7a, 0xbe, 0xa8, 0xce, 0xcc, 0xbc, 0xc1, 0x8d, 0xbc, 0x2e, 0x6b, 0xd7, 0xe5, 0x0b, 0xbe, 0xc7, + 0x6f, 0x2b, 0x2e, 0xd2, 0x72, 0xef, 0x97, 0xaa, 0x8d, 0xe7, 0x54, 0xae, 0x57, 0x2e, 0xce, 0x8a, 0x32, 0x4e, 0xf5, + 0xa4, 0x2e, 0xc6, 0x1a, 0xb6, 0xe1, 0xf7, 0x88, 0xba, 0x92, 0x96, 0xa3, 0xa7, 0x94, 0xab, 0x66, 0xca, 0xc5, 0x3a, + 0xcf, 0x7f, 0xde, 0x49, 0xc5, 0x29, 0x6e, 0xa6, 0x20, 0x55, 0x6a, 0xb9, 0x80, 0xea, 0x39, 0x6a, 0xb9, 0x5b, 0x9a, + 0x1d, 0xe0, 0xdc, 0x36, 0xd5, 0xc7, 0xca, 0xec, 0xc2, 0x4b, 0x6e, 0xdc, 0x9f, 0x4c, 0x19, 0x16, 0x8c, 0x42, 0x9b, + 0x55, 0x57, 0xda, 0xbe, 0xd0, 0x3a, 0x0d, 0xc3, 0x95, 0x1f, 0x2f, 0x20, 0x5d, 0xc0, 0x38, 0x5e, 0x94, 0x4c, 0x8c, + 0xdb, 0xa3, 0xb7, 0x82, 0xf8, 0x92, 0xad, 0x40, 0xc0, 0x5c, 0xc3, 0xdb, 0x75, 0x1d, 0x6d, 0xf7, 0xc4, 0x29, 0xa3, + 0x72, 0x15, 0x8b, 0xef, 0xe3, 0x95, 0x81, 0x4c, 0x56, 0xc7, 0x63, 0x63, 0x4c, 0xa7, 0x3f, 0x25, 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, 0x9e, 0x31, 0x57, 0x08, 0x56, 0xaa, 0xec, 0xf6, + 0x9d, 0x1a, 0x53, 0x31, 0x83, 0x29, 0xb6, 0x9d, 0xc5, 0xa4, 0x5b, 0xf9, 0xa7, 0x9d, 0xfb, 0x65, 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, 0x59, 0x49, 0xbe, 0x2b, 0x8d, 0xb9, 0xf4, + 0xa9, 0xd2, 0xc4, 0x70, 0xb2, 0x18, 0x71, 0x91, 0x2e, 0xea, 0xcc, 0xae, 0x85, 0xcf, 0x78, 0x19, 0xce, 0xf9, 0xc2, + 0xe8, 0xa6, 0x74, 0xe9, 0x05, 0x8b, 0x75, 0xa7, 0x37, 0x2b, 0x8d, 0x95, 0x12, 0x71, 0x6b, 0x96, 0x09, 0x94, 0xa5, + 0xac, 0x95, 0xf0, 0xa6, 0x68, 0xd9, 0x4a, 0x1a, 0x79, 0xcf, 0x1c, 0xdc, 0xc7, 0x7e, 0x40, 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, 0x26, 0x56, 0x0a, 0xd8, 0x0b, 0xbc, 0xbc, 0xe1, 0x99, 0xaa, 0x69, 0xd9, 0xa5, 0xe2, 0x00, 0xe3, 0xf3, + 0x32, 0x0c, 0xcb, 0xe1, 0x05, 0x58, 0x4b, 0xec, 0x87, 0xab, 0x39, 0x5f, 0xa8, 0xdf, 0x10, 0x70, 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, 0x9e, 0xaa, 0x99, 0x69, 0xc9, 0x7f, 0x12, 0xb5, 0xa1, 0x89, + 0xbe, 0xc1, 0x2a, 0xf2, 0x87, 0xc7, 0x47, 0x97, 0x40, 0xc6, 0xce, 0xae, 0x64, 0xe6, 0x43, 0xdf, 0x47, 0x06, 0xf7, + 0xdc, 0x94, 0x33, 0xae, 0x82, 0x44, 0x19, 0xb8, 0x7b, 0x35, 0x4b, 0xc6, 0x5a, 0x84, 0xef, 0x1e, 0x15, 0x45, 0x9f, + 0x49, 0xd3, 0x80, 0xee, 0x23, 0xc1, 0x1c, 0xe8, 0xbd, 0x42, 0x87, 0xcb, 0x6a, 0x9b, 0x09, 0xf8, 0x8b, 0x04, 0xf9, + 0xad, 0xd0, 0xab, 0x1a, 0x83, 0x2a, 0xda, 0x45, 0x2c, 0xfd, 0xfb, 0x88, 0x1f, 0x65, 0xf3, 0x2f, 0x73, 0x8f, 0x57, + 0x12, 0x06, 0x3f, 0xa4, 0x66, 0x93, 0xcc, 0xdb, 0x2b, 0xf6, 0x3d, 0x74, 0xd4, 0xa3, 0xd6, 0x78, 0x5f, 0xbd, 0xe0, + 0x14, 0x62, 0x94, 0x50, 0x74, 0x12, 0x0c, 0xe0, 0x76, 0x09, 0x29, 0xee, 0x06, 0xbb, 0x69, 0x5e, 0xf3, 0xa2, 0xe0, + 0x7c, 0x5d, 0x55, 0x81, 0x1f, 0xd0, 0x70, 0xbe, 0xd8, 0x0d, 0x61, 0x38, 0xa6, 0xad, 0x6b, 0x18, 0x84, 0x19, 0xc3, + 0x48, 0x08, 0x5e, 0xff, 0xa2, 0x27, 0x34, 0x89, 0x57, 0xdf, 0xf1, 0x4f, 0x19, 0x2f, 0x14, 0x91, 0x06, 0x11, 0x52, + 0x37, 0xf1, 0x8d, 0x4c, 0x93, 0x02, 0x0a, 0x01, 0x46, 0x01, 0x95, 0xd8, 0xd0, 0x54, 0xfc, 0xad, 0x16, 0x1f, 0xfc, + 0xd4, 0x74, 0x3c, 0x1a, 0xd7, 0xad, 0xce, 0xa8, 0xa0, 0x33, 0xd0, 0xa3, 0x56, 0xd4, 0xd3, 0xa0, 0x95, 0x60, 0x1a, + 0x69, 0xde, 0xba, 0x87, 0xc0, 0x2b, 0xd3, 0xe2, 0x9d, 0x07, 0x74, 0x73, 0xe6, 0x83, 0x27, 0x8f, 0xe9, 0x99, 0x43, + 0x4f, 0xae, 0xd8, 0x51, 0xd5, 0x43, 0xed, 0xbd, 0x19, 0xa1, 0xa0, 0xdf, 0xc7, 0x14, 0xe8, 0x46, 0x50, 0x7b, 0x57, + 0xf7, 0x1f, 0xcb, 0x5d, 0x0e, 0xdf, 0x71, 0x96, 0x1b, 0xc0, 0x52, 0x91, 0xb5, 0x02, 0x8f, 0x02, 0xd4, 0xa5, 0x32, + 0x84, 0x2d, 0xe6, 0x70, 0xa8, 0xec, 0x56, 0xad, 0x86, 0x92, 0x1c, 0x96, 0x23, 0x70, 0x08, 0x5d, 0x97, 0x83, 0x72, + 0xb4, 0xcc, 0xaa, 0xf7, 0xf8, 0x5b, 0xb3, 0x0e, 0x49, 0x76, 0x1f, 0xeb, 0xc0, 0x2d, 0xeb, 0x30, 0xfd, 0x68, 0x90, + 0x02, 0xd0, 0x64, 0x23, 0x70, 0x09, 0xc0, 0x7b, 0xfb, 0x8f, 0x08, 0xb5, 0x32, 0xbd, 0x97, 0xb1, 0x50, 0xdf, 0x37, + 0x92, 0xa0, 0x84, 0x66, 0x42, 0xe5, 0x58, 0x0a, 0xde, 0x79, 0xa4, 0x73, 0x52, 0x67, 0xe2, 0x3d, 0x88, 0xd3, 0xc2, + 0x07, 0xf6, 0x16, 0x04, 0xe7, 0x2c, 0xe8, 0x1d, 0xde, 0x66, 0xb5, 0xd4, 0x46, 0x0f, 0x14, 0xc0, 0xef, 0x06, 0x77, + 0x08, 0xf2, 0xd5, 0x18, 0xae, 0x95, 0xbc, 0x09, 0xf9, 0xb0, 0xa0, 0x07, 0x64, 0x60, 0x9f, 0xc5, 0x30, 0xa6, 0x07, + 0xe4, 0xd0, 0x3e, 0x4b, 0x37, 0x80, 0x03, 0xa9, 0x47, 0x95, 0x1e, 0x40, 0x83, 0x7e, 0xb7, 0x2d, 0xb2, 0x24, 0xeb, + 0xc7, 0xd2, 0x28, 0x62, 0xa0, 0x4a, 0x10, 0x51, 0x8b, 0x7f, 0x3e, 0x98, 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, 0xbd, 0xc9, 0xe0, 0xc0, 0xc8, 0xf0, + 0xa5, 0xb7, 0x7f, 0xe1, 0x6b, 0x2d, 0xdd, 0x13, 0x83, 0x92, 0x3c, 0x3e, 0x50, 0xf4, 0xef, 0x5e, 0x59, 0xf9, 0xd4, + 0x4e, 0xff, 0x76, 0x6b, 0xd6, 0xe7, 0xe1, 0x68, 0xb2, 0xdd, 0xf6, 0xb4, 0x81, 0x2b, 0xd5, 0x2a, 0x04, 0xec, 0x42, + 0x49, 0xf6, 0x0f, 0x20, 0x2a, 0x42, 0x33, 0xee, 0x66, 0xd9, 0x90, 0xc8, 0xf8, 0x71, 0x3a, 0xcb, 0x86, 0x60, 0x87, + 0x7b, 0x51, 0x89, 0xcb, 0x51, 0x6b, 0x83, 0xd3, 0xb3, 0x24, 0x84, 0x50, 0x0e, 0x58, 0xd9, 0xad, 0xfa, 0x73, 0xa7, + 0xcc, 0x84, 0xd4, 0x64, 0x75, 0x3b, 0xa5, 0x7b, 0x98, 0xe6, 0x7b, 0x66, 0x04, 0x07, 0xdc, 0xdb, 0x5f, 0xf5, 0xc7, + 0x30, 0xc9, 0x34, 0x39, 0x45, 0xf2, 0x8b, 0xf4, 0x14, 0x92, 0x76, 0xe8, 0xa9, 0x22, 0x80, 0x13, 0x6a, 0x3f, 0x86, + 0xdf, 0x30, 0xee, 0xdf, 0x35, 0x5f, 0xbb, 0xa9, 0x88, 0x9e, 0x52, 0x2c, 0x53, 0x93, 0xd3, 0x24, 0x2b, 0x12, 0x88, + 0xda, 0xa8, 0x9a, 0x11, 0x3d, 0x71, 0x31, 0x1f, 0x15, 0xe1, 0xf3, 0x6a, 0xfd, 0x9f, 0x21, 0x7c, 0x46, 0xe1, 0x06, + 0x70, 0x79, 0xc5, 0xe5, 0x79, 0xf8, 0xec, 0x29, 0xdd, 0x9b, 0x7c, 0x73, 0x40, 0xf7, 0x0e, 0x9e, 0x3c, 0x23, 0x00, + 0x8b, 0x76, 0x79, 0x1e, 0x1e, 0x3c, 0x7b, 0x46, 0xf7, 0xbe, 0xfd, 0x96, 0xee, 0x4d, 0x9e, 0x1c, 0x34, 0xd2, 0x26, + 0xcf, 0xbe, 0xa5, 0x7b, 0xdf, 0x3c, 0x6d, 0xa4, 0x1d, 0x8c, 0x9f, 0xd1, 0xbd, 0xbf, 0x7f, 0x63, 0xd2, 0xfe, 0x06, + 0xd9, 0xbe, 0x3d, 0xc0, 0xff, 0x4c, 0xda, 0xe4, 0xd9, 0x13, 0xba, 0x37, 0x19, 0x43, 0x25, 0xcf, 0x5c, 0x25, 0xe3, + 0x09, 0x7c, 0xfc, 0x04, 0xfe, 0xfb, 0x1b, 0x09, 0x16, 0xb4, 0x92, 0x2c, 0x17, 0xa8, 0x3f, 0x43, 0x11, 0x27, 0xaa, + 0x26, 0x12, 0x1e, 0x62, 0x66, 0xf5, 0x4d, 0x1c, 0x06, 0xc4, 0xa5, 0x43, 0x41, 0x74, 0x6f, 0x3c, 0x7a, 0x46, 0x02, + 0x1f, 0x9e, 0xee, 0xc6, 0x07, 0x19, 0xcb, 0xc5, 0x3c, 0xfb, 0x2a, 0x37, 0xb1, 0x15, 0x3c, 0x00, 0xab, 0x8f, 0x7e, + 0xae, 0x4a, 0xce, 0xb3, 0xaf, 0x2a, 0xb9, 0x9b, 0xeb, 0xf7, 0x16, 0xa0, 0xbc, 0xbf, 0x6a, 0xd9, 0x4d, 0xa1, 0x42, + 0xa7, 0xb5, 0x46, 0x9f, 0x7d, 0xc4, 0xf4, 0xc1, 0xc0, 0xbb, 0x61, 0xff, 0xb4, 0x53, 0x4e, 0xeb, 0x1b, 0x8d, 0x42, + 0x8d, 0xca, 0x43, 0xc2, 0x8e, 0xa0, 0xe8, 0xc1, 0x00, 0x78, 0x02, 0x0f, 0xf7, 0xed, 0xdf, 0x2c, 0xe3, 0x63, 0x47, + 0x19, 0xbf, 0xa0, 0x0c, 0x01, 0x8d, 0x7a, 0x98, 0xdd, 0xf4, 0xb0, 0xd1, 0xad, 0x5e, 0xb2, 0x54, 0x27, 0x53, 0xd3, + 0x33, 0xd8, 0xd7, 0xba, 0x96, 0x7b, 0x46, 0x14, 0x2d, 0x2f, 0xf6, 0x52, 0x3e, 0xab, 0xd8, 0x4f, 0x4b, 0x54, 0x6f, + 0x45, 0x8d, 0x37, 0x32, 0x9b, 0x55, 0xec, 0x7b, 0xf3, 0x06, 0xb8, 0x19, 0xf6, 0xbb, 0x7a, 0xf2, 0x03, 0x67, 0x70, + 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, 0x5c, 0xd9, 0xff, 0x6a, 0xc8, 0x4b, 0x50, 0xb8, 0xd5, 0x2c, 0x6f, + 0xa7, 0x30, 0x84, 0x10, 0xfc, 0x71, 0xc9, 0x00, 0x70, 0x20, 0xc0, 0x60, 0xac, 0x65, 0x40, 0xcd, 0x96, 0x8f, 0x36, + 0x5c, 0xa9, 0x27, 0x81, 0x33, 0xb8, 0x90, 0x45, 0xc2, 0x4f, 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, 0xb0, 0x05, 0x91, 0x21, + 0x78, 0xb8, 0xfd, 0x6b, 0xa9, 0x02, 0x47, 0xf5, 0xfb, 0x5c, 0xfa, 0x6e, 0x4f, 0xc6, 0x8e, 0x1c, 0xa7, 0x7e, 0x2a, + 0x1c, 0xfc, 0x37, 0xa9, 0x6b, 0x63, 0xb9, 0x92, 0x32, 0xcb, 0xb2, 0xb0, 0xa3, 0x50, 0xcb, 0x3d, 0x2a, 0x0f, 0x92, + 0x2f, 0xe4, 0x10, 0xc9, 0x02, 0xa3, 0x50, 0x90, 0xe1, 0x84, 0x8a, 0xd1, 0x5a, 0x94, 0xcb, 0xec, 0xa2, 0x0a, 0x37, + 0x4a, 0xa1, 0xcc, 0x29, 0xfa, 0x76, 0x83, 0x03, 0x09, 0x89, 0xb2, 0xf2, 0x6d, 0xfc, 0x36, 0x44, 0xb0, 0x3a, 0xae, + 0x6d, 0xa1, 0xb8, 0xb7, 0x3f, 0x79, 0xda, 0xc5, 0x1f, 0x19, 0x17, 0x50, 0x17, 0x8b, 0x69, 0x38, 0xb1, 0xb1, 0x6f, + 0xdc, 0x17, 0x56, 0xd3, 0x03, 0x50, 0xdf, 0xa5, 0x12, 0x23, 0xa8, 0xaf, 0x8c, 0x7d, 0x6c, 0x8f, 0x31, 0x39, 0x83, + 0x58, 0xc3, 0x2a, 0x67, 0xa6, 0xfa, 0x46, 0xd8, 0x11, 0x00, 0x37, 0x42, 0x6b, 0x14, 0x04, 0x1e, 0xaf, 0x42, 0x3c, + 0x2f, 0x55, 0xf8, 0xd6, 0x8c, 0xd0, 0x31, 0x78, 0x53, 0xd9, 0x46, 0x66, 0xd2, 0x17, 0x0c, 0x9a, 0x63, 0x5b, 0x47, + 0x61, 0xb5, 0x95, 0x65, 0x47, 0x00, 0x37, 0x90, 0x1d, 0x9a, 0x8b, 0xe7, 0xac, 0x9a, 0x67, 0x8b, 0xc8, 0x04, 0x05, + 0x5c, 0x0a, 0xcb, 0xa0, 0x7d, 0xba, 0x47, 0xb6, 0xe3, 0x10, 0xba, 0xe1, 0x3e, 0x82, 0xf1, 0xb4, 0x9b, 0x82, 0x15, + 0x44, 0x23, 0xc4, 0xc3, 0x8c, 0x59, 0x7c, 0xaf, 0x34, 0xe5, 0xa9, 0x6a, 0x09, 0x04, 0x8e, 0x42, 0xa8, 0x8b, 0x5d, + 0xa3, 0x04, 0x97, 0xa9, 0x11, 0xcc, 0x60, 0xc7, 0x8e, 0xd4, 0x76, 0xc9, 0x39, 0x1d, 0xaa, 0x29, 0x2d, 0xf5, 0x94, + 0x6a, 0x5f, 0x43, 0x31, 0x2f, 0xd1, 0x43, 0x0f, 0x5c, 0x0f, 0xb4, 0x43, 0x5e, 0x49, 0x27, 0x26, 0x82, 0x4e, 0xab, + 0x4d, 0xd8, 0xb9, 0x91, 0x6e, 0x59, 0x8d, 0xbc, 0x63, 0x68, 0x76, 0xc4, 0x4b, 0x3f, 0x50, 0x17, 0x40, 0x84, 0xdc, + 0xdb, 0x22, 0x73, 0x44, 0xb3, 0xac, 0x7c, 0x05, 0x65, 0x71, 0xc4, 0xd6, 0x15, 0x70, 0x2d, 0x05, 0x93, 0x4b, 0x1e, + 0xf1, 0x14, 0x11, 0x01, 0x8f, 0x95, 0x76, 0x7d, 0xa7, 0x25, 0x84, 0x66, 0x29, 0x10, 0x37, 0x17, 0xc5, 0xb9, 0xb6, + 0x81, 0x2c, 0x80, 0xbe, 0xfd, 0x9c, 0x5d, 0x79, 0xe1, 0x60, 0x37, 0x57, 0x99, 0x78, 0xc1, 0x2f, 0x32, 0xc1, 0x53, + 0x04, 0xbb, 0xba, 0x35, 0x0f, 0xdc, 0xb1, 0x6d, 0x60, 0xf9, 0xf6, 0x1d, 0x2c, 0x98, 0x32, 0xd4, 0x4a, 0x89, 0x4c, + 0x44, 0x02, 0x32, 0xfb, 0xcc, 0xdd, 0x9b, 0x4c, 0xbc, 0x89, 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, 0x0e, 0xbf, 0xc4, 0x50, 0x2b, 0xe3, 0x7e, 0x1f, 0x24, 0x66, 0xd2, 0x36, 0x65, 0x26, 0x23, 0xa9, 0xd1, 0x42, + 0x2a, 0xca, 0x07, 0x13, 0xb2, 0xbb, 0x52, 0x2d, 0x23, 0x6a, 0xbf, 0x0a, 0xc5, 0x6c, 0x1c, 0x4d, 0x08, 0x9d, 0x74, + 0xac, 0x77, 0xd3, 0x5a, 0xc8, 0x34, 0x7a, 0x16, 0x79, 0x3e, 0x9d, 0x05, 0xab, 0xa6, 0xc5, 0x21, 0xe3, 0xd3, 0x62, + 0x30, 0x20, 0xda, 0xa5, 0x70, 0x83, 0xf5, 0x80, 0x29, 0x8d, 0x8b, 0xb7, 0x66, 0x5a, 0xfd, 0x4a, 0xaa, 0x90, 0xf4, + 0x9e, 0x01, 0x49, 0x26, 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, 0xde, 0xc6, 0x6f, 0x23, 0x7b, 0x59, 0xd0, 0x45, 0xbe, 0x40, 0x21, 0x6b, 0x1e, 0x86, 0xd5, 0xb0, 0x3d, + 0x88, 0x64, 0xbf, 0x3d, 0x09, 0x8d, 0xc6, 0xc0, 0x02, 0xd9, 0xa1, 0x11, 0xb8, 0x08, 0xad, 0xfc, 0xed, 0x10, 0x5c, + 0xb8, 0x2c, 0x22, 0xcb, 0x50, 0xc7, 0x6f, 0x6a, 0x37, 0x41, 0xf5, 0x0a, 0x9d, 0xa6, 0xb0, 0x2a, 0x65, 0x92, 0x0f, + 0xbf, 0x5e, 0xc9, 0x02, 0x33, 0x79, 0x5d, 0xf6, 0xe8, 0x6b, 0xbb, 0xbd, 0x03, 0x53, 0xb0, 0xee, 0x93, 0xf7, 0xf5, + 0xe3, 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, 0xa3, 0x4c, + 0xd6, 0xfe, 0xd5, 0x5d, 0xa4, 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, 0x86, 0x85, 0x57, 0xc3, + 0x4b, 0xb2, 0x1f, 0xa6, 0x83, 0x89, 0x12, 0x8c, 0xdd, 0xb1, 0x65, 0x19, 0xaa, 0xc4, 0xd5, 0xfe, 0x05, 0x79, 0x7c, + 0x41, 0x6f, 0xe9, 0x0d, 0x3d, 0xa5, 0x27, 0x40, 0xf8, 0xef, 0x0e, 0x27, 0x7c, 0x38, 0x79, 0xda, 0xef, 0xf7, 0xce, + 0xfb, 0xfd, 0xde, 0x99, 0x31, 0xa0, 0xd0, 0xbb, 0xe8, 0xb2, 0xa6, 0xfa, 0xd7, 0x55, 0xbd, 0x98, 0x9e, 0xa8, 0x8d, + 0x9b, 0xf0, 0x2c, 0x0f, 0xaf, 0xf6, 0xef, 0xc8, 0x10, 0x1f, 0x2f, 0x72, 0x29, 0x8b, 0xf0, 0x72, 0xff, 0x8e, 0xd0, + 0x93, 0x23, 0xd0, 0x9b, 0x62, 0x7d, 0x27, 0x8f, 0xef, 0x74, 0x6d, 0x84, 0xbe, 0x0c, 0x13, 0xd8, 0x26, 0xb7, 0xcc, + 0xde, 0xb5, 0x27, 0x63, 0x88, 0x65, 0x72, 0xe7, 0x95, 0x77, 0xf7, 0xf8, 0x96, 0xec, 0xdf, 0x82, 0xa7, 0xa8, 0x25, + 0x7f, 0xb3, 0xf0, 0x86, 0xb5, 0x6a, 0x78, 0x7c, 0x47, 0x4f, 0x5b, 0x8d, 0x78, 0x7c, 0x47, 0xa2, 0xf0, 0x86, 0x5d, + 0xd2, 0x53, 0x76, 0x45, 0xe8, 0x79, 0xbf, 0x7f, 0xd6, 0xef, 0xcb, 0x7e, 0xff, 0xa7, 0x38, 0x0c, 0xe3, 0x61, 0x41, + 0xf6, 0x25, 0xbd, 0xdb, 0x9f, 0xf0, 0x27, 0x64, 0x16, 0xea, 0xe6, 0xab, 0x05, 0x67, 0x55, 0xde, 0x2a, 0xd7, 0x1d, + 0x05, 0x6b, 0x85, 0x3b, 0xa6, 0x9e, 0x4e, 0xe8, 0x0d, 0x2b, 0xe8, 0x29, 0x8b, 0x49, 0x74, 0x0d, 0xad, 0x38, 0x9f, + 0x15, 0xd1, 0x0d, 0x3d, 0x65, 0x67, 0xb3, 0x38, 0x3a, 0xa5, 0x27, 0x2c, 0x1f, 0x4e, 0x20, 0xef, 0xe9, 0xf0, 0x86, + 0xec, 0x9f, 0x90, 0x28, 0x3c, 0xd1, 0xbf, 0xef, 0xe8, 0x25, 0x0f, 0x4f, 0xa8, 0x57, 0xcd, 0x09, 0x31, 0xd5, 0x37, + 0x6a, 0x3f, 0x21, 0x91, 0x3f, 0x98, 0x27, 0xd6, 0x9e, 0xe6, 0x91, 0xa3, 0x8d, 0x69, 0x19, 0x82, 0xbe, 0xb9, 0x0c, + 0x6f, 0x08, 0x99, 0x36, 0xc7, 0x0e, 0x06, 0x74, 0xf6, 0x28, 0x4a, 0x08, 0xbd, 0xf1, 0x4b, 0xbd, 0xc1, 0x31, 0x34, + 0x23, 0xa4, 0xd2, 0x4e, 0x31, 0x0d, 0xd7, 0xc1, 0x6b, 0x0d, 0xd6, 0x71, 0xde, 0xef, 0x87, 0xeb, 0x7e, 0x1f, 0x22, + 0xdd, 0x17, 0x33, 0x13, 0xdb, 0xcd, 0x91, 0x4d, 0x7a, 0x03, 0xda, 0xff, 0xd7, 0x83, 0x01, 0x74, 0xc6, 0x2b, 0x29, + 0xbc, 0x19, 0xbc, 0x7e, 0x7c, 0x47, 0x54, 0x1d, 0x05, 0x15, 0x32, 0x2c, 0xe8, 0x1b, 0x9a, 0x01, 0xe0, 0xd7, 0xeb, + 0xc1, 0x80, 0x44, 0xe6, 0x33, 0x32, 0x7d, 0x7d, 0x78, 0x32, 0x1d, 0x0c, 0x5e, 0x9b, 0x6d, 0xf2, 0x96, 0xdd, 0x53, + 0x0a, 0xac, 0xbf, 0xb3, 0x7e, 0xff, 0xed, 0x51, 0x4c, 0xce, 0x0b, 0x1e, 0x7f, 0x9c, 0x36, 0xdb, 0xf2, 0xd6, 0x45, + 0x55, 0x3b, 0xeb, 0xf7, 0xd7, 0xfd, 0xfe, 0x29, 0x60, 0x17, 0xcd, 0x9c, 0xaf, 0x27, 0x48, 0x5b, 0xe6, 0x8e, 0x22, + 0x69, 0x92, 0x43, 0x63, 0x68, 0x5b, 0xac, 0xda, 0x36, 0xeb, 0xc8, 0xc0, 0xe2, 0xa8, 0x59, 0x51, 0x5c, 0x93, 0x28, + 0xec, 0x9d, 0x6d, 0xb7, 0xa7, 0x8c, 0xb1, 0x98, 0x80, 0xf4, 0xc3, 0x7f, 0x7d, 0x5a, 0x37, 0x62, 0x88, 0x09, 0x89, + 0xcc, 0xe6, 0x66, 0x69, 0x0f, 0x81, 0x88, 0xc3, 0xa6, 0x7f, 0x6f, 0xee, 0xe5, 0xa2, 0x76, 0x7c, 0xeb, 0x2f, 0x00, + 0x42, 0x24, 0x59, 0xc8, 0x67, 0x38, 0x06, 0x65, 0x06, 0x40, 0xe6, 0x91, 0x9a, 0x79, 0x09, 0x20, 0xc0, 0x64, 0xbb, + 0x1d, 0x8d, 0xc7, 0x13, 0x5a, 0xb0, 0xd1, 0xdf, 0x9e, 0x3d, 0xae, 0x1e, 0x87, 0x41, 0x30, 0xc8, 0x48, 0x4b, 0x4f, + 0x61, 0x17, 0x6b, 0xb5, 0x0f, 0x46, 0xf0, 0x9a, 0x7d, 0xbc, 0xce, 0xbe, 0x98, 0x7d, 0x44, 0xc2, 0xda, 0x60, 0x1c, + 0xb9, 0x48, 0x5b, 0x7a, 0xbb, 0x7b, 0x18, 0x4c, 0x2e, 0xd2, 0xcf, 0xb0, 0x9d, 0x3e, 0xff, 0xe6, 0xc1, 0x78, 0xc2, + 0xc1, 0xe8, 0x2e, 0x0a, 0xfa, 0x4c, 0xdb, 0x6e, 0x2b, 0xff, 0x12, 0xf8, 0x16, 0x53, 0x41, 0xc7, 0x66, 0x59, 0xb8, + 0x41, 0x45, 0xd4, 0xd1, 0x32, 0xa8, 0x6a, 0x65, 0x3b, 0x07, 0xd4, 0x12, 0xab, 0x32, 0x71, 0x0b, 0x0c, 0x43, 0x86, + 0xba, 0xdc, 0xe3, 0xea, 0x5f, 0xbc, 0x90, 0x06, 0x3e, 0xc3, 0x89, 0x08, 0x3d, 0x6e, 0x8d, 0xfb, 0xdc, 0x9a, 0xf8, + 0x0c, 0xb7, 0x56, 0x22, 0x89, 0x35, 0xb0, 0xa4, 0xe6, 0x72, 0x94, 0xb0, 0xa3, 0x92, 0xf1, 0x59, 0x19, 0x25, 0x34, + 0x86, 0x07, 0xc9, 0xc4, 0x4c, 0x46, 0x09, 0xda, 0x27, 0xba, 0x08, 0x83, 0x7f, 0x01, 0x66, 0x3f, 0xcd, 0xe1, 0xaf, + 0x24, 0xd3, 0xe4, 0x10, 0x02, 0x42, 0x1c, 0x8e, 0x67, 0x71, 0x38, 0x26, 0x51, 0x72, 0x04, 0x4f, 0xf0, 0x5f, 0x11, + 0x8e, 0x49, 0xad, 0xef, 0x30, 0x52, 0x5d, 0x6e, 0x13, 0x06, 0x70, 0x65, 0xe3, 0xd9, 0x24, 0xb2, 0xd2, 0x5d, 0xf9, + 0x78, 0x34, 0x7e, 0x46, 0xa6, 0x71, 0x28, 0x07, 0x09, 0xa1, 0xe0, 0xdd, 0x1b, 0x96, 0xc3, 0x44, 0xc3, 0xb3, 0x01, + 0x9b, 0x57, 0x3a, 0x36, 0x4f, 0xc2, 0x09, 0x08, 0xc3, 0x84, 0x1c, 0xeb, 0x3d, 0x48, 0x29, 0xfa, 0x3c, 0xc7, 0x7e, + 0xea, 0x23, 0x08, 0xb3, 0xa3, 0x96, 0x8a, 0xaf, 0x00, 0xe8, 0x12, 0x07, 0x87, 0xda, 0x33, 0x5f, 0xcc, 0xc2, 0xd2, + 0xa3, 0x52, 0xa6, 0xba, 0x7d, 0xd1, 0xa0, 0xfc, 0xa6, 0x41, 0xfb, 0x82, 0x0c, 0x26, 0xb4, 0x3c, 0x9a, 0xf0, 0x27, + 0x10, 0xc0, 0xa3, 0x11, 0xf1, 0x4b, 0xe1, 0xc4, 0x40, 0x78, 0x15, 0x64, 0xa0, 0xd2, 0x5a, 0x35, 0x66, 0x64, 0x2b, + 0xde, 0x83, 0x30, 0x29, 0x7b, 0x37, 0x72, 0x9d, 0xa7, 0x10, 0x15, 0x6c, 0x9d, 0x57, 0x7b, 0x97, 0x60, 0xc9, 0x1e, + 0x57, 0x10, 0x27, 0x6c, 0xbd, 0x02, 0xec, 0xdc, 0x47, 0x9b, 0xb2, 0xde, 0x53, 0xdf, 0xed, 0x61, 0xcb, 0xe1, 0x55, + 0x25, 0xf7, 0x26, 0xe3, 0xf1, 0x78, 0xf4, 0x07, 0x1c, 0x1d, 0x40, 0x68, 0x49, 0x64, 0xf8, 0x64, 0x80, 0xc6, 0x5d, + 0x57, 0xdc, 0x1b, 0x17, 0x8a, 0xb2, 0xd2, 0xc9, 0x84, 0x80, 0xf8, 0xd9, 0xf4, 0x0d, 0xf6, 0x15, 0xd7, 0xf1, 0x4f, + 0x76, 0x3f, 0x31, 0x2b, 0x5a, 0xad, 0xd4, 0xd1, 0xbb, 0x93, 0xd3, 0xd7, 0x1f, 0x5e, 0xff, 0xf6, 0xf2, 0xec, 0xf5, + 0xdb, 0x57, 0xaf, 0xdf, 0xbe, 0xfe, 0xf0, 0xcf, 0x07, 0x18, 0x6c, 0xdf, 0x56, 0xc4, 0x8e, 0xbd, 0x77, 0x8f, 0xf1, + 0x6a, 0xf1, 0x85, 0xb3, 0x07, 0xee, 0x16, 0x0b, 0xb0, 0x09, 0x86, 0x5b, 0x10, 0x54, 0x33, 0x1a, 0x95, 0xbe, 0x27, + 0x20, 0xa3, 0x51, 0x21, 0x1b, 0x0f, 0x2b, 0xb6, 0x42, 0x2e, 0xde, 0x31, 0x1c, 0x7c, 0x64, 0x7f, 0x2b, 0xce, 0x84, + 0xdb, 0xd1, 0xd6, 0xac, 0x08, 0xf8, 0x7c, 0xad, 0x45, 0xe5, 0x71, 0x21, 0x6a, 0x6f, 0xdb, 0xe7, 0x90, 0x50, 0x8f, + 0xc8, 0x75, 0xf0, 0xbe, 0x0d, 0xb2, 0xc7, 0x47, 0xde, 0x93, 0xf2, 0x0c, 0xf5, 0x39, 0x1a, 0x3e, 0x6a, 0x3c, 0xa3, + 0x13, 0x73, 0x6d, 0x74, 0xa8, 0x67, 0x05, 0xec, 0x6f, 0x25, 0xc6, 0x86, 0x68, 0x0f, 0x29, 0x62, 0x7d, 0x38, 0xdd, + 0xef, 0xee, 0xcd, 0xe8, 0x7b, 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, 0xf7, 0x5c, 0x29, 0x9a, 0xb7, 0x2e, 0xb0, 0x07, 0x6a, 0x5e, 0xc7, 0x4b, 0x16, 0x02, 0x36, 0xe3, + 0xbe, 0x5d, 0x24, 0xce, 0xef, 0x9d, 0x4e, 0xc8, 0xfe, 0xc1, 0x94, 0x0f, 0x59, 0x49, 0xc5, 0x80, 0x95, 0xf5, 0x0e, + 0x35, 0xe7, 0x6d, 0x42, 0x2e, 0x76, 0x69, 0xb8, 0x18, 0xf2, 0x87, 0x2e, 0x49, 0x1f, 0x78, 0xc3, 0xa1, 0xda, 0x36, + 0x17, 0x43, 0x9a, 0x72, 0xba, 0x4b, 0x65, 0x40, 0x88, 0x74, 0x15, 0x57, 0xa4, 0xd6, 0x47, 0x55, 0xea, 0x24, 0x1d, + 0xd7, 0xd9, 0xe6, 0x33, 0x97, 0x6c, 0x75, 0xbb, 0xf6, 0xaf, 0xd5, 0xed, 0x0b, 0x33, 0x90, 0xbf, 0x3f, 0x11, 0xd5, + 0xc4, 0x40, 0x74, 0x01, 0x15, 0xfc, 0x13, 0xbc, 0x3c, 0x79, 0xa4, 0x15, 0xa0, 0xf7, 0x9d, 0x1d, 0x5d, 0x7b, 0xbc, + 0x31, 0x8b, 0xad, 0x25, 0xce, 0x59, 0xe5, 0x3b, 0xcb, 0xab, 0xb2, 0x15, 0xba, 0x8e, 0x60, 0xbf, 0x84, 0x1d, 0x7d, + 0xf7, 0xb6, 0x01, 0x10, 0xa5, 0xb0, 0x72, 0x67, 0xbf, 0xf0, 0xce, 0x7e, 0x61, 0xcf, 0x7e, 0xbb, 0x09, 0x94, 0x0f, + 0x2b, 0xb4, 0xec, 0x95, 0x14, 0x95, 0x69, 0xf2, 0xb8, 0xa9, 0xcb, 0x42, 0x5a, 0xcc, 0xf7, 0x2d, 0xed, 0x7a, 0x3a, + 0xa6, 0x12, 0xd5, 0x23, 0x3f, 0x60, 0xab, 0xf6, 0x4b, 0xf2, 0xf0, 0x3d, 0xf3, 0x7f, 0xf6, 0x06, 0x79, 0xdf, 0xdd, + 0xee, 0xff, 0xe6, 0x42, 0x07, 0xb7, 0xb5, 0x54, 0x78, 0xea, 0xea, 0xb8, 0xc0, 0xbb, 0x5a, 0xfa, 0xf0, 0x5d, 0xed, + 0x5d, 0xa6, 0x97, 0x5d, 0x05, 0xa8, 0x41, 0x62, 0x7d, 0xc5, 0x8b, 0x2c, 0xa9, 0xad, 0x42, 0xe3, 0x84, 0x43, 0x68, + 0x0f, 0xef, 0xe0, 0x02, 0x39, 0x2c, 0x21, 0xf4, 0x63, 0x65, 0x04, 0x80, 0x3e, 0x8b, 0x7d, 0xc2, 0xc3, 0x8c, 0x0c, + 0x7c, 0x89, 0x5f, 0x29, 0x7d, 0x71, 0xf1, 0xfe, 0x4e, 0x66, 0x82, 0x5e, 0x25, 0x36, 0xbb, 0x94, 0xed, 0x98, 0x1f, + 0xfe, 0x17, 0x18, 0x0d, 0xc2, 0x6b, 0x4b, 0xb6, 0x2f, 0x3a, 0x66, 0xb9, 0x82, 0xa3, 0xb6, 0x74, 0x65, 0x96, 0xad, + 0xeb, 0x67, 0x35, 0xcc, 0xf4, 0x99, 0x72, 0x02, 0xb2, 0x2f, 0xe4, 0xee, 0xa7, 0xba, 0x62, 0x41, 0x8e, 0x26, 0xe3, + 0x29, 0x11, 0x83, 0x41, 0x2b, 0xf9, 0x10, 0x93, 0x87, 0xc3, 0x1d, 0xe6, 0x52, 0xe8, 0x7e, 0x78, 0x7d, 0x80, 0xfa, + 0x1a, 0x5b, 0x92, 0x6c, 0x2a, 0xf6, 0x17, 0x98, 0xc5, 0x02, 0x71, 0x74, 0xf0, 0x8b, 0xf3, 0x05, 0x80, 0x2c, 0xc3, + 0x32, 0xd3, 0xc2, 0xa2, 0x32, 0x55, 0x3e, 0xb2, 0x05, 0x93, 0x87, 0xe3, 0x99, 0xdf, 0x73, 0xc7, 0xe0, 0x10, 0x12, + 0x4d, 0xac, 0xf1, 0x8b, 0x9f, 0x05, 0xe3, 0x38, 0x94, 0x47, 0xb2, 0xf1, 0x5d, 0x49, 0xa2, 0xb1, 0x31, 0x55, 0xd6, + 0x57, 0x89, 0x6a, 0x98, 0x90, 0xc7, 0x05, 0xd9, 0x2f, 0xe8, 0xd2, 0x1f, 0x4b, 0x4c, 0xdf, 0x8f, 0xf7, 0x27, 0x63, + 0xf2, 0x38, 0x7e, 0x3c, 0x31, 0x70, 0xc3, 0x7e, 0x8e, 0x7c, 0xb8, 0x24, 0xfb, 0xcd, 0x2a, 0xc1, 0x14, 0xd5, 0xf4, + 0xcc, 0xaf, 0x24, 0x19, 0x2c, 0x07, 0xe9, 0xe3, 0x56, 0x5e, 0xac, 0x55, 0x8f, 0xf7, 0xfa, 0x90, 0x4f, 0x89, 0x68, + 0xdc, 0x18, 0xd6, 0xf4, 0x2a, 0xfe, 0x53, 0x16, 0x51, 0x29, 0x01, 0x91, 0x10, 0xd4, 0xdb, 0xd9, 0x45, 0x96, 0xc4, + 0x22, 0x8d, 0xd2, 0x9a, 0xd0, 0xf4, 0x88, 0x4d, 0xc6, 0xb3, 0x94, 0xa5, 0x87, 0x93, 0x67, 0xb3, 0xc9, 0xb3, 0xe8, + 0x60, 0x1c, 0xa5, 0x83, 0x01, 0x24, 0x1f, 0x8c, 0xc1, 0xc5, 0x0e, 0x7e, 0xb3, 0x03, 0x18, 0xba, 0x23, 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, 0x0b, 0xf9, 0xff, 0xe3, 0x86, 0x71, 0xdf, 0x5d, 0xc2, 0x2c, + 0xae, 0xeb, 0x6c, 0xb4, 0x2a, 0x64, 0x25, 0xe1, 0x36, 0xa1, 0x44, 0x61, 0xa3, 0x78, 0xb5, 0xca, 0xb5, 0x8b, 0xd8, + 0xbc, 0xa2, 0x00, 0xee, 0x02, 0x71, 0x8a, 0x81, 0x85, 0x36, 0x06, 0x72, 0x9f, 0x78, 0x21, 0x99, 0x55, 0xfb, 0x98, + 0x7b, 0xe4, 0x9f, 0x21, 0x18, 0xa3, 0x8a, 0xa3, 0xf1, 0x4c, 0x61, 0x5d, 0x7c, 0x4e, 0xde, 0xfb, 0x6f, 0x1c, 0x45, + 0xf6, 0x68, 0x06, 0x3d, 0x41, 0xe4, 0x3c, 0xe2, 0xec, 0xc9, 0xe4, 0x65, 0xe0, 0x7e, 0x06, 0x2b, 0xfd, 0x75, 0xb7, + 0x19, 0x6b, 0xdb, 0xa3, 0x7b, 0x61, 0x84, 0xa2, 0x9f, 0xf0, 0x9d, 0xa9, 0x17, 0x70, 0x09, 0xd5, 0xc0, 0xae, 0x2f, + 0x2f, 0x79, 0x09, 0x20, 0x42, 0x99, 0xe8, 0xf7, 0x7b, 0x7f, 0x1a, 0x68, 0xd2, 0x92, 0x17, 0x6f, 0x32, 0x61, 0x9d, + 0x71, 0xa0, 0xa9, 0x40, 0xfd, 0x3f, 0x56, 0xf6, 0x99, 0x8e, 0xc9, 0xcc, 0x7f, 0x1c, 0x4e, 0x48, 0xd4, 0x7c, 0x4d, + 0x3e, 0x73, 0x9a, 0x7e, 0xe6, 0x8a, 0xf6, 0x1f, 0xc8, 0xcc, 0x0d, 0x87, 0x0c, 0xf5, 0x97, 0x8e, 0x79, 0x32, 0x7a, + 0x9d, 0x98, 0x1d, 0x09, 0x56, 0xcd, 0x20, 0x0a, 0x7b, 0x01, 0x0f, 0xea, 0x5a, 0x16, 0x4f, 0x61, 0xf6, 0x41, 0x8d, + 0x28, 0x0e, 0xd9, 0x78, 0x16, 0xca, 0x70, 0x02, 0xf6, 0xbd, 0x93, 0x31, 0xdc, 0x07, 0x64, 0xf8, 0xb1, 0x0a, 0xb1, + 0x73, 0x90, 0xf6, 0xb1, 0x42, 0xc5, 0x04, 0x40, 0x04, 0x42, 0xde, 0x7e, 0x5f, 0xaa, 0x24, 0x7c, 0x5d, 0x62, 0x4a, + 0xa1, 0x3e, 0xf8, 0x4f, 0xa4, 0xea, 0x8e, 0xe9, 0x57, 0xeb, 0xc7, 0x9f, 0x09, 0xc5, 0xa7, 0xbb, 0x94, 0xf8, 0x16, + 0x82, 0x3b, 0x4b, 0xd0, 0x41, 0x54, 0x68, 0xc6, 0xf6, 0x30, 0xbf, 0x2b, 0xee, 0xe7, 0x77, 0xc5, 0xff, 0x3b, 0x7e, + 0x57, 0x3c, 0xc4, 0x18, 0x56, 0x16, 0x1a, 0x7e, 0x16, 0x8c, 0x83, 0xe8, 0x3f, 0xe7, 0x13, 0xef, 0xe5, 0xa9, 0xaf, + 0x32, 0x31, 0xbd, 0x87, 0x69, 0xf6, 0x09, 0x0a, 0xc2, 0x2a, 0xee, 0xd2, 0x93, 0x75, 0x65, 0x6f, 0xad, 0x64, 0x88, + 0x79, 0x1e, 0x60, 0x8d, 0xc2, 0xca, 0x03, 0xba, 0x47, 0xd5, 0x06, 0x71, 0x22, 0x78, 0x18, 0x33, 0x2b, 0x7d, 0xdf, + 0x6e, 0x8d, 0x0a, 0xf3, 0x41, 0x2e, 0x0a, 0xb2, 0x9b, 0x8f, 0x67, 0xe3, 0x28, 0xc4, 0x06, 0xfc, 0xc7, 0x8c, 0x55, + 0x43, 0x36, 0xdf, 0xc9, 0x48, 0xed, 0x98, 0x3c, 0x4d, 0x76, 0x49, 0xef, 0x80, 0x77, 0xc8, 0xcf, 0xeb, 0x8f, 0x61, + 0x21, 0x0d, 0xbf, 0x25, 0x2f, 0xe3, 0x22, 0xab, 0x96, 0x57, 0x59, 0x82, 0x4c, 0x17, 0xbc, 0xf8, 0x62, 0xa6, 0xcb, + 0xfb, 0x58, 0x1f, 0x30, 0x9e, 0x52, 0xbc, 0x6e, 0x88, 0xd2, 0xd7, 0x2d, 0xcf, 0x0a, 0x75, 0x79, 0x52, 0x31, 0xdb, + 0xb3, 0x12, 0x9c, 0x4e, 0xc1, 0x04, 0x5f, 0xff, 0x74, 0xbd, 0x8f, 0x01, 0x17, 0x14, 0x6a, 0x4e, 0x0b, 0xb9, 0x32, + 0x58, 0x4e, 0x16, 0xba, 0x13, 0x30, 0x43, 0xa5, 0xc0, 0x0b, 0x14, 0xfc, 0x45, 0x03, 0x23, 0xfa, 0xca, 0xfd, 0x26, + 0x03, 0x83, 0x74, 0x69, 0x4e, 0x84, 0xb1, 0xe3, 0x76, 0x8a, 0xb4, 0x15, 0xe5, 0x8c, 0xb3, 0xf7, 0xea, 0x4a, 0x01, + 0x06, 0x78, 0x9b, 0x9b, 0xe8, 0x3c, 0x41, 0xaf, 0x05, 0xa5, 0xf3, 0x06, 0xee, 0x66, 0x19, 0x19, 0xe1, 0xe2, 0xe3, + 0xca, 0x63, 0xc1, 0x3d, 0xfb, 0x85, 0x58, 0x1a, 0xcd, 0x34, 0x18, 0xb3, 0x79, 0xc1, 0x02, 0x85, 0x0a, 0x14, 0x58, + 0xce, 0xb4, 0xa5, 0x69, 0x35, 0xe4, 0xfb, 0x07, 0x68, 0x6d, 0x5a, 0x0d, 0xf8, 0xfe, 0x41, 0x1d, 0x65, 0x87, 0x90, + 0xe5, 0xc8, 0xcf, 0xa0, 0x5e, 0xd7, 0x91, 0x49, 0x31, 0xd9, 0xfd, 0xfa, 0x52, 0x7f, 0x54, 0x37, 0xe0, 0xfa, 0x01, + 0x08, 0x60, 0x03, 0x70, 0x08, 0x54, 0x83, 0xa5, 0x11, 0xc1, 0xa2, 0x4c, 0xa1, 0x7d, 0x0d, 0xbd, 0x37, 0x1a, 0xfe, + 0x0b, 0xdc, 0x45, 0xe4, 0xca, 0xff, 0x04, 0x81, 0xbf, 0xa2, 0x4c, 0x2b, 0x53, 0xfc, 0x4f, 0xb4, 0x7a, 0x85, 0x72, + 0xd6, 0xb4, 0xe6, 0x83, 0x68, 0x4d, 0x84, 0x6a, 0xc6, 0x10, 0xfc, 0x5b, 0x59, 0xa6, 0x2d, 0x55, 0x95, 0xfa, 0xd0, + 0x78, 0xad, 0x15, 0xce, 0xf2, 0x71, 0xe4, 0xbd, 0xc6, 0xd0, 0xb1, 0x89, 0xb3, 0x94, 0x53, 0xa9, 0xb3, 0x4f, 0xfb, + 0x32, 0x72, 0x80, 0xd3, 0x09, 0x1b, 0x4f, 0x93, 0x43, 0x39, 0x4d, 0x1c, 0x64, 0x7e, 0xce, 0x30, 0xb2, 0xaa, 0x01, + 0x61, 0x51, 0x36, 0x94, 0xb6, 0x00, 0x93, 0x9c, 0x10, 0x32, 0xc5, 0x50, 0x14, 0xf9, 0x48, 0xf7, 0xc3, 0x7a, 0xb3, + 0xba, 0x2f, 0xde, 0x69, 0x80, 0xd3, 0x30, 0x81, 0x40, 0xe0, 0x45, 0x7c, 0x93, 0x89, 0x4b, 0xf0, 0x18, 0x1e, 0xc0, + 0x97, 0xe0, 0x26, 0x97, 0xb2, 0xdf, 0xab, 0x30, 0xc7, 0xb5, 0x05, 0x0c, 0x1a, 0xac, 0x1e, 0x44, 0x87, 0x4b, 0x69, + 0xb3, 0xab, 0x00, 0xb1, 0x31, 0x85, 0x58, 0x16, 0x6c, 0x6d, 0xd9, 0xb3, 0xef, 0x55, 0xd3, 0xd0, 0x3a, 0xe1, 0x58, + 0x5c, 0xe6, 0x10, 0x45, 0x65, 0x10, 0x83, 0x3b, 0x92, 0xc7, 0xe7, 0x3d, 0x12, 0xe1, 0x05, 0x01, 0xb7, 0xb2, 0x58, + 0x86, 0x2b, 0xba, 0x1c, 0xdd, 0xd2, 0xf5, 0xe8, 0x86, 0x8e, 0xe9, 0xe4, 0xef, 0x63, 0xb0, 0xc8, 0xd6, 0xa9, 0x77, + 0x74, 0x3d, 0x5a, 0xd2, 0x6f, 0xc7, 0xf4, 0xe0, 0x6f, 0x60, 0xc2, 0x87, 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, 0xae, 0xf8, 0x55, 0xc9, 0x52, + 0xd8, 0x16, 0xb0, 0x7c, 0x3d, 0xaf, 0xa8, 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, 0x8e, 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, 0xca, 0xd3, 0xf6, + 0x75, 0xb0, 0xb1, 0xaa, 0xe8, 0x86, 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, 0xbe, 0x87, 0x88, 0xca, 0x50, 0xde, 0xe0, 0x1f, 0x18, 0x3c, 0x99, 0xad, 0xd2, 0x30, + 0x19, 0xdd, 0xd1, 0x78, 0xb4, 0x44, 0x38, 0x18, 0xb6, 0x4e, 0x15, 0xde, 0xfa, 0x05, 0xa4, 0xdf, 0xd2, 0x78, 0x74, + 0x43, 0x53, 0x6b, 0x73, 0x6a, 0xa0, 0xae, 0x7a, 0x63, 0x7a, 0x1b, 0xc1, 0xeb, 0xbb, 0x68, 0x49, 0x61, 0x2b, 0x1d, + 0xe7, 0xd9, 0xa5, 0x88, 0x52, 0x8a, 0x08, 0x84, 0x6b, 0x44, 0x0e, 0x5c, 0x6a, 0xb4, 0xc1, 0xf5, 0x00, 0xca, 0xd0, + 0x70, 0x81, 0xcb, 0x41, 0x3c, 0x5a, 0x7a, 0x64, 0x6a, 0xa9, 0x2f, 0xb2, 0x08, 0x1f, 0xed, 0x6c, 0xb4, 0x14, 0xcf, + 0x88, 0x85, 0x71, 0x05, 0x43, 0xa8, 0x0b, 0x2b, 0x4d, 0x41, 0xd2, 0x05, 0x8e, 0xec, 0x85, 0x45, 0x15, 0x6e, 0xc0, + 0xb4, 0xe8, 0x0e, 0xcc, 0xa3, 0x40, 0xe1, 0xe0, 0x12, 0xa4, 0x9f, 0x50, 0xb6, 0x73, 0x94, 0x26, 0x87, 0x37, 0x41, + 0xe9, 0xce, 0x04, 0x21, 0xed, 0xea, 0x26, 0x5b, 0xd2, 0x37, 0xd8, 0xde, 0xa1, 0x53, 0x51, 0x41, 0xf5, 0xb9, 0x05, + 0x93, 0x25, 0x1b, 0x84, 0x2d, 0x61, 0x7a, 0xa6, 0xd7, 0x80, 0x3d, 0xbd, 0x7f, 0xb0, 0x33, 0xdf, 0xc5, 0xec, 0xd3, + 0x7e, 0x19, 0x8d, 0x95, 0x05, 0x6f, 0x6e, 0x89, 0xdd, 0x92, 0x8d, 0xa7, 0xcb, 0xc3, 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, + 0x96, 0x69, 0x98, 0xe2, 0x22, 0x30, 0x29, 0xfd, 0x7e, 0x98, 0xb3, 0x94, 0x78, 0xd0, 0xa1, 0xee, 0xd4, 0x4e, 0x7d, + 0x21, 0x08, 0xf0, 0x48, 0xea, 0x1c, 0x9b, 0xfc, 0x7d, 0x3c, 0x0b, 0xd4, 0x40, 0x04, 0x51, 0x76, 0x88, 0x8f, 0x18, + 0xb8, 0x28, 0xd2, 0x71, 0x3b, 0x5d, 0x11, 0x17, 0xbb, 0xc7, 0x2c, 0xc4, 0x49, 0xc2, 0x5c, 0xb3, 0x6c, 0xc8, 0xaa, + 0x08, 0x13, 0x74, 0x61, 0x60, 0x96, 0x37, 0x64, 0xd5, 0xfe, 0x01, 0x44, 0x6a, 0xb5, 0x65, 0xac, 0xba, 0xca, 0xf8, + 0x16, 0x80, 0xac, 0x19, 0x63, 0x07, 0x7f, 0x1b, 0xcf, 0xd4, 0x37, 0x51, 0xc8, 0x8f, 0x0e, 0xfe, 0x06, 0xc9, 0x87, + 0xdf, 0x22, 0x33, 0x07, 0xc9, 0x8d, 0x82, 0x2e, 0x9b, 0xb3, 0xae, 0xa1, 0x34, 0x71, 0xed, 0x95, 0x7a, 0xed, 0x49, + 0xb3, 0xf6, 0x0a, 0x74, 0xa7, 0x36, 0xbc, 0x87, 0xb2, 0x9d, 0x05, 0x13, 0x74, 0x34, 0xbb, 0x03, 0x1d, 0xbc, 0x53, + 0x04, 0xbd, 0x4c, 0x42, 0xe3, 0x11, 0xaa, 0x8c, 0x7a, 0x61, 0x47, 0x76, 0xb3, 0x2e, 0x99, 0x67, 0xc0, 0x1c, 0xdb, + 0x73, 0x48, 0x0c, 0x73, 0x75, 0x50, 0xa7, 0xac, 0x1c, 0xe6, 0x78, 0x00, 0xaf, 0x99, 0x1c, 0x8a, 0x41, 0xae, 0x51, + 0xbe, 0x2f, 0x58, 0x31, 0x2c, 0x07, 0xb9, 0xe6, 0x66, 0xa6, 0xcd, 0xd8, 0xb4, 0x89, 0x0e, 0xcf, 0xbc, 0x62, 0x47, + 0xab, 0x1e, 0xf0, 0xb1, 0xe0, 0xc9, 0xec, 0x7b, 0x3e, 0xbe, 0x01, 0x4e, 0x66, 0x73, 0x1b, 0x2d, 0xe9, 0x5d, 0x94, + 0xd2, 0x9b, 0x68, 0x4d, 0x97, 0xd1, 0x85, 0x31, 0x31, 0x4e, 0x6a, 0x38, 0x07, 0xa0, 0x55, 0x00, 0x89, 0xa7, 0x7e, + 0xbd, 0xe7, 0x49, 0x15, 0x2e, 0x69, 0x0a, 0x6e, 0xc3, 0xbe, 0x7d, 0xe6, 0x95, 0x2f, 0x91, 0xda, 0x20, 0xc6, 0x9a, + 0x35, 0x54, 0xdc, 0x78, 0xeb, 0x3e, 0x12, 0x35, 0xec, 0x5c, 0x17, 0x9b, 0xa8, 0x1a, 0x4e, 0xa6, 0x25, 0x20, 0xb6, + 0x96, 0xc3, 0xa1, 0x3b, 0x42, 0x76, 0x8f, 0x1f, 0x1d, 0xe8, 0xb9, 0x27, 0x2d, 0xb6, 0x6d, 0xcb, 0x1f, 0x18, 0xc2, + 0x94, 0x7e, 0xfe, 0xc8, 0x07, 0xc4, 0x8a, 0x4b, 0x38, 0x1b, 0x81, 0x3a, 0x5a, 0xa1, 0xd3, 0xef, 0x55, 0x58, 0xe8, + 0x03, 0x7c, 0x73, 0x1b, 0x25, 0xf4, 0x2e, 0xca, 0x3d, 0xb2, 0xb6, 0xac, 0x99, 0x9c, 0x9e, 0x65, 0x21, 0x6f, 0x1f, + 0xe8, 0xe5, 0x02, 0x40, 0xb4, 0x06, 0xb1, 0x2f, 0x75, 0x3d, 0x00, 0xa7, 0x21, 0x34, 0x09, 0x8d, 0xe0, 0xaa, 0x82, + 0x30, 0x02, 0xae, 0x24, 0xfc, 0x0d, 0x26, 0x2a, 0xf0, 0x05, 0xb8, 0xc8, 0xa4, 0x69, 0xce, 0x83, 0xda, 0x1f, 0xc9, + 0xd3, 0xa2, 0xed, 0xed, 0x0a, 0xa3, 0x09, 0xc6, 0x9e, 0x68, 0x9f, 0x47, 0xca, 0x51, 0x5c, 0x24, 0x61, 0x36, 0xba, + 0x55, 0xe7, 0x39, 0xcd, 0x46, 0x77, 0xfa, 0x57, 0x45, 0xc7, 0xf4, 0x3b, 0x1d, 0xd0, 0x46, 0x49, 0xdf, 0x3a, 0xce, + 0x06, 0xb4, 0x5e, 0x2c, 0x8d, 0xff, 0xb5, 0x1c, 0xdd, 0x52, 0x39, 0xba, 0xf3, 0x2d, 0xa9, 0x26, 0xd3, 0xe2, 0x50, + 0xa0, 0x21, 0x55, 0xe7, 0xf7, 0x05, 0xf0, 0x73, 0xa5, 0xf1, 0x9d, 0x36, 0xdf, 0x7b, 0xed, 0x3f, 0xef, 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, 0xcb, 0xed, 0x56, 0xc5, 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, 0x5c, 0xd7, 0xcf, 0xda, 0xd4, 0xe8, 0x15, 0x58, 0xf8, + 0x6e, 0x94, 0x79, 0x24, 0xb7, 0x08, 0xa9, 0x0a, 0xac, 0xd4, 0x2d, 0x24, 0x98, 0x7f, 0x25, 0x67, 0xab, 0x32, 0x5f, + 0x3d, 0xf2, 0xa0, 0x9c, 0x4d, 0x4f, 0x7f, 0x43, 0x82, 0x76, 0xd7, 0x91, 0xe6, 0xf1, 0x16, 0x1d, 0x3e, 0xbb, 0xd6, + 0x12, 0x73, 0x27, 0x51, 0xf1, 0x7c, 0x0a, 0xd8, 0xea, 0x45, 0x76, 0xa5, 0x7c, 0xac, 0x76, 0x71, 0xfc, 0xcc, 0xf9, + 0x13, 0x57, 0xe1, 0x5a, 0x34, 0x94, 0x20, 0xe0, 0xcd, 0x61, 0xec, 0x0a, 0x55, 0x40, 0x43, 0x73, 0x03, 0xc7, 0xb9, + 0x1a, 0x56, 0x9a, 0x80, 0x69, 0x29, 0x8f, 0x0e, 0x70, 0x68, 0xf2, 0xa8, 0xdd, 0x34, 0xac, 0x0c, 0x5d, 0x6b, 0xf4, + 0xb9, 0xad, 0x74, 0xc6, 0x9b, 0x0d, 0xdf, 0x3f, 0x18, 0x54, 0xf8, 0x93, 0x34, 0x47, 0xa3, 0x9d, 0x1b, 0xee, 0x34, + 0x02, 0x33, 0x57, 0x72, 0x45, 0x76, 0x47, 0xc9, 0xcb, 0xef, 0xe9, 0x85, 0x05, 0xf4, 0xe7, 0x3f, 0x17, 0x13, 0x4e, + 0x5a, 0x62, 0x42, 0xb4, 0x74, 0xd0, 0xa2, 0x83, 0x1d, 0xe5, 0x95, 0x7d, 0x89, 0x97, 0xce, 0xf1, 0xbf, 0xaf, 0xc7, + 0xda, 0x55, 0x20, 0xb4, 0x3a, 0xb9, 0xdf, 0x9e, 0x2c, 0x10, 0x35, 0xa0, 0x9a, 0x5d, 0x95, 0xa3, 0x4c, 0x3b, 0x2b, + 0xb2, 0x69, 0xc8, 0x5c, 0x77, 0xb3, 0x34, 0x6c, 0x26, 0x3b, 0x16, 0x96, 0x19, 0x06, 0x6b, 0xa7, 0x8a, 0x3e, 0x07, + 0x2d, 0x3f, 0x82, 0x17, 0x4d, 0xe5, 0x99, 0xcf, 0x66, 0x19, 0xf1, 0x02, 0x9d, 0x73, 0x2a, 0x16, 0x4d, 0xe9, 0x58, + 0xb9, 0xdd, 0x96, 0x68, 0x2c, 0x51, 0x46, 0x41, 0x50, 0xdb, 0x20, 0xec, 0xba, 0x74, 0x4f, 0xfa, 0xb4, 0x8b, 0x4f, + 0x2b, 0xd0, 0xf7, 0xf8, 0x3e, 0x03, 0x89, 0xa9, 0x27, 0x79, 0xa8, 0x1a, 0xcd, 0xd1, 0xc9, 0xb3, 0x38, 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, 0x07, 0xd4, 0xa9, 0x8b, 0x75, 0x1b, 0x50, 0xb2, 0xe4, 0xdd, 0x3a, 0x3d, 0xb1, 0xd2, 0x77, 0xfb, + 0xe1, 0xce, 0x3c, 0x6a, 0x76, 0x77, 0xbb, 0x9d, 0x90, 0xb6, 0x7d, 0x30, 0xde, 0x97, 0xb0, 0x10, 0xe7, 0x1d, 0xb6, + 0xf7, 0x7d, 0x58, 0x3d, 0xe6, 0x83, 0x5f, 0x70, 0x9c, 0x61, 0xf4, 0x33, 0x65, 0xe8, 0xf3, 0xaa, 0x90, 0x57, 0xaa, + 0x53, 0xbe, 0xd0, 0xad, 0x65, 0xea, 0xfd, 0x36, 0x7e, 0xdb, 0x0a, 0x10, 0xe3, 0x75, 0xc5, 0x4a, 0xf1, 0x86, 0x56, + 0x18, 0xd7, 0xc0, 0x6d, 0x72, 0xa8, 0xa5, 0x5a, 0x20, 0xea, 0xf2, 0x93, 0xc7, 0x3c, 0x32, 0xea, 0x4c, 0xf8, 0xee, + 0x31, 0xf7, 0xa5, 0x6b, 0xbb, 0x4d, 0xfc, 0x5c, 0xd3, 0xf6, 0x77, 0x07, 0xba, 0xa3, 0x75, 0x0f, 0x37, 0xcf, 0xe6, + 0xe7, 0x91, 0xf9, 0x62, 0x80, 0xcd, 0xda, 0x65, 0x5c, 0x76, 0x0c, 0xf7, 0xbd, 0xe9, 0xc1, 0x58, 0x40, 0x20, 0x31, + 0x43, 0x2f, 0x03, 0x17, 0xb8, 0xc0, 0x5d, 0x61, 0xc0, 0x10, 0xd7, 0xb4, 0xe4, 0x4c, 0x5b, 0xd9, 0xfa, 0xc8, 0xdb, + 0xa8, 0x10, 0xac, 0xeb, 0x8e, 0x9b, 0x24, 0x87, 0xe0, 0x84, 0x2d, 0xf7, 0xbe, 0xf6, 0xda, 0x19, 0xfe, 0x63, 0x20, + 0x9c, 0x5b, 0xa2, 0x67, 0xd4, 0xf6, 0x58, 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, 0xde, 0xbf, 0xe6, 0x38, 0x71, 0x96, 0xc2, 0xf6, 0xc3, 0x87, 0x0b, 0x76, 0x4d, 0x00, 0x83, 0x16, 0x93, 0x05, + 0x4a, 0x50, 0xc9, 0x5a, 0xd5, 0x6e, 0xa7, 0xc4, 0x2f, 0xf7, 0x8b, 0x2e, 0xb3, 0x9d, 0xc7, 0xaf, 0x9b, 0xb4, 0xcf, + 0x7c, 0x8e, 0x7e, 0x98, 0xdf, 0x59, 0x27, 0x25, 0x67, 0x18, 0xd7, 0xf2, 0xff, 0xab, 0xe8, 0x65, 0x91, 0xa5, 0xd1, + 0xc6, 0xf0, 0x60, 0x36, 0xd4, 0xa6, 0x0f, 0x8d, 0x51, 0xb9, 0x65, 0xa3, 0x88, 0x68, 0x75, 0x0b, 0x82, 0x19, 0xc5, + 0x7d, 0x89, 0x36, 0xaf, 0x54, 0x59, 0x78, 0x87, 0xcf, 0x6c, 0xf4, 0x86, 0xed, 0x09, 0xa1, 0x7c, 0xf7, 0xb4, 0x30, + 0xab, 0x96, 0x8a, 0x06, 0xdb, 0x25, 0xbc, 0x8b, 0x51, 0xa5, 0x9f, 0x30, 0xd9, 0xb2, 0x60, 0xaa, 0xff, 0xdf, 0x17, + 0x59, 0xda, 0xa6, 0xe8, 0xc0, 0x74, 0x36, 0x7d, 0x3a, 0xe9, 0x06, 0xd7, 0x19, 0xb0, 0x88, 0x60, 0x4b, 0x85, 0xe3, + 0x51, 0x6a, 0x37, 0x48, 0x98, 0x08, 0x6e, 0xa2, 0x5e, 0x76, 0xb4, 0x4c, 0xc9, 0xaa, 0x80, 0xe7, 0x57, 0xae, 0x32, + 0x1d, 0x47, 0x43, 0xbf, 0x7f, 0x95, 0x9a, 0xd0, 0xaf, 0xd4, 0x4b, 0x55, 0x9c, 0x87, 0x51, 0x75, 0xa8, 0x30, 0x46, + 0x4b, 0x9a, 0xc2, 0x31, 0x98, 0x5d, 0x84, 0x29, 0x5e, 0xce, 0x36, 0x09, 0xfb, 0x82, 0x81, 0x5c, 0x6a, 0x83, 0x7a, + 0x4d, 0x89, 0xd6, 0xac, 0xbd, 0x99, 0x53, 0x42, 0x2f, 0x58, 0xe9, 0xdf, 0x85, 0xd6, 0x20, 0x50, 0x94, 0xcd, 0x94, + 0xe9, 0xb9, 0x6e, 0xe7, 0x05, 0x4d, 0x68, 0x41, 0x57, 0xa4, 0x06, 0x7d, 0xaf, 0x93, 0xb3, 0xa3, 0x93, 0x9d, 0x99, + 0xf5, 0x98, 0x15, 0xc3, 0xc9, 0x34, 0x86, 0x6b, 0x5a, 0xec, 0xae, 0x69, 0xcb, 0xe6, 0x8d, 0xab, 0xb1, 0x71, 0x1a, + 0xb4, 0x0b, 0xa4, 0x6d, 0x9a, 0xdb, 0x4f, 0x3d, 0x6e, 0x7f, 0x5d, 0xb3, 0xe5, 0xb4, 0xb7, 0xde, 0x6e, 0x7b, 0x29, + 0xd8, 0x88, 0x7a, 0x7c, 0xfc, 0x5a, 0x49, 0xd7, 0x2d, 0x97, 0x9f, 0xc2, 0xb3, 0xc7, 0xd7, 0x2f, 0x7d, 0x70, 0x39, + 0x5a, 0xb5, 0xb9, 0xfb, 0xe5, 0x2e, 0xb2, 0xdc, 0x17, 0x0d, 0x2d, 0xd7, 0x33, 0xd4, 0x24, 0xcf, 0x46, 0x7b, 0x87, + 0x5a, 0xb0, 0x9c, 0x75, 0x13, 0x9e, 0x18, 0xec, 0xd8, 0xab, 0xc6, 0xe6, 0xa8, 0xcc, 0x25, 0xab, 0x41, 0x02, 0x7d, + 0x92, 0x67, 0x9a, 0xfe, 0x41, 0x86, 0xf9, 0xe8, 0x96, 0xe6, 0x80, 0x2b, 0x56, 0xd9, 0x4b, 0x06, 0xa9, 0xab, 0xf6, + 0x12, 0x57, 0xbe, 0xc2, 0x21, 0xd9, 0xe0, 0x93, 0x61, 0xaa, 0x3e, 0xbb, 0xe4, 0xc1, 0xff, 0xdb, 0xaa, 0x55, 0x7a, + 0x6e, 0x92, 0x1b, 0x8e, 0x7f, 0x9d, 0xb4, 0x7d, 0x4c, 0x0c, 0x12, 0xf0, 0xd4, 0x2e, 0x86, 0x6a, 0x54, 0x15, 0xb1, + 0x28, 0x73, 0x13, 0x73, 0xec, 0xde, 0xae, 0xa1, 0x83, 0x32, 0xf8, 0x75, 0xc3, 0x27, 0xe6, 0x0e, 0x6c, 0x05, 0x3a, + 0x3a, 0xd1, 0x5c, 0x86, 0x99, 0xb9, 0x0c, 0xd3, 0xae, 0xad, 0x02, 0xc3, 0xab, 0xb6, 0x4a, 0xa2, 0x5c, 0x8d, 0x7a, + 0xdc, 0xcc, 0x52, 0xb3, 0x17, 0x79, 0xf7, 0x9a, 0xf4, 0x24, 0xfe, 0x74, 0xe9, 0xc9, 0xeb, 0x61, 0x40, 0xe4, 0x97, + 0x2c, 0x0d, 0xd7, 0x28, 0x08, 0x4e, 0xad, 0x76, 0x20, 0xcd, 0x47, 0x80, 0xcc, 0x8f, 0xd3, 0xf0, 0x9d, 0x16, 0xe7, + 0x90, 0x8d, 0xd2, 0x38, 0xb1, 0xa5, 0x51, 0x0f, 0xc1, 0x9d, 0xf7, 0x8a, 0xc7, 0x10, 0xf8, 0xf0, 0x03, 0x6e, 0x06, + 0x15, 0xdd, 0x96, 0x98, 0x28, 0x6d, 0x1e, 0x75, 0xcb, 0x47, 0x0d, 0xa1, 0x92, 0x95, 0xe1, 0xc5, 0xd0, 0xde, 0x1d, + 0x81, 0x51, 0xe5, 0x04, 0x32, 0xc3, 0x62, 0xff, 0x60, 0x98, 0x2a, 0x41, 0xd1, 0x50, 0x0e, 0x97, 0x28, 0x07, 0xc4, + 0x24, 0x10, 0x18, 0x15, 0x83, 0x54, 0x57, 0xa6, 0x5e, 0x0c, 0x52, 0x7d, 0xab, 0x22, 0xf5, 0x59, 0x16, 0x56, 0x54, + 0xb7, 0x88, 0x8e, 0xe9, 0x50, 0xd2, 0xa5, 0xd9, 0xa9, 0xb9, 0x96, 0x5e, 0xa8, 0xe5, 0xf8, 0x5c, 0xa7, 0xc1, 0x28, + 0x9e, 0xba, 0x14, 0xfd, 0x56, 0xed, 0x67, 0xff, 0x2d, 0xa6, 0xd4, 0x88, 0x4d, 0xed, 0x2d, 0x62, 0x58, 0xb5, 0x1f, + 0xb2, 0x2a, 0x07, 0xed, 0x2e, 0x28, 0x1b, 0x2b, 0xe3, 0x3c, 0xdf, 0x08, 0x66, 0x0e, 0xda, 0xc6, 0xaa, 0xe9, 0x43, + 0x6f, 0xc4, 0xa8, 0xbd, 0x31, 0xd5, 0xb8, 0x27, 0xf0, 0xd3, 0x06, 0x4d, 0xf7, 0x22, 0xcf, 0x51, 0x8f, 0xbc, 0xfb, + 0x9f, 0x39, 0xb2, 0x33, 0xf9, 0x2c, 0x96, 0x49, 0xdd, 0x3e, 0x26, 0xc1, 0x42, 0xd5, 0x31, 0xba, 0x70, 0x23, 0x53, + 0xda, 0xcf, 0x9d, 0xe9, 0x47, 0x3c, 0x93, 0x87, 0xed, 0xd0, 0xa8, 0x2f, 0x0d, 0x6b, 0x49, 0x11, 0xf5, 0x05, 0xbd, + 0x35, 0xd5, 0xd1, 0x01, 0xf5, 0x3a, 0x02, 0xab, 0x2b, 0xda, 0xa0, 0x06, 0x60, 0x32, 0xae, 0x6d, 0x6d, 0x3e, 0x07, + 0x53, 0x5b, 0x55, 0xc1, 0x33, 0xba, 0x2b, 0x94, 0xee, 0x4d, 0xea, 0xba, 0x35, 0xc4, 0x16, 0x30, 0x20, 0x70, 0xa3, + 0xa7, 0xa6, 0x3f, 0x68, 0xa2, 0x02, 0xd0, 0xa0, 0x71, 0x3b, 0xd3, 0x39, 0x12, 0xfd, 0x4e, 0x6d, 0xda, 0x66, 0xaa, + 0x57, 0x95, 0x0f, 0xa0, 0xe2, 0xcf, 0xd2, 0xd9, 0x85, 0x19, 0xb1, 0x00, 0xc6, 0x3d, 0x70, 0xa6, 0x7a, 0xc7, 0x19, + 0x58, 0x4f, 0xe4, 0x79, 0x56, 0xf2, 0x44, 0x0a, 0x98, 0x11, 0x79, 0x75, 0x25, 0x05, 0x0c, 0x83, 0x1a, 0x00, 0xb4, + 0x68, 0x2e, 0xa3, 0x09, 0x7f, 0x52, 0xd3, 0xfb, 0xf2, 0xf0, 0x27, 0x3a, 0xd7, 0x37, 0xe3, 0x1a, 0x0c, 0x95, 0xd7, + 0x15, 0xdf, 0xc9, 0xf4, 0x0d, 0x7f, 0xea, 0x65, 0x5a, 0xca, 0x75, 0xb1, 0x93, 0xe5, 0xc9, 0x37, 0xfc, 0x99, 0xce, + 0x73, 0xf0, 0xb4, 0xa6, 0x69, 0x7c, 0xb7, 0x93, 0xe5, 0xef, 0xdf, 0x3c, 0xb5, 0x79, 0x9e, 0x8c, 0x6b, 0x7a, 0xc3, + 0xf9, 0x47, 0x97, 0x69, 0xa2, 0xab, 0x1a, 0x3f, 0xfd, 0xbb, 0xcd, 0xf5, 0xb4, 0xa6, 0x57, 0x52, 0x54, 0xcb, 0x9d, + 0xa2, 0x0e, 0xbe, 0x39, 0xf8, 0x3b, 0xff, 0xc6, 0x74, 0xef, 0xa0, 0xa6, 0x7f, 0xad, 0xe3, 0xa2, 0xe2, 0xc5, 0x4e, + 0x71, 0x7f, 0xfb, 0xfb, 0xdf, 0x9f, 0xda, 0x8c, 0x4f, 0x6b, 0x7a, 0xc7, 0xe3, 0x8e, 0xb6, 0x4f, 0x9e, 0x3d, 0xe5, + 0x7f, 0xab, 0x6b, 0xfa, 0x2b, 0xf3, 0x83, 0xa3, 0x1e, 0x67, 0x9e, 0x1e, 0x3e, 0x91, 0x4d, 0xd4, 0x80, 0xa1, 0x87, + 0x06, 0x90, 0x4b, 0xab, 0xa6, 0xb9, 0xc7, 0x2b, 0x17, 0xdc, 0xbe, 0xcf, 0xe2, 0x34, 0x5e, 0xc1, 0x41, 0xb0, 0x41, + 0xe3, 0xac, 0x02, 0x38, 0x55, 0xe0, 0x3d, 0xa3, 0x92, 0x66, 0xa5, 0xfc, 0x07, 0xe7, 0x1f, 0x61, 0xd0, 0x10, 0xd2, + 0x46, 0x45, 0x06, 0x3a, 0x59, 0xe9, 0xc8, 0x46, 0xe8, 0xbf, 0xd9, 0x8c, 0x83, 0xe3, 0xc3, 0xe8, 0xf5, 0xfb, 0x61, + 0xc1, 0x44, 0x58, 0x10, 0x42, 0xff, 0x0c, 0x0b, 0x70, 0x28, 0x29, 0x98, 0x97, 0xcf, 0xf8, 0x9e, 0x6b, 0xa3, 0xb0, + 0x10, 0x44, 0x77, 0x91, 0x7d, 0x40, 0xd5, 0xa3, 0xef, 0xd0, 0x0d, 0xf1, 0xb2, 0xc2, 0x82, 0xa1, 0x55, 0x0d, 0xcc, + 0x10, 0x14, 0xff, 0x86, 0x87, 0x12, 0x7c, 0xe2, 0x01, 0x3e, 0x7a, 0x4c, 0x66, 0x5c, 0x5d, 0x6b, 0x4f, 0x2e, 0xc2, + 0x82, 0x06, 0xba, 0xed, 0x10, 0x74, 0x20, 0xf2, 0x5f, 0x80, 0xa7, 0xc0, 0xc0, 0x87, 0x85, 0x5d, 0xca, 0x5d, 0x7f, + 0xf5, 0x5f, 0x0d, 0xeb, 0xe8, 0xc2, 0x8f, 0xfe, 0x6a, 0x5d, 0xd8, 0x33, 0x32, 0x95, 0x87, 0xe5, 0x70, 0x32, 0x1d, + 0x0c, 0xa4, 0x8b, 0xe3, 0x76, 0x9c, 0xcd, 0x7f, 0x9d, 0xcb, 0xc5, 0x02, 0x75, 0xdf, 0x38, 0xaf, 0x33, 0xfd, 0x37, + 0xd2, 0xce, 0x07, 0x6f, 0x8e, 0x7f, 0x3f, 0x3b, 0x3d, 0x7e, 0x05, 0xce, 0x07, 0x1f, 0x5e, 0x7e, 0xff, 0xf2, 0xbd, + 0x0a, 0xee, 0xae, 0xe6, 0xbc, 0xdf, 0x77, 0x52, 0x9f, 0x90, 0x0f, 0x2b, 0xb2, 0x1f, 0xc6, 0x8f, 0x0b, 0x65, 0xf4, + 0x40, 0x0e, 0x99, 0x85, 0x42, 0x86, 0x2a, 0x6a, 0xfb, 0xbb, 0x1c, 0x4e, 0x3c, 0x30, 0x8b, 0xbb, 0x86, 0x08, 0xd7, + 0x6f, 0xb9, 0x0d, 0xb2, 0x26, 0x8f, 0xbc, 0x7e, 0x70, 0x32, 0x95, 0x8e, 0x2d, 0x2c, 0x18, 0x94, 0x0d, 0x6d, 0x3a, + 0xce, 0xe6, 0xc5, 0xc2, 0xb6, 0xcb, 0x2d, 0x90, 0x51, 0x9a, 0x5d, 0x5c, 0x84, 0x0a, 0xba, 0xfa, 0x08, 0x34, 0x00, + 0xa6, 0x51, 0x85, 0x6b, 0x11, 0x9f, 0xf9, 0xe5, 0x47, 0x63, 0xaf, 0x79, 0xb7, 0xa8, 0x7b, 0x32, 0xcd, 0xaa, 0x1a, + 0x03, 0x3a, 0x98, 0x50, 0xee, 0x06, 0xdd, 0x04, 0x93, 0x51, 0x6d, 0xf9, 0x75, 0x5e, 0x2d, 0x4c, 0x73, 0xdc, 0x30, + 0x54, 0x5e, 0xc9, 0x6b, 0xd9, 0x40, 0x64, 0x20, 0x19, 0x86, 0x3d, 0x1a, 0xa3, 0x48, 0x7d, 0x6f, 0xd7, 0x3b, 0x7e, + 0x93, 0x4b, 0x88, 0xa6, 0x98, 0x81, 0x74, 0xfe, 0x58, 0x28, 0xe7, 0x72, 0xc9, 0xf8, 0x5c, 0x2c, 0x8e, 0xc0, 0xed, + 0x7c, 0x2e, 0x16, 0x11, 0x06, 0xe5, 0xcb, 0x20, 0x56, 0x09, 0xd8, 0xbd, 0x38, 0x08, 0xdf, 0x4e, 0x68, 0x03, 0xbb, + 0x81, 0x24, 0x1b, 0x94, 0x76, 0xa5, 0x21, 0xca, 0x9d, 0xf2, 0x68, 0x83, 0xc8, 0x43, 0xac, 0x9a, 0x57, 0x6d, 0x4f, + 0x36, 0x73, 0x31, 0xc1, 0x55, 0x16, 0x33, 0x39, 0x8d, 0x0f, 0x59, 0x31, 0x8d, 0xa1, 0x94, 0x38, 0x4d, 0xc3, 0x98, + 0x4e, 0xa8, 0x20, 0x24, 0x61, 0x7c, 0x1e, 0x2f, 0x68, 0x82, 0x52, 0x82, 0x10, 0x42, 0x7e, 0x8c, 0xd0, 0x36, 0x07, + 0x96, 0xbc, 0xdd, 0x7e, 0x9e, 0x7e, 0x6e, 0xc7, 0x70, 0x19, 0x15, 0xa1, 0x1b, 0x74, 0xd6, 0xf0, 0x6f, 0x44, 0x05, + 0x8d, 0xb1, 0x62, 0x08, 0x02, 0x5e, 0x60, 0x54, 0xc2, 0x82, 0xc4, 0xac, 0x82, 0x28, 0x02, 0xe5, 0x3c, 0x5e, 0xb0, + 0x82, 0x36, 0x6d, 0x4e, 0x63, 0x6d, 0x12, 0xd4, 0x73, 0x58, 0x6a, 0x7b, 0x52, 0xa9, 0x10, 0x7b, 0x7c, 0x26, 0xa2, + 0x6b, 0x6d, 0x68, 0x00, 0x28, 0x50, 0x4a, 0x2e, 0x7e, 0xf3, 0xe5, 0x1e, 0x6e, 0x0a, 0xfa, 0x9f, 0x6d, 0x4c, 0xb4, + 0xb3, 0x5c, 0x1d, 0x7a, 0xf3, 0x05, 0x8d, 0xf3, 0x1c, 0x42, 0xb1, 0x19, 0x04, 0x72, 0x91, 0x55, 0x10, 0xd1, 0xe2, + 0x2e, 0x30, 0x21, 0xe1, 0xa0, 0x4d, 0xbf, 0x42, 0x6a, 0x43, 0x4c, 0xae, 0x3c, 0x31, 0xb0, 0xdb, 0x2a, 0x41, 0xc0, + 0x91, 0x9e, 0x67, 0x9f, 0x9a, 0x18, 0x6b, 0x9a, 0x9a, 0x99, 0x78, 0x1b, 0x0a, 0xd1, 0xa0, 0x05, 0xd1, 0x0c, 0xde, + 0x3f, 0x57, 0x1c, 0xaf, 0x3a, 0xf0, 0x03, 0xde, 0xb9, 0x38, 0xf3, 0x6a, 0xe6, 0x11, 0x39, 0xf5, 0x51, 0x8e, 0xe8, + 0x97, 0x3c, 0xac, 0x46, 0x3a, 0x19, 0x63, 0x25, 0x71, 0xd0, 0xdb, 0x60, 0xc1, 0x9c, 0xd0, 0x15, 0x0f, 0x2d, 0x1f, + 0xff, 0x0a, 0x99, 0x8c, 0x92, 0x1a, 0x2b, 0xba, 0xd2, 0x62, 0xc4, 0x79, 0x0d, 0xb3, 0x34, 0x59, 0xd1, 0xc5, 0x42, + 0x93, 0x66, 0xa1, 0x4c, 0x03, 0x7c, 0x02, 0x2d, 0x46, 0xee, 0xa1, 0xa6, 0x0d, 0x84, 0x86, 0xdd, 0x21, 0xe0, 0x23, + 0xf7, 0xd0, 0xe1, 0xff, 0xe7, 0xd9, 0x05, 0x22, 0xed, 0xcd, 0x4d, 0x64, 0x3c, 0x52, 0x37, 0x70, 0x50, 0x8c, 0x8f, + 0x7d, 0x33, 0xf1, 0x0b, 0x67, 0xf4, 0x21, 0xa9, 0x7c, 0x87, 0x0f, 0x96, 0x3f, 0xde, 0xd4, 0xcc, 0xca, 0x08, 0xd6, + 0xc3, 0x76, 0x8b, 0x0b, 0xa2, 0xed, 0x02, 0x48, 0x3d, 0xe3, 0xd5, 0xc2, 0x37, 0x5e, 0x8d, 0xef, 0x31, 0x5e, 0x75, + 0x67, 0x6a, 0x98, 0x93, 0x0d, 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, 0x6e, + 0xb7, 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, 0x5f, 0xc4, 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, 0x21, 0xbb, 0xe2, 0x65, 0x15, 0x5f, 0xad, 0x8c, 0x25, 0x31, + 0x67, 0xf7, 0xb9, 0xed, 0x51, 0x61, 0x5e, 0xbd, 0x7d, 0xf9, 0xfd, 0x71, 0xe3, 0xd5, 0x2e, 0xe2, 0x68, 0x08, 0xb6, + 0x15, 0x63, 0x8c, 0xde, 0xe2, 0xd3, 0x60, 0xa2, 0x5c, 0x23, 0xd0, 0xbb, 0x14, 0xf4, 0xdb, 0x5f, 0xea, 0x09, 0x78, + 0xc5, 0xf5, 0xf2, 0x4b, 0x3e, 0x02, 0x96, 0xa8, 0xd0, 0xb3, 0xc2, 0xdc, 0xac, 0xcc, 0xee, 0xed, 0x56, 0x64, 0xa6, + 0x5d, 0x69, 0x64, 0x20, 0x5e, 0x6d, 0x87, 0xb1, 0x70, 0xe9, 0x9a, 0x6e, 0x07, 0xbb, 0x5a, 0x7a, 0x96, 0xc8, 0xdb, + 0x6d, 0x09, 0x1d, 0xb2, 0x03, 0xee, 0xbd, 0x8c, 0x6f, 0xe1, 0x65, 0xe9, 0x75, 0xb3, 0x19, 0x3c, 0x01, 0xcc, 0x84, + 0x0b, 0x67, 0x59, 0x1c, 0x33, 0x9e, 0x84, 0x2a, 0x36, 0x57, 0x43, 0xe4, 0xad, 0x08, 0xad, 0xd9, 0x5f, 0xa1, 0x18, + 0x81, 0xdd, 0xc9, 0xe9, 0xc7, 0x6c, 0x35, 0x5b, 0x02, 0x6a, 0xfe, 0x55, 0x26, 0x80, 0xe6, 0xda, 0xb5, 0x60, 0x9b, + 0x42, 0x9b, 0xeb, 0xfa, 0x79, 0xbc, 0x8a, 0x13, 0x50, 0xdd, 0x80, 0xb7, 0xc8, 0x9d, 0x16, 0x5d, 0x19, 0x74, 0x51, + 0xfa, 0x40, 0x39, 0x96, 0x14, 0x3a, 0xfa, 0xde, 0x13, 0xea, 0xdc, 0x33, 0x80, 0x4b, 0x1a, 0x35, 0x4f, 0xb5, 0x94, + 0xb1, 0x00, 0x58, 0xe8, 0x60, 0xa6, 0xc8, 0x56, 0x74, 0x6b, 0x30, 0x29, 0xe0, 0xad, 0x01, 0xfe, 0x10, 0x59, 0xa5, + 0xee, 0x8a, 0x65, 0x58, 0x7a, 0xf6, 0xd7, 0xfd, 0x7e, 0xec, 0xd9, 0x5f, 0x5f, 0x68, 0x5a, 0x17, 0xb7, 0x1b, 0x40, + 0x6a, 0x0c, 0x20, 0x72, 0xac, 0x07, 0xc2, 0x44, 0x14, 0x6b, 0xfa, 0xfe, 0x1d, 0x9b, 0x2c, 0x0a, 0x84, 0x7e, 0xa7, + 0x5e, 0x4f, 0x4a, 0x02, 0x3a, 0xb5, 0x8a, 0x1d, 0x0d, 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, + 0xfb, 0xbf, 0x99, 0x2c, 0x08, 0x6a, 0xae, 0xfc, 0x40, 0x8e, 0x3b, 0x99, 0x1a, 0x7b, 0xaa, 0x51, 0x83, 0x60, 0x32, + 0x82, 0xc0, 0x70, 0xc3, 0x2f, 0xf8, 0xf8, 0x60, 0x41, 0x40, 0x45, 0x66, 0xcd, 0x42, 0xcc, 0x8b, 0xc3, 0x27, 0x80, + 0x1a, 0x33, 0x3a, 0x78, 0x06, 0xa0, 0xb0, 0x10, 0x10, 0x7d, 0x0c, 0x32, 0x5a, 0x01, 0xbf, 0x85, 0xfa, 0xdd, 0x3a, + 0xf1, 0x7d, 0xe8, 0x57, 0x41, 0x2f, 0x62, 0x60, 0x38, 0xa2, 0xc9, 0x7e, 0xc8, 0x07, 0x93, 0x01, 0x68, 0x4b, 0xbc, + 0xdd, 0xd7, 0xd2, 0x8a, 0x9b, 0xd3, 0xa5, 0xd3, 0xfd, 0x93, 0x36, 0x41, 0x12, 0xa9, 0x64, 0xa5, 0x22, 0x06, 0x10, + 0xca, 0x52, 0x6d, 0x93, 0x25, 0x58, 0x56, 0x98, 0x25, 0xcd, 0x0d, 0x4a, 0xe2, 0xee, 0x66, 0xe0, 0x18, 0x35, 0xeb, + 0x38, 0x2c, 0x5b, 0x6e, 0xd4, 0x00, 0x9f, 0x93, 0xb0, 0xc2, 0xde, 0x70, 0x66, 0xd2, 0x3b, 0xd3, 0xe1, 0xea, 0x98, + 0xb3, 0x37, 0x1c, 0xc1, 0x38, 0x12, 0xbc, 0xf1, 0xd0, 0x25, 0xd3, 0x50, 0x91, 0x29, 0xe3, 0x60, 0xda, 0x03, 0xdc, + 0x7b, 0x0e, 0xc6, 0x61, 0x6c, 0x50, 0x59, 0x52, 0x9f, 0x7a, 0x77, 0x21, 0x10, 0xa4, 0xb5, 0x5e, 0xe6, 0x33, 0x3c, + 0x3d, 0x23, 0x94, 0xfd, 0x21, 0x87, 0x2f, 0xc0, 0x8e, 0x82, 0x1c, 0x4d, 0xf8, 0xb3, 0xc7, 0xbb, 0x81, 0xaa, 0xf8, + 0x20, 0xd8, 0x8b, 0x45, 0xba, 0x17, 0x0c, 0x04, 0xfc, 0x2a, 0xf8, 0x5e, 0x25, 0xe5, 0xde, 0x45, 0x5c, 0xec, 0xc5, + 0xab, 0xb8, 0xa8, 0xf6, 0x6e, 0xb2, 0x6a, 0xb9, 0x67, 0x3a, 0x04, 0xd0, 0xbc, 0xc1, 0x20, 0x1e, 0x04, 0x7b, 0xc1, + 0xa0, 0x30, 0x53, 0xbb, 0x62, 0x65, 0xe3, 0x38, 0x33, 0x21, 0xca, 0x82, 0x66, 0x80, 0xb0, 0xc6, 0x69, 0x00, 0x7c, + 0xea, 0x9a, 0xa5, 0xf4, 0x02, 0xc3, 0x0d, 0x88, 0xe9, 0x1a, 0xfa, 0x00, 0x3c, 0xf2, 0x9a, 0xc6, 0xb0, 0x04, 0x2e, + 0x06, 0x03, 0xb2, 0x86, 0xc8, 0x05, 0x6b, 0x6a, 0x83, 0x38, 0x84, 0x6b, 0x65, 0xa7, 0xbd, 0x0b, 0xcc, 0xb4, 0xdd, + 0x02, 0xa2, 0xf2, 0x84, 0xf4, 0xfb, 0xf6, 0x1b, 0xea, 0x5f, 0xb0, 0x97, 0x60, 0x7f, 0x55, 0x54, 0x61, 0x22, 0x95, + 0xe6, 0xfb, 0x92, 0x1d, 0x0d, 0x54, 0xc4, 0xe1, 0x1d, 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, 0xaf, 0x34, 0xbb, 0xf4, 0x30, 0x90, 0x32, + 0x6e, 0x0f, 0x2d, 0x61, 0xd2, 0xf2, 0x22, 0xbc, 0xf7, 0x9a, 0x9b, 0xdc, 0x8b, 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, 0xcf, 0x74, 0x17, 0x80, 0xd1, 0x2f, 0x66, 0x69, 0xb4, 0xbc, 0xd7, 0xcc, 0x02, 0xc9, 0x33, 0xf4, 0x5d, + 0x07, 0xdb, 0x1b, 0xfb, 0x20, 0xe5, 0xfc, 0x50, 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, 0x3f, 0x91, 0x6f, 0x72, 0x07, 0x5d, 0x2e, 0xc7, + 0x9a, 0xb7, 0x1c, 0x80, 0x8a, 0x7e, 0xa4, 0xa8, 0xee, 0x17, 0x38, 0xc2, 0x3c, 0x58, 0xb7, 0xf9, 0x64, 0xdf, 0x14, + 0x38, 0x44, 0x9e, 0xb4, 0xd1, 0x14, 0xd0, 0xbd, 0x8b, 0xc7, 0x5d, 0xfd, 0xb6, 0x74, 0x17, 0x28, 0xd1, 0x4e, 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, + 0xeb, 0x33, 0x8e, 0xa2, 0x1f, 0xa3, 0x46, 0xbe, 0x89, 0xc4, 0x63, 0x39, 0x88, 0x1f, 0x17, 0x74, 0x19, 0x89, 0xc7, + 0xc5, 0x20, 0x7e, 0x2c, 0xeb, 0x7a, 0xf7, 0x5c, 0xb9, 0xbf, 0x8f, 0xc8, 0xb3, 0xee, 0xec, 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, 0xfd, 0x62, 0x74, 0xe3, 0xbb, 0xeb, 0xef, 0x17, 0xa3, 0x25, 0x19, 0x4e, 0xcc, 0xe4, 0xc7, 0x47, 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, 0xdf, 0xab, 0x76, 0xb4, 0x69, 0x6f, 0xe2, 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, 0x4d, 0xd9, 0xfc, 0x2a, 0xda, 0xe7, 0xc8, 0x48, + 0xd9, 0x26, 0x23, 0x15, 0x18, 0x61, 0x4a, 0x91, 0xc4, 0x55, 0x08, 0x81, 0xec, 0xbf, 0xa4, 0xb8, 0x16, 0x4b, 0xef, + 0x35, 0x08, 0x13, 0x6c, 0x17, 0xb4, 0x5f, 0xdd, 0xce, 0x6d, 0xa5, 0xc5, 0x1e, 0xa9, 0xef, 0x73, 0x67, 0xbb, 0xa2, + 0xc9, 0xdf, 0x97, 0x0d, 0x68, 0x03, 0x88, 0xf2, 0xbe, 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, 0x80, + 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, 0x53, 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, 0x11, 0xcb, 0xe6, 0x62, 0x31, 0x5a, 0x49, 0x08, 0x1b, 0x7c, 0xc8, 0xb2, 0x79, 0xa9, + 0x1f, 0x42, 0x5f, 0x58, 0x7a, 0x02, 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, 0x23, 0xd4, + 0xfe, 0x7e, 0x1e, 0xc5, 0x5a, 0x2e, 0xb9, 0x72, 0x7e, 0xf1, 0x37, 0x9f, 0xb1, 0xd7, 0x3d, 0xc3, 0x60, 0x01, 0xce, + 0xd2, 0xf6, 0x2a, 0x13, 0xef, 0x64, 0x2b, 0x38, 0x0e, 0x66, 0x51, 0x0e, 0xab, 0x9e, 0x1c, 0xd1, 0x5c, 0xe4, 0xda, + 0xbb, 0x08, 0x91, 0x83, 0xcc, 0x1e, 0x03, 0xec, 0x46, 0xf8, 0x3a, 0xb4, 0x36, 0xb7, 0xba, 0x42, 0xfc, 0x8d, 0x12, + 0x89, 0x9f, 0xa5, 0xfc, 0xb8, 0x5e, 0xa9, 0x5c, 0x95, 0xc1, 0x63, 0xd5, 0xcd, 0xe0, 0x99, 0xf6, 0x3d, 0xd6, 0xfe, + 0xad, 0xed, 0xe6, 0x78, 0xef, 0xc1, 0x83, 0xd6, 0xff, 0xd6, 0x93, 0x10, 0xda, 0x2b, 0x27, 0xa9, 0x3b, 0x6a, 0xf4, + 0xcc, 0x64, 0x8d, 0xa8, 0x84, 0xa9, 0xdd, 0xa9, 0x1c, 0x03, 0x35, 0x1d, 0xc0, 0xb5, 0x44, 0x4d, 0xd0, 0x93, 0x82, + 0x8d, 0xe1, 0x88, 0xb3, 0x38, 0x68, 0x87, 0x31, 0x8a, 0x97, 0x73, 0x25, 0x5e, 0xce, 0x8f, 0x18, 0x07, 0x68, 0x2d, + 0x40, 0xaa, 0xd7, 0xb0, 0x9f, 0xb9, 0x82, 0x05, 0x36, 0x77, 0xbe, 0x03, 0x0b, 0x64, 0x88, 0x93, 0xcd, 0x71, 0xb2, + 0xc7, 0xb5, 0x9e, 0x7b, 0x81, 0x8f, 0x93, 0x7a, 0xe1, 0xd5, 0x55, 0xb6, 0xeb, 0x5a, 0xb2, 0x72, 0x5e, 0x0c, 0x26, + 0x10, 0x94, 0xa5, 0x9c, 0x17, 0xc3, 0xc9, 0x82, 0xe6, 0xf0, 0x63, 0xd1, 0x40, 0x87, 0x58, 0x0e, 0x12, 0xb8, 0x74, + 0xf6, 0x18, 0xf0, 0x86, 0x52, 0x8b, 0xbb, 0xb1, 0x8e, 0x1c, 0xeb, 0x28, 0xf6, 0xc3, 0x18, 0x70, 0x65, 0x9d, 0xc0, + 0xfb, 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, 0x1d, 0x95, 0x43, + 0x2d, 0x84, 0xeb, 0x5a, 0x78, 0x1d, 0xa7, 0x65, 0x0c, 0x2e, 0xd2, 0xda, 0x36, 0xf1, 0x1e, 0xba, 0xee, 0xf9, 0x31, + 0xb7, 0x3a, 0x46, 0x5b, 0x48, 0xbf, 0x1d, 0x9d, 0xde, 0x73, 0x18, 0x80, 0xa6, 0x07, 0xb3, 0xaa, 0x7d, 0x26, 0x71, + 0x73, 0xda, 0x09, 0x42, 0x22, 0x10, 0x45, 0xe9, 0x8c, 0x30, 0xfd, 0x3b, 0xcd, 0x65, 0x15, 0xad, 0x1e, 0xe4, 0x99, + 0x43, 0x9e, 0x85, 0xde, 0xf6, 0xa0, 0x55, 0x73, 0x37, 0x18, 0x27, 0x6e, 0xb7, 0x77, 0xfe, 0xdf, 0xb2, 0xae, 0xad, + 0xd6, 0x88, 0xc7, 0xed, 0xea, 0x07, 0x8d, 0xbd, 0xda, 0x53, 0x31, 0x60, 0x56, 0xd2, 0x3b, 0xa3, 0x4a, 0x5e, 0x64, + 0xbc, 0xc4, 0x93, 0x6a, 0xd5, 0xf0, 0xf1, 0xbe, 0xc9, 0x46, 0xe6, 0x81, 0x4c, 0x01, 0xf1, 0xfc, 0x26, 0x35, 0xea, + 0xe3, 0x14, 0x25, 0xe0, 0xef, 0x74, 0x7c, 0x23, 0xfa, 0xd1, 0xbe, 0xb8, 0xe4, 0xd5, 0xc9, 0x8d, 0x30, 0x2f, 0x5e, + 0x58, 0x9d, 0x3f, 0x7d, 0x53, 0xf8, 0xd0, 0xe1, 0xa8, 0xbd, 0x83, 0x22, 0x4b, 0x26, 0x8e, 0x26, 0x46, 0xd6, 0x26, + 0x66, 0x1f, 0x15, 0x5c, 0x4c, 0x54, 0xa1, 0x67, 0x9d, 0x3d, 0x61, 0x0a, 0xd0, 0x37, 0x8e, 0x51, 0xc9, 0x18, 0x16, + 0x0c, 0xd4, 0x69, 0x4a, 0x88, 0x1e, 0x8a, 0x19, 0xc6, 0x2b, 0x06, 0x50, 0x98, 0x42, 0x81, 0x28, 0x3a, 0xfb, 0x70, + 0xa0, 0x09, 0xfd, 0xfe, 0x4d, 0xaa, 0x33, 0xd0, 0xb2, 0x9e, 0x4a, 0x10, 0xd5, 0x41, 0xb4, 0x55, 0x5e, 0x84, 0x3f, + 0x2e, 0x69, 0x99, 0xd1, 0xa5, 0xa0, 0xa9, 0xa0, 0x49, 0x46, 0x2f, 0xb8, 0x12, 0x15, 0x5f, 0x08, 0xa6, 0x68, 0xbb, + 0x21, 0xec, 0xff, 0x6a, 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, 0x9d, 0xae, 0xcf, 0x9f, 0xcb, 0xab, 0x95, 0x14, 0x5c, 0x54, 0x0a, 0xa2, 0xdf, 0xe0, 0xbe, 0x9b, 0xb8, + 0xea, 0xac, 0x59, 0x2b, 0x7d, 0xe8, 0x5b, 0x9f, 0xb5, 0x71, 0x5f, 0x18, 0x1c, 0x83, 0x9d, 0x8f, 0x88, 0x81, 0x34, + 0xa8, 0x74, 0x8b, 0x43, 0x13, 0xa0, 0x4b, 0x87, 0x14, 0xb2, 0x64, 0x2a, 0x53, 0x25, 0xa8, 0xf8, 0xc6, 0xef, 0xa5, + 0xac, 0x46, 0x7f, 0xad, 0x79, 0x71, 0x77, 0xca, 0x73, 0x8e, 0x63, 0x14, 0x24, 0xb1, 0xb8, 0x8e, 0xcb, 0x80, 0xf8, + 0x96, 0x57, 0xc1, 0x41, 0x6a, 0xc2, 0xc6, 0xec, 0x54, 0x8d, 0x5a, 0x2f, 0x89, 0xbe, 0x32, 0xca, 0x37, 0x06, 0x43, + 0x13, 0x51, 0x05, 0x7d, 0xaf, 0xd5, 0x3d, 0xad, 0x6e, 0x58, 0x40, 0xfc, 0xb9, 0xd2, 0x0b, 0xb5, 0x5e, 0x37, 0x63, + 0x6e, 0x98, 0x08, 0x41, 0xa3, 0x27, 0xf5, 0xa2, 0xf6, 0xdc, 0xd2, 0x54, 0x64, 0xdc, 0x68, 0x93, 0xf3, 0x4b, 0x90, + 0xf1, 0x39, 0x73, 0xa1, 0x49, 0x5d, 0x53, 0x05, 0x55, 0x18, 0x6d, 0x6e, 0x1b, 0xe9, 0xf4, 0x0e, 0xdc, 0xd9, 0x8c, + 0xd9, 0x91, 0x76, 0x69, 0xac, 0x69, 0xc1, 0xcb, 0x95, 0x14, 0x25, 0x84, 0x71, 0xee, 0x8d, 0xe9, 0x55, 0x9c, 0x89, + 0x2a, 0xce, 0xc4, 0x71, 0xb9, 0xe2, 0x49, 0xf5, 0x1e, 0x6e, 0x71, 0xca, 0xea, 0xa6, 0x2e, 0xe1, 0x4a, 0x97, 0xec, + 0x61, 0x30, 0x35, 0x15, 0xf7, 0xd8, 0x19, 0x5c, 0x54, 0x7f, 0x44, 0x4b, 0x89, 0xb1, 0x50, 0x75, 0xf1, 0xf1, 0x79, + 0x29, 0xf3, 0x75, 0x05, 0xda, 0xdd, 0x8b, 0x2a, 0x3a, 0x78, 0xba, 0xba, 0x9d, 0xaa, 0x1b, 0x4c, 0xf4, 0xf4, 0x60, + 0x75, 0xdb, 0xcb, 0xae, 0x56, 0xb2, 0xa8, 0x62, 0x51, 0x4d, 0x15, 0x22, 0x59, 0x12, 0xe7, 0x49, 0x38, 0x19, 0x8f, + 0xbf, 0xda, 0x1b, 0xee, 0x41, 0x06, 0x32, 0xfd, 0x34, 0x54, 0x2e, 0x47, 0xc3, 0xc9, 0x78, 0x3c, 0x95, 0xea, 0x6e, + 0x17, 0x8d, 0x26, 0x35, 0xd6, 0x33, 0x4c, 0xf4, 0xcc, 0x8c, 0xf8, 0xed, 0x2a, 0x16, 0x29, 0xc4, 0xaf, 0xd3, 0xc5, + 0x1f, 0x3c, 0x1d, 0x37, 0xca, 0xb7, 0x9f, 0x3e, 0xab, 0xff, 0xa8, 0x4d, 0x58, 0x6b, 0xd3, 0xee, 0xe7, 0x7f, 0x1c, + 0xaa, 0xf9, 0x3e, 0x3a, 0xdc, 0xd7, 0x3f, 0xfe, 0xa8, 0xeb, 0xe9, 0x9b, 0x22, 0x9c, 0xff, 0x33, 0x54, 0xf3, 0x79, + 0x5c, 0x14, 0xf1, 0x5d, 0x0d, 0x91, 0x3c, 0x85, 0xf3, 0x26, 0xa1, 0xde, 0x36, 0xa0, 0x07, 0x64, 0x7a, 0x21, 0x18, + 0x7c, 0xf3, 0xbe, 0x0a, 0x03, 0x5e, 0xae, 0x86, 0x5c, 0x54, 0x59, 0x75, 0x37, 0xc4, 0x3c, 0x01, 0x7e, 0x6a, 0x78, + 0xb3, 0xe7, 0x85, 0x21, 0x36, 0x17, 0x05, 0xe7, 0x9f, 0x78, 0xa8, 0x8c, 0xa3, 0xc7, 0x68, 0x1c, 0x3d, 0xa6, 0x6a, + 0x30, 0x26, 0xdf, 0x50, 0xdd, 0x99, 0xc9, 0x37, 0x60, 0x82, 0x94, 0xb5, 0xbf, 0x51, 0xc6, 0x89, 0xd1, 0x98, 0x5e, + 0xbf, 0xca, 0xb3, 0x15, 0x30, 0xc1, 0x4b, 0xfd, 0xa3, 0x26, 0xf4, 0x3d, 0x6f, 0x67, 0x1f, 0x8d, 0x46, 0xcf, 0x0b, + 0x3a, 0x1a, 0x8d, 0x3e, 0x66, 0x35, 0xa1, 0x2b, 0xd1, 0xf1, 0xfe, 0x3d, 0xa7, 0xe7, 0x32, 0xbd, 0x8b, 0x82, 0x80, + 0x2e, 0xb3, 0x34, 0xe5, 0x42, 0x95, 0x75, 0x9a, 0xb6, 0xf3, 0xaa, 0x16, 0x22, 0xf0, 0x8f, 0x6e, 0x23, 0x42, 0x10, + 0x11, 0x7a, 0xb2, 0xd3, 0xb3, 0xd1, 0x68, 0x74, 0x9a, 0x9a, 0x6a, 0x1d, 0x43, 0xfe, 0x06, 0xcd, 0x07, 0x9c, 0x5d, + 0x3e, 0x58, 0xdf, 0x98, 0x68, 0x27, 0xfb, 0xff, 0x3d, 0x9c, 0xcd, 0xc7, 0xc3, 0x6f, 0x47, 0x8b, 0xc7, 0xfb, 0x34, + 0x08, 0x7c, 0xd0, 0xea, 0x50, 0x5b, 0x73, 0x4c, 0xcb, 0xc3, 0xf1, 0x94, 0x94, 0x03, 0xf6, 0xd4, 0xfa, 0xd2, 0x7c, + 0xf5, 0x14, 0x90, 0x48, 0x51, 0x84, 0x1a, 0x38, 0xe9, 0x1f, 0x5e, 0x45, 0x5e, 0x0b, 0xc0, 0x47, 0xb3, 0x91, 0x0c, + 0x8c, 0x16, 0x70, 0x1c, 0x41, 0x79, 0xb5, 0x35, 0x8d, 0xe8, 0x31, 0x96, 0x99, 0xa8, 0xa0, 0xe3, 0x69, 0x79, 0x93, + 0x55, 0xc9, 0x12, 0x03, 0x1b, 0xc5, 0x25, 0x0f, 0xbe, 0x0a, 0xa2, 0x92, 0x1d, 0x3c, 0x9b, 0x2a, 0x78, 0x5f, 0x4c, + 0x4a, 0xf9, 0x25, 0x24, 0x7e, 0x3b, 0x46, 0x08, 0x54, 0xa2, 0x3d, 0x16, 0xb1, 0xc6, 0x57, 0xb9, 0x8c, 0xc1, 0x83, + 0xb3, 0xd4, 0x3c, 0x8b, 0x3d, 0x09, 0xac, 0xfd, 0x45, 0xab, 0x39, 0x12, 0x9a, 0x13, 0x4a, 0x26, 0xf7, 0x4b, 0x2a, + 0xbf, 0x9a, 0xa0, 0x57, 0x10, 0xb8, 0x55, 0x47, 0x70, 0xdc, 0x59, 0xcb, 0x06, 0xbd, 0x7c, 0x52, 0xb6, 0x3f, 0xff, + 0xdf, 0x25, 0x5d, 0x0c, 0xf6, 0xdd, 0xd0, 0x9c, 0x68, 0xf7, 0xd5, 0x0a, 0x19, 0xa5, 0x2a, 0x7c, 0x9e, 0x12, 0x6b, + 0x7c, 0xca, 0xd9, 0xd1, 0xc6, 0x74, 0x67, 0x54, 0x15, 0xd9, 0x55, 0x48, 0x74, 0xaf, 0x1c, 0x28, 0x66, 0x10, 0x65, + 0x23, 0x5c, 0x3f, 0x60, 0x2d, 0xe2, 0x75, 0xf2, 0x9a, 0x17, 0x55, 0x96, 0xa8, 0xf7, 0xd7, 0x8d, 0xf7, 0x40, 0x0d, + 0x54, 0x83, 0xde, 0x15, 0x0c, 0xe6, 0xf9, 0xa4, 0x00, 0xd0, 0xce, 0x92, 0x17, 0xd7, 0xdc, 0xa7, 0x1b, 0x41, 0x50, + 0xbb, 0x66, 0x5e, 0x36, 0x82, 0x4d, 0xc0, 0x57, 0xef, 0x0a, 0xc0, 0xdc, 0x08, 0x41, 0x6a, 0x0a, 0xa1, 0x70, 0xe0, + 0x02, 0x5f, 0x55, 0x45, 0x76, 0xbe, 0xae, 0x38, 0x06, 0xfb, 0xf0, 0xe2, 0x26, 0x2a, 0x27, 0x3c, 0x1e, 0x06, 0xf8, + 0x23, 0xa0, 0x2a, 0xe0, 0x86, 0xf1, 0xb0, 0x83, 0x17, 0xea, 0x97, 0x7b, 0xa3, 0xf6, 0x08, 0x7b, 0x93, 0x86, 0x10, + 0x5c, 0x07, 0x1f, 0x02, 0x58, 0x52, 0x84, 0x9e, 0xe0, 0xa9, 0x1a, 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, 0x28, 0xef, + 0xf4, 0xc4, 0xb8, 0x30, 0x7d, 0x1c, 0x22, 0xbf, 0xbc, 0x2b, 0x54, 0xe8, 0x17, 0xbe, 0x00, 0xf0, 0x2b, 0xb8, 0xdd, + 0xef, 0xc6, 0x77, 0x51, 0xd9, 0xcf, 0x38, 0xdb, 0xff, 0xef, 0x79, 0x3c, 0xfc, 0x34, 0x1e, 0x7e, 0xbb, 0x18, 0x84, + 0x43, 0xfb, 0x93, 0x3c, 0x7e, 0xb4, 0x4f, 0x5f, 0x71, 0xcb, 0x95, 0xc0, 0xc2, 0x6f, 0x04, 0xb7, 0x51, 0x2b, 0x21, + 0x88, 0x02, 0xbc, 0x51, 0xb8, 0xd5, 0x38, 0x01, 0x80, 0xbf, 0xe0, 0xbf, 0x02, 0x34, 0x12, 0x72, 0x17, 0x0d, 0xd0, + 0x0f, 0xa8, 0xdf, 0x47, 0x4f, 0x1a, 0x06, 0x72, 0x20, 0x9e, 0x50, 0x31, 0x50, 0x88, 0x2e, 0x63, 0xa2, 0x60, 0x7f, + 0x6d, 0xf6, 0xed, 0xb6, 0xd7, 0x96, 0xfc, 0xe0, 0x97, 0x7e, 0xa6, 0x89, 0x99, 0x77, 0xb8, 0xa1, 0xac, 0xe4, 0x2a, + 0x44, 0x6c, 0x3c, 0xfd, 0x2b, 0x67, 0x10, 0x6b, 0xf2, 0x3a, 0x03, 0x1f, 0x06, 0xfb, 0xc5, 0x78, 0x06, 0x6c, 0x03, + 0xdc, 0x71, 0x0a, 0x7e, 0x91, 0x81, 0x5b, 0xb3, 0x88, 0xf1, 0x82, 0x6d, 0x97, 0x44, 0xbf, 0xdf, 0xcb, 0xb3, 0x30, + 0xd7, 0x38, 0xcb, 0x79, 0x6d, 0xc4, 0xee, 0xa8, 0x13, 0x06, 0x71, 0xbb, 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, 0xb8, 0x2e, 0xb3, 0x5e, 0x2f, 0x0c, 0xd1, 0xa1, 0x11, 0x4b, 0xc5, + 0xda, 0x20, 0xbc, 0x8f, 0x49, 0x18, 0x5d, 0x81, 0xac, 0x2e, 0x3c, 0xe3, 0x04, 0xf9, 0x32, 0x30, 0x59, 0x53, 0xd5, + 0x7a, 0x39, 0xe1, 0xb1, 0x91, 0x2f, 0x1b, 0x41, 0x83, 0xbc, 0xa4, 0xa8, 0x37, 0x71, 0x3b, 0xf6, 0x51, 0x0b, 0xa9, + 0x71, 0x53, 0x4f, 0x7b, 0x9a, 0x54, 0xf4, 0x58, 0xaf, 0x52, 0xbf, 0xc0, 0xb2, 0xc0, 0x92, 0x0f, 0x42, 0x7b, 0x9a, + 0x56, 0x60, 0x86, 0x6b, 0x9b, 0xc1, 0xd0, 0x0f, 0x87, 0xb6, 0x08, 0x9d, 0x51, 0xdb, 0x12, 0xc2, 0xb6, 0x0d, 0xc2, + 0xca, 0x7b, 0x22, 0x5f, 0x3d, 0xf5, 0x18, 0xe1, 0x90, 0x9b, 0xcd, 0x2c, 0x1a, 0x18, 0xe6, 0x57, 0xb2, 0xd9, 0x3c, + 0xdd, 0x5c, 0x2f, 0x2a, 0xa6, 0x80, 0xed, 0xb6, 0x12, 0x04, 0xff, 0x7e, 0xcc, 0x66, 0xf8, 0x37, 0xeb, 0xf7, 0x7b, + 0x21, 0xfe, 0xe2, 0x18, 0xbc, 0x67, 0x2e, 0x16, 0xec, 0x23, 0xc8, 0x54, 0x48, 0x84, 0xa9, 0xca, 0xf8, 0x8d, 0x55, + 0x60, 0x01, 0x67, 0x3e, 0x50, 0xb9, 0x30, 0x93, 0xbd, 0xbc, 0xb8, 0x86, 0x1c, 0xb7, 0xc6, 0x29, 0x1b, 0x65, 0x89, + 0x72, 0x5d, 0xc8, 0x46, 0x71, 0x9e, 0xc5, 0x25, 0x2f, 0xb7, 0x5b, 0x7d, 0x38, 0x26, 0x05, 0x07, 0xf6, 0x54, 0x51, + 0xa9, 0x92, 0x75, 0xa4, 0xba, 0xf1, 0x97, 0x61, 0x81, 0xfb, 0x94, 0xcf, 0x0b, 0x43, 0x23, 0xf6, 0xe0, 0xf2, 0xce, + 0xd4, 0xad, 0xb4, 0x17, 0x16, 0xd0, 0xbc, 0x92, 0x90, 0x0d, 0xa6, 0x7a, 0x16, 0xad, 0x31, 0x13, 0xf3, 0x62, 0x01, + 0x61, 0x64, 0x8a, 0x05, 0xd8, 0x4c, 0x71, 0x01, 0x5e, 0x24, 0x31, 0xc0, 0xc4, 0xc5, 0x64, 0x0a, 0xf1, 0xcc, 0x55, + 0x39, 0xf1, 0xc2, 0xdc, 0x2f, 0x13, 0x87, 0x94, 0x01, 0xaf, 0x6a, 0x83, 0x26, 0x66, 0x1b, 0x8e, 0x3a, 0x41, 0x4e, + 0x4c, 0x7e, 0x3f, 0x55, 0x10, 0xe2, 0x4e, 0x1c, 0x09, 0x97, 0x15, 0xdb, 0x85, 0x97, 0x1d, 0x88, 0x31, 0x6a, 0x70, + 0xca, 0xcf, 0x0c, 0x8e, 0xc6, 0xe0, 0xdc, 0x78, 0x27, 0x48, 0x11, 0xc6, 0x64, 0x23, 0xd9, 0x95, 0x0c, 0xc5, 0x3c, + 0x5e, 0x80, 0xb2, 0x2e, 0x5e, 0x80, 0x65, 0x8d, 0x31, 0xc0, 0x04, 0x79, 0x15, 0xf7, 0x42, 0x3f, 0x51, 0x5c, 0x21, + 0xd2, 0xb3, 0x72, 0x7d, 0x54, 0xb4, 0x43, 0x5f, 0xe0, 0xf5, 0x5e, 0x99, 0xe3, 0x66, 0x3d, 0x16, 0x48, 0x6c, 0x08, + 0x18, 0x1b, 0xe9, 0x34, 0xd5, 0x5a, 0xf7, 0xc6, 0xcc, 0x03, 0x9f, 0x66, 0x23, 0x21, 0xab, 0xb3, 0x0b, 0x10, 0xa1, + 0xf8, 0x68, 0xf0, 0xc8, 0x2f, 0xe2, 0xce, 0x32, 0x6f, 0x6d, 0x8b, 0x4a, 0x76, 0xb4, 0x01, 0x90, 0x3e, 0x1d, 0x2d, + 0x4a, 0xc9, 0x29, 0x4a, 0x52, 0xbb, 0x4d, 0x01, 0x2b, 0xc9, 0x5f, 0xc0, 0x10, 0x6c, 0x6c, 0x4f, 0x38, 0x9d, 0x22, + 0xc4, 0x27, 0x9a, 0x22, 0xb2, 0x62, 0x58, 0x52, 0x1c, 0xdb, 0x12, 0x51, 0x3f, 0x6d, 0x59, 0x76, 0x30, 0x4c, 0x54, + 0xdc, 0x17, 0xa9, 0x47, 0x89, 0x82, 0x80, 0xea, 0x21, 0x07, 0x89, 0xad, 0x6d, 0x20, 0x3c, 0x20, 0x8f, 0xe8, 0x8d, + 0xf5, 0xf7, 0x59, 0xe7, 0xd9, 0x85, 0xe6, 0xa8, 0x5c, 0xef, 0x0a, 0x33, 0x46, 0x78, 0x92, 0x19, 0x98, 0x7c, 0xef, + 0x3c, 0x33, 0x6a, 0x8a, 0x9e, 0x87, 0x4f, 0x76, 0x8c, 0x11, 0xe9, 0xee, 0x19, 0x74, 0x13, 0xbc, 0xaa, 0xc3, 0x46, + 0xbb, 0x52, 0x10, 0x12, 0xa6, 0x16, 0x4d, 0xcc, 0x7a, 0xd6, 0x80, 0x7a, 0xbb, 0xed, 0xe9, 0xb9, 0xba, 0x7f, 0xee, + 0xb6, 0xdb, 0x1e, 0x76, 0xeb, 0x45, 0xda, 0x6d, 0x05, 0x5e, 0xa9, 0x0f, 0xda, 0xe3, 0xcf, 0xdd, 0xf8, 0x73, 0x83, + 0xe4, 0x51, 0x3a, 0x9a, 0x69, 0xeb, 0x83, 0x70, 0xb8, 0xe9, 0x5d, 0xa3, 0x49, 0xdf, 0x67, 0xa1, 0xa4, 0x2b, 0xd1, + 0xa8, 0xae, 0x76, 0x26, 0x95, 0x0f, 0xae, 0xff, 0x87, 0x57, 0x01, 0x1e, 0x71, 0x6a, 0x67, 0xdf, 0xdb, 0xa0, 0xa2, + 0xd1, 0x16, 0x8e, 0x14, 0xa1, 0x07, 0x24, 0xe1, 0xbe, 0x96, 0xb5, 0xb8, 0xcd, 0xd3, 0xec, 0x61, 0xfa, 0xf4, 0x3a, + 0xf5, 0xad, 0xee, 0xdd, 0x32, 0xcb, 0xcc, 0x81, 0x57, 0x51, 0x1c, 0xd0, 0xa8, 0x8b, 0xf6, 0x5d, 0x65, 0x65, 0x09, + 0x5e, 0x1e, 0x70, 0x7d, 0x3e, 0xe5, 0x3e, 0xdc, 0xdc, 0x65, 0xd5, 0xdc, 0xa4, 0xa7, 0xd9, 0x3c, 0x5b, 0x6c, 0xb7, + 0x21, 0xfe, 0xed, 0x6a, 0x91, 0xa3, 0xc9, 0x73, 0xd0, 0xe1, 0x61, 0xe4, 0x1e, 0xa6, 0x1b, 0xe7, 0x6d, 0xfe, 0x4f, + 0xa2, 0xe1, 0x24, 0x70, 0x0c, 0xf4, 0x62, 0xf6, 0x08, 0x64, 0x30, 0xc6, 0xa9, 0x5f, 0xcc, 0xf4, 0x9a, 0x81, 0xe8, + 0x5b, 0x22, 0x02, 0x1c, 0x5d, 0x6c, 0x24, 0x1a, 0x59, 0x70, 0x52, 0x13, 0xb0, 0xd8, 0xb4, 0xe5, 0x7d, 0xb0, 0xb4, + 0xad, 0x2a, 0xee, 0xbc, 0x25, 0xcd, 0x71, 0x1d, 0x38, 0xdb, 0x7e, 0x33, 0xc4, 0xa6, 0xec, 0x6a, 0x81, 0xdc, 0x2f, + 0xaf, 0x69, 0x6f, 0x5c, 0x27, 0x30, 0x6b, 0x9b, 0xda, 0x32, 0x7e, 0xb6, 0xf4, 0x9f, 0xf5, 0xe0, 0x2a, 0xe3, 0xa7, + 0xb9, 0xb1, 0x4a, 0xb0, 0xfb, 0xc6, 0xf3, 0x1d, 0x80, 0x70, 0x6c, 0x3e, 0x3d, 0x3e, 0xcd, 0x3c, 0x7a, 0x0c, 0x44, + 0xc7, 0x7c, 0x54, 0xba, 0x8f, 0xec, 0xee, 0xf5, 0x03, 0xe0, 0xcd, 0xab, 0x76, 0x41, 0xf3, 0x72, 0x01, 0x81, 0x44, + 0xbd, 0xf2, 0x0a, 0xcb, 0x67, 0xc6, 0xec, 0x12, 0xc8, 0x50, 0x41, 0xc0, 0x26, 0xa9, 0xeb, 0x5c, 0x88, 0x55, 0x87, + 0x95, 0xf9, 0x48, 0xc2, 0x8e, 0x42, 0x34, 0xe7, 0x0c, 0x66, 0xc1, 0x7f, 0x05, 0x83, 0x72, 0x10, 0x44, 0x41, 0x14, + 0x04, 0x64, 0x50, 0xc0, 0x2f, 0xc4, 0x19, 0x23, 0x18, 0xa3, 0x04, 0x3a, 0xfc, 0x8e, 0x33, 0x9f, 0x11, 0x79, 0xd9, + 0x08, 0x63, 0xe9, 0x06, 0xe0, 0x5c, 0xca, 0x9c, 0xc7, 0xe8, 0x63, 0xf1, 0x8e, 0xb3, 0x8c, 0xd0, 0x77, 0xde, 0xa9, + 0xfc, 0x88, 0x37, 0x82, 0xdb, 0xed, 0x0e, 0xdb, 0x2b, 0x1e, 0x66, 0xb4, 0x37, 0xa6, 0xef, 0x38, 0x89, 0xb2, 0x86, + 0xf3, 0x30, 0x87, 0x9e, 0x55, 0x96, 0xb5, 0xa2, 0x86, 0xdc, 0xa0, 0x58, 0x17, 0x59, 0x26, 0x27, 0xc3, 0x55, 0x73, + 0x2a, 0x70, 0xdd, 0xd9, 0xf5, 0x02, 0x92, 0x32, 0xa1, 0x59, 0x3a, 0x1b, 0xbe, 0xda, 0xb6, 0xec, 0x45, 0xeb, 0x14, + 0xf2, 0x1a, 0xa2, 0xa2, 0x1f, 0x3a, 0x02, 0x6a, 0x68, 0xc5, 0x65, 0x05, 0x2e, 0xbb, 0xa6, 0x3d, 0xdc, 0xb4, 0xc7, + 0x34, 0xe3, 0x03, 0xc4, 0x88, 0xe3, 0xd8, 0x32, 0xb0, 0x9b, 0x70, 0x78, 0x36, 0xce, 0xf7, 0x65, 0x97, 0xde, 0xba, + 0x5a, 0x3c, 0xc2, 0xda, 0xf3, 0x56, 0x48, 0x08, 0x90, 0x96, 0xa6, 0xd2, 0xed, 0x36, 0x08, 0x60, 0x80, 0xfb, 0xfd, + 0x1e, 0x70, 0xad, 0x86, 0x9d, 0x34, 0xb7, 0x66, 0x4b, 0xec, 0x15, 0x85, 0xc7, 0x40, 0x94, 0x9a, 0xff, 0x0c, 0x02, + 0x8a, 0xe7, 0x6e, 0x08, 0xf6, 0x95, 0xec, 0x68, 0x53, 0xf4, 0xfb, 0x2f, 0x0a, 0x7c, 0x40, 0x39, 0x28, 0x88, 0x75, + 0x75, 0xdc, 0x0a, 0xc3, 0x3e, 0xa9, 0x0f, 0x71, 0x2c, 0xf2, 0x2c, 0x74, 0x84, 0xa5, 0x32, 0x84, 0x85, 0x2b, 0x46, + 0x3a, 0x88, 0x83, 0x9a, 0x74, 0x0e, 0x56, 0xe5, 0x82, 0x0d, 0xf7, 0x7a, 0x9f, 0x00, 0x16, 0x3c, 0xf3, 0x86, 0xe5, + 0xbd, 0x07, 0x00, 0xd6, 0xeb, 0xe1, 0x42, 0x71, 0x2f, 0x5f, 0x35, 0xd0, 0x27, 0xf1, 0xa5, 0x65, 0xd7, 0x67, 0x5a, + 0x56, 0x32, 0x1a, 0x8d, 0xaa, 0x5a, 0x49, 0x3e, 0x1c, 0x79, 0x69, 0xa1, 0x56, 0xca, 0x38, 0xe5, 0x29, 0x58, 0x7a, + 0x1b, 0x4a, 0x37, 0x5f, 0xd0, 0x15, 0x17, 0xa9, 0xfa, 0xe9, 0xa1, 0x4d, 0x36, 0x88, 0x6b, 0xd6, 0xd4, 0x59, 0xd8, + 0xe1, 0x87, 0x80, 0x8f, 0xf6, 0x61, 0xe6, 0xd2, 0x35, 0x2c, 0x2d, 0x88, 0x23, 0xe3, 0x82, 0x87, 0x2e, 0x0f, 0x60, + 0xfd, 0x99, 0x43, 0x12, 0x3f, 0x85, 0x9f, 0x33, 0x93, 0xd6, 0xf1, 0x19, 0xce, 0x66, 0x54, 0xaa, 0x1b, 0x41, 0xfb, + 0x35, 0x24, 0x12, 0x83, 0x6c, 0xdc, 0x60, 0x28, 0x5a, 0x77, 0x1b, 0xb8, 0xf2, 0x5b, 0x7a, 0xe7, 0xd3, 0x20, 0xc0, + 0xb6, 0xc6, 0x62, 0x00, 0x30, 0x14, 0x7f, 0xa0, 0xaa, 0xc6, 0x5c, 0x51, 0x4c, 0xc3, 0x54, 0xa2, 0xbd, 0xe3, 0xb8, + 0x8e, 0x1a, 0x57, 0x59, 0xc1, 0x4a, 0x6b, 0xcb, 0xeb, 0xde, 0xd2, 0xc2, 0x96, 0x80, 0x6a, 0x30, 0xdc, 0x09, 0xe0, + 0x33, 0x22, 0xd5, 0x81, 0x20, 0xbb, 0x0f, 0x0e, 0x9a, 0xb3, 0x04, 0xcf, 0xc3, 0x10, 0xfe, 0xc0, 0xc2, 0x81, 0x65, + 0xa9, 0xfa, 0xb9, 0x9c, 0xc6, 0x70, 0xee, 0xe6, 0x6a, 0x87, 0xcf, 0x96, 0xa0, 0xc8, 0x53, 0x73, 0x6a, 0x2e, 0x5f, + 0x79, 0x63, 0xbf, 0xc7, 0x04, 0xf3, 0x98, 0xd9, 0x86, 0xdf, 0x7a, 0xba, 0xad, 0x2f, 0xac, 0x1b, 0x38, 0x69, 0x2f, + 0x9c, 0xf6, 0x62, 0xbb, 0x34, 0x10, 0x77, 0x75, 0x43, 0x88, 0xf0, 0x5a, 0x13, 0x8b, 0xac, 0x21, 0xd3, 0xb1, 0xd8, + 0x18, 0xaa, 0x4d, 0xc5, 0x73, 0xad, 0x10, 0x2f, 0xa7, 0xea, 0xc2, 0xd4, 0x4a, 0x65, 0xc2, 0x20, 0xcc, 0x94, 0xb0, + 0xa8, 0x32, 0xf0, 0xd9, 0xaf, 0x90, 0xe2, 0xda, 0x7a, 0xde, 0xe2, 0xf2, 0xcd, 0x4c, 0x9b, 0xed, 0xa7, 0xaf, 0xf2, + 0xf8, 0x72, 0xbb, 0x0d, 0xbb, 0x5f, 0x80, 0xf9, 0x65, 0xa9, 0x34, 0x6a, 0xe0, 0xf4, 0x10, 0xa2, 0x9f, 0xf3, 0x3d, + 0x39, 0x27, 0x8e, 0x93, 0x6b, 0x37, 0x6f, 0xb6, 0x93, 0x62, 0x04, 0x16, 0x70, 0xe2, 0x22, 0x1d, 0x68, 0xa9, 0xe0, + 0xb4, 0x65, 0xbc, 0xb7, 0xe9, 0x1d, 0xa5, 0xc2, 0xab, 0x85, 0x26, 0x21, 0x95, 0xbb, 0x97, 0xd8, 0x51, 0x03, 0xce, + 0x49, 0xdd, 0x41, 0xc0, 0x49, 0x4d, 0x37, 0xd6, 0x2a, 0x4e, 0x4d, 0x82, 0xf7, 0x4a, 0x0f, 0x5d, 0xa2, 0x9d, 0xb8, + 0xdd, 0xb6, 0x2a, 0x5b, 0xa8, 0x8f, 0x7b, 0x39, 0x4b, 0xd4, 0xf1, 0x80, 0x42, 0x17, 0x75, 0x34, 0xe4, 0x0b, 0x52, + 0xe8, 0x95, 0xa3, 0x55, 0xab, 0xbb, 0x92, 0x81, 0x52, 0xad, 0x82, 0xbc, 0x26, 0xd6, 0x5d, 0x2b, 0x6b, 0x2c, 0xae, + 0x9c, 0x90, 0xc2, 0x26, 0x7c, 0x69, 0x29, 0x16, 0x56, 0xb0, 0x37, 0xa6, 0xbe, 0x70, 0x89, 0xd0, 0x76, 0xb7, 0x21, + 0x26, 0x19, 0xac, 0x9b, 0xed, 0xf6, 0x75, 0x11, 0xce, 0xb3, 0x05, 0x95, 0xa3, 0x2c, 0x45, 0x08, 0x31, 0xe3, 0xa1, + 0x6b, 0xbb, 0x60, 0x26, 0x86, 0xba, 0xf6, 0x78, 0x49, 0xa6, 0x58, 0x9b, 0x24, 0x47, 0xf1, 0xb9, 0x2c, 0xd4, 0x5a, + 0x23, 0x04, 0x0f, 0xf7, 0x3f, 0x53, 0x88, 0xe1, 0x66, 0xd6, 0xdd, 0x6f, 0x3b, 0x37, 0xc4, 0x3f, 0x21, 0x90, 0x40, + 0xc9, 0x5e, 0x17, 0xa3, 0xf3, 0x4c, 0xa4, 0xb8, 0x53, 0x55, 0x54, 0x5c, 0xb5, 0x0e, 0x9a, 0x2d, 0xb7, 0xf7, 0x62, + 0x4b, 0x14, 0x20, 0xae, 0xb1, 0xd0, 0x8c, 0x67, 0xe5, 0x2c, 0x45, 0x32, 0x8a, 0x0d, 0x89, 0x4a, 0x2f, 0x2a, 0xba, + 0xcf, 0xd3, 0x98, 0x1e, 0xba, 0x35, 0x08, 0xae, 0x9a, 0x3b, 0x1b, 0x69, 0xbe, 0x20, 0x44, 0x4d, 0x80, 0x84, 0x8d, + 0x6a, 0x4e, 0xad, 0x4b, 0xf1, 0x30, 0xab, 0x7c, 0xa6, 0x0f, 0xe2, 0x4b, 0x01, 0x3c, 0xac, 0xb7, 0xbd, 0xaf, 0x84, + 0xc7, 0xda, 0xe0, 0xdb, 0xed, 0xf6, 0x52, 0xcc, 0x83, 0xc0, 0x63, 0x34, 0xbf, 0x53, 0x12, 0xf3, 0xde, 0x98, 0xc2, + 0x8a, 0xf7, 0x5d, 0xda, 0xba, 0x49, 0xad, 0xb5, 0x40, 0xdd, 0xe1, 0xfa, 0x80, 0xe7, 0x29, 0x71, 0xb4, 0xa3, 0x72, + 0x2a, 0xad, 0xae, 0x1c, 0xbb, 0x22, 0x30, 0x30, 0xf4, 0x0f, 0x29, 0xdb, 0x80, 0x39, 0x1e, 0x58, 0xdb, 0xa0, 0x9f, + 0x92, 0xd2, 0xc2, 0x8c, 0xd1, 0x98, 0x45, 0xae, 0xab, 0xe8, 0x80, 0xeb, 0xe8, 0xed, 0x3c, 0xfa, 0xdb, 0xb3, 0x31, + 0x2d, 0x62, 0x91, 0xca, 0x2b, 0x50, 0x41, 0x80, 0x32, 0x04, 0x0d, 0xff, 0x35, 0x35, 0x00, 0x0d, 0x82, 0x1b, 0x80, + 0x7f, 0x74, 0x3a, 0x0d, 0xda, 0x9a, 0x7c, 0x4c, 0x52, 0x55, 0xe4, 0xac, 0x0d, 0x65, 0xa6, 0x92, 0x43, 0xf2, 0xb8, + 0x04, 0x3c, 0x47, 0x6c, 0x96, 0xb2, 0xb9, 0x50, 0x9b, 0x4d, 0xbd, 0x56, 0xec, 0xc8, 0x6d, 0xa3, 0x68, 0xb3, 0x16, + 0xb5, 0x9d, 0xc4, 0x7c, 0x31, 0xbd, 0xb5, 0xc2, 0xc0, 0xa9, 0x69, 0xcd, 0xcd, 0x0e, 0x74, 0x9a, 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, 0x0d, 0x69, 0xaa, 0xd0, 0xa3, 0x03, 0xbd, 0x1d, 0x02, 0x9a, 0xb3, 0x31, + 0x5d, 0xd2, 0x14, 0x2f, 0xd0, 0x74, 0x0d, 0x66, 0x29, 0x17, 0xd0, 0xd7, 0x6e, 0x9f, 0xe4, 0x0b, 0xd5, 0x13, 0xe1, + 0x2d, 0x51, 0xf0, 0xe5, 0x48, 0xc1, 0x2b, 0x2b, 0xe7, 0xb1, 0x99, 0x43, 0xc0, 0x63, 0x51, 0x25, 0x7a, 0x27, 0xc5, + 0x25, 0x28, 0x53, 0xe1, 0x08, 0x34, 0x55, 0x23, 0x96, 0x70, 0x80, 0xdb, 0x8b, 0xa7, 0x01, 0xa1, 0x20, 0xd5, 0x5d, + 0xdb, 0x15, 0x79, 0xcb, 0x8e, 0x36, 0xb7, 0x60, 0x16, 0x5b, 0xad, 0xcb, 0xd6, 0x57, 0x36, 0xd9, 0x7d, 0x5c, 0x13, + 0x6c, 0xbb, 0xb7, 0x41, 0xc2, 0x5b, 0x7a, 0x43, 0x36, 0x37, 0xfd, 0x7e, 0x08, 0xfd, 0x21, 0x54, 0x77, 0xe8, 0xb6, + 0xb3, 0x43, 0xb7, 0x3e, 0xf3, 0x6b, 0xf5, 0x7c, 0xca, 0x1b, 0xe2, 0x03, 0x9a, 0x68, 0xd1, 0x55, 0x7c, 0x07, 0x9b, + 0x3a, 0xaa, 0xa8, 0xaa, 0x3c, 0x4a, 0x28, 0xa8, 0x80, 0x33, 0x5e, 0x9e, 0x72, 0x8c, 0x6d, 0xaa, 0x9f, 0xde, 0x69, + 0x5e, 0x6d, 0x6d, 0xd6, 0x66, 0xb9, 0x3e, 0x07, 0x8b, 0x80, 0x73, 0x1e, 0x5d, 0x69, 0x5a, 0x72, 0xe9, 0x31, 0xf5, + 0x67, 0x38, 0x2a, 0xc1, 0x45, 0x9c, 0xe5, 0x3c, 0x0d, 0xe8, 0x45, 0xb3, 0xff, 0xa1, 0xb6, 0x95, 0x5a, 0x36, 0xce, + 0xdc, 0xeb, 0x90, 0x6c, 0xfe, 0xc7, 0x06, 0xea, 0x4d, 0x88, 0x11, 0x51, 0xcd, 0x82, 0x3e, 0x61, 0x10, 0x1b, 0x33, + 0x28, 0xd7, 0x49, 0xc2, 0xcb, 0x32, 0x30, 0x4a, 0xad, 0x35, 0x5b, 0x9b, 0xf3, 0xec, 0x11, 0x3b, 0x7a, 0xd4, 0x63, + 0xec, 0x96, 0xd0, 0x44, 0xeb, 0x84, 0x4c, 0x8d, 0x91, 0xa7, 0x05, 0xd2, 0x1d, 0x8a, 0xb2, 0x8b, 0xf0, 0x04, 0x85, + 0x2c, 0xed, 0x7d, 0x6e, 0x4e, 0x64, 0xf5, 0x8d, 0x36, 0xba, 0x88, 0x54, 0x22, 0xc8, 0xc6, 0x6f, 0x10, 0xb0, 0x17, + 0x9a, 0x1d, 0x90, 0xcd, 0x92, 0x9d, 0xd2, 0x33, 0x6b, 0x02, 0x03, 0xaf, 0x4f, 0x54, 0xa2, 0x19, 0x65, 0x45, 0x74, + 0x95, 0x91, 0xcb, 0x5d, 0x48, 0xa2, 0xb3, 0x90, 0xf8, 0xb9, 0x61, 0x69, 0x5d, 0x87, 0x28, 0x66, 0x36, 0x1b, 0x5e, + 0x75, 0xf7, 0x51, 0x63, 0x5b, 0x19, 0x9f, 0xea, 0x5b, 0x9b, 0x46, 0xa6, 0xd0, 0xd7, 0xe1, 0xa4, 0xdf, 0x87, 0xbf, + 0x9a, 0x7e, 0xe0, 0x2d, 0x05, 0x7f, 0xb1, 0x47, 0xa4, 0x4e, 0x58, 0x00, 0x70, 0x84, 0x39, 0xaf, 0x9a, 0x13, 0xf8, + 0x88, 0x1d, 0x6d, 0x1e, 0x85, 0xa7, 0x8d, 0x99, 0xbb, 0x0b, 0xf1, 0x52, 0x95, 0xf4, 0xbc, 0x79, 0x32, 0x03, 0xb1, + 0x0a, 0xcd, 0x7e, 0xbd, 0x65, 0x56, 0x9f, 0x00, 0x44, 0xea, 0xd6, 0x3a, 0x94, 0xe2, 0xc7, 0xa6, 0xcb, 0x64, 0x93, + 0xb2, 0x36, 0x13, 0xa5, 0x54, 0x24, 0xcd, 0x45, 0x00, 0xfd, 0x86, 0xe1, 0xa8, 0x01, 0xde, 0x5b, 0x8f, 0xbd, 0x19, + 0x1a, 0x6f, 0x4c, 0x0d, 0x3d, 0xdb, 0xe8, 0xe5, 0xed, 0x28, 0x84, 0x19, 0x8b, 0xe8, 0xd6, 0x1d, 0x8b, 0xe1, 0x29, + 0x3d, 0x81, 0x0a, 0xdf, 0x84, 0x18, 0x4d, 0x97, 0xd4, 0xf5, 0x74, 0xad, 0xb6, 0xd2, 0x0d, 0xa1, 0x39, 0x46, 0xf1, + 0xf1, 0xda, 0x76, 0x47, 0x8d, 0xd0, 0x9e, 0x50, 0x1e, 0xde, 0xd2, 0x8a, 0xde, 0x58, 0x16, 0xc1, 0xc9, 0x8f, 0xbd, + 0xfc, 0x84, 0x9e, 0x7b, 0x02, 0x93, 0xa2, 0xad, 0x01, 0xfc, 0x01, 0xf5, 0xc3, 0x59, 0x3d, 0xb5, 0x52, 0x0e, 0x4f, + 0xe1, 0x4b, 0x36, 0x20, 0x57, 0xd0, 0x8b, 0x35, 0x66, 0x47, 0x31, 0xe8, 0xa0, 0x76, 0x76, 0x87, 0x37, 0x29, 0x65, + 0x88, 0xd6, 0x77, 0x0e, 0xe2, 0xe9, 0x1f, 0xa0, 0xe9, 0x83, 0xb4, 0x30, 0xa5, 0x6b, 0x14, 0xf0, 0x80, 0xbe, 0xa9, + 0xdf, 0xcf, 0xf1, 0xb9, 0xf6, 0x2c, 0xb1, 0xb0, 0xc7, 0x4b, 0x42, 0x97, 0x5e, 0xdc, 0x28, 0x90, 0x36, 0x3b, 0x56, + 0x01, 0x58, 0x91, 0x04, 0x1a, 0x91, 0x80, 0xa5, 0x8e, 0x27, 0x2e, 0xdb, 0xa0, 0x01, 0x49, 0x54, 0x52, 0xc8, 0x12, + 0x49, 0xe0, 0x87, 0x11, 0x84, 0x28, 0x8a, 0x41, 0xdc, 0xab, 0x97, 0x57, 0x5c, 0x53, 0x03, 0x4e, 0x14, 0xc1, 0x04, + 0xeb, 0x74, 0x0a, 0xc4, 0x56, 0xac, 0x57, 0xe0, 0x79, 0xe9, 0x38, 0x71, 0x64, 0x09, 0xd0, 0x20, 0xcd, 0x97, 0x4e, + 0xbb, 0xe5, 0xed, 0x89, 0x96, 0x2a, 0x36, 0xf7, 0x5e, 0x2c, 0x2c, 0xf7, 0x58, 0xf9, 0xdb, 0x81, 0xf6, 0xc2, 0x6a, + 0x47, 0x44, 0x0d, 0x56, 0x76, 0x6d, 0xbb, 0x36, 0x94, 0x86, 0xea, 0x5e, 0x39, 0x26, 0xa0, 0xa2, 0xab, 0xb8, 0x5a, + 0x46, 0xd9, 0x08, 0xfe, 0x6c, 0xb7, 0xc1, 0x7e, 0x00, 0x16, 0x90, 0xbf, 0xbe, 0xff, 0x39, 0xc2, 0xf0, 0x4c, 0xbf, + 0xbe, 0xff, 0x79, 0xbb, 0x7d, 0x36, 0x1e, 0x1b, 0xae, 0xc0, 0xa9, 0x75, 0x80, 0x3f, 0x30, 0x6c, 0x83, 0x5d, 0xb2, + 0xdb, 0xed, 0x33, 0xe0, 0x20, 0x14, 0xdb, 0x60, 0x76, 0xb1, 0x72, 0xe4, 0x52, 0xac, 0x86, 0xde, 0x91, 0x80, 0x55, + 0xb7, 0xc3, 0x52, 0xec, 0x52, 0x1f, 0x15, 0x82, 0x51, 0x2f, 0xfa, 0x97, 0x9d, 0x02, 0x4b, 0x0a, 0xa6, 0xab, 0xc1, + 0xb2, 0xaa, 0x56, 0x65, 0xb4, 0xbf, 0x1f, 0xaf, 0xb2, 0x51, 0x99, 0xc1, 0x36, 0x2f, 0xaf, 0x2f, 0x01, 0x50, 0x21, + 0xa0, 0x8d, 0x77, 0x6b, 0x91, 0x99, 0x17, 0x0b, 0xba, 0xcc, 0x70, 0x4d, 0x82, 0xd9, 0x41, 0xce, 0xad, 0x6e, 0x72, + 0x4a, 0xec, 0x03, 0xd8, 0x1c, 0x6e, 0xb7, 0x0d, 0x7e, 0xe1, 0x68, 0xf4, 0x6c, 0xb6, 0xcc, 0xb4, 0x41, 0x27, 0x37, + 0xfb, 0x9f, 0x44, 0x5e, 0x1a, 0x2a, 0x3e, 0xc9, 0xf4, 0x65, 0x06, 0x7c, 0x1e, 0x7b, 0x2b, 0x42, 0x9f, 0xe5, 0x6a, + 0xb4, 0x06, 0xd8, 0xd8, 0xec, 0xe2, 0x6e, 0x94, 0x72, 0x88, 0x48, 0x11, 0x58, 0x75, 0xcd, 0x32, 0x23, 0xbe, 0x4d, + 0xc5, 0x5d, 0x4b, 0x15, 0xf6, 0x56, 0x78, 0xce, 0x2a, 0xdc, 0x38, 0xca, 0xf4, 0x26, 0x51, 0xf8, 0x12, 0x85, 0xa8, + 0x1c, 0x8d, 0xe9, 0x9c, 0x40, 0x2a, 0xf3, 0x98, 0x50, 0xcc, 0xe1, 0xde, 0xfd, 0x9a, 0x3a, 0x73, 0x19, 0x5f, 0xb8, + 0xf7, 0xd2, 0x97, 0x99, 0xdc, 0x4a, 0x00, 0x45, 0x52, 0xb5, 0xff, 0xf2, 0x19, 0xa9, 0xf1, 0x3f, 0x53, 0xad, 0x01, + 0xe8, 0xfd, 0x02, 0x35, 0x39, 0x82, 0x80, 0xad, 0x98, 0xfa, 0x68, 0xfa, 0x56, 0x32, 0xff, 0x01, 0x75, 0x3b, 0x82, + 0x6d, 0x54, 0xfc, 0x9c, 0xa8, 0xa2, 0x05, 0x4f, 0xd7, 0x22, 0x8d, 0x45, 0x72, 0x17, 0xf1, 0x7a, 0x8a, 0x25, 0x31, + 0x1b, 0x21, 0xeb, 0x97, 0x66, 0x17, 0x7e, 0x2e, 0x1a, 0x26, 0xe0, 0xb4, 0xf4, 0xb7, 0x95, 0xb7, 0x99, 0x2c, 0xe3, + 0x8c, 0x4c, 0xb9, 0x42, 0xec, 0xb6, 0xfa, 0x1e, 0x73, 0x82, 0x3f, 0x3d, 0x78, 0x4a, 0xe8, 0xad, 0x9c, 0x96, 0x08, + 0x4a, 0x27, 0x52, 0xeb, 0xaa, 0x89, 0xfd, 0x9a, 0x42, 0x14, 0x07, 0xc1, 0x20, 0x74, 0xa7, 0x69, 0x9f, 0xe2, 0xfb, + 0x6c, 0xd9, 0x6f, 0x4d, 0xd9, 0x92, 0x6c, 0x04, 0x74, 0x4c, 0x3a, 0x6f, 0x4f, 0x6f, 0xcf, 0xce, 0xbc, 0xdf, 0xa0, + 0x09, 0x07, 0xd5, 0x0d, 0xb4, 0xab, 0x20, 0xd3, 0x18, 0xc5, 0x66, 0x31, 0xd6, 0x6e, 0x4d, 0x44, 0x10, 0x74, 0xba, + 0x9c, 0x85, 0xed, 0x76, 0x42, 0x7c, 0x09, 0x24, 0x50, 0xe0, 0xca, 0x45, 0x39, 0x09, 0x89, 0xba, 0x90, 0xe9, 0xc9, + 0xba, 0x96, 0x2c, 0xd0, 0x6b, 0xec, 0x20, 0xa0, 0xc7, 0xdc, 0x3e, 0x05, 0xf4, 0x7d, 0xc1, 0x8e, 0xf9, 0x20, 0x18, + 0x62, 0x7c, 0xd5, 0x80, 0xde, 0x48, 0xf5, 0x08, 0x1e, 0xc2, 0xc0, 0x72, 0xd1, 0x57, 0x05, 0x43, 0x58, 0xa1, 0xbf, + 0x52, 0x36, 0xf9, 0xe6, 0xef, 0x6e, 0x7e, 0xcf, 0xb5, 0x98, 0x1d, 0x84, 0xe2, 0xf6, 0x7a, 0x02, 0xc4, 0xaf, 0xe2, + 0x57, 0x60, 0x5d, 0xad, 0x25, 0xde, 0x6e, 0x7a, 0xfe, 0x14, 0xbe, 0x1c, 0xdd, 0x7e, 0x52, 0x9a, 0x4f, 0x20, 0x48, + 0x8d, 0x93, 0x94, 0xbb, 0xef, 0x3e, 0x4a, 0x57, 0x11, 0x8c, 0x16, 0x20, 0xd6, 0xdd, 0x5b, 0xc9, 0x59, 0x53, 0xf8, + 0x8f, 0x75, 0xbe, 0xc7, 0xd8, 0x21, 0xf2, 0x14, 0xa7, 0xbf, 0x01, 0x86, 0x7d, 0xe7, 0xdf, 0xca, 0xac, 0x21, 0xd1, + 0xb9, 0xfa, 0x08, 0xe8, 0xff, 0x58, 0x8f, 0xdf, 0x31, 0x4a, 0xfa, 0x92, 0x38, 0x47, 0xb8, 0x22, 0x5e, 0xa2, 0xa9, + 0x5e, 0x6f, 0x5c, 0xd3, 0x4f, 0x85, 0x79, 0xa1, 0x15, 0x1c, 0xf6, 0xad, 0x51, 0x78, 0xe0, 0x99, 0xf7, 0x9b, 0x68, + 0x08, 0xba, 0x7f, 0xc7, 0xbd, 0xf1, 0x9b, 0x60, 0x19, 0xde, 0x94, 0xb3, 0xcc, 0xdc, 0xe1, 0x6e, 0x32, 0x91, 0xca, + 0x1b, 0xc6, 0x82, 0xb5, 0x50, 0xe6, 0xab, 0x69, 0x30, 0xdb, 0xd4, 0x91, 0x4a, 0x76, 0xdf, 0xbf, 0x6d, 0x9c, 0xb0, + 0xd9, 0x20, 0x38, 0xad, 0x64, 0x11, 0x5f, 0xf2, 0x60, 0xaa, 0x55, 0x14, 0x59, 0xd6, 0xef, 0x67, 0x80, 0x0c, 0xe3, + 0xb4, 0x77, 0xf0, 0x64, 0xa9, 0x99, 0x09, 0x71, 0x6d, 0x75, 0x16, 0xf0, 0xd6, 0x8c, 0xe6, 0x71, 0x05, 0xbb, 0xcc, + 0x57, 0x52, 0xfc, 0xd9, 0x92, 0x64, 0x63, 0xfd, 0x0d, 0x19, 0xb6, 0x95, 0xcf, 0x9c, 0x03, 0xc6, 0xcc, 0x8d, 0x54, + 0x41, 0xee, 0x7a, 0xc0, 0x08, 0x21, 0x11, 0x10, 0xce, 0x62, 0xe2, 0x4e, 0x98, 0xf0, 0x8f, 0x2e, 0x30, 0x4e, 0x8c, + 0x81, 0x71, 0x3e, 0xca, 0x90, 0xd3, 0x63, 0x3e, 0x48, 0x1a, 0xb3, 0xf5, 0xa7, 0x2a, 0x91, 0x5e, 0x4b, 0x42, 0xcf, + 0xe0, 0xf7, 0xb8, 0xc5, 0x03, 0x35, 0x82, 0x53, 0xba, 0x9b, 0xd3, 0xfe, 0xab, 0x82, 0x0c, 0xff, 0x02, 0xef, 0xae, + 0xd8, 0x5e, 0x96, 0x13, 0x58, 0xdc, 0xb1, 0x57, 0x3c, 0xcd, 0x55, 0x8b, 0x13, 0xe2, 0x11, 0x8b, 0xdc, 0x27, 0x16, + 0x30, 0xa2, 0x86, 0xd1, 0xf8, 0xf1, 0xf4, 0xe4, 0xad, 0xc6, 0x6c, 0xca, 0xfd, 0x0f, 0x60, 0x44, 0xb5, 0xb4, 0xdd, + 0x0e, 0xf8, 0x72, 0x84, 0x06, 0xdb, 0xa9, 0x1b, 0xec, 0x7e, 0xdf, 0xa4, 0x1d, 0x95, 0x5e, 0x36, 0x27, 0x06, 0xdd, + 0x51, 0xda, 0x2c, 0x95, 0x41, 0x6d, 0x57, 0xe1, 0x68, 0x3e, 0x6b, 0xc4, 0xaa, 0xde, 0x87, 0xe1, 0x92, 0xc6, 0x56, + 0x56, 0x6e, 0x77, 0x13, 0x8e, 0x6c, 0x02, 0x5c, 0x9f, 0x82, 0xb2, 0x6a, 0xce, 0x41, 0x0b, 0x3a, 0x13, 0x38, 0xa2, + 0xed, 0x36, 0x84, 0x08, 0x1c, 0xc5, 0x70, 0x32, 0x0b, 0x8b, 0xe1, 0x50, 0x0d, 0x7c, 0x41, 0x48, 0xf4, 0xa9, 0x98, + 0x67, 0x0b, 0x85, 0xd8, 0xe3, 0xef, 0xa4, 0xdf, 0x0a, 0xc5, 0x29, 0xf7, 0x7e, 0x13, 0x64, 0xf3, 0x7b, 0x8a, 0x31, + 0x07, 0x9d, 0x66, 0x33, 0x03, 0x09, 0xeb, 0x71, 0x45, 0xd4, 0x3a, 0xb2, 0xb3, 0x01, 0xaa, 0x58, 0x34, 0x85, 0x05, + 0x75, 0x8b, 0x27, 0xd6, 0x33, 0x7a, 0x0f, 0x2a, 0x41, 0x54, 0x0b, 0x76, 0x63, 0xb8, 0xd6, 0x3e, 0x89, 0x50, 0x52, + 0x4e, 0x9a, 0xcc, 0x8c, 0x15, 0x0d, 0x16, 0x20, 0x24, 0x8d, 0xcb, 0xea, 0x8d, 0x4c, 0xb3, 0x8b, 0x0c, 0x10, 0x13, + 0x9c, 0xff, 0x9c, 0x6c, 0xbc, 0x79, 0xae, 0xe6, 0xa5, 0x2b, 0x71, 0x66, 0x61, 0x3e, 0xba, 0xde, 0xd2, 0x82, 0x44, + 0x05, 0xd0, 0x28, 0x5f, 0xcb, 0xf3, 0xd3, 0x8e, 0x55, 0xc8, 0xee, 0x87, 0x53, 0x65, 0x3b, 0xc4, 0x8f, 0x58, 0x45, + 0xbc, 0xd3, 0xba, 0x52, 0x22, 0x8d, 0x8e, 0xb6, 0x01, 0x31, 0x6c, 0xd9, 0xb7, 0xa8, 0xe1, 0x83, 0x30, 0x83, 0x4e, + 0xf2, 0x83, 0x9e, 0xd1, 0xb1, 0x35, 0x90, 0xf4, 0xb5, 0x08, 0xbe, 0x46, 0x47, 0x3a, 0x51, 0xa6, 0x91, 0x98, 0x42, + 0xa2, 0x5f, 0x2f, 0xb4, 0xc6, 0x32, 0xca, 0xbe, 0x22, 0xff, 0x7b, 0xdd, 0xbd, 0xdf, 0xc4, 0x76, 0x0b, 0x93, 0xec, + 0x79, 0x5c, 0xc1, 0xa6, 0x46, 0xad, 0x10, 0xce, 0xce, 0x71, 0x85, 0xda, 0xb1, 0x5e, 0x58, 0x02, 0x79, 0x00, 0x5b, + 0x91, 0x06, 0x65, 0x90, 0xec, 0x53, 0x31, 0x17, 0x0b, 0x27, 0xca, 0x91, 0x0a, 0xef, 0x4b, 0x8e, 0x52, 0x0e, 0x57, + 0xb1, 0xb0, 0x60, 0xc8, 0xaf, 0x8e, 0x2e, 0x0a, 0x79, 0x05, 0x92, 0x12, 0xc3, 0x50, 0x59, 0x5e, 0x17, 0x57, 0x6d, + 0x49, 0x68, 0xef, 0x0c, 0x40, 0x58, 0x0a, 0x10, 0xbc, 0x34, 0x6a, 0x88, 0xd9, 0x46, 0xed, 0xae, 0xe8, 0x5e, 0x72, + 0x40, 0x9d, 0xee, 0xda, 0xad, 0x37, 0x65, 0x9b, 0x6d, 0xc5, 0x85, 0x7f, 0x42, 0xe9, 0xc7, 0x7c, 0x50, 0xf8, 0x54, + 0x02, 0x37, 0xbe, 0xda, 0x64, 0xd9, 0xc5, 0x1d, 0x2e, 0xfd, 0xaa, 0x31, 0x7e, 0xfd, 0x7e, 0x4f, 0x2d, 0x84, 0x46, + 0x2a, 0x30, 0xdf, 0x3e, 0x33, 0x55, 0x19, 0x4d, 0xa9, 0xbd, 0x04, 0x57, 0xce, 0x7e, 0x04, 0x15, 0x71, 0x5d, 0x91, + 0xc9, 0xd4, 0x00, 0xed, 0x79, 0x59, 0xe1, 0x56, 0x16, 0xe0, 0xb1, 0x13, 0x90, 0xed, 0x96, 0x87, 0x81, 0x3e, 0x74, + 0x02, 0x7f, 0x4b, 0x9e, 0x22, 0xb3, 0x66, 0x1f, 0x7f, 0xd1, 0x82, 0x7f, 0x6c, 0xc1, 0xcf, 0x28, 0xee, 0xb4, 0x32, + 0xff, 0x56, 0x5a, 0xb7, 0xb8, 0x7f, 0x27, 0xd3, 0x84, 0xa2, 0x32, 0xa1, 0xf6, 0x2b, 0xfd, 0x97, 0x09, 0x96, 0xa4, + 0xb2, 0x7f, 0x90, 0xf0, 0xc1, 0xac, 0xf1, 0xc4, 0x1a, 0x4f, 0x86, 0xd3, 0xad, 0x34, 0x0c, 0x01, 0x0a, 0xfd, 0xbc, + 0xcc, 0x15, 0xd5, 0xcf, 0xbf, 0xac, 0xf9, 0x9a, 0x37, 0x5b, 0x6c, 0x93, 0x1e, 0x68, 0xb0, 0x97, 0x47, 0x53, 0x0a, + 0x27, 0x51, 0xe7, 0x46, 0xa2, 0x2e, 0x6a, 0x96, 0xa1, 0x3a, 0xc1, 0xab, 0x79, 0xaa, 0x87, 0xbd, 0x99, 0x88, 0xd6, + 0x4a, 0xca, 0x12, 0x03, 0xd6, 0x3a, 0xf2, 0x90, 0xdc, 0xad, 0x75, 0xdc, 0x69, 0xa8, 0x4b, 0x53, 0x28, 0x01, 0x56, + 0xb8, 0x00, 0x47, 0xd0, 0xcf, 0x45, 0xc8, 0xe1, 0x9a, 0xaa, 0xf4, 0x0b, 0x9a, 0x92, 0x27, 0x9e, 0xa2, 0x56, 0x2b, + 0xd2, 0xed, 0x47, 0x39, 0x76, 0xc3, 0x37, 0x4e, 0xc8, 0x89, 0x11, 0xfa, 0xbb, 0x63, 0x29, 0x67, 0x68, 0xf1, 0xa0, + 0x4e, 0xb0, 0x5e, 0xde, 0x52, 0xa0, 0x98, 0xa3, 0xcb, 0xaa, 0x6b, 0x5e, 0xa3, 0xed, 0xcb, 0xb2, 0xdf, 0xcf, 0x6d, + 0x3d, 0x29, 0x3b, 0xda, 0x2c, 0xcd, 0x3e, 0x44, 0xc5, 0x14, 0xee, 0xfa, 0x44, 0xf3, 0x57, 0xa1, 0xbe, 0x6a, 0xcb, + 0x9c, 0x8f, 0x38, 0xe2, 0x62, 0xe4, 0xa4, 0xfe, 0x45, 0x4d, 0xbd, 0x12, 0xf7, 0xab, 0x4a, 0xbe, 0x13, 0xc6, 0x8a, + 0xd1, 0x01, 0xf5, 0xa7, 0x4a, 0xe5, 0xfd, 0xb2, 0x00, 0xb8, 0x27, 0xc1, 0x3e, 0x81, 0x7d, 0x85, 0x46, 0xf8, 0x6d, + 0x09, 0xf8, 0x37, 0x8a, 0x1b, 0xb0, 0x0a, 0x0c, 0x30, 0x9a, 0x6c, 0xcf, 0x69, 0x02, 0x07, 0x9c, 0xd0, 0x2a, 0x0a, + 0x2a, 0xcc, 0xd0, 0x50, 0x5b, 0x18, 0x3d, 0x45, 0x19, 0xb7, 0xca, 0xec, 0xdd, 0x18, 0x3b, 0x2d, 0xf0, 0x1a, 0xfe, + 0x7c, 0x5e, 0xe8, 0x61, 0xa3, 0x0e, 0xd2, 0xa3, 0x93, 0x98, 0xfe, 0xb8, 0x85, 0x93, 0x9b, 0x85, 0xb3, 0xac, 0x59, + 0x02, 0xdd, 0x81, 0x0b, 0x62, 0xdc, 0xef, 0xe7, 0x70, 0x64, 0x9a, 0x91, 0x2f, 0x58, 0x4e, 0x63, 0xb6, 0xa4, 0xda, + 0xd3, 0xee, 0xb2, 0x0a, 0x73, 0xba, 0xb4, 0x32, 0xde, 0x94, 0x81, 0xca, 0x68, 0xbb, 0x0d, 0xe1, 0x4f, 0xb7, 0xb5, + 0x4b, 0x3a, 0x5f, 0x42, 0x06, 0xf8, 0x03, 0x12, 0x51, 0xc4, 0xbe, 0xfe, 0xb7, 0x1a, 0xa7, 0xf4, 0x44, 0x69, 0xcd, + 0x12, 0xba, 0x66, 0xba, 0x7e, 0x7a, 0xc1, 0xd6, 0x8d, 0xa5, 0xb0, 0xdd, 0x86, 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, 0xf9, 0x50, 0x99, 0xaf, 0x8d, 0x47, 0xdc, 0xbf, 0xd2, 0x30, 0x31, 0x45, 0xa2, 0x42, 0x74, 0xf6, + 0x1b, 0xc8, 0x72, 0x04, 0xe0, 0x58, 0x9e, 0xca, 0x9a, 0xfe, 0x98, 0x42, 0x1c, 0x74, 0x68, 0xd0, 0xbb, 0x42, 0x5e, + 0x65, 0x25, 0x0f, 0xf1, 0x9e, 0xe0, 0x69, 0x46, 0xef, 0x37, 0xf8, 0xd0, 0xd6, 0x1e, 0x3d, 0x41, 0x36, 0x9e, 0x72, + 0xbf, 0xfe, 0x4e, 0x84, 0x73, 0x88, 0x56, 0xb9, 0xa0, 0x5a, 0x5d, 0xed, 0x00, 0xa8, 0x3c, 0xdb, 0xab, 0x47, 0x70, + 0xba, 0xe9, 0xeb, 0x5b, 0x15, 0x3a, 0x73, 0x00, 0x69, 0x0f, 0xc9, 0xba, 0xe6, 0x7a, 0x07, 0xb8, 0x23, 0xb1, 0x5a, + 0x03, 0x8d, 0x75, 0x5b, 0xb3, 0xd3, 0x1e, 0xc5, 0x63, 0x22, 0x33, 0x63, 0x91, 0x62, 0xcc, 0xdd, 0x3a, 0x2d, 0x8a, + 0x36, 0x68, 0x86, 0xb0, 0x7b, 0xd7, 0xe1, 0xeb, 0x56, 0x84, 0xf5, 0xfb, 0x6d, 0x5f, 0x60, 0x34, 0x8c, 0xb9, 0x76, + 0xcf, 0x33, 0x74, 0xc3, 0x06, 0xdb, 0xc8, 0x79, 0x88, 0x7c, 0x98, 0xa9, 0x03, 0x51, 0xd6, 0xd6, 0x80, 0xed, 0x11, + 0xd7, 0x9b, 0x56, 0xf1, 0xf3, 0x2a, 0xe6, 0x6c, 0xcf, 0x1a, 0xa7, 0xb4, 0xbe, 0xc6, 0x35, 0xc7, 0x55, 0x21, 0xa2, + 0xb6, 0x9e, 0xf1, 0x30, 0xec, 0x7c, 0x81, 0x3b, 0xb3, 0xc2, 0xe0, 0x45, 0x58, 0x2a, 0xd9, 0xa9, 0x5c, 0x7f, 0x0e, + 0x5b, 0x1c, 0xa4, 0xf2, 0xa5, 0xd7, 0xdf, 0x7f, 0xf9, 0xe2, 0x0b, 0x74, 0x53, 0x73, 0x7e, 0x04, 0x41, 0x26, 0xd0, + 0x21, 0x4b, 0xa9, 0x1e, 0xbf, 0x2b, 0x80, 0xda, 0xc3, 0x3c, 0x7c, 0x57, 0x30, 0x11, 0x5f, 0x67, 0x97, 0x71, 0x25, + 0x8b, 0xd1, 0x35, 0x17, 0xa9, 0x2c, 0xac, 0xd4, 0x38, 0x38, 0x5e, 0xad, 0x72, 0x1e, 0x80, 0xa9, 0xbc, 0x65, 0x94, + 0x6d, 0x65, 0x99, 0x1e, 0x5c, 0x2d, 0x4f, 0xaf, 0xb4, 0xe8, 0xbc, 0xbc, 0xbe, 0x0c, 0x22, 0xfc, 0x75, 0x6e, 0x7e, + 0x5c, 0xc5, 0xe5, 0xc7, 0x20, 0xb2, 0x36, 0x75, 0xe6, 0x07, 0x4a, 0xe5, 0xc1, 0x7f, 0x0a, 0x64, 0xba, 0xdf, 0x15, + 0x60, 0x99, 0x6d, 0x2b, 0x3e, 0x8c, 0xb1, 0xd6, 0xe1, 0x84, 0xcc, 0x54, 0x89, 0xde, 0xbb, 0x64, 0x5d, 0x80, 0xb5, + 0x9f, 0xc2, 0x32, 0x56, 0xb9, 0x66, 0x58, 0x99, 0xaa, 0xc8, 0xcc, 0xca, 0x9a, 0xed, 0x87, 0xd6, 0x89, 0x66, 0x8e, + 0xde, 0x02, 0xfa, 0x81, 0xec, 0x5f, 0xd2, 0x72, 0xcd, 0x3c, 0x1f, 0x9b, 0xc6, 0xeb, 0x47, 0xfb, 0x97, 0x6e, 0xc1, + 0xde, 0xda, 0x3b, 0x39, 0x0a, 0x13, 0xc1, 0xb3, 0xd6, 0x8c, 0x2f, 0xf2, 0xac, 0x80, 0x95, 0x33, 0x19, 0x8f, 0xa9, + 0xb7, 0xb4, 0x5a, 0x37, 0x47, 0x87, 0xe4, 0x9a, 0x3d, 0xae, 0x1e, 0x73, 0xb2, 0xcf, 0x5b, 0xa6, 0xb6, 0x6d, 0xeb, + 0x38, 0x4f, 0x93, 0xaf, 0x4c, 0xf7, 0xc5, 0xda, 0x46, 0x44, 0x57, 0xce, 0x7d, 0xce, 0x2b, 0xb8, 0xf5, 0x4d, 0x69, + 0xe8, 0xb5, 0x04, 0x20, 0x3a, 0x6d, 0xc0, 0x5f, 0xb0, 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, 0xb1, 0xbb, 0xca, 0xa5, 0x13, 0xf5, + 0x5b, 0x26, 0x5c, 0xb9, 0x12, 0x04, 0x64, 0x5a, 0xb0, 0x5e, 0x61, 0x76, 0x91, 0x5c, 0x03, 0x21, 0x03, 0xc3, 0xd7, + 0x60, 0x2d, 0x4a, 0x6e, 0xac, 0x60, 0xbd, 0x7b, 0xbe, 0x4e, 0x10, 0x52, 0xf0, 0xc0, 0x4d, 0xd0, 0x0f, 0xad, 0x9b, + 0xb7, 0xa3, 0x44, 0x19, 0xc4, 0xe3, 0xd6, 0x4e, 0x39, 0x48, 0x20, 0x00, 0xf7, 0x54, 0x85, 0xe0, 0x50, 0x20, 0xeb, + 0xe0, 0x6a, 0xc6, 0x11, 0x5c, 0x5d, 0x39, 0x73, 0x71, 0x03, 0xb0, 0xae, 0xfc, 0xb9, 0x6c, 0x70, 0x61, 0x3d, 0xa2, + 0xca, 0x9c, 0x71, 0x8a, 0x41, 0x8c, 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, 0x20, 0x0a, 0xb5, 0x01, 0x43, 0xe0, 0x90, 0xf8, 0x83, 0x41, 0xa8, 0xf1, 0x4e, 0x06, 0x2a, 0x20, 0x16, + 0xf1, 0x78, 0x6c, 0xc4, 0xcd, 0x0a, 0xc7, 0x43, 0x0c, 0x7e, 0xd5, 0x7c, 0x41, 0x02, 0x42, 0x4d, 0x69, 0xe8, 0xf2, + 0x18, 0x0e, 0x27, 0x7b, 0x13, 0x48, 0xc5, 0xcc, 0x4c, 0x15, 0xc6, 0xc6, 0x24, 0x82, 0x78, 0xa7, 0x9d, 0xf5, 0x42, + 0xb9, 0xdd, 0x35, 0x1a, 0xc8, 0x95, 0xc1, 0x17, 0x55, 0x3c, 0xd9, 0x1b, 0x76, 0x55, 0x8c, 0xa3, 0x70, 0x6d, 0x94, + 0x6f, 0x67, 0x87, 0x00, 0x5e, 0x7b, 0x36, 0xf4, 0xe5, 0x12, 0x67, 0xfb, 0x4f, 0xc9, 0xe3, 0xa7, 0x84, 0x9e, 0xb1, + 0xb3, 0xaf, 0x9e, 0xd2, 0x33, 0x45, 0x4e, 0xf6, 0x26, 0xd1, 0x35, 0xb3, 0x98, 0x2f, 0x07, 0xaa, 0x09, 0xf4, 0x72, + 0xb4, 0x16, 0x6a, 0x81, 0x69, 0x87, 0xa6, 0xf0, 0xdb, 0xf1, 0x5e, 0x30, 0xb8, 0x6e, 0x37, 0xfd, 0xba, 0xdd, 0x56, + 0xcf, 0xab, 0x6b, 0xef, 0x20, 0xda, 0x2d, 0x66, 0xf2, 0xf7, 0xf1, 0x9e, 0x9b, 0x03, 0xac, 0xef, 0xe1, 0x31, 0x31, + 0x4d, 0xda, 0x19, 0x15, 0xbf, 0xa6, 0x27, 0xd8, 0x87, 0x66, 0x91, 0x1d, 0x7d, 0x18, 0xfe, 0x5b, 0x9d, 0xa8, 0xcf, + 0xbe, 0x3a, 0x00, 0x72, 0x04, 0x32, 0x50, 0x2c, 0x11, 0xcc, 0x70, 0xa0, 0x29, 0xa0, 0x20, 0xd3, 0xe3, 0x4e, 0xf5, + 0xf0, 0xab, 0x51, 0x53, 0x33, 0x72, 0x0d, 0x53, 0x83, 0x6d, 0xc1, 0x0f, 0x54, 0x37, 0xf4, 0x37, 0x1a, 0xdd, 0x48, + 0x3b, 0x99, 0x99, 0x97, 0xd4, 0xc6, 0x75, 0xbb, 0x86, 0x00, 0xc6, 0x0e, 0x5e, 0x50, 0xb2, 0xaf, 0x0f, 0x2f, 0xf7, + 0x70, 0x15, 0x01, 0x4a, 0x16, 0x0b, 0xbe, 0x1e, 0x5c, 0xea, 0xcd, 0xbd, 0x17, 0x90, 0xc1, 0xd7, 0xc1, 0xd1, 0xd7, + 0x03, 0x39, 0x08, 0x0e, 0xf7, 0x2f, 0x8f, 0x02, 0x67, 0xdc, 0x0f, 0x21, 0x1e, 0x55, 0x45, 0x31, 0x13, 0xa6, 0x8a, + 0xc4, 0xd6, 0x9e, 0xdb, 0x7a, 0x95, 0xf1, 0x19, 0x4d, 0xa7, 0x16, 0xf9, 0x3b, 0x4c, 0x59, 0x6c, 0x7e, 0x07, 0x13, + 0x7e, 0x15, 0x44, 0x2e, 0x08, 0xea, 0x2c, 0x8f, 0x62, 0xba, 0x64, 0xb7, 0x22, 0x4c, 0x69, 0xb2, 0x9f, 0x13, 0x12, + 0x85, 0x4b, 0x05, 0x9e, 0xa7, 0x5e, 0x27, 0x10, 0xc7, 0xd5, 0x7d, 0x7e, 0x2b, 0xc2, 0x25, 0xcd, 0xf7, 0x13, 0xd2, + 0x2a, 0xc2, 0x45, 0x64, 0xd9, 0xd4, 0xf4, 0x82, 0x85, 0x2b, 0x7a, 0x09, 0xcc, 0x94, 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, 0xed, 0x4d, 0x6c, 0x4e, 0xf6, 0x32, 0x5a, 0x2b, 0x97, 0x55, 0xcb, 0x90, 0x14, 0x6b, 0x86, + 0xfc, 0x3d, 0x4a, 0x4e, 0xad, 0xc0, 0x93, 0x5d, 0xf0, 0x2a, 0x59, 0xfa, 0x07, 0x95, 0xb5, 0x1a, 0xb0, 0xc7, 0x88, + 0x65, 0xa1, 0x70, 0xec, 0xdf, 0x64, 0xac, 0x58, 0xfb, 0x02, 0x8d, 0x18, 0xb9, 0xb7, 0x37, 0x19, 0xf3, 0x62, 0xae, + 0x26, 0x6b, 0x2f, 0x54, 0x9d, 0x97, 0x9e, 0xb7, 0x78, 0x2f, 0xa7, 0xd4, 0x30, 0x12, 0xd1, 0xbd, 0xb1, 0x32, 0xa3, + 0x54, 0x89, 0x5a, 0x83, 0x46, 0x04, 0x1b, 0xbb, 0xe0, 0x97, 0xe0, 0x84, 0xca, 0x3d, 0x75, 0xb6, 0x6f, 0xa7, 0x54, + 0x7a, 0xc0, 0xb2, 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, + 0x24, 0x77, 0xb9, 0x6e, 0x05, 0xc9, 0x7d, 0x3a, 0x7e, 0xaa, 0x07, 0x3a, 0x5d, 0x6b, 0xc7, 0x43, 0x9f, 0xdf, 0x46, + 0x7c, 0x6d, 0xdd, 0x7b, 0xaa, 0xb5, 0x0a, 0x65, 0xa0, 0xc5, 0x8a, 0xca, 0x95, 0x5a, 0xd2, 0xfb, 0x5d, 0x04, 0xc0, + 0x22, 0x36, 0x66, 0xe3, 0x5d, 0xdb, 0xac, 0x10, 0x34, 0xba, 0xec, 0x68, 0x13, 0x0f, 0x58, 0xa2, 0x5b, 0x3b, 0x98, + 0xd0, 0xf8, 0x88, 0x95, 0xfd, 0x7e, 0x7e, 0x04, 0xf4, 0x54, 0x1b, 0x31, 0x15, 0x70, 0xe4, 0x7f, 0x69, 0x45, 0xa6, + 0x28, 0xb0, 0x59, 0x53, 0x77, 0x6b, 0x2c, 0x23, 0xd1, 0x97, 0x29, 0x5d, 0x9e, 0xf0, 0x0c, 0x98, 0xd6, 0xeb, 0x96, + 0xe3, 0xca, 0xae, 0xe2, 0xc8, 0x53, 0x61, 0x59, 0x71, 0x5e, 0x85, 0xe3, 0xad, 0xc7, 0x37, 0xd8, 0x37, 0x6c, 0xda, + 0x85, 0x3f, 0x84, 0xb0, 0x10, 0xde, 0x64, 0x70, 0x1b, 0xd1, 0x76, 0x12, 0xa8, 0xbc, 0x31, 0xd7, 0x09, 0x65, 0x73, + 0xbb, 0x5e, 0x7b, 0x06, 0xe9, 0xc4, 0x1c, 0x28, 0xd5, 0x08, 0x5a, 0xa3, 0x59, 0x50, 0x35, 0xe2, 0x91, 0xe3, 0xe1, + 0x9d, 0x41, 0xac, 0x96, 0x2f, 0x69, 0x2a, 0x45, 0x03, 0x30, 0x2e, 0x80, 0xcb, 0xd3, 0xaf, 0xef, 0x7f, 0x3e, 0xe5, + 0x71, 0x91, 0x2c, 0xdf, 0xc5, 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, 0xdd, 0x07, 0x20, 0x4f, 0xe3, 0x42, 0x1a, 0x49, 0x5d, 0x88, 0x31, 0x17, 0xf1, 0xba, 0x3e, 0x1e, 0x37, + 0xba, 0x5e, 0xb2, 0x67, 0xe3, 0x27, 0xd3, 0x37, 0x59, 0x98, 0x0d, 0x04, 0x19, 0x55, 0x4b, 0x2e, 0x5a, 0xa6, 0x9c, + 0xca, 0x24, 0x00, 0x7d, 0x3c, 0x7b, 0x8c, 0x1d, 0x8c, 0xc7, 0x64, 0xd3, 0x16, 0x0f, 0xf0, 0x70, 0xb9, 0x0e, 0x0b, + 0x32, 0xd3, 0x75, 0x44, 0x81, 0xe0, 0xb7, 0x55, 0x00, 0x48, 0x8e, 0xb6, 0x2a, 0xc3, 0xa5, 0xb1, 0x67, 0xe3, 0x09, + 0x95, 0xd8, 0xed, 0x90, 0xd4, 0x5e, 0x85, 0x6e, 0xe6, 0xa5, 0xef, 0x51, 0x24, 0x8d, 0xcb, 0xd2, 0x4e, 0xa5, 0x52, + 0xed, 0x99, 0x99, 0xeb, 0x1a, 0xc4, 0x60, 0x08, 0x75, 0xdd, 0xa5, 0x57, 0xf7, 0x6e, 0x73, 0xad, 0xd9, 0x0e, 0x78, + 0xaf, 0x41, 0x33, 0x94, 0xbc, 0xc5, 0xbc, 0x75, 0x45, 0xd4, 0x74, 0xb5, 0x06, 0xb3, 0x62, 0x94, 0x2d, 0x45, 0xe9, + 0x9a, 0x82, 0x52, 0x30, 0xba, 0x58, 0x7b, 0x0b, 0xf7, 0x8d, 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, 0xc7, + 0x15, 0x39, 0x06, 0x47, 0x2f, 0x93, 0xd3, 0x50, 0xe0, 0x1f, 0x33, 0x05, 0x62, 0x3a, 0x54, 0xf7, 0x1b, 0xdc, 0xfc, + 0xff, 0x28, 0x58, 0xe0, 0xf1, 0xad, 0x97, 0xb8, 0x8d, 0xfe, 0x51, 0xf8, 0xb4, 0xf4, 0xb9, 0xf4, 0x5d, 0x5d, 0x3c, + 0x69, 0x6f, 0x36, 0x4a, 0x96, 0x59, 0x9e, 0xbe, 0x95, 0x29, 0x07, 0x91, 0x19, 0x5a, 0x83, 0xb2, 0x23, 0xd1, 0xb8, + 0xe1, 0x81, 0x11, 0x63, 0xe3, 0xc6, 0xf7, 0x63, 0x06, 0xb2, 0x61, 0xb0, 0xfa, 0x66, 0xa9, 0x4c, 0xd6, 0x57, 0x80, + 0x29, 0xa2, 0xe4, 0x27, 0x2f, 0x73, 0x0e, 0x4f, 0xa1, 0xbe, 0x7e, 0x81, 0xdb, 0x5c, 0xe9, 0xfb, 0x9c, 0xff, 0x98, + 0xd1, 0x1f, 0x11, 0xe8, 0x24, 0x5e, 0x81, 0xdc, 0xe3, 0x39, 0xd4, 0x8d, 0x30, 0xb5, 0x1c, 0x83, 0x03, 0x21, 0x1a, + 0x88, 0xa8, 0x58, 0xa0, 0xa0, 0x2e, 0x0c, 0xb0, 0x86, 0xba, 0x60, 0x0e, 0xcf, 0x73, 0x99, 0x7c, 0x9c, 0x1a, 0x9f, + 0xf9, 0x61, 0x8c, 0x31, 0x93, 0x83, 0x41, 0x58, 0xcd, 0x82, 0xe1, 0x78, 0x34, 0x39, 0x78, 0x06, 0xe7, 0x76, 0x30, + 0x0e, 0xc8, 0x20, 0xa8, 0xcb, 0x55, 0x2c, 0x68, 0x79, 0x7d, 0x69, 0xcb, 0xc0, 0x8f, 0xeb, 0x60, 0xf0, 0x8f, 0xc2, + 0x53, 0xbc, 0x83, 0xe6, 0xe4, 0x4c, 0x86, 0x60, 0x63, 0xbf, 0x26, 0x20, 0x29, 0xeb, 0x69, 0x7e, 0x52, 0x1f, 0x6e, + 0x4c, 0x69, 0xff, 0xcc, 0xe1, 0x05, 0x87, 0x1d, 0x12, 0x28, 0x90, 0xc6, 0xd3, 0x6c, 0xf4, 0x5a, 0x29, 0x72, 0xdf, + 0x15, 0x1c, 0xee, 0xcc, 0x3d, 0x67, 0x7a, 0xe4, 0x14, 0x12, 0xcd, 0x2c, 0xe0, 0x46, 0xfe, 0x5a, 0x5c, 0xc7, 0x79, + 0x96, 0xee, 0x35, 0xdf, 0xec, 0x95, 0x77, 0xa2, 0x8a, 0x6f, 0x47, 0x81, 0xb1, 0x26, 0xe4, 0xbe, 0xea, 0x09, 0xd0, + 0x13, 0x60, 0x0b, 0x80, 0x01, 0xf1, 0x8e, 0x99, 0xc9, 0x8c, 0x47, 0xe0, 0x11, 0xd8, 0xf4, 0x81, 0x2c, 0xee, 0x9c, + 0x4b, 0x92, 0xbf, 0x99, 0x4a, 0x7b, 0xd5, 0x2b, 0x77, 0x0a, 0xb2, 0x5e, 0x6d, 0xe5, 0xae, 0x5b, 0x9f, 0x7d, 0xd3, + 0xe1, 0x15, 0x78, 0x2e, 0xc1, 0x2d, 0xb2, 0xdf, 0x6f, 0x0a, 0x2a, 0x85, 0x51, 0x11, 0xef, 0x24, 0xd7, 0xe8, 0xdf, + 0xee, 0x8d, 0x8d, 0x22, 0xb9, 0xe5, 0xc3, 0x03, 0xa8, 0x33, 0x79, 0x57, 0xdc, 0xce, 0x21, 0x6a, 0xeb, 0x6e, 0x3c, + 0xb0, 0xda, 0xa0, 0x5d, 0xd6, 0x1c, 0xc1, 0x85, 0x17, 0x7b, 0x19, 0x8c, 0x05, 0xce, 0xca, 0x48, 0xa9, 0x71, 0x0d, + 0xa9, 0x05, 0x9f, 0xe4, 0xe9, 0x3d, 0x64, 0xa9, 0x27, 0x41, 0x91, 0xe3, 0x59, 0x0c, 0x99, 0xc6, 0xdb, 0xc0, 0xe3, + 0x77, 0x32, 0x04, 0x69, 0xda, 0x76, 0xdb, 0x1c, 0x81, 0xb2, 0x7b, 0x60, 0x4a, 0x52, 0xd7, 0xc6, 0xd4, 0x40, 0x43, + 0xed, 0xa1, 0x46, 0x2a, 0xe2, 0xec, 0xe8, 0x0d, 0xe8, 0x10, 0xc1, 0xf7, 0x3b, 0xcd, 0xca, 0x8e, 0x17, 0x13, 0x82, + 0x27, 0xef, 0xcb, 0xdb, 0xac, 0xac, 0xca, 0xe8, 0x7d, 0x8a, 0x86, 0x50, 0x89, 0x14, 0xd1, 0x2b, 0x88, 0xa7, 0x57, + 0xe2, 0xef, 0x32, 0xfa, 0x39, 0xa5, 0x71, 0x9a, 0x62, 0xfa, 0x8b, 0x02, 0x7e, 0x3e, 0x07, 0x54, 0x47, 0xdc, 0x09, + 0xd1, 0xb9, 0x04, 0x7b, 0x35, 0x88, 0x66, 0x55, 0x71, 0xc0, 0xd0, 0x8c, 0x6e, 0x05, 0x45, 0x8c, 0x36, 0xcc, 0xfe, + 0x43, 0x81, 0x42, 0x21, 0x55, 0xcc, 0x77, 0xc2, 0x3e, 0x44, 0x3f, 0x62, 0x91, 0xc7, 0xef, 0x5e, 0x9b, 0x21, 0x8d, + 0xee, 0x24, 0xd5, 0x5b, 0x1b, 0x8f, 0x2d, 0x0c, 0x5c, 0x16, 0x5d, 0xae, 0xe9, 0x59, 0xbc, 0xca, 0xa2, 0x0d, 0xe0, + 0x4f, 0xbc, 0x7b, 0xfd, 0x5c, 0x59, 0x98, 0xbc, 0xc8, 0x40, 0x71, 0x70, 0xfc, 0xee, 0xf5, 0x1b, 0x99, 0xae, 0x73, + 0x1e, 0x9d, 0x49, 0x24, 0xad, 0xc7, 0xef, 0x5e, 0xff, 0x82, 0xe6, 0x5e, 0x3f, 0x17, 0xf0, 0xfe, 0x15, 0xf0, 0x96, + 0x51, 0xbc, 0x86, 0x3e, 0xa9, 0xdf, 0xc9, 0x1a, 0x3b, 0xe5, 0xd5, 0x5a, 0x46, 0xbf, 0xa6, 0xb5, 0x27, 0xad, 0xfa, + 0x67, 0xe1, 0x53, 0x3b, 0x4f, 0xc0, 0x73, 0x9b, 0x67, 0xe2, 0x63, 0x64, 0x45, 0x3b, 0x41, 0xf4, 0xf5, 0xde, 0xed, + 0x55, 0x2e, 0xca, 0x08, 0x5f, 0x30, 0xb4, 0x0b, 0x8a, 0xf6, 0xf7, 0x6f, 0x6e, 0x6e, 0x46, 0x37, 0x4f, 0x46, 0xb2, + 0xb8, 0xdc, 0x9f, 0x7c, 0xfb, 0xed, 0xb7, 0xfb, 0xf8, 0x36, 0xf8, 0xba, 0xed, 0xf6, 0x5e, 0x11, 0x3e, 0x60, 0x01, + 0x22, 0x54, 0x7f, 0x0d, 0x57, 0x14, 0xd0, 0xc2, 0x0d, 0xbe, 0x0e, 0xbe, 0xd6, 0x87, 0xce, 0xd7, 0x87, 0xe5, 0xf5, + 0xa5, 0x2a, 0xbf, 0xab, 0xe4, 0x83, 0xf1, 0x78, 0xbc, 0x0f, 0x12, 0xa8, 0xaf, 0x07, 0x7c, 0x10, 0x1c, 0x05, 0x83, + 0x0c, 0x2e, 0x34, 0xe5, 0xf5, 0xe5, 0x51, 0xe0, 0x99, 0xe6, 0x36, 0x58, 0x44, 0x07, 0xe2, 0x12, 0xec, 0x5f, 0xd2, + 0xe0, 0xeb, 0x80, 0xb8, 0x94, 0xaf, 0x20, 0xe5, 0xab, 0x83, 0x67, 0x7e, 0xda, 0xff, 0x52, 0x69, 0x4f, 0xfc, 0xb4, + 0x43, 0x4c, 0x7b, 0xf2, 0xdc, 0x4f, 0x3b, 0x52, 0x69, 0x2f, 0xfd, 0xb4, 0xff, 0x5d, 0x0e, 0x20, 0x75, 0xcf, 0xb7, + 0xfe, 0x3b, 0xf7, 0x5a, 0x83, 0xa7, 0x50, 0x94, 0x5d, 0xc5, 0x97, 0x1c, 0x1a, 0x3d, 0xb8, 0xbd, 0xca, 0x69, 0x30, + 0xc0, 0xf6, 0x7a, 0x26, 0x21, 0xde, 0x07, 0x5f, 0xaf, 0x8b, 0x3c, 0x0c, 0xbe, 0x1e, 0x60, 0x21, 0x83, 0xaf, 0x03, + 0xf2, 0xb5, 0x31, 0x90, 0x11, 0x6c, 0x13, 0xb8, 0x50, 0xa4, 0x43, 0x1b, 0x20, 0xcc, 0x97, 0xc6, 0xd5, 0xf4, 0xaf, + 0xa2, 0x3b, 0x1b, 0xde, 0x12, 0x95, 0x9b, 0x6e, 0x50, 0xd3, 0x13, 0xf0, 0x4e, 0x80, 0x46, 0x45, 0xc1, 0x75, 0x5c, + 0x84, 0xc3, 0x61, 0x79, 0x7d, 0x49, 0xc0, 0x2e, 0x73, 0xc5, 0xe3, 0x2a, 0x0a, 0x84, 0x1c, 0xaa, 0x9f, 0x81, 0x8a, + 0x7c, 0x15, 0x20, 0x20, 0x12, 0xfc, 0x17, 0xd4, 0xf4, 0x9d, 0x64, 0x9b, 0x60, 0x78, 0xc3, 0xcf, 0x3f, 0x66, 0xd5, + 0x50, 0x89, 0x16, 0xaf, 0x05, 0x85, 0x1f, 0xf0, 0xd7, 0x55, 0x1d, 0xfd, 0x05, 0x6e, 0xdc, 0x4d, 0x0d, 0xfb, 0x3b, + 0xe9, 0x58, 0xd4, 0x77, 0x72, 0x9e, 0x2d, 0xa6, 0xad, 0x03, 0xfd, 0x44, 0x92, 0x6a, 0x9e, 0x0d, 0x82, 0x61, 0x30, + 0xe0, 0x0b, 0x76, 0x22, 0xe7, 0xdc, 0x33, 0x9f, 0x7a, 0x24, 0xfd, 0x69, 0x9e, 0x65, 0x03, 0xf0, 0x4d, 0x41, 0x7e, + 0x64, 0xff, 0xbf, 0xe7, 0x43, 0x14, 0x1e, 0x0e, 0x1e, 0xed, 0x93, 0x59, 0xb0, 0xba, 0x45, 0x8f, 0xce, 0x28, 0xc8, + 0xc4, 0x92, 0x17, 0x59, 0xe5, 0x2d, 0x95, 0xbb, 0x75, 0xdb, 0xcb, 0xe3, 0xde, 0xb3, 0x79, 0x15, 0x8b, 0x40, 0x9d, + 0x73, 0xa0, 0x78, 0x43, 0xd9, 0x53, 0xd9, 0x94, 0x90, 0x6a, 0x43, 0xde, 0xb0, 0x1c, 0xb0, 0xe0, 0xb0, 0x37, 0x1c, + 0xee, 0x05, 0x03, 0xa7, 0xce, 0x1d, 0x04, 0x7b, 0xc3, 0xe1, 0x51, 0xe0, 0xee, 0x43, 0xd9, 0xc8, 0xdd, 0x19, 0x69, + 0xc1, 0xfe, 0x59, 0x84, 0x25, 0x05, 0xf1, 0x98, 0xd4, 0xe2, 0x2f, 0x0d, 0x2e, 0x33, 0x00, 0xe8, 0x23, 0x25, 0x01, + 0x33, 0xb0, 0x32, 0x03, 0x08, 0xcd, 0x4d, 0x63, 0x76, 0x06, 0xcc, 0x23, 0x70, 0xcc, 0x23, 0x64, 0x1c, 0x00, 0xb1, + 0x24, 0xc0, 0xb9, 0x0b, 0xa2, 0x58, 0x17, 0xf2, 0x08, 0x40, 0xef, 0xf1, 0x27, 0x31, 0xa5, 0x60, 0x92, 0x8e, 0x55, + 0x08, 0x82, 0x38, 0x3e, 0xbb, 0x16, 0xad, 0xc9, 0x59, 0xa2, 0x83, 0x19, 0x49, 0x80, 0x0d, 0x31, 0xb0, 0x73, 0x70, + 0x3f, 0x07, 0xa5, 0x87, 0xd5, 0x3b, 0x21, 0x17, 0x7c, 0xc7, 0x3d, 0xd9, 0x2c, 0x5c, 0x3d, 0xe1, 0x20, 0xb8, 0xe3, + 0x9a, 0x05, 0x18, 0x55, 0xc5, 0xba, 0xac, 0x78, 0xfa, 0xe1, 0x6e, 0x05, 0xb1, 0xef, 0x70, 0x40, 0xdf, 0xc9, 0x3c, + 0x4b, 0xee, 0x42, 0x67, 0xcf, 0xb5, 0x51, 0xe9, 0x3f, 0x7c, 0x78, 0xf3, 0x73, 0x04, 0x22, 0xc7, 0xda, 0x50, 0xfa, + 0x3b, 0x8e, 0x67, 0x93, 0x1f, 0xe1, 0xc9, 0xdf, 0xd8, 0x77, 0xdc, 0x9e, 0x1e, 0xfd, 0x3e, 0xd4, 0x4d, 0xef, 0xf8, + 0xec, 0x8e, 0x8f, 0x5c, 0x71, 0xa8, 0xae, 0x70, 0x5f, 0xdf, 0xac, 0x7d, 0x23, 0xa4, 0x87, 0xe7, 0x99, 0xf2, 0xc6, + 0xfc, 0x68, 0x07, 0xc3, 0x20, 0x98, 0x6a, 0xa1, 0x24, 0x44, 0xdd, 0x60, 0x4a, 0xc0, 0x10, 0xed, 0xe9, 0x65, 0x35, + 0x45, 0xce, 0x4d, 0x8d, 0x2c, 0xbc, 0x1f, 0x30, 0x2d, 0x74, 0x68, 0xe4, 0x50, 0x7e, 0x70, 0x38, 0x61, 0xcc, 0xc2, + 0x6f, 0x95, 0x30, 0xfd, 0x6a, 0x51, 0x39, 0x07, 0xd1, 0x3d, 0x30, 0xc6, 0x15, 0xbc, 0x80, 0xae, 0xb0, 0xeb, 0xb5, + 0x8a, 0x8a, 0x81, 0xe0, 0x71, 0xc8, 0x01, 0x7a, 0xd8, 0x05, 0x2d, 0x2b, 0x4b, 0x75, 0xab, 0x72, 0x96, 0x2a, 0xea, + 0x32, 0x94, 0x95, 0xb1, 0xc2, 0x7c, 0x2f, 0xd9, 0x0f, 0x05, 0x7a, 0x96, 0x4f, 0x45, 0x17, 0xbc, 0x10, 0x4a, 0xb0, + 0x5c, 0xd7, 0x3b, 0x11, 0x88, 0x3a, 0x3f, 0xf4, 0xae, 0xfa, 0x1a, 0xc7, 0x8e, 0xa7, 0x6f, 0x64, 0xca, 0xb5, 0x09, + 0x85, 0xe6, 0xf3, 0xa5, 0xaf, 0x98, 0x28, 0xd8, 0x0d, 0xf4, 0xab, 0x6d, 0xa3, 0xcf, 0xee, 0xd6, 0x7a, 0x33, 0x28, + 0xd1, 0x31, 0xaf, 0x51, 0x70, 0xad, 0x14, 0x0a, 0x46, 0x7b, 0x1b, 0x7f, 0x86, 0x23, 0xb7, 0xba, 0x3d, 0xf4, 0x7e, + 0xab, 0xe2, 0xcb, 0xb7, 0xe8, 0xdb, 0x69, 0x7f, 0x8e, 0x2a, 0xf9, 0xeb, 0x6a, 0x05, 0x3e, 0x54, 0x10, 0x59, 0xc4, + 0xe2, 0xd2, 0x42, 0x3d, 0xa7, 0xef, 0x8e, 0xdf, 0x82, 0x1f, 0x25, 0xfe, 0xfe, 0xed, 0xfb, 0xa0, 0x26, 0xd3, 0x78, + 0x56, 0x98, 0x0f, 0x6d, 0x0e, 0x08, 0x4d, 0xe2, 0xd2, 0xec, 0xfb, 0x59, 0xdc, 0x64, 0xdf, 0x35, 0x5b, 0x4f, 0x8b, + 0x26, 0x92, 0x94, 0xe1, 0xf6, 0xc1, 0x80, 0x40, 0x1f, 0x20, 0x8a, 0xb3, 0x2f, 0x68, 0x0c, 0x69, 0x3e, 0xb3, 0xef, + 0x47, 0xc4, 0x7b, 0xb9, 0x13, 0x42, 0x8c, 0x2b, 0x2c, 0x1a, 0x3d, 0xe4, 0x33, 0x1e, 0x29, 0xc3, 0xa2, 0xf7, 0x98, + 0x40, 0x9c, 0xe1, 0xb4, 0x7a, 0x8f, 0x98, 0xc7, 0x78, 0x37, 0xd0, 0xb2, 0x87, 0x28, 0xa3, 0x2e, 0x7b, 0xc3, 0xe2, + 0xfb, 0xe3, 0x3a, 0xcc, 0xac, 0xe5, 0xe5, 0x10, 0xfe, 0x06, 0xda, 0x00, 0x9c, 0x72, 0x64, 0xf9, 0x2a, 0xb3, 0xd1, + 0xd5, 0x12, 0xd3, 0x9b, 0x08, 0x62, 0xf1, 0xe8, 0x74, 0x58, 0xbb, 0x3a, 0x55, 0xef, 0x6a, 0xe7, 0x33, 0xd1, 0xab, + 0x40, 0x2b, 0xd7, 0xb6, 0xc7, 0x43, 0xb8, 0x4b, 0x2d, 0xad, 0xb0, 0x11, 0xe5, 0x5c, 0x3c, 0xdd, 0x39, 0x36, 0x27, + 0xa0, 0xc1, 0x95, 0x4c, 0x01, 0x38, 0x4b, 0xab, 0xd1, 0xa8, 0x11, 0xf6, 0x59, 0x39, 0x9f, 0xc3, 0xd6, 0x42, 0x3c, + 0x2d, 0x00, 0xc3, 0x6d, 0x62, 0x50, 0xf2, 0x6e, 0x0c, 0xca, 0xe9, 0x47, 0x05, 0x6f, 0x1d, 0x9c, 0x95, 0xcb, 0x38, + 0x95, 0x37, 0x80, 0xc5, 0x18, 0xf8, 0xa9, 0x58, 0xaa, 0x97, 0x90, 0x2c, 0x79, 0xf2, 0x11, 0xad, 0x36, 0xd2, 0x00, + 0xb8, 0xca, 0xa9, 0xb1, 0xdc, 0x53, 0x20, 0xa1, 0xae, 0x14, 0x95, 0x10, 0x57, 0x55, 0x9c, 0x2c, 0x4f, 0x31, 0x35, + 0xdc, 0x40, 0x2f, 0xa2, 0x40, 0xae, 0xb8, 0x00, 0x92, 0x9e, 0xb3, 0x7f, 0x65, 0x1a, 0x6b, 0xfc, 0xb9, 0x44, 0x01, + 0x93, 0x46, 0x0d, 0xc6, 0x4a, 0xd9, 0x4b, 0x69, 0xa2, 0xbd, 0x05, 0x41, 0xed, 0x5e, 0xfe, 0x05, 0x75, 0x3f, 0x87, + 0x56, 0x84, 0x0d, 0x30, 0x44, 0x79, 0x8e, 0x3b, 0x34, 0xb5, 0x4b, 0xce, 0x03, 0x46, 0x74, 0xde, 0x67, 0xb5, 0xdd, + 0xea, 0xcf, 0x97, 0x80, 0x6d, 0x9a, 0x1a, 0x9f, 0xc2, 0x30, 0x21, 0x26, 0x36, 0xb0, 0x55, 0x56, 0xda, 0x0d, 0x65, + 0xda, 0x49, 0x97, 0xcc, 0x6b, 0xe1, 0x34, 0xef, 0x31, 0xb6, 0x1c, 0xa9, 0xdc, 0xfd, 0x7e, 0x68, 0x7e, 0xb2, 0x9c, + 0x3e, 0xd7, 0x21, 0x9b, 0xbd, 0xf1, 0xa0, 0x39, 0xd1, 0xea, 0xaa, 0x8e, 0x7e, 0x40, 0x07, 0x60, 0xa6, 0x2d, 0x40, + 0xa6, 0x0b, 0x36, 0xed, 0x2b, 0x51, 0x71, 0x49, 0xc2, 0x52, 0x49, 0x60, 0x67, 0x37, 0x25, 0x3b, 0x9b, 0x80, 0x78, + 0x86, 0xbb, 0x9e, 0x16, 0x3b, 0x21, 0x4d, 0x78, 0x8b, 0xbd, 0x04, 0x44, 0x1d, 0xaa, 0xba, 0x84, 0x6c, 0x8c, 0xa1, + 0x8b, 0x7f, 0x51, 0x0a, 0x13, 0xd6, 0x32, 0xa9, 0x4a, 0x4c, 0x10, 0xa4, 0x72, 0xb7, 0x45, 0x60, 0x89, 0x82, 0x1d, + 0xc0, 0xde, 0xbb, 0x51, 0x37, 0xa3, 0xa6, 0xaa, 0x53, 0x2f, 0xc1, 0xc7, 0x69, 0xd6, 0x55, 0x90, 0x59, 0xd8, 0x55, + 0xb1, 0xe6, 0x81, 0x8e, 0x4d, 0xa5, 0x8c, 0x89, 0xbb, 0xb4, 0xc8, 0x10, 0x0f, 0x18, 0x63, 0xe9, 0x42, 0x20, 0xdf, + 0x6c, 0x77, 0xdc, 0xf4, 0x04, 0xa1, 0x9f, 0xb0, 0xa1, 0x04, 0x6e, 0x3a, 0xdb, 0x53, 0xd3, 0xcc, 0x07, 0x44, 0x1c, + 0x06, 0x14, 0x48, 0x36, 0x0e, 0x69, 0x8e, 0xf4, 0x05, 0x49, 0x13, 0x06, 0x86, 0x56, 0x3c, 0x27, 0xc8, 0x8a, 0x42, + 0xcf, 0xd6, 0x55, 0x1b, 0xe7, 0xca, 0x30, 0x47, 0x4b, 0x4e, 0x85, 0xcf, 0x09, 0x32, 0xb1, 0x7b, 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, 0x68, 0x18, 0x62, 0xb7, 0x3f, 0xc1, 0x7e, 0xad, 0x9d, 0xd6, 0x65, 0x8a, 0xe5, 0x65, 0x0a, + 0xd1, 0x5e, 0xc8, 0xfc, 0x46, 0x91, 0xe8, 0x4e, 0x11, 0x86, 0x84, 0x75, 0x94, 0x3d, 0x69, 0x53, 0x03, 0xe8, 0xa9, + 0x17, 0xf0, 0xbc, 0x73, 0x2d, 0xc3, 0x2e, 0xd2, 0xfd, 0x55, 0xc1, 0xa7, 0x74, 0x83, 0x20, 0x45, 0x6f, 0x52, 0x30, + 0xe7, 0xf5, 0x28, 0xa9, 0x37, 0xa7, 0x2d, 0x33, 0xaa, 0x8e, 0x8a, 0x90, 0x72, 0x82, 0xff, 0xe4, 0xa5, 0xd4, 0xc4, + 0x26, 0x4c, 0xf0, 0xc0, 0x87, 0x79, 0x86, 0x0d, 0xbc, 0xdd, 0xbe, 0x4b, 0xc3, 0xa4, 0xcd, 0x36, 0xa4, 0x20, 0xad, + 0x30, 0x71, 0x31, 0xa0, 0xb2, 0xd7, 0xb8, 0x5f, 0xb0, 0x9d, 0x34, 0x05, 0x0f, 0xc2, 0x46, 0x03, 0x13, 0xb7, 0xba, + 0xf8, 0x3a, 0x4c, 0x68, 0xb8, 0xa4, 0xda, 0xd9, 0x49, 0x4b, 0x9a, 0xdb, 0xeb, 0xf2, 0xc2, 0xf6, 0x41, 0xc7, 0x0e, + 0xeb, 0x1a, 0x1e, 0x68, 0x5e, 0xb3, 0x8b, 0x2b, 0xa6, 0x69, 0xa2, 0xb1, 0x1e, 0x52, 0x96, 0x1c, 0xeb, 0x7a, 0xba, + 0xc2, 0xd5, 0x32, 0xd3, 0xc0, 0xee, 0x12, 0x2f, 0xf4, 0x80, 0x87, 0x1d, 0xae, 0x48, 0x74, 0x81, 0xcd, 0x66, 0xab, + 0x9a, 0x4c, 0xf3, 0xfb, 0xb2, 0xe5, 0x26, 0x20, 0x9c, 0xa5, 0xbe, 0xb9, 0x4f, 0x8e, 0x35, 0x6d, 0xf3, 0x93, 0x00, + 0xc7, 0xdb, 0x2b, 0x20, 0xe9, 0x58, 0x82, 0x2e, 0xbe, 0xa5, 0x3f, 0x88, 0xd4, 0x4c, 0x05, 0xbd, 0x77, 0xbe, 0x48, + 0xdd, 0xfc, 0x02, 0x6c, 0xa3, 0x36, 0xc6, 0x34, 0x2b, 0x5b, 0x87, 0x89, 0xb2, 0xb0, 0x46, 0x16, 0x72, 0x09, 0x3e, + 0x98, 0xbb, 0x4d, 0x9d, 0x1e, 0x77, 0x10, 0x61, 0xbf, 0x8b, 0x1e, 0x8f, 0x30, 0x56, 0xac, 0x41, 0x62, 0x58, 0x85, + 0x35, 0x6d, 0x2e, 0x87, 0x28, 0xa7, 0x66, 0xc9, 0x44, 0x4b, 0xea, 0x53, 0x8a, 0x28, 0x05, 0x73, 0xe3, 0x69, 0xd9, + 0x30, 0x25, 0x44, 0xc8, 0x0a, 0xe9, 0x80, 0x6a, 0x2d, 0xb4, 0x54, 0x13, 0xf4, 0x3a, 0xf4, 0xb2, 0xd0, 0x98, 0x82, + 0xe8, 0x23, 0x32, 0xdc, 0x88, 0x23, 0xa3, 0xbb, 0x63, 0x14, 0x13, 0x08, 0x55, 0xed, 0xe5, 0x85, 0xd5, 0xa7, 0x65, + 0x5b, 0x1d, 0xc4, 0x15, 0x22, 0xdf, 0x77, 0x13, 0xd4, 0x18, 0x05, 0x6d, 0x4e, 0x37, 0xfa, 0x6b, 0x11, 0xfa, 0x76, + 0xe1, 0xd8, 0x8d, 0x82, 0x48, 0x88, 0xc0, 0xea, 0x35, 0x15, 0x03, 0xb2, 0xce, 0x63, 0x17, 0xa1, 0x49, 0x77, 0x0b, + 0x51, 0xde, 0xa8, 0xac, 0x3f, 0xae, 0x43, 0xb2, 0xdd, 0x62, 0x59, 0xe0, 0xcb, 0x7e, 0xba, 0xbe, 0x07, 0xf2, 0xfb, + 0xcd, 0xfa, 0xb3, 0x90, 0xdf, 0xaf, 0xb3, 0x2f, 0x81, 0xfc, 0x7e, 0xb3, 0xfe, 0x9f, 0x86, 0xfc, 0x3e, 0x5d, 0x7b, + 0x90, 0xdf, 0x6a, 0x30, 0x7e, 0x2f, 0x58, 0x70, 0xf2, 0x36, 0xa0, 0x2f, 0x24, 0x0b, 0x4e, 0x5e, 0xbd, 0xf2, 0x8d, + 0x40, 0x84, 0x46, 0xae, 0x37, 0xb2, 0x60, 0xc4, 0x6d, 0x81, 0x57, 0xa8, 0x75, 0xf2, 0x81, 0x8a, 0x32, 0x00, 0x5e, + 0x2f, 0xff, 0x91, 0x55, 0xcb, 0x30, 0xd8, 0x0f, 0xc8, 0xcc, 0x41, 0x82, 0x0e, 0x27, 0x70, 0x7b, 0x43, 0x23, 0xcb, + 0xea, 0x8b, 0xe0, 0xc3, 0x47, 0xa3, 0x51, 0x5c, 0x5c, 0xe2, 0xa5, 0xce, 0x6c, 0x24, 0x04, 0x3c, 0xce, 0x78, 0x69, + 0x43, 0x44, 0x2c, 0xe3, 0xf2, 0x4c, 0xc7, 0x66, 0x29, 0xed, 0x56, 0x84, 0x88, 0xf3, 0x67, 0x80, 0x53, 0x6f, 0xf7, + 0x66, 0x8c, 0xfd, 0x50, 0x1c, 0xb1, 0x0e, 0x20, 0xfb, 0x7c, 0xad, 0xdf, 0x9d, 0xc7, 0x25, 0x7f, 0x17, 0x57, 0x4b, + 0x06, 0xbd, 0x84, 0xbb, 0x88, 0xe0, 0x49, 0xe5, 0xb1, 0x4d, 0x0a, 0xa8, 0x3c, 0xd3, 0x40, 0xe5, 0x1d, 0xef, 0x69, + 0x68, 0x87, 0x45, 0xfb, 0x00, 0x1b, 0xe9, 0x72, 0x06, 0x46, 0x8b, 0x2f, 0xaf, 0xb9, 0xa8, 0x7e, 0x06, 0x3c, 0x75, + 0xc1, 0x0b, 0xb8, 0x25, 0x20, 0x17, 0xdb, 0x70, 0x42, 0xa0, 0xc2, 0xf7, 0xec, 0x50, 0x51, 0x63, 0x8c, 0x68, 0xa2, + 0xd1, 0x6f, 0xbc, 0x09, 0xa1, 0x77, 0x27, 0xe8, 0x8a, 0x30, 0x12, 0xde, 0x5f, 0x6b, 0x7e, 0x96, 0x81, 0xf9, 0xbc, + 0x00, 0x28, 0x0d, 0x84, 0x43, 0x65, 0x4a, 0x6e, 0x81, 0x09, 0x1b, 0x63, 0xae, 0x94, 0xa5, 0x1e, 0x52, 0x29, 0x55, + 0x70, 0xba, 0x82, 0xa6, 0x12, 0x70, 0xb8, 0x23, 0x09, 0x60, 0xa6, 0xb6, 0x30, 0x88, 0x6e, 0x9b, 0xd2, 0x2c, 0x8d, + 0x9c, 0x22, 0xcd, 0xe1, 0x93, 0x52, 0x05, 0x3a, 0x7d, 0x96, 0xc4, 0x15, 0xbf, 0x94, 0x05, 0x84, 0xc2, 0x6d, 0xa5, + 0x50, 0xa4, 0xdf, 0x67, 0x62, 0x7d, 0xc5, 0x8b, 0x2c, 0x39, 0x5b, 0x66, 0x65, 0x05, 0xf9, 0xe6, 0xfa, 0xf4, 0x5b, + 0xd4, 0xd3, 0x02, 0xe7, 0x4d, 0x4d, 0x0a, 0x33, 0xf3, 0x78, 0xac, 0x76, 0x3a, 0xa8, 0x57, 0xbd, 0xd7, 0x06, 0xfb, + 0xbd, 0x39, 0xd1, 0xe3, 0xd6, 0x7a, 0xb0, 0x9a, 0xd4, 0x66, 0xaa, 0x82, 0x38, 0x02, 0xea, 0xc0, 0x8e, 0x70, 0x16, + 0x53, 0xba, 0xb6, 0x08, 0x2a, 0x60, 0xed, 0x80, 0x39, 0x32, 0x71, 0x79, 0x76, 0xa3, 0xe4, 0x27, 0x3d, 0x45, 0x61, + 0xd2, 0x28, 0x56, 0xc8, 0x3e, 0x4b, 0x16, 0xae, 0x59, 0x72, 0x4f, 0xae, 0x75, 0x94, 0x34, 0x30, 0xba, 0xe2, 0xf6, + 0x40, 0x1c, 0x26, 0xed, 0x94, 0xed, 0x76, 0x27, 0x13, 0xb0, 0x06, 0xad, 0x24, 0x88, 0xd6, 0xb1, 0x9c, 0x0d, 0x27, + 0x11, 0x40, 0xa8, 0x68, 0xb2, 0xf6, 0xd7, 0x9a, 0x1b, 0x90, 0xf9, 0x50, 0x7b, 0xfa, 0x39, 0x91, 0xbc, 0x1e, 0x59, + 0xcf, 0x38, 0x4e, 0x4f, 0xfb, 0x1c, 0x0c, 0xb3, 0xfc, 0x21, 0x81, 0x48, 0x30, 0x9d, 0xd3, 0xb3, 0x98, 0x6a, 0x33, + 0x61, 0xc3, 0xa3, 0xd0, 0x2f, 0xfb, 0x4e, 0x03, 0xe0, 0x26, 0x3c, 0x1c, 0x3e, 0x1b, 0x93, 0x5a, 0xdb, 0xac, 0xe3, + 0x02, 0xb2, 0xbf, 0xd5, 0x22, 0x73, 0xcf, 0x76, 0xa1, 0xd1, 0xa6, 0xb7, 0x41, 0xbb, 0x46, 0x2a, 0xee, 0xe9, 0x7e, + 0x4d, 0x6a, 0xb7, 0x60, 0xac, 0x04, 0xe9, 0x0f, 0x75, 0x6a, 0x9d, 0x3d, 0xda, 0x64, 0xba, 0xca, 0xfa, 0x8f, 0xcc, + 0xc6, 0x9b, 0x6b, 0x50, 0x80, 0x5a, 0x2f, 0x25, 0x1f, 0xee, 0xad, 0x23, 0x9b, 0x9e, 0x18, 0x96, 0x75, 0x92, 0x91, + 0x91, 0x7a, 0xe4, 0x2a, 0xfc, 0x56, 0x77, 0x16, 0x7e, 0xcb, 0x93, 0xb0, 0xab, 0x61, 0x8a, 0xc3, 0x37, 0x5d, 0x40, + 0x04, 0x4c, 0x90, 0xeb, 0x87, 0x7f, 0x3c, 0xda, 0x34, 0xc9, 0x52, 0xbd, 0xef, 0x7d, 0x86, 0xbf, 0xb3, 0x14, 0xfe, + 0x56, 0xf5, 0x1f, 0x74, 0x73, 0xc5, 0xab, 0xa5, 0x4c, 0xa3, 0xe0, 0xdd, 0xc9, 0xe9, 0x87, 0x40, 0x23, 0xab, 0xe3, + 0xfd, 0xc2, 0x68, 0x94, 0x0d, 0x86, 0x13, 0x68, 0x58, 0x72, 0x79, 0x89, 0xe0, 0x82, 0x1a, 0x9d, 0xfe, 0x74, 0x29, + 0x6f, 0x8e, 0xf3, 0xdc, 0x67, 0x82, 0x0d, 0xe1, 0xd4, 0x7c, 0x61, 0x83, 0xea, 0x84, 0x20, 0xcb, 0x1b, 0x65, 0xe5, + 0x99, 0xd6, 0xbe, 0xa4, 0x67, 0xe7, 0x77, 0x67, 0x5a, 0xc2, 0x63, 0xd1, 0x1d, 0x9f, 0xff, 0x71, 0x98, 0x66, 0xd7, + 0x7b, 0x48, 0xdd, 0x59, 0x00, 0xa6, 0xf1, 0x39, 0x3f, 0x5f, 0x57, 0x95, 0x14, 0xc3, 0x42, 0xde, 0x04, 0x47, 0x87, + 0xea, 0xc1, 0x64, 0x88, 0xd5, 0x63, 0xb0, 0xf7, 0x5f, 0x49, 0x9e, 0x25, 0x1f, 0x59, 0xf0, 0x68, 0x93, 0xb1, 0xa3, + 0x16, 0x0d, 0x1f, 0xd7, 0xc1, 0x11, 0xb4, 0x75, 0xef, 0x38, 0xcf, 0x0f, 0xf7, 0xd5, 0x17, 0x47, 0x87, 0xfb, 0x69, + 0x76, 0x7d, 0xe4, 0x01, 0xed, 0x3b, 0xbb, 0x59, 0x84, 0x34, 0x73, 0xf7, 0x62, 0x70, 0x90, 0x4d, 0x78, 0x68, 0x39, + 0x09, 0x90, 0xc6, 0x98, 0x30, 0x25, 0x28, 0xc1, 0x09, 0x63, 0x38, 0x37, 0xb7, 0xdb, 0xd0, 0x1a, 0xf5, 0x24, 0x1e, + 0xe2, 0x4d, 0x01, 0x9c, 0x06, 0x66, 0xa1, 0x09, 0xa1, 0x49, 0x4d, 0x42, 0x83, 0xcb, 0x13, 0x13, 0x5a, 0xd4, 0x14, + 0x8e, 0x92, 0x37, 0xf1, 0xca, 0x08, 0xb1, 0xb4, 0x50, 0xc0, 0xb4, 0x7e, 0xd6, 0x18, 0xc7, 0xa8, 0x3d, 0xaa, 0x06, + 0x29, 0xab, 0x57, 0xde, 0x37, 0xb0, 0x20, 0xb7, 0x0c, 0x2b, 0x1a, 0xb4, 0x28, 0x04, 0xc8, 0x1d, 0x7d, 0x71, 0x19, + 0xa7, 0xe1, 0xbc, 0xa4, 0x72, 0x41, 0xd8, 0x51, 0xb8, 0x41, 0xb6, 0xb9, 0x54, 0x54, 0x38, 0x92, 0xb5, 0x83, 0xad, + 0x54, 0xb3, 0x73, 0xf4, 0x68, 0x23, 0x10, 0x29, 0xb1, 0x64, 0x47, 0xcd, 0xf9, 0xaa, 0xe2, 0xf3, 0xe1, 0x92, 0x83, + 0x7f, 0x4d, 0xb0, 0xf7, 0x5f, 0xe9, 0x79, 0x6e, 0x27, 0x45, 0xad, 0xc8, 0x65, 0x2c, 0xd2, 0x9c, 0x7f, 0x88, 0xcf, + 0x7f, 0xc0, 0x3c, 0x2f, 0xce, 0xf3, 0xe7, 0x90, 0xa1, 0x0e, 0x8e, 0x1e, 0x6d, 0x92, 0x6a, 0xf4, 0xf2, 0xed, 0x87, + 0xd7, 0x1f, 0xfe, 0x79, 0xf6, 0xfc, 0xf8, 0xc3, 0xcb, 0xef, 0x4f, 0xde, 0xbf, 0x7e, 0x79, 0x3a, 0xb7, 0x0e, 0xad, + 0x0a, 0x27, 0x8d, 0x2c, 0xb6, 0x5b, 0x97, 0xef, 0xd7, 0xb7, 0x2f, 0x5e, 0xbe, 0x7a, 0xfd, 0xf6, 0xe5, 0x8b, 0x5a, + 0xcd, 0x65, 0xbb, 0x21, 0xb0, 0x43, 0xe3, 0x4c, 0xf0, 0x02, 0x8a, 0xd7, 0xd1, 0x1a, 0xb1, 0xd9, 0x1a, 0xde, 0xaf, + 0xd9, 0x74, 0x1d, 0x09, 0x01, 0x16, 0xd9, 0x9e, 0xde, 0x2c, 0xd0, 0x70, 0x69, 0x36, 0x8e, 0xbf, 0xc4, 0xfc, 0xde, + 0xbc, 0xc4, 0xef, 0xde, 0xcb, 0x1b, 0xd3, 0x15, 0x3d, 0x42, 0x0a, 0xb9, 0x6b, 0xf6, 0xfc, 0x8f, 0x43, 0x5f, 0x5a, + 0x86, 0x22, 0x05, 0x55, 0x2e, 0xfc, 0xaa, 0x83, 0x3d, 0x6d, 0xb9, 0x17, 0x40, 0xe0, 0x89, 0xe0, 0xe8, 0x70, 0xdf, + 0xcf, 0x7d, 0xf4, 0x47, 0xf4, 0xb3, 0xd7, 0x39, 0x2c, 0x15, 0xc6, 0xa1, 0x99, 0xb6, 0x73, 0xba, 0x41, 0x68, 0x24, + 0x77, 0xfe, 0xa9, 0x15, 0x64, 0xc8, 0x95, 0x24, 0x91, 0x9d, 0x44, 0x65, 0x91, 0x62, 0x4a, 0xfb, 0x43, 0xff, 0x75, + 0x7d, 0xc6, 0x1b, 0x3e, 0x17, 0xa5, 0x2c, 0x02, 0xe8, 0x47, 0x3b, 0x5e, 0xc4, 0x9e, 0x17, 0x97, 0x05, 0x7b, 0xd4, + 0x49, 0xde, 0x61, 0x44, 0xf6, 0xdb, 0x9f, 0x7a, 0x1d, 0xfb, 0x83, 0xb8, 0x1f, 0x7b, 0xba, 0x33, 0x2d, 0xf2, 0x62, + 0x1b, 0x78, 0x7f, 0x5c, 0x8f, 0xf9, 0x49, 0x46, 0xff, 0x21, 0xe9, 0x65, 0x4c, 0xaf, 0x62, 0x7a, 0x2a, 0x16, 0x75, + 0xe7, 0xec, 0xd8, 0x98, 0x31, 0x94, 0x4f, 0x43, 0x40, 0x9e, 0xd0, 0xf7, 0x01, 0xcd, 0x25, 0x67, 0x23, 0xad, 0x2b, + 0xfb, 0x10, 0x17, 0x97, 0xdc, 0x84, 0x6a, 0x31, 0x6f, 0x2b, 0x3d, 0x2a, 0xc4, 0x1b, 0x16, 0x80, 0x65, 0xe9, 0x69, + 0x93, 0x82, 0x6c, 0x94, 0x54, 0x45, 0xfe, 0x13, 0xbf, 0x03, 0xae, 0xad, 0xac, 0xe4, 0x0a, 0x78, 0xf5, 0xff, 0xd3, + 0xdc, 0xb3, 0x2e, 0xb7, 0x6d, 0x5c, 0xfd, 0xbf, 0x4f, 0x01, 0xc3, 0xae, 0x03, 0xd8, 0x00, 0x04, 0x90, 0xa2, 0x28, + 0x93, 0x22, 0x95, 0xc4, 0x76, 0xa6, 0xea, 0x28, 0x71, 0xc6, 0x56, 0x3d, 0x6d, 0x14, 0x8d, 0x08, 0x82, 0x4b, 0x12, + 0x35, 0x08, 0x60, 0x00, 0x50, 0xa2, 0x42, 0xa3, 0xcf, 0xd2, 0x67, 0xe9, 0x93, 0x7d, 0x73, 0xce, 0x5e, 0xb0, 0xb8, + 0x91, 0x54, 0xec, 0xb4, 0xdf, 0xa4, 0xaa, 0x89, 0xc5, 0xee, 0x62, 0xf7, 0xec, 0xee, 0xd9, 0x73, 0x3f, 0xee, 0x82, + 0xc9, 0x5e, 0x0c, 0x8d, 0x1c, 0xf6, 0xb9, 0xcf, 0x9f, 0x89, 0x85, 0x5b, 0x12, 0x08, 0x3e, 0x2b, 0x8b, 0x16, 0x8b, + 0x80, 0x68, 0x2a, 0x4f, 0x1e, 0xa2, 0x1a, 0xe2, 0x33, 0xe7, 0x4f, 0x6c, 0x1e, 0xb1, 0x53, 0xcf, 0xdb, 0x8e, 0x16, + 0x9f, 0x31, 0x11, 0x21, 0xed, 0x28, 0xe5, 0x8a, 0xb2, 0xd9, 0x3b, 0x54, 0x6f, 0xb0, 0x75, 0x29, 0x8e, 0xae, 0x39, + 0x8b, 0xd6, 0xd3, 0x80, 0x98, 0xb8, 0xdd, 0xe1, 0x93, 0xdb, 0xe9, 0x7a, 0x3a, 0x85, 0x2c, 0x2d, 0x4f, 0x6c, 0x03, + 0xe2, 0xce, 0x44, 0x29, 0xf2, 0x83, 0xb9, 0x3e, 0x84, 0x49, 0x59, 0x59, 0x75, 0xf8, 0x60, 0x2b, 0x02, 0xa2, 0x1e, + 0xfa, 0x81, 0x0c, 0x78, 0xbf, 0x86, 0x53, 0x3b, 0x52, 0x3f, 0xc0, 0xee, 0x4b, 0xd5, 0x61, 0xd3, 0xd1, 0x1f, 0x5d, + 0xab, 0x1f, 0x10, 0xc6, 0x98, 0xbd, 0xf8, 0x35, 0xdd, 0xbd, 0xaa, 0xa1, 0x52, 0xa5, 0xf7, 0x1a, 0xf3, 0x18, 0x80, + 0xd0, 0xf7, 0x8d, 0xef, 0x2e, 0xc2, 0x28, 0xcd, 0x7c, 0x4f, 0xbd, 0x19, 0x5e, 0xf8, 0xda, 0xf5, 0x2a, 0xd3, 0xf4, + 0x1b, 0xc3, 0xcb, 0xe4, 0x14, 0x28, 0x1c, 0x61, 0x62, 0x06, 0x94, 0xb6, 0x4a, 0xf2, 0x09, 0xda, 0x59, 0x91, 0xa3, + 0x66, 0xac, 0xe4, 0x65, 0x23, 0xa8, 0x57, 0xc9, 0xa7, 0x82, 0x89, 0xa1, 0x54, 0x6c, 0xa9, 0x0f, 0x29, 0xa7, 0xf2, + 0x7a, 0xbd, 0xc5, 0xab, 0x3c, 0x2b, 0x6e, 0x4b, 0x8c, 0x01, 0xcc, 0x1d, 0x67, 0xe8, 0xf3, 0x13, 0xd9, 0xe8, 0xb3, + 0x74, 0xef, 0x4e, 0xbe, 0x2b, 0xd3, 0x05, 0x70, 0x7f, 0x83, 0xc5, 0x45, 0x18, 0x65, 0x0a, 0x04, 0xb6, 0x81, 0x2f, + 0x4e, 0xaa, 0x46, 0x62, 0xac, 0x57, 0x4d, 0xcf, 0x19, 0x32, 0xf8, 0x1e, 0x2f, 0x3f, 0x8d, 0x85, 0x37, 0x2b, 0x45, + 0xb0, 0xa0, 0xcc, 0x42, 0x08, 0x0b, 0x98, 0x45, 0x97, 0xd1, 0x7d, 0x55, 0x0f, 0xf2, 0x7a, 0xb2, 0xff, 0xee, 0xd5, + 0x38, 0x99, 0xcc, 0xb3, 0xfa, 0x69, 0x2c, 0x31, 0x29, 0x27, 0x74, 0x2a, 0x67, 0x0a, 0x0d, 0x3f, 0x38, 0x0d, 0x93, + 0x81, 0x9d, 0x18, 0xde, 0x05, 0x80, 0x92, 0xd8, 0x35, 0x3d, 0xc9, 0x6f, 0x79, 0xea, 0x64, 0x9e, 0xb8, 0x58, 0xba, + 0x9c, 0x01, 0xbb, 0x86, 0xf1, 0x3a, 0xc3, 0x50, 0xbb, 0x30, 0x00, 0x92, 0xab, 0x0a, 0x86, 0xee, 0x04, 0x2c, 0x5d, + 0x90, 0x89, 0xb9, 0xaa, 0xf8, 0xb3, 0x7a, 0x19, 0x23, 0x7a, 0x01, 0x79, 0x21, 0x7e, 0x47, 0x41, 0x15, 0x3c, 0x26, + 0x6c, 0x1a, 0x9e, 0x51, 0xc4, 0xa9, 0xd7, 0x3c, 0x54, 0xe8, 0x34, 0x60, 0x06, 0x8f, 0xf6, 0x33, 0xd4, 0x82, 0xc6, + 0xc9, 0x42, 0xf8, 0xcd, 0xd2, 0x34, 0x27, 0xcf, 0xb6, 0x61, 0x7e, 0xfe, 0x6c, 0x9b, 0xe6, 0xa3, 0x67, 0x5b, 0x17, + 0x28, 0xb9, 0x5c, 0x85, 0x89, 0x16, 0x8e, 0x3a, 0xc5, 0xf4, 0x60, 0x53, 0xd1, 0x72, 0x05, 0x35, 0xf5, 0x23, 0xa6, + 0x8f, 0x8f, 0x13, 0x7f, 0xe5, 0x26, 0x0f, 0x54, 0x7d, 0x6f, 0xc8, 0x3a, 0x7e, 0x5d, 0x55, 0x28, 0x5e, 0xa7, 0xf3, + 0xa5, 0x28, 0x5e, 0x55, 0xbe, 0x15, 0x65, 0x84, 0x4d, 0x4e, 0xe8, 0x30, 0xe1, 0x5b, 0xb7, 0xea, 0x4b, 0x62, 0xcd, + 0x48, 0xe6, 0xfa, 0x01, 0x6d, 0x32, 0xe4, 0xc9, 0xe9, 0x6b, 0xb3, 0x49, 0xcb, 0xb3, 0x09, 0xcb, 0xdb, 0x05, 0x27, + 0x43, 0x31, 0x3e, 0x1d, 0x37, 0xce, 0x0c, 0x93, 0x56, 0x35, 0x2f, 0x20, 0x7d, 0xf7, 0x5f, 0x85, 0x3e, 0x01, 0xe8, + 0x87, 0x00, 0x7d, 0x12, 0x7a, 0xd1, 0x8c, 0xfc, 0xed, 0xfd, 0x85, 0xc8, 0x92, 0x05, 0x02, 0x9f, 0x09, 0xdb, 0x87, + 0x29, 0x92, 0x0b, 0x09, 0x92, 0x0a, 0x34, 0x9f, 0x95, 0x22, 0x76, 0x4c, 0x92, 0xab, 0xca, 0x39, 0x1d, 0x3b, 0x99, + 0xd1, 0x51, 0x8f, 0x22, 0x6c, 0x95, 0xe4, 0x67, 0x47, 0xb4, 0x36, 0xbd, 0xdc, 0x68, 0x25, 0x00, 0x43, 0x02, 0x33, + 0x2c, 0xa0, 0x00, 0x09, 0x3d, 0x47, 0x4e, 0xc1, 0x3f, 0x58, 0x2b, 0x14, 0xab, 0x3b, 0xe7, 0x65, 0xca, 0x04, 0x5b, + 0xa9, 0xe3, 0x33, 0x4c, 0xd1, 0x05, 0xd7, 0x33, 0x04, 0xf5, 0x38, 0x3b, 0xa2, 0x8f, 0x4a, 0xe5, 0x00, 0x14, 0x9d, + 0x70, 0x4e, 0x6e, 0xc0, 0x3a, 0x78, 0xd4, 0xc9, 0x80, 0x8c, 0xf0, 0x50, 0xea, 0xe6, 0xaa, 0xb2, 0x62, 0x94, 0x10, + 0x8b, 0x1e, 0x04, 0xa1, 0x05, 0x6c, 0x38, 0xaa, 0xaa, 0xb2, 0x72, 0x37, 0x38, 0x73, 0xfe, 0xc6, 0xdd, 0x68, 0x0e, + 0x7b, 0x55, 0x1c, 0xad, 0xb4, 0x7c, 0xb4, 0x3c, 0xb6, 0xb8, 0xe0, 0x37, 0x20, 0x18, 0xe9, 0x25, 0xea, 0x63, 0x1b, + 0x16, 0x77, 0xc9, 0x17, 0x77, 0xd6, 0xb2, 0xb8, 0xb3, 0x1d, 0x8b, 0x1b, 0xb0, 0x85, 0x54, 0x04, 0xe8, 0x12, 0xf4, + 0x05, 0x13, 0xc0, 0x63, 0x74, 0xc5, 0x80, 0x9d, 0x33, 0x84, 0x93, 0x99, 0x06, 0x60, 0x0b, 0xd5, 0x02, 0xab, 0x26, + 0xb8, 0x48, 0x80, 0xa8, 0x4f, 0x5c, 0x9c, 0x3a, 0x3e, 0x6f, 0x48, 0xb9, 0xa9, 0x05, 0xd5, 0xf9, 0xc2, 0x2e, 0xa5, + 0xe9, 0xc4, 0xb5, 0x65, 0xcb, 0x4c, 0x97, 0x3b, 0x66, 0xea, 0x95, 0x8e, 0x2e, 0x9b, 0x36, 0x3d, 0x84, 0xf2, 0xa4, + 0x60, 0x0f, 0x82, 0x7d, 0x28, 0x6e, 0x99, 0xf2, 0x3e, 0x6c, 0x47, 0xa9, 0xd2, 0x8e, 0x8a, 0xdd, 0x34, 0xbd, 0x8f, + 0x12, 0x50, 0xb0, 0x40, 0x37, 0x8f, 0xdb, 0x52, 0x2b, 0x3f, 0x64, 0xb1, 0x5b, 0x5a, 0x37, 0x53, 0xf1, 0x5e, 0xde, + 0x52, 0x9d, 0x5e, 0x8f, 0xd6, 0x88, 0xdd, 0x2c, 0x23, 0x09, 0x02, 0xdd, 0x85, 0x20, 0xdf, 0xff, 0x4f, 0xb6, 0x59, + 0x03, 0x0e, 0x09, 0xf4, 0x02, 0xab, 0x23, 0x86, 0x8e, 0x81, 0x94, 0x4a, 0xf8, 0xbd, 0x2b, 0xc5, 0x81, 0x4b, 0x04, + 0xe0, 0x7f, 0xc2, 0xe3, 0xaa, 0x25, 0x92, 0xa7, 0x92, 0x73, 0xa2, 0x5b, 0xb1, 0x3b, 0xfb, 0x00, 0x7a, 0x3c, 0xad, + 0x63, 0x80, 0x4d, 0xae, 0x1c, 0xf5, 0x2d, 0xa1, 0xb4, 0x9d, 0x57, 0x20, 0x49, 0xc4, 0x92, 0xcc, 0xe2, 0x09, 0x9c, + 0x25, 0x5d, 0x73, 0x7e, 0xb3, 0xed, 0xe4, 0x47, 0x0b, 0x5f, 0xaf, 0x61, 0x4d, 0x40, 0x6d, 0xc1, 0x68, 0x2c, 0x58, + 0xac, 0xc0, 0x70, 0x4e, 0x74, 0x10, 0xf4, 0x5e, 0x43, 0xfa, 0x52, 0x9b, 0xf3, 0xaf, 0x93, 0x04, 0x2e, 0xa9, 0x6b, + 0xfb, 0x26, 0x7f, 0xbe, 0xc0, 0x5f, 0xce, 0x4d, 0xfe, 0x7c, 0x8a, 0xbf, 0x3a, 0x37, 0x98, 0xa8, 0xae, 0x81, 0x6f, + 0x97, 0xe6, 0xac, 0x8e, 0x4b, 0xfb, 0x89, 0x9a, 0x9b, 0x3d, 0x62, 0xdb, 0xb0, 0x05, 0x7e, 0xfa, 0x6c, 0x9b, 0x82, + 0x83, 0xa5, 0x3c, 0x87, 0xd0, 0x4a, 0xf4, 0xbc, 0xb1, 0x7c, 0xd1, 0x52, 0x3e, 0xd5, 0xff, 0xcb, 0xf7, 0x3c, 0xee, + 0x92, 0xa8, 0xb8, 0x53, 0xca, 0x52, 0x87, 0xdb, 0xa9, 0x1f, 0xba, 0xc9, 0xc3, 0x2d, 0xe5, 0x26, 0x34, 0x4e, 0xaa, + 0x0b, 0x69, 0x0a, 0xa5, 0x26, 0xcb, 0xda, 0xad, 0x4c, 0x92, 0xe7, 0x3e, 0xb0, 0x8b, 0x7e, 0xf4, 0xf7, 0x44, 0xa2, + 0xd2, 0x4a, 0xfc, 0x26, 0x5b, 0x90, 0xd2, 0x87, 0x6e, 0x9f, 0x6d, 0x35, 0x52, 0xef, 0xa6, 0x32, 0xdb, 0x0a, 0x19, + 0x08, 0xcb, 0x83, 0xbc, 0xeb, 0x6a, 0xe6, 0x0f, 0x50, 0x7d, 0x35, 0x8d, 0x36, 0xe6, 0xb3, 0x6d, 0x76, 0xae, 0xae, + 0xdc, 0xe4, 0x13, 0x99, 0x99, 0x9e, 0x9f, 0x78, 0x01, 0x51, 0x07, 0xea, 0x34, 0x70, 0xc3, 0x4f, 0xec, 0xd1, 0x8c, + 0xd6, 0x19, 0x2a, 0xa4, 0xf7, 0xb2, 0xba, 0x1c, 0x26, 0x54, 0x42, 0x87, 0xb4, 0x69, 0x03, 0x14, 0x94, 0xd7, 0x42, + 0xbe, 0x55, 0xd0, 0x85, 0x45, 0x2d, 0x03, 0xec, 0x29, 0x41, 0x47, 0x0e, 0x0e, 0xaa, 0x86, 0x8a, 0xeb, 0xa5, 0x1a, + 0xf2, 0x54, 0xa9, 0x6c, 0x52, 0x64, 0x58, 0xbc, 0xc5, 0x1e, 0x7e, 0xff, 0xe7, 0x68, 0xee, 0xeb, 0xc3, 0x3f, 0xc7, + 0x68, 0xbc, 0xf6, 0x0f, 0xca, 0x8d, 0xdd, 0x34, 0x5d, 0xaf, 0xc8, 0x8c, 0xea, 0xe2, 0xce, 0x8b, 0xa1, 0x94, 0x69, + 0x79, 0x79, 0x38, 0xbf, 0xae, 0x3b, 0xfd, 0xe3, 0xd7, 0x60, 0x23, 0x00, 0x34, 0x5d, 0x34, 0x9f, 0xab, 0x05, 0x57, + 0xbd, 0xa7, 0x99, 0x73, 0xfc, 0xeb, 0xfa, 0x87, 0xb7, 0xf6, 0x0f, 0xa2, 0x71, 0xa8, 0xea, 0xf9, 0x84, 0x2b, 0x3c, + 0x19, 0x69, 0x2a, 0x8d, 0x97, 0xcf, 0x68, 0xee, 0x86, 0xed, 0xd3, 0xb9, 0x2e, 0xed, 0xb2, 0x98, 0x90, 0x19, 0xd8, + 0xc2, 0x1a, 0xb5, 0xd2, 0xdb, 0x80, 0xdc, 0x11, 0xa1, 0x4c, 0xad, 0x7f, 0xac, 0xa1, 0x05, 0x46, 0x7b, 0x63, 0x4a, + 0x5a, 0x46, 0x58, 0x49, 0x53, 0x9a, 0xe0, 0x1c, 0xd8, 0xcc, 0xe5, 0x5d, 0x5e, 0xd9, 0xd5, 0x13, 0x43, 0x95, 0x06, + 0xd0, 0x3a, 0xb2, 0xf3, 0x96, 0xf2, 0x01, 0xa6, 0x7a, 0x6e, 0x1e, 0x9b, 0xe1, 0xe8, 0x03, 0x88, 0x8e, 0xcd, 0xe0, + 0x14, 0xc0, 0xe6, 0xd7, 0x0a, 0x01, 0x44, 0x1b, 0xc4, 0x9a, 0xc4, 0x52, 0x2a, 0x95, 0x77, 0x70, 0xfb, 0x42, 0x34, + 0xb4, 0xe5, 0x92, 0x9f, 0xc6, 0xb5, 0x51, 0xca, 0x33, 0x9f, 0x62, 0x0a, 0xd5, 0x90, 0xa4, 0x69, 0x2b, 0xc0, 0xc4, + 0xa2, 0x1b, 0x6a, 0x51, 0xbb, 0x0c, 0x8f, 0xa2, 0xdc, 0xb0, 0x0d, 0xb8, 0x95, 0x71, 0x82, 0xd5, 0x6f, 0x21, 0x86, + 0xbf, 0x5d, 0x31, 0x0b, 0x91, 0x64, 0x31, 0x55, 0x99, 0xf6, 0xbe, 0xed, 0xfd, 0xbd, 0xca, 0x06, 0x55, 0xba, 0x29, + 0x1b, 0x87, 0xa6, 0x95, 0xb0, 0x5f, 0x4d, 0x40, 0x83, 0x1d, 0xf0, 0x31, 0x55, 0x50, 0x1c, 0x99, 0xcf, 0x89, 0x97, + 0xa5, 0x3a, 0x17, 0xd7, 0x88, 0x78, 0xad, 0xe0, 0xa7, 0xf3, 0x64, 0xa4, 0xfe, 0x04, 0x5e, 0xeb, 0x3c, 0xac, 0x11, + 0x1b, 0x10, 0x67, 0x5b, 0x9a, 0xc1, 0x44, 0x7b, 0x2c, 0x83, 0x88, 0x7d, 0x05, 0xd2, 0x71, 0x37, 0x94, 0xe3, 0xd0, + 0xd8, 0x15, 0x50, 0xec, 0x8b, 0x48, 0xd8, 0x91, 0xec, 0x46, 0x40, 0xbb, 0x8e, 0xef, 0xd6, 0xf9, 0xa1, 0xe7, 0xd8, + 0xb9, 0x6a, 0x80, 0xb7, 0xd4, 0xa7, 0x43, 0x0f, 0x3d, 0xb6, 0xea, 0x42, 0xab, 0x75, 0xf8, 0x98, 0x76, 0x1d, 0xe7, + 0x95, 0xa3, 0x1a, 0xd4, 0x48, 0x4d, 0xc2, 0x6d, 0x5e, 0x74, 0x47, 0x92, 0x2f, 0x9e, 0x4a, 0xb9, 0xf3, 0xc3, 0xc6, + 0x73, 0xe2, 0xd8, 0x80, 0x84, 0xb3, 0x28, 0x7e, 0xc4, 0x14, 0xba, 0xaa, 0xa1, 0x7a, 0x41, 0x94, 0x12, 0x79, 0x0e, + 0x54, 0xec, 0xf0, 0x85, 0x93, 0xf8, 0xf9, 0xfd, 0xdb, 0x0f, 0x1f, 0x54, 0x03, 0x73, 0x6f, 0xa6, 0x72, 0xef, 0x6c, + 0x43, 0xed, 0xc1, 0xfe, 0x8d, 0xfb, 0x8e, 0xde, 0x30, 0x94, 0xaf, 0x2c, 0xef, 0x39, 0x5a, 0x56, 0xdb, 0x72, 0xec, + 0xe6, 0x61, 0x5f, 0xa6, 0xcc, 0xe0, 0x41, 0xf3, 0x6a, 0xc0, 0x0d, 0xbb, 0xaf, 0xb7, 0x52, 0xc9, 0xca, 0x0f, 0x6f, + 0x1b, 0x4a, 0xdd, 0x4d, 0x43, 0x29, 0x70, 0x53, 0x35, 0x5c, 0xb5, 0x8e, 0x56, 0xd2, 0xed, 0x0c, 0xa9, 0x93, 0xf7, + 0x81, 0x4b, 0x62, 0x69, 0xbe, 0x60, 0xd0, 0x2c, 0x76, 0x7a, 0x75, 0xd4, 0x0d, 0xc5, 0x8c, 0x0f, 0x11, 0xb0, 0xf5, + 0x02, 0x30, 0xb1, 0x23, 0xb2, 0x1e, 0xac, 0x4c, 0xb9, 0x09, 0x03, 0x59, 0xa9, 0x13, 0x4a, 0x61, 0xde, 0x66, 0x64, + 0x15, 0x93, 0xc4, 0xcd, 0xd6, 0x09, 0xb9, 0x0d, 0xa2, 0xfb, 0x27, 0x85, 0x01, 0xfb, 0x9e, 0xca, 0x4b, 0x7f, 0xb1, + 0x14, 0xb5, 0xcf, 0x35, 0x32, 0x12, 0x0b, 0xb8, 0xf3, 0x03, 0xf9, 0x7f, 0xfe, 0x6d, 0x59, 0xff, 0xf9, 0xf7, 0xde, + 0xaa, 0xd0, 0x7d, 0x3e, 0x31, 0xb2, 0xd1, 0x01, 0xfb, 0xa2, 0xf9, 0x4b, 0x65, 0x98, 0x37, 0xd7, 0xa9, 0x2d, 0x02, + 0xbc, 0xaf, 0x2d, 0x41, 0xad, 0xb0, 0xbc, 0x6f, 0x1e, 0x35, 0x30, 0x98, 0xd7, 0xde, 0x91, 0x41, 0xa5, 0x2f, 0x1a, + 0xda, 0x44, 0x1f, 0x1c, 0xb4, 0x22, 0xbf, 0x1f, 0xc2, 0xfb, 0xe6, 0xf0, 0x85, 0xc3, 0x67, 0xa2, 0xc1, 0xd7, 0x93, + 0x89, 0xc8, 0xe6, 0x26, 0x37, 0x05, 0xa3, 0xfa, 0xf3, 0x5a, 0x09, 0xbb, 0x3c, 0x07, 0xb6, 0x4e, 0xbd, 0xdd, 0x47, + 0xaf, 0x27, 0x68, 0xfe, 0x75, 0x36, 0x4d, 0x0a, 0x62, 0xa5, 0x15, 0xb5, 0x51, 0xf3, 0xed, 0x5a, 0xa7, 0x35, 0xbc, + 0x06, 0xa5, 0x98, 0xe2, 0x2b, 0x9f, 0xe8, 0xc6, 0xeb, 0x09, 0x93, 0xed, 0x30, 0x8b, 0xd3, 0x41, 0x75, 0x6b, 0x33, + 0xc9, 0x68, 0x09, 0xe8, 0x86, 0x42, 0x35, 0x2e, 0x58, 0x99, 0x14, 0xa2, 0x34, 0x14, 0xa9, 0x03, 0x53, 0x3f, 0xc9, + 0x31, 0xc3, 0xc8, 0xbb, 0x36, 0xab, 0xac, 0x9f, 0xf7, 0x5b, 0x65, 0x5d, 0x1d, 0x64, 0x95, 0xf5, 0xf3, 0x57, 0xb7, + 0xca, 0x7a, 0x27, 0x5b, 0x65, 0xc1, 0x22, 0xbe, 0x25, 0x07, 0x99, 0x4a, 0x71, 0x3b, 0x89, 0xe8, 0x3e, 0x1d, 0x39, + 0x8c, 0xa4, 0x4d, 0xbd, 0x25, 0x01, 0x36, 0x9d, 0xad, 0x4a, 0x10, 0x2d, 0xc0, 0x6c, 0xea, 0x8f, 0x37, 0x70, 0x0a, + 0xa2, 0x85, 0x6c, 0xde, 0x14, 0xb2, 0x18, 0xab, 0x45, 0xdc, 0x24, 0x6a, 0x52, 0x64, 0x1b, 0x3c, 0xca, 0x92, 0x79, + 0xac, 0x4b, 0x79, 0xa4, 0x85, 0xbd, 0x58, 0x87, 0x1b, 0x1d, 0x0d, 0xd0, 0x5e, 0x49, 0x34, 0xec, 0xbc, 0xe4, 0xd1, + 0x24, 0xe4, 0x1e, 0x84, 0x5d, 0x2e, 0x8d, 0xcc, 0xb0, 0x55, 0x7f, 0xdd, 0x38, 0xdf, 0x5f, 0x3b, 0xc3, 0xae, 0x03, + 0xee, 0xd0, 0xc0, 0xe4, 0x61, 0x81, 0x3d, 0xec, 0x76, 0xa1, 0xe0, 0x5e, 0x2a, 0xe8, 0x40, 0x81, 0x2f, 0x15, 0xf4, + 0xa0, 0xc0, 0x93, 0x0a, 0x4e, 0xa0, 0x60, 0x26, 0x15, 0xf4, 0xa1, 0xe0, 0x4e, 0xcd, 0xaf, 0x43, 0x31, 0xdc, 0xbe, + 0x7e, 0x63, 0x50, 0xa6, 0x82, 0x97, 0xf5, 0x0d, 0x07, 0xec, 0x94, 0xdc, 0xc5, 0x20, 0x32, 0xa8, 0x80, 0x6f, 0x90, + 0x18, 0xf7, 0x4b, 0x42, 0x43, 0x33, 0xbf, 0xc1, 0x3b, 0xc7, 0xca, 0x22, 0xb0, 0x54, 0xe6, 0x21, 0x0f, 0x38, 0x1c, + 0x14, 0x55, 0x07, 0x99, 0xcd, 0x50, 0xac, 0x1c, 0x0f, 0x1b, 0x21, 0xad, 0x65, 0xf1, 0x8e, 0x7e, 0xce, 0x14, 0x5b, + 0xa0, 0xb0, 0xf1, 0xd0, 0x64, 0xc1, 0xe0, 0xd7, 0xd0, 0xf4, 0xbf, 0x21, 0xd3, 0xf5, 0x42, 0xb9, 0x8c, 0x16, 0x7b, + 0x95, 0xf6, 0xf2, 0x2b, 0x18, 0xa5, 0x4a, 0x35, 0x20, 0x26, 0xdf, 0x96, 0xec, 0x5b, 0xf4, 0x31, 0x2f, 0xd7, 0xcf, + 0x60, 0x6c, 0x4a, 0x46, 0x4d, 0x46, 0xe0, 0x3b, 0x00, 0x23, 0x49, 0x6b, 0x7e, 0x09, 0x70, 0x96, 0x9e, 0xaf, 0x5c, + 0x69, 0x3c, 0xe3, 0x1f, 0x49, 0x9a, 0xba, 0x0b, 0x5e, 0xbf, 0x3e, 0x4e, 0x30, 0x93, 0x11, 0xfc, 0x17, 0x02, 0x10, + 0x84, 0x69, 0x7e, 0xcd, 0x1a, 0x22, 0x89, 0xee, 0x15, 0xb0, 0xb7, 0x81, 0x0d, 0x55, 0x58, 0x06, 0xf8, 0x16, 0x2c, + 0x61, 0x59, 0x87, 0x0f, 0x87, 0xff, 0x8e, 0x04, 0xd5, 0xc2, 0xcc, 0x5d, 0x54, 0x8b, 0xe8, 0x3e, 0xc8, 0xe5, 0xb1, + 0x09, 0x15, 0x7a, 0xa9, 0xf0, 0x4b, 0x74, 0xc2, 0x41, 0xb4, 0xf8, 0x43, 0x15, 0xc2, 0x3b, 0x14, 0xf9, 0x1f, 0x42, + 0xc3, 0xcf, 0x26, 0x16, 0xc2, 0x58, 0xb1, 0x00, 0x84, 0x83, 0x30, 0x5b, 0x9a, 0xe8, 0xcc, 0xa5, 0x75, 0x42, 0xdd, + 0xb0, 0x70, 0x6d, 0xb7, 0x55, 0x17, 0xd6, 0x41, 0xb2, 0x98, 0xba, 0x9a, 0xd3, 0xe9, 0x1b, 0xfc, 0xcf, 0xb2, 0x7b, + 0x7a, 0x8e, 0x3d, 0x28, 0x33, 0xff, 0x6e, 0x3b, 0x8f, 0xc2, 0xcc, 0x9c, 0xbb, 0x2b, 0x3f, 0x78, 0x18, 0xac, 0xa2, + 0x30, 0x4a, 0x63, 0xd7, 0x23, 0xc3, 0x82, 0xa1, 0x1e, 0x62, 0x70, 0x04, 0xe6, 0x9f, 0xe7, 0x58, 0x9d, 0x84, 0xac, + 0x68, 0x6b, 0x11, 0xfb, 0x60, 0x1e, 0x90, 0x4d, 0xce, 0x3e, 0x5f, 0xaa, 0x4c, 0xab, 0xe2, 0x96, 0xa3, 0x2d, 0x80, + 0x22, 0x65, 0x81, 0x15, 0x20, 0x9c, 0xd0, 0x30, 0x76, 0x67, 0x18, 0x0b, 0xd0, 0xea, 0xf4, 0x12, 0xb2, 0x52, 0xac, + 0x5e, 0x6b, 0xe7, 0x49, 0x74, 0x3f, 0x86, 0xd1, 0x62, 0x63, 0x33, 0x25, 0xc1, 0x1c, 0xdf, 0x98, 0xe8, 0xcb, 0xc1, + 0xfb, 0x31, 0x91, 0x11, 0x87, 0xde, 0xc8, 0x6a, 0x08, 0xaf, 0x07, 0x1d, 0xc5, 0x1e, 0xae, 0xfc, 0xd0, 0xa4, 0xd3, + 0xe9, 0xdb, 0xb1, 0xd4, 0x97, 0x0c, 0x3f, 0x7d, 0x8b, 0xd5, 0x1d, 0xc5, 0x1e, 0x02, 0xb3, 0x36, 0x0f, 0xa2, 0xfb, + 0xc1, 0xd2, 0x9f, 0xcd, 0x48, 0x38, 0xc4, 0x31, 0x8b, 0x42, 0x12, 0x04, 0x7e, 0x9c, 0xfa, 0xe9, 0x70, 0xe5, 0x6e, + 0x58, 0xaf, 0xc7, 0x6d, 0xbd, 0x76, 0x59, 0xaf, 0xdd, 0x83, 0x7b, 0x95, 0xba, 0x01, 0xbf, 0x11, 0xda, 0x0f, 0x1b, + 0x5a, 0x4f, 0xb1, 0x2b, 0xf3, 0x3c, 0xb8, 0xd7, 0x38, 0x21, 0xdb, 0x95, 0x9b, 0x2c, 0xfc, 0x70, 0x60, 0xe7, 0xd6, + 0xdd, 0x96, 0x6e, 0x8c, 0xa7, 0xa7, 0xa7, 0xa7, 0xb9, 0x35, 0xe3, 0x4f, 0xf6, 0x6c, 0x96, 0x5b, 0x1e, 0x7f, 0x9a, + 0xcf, 0x6d, 0x7b, 0x3e, 0xcf, 0x2d, 0x9f, 0x17, 0x74, 0x3b, 0xde, 0xac, 0xdb, 0xc9, 0xad, 0x7b, 0xa9, 0x46, 0x6e, + 0x11, 0xf6, 0x94, 0x90, 0xd9, 0x10, 0x37, 0x12, 0x35, 0xe4, 0x1c, 0xf4, 0x6d, 0x3b, 0x47, 0x0c, 0x70, 0x5d, 0xc2, + 0x4d, 0x28, 0xeb, 0xb9, 0xd9, 0x1e, 0x5c, 0x53, 0x29, 0x3e, 0xe7, 0x79, 0x8d, 0xf5, 0x66, 0x6e, 0xf2, 0xe9, 0x46, + 0x91, 0x66, 0xe1, 0xba, 0xb4, 0xda, 0x96, 0x83, 0xc1, 0xdc, 0x0c, 0x20, 0x48, 0xd6, 0x70, 0x1a, 0x25, 0x70, 0x66, + 0x13, 0x77, 0xe6, 0xaf, 0xd3, 0x81, 0xd3, 0x89, 0x37, 0xbc, 0x88, 0xed, 0xf5, 0xa2, 0x00, 0xcf, 0xde, 0x20, 0x8d, + 0x02, 0x7f, 0xc6, 0x8b, 0xda, 0xce, 0x92, 0xd3, 0xd1, 0x87, 0xe8, 0x22, 0xee, 0x63, 0xa0, 0x03, 0x37, 0x08, 0x14, + 0xab, 0x9b, 0x2a, 0xc4, 0x4d, 0x51, 0xc4, 0xab, 0xd8, 0x29, 0x85, 0x0b, 0xba, 0x83, 0x3b, 0xc7, 0xf1, 0x46, 0xec, + 0x79, 0xe7, 0x24, 0xde, 0xe4, 0xdf, 0xae, 0xc8, 0xcc, 0x77, 0x15, 0xad, 0xd8, 0x4d, 0x8e, 0x0d, 0x62, 0x60, 0x7d, + 0xdb, 0xb2, 0x4d, 0xf9, 0xb1, 0x80, 0x60, 0x82, 0x4f, 0xfc, 0x55, 0x1c, 0x25, 0x99, 0x1b, 0x66, 0x79, 0x3e, 0xb9, + 0xc9, 0xf3, 0xe1, 0x95, 0xaf, 0x5d, 0xff, 0x43, 0xa3, 0xf7, 0x34, 0x55, 0x9b, 0xe4, 0xfa, 0x8d, 0xf1, 0x96, 0xc8, + 0x56, 0x1a, 0x70, 0x8d, 0xa1, 0x85, 0x86, 0x5c, 0x99, 0xde, 0x92, 0xf5, 0xca, 0x14, 0xc8, 0xa2, 0x3a, 0xb5, 0xfa, + 0x28, 0x57, 0xc1, 0x1b, 0x08, 0x2a, 0xbc, 0x25, 0xa3, 0x2b, 0xc9, 0xe2, 0x03, 0x88, 0x15, 0xac, 0x4c, 0x2d, 0xf9, + 0x9f, 0xb5, 0xd1, 0x8c, 0xdf, 0xed, 0xa7, 0x19, 0x7f, 0xc9, 0x0e, 0xa1, 0x19, 0xbf, 0xfb, 0xea, 0x34, 0xe3, 0xb3, + 0xba, 0x25, 0xff, 0x45, 0x34, 0x52, 0x85, 0x90, 0x1f, 0xae, 0xa6, 0x84, 0xc6, 0xc8, 0xb9, 0xf8, 0xdd, 0x86, 0xf7, + 0xbc, 0x37, 0x9a, 0xf5, 0x8d, 0xde, 0xdc, 0x20, 0x8f, 0x7d, 0x17, 0x8e, 0xfe, 0x9e, 0xc8, 0xcf, 0xf3, 0xf9, 0xe8, + 0x4d, 0x24, 0x15, 0x88, 0x27, 0x66, 0xff, 0x50, 0x8a, 0x67, 0x40, 0xdf, 0x70, 0xbb, 0x47, 0xcc, 0xf8, 0x00, 0xee, + 0xd0, 0xd4, 0xce, 0x77, 0x26, 0xec, 0xbd, 0x86, 0xe5, 0x21, 0x68, 0xc2, 0xc8, 0x92, 0x3b, 0xbd, 0xd4, 0x44, 0x89, + 0x0b, 0x92, 0x31, 0x2f, 0xd5, 0xef, 0x1f, 0x2e, 0x66, 0xda, 0x45, 0xa4, 0xe7, 0x7e, 0xfa, 0xae, 0xea, 0x72, 0xc2, + 0xd4, 0x2f, 0x23, 0x79, 0x3a, 0x39, 0xb3, 0xd9, 0x92, 0x53, 0x3a, 0xc3, 0x6b, 0xda, 0xfc, 0xbc, 0x34, 0xd3, 0x81, + 0xdc, 0x90, 0xa5, 0x96, 0xaa, 0x5d, 0xc6, 0xcc, 0xde, 0x7f, 0xcb, 0x28, 0x40, 0xcc, 0x96, 0x85, 0x9e, 0xba, 0x33, + 0xda, 0xdc, 0x9f, 0xe5, 0xb9, 0x3e, 0xe4, 0x80, 0x90, 0x2e, 0x5a, 0xb2, 0x8f, 0x88, 0x4b, 0xef, 0x85, 0x59, 0x01, + 0x53, 0xd2, 0x51, 0x0d, 0xdc, 0x05, 0xe8, 0xb4, 0x99, 0xbe, 0x8e, 0xc1, 0x4c, 0x55, 0x28, 0xf8, 0xa8, 0xad, 0x83, + 0x34, 0x21, 0x50, 0xc2, 0x0a, 0xf8, 0xf3, 0x57, 0xbc, 0xa0, 0x6e, 0x35, 0x49, 0x81, 0x83, 0x4a, 0x79, 0xf0, 0xab, + 0xe7, 0x72, 0x6d, 0x8a, 0x76, 0x58, 0x1d, 0x7c, 0xc8, 0x55, 0x41, 0xfb, 0xe1, 0xf6, 0x1b, 0x9f, 0x1d, 0x41, 0x83, + 0x71, 0x45, 0x77, 0xbf, 0xc7, 0x26, 0x10, 0x48, 0x89, 0xf4, 0xde, 0xb0, 0xd2, 0x7b, 0xe5, 0xc5, 0x96, 0xc7, 0xa4, + 0xc8, 0xdc, 0xd8, 0x04, 0x16, 0x1f, 0x71, 0x2f, 0xc3, 0x78, 0x52, 0xf8, 0x8b, 0xe1, 0x3a, 0x05, 0xdc, 0x88, 0x8c, + 0x2a, 0xe2, 0x9f, 0xa1, 0xb7, 0x4e, 0xd2, 0x28, 0x19, 0xc4, 0x91, 0x1f, 0x66, 0x24, 0xc9, 0x11, 0x54, 0xd7, 0x08, + 0x1f, 0x0e, 0x9e, 0x9b, 0x6d, 0x14, 0xbb, 0x9e, 0x9f, 0x3d, 0x0c, 0x6c, 0x46, 0x52, 0xd8, 0x43, 0x46, 0x1d, 0xd8, + 0x8d, 0xf5, 0x07, 0x0c, 0x9a, 0x2f, 0x91, 0xf0, 0x4b, 0xea, 0xe4, 0x8c, 0xbc, 0xcd, 0x87, 0xd2, 0x5b, 0x1a, 0x95, + 0x03, 0xc8, 0x0f, 0x37, 0x31, 0x17, 0x80, 0xe5, 0x61, 0xa9, 0xed, 0x19, 0x59, 0x18, 0x88, 0xb5, 0x41, 0x2e, 0xcf, + 0xff, 0xac, 0x9e, 0xae, 0xd8, 0xcd, 0xc5, 0x40, 0xf1, 0xe8, 0x87, 0x8c, 0x6c, 0xe0, 0x42, 0x0e, 0x2b, 0xe3, 0x90, + 0x9a, 0x53, 0x32, 0x8f, 0x12, 0x42, 0x23, 0xb8, 0x3a, 0xa7, 0xf1, 0xe6, 0xf0, 0xee, 0x77, 0x4f, 0xbf, 0xb9, 0x9f, + 0x30, 0xca, 0x34, 0xde, 0x99, 0xbe, 0xa7, 0xb7, 0xfa, 0x7d, 0x06, 0xa4, 0x21, 0x85, 0xbc, 0x47, 0x83, 0x65, 0x0d, + 0x54, 0x75, 0xd8, 0x18, 0x28, 0x2b, 0x8e, 0xd8, 0x9d, 0x97, 0x90, 0xc0, 0xcd, 0xfc, 0x3b, 0x4e, 0x33, 0x76, 0x4f, + 0xe2, 0x0d, 0x5f, 0x63, 0xbc, 0xf0, 0x1e, 0xb1, 0x48, 0x95, 0xa1, 0xf0, 0x45, 0xaa, 0x16, 0xe3, 0x22, 0x0d, 0x6b, + 0xb3, 0xe1, 0xb1, 0x23, 0x2a, 0x37, 0x7d, 0x2f, 0xde, 0xc8, 0x57, 0x74, 0xd1, 0x4c, 0xdc, 0xd4, 0xd5, 0xa0, 0x5f, + 0x2b, 0x7f, 0x36, 0x0b, 0x48, 0x5e, 0x5a, 0xe8, 0xf2, 0x5a, 0x4a, 0xc0, 0x11, 0x70, 0x70, 0xa7, 0x69, 0x14, 0xac, + 0x33, 0xd2, 0x0c, 0x2e, 0x0a, 0x9c, 0x8e, 0x5d, 0x00, 0x07, 0x7f, 0x97, 0xc7, 0xda, 0x03, 0x72, 0x1b, 0xb6, 0x89, + 0x3d, 0x84, 0x18, 0xbf, 0x66, 0xb7, 0x3c, 0x74, 0x78, 0x25, 0x06, 0x6d, 0x34, 0x4c, 0xc4, 0x80, 0x6b, 0x89, 0x62, + 0x6f, 0xc5, 0x72, 0x58, 0x99, 0x88, 0x73, 0x2a, 0x8a, 0xf2, 0xf2, 0x64, 0xfe, 0x98, 0x33, 0xf6, 0xaa, 0xf9, 0x8c, + 0xbd, 0xe2, 0x67, 0x6c, 0xf7, 0xce, 0x7c, 0x3a, 0x77, 0xe0, 0xbf, 0x61, 0x31, 0xa1, 0x81, 0xad, 0x74, 0xe3, 0x8d, + 0xe2, 0xc4, 0x1b, 0xc5, 0xec, 0xc4, 0x1b, 0x05, 0xbb, 0x46, 0x93, 0x0c, 0xc3, 0xea, 0xe8, 0x86, 0xad, 0x40, 0x21, + 0xfc, 0xd9, 0xa5, 0x57, 0xce, 0x31, 0xbc, 0x83, 0x56, 0xbd, 0xfa, 0xbb, 0xce, 0xee, 0xa3, 0x4e, 0xcf, 0x12, 0x47, + 0xda, 0xba, 0x95, 0xb9, 0xd3, 0x29, 0x99, 0x0d, 0xe6, 0x91, 0xb7, 0x4e, 0xff, 0xc5, 0xc6, 0xcf, 0x80, 0xb8, 0x13, + 0x11, 0x54, 0xfa, 0xe1, 0x4d, 0x41, 0x51, 0x72, 0x47, 0x78, 0x0f, 0x5b, 0xb1, 0x4e, 0x03, 0x1a, 0x90, 0xb8, 0x63, + 0x1d, 0x37, 0x6c, 0xf2, 0x66, 0x40, 0xff, 0x61, 0xab, 0xd4, 0x8e, 0x62, 0xbe, 0x00, 0x2c, 0x3b, 0xc1, 0xf1, 0x78, + 0x68, 0xb0, 0xd5, 0xb4, 0x4f, 0x9b, 0x87, 0x7b, 0xcd, 0xbf, 0x74, 0xc3, 0x2f, 0x15, 0x76, 0x6f, 0x31, 0x57, 0x90, + 0xdd, 0xbd, 0xb6, 0xed, 0x91, 0x5a, 0xaf, 0x3b, 0x2e, 0x84, 0xa2, 0xee, 0x81, 0x58, 0xfe, 0xe9, 0xab, 0x63, 0xf8, + 0x8f, 0x52, 0xf5, 0xbf, 0x64, 0x4d, 0x84, 0xfa, 0x45, 0xd9, 0xf6, 0x9a, 0x92, 0x4a, 0x48, 0x88, 0x1f, 0x5e, 0x7f, + 0x3e, 0x7f, 0x5c, 0x83, 0x83, 0x6b, 0x53, 0x6b, 0xa6, 0x6a, 0xed, 0xef, 0xa3, 0x08, 0x92, 0x65, 0xd6, 0xab, 0x73, + 0xf0, 0x50, 0xf3, 0xf2, 0x6c, 0x04, 0x8d, 0x38, 0x1f, 0x41, 0xb5, 0xf8, 0x2a, 0xb6, 0xa1, 0xac, 0xc4, 0xdb, 0x36, + 0x56, 0xe2, 0xcd, 0x7e, 0x56, 0xe2, 0xaf, 0x07, 0xb1, 0x12, 0x6f, 0xbe, 0x3a, 0x2b, 0xf1, 0xb6, 0xce, 0x4a, 0x5c, + 0x45, 0xdc, 0x84, 0xd5, 0xb8, 0x58, 0xb3, 0x9f, 0x1f, 0xa9, 0x52, 0xee, 0x32, 0x1a, 0xf5, 0x6c, 0x1a, 0x64, 0xf8, + 0xea, 0x77, 0x33, 0x16, 0xb8, 0x11, 0xdf, 0xa3, 0x45, 0x57, 0xc1, 0x5a, 0x30, 0xcc, 0x8e, 0xdf, 0x91, 0x8a, 0x83, + 0x28, 0x5c, 0xfc, 0x0c, 0x4a, 0x59, 0x10, 0x07, 0x26, 0xd2, 0x0b, 0x3f, 0xfd, 0x39, 0x8a, 0xd7, 0xf1, 0x05, 0xf4, + 0xf5, 0xd1, 0x4f, 0xfd, 0x69, 0x40, 0x84, 0xef, 0x2f, 0xb5, 0x40, 0x63, 0x32, 0x71, 0x30, 0xfa, 0xe4, 0x3f, 0xdd, + 0x0d, 0xff, 0x89, 0x66, 0xa1, 0xec, 0x37, 0x35, 0x6d, 0x53, 0x9b, 0x19, 0x11, 0xae, 0x04, 0x94, 0x06, 0xfd, 0x78, + 0x66, 0xe4, 0x2a, 0xd2, 0x1b, 0x66, 0xc9, 0xed, 0x1d, 0x5a, 0xfb, 0x21, 0x35, 0xa6, 0x66, 0xad, 0x1b, 0x22, 0xe8, + 0x55, 0x5d, 0x0c, 0xbf, 0x8a, 0xd6, 0x29, 0x99, 0x45, 0xf7, 0xa1, 0x6a, 0x84, 0xc2, 0xac, 0x1f, 0x34, 0x9c, 0xa2, + 0x0d, 0xa6, 0x6b, 0xfc, 0x80, 0x84, 0x72, 0x94, 0x68, 0x2a, 0x64, 0x0b, 0x5d, 0xc7, 0x26, 0x55, 0x35, 0x9b, 0x38, + 0x45, 0x55, 0xe4, 0x15, 0x7a, 0xa2, 0x69, 0xd1, 0xe8, 0x71, 0x2d, 0xb9, 0xa9, 0x46, 0x64, 0x31, 0xa9, 0x70, 0xaa, + 0x85, 0x5c, 0xb8, 0xc8, 0x23, 0x4f, 0x34, 0x2c, 0x1c, 0x7b, 0x43, 0x9d, 0x45, 0x8b, 0xb7, 0x10, 0xb7, 0x23, 0x5f, + 0xb3, 0xf5, 0x60, 0x71, 0x18, 0xe8, 0xe3, 0x6b, 0x09, 0x8c, 0xef, 0xee, 0x48, 0x12, 0xb8, 0x0f, 0x9a, 0x9e, 0x47, + 0xe1, 0x8f, 0x00, 0x80, 0x37, 0xd1, 0x7d, 0x28, 0x57, 0xc0, 0xf4, 0x28, 0x0d, 0x7b, 0xa9, 0x31, 0x62, 0x08, 0xb8, + 0x8a, 0x48, 0x23, 0x80, 0xc4, 0xb4, 0x0b, 0xf2, 0x77, 0x83, 0xfe, 0xfb, 0x0f, 0x3d, 0x37, 0x2e, 0x23, 0xf1, 0xa1, + 0xbf, 0xc5, 0x07, 0x7c, 0xe6, 0xf9, 0xf3, 0x27, 0xed, 0xd3, 0x2e, 0x27, 0x44, 0x6f, 0x68, 0xad, 0xb7, 0x9e, 0x02, + 0x18, 0xc5, 0x55, 0xb4, 0xf6, 0x96, 0x68, 0x6b, 0xfa, 0xf5, 0xe6, 0x9b, 0x41, 0x9f, 0x98, 0x17, 0x54, 0x4c, 0xbd, + 0x52, 0x54, 0x40, 0x01, 0xbf, 0xff, 0x16, 0x42, 0x5e, 0xfe, 0x0f, 0xc1, 0x50, 0xdf, 0x35, 0x8c, 0x8b, 0xf7, 0x1f, + 0xb7, 0x79, 0x87, 0x90, 0xbe, 0x92, 0x05, 0x93, 0xe0, 0xca, 0xb5, 0x66, 0x24, 0x93, 0x57, 0x81, 0x26, 0x07, 0x6e, + 0x6b, 0x8b, 0x49, 0xc7, 0xbf, 0x42, 0x2c, 0xca, 0xa6, 0x33, 0x5b, 0x7f, 0x83, 0x30, 0x6c, 0x55, 0x41, 0x32, 0xcc, + 0xe4, 0x81, 0x20, 0xfa, 0xaa, 0xbe, 0x5b, 0xf9, 0xa1, 0x81, 0x71, 0xd7, 0xeb, 0x6f, 0xdc, 0x0d, 0x44, 0x1e, 0x06, + 0xe4, 0x56, 0x7d, 0x05, 0x85, 0x86, 0xec, 0xa9, 0x06, 0xc9, 0x95, 0xd4, 0x46, 0x48, 0x70, 0x2d, 0xde, 0xe4, 0x4f, + 0x8a, 0xa2, 0x28, 0x82, 0x8d, 0x50, 0x04, 0x1f, 0x81, 0xe5, 0xc8, 0x0e, 0x80, 0xb6, 0x24, 0x8f, 0x37, 0xb4, 0x04, + 0x38, 0x03, 0xd4, 0xc9, 0xf2, 0x02, 0x16, 0x5c, 0xaf, 0x67, 0xf3, 0x02, 0xce, 0xd0, 0x43, 0x60, 0x34, 0x37, 0x81, + 0x18, 0xbc, 0x03, 0x05, 0x19, 0x76, 0x7c, 0xcb, 0x24, 0xc1, 0x8a, 0x4d, 0x1f, 0x27, 0x43, 0xd2, 0x1c, 0x85, 0x2d, + 0x94, 0xb0, 0x20, 0x68, 0x1d, 0x2a, 0x41, 0x95, 0x0d, 0xd2, 0x80, 0x1b, 0x91, 0x2f, 0xda, 0x64, 0x2b, 0x12, 0xae, + 0x55, 0xcc, 0xc2, 0x84, 0x51, 0xf1, 0xa0, 0xce, 0x1b, 0x4a, 0x6c, 0x01, 0xb6, 0x69, 0x6e, 0xb9, 0xa4, 0x77, 0x61, + 0xca, 0x50, 0xaa, 0x6b, 0x78, 0x4c, 0xb1, 0x99, 0x32, 0xdc, 0x56, 0xbd, 0x21, 0xd8, 0x92, 0x46, 0x55, 0xd7, 0x29, + 0x6a, 0x8c, 0x0c, 0x7d, 0xd0, 0x78, 0x14, 0x4c, 0x5c, 0xc4, 0xc1, 0xae, 0xb9, 0xd5, 0x45, 0x13, 0x1a, 0x19, 0xb7, + 0x22, 0x28, 0x4a, 0xf4, 0x7a, 0x37, 0x6c, 0x9c, 0x10, 0x0a, 0xa8, 0xb5, 0x1f, 0xaf, 0xd6, 0x4f, 0xcb, 0xa4, 0x3f, + 0x91, 0x07, 0x7a, 0x91, 0x50, 0x50, 0x7d, 0x22, 0x0f, 0x60, 0xfb, 0xf7, 0x16, 0xa4, 0x29, 0xea, 0x0e, 0x74, 0x6d, + 0x40, 0x70, 0x7d, 0x0f, 0xc2, 0x43, 0xed, 0x38, 0x40, 0x76, 0xbe, 0x03, 0x8b, 0x23, 0x88, 0x21, 0x8f, 0x32, 0x3f, + 0xc4, 0xcc, 0xca, 0x5e, 0x6b, 0x84, 0xb1, 0xd9, 0x70, 0x34, 0xf4, 0x17, 0x8e, 0x6d, 0x1f, 0xd5, 0xea, 0x83, 0x20, + 0xbb, 0xa9, 0xb6, 0x6e, 0x64, 0x23, 0xc7, 0x36, 0xfd, 0x17, 0x56, 0x67, 0x58, 0xbb, 0xa3, 0xa5, 0xe8, 0x8d, 0x13, + 0x14, 0x7f, 0x8d, 0x9f, 0x6d, 0xb5, 0xda, 0x81, 0xd4, 0xab, 0x56, 0xeb, 0x38, 0xb6, 0x9c, 0xc9, 0xbf, 0x26, 0xf5, + 0xab, 0x9f, 0xc6, 0x8e, 0xa4, 0x99, 0x44, 0x26, 0x10, 0x7f, 0x58, 0x83, 0x63, 0xf4, 0x67, 0xe5, 0xa5, 0xa2, 0xd1, + 0xe3, 0xa3, 0xeb, 0x13, 0x91, 0xa0, 0x9a, 0xbb, 0x75, 0xc9, 0x1d, 0x54, 0xbe, 0x98, 0x56, 0x31, 0x1c, 0x8b, 0x74, + 0x4a, 0x0a, 0x8d, 0xde, 0x4e, 0x6a, 0x01, 0xfb, 0x6f, 0xb9, 0x3e, 0xad, 0x29, 0x44, 0x02, 0x80, 0x1a, 0x10, 0xad, + 0x7c, 0x6f, 0x87, 0xeb, 0xb8, 0xdc, 0x5d, 0xf9, 0x92, 0x3c, 0xbc, 0x33, 0xbc, 0x74, 0x50, 0x87, 0x26, 0xfa, 0x6b, + 0xbe, 0xee, 0x1e, 0xd9, 0x25, 0x09, 0x67, 0xe5, 0x0e, 0x2b, 0xf7, 0xd7, 0xe1, 0xdd, 0x95, 0x30, 0x0a, 0x84, 0xf1, + 0x8f, 0x1a, 0x30, 0x4a, 0x1e, 0x85, 0xb8, 0xf9, 0xe9, 0x71, 0xf3, 0x0f, 0xa2, 0x62, 0xb0, 0x01, 0x8d, 0xc1, 0x25, + 0x9a, 0x49, 0x42, 0x71, 0x88, 0x15, 0x8d, 0x8e, 0xb8, 0x1a, 0x27, 0x44, 0x5b, 0x77, 0x62, 0xc6, 0x6d, 0x0a, 0x8b, + 0x36, 0x3e, 0x8b, 0xfe, 0x78, 0xa8, 0xd4, 0xda, 0xdf, 0x2f, 0xb5, 0xce, 0xf6, 0x49, 0xad, 0xa9, 0x47, 0xd3, 0x7d, + 0xe2, 0xc6, 0x92, 0x53, 0x1c, 0x27, 0xce, 0x65, 0xdf, 0xb8, 0x92, 0xa8, 0x1b, 0x1d, 0xa0, 0x78, 0xab, 0x5a, 0x6f, + 0xd4, 0x4a, 0x10, 0xc5, 0xdf, 0x12, 0x83, 0xc2, 0x15, 0xea, 0xb2, 0x6c, 0xfc, 0xaa, 0x90, 0x8d, 0x53, 0xae, 0xa6, + 0xf0, 0x65, 0xe1, 0xd4, 0xbf, 0xe4, 0x27, 0x26, 0xb8, 0x83, 0xc2, 0x5f, 0xac, 0x18, 0xa9, 0xe4, 0x01, 0x55, 0x30, + 0x1a, 0x92, 0x5f, 0x1d, 0xe7, 0x32, 0xca, 0xee, 0x75, 0xe5, 0xaa, 0x85, 0x03, 0x54, 0x51, 0x0e, 0x52, 0x77, 0x1c, + 0xb2, 0x28, 0x96, 0xb7, 0x4d, 0xd9, 0x03, 0x46, 0x7e, 0x2d, 0x6d, 0x12, 0xe1, 0xaa, 0x42, 0x01, 0xcc, 0xc5, 0xf4, + 0x15, 0xbd, 0xb6, 0xb0, 0x81, 0xc0, 0x41, 0x36, 0x78, 0xd6, 0xed, 0x97, 0xce, 0xd3, 0x0c, 0x05, 0x85, 0x16, 0x5e, + 0x96, 0x41, 0x20, 0x7c, 0x6f, 0xb6, 0x0d, 0xb7, 0x3c, 0x5e, 0xf2, 0xec, 0x7e, 0x07, 0xf1, 0xa2, 0x62, 0xcb, 0x8a, + 0x7c, 0x3c, 0x99, 0x26, 0x35, 0xcf, 0xc5, 0xaa, 0xf5, 0x4e, 0xa9, 0x10, 0x67, 0xcb, 0x9c, 0x53, 0xca, 0x32, 0x7a, + 0x56, 0x63, 0xc0, 0xbf, 0xcb, 0xb6, 0x4e, 0xb2, 0x0e, 0x31, 0x9a, 0xbc, 0x99, 0x25, 0xae, 0xf7, 0x49, 0x1a, 0x32, + 0x97, 0x73, 0x82, 0x0c, 0xb8, 0xac, 0x29, 0x18, 0xba, 0x18, 0x7c, 0x91, 0x0c, 0xac, 0x4e, 0x2a, 0x49, 0x5f, 0x06, + 0x4f, 0xed, 0xae, 0xfb, 0x6a, 0x7e, 0x5c, 0x11, 0x8a, 0x76, 0x7a, 0x65, 0x91, 0x79, 0xcb, 0x38, 0xb2, 0xe5, 0x7a, + 0x35, 0xdd, 0xca, 0xb2, 0x55, 0x49, 0xe4, 0x5a, 0x17, 0xb3, 0xca, 0x9f, 0x9d, 0xcf, 0xe7, 0x65, 0x41, 0xa3, 0xad, + 0x1c, 0xa3, 0xb0, 0xf0, 0xa9, 0x6d, 0xdb, 0xd5, 0xb1, 0xef, 0x06, 0xbb, 0x89, 0x72, 0xdb, 0xd3, 0xc6, 0x11, 0x23, + 0x6c, 0xf7, 0xc1, 0xaf, 0x0e, 0x8e, 0xdc, 0x2a, 0x4e, 0x76, 0xc9, 0x2c, 0x62, 0x48, 0x8d, 0x21, 0xfc, 0x8c, 0xac, + 0xd2, 0x81, 0x47, 0x50, 0x07, 0x63, 0x49, 0x07, 0x1a, 0x0d, 0x07, 0xcc, 0x05, 0x98, 0x8a, 0x38, 0x7c, 0x57, 0xd8, + 0x0a, 0xca, 0xc3, 0x6b, 0xc2, 0x7b, 0xfe, 0x11, 0x3c, 0x28, 0xdb, 0xba, 0x4c, 0x1b, 0xa7, 0xd5, 0xb3, 0xff, 0x5c, + 0xaa, 0xa7, 0xc0, 0x05, 0xb8, 0xe5, 0x0a, 0x6d, 0x2a, 0x9f, 0xc5, 0xff, 0x17, 0xf2, 0xff, 0x57, 0xf1, 0xa6, 0x6c, + 0x3f, 0x72, 0x0a, 0x12, 0xed, 0xe2, 0xb4, 0xd0, 0x51, 0x37, 0xed, 0x01, 0x61, 0x65, 0x30, 0x97, 0x15, 0xe8, 0xa0, + 0xa4, 0x2f, 0xa5, 0xdc, 0x68, 0x10, 0xbf, 0x23, 0xc5, 0x0c, 0x4b, 0x5c, 0x88, 0x10, 0x8b, 0x84, 0x71, 0x30, 0x07, + 0xe3, 0xe5, 0x29, 0xea, 0x0f, 0x4a, 0x7b, 0x02, 0xb4, 0xf1, 0xb5, 0xb9, 0x1d, 0x24, 0xee, 0xaf, 0xea, 0xb5, 0x78, + 0xc7, 0x00, 0x32, 0x07, 0x0e, 0x21, 0x1a, 0x12, 0x28, 0x95, 0xcd, 0x4d, 0x47, 0x29, 0xde, 0xca, 0x7a, 0x36, 0x3e, + 0x30, 0xec, 0xae, 0xb9, 0x0a, 0xed, 0x9b, 0x6b, 0x0b, 0x60, 0xb2, 0x6c, 0xfb, 0xe1, 0xb3, 0x09, 0x4b, 0x2c, 0xef, + 0x47, 0x07, 0x97, 0x1c, 0xf7, 0xaf, 0x89, 0x77, 0x67, 0x4a, 0xcf, 0x3f, 0xca, 0x17, 0xff, 0xda, 0x28, 0xd0, 0xbb, + 0x2a, 0x49, 0xe8, 0x98, 0xb5, 0x78, 0x47, 0x3f, 0xa8, 0xf6, 0xca, 0x0f, 0x0f, 0xaf, 0xeb, 0x6e, 0x0e, 0xae, 0x0b, + 0x17, 0xc6, 0xc1, 0x95, 0xe1, 0xc6, 0xa1, 0x96, 0x0b, 0xd9, 0xe8, 0xaf, 0x92, 0x40, 0x51, 0x76, 0xfc, 0x55, 0xb1, + 0x15, 0xa5, 0xf2, 0xaf, 0xd6, 0x40, 0x7c, 0x1e, 0x94, 0x52, 0x41, 0xe1, 0x59, 0xd1, 0xd4, 0xbe, 0x72, 0xaa, 0xf4, + 0xbb, 0xca, 0x89, 0xad, 0x52, 0x2e, 0x6c, 0xa4, 0xf6, 0x3a, 0x85, 0x43, 0xdf, 0xb1, 0xad, 0x8e, 0xcf, 0x16, 0xfc, + 0x92, 0x98, 0xfb, 0x41, 0x40, 0x51, 0x45, 0x9a, 0x25, 0xd1, 0x27, 0x52, 0x56, 0xb3, 0xd0, 0x32, 0x66, 0x04, 0xd2, + 0xe1, 0x8f, 0x70, 0x76, 0x3c, 0x37, 0x1e, 0xe0, 0xd9, 0x90, 0x0b, 0xc1, 0x80, 0x93, 0x96, 0xe2, 0x27, 0xe0, 0x0e, + 0x9e, 0xaa, 0xe3, 0x33, 0x08, 0x1a, 0xa8, 0xcc, 0x46, 0xea, 0x8f, 0x9d, 0xbe, 0xe2, 0xf4, 0xee, 0xcc, 0xae, 0x67, + 0x9b, 0x8e, 0x75, 0xac, 0xd8, 0xd6, 0x89, 0xd9, 0xb1, 0xfa, 0x4a, 0xc7, 0xea, 0xc1, 0xbf, 0x9e, 0x63, 0xbd, 0x52, + 0x6c, 0x78, 0x52, 0x1c, 0xab, 0x8b, 0xff, 0x76, 0xac, 0xfe, 0x5d, 0x97, 0xde, 0xf4, 0xae, 0x70, 0xab, 0xaa, 0x8c, + 0x02, 0x9c, 0x40, 0xd4, 0xa3, 0xf1, 0xd9, 0x3a, 0x25, 0xca, 0x66, 0xa4, 0xbe, 0x52, 0x95, 0x65, 0x42, 0xe6, 0x23, + 0xf5, 0xa9, 0x2b, 0x95, 0x3a, 0xa7, 0x8d, 0xc5, 0x9d, 0x7e, 0x63, 0x71, 0xf7, 0xa4, 0xb1, 0xf8, 0xb8, 0x57, 0x2e, + 0x3e, 0x5a, 0xd0, 0x57, 0x52, 0xce, 0xbe, 0x95, 0x9b, 0x25, 0xfe, 0x46, 0x73, 0x14, 0x40, 0xd7, 0x26, 0xfc, 0xd3, + 0xef, 0xe8, 0xa2, 0xd5, 0x14, 0x5a, 0x09, 0x68, 0xf4, 0x4f, 0x15, 0xe7, 0xe4, 0x2f, 0x9d, 0x13, 0x0f, 0xea, 0x41, + 0x86, 0x49, 0xf8, 0xbb, 0xeb, 0x9e, 0x7a, 0xb6, 0x02, 0x0d, 0x1d, 0xf8, 0x6f, 0xd9, 0xeb, 0x78, 0xf4, 0xc1, 0x86, + 0xf7, 0x1f, 0x9d, 0x7e, 0x6a, 0x9b, 0x0e, 0xfc, 0xf7, 0x9b, 0x50, 0xb9, 0x83, 0xc2, 0x5f, 0xee, 0xf7, 0xd8, 0x56, + 0xba, 0xa7, 0xcb, 0x8e, 0xf5, 0xea, 0xae, 0x6f, 0x9d, 0x2e, 0x9d, 0xfe, 0x47, 0xfa, 0x14, 0x98, 0x1d, 0xeb, 0x15, + 0xfc, 0x7d, 0xec, 0xda, 0x4b, 0xd3, 0xb1, 0x4e, 0xef, 0xba, 0x56, 0x37, 0x30, 0x4f, 0xac, 0x53, 0xf8, 0xfb, 0x0d, + 0xc0, 0x0b, 0x70, 0x65, 0x29, 0x41, 0x15, 0xd8, 0x18, 0x15, 0xfb, 0x0d, 0xf9, 0x23, 0x9d, 0x63, 0xa5, 0x77, 0xfc, + 0x97, 0xd3, 0x3b, 0xf3, 0x78, 0xe9, 0x74, 0xee, 0xcc, 0xd6, 0x9f, 0x1f, 0x01, 0xf2, 0xbb, 0x17, 0x0e, 0xc0, 0x88, + 0x39, 0x40, 0xfe, 0x34, 0x31, 0x2e, 0xdb, 0xc4, 0xe8, 0xef, 0xf7, 0x8b, 0xd1, 0x7f, 0x58, 0x1f, 0x22, 0x46, 0x7f, + 0xff, 0xd5, 0xc5, 0xe8, 0x97, 0x55, 0x2b, 0xee, 0xf7, 0xd5, 0x58, 0xe5, 0xbf, 0x6c, 0xab, 0x44, 0xb2, 0xef, 0x6a, + 0xd7, 0x57, 0xeb, 0x1b, 0x88, 0xb6, 0xf3, 0x3e, 0x1a, 0xfd, 0xb0, 0x2e, 0x99, 0x28, 0x45, 0x80, 0x01, 0xde, 0x47, + 0x14, 0x03, 0xfc, 0xb6, 0x1e, 0x81, 0x5d, 0x04, 0xbb, 0x35, 0xfd, 0x99, 0xb9, 0x74, 0x83, 0xb9, 0xb8, 0x71, 0xa1, + 0x64, 0x88, 0xc5, 0x60, 0x33, 0x0f, 0x97, 0x09, 0x28, 0x6b, 0xd6, 0xab, 0x30, 0x1d, 0x9c, 0xd8, 0x80, 0xe6, 0x3b, + 0xf3, 0x24, 0xaf, 0x34, 0xb6, 0x78, 0x7c, 0xa2, 0x5b, 0x66, 0xd3, 0xdf, 0xfa, 0x1e, 0x4d, 0xd6, 0x9a, 0x7b, 0x77, + 0xea, 0xfd, 0x2a, 0x60, 0x0b, 0xc2, 0x4d, 0xfa, 0x80, 0xd8, 0x68, 0x7a, 0x5f, 0x36, 0x1c, 0xab, 0x98, 0x0a, 0xb6, + 0x8f, 0x14, 0x46, 0x52, 0x6d, 0xef, 0x94, 0x0d, 0xcf, 0xf6, 0x4d, 0xb3, 0xe1, 0xf3, 0xa5, 0xe6, 0x3b, 0xac, 0xde, + 0x44, 0xc7, 0x55, 0x50, 0x55, 0x32, 0x6d, 0x35, 0x02, 0xa4, 0xa0, 0x3d, 0x0b, 0xd3, 0xb8, 0x82, 0xf0, 0xb1, 0x15, + 0xbc, 0x8d, 0x6d, 0xe9, 0x5d, 0xa9, 0x4f, 0xd9, 0x9c, 0xee, 0xc5, 0x16, 0xe9, 0x41, 0xff, 0x37, 0x20, 0x6c, 0xd8, + 0x7d, 0x3c, 0x8d, 0x64, 0x38, 0x6f, 0xa5, 0x7e, 0x29, 0xa9, 0x9d, 0x2f, 0x9d, 0x6d, 0x9d, 0xb4, 0x69, 0x35, 0xa4, + 0x75, 0xc8, 0x8a, 0xdf, 0xd1, 0xf8, 0x79, 0x6a, 0xb6, 0x9a, 0x53, 0xd3, 0x62, 0xb4, 0xcc, 0xdd, 0xd5, 0x19, 0xaf, + 0xf7, 0x14, 0x36, 0xb1, 0xc1, 0x1e, 0x64, 0xc7, 0xf1, 0xed, 0x1c, 0xb2, 0x22, 0x0f, 0x90, 0x88, 0x90, 0x28, 0xa8, + 0x0e, 0xda, 0xd8, 0x0e, 0x77, 0x98, 0x7f, 0xc8, 0x1d, 0xb3, 0x4e, 0xd0, 0x56, 0x77, 0x97, 0xc5, 0x88, 0x70, 0x6d, + 0xd8, 0x96, 0x14, 0xa8, 0x4e, 0xaf, 0x6f, 0x38, 0x27, 0x86, 0xd5, 0xef, 0xe9, 0x39, 0x3f, 0x70, 0x72, 0x97, 0x25, + 0x80, 0x80, 0xc9, 0xae, 0x18, 0xa6, 0x1f, 0xfa, 0x99, 0xef, 0x06, 0x39, 0xa0, 0xfa, 0x32, 0xcd, 0xfb, 0xcf, 0x75, + 0x9a, 0xc1, 0x1c, 0x39, 0x49, 0x86, 0xe6, 0xca, 0xe6, 0x94, 0x64, 0xf7, 0x84, 0x84, 0x2d, 0xaa, 0xdc, 0xaa, 0xf5, + 0xf3, 0x1f, 0x67, 0x0b, 0x9a, 0x53, 0x3b, 0x8b, 0x69, 0x16, 0xb2, 0xfd, 0xc1, 0x4d, 0x75, 0xf3, 0x89, 0xf1, 0x53, + 0x1b, 0xc2, 0xfd, 0xe7, 0x7e, 0x84, 0x9b, 0x91, 0x43, 0x10, 0xee, 0x3f, 0xbf, 0x3a, 0xc2, 0xfd, 0x49, 0x46, 0xb8, + 0x25, 0x4f, 0x95, 0x42, 0x26, 0xfa, 0x01, 0x9f, 0x35, 0x08, 0xf2, 0xfb, 0x52, 0x3d, 0xa2, 0xe4, 0xa5, 0x2a, 0x25, + 0x5f, 0xfd, 0x58, 0xca, 0x26, 0x83, 0x2c, 0x3b, 0x06, 0x25, 0xa5, 0x99, 0x2b, 0x20, 0x31, 0xa9, 0x48, 0xb1, 0x0d, + 0x7d, 0x5e, 0x84, 0x59, 0x60, 0xbd, 0x67, 0x6c, 0x09, 0xa8, 0x20, 0x7e, 0x88, 0x92, 0x95, 0x8b, 0x01, 0xd9, 0x54, + 0xcc, 0x42, 0x07, 0x0f, 0x36, 0x78, 0x47, 0x79, 0x51, 0x38, 0x13, 0x72, 0x74, 0x32, 0xba, 0xa6, 0xf4, 0xa0, 0xfa, + 0x40, 0xdc, 0x44, 0x35, 0xe8, 0x6b, 0x58, 0xdc, 0x17, 0x5d, 0xfb, 0x45, 0xe7, 0xf8, 0xc5, 0x89, 0x0d, 0xff, 0x73, + 0x48, 0x37, 0x37, 0x58, 0xc5, 0x55, 0x14, 0x42, 0x22, 0x0c, 0x5e, 0xb3, 0xad, 0xda, 0x3d, 0x21, 0x9f, 0x8a, 0x5a, + 0xfd, 0xe6, 0x4a, 0x33, 0xf7, 0xa1, 0xa8, 0xd3, 0x58, 0x63, 0x19, 0xad, 0xa5, 0x61, 0x35, 0x8c, 0xc6, 0x0f, 0xd7, + 0x20, 0x19, 0x92, 0x6a, 0xc8, 0xaf, 0xd9, 0x74, 0x8b, 0x79, 0x91, 0x6e, 0x7e, 0x53, 0x64, 0xdb, 0xe1, 0x59, 0x3f, + 0xf6, 0x42, 0x90, 0x09, 0xd5, 0x6d, 0x8c, 0xd5, 0x8d, 0xf9, 0x66, 0x14, 0xc8, 0x75, 0x57, 0xa4, 0x54, 0xc7, 0x05, + 0xca, 0x92, 0x75, 0xe8, 0xd1, 0xac, 0xe9, 0xee, 0x34, 0xd5, 0xfc, 0x23, 0x88, 0xd6, 0x89, 0x1f, 0xd6, 0x71, 0xd5, + 0xdc, 0xb1, 0x5d, 0xa4, 0x26, 0x48, 0xf9, 0xaa, 0xb8, 0x2f, 0x32, 0x23, 0xa1, 0x09, 0x4d, 0x71, 0x69, 0xcd, 0x91, + 0xfb, 0x42, 0x34, 0x7c, 0x91, 0x19, 0x90, 0x54, 0x14, 0x96, 0xfb, 0xf9, 0x73, 0x5a, 0x0b, 0xd2, 0xfc, 0xd1, 0x69, + 0x9d, 0x7b, 0x22, 0x35, 0x98, 0xaa, 0xb8, 0x8b, 0x48, 0xc5, 0xd4, 0x60, 0x03, 0xcf, 0x88, 0x5e, 0xbe, 0x1c, 0x8f, + 0x1c, 0x9d, 0x25, 0xa9, 0x2c, 0x65, 0x54, 0xba, 0x3c, 0x4c, 0x35, 0xae, 0x37, 0x3a, 0x6d, 0xc5, 0x7e, 0xb8, 0xe0, + 0x9a, 0x69, 0x81, 0xbd, 0x20, 0xc3, 0x01, 0x55, 0x81, 0xb9, 0x5c, 0x45, 0xcd, 0xeb, 0xdc, 0x91, 0x04, 0x12, 0x6c, + 0x8e, 0xd4, 0xae, 0x65, 0x5b, 0xb6, 0x2a, 0x1a, 0xce, 0xfd, 0xc5, 0x68, 0x1b, 0x65, 0x2e, 0xe4, 0x8a, 0x09, 0xa2, + 0x05, 0x78, 0x7e, 0x64, 0x7e, 0x16, 0x40, 0xe2, 0x11, 0x70, 0x01, 0x59, 0x51, 0xae, 0x31, 0x67, 0xf6, 0xb8, 0x6e, + 0xf2, 0x09, 0x93, 0xcf, 0x71, 0xa7, 0x2f, 0x0c, 0x49, 0xf3, 0x23, 0x5c, 0x86, 0x9a, 0xaa, 0x41, 0xea, 0x43, 0x92, + 0xa4, 0xa6, 0x6c, 0xdf, 0x3e, 0x50, 0xa0, 0x0d, 0xa4, 0x25, 0xc7, 0x0e, 0xe6, 0x89, 0xbb, 0x82, 0x18, 0xdd, 0xdb, + 0xdc, 0x60, 0x98, 0x56, 0x65, 0xa8, 0x56, 0x71, 0x5e, 0x9d, 0x18, 0x4a, 0xc7, 0x31, 0x14, 0x1b, 0xd0, 0xad, 0x9a, + 0x1b, 0xdb, 0xfc, 0x66, 0xb8, 0x4f, 0x45, 0x47, 0xf1, 0xcb, 0x53, 0x3a, 0x0f, 0xaa, 0x9c, 0x63, 0xc2, 0xcf, 0x8c, + 0x06, 0x14, 0xd4, 0xa4, 0xe8, 0xd9, 0x3e, 0x15, 0xd3, 0x5f, 0x91, 0x4d, 0xa6, 0x63, 0x62, 0x0e, 0x56, 0xc5, 0xd7, + 0xb7, 0xe8, 0x9a, 0xe6, 0x87, 0x8a, 0xff, 0xf9, 0xb3, 0xe6, 0x83, 0xf9, 0xfd, 0x48, 0x82, 0x0f, 0x3c, 0xeb, 0x25, + 0x80, 0xf9, 0x85, 0x62, 0x09, 0x81, 0x05, 0xbe, 0x31, 0xf0, 0x6f, 0x51, 0xcc, 0x7f, 0x30, 0xc5, 0x9e, 0x15, 0xb8, + 0xe1, 0x02, 0x50, 0x9a, 0x1b, 0x2e, 0x6a, 0x06, 0x04, 0xd4, 0xbb, 0xae, 0x52, 0x5a, 0x74, 0x55, 0x28, 0xf7, 0xd3, + 0xef, 0x1f, 0xae, 0x68, 0xe2, 0x21, 0x48, 0x72, 0xed, 0xce, 0xd0, 0x15, 0xac, 0xd0, 0x3d, 0xbc, 0x1c, 0x7d, 0x73, + 0xb6, 0x22, 0x99, 0x4b, 0x05, 0x97, 0xc0, 0xe2, 0x01, 0x39, 0xa0, 0x78, 0x3c, 0x69, 0x28, 0x65, 0xf0, 0x66, 0xe4, + 0xce, 0xf7, 0x18, 0x9f, 0x66, 0x28, 0xec, 0x9e, 0x32, 0xd1, 0x46, 0x69, 0xe4, 0x18, 0xd4, 0x44, 0xd6, 0x73, 0x31, + 0xec, 0xe0, 0x28, 0x8c, 0xd4, 0xf1, 0x37, 0xc2, 0x9b, 0xa8, 0x6d, 0x11, 0x20, 0xfb, 0xdf, 0x75, 0x42, 0x82, 0x7f, + 0x8d, 0xbe, 0x81, 0x8b, 0xfb, 0x9b, 0x1b, 0x55, 0x1f, 0x66, 0x16, 0xf2, 0x31, 0xdf, 0x34, 0x64, 0xc1, 0x43, 0x1e, + 0x95, 0x31, 0x9b, 0x5d, 0x89, 0xd9, 0x84, 0xdf, 0xfb, 0x59, 0xd7, 0xf1, 0x19, 0x5e, 0x68, 0x63, 0xe0, 0x2e, 0xb6, + 0x25, 0x9e, 0xd3, 0x19, 0x22, 0x83, 0x3a, 0x0d, 0x5c, 0xef, 0x13, 0xe7, 0x50, 0xe5, 0x87, 0x43, 0x78, 0x51, 0x41, + 0xd9, 0x35, 0xee, 0x65, 0xdc, 0xca, 0x5b, 0xfc, 0x32, 0x7e, 0xea, 0x7e, 0xe9, 0x67, 0x82, 0x19, 0xc6, 0x87, 0x1c, + 0xb4, 0x39, 0x38, 0xbe, 0x82, 0xfd, 0x01, 0x06, 0xd5, 0x39, 0xfd, 0x4b, 0xef, 0xce, 0xb1, 0x97, 0x1d, 0xc7, 0x02, + 0x36, 0x67, 0xd9, 0xb5, 0xfa, 0x81, 0xd9, 0xb5, 0xfa, 0xf0, 0xf7, 0x11, 0x58, 0x2f, 0xb3, 0x63, 0x1d, 0x7f, 0x74, + 0x3a, 0x81, 0x79, 0x6a, 0xf5, 0xe1, 0xef, 0x92, 0xb6, 0xfa, 0x05, 0x99, 0x1e, 0x60, 0x78, 0xbe, 0x29, 0x61, 0x01, + 0xe9, 0xb7, 0xd0, 0x22, 0x18, 0xa5, 0xeb, 0xad, 0x41, 0x13, 0x01, 0x28, 0x43, 0x35, 0x78, 0x94, 0xc0, 0x70, 0xa8, + 0x41, 0x5a, 0x6e, 0x0c, 0x28, 0xcf, 0x0d, 0x32, 0xc2, 0x22, 0xc5, 0x7c, 0xfb, 0x31, 0x62, 0x6d, 0x9a, 0x03, 0x70, + 0xf3, 0x4c, 0x45, 0x54, 0x75, 0xf1, 0xb7, 0x18, 0x03, 0xeb, 0xf0, 0x90, 0xe1, 0x12, 0x56, 0x2a, 0xb2, 0xe5, 0xe5, + 0xfb, 0x07, 0x8e, 0x7e, 0xa3, 0x44, 0x64, 0x6b, 0xf9, 0xaa, 0x7d, 0x33, 0x75, 0x86, 0xe8, 0xfd, 0xf7, 0xf6, 0x83, + 0x49, 0x4a, 0x69, 0x3f, 0x3c, 0xba, 0xe7, 0xcc, 0x4f, 0xc4, 0xf0, 0x24, 0x14, 0xed, 0x34, 0x47, 0x2e, 0xd7, 0x21, + 0xad, 0xc5, 0x05, 0x50, 0xc9, 0x77, 0x6e, 0x20, 0x99, 0x5e, 0x48, 0x2d, 0x9f, 0x08, 0xcc, 0xff, 0xfc, 0x79, 0x31, + 0x38, 0xb3, 0x32, 0xee, 0x33, 0xa7, 0x07, 0xd7, 0x6e, 0x8f, 0x74, 0x77, 0x5a, 0x01, 0xed, 0x0f, 0x0f, 0x5b, 0xc4, + 0x93, 0xe4, 0x9a, 0x7e, 0xae, 0x63, 0x6c, 0x35, 0x45, 0xaa, 0x69, 0x18, 0x21, 0xb0, 0x6e, 0x85, 0xd5, 0x51, 0xf5, + 0x61, 0xc8, 0x15, 0x66, 0xe1, 0x8e, 0x90, 0xb8, 0x8c, 0x17, 0x53, 0x01, 0x34, 0x3b, 0xe6, 0xb1, 0xc7, 0xa5, 0xf1, + 0x7f, 0x3d, 0x09, 0x74, 0x2f, 0x02, 0x0d, 0x5f, 0xe5, 0xb4, 0x96, 0xdc, 0x4d, 0xc4, 0xbd, 0x4a, 0x2f, 0x54, 0x92, + 0x9e, 0xab, 0x50, 0x04, 0xf9, 0x8e, 0x30, 0xc5, 0x99, 0x30, 0x6f, 0x12, 0xb7, 0x45, 0x51, 0x60, 0xf8, 0x10, 0x13, + 0x5a, 0xe3, 0xae, 0x4e, 0xfa, 0xf3, 0xe7, 0xad, 0x97, 0x10, 0x55, 0x27, 0xcb, 0x99, 0x1e, 0x55, 0x19, 0xbf, 0xa9, + 0x32, 0x8a, 0x11, 0xfd, 0x22, 0xd6, 0xe0, 0x56, 0x59, 0x74, 0xef, 0xe1, 0xcf, 0x29, 0x71, 0x33, 0x8b, 0xe9, 0x41, + 0x34, 0xe9, 0x72, 0x37, 0x1c, 0xd2, 0x05, 0x7b, 0x2c, 0x16, 0x7f, 0x8b, 0x05, 0x9b, 0x7b, 0xb6, 0xfd, 0xb8, 0x66, + 0x7e, 0xc8, 0xd0, 0xc7, 0x67, 0xbb, 0x08, 0x9e, 0xf2, 0x2e, 0x73, 0x69, 0x84, 0x0d, 0xf9, 0xca, 0x8d, 0x32, 0x97, + 0xe7, 0x15, 0x01, 0xba, 0x7c, 0xd8, 0xa8, 0x30, 0x94, 0x7c, 0x95, 0xc7, 0xef, 0xae, 0xbe, 0x53, 0xd8, 0xfe, 0xa7, + 0xfa, 0x2d, 0x64, 0x64, 0x68, 0x14, 0xfc, 0x11, 0x8d, 0x82, 0xaf, 0xb0, 0xb4, 0x12, 0x10, 0x4b, 0x3e, 0x3f, 0xa2, + 0x10, 0x54, 0x15, 0x12, 0x7a, 0x54, 0xeb, 0xb7, 0x5a, 0x07, 0x99, 0x1f, 0xbb, 0x49, 0x76, 0x04, 0x4d, 0x4d, 0x40, + 0x72, 0x6a, 0x9b, 0x07, 0x33, 0x55, 0x1c, 0x72, 0xa1, 0x5a, 0x16, 0x72, 0xcd, 0xe1, 0xdc, 0x0f, 0x84, 0xe2, 0x90, + 0x7f, 0xc0, 0xf5, 0x3c, 0x12, 0x67, 0x23, 0xd5, 0x8d, 0x21, 0x1b, 0x02, 0xc6, 0x37, 0x3e, 0x8a, 0xbc, 0x8c, 0x64, + 0x66, 0x9a, 0x25, 0xc4, 0x5d, 0xa9, 0x22, 0xd6, 0x67, 0xbd, 0xbf, 0x74, 0x3d, 0x5d, 0xf9, 0x99, 0x08, 0x96, 0x47, + 0x27, 0x08, 0x2a, 0x3c, 0x18, 0xe2, 0x78, 0x92, 0x33, 0x10, 0x5e, 0x46, 0x8b, 0xca, 0x8e, 0x2a, 0x28, 0x97, 0x73, + 0x0c, 0xc5, 0xca, 0x22, 0xe0, 0xcf, 0xd0, 0x23, 0xe7, 0x96, 0x79, 0x5d, 0x8b, 0x98, 0x7e, 0xea, 0xf8, 0x8c, 0xb1, + 0xb7, 0x0a, 0x06, 0x0a, 0x50, 0x7b, 0x36, 0x04, 0x9b, 0x6d, 0xf3, 0xc7, 0x3e, 0x62, 0x95, 0xe1, 0x6a, 0xa2, 0x3d, + 0x63, 0xdc, 0x6f, 0x3a, 0x96, 0x2b, 0x20, 0x84, 0x4a, 0x2a, 0xde, 0xa5, 0x33, 0x16, 0x0e, 0x40, 0x38, 0x2a, 0xa4, + 0x95, 0x3e, 0x7f, 0x7e, 0x3d, 0xf9, 0xcf, 0xbf, 0x21, 0x38, 0xf9, 0xd2, 0xe1, 0x5e, 0xd0, 0xd7, 0x72, 0x2d, 0x46, + 0x7d, 0x1a, 0x13, 0x54, 0xef, 0x93, 0x19, 0x0f, 0x0b, 0xc2, 0xb7, 0x56, 0x3e, 0xb9, 0xe1, 0xa1, 0x9e, 0x20, 0x01, + 0x81, 0xce, 0x7d, 0xb5, 0x27, 0xb0, 0xbc, 0x13, 0x1e, 0x22, 0x40, 0xf9, 0x75, 0xf3, 0x7d, 0x1f, 0xb2, 0xf4, 0xd6, + 0xf2, 0x02, 0x48, 0x03, 0xc4, 0x3d, 0x34, 0x3e, 0x73, 0x99, 0xf0, 0x15, 0xc8, 0x8f, 0x74, 0x70, 0x04, 0xd3, 0x5c, + 0x46, 0x2b, 0x62, 0xf9, 0xd1, 0xd1, 0x3d, 0x99, 0x9a, 0x6e, 0xec, 0x53, 0xf9, 0x32, 0xca, 0xdd, 0x14, 0x4a, 0xf9, + 0x09, 0x05, 0x2d, 0xa5, 0xaf, 0xf3, 0x02, 0x94, 0x51, 0x01, 0x28, 0xf8, 0xe9, 0x8e, 0xcb, 0x01, 0xfc, 0x2c, 0x1e, + 0x31, 0xbe, 0x8c, 0xe5, 0xcf, 0x69, 0x1c, 0x3e, 0x1e, 0x72, 0xaf, 0x78, 0x30, 0xa3, 0xf9, 0x5c, 0x0e, 0xba, 0x67, + 0x95, 0xbf, 0x2f, 0xa0, 0x52, 0xec, 0xd9, 0x28, 0xa6, 0x5f, 0xaa, 0x7f, 0x42, 0xfc, 0x84, 0x6c, 0xb9, 0x2c, 0x3e, + 0x23, 0x9c, 0xe7, 0x5a, 0xf0, 0x3e, 0x01, 0x92, 0xa7, 0xb4, 0x12, 0x43, 0x14, 0xd5, 0xc8, 0xd0, 0x2d, 0xa4, 0xc9, + 0x93, 0xd1, 0x88, 0xe2, 0xb1, 0x2a, 0x3a, 0x03, 0x28, 0x35, 0x44, 0xcf, 0x87, 0xc9, 0x66, 0xd0, 0xd0, 0xa4, 0x1e, + 0x5c, 0xd8, 0xa8, 0x3a, 0x9d, 0xfa, 0x18, 0x8f, 0x5c, 0xbe, 0xbf, 0x4a, 0x3b, 0x10, 0x76, 0x16, 0x5b, 0x58, 0x40, + 0xe0, 0xbc, 0x9f, 0x0a, 0x1e, 0x57, 0xbe, 0xa5, 0x28, 0xdb, 0x0c, 0xdc, 0x87, 0x48, 0xd2, 0xac, 0x33, 0x27, 0xfb, + 0x4b, 0x2c, 0xbd, 0xe2, 0xce, 0x6d, 0xb5, 0x93, 0x24, 0x22, 0x90, 0xd7, 0x4f, 0x93, 0x1c, 0x32, 0x7c, 0xdf, 0x61, + 0x92, 0xeb, 0x96, 0x27, 0x83, 0xd8, 0x31, 0x2f, 0x0e, 0x5a, 0xe9, 0x25, 0x9e, 0xfb, 0xfc, 0xec, 0x08, 0xe6, 0x07, + 0x81, 0x01, 0x4a, 0x94, 0x91, 0xaf, 0x43, 0xf4, 0x01, 0x37, 0xa5, 0xd6, 0x01, 0x17, 0x33, 0x4e, 0xd4, 0x21, 0xe7, + 0x28, 0xa2, 0x83, 0x96, 0xaa, 0xd4, 0x89, 0x15, 0xbb, 0x99, 0xca, 0xdb, 0x1f, 0xb1, 0xff, 0xb7, 0x35, 0x86, 0xeb, + 0xcf, 0x87, 0x19, 0xe1, 0x7e, 0xb7, 0x97, 0x59, 0x8b, 0x6b, 0x6e, 0x5b, 0x15, 0x4a, 0xb0, 0xee, 0xa8, 0x50, 0xec, + 0xe3, 0x5d, 0xb5, 0x0a, 0xd2, 0x48, 0x54, 0x8b, 0x5d, 0x4d, 0x7d, 0x8a, 0x3b, 0xbe, 0x56, 0x1b, 0x4b, 0xa1, 0xde, + 0x65, 0x36, 0x82, 0xaa, 0x5c, 0xd8, 0xee, 0xc6, 0x31, 0xad, 0xac, 0x0f, 0xcf, 0x8e, 0x28, 0xdf, 0x39, 0xa6, 0x3b, + 0x6c, 0x7c, 0x06, 0xd6, 0x85, 0x74, 0xd1, 0xdd, 0x38, 0x66, 0x4b, 0x4a, 0x7f, 0xd1, 0x37, 0x47, 0xcb, 0x6c, 0x15, + 0x8c, 0xff, 0x0f, 0x00, 0xa3, 0x9b, 0x76, 0x11, 0x5a, 0x03, 0x00}; } // namespace web_server } // namespace esphome From fcdf36e991342e29213f07c4f09fd639c83d7e54 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 21 May 2024 11:07:20 +1200 Subject: [PATCH 1491/2101] Bump version to 2024.5.2 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 9d2b8b78ea..48b8aa8656 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.5.1" +__version__ = "2024.5.2" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 76abf2200cb297e1b89abaf44d8997f047848d95 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Tue, 21 May 2024 20:08:53 -0500 Subject: [PATCH 1492/2101] Uncouple safe_mode from OTA (#6759) --- CODEOWNERS | 2 +- esphome/components/esphome/ota/__init__.py | 30 ++--- .../components/esphome/ota/ota_esphome.cpp | 98 +------------- esphome/components/esphome/ota/ota_esphome.h | 27 +--- esphome/components/ota/__init__.py | 4 +- esphome/components/safe_mode/__init__.py | 53 +++++++- .../components/safe_mode/button/__init__.py | 13 +- .../safe_mode/button/safe_mode_button.cpp | 6 +- .../safe_mode/button/safe_mode_button.h | 6 +- esphome/components/safe_mode/safe_mode.cpp | 125 ++++++++++++++++++ esphome/components/safe_mode/safe_mode.h | 44 ++++++ .../components/safe_mode/switch/__init__.py | 13 +- .../safe_mode/switch/safe_mode_switch.cpp | 9 +- .../safe_mode/switch/safe_mode_switch.h | 6 +- esphome/cpp_helpers.py | 17 +-- tests/components/ota/common.yaml | 3 - tests/components/safe_mode/common.yaml | 6 +- tests/test1.yaml | 7 +- tests/test2.yaml | 4 +- tests/test3.yaml | 6 +- tests/test4.yaml | 3 +- 21 files changed, 282 insertions(+), 200 deletions(-) create mode 100644 esphome/components/safe_mode/safe_mode.cpp create mode 100644 esphome/components/safe_mode/safe_mode.h diff --git a/CODEOWNERS b/CODEOWNERS index dc6c8caa87..22e581275b 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -306,7 +306,7 @@ esphome/components/rp2040_pwm/* @jesserockz esphome/components/rpi_dpi_rgb/* @clydebarrow esphome/components/rtl87xx/* @kuba2k2 esphome/components/rtttl/* @glmnet -esphome/components/safe_mode/* @jsuanet @paulmonigatti +esphome/components/safe_mode/* @jsuanet @kbx81 @paulmonigatti esphome/components/scd4x/* @martgras @sjtrny esphome/components/script/* @esphome/core esphome/components/sdm_meter/* @jesserockz @polyfaces diff --git a/esphome/components/esphome/ota/__init__.py b/esphome/components/esphome/ota/__init__.py index abe9323b53..c5903974c2 100644 --- a/esphome/components/esphome/ota/__init__.py +++ b/esphome/components/esphome/ota/__init__.py @@ -1,19 +1,16 @@ -from esphome.cpp_generator import RawExpression import esphome.codegen as cg import esphome.config_validation as cv from esphome.components.ota import BASE_OTA_SCHEMA, ota_to_code, OTAComponent from esphome.const import ( CONF_ID, CONF_NUM_ATTEMPTS, - CONF_OTA, CONF_PASSWORD, CONF_PORT, CONF_REBOOT_TIMEOUT, CONF_SAFE_MODE, CONF_VERSION, - KEY_PAST_SAFE_MODE, ) -from esphome.core import CORE, coroutine_with_priority +from esphome.core import coroutine_with_priority CODEOWNERS = ["@esphome/core"] @@ -28,7 +25,6 @@ CONFIG_SCHEMA = ( cv.Schema( { cv.GenerateID(): cv.declare_id(ESPHomeOTAComponent), - cv.Optional(CONF_SAFE_MODE, default=True): cv.boolean, cv.Optional(CONF_VERSION, default=2): cv.one_of(1, 2, int=True), cv.SplitDefault( CONF_PORT, @@ -39,10 +35,15 @@ CONFIG_SCHEMA = ( rtl87xx=8892, ): cv.port, cv.Optional(CONF_PASSWORD): cv.string, - cv.Optional( - CONF_REBOOT_TIMEOUT, default="5min" - ): cv.positive_time_period_milliseconds, - cv.Optional(CONF_NUM_ATTEMPTS, default="10"): cv.positive_not_null_int, + cv.Optional(CONF_NUM_ATTEMPTS): cv.invalid( + f"'{CONF_SAFE_MODE}' (and its related configuration variables) has moved from 'ota' to its own component. See https://esphome.io/components/safe_mode" + ), + cv.Optional(CONF_REBOOT_TIMEOUT): cv.invalid( + f"'{CONF_SAFE_MODE}' (and its related configuration variables) has moved from 'ota' to its own component. See https://esphome.io/components/safe_mode" + ), + cv.Optional(CONF_SAFE_MODE): cv.invalid( + f"'{CONF_SAFE_MODE}' (and its related configuration variables) has moved from 'ota' to its own component. See https://esphome.io/components/safe_mode" + ), } ) .extend(BASE_OTA_SCHEMA) @@ -50,10 +51,8 @@ CONFIG_SCHEMA = ( ) -@coroutine_with_priority(50.0) +@coroutine_with_priority(52.0) async def to_code(config): - CORE.data[CONF_OTA] = {} - var = cg.new_Pvariable(config[CONF_ID]) await ota_to_code(var, config) cg.add(var.set_port(config[CONF_PORT])) @@ -63,10 +62,3 @@ async def to_code(config): cg.add_define("USE_OTA_VERSION", config[CONF_VERSION]) await cg.register_component(var, config) - - if config[CONF_SAFE_MODE]: - condition = var.should_enter_safe_mode( - config[CONF_NUM_ATTEMPTS], config[CONF_REBOOT_TIMEOUT] - ) - cg.add(RawExpression(f"if ({condition}) return")) - CORE.data[CONF_OTA][KEY_PAST_SAFE_MODE] = True diff --git a/esphome/components/esphome/ota/ota_esphome.cpp b/esphome/components/esphome/ota/ota_esphome.cpp index f2f1cfc6a8..9d5044aaeb 100644 --- a/esphome/components/esphome/ota/ota_esphome.cpp +++ b/esphome/components/esphome/ota/ota_esphome.cpp @@ -78,23 +78,9 @@ void ESPHomeOTAComponent::dump_config() { ESP_LOGCONFIG(TAG, " Password configured"); } #endif - if (this->has_safe_mode_ && this->safe_mode_rtc_value_ > 1 && - this->safe_mode_rtc_value_ != ESPHomeOTAComponent::ENTER_SAFE_MODE_MAGIC) { - ESP_LOGW(TAG, "Last reset occurred too quickly; safe mode will be invoked in %" PRIu32 " restarts", - this->safe_mode_num_attempts_ - this->safe_mode_rtc_value_); - } } -void ESPHomeOTAComponent::loop() { - this->handle_(); - - if (this->has_safe_mode_ && (millis() - this->safe_mode_start_time_) > this->safe_mode_enable_time_) { - this->has_safe_mode_ = false; - // successful boot, reset counter - ESP_LOGI(TAG, "Boot seems successful; resetting boot loop counter"); - this->clean_rtc(); - } -} +void ESPHomeOTAComponent::loop() { this->handle_(); } static const uint8_t FEATURE_SUPPORTS_COMPRESSION = 0x01; @@ -423,86 +409,4 @@ bool ESPHomeOTAComponent::writeall_(const uint8_t *buf, size_t len) { float ESPHomeOTAComponent::get_setup_priority() const { return setup_priority::AFTER_WIFI; } uint16_t ESPHomeOTAComponent::get_port() const { return this->port_; } void ESPHomeOTAComponent::set_port(uint16_t port) { this->port_ = port; } - -void ESPHomeOTAComponent::set_safe_mode_pending(const bool &pending) { - if (!this->has_safe_mode_) - return; - - uint32_t current_rtc = this->read_rtc_(); - - if (pending && current_rtc != ESPHomeOTAComponent::ENTER_SAFE_MODE_MAGIC) { - ESP_LOGI(TAG, "Device will enter safe mode on next boot"); - this->write_rtc_(ESPHomeOTAComponent::ENTER_SAFE_MODE_MAGIC); - } - - if (!pending && current_rtc == ESPHomeOTAComponent::ENTER_SAFE_MODE_MAGIC) { - ESP_LOGI(TAG, "Safe mode pending has been cleared"); - this->clean_rtc(); - } -} -bool ESPHomeOTAComponent::get_safe_mode_pending() { - return this->has_safe_mode_ && this->read_rtc_() == ESPHomeOTAComponent::ENTER_SAFE_MODE_MAGIC; -} - -bool ESPHomeOTAComponent::should_enter_safe_mode(uint8_t num_attempts, uint32_t enable_time) { - this->has_safe_mode_ = true; - this->safe_mode_start_time_ = millis(); - this->safe_mode_enable_time_ = enable_time; - this->safe_mode_num_attempts_ = num_attempts; - this->rtc_ = global_preferences->make_preference(233825507UL, false); - this->safe_mode_rtc_value_ = this->read_rtc_(); - - bool is_manual_safe_mode = this->safe_mode_rtc_value_ == ESPHomeOTAComponent::ENTER_SAFE_MODE_MAGIC; - - if (is_manual_safe_mode) { - ESP_LOGI(TAG, "Safe mode has been entered manually"); - } else { - ESP_LOGCONFIG(TAG, "There have been %" PRIu32 " suspected unsuccessful boot attempts", this->safe_mode_rtc_value_); - } - - if (this->safe_mode_rtc_value_ >= num_attempts || is_manual_safe_mode) { - this->clean_rtc(); - - if (!is_manual_safe_mode) { - ESP_LOGE(TAG, "Boot loop detected. Proceeding to safe mode"); - } - - this->status_set_error(); - this->set_timeout(enable_time, []() { - ESP_LOGE(TAG, "No OTA attempt made, restarting"); - App.reboot(); - }); - - // Delay here to allow power to stabilise before Wi-Fi/Ethernet is initialised. - delay(300); // NOLINT - App.setup(); - - ESP_LOGI(TAG, "Waiting for OTA attempt"); - - return true; - } else { - // increment counter - this->write_rtc_(this->safe_mode_rtc_value_ + 1); - return false; - } -} - -void ESPHomeOTAComponent::write_rtc_(uint32_t val) { - this->rtc_.save(&val); - global_preferences->sync(); -} - -uint32_t ESPHomeOTAComponent::read_rtc_() { - uint32_t val; - if (!this->rtc_.load(&val)) - return 0; - return val; -} - -void ESPHomeOTAComponent::clean_rtc() { this->write_rtc_(0); } - -void ESPHomeOTAComponent::on_safe_shutdown() { - if (this->has_safe_mode_ && this->read_rtc_() != ESPHomeOTAComponent::ENTER_SAFE_MODE_MAGIC) - this->clean_rtc(); -} } // namespace esphome diff --git a/esphome/components/esphome/ota/ota_esphome.h b/esphome/components/esphome/ota/ota_esphome.h index e8f36f05ca..42629b4346 100644 --- a/esphome/components/esphome/ota/ota_esphome.h +++ b/esphome/components/esphome/ota/ota_esphome.h @@ -15,17 +15,9 @@ class ESPHomeOTAComponent : public ota::OTAComponent { void set_auth_password(const std::string &password) { password_ = password; } #endif // USE_OTA_PASSWORD - /// Manually set the port OTA should listen on. + /// Manually set the port OTA should listen on void set_port(uint16_t port); - bool should_enter_safe_mode(uint8_t num_attempts, uint32_t enable_time); - - /// Set to true if the next startup will enter safe mode - void set_safe_mode_pending(const bool &pending); - bool get_safe_mode_pending(); - - // ========== INTERNAL METHODS ========== - // (In most use cases you won't need these) void setup() override; void dump_config() override; float get_setup_priority() const override; @@ -33,14 +25,7 @@ class ESPHomeOTAComponent : public ota::OTAComponent { uint16_t get_port() const; - void clean_rtc(); - - void on_safe_shutdown() override; - protected: - void write_rtc_(uint32_t val); - uint32_t read_rtc_(); - void handle_(); bool readall_(uint8_t *buf, size_t len); bool writeall_(const uint8_t *buf, size_t len); @@ -53,16 +38,6 @@ class ESPHomeOTAComponent : public ota::OTAComponent { std::unique_ptr server_; std::unique_ptr client_; - - bool has_safe_mode_{false}; ///< stores whether safe mode can be enabled - uint32_t safe_mode_start_time_; ///< stores when safe mode was enabled - uint32_t safe_mode_enable_time_{60000}; ///< The time safe mode should be on for - uint32_t safe_mode_rtc_value_; - uint8_t safe_mode_num_attempts_; - ESPPreferenceObject rtc_; - - static const uint32_t ENTER_SAFE_MODE_MAGIC = - 0x5afe5afe; ///< a magic number to indicate that safe mode should be entered on next boot }; } // namespace esphome diff --git a/esphome/components/ota/__init__.py b/esphome/components/ota/__init__.py index 3d2956931c..4e447bfb2d 100644 --- a/esphome/components/ota/__init__.py +++ b/esphome/components/ota/__init__.py @@ -6,7 +6,7 @@ from esphome.core import CORE, coroutine_with_priority from esphome.const import CONF_ESPHOME, CONF_OTA, CONF_PLATFORM, CONF_TRIGGER_ID CODEOWNERS = ["@esphome/core"] -AUTO_LOAD = ["md5"] +AUTO_LOAD = ["md5", "safe_mode"] IS_PLATFORM_COMPONENT = True @@ -76,7 +76,7 @@ BASE_OTA_SCHEMA = cv.Schema( ) -@coroutine_with_priority(51.0) +@coroutine_with_priority(54.0) async def to_code(config): cg.add_define("USE_OTA") diff --git a/esphome/components/safe_mode/__init__.py b/esphome/components/safe_mode/__init__.py index ab884bfee4..7f227d7dd1 100644 --- a/esphome/components/safe_mode/__init__.py +++ b/esphome/components/safe_mode/__init__.py @@ -1,5 +1,56 @@ +from esphome.cpp_generator import RawExpression import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.const import ( + CONF_DISABLED, + CONF_ID, + CONF_NUM_ATTEMPTS, + CONF_REBOOT_TIMEOUT, + CONF_SAFE_MODE, + KEY_PAST_SAFE_MODE, +) +from esphome.core import CORE, coroutine_with_priority -CODEOWNERS = ["@paulmonigatti", "@jsuanet"] + +CODEOWNERS = ["@paulmonigatti", "@jsuanet", "@kbx81"] safe_mode_ns = cg.esphome_ns.namespace("safe_mode") +SafeModeComponent = safe_mode_ns.class_("SafeModeComponent", cg.Component) + + +def _remove_id_if_disabled(value): + value = value.copy() + if value[CONF_DISABLED]: + value.pop(CONF_ID) + return value + + +CONFIG_SCHEMA = cv.All( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(SafeModeComponent), + cv.Optional(CONF_DISABLED, default=False): cv.boolean, + cv.Optional(CONF_NUM_ATTEMPTS, default="10"): cv.positive_not_null_int, + cv.Optional( + CONF_REBOOT_TIMEOUT, default="5min" + ): cv.positive_time_period_milliseconds, + } + ).extend(cv.COMPONENT_SCHEMA), + _remove_id_if_disabled, +) + + +@coroutine_with_priority(50.0) +async def to_code(config): + if config[CONF_DISABLED]: + return + + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, config) + + condition = var.should_enter_safe_mode( + config[CONF_NUM_ATTEMPTS], config[CONF_REBOOT_TIMEOUT] + ) + cg.add(RawExpression(f"if ({condition}) return")) + CORE.data[CONF_SAFE_MODE] = {} + CORE.data[CONF_SAFE_MODE][KEY_PAST_SAFE_MODE] = True diff --git a/esphome/components/safe_mode/button/__init__.py b/esphome/components/safe_mode/button/__init__.py index bd51d2e038..5662db8f7e 100644 --- a/esphome/components/safe_mode/button/__init__.py +++ b/esphome/components/safe_mode/button/__init__.py @@ -1,16 +1,15 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import button -from esphome.components.esphome.ota import ESPHomeOTAComponent from esphome.const import ( - CONF_ESPHOME, + CONF_SAFE_MODE, DEVICE_CLASS_RESTART, ENTITY_CATEGORY_CONFIG, ICON_RESTART_ALERT, ) -from .. import safe_mode_ns +from .. import safe_mode_ns, SafeModeComponent -DEPENDENCIES = ["ota.esphome"] +DEPENDENCIES = ["safe_mode"] SafeModeButton = safe_mode_ns.class_("SafeModeButton", button.Button, cg.Component) @@ -21,7 +20,7 @@ CONFIG_SCHEMA = ( entity_category=ENTITY_CATEGORY_CONFIG, icon=ICON_RESTART_ALERT, ) - .extend({cv.GenerateID(CONF_ESPHOME): cv.use_id(ESPHomeOTAComponent)}) + .extend({cv.GenerateID(CONF_SAFE_MODE): cv.use_id(SafeModeComponent)}) .extend(cv.COMPONENT_SCHEMA) ) @@ -30,5 +29,5 @@ async def to_code(config): var = await button.new_button(config) await cg.register_component(var, config) - ota = await cg.get_variable(config[CONF_ESPHOME]) - cg.add(var.set_ota(ota)) + safe_mode_component = await cg.get_variable(config[CONF_SAFE_MODE]) + cg.add(var.set_safe_mode(safe_mode_component)) diff --git a/esphome/components/safe_mode/button/safe_mode_button.cpp b/esphome/components/safe_mode/button/safe_mode_button.cpp index d513b79c12..261688807a 100644 --- a/esphome/components/safe_mode/button/safe_mode_button.cpp +++ b/esphome/components/safe_mode/button/safe_mode_button.cpp @@ -8,11 +8,13 @@ namespace safe_mode { static const char *const TAG = "safe_mode.button"; -void SafeModeButton::set_ota(esphome::ESPHomeOTAComponent *ota) { this->ota_ = ota; } +void SafeModeButton::set_safe_mode(SafeModeComponent *safe_mode_component) { + this->safe_mode_component_ = safe_mode_component; +} void SafeModeButton::press_action() { ESP_LOGI(TAG, "Restarting device in safe mode..."); - this->ota_->set_safe_mode_pending(true); + this->safe_mode_component_->set_safe_mode_pending(true); // Let MQTT settle a bit delay(100); // NOLINT diff --git a/esphome/components/safe_mode/button/safe_mode_button.h b/esphome/components/safe_mode/button/safe_mode_button.h index a306735b7f..fea0955abb 100644 --- a/esphome/components/safe_mode/button/safe_mode_button.h +++ b/esphome/components/safe_mode/button/safe_mode_button.h @@ -1,7 +1,7 @@ #pragma once #include "esphome/components/button/button.h" -#include "esphome/components/esphome/ota/ota_esphome.h" +#include "esphome/components/safe_mode/safe_mode.h" #include "esphome/core/component.h" namespace esphome { @@ -10,10 +10,10 @@ namespace safe_mode { class SafeModeButton : public button::Button, public Component { public: void dump_config() override; - void set_ota(esphome::ESPHomeOTAComponent *ota); + void set_safe_mode(SafeModeComponent *safe_mode_component); protected: - esphome::ESPHomeOTAComponent *ota_; + SafeModeComponent *safe_mode_component_; void press_action() override; }; diff --git a/esphome/components/safe_mode/safe_mode.cpp b/esphome/components/safe_mode/safe_mode.cpp new file mode 100644 index 0000000000..06772ae1e0 --- /dev/null +++ b/esphome/components/safe_mode/safe_mode.cpp @@ -0,0 +1,125 @@ +#include "safe_mode.h" + +#include "esphome/core/application.h" +#include "esphome/core/hal.h" +#include "esphome/core/log.h" +#include "esphome/core/util.h" + +#include +#include +#include + +namespace esphome { +namespace safe_mode { + +static const char *const TAG = "safe_mode"; + +void SafeModeComponent::dump_config() { + ESP_LOGCONFIG(TAG, "Safe Mode:"); + ESP_LOGCONFIG(TAG, " Invoke after %u boot attempts", this->safe_mode_num_attempts_); + ESP_LOGCONFIG(TAG, " Remain in safe mode for %" PRIu32 " seconds", + this->safe_mode_enable_time_ / 1000); // because milliseconds + + 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_; + if (remaining_restarts) { + ESP_LOGW(TAG, "Last reset occurred too quickly; safe mode will be invoked in %" PRIu32 " restarts", + remaining_restarts); + } else { + ESP_LOGW(TAG, "SAFE MODE IS ACTIVE"); + } + } +} + +float SafeModeComponent::get_setup_priority() const { return setup_priority::AFTER_WIFI; } + +void SafeModeComponent::loop() { + if (!this->boot_successful_ && (millis() - this->safe_mode_start_time_) > this->safe_mode_enable_time_) { + // successful boot, reset counter + ESP_LOGI(TAG, "Boot seems successful; resetting boot loop counter"); + this->clean_rtc(); + this->boot_successful_ = true; + } +} + +void SafeModeComponent::set_safe_mode_pending(const bool &pending) { + uint32_t current_rtc = this->read_rtc_(); + + if (pending && current_rtc != SafeModeComponent::ENTER_SAFE_MODE_MAGIC) { + ESP_LOGI(TAG, "Device will enter safe mode on next boot"); + this->write_rtc_(SafeModeComponent::ENTER_SAFE_MODE_MAGIC); + } + + if (!pending && current_rtc == SafeModeComponent::ENTER_SAFE_MODE_MAGIC) { + ESP_LOGI(TAG, "Safe mode pending has been cleared"); + this->clean_rtc(); + } +} + +bool SafeModeComponent::get_safe_mode_pending() { + return this->read_rtc_() == SafeModeComponent::ENTER_SAFE_MODE_MAGIC; +} + +bool SafeModeComponent::should_enter_safe_mode(uint8_t num_attempts, uint32_t enable_time) { + this->safe_mode_start_time_ = millis(); + this->safe_mode_enable_time_ = enable_time; + this->safe_mode_num_attempts_ = num_attempts; + this->rtc_ = global_preferences->make_preference(233825507UL, false); + this->safe_mode_rtc_value_ = this->read_rtc_(); + + bool is_manual_safe_mode = this->safe_mode_rtc_value_ == SafeModeComponent::ENTER_SAFE_MODE_MAGIC; + + if (is_manual_safe_mode) { + ESP_LOGI(TAG, "Safe mode invoked manually"); + } else { + ESP_LOGCONFIG(TAG, "There have been %" PRIu32 " suspected unsuccessful boot attempts", this->safe_mode_rtc_value_); + } + + if (this->safe_mode_rtc_value_ >= num_attempts || is_manual_safe_mode) { + this->clean_rtc(); + + if (!is_manual_safe_mode) { + ESP_LOGE(TAG, "Boot loop detected. Proceeding to safe mode"); + } + + this->status_set_error(); + this->set_timeout(enable_time, []() { + ESP_LOGW(TAG, "Safe mode enable time has elapsed -- restarting"); + App.reboot(); + }); + + // Delay here to allow power to stabilize before Wi-Fi/Ethernet is initialised + delay(300); // NOLINT + App.setup(); + + ESP_LOGW(TAG, "SAFE MODE IS ACTIVE"); + + return true; + } else { + // increment counter + this->write_rtc_(this->safe_mode_rtc_value_ + 1); + return false; + } +} + +void SafeModeComponent::write_rtc_(uint32_t val) { + this->rtc_.save(&val); + global_preferences->sync(); +} + +uint32_t SafeModeComponent::read_rtc_() { + uint32_t val; + if (!this->rtc_.load(&val)) + return 0; + return val; +} + +void SafeModeComponent::clean_rtc() { this->write_rtc_(0); } + +void SafeModeComponent::on_safe_shutdown() { + if (this->read_rtc_() != SafeModeComponent::ENTER_SAFE_MODE_MAGIC) + this->clean_rtc(); +} + +} // namespace safe_mode +} // namespace esphome diff --git a/esphome/components/safe_mode/safe_mode.h b/esphome/components/safe_mode/safe_mode.h new file mode 100644 index 0000000000..6c7450a6ff --- /dev/null +++ b/esphome/components/safe_mode/safe_mode.h @@ -0,0 +1,44 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/core/defines.h" +#include "esphome/core/helpers.h" +#include "esphome/core/preferences.h" + +namespace esphome { +namespace safe_mode { + +/// SafeModeComponent provides a safe way to recover from repeated boot failures +class SafeModeComponent : public Component { + public: + bool should_enter_safe_mode(uint8_t num_attempts, uint32_t enable_time); + + /// Set to true if the next startup will enter safe mode + void set_safe_mode_pending(const bool &pending); + bool get_safe_mode_pending(); + + void dump_config() override; + float get_setup_priority() const override; + void loop() override; + + void clean_rtc(); + + void on_safe_shutdown() override; + + protected: + void write_rtc_(uint32_t val); + uint32_t read_rtc_(); + + bool boot_successful_{false}; ///< set to true after boot is considered successful + uint32_t safe_mode_start_time_; ///< stores when safe mode was enabled + uint32_t safe_mode_enable_time_{60000}; ///< The time safe mode should remain active for + uint32_t safe_mode_rtc_value_; + uint8_t safe_mode_num_attempts_; + ESPPreferenceObject rtc_; + + 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 diff --git a/esphome/components/safe_mode/switch/__init__.py b/esphome/components/safe_mode/switch/__init__.py index 0f8e500482..7271358149 100644 --- a/esphome/components/safe_mode/switch/__init__.py +++ b/esphome/components/safe_mode/switch/__init__.py @@ -1,15 +1,14 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import switch -from esphome.components.esphome.ota import ESPHomeOTAComponent from esphome.const import ( - CONF_ESPHOME, + CONF_SAFE_MODE, ENTITY_CATEGORY_CONFIG, ICON_RESTART_ALERT, ) -from .. import safe_mode_ns +from .. import safe_mode_ns, SafeModeComponent -DEPENDENCIES = ["ota.esphome"] +DEPENDENCIES = ["safe_mode"] SafeModeSwitch = safe_mode_ns.class_("SafeModeSwitch", switch.Switch, cg.Component) @@ -20,7 +19,7 @@ CONFIG_SCHEMA = ( entity_category=ENTITY_CATEGORY_CONFIG, icon=ICON_RESTART_ALERT, ) - .extend({cv.GenerateID(CONF_ESPHOME): cv.use_id(ESPHomeOTAComponent)}) + .extend({cv.GenerateID(CONF_SAFE_MODE): cv.use_id(SafeModeComponent)}) .extend(cv.COMPONENT_SCHEMA) ) @@ -29,5 +28,5 @@ async def to_code(config): var = await switch.new_switch(config) await cg.register_component(var, config) - ota = await cg.get_variable(config[CONF_ESPHOME]) - cg.add(var.set_ota(ota)) + safe_mode_component = await cg.get_variable(config[CONF_SAFE_MODE]) + cg.add(var.set_safe_mode(safe_mode_component)) diff --git a/esphome/components/safe_mode/switch/safe_mode_switch.cpp b/esphome/components/safe_mode/switch/safe_mode_switch.cpp index 71408df140..13b35ed210 100644 --- a/esphome/components/safe_mode/switch/safe_mode_switch.cpp +++ b/esphome/components/safe_mode/switch/safe_mode_switch.cpp @@ -6,9 +6,11 @@ namespace esphome { namespace safe_mode { -static const char *const TAG = "safe_mode_switch"; +static const char *const TAG = "safe_mode.switch"; -void SafeModeSwitch::set_ota(esphome::ESPHomeOTAComponent *ota) { this->ota_ = ota; } +void SafeModeSwitch::set_safe_mode(SafeModeComponent *safe_mode_component) { + this->safe_mode_component_ = safe_mode_component; +} void SafeModeSwitch::write_state(bool state) { // Acknowledge @@ -16,13 +18,14 @@ void SafeModeSwitch::write_state(bool state) { if (state) { ESP_LOGI(TAG, "Restarting device in safe mode..."); - this->ota_->set_safe_mode_pending(true); + this->safe_mode_component_->set_safe_mode_pending(true); // Let MQTT settle a bit delay(100); // NOLINT App.safe_reboot(); } } + void SafeModeSwitch::dump_config() { LOG_SWITCH("", "Safe Mode Switch", this); } } // namespace safe_mode diff --git a/esphome/components/safe_mode/switch/safe_mode_switch.h b/esphome/components/safe_mode/switch/safe_mode_switch.h index 5bd15a44de..24e660c803 100644 --- a/esphome/components/safe_mode/switch/safe_mode_switch.h +++ b/esphome/components/safe_mode/switch/safe_mode_switch.h @@ -1,6 +1,6 @@ #pragma once -#include "esphome/components/esphome/ota/ota_esphome.h" +#include "esphome/components/safe_mode/safe_mode.h" #include "esphome/components/switch/switch.h" #include "esphome/core/component.h" @@ -10,10 +10,10 @@ namespace safe_mode { class SafeModeSwitch : public switch_::Switch, public Component { public: void dump_config() override; - void set_ota(esphome::ESPHomeOTAComponent *ota); + void set_safe_mode(SafeModeComponent *safe_mode_component); protected: - esphome::ESPHomeOTAComponent *ota_; + SafeModeComponent *safe_mode_component_; void write_state(bool state) override; }; diff --git a/esphome/cpp_helpers.py b/esphome/cpp_helpers.py index ce494e5d9d..825224bb9d 100644 --- a/esphome/cpp_helpers.py +++ b/esphome/cpp_helpers.py @@ -3,12 +3,9 @@ import logging from esphome.const import ( CONF_DISABLED_BY_DEFAULT, CONF_ENTITY_CATEGORY, - CONF_ESPHOME, CONF_ICON, CONF_INTERNAL, CONF_NAME, - CONF_OTA, - CONF_PLATFORM, CONF_SAFE_MODE, CONF_SETUP_PRIORITY, CONF_TYPE_ID, @@ -141,22 +138,12 @@ async def build_registry_list(registry, config): async def past_safe_mode(): - ota_conf = {} - for ota_item in CORE.config.get(CONF_OTA, []): - if ota_item[CONF_PLATFORM] == CONF_ESPHOME: - ota_conf = ota_item - break - - if not ota_conf: - return - - safe_mode_enabled = ota_conf[CONF_SAFE_MODE] - if not safe_mode_enabled: + if CONF_SAFE_MODE not in CORE.config: return def _safe_mode_generator(): while True: - if CORE.data.get(CONF_OTA, {}).get(KEY_PAST_SAFE_MODE, False): + if CORE.data.get(CONF_SAFE_MODE, {}).get(KEY_PAST_SAFE_MODE, False): return yield diff --git a/tests/components/ota/common.yaml b/tests/components/ota/common.yaml index 4910e2d891..1433dada1f 100644 --- a/tests/components/ota/common.yaml +++ b/tests/components/ota/common.yaml @@ -4,11 +4,8 @@ wifi: ota: - platform: esphome - safe_mode: true password: "superlongpasswordthatnoonewillknow" port: 3286 - reboot_timeout: 2min - num_attempts: 5 on_begin: then: - logger.log: "OTA start" diff --git a/tests/components/safe_mode/common.yaml b/tests/components/safe_mode/common.yaml index 1dfc516254..9c1d1ad3f9 100644 --- a/tests/components/safe_mode/common.yaml +++ b/tests/components/safe_mode/common.yaml @@ -2,9 +2,9 @@ wifi: ssid: MySSID password: password1 -ota: - - platform: esphome - safe_mode: true +safe_mode: + num_attempts: 3 + reboot_timeout: 2min button: - platform: safe_mode diff --git a/tests/test1.yaml b/tests/test1.yaml index dc46b55c44..2a20a1bb45 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -264,13 +264,14 @@ uart: parity: EVEN baud_rate: 9600 +safe_mode: + num_attempts: 3 + reboot_timeout: 2min + ota: - platform: esphome - safe_mode: true password: "superlongpasswordthatnoonewillknow" port: 3286 - reboot_timeout: 2min - num_attempts: 5 on_state_change: then: lambda: >- diff --git a/tests/test2.yaml b/tests/test2.yaml index 54ff4807a3..92977697c1 100644 --- a/tests/test2.yaml +++ b/tests/test2.yaml @@ -79,11 +79,11 @@ uart: sequence: - lambda: UARTDebug::log_hex(direction, bytes, ':'); +safe_mode: + ota: - platform: esphome - safe_mode: true port: 3286 - num_attempts: 15 logger: level: DEBUG diff --git a/tests/test3.yaml b/tests/test3.yaml index 7554d4bcb2..d10413b142 100644 --- a/tests/test3.yaml +++ b/tests/test3.yaml @@ -327,11 +327,13 @@ modbus: vbus: uart_id: uart_4 +safe_mode: + num_attempts: 5 + reboot_timeout: 10min + ota: - platform: esphome - safe_mode: true port: 3286 - reboot_timeout: 15min logger: hardware_uart: UART1 diff --git a/tests/test4.yaml b/tests/test4.yaml index 86beee81c6..c9e8a27317 100644 --- a/tests/test4.yaml +++ b/tests/test4.yaml @@ -102,9 +102,10 @@ uart: baud_rate: 1200 parity: EVEN +safe_mode: + ota: - platform: esphome - safe_mode: true port: 3286 logger: From 1ca7c2d7ddc44f8debe288a98fbca3e40796f5cf Mon Sep 17 00:00:00 2001 From: Jeroen van Oort Date: Wed, 22 May 2024 06:17:32 +0200 Subject: [PATCH 1493/2101] Add support for acting as Modbus server (#4874) Co-authored-by: Jeroen van Oort Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/modbus/__init__.py | 35 ++++++++++++ esphome/components/modbus/modbus.cpp | 27 ++++++--- esphome/components/modbus/modbus.h | 9 +++ .../components/modbus_controller/__init__.py | 52 +++++++++++++++-- .../modbus_controller/modbus_controller.cpp | 57 +++++++++++++++++-- .../modbus_controller/modbus_controller.h | 22 +++++++ .../modbus_controller/test.esp32.yaml | 22 ++++++- 7 files changed, 203 insertions(+), 21 deletions(-) diff --git a/esphome/components/modbus/__init__.py b/esphome/components/modbus/__init__.py index 6fea7033f2..ae0c818c28 100644 --- a/esphome/components/modbus/__init__.py +++ b/esphome/components/modbus/__init__.py @@ -1,5 +1,9 @@ +from __future__ import annotations +from typing import Literal + import esphome.codegen as cg import esphome.config_validation as cv +import esphome.final_validate as fv from esphome.cpp_helpers import gpio_pin_expression from esphome.components import uart from esphome.const import ( @@ -17,13 +21,21 @@ Modbus = modbus_ns.class_("Modbus", cg.Component, uart.UARTDevice) ModbusDevice = modbus_ns.class_("ModbusDevice") MULTI_CONF = True +CONF_ROLE = "role" CONF_MODBUS_ID = "modbus_id" CONF_SEND_WAIT_TIME = "send_wait_time" +ModbusRole = modbus_ns.enum("ModbusRole") +MODBUS_ROLES = { + "client": ModbusRole.CLIENT, + "server": ModbusRole.SERVER, +} + CONFIG_SCHEMA = ( cv.Schema( { cv.GenerateID(): cv.declare_id(Modbus), + cv.Optional(CONF_ROLE, default="client"): cv.enum(MODBUS_ROLES), cv.Optional(CONF_FLOW_CONTROL_PIN): pins.gpio_output_pin_schema, cv.Optional( CONF_SEND_WAIT_TIME, default="250ms" @@ -43,6 +55,7 @@ async def to_code(config): await uart.register_uart_device(var, config) + cg.add(var.set_role(config[CONF_ROLE])) if CONF_FLOW_CONTROL_PIN in config: pin = await gpio_pin_expression(config[CONF_FLOW_CONTROL_PIN]) cg.add(var.set_flow_control_pin(pin)) @@ -62,6 +75,28 @@ def modbus_device_schema(default_address): return cv.Schema(schema) +def final_validate_modbus_device( + name: str, *, role: Literal["server", "client"] | None = None +): + def validate_role(value): + assert role in MODBUS_ROLES + if value != role: + raise cv.Invalid(f"Component {name} requires role to be {role}") + return value + + def validate_hub(hub_config): + hub_schema = {} + if role is not None: + hub_schema[cv.Required(CONF_ROLE)] = validate_role + + return cv.Schema(hub_schema, extra=cv.ALLOW_EXTRA)(hub_config) + + return cv.Schema( + {cv.Required(CONF_MODBUS_ID): fv.id_declaration_match_schema(validate_hub)}, + extra=cv.ALLOW_EXTRA, + ) + + async def register_modbus_device(var, config): parent = await cg.get_variable(config[CONF_MODBUS_ID]) cg.add(var.set_parent(parent)) diff --git a/esphome/components/modbus/modbus.cpp b/esphome/components/modbus/modbus.cpp index 137fb0b26b..f8dd4c18b9 100644 --- a/esphome/components/modbus/modbus.cpp +++ b/esphome/components/modbus/modbus.cpp @@ -77,7 +77,13 @@ bool Modbus::parse_modbus_byte_(uint8_t byte) { ESP_LOGD(TAG, "Modbus user-defined function %02X found", function_code); } else { - // the response for write command mirrors the requests and data startes at offset 2 instead of 3 for read commands + // data starts at 2 and length is 4 for read registers commands + if (this->role == ModbusRole::SERVER && (function_code == 0x3 || function_code == 0x4)) { + data_offset = 2; + data_len = 4; + } + + // the response for write command mirrors the requests and data starts at offset 2 instead of 3 for read commands if (function_code == 0x5 || function_code == 0x06 || function_code == 0xF || function_code == 0x10) { data_offset = 2; data_len = 4; @@ -123,6 +129,9 @@ bool Modbus::parse_modbus_byte_(uint8_t byte) { // Ignore modbus exception not related to a pending command ESP_LOGD(TAG, "Ignoring Modbus error - not expecting a response"); } + } else if (this->role == ModbusRole::SERVER && (function_code == 0x3 || function_code == 0x4)) { + 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)); } else { device->on_modbus_data(data); } @@ -164,16 +173,18 @@ void Modbus::send(uint8_t address, uint8_t function_code, uint16_t start_address std::vector data; data.push_back(address); data.push_back(function_code); - data.push_back(start_address >> 8); - data.push_back(start_address >> 0); - if (function_code != 0x5 && function_code != 0x6) { - data.push_back(number_of_entities >> 8); - data.push_back(number_of_entities >> 0); + if (this->role == ModbusRole::CLIENT) { + data.push_back(start_address >> 8); + data.push_back(start_address >> 0); + if (function_code != 0x5 && function_code != 0x6) { + data.push_back(number_of_entities >> 8); + data.push_back(number_of_entities >> 0); + } } if (payload != nullptr) { - if (function_code == 0xF || function_code == 0x10) { // Write multiple - data.push_back(payload_len); // Byte count is required for write + if (this->role == ModbusRole::SERVER || function_code == 0xF || function_code == 0x10) { // Write multiple + data.push_back(payload_len); // Byte count is required for write } else { payload_len = 2; // Write single register or coil } diff --git a/esphome/components/modbus/modbus.h b/esphome/components/modbus/modbus.h index dd8732c6e9..4a78ed4aab 100644 --- a/esphome/components/modbus/modbus.h +++ b/esphome/components/modbus/modbus.h @@ -8,6 +8,11 @@ namespace esphome { namespace modbus { +enum ModbusRole { + CLIENT, + SERVER, +}; + class ModbusDevice; class Modbus : public uart::UARTDevice, public Component { @@ -27,11 +32,14 @@ class Modbus : public uart::UARTDevice, public Component { 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 &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; } + ModbusRole role; + protected: GPIOPin *flow_control_pin_{nullptr}; @@ -50,6 +58,7 @@ class ModbusDevice { void set_address(uint8_t address) { address_ = address; } virtual void on_modbus_data(const std::vector &data) = 0; virtual void on_modbus_error(uint8_t function_code, uint8_t exception_code) {} + virtual void on_modbus_read_registers(uint8_t function_code, uint16_t start_address, uint16_t number_of_registers){}; void send(uint8_t function, uint16_t start_address, uint16_t number_of_entities, uint8_t payload_len = 0, const uint8_t *payload = nullptr) { this->parent_->send(this->address_, function, start_address, number_of_entities, payload_len, payload); diff --git a/esphome/components/modbus_controller/__init__.py b/esphome/components/modbus_controller/__init__.py index 8703771c3a..b8ab48fcc6 100644 --- a/esphome/components/modbus_controller/__init__.py +++ b/esphome/components/modbus_controller/__init__.py @@ -23,6 +23,8 @@ CODEOWNERS = ["@martgras"] AUTO_LOAD = ["modbus"] +CONF_READ_LAMBDA = "read_lambda" +CONF_SERVER_REGISTERS = "server_registers" MULTI_CONF = True modbus_controller_ns = cg.esphome_ns.namespace("modbus_controller") @@ -31,6 +33,7 @@ ModbusController = modbus_controller_ns.class_( ) SensorItem = modbus_controller_ns.struct("SensorItem") +ServerRegister = modbus_controller_ns.struct("ServerRegister") ModbusFunctionCode_ns = modbus_controller_ns.namespace("ModbusFunctionCode") ModbusFunctionCode = ModbusFunctionCode_ns.enum("ModbusFunctionCode") @@ -94,10 +97,18 @@ TYPE_REGISTER_MAP = { "FP32_R": 2, } -MULTI_CONF = True - _LOGGER = logging.getLogger(__name__) +ModbusServerRegisterSchema = cv.Schema( + { + cv.GenerateID(): cv.declare_id(ServerRegister), + cv.Required(CONF_ADDRESS): cv.positive_int, + cv.Optional(CONF_VALUE_TYPE, default="U_WORD"): cv.enum(SENSOR_VALUE_TYPE), + cv.Required(CONF_READ_LAMBDA): cv.returning_lambda, + } +) + + CONFIG_SCHEMA = cv.All( cv.Schema( { @@ -106,6 +117,9 @@ CONFIG_SCHEMA = cv.All( CONF_COMMAND_THROTTLE, default="0ms" ): cv.positive_time_period_milliseconds, cv.Optional(CONF_OFFLINE_SKIP_UPDATES, default=0): cv.positive_int, + cv.Optional( + CONF_SERVER_REGISTERS, + ): cv.ensure_list(ModbusServerRegisterSchema), } ) .extend(cv.polling_component_schema("60s")) @@ -154,6 +168,17 @@ def validate_modbus_register(config): return config +def _final_validate(config): + if CONF_SERVER_REGISTERS in config: + return modbus.final_validate_modbus_device("modbus_controller", role="server")( + config + ) + return config + + +FINAL_VALIDATE_SCHEMA = _final_validate + + def modbus_calc_properties(config): byte_offset = 0 reg_count = 0 @@ -183,7 +208,7 @@ def modbus_calc_properties(config): async def add_modbus_base_properties( - var, config, sensor_type, lamdba_param_type=cg.float_, lamdba_return_type=float + var, config, sensor_type, lambda_param_type=cg.float_, lambda_return_type=float ): if CONF_CUSTOM_COMMAND in config: cg.add(var.set_custom_data(config[CONF_CUSTOM_COMMAND])) @@ -196,13 +221,13 @@ async def add_modbus_base_properties( config[CONF_LAMBDA], [ (sensor_type.operator("ptr"), "item"), - (lamdba_param_type, "x"), + (lambda_param_type, "x"), ( cg.std_vector.template(cg.uint8).operator("const").operator("ref"), "data", ), ], - return_type=cg.optional.template(lamdba_return_type), + return_type=cg.optional.template(lambda_return_type), ) cg.add(var.set_template(template_)) @@ -211,6 +236,23 @@ async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) cg.add(var.set_command_throttle(config[CONF_COMMAND_THROTTLE])) cg.add(var.set_offline_skip_updates(config[CONF_OFFLINE_SKIP_UPDATES])) + if CONF_SERVER_REGISTERS in config: + for server_register in config[CONF_SERVER_REGISTERS]: + cg.add( + var.add_server_register( + cg.new_Pvariable( + server_register[CONF_ID], + server_register[CONF_ADDRESS], + server_register[CONF_VALUE_TYPE], + TYPE_REGISTER_MAP[server_register[CONF_VALUE_TYPE]], + await cg.process_lambda( + server_register[CONF_READ_LAMBDA], + [], + return_type=cg.float_, + ), + ) + ) + ) await register_modbus_device(var, config) diff --git a/esphome/components/modbus_controller/modbus_controller.cpp b/esphome/components/modbus_controller/modbus_controller.cpp index 7565dc5e1b..9f73988b03 100644 --- a/esphome/components/modbus_controller/modbus_controller.cpp +++ b/esphome/components/modbus_controller/modbus_controller.cpp @@ -7,10 +7,7 @@ namespace modbus_controller { static const char *const TAG = "modbus_controller"; -void ModbusController::setup() { - // Modbus::setup(); - this->create_register_ranges_(); -} +void ModbusController::setup() { this->create_register_ranges_(); } /* To work with the existing modbus class and avoid polling for responses a command queue is used. @@ -102,6 +99,51 @@ void ModbusController::on_modbus_error(uint8_t function_code, uint8_t exception_ } } +void ModbusController::on_modbus_read_registers(uint8_t function_code, uint16_t start_address, + uint16_t number_of_registers) { + ESP_LOGD(TAG, + "Received read holding/input registers for device 0x%X. FC: 0x%X. Start address: 0x%X. Number of registers: " + "0x%X.", + this->address_, function_code, start_address, number_of_registers); + + std::vector sixteen_bit_response; + for (uint16_t current_address = start_address; current_address < start_address + number_of_registers;) { + bool found = false; + for (auto *server_register : this->server_registers_) { + if (server_register->address == current_address) { + float value = server_register->read_lambda(); + + ESP_LOGD(TAG, "Matched register. Address: 0x%02X. Value type: %zu. Register count: %u. Value: %0.1f.", + server_register->address, static_cast(server_register->value_type), + server_register->register_count, value); + number_to_payload(sixteen_bit_response, value, server_register->value_type); + current_address += server_register->register_count; + found = true; + break; + } + } + + if (!found) { + ESP_LOGW(TAG, "Could not match any register to address %02X. Sending exception response.", current_address); + std::vector error_response; + error_response.push_back(this->address_); + error_response.push_back(0x81); + error_response.push_back(0x02); + this->send_raw(error_response); + return; + } + } + + std::vector response; + for (auto v : sixteen_bit_response) { + auto decoded_value = decode_value(v); + response.push_back(decoded_value[0]); + response.push_back(decoded_value[1]); + } + + this->send(function_code, start_address, number_of_registers, response.size(), response.data()); +} + SensorSet ModbusController::find_sensors_(ModbusRegisterType register_type, uint16_t start_address) const { auto reg_it = find_if(begin(register_ranges_), end(register_ranges_), [=](RegisterRange const &r) { return (r.start_address == start_address && r.register_type == register_type); @@ -190,7 +232,7 @@ void ModbusController::update() { // walk through the sensors and determine the register ranges to read size_t ModbusController::create_register_ranges_() { register_ranges_.clear(); - if (sensorset_.empty()) { + if (this->parent_->role == modbus::ModbusRole::CLIENT && sensorset_.empty()) { ESP_LOGW(TAG, "No sensors registered"); return 0; } @@ -309,6 +351,11 @@ void ModbusController::dump_config() { ESP_LOGCONFIG(TAG, " Range type=%zu start=0x%X count=%d skip_updates=%d", static_cast(it.register_type), it.start_address, it.register_count, it.skip_updates); } + ESP_LOGCONFIG(TAG, "server registers"); + for (auto &r : server_registers_) { + ESP_LOGCONFIG(TAG, " Address=0x%02X value_type=%zu register_count=%u", r->address, + static_cast(r->value_type), r->register_count); + } #endif } diff --git a/esphome/components/modbus_controller/modbus_controller.h b/esphome/components/modbus_controller/modbus_controller.h index a389375523..9b7d59c93f 100644 --- a/esphome/components/modbus_controller/modbus_controller.h +++ b/esphome/components/modbus_controller/modbus_controller.h @@ -8,6 +8,7 @@ #include #include #include +#include #include namespace esphome { @@ -251,6 +252,21 @@ class SensorItem { bool force_new_range{false}; }; +class ServerRegister { + public: + ServerRegister(uint16_t address, SensorValueType value_type, uint8_t register_count, + std::function read_lambda) { + this->address = address; + this->value_type = value_type; + this->register_count = register_count; + this->read_lambda = std::move(read_lambda); + } + uint16_t address; + SensorValueType value_type; + uint8_t register_count; + std::function read_lambda; +}; + // ModbusController::create_register_ranges_ tries to optimize register range // for this the sensors must be ordered by register_type, start_address and bitmask class SensorItemsComparator { @@ -418,10 +434,14 @@ class ModbusController : public PollingComponent, public modbus::ModbusDevice { void queue_command(const ModbusCommandItem &command); /// Registers a sensor with the controller. Called by esphomes code generator void add_sensor_item(SensorItem *item) { sensorset_.insert(item); } + /// Registers a server register with the controller. Called by esphomes code generator + void add_server_register(ServerRegister *server_register) { server_registers_.push_back(server_register); } /// called when a modbus response was parsed without errors void on_modbus_data(const std::vector &data) override; /// called when a modbus error response was received void on_modbus_error(uint8_t function_code, uint8_t exception_code) override; + /// called when a modbus request (function code 3 or 4) was parsed without errors + void on_modbus_read_registers(uint8_t function_code, uint16_t start_address, uint16_t number_of_registers) final; /// default delegate called by process_modbus_data when a response has retrieved from the incoming queue void on_register_data(ModbusRegisterType register_type, uint16_t start_address, const std::vector &data); /// default delegate called by process_modbus_data when a response for a write response has retrieved from the @@ -452,6 +472,8 @@ class ModbusController : public PollingComponent, public modbus::ModbusDevice { void dump_sensors_(); /// Collection of all sensors for this component SensorSet sensorset_; + /// Collection of all server registers for this component + std::vector server_registers_; /// Continuous range of modbus registers std::vector register_ranges_; /// Hold the pending requests to be sent diff --git a/tests/components/modbus_controller/test.esp32.yaml b/tests/components/modbus_controller/test.esp32.yaml index c5fe3fd057..3e022b10ab 100644 --- a/tests/components/modbus_controller/test.esp32.yaml +++ b/tests/components/modbus_controller/test.esp32.yaml @@ -1,14 +1,30 @@ uart: - - id: uart_modbus + - id: uart_modbus_client tx_pin: 17 rx_pin: 16 baud_rate: 9600 + - id: uart_modbus_server + tx_pin: 1 + rx_pin: 3 + baud_rate: 9600 modbus: - id: mod_bus1 - flow_control_pin: 15 + - id: mod_bus1 + uart_id: uart_modbus_client + flow_control_pin: 15 + - id: mod_bus2 + uart_id: uart_modbus_server + role: server modbus_controller: - id: modbus_controller1 address: 0x2 modbus_id: mod_bus1 + - id: modbus_controller2 + address: 0x2 + modbus_id: mod_bus2 + server_registers: + - address: 0x0000 + value_type: S_DWORD_R + read_lambda: |- + return 42.3; From 9a6fde21ee2fa4049e8c12760b8a12cf49cf4c94 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Wed, 22 May 2024 14:43:13 -0500 Subject: [PATCH 1494/2101] Add on_safe_mode trigger (#6790) --- esphome/components/safe_mode/__init__.py | 14 ++++++++++++++ esphome/components/safe_mode/automation.h | 17 +++++++++++++++++ esphome/components/safe_mode/safe_mode.cpp | 2 ++ esphome/components/safe_mode/safe_mode.h | 5 +++++ tests/components/safe_mode/common.yaml | 2 ++ 5 files changed, 40 insertions(+) create mode 100644 esphome/components/safe_mode/automation.h diff --git a/esphome/components/safe_mode/__init__.py b/esphome/components/safe_mode/__init__.py index 7f227d7dd1..92b285e279 100644 --- a/esphome/components/safe_mode/__init__.py +++ b/esphome/components/safe_mode/__init__.py @@ -7,15 +7,20 @@ 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, coroutine_with_priority +from esphome import automation CODEOWNERS = ["@paulmonigatti", "@jsuanet", "@kbx81"] +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()) def _remove_id_if_disabled(value): @@ -34,6 +39,11 @@ 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), + } + ), } ).extend(cv.COMPONENT_SCHEMA), _remove_id_if_disabled, @@ -48,6 +58,10 @@ 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) + condition = var.should_enter_safe_mode( config[CONF_NUM_ATTEMPTS], config[CONF_REBOOT_TIMEOUT] ) diff --git a/esphome/components/safe_mode/automation.h b/esphome/components/safe_mode/automation.h new file mode 100644 index 0000000000..d1388449ee --- /dev/null +++ b/esphome/components/safe_mode/automation.h @@ -0,0 +1,17 @@ +#pragma once +#include "safe_mode.h" + +#include "esphome/core/automation.h" + +namespace esphome { +namespace safe_mode { + +class SafeModeTrigger : public Trigger<> { + public: + explicit SafeModeTrigger(SafeModeComponent *parent) { + parent->add_on_safe_mode_callback([this, parent]() { trigger(); }); + } +}; + +} // namespace safe_mode +} // namespace esphome diff --git a/esphome/components/safe_mode/safe_mode.cpp b/esphome/components/safe_mode/safe_mode.cpp index 06772ae1e0..6934dcb9d9 100644 --- a/esphome/components/safe_mode/safe_mode.cpp +++ b/esphome/components/safe_mode/safe_mode.cpp @@ -94,6 +94,8 @@ bool SafeModeComponent::should_enter_safe_mode(uint8_t num_attempts, uint32_t en ESP_LOGW(TAG, "SAFE MODE IS ACTIVE"); + this->safe_mode_callback_.call(); + return true; } else { // increment counter diff --git a/esphome/components/safe_mode/safe_mode.h b/esphome/components/safe_mode/safe_mode.h index 6c7450a6ff..0ec3c29529 100644 --- a/esphome/components/safe_mode/safe_mode.h +++ b/esphome/components/safe_mode/safe_mode.h @@ -25,6 +25,10 @@ class SafeModeComponent : public Component { void on_safe_shutdown() override; + void add_on_safe_mode_callback(std::function &&callback) { + this->safe_mode_callback_.add(std::move(callback)); + } + protected: void write_rtc_(uint32_t val); uint32_t read_rtc_(); @@ -35,6 +39,7 @@ class SafeModeComponent : public Component { uint32_t safe_mode_rtc_value_; uint8_t safe_mode_num_attempts_; ESPPreferenceObject rtc_; + CallbackManager safe_mode_callback_{}; static const uint32_t ENTER_SAFE_MODE_MAGIC = 0x5afe5afe; ///< a magic number to indicate that safe mode should be entered on next boot diff --git a/tests/components/safe_mode/common.yaml b/tests/components/safe_mode/common.yaml index 9c1d1ad3f9..ce8bf2f0cf 100644 --- a/tests/components/safe_mode/common.yaml +++ b/tests/components/safe_mode/common.yaml @@ -5,6 +5,8 @@ wifi: safe_mode: num_attempts: 3 reboot_timeout: 2min + on_safe_mode: + - logger.log: Time for safe mode button: - platform: safe_mode From 7f9383c83b1a4758b3950bf91333222d4ba40ca3 Mon Sep 17 00:00:00 2001 From: Penny Wood Date: Thu, 23 May 2024 05:31:56 +0800 Subject: [PATCH 1495/2101] [sx1509] Output open drain pin mode (#6788) --- esphome/components/sx1509/__init__.py | 4 ++ esphome/components/sx1509/sx1509.cpp | 56 ++++++++++++++----- .../components/sx1509/test.esp32-c3-idf.yaml | 18 ++++++ tests/components/sx1509/test.esp32-c3.yaml | 18 ++++++ tests/components/sx1509/test.esp32-idf.yaml | 18 ++++++ tests/components/sx1509/test.esp32.yaml | 18 ++++++ tests/components/sx1509/test.esp8266.yaml | 18 ++++++ tests/components/sx1509/test.rp2040.yaml | 18 ++++++ 8 files changed, 155 insertions(+), 13 deletions(-) diff --git a/esphome/components/sx1509/__init__.py b/esphome/components/sx1509/__init__.py index faef940125..e4f79dc2bc 100644 --- a/esphome/components/sx1509/__init__.py +++ b/esphome/components/sx1509/__init__.py @@ -11,6 +11,7 @@ from esphome.const import ( CONF_OUTPUT, CONF_PULLDOWN, CONF_PULLUP, + CONF_OPEN_DRAIN, ) CONF_KEYPAD = "keypad" @@ -79,6 +80,8 @@ def validate_mode(value): raise cv.Invalid("Pulldown only available with input") if value[CONF_PULLUP] and value[CONF_PULLDOWN]: raise cv.Invalid("Can only have one of pullup or pulldown") + if value[CONF_OPEN_DRAIN] and not value[CONF_OUTPUT]: + raise cv.Invalid("Open drain available only with output") return value @@ -94,6 +97,7 @@ SX1509_PIN_SCHEMA = cv.All( cv.Optional(CONF_PULLUP, default=False): cv.boolean, cv.Optional(CONF_PULLDOWN, default=False): cv.boolean, cv.Optional(CONF_OUTPUT, default=False): cv.boolean, + cv.Optional(CONF_OPEN_DRAIN, default=False): cv.boolean, }, validate_mode, ), diff --git a/esphome/components/sx1509/sx1509.cpp b/esphome/components/sx1509/sx1509.cpp index ee90e0e410..855a90bacd 100644 --- a/esphome/components/sx1509/sx1509.cpp +++ b/esphome/components/sx1509/sx1509.cpp @@ -86,33 +86,63 @@ void SX1509Component::digital_write(uint8_t pin, bool bit_value) { } void SX1509Component::pin_mode(uint8_t pin, gpio::Flags flags) { + ESP_LOGI(TAG, "Configuring pin %u with flags %x", pin, flags); + + uint16_t temp_word = 0; + this->read_byte_16(REG_DIR_B, &this->ddr_mask_); - if (flags == gpio::FLAG_OUTPUT) { + if (flags & gpio::FLAG_OUTPUT) { + // Always disable input buffer + this->read_byte_16(REG_INPUT_DISABLE_B, &temp_word); + temp_word |= (1 << pin); + this->write_byte_16(REG_INPUT_DISABLE_B, temp_word); + + if (flags & gpio::FLAG_OPEN_DRAIN) { + // Pullup must be disabled for open drain mode + this->read_byte_16(REG_PULL_UP_B, &temp_word); + temp_word &= ~(1 << pin); + this->write_byte_16(REG_PULL_UP_B, temp_word); + this->read_byte_16(REG_OPEN_DRAIN_B, &temp_word); + temp_word |= (1 << pin); + this->write_byte_16(REG_OPEN_DRAIN_B, temp_word); + ESP_LOGD(TAG, "Open drain output mode set for %u", pin); + } else { + ESP_LOGD(TAG, "Output Mode for %u", pin); + } + + // Set direction to output this->ddr_mask_ &= ~(1 << pin); + this->write_byte_16(REG_DIR_B, this->ddr_mask_); } else { - this->ddr_mask_ |= (1 << pin); + ESP_LOGD(TAG, "Input Mode for %u", pin); - uint16_t temp_pullup; - this->read_byte_16(REG_PULL_UP_B, &temp_pullup); - uint16_t temp_pulldown; - this->read_byte_16(REG_PULL_DOWN_B, &temp_pulldown); + // Always enable input buffer + this->read_byte_16(REG_INPUT_DISABLE_B, &temp_word); + temp_word &= ~(1 << pin); + this->write_byte_16(REG_INPUT_DISABLE_B, temp_word); + // Pullup + this->read_byte_16(REG_PULL_UP_B, &temp_word); if (flags & gpio::FLAG_PULLUP) { - temp_pullup |= (1 << pin); + temp_word |= (1 << pin); } else { - temp_pullup &= ~(1 << pin); + temp_word &= ~(1 << pin); } + this->write_byte_16(REG_PULL_UP_B, temp_word); + // Pulldown + this->read_byte_16(REG_PULL_DOWN_B, &temp_word); if (flags & gpio::FLAG_PULLDOWN) { - temp_pulldown |= (1 << pin); + temp_word |= (1 << pin); } else { - temp_pulldown &= ~(1 << pin); + temp_word &= ~(1 << pin); } + this->write_byte_16(REG_PULL_DOWN_B, temp_word); - this->write_byte_16(REG_PULL_UP_B, temp_pullup); - this->write_byte_16(REG_PULL_DOWN_B, temp_pulldown); + // Set direction to input + this->ddr_mask_ |= (1 << pin); + this->write_byte_16(REG_DIR_B, this->ddr_mask_); } - this->write_byte_16(REG_DIR_B, this->ddr_mask_); } void SX1509Component::setup_led_driver(uint8_t pin) { diff --git a/tests/components/sx1509/test.esp32-c3-idf.yaml b/tests/components/sx1509/test.esp32-c3-idf.yaml index ced849b3df..0397812880 100644 --- a/tests/components/sx1509/test.esp32-c3-idf.yaml +++ b/tests/components/sx1509/test.esp32-c3-idf.yaml @@ -13,3 +13,21 @@ binary_sensor: pin: sx1509: sx1509_hub number: 3 + +switch: + - platform: gpio + name: GPIO SX1509 Test Out Open Drain + pin: + sx1509: sx1509_hub + number: 0 + mode: + output: true + open_drain: true + + - platform: gpio + name: GPIO SX1509 Test Out Standard + pin: + sx1509: sx1509_hub + number: 1 + mode: + output: true diff --git a/tests/components/sx1509/test.esp32-c3.yaml b/tests/components/sx1509/test.esp32-c3.yaml index ced849b3df..0397812880 100644 --- a/tests/components/sx1509/test.esp32-c3.yaml +++ b/tests/components/sx1509/test.esp32-c3.yaml @@ -13,3 +13,21 @@ binary_sensor: pin: sx1509: sx1509_hub number: 3 + +switch: + - platform: gpio + name: GPIO SX1509 Test Out Open Drain + pin: + sx1509: sx1509_hub + number: 0 + mode: + output: true + open_drain: true + + - platform: gpio + name: GPIO SX1509 Test Out Standard + pin: + sx1509: sx1509_hub + number: 1 + mode: + output: true diff --git a/tests/components/sx1509/test.esp32-idf.yaml b/tests/components/sx1509/test.esp32-idf.yaml index 1698f2abc4..aa1d161a43 100644 --- a/tests/components/sx1509/test.esp32-idf.yaml +++ b/tests/components/sx1509/test.esp32-idf.yaml @@ -13,3 +13,21 @@ binary_sensor: pin: sx1509: sx1509_hub number: 3 + +switch: + - platform: gpio + name: GPIO SX1509 Test Out Open Drain + pin: + sx1509: sx1509_hub + number: 0 + mode: + output: true + open_drain: true + + - platform: gpio + name: GPIO SX1509 Test Out Standard + pin: + sx1509: sx1509_hub + number: 1 + mode: + output: true diff --git a/tests/components/sx1509/test.esp32.yaml b/tests/components/sx1509/test.esp32.yaml index 1698f2abc4..aa1d161a43 100644 --- a/tests/components/sx1509/test.esp32.yaml +++ b/tests/components/sx1509/test.esp32.yaml @@ -13,3 +13,21 @@ binary_sensor: pin: sx1509: sx1509_hub number: 3 + +switch: + - platform: gpio + name: GPIO SX1509 Test Out Open Drain + pin: + sx1509: sx1509_hub + number: 0 + mode: + output: true + open_drain: true + + - platform: gpio + name: GPIO SX1509 Test Out Standard + pin: + sx1509: sx1509_hub + number: 1 + mode: + output: true diff --git a/tests/components/sx1509/test.esp8266.yaml b/tests/components/sx1509/test.esp8266.yaml index ced849b3df..0397812880 100644 --- a/tests/components/sx1509/test.esp8266.yaml +++ b/tests/components/sx1509/test.esp8266.yaml @@ -13,3 +13,21 @@ binary_sensor: pin: sx1509: sx1509_hub number: 3 + +switch: + - platform: gpio + name: GPIO SX1509 Test Out Open Drain + pin: + sx1509: sx1509_hub + number: 0 + mode: + output: true + open_drain: true + + - platform: gpio + name: GPIO SX1509 Test Out Standard + pin: + sx1509: sx1509_hub + number: 1 + mode: + output: true diff --git a/tests/components/sx1509/test.rp2040.yaml b/tests/components/sx1509/test.rp2040.yaml index ced849b3df..0397812880 100644 --- a/tests/components/sx1509/test.rp2040.yaml +++ b/tests/components/sx1509/test.rp2040.yaml @@ -13,3 +13,21 @@ binary_sensor: pin: sx1509: sx1509_hub number: 3 + +switch: + - platform: gpio + name: GPIO SX1509 Test Out Open Drain + pin: + sx1509: sx1509_hub + number: 0 + mode: + output: true + open_drain: true + + - platform: gpio + name: GPIO SX1509 Test Out Standard + pin: + sx1509: sx1509_hub + number: 1 + mode: + output: true From 4ab7a5d964c5a2d956e873292ef061d21d8ddf66 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 23 May 2024 17:04:33 +1200 Subject: [PATCH 1496/2101] [ledc] Change some logging lines from debug to verbose (#6796) --- esphome/components/ledc/ledc_output.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/ledc/ledc_output.cpp b/esphome/components/ledc/ledc_output.cpp index 0533143d37..1040ac25b6 100644 --- a/esphome/components/ledc/ledc_output.cpp +++ b/esphome/components/ledc/ledc_output.cpp @@ -52,12 +52,12 @@ float ledc_min_frequency_for_bit_depth(uint8_t bit_depth, bool low_frequency) { } optional ledc_bit_depth_for_frequency(float frequency) { - ESP_LOGD(TAG, "Calculating resolution bit-depth for frequency %f", frequency); + ESP_LOGV(TAG, "Calculating resolution bit-depth for frequency %f", frequency); for (int i = MAX_RES_BITS; i >= 1; i--) { const float min_frequency = ledc_min_frequency_for_bit_depth(i, (frequency < 100)); const float max_frequency = ledc_max_frequency_for_bit_depth(i); if (min_frequency <= frequency && frequency <= max_frequency) { - ESP_LOGD(TAG, "Resolution calculated as %d", i); + ESP_LOGV(TAG, "Resolution calculated as %d", i); return i; } } From aed0593793d8595d3e32737ffe77805dd02e1f95 Mon Sep 17 00:00:00 2001 From: Pavlo Dudnytskyi Date: Thu, 23 May 2024 23:07:39 +0200 Subject: [PATCH 1497/2101] [haier] ``text_sensor`` and ``button`` platforms (#6780) --- CODEOWNERS | 4 + esphome/components/haier/automation.h | 4 +- .../haier/binary_sensor/__init__.py | 1 + esphome/components/haier/button/__init__.py | 41 ++++++ .../components/haier/button/self_cleaning.cpp | 9 ++ .../components/haier/button/self_cleaning.h | 18 +++ .../haier/button/steri_cleaning.cpp | 9 ++ .../components/haier/button/steri_cleaning.h | 18 +++ esphome/components/haier/climate.py | 7 +- esphome/components/haier/haier_base.cpp | 3 +- esphome/components/haier/haier_base.h | 3 +- esphome/components/haier/hon_climate.cpp | 130 +++++++++++------- esphome/components/haier/hon_climate.h | 59 ++++---- esphome/components/haier/hon_packet.h | 5 +- esphome/components/haier/sensor/__init__.py | 1 + .../components/haier/text_sensor/__init__.py | 54 ++++++++ platformio.ini | 2 +- tests/components/haier/test.esp32-c3-idf.yaml | 18 +++ tests/components/haier/test.esp32-c3.yaml | 18 +++ tests/components/haier/test.esp32-idf.yaml | 18 +++ tests/components/haier/test.esp32.yaml | 18 +++ tests/components/haier/test.esp8266.yaml | 18 +++ tests/components/haier/test.rp2040.yaml | 18 +++ 23 files changed, 396 insertions(+), 80 deletions(-) create mode 100644 esphome/components/haier/button/__init__.py create mode 100644 esphome/components/haier/button/self_cleaning.cpp create mode 100644 esphome/components/haier/button/self_cleaning.h create mode 100644 esphome/components/haier/button/steri_cleaning.cpp create mode 100644 esphome/components/haier/button/steri_cleaning.h create mode 100644 esphome/components/haier/text_sensor/__init__.py diff --git a/CODEOWNERS b/CODEOWNERS index 22e581275b..e099ca42ac 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -152,6 +152,10 @@ esphome/components/grove_tb6612fng/* @max246 esphome/components/growatt_solar/* @leeuwte esphome/components/gt911/* @clydebarrow @jesserockz esphome/components/haier/* @paveldn +esphome/components/haier/binary_sensor/* @paveldn +esphome/components/haier/button/* @paveldn +esphome/components/haier/sensor/* @paveldn +esphome/components/haier/text_sensor/* @paveldn esphome/components/havells_solar/* @sourabhjaiswal esphome/components/hbridge/fan/* @WeekendWarrior esphome/components/hbridge/light/* @DotNetDann diff --git a/esphome/components/haier/automation.h b/esphome/components/haier/automation.h index 84e4554db8..55df7ecc1d 100644 --- a/esphome/components/haier/automation.h +++ b/esphome/components/haier/automation.h @@ -46,7 +46,7 @@ template class BeeperOffAction : public Action { template class VerticalAirflowAction : public Action { public: VerticalAirflowAction(HonClimate *parent) : parent_(parent) {} - TEMPLATABLE_VALUE(AirflowVerticalDirection, direction) + TEMPLATABLE_VALUE(hon_protocol::VerticalSwingMode, direction) void play(Ts... x) { this->parent_->set_vertical_airflow(this->direction_.value(x...)); } protected: @@ -56,7 +56,7 @@ template class VerticalAirflowAction : public Action { template class HorizontalAirflowAction : public Action { public: HorizontalAirflowAction(HonClimate *parent) : parent_(parent) {} - TEMPLATABLE_VALUE(AirflowHorizontalDirection, direction) + TEMPLATABLE_VALUE(hon_protocol::HorizontalSwingMode, direction) void play(Ts... x) { this->parent_->set_horizontal_airflow(this->direction_.value(x...)); } protected: diff --git a/esphome/components/haier/binary_sensor/__init__.py b/esphome/components/haier/binary_sensor/__init__.py index 4f72560a7b..8e9d5ec578 100644 --- a/esphome/components/haier/binary_sensor/__init__.py +++ b/esphome/components/haier/binary_sensor/__init__.py @@ -11,6 +11,7 @@ from ..climate import ( HonClimate, ) +CODEOWNERS = ["@paveldn"] BinarySensorTypeEnum = HonClimate.enum("SubBinarySensorType", True) # Haier sensors diff --git a/esphome/components/haier/button/__init__.py b/esphome/components/haier/button/__init__.py new file mode 100644 index 0000000000..efe6180aaf --- /dev/null +++ b/esphome/components/haier/button/__init__.py @@ -0,0 +1,41 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import button +from ..climate import ( + CONF_HAIER_ID, + HonClimate, + haier_ns, +) + +CODEOWNERS = ["@paveldn"] +SelfCleaningButton = haier_ns.class_("SelfCleaningButton", button.Button) +SteriCleaningButton = haier_ns.class_("SteriCleaningButton", button.Button) + + +# Haier buttons +CONF_SELF_CLEANING = "self_cleaning" +CONF_STERI_CLEANING = "steri_cleaning" + +# Additional icons +ICON_SPRAY_BOTTLE = "mdi:spray-bottle" + +CONFIG_SCHEMA = cv.Schema( + { + cv.Required(CONF_HAIER_ID): cv.use_id(HonClimate), + cv.Optional(CONF_SELF_CLEANING): button.button_schema( + SelfCleaningButton, + icon=ICON_SPRAY_BOTTLE, + ), + cv.Optional(CONF_STERI_CLEANING): button.button_schema( + SteriCleaningButton, + icon=ICON_SPRAY_BOTTLE, + ), + } +) + + +async def to_code(config): + for button_type in [CONF_SELF_CLEANING, CONF_STERI_CLEANING]: + if conf := config.get(button_type): + btn = await button.new_button(conf) + await cg.register_parented(btn, config[CONF_HAIER_ID]) diff --git a/esphome/components/haier/button/self_cleaning.cpp b/esphome/components/haier/button/self_cleaning.cpp new file mode 100644 index 0000000000..128726036e --- /dev/null +++ b/esphome/components/haier/button/self_cleaning.cpp @@ -0,0 +1,9 @@ +#include "self_cleaning.h" + +namespace esphome { +namespace haier { + +void SelfCleaningButton::press_action() { this->parent_->start_self_cleaning(); } + +} // namespace haier +} // namespace esphome diff --git a/esphome/components/haier/button/self_cleaning.h b/esphome/components/haier/button/self_cleaning.h new file mode 100644 index 0000000000..308fb70f06 --- /dev/null +++ b/esphome/components/haier/button/self_cleaning.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/button/button.h" +#include "../hon_climate.h" + +namespace esphome { +namespace haier { + +class SelfCleaningButton : public button::Button, public Parented { + public: + SelfCleaningButton() = default; + + protected: + void press_action() override; +}; + +} // namespace haier +} // namespace esphome diff --git a/esphome/components/haier/button/steri_cleaning.cpp b/esphome/components/haier/button/steri_cleaning.cpp new file mode 100644 index 0000000000..02b723f1a4 --- /dev/null +++ b/esphome/components/haier/button/steri_cleaning.cpp @@ -0,0 +1,9 @@ +#include "steri_cleaning.h" + +namespace esphome { +namespace haier { + +void SteriCleaningButton::press_action() { this->parent_->start_steri_cleaning(); } + +} // namespace haier +} // namespace esphome diff --git a/esphome/components/haier/button/steri_cleaning.h b/esphome/components/haier/button/steri_cleaning.h new file mode 100644 index 0000000000..6cad313fb3 --- /dev/null +++ b/esphome/components/haier/button/steri_cleaning.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/button/button.h" +#include "../hon_climate.h" + +namespace esphome { +namespace haier { + +class SteriCleaningButton : public button::Button, public Parented { + public: + SteriCleaningButton() = default; + + protected: + void press_action() override; +}; + +} // namespace haier +} // namespace esphome diff --git a/esphome/components/haier/climate.py b/esphome/components/haier/climate.py index b16244fd90..1562708a4f 100644 --- a/esphome/components/haier/climate.py +++ b/esphome/components/haier/climate.py @@ -55,6 +55,7 @@ PROTOCOL_HON = "HON" PROTOCOL_SMARTAIR2 = "SMARTAIR2" haier_ns = cg.esphome_ns.namespace("haier") +hon_protocol_ns = haier_ns.namespace("hon_protocol") HaierClimateBase = haier_ns.class_( "HaierClimateBase", uart.UARTDevice, climate.Climate, cg.Component ) @@ -63,7 +64,7 @@ Smartair2Climate = haier_ns.class_("Smartair2Climate", HaierClimateBase) CONF_HAIER_ID = "haier_id" -AirflowVerticalDirection = haier_ns.enum("AirflowVerticalDirection", True) +AirflowVerticalDirection = hon_protocol_ns.enum("VerticalSwingMode", True) AIRFLOW_VERTICAL_DIRECTION_OPTIONS = { "HEALTH_UP": AirflowVerticalDirection.HEALTH_UP, "MAX_UP": AirflowVerticalDirection.MAX_UP, @@ -73,7 +74,7 @@ AIRFLOW_VERTICAL_DIRECTION_OPTIONS = { "HEALTH_DOWN": AirflowVerticalDirection.HEALTH_DOWN, } -AirflowHorizontalDirection = haier_ns.enum("AirflowHorizontalDirection", True) +AirflowHorizontalDirection = hon_protocol_ns.enum("HorizontalSwingMode", True) AIRFLOW_HORIZONTAL_DIRECTION_OPTIONS = { "MAX_LEFT": AirflowHorizontalDirection.MAX_LEFT, "LEFT": AirflowHorizontalDirection.LEFT, @@ -483,4 +484,4 @@ async def to_code(config): trigger, [(cg.uint8, "code"), (cg.const_char_ptr, "message")], conf ) # https://github.com/paveldn/HaierProtocol - cg.add_library("pavlodn/HaierProtocol", "0.9.25") + cg.add_library("pavlodn/HaierProtocol", "0.9.28") diff --git a/esphome/components/haier/haier_base.cpp b/esphome/components/haier/haier_base.cpp index a3f68bb081..1fca3dfb85 100644 --- a/esphome/components/haier/haier_base.cpp +++ b/esphome/components/haier/haier_base.cpp @@ -234,6 +234,7 @@ void HaierClimateBase::setup() { this->haier_protocol_.set_default_timeout_handler( std::bind(&esphome::haier::HaierClimateBase::timeout_default_handler_, this, std::placeholders::_1)); this->set_handlers(); + this->initialization(); } void HaierClimateBase::dump_config() { @@ -326,7 +327,7 @@ ClimateTraits HaierClimateBase::traits() { return traits_; } void HaierClimateBase::control(const ClimateCall &call) { ESP_LOGD("Control", "Control call"); - if (this->protocol_phase_ < ProtocolPhases::IDLE) { + if (!this->valid_connection()) { ESP_LOGW(TAG, "Can't send control packet, first poll answer not received"); return; // cancel the control, we cant do it without a poll answer. } diff --git a/esphome/components/haier/haier_base.h b/esphome/components/haier/haier_base.h index 504c841e5f..f261a106a2 100644 --- a/esphome/components/haier/haier_base.h +++ b/esphome/components/haier/haier_base.h @@ -44,7 +44,7 @@ class HaierClimateBase : public esphome::Component, void set_supported_modes(const std::set &modes); void set_supported_swing_modes(const std::set &modes); void set_supported_presets(const std::set &presets); - bool valid_connection() { return this->protocol_phase_ >= ProtocolPhases::IDLE; }; + bool valid_connection() const { return this->protocol_phase_ >= ProtocolPhases::IDLE; }; size_t available() noexcept override { return esphome::uart::UARTDevice::available(); }; size_t read_array(uint8_t *data, size_t len) noexcept override { return esphome::uart::UARTDevice::read_array(data, len) ? len : 0; @@ -80,6 +80,7 @@ class HaierClimateBase : public esphome::Component, virtual void process_phase(std::chrono::steady_clock::time_point now) = 0; virtual haier_protocol::HaierMessage get_control_message() = 0; virtual haier_protocol::HaierMessage get_power_message(bool state) = 0; + virtual void initialization(){}; virtual bool prepare_pending_action(); virtual void process_protocol_reset(); esphome::climate::ClimateTraits traits() override; diff --git a/esphome/components/haier/hon_climate.cpp b/esphome/components/haier/hon_climate.cpp index 9933cb4c8f..903f7964da 100644 --- a/esphome/components/haier/hon_climate.cpp +++ b/esphome/components/haier/hon_climate.cpp @@ -19,38 +19,6 @@ constexpr uint8_t CONTROL_MESSAGE_RETRIES = 5; constexpr std::chrono::milliseconds CONTROL_MESSAGE_RETRIES_INTERVAL = std::chrono::milliseconds(500); constexpr size_t ALARM_STATUS_REQUEST_INTERVAL_MS = 600000; -hon_protocol::VerticalSwingMode get_vertical_swing_mode(AirflowVerticalDirection direction) { - switch (direction) { - case AirflowVerticalDirection::HEALTH_UP: - return hon_protocol::VerticalSwingMode::HEALTH_UP; - case AirflowVerticalDirection::MAX_UP: - return hon_protocol::VerticalSwingMode::MAX_UP; - case AirflowVerticalDirection::UP: - return hon_protocol::VerticalSwingMode::UP; - case AirflowVerticalDirection::DOWN: - return hon_protocol::VerticalSwingMode::DOWN; - case AirflowVerticalDirection::HEALTH_DOWN: - return hon_protocol::VerticalSwingMode::HEALTH_DOWN; - default: - return hon_protocol::VerticalSwingMode::CENTER; - } -} - -hon_protocol::HorizontalSwingMode get_horizontal_swing_mode(AirflowHorizontalDirection direction) { - switch (direction) { - case AirflowHorizontalDirection::MAX_LEFT: - return hon_protocol::HorizontalSwingMode::MAX_LEFT; - case AirflowHorizontalDirection::LEFT: - return hon_protocol::HorizontalSwingMode::LEFT; - case AirflowHorizontalDirection::RIGHT: - return hon_protocol::HorizontalSwingMode::RIGHT; - case AirflowHorizontalDirection::MAX_RIGHT: - return hon_protocol::HorizontalSwingMode::MAX_RIGHT; - default: - return hon_protocol::HorizontalSwingMode::CENTER; - } -} - HonClimate::HonClimate() : cleaning_status_(CleaningState::NO_CLEANING), got_valid_outdoor_temp_(false), active_alarms_{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -66,17 +34,21 @@ void HonClimate::set_beeper_state(bool state) { this->beeper_status_ = state; } bool HonClimate::get_beeper_state() const { return this->beeper_status_; } -AirflowVerticalDirection HonClimate::get_vertical_airflow() const { return this->vertical_direction_; }; +esphome::optional HonClimate::get_vertical_airflow() const { + return this->current_vertical_swing_; +}; -void HonClimate::set_vertical_airflow(AirflowVerticalDirection direction) { - this->vertical_direction_ = direction; +void HonClimate::set_vertical_airflow(hon_protocol::VerticalSwingMode direction) { + this->pending_vertical_direction_ = direction; this->force_send_control_ = true; } -AirflowHorizontalDirection HonClimate::get_horizontal_airflow() const { return this->horizontal_direction_; } +esphome::optional HonClimate::get_horizontal_airflow() const { + return this->current_horizontal_swing_; +} -void HonClimate::set_horizontal_airflow(AirflowHorizontalDirection direction) { - this->horizontal_direction_ = direction; +void HonClimate::set_horizontal_airflow(hon_protocol::HorizontalSwingMode direction) { + this->pending_horizontal_direction_ = direction; this->force_send_control_ = true; } @@ -148,6 +120,11 @@ haier_protocol::HandlerError HonClimate::get_device_version_answer_handler_(haie this->hvac_hardware_info_.value().hardware_version_ = std::string(tmp); strncpy(tmp, answr->device_name, 8); this->hvac_hardware_info_.value().device_name_ = std::string(tmp); +#ifdef USE_TEXT_SENSOR + this->update_sub_text_sensor_(SubTextSensorType::APPLIANCE_NAME, this->hvac_hardware_info_.value().device_name_); + this->update_sub_text_sensor_(SubTextSensorType::PROTOCOL_VERSION, + this->hvac_hardware_info_.value().protocol_version_); +#endif this->hvac_hardware_info_.value().functions_[0] = (answr->functions[1] & 0x01) != 0; // interactive mode support this->hvac_hardware_info_.value().functions_[1] = (answr->functions[1] & 0x02) != 0; // controller-device mode support @@ -488,6 +465,19 @@ haier_protocol::HaierMessage HonClimate::get_power_message(bool state) { } } +void HonClimate::initialization() { + constexpr uint32_t restore_settings_version = 0xE834D8DCUL; + this->rtc_ = global_preferences->make_preference(this->get_object_id_hash() ^ restore_settings_version); + HonSettings recovered; + if (this->rtc_.load(&recovered)) { + this->settings_ = recovered; + } else { + this->settings_ = {hon_protocol::VerticalSwingMode::CENTER, hon_protocol::HorizontalSwingMode::CENTER}; + } + this->current_vertical_swing_ = this->settings_.last_vertiacal_swing; + this->current_horizontal_swing_ = this->settings_.last_horizontal_swing; +} + haier_protocol::HaierMessage HonClimate::get_control_message() { uint8_t control_out_buffer[sizeof(hon_protocol::HaierPacketControl)]; memcpy(control_out_buffer, this->last_status_message_.get(), sizeof(hon_protocol::HaierPacketControl)); @@ -560,16 +550,16 @@ haier_protocol::HaierMessage HonClimate::get_control_message() { if (climate_control.swing_mode.has_value()) { switch (climate_control.swing_mode.value()) { case CLIMATE_SWING_OFF: - out_data->horizontal_swing_mode = (uint8_t) get_horizontal_swing_mode(this->horizontal_direction_); - out_data->vertical_swing_mode = (uint8_t) get_vertical_swing_mode(this->vertical_direction_); + out_data->horizontal_swing_mode = (uint8_t) this->settings_.last_horizontal_swing; + out_data->vertical_swing_mode = (uint8_t) this->settings_.last_vertiacal_swing; break; case CLIMATE_SWING_VERTICAL: - out_data->horizontal_swing_mode = (uint8_t) get_horizontal_swing_mode(this->horizontal_direction_); + out_data->horizontal_swing_mode = (uint8_t) this->settings_.last_horizontal_swing; out_data->vertical_swing_mode = (uint8_t) hon_protocol::VerticalSwingMode::AUTO; break; case CLIMATE_SWING_HORIZONTAL: out_data->horizontal_swing_mode = (uint8_t) hon_protocol::HorizontalSwingMode::AUTO; - out_data->vertical_swing_mode = (uint8_t) get_vertical_swing_mode(this->vertical_direction_); + out_data->vertical_swing_mode = (uint8_t) this->settings_.last_vertiacal_swing; break; case CLIMATE_SWING_BOTH: out_data->horizontal_swing_mode = (uint8_t) hon_protocol::HorizontalSwingMode::AUTO; @@ -631,11 +621,14 @@ haier_protocol::HaierMessage HonClimate::get_control_message() { break; } } - } else { - if (out_data->vertical_swing_mode != (uint8_t) hon_protocol::VerticalSwingMode::AUTO) - out_data->vertical_swing_mode = (uint8_t) get_vertical_swing_mode(this->vertical_direction_); - if (out_data->horizontal_swing_mode != (uint8_t) hon_protocol::HorizontalSwingMode::AUTO) - out_data->horizontal_swing_mode = (uint8_t) get_horizontal_swing_mode(this->horizontal_direction_); + } + if (this->pending_vertical_direction_.has_value()) { + out_data->vertical_swing_mode = (uint8_t) this->pending_vertical_direction_.value(); + this->pending_vertical_direction_.reset(); + } + if (this->pending_horizontal_direction_.has_value()) { + out_data->horizontal_swing_mode = (uint8_t) this->pending_horizontal_direction_.value(); + this->pending_horizontal_direction_.reset(); } out_data->beeper_status = ((!this->beeper_status_) || (!has_hvac_settings)) ? 1 : 0; control_out_buffer[4] = 0; // This byte should be cleared before setting values @@ -737,6 +730,33 @@ void HonClimate::update_sub_binary_sensor_(SubBinarySensorType type, uint8_t val } #endif // USE_BINARY_SENSOR +#ifdef USE_TEXT_SENSOR +void HonClimate::set_sub_text_sensor(SubTextSensorType type, text_sensor::TextSensor *sens) { + this->sub_text_sensors_[(size_t) type] = sens; + switch (type) { + case SubTextSensorType::APPLIANCE_NAME: + if (this->hvac_hardware_info_.has_value()) + sens->publish_state(this->hvac_hardware_info_.value().device_name_); + break; + case SubTextSensorType::PROTOCOL_VERSION: + if (this->hvac_hardware_info_.has_value()) + sens->publish_state(this->hvac_hardware_info_.value().protocol_version_); + break; + case SubTextSensorType::CLEANING_STATUS: + sens->publish_state(this->get_cleaning_status_text()); + break; + default: + break; + } +} + +void HonClimate::update_sub_text_sensor_(SubTextSensorType type, const std::string &value) { + size_t index = (size_t) type; + if (this->sub_text_sensors_[index] != nullptr) + this->sub_text_sensors_[index]->publish_state(value); +} +#endif // USE_TEXT_SENSOR + haier_protocol::HandlerError HonClimate::process_status_message_(const uint8_t *packet_buffer, uint8_t size) { size_t expected_size = 2 + sizeof(hon_protocol::HaierPacketControl) + sizeof(hon_protocol::HaierPacketSensors) + this->extra_control_packet_bytes_; @@ -896,6 +916,9 @@ haier_protocol::HandlerError HonClimate::process_status_message_(const uint8_t * PendingAction({ActionRequest::TURN_POWER_OFF, esphome::optional()}); } this->cleaning_status_ = new_cleaning; +#ifdef USE_TEXT_SENSOR + this->update_sub_text_sensor_(SubTextSensorType::CLEANING_STATUS, this->get_cleaning_status_text()); +#endif // USE_TEXT_SENSOR } } { @@ -941,6 +964,19 @@ haier_protocol::HandlerError HonClimate::process_status_message_(const uint8_t * this->swing_mode = CLIMATE_SWING_OFF; } } + // Saving last known non auto mode for vertical and horizontal swing + this->current_vertical_swing_ = (hon_protocol::VerticalSwingMode) packet.control.vertical_swing_mode; + this->current_horizontal_swing_ = (hon_protocol::HorizontalSwingMode) packet.control.horizontal_swing_mode; + bool save_settings = ((this->current_vertical_swing_.value() != hon_protocol::VerticalSwingMode::AUTO) && + (this->current_vertical_swing_.value() != hon_protocol::VerticalSwingMode::AUTO_SPECIAL) && + (this->current_vertical_swing_.value() != this->settings_.last_vertiacal_swing)) || + ((this->current_horizontal_swing_.value() != hon_protocol::HorizontalSwingMode::AUTO) && + (this->current_horizontal_swing_.value() != this->settings_.last_horizontal_swing)); + if (save_settings) { + this->settings_.last_vertiacal_swing = this->current_vertical_swing_.value(); + this->settings_.last_horizontal_swing = this->current_horizontal_swing_.value(); + this->rtc_.save(&this->settings_); + } should_publish = should_publish || (old_swing_mode != this->swing_mode); } this->last_valid_status_timestamp_ = std::chrono::steady_clock::now(); diff --git a/esphome/components/haier/hon_climate.h b/esphome/components/haier/hon_climate.h index c4fae20a98..7b4fcee6b9 100644 --- a/esphome/components/haier/hon_climate.h +++ b/esphome/components/haier/hon_climate.h @@ -7,29 +7,16 @@ #ifdef USE_BINARY_SENSOR #include "esphome/components/binary_sensor/binary_sensor.h" #endif +#ifdef USE_TEXT_SENSOR +#include "esphome/components/text_sensor/text_sensor.h" +#endif #include "esphome/core/automation.h" #include "haier_base.h" +#include "hon_packet.h" namespace esphome { namespace haier { -enum class AirflowVerticalDirection : uint8_t { - HEALTH_UP = 0, - MAX_UP = 1, - UP = 2, - CENTER = 3, - DOWN = 4, - HEALTH_DOWN = 5, -}; - -enum class AirflowHorizontalDirection : uint8_t { - MAX_LEFT = 0, - LEFT = 1, - CENTER = 2, - RIGHT = 3, - MAX_RIGHT = 4, -}; - enum class CleaningState : uint8_t { NO_CLEANING = 0, SELF_CLEAN = 1, @@ -38,6 +25,11 @@ 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; +}; + class HonClimate : public HaierClimateBase { #ifdef USE_SENSOR public: @@ -80,6 +72,20 @@ class HonClimate : public HaierClimateBase { protected: void update_sub_binary_sensor_(SubBinarySensorType type, uint8_t value); binary_sensor::BinarySensor *sub_binary_sensors_[(size_t) SubBinarySensorType::SUB_BINARY_SENSOR_TYPE_COUNT]{nullptr}; +#endif +#ifdef USE_TEXT_SENSOR + public: + enum class SubTextSensorType { + CLEANING_STATUS = 0, + PROTOCOL_VERSION, + APPLIANCE_NAME, + SUB_TEXT_SENSOR_TYPE_COUNT, + }; + void set_sub_text_sensor(SubTextSensorType type, text_sensor::TextSensor *sens); + + protected: + void update_sub_text_sensor_(SubTextSensorType type, const std::string &value); + text_sensor::TextSensor *sub_text_sensors_[(size_t) SubTextSensorType::SUB_TEXT_SENSOR_TYPE_COUNT]{nullptr}; #endif public: HonClimate(); @@ -89,10 +95,10 @@ class HonClimate : public HaierClimateBase { void dump_config() override; void set_beeper_state(bool state); bool get_beeper_state() const; - AirflowVerticalDirection get_vertical_airflow() const; - void set_vertical_airflow(AirflowVerticalDirection direction); - AirflowHorizontalDirection get_horizontal_airflow() const; - void set_horizontal_airflow(AirflowHorizontalDirection direction); + esphome::optional get_vertical_airflow() const; + void set_vertical_airflow(hon_protocol::VerticalSwingMode direction); + esphome::optional get_horizontal_airflow() const; + void set_horizontal_airflow(hon_protocol::HorizontalSwingMode direction); std::string get_cleaning_status_text() const; CleaningState get_cleaning_status() const; void start_self_cleaning(); @@ -108,6 +114,7 @@ class HonClimate : public HaierClimateBase { void process_phase(std::chrono::steady_clock::time_point now) override; haier_protocol::HaierMessage get_control_message() override; haier_protocol::HaierMessage get_power_message(bool state) override; + void initialization() override; bool prepare_pending_action() override; void process_protocol_reset() override; bool should_get_big_data_(); @@ -147,9 +154,9 @@ class HonClimate : public HaierClimateBase { bool beeper_status_; CleaningState cleaning_status_; bool got_valid_outdoor_temp_; - AirflowVerticalDirection vertical_direction_; - AirflowHorizontalDirection horizontal_direction_; - esphome::optional hvac_hardware_info_; + esphome::optional pending_vertical_direction_{}; + esphome::optional pending_horizontal_direction_{}; + esphome::optional hvac_hardware_info_{}; uint8_t active_alarms_[8]; int extra_control_packet_bytes_; HonControlMethod control_method_; @@ -159,6 +166,10 @@ class HonClimate : public HaierClimateBase { float active_alarm_count_{NAN}; std::chrono::steady_clock::time_point last_alarm_request_; int big_data_sensors_{0}; + esphome::optional current_vertical_swing_{}; + esphome::optional current_horizontal_swing_{}; + HonSettings settings_; + ESPPreferenceObject rtc_; }; class HaierAlarmStartTrigger : public Trigger { diff --git a/esphome/components/haier/hon_packet.h b/esphome/components/haier/hon_packet.h index bbca7bb653..a03ac2831f 100644 --- a/esphome/components/haier/hon_packet.h +++ b/esphome/components/haier/hon_packet.h @@ -13,7 +13,10 @@ enum class VerticalSwingMode : uint8_t { UP = 0x04, CENTER = 0x06, DOWN = 0x08, - AUTO = 0x0C + MAX_DOWN = 0x0A, + AUTO = 0x0C, + // Auto for special modes + AUTO_SPECIAL = 0x0E }; enum class HorizontalSwingMode : uint8_t { diff --git a/esphome/components/haier/sensor/__init__.py b/esphome/components/haier/sensor/__init__.py index 01f997baa5..b2717631e0 100644 --- a/esphome/components/haier/sensor/__init__.py +++ b/esphome/components/haier/sensor/__init__.py @@ -31,6 +31,7 @@ from ..climate import ( HonClimate, ) +CODEOWNERS = ["@paveldn"] SensorTypeEnum = HonClimate.enum("SubSensorType", True) # Haier sensors diff --git a/esphome/components/haier/text_sensor/__init__.py b/esphome/components/haier/text_sensor/__init__.py new file mode 100644 index 0000000000..528b70d83e --- /dev/null +++ b/esphome/components/haier/text_sensor/__init__.py @@ -0,0 +1,54 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import text_sensor +from esphome.const import ( + ENTITY_CATEGORY_DIAGNOSTIC, + ENTITY_CATEGORY_NONE, +) +from ..climate import ( + CONF_HAIER_ID, + HonClimate, +) + +CODEOWNERS = ["@paveldn"] +TextSensorTypeEnum = HonClimate.enum("SubTextSensorType", True) + +# Haier text sensors +CONF_CLEANING_STATUS = "cleaning_status" +CONF_PROTOCOL_VERSION = "protocol_version" +CONF_APPLIANCE_NAME = "appliance_name" + +# Additional icons +ICON_SPRAY_BOTTLE = "mdi:spray-bottle" +ICON_TEXT_BOX = "mdi:text-box-outline" + +TEXT_SENSOR_TYPES = { + CONF_CLEANING_STATUS: text_sensor.text_sensor_schema( + icon=ICON_SPRAY_BOTTLE, + entity_category=ENTITY_CATEGORY_NONE, + ), + CONF_PROTOCOL_VERSION: text_sensor.text_sensor_schema( + icon=ICON_TEXT_BOX, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + ), + CONF_APPLIANCE_NAME: text_sensor.text_sensor_schema( + icon=ICON_TEXT_BOX, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + ), +} + +CONFIG_SCHEMA = cv.Schema( + { + cv.Required(CONF_HAIER_ID): cv.use_id(HonClimate), + } +).extend({cv.Optional(type): schema for type, schema in TEXT_SENSOR_TYPES.items()}) + + +async def to_code(config): + paren = await cg.get_variable(config[CONF_HAIER_ID]) + + for type, _ in TEXT_SENSOR_TYPES.items(): + if conf := config.get(type): + sens = await text_sensor.new_text_sensor(conf) + text_sensor_type = getattr(TextSensorTypeEnum, type.upper()) + cg.add(paren.set_sub_text_sensor(text_sensor_type, sens)) diff --git a/platformio.ini b/platformio.ini index d342b32b02..65c742cf91 100644 --- a/platformio.ini +++ b/platformio.ini @@ -39,7 +39,7 @@ lib_deps = bblanchon/ArduinoJson@6.18.5 ; json wjtje/qr-code-generator-library@1.7.0 ; qr_code functionpointer/arduino-MLX90393@1.0.0 ; mlx90393 - pavlodn/HaierProtocol@0.9.25 ; haier + pavlodn/HaierProtocol@0.9.28 ; haier ; 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 build_flags = diff --git a/tests/components/haier/test.esp32-c3-idf.yaml b/tests/components/haier/test.esp32-c3-idf.yaml index 72cfb781a7..fed573bd1d 100644 --- a/tests/components/haier/test.esp32-c3-idf.yaml +++ b/tests/components/haier/test.esp32-c3-idf.yaml @@ -93,3 +93,21 @@ binary_sensor: name: Haier Indoor Fan Status outdoor_fan_status: name: Haier Outdoor Fan Status + +button: + - platform: haier + haier_id: haier_ac + self_cleaning: + name: Haier start self cleaning + steri_cleaning: + name: Haier start 56°C steri-cleaning + +text_sensor: + - platform: haier + haier_id: haier_ac + appliance_name: + name: Haier appliance name + cleaning_status: + name: Haier cleaning status + protocol_version: + name: Haier protocol version diff --git a/tests/components/haier/test.esp32-c3.yaml b/tests/components/haier/test.esp32-c3.yaml index 72cfb781a7..fed573bd1d 100644 --- a/tests/components/haier/test.esp32-c3.yaml +++ b/tests/components/haier/test.esp32-c3.yaml @@ -93,3 +93,21 @@ binary_sensor: name: Haier Indoor Fan Status outdoor_fan_status: name: Haier Outdoor Fan Status + +button: + - platform: haier + haier_id: haier_ac + self_cleaning: + name: Haier start self cleaning + steri_cleaning: + name: Haier start 56°C steri-cleaning + +text_sensor: + - platform: haier + haier_id: haier_ac + appliance_name: + name: Haier appliance name + cleaning_status: + name: Haier cleaning status + protocol_version: + name: Haier protocol version diff --git a/tests/components/haier/test.esp32-idf.yaml b/tests/components/haier/test.esp32-idf.yaml index d3eeb04d65..efff532d25 100644 --- a/tests/components/haier/test.esp32-idf.yaml +++ b/tests/components/haier/test.esp32-idf.yaml @@ -93,3 +93,21 @@ binary_sensor: name: Haier Indoor Fan Status outdoor_fan_status: name: Haier Outdoor Fan Status + +button: + - platform: haier + haier_id: haier_ac + self_cleaning: + name: Haier start self cleaning + steri_cleaning: + name: Haier start 56°C steri-cleaning + +text_sensor: + - platform: haier + haier_id: haier_ac + appliance_name: + name: Haier appliance name + cleaning_status: + name: Haier cleaning status + protocol_version: + name: Haier protocol version diff --git a/tests/components/haier/test.esp32.yaml b/tests/components/haier/test.esp32.yaml index d3eeb04d65..efff532d25 100644 --- a/tests/components/haier/test.esp32.yaml +++ b/tests/components/haier/test.esp32.yaml @@ -93,3 +93,21 @@ binary_sensor: name: Haier Indoor Fan Status outdoor_fan_status: name: Haier Outdoor Fan Status + +button: + - platform: haier + haier_id: haier_ac + self_cleaning: + name: Haier start self cleaning + steri_cleaning: + name: Haier start 56°C steri-cleaning + +text_sensor: + - platform: haier + haier_id: haier_ac + appliance_name: + name: Haier appliance name + cleaning_status: + name: Haier cleaning status + protocol_version: + name: Haier protocol version diff --git a/tests/components/haier/test.esp8266.yaml b/tests/components/haier/test.esp8266.yaml index 72cfb781a7..fed573bd1d 100644 --- a/tests/components/haier/test.esp8266.yaml +++ b/tests/components/haier/test.esp8266.yaml @@ -93,3 +93,21 @@ binary_sensor: name: Haier Indoor Fan Status outdoor_fan_status: name: Haier Outdoor Fan Status + +button: + - platform: haier + haier_id: haier_ac + self_cleaning: + name: Haier start self cleaning + steri_cleaning: + name: Haier start 56°C steri-cleaning + +text_sensor: + - platform: haier + haier_id: haier_ac + appliance_name: + name: Haier appliance name + cleaning_status: + name: Haier cleaning status + protocol_version: + name: Haier protocol version diff --git a/tests/components/haier/test.rp2040.yaml b/tests/components/haier/test.rp2040.yaml index 72cfb781a7..fed573bd1d 100644 --- a/tests/components/haier/test.rp2040.yaml +++ b/tests/components/haier/test.rp2040.yaml @@ -93,3 +93,21 @@ binary_sensor: name: Haier Indoor Fan Status outdoor_fan_status: name: Haier Outdoor Fan Status + +button: + - platform: haier + haier_id: haier_ac + self_cleaning: + name: Haier start self cleaning + steri_cleaning: + name: Haier start 56°C steri-cleaning + +text_sensor: + - platform: haier + haier_id: haier_ac + appliance_name: + name: Haier appliance name + cleaning_status: + name: Haier cleaning status + protocol_version: + name: Haier protocol version From c2d67659f3a2bca35cc5ca97708470c9e9f46fd5 Mon Sep 17 00:00:00 2001 From: polyfloyd Date: Thu, 23 May 2024 23:08:28 +0200 Subject: [PATCH 1498/2101] mpr121: Add GPIO support (#6776) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/mpr121/__init__.py | 88 ++++++++++++++++++- .../__init__.py} | 7 +- .../binary_sensor/mpr121_binary_sensor.cpp | 20 +++++ .../binary_sensor/mpr121_binary_sensor.h | 26 ++++++ esphome/components/mpr121/mpr121.cpp | 87 ++++++++++++++++-- esphome/components/mpr121/mpr121.h | 68 ++++++++++---- tests/components/mpr121/common.yaml | 41 +++++++++ .../components/mpr121/test.esp32-c3-idf.yaml | 29 +----- tests/components/mpr121/test.esp32-c3.yaml | 29 +----- tests/components/mpr121/test.esp32-idf.yaml | 29 +----- tests/components/mpr121/test.esp32.yaml | 29 +----- tests/components/mpr121/test.esp8266.yaml | 29 +----- tests/components/mpr121/test.rp2040.yaml | 29 +----- tests/test3.1.yaml | 27 ------ 14 files changed, 332 insertions(+), 206 deletions(-) rename esphome/components/mpr121/{binary_sensor.py => binary_sensor/__init__.py} (82%) create mode 100644 esphome/components/mpr121/binary_sensor/mpr121_binary_sensor.cpp create mode 100644 esphome/components/mpr121/binary_sensor/mpr121_binary_sensor.h create mode 100644 tests/components/mpr121/common.yaml diff --git a/esphome/components/mpr121/__init__.py b/esphome/components/mpr121/__init__.py index dabfb47ad6..1f8e804e88 100644 --- a/esphome/components/mpr121/__init__.py +++ b/esphome/components/mpr121/__init__.py @@ -1,19 +1,32 @@ import esphome.codegen as cg import esphome.config_validation as cv +import esphome.final_validate as fv +from esphome import pins from esphome.components import i2c -from esphome.const import CONF_ID +from esphome.const import ( + CONF_BINARY_SENSOR, + CONF_CHANNEL, + CONF_ID, + CONF_INPUT, + CONF_INVERTED, + CONF_MODE, + CONF_NUMBER, + CONF_OUTPUT, +) CONF_TOUCH_THRESHOLD = "touch_threshold" CONF_RELEASE_THRESHOLD = "release_threshold" CONF_TOUCH_DEBOUNCE = "touch_debounce" CONF_RELEASE_DEBOUNCE = "release_debounce" +CONF_MAX_TOUCH_CHANNEL = "max_touch_channel" +CONF_MPR121 = "mpr121" +CONF_MPR121_ID = "mpr121_id" DEPENDENCIES = ["i2c"] -AUTO_LOAD = ["binary_sensor"] mpr121_ns = cg.esphome_ns.namespace("mpr121") -CONF_MPR121_ID = "mpr121_id" MPR121Component = mpr121_ns.class_("MPR121Component", cg.Component, i2c.I2CDevice) +MPR121GPIOPin = mpr121_ns.class_("MPR121GPIOPin", cg.GPIOPin) MULTI_CONF = True CONFIG_SCHEMA = ( @@ -28,6 +41,7 @@ CONFIG_SCHEMA = ( cv.Optional(CONF_RELEASE_THRESHOLD, default=0x06): cv.int_range( min=0x05, max=0x30 ), + cv.Optional(CONF_MAX_TOUCH_CHANNEL): cv.int_range(min=3, max=11), } ) .extend(cv.COMPONENT_SCHEMA) @@ -35,11 +49,79 @@ CONFIG_SCHEMA = ( ) +def _final_validate(config): + fconf = fv.full_config.get() + max_touch_channel = 3 + if (binary_sensors := fconf.get(CONF_BINARY_SENSOR)) is not None: + for binary_sensor in binary_sensors: + if binary_sensor.get(CONF_MPR121_ID) == config[CONF_ID]: + max_touch_channel = max(max_touch_channel, binary_sensor[CONF_CHANNEL]) + if max_touch_channel_in_config := config.get(CONF_MAX_TOUCH_CHANNEL): + if max_touch_channel != max_touch_channel_in_config: + raise cv.Invalid( + "Max touch channel must equal the highest binary sensor channel or be removed for auto calculation", + path=[CONF_MAX_TOUCH_CHANNEL], + ) + path = fconf.get_path_for_id(config[CONF_ID])[:-1] + this_config = fconf.get_config_for_path(path) + this_config[CONF_MAX_TOUCH_CHANNEL] = max_touch_channel + + +FINAL_VALIDATE_SCHEMA = _final_validate + + async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) cg.add(var.set_touch_debounce(config[CONF_TOUCH_DEBOUNCE])) cg.add(var.set_release_debounce(config[CONF_RELEASE_DEBOUNCE])) cg.add(var.set_touch_threshold(config[CONF_TOUCH_THRESHOLD])) cg.add(var.set_release_threshold(config[CONF_RELEASE_THRESHOLD])) + cg.add(var.set_max_touch_channel(config[CONF_MAX_TOUCH_CHANNEL])) await cg.register_component(var, config) await i2c.register_i2c_device(var, config) + + +def validate_mode(value): + if bool(value[CONF_INPUT]) == bool(value[CONF_OUTPUT]): + raise cv.Invalid("Mode must be either input or output") + return value + + +# https://www.nxp.com/docs/en/data-sheet/MPR121.pdf, page 4 +# +# Among the 12 electrode inputs, 8 inputs are designed as multifunctional pins. When these pins are +# not configured as electrodes, they may be used to drive LEDs or used for general purpose input or +# output. +MPR121_GPIO_PIN_SCHEMA = pins.gpio_base_schema( + MPR121GPIOPin, + cv.int_range(min=4, max=11), + modes=[CONF_INPUT, CONF_OUTPUT], + mode_validator=validate_mode, +).extend( + { + cv.Required(CONF_MPR121): cv.use_id(MPR121Component), + } +) + + +def mpr121_pin_final_validate(pin_config, parent_config): + if pin_config[CONF_NUMBER] <= parent_config[CONF_MAX_TOUCH_CHANNEL]: + raise cv.Invalid( + "Pin number must be higher than the max touch channel of the MPR121 component", + ) + + +@pins.PIN_SCHEMA_REGISTRY.register( + CONF_MPR121, MPR121_GPIO_PIN_SCHEMA, mpr121_pin_final_validate +) +async def mpr121_gpio_pin_to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + parent = await cg.get_variable(config[CONF_MPR121]) + + 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/mpr121/binary_sensor.py b/esphome/components/mpr121/binary_sensor/__init__.py similarity index 82% rename from esphome/components/mpr121/binary_sensor.py rename to esphome/components/mpr121/binary_sensor/__init__.py index 131fbcfc5b..292c631c37 100644 --- a/esphome/components/mpr121/binary_sensor.py +++ b/esphome/components/mpr121/binary_sensor/__init__.py @@ -2,7 +2,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import binary_sensor from esphome.const import CONF_CHANNEL -from . import ( +from .. import ( mpr121_ns, MPR121Component, CONF_MPR121_ID, @@ -11,9 +11,9 @@ from . import ( ) DEPENDENCIES = ["mpr121"] -MPR121Channel = mpr121_ns.class_("MPR121Channel", binary_sensor.BinarySensor) +MPR121BinarySensor = mpr121_ns.class_("MPR121BinarySensor", binary_sensor.BinarySensor) -CONFIG_SCHEMA = binary_sensor.binary_sensor_schema(MPR121Channel).extend( +CONFIG_SCHEMA = binary_sensor.binary_sensor_schema(MPR121BinarySensor).extend( { cv.GenerateID(CONF_MPR121_ID): cv.use_id(MPR121Component), cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=11), @@ -27,6 +27,7 @@ async def to_code(config): var = await binary_sensor.new_binary_sensor(config) hub = await cg.get_variable(config[CONF_MPR121_ID]) cg.add(var.set_channel(config[CONF_CHANNEL])) + cg.register_parented(var, hub) if CONF_TOUCH_THRESHOLD in config: cg.add(var.set_touch_threshold(config[CONF_TOUCH_THRESHOLD])) diff --git a/esphome/components/mpr121/binary_sensor/mpr121_binary_sensor.cpp b/esphome/components/mpr121/binary_sensor/mpr121_binary_sensor.cpp new file mode 100644 index 0000000000..dce0e73b9a --- /dev/null +++ b/esphome/components/mpr121/binary_sensor/mpr121_binary_sensor.cpp @@ -0,0 +1,20 @@ +#include "mpr121_binary_sensor.h" + +namespace esphome { +namespace mpr121 { + +void MPR121BinarySensor::setup() { + uint8_t touch_threshold = this->touch_threshold_.value_or(this->parent_->get_touch_threshold()); + this->parent_->write_byte(MPR121_TOUCHTH_0 + 2 * this->channel_, touch_threshold); + + uint8_t release_threshold = this->release_threshold_.value_or(this->parent_->get_release_threshold()); + this->parent_->write_byte(MPR121_RELEASETH_0 + 2 * this->channel_, release_threshold); +} + +void MPR121BinarySensor::process(uint16_t data) { + bool new_state = data & (1 << this->channel_); + this->publish_state(new_state); +} + +} // namespace mpr121 +} // namespace esphome diff --git a/esphome/components/mpr121/binary_sensor/mpr121_binary_sensor.h b/esphome/components/mpr121/binary_sensor/mpr121_binary_sensor.h new file mode 100644 index 0000000000..577ba82893 --- /dev/null +++ b/esphome/components/mpr121/binary_sensor/mpr121_binary_sensor.h @@ -0,0 +1,26 @@ +#pragma once + +#include "esphome/components/binary_sensor/binary_sensor.h" + +#include "../mpr121.h" + +namespace esphome { +namespace mpr121 { + +class MPR121BinarySensor : public binary_sensor::BinarySensor, public MPR121Channel, public Parented { + public: + void set_channel(uint8_t channel) { this->channel_ = channel; } + void set_touch_threshold(uint8_t touch_threshold) { this->touch_threshold_ = touch_threshold; }; + void set_release_threshold(uint8_t release_threshold) { this->release_threshold_ = release_threshold; }; + + void setup() override; + void process(uint16_t data) override; + + protected: + uint8_t channel_{0}; + optional touch_threshold_{}; + optional release_threshold_{}; +}; + +} // namespace mpr121 +} // namespace esphome diff --git a/esphome/components/mpr121/mpr121.cpp b/esphome/components/mpr121/mpr121.cpp index 7ba3da7b4d..de364c59ff 100644 --- a/esphome/components/mpr121/mpr121.cpp +++ b/esphome/components/mpr121/mpr121.cpp @@ -1,6 +1,9 @@ #include "mpr121.h" -#include "esphome/core/log.h" + +#include + #include "esphome/core/hal.h" +#include "esphome/core/log.h" namespace esphome { namespace mpr121 { @@ -20,10 +23,7 @@ void MPR121Component::setup() { // set touch sensitivity for all 12 channels for (auto *channel : this->channels_) { - this->write_byte(MPR121_TOUCHTH_0 + 2 * channel->channel_, - channel->touch_threshold_.value_or(this->touch_threshold_)); - this->write_byte(MPR121_RELEASETH_0 + 2 * channel->channel_, - channel->release_threshold_.value_or(this->release_threshold_)); + channel->setup(); } this->write_byte(MPR121_MHDR, 0x01); this->write_byte(MPR121_NHDR, 0x01); @@ -44,8 +44,15 @@ void MPR121Component::setup() { this->write_byte(MPR121_CONFIG1, 0x10); // 0.5uS encoding, 1ms period this->write_byte(MPR121_CONFIG2, 0x20); - // start with first 5 bits of baseline tracking - this->write_byte(MPR121_ECR, 0x8F); + + // Write the Electrode Configuration Register + // * Highest 2 bits is "Calibration Lock", which we set to a value corresponding to 5 bits. + // * The 2 bits below is "Proximity Enable" and are left at 0. + // * The 4 least significant bits control how many electrodes are enabled. Electrodes are enabled + // as a range, starting at 0 up to the highest channel index used. + this->write_byte(MPR121_ECR, 0x80 | (this->max_touch_channel_ + 1)); + + this->flush_gpio_(); } void MPR121Component::set_touch_debounce(uint8_t debounce) { @@ -86,6 +93,72 @@ void MPR121Component::loop() { for (auto *channel : this->channels_) channel->process(val); + + this->read_byte(MPR121_GPIODATA, &this->gpio_input_); +} + +bool MPR121Component::digital_read(uint8_t ionum) { return (this->gpio_input_ & (1 << ionum)) != 0; } + +void MPR121Component::digital_write(uint8_t ionum, bool value) { + if (value) { + this->gpio_output_ |= (1 << ionum); + } else { + this->gpio_output_ &= ~(1 << ionum); + } + this->flush_gpio_(); +} + +void MPR121Component::pin_mode(uint8_t ionum, gpio::Flags flags) { + this->gpio_enable_ |= (1 << ionum); + if (flags & gpio::FLAG_INPUT) { + this->gpio_direction_ &= ~(1 << ionum); + } else if (flags & gpio::FLAG_OUTPUT) { + this->gpio_direction_ |= 1 << ionum; + } + this->flush_gpio_(); +} + +bool MPR121Component::flush_gpio_() { + if (this->is_failed()) { + return false; + } + + // TODO: The CTL registers can configure internal pullup/pulldown resistors. + this->write_byte(MPR121_GPIOCTL0, 0x00); + this->write_byte(MPR121_GPIOCTL1, 0x00); + this->write_byte(MPR121_GPIOEN, this->gpio_enable_); + this->write_byte(MPR121_GPIODIR, this->gpio_direction_); + + if (!this->write_byte(MPR121_GPIODATA, this->gpio_output_)) { + this->status_set_warning(); + return false; + } + + this->status_clear_warning(); + return true; +} + +void MPR121GPIOPin::setup() { this->pin_mode(this->flags_); } + +void MPR121GPIOPin::pin_mode(gpio::Flags flags) { + assert(this->pin_ >= 4); + this->parent_->pin_mode(this->pin_ - 4, flags); +} + +bool MPR121GPIOPin::digital_read() { + assert(this->pin_ >= 4); + return this->parent_->digital_read(this->pin_ - 4) != this->inverted_; +} + +void MPR121GPIOPin::digital_write(bool value) { + assert(this->pin_ >= 4); + this->parent_->digital_write(this->pin_ - 4, value != this->inverted_); +} + +std::string MPR121GPIOPin::dump_summary() const { + char buffer[32]; + snprintf(buffer, sizeof(buffer), "ELE%u on MPR121", this->pin_); + return buffer; } } // namespace mpr121 diff --git a/esphome/components/mpr121/mpr121.h b/esphome/components/mpr121/mpr121.h index 8b7735fa28..f2dc2fe9c9 100644 --- a/esphome/components/mpr121/mpr121.h +++ b/esphome/components/mpr121/mpr121.h @@ -1,8 +1,10 @@ #pragma once #include "esphome/core/component.h" +#include "esphome/core/defines.h" +#include "esphome/core/hal.h" + #include "esphome/components/i2c/i2c.h" -#include "esphome/components/binary_sensor/binary_sensor.h" #include @@ -39,6 +41,9 @@ enum { MPR121_UPLIMIT = 0x7D, MPR121_LOWLIMIT = 0x7E, MPR121_TARGETLIMIT = 0x7F, + MPR121_GPIOCTL0 = 0x73, + MPR121_GPIOCTL1 = 0x74, + MPR121_GPIODATA = 0x75, MPR121_GPIODIR = 0x76, MPR121_GPIOEN = 0x77, MPR121_GPIOSET = 0x78, @@ -47,19 +52,10 @@ enum { MPR121_SOFTRESET = 0x80, }; -class MPR121Channel : public binary_sensor::BinarySensor { - friend class MPR121Component; - +class MPR121Channel { public: - void set_channel(uint8_t channel) { channel_ = channel; } - void process(uint16_t data) { this->publish_state(static_cast(data & (1 << this->channel_))); } - void set_touch_threshold(uint8_t touch_threshold) { this->touch_threshold_ = touch_threshold; }; - void set_release_threshold(uint8_t release_threshold) { this->release_threshold_ = release_threshold; }; - - protected: - uint8_t channel_{0}; - optional touch_threshold_{}; - optional release_threshold_{}; + virtual void setup() = 0; + virtual void process(uint16_t data) = 0; }; class MPR121Component : public Component, public i2c::I2CDevice { @@ -69,23 +65,63 @@ class MPR121Component : public Component, public i2c::I2CDevice { void set_release_debounce(uint8_t debounce); void set_touch_threshold(uint8_t touch_threshold) { this->touch_threshold_ = touch_threshold; }; void set_release_threshold(uint8_t release_threshold) { this->release_threshold_ = release_threshold; }; - uint8_t get_touch_threshold() { return this->touch_threshold_; }; - uint8_t get_release_threshold() { return this->release_threshold_; }; + uint8_t get_touch_threshold() const { return this->touch_threshold_; }; + uint8_t get_release_threshold() const { return this->release_threshold_; }; void setup() override; void dump_config() override; - float get_setup_priority() const override { return setup_priority::DATA; } + float get_setup_priority() const override { return setup_priority::IO; } void loop() override; + void set_max_touch_channel(uint8_t max_touch_channel) { this->max_touch_channel_ = max_touch_channel; } + + // GPIO helper functions. + bool digital_read(uint8_t ionum); + void digital_write(uint8_t ionum, bool value); + void pin_mode(uint8_t ionum, gpio::Flags flags); + protected: std::vector channels_{}; uint8_t debounce_{0}; uint8_t touch_threshold_{}; uint8_t release_threshold_{}; + uint8_t max_touch_channel_{3}; enum ErrorCode { NONE = 0, COMMUNICATION_FAILED, WRONG_CHIP_STATE, } error_code_{NONE}; + + bool flush_gpio_(); + + /// The enable mask - zero means high Z, 1 means GPIO usage + uint8_t gpio_enable_{0x00}; + /// Mask for the pin mode - 1 means output, 0 means input + uint8_t gpio_direction_{0x00}; + /// The mask to write as output state - 1 means HIGH, 0 means LOW + uint8_t gpio_output_{0x00}; + /// The mask to read as input state - 1 means HIGH, 0 means LOW + uint8_t gpio_input_{0x00}; +}; + +/// Helper class to expose a MPR121 pin as an internal input GPIO pin. +class MPR121GPIOPin : public GPIOPin { + public: + void setup() override; + void pin_mode(gpio::Flags flags) override; + bool digital_read() override; + void digital_write(bool value) override; + std::string dump_summary() const override; + + void set_parent(MPR121Component *parent) { this->parent_ = parent; } + void set_pin(uint8_t pin) { this->pin_ = pin; } + void set_inverted(bool inverted) { this->inverted_ = inverted; } + void set_flags(gpio::Flags flags) { this->flags_ = flags; } + + protected: + MPR121Component *parent_; + uint8_t pin_; + bool inverted_; + gpio::Flags flags_; }; } // namespace mpr121 diff --git a/tests/components/mpr121/common.yaml b/tests/components/mpr121/common.yaml new file mode 100644 index 0000000000..fcf61b57f3 --- /dev/null +++ b/tests/components/mpr121/common.yaml @@ -0,0 +1,41 @@ +i2c: + - id: i2c_mpr121 + scl: ${i2c_scl} + sda: ${i2c_sda} + +mpr121: + id: mpr121_first + address: 0x5A + +binary_sensor: + - platform: mpr121 + id: touchkey0 + name: touchkey0 + channel: 0 + - platform: mpr121 + id: bin1 + name: touchkey1 + channel: 1 + - platform: mpr121 + id: bin2 + name: touchkey2 + channel: 2 + - platform: mpr121 + id: bin3 + name: touchkey3 + channel: 6 + +output: + - platform: gpio + id: gpio1 + pin: + mpr121: mpr121_first + number: 7 + mode: OUTPUT + - platform: gpio + id: gpio2 + pin: + mpr121: mpr121_first + number: 11 + mode: OUTPUT + inverted: true diff --git a/tests/components/mpr121/test.esp32-c3-idf.yaml b/tests/components/mpr121/test.esp32-c3-idf.yaml index 517e092560..d7ae0d5161 100644 --- a/tests/components/mpr121/test.esp32-c3-idf.yaml +++ b/tests/components/mpr121/test.esp32-c3-idf.yaml @@ -1,26 +1,5 @@ -i2c: - - id: i2c_mpr121 - scl: 5 - sda: 4 +substitutions: + i2c_scl: GPIO5 + i2c_sda: GPIO4 -mpr121: - id: mpr121_first - address: 0x5A - -binary_sensor: - - platform: mpr121 - id: touchkey0 - name: touchkey0 - channel: 0 - - platform: mpr121 - id: bin1 - name: touchkey1 - channel: 1 - - platform: mpr121 - id: bin2 - name: touchkey2 - channel: 2 - - platform: mpr121 - id: bin3 - name: touchkey3 - channel: 3 +<<: !include common.yaml diff --git a/tests/components/mpr121/test.esp32-c3.yaml b/tests/components/mpr121/test.esp32-c3.yaml index 517e092560..d7ae0d5161 100644 --- a/tests/components/mpr121/test.esp32-c3.yaml +++ b/tests/components/mpr121/test.esp32-c3.yaml @@ -1,26 +1,5 @@ -i2c: - - id: i2c_mpr121 - scl: 5 - sda: 4 +substitutions: + i2c_scl: GPIO5 + i2c_sda: GPIO4 -mpr121: - id: mpr121_first - address: 0x5A - -binary_sensor: - - platform: mpr121 - id: touchkey0 - name: touchkey0 - channel: 0 - - platform: mpr121 - id: bin1 - name: touchkey1 - channel: 1 - - platform: mpr121 - id: bin2 - name: touchkey2 - channel: 2 - - platform: mpr121 - id: bin3 - name: touchkey3 - channel: 3 +<<: !include common.yaml diff --git a/tests/components/mpr121/test.esp32-idf.yaml b/tests/components/mpr121/test.esp32-idf.yaml index 96996fd8ee..1037d5d35b 100644 --- a/tests/components/mpr121/test.esp32-idf.yaml +++ b/tests/components/mpr121/test.esp32-idf.yaml @@ -1,26 +1,5 @@ -i2c: - - id: i2c_mpr121 - scl: 16 - sda: 17 +substitutions: + i2c_scl: GPIO16 + i2c_sda: GPIO17 -mpr121: - id: mpr121_first - address: 0x5A - -binary_sensor: - - platform: mpr121 - id: touchkey0 - name: touchkey0 - channel: 0 - - platform: mpr121 - id: bin1 - name: touchkey1 - channel: 1 - - platform: mpr121 - id: bin2 - name: touchkey2 - channel: 2 - - platform: mpr121 - id: bin3 - name: touchkey3 - channel: 3 +<<: !include common.yaml diff --git a/tests/components/mpr121/test.esp32.yaml b/tests/components/mpr121/test.esp32.yaml index 96996fd8ee..1037d5d35b 100644 --- a/tests/components/mpr121/test.esp32.yaml +++ b/tests/components/mpr121/test.esp32.yaml @@ -1,26 +1,5 @@ -i2c: - - id: i2c_mpr121 - scl: 16 - sda: 17 +substitutions: + i2c_scl: GPIO16 + i2c_sda: GPIO17 -mpr121: - id: mpr121_first - address: 0x5A - -binary_sensor: - - platform: mpr121 - id: touchkey0 - name: touchkey0 - channel: 0 - - platform: mpr121 - id: bin1 - name: touchkey1 - channel: 1 - - platform: mpr121 - id: bin2 - name: touchkey2 - channel: 2 - - platform: mpr121 - id: bin3 - name: touchkey3 - channel: 3 +<<: !include common.yaml diff --git a/tests/components/mpr121/test.esp8266.yaml b/tests/components/mpr121/test.esp8266.yaml index 517e092560..d7ae0d5161 100644 --- a/tests/components/mpr121/test.esp8266.yaml +++ b/tests/components/mpr121/test.esp8266.yaml @@ -1,26 +1,5 @@ -i2c: - - id: i2c_mpr121 - scl: 5 - sda: 4 +substitutions: + i2c_scl: GPIO5 + i2c_sda: GPIO4 -mpr121: - id: mpr121_first - address: 0x5A - -binary_sensor: - - platform: mpr121 - id: touchkey0 - name: touchkey0 - channel: 0 - - platform: mpr121 - id: bin1 - name: touchkey1 - channel: 1 - - platform: mpr121 - id: bin2 - name: touchkey2 - channel: 2 - - platform: mpr121 - id: bin3 - name: touchkey3 - channel: 3 +<<: !include common.yaml diff --git a/tests/components/mpr121/test.rp2040.yaml b/tests/components/mpr121/test.rp2040.yaml index 517e092560..d7ae0d5161 100644 --- a/tests/components/mpr121/test.rp2040.yaml +++ b/tests/components/mpr121/test.rp2040.yaml @@ -1,26 +1,5 @@ -i2c: - - id: i2c_mpr121 - scl: 5 - sda: 4 +substitutions: + i2c_scl: GPIO5 + i2c_sda: GPIO4 -mpr121: - id: mpr121_first - address: 0x5A - -binary_sensor: - - platform: mpr121 - id: touchkey0 - name: touchkey0 - channel: 0 - - platform: mpr121 - id: bin1 - name: touchkey1 - channel: 1 - - platform: mpr121 - id: bin2 - name: touchkey2 - channel: 2 - - platform: mpr121 - id: bin3 - name: touchkey3 - channel: 3 +<<: !include common.yaml diff --git a/tests/test3.1.yaml b/tests/test3.1.yaml index a7d8dcb3f4..018a4d94f3 100644 --- a/tests/test3.1.yaml +++ b/tests/test3.1.yaml @@ -344,10 +344,6 @@ apds9960: address: 0x20 update_interval: 60s -mpr121: - id: mpr121_first - address: 0x5A - binary_sensor: - platform: apds9960 direction: up @@ -371,25 +367,6 @@ binary_sensor: direction: right name: APDS9960 Right - - platform: mpr121 - id: touchkey0 - channel: 0 - name: touchkey0 - - platform: mpr121 - channel: 1 - name: touchkey1 - id: bin1 - - platform: mpr121 - channel: 2 - name: touchkey2 - id: bin2 - - platform: mpr121 - channel: 3 - name: touchkey3 - id: bin3 - on_press: - then: - - switch.toggle: mpr121_toggle - platform: ttp229_lsf channel: 1 name: TTP229 LSF Test @@ -443,10 +420,6 @@ grove_tb6612fng: address: 0x14 switch: - - platform: template - name: mpr121_toggle - id: mpr121_toggle - optimistic: true - platform: gpio id: gpio_switch1 pin: From 9d03f472335be2c696547c8484421dba8252f145 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Thu, 23 May 2024 23:11:34 +0200 Subject: [PATCH 1499/2101] [nextion] Add basic functions to Intelligent series (#6791) --- esphome/components/nextion/nextion.h | 67 +++++++++++++++++++ .../components/nextion/nextion_commands.cpp | 20 +++++- 2 files changed, 86 insertions(+), 1 deletion(-) diff --git a/esphome/components/nextion/nextion.h b/esphome/components/nextion/nextion.h index dfa74f644d..4546baa4d8 100644 --- a/esphome/components/nextion/nextion.h +++ b/esphome/components/nextion/nextion.h @@ -952,6 +952,73 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe */ bool set_protocol_reparse_mode(bool active_mode); + // ======== Nextion Intelligent Series ======== + + /** + * Set the video id of a component. + * @param component The component name. + * @param vid_id The video ID. + * + * Example: + * ```cpp + * it.set_component_vid("textview", 1); + * ``` + * + * This will change the video id of the component `textview`. + * + * Note: Requires Nextion Intelligent series display. + */ + void set_component_vid(const char *component, uint8_t vid_id); + + /** + * Set the drag availability of a component. + * @param component The component name. + * @param drag False: Drag not available, True: Drag available. + * + * Example: + * ```cpp + * it.set_component_drag("textview", true); + * ``` + * + * This will enable drag to the component `textview`. + * + * Note: Requires Nextion Intelligent series display. + */ + void set_component_drag(const char *component, bool drag); + + /** + * Set the opaqueness (fading) of a component. + * @param component The component name. + * @param aph An integer between 0 and 127 related to the opaqueness/fading level. + * + * Example: + * ```cpp + * it.set_component_aph("textview", 64); + * ``` + * + * This will set the opaqueness level of the component `textview` to 64. + * + * Note: Requires Nextion Intelligent series display. + */ + void set_component_aph(const char *component, uint8_t aph); + + /** + * Set the position of a component. + * @param component The component name. + * @param x The new X (horizontal) coordinate for the component. + * @param y The new Y (vertical) coordinate for the component. + * + * Example: + * ```cpp + * it.set_component_aph("textview", 64, 35); + * ``` + * + * This will move the component `textview` to the column 64 of row 35 of the display. + * + * Note: Requires Nextion Intelligent series display. + */ + void set_component_position(const char *component, uint32_t x, uint32_t y); + // ========== INTERNAL METHODS ========== // (In most use cases you won't need these) void register_touch_component(NextionComponentBase *obj) { this->touch_.push_back(obj); } diff --git a/esphome/components/nextion/nextion_commands.cpp b/esphome/components/nextion/nextion_commands.cpp index fdd6c74d99..398e9dd502 100644 --- a/esphome/components/nextion/nextion_commands.cpp +++ b/esphome/components/nextion/nextion_commands.cpp @@ -148,7 +148,25 @@ void Nextion::set_component_pic(const char *component, uint8_t pic_id) { } void Nextion::set_component_picc(const char *component, uint8_t pic_id) { - this->add_no_result_to_queue_with_printf_("set_component_pic", "%s.picc=%" PRIu8, component, pic_id); + this->add_no_result_to_queue_with_printf_("set_component_picc", "%s.picc=%" PRIu8, 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); +} + +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); +} + +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); +} + +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); } void Nextion::set_component_text_printf(const char *component, const char *format, ...) { From 863bee28d9649f3179b75b3a5ebb833d9c7232a5 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Sat, 25 May 2024 07:42:24 +1200 Subject: [PATCH 1500/2101] [voice_assistant] Don't allocate buffers until starting the microphone for the first time (#6800) --- .../voice_assistant/voice_assistant.cpp | 96 +++++++++++++++---- .../voice_assistant/voice_assistant.h | 4 + 2 files changed, 83 insertions(+), 17 deletions(-) diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index 109e52f8eb..59ba39c527 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -71,6 +71,12 @@ void VoiceAssistant::setup() { ESP_LOGCONFIG(TAG, "Setting up Voice Assistant..."); global_voice_assistant = this; +} + +bool VoiceAssistant::allocate_buffers_() { + if (this->send_buffer_ != nullptr) { + return true; // Already allocated + } #ifdef USE_SPEAKER if (this->speaker_ != nullptr) { @@ -78,8 +84,7 @@ void VoiceAssistant::setup() { this->speaker_buffer_ = speaker_allocator.allocate(SPEAKER_BUFFER_SIZE); if (this->speaker_buffer_ == nullptr) { ESP_LOGW(TAG, "Could not allocate speaker buffer"); - this->mark_failed(); - return; + return false; } } #endif @@ -88,8 +93,7 @@ void VoiceAssistant::setup() { this->input_buffer_ = allocator.allocate(INPUT_BUFFER_SIZE); if (this->input_buffer_ == nullptr) { ESP_LOGW(TAG, "Could not allocate input buffer"); - this->mark_failed(); - return; + return false; } #ifdef USE_ESP_ADF @@ -99,17 +103,71 @@ void VoiceAssistant::setup() { this->ring_buffer_ = RingBuffer::create(BUFFER_SIZE * sizeof(int16_t)); if (this->ring_buffer_ == nullptr) { ESP_LOGW(TAG, "Could not allocate ring buffer"); - this->mark_failed(); - return; + return false; } ExternalRAMAllocator send_allocator(ExternalRAMAllocator::ALLOW_FAILURE); this->send_buffer_ = send_allocator.allocate(SEND_BUFFER_SIZE); if (send_buffer_ == nullptr) { ESP_LOGW(TAG, "Could not allocate send buffer"); - this->mark_failed(); - return; + return false; } + + return true; +} + +void VoiceAssistant::clear_buffers_() { + if (this->send_buffer_ != nullptr) { + memset(this->send_buffer_, 0, SEND_BUFFER_SIZE); + } + + if (this->input_buffer_ != nullptr) { + memset(this->input_buffer_, 0, INPUT_BUFFER_SIZE * sizeof(int16_t)); + } + + if (this->ring_buffer_ != nullptr) { + this->ring_buffer_->reset(); + } + +#ifdef USE_SPEAKER + if (this->speaker_buffer_ != nullptr) { + memset(this->speaker_buffer_, 0, SPEAKER_BUFFER_SIZE); + + this->speaker_buffer_size_ = 0; + this->speaker_buffer_index_ = 0; + this->speaker_bytes_received_ = 0; + } +#endif +} + +void VoiceAssistant::deallocate_buffers_() { + ExternalRAMAllocator send_deallocator(ExternalRAMAllocator::ALLOW_FAILURE); + send_deallocator.deallocate(this->send_buffer_, SEND_BUFFER_SIZE); + this->send_buffer_ = nullptr; + + if (this->ring_buffer_ != nullptr) { + this->ring_buffer_.reset(); + this->ring_buffer_ = nullptr; + } + +#ifdef USE_ESP_ADF + if (this->vad_instance_ != nullptr) { + vad_destroy(this->vad_instance_); + this->vad_instance_ = nullptr; + } +#endif + + ExternalRAMAllocator input_deallocator(ExternalRAMAllocator::ALLOW_FAILURE); + input_deallocator.deallocate(this->input_buffer_, INPUT_BUFFER_SIZE); + this->input_buffer_ = nullptr; + +#ifdef USE_SPEAKER + if (this->speaker_buffer_ != nullptr) { + ExternalRAMAllocator speaker_deallocator(ExternalRAMAllocator::ALLOW_FAILURE); + speaker_deallocator.deallocate(this->speaker_buffer_, SPEAKER_BUFFER_SIZE); + this->speaker_buffer_ = nullptr; + } +#endif } int VoiceAssistant::read_microphone_() { @@ -138,14 +196,13 @@ void VoiceAssistant::loop() { } this->continuous_ = false; this->signal_stop_(); + this->clear_buffers_(); return; } switch (this->state_) { case State::IDLE: { if (this->continuous_ && this->desired_state_ == State::IDLE) { this->idle_trigger_->trigger(); - - this->ring_buffer_->reset(); #ifdef USE_ESP_ADF if (this->use_wake_word_) { this->set_state_(State::START_MICROPHONE, State::WAIT_FOR_VAD); @@ -161,8 +218,15 @@ void VoiceAssistant::loop() { } case State::START_MICROPHONE: { ESP_LOGD(TAG, "Starting Microphone"); - memset(this->send_buffer_, 0, SEND_BUFFER_SIZE); - memset(this->input_buffer_, 0, INPUT_BUFFER_SIZE * sizeof(int16_t)); + if (!this->allocate_buffers_()) { + this->status_set_error("Failed to allocate buffers"); + return; + } + if (this->status_has_error()) { + this->status_clear_error(); + } + this->clear_buffers_(); + this->mic_->start(); this->high_freq_.start(); this->set_state_(State::STARTING_MICROPHONE); @@ -343,10 +407,9 @@ void VoiceAssistant::loop() { this->speaker_->stop(); this->cancel_timeout("speaker-timeout"); this->cancel_timeout("playing"); - this->speaker_buffer_size_ = 0; - this->speaker_buffer_index_ = 0; - this->speaker_bytes_received_ = 0; - memset(this->speaker_buffer_, 0, SPEAKER_BUFFER_SIZE); + + this->clear_buffers_(); + this->wait_for_stream_end_ = false; this->stream_ended_ = false; @@ -507,7 +570,6 @@ void VoiceAssistant::request_start(bool continuous, bool silence_detection) { if (this->state_ == State::IDLE) { this->continuous_ = continuous; this->silence_detection_ = silence_detection; - this->ring_buffer_->reset(); #ifdef USE_ESP_ADF if (this->use_wake_word_) { this->set_state_(State::START_MICROPHONE, State::WAIT_FOR_VAD); diff --git a/esphome/components/voice_assistant/voice_assistant.h b/esphome/components/voice_assistant/voice_assistant.h index 1c0ea12f4f..17141365d4 100644 --- a/esphome/components/voice_assistant/voice_assistant.h +++ b/esphome/components/voice_assistant/voice_assistant.h @@ -151,6 +151,10 @@ class VoiceAssistant : public Component { void set_wake_word(const std::string &wake_word) { this->wake_word_ = wake_word; } protected: + bool allocate_buffers_(); + void clear_buffers_(); + void deallocate_buffers_(); + int read_microphone_(); void set_state_(State state); void set_state_(State state, State desired_state); From 04db724295e4e5a537e1532b426a9c64bc19a7aa Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Sat, 25 May 2024 07:42:24 +1200 Subject: [PATCH 1501/2101] [voice_assistant] Don't allocate buffers until starting the microphone for the first time (#6800) --- .../voice_assistant/voice_assistant.cpp | 96 +++++++++++++++---- .../voice_assistant/voice_assistant.h | 4 + 2 files changed, 83 insertions(+), 17 deletions(-) diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index 109e52f8eb..59ba39c527 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -71,6 +71,12 @@ void VoiceAssistant::setup() { ESP_LOGCONFIG(TAG, "Setting up Voice Assistant..."); global_voice_assistant = this; +} + +bool VoiceAssistant::allocate_buffers_() { + if (this->send_buffer_ != nullptr) { + return true; // Already allocated + } #ifdef USE_SPEAKER if (this->speaker_ != nullptr) { @@ -78,8 +84,7 @@ void VoiceAssistant::setup() { this->speaker_buffer_ = speaker_allocator.allocate(SPEAKER_BUFFER_SIZE); if (this->speaker_buffer_ == nullptr) { ESP_LOGW(TAG, "Could not allocate speaker buffer"); - this->mark_failed(); - return; + return false; } } #endif @@ -88,8 +93,7 @@ void VoiceAssistant::setup() { this->input_buffer_ = allocator.allocate(INPUT_BUFFER_SIZE); if (this->input_buffer_ == nullptr) { ESP_LOGW(TAG, "Could not allocate input buffer"); - this->mark_failed(); - return; + return false; } #ifdef USE_ESP_ADF @@ -99,17 +103,71 @@ void VoiceAssistant::setup() { this->ring_buffer_ = RingBuffer::create(BUFFER_SIZE * sizeof(int16_t)); if (this->ring_buffer_ == nullptr) { ESP_LOGW(TAG, "Could not allocate ring buffer"); - this->mark_failed(); - return; + return false; } ExternalRAMAllocator send_allocator(ExternalRAMAllocator::ALLOW_FAILURE); this->send_buffer_ = send_allocator.allocate(SEND_BUFFER_SIZE); if (send_buffer_ == nullptr) { ESP_LOGW(TAG, "Could not allocate send buffer"); - this->mark_failed(); - return; + return false; } + + return true; +} + +void VoiceAssistant::clear_buffers_() { + if (this->send_buffer_ != nullptr) { + memset(this->send_buffer_, 0, SEND_BUFFER_SIZE); + } + + if (this->input_buffer_ != nullptr) { + memset(this->input_buffer_, 0, INPUT_BUFFER_SIZE * sizeof(int16_t)); + } + + if (this->ring_buffer_ != nullptr) { + this->ring_buffer_->reset(); + } + +#ifdef USE_SPEAKER + if (this->speaker_buffer_ != nullptr) { + memset(this->speaker_buffer_, 0, SPEAKER_BUFFER_SIZE); + + this->speaker_buffer_size_ = 0; + this->speaker_buffer_index_ = 0; + this->speaker_bytes_received_ = 0; + } +#endif +} + +void VoiceAssistant::deallocate_buffers_() { + ExternalRAMAllocator send_deallocator(ExternalRAMAllocator::ALLOW_FAILURE); + send_deallocator.deallocate(this->send_buffer_, SEND_BUFFER_SIZE); + this->send_buffer_ = nullptr; + + if (this->ring_buffer_ != nullptr) { + this->ring_buffer_.reset(); + this->ring_buffer_ = nullptr; + } + +#ifdef USE_ESP_ADF + if (this->vad_instance_ != nullptr) { + vad_destroy(this->vad_instance_); + this->vad_instance_ = nullptr; + } +#endif + + ExternalRAMAllocator input_deallocator(ExternalRAMAllocator::ALLOW_FAILURE); + input_deallocator.deallocate(this->input_buffer_, INPUT_BUFFER_SIZE); + this->input_buffer_ = nullptr; + +#ifdef USE_SPEAKER + if (this->speaker_buffer_ != nullptr) { + ExternalRAMAllocator speaker_deallocator(ExternalRAMAllocator::ALLOW_FAILURE); + speaker_deallocator.deallocate(this->speaker_buffer_, SPEAKER_BUFFER_SIZE); + this->speaker_buffer_ = nullptr; + } +#endif } int VoiceAssistant::read_microphone_() { @@ -138,14 +196,13 @@ void VoiceAssistant::loop() { } this->continuous_ = false; this->signal_stop_(); + this->clear_buffers_(); return; } switch (this->state_) { case State::IDLE: { if (this->continuous_ && this->desired_state_ == State::IDLE) { this->idle_trigger_->trigger(); - - this->ring_buffer_->reset(); #ifdef USE_ESP_ADF if (this->use_wake_word_) { this->set_state_(State::START_MICROPHONE, State::WAIT_FOR_VAD); @@ -161,8 +218,15 @@ void VoiceAssistant::loop() { } case State::START_MICROPHONE: { ESP_LOGD(TAG, "Starting Microphone"); - memset(this->send_buffer_, 0, SEND_BUFFER_SIZE); - memset(this->input_buffer_, 0, INPUT_BUFFER_SIZE * sizeof(int16_t)); + if (!this->allocate_buffers_()) { + this->status_set_error("Failed to allocate buffers"); + return; + } + if (this->status_has_error()) { + this->status_clear_error(); + } + this->clear_buffers_(); + this->mic_->start(); this->high_freq_.start(); this->set_state_(State::STARTING_MICROPHONE); @@ -343,10 +407,9 @@ void VoiceAssistant::loop() { this->speaker_->stop(); this->cancel_timeout("speaker-timeout"); this->cancel_timeout("playing"); - this->speaker_buffer_size_ = 0; - this->speaker_buffer_index_ = 0; - this->speaker_bytes_received_ = 0; - memset(this->speaker_buffer_, 0, SPEAKER_BUFFER_SIZE); + + this->clear_buffers_(); + this->wait_for_stream_end_ = false; this->stream_ended_ = false; @@ -507,7 +570,6 @@ void VoiceAssistant::request_start(bool continuous, bool silence_detection) { if (this->state_ == State::IDLE) { this->continuous_ = continuous; this->silence_detection_ = silence_detection; - this->ring_buffer_->reset(); #ifdef USE_ESP_ADF if (this->use_wake_word_) { this->set_state_(State::START_MICROPHONE, State::WAIT_FOR_VAD); diff --git a/esphome/components/voice_assistant/voice_assistant.h b/esphome/components/voice_assistant/voice_assistant.h index 1c0ea12f4f..17141365d4 100644 --- a/esphome/components/voice_assistant/voice_assistant.h +++ b/esphome/components/voice_assistant/voice_assistant.h @@ -151,6 +151,10 @@ class VoiceAssistant : public Component { void set_wake_word(const std::string &wake_word) { this->wake_word_ = wake_word; } protected: + bool allocate_buffers_(); + void clear_buffers_(); + void deallocate_buffers_(); + int read_microphone_(); void set_state_(State state); void set_state_(State state, State desired_state); From af755380b7e8f8b90cfd1f45c9dcbf09bb94c101 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Sat, 25 May 2024 08:14:39 +1200 Subject: [PATCH 1502/2101] Bump version to 2024.5.3 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 48b8aa8656..0c53287909 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.5.2" +__version__ = "2024.5.3" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 6d341ce4e7f41c09d723f9663e61e0c0dd51d159 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 27 May 2024 07:15:05 +1200 Subject: [PATCH 1503/2101] [web_server_base] Bump ESPAsyncWebServer-esphome to 3.2.2 (#6797) Co-authored-by: Samuel Sieb --- esphome/components/web_server_base/__init__.py | 2 +- platformio.ini | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/web_server_base/__init__.py b/esphome/components/web_server_base/__init__.py index 1970b5a0c5..4f894619b0 100644 --- a/esphome/components/web_server_base/__init__.py +++ b/esphome/components/web_server_base/__init__.py @@ -37,4 +37,4 @@ async def to_code(config): cg.add_library("FS", None) cg.add_library("Update", None) # https://github.com/esphome/ESPAsyncWebServer/blob/master/library.json - cg.add_library("esphome/ESPAsyncWebServer-esphome", "3.2.0") + cg.add_library("esphome/ESPAsyncWebServer-esphome", "3.2.2") diff --git a/platformio.ini b/platformio.ini index 65c742cf91..fd0ae7c6d8 100644 --- a/platformio.ini +++ b/platformio.ini @@ -58,7 +58,7 @@ lib_deps = SPI ; spi (Arduino built-in) Wire ; i2c (Arduino built-int) heman/AsyncMqttClient-esphome@1.0.0 ; mqtt - esphome/ESPAsyncWebServer-esphome@3.2.0 ; web_server_base + esphome/ESPAsyncWebServer-esphome@3.2.2 ; web_server_base fastled/FastLED@3.3.2 ; fastled_base mikalhart/TinyGPSPlus@1.0.2 ; gps freekode/TM1651@1.0.1 ; tm1651 From 4125b48b86a4da0ba27704ab11f2033a8275540c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C5=A1o=20Domadenik?= Date: Sun, 26 May 2024 21:23:00 +0200 Subject: [PATCH 1504/2101] Fix incorrect naming of the AdaFruit MagTag display. (#6810) --- esphome/components/waveshare_epaper/display.py | 4 ++-- .../components/waveshare_epaper/waveshare_epaper.cpp | 12 ++++++------ .../components/waveshare_epaper/waveshare_epaper.h | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/esphome/components/waveshare_epaper/display.py b/esphome/components/waveshare_epaper/display.py index bba60efc0a..9ad948e915 100644 --- a/esphome/components/waveshare_epaper/display.py +++ b/esphome/components/waveshare_epaper/display.py @@ -48,7 +48,7 @@ WaveshareEPaper2P9InBV3 = waveshare_epaper_ns.class_( WaveshareEPaper2P9InV2R2 = waveshare_epaper_ns.class_( "WaveshareEPaper2P9InV2R2", WaveshareEPaper ) -GDEY029T94 = waveshare_epaper_ns.class_("GDEY029T94", WaveshareEPaper) +GDEW029T5 = waveshare_epaper_ns.class_("GDEW029T5", WaveshareEPaper) WaveshareEPaper2P9InDKE = waveshare_epaper_ns.class_( "WaveshareEPaper2P9InDKE", WaveshareEPaper ) @@ -110,7 +110,7 @@ MODELS = { "2.13in-ttgo-b74": ("a", WaveshareEPaperTypeAModel.TTGO_EPAPER_2_13_IN_B74), "2.90in": ("a", WaveshareEPaperTypeAModel.WAVESHARE_EPAPER_2_9_IN), "2.90inv2": ("a", WaveshareEPaperTypeAModel.WAVESHARE_EPAPER_2_9_IN_V2), - "gdey029t94": ("c", GDEY029T94), + "gdew029t5": ("c", GDEW029T5), "2.70in": ("b", WaveshareEPaper2P7In), "2.70in-b": ("b", WaveshareEPaper2P7InB), "2.70in-bv2": ("b", WaveshareEPaper2P7InBV2), diff --git a/esphome/components/waveshare_epaper/waveshare_epaper.cpp b/esphome/components/waveshare_epaper/waveshare_epaper.cpp index 7224aa44ed..5428f4ec80 100644 --- a/esphome/components/waveshare_epaper/waveshare_epaper.cpp +++ b/esphome/components/waveshare_epaper/waveshare_epaper.cpp @@ -1514,7 +1514,7 @@ void WaveshareEPaper2P9InV2R2::set_full_update_every(uint32_t full_update_every) // - https://github.com/adafruit/Adafruit_EPD/blob/master/src/panels/ThinkInk_290_Grayscale4_T5.h // ======================================================== -void GDEY029T94::initialize() { +void GDEW029T5::initialize() { // from https://www.waveshare.com/w/upload/b/bb/2.9inch-e-paper-b-specification.pdf, page 37 // EPD hardware init start this->reset_(); @@ -1560,7 +1560,7 @@ void GDEY029T94::initialize() { // EPD hardware init end } -void HOT GDEY029T94::display() { +void HOT GDEW029T5::display() { // COMMAND DATA START TRANSMISSION 2 (B/W only) this->command(0x13); delay(2); @@ -1580,11 +1580,11 @@ void HOT GDEY029T94::display() { // NOTE: power off < deep sleep this->command(0x02); } -int GDEY029T94::get_width_internal() { return 128; } -int GDEY029T94::get_height_internal() { return 296; } -void GDEY029T94::dump_config() { +int GDEW029T5::get_width_internal() { return 128; } +int GDEW029T5::get_height_internal() { return 296; } +void GDEW029T5::dump_config() { LOG_DISPLAY("", "Waveshare E-Paper (Good Display)", this); - ESP_LOGCONFIG(TAG, " Model: 2.9in Greyscale GDEY029T94"); + ESP_LOGCONFIG(TAG, " Model: 2.9in Greyscale GDEW029T5"); LOG_PIN(" Reset Pin: ", this->reset_pin_); LOG_PIN(" DC Pin: ", this->dc_pin_); LOG_PIN(" Busy Pin: ", this->busy_pin_); diff --git a/esphome/components/waveshare_epaper/waveshare_epaper.h b/esphome/components/waveshare_epaper/waveshare_epaper.h index 3c4470c30c..4a5844ae88 100644 --- a/esphome/components/waveshare_epaper/waveshare_epaper.h +++ b/esphome/components/waveshare_epaper/waveshare_epaper.h @@ -227,7 +227,7 @@ class WaveshareEPaper2P7InBV2 : public WaveshareEPaperBWR { int get_height_internal() override; }; -class GDEY029T94 : public WaveshareEPaper { +class GDEW029T5 : public WaveshareEPaper { public: void initialize() override; From 17c6bf57cdcdffe00af8578ec1c4fd3e00e6d451 Mon Sep 17 00:00:00 2001 From: august huber Date: Sun, 26 May 2024 15:40:38 -0400 Subject: [PATCH 1505/2101] [tuya] add support for extended services (#6808) --- esphome/components/tuya/tuya.cpp | 24 ++++++++++++++++++++++++ esphome/components/tuya/tuya.h | 7 +++++++ 2 files changed, 31 insertions(+) diff --git a/esphome/components/tuya/tuya.cpp b/esphome/components/tuya/tuya.cpp index 1cc9681d09..402953bb3b 100644 --- a/esphome/components/tuya/tuya.cpp +++ b/esphome/components/tuya/tuya.cpp @@ -269,6 +269,30 @@ void Tuya::handle_command_(uint8_t command, uint8_t version, const uint8_t *buff ESP_LOGV(TAG, "Network status requested, reported as %i", wifi_status); break; } + case TuyaCommandType::EXTENDED_SERVICES: { + uint8_t subcommand = buffer[0]; + switch ((TuyaExtendedServicesCommandType) subcommand) { + case TuyaExtendedServicesCommandType::RESET_NOTIFICATION: { + this->send_command_( + TuyaCommand{.cmd = TuyaCommandType::EXTENDED_SERVICES, + .payload = std::vector{ + static_cast(TuyaExtendedServicesCommandType::RESET_NOTIFICATION), 0x00}}); + ESP_LOGV(TAG, "Reset status notification enabled"); + break; + } + case TuyaExtendedServicesCommandType::MODULE_RESET: { + ESP_LOGE(TAG, "EXTENDED_SERVICES::MODULE_RESET is not handled"); + break; + } + case TuyaExtendedServicesCommandType::UPDATE_IN_PROGRESS: { + ESP_LOGE(TAG, "EXTENDED_SERVICES::UPDATE_IN_PROGRESS is not handled"); + break; + } + default: + ESP_LOGE(TAG, "Invalid extended services subcommand (0x%02X) received", subcommand); + } + break; + } default: ESP_LOGE(TAG, "Invalid command (0x%02X) received", command); } diff --git a/esphome/components/tuya/tuya.h b/esphome/components/tuya/tuya.h index 7dc405e3dd..6db417d474 100644 --- a/esphome/components/tuya/tuya.h +++ b/esphome/components/tuya/tuya.h @@ -60,6 +60,13 @@ enum class TuyaCommandType : uint8_t { WIFI_RSSI = 0x24, VACUUM_MAP_UPLOAD = 0x28, GET_NETWORK_STATUS = 0x2B, + EXTENDED_SERVICES = 0x34, +}; + +enum class TuyaExtendedServicesCommandType : uint8_t { + RESET_NOTIFICATION = 0x04, + MODULE_RESET = 0x05, + UPDATE_IN_PROGRESS = 0x0A, }; enum class TuyaInitState : uint8_t { From e285196709771e22a42b2eb0c69add723d546ca5 Mon Sep 17 00:00:00 2001 From: august huber Date: Sun, 26 May 2024 15:41:29 -0400 Subject: [PATCH 1506/2101] fix libretiny regression from #6715 (#6806) --- esphome/components/debug/debug_libretiny.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/debug/debug_libretiny.cpp b/esphome/components/debug/debug_libretiny.cpp index 725cd870ca..c3418cf96c 100644 --- a/esphome/components/debug/debug_libretiny.cpp +++ b/esphome/components/debug/debug_libretiny.cpp @@ -12,7 +12,7 @@ std::string DebugComponent::get_reset_reason_() { return lt_get_reboot_reason_na uint32_t DebugComponent::get_free_heap_() { return lt_heap_get_free(); } void DebugComponent::get_device_info_(std::string &device_info) { - reset_reason = get_reset_reason_(); + str::string reset_reason = get_reset_reason_(); ESP_LOGD(TAG, "LibreTiny Version: %s", lt_get_version()); ESP_LOGD(TAG, "Chip: %s (%04x) @ %u MHz", lt_cpu_get_model_name(), lt_cpu_get_model(), lt_cpu_get_freq_mhz()); ESP_LOGD(TAG, "Chip ID: 0x%06X", lt_cpu_get_mac_id()); From 6e4fd428e72ec5fb4d04802de1d0f8c65f1c961d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Poczkodi?= Date: Mon, 27 May 2024 22:19:22 +0200 Subject: [PATCH 1507/2101] [helpers] Move Base64 string to cpp (#6819) --- esphome/core/helpers.cpp | 4 ++++ esphome/core/helpers.h | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/core/helpers.cpp b/esphome/core/helpers.cpp index fdc0eed774..dee771d4e9 100644 --- a/esphome/core/helpers.cpp +++ b/esphome/core/helpers.cpp @@ -433,6 +433,10 @@ int8_t step_to_accuracy_decimals(float step) { return str.length() - dot_pos - 1; } +static const std::string BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + static inline bool is_base64(char c) { return (isalnum(c) || (c == '+') || (c == '/')); } std::string base64_encode(const std::vector &buf) { return base64_encode(buf.data(), buf.size()); } diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 809e7d6767..4af840f77b 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -435,10 +435,6 @@ std::string value_accuracy_to_string(float value, int8_t accuracy_decimals); /// Derive accuracy in decimals from an increment step. int8_t step_to_accuracy_decimals(float step); -static const std::string BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789+/"; - std::string base64_encode(const uint8_t *buf, size_t buf_len); std::string base64_encode(const std::vector &buf); From 54b51269ab465fb4f8f849f1f52b6b42977635c8 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 27 May 2024 07:15:05 +1200 Subject: [PATCH 1508/2101] [web_server_base] Bump ESPAsyncWebServer-esphome to 3.2.2 (#6797) Co-authored-by: Samuel Sieb --- esphome/components/web_server_base/__init__.py | 2 +- platformio.ini | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/web_server_base/__init__.py b/esphome/components/web_server_base/__init__.py index 1970b5a0c5..4f894619b0 100644 --- a/esphome/components/web_server_base/__init__.py +++ b/esphome/components/web_server_base/__init__.py @@ -37,4 +37,4 @@ async def to_code(config): cg.add_library("FS", None) cg.add_library("Update", None) # https://github.com/esphome/ESPAsyncWebServer/blob/master/library.json - cg.add_library("esphome/ESPAsyncWebServer-esphome", "3.2.0") + cg.add_library("esphome/ESPAsyncWebServer-esphome", "3.2.2") diff --git a/platformio.ini b/platformio.ini index d342b32b02..67a631dda8 100644 --- a/platformio.ini +++ b/platformio.ini @@ -58,7 +58,7 @@ lib_deps = SPI ; spi (Arduino built-in) Wire ; i2c (Arduino built-int) heman/AsyncMqttClient-esphome@1.0.0 ; mqtt - esphome/ESPAsyncWebServer-esphome@3.2.0 ; web_server_base + esphome/ESPAsyncWebServer-esphome@3.2.2 ; web_server_base fastled/FastLED@3.3.2 ; fastled_base mikalhart/TinyGPSPlus@1.0.2 ; gps freekode/TM1651@1.0.1 ; tm1651 From f07479419c30e3ae89fcdefff254601dbdedd36f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Poczkodi?= Date: Mon, 27 May 2024 22:19:22 +0200 Subject: [PATCH 1509/2101] [helpers] Move Base64 string to cpp (#6819) --- esphome/core/helpers.cpp | 4 ++++ esphome/core/helpers.h | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/core/helpers.cpp b/esphome/core/helpers.cpp index fdc0eed774..dee771d4e9 100644 --- a/esphome/core/helpers.cpp +++ b/esphome/core/helpers.cpp @@ -433,6 +433,10 @@ int8_t step_to_accuracy_decimals(float step) { return str.length() - dot_pos - 1; } +static const std::string BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + static inline bool is_base64(char c) { return (isalnum(c) || (c == '+') || (c == '/')); } std::string base64_encode(const std::vector &buf) { return base64_encode(buf.data(), buf.size()); } diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 809e7d6767..4af840f77b 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -435,10 +435,6 @@ std::string value_accuracy_to_string(float value, int8_t accuracy_decimals); /// Derive accuracy in decimals from an increment step. int8_t step_to_accuracy_decimals(float step); -static const std::string BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789+/"; - std::string base64_encode(const uint8_t *buf, size_t buf_len); std::string base64_encode(const std::vector &buf); From 4cd4b168b44e073c3e874ba625cc10b3bb7c9bae Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 28 May 2024 08:29:19 +1200 Subject: [PATCH 1510/2101] Bump version to 2024.5.4 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 0c53287909..ad5858dcf3 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.5.3" +__version__ = "2024.5.4" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 497cf8742f495918ed368eafdeafe72d53c5b9e2 Mon Sep 17 00:00:00 2001 From: pimdo <38102897+pimdo@users.noreply.github.com> Date: Tue, 28 May 2024 02:42:59 +0100 Subject: [PATCH 1511/2101] Make i2s_audio compatible with IDF 5+ (#6534) * Update i2s_audio.cpp Replace usage of I2S_NUM_MAX with I2S_NUM_1 * Update i2s_audio_microphone.cpp Replace I2S_MCLK_MULTIPLE_DEFAULT with I2S_MCLK_MULTIPLE_256 * Update i2s_audio_speaker.cpp Replace I2S_MCLK_MULTIPLE_DEFAULT with I2S_MCLK_MULTIPLE_256 * Update voice_assistant.cpp Fix msg.event_type format * check SOC_I2S_NUM for c3 * use I2S_NUM_AUTO * Update i2s_audio.cpp * Couple tweaks * Why did they take away I2S_NUM_MAX Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --------- Co-authored-by: Keith Burzinski Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/i2s_audio/i2s_audio.cpp | 4 ++++ .../components/i2s_audio/microphone/i2s_audio_microphone.cpp | 2 +- esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp | 2 +- esphome/components/voice_assistant/voice_assistant.cpp | 5 +++-- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/esphome/components/i2s_audio/i2s_audio.cpp b/esphome/components/i2s_audio/i2s_audio.cpp index c1a608c064..ad73b383fe 100644 --- a/esphome/components/i2s_audio/i2s_audio.cpp +++ b/esphome/components/i2s_audio/i2s_audio.cpp @@ -9,6 +9,10 @@ namespace i2s_audio { static const char *const TAG = "i2s_audio"; +#if defined(USE_ESP_IDF) && (ESP_IDF_VERSION_MAJOR >= 5) +static const uint8_t I2S_NUM_MAX = SOC_I2S_NUM; // because IDF 5+ took this away :( +#endif + void I2SAudioComponent::setup() { static i2s_port_t next_port_num = I2S_NUM_0; diff --git a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp index 1475df0975..a672348d85 100644 --- a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +++ b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp @@ -57,7 +57,7 @@ void I2SAudioMicrophone::start_() { .use_apll = this->use_apll_, .tx_desc_auto_clear = false, .fixed_mclk = 0, - .mclk_multiple = I2S_MCLK_MULTIPLE_DEFAULT, + .mclk_multiple = I2S_MCLK_MULTIPLE_256, .bits_per_chan = I2S_BITS_PER_CHAN_DEFAULT, }; diff --git a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp index 95e63035fe..69536742cb 100644 --- a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +++ b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp @@ -51,7 +51,7 @@ void I2SAudioSpeaker::player_task(void *params) { .use_apll = false, .tx_desc_auto_clear = true, .fixed_mclk = I2S_PIN_NO_CHANGE, - .mclk_multiple = I2S_MCLK_MULTIPLE_DEFAULT, + .mclk_multiple = I2S_MCLK_MULTIPLE_256, .bits_per_chan = I2S_BITS_PER_CHAN_DEFAULT, }; #if SOC_I2S_SUPPORTS_DAC diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index 59ba39c527..712a0ab137 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -4,6 +4,7 @@ #include "esphome/core/log.h" +#include #include namespace esphome { @@ -622,7 +623,7 @@ void VoiceAssistant::signal_stop_() { } void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { - ESP_LOGD(TAG, "Event Type: %d", msg.event_type); + ESP_LOGD(TAG, "Event Type: %" PRId32, msg.event_type); switch (msg.event_type) { case api::enums::VOICE_ASSISTANT_RUN_START: ESP_LOGD(TAG, "Assist Pipeline running"); @@ -785,7 +786,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { this->defer([this]() { this->stt_vad_end_trigger_->trigger(); }); break; default: - ESP_LOGD(TAG, "Unhandled event type: %d", msg.event_type); + ESP_LOGD(TAG, "Unhandled event type: %" PRId32, msg.event_type); break; } } From db6f6f0cb7d1df10ac10b37e6dac46a0747406b7 Mon Sep 17 00:00:00 2001 From: DAVe3283 Date: Tue, 28 May 2024 13:40:34 -0600 Subject: [PATCH 1512/2101] Fix compile errors on ESP32-C6 with latest ESP-IDF (#6822) * Use PRI macros to fix ESP32-C6 compile * Fix compile error on latest ESP-IDF framework & platform --- esphome/components/ade7880/ade7880.cpp | 23 +++++++------- .../components/ade7953_base/ade7953_base.cpp | 3 +- .../fingerprint_grow/fingerprint_grow.cpp | 14 ++++----- esphome/components/he60r/he60r.cpp | 3 +- esphome/components/mhz19/mhz19.cpp | 5 +-- .../remote_base/abbwelcome_protocol.h | 4 ++- .../remote_base/byronsx_protocol.cpp | 22 +++++++------ .../remote_base/drayton_protocol.cpp | 17 +++++----- .../remote_base/keeloq_protocol.cpp | 31 ++++++++++--------- .../uart/uart_component_esp_idf.cpp | 2 +- esphome/components/xgzp68xx/xgzp68xx.cpp | 5 +-- 11 files changed, 73 insertions(+), 56 deletions(-) diff --git a/esphome/components/ade7880/ade7880.cpp b/esphome/components/ade7880/ade7880.cpp index 31b72d51a6..a03f1227f1 100644 --- a/esphome/components/ade7880/ade7880.cpp +++ b/esphome/components/ade7880/ade7880.cpp @@ -10,6 +10,7 @@ #include "ade7880.h" #include "ade7880_registers.h" #include "esphome/core/log.h" +#include namespace esphome { namespace ade7880 { @@ -156,7 +157,7 @@ void ADE7880::update() { }); } - ESP_LOGD(TAG, "update took %u ms", millis() - start); + ESP_LOGD(TAG, "update took %" PRIu32 " ms", millis() - start); } void ADE7880::dump_config() { @@ -176,9 +177,9 @@ void ADE7880::dump_config() { LOG_SENSOR(" ", "Forward Active Energy", this->channel_a_->forward_active_energy); LOG_SENSOR(" ", "Reverse Active Energy", this->channel_a_->reverse_active_energy); ESP_LOGCONFIG(TAG, " Calibration:"); - ESP_LOGCONFIG(TAG, " Current: %u", this->channel_a_->current_gain_calibration); - ESP_LOGCONFIG(TAG, " Voltage: %d", this->channel_a_->voltage_gain_calibration); - ESP_LOGCONFIG(TAG, " Power: %d", this->channel_a_->power_gain_calibration); + ESP_LOGCONFIG(TAG, " Current: %" PRId32, this->channel_a_->current_gain_calibration); + ESP_LOGCONFIG(TAG, " Voltage: %" PRId32, this->channel_a_->voltage_gain_calibration); + ESP_LOGCONFIG(TAG, " Power: %" PRId32, this->channel_a_->power_gain_calibration); ESP_LOGCONFIG(TAG, " Phase Angle: %u", this->channel_a_->phase_angle_calibration); } @@ -192,9 +193,9 @@ void ADE7880::dump_config() { LOG_SENSOR(" ", "Forward Active Energy", this->channel_b_->forward_active_energy); LOG_SENSOR(" ", "Reverse Active Energy", this->channel_b_->reverse_active_energy); ESP_LOGCONFIG(TAG, " Calibration:"); - ESP_LOGCONFIG(TAG, " Current: %u", this->channel_b_->current_gain_calibration); - ESP_LOGCONFIG(TAG, " Voltage: %d", this->channel_b_->voltage_gain_calibration); - ESP_LOGCONFIG(TAG, " Power: %d", this->channel_b_->power_gain_calibration); + ESP_LOGCONFIG(TAG, " Current: %" PRId32, this->channel_b_->current_gain_calibration); + ESP_LOGCONFIG(TAG, " Voltage: %" PRId32, this->channel_b_->voltage_gain_calibration); + ESP_LOGCONFIG(TAG, " Power: %" PRId32, this->channel_b_->power_gain_calibration); ESP_LOGCONFIG(TAG, " Phase Angle: %u", this->channel_b_->phase_angle_calibration); } @@ -208,9 +209,9 @@ void ADE7880::dump_config() { LOG_SENSOR(" ", "Forward Active Energy", this->channel_c_->forward_active_energy); LOG_SENSOR(" ", "Reverse Active Energy", this->channel_c_->reverse_active_energy); ESP_LOGCONFIG(TAG, " Calibration:"); - ESP_LOGCONFIG(TAG, " Current: %u", this->channel_c_->current_gain_calibration); - ESP_LOGCONFIG(TAG, " Voltage: %d", this->channel_c_->voltage_gain_calibration); - ESP_LOGCONFIG(TAG, " Power: %d", this->channel_c_->power_gain_calibration); + ESP_LOGCONFIG(TAG, " Current: %" PRId32, this->channel_c_->current_gain_calibration); + ESP_LOGCONFIG(TAG, " Voltage: %" PRId32, this->channel_c_->voltage_gain_calibration); + ESP_LOGCONFIG(TAG, " Power: %" PRId32, this->channel_c_->power_gain_calibration); ESP_LOGCONFIG(TAG, " Phase Angle: %u", this->channel_c_->phase_angle_calibration); } @@ -218,7 +219,7 @@ void ADE7880::dump_config() { ESP_LOGCONFIG(TAG, " Neutral:"); LOG_SENSOR(" ", "Current", this->channel_n_->current); ESP_LOGCONFIG(TAG, " Calibration:"); - ESP_LOGCONFIG(TAG, " Current: %u", this->channel_n_->current_gain_calibration); + ESP_LOGCONFIG(TAG, " Current: %" PRId32, this->channel_n_->current_gain_calibration); } LOG_I2C_DEVICE(this); diff --git a/esphome/components/ade7953_base/ade7953_base.cpp b/esphome/components/ade7953_base/ade7953_base.cpp index 862f5567a8..79161c5676 100644 --- a/esphome/components/ade7953_base/ade7953_base.cpp +++ b/esphome/components/ade7953_base/ade7953_base.cpp @@ -1,5 +1,6 @@ #include "ade7953_base.h" #include "esphome/core/log.h" +#include namespace esphome { namespace ade7953_base { @@ -105,7 +106,7 @@ void ADE7953::update() { this->last_update_ = now; // prevent DIV/0 pf = ADE_WATTSEC_POWER_FACTOR * (diff < 10 ? 10 : diff) / 1000; - ESP_LOGVV(TAG, "ADE7953::update() diff=%d pf=%f", diff, pf); + ESP_LOGVV(TAG, "ADE7953::update() diff=%" PRIu32 " pf=%f", diff, pf); } // Apparent power diff --git a/esphome/components/fingerprint_grow/fingerprint_grow.cpp b/esphome/components/fingerprint_grow/fingerprint_grow.cpp index bd0817350a..8f58db9159 100644 --- a/esphome/components/fingerprint_grow/fingerprint_grow.cpp +++ b/esphome/components/fingerprint_grow/fingerprint_grow.cpp @@ -541,34 +541,34 @@ void FingerprintGrowComponent::dump_config() { ESP_LOGCONFIG(TAG, " Sensor Power Pin: %s", this->has_power_pin_ ? this->sensor_power_pin_->dump_summary().c_str() : "None"); if (this->idle_period_to_sleep_ms_ < UINT32_MAX) { - ESP_LOGCONFIG(TAG, " Idle Period to Sleep: %u ms", this->idle_period_to_sleep_ms_); + ESP_LOGCONFIG(TAG, " Idle Period to Sleep: %" PRIu32 " ms", this->idle_period_to_sleep_ms_); } else { ESP_LOGCONFIG(TAG, " Idle Period to Sleep: Never"); } LOG_UPDATE_INTERVAL(this); if (this->fingerprint_count_sensor_) { LOG_SENSOR(" ", "Fingerprint Count", this->fingerprint_count_sensor_); - ESP_LOGCONFIG(TAG, " Current Value: %d", (uint16_t) this->fingerprint_count_sensor_->get_state()); + ESP_LOGCONFIG(TAG, " Current Value: %u", (uint16_t) this->fingerprint_count_sensor_->get_state()); } if (this->status_sensor_) { LOG_SENSOR(" ", "Status", this->status_sensor_); - ESP_LOGCONFIG(TAG, " Current Value: %d", (uint8_t) this->status_sensor_->get_state()); + ESP_LOGCONFIG(TAG, " Current Value: %u", (uint8_t) this->status_sensor_->get_state()); } if (this->capacity_sensor_) { LOG_SENSOR(" ", "Capacity", this->capacity_sensor_); - ESP_LOGCONFIG(TAG, " Current Value: %d", (uint16_t) this->capacity_sensor_->get_state()); + ESP_LOGCONFIG(TAG, " Current Value: %u", (uint16_t) this->capacity_sensor_->get_state()); } if (this->security_level_sensor_) { LOG_SENSOR(" ", "Security Level", this->security_level_sensor_); - ESP_LOGCONFIG(TAG, " Current Value: %d", (uint8_t) this->security_level_sensor_->get_state()); + ESP_LOGCONFIG(TAG, " Current Value: %u", (uint8_t) this->security_level_sensor_->get_state()); } if (this->last_finger_id_sensor_) { LOG_SENSOR(" ", "Last Finger ID", this->last_finger_id_sensor_); - ESP_LOGCONFIG(TAG, " Current Value: %d", (uint32_t) this->last_finger_id_sensor_->get_state()); + ESP_LOGCONFIG(TAG, " Current Value: %" PRIu32, (uint32_t) this->last_finger_id_sensor_->get_state()); } if (this->last_confidence_sensor_) { LOG_SENSOR(" ", "Last Confidence", this->last_confidence_sensor_); - ESP_LOGCONFIG(TAG, " Current Value: %d", (uint32_t) this->last_confidence_sensor_->get_state()); + ESP_LOGCONFIG(TAG, " Current Value: %" PRIu32, (uint32_t) this->last_confidence_sensor_->get_state()); } } diff --git a/esphome/components/he60r/he60r.cpp b/esphome/components/he60r/he60r.cpp index d6e6122b1b..96ad1f04be 100644 --- a/esphome/components/he60r/he60r.cpp +++ b/esphome/components/he60r/he60r.cpp @@ -1,6 +1,7 @@ #include "he60r.h" #include "esphome/core/hal.h" #include "esphome/core/log.h" +#include namespace esphome { namespace he60r { @@ -127,7 +128,7 @@ void HE60rCover::update_() { if (toggles_needed_ != 0) { if ((this->counter_++ & 0x3) == 0) { toggles_needed_--; - ESP_LOGD(TAG, "Writing byte 0x30, still needed=%d", toggles_needed_); + ESP_LOGD(TAG, "Writing byte 0x30, still needed=%" PRIu32, toggles_needed_); this->write_byte(TOGGLE_BYTE); } else { this->write_byte(QUERY_BYTE); diff --git a/esphome/components/mhz19/mhz19.cpp b/esphome/components/mhz19/mhz19.cpp index 019f6cee51..574aee1bd5 100644 --- a/esphome/components/mhz19/mhz19.cpp +++ b/esphome/components/mhz19/mhz19.cpp @@ -1,5 +1,6 @@ #include "mhz19.h" #include "esphome/core/log.h" +#include namespace esphome { namespace mhz19 { @@ -32,7 +33,7 @@ void MHZ19Component::update() { uint32_t now_ms = millis(); uint32_t warmup_ms = this->warmup_seconds_ * 1000; if (now_ms < warmup_ms) { - ESP_LOGW(TAG, "MHZ19 warming up, %ds left", (warmup_ms - now_ms) / 1000); + ESP_LOGW(TAG, "MHZ19 warming up, %" PRIu32 " s left", (warmup_ms - now_ms) / 1000); this->status_set_warning(); return; } @@ -110,7 +111,7 @@ void MHZ19Component::dump_config() { ESP_LOGCONFIG(TAG, " Automatic baseline calibration disabled on boot"); } - ESP_LOGCONFIG(TAG, " Warmup seconds: %ds", this->warmup_seconds_); + ESP_LOGCONFIG(TAG, " Warmup time: %" PRIu32 " s", this->warmup_seconds_); } } // namespace mhz19 diff --git a/esphome/components/remote_base/abbwelcome_protocol.h b/esphome/components/remote_base/abbwelcome_protocol.h index 0493993926..f2d0f5b547 100644 --- a/esphome/components/remote_base/abbwelcome_protocol.h +++ b/esphome/components/remote_base/abbwelcome_protocol.h @@ -4,6 +4,7 @@ #include "esphome/core/helpers.h" #include "remote_base.h" #include +#include #include #include @@ -144,7 +145,8 @@ class ABBWelcomeData { std::string to_string(uint8_t max_print_bytes = 255) const { std::string info; if (this->is_valid()) { - info = str_sprintf(this->get_three_byte_address() ? "[%06X %s %06X] Type: %02X" : "[%04X %s %04X] Type: %02X", + info = str_sprintf(this->get_three_byte_address() ? "[%06" PRIX32 " %s %06" PRIX32 "] Type: %02X" + : "[%04" PRIX32 " %s %04" PRIX32 "] Type: %02X", this->get_source_address(), this->get_retransmission() ? "»" : ">", this->get_destination_address(), this->get_message_type()); if (this->get_data_size()) diff --git a/esphome/components/remote_base/byronsx_protocol.cpp b/esphome/components/remote_base/byronsx_protocol.cpp index 3096283b30..2d4c60ff8b 100644 --- a/esphome/components/remote_base/byronsx_protocol.cpp +++ b/esphome/components/remote_base/byronsx_protocol.cpp @@ -1,5 +1,6 @@ #include "byronsx_protocol.h" #include "esphome/core/log.h" +#include namespace esphome { namespace remote_base { @@ -57,7 +58,7 @@ void ByronSXProtocol::encode(RemoteTransmitData *dst, const ByronSXData &data) { out_data <<= NBITS_COMMAND; out_data |= data.command; - ESP_LOGV(TAG, "Send ByronSX: out_data %03x", out_data); + ESP_LOGV(TAG, "Send ByronSX: out_data %03" PRIx32, out_data); // Initial Mark start bit dst->mark(1 * BIT_TIME_US); @@ -90,13 +91,16 @@ optional ByronSXProtocol::decode(RemoteReceiveData src) { return {}; } - ESP_LOGVV(TAG, "%3d: %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d", src.size(), src.peek(0), - src.peek(1), src.peek(2), src.peek(3), src.peek(4), src.peek(5), src.peek(6), src.peek(7), src.peek(8), - src.peek(9), src.peek(10), src.peek(11), src.peek(12), src.peek(13), src.peek(14), src.peek(15), - src.peek(16), src.peek(17), src.peek(18), src.peek(19)); + ESP_LOGVV(TAG, + "%3" PRId32 ": %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 + " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 + " %" PRId32 " %" PRId32 " %" PRId32, + src.size(), src.peek(0), src.peek(1), src.peek(2), src.peek(3), src.peek(4), src.peek(5), src.peek(6), + src.peek(7), src.peek(8), src.peek(9), src.peek(10), src.peek(11), src.peek(12), src.peek(13), src.peek(14), + src.peek(15), src.peek(16), src.peek(17), src.peek(18), src.peek(19)); - ESP_LOGVV(TAG, " %d %d %d %d %d %d", src.peek(20), src.peek(21), src.peek(22), src.peek(23), src.peek(24), - src.peek(25)); + ESP_LOGVV(TAG, " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32, src.peek(20), + src.peek(21), src.peek(22), src.peek(23), src.peek(24), src.peek(25)); // Read data bits uint32_t out_data = 0; @@ -107,10 +111,10 @@ optional ByronSXProtocol::decode(RemoteReceiveData src) { } else if (src.expect_space(BIT_TIME_US) && src.expect_mark(2 * BIT_TIME_US)) { out_data |= 0 << bit; } else { - ESP_LOGV(TAG, "Decode ByronSX: Fail 2, %2d %08x", bit, out_data); + ESP_LOGV(TAG, "Decode ByronSX: Fail 2, %2d %08" PRIx32, bit, out_data); return {}; } - ESP_LOGVV(TAG, "Decode ByronSX: Data, %2d %08x", bit, out_data); + ESP_LOGVV(TAG, "Decode ByronSX: Data, %2d %08" PRIx32, bit, out_data); } // last bit followed by a long space diff --git a/esphome/components/remote_base/drayton_protocol.cpp b/esphome/components/remote_base/drayton_protocol.cpp index acfb7a0f16..73c0fb116c 100644 --- a/esphome/components/remote_base/drayton_protocol.cpp +++ b/esphome/components/remote_base/drayton_protocol.cpp @@ -151,12 +151,12 @@ optional DraytonProtocol::decode(RemoteReceiveData src) { // Look for sync pulse, after. If sucessful index points to space of sync symbol while (src.size() - src.get_index() >= MIN_RX_SRC) { - ESP_LOGVV(TAG, "Decode Drayton: sync search %d, %" PRId32 " %" PRId32, src.size() - src.get_index(), src.peek(), - src.peek(1)); + ESP_LOGVV(TAG, "Decode Drayton: sync search %" PRIu32 ", %" PRId32 " %" PRId32, src.size() - src.get_index(), + src.peek(), src.peek(1)); if (src.peek_mark(2 * BIT_TIME_US) && (src.peek_space(2 * BIT_TIME_US, 1) || src.peek_space(3 * BIT_TIME_US, 1))) { src.advance(1); - ESP_LOGVV(TAG, "Decode Drayton: Found SYNC, - %d", src.get_index()); + ESP_LOGVV(TAG, "Decode Drayton: Found SYNC, - %" PRIu32, src.get_index()); break; } else { src.advance(2); @@ -174,14 +174,16 @@ optional DraytonProtocol::decode(RemoteReceiveData src) { // Checks next bit to leave index pointing correctly uint32_t out_data = 0; uint8_t bit = NDATABITS - 1; - ESP_LOGVV(TAG, "Decode Drayton: first bit %d %" PRId32 ", %" PRId32, src.peek(0), src.peek(1), src.peek(2)); + ESP_LOGVV(TAG, "Decode Drayton: first bit %" PRId32 " %" PRId32 ", %" PRId32, src.peek(0), src.peek(1), + src.peek(2)); if (src.expect_space(3 * BIT_TIME_US) && (src.expect_mark(BIT_TIME_US) || src.peek_mark(2 * BIT_TIME_US))) { out_data |= 0 << bit; } else if (src.expect_space(2 * BIT_TIME_US) && src.expect_mark(BIT_TIME_US) && (src.expect_space(BIT_TIME_US) || src.peek_space(2 * BIT_TIME_US))) { out_data |= 1 << bit; } else { - ESP_LOGV(TAG, "Decode Drayton: Fail 2, - %d %d %d", src.peek(-1), src.peek(0), src.peek(1)); + ESP_LOGV(TAG, "Decode Drayton: Fail 2, - %" PRId32 " %" PRId32 " %" PRId32, src.peek(-1), src.peek(0), + src.peek(1)); continue; } @@ -202,7 +204,8 @@ optional DraytonProtocol::decode(RemoteReceiveData src) { } if (bit > 0) { - ESP_LOGVV(TAG, "Decode Drayton: Fail 3, %d %" PRId32 " %" PRId32, src.peek(-1), src.peek(0), src.peek(1)); + ESP_LOGVV(TAG, "Decode Drayton: Fail 3, %" PRId32 " %" PRId32 " %" PRId32, src.peek(-1), src.peek(0), + src.peek(1)); continue; } @@ -214,7 +217,7 @@ optional DraytonProtocol::decode(RemoteReceiveData src) { continue; } - ESP_LOGV(TAG, "Decode Drayton: Data, %2d %08x", bit, out_data); + ESP_LOGV(TAG, "Decode Drayton: Data, %2d %08" PRIx32, bit, out_data); out.channel = (uint8_t) (out_data & 0x1F); out_data >>= NBITS_CHANNEL; diff --git a/esphome/components/remote_base/keeloq_protocol.cpp b/esphome/components/remote_base/keeloq_protocol.cpp index 09d9ea4f53..72540c37f1 100644 --- a/esphome/components/remote_base/keeloq_protocol.cpp +++ b/esphome/components/remote_base/keeloq_protocol.cpp @@ -52,7 +52,7 @@ void KeeloqProtocol::encode(RemoteTransmitData *dst, const KeeloqData &data) { // Encrypted field out_data = data.encrypted; - ESP_LOGV(TAG, "Send Keeloq: Encrypted data %04x", out_data); + ESP_LOGV(TAG, "Send Keeloq: Encrypted data %04" PRIx32, out_data); for (uint32_t mask = 1, cnt = 0; cnt < NBITS_ENCRYPTED_DATA; cnt++, mask <<= 1) { if (out_data & mask) { @@ -68,7 +68,7 @@ void KeeloqProtocol::encode(RemoteTransmitData *dst, const KeeloqData &data) { out_data = (data.command & 0x0f); out_data <<= NBITS_SERIAL; out_data |= data.address; - ESP_LOGV(TAG, "Send Keeloq: Fixed data %04x", out_data); + ESP_LOGV(TAG, "Send Keeloq: Fixed data %04" PRIx32, out_data); for (uint32_t mask = 1, cnt = 0; cnt < (NBITS_FIXED_DATA - 2); cnt++, mask <<= 1) { if (out_data & mask) { @@ -111,21 +111,24 @@ optional KeeloqProtocol::decode(RemoteReceiveData src) { return {}; } - ESP_LOGVV(TAG, "%2d: %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d", src.size(), src.peek(0), - src.peek(1), src.peek(2), src.peek(3), src.peek(4), src.peek(5), src.peek(6), src.peek(7), src.peek(8), - src.peek(9), src.peek(10), src.peek(11), src.peek(12), src.peek(13), src.peek(14), src.peek(15), - src.peek(16), src.peek(17), src.peek(18), src.peek(19)); + ESP_LOGVV(TAG, + "%2" PRId32 ": %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 + " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 + " %" PRId32 " %" PRId32 " %" PRId32, + src.size(), src.peek(0), src.peek(1), src.peek(2), src.peek(3), src.peek(4), src.peek(5), src.peek(6), + src.peek(7), src.peek(8), src.peek(9), src.peek(10), src.peek(11), src.peek(12), src.peek(13), src.peek(14), + src.peek(15), src.peek(16), src.peek(17), src.peek(18), src.peek(19)); // Check preamble bits int8_t bit = NBITS_PREAMBLE - 1; while (--bit >= 0) { if (!src.expect_mark(BIT_TIME_US) || !src.expect_space(BIT_TIME_US)) { - ESP_LOGV(TAG, "Decode KeeLoq: Fail 1, %d %d", bit + 1, src.peek()); + ESP_LOGV(TAG, "Decode KeeLoq: Fail 1, %d %" PRId32, bit + 1, src.peek()); return {}; } } if (!src.expect_mark(BIT_TIME_US) || !src.expect_space(10 * BIT_TIME_US)) { - ESP_LOGV(TAG, "Decode KeeLoq: Fail 1, %d %d", bit + 1, src.peek()); + ESP_LOGV(TAG, "Decode KeeLoq: Fail 1, %d %" PRId32, bit + 1, src.peek()); return {}; } @@ -137,11 +140,11 @@ optional KeeloqProtocol::decode(RemoteReceiveData src) { } else if (src.expect_mark(BIT_TIME_US) && src.expect_space(2 * BIT_TIME_US)) { out_data |= 1 << bit; } else { - ESP_LOGV(TAG, "Decode KeeLoq: Fail 2, %d %d", src.get_index(), src.peek()); + ESP_LOGV(TAG, "Decode KeeLoq: Fail 2, %" PRIu32 " %" PRId32, src.get_index(), src.peek()); return {}; } } - ESP_LOGVV(TAG, "Decode KeeLoq: Data, %d %08x", bit, out_data); + ESP_LOGVV(TAG, "Decode KeeLoq: Data, %d %08" PRIx32, bit, out_data); out.encrypted = out_data; // Read Serial Number and Button Status @@ -152,11 +155,11 @@ optional KeeloqProtocol::decode(RemoteReceiveData src) { } else if (src.expect_mark(BIT_TIME_US) && src.expect_space(2 * BIT_TIME_US)) { out_data |= 1 << bit; } else { - ESP_LOGV(TAG, "Decode KeeLoq: Fail 3, %d %d", src.get_index(), src.peek()); + ESP_LOGV(TAG, "Decode KeeLoq: Fail 3, %" PRIu32 " %" PRId32, src.get_index(), src.peek()); return {}; } } - ESP_LOGVV(TAG, "Decode KeeLoq: Data, %2d %08x", bit, out_data); + ESP_LOGVV(TAG, "Decode KeeLoq: Data, %2d %08" PRIx32, bit, out_data); out.command = (out_data >> 28) & 0xf; out.address = out_data & 0xfffffff; @@ -166,7 +169,7 @@ optional KeeloqProtocol::decode(RemoteReceiveData src) { } else if (src.expect_mark(BIT_TIME_US) && src.expect_space(2 * BIT_TIME_US)) { out.vlow = true; } else { - ESP_LOGV(TAG, "Decode KeeLoq: Fail 4, %08x", src.peek()); + ESP_LOGV(TAG, "Decode KeeLoq: Fail 4, %" PRId32, src.peek()); return {}; } @@ -176,7 +179,7 @@ optional KeeloqProtocol::decode(RemoteReceiveData src) { } else if (src.expect_mark(BIT_TIME_US) && src.peek_space_at_least(2 * BIT_TIME_US)) { out.repeat = true; } else { - ESP_LOGV(TAG, "Decode KeeLoq: Fail 5, %08x", src.peek()); + ESP_LOGV(TAG, "Decode KeeLoq: Fail 5, %" PRId32, src.peek()); return {}; } diff --git a/esphome/components/uart/uart_component_esp_idf.cpp b/esphome/components/uart/uart_component_esp_idf.cpp index 2dd6ab105f..c66753b0c4 100644 --- a/esphome/components/uart/uart_component_esp_idf.cpp +++ b/esphome/components/uart/uart_component_esp_idf.cpp @@ -69,7 +69,7 @@ void IDFUARTComponent::setup() { this->mark_failed(); return; } - this->uart_num_ = next_uart_num++; + this->uart_num_ = static_cast(next_uart_num++); ESP_LOGCONFIG(TAG, "Setting up UART %u...", this->uart_num_); this->lock_ = xSemaphoreCreateMutex(); diff --git a/esphome/components/xgzp68xx/xgzp68xx.cpp b/esphome/components/xgzp68xx/xgzp68xx.cpp index ea3583c3c5..dff00fb696 100644 --- a/esphome/components/xgzp68xx/xgzp68xx.cpp +++ b/esphome/components/xgzp68xx/xgzp68xx.cpp @@ -3,6 +3,7 @@ #include "esphome/core/hal.h" #include "esphome/core/helpers.h" #include "esphome/components/i2c/i2c.h" +#include namespace esphome { namespace xgzp68xx { @@ -37,8 +38,8 @@ void XGZP68XXComponent::update() { temperature_raw = encode_uint16(data[3], data[4]); // Convert the pressure data to hPa - ESP_LOGV(TAG, "Got raw pressure=%d, raw temperature=%d ", pressure_raw, temperature_raw); - ESP_LOGV(TAG, "K value is %d ", this->k_value_); + ESP_LOGV(TAG, "Got raw pressure=%" PRIu32 ", raw temperature=%u", pressure_raw, temperature_raw); + ESP_LOGV(TAG, "K value is %u", this->k_value_); // The most significant bit of both pressure and temperature will be 1 to indicate a negative value. // This is directly from the datasheet, and the calculations below will handle this. From 06996def725aececb406739857f59873f72271ca Mon Sep 17 00:00:00 2001 From: DAVe3283 Date: Tue, 28 May 2024 14:44:47 -0600 Subject: [PATCH 1513/2101] Use uint8_t instead of uint32_t for 8-bit values on mitsubishi (#6824) This solves some printf formatting issues on ESP-IDF and saves RAM on all platforms. --- esphome/components/mitsubishi/mitsubishi.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/mitsubishi/mitsubishi.cpp b/esphome/components/mitsubishi/mitsubishi.cpp index 081c24a050..fd57adc586 100644 --- a/esphome/components/mitsubishi/mitsubishi.cpp +++ b/esphome/components/mitsubishi/mitsubishi.cpp @@ -6,7 +6,7 @@ namespace mitsubishi { static const char *const TAG = "mitsubishi.climate"; -const uint32_t MITSUBISHI_OFF = 0x00; +const uint8_t MITSUBISHI_OFF = 0x00; const uint8_t MITSUBISHI_MODE_AUTO = 0x20; const uint8_t MITSUBISHI_MODE_COOL = 0x18; @@ -109,8 +109,8 @@ void MitsubishiClimate::transmit_state() { // Byte 15: HVAC specfic, i.e. POWERFUL, SMART SET, PLASMA, always 0x00 // Byte 16: Constant 0x00 // Byte 17: Checksum: SUM[Byte0...Byte16] - uint32_t remote_state[18] = {0x23, 0xCB, 0x26, 0x01, 0x00, 0x20, 0x08, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t remote_state[18] = {0x23, 0xCB, 0x26, 0x01, 0x00, 0x20, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; switch (this->mode) { case climate::CLIMATE_MODE_HEAT: @@ -249,7 +249,7 @@ void MitsubishiClimate::transmit_state() { data->set_carrier_frequency(38000); // repeat twice - for (uint16_t r = 0; r < 2; r++) { + for (uint8_t r = 0; r < 2; r++) { // Header data->mark(MITSUBISHI_HEADER_MARK); data->space(MITSUBISHI_HEADER_SPACE); From 2b691ad5adde275544f1e7896463083a84f028af Mon Sep 17 00:00:00 2001 From: Frederik <5511687+fightforlife@users.noreply.github.com> Date: Wed, 29 May 2024 00:02:45 +0200 Subject: [PATCH 1514/2101] Make SPI Ethernet (W5500) compatible with ESP-IDF v5 (#6778) * change MAC PHY init order according to IDF examples * add idfv5 specific w5500 config init * esp_mac.h needs to be included directly starting with idf5 * Header fix * Couple tweaks --------- Co-authored-by: Keith Burzinski --- esphome/components/ethernet/ethernet_component.cpp | 8 ++++++-- esphome/components/ethernet/ethernet_component.h | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index 3af462d593..2a4e5cbad3 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -98,11 +98,15 @@ void EthernetComponent::setup() { .post_cb = nullptr, }; +#if USE_ESP_IDF && (ESP_IDF_VERSION_MAJOR >= 5) + eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(host, &devcfg); +#else spi_device_handle_t spi_handle = nullptr; err = spi_bus_add_device(host, &devcfg, &spi_handle); ESPHL_ERROR_CHECK(err, "SPI bus add device error"); eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(spi_handle); +#endif w5500_config.int_gpio_num = this->interrupt_pin_; phy_config.phy_addr = this->phy_addr_spi_; phy_config.reset_gpio_num = this->reset_pin_; @@ -614,14 +618,14 @@ void EthernetComponent::rtl8201_set_rmii_mode_(esp_eth_mac_t *mac) { err = mac->read_phy_reg(mac, this->phy_addr_, RTL8201_RMSR_REG_ADDR, &(phy_rmii_mode)); ESPHL_ERROR_CHECK(err, "Read PHY RMSR Register failed"); - ESP_LOGV(TAG, "Hardware default RTL8201 RMII Mode Register is: 0x%04X", phy_rmii_mode); + ESP_LOGV(TAG, "Hardware default RTL8201 RMII Mode Register is: 0x%04" PRIX32, phy_rmii_mode); err = mac->write_phy_reg(mac, this->phy_addr_, RTL8201_RMSR_REG_ADDR, 0x1FFA); ESPHL_ERROR_CHECK(err, "Setting Register 16 RMII Mode Setting failed"); err = mac->read_phy_reg(mac, this->phy_addr_, RTL8201_RMSR_REG_ADDR, &(phy_rmii_mode)); ESPHL_ERROR_CHECK(err, "Read PHY RMSR Register failed"); - ESP_LOGV(TAG, "Setting RTL8201 RMII Mode Register to: 0x%04X", phy_rmii_mode); + ESP_LOGV(TAG, "Setting RTL8201 RMII Mode Register to: 0x%04" PRIX32, phy_rmii_mode); err = mac->write_phy_reg(mac, this->phy_addr_, 0x1f, 0x0); ESPHL_ERROR_CHECK(err, "Setting Page 0 failed"); diff --git a/esphome/components/ethernet/ethernet_component.h b/esphome/components/ethernet/ethernet_component.h index 6276885fd1..3705e3e06a 100644 --- a/esphome/components/ethernet/ethernet_component.h +++ b/esphome/components/ethernet/ethernet_component.h @@ -10,6 +10,7 @@ #include "esp_eth.h" #include "esp_eth_mac.h" #include "esp_netif.h" +#include "esp_mac.h" namespace esphome { namespace ethernet { From ec3164f80058c43ea21d7bc5c7f62bdf7679703f Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Wed, 29 May 2024 14:36:49 +1000 Subject: [PATCH 1515/2101] [wake_on_lan] Make component platform independent (#6815) --- CODEOWNERS | 2 +- .../components/socket/lwip_raw_tcp_impl.cpp | 3 +- esphome/components/wake_on_lan/__init__.py | 2 +- esphome/components/wake_on_lan/button.py | 34 +++++---- .../components/wake_on_lan/wake_on_lan.cpp | 70 +++++++++++++------ esphome/components/wake_on_lan/wake_on_lan.h | 15 ++-- .../wake_on_lan/test.esp32-c3-idf.yaml | 1 + .../wake_on_lan/test.esp32-idf.yaml | 1 + 8 files changed, 84 insertions(+), 44 deletions(-) create mode 100644 tests/components/wake_on_lan/test.esp32-c3-idf.yaml create mode 100644 tests/components/wake_on_lan/test.esp32-idf.yaml diff --git a/CODEOWNERS b/CODEOWNERS index e099ca42ac..8b6143859a 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -414,7 +414,7 @@ esphome/components/veml3235/* @kbx81 esphome/components/veml7700/* @latonita esphome/components/version/* @esphome/core esphome/components/voice_assistant/* @jesserockz -esphome/components/wake_on_lan/* @willwill2will54 +esphome/components/wake_on_lan/* @clydebarrow @willwill2will54 esphome/components/waveshare_epaper/* @clydebarrow esphome/components/web_server_base/* @OttoWinter esphome/components/web_server_idf/* @dentra diff --git a/esphome/components/socket/lwip_raw_tcp_impl.cpp b/esphome/components/socket/lwip_raw_tcp_impl.cpp index bd59b81caa..1d998902ff 100644 --- a/esphome/components/socket/lwip_raw_tcp_impl.cpp +++ b/esphome/components/socket/lwip_raw_tcp_impl.cpp @@ -469,7 +469,8 @@ class LWIPRawImpl : public Socket { } ssize_t sendto(const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen) override { // return ::sendto(fd_, buf, len, flags, to, tolen); - return 0; + errno = ENOSYS; + return -1; } int setblocking(bool blocking) override { if (pcb_ == nullptr) { diff --git a/esphome/components/wake_on_lan/__init__.py b/esphome/components/wake_on_lan/__init__.py index 3548fb02f4..90539e5d3c 100644 --- a/esphome/components/wake_on_lan/__init__.py +++ b/esphome/components/wake_on_lan/__init__.py @@ -1 +1 @@ -CODEOWNERS = ["@willwill2will54"] +CODEOWNERS = ["@willwill2will54", "@clydebarrow"] diff --git a/esphome/components/wake_on_lan/button.py b/esphome/components/wake_on_lan/button.py index 778ea60cfa..b09e87e811 100644 --- a/esphome/components/wake_on_lan/button.py +++ b/esphome/components/wake_on_lan/button.py @@ -2,6 +2,16 @@ import esphome.codegen as cg from esphome.components import button import esphome.config_validation as cv from esphome.const import CONF_ID +from esphome.core import CORE + +DEPENDENCIES = ["network"] + + +def AUTO_LOAD(): + if CORE.is_esp8266 or CORE.is_rp2040: + return [] + return ["socket"] + CONF_TARGET_MAC_ADDRESS = "target_mac_address" @@ -9,25 +19,19 @@ wake_on_lan_ns = cg.esphome_ns.namespace("wake_on_lan") WakeOnLanButton = wake_on_lan_ns.class_("WakeOnLanButton", button.Button, cg.Component) -DEPENDENCIES = ["network"] - -CONFIG_SCHEMA = cv.All( +CONFIG_SCHEMA = ( button.button_schema(WakeOnLanButton) .extend(cv.COMPONENT_SCHEMA) .extend( - cv.Schema( - { - cv.Required(CONF_TARGET_MAC_ADDRESS): cv.mac_address, - } - ), - ), - cv.only_with_arduino, + { + cv.Required(CONF_TARGET_MAC_ADDRESS): cv.mac_address, + } + ) ) -def to_code(config): +async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) - - yield cg.add(var.set_macaddr(*config[CONF_TARGET_MAC_ADDRESS].parts)) - yield cg.register_component(var, config) - yield button.register_button(var, config) + cg.add(var.set_macaddr(*config[CONF_TARGET_MAC_ADDRESS].parts)) + await cg.register_component(var, config) + await button.register_button(var, config) diff --git a/esphome/components/wake_on_lan/wake_on_lan.cpp b/esphome/components/wake_on_lan/wake_on_lan.cpp index f414bf6c71..080e1bbac8 100644 --- a/esphome/components/wake_on_lan/wake_on_lan.cpp +++ b/esphome/components/wake_on_lan/wake_on_lan.cpp @@ -1,5 +1,3 @@ -#ifdef USE_ARDUINO - #include "wake_on_lan.h" #include "esphome/core/log.h" #include "esphome/components/network/ip_address.h" @@ -22,40 +20,68 @@ void WakeOnLanButton::set_macaddr(uint8_t a, uint8_t b, uint8_t c, uint8_t d, ui void WakeOnLanButton::dump_config() { LOG_BUTTON("", "Wake-on-LAN Button", this); - ESP_LOGCONFIG(TAG, " Target MAC address: %02X:%02X:%02X:%02X:%02X:%02X", macaddr_[0], macaddr_[1], macaddr_[2], - macaddr_[3], macaddr_[4], macaddr_[5]); + ESP_LOGCONFIG(TAG, " Target MAC address: %02X:%02X:%02X:%02X:%02X:%02X", this->macaddr_[0], this->macaddr_[1], + this->macaddr_[2], this->macaddr_[3], this->macaddr_[4], this->macaddr_[5]); } void WakeOnLanButton::press_action() { + if (!network::is_connected()) { + ESP_LOGW(TAG, "Network not connected"); + return; + } ESP_LOGI(TAG, "Sending Wake-on-LAN Packet..."); - bool begin_status = false; - bool end_status = false; +#if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) + struct sockaddr_storage saddr {}; + auto addr_len = + socket::set_sockaddr(reinterpret_cast(&saddr), sizeof(saddr), "255.255.255.255", this->port_); + uint8_t buffer[6 + sizeof this->macaddr_ * 16]; + memcpy(buffer, PREFIX, sizeof(PREFIX)); + for (size_t i = 0; i != 16; i++) { + memcpy(buffer + i * sizeof(this->macaddr_) + sizeof(PREFIX), this->macaddr_, sizeof(this->macaddr_)); + } + if (this->broadcast_socket_->sendto(buffer, sizeof(buffer), 0, reinterpret_cast(&saddr), + addr_len) <= 0) + ESP_LOGW(TAG, "sendto() error %d", errno); +#else IPAddress broadcast = IPAddress(255, 255, 255, 255); -#ifdef USE_ESP8266 for (auto ip : esphome::network::get_ip_addresses()) { if (ip.is_ip4()) { - begin_status = this->udp_client_.beginPacketMulticast(broadcast, 9, ip, 128); - break; + if (this->udp_client_.beginPacketMulticast(broadcast, 9, ip, 128) != 0) { + this->udp_client_.write(PREFIX, 6); + for (size_t i = 0; i < 16; i++) { + this->udp_client_.write(macaddr_, 6); + } + if (this->udp_client_.endPacket() != 0) + return; + ESP_LOGW(TAG, "WOL broadcast failed"); + return; + } } } + ESP_LOGW(TAG, "No ip4 addresses to broadcast to"); #endif -#ifdef USE_ESP32 - begin_status = this->udp_client_.beginPacket(broadcast, 9); -#endif +} - if (begin_status) { - this->udp_client_.write(PREFIX, 6); - for (size_t i = 0; i < 16; i++) { - this->udp_client_.write(macaddr_, 6); - } - end_status = this->udp_client_.endPacket(); +void WakeOnLanButton::setup() { +#if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) + this->broadcast_socket_ = socket::socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); + if (this->broadcast_socket_ == nullptr) { + this->mark_failed(); + this->status_set_error("Could not create socket"); + return; } - if (!begin_status || end_status) { - ESP_LOGE(TAG, "Sending Wake-on-LAN Packet Failed!"); + int enable = 1; + auto err = this->broadcast_socket_->setsockopt(SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)); + if (err != 0) { + this->status_set_warning("Socket unable to set reuseaddr"); + // we can still continue } + err = this->broadcast_socket_->setsockopt(SOL_SOCKET, SO_BROADCAST, &enable, sizeof(int)); + if (err != 0) { + this->status_set_warning("Socket unable to set broadcast"); + } +#endif } } // namespace wake_on_lan } // namespace esphome - -#endif diff --git a/esphome/components/wake_on_lan/wake_on_lan.h b/esphome/components/wake_on_lan/wake_on_lan.h index 72f900e3fa..42cb3a9268 100644 --- a/esphome/components/wake_on_lan/wake_on_lan.h +++ b/esphome/components/wake_on_lan/wake_on_lan.h @@ -1,10 +1,12 @@ #pragma once -#ifdef USE_ARDUINO - #include "esphome/components/button/button.h" #include "esphome/core/component.h" +#if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) +#include "esphome/components/socket/socket.h" +#else #include "WiFiUdp.h" +#endif namespace esphome { namespace wake_on_lan { @@ -14,14 +16,19 @@ class WakeOnLanButton : public button::Button, public Component { void set_macaddr(uint8_t a, uint8_t b, uint8_t c, uint8_t d, uint8_t e, uint8_t f); void dump_config() override; + void setup() override; + float get_setup_priority() const override { return setup_priority::AFTER_WIFI; } protected: +#if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) + std::unique_ptr broadcast_socket_{}; +#else WiFiUDP udp_client_{}; +#endif void press_action() override; + uint16_t port_{9}; uint8_t macaddr_[6]; }; } // namespace wake_on_lan } // namespace esphome - -#endif diff --git a/tests/components/wake_on_lan/test.esp32-c3-idf.yaml b/tests/components/wake_on_lan/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/wake_on_lan/test.esp32-c3-idf.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/wake_on_lan/test.esp32-idf.yaml b/tests/components/wake_on_lan/test.esp32-idf.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/wake_on_lan/test.esp32-idf.yaml @@ -0,0 +1 @@ +<<: !include common.yaml From bff24e297774d7f79deea30c9cdaed4bc23e47d4 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Wed, 29 May 2024 00:05:19 -0500 Subject: [PATCH 1516/2101] Fix a bunch of components for IDF 5 compatibility and #6802 (#6805) --- esphome/components/ade7880/ade7880.cpp | 1 + .../components/ade7953_base/ade7953_base.cpp | 1 + esphome/components/ags10/ags10.cpp | 4 +- .../components/ct_clamp/ct_clamp_sensor.cpp | 5 ++- .../fingerprint_grow/fingerprint_grow.cpp | 2 +- esphome/components/he60r/he60r.cpp | 7 ++-- esphome/components/htu31d/htu31d.cpp | 4 +- .../components/ina2xx_base/ina2xx_base.cpp | 8 ++-- esphome/components/jsn_sr04t/jsn_sr04t.cpp | 4 +- esphome/components/mhz19/mhz19.cpp | 1 + .../micro_wake_word/micro_wake_word.cpp | 3 +- .../remote_base/byronsx_protocol.cpp | 1 + .../remote_base/drayton_protocol.cpp | 2 + esphome/components/sonoff_d1/sonoff_d1.cpp | 3 +- esphome/components/weikai/weikai.cpp | 4 +- esphome/components/wl_134/wl_134.cpp | 4 +- esphome/components/xgzp68xx/xgzp68xx.cpp | 1 + .../remote_receiver/esp32-common.yaml | 40 +++++++++---------- 18 files changed, 55 insertions(+), 40 deletions(-) diff --git a/esphome/components/ade7880/ade7880.cpp b/esphome/components/ade7880/ade7880.cpp index a03f1227f1..4a45b3b321 100644 --- a/esphome/components/ade7880/ade7880.cpp +++ b/esphome/components/ade7880/ade7880.cpp @@ -10,6 +10,7 @@ #include "ade7880.h" #include "ade7880_registers.h" #include "esphome/core/log.h" + #include namespace esphome { diff --git a/esphome/components/ade7953_base/ade7953_base.cpp b/esphome/components/ade7953_base/ade7953_base.cpp index 79161c5676..2511b4e04c 100644 --- a/esphome/components/ade7953_base/ade7953_base.cpp +++ b/esphome/components/ade7953_base/ade7953_base.cpp @@ -1,5 +1,6 @@ #include "ade7953_base.h" #include "esphome/core/log.h" + #include namespace esphome { diff --git a/esphome/components/ags10/ags10.cpp b/esphome/components/ags10/ags10.cpp index dfaa00e2e9..422380da83 100644 --- a/esphome/components/ags10/ags10.cpp +++ b/esphome/components/ags10/ags10.cpp @@ -1,5 +1,7 @@ #include "ags10.h" +#include + namespace esphome { namespace ags10 { static const char *const TAG = "ags10"; @@ -35,7 +37,7 @@ void AGS10Component::setup() { auto resistance = this->read_resistance_(); if (resistance) { - ESP_LOGD(TAG, "AGS10 Sensor Resistance: 0x%08X", *resistance); + ESP_LOGD(TAG, "AGS10 Sensor Resistance: 0x%08" PRIX32, *resistance); if (this->resistance_ != nullptr) { this->resistance_->publish_state(*resistance); } diff --git a/esphome/components/ct_clamp/ct_clamp_sensor.cpp b/esphome/components/ct_clamp/ct_clamp_sensor.cpp index d555befcde..0aa0258a9b 100644 --- a/esphome/components/ct_clamp/ct_clamp_sensor.cpp +++ b/esphome/components/ct_clamp/ct_clamp_sensor.cpp @@ -1,6 +1,7 @@ #include "ct_clamp_sensor.h" #include "esphome/core/log.h" +#include #include namespace esphome { @@ -37,8 +38,8 @@ void CTClampSensor::update() { float rms_ac = 0; if (rms_ac_squared > 0) rms_ac = std::sqrt(rms_ac_squared); - ESP_LOGD(TAG, "'%s' - Raw AC Value: %.3fA after %d different samples (%d SPS)", this->name_.c_str(), rms_ac, - this->num_samples_, 1000 * this->num_samples_ / this->sample_duration_); + ESP_LOGD(TAG, "'%s' - Raw AC Value: %.3fA after %" PRIu32 " different samples (%" PRIu32 " SPS)", + this->name_.c_str(), rms_ac, this->num_samples_, 1000 * this->num_samples_ / this->sample_duration_); this->publish_state(rms_ac); }); diff --git a/esphome/components/fingerprint_grow/fingerprint_grow.cpp b/esphome/components/fingerprint_grow/fingerprint_grow.cpp index 8f58db9159..c2cab368c9 100644 --- a/esphome/components/fingerprint_grow/fingerprint_grow.cpp +++ b/esphome/components/fingerprint_grow/fingerprint_grow.cpp @@ -377,7 +377,7 @@ uint8_t FingerprintGrowComponent::transfer_(std::vector *p_data_buffer) this->write((uint8_t) (wire_length >> 8)); this->write((uint8_t) (wire_length & 0xFF)); - uint16_t sum = ((wire_length) >> 8) + ((wire_length) &0xFF) + COMMAND; + uint16_t sum = (wire_length >> 8) + (wire_length & 0xFF) + COMMAND; for (auto data : *p_data_buffer) { this->write(data); sum += data; diff --git a/esphome/components/he60r/he60r.cpp b/esphome/components/he60r/he60r.cpp index 96ad1f04be..05f3f528a5 100644 --- a/esphome/components/he60r/he60r.cpp +++ b/esphome/components/he60r/he60r.cpp @@ -1,6 +1,7 @@ #include "he60r.h" #include "esphome/core/hal.h" #include "esphome/core/log.h" + #include namespace esphome { @@ -125,10 +126,10 @@ void HE60rCover::process_rx_(uint8_t data) { } void HE60rCover::update_() { - if (toggles_needed_ != 0) { + if (this->toggles_needed_ != 0) { if ((this->counter_++ & 0x3) == 0) { - toggles_needed_--; - ESP_LOGD(TAG, "Writing byte 0x30, still needed=%" PRIu32, toggles_needed_); + this->toggles_needed_--; + ESP_LOGD(TAG, "Writing byte 0x30, still needed=%" PRIu32, this->toggles_needed_); this->write_byte(TOGGLE_BYTE); } else { this->write_byte(QUERY_BYTE); diff --git a/esphome/components/htu31d/htu31d.cpp b/esphome/components/htu31d/htu31d.cpp index 928250a5b2..bf4689d837 100644 --- a/esphome/components/htu31d/htu31d.cpp +++ b/esphome/components/htu31d/htu31d.cpp @@ -12,6 +12,8 @@ #include "esphome/core/helpers.h" #include "esphome/core/log.h" +#include + namespace esphome { namespace htu31d { @@ -204,7 +206,7 @@ uint32_t HTU31DComponent::read_serial_num_() { return 0; } - ESP_LOGD(TAG, "Found serial: 0x%X", serial); + ESP_LOGD(TAG, "Found serial: 0x%" PRIX32, serial); return serial; } diff --git a/esphome/components/ina2xx_base/ina2xx_base.cpp b/esphome/components/ina2xx_base/ina2xx_base.cpp index 5d947d0537..924bf91e5e 100644 --- a/esphome/components/ina2xx_base/ina2xx_base.cpp +++ b/esphome/components/ina2xx_base/ina2xx_base.cpp @@ -483,7 +483,7 @@ bool INA2XX::read_power_w_(float &power_out) { uint64_t power_reading{0}; auto ret = this->read_unsigned_((uint8_t) RegisterMap::REG_POWER, 3, power_reading); - ESP_LOGV(TAG, "read_power_w_ ret=%s, reading_lsb=%d", OKFAILED(ret), (uint32_t) power_reading); + ESP_LOGV(TAG, "read_power_w_ ret=%s, reading_lsb=%" PRIu32, OKFAILED(ret), (uint32_t) power_reading); if (ret) { power_out = this->cfg_.power_coeff * this->current_lsb_ * (float) power_reading; } @@ -503,8 +503,8 @@ bool INA2XX::read_energy_(double &joules_out, double &watt_hours_out) { uint64_t previous_energy = this->energy_overflows_count_ * (((uint64_t) 1) << 40); auto ret = this->read_unsigned_((uint8_t) RegisterMap::REG_ENERGY, 5, joules_reading); - ESP_LOGV(TAG, "read_energy_j_ ret=%s, reading_lsb=0x%" PRIX64 ", current_lsb=%f, overflow_cnt=%d", OKFAILED(ret), - joules_reading, this->current_lsb_, this->energy_overflows_count_); + ESP_LOGV(TAG, "read_energy_j_ ret=%s, reading_lsb=0x%" PRIX64 ", current_lsb=%f, overflow_cnt=%" PRIu32, + OKFAILED(ret), joules_reading, this->current_lsb_, this->energy_overflows_count_); if (ret) { joules_out = this->cfg_.energy_coeff * this->current_lsb_ * (double) joules_reading + (double) previous_energy; watt_hours_out = joules_out / 3600.0; @@ -528,7 +528,7 @@ bool INA2XX::read_charge_(double &coulombs_out, double &_hours_out) { auto ret = this->read_unsigned_((uint8_t) RegisterMap::REG_CHARGE, 5, raw); coulombs_reading = this->two_complement_(raw, 40); - ESP_LOGV(TAG, "read_charge_c_ ret=%d, curr_charge=%f + 39-bit overflow_cnt=%d", ret, coulombs_reading, + ESP_LOGV(TAG, "read_charge_c_ ret=%d, curr_charge=%f + 39-bit overflow_cnt=%" PRIu32, ret, coulombs_reading, this->charge_overflows_count_); if (ret) { coulombs_out = this->current_lsb_ * (double) coulombs_reading + (double) previous_charge; diff --git a/esphome/components/jsn_sr04t/jsn_sr04t.cpp b/esphome/components/jsn_sr04t/jsn_sr04t.cpp index 70e21a137d..b96bf8f762 100644 --- a/esphome/components/jsn_sr04t/jsn_sr04t.cpp +++ b/esphome/components/jsn_sr04t/jsn_sr04t.cpp @@ -2,8 +2,6 @@ #include "esphome/core/helpers.h" #include "esphome/core/log.h" -#include - // Very basic support for JSN_SR04T V3.0 distance sensor in mode 2 namespace esphome { @@ -38,7 +36,7 @@ void Jsnsr04tComponent::check_buffer_() { uint16_t distance = encode_uint16(this->buffer_[1], this->buffer_[2]); if (distance > 250) { float meters = distance / 1000.0f; - ESP_LOGV(TAG, "Distance from sensor: %" PRIu32 "mm, %.3fm", distance, meters); + ESP_LOGV(TAG, "Distance from sensor: %umm, %.3fm", distance, meters); this->publish_state(meters); } else { ESP_LOGW(TAG, "Invalid data read from sensor: %s", format_hex_pretty(this->buffer_).c_str()); diff --git a/esphome/components/mhz19/mhz19.cpp b/esphome/components/mhz19/mhz19.cpp index 574aee1bd5..c3c8120362 100644 --- a/esphome/components/mhz19/mhz19.cpp +++ b/esphome/components/mhz19/mhz19.cpp @@ -1,5 +1,6 @@ #include "mhz19.h" #include "esphome/core/log.h" + #include namespace esphome { diff --git a/esphome/components/micro_wake_word/micro_wake_word.cpp b/esphome/components/micro_wake_word/micro_wake_word.cpp index f637f8b2bb..5a89708127 100644 --- a/esphome/components/micro_wake_word/micro_wake_word.cpp +++ b/esphome/components/micro_wake_word/micro_wake_word.cpp @@ -20,6 +20,7 @@ #include #include +#include #include namespace esphome { @@ -316,7 +317,7 @@ float MicroWakeWord::perform_streaming_inference_() { return false; } - ESP_LOGV(TAG, "Streaming Inference Latency=%u ms", (millis() - prior_invoke)); + ESP_LOGV(TAG, "Streaming Inference Latency=%" PRIu32 " ms", (millis() - prior_invoke)); TfLiteTensor *output = this->streaming_interpreter_->output(0); diff --git a/esphome/components/remote_base/byronsx_protocol.cpp b/esphome/components/remote_base/byronsx_protocol.cpp index 2d4c60ff8b..6bfa4b7ff9 100644 --- a/esphome/components/remote_base/byronsx_protocol.cpp +++ b/esphome/components/remote_base/byronsx_protocol.cpp @@ -1,5 +1,6 @@ #include "byronsx_protocol.h" #include "esphome/core/log.h" + #include namespace esphome { diff --git a/esphome/components/remote_base/drayton_protocol.cpp b/esphome/components/remote_base/drayton_protocol.cpp index 73c0fb116c..da2e985af0 100644 --- a/esphome/components/remote_base/drayton_protocol.cpp +++ b/esphome/components/remote_base/drayton_protocol.cpp @@ -1,6 +1,8 @@ #include "drayton_protocol.h" #include "esphome/core/log.h" +#include + namespace esphome { namespace remote_base { diff --git a/esphome/components/sonoff_d1/sonoff_d1.cpp b/esphome/components/sonoff_d1/sonoff_d1.cpp index 6ae80296fd..e70ec7b70d 100644 --- a/esphome/components/sonoff_d1/sonoff_d1.cpp +++ b/esphome/components/sonoff_d1/sonoff_d1.cpp @@ -128,7 +128,8 @@ bool SonoffD1Output::read_ack_(const uint8_t *cmd, const size_t len) { // Expected acknowledgement from rf chip uint8_t ref_buffer[7] = {0xAA, 0x55, cmd[2], cmd[3], 0x00, 0x00, 0x00}; uint8_t buffer[sizeof(ref_buffer)] = {0}; - uint32_t pos = 0, buf_len = sizeof(ref_buffer); + uint32_t pos = 0; + size_t buf_len = sizeof(ref_buffer); // Update the reference checksum this->populate_checksum_(ref_buffer, sizeof(ref_buffer)); diff --git a/esphome/components/weikai/weikai.cpp b/esphome/components/weikai/weikai.cpp index a04bc0a574..00bce9bcff 100644 --- a/esphome/components/weikai/weikai.cpp +++ b/esphome/components/weikai/weikai.cpp @@ -375,8 +375,8 @@ void WeikaiChannel::set_baudrate_() { this->parent_->page1_ = false; // switch back to page 0 this->reg(WKREG_SPAGE) = 0; - ESP_LOGV(TAG, " Crystal=%d baudrate=%d => registers [%d %d %d]", this->parent_->crystal_, this->baud_rate_, - baud_high, baud_low, baud_dec); + ESP_LOGV(TAG, " Crystal=%" PRId32 " baudrate=%" PRId32 " => registers [%d %d %d]", this->parent_->crystal_, + this->baud_rate_, baud_high, baud_low, baud_dec); } inline bool WeikaiChannel::tx_fifo_is_not_empty_() { return this->reg(WKREG_FSR) & FSR_TFDAT; } diff --git a/esphome/components/wl_134/wl_134.cpp b/esphome/components/wl_134/wl_134.cpp index 3ffa0c63ce..403f8bd1b3 100644 --- a/esphome/components/wl_134/wl_134.cpp +++ b/esphome/components/wl_134/wl_134.cpp @@ -1,6 +1,8 @@ #include "wl_134.h" #include "esphome/core/log.h" +#include + namespace esphome { namespace wl_134 { @@ -71,7 +73,7 @@ Wl134Component::Rfid134Error Wl134Component::read_packet_() { ESP_LOGV(TAG, "isData: %s", reading.isData ? "true" : "false"); ESP_LOGV(TAG, "isAnimal: %s", reading.isAnimal ? "true" : "false"); ESP_LOGV(TAG, "Reserved0: %d", reading.reserved0); - ESP_LOGV(TAG, "Reserved1: %d", reading.reserved1); + ESP_LOGV(TAG, "Reserved1: %" PRId32, reading.reserved1); char buf[20]; sprintf(buf, "%03d%012lld", reading.country, reading.id); diff --git a/esphome/components/xgzp68xx/xgzp68xx.cpp b/esphome/components/xgzp68xx/xgzp68xx.cpp index dff00fb696..ad6217845d 100644 --- a/esphome/components/xgzp68xx/xgzp68xx.cpp +++ b/esphome/components/xgzp68xx/xgzp68xx.cpp @@ -3,6 +3,7 @@ #include "esphome/core/hal.h" #include "esphome/core/helpers.h" #include "esphome/components/i2c/i2c.h" + #include namespace esphome { diff --git a/tests/components/remote_receiver/esp32-common.yaml b/tests/components/remote_receiver/esp32-common.yaml index c3987f8cd9..7e5d2cce32 100644 --- a/tests/components/remote_receiver/esp32-common.yaml +++ b/tests/components/remote_receiver/esp32-common.yaml @@ -32,8 +32,8 @@ remote_receiver: on_coolix: then: - logger.log: - format: "on_coolix: %u %u" - args: ["x.first", "x.second"] + format: "on_coolix: %lu %lu" + args: ["long(x.first)", "long(x.second)"] on_dish: then: - logger.log: @@ -52,13 +52,13 @@ remote_receiver: on_jvc: then: - logger.log: - format: "on_jvc: %u" - args: ["x.data"] + format: "on_jvc: %lu" + args: ["long(x.data)"] on_keeloq: then: - logger.log: - format: "on_keeloq: %u %u %u" - args: ["x.encrypted", "x.address", "x.command"] + format: "on_keeloq: %lu %lu %u" + args: ["long(x.encrypted)", "long(x.address)", "x.command"] on_haier: then: - logger.log: @@ -67,13 +67,13 @@ remote_receiver: on_lg: then: - logger.log: - format: "on_lg: %u %u" - args: ["x.data", "x.nbits"] + format: "on_lg: %lu %u" + args: ["long(x.data)", "x.nbits"] on_magiquest: then: - logger.log: - format: "on_magiquest: %u %u" - args: ["x.magnitude", "x.wand_id"] + format: "on_magiquest: %u %lu" + args: ["x.magnitude", "long(x.wand_id)"] on_midea: then: - logger.log: @@ -87,13 +87,13 @@ remote_receiver: on_nexa: then: - logger.log: - format: "on_nexa: %u %u %u %u %u" - args: ["x.device", "x.group", "x.state", "x.channel", "x.level"] + format: "on_nexa: %lu %u %u %u %u" + args: ["long(x.device)", "x.group", "x.state", "x.channel", "x.level"] on_panasonic: then: - logger.log: - format: "on_panasonic: %u %u" - args: ["x.address", "x.command"] + format: "on_panasonic: %u %lu" + args: ["x.address", "long(x.command)"] on_pioneer: then: - logger.log: @@ -107,8 +107,8 @@ remote_receiver: on_raw: then: - logger.log: - format: "on_raw: %u" - args: ["x.front()"] + format: "on_raw: %lu" + args: ["long(x.front())"] on_rc5: then: - logger.log: @@ -132,13 +132,13 @@ remote_receiver: on_samsung36: then: - logger.log: - format: "on_samsung36: %u %u" - args: ["x.address", "x.command"] + format: "on_samsung36: %u %lu" + args: ["x.address", "long(x.command)"] on_sony: then: - logger.log: - format: "on_sony: %u %u" - args: ["x.data", "x.nbits"] + format: "on_sony: %lu %u" + args: ["long(x.data)", "x.nbits"] on_toshiba_ac: then: - logger.log: From 60433c5e645690f358be94c2e3136aecfd84fa59 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 29 May 2024 17:09:13 +1200 Subject: [PATCH 1517/2101] Bump docker/login-action from 3.1.0 to 3.2.0 (#6823) 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 47dc217bf7..563d485b6a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -96,12 +96,12 @@ jobs: uses: docker/setup-qemu-action@v3.0.0 - name: Log in to docker hub - uses: docker/login-action@v3.1.0 + uses: docker/login-action@v3.2.0 with: username: ${{ secrets.DOCKER_USER }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Log in to the GitHub container registry - uses: docker/login-action@v3.1.0 + uses: docker/login-action@v3.2.0 with: registry: ghcr.io username: ${{ github.actor }} @@ -188,13 +188,13 @@ jobs: - name: Log in to docker hub if: matrix.registry == 'dockerhub' - uses: docker/login-action@v3.1.0 + uses: docker/login-action@v3.2.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@v3.1.0 + uses: docker/login-action@v3.2.0 with: registry: ghcr.io username: ${{ github.actor }} From 6d5d382f3db98e2a9997fed9e62811f91bad06f0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 29 May 2024 17:10:47 +1200 Subject: [PATCH 1518/2101] Bump pytest-cov from 4.1.0 to 5.0.0 (#6580) 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 ae833841ca..0052e7545c 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -6,7 +6,7 @@ pre-commit # Unit tests pytest==8.2.0 -pytest-cov==4.1.0 +pytest-cov==5.0.0 pytest-mock==3.14.0 pytest-asyncio==0.23.6 asyncmock==0.4.2 From 439fd9471863e4bf12cdc5e11b098ab0b7b96874 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 29 May 2024 17:11:02 +1200 Subject: [PATCH 1519/2101] Bump peter-evans/create-pull-request from 6.0.4 to 6.0.5 (#6635) 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 9a8c9d1753..e65e851f3c 100644 --- a/.github/workflows/sync-device-classes.yml +++ b/.github/workflows/sync-device-classes.yml @@ -36,7 +36,7 @@ jobs: python ./script/sync-device_class.py - name: Commit changes - uses: peter-evans/create-pull-request@v6.0.4 + uses: peter-evans/create-pull-request@v6.0.5 with: commit-message: "Synchronise Device Classes from Home Assistant" committer: esphomebot From 5ae32e81c360a73f7ebe14d330d6e9d58eac324a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 29 May 2024 17:11:34 +1200 Subject: [PATCH 1520/2101] Bump black from 24.4.0 to 24.4.2 (#6646) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- .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 418716e4f4..74acfa1c1d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,7 +3,7 @@ # See https://pre-commit.com/hooks.html for more hooks repos: - repo: https://github.com/psf/black-pre-commit-mirror - rev: 24.2.0 + rev: 24.4.2 hooks: - id: black args: diff --git a/requirements_test.txt b/requirements_test.txt index 0052e7545c..94abe1cd76 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,6 +1,6 @@ pylint==3.1.0 flake8==7.0.0 # also change in .pre-commit-config.yaml when updating -black==24.4.0 # also change in .pre-commit-config.yaml when updating +black==24.4.2 # also change in .pre-commit-config.yaml when updating pyupgrade==3.15.2 # also change in .pre-commit-config.yaml when updating pre-commit From 854d3f2e4a919c27f723d940295f0adec1614168 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 30 May 2024 13:09:19 +1200 Subject: [PATCH 1521/2101] [voice_assistant] Timers (#6821) Co-authored-by: Keith Burzinski --- esphome/components/api/api.proto | 19 ++++ esphome/components/api/api_connection.cpp | 9 ++ esphome/components/api/api_connection.h | 1 + esphome/components/api/api_pb2.cpp | 92 +++++++++++++++++++ esphome/components/api/api_pb2.h | 23 +++++ esphome/components/api/api_pb2_service.cpp | 13 +++ esphome/components/api/api_pb2_service.h | 3 + .../components/voice_assistant/__init__.py | 66 +++++++++++++ .../voice_assistant/voice_assistant.cpp | 53 +++++++++++ .../voice_assistant/voice_assistant.h | 42 +++++++++ 10 files changed, 321 insertions(+) diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index 774ca7ed9b..0becec2348 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -1517,6 +1517,25 @@ message VoiceAssistantAudio { bool end = 2; } +enum VoiceAssistantTimerEvent { + VOICE_ASSISTANT_TIMER_STARTED = 0; + VOICE_ASSISTANT_TIMER_UPDATED = 1; + VOICE_ASSISTANT_TIMER_CANCELLED = 2; + VOICE_ASSISTANT_TIMER_FINISHED = 3; +} + +message VoiceAssistantTimerEventResponse { + option (id) = 115; + option (source) = SOURCE_CLIENT; + option (ifdef) = "USE_VOICE_ASSISTANT"; + + VoiceAssistantTimerEvent event_type = 1; + string timer_id = 2; + string name = 3; + uint32 total_seconds = 4; + uint32 seconds_left = 5; + bool is_active = 6; +} // ==================== ALARM CONTROL PANEL ==================== enum AlarmControlPanelState { diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 2804dba31f..253f04aa39 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1193,6 +1193,15 @@ void APIConnection::on_voice_assistant_audio(const VoiceAssistantAudio &msg) { voice_assistant::global_voice_assistant->on_audio(msg); } }; +void APIConnection::on_voice_assistant_timer_event_response(const VoiceAssistantTimerEventResponse &msg) { + if (voice_assistant::global_voice_assistant != nullptr) { + if (voice_assistant::global_voice_assistant->get_api_connection() != this) { + return; + } + + voice_assistant::global_voice_assistant->on_timer_event(msg); + } +}; #endif diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index ee466c5d10..293da17fa4 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -150,6 +150,7 @@ class APIConnection : public APIServerConnection { 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; #endif #ifdef USE_ALARM_CONTROL_PANEL diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index a48087e348..9db6482c49 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -475,6 +475,22 @@ template<> const char *proto_enum_to_string(enums::V } #endif #ifdef HAS_PROTO_MESSAGE_DUMP +template<> const char *proto_enum_to_string(enums::VoiceAssistantTimerEvent value) { + switch (value) { + case enums::VOICE_ASSISTANT_TIMER_STARTED: + return "VOICE_ASSISTANT_TIMER_STARTED"; + case enums::VOICE_ASSISTANT_TIMER_UPDATED: + return "VOICE_ASSISTANT_TIMER_UPDATED"; + case enums::VOICE_ASSISTANT_TIMER_CANCELLED: + return "VOICE_ASSISTANT_TIMER_CANCELLED"; + case enums::VOICE_ASSISTANT_TIMER_FINISHED: + return "VOICE_ASSISTANT_TIMER_FINISHED"; + default: + return "UNKNOWN"; + } +} +#endif +#ifdef HAS_PROTO_MESSAGE_DUMP template<> const char *proto_enum_to_string(enums::AlarmControlPanelState value) { switch (value) { case enums::ALARM_STATE_DISARMED: @@ -6857,6 +6873,82 @@ void VoiceAssistantAudio::dump_to(std::string &out) const { out.append("}"); } #endif +bool VoiceAssistantTimerEventResponse::decode_varint(uint32_t field_id, ProtoVarInt value) { + switch (field_id) { + case 1: { + this->event_type = value.as_enum(); + return true; + } + case 4: { + this->total_seconds = value.as_uint32(); + return true; + } + case 5: { + this->seconds_left = value.as_uint32(); + return true; + } + case 6: { + this->is_active = value.as_bool(); + return true; + } + default: + return false; + } +} +bool VoiceAssistantTimerEventResponse::decode_length(uint32_t field_id, ProtoLengthDelimited value) { + switch (field_id) { + case 2: { + this->timer_id = value.as_string(); + return true; + } + case 3: { + this->name = value.as_string(); + return true; + } + default: + return false; + } +} +void VoiceAssistantTimerEventResponse::encode(ProtoWriteBuffer buffer) const { + buffer.encode_enum(1, this->event_type); + buffer.encode_string(2, this->timer_id); + buffer.encode_string(3, this->name); + buffer.encode_uint32(4, this->total_seconds); + buffer.encode_uint32(5, this->seconds_left); + buffer.encode_bool(6, this->is_active); +} +#ifdef HAS_PROTO_MESSAGE_DUMP +void VoiceAssistantTimerEventResponse::dump_to(std::string &out) const { + __attribute__((unused)) char buffer[64]; + out.append("VoiceAssistantTimerEventResponse {\n"); + out.append(" event_type: "); + out.append(proto_enum_to_string(this->event_type)); + out.append("\n"); + + out.append(" timer_id: "); + out.append("'").append(this->timer_id).append("'"); + out.append("\n"); + + out.append(" name: "); + out.append("'").append(this->name).append("'"); + out.append("\n"); + + out.append(" total_seconds: "); + sprintf(buffer, "%" PRIu32, this->total_seconds); + out.append(buffer); + out.append("\n"); + + out.append(" seconds_left: "); + sprintf(buffer, "%" PRIu32, this->seconds_left); + out.append(buffer); + out.append("\n"); + + out.append(" is_active: "); + out.append(YESNO(this->is_active)); + out.append("\n"); + out.append("}"); +} +#endif bool ListEntitiesAlarmControlPanelResponse::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { case 6: { diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index 807b150d82..54cbd20559 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -191,6 +191,12 @@ enum VoiceAssistantEvent : uint32_t { VOICE_ASSISTANT_TTS_STREAM_START = 98, VOICE_ASSISTANT_TTS_STREAM_END = 99, }; +enum VoiceAssistantTimerEvent : uint32_t { + VOICE_ASSISTANT_TIMER_STARTED = 0, + VOICE_ASSISTANT_TIMER_UPDATED = 1, + VOICE_ASSISTANT_TIMER_CANCELLED = 2, + VOICE_ASSISTANT_TIMER_FINISHED = 3, +}; enum AlarmControlPanelState : uint32_t { ALARM_STATE_DISARMED = 0, ALARM_STATE_ARMED_HOME = 1, @@ -1775,6 +1781,23 @@ class VoiceAssistantAudio : public ProtoMessage { bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; bool decode_varint(uint32_t field_id, ProtoVarInt value) override; }; +class VoiceAssistantTimerEventResponse : public ProtoMessage { + public: + enums::VoiceAssistantTimerEvent event_type{}; + std::string timer_id{}; + std::string name{}; + uint32_t total_seconds{0}; + uint32_t seconds_left{0}; + bool is_active{false}; + void encode(ProtoWriteBuffer buffer) const override; +#ifdef HAS_PROTO_MESSAGE_DUMP + void dump_to(std::string &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 ListEntitiesAlarmControlPanelResponse : public ProtoMessage { public: std::string object_id{}; diff --git a/esphome/components/api/api_pb2_service.cpp b/esphome/components/api/api_pb2_service.cpp index 093fe917e0..7c95bb03ad 100644 --- a/esphome/components/api/api_pb2_service.cpp +++ b/esphome/components/api/api_pb2_service.cpp @@ -484,6 +484,8 @@ bool APIServerConnectionBase::send_voice_assistant_audio(const VoiceAssistantAud return this->send_message_(msg, 106); } #endif +#ifdef USE_VOICE_ASSISTANT +#endif #ifdef USE_ALARM_CONTROL_PANEL bool APIServerConnectionBase::send_list_entities_alarm_control_panel_response( const ListEntitiesAlarmControlPanelResponse &msg) { @@ -1093,6 +1095,17 @@ bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, ESP_LOGVV(TAG, "on_date_time_command_request: %s", msg.dump().c_str()); #endif this->on_date_time_command_request(msg); +#endif + break; + } + case 115: { +#ifdef USE_VOICE_ASSISTANT + 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()); +#endif + this->on_voice_assistant_timer_event_response(msg); #endif break; } diff --git a/esphome/components/api/api_pb2_service.h b/esphome/components/api/api_pb2_service.h index 196d904aca..2f8a2b3def 100644 --- a/esphome/components/api/api_pb2_service.h +++ b/esphome/components/api/api_pb2_service.h @@ -244,6 +244,9 @@ class APIServerConnectionBase : public ProtoService { bool send_voice_assistant_audio(const VoiceAssistantAudio &msg); virtual void on_voice_assistant_audio(const VoiceAssistantAudio &value){}; #endif +#ifdef USE_VOICE_ASSISTANT + virtual void on_voice_assistant_timer_event_response(const VoiceAssistantTimerEventResponse &value){}; +#endif #ifdef USE_ALARM_CONTROL_PANEL bool send_list_entities_alarm_control_panel_response(const ListEntitiesAlarmControlPanelResponse &msg); #endif diff --git a/esphome/components/voice_assistant/__init__.py b/esphome/components/voice_assistant/__init__.py index 3ba0c58ce4..c18f0a6850 100644 --- a/esphome/components/voice_assistant/__init__.py +++ b/esphome/components/voice_assistant/__init__.py @@ -44,6 +44,12 @@ CONF_VOLUME_MULTIPLIER = "volume_multiplier" CONF_WAKE_WORD = "wake_word" +CONF_ON_TIMER_STARTED = "on_timer_started" +CONF_ON_TIMER_UPDATED = "on_timer_updated" +CONF_ON_TIMER_CANCELLED = "on_timer_cancelled" +CONF_ON_TIMER_FINISHED = "on_timer_finished" +CONF_ON_TIMER_TICK = "on_timer_tick" + voice_assistant_ns = cg.esphome_ns.namespace("voice_assistant") VoiceAssistant = voice_assistant_ns.class_("VoiceAssistant", cg.Component) @@ -64,6 +70,8 @@ ConnectedCondition = voice_assistant_ns.class_( "ConnectedCondition", automation.Condition, cg.Parented.template(VoiceAssistant) ) +Timer = voice_assistant_ns.struct("Timer") + def tts_stream_validate(config): if CONF_SPEAKER not in config and ( @@ -131,6 +139,21 @@ CONFIG_SCHEMA = cv.All( single=True ), cv.Optional(CONF_ON_IDLE): automation.validate_automation(single=True), + cv.Optional(CONF_ON_TIMER_STARTED): automation.validate_automation( + single=True + ), + cv.Optional(CONF_ON_TIMER_UPDATED): automation.validate_automation( + single=True + ), + cv.Optional(CONF_ON_TIMER_CANCELLED): automation.validate_automation( + single=True + ), + cv.Optional(CONF_ON_TIMER_FINISHED): automation.validate_automation( + single=True + ), + cv.Optional(CONF_ON_TIMER_TICK): automation.validate_automation( + single=True + ), } ).extend(cv.COMPONENT_SCHEMA), tts_stream_validate, @@ -270,6 +293,49 @@ async def to_code(config): config[CONF_ON_IDLE], ) + has_timers = False + if on_timer_started := config.get(CONF_ON_TIMER_STARTED): + await automation.build_automation( + var.get_timer_started_trigger(), + [(Timer, "timer")], + on_timer_started, + ) + has_timers = True + + if on_timer_updated := config.get(CONF_ON_TIMER_UPDATED): + await automation.build_automation( + var.get_timer_updated_trigger(), + [(Timer, "timer")], + on_timer_updated, + ) + has_timers = True + + if on_timer_cancelled := config.get(CONF_ON_TIMER_CANCELLED): + await automation.build_automation( + var.get_timer_cancelled_trigger(), + [(Timer, "timer")], + on_timer_cancelled, + ) + has_timers = True + + if on_timer_finished := config.get(CONF_ON_TIMER_FINISHED): + await automation.build_automation( + var.get_timer_finished_trigger(), + [(Timer, "timer")], + on_timer_finished, + ) + has_timers = True + + 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")], + on_timer_tick, + ) + has_timers = True + + cg.add(var.set_has_timers(has_timers)) + cg.add_define("USE_VOICE_ASSISTANT") diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index 712a0ab137..0bd8194190 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -798,12 +798,65 @@ void VoiceAssistant::on_audio(const api::VoiceAssistantAudio &msg) { this->speaker_buffer_index_ += msg.data.length(); this->speaker_buffer_size_ += msg.data.length(); this->speaker_bytes_received_ += msg.data.length(); + ESP_LOGD(TAG, "Received audio: %d bytes from API", msg.data.length()); } else { ESP_LOGE(TAG, "Cannot receive audio, buffer is full"); } #endif } +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; + ESP_LOGD(TAG, "Timer Event"); + ESP_LOGD(TAG, " Type: %d", msg.event_type); + ESP_LOGD(TAG, " %s", timer.to_string().c_str()); + + switch (msg.event_type) { + case api::enums::VOICE_ASSISTANT_TIMER_STARTED: + this->timer_started_trigger_->trigger(timer); + break; + case api::enums::VOICE_ASSISTANT_TIMER_UPDATED: + this->timer_updated_trigger_->trigger(timer); + break; + case api::enums::VOICE_ASSISTANT_TIMER_CANCELLED: + 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->timers_.erase(timer.id); + break; + } + + if (this->timers_.empty()) { + this->cancel_interval("timer-event"); + this->timer_tick_running_ = false; + } else if (!this->timer_tick_running_) { + this->set_interval("timer-event", 1000, [this]() { this->timer_tick_(); }); + this->timer_tick_running_ = true; + } +} + +void VoiceAssistant::timer_tick_() { + std::vector res; + res.reserve(this->timers_.size()); + for (auto &pair : this->timers_) { + auto &timer = pair.second; + if (timer.is_active && timer.seconds_left > 0) { + timer.seconds_left--; + } + res.push_back(timer); + } + this->timer_tick_trigger_->trigger(res); +} + VoiceAssistant *global_voice_assistant = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) } // namespace voice_assistant diff --git a/esphome/components/voice_assistant/voice_assistant.h b/esphome/components/voice_assistant/voice_assistant.h index 17141365d4..a160972e22 100644 --- a/esphome/components/voice_assistant/voice_assistant.h +++ b/esphome/components/voice_assistant/voice_assistant.h @@ -24,6 +24,9 @@ #include #endif +#include +#include + namespace esphome { namespace voice_assistant { @@ -36,6 +39,7 @@ enum VoiceAssistantFeature : uint32_t { FEATURE_VOICE_ASSISTANT = 1 << 0, FEATURE_SPEAKER = 1 << 1, FEATURE_API_AUDIO = 1 << 2, + FEATURE_TIMERS = 1 << 3, }; enum class State { @@ -59,6 +63,20 @@ enum AudioMode : uint8_t { AUDIO_MODE_API, }; +struct Timer { + std::string id; + std::string name; + uint32_t total_seconds; + uint32_t seconds_left; + bool is_active; + + std::string to_string() const { + return str_sprintf("Timer(id=%s, name=%s, total_seconds=%" PRIu32 ", seconds_left=%" PRIu32 ", is_active=%s)", + this->id.c_str(), this->name.c_str(), this->total_seconds, this->seconds_left, + YESNO(this->is_active)); + } +}; + class VoiceAssistant : public Component { public: void setup() override; @@ -100,6 +118,11 @@ class VoiceAssistant : public Component { flags |= VoiceAssistantFeature::FEATURE_SPEAKER; } #endif + + if (this->has_timers_) { + flags |= VoiceAssistantFeature::FEATURE_TIMERS; + } + return flags; } @@ -108,6 +131,7 @@ class VoiceAssistant : public Component { void on_event(const api::VoiceAssistantEventResponse &msg); void on_audio(const api::VoiceAssistantAudio &msg); + void on_timer_event(const api::VoiceAssistantTimerEventResponse &msg); bool is_running() const { return this->state_ != State::IDLE; } void set_continuous(bool continuous) { this->continuous_ = continuous; } @@ -150,6 +174,14 @@ class VoiceAssistant : public Component { 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_; } + void set_has_timers(bool has_timers) { this->has_timers_ = has_timers; } + const std::unordered_map &get_timers() const { return this->timers_; } + protected: bool allocate_buffers_(); void clear_buffers_(); @@ -186,6 +218,16 @@ class VoiceAssistant : public Component { 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>(); + bool has_timers_{false}; + bool timer_tick_running_{false}; + microphone::Microphone *mic_{nullptr}; #ifdef USE_SPEAKER void write_speaker_(); From a7fc1a62981cf6ae51c2f44d71185c3d89071927 Mon Sep 17 00:00:00 2001 From: RFDarter Date: Thu, 30 May 2024 03:54:20 +0200 Subject: [PATCH 1522/2101] [web_server] add entity sorting for v3 (#6445) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- .../alarm_control_panel/__init__.py | 7 + esphome/components/binary_sensor/__init__.py | 127 ++++++----- esphome/components/button/__init__.py | 31 ++- esphome/components/climate/__init__.py | 185 ++++++++-------- esphome/components/cover/__init__.py | 67 +++--- esphome/components/datetime/__init__.py | 30 ++- esphome/components/fan/__init__.py | 137 ++++++------ esphome/components/light/__init__.py | 59 ++--- esphome/components/lock/__init__.py | 39 ++-- esphome/components/number/__init__.py | 50 +++-- esphome/components/select/__init__.py | 31 ++- esphome/components/sensor/__init__.py | 87 ++++---- esphome/components/switch/__init__.py | 43 ++-- esphome/components/text/__init__.py | 33 +-- esphome/components/text_sensor/__init__.py | 51 +++-- esphome/components/valve/__init__.py | 55 +++-- esphome/components/web_server/__init__.py | 58 +++++ esphome/components/web_server/web_server.cpp | 204 ++++++++++++------ esphome/components/web_server/web_server.h | 9 + esphome/const.py | 2 + 20 files changed, 802 insertions(+), 503 deletions(-) diff --git a/esphome/components/alarm_control_panel/__init__.py b/esphome/components/alarm_control_panel/__init__.py index 35d239c267..7ad4358011 100644 --- a/esphome/components/alarm_control_panel/__init__.py +++ b/esphome/components/alarm_control_panel/__init__.py @@ -1,5 +1,6 @@ import esphome.codegen as cg import esphome.config_validation as cv +from esphome.components import web_server from esphome import automation from esphome.automation import maybe_simple_id from esphome.core import CORE, coroutine_with_priority @@ -8,6 +9,7 @@ from esphome.const import ( CONF_ON_STATE, CONF_TRIGGER_ID, CONF_CODE, + CONF_WEB_SERVER_ID, ) from esphome.cpp_helpers import setup_entity @@ -76,6 +78,8 @@ AlarmControlPanelCondition = alarm_control_panel_ns.class_( ) ALARM_CONTROL_PANEL_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend( + web_server.WEBSERVER_SORTING_SCHEMA +).extend( { cv.GenerateID(): cv.declare_id(AlarmControlPanel), cv.Optional(CONF_ON_STATE): automation.validate_automation( @@ -185,6 +189,9 @@ async def setup_alarm_control_panel_core_(var, config): for conf in config.get(CONF_ON_READY, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) await automation.build_automation(trigger, [], conf) + if (webserver_id := config.get(CONF_WEB_SERVER_ID)) is not None: + web_server_ = await cg.get_variable(webserver_id) + web_server.add_entity_to_sorting_list(web_server_, var, config) async def register_alarm_control_panel(var, config): diff --git a/esphome/components/binary_sensor/__init__.py b/esphome/components/binary_sensor/__init__.py index 2f788d7103..11a1887206 100644 --- a/esphome/components/binary_sensor/__init__.py +++ b/esphome/components/binary_sensor/__init__.py @@ -4,7 +4,7 @@ from esphome.cpp_generator import MockObjClass from esphome.cpp_helpers import setup_entity from esphome import automation, core from esphome.automation import Condition, maybe_simple_id -from esphome.components import mqtt +from esphome.components import mqtt, web_server from esphome.const import ( CONF_DELAY, CONF_DEVICE_CLASS, @@ -27,6 +27,7 @@ from esphome.const import ( CONF_TIMING, CONF_TRIGGER_ID, CONF_MQTT_ID, + CONF_WEB_SERVER_ID, DEVICE_CLASS_BATTERY, DEVICE_CLASS_BATTERY_CHARGING, DEVICE_CLASS_CARBON_MONOXIDE, @@ -385,70 +386,76 @@ def validate_click_timing(value): return value -BINARY_SENSOR_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMPONENT_SCHEMA).extend( - { - cv.GenerateID(): cv.declare_id(BinarySensor), - cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id( - mqtt.MQTTBinarySensorComponent - ), - cv.Optional(CONF_PUBLISH_INITIAL_STATE): 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_CLICK): cv.All( - automation.validate_automation( +BINARY_SENSOR_SCHEMA = ( + cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA) + .extend(cv.MQTT_COMPONENT_SCHEMA) + .extend( + { + cv.GenerateID(): cv.declare_id(BinarySensor), + cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id( + mqtt.MQTTBinarySensorComponent + ), + cv.Optional(CONF_PUBLISH_INITIAL_STATE): 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(ClickTrigger), - cv.Optional( - CONF_MIN_LENGTH, default="50ms" - ): cv.positive_time_period_milliseconds, - cv.Optional( - CONF_MAX_LENGTH, default="350ms" - ): cv.positive_time_period_milliseconds, + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(PressTrigger), } ), - validate_click_timing, - ), - cv.Optional(CONF_ON_DOUBLE_CLICK): cv.All( - automation.validate_automation( + cv.Optional(CONF_ON_RELEASE): automation.validate_automation( { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(DoubleClickTrigger), - cv.Optional( - CONF_MIN_LENGTH, default="50ms" - ): cv.positive_time_period_milliseconds, - cv.Optional( - CONF_MAX_LENGTH, default="350ms" - ): cv.positive_time_period_milliseconds, + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ReleaseTrigger), } ), - validate_click_timing, - ), - cv.Optional(CONF_ON_MULTI_CLICK): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(MultiClickTrigger), - cv.Required(CONF_TIMING): cv.All( - [parse_multi_click_timing_str], validate_multi_click_timing + cv.Optional(CONF_ON_CLICK): cv.All( + automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ClickTrigger), + cv.Optional( + CONF_MIN_LENGTH, default="50ms" + ): cv.positive_time_period_milliseconds, + cv.Optional( + CONF_MAX_LENGTH, default="350ms" + ): cv.positive_time_period_milliseconds, + } ), - cv.Optional( - CONF_INVALID_COOLDOWN, default="1s" - ): cv.positive_time_period_milliseconds, - } - ), - cv.Optional(CONF_ON_STATE): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(StateTrigger), - } - ), - } + validate_click_timing, + ), + cv.Optional(CONF_ON_DOUBLE_CLICK): cv.All( + automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( + DoubleClickTrigger + ), + cv.Optional( + CONF_MIN_LENGTH, default="50ms" + ): cv.positive_time_period_milliseconds, + cv.Optional( + CONF_MAX_LENGTH, default="350ms" + ): cv.positive_time_period_milliseconds, + } + ), + validate_click_timing, + ), + cv.Optional(CONF_ON_MULTI_CLICK): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(MultiClickTrigger), + cv.Required(CONF_TIMING): cv.All( + [parse_multi_click_timing_str], validate_multi_click_timing + ), + cv.Optional( + CONF_INVALID_COOLDOWN, default="1s" + ): cv.positive_time_period_milliseconds, + } + ), + cv.Optional(CONF_ON_STATE): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(StateTrigger), + } + ), + } + ) ) _UNDEF = object() @@ -536,6 +543,10 @@ async def setup_binary_sensor_core_(var, config): mqtt_ = cg.new_Pvariable(mqtt_id, var) await mqtt.register_mqtt_component(mqtt_, config) + if (webserver_id := config.get(CONF_WEB_SERVER_ID)) is not None: + web_server_ = await cg.get_variable(webserver_id) + web_server.add_entity_to_sorting_list(web_server_, var, config) + async def register_binary_sensor(var, config): if not CORE.has_id(config[CONF_ID]): diff --git a/esphome/components/button/__init__.py b/esphome/components/button/__init__.py index 5dcbf7ad01..773ab9d37f 100644 --- a/esphome/components/button/__init__.py +++ b/esphome/components/button/__init__.py @@ -2,7 +2,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation from esphome.automation import maybe_simple_id -from esphome.components import mqtt +from esphome.components import mqtt, web_server from esphome.const import ( CONF_DEVICE_CLASS, CONF_ENTITY_CATEGORY, @@ -11,6 +11,7 @@ from esphome.const import ( CONF_ON_PRESS, CONF_TRIGGER_ID, CONF_MQTT_ID, + CONF_WEB_SERVER_ID, DEVICE_CLASS_EMPTY, DEVICE_CLASS_IDENTIFY, DEVICE_CLASS_RESTART, @@ -43,16 +44,20 @@ ButtonPressTrigger = button_ns.class_( validate_device_class = cv.one_of(*DEVICE_CLASSES, lower=True, space="_") -BUTTON_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA).extend( - { - 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), - } - ), - } +BUTTON_SCHEMA = ( + cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA) + .extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA) + .extend( + { + 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), + } + ), + } + ) ) _UNDEF = object() @@ -92,6 +97,10 @@ async def setup_button_core_(var, config): mqtt_ = cg.new_Pvariable(mqtt_id, var) await mqtt.register_mqtt_component(mqtt_, config) + if (webserver_id := config.get(CONF_WEB_SERVER_ID)) is not None: + web_server_ = await cg.get_variable(webserver_id) + web_server.add_entity_to_sorting_list(web_server_, var, config) + async def register_button(var, config): if not CORE.has_id(config[CONF_ID]): diff --git a/esphome/components/climate/__init__.py b/esphome/components/climate/__init__.py index 7b0a27feae..ccd7a3da4e 100644 --- a/esphome/components/climate/__init__.py +++ b/esphome/components/climate/__init__.py @@ -2,7 +2,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.cpp_helpers import setup_entity from esphome import automation -from esphome.components import mqtt +from esphome.components import mqtt, web_server from esphome.const import ( CONF_ACTION_STATE_TOPIC, CONF_AWAY, @@ -44,6 +44,7 @@ from esphome.const import ( CONF_TRIGGER_ID, CONF_VISUAL, CONF_MQTT_ID, + CONF_WEB_SERVER_ID, ) from esphome.core import CORE, coroutine_with_priority @@ -150,93 +151,97 @@ VISUAL_TEMPERATURE_STEP_SCHEMA = cv.Any( ), ) -CLIMATE_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA).extend( - { - cv.GenerateID(): cv.declare_id(Climate), - cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTClimateComponent), - cv.Optional(CONF_VISUAL, default={}): cv.Schema( - { - cv.Optional(CONF_MIN_TEMPERATURE): cv.temperature, - cv.Optional(CONF_MAX_TEMPERATURE): cv.temperature, - cv.Optional(CONF_TEMPERATURE_STEP): VISUAL_TEMPERATURE_STEP_SCHEMA, - cv.Optional(CONF_MIN_HUMIDITY): cv.percentage_int, - cv.Optional(CONF_MAX_HUMIDITY): cv.percentage_int, - } - ), - cv.Optional(CONF_ACTION_STATE_TOPIC): cv.All( - cv.requires_component("mqtt"), cv.publish_topic - ), - cv.Optional(CONF_AWAY_COMMAND_TOPIC): cv.All( - cv.requires_component("mqtt"), cv.publish_topic - ), - cv.Optional(CONF_AWAY_STATE_TOPIC): cv.All( - cv.requires_component("mqtt"), cv.publish_topic - ), - cv.Optional(CONF_CURRENT_TEMPERATURE_STATE_TOPIC): cv.All( - cv.requires_component("mqtt"), cv.publish_topic - ), - cv.Optional(CONF_CURRENT_HUMIDITY_STATE_TOPIC): cv.All( - cv.requires_component("mqtt"), cv.publish_topic - ), - cv.Optional(CONF_FAN_MODE_COMMAND_TOPIC): cv.All( - cv.requires_component("mqtt"), cv.publish_topic - ), - cv.Optional(CONF_FAN_MODE_STATE_TOPIC): cv.All( - cv.requires_component("mqtt"), cv.publish_topic - ), - cv.Optional(CONF_MODE_COMMAND_TOPIC): cv.All( - cv.requires_component("mqtt"), cv.publish_topic - ), - cv.Optional(CONF_MODE_STATE_TOPIC): cv.All( - cv.requires_component("mqtt"), cv.publish_topic - ), - cv.Optional(CONF_PRESET_COMMAND_TOPIC): cv.All( - cv.requires_component("mqtt"), cv.publish_topic - ), - cv.Optional(CONF_PRESET_STATE_TOPIC): cv.All( - cv.requires_component("mqtt"), cv.publish_topic - ), - cv.Optional(CONF_SWING_MODE_COMMAND_TOPIC): cv.All( - cv.requires_component("mqtt"), cv.publish_topic - ), - cv.Optional(CONF_SWING_MODE_STATE_TOPIC): cv.All( - cv.requires_component("mqtt"), cv.publish_topic - ), - cv.Optional(CONF_TARGET_TEMPERATURE_COMMAND_TOPIC): cv.All( - cv.requires_component("mqtt"), cv.publish_topic - ), - cv.Optional(CONF_TARGET_TEMPERATURE_STATE_TOPIC): cv.All( - cv.requires_component("mqtt"), cv.publish_topic - ), - cv.Optional(CONF_TARGET_TEMPERATURE_HIGH_COMMAND_TOPIC): cv.All( - cv.requires_component("mqtt"), cv.publish_topic - ), - cv.Optional(CONF_TARGET_TEMPERATURE_HIGH_STATE_TOPIC): cv.All( - cv.requires_component("mqtt"), cv.publish_topic - ), - cv.Optional(CONF_TARGET_TEMPERATURE_LOW_COMMAND_TOPIC): cv.All( - cv.requires_component("mqtt"), cv.publish_topic - ), - cv.Optional(CONF_TARGET_TEMPERATURE_LOW_STATE_TOPIC): cv.All( - cv.requires_component("mqtt"), cv.publish_topic - ), - cv.Optional(CONF_TARGET_HUMIDITY_COMMAND_TOPIC): cv.All( - cv.requires_component("mqtt"), cv.publish_topic - ), - cv.Optional(CONF_TARGET_HUMIDITY_STATE_TOPIC): cv.All( - cv.requires_component("mqtt"), cv.publish_topic - ), - cv.Optional(CONF_ON_CONTROL): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ControlTrigger), - } - ), - cv.Optional(CONF_ON_STATE): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(StateTrigger), - } - ), - } +CLIMATE_SCHEMA = ( + cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA) + .extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA) + .extend( + { + cv.GenerateID(): cv.declare_id(Climate), + cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTClimateComponent), + cv.Optional(CONF_VISUAL, default={}): cv.Schema( + { + cv.Optional(CONF_MIN_TEMPERATURE): cv.temperature, + cv.Optional(CONF_MAX_TEMPERATURE): cv.temperature, + cv.Optional(CONF_TEMPERATURE_STEP): VISUAL_TEMPERATURE_STEP_SCHEMA, + cv.Optional(CONF_MIN_HUMIDITY): cv.percentage_int, + cv.Optional(CONF_MAX_HUMIDITY): cv.percentage_int, + } + ), + cv.Optional(CONF_ACTION_STATE_TOPIC): cv.All( + cv.requires_component("mqtt"), cv.publish_topic + ), + cv.Optional(CONF_AWAY_COMMAND_TOPIC): cv.All( + cv.requires_component("mqtt"), cv.publish_topic + ), + cv.Optional(CONF_AWAY_STATE_TOPIC): cv.All( + cv.requires_component("mqtt"), cv.publish_topic + ), + cv.Optional(CONF_CURRENT_TEMPERATURE_STATE_TOPIC): cv.All( + cv.requires_component("mqtt"), cv.publish_topic + ), + cv.Optional(CONF_CURRENT_HUMIDITY_STATE_TOPIC): cv.All( + cv.requires_component("mqtt"), cv.publish_topic + ), + cv.Optional(CONF_FAN_MODE_COMMAND_TOPIC): cv.All( + cv.requires_component("mqtt"), cv.publish_topic + ), + cv.Optional(CONF_FAN_MODE_STATE_TOPIC): cv.All( + cv.requires_component("mqtt"), cv.publish_topic + ), + cv.Optional(CONF_MODE_COMMAND_TOPIC): cv.All( + cv.requires_component("mqtt"), cv.publish_topic + ), + cv.Optional(CONF_MODE_STATE_TOPIC): cv.All( + cv.requires_component("mqtt"), cv.publish_topic + ), + cv.Optional(CONF_PRESET_COMMAND_TOPIC): cv.All( + cv.requires_component("mqtt"), cv.publish_topic + ), + cv.Optional(CONF_PRESET_STATE_TOPIC): cv.All( + cv.requires_component("mqtt"), cv.publish_topic + ), + cv.Optional(CONF_SWING_MODE_COMMAND_TOPIC): cv.All( + cv.requires_component("mqtt"), cv.publish_topic + ), + cv.Optional(CONF_SWING_MODE_STATE_TOPIC): cv.All( + cv.requires_component("mqtt"), cv.publish_topic + ), + cv.Optional(CONF_TARGET_TEMPERATURE_COMMAND_TOPIC): cv.All( + cv.requires_component("mqtt"), cv.publish_topic + ), + cv.Optional(CONF_TARGET_TEMPERATURE_STATE_TOPIC): cv.All( + cv.requires_component("mqtt"), cv.publish_topic + ), + cv.Optional(CONF_TARGET_TEMPERATURE_HIGH_COMMAND_TOPIC): cv.All( + cv.requires_component("mqtt"), cv.publish_topic + ), + cv.Optional(CONF_TARGET_TEMPERATURE_HIGH_STATE_TOPIC): cv.All( + cv.requires_component("mqtt"), cv.publish_topic + ), + cv.Optional(CONF_TARGET_TEMPERATURE_LOW_COMMAND_TOPIC): cv.All( + cv.requires_component("mqtt"), cv.publish_topic + ), + cv.Optional(CONF_TARGET_TEMPERATURE_LOW_STATE_TOPIC): cv.All( + cv.requires_component("mqtt"), cv.publish_topic + ), + cv.Optional(CONF_TARGET_HUMIDITY_COMMAND_TOPIC): cv.All( + cv.requires_component("mqtt"), cv.publish_topic + ), + cv.Optional(CONF_TARGET_HUMIDITY_STATE_TOPIC): cv.All( + cv.requires_component("mqtt"), cv.publish_topic + ), + cv.Optional(CONF_ON_CONTROL): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ControlTrigger), + } + ), + cv.Optional(CONF_ON_STATE): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(StateTrigger), + } + ), + } + ) ) @@ -403,6 +408,10 @@ async def setup_climate_core_(var, config): trigger, [(ClimateCall.operator("ref"), "x")], conf ) + if (webserver_id := config.get(CONF_WEB_SERVER_ID)) is not None: + web_server_ = await cg.get_variable(webserver_id) + web_server.add_entity_to_sorting_list(web_server_, var, config) + async def register_climate(var, config): if not CORE.has_id(config[CONF_ID]): diff --git a/esphome/components/cover/__init__.py b/esphome/components/cover/__init__.py index 8e0371017d..313b2c5928 100644 --- a/esphome/components/cover/__init__.py +++ b/esphome/components/cover/__init__.py @@ -2,7 +2,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation from esphome.automation import maybe_simple_id, Condition -from esphome.components import mqtt +from esphome.components import mqtt, web_server from esphome.const import ( CONF_ID, CONF_DEVICE_CLASS, @@ -16,6 +16,7 @@ from esphome.const import ( CONF_TILT_STATE_TOPIC, CONF_STOP, CONF_MQTT_ID, + CONF_WEB_SERVER_ID, CONF_TRIGGER_ID, DEVICE_CLASS_AWNING, DEVICE_CLASS_BLIND, @@ -88,34 +89,38 @@ CoverClosedTrigger = cover_ns.class_( CONF_ON_CLOSED = "on_closed" -COVER_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA).extend( - { - cv.GenerateID(): cv.declare_id(Cover), - cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTCoverComponent), - 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 - ), - cv.Optional(CONF_POSITION_STATE_TOPIC): cv.All( - cv.requires_component("mqtt"), cv.subscribe_topic - ), - cv.Optional(CONF_TILT_COMMAND_TOPIC): cv.All( - cv.requires_component("mqtt"), cv.subscribe_topic - ), - 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), - } - ), - } +COVER_SCHEMA = ( + cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA) + .extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA) + .extend( + { + cv.GenerateID(): cv.declare_id(Cover), + cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTCoverComponent), + 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 + ), + cv.Optional(CONF_POSITION_STATE_TOPIC): cv.All( + cv.requires_component("mqtt"), cv.subscribe_topic + ), + cv.Optional(CONF_TILT_COMMAND_TOPIC): cv.All( + cv.requires_component("mqtt"), cv.subscribe_topic + ), + 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), + } + ), + } + ) ) @@ -132,6 +137,10 @@ async def setup_cover_core_(var, config): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) await automation.build_automation(trigger, [], conf) + if (webserver_id := config.get(CONF_WEB_SERVER_ID)) is not None: + web_server_ = await cg.get_variable(webserver_id) + web_server.add_entity_to_sorting_list(web_server_, 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/datetime/__init__.py b/esphome/components/datetime/__init__.py index 262f1e2315..c118216a2d 100644 --- a/esphome/components/datetime/__init__.py +++ b/esphome/components/datetime/__init__.py @@ -2,7 +2,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation -from esphome.components import mqtt, time +from esphome.components import mqtt, web_server, time from esphome.const import ( CONF_ID, CONF_ON_TIME, @@ -11,6 +11,7 @@ from esphome.const import ( CONF_TRIGGER_ID, CONF_TYPE, CONF_MQTT_ID, + CONF_WEB_SERVER_ID, CONF_DATE, CONF_DATETIME, CONF_TIME, @@ -63,16 +64,20 @@ DATETIME_MODES = [ ] -_DATETIME_SCHEMA = cv.Schema( - { - cv.Optional(CONF_ON_VALUE): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(DateTimeStateTrigger), - } - ), - cv.GenerateID(CONF_TIME_ID): cv.use_id(time.RealTimeClock), - } -).extend(cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA)) +_DATETIME_SCHEMA = ( + cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA) + .extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA) + .extend( + { + cv.Optional(CONF_ON_VALUE): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(DateTimeStateTrigger), + } + ), + cv.GenerateID(CONF_TIME_ID): cv.use_id(time.RealTimeClock), + } + ) +) def date_schema(class_: MockObjClass) -> cv.Schema: @@ -128,6 +133,9 @@ async def setup_datetime_core_(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) + if (webserver_id := config.get(CONF_WEB_SERVER_ID)) is not None: + web_server_ = await cg.get_variable(webserver_id) + web_server.add_entity_to_sorting_list(web_server_, 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.ESPTime, "x")], conf) diff --git a/esphome/components/fan/__init__.py b/esphome/components/fan/__init__.py index 14cf6cc9c9..847a59baa1 100644 --- a/esphome/components/fan/__init__.py +++ b/esphome/components/fan/__init__.py @@ -2,10 +2,11 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation from esphome.automation import maybe_simple_id -from esphome.components import mqtt +from esphome.components import mqtt, web_server from esphome.const import ( CONF_ID, CONF_MQTT_ID, + CONF_WEB_SERVER_ID, CONF_OSCILLATING, CONF_OSCILLATION_COMMAND_TOPIC, CONF_OSCILLATION_STATE_TOPIC, @@ -79,67 +80,75 @@ FanPresetSetTrigger = fan_ns.class_( FanIsOnCondition = fan_ns.class_("FanIsOnCondition", automation.Condition.template()) FanIsOffCondition = fan_ns.class_("FanIsOffCondition", automation.Condition.template()) -FAN_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA).extend( - { - cv.GenerateID(): cv.declare_id(Fan), - cv.Optional(CONF_RESTORE_MODE, default="ALWAYS_OFF"): cv.enum( - RESTORE_MODES, upper=True, space="_" - ), - cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTFanComponent), - cv.Optional(CONF_OSCILLATION_STATE_TOPIC): cv.All( - cv.requires_component("mqtt"), cv.publish_topic - ), - cv.Optional(CONF_OSCILLATION_COMMAND_TOPIC): cv.All( - cv.requires_component("mqtt"), cv.subscribe_topic - ), - cv.Optional(CONF_SPEED_LEVEL_STATE_TOPIC): cv.All( - cv.requires_component("mqtt"), cv.publish_topic - ), - cv.Optional(CONF_SPEED_LEVEL_COMMAND_TOPIC): cv.All( - cv.requires_component("mqtt"), cv.subscribe_topic - ), - cv.Optional(CONF_SPEED_STATE_TOPIC): cv.All( - cv.requires_component("mqtt"), cv.publish_topic - ), - cv.Optional(CONF_SPEED_COMMAND_TOPIC): cv.All( - cv.requires_component("mqtt"), cv.subscribe_topic - ), - cv.Optional(CONF_ON_STATE): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(FanStateTrigger), - } - ), - cv.Optional(CONF_ON_TURN_ON): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(FanTurnOnTrigger), - } - ), - cv.Optional(CONF_ON_TURN_OFF): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(FanTurnOffTrigger), - } - ), - cv.Optional(CONF_ON_DIRECTION_SET): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(FanDirectionSetTrigger), - } - ), - cv.Optional(CONF_ON_OSCILLATING_SET): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(FanOscillatingSetTrigger), - } - ), - cv.Optional(CONF_ON_SPEED_SET): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(FanSpeedSetTrigger), - } - ), - cv.Optional(CONF_ON_PRESET_SET): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(FanPresetSetTrigger), - } - ), - } +FAN_SCHEMA = ( + cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA) + .extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA) + .extend( + { + cv.GenerateID(): cv.declare_id(Fan), + cv.Optional(CONF_RESTORE_MODE, default="ALWAYS_OFF"): cv.enum( + RESTORE_MODES, upper=True, space="_" + ), + cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTFanComponent), + cv.Optional(CONF_OSCILLATION_STATE_TOPIC): cv.All( + cv.requires_component("mqtt"), cv.publish_topic + ), + cv.Optional(CONF_OSCILLATION_COMMAND_TOPIC): cv.All( + cv.requires_component("mqtt"), cv.subscribe_topic + ), + cv.Optional(CONF_SPEED_LEVEL_STATE_TOPIC): cv.All( + cv.requires_component("mqtt"), cv.publish_topic + ), + cv.Optional(CONF_SPEED_LEVEL_COMMAND_TOPIC): cv.All( + cv.requires_component("mqtt"), cv.subscribe_topic + ), + cv.Optional(CONF_SPEED_STATE_TOPIC): cv.All( + cv.requires_component("mqtt"), cv.publish_topic + ), + cv.Optional(CONF_SPEED_COMMAND_TOPIC): cv.All( + cv.requires_component("mqtt"), cv.subscribe_topic + ), + cv.Optional(CONF_ON_STATE): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(FanStateTrigger), + } + ), + cv.Optional(CONF_ON_TURN_ON): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(FanTurnOnTrigger), + } + ), + cv.Optional(CONF_ON_TURN_OFF): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(FanTurnOffTrigger), + } + ), + cv.Optional(CONF_ON_DIRECTION_SET): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( + FanDirectionSetTrigger + ), + } + ), + cv.Optional(CONF_ON_OSCILLATING_SET): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( + FanOscillatingSetTrigger + ), + } + ), + cv.Optional(CONF_ON_SPEED_SET): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(FanSpeedSetTrigger), + } + ), + cv.Optional(CONF_ON_PRESET_SET): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(FanPresetSetTrigger), + } + ), + } + ) ) _PRESET_MODES_SCHEMA = cv.All( @@ -209,6 +218,10 @@ async def setup_fan_core_(var, config): if (speed_command_topic := config.get(CONF_SPEED_COMMAND_TOPIC)) is not None: cg.add(mqtt_.set_custom_speed_command_topic(speed_command_topic)) + if (webserver_id := config.get(CONF_WEB_SERVER_ID)) is not None: + web_server_ = await cg.get_variable(webserver_id) + web_server.add_entity_to_sorting_list(web_server_, var, config) + for conf in config.get(CONF_ON_STATE, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) await automation.build_automation(trigger, [(Fan.operator("ptr"), "x")], conf) diff --git a/esphome/components/light/__init__.py b/esphome/components/light/__init__.py index fdc4676758..161b4d8cd9 100644 --- a/esphome/components/light/__init__.py +++ b/esphome/components/light/__init__.py @@ -1,7 +1,7 @@ import esphome.codegen as cg import esphome.config_validation as cv import esphome.automation as auto -from esphome.components import mqtt, power_supply +from esphome.components import mqtt, power_supply, web_server from esphome.const import ( CONF_COLOR_CORRECT, CONF_DEFAULT_TRANSITION_LENGTH, @@ -10,6 +10,7 @@ from esphome.const import ( CONF_GAMMA_CORRECT, CONF_ID, CONF_MQTT_ID, + CONF_WEB_SERVER_ID, CONF_POWER_SUPPLY, CONF_RESTORE_MODE, CONF_ON_TURN_OFF, @@ -56,29 +57,35 @@ RESTORE_MODES = { "RESTORE_AND_ON": LightRestoreMode.LIGHT_RESTORE_AND_ON, } -LIGHT_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA).extend( - { - cv.GenerateID(): cv.declare_id(LightState), - cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTJSONLightComponent), - cv.Optional(CONF_RESTORE_MODE, default="ALWAYS_OFF"): cv.enum( - RESTORE_MODES, upper=True, space="_" - ), - cv.Optional(CONF_ON_TURN_ON): auto.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(LightTurnOnTrigger), - } - ), - cv.Optional(CONF_ON_TURN_OFF): auto.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(LightTurnOffTrigger), - } - ), - cv.Optional(CONF_ON_STATE): auto.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(LightStateTrigger), - } - ), - } +LIGHT_SCHEMA = ( + cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA) + .extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA) + .extend( + { + cv.GenerateID(): cv.declare_id(LightState), + cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id( + mqtt.MQTTJSONLightComponent + ), + cv.Optional(CONF_RESTORE_MODE, default="ALWAYS_OFF"): cv.enum( + RESTORE_MODES, upper=True, space="_" + ), + cv.Optional(CONF_ON_TURN_ON): auto.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(LightTurnOnTrigger), + } + ), + cv.Optional(CONF_ON_TURN_OFF): auto.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(LightTurnOffTrigger), + } + ), + cv.Optional(CONF_ON_STATE): auto.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(LightStateTrigger), + } + ), + } + ) ) BINARY_LIGHT_SCHEMA = LIGHT_SCHEMA.extend( @@ -173,6 +180,10 @@ async def setup_light_core_(light_var, output_var, config): mqtt_ = cg.new_Pvariable(mqtt_id, light_var) await mqtt.register_mqtt_component(mqtt_, config) + if (webserver_id := config.get(CONF_WEB_SERVER_ID)) is not None: + web_server_ = await cg.get_variable(webserver_id) + web_server.add_entity_to_sorting_list(web_server_, light_var, config) + async def register_light(output_var, config): light_var = cg.new_Pvariable(config[CONF_ID], output_var) diff --git a/esphome/components/lock/__init__.py b/esphome/components/lock/__init__.py index 457ffa278a..c2d6054ed9 100644 --- a/esphome/components/lock/__init__.py +++ b/esphome/components/lock/__init__.py @@ -2,13 +2,14 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation from esphome.automation import Condition, maybe_simple_id -from esphome.components import mqtt +from esphome.components import mqtt, web_server from esphome.const import ( CONF_ID, CONF_ON_LOCK, CONF_ON_UNLOCK, CONF_TRIGGER_ID, CONF_MQTT_ID, + CONF_WEB_SERVER_ID, ) from esphome.core import CORE, coroutine_with_priority from esphome.cpp_helpers import setup_entity @@ -30,20 +31,24 @@ LockCondition = lock_ns.class_("LockCondition", Condition) LockLockTrigger = lock_ns.class_("LockLockTrigger", automation.Trigger.template()) LockUnlockTrigger = lock_ns.class_("LockUnlockTrigger", automation.Trigger.template()) -LOCK_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMMAND_COMPONENT_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), - } - ), - } +LOCK_SCHEMA = ( + cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA) + .extend(cv.MQTT_COMMAND_COMPONENT_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), + } + ), + } + ) ) @@ -61,6 +66,10 @@ async def setup_lock_core_(var, config): mqtt_ = cg.new_Pvariable(mqtt_id, var) await mqtt.register_mqtt_component(mqtt_, config) + if (webserver_id := config.get(CONF_WEB_SERVER_ID)) is not None: + web_server_ = await cg.get_variable(webserver_id) + web_server.add_entity_to_sorting_list(web_server_, var, config) + async def register_lock(var, config): if not CORE.has_id(config[CONF_ID]): diff --git a/esphome/components/number/__init__.py b/esphome/components/number/__init__.py index 8c3b15d22d..303535c138 100644 --- a/esphome/components/number/__init__.py +++ b/esphome/components/number/__init__.py @@ -2,6 +2,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation from esphome.components import mqtt +from esphome.components import web_server from esphome.const import ( CONF_ABOVE, CONF_BELOW, @@ -18,6 +19,7 @@ from esphome.const import ( CONF_VALUE, CONF_OPERATION, CONF_CYCLE, + CONF_WEB_SERVER_ID, DEVICE_CLASS_APPARENT_POWER, DEVICE_CLASS_AQI, DEVICE_CLASS_ATMOSPHERIC_PRESSURE, @@ -167,26 +169,30 @@ NUMBER_OPERATION_OPTIONS = { validate_device_class = cv.one_of(*DEVICE_CLASSES, lower=True, space="_") validate_unit_of_measurement = cv.string_strict -NUMBER_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMMAND_COMPONENT_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_RANGE): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ValueRangeTrigger), - cv.Optional(CONF_ABOVE): cv.templatable(cv.float_), - cv.Optional(CONF_BELOW): cv.templatable(cv.float_), - }, - cv.has_at_least_one_key(CONF_ABOVE, CONF_BELOW), - ), - cv.Optional(CONF_UNIT_OF_MEASUREMENT): validate_unit_of_measurement, - cv.Optional(CONF_MODE, default="AUTO"): cv.enum(NUMBER_MODES, upper=True), - cv.Optional(CONF_DEVICE_CLASS): validate_device_class, - } +NUMBER_SCHEMA = ( + cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA) + .extend(cv.MQTT_COMMAND_COMPONENT_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_RANGE): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ValueRangeTrigger), + cv.Optional(CONF_ABOVE): cv.templatable(cv.float_), + cv.Optional(CONF_BELOW): cv.templatable(cv.float_), + }, + cv.has_at_least_one_key(CONF_ABOVE, CONF_BELOW), + ), + cv.Optional(CONF_UNIT_OF_MEASUREMENT): validate_unit_of_measurement, + cv.Optional(CONF_MODE, default="AUTO"): cv.enum(NUMBER_MODES, upper=True), + cv.Optional(CONF_DEVICE_CLASS): validate_device_class, + } + ) ) _UNDEF = object() @@ -248,6 +254,10 @@ async def setup_number_core_( mqtt_ = cg.new_Pvariable(mqtt_id, var) await mqtt.register_mqtt_component(mqtt_, config) + if (webserver_id := config.get(CONF_WEB_SERVER_ID)) is not None: + web_server_ = await cg.get_variable(webserver_id) + web_server.add_entity_to_sorting_list(web_server_, var, config) + async def register_number( var, config, *, min_value: float, max_value: float, step: float diff --git a/esphome/components/select/__init__.py b/esphome/components/select/__init__.py index 1d234d5617..073fbef1d4 100644 --- a/esphome/components/select/__init__.py +++ b/esphome/components/select/__init__.py @@ -1,7 +1,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation -from esphome.components import mqtt +from esphome.components import mqtt, web_server from esphome.const import ( CONF_ENTITY_CATEGORY, CONF_ICON, @@ -10,6 +10,7 @@ from esphome.const import ( CONF_OPTION, CONF_TRIGGER_ID, CONF_MQTT_ID, + CONF_WEB_SERVER_ID, CONF_CYCLE, CONF_MODE, CONF_OPERATION, @@ -47,16 +48,20 @@ SELECT_OPERATION_OPTIONS = { } -SELECT_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA).extend( - { - cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTSelectComponent), - cv.GenerateID(): cv.declare_id(Select), - cv.Optional(CONF_ON_VALUE): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(SelectStateTrigger), - } - ), - } +SELECT_SCHEMA = ( + cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA) + .extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA) + .extend( + { + cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTSelectComponent), + cv.GenerateID(): cv.declare_id(Select), + cv.Optional(CONF_ON_VALUE): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(SelectStateTrigger), + } + ), + } + ) ) _UNDEF = object() @@ -99,6 +104,10 @@ async def setup_select_core_(var, config, *, options: list[str]): mqtt_ = cg.new_Pvariable(mqtt_id, var) await mqtt.register_mqtt_component(mqtt_, config) + if (webserver_id := config.get(CONF_WEB_SERVER_ID)) is not None: + web_server_ = await cg.get_variable(webserver_id) + web_server.add_entity_to_sorting_list(web_server_, var, config) + async def register_select(var, config, *, options: list[str]): if not CORE.has_id(config[CONF_ID]): diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index ef5c4cc645..6077f5dc1f 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -3,7 +3,7 @@ import math import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation -from esphome.components import mqtt +from esphome.components import mqtt, web_server from esphome.const import ( CONF_DEVICE_CLASS, CONF_ABOVE, @@ -31,6 +31,7 @@ from esphome.const import ( CONF_UNIT_OF_MEASUREMENT, CONF_WINDOW_SIZE, CONF_MQTT_ID, + CONF_WEB_SERVER_ID, CONF_FORCE_UPDATE, CONF_VALUE, CONF_MIN_VALUE, @@ -252,43 +253,49 @@ validate_accuracy_decimals = cv.int_ validate_icon = cv.icon validate_device_class = cv.one_of(*DEVICE_CLASSES, lower=True, space="_") -SENSOR_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMPONENT_SCHEMA).extend( - { - cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTSensorComponent), - cv.GenerateID(): cv.declare_id(Sensor), - cv.Optional(CONF_UNIT_OF_MEASUREMENT): validate_unit_of_measurement, - cv.Optional(CONF_ACCURACY_DECIMALS): validate_accuracy_decimals, - cv.Optional(CONF_DEVICE_CLASS): validate_device_class, - cv.Optional(CONF_STATE_CLASS): validate_state_class, - cv.Optional(CONF_ENTITY_CATEGORY): sensor_entity_category, - cv.Optional("last_reset_type"): cv.invalid( - "last_reset_type has been removed since 2021.9.0. state_class: total_increasing should be used for total values." - ), - cv.Optional(CONF_FORCE_UPDATE, default=False): cv.boolean, - cv.Optional(CONF_EXPIRE_AFTER): cv.All( - cv.requires_component("mqtt"), - 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_RANGE): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ValueRangeTrigger), - cv.Optional(CONF_ABOVE): cv.templatable(cv.float_), - cv.Optional(CONF_BELOW): cv.templatable(cv.float_), - }, - cv.has_at_least_one_key(CONF_ABOVE, CONF_BELOW), - ), - } +SENSOR_SCHEMA = ( + cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA) + .extend(cv.MQTT_COMPONENT_SCHEMA) + .extend( + { + cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTSensorComponent), + cv.GenerateID(): cv.declare_id(Sensor), + cv.Optional(CONF_UNIT_OF_MEASUREMENT): validate_unit_of_measurement, + cv.Optional(CONF_ACCURACY_DECIMALS): validate_accuracy_decimals, + cv.Optional(CONF_DEVICE_CLASS): validate_device_class, + cv.Optional(CONF_STATE_CLASS): validate_state_class, + cv.Optional(CONF_ENTITY_CATEGORY): sensor_entity_category, + cv.Optional("last_reset_type"): cv.invalid( + "last_reset_type has been removed since 2021.9.0. state_class: total_increasing should be used for total values." + ), + cv.Optional(CONF_FORCE_UPDATE, default=False): cv.boolean, + cv.Optional(CONF_EXPIRE_AFTER): cv.All( + cv.requires_component("mqtt"), + 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_RANGE): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ValueRangeTrigger), + cv.Optional(CONF_ABOVE): cv.templatable(cv.float_), + cv.Optional(CONF_BELOW): cv.templatable(cv.float_), + }, + cv.has_at_least_one_key(CONF_ABOVE, CONF_BELOW), + ), + } + ) ) _UNDEF = object() @@ -772,6 +779,10 @@ async def setup_sensor_core_(var, config): else: cg.add(mqtt_.set_expire_after(expire_after)) + if (webserver_id := config.get(CONF_WEB_SERVER_ID)) is not None: + web_server_ = await cg.get_variable(webserver_id) + web_server.add_entity_to_sorting_list(web_server_, var, config) + async def register_sensor(var, config): if not CORE.has_id(config[CONF_ID]): diff --git a/esphome/components/switch/__init__.py b/esphome/components/switch/__init__.py index e997ec7ca5..3539d0e34e 100644 --- a/esphome/components/switch/__init__.py +++ b/esphome/components/switch/__init__.py @@ -2,7 +2,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation from esphome.automation import Condition, maybe_simple_id -from esphome.components import mqtt +from esphome.components import mqtt, web_server from esphome.const import ( CONF_DEVICE_CLASS, CONF_ENTITY_CATEGORY, @@ -10,6 +10,7 @@ from esphome.const import ( CONF_ID, CONF_INVERTED, CONF_MQTT_ID, + CONF_WEB_SERVER_ID, CONF_ON_TURN_OFF, CONF_ON_TURN_ON, CONF_RESTORE_MODE, @@ -64,22 +65,26 @@ SwitchTurnOffTrigger = switch_ns.class_( validate_device_class = cv.one_of(*DEVICE_CLASSES, lower=True) -_SWITCH_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA).extend( - { - cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTSwitchComponent), - cv.Optional(CONF_INVERTED): cv.boolean, - 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_DEVICE_CLASS): validate_device_class, - } +_SWITCH_SCHEMA = ( + cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA) + .extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA) + .extend( + { + cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTSwitchComponent), + cv.Optional(CONF_INVERTED): cv.boolean, + 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_DEVICE_CLASS): validate_device_class, + } + ) ) _UNDEF = object() @@ -151,6 +156,10 @@ async def setup_switch_core_(var, config): mqtt_ = cg.new_Pvariable(mqtt_id, var) await mqtt.register_mqtt_component(mqtt_, config) + if (webserver_id := config.get(CONF_WEB_SERVER_ID)) is not None: + web_server_ = await cg.get_variable(webserver_id) + web_server.add_entity_to_sorting_list(web_server_, var, config) + if (device_class := config.get(CONF_DEVICE_CLASS)) is not None: cg.add(var.set_device_class(device_class)) diff --git a/esphome/components/text/__init__.py b/esphome/components/text/__init__.py index 4ca055a730..5a8e763495 100644 --- a/esphome/components/text/__init__.py +++ b/esphome/components/text/__init__.py @@ -2,13 +2,14 @@ from typing import Optional import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation -from esphome.components import mqtt +from esphome.components import mqtt, web_server from esphome.const import ( CONF_ID, CONF_MODE, CONF_ON_VALUE, CONF_TRIGGER_ID, CONF_MQTT_ID, + CONF_WEB_SERVER_ID, CONF_VALUE, ) @@ -38,17 +39,21 @@ TEXT_MODES = { "PASSWORD": TextMode.TEXT_MODE_PASSWORD, # to be implemented for keys, passwords, etc. } -TEXT_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMPONENT_SCHEMA).extend( - { - cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTTextComponent), - cv.GenerateID(): cv.declare_id(Text), - cv.Optional(CONF_ON_VALUE): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(TextStateTrigger), - } - ), - cv.Required(CONF_MODE): cv.enum(TEXT_MODES, upper=True), - } +TEXT_SCHEMA = ( + cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA) + .extend(cv.MQTT_COMPONENT_SCHEMA) + .extend( + { + cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTTextComponent), + cv.GenerateID(): cv.declare_id(Text), + cv.Optional(CONF_ON_VALUE): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(TextStateTrigger), + } + ), + cv.Required(CONF_MODE): cv.enum(TEXT_MODES, upper=True), + } + ) ) @@ -77,6 +82,10 @@ async def setup_text_core_( mqtt_ = cg.new_Pvariable(mqtt_id, var) await mqtt.register_mqtt_component(mqtt_, config) + if (webserver_id := config.get(CONF_WEB_SERVER_ID)) is not None: + web_server_ = await cg.get_variable(webserver_id) + web_server.add_entity_to_sorting_list(web_server_, var, config) + async def register_text( var, diff --git a/esphome/components/text_sensor/__init__.py b/esphome/components/text_sensor/__init__.py index 6c28b57b3d..f4e795924c 100644 --- a/esphome/components/text_sensor/__init__.py +++ b/esphome/components/text_sensor/__init__.py @@ -1,7 +1,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation -from esphome.components import mqtt +from esphome.components import mqtt, web_server from esphome.const import ( CONF_DEVICE_CLASS, CONF_ENTITY_CATEGORY, @@ -12,6 +12,7 @@ from esphome.const import ( CONF_ON_RAW_VALUE, CONF_TRIGGER_ID, CONF_MQTT_ID, + CONF_WEB_SERVER_ID, CONF_STATE, CONF_FROM, CONF_TO, @@ -124,25 +125,31 @@ async def map_filter_to_code(config, filter_id): validate_device_class = cv.one_of(*DEVICE_CLASSES, lower=True, space="_") -TEXT_SENSOR_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMPONENT_SCHEMA).extend( - { - cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTTextSensor), - 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 - ), - } - ), - } +TEXT_SENSOR_SCHEMA = ( + cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA) + .extend(cv.MQTT_COMPONENT_SCHEMA) + .extend( + { + cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTTextSensor), + 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 + ), + } + ), + } + ) ) _UNDEF = object() @@ -205,6 +212,10 @@ async def setup_text_sensor_core_(var, config): mqtt_ = cg.new_Pvariable(mqtt_id, var) await mqtt.register_mqtt_component(mqtt_, config) + if (webserver_id := config.get(CONF_WEB_SERVER_ID)) is not None: + web_server_ = await cg.get_variable(webserver_id) + web_server.add_entity_to_sorting_list(web_server_, var, config) + async def register_text_sensor(var, config): if not CORE.has_id(config[CONF_ID]): diff --git a/esphome/components/valve/__init__.py b/esphome/components/valve/__init__.py index ea6bfc6055..c03d13fec8 100644 --- a/esphome/components/valve/__init__.py +++ b/esphome/components/valve/__init__.py @@ -2,7 +2,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation from esphome.automation import maybe_simple_id, Condition -from esphome.components import mqtt +from esphome.components import mqtt, web_server from esphome.const import ( CONF_DEVICE_CLASS, CONF_ID, @@ -14,6 +14,7 @@ from esphome.const import ( CONF_STATE, CONF_STOP, CONF_TRIGGER_ID, + CONF_WEB_SERVER_ID, DEVICE_CLASS_EMPTY, DEVICE_CLASS_GAS, DEVICE_CLASS_WATER, @@ -70,28 +71,32 @@ ValveClosedTrigger = valve_ns.class_( CONF_ON_CLOSED = "on_closed" -VALVE_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA).extend( - { - cv.GenerateID(): cv.declare_id(Valve), - cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTValveComponent), - 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 - ), - cv.Optional(CONF_POSITION_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(ValveOpenTrigger), - } - ), - cv.Optional(CONF_ON_CLOSED): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ValveClosedTrigger), - } - ), - } +VALVE_SCHEMA = ( + cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA) + .extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA) + .extend( + { + cv.GenerateID(): cv.declare_id(Valve), + cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTValveComponent), + 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 + ), + cv.Optional(CONF_POSITION_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(ValveOpenTrigger), + } + ), + cv.Optional(CONF_ON_CLOSED): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ValveClosedTrigger), + } + ), + } + ) ) @@ -119,6 +124,10 @@ async def setup_valve_core_(var, config): mqtt_.set_custom_position_command_topic(position_command_topic_config) ) + if (webserver_id := config.get(CONF_WEB_SERVER_ID)) is not None: + web_server_ = await cg.get_variable(webserver_id) + web_server.add_entity_to_sorting_list(web_server_, var, config) + async def register_valve(var, config): if not CORE.has_id(config[CONF_ID]): diff --git a/esphome/components/web_server/__init__.py b/esphome/components/web_server/__init__.py index fa614fb5a6..232ab40d10 100644 --- a/esphome/components/web_server/__init__.py +++ b/esphome/components/web_server/__init__.py @@ -1,6 +1,9 @@ +from __future__ import annotations + import gzip import esphome.codegen as cg import esphome.config_validation as cv +import esphome.final_validate as fv from esphome.components import web_server_base from esphome.components.web_server_base import CONF_WEB_SERVER_BASE_ID from esphome.const import ( @@ -19,6 +22,8 @@ from esphome.const import ( CONF_LOG, CONF_VERSION, CONF_LOCAL, + CONF_WEB_SERVER_ID, + CONF_WEB_SERVER_SORTING_WEIGHT, PLATFORM_ESP32, PLATFORM_ESP8266, PLATFORM_BK72XX, @@ -64,6 +69,46 @@ def validate_ota(config): return config +def _validate_no_sorting_weight( + webserver_version: int, config: dict, path: list[str] | None = None +) -> None: + if path is None: + path = [] + if CONF_WEB_SERVER_SORTING_WEIGHT in config: + raise cv.FinalExternalInvalid( + f"Sorting weight on entities is not supported in web_server version {webserver_version}", + path=path + [CONF_WEB_SERVER_SORTING_WEIGHT], + ) + for p, value in config.items(): + if isinstance(value, dict): + _validate_no_sorting_weight(webserver_version, value, path + [p]) + elif isinstance(value, list): + for i, item in enumerate(value): + if isinstance(item, dict): + _validate_no_sorting_weight(webserver_version, item, path + [p, i]) + + +def _final_validate_sorting_weight(config): + if (webserver_version := config.get(CONF_VERSION)) != 3: + _validate_no_sorting_weight(webserver_version, fv.full_config.get()) + + return config + + +FINAL_VALIDATE_SCHEMA = _final_validate_sorting_weight + + +WEBSERVER_SORTING_SCHEMA = cv.Schema( + { + cv.OnlyWith(CONF_WEB_SERVER_ID, "web_server"): cv.use_id(WebServer), + cv.Optional(CONF_WEB_SERVER_SORTING_WEIGHT): cv.All( + cv.requires_component("web_server"), + cv.float_, + ), + } +) + + CONFIG_SCHEMA = cv.All( cv.Schema( { @@ -108,6 +153,19 @@ CONFIG_SCHEMA = cv.All( ) +def add_entity_to_sorting_list(web_server, entity, config): + sorting_weight = 50 + if CONF_WEB_SERVER_SORTING_WEIGHT in config: + sorting_weight = config[CONF_WEB_SERVER_SORTING_WEIGHT] + + cg.add( + web_server.add_entity_to_sorting_list( + entity, + sorting_weight, + ) + ) + + def build_index_html(config) -> str: html = "" css_include = config.get(CONF_CSS_INCLUDE) diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index d72307991f..5bb36f9600 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -435,7 +435,7 @@ void WebServer::handle_sensor_request(AsyncWebServerRequest *request, const UrlM request->send(404); } std::string WebServer::sensor_json(sensor::Sensor *obj, float value, JsonDetail start_config) { - return json::build_json([obj, value, start_config](JsonObject root) { + return json::build_json([this, obj, value, start_config](JsonObject root) { std::string state; if (std::isnan(value)) { state = "NA"; @@ -446,6 +446,9 @@ std::string WebServer::sensor_json(sensor::Sensor *obj, float value, JsonDetail } set_json_icon_state_value(root, obj, "sensor-" + obj->get_object_id(), state, value, start_config); if (start_config == DETAIL_ALL) { + if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) { + root["sorting_weight"] = this->sorting_entitys_[obj].weight; + } if (!obj->get_unit_of_measurement().empty()) root["uom"] = obj->get_unit_of_measurement(); } @@ -471,8 +474,13 @@ void WebServer::handle_text_sensor_request(AsyncWebServerRequest *request, const } std::string WebServer::text_sensor_json(text_sensor::TextSensor *obj, const std::string &value, JsonDetail start_config) { - return json::build_json([obj, value, start_config](JsonObject root) { + return json::build_json([this, obj, value, start_config](JsonObject root) { set_json_icon_state_value(root, obj, "text_sensor-" + obj->get_object_id(), value, value, start_config); + if (start_config == DETAIL_ALL) { + if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) { + root["sorting_weight"] = this->sorting_entitys_[obj].weight; + } + } }); } #endif @@ -483,14 +491,6 @@ void WebServer::on_switch_update(switch_::Switch *obj, bool state) { return; this->events_.send(this->switch_json(obj, state, DETAIL_STATE).c_str(), "state"); } -std::string WebServer::switch_json(switch_::Switch *obj, bool value, JsonDetail start_config) { - return json::build_json([obj, value, start_config](JsonObject root) { - set_json_icon_state_value(root, obj, "switch-" + obj->get_object_id(), value ? "ON" : "OFF", value, start_config); - if (start_config == DETAIL_ALL) { - root["assumed_state"] = obj->assumed_state(); - } - }); -} void WebServer::handle_switch_request(AsyncWebServerRequest *request, const UrlMatch &match) { for (switch_::Switch *obj : App.get_switches()) { if (obj->get_object_id() != match.id) @@ -515,14 +515,20 @@ void WebServer::handle_switch_request(AsyncWebServerRequest *request, const UrlM } request->send(404); } +std::string WebServer::switch_json(switch_::Switch *obj, bool value, JsonDetail start_config) { + return json::build_json([this, obj, value, start_config](JsonObject root) { + set_json_icon_state_value(root, obj, "switch-" + obj->get_object_id(), value ? "ON" : "OFF", value, start_config); + if (start_config == DETAIL_ALL) { + root["assumed_state"] = obj->assumed_state(); + if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) { + root["sorting_weight"] = this->sorting_entitys_[obj].weight; + } + } + }); +} #endif #ifdef USE_BUTTON -std::string WebServer::button_json(button::Button *obj, JsonDetail start_config) { - return json::build_json( - [obj, start_config](JsonObject root) { set_json_id(root, obj, "button-" + obj->get_object_id(), start_config); }); -} - void WebServer::handle_button_request(AsyncWebServerRequest *request, const UrlMatch &match) { for (button::Button *obj : App.get_buttons()) { if (obj->get_object_id() != match.id) @@ -538,6 +544,16 @@ void WebServer::handle_button_request(AsyncWebServerRequest *request, const UrlM } request->send(404); } +std::string WebServer::button_json(button::Button *obj, JsonDetail start_config) { + return json::build_json([this, obj, start_config](JsonObject root) { + set_json_id(root, obj, "button-" + obj->get_object_id(), start_config); + if (start_config == DETAIL_ALL) { + if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) { + root["sorting_weight"] = this->sorting_entitys_[obj].weight; + } + } + }); +} #endif #ifdef USE_BINARY_SENSOR @@ -546,12 +562,6 @@ void WebServer::on_binary_sensor_update(binary_sensor::BinarySensor *obj, bool s return; this->events_.send(this->binary_sensor_json(obj, state, DETAIL_STATE).c_str(), "state"); } -std::string WebServer::binary_sensor_json(binary_sensor::BinarySensor *obj, bool value, JsonDetail start_config) { - return json::build_json([obj, value, start_config](JsonObject root) { - set_json_icon_state_value(root, obj, "binary_sensor-" + obj->get_object_id(), value ? "ON" : "OFF", value, - start_config); - }); -} void WebServer::handle_binary_sensor_request(AsyncWebServerRequest *request, const UrlMatch &match) { for (binary_sensor::BinarySensor *obj : App.get_binary_sensors()) { if (obj->get_object_id() != match.id) @@ -562,6 +572,17 @@ void WebServer::handle_binary_sensor_request(AsyncWebServerRequest *request, con } request->send(404); } +std::string WebServer::binary_sensor_json(binary_sensor::BinarySensor *obj, bool value, JsonDetail start_config) { + return json::build_json([this, obj, value, start_config](JsonObject root) { + set_json_icon_state_value(root, obj, "binary_sensor-" + obj->get_object_id(), value ? "ON" : "OFF", value, + start_config); + if (start_config == DETAIL_ALL) { + if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) { + root["sorting_weight"] = this->sorting_entitys_[obj].weight; + } + } + }); +} #endif #ifdef USE_FAN @@ -570,19 +591,6 @@ void WebServer::on_fan_update(fan::Fan *obj) { return; this->events_.send(this->fan_json(obj, DETAIL_STATE).c_str(), "state"); } -std::string WebServer::fan_json(fan::Fan *obj, JsonDetail start_config) { - return json::build_json([obj, start_config](JsonObject root) { - set_json_icon_state_value(root, obj, "fan-" + obj->get_object_id(), obj->state ? "ON" : "OFF", obj->state, - start_config); - const auto traits = obj->get_traits(); - if (traits.supports_speed()) { - root["speed_level"] = obj->speed; - root["speed_count"] = traits.supported_speed_count(); - } - if (obj->get_traits().supports_oscillation()) - root["oscillation"] = obj->oscillating; - }); -} void WebServer::handle_fan_request(AsyncWebServerRequest *request, const UrlMatch &match) { for (fan::Fan *obj : App.get_fans()) { if (obj->get_object_id() != match.id) @@ -635,6 +643,24 @@ void WebServer::handle_fan_request(AsyncWebServerRequest *request, const UrlMatc } request->send(404); } +std::string WebServer::fan_json(fan::Fan *obj, JsonDetail start_config) { + return json::build_json([this, obj, start_config](JsonObject root) { + set_json_icon_state_value(root, obj, "fan-" + obj->get_object_id(), obj->state ? "ON" : "OFF", obj->state, + start_config); + const auto traits = obj->get_traits(); + if (traits.supports_speed()) { + root["speed_level"] = obj->speed; + root["speed_count"] = traits.supported_speed_count(); + } + if (obj->get_traits().supports_oscillation()) + root["oscillation"] = obj->oscillating; + if (start_config == DETAIL_ALL) { + if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) { + root["sorting_weight"] = this->sorting_entitys_[obj].weight; + } + } + }); +} #endif #ifdef USE_LIGHT @@ -729,7 +755,7 @@ void WebServer::handle_light_request(AsyncWebServerRequest *request, const UrlMa request->send(404); } std::string WebServer::light_json(light::LightState *obj, JsonDetail start_config) { - return json::build_json([obj, start_config](JsonObject root) { + return json::build_json([this, obj, start_config](JsonObject root) { set_json_id(root, obj, "light-" + obj->get_object_id(), start_config); root["state"] = obj->remote_values.is_on() ? "ON" : "OFF"; @@ -740,6 +766,9 @@ std::string WebServer::light_json(light::LightState *obj, JsonDetail start_confi for (auto const &option : obj->get_effects()) { opt.add(option->get_name()); } + if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) { + root["sorting_weight"] = this->sorting_entitys_[obj].weight; + } } }); } @@ -803,7 +832,7 @@ void WebServer::handle_cover_request(AsyncWebServerRequest *request, const UrlMa request->send(404); } std::string WebServer::cover_json(cover::Cover *obj, JsonDetail start_config) { - return json::build_json([obj, start_config](JsonObject root) { + return json::build_json([this, obj, start_config](JsonObject root) { set_json_icon_state_value(root, obj, "cover-" + obj->get_object_id(), obj->is_fully_closed() ? "CLOSED" : "OPEN", obj->position, start_config); root["current_operation"] = cover::cover_operation_to_str(obj->current_operation); @@ -812,6 +841,11 @@ std::string WebServer::cover_json(cover::Cover *obj, JsonDetail start_config) { root["position"] = obj->position; if (obj->get_traits().get_supports_tilt()) root["tilt"] = obj->tilt; + if (start_config == DETAIL_ALL) { + if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) { + root["sorting_weight"] = this->sorting_entitys_[obj].weight; + } + } }); } #endif @@ -852,7 +886,7 @@ void WebServer::handle_number_request(AsyncWebServerRequest *request, const UrlM } std::string WebServer::number_json(number::Number *obj, float value, JsonDetail start_config) { - return json::build_json([obj, value, start_config](JsonObject root) { + return json::build_json([this, obj, value, start_config](JsonObject root) { set_json_id(root, obj, "number-" + obj->get_object_id(), start_config); if (start_config == DETAIL_ALL) { root["min_value"] = @@ -864,6 +898,9 @@ std::string WebServer::number_json(number::Number *obj, float value, JsonDetail root["mode"] = (int) obj->traits.get_mode(); if (!obj->traits.get_unit_of_measurement().empty()) root["uom"] = obj->traits.get_unit_of_measurement(); + if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) { + root["sorting_weight"] = this->sorting_entitys_[obj].weight; + } } if (std::isnan(value)) { root["value"] = "\"NaN\""; @@ -919,11 +956,16 @@ void WebServer::handle_date_request(AsyncWebServerRequest *request, const UrlMat } std::string WebServer::date_json(datetime::DateEntity *obj, JsonDetail start_config) { - return json::build_json([obj, start_config](JsonObject root) { + return json::build_json([this, obj, start_config](JsonObject root) { set_json_id(root, obj, "date-" + obj->get_object_id(), start_config); std::string value = str_sprintf("%d-%02d-%02d", obj->year, obj->month, obj->day); root["value"] = value; root["state"] = value; + if (start_config == DETAIL_ALL) { + if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) { + root["sorting_weight"] = this->sorting_entitys_[obj].weight; + } + } }); } #endif // USE_DATETIME_DATE @@ -967,11 +1009,16 @@ void WebServer::handle_time_request(AsyncWebServerRequest *request, const UrlMat request->send(404); } std::string WebServer::time_json(datetime::TimeEntity *obj, JsonDetail start_config) { - return json::build_json([obj, start_config](JsonObject root) { + return json::build_json([this, obj, start_config](JsonObject root) { set_json_id(root, obj, "time-" + obj->get_object_id(), start_config); std::string value = str_sprintf("%02d:%02d:%02d", obj->hour, obj->minute, obj->second); root["value"] = value; root["state"] = value; + if (start_config == DETAIL_ALL) { + if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) { + root["sorting_weight"] = this->sorting_entitys_[obj].weight; + } + } }); } #endif // USE_DATETIME_TIME @@ -1015,12 +1062,17 @@ void WebServer::handle_datetime_request(AsyncWebServerRequest *request, const Ur request->send(404); } std::string WebServer::datetime_json(datetime::DateTimeEntity *obj, JsonDetail start_config) { - return json::build_json([obj, start_config](JsonObject root) { + return json::build_json([this, obj, start_config](JsonObject root) { set_json_id(root, obj, "datetime-" + obj->get_object_id(), start_config); std::string value = str_sprintf("%d-%02d-%02d %02d:%02d:%02d", obj->year, obj->month, obj->day, obj->hour, obj->minute, obj->second); root["value"] = value; root["state"] = value; + if (start_config == DETAIL_ALL) { + if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) { + root["sorting_weight"] = this->sorting_entitys_[obj].weight; + } + } }); } #endif // USE_DATETIME_DATETIME @@ -1060,11 +1112,8 @@ void WebServer::handle_text_request(AsyncWebServerRequest *request, const UrlMat } std::string WebServer::text_json(text::Text *obj, const std::string &value, JsonDetail start_config) { - return json::build_json([obj, value, start_config](JsonObject root) { + return json::build_json([this, obj, value, start_config](JsonObject root) { set_json_id(root, obj, "text-" + obj->get_object_id(), start_config); - if (start_config == DETAIL_ALL) { - root["mode"] = (int) obj->traits.get_mode(); - } root["min_length"] = obj->traits.get_min_length(); root["max_length"] = obj->traits.get_max_length(); root["pattern"] = obj->traits.get_pattern(); @@ -1074,6 +1123,12 @@ std::string WebServer::text_json(text::Text *obj, const std::string &value, Json root["state"] = value; } root["value"] = value; + if (start_config == DETAIL_ALL) { + root["mode"] = (int) obj->traits.get_mode(); + if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) { + root["sorting_weight"] = this->sorting_entitys_[obj].weight; + } + } }); } #endif @@ -1119,13 +1174,16 @@ void WebServer::handle_select_request(AsyncWebServerRequest *request, const UrlM request->send(404); } std::string WebServer::select_json(select::Select *obj, const std::string &value, JsonDetail start_config) { - return json::build_json([obj, value, start_config](JsonObject root) { + return json::build_json([this, obj, value, start_config](JsonObject root) { set_json_icon_state_value(root, obj, "select-" + obj->get_object_id(), value, value, start_config); if (start_config == DETAIL_ALL) { JsonArray opt = root.createNestedArray("option"); for (auto &option : obj->traits.get_options()) { opt.add(option); } + if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) { + root["sorting_weight"] = this->sorting_entitys_[obj].weight; + } } }); } @@ -1140,7 +1198,6 @@ void WebServer::on_climate_update(climate::Climate *obj) { return; this->events_.send(this->climate_json(obj, DETAIL_STATE).c_str(), "state"); } - void WebServer::handle_climate_request(AsyncWebServerRequest *request, const UrlMatch &match) { for (auto *obj : App.get_climates()) { if (obj->get_object_id() != match.id) @@ -1188,9 +1245,8 @@ void WebServer::handle_climate_request(AsyncWebServerRequest *request, const Url } request->send(404); } - std::string WebServer::climate_json(climate::Climate *obj, JsonDetail start_config) { - return json::build_json([obj, start_config](JsonObject root) { + return json::build_json([this, obj, start_config](JsonObject root) { set_json_id(root, obj, "climate-" + obj->get_object_id(), start_config); const auto traits = obj->get_traits(); int8_t target_accuracy = traits.get_target_temperature_accuracy_decimals(); @@ -1227,6 +1283,9 @@ std::string WebServer::climate_json(climate::Climate *obj, JsonDetail start_conf for (auto const &custom_preset : traits.get_supported_custom_presets()) opt.add(custom_preset); } + if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) { + root["sorting_weight"] = this->sorting_entitys_[obj].weight; + } } bool has_state = false; @@ -1283,12 +1342,6 @@ void WebServer::on_lock_update(lock::Lock *obj) { return; this->events_.send(this->lock_json(obj, obj->state, DETAIL_STATE).c_str(), "state"); } -std::string WebServer::lock_json(lock::Lock *obj, lock::LockState value, JsonDetail start_config) { - return json::build_json([obj, value, start_config](JsonObject root) { - set_json_icon_state_value(root, obj, "lock-" + obj->get_object_id(), lock::lock_state_to_string(value), value, - start_config); - }); -} void WebServer::handle_lock_request(AsyncWebServerRequest *request, const UrlMatch &match) { for (lock::Lock *obj : App.get_locks()) { if (obj->get_object_id() != match.id) @@ -1313,6 +1366,17 @@ void WebServer::handle_lock_request(AsyncWebServerRequest *request, const UrlMat } request->send(404); } +std::string WebServer::lock_json(lock::Lock *obj, lock::LockState value, JsonDetail start_config) { + return json::build_json([this, obj, value, start_config](JsonObject root) { + set_json_icon_state_value(root, obj, "lock-" + obj->get_object_id(), lock::lock_state_to_string(value), value, + start_config); + if (start_config == DETAIL_ALL) { + if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) { + root["sorting_weight"] = this->sorting_entitys_[obj].weight; + } + } + }); +} #endif #ifdef USE_VALVE @@ -1366,13 +1430,16 @@ void WebServer::handle_valve_request(AsyncWebServerRequest *request, const UrlMa request->send(404); } std::string WebServer::valve_json(valve::Valve *obj, JsonDetail start_config) { - return json::build_json([obj, start_config](JsonObject root) { + return json::build_json([this, obj, start_config](JsonObject root) { set_json_icon_state_value(root, obj, "valve-" + obj->get_object_id(), obj->is_fully_closed() ? "CLOSED" : "OPEN", obj->position, start_config); root["current_operation"] = valve::valve_operation_to_str(obj->current_operation); if (obj->get_traits().get_supports_position()) root["position"] = obj->position; + if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) { + root["sorting_weight"] = this->sorting_entitys_[obj].weight; + } }); } #endif @@ -1383,15 +1450,6 @@ void WebServer::on_alarm_control_panel_update(alarm_control_panel::AlarmControlP return; this->events_.send(this->alarm_control_panel_json(obj, obj->get_state(), DETAIL_STATE).c_str(), "state"); } -std::string WebServer::alarm_control_panel_json(alarm_control_panel::AlarmControlPanel *obj, - alarm_control_panel::AlarmControlPanelState value, - JsonDetail start_config) { - return json::build_json([obj, value, start_config](JsonObject root) { - char buf[16]; - set_json_icon_state_value(root, obj, "alarm-control-panel-" + obj->get_object_id(), - PSTR_LOCAL(alarm_control_panel_state_to_string(value)), value, start_config); - }); -} void WebServer::handle_alarm_control_panel_request(AsyncWebServerRequest *request, const UrlMatch &match) { for (alarm_control_panel::AlarmControlPanel *obj : App.get_alarm_control_panels()) { if (obj->get_object_id() != match.id) @@ -1405,6 +1463,20 @@ void WebServer::handle_alarm_control_panel_request(AsyncWebServerRequest *reques } request->send(404); } +std::string WebServer::alarm_control_panel_json(alarm_control_panel::AlarmControlPanel *obj, + alarm_control_panel::AlarmControlPanelState value, + JsonDetail start_config) { + return json::build_json([this, obj, value, start_config](JsonObject root) { + char buf[16]; + set_json_icon_state_value(root, obj, "alarm-control-panel-" + obj->get_object_id(), + PSTR_LOCAL(alarm_control_panel_state_to_string(value)), value, start_config); + if (start_config == DETAIL_ALL) { + if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) { + root["sorting_weight"] = this->sorting_entitys_[obj].weight; + } + } + }); +} #endif #ifdef USE_EVENT @@ -1709,6 +1781,10 @@ void WebServer::handleRequest(AsyncWebServerRequest *request) { bool WebServer::isRequestHandlerTrivial() { return false; } +void WebServer::add_entity_to_sorting_list(EntityBase *entity, float weight) { + this->sorting_entitys_[entity] = SortingComponents{weight}; +} + void WebServer::schedule_(std::function &&f) { #ifdef USE_ESP32 xSemaphoreTake(this->to_schedule_lock_, portMAX_DELAY); diff --git a/esphome/components/web_server/web_server.h b/esphome/components/web_server/web_server.h index dda14a7e05..0fb40e2c33 100644 --- a/esphome/components/web_server/web_server.h +++ b/esphome/components/web_server/web_server.h @@ -5,8 +5,10 @@ #include "esphome/components/web_server_base/web_server_base.h" #include "esphome/core/component.h" #include "esphome/core/controller.h" +#include "esphome/core/entity_base.h" #include +#include #ifdef USE_ESP32 #include #include @@ -39,6 +41,10 @@ struct UrlMatch { bool valid; ///< Whether this match is valid }; +struct SortingComponents { + float weight; +}; + enum JsonDetail { DETAIL_ALL, DETAIL_STATE }; /** This class allows users to create a web server with their ESP nodes. @@ -320,12 +326,15 @@ class WebServer : public Controller, public Component, public AsyncWebHandler { /// This web handle is not trivial. bool isRequestHandlerTrivial() override; + void add_entity_to_sorting_list(EntityBase *entity, float weight); + protected: void schedule_(std::function &&f); friend ListEntitiesIterator; web_server_base::WebServerBase *base_; AsyncEventSource events_{"/events"}; ListEntitiesIterator entities_iterator_; + std::map sorting_entitys_; #if USE_WEBSERVER_VERSION == 1 const char *css_url_{nullptr}; const char *js_url_{nullptr}; diff --git a/esphome/const.py b/esphome/const.py index 616b686052..1aafffb5d0 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -904,6 +904,8 @@ CONF_WARM_WHITE = "warm_white" CONF_WARM_WHITE_COLOR_TEMPERATURE = "warm_white_color_temperature" CONF_WATCHDOG_THRESHOLD = "watchdog_threshold" CONF_WEB_SERVER = "web_server" +CONF_WEB_SERVER_ID = "web_server_id" +CONF_WEB_SERVER_SORTING_WEIGHT = "web_server_sorting_weight" CONF_WEIGHT = "weight" CONF_WHILE = "while" CONF_WHITE = "white" From c130ddbe9cabcfa88ade0d489414aecc82850548 Mon Sep 17 00:00:00 2001 From: Michael Hansen Date: Wed, 29 May 2024 20:58:13 -0500 Subject: [PATCH 1523/2101] [micro_wake_word] Ensure model string is Path (#6826) --- esphome/components/micro_wake_word/__init__.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/esphome/components/micro_wake_word/__init__.py b/esphome/components/micro_wake_word/__init__.py index 9073d103f1..def2808e54 100644 --- a/esphome/components/micro_wake_word/__init__.py +++ b/esphome/components/micro_wake_word/__init__.py @@ -329,11 +329,14 @@ async def to_code(config): file: Path = base_dir / h.hexdigest()[:8] / model_config[CONF_FILE] elif model_config[CONF_TYPE] == TYPE_LOCAL: - file = model_config[CONF_PATH] + file = Path(model_config[CONF_PATH]) elif model_config[CONF_TYPE] == TYPE_HTTP: file = _compute_local_file_path(model_config) / "manifest.json" + else: + raise ValueError("Unsupported config type: {model_config[CONF_TYPE]}") + manifest, data = _load_model_data(file) rhs = [HexInt(x) for x in data] From 9de8eaff24f63a0acc25fdc555babfc3b54c7b27 Mon Sep 17 00:00:00 2001 From: Erdem Date: Thu, 30 May 2024 08:31:09 +0300 Subject: [PATCH 1524/2101] Fix DHT reading timing for SI7021 on ESP32 (#6604) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/dht/dht.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/esphome/components/dht/dht.cpp b/esphome/components/dht/dht.cpp index 5112092073..db1c851d5f 100644 --- a/esphome/components/dht/dht.cpp +++ b/esphome/components/dht/dht.cpp @@ -86,9 +86,14 @@ bool HOT IRAM_ATTR DHT::read_sensor_(float *temperature, float *humidity, bool r if (this->model_ == DHT_MODEL_DHT11) { delayMicroseconds(18000); } else if (this->model_ == DHT_MODEL_SI7021) { +#ifdef USE_ESP8266 delayMicroseconds(500); this->pin_->digital_write(true); delayMicroseconds(40); +#else + delayMicroseconds(400); + this->pin_->digital_write(true); +#endif } else if (this->model_ == DHT_MODEL_DHT22_TYPE2) { delayMicroseconds(2000); } else if (this->model_ == DHT_MODEL_AM2120 || this->model_ == DHT_MODEL_AM2302) { From 63fc8ab10a52fc118c89218e40ccc919877a19f9 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 30 May 2024 19:59:15 +1200 Subject: [PATCH 1525/2101] [core] Const-ify some Component fields (#6831) --- esphome/core/component.cpp | 8 ++++---- esphome/core/component.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index 594e8ff7df..ae73a451d9 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -1,11 +1,11 @@ #include "esphome/core/component.h" +#include +#include #include "esphome/core/application.h" #include "esphome/core/hal.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" -#include -#include namespace esphome { @@ -140,8 +140,8 @@ void Component::set_retry(uint32_t initial_wait_time, uint8_t max_attempts, std: float backoff_increase_factor) { // NOLINT App.scheduler.set_retry(this, "", initial_wait_time, max_attempts, std::move(f), backoff_increase_factor); } -bool Component::is_failed() { return (this->component_state_ & COMPONENT_STATE_MASK) == COMPONENT_STATE_FAILED; } -bool Component::is_ready() { +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_SETUP; } diff --git a/esphome/core/component.h b/esphome/core/component.h index e6ffe96d1e..a6bd8f81ac 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -118,9 +118,9 @@ class Component { */ virtual void mark_failed(); - bool is_failed(); + bool is_failed() const; - bool is_ready(); + bool is_ready() const; virtual bool can_proceed(); From 8aba890e6974b40fffa14271b63371d179949733 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 30 May 2024 20:00:09 +1200 Subject: [PATCH 1526/2101] [voice_assistant] Half the microphone ringbuffer size (#6830) --- esphome/components/voice_assistant/voice_assistant.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index 0bd8194190..c2fd14fbd5 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -18,7 +18,7 @@ static const char *const TAG = "voice_assistant"; static const size_t SAMPLE_RATE_HZ = 16000; static const size_t INPUT_BUFFER_SIZE = 32 * SAMPLE_RATE_HZ / 1000; // 32ms * 16kHz / 1000ms -static const size_t BUFFER_SIZE = 1024 * SAMPLE_RATE_HZ / 1000; +static const size_t BUFFER_SIZE = 512 * SAMPLE_RATE_HZ / 1000; static const size_t SEND_BUFFER_SIZE = INPUT_BUFFER_SIZE * sizeof(int16_t); static const size_t RECEIVE_SIZE = 1024; static const size_t SPEAKER_BUFFER_SIZE = 16 * RECEIVE_SIZE; From dd2788133683cc7485008559de7d1a4b7ae21825 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 30 May 2024 20:01:39 +1200 Subject: [PATCH 1527/2101] [i2s_speaker] Add buffer allocation failure checks (#6829) --- .../i2s_audio/speaker/i2s_audio_speaker.cpp | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp index 69536742cb..546c2c98f7 100644 --- a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +++ b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp @@ -19,10 +19,27 @@ void I2SAudioSpeaker::setup() { ESP_LOGCONFIG(TAG, "Setting up I2S Audio Speaker..."); this->buffer_queue_ = xQueueCreate(BUFFER_COUNT, sizeof(DataEvent)); + if (this->buffer_queue_ == nullptr) { + ESP_LOGE(TAG, "Failed to create buffer queue"); + this->mark_failed(); + return; + } + this->event_queue_ = xQueueCreate(BUFFER_COUNT, sizeof(TaskEvent)); + if (this->event_queue_ == nullptr) { + ESP_LOGE(TAG, "Failed to create event queue"); + this->mark_failed(); + return; + } } -void I2SAudioSpeaker::start() { this->state_ = speaker::STATE_STARTING; } +void I2SAudioSpeaker::start() { + if (this->is_failed()) { + ESP_LOGE(TAG, "Cannot start audio, speaker failed to setup"); + return; + } + this->state_ = speaker::STATE_STARTING; +} void I2SAudioSpeaker::start_() { if (!this->parent_->try_lock()) { return; // Waiting for another i2s component to return lock @@ -141,6 +158,8 @@ void I2SAudioSpeaker::player_task(void *params) { } void I2SAudioSpeaker::stop() { + if (this->is_failed()) + return; if (this->state_ == speaker::STATE_STOPPED) return; if (this->state_ == speaker::STATE_STARTING) { @@ -200,6 +219,10 @@ void I2SAudioSpeaker::loop() { } size_t I2SAudioSpeaker::play(const uint8_t *data, size_t length) { + if (this->is_failed()) { + ESP_LOGE(TAG, "Cannot play audio, speaker failed to setup"); + return 0; + } if (this->state_ != speaker::STATE_RUNNING && this->state_ != speaker::STATE_STARTING) { this->start(); } From 8dfe1d52203e5ab6d07baaea74b981bf3c6cab98 Mon Sep 17 00:00:00 2001 From: Anton Viktorov Date: Thu, 30 May 2024 08:46:52 +0000 Subject: [PATCH 1528/2101] LTR-303, LTR-329, LTR-553, LTR-556, LTR-559, LTR-659 Series of Lite-On Light (ALS) and Proximity(PS) sensors (#6076) * LTR303 and LTR329 light sensors * LTR303 tidy up * LTR303 unused var * LTR303 tidy up + test * LTR303 auto sensitivity mode * LTR303 auto sensitivity mode tidy * LTR303 State machine version * LTR303 name fix * publish split * minor * new definitions for LTR * als-ps test * als-ps test * als-ps test * ps options * ps options * trgger bug fixed * trgger bug fixed * Minor comments * ltr303->ltr_als_ps * codeowners, tests * tidy up * tidy up * tidy up * gain enum name fix * auto gain fix * tweaks * new style tests * als/ps separate init * logd->logv * reconfiguration count changed * old-style tests removed * const py * ambient light const in vmel7700 and ltr390 * Update esphome/components/ltr_als_ps/ltr_als_ps.cpp Co-authored-by: Keith Burzinski * Apply suggestions from code review Co-authored-by: Keith Burzinski * remove commented code --------- Co-authored-by: Keith Burzinski --- CODEOWNERS | 1 + esphome/components/ltr390/sensor.py | 8 +- esphome/components/ltr_als_ps/__init__.py | 1 + esphome/components/ltr_als_ps/ltr_als_ps.cpp | 519 ++++++++++++++++++ esphome/components/ltr_als_ps/ltr_als_ps.h | 184 +++++++ .../components/ltr_als_ps/ltr_definitions.h | 275 ++++++++++ esphome/components/ltr_als_ps/sensor.py | 271 +++++++++ esphome/components/veml7700/sensor.py | 8 +- esphome/const.py | 1 + tests/components/ltr_als_ps/common.yaml | 11 + .../ltr_als_ps/test.esp32-c3-idf.yaml | 6 + .../components/ltr_als_ps/test.esp32-c3.yaml | 6 + .../components/ltr_als_ps/test.esp32-idf.yaml | 6 + tests/components/ltr_als_ps/test.esp32.yaml | 6 + tests/components/ltr_als_ps/test.esp8266.yaml | 6 + tests/components/ltr_als_ps/test.rp2040.yaml | 6 + 16 files changed, 1307 insertions(+), 8 deletions(-) create mode 100644 esphome/components/ltr_als_ps/__init__.py create mode 100644 esphome/components/ltr_als_ps/ltr_als_ps.cpp create mode 100644 esphome/components/ltr_als_ps/ltr_als_ps.h create mode 100644 esphome/components/ltr_als_ps/ltr_definitions.h create mode 100644 esphome/components/ltr_als_ps/sensor.py create mode 100644 tests/components/ltr_als_ps/common.yaml create mode 100644 tests/components/ltr_als_ps/test.esp32-c3-idf.yaml create mode 100644 tests/components/ltr_als_ps/test.esp32-c3.yaml create mode 100644 tests/components/ltr_als_ps/test.esp32-idf.yaml create mode 100644 tests/components/ltr_als_ps/test.esp32.yaml create mode 100644 tests/components/ltr_als_ps/test.esp8266.yaml create mode 100644 tests/components/ltr_als_ps/test.rp2040.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 8b6143859a..0dc5339193 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -210,6 +210,7 @@ esphome/components/lilygo_t5_47/touchscreen/* @jesserockz esphome/components/lock/* @esphome/core esphome/components/logger/* @esphome/core esphome/components/ltr390/* @sjtrny +esphome/components/ltr_als_ps/* @latonita esphome/components/matrix_keypad/* @ssieb esphome/components/max31865/* @DAVe3283 esphome/components/max44009/* @berfenger diff --git a/esphome/components/ltr390/sensor.py b/esphome/components/ltr390/sensor.py index fe8cad00b6..8b2676599c 100644 --- a/esphome/components/ltr390/sensor.py +++ b/esphome/components/ltr390/sensor.py @@ -2,14 +2,15 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import i2c, sensor from esphome.const import ( - CONF_ID, + CONF_AMBIENT_LIGHT, CONF_GAIN, + CONF_ID, CONF_LIGHT, CONF_RESOLUTION, - UNIT_LUX, - ICON_BRIGHTNESS_5, DEVICE_CLASS_EMPTY, DEVICE_CLASS_ILLUMINANCE, + ICON_BRIGHTNESS_5, + UNIT_LUX, ) CODEOWNERS = ["@sjtrny"] @@ -21,7 +22,6 @@ LTR390Component = ltr390_ns.class_( "LTR390Component", cg.PollingComponent, i2c.I2CDevice ) -CONF_AMBIENT_LIGHT = "ambient_light" CONF_UV_INDEX = "uv_index" CONF_UV = "uv" CONF_WINDOW_CORRECTION_FACTOR = "window_correction_factor" diff --git a/esphome/components/ltr_als_ps/__init__.py b/esphome/components/ltr_als_ps/__init__.py new file mode 100644 index 0000000000..dd06cfffea --- /dev/null +++ b/esphome/components/ltr_als_ps/__init__.py @@ -0,0 +1 @@ +CODEOWNERS = ["@latonita"] diff --git a/esphome/components/ltr_als_ps/ltr_als_ps.cpp b/esphome/components/ltr_als_ps/ltr_als_ps.cpp new file mode 100644 index 0000000000..ae299c9b66 --- /dev/null +++ b/esphome/components/ltr_als_ps/ltr_als_ps.cpp @@ -0,0 +1,519 @@ +#include "ltr_als_ps.h" +#include "esphome/core/application.h" +#include "esphome/core/log.h" +#include "esphome/core/helpers.h" + +using esphome::i2c::ErrorCode; + +namespace esphome { +namespace ltr_als_ps { + +static const char *const TAG = "ltr_als_ps"; + +static const uint8_t MAX_TRIES = 5; + +template T get_next(const T (&array)[size], const T val) { + size_t i = 0; + size_t idx = -1; + while (idx == -1 && i < size) { + if (array[i] == val) { + idx = i; + break; + } + i++; + } + if (idx == -1 || i + 1 >= size) + return val; + return array[i + 1]; +} + +template T get_prev(const T (&array)[size], const T val) { + size_t i = size - 1; + size_t idx = -1; + while (idx == -1 && i > 0) { + if (array[i] == val) { + idx = i; + break; + } + i--; + } + if (idx == -1 || i == 0) + return val; + return array[i - 1]; +} + +static uint16_t get_itime_ms(IntegrationTime time) { + static const uint16_t ALS_INT_TIME[8] = {100, 50, 200, 400, 150, 250, 300, 350}; + return ALS_INT_TIME[time & 0b111]; +} + +static uint16_t get_meas_time_ms(MeasurementRepeatRate rate) { + static const uint16_t ALS_MEAS_RATE[8] = {50, 100, 200, 500, 1000, 2000, 2000, 2000}; + return ALS_MEAS_RATE[rate & 0b111]; +} + +static float get_gain_coeff(AlsGain gain) { + static const float ALS_GAIN[8] = {1, 2, 4, 8, 0, 0, 48, 96}; + return ALS_GAIN[gain & 0b111]; +} + +static float get_ps_gain_coeff(PsGain gain) { + static const float PS_GAIN[4] = {16, 0, 32, 64}; + return PS_GAIN[gain & 0b11]; +} + +void LTRAlsPsComponent::setup() { + ESP_LOGCONFIG(TAG, "Setting up LTR-303/329/55x/659"); + // As per datasheet we need to wait at least 100ms after power on to get ALS chip responsive + this->set_timeout(100, [this]() { this->state_ = State::DELAYED_SETUP; }); +} + +void LTRAlsPsComponent::dump_config() { + auto get_device_type = [](LtrType typ) { + switch (typ) { + case LtrType::LTR_TYPE_ALS_ONLY: + return "ALS only"; + case LtrType::LTR_TYPE_PS_ONLY: + return "PS only"; + case LtrType::LTR_TYPE_ALS_AND_PS: + return "ALS + PS"; + default: + return "Unknown"; + } + }; + + LOG_I2C_DEVICE(this); + ESP_LOGCONFIG(TAG, " Device type: %s", get_device_type(this->ltr_type_)); + if (this->is_als_()) { + ESP_LOGCONFIG(TAG, " Automatic mode: %s", ONOFF(this->automatic_mode_enabled_)); + ESP_LOGCONFIG(TAG, " Gain: %.0fx", get_gain_coeff(this->gain_)); + ESP_LOGCONFIG(TAG, " Integration time: %d ms", get_itime_ms(this->integration_time_)); + ESP_LOGCONFIG(TAG, " Measurement repeat rate: %d ms", get_meas_time_ms(this->repeat_rate_)); + ESP_LOGCONFIG(TAG, " Glass attenuation factor: %f", this->glass_attenuation_factor_); + LOG_SENSOR(" ", "ALS calculated lux", this->ambient_light_sensor_); + LOG_SENSOR(" ", "CH1 Infrared counts", this->infrared_counts_sensor_); + LOG_SENSOR(" ", "CH0 Visible+IR counts", this->full_spectrum_counts_sensor_); + LOG_SENSOR(" ", "Actual gain", this->actual_gain_sensor_); + } + if (this->is_ps_()) { + ESP_LOGCONFIG(TAG, " Proximity gain: %.0fx", get_ps_gain_coeff(this->ps_gain_)); + ESP_LOGCONFIG(TAG, " Proximity cooldown time: %d s", this->ps_cooldown_time_s_); + ESP_LOGCONFIG(TAG, " Proximity high threshold: %d", this->ps_threshold_high_); + ESP_LOGCONFIG(TAG, " Proximity low threshold: %d", this->ps_threshold_low_); + LOG_SENSOR(" ", "Proximity counts", this->proximity_counts_sensor_); + } + LOG_UPDATE_INTERVAL(this); + + if (this->is_failed()) { + ESP_LOGE(TAG, "Communication with I2C LTR-303/329/55x/659 failed!"); + } +} + +void LTRAlsPsComponent::update() { + ESP_LOGV(TAG, "Updating"); + if (this->is_ready() && this->state_ == State::IDLE) { + ESP_LOGV(TAG, "Initiating new data collection"); + + this->state_ = this->automatic_mode_enabled_ ? State::COLLECTING_DATA_AUTO : State::WAITING_FOR_DATA; + + this->als_readings_.ch0 = 0; + this->als_readings_.ch1 = 0; + this->als_readings_.gain = this->gain_; + this->als_readings_.integration_time = this->integration_time_; + this->als_readings_.lux = 0; + this->als_readings_.number_of_adjustments = 0; + + } else { + ESP_LOGV(TAG, "Component not ready yet"); + } +} + +void LTRAlsPsComponent::loop() { + ErrorCode err = i2c::ERROR_OK; + static uint8_t tries{0}; + + switch (this->state_) { + case State::DELAYED_SETUP: + err = this->write(nullptr, 0); + if (err != i2c::ERROR_OK) { + ESP_LOGV(TAG, "i2c connection failed"); + this->mark_failed(); + } + this->configure_reset_(); + if (this->is_als_()) { + this->configure_als_(); + this->configure_integration_time_(this->integration_time_); + } + if (this->is_ps_()) { + this->configure_ps_(); + } + + this->state_ = State::IDLE; + break; + + case State::IDLE: + if (this->is_ps_()) { + check_and_trigger_ps_(); + } + break; + + case State::WAITING_FOR_DATA: + if (this->is_als_data_ready_(this->als_readings_) == DataAvail::DATA_OK) { + 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) { + ESP_LOGW(TAG, "Can't get data after several tries."); + tries = 0; + this->status_set_warning(); + this->state_ = State::IDLE; + return; + } else { + tries++; + } + break; + + case State::COLLECTING_DATA_AUTO: + case State::DATA_COLLECTED: + // first measurement in auto mode (COLLECTING_DATA_AUTO state) require device reconfiguration + if (this->state_ == State::COLLECTING_DATA_AUTO || this->are_adjustments_required_(this->als_readings_)) { + this->state_ = State::ADJUSTMENT_IN_PROGRESS; + ESP_LOGD(TAG, "Reconfiguring sensitivity: gain = %.0fx, time = %d ms", get_gain_coeff(this->als_readings_.gain), + get_itime_ms(this->als_readings_.integration_time)); + this->configure_integration_time_(this->als_readings_.integration_time); + this->configure_gain_(this->als_readings_.gain); + // if sensitivity adjustment needed - need to wait for first data samples after setting new parameters + this->set_timeout(2 * get_meas_time_ms(this->repeat_rate_), + [this]() { this->state_ = State::WAITING_FOR_DATA; }); + } else { + this->state_ = State::READY_TO_PUBLISH; + } + break; + + case State::ADJUSTMENT_IN_PROGRESS: + // nothing to be done, just waiting for the timeout + break; + + case State::READY_TO_PUBLISH: + this->publish_data_part_1_(this->als_readings_); + this->state_ = State::KEEP_PUBLISHING; + break; + + case State::KEEP_PUBLISHING: + this->publish_data_part_2_(this->als_readings_); + this->status_clear_warning(); + this->state_ = State::IDLE; + break; + + default: + break; + } +} + +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; + 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; + 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(); + } + } +} + +bool LTRAlsPsComponent::check_part_number_() { + uint8_t manuf_id = this->reg((uint8_t) CommandRegisters::MANUFAC_ID).get(); + if (manuf_id != 0x05) { // 0x05 is Lite-On Semiconductor Corp. ID + ESP_LOGW(TAG, "Unknown manufacturer ID: 0x%02X", manuf_id); + this->mark_failed(); + return false; + } + + // Things getting not really funny here, we can't identify device type by part number ID + // ======================== ========= ===== ================= + // Device Part ID Rev Capabilities + // ======================== ========= ===== ================= + // Ltr-329/ltr-303 0x0a 0x00 Als 16b + // Ltr-553/ltr-556/ltr-556 0x09 0x02 Als 16b + Ps 11b diff nm sens + // Ltr-659 0x09 0x02 Ps 11b and ps gain + // + // There are other devices which might potentially work with default settings, + // but registers layout is different and we can't use them properly. For ex. ltr-558 + + PartIdRegister part_id{0}; + part_id.raw = this->reg((uint8_t) CommandRegisters::PART_ID).get(); + if (part_id.part_number_id != 0x0a && part_id.part_number_id != 0x09) { + ESP_LOGW(TAG, "Unknown part number ID: 0x%02X. It might not work properly.", part_id.part_number_id); + this->status_set_warning(); + return true; + } + return true; +} + +void LTRAlsPsComponent::configure_reset_() { + ESP_LOGV(TAG, "Resetting"); + + AlsControlRegister als_ctrl{0}; + als_ctrl.sw_reset = true; + this->reg((uint8_t) CommandRegisters::ALS_CONTR) = als_ctrl.raw; + delay(2); + + uint8_t tries = MAX_TRIES; + do { + ESP_LOGV(TAG, "Waiting for chip to reset"); + delay(2); + als_ctrl.raw = this->reg((uint8_t) CommandRegisters::ALS_CONTR).get(); + } while (als_ctrl.sw_reset && tries--); // while sw reset bit is on - keep waiting + + if (als_ctrl.sw_reset) { + ESP_LOGW(TAG, "Reset timed out"); + } +} + +void LTRAlsPsComponent::configure_als_() { + AlsControlRegister als_ctrl{0}; + + als_ctrl.sw_reset = false; + als_ctrl.active_mode = true; + als_ctrl.gain = this->gain_; + + ESP_LOGV(TAG, "Setting active mode and gain reg 0x%02X", als_ctrl.raw); + this->reg((uint8_t) CommandRegisters::ALS_CONTR) = als_ctrl.raw; + delay(5); + + uint8_t tries = MAX_TRIES; + do { + ESP_LOGV(TAG, "Waiting for device to become active..."); + delay(2); + als_ctrl.raw = this->reg((uint8_t) CommandRegisters::ALS_CONTR).get(); + } while (!als_ctrl.active_mode && tries--); // while active mode is not set - keep waiting + + if (!als_ctrl.active_mode) { + ESP_LOGW(TAG, "Failed to activate device"); + } +} + +void LTRAlsPsComponent::configure_ps_() { + PsMeasurementRateRegister ps_meas{0}; + ps_meas.ps_measurement_rate = PsMeasurementRate::PS_MEAS_RATE_50MS; + this->reg((uint8_t) CommandRegisters::PS_MEAS_RATE) = ps_meas.raw; + + PsControlRegister ps_ctrl{0}; + ps_ctrl.ps_mode_active = true; + ps_ctrl.ps_mode_xxx = true; + this->reg((uint8_t) CommandRegisters::PS_CONTR) = ps_ctrl.raw; +} + +uint16_t LTRAlsPsComponent::read_ps_data_() { + AlsPsStatusRegister als_status{0}; + als_status.raw = this->reg((uint8_t) CommandRegisters::ALS_PS_STATUS).get(); + if (!als_status.ps_new_data || als_status.data_invalid) { + return this->ps_readings_; + } + + uint8_t ps_low = this->reg((uint8_t) CommandRegisters::PS_DATA_0).get(); + PsData1Register ps_high; + ps_high.raw = this->reg((uint8_t) CommandRegisters::PS_DATA_1).get(); + + uint16_t val = encode_uint16(ps_high.ps_data_high, ps_low); + if (ps_high.ps_saturation_flag) { + return 0x7ff; // full 11 bit range + } + return val; +} + +void LTRAlsPsComponent::configure_gain_(AlsGain gain) { + AlsControlRegister als_ctrl{0}; + als_ctrl.active_mode = true; + als_ctrl.gain = gain; + this->reg((uint8_t) CommandRegisters::ALS_CONTR) = als_ctrl.raw; + delay(2); + + AlsControlRegister read_als_ctrl{0}; + read_als_ctrl.raw = this->reg((uint8_t) CommandRegisters::ALS_CONTR).get(); + if (read_als_ctrl.gain != gain) { + ESP_LOGW(TAG, "Failed to set gain. We will try one more time."); + this->reg((uint8_t) CommandRegisters::ALS_CONTR) = als_ctrl.raw; + delay(2); + } +} + +void LTRAlsPsComponent::configure_integration_time_(IntegrationTime time) { + MeasurementRateRegister meas{0}; + meas.measurement_repeat_rate = this->repeat_rate_; + meas.integration_time = time; + this->reg((uint8_t) CommandRegisters::MEAS_RATE) = meas.raw; + delay(2); + + MeasurementRateRegister read_meas{0}; + read_meas.raw = this->reg((uint8_t) CommandRegisters::MEAS_RATE).get(); + if (read_meas.integration_time != time) { + ESP_LOGW(TAG, "Failed to set integration time. We will try one more time."); + this->reg((uint8_t) CommandRegisters::MEAS_RATE) = meas.raw; + delay(2); + } +} + +DataAvail LTRAlsPsComponent::is_als_data_ready_(AlsReadings &data) { + AlsPsStatusRegister als_status{0}; + + als_status.raw = this->reg((uint8_t) CommandRegisters::ALS_PS_STATUS).get(); + if (!als_status.als_new_data) + return DataAvail::NO_DATA; + + if (als_status.data_invalid) { + ESP_LOGW(TAG, "Data available but not valid"); + return DataAvail::BAD_DATA; + } + ESP_LOGV(TAG, "Data ready, reported gain is %.0f", get_gain_coeff(als_status.gain)); + if (data.gain != als_status.gain) { + ESP_LOGW(TAG, "Actual gain differs from requested (%.0f)", get_gain_coeff(data.gain)); + return DataAvail::BAD_DATA; + } + return DataAvail::DATA_OK; +} + +void LTRAlsPsComponent::read_sensor_data_(AlsReadings &data) { + data.ch1 = 0; + data.ch0 = 0; + uint8_t ch1_0 = this->reg((uint8_t) CommandRegisters::ALS_DATA_CH1_0).get(); + uint8_t ch1_1 = this->reg((uint8_t) CommandRegisters::ALS_DATA_CH1_1).get(); + uint8_t ch0_0 = this->reg((uint8_t) CommandRegisters::ALS_DATA_CH0_0).get(); + uint8_t ch0_1 = this->reg((uint8_t) CommandRegisters::ALS_DATA_CH0_1).get(); + data.ch1 = encode_uint16(ch1_1, ch1_0); + data.ch0 = encode_uint16(ch0_1, ch0_0); + + ESP_LOGV(TAG, "Got sensor data: CH1 = %d, CH0 = %d", data.ch1, data.ch0); +} + +bool LTRAlsPsComponent::are_adjustments_required_(AlsReadings &data) { + if (!this->automatic_mode_enabled_) + return false; + + if (data.number_of_adjustments > 15) { + // sometimes sensors fail to change sensitivity. this prevents us from infinite loop + ESP_LOGW(TAG, "Too many sensitivity adjustments done. Apparently, sensor reconfiguration fails. Stopping."); + return false; + } + data.number_of_adjustments++; + + // Recommended thresholds as per datasheet + static const uint16_t LOW_INTENSITY_THRESHOLD = 1000; + static const uint16_t HIGH_INTENSITY_THRESHOLD = 30000; + static const AlsGain GAINS[GAINS_COUNT] = {GAIN_1, GAIN_2, GAIN_4, GAIN_8, GAIN_48, GAIN_96}; + static const IntegrationTime INT_TIMES[TIMES_COUNT] = { + INTEGRATION_TIME_50MS, INTEGRATION_TIME_100MS, INTEGRATION_TIME_150MS, INTEGRATION_TIME_200MS, + INTEGRATION_TIME_250MS, INTEGRATION_TIME_300MS, INTEGRATION_TIME_350MS, INTEGRATION_TIME_400MS}; + + if (data.ch0 <= LOW_INTENSITY_THRESHOLD) { + AlsGain next_gain = get_next(GAINS, data.gain); + if (next_gain != data.gain) { + data.gain = next_gain; + ESP_LOGV(TAG, "Low illuminance. Increasing gain."); + return true; + } + IntegrationTime next_time = get_next(INT_TIMES, data.integration_time); + if (next_time != data.integration_time) { + data.integration_time = next_time; + ESP_LOGV(TAG, "Low illuminance. Increasing integration time."); + return true; + } + } else if (data.ch0 >= HIGH_INTENSITY_THRESHOLD) { + AlsGain prev_gain = get_prev(GAINS, data.gain); + if (prev_gain != data.gain) { + data.gain = prev_gain; + ESP_LOGV(TAG, "High illuminance. Decreasing gain."); + return true; + } + IntegrationTime prev_time = get_prev(INT_TIMES, data.integration_time); + if (prev_time != data.integration_time) { + data.integration_time = prev_time; + ESP_LOGV(TAG, "High illuminance. Decreasing integration time."); + return true; + } + } else { + ESP_LOGD(TAG, "Illuminance is sufficient."); + return false; + } + ESP_LOGD(TAG, "Can't adjust sensitivity anymore."); + return false; +} + +void LTRAlsPsComponent::apply_lux_calculation_(AlsReadings &data) { + if ((data.ch0 == 0xFFFF) || (data.ch1 == 0xFFFF)) { + ESP_LOGW(TAG, "Sensors got saturated"); + data.lux = 0.0f; + return; + } + + if ((data.ch0 == 0x0000) && (data.ch1 == 0x0000)) { + ESP_LOGW(TAG, "Sensors blacked out"); + data.lux = 0.0f; + return; + } + + float ch0 = data.ch0; + float ch1 = data.ch1; + float ratio = ch1 / (ch0 + ch1); + float als_gain = get_gain_coeff(data.gain); + float als_time = ((float) get_itime_ms(data.integration_time)) / 100.0f; + float inv_pfactor = this->glass_attenuation_factor_; + float lux = 0.0f; + + if (ratio < 0.45) { + lux = (1.7743 * ch0 + 1.1059 * ch1); + } else if (ratio < 0.64 && ratio >= 0.45) { + lux = (4.2785 * ch0 - 1.9548 * ch1); + } else if (ratio < 0.85 && ratio >= 0.64) { + lux = (0.5926 * ch0 + 0.1185 * ch1); + } else { + ESP_LOGW(TAG, "Impossible ch1/(ch0 + ch1) ratio"); + lux = 0.0f; + } + lux = inv_pfactor * lux / als_gain / als_time; + data.lux = lux; + + ESP_LOGV(TAG, "Lux calculation: ratio %.3f, gain %.0fx, int time %.1f, inv_pfactor %.3f, lux %.3f", ratio, als_gain, + als_time, inv_pfactor, lux); +} + +void LTRAlsPsComponent::publish_data_part_1_(AlsReadings &data) { + if (this->proximity_counts_sensor_ != nullptr) { + this->proximity_counts_sensor_->publish_state(this->ps_readings_); + } + if (this->ambient_light_sensor_ != nullptr) { + this->ambient_light_sensor_->publish_state(data.lux); + } + if (this->infrared_counts_sensor_ != nullptr) { + this->infrared_counts_sensor_->publish_state(data.ch1); + } + if (this->full_spectrum_counts_sensor_ != nullptr) { + this->full_spectrum_counts_sensor_->publish_state(data.ch0); + } +} + +void LTRAlsPsComponent::publish_data_part_2_(AlsReadings &data) { + if (this->actual_gain_sensor_ != nullptr) { + this->actual_gain_sensor_->publish_state(get_gain_coeff(data.gain)); + } + if (this->actual_integration_time_sensor_ != nullptr) { + this->actual_integration_time_sensor_->publish_state(get_itime_ms(data.integration_time)); + } +} +} // namespace ltr_als_ps +} // namespace esphome diff --git a/esphome/components/ltr_als_ps/ltr_als_ps.h b/esphome/components/ltr_als_ps/ltr_als_ps.h new file mode 100644 index 0000000000..4cbbcea54c --- /dev/null +++ b/esphome/components/ltr_als_ps/ltr_als_ps.h @@ -0,0 +1,184 @@ +#pragma once + +#include "esphome/components/i2c/i2c.h" +#include "esphome/components/sensor/sensor.h" +#include "esphome/core/component.h" +#include "esphome/core/optional.h" +#include "esphome/core/automation.h" + +#include "ltr_definitions.h" + +namespace esphome { +namespace ltr_als_ps { + +enum DataAvail : uint8_t { NO_DATA, BAD_DATA, DATA_OK }; + +enum LtrType : uint8_t { + LTR_TYPE_UNKNOWN = 0, + LTR_TYPE_ALS_ONLY = 1, + LTR_TYPE_PS_ONLY = 2, + LTR_TYPE_ALS_AND_PS = 3, +}; + +class LTRAlsPsComponent : public PollingComponent, public i2c::I2CDevice { + public: + // + // EspHome framework functions + // + float get_setup_priority() const override { return setup_priority::DATA; } + void setup() override; + void dump_config() override; + void update() override; + void loop() override; + + // Configuration setters : General + // + void set_ltr_type(LtrType type) { this->ltr_type_ = type; } + + // Configuration setters : ALS + // + void set_als_auto_mode(bool enable) { this->automatic_mode_enabled_ = enable; } + void set_als_gain(AlsGain gain) { this->gain_ = gain; } + void set_als_integration_time(IntegrationTime time) { this->integration_time_ = time; } + void set_als_meas_repeat_rate(MeasurementRepeatRate rate) { this->repeat_rate_ = rate; } + void set_als_glass_attenuation_factor(float factor) { this->glass_attenuation_factor_ = factor; } + + // Configuration setters : PS + // + void set_ps_high_threshold(uint16_t threshold) { this->ps_threshold_high_ = threshold; } + void set_ps_low_threshold(uint16_t threshold) { this->ps_threshold_low_ = threshold; } + void set_ps_cooldown_time_s(uint16_t time) { this->ps_cooldown_time_s_ = time; } + void set_ps_gain(PsGain gain) { this->ps_gain_ = gain; } + + // Sensors setters + // + void set_ambient_light_sensor(sensor::Sensor *sensor) { this->ambient_light_sensor_ = sensor; } + void set_full_spectrum_counts_sensor(sensor::Sensor *sensor) { this->full_spectrum_counts_sensor_ = sensor; } + void set_infrared_counts_sensor(sensor::Sensor *sensor) { this->infrared_counts_sensor_ = sensor; } + void set_actual_gain_sensor(sensor::Sensor *sensor) { this->actual_gain_sensor_ = sensor; } + 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; } + + protected: + // + // Internal state machine, used to split all the actions into + // small steps in loop() to make sure we are not blocking execution + // + enum class State : uint8_t { + NOT_INITIALIZED, + DELAYED_SETUP, + IDLE, + WAITING_FOR_DATA, + COLLECTING_DATA_AUTO, + DATA_COLLECTED, + ADJUSTMENT_IN_PROGRESS, + READY_TO_PUBLISH, + KEEP_PUBLISHING + } state_{State::NOT_INITIALIZED}; + + LtrType ltr_type_{LtrType::LTR_TYPE_ALS_ONLY}; + + // + // Current measurements data + // + struct AlsReadings { + uint16_t ch0{0}; + uint16_t ch1{0}; + AlsGain gain{AlsGain::GAIN_1}; + IntegrationTime integration_time{IntegrationTime::INTEGRATION_TIME_100MS}; + float lux{0.0f}; + uint8_t number_of_adjustments{0}; + } als_readings_; + uint16_t ps_readings_{0xfffe}; + + inline bool is_als_() const { + return this->ltr_type_ == LtrType::LTR_TYPE_ALS_ONLY || this->ltr_type_ == LtrType::LTR_TYPE_ALS_AND_PS; + } + inline bool is_ps_() const { + return this->ltr_type_ == LtrType::LTR_TYPE_PS_ONLY || this->ltr_type_ == LtrType::LTR_TYPE_ALS_AND_PS; + } + + // + // Device interaction and data manipulation + // + bool check_part_number_(); + + void configure_reset_(); + void configure_als_(); + void configure_integration_time_(IntegrationTime time); + void configure_gain_(AlsGain gain); + DataAvail is_als_data_ready_(AlsReadings &data); + void read_sensor_data_(AlsReadings &data); + bool are_adjustments_required_(AlsReadings &data); + void apply_lux_calculation_(AlsReadings &data); + void publish_data_part_1_(AlsReadings &data); + void publish_data_part_2_(AlsReadings &data); + + void configure_ps_(); + uint16_t read_ps_data_(); + void check_and_trigger_ps_(); + + // + // Component configuration + // + bool automatic_mode_enabled_{true}; + AlsGain gain_{AlsGain::GAIN_1}; + IntegrationTime integration_time_{IntegrationTime::INTEGRATION_TIME_100MS}; + MeasurementRepeatRate repeat_rate_{MeasurementRepeatRate::REPEAT_RATE_500MS}; + float glass_attenuation_factor_{1.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}; + + // + // Sensors for publishing data + // + sensor::Sensor *infrared_counts_sensor_{nullptr}; // direct reading CH1, infrared only + sensor::Sensor *full_spectrum_counts_sensor_{nullptr}; // direct reading CH0, infrared + visible light + sensor::Sensor *ambient_light_sensor_{nullptr}; // calculated lux + sensor::Sensor *actual_gain_sensor_{nullptr}; // actual gain of reading + sensor::Sensor *actual_integration_time_sensor_{nullptr}; // actual integration time + sensor::Sensor *proximity_counts_sensor_{nullptr}; // proximity sensor + + bool is_any_als_sensor_enabled_() const { + return this->ambient_light_sensor_ != nullptr || this->full_spectrum_counts_sensor_ != nullptr || + this->infrared_counts_sensor_ != nullptr || this->actual_gain_sensor_ != nullptr || + this->actual_integration_time_sensor_ != nullptr; + } + 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 on_ps_high_trigger_callback_; + CallbackManager on_ps_low_trigger_callback_; + + void add_on_ps_high_trigger_callback_(std::function callback) { + this->on_ps_high_trigger_callback_.add(std::move(callback)); + } + + void add_on_ps_low_trigger_callback_(std::function callback) { + this->on_ps_low_trigger_callback_.add(std::move(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/ltr_definitions.h b/esphome/components/ltr_als_ps/ltr_definitions.h new file mode 100644 index 0000000000..739445e9a0 --- /dev/null +++ b/esphome/components/ltr_als_ps/ltr_definitions.h @@ -0,0 +1,275 @@ +#pragma once + +#include + +namespace esphome { +namespace ltr_als_ps { + +enum class CommandRegisters : uint8_t { + ALS_CONTR = 0x80, // ALS operation mode control and SW reset + PS_CONTR = 0x81, // PS operation mode control + PS_LED = 0x82, // PS LED pulse frequency control + PS_N_PULSES = 0x83, // PS number of pulses control + PS_MEAS_RATE = 0x84, // PS measurement rate in active mode + MEAS_RATE = 0x85, // ALS measurement rate in active mode + PART_ID = 0x86, // Part Number ID and Revision ID + MANUFAC_ID = 0x87, // Manufacturer ID + ALS_DATA_CH1_0 = 0x88, // ALS measurement CH1 data, lower byte - infrared only + ALS_DATA_CH1_1 = 0x89, // ALS measurement CH1 data, upper byte - infrared only + ALS_DATA_CH0_0 = 0x8A, // ALS measurement CH0 data, lower byte - visible + infrared + ALS_DATA_CH0_1 = 0x8B, // ALS measurement CH0 data, upper byte - visible + infrared + ALS_PS_STATUS = 0x8C, // ALS PS new data status + PS_DATA_0 = 0x8D, // PS measurement data, lower byte + PS_DATA_1 = 0x8E, // PS measurement data, upper byte + ALS_PS_INTERRUPT = 0x8F, // Interrupt status + PS_THRES_UP_0 = 0x90, // PS interrupt upper threshold, lower byte + PS_THRES_UP_1 = 0x91, // PS interrupt upper threshold, upper byte + PS_THRES_LOW_0 = 0x92, // PS interrupt lower threshold, lower byte + PS_THRES_LOW_1 = 0x93, // PS interrupt lower threshold, upper byte + PS_OFFSET_1 = 0x94, // PS offset, upper byte + PS_OFFSET_0 = 0x95, // PS offset, lower byte + // 0x96 - reserved + ALS_THRES_UP_0 = 0x97, // ALS interrupt upper threshold, lower byte + ALS_THRES_UP_1 = 0x98, // ALS interrupt upper threshold, upper byte + ALS_THRES_LOW_0 = 0x99, // ALS interrupt lower threshold, lower byte + ALS_THRES_LOW_1 = 0x9A, // ALS interrupt lower threshold, upper byte + // 0x9B - reserved + // 0x9C - reserved + // 0x9D - reserved + INTERRUPT_PERSIST = 0x9E // Interrupt persistence filter +}; + +// ALS Sensor gain levels +enum AlsGain : uint8_t { + GAIN_1 = 0, // default + GAIN_2 = 1, + GAIN_4 = 2, + GAIN_8 = 3, + GAIN_48 = 6, + GAIN_96 = 7, +}; +static const uint8_t GAINS_COUNT = 6; + +// ALS Sensor integration times +enum IntegrationTime : uint8_t { + INTEGRATION_TIME_100MS = 0, // default + INTEGRATION_TIME_50MS = 1, + INTEGRATION_TIME_200MS = 2, + INTEGRATION_TIME_400MS = 3, + INTEGRATION_TIME_150MS = 4, + INTEGRATION_TIME_250MS = 5, + INTEGRATION_TIME_300MS = 6, + INTEGRATION_TIME_350MS = 7 +}; +static const uint8_t TIMES_COUNT = 8; + +// ALS Sensor measurement repeat rate +enum MeasurementRepeatRate { + REPEAT_RATE_50MS = 0, + REPEAT_RATE_100MS = 1, + REPEAT_RATE_200MS = 2, + REPEAT_RATE_500MS = 3, // default + REPEAT_RATE_1000MS = 4, + REPEAT_RATE_2000MS = 5 +}; + +// PS Sensor gain levels +enum PsGain : uint8_t { + PS_GAIN_16 = 0, // default + PS_GAIN_32 = 2, + PS_GAIN_64 = 3, +}; + +// PS Mode +enum PsMode : uint8_t { + PS_MODE_STANDBY_00 = 0, // default + PS_MODE_STANDBY_01 = 1, + PS_MODE_ACTIVE_10 = 2, + PS_MODE_ACTIVE_11 = 3, +}; + +// LED Pulse Modulation Frequency +enum PsLedFreq : uint8_t { + PS_LED_FREQ_30KHZ = 0, + PS_LED_FREQ_40KHZ = 1, + PS_LED_FREQ_50KHZ = 2, + PS_LED_FREQ_60KHZ = 3, // default + PS_LED_FREQ_70KHZ = 4, + PS_LED_FREQ_80KHZ = 5, + PS_LED_FREQ_90KHZ = 6, + PS_LED_FREQ_100KHZ = 7, +}; + +// LED current duty +enum PsLedDuty : uint8_t { + PS_LED_DUTY_25 = 0, + PS_LED_DUTY_50 = 1, + PS_LED_DUTY_75 = 2, + PS_LED_DUTY_100 = 3, // default +}; + +// LED pulsed current level +enum PsLedCurrent : uint8_t { + PS_LED_CURRENT_5MA = 0, + PS_LED_CURRENT_10MA = 1, + PS_LED_CURRENT_20MA = 2, + PS_LED_CURRENT_50MA = 3, + PS_LED_CURRENT_100MA = 4, // default + PS_LED_CURRENT_100MA1 = 5, + PS_LED_CURRENT_100MA2 = 6, + PS_LED_CURRENT_100MA3 = 7, +}; + +// PS measurement rate +enum PsMeasurementRate : uint8_t { + PS_MEAS_RATE_50MS = 0, + PS_MEAS_RATE_70MS = 1, + PS_MEAS_RATE_100MS = 2, + PS_MEAS_RATE_200MS = 3, + PS_MEAS_RATE_500MS = 4, // default + PS_MEAS_RATE_1000MS = 5, + PS_MEAS_RATE_2000MS = 6, + PS_MEAS_RATE_2000MS1 = 7, + PS_MEAS_RATE_10MS = 8, +}; + +// +// ALS_CONTR Register (0x80) +// +union AlsControlRegister { + uint8_t raw; + struct { + bool active_mode : 1; + bool sw_reset : 1; + AlsGain gain : 3; + uint8_t reserved : 3; + } __attribute__((packed)); +}; + +// +// PS_CONTR Register (0x81) +// +union PsControlRegister { + uint8_t raw; + struct { + bool ps_mode_xxx : 1; + bool ps_mode_active : 1; + PsGain ps_gain : 2; // only LTR-659/558 + bool reserved_4 : 1; + bool ps_saturation_indicator_enable : 1; + bool reserved_6 : 1; + bool reserved_7 : 1; + } __attribute__((packed)); +}; + +// +// PS_LED Register (0x82) +// +union PsLedRegister { + uint8_t raw; + struct { + PsLedCurrent ps_led_current : 3; + PsLedDuty ps_led_duty : 2; + PsLedFreq ps_led_freq : 3; + } __attribute__((packed)); +}; + +// +// PS_N_PULSES Register (0x83) +// +union PsNPulsesRegister { + uint8_t raw; + struct { + uint8_t number_of_pulses : 4; + uint8_t reserved : 4; + } __attribute__((packed)); +}; + +// +// PS_MEAS_RATE Register (0x84) +// +union PsMeasurementRateRegister { + uint8_t raw; + struct { + PsMeasurementRate ps_measurement_rate : 4; + uint8_t reserved : 4; + } __attribute__((packed)); +}; + +// +// ALS_MEAS_RATE Register (0x85) +// +union MeasurementRateRegister { + uint8_t raw; + struct { + MeasurementRepeatRate measurement_repeat_rate : 3; + IntegrationTime integration_time : 3; + bool reserved_6 : 1; + bool reserved_7 : 1; + } __attribute__((packed)); +}; + +// +// PART_ID Register (0x86) (Read Only) +// +union PartIdRegister { + uint8_t raw; + struct { + uint8_t part_number_id : 4; + uint8_t revision_id : 4; + } __attribute__((packed)); +}; + +// +// ALS_PS_STATUS Register (0x8C) (Read Only) +// +union AlsPsStatusRegister { + uint8_t raw; + struct { + bool ps_new_data : 1; // 0 - old data, 1 - new data + bool ps_interrupt : 1; // 0 - interrupt signal not active, 1 - interrupt signal active + bool als_new_data : 1; // 0 - old data, 1 - new data + bool als_interrupt : 1; // 0 - interrupt signal not active, 1 - interrupt signal active + AlsGain gain : 3; // current ALS gain + bool data_invalid : 1; + } __attribute__((packed)); +}; + +// +// PS_DATA_1 Register (0x8E) (Read Only) +// +union PsData1Register { + uint8_t raw; + struct { + uint8_t ps_data_high : 3; + uint8_t reserved : 4; + bool ps_saturation_flag : 1; + } __attribute__((packed)); +}; + +// +// INTERRUPT Register (0x8F) (Read Only) +// +union InterruptRegister { + uint8_t raw; + struct { + bool ps_interrupt : 1; + bool als_interrupt : 1; + bool interrupt_polarity : 1; // 0 - active low (default), 1 - active high + uint8_t reserved : 5; + } __attribute__((packed)); +}; + +// +// INTERRUPT_PERSIST Register (0x9E) +// +union InterruptPersistRegister { + uint8_t raw; + struct { + uint8_t als_persist : 4; // 0 - every ALS cycle, 1 - every 2 ALS cycles, ... 15 - every 16 ALS cycles + uint8_t ps_persist : 4; // 0 - every PS cycle, 1 - every 2 PS cycles, ... 15 - every 16 PS cycles + } __attribute__((packed)); +}; + +} // namespace ltr_als_ps +} // namespace esphome diff --git a/esphome/components/ltr_als_ps/sensor.py b/esphome/components/ltr_als_ps/sensor.py new file mode 100644 index 0000000000..ac9f7e6788 --- /dev/null +++ b/esphome/components/ltr_als_ps/sensor.py @@ -0,0 +1,271 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome import automation +from esphome.components import i2c, sensor +from esphome.const import ( + CONF_ACTUAL_GAIN, + CONF_AMBIENT_LIGHT, + CONF_AUTO_MODE, + CONF_GAIN, + CONF_GLASS_ATTENUATION_FACTOR, + CONF_ID, + CONF_INTEGRATION_TIME, + CONF_NAME, + CONF_REPEAT, + CONF_TRIGGER_ID, + CONF_TYPE, + DEVICE_CLASS_DISTANCE, + DEVICE_CLASS_ILLUMINANCE, + ICON_BRIGHTNESS_5, + ICON_BRIGHTNESS_6, + ICON_TIMER, + STATE_CLASS_MEASUREMENT, + UNIT_LUX, + UNIT_MILLISECOND, +) + +CODEOWNERS = ["@latonita"] +DEPENDENCIES = ["i2c"] + +CONF_ACTUAL_INTEGRATION_TIME = "actual_integration_time" +CONF_FULL_SPECTRUM_COUNTS = "full_spectrum_counts" +CONF_INFRARED_COUNTS = "infrared_counts" +CONF_ON_PS_HIGH_THRESHOLD = "on_ps_high_threshold" +CONF_ON_PS_LOW_THRESHOLD = "on_ps_low_threshold" +CONF_PS_COOLDOWN = "ps_cooldown" +CONF_PS_COUNTS = "ps_counts" +CONF_PS_GAIN = "ps_gain" +CONF_PS_HIGH_THRESHOLD = "ps_high_threshold" +CONF_PS_LOW_THRESHOLD = "ps_low_threshold" +ICON_BRIGHTNESS_7 = "mdi:brightness-7" +ICON_GAIN = "mdi:multiplication" +ICON_PROXIMITY = "mdi:hand-wave-outline" +UNIT_COUNTS = "#" + +ltr_als_ps_ns = cg.esphome_ns.namespace("ltr_als_ps") + +LTRAlsPsComponent = ltr_als_ps_ns.class_( + "LTRAlsPsComponent", cg.PollingComponent, i2c.I2CDevice +) + +LtrType = ltr_als_ps_ns.enum("LtrType") +LTR_TYPES = { + "ALS": LtrType.LTR_TYPE_ALS_ONLY, + "PS": LtrType.LTR_TYPE_PS_ONLY, + "ALS_PS": LtrType.LTR_TYPE_ALS_AND_PS, +} + +AlsGain = ltr_als_ps_ns.enum("AlsGain") +ALS_GAINS = { + "1X": AlsGain.GAIN_1, + "2X": AlsGain.GAIN_2, + "4X": AlsGain.GAIN_4, + "8X": AlsGain.GAIN_8, + "48X": AlsGain.GAIN_48, + "96X": AlsGain.GAIN_96, +} + +IntegrationTime = ltr_als_ps_ns.enum("IntegrationTime") +INTEGRATION_TIMES = { + 50: IntegrationTime.INTEGRATION_TIME_50MS, + 100: IntegrationTime.INTEGRATION_TIME_100MS, + 150: IntegrationTime.INTEGRATION_TIME_150MS, + 200: IntegrationTime.INTEGRATION_TIME_200MS, + 250: IntegrationTime.INTEGRATION_TIME_250MS, + 300: IntegrationTime.INTEGRATION_TIME_300MS, + 350: IntegrationTime.INTEGRATION_TIME_350MS, + 400: IntegrationTime.INTEGRATION_TIME_400MS, +} + +MeasurementRepeatRate = ltr_als_ps_ns.enum("MeasurementRepeatRate") +MEASUREMENT_REPEAT_RATES = { + 50: MeasurementRepeatRate.REPEAT_RATE_50MS, + 100: MeasurementRepeatRate.REPEAT_RATE_100MS, + 200: MeasurementRepeatRate.REPEAT_RATE_200MS, + 500: MeasurementRepeatRate.REPEAT_RATE_500MS, + 1000: MeasurementRepeatRate.REPEAT_RATE_1000MS, + 2000: MeasurementRepeatRate.REPEAT_RATE_2000MS, +} + +PsGain = ltr_als_ps_ns.enum("PsGain") +PS_GAINS = { + "16X": PsGain.PS_GAIN_16, + "32X": PsGain.PS_GAIN_32, + "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 + return cv.enum(INTEGRATION_TIMES, int=True)(value) + + +def validate_repeat_rate(value): + value = cv.positive_time_period_milliseconds(value).total_milliseconds + return cv.enum(MEASUREMENT_REPEAT_RATES, int=True)(value) + + +def validate_time_and_repeat_rate(config): + integraton_time = config[CONF_INTEGRATION_TIME] + repeat_rate = config[CONF_REPEAT] + if integraton_time > repeat_rate: + raise cv.Invalid( + f"Measurement repeat rate ({repeat_rate}ms) shall be greater or equal to integration time ({integraton_time}ms)" + ) + return config + + +CONFIG_SCHEMA = cv.All( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(LTRAlsPsComponent), + cv.Optional(CONF_TYPE, default="ALS_PS"): cv.enum(LTR_TYPES, upper=True), + cv.Optional(CONF_AUTO_MODE, default=True): cv.boolean, + cv.Optional(CONF_GAIN, default="1X"): cv.enum(ALS_GAINS, upper=True), + cv.Optional( + CONF_INTEGRATION_TIME, default="100ms" + ): validate_integration_time, + cv.Optional(CONF_REPEAT, default="500ms"): validate_repeat_rate, + cv.Optional(CONF_GLASS_ATTENUATION_FACTOR, default=1.0): cv.float_range( + min=1.0 + ), + cv.Optional( + CONF_PS_COOLDOWN, default="5s" + ): cv.positive_time_period_seconds, + cv.Optional(CONF_PS_GAIN, default="16X"): cv.enum(PS_GAINS, upper=True), + cv.Optional(CONF_PS_HIGH_THRESHOLD, default=65535): cv.int_range( + min=0, max=65535 + ), + 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_AMBIENT_LIGHT): cv.maybe_simple_value( + sensor.sensor_schema( + unit_of_measurement=UNIT_LUX, + icon=ICON_BRIGHTNESS_6, + accuracy_decimals=1, + device_class=DEVICE_CLASS_ILLUMINANCE, + state_class=STATE_CLASS_MEASUREMENT, + ), + key=CONF_NAME, + ), + cv.Optional(CONF_INFRARED_COUNTS): cv.maybe_simple_value( + sensor.sensor_schema( + 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, + ), + cv.Optional(CONF_FULL_SPECTRUM_COUNTS): cv.maybe_simple_value( + sensor.sensor_schema( + 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, + ), + cv.Optional(CONF_PS_COUNTS): cv.maybe_simple_value( + sensor.sensor_schema( + unit_of_measurement=UNIT_COUNTS, + icon=ICON_PROXIMITY, + accuracy_decimals=0, + device_class=DEVICE_CLASS_DISTANCE, + state_class=STATE_CLASS_MEASUREMENT, + ), + key=CONF_NAME, + ), + cv.Optional(CONF_ACTUAL_GAIN): cv.maybe_simple_value( + sensor.sensor_schema( + icon=ICON_GAIN, + accuracy_decimals=0, + device_class=DEVICE_CLASS_ILLUMINANCE, + state_class=STATE_CLASS_MEASUREMENT, + ), + key=CONF_NAME, + ), + cv.Optional(CONF_ACTUAL_INTEGRATION_TIME): cv.maybe_simple_value( + sensor.sensor_schema( + unit_of_measurement=UNIT_MILLISECOND, + icon=ICON_TIMER, + accuracy_decimals=0, + state_class=STATE_CLASS_MEASUREMENT, + ), + key=CONF_NAME, + ), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x29)), + validate_time_and_repeat_rate, +) + + +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 als_config := config.get(CONF_AMBIENT_LIGHT): + sens = await sensor.new_sensor(als_config) + cg.add(var.set_ambient_light_sensor(sens)) + + if infrared_cnt_config := config.get(CONF_INFRARED_COUNTS): + sens = await sensor.new_sensor(infrared_cnt_config) + cg.add(var.set_infrared_counts_sensor(sens)) + + if full_spect_cnt_config := config.get(CONF_FULL_SPECTRUM_COUNTS): + sens = await sensor.new_sensor(full_spect_cnt_config) + cg.add(var.set_full_spectrum_counts_sensor(sens)) + + if act_gain_config := config.get(CONF_ACTUAL_GAIN): + sens = await sensor.new_sensor(act_gain_config) + cg.add(var.set_actual_gain_sensor(sens)) + + if act_itime_config := config.get(CONF_ACTUAL_INTEGRATION_TIME): + sens = await sensor.new_sensor(act_itime_config) + cg.add(var.set_actual_integration_time_sensor(sens)) + + if prox_cnt_config := config.get(CONF_PS_COUNTS): + 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) + + cg.add(var.set_ltr_type(config[CONF_TYPE])) + + cg.add(var.set_als_auto_mode(config[CONF_AUTO_MODE])) + cg.add(var.set_als_gain(config[CONF_GAIN])) + cg.add(var.set_als_integration_time(config[CONF_INTEGRATION_TIME])) + cg.add(var.set_als_meas_repeat_rate(config[CONF_REPEAT])) + cg.add(var.set_als_glass_attenuation_factor(config[CONF_GLASS_ATTENUATION_FACTOR])) + + cg.add(var.set_ps_cooldown_time_s(config[CONF_PS_COOLDOWN])) + cg.add(var.set_ps_gain(config[CONF_PS_GAIN])) + cg.add(var.set_ps_high_threshold(config[CONF_PS_HIGH_THRESHOLD])) + cg.add(var.set_ps_low_threshold(config[CONF_PS_LOW_THRESHOLD])) diff --git a/esphome/components/veml7700/sensor.py b/esphome/components/veml7700/sensor.py index 7ce05b47e4..7b0f75e70c 100644 --- a/esphome/components/veml7700/sensor.py +++ b/esphome/components/veml7700/sensor.py @@ -3,6 +3,7 @@ import esphome.config_validation as cv from esphome.components import i2c, sensor from esphome.const import ( CONF_ACTUAL_GAIN, + CONF_AMBIENT_LIGHT, CONF_AUTO_MODE, CONF_FULL_SPECTRUM, CONF_GAIN, @@ -11,13 +12,13 @@ from esphome.const import ( CONF_INFRARED, CONF_INTEGRATION_TIME, CONF_NAME, - UNIT_LUX, - UNIT_MILLISECOND, + DEVICE_CLASS_ILLUMINANCE, ICON_BRIGHTNESS_5, ICON_BRIGHTNESS_6, ICON_TIMER, - DEVICE_CLASS_ILLUMINANCE, STATE_CLASS_MEASUREMENT, + UNIT_LUX, + UNIT_MILLISECOND, ) CODEOWNERS = ["@latonita"] @@ -28,7 +29,6 @@ ICON_MULTIPLICATION = "mdi:multiplication" ICON_BRIGHTNESS_7 = "mdi:brightness-7" CONF_ACTUAL_INTEGRATION_TIME = "actual_integration_time" -CONF_AMBIENT_LIGHT = "ambient_light" CONF_AMBIENT_LIGHT_COUNTS = "ambient_light_counts" CONF_FULL_SPECTRUM_COUNTS = "full_spectrum_counts" CONF_LUX_COMPENSATION = "lux_compensation" diff --git a/esphome/const.py b/esphome/const.py index 1aafffb5d0..ed0a9b1f64 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -49,6 +49,7 @@ CONF_AFTER = "after" CONF_ALLOW_OTHER_USES = "allow_other_uses" CONF_ALPHA = "alpha" CONF_ALTITUDE = "altitude" +CONF_AMBIENT_LIGHT = "ambient_light" CONF_ANALOG = "analog" CONF_AND = "and" CONF_ANGLE = "angle" diff --git a/tests/components/ltr_als_ps/common.yaml b/tests/components/ltr_als_ps/common.yaml new file mode 100644 index 0000000000..aa5c8abed7 --- /dev/null +++ b/tests/components/ltr_als_ps/common.yaml @@ -0,0 +1,11 @@ +sensor: + - platform: ltr_als_ps + address: 0x23 + i2c_id: i2c_als_ps + gain: 1x + integration_time: 100ms + ps_cooldown: 5 s + ambient_light: "Ambient light" + full_spectrum_counts: "Full spectrum counts" + infrared_counts: "Infrared counts" + actual_gain: "Actual gain" diff --git a/tests/components/ltr_als_ps/test.esp32-c3-idf.yaml b/tests/components/ltr_als_ps/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..d64d70f018 --- /dev/null +++ b/tests/components/ltr_als_ps/test.esp32-c3-idf.yaml @@ -0,0 +1,6 @@ +i2c: + - id: i2c_als_ps + scl: 5 + sda: 4 + +<<: !include common.yaml diff --git a/tests/components/ltr_als_ps/test.esp32-c3.yaml b/tests/components/ltr_als_ps/test.esp32-c3.yaml new file mode 100644 index 0000000000..d64d70f018 --- /dev/null +++ b/tests/components/ltr_als_ps/test.esp32-c3.yaml @@ -0,0 +1,6 @@ +i2c: + - id: i2c_als_ps + scl: 5 + sda: 4 + +<<: !include common.yaml diff --git a/tests/components/ltr_als_ps/test.esp32-idf.yaml b/tests/components/ltr_als_ps/test.esp32-idf.yaml new file mode 100644 index 0000000000..2349292a64 --- /dev/null +++ b/tests/components/ltr_als_ps/test.esp32-idf.yaml @@ -0,0 +1,6 @@ +i2c: + - id: i2c_als_ps + scl: 16 + sda: 17 + +<<: !include common.yaml diff --git a/tests/components/ltr_als_ps/test.esp32.yaml b/tests/components/ltr_als_ps/test.esp32.yaml new file mode 100644 index 0000000000..2349292a64 --- /dev/null +++ b/tests/components/ltr_als_ps/test.esp32.yaml @@ -0,0 +1,6 @@ +i2c: + - id: i2c_als_ps + scl: 16 + sda: 17 + +<<: !include common.yaml diff --git a/tests/components/ltr_als_ps/test.esp8266.yaml b/tests/components/ltr_als_ps/test.esp8266.yaml new file mode 100644 index 0000000000..d64d70f018 --- /dev/null +++ b/tests/components/ltr_als_ps/test.esp8266.yaml @@ -0,0 +1,6 @@ +i2c: + - id: i2c_als_ps + scl: 5 + sda: 4 + +<<: !include common.yaml diff --git a/tests/components/ltr_als_ps/test.rp2040.yaml b/tests/components/ltr_als_ps/test.rp2040.yaml new file mode 100644 index 0000000000..d64d70f018 --- /dev/null +++ b/tests/components/ltr_als_ps/test.rp2040.yaml @@ -0,0 +1,6 @@ +i2c: + - id: i2c_als_ps + scl: 5 + sda: 4 + +<<: !include common.yaml From 2894a138e78418d2f61845fca6832053ca48292a Mon Sep 17 00:00:00 2001 From: NonaSuomy Date: Fri, 31 May 2024 01:13:11 -0400 Subject: [PATCH 1529/2101] Update const.py added missing millimeter (#6834) * Update const.py added missing millimeter Added missing millimeter * Fixed UNIT_MILLIMETER in multiple locations. --- esphome/components/a02yyuw/sensor.py | 4 ++-- esphome/components/hydreon_rgxx/sensor.py | 8 ++++---- esphome/components/mopeka_pro_check/sensor.py | 3 +-- esphome/components/mopeka_std_check/sensor.py | 3 +-- esphome/const.py | 1 + 5 files changed, 9 insertions(+), 10 deletions(-) diff --git a/esphome/components/a02yyuw/sensor.py b/esphome/components/a02yyuw/sensor.py index 5232b04546..d491a51be9 100644 --- a/esphome/components/a02yyuw/sensor.py +++ b/esphome/components/a02yyuw/sensor.py @@ -4,11 +4,11 @@ from esphome.const import ( STATE_CLASS_MEASUREMENT, ICON_ARROW_EXPAND_VERTICAL, DEVICE_CLASS_DISTANCE, + UNIT_MILLIMETER, ) CODEOWNERS = ["@TH-Braemer"] DEPENDENCIES = ["uart"] -UNIT_MILLIMETERS = "mm" a02yyuw_ns = cg.esphome_ns.namespace("a02yyuw") A02yyuwComponent = a02yyuw_ns.class_( @@ -17,7 +17,7 @@ A02yyuwComponent = a02yyuw_ns.class_( CONFIG_SCHEMA = sensor.sensor_schema( A02yyuwComponent, - unit_of_measurement=UNIT_MILLIMETERS, + unit_of_measurement=UNIT_MILLIMETER, icon=ICON_ARROW_EXPAND_VERTICAL, accuracy_decimals=0, state_class=STATE_CLASS_MEASUREMENT, diff --git a/esphome/components/hydreon_rgxx/sensor.py b/esphome/components/hydreon_rgxx/sensor.py index 72b74bf624..fb2099c85e 100644 --- a/esphome/components/hydreon_rgxx/sensor.py +++ b/esphome/components/hydreon_rgxx/sensor.py @@ -12,13 +12,13 @@ from esphome.const import ( STATE_CLASS_MEASUREMENT, STATE_CLASS_TOTAL_INCREASING, UNIT_CELSIUS, + UNIT_MILLIMETER, ICON_THERMOMETER, ) from . import RGModel, RG15Resolution, HydreonRGxxComponent UNIT_INTENSITY = "intensity" -UNIT_MILLIMETERS = "mm" UNIT_MILLIMETERS_PER_HOUR = "mm/h" CONF_ACC = "acc" @@ -85,19 +85,19 @@ CONFIG_SCHEMA = cv.All( ), cv.Optional(CONF_RESOLUTION): cv.enum(RG15_RESOLUTION, upper=False), cv.Optional(CONF_ACC): sensor.sensor_schema( - unit_of_measurement=UNIT_MILLIMETERS, + unit_of_measurement=UNIT_MILLIMETER, accuracy_decimals=2, device_class=DEVICE_CLASS_PRECIPITATION, state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_EVENT_ACC): sensor.sensor_schema( - unit_of_measurement=UNIT_MILLIMETERS, + unit_of_measurement=UNIT_MILLIMETER, accuracy_decimals=2, device_class=DEVICE_CLASS_PRECIPITATION, state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_TOTAL_ACC): sensor.sensor_schema( - unit_of_measurement=UNIT_MILLIMETERS, + unit_of_measurement=UNIT_MILLIMETER, accuracy_decimals=2, device_class=DEVICE_CLASS_PRECIPITATION, state_class=STATE_CLASS_TOTAL_INCREASING, diff --git a/esphome/components/mopeka_pro_check/sensor.py b/esphome/components/mopeka_pro_check/sensor.py index 51a515ef0c..0ba33e94de 100644 --- a/esphome/components/mopeka_pro_check/sensor.py +++ b/esphome/components/mopeka_pro_check/sensor.py @@ -12,6 +12,7 @@ from esphome.const import ( CONF_TEMPERATURE, DEVICE_CLASS_TEMPERATURE, UNIT_CELSIUS, + UNIT_MILLIMETER, STATE_CLASS_MEASUREMENT, CONF_BATTERY_LEVEL, DEVICE_CLASS_BATTERY, @@ -25,8 +26,6 @@ ICON_PROPANE_TANK = "mdi:propane-tank" TANK_TYPE_CUSTOM = "CUSTOM" -UNIT_MILLIMETER = "mm" - def small_distance(value): """small_distance is stored in mm""" diff --git a/esphome/components/mopeka_std_check/sensor.py b/esphome/components/mopeka_std_check/sensor.py index bbba798e95..ac745cf3d5 100644 --- a/esphome/components/mopeka_std_check/sensor.py +++ b/esphome/components/mopeka_std_check/sensor.py @@ -12,6 +12,7 @@ from esphome.const import ( CONF_TEMPERATURE, DEVICE_CLASS_TEMPERATURE, UNIT_CELSIUS, + UNIT_MILLIMETER, STATE_CLASS_MEASUREMENT, CONF_BATTERY_LEVEL, DEVICE_CLASS_BATTERY, @@ -26,8 +27,6 @@ ICON_PROPANE_TANK = "mdi:propane-tank" TANK_TYPE_CUSTOM = "CUSTOM" -UNIT_MILLIMETER = "mm" - def small_distance(value): """small_distance is stored in mm""" diff --git a/esphome/const.py b/esphome/const.py index ed0a9b1f64..dcb353ab1c 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1035,6 +1035,7 @@ UNIT_MICROSIEMENS_PER_CENTIMETER = "µS/cm" UNIT_MICROSILVERTS_PER_HOUR = "µSv/h" UNIT_MICROTESLA = "µT" UNIT_MILLIGRAMS_PER_CUBIC_METER = "mg/m³" +UNIT_MILLIMETER = "mm" UNIT_MILLISECOND = "ms" UNIT_MILLISIEMENS_PER_CENTIMETER = "mS/cm" UNIT_MINUTE = "min" From 1f301df51d4389f16e6a059c2ac87186c9631be8 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Fri, 31 May 2024 00:49:11 -0500 Subject: [PATCH 1530/2101] Fix log message in VA for IDF 5 (#6839) --- esphome/components/voice_assistant/voice_assistant.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index c2fd14fbd5..e4fd2f2e9d 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -815,7 +815,7 @@ void VoiceAssistant::on_timer_event(const api::VoiceAssistantTimerEventResponse }; this->timers_[timer.id] = timer; ESP_LOGD(TAG, "Timer Event"); - ESP_LOGD(TAG, " Type: %d", msg.event_type); + ESP_LOGD(TAG, " Type: %" PRId32, msg.event_type); ESP_LOGD(TAG, " %s", timer.to_string().c_str()); switch (msg.event_type) { From 41e13fa6f437cac86916a99cf45ef8ce1a627d44 Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Fri, 31 May 2024 17:49:48 -0700 Subject: [PATCH 1531/2101] Replace random non-ascii-print characters with standard substitutes (#6840) --- esphome/components/api/custom_api_device.h | 2 +- esphome/components/ethernet/ethernet_component.cpp | 8 ++++---- esphome/components/feedback/feedback_cover.cpp | 4 ++-- esphome/components/max6956/max6956.h | 2 +- esphome/components/ntc/sensor.py | 2 +- esphome/components/wifi/wifi_component.cpp | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/esphome/components/api/custom_api_device.h b/esphome/components/api/custom_api_device.h index 9f125a6149..845a35fc54 100644 --- a/esphome/components/api/custom_api_device.h +++ b/esphome/components/api/custom_api_device.h @@ -105,7 +105,7 @@ class CustomAPIDevice { /** Subscribe to the state (or attribute state) of an entity from Home Assistant. * * Usage: - *å + * * ```cpp * void setup() override { * subscribe_homeassistant_state(&CustomNativeAPI::on_state_changed, "sensor.weather_forecast"); diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index 2a4e5cbad3..087a3b1750 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -576,11 +576,11 @@ void EthernetComponent::ksz8081_set_clock_reference_(esp_eth_mac_t *mac) { /* * Bit 7 is `RMII Reference Clock Select`. Default is `0`. * KSZ8081RNA: - * 0 - clock input to XI (Pin 8) is 25 MHz for RMII – 25 MHz clock mode. - * 1 - clock input to XI (Pin 8) is 50 MHz for RMII – 50 MHz clock mode. + * 0 - clock input to XI (Pin 8) is 25 MHz for RMII - 25 MHz clock mode. + * 1 - clock input to XI (Pin 8) is 50 MHz for RMII - 50 MHz clock mode. * KSZ8081RND: - * 0 - clock input to XI (Pin 8) is 50 MHz for RMII – 50 MHz clock mode. - * 1 - clock input to XI (Pin 8) is 25 MHz (driven clock only, not a crystal) for RMII – 25 MHz clock mode. + * 0 - clock input to XI (Pin 8) is 50 MHz for RMII - 50 MHz clock mode. + * 1 - clock input to XI (Pin 8) is 25 MHz (driven clock only, not a crystal) for RMII - 25 MHz clock mode. */ if ((phy_control_2 & (1 << 7)) != (1 << 7)) { phy_control_2 |= 1 << 7; diff --git a/esphome/components/feedback/feedback_cover.cpp b/esphome/components/feedback/feedback_cover.cpp index 117c626f58..fa3166ba65 100644 --- a/esphome/components/feedback/feedback_cover.cpp +++ b/esphome/components/feedback/feedback_cover.cpp @@ -244,7 +244,7 @@ void FeedbackCover::loop() { // update current position at requested interval, regardless of who started the movement // so that we also update UI if there was an external movement - // don´t save intermediate positions + // don't save intermediate positions if (now - this->last_publish_time_ > this->update_interval_) { this->publish_state(false); this->last_publish_time_ = now; @@ -274,7 +274,7 @@ void FeedbackCover::control(const CoverCall &call) { if (pos == this->position) { // already at target, - // for covers with built in end stop, if we don´t have sensors we should send the command again + // for covers with built in end stop, if we don't have sensors we should send the command again // to make sure the assumed state is not wrong if (this->has_built_in_endstop_ && ((pos == COVER_OPEN #ifdef USE_BINARY_SENSOR diff --git a/esphome/components/max6956/max6956.h b/esphome/components/max6956/max6956.h index 141164ab30..759fa45b07 100644 --- a/esphome/components/max6956/max6956.h +++ b/esphome/components/max6956/max6956.h @@ -29,7 +29,7 @@ enum MAX6956GPIORegisters { MAX6956_PORT_CONFIG_START = 0x09, // Port Configuration P7, P6, P5, P4 MAX6956_CURRENT_START = 0x12, // Current054 MAX6956_1PORT_VALUE_START = 0x20, // Port 0 only (virtual port, no action) - MAX6956_8PORTS_VALUE_START = 0x44, // 8 ports 4–11 (data bits D0–D7) + MAX6956_8PORTS_VALUE_START = 0x44, // 8 ports 4-11 (data bits D0-D7) }; enum MAX6956GPIOFlag { FLAG_LED = 0x20 }; diff --git a/esphome/components/ntc/sensor.py b/esphome/components/ntc/sensor.py index 06fc55fc43..961511fe00 100644 --- a/esphome/components/ntc/sensor.py +++ b/esphome/components/ntc/sensor.py @@ -100,7 +100,7 @@ def process_calibration(value): elif isinstance(value, list): if len(value) != 3: raise cv.Invalid( - "Steinhart–Hart Calibration must consist of exactly three values" + "Steinhart-Hart Calibration must consist of exactly three values" ) value = cv.Schema([validate_calibration_parameter])(value) a, b, c = calc_steinhart_hart(value) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 2f34f2b05b..1359e0b7c5 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -58,7 +58,7 @@ void WiFiComponent::setup() { void WiFiComponent::start() { ESP_LOGCONFIG(TAG, "Starting WiFi..."); - ESP_LOGCONFIG(TAG, " Local MAC: %s", get_mac_address_pretty().c_str()); + ESP_LOGCONFIG(TAG, " Local MAC: %s", get_mac_address_pretty().c_str()); this->last_connected_ = millis(); uint32_t hash = this->has_sta() ? fnv1_hash(App.get_compilation_time()) : 88491487UL; From 2beb1f033611c0984c3c4d11734e967cc8a1416f Mon Sep 17 00:00:00 2001 From: Simone Rossetto Date: Sat, 1 Jun 2024 04:36:51 +0200 Subject: [PATCH 1532/2101] Wireguard support for bk72 microcontrollers (#6842) * Bump esp_wireguard to v0.4.1 * add support for bk72 microcontrollers (thanks to kuba2k2) * fix compilation error using esp-idf v5 (thanks to kbx81) * fix crash on vpn disconnection with alive tcp connection (thanks to jefftharris) * Disable ipv6 for bk72 wireguard test * Completely remove ipv6 entry from bk72 wg test --- esphome/components/wireguard/__init__.py | 2 +- platformio.ini | 8 +-- tests/components/wireguard/test.bk72xx.yaml | 59 +++++++++++++++++++++ 3 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 tests/components/wireguard/test.bk72xx.yaml diff --git a/esphome/components/wireguard/__init__.py b/esphome/components/wireguard/__init__.py index 7612c7d964..177ad6d356 100644 --- a/esphome/components/wireguard/__init__.py +++ b/esphome/components/wireguard/__init__.py @@ -122,7 +122,7 @@ async def to_code(config): # the '+1' modifier is relative to the device's own address that will # be automatically added to the provided list. cg.add_build_flag(f"-DCONFIG_WIREGUARD_MAX_SRC_IPS={len(allowed_ips) + 1}") - cg.add_library("droscy/esp_wireguard", "0.4.0") + cg.add_library("droscy/esp_wireguard", "0.4.1") await cg.register_component(var, config) diff --git a/platformio.ini b/platformio.ini index fd0ae7c6d8..6b34b2f05d 100644 --- a/platformio.ini +++ b/platformio.ini @@ -94,7 +94,7 @@ lib_deps = ESP8266mDNS ; mdns (Arduino built-in) DNSServer ; captive_portal (Arduino built-in) crankyoldgit/IRremoteESP8266@~2.8.4 ; heatpumpir - droscy/esp_wireguard@0.4.0 ; wireguard + droscy/esp_wireguard@0.4.1 ; wireguard build_flags = ${common:arduino.build_flags} -Wno-nonnull-compare @@ -124,7 +124,7 @@ lib_deps = DNSServer ; captive_portal (Arduino built-in) esphome/ESP32-audioI2S@2.0.7 ; i2s_audio crankyoldgit/IRremoteESP8266@~2.8.4 ; heatpumpir - droscy/esp_wireguard@0.4.0 ; wireguard + droscy/esp_wireguard@0.4.1 ; wireguard build_flags = ${common:arduino.build_flags} -DUSE_ESP32 @@ -143,7 +143,7 @@ framework = espidf lib_deps = ${common:idf.lib_deps} espressif/esp32-camera@1.0.0 ; esp32_camera - droscy/esp_wireguard@0.4.0 ; wireguard + droscy/esp_wireguard@0.4.1 ; wireguard build_flags = ${common:idf.build_flags} -Wno-nonnull-compare @@ -174,6 +174,8 @@ build_flags = extends = common:arduino platform = libretiny framework = arduino +lib_deps = + droscy/esp_wireguard@0.4.1 ; wireguard build_flags = ${common:arduino.build_flags} -DUSE_LIBRETINY diff --git a/tests/components/wireguard/test.bk72xx.yaml b/tests/components/wireguard/test.bk72xx.yaml new file mode 100644 index 0000000000..85325139a9 --- /dev/null +++ b/tests/components/wireguard/test.bk72xx.yaml @@ -0,0 +1,59 @@ +wifi: + ssid: "MySSID1" + password: "password1" + +time: + - platform: sntp + +wireguard: + address: 172.16.34.100 + netmask: 255.255.255.0 + # NEVER use the following keys for your vpn, they are now public! + private_key: wPBMxtNYH3mChicrbpsRpZIasIdPq3yZuthn23FbGG8= + peer_public_key: Hs2JfikvYU03/Kv3YoAs1hrUIPPTEkpsZKSPUljE9yc= + peer_preshared_key: 20fjM5GRnSolGPC5SRj9ljgIUyQfruv0B0bvLl3Yt60= + peer_endpoint: wg.server.example + peer_persistent_keepalive: 25s + peer_allowed_ips: + - 172.16.34.0/24 + - 192.168.4.0/24 + +binary_sensor: + - platform: wireguard + status: + name: 'WireGuard Status' + enabled: + name: 'WireGuard Enabled' + +sensor: + - platform: wireguard + latest_handshake: + name: 'WireGuard Latest Handshake' + +text_sensor: + - platform: wireguard + address: + name: 'WireGuard Address' + +button: + - platform: template + name: 'Toggle WireGuard' + entity_category: config + on_press: + - if: + condition: wireguard.enabled + then: + - wireguard.disable: + else: + - wireguard.enable: + + - platform: template + name: 'Log WireGuard status' + entity_category: config + on_press: + - if: + condition: wireguard.peer_online + then: + - logger.log: 'wireguard remote peer is online' + else: + - logger.log: 'wireguard remote peer is offline' From 2353b2b5e1e66874a84f5f0e1e2ae0fff5780407 Mon Sep 17 00:00:00 2001 From: "Kevin P. Fleming" Date: Sat, 1 Jun 2024 18:40:50 -0400 Subject: [PATCH 1533/2101] Add messages when WiFi and Ethernet components set 'warning' flag. (#6850) --- esphome/components/ethernet/ethernet_component.cpp | 2 +- esphome/components/wifi/wifi_component.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index 087a3b1750..7672dc2dcb 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -410,7 +410,7 @@ void EthernetComponent::start_connect_() { global_eth_component->ipv6_count_ = 0; #endif /* USE_NETWORK_IPV6 */ this->connect_begin_ = millis(); - this->status_set_warning(); + this->status_set_warning("waiting for IP configuration"); esp_err_t err; err = esp_netif_set_hostname(this->eth_netif_, App.get_name().c_str()); diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 1359e0b7c5..8c40f87879 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -135,7 +135,7 @@ void WiFiComponent::loop() { switch (this->state_) { case WIFI_COMPONENT_STATE_COOLDOWN: { - this->status_set_warning(); + this->status_set_warning("waiting to reconnect"); if (millis() - this->action_started_ > 5000) { if (this->fast_connect_ || this->retry_hidden_) { this->start_connecting(this->sta_[0], false); @@ -146,13 +146,13 @@ void WiFiComponent::loop() { break; } case WIFI_COMPONENT_STATE_STA_SCANNING: { - this->status_set_warning(); + this->status_set_warning("scanning for networks"); this->check_scanning_finished(); break; } case WIFI_COMPONENT_STATE_STA_CONNECTING: case WIFI_COMPONENT_STATE_STA_CONNECTING_2: { - this->status_set_warning(); + this->status_set_warning("associating to network"); this->check_connecting_finished(); break; } From b8d2a6f574e4f49d12d3e677220c9dd92a364aae Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Mon, 3 Jun 2024 05:23:49 +0200 Subject: [PATCH 1534/2101] [sntp] fix for ESP-IDF > 5.0 (#6769) * Make sntp work with ESP-IDF >= 5.0 * Set operatingmode on other than ESP-IDF --------- Co-authored-by: Keith Burzinski --- esphome/components/sntp/sntp_component.cpp | 23 +++++++++------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/esphome/components/sntp/sntp_component.cpp b/esphome/components/sntp/sntp_component.cpp index 6a60e8d5c1..a0e791be75 100644 --- a/esphome/components/sntp/sntp_component.cpp +++ b/esphome/components/sntp/sntp_component.cpp @@ -1,16 +1,11 @@ #include "sntp_component.h" #include "esphome/core/log.h" -#if defined(USE_ESP32) || defined(USE_LIBRETINY) -#include "lwip/apps/sntp.h" #ifdef USE_ESP_IDF #include "esp_sntp.h" -#endif -#endif -#ifdef USE_ESP8266 +#elif USE_ESP8266 #include "sntp.h" -#endif -#ifdef USE_RP2040 +#else #include "lwip/apps/sntp.h" #endif @@ -27,14 +22,14 @@ static const char *const TAG = "sntp"; void SNTPComponent::setup() { #ifndef USE_HOST ESP_LOGCONFIG(TAG, "Setting up SNTP..."); -#if defined(USE_ESP32) || defined(USE_LIBRETINY) - if (sntp_enabled()) { - sntp_stop(); +#if defined(USE_ESP_IDF) + if (esp_sntp_enabled()) { + esp_sntp_stop(); } - sntp_setoperatingmode(SNTP_OPMODE_POLL); -#endif -#ifdef USE_ESP8266 + esp_sntp_setoperatingmode(ESP_SNTP_OPMODE_POLL); +#else sntp_stop(); + sntp_setoperatingmode(SNTP_OPMODE_POLL); #endif sntp_setservername(0, strdup(this->server_1_.c_str())); @@ -45,7 +40,7 @@ void SNTPComponent::setup() { sntp_setservername(2, strdup(this->server_3_.c_str())); } #ifdef USE_ESP_IDF - sntp_set_sync_interval(this->get_update_interval()); + esp_sntp_set_sync_interval(this->get_update_interval()); #endif sntp_init(); From 05491e756bb76c43c669009ac7afb5da877b5ee1 Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Mon, 3 Jun 2024 18:34:47 -0700 Subject: [PATCH 1535/2101] Avoid unsafe git error when container user and file config volume permissions don't match (#6843) --- docker/Dockerfile | 3 +++ script/setup | 5 ----- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 3c661b7e1c..f6234235f7 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -100,6 +100,9 @@ RUN --mount=type=tmpfs,target=/root/.cargo if [ "$TARGETARCH$TARGETVARIANT" = "a --break-system-packages --no-cache-dir -r /requirements.txt -r /requirements_optional.txt \ && /platformio_install_deps.py /platformio.ini --libraries +# Avoid unsafe git error when container user and file config volume permissions don't match +RUN git config --system --add safe.directory '/config/*' + # ======================= docker-type image ======================= FROM base AS docker diff --git a/script/setup b/script/setup index 1a18a6a9ea..aeb1b39bc1 100755 --- a/script/setup +++ b/script/setup @@ -13,11 +13,6 @@ if [ ! -n "$DEVCONTAINER" ] && [ ! -n "$VIRTUAL_ENV" ] && [ ! "$ESPHOME_NO_VENV" source $location fi -# Avoid unsafe git error when running inside devcontainer -if [ -n "$DEVCONTAINER" ]; then - git config --global --add safe.directory "$PWD" -fi - pip3 install -r requirements.txt -r requirements_optional.txt -r requirements_test.txt -r requirements_dev.txt pip3 install setuptools wheel pip3 install -e ".[dev,test,displays]" --config-settings editable_mode=compat From 78b48209aa2456e05bc2c94357e58809d9c7403f Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Mon, 3 Jun 2024 19:57:05 -0700 Subject: [PATCH 1536/2101] Add Ethernet MAC address to ethernet_info (#6835) --- .../ethernet/ethernet_component.cpp | 54 +++++++++++++------ .../components/ethernet/ethernet_component.h | 4 ++ .../ethernet_info_text_sensor.cpp | 1 + .../ethernet_info/ethernet_info_text_sensor.h | 7 +++ .../components/ethernet_info/text_sensor.py | 11 ++++ tests/components/ethernet_info/common.yaml | 2 + 6 files changed, 63 insertions(+), 16 deletions(-) diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index 7672dc2dcb..6bb9732fef 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -28,6 +28,13 @@ EthernetComponent *global_eth_component; // NOLINT(cppcoreguidelines-avoid-non- return; \ } +#define ESPHL_ERROR_CHECK_RET(err, message, ret) \ + if ((err) != ESP_OK) { \ + ESP_LOGE(TAG, message ": (%d) %s", err, esp_err_to_name(err)); \ + this->mark_failed(); \ + return ret; \ + } + EthernetComponent::EthernetComponent() { global_eth_component = this; } void EthernetComponent::setup() { @@ -498,22 +505,9 @@ void EthernetComponent::dump_connect_params_() { } #endif /* USE_NETWORK_IPV6 */ - esp_err_t err; - - uint8_t mac[6]; - err = esp_eth_ioctl(this->eth_handle_, ETH_CMD_G_MAC_ADDR, &mac); - ESPHL_ERROR_CHECK(err, "ETH_CMD_G_MAC error"); - ESP_LOGCONFIG(TAG, " MAC Address: %02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - - eth_duplex_t duplex_mode; - err = esp_eth_ioctl(this->eth_handle_, ETH_CMD_G_DUPLEX_MODE, &duplex_mode); - ESPHL_ERROR_CHECK(err, "ETH_CMD_G_DUPLEX_MODE error"); - ESP_LOGCONFIG(TAG, " Is Full Duplex: %s", YESNO(duplex_mode == ETH_DUPLEX_FULL)); - - eth_speed_t speed; - err = esp_eth_ioctl(this->eth_handle_, ETH_CMD_G_SPEED, &speed); - ESPHL_ERROR_CHECK(err, "ETH_CMD_G_SPEED error"); - ESP_LOGCONFIG(TAG, " Link Speed: %u", speed == ETH_SPEED_100M ? 100 : 10); + ESP_LOGCONFIG(TAG, " MAC Address: %s", this->get_eth_mac_address_pretty().c_str()); + ESP_LOGCONFIG(TAG, " Is Full Duplex: %s", YESNO(this->get_duplex_mode() == ETH_DUPLEX_FULL)); + ESP_LOGCONFIG(TAG, " Link Speed: %u", this->get_link_speed() == ETH_SPEED_100M ? 100 : 10); } #ifdef USE_ETHERNET_SPI @@ -546,6 +540,34 @@ std::string EthernetComponent::get_use_address() const { void EthernetComponent::set_use_address(const std::string &use_address) { this->use_address_ = use_address; } +void EthernetComponent::get_eth_mac_address_raw(uint8_t *mac) { + esp_err_t err; + err = esp_eth_ioctl(this->eth_handle_, ETH_CMD_G_MAC_ADDR, mac); + ESPHL_ERROR_CHECK(err, "ETH_CMD_G_MAC error"); +} + +std::string EthernetComponent::get_eth_mac_address_pretty() { + uint8_t mac[6]; + get_mac_address_raw(mac); + return str_snprintf("%02X:%02X:%02X:%02X:%02X:%02X", 17, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); +} + +eth_duplex_t EthernetComponent::get_duplex_mode() { + esp_err_t err; + eth_duplex_t duplex_mode; + err = esp_eth_ioctl(this->eth_handle_, ETH_CMD_G_DUPLEX_MODE, &duplex_mode); + ESPHL_ERROR_CHECK_RET(err, "ETH_CMD_G_DUPLEX_MODE error", ETH_DUPLEX_HALF); + return duplex_mode; +} + +eth_speed_t EthernetComponent::get_link_speed() { + esp_err_t err; + eth_speed_t speed; + err = esp_eth_ioctl(this->eth_handle_, ETH_CMD_G_SPEED, &speed); + ESPHL_ERROR_CHECK_RET(err, "ETH_CMD_G_SPEED error", ETH_SPEED_10M); + return speed; +} + bool EthernetComponent::powerdown() { ESP_LOGI(TAG, "Powering down ethernet PHY"); if (this->phy_ == nullptr) { diff --git a/esphome/components/ethernet/ethernet_component.h b/esphome/components/ethernet/ethernet_component.h index 3705e3e06a..e57aa5fe12 100644 --- a/esphome/components/ethernet/ethernet_component.h +++ b/esphome/components/ethernet/ethernet_component.h @@ -74,6 +74,10 @@ class EthernetComponent : public Component { network::IPAddress get_dns_address(uint8_t num); std::string get_use_address() const; void set_use_address(const std::string &use_address); + void get_eth_mac_address_raw(uint8_t *mac); + std::string get_eth_mac_address_pretty(); + eth_duplex_t get_duplex_mode(); + eth_speed_t get_link_speed(); bool powerdown(); protected: diff --git a/esphome/components/ethernet_info/ethernet_info_text_sensor.cpp b/esphome/components/ethernet_info/ethernet_info_text_sensor.cpp index c8b2b5885b..329fb9113a 100644 --- a/esphome/components/ethernet_info/ethernet_info_text_sensor.cpp +++ b/esphome/components/ethernet_info/ethernet_info_text_sensor.cpp @@ -10,6 +10,7 @@ static const char *const TAG = "ethernet_info"; void IPAddressEthernetInfo::dump_config() { LOG_TEXT_SENSOR("", "EthernetInfo IPAddress", this); } void DNSAddressEthernetInfo::dump_config() { LOG_TEXT_SENSOR("", "EthernetInfo DNS Address", this); } +void MACAddressEthernetInfo::dump_config() { LOG_TEXT_SENSOR("", "EthernetInfo MAC Address", this); } } // namespace ethernet_info } // namespace esphome diff --git a/esphome/components/ethernet_info/ethernet_info_text_sensor.h b/esphome/components/ethernet_info/ethernet_info_text_sensor.h index 82a7dcf56e..94eed886e5 100644 --- a/esphome/components/ethernet_info/ethernet_info_text_sensor.h +++ b/esphome/components/ethernet_info/ethernet_info_text_sensor.h @@ -59,6 +59,13 @@ class DNSAddressEthernetInfo : public PollingComponent, public text_sensor::Text std::string last_results_; }; +class MACAddressEthernetInfo : public Component, public text_sensor::TextSensor { + public: + void setup() override { this->publish_state(ethernet::global_eth_component->get_eth_mac_address_pretty()); } + std::string unique_id() override { return get_mac_address() + "-ethernetinfo-mac"; } + void dump_config() override; +}; + } // namespace ethernet_info } // namespace esphome diff --git a/esphome/components/ethernet_info/text_sensor.py b/esphome/components/ethernet_info/text_sensor.py index 292673c182..a545475870 100644 --- a/esphome/components/ethernet_info/text_sensor.py +++ b/esphome/components/ethernet_info/text_sensor.py @@ -4,6 +4,7 @@ from esphome.components import text_sensor from esphome.const import ( CONF_IP_ADDRESS, CONF_DNS_ADDRESS, + CONF_MAC_ADDRESS, ENTITY_CATEGORY_DIAGNOSTIC, ) @@ -19,6 +20,10 @@ DNSAddressEthernetInfo = ethernet_info_ns.class_( "DNSAddressEthernetInfo", text_sensor.TextSensor, cg.PollingComponent ) +MACAddressEthernetInfo = ethernet_info_ns.class_( + "MACAddressEthernetInfo", text_sensor.TextSensor, cg.PollingComponent +) + CONFIG_SCHEMA = cv.Schema( { cv.Optional(CONF_IP_ADDRESS): text_sensor.text_sensor_schema( @@ -36,6 +41,9 @@ CONFIG_SCHEMA = cv.Schema( cv.Optional(CONF_DNS_ADDRESS): text_sensor.text_sensor_schema( DNSAddressEthernetInfo, entity_category=ENTITY_CATEGORY_DIAGNOSTIC ).extend(cv.polling_component_schema("1s")), + cv.Optional(CONF_MAC_ADDRESS): text_sensor.text_sensor_schema( + MACAddressEthernetInfo, entity_category=ENTITY_CATEGORY_DIAGNOSTIC + ), } ) @@ -51,3 +59,6 @@ async def to_code(config): if conf := config.get(CONF_DNS_ADDRESS): dns_info = await text_sensor.new_text_sensor(config[CONF_DNS_ADDRESS]) await cg.register_component(dns_info, config[CONF_DNS_ADDRESS]) + if conf := config.get(CONF_MAC_ADDRESS): + mac_info = await text_sensor.new_text_sensor(config[CONF_MAC_ADDRESS]) + await cg.register_component(mac_info, config[CONF_MAC_ADDRESS]) diff --git a/tests/components/ethernet_info/common.yaml b/tests/components/ethernet_info/common.yaml index dade4d7ca5..d9a6f515b1 100644 --- a/tests/components/ethernet_info/common.yaml +++ b/tests/components/ethernet_info/common.yaml @@ -17,3 +17,5 @@ text_sensor: name: IP Address dns_address: name: DNS Address + mac_address: + name: MAC Address From cdf83c5d8c1f8ff99d77b63b04177d253feecbb3 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Tue, 4 Jun 2024 13:09:46 +1000 Subject: [PATCH 1537/2101] Add host time platform; remove host support from sntp. (#6854) --- CODEOWNERS | 3 +- esphome/components/host/__init__.py | 2 +- esphome/components/host/time/__init__.py | 20 +++++++++++ esphome/components/host/time/host_time.h | 15 +++++++++ esphome/components/sntp/sntp_component.cpp | 4 +-- esphome/components/sntp/time.py | 39 ++++++++++++++++------ tests/components/host/common.yaml | 7 +--- tests/components/sntp/test.bk72xx.yaml | 1 + 8 files changed, 69 insertions(+), 22 deletions(-) create mode 100644 esphome/components/host/time/__init__.py create mode 100644 esphome/components/host/time/host_time.h create mode 100644 tests/components/sntp/test.bk72xx.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 0dc5339193..82f61c3b80 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -167,7 +167,8 @@ esphome/components/homeassistant/* @OttoWinter esphome/components/honeywell_hih_i2c/* @Benichou34 esphome/components/honeywellabp/* @RubyBailey esphome/components/honeywellabp2_i2c/* @jpfaff -esphome/components/host/* @esphome/core +esphome/components/host/* @clydebarrow @esphome/core +esphome/components/host/time/* @clydebarrow esphome/components/hrxl_maxsonar_wr/* @netmikey esphome/components/hte501/* @Stock-M esphome/components/htu31d/* @betterengineering diff --git a/esphome/components/host/__init__.py b/esphome/components/host/__init__.py index 3bd3b6b172..39e418c9ea 100644 --- a/esphome/components/host/__init__.py +++ b/esphome/components/host/__init__.py @@ -16,7 +16,7 @@ from .const import KEY_HOST # force import gpio to register pin schema from .gpio import host_pin_to_code # noqa -CODEOWNERS = ["@esphome/core"] +CODEOWNERS = ["@esphome/core", "@clydebarrow"] AUTO_LOAD = ["network"] diff --git a/esphome/components/host/time/__init__.py b/esphome/components/host/time/__init__.py new file mode 100644 index 0000000000..76a88d98a1 --- /dev/null +++ b/esphome/components/host/time/__init__.py @@ -0,0 +1,20 @@ +import esphome.codegen as cg +from esphome.const import CONF_ID +import esphome.config_validation as cv +from esphome.components import time as time_ + +CODEOWNERS = ["@clydebarrow"] + +time_ns = cg.esphome_ns.namespace("host") +HostTime = time_ns.class_("HostTime", time_.RealTimeClock) +CONFIG_SCHEMA = time_.TIME_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(HostTime), + } +).extend(cv.COMPONENT_SCHEMA) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, config) + await time_.register_time(var, config) diff --git a/esphome/components/host/time/host_time.h b/esphome/components/host/time/host_time.h new file mode 100644 index 0000000000..4f1473b809 --- /dev/null +++ b/esphome/components/host/time/host_time.h @@ -0,0 +1,15 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/components/time/real_time_clock.h" + +namespace esphome { +namespace host { + +class HostTime : public time::RealTimeClock { + public: + void update() override {} +}; + +} // namespace host +} // namespace esphome diff --git a/esphome/components/sntp/sntp_component.cpp b/esphome/components/sntp/sntp_component.cpp index a0e791be75..4ded98d483 100644 --- a/esphome/components/sntp/sntp_component.cpp +++ b/esphome/components/sntp/sntp_component.cpp @@ -20,7 +20,6 @@ namespace sntp { static const char *const TAG = "sntp"; void SNTPComponent::setup() { -#ifndef USE_HOST ESP_LOGCONFIG(TAG, "Setting up SNTP..."); #if defined(USE_ESP_IDF) if (esp_sntp_enabled()) { @@ -44,7 +43,6 @@ void SNTPComponent::setup() { #endif sntp_init(); -#endif } void SNTPComponent::dump_config() { ESP_LOGCONFIG(TAG, "SNTP Time:"); @@ -54,7 +52,7 @@ void SNTPComponent::dump_config() { ESP_LOGCONFIG(TAG, " Timezone: '%s'", this->timezone_.c_str()); } void SNTPComponent::update() { -#if !defined(USE_ESP_IDF) && !defined(USE_HOST) +#if !defined(USE_ESP_IDF) // force resync if (sntp_enabled()) { sntp_stop(); diff --git a/esphome/components/sntp/time.py b/esphome/components/sntp/time.py index b1362f5421..7cc82e3dff 100644 --- a/esphome/components/sntp/time.py +++ b/esphome/components/sntp/time.py @@ -2,24 +2,41 @@ from esphome.components import time as time_ import esphome.config_validation as cv import esphome.codegen as cg from esphome.core import CORE -from esphome.const import CONF_ID, CONF_SERVERS - +from esphome.const import ( + CONF_ID, + CONF_SERVERS, + PLATFORM_ESP32, + PLATFORM_ESP8266, + PLATFORM_RP2040, + PLATFORM_RTL87XX, + PLATFORM_BK72XX, +) DEPENDENCIES = ["network"] sntp_ns = cg.esphome_ns.namespace("sntp") SNTPComponent = sntp_ns.class_("SNTPComponent", time_.RealTimeClock) - DEFAULT_SERVERS = ["0.pool.ntp.org", "1.pool.ntp.org", "2.pool.ntp.org"] -CONFIG_SCHEMA = time_.TIME_SCHEMA.extend( - { - cv.GenerateID(): cv.declare_id(SNTPComponent), - cv.Optional(CONF_SERVERS, default=DEFAULT_SERVERS): cv.All( - cv.ensure_list(cv.Any(cv.domain, cv.hostname)), cv.Length(min=1, max=3) - ), - } -).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = cv.All( + time_.TIME_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(SNTPComponent), + cv.Optional(CONF_SERVERS, default=DEFAULT_SERVERS): cv.All( + cv.ensure_list(cv.Any(cv.domain, cv.hostname)), cv.Length(min=1, max=3) + ), + } + ).extend(cv.COMPONENT_SCHEMA), + cv.only_on( + [ + PLATFORM_ESP32, + PLATFORM_ESP8266, + PLATFORM_RP2040, + PLATFORM_BK72XX, + PLATFORM_RTL87XX, + ] + ), +) async def to_code(config): diff --git a/tests/components/host/common.yaml b/tests/components/host/common.yaml index 3d14c190a6..fca0c5d597 100644 --- a/tests/components/host/common.yaml +++ b/tests/components/host/common.yaml @@ -1,15 +1,10 @@ time: - - platform: sntp + - platform: host id: esptime timezone: Australia/Sydney logger: level: VERBOSE - logs: - lvgl: INFO - display: DEBUG - sensor: INFO - vnc: DEBUG host: mac_address: "62:23:45:AF:B3:DD" diff --git a/tests/components/sntp/test.bk72xx.yaml b/tests/components/sntp/test.bk72xx.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/sntp/test.bk72xx.yaml @@ -0,0 +1 @@ +<<: !include common.yaml From 2d56d8d84feb8df4341725bfe0a409a44b5305a8 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Mon, 3 Jun 2024 22:10:44 -0500 Subject: [PATCH 1538/2101] [wireguard] Implement workaround for crash on IDF 5+ (#6846) --- esphome/components/wireguard/__init__.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/esphome/components/wireguard/__init__.py b/esphome/components/wireguard/__init__.py index 177ad6d356..5d5f620b51 100644 --- a/esphome/components/wireguard/__init__.py +++ b/esphome/components/wireguard/__init__.py @@ -7,7 +7,10 @@ from esphome.const import ( CONF_TIME_ID, CONF_ADDRESS, CONF_REBOOT_TIMEOUT, + KEY_CORE, + KEY_FRAMEWORK_VERSION, ) +from esphome.components.esp32 import CORE, add_idf_sdkconfig_option from esphome.components import time from esphome.core import TimePeriod from esphome import automation @@ -117,6 +120,13 @@ async def to_code(config): if config[CONF_REQUIRE_CONNECTION_TO_PROCEED]: cg.add(var.disable_auto_proceed()) + # Workaround for crash on IDF 5+ + # See https://github.com/trombik/esp_wireguard/issues/33#issuecomment-1568503651 + if CORE.using_esp_idf and CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] >= cv.Version( + 5, 0, 0 + ): + add_idf_sdkconfig_option("CONFIG_LWIP_PPP_SUPPORT", True) + # This flag is added here because the esp_wireguard library statically # set the size of its allowed_ips list at compile time using this value; # the '+1' modifier is relative to the device's own address that will From eb75778f84e32eed1f5a497471f86bb964906166 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Mon, 3 Jun 2024 22:18:20 -0500 Subject: [PATCH 1539/2101] [improv_serial] Fix for IDF 4.4.7 (#6855) --- esphome/components/improv_serial/improv_serial_component.cpp | 1 + esphome/components/improv_serial/improv_serial_component.h | 1 + 2 files changed, 2 insertions(+) diff --git a/esphome/components/improv_serial/improv_serial_component.cpp b/esphome/components/improv_serial/improv_serial_component.cpp index 40297bee68..2937720496 100644 --- a/esphome/components/improv_serial/improv_serial_component.cpp +++ b/esphome/components/improv_serial/improv_serial_component.cpp @@ -109,6 +109,7 @@ void ImprovSerialComponent::write_data_(std::vector &data) { #if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S3) case logger::UART_SELECTION_USB_SERIAL_JTAG: usb_serial_jtag_write_bytes((char *) data.data(), data.size(), 20 / portTICK_PERIOD_MS); + usb_serial_jtag_ll_txfifo_flush(); // fixes for issue in IDF 4.4.7 break; #endif // USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32S3 default: diff --git a/esphome/components/improv_serial/improv_serial_component.h b/esphome/components/improv_serial/improv_serial_component.h index 8583d0762b..f737f93d86 100644 --- a/esphome/components/improv_serial/improv_serial_component.h +++ b/esphome/components/improv_serial/improv_serial_component.h @@ -17,6 +17,7 @@ #if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S3) || \ defined(USE_ESP32_VARIANT_ESP32H2) #include +#include #endif #if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) #include From 69d38f61371f4f0548b50bedd1ca48784fa51028 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 5 Jun 2024 13:02:18 +1200 Subject: [PATCH 1540/2101] [ft5x06] Interrupt pin and code quality improvements (#6851) Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> --- .../components/ft5x06/touchscreen/__init__.py | 8 +- .../ft5x06/touchscreen/ft5x06_touchscreen.cpp | 102 ++++++++++++++++++ .../ft5x06/touchscreen/ft5x06_touchscreen.h | 94 ++-------------- 3 files changed, 119 insertions(+), 85 deletions(-) create mode 100644 esphome/components/ft5x06/touchscreen/ft5x06_touchscreen.cpp diff --git a/esphome/components/ft5x06/touchscreen/__init__.py b/esphome/components/ft5x06/touchscreen/__init__.py index adeeac0d1a..4ceb50c709 100644 --- a/esphome/components/ft5x06/touchscreen/__init__.py +++ b/esphome/components/ft5x06/touchscreen/__init__.py @@ -1,8 +1,9 @@ +from esphome import pins import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import i2c, touchscreen -from esphome.const import CONF_ID +from esphome.const import CONF_ID, CONF_INTERRUPT_PIN from .. import ft5x06_ns FT5x06ButtonListener = ft5x06_ns.class_("FT5x06ButtonListener") @@ -16,6 +17,7 @@ FT5x06Touchscreen = ft5x06_ns.class_( CONFIG_SCHEMA = touchscreen.TOUCHSCREEN_SCHEMA.extend( { cv.GenerateID(): cv.declare_id(FT5x06Touchscreen), + cv.Optional(CONF_INTERRUPT_PIN): pins.internal_gpio_input_pin_schema, } ).extend(i2c.i2c_device_schema(0x48)) @@ -24,3 +26,7 @@ async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await i2c.register_i2c_device(var, config) await touchscreen.register_touchscreen(var, config) + + if interrupt_pin := config.get(CONF_INTERRUPT_PIN): + pin = await cg.gpio_pin_expression(interrupt_pin) + cg.add(var.set_interrupt_pin(pin)) diff --git a/esphome/components/ft5x06/touchscreen/ft5x06_touchscreen.cpp b/esphome/components/ft5x06/touchscreen/ft5x06_touchscreen.cpp new file mode 100644 index 0000000000..bd603fdc10 --- /dev/null +++ b/esphome/components/ft5x06/touchscreen/ft5x06_touchscreen.cpp @@ -0,0 +1,102 @@ +#include "ft5x06_touchscreen.h" + +#include "esphome/core/log.h" + +namespace esphome { +namespace ft5x06 { + +static const char *const TAG = "ft5x06.touchscreen"; + +void FT5x06Touchscreen::setup() { + ESP_LOGCONFIG(TAG, "Setting up FT5x06 Touchscreen..."); + if (this->interrupt_pin_ != nullptr) { + this->interrupt_pin_->setup(); + this->interrupt_pin_->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP); + this->interrupt_pin_->setup(); + this->attach_interrupt_(this->interrupt_pin_, gpio::INTERRUPT_FALLING_EDGE); + } + + // wait 200ms after reset. + this->set_timeout(200, [this] { this->continue_setup_(); }); +} + +void FT5x06Touchscreen::continue_setup_() { + uint8_t data[4]; + if (!this->set_mode_(FT5X06_OP_MODE)) + return; + + if (!this->err_check_(this->read_register(FT5X06_VENDOR_ID_REG, data, 1), "Read Vendor ID")) + return; + switch (data[0]) { + case FT5X06_ID_1: + case FT5X06_ID_2: + case FT5X06_ID_3: + this->vendor_id_ = (VendorId) data[0]; + ESP_LOGD(TAG, "Read vendor ID 0x%X", data[0]); + break; + + default: + ESP_LOGE(TAG, "Unknown vendor ID 0x%X", data[0]); + this->mark_failed(); + return; + } + // reading the chip registers to get max x/y does not seem to work. + if (this->display_ != nullptr) { + if (this->x_raw_max_ == this->x_raw_min_) { + this->x_raw_max_ = this->display_->get_native_width(); + } + if (this->y_raw_max_ == this->y_raw_min_) { + this->y_raw_max_ = this->display_->get_native_height(); + } + } + ESP_LOGCONFIG(TAG, "FT5x06 Touchscreen setup complete"); +} + +void FT5x06Touchscreen::update_touches() { + uint8_t touch_cnt; + uint8_t data[MAX_TOUCHES][6]; + + if (!this->read_byte(FT5X06_TD_STATUS, &touch_cnt) || touch_cnt > MAX_TOUCHES) { + ESP_LOGW(TAG, "Failed to read status"); + return; + } + if (touch_cnt == 0) + return; + + if (!this->read_bytes(FT5X06_TOUCH_DATA, (uint8_t *) data, touch_cnt * 6)) { + ESP_LOGW(TAG, "Failed to read touch data"); + return; + } + for (uint8_t i = 0; i != touch_cnt; i++) { + uint8_t status = data[i][0] >> 6; + uint8_t id = data[i][2] >> 3; + uint16_t x = encode_uint16(data[i][0] & 0x0F, data[i][1]); + uint16_t y = encode_uint16(data[i][2] & 0xF, data[i][3]); + + ESP_LOGD(TAG, "Read %X status, id: %d, pos %d/%d", status, id, x, y); + if (status == 0 || status == 2) { + this->add_raw_touch_position_(id, x, y); + } + } +} + +void FT5x06Touchscreen::dump_config() { + ESP_LOGCONFIG(TAG, "FT5x06 Touchscreen:"); + ESP_LOGCONFIG(TAG, " Address: 0x%02X", this->address_); + ESP_LOGCONFIG(TAG, " Vendor ID: 0x%X", (int) this->vendor_id_); +} + +bool FT5x06Touchscreen::err_check_(i2c::ErrorCode err, const char *msg) { + if (err != i2c::ERROR_OK) { + this->mark_failed(); + ESP_LOGE(TAG, "%s failed - err 0x%X", msg, err); + return false; + } + return true; +} +bool FT5x06Touchscreen::set_mode_(FTMode mode) { + return this->err_check_(this->write_register(FT5X06_MODE_REG, (uint8_t *) &mode, 1), "Set mode"); +} + +} // namespace ft5x06 +} // namespace esphome diff --git a/esphome/components/ft5x06/touchscreen/ft5x06_touchscreen.h b/esphome/components/ft5x06/touchscreen/ft5x06_touchscreen.h index 7ddd2e44d7..23e5a0c49f 100644 --- a/esphome/components/ft5x06/touchscreen/ft5x06_touchscreen.h +++ b/esphome/components/ft5x06/touchscreen/ft5x06_touchscreen.h @@ -3,14 +3,12 @@ #include "esphome/components/i2c/i2c.h" #include "esphome/components/touchscreen/touchscreen.h" #include "esphome/core/component.h" +#include "esphome/core/gpio.h" #include "esphome/core/hal.h" -#include "esphome/core/log.h" namespace esphome { namespace ft5x06 { -static const char *const TAG = "ft5x06.touchscreen"; - enum VendorId { FT5X06_ID_UNKNOWN = 0, FT5X06_ID_1 = 0x51, @@ -39,91 +37,19 @@ static const size_t MAX_TOUCHES = 5; // max number of possible touches reported class FT5x06Touchscreen : public touchscreen::Touchscreen, public i2c::I2CDevice { public: - void setup() override { - esph_log_config(TAG, "Setting up FT5x06 Touchscreen..."); - // wait 200ms after reset. - this->set_timeout(200, [this] { this->continue_setup_(); }); - } + void setup() override; + void dump_config() override; + void update_touches() override; - void continue_setup_(void) { - uint8_t data[4]; - if (!this->set_mode_(FT5X06_OP_MODE)) - return; - - if (!this->err_check_(this->read_register(FT5X06_VENDOR_ID_REG, data, 1), "Read Vendor ID")) - return; - switch (data[0]) { - case FT5X06_ID_1: - case FT5X06_ID_2: - case FT5X06_ID_3: - this->vendor_id_ = (VendorId) data[0]; - esph_log_d(TAG, "Read vendor ID 0x%X", data[0]); - break; - - default: - esph_log_e(TAG, "Unknown vendor ID 0x%X", data[0]); - this->mark_failed(); - return; - } - // reading the chip registers to get max x/y does not seem to work. - if (this->display_ != nullptr) { - if (this->x_raw_max_ == this->x_raw_min_) { - this->x_raw_max_ = this->display_->get_native_width(); - } - if (this->y_raw_max_ == this->y_raw_min_) { - this->y_raw_max_ = this->display_->get_native_height(); - } - } - esph_log_config(TAG, "FT5x06 Touchscreen setup complete"); - } - - void update_touches() override { - uint8_t touch_cnt; - uint8_t data[MAX_TOUCHES][6]; - - if (!this->read_byte(FT5X06_TD_STATUS, &touch_cnt) || touch_cnt > MAX_TOUCHES) { - esph_log_w(TAG, "Failed to read status"); - return; - } - if (touch_cnt == 0) - return; - - if (!this->read_bytes(FT5X06_TOUCH_DATA, (uint8_t *) data, touch_cnt * 6)) { - esph_log_w(TAG, "Failed to read touch data"); - return; - } - for (uint8_t i = 0; i != touch_cnt; i++) { - uint8_t status = data[i][0] >> 6; - uint8_t id = data[i][2] >> 3; - uint16_t x = encode_uint16(data[i][0] & 0x0F, data[i][1]); - uint16_t y = encode_uint16(data[i][2] & 0xF, data[i][3]); - - esph_log_d(TAG, "Read %X status, id: %d, pos %d/%d", status, id, x, y); - if (status == 0 || status == 2) { - this->add_raw_touch_position_(id, x, y); - } - } - } - - void dump_config() override { - esph_log_config(TAG, "FT5x06 Touchscreen:"); - esph_log_config(TAG, " Address: 0x%02X", this->address_); - esph_log_config(TAG, " Vendor ID: 0x%X", (int) this->vendor_id_); - } + void set_interrupt_pin(InternalGPIOPin *interrupt_pin) { this->interrupt_pin_ = interrupt_pin; } protected: - bool err_check_(i2c::ErrorCode err, const char *msg) { - if (err != i2c::ERROR_OK) { - this->mark_failed(); - esph_log_e(TAG, "%s failed - err 0x%X", msg, err); - return false; - } - return true; - } - bool set_mode_(FTMode mode) { - return this->err_check_(this->write_register(FT5X06_MODE_REG, (uint8_t *) &mode, 1), "Set mode"); - } + void continue_setup_(); + bool err_check_(i2c::ErrorCode err, const char *msg); + bool set_mode_(FTMode mode); VendorId vendor_id_{FT5X06_ID_UNKNOWN}; + + InternalGPIOPin *interrupt_pin_{nullptr}; }; } // namespace ft5x06 From ac9f57600db0f44a9a1b048e5228d6b67df29d50 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 30 May 2024 20:00:09 +1200 Subject: [PATCH 1541/2101] [voice_assistant] Half the microphone ringbuffer size (#6830) --- esphome/components/voice_assistant/voice_assistant.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index 59ba39c527..421bca9afb 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -17,7 +17,7 @@ static const char *const TAG = "voice_assistant"; static const size_t SAMPLE_RATE_HZ = 16000; static const size_t INPUT_BUFFER_SIZE = 32 * SAMPLE_RATE_HZ / 1000; // 32ms * 16kHz / 1000ms -static const size_t BUFFER_SIZE = 1024 * SAMPLE_RATE_HZ / 1000; +static const size_t BUFFER_SIZE = 512 * SAMPLE_RATE_HZ / 1000; static const size_t SEND_BUFFER_SIZE = INPUT_BUFFER_SIZE * sizeof(int16_t); static const size_t RECEIVE_SIZE = 1024; static const size_t SPEAKER_BUFFER_SIZE = 16 * RECEIVE_SIZE; From ce4a3d995006a6f2b0a7afbee2f47c9807f54831 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 30 May 2024 20:01:39 +1200 Subject: [PATCH 1542/2101] [i2s_speaker] Add buffer allocation failure checks (#6829) --- .../i2s_audio/speaker/i2s_audio_speaker.cpp | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp index 95e63035fe..7f03a43da4 100644 --- a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +++ b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp @@ -19,10 +19,27 @@ void I2SAudioSpeaker::setup() { ESP_LOGCONFIG(TAG, "Setting up I2S Audio Speaker..."); this->buffer_queue_ = xQueueCreate(BUFFER_COUNT, sizeof(DataEvent)); + if (this->buffer_queue_ == nullptr) { + ESP_LOGE(TAG, "Failed to create buffer queue"); + this->mark_failed(); + return; + } + this->event_queue_ = xQueueCreate(BUFFER_COUNT, sizeof(TaskEvent)); + if (this->event_queue_ == nullptr) { + ESP_LOGE(TAG, "Failed to create event queue"); + this->mark_failed(); + return; + } } -void I2SAudioSpeaker::start() { this->state_ = speaker::STATE_STARTING; } +void I2SAudioSpeaker::start() { + if (this->is_failed()) { + ESP_LOGE(TAG, "Cannot start audio, speaker failed to setup"); + return; + } + this->state_ = speaker::STATE_STARTING; +} void I2SAudioSpeaker::start_() { if (!this->parent_->try_lock()) { return; // Waiting for another i2s component to return lock @@ -141,6 +158,8 @@ void I2SAudioSpeaker::player_task(void *params) { } void I2SAudioSpeaker::stop() { + if (this->is_failed()) + return; if (this->state_ == speaker::STATE_STOPPED) return; if (this->state_ == speaker::STATE_STARTING) { @@ -200,6 +219,10 @@ void I2SAudioSpeaker::loop() { } size_t I2SAudioSpeaker::play(const uint8_t *data, size_t length) { + if (this->is_failed()) { + ESP_LOGE(TAG, "Cannot play audio, speaker failed to setup"); + return 0; + } if (this->state_ != speaker::STATE_RUNNING && this->state_ != speaker::STATE_STARTING) { this->start(); } From 388b2c2de0e92f4f5a8d18379e651a266b3750fa Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Mon, 3 Jun 2024 22:18:20 -0500 Subject: [PATCH 1543/2101] [improv_serial] Fix for IDF 4.4.7 (#6855) --- esphome/components/improv_serial/improv_serial_component.cpp | 1 + esphome/components/improv_serial/improv_serial_component.h | 1 + 2 files changed, 2 insertions(+) diff --git a/esphome/components/improv_serial/improv_serial_component.cpp b/esphome/components/improv_serial/improv_serial_component.cpp index 40297bee68..2937720496 100644 --- a/esphome/components/improv_serial/improv_serial_component.cpp +++ b/esphome/components/improv_serial/improv_serial_component.cpp @@ -109,6 +109,7 @@ void ImprovSerialComponent::write_data_(std::vector &data) { #if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S3) case logger::UART_SELECTION_USB_SERIAL_JTAG: usb_serial_jtag_write_bytes((char *) data.data(), data.size(), 20 / portTICK_PERIOD_MS); + usb_serial_jtag_ll_txfifo_flush(); // fixes for issue in IDF 4.4.7 break; #endif // USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32S3 default: diff --git a/esphome/components/improv_serial/improv_serial_component.h b/esphome/components/improv_serial/improv_serial_component.h index 8583d0762b..f737f93d86 100644 --- a/esphome/components/improv_serial/improv_serial_component.h +++ b/esphome/components/improv_serial/improv_serial_component.h @@ -17,6 +17,7 @@ #if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S3) || \ defined(USE_ESP32_VARIANT_ESP32H2) #include +#include #endif #if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) #include From 664ee56dc5c3170bab8722dea504cbf072e95ccb Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 5 Jun 2024 15:51:29 +1200 Subject: [PATCH 1544/2101] Bump version to 2024.5.5 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index ad5858dcf3..658773b3db 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.5.4" +__version__ = "2024.5.5" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 594856899a657ce5787f00d3432982869d29a8e9 Mon Sep 17 00:00:00 2001 From: Nate Clark Date: Wed, 5 Jun 2024 02:51:56 -0400 Subject: [PATCH 1545/2101] [ethernet] Add config option to set arbitrary PHY register values (#6836) --- esphome/components/ethernet/__init__.py | 29 ++++++++++ .../ethernet/ethernet_component.cpp | 58 +++++++------------ .../components/ethernet/ethernet_component.h | 12 +++- 3 files changed, 60 insertions(+), 39 deletions(-) diff --git a/esphome/components/ethernet/__init__.py b/esphome/components/ethernet/__init__.py index ade94cb9f5..697436415b 100644 --- a/esphome/components/ethernet/__init__.py +++ b/esphome/components/ethernet/__init__.py @@ -11,6 +11,7 @@ from esphome.components.esp32.const import ( from esphome.const import ( CONF_DOMAIN, CONF_ID, + CONF_VALUE, CONF_MANUAL_IP, CONF_STATIC_IP, CONF_TYPE, @@ -26,6 +27,8 @@ from esphome.const import ( CONF_INTERRUPT_PIN, CONF_RESET_PIN, CONF_SPI, + CONF_PAGE_ID, + CONF_ADDRESS, ) from esphome.core import CORE, coroutine_with_priority from esphome.components.network import IPAddress @@ -36,11 +39,13 @@ DEPENDENCIES = ["esp32"] AUTO_LOAD = ["network"] ethernet_ns = cg.esphome_ns.namespace("ethernet") +PHYRegister = ethernet_ns.struct("PHYRegister") CONF_PHY_ADDR = "phy_addr" CONF_MDC_PIN = "mdc_pin" CONF_MDIO_PIN = "mdio_pin" CONF_CLK_MODE = "clk_mode" CONF_POWER_PIN = "power_pin" +CONF_PHY_REGISTERS = "phy_registers" CONF_CLOCK_SPEED = "clock_speed" @@ -117,6 +122,13 @@ BASE_SCHEMA = cv.Schema( } ).extend(cv.COMPONENT_SCHEMA) +PHY_REGISTER_SCHEMA = cv.Schema( + { + cv.Required(CONF_ADDRESS): cv.hex_int, + cv.Required(CONF_VALUE): cv.hex_int, + cv.Optional(CONF_PAGE_ID): cv.hex_int, + } +) RMII_SCHEMA = BASE_SCHEMA.extend( cv.Schema( { @@ -127,6 +139,7 @@ RMII_SCHEMA = BASE_SCHEMA.extend( ), cv.Optional(CONF_PHY_ADDR, default=0): cv.int_range(min=0, max=31), cv.Optional(CONF_POWER_PIN): pins.internal_gpio_output_pin_number, + cv.Optional(CONF_PHY_REGISTERS): cv.ensure_list(PHY_REGISTER_SCHEMA), } ) ) @@ -198,6 +211,15 @@ def manual_ip(config): ) +def phy_register(address: int, value: int, page: int): + return cg.StructInitializer( + PHYRegister, + ("address", address), + ("value", value), + ("page", page), + ) + + @coroutine_with_priority(60.0) async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) @@ -225,6 +247,13 @@ async def to_code(config): cg.add(var.set_clk_mode(*CLK_MODES[config[CONF_CLK_MODE]])) if CONF_POWER_PIN in config: cg.add(var.set_power_pin(config[CONF_POWER_PIN])) + for register_value in config.get(CONF_PHY_REGISTERS, []): + reg = phy_register( + register_value.get(CONF_ADDRESS), + register_value.get(CONF_VALUE), + register_value.get(CONF_PAGE_ID), + ) + cg.add(var.add_phy_register(reg)) cg.add(var.set_type(ETHERNET_TYPES[config[CONF_TYPE]])) cg.add(var.set_use_address(config[CONF_USE_ADDRESS])) diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index 6bb9732fef..75bdd29be7 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -195,9 +195,9 @@ void EthernetComponent::setup() { // KSZ8081RNA default is incorrect. It expects a 25MHz clock instead of the 50MHz we provide. this->ksz8081_set_clock_reference_(mac); } - if (this->type_ == ETHERNET_TYPE_RTL8201 && this->clk_mode_ == EMAC_CLK_EXT_IN) { - // Change in default behavior of RTL8201FI may require register setting to enable external clock - this->rtl8201_set_rmii_mode_(mac); + + for (const auto &phy_register : this->phy_registers_) { + this->write_phy_register_(mac, phy_register); } #endif @@ -527,6 +527,7 @@ void EthernetComponent::set_clk_mode(emac_rmii_clock_mode_t clk_mode, emac_rmii_ this->clk_mode_ = clk_mode; this->clk_gpio_ = clk_gpio; } +void EthernetComponent::add_phy_register(PHYRegister register_value) { this->phy_registers_.push_back(register_value); } #endif void EthernetComponent::set_type(EthernetType type) { this->type_ = type; } void EthernetComponent::set_manual_ip(const ManualIP &manual_ip) { this->manual_ip_ = manual_ip; } @@ -613,44 +614,27 @@ void EthernetComponent::ksz8081_set_clock_reference_(esp_eth_mac_t *mac) { ESP_LOGVV(TAG, "KSZ8081 PHY Control 2: %s", format_hex_pretty((u_int8_t *) &phy_control_2, 2).c_str()); } } -constexpr uint8_t RTL8201_RMSR_REG_ADDR = 0x10; -void EthernetComponent::rtl8201_set_rmii_mode_(esp_eth_mac_t *mac) { + +void EthernetComponent::write_phy_register_(esp_eth_mac_t *mac, PHYRegister register_data) { esp_err_t err; - uint32_t phy_rmii_mode; - err = mac->write_phy_reg(mac, this->phy_addr_, 0x1f, 0x07); - ESPHL_ERROR_CHECK(err, "Setting Page 7 failed"); + constexpr uint8_t eth_phy_psr_reg_addr = 0x1F; - /* - * RTL8201 RMII Mode Setting Register (RMSR) - * Page 7 Register 16 - * - * bit 0 Reserved 0 - * bit 1 Rg_rmii_rxdsel 1 (default) - * bit 2 Rg_rmii_rxdv_sel: 0 (default) - * bit 3 RMII Mode: 1 (RMII Mode) - * bit 4~7 Rg_rmii_rx_offset: 1111 (default) - * bit 8~11 Rg_rmii_tx_offset: 1111 (default) - * bit 12 Rg_rmii_clkdir: 1 (Input) - * bit 13~15 Reserved 000 - * - * Binary: 0001 1111 1111 1010 - * Hex: 0x1FFA - * - */ + if (this->type_ == ETHERNET_TYPE_RTL8201 && register_data.page) { + ESP_LOGD(TAG, "Select PHY Register Page: 0x%02" PRIX32, register_data.page); + err = mac->write_phy_reg(mac, this->phy_addr_, eth_phy_psr_reg_addr, register_data.page); + ESPHL_ERROR_CHECK(err, "Select PHY Register page failed"); + } - err = mac->read_phy_reg(mac, this->phy_addr_, RTL8201_RMSR_REG_ADDR, &(phy_rmii_mode)); - ESPHL_ERROR_CHECK(err, "Read PHY RMSR Register failed"); - ESP_LOGV(TAG, "Hardware default RTL8201 RMII Mode Register is: 0x%04" PRIX32, phy_rmii_mode); + ESP_LOGD(TAG, "Writing to PHY Register Address: 0x%02" PRIX32, register_data.address); + ESP_LOGD(TAG, "Writing to PHY Register Value: 0x%04" PRIX32, register_data.value); + err = mac->write_phy_reg(mac, this->phy_addr_, register_data.address, register_data.value); + ESPHL_ERROR_CHECK(err, "Writing PHY Register failed"); - err = mac->write_phy_reg(mac, this->phy_addr_, RTL8201_RMSR_REG_ADDR, 0x1FFA); - ESPHL_ERROR_CHECK(err, "Setting Register 16 RMII Mode Setting failed"); - - err = mac->read_phy_reg(mac, this->phy_addr_, RTL8201_RMSR_REG_ADDR, &(phy_rmii_mode)); - ESPHL_ERROR_CHECK(err, "Read PHY RMSR Register failed"); - ESP_LOGV(TAG, "Setting RTL8201 RMII Mode Register to: 0x%04" PRIX32, phy_rmii_mode); - - err = mac->write_phy_reg(mac, this->phy_addr_, 0x1f, 0x0); - ESPHL_ERROR_CHECK(err, "Setting Page 0 failed"); + if (this->type_ == ETHERNET_TYPE_RTL8201 && register_data.page) { + ESP_LOGD(TAG, "Select PHY Register Page 0x%02" PRIX32, 0x0); + err = mac->write_phy_reg(mac, this->phy_addr_, eth_phy_psr_reg_addr, 0x0); + ESPHL_ERROR_CHECK(err, "Select PHY Register Page 0 failed"); + } } #endif diff --git a/esphome/components/ethernet/ethernet_component.h b/esphome/components/ethernet/ethernet_component.h index e57aa5fe12..f0fe6cab87 100644 --- a/esphome/components/ethernet/ethernet_component.h +++ b/esphome/components/ethernet/ethernet_component.h @@ -35,6 +35,12 @@ struct ManualIP { network::IPAddress dns2; ///< The second DNS server. 0.0.0.0 for default. }; +struct PHYRegister { + uint32_t address; + uint32_t value; + uint32_t page; +}; + enum class EthernetComponentState { STOPPED, CONNECTING, @@ -66,6 +72,7 @@ class EthernetComponent : public Component { void set_mdc_pin(uint8_t mdc_pin); void set_mdio_pin(uint8_t mdio_pin); void set_clk_mode(emac_rmii_clock_mode_t clk_mode, emac_rmii_clock_gpio_t clk_gpio); + void add_phy_register(PHYRegister register_value); #endif void set_type(EthernetType type); void set_manual_ip(const ManualIP &manual_ip); @@ -91,8 +98,8 @@ class EthernetComponent : public Component { void dump_connect_params_(); /// @brief Set `RMII Reference Clock Select` bit for KSZ8081. void ksz8081_set_clock_reference_(esp_eth_mac_t *mac); - /// @brief Set `RMII Mode Setting Register` for RTL8201. - void rtl8201_set_rmii_mode_(esp_eth_mac_t *mac); + /// @brief Set arbitratry PHY registers from config. + void write_phy_register_(esp_eth_mac_t *mac, PHYRegister register_data); std::string use_address_; #ifdef USE_ETHERNET_SPI @@ -111,6 +118,7 @@ class EthernetComponent : public Component { uint8_t mdio_pin_{18}; emac_rmii_clock_mode_t clk_mode_{EMAC_CLK_EXT_IN}; emac_rmii_clock_gpio_t clk_gpio_{EMAC_CLK_IN_GPIO}; + std::vector phy_registers_{}; #endif EthernetType type_{ETHERNET_TYPE_UNKNOWN}; optional manual_ip_{}; From f36a96c8e20c3b593f7dc48ba9f74e2c1fafe97e Mon Sep 17 00:00:00 2001 From: svxa <59204027+svxa@users.noreply.github.com> Date: Wed, 5 Jun 2024 09:35:19 +0200 Subject: [PATCH 1546/2101] Add carrier_frequency option to remote_transmitter.transmit_aeha (#6792) --- esphome/components/remote_base/__init__.py | 14 +++++++++++++- esphome/components/remote_base/aeha_protocol.cpp | 1 - esphome/components/remote_base/aeha_protocol.h | 2 ++ .../remote_transmitter/common-buttons.yaml | 1 + tests/test1.yaml | 1 + 5 files changed, 17 insertions(+), 2 deletions(-) diff --git a/esphome/components/remote_base/__init__.py b/esphome/components/remote_base/__init__.py index 9d49026aa3..3d1c10a092 100644 --- a/esphome/components/remote_base/__init__.py +++ b/esphome/components/remote_base/__init__.py @@ -1769,7 +1769,17 @@ def aeha_dumper(var, config): pass -@register_action("aeha", AEHAAction, AEHA_SCHEMA) +@register_action( + "aeha", + AEHAAction, + AEHA_SCHEMA.extend( + { + cv.Optional(CONF_CARRIER_FREQUENCY, default="38000Hz"): cv.All( + cv.frequency, cv.int_ + ), + } + ), +) async def aeha_action(var, config, args): template_ = await cg.templatable(config[CONF_ADDRESS], args, cg.uint16) cg.add(var.set_address(template_)) @@ -1777,6 +1787,8 @@ async def aeha_action(var, config, args): config[CONF_DATA], args, cg.std_vector.template(cg.uint8) ) cg.add(var.set_data(template_)) + templ = await cg.templatable(config[CONF_CARRIER_FREQUENCY], args, cg.uint32) + cg.add(var.set_carrier_frequency(templ)) # Haier diff --git a/esphome/components/remote_base/aeha_protocol.cpp b/esphome/components/remote_base/aeha_protocol.cpp index 40bdadf634..04fe731817 100644 --- a/esphome/components/remote_base/aeha_protocol.cpp +++ b/esphome/components/remote_base/aeha_protocol.cpp @@ -16,7 +16,6 @@ static const uint16_t BIT_ZERO_LOW_US = BITWISE; static const uint16_t TRAILER = BITWISE; void AEHAProtocol::encode(RemoteTransmitData *dst, const AEHAData &data) { - dst->set_carrier_frequency(38000); dst->reserve(2 + 32 + (data.data.size() * 2) + 1); dst->item(HEADER_HIGH_US, HEADER_LOW_US); diff --git a/esphome/components/remote_base/aeha_protocol.h b/esphome/components/remote_base/aeha_protocol.h index c41f3f8df1..51718eefcb 100644 --- a/esphome/components/remote_base/aeha_protocol.h +++ b/esphome/components/remote_base/aeha_protocol.h @@ -30,12 +30,14 @@ template class AEHAAction : public RemoteTransmitterActionBase, data) + TEMPLATABLE_VALUE(uint32_t, carrier_frequency); void set_data(const std::vector &data) { data_ = data; } void encode(RemoteTransmitData *dst, Ts... x) override { AEHAData data{}; data.address = this->address_.value(x...); data.data = this->data_.value(x...); + dst->set_carrier_frequency(this->carrier_frequency_.value(x...)); AEHAProtocol().encode(dst, data); } }; diff --git a/tests/components/remote_transmitter/common-buttons.yaml b/tests/components/remote_transmitter/common-buttons.yaml index e727017e85..c6a2453b20 100644 --- a/tests/components/remote_transmitter/common-buttons.yaml +++ b/tests/components/remote_transmitter/common-buttons.yaml @@ -118,6 +118,7 @@ button: on_press: remote_transmitter.transmit_aeha: address: 0x8008 + carrier_frequency: 36700Hz data: [ 0x00, diff --git a/tests/test1.yaml b/tests/test1.yaml index 2a20a1bb45..c49ff307e5 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -2906,6 +2906,7 @@ switch: turn_on_action: remote_transmitter.transmit_aeha: address: 0x8008 + carrier_frequency: 36700Hz data: [ 0x00, From c52d5c02791850317bc9302ef86a18fec6b01dd2 Mon Sep 17 00:00:00 2001 From: Will Rouesnel Date: Wed, 5 Jun 2024 17:52:19 +1000 Subject: [PATCH 1547/2101] Add `invert_position_report` to `tuya.cover` (#6020) --- esphome/components/tuya/cover/__init__.py | 3 +++ esphome/components/tuya/cover/tuya_cover.cpp | 9 ++++++--- esphome/components/tuya/cover/tuya_cover.h | 2 ++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/esphome/components/tuya/cover/__init__.py b/esphome/components/tuya/cover/__init__.py index f886c7030f..2dd66f814d 100644 --- a/esphome/components/tuya/cover/__init__.py +++ b/esphome/components/tuya/cover/__init__.py @@ -16,6 +16,7 @@ CONF_DIRECTION_DATAPOINT = "direction_datapoint" CONF_POSITION_DATAPOINT = "position_datapoint" CONF_POSITION_REPORT_DATAPOINT = "position_report_datapoint" CONF_INVERT_POSITION = "invert_position" +CONF_INVERT_POSITION_REPORT = "invert_position_report" TuyaCover = tuya_ns.class_("TuyaCover", cover.Cover, cg.Component) @@ -47,6 +48,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_MIN_VALUE, default=0): cv.int_, cv.Optional(CONF_MAX_VALUE, default=100): cv.int_, cv.Optional(CONF_INVERT_POSITION, default=False): cv.boolean, + cv.Optional(CONF_INVERT_POSITION_REPORT, default=False): cv.boolean, cv.Optional(CONF_RESTORE_MODE, default="RESTORE"): cv.enum( RESTORE_MODES, upper=True ), @@ -71,6 +73,7 @@ async def to_code(config): cg.add(var.set_min_value(config[CONF_MIN_VALUE])) cg.add(var.set_max_value(config[CONF_MAX_VALUE])) cg.add(var.set_invert_position(config[CONF_INVERT_POSITION])) + cg.add(var.set_invert_position_report(config[CONF_INVERT_POSITION_REPORT])) cg.add(var.set_restore_mode(config[CONF_RESTORE_MODE])) paren = await cg.get_variable(config[CONF_TUYA_ID]) cg.add(var.set_tuya_parent(paren)) diff --git a/esphome/components/tuya/cover/tuya_cover.cpp b/esphome/components/tuya/cover/tuya_cover.cpp index fcb961f45e..14bf937cf7 100644 --- a/esphome/components/tuya/cover/tuya_cover.cpp +++ b/esphome/components/tuya/cover/tuya_cover.cpp @@ -51,7 +51,7 @@ void TuyaCover::setup() { return; } auto pos = float(datapoint.value_uint - this->min_value_) / this->value_range_; - this->position = 1.0f - pos; + this->position = this->invert_position_report_ ? pos : 1.0f - pos; this->publish_state(); }); } @@ -62,7 +62,7 @@ void TuyaCover::control(const cover::CoverCall &call) { this->parent_->force_set_enum_datapoint_value(*this->control_id_, COMMAND_STOP); } else { auto pos = this->position; - pos = 1.0f - pos; + pos = this->invert_position_report_ ? pos : 1.0f - pos; auto position_int = static_cast(pos * this->value_range_); position_int = position_int + this->min_value_; @@ -78,7 +78,7 @@ void TuyaCover::control(const cover::CoverCall &call) { this->parent_->force_set_enum_datapoint_value(*this->control_id_, COMMAND_CLOSE); } } else { - pos = 1.0f - pos; + pos = this->invert_position_report_ ? pos : 1.0f - pos; auto position_int = static_cast(pos * this->value_range_); position_int = position_int + this->min_value_; @@ -112,6 +112,9 @@ void TuyaCover::dump_config() { ESP_LOGCONFIG(TAG, " Configured as Inverted, but direction_datapoint isn't configured"); } } + if (this->invert_position_report_) { + ESP_LOGCONFIG(TAG, " Position Reporting Inverted"); + } if (this->control_id_.has_value()) { ESP_LOGCONFIG(TAG, " Control has datapoint ID %u", *this->control_id_); } diff --git a/esphome/components/tuya/cover/tuya_cover.h b/esphome/components/tuya/cover/tuya_cover.h index 87c72b0e66..bb5a00bc59 100644 --- a/esphome/components/tuya/cover/tuya_cover.h +++ b/esphome/components/tuya/cover/tuya_cover.h @@ -25,6 +25,7 @@ class TuyaCover : public cover::Cover, public Component { void set_min_value(uint32_t min_value) { min_value_ = min_value; } void set_max_value(uint32_t max_value) { max_value_ = max_value; } void set_invert_position(bool invert_position) { invert_position_ = invert_position; } + void set_invert_position_report(bool invert_position_report) { invert_position_report_ = invert_position_report; } void set_restore_mode(TuyaCoverRestoreMode restore_mode) { restore_mode_ = restore_mode; } protected: @@ -42,6 +43,7 @@ class TuyaCover : public cover::Cover, public Component { uint32_t max_value_; uint32_t value_range_; bool invert_position_; + bool invert_position_report_; }; } // namespace tuya From cc217d8a83a049d259b163fd01e38141373b3e9d Mon Sep 17 00:00:00 2001 From: zry98 Date: Wed, 5 Jun 2024 10:11:19 +0200 Subject: [PATCH 1548/2101] [Tuya Climate] Support both datapoint and pins for active state (#6789) --- esphome/components/tuya/climate/__init__.py | 15 ++-- .../components/tuya/climate/tuya_climate.cpp | 76 +++++++++++-------- 2 files changed, 52 insertions(+), 39 deletions(-) diff --git a/esphome/components/tuya/climate/__init__.py b/esphome/components/tuya/climate/__init__.py index 56eb377ed7..363e7c764b 100644 --- a/esphome/components/tuya/climate/__init__.py +++ b/esphome/components/tuya/climate/__init__.py @@ -189,8 +189,6 @@ CONFIG_SCHEMA = cv.All( cv.has_at_least_one_key(CONF_TARGET_TEMPERATURE_DATAPOINT, CONF_SWITCH_DATAPOINT), validate_temperature_multipliers, validate_cooling_values, - cv.has_at_most_one_key(CONF_ACTIVE_STATE, CONF_HEATING_STATE_PIN), - cv.has_at_most_one_key(CONF_ACTIVE_STATE, CONF_COOLING_STATE_PIN), ) @@ -207,6 +205,12 @@ async def to_code(config): if switch_datapoint := config.get(CONF_SWITCH_DATAPOINT): cg.add(var.set_switch_id(switch_datapoint)) + if heating_state_pin_config := config.get(CONF_HEATING_STATE_PIN): + heating_state_pin = await cg.gpio_pin_expression(heating_state_pin_config) + cg.add(var.set_heating_state_pin(heating_state_pin)) + if cooling_state_pin_config := config.get(CONF_COOLING_STATE_PIN): + cooling_state_pin = await cg.gpio_pin_expression(cooling_state_pin_config) + cg.add(var.set_cooling_state_pin(cooling_state_pin)) if active_state_config := config.get(CONF_ACTIVE_STATE): cg.add(var.set_active_state_id(active_state_config.get(CONF_DATAPOINT))) if (heating_value := active_state_config.get(CONF_HEATING_VALUE)) is not None: @@ -217,13 +221,6 @@ async def to_code(config): cg.add(var.set_active_state_drying_value(drying_value)) if (fanonly_value := active_state_config.get(CONF_FANONLY_VALUE)) is not None: cg.add(var.set_active_state_fanonly_value(fanonly_value)) - else: - if heating_state_pin_config := config.get(CONF_HEATING_STATE_PIN): - heating_state_pin = await cg.gpio_pin_expression(heating_state_pin_config) - cg.add(var.set_heating_state_pin(heating_state_pin)) - if cooling_state_pin_config := config.get(CONF_COOLING_STATE_PIN): - cooling_state_pin = await cg.gpio_pin_expression(cooling_state_pin_config) - cg.add(var.set_cooling_state_pin(cooling_state_pin)) if target_temperature_datapoint := config.get(CONF_TARGET_TEMPERATURE_DATAPOINT): cg.add(var.set_target_temperature_id(target_temperature_datapoint)) diff --git a/esphome/components/tuya/climate/tuya_climate.cpp b/esphome/components/tuya/climate/tuya_climate.cpp index 274e19a69e..7827a4e3ab 100644 --- a/esphome/components/tuya/climate/tuya_climate.cpp +++ b/esphome/components/tuya/climate/tuya_climate.cpp @@ -24,6 +24,14 @@ void TuyaClimate::setup() { this->publish_state(); }); } + if (this->heating_state_pin_ != nullptr) { + this->heating_state_pin_->setup(); + this->heating_state_ = this->heating_state_pin_->digital_read(); + } + if (this->cooling_state_pin_ != nullptr) { + this->cooling_state_pin_->setup(); + this->cooling_state_ = this->cooling_state_pin_->digital_read(); + } if (this->active_state_id_.has_value()) { this->parent_->register_listener(*this->active_state_id_, [this](const TuyaDatapoint &datapoint) { ESP_LOGV(TAG, "MCU reported active state is: %u", datapoint.value_enum); @@ -31,15 +39,6 @@ void TuyaClimate::setup() { this->compute_state_(); this->publish_state(); }); - } else { - if (this->heating_state_pin_ != nullptr) { - this->heating_state_pin_->setup(); - this->heating_state_ = this->heating_state_pin_->digital_read(); - } - if (this->cooling_state_pin_ != nullptr) { - this->cooling_state_pin_->setup(); - this->cooling_state_ = this->cooling_state_pin_->digital_read(); - } } if (this->target_temperature_id_.has_value()) { this->parent_->register_listener(*this->target_temperature_id_, [this](const TuyaDatapoint &datapoint) { @@ -113,9 +112,6 @@ void TuyaClimate::setup() { } void TuyaClimate::loop() { - if (this->active_state_id_.has_value()) - return; - bool state_changed = false; if (this->heating_state_pin_ != nullptr) { bool heating_state = this->heating_state_pin_->digital_read(); @@ -147,14 +143,18 @@ void TuyaClimate::control(const climate::ClimateCall &call) { this->parent_->set_boolean_datapoint_value(*this->switch_id_, switch_state); const climate::ClimateMode new_mode = *call.get_mode(); - if (new_mode == climate::CLIMATE_MODE_HEAT && this->supports_heat_) { - this->parent_->set_enum_datapoint_value(*this->active_state_id_, *this->active_state_heating_value_); - } else if (new_mode == climate::CLIMATE_MODE_COOL && this->supports_cool_) { - this->parent_->set_enum_datapoint_value(*this->active_state_id_, *this->active_state_cooling_value_); - } else if (new_mode == climate::CLIMATE_MODE_DRY && this->active_state_drying_value_.has_value()) { - this->parent_->set_enum_datapoint_value(*this->active_state_id_, *this->active_state_drying_value_); - } else if (new_mode == climate::CLIMATE_MODE_FAN_ONLY && this->active_state_fanonly_value_.has_value()) { - this->parent_->set_enum_datapoint_value(*this->active_state_id_, *this->active_state_fanonly_value_); + if (this->active_state_id_.has_value()) { + if (new_mode == climate::CLIMATE_MODE_HEAT && this->supports_heat_) { + this->parent_->set_enum_datapoint_value(*this->active_state_id_, *this->active_state_heating_value_); + } else if (new_mode == climate::CLIMATE_MODE_COOL && this->supports_cool_) { + this->parent_->set_enum_datapoint_value(*this->active_state_id_, *this->active_state_cooling_value_); + } else if (new_mode == climate::CLIMATE_MODE_DRY && this->active_state_drying_value_.has_value()) { + this->parent_->set_enum_datapoint_value(*this->active_state_id_, *this->active_state_drying_value_); + } else if (new_mode == climate::CLIMATE_MODE_FAN_ONLY && this->active_state_fanonly_value_.has_value()) { + this->parent_->set_enum_datapoint_value(*this->active_state_id_, *this->active_state_fanonly_value_); + } + } else { + ESP_LOGW(TAG, "Active state (mode) datapoint not configured"); } } @@ -422,7 +422,32 @@ void TuyaClimate::compute_state_() { } climate::ClimateAction target_action = climate::CLIMATE_ACTION_IDLE; - if (this->active_state_id_.has_value()) { + if (this->heating_state_pin_ != nullptr || this->cooling_state_pin_ != nullptr) { + // Use state from input pins + if (this->heating_state_) { + target_action = climate::CLIMATE_ACTION_HEATING; + this->mode = climate::CLIMATE_MODE_HEAT; + } else if (this->cooling_state_) { + target_action = climate::CLIMATE_ACTION_COOLING; + this->mode = climate::CLIMATE_MODE_COOL; + } + if (this->active_state_id_.has_value()) { + // Both are available, use MCU datapoint as mode + if (this->supports_heat_ && this->active_state_heating_value_.has_value() && + this->active_state_ == this->active_state_heating_value_) { + this->mode = climate::CLIMATE_MODE_HEAT; + } else if (this->supports_cool_ && this->active_state_cooling_value_.has_value() && + this->active_state_ == this->active_state_cooling_value_) { + this->mode = climate::CLIMATE_MODE_COOL; + } else if (this->active_state_drying_value_.has_value() && + this->active_state_ == this->active_state_drying_value_) { + this->mode = climate::CLIMATE_MODE_DRY; + } else if (this->active_state_fanonly_value_.has_value() && + this->active_state_ == this->active_state_fanonly_value_) { + this->mode = climate::CLIMATE_MODE_FAN_ONLY; + } + } + } else if (this->active_state_id_.has_value()) { // Use state from MCU datapoint if (this->supports_heat_ && this->active_state_heating_value_.has_value() && this->active_state_ == this->active_state_heating_value_) { @@ -441,15 +466,6 @@ void TuyaClimate::compute_state_() { target_action = climate::CLIMATE_ACTION_FAN; this->mode = climate::CLIMATE_MODE_FAN_ONLY; } - } else if (this->heating_state_pin_ != nullptr || this->cooling_state_pin_ != nullptr) { - // Use state from input pins - if (this->heating_state_) { - target_action = climate::CLIMATE_ACTION_HEATING; - this->mode = climate::CLIMATE_MODE_HEAT; - } else if (this->cooling_state_) { - target_action = climate::CLIMATE_ACTION_COOLING; - this->mode = climate::CLIMATE_MODE_COOL; - } } else { // Fallback to active state calc based on temp and hysteresis const float temp_diff = this->target_temperature - this->current_temperature; From 7143e9cd9e2073351cfd239e242e2132a36eec0b Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Thu, 6 Jun 2024 05:27:06 +1000 Subject: [PATCH 1549/2101] [config] Allow file: scheme for git external components (#6844) --- esphome/config_validation.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/config_validation.py b/esphome/config_validation.py index 5fc72921e1..7259e3c062 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -1949,13 +1949,13 @@ def url(value): except ValueError as e: raise Invalid("Not a valid URL") from e - if not parsed.scheme or not parsed.netloc: - raise Invalid("Expected a URL scheme and host") - return parsed.geturl() + if parsed.scheme and parsed.netloc or parsed.scheme == "file": + return parsed.geturl() + raise Invalid("Expected a file scheme or a URL scheme with host") def git_ref(value): - if re.match(r"[a-zA-Z0-9\-_.\./]+", value) is None: + if re.match(r"[a-zA-Z0-9_./-]+", value) is None: raise Invalid("Not a valid git ref") return value From 8ef4aaa70eac95656f2742b7e57d1010cfb235b5 Mon Sep 17 00:00:00 2001 From: Olivier ARCHER Date: Thu, 6 Jun 2024 04:35:28 +0200 Subject: [PATCH 1550/2101] [ota] http_request update platform (#5586) Co-authored-by: Keith Burzinski Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Co-authored-by: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> --- CODEOWNERS | 1 + .../components/http_request/ota/__init__.py | 189 +++++++++++ .../components/http_request/ota/automation.h | 42 +++ .../http_request/ota/ota_http_request.cpp | 293 ++++++++++++++++++ .../http_request/ota/ota_http_request.h | 72 +++++ .../ota/ota_http_request_arduino.cpp | 134 ++++++++ .../ota/ota_http_request_arduino.h | 42 +++ .../http_request/ota/ota_http_request_idf.cpp | 86 +++++ .../http_request/ota/ota_http_request_idf.h | 24 ++ .../components/http_request/ota/watchdog.cpp | 71 +++++ .../components/http_request/ota/watchdog.h | 27 ++ esphome/core/defines.h | 1 + .../{common.yaml => common_http_request.yaml} | 4 - tests/components/http_request/common_ota.yaml | 36 +++ .../http_request/test-nossl.esp8266.yaml | 38 +++ .../http_request/test.esp32-c3-idf.yaml | 4 + .../http_request/test.esp32-c3.yaml | 7 +- .../http_request/test.esp32-idf.yaml | 4 + tests/components/http_request/test.esp32.yaml | 7 +- .../components/http_request/test.esp8266.yaml | 7 +- .../components/http_request/test.rp2040.yaml | 4 + 21 files changed, 1083 insertions(+), 10 deletions(-) create mode 100644 esphome/components/http_request/ota/__init__.py create mode 100644 esphome/components/http_request/ota/automation.h create mode 100644 esphome/components/http_request/ota/ota_http_request.cpp create mode 100644 esphome/components/http_request/ota/ota_http_request.h create mode 100644 esphome/components/http_request/ota/ota_http_request_arduino.cpp create mode 100644 esphome/components/http_request/ota/ota_http_request_arduino.h create mode 100644 esphome/components/http_request/ota/ota_http_request_idf.cpp create mode 100644 esphome/components/http_request/ota/ota_http_request_idf.h create mode 100644 esphome/components/http_request/ota/watchdog.cpp create mode 100644 esphome/components/http_request/ota/watchdog.h rename tests/components/http_request/{common.yaml => common_http_request.yaml} (95%) create mode 100644 tests/components/http_request/common_ota.yaml create mode 100644 tests/components/http_request/test-nossl.esp8266.yaml create mode 100644 tests/components/http_request/test.esp32-c3-idf.yaml create mode 100644 tests/components/http_request/test.esp32-idf.yaml create mode 100644 tests/components/http_request/test.rp2040.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 82f61c3b80..90574ca9ba 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -171,6 +171,7 @@ esphome/components/host/* @clydebarrow @esphome/core esphome/components/host/time/* @clydebarrow esphome/components/hrxl_maxsonar_wr/* @netmikey esphome/components/hte501/* @Stock-M +esphome/components/http_request/ota/* @oarcher esphome/components/htu31d/* @betterengineering esphome/components/hydreon_rgxx/* @functionpointer esphome/components/hyt271/* @Philippe12 diff --git a/esphome/components/http_request/ota/__init__.py b/esphome/components/http_request/ota/__init__.py new file mode 100644 index 0000000000..6a56fac83a --- /dev/null +++ b/esphome/components/http_request/ota/__init__.py @@ -0,0 +1,189 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome import automation +from esphome.const import ( + CONF_ESP8266_DISABLE_SSL_SUPPORT, + CONF_ID, + CONF_PASSWORD, + CONF_TIMEOUT, + CONF_URL, + CONF_USERNAME, +) +from esphome.components import esp32 +from esphome.components.ota import BASE_OTA_SCHEMA, ota_to_code, OTAComponent +from esphome.core import CORE, coroutine_with_priority +from .. import http_request_ns + +CODEOWNERS = ["@oarcher"] + +AUTO_LOAD = ["md5"] +DEPENDENCIES = ["network"] + +CONF_MD5 = "md5" +CONF_MD5_URL = "md5_url" +CONF_VERIFY_SSL = "verify_ssl" +CONF_WATCHDOG_TIMEOUT = "watchdog_timeout" + +OtaHttpRequestComponent = http_request_ns.class_( + "OtaHttpRequestComponent", OTAComponent +) +OtaHttpRequestComponentArduino = http_request_ns.class_( + "OtaHttpRequestComponentArduino", OtaHttpRequestComponent +) +OtaHttpRequestComponentIDF = http_request_ns.class_( + "OtaHttpRequestComponentIDF", OtaHttpRequestComponent +) +OtaHttpRequestComponentFlashAction = http_request_ns.class_( + "OtaHttpRequestComponentFlashAction", automation.Action +) + + +def validate_ssl_verification(config): + error_message = "" + + if CORE.is_esp32: + if not CORE.using_esp_idf and config[CONF_VERIFY_SSL]: + error_message = "ESPHome supports certificate verification only via ESP-IDF" + + if CORE.is_rp2040 and config[CONF_VERIFY_SSL]: + error_message = "ESPHome does not support certificate verification in Arduino" + + if ( + CORE.is_esp8266 + and not config[CONF_ESP8266_DISABLE_SSL_SUPPORT] + and config[CONF_VERIFY_SSL] + ): + error_message = "ESPHome does not support certificate verification in Arduino" + + if len(error_message) > 0: + raise cv.Invalid( + f"{error_message}. Set '{CONF_VERIFY_SSL}: false' to skip certificate validation and allow less secure HTTPS connections." + ) + + return config + + +def _declare_request_class(value): + if CORE.using_esp_idf: + return cv.declare_id(OtaHttpRequestComponentIDF)(value) + + if CORE.is_esp8266 or CORE.is_esp32 or CORE.is_rp2040: + return cv.declare_id(OtaHttpRequestComponentArduino)(value) + return NotImplementedError + + +CONFIG_SCHEMA = cv.All( + cv.Schema( + { + cv.GenerateID(): _declare_request_class, + cv.SplitDefault(CONF_ESP8266_DISABLE_SSL_SUPPORT, esp8266=False): cv.All( + cv.only_on_esp8266, cv.boolean + ), + cv.Optional(CONF_VERIFY_SSL, default=True): cv.boolean, + cv.Optional( + CONF_TIMEOUT, default="5min" + ): cv.positive_time_period_milliseconds, + cv.Optional(CONF_WATCHDOG_TIMEOUT): cv.All( + cv.Any(cv.only_on_esp32, cv.only_on_rp2040), + cv.positive_not_null_time_period, + cv.positive_time_period_milliseconds, + ), + } + ) + .extend(BASE_OTA_SCHEMA) + .extend(cv.COMPONENT_SCHEMA), + cv.require_framework_version( + esp8266_arduino=cv.Version(2, 5, 1), + esp32_arduino=cv.Version(0, 0, 0), + esp_idf=cv.Version(0, 0, 0), + rp2040_arduino=cv.Version(0, 0, 0), + ), + validate_ssl_verification, +) + + +@coroutine_with_priority(52.0) +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + await ota_to_code(var, config) + + cg.add(var.set_timeout(config[CONF_TIMEOUT])) + + if timeout_ms := config.get(CONF_WATCHDOG_TIMEOUT): + cg.add_define( + "USE_HTTP_REQUEST_OTA_WATCHDOG_TIMEOUT", + timeout_ms, + ) + + if CORE.is_esp8266 and not config[CONF_ESP8266_DISABLE_SSL_SUPPORT]: + cg.add_define("USE_HTTP_REQUEST_ESP8266_HTTPS") + + if CORE.is_esp32: + if CORE.using_esp_idf: + esp32.add_idf_sdkconfig_option( + "CONFIG_MBEDTLS_CERTIFICATE_BUNDLE", + config.get(CONF_VERIFY_SSL), + ) + esp32.add_idf_sdkconfig_option( + "CONFIG_ESP_TLS_INSECURE", + not config.get(CONF_VERIFY_SSL), + ) + esp32.add_idf_sdkconfig_option( + "CONFIG_ESP_TLS_SKIP_SERVER_CERT_VERIFY", + not config.get(CONF_VERIFY_SSL), + ) + else: + cg.add_library("WiFiClientSecure", None) + cg.add_library("HTTPClient", None) + if CORE.is_esp8266: + cg.add_library("ESP8266HTTPClient", None) + if CORE.is_rp2040 and CORE.using_arduino: + cg.add_library("HTTPClient", None) + + await cg.register_component(var, config) + + +OTA_HTTP_REQUEST_FLASH_ACTION_SCHEMA = cv.All( + cv.Schema( + { + cv.GenerateID(): cv.use_id(OtaHttpRequestComponent), + cv.Optional(CONF_MD5_URL): cv.templatable(cv.url), + cv.Optional(CONF_MD5): cv.templatable(cv.string), + cv.Optional(CONF_PASSWORD): cv.templatable(cv.string), + cv.Optional(CONF_USERNAME): cv.templatable(cv.string), + cv.Required(CONF_URL): cv.templatable(cv.url), + } + ), + cv.has_exactly_one_key(CONF_MD5, CONF_MD5_URL), +) + + +@automation.register_action( + "ota_http_request.flash", + OtaHttpRequestComponentFlashAction, + OTA_HTTP_REQUEST_FLASH_ACTION_SCHEMA, +) +async def ota_http_request_action_to_code(config, action_id, template_arg, args): + paren = await cg.get_variable(config[CONF_ID]) + var = cg.new_Pvariable(action_id, template_arg, paren) + + if md5_url := config.get(CONF_MD5_URL): + template_ = await cg.templatable(md5_url, args, cg.std_string) + cg.add(var.set_md5_url(template_)) + + if md5_str := config.get(CONF_MD5): + template_ = await cg.templatable(md5_str, args, cg.std_string) + cg.add(var.set_md5(template_)) + + if password_str := config.get(CONF_PASSWORD): + template_ = await cg.templatable(password_str, args, cg.std_string) + cg.add(var.set_password(template_)) + + if username_str := config.get(CONF_USERNAME): + template_ = await cg.templatable(username_str, args, cg.std_string) + cg.add(var.set_username(template_)) + + template_ = await cg.templatable(config[CONF_URL], args, cg.std_string) + cg.add(var.set_url(template_)) + + return var diff --git a/esphome/components/http_request/ota/automation.h b/esphome/components/http_request/ota/automation.h new file mode 100644 index 0000000000..d4c21f1c72 --- /dev/null +++ b/esphome/components/http_request/ota/automation.h @@ -0,0 +1,42 @@ +#pragma once +#include "ota_http_request.h" + +#include "esphome/core/automation.h" + +namespace esphome { +namespace http_request { + +template class OtaHttpRequestComponentFlashAction : public Action { + public: + OtaHttpRequestComponentFlashAction(OtaHttpRequestComponent *parent) : parent_(parent) {} + TEMPLATABLE_VALUE(std::string, md5_url) + TEMPLATABLE_VALUE(std::string, md5) + TEMPLATABLE_VALUE(std::string, password) + TEMPLATABLE_VALUE(std::string, url) + TEMPLATABLE_VALUE(std::string, username) + + void play(Ts... x) override { + if (this->md5_url_.has_value()) { + this->parent_->set_md5_url(this->md5_url_.value(x...)); + } + if (this->md5_.has_value()) { + this->parent_->set_md5(this->md5_.value(x...)); + } + if (this->password_.has_value()) { + this->parent_->set_password(this->password_.value(x...)); + } + if (this->username_.has_value()) { + this->parent_->set_username(this->username_.value(x...)); + } + this->parent_->set_url(this->url_.value(x...)); + + this->parent_->flash(); + // Normally never reached due to reboot + } + + protected: + OtaHttpRequestComponent *parent_; +}; + +} // namespace http_request +} // namespace esphome diff --git a/esphome/components/http_request/ota/ota_http_request.cpp b/esphome/components/http_request/ota/ota_http_request.cpp new file mode 100644 index 0000000000..cf0816c858 --- /dev/null +++ b/esphome/components/http_request/ota/ota_http_request.cpp @@ -0,0 +1,293 @@ +#include "ota_http_request.h" +#include "watchdog.h" + +#include "esphome/core/application.h" +#include "esphome/core/defines.h" +#include "esphome/core/log.h" + +#include "esphome/components/md5/md5.h" +#include "esphome/components/ota/ota_backend_arduino_esp32.h" +#include "esphome/components/ota/ota_backend_arduino_esp8266.h" +#include "esphome/components/ota/ota_backend_arduino_rp2040.h" +#include "esphome/components/ota/ota_backend_esp_idf.h" +#include "esphome/components/ota/ota_backend.h" + +namespace esphome { +namespace http_request { + +void OtaHttpRequestComponent::setup() { +#ifdef USE_OTA_STATE_CALLBACK + ota::register_ota_platform(this); +#endif +} + +void OtaHttpRequestComponent::dump_config() { + ESP_LOGCONFIG(TAG, "Over-The-Air updates via HTTP request:"); + ESP_LOGCONFIG(TAG, " Timeout: %llus", this->timeout_ / 1000); +#ifdef USE_ESP8266 +#ifdef USE_HTTP_REQUEST_ESP8266_HTTPS + ESP_LOGCONFIG(TAG, " ESP8266 SSL support: No"); +#else + ESP_LOGCONFIG(TAG, " ESP8266 SSL support: Yes"); +#endif +#endif +#ifdef CONFIG_MBEDTLS_CERTIFICATE_BUNDLE + ESP_LOGCONFIG(TAG, " TLS server verification: Yes"); +#else + ESP_LOGCONFIG(TAG, " TLS server verification: No"); +#endif +#ifdef USE_HTTP_REQUEST_OTA_WATCHDOG_TIMEOUT + ESP_LOGCONFIG(TAG, " Watchdog timeout: %ds", USE_HTTP_REQUEST_OTA_WATCHDOG_TIMEOUT / 1000); +#endif +}; + +void OtaHttpRequestComponent::set_md5_url(const std::string &url) { + if (!this->validate_url_(url)) { + this->md5_url_.clear(); // URL was not valid; prevent flashing until it is + return; + } + this->md5_url_ = url; + this->md5_expected_.clear(); // to be retrieved later +} + +void OtaHttpRequestComponent::set_url(const std::string &url) { + if (!this->validate_url_(url)) { + this->url_.clear(); // URL was not valid; prevent flashing until it is + return; + } + this->url_ = url; +} + +bool OtaHttpRequestComponent::check_status() { + // status can be -1, or HTTP status code + if (this->status_ < 100) { + ESP_LOGE(TAG, "HTTP server did not respond (error %d)", this->status_); + return false; + } + if (this->status_ >= 310) { + ESP_LOGE(TAG, "HTTP error %d", this->status_); + return false; + } + ESP_LOGV(TAG, "HTTP status %d", this->status_); + return true; +} + +void OtaHttpRequestComponent::flash() { + if (this->url_.empty()) { + ESP_LOGE(TAG, "URL not set; cannot start update"); + return; + } + + ESP_LOGI(TAG, "Starting update..."); +#ifdef USE_OTA_STATE_CALLBACK + this->state_callback_.call(ota::OTA_STARTED, 0.0f, 0); +#endif + + auto ota_status = this->do_ota_(); + + switch (ota_status) { + case ota::OTA_RESPONSE_OK: +#ifdef USE_OTA_STATE_CALLBACK + this->state_callback_.call(ota::OTA_COMPLETED, 100.0f, ota_status); +#endif + delay(10); + App.safe_reboot(); + break; + + default: +#ifdef USE_OTA_STATE_CALLBACK + this->state_callback_.call(ota::OTA_ERROR, 0.0f, ota_status); +#endif + this->md5_computed_.clear(); // will be reset at next attempt + this->md5_expected_.clear(); // will be reset at next attempt + break; + } +} + +void OtaHttpRequestComponent::cleanup_(std::unique_ptr backend) { + if (this->update_started_) { + ESP_LOGV(TAG, "Aborting OTA backend"); + backend->abort(); + } + ESP_LOGV(TAG, "Aborting HTTP connection"); + this->http_end(); +}; + +uint8_t OtaHttpRequestComponent::do_ota_() { + uint8_t buf[this->http_recv_buffer_ + 1]; + uint32_t last_progress = 0; + uint32_t update_start_time = millis(); + md5::MD5Digest md5_receive; + std::unique_ptr md5_receive_str(new char[33]); + + if (this->md5_expected_.empty() && !this->http_get_md5_()) { + return OTA_MD5_INVALID; + } + + ESP_LOGD(TAG, "MD5 expected: %s", this->md5_expected_.c_str()); + + auto url_with_auth = this->get_url_with_auth_(this->url_); + if (url_with_auth.empty()) { + return OTA_BAD_URL; + } + ESP_LOGVV(TAG, "url_with_auth: %s", url_with_auth.c_str()); + ESP_LOGI(TAG, "Connecting to: %s", this->url_.c_str()); + this->http_init(url_with_auth); + if (!this->check_status()) { + this->http_end(); + return OTA_CONNECTION_ERROR; + } + + // we will compute MD5 on the fly for verification -- Arduino OTA seems to ignore it + md5_receive.init(); + ESP_LOGV(TAG, "MD5Digest initialized"); + + ESP_LOGV(TAG, "OTA backend begin"); + auto backend = ota::make_ota_backend(); + auto error_code = backend->begin(this->body_length_); + if (error_code != ota::OTA_RESPONSE_OK) { + ESP_LOGW(TAG, "backend->begin error: %d", error_code); + this->cleanup_(std::move(backend)); + return error_code; + } + + this->bytes_read_ = 0; + while (this->bytes_read_ < this->body_length_) { + // read a maximum of chunk_size bytes into buf. (real read size returned) + int bufsize = this->http_read(buf, this->http_recv_buffer_); + ESP_LOGVV(TAG, "bytes_read_ = %u, body_length_ = %u, bufsize = %i", this->bytes_read_, this->body_length_, bufsize); + + // feed watchdog and give other tasks a chance to run + App.feed_wdt(); + yield(); + + if (bufsize < 0) { + ESP_LOGE(TAG, "Stream closed"); + this->cleanup_(std::move(backend)); + return OTA_CONNECTION_ERROR; + } else if (bufsize > 0 && bufsize <= this->http_recv_buffer_) { + // add read bytes to MD5 + md5_receive.add(buf, bufsize); + + // write bytes to OTA backend + this->update_started_ = true; + error_code = backend->write(buf, bufsize); + if (error_code != ota::OTA_RESPONSE_OK) { + // error code explanation available at + // https://github.com/esphome/esphome/blob/dev/esphome/components/ota/ota_backend.h + ESP_LOGE(TAG, "Error code (%02X) writing binary data to flash at offset %d and size %d", error_code, + this->bytes_read_ - bufsize, this->body_length_); + this->cleanup_(std::move(backend)); + return error_code; + } + } + + uint32_t now = millis(); + if ((now - last_progress > 1000) or (this->bytes_read_ == this->body_length_)) { + last_progress = now; + float percentage = this->bytes_read_ * 100.0f / this->body_length_; + ESP_LOGD(TAG, "Progress: %0.1f%%", percentage); +#ifdef USE_OTA_STATE_CALLBACK + this->state_callback_.call(ota::OTA_IN_PROGRESS, percentage, 0); +#endif + } + } // while + + ESP_LOGI(TAG, "Done in %.0f seconds", float(millis() - update_start_time) / 1000); + + // verify MD5 is as expected and act accordingly + md5_receive.calculate(); + md5_receive.get_hex(md5_receive_str.get()); + this->md5_computed_ = md5_receive_str.get(); + if (strncmp(this->md5_computed_.c_str(), this->md5_expected_.c_str(), MD5_SIZE) != 0) { + ESP_LOGE(TAG, "MD5 computed: %s - Aborting due to MD5 mismatch", this->md5_computed_.c_str()); + this->cleanup_(std::move(backend)); + return ota::OTA_RESPONSE_ERROR_MD5_MISMATCH; + } else { + backend->set_update_md5(md5_receive_str.get()); + } + + this->http_end(); + + // feed watchdog and give other tasks a chance to run + App.feed_wdt(); + yield(); + delay(100); // NOLINT + + error_code = backend->end(); + if (error_code != ota::OTA_RESPONSE_OK) { + ESP_LOGW(TAG, "Error ending update! error_code: %d", error_code); + this->cleanup_(std::move(backend)); + return error_code; + } + + ESP_LOGI(TAG, "Update complete"); + return ota::OTA_RESPONSE_OK; +} + +std::string OtaHttpRequestComponent::get_url_with_auth_(const std::string &url) { + if (this->username_.empty() || this->password_.empty()) { + return url; + } + + auto start_char = url.find("://"); + if ((start_char == std::string::npos) || (start_char < 4)) { + ESP_LOGE(TAG, "Incorrect URL prefix"); + return {}; + } + + ESP_LOGD(TAG, "Using basic HTTP authentication"); + + start_char += 3; // skip '://' characters + auto url_with_auth = + url.substr(0, start_char) + this->username_ + ":" + this->password_ + "@" + url.substr(start_char); + return url_with_auth; +} + +bool OtaHttpRequestComponent::http_get_md5_() { + if (this->md5_url_.empty()) { + return false; + } + + auto url_with_auth = this->get_url_with_auth_(this->md5_url_); + if (url_with_auth.empty()) { + return false; + } + + ESP_LOGVV(TAG, "url_with_auth: %s", url_with_auth.c_str()); + ESP_LOGI(TAG, "Connecting to: %s", this->md5_url_.c_str()); + this->http_init(url_with_auth); + if (!this->check_status()) { + this->http_end(); + return false; + } + int length = this->body_length_; + if (length < 0) { + this->http_end(); + return false; + } + if (length < MD5_SIZE) { + ESP_LOGE(TAG, "MD5 file must be %u bytes; %u bytes reported by HTTP server. Aborting", MD5_SIZE, + this->body_length_); + this->http_end(); + return false; + } + + this->bytes_read_ = 0; + this->md5_expected_.resize(MD5_SIZE); + auto read_len = this->http_read((uint8_t *) this->md5_expected_.data(), MD5_SIZE); + this->http_end(); + + return read_len == MD5_SIZE; +} + +bool OtaHttpRequestComponent::validate_url_(const std::string &url) { + if ((url.length() < 8) || (url.find("http") != 0) || (url.find("://") == std::string::npos)) { + ESP_LOGE(TAG, "URL is invalid and/or must be prefixed with 'http://' or 'https://'"); + return false; + } + return true; +} + +} // namespace http_request +} // namespace esphome diff --git a/esphome/components/http_request/ota/ota_http_request.h b/esphome/components/http_request/ota/ota_http_request.h new file mode 100644 index 0000000000..9fbdf2ec25 --- /dev/null +++ b/esphome/components/http_request/ota/ota_http_request.h @@ -0,0 +1,72 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/core/defines.h" +#include "esphome/components/ota/ota_backend.h" + +#include +#include +#include + +namespace esphome { +namespace http_request { + +static const char *const TAG = "http_request.ota"; +static const uint8_t MD5_SIZE = 32; + +enum OtaHttpRequestError : uint8_t { + OTA_MD5_INVALID = 0x10, + OTA_BAD_URL = 0x11, + OTA_CONNECTION_ERROR = 0x12, +}; + +class OtaHttpRequestComponent : public ota::OTAComponent { + public: + void setup() override; + void dump_config() override; + float get_setup_priority() const override { return setup_priority::AFTER_WIFI; } + + void set_md5_url(const std::string &md5_url); + void set_md5(const std::string &md5) { this->md5_expected_ = md5; } + void set_password(const std::string &password) { this->password_ = password; } + void set_timeout(const uint64_t timeout) { this->timeout_ = timeout; } + void set_url(const std::string &url); + void set_username(const std::string &username) { this->username_ = username; } + + std::string md5_computed() { return this->md5_computed_; } + std::string md5_expected() { return this->md5_expected_; } + + bool check_status(); + + void flash(); + + virtual void http_init(const std::string &url){}; + virtual int http_read(uint8_t *buf, size_t len) { return 0; }; + virtual void http_end(){}; + + protected: + void cleanup_(std::unique_ptr backend); + uint8_t do_ota_(); + std::string get_url_with_auth_(const std::string &url); + bool http_get_md5_(); + bool secure_() { return this->url_.find("https:") != std::string::npos; }; + bool validate_url_(const std::string &url); + + std::string md5_computed_{}; + std::string md5_expected_{}; + std::string md5_url_{}; + std::string password_{}; + std::string username_{}; + std::string url_{}; + size_t body_length_ = 0; + size_t bytes_read_ = 0; + int status_ = -1; + uint64_t timeout_ = 0; + bool update_started_ = false; + const uint16_t http_recv_buffer_ = 256; // the firmware GET chunk size + const uint16_t max_http_recv_buffer_ = 512; // internal max http buffer size must be > HTTP_RECV_BUFFER_ (TLS + // overhead) and must be a power of two from 512 to 4096 +}; + +} // namespace http_request +} // namespace esphome diff --git a/esphome/components/http_request/ota/ota_http_request_arduino.cpp b/esphome/components/http_request/ota/ota_http_request_arduino.cpp new file mode 100644 index 0000000000..d1dc638d5e --- /dev/null +++ b/esphome/components/http_request/ota/ota_http_request_arduino.cpp @@ -0,0 +1,134 @@ +#include "ota_http_request.h" +#include "watchdog.h" + +#ifdef USE_ARDUINO +#include "ota_http_request_arduino.h" +#include "esphome/core/defines.h" +#include "esphome/core/log.h" +#include "esphome/core/application.h" +#include "esphome/components/network/util.h" +#include "esphome/components/md5/md5.h" + +namespace esphome { +namespace http_request { + +struct Header { + const char *name; + const char *value; +}; + +void OtaHttpRequestComponentArduino::http_init(const std::string &url) { + const char *header_keys[] = {"Content-Length", "Content-Type"}; + const size_t header_count = sizeof(header_keys) / sizeof(header_keys[0]); + watchdog::WatchdogManager wdts; + +#ifdef USE_ESP8266 + if (this->stream_ptr_ == nullptr && this->set_stream_ptr_()) { + ESP_LOGE(TAG, "Unable to set client"); + return; + } +#endif // USE_ESP8266 + +#ifdef USE_RP2040 + this->client_.setInsecure(); +#endif + + App.feed_wdt(); + +#if defined(USE_ESP32) || defined(USE_RP2040) + this->status_ = this->client_.begin(url.c_str()); +#endif +#ifdef USE_ESP8266 + this->client_.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); + this->status_ = this->client_.begin(*this->stream_ptr_, url.c_str()); +#endif + + if (!this->status_) { + this->client_.end(); + return; + } + + this->client_.setReuse(true); + + // returned needed headers must be collected before the requests + this->client_.collectHeaders(header_keys, header_count); + + // HTTP GET + this->status_ = this->client_.GET(); + + this->body_length_ = (size_t) this->client_.getSize(); + +#if defined(USE_ESP32) || defined(USE_RP2040) + if (this->stream_ptr_ == nullptr) { + this->set_stream_ptr_(); + } +#endif +} + +int OtaHttpRequestComponentArduino::http_read(uint8_t *buf, const size_t max_len) { +#ifdef USE_ESP8266 +#if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(3, 1, 0) // && USE_ARDUINO_VERSION_CODE < VERSION_CODE(?, ?, ?) + if (!this->secure_()) { + ESP_LOGW(TAG, "Using HTTP on Arduino version >= 3.1 is **very** slow. Consider setting framework version to 3.0.2 " + "in your YAML, or use HTTPS"); + } +#endif // USE_ARDUINO_VERSION_CODE +#endif // USE_ESP8266 + + watchdog::WatchdogManager wdts; + + // Since arduino8266 >= 3.1 using this->stream_ptr_ is broken (https://github.com/esp8266/Arduino/issues/9035) + WiFiClient *stream_ptr = this->client_.getStreamPtr(); + if (stream_ptr == nullptr) { + ESP_LOGE(TAG, "Stream pointer vanished!"); + return -1; + } + + int available_data = stream_ptr->available(); + int bufsize = std::min((int) max_len, available_data); + if (bufsize > 0) { + stream_ptr->readBytes(buf, bufsize); + this->bytes_read_ += bufsize; + buf[bufsize] = '\0'; // not fed to ota + } + + return bufsize; +} + +void OtaHttpRequestComponentArduino::http_end() { + watchdog::WatchdogManager wdts; + this->client_.end(); +} + +int OtaHttpRequestComponentArduino::set_stream_ptr_() { +#ifdef USE_ESP8266 +#ifdef USE_HTTP_REQUEST_ESP8266_HTTPS + if (this->secure_()) { + ESP_LOGV(TAG, "ESP8266 HTTPS connection with WiFiClientSecure"); + this->stream_ptr_ = std::make_unique(); + WiFiClientSecure *secure_client = static_cast(this->stream_ptr_.get()); + secure_client->setBufferSizes(this->max_http_recv_buffer_, 512); + secure_client->setInsecure(); + } else { + this->stream_ptr_ = std::make_unique(); + } +#else + ESP_LOGV(TAG, "ESP8266 HTTP connection with WiFiClient"); + if (this->secure_()) { + ESP_LOGE(TAG, "Can't use HTTPS connection with esp8266_disable_ssl_support"); + return -1; + } + this->stream_ptr_ = std::make_unique(); +#endif // USE_HTTP_REQUEST_ESP8266_HTTPS +#endif // USE_ESP8266 + +#if defined(USE_ESP32) || defined(USE_RP2040) + this->stream_ptr_ = std::unique_ptr(this->client_.getStreamPtr()); +#endif + return 0; +} + +} // namespace http_request +} // namespace esphome + +#endif // USE_ARDUINO diff --git a/esphome/components/http_request/ota/ota_http_request_arduino.h b/esphome/components/http_request/ota/ota_http_request_arduino.h new file mode 100644 index 0000000000..02bc046520 --- /dev/null +++ b/esphome/components/http_request/ota/ota_http_request_arduino.h @@ -0,0 +1,42 @@ +#pragma once + +#include "ota_http_request.h" + +#ifdef USE_ARDUINO +#include "esphome/core/automation.h" +#include "esphome/core/component.h" +#include "esphome/core/defines.h" + +#include +#include +#include + +#if defined(USE_ESP32) || defined(USE_RP2040) +#include +#endif +#ifdef USE_ESP8266 +#include +#ifdef USE_HTTP_REQUEST_ESP8266_HTTPS +#include +#endif +#endif + +namespace esphome { +namespace http_request { + +class OtaHttpRequestComponentArduino : public OtaHttpRequestComponent { + public: + void http_init(const std::string &url) override; + int http_read(uint8_t *buf, size_t len) override; + void http_end() override; + + protected: + int set_stream_ptr_(); + HTTPClient client_{}; + std::unique_ptr stream_ptr_; +}; + +} // namespace http_request +} // namespace esphome + +#endif // USE_ARDUINO diff --git a/esphome/components/http_request/ota/ota_http_request_idf.cpp b/esphome/components/http_request/ota/ota_http_request_idf.cpp new file mode 100644 index 0000000000..9fa565d9bb --- /dev/null +++ b/esphome/components/http_request/ota/ota_http_request_idf.cpp @@ -0,0 +1,86 @@ +#include "ota_http_request_idf.h" +#include "watchdog.h" + +#ifdef USE_ESP_IDF +#include "esphome/core/application.h" +#include "esphome/core/defines.h" +#include "esphome/core/log.h" +#include "esphome/components/md5/md5.h" +#include "esphome/components/network/util.h" + +#include "esp_event.h" +#include "esp_http_client.h" +#include "esp_idf_version.h" +#include "esp_log.h" +#include "esp_netif.h" +#include "esp_system.h" +#include "esp_task_wdt.h" +#include "esp_tls.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "nvs_flash.h" + +#include +#include +#include +#include +#include +#if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE +#include "esp_crt_bundle.h" +#endif + +namespace esphome { +namespace http_request { + +void OtaHttpRequestComponentIDF::http_init(const std::string &url) { + App.feed_wdt(); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmissing-field-initializers" + esp_http_client_config_t config = {nullptr}; + config.url = url.c_str(); + config.method = HTTP_METHOD_GET; + config.timeout_ms = (int) this->timeout_; + config.buffer_size = this->max_http_recv_buffer_; + config.auth_type = HTTP_AUTH_TYPE_BASIC; + config.max_authorization_retries = -1; +#if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE + if (this->secure_()) { + config.crt_bundle_attach = esp_crt_bundle_attach; + } +#endif +#pragma GCC diagnostic pop + + watchdog::WatchdogManager wdts; + this->client_ = esp_http_client_init(&config); + if ((this->status_ = esp_http_client_open(this->client_, 0)) == ESP_OK) { + this->body_length_ = esp_http_client_fetch_headers(this->client_); + this->status_ = esp_http_client_get_status_code(this->client_); + } +} + +int OtaHttpRequestComponentIDF::http_read(uint8_t *buf, const size_t max_len) { + watchdog::WatchdogManager wdts; + int bufsize = std::min(max_len, this->body_length_ - this->bytes_read_); + + App.feed_wdt(); + int read_len = esp_http_client_read(this->client_, (char *) buf, bufsize); + if (read_len > 0) { + this->bytes_read_ += bufsize; + buf[bufsize] = '\0'; // not fed to ota + } + + return read_len; +} + +void OtaHttpRequestComponentIDF::http_end() { + watchdog::WatchdogManager wdts; + + esp_http_client_close(this->client_); + esp_http_client_cleanup(this->client_); +} + +} // namespace http_request +} // namespace esphome + +#endif // USE_ESP_IDF diff --git a/esphome/components/http_request/ota/ota_http_request_idf.h b/esphome/components/http_request/ota/ota_http_request_idf.h new file mode 100644 index 0000000000..9783b2a3e1 --- /dev/null +++ b/esphome/components/http_request/ota/ota_http_request_idf.h @@ -0,0 +1,24 @@ +#pragma once + +#include "ota_http_request.h" + +#ifdef USE_ESP_IDF +#include "esp_http_client.h" + +namespace esphome { +namespace http_request { + +class OtaHttpRequestComponentIDF : public OtaHttpRequestComponent { + public: + void http_init(const std::string &url) override; + int http_read(uint8_t *buf, size_t len) override; + void http_end() override; + + protected: + esp_http_client_handle_t client_{}; +}; + +} // namespace http_request +} // namespace esphome + +#endif // USE_ESP_IDF diff --git a/esphome/components/http_request/ota/watchdog.cpp b/esphome/components/http_request/ota/watchdog.cpp new file mode 100644 index 0000000000..663c9afaac --- /dev/null +++ b/esphome/components/http_request/ota/watchdog.cpp @@ -0,0 +1,71 @@ +#include "watchdog.h" + +#ifdef USE_HTTP_REQUEST_OTA_WATCHDOG_TIMEOUT + +#include "esphome/core/application.h" +#include "esphome/core/log.h" + +#include +#include +#ifdef USE_ESP32 +#include "esp_idf_version.h" +#include "esp_task_wdt.h" +#endif +#ifdef USE_RP2040 +#include "hardware/watchdog.h" +#include "pico/stdlib.h" +#endif + +namespace esphome { +namespace http_request { +namespace watchdog { + +static const char *const TAG = "watchdog.http_request.ota"; + +WatchdogManager::WatchdogManager() { + this->saved_timeout_ms_ = this->get_timeout_(); + this->set_timeout_(USE_HTTP_REQUEST_OTA_WATCHDOG_TIMEOUT); +} + +WatchdogManager::~WatchdogManager() { this->set_timeout_(this->saved_timeout_ms_); } + +void WatchdogManager::set_timeout_(uint32_t timeout_ms) { + ESP_LOGV(TAG, "Adjusting WDT to %" PRIu32 "ms", timeout_ms); +#ifdef USE_ESP32 +#if ESP_IDF_VERSION_MAJOR >= 5 + esp_task_wdt_config_t wdt_config = { + .timeout_ms = timeout_ms, + .idle_core_mask = 0x03, + .trigger_panic = true, + }; + esp_task_wdt_reconfigure(&wdt_config); +#else + esp_task_wdt_init(timeout_ms, true); +#endif // ESP_IDF_VERSION_MAJOR +#endif // USE_ESP32 + +#ifdef USE_RP2040 + watchdog_enable(timeout_ms, true); +#endif +} + +uint32_t WatchdogManager::get_timeout_() { + uint32_t timeout_ms = 0; + +#ifdef USE_ESP32 + timeout_ms = (uint32_t) CONFIG_ESP_TASK_WDT_TIMEOUT_S * 1000; +#endif // USE_ESP32 + +#ifdef USE_RP2040 + timeout_ms = watchdog_get_count() / 1000; +#endif + + ESP_LOGVV(TAG, "get_timeout: %" PRIu32 "ms", timeout_ms); + + return timeout_ms; +} + +} // namespace watchdog +} // namespace http_request +} // namespace esphome +#endif diff --git a/esphome/components/http_request/ota/watchdog.h b/esphome/components/http_request/ota/watchdog.h new file mode 100644 index 0000000000..0a09dcd6fa --- /dev/null +++ b/esphome/components/http_request/ota/watchdog.h @@ -0,0 +1,27 @@ +#pragma once + +#include "esphome/core/defines.h" + +#include + +namespace esphome { +namespace http_request { +namespace watchdog { + +class WatchdogManager { +#ifdef USE_HTTP_REQUEST_OTA_WATCHDOG_TIMEOUT + public: + WatchdogManager(); + ~WatchdogManager(); + + private: + uint32_t get_timeout_(); + void set_timeout_(uint32_t timeout_ms); + + uint32_t saved_timeout_ms_{0}; +#endif +}; + +} // namespace watchdog +} // namespace http_request +} // namespace esphome diff --git a/esphome/core/defines.h b/esphome/core/defines.h index c2ad0f641c..76b6af6592 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -33,6 +33,7 @@ #define USE_GRAPH #define USE_GRAPHICAL_DISPLAY_MENU #define USE_HOMEASSISTANT_TIME +#define USE_HTTP_REQUEST_OTA_WATCHDOG_TIMEOUT 8000 // NOLINT #define USE_JSON #define USE_LIGHT #define USE_LOCK diff --git a/tests/components/http_request/common.yaml b/tests/components/http_request/common_http_request.yaml similarity index 95% rename from tests/components/http_request/common.yaml rename to tests/components/http_request/common_http_request.yaml index 848fe3f509..b00768c736 100644 --- a/tests/components/http_request/common.yaml +++ b/tests/components/http_request/common_http_request.yaml @@ -28,10 +28,6 @@ esphome: body: "Some data" verify_ssl: false -wifi: - ssid: MySSID - password: password1 - http_request: useragent: esphome/tagreader timeout: 10s diff --git a/tests/components/http_request/common_ota.yaml b/tests/components/http_request/common_ota.yaml new file mode 100644 index 0000000000..10e7d54c3f --- /dev/null +++ b/tests/components/http_request/common_ota.yaml @@ -0,0 +1,36 @@ +wifi: + ssid: MySSID + password: password1 + +ota: + - platform: http_request + verify_ssl: ${verify_ssl} + on_begin: + then: + - logger.log: "OTA start" + on_progress: + then: + - logger.log: + format: "OTA progress %0.1f%%" + args: ["x"] + on_end: + then: + - logger.log: "OTA end" + on_error: + then: + - logger.log: + format: "OTA update error %d" + args: ["x"] + on_state_change: + then: + lambda: 'ESP_LOGD("ota", "State %d", state);' + +button: + - platform: template + name: Firmware update + on_press: + then: + - ota_http_request.flash: + md5_url: http://my.ha.net:8123/local/esphome/firmware.md5 + url: http://my.ha.net:8123/local/esphome/firmware.bin + - logger.log: "This message should be not displayed (reboot)" diff --git a/tests/components/http_request/test-nossl.esp8266.yaml b/tests/components/http_request/test-nossl.esp8266.yaml new file mode 100644 index 0000000000..65116d5550 --- /dev/null +++ b/tests/components/http_request/test-nossl.esp8266.yaml @@ -0,0 +1,38 @@ +<<: !include common_http_request.yaml + +wifi: + ssid: MySSID + password: password1 + +ota: + - platform: http_request + esp8266_disable_ssl_support: true + on_begin: + then: + - logger.log: "OTA start" + on_progress: + then: + - logger.log: + format: "OTA progress %0.1f%%" + args: ["x"] + on_end: + then: + - logger.log: "OTA end" + on_error: + then: + - logger.log: + format: "OTA update error %d" + args: ["x"] + on_state_change: + then: + lambda: 'ESP_LOGD("ota", "State %d", state);' + +button: + - platform: template + name: Firmware update + on_press: + then: + - ota_http_request.flash: + md5_url: http://my.ha.net:8123/local/esphome/firmware.md5 + url: http://my.ha.net:8123/local/esphome/firmware.bin + - logger.log: "This message should be not displayed (reboot)" diff --git a/tests/components/http_request/test.esp32-c3-idf.yaml b/tests/components/http_request/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..da629e83a9 --- /dev/null +++ b/tests/components/http_request/test.esp32-c3-idf.yaml @@ -0,0 +1,4 @@ +substitutions: + verify_ssl: "true" + +<<: !include common_ota.yaml diff --git a/tests/components/http_request/test.esp32-c3.yaml b/tests/components/http_request/test.esp32-c3.yaml index 25cb37a0b4..1f597bb500 100644 --- a/tests/components/http_request/test.esp32-c3.yaml +++ b/tests/components/http_request/test.esp32-c3.yaml @@ -1,2 +1,5 @@ -packages: - common: !include common.yaml +substitutions: + verify_ssl: "false" + +<<: !include common_http_request.yaml +<<: !include common_ota.yaml diff --git a/tests/components/http_request/test.esp32-idf.yaml b/tests/components/http_request/test.esp32-idf.yaml new file mode 100644 index 0000000000..da629e83a9 --- /dev/null +++ b/tests/components/http_request/test.esp32-idf.yaml @@ -0,0 +1,4 @@ +substitutions: + verify_ssl: "true" + +<<: !include common_ota.yaml diff --git a/tests/components/http_request/test.esp32.yaml b/tests/components/http_request/test.esp32.yaml index 25cb37a0b4..1f597bb500 100644 --- a/tests/components/http_request/test.esp32.yaml +++ b/tests/components/http_request/test.esp32.yaml @@ -1,2 +1,5 @@ -packages: - common: !include common.yaml +substitutions: + verify_ssl: "false" + +<<: !include common_http_request.yaml +<<: !include common_ota.yaml diff --git a/tests/components/http_request/test.esp8266.yaml b/tests/components/http_request/test.esp8266.yaml index 25cb37a0b4..1f597bb500 100644 --- a/tests/components/http_request/test.esp8266.yaml +++ b/tests/components/http_request/test.esp8266.yaml @@ -1,2 +1,5 @@ -packages: - common: !include common.yaml +substitutions: + verify_ssl: "false" + +<<: !include common_http_request.yaml +<<: !include common_ota.yaml diff --git a/tests/components/http_request/test.rp2040.yaml b/tests/components/http_request/test.rp2040.yaml new file mode 100644 index 0000000000..077e4d82da --- /dev/null +++ b/tests/components/http_request/test.rp2040.yaml @@ -0,0 +1,4 @@ +substitutions: + verify_ssl: "false" + +<<: !include common_ota.yaml From ccab57fc583189976248b7574eb4ca448860b16a Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 7 Jun 2024 16:30:49 +1200 Subject: [PATCH 1551/2101] [logger] Fix defines for development (#6870) * [logger] Fix defines for development * Set debugging flags for rp2040 --- esphome/components/logger/__init__.py | 27 ++++++++++++++++++++------- esphome/core/defines.h | 9 +++++++++ 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/esphome/components/logger/__init__.py b/esphome/components/logger/__init__.py index c05f3d54aa..99aa39c4ba 100644 --- a/esphome/components/logger/__init__.py +++ b/esphome/components/logger/__init__.py @@ -112,11 +112,18 @@ HARDWARE_UART_TO_UART_SELECTION = { } HARDWARE_UART_TO_SERIAL = { - UART0: cg.global_ns.Serial, - UART0_SWAP: cg.global_ns.Serial, - UART1: cg.global_ns.Serial1, - UART2: cg.global_ns.Serial2, - DEFAULT: cg.global_ns.Serial, + PLATFORM_ESP8266: { + UART0: cg.global_ns.Serial, + UART0_SWAP: cg.global_ns.Serial, + UART1: cg.global_ns.Serial1, + UART2: cg.global_ns.Serial2, + DEFAULT: cg.global_ns.Serial, + }, + PLATFORM_RP2040: { + UART0: cg.global_ns.Serial1, + UART1: cg.global_ns.Serial2, + USB_CDC: cg.global_ns.Serial, + }, } is_log_level = cv.one_of(*LOG_LEVELS, upper=True) @@ -244,8 +251,14 @@ async def to_code(config): is_at_least_very_verbose = this_severity >= very_verbose_severity has_serial_logging = baud_rate != 0 - if CORE.is_esp8266 and has_serial_logging and is_at_least_verbose: - debug_serial_port = HARDWARE_UART_TO_SERIAL[config.get(CONF_HARDWARE_UART)] + if ( + (CORE.is_esp8266 or CORE.is_rp2040) + and has_serial_logging + and is_at_least_verbose + ): + debug_serial_port = HARDWARE_UART_TO_SERIAL[CORE.target_platform][ + config.get(CONF_HARDWARE_UART) + ] cg.add_build_flag(f"-DDEBUG_ESP_PORT={debug_serial_port}") cg.add_build_flag("-DLWIP_DEBUG") DEBUG_COMPONENTS = { diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 76b6af6592..affcd78089 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -101,6 +101,14 @@ #ifdef USE_ESP_IDF #define USE_ESP_IDF_VERSION_CODE VERSION_CODE(4, 4, 2) #endif + +#if defined(USE_ESP32_VARIANT_ESP32S2) +#define USE_LOGGER_USB_CDC +#elif defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32C3) || \ + defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32H2) +#define USE_LOGGER_USB_CDC +#define USE_LOGGER_USB_SERIAL_JTAG +#endif #endif // ESP8266-specific feature flags @@ -123,6 +131,7 @@ #ifdef USE_RP2040 #define USE_ARDUINO_VERSION_CODE VERSION_CODE(3, 3, 0) +#define USE_LOGGER_USB_CDC #define USE_SOCKET_IMPL_LWIP_TCP #define USE_SPI #endif From 276eea2b69f71a91dd87c672ad8c72d8883592a3 Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Fri, 7 Jun 2024 12:36:07 -0700 Subject: [PATCH 1552/2101] [docker] Avoid unsafe git error when container user and file config volume permissions don't match (#6873) --- docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index f6234235f7..36be700f55 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -101,7 +101,7 @@ RUN --mount=type=tmpfs,target=/root/.cargo if [ "$TARGETARCH$TARGETVARIANT" = "a && /platformio_install_deps.py /platformio.ini --libraries # Avoid unsafe git error when container user and file config volume permissions don't match -RUN git config --system --add safe.directory '/config/*' +RUN git config --system --add safe.directory '*' # ======================= docker-type image ======================= From 861a23d039cdc3900087958fb0586bffd790fd7c Mon Sep 17 00:00:00 2001 From: RFDarter Date: Fri, 7 Jun 2024 21:37:05 +0200 Subject: [PATCH 1553/2101] [datetime] Add logs on DateCall perform (#6868) --- esphome/components/datetime/date_entity.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/esphome/components/datetime/date_entity.cpp b/esphome/components/datetime/date_entity.cpp index 19399c1e59..b5bcef43af 100644 --- a/esphome/components/datetime/date_entity.cpp +++ b/esphome/components/datetime/date_entity.cpp @@ -80,6 +80,17 @@ void DateCall::validate_() { void DateCall::perform() { this->validate_(); + ESP_LOGD(TAG, "'%s' - Setting", this->parent_->get_name().c_str()); + + if (this->year_.has_value()) { + ESP_LOGD(TAG, " Year: %d", *this->year_); + } + if (this->month_.has_value()) { + ESP_LOGD(TAG, " Month: %d", *this->month_); + } + if (this->day_.has_value()) { + ESP_LOGD(TAG, " Day: %d", *this->day_); + } this->parent_->control(*this); } From 8718e15a6a6dc56323e8e1ce1163da8b6eec9e9f Mon Sep 17 00:00:00 2001 From: Mischa Siekmann <45062894+gnumpi@users.noreply.github.com> Date: Fri, 7 Jun 2024 21:43:22 +0200 Subject: [PATCH 1554/2101] fix: arduino media player sets wrong state for announcements (#6849) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- .../i2s_audio/media_player/i2s_audio_media_player.cpp | 11 ++++++++--- .../i2s_audio/media_player/i2s_audio_media_player.h | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/esphome/components/i2s_audio/media_player/i2s_audio_media_player.cpp b/esphome/components/i2s_audio/media_player/i2s_audio_media_player.cpp index 1890e27bdf..ef494fac2e 100644 --- a/esphome/components/i2s_audio/media_player/i2s_audio_media_player.cpp +++ b/esphome/components/i2s_audio/media_player/i2s_audio_media_player.cpp @@ -27,6 +27,11 @@ void I2SAudioMediaPlayer::control(const media_player::MediaPlayerCall &call) { this->start(); } } + + if (this->state == media_player::MEDIA_PLAYER_STATE_ANNOUNCING) { + this->is_announcement_ = true; + } + if (call.get_volume().has_value()) { this->volume = call.get_volume().value(); this->set_volume_(volume); @@ -171,9 +176,8 @@ void I2SAudioMediaPlayer::start_() { if (this->current_url_.has_value()) { this->audio_->connecttohost(this->current_url_.value().c_str()); this->state = media_player::MEDIA_PLAYER_STATE_PLAYING; - if (this->is_announcement_.has_value()) { - this->state = this->is_announcement_.value() ? media_player::MEDIA_PLAYER_STATE_ANNOUNCING - : media_player::MEDIA_PLAYER_STATE_PLAYING; + if (this->is_announcement_) { + this->state = media_player::MEDIA_PLAYER_STATE_ANNOUNCING; } this->publish_state(); } @@ -202,6 +206,7 @@ void I2SAudioMediaPlayer::stop_() { this->high_freq_.stop(); this->state = media_player::MEDIA_PLAYER_STATE_IDLE; this->publish_state(); + this->is_announcement_ = false; } media_player::MediaPlayerTraits I2SAudioMediaPlayer::get_traits() { diff --git a/esphome/components/i2s_audio/media_player/i2s_audio_media_player.h b/esphome/components/i2s_audio/media_player/i2s_audio_media_player.h index d7d9b1f74a..5afe778122 100644 --- a/esphome/components/i2s_audio/media_player/i2s_audio_media_player.h +++ b/esphome/components/i2s_audio/media_player/i2s_audio_media_player.h @@ -78,7 +78,7 @@ class I2SAudioMediaPlayer : public Component, public media_player::MediaPlayer, HighFrequencyLoopRequester high_freq_; optional current_url_{}; - optional is_announcement_{}; + bool is_announcement_{false}; }; } // namespace i2s_audio From d77ea461571e338ee1344f56e225fd4de26d66c7 Mon Sep 17 00:00:00 2001 From: RFDarter Date: Fri, 7 Jun 2024 22:29:10 +0200 Subject: [PATCH 1555/2101] [datetime] datetime-datetime strptime support value string without seconds (#6867) --- esphome/core/time.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/esphome/core/time.cpp b/esphome/core/time.cpp index add671701f..f7aa4fdddb 100644 --- a/esphome/core/time.cpp +++ b/esphome/core/time.cpp @@ -84,6 +84,16 @@ bool ESPTime::strptime(const std::string &time_to_parse, ESPTime &esp_time) { esp_time.hour = hour; esp_time.minute = minute; esp_time.second = second; + } else if (sscanf(time_to_parse.c_str(), "%04hu-%02hhu-%02hhu %02hhu:%02hhu %n", &year, &month, &day, // NOLINT + &hour, // NOLINT + &minute, &num) == 5 && // NOLINT + num == time_to_parse.size()) { + esp_time.year = year; + esp_time.month = month; + esp_time.day_of_month = day; + esp_time.hour = hour; + esp_time.minute = minute; + esp_time.second = 0; } else if (sscanf(time_to_parse.c_str(), "%02hhu:%02hhu:%02hhu %n", &hour, &minute, &second, &num) == 3 && // NOLINT num == time_to_parse.size()) { esp_time.hour = hour; From 38b7bed2faa522e7e065d8362d6ea0bcaf1c64d5 Mon Sep 17 00:00:00 2001 From: esphomebot Date: Sat, 8 Jun 2024 21:55:57 +1200 Subject: [PATCH 1556/2101] Update webserver local assets to 20240608-093147 (#6874) --- .../components/web_server/server_index_v2.h | 1231 +++++++++-------- .../components/web_server/server_index_v3.h | 721 +++++----- 2 files changed, 977 insertions(+), 975 deletions(-) diff --git a/esphome/components/web_server/server_index_v2.h b/esphome/components/web_server/server_index_v2.h index 31c2d1fd85..7417f37015 100644 --- a/esphome/components/web_server/server_index_v2.h +++ b/esphome/components/web_server/server_index_v2.h @@ -11,623 +11,624 @@ namespace web_server { const uint8_t INDEX_GZ[] PROGMEM = { 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xcd, 0x7d, 0xd9, 0x92, 0xdb, 0x46, 0xb6, 0xe0, 0xf3, - 0xdc, 0xaf, 0x40, 0xc1, 0xd5, 0x25, 0x64, 0x33, 0x89, 0x22, 0x59, 0xda, 0x0c, 0x56, 0x92, 0x5d, 0x2a, 0xc9, 0x2d, - 0xbb, 0xb5, 0xd8, 0x2a, 0xc9, 0x6e, 0x9b, 0x66, 0x57, 0xa1, 0x88, 0x24, 0x99, 0x16, 0x88, 0xa4, 0x13, 0xc9, 0x5a, + 0xdc, 0xaf, 0x40, 0xa5, 0xab, 0x4b, 0xc8, 0x66, 0x12, 0x45, 0xb2, 0xb4, 0x19, 0xac, 0x24, 0xbb, 0x54, 0x92, 0x5b, + 0x76, 0x6b, 0xb1, 0x55, 0x92, 0xdd, 0x36, 0xcd, 0xae, 0x42, 0x11, 0x49, 0x32, 0x2d, 0x10, 0x49, 0x03, 0xc9, 0x5a, 0x4c, 0xe2, 0xc6, 0x7c, 0xc0, 0x44, 0x4c, 0xc4, 0x3c, 0xcd, 0xcb, 0xc4, 0xdc, 0x87, 0xf9, 0x88, 0x79, 0xbe, 0x9f, 0x72, 0x7f, 0x60, 0xe6, 0x13, 0x26, 0x4e, 0x2e, 0x40, 0x82, 0x4b, 0xa9, 0xbc, 0xdc, 0x1b, 0x13, 0x0a, 0x49, 0x44, - 0xae, 0x27, 0x4f, 0x9e, 0x3c, 0x7b, 0x02, 0xc7, 0x7b, 0x09, 0x1f, 0xc9, 0xdb, 0x39, 0xf5, 0xa6, 0x72, 0x96, 0xf6, - 0x8e, 0xcd, 0xbf, 0x34, 0x4e, 0x7a, 0xc7, 0x29, 0xcb, 0x3e, 0x7a, 0x82, 0xa6, 0x84, 0x8d, 0x78, 0xe6, 0x4d, 0x05, - 0x1d, 0x93, 0x24, 0x96, 0x71, 0xc4, 0x66, 0xf1, 0x84, 0x7a, 0x87, 0xbd, 0xe3, 0x19, 0x95, 0xb1, 0x37, 0x9a, 0xc6, - 0x22, 0xa7, 0x92, 0x7c, 0x78, 0xff, 0x45, 0xf3, 0x69, 0xef, 0x38, 0x1f, 0x09, 0x36, 0x97, 0x1e, 0x0c, 0x49, 0x66, - 0x3c, 0x59, 0xa4, 0xb4, 0x77, 0x78, 0x78, 0x7d, 0x7d, 0x1d, 0xfe, 0x94, 0xff, 0xd3, 0x88, 0x67, 0xb9, 0xf4, 0x5e, - 0x91, 0x6b, 0x96, 0x25, 0xfc, 0x1a, 0x53, 0x49, 0x5e, 0x85, 0x67, 0xd3, 0x38, 0xe1, 0xd7, 0xef, 0x38, 0x97, 0x07, - 0x07, 0x81, 0x7e, 0xbc, 0x3d, 0x3d, 0x3b, 0x23, 0x84, 0x5c, 0x71, 0x96, 0x78, 0xad, 0xd5, 0xaa, 0x2a, 0x0c, 0xb3, - 0x58, 0xb2, 0x2b, 0xaa, 0xbb, 0xa0, 0x83, 0x03, 0x3f, 0x4e, 0xf8, 0x5c, 0xd2, 0xe4, 0x4c, 0xde, 0xa6, 0xf4, 0x6c, - 0x4a, 0xa9, 0xcc, 0x7d, 0x96, 0x79, 0xcf, 0xf9, 0x68, 0x31, 0xa3, 0x99, 0x0c, 0xe7, 0x82, 0x4b, 0x0e, 0x90, 0x1c, - 0x1c, 0xf8, 0x82, 0xce, 0xd3, 0x78, 0x44, 0xa1, 0xfe, 0xf4, 0xec, 0xac, 0xea, 0x51, 0x35, 0xc2, 0x4c, 0x92, 0xb3, - 0xdb, 0xd9, 0x25, 0x4f, 0x03, 0x84, 0x53, 0x49, 0x32, 0x7a, 0xed, 0x7d, 0x47, 0xe3, 0x8f, 0xaf, 0xe3, 0x79, 0x77, - 0x94, 0xc6, 0x79, 0xee, 0x5d, 0xca, 0xa5, 0x5a, 0x82, 0x58, 0x8c, 0x24, 0x17, 0x81, 0xc4, 0x14, 0x33, 0xb4, 0x64, - 0xe3, 0x40, 0x4e, 0x59, 0x1e, 0x9e, 0xef, 0x8f, 0xf2, 0xfc, 0x1d, 0xcd, 0x17, 0xa9, 0xdc, 0x27, 0x7b, 0x2d, 0xcc, - 0xf6, 0x08, 0x61, 0x12, 0xc9, 0xa9, 0xe0, 0xd7, 0xde, 0x0b, 0x21, 0xb8, 0x08, 0xfc, 0xd3, 0xb3, 0x33, 0xdd, 0xc2, - 0x63, 0xb9, 0x97, 0x71, 0xe9, 0x95, 0xe3, 0xc5, 0x97, 0x29, 0x0d, 0xbd, 0x0f, 0x39, 0xf5, 0x2e, 0x16, 0x59, 0x1e, - 0x8f, 0xe9, 0xe9, 0xd9, 0xd9, 0x85, 0xc7, 0x85, 0x77, 0x31, 0xca, 0xf3, 0x0b, 0x8f, 0x65, 0xb9, 0xa4, 0x71, 0x12, - 0xfa, 0xa8, 0xab, 0x26, 0x1b, 0xe5, 0xf9, 0x7b, 0x7a, 0x23, 0x89, 0xc4, 0xea, 0x51, 0x12, 0x5a, 0x4c, 0xa8, 0xf4, - 0xf2, 0x72, 0x5d, 0x01, 0x5a, 0xa6, 0x54, 0x7a, 0x92, 0xa8, 0x7a, 0xde, 0xd5, 0xb8, 0xa7, 0xfa, 0x51, 0x76, 0xd9, - 0x38, 0xa0, 0xf2, 0xe0, 0x40, 0x96, 0x78, 0x46, 0x7a, 0x69, 0x1e, 0x23, 0x74, 0xcf, 0x96, 0x1d, 0x1c, 0xd0, 0x30, - 0xa5, 0xd9, 0x44, 0x4e, 0x09, 0x21, 0xed, 0x2e, 0x3b, 0x38, 0x08, 0x24, 0x49, 0x65, 0x38, 0xa1, 0x32, 0xa0, 0x08, - 0xe1, 0xaa, 0xf7, 0xc1, 0x41, 0xa0, 0x91, 0xc0, 0x89, 0x46, 0x5c, 0x0d, 0xc7, 0x28, 0x34, 0xd8, 0x3f, 0xbb, 0xcd, - 0x46, 0x81, 0x0b, 0x3f, 0xc2, 0xec, 0xe0, 0x20, 0x95, 0x61, 0x0e, 0x23, 0x62, 0x89, 0x50, 0x21, 0xa8, 0x5c, 0x88, - 0xcc, 0x93, 0x85, 0xe4, 0x67, 0x52, 0xb0, 0x6c, 0x12, 0xa0, 0xa5, 0x2d, 0x73, 0x3a, 0x16, 0x85, 0x06, 0xf7, 0x6b, - 0x49, 0x04, 0xe9, 0xc1, 0x8c, 0x97, 0x32, 0x80, 0x5d, 0xe4, 0x63, 0x4f, 0x10, 0xe2, 0xe7, 0xaa, 0xaf, 0xdf, 0x17, - 0x91, 0x68, 0xf8, 0x3e, 0xd6, 0x50, 0x62, 0x26, 0x11, 0xfe, 0x48, 0x02, 0x81, 0xc3, 0x30, 0x94, 0x88, 0xf4, 0x96, - 0x16, 0x2b, 0xc2, 0x59, 0x67, 0x5f, 0x0c, 0x5a, 0xc3, 0x48, 0x86, 0x82, 0x26, 0x8b, 0x11, 0x0d, 0x02, 0x86, 0x73, - 0x9c, 0x21, 0xd2, 0x63, 0x8d, 0x80, 0x93, 0x1e, 0x6c, 0x37, 0xaf, 0xef, 0x35, 0x21, 0x7b, 0x2d, 0x64, 0x60, 0xe4, - 0x16, 0x40, 0xc0, 0xb0, 0x81, 0x87, 0x13, 0xe2, 0x67, 0x8b, 0xd9, 0x25, 0x15, 0x7e, 0xd9, 0xac, 0x5b, 0x23, 0x8b, - 0x45, 0x4e, 0xbd, 0x51, 0x9e, 0x7b, 0xe3, 0x45, 0x36, 0x92, 0x8c, 0x67, 0x9e, 0xdf, 0xe0, 0x0d, 0x5f, 0x93, 0x43, - 0x49, 0x0d, 0x3e, 0x2a, 0x50, 0x90, 0xa3, 0x86, 0x18, 0x64, 0x8d, 0xf6, 0x10, 0x03, 0x94, 0xa8, 0x6b, 0xc6, 0x33, - 0x08, 0xa0, 0x58, 0xc0, 0x1a, 0x0b, 0xfc, 0x41, 0xc2, 0x2a, 0xd5, 0x12, 0xa9, 0xec, 0x8b, 0x70, 0xf3, 0xa0, 0x10, - 0x19, 0xce, 0xe2, 0x79, 0x40, 0x49, 0x8f, 0x2a, 0xe2, 0x8a, 0xb3, 0x11, 0xc0, 0x5a, 0xdb, 0xb7, 0x3e, 0x8d, 0x68, - 0x58, 0x91, 0x14, 0x8a, 0x64, 0x38, 0xe6, 0xe2, 0x45, 0x3c, 0x9a, 0x42, 0xbf, 0x92, 0x60, 0x12, 0x7b, 0xde, 0x46, - 0x82, 0xc6, 0x92, 0xbe, 0x48, 0x29, 0x3c, 0x05, 0xbe, 0xea, 0xe9, 0x23, 0x9c, 0x93, 0x57, 0x61, 0xca, 0xe4, 0x1b, - 0x9e, 0x8d, 0x68, 0x37, 0x77, 0xa8, 0x8b, 0xc1, 0xbe, 0x9f, 0x48, 0x29, 0xd8, 0xe5, 0x42, 0xd2, 0xc0, 0xcf, 0xa0, - 0x85, 0x8f, 0x73, 0x84, 0x59, 0x28, 0xe9, 0x8d, 0x3c, 0xe5, 0x99, 0xa4, 0x99, 0x24, 0xd4, 0x22, 0x15, 0x8b, 0x30, - 0x9e, 0xcf, 0x69, 0x96, 0x9c, 0x4e, 0x59, 0x9a, 0x04, 0x0c, 0x15, 0xa8, 0xc0, 0xb1, 0x24, 0xb0, 0x46, 0xd2, 0x13, - 0x11, 0xfc, 0xb3, 0x7b, 0x35, 0x81, 0x24, 0x3d, 0x75, 0x28, 0x28, 0xf1, 0xfd, 0xee, 0x98, 0x8b, 0xc0, 0xac, 0xc0, - 0xe3, 0x63, 0x4f, 0xc2, 0x1c, 0xef, 0x16, 0x29, 0xcd, 0x11, 0x6d, 0x10, 0x56, 0x6e, 0xa3, 0x41, 0xf0, 0xd7, 0x40, - 0xf1, 0x05, 0x0a, 0x04, 0x8a, 0x44, 0xf7, 0x2a, 0x16, 0xde, 0x17, 0xe6, 0x44, 0xfd, 0x64, 0xb9, 0xd9, 0x54, 0x92, - 0x9f, 0x42, 0x29, 0x16, 0xb9, 0xa4, 0xc9, 0xfb, 0xdb, 0x39, 0xcd, 0xf1, 0x4b, 0x49, 0xa6, 0xb2, 0x3f, 0x95, 0x21, - 0x9d, 0xcd, 0xe5, 0xed, 0x99, 0x62, 0x8c, 0x91, 0xef, 0xe3, 0x11, 0xb4, 0x14, 0x34, 0x1e, 0x01, 0x33, 0x33, 0xd8, - 0xfa, 0x9a, 0xa7, 0xb7, 0x63, 0x96, 0xa6, 0x67, 0x8b, 0xf9, 0x9c, 0x0b, 0x89, 0xff, 0x4a, 0x96, 0x92, 0x57, 0xa8, - 0x81, 0xbd, 0x5c, 0xe6, 0xd7, 0x4c, 0x8e, 0xa6, 0x81, 0x44, 0xcb, 0x51, 0x9c, 0x53, 0xef, 0x19, 0xe7, 0x29, 0x8d, - 0xb3, 0x48, 0x10, 0xd1, 0x7f, 0x29, 0xa3, 0x6c, 0x91, 0xa6, 0xdd, 0x4b, 0x41, 0xe3, 0x8f, 0x5d, 0x55, 0xfd, 0xf6, - 0xf2, 0x27, 0x3a, 0x92, 0x91, 0xfa, 0x7d, 0x22, 0x44, 0x7c, 0x0b, 0x0d, 0x09, 0x81, 0x66, 0x7d, 0x11, 0x7d, 0x75, - 0xf6, 0xf6, 0x4d, 0xa8, 0x0f, 0x09, 0x1b, 0xdf, 0x06, 0xa2, 0x3c, 0x78, 0xa2, 0xc0, 0x63, 0xc1, 0x67, 0x6b, 0x53, - 0x6b, 0xac, 0x89, 0xee, 0x0e, 0x10, 0x28, 0x11, 0x7b, 0x7a, 0x68, 0x17, 0x82, 0x37, 0x8a, 0xe6, 0xa1, 0x92, 0x98, - 0x79, 0xe1, 0x9f, 0x48, 0x17, 0x07, 0x02, 0xdd, 0x0d, 0xad, 0x14, 0xb7, 0x4b, 0x4a, 0x14, 0x9c, 0x73, 0x90, 0x30, - 0x00, 0xe3, 0x28, 0x96, 0xa3, 0xe9, 0x92, 0xaa, 0xc1, 0x0a, 0x0b, 0x31, 0x2d, 0x0a, 0x7c, 0x5d, 0xd2, 0xbb, 0xdc, - 0x23, 0x44, 0x28, 0x46, 0x45, 0xe4, 0x6a, 0x25, 0x08, 0x11, 0x08, 0x7f, 0x47, 0x96, 0xb1, 0x5d, 0x4f, 0xb4, 0xd7, - 0xc2, 0x70, 0x2e, 0x23, 0xcd, 0x5d, 0xf0, 0x88, 0x67, 0x57, 0x54, 0x48, 0x2a, 0xa2, 0xbf, 0x62, 0x41, 0xc7, 0x29, - 0x40, 0xb1, 0xd7, 0xc6, 0xd3, 0x38, 0x3f, 0x9d, 0xc6, 0xd9, 0x84, 0x26, 0xd1, 0xb5, 0x2c, 0xf0, 0xdf, 0x89, 0x3f, - 0x66, 0x59, 0x9c, 0xb2, 0x5f, 0x68, 0xe2, 0x1b, 0x69, 0x70, 0xe2, 0xd1, 0x1b, 0x49, 0xb3, 0x24, 0xf7, 0x5e, 0xbe, - 0x7f, 0xfd, 0xca, 0xec, 0x63, 0x4d, 0x40, 0xa0, 0x65, 0xbe, 0x98, 0x53, 0x11, 0x20, 0x6c, 0x04, 0xc4, 0x0b, 0xa6, - 0x98, 0xe3, 0xeb, 0x78, 0xae, 0x4b, 0x58, 0xfe, 0x61, 0x9e, 0xc4, 0x92, 0x7e, 0x4d, 0xb3, 0x84, 0x65, 0x13, 0xb2, - 0xd7, 0xd6, 0xe5, 0xd3, 0xd8, 0x54, 0x24, 0x65, 0xd1, 0xf9, 0xfe, 0x8b, 0x54, 0xad, 0xbb, 0x7c, 0x5c, 0x04, 0xa8, - 0xc8, 0x65, 0x2c, 0xd9, 0xc8, 0x8b, 0x93, 0xe4, 0xcb, 0x8c, 0x49, 0xa6, 0x00, 0x14, 0xb0, 0x3d, 0x40, 0xa2, 0x54, - 0x8b, 0x0a, 0x0b, 0x78, 0x80, 0x70, 0x10, 0x18, 0x01, 0x30, 0x45, 0x66, 0xbf, 0x0e, 0x0e, 0x2a, 0x76, 0xdf, 0xa7, - 0x91, 0xae, 0x24, 0x83, 0x21, 0x0a, 0xe7, 0x8b, 0x1c, 0x36, 0xda, 0x4e, 0x01, 0xd2, 0x85, 0x5f, 0xe6, 0x54, 0x5c, - 0xd1, 0xa4, 0x24, 0x8e, 0x3c, 0x40, 0xcb, 0xb5, 0x39, 0xcc, 0xb1, 0x90, 0x64, 0x30, 0xec, 0xba, 0x7c, 0x9b, 0x1a, - 0x3a, 0x17, 0x7c, 0x4e, 0x85, 0x64, 0x34, 0x2f, 0x59, 0x49, 0x00, 0x52, 0xb4, 0x64, 0x27, 0x39, 0xb1, 0xeb, 0x9b, - 0x07, 0x0c, 0x53, 0x54, 0x63, 0x18, 0x56, 0xd0, 0xbe, 0xb8, 0x52, 0x12, 0x23, 0xc7, 0x0c, 0x61, 0xa9, 0x21, 0xcd, - 0x11, 0x2a, 0x10, 0x96, 0x16, 0x5c, 0xcd, 0x8a, 0xcc, 0x6c, 0xb7, 0x20, 0xaa, 0xc9, 0x77, 0x4a, 0x54, 0x03, 0x43, - 0x8b, 0x25, 0x3d, 0x38, 0x08, 0x68, 0x58, 0x12, 0x05, 0xd9, 0x6b, 0x9b, 0x3d, 0x72, 0x90, 0xb5, 0x03, 0x6c, 0x98, - 0x58, 0x62, 0x8a, 0xf0, 0x1e, 0x0d, 0x33, 0x7e, 0x32, 0x1a, 0xd1, 0x3c, 0xe7, 0xe2, 0xe0, 0x60, 0x4f, 0xb5, 0x2f, - 0xb5, 0x09, 0xd8, 0xc3, 0xb7, 0xd7, 0x59, 0x05, 0x01, 0xaa, 0x24, 0xac, 0x91, 0x0b, 0x12, 0xe4, 0x94, 0x52, 0x38, - 0xfc, 0xbe, 0x55, 0x3c, 0x22, 0xff, 0xfc, 0xdc, 0x6f, 0x48, 0x6c, 0xd0, 0x30, 0xa1, 0x76, 0xea, 0xdb, 0xe7, 0x54, - 0xab, 0x56, 0x4a, 0xf1, 0xd8, 0xc0, 0x8c, 0x3e, 0x3f, 0x61, 0x42, 0xc7, 0x2c, 0x73, 0x96, 0x5d, 0x03, 0x09, 0x4b, - 0x9c, 0xa3, 0xc2, 0xd9, 0xd0, 0xad, 0x43, 0x2b, 0x9d, 0x46, 0xef, 0xdc, 0x72, 0xa2, 0xf4, 0x08, 0x67, 0x1b, 0x07, - 0x74, 0x58, 0x60, 0x85, 0x7a, 0xbb, 0x9a, 0x4c, 0x01, 0x3a, 0x90, 0xc3, 0xae, 0xa9, 0x27, 0xb9, 0xc6, 0x9c, 0xa0, - 0x3f, 0x2f, 0x68, 0x2e, 0x35, 0x1d, 0x07, 0x12, 0x67, 0x98, 0xa1, 0x02, 0x8e, 0xdb, 0x98, 0x4d, 0x16, 0x02, 0xd4, - 0x1d, 0x38, 0x8a, 0x34, 0x5b, 0xcc, 0xa8, 0x7d, 0xda, 0x06, 0xdb, 0xdb, 0x39, 0x08, 0xc4, 0x1c, 0x68, 0xfa, 0x6e, - 0x72, 0x02, 0x58, 0x25, 0x5a, 0xad, 0xbe, 0xb3, 0x83, 0x54, 0x5b, 0x59, 0xaa, 0x68, 0x6b, 0x7b, 0xf2, 0x77, 0x64, - 0xe4, 0xf1, 0x5e, 0x5b, 0x43, 0xff, 0xf7, 0x21, 0xd9, 0x6b, 0x95, 0x14, 0x6c, 0x70, 0xaa, 0x81, 0xd1, 0x28, 0x7c, - 0xab, 0x07, 0x42, 0x4a, 0xba, 0xd7, 0x88, 0x25, 0x9c, 0x6e, 0xd0, 0xe9, 0x94, 0x0c, 0x40, 0xcf, 0x08, 0xa7, 0xc3, - 0x5d, 0xc4, 0x64, 0xb9, 0x41, 0x20, 0x37, 0xeb, 0x2a, 0xa6, 0x71, 0x55, 0x67, 0x1a, 0x6b, 0x8b, 0xf0, 0xe7, 0x65, - 0x17, 0xbf, 0xa4, 0x31, 0x73, 0xcc, 0xab, 0x2a, 0xcc, 0x14, 0x30, 0xd5, 0x92, 0x9c, 0x21, 0xde, 0xc4, 0x33, 0x9a, - 0x07, 0x14, 0xe1, 0x5d, 0x0d, 0x34, 0x71, 0x42, 0x93, 0xa1, 0x23, 0x36, 0x73, 0x10, 0x9b, 0x0c, 0x69, 0xad, 0xac, - 0x7e, 0xdc, 0x72, 0x4c, 0x07, 0xf9, 0xb0, 0x52, 0xe6, 0x9c, 0xc5, 0x2b, 0x79, 0x6c, 0xa8, 0xdb, 0xe2, 0x4f, 0x97, - 0x69, 0xa4, 0x29, 0xa5, 0x21, 0x47, 0x78, 0xaf, 0xb5, 0xbe, 0x8f, 0xb6, 0x55, 0xb5, 0xc6, 0xc1, 0x10, 0xf6, 0x41, - 0x89, 0x8b, 0x90, 0xe5, 0xea, 0xff, 0xda, 0x39, 0x03, 0xb4, 0x9d, 0x01, 0x59, 0x84, 0xe3, 0x34, 0x96, 0x41, 0xfb, - 0xb0, 0x05, 0x9a, 0xe8, 0x15, 0x05, 0x69, 0x82, 0xd0, 0xe6, 0x52, 0x68, 0xb8, 0xc8, 0xf2, 0x29, 0x1b, 0xcb, 0x20, - 0x96, 0x8a, 0xa1, 0xd0, 0x34, 0xa7, 0x9e, 0xac, 0xe9, 0xc3, 0x8a, 0xd9, 0xc4, 0x40, 0x6a, 0xa5, 0xf2, 0x45, 0x2d, - 0xa4, 0x8a, 0x69, 0x01, 0x6f, 0xa8, 0x74, 0xe9, 0x8a, 0xc7, 0xd8, 0xd6, 0x0c, 0xf4, 0xc5, 0x76, 0x5f, 0x8f, 0x18, - 0x19, 0x56, 0xc0, 0x1c, 0x95, 0x95, 0x45, 0x2e, 0x7f, 0x30, 0x85, 0x32, 0x94, 0xfc, 0x15, 0xbf, 0xa6, 0xe2, 0x34, - 0x06, 0xe0, 0x23, 0xdd, 0xbd, 0xd0, 0x62, 0x40, 0x71, 0x7b, 0xd9, 0xb5, 0xf4, 0x72, 0xae, 0x16, 0xfe, 0xb5, 0xe0, - 0x33, 0x96, 0x53, 0xd0, 0xd4, 0x34, 0xfe, 0x33, 0x38, 0x65, 0xea, 0x38, 0x82, 0xa8, 0xa1, 0x25, 0x7d, 0x9d, 0xbc, - 0xaa, 0xd3, 0xd7, 0xf9, 0xfe, 0x8b, 0x89, 0x65, 0x7f, 0xf5, 0x43, 0x8c, 0x70, 0x60, 0xec, 0x09, 0x47, 0xca, 0x85, - 0x53, 0x64, 0xc4, 0xfb, 0x6a, 0x25, 0x1d, 0xb3, 0xad, 0xa6, 0x2b, 0x52, 0x7d, 0x6c, 0x50, 0x11, 0x27, 0x09, 0x68, - 0x75, 0x82, 0xa7, 0xa9, 0x23, 0xa8, 0x30, 0xeb, 0x96, 0xa2, 0xe9, 0x7c, 0xff, 0xc5, 0xd9, 0x5d, 0xd2, 0x09, 0xea, - 0x5d, 0x01, 0x65, 0x01, 0xcd, 0x12, 0x2a, 0xc0, 0x8c, 0x74, 0x76, 0xcb, 0xc8, 0xd8, 0x53, 0x9e, 0x65, 0x74, 0x24, - 0x69, 0x02, 0x56, 0x0a, 0x23, 0x32, 0x9c, 0xf2, 0x5c, 0x96, 0x85, 0x15, 0xf4, 0xcc, 0x81, 0x9e, 0x85, 0xa3, 0x38, - 0x4d, 0x03, 0x6d, 0x91, 0xcc, 0xf8, 0x15, 0xdd, 0x02, 0x75, 0xb7, 0x06, 0x72, 0x39, 0x0c, 0x75, 0x86, 0xa1, 0x61, - 0x3e, 0x4f, 0xd9, 0x88, 0x96, 0x82, 0xeb, 0x2c, 0x64, 0x59, 0x42, 0x6f, 0x80, 0x8f, 0xa0, 0x5e, 0xaf, 0xd7, 0xc2, - 0x6d, 0x54, 0x68, 0x84, 0x2f, 0x37, 0x10, 0x7b, 0x87, 0xc8, 0x04, 0x22, 0x23, 0xbd, 0xe5, 0x36, 0x7e, 0x40, 0x91, - 0x23, 0x27, 0x99, 0xb5, 0xac, 0x34, 0x6f, 0x46, 0x38, 0xa1, 0x29, 0x95, 0xd4, 0xf2, 0x72, 0xd0, 0x9f, 0xf5, 0xd1, - 0x7d, 0x57, 0xe2, 0xaf, 0x24, 0x27, 0x7b, 0xca, 0xec, 0x9e, 0xe7, 0xa5, 0xa5, 0x5e, 0x6d, 0x4f, 0x85, 0xed, 0xbe, - 0xd4, 0xdb, 0x13, 0x4b, 0x19, 0x8f, 0xa6, 0xda, 0x44, 0x0f, 0x36, 0x96, 0x54, 0x8d, 0x61, 0xf8, 0x7a, 0x79, 0x88, - 0x3e, 0x58, 0x30, 0xb7, 0xa1, 0xe0, 0xcc, 0x30, 0x05, 0x0a, 0x56, 0x9f, 0xde, 0xb6, 0xd3, 0x38, 0x4d, 0x2f, 0xe3, - 0xd1, 0xc7, 0x3a, 0xf5, 0x57, 0x64, 0x40, 0xd6, 0xb9, 0xb1, 0x53, 0xe5, 0xb0, 0x2c, 0x77, 0xdd, 0x96, 0x4b, 0xd7, - 0x0e, 0x4a, 0xb0, 0xd7, 0xaa, 0xc8, 0xbe, 0xbe, 0xd1, 0x3b, 0xa9, 0x5d, 0x41, 0xc4, 0xcc, 0xca, 0x02, 0xe0, 0x02, - 0x9f, 0xa4, 0x38, 0xcb, 0x0f, 0x0c, 0xdd, 0x81, 0xad, 0x51, 0xac, 0x01, 0x22, 0xd1, 0xb2, 0x48, 0x58, 0xbe, 0x1b, - 0x03, 0x7f, 0x08, 0x94, 0xcf, 0x9d, 0x19, 0xee, 0x0b, 0x68, 0xc9, 0xe3, 0x8c, 0xca, 0x5c, 0x42, 0x66, 0xb4, 0x09, - 0xcb, 0x68, 0xfe, 0x06, 0x9a, 0x8b, 0xa2, 0xf7, 0xb7, 0xba, 0x0a, 0x74, 0x32, 0x80, 0x22, 0xef, 0xba, 0xca, 0x44, - 0x8d, 0x02, 0x0c, 0x4f, 0x65, 0x4a, 0xe4, 0x66, 0x35, 0xe3, 0xd1, 0xa8, 0xeb, 0xda, 0xfe, 0x36, 0x2c, 0x97, 0x93, - 0x20, 0x08, 0x72, 0xb0, 0xdf, 0xac, 0x5e, 0x5f, 0x2d, 0x22, 0xdf, 0x58, 0x44, 0x1e, 0x3a, 0x46, 0x16, 0xaa, 0x68, - 0xd9, 0xe9, 0x1e, 0xfd, 0x15, 0xb9, 0x8d, 0x40, 0x59, 0x0d, 0x81, 0x3f, 0xa3, 0x92, 0xdd, 0xa6, 0x44, 0x62, 0x6e, - 0x0c, 0x1c, 0x43, 0x69, 0xc0, 0x30, 0xaa, 0x2e, 0x19, 0xd2, 0x47, 0xa3, 0x66, 0xec, 0x66, 0x98, 0xa3, 0x35, 0xcd, - 0xbe, 0x28, 0x0c, 0x8e, 0x28, 0x32, 0x7b, 0x53, 0x53, 0x89, 0x1d, 0xac, 0xe0, 0x8c, 0x18, 0x35, 0x58, 0x6b, 0x3d, - 0xeb, 0xb8, 0x29, 0xc7, 0x85, 0x83, 0x5a, 0xa1, 0xa6, 0xa6, 0x4f, 0x5a, 0xc5, 0x2a, 0x43, 0x78, 0x6a, 0x35, 0x52, - 0x5e, 0xad, 0x9b, 0x10, 0xdf, 0x7a, 0x23, 0xfc, 0xfe, 0xb2, 0x66, 0x12, 0x46, 0x4e, 0xb3, 0x22, 0x02, 0x96, 0xca, - 0xb7, 0xa1, 0x7b, 0x1b, 0xcd, 0xd4, 0xc6, 0x71, 0x10, 0xce, 0x5d, 0x84, 0x3b, 0x98, 0xcd, 0x34, 0xe7, 0xca, 0x86, - 0x64, 0x5a, 0xef, 0x1b, 0x50, 0xcc, 0xf5, 0x3e, 0x6c, 0x20, 0x71, 0x5d, 0xf1, 0x54, 0x24, 0x08, 0x06, 0x6c, 0x0e, - 0xca, 0x9d, 0x2b, 0x1f, 0x02, 0x80, 0x9d, 0xad, 0x56, 0x1b, 0x44, 0xb7, 0x55, 0xff, 0x44, 0x61, 0x65, 0x14, 0xae, - 0x56, 0xd7, 0x12, 0x05, 0x46, 0xf3, 0xc5, 0x14, 0xf5, 0x2d, 0xc7, 0x3d, 0x79, 0x05, 0xad, 0x94, 0x22, 0x5a, 0x95, - 0x94, 0x26, 0x43, 0x9d, 0x66, 0xeb, 0xfb, 0x24, 0x1d, 0xb6, 0x7d, 0xba, 0xc1, 0xbd, 0x54, 0xa1, 0x11, 0xd3, 0xd5, - 0x92, 0x4f, 0xcd, 0xd0, 0x0c, 0x21, 0x14, 0xe5, 0xca, 0x8a, 0xd9, 0xdb, 0x66, 0x58, 0x1e, 0x1c, 0xe4, 0xce, 0x40, - 0xe7, 0x25, 0x9b, 0xf8, 0x29, 0x00, 0x91, 0x9c, 0xdf, 0x66, 0x4a, 0x77, 0xf9, 0xc9, 0x0a, 0xa1, 0x0d, 0xb3, 0xb4, - 0xd5, 0x05, 0x6b, 0x3c, 0xbe, 0x8e, 0x99, 0xf4, 0xca, 0x51, 0xb4, 0x35, 0x1e, 0x50, 0xb4, 0x34, 0xaa, 0x46, 0x28, - 0x28, 0x28, 0x8f, 0xc0, 0x13, 0xac, 0x0a, 0xad, 0xe9, 0x7e, 0x34, 0xa5, 0xe0, 0x08, 0xb6, 0x5a, 0x44, 0x69, 0x17, - 0xee, 0x19, 0x29, 0x62, 0x06, 0xde, 0x0e, 0x7b, 0xb1, 0xde, 0xbd, 0x66, 0x07, 0xcc, 0xa9, 0x18, 0x73, 0x31, 0xb3, - 0x75, 0xc5, 0xda, 0xb3, 0xe1, 0x8c, 0x6c, 0x1c, 0x6c, 0x1d, 0xdb, 0xa8, 0xff, 0xdd, 0x35, 0xa3, 0xbb, 0x32, 0xd7, - 0x6b, 0xa2, 0xb4, 0x94, 0xbe, 0xda, 0x1f, 0x68, 0x29, 0x33, 0x77, 0xcd, 0x7b, 0xe3, 0x4c, 0xed, 0x6a, 0x87, 0xc9, - 0x5e, 0xbb, 0x5b, 0xda, 0x7c, 0x96, 0x1a, 0xba, 0xda, 0xb1, 0x61, 0x44, 0x2a, 0x5f, 0xa4, 0x89, 0x01, 0x96, 0x21, - 0x4c, 0x0d, 0x1d, 0x5d, 0xb3, 0x34, 0xad, 0x4a, 0x7f, 0x0d, 0x5f, 0xcf, 0x0d, 0x5f, 0xcf, 0x2c, 0x5f, 0x07, 0x4e, - 0x01, 0x7c, 0x5d, 0x0f, 0x57, 0x75, 0xcf, 0x36, 0x4e, 0x67, 0xa6, 0x39, 0x7a, 0xae, 0xec, 0x68, 0x98, 0x6f, 0x61, - 0x21, 0x40, 0xa5, 0xe6, 0xf5, 0x31, 0x30, 0x4e, 0x18, 0x30, 0x00, 0xb5, 0x0b, 0x93, 0xba, 0x2e, 0x8a, 0x8f, 0x01, - 0xc2, 0x79, 0x41, 0x4b, 0xca, 0x3e, 0x79, 0x01, 0x4e, 0x3a, 0x67, 0x39, 0x20, 0xc4, 0x54, 0xf1, 0xaf, 0x52, 0xa2, - 0xec, 0xea, 0x98, 0x59, 0x5d, 0x6e, 0x57, 0x07, 0x9c, 0xbe, 0x5a, 0x5d, 0x72, 0x37, 0xaf, 0x57, 0xcb, 0x63, 0xe5, - 0xf2, 0xaa, 0xfd, 0x5e, 0xad, 0x82, 0xb5, 0x12, 0xf0, 0xdf, 0x1b, 0x13, 0x45, 0x94, 0xa3, 0x03, 0x0f, 0x70, 0x31, - 0x03, 0x05, 0x85, 0x5e, 0x74, 0x29, 0xe2, 0x5e, 0x7d, 0xca, 0xc1, 0xa3, 0xdc, 0xf4, 0xba, 0xff, 0x29, 0x9f, 0xcd, - 0x41, 0x1b, 0x5b, 0x23, 0xe9, 0x09, 0x35, 0x13, 0x56, 0xf5, 0xc5, 0x96, 0xb2, 0x5a, 0x1f, 0x75, 0x1e, 0x6b, 0xd4, - 0x54, 0xda, 0xcb, 0x7b, 0xad, 0x62, 0x51, 0x16, 0x95, 0x8c, 0x63, 0x9b, 0x53, 0xe5, 0x74, 0xdd, 0x25, 0x63, 0x2b, - 0xde, 0x06, 0x4c, 0xf3, 0x61, 0x06, 0xbc, 0xce, 0x61, 0x3f, 0x96, 0xdc, 0xdd, 0xfd, 0x2f, 0x2a, 0xe4, 0x2c, 0x8b, - 0x35, 0xf4, 0x2d, 0x8b, 0xe2, 0x44, 0x1b, 0xd9, 0xf8, 0x64, 0xb7, 0x35, 0x5c, 0xd5, 0x19, 0x63, 0x71, 0x30, 0xc4, - 0x27, 0x9b, 0xaa, 0x23, 0x59, 0xce, 0x78, 0x42, 0x23, 0x9f, 0xcf, 0x69, 0xe6, 0x17, 0xe0, 0x55, 0x35, 0x7b, 0x3f, - 0x92, 0xc1, 0xf2, 0x5d, 0xdd, 0xbd, 0x1a, 0x9d, 0x14, 0xe0, 0xfd, 0xfa, 0x62, 0xd3, 0xf1, 0xfa, 0x2d, 0x15, 0xb9, - 0x52, 0x44, 0x4b, 0x9d, 0xf6, 0x8b, 0x4a, 0x2c, 0x7d, 0x11, 0xed, 0x6c, 0x5f, 0x99, 0x20, 0x7e, 0x3b, 0x7c, 0x1c, - 0x1e, 0xf9, 0x48, 0xb9, 0x85, 0xbf, 0x32, 0x07, 0xfe, 0xb9, 0x75, 0x0b, 0xbf, 0x20, 0xcf, 0xeb, 0x5e, 0xe1, 0x44, - 0x92, 0x17, 0xfd, 0x17, 0xd6, 0x62, 0xe6, 0x29, 0x1b, 0xdd, 0x06, 0x7e, 0xca, 0x64, 0x13, 0x42, 0x6f, 0x3e, 0x5e, - 0xea, 0x0a, 0x70, 0x29, 0x2a, 0x77, 0x76, 0x61, 0x6d, 0x3d, 0x2c, 0x25, 0xf1, 0xf7, 0x53, 0x26, 0xf7, 0x7d, 0x3c, - 0x23, 0x17, 0xf0, 0x63, 0x7f, 0x19, 0xbc, 0x8e, 0xe5, 0x34, 0x14, 0x71, 0x96, 0xf0, 0x59, 0x80, 0x1a, 0xbe, 0x8f, - 0xc2, 0x5c, 0xd9, 0x1b, 0x9f, 0xa3, 0x62, 0xff, 0x02, 0xdf, 0x48, 0xe2, 0xf7, 0xfd, 0xc6, 0x0c, 0xbf, 0x91, 0xe4, - 0xe2, 0x78, 0x7f, 0x79, 0x23, 0x8b, 0xde, 0x05, 0xbe, 0x29, 0x3d, 0xf6, 0xf8, 0x6b, 0x12, 0x20, 0xd2, 0xbb, 0x31, - 0xd0, 0x9c, 0xf2, 0x99, 0xf6, 0xdc, 0xfb, 0x08, 0x7f, 0x80, 0xb8, 0x8a, 0xa8, 0xb8, 0x8d, 0x09, 0xad, 0xec, 0x11, - 0x9f, 0x2b, 0x17, 0x81, 0x7f, 0x70, 0xe0, 0x94, 0x95, 0xaa, 0x02, 0x3e, 0x91, 0xa4, 0x66, 0x90, 0xe3, 0xf7, 0x2a, - 0x42, 0x73, 0x22, 0x03, 0x81, 0xec, 0x30, 0x81, 0xf5, 0x43, 0x9b, 0xa3, 0x29, 0x06, 0xda, 0xc3, 0x10, 0x32, 0x49, - 0x45, 0x2c, 0xb9, 0x18, 0x22, 0x57, 0xfd, 0xc0, 0x7f, 0x23, 0x17, 0x03, 0xef, 0x3f, 0xfd, 0xd3, 0x8f, 0xe3, 0x1f, - 0xc5, 0xf0, 0x02, 0xbf, 0x25, 0x87, 0xc7, 0x41, 0x3f, 0x0a, 0xf6, 0x9a, 0xcd, 0xd5, 0x8f, 0x87, 0x83, 0x7f, 0xc4, - 0xcd, 0x5f, 0x4e, 0x9a, 0x3f, 0x0c, 0xd1, 0x2a, 0xf8, 0xf1, 0xb0, 0x3f, 0x30, 0x4f, 0x83, 0x7f, 0xf4, 0x7e, 0xcc, - 0x87, 0x7f, 0xd6, 0x85, 0xfb, 0x08, 0x1d, 0x4e, 0xf0, 0x42, 0x92, 0xc3, 0x66, 0xb3, 0x77, 0x38, 0xc1, 0x73, 0x49, - 0x0e, 0xe1, 0xff, 0x4b, 0xf2, 0x8e, 0x4e, 0x5e, 0xdc, 0xcc, 0x83, 0x8b, 0xde, 0x6a, 0x7f, 0xf9, 0xb7, 0x02, 0x46, - 0x1d, 0xfc, 0xe3, 0xc7, 0x1f, 0x73, 0xff, 0x41, 0x8f, 0x1c, 0x0e, 0x1b, 0x28, 0x80, 0xd2, 0x3f, 0x13, 0xf5, 0x6f, - 0xd0, 0x8f, 0x06, 0xff, 0x30, 0x50, 0xf8, 0x0f, 0x7e, 0xbc, 0x38, 0xee, 0x91, 0xe1, 0x2a, 0xf0, 0x57, 0x0f, 0xd0, - 0x0a, 0xa1, 0xd5, 0x3e, 0xba, 0xc0, 0xfe, 0xc4, 0x47, 0x78, 0x22, 0xc9, 0xe1, 0x83, 0xc3, 0x09, 0xbe, 0x92, 0xe4, - 0xd0, 0x3f, 0x9c, 0xe0, 0x17, 0x92, 0x1c, 0xfe, 0x23, 0xe8, 0x47, 0xda, 0xc3, 0xb6, 0x52, 0xee, 0x8d, 0x15, 0x04, - 0x37, 0x62, 0x41, 0xe3, 0x95, 0x64, 0x32, 0xa5, 0x68, 0xff, 0x90, 0xe1, 0x33, 0x85, 0xa6, 0x40, 0x82, 0x13, 0x06, - 0x6c, 0xbb, 0x60, 0x79, 0x0e, 0x9b, 0x0d, 0x34, 0xb3, 0x1f, 0x09, 0xac, 0xfd, 0x00, 0x79, 0x24, 0xf1, 0x55, 0x9c, - 0x2e, 0x68, 0x1e, 0xd1, 0x02, 0xe1, 0x11, 0x39, 0x93, 0x41, 0x1b, 0xe1, 0x77, 0x12, 0x7e, 0x74, 0x10, 0x3e, 0x33, - 0x01, 0x4c, 0x38, 0xc8, 0x9a, 0xa8, 0x32, 0xae, 0x35, 0x16, 0x1f, 0xe1, 0xf9, 0x96, 0x4a, 0x39, 0x05, 0xef, 0x02, - 0xc2, 0xe3, 0x5a, 0xb8, 0x13, 0x5f, 0x13, 0x4b, 0x12, 0xef, 0x05, 0xa5, 0xdf, 0xc5, 0xe9, 0x47, 0x2a, 0x82, 0x1b, - 0xdc, 0xee, 0x7c, 0x8e, 0x95, 0x0b, 0x7a, 0xaf, 0x8d, 0xba, 0x65, 0xac, 0xea, 0x54, 0xea, 0x18, 0x01, 0x08, 0xd9, - 0xba, 0x2f, 0x06, 0x76, 0x7c, 0x4f, 0x6c, 0x38, 0xac, 0x44, 0x7c, 0xed, 0xa3, 0x7a, 0x5c, 0x94, 0x65, 0x57, 0x71, - 0xca, 0x12, 0x4f, 0xd2, 0xd9, 0x3c, 0x8d, 0x25, 0xf5, 0xcc, 0x7a, 0xbd, 0x18, 0x06, 0xf2, 0x4b, 0x95, 0x21, 0x71, - 0x0c, 0xce, 0xc4, 0x06, 0x9c, 0xe0, 0xac, 0x04, 0x10, 0x9d, 0x32, 0x6a, 0xc7, 0xeb, 0x2a, 0xf8, 0xb5, 0x1e, 0xdf, - 0x6b, 0xb6, 0xc1, 0x11, 0x36, 0x54, 0xe2, 0x39, 0xc7, 0x19, 0x01, 0x21, 0xda, 0xe9, 0xfb, 0xc7, 0xf9, 0xd5, 0xa4, - 0xe7, 0x43, 0x6c, 0x86, 0x93, 0xb7, 0xca, 0x2f, 0x04, 0x0d, 0xa6, 0xa4, 0xd5, 0x9d, 0x1e, 0xd3, 0xee, 0xb4, 0xd1, - 0xb0, 0x3a, 0x74, 0x4a, 0xc4, 0x60, 0xaa, 0xbb, 0xc7, 0x38, 0xc1, 0x0b, 0xd2, 0x6c, 0xe3, 0x09, 0x69, 0xa9, 0x2e, - 0xdd, 0xc9, 0x71, 0x6a, 0xa6, 0x39, 0x38, 0x08, 0x78, 0x98, 0xc6, 0xb9, 0xfc, 0x12, 0x8c, 0x7d, 0x32, 0xc1, 0x09, - 0xe1, 0x21, 0xbd, 0xa1, 0xa3, 0x20, 0x45, 0x38, 0x31, 0x9c, 0x06, 0x75, 0xd1, 0x84, 0x38, 0xcd, 0xc0, 0x88, 0x20, - 0x6f, 0xfb, 0xc9, 0xa0, 0x3d, 0x24, 0x84, 0xf8, 0x7b, 0xcd, 0xa6, 0xdf, 0xe7, 0x64, 0x21, 0x23, 0x28, 0x71, 0x54, - 0x65, 0x32, 0x87, 0xa2, 0x8e, 0x53, 0x14, 0xbc, 0x90, 0xa1, 0xa4, 0xb9, 0x0c, 0xa0, 0x18, 0xcc, 0xff, 0xdc, 0x12, - 0xb6, 0x7f, 0x7c, 0xe8, 0x37, 0xa0, 0x54, 0x11, 0x27, 0xc2, 0x9c, 0x5c, 0xa2, 0x28, 0x19, 0x1c, 0x0d, 0x5d, 0xfe, - 0xaf, 0x0a, 0x61, 0xf2, 0xcb, 0x7e, 0x32, 0x68, 0xa9, 0xc9, 0x7b, 0x7e, 0x3f, 0xe0, 0x24, 0xd7, 0x0a, 0x5a, 0x3f, - 0x8f, 0xde, 0xaa, 0xa5, 0xa2, 0xc8, 0x00, 0x67, 0xe6, 0x5d, 0x90, 0x66, 0x27, 0x0a, 0x16, 0xee, 0x22, 0x9a, 0x30, - 0x99, 0xc1, 0x02, 0x8e, 0x09, 0xb4, 0xc7, 0x9c, 0xc0, 0x8c, 0x55, 0xb7, 0xcb, 0xc8, 0x3c, 0x3f, 0xf0, 0x1f, 0xf4, - 0xaf, 0x64, 0x34, 0x91, 0x7a, 0xfa, 0x2b, 0xb9, 0x5a, 0xc1, 0xff, 0x13, 0xd9, 0xe7, 0xe4, 0x52, 0x15, 0x2d, 0x4c, - 0xd1, 0x1c, 0x8a, 0xde, 0x46, 0x00, 0x2a, 0xce, 0x4b, 0x25, 0x4b, 0xef, 0xc9, 0x15, 0x51, 0xb0, 0x1f, 0x1c, 0x88, - 0xc1, 0xb4, 0xd1, 0x1e, 0x82, 0x7f, 0x5f, 0xc8, 0xfc, 0x3b, 0x26, 0xa7, 0x81, 0x7f, 0xd8, 0xf3, 0x51, 0xdf, 0xf7, - 0x60, 0x6b, 0xbb, 0x59, 0x83, 0x68, 0x0c, 0xa7, 0x8d, 0x37, 0x32, 0x5a, 0xf4, 0x48, 0xab, 0x1f, 0x30, 0xe3, 0xcf, - 0x43, 0x38, 0x35, 0x8c, 0xb3, 0x85, 0x17, 0xa8, 0x21, 0x65, 0xc3, 0x3e, 0x2f, 0x50, 0x63, 0xd6, 0xb8, 0x42, 0x51, - 0xda, 0x98, 0x35, 0x82, 0x05, 0x21, 0xa4, 0xd9, 0x29, 0xbb, 0x59, 0xe9, 0x37, 0x45, 0xd1, 0x95, 0x75, 0x76, 0x0e, - 0xd4, 0x71, 0xc8, 0x1a, 0x81, 0x18, 0xd0, 0xe1, 0x6a, 0xe5, 0x1f, 0xf7, 0x7b, 0x3e, 0x6a, 0x04, 0x96, 0xd0, 0x0e, - 0x2d, 0xa5, 0x21, 0x84, 0xd9, 0xb0, 0x30, 0xa1, 0xa4, 0x97, 0xb5, 0xb0, 0xd1, 0xb2, 0x3a, 0xec, 0x0e, 0x0f, 0xa0, - 0x45, 0x69, 0xc7, 0x68, 0x7d, 0x75, 0x0e, 0xcb, 0xb4, 0xc4, 0x9c, 0x91, 0x16, 0xe6, 0xc4, 0xfa, 0xae, 0xa7, 0x44, - 0x56, 0x04, 0x9f, 0x92, 0xaa, 0x39, 0x1e, 0xc4, 0x38, 0x19, 0x92, 0xd7, 0xda, 0x1e, 0xe9, 0x5a, 0xbf, 0x38, 0x4d, - 0xc9, 0xcb, 0xb5, 0xe8, 0x6d, 0x0c, 0xb1, 0x95, 0xeb, 0x70, 0xb4, 0x10, 0x82, 0x66, 0xf2, 0x0d, 0x4f, 0x8c, 0x9a, - 0x46, 0x53, 0xb0, 0x94, 0x20, 0x2c, 0x8b, 0x41, 0x47, 0xeb, 0xd8, 0x93, 0xb1, 0xd8, 0xa8, 0x9e, 0x90, 0x85, 0x56, - 0x9f, 0x54, 0xb0, 0xb6, 0x3b, 0x31, 0x76, 0x71, 0x80, 0xf0, 0xc2, 0x44, 0x71, 0x83, 0x30, 0x0c, 0x27, 0xe1, 0x08, - 0xaa, 0x61, 0x82, 0x1c, 0x15, 0xea, 0x1c, 0x05, 0x39, 0xb9, 0x0e, 0x33, 0x7a, 0xa3, 0x66, 0x0d, 0x50, 0x25, 0x99, - 0xed, 0xf1, 0x3a, 0x9e, 0x76, 0x15, 0xbb, 0xc9, 0xc3, 0x8c, 0x27, 0x14, 0xd0, 0x03, 0x71, 0x7b, 0x53, 0x34, 0x8d, - 0x73, 0x37, 0x3e, 0x55, 0xc1, 0x37, 0x70, 0x9d, 0xd7, 0x13, 0xf0, 0xf8, 0x2a, 0x5d, 0xab, 0x6c, 0xac, 0xdd, 0xe0, - 0x08, 0xb1, 0x71, 0x30, 0x09, 0x21, 0xae, 0xa7, 0x48, 0x48, 0x82, 0x29, 0x37, 0x71, 0x89, 0x6a, 0x56, 0x8e, 0x79, - 0x45, 0x92, 0x01, 0x6f, 0x34, 0x94, 0x17, 0x7a, 0xa1, 0x49, 0x62, 0x82, 0xf0, 0x55, 0x79, 0xb6, 0x6c, 0xbb, 0xb7, - 0x92, 0xd4, 0xa7, 0x0a, 0xae, 0xea, 0xee, 0xdc, 0x86, 0x94, 0x48, 0x79, 0x0a, 0x65, 0x30, 0x43, 0xf8, 0x19, 0x39, - 0x0c, 0x06, 0x61, 0xff, 0x2f, 0x43, 0xd4, 0x0f, 0xc2, 0x3f, 0xa3, 0x43, 0xcd, 0x39, 0xae, 0x50, 0x37, 0xd5, 0x73, - 0x2c, 0x55, 0xfc, 0xb2, 0x8d, 0x95, 0x27, 0x31, 0xca, 0x70, 0x16, 0xcf, 0x68, 0xf4, 0x0c, 0x0e, 0xb9, 0x25, 0x9c, - 0xb7, 0x12, 0x03, 0x25, 0x45, 0xcf, 0x0c, 0x2f, 0x09, 0xfd, 0xfe, 0x2b, 0x59, 0x3e, 0xf5, 0xfd, 0xfe, 0xf3, 0xea, - 0xe9, 0x2f, 0x7e, 0xff, 0x17, 0x19, 0xfd, 0x5c, 0x18, 0x6f, 0x77, 0x6d, 0x8e, 0xc7, 0x76, 0x8e, 0x42, 0x6f, 0x8d, - 0x83, 0xbb, 0x05, 0xda, 0x74, 0x74, 0x4c, 0x50, 0xc1, 0xc6, 0x25, 0x33, 0xca, 0x43, 0x19, 0x4f, 0x00, 0xa9, 0xce, - 0x1e, 0xe4, 0x6e, 0x5c, 0xbf, 0x5a, 0x31, 0x90, 0x8a, 0xa5, 0x57, 0x40, 0xe6, 0xa4, 0xd7, 0x42, 0xcb, 0x5a, 0x5b, - 0xa5, 0x33, 0xd5, 0xe3, 0xe8, 0x25, 0x9f, 0xbe, 0x22, 0xad, 0xee, 0xd5, 0xf1, 0xa4, 0x7b, 0xd5, 0x68, 0xa0, 0xdc, - 0x92, 0xd6, 0x62, 0x70, 0x35, 0xc4, 0x5f, 0x83, 0x53, 0xcf, 0xa5, 0x25, 0x5c, 0x5b, 0x5e, 0xc7, 0x2c, 0xaf, 0xd1, - 0xc8, 0x0a, 0xd4, 0x75, 0xba, 0x4e, 0x74, 0xd7, 0xa2, 0xd0, 0x38, 0x59, 0x27, 0xb5, 0xa7, 0x48, 0x95, 0x40, 0x32, - 0x14, 0x21, 0xe4, 0x46, 0xa2, 0xad, 0xa3, 0xc2, 0x98, 0xd0, 0x5d, 0x9d, 0x59, 0x60, 0x9f, 0x5a, 0x4a, 0x04, 0x80, - 0x05, 0xe8, 0x5a, 0x7a, 0x82, 0x67, 0x78, 0xd1, 0x68, 0x2b, 0x32, 0x6f, 0xb6, 0xbb, 0xf5, 0xb1, 0x9e, 0x54, 0x63, - 0xe1, 0x45, 0x83, 0xcc, 0x4a, 0x2c, 0x15, 0x59, 0xa3, 0x51, 0xd4, 0x83, 0x9d, 0xf6, 0xe4, 0xd6, 0x02, 0x10, 0x37, - 0xeb, 0x49, 0x19, 0x56, 0xc2, 0x56, 0x32, 0x95, 0x85, 0x2c, 0xcb, 0xa8, 0x00, 0x29, 0x4a, 0x24, 0x66, 0x45, 0x51, - 0x49, 0x76, 0x10, 0xa3, 0x98, 0x12, 0x01, 0x9c, 0x47, 0xd9, 0x5d, 0x38, 0xc3, 0x1c, 0x4f, 0x15, 0xdf, 0x20, 0x84, - 0x9c, 0xd9, 0x74, 0x16, 0xa9, 0x78, 0x50, 0x4a, 0x98, 0x23, 0x93, 0x72, 0x42, 0xc3, 0xf3, 0xfd, 0x53, 0x7e, 0xa7, - 0x4d, 0x36, 0x60, 0xc3, 0x48, 0x35, 0x4b, 0x0d, 0xe7, 0x8a, 0xc9, 0x87, 0x40, 0xa2, 0x32, 0x3a, 0x12, 0x2a, 0x06, - 0xf8, 0x9c, 0x09, 0xaa, 0x74, 0xf0, 0x7d, 0x6b, 0xf7, 0xa5, 0x75, 0x05, 0x32, 0x75, 0xbd, 0x37, 0x80, 0xc8, 0x18, - 0x9c, 0x3b, 0x19, 0xd9, 0x68, 0x76, 0xbe, 0x7f, 0xf2, 0x76, 0x9b, 0x0d, 0xbc, 0x5a, 0x19, 0xeb, 0x57, 0xe9, 0x36, - 0x38, 0xae, 0x20, 0x4d, 0xcd, 0x8f, 0x28, 0x48, 0x95, 0x8a, 0x14, 0x07, 0x02, 0xa8, 0xe8, 0x7c, 0xff, 0xe4, 0x7d, - 0x20, 0x94, 0x6f, 0x09, 0x61, 0x77, 0xd9, 0x01, 0x27, 0xc1, 0x94, 0x50, 0xa4, 0xd7, 0x5e, 0xb2, 0x2e, 0xee, 0x08, - 0xf0, 0x68, 0xaa, 0x2a, 0xc1, 0x82, 0x18, 0xb0, 0x21, 0x49, 0x0d, 0x06, 0x48, 0x8a, 0x70, 0x5a, 0xb3, 0xcb, 0x08, - 0x6c, 0x80, 0x9a, 0xeb, 0x0c, 0x76, 0x22, 0xd4, 0xaa, 0x1f, 0xc2, 0xa9, 0x9a, 0x55, 0x16, 0x5a, 0x78, 0x3c, 0xdb, - 0xc8, 0x4a, 0xab, 0xcc, 0xd1, 0x6f, 0xc1, 0x76, 0xb2, 0x0f, 0x6f, 0x88, 0xb5, 0x24, 0x4c, 0xc1, 0x73, 0x9b, 0x3e, - 0x76, 0xbe, 0x7f, 0xf2, 0xda, 0x64, 0x90, 0xcd, 0x63, 0xcb, 0xef, 0x37, 0x4c, 0xcc, 0x93, 0xd7, 0x61, 0x55, 0xab, - 0x1a, 0x9f, 0xef, 0x9f, 0x7c, 0xd8, 0xd6, 0x0c, 0xca, 0x8b, 0x45, 0x65, 0xe3, 0x2b, 0xf8, 0x96, 0x34, 0x8d, 0x96, - 0x46, 0x38, 0x44, 0xac, 0xc0, 0x4a, 0x20, 0x45, 0x79, 0x51, 0xba, 0x46, 0x9e, 0xe3, 0x8c, 0xa8, 0x30, 0x50, 0x7d, - 0xd7, 0x8c, 0x9a, 0xc7, 0x78, 0x76, 0x36, 0xe2, 0x73, 0xba, 0x23, 0x36, 0x74, 0x83, 0x42, 0x36, 0x83, 0xd4, 0x19, - 0x05, 0x3a, 0xc3, 0x7b, 0x2d, 0xd4, 0xad, 0x8b, 0xaf, 0x4c, 0x11, 0x29, 0xaf, 0xc9, 0x16, 0x3c, 0x25, 0x2d, 0x9c, - 0x92, 0x16, 0x8e, 0x49, 0x3e, 0x68, 0x69, 0x01, 0xd1, 0x8d, 0xcb, 0x71, 0xb5, 0x98, 0x81, 0xac, 0x30, 0x73, 0x5a, - 0xb5, 0x00, 0x4e, 0xba, 0xb1, 0xf2, 0x3d, 0x2a, 0x99, 0x9e, 0x28, 0xb2, 0x78, 0x1f, 0x70, 0xcc, 0xd5, 0xc0, 0x67, - 0xec, 0x32, 0x85, 0xc4, 0x12, 0x58, 0x15, 0x96, 0x28, 0x2a, 0x9b, 0xb6, 0x4d, 0xd3, 0x38, 0x54, 0xfb, 0xc4, 0x71, - 0x1c, 0x02, 0xe7, 0xc6, 0xb1, 0xc9, 0xc3, 0xc9, 0x37, 0xbb, 0x3c, 0x3e, 0x38, 0x08, 0x74, 0xa7, 0x2f, 0x65, 0xc0, - 0x6d, 0x7d, 0x15, 0xb9, 0xfb, 0x56, 0xf3, 0x8a, 0x04, 0x29, 0xf8, 0x1b, 0x8d, 0x74, 0x58, 0x40, 0x18, 0x3a, 0x88, - 0xeb, 0x18, 0xb4, 0xc0, 0x2b, 0x5d, 0xaf, 0xbe, 0xfc, 0x46, 0xa3, 0x8c, 0xd2, 0xd6, 0xb1, 0x75, 0x83, 0xb3, 0xe2, - 0x2a, 0x28, 0x53, 0x7f, 0x5a, 0x1b, 0xf9, 0x52, 0x16, 0x04, 0xc4, 0x5c, 0x9a, 0x65, 0x76, 0x31, 0xce, 0x91, 0x60, - 0xd0, 0xee, 0x4b, 0x93, 0xb5, 0x80, 0x55, 0x76, 0x95, 0x69, 0x64, 0xd9, 0x59, 0x07, 0x45, 0xb6, 0x11, 0x44, 0xa5, - 0xa0, 0x51, 0xa3, 0x30, 0xe4, 0xfd, 0x7e, 0x33, 0xe7, 0x12, 0xe7, 0xc8, 0x38, 0xb9, 0x14, 0x14, 0x0a, 0x59, 0x9d, - 0x12, 0x29, 0x2f, 0xc9, 0x7c, 0x37, 0xc9, 0x9f, 0x38, 0x24, 0xff, 0x8c, 0x50, 0x87, 0xfc, 0xb5, 0x8b, 0x23, 0xe4, - 0xc6, 0xb9, 0x90, 0xdb, 0xaa, 0xd3, 0x39, 0x01, 0x27, 0x5a, 0x1d, 0xa3, 0xb5, 0xb0, 0xe2, 0x0e, 0x86, 0xe2, 0x9e, - 0x10, 0xe5, 0x86, 0xc4, 0x36, 0x06, 0x1c, 0x54, 0x41, 0x35, 0x98, 0x7a, 0x9b, 0x4f, 0xcf, 0xe5, 0x80, 0x27, 0x1f, - 0xee, 0x8e, 0x87, 0x9e, 0xce, 0x37, 0x4f, 0xae, 0x93, 0xfb, 0x09, 0xab, 0x76, 0x0e, 0x6e, 0x3d, 0x13, 0x14, 0xe6, - 0x2f, 0xe3, 0xd8, 0x75, 0xe6, 0xb3, 0x76, 0x08, 0xad, 0xfc, 0x03, 0x68, 0xdb, 0x6d, 0xd5, 0x82, 0x3a, 0xc3, 0x02, - 0x3f, 0xd2, 0x19, 0xa8, 0xb1, 0xd8, 0xc1, 0x3e, 0x4e, 0x54, 0x03, 0x9a, 0x25, 0xdb, 0xab, 0x9f, 0x15, 0x86, 0x4c, - 0x34, 0x68, 0x68, 0x09, 0xfc, 0x4f, 0x93, 0x3c, 0xd0, 0x8d, 0x92, 0x0b, 0x80, 0xa0, 0xb9, 0xc2, 0x53, 0x85, 0x30, - 0xdf, 0xaf, 0xbc, 0xef, 0x2f, 0xf7, 0x08, 0x99, 0x57, 0xde, 0xc7, 0x77, 0x55, 0xea, 0x15, 0x90, 0x05, 0x8a, 0xc0, - 0x7c, 0x2c, 0x0b, 0x74, 0xf8, 0xf2, 0xcc, 0x36, 0x57, 0x26, 0x64, 0x58, 0x69, 0xdc, 0x4e, 0x68, 0x53, 0xb9, 0xe5, - 0x74, 0xbd, 0x45, 0xc3, 0x5a, 0xed, 0x3e, 0xd4, 0xbe, 0x97, 0x0a, 0x46, 0x78, 0x7e, 0xaf, 0x5a, 0xdb, 0x71, 0x8b, - 0x8f, 0xeb, 0xf9, 0x2b, 0x6b, 0x9b, 0x12, 0xb2, 0x2c, 0xa7, 0x42, 0x3e, 0xa3, 0x63, 0x2e, 0x20, 0x66, 0x51, 0xe2, - 0x04, 0x15, 0xfb, 0x8e, 0xdf, 0x4e, 0xad, 0xcf, 0x09, 0x14, 0xac, 0x2d, 0x50, 0xfd, 0xfa, 0xa8, 0x82, 0xd6, 0xe7, - 0xeb, 0xbd, 0xe6, 0x07, 0x07, 0x1f, 0x2a, 0x34, 0x19, 0x28, 0x15, 0x14, 0x0e, 0xd3, 0xd2, 0x2a, 0x8d, 0x89, 0xe4, - 0xee, 0x07, 0xa5, 0x13, 0xc0, 0x32, 0x0c, 0x97, 0xf7, 0xbc, 0x24, 0xb2, 0x98, 0xac, 0xb3, 0x78, 0xe3, 0x9c, 0x60, - 0xae, 0xe1, 0x02, 0x1c, 0x1e, 0x4c, 0x6d, 0xed, 0x2d, 0xca, 0xab, 0x64, 0xd8, 0x12, 0x86, 0x53, 0x40, 0x56, 0xa0, - 0xcc, 0x10, 0x87, 0x02, 0xb7, 0x9a, 0x25, 0xa7, 0xa0, 0x57, 0x4e, 0x71, 0x1e, 0x4e, 0x21, 0xfd, 0xb5, 0x76, 0x64, - 0x11, 0xc2, 0x3a, 0x31, 0xc7, 0x49, 0x25, 0x38, 0x79, 0xb9, 0xcd, 0xa5, 0x6c, 0x89, 0x9a, 0x2a, 0xa9, 0xa3, 0x5a, - 0xa0, 0xb2, 0x43, 0x78, 0x15, 0x30, 0xa3, 0xb8, 0xd9, 0xb8, 0x19, 0x30, 0xe0, 0x67, 0x32, 0xd0, 0xc1, 0x28, 0x90, - 0x19, 0x3c, 0x5c, 0x04, 0xb5, 0xa9, 0xbb, 0x5c, 0x75, 0xc3, 0x06, 0x71, 0x53, 0x17, 0x4d, 0x5c, 0xc5, 0xf5, 0x4e, - 0x2b, 0x5e, 0x3a, 0xd6, 0x19, 0xd4, 0xd2, 0x72, 0xc1, 0x2a, 0x91, 0xc4, 0x59, 0xfe, 0x58, 0x27, 0x45, 0x97, 0x8d, - 0x30, 0x55, 0x60, 0xbc, 0x54, 0x7b, 0x40, 0x0b, 0xa0, 0xaf, 0xe5, 0x89, 0x74, 0x76, 0xd4, 0x3a, 0xb1, 0xd5, 0x9c, - 0x8e, 0xd4, 0x7f, 0x07, 0xa9, 0x2e, 0xeb, 0x67, 0xfe, 0xa5, 0x92, 0x85, 0x0c, 0xe7, 0x35, 0xc6, 0x9e, 0x29, 0xc6, - 0x8e, 0x40, 0x4f, 0xb3, 0x89, 0xdf, 0x7d, 0x93, 0xf1, 0xc2, 0x8c, 0x94, 0x33, 0x24, 0xf6, 0x75, 0x19, 0x2d, 0x77, - 0x7e, 0xaf, 0xed, 0x46, 0xc4, 0x08, 0x64, 0x01, 0x61, 0xc3, 0xd9, 0x33, 0x84, 0xf3, 0x46, 0xa3, 0x9b, 0x1f, 0xd3, - 0xca, 0x49, 0x52, 0xc1, 0xc8, 0x20, 0xa0, 0x0b, 0x04, 0x5f, 0x93, 0xa1, 0x10, 0xf2, 0xb7, 0x99, 0xd9, 0x39, 0xf8, - 0xda, 0x4f, 0xde, 0x05, 0x2e, 0x57, 0x73, 0xdb, 0x96, 0x41, 0x53, 0x58, 0x4f, 0x50, 0x05, 0x5c, 0xbe, 0xbe, 0x3b, - 0xc1, 0x03, 0xe0, 0xde, 0x6b, 0x63, 0x48, 0x45, 0x43, 0x5d, 0xa9, 0x59, 0x42, 0x79, 0xfa, 0xba, 0xa8, 0xca, 0x4a, - 0x74, 0x27, 0xeb, 0xca, 0xca, 0x98, 0x95, 0x24, 0x2f, 0x8a, 0x9c, 0x56, 0xe1, 0xfd, 0xb5, 0xf4, 0x4b, 0x25, 0x5c, - 0x36, 0xbd, 0xed, 0xa7, 0x73, 0x22, 0xb1, 0x43, 0xa8, 0x5f, 0xef, 0x8a, 0x7d, 0x54, 0x60, 0xc2, 0xb9, 0x36, 0x42, - 0xf1, 0xe7, 0x6d, 0x42, 0x11, 0x67, 0xe6, 0xc8, 0x2b, 0x81, 0xd8, 0xbe, 0x87, 0x40, 0x34, 0x6e, 0x76, 0x2b, 0x13, - 0x41, 0x1d, 0xa9, 0xc9, 0xc4, 0xfa, 0x96, 0x92, 0x0c, 0x33, 0xb3, 0x1b, 0xbd, 0xce, 0x6a, 0xc5, 0x06, 0x2d, 0x70, - 0x23, 0xf9, 0x3e, 0xfc, 0x6c, 0xeb, 0x9f, 0x0e, 0x27, 0xd6, 0x6e, 0xe0, 0x80, 0x95, 0x26, 0x0b, 0x0a, 0x21, 0xc1, - 0x39, 0x50, 0x49, 0x59, 0x8a, 0xa6, 0x0d, 0x05, 0x19, 0x02, 0x27, 0xac, 0x0c, 0x33, 0x01, 0xc4, 0x4a, 0x56, 0x18, - 0x03, 0x32, 0xd8, 0x9a, 0xfb, 0x67, 0xcd, 0xcb, 0x4f, 0x6b, 0xa2, 0x35, 0xb9, 0xa2, 0xd5, 0x87, 0x5a, 0xbe, 0x81, - 0x81, 0xc0, 0xe8, 0x87, 0x7b, 0xca, 0x04, 0xad, 0x44, 0x39, 0x72, 0xe5, 0x10, 0x6e, 0x81, 0x13, 0x6d, 0xef, 0x83, - 0x8e, 0xf0, 0x6e, 0x91, 0x26, 0x98, 0x3b, 0x74, 0xfd, 0x92, 0xc8, 0x1a, 0x2b, 0x99, 0x12, 0x63, 0x29, 0xe1, 0x58, - 0x91, 0xa9, 0x24, 0xd9, 0xa0, 0x35, 0x04, 0x05, 0xb4, 0x9b, 0x1e, 0x67, 0x95, 0x09, 0x9c, 0x36, 0x1a, 0x28, 0xb6, - 0xb3, 0x4e, 0x07, 0xac, 0x91, 0x0e, 0x31, 0xc5, 0xa9, 0x36, 0x4c, 0xce, 0x0e, 0x0e, 0x82, 0xb8, 0x9a, 0x77, 0x90, - 0x0e, 0x11, 0xe6, 0xab, 0x55, 0xa0, 0xc0, 0x8a, 0xd1, 0x6a, 0x15, 0xbb, 0x60, 0xa9, 0x6a, 0xe8, 0x36, 0xef, 0x4b, - 0x32, 0x57, 0x02, 0x70, 0x0e, 0x10, 0x36, 0x48, 0x10, 0x1b, 0xf7, 0x5e, 0x0c, 0xee, 0xa8, 0x46, 0x36, 0x48, 0x1b, - 0xed, 0xa1, 0xc3, 0xb8, 0x06, 0xe9, 0x90, 0xc4, 0x05, 0x3f, 0x38, 0xd8, 0xcb, 0x8d, 0x88, 0xfc, 0x09, 0x44, 0xd9, - 0x4f, 0x4a, 0xb2, 0xe8, 0x01, 0xdd, 0xdd, 0x58, 0x77, 0x06, 0x94, 0x14, 0x65, 0xb6, 0xd5, 0xb6, 0xab, 0x65, 0x41, - 0x94, 0x8d, 0xb0, 0x09, 0x06, 0xf7, 0xc1, 0xb2, 0x2f, 0xc9, 0xfc, 0x95, 0x2c, 0x73, 0xac, 0x7f, 0xde, 0x9a, 0x59, - 0x1d, 0x86, 0x61, 0x2c, 0x26, 0x2a, 0x96, 0x61, 0xc3, 0xb0, 0x8a, 0xf8, 0x8f, 0x0c, 0x98, 0xce, 0xc4, 0x83, 0x72, - 0xae, 0x21, 0xd1, 0xe0, 0x5b, 0xd5, 0xc6, 0xde, 0x25, 0xf9, 0x69, 0xab, 0x97, 0x41, 0x43, 0xf2, 0xfc, 0xb7, 0x42, - 0xf2, 0xd0, 0x40, 0xa2, 0xc9, 0x63, 0x0d, 0x67, 0x3b, 0x70, 0xf1, 0x93, 0x5c, 0xc3, 0xd9, 0x6e, 0xdc, 0x5a, 0x4c, - 0xfd, 0xb2, 0x0b, 0x3e, 0x87, 0x37, 0x68, 0x40, 0xab, 0x02, 0x07, 0xca, 0x47, 0xeb, 0xba, 0x97, 0x66, 0xa5, 0x20, - 0x4c, 0x25, 0x09, 0x58, 0xfd, 0x00, 0x54, 0xda, 0xa8, 0x63, 0xf8, 0xb2, 0x68, 0x8e, 0x1c, 0x97, 0x40, 0x3d, 0x75, - 0x05, 0xc8, 0xc9, 0x78, 0xdb, 0xe7, 0x07, 0x07, 0x60, 0x1b, 0x80, 0x12, 0x17, 0x8e, 0xe2, 0xb9, 0x5c, 0x08, 0x50, - 0xa5, 0x72, 0xfb, 0x1b, 0x8a, 0xe1, 0x16, 0x88, 0x2a, 0x83, 0x1f, 0x50, 0x30, 0x8f, 0xf3, 0x9c, 0x5d, 0xe9, 0x32, - 0xf3, 0x1b, 0x73, 0x62, 0x49, 0x39, 0xd7, 0x3a, 0x61, 0x86, 0xba, 0x99, 0xa1, 0xd3, 0x3a, 0xda, 0x5e, 0x5c, 0xd1, - 0x4c, 0xbe, 0x62, 0xb9, 0xa4, 0x19, 0x2c, 0xbf, 0xa2, 0x38, 0x58, 0x51, 0x8e, 0xe0, 0xc0, 0xd6, 0x7a, 0xc5, 0x49, - 0x72, 0x67, 0x17, 0x59, 0xd7, 0x81, 0xa6, 0x71, 0x96, 0xa4, 0x7a, 0x12, 0x37, 0x9f, 0xd1, 0xe6, 0x70, 0x96, 0x2d, - 0xdd, 0x7c, 0x9a, 0x4a, 0xd9, 0x50, 0xdc, 0x3d, 0x60, 0xc4, 0x4a, 0x02, 0x2b, 0x3d, 0xef, 0xd4, 0x5a, 0x20, 0xe2, - 0xbd, 0x63, 0x13, 0xdc, 0x95, 0x60, 0xe9, 0x70, 0xd4, 0xb0, 0x0e, 0xa7, 0xa5, 0x9b, 0x2f, 0xb7, 0x5e, 0x69, 0xdb, - 0x26, 0x1c, 0x14, 0x9d, 0x3c, 0xde, 0x6d, 0x59, 0xbd, 0xb6, 0x92, 0xc3, 0x4a, 0x0b, 0x76, 0x5f, 0xc6, 0x8c, 0x96, - 0x96, 0xbc, 0x90, 0x3d, 0x8a, 0xfb, 0x92, 0x3c, 0x87, 0x3b, 0x43, 0x2f, 0xe5, 0x2c, 0x5d, 0xbb, 0x1a, 0xd3, 0xdd, - 0x2f, 0xb5, 0xff, 0x7d, 0x19, 0xbc, 0xc4, 0xef, 0x21, 0xb0, 0xfb, 0x55, 0xd5, 0x7c, 0x33, 0xa0, 0xfb, 0x55, 0x85, - 0xa0, 0xaf, 0xa2, 0x8d, 0x76, 0x4e, 0x20, 0xb7, 0x13, 0x3e, 0x0d, 0x5b, 0xbe, 0xd5, 0x96, 0x7e, 0xd6, 0x61, 0x24, - 0x9d, 0x69, 0xa9, 0xce, 0x03, 0xae, 0xf2, 0xd4, 0x20, 0x5f, 0xae, 0x6e, 0x21, 0x51, 0x93, 0x61, 0xa8, 0x75, 0xf8, - 0x5d, 0xdb, 0x63, 0x64, 0x4c, 0xa6, 0xed, 0x8c, 0xaf, 0x63, 0x21, 0xf7, 0xe1, 0x94, 0xf1, 0x8d, 0x7b, 0x78, 0x53, - 0x02, 0x1e, 0xb4, 0xfb, 0x4d, 0xe1, 0x18, 0xdb, 0xb9, 0xbe, 0x07, 0xe4, 0x8e, 0x4f, 0xb8, 0xd5, 0xdd, 0xea, 0x56, - 0xc6, 0xd7, 0x60, 0xff, 0x23, 0x3c, 0xb5, 0x97, 0xe3, 0xa8, 0xe1, 0xc0, 0x34, 0x5a, 0x16, 0xa5, 0x53, 0x80, 0x6b, - 0xe5, 0x4d, 0x20, 0xcc, 0x0b, 0x15, 0xe0, 0xfe, 0x01, 0x7f, 0x63, 0x58, 0xe2, 0xb8, 0xe4, 0x38, 0x27, 0xf7, 0xe5, - 0x88, 0x1a, 0xfc, 0x32, 0x7e, 0x0f, 0x74, 0xac, 0x28, 0xb4, 0xb0, 0x54, 0xf4, 0x9c, 0x9b, 0x85, 0xec, 0x4c, 0x4b, - 0xc5, 0xb4, 0x4c, 0xa9, 0x51, 0xd3, 0x6c, 0xc9, 0xe3, 0xb4, 0x56, 0xb6, 0x2c, 0x4f, 0x55, 0x6d, 0x5e, 0xb4, 0x03, - 0x8b, 0x55, 0x68, 0x71, 0xb5, 0x0a, 0xea, 0xa8, 0x26, 0xcc, 0x89, 0x64, 0x20, 0xcc, 0x9c, 0x8c, 0x8a, 0x9a, 0x66, - 0xad, 0xfb, 0x04, 0x68, 0x3d, 0xa1, 0xc8, 0xea, 0xe6, 0x35, 0x38, 0x5c, 0x17, 0x82, 0xee, 0xee, 0xfa, 0x14, 0xb0, - 0x5e, 0x5d, 0x39, 0x91, 0x83, 0xa1, 0x9f, 0xcb, 0x54, 0xd9, 0x2a, 0xa7, 0x75, 0x0b, 0x7e, 0xd1, 0x1d, 0xc9, 0xb2, - 0x06, 0x75, 0x9b, 0xf5, 0x4e, 0xb2, 0xd1, 0x73, 0xbe, 0x2b, 0xd9, 0xa8, 0xa6, 0xed, 0xee, 0xb5, 0xd0, 0xdd, 0x69, - 0xa9, 0x7a, 0xae, 0xed, 0x4d, 0x7e, 0xc3, 0x74, 0x6d, 0xa0, 0x4d, 0x8d, 0x66, 0xcb, 0x55, 0xce, 0x8a, 0x62, 0x5c, - 0x5e, 0x26, 0x50, 0xb9, 0x3b, 0x63, 0x4d, 0xff, 0xc6, 0x6a, 0x54, 0xd7, 0x71, 0x83, 0x1f, 0xc8, 0x24, 0xe5, 0x97, - 0x71, 0xfa, 0x1e, 0xe6, 0xab, 0x2a, 0x5f, 0xde, 0x26, 0x22, 0x96, 0xd4, 0x70, 0x97, 0x0a, 0x86, 0x1f, 0x1c, 0x18, - 0x7e, 0xd0, 0x7c, 0xba, 0xea, 0x8f, 0x97, 0xaf, 0xca, 0x01, 0xa2, 0x71, 0x61, 0x59, 0xc6, 0xb9, 0xdc, 0x3e, 0xc7, - 0x3a, 0x0b, 0x3b, 0x2f, 0x59, 0xd8, 0xb9, 0x0c, 0xd6, 0x87, 0x0a, 0x82, 0x6f, 0xb6, 0x8f, 0xb2, 0xc9, 0xd9, 0xbe, - 0xa9, 0x0e, 0xfe, 0x37, 0xd1, 0x9d, 0x7d, 0x1c, 0x2e, 0x77, 0x14, 0x1e, 0xa9, 0x74, 0x15, 0x0d, 0xf2, 0x3b, 0x48, - 0x3b, 0x90, 0xa4, 0xe7, 0xdc, 0x39, 0xa8, 0xe4, 0x94, 0x4d, 0x04, 0x0a, 0x46, 0x8b, 0x5c, 0xf2, 0x99, 0x19, 0x33, - 0x37, 0xd7, 0x8c, 0x54, 0x25, 0xb8, 0xa2, 0x55, 0xb4, 0x3d, 0xaa, 0x5f, 0xe4, 0x5a, 0x7e, 0x64, 0x59, 0x12, 0xe5, - 0xd8, 0x48, 0x91, 0x3c, 0xca, 0x0a, 0x62, 0x93, 0x8d, 0x37, 0xeb, 0xf0, 0x98, 0x65, 0x2c, 0x9f, 0x52, 0x11, 0x70, - 0xb4, 0xdc, 0x35, 0x19, 0x87, 0x80, 0x8c, 0x9e, 0x0c, 0x7f, 0x5b, 0x5d, 0xf8, 0x0b, 0x61, 0x34, 0xf0, 0x03, 0xcd, - 0xa8, 0x9c, 0xf2, 0x04, 0x12, 0x53, 0xc2, 0xa4, 0xbc, 0xd1, 0x74, 0x70, 0xb0, 0x17, 0xf8, 0xca, 0x2d, 0x01, 0x57, - 0xbf, 0xdd, 0x1a, 0xd4, 0x5f, 0xc2, 0xf5, 0x9c, 0x6a, 0x6a, 0x8a, 0x96, 0x74, 0xfd, 0x26, 0x8b, 0x0c, 0x3f, 0xd2, - 0x5b, 0x2c, 0x50, 0x51, 0x44, 0x1a, 0x6a, 0x7f, 0xcc, 0x68, 0x9a, 0xf8, 0xf8, 0x23, 0xbd, 0x8d, 0xca, 0xdb, 0xe2, - 0xea, 0x72, 0xb3, 0xda, 0x40, 0x9f, 0x5f, 0x67, 0x3e, 0xae, 0x26, 0x89, 0x96, 0x05, 0xe6, 0x82, 0x4d, 0x80, 0x38, - 0xff, 0x46, 0x6f, 0x23, 0x3d, 0x1e, 0x73, 0x2e, 0xeb, 0xa1, 0xa5, 0x45, 0x7d, 0xe8, 0x14, 0xbb, 0xdb, 0x60, 0x0c, - 0x8a, 0x81, 0xea, 0x3b, 0x24, 0xb5, 0x76, 0x95, 0x79, 0x88, 0x50, 0x71, 0xdf, 0xa5, 0xe0, 0x2f, 0x5c, 0xd1, 0x26, - 0x6b, 0xa9, 0xaf, 0x6b, 0x9d, 0x28, 0x74, 0xa8, 0x72, 0x3d, 0xce, 0x03, 0x61, 0x4f, 0x9d, 0xb9, 0x83, 0xe0, 0x38, - 0xc2, 0xbe, 0x90, 0x66, 0xd0, 0xe8, 0x5b, 0x9d, 0x12, 0x52, 0x45, 0x92, 0x5e, 0x57, 0xfd, 0xbc, 0xf3, 0x00, 0xf0, - 0x0e, 0x29, 0x2d, 0xb1, 0xba, 0x8e, 0x59, 0xd8, 0x74, 0xd1, 0xef, 0x24, 0x09, 0x96, 0x76, 0x09, 0x91, 0x70, 0xb1, - 0x28, 0x0b, 0xa0, 0x42, 0x43, 0x5f, 0x3a, 0x03, 0x90, 0x8d, 0x03, 0xb6, 0x21, 0x35, 0x33, 0x25, 0x35, 0x43, 0x07, - 0xe3, 0x3b, 0xa4, 0x24, 0x55, 0xc8, 0x50, 0x4a, 0xa4, 0x12, 0x7a, 0x66, 0x73, 0x0d, 0x09, 0xb9, 0x1b, 0x5a, 0x5e, - 0x9f, 0xd3, 0x7b, 0x9e, 0xd5, 0xc0, 0x0a, 0xd4, 0x38, 0xa8, 0x88, 0x60, 0x49, 0x54, 0x37, 0x28, 0xac, 0x3b, 0x47, - 0xd8, 0xfc, 0xd6, 0x80, 0x87, 0x76, 0x59, 0xc4, 0xa2, 0x24, 0x98, 0xa2, 0xa5, 0x08, 0xa6, 0x38, 0x83, 0x7c, 0x44, - 0x5e, 0x94, 0xf0, 0x53, 0x77, 0x37, 0x6a, 0xd9, 0xca, 0xdb, 0xaf, 0xf8, 0x81, 0x32, 0x2f, 0x21, 0x47, 0x13, 0x0b, - 0xcb, 0x53, 0x44, 0xa0, 0xee, 0xda, 0x39, 0xdb, 0xf6, 0x95, 0x49, 0xd1, 0x31, 0x80, 0x7d, 0x27, 0x83, 0xa5, 0xb3, - 0x0a, 0xf7, 0x2e, 0xb7, 0xb9, 0xf2, 0x67, 0x82, 0x7d, 0x55, 0x12, 0x69, 0x90, 0x93, 0x35, 0x89, 0x73, 0x77, 0xae, - 0xe5, 0xcf, 0x0b, 0x2a, 0x6e, 0xcf, 0x28, 0xe4, 0x3a, 0x73, 0xb8, 0xeb, 0x5b, 0x6d, 0x43, 0x95, 0xa7, 0xde, 0xcf, - 0x94, 0xb2, 0x52, 0xd4, 0x2f, 0x01, 0xae, 0x5f, 0x11, 0x2c, 0x54, 0xb4, 0xd1, 0x71, 0xc4, 0xe8, 0xd3, 0x42, 0x77, - 0x5e, 0x9e, 0xa4, 0x5d, 0x06, 0xfe, 0xb5, 0x0a, 0xd3, 0x26, 0x58, 0x80, 0xb9, 0x7b, 0x21, 0x75, 0x90, 0x0f, 0xd7, - 0xbd, 0x32, 0x50, 0x04, 0xe1, 0xbb, 0x6c, 0xf7, 0x52, 0xb7, 0x65, 0xcd, 0xee, 0x5e, 0x6a, 0x2d, 0xe8, 0xa7, 0x52, - 0x7e, 0xb0, 0x99, 0xa7, 0xbc, 0xbc, 0xcc, 0x8a, 0x02, 0x15, 0x00, 0xde, 0xf7, 0xdd, 0x20, 0xf8, 0xde, 0x24, 0x0d, - 0x86, 0x10, 0x8b, 0x3d, 0x4b, 0xb9, 0x65, 0xe2, 0xd5, 0xfc, 0xdf, 0x6f, 0xcc, 0xff, 0xbd, 0x73, 0xe5, 0x14, 0x4c, - 0xa3, 0x49, 0x46, 0x13, 0xcb, 0x3a, 0x91, 0x26, 0x40, 0xa5, 0xb7, 0xe5, 0x92, 0x7c, 0xbc, 0x88, 0x40, 0xe3, 0x5a, - 0x8e, 0x79, 0x26, 0x9b, 0xe3, 0x78, 0xc6, 0xd2, 0xdb, 0x68, 0xc1, 0x9a, 0x33, 0x9e, 0xf1, 0x7c, 0x1e, 0x8f, 0x28, - 0xce, 0x6f, 0x73, 0x49, 0x67, 0xcd, 0x05, 0xc3, 0x2f, 0x69, 0x7a, 0x45, 0x25, 0x1b, 0xc5, 0xd8, 0x3f, 0x11, 0x2c, - 0x4e, 0xbd, 0x37, 0xb1, 0x10, 0xfc, 0xda, 0xc7, 0xef, 0xf8, 0x25, 0x97, 0x1c, 0xbf, 0xbd, 0xb9, 0x9d, 0xd0, 0x0c, - 0x7f, 0xb8, 0x5c, 0x64, 0x72, 0x81, 0xf3, 0x38, 0xcb, 0x9b, 0x39, 0x15, 0x6c, 0xdc, 0x1d, 0xf1, 0x94, 0x8b, 0x26, - 0xa4, 0x6c, 0xcf, 0x68, 0x94, 0xb2, 0xc9, 0x54, 0x7a, 0x49, 0x2c, 0x3e, 0x76, 0x9b, 0xcd, 0xb9, 0x60, 0xb3, 0x58, - 0xdc, 0x36, 0x55, 0x8b, 0xe8, 0xb3, 0xd6, 0x51, 0xfc, 0xf9, 0xf8, 0x61, 0x57, 0x8a, 0x38, 0xcb, 0x19, 0x6c, 0x53, - 0x14, 0xa7, 0xa9, 0x77, 0xf4, 0xa8, 0x35, 0xcb, 0xf7, 0x74, 0x20, 0x2f, 0xce, 0x64, 0x71, 0x81, 0x3f, 0x02, 0xdc, - 0xe1, 0xa5, 0xcc, 0xf0, 0xe5, 0x42, 0x4a, 0x9e, 0x2d, 0x47, 0x0b, 0x91, 0x73, 0x11, 0xcd, 0x39, 0xcb, 0x24, 0x15, - 0xdd, 0x4b, 0x2e, 0x12, 0x2a, 0x9a, 0x22, 0x4e, 0xd8, 0x22, 0x8f, 0x1e, 0xce, 0x6f, 0xba, 0xa0, 0x59, 0x4c, 0x04, - 0x5f, 0x64, 0x89, 0x99, 0x8b, 0x65, 0x53, 0x2a, 0x98, 0x74, 0x2b, 0xd4, 0x2b, 0x4c, 0xa2, 0x94, 0x65, 0x34, 0x16, - 0xcd, 0x09, 0x74, 0x06, 0xb3, 0xa8, 0x95, 0xd0, 0x09, 0x16, 0x93, 0xcb, 0x38, 0x68, 0x77, 0x9e, 0x60, 0xfb, 0x37, - 0x7c, 0x84, 0xbc, 0xd6, 0xf6, 0xe2, 0x76, 0xab, 0xf5, 0x27, 0xd4, 0x5d, 0x9b, 0x45, 0x01, 0x14, 0xb5, 0xe7, 0x37, - 0x5e, 0xce, 0x21, 0xa7, 0x6d, 0x5b, 0xcf, 0xee, 0x3c, 0x4e, 0x20, 0x21, 0x38, 0xea, 0xcc, 0x6f, 0x0a, 0x58, 0x5d, - 0xa4, 0x93, 0x4c, 0xcd, 0x22, 0xcd, 0xd3, 0xf2, 0xb7, 0x42, 0xfc, 0x74, 0x3b, 0xc4, 0x1d, 0x0b, 0x71, 0x85, 0xf5, - 0x66, 0xb2, 0x10, 0x2a, 0xb6, 0x1a, 0xb5, 0x73, 0x0d, 0xc8, 0x94, 0x5f, 0x51, 0x61, 0xe1, 0x50, 0x0f, 0xbf, 0x19, - 0x8c, 0xce, 0x76, 0x30, 0x9e, 0x7e, 0x0a, 0x0c, 0x91, 0x25, 0xcb, 0xfa, 0xbe, 0xb6, 0x05, 0x9d, 0x75, 0xa7, 0x14, - 0xe8, 0x29, 0xea, 0xc0, 0xef, 0x6b, 0x96, 0xc8, 0xa9, 0xfe, 0xa9, 0xc8, 0xf9, 0x5a, 0xd7, 0x3d, 0x6a, 0xb5, 0xf4, - 0x73, 0xce, 0x7e, 0xa1, 0x51, 0x3b, 0x84, 0x06, 0xc5, 0x05, 0xfe, 0x5b, 0x79, 0x99, 0xb7, 0xce, 0x3d, 0xf1, 0x0f, - 0xee, 0x2d, 0x5f, 0x27, 0x49, 0xb1, 0xba, 0x11, 0x8d, 0x85, 0x95, 0x95, 0x5a, 0xf8, 0x80, 0xdb, 0x4e, 0x9d, 0x27, - 0xc2, 0x7a, 0xe5, 0x2d, 0x4e, 0xd6, 0xff, 0x41, 0xe7, 0x5d, 0x44, 0x10, 0xe9, 0x70, 0x92, 0x0d, 0x79, 0x37, 0xeb, - 0x91, 0x56, 0x37, 0x6b, 0x36, 0x51, 0xc0, 0x89, 0x18, 0x64, 0x26, 0x3d, 0x2f, 0x60, 0x7d, 0xae, 0x8c, 0xed, 0x1c, - 0x45, 0x1c, 0xae, 0x9a, 0xae, 0x56, 0x55, 0x18, 0x80, 0xa9, 0xeb, 0x1a, 0x7f, 0x93, 0xa6, 0x01, 0xce, 0x1d, 0x4e, - 0x9e, 0xd9, 0x17, 0xbb, 0x08, 0xcb, 0x2b, 0x52, 0x3e, 0x52, 0x98, 0x0b, 0xe7, 0xb1, 0x9c, 0x82, 0x97, 0xa2, 0x14, - 0x3f, 0x55, 0x12, 0x93, 0x7f, 0xe8, 0xa3, 0xbe, 0x28, 0x33, 0xdc, 0x20, 0x93, 0x4f, 0x14, 0x30, 0xca, 0x37, 0x92, - 0xc0, 0x88, 0xf8, 0x17, 0xa2, 0x6d, 0x3a, 0x6b, 0xd1, 0x8d, 0xef, 0x6b, 0xd1, 0xd1, 0x4c, 0x32, 0x95, 0xbb, 0x6d, - 0x23, 0x0e, 0xd3, 0x38, 0x3f, 0x1f, 0xe9, 0xbb, 0x92, 0x79, 0x75, 0x33, 0x20, 0x56, 0xd0, 0x6b, 0x23, 0x8d, 0x0a, - 0x65, 0x8f, 0x7e, 0x2f, 0x77, 0xda, 0x27, 0xe2, 0x2e, 0xfb, 0xa4, 0x5c, 0x78, 0xce, 0x17, 0x62, 0x04, 0xe1, 0x48, - 0x23, 0xf5, 0x36, 0x1d, 0x37, 0xbe, 0x52, 0x31, 0x7c, 0x2c, 0x9d, 0x4c, 0x50, 0x89, 0x99, 0xfb, 0x52, 0x09, 0xaa, - 0x42, 0x5e, 0xfa, 0xbe, 0x86, 0x11, 0x71, 0x76, 0x49, 0x20, 0xb3, 0x13, 0x95, 0xd4, 0x18, 0x64, 0xa4, 0x97, 0x85, - 0x8b, 0x8c, 0xfd, 0xbc, 0xa0, 0xe7, 0x0c, 0x74, 0x4d, 0x16, 0xb2, 0x44, 0xc5, 0x9a, 0x40, 0xf6, 0x35, 0xdb, 0x10, - 0xbc, 0x60, 0x89, 0xde, 0x98, 0x4c, 0x55, 0x9a, 0xdc, 0x26, 0xbf, 0xe9, 0x83, 0xbf, 0x18, 0xb4, 0x03, 0x86, 0x13, - 0x3e, 0x8b, 0x59, 0x16, 0x29, 0x97, 0x6f, 0x39, 0x58, 0x04, 0xad, 0x31, 0x4b, 0xa2, 0xcc, 0x6c, 0x4f, 0x1b, 0x85, - 0x3f, 0x71, 0x96, 0xa9, 0xae, 0x45, 0x97, 0x2b, 0x84, 0x6a, 0xf4, 0x11, 0x8b, 0xe0, 0x13, 0x2d, 0xd7, 0x38, 0xc2, - 0x6e, 0x75, 0x79, 0xed, 0xbc, 0xb6, 0x03, 0xad, 0xb5, 0x8d, 0xd2, 0x46, 0x00, 0x5f, 0x2f, 0xcd, 0xb9, 0x90, 0x41, - 0x30, 0xc5, 0x29, 0x22, 0xbd, 0xa9, 0x72, 0x76, 0x1d, 0xa7, 0xea, 0xbf, 0x7e, 0xb3, 0x1d, 0xb5, 0x4b, 0xf3, 0xbd, - 0x76, 0x1b, 0x58, 0x27, 0x47, 0x99, 0x1b, 0xa5, 0x6a, 0x19, 0xe5, 0x6f, 0xbd, 0xd4, 0xea, 0xb9, 0x5c, 0x2e, 0x36, - 0xc7, 0x4d, 0x8b, 0xaa, 0xa0, 0x06, 0x84, 0x0a, 0x16, 0xed, 0x98, 0x0a, 0x15, 0xd5, 0xba, 0x4b, 0x55, 0xf2, 0x42, - 0x8b, 0xe8, 0xf3, 0xfd, 0xa5, 0x30, 0x33, 0x16, 0x17, 0xcc, 0x3a, 0x99, 0xea, 0x24, 0x57, 0x18, 0x8c, 0x38, 0x7a, - 0xe8, 0xb6, 0x66, 0x1a, 0x96, 0x5b, 0x22, 0xb6, 0xd2, 0x6d, 0xa8, 0x1f, 0xa9, 0x20, 0x55, 0xb8, 0x6b, 0x63, 0x00, - 0xc8, 0xd5, 0xdb, 0x06, 0x18, 0x98, 0xad, 0xb9, 0xb4, 0x4b, 0x00, 0x6d, 0x6c, 0x4c, 0xe1, 0x22, 0xcd, 0xc5, 0xfe, - 0xf2, 0x1b, 0x59, 0x1c, 0x3a, 0x4d, 0xd5, 0x6f, 0x96, 0xc0, 0xff, 0x20, 0x01, 0x97, 0x5a, 0x29, 0x8d, 0xfc, 0xaf, - 0xdf, 0x9e, 0xbd, 0xf7, 0xf1, 0x25, 0x4f, 0x6e, 0x23, 0x5f, 0x8a, 0x05, 0xf5, 0x0b, 0x14, 0xca, 0x29, 0xcd, 0xca, - 0x97, 0xf1, 0xf0, 0x94, 0x86, 0x29, 0x9f, 0xe8, 0x4b, 0x99, 0xeb, 0x46, 0xf2, 0xe8, 0xe2, 0x58, 0xbd, 0x64, 0xaa, - 0x77, 0x2c, 0xf5, 0xeb, 0xbd, 0xa4, 0x80, 0x9f, 0x3d, 0x08, 0xa1, 0x1c, 0x1f, 0xca, 0xa9, 0x7a, 0x38, 0x83, 0x03, - 0xa3, 0x9e, 0xf6, 0x97, 0x1b, 0xc4, 0xd4, 0x87, 0x21, 0xa6, 0x3d, 0xbd, 0x84, 0x5c, 0xb5, 0xba, 0x88, 0x46, 0x17, - 0x17, 0xc5, 0xf1, 0x21, 0x8c, 0x75, 0x68, 0xc7, 0x05, 0x08, 0x6d, 0xff, 0x92, 0xc0, 0xe0, 0x65, 0x43, 0x82, 0xf4, - 0x60, 0x08, 0x98, 0x37, 0xe9, 0xc1, 0x22, 0x81, 0xc0, 0xa0, 0x77, 0x52, 0x96, 0xa8, 0x13, 0xab, 0x8b, 0x76, 0x41, - 0xa0, 0x1b, 0x56, 0x74, 0xaf, 0xbd, 0xa9, 0xd5, 0xfe, 0x5a, 0x90, 0x12, 0x17, 0xba, 0x0b, 0x04, 0xff, 0x2b, 0xc8, - 0x8e, 0x0f, 0x35, 0x1e, 0x2e, 0xdc, 0x57, 0x9b, 0xe8, 0xd7, 0x0e, 0x94, 0xd8, 0x1a, 0xe4, 0x12, 0x7f, 0x94, 0xf8, - 0xe3, 0x85, 0x6a, 0x6a, 0x85, 0x11, 0x68, 0x49, 0x20, 0xb4, 0x5b, 0x56, 0xeb, 0x18, 0xf1, 0x34, 0x8d, 0xe7, 0x39, - 0x8d, 0xec, 0x0f, 0x23, 0x97, 0x40, 0xbc, 0x6d, 0x2a, 0x02, 0x26, 0xbd, 0xe6, 0x14, 0xd4, 0x85, 0x4d, 0x2d, 0xe5, - 0x2a, 0x16, 0x41, 0xb3, 0x39, 0x6a, 0x5e, 0x4e, 0x50, 0x21, 0xa7, 0x4b, 0x57, 0xaa, 0x3d, 0x6e, 0xb5, 0xba, 0x90, - 0x0b, 0xd9, 0x8c, 0x53, 0x36, 0xc9, 0xa2, 0x94, 0x8e, 0x65, 0x21, 0xe1, 0x96, 0xda, 0xd2, 0xaa, 0x11, 0x61, 0xe7, - 0x91, 0xa0, 0x33, 0x2f, 0x84, 0x7f, 0xef, 0x9e, 0xb8, 0x90, 0x49, 0x94, 0xc9, 0x69, 0x53, 0x65, 0xdd, 0xc2, 0x9d, - 0x01, 0x39, 0xad, 0x3d, 0x2f, 0x9d, 0x89, 0x46, 0x14, 0x54, 0xac, 0x42, 0x0a, 0x4f, 0x4e, 0xb1, 0x14, 0x6e, 0xbb, - 0x0c, 0x2d, 0x37, 0x56, 0xb0, 0x29, 0xe9, 0x8f, 0x50, 0x91, 0x2b, 0xc5, 0x78, 0xb3, 0xb1, 0x55, 0x97, 0xea, 0x4f, - 0x1b, 0xe8, 0x73, 0x14, 0xbb, 0x42, 0x3b, 0x96, 0x97, 0xba, 0xc7, 0x7d, 0x90, 0x59, 0x53, 0x39, 0xb1, 0xdb, 0x03, - 0x15, 0x2c, 0x9b, 0x2f, 0xe4, 0x40, 0x39, 0xb5, 0x05, 0x5c, 0x90, 0x18, 0x62, 0xa7, 0x04, 0x70, 0x30, 0x5c, 0x6a, - 0x60, 0x46, 0x71, 0x3a, 0x0a, 0x00, 0x22, 0xaf, 0xe9, 0x3d, 0x15, 0x74, 0x86, 0xba, 0x33, 0x96, 0x35, 0x75, 0xdd, - 0x23, 0x47, 0x2d, 0x09, 0x9f, 0xc0, 0x53, 0x11, 0xaa, 0xd1, 0xb0, 0xca, 0x5d, 0xdd, 0x82, 0xcb, 0x8b, 0x61, 0x51, - 0x74, 0x85, 0x0c, 0x06, 0xaf, 0x03, 0x34, 0xc4, 0xbf, 0x38, 0x2f, 0x67, 0xf1, 0xed, 0x51, 0xf1, 0x71, 0x07, 0xed, - 0x68, 0xe2, 0x9e, 0x05, 0xd5, 0xec, 0x17, 0x02, 0x0d, 0xdf, 0x05, 0x3e, 0xcd, 0xe7, 0x4d, 0xcd, 0xbb, 0x9a, 0x8a, - 0x64, 0x7d, 0xe8, 0x8a, 0x8c, 0xa7, 0xf6, 0x7b, 0xb9, 0x54, 0x6c, 0xc9, 0x5c, 0xd2, 0xd0, 0xce, 0x84, 0x61, 0x79, - 0xa9, 0xc7, 0x3c, 0xbb, 0xd7, 0x78, 0x50, 0x8d, 0x9f, 0x5c, 0x9c, 0xd4, 0x79, 0x1c, 0xf0, 0xa5, 0xf2, 0x05, 0x76, - 0x71, 0x9a, 0xc2, 0x84, 0x17, 0x56, 0x7d, 0x71, 0x5f, 0xfa, 0x31, 0x90, 0xc3, 0x00, 0x15, 0xe6, 0x9c, 0x3e, 0x53, - 0x2a, 0xa5, 0xf3, 0xd6, 0xbc, 0x3d, 0x69, 0x83, 0x45, 0x5a, 0xfa, 0x32, 0x08, 0x77, 0xd7, 0xf2, 0xa2, 0xbb, 0x15, - 0xef, 0xd2, 0x0a, 0xa9, 0xa7, 0x16, 0x44, 0x7c, 0x91, 0x25, 0xbe, 0xf7, 0x97, 0x51, 0xca, 0x46, 0x1f, 0x89, 0xbf, - 0xbf, 0x0c, 0xd0, 0xe6, 0xb5, 0x47, 0xc5, 0x15, 0x2c, 0xc3, 0x46, 0x75, 0x47, 0x7a, 0x16, 0x3a, 0xbc, 0x58, 0xbf, - 0x15, 0xc7, 0xef, 0xed, 0x2f, 0x81, 0xf1, 0xe8, 0x79, 0x7a, 0x17, 0xc5, 0x79, 0xf5, 0xae, 0xab, 0x0a, 0x0a, 0x40, - 0xb3, 0x2e, 0xf7, 0x14, 0x51, 0x11, 0xff, 0x93, 0x94, 0xe6, 0x7b, 0x9a, 0xa9, 0x01, 0x9c, 0xd2, 0xf0, 0x37, 0xdf, - 0xfb, 0x4b, 0x59, 0x46, 0x4b, 0x8f, 0x86, 0x4a, 0xc9, 0x20, 0x3e, 0xcc, 0x05, 0x66, 0x6c, 0x98, 0x50, 0x19, 0xb3, - 0x54, 0x77, 0xe9, 0x5a, 0x03, 0x7c, 0x6d, 0x45, 0xab, 0x55, 0x5e, 0x5f, 0x0b, 0xab, 0x63, 0x50, 0xad, 0xec, 0xf8, - 0xb0, 0x82, 0x5b, 0xad, 0x4c, 0x9d, 0x49, 0x37, 0x34, 0x58, 0xad, 0x50, 0xd7, 0x79, 0x7f, 0x19, 0xa9, 0x6b, 0x43, - 0x00, 0x20, 0x37, 0x00, 0x42, 0xd0, 0x5a, 0x5f, 0x8b, 0x09, 0x52, 0xc2, 0x43, 0x19, 0x8b, 0x09, 0x95, 0x6b, 0x88, - 0x4d, 0x75, 0x8e, 0x6a, 0xd7, 0x06, 0xa8, 0x37, 0xa0, 0x8d, 0xeb, 0xd0, 0x5e, 0x00, 0xd2, 0xfb, 0xfb, 0x4b, 0x56, - 0x90, 0xfd, 0x25, 0xcd, 0x46, 0x3c, 0xa1, 0x1f, 0xde, 0x7d, 0x09, 0x97, 0x1c, 0x79, 0x06, 0x86, 0xc5, 0x14, 0x81, - 0xe0, 0x54, 0x9b, 0xa3, 0x45, 0x08, 0x57, 0x22, 0x44, 0x73, 0x02, 0x4f, 0xcd, 0xa5, 0x40, 0x2c, 0x7c, 0xaf, 0xaf, - 0x21, 0xa7, 0x89, 0x86, 0x99, 0x64, 0xaa, 0x17, 0x2f, 0x8e, 0x0f, 0x75, 0x6b, 0x2d, 0x02, 0x74, 0x23, 0x40, 0x82, - 0x3a, 0xa7, 0x15, 0x0e, 0x20, 0xaf, 0xd9, 0xc5, 0x43, 0xc2, 0xae, 0x4a, 0x62, 0x53, 0x17, 0xa8, 0x7a, 0xc7, 0x69, - 0x7c, 0x49, 0xd3, 0xde, 0xfe, 0x32, 0x5b, 0xad, 0x5a, 0xc5, 0xf1, 0xa1, 0x7e, 0xf4, 0x8e, 0x15, 0xdf, 0xd0, 0x2f, - 0xbc, 0x54, 0x5b, 0x0c, 0xb7, 0x12, 0x21, 0xdb, 0xd3, 0xa6, 0x39, 0x45, 0x66, 0x80, 0xc2, 0xf7, 0x54, 0x82, 0x85, - 0x6a, 0x54, 0x2a, 0x44, 0x85, 0xef, 0xb1, 0x64, 0xb3, 0x2c, 0x97, 0x74, 0x0e, 0xa5, 0xd3, 0xd5, 0xaa, 0x5d, 0xf8, - 0xde, 0x8c, 0x65, 0xf0, 0x94, 0xad, 0x56, 0xea, 0xc2, 0xdf, 0x8c, 0x65, 0x41, 0x0b, 0xc8, 0xd6, 0xf7, 0x66, 0xf1, - 0x8d, 0x5a, 0xb0, 0xad, 0x89, 0x6f, 0x82, 0xb6, 0xa9, 0x0a, 0x4b, 0xfc, 0xe4, 0x40, 0x71, 0xd5, 0x8e, 0xa6, 0x66, - 0x47, 0x13, 0xbc, 0xd0, 0x57, 0x99, 0x48, 0x90, 0x90, 0x74, 0xfb, 0x8e, 0x26, 0x76, 0x47, 0x17, 0x3b, 0x76, 0x74, - 0x71, 0xc7, 0x8e, 0xc6, 0x66, 0xf7, 0xbc, 0x12, 0x77, 0x7c, 0xb5, 0x6a, 0xb7, 0x2a, 0xec, 0x1d, 0x1f, 0x26, 0xec, - 0x0a, 0x76, 0x03, 0xd4, 0x3c, 0xc9, 0x66, 0x74, 0x3b, 0x51, 0xd6, 0x51, 0x4c, 0x7f, 0x15, 0x26, 0x2b, 0x2c, 0x64, - 0x75, 0x2c, 0xb8, 0x74, 0x5d, 0xc6, 0xdc, 0xfe, 0x48, 0xca, 0x66, 0x80, 0x87, 0x1c, 0xf0, 0x30, 0x35, 0x78, 0xb8, - 0x28, 0xce, 0x41, 0x24, 0xa8, 0xe5, 0xdc, 0x8b, 0xf4, 0xa0, 0xb5, 0xdf, 0xdb, 0x4d, 0x62, 0x10, 0x0d, 0xbf, 0xe6, - 0x22, 0xf1, 0x23, 0xdd, 0xf4, 0x57, 0x61, 0x66, 0xc6, 0x32, 0x93, 0x5b, 0xb5, 0x93, 0xb4, 0xaa, 0x7a, 0x97, 0xc0, - 0x3a, 0x8f, 0x1e, 0xe9, 0x16, 0xf3, 0x58, 0x4a, 0x2a, 0x32, 0x43, 0xa8, 0xbe, 0xff, 0xff, 0x05, 0xd1, 0x6d, 0x61, - 0x23, 0xb1, 0x65, 0x23, 0x96, 0xde, 0x8c, 0x7e, 0x6e, 0x58, 0xbc, 0x96, 0x46, 0x7b, 0x95, 0xc2, 0x7a, 0x8b, 0x5c, - 0x1b, 0x41, 0x17, 0x81, 0xc9, 0xb2, 0x98, 0xd1, 0xe4, 0x5c, 0xf1, 0xe3, 0xfe, 0xe8, 0xc2, 0xe8, 0xa7, 0x6b, 0xd2, - 0xad, 0xea, 0x80, 0xfd, 0x1f, 0x17, 0x9d, 0x27, 0x0f, 0x4f, 0x7d, 0xac, 0x59, 0x3a, 0x1f, 0x8f, 0x7d, 0x54, 0x78, - 0xf7, 0xeb, 0xd6, 0x7e, 0xf8, 0xe3, 0xe2, 0x8b, 0x17, 0xad, 0x2f, 0xca, 0xce, 0x99, 0x8f, 0x8a, 0x0b, 0x13, 0xce, - 0xb7, 0x92, 0xc9, 0x81, 0xd7, 0xae, 0x68, 0x1c, 0x67, 0xbb, 0x97, 0x33, 0x70, 0x97, 0x93, 0xcf, 0x29, 0x4d, 0xb0, - 0xef, 0xf9, 0x78, 0xa3, 0xf4, 0x3c, 0xa5, 0x57, 0xd4, 0xbe, 0x68, 0x70, 0xcb, 0x64, 0x5b, 0x7a, 0x8c, 0xf8, 0x22, - 0x93, 0x26, 0xaf, 0xc1, 0x70, 0x56, 0x67, 0x49, 0x17, 0x6a, 0x0d, 0xae, 0x49, 0x70, 0xab, 0xc5, 0x5a, 0x5d, 0x58, - 0x15, 0x17, 0xd8, 0x77, 0x00, 0xd8, 0x09, 0x59, 0x7f, 0x47, 0x79, 0xd4, 0xc2, 0xad, 0x5d, 0xb0, 0xe1, 0x36, 0x8a, - 0x7c, 0x7f, 0x68, 0xf1, 0xa4, 0x5c, 0x93, 0xb5, 0xf7, 0x43, 0xec, 0xc4, 0xd7, 0x27, 0x31, 0x70, 0x29, 0x60, 0xb0, - 0x8c, 0xe6, 0xf9, 0x4e, 0x04, 0x94, 0x9b, 0x88, 0xfd, 0xaa, 0xb5, 0xbf, 0x63, 0x14, 0xdc, 0xc2, 0x70, 0xc2, 0x14, - 0xc0, 0x65, 0x80, 0xd4, 0xb4, 0xa2, 0xe3, 0x31, 0x1d, 0x95, 0x9e, 0x5d, 0x08, 0x75, 0x8d, 0x59, 0x2a, 0x21, 0xe2, - 0xa3, 0x42, 0x31, 0xfe, 0x1b, 0x9e, 0x51, 0x1f, 0xd9, 0xe4, 0x4d, 0x03, 0xbf, 0x11, 0xf7, 0xdb, 0xe1, 0xd1, 0x23, - 0xd6, 0x61, 0x31, 0xb3, 0xac, 0x56, 0xd6, 0xab, 0x53, 0x2b, 0xaf, 0x23, 0x92, 0x2b, 0xb7, 0xcd, 0xae, 0x03, 0x74, - 0xbf, 0x63, 0xb2, 0x6c, 0x7f, 0xf1, 0xa8, 0xdd, 0x2a, 0x7c, 0xec, 0xc3, 0x70, 0xf7, 0x3d, 0x25, 0xaa, 0xd7, 0x11, - 0xf4, 0x5a, 0x64, 0xbf, 0xa6, 0x5f, 0xa7, 0xfd, 0x79, 0xdb, 0xc7, 0xfa, 0xbd, 0x01, 0xa8, 0x28, 0x99, 0xc1, 0x08, - 0x7c, 0x9d, 0xbf, 0x7b, 0x29, 0xf5, 0xc1, 0xef, 0x07, 0xcf, 0xe3, 0x76, 0xcb, 0xc7, 0x7e, 0x2e, 0xf9, 0xfc, 0x57, - 0x2c, 0xe1, 0xc8, 0xc7, 0xfe, 0x28, 0xe5, 0x39, 0x75, 0xd7, 0xa0, 0xb5, 0xd7, 0xdf, 0xbf, 0x08, 0x0d, 0xd1, 0x5c, - 0xd0, 0x3c, 0xf7, 0xdc, 0xf1, 0x0d, 0x29, 0x7d, 0x82, 0x61, 0x6e, 0xa5, 0xb8, 0x9c, 0x4a, 0x85, 0x17, 0x7d, 0xa5, - 0xdf, 0xa5, 0x2a, 0x5d, 0xb6, 0x41, 0x6c, 0x4a, 0x04, 0x94, 0x8c, 0x4d, 0x2b, 0x53, 0x9f, 0x9c, 0x79, 0xcb, 0xd1, - 0xd3, 0x13, 0xeb, 0x10, 0xf0, 0xe6, 0x04, 0xb5, 0x92, 0x19, 0xcb, 0xce, 0xb7, 0x94, 0xc6, 0x37, 0x5b, 0x4a, 0x41, - 0x43, 0x2b, 0xa1, 0x33, 0x6f, 0x9b, 0xf9, 0x34, 0xd6, 0x2b, 0x3d, 0xc7, 0x05, 0x31, 0x51, 0x6e, 0xca, 0x4f, 0x40, - 0xea, 0x6c, 0x83, 0x1a, 0xe1, 0xb7, 0x4f, 0x07, 0x25, 0xbf, 0x6a, 0x3a, 0x7a, 0xf3, 0xe9, 0x3d, 0x77, 0x14, 0x9b, - 0xdf, 0x81, 0x7d, 0x73, 0x73, 0x7c, 0x1d, 0xfd, 0x5b, 0x8a, 0x8d, 0xee, 0x51, 0x6e, 0xc1, 0x28, 0x65, 0xb3, 0x6a, - 0x17, 0x36, 0xc1, 0x54, 0x4a, 0x07, 0xa4, 0x0f, 0xb9, 0x83, 0x68, 0xed, 0xe3, 0x1c, 0x2e, 0x45, 0xc2, 0x9b, 0x27, - 0x16, 0x82, 0x9e, 0xa7, 0xfc, 0x7a, 0xfd, 0x4d, 0x5a, 0xbb, 0x1b, 0x4f, 0xd9, 0x64, 0xea, 0xdc, 0x74, 0xa2, 0xa4, - 0x44, 0xfd, 0x9d, 0x13, 0x14, 0xff, 0xfa, 0x2f, 0x61, 0xf8, 0xaf, 0xff, 0xf2, 0xc9, 0xa6, 0x30, 0x7c, 0x71, 0x81, - 0x65, 0x35, 0xec, 0x6e, 0x02, 0xdf, 0x3e, 0x53, 0x1d, 0xe7, 0xdb, 0xdb, 0x6c, 0x6c, 0x02, 0xd4, 0x6f, 0x6c, 0xc1, - 0x46, 0xa1, 0x3e, 0x00, 0xde, 0x6f, 0x01, 0x0c, 0xd6, 0xf5, 0x49, 0xc8, 0xa0, 0xd1, 0xef, 0x02, 0xed, 0x02, 0x45, - 0xf7, 0xda, 0x91, 0xdf, 0x8e, 0xe1, 0x4f, 0xad, 0xe1, 0x77, 0x82, 0x6f, 0x3c, 0x02, 0xa3, 0x8b, 0x8b, 0x32, 0xa5, - 0xcd, 0xed, 0x0a, 0x57, 0xe6, 0xfb, 0x1b, 0x25, 0x46, 0xf6, 0x47, 0x2d, 0xd4, 0x53, 0x17, 0xf2, 0xc8, 0xe8, 0xe2, - 0x35, 0xbc, 0x27, 0xe7, 0xf8, 0x52, 0x58, 0x97, 0xea, 0x1d, 0xfc, 0x19, 0x86, 0xa8, 0xaf, 0x4a, 0x0d, 0xba, 0xc1, - 0x9c, 0xa1, 0x14, 0x34, 0x7e, 0x00, 0x13, 0x8f, 0x2e, 0x8c, 0x7d, 0x77, 0xaa, 0x1d, 0x1f, 0xd1, 0x3a, 0x69, 0x1b, - 0x87, 0x48, 0x0d, 0xe9, 0xd8, 0x7b, 0xaf, 0xf0, 0xa5, 0x1a, 0xd3, 0xca, 0x9e, 0x56, 0xce, 0x25, 0x50, 0xe5, 0x2f, - 0x0a, 0x15, 0x18, 0xff, 0xeb, 0xae, 0xd8, 0xdd, 0xdf, 0x3f, 0x1d, 0xbb, 0xe3, 0xf7, 0x8a, 0xdd, 0xfd, 0xfd, 0x0f, - 0x8f, 0xdd, 0xfd, 0xd5, 0x8d, 0xdd, 0xc1, 0x26, 0x7e, 0x79, 0xaf, 0xf8, 0x9a, 0x8d, 0x7d, 0xf0, 0xeb, 0x9c, 0xb4, - 0x8d, 0x26, 0x9b, 0xf2, 0x09, 0x04, 0xd7, 0xfe, 0xfd, 0x63, 0x65, 0x29, 0x9f, 0xb8, 0x91, 0x32, 0x78, 0x4f, 0x2a, - 0x84, 0xc6, 0xba, 0x36, 0xa6, 0x65, 0xa2, 0x53, 0xad, 0xf2, 0x0e, 0x48, 0xf3, 0xa1, 0x7d, 0x67, 0x81, 0x1f, 0x95, - 0xef, 0x1d, 0x6a, 0xe1, 0x8e, 0x8d, 0x5f, 0x45, 0x2a, 0xf4, 0x55, 0x76, 0xec, 0x34, 0xec, 0x05, 0x07, 0x77, 0x84, - 0xae, 0x7d, 0xaf, 0x8a, 0xbe, 0xef, 0xbe, 0xf4, 0x7f, 0xbc, 0x69, 0x3f, 0x1b, 0xb4, 0xbb, 0x47, 0xed, 0x99, 0x1f, - 0xf9, 0x20, 0xa5, 0x54, 0x41, 0xab, 0x7b, 0x74, 0x04, 0x05, 0xd7, 0x4e, 0x41, 0x07, 0x0a, 0x98, 0x53, 0xf0, 0x08, - 0x0a, 0x46, 0x4e, 0xc1, 0x63, 0x28, 0x48, 0x9c, 0x82, 0x27, 0x50, 0x70, 0xe5, 0x17, 0x03, 0x56, 0x82, 0xfb, 0x04, - 0x0d, 0xb1, 0x36, 0x1e, 0x6c, 0xd9, 0x13, 0xdc, 0x86, 0xa0, 0x59, 0x3c, 0x51, 0xb9, 0x3e, 0xe0, 0x82, 0x8b, 0x38, - 0xbe, 0x9e, 0xd2, 0x2c, 0x82, 0xb0, 0xe5, 0x73, 0x25, 0x63, 0x42, 0xc9, 0xdf, 0xb3, 0x19, 0xb5, 0x5f, 0xa8, 0xb0, - 0x78, 0xf0, 0x7c, 0x34, 0x68, 0x0d, 0x8b, 0x6e, 0xb9, 0x73, 0x3a, 0xda, 0x66, 0xf2, 0x3e, 0xf4, 0x5e, 0x56, 0x75, - 0x7a, 0xba, 0x66, 0xb9, 0xe7, 0x3b, 0xa2, 0x36, 0x8e, 0x3b, 0x60, 0x9c, 0xf2, 0xeb, 0xe6, 0x8d, 0xdf, 0xdb, 0x1e, - 0xc9, 0x01, 0x88, 0xca, 0x48, 0x8e, 0x5a, 0x53, 0xf9, 0xf4, 0x3e, 0x9e, 0x94, 0xbf, 0x5f, 0xd3, 0x3c, 0x8f, 0x27, - 0xa6, 0xe5, 0xee, 0xc8, 0x8d, 0x02, 0xd1, 0x8d, 0xda, 0x58, 0x20, 0x20, 0xfa, 0x02, 0x9b, 0x05, 0xe6, 0xb4, 0x09, - 0xc6, 0x00, 0x76, 0xea, 0x71, 0x1c, 0x35, 0x7d, 0xbd, 0x48, 0xc6, 0x93, 0xaa, 0xe0, 0x78, 0x2e, 0xa8, 0x2a, 0xd5, - 0x18, 0x2e, 0x8e, 0x0f, 0xa1, 0x40, 0x57, 0xef, 0x88, 0xd7, 0x58, 0xdb, 0x7d, 0x77, 0xd4, 0xc6, 0xb3, 0xf1, 0x1a, - 0x37, 0xc3, 0xa5, 0x4c, 0x6f, 0xd9, 0x8c, 0x12, 0x7c, 0xd6, 0x1e, 0xc1, 0x1f, 0x13, 0x83, 0xf8, 0x6c, 0x3c, 0x1e, - 0xdf, 0x19, 0xbf, 0xf9, 0x2c, 0x19, 0xd3, 0x0e, 0x7d, 0xd4, 0x85, 0xec, 0x87, 0xa6, 0xf1, 0xfa, 0xb7, 0x0b, 0x85, - 0xbb, 0xe5, 0xfd, 0x1a, 0x43, 0x80, 0x40, 0x4e, 0x97, 0xf7, 0x8f, 0xe5, 0x14, 0x73, 0x41, 0x97, 0xb3, 0x58, 0x4c, - 0x58, 0x16, 0xb5, 0x8a, 0xf0, 0xca, 0x04, 0x3f, 0x3e, 0x7b, 0xfa, 0xf4, 0x69, 0x11, 0x26, 0xf6, 0xa9, 0x95, 0x24, - 0x45, 0x38, 0x5a, 0x96, 0xcb, 0x68, 0xb5, 0xc6, 0xe3, 0x22, 0x64, 0xb6, 0xe0, 0xa8, 0x33, 0x4a, 0x8e, 0x3a, 0x45, - 0x78, 0xed, 0xb4, 0x28, 0x42, 0x6a, 0x9e, 0x04, 0x4d, 0x6a, 0x29, 0x14, 0x4f, 0x5a, 0xad, 0x22, 0xd4, 0x84, 0xb6, - 0x04, 0x8b, 0x48, 0xff, 0x8c, 0xe2, 0x85, 0xe4, 0xc0, 0x92, 0xbb, 0x5c, 0x06, 0x83, 0x73, 0xf3, 0x7a, 0x0a, 0xfd, - 0x29, 0x87, 0x02, 0x0d, 0xf1, 0x97, 0x6e, 0x98, 0x02, 0x88, 0x59, 0x85, 0x27, 0xb8, 0x8d, 0x62, 0xd4, 0xaa, 0x81, - 0xb2, 0x54, 0xf5, 0x97, 0x84, 0x57, 0xd1, 0x0b, 0xe0, 0x3f, 0xd0, 0x52, 0xbf, 0x47, 0x4d, 0xd2, 0x1d, 0x5c, 0x9f, - 0xd2, 0x4f, 0x72, 0xfd, 0xdb, 0xfb, 0x30, 0x7d, 0x4a, 0xff, 0x68, 0xa6, 0x6f, 0x5e, 0x36, 0xaa, 0x99, 0xbe, 0x66, - 0x6b, 0x33, 0x49, 0xfc, 0xd1, 0x94, 0x8e, 0x3e, 0x5e, 0xf2, 0x9b, 0x26, 0x1c, 0x09, 0xe1, 0x2b, 0x7e, 0xba, 0xff, - 0x5b, 0xd3, 0x2d, 0xec, 0x60, 0xce, 0x97, 0x20, 0x94, 0xd8, 0x7c, 0x9b, 0x11, 0xff, 0xad, 0x35, 0xab, 0x74, 0xc9, - 0x78, 0x4c, 0xfc, 0xb7, 0xe3, 0xb1, 0x6f, 0x2f, 0xd9, 0xc5, 0x92, 0xaa, 0x56, 0x6f, 0x6a, 0x25, 0xaa, 0xd5, 0x17, - 0x5f, 0xb8, 0x65, 0x6e, 0x81, 0x09, 0x72, 0xb8, 0x01, 0x0d, 0x53, 0x93, 0xb0, 0x1c, 0x8e, 0x1a, 0x7c, 0xa0, 0xa2, - 0xfe, 0x96, 0x3f, 0x51, 0x7b, 0x21, 0x73, 0x09, 0xf0, 0x96, 0xb7, 0x48, 0xaf, 0xdf, 0x30, 0x9f, 0x50, 0x9b, 0xf0, - 0xf6, 0xec, 0xf6, 0xcb, 0x24, 0x98, 0x49, 0x54, 0xb0, 0xfc, 0x6d, 0xb6, 0x76, 0x7b, 0x44, 0xc3, 0x48, 0x88, 0xbb, - 0xac, 0x42, 0xf2, 0xc9, 0x24, 0x85, 0x4f, 0x84, 0x2c, 0x6b, 0x6f, 0x1e, 0xd5, 0xdd, 0xfb, 0xb5, 0xf5, 0x46, 0x6e, - 0x47, 0xf3, 0x9e, 0x4e, 0xf5, 0xc5, 0x22, 0x9d, 0x75, 0x7c, 0x65, 0x3e, 0x5d, 0xa3, 0x2c, 0xb2, 0xa5, 0xe1, 0xff, - 0x4b, 0x9d, 0xab, 0x2a, 0x21, 0x4f, 0x43, 0x0f, 0x9c, 0x14, 0x85, 0xc9, 0xf2, 0x4f, 0x58, 0x3e, 0x87, 0x37, 0x62, - 0xea, 0x9e, 0xf4, 0x53, 0x2c, 0x3c, 0xbf, 0x76, 0x22, 0x09, 0xb5, 0xed, 0x2a, 0x6c, 0x28, 0x41, 0xfb, 0x6a, 0x67, - 0xb2, 0xf0, 0x8d, 0xcb, 0xd7, 0x22, 0xd1, 0xf7, 0x34, 0x3e, 0x75, 0x8c, 0xc3, 0x59, 0x21, 0xf8, 0x5d, 0xcb, 0x0d, - 0xb1, 0x55, 0xb6, 0xa0, 0x70, 0x23, 0x65, 0xaa, 0x46, 0x63, 0x4b, 0xf9, 0xe5, 0xf3, 0x79, 0x9c, 0x69, 0x36, 0x4a, - 0x7c, 0xcd, 0x0f, 0xf6, 0x97, 0xd5, 0xce, 0x17, 0xbe, 0x05, 0x5b, 0x13, 0x6f, 0xef, 0xf8, 0x10, 0x3a, 0xf4, 0xbc, - 0x1a, 0xe8, 0xd9, 0x86, 0x3b, 0xff, 0x13, 0x81, 0xf5, 0x8b, 0x30, 0xbf, 0xc6, 0x61, 0x7e, 0xed, 0xfd, 0x79, 0xd9, - 0xbc, 0xa6, 0x97, 0x1f, 0x99, 0x6c, 0xca, 0x78, 0xde, 0x04, 0x85, 0x5f, 0xf9, 0xe5, 0x0c, 0x7b, 0x56, 0xe9, 0x61, - 0xfa, 0x8e, 0x7c, 0x77, 0x91, 0x43, 0xfc, 0x5d, 0xa9, 0xad, 0x51, 0xc6, 0x33, 0xda, 0xad, 0xa7, 0x01, 0xba, 0xe1, - 0x5c, 0x8b, 0xad, 0xe1, 0x92, 0x43, 0xbc, 0x5e, 0xde, 0x46, 0x2d, 0xc3, 0xd6, 0x5b, 0x36, 0x56, 0xdb, 0xda, 0xda, - 0x3e, 0x32, 0xc8, 0x6d, 0x28, 0xe9, 0x25, 0x36, 0x63, 0xd6, 0xbb, 0x62, 0xce, 0x9f, 0x4a, 0x8a, 0x03, 0x6f, 0x9e, - 0xfd, 0xeb, 0x64, 0x13, 0xae, 0x17, 0xab, 0xa4, 0xb8, 0xfb, 0x40, 0x16, 0xc5, 0x63, 0x49, 0x05, 0xbe, 0x4f, 0xcb, - 0x4b, 0x75, 0x7f, 0x65, 0x09, 0x62, 0x26, 0x6a, 0x3f, 0x9d, 0xdf, 0xdc, 0x7f, 0xf8, 0xbb, 0x97, 0x5f, 0x18, 0x1c, - 0xd9, 0xf7, 0xb9, 0xf8, 0x7e, 0x17, 0x0e, 0x42, 0x1a, 0xdf, 0x46, 0x2c, 0x53, 0x32, 0xef, 0x12, 0x5c, 0x72, 0xdd, - 0x39, 0x37, 0xd9, 0x9d, 0x82, 0xa6, 0xea, 0xe3, 0x6d, 0x66, 0x2b, 0x8e, 0x1e, 0xcf, 0x6f, 0xec, 0x6e, 0xb4, 0xd7, - 0xb2, 0x36, 0xff, 0xd0, 0xe4, 0xcc, 0xdd, 0xd9, 0xa0, 0xf5, 0x04, 0xc3, 0x47, 0xf3, 0x9b, 0xae, 0x16, 0xb4, 0x4d, - 0xa1, 0xa1, 0x6a, 0xcd, 0x6f, 0xdc, 0xf4, 0xd4, 0x6a, 0x20, 0x2f, 0x3c, 0xca, 0x3d, 0x1a, 0xe7, 0xb4, 0x0b, 0x6f, - 0xac, 0x66, 0xa3, 0x38, 0x35, 0xc2, 0x7c, 0xc6, 0x92, 0x24, 0xa5, 0x5d, 0x2b, 0xaf, 0xbd, 0xf6, 0x63, 0xc8, 0xee, - 0x74, 0xb7, 0xac, 0xbe, 0x2b, 0x0e, 0xf2, 0x4a, 0x3c, 0xc5, 0x97, 0x39, 0x4f, 0xe1, 0x73, 0x11, 0x5b, 0xd1, 0x69, - 0xd2, 0x1e, 0x5b, 0x15, 0xf2, 0xd4, 0xef, 0xfa, 0x5a, 0x1e, 0xb5, 0xfe, 0xd4, 0x55, 0x1b, 0xde, 0xea, 0x4a, 0x3e, - 0x8f, 0x9a, 0x47, 0xf5, 0x85, 0x40, 0x55, 0xb9, 0x04, 0xbc, 0x65, 0x59, 0x18, 0xa4, 0x95, 0xe6, 0xd3, 0x5e, 0xd8, - 0x36, 0x65, 0x6a, 0x00, 0x78, 0xb5, 0x72, 0x59, 0x54, 0xd4, 0x17, 0xf3, 0xef, 0x73, 0x5a, 0x3e, 0xdf, 0x7e, 0x5a, - 0x3e, 0xb7, 0xa7, 0xe5, 0x6e, 0x8a, 0xfd, 0x6c, 0xdc, 0x86, 0x3f, 0xdd, 0x6a, 0x41, 0x51, 0xcb, 0x3b, 0x9a, 0xdf, - 0x78, 0xa0, 0xa7, 0x35, 0x3b, 0xf3, 0x1b, 0x9d, 0x9c, 0x0b, 0x61, 0x83, 0x16, 0xa4, 0xab, 0xe2, 0x96, 0x07, 0x85, - 0xf0, 0xb7, 0x55, 0xab, 0x6a, 0x3f, 0x84, 0x3a, 0xe8, 0xf5, 0x68, 0xb3, 0xae, 0x73, 0xf7, 0xa1, 0x8d, 0x32, 0x2e, - 0x83, 0xc8, 0x72, 0x63, 0x14, 0xca, 0xf8, 0xf2, 0x92, 0x26, 0xd1, 0x98, 0x8f, 0x16, 0xf9, 0x3f, 0x1b, 0xf8, 0x0d, - 0x12, 0xef, 0x3c, 0xd2, 0x6b, 0xe3, 0xd8, 0xae, 0x3a, 0x55, 0xd8, 0x8e, 0xb0, 0x2c, 0xf7, 0x29, 0xca, 0x47, 0x71, - 0x4a, 0x83, 0x4e, 0xf8, 0x70, 0xcb, 0x21, 0xf8, 0x0f, 0xd9, 0x9b, 0xad, 0x8b, 0xf9, 0xbd, 0xc8, 0xb8, 0x13, 0x09, - 0xbf, 0x0a, 0x07, 0xee, 0x1e, 0xb6, 0x9e, 0x6e, 0x07, 0x77, 0x60, 0x67, 0x1a, 0x5a, 0xa1, 0x60, 0xe4, 0x4e, 0x42, - 0xc7, 0xf1, 0x22, 0x95, 0x77, 0x8f, 0xba, 0x8b, 0x32, 0x36, 0x46, 0xbd, 0x83, 0xa1, 0x57, 0x6d, 0xef, 0xc9, 0xa5, - 0x3f, 0xfb, 0xfc, 0x21, 0xfc, 0xd1, 0x99, 0x46, 0xb7, 0x95, 0xae, 0xae, 0x6d, 0x55, 0xd0, 0xd5, 0xf7, 0x6b, 0xca, - 0xb8, 0x16, 0xe1, 0x4a, 0x1f, 0xbf, 0x6f, 0x6b, 0xd0, 0x2a, 0xef, 0xd5, 0xdc, 0x68, 0x59, 0xbf, 0xaa, 0xf5, 0xaf, - 0x1b, 0xfc, 0x9e, 0x6d, 0x47, 0x5a, 0x73, 0xad, 0xb7, 0x35, 0x5f, 0xaf, 0xdb, 0x68, 0x6c, 0x31, 0xae, 0xda, 0xef, - 0x93, 0xdb, 0xd2, 0x44, 0xd1, 0x81, 0x40, 0xb0, 0x52, 0xf6, 0xb5, 0x95, 0xc2, 0x28, 0x79, 0x00, 0xef, 0x8e, 0xf5, - 0x6e, 0x66, 0x69, 0x96, 0x13, 0x7f, 0x2a, 0xe5, 0x3c, 0xd2, 0x9f, 0x3b, 0xbd, 0x3e, 0x0a, 0xb9, 0x98, 0x1c, 0x76, - 0x5a, 0xad, 0x16, 0xbc, 0xf3, 0xd3, 0xf7, 0xae, 0x18, 0xbd, 0x7e, 0xc6, 0x6f, 0x88, 0xff, 0xc4, 0x7b, 0xea, 0x3d, - 0x39, 0xf2, 0x1e, 0x3d, 0xf6, 0x3d, 0xc5, 0xce, 0x89, 0xff, 0xe4, 0xc8, 0xf7, 0x34, 0x3b, 0x27, 0xfe, 0xa3, 0xc7, - 0x7e, 0xef, 0x78, 0x62, 0x55, 0x32, 0xb8, 0x34, 0xa8, 0xf5, 0x9d, 0x5c, 0x0a, 0xfe, 0x91, 0xd6, 0x0f, 0xae, 0x2e, - 0x33, 0xb9, 0x68, 0x1d, 0xfb, 0x08, 0xa7, 0x77, 0x14, 0xcf, 0x23, 0x45, 0x14, 0x6e, 0x21, 0xb8, 0x65, 0x74, 0xa9, - 0x9a, 0x02, 0xd4, 0xcc, 0x4b, 0xbf, 0x77, 0x0c, 0x79, 0xe3, 0x5e, 0x42, 0xfc, 0xd7, 0x9d, 0x27, 0x5e, 0xfb, 0xf1, - 0x55, 0xf3, 0xe1, 0xa8, 0xd5, 0x6c, 0x7b, 0xed, 0x66, 0x27, 0x7c, 0xe2, 0x75, 0xf4, 0xbf, 0x5e, 0xcb, 0x3b, 0xf2, - 0xda, 0xe1, 0x13, 0xef, 0xc8, 0xeb, 0x84, 0x4f, 0xae, 0x1e, 0xea, 0x7c, 0x82, 0xd8, 0x3f, 0xec, 0x1d, 0xc3, 0xa7, - 0x2b, 0x6f, 0x88, 0xff, 0xb9, 0xaf, 0x3f, 0x10, 0xeb, 0x7f, 0xe6, 0x96, 0xb6, 0x9f, 0x6e, 0x2d, 0xee, 0x3c, 0xd9, - 0x5a, 0x7c, 0xf4, 0x78, 0x6b, 0xf1, 0xc3, 0x47, 0xf5, 0xe2, 0xc3, 0x89, 0xae, 0x2a, 0x4f, 0x39, 0xf1, 0x67, 0xb1, - 0x14, 0xec, 0x26, 0x68, 0x7b, 0x2d, 0xaf, 0xe5, 0x35, 0xe1, 0xbf, 0x27, 0x1d, 0x54, 0xf6, 0xba, 0x84, 0x5e, 0xe5, - 0x2a, 0x9f, 0x3c, 0xf5, 0xda, 0x8f, 0x5f, 0x76, 0x1e, 0x8f, 0xa0, 0x9d, 0x5a, 0x68, 0xdb, 0x6b, 0x5f, 0x1d, 0x3d, - 0x1d, 0xb5, 0x3c, 0xe8, 0xd8, 0x86, 0x3f, 0xd3, 0x47, 0x9d, 0x91, 0x7e, 0x68, 0x41, 0xfd, 0xb7, 0xed, 0x27, 0x79, - 0xab, 0xd9, 0x86, 0x3f, 0xbf, 0x94, 0x1a, 0x31, 0xe8, 0xe3, 0xee, 0xb8, 0x0f, 0x5b, 0xde, 0xd1, 0xd3, 0x69, 0x27, - 0xfc, 0xfc, 0xea, 0x49, 0xf8, 0x74, 0xda, 0x7e, 0xf2, 0xad, 0x7e, 0x4a, 0x9b, 0x9d, 0xf0, 0x73, 0xf8, 0xfb, 0xed, - 0x51, 0x6b, 0xda, 0x6c, 0x87, 0x4f, 0xaf, 0x8e, 0xc2, 0xa3, 0xb4, 0xf9, 0x38, 0x7c, 0x0a, 0x7f, 0xab, 0xe1, 0xa6, - 0x7c, 0x46, 0x7d, 0x0f, 0xf6, 0x7b, 0xcd, 0xdc, 0x72, 0xe7, 0xe8, 0x3c, 0xf4, 0x1e, 0x3d, 0x7c, 0xf9, 0xf4, 0xaa, - 0xf9, 0x70, 0xda, 0xee, 0x5c, 0x35, 0x77, 0xfe, 0xfc, 0x16, 0x10, 0x6f, 0x06, 0x8e, 0x29, 0x5c, 0xe0, 0xb1, 0x88, - 0x53, 0xef, 0x9f, 0x7d, 0x80, 0xf3, 0x5d, 0xe6, 0xb5, 0xf8, 0xb4, 0x79, 0x9d, 0xd1, 0xfb, 0xd8, 0xd7, 0xe2, 0x0f, - 0xb7, 0xaf, 0x73, 0xba, 0xe6, 0x54, 0xbd, 0x95, 0x1b, 0x66, 0xf4, 0xba, 0xed, 0xf5, 0x4e, 0x06, 0x03, 0x06, 0xdf, - 0x39, 0x2a, 0xba, 0xb7, 0xf0, 0x8a, 0x6b, 0xd7, 0xdb, 0xc0, 0xe1, 0x20, 0xdf, 0x4a, 0x7d, 0x92, 0xf9, 0x2e, 0x84, - 0xa4, 0x9f, 0x46, 0xc8, 0xb7, 0xf7, 0xc1, 0x47, 0xfa, 0x87, 0xe3, 0x83, 0xbb, 0xf8, 0xa8, 0xf9, 0x79, 0x95, 0x3d, - 0xab, 0xec, 0xd1, 0x33, 0xf5, 0x1c, 0xc0, 0x1d, 0x8f, 0x86, 0x7f, 0x48, 0xa1, 0x28, 0xf7, 0x75, 0x5c, 0xe1, 0xcd, - 0xaf, 0x71, 0x49, 0xeb, 0x0b, 0x5d, 0xc4, 0x37, 0xc6, 0xff, 0x1c, 0xbe, 0x65, 0x60, 0x1f, 0xae, 0xf4, 0x15, 0x63, - 0xe2, 0x77, 0xc2, 0x56, 0xd8, 0x2a, 0x1d, 0x07, 0x70, 0x89, 0x8f, 0x2c, 0xb9, 0x8c, 0xe1, 0x73, 0x9a, 0x29, 0x9f, - 0xa8, 0x0f, 0x6f, 0xc2, 0xeb, 0xce, 0xd5, 0x27, 0x50, 0xf5, 0x9b, 0xe6, 0x23, 0xdf, 0x37, 0x57, 0xff, 0xe1, 0x92, - 0xd8, 0x37, 0x70, 0x91, 0xce, 0x7a, 0xac, 0x67, 0x60, 0x53, 0xbf, 0xa6, 0x09, 0x8b, 0x03, 0x3f, 0x98, 0x0b, 0x3a, - 0xa6, 0x22, 0x6f, 0xd6, 0x6e, 0x97, 0xa9, 0x8b, 0x65, 0xc8, 0xb7, 0x1f, 0x6e, 0x14, 0xf0, 0xfa, 0x5e, 0x32, 0x30, - 0x5e, 0x2d, 0xdf, 0xa8, 0xf9, 0x7e, 0x81, 0x6d, 0x89, 0x00, 0x8e, 0x5e, 0xa9, 0x06, 0xbe, 0xd6, 0x0d, 0xda, 0x61, - 0xe7, 0x11, 0xd2, 0xbc, 0x04, 0x5e, 0x8b, 0xfa, 0x7d, 0xd0, 0x3c, 0x6a, 0xfd, 0x09, 0x39, 0xdd, 0xca, 0x81, 0x86, - 0xc6, 0xa9, 0x23, 0xaa, 0x0f, 0xde, 0xd6, 0xaf, 0xfe, 0xf9, 0x9a, 0x22, 0x3e, 0xd3, 0x6b, 0x87, 0x17, 0xac, 0x9a, - 0xf8, 0xa1, 0xbe, 0xc0, 0x3e, 0x66, 0x93, 0xc0, 0xfd, 0x9c, 0xa9, 0x7e, 0xed, 0xaa, 0xfa, 0x0a, 0x32, 0x2a, 0xaa, - 0x26, 0x02, 0x2d, 0x95, 0x2f, 0x9e, 0x65, 0x9e, 0x58, 0xad, 0x02, 0x01, 0x8e, 0x58, 0xe2, 0xe0, 0x14, 0x9e, 0x51, - 0x0d, 0xc9, 0x02, 0x97, 0x00, 0x29, 0x04, 0x13, 0xa1, 0xff, 0xaf, 0x8a, 0xed, 0x0f, 0xe3, 0x5e, 0x09, 0xd3, 0x38, - 0x9b, 0x00, 0x15, 0xc6, 0xd9, 0x64, 0xc3, 0x79, 0xa3, 0xc3, 0x09, 0x6b, 0xa5, 0xd5, 0x50, 0x95, 0x93, 0x26, 0x7f, - 0x76, 0xfb, 0xde, 0xbc, 0x9f, 0xc9, 0x07, 0x1f, 0xa8, 0xf2, 0x7d, 0x57, 0xef, 0x92, 0x6d, 0x90, 0x07, 0xfa, 0x03, - 0xe1, 0x2a, 0x21, 0x0d, 0xa4, 0x1f, 0x5c, 0xea, 0xf3, 0x8c, 0xcd, 0x43, 0x7c, 0x2d, 0xfb, 0x12, 0x7a, 0xc5, 0x46, - 0x46, 0x84, 0x61, 0xcf, 0x5c, 0x6c, 0x6e, 0xaa, 0xad, 0x21, 0x6d, 0xac, 0xad, 0xfe, 0x51, 0xac, 0x32, 0x8c, 0x49, - 0xc6, 0xfd, 0xde, 0x83, 0xf2, 0xeb, 0x8c, 0xbb, 0x36, 0x01, 0xbe, 0x5a, 0x3e, 0x10, 0x34, 0xfd, 0x67, 0xf2, 0x00, - 0xbe, 0x5b, 0xfe, 0x60, 0x08, 0x9f, 0xcc, 0x0e, 0x95, 0x28, 0x78, 0x50, 0x7d, 0xbe, 0x1c, 0xf8, 0x60, 0xe3, 0x66, - 0x96, 0xe2, 0xfb, 0x8a, 0x6f, 0x23, 0xaa, 0x3b, 0x8f, 0x2a, 0x51, 0xdd, 0x79, 0xe4, 0x4a, 0xcf, 0xb6, 0xd7, 0xee, - 0x84, 0x8f, 0x1c, 0x01, 0x70, 0xd5, 0x84, 0xff, 0x6b, 0x22, 0xe0, 0x61, 0xf8, 0xa8, 0x94, 0x01, 0xaf, 0xda, 0x9d, - 0xf0, 0x48, 0x8b, 0x9b, 0x4e, 0xf8, 0xe8, 0x07, 0xc5, 0xa0, 0x35, 0x73, 0xae, 0x1f, 0x88, 0x2d, 0xa1, 0x1a, 0x9d, - 0x54, 0xe7, 0xe3, 0xa0, 0xfc, 0x06, 0x9c, 0x39, 0x9f, 0xc6, 0x25, 0xf4, 0x3c, 0x16, 0xf0, 0x21, 0x8e, 0xfa, 0xd9, - 0xad, 0xd5, 0xe1, 0x1a, 0xbf, 0xd8, 0x32, 0x05, 0x9c, 0x70, 0x1f, 0xbb, 0x37, 0x83, 0xe1, 0x5a, 0xad, 0x7a, 0x6d, - 0xb1, 0x7d, 0x7b, 0xdb, 0x6e, 0xd2, 0xd6, 0x0d, 0xed, 0x1b, 0xe2, 0x14, 0xb3, 0x60, 0xea, 0x15, 0xf1, 0x6a, 0x92, - 0x2f, 0x93, 0x62, 0x7d, 0x7e, 0xc8, 0xed, 0x13, 0xdc, 0xb9, 0x1c, 0x4d, 0xab, 0x04, 0xf4, 0x84, 0xc1, 0x75, 0xf6, - 0xa2, 0xb0, 0xa0, 0xd7, 0x9c, 0x81, 0x15, 0x96, 0x14, 0xbf, 0xa0, 0x79, 0xdf, 0x87, 0x22, 0x3f, 0xf2, 0x95, 0x23, - 0xc9, 0x2f, 0x3f, 0x46, 0x52, 0x12, 0x76, 0x55, 0x80, 0xd5, 0x25, 0x12, 0x38, 0xb5, 0x80, 0x1f, 0x1f, 0x1d, 0x1c, - 0xec, 0x3c, 0x2f, 0x4a, 0x1b, 0x83, 0xb5, 0x56, 0x1f, 0x31, 0x70, 0x59, 0x91, 0xef, 0x22, 0xba, 0x1c, 0x57, 0xa1, - 0x10, 0x19, 0x3c, 0x5d, 0xd2, 0x58, 0x86, 0x71, 0xa6, 0x53, 0x14, 0x1c, 0x86, 0x85, 0xdb, 0xf4, 0x08, 0x15, 0x5c, - 0xc6, 0xce, 0x57, 0x4a, 0xcd, 0x39, 0xe7, 0x32, 0xb6, 0x57, 0xfd, 0x32, 0x59, 0xcb, 0x85, 0x9f, 0x76, 0x7a, 0x6f, - 0xdf, 0x9f, 0x78, 0xfa, 0x78, 0x1e, 0x1f, 0x4e, 0x3b, 0xbd, 0x63, 0x65, 0x99, 0xeb, 0x8b, 0x42, 0x44, 0x5f, 0x14, - 0xf2, 0xcc, 0xa5, 0x31, 0x88, 0xd7, 0x14, 0x87, 0x7a, 0xd9, 0xbe, 0x47, 0xb3, 0x91, 0xf6, 0x29, 0xce, 0x16, 0xa9, - 0x64, 0xf0, 0x0a, 0xde, 0x43, 0xe8, 0xda, 0x84, 0x0d, 0x2b, 0x13, 0x4d, 0xad, 0x86, 0x23, 0x33, 0xeb, 0x81, 0x1c, - 0xb3, 0x94, 0xda, 0xd4, 0x52, 0x33, 0x54, 0x99, 0xf9, 0xbc, 0xd9, 0x3a, 0x5f, 0x5c, 0xce, 0x98, 0xf4, 0x6d, 0x7e, - 0xf6, 0x07, 0xd3, 0xe1, 0x58, 0x4d, 0xd5, 0xbb, 0x28, 0x8c, 0x8b, 0xd4, 0x7e, 0x6e, 0x64, 0xed, 0x03, 0xef, 0x7a, - 0xf5, 0x46, 0x42, 0xc0, 0x8d, 0x9f, 0xe9, 0x51, 0xaf, 0x74, 0x4a, 0xba, 0x75, 0xc5, 0xf1, 0xe1, 0xf4, 0xa8, 0x77, - 0x11, 0xcd, 0xcd, 0x78, 0xaf, 0xf8, 0xc6, 0xc7, 0xe2, 0x4b, 0x8e, 0xd9, 0x57, 0xa9, 0xed, 0xfa, 0x0e, 0xa5, 0x01, - 0x78, 0xc4, 0x53, 0xbf, 0x77, 0x6c, 0x94, 0x01, 0x4f, 0x05, 0x5d, 0xfd, 0x47, 0x2d, 0x9b, 0x2d, 0x9f, 0x72, 0xa5, - 0x2d, 0xe9, 0x2e, 0xce, 0x24, 0x35, 0xbf, 0xee, 0xb4, 0xdd, 0x3b, 0x8e, 0x8d, 0x9a, 0x09, 0xcc, 0x23, 0x8f, 0x0e, - 0xa1, 0x33, 0xe8, 0x72, 0x21, 0xe3, 0x87, 0xd7, 0xf4, 0xb2, 0x19, 0xcf, 0x59, 0xe5, 0x44, 0x05, 0xa5, 0xa3, 0x9c, - 0x92, 0x57, 0x33, 0xc1, 0xcf, 0x78, 0x6d, 0x91, 0x8a, 0x85, 0x17, 0xc6, 0x43, 0xab, 0x74, 0x75, 0x1a, 0x4b, 0xdf, - 0xd3, 0x1c, 0xde, 0x7a, 0x72, 0x8d, 0xec, 0x2d, 0xfc, 0xde, 0xbf, 0xfd, 0x8f, 0xff, 0x65, 0x9c, 0xb3, 0xc7, 0x87, - 0xd3, 0xb6, 0x1d, 0x6b, 0x0d, 0xd1, 0xc5, 0x31, 0x5c, 0x30, 0xab, 0xa2, 0x89, 0xf4, 0xa6, 0x39, 0x11, 0x2c, 0x69, - 0x4e, 0xe3, 0x74, 0xec, 0xf7, 0x76, 0x23, 0xc8, 0xbd, 0x59, 0x62, 0xa0, 0xae, 0x17, 0x01, 0x09, 0xfe, 0xa6, 0xbb, - 0x11, 0x36, 0xc5, 0x5e, 0x9d, 0x56, 0xf7, 0xa6, 0x44, 0x75, 0xa0, 0x6a, 0xb7, 0x25, 0x84, 0xf9, 0x2a, 0x91, 0x61, - 0x6a, 0xa2, 0x76, 0x49, 0xa2, 0xf0, 0xbd, 0x32, 0x1a, 0xf2, 0x7f, 0xff, 0xe7, 0x7f, 0xf9, 0x6f, 0xf6, 0x11, 0x82, - 0x1c, 0xff, 0xf6, 0xdf, 0xff, 0xf3, 0xff, 0xf9, 0xdf, 0xff, 0x15, 0x12, 0xeb, 0x4d, 0x20, 0x44, 0xf1, 0x09, 0xaf, - 0x8a, 0x82, 0x68, 0x86, 0xe1, 0x41, 0x32, 0xda, 0x8c, 0xe5, 0x92, 0x8d, 0xea, 0xd7, 0x26, 0xce, 0xd4, 0x84, 0xea, - 0xb0, 0x19, 0xe8, 0xd4, 0xa1, 0x2d, 0x2a, 0x1a, 0xa9, 0xa1, 0x5c, 0xd1, 0x62, 0x71, 0x7c, 0x08, 0xf8, 0xbe, 0xdf, - 0x4d, 0xb3, 0xb0, 0xdc, 0x8e, 0xa5, 0x75, 0xfd, 0x41, 0x49, 0x51, 0x95, 0x7b, 0xe0, 0x94, 0x5f, 0xc2, 0x63, 0xd4, - 0x71, 0x8a, 0xd5, 0xee, 0xd5, 0xfa, 0x74, 0x7f, 0x5a, 0xe4, 0x92, 0x8d, 0x01, 0xe5, 0xda, 0xc1, 0xa8, 0xe2, 0x9f, - 0x4d, 0x50, 0xff, 0xd2, 0xdb, 0x42, 0x8d, 0xa2, 0x6d, 0xc6, 0x87, 0x4f, 0xff, 0x54, 0xfc, 0x65, 0x06, 0x4a, 0x96, - 0x17, 0xcc, 0xe2, 0x1b, 0x63, 0x49, 0x3e, 0x6e, 0xb5, 0xe6, 0x37, 0x68, 0x59, 0xcd, 0x80, 0x77, 0x4d, 0xa6, 0x9c, - 0x92, 0xee, 0x80, 0x2a, 0x70, 0x5a, 0xfa, 0x3f, 0x5b, 0x1e, 0x38, 0x51, 0xbd, 0x56, 0x51, 0xfc, 0x79, 0xa9, 0x5c, - 0x70, 0xec, 0x17, 0x08, 0x70, 0x1a, 0x6f, 0xe5, 0x25, 0x77, 0x17, 0xb7, 0x74, 0x7a, 0x75, 0x74, 0xaf, 0x69, 0x7b, - 0xf3, 0x02, 0x95, 0x1b, 0xa0, 0x75, 0x43, 0xab, 0x0f, 0x21, 0x58, 0x3a, 0x6d, 0xe3, 0x69, 0x67, 0x59, 0x0e, 0x2f, - 0x25, 0x9f, 0xb9, 0x11, 0x59, 0x1a, 0xd3, 0x11, 0x1d, 0x5b, 0x2f, 0xaf, 0xa9, 0xd7, 0xd1, 0xd6, 0x62, 0x7a, 0xb4, - 0x65, 0x2e, 0x03, 0x92, 0x8a, 0xc4, 0x7a, 0xad, 0xe2, 0x33, 0x38, 0x81, 0xcb, 0x71, 0xca, 0x63, 0x19, 0x29, 0x82, - 0xed, 0xba, 0x71, 0xdd, 0x18, 0xd8, 0x0c, 0x5f, 0x3a, 0xf0, 0x74, 0x75, 0x53, 0xf0, 0xb7, 0xd6, 0xaf, 0xb9, 0x15, - 0xa1, 0xea, 0xee, 0x0e, 0xa5, 0xdd, 0x35, 0xdf, 0x9a, 0x70, 0xe9, 0x9b, 0x9a, 0x9f, 0xc3, 0xc8, 0x98, 0x0e, 0xda, - 0x5e, 0xaf, 0x45, 0xb5, 0xae, 0xfd, 0x4a, 0x06, 0xbe, 0x02, 0xd3, 0x5f, 0x6f, 0xa5, 0x0a, 0xa1, 0xd5, 0x1b, 0xf2, - 0x6d, 0x69, 0x05, 0xc5, 0xf3, 0xb9, 0x6a, 0x88, 0xba, 0xc7, 0x87, 0x5a, 0x79, 0x05, 0xee, 0xa1, 0x72, 0x01, 0x74, - 0xe8, 0xdd, 0x34, 0x32, 0x47, 0x41, 0xff, 0x32, 0x41, 0x79, 0xf8, 0x5c, 0x55, 0xef, 0xff, 0x01, 0xb9, 0x37, 0x65, - 0xfc, 0x3f, 0x86, 0x00, 0x00}; + 0xae, 0x27, 0x4f, 0x9e, 0x3c, 0x7b, 0x02, 0xc7, 0x7b, 0xb1, 0x18, 0xc9, 0xdb, 0x39, 0xf3, 0xa6, 0x72, 0x96, 0xf4, + 0x8e, 0xcd, 0xbf, 0x2c, 0x8a, 0x7b, 0xc7, 0x09, 0x4f, 0x3f, 0x7a, 0x19, 0x4b, 0x28, 0x1f, 0x89, 0xd4, 0x9b, 0x66, + 0x6c, 0x4c, 0xe3, 0x48, 0x46, 0x21, 0x9f, 0x45, 0x13, 0xe6, 0x1d, 0xf6, 0x8e, 0x67, 0x4c, 0x46, 0xde, 0x68, 0x1a, + 0x65, 0x39, 0x93, 0xf4, 0xc3, 0xfb, 0x2f, 0x9a, 0x4f, 0x7b, 0xc7, 0xf9, 0x28, 0xe3, 0x73, 0xe9, 0xc1, 0x90, 0x74, + 0x26, 0xe2, 0x45, 0xc2, 0x7a, 0x87, 0x87, 0xd7, 0xd7, 0xd7, 0xc1, 0x4f, 0xf9, 0x3f, 0x8d, 0x44, 0x9a, 0x4b, 0xef, + 0x15, 0xbd, 0xe6, 0x69, 0x2c, 0xae, 0x09, 0x93, 0xf4, 0x55, 0x70, 0x36, 0x8d, 0x62, 0x71, 0xfd, 0x4e, 0x08, 0x79, + 0x70, 0xe0, 0xeb, 0xc7, 0xdb, 0xd3, 0xb3, 0x33, 0x4a, 0xe9, 0x95, 0xe0, 0xb1, 0xd7, 0x5a, 0xad, 0xaa, 0xc2, 0x20, + 0x8d, 0x24, 0xbf, 0x62, 0xba, 0x0b, 0x3e, 0x38, 0x40, 0x51, 0x2c, 0xe6, 0x92, 0xc5, 0x67, 0xf2, 0x36, 0x61, 0x67, + 0x53, 0xc6, 0x64, 0x8e, 0x78, 0xea, 0x3d, 0x17, 0xa3, 0xc5, 0x8c, 0xa5, 0x32, 0x98, 0x67, 0x42, 0x0a, 0x80, 0xe4, + 0xe0, 0x00, 0x65, 0x6c, 0x9e, 0x44, 0x23, 0x06, 0xf5, 0xa7, 0x67, 0x67, 0x55, 0x8f, 0xaa, 0x11, 0xe1, 0x92, 0x9e, + 0xdd, 0xce, 0x2e, 0x45, 0xe2, 0x63, 0x92, 0x48, 0x9a, 0xb2, 0x6b, 0xef, 0x3b, 0x16, 0x7d, 0x7c, 0x1d, 0xcd, 0xbb, + 0xa3, 0x24, 0xca, 0x73, 0xef, 0x52, 0x2e, 0xd5, 0x12, 0xb2, 0xc5, 0x48, 0x8a, 0xcc, 0x97, 0x84, 0x11, 0x8e, 0x97, + 0x7c, 0xec, 0xcb, 0x29, 0xcf, 0x83, 0xf3, 0xfd, 0x51, 0x9e, 0xbf, 0x63, 0xf9, 0x22, 0x91, 0xfb, 0x74, 0xaf, 0x45, + 0xf8, 0x1e, 0xa5, 0x5c, 0x62, 0x39, 0xcd, 0xc4, 0xb5, 0xf7, 0x22, 0xcb, 0x44, 0xe6, 0xa3, 0xd3, 0xb3, 0x33, 0xdd, + 0xc2, 0xe3, 0xb9, 0x97, 0x0a, 0xe9, 0x95, 0xe3, 0x45, 0x97, 0x09, 0x0b, 0xbc, 0x0f, 0x39, 0xf3, 0x2e, 0x16, 0x69, + 0x1e, 0x8d, 0xd9, 0xe9, 0xd9, 0xd9, 0x85, 0x27, 0x32, 0xef, 0x62, 0x94, 0xe7, 0x17, 0x1e, 0x4f, 0x73, 0xc9, 0xa2, + 0x38, 0x40, 0xb8, 0xab, 0x26, 0x1b, 0xe5, 0xf9, 0x7b, 0x76, 0x23, 0xa9, 0x24, 0xea, 0x51, 0x52, 0x56, 0x4c, 0x98, + 0xf4, 0xf2, 0x72, 0x5d, 0x3e, 0x5e, 0x26, 0x4c, 0x7a, 0x92, 0xaa, 0x7a, 0xd1, 0xd5, 0xb8, 0x67, 0xfa, 0x51, 0x76, + 0xf9, 0xd8, 0x67, 0xf2, 0xe0, 0x40, 0x96, 0x78, 0xc6, 0x7a, 0x69, 0x1e, 0xa7, 0x6c, 0xcf, 0x96, 0x1d, 0x1c, 0xb0, + 0x20, 0x61, 0xe9, 0x44, 0x4e, 0x29, 0xa5, 0xed, 0x2e, 0x3f, 0x38, 0xf0, 0x25, 0x4d, 0x64, 0x30, 0x61, 0xd2, 0x67, + 0x18, 0x93, 0xaa, 0xf7, 0xc1, 0x81, 0xaf, 0x91, 0x20, 0xa8, 0x46, 0x5c, 0x0d, 0xc7, 0x38, 0x30, 0xd8, 0x3f, 0xbb, + 0x4d, 0x47, 0xbe, 0x0b, 0x3f, 0x26, 0xfc, 0xe0, 0x20, 0x91, 0x41, 0x0e, 0x23, 0x12, 0x89, 0x71, 0x91, 0x31, 0xb9, + 0xc8, 0x52, 0x4f, 0x16, 0x52, 0x9c, 0xc9, 0x8c, 0xa7, 0x13, 0x1f, 0x2f, 0x6d, 0x99, 0xd3, 0xb1, 0x28, 0x34, 0xb8, + 0x5f, 0x4b, 0x9a, 0xd1, 0x1e, 0xcc, 0x78, 0x29, 0x7d, 0xd8, 0x45, 0x31, 0xf6, 0x32, 0x4a, 0x51, 0xae, 0xfa, 0xa2, + 0x7e, 0x16, 0x66, 0x0d, 0x84, 0x88, 0x86, 0x92, 0x70, 0x89, 0xc9, 0x47, 0xea, 0x67, 0x24, 0x08, 0x02, 0x89, 0x69, + 0x6f, 0x69, 0xb1, 0x92, 0x39, 0xeb, 0xec, 0x67, 0x83, 0xd6, 0x30, 0x94, 0x41, 0xc6, 0xe2, 0xc5, 0x88, 0xf9, 0x3e, + 0x27, 0x39, 0x49, 0x31, 0xed, 0xf1, 0x86, 0x2f, 0x68, 0x0f, 0xb6, 0x5b, 0xd4, 0xf7, 0x9a, 0xd2, 0xbd, 0x16, 0x36, + 0x30, 0x0a, 0x0b, 0x20, 0x60, 0xd8, 0xc0, 0x23, 0x28, 0x45, 0xe9, 0x62, 0x76, 0xc9, 0x32, 0x54, 0x36, 0xeb, 0xd6, + 0xc8, 0x62, 0x91, 0x33, 0x6f, 0x94, 0xe7, 0xde, 0x78, 0x91, 0x8e, 0x24, 0x17, 0xa9, 0x87, 0x1a, 0xa2, 0x81, 0x34, + 0x39, 0x94, 0xd4, 0x80, 0x70, 0x81, 0xfd, 0x1c, 0x37, 0xb2, 0x41, 0xda, 0x68, 0x0f, 0x09, 0x40, 0x89, 0xbb, 0x66, + 0x3c, 0x83, 0x00, 0x46, 0x32, 0x58, 0x63, 0x41, 0x3e, 0x48, 0x58, 0xa5, 0x5a, 0x22, 0x93, 0xfd, 0x2c, 0xd8, 0x3c, + 0x28, 0x54, 0x06, 0xb3, 0x68, 0xee, 0x33, 0xda, 0x63, 0x8a, 0xb8, 0xa2, 0x74, 0x04, 0xb0, 0xd6, 0xf6, 0xad, 0xcf, + 0x42, 0x16, 0x54, 0x24, 0x85, 0x43, 0x19, 0x8c, 0x45, 0xf6, 0x22, 0x1a, 0x4d, 0xa1, 0x5f, 0x49, 0x30, 0xb1, 0x3d, + 0x6f, 0xa3, 0x8c, 0x45, 0x92, 0xbd, 0x48, 0x18, 0x3c, 0xf9, 0x48, 0xf5, 0x44, 0x98, 0xe4, 0xf4, 0x55, 0x90, 0x70, + 0xf9, 0x46, 0xa4, 0x23, 0xd6, 0xcd, 0x1d, 0xea, 0xe2, 0xb0, 0xef, 0x27, 0x52, 0x66, 0xfc, 0x72, 0x21, 0x99, 0x8f, + 0x52, 0x68, 0x81, 0x48, 0x8e, 0x09, 0x0f, 0x24, 0xbb, 0x91, 0xa7, 0x22, 0x95, 0x2c, 0x95, 0x94, 0x59, 0xa4, 0x92, + 0x2c, 0x88, 0xe6, 0x73, 0x96, 0xc6, 0xa7, 0x53, 0x9e, 0xc4, 0x3e, 0xc7, 0x05, 0x2e, 0x48, 0x24, 0x29, 0xac, 0x91, + 0xf6, 0xb2, 0x10, 0xfe, 0xd9, 0xbd, 0x1a, 0x5f, 0xd2, 0x9e, 0x3a, 0x14, 0x8c, 0x22, 0xd4, 0x1d, 0x8b, 0xcc, 0x37, + 0x2b, 0xf0, 0xc4, 0xd8, 0x93, 0x30, 0xc7, 0xbb, 0x45, 0xc2, 0x72, 0xcc, 0x1a, 0x94, 0x97, 0xdb, 0x68, 0x10, 0xfc, + 0x35, 0x50, 0x7c, 0x81, 0xfd, 0x0c, 0x87, 0x59, 0xf7, 0x2a, 0xca, 0xbc, 0x2f, 0xcc, 0x89, 0xfa, 0xc9, 0x72, 0xb3, + 0xa9, 0xa4, 0x3f, 0x05, 0x32, 0x5b, 0xe4, 0x92, 0xc5, 0xef, 0x6f, 0xe7, 0x2c, 0x27, 0xef, 0x25, 0x9d, 0xca, 0xfe, + 0x54, 0x06, 0x6c, 0x36, 0x97, 0xb7, 0x67, 0x8a, 0x31, 0x86, 0x08, 0x91, 0x11, 0xb4, 0xcc, 0x58, 0x34, 0x02, 0x66, + 0x66, 0xb0, 0xf5, 0xb5, 0x48, 0x6e, 0xc7, 0x3c, 0x49, 0xce, 0x16, 0xf3, 0xb9, 0xc8, 0x24, 0xf9, 0x2b, 0x5d, 0x4a, + 0x51, 0xa1, 0x06, 0xf6, 0x72, 0x99, 0x5f, 0x73, 0x39, 0x9a, 0xfa, 0x12, 0x2f, 0x47, 0x51, 0xce, 0xbc, 0x67, 0x42, + 0x24, 0x2c, 0x4a, 0xc3, 0x8c, 0x66, 0xfd, 0xf7, 0x32, 0x4c, 0x17, 0x49, 0xd2, 0xbd, 0xcc, 0x58, 0xf4, 0xb1, 0xab, + 0xaa, 0xdf, 0x5e, 0xfe, 0xc4, 0x46, 0x32, 0x54, 0xbf, 0x4f, 0xb2, 0x2c, 0xba, 0x85, 0x86, 0x94, 0x42, 0xb3, 0x7e, + 0x16, 0x7e, 0x75, 0xf6, 0xf6, 0x4d, 0xa0, 0x0f, 0x09, 0x1f, 0xdf, 0xfa, 0x59, 0x79, 0xf0, 0xb2, 0x82, 0x8c, 0x33, + 0x31, 0x5b, 0x9b, 0x5a, 0x63, 0x2d, 0xeb, 0xee, 0x00, 0x81, 0xd1, 0x6c, 0x4f, 0x0f, 0xed, 0x42, 0xf0, 0x46, 0xd1, + 0x3c, 0x54, 0x52, 0x33, 0x2f, 0xfc, 0x13, 0xea, 0x62, 0x3f, 0xc3, 0x77, 0x43, 0x2b, 0xb3, 0xdb, 0x25, 0xa3, 0x0a, + 0xce, 0x39, 0x48, 0x18, 0x80, 0x71, 0x14, 0xc9, 0xd1, 0x74, 0xc9, 0xd4, 0x60, 0x85, 0x85, 0x98, 0x15, 0x05, 0xb9, + 0x2e, 0xe9, 0x5d, 0xee, 0x51, 0x9a, 0x29, 0x46, 0x45, 0xe5, 0x6a, 0x95, 0x51, 0x9a, 0x61, 0xf2, 0x1d, 0x5d, 0x46, + 0x76, 0x3d, 0xe1, 0x5e, 0x8b, 0xc0, 0xb9, 0x0c, 0x35, 0x77, 0x21, 0x23, 0x91, 0x5e, 0xb1, 0x4c, 0xb2, 0x2c, 0xfc, + 0x2b, 0xc9, 0xd8, 0x38, 0x01, 0x28, 0xf6, 0xda, 0x64, 0x1a, 0xe5, 0xa7, 0xd3, 0x28, 0x9d, 0xb0, 0x38, 0xbc, 0x96, + 0x05, 0xf9, 0x3b, 0x45, 0x63, 0x9e, 0x46, 0x09, 0xff, 0x85, 0xc5, 0xc8, 0x48, 0x83, 0x13, 0x8f, 0xdd, 0x48, 0x96, + 0xc6, 0xb9, 0xf7, 0xf2, 0xfd, 0xeb, 0x57, 0x66, 0x1f, 0x6b, 0x02, 0x02, 0x2f, 0xf3, 0xc5, 0x9c, 0x65, 0x3e, 0x26, + 0x46, 0x40, 0xbc, 0xe0, 0x8a, 0x39, 0xbe, 0x8e, 0xe6, 0xba, 0x84, 0xe7, 0x1f, 0xe6, 0x71, 0x24, 0xd9, 0xd7, 0x2c, + 0x8d, 0x79, 0x3a, 0xa1, 0x7b, 0x6d, 0x5d, 0x3e, 0x8d, 0x4c, 0x45, 0x5c, 0x16, 0x9d, 0xef, 0xbf, 0x48, 0xd4, 0xba, + 0xcb, 0xc7, 0x85, 0x8f, 0x8b, 0x5c, 0x46, 0x92, 0x8f, 0xbc, 0x28, 0x8e, 0xbf, 0x4c, 0xb9, 0xe4, 0x0a, 0xc0, 0x0c, + 0xb6, 0x07, 0x48, 0x94, 0x69, 0x51, 0x61, 0x01, 0xf7, 0x31, 0xf1, 0x7d, 0x23, 0x00, 0xa6, 0xd8, 0xec, 0xd7, 0xc1, + 0x41, 0xc5, 0xee, 0xfb, 0x2c, 0xd4, 0x95, 0x74, 0x30, 0xc4, 0xc1, 0x7c, 0x91, 0xc3, 0x46, 0xdb, 0x29, 0x40, 0xba, + 0x88, 0xcb, 0x9c, 0x65, 0x57, 0x2c, 0x2e, 0x89, 0x23, 0xf7, 0xf1, 0x72, 0x6d, 0x0e, 0x73, 0x2c, 0x24, 0x1d, 0x0c, + 0xbb, 0x2e, 0xdf, 0x66, 0x86, 0xce, 0x33, 0x31, 0x67, 0x99, 0xe4, 0x2c, 0x2f, 0x59, 0x89, 0x0f, 0x52, 0xb4, 0x64, + 0x27, 0x39, 0xb5, 0xeb, 0x9b, 0xfb, 0x9c, 0x30, 0x5c, 0x63, 0x18, 0x56, 0xd0, 0xbe, 0xb8, 0x52, 0x12, 0x23, 0x27, + 0x1c, 0x13, 0xa9, 0x21, 0xcd, 0x31, 0x2e, 0x30, 0x91, 0x16, 0x5c, 0xcd, 0x8a, 0xcc, 0x6c, 0xb7, 0x20, 0xaa, 0xe9, + 0x77, 0x4a, 0x54, 0x03, 0x43, 0x8b, 0x24, 0x3b, 0x38, 0xf0, 0x59, 0x50, 0x12, 0x05, 0xdd, 0x6b, 0x9b, 0x3d, 0x72, + 0x90, 0xb5, 0x03, 0x6c, 0x98, 0x58, 0x12, 0x86, 0xc9, 0x1e, 0x0b, 0x52, 0x71, 0x32, 0x1a, 0xb1, 0x3c, 0x17, 0xd9, + 0xc1, 0xc1, 0x9e, 0x6a, 0x5f, 0x6a, 0x13, 0xb0, 0x87, 0x6f, 0xaf, 0xd3, 0x0a, 0x02, 0x5c, 0x49, 0x58, 0x23, 0x17, + 0x24, 0xc8, 0x29, 0xa5, 0x70, 0xa0, 0xbe, 0x55, 0x3c, 0x42, 0x74, 0x7e, 0x8e, 0x1a, 0x92, 0x18, 0x34, 0x4c, 0x98, + 0x9d, 0xfa, 0xf6, 0x39, 0xd3, 0xaa, 0x95, 0x52, 0x3c, 0x36, 0x30, 0xa3, 0xcf, 0x4f, 0x10, 0xb3, 0x31, 0x4f, 0x9d, + 0x65, 0xd7, 0x40, 0x22, 0x92, 0xe4, 0xb8, 0x70, 0x36, 0x74, 0xeb, 0xd0, 0x4a, 0xa7, 0xd1, 0x3b, 0xb7, 0x9c, 0x28, + 0x3d, 0xc2, 0xd9, 0xc6, 0x01, 0x1b, 0x16, 0x44, 0xa1, 0xde, 0xae, 0x26, 0x55, 0x80, 0x0e, 0xe4, 0xb0, 0x6b, 0xea, + 0x69, 0xae, 0x31, 0x97, 0xb1, 0x9f, 0x17, 0x2c, 0x97, 0x9a, 0x8e, 0x7d, 0x49, 0x52, 0xc2, 0x71, 0x01, 0xc7, 0x6d, + 0xcc, 0x27, 0x8b, 0x0c, 0xd4, 0x1d, 0x38, 0x8a, 0x2c, 0x5d, 0xcc, 0x98, 0x7d, 0xda, 0x06, 0xdb, 0xdb, 0x39, 0x08, + 0xc4, 0x1c, 0x68, 0xfa, 0x6e, 0x72, 0x02, 0x58, 0x25, 0x5e, 0xad, 0xbe, 0xb3, 0x83, 0x54, 0x5b, 0x59, 0xaa, 0x68, + 0x6b, 0x7b, 0xf2, 0x77, 0x6c, 0xe4, 0xf1, 0x5e, 0x5b, 0x43, 0xff, 0xf7, 0x21, 0xdd, 0x6b, 0x95, 0x14, 0x6c, 0x70, + 0xaa, 0x81, 0xd1, 0x28, 0x7c, 0xab, 0x07, 0xc2, 0x4a, 0xba, 0xd7, 0x88, 0x25, 0x98, 0x6e, 0xd0, 0xe9, 0x94, 0x0e, + 0x40, 0xcf, 0x08, 0xa6, 0xc3, 0x5d, 0xc4, 0x64, 0xb9, 0x81, 0x2f, 0x37, 0xeb, 0x2a, 0xa6, 0x71, 0x55, 0x67, 0x1a, + 0x6b, 0x8b, 0x40, 0xf3, 0xb2, 0x0b, 0x2a, 0x69, 0xcc, 0x1c, 0xf3, 0xaa, 0x8a, 0x70, 0x05, 0x4c, 0xb5, 0x24, 0x67, + 0x88, 0x37, 0xd1, 0x8c, 0xe5, 0x3e, 0xc3, 0x64, 0x57, 0x03, 0x4d, 0x9c, 0xd0, 0x64, 0xe8, 0x88, 0xcd, 0x1c, 0xc4, + 0x26, 0xc7, 0x5a, 0x2b, 0xab, 0x1f, 0xb7, 0x9c, 0xb0, 0x41, 0x3e, 0xac, 0x94, 0x39, 0x67, 0xf1, 0x4a, 0x1e, 0x1b, + 0xea, 0xb6, 0xf8, 0xd3, 0x65, 0x1a, 0x69, 0x4a, 0x69, 0xc8, 0x31, 0xd9, 0x6b, 0xad, 0xef, 0xa3, 0x6d, 0x55, 0xad, + 0x71, 0x30, 0x84, 0x7d, 0x50, 0xe2, 0x22, 0xe0, 0xb9, 0xfa, 0xbf, 0x76, 0xce, 0x00, 0x6d, 0x67, 0x40, 0x16, 0xc1, + 0x38, 0x89, 0xa4, 0xdf, 0x3e, 0x6c, 0x81, 0x26, 0x7a, 0xc5, 0x40, 0x9a, 0x60, 0xbc, 0xb9, 0x14, 0x16, 0x2c, 0xd2, + 0x7c, 0xca, 0xc7, 0xd2, 0x8f, 0xa4, 0x62, 0x28, 0x2c, 0xc9, 0x99, 0x27, 0x6b, 0xfa, 0xb0, 0x62, 0x36, 0x11, 0x90, + 0x5a, 0xa9, 0x7c, 0x31, 0x0b, 0xa9, 0x62, 0x5a, 0xc0, 0x1b, 0x2a, 0x5d, 0xba, 0xe2, 0x31, 0xb6, 0x35, 0x07, 0x7d, + 0xb1, 0xdd, 0xd7, 0x23, 0x86, 0x86, 0x15, 0x70, 0x47, 0x65, 0xe5, 0xa1, 0xcb, 0x1f, 0x4c, 0xa1, 0x0c, 0xa4, 0x78, + 0x25, 0xae, 0x59, 0x76, 0x1a, 0x01, 0xf0, 0xa1, 0xee, 0x5e, 0x68, 0x31, 0xa0, 0xb8, 0xbd, 0xec, 0x5a, 0x7a, 0x39, + 0x57, 0x0b, 0xff, 0x3a, 0x13, 0x33, 0x9e, 0x33, 0xd0, 0xd4, 0x34, 0xfe, 0x53, 0x38, 0x65, 0xea, 0x38, 0x82, 0xa8, + 0x61, 0x25, 0x7d, 0x9d, 0xbc, 0xaa, 0xd3, 0xd7, 0xf9, 0xfe, 0x8b, 0x89, 0x65, 0x7f, 0xf5, 0x43, 0x8c, 0x89, 0x6f, + 0xec, 0x09, 0x47, 0xca, 0x05, 0x53, 0x6c, 0xc4, 0xfb, 0x6a, 0x25, 0x1d, 0xb3, 0xad, 0xa6, 0x2b, 0x32, 0x7d, 0x6c, + 0x70, 0x11, 0xc5, 0x31, 0x68, 0x75, 0x99, 0x48, 0x12, 0x47, 0x50, 0x11, 0xde, 0x2d, 0x45, 0xd3, 0xf9, 0xfe, 0x8b, + 0xb3, 0xbb, 0xa4, 0x13, 0xd4, 0xbb, 0x02, 0xca, 0x02, 0x9a, 0xc6, 0x2c, 0x03, 0x33, 0xd2, 0xd9, 0x2d, 0x23, 0x63, + 0x4f, 0x45, 0x9a, 0xb2, 0x91, 0x64, 0x31, 0x58, 0x29, 0x9c, 0xca, 0x60, 0x2a, 0x72, 0x59, 0x16, 0x56, 0xd0, 0x73, + 0x07, 0x7a, 0x1e, 0x8c, 0xa2, 0x24, 0xf1, 0xb5, 0x45, 0x32, 0x13, 0x57, 0x6c, 0x0b, 0xd4, 0xdd, 0x1a, 0xc8, 0xe5, + 0x30, 0xcc, 0x19, 0x86, 0x05, 0xf9, 0x3c, 0xe1, 0x23, 0x56, 0x0a, 0xae, 0xb3, 0x80, 0xa7, 0x31, 0xbb, 0x01, 0x3e, + 0x82, 0x7b, 0xbd, 0x5e, 0x8b, 0xb4, 0x71, 0xa1, 0x11, 0xbe, 0xdc, 0x40, 0xec, 0x1d, 0x22, 0x13, 0x88, 0x8c, 0xf6, + 0x96, 0xdb, 0xf8, 0x01, 0xc3, 0x8e, 0x9c, 0xe4, 0xd6, 0xb2, 0xd2, 0xbc, 0x19, 0x93, 0x98, 0x25, 0x4c, 0x32, 0xcb, + 0xcb, 0x41, 0x7f, 0xd6, 0x47, 0xf7, 0x5d, 0x89, 0xbf, 0x92, 0x9c, 0xec, 0x29, 0xb3, 0x7b, 0x9e, 0x97, 0x96, 0x7a, + 0xb5, 0x3d, 0x15, 0xb6, 0xfb, 0x52, 0x6f, 0x4f, 0x24, 0x65, 0x34, 0x9a, 0x6a, 0x13, 0xdd, 0xdf, 0x58, 0x52, 0x35, + 0x86, 0xe1, 0xeb, 0xe5, 0x21, 0xfa, 0x60, 0xc1, 0xdc, 0x86, 0x82, 0x33, 0xc3, 0x14, 0x18, 0x58, 0x7d, 0x7a, 0xdb, + 0x4e, 0xa3, 0x24, 0xb9, 0x8c, 0x46, 0x1f, 0xeb, 0xd4, 0x5f, 0x91, 0x01, 0x5d, 0xe7, 0xc6, 0x4e, 0x95, 0xc3, 0xb2, + 0xdc, 0x75, 0x5b, 0x2e, 0x5d, 0x3b, 0x28, 0xfe, 0x5e, 0xab, 0x22, 0xfb, 0xfa, 0x46, 0xef, 0xa4, 0x76, 0x05, 0x11, + 0x37, 0x2b, 0xf3, 0x81, 0x0b, 0x7c, 0x92, 0xe2, 0x2c, 0x3f, 0x30, 0x74, 0x07, 0xb6, 0x46, 0xb1, 0x06, 0x88, 0xc4, + 0xcb, 0x22, 0xe6, 0xf9, 0x6e, 0x0c, 0xfc, 0x21, 0x50, 0x3e, 0x77, 0x66, 0xb8, 0x2f, 0xa0, 0x25, 0x8f, 0x33, 0x2a, + 0x73, 0x09, 0x99, 0xd1, 0x26, 0x2c, 0xa3, 0xf9, 0x1b, 0x68, 0x2e, 0x8a, 0xde, 0xdf, 0xea, 0x2a, 0xd0, 0xc9, 0x00, + 0x8a, 0xbc, 0xeb, 0x2a, 0x13, 0x35, 0x0a, 0x30, 0x3c, 0x95, 0x2b, 0x91, 0x9b, 0xd6, 0x8c, 0x47, 0xa3, 0xae, 0x6b, + 0xfb, 0xdb, 0xb0, 0x5c, 0x41, 0x7d, 0xdf, 0xcf, 0xc1, 0x7e, 0xb3, 0x7a, 0x7d, 0xb5, 0x88, 0x7c, 0x63, 0x11, 0x79, + 0xe0, 0x18, 0x59, 0xb8, 0xa2, 0x65, 0xa7, 0x7b, 0xf8, 0x57, 0xec, 0x36, 0x02, 0x65, 0x35, 0x00, 0xfe, 0x8c, 0x4b, + 0x76, 0x9b, 0x50, 0x49, 0x84, 0x31, 0x70, 0x0c, 0xa5, 0x01, 0xc3, 0xa8, 0xba, 0xa4, 0x58, 0x1f, 0x8d, 0x9a, 0xb1, + 0x9b, 0x12, 0x81, 0xd7, 0x34, 0xfb, 0xa2, 0x30, 0x38, 0x62, 0xd8, 0xec, 0x4d, 0x4d, 0x25, 0x76, 0xb0, 0x42, 0x52, + 0x6a, 0xd4, 0x60, 0xad, 0xf5, 0xac, 0xe3, 0xa6, 0x1c, 0x17, 0x0e, 0x6a, 0x85, 0x9a, 0x9a, 0x3e, 0x69, 0x15, 0xab, + 0x14, 0x93, 0xa9, 0xd5, 0x48, 0x45, 0xb5, 0x6e, 0x4a, 0x91, 0xf5, 0x46, 0xa0, 0xfe, 0xb2, 0x66, 0x12, 0x86, 0x4e, + 0xb3, 0x22, 0x04, 0x96, 0x2a, 0xb6, 0xa1, 0x7b, 0x1b, 0xcd, 0xd4, 0xc6, 0x71, 0x10, 0x2e, 0x5c, 0x84, 0x3b, 0x98, + 0x4d, 0x35, 0xe7, 0x4a, 0x87, 0x74, 0x5a, 0xef, 0xeb, 0x33, 0x22, 0xf4, 0x3e, 0x6c, 0x20, 0x71, 0x5d, 0xf1, 0x54, + 0x24, 0x08, 0x06, 0x6c, 0x0e, 0xca, 0x9d, 0x2b, 0x1f, 0x7c, 0x80, 0x9d, 0xaf, 0x56, 0x1b, 0x44, 0xb7, 0x55, 0xff, + 0xc4, 0x41, 0x65, 0x14, 0xae, 0x56, 0xd7, 0x12, 0xfb, 0x46, 0xf3, 0x25, 0x0c, 0xf7, 0x2d, 0xc7, 0x3d, 0x79, 0x05, + 0xad, 0x94, 0x22, 0x5a, 0x95, 0x94, 0x26, 0x43, 0x9d, 0x66, 0xeb, 0xfb, 0x24, 0x1d, 0xb6, 0x7d, 0xba, 0xc1, 0xbd, + 0x54, 0xa1, 0x11, 0xd3, 0xd5, 0x92, 0x4f, 0xcd, 0xd0, 0x1c, 0x63, 0x1c, 0xe6, 0xca, 0x8a, 0xd9, 0xdb, 0x66, 0x58, + 0x1e, 0x1c, 0xe4, 0xce, 0x40, 0xe7, 0x25, 0x9b, 0xf8, 0xc9, 0x07, 0x91, 0x9c, 0xdf, 0xa6, 0x4a, 0x77, 0xf9, 0xc9, + 0x0a, 0xa1, 0x0d, 0xb3, 0xb4, 0xd5, 0x05, 0x6b, 0x3c, 0xba, 0x8e, 0xb8, 0xf4, 0xca, 0x51, 0xb4, 0x35, 0xee, 0x33, + 0xbc, 0x34, 0xaa, 0x46, 0x90, 0x31, 0x50, 0x1e, 0x81, 0x27, 0x58, 0x15, 0x5a, 0xd3, 0xfd, 0x68, 0xca, 0xc0, 0x11, + 0x6c, 0xb5, 0x88, 0xd2, 0x2e, 0xdc, 0x33, 0x52, 0xc4, 0x0c, 0xbc, 0x1d, 0xf6, 0x62, 0xbd, 0x7b, 0xcd, 0x0e, 0x98, + 0xb3, 0x6c, 0x2c, 0xb2, 0x99, 0xad, 0x2b, 0xd6, 0x9e, 0x0d, 0x67, 0xe4, 0x63, 0x7f, 0xeb, 0xd8, 0x46, 0xfd, 0xef, + 0xae, 0x19, 0xdd, 0x95, 0xb9, 0x5e, 0x13, 0xa5, 0xa5, 0xf4, 0xd5, 0xfe, 0x40, 0x4b, 0x99, 0xb9, 0x6b, 0xde, 0x1b, + 0x67, 0x6a, 0x57, 0x3b, 0x4c, 0xf6, 0xda, 0xdd, 0xd2, 0xe6, 0xb3, 0xd4, 0xd0, 0xd5, 0x8e, 0x0d, 0x23, 0x52, 0xc5, + 0x22, 0x89, 0x0d, 0xb0, 0x1c, 0x13, 0x66, 0xe8, 0xe8, 0x9a, 0x27, 0x49, 0x55, 0xfa, 0x6b, 0xf8, 0x7a, 0x6e, 0xf8, + 0x7a, 0x6a, 0xf9, 0x3a, 0x70, 0x0a, 0xe0, 0xeb, 0x7a, 0xb8, 0xaa, 0x7b, 0xba, 0x71, 0x3a, 0x53, 0xcd, 0xd1, 0x73, + 0x65, 0x47, 0xc3, 0x7c, 0x0b, 0x0b, 0x01, 0x2e, 0x35, 0xaf, 0x8f, 0xbe, 0x71, 0xc2, 0x80, 0x01, 0xa8, 0x5d, 0x98, + 0xcc, 0x75, 0x51, 0x7c, 0xf4, 0x31, 0xc9, 0x0b, 0x56, 0x52, 0xf6, 0xc9, 0x0b, 0x70, 0xd2, 0x39, 0xcb, 0x01, 0x21, + 0xa6, 0x8a, 0x7f, 0x95, 0x12, 0x65, 0x57, 0xc7, 0xcd, 0xea, 0x72, 0xbb, 0x3a, 0xe0, 0xf4, 0xd5, 0xea, 0xe2, 0xbb, + 0x79, 0xbd, 0x5a, 0x1e, 0x2f, 0x97, 0x57, 0xed, 0xf7, 0x6a, 0xe5, 0xaf, 0x95, 0x80, 0xff, 0xde, 0x98, 0x28, 0x59, + 0x39, 0x3a, 0xf0, 0x00, 0x17, 0x33, 0x50, 0x50, 0xe8, 0x45, 0x97, 0x22, 0xee, 0xd5, 0xa7, 0x1c, 0x3c, 0xca, 0x4d, + 0xaf, 0xfb, 0x9f, 0x8a, 0xd9, 0x1c, 0xb4, 0xb1, 0x35, 0x92, 0x9e, 0x30, 0x33, 0x61, 0x55, 0x5f, 0x6c, 0x29, 0xab, + 0xf5, 0x51, 0xe7, 0xb1, 0x46, 0x4d, 0xa5, 0xbd, 0xbc, 0xd7, 0x2a, 0x16, 0x65, 0x51, 0xc9, 0x38, 0xb6, 0x39, 0x55, + 0x4e, 0xd7, 0x5d, 0x32, 0xb6, 0xe2, 0xad, 0xcf, 0x35, 0x1f, 0xe6, 0xc0, 0xeb, 0x1c, 0xf6, 0x63, 0xc9, 0xdd, 0xdd, + 0xff, 0xa2, 0x42, 0xce, 0xb2, 0x58, 0x43, 0xdf, 0xb2, 0x28, 0x4e, 0xb4, 0x91, 0x4d, 0x4e, 0x76, 0x5b, 0xc3, 0x55, + 0x9d, 0x31, 0x16, 0x07, 0x43, 0x72, 0xb2, 0xa9, 0x3a, 0xd2, 0xe5, 0x4c, 0xc4, 0x2c, 0x44, 0x62, 0xce, 0x52, 0x54, + 0x80, 0x57, 0xd5, 0xec, 0xfd, 0x48, 0xfa, 0xcb, 0x77, 0x75, 0xf7, 0x6a, 0x78, 0x52, 0x80, 0xf7, 0xeb, 0x8b, 0x4d, + 0xc7, 0xeb, 0xb7, 0x2c, 0xcb, 0x95, 0x22, 0x5a, 0xea, 0xb4, 0x5f, 0x54, 0x62, 0xe9, 0x8b, 0x70, 0x67, 0xfb, 0xca, + 0x04, 0x41, 0xed, 0xe0, 0x71, 0x70, 0x84, 0xb0, 0x72, 0x0b, 0x7f, 0x65, 0x0e, 0xfc, 0x73, 0xeb, 0x16, 0x7e, 0x41, + 0x9f, 0xd7, 0xbd, 0xc2, 0xb1, 0xa4, 0x2f, 0xfa, 0x2f, 0xac, 0xc5, 0x2c, 0x12, 0x3e, 0xba, 0xf5, 0x51, 0xc2, 0x65, + 0x13, 0x42, 0x6f, 0x88, 0x2c, 0x75, 0x05, 0xb8, 0x14, 0x95, 0x3b, 0xbb, 0xb0, 0xb6, 0x1e, 0x91, 0x92, 0xa2, 0xfd, + 0x84, 0xcb, 0x7d, 0x44, 0x66, 0xf4, 0x02, 0x7e, 0xec, 0x2f, 0xfd, 0xd7, 0x91, 0x9c, 0x06, 0x59, 0x94, 0xc6, 0x62, + 0xe6, 0xe3, 0x06, 0x42, 0x38, 0xc8, 0x95, 0xbd, 0xf1, 0x39, 0x2e, 0xf6, 0x2f, 0xc8, 0x8d, 0xa4, 0xa8, 0x8f, 0x1a, + 0x33, 0xf2, 0x52, 0xd2, 0x8b, 0xe3, 0xfd, 0xe5, 0x8d, 0x2c, 0x7a, 0x17, 0xe4, 0xa6, 0xf4, 0xd8, 0x93, 0xaf, 0xa9, + 0x8f, 0x69, 0xef, 0xc6, 0x40, 0x73, 0x2a, 0x66, 0xda, 0x73, 0x8f, 0x30, 0xf9, 0x00, 0x71, 0x95, 0xac, 0xe2, 0x36, + 0x26, 0xb4, 0xb2, 0x47, 0x91, 0x50, 0x2e, 0x02, 0x74, 0x70, 0xe0, 0x94, 0x95, 0xaa, 0x02, 0x39, 0x91, 0xb4, 0x66, + 0x90, 0x93, 0x37, 0x2a, 0x42, 0x73, 0x22, 0xfd, 0x0c, 0xdb, 0x61, 0x7c, 0xeb, 0x87, 0x36, 0x47, 0x33, 0x1b, 0x68, + 0x0f, 0x43, 0xc0, 0x25, 0xcb, 0x22, 0x29, 0xb2, 0x21, 0x76, 0xd5, 0x0f, 0xf2, 0x37, 0x7a, 0x31, 0xf0, 0xfe, 0xd3, + 0x3f, 0xfd, 0x38, 0xfe, 0x31, 0x1b, 0x5e, 0x90, 0xb7, 0xf4, 0xf0, 0xd8, 0xef, 0x87, 0xfe, 0x5e, 0xb3, 0xb9, 0xfa, + 0xf1, 0x70, 0xf0, 0x8f, 0xa8, 0xf9, 0xcb, 0x49, 0xf3, 0x87, 0x21, 0x5e, 0xf9, 0x3f, 0x1e, 0xf6, 0x07, 0xe6, 0x69, + 0xf0, 0x8f, 0xde, 0x8f, 0xf9, 0xf0, 0xcf, 0xba, 0x70, 0x1f, 0xe3, 0xc3, 0x09, 0x59, 0x48, 0x7a, 0xd8, 0x6c, 0xf6, + 0x0e, 0x27, 0x64, 0x2e, 0xe9, 0x21, 0xfc, 0x7f, 0x49, 0xdf, 0xb1, 0xc9, 0x8b, 0x9b, 0xb9, 0x7f, 0xd1, 0x5b, 0xed, + 0x2f, 0xff, 0x56, 0xc0, 0xa8, 0x83, 0x7f, 0xfc, 0xf8, 0x63, 0x8e, 0x1e, 0xf4, 0xe8, 0xe1, 0xb0, 0x81, 0x7d, 0x28, + 0xfd, 0x33, 0x55, 0xff, 0xfa, 0xfd, 0x70, 0xf0, 0x0f, 0x03, 0x05, 0x7a, 0xf0, 0xe3, 0xc5, 0x71, 0x8f, 0x0e, 0x57, + 0x3e, 0x5a, 0x3d, 0xc0, 0x2b, 0x8c, 0x57, 0xfb, 0xf8, 0x82, 0xa0, 0x09, 0xc2, 0x64, 0x22, 0xe9, 0xe1, 0x83, 0xc3, + 0x09, 0xb9, 0x92, 0xf4, 0x10, 0x1d, 0x4e, 0xc8, 0x0b, 0x49, 0x0f, 0xff, 0xe1, 0xf7, 0x43, 0xed, 0x61, 0x5b, 0x29, + 0xf7, 0xc6, 0x0a, 0x82, 0x1b, 0x51, 0xc6, 0xa2, 0x95, 0xe4, 0x32, 0x61, 0x78, 0xff, 0x90, 0x93, 0x33, 0x85, 0x26, + 0x5f, 0x82, 0x13, 0x06, 0x6c, 0x3b, 0x7f, 0x79, 0x0e, 0x9b, 0x0d, 0x34, 0xb3, 0x1f, 0x66, 0x44, 0xfb, 0x01, 0xf2, + 0x50, 0x92, 0xab, 0x28, 0x59, 0xb0, 0x3c, 0x64, 0x05, 0x26, 0x23, 0x7a, 0x26, 0xfd, 0x36, 0x26, 0xef, 0x24, 0xfc, + 0xe8, 0x60, 0x72, 0x66, 0x02, 0x98, 0x70, 0x90, 0x35, 0x51, 0xa5, 0x42, 0x6b, 0x2c, 0x08, 0x93, 0xf9, 0x96, 0x4a, + 0x39, 0x05, 0xef, 0x02, 0x26, 0xe3, 0x5a, 0xb8, 0x93, 0x5c, 0x53, 0x4b, 0x12, 0xef, 0x33, 0xc6, 0xbe, 0x8b, 0x92, + 0x8f, 0x2c, 0xf3, 0x6f, 0x48, 0xbb, 0xf3, 0x39, 0x51, 0x2e, 0xe8, 0xbd, 0x36, 0xee, 0x96, 0xb1, 0xaa, 0x53, 0xa9, + 0x63, 0x04, 0x20, 0x64, 0xeb, 0xbe, 0x18, 0xd8, 0xf1, 0xbd, 0x6c, 0xc3, 0x61, 0x95, 0x45, 0xd7, 0x08, 0xd7, 0xe3, + 0xa2, 0x3c, 0xbd, 0x8a, 0x12, 0x1e, 0x7b, 0x92, 0xcd, 0xe6, 0x49, 0x24, 0x99, 0x67, 0xd6, 0xeb, 0x45, 0x30, 0x10, + 0x2a, 0x55, 0x86, 0xd8, 0x31, 0x38, 0x63, 0x1b, 0x70, 0x82, 0xb3, 0xe2, 0x43, 0x74, 0xca, 0xa8, 0x1d, 0xaf, 0xab, + 0xe0, 0xd7, 0x7a, 0x7c, 0xaf, 0xd9, 0x06, 0x47, 0xd8, 0x50, 0x89, 0xe7, 0x9c, 0xa4, 0x14, 0x84, 0x68, 0xa7, 0x8f, + 0x8e, 0xf3, 0xab, 0x49, 0x0f, 0x41, 0x6c, 0x46, 0xd0, 0xb7, 0xca, 0x2f, 0x04, 0x0d, 0xa6, 0xb4, 0xd5, 0x9d, 0x1e, + 0xb3, 0xee, 0xb4, 0xd1, 0xb0, 0x3a, 0x74, 0x42, 0xb3, 0xc1, 0x54, 0x77, 0x8f, 0x48, 0x4c, 0x16, 0xb4, 0xd9, 0x26, + 0x13, 0xda, 0x52, 0x5d, 0xba, 0x93, 0xe3, 0xc4, 0x4c, 0x73, 0x70, 0xe0, 0x8b, 0x20, 0x89, 0x72, 0xf9, 0x25, 0x18, + 0xfb, 0x74, 0x42, 0x62, 0x2a, 0x02, 0x76, 0xc3, 0x46, 0x7e, 0x82, 0x49, 0x6c, 0x38, 0x0d, 0xee, 0xe2, 0x09, 0x75, + 0x9a, 0x81, 0x11, 0x41, 0xdf, 0xf6, 0xe3, 0x41, 0x7b, 0x48, 0x29, 0x45, 0x7b, 0xcd, 0x26, 0xea, 0x0b, 0xba, 0x90, + 0x21, 0x94, 0x38, 0xaa, 0x32, 0x9d, 0x43, 0x51, 0xc7, 0x29, 0xf2, 0x5f, 0xc8, 0x40, 0xb2, 0x5c, 0xfa, 0x50, 0x0c, + 0xe6, 0x7f, 0x6e, 0x09, 0x1b, 0x1d, 0x1f, 0xa2, 0x06, 0x94, 0x2a, 0xe2, 0xc4, 0x44, 0xd0, 0x4b, 0x1c, 0xc6, 0x83, + 0xa3, 0xa1, 0xcb, 0xff, 0x55, 0x21, 0x4c, 0x7e, 0xd9, 0x8f, 0x07, 0x2d, 0x35, 0x79, 0x0f, 0xf5, 0x7d, 0x41, 0x73, + 0xad, 0xa0, 0xf5, 0xf3, 0xf0, 0xad, 0x5a, 0x2a, 0x0e, 0x0d, 0x70, 0x66, 0xde, 0x05, 0x6d, 0x76, 0x42, 0x7f, 0xe1, + 0x2e, 0xa2, 0x09, 0x93, 0x19, 0x2c, 0x90, 0x88, 0x42, 0x7b, 0x22, 0x28, 0xcc, 0x58, 0x75, 0xbb, 0x0c, 0xcd, 0xf3, + 0x03, 0xf4, 0xa0, 0x7f, 0x25, 0xc3, 0x89, 0xd4, 0xd3, 0x5f, 0xc9, 0xd5, 0x0a, 0xfe, 0x9f, 0xc8, 0xbe, 0xa0, 0x97, + 0xaa, 0x68, 0x61, 0x8a, 0xe6, 0x50, 0xf4, 0x36, 0x04, 0x50, 0x49, 0x5e, 0x2a, 0x59, 0x7a, 0x4f, 0xae, 0xa8, 0x82, + 0xfd, 0xe0, 0x20, 0x1b, 0x4c, 0x1b, 0xed, 0x21, 0xf8, 0xf7, 0x33, 0x99, 0x7f, 0xc7, 0xe5, 0xd4, 0x47, 0x87, 0x3d, + 0x84, 0xfb, 0xc8, 0x83, 0xad, 0xed, 0xa6, 0x0d, 0xaa, 0x31, 0x9c, 0x34, 0x5e, 0xca, 0x70, 0xd1, 0xa3, 0xad, 0xbe, + 0xcf, 0x8d, 0x3f, 0x0f, 0x93, 0xc4, 0x30, 0xce, 0x16, 0x59, 0xe0, 0x86, 0x94, 0x0d, 0xfb, 0xbc, 0xc0, 0x8d, 0x59, + 0xe3, 0x0a, 0x87, 0x49, 0x63, 0xd6, 0xf0, 0x17, 0x94, 0xd2, 0x66, 0xa7, 0xec, 0x66, 0xa5, 0xdf, 0x14, 0x87, 0x57, + 0xd6, 0xd9, 0x39, 0x50, 0xc7, 0x21, 0x6d, 0xf8, 0xd9, 0x80, 0x0d, 0x57, 0x2b, 0x74, 0xdc, 0xef, 0x21, 0xdc, 0xf0, + 0x2d, 0xa1, 0x1d, 0x5a, 0x4a, 0xc3, 0x98, 0xf0, 0x61, 0x61, 0x42, 0x49, 0xef, 0x6b, 0x61, 0xa3, 0x65, 0x75, 0xd8, + 0x1d, 0x1e, 0xc0, 0x8a, 0xd2, 0x8e, 0xd1, 0xfa, 0xea, 0x1c, 0x96, 0x69, 0x89, 0x39, 0xa5, 0x2d, 0x22, 0xa8, 0xf5, + 0x5d, 0x4f, 0xa9, 0xac, 0x08, 0x3e, 0xa1, 0x55, 0x73, 0x32, 0x88, 0x48, 0x3c, 0xa4, 0xaf, 0xb5, 0x3d, 0xd2, 0xb5, + 0x7e, 0x71, 0x96, 0xd0, 0xf7, 0x6b, 0xd1, 0xdb, 0x08, 0x62, 0x2b, 0xd7, 0xc1, 0x68, 0x91, 0x65, 0x2c, 0x95, 0x6f, + 0x44, 0x6c, 0xd4, 0x34, 0x96, 0x80, 0xa5, 0x04, 0x61, 0x59, 0x02, 0x3a, 0x5a, 0xc7, 0x9e, 0x8c, 0xc5, 0x46, 0xf5, + 0x84, 0x2e, 0xb4, 0xfa, 0xa4, 0x82, 0xb5, 0xdd, 0x89, 0xb1, 0x8b, 0x7d, 0x4c, 0x16, 0x26, 0x8a, 0xeb, 0x07, 0x41, + 0x30, 0x09, 0x46, 0x50, 0x0d, 0x13, 0xe4, 0xb8, 0x50, 0xe7, 0xc8, 0xcf, 0xe9, 0x75, 0x90, 0xb2, 0x1b, 0x35, 0xab, + 0x8f, 0x2b, 0xc9, 0x6c, 0x8f, 0xd7, 0xf1, 0xb4, 0xab, 0xd8, 0x4d, 0x1e, 0xa4, 0x22, 0x66, 0x80, 0x1e, 0x88, 0xdb, + 0x9b, 0xa2, 0x69, 0x94, 0xbb, 0xf1, 0xa9, 0x0a, 0xbe, 0x81, 0xeb, 0xbc, 0x9e, 0x80, 0xc7, 0x57, 0xe9, 0x5a, 0x65, + 0x63, 0xed, 0x06, 0xc7, 0x98, 0x8f, 0xfd, 0x49, 0x00, 0x71, 0x3d, 0x45, 0x42, 0x12, 0x4c, 0xb9, 0x89, 0x4b, 0x54, + 0xb3, 0x72, 0xcc, 0x2b, 0x1a, 0x0f, 0x44, 0xa3, 0xa1, 0xbc, 0xd0, 0x0b, 0x4d, 0x12, 0x13, 0x4c, 0xae, 0xca, 0xb3, + 0x65, 0xdb, 0xbd, 0x95, 0xb4, 0x3e, 0x95, 0x7f, 0x55, 0x77, 0xe7, 0x36, 0xa4, 0xc4, 0xca, 0x53, 0x28, 0xfd, 0x19, + 0x26, 0xcf, 0xe8, 0xa1, 0x3f, 0x08, 0xfa, 0x7f, 0x19, 0xe2, 0xbe, 0x1f, 0xfc, 0x19, 0x1f, 0x6a, 0xce, 0x71, 0x85, + 0xbb, 0x89, 0x9e, 0x63, 0xa9, 0xe2, 0x97, 0x6d, 0xa2, 0x3c, 0x89, 0x61, 0x4a, 0xd2, 0x68, 0xc6, 0xc2, 0x67, 0x70, + 0xc8, 0x2d, 0xe1, 0xbc, 0x95, 0x04, 0x28, 0x29, 0x7c, 0x66, 0x78, 0x49, 0x80, 0xfa, 0xaf, 0x64, 0xf9, 0xd4, 0x47, + 0xfd, 0xe7, 0xd5, 0xd3, 0x5f, 0x50, 0xff, 0x17, 0x19, 0xfe, 0x5c, 0x18, 0x6f, 0x77, 0x6d, 0x8e, 0xc7, 0x76, 0x8e, + 0x42, 0x6f, 0x8d, 0x83, 0xbb, 0x05, 0xde, 0x74, 0x74, 0x4c, 0x70, 0xc1, 0xc7, 0x25, 0x33, 0xca, 0x03, 0x19, 0x4d, + 0x00, 0xa9, 0xce, 0x1e, 0xe4, 0x6e, 0x5c, 0xbf, 0x5a, 0x31, 0x90, 0x8a, 0xa5, 0x57, 0x40, 0xe6, 0xa4, 0xd7, 0xc2, + 0xcb, 0x5a, 0x5b, 0xa5, 0x33, 0xd5, 0xe3, 0xe8, 0x25, 0x9f, 0xbe, 0xa2, 0xad, 0xee, 0xd5, 0xf1, 0xa4, 0x7b, 0xd5, + 0x68, 0xe0, 0xdc, 0x92, 0xd6, 0x62, 0x70, 0x35, 0x24, 0x5f, 0x83, 0x53, 0xcf, 0xa5, 0x25, 0x52, 0x5b, 0x5e, 0xc7, + 0x2c, 0xaf, 0xd1, 0x48, 0x0b, 0xdc, 0x75, 0xba, 0x4e, 0x74, 0xd7, 0xa2, 0xd0, 0x38, 0x59, 0x27, 0xb5, 0xa7, 0x58, + 0x95, 0x40, 0x32, 0x14, 0xa5, 0xf4, 0x46, 0xe2, 0xad, 0xa3, 0xc2, 0x98, 0xd0, 0x5d, 0x9d, 0x59, 0x60, 0x9f, 0x5a, + 0x4a, 0xf8, 0x80, 0x05, 0xe8, 0x5a, 0x7a, 0x82, 0x67, 0x64, 0xd1, 0x68, 0x2b, 0x32, 0x6f, 0xb6, 0xbb, 0xf5, 0xb1, + 0x9e, 0x54, 0x63, 0x91, 0x45, 0x83, 0xce, 0x4a, 0x2c, 0x15, 0x69, 0xa3, 0x51, 0xd4, 0x83, 0x9d, 0xf6, 0xe4, 0xd6, + 0x02, 0x10, 0x37, 0xeb, 0x49, 0x19, 0x56, 0xc2, 0x56, 0x32, 0x95, 0x07, 0x3c, 0x4d, 0x59, 0x06, 0x52, 0x94, 0x4a, + 0xc2, 0x8b, 0xa2, 0x92, 0xec, 0x20, 0x46, 0x09, 0xa3, 0x19, 0x70, 0x1e, 0x65, 0x77, 0x91, 0x94, 0x08, 0x32, 0x55, + 0x7c, 0x83, 0x52, 0x7a, 0x66, 0xd3, 0x59, 0xa4, 0xe2, 0x41, 0x09, 0xe5, 0x8e, 0x4c, 0xca, 0x29, 0x0b, 0xce, 0xf7, + 0x4f, 0xc5, 0x9d, 0x36, 0xd9, 0x80, 0x0f, 0x43, 0xd5, 0x2c, 0x31, 0x9c, 0x2b, 0xa2, 0x1f, 0x7c, 0x89, 0xcb, 0xe8, + 0x48, 0xa0, 0x18, 0xe0, 0x73, 0x9e, 0x31, 0xa5, 0x83, 0xef, 0x5b, 0xbb, 0x2f, 0xa9, 0x2b, 0x90, 0x89, 0xeb, 0xbd, + 0x01, 0x44, 0x46, 0xe0, 0xdc, 0x49, 0xe9, 0x46, 0xb3, 0xf3, 0xfd, 0x93, 0xb7, 0xdb, 0x6c, 0xe0, 0xd5, 0xca, 0x58, + 0xbf, 0x4a, 0xb7, 0x21, 0x51, 0x05, 0x69, 0x62, 0x7e, 0x84, 0x7e, 0xa2, 0x54, 0xa4, 0xc8, 0xcf, 0x80, 0x8a, 0xce, + 0xf7, 0x4f, 0xde, 0xfb, 0x99, 0xf2, 0x2d, 0x61, 0xe2, 0x2e, 0xdb, 0x17, 0xd4, 0x9f, 0x52, 0x86, 0xf5, 0xda, 0x4b, + 0xd6, 0x25, 0x1c, 0x01, 0x1e, 0x4e, 0x55, 0x25, 0x58, 0x10, 0x03, 0x3e, 0xa4, 0x89, 0xc1, 0x00, 0x4d, 0x30, 0x49, + 0x6a, 0x76, 0x19, 0x85, 0x0d, 0x50, 0x73, 0x9d, 0xc1, 0x4e, 0x04, 0x5a, 0xf5, 0xc3, 0x24, 0x51, 0xb3, 0xca, 0x42, + 0x0b, 0x8f, 0x67, 0x1b, 0x59, 0x69, 0x95, 0x39, 0xfa, 0x2d, 0xd8, 0x4e, 0xf6, 0xe1, 0x0d, 0xb5, 0x96, 0x84, 0x29, + 0x78, 0x6e, 0xd3, 0xc7, 0xce, 0xf7, 0x4f, 0x5e, 0x9b, 0x0c, 0xb2, 0x79, 0x64, 0xf9, 0xfd, 0x86, 0x89, 0x79, 0xf2, + 0x3a, 0xa8, 0x6a, 0x55, 0xe3, 0xf3, 0xfd, 0x93, 0x0f, 0xdb, 0x9a, 0x41, 0x79, 0xb1, 0xa8, 0x6c, 0x7c, 0x05, 0xdf, + 0x92, 0x25, 0xe1, 0xd2, 0x08, 0x87, 0x90, 0x17, 0x44, 0x09, 0xa4, 0x30, 0x2f, 0x4a, 0xd7, 0xc8, 0x73, 0x92, 0x52, + 0x15, 0x06, 0xaa, 0xef, 0x9a, 0x51, 0xf3, 0xb8, 0x48, 0xcf, 0x46, 0x62, 0xce, 0x76, 0xc4, 0x86, 0x6e, 0x70, 0xc0, + 0x67, 0x90, 0x3a, 0xa3, 0x40, 0xe7, 0x64, 0xaf, 0x85, 0xbb, 0x75, 0xf1, 0x95, 0x2a, 0x22, 0x15, 0x35, 0xd9, 0x42, + 0xa6, 0xb4, 0x45, 0x12, 0xda, 0x22, 0x11, 0xcd, 0x07, 0x2d, 0x2d, 0x20, 0xba, 0x51, 0x39, 0xae, 0x16, 0x33, 0x90, + 0x15, 0x66, 0x4e, 0xab, 0x16, 0xc0, 0x71, 0x37, 0x52, 0xbe, 0x47, 0x25, 0xd3, 0x63, 0x45, 0x16, 0x6f, 0x7c, 0x41, + 0x84, 0x1a, 0xf8, 0x8c, 0x5f, 0x26, 0x90, 0x58, 0x02, 0xab, 0x22, 0x12, 0x87, 0x65, 0xd3, 0xb6, 0x69, 0x1a, 0x05, + 0x6a, 0x9f, 0x04, 0x89, 0x02, 0xe0, 0xdc, 0x24, 0x32, 0x79, 0x38, 0xf9, 0x66, 0x97, 0xc7, 0x07, 0x07, 0xbe, 0xee, + 0xf4, 0xa5, 0xf4, 0x85, 0xad, 0xaf, 0x22, 0x77, 0xdf, 0x6a, 0x5e, 0x11, 0x63, 0x05, 0x7f, 0xa3, 0x91, 0x0c, 0x0b, + 0x08, 0x43, 0xfb, 0x51, 0x1d, 0x83, 0x16, 0x78, 0xa5, 0xeb, 0xd5, 0x97, 0xdf, 0x68, 0x94, 0x51, 0xda, 0x3a, 0xb6, + 0x6e, 0x48, 0x5a, 0x5c, 0xf9, 0x65, 0xea, 0x4f, 0x6b, 0x23, 0x5f, 0xca, 0x82, 0x80, 0xb9, 0x4b, 0xb3, 0xdc, 0x2e, + 0xc6, 0x39, 0x12, 0x1c, 0xda, 0x7d, 0x69, 0xb2, 0x16, 0x88, 0xca, 0xae, 0x32, 0x8d, 0x2c, 0x3b, 0xeb, 0xe0, 0xd0, + 0x36, 0x82, 0xa8, 0x14, 0x34, 0x6a, 0x14, 0x86, 0xbc, 0xdf, 0x6c, 0xe6, 0x5c, 0x92, 0x1c, 0x1b, 0x27, 0x97, 0x82, + 0x42, 0x21, 0xab, 0x53, 0x22, 0xe5, 0x25, 0x9d, 0xef, 0x26, 0xf9, 0x13, 0x87, 0xe4, 0x9f, 0x51, 0xe6, 0x90, 0xbf, + 0x76, 0x71, 0x04, 0xc2, 0x38, 0x17, 0x72, 0x5b, 0x75, 0x3a, 0xa7, 0xe0, 0x44, 0xab, 0x63, 0xb4, 0x16, 0x56, 0xdc, + 0xc1, 0x50, 0xdc, 0x13, 0xa2, 0xdc, 0x90, 0xc4, 0xc6, 0x80, 0xfd, 0x2a, 0xa8, 0x06, 0x53, 0x6f, 0xf3, 0xe9, 0xb9, + 0x1c, 0xf0, 0xe4, 0xc3, 0xdd, 0xf1, 0xd0, 0xd3, 0xf9, 0xe6, 0xc9, 0x75, 0x72, 0x3f, 0x61, 0xd5, 0xce, 0xc1, 0xad, + 0x67, 0x82, 0xc2, 0xfc, 0x65, 0x1c, 0xbb, 0xce, 0x7c, 0xd6, 0x0e, 0xa1, 0x95, 0x7f, 0x00, 0x6d, 0xbb, 0xad, 0x5a, + 0x30, 0x67, 0x58, 0xe0, 0x47, 0x3a, 0x03, 0x35, 0xca, 0x76, 0xb0, 0x8f, 0x13, 0xd5, 0x80, 0xa5, 0xf1, 0xf6, 0xea, + 0x67, 0x85, 0x21, 0x13, 0x0d, 0x1a, 0x5e, 0x02, 0xff, 0xd3, 0x24, 0x0f, 0x74, 0xa3, 0xe4, 0x02, 0x20, 0x68, 0xae, + 0xf0, 0x54, 0x21, 0x0c, 0xa1, 0xca, 0xfb, 0xfe, 0x72, 0x8f, 0xd2, 0x79, 0xe5, 0x7d, 0x7c, 0x57, 0xa5, 0x5e, 0x01, + 0x59, 0xe0, 0x10, 0xcc, 0xc7, 0xb2, 0x40, 0x87, 0x2f, 0xcf, 0x6c, 0x73, 0x65, 0x42, 0x06, 0x95, 0xc6, 0xed, 0x84, + 0x36, 0x95, 0x5b, 0x4e, 0xd7, 0x5b, 0x34, 0xac, 0xd5, 0xee, 0x43, 0xed, 0x1b, 0xa9, 0x60, 0x84, 0xe7, 0xf7, 0xaa, + 0xb5, 0x1d, 0xb7, 0xf8, 0xb8, 0x9e, 0xbf, 0xb2, 0xb6, 0x29, 0x01, 0x4f, 0x73, 0x96, 0xc9, 0x67, 0x6c, 0x2c, 0x32, + 0x88, 0x59, 0x94, 0x38, 0xc1, 0xc5, 0xbe, 0xe3, 0xb7, 0x53, 0xeb, 0x73, 0x02, 0x05, 0x6b, 0x0b, 0x54, 0xbf, 0x3e, + 0xaa, 0xa0, 0xf5, 0xf9, 0x7a, 0xaf, 0xf9, 0xc1, 0xc1, 0x87, 0x0a, 0x4d, 0x06, 0x4a, 0x05, 0x85, 0xc3, 0xb4, 0xb4, + 0x4a, 0x63, 0x22, 0xb9, 0xfb, 0x7e, 0xe9, 0x04, 0xb0, 0x0c, 0xc3, 0xe5, 0x3d, 0x2f, 0xa9, 0x2c, 0x26, 0xeb, 0x2c, + 0xde, 0x38, 0x27, 0xb8, 0x6b, 0xb8, 0x00, 0x87, 0x07, 0x53, 0x5b, 0x7b, 0x8b, 0xf2, 0x2a, 0x19, 0xb6, 0x84, 0xe1, + 0x14, 0x90, 0xe5, 0x2b, 0x33, 0xc4, 0xa1, 0xc0, 0xad, 0x66, 0xc9, 0x29, 0xe8, 0x95, 0x53, 0x92, 0x07, 0x53, 0x48, + 0x7f, 0xad, 0x1d, 0x59, 0x8c, 0x89, 0x4e, 0xcc, 0x71, 0x52, 0x09, 0x4e, 0x5e, 0x6e, 0x73, 0x29, 0x5b, 0xa2, 0x66, + 0x4a, 0xea, 0xa8, 0x16, 0xb8, 0xec, 0x10, 0x5c, 0xf9, 0xdc, 0x28, 0x6e, 0x36, 0x6e, 0x06, 0x0c, 0xf8, 0x99, 0xf4, + 0x75, 0x30, 0x0a, 0x64, 0x86, 0x08, 0x16, 0x7e, 0x6d, 0xea, 0xae, 0x50, 0xdd, 0x88, 0x41, 0xdc, 0xd4, 0x45, 0x93, + 0x50, 0x71, 0xbd, 0xd3, 0x8a, 0x97, 0x8e, 0x75, 0x06, 0xb5, 0xb4, 0x5c, 0xb0, 0x4a, 0x24, 0x71, 0x96, 0x3f, 0xd6, + 0x49, 0xd1, 0x65, 0x23, 0xc2, 0x14, 0x18, 0xef, 0xd5, 0x1e, 0xb0, 0x02, 0xfe, 0x5f, 0x9e, 0x48, 0x67, 0x47, 0xad, + 0x13, 0x5b, 0xcd, 0xe9, 0x48, 0xfd, 0x77, 0x90, 0xea, 0xb2, 0x7e, 0xe6, 0x5f, 0x2a, 0x59, 0xc8, 0x49, 0x5e, 0x63, + 0xec, 0xa9, 0x62, 0xec, 0x18, 0xf4, 0x34, 0x9b, 0xf8, 0xdd, 0x37, 0x19, 0x2f, 0xdc, 0x48, 0x39, 0x43, 0x62, 0x5f, + 0x97, 0xd1, 0x72, 0xe7, 0xf7, 0xda, 0x6e, 0x84, 0x9c, 0x42, 0x16, 0x10, 0x31, 0x9c, 0x3d, 0xc5, 0x24, 0x6f, 0x34, + 0xba, 0xf9, 0x31, 0xab, 0x9c, 0x24, 0x15, 0x8c, 0x1c, 0x02, 0xba, 0x40, 0xf0, 0x35, 0x19, 0x0a, 0x21, 0x7f, 0x9b, + 0x99, 0x9d, 0x83, 0xaf, 0xfd, 0xe4, 0x9d, 0xef, 0x72, 0x35, 0xb7, 0x6d, 0x19, 0x34, 0x85, 0xf5, 0xf8, 0x55, 0xc0, + 0xe5, 0xeb, 0xbb, 0x13, 0x3c, 0x00, 0xee, 0xbd, 0x36, 0x81, 0x54, 0x34, 0xdc, 0x95, 0x9a, 0x25, 0x94, 0xa7, 0xaf, + 0x8b, 0xab, 0xac, 0x44, 0x77, 0xb2, 0xae, 0xac, 0x8c, 0x59, 0x49, 0xf3, 0xa2, 0xc8, 0x59, 0x15, 0xde, 0x5f, 0x4b, + 0xbf, 0x54, 0xc2, 0x65, 0xd3, 0xdb, 0x7e, 0x3a, 0xa7, 0x92, 0x38, 0x84, 0xfa, 0xf5, 0xae, 0xd8, 0x47, 0x05, 0x26, + 0x9c, 0x6b, 0x23, 0x14, 0x7f, 0xde, 0x26, 0x14, 0x49, 0x6a, 0x8e, 0xbc, 0x12, 0x88, 0xed, 0x7b, 0x08, 0x44, 0xe3, + 0x66, 0xb7, 0x32, 0x11, 0xd4, 0x91, 0x9a, 0x4c, 0xac, 0x6f, 0x29, 0x4d, 0x09, 0x37, 0xbb, 0xd1, 0xeb, 0xac, 0x56, + 0x7c, 0xd0, 0x02, 0x37, 0x12, 0x42, 0xf0, 0xb3, 0xad, 0x7f, 0x3a, 0x9c, 0x58, 0xbb, 0x81, 0x7d, 0x5e, 0x9a, 0x2c, + 0x38, 0x80, 0x04, 0x67, 0x5f, 0x25, 0x65, 0x29, 0x9a, 0x36, 0x14, 0x64, 0x08, 0x9c, 0xf2, 0x32, 0xcc, 0x04, 0x10, + 0x2b, 0x59, 0x61, 0x0c, 0x48, 0x7f, 0x6b, 0xee, 0x9f, 0x35, 0x2f, 0x3f, 0xad, 0x89, 0xd6, 0xe4, 0x8a, 0x56, 0x1f, + 0x6a, 0xf9, 0x06, 0x06, 0x02, 0xa3, 0x1f, 0xee, 0x29, 0x13, 0xb4, 0x12, 0xe5, 0xd8, 0x95, 0x43, 0xa4, 0x05, 0x4e, + 0xb4, 0xbd, 0x0f, 0x3a, 0xc2, 0xbb, 0x45, 0x9a, 0x10, 0xe1, 0xd0, 0xf5, 0x4b, 0x2a, 0x6b, 0xac, 0x64, 0x4a, 0x8d, + 0xa5, 0x44, 0x22, 0x45, 0xa6, 0x92, 0xa6, 0x83, 0xd6, 0x10, 0x14, 0xd0, 0x6e, 0x72, 0x9c, 0x56, 0x26, 0x70, 0xd2, + 0x68, 0xe0, 0xc8, 0xce, 0x3a, 0x1d, 0xf0, 0x46, 0x32, 0x24, 0x8c, 0x24, 0xda, 0x30, 0x39, 0x3b, 0x38, 0xf0, 0xa3, + 0x6a, 0xde, 0x41, 0x32, 0xc4, 0x44, 0xac, 0x56, 0xbe, 0x02, 0x2b, 0xc2, 0xab, 0x55, 0xe4, 0x82, 0xa5, 0xaa, 0xa1, + 0xdb, 0xbc, 0x2f, 0xe9, 0x5c, 0x09, 0xc0, 0x39, 0x40, 0xd8, 0xa0, 0x7e, 0x64, 0xdc, 0x7b, 0x11, 0xb8, 0xa3, 0x1a, + 0xe9, 0x20, 0x69, 0xb4, 0x87, 0x0e, 0xe3, 0x1a, 0x24, 0x43, 0x1a, 0x15, 0xe2, 0xe0, 0x60, 0x2f, 0x37, 0x22, 0xf2, + 0x27, 0x10, 0x65, 0x3f, 0x29, 0xc9, 0xa2, 0x07, 0x74, 0x77, 0x63, 0xdd, 0x19, 0x50, 0x52, 0x94, 0xd9, 0x56, 0xdb, + 0xae, 0x96, 0x05, 0x51, 0x36, 0x22, 0x26, 0x18, 0xdc, 0x07, 0xcb, 0xbe, 0x24, 0xf3, 0x57, 0xb2, 0xcc, 0xb1, 0xfe, + 0x79, 0x6b, 0x66, 0x75, 0x10, 0x04, 0x51, 0x36, 0x51, 0xb1, 0x0c, 0x1b, 0x86, 0x55, 0xc4, 0x7f, 0x64, 0xc0, 0x74, + 0x26, 0x1e, 0x94, 0x73, 0x0d, 0xa9, 0x06, 0xdf, 0xaa, 0x36, 0xf6, 0x2e, 0xc9, 0x4f, 0x5b, 0xbd, 0x0c, 0x1a, 0x92, + 0xe7, 0xbf, 0x15, 0x92, 0x87, 0x06, 0x12, 0x4d, 0x1e, 0x6b, 0x38, 0xdb, 0x81, 0x8b, 0x9f, 0xe4, 0x1a, 0xce, 0x76, + 0xe3, 0xd6, 0x62, 0xea, 0x97, 0x5d, 0xf0, 0x39, 0xbc, 0x41, 0x03, 0x5a, 0x15, 0x38, 0x50, 0x3e, 0x5a, 0xd7, 0xbd, + 0x34, 0x2b, 0x05, 0x61, 0x2a, 0xa9, 0xcf, 0xeb, 0x07, 0xa0, 0xd2, 0x46, 0x1d, 0xc3, 0x97, 0x87, 0x73, 0xec, 0xb8, + 0x04, 0xea, 0xa9, 0x2b, 0x40, 0x4e, 0xc6, 0xdb, 0x3e, 0x3f, 0x38, 0x00, 0xdb, 0x00, 0x94, 0xb8, 0x60, 0x14, 0xcd, + 0xe5, 0x22, 0x03, 0x55, 0x2a, 0xb7, 0xbf, 0xa1, 0x18, 0x6e, 0x81, 0xa8, 0x32, 0xf8, 0x01, 0x05, 0xf3, 0x28, 0xcf, + 0xf9, 0x95, 0x2e, 0x33, 0xbf, 0x89, 0xa0, 0x96, 0x94, 0x73, 0xad, 0x13, 0xa6, 0xb8, 0x9b, 0x1a, 0x3a, 0xad, 0xa3, + 0xed, 0xc5, 0x15, 0x4b, 0xe5, 0x2b, 0x9e, 0x4b, 0x96, 0xc2, 0xf2, 0x2b, 0x8a, 0x83, 0x15, 0xe5, 0x18, 0x0e, 0x6c, + 0xad, 0x57, 0x14, 0xc7, 0x77, 0x76, 0x91, 0x75, 0x1d, 0x68, 0x1a, 0xa5, 0x71, 0xa2, 0x27, 0x71, 0xf3, 0x19, 0x6d, + 0x0e, 0x67, 0xd9, 0xd2, 0xcd, 0xa7, 0xa9, 0x94, 0x0d, 0xc5, 0xdd, 0x7d, 0x4e, 0xad, 0x24, 0xb0, 0xd2, 0xf3, 0x4e, + 0xad, 0x05, 0x22, 0xde, 0x3b, 0x36, 0xc1, 0x5d, 0x09, 0x91, 0x0e, 0x47, 0x0d, 0xea, 0x70, 0x5a, 0xba, 0xf9, 0x72, + 0xeb, 0x95, 0xb6, 0x6d, 0xc2, 0x41, 0xd1, 0xc9, 0xe3, 0xdd, 0x96, 0xd5, 0x6b, 0x2b, 0x39, 0xac, 0xb4, 0xe0, 0xf7, + 0x65, 0xcc, 0x78, 0x69, 0xc9, 0x0b, 0xdb, 0xa3, 0xb8, 0x2f, 0xe9, 0x73, 0xb8, 0x33, 0xf4, 0x52, 0xce, 0x92, 0xb5, + 0xab, 0x31, 0xdd, 0xfd, 0x52, 0xfb, 0xdf, 0x97, 0xfe, 0x7b, 0xf2, 0x06, 0x02, 0xbb, 0x5f, 0x55, 0xcd, 0x37, 0x03, + 0xba, 0x5f, 0x55, 0x08, 0xfa, 0x2a, 0xdc, 0x68, 0xe7, 0x04, 0x72, 0x3b, 0xc1, 0xd3, 0xa0, 0x85, 0xac, 0xb6, 0xf4, + 0xb3, 0x0e, 0x23, 0xe9, 0x4c, 0x4b, 0x75, 0x1e, 0x48, 0x95, 0xa7, 0x06, 0xf9, 0x72, 0x75, 0x0b, 0x89, 0x99, 0x0c, + 0x43, 0xad, 0xc3, 0xef, 0xda, 0x1e, 0x23, 0x63, 0x52, 0x6d, 0x67, 0x7c, 0x1d, 0x65, 0x72, 0x1f, 0x4e, 0x99, 0xd8, + 0xb8, 0x87, 0x37, 0xa5, 0xe0, 0x41, 0xbb, 0xdf, 0x14, 0x8e, 0xb1, 0x9d, 0xeb, 0x7b, 0x40, 0xee, 0xf8, 0x54, 0x58, + 0xdd, 0xad, 0x6e, 0x65, 0x7c, 0x0d, 0xf6, 0x3f, 0x26, 0x53, 0x7b, 0x39, 0x8e, 0x19, 0x0e, 0xcc, 0xc2, 0x65, 0x51, + 0x3a, 0x05, 0x84, 0x56, 0xde, 0x32, 0x4c, 0x44, 0xa1, 0x02, 0xdc, 0x3f, 0x90, 0x6f, 0x0c, 0x4b, 0x1c, 0x97, 0x1c, + 0xe7, 0xe4, 0xbe, 0x1c, 0x51, 0x83, 0x5f, 0xc6, 0xef, 0x81, 0x8e, 0x15, 0x85, 0x16, 0x96, 0x8a, 0x9e, 0x0b, 0xb3, + 0x90, 0x9d, 0x69, 0xa9, 0x84, 0x95, 0x29, 0x35, 0x6a, 0x9a, 0x2d, 0x79, 0x9c, 0xd6, 0xca, 0x96, 0xe5, 0xa9, 0xaa, + 0xcd, 0x8b, 0x77, 0x60, 0xb1, 0x0a, 0x2d, 0xae, 0x56, 0x7e, 0x1d, 0xd5, 0x94, 0x3b, 0x91, 0x0c, 0x4c, 0xb8, 0x93, + 0x51, 0x51, 0xd3, 0xac, 0x75, 0x1f, 0x1f, 0xaf, 0x27, 0x14, 0x59, 0xdd, 0xbc, 0x06, 0x87, 0xeb, 0x42, 0xd0, 0xdd, + 0x5d, 0x9f, 0x02, 0xd1, 0xab, 0x2b, 0x27, 0x72, 0x30, 0xf4, 0x73, 0x99, 0x2a, 0x5b, 0xe5, 0xb4, 0x6e, 0xc1, 0x2f, + 0xbe, 0x23, 0x59, 0xd6, 0xa0, 0x6e, 0xb3, 0xde, 0x49, 0x36, 0x7a, 0x2e, 0x76, 0x25, 0x1b, 0xd5, 0xb4, 0xdd, 0xbd, + 0x16, 0xbe, 0x3b, 0x2d, 0x55, 0xcf, 0xb5, 0xbd, 0xc9, 0x6f, 0x98, 0xae, 0x0d, 0xb4, 0xa9, 0xd1, 0x6c, 0xb9, 0xca, + 0x59, 0x51, 0x8c, 0xcb, 0xcb, 0x04, 0x2a, 0x77, 0x67, 0xac, 0xe9, 0xdf, 0x58, 0x8d, 0xea, 0x3a, 0xae, 0xff, 0x03, + 0x9d, 0x24, 0xe2, 0x32, 0x4a, 0xde, 0xc3, 0x7c, 0x55, 0xe5, 0xcb, 0xdb, 0x38, 0x8b, 0x24, 0x33, 0xdc, 0xa5, 0x82, + 0xe1, 0x07, 0x07, 0x86, 0x1f, 0x34, 0x9f, 0xae, 0xfa, 0x93, 0xe5, 0xab, 0x72, 0x80, 0x70, 0x5c, 0x58, 0x96, 0x71, + 0x2e, 0xb7, 0xcf, 0xb1, 0xce, 0xc2, 0xce, 0x4b, 0x16, 0x76, 0x2e, 0xfd, 0xf5, 0xa1, 0x7c, 0xff, 0x9b, 0xed, 0xa3, + 0x6c, 0x72, 0xb6, 0x6f, 0xaa, 0x83, 0xff, 0x4d, 0x78, 0x67, 0x1f, 0x87, 0xcb, 0x1d, 0x05, 0x47, 0x2a, 0x5d, 0x45, + 0x83, 0xfc, 0x0e, 0xd2, 0x0e, 0x24, 0xed, 0x39, 0x77, 0x0e, 0x2a, 0x39, 0x65, 0x13, 0x81, 0xfc, 0xd1, 0x22, 0x97, + 0x62, 0x66, 0xc6, 0xcc, 0xcd, 0x35, 0x23, 0x55, 0x09, 0xae, 0x68, 0x15, 0x6d, 0x0f, 0xeb, 0x17, 0xb9, 0x96, 0x1f, + 0x79, 0x1a, 0x87, 0x39, 0x31, 0x52, 0x24, 0x0f, 0xd3, 0x82, 0xda, 0x64, 0xe3, 0xcd, 0x3a, 0x32, 0xe6, 0x29, 0xcf, + 0xa7, 0x2c, 0xf3, 0x05, 0x5e, 0xee, 0x9a, 0x4c, 0x40, 0x40, 0x46, 0x4f, 0x46, 0xbe, 0xad, 0x2e, 0xfc, 0x05, 0x30, + 0x1a, 0xf8, 0x81, 0x66, 0x4c, 0x4e, 0x45, 0x0c, 0x89, 0x29, 0x41, 0x5c, 0xde, 0x68, 0x3a, 0x38, 0xd8, 0xf3, 0x91, + 0x72, 0x4b, 0xc0, 0xd5, 0x6f, 0xb7, 0x06, 0xf7, 0x97, 0x70, 0x3d, 0xa7, 0x9a, 0x9a, 0xe1, 0x25, 0x5b, 0xbf, 0xc9, + 0x22, 0x83, 0x8f, 0xec, 0x96, 0x64, 0xb8, 0x28, 0x42, 0x0d, 0x35, 0x1a, 0x73, 0x96, 0xc4, 0x88, 0x7c, 0x64, 0xb7, + 0x61, 0x79, 0x5b, 0x5c, 0x5d, 0x6e, 0x56, 0x1b, 0x88, 0xc4, 0x75, 0x8a, 0x48, 0x35, 0x49, 0xb8, 0x2c, 0x88, 0xc8, + 0xf8, 0x04, 0x88, 0xf3, 0x6f, 0xec, 0x36, 0xd4, 0xe3, 0x71, 0xe7, 0xb2, 0x1e, 0x5e, 0x5a, 0xd4, 0x07, 0x4e, 0xb1, + 0xbb, 0x0d, 0xc6, 0xa0, 0x18, 0xa8, 0xbe, 0x43, 0x5a, 0x6b, 0x57, 0x99, 0x87, 0x18, 0x17, 0xf7, 0x5d, 0x0a, 0xf9, + 0xc2, 0x15, 0x6d, 0xb2, 0x96, 0xfa, 0xba, 0xd6, 0x89, 0x41, 0x87, 0x2a, 0xd7, 0xe3, 0xdc, 0xcf, 0xec, 0xa9, 0x33, + 0x77, 0x10, 0x1c, 0x47, 0xd8, 0x17, 0xd2, 0x0c, 0x1a, 0x7e, 0xab, 0x53, 0x42, 0xaa, 0x48, 0xd2, 0xeb, 0xaa, 0x9f, + 0x77, 0xee, 0x03, 0xde, 0x21, 0xa5, 0x25, 0x52, 0xd7, 0x31, 0x0b, 0x9b, 0x2e, 0xfa, 0x9d, 0xa4, 0xfe, 0xd2, 0x2e, + 0x21, 0xcc, 0x5c, 0x2c, 0xca, 0x02, 0xa8, 0xd0, 0xd0, 0x97, 0xce, 0x00, 0xe4, 0x63, 0x9f, 0x6f, 0x48, 0xcd, 0x54, + 0x49, 0xcd, 0xc0, 0xc1, 0xf8, 0x0e, 0x29, 0xc9, 0x14, 0x32, 0x94, 0x12, 0xa9, 0x84, 0x9e, 0xd9, 0x5c, 0x43, 0x42, + 0xee, 0x86, 0x96, 0xd7, 0xe7, 0xf4, 0x9e, 0xa7, 0x35, 0xb0, 0x7c, 0x35, 0x0e, 0x2e, 0x42, 0x58, 0x12, 0xd3, 0x0d, + 0x0a, 0xeb, 0xce, 0xc9, 0x6c, 0x7e, 0xab, 0x2f, 0x02, 0xbb, 0x2c, 0x6a, 0x51, 0xe2, 0x4f, 0xf1, 0x32, 0xf3, 0xa7, + 0x24, 0x85, 0x7c, 0x44, 0x51, 0x94, 0xf0, 0x33, 0x77, 0x37, 0x6a, 0xd9, 0xca, 0xdb, 0xaf, 0xf8, 0x81, 0x32, 0x2f, + 0x21, 0x47, 0x93, 0x64, 0x96, 0xa7, 0x64, 0xbe, 0xba, 0x6b, 0xe7, 0x6c, 0xdb, 0x57, 0x26, 0x45, 0xc7, 0x00, 0xf6, + 0x9d, 0xf4, 0x97, 0xce, 0x2a, 0xdc, 0xbb, 0xdc, 0xe6, 0xca, 0x9f, 0x09, 0xf6, 0x55, 0x49, 0xa4, 0x7e, 0x4e, 0xd7, + 0x24, 0xce, 0xdd, 0xb9, 0x96, 0x3f, 0x2f, 0x58, 0x76, 0x7b, 0xc6, 0x20, 0xd7, 0x59, 0xc0, 0x5d, 0xdf, 0x6a, 0x1b, + 0xaa, 0x3c, 0xf5, 0x7e, 0xaa, 0x94, 0x95, 0xa2, 0x7e, 0x09, 0x70, 0xfd, 0x8a, 0x60, 0xa1, 0xa2, 0x8d, 0x8e, 0x23, + 0x46, 0x9f, 0x16, 0xb6, 0xf3, 0xf2, 0x24, 0xeb, 0x72, 0xf0, 0xaf, 0x55, 0x98, 0x36, 0xc1, 0x02, 0x22, 0xdc, 0x0b, + 0xa9, 0x83, 0x7c, 0xb8, 0xee, 0x95, 0x81, 0x22, 0x08, 0xdf, 0xa5, 0xbb, 0x97, 0xba, 0x2d, 0x6b, 0x76, 0xf7, 0x52, + 0x6b, 0x41, 0x3f, 0x95, 0xf2, 0x43, 0xcc, 0x3c, 0xe5, 0xe5, 0x65, 0x5e, 0x14, 0xb8, 0x00, 0xf0, 0xbe, 0xef, 0xfa, + 0xfe, 0xf7, 0x26, 0x69, 0x30, 0x80, 0x58, 0xec, 0x59, 0x22, 0x2c, 0x13, 0xaf, 0xe6, 0xff, 0x7e, 0x63, 0xfe, 0xef, + 0x9d, 0x2b, 0xa7, 0x60, 0x1a, 0x4d, 0x52, 0x16, 0x5b, 0xd6, 0x89, 0x35, 0x01, 0x2a, 0xbd, 0x2d, 0x97, 0xf4, 0xe3, + 0x45, 0x08, 0x1a, 0xd7, 0x72, 0x2c, 0x52, 0xd9, 0x1c, 0x47, 0x33, 0x9e, 0xdc, 0x86, 0x0b, 0xde, 0x9c, 0x89, 0x54, + 0xe4, 0xf3, 0x68, 0xc4, 0x48, 0x7e, 0x9b, 0x4b, 0x36, 0x6b, 0x2e, 0x38, 0x79, 0xc9, 0x92, 0x2b, 0x26, 0xf9, 0x28, + 0x22, 0xe8, 0x24, 0xe3, 0x51, 0xe2, 0xbd, 0x89, 0xb2, 0x4c, 0x5c, 0x23, 0xf2, 0x4e, 0x5c, 0x0a, 0x29, 0xc8, 0xdb, + 0x9b, 0xdb, 0x09, 0x4b, 0xc9, 0x87, 0xcb, 0x45, 0x2a, 0x17, 0x24, 0x8f, 0xd2, 0xbc, 0x99, 0xb3, 0x8c, 0x8f, 0xbb, + 0x23, 0x91, 0x88, 0xac, 0x09, 0x29, 0xdb, 0x33, 0x16, 0x26, 0x7c, 0x32, 0x95, 0x5e, 0x1c, 0x65, 0x1f, 0xbb, 0xcd, + 0xe6, 0x3c, 0xe3, 0xb3, 0x28, 0xbb, 0x6d, 0xaa, 0x16, 0xe1, 0x67, 0xad, 0xa3, 0xe8, 0xf3, 0xf1, 0xc3, 0xae, 0xcc, + 0xa2, 0x34, 0xe7, 0xb0, 0x4d, 0x61, 0x94, 0x24, 0xde, 0xd1, 0xa3, 0xd6, 0x2c, 0xdf, 0xd3, 0x81, 0xbc, 0x28, 0x95, + 0xc5, 0x05, 0xf9, 0x08, 0x70, 0x07, 0x97, 0x32, 0x25, 0x97, 0x0b, 0x29, 0x45, 0xba, 0x1c, 0x2d, 0xb2, 0x5c, 0x64, + 0xe1, 0x5c, 0xf0, 0x54, 0xb2, 0xac, 0x7b, 0x29, 0xb2, 0x98, 0x65, 0xcd, 0x2c, 0x8a, 0xf9, 0x22, 0x0f, 0x1f, 0xce, + 0x6f, 0xba, 0xa0, 0x59, 0x4c, 0x32, 0xb1, 0x48, 0x63, 0x33, 0x17, 0x4f, 0xa7, 0x2c, 0xe3, 0xd2, 0xad, 0x50, 0xaf, + 0x30, 0x09, 0x13, 0x9e, 0xb2, 0x28, 0x6b, 0x4e, 0xa0, 0x33, 0x98, 0x45, 0xad, 0x98, 0x4d, 0x48, 0x36, 0xb9, 0x8c, + 0xfc, 0x76, 0xe7, 0x09, 0xb1, 0x7f, 0x83, 0x47, 0xd8, 0x6b, 0x6d, 0x2f, 0x6e, 0xb7, 0x5a, 0x7f, 0xc2, 0xdd, 0xb5, + 0x59, 0x14, 0x40, 0x61, 0x7b, 0x7e, 0xe3, 0xe5, 0x02, 0x72, 0xda, 0xb6, 0xf5, 0xec, 0xce, 0xa3, 0x18, 0x12, 0x82, + 0xc3, 0xce, 0xfc, 0xa6, 0x80, 0xd5, 0x85, 0x3a, 0xc9, 0xd4, 0x2c, 0xd2, 0x3c, 0x2d, 0x7f, 0x2b, 0xc4, 0x4f, 0xb7, + 0x43, 0xdc, 0xb1, 0x10, 0x57, 0x58, 0x6f, 0xc6, 0x8b, 0x4c, 0xc5, 0x56, 0xc3, 0x76, 0xae, 0x01, 0x99, 0x8a, 0x2b, + 0x96, 0x59, 0x38, 0xd4, 0xc3, 0x6f, 0x06, 0xa3, 0xb3, 0x1d, 0x8c, 0xa7, 0x9f, 0x02, 0x23, 0x4b, 0xe3, 0x65, 0x7d, + 0x5f, 0xdb, 0x19, 0x9b, 0x75, 0xa7, 0x0c, 0xe8, 0x29, 0xec, 0xc0, 0xef, 0x6b, 0x1e, 0xcb, 0xa9, 0xfe, 0xa9, 0xc8, + 0xf9, 0x5a, 0xd7, 0x3d, 0x6a, 0xb5, 0xf4, 0x73, 0xce, 0x7f, 0x61, 0x61, 0x3b, 0x80, 0x06, 0xc5, 0x05, 0xf9, 0x5b, + 0x79, 0x99, 0xb7, 0xce, 0x3d, 0xc9, 0x0f, 0xee, 0x2d, 0x5f, 0x27, 0x49, 0xb1, 0xba, 0x11, 0x4d, 0x32, 0x2b, 0x2b, + 0xb5, 0xf0, 0x01, 0xb7, 0x9d, 0x3a, 0x4f, 0x94, 0xf7, 0xca, 0x5b, 0x9c, 0xbc, 0xff, 0x83, 0xce, 0xbb, 0x08, 0x21, + 0xd2, 0xe1, 0x24, 0x1b, 0x8a, 0x6e, 0xda, 0xa3, 0xad, 0x6e, 0xda, 0x6c, 0x62, 0x5f, 0xd0, 0x6c, 0x90, 0x9a, 0xf4, + 0x3c, 0x9f, 0xf7, 0x85, 0x32, 0xb6, 0x73, 0x1c, 0x0a, 0xb8, 0x6a, 0xba, 0x5a, 0x55, 0x61, 0x00, 0xae, 0xae, 0x6b, + 0xfc, 0x4d, 0x9a, 0x06, 0x24, 0x77, 0x38, 0x79, 0x6a, 0x5f, 0xec, 0x92, 0x59, 0x5e, 0x91, 0x88, 0x91, 0xc2, 0x5c, + 0x30, 0x8f, 0xe4, 0x14, 0xbc, 0x14, 0xa5, 0xf8, 0xa9, 0x92, 0x98, 0xd0, 0x21, 0xc2, 0xfd, 0xac, 0xcc, 0x70, 0x83, + 0x4c, 0xbe, 0xac, 0x80, 0x51, 0xbe, 0x91, 0x14, 0x46, 0x24, 0xbf, 0x50, 0x6d, 0xd3, 0x59, 0x8b, 0x6e, 0x7c, 0x5f, + 0x8b, 0x8e, 0xa5, 0x92, 0xab, 0xdc, 0x6d, 0x1b, 0x71, 0x98, 0x46, 0xf9, 0xf9, 0x48, 0xdf, 0x95, 0xcc, 0xab, 0x9b, + 0x01, 0x91, 0x82, 0x5e, 0x1b, 0x69, 0x2c, 0x53, 0xf6, 0xe8, 0xf7, 0x72, 0xa7, 0x7d, 0x92, 0xdd, 0x65, 0x9f, 0x94, + 0x0b, 0xcf, 0xc5, 0x22, 0x1b, 0x41, 0x38, 0xd2, 0x48, 0xbd, 0x4d, 0xc7, 0x0d, 0x52, 0x2a, 0x06, 0x22, 0xd2, 0xc9, + 0x04, 0x95, 0x84, 0xbb, 0x2f, 0x95, 0x60, 0x2a, 0xe4, 0xa5, 0xef, 0x6b, 0x18, 0x11, 0x67, 0x97, 0x04, 0x32, 0x3b, + 0x56, 0x49, 0x8d, 0x7e, 0x4a, 0x7b, 0x69, 0xb0, 0x48, 0xf9, 0xcf, 0x0b, 0x76, 0xce, 0x41, 0xd7, 0xe4, 0x01, 0x8f, + 0x55, 0xac, 0x09, 0x64, 0x5f, 0xb3, 0x0d, 0xc1, 0x0b, 0x1e, 0xeb, 0x8d, 0x49, 0x55, 0xa5, 0xc9, 0x6d, 0x42, 0x4d, + 0x04, 0xfe, 0x62, 0xd0, 0x0e, 0x38, 0x89, 0xc5, 0x2c, 0xe2, 0x69, 0xa8, 0x5c, 0xbe, 0xe5, 0x60, 0x21, 0xb4, 0x26, + 0x3c, 0x0e, 0x53, 0xb3, 0x3d, 0x6d, 0x1c, 0xfc, 0x24, 0x78, 0xaa, 0xba, 0x16, 0x5d, 0xa1, 0x10, 0xaa, 0xd1, 0x47, + 0x2d, 0x82, 0x4f, 0xb4, 0x5c, 0x13, 0x98, 0xb8, 0xd5, 0xe5, 0xb5, 0xf3, 0xda, 0x0e, 0xb4, 0xd6, 0x36, 0x4a, 0x1b, + 0x01, 0x62, 0xbd, 0x34, 0x17, 0x99, 0xf4, 0xfd, 0x29, 0x49, 0x30, 0xed, 0x4d, 0x95, 0xb3, 0xeb, 0x38, 0x51, 0xff, + 0xf5, 0x9b, 0xed, 0xb0, 0x5d, 0x9a, 0xef, 0xb5, 0xdb, 0xc0, 0x3a, 0x39, 0xca, 0xdc, 0x28, 0x55, 0xcb, 0x28, 0x7f, + 0xeb, 0xa5, 0x56, 0xcf, 0xe5, 0x72, 0x89, 0x39, 0x6e, 0x5a, 0x54, 0xf9, 0x35, 0x20, 0x54, 0xb0, 0x68, 0xc7, 0x54, + 0xb8, 0xa8, 0xd6, 0x5d, 0xaa, 0x92, 0x17, 0x5a, 0x44, 0x9f, 0xef, 0x2f, 0x33, 0x33, 0x63, 0x71, 0xc1, 0xad, 0x93, + 0xa9, 0x4e, 0x72, 0x85, 0xc1, 0x88, 0xa3, 0x87, 0x6e, 0x6b, 0xa6, 0x61, 0xb9, 0xa5, 0xd9, 0x56, 0xba, 0x0d, 0xf4, + 0x23, 0xcb, 0x68, 0x15, 0xee, 0xda, 0x18, 0x00, 0x72, 0xf5, 0xb6, 0x01, 0x06, 0x66, 0x6b, 0x2e, 0xed, 0x12, 0x40, + 0x1b, 0x1b, 0x33, 0xb8, 0x48, 0x73, 0xb1, 0xbf, 0xfc, 0x46, 0x16, 0x87, 0x4e, 0x53, 0xf5, 0x9b, 0xc7, 0xf0, 0x3f, + 0x48, 0xc0, 0xa5, 0x56, 0x4a, 0x43, 0xf4, 0xf5, 0xdb, 0xb3, 0xf7, 0x88, 0x5c, 0x8a, 0xf8, 0x36, 0x44, 0x32, 0x5b, + 0x30, 0x54, 0xe0, 0x40, 0x4e, 0x59, 0x5a, 0xbe, 0x8c, 0x47, 0x24, 0x2c, 0x48, 0xc4, 0x44, 0x5f, 0xca, 0x5c, 0x37, + 0x92, 0x47, 0x17, 0xc7, 0xea, 0x25, 0x53, 0xbd, 0x63, 0xa9, 0x5f, 0xef, 0x25, 0x33, 0xf8, 0xd9, 0x83, 0x10, 0xca, + 0xf1, 0xa1, 0x9c, 0xaa, 0x87, 0x33, 0x38, 0x30, 0xea, 0x69, 0x7f, 0xb9, 0x41, 0x4c, 0x7d, 0x18, 0x62, 0xda, 0xd3, + 0x4b, 0xc8, 0x55, 0xab, 0x8b, 0x70, 0x74, 0x71, 0x51, 0x1c, 0x1f, 0xc2, 0x58, 0x87, 0x76, 0x5c, 0x80, 0xd0, 0xf6, + 0x2f, 0x09, 0x0c, 0x5e, 0x36, 0x94, 0xd1, 0x1e, 0x0c, 0x01, 0xf3, 0xc6, 0x3d, 0x58, 0x24, 0x10, 0x18, 0xf4, 0x8e, + 0xcb, 0x12, 0x75, 0x62, 0x75, 0xd1, 0x2e, 0x08, 0x74, 0xc3, 0x8a, 0xee, 0xb5, 0x37, 0xb5, 0xda, 0x5f, 0x0b, 0x52, + 0xec, 0x42, 0x77, 0x81, 0xe1, 0x7f, 0x05, 0xd9, 0xf1, 0xa1, 0xc6, 0xc3, 0x85, 0xfb, 0x6a, 0x13, 0xfd, 0xda, 0x81, + 0x12, 0x5b, 0x83, 0x5c, 0x92, 0x8f, 0x92, 0x7c, 0xbc, 0x50, 0x4d, 0xad, 0x30, 0x02, 0x2d, 0x09, 0x84, 0x76, 0xcb, + 0x6a, 0x1d, 0x23, 0x91, 0x24, 0xd1, 0x3c, 0x67, 0xa1, 0xfd, 0x61, 0xe4, 0x12, 0x88, 0xb7, 0x4d, 0x45, 0xc0, 0xa4, + 0xd7, 0x9c, 0x82, 0xba, 0xb0, 0xa9, 0xa5, 0x5c, 0x45, 0x99, 0xdf, 0x6c, 0x8e, 0x9a, 0x97, 0x13, 0x5c, 0xc8, 0xe9, + 0xd2, 0x95, 0x6a, 0x8f, 0x5b, 0xad, 0x2e, 0xe4, 0x42, 0x36, 0xa3, 0x84, 0x4f, 0xd2, 0x30, 0x61, 0x63, 0x59, 0x48, + 0xb8, 0xa5, 0xb6, 0xb4, 0x6a, 0x44, 0xd0, 0x79, 0x94, 0xb1, 0x99, 0x17, 0xc0, 0xbf, 0x77, 0x4f, 0x5c, 0xc8, 0x38, + 0x4c, 0xe5, 0xb4, 0xa9, 0xb2, 0x6e, 0xe1, 0xce, 0x80, 0x9c, 0xd6, 0x9e, 0x97, 0xce, 0x44, 0x23, 0x06, 0x2a, 0x56, + 0x21, 0x33, 0x4f, 0x4e, 0x89, 0xcc, 0xdc, 0x76, 0x29, 0x5e, 0x6e, 0xac, 0x60, 0x53, 0xd2, 0x1f, 0xe1, 0x22, 0x57, + 0x8a, 0xf1, 0x66, 0x63, 0xab, 0x2e, 0xd5, 0x9f, 0x36, 0xd0, 0xe7, 0x28, 0x76, 0x85, 0x76, 0x2c, 0x2f, 0x75, 0x8f, + 0xfb, 0x20, 0xb3, 0xa6, 0x72, 0x12, 0xb7, 0x07, 0x2e, 0x78, 0x3a, 0x5f, 0xc8, 0x81, 0x72, 0x6a, 0x67, 0x70, 0x41, + 0x62, 0x48, 0x9c, 0x12, 0xc0, 0xc1, 0x70, 0xa9, 0x81, 0x19, 0x45, 0xc9, 0xc8, 0x07, 0x88, 0xbc, 0xa6, 0xf7, 0x34, + 0x63, 0x33, 0xdc, 0x9d, 0xf1, 0xb4, 0xa9, 0xeb, 0x1e, 0x39, 0x6a, 0x49, 0xf0, 0x04, 0x9e, 0x8a, 0x40, 0x8d, 0x46, + 0x54, 0xee, 0xea, 0x16, 0x5c, 0x5e, 0x0c, 0x8b, 0xa2, 0x9b, 0x49, 0x7f, 0xf0, 0xda, 0xc7, 0x43, 0xf2, 0x8b, 0xf3, + 0x72, 0x16, 0x64, 0x8f, 0x0a, 0x22, 0x1d, 0xbc, 0xa3, 0x89, 0x7b, 0x16, 0x54, 0xb3, 0x5f, 0x28, 0x34, 0x7c, 0xe7, + 0x23, 0x96, 0xcf, 0x9b, 0x9a, 0x77, 0x35, 0x15, 0xc9, 0x22, 0xe8, 0x8a, 0x8d, 0xa7, 0xf6, 0x7b, 0xb9, 0x54, 0x6c, + 0xc9, 0x5c, 0xd2, 0xd0, 0xce, 0x84, 0x61, 0x79, 0xa9, 0xc7, 0x3c, 0xbb, 0xd7, 0x78, 0x70, 0x8d, 0x9f, 0x5c, 0x9c, + 0xd4, 0x79, 0x1c, 0xf0, 0xa5, 0xf2, 0x05, 0x76, 0x51, 0x92, 0xc0, 0x84, 0x17, 0x56, 0x7d, 0x71, 0x5f, 0xfa, 0x31, + 0x90, 0x43, 0x1f, 0x17, 0xe6, 0x9c, 0x3e, 0x53, 0x2a, 0xa5, 0xf3, 0xd6, 0xbc, 0x3d, 0x69, 0x83, 0x45, 0x5a, 0xfa, + 0x72, 0x08, 0x77, 0xd7, 0xf2, 0xa2, 0xbb, 0x15, 0xef, 0xd2, 0x0a, 0xa9, 0xa7, 0x16, 0x44, 0x51, 0x96, 0xc6, 0xc8, + 0xfb, 0xcb, 0x28, 0xe1, 0xa3, 0x8f, 0x14, 0xed, 0x2f, 0x7d, 0xbc, 0x79, 0xed, 0x51, 0x71, 0x05, 0xcb, 0xb0, 0x71, + 0xdd, 0x91, 0x9e, 0x06, 0x0e, 0x2f, 0xd6, 0x6f, 0xc5, 0x41, 0xbd, 0xfd, 0x25, 0x30, 0x1e, 0x3d, 0x4f, 0xef, 0xa2, + 0x38, 0xaf, 0xde, 0x75, 0x55, 0x41, 0x01, 0x68, 0xd6, 0xe5, 0x9e, 0x22, 0x2a, 0x8a, 0x3e, 0x49, 0x69, 0xc8, 0xd3, + 0x4c, 0x0d, 0xe0, 0x94, 0x86, 0xbf, 0x21, 0xef, 0x2f, 0x65, 0x19, 0x2b, 0x3d, 0x1a, 0x2a, 0x25, 0x83, 0x22, 0x98, + 0x0b, 0xcc, 0xd8, 0x20, 0x66, 0x32, 0xe2, 0x89, 0xee, 0xd2, 0xb5, 0x06, 0xf8, 0xda, 0x8a, 0x56, 0xab, 0xbc, 0xbe, + 0x16, 0x5e, 0xc7, 0xa0, 0x5a, 0xd9, 0xf1, 0x61, 0x05, 0xb7, 0x5a, 0x99, 0x3a, 0x93, 0x6e, 0x68, 0xb0, 0x5a, 0xa1, + 0xae, 0xf3, 0xfe, 0x32, 0x52, 0xd7, 0x86, 0x00, 0x40, 0x61, 0x00, 0x84, 0xa0, 0xb5, 0xbe, 0x16, 0xe3, 0x27, 0x54, + 0x04, 0x32, 0xca, 0x26, 0x4c, 0xae, 0x21, 0x36, 0xd1, 0x39, 0xaa, 0x5d, 0x1b, 0xa0, 0xde, 0x80, 0x36, 0xaa, 0x43, + 0x7b, 0x01, 0x48, 0xef, 0xef, 0x2f, 0x79, 0x41, 0xf7, 0x97, 0x2c, 0x1d, 0x89, 0x98, 0x7d, 0x78, 0xf7, 0x25, 0x5c, + 0x72, 0x14, 0x29, 0x18, 0x16, 0x53, 0x0c, 0x82, 0x53, 0x6d, 0x8e, 0x16, 0x21, 0x42, 0x89, 0x10, 0xcd, 0x09, 0x3c, + 0x35, 0x97, 0x02, 0xb1, 0x40, 0x5e, 0x5f, 0x43, 0xce, 0x62, 0x0d, 0x33, 0x4d, 0x55, 0x2f, 0x51, 0x1c, 0x1f, 0xea, + 0xd6, 0x5a, 0x04, 0xe8, 0x46, 0x80, 0x04, 0x75, 0x4e, 0x2b, 0x1c, 0x40, 0x5e, 0xb3, 0x8b, 0x87, 0x98, 0x5f, 0x95, + 0xc4, 0xa6, 0x2e, 0x50, 0xf5, 0x8e, 0x93, 0xe8, 0x92, 0x25, 0xbd, 0xfd, 0x65, 0xba, 0x5a, 0xb5, 0x8a, 0xe3, 0x43, + 0xfd, 0xe8, 0x1d, 0x2b, 0xbe, 0xa1, 0x5f, 0x78, 0xa9, 0xb6, 0x18, 0x6e, 0x25, 0x42, 0xb6, 0xa7, 0x4d, 0x73, 0x0a, + 0xcd, 0x00, 0x05, 0xf2, 0x54, 0x82, 0x85, 0x6a, 0x54, 0x2a, 0x44, 0x05, 0xf2, 0x78, 0xbc, 0x59, 0x96, 0x4b, 0x36, + 0x87, 0xd2, 0xe9, 0x6a, 0xd5, 0x2e, 0x90, 0x37, 0xe3, 0x29, 0x3c, 0xa5, 0xab, 0x95, 0xba, 0xf0, 0x37, 0xe3, 0xa9, + 0xdf, 0x02, 0xb2, 0x45, 0xde, 0x2c, 0xba, 0x51, 0x0b, 0xb6, 0x35, 0xd1, 0x8d, 0xdf, 0x36, 0x55, 0x41, 0x89, 0x9f, + 0x1c, 0x28, 0xae, 0xda, 0xd1, 0xc4, 0xec, 0x68, 0x4c, 0x16, 0xfa, 0x2a, 0x13, 0xf5, 0x63, 0x9a, 0x6c, 0xdf, 0xd1, + 0xd8, 0xee, 0xe8, 0x62, 0xc7, 0x8e, 0x2e, 0xee, 0xd8, 0xd1, 0xc8, 0xec, 0x9e, 0x57, 0xe2, 0x4e, 0xac, 0x56, 0xed, + 0x56, 0x85, 0xbd, 0xe3, 0xc3, 0x98, 0x5f, 0xc1, 0x6e, 0x80, 0x9a, 0x27, 0xf9, 0x8c, 0x6d, 0x27, 0xca, 0x3a, 0x8a, + 0xd9, 0xaf, 0xc2, 0x64, 0x85, 0x85, 0xb4, 0x8e, 0x05, 0x97, 0xae, 0xcb, 0x98, 0xdb, 0x1f, 0x49, 0xd9, 0x1c, 0xf0, + 0x90, 0x03, 0x1e, 0xa6, 0xf6, 0x05, 0x98, 0x3e, 0x7a, 0x8f, 0x08, 0xf2, 0x90, 0x25, 0xeb, 0x8b, 0xe2, 0x1c, 0x64, + 0x84, 0x5a, 0xdf, 0xbd, 0x68, 0x11, 0x5a, 0xa3, 0xde, 0x6e, 0x9a, 0x83, 0xf0, 0xf8, 0xb5, 0xc8, 0x62, 0x14, 0xea, + 0xa6, 0xbf, 0x0a, 0x55, 0x33, 0x9e, 0x9a, 0x64, 0xab, 0x9d, 0xb4, 0x56, 0xd5, 0xbb, 0x14, 0xd7, 0x79, 0xf4, 0x48, + 0xb7, 0x98, 0x47, 0x52, 0xb2, 0x2c, 0x35, 0x94, 0x8b, 0xd0, 0xff, 0x17, 0x54, 0xb8, 0x85, 0xaf, 0x44, 0x76, 0x03, + 0x2c, 0x01, 0x1a, 0x85, 0xdd, 0xf0, 0x7c, 0x2d, 0x9e, 0xf6, 0x2a, 0x0d, 0xf6, 0x16, 0xbb, 0x46, 0x83, 0x2e, 0x02, + 0x1b, 0x66, 0x31, 0x63, 0xf1, 0xb9, 0x62, 0xd0, 0xfd, 0xd1, 0x85, 0x51, 0x58, 0xd7, 0xc4, 0x5d, 0xd5, 0x81, 0xa0, + 0x1f, 0x17, 0x9d, 0x27, 0x0f, 0x4f, 0x11, 0xd1, 0x3c, 0x5e, 0x8c, 0xc7, 0x08, 0x17, 0xde, 0xfd, 0xba, 0xb5, 0x1f, + 0xfe, 0xb8, 0xf8, 0xe2, 0x45, 0xeb, 0x8b, 0xb2, 0x73, 0x0a, 0x44, 0x64, 0xe2, 0xfb, 0x56, 0x54, 0x39, 0xf0, 0xda, + 0x15, 0x8d, 0xa3, 0x74, 0xf7, 0x72, 0x06, 0xee, 0x72, 0xf2, 0x39, 0x63, 0x31, 0x10, 0x27, 0xd9, 0x28, 0x3d, 0x4f, + 0xd8, 0x15, 0xb3, 0x6f, 0x1e, 0xdc, 0x32, 0xd9, 0x96, 0x1e, 0x23, 0xb1, 0x48, 0xa5, 0x49, 0x74, 0x30, 0xac, 0xd6, + 0x59, 0xd2, 0x85, 0x5a, 0x83, 0x6b, 0x23, 0xdc, 0x6a, 0x39, 0x57, 0x97, 0x5e, 0xc5, 0x05, 0x41, 0x0e, 0x00, 0x3b, + 0x21, 0xeb, 0xef, 0x28, 0x0f, 0x5b, 0xa4, 0xb5, 0x0b, 0x36, 0xd2, 0xc6, 0x21, 0x42, 0x43, 0x8b, 0x27, 0xe5, 0xab, + 0xac, 0xbd, 0x30, 0x62, 0x27, 0xbe, 0x3e, 0x89, 0x81, 0xcb, 0x0c, 0x06, 0x4b, 0x59, 0x9e, 0xef, 0x44, 0x40, 0xb9, + 0x89, 0x04, 0x55, 0xad, 0xd1, 0x8e, 0x51, 0x48, 0x8b, 0xc0, 0x09, 0x53, 0x00, 0x97, 0x11, 0x53, 0xd3, 0x8a, 0x8d, + 0xc7, 0x6c, 0x54, 0xba, 0x7a, 0x21, 0xf6, 0x35, 0xe6, 0x89, 0x84, 0x10, 0x90, 0x8a, 0xcd, 0xa0, 0x37, 0x22, 0x65, + 0x08, 0xdb, 0x6c, 0x4e, 0x03, 0xbf, 0x91, 0xff, 0xdb, 0xe1, 0xd1, 0x23, 0xd6, 0x61, 0x31, 0xb3, 0xac, 0x56, 0xd6, + 0xcd, 0x53, 0x2b, 0xaf, 0x23, 0x52, 0x28, 0x3f, 0xce, 0xae, 0x03, 0x74, 0xbf, 0x63, 0xb2, 0x6c, 0x7f, 0xf1, 0xa8, + 0xdd, 0x2a, 0x10, 0x41, 0x30, 0xdc, 0x7d, 0x4f, 0x89, 0xea, 0x75, 0x04, 0xbd, 0x16, 0xe9, 0xaf, 0xe9, 0xd7, 0x69, + 0x7f, 0xde, 0x46, 0x44, 0xbf, 0x48, 0x00, 0x17, 0x25, 0x33, 0x18, 0x81, 0xf3, 0xf3, 0x77, 0x2f, 0xa5, 0x3e, 0xf8, + 0xfd, 0xe0, 0x79, 0xdc, 0x6e, 0x21, 0x82, 0x72, 0x29, 0xe6, 0xbf, 0x62, 0x09, 0x47, 0x88, 0xa0, 0x51, 0x22, 0x72, + 0xe6, 0xae, 0x41, 0xab, 0xb3, 0xbf, 0x7f, 0x11, 0x1a, 0xa2, 0x79, 0xc6, 0xf2, 0xdc, 0x73, 0xc7, 0x37, 0xa4, 0xf4, + 0x09, 0x86, 0xb9, 0x95, 0xe2, 0x72, 0x26, 0x15, 0x5e, 0xf4, 0x1d, 0x7f, 0x97, 0xaa, 0x74, 0xd9, 0x06, 0xb1, 0x29, + 0x11, 0x50, 0x32, 0x36, 0xad, 0x5d, 0x7d, 0x72, 0xe6, 0x2d, 0x47, 0x4f, 0x4f, 0xac, 0x63, 0xc2, 0x9b, 0x13, 0xd4, + 0x4a, 0x66, 0x3c, 0x3d, 0xdf, 0x52, 0x1a, 0xdd, 0x6c, 0x29, 0x05, 0x95, 0xad, 0x84, 0xce, 0xbc, 0x7e, 0xe6, 0xd3, + 0x58, 0xaf, 0x14, 0x1f, 0x17, 0xc4, 0x58, 0xf9, 0x2d, 0x3f, 0x01, 0xa9, 0xb3, 0x0d, 0x6a, 0x84, 0xdf, 0x3e, 0x1d, + 0x94, 0xfc, 0x9a, 0xe9, 0xca, 0x51, 0x7e, 0xdf, 0x0a, 0xa1, 0xb4, 0x09, 0xfe, 0xeb, 0xe4, 0x57, 0xad, 0x95, 0xdd, + 0x7c, 0x9a, 0xe0, 0x1c, 0xad, 0xea, 0x77, 0x6c, 0xbd, 0xb9, 0xc7, 0xbe, 0xbe, 0xf7, 0x5b, 0x8a, 0x8d, 0xe2, 0x53, + 0xee, 0xff, 0x28, 0xe1, 0xb3, 0x8a, 0x04, 0x36, 0xc1, 0x54, 0x1a, 0x0f, 0x24, 0x33, 0xb9, 0x83, 0x68, 0xd5, 0xe7, + 0x1c, 0xae, 0x68, 0xc2, 0x7b, 0x30, 0x16, 0x19, 0x3b, 0x4f, 0xc4, 0xf5, 0xfa, 0x7b, 0xbd, 0x76, 0x37, 0x9e, 0xf2, + 0xc9, 0xd4, 0xb9, 0x77, 0xc5, 0x68, 0xb9, 0x09, 0x77, 0x4e, 0x50, 0xfc, 0xeb, 0xbf, 0x04, 0xc1, 0xbf, 0xfe, 0xcb, + 0x27, 0x9b, 0xc2, 0xf0, 0xc5, 0x05, 0x91, 0xd5, 0xb0, 0xbb, 0x4f, 0xd7, 0xf6, 0x99, 0xea, 0x38, 0xdf, 0xde, 0x66, + 0x63, 0x13, 0xa0, 0x7e, 0x63, 0x0b, 0x36, 0x0a, 0xf5, 0xe9, 0xf3, 0x7e, 0x0b, 0x60, 0xb0, 0xae, 0x4f, 0x42, 0x06, + 0x8d, 0x7e, 0x17, 0x68, 0x17, 0x38, 0xbc, 0xd7, 0x8e, 0xfc, 0x76, 0x0c, 0x7f, 0x6a, 0x0d, 0xbf, 0x13, 0x7c, 0xe3, + 0x9f, 0x18, 0x5d, 0x5c, 0x94, 0x09, 0x76, 0x6e, 0x57, 0xb8, 0xc0, 0xdf, 0xdf, 0x28, 0x31, 0x8a, 0x47, 0xd8, 0xc2, + 0x3d, 0x75, 0x3d, 0x90, 0x8e, 0x2e, 0x5e, 0xc3, 0x5b, 0x7b, 0x8e, 0x2f, 0x33, 0xeb, 0xe0, 0xbd, 0x43, 0x38, 0xc0, + 0x10, 0xf5, 0x55, 0xa9, 0x41, 0x37, 0x24, 0x03, 0x94, 0x82, 0xb9, 0x01, 0x60, 0x92, 0xd1, 0x85, 0xb1, 0x36, 0x4f, + 0xb5, 0x1b, 0x26, 0x5c, 0x27, 0x6d, 0xe3, 0x9e, 0xa9, 0x21, 0x9d, 0x78, 0xef, 0x15, 0xbe, 0x54, 0x63, 0x56, 0x59, + 0xf7, 0xca, 0xd5, 0x05, 0x76, 0xc4, 0x45, 0xa1, 0xc2, 0xf4, 0x7f, 0xdd, 0x15, 0x49, 0xfc, 0xfb, 0xa7, 0x23, 0x89, + 0xe2, 0x5e, 0x91, 0xc4, 0xbf, 0xff, 0xe1, 0x91, 0xc4, 0xbf, 0xba, 0x91, 0x44, 0xd8, 0xc4, 0x2f, 0xef, 0x15, 0xed, + 0xb3, 0x91, 0x18, 0x71, 0x9d, 0xd3, 0xb6, 0x51, 0xa3, 0x13, 0x31, 0x81, 0x50, 0xdf, 0xbf, 0x7f, 0xe4, 0x2e, 0x11, + 0x13, 0x37, 0x6e, 0x07, 0x6f, 0x6d, 0x85, 0x40, 0x5d, 0xd7, 0x46, 0xd8, 0x4c, 0xac, 0xac, 0x55, 0xde, 0x48, 0x69, + 0x3e, 0xb4, 0x6f, 0x50, 0x40, 0x61, 0xf9, 0x16, 0xa4, 0x16, 0xe9, 0xd8, 0x68, 0x5a, 0xa8, 0x02, 0x71, 0x65, 0xc7, + 0x4e, 0xc3, 0x5e, 0xb7, 0x70, 0x47, 0xe8, 0xda, 0xb7, 0xbc, 0xe8, 0xdb, 0xf7, 0x4b, 0xf4, 0xe3, 0x4d, 0xfb, 0xd9, + 0xa0, 0xdd, 0x3d, 0x6a, 0xcf, 0x50, 0x88, 0x40, 0x44, 0xaa, 0x82, 0x56, 0xf7, 0xe8, 0x08, 0x0a, 0xae, 0x9d, 0x82, + 0x0e, 0x14, 0x70, 0xa7, 0xe0, 0x11, 0x14, 0x8c, 0x9c, 0x82, 0xc7, 0x50, 0x10, 0x3b, 0x05, 0x4f, 0xa0, 0xe0, 0x0a, + 0x15, 0x03, 0x5e, 0x82, 0xfb, 0x04, 0x0f, 0x89, 0xb6, 0x5c, 0x6c, 0xd9, 0x13, 0xd2, 0x86, 0x10, 0x5e, 0x34, 0x51, + 0x99, 0x47, 0xe0, 0x10, 0x0c, 0x05, 0xb9, 0x9e, 0xb2, 0x34, 0x84, 0x20, 0xea, 0x73, 0x25, 0x63, 0x02, 0x29, 0xde, + 0xf3, 0x19, 0xb3, 0xdf, 0xcb, 0xb0, 0x78, 0xf0, 0x10, 0x1e, 0xb4, 0x86, 0x45, 0xb7, 0xdc, 0x39, 0x1d, 0xfb, 0x33, + 0x59, 0x28, 0x7a, 0x2f, 0xab, 0x3a, 0x3d, 0x5d, 0xb3, 0xdc, 0xf3, 0x1d, 0x31, 0x24, 0xc7, 0x17, 0x31, 0x4e, 0xc4, + 0x75, 0xf3, 0x06, 0xf5, 0xb6, 0xc7, 0x95, 0x00, 0xa2, 0x32, 0xae, 0xa4, 0xd6, 0x54, 0x3e, 0xbd, 0x8f, 0x26, 0xe5, + 0xef, 0xd7, 0x2c, 0xcf, 0xa3, 0x89, 0x69, 0xb9, 0x3b, 0x8e, 0xa4, 0x40, 0x74, 0x63, 0x48, 0x16, 0x08, 0x88, 0x05, + 0xc1, 0x66, 0x81, 0x2d, 0x6f, 0x42, 0x43, 0x80, 0x9d, 0x7a, 0x54, 0x49, 0x4d, 0x5f, 0x2f, 0x92, 0xd1, 0xa4, 0x2a, + 0x38, 0x9e, 0x67, 0x4c, 0x95, 0x6a, 0x0c, 0x17, 0xc7, 0x87, 0x50, 0xa0, 0xab, 0x77, 0x44, 0x8f, 0xac, 0xe3, 0x60, + 0x77, 0x0c, 0xc9, 0xb3, 0xd1, 0x23, 0x37, 0xdf, 0xa6, 0x4c, 0xb6, 0xd9, 0x8c, 0x59, 0x7c, 0xd6, 0x1e, 0xc1, 0x1f, + 0x13, 0x11, 0xf9, 0x6c, 0x3c, 0x1e, 0xdf, 0x19, 0x4d, 0xfa, 0x2c, 0x1e, 0xb3, 0x0e, 0x7b, 0xd4, 0x85, 0x5c, 0x8c, + 0xa6, 0x89, 0x41, 0xb4, 0x0b, 0x85, 0xbb, 0xe5, 0xfd, 0x1a, 0x43, 0xb8, 0x42, 0x4e, 0x97, 0xf7, 0x8f, 0x2c, 0x15, + 0xf3, 0x8c, 0x2d, 0x67, 0x51, 0x36, 0xe1, 0x69, 0xd8, 0x2a, 0x82, 0x2b, 0x13, 0x8a, 0xf9, 0xec, 0xe9, 0xd3, 0xa7, + 0x45, 0x10, 0xdb, 0xa7, 0x56, 0x1c, 0x17, 0xc1, 0x68, 0x59, 0x2e, 0xa3, 0xd5, 0x1a, 0x8f, 0x8b, 0x80, 0xdb, 0x82, + 0xa3, 0xce, 0x28, 0x3e, 0xea, 0x14, 0xc1, 0xb5, 0xd3, 0xa2, 0x08, 0x98, 0x79, 0xca, 0x58, 0x5c, 0x4b, 0xe8, 0x78, + 0xd2, 0x6a, 0x15, 0x81, 0x26, 0xb4, 0x25, 0x98, 0x63, 0xfa, 0x67, 0x18, 0x2d, 0xa4, 0x00, 0x96, 0xdc, 0x15, 0xd2, + 0x1f, 0x9c, 0x9b, 0x97, 0x65, 0xe8, 0x0f, 0x4b, 0x14, 0x78, 0x48, 0xbe, 0x74, 0x83, 0x26, 0x40, 0xcc, 0x2a, 0x58, + 0x22, 0x6c, 0x4c, 0xa5, 0x56, 0x0d, 0x94, 0xa5, 0xaa, 0xbf, 0xa4, 0xa2, 0x8a, 0xa5, 0x00, 0xff, 0x81, 0x96, 0xfa, + 0xad, 0x6e, 0x92, 0xed, 0xe0, 0xfa, 0x8c, 0x7d, 0x92, 0xeb, 0xdf, 0xde, 0x87, 0xe9, 0x33, 0xf6, 0x47, 0x33, 0x7d, + 0xf3, 0xea, 0x53, 0xcd, 0xf4, 0x35, 0x5b, 0x9b, 0x49, 0x8a, 0x46, 0x53, 0x36, 0xfa, 0x78, 0x29, 0x6e, 0x9a, 0x70, + 0x24, 0x32, 0xa4, 0xf8, 0xe9, 0xfe, 0x6f, 0x4d, 0xfe, 0xb0, 0x83, 0x39, 0xdf, 0xa5, 0x50, 0x62, 0xf3, 0x6d, 0x4a, + 0xd1, 0x5b, 0x6b, 0xd3, 0xe9, 0x92, 0xf1, 0x98, 0xa2, 0xb7, 0xe3, 0x31, 0xb2, 0x57, 0xfe, 0x22, 0xc9, 0x54, 0xab, + 0x37, 0xb5, 0x12, 0xd5, 0xea, 0x8b, 0x2f, 0xdc, 0x32, 0xb7, 0xc0, 0x84, 0x5c, 0xdc, 0xf0, 0x8a, 0xa9, 0x89, 0x79, + 0x0e, 0x47, 0x0d, 0x3e, 0x97, 0x51, 0x7f, 0xe7, 0x60, 0x56, 0x7b, 0x3d, 0x74, 0x09, 0xf0, 0x96, 0x77, 0x5a, 0xaf, + 0xdf, 0x77, 0x9f, 0x30, 0x9b, 0x7e, 0xf7, 0xec, 0xf6, 0xcb, 0xd8, 0x9f, 0x49, 0x5c, 0xf0, 0xfc, 0x6d, 0xba, 0x76, + 0x97, 0x45, 0xc3, 0x48, 0xa9, 0xbb, 0xac, 0x42, 0x8a, 0xc9, 0x24, 0x81, 0x0f, 0x96, 0x2c, 0x6b, 0xef, 0x41, 0xd5, + 0xdd, 0xfb, 0xb5, 0xf5, 0x86, 0x6e, 0x47, 0xf3, 0xd6, 0x50, 0xf5, 0xfd, 0x24, 0x9d, 0x03, 0x7d, 0x65, 0x3e, 0xa4, + 0xa3, 0xcc, 0xc1, 0xa5, 0xe1, 0xff, 0x4b, 0x9d, 0x39, 0x2b, 0x21, 0x6b, 0x44, 0x0f, 0x1c, 0x17, 0x85, 0xb9, 0x73, + 0x10, 0xf3, 0x7c, 0x0e, 0xef, 0xe7, 0xd4, 0x3d, 0xd9, 0xa7, 0x58, 0x78, 0x7e, 0xed, 0xc4, 0x35, 0x6a, 0xdb, 0x55, + 0xd8, 0xc0, 0x86, 0x76, 0x14, 0xcf, 0x64, 0x81, 0x8c, 0xbf, 0xd9, 0x22, 0x11, 0x79, 0x1a, 0x9f, 0x3a, 0xe2, 0xe2, + 0xac, 0x10, 0x9c, 0xbe, 0xe5, 0x86, 0xd8, 0x2a, 0x5b, 0x50, 0xb8, 0x71, 0x3b, 0x55, 0xa3, 0xb1, 0xa5, 0xa2, 0x04, + 0xf9, 0x3c, 0x4a, 0x35, 0x1b, 0xa5, 0x48, 0xf3, 0x83, 0xfd, 0x65, 0xb5, 0xf3, 0x05, 0xb2, 0x60, 0x6b, 0xe2, 0xed, + 0x1d, 0x1f, 0x42, 0x87, 0x9e, 0x57, 0x03, 0x3d, 0xdd, 0x08, 0x2e, 0x7c, 0x22, 0xcc, 0x7f, 0x11, 0xe4, 0xd7, 0x24, + 0xc8, 0xaf, 0xbd, 0x3f, 0x2f, 0x9b, 0xd7, 0xec, 0xf2, 0x23, 0x97, 0x4d, 0x19, 0xcd, 0x9b, 0xa0, 0xf0, 0x2b, 0xa7, + 0xa0, 0x61, 0xcf, 0x2a, 0x59, 0x4d, 0xdf, 0xd8, 0xef, 0x2e, 0x72, 0xc8, 0x06, 0x50, 0x6a, 0x6b, 0x98, 0x8a, 0x94, + 0x75, 0xeb, 0x49, 0x89, 0x6e, 0x70, 0xd9, 0x62, 0x6b, 0xb8, 0x14, 0x90, 0x3d, 0x20, 0x6f, 0xc3, 0x96, 0x61, 0xeb, + 0x2d, 0x1b, 0x39, 0x6e, 0x6d, 0x6d, 0x1f, 0x1a, 0xe4, 0x36, 0x94, 0xf4, 0xca, 0x36, 0x23, 0xe8, 0xbb, 0x22, 0xe0, + 0x9f, 0x4a, 0xd1, 0x03, 0x57, 0xa2, 0xfd, 0xeb, 0xe4, 0x36, 0xae, 0x17, 0xab, 0x14, 0xbd, 0xfb, 0x40, 0x16, 0x46, + 0x63, 0xc9, 0x32, 0x72, 0x9f, 0x96, 0x97, 0xea, 0x36, 0xcd, 0x12, 0xc4, 0x4c, 0xd8, 0x7e, 0x3a, 0xbf, 0xb9, 0xff, + 0xf0, 0x77, 0x2f, 0xbf, 0x30, 0x38, 0xb2, 0x6f, 0x97, 0x41, 0xa8, 0x0b, 0x07, 0x21, 0x89, 0x6e, 0x43, 0x9e, 0x2a, + 0x99, 0x77, 0x09, 0xfe, 0xc0, 0xee, 0x5c, 0x98, 0x5c, 0xd3, 0x8c, 0x25, 0xea, 0x53, 0x72, 0x66, 0x2b, 0x8e, 0x1e, + 0xcf, 0x6f, 0xec, 0x6e, 0xb4, 0xd7, 0x72, 0x48, 0xff, 0xd0, 0x54, 0xd1, 0xdd, 0xb9, 0xa9, 0xf5, 0x74, 0xc7, 0x47, + 0xf3, 0x9b, 0xae, 0x16, 0xb4, 0xcd, 0x4c, 0x43, 0xd5, 0x9a, 0xdf, 0xb8, 0xc9, 0xb2, 0xd5, 0x40, 0x5e, 0x70, 0x94, + 0x7b, 0x2c, 0xca, 0x59, 0x17, 0xde, 0x9f, 0xcd, 0x47, 0x51, 0x62, 0x84, 0xf9, 0x8c, 0xc7, 0x71, 0xc2, 0xba, 0x56, + 0x5e, 0x7b, 0xed, 0xc7, 0x90, 0x6b, 0xea, 0x6e, 0x59, 0x7d, 0x57, 0x1c, 0xe4, 0x95, 0x78, 0x8a, 0x2e, 0x73, 0x91, + 0xc0, 0xc7, 0x2b, 0xb6, 0xa2, 0xd3, 0x24, 0x61, 0xb6, 0x2a, 0xe4, 0xa9, 0xdf, 0xf5, 0xb5, 0x3c, 0x6a, 0xfd, 0xa9, + 0xab, 0x36, 0xbc, 0xd5, 0x95, 0x62, 0x1e, 0x36, 0x8f, 0xea, 0x0b, 0x81, 0xaa, 0x72, 0x09, 0x64, 0xcb, 0xb2, 0x08, + 0x48, 0x2b, 0xcd, 0xa7, 0xbd, 0xa0, 0x6d, 0xca, 0xd4, 0x00, 0xf0, 0xa2, 0xe7, 0xb2, 0xa8, 0xa8, 0x2f, 0xe6, 0xdf, + 0xe7, 0xb4, 0x7c, 0xbe, 0xfd, 0xb4, 0x7c, 0x6e, 0x4f, 0xcb, 0xdd, 0x14, 0xfb, 0xd9, 0xb8, 0x0d, 0x7f, 0xba, 0xd5, + 0x82, 0xc2, 0x96, 0x77, 0x34, 0xbf, 0xf1, 0x40, 0x4f, 0x6b, 0x76, 0xe6, 0x37, 0x3a, 0x55, 0x18, 0x62, 0x16, 0x2d, + 0x48, 0x9e, 0x25, 0x2d, 0x0f, 0x0a, 0xe1, 0x6f, 0xab, 0x56, 0xd5, 0x7e, 0x08, 0x75, 0xd0, 0xeb, 0xd1, 0x66, 0x5d, + 0xe7, 0xee, 0x43, 0x1b, 0xa6, 0x42, 0xfa, 0xa1, 0xe5, 0xc6, 0x38, 0x90, 0xd1, 0xe5, 0x25, 0x8b, 0xc3, 0xb1, 0x18, + 0x2d, 0xf2, 0x7f, 0x36, 0xf0, 0x1b, 0x24, 0xde, 0x79, 0xa4, 0xd7, 0xc6, 0xb1, 0x5d, 0x75, 0xe2, 0xb2, 0x1d, 0x61, + 0x59, 0xee, 0x53, 0x98, 0x8f, 0xa2, 0x84, 0xf9, 0x9d, 0xe0, 0xe1, 0x96, 0x43, 0xf0, 0x1f, 0xb2, 0x37, 0x5b, 0x17, + 0xf3, 0x7b, 0x91, 0x71, 0x27, 0x12, 0x7e, 0x15, 0x0e, 0xdc, 0x3d, 0x6c, 0x3d, 0xdd, 0x0e, 0xee, 0xc0, 0xce, 0x34, + 0xb4, 0x42, 0xc1, 0xc8, 0x9d, 0x98, 0x8d, 0xa3, 0x45, 0x22, 0xef, 0x1e, 0x75, 0x17, 0x65, 0x6c, 0x8c, 0x7a, 0x07, + 0x43, 0xaf, 0xda, 0xde, 0x93, 0x4b, 0x7f, 0xf6, 0xf9, 0x43, 0xf8, 0xa3, 0xf3, 0x9e, 0x6e, 0x2b, 0x5d, 0x5d, 0xdb, + 0xaa, 0xa0, 0xab, 0xef, 0xd7, 0x94, 0x71, 0x2d, 0xc2, 0x95, 0x3e, 0x7e, 0xdf, 0xd6, 0xa0, 0x55, 0xde, 0xab, 0xb9, + 0xd1, 0xb2, 0x7e, 0x55, 0xeb, 0x5f, 0x37, 0xf8, 0x3d, 0xdb, 0x8e, 0xb4, 0xe6, 0x5a, 0x6f, 0x6b, 0xbe, 0xa5, 0xb7, + 0xd1, 0xd8, 0x62, 0x5c, 0xb5, 0xdf, 0xa7, 0xb7, 0xa5, 0x89, 0xa2, 0xa3, 0x90, 0x60, 0xa5, 0xec, 0x6b, 0x2b, 0x85, + 0x33, 0xfa, 0x00, 0xde, 0x64, 0xeb, 0xdd, 0xcc, 0x92, 0x34, 0xa7, 0x68, 0x2a, 0xe5, 0x3c, 0xd4, 0x1f, 0x5f, 0xbd, + 0x3e, 0x0a, 0x44, 0x36, 0x39, 0xec, 0xb4, 0x5a, 0x2d, 0x78, 0x03, 0x29, 0xf2, 0xae, 0x38, 0xbb, 0x7e, 0x26, 0x6e, + 0x28, 0x7a, 0xe2, 0x3d, 0xf5, 0x9e, 0x1c, 0x79, 0x8f, 0x1e, 0x23, 0x4f, 0xb1, 0x73, 0x8a, 0x9e, 0x1c, 0x21, 0x4f, + 0xb3, 0x73, 0x8a, 0x1e, 0x3d, 0x46, 0xbd, 0xe3, 0x89, 0x55, 0xc9, 0xe0, 0x0a, 0xa3, 0xd6, 0x77, 0x72, 0x99, 0x89, + 0x8f, 0xac, 0x7e, 0x70, 0x75, 0x99, 0xc9, 0x8c, 0xeb, 0xd8, 0x47, 0x38, 0xbd, 0xa3, 0x68, 0x1e, 0x2a, 0xa2, 0x70, + 0x0b, 0xc1, 0x2d, 0xa3, 0x4b, 0xd5, 0x14, 0xa0, 0x66, 0x5e, 0xa2, 0xde, 0x31, 0x64, 0xb1, 0x7b, 0x31, 0x45, 0xaf, + 0x3b, 0x4f, 0xbc, 0xf6, 0xe3, 0xab, 0xe6, 0xc3, 0x51, 0xab, 0xd9, 0xf6, 0xda, 0xcd, 0x4e, 0xf0, 0xc4, 0xeb, 0xe8, + 0x7f, 0xbd, 0x96, 0x77, 0xe4, 0xb5, 0x83, 0x27, 0xde, 0x91, 0xd7, 0x09, 0x9e, 0x5c, 0x3d, 0xd4, 0xc9, 0x0c, 0x11, + 0x3a, 0xec, 0x1d, 0xc3, 0x87, 0x34, 0x6f, 0x28, 0xfa, 0x1c, 0xe9, 0xcf, 0xd5, 0xa2, 0xcf, 0xdc, 0xd2, 0xf6, 0xd3, + 0xad, 0xc5, 0x9d, 0x27, 0x5b, 0x8b, 0x8f, 0x1e, 0x6f, 0x2d, 0x7e, 0xf8, 0xa8, 0x5e, 0x7c, 0x38, 0xd1, 0x55, 0xe5, + 0x29, 0xa7, 0x68, 0x16, 0xc9, 0x8c, 0xdf, 0xf8, 0x6d, 0xaf, 0xe5, 0xb5, 0xbc, 0x26, 0xfc, 0xf7, 0xa4, 0x83, 0xcb, + 0x5e, 0x97, 0xd0, 0xab, 0x5c, 0xe5, 0x93, 0xa7, 0x5e, 0xfb, 0xf1, 0xcb, 0xce, 0xe3, 0x11, 0xb4, 0x53, 0x0b, 0x6d, + 0x7b, 0xed, 0xab, 0xa3, 0xa7, 0xa3, 0x96, 0x07, 0x1d, 0xdb, 0xf0, 0x67, 0xfa, 0xa8, 0x33, 0xd2, 0x0f, 0x2d, 0xa8, + 0xff, 0xb6, 0xfd, 0x24, 0x6f, 0x35, 0xdb, 0xf0, 0xe7, 0x97, 0x52, 0x23, 0x06, 0x7d, 0xdc, 0x1d, 0xf7, 0x61, 0xcb, + 0x3b, 0x7a, 0x3a, 0xed, 0x04, 0x9f, 0x5f, 0x3d, 0x09, 0x9e, 0x4e, 0xdb, 0x4f, 0xbe, 0xd5, 0x4f, 0x49, 0xb3, 0x13, + 0x7c, 0x0e, 0x7f, 0xbf, 0x3d, 0x6a, 0x4d, 0x9b, 0xed, 0xe0, 0xe9, 0xd5, 0x51, 0x70, 0x94, 0x34, 0x1f, 0x07, 0x4f, + 0xe1, 0x6f, 0x35, 0xdc, 0x54, 0xcc, 0x18, 0xf2, 0x60, 0xbf, 0xd7, 0xcc, 0x2d, 0x77, 0x8e, 0xce, 0x43, 0xef, 0xd1, + 0xc3, 0x97, 0x4f, 0xaf, 0x9a, 0x0f, 0xa7, 0xed, 0xce, 0x55, 0x73, 0xe7, 0xcf, 0x6f, 0x01, 0xf1, 0x66, 0xe0, 0x88, + 0xc1, 0x75, 0x22, 0x8b, 0x38, 0xf5, 0x36, 0xdc, 0x07, 0x24, 0xdf, 0x65, 0x5e, 0x67, 0x9f, 0x36, 0xaf, 0x53, 0x76, + 0x1f, 0xfb, 0x3a, 0xfb, 0xc3, 0xed, 0xeb, 0x9c, 0xad, 0x39, 0x55, 0x6f, 0xe5, 0x86, 0x19, 0xbd, 0x6e, 0x7b, 0xbd, + 0x93, 0xfe, 0x80, 0xc3, 0x57, 0x97, 0x8a, 0xee, 0x2d, 0xbc, 0x70, 0xdb, 0xf5, 0x36, 0x08, 0x38, 0xc8, 0xb7, 0x52, + 0x9f, 0x64, 0xb1, 0x0b, 0x21, 0xc9, 0xa7, 0x11, 0xf2, 0xed, 0x7d, 0xf0, 0x91, 0xfc, 0xe1, 0xf8, 0x10, 0x2e, 0x3e, + 0x6a, 0x7e, 0x5e, 0x65, 0xcf, 0x2a, 0x7b, 0xf4, 0x4c, 0x3d, 0xfb, 0x70, 0xe3, 0xa4, 0x81, 0x0e, 0x19, 0x14, 0xe5, + 0x48, 0xc7, 0x15, 0x5e, 0xfe, 0x1a, 0x97, 0xb4, 0xbe, 0x5e, 0x46, 0x91, 0x31, 0xfe, 0xe7, 0xf0, 0x65, 0x05, 0xfb, + 0x70, 0xa5, 0x2f, 0x3c, 0x53, 0xd4, 0x09, 0x5a, 0x41, 0xab, 0x74, 0x1c, 0xc0, 0x95, 0x42, 0xba, 0x14, 0x32, 0x82, + 0x8f, 0x7b, 0x26, 0x62, 0xa2, 0x3e, 0x03, 0x0a, 0x2f, 0x5f, 0x57, 0x1f, 0x64, 0xd5, 0xef, 0xbd, 0x0f, 0x11, 0x32, + 0x2f, 0x22, 0x80, 0x2b, 0x6b, 0xdf, 0xc0, 0xb5, 0x3e, 0xeb, 0xb1, 0x9e, 0x81, 0x4d, 0xfd, 0x9a, 0xc5, 0x3c, 0xf2, + 0x91, 0x3f, 0xcf, 0xd8, 0x98, 0x65, 0x79, 0xb3, 0x76, 0xd7, 0x4d, 0x5d, 0x73, 0xc3, 0xc8, 0x7e, 0x46, 0x32, 0x83, + 0x97, 0x09, 0xd3, 0x81, 0xf1, 0x6a, 0x21, 0xa3, 0xe6, 0xa3, 0x82, 0xd8, 0x92, 0x0c, 0x38, 0x7a, 0xa5, 0x1a, 0x20, + 0xad, 0x1b, 0xb4, 0x83, 0xce, 0x23, 0xac, 0x79, 0x09, 0xbc, 0xa4, 0xf5, 0x7b, 0xbf, 0x79, 0xd4, 0xfa, 0x13, 0x76, + 0xba, 0x95, 0x03, 0x0d, 0x8d, 0x53, 0x27, 0xab, 0x3e, 0xbf, 0x5b, 0xbf, 0x88, 0x88, 0x34, 0x45, 0x7c, 0xa6, 0xd7, + 0x0e, 0xaf, 0x7b, 0x35, 0xf1, 0x43, 0x7d, 0x9d, 0x7e, 0xcc, 0x27, 0xbe, 0xfb, 0x71, 0x55, 0xfd, 0x12, 0x58, 0xf5, + 0x4d, 0x66, 0x5c, 0x54, 0x4d, 0x32, 0xbc, 0x54, 0xbe, 0x78, 0x9e, 0x7a, 0xd9, 0x6a, 0xe5, 0x67, 0xe0, 0x88, 0xa5, + 0x0e, 0x4e, 0xe1, 0x19, 0xd7, 0x90, 0x9c, 0x91, 0x12, 0x20, 0x85, 0x60, 0x9a, 0xe9, 0xff, 0xab, 0x62, 0xfb, 0xc3, + 0xb8, 0x57, 0x82, 0x24, 0x4a, 0x27, 0x40, 0x85, 0x51, 0x3a, 0xd9, 0x70, 0xde, 0xe8, 0x70, 0xc2, 0x5a, 0x69, 0x35, + 0x54, 0xe5, 0xa4, 0xc9, 0x9f, 0xdd, 0xbe, 0x37, 0x6f, 0x8b, 0x42, 0xe0, 0x03, 0x55, 0xbe, 0xef, 0xea, 0xcd, 0xb6, + 0x0d, 0xfa, 0x40, 0x7f, 0xae, 0x5c, 0x65, 0xc3, 0x81, 0xf4, 0x83, 0x2b, 0x86, 0x9e, 0xb1, 0x79, 0x28, 0xd2, 0xb2, + 0x2f, 0x66, 0x57, 0x7c, 0x64, 0x44, 0x18, 0xf1, 0xcc, 0x35, 0xeb, 0xa6, 0xda, 0x1a, 0xda, 0x26, 0xda, 0xea, 0x1f, + 0x45, 0x2a, 0xdf, 0x99, 0xa6, 0x02, 0xf5, 0x1e, 0x94, 0xdf, 0x8a, 0xdc, 0xb5, 0x09, 0xf0, 0x0d, 0xf5, 0x41, 0xc6, + 0x92, 0x7f, 0xa6, 0x0f, 0xe0, 0x2b, 0xea, 0x0f, 0x86, 0xf0, 0x01, 0xef, 0x40, 0x89, 0x82, 0x07, 0xd5, 0xc7, 0xd4, + 0x81, 0x0f, 0x36, 0x6e, 0x66, 0x09, 0xb9, 0xaf, 0xf8, 0x36, 0xa2, 0xba, 0xf3, 0xa8, 0x12, 0xd5, 0x9d, 0x47, 0xae, + 0xf4, 0x6c, 0x7b, 0xed, 0x4e, 0xf0, 0xc8, 0x11, 0x00, 0x57, 0x4d, 0xf8, 0xbf, 0x26, 0x02, 0x1e, 0x06, 0x8f, 0x4a, + 0x19, 0xf0, 0xaa, 0xdd, 0x09, 0x8e, 0xb4, 0xb8, 0xe9, 0x04, 0x8f, 0x7e, 0x50, 0x0c, 0x5a, 0x33, 0xe7, 0xfa, 0x81, + 0xd8, 0x12, 0xaa, 0xd1, 0x19, 0x7d, 0x88, 0xf8, 0xe5, 0x17, 0xe9, 0xcc, 0xf9, 0x34, 0x2e, 0xa1, 0xe7, 0x51, 0x06, + 0x9f, 0x05, 0xa9, 0x9f, 0xdd, 0x5a, 0x1d, 0xa9, 0xf1, 0x8b, 0x2d, 0x53, 0xc0, 0x09, 0x47, 0xc4, 0xbd, 0xa7, 0x0c, + 0x97, 0x7c, 0xd5, 0x4b, 0x94, 0xed, 0xbb, 0xe4, 0x76, 0x93, 0xb6, 0x6e, 0x68, 0xdf, 0x57, 0xa7, 0x98, 0x05, 0x57, + 0x2f, 0xac, 0x57, 0x93, 0x7c, 0x19, 0x17, 0xeb, 0xf3, 0x43, 0x62, 0x61, 0x26, 0x9c, 0xab, 0xda, 0xac, 0x4a, 0x87, + 0x8f, 0x39, 0x5c, 0xae, 0x2f, 0x0a, 0x0b, 0x7a, 0xcd, 0x19, 0x58, 0x61, 0x49, 0xf1, 0x0b, 0x96, 0xf7, 0x11, 0x14, + 0xa1, 0x10, 0x29, 0x47, 0x12, 0x2a, 0x3f, 0x8d, 0x52, 0x12, 0x76, 0x55, 0x40, 0xd4, 0x95, 0x16, 0x38, 0xb5, 0x80, + 0x1f, 0x84, 0x0f, 0x0e, 0x76, 0x9e, 0x17, 0xa5, 0x8d, 0xc1, 0x5a, 0xab, 0x4f, 0x2a, 0xb8, 0xac, 0x08, 0xb9, 0x88, + 0x2e, 0xc7, 0x55, 0x28, 0xc4, 0x06, 0x4f, 0x97, 0x2c, 0x92, 0x41, 0x94, 0xea, 0x14, 0x05, 0x87, 0x61, 0x91, 0x36, + 0x3b, 0xc2, 0x85, 0x90, 0x91, 0xf3, 0xcd, 0x54, 0x73, 0xce, 0x85, 0x8c, 0xec, 0xc5, 0xc3, 0x54, 0xd6, 0x32, 0xf3, + 0xa7, 0x9d, 0xde, 0xdb, 0xf7, 0x27, 0x9e, 0x3e, 0x9e, 0xc7, 0x87, 0xd3, 0x4e, 0xef, 0x58, 0x59, 0xe6, 0xfa, 0xda, + 0x12, 0xd5, 0xd7, 0x96, 0x3c, 0x73, 0x85, 0x0d, 0xe2, 0x35, 0xc5, 0xa1, 0x5e, 0x36, 0xf2, 0x58, 0x3a, 0xd2, 0x3e, + 0xc5, 0xd9, 0x22, 0x91, 0x1c, 0x5e, 0x08, 0x7c, 0x08, 0x5d, 0x9b, 0xb0, 0x61, 0x65, 0x96, 0xab, 0xd5, 0x70, 0x64, + 0x6a, 0x3d, 0x90, 0x63, 0x9e, 0x30, 0x9b, 0xd7, 0x6a, 0x86, 0x2a, 0xf3, 0xb0, 0x37, 0x5b, 0xe7, 0x8b, 0xcb, 0x19, + 0x97, 0xc8, 0x66, 0x8b, 0x7f, 0x30, 0x1d, 0x8e, 0xd5, 0x54, 0xbd, 0x8b, 0xc2, 0xb8, 0x48, 0xed, 0xc7, 0x4f, 0xd6, + 0x3e, 0x37, 0xaf, 0x57, 0x6f, 0x24, 0x04, 0xdc, 0x3f, 0x9a, 0x1e, 0xf5, 0x4a, 0xa7, 0xa4, 0x5b, 0x57, 0x1c, 0x1f, + 0x4e, 0x8f, 0x7a, 0x17, 0xe1, 0xdc, 0x8c, 0xf7, 0x4a, 0x6c, 0x7c, 0xba, 0xbe, 0xe4, 0x98, 0x7d, 0x95, 0x68, 0xaf, + 0x6f, 0x74, 0x1a, 0x80, 0x47, 0x22, 0x41, 0xbd, 0x63, 0xa3, 0x0c, 0x78, 0x2a, 0xe8, 0x8a, 0x1e, 0xb5, 0x6c, 0xee, + 0x7e, 0x22, 0x94, 0xb6, 0xa4, 0xbb, 0x38, 0x93, 0xd4, 0xfc, 0xba, 0xd3, 0x76, 0xef, 0x38, 0x32, 0x6a, 0x26, 0x30, + 0x8f, 0x3c, 0x3c, 0x84, 0xce, 0xa0, 0xcb, 0x05, 0x5c, 0x1c, 0x5e, 0xb3, 0xcb, 0x66, 0x34, 0xe7, 0x95, 0x13, 0x15, + 0x94, 0x8e, 0x72, 0x4a, 0x51, 0xcd, 0x04, 0x3f, 0xa3, 0xb5, 0x45, 0x2a, 0x16, 0x5e, 0x18, 0x0f, 0xad, 0xd2, 0xd5, + 0x59, 0x24, 0x91, 0xa7, 0x39, 0xbc, 0xf5, 0xe4, 0x1a, 0xd9, 0x5b, 0xa0, 0xde, 0xbf, 0xfd, 0x8f, 0xff, 0x65, 0x9c, + 0xb3, 0xc7, 0x87, 0xd3, 0xb6, 0x1d, 0x6b, 0x0d, 0xd1, 0xc5, 0x31, 0x5c, 0x77, 0xab, 0xa2, 0x89, 0xec, 0xa6, 0x39, + 0xc9, 0x78, 0xdc, 0x9c, 0x46, 0xc9, 0x18, 0xf5, 0x76, 0x23, 0xc8, 0xbd, 0xe7, 0x62, 0xa0, 0xae, 0x17, 0x01, 0x09, + 0xfe, 0xa6, 0x9b, 0x1a, 0x36, 0xe1, 0x5f, 0x9d, 0x56, 0xf7, 0xde, 0x46, 0x75, 0xa0, 0x6a, 0x77, 0x37, 0x32, 0xf3, + 0x8d, 0x24, 0xc3, 0xd4, 0xb2, 0xda, 0x95, 0x8d, 0x02, 0x79, 0x65, 0x34, 0xe4, 0xff, 0xfe, 0xcf, 0xff, 0xf2, 0xdf, + 0xec, 0x23, 0x04, 0x39, 0xfe, 0xed, 0xbf, 0xff, 0xe7, 0xff, 0xf3, 0xbf, 0xff, 0x2b, 0xa4, 0xf9, 0x9b, 0x40, 0x88, + 0xe2, 0x13, 0x5e, 0x15, 0x05, 0xd1, 0x0c, 0xc3, 0x83, 0x4c, 0xb8, 0x19, 0xcf, 0x25, 0x1f, 0xd5, 0x2f, 0x71, 0x9c, + 0xa9, 0x09, 0xd5, 0x61, 0x33, 0xd0, 0xa9, 0x43, 0x5b, 0x54, 0x34, 0x52, 0x43, 0xb9, 0xa2, 0xc5, 0xe2, 0xf8, 0x10, + 0xf0, 0x7d, 0xbf, 0x7b, 0x6f, 0x41, 0xb9, 0x1d, 0x4b, 0xeb, 0xfa, 0x83, 0x92, 0xa2, 0x2a, 0xf7, 0xc0, 0x29, 0xbf, + 0x84, 0xc7, 0xb0, 0xe3, 0x14, 0xab, 0xdd, 0xab, 0xf5, 0xe9, 0xfe, 0xb4, 0xc8, 0x25, 0x1f, 0x03, 0xca, 0xb5, 0x83, + 0x51, 0xc5, 0x3f, 0x9b, 0xa0, 0xfe, 0x25, 0xb7, 0x85, 0x1a, 0x45, 0xdb, 0x8c, 0x0f, 0x9f, 0xfe, 0xa9, 0xf8, 0xcb, + 0x0c, 0x94, 0x2c, 0xcf, 0x9f, 0x45, 0x37, 0xc6, 0x92, 0x7c, 0xdc, 0x6a, 0xcd, 0x6f, 0xf0, 0xb2, 0x9a, 0x81, 0xec, + 0x9a, 0x4c, 0x39, 0x25, 0xdd, 0x01, 0x55, 0xe0, 0xb4, 0xf4, 0x7f, 0xb6, 0x3c, 0x70, 0xa2, 0x7a, 0xad, 0xa2, 0xf8, + 0xf3, 0x52, 0xb9, 0xe0, 0xf8, 0x2f, 0x10, 0xe0, 0x34, 0xde, 0xca, 0x4b, 0xe1, 0x2e, 0x6e, 0xe9, 0xf4, 0xea, 0xe8, + 0x5e, 0xd3, 0xf6, 0xe6, 0x75, 0x2e, 0x37, 0x40, 0xeb, 0x86, 0x56, 0x1f, 0x42, 0xb0, 0x74, 0xda, 0x26, 0xd3, 0xce, + 0xb2, 0x1c, 0x5e, 0x4a, 0x31, 0x73, 0x23, 0xb2, 0x2c, 0x62, 0x23, 0x36, 0xb6, 0x5e, 0x5e, 0x53, 0xaf, 0xa3, 0xad, + 0xc5, 0xf4, 0x68, 0xcb, 0x5c, 0x06, 0x24, 0x15, 0x89, 0xf5, 0x5a, 0xc5, 0x67, 0x70, 0x02, 0x97, 0xe3, 0x44, 0x44, + 0x32, 0x54, 0x04, 0xdb, 0x75, 0xe3, 0xba, 0x11, 0xb0, 0x19, 0xb1, 0x74, 0xe0, 0xe9, 0xea, 0xa6, 0xe0, 0x6f, 0xad, + 0x5f, 0xba, 0x2b, 0x02, 0xd5, 0xdd, 0x1d, 0x4a, 0xbb, 0x6b, 0xbe, 0x35, 0xe1, 0xd2, 0x97, 0x35, 0x3f, 0x87, 0x91, + 0x31, 0x1d, 0xbc, 0xbd, 0x5e, 0x8b, 0x6a, 0x5d, 0xfb, 0x95, 0xf4, 0x91, 0x02, 0x13, 0xad, 0xb7, 0x52, 0x85, 0xd0, + 0xea, 0x25, 0xfd, 0xb6, 0xb4, 0x82, 0xa2, 0xf9, 0x5c, 0x35, 0xc4, 0xdd, 0xe3, 0x43, 0xad, 0xbc, 0x02, 0xf7, 0x50, + 0xb9, 0x00, 0x3a, 0xf4, 0x6e, 0x1a, 0x99, 0xa3, 0xa0, 0x7f, 0x99, 0xa0, 0x3c, 0x7c, 0x3c, 0xab, 0xf7, 0xff, 0x00, + 0x08, 0x50, 0x84, 0x3d, 0xcd, 0x86, 0x00, 0x00}; } // namespace web_server } // namespace esphome diff --git a/esphome/components/web_server/server_index_v3.h b/esphome/components/web_server/server_index_v3.h index f2f278b08f..f649a9385e 100644 --- a/esphome/components/web_server/server_index_v3.h +++ b/esphome/components/web_server/server_index_v3.h @@ -3632,366 +3632,367 @@ const uint8_t INDEX_GZ[] PROGMEM = { 0xe7, 0xec, 0xd8, 0x98, 0x31, 0x94, 0x4f, 0x43, 0x40, 0x9e, 0xd0, 0xf7, 0x01, 0xcd, 0x25, 0x67, 0x23, 0xad, 0x2b, 0xfb, 0x10, 0x17, 0x97, 0xdc, 0x84, 0x6a, 0x31, 0x6f, 0x2b, 0x3d, 0x2a, 0xc4, 0x1b, 0x16, 0x80, 0x65, 0xe9, 0x69, 0x93, 0x82, 0x6c, 0x94, 0x54, 0x45, 0xfe, 0x13, 0xbf, 0x03, 0xae, 0xad, 0xac, 0xe4, 0x0a, 0x78, 0xf5, 0xff, 0xd3, - 0xdc, 0xb3, 0x2e, 0xb7, 0x6d, 0x5c, 0xfd, 0xbf, 0x4f, 0x01, 0xc3, 0xae, 0x03, 0xd8, 0x00, 0x04, 0x90, 0xa2, 0x28, - 0x93, 0x22, 0x95, 0xc4, 0x76, 0xa6, 0xea, 0x28, 0x71, 0xc6, 0x56, 0x3d, 0x6d, 0x14, 0x8d, 0x08, 0x82, 0x4b, 0x12, - 0x35, 0x08, 0x60, 0x00, 0x50, 0xa2, 0x42, 0xa3, 0xcf, 0xd2, 0x67, 0xe9, 0x93, 0x7d, 0x73, 0xce, 0x5e, 0xb0, 0xb8, - 0x91, 0x54, 0xec, 0xb4, 0xdf, 0xa4, 0xaa, 0x89, 0xc5, 0xee, 0x62, 0xf7, 0xec, 0xee, 0xd9, 0x73, 0x3f, 0xee, 0x82, - 0xc9, 0x5e, 0x0c, 0x8d, 0x1c, 0xf6, 0xb9, 0xcf, 0x9f, 0x89, 0x85, 0x5b, 0x12, 0x08, 0x3e, 0x2b, 0x8b, 0x16, 0x8b, - 0x80, 0x68, 0x2a, 0x4f, 0x1e, 0xa2, 0x1a, 0xe2, 0x33, 0xe7, 0x4f, 0x6c, 0x1e, 0xb1, 0x53, 0xcf, 0xdb, 0x8e, 0x16, - 0x9f, 0x31, 0x11, 0x21, 0xed, 0x28, 0xe5, 0x8a, 0xb2, 0xd9, 0x3b, 0x54, 0x6f, 0xb0, 0x75, 0x29, 0x8e, 0xae, 0x39, - 0x8b, 0xd6, 0xd3, 0x80, 0x98, 0xb8, 0xdd, 0xe1, 0x93, 0xdb, 0xe9, 0x7a, 0x3a, 0x85, 0x2c, 0x2d, 0x4f, 0x6c, 0x03, - 0xe2, 0xce, 0x44, 0x29, 0xf2, 0x83, 0xb9, 0x3e, 0x84, 0x49, 0x59, 0x59, 0x75, 0xf8, 0x60, 0x2b, 0x02, 0xa2, 0x1e, - 0xfa, 0x81, 0x0c, 0x78, 0xbf, 0x86, 0x53, 0x3b, 0x52, 0x3f, 0xc0, 0xee, 0x4b, 0xd5, 0x61, 0xd3, 0xd1, 0x1f, 0x5d, - 0xab, 0x1f, 0x10, 0xc6, 0x98, 0xbd, 0xf8, 0x35, 0xdd, 0xbd, 0xaa, 0xa1, 0x52, 0xa5, 0xf7, 0x1a, 0xf3, 0x18, 0x80, - 0xd0, 0xf7, 0x8d, 0xef, 0x2e, 0xc2, 0x28, 0xcd, 0x7c, 0x4f, 0xbd, 0x19, 0x5e, 0xf8, 0xda, 0xf5, 0x2a, 0xd3, 0xf4, - 0x1b, 0xc3, 0xcb, 0xe4, 0x14, 0x28, 0x1c, 0x61, 0x62, 0x06, 0x94, 0xb6, 0x4a, 0xf2, 0x09, 0xda, 0x59, 0x91, 0xa3, - 0x66, 0xac, 0xe4, 0x65, 0x23, 0xa8, 0x57, 0xc9, 0xa7, 0x82, 0x89, 0xa1, 0x54, 0x6c, 0xa9, 0x0f, 0x29, 0xa7, 0xf2, - 0x7a, 0xbd, 0xc5, 0xab, 0x3c, 0x2b, 0x6e, 0x4b, 0x8c, 0x01, 0xcc, 0x1d, 0x67, 0xe8, 0xf3, 0x13, 0xd9, 0xe8, 0xb3, - 0x74, 0xef, 0x4e, 0xbe, 0x2b, 0xd3, 0x05, 0x70, 0x7f, 0x83, 0xc5, 0x45, 0x18, 0x65, 0x0a, 0x04, 0xb6, 0x81, 0x2f, - 0x4e, 0xaa, 0x46, 0x62, 0xac, 0x57, 0x4d, 0xcf, 0x19, 0x32, 0xf8, 0x1e, 0x2f, 0x3f, 0x8d, 0x85, 0x37, 0x2b, 0x45, - 0xb0, 0xa0, 0xcc, 0x42, 0x08, 0x0b, 0x98, 0x45, 0x97, 0xd1, 0x7d, 0x55, 0x0f, 0xf2, 0x7a, 0xb2, 0xff, 0xee, 0xd5, - 0x38, 0x99, 0xcc, 0xb3, 0xfa, 0x69, 0x2c, 0x31, 0x29, 0x27, 0x74, 0x2a, 0x67, 0x0a, 0x0d, 0x3f, 0x38, 0x0d, 0x93, - 0x81, 0x9d, 0x18, 0xde, 0x05, 0x80, 0x92, 0xd8, 0x35, 0x3d, 0xc9, 0x6f, 0x79, 0xea, 0x64, 0x9e, 0xb8, 0x58, 0xba, - 0x9c, 0x01, 0xbb, 0x86, 0xf1, 0x3a, 0xc3, 0x50, 0xbb, 0x30, 0x00, 0x92, 0xab, 0x0a, 0x86, 0xee, 0x04, 0x2c, 0x5d, - 0x90, 0x89, 0xb9, 0xaa, 0xf8, 0xb3, 0x7a, 0x19, 0x23, 0x7a, 0x01, 0x79, 0x21, 0x7e, 0x47, 0x41, 0x15, 0x3c, 0x26, - 0x6c, 0x1a, 0x9e, 0x51, 0xc4, 0xa9, 0xd7, 0x3c, 0x54, 0xe8, 0x34, 0x60, 0x06, 0x8f, 0xf6, 0x33, 0xd4, 0x82, 0xc6, - 0xc9, 0x42, 0xf8, 0xcd, 0xd2, 0x34, 0x27, 0xcf, 0xb6, 0x61, 0x7e, 0xfe, 0x6c, 0x9b, 0xe6, 0xa3, 0x67, 0x5b, 0x17, - 0x28, 0xb9, 0x5c, 0x85, 0x89, 0x16, 0x8e, 0x3a, 0xc5, 0xf4, 0x60, 0x53, 0xd1, 0x72, 0x05, 0x35, 0xf5, 0x23, 0xa6, - 0x8f, 0x8f, 0x13, 0x7f, 0xe5, 0x26, 0x0f, 0x54, 0x7d, 0x6f, 0xc8, 0x3a, 0x7e, 0x5d, 0x55, 0x28, 0x5e, 0xa7, 0xf3, - 0xa5, 0x28, 0x5e, 0x55, 0xbe, 0x15, 0x65, 0x84, 0x4d, 0x4e, 0xe8, 0x30, 0xe1, 0x5b, 0xb7, 0xea, 0x4b, 0x62, 0xcd, - 0x48, 0xe6, 0xfa, 0x01, 0x6d, 0x32, 0xe4, 0xc9, 0xe9, 0x6b, 0xb3, 0x49, 0xcb, 0xb3, 0x09, 0xcb, 0xdb, 0x05, 0x27, - 0x43, 0x31, 0x3e, 0x1d, 0x37, 0xce, 0x0c, 0x93, 0x56, 0x35, 0x2f, 0x20, 0x7d, 0xf7, 0x5f, 0x85, 0x3e, 0x01, 0xe8, - 0x87, 0x00, 0x7d, 0x12, 0x7a, 0xd1, 0x8c, 0xfc, 0xed, 0xfd, 0x85, 0xc8, 0x92, 0x05, 0x02, 0x9f, 0x09, 0xdb, 0x87, - 0x29, 0x92, 0x0b, 0x09, 0x92, 0x0a, 0x34, 0x9f, 0x95, 0x22, 0x76, 0x4c, 0x92, 0xab, 0xca, 0x39, 0x1d, 0x3b, 0x99, - 0xd1, 0x51, 0x8f, 0x22, 0x6c, 0x95, 0xe4, 0x67, 0x47, 0xb4, 0x36, 0xbd, 0xdc, 0x68, 0x25, 0x00, 0x43, 0x02, 0x33, - 0x2c, 0xa0, 0x00, 0x09, 0x3d, 0x47, 0x4e, 0xc1, 0x3f, 0x58, 0x2b, 0x14, 0xab, 0x3b, 0xe7, 0x65, 0xca, 0x04, 0x5b, - 0xa9, 0xe3, 0x33, 0x4c, 0xd1, 0x05, 0xd7, 0x33, 0x04, 0xf5, 0x38, 0x3b, 0xa2, 0x8f, 0x4a, 0xe5, 0x00, 0x14, 0x9d, - 0x70, 0x4e, 0x6e, 0xc0, 0x3a, 0x78, 0xd4, 0xc9, 0x80, 0x8c, 0xf0, 0x50, 0xea, 0xe6, 0xaa, 0xb2, 0x62, 0x94, 0x10, - 0x8b, 0x1e, 0x04, 0xa1, 0x05, 0x6c, 0x38, 0xaa, 0xaa, 0xb2, 0x72, 0x37, 0x38, 0x73, 0xfe, 0xc6, 0xdd, 0x68, 0x0e, - 0x7b, 0x55, 0x1c, 0xad, 0xb4, 0x7c, 0xb4, 0x3c, 0xb6, 0xb8, 0xe0, 0x37, 0x20, 0x18, 0xe9, 0x25, 0xea, 0x63, 0x1b, - 0x16, 0x77, 0xc9, 0x17, 0x77, 0xd6, 0xb2, 0xb8, 0xb3, 0x1d, 0x8b, 0x1b, 0xb0, 0x85, 0x54, 0x04, 0xe8, 0x12, 0xf4, - 0x05, 0x13, 0xc0, 0x63, 0x74, 0xc5, 0x80, 0x9d, 0x33, 0x84, 0x93, 0x99, 0x06, 0x60, 0x0b, 0xd5, 0x02, 0xab, 0x26, - 0xb8, 0x48, 0x80, 0xa8, 0x4f, 0x5c, 0x9c, 0x3a, 0x3e, 0x6f, 0x48, 0xb9, 0xa9, 0x05, 0xd5, 0xf9, 0xc2, 0x2e, 0xa5, - 0xe9, 0xc4, 0xb5, 0x65, 0xcb, 0x4c, 0x97, 0x3b, 0x66, 0xea, 0x95, 0x8e, 0x2e, 0x9b, 0x36, 0x3d, 0x84, 0xf2, 0xa4, - 0x60, 0x0f, 0x82, 0x7d, 0x28, 0x6e, 0x99, 0xf2, 0x3e, 0x6c, 0x47, 0xa9, 0xd2, 0x8e, 0x8a, 0xdd, 0x34, 0xbd, 0x8f, - 0x12, 0x50, 0xb0, 0x40, 0x37, 0x8f, 0xdb, 0x52, 0x2b, 0x3f, 0x64, 0xb1, 0x5b, 0x5a, 0x37, 0x53, 0xf1, 0x5e, 0xde, - 0x52, 0x9d, 0x5e, 0x8f, 0xd6, 0x88, 0xdd, 0x2c, 0x23, 0x09, 0x02, 0xdd, 0x85, 0x20, 0xdf, 0xff, 0x4f, 0xb6, 0x59, - 0x03, 0x0e, 0x09, 0xf4, 0x02, 0xab, 0x23, 0x86, 0x8e, 0x81, 0x94, 0x4a, 0xf8, 0xbd, 0x2b, 0xc5, 0x81, 0x4b, 0x04, - 0xe0, 0x7f, 0xc2, 0xe3, 0xaa, 0x25, 0x92, 0xa7, 0x92, 0x73, 0xa2, 0x5b, 0xb1, 0x3b, 0xfb, 0x00, 0x7a, 0x3c, 0xad, - 0x63, 0x80, 0x4d, 0xae, 0x1c, 0xf5, 0x2d, 0xa1, 0xb4, 0x9d, 0x57, 0x20, 0x49, 0xc4, 0x92, 0xcc, 0xe2, 0x09, 0x9c, - 0x25, 0x5d, 0x73, 0x7e, 0xb3, 0xed, 0xe4, 0x47, 0x0b, 0x5f, 0xaf, 0x61, 0x4d, 0x40, 0x6d, 0xc1, 0x68, 0x2c, 0x58, - 0xac, 0xc0, 0x70, 0x4e, 0x74, 0x10, 0xf4, 0x5e, 0x43, 0xfa, 0x52, 0x9b, 0xf3, 0xaf, 0x93, 0x04, 0x2e, 0xa9, 0x6b, - 0xfb, 0x26, 0x7f, 0xbe, 0xc0, 0x5f, 0xce, 0x4d, 0xfe, 0x7c, 0x8a, 0xbf, 0x3a, 0x37, 0x98, 0xa8, 0xae, 0x81, 0x6f, - 0x97, 0xe6, 0xac, 0x8e, 0x4b, 0xfb, 0x89, 0x9a, 0x9b, 0x3d, 0x62, 0xdb, 0xb0, 0x05, 0x7e, 0xfa, 0x6c, 0x9b, 0x82, - 0x83, 0xa5, 0x3c, 0x87, 0xd0, 0x4a, 0xf4, 0xbc, 0xb1, 0x7c, 0xd1, 0x52, 0x3e, 0xd5, 0xff, 0xcb, 0xf7, 0x3c, 0xee, - 0x92, 0xa8, 0xb8, 0x53, 0xca, 0x52, 0x87, 0xdb, 0xa9, 0x1f, 0xba, 0xc9, 0xc3, 0x2d, 0xe5, 0x26, 0x34, 0x4e, 0xaa, - 0x0b, 0x69, 0x0a, 0xa5, 0x26, 0xcb, 0xda, 0xad, 0x4c, 0x92, 0xe7, 0x3e, 0xb0, 0x8b, 0x7e, 0xf4, 0xf7, 0x44, 0xa2, - 0xd2, 0x4a, 0xfc, 0x26, 0x5b, 0x90, 0xd2, 0x87, 0x6e, 0x9f, 0x6d, 0x35, 0x52, 0xef, 0xa6, 0x32, 0xdb, 0x0a, 0x19, - 0x08, 0xcb, 0x83, 0xbc, 0xeb, 0x6a, 0xe6, 0x0f, 0x50, 0x7d, 0x35, 0x8d, 0x36, 0xe6, 0xb3, 0x6d, 0x76, 0xae, 0xae, - 0xdc, 0xe4, 0x13, 0x99, 0x99, 0x9e, 0x9f, 0x78, 0x01, 0x51, 0x07, 0xea, 0x34, 0x70, 0xc3, 0x4f, 0xec, 0xd1, 0x8c, - 0xd6, 0x19, 0x2a, 0xa4, 0xf7, 0xb2, 0xba, 0x1c, 0x26, 0x54, 0x42, 0x87, 0xb4, 0x69, 0x03, 0x14, 0x94, 0xd7, 0x42, - 0xbe, 0x55, 0xd0, 0x85, 0x45, 0x2d, 0x03, 0xec, 0x29, 0x41, 0x47, 0x0e, 0x0e, 0xaa, 0x86, 0x8a, 0xeb, 0xa5, 0x1a, - 0xf2, 0x54, 0xa9, 0x6c, 0x52, 0x64, 0x58, 0xbc, 0xc5, 0x1e, 0x7e, 0xff, 0xe7, 0x68, 0xee, 0xeb, 0xc3, 0x3f, 0xc7, - 0x68, 0xbc, 0xf6, 0x0f, 0xca, 0x8d, 0xdd, 0x34, 0x5d, 0xaf, 0xc8, 0x8c, 0xea, 0xe2, 0xce, 0x8b, 0xa1, 0x94, 0x69, - 0x79, 0x79, 0x38, 0xbf, 0xae, 0x3b, 0xfd, 0xe3, 0xd7, 0x60, 0x23, 0x00, 0x34, 0x5d, 0x34, 0x9f, 0xab, 0x05, 0x57, - 0xbd, 0xa7, 0x99, 0x73, 0xfc, 0xeb, 0xfa, 0x87, 0xb7, 0xf6, 0x0f, 0xa2, 0x71, 0xa8, 0xea, 0xf9, 0x84, 0x2b, 0x3c, - 0x19, 0x69, 0x2a, 0x8d, 0x97, 0xcf, 0x68, 0xee, 0x86, 0xed, 0xd3, 0xb9, 0x2e, 0xed, 0xb2, 0x98, 0x90, 0x19, 0xd8, - 0xc2, 0x1a, 0xb5, 0xd2, 0xdb, 0x80, 0xdc, 0x11, 0xa1, 0x4c, 0xad, 0x7f, 0xac, 0xa1, 0x05, 0x46, 0x7b, 0x63, 0x4a, - 0x5a, 0x46, 0x58, 0x49, 0x53, 0x9a, 0xe0, 0x1c, 0xd8, 0xcc, 0xe5, 0x5d, 0x5e, 0xd9, 0xd5, 0x13, 0x43, 0x95, 0x06, - 0xd0, 0x3a, 0xb2, 0xf3, 0x96, 0xf2, 0x01, 0xa6, 0x7a, 0x6e, 0x1e, 0x9b, 0xe1, 0xe8, 0x03, 0x88, 0x8e, 0xcd, 0xe0, - 0x14, 0xc0, 0xe6, 0xd7, 0x0a, 0x01, 0x44, 0x1b, 0xc4, 0x9a, 0xc4, 0x52, 0x2a, 0x95, 0x77, 0x70, 0xfb, 0x42, 0x34, - 0xb4, 0xe5, 0x92, 0x9f, 0xc6, 0xb5, 0x51, 0xca, 0x33, 0x9f, 0x62, 0x0a, 0xd5, 0x90, 0xa4, 0x69, 0x2b, 0xc0, 0xc4, - 0xa2, 0x1b, 0x6a, 0x51, 0xbb, 0x0c, 0x8f, 0xa2, 0xdc, 0xb0, 0x0d, 0xb8, 0x95, 0x71, 0x82, 0xd5, 0x6f, 0x21, 0x86, - 0xbf, 0x5d, 0x31, 0x0b, 0x91, 0x64, 0x31, 0x55, 0x99, 0xf6, 0xbe, 0xed, 0xfd, 0xbd, 0xca, 0x06, 0x55, 0xba, 0x29, - 0x1b, 0x87, 0xa6, 0x95, 0xb0, 0x5f, 0x4d, 0x40, 0x83, 0x1d, 0xf0, 0x31, 0x55, 0x50, 0x1c, 0x99, 0xcf, 0x89, 0x97, - 0xa5, 0x3a, 0x17, 0xd7, 0x88, 0x78, 0xad, 0xe0, 0xa7, 0xf3, 0x64, 0xa4, 0xfe, 0x04, 0x5e, 0xeb, 0x3c, 0xac, 0x11, - 0x1b, 0x10, 0x67, 0x5b, 0x9a, 0xc1, 0x44, 0x7b, 0x2c, 0x83, 0x88, 0x7d, 0x05, 0xd2, 0x71, 0x37, 0x94, 0xe3, 0xd0, - 0xd8, 0x15, 0x50, 0xec, 0x8b, 0x48, 0xd8, 0x91, 0xec, 0x46, 0x40, 0xbb, 0x8e, 0xef, 0xd6, 0xf9, 0xa1, 0xe7, 0xd8, - 0xb9, 0x6a, 0x80, 0xb7, 0xd4, 0xa7, 0x43, 0x0f, 0x3d, 0xb6, 0xea, 0x42, 0xab, 0x75, 0xf8, 0x98, 0x76, 0x1d, 0xe7, - 0x95, 0xa3, 0x1a, 0xd4, 0x48, 0x4d, 0xc2, 0x6d, 0x5e, 0x74, 0x47, 0x92, 0x2f, 0x9e, 0x4a, 0xb9, 0xf3, 0xc3, 0xc6, - 0x73, 0xe2, 0xd8, 0x80, 0x84, 0xb3, 0x28, 0x7e, 0xc4, 0x14, 0xba, 0xaa, 0xa1, 0x7a, 0x41, 0x94, 0x12, 0x79, 0x0e, - 0x54, 0xec, 0xf0, 0x85, 0x93, 0xf8, 0xf9, 0xfd, 0xdb, 0x0f, 0x1f, 0x54, 0x03, 0x73, 0x6f, 0xa6, 0x72, 0xef, 0x6c, - 0x43, 0xed, 0xc1, 0xfe, 0x8d, 0xfb, 0x8e, 0xde, 0x30, 0x94, 0xaf, 0x2c, 0xef, 0x39, 0x5a, 0x56, 0xdb, 0x72, 0xec, - 0xe6, 0x61, 0x5f, 0xa6, 0xcc, 0xe0, 0x41, 0xf3, 0x6a, 0xc0, 0x0d, 0xbb, 0xaf, 0xb7, 0x52, 0xc9, 0xca, 0x0f, 0x6f, - 0x1b, 0x4a, 0xdd, 0x4d, 0x43, 0x29, 0x70, 0x53, 0x35, 0x5c, 0xb5, 0x8e, 0x56, 0xd2, 0xed, 0x0c, 0xa9, 0x93, 0xf7, - 0x81, 0x4b, 0x62, 0x69, 0xbe, 0x60, 0xd0, 0x2c, 0x76, 0x7a, 0x75, 0xd4, 0x0d, 0xc5, 0x8c, 0x0f, 0x11, 0xb0, 0xf5, - 0x02, 0x30, 0xb1, 0x23, 0xb2, 0x1e, 0xac, 0x4c, 0xb9, 0x09, 0x03, 0x59, 0xa9, 0x13, 0x4a, 0x61, 0xde, 0x66, 0x64, - 0x15, 0x93, 0xc4, 0xcd, 0xd6, 0x09, 0xb9, 0x0d, 0xa2, 0xfb, 0x27, 0x85, 0x01, 0xfb, 0x9e, 0xca, 0x4b, 0x7f, 0xb1, - 0x14, 0xb5, 0xcf, 0x35, 0x32, 0x12, 0x0b, 0xb8, 0xf3, 0x03, 0xf9, 0x7f, 0xfe, 0x6d, 0x59, 0xff, 0xf9, 0xf7, 0xde, - 0xaa, 0xd0, 0x7d, 0x3e, 0x31, 0xb2, 0xd1, 0x01, 0xfb, 0xa2, 0xf9, 0x4b, 0x65, 0x98, 0x37, 0xd7, 0xa9, 0x2d, 0x02, - 0xbc, 0xaf, 0x2d, 0x41, 0xad, 0xb0, 0xbc, 0x6f, 0x1e, 0x35, 0x30, 0x98, 0xd7, 0xde, 0x91, 0x41, 0xa5, 0x2f, 0x1a, - 0xda, 0x44, 0x1f, 0x1c, 0xb4, 0x22, 0xbf, 0x1f, 0xc2, 0xfb, 0xe6, 0xf0, 0x85, 0xc3, 0x67, 0xa2, 0xc1, 0xd7, 0x93, - 0x89, 0xc8, 0xe6, 0x26, 0x37, 0x05, 0xa3, 0xfa, 0xf3, 0x5a, 0x09, 0xbb, 0x3c, 0x07, 0xb6, 0x4e, 0xbd, 0xdd, 0x47, - 0xaf, 0x27, 0x68, 0xfe, 0x75, 0x36, 0x4d, 0x0a, 0x62, 0xa5, 0x15, 0xb5, 0x51, 0xf3, 0xed, 0x5a, 0xa7, 0x35, 0xbc, - 0x06, 0xa5, 0x98, 0xe2, 0x2b, 0x9f, 0xe8, 0xc6, 0xeb, 0x09, 0x93, 0xed, 0x30, 0x8b, 0xd3, 0x41, 0x75, 0x6b, 0x33, - 0xc9, 0x68, 0x09, 0xe8, 0x86, 0x42, 0x35, 0x2e, 0x58, 0x99, 0x14, 0xa2, 0x34, 0x14, 0xa9, 0x03, 0x53, 0x3f, 0xc9, - 0x31, 0xc3, 0xc8, 0xbb, 0x36, 0xab, 0xac, 0x9f, 0xf7, 0x5b, 0x65, 0x5d, 0x1d, 0x64, 0x95, 0xf5, 0xf3, 0x57, 0xb7, - 0xca, 0x7a, 0x27, 0x5b, 0x65, 0xc1, 0x22, 0xbe, 0x25, 0x07, 0x99, 0x4a, 0x71, 0x3b, 0x89, 0xe8, 0x3e, 0x1d, 0x39, - 0x8c, 0xa4, 0x4d, 0xbd, 0x25, 0x01, 0x36, 0x9d, 0xad, 0x4a, 0x10, 0x2d, 0xc0, 0x6c, 0xea, 0x8f, 0x37, 0x70, 0x0a, - 0xa2, 0x85, 0x6c, 0xde, 0x14, 0xb2, 0x18, 0xab, 0x45, 0xdc, 0x24, 0x6a, 0x52, 0x64, 0x1b, 0x3c, 0xca, 0x92, 0x79, - 0xac, 0x4b, 0x79, 0xa4, 0x85, 0xbd, 0x58, 0x87, 0x1b, 0x1d, 0x0d, 0xd0, 0x5e, 0x49, 0x34, 0xec, 0xbc, 0xe4, 0xd1, - 0x24, 0xe4, 0x1e, 0x84, 0x5d, 0x2e, 0x8d, 0xcc, 0xb0, 0x55, 0x7f, 0xdd, 0x38, 0xdf, 0x5f, 0x3b, 0xc3, 0xae, 0x03, - 0xee, 0xd0, 0xc0, 0xe4, 0x61, 0x81, 0x3d, 0xec, 0x76, 0xa1, 0xe0, 0x5e, 0x2a, 0xe8, 0x40, 0x81, 0x2f, 0x15, 0xf4, - 0xa0, 0xc0, 0x93, 0x0a, 0x4e, 0xa0, 0x60, 0x26, 0x15, 0xf4, 0xa1, 0xe0, 0x4e, 0xcd, 0xaf, 0x43, 0x31, 0xdc, 0xbe, - 0x7e, 0x63, 0x50, 0xa6, 0x82, 0x97, 0xf5, 0x0d, 0x07, 0xec, 0x94, 0xdc, 0xc5, 0x20, 0x32, 0xa8, 0x80, 0x6f, 0x90, - 0x18, 0xf7, 0x4b, 0x42, 0x43, 0x33, 0xbf, 0xc1, 0x3b, 0xc7, 0xca, 0x22, 0xb0, 0x54, 0xe6, 0x21, 0x0f, 0x38, 0x1c, - 0x14, 0x55, 0x07, 0x99, 0xcd, 0x50, 0xac, 0x1c, 0x0f, 0x1b, 0x21, 0xad, 0x65, 0xf1, 0x8e, 0x7e, 0xce, 0x14, 0x5b, - 0xa0, 0xb0, 0xf1, 0xd0, 0x64, 0xc1, 0xe0, 0xd7, 0xd0, 0xf4, 0xbf, 0x21, 0xd3, 0xf5, 0x42, 0xb9, 0x8c, 0x16, 0x7b, - 0x95, 0xf6, 0xf2, 0x2b, 0x18, 0xa5, 0x4a, 0x35, 0x20, 0x26, 0xdf, 0x96, 0xec, 0x5b, 0xf4, 0x31, 0x2f, 0xd7, 0xcf, - 0x60, 0x6c, 0x4a, 0x46, 0x4d, 0x46, 0xe0, 0x3b, 0x00, 0x23, 0x49, 0x6b, 0x7e, 0x09, 0x70, 0x96, 0x9e, 0xaf, 0x5c, - 0x69, 0x3c, 0xe3, 0x1f, 0x49, 0x9a, 0xba, 0x0b, 0x5e, 0xbf, 0x3e, 0x4e, 0x30, 0x93, 0x11, 0xfc, 0x17, 0x02, 0x10, - 0x84, 0x69, 0x7e, 0xcd, 0x1a, 0x22, 0x89, 0xee, 0x15, 0xb0, 0xb7, 0x81, 0x0d, 0x55, 0x58, 0x06, 0xf8, 0x16, 0x2c, - 0x61, 0x59, 0x87, 0x0f, 0x87, 0xff, 0x8e, 0x04, 0xd5, 0xc2, 0xcc, 0x5d, 0x54, 0x8b, 0xe8, 0x3e, 0xc8, 0xe5, 0xb1, - 0x09, 0x15, 0x7a, 0xa9, 0xf0, 0x4b, 0x74, 0xc2, 0x41, 0xb4, 0xf8, 0x43, 0x15, 0xc2, 0x3b, 0x14, 0xf9, 0x1f, 0x42, - 0xc3, 0xcf, 0x26, 0x16, 0xc2, 0x58, 0xb1, 0x00, 0x84, 0x83, 0x30, 0x5b, 0x9a, 0xe8, 0xcc, 0xa5, 0x75, 0x42, 0xdd, - 0xb0, 0x70, 0x6d, 0xb7, 0x55, 0x17, 0xd6, 0x41, 0xb2, 0x98, 0xba, 0x9a, 0xd3, 0xe9, 0x1b, 0xfc, 0xcf, 0xb2, 0x7b, - 0x7a, 0x8e, 0x3d, 0x28, 0x33, 0xff, 0x6e, 0x3b, 0x8f, 0xc2, 0xcc, 0x9c, 0xbb, 0x2b, 0x3f, 0x78, 0x18, 0xac, 0xa2, - 0x30, 0x4a, 0x63, 0xd7, 0x23, 0xc3, 0x82, 0xa1, 0x1e, 0x62, 0x70, 0x04, 0xe6, 0x9f, 0xe7, 0x58, 0x9d, 0x84, 0xac, - 0x68, 0x6b, 0x11, 0xfb, 0x60, 0x1e, 0x90, 0x4d, 0xce, 0x3e, 0x5f, 0xaa, 0x4c, 0xab, 0xe2, 0x96, 0xa3, 0x2d, 0x80, - 0x22, 0x65, 0x81, 0x15, 0x20, 0x9c, 0xd0, 0x30, 0x76, 0x67, 0x18, 0x0b, 0xd0, 0xea, 0xf4, 0x12, 0xb2, 0x52, 0xac, - 0x5e, 0x6b, 0xe7, 0x49, 0x74, 0x3f, 0x86, 0xd1, 0x62, 0x63, 0x33, 0x25, 0xc1, 0x1c, 0xdf, 0x98, 0xe8, 0xcb, 0xc1, - 0xfb, 0x31, 0x91, 0x11, 0x87, 0xde, 0xc8, 0x6a, 0x08, 0xaf, 0x07, 0x1d, 0xc5, 0x1e, 0xae, 0xfc, 0xd0, 0xa4, 0xd3, - 0xe9, 0xdb, 0xb1, 0xd4, 0x97, 0x0c, 0x3f, 0x7d, 0x8b, 0xd5, 0x1d, 0xc5, 0x1e, 0x02, 0xb3, 0x36, 0x0f, 0xa2, 0xfb, - 0xc1, 0xd2, 0x9f, 0xcd, 0x48, 0x38, 0xc4, 0x31, 0x8b, 0x42, 0x12, 0x04, 0x7e, 0x9c, 0xfa, 0xe9, 0x70, 0xe5, 0x6e, - 0x58, 0xaf, 0xc7, 0x6d, 0xbd, 0x76, 0x59, 0xaf, 0xdd, 0x83, 0x7b, 0x95, 0xba, 0x01, 0xbf, 0x11, 0xda, 0x0f, 0x1b, - 0x5a, 0x4f, 0xb1, 0x2b, 0xf3, 0x3c, 0xb8, 0xd7, 0x38, 0x21, 0xdb, 0x95, 0x9b, 0x2c, 0xfc, 0x70, 0x60, 0xe7, 0xd6, - 0xdd, 0x96, 0x6e, 0x8c, 0xa7, 0xa7, 0xa7, 0xa7, 0xb9, 0x35, 0xe3, 0x4f, 0xf6, 0x6c, 0x96, 0x5b, 0x1e, 0x7f, 0x9a, - 0xcf, 0x6d, 0x7b, 0x3e, 0xcf, 0x2d, 0x9f, 0x17, 0x74, 0x3b, 0xde, 0xac, 0xdb, 0xc9, 0xad, 0x7b, 0xa9, 0x46, 0x6e, - 0x11, 0xf6, 0x94, 0x90, 0xd9, 0x10, 0x37, 0x12, 0x35, 0xe4, 0x1c, 0xf4, 0x6d, 0x3b, 0x47, 0x0c, 0x70, 0x5d, 0xc2, - 0x4d, 0x28, 0xeb, 0xb9, 0xd9, 0x1e, 0x5c, 0x53, 0x29, 0x3e, 0xe7, 0x79, 0x8d, 0xf5, 0x66, 0x6e, 0xf2, 0xe9, 0x46, - 0x91, 0x66, 0xe1, 0xba, 0xb4, 0xda, 0x96, 0x83, 0xc1, 0xdc, 0x0c, 0x20, 0x48, 0xd6, 0x70, 0x1a, 0x25, 0x70, 0x66, - 0x13, 0x77, 0xe6, 0xaf, 0xd3, 0x81, 0xd3, 0x89, 0x37, 0xbc, 0x88, 0xed, 0xf5, 0xa2, 0x00, 0xcf, 0xde, 0x20, 0x8d, - 0x02, 0x7f, 0xc6, 0x8b, 0xda, 0xce, 0x92, 0xd3, 0xd1, 0x87, 0xe8, 0x22, 0xee, 0x63, 0xa0, 0x03, 0x37, 0x08, 0x14, - 0xab, 0x9b, 0x2a, 0xc4, 0x4d, 0x51, 0xc4, 0xab, 0xd8, 0x29, 0x85, 0x0b, 0xba, 0x83, 0x3b, 0xc7, 0xf1, 0x46, 0xec, - 0x79, 0xe7, 0x24, 0xde, 0xe4, 0xdf, 0xae, 0xc8, 0xcc, 0x77, 0x15, 0xad, 0xd8, 0x4d, 0x8e, 0x0d, 0x62, 0x60, 0x7d, - 0xdb, 0xb2, 0x4d, 0xf9, 0xb1, 0x80, 0x60, 0x82, 0x4f, 0xfc, 0x55, 0x1c, 0x25, 0x99, 0x1b, 0x66, 0x79, 0x3e, 0xb9, - 0xc9, 0xf3, 0xe1, 0x95, 0xaf, 0x5d, 0xff, 0x43, 0xa3, 0xf7, 0x34, 0x55, 0x9b, 0xe4, 0xfa, 0x8d, 0xf1, 0x96, 0xc8, - 0x56, 0x1a, 0x70, 0x8d, 0xa1, 0x85, 0x86, 0x5c, 0x99, 0xde, 0x92, 0xf5, 0xca, 0x14, 0xc8, 0xa2, 0x3a, 0xb5, 0xfa, - 0x28, 0x57, 0xc1, 0x1b, 0x08, 0x2a, 0xbc, 0x25, 0xa3, 0x2b, 0xc9, 0xe2, 0x03, 0x88, 0x15, 0xac, 0x4c, 0x2d, 0xf9, - 0x9f, 0xb5, 0xd1, 0x8c, 0xdf, 0xed, 0xa7, 0x19, 0x7f, 0xc9, 0x0e, 0xa1, 0x19, 0xbf, 0xfb, 0xea, 0x34, 0xe3, 0xb3, - 0xba, 0x25, 0xff, 0x45, 0x34, 0x52, 0x85, 0x90, 0x1f, 0xae, 0xa6, 0x84, 0xc6, 0xc8, 0xb9, 0xf8, 0xdd, 0x86, 0xf7, - 0xbc, 0x37, 0x9a, 0xf5, 0x8d, 0xde, 0xdc, 0x20, 0x8f, 0x7d, 0x17, 0x8e, 0xfe, 0x9e, 0xc8, 0xcf, 0xf3, 0xf9, 0xe8, - 0x4d, 0x24, 0x15, 0x88, 0x27, 0x66, 0xff, 0x50, 0x8a, 0x67, 0x40, 0xdf, 0x70, 0xbb, 0x47, 0xcc, 0xf8, 0x00, 0xee, - 0xd0, 0xd4, 0xce, 0x77, 0x26, 0xec, 0xbd, 0x86, 0xe5, 0x21, 0x68, 0xc2, 0xc8, 0x92, 0x3b, 0xbd, 0xd4, 0x44, 0x89, - 0x0b, 0x92, 0x31, 0x2f, 0xd5, 0xef, 0x1f, 0x2e, 0x66, 0xda, 0x45, 0xa4, 0xe7, 0x7e, 0xfa, 0xae, 0xea, 0x72, 0xc2, - 0xd4, 0x2f, 0x23, 0x79, 0x3a, 0x39, 0xb3, 0xd9, 0x92, 0x53, 0x3a, 0xc3, 0x6b, 0xda, 0xfc, 0xbc, 0x34, 0xd3, 0x81, - 0xdc, 0x90, 0xa5, 0x96, 0xaa, 0x5d, 0xc6, 0xcc, 0xde, 0x7f, 0xcb, 0x28, 0x40, 0xcc, 0x96, 0x85, 0x9e, 0xba, 0x33, - 0xda, 0xdc, 0x9f, 0xe5, 0xb9, 0x3e, 0xe4, 0x80, 0x90, 0x2e, 0x5a, 0xb2, 0x8f, 0x88, 0x4b, 0xef, 0x85, 0x59, 0x01, - 0x53, 0xd2, 0x51, 0x0d, 0xdc, 0x05, 0xe8, 0xb4, 0x99, 0xbe, 0x8e, 0xc1, 0x4c, 0x55, 0x28, 0xf8, 0xa8, 0xad, 0x83, - 0x34, 0x21, 0x50, 0xc2, 0x0a, 0xf8, 0xf3, 0x57, 0xbc, 0xa0, 0x6e, 0x35, 0x49, 0x81, 0x83, 0x4a, 0x79, 0xf0, 0xab, - 0xe7, 0x72, 0x6d, 0x8a, 0x76, 0x58, 0x1d, 0x7c, 0xc8, 0x55, 0x41, 0xfb, 0xe1, 0xf6, 0x1b, 0x9f, 0x1d, 0x41, 0x83, - 0x71, 0x45, 0x77, 0xbf, 0xc7, 0x26, 0x10, 0x48, 0x89, 0xf4, 0xde, 0xb0, 0xd2, 0x7b, 0xe5, 0xc5, 0x96, 0xc7, 0xa4, - 0xc8, 0xdc, 0xd8, 0x04, 0x16, 0x1f, 0x71, 0x2f, 0xc3, 0x78, 0x52, 0xf8, 0x8b, 0xe1, 0x3a, 0x05, 0xdc, 0x88, 0x8c, - 0x2a, 0xe2, 0x9f, 0xa1, 0xb7, 0x4e, 0xd2, 0x28, 0x19, 0xc4, 0x91, 0x1f, 0x66, 0x24, 0xc9, 0x11, 0x54, 0xd7, 0x08, - 0x1f, 0x0e, 0x9e, 0x9b, 0x6d, 0x14, 0xbb, 0x9e, 0x9f, 0x3d, 0x0c, 0x6c, 0x46, 0x52, 0xd8, 0x43, 0x46, 0x1d, 0xd8, - 0x8d, 0xf5, 0x07, 0x0c, 0x9a, 0x2f, 0x91, 0xf0, 0x4b, 0xea, 0xe4, 0x8c, 0xbc, 0xcd, 0x87, 0xd2, 0x5b, 0x1a, 0x95, - 0x03, 0xc8, 0x0f, 0x37, 0x31, 0x17, 0x80, 0xe5, 0x61, 0xa9, 0xed, 0x19, 0x59, 0x18, 0x88, 0xb5, 0x41, 0x2e, 0xcf, - 0xff, 0xac, 0x9e, 0xae, 0xd8, 0xcd, 0xc5, 0x40, 0xf1, 0xe8, 0x87, 0x8c, 0x6c, 0xe0, 0x42, 0x0e, 0x2b, 0xe3, 0x90, - 0x9a, 0x53, 0x32, 0x8f, 0x12, 0x42, 0x23, 0xb8, 0x3a, 0xa7, 0xf1, 0xe6, 0xf0, 0xee, 0x77, 0x4f, 0xbf, 0xb9, 0x9f, - 0x30, 0xca, 0x34, 0xde, 0x99, 0xbe, 0xa7, 0xb7, 0xfa, 0x7d, 0x06, 0xa4, 0x21, 0x85, 0xbc, 0x47, 0x83, 0x65, 0x0d, - 0x54, 0x75, 0xd8, 0x18, 0x28, 0x2b, 0x8e, 0xd8, 0x9d, 0x97, 0x90, 0xc0, 0xcd, 0xfc, 0x3b, 0x4e, 0x33, 0x76, 0x4f, - 0xe2, 0x0d, 0x5f, 0x63, 0xbc, 0xf0, 0x1e, 0xb1, 0x48, 0x95, 0xa1, 0xf0, 0x45, 0xaa, 0x16, 0xe3, 0x22, 0x0d, 0x6b, - 0xb3, 0xe1, 0xb1, 0x23, 0x2a, 0x37, 0x7d, 0x2f, 0xde, 0xc8, 0x57, 0x74, 0xd1, 0x4c, 0xdc, 0xd4, 0xd5, 0xa0, 0x5f, - 0x2b, 0x7f, 0x36, 0x0b, 0x48, 0x5e, 0x5a, 0xe8, 0xf2, 0x5a, 0x4a, 0xc0, 0x11, 0x70, 0x70, 0xa7, 0x69, 0x14, 0xac, - 0x33, 0xd2, 0x0c, 0x2e, 0x0a, 0x9c, 0x8e, 0x5d, 0x00, 0x07, 0x7f, 0x97, 0xc7, 0xda, 0x03, 0x72, 0x1b, 0xb6, 0x89, - 0x3d, 0x84, 0x18, 0xbf, 0x66, 0xb7, 0x3c, 0x74, 0x78, 0x25, 0x06, 0x6d, 0x34, 0x4c, 0xc4, 0x80, 0x6b, 0x89, 0x62, - 0x6f, 0xc5, 0x72, 0x58, 0x99, 0x88, 0x73, 0x2a, 0x8a, 0xf2, 0xf2, 0x64, 0xfe, 0x98, 0x33, 0xf6, 0xaa, 0xf9, 0x8c, - 0xbd, 0xe2, 0x67, 0x6c, 0xf7, 0xce, 0x7c, 0x3a, 0x77, 0xe0, 0xbf, 0x61, 0x31, 0xa1, 0x81, 0xad, 0x74, 0xe3, 0x8d, - 0xe2, 0xc4, 0x1b, 0xc5, 0xec, 0xc4, 0x1b, 0x05, 0xbb, 0x46, 0x93, 0x0c, 0xc3, 0xea, 0xe8, 0x86, 0xad, 0x40, 0x21, - 0xfc, 0xd9, 0xa5, 0x57, 0xce, 0x31, 0xbc, 0x83, 0x56, 0xbd, 0xfa, 0xbb, 0xce, 0xee, 0xa3, 0x4e, 0xcf, 0x12, 0x47, - 0xda, 0xba, 0x95, 0xb9, 0xd3, 0x29, 0x99, 0x0d, 0xe6, 0x91, 0xb7, 0x4e, 0xff, 0xc5, 0xc6, 0xcf, 0x80, 0xb8, 0x13, - 0x11, 0x54, 0xfa, 0xe1, 0x4d, 0x41, 0x51, 0x72, 0x47, 0x78, 0x0f, 0x5b, 0xb1, 0x4e, 0x03, 0x1a, 0x90, 0xb8, 0x63, - 0x1d, 0x37, 0x6c, 0xf2, 0x66, 0x40, 0xff, 0x61, 0xab, 0xd4, 0x8e, 0x62, 0xbe, 0x00, 0x2c, 0x3b, 0xc1, 0xf1, 0x78, - 0x68, 0xb0, 0xd5, 0xb4, 0x4f, 0x9b, 0x87, 0x7b, 0xcd, 0xbf, 0x74, 0xc3, 0x2f, 0x15, 0x76, 0x6f, 0x31, 0x57, 0x90, - 0xdd, 0xbd, 0xb6, 0xed, 0x91, 0x5a, 0xaf, 0x3b, 0x2e, 0x84, 0xa2, 0xee, 0x81, 0x58, 0xfe, 0xe9, 0xab, 0x63, 0xf8, - 0x8f, 0x52, 0xf5, 0xbf, 0x64, 0x4d, 0x84, 0xfa, 0x45, 0xd9, 0xf6, 0x9a, 0x92, 0x4a, 0x48, 0x88, 0x1f, 0x5e, 0x7f, - 0x3e, 0x7f, 0x5c, 0x83, 0x83, 0x6b, 0x53, 0x6b, 0xa6, 0x6a, 0xed, 0xef, 0xa3, 0x08, 0x92, 0x65, 0xd6, 0xab, 0x73, - 0xf0, 0x50, 0xf3, 0xf2, 0x6c, 0x04, 0x8d, 0x38, 0x1f, 0x41, 0xb5, 0xf8, 0x2a, 0xb6, 0xa1, 0xac, 0xc4, 0xdb, 0x36, - 0x56, 0xe2, 0xcd, 0x7e, 0x56, 0xe2, 0xaf, 0x07, 0xb1, 0x12, 0x6f, 0xbe, 0x3a, 0x2b, 0xf1, 0xb6, 0xce, 0x4a, 0x5c, - 0x45, 0xdc, 0x84, 0xd5, 0xb8, 0x58, 0xb3, 0x9f, 0x1f, 0xa9, 0x52, 0xee, 0x32, 0x1a, 0xf5, 0x6c, 0x1a, 0x64, 0xf8, - 0xea, 0x77, 0x33, 0x16, 0xb8, 0x11, 0xdf, 0xa3, 0x45, 0x57, 0xc1, 0x5a, 0x30, 0xcc, 0x8e, 0xdf, 0x91, 0x8a, 0x83, - 0x28, 0x5c, 0xfc, 0x0c, 0x4a, 0x59, 0x10, 0x07, 0x26, 0xd2, 0x0b, 0x3f, 0xfd, 0x39, 0x8a, 0xd7, 0xf1, 0x05, 0xf4, - 0xf5, 0xd1, 0x4f, 0xfd, 0x69, 0x40, 0x84, 0xef, 0x2f, 0xb5, 0x40, 0x63, 0x32, 0x71, 0x30, 0xfa, 0xe4, 0x3f, 0xdd, - 0x0d, 0xff, 0x89, 0x66, 0xa1, 0xec, 0x37, 0x35, 0x6d, 0x53, 0x9b, 0x19, 0x11, 0xae, 0x04, 0x94, 0x06, 0xfd, 0x78, - 0x66, 0xe4, 0x2a, 0xd2, 0x1b, 0x66, 0xc9, 0xed, 0x1d, 0x5a, 0xfb, 0x21, 0x35, 0xa6, 0x66, 0xad, 0x1b, 0x22, 0xe8, - 0x55, 0x5d, 0x0c, 0xbf, 0x8a, 0xd6, 0x29, 0x99, 0x45, 0xf7, 0xa1, 0x6a, 0x84, 0xc2, 0xac, 0x1f, 0x34, 0x9c, 0xa2, - 0x0d, 0xa6, 0x6b, 0xfc, 0x80, 0x84, 0x72, 0x94, 0x68, 0x2a, 0x64, 0x0b, 0x5d, 0xc7, 0x26, 0x55, 0x35, 0x9b, 0x38, - 0x45, 0x55, 0xe4, 0x15, 0x7a, 0xa2, 0x69, 0xd1, 0xe8, 0x71, 0x2d, 0xb9, 0xa9, 0x46, 0x64, 0x31, 0xa9, 0x70, 0xaa, - 0x85, 0x5c, 0xb8, 0xc8, 0x23, 0x4f, 0x34, 0x2c, 0x1c, 0x7b, 0x43, 0x9d, 0x45, 0x8b, 0xb7, 0x10, 0xb7, 0x23, 0x5f, - 0xb3, 0xf5, 0x60, 0x71, 0x18, 0xe8, 0xe3, 0x6b, 0x09, 0x8c, 0xef, 0xee, 0x48, 0x12, 0xb8, 0x0f, 0x9a, 0x9e, 0x47, - 0xe1, 0x8f, 0x00, 0x80, 0x37, 0xd1, 0x7d, 0x28, 0x57, 0xc0, 0xf4, 0x28, 0x0d, 0x7b, 0xa9, 0x31, 0x62, 0x08, 0xb8, - 0x8a, 0x48, 0x23, 0x80, 0xc4, 0xb4, 0x0b, 0xf2, 0x77, 0x83, 0xfe, 0xfb, 0x0f, 0x3d, 0x37, 0x2e, 0x23, 0xf1, 0xa1, - 0xbf, 0xc5, 0x07, 0x7c, 0xe6, 0xf9, 0xf3, 0x27, 0xed, 0xd3, 0x2e, 0x27, 0x44, 0x6f, 0x68, 0xad, 0xb7, 0x9e, 0x02, - 0x18, 0xc5, 0x55, 0xb4, 0xf6, 0x96, 0x68, 0x6b, 0xfa, 0xf5, 0xe6, 0x9b, 0x41, 0x9f, 0x98, 0x17, 0x54, 0x4c, 0xbd, - 0x52, 0x54, 0x40, 0x01, 0xbf, 0xff, 0x16, 0x42, 0x5e, 0xfe, 0x0f, 0xc1, 0x50, 0xdf, 0x35, 0x8c, 0x8b, 0xf7, 0x1f, - 0xb7, 0x79, 0x87, 0x90, 0xbe, 0x92, 0x05, 0x93, 0xe0, 0xca, 0xb5, 0x66, 0x24, 0x93, 0x57, 0x81, 0x26, 0x07, 0x6e, - 0x6b, 0x8b, 0x49, 0xc7, 0xbf, 0x42, 0x2c, 0xca, 0xa6, 0x33, 0x5b, 0x7f, 0x83, 0x30, 0x6c, 0x55, 0x41, 0x32, 0xcc, - 0xe4, 0x81, 0x20, 0xfa, 0xaa, 0xbe, 0x5b, 0xf9, 0xa1, 0x81, 0x71, 0xd7, 0xeb, 0x6f, 0xdc, 0x0d, 0x44, 0x1e, 0x06, - 0xe4, 0x56, 0x7d, 0x05, 0x85, 0x86, 0xec, 0xa9, 0x06, 0xc9, 0x95, 0xd4, 0x46, 0x48, 0x70, 0x2d, 0xde, 0xe4, 0x4f, - 0x8a, 0xa2, 0x28, 0x82, 0x8d, 0x50, 0x04, 0x1f, 0x81, 0xe5, 0xc8, 0x0e, 0x80, 0xb6, 0x24, 0x8f, 0x37, 0xb4, 0x04, - 0x38, 0x03, 0xd4, 0xc9, 0xf2, 0x02, 0x16, 0x5c, 0xaf, 0x67, 0xf3, 0x02, 0xce, 0xd0, 0x43, 0x60, 0x34, 0x37, 0x81, - 0x18, 0xbc, 0x03, 0x05, 0x19, 0x76, 0x7c, 0xcb, 0x24, 0xc1, 0x8a, 0x4d, 0x1f, 0x27, 0x43, 0xd2, 0x1c, 0x85, 0x2d, - 0x94, 0xb0, 0x20, 0x68, 0x1d, 0x2a, 0x41, 0x95, 0x0d, 0xd2, 0x80, 0x1b, 0x91, 0x2f, 0xda, 0x64, 0x2b, 0x12, 0xae, - 0x55, 0xcc, 0xc2, 0x84, 0x51, 0xf1, 0xa0, 0xce, 0x1b, 0x4a, 0x6c, 0x01, 0xb6, 0x69, 0x6e, 0xb9, 0xa4, 0x77, 0x61, - 0xca, 0x50, 0xaa, 0x6b, 0x78, 0x4c, 0xb1, 0x99, 0x32, 0xdc, 0x56, 0xbd, 0x21, 0xd8, 0x92, 0x46, 0x55, 0xd7, 0x29, - 0x6a, 0x8c, 0x0c, 0x7d, 0xd0, 0x78, 0x14, 0x4c, 0x5c, 0xc4, 0xc1, 0xae, 0xb9, 0xd5, 0x45, 0x13, 0x1a, 0x19, 0xb7, - 0x22, 0x28, 0x4a, 0xf4, 0x7a, 0x37, 0x6c, 0x9c, 0x10, 0x0a, 0xa8, 0xb5, 0x1f, 0xaf, 0xd6, 0x4f, 0xcb, 0xa4, 0x3f, - 0x91, 0x07, 0x7a, 0x91, 0x50, 0x50, 0x7d, 0x22, 0x0f, 0x60, 0xfb, 0xf7, 0x16, 0xa4, 0x29, 0xea, 0x0e, 0x74, 0x6d, - 0x40, 0x70, 0x7d, 0x0f, 0xc2, 0x43, 0xed, 0x38, 0x40, 0x76, 0xbe, 0x03, 0x8b, 0x23, 0x88, 0x21, 0x8f, 0x32, 0x3f, - 0xc4, 0xcc, 0xca, 0x5e, 0x6b, 0x84, 0xb1, 0xd9, 0x70, 0x34, 0xf4, 0x17, 0x8e, 0x6d, 0x1f, 0xd5, 0xea, 0x83, 0x20, - 0xbb, 0xa9, 0xb6, 0x6e, 0x64, 0x23, 0xc7, 0x36, 0xfd, 0x17, 0x56, 0x67, 0x58, 0xbb, 0xa3, 0xa5, 0xe8, 0x8d, 0x13, - 0x14, 0x7f, 0x8d, 0x9f, 0x6d, 0xb5, 0xda, 0x81, 0xd4, 0xab, 0x56, 0xeb, 0x38, 0xb6, 0x9c, 0xc9, 0xbf, 0x26, 0xf5, - 0xab, 0x9f, 0xc6, 0x8e, 0xa4, 0x99, 0x44, 0x26, 0x10, 0x7f, 0x58, 0x83, 0x63, 0xf4, 0x67, 0xe5, 0xa5, 0xa2, 0xd1, - 0xe3, 0xa3, 0xeb, 0x13, 0x91, 0xa0, 0x9a, 0xbb, 0x75, 0xc9, 0x1d, 0x54, 0xbe, 0x98, 0x56, 0x31, 0x1c, 0x8b, 0x74, - 0x4a, 0x0a, 0x8d, 0xde, 0x4e, 0x6a, 0x01, 0xfb, 0x6f, 0xb9, 0x3e, 0xad, 0x29, 0x44, 0x02, 0x80, 0x1a, 0x10, 0xad, - 0x7c, 0x6f, 0x87, 0xeb, 0xb8, 0xdc, 0x5d, 0xf9, 0x92, 0x3c, 0xbc, 0x33, 0xbc, 0x74, 0x50, 0x87, 0x26, 0xfa, 0x6b, - 0xbe, 0xee, 0x1e, 0xd9, 0x25, 0x09, 0x67, 0xe5, 0x0e, 0x2b, 0xf7, 0xd7, 0xe1, 0xdd, 0x95, 0x30, 0x0a, 0x84, 0xf1, - 0x8f, 0x1a, 0x30, 0x4a, 0x1e, 0x85, 0xb8, 0xf9, 0xe9, 0x71, 0xf3, 0x0f, 0xa2, 0x62, 0xb0, 0x01, 0x8d, 0xc1, 0x25, - 0x9a, 0x49, 0x42, 0x71, 0x88, 0x15, 0x8d, 0x8e, 0xb8, 0x1a, 0x27, 0x44, 0x5b, 0x77, 0x62, 0xc6, 0x6d, 0x0a, 0x8b, - 0x36, 0x3e, 0x8b, 0xfe, 0x78, 0xa8, 0xd4, 0xda, 0xdf, 0x2f, 0xb5, 0xce, 0xf6, 0x49, 0xad, 0xa9, 0x47, 0xd3, 0x7d, - 0xe2, 0xc6, 0x92, 0x53, 0x1c, 0x27, 0xce, 0x65, 0xdf, 0xb8, 0x92, 0xa8, 0x1b, 0x1d, 0xa0, 0x78, 0xab, 0x5a, 0x6f, - 0xd4, 0x4a, 0x10, 0xc5, 0xdf, 0x12, 0x83, 0xc2, 0x15, 0xea, 0xb2, 0x6c, 0xfc, 0xaa, 0x90, 0x8d, 0x53, 0xae, 0xa6, - 0xf0, 0x65, 0xe1, 0xd4, 0xbf, 0xe4, 0x27, 0x26, 0xb8, 0x83, 0xc2, 0x5f, 0xac, 0x18, 0xa9, 0xe4, 0x01, 0x55, 0x30, - 0x1a, 0x92, 0x5f, 0x1d, 0xe7, 0x32, 0xca, 0xee, 0x75, 0xe5, 0xaa, 0x85, 0x03, 0x54, 0x51, 0x0e, 0x52, 0x77, 0x1c, - 0xb2, 0x28, 0x96, 0xb7, 0x4d, 0xd9, 0x03, 0x46, 0x7e, 0x2d, 0x6d, 0x12, 0xe1, 0xaa, 0x42, 0x01, 0xcc, 0xc5, 0xf4, - 0x15, 0xbd, 0xb6, 0xb0, 0x81, 0xc0, 0x41, 0x36, 0x78, 0xd6, 0xed, 0x97, 0xce, 0xd3, 0x0c, 0x05, 0x85, 0x16, 0x5e, - 0x96, 0x41, 0x20, 0x7c, 0x6f, 0xb6, 0x0d, 0xb7, 0x3c, 0x5e, 0xf2, 0xec, 0x7e, 0x07, 0xf1, 0xa2, 0x62, 0xcb, 0x8a, - 0x7c, 0x3c, 0x99, 0x26, 0x35, 0xcf, 0xc5, 0xaa, 0xf5, 0x4e, 0xa9, 0x10, 0x67, 0xcb, 0x9c, 0x53, 0xca, 0x32, 0x7a, - 0x56, 0x63, 0xc0, 0xbf, 0xcb, 0xb6, 0x4e, 0xb2, 0x0e, 0x31, 0x9a, 0xbc, 0x99, 0x25, 0xae, 0xf7, 0x49, 0x1a, 0x32, - 0x97, 0x73, 0x82, 0x0c, 0xb8, 0xac, 0x29, 0x18, 0xba, 0x18, 0x7c, 0x91, 0x0c, 0xac, 0x4e, 0x2a, 0x49, 0x5f, 0x06, - 0x4f, 0xed, 0xae, 0xfb, 0x6a, 0x7e, 0x5c, 0x11, 0x8a, 0x76, 0x7a, 0x65, 0x91, 0x79, 0xcb, 0x38, 0xb2, 0xe5, 0x7a, - 0x35, 0xdd, 0xca, 0xb2, 0x55, 0x49, 0xe4, 0x5a, 0x17, 0xb3, 0xca, 0x9f, 0x9d, 0xcf, 0xe7, 0x65, 0x41, 0xa3, 0xad, - 0x1c, 0xa3, 0xb0, 0xf0, 0xa9, 0x6d, 0xdb, 0xd5, 0xb1, 0xef, 0x06, 0xbb, 0x89, 0x72, 0xdb, 0xd3, 0xc6, 0x11, 0x23, - 0x6c, 0xf7, 0xc1, 0xaf, 0x0e, 0x8e, 0xdc, 0x2a, 0x4e, 0x76, 0xc9, 0x2c, 0x62, 0x48, 0x8d, 0x21, 0xfc, 0x8c, 0xac, - 0xd2, 0x81, 0x47, 0x50, 0x07, 0x63, 0x49, 0x07, 0x1a, 0x0d, 0x07, 0xcc, 0x05, 0x98, 0x8a, 0x38, 0x7c, 0x57, 0xd8, - 0x0a, 0xca, 0xc3, 0x6b, 0xc2, 0x7b, 0xfe, 0x11, 0x3c, 0x28, 0xdb, 0xba, 0x4c, 0x1b, 0xa7, 0xd5, 0xb3, 0xff, 0x5c, - 0xaa, 0xa7, 0xc0, 0x05, 0xb8, 0xe5, 0x0a, 0x6d, 0x2a, 0x9f, 0xc5, 0xff, 0x17, 0xf2, 0xff, 0x57, 0xf1, 0xa6, 0x6c, - 0x3f, 0x72, 0x0a, 0x12, 0xed, 0xe2, 0xb4, 0xd0, 0x51, 0x37, 0xed, 0x01, 0x61, 0x65, 0x30, 0x97, 0x15, 0xe8, 0xa0, - 0xa4, 0x2f, 0xa5, 0xdc, 0x68, 0x10, 0xbf, 0x23, 0xc5, 0x0c, 0x4b, 0x5c, 0x88, 0x10, 0x8b, 0x84, 0x71, 0x30, 0x07, - 0xe3, 0xe5, 0x29, 0xea, 0x0f, 0x4a, 0x7b, 0x02, 0xb4, 0xf1, 0xb5, 0xb9, 0x1d, 0x24, 0xee, 0xaf, 0xea, 0xb5, 0x78, - 0xc7, 0x00, 0x32, 0x07, 0x0e, 0x21, 0x1a, 0x12, 0x28, 0x95, 0xcd, 0x4d, 0x47, 0x29, 0xde, 0xca, 0x7a, 0x36, 0x3e, - 0x30, 0xec, 0xae, 0xb9, 0x0a, 0xed, 0x9b, 0x6b, 0x0b, 0x60, 0xb2, 0x6c, 0xfb, 0xe1, 0xb3, 0x09, 0x4b, 0x2c, 0xef, - 0x47, 0x07, 0x97, 0x1c, 0xf7, 0xaf, 0x89, 0x77, 0x67, 0x4a, 0xcf, 0x3f, 0xca, 0x17, 0xff, 0xda, 0x28, 0xd0, 0xbb, - 0x2a, 0x49, 0xe8, 0x98, 0xb5, 0x78, 0x47, 0x3f, 0xa8, 0xf6, 0xca, 0x0f, 0x0f, 0xaf, 0xeb, 0x6e, 0x0e, 0xae, 0x0b, - 0x17, 0xc6, 0xc1, 0x95, 0xe1, 0xc6, 0xa1, 0x96, 0x0b, 0xd9, 0xe8, 0xaf, 0x92, 0x40, 0x51, 0x76, 0xfc, 0x55, 0xb1, - 0x15, 0xa5, 0xf2, 0xaf, 0xd6, 0x40, 0x7c, 0x1e, 0x94, 0x52, 0x41, 0xe1, 0x59, 0xd1, 0xd4, 0xbe, 0x72, 0xaa, 0xf4, - 0xbb, 0xca, 0x89, 0xad, 0x52, 0x2e, 0x6c, 0xa4, 0xf6, 0x3a, 0x85, 0x43, 0xdf, 0xb1, 0xad, 0x8e, 0xcf, 0x16, 0xfc, - 0x92, 0x98, 0xfb, 0x41, 0x40, 0x51, 0x45, 0x9a, 0x25, 0xd1, 0x27, 0x52, 0x56, 0xb3, 0xd0, 0x32, 0x66, 0x04, 0xd2, - 0xe1, 0x8f, 0x70, 0x76, 0x3c, 0x37, 0x1e, 0xe0, 0xd9, 0x90, 0x0b, 0xc1, 0x80, 0x93, 0x96, 0xe2, 0x27, 0xe0, 0x0e, - 0x9e, 0xaa, 0xe3, 0x33, 0x08, 0x1a, 0xa8, 0xcc, 0x46, 0xea, 0x8f, 0x9d, 0xbe, 0xe2, 0xf4, 0xee, 0xcc, 0xae, 0x67, - 0x9b, 0x8e, 0x75, 0xac, 0xd8, 0xd6, 0x89, 0xd9, 0xb1, 0xfa, 0x4a, 0xc7, 0xea, 0xc1, 0xbf, 0x9e, 0x63, 0xbd, 0x52, - 0x6c, 0x78, 0x52, 0x1c, 0xab, 0x8b, 0xff, 0x76, 0xac, 0xfe, 0x5d, 0x97, 0xde, 0xf4, 0xae, 0x70, 0xab, 0xaa, 0x8c, - 0x02, 0x9c, 0x40, 0xd4, 0xa3, 0xf1, 0xd9, 0x3a, 0x25, 0xca, 0x66, 0xa4, 0xbe, 0x52, 0x95, 0x65, 0x42, 0xe6, 0x23, - 0xf5, 0xa9, 0x2b, 0x95, 0x3a, 0xa7, 0x8d, 0xc5, 0x9d, 0x7e, 0x63, 0x71, 0xf7, 0xa4, 0xb1, 0xf8, 0xb8, 0x57, 0x2e, - 0x3e, 0x5a, 0xd0, 0x57, 0x52, 0xce, 0xbe, 0x95, 0x9b, 0x25, 0xfe, 0x46, 0x73, 0x14, 0x40, 0xd7, 0x26, 0xfc, 0xd3, - 0xef, 0xe8, 0xa2, 0xd5, 0x14, 0x5a, 0x09, 0x68, 0xf4, 0x4f, 0x15, 0xe7, 0xe4, 0x2f, 0x9d, 0x13, 0x0f, 0xea, 0x41, - 0x86, 0x49, 0xf8, 0xbb, 0xeb, 0x9e, 0x7a, 0xb6, 0x02, 0x0d, 0x1d, 0xf8, 0x6f, 0xd9, 0xeb, 0x78, 0xf4, 0xc1, 0x86, - 0xf7, 0x1f, 0x9d, 0x7e, 0x6a, 0x9b, 0x0e, 0xfc, 0xf7, 0x9b, 0x50, 0xb9, 0x83, 0xc2, 0x5f, 0xee, 0xf7, 0xd8, 0x56, - 0xba, 0xa7, 0xcb, 0x8e, 0xf5, 0xea, 0xae, 0x6f, 0x9d, 0x2e, 0x9d, 0xfe, 0x47, 0xfa, 0x14, 0x98, 0x1d, 0xeb, 0x15, - 0xfc, 0x7d, 0xec, 0xda, 0x4b, 0xd3, 0xb1, 0x4e, 0xef, 0xba, 0x56, 0x37, 0x30, 0x4f, 0xac, 0x53, 0xf8, 0xfb, 0x0d, - 0xc0, 0x0b, 0x70, 0x65, 0x29, 0x41, 0x15, 0xd8, 0x18, 0x15, 0xfb, 0x0d, 0xf9, 0x23, 0x9d, 0x63, 0xa5, 0x77, 0xfc, - 0x97, 0xd3, 0x3b, 0xf3, 0x78, 0xe9, 0x74, 0xee, 0xcc, 0xd6, 0x9f, 0x1f, 0x01, 0xf2, 0xbb, 0x17, 0x0e, 0xc0, 0x88, - 0x39, 0x40, 0xfe, 0x34, 0x31, 0x2e, 0xdb, 0xc4, 0xe8, 0xef, 0xf7, 0x8b, 0xd1, 0x7f, 0x58, 0x1f, 0x22, 0x46, 0x7f, - 0xff, 0xd5, 0xc5, 0xe8, 0x97, 0x55, 0x2b, 0xee, 0xf7, 0xd5, 0x58, 0xe5, 0xbf, 0x6c, 0xab, 0x44, 0xb2, 0xef, 0x6a, - 0xd7, 0x57, 0xeb, 0x1b, 0x88, 0xb6, 0xf3, 0x3e, 0x1a, 0xfd, 0xb0, 0x2e, 0x99, 0x28, 0x45, 0x80, 0x01, 0xde, 0x47, - 0x14, 0x03, 0xfc, 0xb6, 0x1e, 0x81, 0x5d, 0x04, 0xbb, 0x35, 0xfd, 0x99, 0xb9, 0x74, 0x83, 0xb9, 0xb8, 0x71, 0xa1, - 0x64, 0x88, 0xc5, 0x60, 0x33, 0x0f, 0x97, 0x09, 0x28, 0x6b, 0xd6, 0xab, 0x30, 0x1d, 0x9c, 0xd8, 0x80, 0xe6, 0x3b, - 0xf3, 0x24, 0xaf, 0x34, 0xb6, 0x78, 0x7c, 0xa2, 0x5b, 0x66, 0xd3, 0xdf, 0xfa, 0x1e, 0x4d, 0xd6, 0x9a, 0x7b, 0x77, - 0xea, 0xfd, 0x2a, 0x60, 0x0b, 0xc2, 0x4d, 0xfa, 0x80, 0xd8, 0x68, 0x7a, 0x5f, 0x36, 0x1c, 0xab, 0x98, 0x0a, 0xb6, - 0x8f, 0x14, 0x46, 0x52, 0x6d, 0xef, 0x94, 0x0d, 0xcf, 0xf6, 0x4d, 0xb3, 0xe1, 0xf3, 0xa5, 0xe6, 0x3b, 0xac, 0xde, - 0x44, 0xc7, 0x55, 0x50, 0x55, 0x32, 0x6d, 0x35, 0x02, 0xa4, 0xa0, 0x3d, 0x0b, 0xd3, 0xb8, 0x82, 0xf0, 0xb1, 0x15, - 0xbc, 0x8d, 0x6d, 0xe9, 0x5d, 0xa9, 0x4f, 0xd9, 0x9c, 0xee, 0xc5, 0x16, 0xe9, 0x41, 0xff, 0x37, 0x20, 0x6c, 0xd8, - 0x7d, 0x3c, 0x8d, 0x64, 0x38, 0x6f, 0xa5, 0x7e, 0x29, 0xa9, 0x9d, 0x2f, 0x9d, 0x6d, 0x9d, 0xb4, 0x69, 0x35, 0xa4, - 0x75, 0xc8, 0x8a, 0xdf, 0xd1, 0xf8, 0x79, 0x6a, 0xb6, 0x9a, 0x53, 0xd3, 0x62, 0xb4, 0xcc, 0xdd, 0xd5, 0x19, 0xaf, - 0xf7, 0x14, 0x36, 0xb1, 0xc1, 0x1e, 0x64, 0xc7, 0xf1, 0xed, 0x1c, 0xb2, 0x22, 0x0f, 0x90, 0x88, 0x90, 0x28, 0xa8, - 0x0e, 0xda, 0xd8, 0x0e, 0x77, 0x98, 0x7f, 0xc8, 0x1d, 0xb3, 0x4e, 0xd0, 0x56, 0x77, 0x97, 0xc5, 0x88, 0x70, 0x6d, - 0xd8, 0x96, 0x14, 0xa8, 0x4e, 0xaf, 0x6f, 0x38, 0x27, 0x86, 0xd5, 0xef, 0xe9, 0x39, 0x3f, 0x70, 0x72, 0x97, 0x25, - 0x80, 0x80, 0xc9, 0xae, 0x18, 0xa6, 0x1f, 0xfa, 0x99, 0xef, 0x06, 0x39, 0xa0, 0xfa, 0x32, 0xcd, 0xfb, 0xcf, 0x75, - 0x9a, 0xc1, 0x1c, 0x39, 0x49, 0x86, 0xe6, 0xca, 0xe6, 0x94, 0x64, 0xf7, 0x84, 0x84, 0x2d, 0xaa, 0xdc, 0xaa, 0xf5, - 0xf3, 0x1f, 0x67, 0x0b, 0x9a, 0x53, 0x3b, 0x8b, 0x69, 0x16, 0xb2, 0xfd, 0xc1, 0x4d, 0x75, 0xf3, 0x89, 0xf1, 0x53, - 0x1b, 0xc2, 0xfd, 0xe7, 0x7e, 0x84, 0x9b, 0x91, 0x43, 0x10, 0xee, 0x3f, 0xbf, 0x3a, 0xc2, 0xfd, 0x49, 0x46, 0xb8, - 0x25, 0x4f, 0x95, 0x42, 0x26, 0xfa, 0x01, 0x9f, 0x35, 0x08, 0xf2, 0xfb, 0x52, 0x3d, 0xa2, 0xe4, 0xa5, 0x2a, 0x25, - 0x5f, 0xfd, 0x58, 0xca, 0x26, 0x83, 0x2c, 0x3b, 0x06, 0x25, 0xa5, 0x99, 0x2b, 0x20, 0x31, 0xa9, 0x48, 0xb1, 0x0d, - 0x7d, 0x5e, 0x84, 0x59, 0x60, 0xbd, 0x67, 0x6c, 0x09, 0xa8, 0x20, 0x7e, 0x88, 0x92, 0x95, 0x8b, 0x01, 0xd9, 0x54, - 0xcc, 0x42, 0x07, 0x0f, 0x36, 0x78, 0x47, 0x79, 0x51, 0x38, 0x13, 0x72, 0x74, 0x32, 0xba, 0xa6, 0xf4, 0xa0, 0xfa, - 0x40, 0xdc, 0x44, 0x35, 0xe8, 0x6b, 0x58, 0xdc, 0x17, 0x5d, 0xfb, 0x45, 0xe7, 0xf8, 0xc5, 0x89, 0x0d, 0xff, 0x73, - 0x48, 0x37, 0x37, 0x58, 0xc5, 0x55, 0x14, 0x42, 0x22, 0x0c, 0x5e, 0xb3, 0xad, 0xda, 0x3d, 0x21, 0x9f, 0x8a, 0x5a, - 0xfd, 0xe6, 0x4a, 0x33, 0xf7, 0xa1, 0xa8, 0xd3, 0x58, 0x63, 0x19, 0xad, 0xa5, 0x61, 0x35, 0x8c, 0xc6, 0x0f, 0xd7, - 0x20, 0x19, 0x92, 0x6a, 0xc8, 0xaf, 0xd9, 0x74, 0x8b, 0x79, 0x91, 0x6e, 0x7e, 0x53, 0x64, 0xdb, 0xe1, 0x59, 0x3f, - 0xf6, 0x42, 0x90, 0x09, 0xd5, 0x6d, 0x8c, 0xd5, 0x8d, 0xf9, 0x66, 0x14, 0xc8, 0x75, 0x57, 0xa4, 0x54, 0xc7, 0x05, - 0xca, 0x92, 0x75, 0xe8, 0xd1, 0xac, 0xe9, 0xee, 0x34, 0xd5, 0xfc, 0x23, 0x88, 0xd6, 0x89, 0x1f, 0xd6, 0x71, 0xd5, - 0xdc, 0xb1, 0x5d, 0xa4, 0x26, 0x48, 0xf9, 0xaa, 0xb8, 0x2f, 0x32, 0x23, 0xa1, 0x09, 0x4d, 0x71, 0x69, 0xcd, 0x91, - 0xfb, 0x42, 0x34, 0x7c, 0x91, 0x19, 0x90, 0x54, 0x14, 0x96, 0xfb, 0xf9, 0x73, 0x5a, 0x0b, 0xd2, 0xfc, 0xd1, 0x69, - 0x9d, 0x7b, 0x22, 0x35, 0x98, 0xaa, 0xb8, 0x8b, 0x48, 0xc5, 0xd4, 0x60, 0x03, 0xcf, 0x88, 0x5e, 0xbe, 0x1c, 0x8f, - 0x1c, 0x9d, 0x25, 0xa9, 0x2c, 0x65, 0x54, 0xba, 0x3c, 0x4c, 0x35, 0xae, 0x37, 0x3a, 0x6d, 0xc5, 0x7e, 0xb8, 0xe0, - 0x9a, 0x69, 0x81, 0xbd, 0x20, 0xc3, 0x01, 0x55, 0x81, 0xb9, 0x5c, 0x45, 0xcd, 0xeb, 0xdc, 0x91, 0x04, 0x12, 0x6c, - 0x8e, 0xd4, 0xae, 0x65, 0x5b, 0xb6, 0x2a, 0x1a, 0xce, 0xfd, 0xc5, 0x68, 0x1b, 0x65, 0x2e, 0xe4, 0x8a, 0x09, 0xa2, - 0x05, 0x78, 0x7e, 0x64, 0x7e, 0x16, 0x40, 0xe2, 0x11, 0x70, 0x01, 0x59, 0x51, 0xae, 0x31, 0x67, 0xf6, 0xb8, 0x6e, - 0xf2, 0x09, 0x93, 0xcf, 0x71, 0xa7, 0x2f, 0x0c, 0x49, 0xf3, 0x23, 0x5c, 0x86, 0x9a, 0xaa, 0x41, 0xea, 0x43, 0x92, - 0xa4, 0xa6, 0x6c, 0xdf, 0x3e, 0x50, 0xa0, 0x0d, 0xa4, 0x25, 0xc7, 0x0e, 0xe6, 0x89, 0xbb, 0x82, 0x18, 0xdd, 0xdb, - 0xdc, 0x60, 0x98, 0x56, 0x65, 0xa8, 0x56, 0x71, 0x5e, 0x9d, 0x18, 0x4a, 0xc7, 0x31, 0x14, 0x1b, 0xd0, 0xad, 0x9a, - 0x1b, 0xdb, 0xfc, 0x66, 0xb8, 0x4f, 0x45, 0x47, 0xf1, 0xcb, 0x53, 0x3a, 0x0f, 0xaa, 0x9c, 0x63, 0xc2, 0xcf, 0x8c, - 0x06, 0x14, 0xd4, 0xa4, 0xe8, 0xd9, 0x3e, 0x15, 0xd3, 0x5f, 0x91, 0x4d, 0xa6, 0x63, 0x62, 0x0e, 0x56, 0xc5, 0xd7, - 0xb7, 0xe8, 0x9a, 0xe6, 0x87, 0x8a, 0xff, 0xf9, 0xb3, 0xe6, 0x83, 0xf9, 0xfd, 0x48, 0x82, 0x0f, 0x3c, 0xeb, 0x25, - 0x80, 0xf9, 0x85, 0x62, 0x09, 0x81, 0x05, 0xbe, 0x31, 0xf0, 0x6f, 0x51, 0xcc, 0x7f, 0x30, 0xc5, 0x9e, 0x15, 0xb8, - 0xe1, 0x02, 0x50, 0x9a, 0x1b, 0x2e, 0x6a, 0x06, 0x04, 0xd4, 0xbb, 0xae, 0x52, 0x5a, 0x74, 0x55, 0x28, 0xf7, 0xd3, - 0xef, 0x1f, 0xae, 0x68, 0xe2, 0x21, 0x48, 0x72, 0xed, 0xce, 0xd0, 0x15, 0xac, 0xd0, 0x3d, 0xbc, 0x1c, 0x7d, 0x73, - 0xb6, 0x22, 0x99, 0x4b, 0x05, 0x97, 0xc0, 0xe2, 0x01, 0x39, 0xa0, 0x78, 0x3c, 0x69, 0x28, 0x65, 0xf0, 0x66, 0xe4, - 0xce, 0xf7, 0x18, 0x9f, 0x66, 0x28, 0xec, 0x9e, 0x32, 0xd1, 0x46, 0x69, 0xe4, 0x18, 0xd4, 0x44, 0xd6, 0x73, 0x31, - 0xec, 0xe0, 0x28, 0x8c, 0xd4, 0xf1, 0x37, 0xc2, 0x9b, 0xa8, 0x6d, 0x11, 0x20, 0xfb, 0xdf, 0x75, 0x42, 0x82, 0x7f, - 0x8d, 0xbe, 0x81, 0x8b, 0xfb, 0x9b, 0x1b, 0x55, 0x1f, 0x66, 0x16, 0xf2, 0x31, 0xdf, 0x34, 0x64, 0xc1, 0x43, 0x1e, - 0x95, 0x31, 0x9b, 0x5d, 0x89, 0xd9, 0x84, 0xdf, 0xfb, 0x59, 0xd7, 0xf1, 0x19, 0x5e, 0x68, 0x63, 0xe0, 0x2e, 0xb6, - 0x25, 0x9e, 0xd3, 0x19, 0x22, 0x83, 0x3a, 0x0d, 0x5c, 0xef, 0x13, 0xe7, 0x50, 0xe5, 0x87, 0x43, 0x78, 0x51, 0x41, - 0xd9, 0x35, 0xee, 0x65, 0xdc, 0xca, 0x5b, 0xfc, 0x32, 0x7e, 0xea, 0x7e, 0xe9, 0x67, 0x82, 0x19, 0xc6, 0x87, 0x1c, - 0xb4, 0x39, 0x38, 0xbe, 0x82, 0xfd, 0x01, 0x06, 0xd5, 0x39, 0xfd, 0x4b, 0xef, 0xce, 0xb1, 0x97, 0x1d, 0xc7, 0x02, - 0x36, 0x67, 0xd9, 0xb5, 0xfa, 0x81, 0xd9, 0xb5, 0xfa, 0xf0, 0xf7, 0x11, 0x58, 0x2f, 0xb3, 0x63, 0x1d, 0x7f, 0x74, - 0x3a, 0x81, 0x79, 0x6a, 0xf5, 0xe1, 0xef, 0x92, 0xb6, 0xfa, 0x05, 0x99, 0x1e, 0x60, 0x78, 0xbe, 0x29, 0x61, 0x01, - 0xe9, 0xb7, 0xd0, 0x22, 0x18, 0xa5, 0xeb, 0xad, 0x41, 0x13, 0x01, 0x28, 0x43, 0x35, 0x78, 0x94, 0xc0, 0x70, 0xa8, - 0x41, 0x5a, 0x6e, 0x0c, 0x28, 0xcf, 0x0d, 0x32, 0xc2, 0x22, 0xc5, 0x7c, 0xfb, 0x31, 0x62, 0x6d, 0x9a, 0x03, 0x70, - 0xf3, 0x4c, 0x45, 0x54, 0x75, 0xf1, 0xb7, 0x18, 0x03, 0xeb, 0xf0, 0x90, 0xe1, 0x12, 0x56, 0x2a, 0xb2, 0xe5, 0xe5, - 0xfb, 0x07, 0x8e, 0x7e, 0xa3, 0x44, 0x64, 0x6b, 0xf9, 0xaa, 0x7d, 0x33, 0x75, 0x86, 0xe8, 0xfd, 0xf7, 0xf6, 0x83, - 0x49, 0x4a, 0x69, 0x3f, 0x3c, 0xba, 0xe7, 0xcc, 0x4f, 0xc4, 0xf0, 0x24, 0x14, 0xed, 0x34, 0x47, 0x2e, 0xd7, 0x21, - 0xad, 0xc5, 0x05, 0x50, 0xc9, 0x77, 0x6e, 0x20, 0x99, 0x5e, 0x48, 0x2d, 0x9f, 0x08, 0xcc, 0xff, 0xfc, 0x79, 0x31, - 0x38, 0xb3, 0x32, 0xee, 0x33, 0xa7, 0x07, 0xd7, 0x6e, 0x8f, 0x74, 0x77, 0x5a, 0x01, 0xed, 0x0f, 0x0f, 0x5b, 0xc4, - 0x93, 0xe4, 0x9a, 0x7e, 0xae, 0x63, 0x6c, 0x35, 0x45, 0xaa, 0x69, 0x18, 0x21, 0xb0, 0x6e, 0x85, 0xd5, 0x51, 0xf5, - 0x61, 0xc8, 0x15, 0x66, 0xe1, 0x8e, 0x90, 0xb8, 0x8c, 0x17, 0x53, 0x01, 0x34, 0x3b, 0xe6, 0xb1, 0xc7, 0xa5, 0xf1, - 0x7f, 0x3d, 0x09, 0x74, 0x2f, 0x02, 0x0d, 0x5f, 0xe5, 0xb4, 0x96, 0xdc, 0x4d, 0xc4, 0xbd, 0x4a, 0x2f, 0x54, 0x92, - 0x9e, 0xab, 0x50, 0x04, 0xf9, 0x8e, 0x30, 0xc5, 0x99, 0x30, 0x6f, 0x12, 0xb7, 0x45, 0x51, 0x60, 0xf8, 0x10, 0x13, - 0x5a, 0xe3, 0xae, 0x4e, 0xfa, 0xf3, 0xe7, 0xad, 0x97, 0x10, 0x55, 0x27, 0xcb, 0x99, 0x1e, 0x55, 0x19, 0xbf, 0xa9, - 0x32, 0x8a, 0x11, 0xfd, 0x22, 0xd6, 0xe0, 0x56, 0x59, 0x74, 0xef, 0xe1, 0xcf, 0x29, 0x71, 0x33, 0x8b, 0xe9, 0x41, - 0x34, 0xe9, 0x72, 0x37, 0x1c, 0xd2, 0x05, 0x7b, 0x2c, 0x16, 0x7f, 0x8b, 0x05, 0x9b, 0x7b, 0xb6, 0xfd, 0xb8, 0x66, - 0x7e, 0xc8, 0xd0, 0xc7, 0x67, 0xbb, 0x08, 0x9e, 0xf2, 0x2e, 0x73, 0x69, 0x84, 0x0d, 0xf9, 0xca, 0x8d, 0x32, 0x97, - 0xe7, 0x15, 0x01, 0xba, 0x7c, 0xd8, 0xa8, 0x30, 0x94, 0x7c, 0x95, 0xc7, 0xef, 0xae, 0xbe, 0x53, 0xd8, 0xfe, 0xa7, - 0xfa, 0x2d, 0x64, 0x64, 0x68, 0x14, 0xfc, 0x11, 0x8d, 0x82, 0xaf, 0xb0, 0xb4, 0x12, 0x10, 0x4b, 0x3e, 0x3f, 0xa2, - 0x10, 0x54, 0x15, 0x12, 0x7a, 0x54, 0xeb, 0xb7, 0x5a, 0x07, 0x99, 0x1f, 0xbb, 0x49, 0x76, 0x04, 0x4d, 0x4d, 0x40, - 0x72, 0x6a, 0x9b, 0x07, 0x33, 0x55, 0x1c, 0x72, 0xa1, 0x5a, 0x16, 0x72, 0xcd, 0xe1, 0xdc, 0x0f, 0x84, 0xe2, 0x90, - 0x7f, 0xc0, 0xf5, 0x3c, 0x12, 0x67, 0x23, 0xd5, 0x8d, 0x21, 0x1b, 0x02, 0xc6, 0x37, 0x3e, 0x8a, 0xbc, 0x8c, 0x64, - 0x66, 0x9a, 0x25, 0xc4, 0x5d, 0xa9, 0x22, 0xd6, 0x67, 0xbd, 0xbf, 0x74, 0x3d, 0x5d, 0xf9, 0x99, 0x08, 0x96, 0x47, - 0x27, 0x08, 0x2a, 0x3c, 0x18, 0xe2, 0x78, 0x92, 0x33, 0x10, 0x5e, 0x46, 0x8b, 0xca, 0x8e, 0x2a, 0x28, 0x97, 0x73, - 0x0c, 0xc5, 0xca, 0x22, 0xe0, 0xcf, 0xd0, 0x23, 0xe7, 0x96, 0x79, 0x5d, 0x8b, 0x98, 0x7e, 0xea, 0xf8, 0x8c, 0xb1, - 0xb7, 0x0a, 0x06, 0x0a, 0x50, 0x7b, 0x36, 0x04, 0x9b, 0x6d, 0xf3, 0xc7, 0x3e, 0x62, 0x95, 0xe1, 0x6a, 0xa2, 0x3d, - 0x63, 0xdc, 0x6f, 0x3a, 0x96, 0x2b, 0x20, 0x84, 0x4a, 0x2a, 0xde, 0xa5, 0x33, 0x16, 0x0e, 0x40, 0x38, 0x2a, 0xa4, - 0x95, 0x3e, 0x7f, 0x7e, 0x3d, 0xf9, 0xcf, 0xbf, 0x21, 0x38, 0xf9, 0xd2, 0xe1, 0x5e, 0xd0, 0xd7, 0x72, 0x2d, 0x46, - 0x7d, 0x1a, 0x13, 0x54, 0xef, 0x93, 0x19, 0x0f, 0x0b, 0xc2, 0xb7, 0x56, 0x3e, 0xb9, 0xe1, 0xa1, 0x9e, 0x20, 0x01, - 0x81, 0xce, 0x7d, 0xb5, 0x27, 0xb0, 0xbc, 0x13, 0x1e, 0x22, 0x40, 0xf9, 0x75, 0xf3, 0x7d, 0x1f, 0xb2, 0xf4, 0xd6, - 0xf2, 0x02, 0x48, 0x03, 0xc4, 0x3d, 0x34, 0x3e, 0x73, 0x99, 0xf0, 0x15, 0xc8, 0x8f, 0x74, 0x70, 0x04, 0xd3, 0x5c, - 0x46, 0x2b, 0x62, 0xf9, 0xd1, 0xd1, 0x3d, 0x99, 0x9a, 0x6e, 0xec, 0x53, 0xf9, 0x32, 0xca, 0xdd, 0x14, 0x4a, 0xf9, - 0x09, 0x05, 0x2d, 0xa5, 0xaf, 0xf3, 0x02, 0x94, 0x51, 0x01, 0x28, 0xf8, 0xe9, 0x8e, 0xcb, 0x01, 0xfc, 0x2c, 0x1e, - 0x31, 0xbe, 0x8c, 0xe5, 0xcf, 0x69, 0x1c, 0x3e, 0x1e, 0x72, 0xaf, 0x78, 0x30, 0xa3, 0xf9, 0x5c, 0x0e, 0xba, 0x67, - 0x95, 0xbf, 0x2f, 0xa0, 0x52, 0xec, 0xd9, 0x28, 0xa6, 0x5f, 0xaa, 0x7f, 0x42, 0xfc, 0x84, 0x6c, 0xb9, 0x2c, 0x3e, - 0x23, 0x9c, 0xe7, 0x5a, 0xf0, 0x3e, 0x01, 0x92, 0xa7, 0xb4, 0x12, 0x43, 0x14, 0xd5, 0xc8, 0xd0, 0x2d, 0xa4, 0xc9, - 0x93, 0xd1, 0x88, 0xe2, 0xb1, 0x2a, 0x3a, 0x03, 0x28, 0x35, 0x44, 0xcf, 0x87, 0xc9, 0x66, 0xd0, 0xd0, 0xa4, 0x1e, - 0x5c, 0xd8, 0xa8, 0x3a, 0x9d, 0xfa, 0x18, 0x8f, 0x5c, 0xbe, 0xbf, 0x4a, 0x3b, 0x10, 0x76, 0x16, 0x5b, 0x58, 0x40, - 0xe0, 0xbc, 0x9f, 0x0a, 0x1e, 0x57, 0xbe, 0xa5, 0x28, 0xdb, 0x0c, 0xdc, 0x87, 0x48, 0xd2, 0xac, 0x33, 0x27, 0xfb, - 0x4b, 0x2c, 0xbd, 0xe2, 0xce, 0x6d, 0xb5, 0x93, 0x24, 0x22, 0x90, 0xd7, 0x4f, 0x93, 0x1c, 0x32, 0x7c, 0xdf, 0x61, - 0x92, 0xeb, 0x96, 0x27, 0x83, 0xd8, 0x31, 0x2f, 0x0e, 0x5a, 0xe9, 0x25, 0x9e, 0xfb, 0xfc, 0xec, 0x08, 0xe6, 0x07, - 0x81, 0x01, 0x4a, 0x94, 0x91, 0xaf, 0x43, 0xf4, 0x01, 0x37, 0xa5, 0xd6, 0x01, 0x17, 0x33, 0x4e, 0xd4, 0x21, 0xe7, - 0x28, 0xa2, 0x83, 0x96, 0xaa, 0xd4, 0x89, 0x15, 0xbb, 0x99, 0xca, 0xdb, 0x1f, 0xb1, 0xff, 0xb7, 0x35, 0x86, 0xeb, - 0xcf, 0x87, 0x19, 0xe1, 0x7e, 0xb7, 0x97, 0x59, 0x8b, 0x6b, 0x6e, 0x5b, 0x15, 0x4a, 0xb0, 0xee, 0xa8, 0x50, 0xec, - 0xe3, 0x5d, 0xb5, 0x0a, 0xd2, 0x48, 0x54, 0x8b, 0x5d, 0x4d, 0x7d, 0x8a, 0x3b, 0xbe, 0x56, 0x1b, 0x4b, 0xa1, 0xde, - 0x65, 0x36, 0x82, 0xaa, 0x5c, 0xd8, 0xee, 0xc6, 0x31, 0xad, 0xac, 0x0f, 0xcf, 0x8e, 0x28, 0xdf, 0x39, 0xa6, 0x3b, - 0x6c, 0x7c, 0x06, 0xd6, 0x85, 0x74, 0xd1, 0xdd, 0x38, 0x66, 0x4b, 0x4a, 0x7f, 0xd1, 0x37, 0x47, 0xcb, 0x6c, 0x15, - 0x8c, 0xff, 0x0f, 0x00, 0xa3, 0x9b, 0x76, 0x11, 0x5a, 0x03, 0x00}; + 0xdc, 0xd3, 0x2f, 0xb7, 0x8d, 0x1b, 0xff, 0x7f, 0x9f, 0x82, 0x61, 0xd2, 0x1c, 0x99, 0x90, 0x34, 0x29, 0x59, 0xb6, + 0x23, 0x59, 0xf6, 0xdd, 0x25, 0xb9, 0xa9, 0x3b, 0xbe, 0xcb, 0x4d, 0xe2, 0x66, 0xda, 0xf3, 0x79, 0x2c, 0x4a, 0x82, + 0x24, 0x36, 0x14, 0xa9, 0x21, 0x29, 0x5b, 0x3e, 0x85, 0x7d, 0x96, 0x3e, 0x4b, 0x9f, 0xec, 0x37, 0xbb, 0x0b, 0x80, + 0xe0, 0x87, 0x3e, 0x7c, 0xc9, 0xb5, 0xbf, 0xb9, 0xba, 0x11, 0x41, 0x00, 0x04, 0x16, 0xc0, 0x62, 0xbf, 0xd7, 0x9f, + 0x72, 0xd9, 0x8b, 0x65, 0xb0, 0xfd, 0x3e, 0xf7, 0xf9, 0x33, 0x73, 0x70, 0x4b, 0x02, 0xc1, 0xe7, 0x64, 0xf1, 0x74, + 0x1a, 0x32, 0x43, 0x17, 0xc9, 0x43, 0x74, 0x4b, 0x7e, 0xe6, 0xfc, 0x89, 0x2b, 0x22, 0x76, 0x9a, 0xf9, 0xa6, 0xa3, + 0x25, 0x66, 0xcc, 0x64, 0x48, 0x3b, 0xa2, 0x5c, 0x51, 0x36, 0x7b, 0x87, 0xea, 0x0d, 0xbe, 0x2e, 0xc5, 0xd1, 0xb5, + 0xc7, 0xf1, 0x72, 0x18, 0x32, 0x1b, 0xb7, 0x3b, 0x7c, 0x72, 0x3d, 0x5c, 0x0e, 0x87, 0x90, 0xa5, 0xe5, 0x89, 0x6b, + 0x41, 0xdc, 0x99, 0x38, 0x45, 0x7e, 0x30, 0x37, 0x7b, 0x30, 0x29, 0x27, 0xab, 0x0e, 0x1f, 0x6c, 0x45, 0x40, 0xd4, + 0x43, 0x1f, 0xc8, 0x80, 0xf7, 0x6b, 0x38, 0xb5, 0x7d, 0xfd, 0x03, 0xec, 0xbe, 0x54, 0xef, 0x35, 0x1d, 0xfd, 0xfe, + 0xb5, 0xfe, 0x01, 0x61, 0x8c, 0xd9, 0x8b, 0x5f, 0xd3, 0xee, 0xd5, 0x2d, 0x9d, 0x94, 0xde, 0x4b, 0xcc, 0x63, 0x00, + 0x42, 0xdf, 0x37, 0x81, 0x3f, 0x8d, 0xe2, 0x34, 0x0b, 0x46, 0xfa, 0x4d, 0xef, 0x22, 0x30, 0xae, 0xe7, 0x99, 0x61, + 0xde, 0x58, 0xa3, 0x4c, 0x4d, 0x81, 0x22, 0x10, 0x26, 0x66, 0x40, 0xd9, 0x54, 0x49, 0x3d, 0x41, 0x5b, 0x2b, 0x0a, + 0xd4, 0x8c, 0x95, 0x46, 0x59, 0x1f, 0xea, 0x55, 0xf2, 0xa9, 0x60, 0x62, 0x28, 0x1d, 0x5b, 0x9a, 0x3d, 0xe2, 0x54, + 0x5e, 0x2f, 0xd7, 0x78, 0x95, 0x67, 0xc5, 0x6d, 0x89, 0x31, 0x80, 0x85, 0xe3, 0x0c, 0x3d, 0x3f, 0x51, 0x8d, 0x3e, + 0x4b, 0xf7, 0xee, 0xe0, 0xbb, 0x32, 0x5d, 0x00, 0xf7, 0x37, 0x58, 0x5c, 0x44, 0x71, 0xa6, 0x41, 0x60, 0x1b, 0xf8, + 0xe2, 0xa0, 0x6a, 0x24, 0xc6, 0x7b, 0x35, 0xcc, 0x9c, 0x23, 0x83, 0xef, 0xf1, 0xf2, 0x33, 0x78, 0x78, 0xb3, 0x52, + 0x04, 0x0b, 0x62, 0x16, 0x22, 0x58, 0xc0, 0x2c, 0xbe, 0x8c, 0xef, 0xab, 0x7a, 0x90, 0xd7, 0x83, 0xdd, 0x77, 0xaf, + 0x21, 0xc8, 0x64, 0x91, 0xd5, 0xcf, 0xe0, 0x89, 0x49, 0x05, 0xa1, 0x53, 0x39, 0x53, 0x68, 0xf8, 0x21, 0x68, 0x98, + 0x0c, 0xec, 0xc4, 0xf0, 0x2e, 0x00, 0x94, 0xc4, 0xaf, 0xe9, 0x41, 0x7e, 0x2b, 0x52, 0x27, 0x8b, 0xc4, 0xc5, 0xca, + 0xe5, 0x0c, 0xd8, 0x35, 0x5a, 0x2c, 0x33, 0x0c, 0xb5, 0x0b, 0x03, 0x60, 0xb9, 0xae, 0x61, 0xe8, 0x4e, 0xc0, 0xd2, + 0x05, 0x99, 0x98, 0xeb, 0x5a, 0x30, 0xae, 0x97, 0x71, 0xa2, 0x17, 0x90, 0x17, 0xe2, 0x77, 0x14, 0x54, 0xc1, 0x63, + 0xc2, 0xa7, 0x31, 0xb2, 0x8a, 0x38, 0xf5, 0xc6, 0x08, 0x15, 0x3a, 0x0d, 0x98, 0x61, 0x44, 0xfd, 0xf4, 0x8c, 0xb0, + 0x71, 0xb2, 0x10, 0x7e, 0xb3, 0x34, 0xcd, 0xc1, 0xb3, 0x75, 0x94, 0x9f, 0x3f, 0x5b, 0xa7, 0x79, 0xff, 0xd9, 0xda, + 0x97, 0xb6, 0x02, 0xfa, 0x95, 0x4e, 0x86, 0x02, 0x03, 0x04, 0xc3, 0x20, 0xbf, 0x2d, 0x3c, 0x77, 0x8a, 0xf9, 0xc2, + 0x2e, 0xa3, 0x72, 0x0d, 0x55, 0xf7, 0x7d, 0xae, 0xa0, 0x5f, 0x24, 0xc1, 0xdc, 0x4f, 0x1e, 0x48, 0x9f, 0x6f, 0xa9, + 0x4a, 0x7f, 0x53, 0xd7, 0x08, 0xd1, 0x13, 0x00, 0x08, 0xe7, 0xeb, 0xda, 0xb7, 0xb2, 0x8c, 0xf1, 0xd9, 0x4a, 0xa5, + 0x26, 0x7c, 0xeb, 0x56, 0x7f, 0xc9, 0x9c, 0x31, 0xcb, 0xfc, 0x20, 0xa4, 0x26, 0x3d, 0x91, 0xad, 0xbe, 0x36, 0xbd, + 0xb4, 0x3c, 0xbd, 0xa8, 0xbc, 0x7f, 0x70, 0x32, 0x74, 0x05, 0xd0, 0xb8, 0x71, 0x66, 0x98, 0xc5, 0xaa, 0x79, 0x45, + 0xe9, 0xdd, 0x7f, 0x75, 0x39, 0x18, 0x2c, 0x47, 0x04, 0xcb, 0xc1, 0xa2, 0x51, 0x3c, 0x66, 0x7f, 0x7b, 0x7f, 0x21, + 0xd3, 0x66, 0x81, 0x04, 0x68, 0xc0, 0x37, 0x66, 0x8a, 0xf4, 0x43, 0x82, 0xb4, 0x03, 0x25, 0xb8, 0xd2, 0xe4, 0x16, + 0x4a, 0x72, 0x5d, 0x3b, 0xa7, 0xb1, 0xb3, 0x31, 0x8d, 0xba, 0x1f, 0x63, 0xab, 0x24, 0x3f, 0x3d, 0xa0, 0xda, 0x74, + 0xdb, 0x51, 0x25, 0x00, 0x43, 0x02, 0x33, 0x2c, 0xa0, 0x00, 0x19, 0x3e, 0xfb, 0x5e, 0xc1, 0x50, 0x38, 0x73, 0x94, + 0xb3, 0x7b, 0xe7, 0x65, 0x52, 0x05, 0x5b, 0xe9, 0x67, 0xa7, 0x98, 0xb3, 0x0b, 0xee, 0x6b, 0x88, 0xf2, 0x71, 0x7a, + 0x40, 0x8f, 0x5a, 0xe5, 0x44, 0x14, 0x9d, 0x08, 0xd6, 0xae, 0xcb, 0x3b, 0x78, 0xd4, 0x51, 0x81, 0x14, 0xf1, 0x50, + 0xea, 0xe7, 0xba, 0x36, 0xe7, 0xa4, 0x11, 0x0f, 0x27, 0x04, 0xb1, 0x06, 0x5c, 0x38, 0xbb, 0xba, 0x36, 0xf7, 0x57, + 0x38, 0x73, 0xf1, 0xc6, 0x5f, 0x19, 0x1e, 0x7f, 0x55, 0x9c, 0xb5, 0xb4, 0x7c, 0xd6, 0x46, 0x7c, 0x71, 0xc1, 0x91, + 0x40, 0x72, 0xd6, 0x33, 0x54, 0xd0, 0x36, 0x2c, 0xee, 0x4c, 0x2c, 0xee, 0x78, 0xc3, 0xe2, 0x8e, 0xb7, 0x2c, 0x6e, + 0xc8, 0x17, 0x52, 0x93, 0xa0, 0x4b, 0xd0, 0x39, 0x4c, 0x02, 0x8f, 0x13, 0x1a, 0x5d, 0x7e, 0xce, 0x10, 0x4e, 0x76, + 0x1a, 0x82, 0x71, 0xd4, 0x06, 0x58, 0x35, 0xc1, 0x45, 0x01, 0x44, 0x7d, 0xe2, 0xf2, 0xd4, 0x89, 0x79, 0x43, 0x0e, + 0x4e, 0x23, 0xac, 0xce, 0x17, 0x76, 0x29, 0xe5, 0x17, 0x37, 0x66, 0x1b, 0x66, 0x3a, 0xdb, 0x32, 0xd3, 0x51, 0xe9, + 0xe8, 0xf2, 0x69, 0xd3, 0x21, 0x54, 0x27, 0x05, 0x7b, 0x10, 0x0c, 0x46, 0x71, 0xcb, 0x94, 0xf7, 0xe1, 0x66, 0x1c, + 0xab, 0xec, 0xa8, 0x85, 0x9f, 0xa6, 0xf7, 0x71, 0x02, 0x1a, 0x17, 0xe8, 0xe6, 0x71, 0x5b, 0x6a, 0x1e, 0x44, 0x3c, + 0x98, 0xcb, 0xc6, 0xcd, 0x54, 0xbc, 0x57, 0xb7, 0x54, 0xab, 0xd3, 0xa1, 0x1a, 0x0b, 0x3f, 0xcb, 0x58, 0x82, 0x40, + 0xf7, 0x21, 0xea, 0xf7, 0xff, 0x93, 0x6d, 0xd6, 0x80, 0x43, 0x42, 0x05, 0xab, 0x23, 0x86, 0x5e, 0x00, 0x6d, 0x95, + 0x88, 0x8b, 0x58, 0x09, 0x0c, 0x97, 0x48, 0xc0, 0xff, 0x84, 0xc7, 0xd5, 0x48, 0x14, 0xd7, 0x25, 0xef, 0xc8, 0x74, + 0x16, 0xfe, 0xf8, 0x03, 0x28, 0xf6, 0x8c, 0x96, 0x05, 0x46, 0xba, 0x6a, 0x18, 0xb8, 0x84, 0x88, 0xbd, 0x51, 0x81, + 0x24, 0x11, 0x4b, 0x72, 0x13, 0x28, 0xf0, 0x9e, 0xf4, 0xed, 0xc9, 0xcd, 0xba, 0x95, 0x1f, 0x4c, 0x03, 0xb3, 0x86, + 0x35, 0x01, 0xb5, 0x85, 0xfd, 0x33, 0xc9, 0x73, 0x85, 0x96, 0x77, 0x64, 0x82, 0xe4, 0xf7, 0x1a, 0xf2, 0x99, 0xba, + 0x82, 0xa1, 0x1d, 0x24, 0x70, 0x6b, 0x5d, 0xbb, 0x37, 0xf9, 0xf3, 0x29, 0xfe, 0xf2, 0x6e, 0xf2, 0xe7, 0x43, 0xfc, + 0xd5, 0xba, 0xc1, 0xcc, 0x75, 0x0d, 0x8c, 0xbc, 0x32, 0x67, 0xfd, 0xac, 0xb4, 0x9f, 0xc8, 0xfe, 0xec, 0x11, 0xdb, + 0x86, 0x2f, 0xf0, 0xd3, 0x67, 0xeb, 0x14, 0x3c, 0x2e, 0xd5, 0x39, 0x44, 0x4e, 0x62, 0xe6, 0x8d, 0xe5, 0xd3, 0x0d, + 0xe5, 0x43, 0xf3, 0xbf, 0x7c, 0xf1, 0xe3, 0x2e, 0x89, 0x8b, 0x3b, 0xa5, 0x2c, 0x86, 0xb8, 0x1d, 0x06, 0x91, 0x9f, + 0x3c, 0xdc, 0x12, 0x7b, 0x61, 0x08, 0xda, 0x5d, 0x8a, 0x57, 0x88, 0xbc, 0x2c, 0xab, 0xbb, 0x32, 0x45, 0xc0, 0xfb, + 0xc0, 0x2f, 0xfa, 0xfe, 0xdf, 0x13, 0x85, 0x6c, 0x2b, 0x31, 0xa0, 0x7c, 0x41, 0x4a, 0x1f, 0xba, 0x7d, 0xb6, 0x36, + 0x58, 0xbd, 0x9b, 0xca, 0x6c, 0x2b, 0x74, 0x21, 0x2c, 0x0f, 0x32, 0xb3, 0xf3, 0x71, 0xd0, 0x45, 0x7d, 0xd6, 0x30, + 0x5e, 0xd9, 0xcf, 0xd6, 0xd9, 0xb9, 0x3e, 0xf7, 0x93, 0x4f, 0x6c, 0x6c, 0x8f, 0x82, 0x64, 0x14, 0x32, 0xbd, 0xab, + 0x0f, 0x43, 0x3f, 0xfa, 0xc4, 0x1f, 0xed, 0x78, 0x99, 0xa1, 0x86, 0x7a, 0x27, 0xef, 0x2b, 0x60, 0x42, 0x22, 0x3b, + 0x24, 0x56, 0x1b, 0xa0, 0xa0, 0xbd, 0x96, 0x02, 0xaf, 0x82, 0x50, 0x2c, 0x6a, 0x59, 0x60, 0x60, 0x09, 0x4a, 0x73, + 0xf0, 0x58, 0xb5, 0x74, 0x5c, 0x2f, 0xdd, 0x52, 0xa7, 0x4a, 0xc2, 0x4a, 0x99, 0x72, 0xf1, 0x16, 0x7b, 0xf8, 0xfd, + 0x9f, 0xa3, 0x64, 0xd8, 0xfb, 0x7f, 0x4e, 0xf6, 0xf2, 0x65, 0x33, 0x84, 0x52, 0x9b, 0x3c, 0x25, 0x1e, 0xf1, 0x71, + 0x4e, 0x60, 0x6e, 0xfe, 0xb4, 0xda, 0xd8, 0x4f, 0xd3, 0xe5, 0x9c, 0x8d, 0x49, 0x33, 0x78, 0x5e, 0x0c, 0xaa, 0xcc, + 0x59, 0xa8, 0x03, 0xfb, 0x75, 0xd9, 0x3a, 0x3e, 0x7c, 0x0d, 0x16, 0x0b, 0x40, 0x50, 0xc6, 0x93, 0x89, 0x5e, 0xf0, + 0xf8, 0x3b, 0x9a, 0x79, 0x87, 0xbf, 0x2e, 0x7f, 0x78, 0xeb, 0xfe, 0x20, 0x1b, 0x47, 0x40, 0x18, 0x0b, 0xf5, 0x2b, + 0xa7, 0x8b, 0x95, 0xf1, 0x8a, 0x19, 0x4d, 0xfc, 0x68, 0xf3, 0x74, 0xae, 0x4b, 0x5b, 0x7c, 0xc1, 0xd8, 0x18, 0x08, + 0x6e, 0xab, 0x56, 0x7a, 0x1b, 0xb2, 0x3b, 0x26, 0x55, 0xbb, 0xf5, 0x8f, 0x35, 0xb4, 0xc0, 0xd8, 0x73, 0x5c, 0x65, + 0xcc, 0xa9, 0x3a, 0x65, 0x4a, 0x03, 0x9c, 0x03, 0x9f, 0xb9, 0x7a, 0xc4, 0x2a, 0x47, 0x6a, 0x60, 0xe9, 0xca, 0x00, + 0x36, 0x8e, 0xec, 0x7c, 0x43, 0x79, 0x17, 0x13, 0x4f, 0x37, 0x8f, 0xcd, 0xf2, 0xcc, 0x2e, 0xc4, 0xea, 0xe6, 0x70, + 0x0a, 0xe1, 0xe4, 0x19, 0x85, 0x38, 0x64, 0x13, 0xc4, 0x9a, 0x84, 0x64, 0x3a, 0x49, 0x5f, 0x84, 0xb5, 0x23, 0x9a, + 0xfd, 0x0a, 0x39, 0x54, 0xe3, 0xda, 0x68, 0xe5, 0x99, 0x0f, 0x31, 0xa1, 0x6b, 0xc4, 0xd2, 0x74, 0x23, 0xc0, 0xe4, + 0xa2, 0x5b, 0x7a, 0x51, 0xbb, 0x0c, 0x8f, 0xa2, 0xdc, 0x72, 0x2d, 0x20, 0x09, 0x70, 0x82, 0xd5, 0x6f, 0xe1, 0xf5, + 0x72, 0x3b, 0xe7, 0xf6, 0x2a, 0xc9, 0x74, 0xa8, 0x73, 0x5b, 0x82, 0x4d, 0xef, 0xef, 0x75, 0x3e, 0xa8, 0xd2, 0x35, + 0xdd, 0x38, 0x34, 0xa3, 0x84, 0x7a, 0x6b, 0xe2, 0x22, 0xec, 0x40, 0x8c, 0xa9, 0x82, 0x5f, 0xd9, 0x64, 0xc2, 0x46, + 0x59, 0x6a, 0x0a, 0xe1, 0x91, 0x8c, 0x1e, 0x0b, 0x5e, 0x43, 0x4f, 0xfa, 0xfa, 0x4f, 0xe0, 0x43, 0x2f, 0x82, 0x2c, + 0xf1, 0x01, 0x09, 0x9e, 0xa9, 0x19, 0x4c, 0xd4, 0x63, 0x19, 0x44, 0xfc, 0x2b, 0x90, 0x1c, 0xbc, 0xa1, 0x1c, 0x87, + 0xc6, 0xef, 0x9f, 0x62, 0x5f, 0xc4, 0xd2, 0xaa, 0x65, 0x3b, 0x2a, 0xda, 0x76, 0x7c, 0xd7, 0xde, 0x0f, 0x1d, 0xcf, + 0xcd, 0x75, 0x0b, 0x7c, 0xb7, 0x3e, 0xed, 0x7b, 0xe8, 0xb1, 0x55, 0x1b, 0x5a, 0x2d, 0xa3, 0xc7, 0xb4, 0x6b, 0x79, + 0xaf, 0x3c, 0xdd, 0x22, 0x93, 0x39, 0x05, 0xb7, 0x8d, 0xe2, 0x3b, 0x96, 0x7c, 0xf1, 0x54, 0xca, 0x9d, 0xef, 0x37, + 0x9e, 0x23, 0xcf, 0x05, 0x24, 0x9c, 0xc5, 0x8b, 0x47, 0x4c, 0xa1, 0xad, 0x5b, 0xfa, 0x28, 0x8c, 0x53, 0xa6, 0xce, + 0x81, 0x84, 0x20, 0x5f, 0x38, 0x89, 0x9f, 0xdf, 0xbf, 0xfd, 0xf0, 0x41, 0xb7, 0x30, 0x13, 0x68, 0xaa, 0xf6, 0xce, + 0x37, 0xd4, 0x0e, 0xec, 0xdf, 0xb8, 0xef, 0xe8, 0x86, 0x21, 0xa6, 0xb6, 0xbc, 0xe7, 0xa8, 0xac, 0xb6, 0xe5, 0xf8, + 0xcd, 0xc3, 0xbf, 0x4c, 0x9c, 0xe8, 0x5e, 0xf3, 0x6a, 0xc0, 0x0d, 0xdb, 0xaf, 0xb7, 0x52, 0xc9, 0x3c, 0x88, 0x6e, + 0x1b, 0x4a, 0xfd, 0x55, 0x43, 0x29, 0xb0, 0x72, 0x35, 0x5c, 0xb5, 0x8c, 0xe7, 0x0a, 0x69, 0x00, 0x89, 0x9c, 0x77, + 0x81, 0x4b, 0xe1, 0xa7, 0xbe, 0x60, 0xd0, 0x3c, 0x92, 0x7b, 0x75, 0xd4, 0x0d, 0xc5, 0x9c, 0x09, 0x92, 0xb0, 0x1d, + 0x85, 0x60, 0xf0, 0xc7, 0x54, 0xad, 0x5c, 0x99, 0x6c, 0x94, 0xe6, 0xba, 0x4a, 0x27, 0x44, 0xde, 0xde, 0x66, 0x6c, + 0xbe, 0x60, 0x89, 0x9f, 0x2d, 0x13, 0x76, 0x1b, 0xc6, 0xf7, 0x4f, 0x0a, 0x73, 0xfa, 0x1d, 0x95, 0x67, 0xc1, 0x74, + 0x26, 0x6b, 0x9f, 0x1b, 0xac, 0x2f, 0x17, 0x70, 0xeb, 0x07, 0xf2, 0xff, 0xfc, 0xdb, 0x71, 0xfe, 0xf3, 0xef, 0x9d, + 0x55, 0xa1, 0xfb, 0x7c, 0x60, 0x65, 0xfd, 0x3d, 0xf6, 0x45, 0xf3, 0x97, 0xca, 0x30, 0x6f, 0xae, 0x53, 0x5b, 0x04, + 0x78, 0x5f, 0x5b, 0x82, 0x5a, 0x61, 0x79, 0xdf, 0x3c, 0x6a, 0x60, 0x30, 0xaf, 0x9d, 0x23, 0x83, 0x4a, 0x5f, 0x34, + 0xb4, 0x81, 0xd9, 0xdd, 0x6b, 0x45, 0x7e, 0x3f, 0x84, 0x77, 0xcd, 0xe1, 0x0b, 0x87, 0xcf, 0xe5, 0x92, 0xaf, 0x07, + 0x03, 0x99, 0x5b, 0x4e, 0x6d, 0x0a, 0x26, 0xfe, 0xe7, 0xb5, 0x12, 0x7e, 0x79, 0x76, 0x5d, 0x93, 0x7c, 0xef, 0xfb, + 0xaf, 0x07, 0x68, 0x8c, 0x76, 0x3a, 0x4c, 0x0a, 0x62, 0x65, 0x23, 0x6a, 0x23, 0x63, 0xf2, 0x5a, 0xa7, 0x35, 0xbc, + 0x06, 0xa5, 0x98, 0x70, 0x2c, 0x1f, 0x98, 0xd6, 0xeb, 0x01, 0x17, 0x2c, 0x71, 0xfb, 0xd7, 0x6e, 0x75, 0x6b, 0x73, + 0xb1, 0x6c, 0x09, 0xe8, 0x96, 0x46, 0xfa, 0x1f, 0xac, 0xcc, 0x0a, 0x39, 0x1e, 0x0a, 0xf8, 0x41, 0xa2, 0x30, 0xc8, + 0x31, 0xdf, 0xc9, 0xbb, 0x4d, 0x36, 0x62, 0x3f, 0xef, 0xb6, 0x11, 0xbb, 0xda, 0xcb, 0x46, 0xec, 0xe7, 0xaf, 0x6e, + 0x23, 0xf6, 0x4e, 0xb5, 0x11, 0x83, 0x45, 0x7c, 0xcb, 0xf6, 0x32, 0xdc, 0x12, 0x56, 0x1b, 0xf1, 0x7d, 0xda, 0xf7, + 0x38, 0x49, 0x9b, 0x8e, 0x66, 0x0c, 0x64, 0x04, 0x7c, 0x55, 0xc2, 0x78, 0x0a, 0x46, 0x5c, 0x7f, 0xbc, 0xb9, 0x55, + 0x18, 0x4f, 0x55, 0x63, 0xab, 0x88, 0x47, 0x7c, 0x2d, 0xa2, 0x38, 0x91, 0x81, 0x93, 0x6b, 0x89, 0x98, 0x4f, 0xf6, + 0xa1, 0xa9, 0x64, 0xb5, 0x96, 0xd6, 0x6b, 0x2d, 0x61, 0x02, 0xd5, 0x45, 0xeb, 0x29, 0xd9, 0xb0, 0xf5, 0x52, 0xc4, + 0xb6, 0x50, 0x7b, 0x90, 0x56, 0xc2, 0x14, 0x27, 0x62, 0xad, 0xff, 0xba, 0xf2, 0xbe, 0xbf, 0xf6, 0x7a, 0x6d, 0x0f, + 0x9c, 0xb3, 0x81, 0xc3, 0xc4, 0x02, 0xb7, 0xd7, 0x6e, 0x43, 0xc1, 0xbd, 0x52, 0xd0, 0x82, 0x82, 0x40, 0x29, 0xe8, + 0x40, 0xc1, 0x48, 0x29, 0x38, 0x82, 0x82, 0xb1, 0x52, 0x70, 0x0c, 0x05, 0x77, 0x7a, 0x7e, 0x1d, 0xc9, 0xe1, 0x1e, + 0x9b, 0x37, 0x16, 0x31, 0x15, 0xa2, 0xec, 0xd8, 0xf2, 0xc0, 0x6a, 0xca, 0x9f, 0x76, 0x63, 0x8b, 0xa4, 0x8b, 0xdd, + 0xc4, 0xba, 0x9f, 0x31, 0x0a, 0x14, 0xfd, 0x06, 0xef, 0x1c, 0x27, 0x8b, 0xc1, 0x6e, 0x5a, 0x04, 0x60, 0x10, 0x70, + 0xd0, 0x74, 0x13, 0x04, 0x46, 0x3d, 0xb9, 0x72, 0x22, 0x88, 0x85, 0xb2, 0x96, 0xc5, 0x3b, 0xfa, 0x9c, 0x2d, 0xb7, + 0x40, 0x61, 0x71, 0x62, 0xa8, 0x52, 0xc9, 0xaf, 0x61, 0x77, 0xf0, 0x86, 0x0d, 0x97, 0x53, 0xed, 0x32, 0x9e, 0xee, + 0x34, 0x21, 0x50, 0x5f, 0xc1, 0x28, 0x75, 0x52, 0xbf, 0xd8, 0x62, 0x5b, 0xf2, 0x6f, 0xd1, 0x63, 0x5e, 0xae, 0x9f, + 0xc1, 0xd8, 0xb4, 0x8c, 0x0c, 0x58, 0xe0, 0x3b, 0x00, 0x23, 0x45, 0x87, 0x7f, 0x09, 0x70, 0x56, 0x9e, 0xaf, 0x7c, + 0x65, 0x3c, 0x67, 0x3f, 0xb2, 0x34, 0xf5, 0xa7, 0xa2, 0x7e, 0x7d, 0x9c, 0x60, 0xb4, 0x23, 0xf9, 0x2f, 0x04, 0x20, + 0x48, 0xf2, 0x82, 0x9a, 0x6d, 0x46, 0x12, 0xdf, 0x6b, 0x60, 0xfd, 0x03, 0x1b, 0xaa, 0xb0, 0x53, 0x08, 0x1c, 0x58, + 0xc2, 0xb2, 0x45, 0x01, 0x1c, 0xfe, 0x3b, 0x16, 0x56, 0x0b, 0x33, 0x7f, 0x5a, 0x2d, 0xa2, 0x7d, 0x90, 0xab, 0x63, + 0x93, 0x0a, 0xfd, 0x52, 0xe1, 0x97, 0x68, 0xa8, 0xc3, 0x78, 0xfa, 0x87, 0xaa, 0xa7, 0xb7, 0x98, 0x15, 0x7c, 0x88, + 0xac, 0x20, 0x1b, 0x38, 0x08, 0x63, 0xcd, 0x01, 0x10, 0x76, 0xa3, 0x6c, 0x66, 0xa3, 0x6b, 0x99, 0xd1, 0x8a, 0x4c, + 0xcb, 0xc1, 0xb5, 0x5d, 0x57, 0x1d, 0x6a, 0xbb, 0xc9, 0x74, 0xe8, 0x1b, 0x5e, 0xeb, 0xd8, 0x12, 0x7f, 0x8e, 0xdb, + 0x31, 0x73, 0xec, 0x41, 0x1b, 0x07, 0x77, 0xeb, 0x49, 0x1c, 0x65, 0xf6, 0xc4, 0x9f, 0x07, 0xe1, 0x43, 0x77, 0x1e, + 0x47, 0x71, 0xba, 0xf0, 0x47, 0xac, 0x57, 0x30, 0xd4, 0x3d, 0x0c, 0xd5, 0xc0, 0xbd, 0x05, 0x3d, 0xa7, 0x95, 0xb0, + 0x39, 0xb5, 0x96, 0x91, 0x18, 0x26, 0x21, 0x5b, 0xe5, 0xfc, 0xf3, 0xa5, 0xca, 0x54, 0x15, 0xb7, 0x1c, 0xb5, 0x00, + 0x8a, 0x94, 0x87, 0x79, 0x80, 0xe0, 0x46, 0xbd, 0x85, 0x3f, 0xc6, 0xc8, 0x84, 0x4e, 0xab, 0x93, 0xb0, 0xb9, 0xe6, + 0x74, 0x36, 0x76, 0x9e, 0xc4, 0xf7, 0x67, 0x30, 0x5a, 0x6c, 0x6c, 0xa7, 0x2c, 0x9c, 0xe0, 0x1b, 0x1b, 0x3d, 0x4b, + 0x44, 0x3f, 0x36, 0x32, 0xe2, 0xd0, 0x1b, 0x9b, 0xf7, 0xe0, 0x75, 0xb7, 0xa5, 0xb9, 0xbd, 0x79, 0x10, 0xd9, 0x34, + 0x9d, 0x63, 0x77, 0xa1, 0xf4, 0xa5, 0xc2, 0xcf, 0x5c, 0x63, 0x75, 0x4f, 0x73, 0x7b, 0xc0, 0xac, 0x4d, 0xc2, 0xf8, + 0xbe, 0x3b, 0x0b, 0xc6, 0x63, 0x16, 0xf5, 0x70, 0xcc, 0xb2, 0x90, 0x85, 0x61, 0xb0, 0x48, 0x83, 0xb4, 0x37, 0xf7, + 0x57, 0xbc, 0xd7, 0xc3, 0x4d, 0xbd, 0xb6, 0x79, 0xaf, 0xed, 0xbd, 0x7b, 0x55, 0xba, 0x01, 0x2f, 0x16, 0xea, 0x87, + 0x0f, 0xad, 0xa3, 0xb9, 0x95, 0x79, 0xee, 0xdd, 0xeb, 0x22, 0x61, 0xeb, 0xb9, 0x9f, 0x4c, 0x83, 0xa8, 0xeb, 0xe6, + 0xce, 0xdd, 0x9a, 0x36, 0xc6, 0xd3, 0x93, 0x93, 0x93, 0xdc, 0x19, 0x8b, 0x27, 0x77, 0x3c, 0xce, 0x9d, 0x91, 0x78, + 0x9a, 0x4c, 0x5c, 0x77, 0x32, 0xc9, 0x9d, 0x40, 0x14, 0xb4, 0x5b, 0xa3, 0x71, 0xbb, 0x95, 0x3b, 0xf7, 0x4a, 0x8d, + 0xdc, 0x61, 0xfc, 0x29, 0x61, 0xe3, 0x1e, 0x6e, 0x24, 0x32, 0x2b, 0xed, 0x1e, 0xbb, 0x6e, 0x8e, 0x18, 0xe0, 0xba, + 0x84, 0x9b, 0x50, 0xd6, 0x73, 0xb3, 0xde, 0xbb, 0xa6, 0x56, 0x7c, 0x6e, 0x34, 0x6a, 0xac, 0x37, 0xf6, 0x93, 0x4f, + 0x37, 0x9a, 0x32, 0x0b, 0xdf, 0xa7, 0x6a, 0x6b, 0x01, 0x06, 0x7b, 0xd5, 0x85, 0x90, 0x5d, 0xbd, 0x61, 0x9c, 0xc0, + 0x99, 0x4d, 0xfc, 0x71, 0xb0, 0x4c, 0xbb, 0x5e, 0x6b, 0xb1, 0x12, 0x45, 0x7c, 0xaf, 0x17, 0x05, 0x78, 0xf6, 0xba, + 0x69, 0x1c, 0x06, 0x63, 0x51, 0xb4, 0xe9, 0x2c, 0x79, 0x2d, 0xb3, 0x87, 0x0e, 0xeb, 0x01, 0x86, 0x5d, 0xf0, 0xc3, + 0x50, 0x73, 0xda, 0xa9, 0xc6, 0xfc, 0x14, 0xe5, 0xcb, 0x9a, 0x9b, 0x12, 0x5c, 0xd0, 0x39, 0xdd, 0x3b, 0x5c, 0xac, + 0xe4, 0x9e, 0xf7, 0x8e, 0x16, 0xab, 0xfc, 0xdb, 0x39, 0x1b, 0x07, 0xbe, 0x66, 0x14, 0xbb, 0xc9, 0x73, 0x41, 0x06, + 0x6d, 0xae, 0x37, 0x6c, 0x53, 0x71, 0x2c, 0x20, 0xb4, 0xe1, 0x93, 0x60, 0xbe, 0x88, 0x93, 0xcc, 0x8f, 0xb2, 0x3c, + 0x1f, 0xdc, 0xe4, 0x79, 0xef, 0x2a, 0x30, 0xae, 0xff, 0x61, 0xd0, 0x3d, 0x4d, 0x3a, 0x9b, 0xdc, 0xbc, 0xb1, 0xde, + 0x32, 0xd5, 0x66, 0x04, 0xae, 0x31, 0xb4, 0x17, 0x51, 0x2b, 0xd3, 0x2d, 0x59, 0xaf, 0x4c, 0x40, 0x96, 0xd5, 0xc9, + 0x06, 0xa5, 0x5c, 0x05, 0x6f, 0x20, 0xa8, 0xf0, 0x96, 0xf5, 0xaf, 0x14, 0xfb, 0x13, 0x20, 0x56, 0xb0, 0x32, 0xf9, + 0x15, 0x3c, 0xdb, 0x44, 0x33, 0x7e, 0xb7, 0x9b, 0x66, 0xfc, 0x25, 0xdb, 0x87, 0x66, 0xfc, 0xee, 0xab, 0xd3, 0x8c, + 0xcf, 0xea, 0x7e, 0x05, 0x17, 0x71, 0x5f, 0x97, 0x1a, 0x06, 0xb8, 0x9a, 0x12, 0x8a, 0xd8, 0x73, 0xf1, 0xbb, 0xdd, + 0x00, 0x44, 0x6f, 0x94, 0x83, 0x8e, 0x6e, 0x6e, 0x90, 0xc7, 0xbe, 0x8b, 0xfa, 0x7f, 0x4f, 0xd4, 0xe7, 0xc9, 0xa4, + 0xff, 0x26, 0x56, 0x0a, 0xe4, 0x13, 0x37, 0xbe, 0x28, 0x45, 0x57, 0xa0, 0x37, 0xc2, 0x0a, 0x13, 0xf3, 0x4f, 0x80, + 0x73, 0x36, 0x59, 0x1d, 0x8f, 0xa5, 0xf5, 0x59, 0xaf, 0x3c, 0x04, 0x43, 0x9a, 0x7c, 0x0a, 0x17, 0x9c, 0x9a, 0x28, + 0x71, 0xca, 0x32, 0xee, 0x33, 0xfb, 0xfd, 0xc3, 0xc5, 0xd8, 0xb8, 0x88, 0xcd, 0x3c, 0x48, 0xdf, 0x55, 0x1d, 0x60, + 0xb8, 0xee, 0xa7, 0xaf, 0x4e, 0x27, 0xe7, 0x16, 0x64, 0x6a, 0x82, 0x69, 0x78, 0x4d, 0xcd, 0xcf, 0x4b, 0x33, 0xed, + 0xaa, 0x0d, 0x79, 0xa2, 0xab, 0xda, 0x65, 0xcc, 0xbd, 0x0f, 0xd6, 0x9c, 0x02, 0xc4, 0xdc, 0x5d, 0xe8, 0x37, 0x3c, + 0xa6, 0xe6, 0xc1, 0x38, 0xcf, 0xcd, 0x9e, 0x00, 0x84, 0x72, 0xd1, 0xb2, 0x5d, 0x44, 0x5c, 0x7a, 0x2f, 0x6d, 0x1a, + 0xb8, 0x86, 0x90, 0xd4, 0x7f, 0x17, 0xa0, 0x50, 0xe7, 0xca, 0x42, 0x0e, 0x33, 0x5d, 0x23, 0xf0, 0x91, 0xa1, 0x85, + 0x32, 0x21, 0xd0, 0x00, 0x4b, 0xf8, 0x8b, 0x57, 0xa2, 0xa0, 0x6e, 0xc3, 0x49, 0xc0, 0x41, 0x8b, 0x00, 0xf0, 0xf2, + 0x17, 0x72, 0x6d, 0x42, 0x3b, 0xbc, 0x0e, 0x3e, 0xe4, 0xba, 0xa4, 0xfd, 0x70, 0xfb, 0x9d, 0x9d, 0x1e, 0x40, 0x83, + 0xb3, 0x8a, 0xe1, 0xc0, 0x0e, 0x0b, 0x45, 0x20, 0x25, 0xd2, 0x7b, 0xcb, 0x49, 0xef, 0xb5, 0x17, 0x6b, 0x11, 0x21, + 0x23, 0xf3, 0x17, 0x36, 0xb0, 0xf8, 0x88, 0x7b, 0x39, 0xc6, 0x53, 0x82, 0x71, 0xf4, 0x96, 0x29, 0xe0, 0x46, 0x64, + 0x54, 0x11, 0xff, 0xf4, 0x46, 0xcb, 0x24, 0x8d, 0x93, 0xee, 0x22, 0x0e, 0xa2, 0x8c, 0x25, 0x39, 0x82, 0xea, 0x1a, + 0xe1, 0x23, 0xc0, 0x73, 0xb3, 0x8e, 0x17, 0xfe, 0x28, 0xc8, 0x1e, 0xba, 0x2e, 0x27, 0x29, 0xdc, 0x1e, 0xa7, 0x0e, + 0xdc, 0xc6, 0xfa, 0x5d, 0x0e, 0xcd, 0x97, 0x48, 0xf8, 0x25, 0x75, 0x72, 0x46, 0xdd, 0xe6, 0x3d, 0xe5, 0x2d, 0xc5, + 0x08, 0x01, 0xf2, 0xc3, 0x4f, 0xec, 0x29, 0x60, 0x79, 0x58, 0x6a, 0x77, 0xcc, 0xa6, 0x16, 0x62, 0x6d, 0x90, 0xcb, + 0x8b, 0x3f, 0xa7, 0x63, 0x6a, 0x6e, 0x73, 0x31, 0x50, 0x3c, 0xe6, 0x3e, 0x23, 0xeb, 0xfa, 0x90, 0x51, 0xcb, 0xda, + 0xa7, 0xe6, 0x90, 0x4d, 0xe2, 0x84, 0x51, 0x3c, 0x59, 0xef, 0x64, 0xb1, 0xda, 0xbf, 0xfb, 0xed, 0xd3, 0x6f, 0xee, + 0x27, 0x8a, 0x33, 0x43, 0x74, 0x66, 0xee, 0xe8, 0xad, 0x7e, 0x9f, 0x01, 0x69, 0x48, 0x90, 0x1f, 0x51, 0xe8, 0xae, + 0xae, 0xae, 0xf7, 0x1a, 0xc3, 0x76, 0x2d, 0x62, 0x7e, 0xe7, 0x25, 0x2c, 0xf4, 0xb3, 0xe0, 0x4e, 0xd0, 0x8c, 0xed, + 0xa3, 0xc5, 0x4a, 0xac, 0x31, 0x5e, 0x78, 0x8f, 0x58, 0xa4, 0xca, 0x50, 0xc4, 0x22, 0x55, 0x8b, 0x71, 0x91, 0x7a, + 0xb5, 0xd9, 0x88, 0x48, 0x16, 0x95, 0x9b, 0xbe, 0xb3, 0x58, 0xa9, 0x57, 0x74, 0xd1, 0x4c, 0xde, 0xd4, 0xd5, 0x10, + 0x64, 0xf3, 0x60, 0x3c, 0x0e, 0x59, 0x5e, 0x5a, 0xe8, 0xf2, 0x5a, 0x2a, 0xc0, 0x91, 0x70, 0xf0, 0x87, 0x69, 0x1c, + 0x2e, 0x33, 0xd6, 0x0c, 0x2e, 0x02, 0x4e, 0xcb, 0x2d, 0x80, 0x83, 0xbf, 0xcb, 0x63, 0xed, 0x00, 0xb9, 0x0d, 0xdb, + 0xc4, 0xed, 0x41, 0xc4, 0x61, 0xbb, 0x5d, 0x1e, 0x3a, 0xbc, 0x92, 0x83, 0xb6, 0x1a, 0x26, 0x62, 0xc1, 0xb5, 0x44, + 0xd8, 0x5b, 0x73, 0x3c, 0x5e, 0x26, 0xa3, 0xae, 0xca, 0xa2, 0xbc, 0x3c, 0x99, 0x3f, 0xe6, 0x8c, 0xbd, 0x6a, 0x3e, + 0x63, 0xaf, 0xc4, 0x19, 0xdb, 0xbe, 0x33, 0x9f, 0x4e, 0x3c, 0xf8, 0xaf, 0x57, 0x4c, 0xa8, 0xeb, 0x6a, 0xed, 0xc5, + 0x4a, 0xf3, 0x16, 0x2b, 0xcd, 0x6e, 0x2d, 0x56, 0x1a, 0x76, 0x8d, 0xf6, 0x20, 0x96, 0xd3, 0x32, 0x2d, 0x57, 0x83, + 0x42, 0xf8, 0x73, 0x4b, 0xaf, 0xbc, 0x43, 0x78, 0x07, 0xad, 0x3a, 0xf5, 0x77, 0xad, 0xed, 0x47, 0x9d, 0xce, 0x92, + 0x40, 0xda, 0xa6, 0x93, 0xf9, 0xc3, 0x21, 0x1b, 0x77, 0x27, 0xf1, 0x68, 0x99, 0xfe, 0x8b, 0x8f, 0x9f, 0x03, 0x71, + 0x2b, 0x22, 0xa8, 0xf4, 0x23, 0x9a, 0x82, 0xa2, 0xe4, 0x8e, 0x89, 0x1e, 0xd6, 0x72, 0x9d, 0xba, 0x14, 0x1e, 0xb9, + 0xe5, 0x1c, 0x36, 0x6c, 0xf2, 0x66, 0x40, 0xff, 0x61, 0xab, 0xb4, 0x19, 0xc5, 0x7c, 0x01, 0x58, 0xb6, 0x82, 0xe3, + 0xf1, 0xd0, 0xe0, 0xab, 0xe9, 0x9e, 0x34, 0x0f, 0xf7, 0x5a, 0x7c, 0xe9, 0x46, 0x5c, 0x2a, 0xfc, 0xde, 0xe2, 0x8e, + 0x29, 0xdb, 0x7b, 0xdd, 0xb4, 0x47, 0x6a, 0xbd, 0x6e, 0xb9, 0x10, 0x8a, 0xba, 0x7b, 0x62, 0xf9, 0xa7, 0xaf, 0x0e, + 0xe1, 0x3f, 0xa2, 0xea, 0x7f, 0xc9, 0x9a, 0x08, 0xf5, 0x8b, 0xb2, 0x25, 0x38, 0x91, 0x4a, 0x48, 0x88, 0xef, 0x5f, + 0x7f, 0x32, 0x79, 0x5c, 0x83, 0xbd, 0x6b, 0x93, 0x29, 0x55, 0xb5, 0xf6, 0xf7, 0x71, 0x0c, 0xa9, 0x3b, 0xeb, 0xd5, + 0x05, 0x78, 0xc8, 0xd8, 0x3d, 0xeb, 0x43, 0x23, 0xc1, 0x47, 0x90, 0x16, 0x5f, 0xc7, 0x36, 0xc4, 0x4a, 0xbc, 0xdd, + 0xc4, 0x4a, 0xbc, 0xd9, 0xcd, 0x4a, 0xfc, 0x75, 0x2f, 0x56, 0xe2, 0xcd, 0x57, 0x67, 0x25, 0xde, 0xd6, 0x59, 0x89, + 0xab, 0x58, 0xd8, 0xcf, 0x5a, 0x17, 0x4b, 0xfe, 0xf3, 0x23, 0x29, 0xe5, 0x2e, 0xe3, 0x7e, 0xc7, 0xa5, 0x90, 0xc7, + 0x57, 0xbf, 0x9b, 0xb1, 0xc0, 0x8d, 0xf8, 0x1e, 0xcd, 0xc9, 0x0a, 0xd6, 0x82, 0x63, 0x76, 0xfc, 0x8e, 0x52, 0x1c, + 0xc6, 0xd1, 0xf4, 0x67, 0x50, 0xca, 0x82, 0x38, 0x30, 0x51, 0x5e, 0x04, 0xe9, 0xcf, 0xf1, 0x62, 0xb9, 0xb8, 0x80, + 0xbe, 0x3e, 0x06, 0x69, 0x30, 0x0c, 0x99, 0xf4, 0x44, 0x26, 0xf3, 0x37, 0x2e, 0x13, 0x07, 0x8b, 0x53, 0xf1, 0xd3, + 0x5f, 0x89, 0x9f, 0x68, 0x93, 0xca, 0x7f, 0x93, 0x5d, 0x9d, 0xde, 0xcc, 0x88, 0x08, 0x25, 0xa0, 0x32, 0xe8, 0xc7, + 0x33, 0x23, 0x57, 0xb1, 0xd9, 0x30, 0x4b, 0x61, 0xef, 0xb0, 0xb1, 0x1f, 0x56, 0x63, 0x6a, 0x96, 0xa6, 0x25, 0x43, + 0x70, 0xd5, 0xc5, 0xf0, 0xf3, 0x78, 0x99, 0xb2, 0x71, 0x7c, 0x1f, 0xe9, 0x56, 0x24, 0x9d, 0x0c, 0x40, 0xc3, 0x29, + 0xdb, 0x60, 0xf2, 0xc8, 0x0f, 0x48, 0x28, 0xc7, 0x89, 0xa1, 0x43, 0xee, 0xd2, 0xe5, 0xc2, 0x26, 0x55, 0xb3, 0x8d, + 0x53, 0xd4, 0x65, 0x96, 0xa3, 0x27, 0x86, 0x11, 0xf7, 0x1f, 0xd7, 0x52, 0x98, 0x6a, 0xc4, 0x0e, 0x97, 0x0a, 0xa7, + 0x46, 0x24, 0x84, 0x8b, 0x22, 0x0e, 0x46, 0xc3, 0xc2, 0xf1, 0x37, 0xe4, 0xba, 0x5a, 0xbc, 0x85, 0x28, 0x22, 0xf9, + 0x92, 0xaf, 0x07, 0x8f, 0x0a, 0x41, 0x8f, 0xaf, 0x15, 0x30, 0xbe, 0xbb, 0x63, 0x49, 0xe8, 0x3f, 0x18, 0x66, 0x1e, + 0x47, 0x3f, 0x02, 0x00, 0xde, 0xc4, 0xf7, 0x91, 0x5a, 0x01, 0x93, 0xb5, 0x34, 0xec, 0xa5, 0xc6, 0xf8, 0x25, 0xe0, + 0xb8, 0xa2, 0x8c, 0x00, 0xd2, 0xe4, 0x4e, 0xd9, 0xdf, 0x2d, 0xfa, 0xf7, 0x1f, 0x66, 0x6e, 0x5d, 0xc6, 0xf2, 0x43, + 0x7f, 0x5b, 0xec, 0xf1, 0x99, 0xe7, 0xcf, 0x9f, 0x6c, 0x9e, 0x76, 0x39, 0x3d, 0x7b, 0x43, 0x6b, 0x73, 0xe3, 0x29, + 0x80, 0x51, 0x5c, 0xc5, 0xcb, 0xd1, 0x0c, 0x0d, 0x5d, 0xbf, 0xde, 0x7c, 0x33, 0xe8, 0x13, 0xb3, 0x94, 0xca, 0xa9, + 0x57, 0x8a, 0x0a, 0x28, 0xe0, 0xf7, 0xdf, 0x42, 0x00, 0xce, 0xff, 0x21, 0x18, 0xea, 0xbb, 0x86, 0x73, 0xf1, 0xc1, + 0xe3, 0x36, 0x6f, 0x0f, 0x92, 0x69, 0xf2, 0xd0, 0x16, 0x42, 0xb9, 0xd6, 0x8c, 0x64, 0xf2, 0x2a, 0xd0, 0xd4, 0x30, + 0x72, 0x9b, 0x22, 0xe4, 0x89, 0xaf, 0x30, 0x87, 0xd8, 0x74, 0xee, 0x68, 0x60, 0x31, 0x8e, 0xad, 0x2a, 0x48, 0x86, + 0x9b, 0x3c, 0x30, 0x44, 0x5f, 0xd5, 0x77, 0xf3, 0x20, 0xb2, 0x30, 0x0a, 0x7c, 0xfd, 0x8d, 0xbf, 0x82, 0x38, 0xc8, + 0x80, 0xdc, 0xaa, 0xaf, 0xa0, 0xd0, 0x52, 0xfd, 0xe6, 0x20, 0xd5, 0x93, 0xde, 0x08, 0x09, 0xa1, 0xc5, 0x1b, 0xfc, + 0x49, 0xd3, 0x34, 0x4d, 0xb2, 0x11, 0x9a, 0xe4, 0x23, 0xb0, 0x1c, 0xd9, 0x01, 0xd0, 0x96, 0xe4, 0x8b, 0x15, 0x95, + 0x00, 0x67, 0x80, 0x3a, 0x59, 0x51, 0xc0, 0x43, 0xfd, 0x75, 0x5c, 0x51, 0x20, 0x18, 0x7a, 0x08, 0xd3, 0xe6, 0x27, + 0x10, 0x11, 0xb8, 0xab, 0x21, 0xc3, 0x8e, 0x6f, 0xb9, 0x24, 0x58, 0x73, 0xe9, 0x71, 0xd0, 0x63, 0xcd, 0x31, 0xe1, + 0x22, 0x05, 0x0b, 0x82, 0xd6, 0xa1, 0x12, 0xe2, 0xd9, 0x62, 0x0d, 0xb8, 0x11, 0xf9, 0xa2, 0x55, 0x36, 0x67, 0xd1, + 0x52, 0xc7, 0x9c, 0x50, 0x18, 0xa3, 0x0f, 0xea, 0xbc, 0x21, 0x62, 0x0b, 0xb0, 0x4d, 0x73, 0xcb, 0x19, 0xdd, 0x85, + 0x29, 0x47, 0xa9, 0xbe, 0x35, 0xe2, 0x8a, 0xcd, 0x94, 0xe3, 0xb6, 0xea, 0x0d, 0xc1, 0x97, 0x34, 0xae, 0x3a, 0x72, + 0x91, 0x25, 0x34, 0xf4, 0x41, 0xd1, 0x31, 0xb8, 0xb8, 0x48, 0x80, 0xdd, 0xf0, 0xab, 0x8b, 0x26, 0x35, 0x32, 0x7e, + 0x45, 0x50, 0x94, 0x98, 0xf5, 0x6e, 0xf8, 0x38, 0x21, 0x30, 0xd1, 0xc6, 0x7e, 0x46, 0xb5, 0x7e, 0x36, 0x4c, 0xfa, + 0x13, 0x7b, 0xa0, 0x8b, 0x84, 0x40, 0xf5, 0x89, 0x3d, 0x80, 0xed, 0xdf, 0x5b, 0x90, 0xa6, 0xe8, 0x5b, 0xd0, 0xb5, + 0x05, 0xa1, 0xfe, 0x47, 0x10, 0xac, 0x6a, 0xcb, 0x01, 0x72, 0xf3, 0x2d, 0x58, 0x1c, 0x41, 0x0c, 0x59, 0x9d, 0xc5, + 0x21, 0xe6, 0x26, 0xfe, 0x46, 0x23, 0x8c, 0xed, 0x86, 0xa3, 0x61, 0xbe, 0xf0, 0x5c, 0xf7, 0xa0, 0x56, 0x1f, 0x04, + 0xd9, 0x4d, 0xb5, 0x4d, 0x2b, 0xeb, 0x7b, 0xae, 0x1d, 0xbc, 0x70, 0x5a, 0xbd, 0xda, 0x1d, 0xad, 0xc4, 0x92, 0x1c, + 0xa0, 0xf8, 0xeb, 0xec, 0xd9, 0xda, 0xa8, 0x1d, 0x48, 0xb3, 0x6a, 0x32, 0x8f, 0x63, 0xcb, 0xb9, 0xfc, 0x6b, 0x50, + 0xbf, 0xfa, 0x29, 0x92, 0x25, 0xe5, 0x35, 0x19, 0x40, 0x34, 0x64, 0x03, 0x8e, 0xd1, 0x9f, 0xb5, 0x97, 0x9a, 0x41, + 0xc7, 0xc7, 0x34, 0x07, 0x32, 0x5d, 0xb6, 0xf0, 0x29, 0x53, 0x3b, 0xa8, 0x7c, 0x31, 0xad, 0x62, 0x38, 0x1e, 0x77, + 0x95, 0x15, 0x1a, 0xbd, 0xad, 0xd4, 0x02, 0xf6, 0xbf, 0xe1, 0xfa, 0x74, 0x86, 0x10, 0x97, 0x00, 0x6a, 0x40, 0xec, + 0xf4, 0x9d, 0x1d, 0x2e, 0x17, 0xe5, 0xee, 0xca, 0x97, 0xe4, 0xfe, 0x9d, 0xe1, 0xa5, 0x83, 0x3a, 0x34, 0xd9, 0x5f, + 0xf3, 0x75, 0xf7, 0xc8, 0x2e, 0x59, 0x34, 0x2e, 0x77, 0x58, 0xb9, 0xbf, 0xf6, 0xef, 0xae, 0x84, 0x51, 0x20, 0xa9, + 0x40, 0xdc, 0x80, 0x51, 0xf2, 0x38, 0xc2, 0xcd, 0x4f, 0xc7, 0x2d, 0xd8, 0x8b, 0x8a, 0xc1, 0x06, 0x14, 0x11, 0x4c, + 0x36, 0x53, 0x84, 0xe2, 0x10, 0xb9, 0x1a, 0xdd, 0x82, 0x0d, 0x41, 0x88, 0x6e, 0xdc, 0x89, 0x99, 0xb0, 0x29, 0x2c, + 0xda, 0x04, 0x3c, 0x16, 0xe5, 0xbe, 0x52, 0xeb, 0x60, 0xb7, 0xd4, 0x3a, 0xdb, 0x25, 0xb5, 0x26, 0x77, 0xaa, 0xfb, + 0xc4, 0x5f, 0x28, 0x1e, 0x79, 0x82, 0x38, 0x57, 0x1d, 0xf3, 0x4a, 0xa2, 0x6e, 0xf4, 0xbe, 0x12, 0xad, 0x6a, 0xbd, + 0x91, 0x95, 0x20, 0x8a, 0xbf, 0x15, 0x06, 0x45, 0x28, 0xd4, 0x55, 0xd9, 0xf8, 0x55, 0x21, 0x1b, 0x27, 0xae, 0xa6, + 0x70, 0xa4, 0x11, 0xd4, 0xbf, 0xe2, 0xa4, 0x26, 0xb9, 0x83, 0xc2, 0x59, 0xad, 0x18, 0xa9, 0xe2, 0x7e, 0x55, 0x30, + 0x1a, 0x8a, 0x53, 0x9f, 0xe0, 0x32, 0xca, 0xbe, 0x7d, 0xe5, 0xaa, 0x85, 0xf7, 0x55, 0x51, 0x0e, 0x52, 0x77, 0x1c, + 0xb2, 0x2c, 0x56, 0xb7, 0x4d, 0xd9, 0xfd, 0x46, 0x7d, 0xad, 0x6c, 0x12, 0xe9, 0x27, 0x43, 0x00, 0x16, 0x62, 0xfa, + 0x8a, 0x5e, 0x5b, 0xda, 0x40, 0xe0, 0x20, 0x1b, 0xdc, 0xfa, 0x76, 0x4b, 0xe7, 0x29, 0x5f, 0x42, 0xa1, 0x85, 0x57, + 0x65, 0x10, 0x08, 0xdf, 0x9b, 0x75, 0xc3, 0x2d, 0x8f, 0x97, 0x3c, 0xbf, 0xdf, 0x41, 0xbc, 0xa8, 0xb9, 0xaa, 0x22, + 0x1f, 0x4f, 0xa6, 0x4d, 0xe6, 0xb9, 0x58, 0xb5, 0xde, 0x29, 0x09, 0x71, 0xd6, 0xdc, 0x33, 0xa6, 0x2c, 0xa3, 0xe7, + 0x35, 0xba, 0xe2, 0xbb, 0x7c, 0xeb, 0x24, 0xcb, 0x08, 0x63, 0xdb, 0xdb, 0x59, 0xe2, 0x8f, 0x3e, 0x29, 0x43, 0x16, + 0x72, 0x4e, 0x90, 0x01, 0x97, 0x35, 0x05, 0x3d, 0x1f, 0x43, 0x41, 0xb2, 0xae, 0xd3, 0x4a, 0x15, 0xe9, 0x4b, 0xf7, + 0xa9, 0xdb, 0xf6, 0x5f, 0x4d, 0x0e, 0x2b, 0x42, 0xd1, 0x56, 0xa7, 0x2c, 0x32, 0xdf, 0x30, 0x8e, 0x6c, 0xb6, 0x9c, + 0x0f, 0xd7, 0xaa, 0x6c, 0x55, 0x11, 0xb9, 0xd6, 0xc5, 0xac, 0xea, 0x67, 0x27, 0x93, 0x49, 0x59, 0xd0, 0xe8, 0x6a, + 0x87, 0x28, 0x2c, 0x7c, 0xea, 0xba, 0x6e, 0x75, 0xec, 0xdb, 0xc1, 0x6e, 0xa3, 0xdc, 0xf6, 0xa4, 0x71, 0xc4, 0x08, + 0xdb, 0x5d, 0xf0, 0xab, 0x83, 0x23, 0x77, 0x8a, 0x93, 0x5d, 0x32, 0x8b, 0xe8, 0x91, 0x31, 0x44, 0x90, 0xb1, 0x79, + 0xda, 0x1d, 0x31, 0xd4, 0xc1, 0x38, 0xca, 0x81, 0x46, 0xc3, 0x01, 0x7b, 0x0a, 0xa6, 0x22, 0x9e, 0xd8, 0x15, 0xae, + 0x86, 0xf2, 0xf0, 0x9a, 0xf0, 0x5e, 0x7c, 0x04, 0x0f, 0xca, 0xba, 0x2e, 0xd3, 0xc6, 0x69, 0x75, 0xdc, 0x3f, 0x97, + 0xea, 0x69, 0x70, 0x01, 0xae, 0x85, 0x42, 0x9b, 0xe4, 0xb3, 0xf8, 0xff, 0x52, 0xfe, 0xff, 0x6a, 0xb1, 0x2a, 0xdb, + 0x8f, 0x9c, 0x80, 0x44, 0xbb, 0x38, 0x2d, 0x34, 0xea, 0xa6, 0x3d, 0x20, 0xad, 0x0c, 0x26, 0xaa, 0x02, 0x1d, 0x94, + 0xf4, 0xa5, 0x04, 0x20, 0x0d, 0xe2, 0x77, 0xa4, 0x98, 0x61, 0x89, 0x0b, 0x11, 0x62, 0x91, 0xbe, 0x0e, 0xe6, 0x60, + 0xbd, 0x3c, 0x41, 0xfd, 0x41, 0x69, 0x4f, 0x80, 0x36, 0xbe, 0x36, 0xb7, 0xbd, 0xc4, 0xfd, 0x55, 0xbd, 0x96, 0xe8, + 0x18, 0x40, 0xe6, 0xc1, 0x21, 0x44, 0x43, 0x02, 0xad, 0xb2, 0xb9, 0x69, 0x94, 0xf2, 0xad, 0xaa, 0x67, 0x13, 0x03, + 0xc3, 0xee, 0x9a, 0xab, 0x50, 0xdf, 0x42, 0x5b, 0x00, 0x93, 0xe5, 0xdb, 0x0f, 0x9f, 0x6d, 0x58, 0x62, 0x75, 0x3f, + 0x7a, 0xb8, 0xe4, 0xb8, 0x7f, 0x6d, 0xbc, 0x3b, 0x53, 0x3a, 0xff, 0x28, 0x5f, 0xfc, 0x6b, 0xa3, 0x40, 0xef, 0xaa, + 0x24, 0xa1, 0xe3, 0xd6, 0xe2, 0x2d, 0x73, 0xaf, 0xda, 0xf3, 0x20, 0xda, 0xbf, 0xae, 0xbf, 0xda, 0xbb, 0x2e, 0x5c, + 0x18, 0x7b, 0x57, 0x86, 0x1b, 0x87, 0x2c, 0x17, 0xb2, 0xfe, 0x5f, 0x15, 0x81, 0xa2, 0xea, 0x75, 0xac, 0x63, 0x2b, + 0xa2, 0xf2, 0xaf, 0x96, 0x40, 0x7c, 0xee, 0x95, 0xe0, 0x41, 0x13, 0x39, 0xda, 0xf4, 0x63, 0xed, 0x44, 0x3b, 0x6e, + 0x6b, 0x47, 0xae, 0x4e, 0x5c, 0x58, 0x5f, 0xef, 0xb4, 0x0a, 0x6f, 0xc2, 0x43, 0x57, 0x3f, 0x3b, 0x9d, 0x8a, 0x4b, + 0x62, 0x12, 0x84, 0x21, 0xa1, 0x8a, 0x34, 0x4b, 0xe2, 0x4f, 0xac, 0xac, 0x66, 0xa1, 0x32, 0x6e, 0x04, 0xd2, 0x12, + 0x8f, 0x70, 0x76, 0x46, 0xfe, 0xa2, 0x8b, 0x67, 0x43, 0x2d, 0x04, 0x03, 0x4e, 0x2a, 0xc5, 0x4f, 0xc0, 0x1d, 0x3c, + 0xd4, 0xcf, 0x4e, 0x21, 0x84, 0xa1, 0x36, 0xee, 0xeb, 0x3f, 0xb6, 0x8e, 0x35, 0xaf, 0x73, 0x67, 0xb7, 0x47, 0xae, + 0xed, 0x39, 0x87, 0x9a, 0xeb, 0x1c, 0xd9, 0x2d, 0xe7, 0x58, 0x6b, 0x39, 0x1d, 0xf8, 0x77, 0xe4, 0x39, 0xaf, 0x34, + 0x17, 0x9e, 0x34, 0xcf, 0x69, 0xe3, 0xbf, 0x2d, 0xe7, 0xf8, 0xae, 0x4d, 0x37, 0xbd, 0x2f, 0xdd, 0xaa, 0x2a, 0xa3, + 0x00, 0x27, 0x10, 0xfd, 0xe0, 0xec, 0x74, 0x99, 0x32, 0x6d, 0xd5, 0xd7, 0x5f, 0xe9, 0xda, 0x2c, 0x61, 0x93, 0xbe, + 0xfe, 0xd4, 0x57, 0x4a, 0xbd, 0x93, 0xc6, 0xe2, 0xd6, 0x71, 0x63, 0x71, 0xfb, 0xa8, 0xb1, 0xf8, 0xb0, 0x53, 0x2e, + 0x3e, 0x98, 0xd2, 0x2b, 0x25, 0x83, 0xe0, 0xdc, 0xcf, 0x92, 0x60, 0x65, 0x78, 0x1a, 0xa0, 0x6b, 0x1b, 0xfe, 0x39, + 0x6e, 0x99, 0xb2, 0xd5, 0x10, 0x5a, 0x49, 0x68, 0x1c, 0x9f, 0x68, 0xde, 0xd1, 0x5f, 0x5a, 0x47, 0x23, 0xa8, 0x07, + 0xf9, 0x2e, 0xe1, 0xef, 0xae, 0x7d, 0x32, 0x72, 0x35, 0x68, 0xe8, 0xc1, 0x7f, 0xb3, 0x4e, 0x6b, 0x44, 0x0f, 0x2e, + 0xbc, 0xff, 0xe8, 0x1d, 0xa7, 0xae, 0xed, 0xc1, 0x7f, 0xbf, 0x49, 0x95, 0x3b, 0x28, 0xfc, 0xd5, 0x7e, 0x0f, 0x5d, + 0xad, 0x7d, 0x32, 0x6b, 0x39, 0xaf, 0xee, 0x8e, 0x9d, 0x93, 0x99, 0x77, 0xfc, 0x91, 0x9e, 0x42, 0xbb, 0xe5, 0xbc, + 0x82, 0xbf, 0x8f, 0x6d, 0x77, 0x66, 0x7b, 0xce, 0xc9, 0x5d, 0xdb, 0x69, 0x87, 0xf6, 0x91, 0x73, 0x02, 0x7f, 0xbf, + 0x01, 0x78, 0x01, 0xae, 0x3c, 0x41, 0xa9, 0x06, 0x1b, 0xa3, 0x62, 0xbf, 0xa1, 0x7e, 0xa4, 0x75, 0xa8, 0x75, 0x0e, + 0xff, 0x72, 0x72, 0x67, 0x1f, 0xce, 0xbc, 0xd6, 0x9d, 0xbd, 0xf1, 0xe7, 0x47, 0x80, 0xfc, 0xf6, 0x85, 0x03, 0x30, + 0x62, 0x46, 0x92, 0x3f, 0x0d, 0xac, 0xcb, 0x4d, 0x62, 0xf4, 0xf7, 0xbb, 0xc5, 0xe8, 0x3f, 0x2c, 0xf7, 0x11, 0xa3, + 0xbf, 0xff, 0xea, 0x62, 0xf4, 0xcb, 0xaa, 0x15, 0xf7, 0xfb, 0x6a, 0xe4, 0xf4, 0x5f, 0xd6, 0x55, 0x22, 0x39, 0xf0, + 0x8d, 0xeb, 0xab, 0xe5, 0x0d, 0xc4, 0xfe, 0x79, 0x1f, 0xf7, 0x7f, 0x58, 0x96, 0x4c, 0x94, 0x62, 0xc0, 0x00, 0xef, + 0x63, 0xc2, 0x00, 0xbf, 0x2d, 0xfb, 0x60, 0x17, 0xc1, 0x6f, 0xcd, 0x60, 0x6c, 0xcf, 0xfc, 0x70, 0x22, 0x6f, 0x5c, + 0x28, 0xe9, 0x61, 0x31, 0xd8, 0xcc, 0xc3, 0x65, 0x02, 0xca, 0x9a, 0xe5, 0x3c, 0x4a, 0xbb, 0x47, 0x2e, 0xa0, 0xf9, + 0xd6, 0x24, 0xc9, 0x2b, 0x8d, 0x1d, 0x11, 0x2d, 0xe9, 0x96, 0xdb, 0xf4, 0x6f, 0x7c, 0x8f, 0x26, 0x6b, 0xcd, 0xbd, + 0x7b, 0xf5, 0x7e, 0x35, 0xb0, 0x05, 0x11, 0x26, 0x7d, 0x40, 0x6c, 0x34, 0xbd, 0x2f, 0x1b, 0x8e, 0x55, 0x4c, 0x05, + 0x37, 0x8f, 0x14, 0x46, 0x52, 0x6d, 0xef, 0x95, 0x0d, 0xcf, 0x76, 0x4d, 0xb3, 0xe1, 0xf3, 0xa5, 0xe6, 0x5b, 0xac, + 0xde, 0x64, 0xc7, 0x55, 0x50, 0x55, 0xf2, 0x7e, 0x35, 0x02, 0xa4, 0xa0, 0x3d, 0x0b, 0xd3, 0xb8, 0x82, 0xf0, 0x71, + 0x35, 0xbc, 0x8d, 0x5d, 0xe5, 0x5d, 0xa9, 0x4f, 0xd5, 0x9c, 0xee, 0xc5, 0x1a, 0xe9, 0xc1, 0xe0, 0x37, 0x20, 0x6c, + 0xf8, 0x7d, 0x3c, 0x8c, 0x55, 0x38, 0xaf, 0x95, 0x7e, 0x89, 0xd4, 0xce, 0x67, 0xde, 0xba, 0x4e, 0xda, 0x6c, 0x34, + 0xa4, 0xf5, 0xd8, 0x5c, 0xdc, 0xd1, 0xf8, 0x79, 0x32, 0x5b, 0xcd, 0xc9, 0xb4, 0x18, 0x2d, 0x73, 0xb7, 0x75, 0x26, + 0xea, 0x3d, 0x85, 0x4d, 0x6c, 0xf1, 0x07, 0xd5, 0x6b, 0x7d, 0x3d, 0x81, 0x1c, 0xcd, 0x5d, 0x24, 0x22, 0x14, 0x0a, + 0xaa, 0x85, 0x36, 0xb6, 0xbd, 0x2d, 0xe6, 0x1f, 0x6a, 0xc7, 0xbc, 0x13, 0xb4, 0xd5, 0xdd, 0x66, 0x31, 0x22, 0x5d, + 0x1b, 0xd6, 0x25, 0x05, 0xaa, 0xd7, 0x39, 0xb6, 0xbc, 0x23, 0xcb, 0x39, 0xee, 0x98, 0xb9, 0x38, 0x70, 0x6a, 0x97, + 0x25, 0x80, 0x80, 0xc9, 0xae, 0x1c, 0x66, 0x10, 0x05, 0x59, 0xe0, 0x87, 0x39, 0xa0, 0xfa, 0x32, 0xcd, 0xfb, 0xcf, + 0x65, 0x9a, 0xc1, 0x1c, 0x05, 0x49, 0x86, 0xe6, 0xca, 0xf6, 0x90, 0x65, 0xf7, 0x8c, 0x45, 0x1b, 0x54, 0xb9, 0x55, + 0xeb, 0xe7, 0x3f, 0xce, 0x16, 0x34, 0x27, 0x3b, 0x8b, 0x61, 0x16, 0xf1, 0xfd, 0x21, 0x4c, 0x75, 0xf3, 0x81, 0xf5, + 0xd3, 0x26, 0x84, 0xfb, 0xcf, 0xdd, 0x08, 0x37, 0x63, 0xfb, 0x20, 0xdc, 0x7f, 0x7e, 0x75, 0x84, 0xfb, 0x93, 0x8a, + 0x70, 0x4b, 0x9e, 0x2a, 0x85, 0x4c, 0xf4, 0x03, 0x3e, 0x1b, 0x10, 0x72, 0xf8, 0xa5, 0x7e, 0x40, 0xe4, 0xa5, 0xae, + 0xa4, 0x82, 0xfd, 0x58, 0xca, 0x6d, 0x83, 0x2c, 0x3b, 0x86, 0x48, 0xa5, 0x3c, 0x1a, 0x90, 0x26, 0x55, 0x26, 0xfc, + 0x86, 0x3e, 0x2f, 0xa2, 0x2c, 0x74, 0xde, 0x73, 0xb6, 0x04, 0x54, 0x10, 0x3f, 0xc4, 0xc9, 0xdc, 0xc7, 0xf0, 0x70, + 0x3a, 0xe6, 0xc4, 0x83, 0x07, 0x17, 0xbc, 0xa3, 0x46, 0x71, 0x34, 0x96, 0x72, 0x74, 0xd6, 0xbf, 0x26, 0x7a, 0x50, + 0x7f, 0x60, 0x7e, 0xa2, 0x5b, 0xf4, 0x1a, 0x16, 0xf7, 0x45, 0xdb, 0x7d, 0xd1, 0x3a, 0x7c, 0x71, 0xe4, 0xc2, 0xff, + 0x3c, 0xd6, 0xce, 0x2d, 0x5e, 0x71, 0x1e, 0x47, 0x90, 0x96, 0x43, 0xd4, 0xdc, 0x54, 0xed, 0x9e, 0xb1, 0x4f, 0x45, + 0xad, 0xe3, 0xe6, 0x4a, 0x63, 0xff, 0xa1, 0xa8, 0xd3, 0x58, 0x63, 0x16, 0x2f, 0x95, 0x61, 0x35, 0x8c, 0x26, 0x88, + 0x96, 0x20, 0x19, 0x52, 0x6a, 0xa8, 0xaf, 0xf9, 0x74, 0x8b, 0x79, 0xb1, 0x76, 0x7e, 0x53, 0xe4, 0xfe, 0x11, 0x39, + 0x48, 0x76, 0x42, 0x90, 0x0b, 0xd5, 0x5d, 0x8c, 0x1c, 0x8e, 0xd9, 0x6f, 0x34, 0xc8, 0xbc, 0x57, 0x24, 0x78, 0xc7, + 0x05, 0xca, 0x92, 0x65, 0x34, 0xa2, 0x1c, 0xee, 0xfe, 0x30, 0x35, 0x82, 0x03, 0x88, 0x1d, 0x8a, 0x1f, 0x36, 0x71, + 0xd5, 0xfc, 0x33, 0xb7, 0x48, 0x94, 0x90, 0x8a, 0x55, 0xf1, 0x5f, 0x64, 0x56, 0x42, 0xe9, 0x55, 0x71, 0x69, 0xed, + 0xbe, 0xff, 0x42, 0x36, 0x7c, 0x91, 0x59, 0x90, 0xe2, 0x14, 0x96, 0xfb, 0xf9, 0x73, 0xaa, 0x05, 0x49, 0x07, 0x69, + 0x5a, 0xe7, 0xa3, 0x22, 0xf8, 0x98, 0xe6, 0x4f, 0x63, 0x8a, 0x3f, 0xd6, 0x1d, 0x59, 0xf1, 0xcb, 0x97, 0x67, 0x7d, + 0xcf, 0xe4, 0x29, 0x33, 0x4b, 0xf9, 0x9d, 0x2e, 0xf7, 0x53, 0x8d, 0x9b, 0x8d, 0x4e, 0x5b, 0x8b, 0x20, 0x9a, 0x0a, + 0xcd, 0xb4, 0xc4, 0x5e, 0x90, 0x6f, 0x81, 0x54, 0x60, 0xbe, 0x50, 0x51, 0x8b, 0x3a, 0x77, 0x2c, 0x81, 0x74, 0x9f, + 0x7d, 0xbd, 0xed, 0xb8, 0x8e, 0xab, 0xcb, 0x86, 0x93, 0x60, 0xda, 0x5f, 0xc7, 0x99, 0x0f, 0x99, 0x6b, 0xc2, 0x78, + 0x0a, 0x9e, 0x1f, 0x59, 0x90, 0x85, 0x90, 0x06, 0x05, 0x5c, 0x40, 0xe6, 0xc4, 0x35, 0xe6, 0xdc, 0x1e, 0xd7, 0x4f, + 0x3e, 0x61, 0x2a, 0x3c, 0xe1, 0xf4, 0x85, 0xf1, 0x70, 0x7e, 0x84, 0xcb, 0xd0, 0xd0, 0x0d, 0x48, 0xc4, 0xc8, 0x92, + 0xd4, 0x56, 0xed, 0xdb, 0xbb, 0x1a, 0xb4, 0x81, 0x24, 0xe9, 0xd8, 0xc1, 0x24, 0xf1, 0xe7, 0x10, 0x31, 0x7c, 0x9d, + 0x5b, 0x1c, 0xd3, 0xea, 0x1c, 0xd5, 0x6a, 0xde, 0xab, 0x23, 0x4b, 0x6b, 0x79, 0x96, 0xe6, 0x02, 0xba, 0xd5, 0x73, + 0x6b, 0x9d, 0xdf, 0xf4, 0x76, 0xa9, 0xe8, 0x08, 0xbf, 0x3c, 0xa5, 0x79, 0x90, 0x72, 0x8e, 0x0b, 0x3f, 0x33, 0x0a, + 0x6f, 0x68, 0x28, 0xb1, 0xbc, 0x03, 0x12, 0xd3, 0x5f, 0xb1, 0x55, 0x66, 0x62, 0x9a, 0x10, 0x5e, 0x25, 0x30, 0xd7, + 0xe8, 0x9a, 0x16, 0x44, 0x5a, 0xf0, 0xf9, 0xb3, 0x11, 0x80, 0xf9, 0x7d, 0x5f, 0x81, 0x0f, 0x3c, 0x9b, 0x25, 0x80, + 0x05, 0x85, 0x62, 0x09, 0x81, 0x05, 0xbe, 0x31, 0xf0, 0x6f, 0x51, 0x2c, 0x7e, 0x70, 0xc5, 0x9e, 0x13, 0xfa, 0xd1, + 0x14, 0x50, 0x9a, 0x1f, 0x4d, 0x6b, 0x06, 0x04, 0xe4, 0x5d, 0x57, 0x29, 0x2d, 0xba, 0x2a, 0x94, 0xfb, 0xe9, 0xf7, + 0x0f, 0x57, 0x94, 0x06, 0x09, 0x52, 0x6e, 0xfb, 0x63, 0x74, 0x05, 0x2b, 0x74, 0x0f, 0x2f, 0xfb, 0xdf, 0x9c, 0xce, + 0x59, 0xe6, 0x93, 0xe0, 0x12, 0x58, 0x3c, 0x20, 0x07, 0xb4, 0x91, 0x48, 0x61, 0x4a, 0x0c, 0xde, 0x98, 0xdd, 0x05, + 0x23, 0xce, 0xa7, 0x59, 0x1a, 0xbf, 0xa7, 0x6c, 0xb4, 0x51, 0xea, 0x7b, 0x16, 0x99, 0xc8, 0x8e, 0x7c, 0x0c, 0x82, + 0xd8, 0x8f, 0x62, 0xfd, 0xec, 0x1b, 0xe9, 0x4d, 0xb4, 0x69, 0x11, 0x20, 0x17, 0xe1, 0x75, 0xc2, 0xc2, 0x7f, 0xf5, + 0xbf, 0x81, 0x8b, 0xfb, 0x9b, 0x1b, 0xdd, 0xec, 0x65, 0x0e, 0xf2, 0x31, 0xdf, 0x34, 0xe4, 0xe4, 0x43, 0x1e, 0x95, + 0x33, 0x9b, 0x6d, 0x85, 0xd9, 0x84, 0xdf, 0xbb, 0x59, 0xd7, 0xb3, 0x53, 0xbc, 0xd0, 0xce, 0x80, 0xbb, 0x58, 0x97, + 0x78, 0x4e, 0xaf, 0x87, 0x0c, 0xea, 0x30, 0xf4, 0x47, 0x9f, 0x04, 0x87, 0xaa, 0x3e, 0xec, 0xc3, 0x8b, 0x4a, 0xca, + 0xae, 0x71, 0x2f, 0xe3, 0x56, 0x5e, 0xe3, 0x97, 0xf1, 0x53, 0xf7, 0xb3, 0x20, 0x93, 0xcc, 0x30, 0x3e, 0xe4, 0xa0, + 0xcd, 0xc1, 0xf1, 0x15, 0xec, 0x0f, 0x30, 0xa8, 0xde, 0xc9, 0x5f, 0x3a, 0x77, 0x9e, 0x3b, 0x6b, 0x79, 0x0e, 0xb0, + 0x39, 0xb3, 0xb6, 0x73, 0x1c, 0xda, 0x6d, 0xe7, 0x18, 0xfe, 0x3e, 0x02, 0xeb, 0x65, 0xb7, 0x9c, 0xc3, 0x8f, 0x5e, + 0x2b, 0xb4, 0x4f, 0x9c, 0x63, 0xf8, 0xbb, 0xa4, 0x56, 0xbf, 0x20, 0xd3, 0x03, 0x0c, 0xcf, 0x37, 0x25, 0x2c, 0xa0, + 0xfc, 0x96, 0x5a, 0x04, 0xab, 0x74, 0xbd, 0x35, 0x68, 0x22, 0x00, 0x65, 0xe8, 0x96, 0x08, 0x51, 0x18, 0xf5, 0x0c, + 0x48, 0x12, 0x8e, 0xe1, 0xed, 0x85, 0x41, 0x46, 0x54, 0x24, 0xbc, 0xdf, 0x7c, 0x8c, 0x78, 0x9b, 0xe6, 0x70, 0xe0, + 0x22, 0x6f, 0x12, 0xa9, 0x2e, 0xfe, 0xb6, 0xc0, 0x10, 0x3b, 0x22, 0x80, 0xb9, 0x82, 0x95, 0x8a, 0xdc, 0x7d, 0xf9, + 0xee, 0x81, 0xa3, 0xdf, 0x28, 0x93, 0xb9, 0x63, 0xbe, 0x6a, 0xdf, 0x5c, 0x9d, 0x21, 0x7b, 0xff, 0xbd, 0xfd, 0x60, + 0xca, 0x54, 0xea, 0x47, 0xc4, 0x1a, 0x1d, 0x07, 0x89, 0x1c, 0x9e, 0x82, 0xa2, 0xbd, 0xe6, 0x38, 0xea, 0x26, 0x24, + 0xd9, 0xb8, 0x00, 0x2a, 0xf9, 0xce, 0x0f, 0x15, 0xd3, 0x0b, 0xa5, 0xe5, 0x13, 0x89, 0xf9, 0x9f, 0x3f, 0x2f, 0x06, + 0x67, 0x57, 0xc6, 0x7d, 0xea, 0x75, 0xe0, 0xda, 0xed, 0xb0, 0xf6, 0x56, 0x2b, 0xa0, 0xdd, 0xc1, 0x6a, 0x8b, 0x60, + 0x96, 0x42, 0xd3, 0x2f, 0x74, 0x8c, 0x1b, 0x4d, 0x91, 0x6a, 0x1a, 0x46, 0x08, 0xf3, 0x5b, 0x61, 0x75, 0x74, 0xb3, + 0x17, 0x09, 0x85, 0x59, 0xb4, 0x25, 0x40, 0x2f, 0xe7, 0xc5, 0x74, 0x00, 0xcd, 0x96, 0x79, 0xec, 0x70, 0x69, 0xfc, + 0x5f, 0x4f, 0x02, 0xdd, 0x8b, 0x40, 0xc3, 0x57, 0x39, 0xad, 0x25, 0x77, 0x13, 0x79, 0xaf, 0xd2, 0x85, 0xca, 0xd2, + 0x73, 0x1d, 0x8a, 0x20, 0xfb, 0x12, 0x26, 0x5c, 0x93, 0xe6, 0x4d, 0xf2, 0xb6, 0x28, 0x0a, 0xac, 0x00, 0x22, 0x54, + 0x1b, 0xc2, 0xd5, 0xc9, 0x7c, 0xfe, 0x7c, 0xe3, 0x25, 0x44, 0xea, 0x64, 0x35, 0xef, 0xa4, 0xae, 0xe2, 0x37, 0x5d, + 0x45, 0x31, 0xb2, 0x5f, 0xc4, 0x1a, 0xc2, 0x2a, 0x8b, 0xf6, 0x1e, 0xfe, 0x1c, 0x32, 0x3f, 0x73, 0xb8, 0x1e, 0xc4, + 0x50, 0x2e, 0x77, 0xcb, 0x63, 0x6d, 0xb0, 0xc7, 0xe2, 0x91, 0xb8, 0x78, 0xa4, 0xbb, 0x67, 0xeb, 0x8f, 0x4b, 0xee, + 0x87, 0x0c, 0x7d, 0x7c, 0x76, 0x8b, 0xe0, 0x29, 0xef, 0x32, 0x9f, 0x22, 0x6c, 0xa8, 0x57, 0x6e, 0x9c, 0xf9, 0x22, + 0xcb, 0x09, 0xd0, 0xe5, 0xbd, 0x46, 0x85, 0xa1, 0xe2, 0xab, 0x7c, 0xf6, 0xee, 0xea, 0x3b, 0x8d, 0xef, 0x7f, 0xd2, + 0x6f, 0x21, 0x23, 0x43, 0x31, 0xf9, 0xfb, 0x14, 0x93, 0x5f, 0xe3, 0x49, 0x2e, 0x20, 0xb2, 0x7d, 0x7e, 0x40, 0x10, + 0xd4, 0x35, 0x16, 0x8d, 0x48, 0xeb, 0x37, 0x5f, 0x86, 0x59, 0xb0, 0xf0, 0x93, 0xec, 0x00, 0x9a, 0xda, 0x80, 0xe4, + 0xf4, 0x4d, 0x1e, 0xcc, 0xa4, 0x38, 0x14, 0x42, 0xb5, 0x2c, 0x12, 0x9a, 0xc3, 0x49, 0x10, 0x4a, 0xc5, 0xa1, 0xf8, + 0x80, 0x3f, 0x1a, 0xb1, 0x45, 0xd6, 0xd7, 0xfd, 0x05, 0xe4, 0x66, 0xc0, 0x68, 0xcb, 0x07, 0xf1, 0x28, 0x63, 0x99, + 0x9d, 0x66, 0x09, 0xf3, 0xe7, 0xba, 0x0c, 0x34, 0x5a, 0xef, 0x2f, 0x5d, 0x0e, 0xe7, 0x41, 0x26, 0x23, 0xf5, 0xd1, + 0x04, 0x41, 0x85, 0x07, 0x43, 0x3c, 0x1b, 0xe4, 0x1c, 0x84, 0x97, 0xf1, 0xb4, 0xb2, 0xa3, 0x0a, 0xca, 0xe5, 0x1c, + 0xe3, 0xc0, 0xf2, 0x78, 0xfc, 0x63, 0xf4, 0xc8, 0xb9, 0xe5, 0x5e, 0xd7, 0x32, 0xa0, 0xa0, 0x7e, 0x76, 0xca, 0xd9, + 0x5b, 0x0d, 0x03, 0x05, 0xe8, 0x1d, 0x17, 0x22, 0xdd, 0x6e, 0xf2, 0xc7, 0x3e, 0xe0, 0x95, 0xe1, 0x6a, 0xa2, 0x9e, + 0x31, 0x0a, 0x39, 0x8d, 0xe5, 0x0a, 0x08, 0xa1, 0x92, 0x8a, 0x77, 0xe6, 0x9d, 0x49, 0x07, 0x20, 0x1c, 0x15, 0xd2, + 0x4a, 0x9f, 0x3f, 0xbf, 0x1e, 0xfc, 0xe7, 0xdf, 0x10, 0x2a, 0x7d, 0xe6, 0x09, 0x2f, 0xe8, 0x6b, 0xb5, 0x16, 0xa7, + 0x3e, 0xad, 0x01, 0xaa, 0xf7, 0xd9, 0x58, 0x84, 0x05, 0x11, 0x5b, 0x2b, 0x1f, 0xdc, 0x88, 0x50, 0x4f, 0x90, 0x0e, + 0xc1, 0x14, 0xbe, 0xda, 0x03, 0x58, 0xde, 0x81, 0x08, 0x11, 0xa0, 0xfd, 0xba, 0xfa, 0xfe, 0x18, 0x42, 0x01, 0xd7, + 0xb2, 0x14, 0x28, 0x03, 0xc4, 0x3d, 0x74, 0x76, 0xea, 0x73, 0xe1, 0x2b, 0x90, 0x1f, 0x69, 0xf7, 0x00, 0xa6, 0x39, + 0x8b, 0xe7, 0xcc, 0x09, 0xe2, 0x83, 0x7b, 0x36, 0xb4, 0xfd, 0x45, 0x40, 0xf2, 0x65, 0x94, 0xbb, 0x69, 0x44, 0xf9, + 0x49, 0x05, 0x2d, 0xd1, 0xd7, 0x79, 0x01, 0xca, 0xb8, 0x00, 0x14, 0xfc, 0xf4, 0xcf, 0xca, 0xd1, 0x03, 0x1d, 0x11, + 0xbf, 0xbe, 0x8c, 0xe5, 0xcf, 0x29, 0x08, 0xa0, 0x88, 0xf7, 0x57, 0x3c, 0xd8, 0xf1, 0x64, 0xa2, 0x46, 0xfc, 0x73, + 0xca, 0xdf, 0x97, 0x50, 0x29, 0xf6, 0x6c, 0xbc, 0xa0, 0x2f, 0xd5, 0x3f, 0x21, 0x7f, 0x42, 0xee, 0x5e, 0x1e, 0x1c, + 0x12, 0xce, 0x73, 0x2d, 0x72, 0xa0, 0x04, 0xc9, 0x53, 0xaa, 0xc4, 0x11, 0x45, 0x35, 0x4e, 0xf5, 0x06, 0xd2, 0xe4, + 0x49, 0xbf, 0x4f, 0x78, 0xac, 0x8a, 0xce, 0x00, 0x4a, 0x0d, 0xb1, 0xfc, 0x61, 0xb2, 0x19, 0x34, 0xb4, 0xc9, 0x83, + 0x0b, 0x1b, 0x55, 0xa7, 0x53, 0x1f, 0xe3, 0x81, 0x2f, 0xf6, 0x57, 0x69, 0x07, 0xc2, 0xce, 0xe2, 0x0b, 0x0b, 0x08, + 0x5c, 0xf4, 0x53, 0xc1, 0xe3, 0xda, 0xb7, 0x84, 0xb2, 0xed, 0xd0, 0x7f, 0x88, 0x15, 0xcd, 0x3a, 0x77, 0xb2, 0xbf, + 0xc4, 0xd2, 0x2b, 0xe1, 0xdc, 0x56, 0x3b, 0x49, 0x32, 0x1e, 0x7a, 0xfd, 0x34, 0xa9, 0x01, 0xcc, 0x77, 0x1d, 0x26, + 0xb5, 0x6e, 0x79, 0x32, 0x88, 0x1d, 0xf3, 0xe2, 0xa0, 0x95, 0x5e, 0xe2, 0xb9, 0xcf, 0x4f, 0x0f, 0x60, 0x7e, 0x10, + 0x18, 0xa0, 0x44, 0x19, 0x05, 0x26, 0x44, 0x1f, 0xf0, 0x53, 0xb2, 0x0e, 0xb8, 0x18, 0x0b, 0xa2, 0x0e, 0x39, 0x47, + 0x19, 0x9a, 0xb4, 0x54, 0xa5, 0x4e, 0xac, 0xb8, 0xcd, 0x54, 0xde, 0xee, 0xfc, 0x01, 0xbf, 0x2d, 0x31, 0x79, 0x40, + 0xde, 0xcb, 0x98, 0xf0, 0xbb, 0xbd, 0xcc, 0x36, 0xb8, 0xe6, 0x6e, 0xaa, 0x42, 0x04, 0xeb, 0x96, 0x0a, 0xc5, 0x3e, + 0xde, 0x56, 0xab, 0x20, 0x8d, 0x64, 0xb5, 0x85, 0x6f, 0xe8, 0x4f, 0x71, 0xc7, 0xd7, 0x6a, 0x63, 0x29, 0xd4, 0xbb, + 0xcc, 0xfa, 0x50, 0x55, 0x08, 0xdb, 0xfd, 0xc5, 0x82, 0x2a, 0x9b, 0xbd, 0xd3, 0x03, 0xe2, 0x3b, 0xcf, 0x68, 0x87, + 0x9d, 0x9d, 0x82, 0x75, 0x21, 0x2d, 0xba, 0xbf, 0x58, 0xf0, 0x25, 0xa5, 0x5f, 0xf4, 0xe6, 0x60, 0x96, 0xcd, 0xc3, + 0xb3, 0xff, 0x03, 0x1c, 0x2a, 0x1a, 0x60, 0x9f, 0x5a, 0x03, 0x00}; } // namespace web_server } // namespace esphome From 618102fe8c6d1fcafa51d2a0e025e08a1a14588d Mon Sep 17 00:00:00 2001 From: Mischa Siekmann <45062894+gnumpi@users.noreply.github.com> Date: Sun, 9 Jun 2024 08:34:21 +0200 Subject: [PATCH 1557/2101] fix: arduino media player still sets wrong state. (#6875) --- .../i2s_audio/media_player/i2s_audio_media_player.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/i2s_audio/media_player/i2s_audio_media_player.cpp b/esphome/components/i2s_audio/media_player/i2s_audio_media_player.cpp index ef494fac2e..5140a923b4 100644 --- a/esphome/components/i2s_audio/media_player/i2s_audio_media_player.cpp +++ b/esphome/components/i2s_audio/media_player/i2s_audio_media_player.cpp @@ -28,7 +28,7 @@ void I2SAudioMediaPlayer::control(const media_player::MediaPlayerCall &call) { } } - if (this->state == media_player::MEDIA_PLAYER_STATE_ANNOUNCING) { + if (play_state == media_player::MEDIA_PLAYER_STATE_ANNOUNCING) { this->is_announcement_ = true; } From 7b45498de67ccdf10271e61577c66b5e216bc6db Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 10 Jun 2024 08:15:29 +1200 Subject: [PATCH 1558/2101] [http_request] Add esp-idf and rp2040 support (#3256) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Implement http_request component for esp-idf * Fix ifdefs * Lint * clang * Set else to fail with error message * Use unique_ptr * Fix * Tidy up casting, explicit HttpResponse lifetime (#3265) Co-authored-by: Daniel Cousens * Remove unique_ptr wrapper * Fix * Use reference * Add duration code into new split files * Add config for tx/rx buffer on idf * Fix * Try reserve response data with rx buffer size * Update http_request.h * Move client cleanup to be earlier * Move capture_response to bool on struct and remove global * Fix returns * Change quotes to brackets * Rework http request * Remove http request from old test yamls * Update component tests * Validate md5 length when hardcoded string * Linting * Add duration_ms to container * More lint * const * Remove default arguments and add helper functions for get and post * Add virtual destructor to HttpContainer * Undo const HEADER_KEYS * 🤦 * Update esphome/components/http_request/ota/ota_http_request.cpp Co-authored-by: Keith Burzinski * Update esphome/components/http_request/ota/ota_http_request.cpp Co-authored-by: Keith Burzinski * lint * Move header keys inline * Add missing WatchdogManagers * CAPS * Fix "follow redirects" string in config dump * IDF 5+ fix --------- Co-authored-by: Daniel Cousens <413395+dcousens@users.noreply.github.com> Co-authored-by: Daniel Cousens Co-authored-by: Keith Burzinski --- esphome/codegen.py | 1 + esphome/components/http_request/__init__.py | 137 +++++++++++---- .../components/http_request/http_request.cpp | 132 +------------- .../components/http_request/http_request.h | 141 +++++++++------ .../http_request/http_request_arduino.cpp | 161 ++++++++++++++++++ .../http_request/http_request_arduino.h | 40 +++++ .../http_request/http_request_idf.cpp | 155 +++++++++++++++++ .../http_request/http_request_idf.h | 34 ++++ .../components/http_request/ota/__init__.py | 109 ++---------- .../http_request/ota/ota_http_request.cpp | 110 +++++------- .../http_request/ota/ota_http_request.h | 24 +-- .../ota/ota_http_request_arduino.cpp | 134 --------------- .../ota/ota_http_request_arduino.h | 42 ----- .../http_request/ota/ota_http_request_idf.cpp | 86 ---------- .../http_request/ota/ota_http_request_idf.h | 24 --- .../http_request/{ota => }/watchdog.cpp | 19 ++- .../http_request/{ota => }/watchdog.h | 5 +- esphome/cpp_types.py | 1 + tests/components/http_request/common.yaml | 75 ++++++++ .../http_request/common_http_request.yaml | 33 ---- tests/components/http_request/common_ota.yaml | 36 ---- .../http_request/test-nossl.esp8266.yaml | 40 +---- .../http_request/test.esp32-c3-idf.yaml | 2 +- .../http_request/test.esp32-c3.yaml | 3 +- .../http_request/test.esp32-idf.yaml | 2 +- tests/components/http_request/test.esp32.yaml | 3 +- .../components/http_request/test.esp8266.yaml | 3 +- .../components/http_request/test.rp2040.yaml | 2 +- tests/test1.yaml | 29 ---- tests/test3.1.yaml | 24 --- tests/test7.yaml | 23 +-- 31 files changed, 748 insertions(+), 882 deletions(-) create mode 100644 esphome/components/http_request/http_request_arduino.cpp create mode 100644 esphome/components/http_request/http_request_arduino.h create mode 100644 esphome/components/http_request/http_request_idf.cpp create mode 100644 esphome/components/http_request/http_request_idf.h delete mode 100644 esphome/components/http_request/ota/ota_http_request_arduino.cpp delete mode 100644 esphome/components/http_request/ota/ota_http_request_arduino.h delete mode 100644 esphome/components/http_request/ota/ota_http_request_idf.cpp delete mode 100644 esphome/components/http_request/ota/ota_http_request_idf.h rename esphome/components/http_request/{ota => }/watchdog.cpp (79%) rename esphome/components/http_request/{ota => }/watchdog.h (84%) create mode 100644 tests/components/http_request/common.yaml delete mode 100644 tests/components/http_request/common_http_request.yaml delete mode 100644 tests/components/http_request/common_ota.yaml diff --git a/esphome/codegen.py b/esphome/codegen.py index dc17f28a03..b552490129 100644 --- a/esphome/codegen.py +++ b/esphome/codegen.py @@ -58,6 +58,7 @@ from esphome.cpp_types import ( # noqa bool_, int_, std_ns, + std_shared_ptr, std_string, std_vector, uint8, diff --git a/esphome/components/http_request/__init__.py b/esphome/components/http_request/__init__.py index 0c3e249512..37487ec9a7 100644 --- a/esphome/components/http_request/__init__.py +++ b/esphome/components/http_request/__init__.py @@ -1,9 +1,8 @@ -import urllib.parse as urlparse - import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation from esphome.const import ( + __version__, CONF_ID, CONF_TIMEOUT, CONF_METHOD, @@ -12,67 +11,91 @@ from esphome.const import ( CONF_ESP8266_DISABLE_SSL_SUPPORT, ) from esphome.core import Lambda, CORE +from esphome.components import esp32 DEPENDENCIES = ["network"] AUTO_LOAD = ["json"] http_request_ns = cg.esphome_ns.namespace("http_request") HttpRequestComponent = http_request_ns.class_("HttpRequestComponent", cg.Component) +HttpRequestArduino = http_request_ns.class_("HttpRequestArduino", HttpRequestComponent) +HttpRequestIDF = http_request_ns.class_("HttpRequestIDF", HttpRequestComponent) + +HttpContainer = http_request_ns.class_("HttpContainer") + HttpRequestSendAction = http_request_ns.class_( "HttpRequestSendAction", automation.Action ) HttpRequestResponseTrigger = http_request_ns.class_( - "HttpRequestResponseTrigger", automation.Trigger + "HttpRequestResponseTrigger", + automation.Trigger.template( + cg.std_shared_ptr.template(HttpContainer), cg.std_string + ), ) -CONF_HEADERS = "headers" +CONF_HTTP_REQUEST_ID = "http_request_id" + CONF_USERAGENT = "useragent" -CONF_BODY = "body" -CONF_JSON = "json" CONF_VERIFY_SSL = "verify_ssl" -CONF_ON_RESPONSE = "on_response" CONF_FOLLOW_REDIRECTS = "follow_redirects" CONF_REDIRECT_LIMIT = "redirect_limit" +CONF_WATCHDOG_TIMEOUT = "watchdog_timeout" + +CONF_MAX_RESPONSE_BUFFER_SIZE = "max_response_buffer_size" +CONF_ON_RESPONSE = "on_response" +CONF_HEADERS = "headers" +CONF_BODY = "body" +CONF_JSON = "json" +CONF_CAPTURE_RESPONSE = "capture_response" def validate_url(value): - value = cv.string(value) - try: - parsed = list(urlparse.urlparse(value)) - except Exception as err: - raise cv.Invalid("Invalid URL") from err - - if not parsed[0] or not parsed[1]: - raise cv.Invalid("URL must have a URL scheme and host") - - if parsed[0] not in ["http", "https"]: - raise cv.Invalid("Scheme must be http or https") - - if not parsed[2]: - parsed[2] = "/" - - return urlparse.urlunparse(parsed) + value = cv.url(value) + if value.startswith("http://") or value.startswith("https://"): + return value + raise cv.Invalid("URL must start with 'http://' or 'https://'") -def validate_secure_url(config): - url_ = config[CONF_URL] +def validate_ssl_verification(config): + error_message = "" + + if CORE.is_esp32: + if not CORE.using_esp_idf and config[CONF_VERIFY_SSL]: + error_message = "ESPHome supports certificate verification only via ESP-IDF" + + if CORE.is_rp2040 and config[CONF_VERIFY_SSL]: + error_message = "ESPHome does not support certificate verification on RP2040" + if ( - config.get(CONF_VERIFY_SSL) - and not isinstance(url_, Lambda) - and url_.lower().startswith("https:") + CORE.is_esp8266 + and not config[CONF_ESP8266_DISABLE_SSL_SUPPORT] + and config[CONF_VERIFY_SSL] ): + error_message = "ESPHome does not support certificate verification on ESP8266" + + if len(error_message) > 0: raise cv.Invalid( - "Currently ESPHome doesn't support SSL verification. " - "Set 'verify_ssl: false' to make insecure HTTPS requests." + f"{error_message}. Set '{CONF_VERIFY_SSL}: false' to skip certificate validation and allow less secure HTTPS connections." ) + return config +def _declare_request_class(value): + if CORE.using_esp_idf: + return cv.declare_id(HttpRequestIDF)(value) + if CORE.is_esp8266 or CORE.is_esp32 or CORE.is_rp2040: + return cv.declare_id(HttpRequestArduino)(value) + return NotImplementedError + + CONFIG_SCHEMA = cv.All( cv.Schema( { - cv.GenerateID(): cv.declare_id(HttpRequestComponent), - cv.Optional(CONF_USERAGENT, "ESPHome"): cv.string, + cv.GenerateID(): _declare_request_class, + cv.Optional( + CONF_USERAGENT, f"ESPHome/{__version__} (https://esphome.io)" + ): cv.string, cv.Optional(CONF_FOLLOW_REDIRECTS, True): cv.boolean, cv.Optional(CONF_REDIRECT_LIMIT, 3): cv.int_, cv.Optional( @@ -81,12 +104,21 @@ CONFIG_SCHEMA = cv.All( cv.SplitDefault(CONF_ESP8266_DISABLE_SSL_SUPPORT, esp8266=False): cv.All( cv.only_on_esp8266, cv.boolean ), + cv.Optional(CONF_VERIFY_SSL, default=True): cv.boolean, + cv.Optional(CONF_WATCHDOG_TIMEOUT): cv.All( + cv.Any(cv.only_on_esp32, cv.only_on_rp2040), + cv.positive_not_null_time_period, + cv.positive_time_period_milliseconds, + ), } ).extend(cv.COMPONENT_SCHEMA), cv.require_framework_version( esp8266_arduino=cv.Version(2, 5, 1), esp32_arduino=cv.Version(0, 0, 0), + esp_idf=cv.Version(0, 0, 0), + rp2040_arduino=cv.Version(0, 0, 0), ), + validate_ssl_verification, ) @@ -100,11 +132,30 @@ async def to_code(config): if CORE.is_esp8266 and not config[CONF_ESP8266_DISABLE_SSL_SUPPORT]: cg.add_define("USE_HTTP_REQUEST_ESP8266_HTTPS") + if timeout_ms := config.get(CONF_WATCHDOG_TIMEOUT): + cg.add(var.set_watchdog_timeout(timeout_ms)) + if CORE.is_esp32: - cg.add_library("WiFiClientSecure", None) - cg.add_library("HTTPClient", None) + if CORE.using_esp_idf: + esp32.add_idf_sdkconfig_option( + "CONFIG_MBEDTLS_CERTIFICATE_BUNDLE", + config.get(CONF_VERIFY_SSL), + ) + esp32.add_idf_sdkconfig_option( + "CONFIG_ESP_TLS_INSECURE", + not config.get(CONF_VERIFY_SSL), + ) + esp32.add_idf_sdkconfig_option( + "CONFIG_ESP_TLS_SKIP_SERVER_CERT_VERIFY", + not config.get(CONF_VERIFY_SSL), + ) + else: + cg.add_library("WiFiClientSecure", None) + cg.add_library("HTTPClient", None) if CORE.is_esp8266: cg.add_library("ESP8266HTTPClient", None) + if CORE.is_rp2040 and CORE.using_arduino: + cg.add_library("HTTPClient", None) await cg.register_component(var, config) @@ -116,12 +167,16 @@ HTTP_REQUEST_ACTION_SCHEMA = cv.Schema( cv.Optional(CONF_HEADERS): cv.All( cv.Schema({cv.string: cv.templatable(cv.string)}) ), - cv.Optional(CONF_VERIFY_SSL, default=True): cv.boolean, + cv.Optional(CONF_VERIFY_SSL): cv.invalid( + f"{CONF_VERIFY_SSL} has moved to the base component configuration." + ), + cv.Optional(CONF_CAPTURE_RESPONSE, default=False): cv.boolean, cv.Optional(CONF_ON_RESPONSE): automation.validate_automation( {cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(HttpRequestResponseTrigger)} ), + cv.Optional(CONF_MAX_RESPONSE_BUFFER_SIZE, default="1kB"): cv.validate_bytes, } -).add_extra(validate_secure_url) +) HTTP_REQUEST_GET_ACTION_SCHEMA = automation.maybe_conf( CONF_URL, HTTP_REQUEST_ACTION_SCHEMA.extend( @@ -173,6 +228,9 @@ async def http_request_action_to_code(config, action_id, template_arg, args): template_ = await cg.templatable(config[CONF_URL], args, cg.std_string) cg.add(var.set_url(template_)) cg.add(var.set_method(config[CONF_METHOD])) + cg.add(var.set_capture_response(config[CONF_CAPTURE_RESPONSE])) + cg.add(var.set_max_response_buffer_size(config[CONF_MAX_RESPONSE_BUFFER_SIZE])) + if CONF_BODY in config: template_ = await cg.templatable(config[CONF_BODY], args, cg.std_string) cg.add(var.set_body(template_)) @@ -196,7 +254,12 @@ async def http_request_action_to_code(config, action_id, template_arg, args): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID]) cg.add(var.register_response_trigger(trigger)) await automation.build_automation( - trigger, [(int, "status_code"), (cg.uint32, "duration_ms")], conf + trigger, + [ + (cg.std_shared_ptr.template(HttpContainer), "response"), + (cg.std_string, "body"), + ], + conf, ) return var diff --git a/esphome/components/http_request/http_request.cpp b/esphome/components/http_request/http_request.cpp index 46894a9afd..be8bef006e 100644 --- a/esphome/components/http_request/http_request.cpp +++ b/esphome/components/http_request/http_request.cpp @@ -1,9 +1,8 @@ -#ifdef USE_ARDUINO - #include "http_request.h" -#include "esphome/core/defines.h" + #include "esphome/core/log.h" -#include "esphome/components/network/util.h" + +#include namespace esphome { namespace http_request { @@ -14,131 +13,12 @@ void HttpRequestComponent::dump_config() { ESP_LOGCONFIG(TAG, "HTTP Request:"); ESP_LOGCONFIG(TAG, " Timeout: %ums", this->timeout_); ESP_LOGCONFIG(TAG, " User-Agent: %s", this->useragent_); - ESP_LOGCONFIG(TAG, " Follow Redirects: %d", this->follow_redirects_); + ESP_LOGCONFIG(TAG, " Follow redirects: %s", YESNO(this->follow_redirects_)); ESP_LOGCONFIG(TAG, " Redirect limit: %d", this->redirect_limit_); -} - -void HttpRequestComponent::set_url(std::string url) { - this->url_ = std::move(url); - this->secure_ = this->url_.compare(0, 6, "https:") == 0; - - if (!this->last_url_.empty() && this->url_ != this->last_url_) { - // Close connection if url has been changed - this->client_.setReuse(false); - this->client_.end(); + if (this->watchdog_timeout_ > 0) { + ESP_LOGCONFIG(TAG, " Watchdog Timeout: %" PRIu32 "ms", this->watchdog_timeout_); } - this->client_.setReuse(true); -} - -void HttpRequestComponent::send(const std::vector &response_triggers) { - if (!network::is_connected()) { - this->client_.end(); - this->status_set_warning(); - ESP_LOGW(TAG, "HTTP Request failed; Not connected to network"); - return; - } - - bool begin_status = false; - const String url = this->url_.c_str(); -#if defined(USE_ESP32) || (defined(USE_ESP8266) && USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 6, 0)) -#if defined(USE_ESP32) || USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 7, 0) - if (this->follow_redirects_) { - this->client_.setFollowRedirects(HTTPC_FORCE_FOLLOW_REDIRECTS); - } else { - this->client_.setFollowRedirects(HTTPC_DISABLE_FOLLOW_REDIRECTS); - } -#else - this->client_.setFollowRedirects(this->follow_redirects_); -#endif - this->client_.setRedirectLimit(this->redirect_limit_); -#endif -#if defined(USE_ESP32) - begin_status = this->client_.begin(url); -#elif defined(USE_ESP8266) - begin_status = this->client_.begin(*this->get_wifi_client_(), url); -#endif - - if (!begin_status) { - this->client_.end(); - this->status_set_warning(); - ESP_LOGW(TAG, "HTTP Request failed at the begin phase. Please check the configuration"); - return; - } - - this->client_.setTimeout(this->timeout_); -#if defined(USE_ESP32) - this->client_.setConnectTimeout(this->timeout_); -#endif - if (this->useragent_ != nullptr) { - this->client_.setUserAgent(this->useragent_); - } - for (const auto &header : this->headers_) { - this->client_.addHeader(header.name, header.value, false, true); - } - - uint32_t start_time = millis(); - int http_code = this->client_.sendRequest(this->method_, this->body_.c_str()); - uint32_t duration = millis() - start_time; - for (auto *trigger : response_triggers) - trigger->process(http_code, duration); - - if (http_code < 0) { - ESP_LOGW(TAG, "HTTP Request failed; URL: %s; Error: %s; Duration: %u ms", this->url_.c_str(), - HTTPClient::errorToString(http_code).c_str(), duration); - this->status_set_warning(); - return; - } - - if (http_code < 200 || http_code >= 300) { - ESP_LOGW(TAG, "HTTP Request failed; URL: %s; Code: %d; Duration: %u ms", this->url_.c_str(), http_code, duration); - this->status_set_warning(); - return; - } - - this->status_clear_warning(); - ESP_LOGD(TAG, "HTTP Request completed; URL: %s; Code: %d; Duration: %u ms", this->url_.c_str(), http_code, duration); -} - -#ifdef USE_ESP8266 -std::shared_ptr HttpRequestComponent::get_wifi_client_() { -#ifdef USE_HTTP_REQUEST_ESP8266_HTTPS - if (this->secure_) { - if (this->wifi_client_secure_ == nullptr) { - this->wifi_client_secure_ = std::make_shared(); - this->wifi_client_secure_->setInsecure(); - this->wifi_client_secure_->setBufferSizes(512, 512); - } - return this->wifi_client_secure_; - } -#endif - - if (this->wifi_client_ == nullptr) { - this->wifi_client_ = std::make_shared(); - } - return this->wifi_client_; -} -#endif - -void HttpRequestComponent::close() { - this->last_url_ = this->url_; - this->client_.end(); -} - -const char *HttpRequestComponent::get_string() { -#if defined(ESP32) - // The static variable is here because HTTPClient::getString() returns a String on ESP32, - // and we need something to keep a buffer alive. - static String str; -#else - // However on ESP8266, HTTPClient::getString() returns a String& to a member variable. - // Leaving this the default so that any new platform either doesn't copy, or encounters a compilation error. - auto & -#endif - str = this->client_.getString(); - return str.c_str(); } } // namespace http_request } // namespace esphome - -#endif // USE_ARDUINO diff --git a/esphome/components/http_request/http_request.h b/esphome/components/http_request/http_request.h index b885de18e6..df6bc7dea7 100644 --- a/esphome/components/http_request/http_request.h +++ b/esphome/components/http_request/http_request.h @@ -1,27 +1,18 @@ #pragma once -#ifdef USE_ARDUINO - -#include "esphome/components/json/json_util.h" -#include "esphome/core/automation.h" -#include "esphome/core/component.h" -#include "esphome/core/defines.h" - #include #include #include #include #include -#ifdef USE_ESP32 -#include -#endif -#ifdef USE_ESP8266 -#include -#ifdef USE_HTTP_REQUEST_ESP8266_HTTPS -#include -#endif -#endif +#include "esphome/components/json/json_util.h" +#include "esphome/core/application.h" +#include "esphome/core/automation.h" +#include "esphome/core/component.h" +#include "esphome/core/defines.h" +#include "esphome/core/helpers.h" +#include "esphome/core/log.h" namespace esphome { namespace http_request { @@ -31,9 +22,32 @@ struct Header { const char *value; }; -class HttpRequestResponseTrigger : public Trigger { +class HttpRequestComponent; + +class HttpContainer : public Parented { public: - void process(int32_t status_code, uint32_t duration_ms) { this->trigger(status_code, duration_ms); } + virtual ~HttpContainer() = default; + size_t content_length; + int status_code; + uint32_t duration_ms; + + virtual int read(uint8_t *buf, size_t max_len) = 0; + virtual void end() = 0; + + void set_secure(bool secure) { this->secure_ = secure; } + + size_t get_bytes_read() const { return this->bytes_read_; } + + protected: + size_t bytes_read_{0}; + bool secure_{false}; +}; + +class HttpRequestResponseTrigger : public Trigger, std::string> { + public: + void process(std::shared_ptr container, std::string response_body) { + this->trigger(std::move(container), std::move(response_body)); + } }; class HttpRequestComponent : public Component { @@ -41,37 +55,33 @@ class HttpRequestComponent : public Component { void dump_config() override; float get_setup_priority() const override { return setup_priority::AFTER_WIFI; } - void set_url(std::string url); - void set_method(const char *method) { this->method_ = method; } void set_useragent(const char *useragent) { this->useragent_ = useragent; } void set_timeout(uint16_t timeout) { this->timeout_ = timeout; } + void set_watchdog_timeout(uint32_t watchdog_timeout) { this->watchdog_timeout_ = watchdog_timeout; } + uint32_t get_watchdog_timeout() const { return this->watchdog_timeout_; } void set_follow_redirects(bool follow_redirects) { this->follow_redirects_ = follow_redirects; } void set_redirect_limit(uint16_t limit) { this->redirect_limit_ = limit; } - void set_body(const std::string &body) { this->body_ = body; } - void set_headers(std::list

headers) { this->headers_ = std::move(headers); } - void send(const std::vector &response_triggers); - void close(); - const char *get_string(); + + std::shared_ptr get(std::string url) { return this->start(std::move(url), "GET", "", {}); } + std::shared_ptr get(std::string url, std::list
headers) { + return this->start(std::move(url), "GET", "", std::move(headers)); + } + std::shared_ptr post(std::string url, std::string body) { + return this->start(std::move(url), "POST", std::move(body), {}); + } + std::shared_ptr post(std::string url, std::string body, std::list
headers) { + return this->start(std::move(url), "POST", std::move(body), std::move(headers)); + } + + virtual std::shared_ptr start(std::string url, std::string method, std::string body, + std::list
headers) = 0; protected: - HTTPClient client_{}; - std::string url_; - std::string last_url_; - const char *method_; const char *useragent_{nullptr}; - bool secure_; bool follow_redirects_; uint16_t redirect_limit_; uint16_t timeout_{5000}; - std::string body_; - std::list
headers_; -#ifdef USE_ESP8266 - std::shared_ptr wifi_client_; -#ifdef USE_HTTP_REQUEST_ESP8266_HTTPS - std::shared_ptr wifi_client_secure_; -#endif - std::shared_ptr get_wifi_client_(); -#endif + uint32_t watchdog_timeout_{0}; }; template class HttpRequestSendAction : public Action { @@ -80,6 +90,7 @@ template class HttpRequestSendAction : public Action { TEMPLATABLE_VALUE(std::string, url) TEMPLATABLE_VALUE(const char *, method) TEMPLATABLE_VALUE(std::string, body) + TEMPLATABLE_VALUE(bool, capture_response) void add_header(const char *key, TemplatableValue value) { this->headers_.insert({key, value}); } @@ -89,19 +100,22 @@ template class HttpRequestSendAction : public Action { void register_response_trigger(HttpRequestResponseTrigger *trigger) { this->response_triggers_.push_back(trigger); } + void set_max_response_buffer_size(size_t max_response_buffer_size) { + this->max_response_buffer_size_ = max_response_buffer_size; + } + void play(Ts... x) override { - this->parent_->set_url(this->url_.value(x...)); - this->parent_->set_method(this->method_.value(x...)); + std::string body; if (this->body_.has_value()) { - this->parent_->set_body(this->body_.value(x...)); + body = this->body_.value(x...); } if (!this->json_.empty()) { auto f = std::bind(&HttpRequestSendAction::encode_json_, this, x..., std::placeholders::_1); - this->parent_->set_body(json::build_json(f)); + body = json::build_json(f); } if (this->json_func_ != nullptr) { auto f = std::bind(&HttpRequestSendAction::encode_json_func_, this, x..., std::placeholders::_1); - this->parent_->set_body(json::build_json(f)); + body = json::build_json(f); } std::list
headers; for (const auto &item : this->headers_) { @@ -111,10 +125,37 @@ template class HttpRequestSendAction : public Action { header.value = val.value(x...); headers.push_back(header); } - this->parent_->set_headers(headers); - this->parent_->send(this->response_triggers_); - this->parent_->close(); - this->parent_->set_body(""); + + auto container = this->parent_->start(this->url_.value(x...), this->method_.value(x...), body, headers); + + if (container == nullptr) { + return; + } + + size_t content_length = container->content_length; + size_t max_length = std::min(content_length, this->max_response_buffer_size_); + + std::string response_body; + if (this->capture_response_.value(x...)) { + ExternalRAMAllocator allocator(ExternalRAMAllocator::ALLOW_FAILURE); + uint8_t *buf = allocator.allocate(max_length); + if (buf != nullptr) { + size_t read_index = 0; + while (container->get_bytes_read() < max_length) { + int read = container->read(buf + read_index, std::min(max_length - read_index, 512)); + App.feed_wdt(); + yield(); + read_index += read; + } + response_body.reserve(read_index); + response_body.assign((char *) buf, read_index); + } + } + + for (auto *trigger : this->response_triggers_) { + trigger->process(container, response_body); + } + container->end(); } protected: @@ -130,9 +171,9 @@ template class HttpRequestSendAction : public Action { std::map> json_{}; std::function json_func_{nullptr}; std::vector response_triggers_; + + size_t max_response_buffer_size_{SIZE_MAX}; }; } // namespace http_request } // namespace esphome - -#endif // USE_ARDUINO diff --git a/esphome/components/http_request/http_request_arduino.cpp b/esphome/components/http_request/http_request_arduino.cpp new file mode 100644 index 0000000000..248a85a439 --- /dev/null +++ b/esphome/components/http_request/http_request_arduino.cpp @@ -0,0 +1,161 @@ +#include "http_request_arduino.h" + +#ifdef USE_ARDUINO + +#include "esphome/components/network/util.h" +#include "esphome/core/application.h" +#include "esphome/core/defines.h" +#include "esphome/core/log.h" + +#include "watchdog.h" + +namespace esphome { +namespace http_request { + +static const char *const TAG = "http_request.arduino"; + +std::shared_ptr HttpRequestArduino::start(std::string url, std::string method, std::string body, + std::list
headers) { + if (!network::is_connected()) { + this->status_momentary_error("failed", 1000); + ESP_LOGW(TAG, "HTTP Request failed; Not connected to network"); + return nullptr; + } + + std::shared_ptr container = std::make_shared(); + container->set_parent(this); + + const uint32_t start = millis(); + + bool secure = url.find("https:") != std::string::npos; + container->set_secure(secure); + + watchdog::WatchdogManager wdm(this->get_watchdog_timeout()); + +#if defined(USE_ESP8266) + std::unique_ptr stream_ptr; +#ifdef USE_HTTP_REQUEST_ESP8266_HTTPS + if (secure) { + ESP_LOGV(TAG, "ESP8266 HTTPS connection with WiFiClientSecure"); + stream_ptr = std::make_unique(); + WiFiClientSecure *secure_client = static_cast(stream_ptr.get()); + secure_client->setBufferSizes(512, 512); + secure_client->setInsecure(); + } else { + stream_ptr = std::make_unique(); + } +#else + ESP_LOGV(TAG, "ESP8266 HTTP connection with WiFiClient"); + if (secure) { + ESP_LOGE(TAG, "Can't use HTTPS connection with esp8266_disable_ssl_support"); + return nullptr; + } + stream_ptr = std::make_unique(); +#endif // USE_HTTP_REQUEST_ESP8266_HTTPS + +#if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(3, 1, 0) // && USE_ARDUINO_VERSION_CODE < VERSION_CODE(?, ?, ?) + if (!secure) { + ESP_LOGW(TAG, "Using HTTP on Arduino version >= 3.1 is **very** slow. Consider setting framework version to 3.0.2 " + "in your YAML, or use HTTPS"); + } +#endif // USE_ARDUINO_VERSION_CODE + + container->client_.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); + bool status = container->client_.begin(*stream_ptr, url.c_str()); + +#elif defined(USE_RP2040) + if (secure) { + container->client_.setInsecure(); + } + bool status = container->client_.begin(url.c_str()); +#elif defined(USE_ESP32) + bool status = container->client_.begin(url.c_str()); +#endif + + App.feed_wdt(); + + if (!status) { + ESP_LOGW(TAG, "HTTP Request failed; URL: %s", url.c_str()); + container->end(); + this->status_momentary_error("failed", 1000); + return nullptr; + } + + container->client_.setReuse(true); + container->client_.setTimeout(this->timeout_); +#if defined(USE_ESP32) + container->client_.setConnectTimeout(this->timeout_); +#endif + + if (this->useragent_ != nullptr) { + container->client_.setUserAgent(this->useragent_); + } + for (const auto &header : headers) { + container->client_.addHeader(header.name, header.value, false, true); + } + + // returned needed headers must be collected before the requests + static const char *header_keys[] = {"Content-Length", "Content-Type"}; + static const size_t HEADER_COUNT = sizeof(header_keys) / sizeof(header_keys[0]); + container->client_.collectHeaders(header_keys, HEADER_COUNT); + + container->status_code = container->client_.sendRequest(method.c_str(), body.c_str()); + if (container->status_code < 0) { + ESP_LOGW(TAG, "HTTP Request failed; URL: %s; Error: %s", url.c_str(), + HTTPClient::errorToString(container->status_code).c_str()); + this->status_momentary_error("failed", 1000); + container->end(); + return nullptr; + } + + if (container->status_code < 200 || container->status_code >= 300) { + ESP_LOGE(TAG, "HTTP Request failed; URL: %s; Code: %d", url.c_str(), container->status_code); + this->status_momentary_error("failed", 1000); + container->end(); + return nullptr; + } + + int content_length = container->client_.getSize(); + ESP_LOGD(TAG, "Content-Length: %d", content_length); + container->content_length = (size_t) content_length; + container->duration_ms = millis() - start; + + return container; +} + +int HttpContainerArduino::read(uint8_t *buf, size_t max_len) { + const uint32_t start = millis(); + watchdog::WatchdogManager wdm(this->parent_->get_watchdog_timeout()); + + WiFiClient *stream_ptr = this->client_.getStreamPtr(); + if (stream_ptr == nullptr) { + ESP_LOGE(TAG, "Stream pointer vanished!"); + return -1; + } + + int available_data = stream_ptr->available(); + int bufsize = std::min(max_len, std::min(this->content_length - this->bytes_read_, (size_t) available_data)); + + if (bufsize == 0) { + this->duration_ms += (millis() - start); + return 0; + } + + App.feed_wdt(); + int read_len = stream_ptr->readBytes(buf, bufsize); + this->bytes_read_ += read_len; + + this->duration_ms += (millis() - start); + + return read_len; +} + +void HttpContainerArduino::end() { + watchdog::WatchdogManager wdm(this->parent_->get_watchdog_timeout()); + this->client_.end(); +} + +} // namespace http_request +} // namespace esphome + +#endif // USE_ARDUINO diff --git a/esphome/components/http_request/http_request_arduino.h b/esphome/components/http_request/http_request_arduino.h new file mode 100644 index 0000000000..dfdf4a35e2 --- /dev/null +++ b/esphome/components/http_request/http_request_arduino.h @@ -0,0 +1,40 @@ +#pragma once + +#include "http_request.h" + +#ifdef USE_ARDUINO + +#if defined(USE_ESP32) || defined(USE_RP2040) +#include +#endif +#ifdef USE_ESP8266 +#include +#ifdef USE_HTTP_REQUEST_ESP8266_HTTPS +#include +#endif +#endif + +namespace esphome { +namespace http_request { + +class HttpRequestArduino; +class HttpContainerArduino : public HttpContainer { + public: + int read(uint8_t *buf, size_t max_len) override; + void end() override; + + protected: + friend class HttpRequestArduino; + HTTPClient client_{}; +}; + +class HttpRequestArduino : public HttpRequestComponent { + public: + std::shared_ptr start(std::string url, std::string method, std::string body, + std::list
headers) override; +}; + +} // namespace http_request +} // namespace esphome + +#endif // USE_ARDUINO diff --git a/esphome/components/http_request/http_request_idf.cpp b/esphome/components/http_request/http_request_idf.cpp new file mode 100644 index 0000000000..138e0438f4 --- /dev/null +++ b/esphome/components/http_request/http_request_idf.cpp @@ -0,0 +1,155 @@ +#include "http_request_idf.h" + +#ifdef USE_ESP_IDF + +#include "esphome/components/network/util.h" +#include "esphome/core/application.h" +#include "esphome/core/defines.h" +#include "esphome/core/log.h" + +#if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE +#include "esp_crt_bundle.h" +#endif + +#include "watchdog.h" + +namespace esphome { +namespace http_request { + +static const char *const TAG = "http_request.idf"; + +std::shared_ptr HttpRequestIDF::start(std::string url, std::string method, std::string body, + std::list
headers) { + if (!network::is_connected()) { + this->status_momentary_error("failed", 1000); + ESP_LOGE(TAG, "HTTP Request failed; Not connected to network"); + return nullptr; + } + + esp_http_client_method_t method_idf; + if (method == "GET") { + method_idf = HTTP_METHOD_GET; + } else if (method == "POST") { + method_idf = HTTP_METHOD_POST; + } else if (method == "PUT") { + method_idf = HTTP_METHOD_PUT; + } else if (method == "DELETE") { + method_idf = HTTP_METHOD_DELETE; + } else if (method == "PATCH") { + method_idf = HTTP_METHOD_PATCH; + } else { + this->status_momentary_error("failed", 1000); + ESP_LOGE(TAG, "HTTP Request failed; Unsupported method"); + return nullptr; + } + + bool secure = url.find("https:") != std::string::npos; + + esp_http_client_config_t config = {}; + + config.url = url.c_str(); + config.method = method_idf; + config.timeout_ms = this->timeout_; + config.disable_auto_redirect = !this->follow_redirects_; + config.max_redirection_count = this->redirect_limit_; +#if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE + if (secure) { + config.crt_bundle_attach = esp_crt_bundle_attach; + } +#endif + + if (this->useragent_ != nullptr) { + config.user_agent = this->useragent_; + } + + const uint32_t start = millis(); + watchdog::WatchdogManager wdm(this->get_watchdog_timeout()); + + esp_http_client_handle_t client = esp_http_client_init(&config); + + std::shared_ptr container = std::make_shared(client); + container->set_parent(this); + + container->set_secure(secure); + + for (const auto &header : headers) { + esp_http_client_set_header(client, header.name, header.value); + } + + int body_len = body.length(); + + esp_err_t err = esp_http_client_open(client, body_len); + if (err != ESP_OK) { + this->status_momentary_error("failed", 1000); + ESP_LOGE(TAG, "HTTP Request failed: %s", esp_err_to_name(err)); + esp_http_client_cleanup(client); + return nullptr; + } + + if (body_len > 0) { + int write_left = body_len; + int write_index = 0; + const char *buf = body.c_str(); + while (body_len > 0) { + int written = esp_http_client_write(client, buf + write_index, write_left); + if (written < 0) { + err = ESP_FAIL; + break; + } + write_left -= written; + write_index += written; + } + } + + if (err != ESP_OK) { + this->status_momentary_error("failed", 1000); + ESP_LOGE(TAG, "HTTP Request failed: %s", esp_err_to_name(err)); + esp_http_client_cleanup(client); + return nullptr; + } + + container->content_length = esp_http_client_fetch_headers(client); + const auto status_code = esp_http_client_get_status_code(client); + container->status_code = status_code; + + if (status_code < 200 || status_code >= 300) { + ESP_LOGE(TAG, "HTTP Request failed; URL: %s; Code: %d", url.c_str(), status_code); + this->status_momentary_error("failed", 1000); + esp_http_client_cleanup(client); + return nullptr; + } + container->duration_ms = millis() - start; + return container; +} + +int HttpContainerIDF::read(uint8_t *buf, size_t max_len) { + const uint32_t start = millis(); + watchdog::WatchdogManager wdm(this->parent_->get_watchdog_timeout()); + + int bufsize = std::min(max_len, this->content_length - this->bytes_read_); + + if (bufsize == 0) { + this->duration_ms += (millis() - start); + return 0; + } + + App.feed_wdt(); + int read_len = esp_http_client_read(this->client_, (char *) buf, bufsize); + this->bytes_read_ += read_len; + + this->duration_ms += (millis() - start); + + return read_len; +} + +void HttpContainerIDF::end() { + watchdog::WatchdogManager wdm(this->parent_->get_watchdog_timeout()); + + esp_http_client_close(this->client_); + esp_http_client_cleanup(this->client_); +} + +} // namespace http_request +} // namespace esphome + +#endif // USE_ESP_IDF diff --git a/esphome/components/http_request/http_request_idf.h b/esphome/components/http_request/http_request_idf.h new file mode 100644 index 0000000000..79f850a636 --- /dev/null +++ b/esphome/components/http_request/http_request_idf.h @@ -0,0 +1,34 @@ +#pragma once + +#include "http_request.h" + +#ifdef USE_ESP_IDF + +#include +#include +#include +#include + +namespace esphome { +namespace http_request { + +class HttpContainerIDF : public HttpContainer { + public: + HttpContainerIDF(esp_http_client_handle_t client) : client_(client) {} + int read(uint8_t *buf, size_t max_len) override; + void end() override; + + protected: + esp_http_client_handle_t client_; +}; + +class HttpRequestIDF : public HttpRequestComponent { + public: + std::shared_ptr start(std::string url, std::string method, std::string body, + std::list
headers) override; +}; + +} // namespace http_request +} // namespace esphome + +#endif // USE_ESP_IDF diff --git a/esphome/components/http_request/ota/__init__.py b/esphome/components/http_request/ota/__init__.py index 6a56fac83a..0ef1fc2348 100644 --- a/esphome/components/http_request/ota/__init__.py +++ b/esphome/components/http_request/ota/__init__.py @@ -2,92 +2,35 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation from esphome.const import ( - CONF_ESP8266_DISABLE_SSL_SUPPORT, CONF_ID, CONF_PASSWORD, - CONF_TIMEOUT, CONF_URL, CONF_USERNAME, ) -from esphome.components import esp32 from esphome.components.ota import BASE_OTA_SCHEMA, ota_to_code, OTAComponent -from esphome.core import CORE, coroutine_with_priority -from .. import http_request_ns +from esphome.core import coroutine_with_priority +from .. import CONF_HTTP_REQUEST_ID, http_request_ns, HttpRequestComponent CODEOWNERS = ["@oarcher"] AUTO_LOAD = ["md5"] -DEPENDENCIES = ["network"] +DEPENDENCIES = ["network", "http_request"] CONF_MD5 = "md5" CONF_MD5_URL = "md5_url" -CONF_VERIFY_SSL = "verify_ssl" -CONF_WATCHDOG_TIMEOUT = "watchdog_timeout" OtaHttpRequestComponent = http_request_ns.class_( "OtaHttpRequestComponent", OTAComponent ) -OtaHttpRequestComponentArduino = http_request_ns.class_( - "OtaHttpRequestComponentArduino", OtaHttpRequestComponent -) -OtaHttpRequestComponentIDF = http_request_ns.class_( - "OtaHttpRequestComponentIDF", OtaHttpRequestComponent -) OtaHttpRequestComponentFlashAction = http_request_ns.class_( "OtaHttpRequestComponentFlashAction", automation.Action ) - -def validate_ssl_verification(config): - error_message = "" - - if CORE.is_esp32: - if not CORE.using_esp_idf and config[CONF_VERIFY_SSL]: - error_message = "ESPHome supports certificate verification only via ESP-IDF" - - if CORE.is_rp2040 and config[CONF_VERIFY_SSL]: - error_message = "ESPHome does not support certificate verification in Arduino" - - if ( - CORE.is_esp8266 - and not config[CONF_ESP8266_DISABLE_SSL_SUPPORT] - and config[CONF_VERIFY_SSL] - ): - error_message = "ESPHome does not support certificate verification in Arduino" - - if len(error_message) > 0: - raise cv.Invalid( - f"{error_message}. Set '{CONF_VERIFY_SSL}: false' to skip certificate validation and allow less secure HTTPS connections." - ) - - return config - - -def _declare_request_class(value): - if CORE.using_esp_idf: - return cv.declare_id(OtaHttpRequestComponentIDF)(value) - - if CORE.is_esp8266 or CORE.is_esp32 or CORE.is_rp2040: - return cv.declare_id(OtaHttpRequestComponentArduino)(value) - return NotImplementedError - - CONFIG_SCHEMA = cv.All( cv.Schema( { - cv.GenerateID(): _declare_request_class, - cv.SplitDefault(CONF_ESP8266_DISABLE_SSL_SUPPORT, esp8266=False): cv.All( - cv.only_on_esp8266, cv.boolean - ), - cv.Optional(CONF_VERIFY_SSL, default=True): cv.boolean, - cv.Optional( - CONF_TIMEOUT, default="5min" - ): cv.positive_time_period_milliseconds, - cv.Optional(CONF_WATCHDOG_TIMEOUT): cv.All( - cv.Any(cv.only_on_esp32, cv.only_on_rp2040), - cv.positive_not_null_time_period, - cv.positive_time_period_milliseconds, - ), + cv.GenerateID(): cv.declare_id(OtaHttpRequestComponent), + cv.GenerateID(CONF_HTTP_REQUEST_ID): cv.use_id(HttpRequestComponent), } ) .extend(BASE_OTA_SCHEMA) @@ -98,7 +41,6 @@ CONFIG_SCHEMA = cv.All( esp_idf=cv.Version(0, 0, 0), rp2040_arduino=cv.Version(0, 0, 0), ), - validate_ssl_verification, ) @@ -106,41 +48,8 @@ CONFIG_SCHEMA = cv.All( async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await ota_to_code(var, config) - - cg.add(var.set_timeout(config[CONF_TIMEOUT])) - - if timeout_ms := config.get(CONF_WATCHDOG_TIMEOUT): - cg.add_define( - "USE_HTTP_REQUEST_OTA_WATCHDOG_TIMEOUT", - timeout_ms, - ) - - if CORE.is_esp8266 and not config[CONF_ESP8266_DISABLE_SSL_SUPPORT]: - cg.add_define("USE_HTTP_REQUEST_ESP8266_HTTPS") - - if CORE.is_esp32: - if CORE.using_esp_idf: - esp32.add_idf_sdkconfig_option( - "CONFIG_MBEDTLS_CERTIFICATE_BUNDLE", - config.get(CONF_VERIFY_SSL), - ) - esp32.add_idf_sdkconfig_option( - "CONFIG_ESP_TLS_INSECURE", - not config.get(CONF_VERIFY_SSL), - ) - esp32.add_idf_sdkconfig_option( - "CONFIG_ESP_TLS_SKIP_SERVER_CERT_VERIFY", - not config.get(CONF_VERIFY_SSL), - ) - else: - cg.add_library("WiFiClientSecure", None) - cg.add_library("HTTPClient", None) - if CORE.is_esp8266: - cg.add_library("ESP8266HTTPClient", None) - if CORE.is_rp2040 and CORE.using_arduino: - cg.add_library("HTTPClient", None) - await cg.register_component(var, config) + await cg.register_parented(var, config[CONF_HTTP_REQUEST_ID]) OTA_HTTP_REQUEST_FLASH_ACTION_SCHEMA = cv.All( @@ -148,7 +57,9 @@ OTA_HTTP_REQUEST_FLASH_ACTION_SCHEMA = cv.All( { cv.GenerateID(): cv.use_id(OtaHttpRequestComponent), cv.Optional(CONF_MD5_URL): cv.templatable(cv.url), - cv.Optional(CONF_MD5): cv.templatable(cv.string), + cv.Optional(CONF_MD5): cv.templatable( + cv.All(cv.string, cv.Length(min=32, max=32)) + ), cv.Optional(CONF_PASSWORD): cv.templatable(cv.string), cv.Optional(CONF_USERNAME): cv.templatable(cv.string), cv.Required(CONF_URL): cv.templatable(cv.url), @@ -159,7 +70,7 @@ OTA_HTTP_REQUEST_FLASH_ACTION_SCHEMA = cv.All( @automation.register_action( - "ota_http_request.flash", + "ota.http_request.flash", OtaHttpRequestComponentFlashAction, OTA_HTTP_REQUEST_FLASH_ACTION_SCHEMA, ) diff --git a/esphome/components/http_request/ota/ota_http_request.cpp b/esphome/components/http_request/ota/ota_http_request.cpp index cf0816c858..a41f552baf 100644 --- a/esphome/components/http_request/ota/ota_http_request.cpp +++ b/esphome/components/http_request/ota/ota_http_request.cpp @@ -1,16 +1,16 @@ #include "ota_http_request.h" -#include "watchdog.h" +#include "../watchdog.h" #include "esphome/core/application.h" #include "esphome/core/defines.h" #include "esphome/core/log.h" #include "esphome/components/md5/md5.h" +#include "esphome/components/ota/ota_backend.h" #include "esphome/components/ota/ota_backend_arduino_esp32.h" #include "esphome/components/ota/ota_backend_arduino_esp8266.h" #include "esphome/components/ota/ota_backend_arduino_rp2040.h" #include "esphome/components/ota/ota_backend_esp_idf.h" -#include "esphome/components/ota/ota_backend.h" namespace esphome { namespace http_request { @@ -21,25 +21,7 @@ void OtaHttpRequestComponent::setup() { #endif } -void OtaHttpRequestComponent::dump_config() { - ESP_LOGCONFIG(TAG, "Over-The-Air updates via HTTP request:"); - ESP_LOGCONFIG(TAG, " Timeout: %llus", this->timeout_ / 1000); -#ifdef USE_ESP8266 -#ifdef USE_HTTP_REQUEST_ESP8266_HTTPS - ESP_LOGCONFIG(TAG, " ESP8266 SSL support: No"); -#else - ESP_LOGCONFIG(TAG, " ESP8266 SSL support: Yes"); -#endif -#endif -#ifdef CONFIG_MBEDTLS_CERTIFICATE_BUNDLE - ESP_LOGCONFIG(TAG, " TLS server verification: Yes"); -#else - ESP_LOGCONFIG(TAG, " TLS server verification: No"); -#endif -#ifdef USE_HTTP_REQUEST_OTA_WATCHDOG_TIMEOUT - ESP_LOGCONFIG(TAG, " Watchdog timeout: %ds", USE_HTTP_REQUEST_OTA_WATCHDOG_TIMEOUT / 1000); -#endif -}; +void OtaHttpRequestComponent::dump_config() { ESP_LOGCONFIG(TAG, "Over-The-Air updates via HTTP request"); }; void OtaHttpRequestComponent::set_md5_url(const std::string &url) { if (!this->validate_url_(url)) { @@ -58,20 +40,6 @@ void OtaHttpRequestComponent::set_url(const std::string &url) { this->url_ = url; } -bool OtaHttpRequestComponent::check_status() { - // status can be -1, or HTTP status code - if (this->status_ < 100) { - ESP_LOGE(TAG, "HTTP server did not respond (error %d)", this->status_); - return false; - } - if (this->status_ >= 310) { - ESP_LOGE(TAG, "HTTP error %d", this->status_); - return false; - } - ESP_LOGV(TAG, "HTTP status %d", this->status_); - return true; -} - void OtaHttpRequestComponent::flash() { if (this->url_.empty()) { ESP_LOGE(TAG, "URL not set; cannot start update"); @@ -104,17 +72,18 @@ void OtaHttpRequestComponent::flash() { } } -void OtaHttpRequestComponent::cleanup_(std::unique_ptr backend) { +void OtaHttpRequestComponent::cleanup_(std::unique_ptr backend, + const std::shared_ptr &container) { if (this->update_started_) { ESP_LOGV(TAG, "Aborting OTA backend"); backend->abort(); } ESP_LOGV(TAG, "Aborting HTTP connection"); - this->http_end(); + container->end(); }; uint8_t OtaHttpRequestComponent::do_ota_() { - uint8_t buf[this->http_recv_buffer_ + 1]; + uint8_t buf[OtaHttpRequestComponent::HTTP_RECV_BUFFER + 1]; uint32_t last_progress = 0; uint32_t update_start_time = millis(); md5::MD5Digest md5_receive; @@ -132,9 +101,10 @@ uint8_t OtaHttpRequestComponent::do_ota_() { } ESP_LOGVV(TAG, "url_with_auth: %s", url_with_auth.c_str()); ESP_LOGI(TAG, "Connecting to: %s", this->url_.c_str()); - this->http_init(url_with_auth); - if (!this->check_status()) { - this->http_end(); + + auto container = this->parent_->get(url_with_auth); + + if (container == nullptr) { return OTA_CONNECTION_ERROR; } @@ -144,18 +114,18 @@ uint8_t OtaHttpRequestComponent::do_ota_() { ESP_LOGV(TAG, "OTA backend begin"); auto backend = ota::make_ota_backend(); - auto error_code = backend->begin(this->body_length_); + auto error_code = backend->begin(container->content_length); if (error_code != ota::OTA_RESPONSE_OK) { ESP_LOGW(TAG, "backend->begin error: %d", error_code); - this->cleanup_(std::move(backend)); + this->cleanup_(std::move(backend), container); return error_code; } - this->bytes_read_ = 0; - while (this->bytes_read_ < this->body_length_) { + while (container->get_bytes_read() < container->content_length) { // read a maximum of chunk_size bytes into buf. (real read size returned) - int bufsize = this->http_read(buf, this->http_recv_buffer_); - ESP_LOGVV(TAG, "bytes_read_ = %u, body_length_ = %u, bufsize = %i", this->bytes_read_, this->body_length_, bufsize); + int bufsize = container->read(buf, OtaHttpRequestComponent::HTTP_RECV_BUFFER); + ESP_LOGVV(TAG, "bytes_read_ = %u, body_length_ = %u, bufsize = %i", container->get_bytes_read(), + container->content_length, bufsize); // feed watchdog and give other tasks a chance to run App.feed_wdt(); @@ -163,9 +133,9 @@ uint8_t OtaHttpRequestComponent::do_ota_() { if (bufsize < 0) { ESP_LOGE(TAG, "Stream closed"); - this->cleanup_(std::move(backend)); + this->cleanup_(std::move(backend), container); return OTA_CONNECTION_ERROR; - } else if (bufsize > 0 && bufsize <= this->http_recv_buffer_) { + } else if (bufsize > 0 && bufsize <= OtaHttpRequestComponent::HTTP_RECV_BUFFER) { // add read bytes to MD5 md5_receive.add(buf, bufsize); @@ -176,16 +146,16 @@ uint8_t OtaHttpRequestComponent::do_ota_() { // error code explanation available at // https://github.com/esphome/esphome/blob/dev/esphome/components/ota/ota_backend.h ESP_LOGE(TAG, "Error code (%02X) writing binary data to flash at offset %d and size %d", error_code, - this->bytes_read_ - bufsize, this->body_length_); - this->cleanup_(std::move(backend)); + container->get_bytes_read() - bufsize, container->content_length); + this->cleanup_(std::move(backend), container); return error_code; } } uint32_t now = millis(); - if ((now - last_progress > 1000) or (this->bytes_read_ == this->body_length_)) { + if ((now - last_progress > 1000) or (container->get_bytes_read() == container->content_length)) { last_progress = now; - float percentage = this->bytes_read_ * 100.0f / this->body_length_; + float percentage = container->get_bytes_read() * 100.0f / container->content_length; ESP_LOGD(TAG, "Progress: %0.1f%%", percentage); #ifdef USE_OTA_STATE_CALLBACK this->state_callback_.call(ota::OTA_IN_PROGRESS, percentage, 0); @@ -201,13 +171,13 @@ uint8_t OtaHttpRequestComponent::do_ota_() { this->md5_computed_ = md5_receive_str.get(); if (strncmp(this->md5_computed_.c_str(), this->md5_expected_.c_str(), MD5_SIZE) != 0) { ESP_LOGE(TAG, "MD5 computed: %s - Aborting due to MD5 mismatch", this->md5_computed_.c_str()); - this->cleanup_(std::move(backend)); + this->cleanup_(std::move(backend), container); return ota::OTA_RESPONSE_ERROR_MD5_MISMATCH; } else { backend->set_update_md5(md5_receive_str.get()); } - this->http_end(); + container->end(); // feed watchdog and give other tasks a chance to run App.feed_wdt(); @@ -217,7 +187,7 @@ uint8_t OtaHttpRequestComponent::do_ota_() { error_code = backend->end(); if (error_code != ota::OTA_RESPONSE_OK) { ESP_LOGW(TAG, "Error ending update! error_code: %d", error_code); - this->cleanup_(std::move(backend)); + this->cleanup_(std::move(backend), container); return error_code; } @@ -256,28 +226,32 @@ bool OtaHttpRequestComponent::http_get_md5_() { ESP_LOGVV(TAG, "url_with_auth: %s", url_with_auth.c_str()); ESP_LOGI(TAG, "Connecting to: %s", this->md5_url_.c_str()); - this->http_init(url_with_auth); - if (!this->check_status()) { - this->http_end(); + auto container = this->parent_->get(url_with_auth); + if (container == nullptr) { + ESP_LOGE(TAG, "Failed to connect to MD5 URL"); return false; } - int length = this->body_length_; - if (length < 0) { - this->http_end(); + size_t length = container->content_length; + if (length == 0) { + container->end(); return false; } if (length < MD5_SIZE) { - ESP_LOGE(TAG, "MD5 file must be %u bytes; %u bytes reported by HTTP server. Aborting", MD5_SIZE, - this->body_length_); - this->http_end(); + ESP_LOGE(TAG, "MD5 file must be %u bytes; %u bytes reported by HTTP server. Aborting", MD5_SIZE, length); + container->end(); return false; } - this->bytes_read_ = 0; this->md5_expected_.resize(MD5_SIZE); - auto read_len = this->http_read((uint8_t *) this->md5_expected_.data(), MD5_SIZE); - this->http_end(); + int read_len = 0; + while (container->get_bytes_read() < MD5_SIZE) { + read_len = container->read((uint8_t *) this->md5_expected_.data(), MD5_SIZE); + App.feed_wdt(); + yield(); + } + container->end(); + ESP_LOGV(TAG, "Read len: %u, MD5 expected: %u", read_len, MD5_SIZE); return read_len == MD5_SIZE; } diff --git a/esphome/components/http_request/ota/ota_http_request.h b/esphome/components/http_request/ota/ota_http_request.h index 9fbdf2ec25..91c7085517 100644 --- a/esphome/components/http_request/ota/ota_http_request.h +++ b/esphome/components/http_request/ota/ota_http_request.h @@ -1,13 +1,16 @@ #pragma once +#include "esphome/components/ota/ota_backend.h" #include "esphome/core/component.h" #include "esphome/core/defines.h" -#include "esphome/components/ota/ota_backend.h" +#include "esphome/core/helpers.h" #include #include #include +#include "../http_request.h" + namespace esphome { namespace http_request { @@ -20,7 +23,7 @@ enum OtaHttpRequestError : uint8_t { OTA_CONNECTION_ERROR = 0x12, }; -class OtaHttpRequestComponent : public ota::OTAComponent { +class OtaHttpRequestComponent : public ota::OTAComponent, public Parented { public: void setup() override; void dump_config() override; @@ -29,27 +32,19 @@ class OtaHttpRequestComponent : public ota::OTAComponent { void set_md5_url(const std::string &md5_url); void set_md5(const std::string &md5) { this->md5_expected_ = md5; } void set_password(const std::string &password) { this->password_ = password; } - void set_timeout(const uint64_t timeout) { this->timeout_ = timeout; } void set_url(const std::string &url); void set_username(const std::string &username) { this->username_ = username; } std::string md5_computed() { return this->md5_computed_; } std::string md5_expected() { return this->md5_expected_; } - bool check_status(); - void flash(); - virtual void http_init(const std::string &url){}; - virtual int http_read(uint8_t *buf, size_t len) { return 0; }; - virtual void http_end(){}; - protected: - void cleanup_(std::unique_ptr backend); + void cleanup_(std::unique_ptr backend, const std::shared_ptr &container); uint8_t do_ota_(); std::string get_url_with_auth_(const std::string &url); bool http_get_md5_(); - bool secure_() { return this->url_.find("https:") != std::string::npos; }; bool validate_url_(const std::string &url); std::string md5_computed_{}; @@ -58,14 +53,9 @@ class OtaHttpRequestComponent : public ota::OTAComponent { std::string password_{}; std::string username_{}; std::string url_{}; - size_t body_length_ = 0; - size_t bytes_read_ = 0; int status_ = -1; - uint64_t timeout_ = 0; bool update_started_ = false; - const uint16_t http_recv_buffer_ = 256; // the firmware GET chunk size - const uint16_t max_http_recv_buffer_ = 512; // internal max http buffer size must be > HTTP_RECV_BUFFER_ (TLS - // overhead) and must be a power of two from 512 to 4096 + static const uint16_t HTTP_RECV_BUFFER = 256; // the firmware GET chunk size }; } // namespace http_request diff --git a/esphome/components/http_request/ota/ota_http_request_arduino.cpp b/esphome/components/http_request/ota/ota_http_request_arduino.cpp deleted file mode 100644 index d1dc638d5e..0000000000 --- a/esphome/components/http_request/ota/ota_http_request_arduino.cpp +++ /dev/null @@ -1,134 +0,0 @@ -#include "ota_http_request.h" -#include "watchdog.h" - -#ifdef USE_ARDUINO -#include "ota_http_request_arduino.h" -#include "esphome/core/defines.h" -#include "esphome/core/log.h" -#include "esphome/core/application.h" -#include "esphome/components/network/util.h" -#include "esphome/components/md5/md5.h" - -namespace esphome { -namespace http_request { - -struct Header { - const char *name; - const char *value; -}; - -void OtaHttpRequestComponentArduino::http_init(const std::string &url) { - const char *header_keys[] = {"Content-Length", "Content-Type"}; - const size_t header_count = sizeof(header_keys) / sizeof(header_keys[0]); - watchdog::WatchdogManager wdts; - -#ifdef USE_ESP8266 - if (this->stream_ptr_ == nullptr && this->set_stream_ptr_()) { - ESP_LOGE(TAG, "Unable to set client"); - return; - } -#endif // USE_ESP8266 - -#ifdef USE_RP2040 - this->client_.setInsecure(); -#endif - - App.feed_wdt(); - -#if defined(USE_ESP32) || defined(USE_RP2040) - this->status_ = this->client_.begin(url.c_str()); -#endif -#ifdef USE_ESP8266 - this->client_.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); - this->status_ = this->client_.begin(*this->stream_ptr_, url.c_str()); -#endif - - if (!this->status_) { - this->client_.end(); - return; - } - - this->client_.setReuse(true); - - // returned needed headers must be collected before the requests - this->client_.collectHeaders(header_keys, header_count); - - // HTTP GET - this->status_ = this->client_.GET(); - - this->body_length_ = (size_t) this->client_.getSize(); - -#if defined(USE_ESP32) || defined(USE_RP2040) - if (this->stream_ptr_ == nullptr) { - this->set_stream_ptr_(); - } -#endif -} - -int OtaHttpRequestComponentArduino::http_read(uint8_t *buf, const size_t max_len) { -#ifdef USE_ESP8266 -#if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(3, 1, 0) // && USE_ARDUINO_VERSION_CODE < VERSION_CODE(?, ?, ?) - if (!this->secure_()) { - ESP_LOGW(TAG, "Using HTTP on Arduino version >= 3.1 is **very** slow. Consider setting framework version to 3.0.2 " - "in your YAML, or use HTTPS"); - } -#endif // USE_ARDUINO_VERSION_CODE -#endif // USE_ESP8266 - - watchdog::WatchdogManager wdts; - - // Since arduino8266 >= 3.1 using this->stream_ptr_ is broken (https://github.com/esp8266/Arduino/issues/9035) - WiFiClient *stream_ptr = this->client_.getStreamPtr(); - if (stream_ptr == nullptr) { - ESP_LOGE(TAG, "Stream pointer vanished!"); - return -1; - } - - int available_data = stream_ptr->available(); - int bufsize = std::min((int) max_len, available_data); - if (bufsize > 0) { - stream_ptr->readBytes(buf, bufsize); - this->bytes_read_ += bufsize; - buf[bufsize] = '\0'; // not fed to ota - } - - return bufsize; -} - -void OtaHttpRequestComponentArduino::http_end() { - watchdog::WatchdogManager wdts; - this->client_.end(); -} - -int OtaHttpRequestComponentArduino::set_stream_ptr_() { -#ifdef USE_ESP8266 -#ifdef USE_HTTP_REQUEST_ESP8266_HTTPS - if (this->secure_()) { - ESP_LOGV(TAG, "ESP8266 HTTPS connection with WiFiClientSecure"); - this->stream_ptr_ = std::make_unique(); - WiFiClientSecure *secure_client = static_cast(this->stream_ptr_.get()); - secure_client->setBufferSizes(this->max_http_recv_buffer_, 512); - secure_client->setInsecure(); - } else { - this->stream_ptr_ = std::make_unique(); - } -#else - ESP_LOGV(TAG, "ESP8266 HTTP connection with WiFiClient"); - if (this->secure_()) { - ESP_LOGE(TAG, "Can't use HTTPS connection with esp8266_disable_ssl_support"); - return -1; - } - this->stream_ptr_ = std::make_unique(); -#endif // USE_HTTP_REQUEST_ESP8266_HTTPS -#endif // USE_ESP8266 - -#if defined(USE_ESP32) || defined(USE_RP2040) - this->stream_ptr_ = std::unique_ptr(this->client_.getStreamPtr()); -#endif - return 0; -} - -} // namespace http_request -} // namespace esphome - -#endif // USE_ARDUINO diff --git a/esphome/components/http_request/ota/ota_http_request_arduino.h b/esphome/components/http_request/ota/ota_http_request_arduino.h deleted file mode 100644 index 02bc046520..0000000000 --- a/esphome/components/http_request/ota/ota_http_request_arduino.h +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include "ota_http_request.h" - -#ifdef USE_ARDUINO -#include "esphome/core/automation.h" -#include "esphome/core/component.h" -#include "esphome/core/defines.h" - -#include -#include -#include - -#if defined(USE_ESP32) || defined(USE_RP2040) -#include -#endif -#ifdef USE_ESP8266 -#include -#ifdef USE_HTTP_REQUEST_ESP8266_HTTPS -#include -#endif -#endif - -namespace esphome { -namespace http_request { - -class OtaHttpRequestComponentArduino : public OtaHttpRequestComponent { - public: - void http_init(const std::string &url) override; - int http_read(uint8_t *buf, size_t len) override; - void http_end() override; - - protected: - int set_stream_ptr_(); - HTTPClient client_{}; - std::unique_ptr stream_ptr_; -}; - -} // namespace http_request -} // namespace esphome - -#endif // USE_ARDUINO diff --git a/esphome/components/http_request/ota/ota_http_request_idf.cpp b/esphome/components/http_request/ota/ota_http_request_idf.cpp deleted file mode 100644 index 9fa565d9bb..0000000000 --- a/esphome/components/http_request/ota/ota_http_request_idf.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#include "ota_http_request_idf.h" -#include "watchdog.h" - -#ifdef USE_ESP_IDF -#include "esphome/core/application.h" -#include "esphome/core/defines.h" -#include "esphome/core/log.h" -#include "esphome/components/md5/md5.h" -#include "esphome/components/network/util.h" - -#include "esp_event.h" -#include "esp_http_client.h" -#include "esp_idf_version.h" -#include "esp_log.h" -#include "esp_netif.h" -#include "esp_system.h" -#include "esp_task_wdt.h" -#include "esp_tls.h" - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "nvs_flash.h" - -#include -#include -#include -#include -#include -#if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE -#include "esp_crt_bundle.h" -#endif - -namespace esphome { -namespace http_request { - -void OtaHttpRequestComponentIDF::http_init(const std::string &url) { - App.feed_wdt(); -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wmissing-field-initializers" - esp_http_client_config_t config = {nullptr}; - config.url = url.c_str(); - config.method = HTTP_METHOD_GET; - config.timeout_ms = (int) this->timeout_; - config.buffer_size = this->max_http_recv_buffer_; - config.auth_type = HTTP_AUTH_TYPE_BASIC; - config.max_authorization_retries = -1; -#if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE - if (this->secure_()) { - config.crt_bundle_attach = esp_crt_bundle_attach; - } -#endif -#pragma GCC diagnostic pop - - watchdog::WatchdogManager wdts; - this->client_ = esp_http_client_init(&config); - if ((this->status_ = esp_http_client_open(this->client_, 0)) == ESP_OK) { - this->body_length_ = esp_http_client_fetch_headers(this->client_); - this->status_ = esp_http_client_get_status_code(this->client_); - } -} - -int OtaHttpRequestComponentIDF::http_read(uint8_t *buf, const size_t max_len) { - watchdog::WatchdogManager wdts; - int bufsize = std::min(max_len, this->body_length_ - this->bytes_read_); - - App.feed_wdt(); - int read_len = esp_http_client_read(this->client_, (char *) buf, bufsize); - if (read_len > 0) { - this->bytes_read_ += bufsize; - buf[bufsize] = '\0'; // not fed to ota - } - - return read_len; -} - -void OtaHttpRequestComponentIDF::http_end() { - watchdog::WatchdogManager wdts; - - esp_http_client_close(this->client_); - esp_http_client_cleanup(this->client_); -} - -} // namespace http_request -} // namespace esphome - -#endif // USE_ESP_IDF diff --git a/esphome/components/http_request/ota/ota_http_request_idf.h b/esphome/components/http_request/ota/ota_http_request_idf.h deleted file mode 100644 index 9783b2a3e1..0000000000 --- a/esphome/components/http_request/ota/ota_http_request_idf.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include "ota_http_request.h" - -#ifdef USE_ESP_IDF -#include "esp_http_client.h" - -namespace esphome { -namespace http_request { - -class OtaHttpRequestComponentIDF : public OtaHttpRequestComponent { - public: - void http_init(const std::string &url) override; - int http_read(uint8_t *buf, size_t len) override; - void http_end() override; - - protected: - esp_http_client_handle_t client_{}; -}; - -} // namespace http_request -} // namespace esphome - -#endif // USE_ESP_IDF diff --git a/esphome/components/http_request/ota/watchdog.cpp b/esphome/components/http_request/watchdog.cpp similarity index 79% rename from esphome/components/http_request/ota/watchdog.cpp rename to esphome/components/http_request/watchdog.cpp index 663c9afaac..e609feb4dd 100644 --- a/esphome/components/http_request/ota/watchdog.cpp +++ b/esphome/components/http_request/watchdog.cpp @@ -1,7 +1,5 @@ #include "watchdog.h" -#ifdef USE_HTTP_REQUEST_OTA_WATCHDOG_TIMEOUT - #include "esphome/core/application.h" #include "esphome/core/log.h" @@ -20,14 +18,22 @@ namespace esphome { namespace http_request { namespace watchdog { -static const char *const TAG = "watchdog.http_request.ota"; +static const char *const TAG = "http_request.watchdog"; -WatchdogManager::WatchdogManager() { +WatchdogManager::WatchdogManager(uint32_t timeout_ms) : timeout_ms_(timeout_ms) { + if (timeout_ms == 0) { + return; + } this->saved_timeout_ms_ = this->get_timeout_(); - this->set_timeout_(USE_HTTP_REQUEST_OTA_WATCHDOG_TIMEOUT); + this->set_timeout_(timeout_ms); } -WatchdogManager::~WatchdogManager() { this->set_timeout_(this->saved_timeout_ms_); } +WatchdogManager::~WatchdogManager() { + if (this->timeout_ms_ == 0) { + return; + } + this->set_timeout_(this->saved_timeout_ms_); +} void WatchdogManager::set_timeout_(uint32_t timeout_ms) { ESP_LOGV(TAG, "Adjusting WDT to %" PRIu32 "ms", timeout_ms); @@ -68,4 +74,3 @@ uint32_t WatchdogManager::get_timeout_() { } // namespace watchdog } // namespace http_request } // namespace esphome -#endif diff --git a/esphome/components/http_request/ota/watchdog.h b/esphome/components/http_request/watchdog.h similarity index 84% rename from esphome/components/http_request/ota/watchdog.h rename to esphome/components/http_request/watchdog.h index 0a09dcd6fa..9b54ae6c82 100644 --- a/esphome/components/http_request/ota/watchdog.h +++ b/esphome/components/http_request/watchdog.h @@ -9,9 +9,8 @@ namespace http_request { namespace watchdog { class WatchdogManager { -#ifdef USE_HTTP_REQUEST_OTA_WATCHDOG_TIMEOUT public: - WatchdogManager(); + WatchdogManager(uint32_t timeout_ms); ~WatchdogManager(); private: @@ -19,7 +18,7 @@ class WatchdogManager { void set_timeout_(uint32_t timeout_ms); uint32_t saved_timeout_ms_{0}; -#endif + uint32_t timeout_ms_{0}; }; } // namespace watchdog diff --git a/esphome/cpp_types.py b/esphome/cpp_types.py index 0f1b7f236b..bd79d3b2f9 100644 --- a/esphome/cpp_types.py +++ b/esphome/cpp_types.py @@ -8,6 +8,7 @@ double = global_ns.namespace("double") bool_ = global_ns.namespace("bool") int_ = global_ns.namespace("int") std_ns = global_ns.namespace("std") +std_shared_ptr = std_ns.class_("shared_ptr") std_string = std_ns.class_("string") std_vector = std_ns.class_("vector") uint8 = global_ns.namespace("uint8_t") diff --git a/tests/components/http_request/common.yaml b/tests/components/http_request/common.yaml new file mode 100644 index 0000000000..2b6996c0b9 --- /dev/null +++ b/tests/components/http_request/common.yaml @@ -0,0 +1,75 @@ +substitutions: + verify_ssl: "true" + +wifi: + ssid: MySSID + password: password1 + +esphome: + on_boot: + then: + - http_request.get: + url: https://esphome.io + headers: + Content-Type: application/json + on_response: + then: + - logger.log: + format: "Response status: %d, Duration: %u ms" + args: + - response->status_code + - response->duration_ms + - http_request.post: + url: https://esphome.io + headers: + Content-Type: application/json + json: + key: value + - http_request.send: + method: PUT + url: https://esphome.io + headers: + Content-Type: application/json + body: "Some data" + +http_request: + useragent: esphome/tagreader + timeout: 10s + verify_ssl: ${verify_ssl} + +ota: + - platform: http_request + on_begin: + then: + - logger.log: "OTA start" + on_progress: + then: + - logger.log: + format: "OTA progress %0.1f%%" + args: ["x"] + on_end: + then: + - logger.log: "OTA end" + on_error: + then: + - logger.log: + format: "OTA update error %d" + args: ["x"] + on_state_change: + then: + lambda: 'ESP_LOGD("ota", "State %d", state);' + +button: + - platform: template + name: Firmware update + on_press: + then: + - ota.http_request.flash: + md5_url: http://my.ha.net:8123/local/esphome/firmware.md5 + url: http://my.ha.net:8123/local/esphome/firmware.bin + + - ota.http_request.flash: + md5: 0123456789abcdef0123456789abcdef + url: http://my.ha.net:8123/local/esphome/firmware.bin + + - logger.log: "This message should be not displayed (reboot)" diff --git a/tests/components/http_request/common_http_request.yaml b/tests/components/http_request/common_http_request.yaml deleted file mode 100644 index b00768c736..0000000000 --- a/tests/components/http_request/common_http_request.yaml +++ /dev/null @@ -1,33 +0,0 @@ -esphome: - on_boot: - then: - - http_request.get: - url: https://esphome.io - headers: - Content-Type: application/json - verify_ssl: false - on_response: - then: - - logger.log: - format: 'Response status: %d, Duration: %u ms' - args: - - status_code - - duration_ms - - http_request.post: - url: https://esphome.io - headers: - Content-Type: application/json - json: - key: value - verify_ssl: false - - http_request.send: - method: PUT - url: https://esphome.io - headers: - Content-Type: application/json - body: "Some data" - verify_ssl: false - -http_request: - useragent: esphome/tagreader - timeout: 10s diff --git a/tests/components/http_request/common_ota.yaml b/tests/components/http_request/common_ota.yaml deleted file mode 100644 index 10e7d54c3f..0000000000 --- a/tests/components/http_request/common_ota.yaml +++ /dev/null @@ -1,36 +0,0 @@ -wifi: - ssid: MySSID - password: password1 - -ota: - - platform: http_request - verify_ssl: ${verify_ssl} - on_begin: - then: - - logger.log: "OTA start" - on_progress: - then: - - logger.log: - format: "OTA progress %0.1f%%" - args: ["x"] - on_end: - then: - - logger.log: "OTA end" - on_error: - then: - - logger.log: - format: "OTA update error %d" - args: ["x"] - on_state_change: - then: - lambda: 'ESP_LOGD("ota", "State %d", state);' - -button: - - platform: template - name: Firmware update - on_press: - then: - - ota_http_request.flash: - md5_url: http://my.ha.net:8123/local/esphome/firmware.md5 - url: http://my.ha.net:8123/local/esphome/firmware.bin - - logger.log: "This message should be not displayed (reboot)" diff --git a/tests/components/http_request/test-nossl.esp8266.yaml b/tests/components/http_request/test-nossl.esp8266.yaml index 65116d5550..9fc4706c89 100644 --- a/tests/components/http_request/test-nossl.esp8266.yaml +++ b/tests/components/http_request/test-nossl.esp8266.yaml @@ -1,38 +1,4 @@ -<<: !include common_http_request.yaml +<<: !include common.yaml -wifi: - ssid: MySSID - password: password1 - -ota: - - platform: http_request - esp8266_disable_ssl_support: true - on_begin: - then: - - logger.log: "OTA start" - on_progress: - then: - - logger.log: - format: "OTA progress %0.1f%%" - args: ["x"] - on_end: - then: - - logger.log: "OTA end" - on_error: - then: - - logger.log: - format: "OTA update error %d" - args: ["x"] - on_state_change: - then: - lambda: 'ESP_LOGD("ota", "State %d", state);' - -button: - - platform: template - name: Firmware update - on_press: - then: - - ota_http_request.flash: - md5_url: http://my.ha.net:8123/local/esphome/firmware.md5 - url: http://my.ha.net:8123/local/esphome/firmware.bin - - logger.log: "This message should be not displayed (reboot)" +http_request: + esp8266_disable_ssl_support: true diff --git a/tests/components/http_request/test.esp32-c3-idf.yaml b/tests/components/http_request/test.esp32-c3-idf.yaml index da629e83a9..ee2f5aa59b 100644 --- a/tests/components/http_request/test.esp32-c3-idf.yaml +++ b/tests/components/http_request/test.esp32-c3-idf.yaml @@ -1,4 +1,4 @@ substitutions: verify_ssl: "true" -<<: !include common_ota.yaml +<<: !include common.yaml diff --git a/tests/components/http_request/test.esp32-c3.yaml b/tests/components/http_request/test.esp32-c3.yaml index 1f597bb500..c1937b5a10 100644 --- a/tests/components/http_request/test.esp32-c3.yaml +++ b/tests/components/http_request/test.esp32-c3.yaml @@ -1,5 +1,4 @@ substitutions: verify_ssl: "false" -<<: !include common_http_request.yaml -<<: !include common_ota.yaml +<<: !include common.yaml diff --git a/tests/components/http_request/test.esp32-idf.yaml b/tests/components/http_request/test.esp32-idf.yaml index da629e83a9..ee2f5aa59b 100644 --- a/tests/components/http_request/test.esp32-idf.yaml +++ b/tests/components/http_request/test.esp32-idf.yaml @@ -1,4 +1,4 @@ substitutions: verify_ssl: "true" -<<: !include common_ota.yaml +<<: !include common.yaml diff --git a/tests/components/http_request/test.esp32.yaml b/tests/components/http_request/test.esp32.yaml index 1f597bb500..c1937b5a10 100644 --- a/tests/components/http_request/test.esp32.yaml +++ b/tests/components/http_request/test.esp32.yaml @@ -1,5 +1,4 @@ substitutions: verify_ssl: "false" -<<: !include common_http_request.yaml -<<: !include common_ota.yaml +<<: !include common.yaml diff --git a/tests/components/http_request/test.esp8266.yaml b/tests/components/http_request/test.esp8266.yaml index 1f597bb500..c1937b5a10 100644 --- a/tests/components/http_request/test.esp8266.yaml +++ b/tests/components/http_request/test.esp8266.yaml @@ -1,5 +1,4 @@ substitutions: verify_ssl: "false" -<<: !include common_http_request.yaml -<<: !include common_ota.yaml +<<: !include common.yaml diff --git a/tests/components/http_request/test.rp2040.yaml b/tests/components/http_request/test.rp2040.yaml index 077e4d82da..c1937b5a10 100644 --- a/tests/components/http_request/test.rp2040.yaml +++ b/tests/components/http_request/test.rp2040.yaml @@ -1,4 +1,4 @@ substitutions: verify_ssl: "false" -<<: !include common_ota.yaml +<<: !include common.yaml diff --git a/tests/test1.yaml b/tests/test1.yaml index c49ff307e5..2dacfda536 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -25,31 +25,6 @@ esphome: then: - lambda: >- ESP_LOGV("main", "ON LOOP!"); - - http_request.get: - url: https://esphome.io - headers: - Content-Type: application/json - verify_ssl: false - - http_request.post: - url: https://esphome.io - verify_ssl: false - json: - key: !lambda |- - return id(${textname}_text).state; - greeting: Hello World - - http_request.send: - method: PUT - url: https://esphome.io - headers: - Content-Type: application/json - body: Some data - verify_ssl: false - on_response: - then: - - logger.log: - format: "Response status: %d" - args: - - status_code build_path: build/test1 packages: @@ -84,10 +59,6 @@ network: mdns: disabled: false -http_request: - useragent: esphome/device - timeout: 10s - mqtt: broker: "192.168.178.84" port: 1883 diff --git a/tests/test3.1.yaml b/tests/test3.1.yaml index 018a4d94f3..c3b078fe67 100644 --- a/tests/test3.1.yaml +++ b/tests/test3.1.yaml @@ -447,26 +447,6 @@ switch: switches: - id: custom_switch name: Custom Switch - on_turn_on: - - http_request.get: - url: https://esphome.io - headers: - Content-Type: application/json - verify_ssl: false - - http_request.post: - url: https://esphome.io - verify_ssl: false - json: - key: !lambda |- - return id(custom_text_sensor).state; - greeting: Hello World - - http_request.send: - method: PUT - url: https://esphome.io - headers: - Content-Type: application/json - body: Some data - verify_ssl: false - platform: template name: open_vent id: open_vent @@ -722,10 +702,6 @@ display: lambda: |- it.printdigit("hello"); -http_request: - useragent: esphome/device - timeout: 10s - button: - platform: output id: output_button diff --git a/tests/test7.yaml b/tests/test7.yaml index b22fbfbcb4..ac193eae4e 100644 --- a/tests/test7.yaml +++ b/tests/test7.yaml @@ -1,7 +1,7 @@ # Tests for ESP32-C3 boards which use toolchain-riscv32-esp --- wifi: - ssid: 'ssid' + ssid: "ssid" network: enable_ipv6: true @@ -12,31 +12,12 @@ esp32: type: arduino esphome: - name: 'on-response-test' - on_boot: - then: - - http_request.send: - method: PUT - url: https://esphome.io - headers: - Content-Type: application/json - body: Some data - verify_ssl: false - on_response: - then: - - logger.log: - format: "Response status: %d" - args: - - status_code + name: test7 logger: debug: -http_request: - useragent: esphome/tagreader - timeout: 10s - sensor: - platform: adc id: adc_sensor_p4 From 6de79d6cfbdf42b5fdc9b1f880b86210900dab5a Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 10 Jun 2024 15:22:41 +1200 Subject: [PATCH 1559/2101] [i2s_speaker] A few fixes (#6872) --- .../i2s_audio/speaker/i2s_audio_speaker.cpp | 40 +++++++++++++++---- .../i2s_audio/speaker/i2s_audio_speaker.h | 2 +- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp index 546c2c98f7..6b07ecb1b6 100644 --- a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +++ b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp @@ -38,15 +38,22 @@ void I2SAudioSpeaker::start() { ESP_LOGE(TAG, "Cannot start audio, speaker failed to setup"); return; } + if (this->task_created_) { + ESP_LOGW(TAG, "Called start while task has been already created."); + return; + } this->state_ = speaker::STATE_STARTING; } void I2SAudioSpeaker::start_() { + if (this->task_created_) { + return; + } if (!this->parent_->try_lock()) { return; // Waiting for another i2s component to return lock } - this->state_ = speaker::STATE_RUNNING; xTaskCreate(I2SAudioSpeaker::player_task, "speaker_task", 8192, (void *) this, 1, &this->player_task_handle_); + this->task_created_ = true; } void I2SAudioSpeaker::player_task(void *params) { @@ -131,7 +138,16 @@ void I2SAudioSpeaker::player_task(void *params) { (10 / portTICK_PERIOD_MS)); if (err != ESP_OK) { event = {.type = TaskEventType::WARNING, .err = err}; - xQueueSend(this_speaker->event_queue_, &event, portMAX_DELAY); + if (xQueueSend(this_speaker->event_queue_, &event, 10 / portTICK_PERIOD_MS) != pdTRUE) { + ESP_LOGW(TAG, "Failed to send WARNING event"); + } + continue; + } + if (bytes_written != sizeof(sample)) { + event = {.type = TaskEventType::WARNING, .err = ESP_FAIL}; + if (xQueueSend(this_speaker->event_queue_, &event, 10 / portTICK_PERIOD_MS) != pdTRUE) { + ESP_LOGW(TAG, "Failed to send WARNING event"); + } continue; } remaining--; @@ -139,18 +155,25 @@ void I2SAudioSpeaker::player_task(void *params) { } event.type = TaskEventType::PLAYING; - xQueueSend(this_speaker->event_queue_, &event, portMAX_DELAY); + event.err = current; + if (xQueueSend(this_speaker->event_queue_, &event, 10 / portTICK_PERIOD_MS) != pdTRUE) { + ESP_LOGW(TAG, "Failed to send PLAYING event"); + } + } + + event.type = TaskEventType::STOPPING; + if (xQueueSend(this_speaker->event_queue_, &event, 10 / portTICK_PERIOD_MS) != pdTRUE) { + ESP_LOGW(TAG, "Failed to send STOPPING event"); } i2s_zero_dma_buffer(this_speaker->parent_->get_port()); - event.type = TaskEventType::STOPPING; - xQueueSend(this_speaker->event_queue_, &event, portMAX_DELAY); - i2s_driver_uninstall(this_speaker->parent_->get_port()); event.type = TaskEventType::STOPPED; - xQueueSend(this_speaker->event_queue_, &event, portMAX_DELAY); + if (xQueueSend(this_speaker->event_queue_, &event, 10 / portTICK_PERIOD_MS) != pdTRUE) { + ESP_LOGW(TAG, "Failed to send STOPPED event"); + } while (true) { delay(10); @@ -181,6 +204,7 @@ void I2SAudioSpeaker::watch_() { break; case TaskEventType::STARTED: ESP_LOGD(TAG, "Started I2S Audio Speaker"); + this->state_ = speaker::STATE_RUNNING; break; case TaskEventType::STOPPING: ESP_LOGD(TAG, "Stopping I2S Audio Speaker"); @@ -191,6 +215,7 @@ void I2SAudioSpeaker::watch_() { case TaskEventType::STOPPED: this->state_ = speaker::STATE_STOPPED; vTaskDelete(this->player_task_handle_); + this->task_created_ = false; this->player_task_handle_ = nullptr; this->parent_->unlock(); xQueueReset(this->buffer_queue_); @@ -208,7 +233,6 @@ void I2SAudioSpeaker::loop() { switch (this->state_) { case speaker::STATE_STARTING: this->start_(); - break; case speaker::STATE_RUNNING: case speaker::STATE_STOPPING: this->watch_(); diff --git a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h index 20c36a69d3..1800feaeec 100644 --- a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +++ b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h @@ -60,7 +60,6 @@ class I2SAudioSpeaker : public Component, public speaker::Speaker, public I2SAud protected: void start_(); - // void stop_(); void watch_(); static void player_task(void *params); @@ -70,6 +69,7 @@ class I2SAudioSpeaker : public Component, public speaker::Speaker, public I2SAud QueueHandle_t event_queue_; uint8_t dout_pin_{0}; + bool task_created_{false}; #if SOC_I2S_SUPPORTS_DAC i2s_dac_mode_t internal_dac_mode_{I2S_DAC_CHANNEL_DISABLE}; From dceab6ce29493e67caaa8cdadf8cf7f4df063635 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 10 Jun 2024 15:22:55 +1200 Subject: [PATCH 1560/2101] [voice_assistant] Write less data to speaker each loop (#6877) --- esphome/components/voice_assistant/voice_assistant.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index e4fd2f2e9d..1fa8236cf4 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -428,14 +428,15 @@ void VoiceAssistant::loop() { #ifdef USE_SPEAKER void VoiceAssistant::write_speaker_() { if (this->speaker_buffer_size_ > 0) { - size_t written = this->speaker_->play(this->speaker_buffer_, this->speaker_buffer_size_); + size_t write_chunk = std::min(this->speaker_buffer_size_, 4 * 1024); + size_t written = this->speaker_->play(this->speaker_buffer_, write_chunk); if (written > 0) { memmove(this->speaker_buffer_, this->speaker_buffer_ + written, this->speaker_buffer_size_ - written); this->speaker_buffer_size_ -= written; this->speaker_buffer_index_ -= written; this->set_timeout("speaker-timeout", 5000, [this]() { this->speaker_->stop(); }); } else { - ESP_LOGD(TAG, "Speaker buffer full, trying again next loop"); + ESP_LOGV(TAG, "Speaker buffer full, trying again next loop"); } } } @@ -798,7 +799,7 @@ void VoiceAssistant::on_audio(const api::VoiceAssistantAudio &msg) { this->speaker_buffer_index_ += msg.data.length(); this->speaker_buffer_size_ += msg.data.length(); this->speaker_bytes_received_ += msg.data.length(); - ESP_LOGD(TAG, "Received audio: %d bytes from API", msg.data.length()); + ESP_LOGV(TAG, "Received audio: %" PRId32 " bytes from API", msg.data.length()); } else { ESP_LOGE(TAG, "Cannot receive audio, buffer is full"); } From 51a8a7e875fff4d9687f743a4fc8c02a6f201e9f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 Jun 2024 10:17:18 +1200 Subject: [PATCH 1561/2101] Bump docker/build-push-action from 5.3.0 to 5.4.0 in /.github/actions/build-image (#6883) 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 d36bd65bb6..d792ab5f4c 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -46,7 +46,7 @@ runs: - name: Build and push to ghcr by digest id: build-ghcr - uses: docker/build-push-action@v5.3.0 + uses: docker/build-push-action@v5.4.0 with: context: . file: ./docker/Dockerfile @@ -69,7 +69,7 @@ runs: - name: Build and push to dockerhub by digest id: build-dockerhub - uses: docker/build-push-action@v5.3.0 + uses: docker/build-push-action@v5.4.0 with: context: . file: ./docker/Dockerfile From 95e45dc12c9e313cbb5787978b3e067f581c76c9 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 11 Jun 2024 10:40:56 +1200 Subject: [PATCH 1562/2101] Allow parse_json to return a boolean result (#6884) * Allow parse_json to return a boolean result * Remove pass variable --- esphome/components/json/json_util.cpp | 17 ++++++++--------- esphome/components/json/json_util.h | 4 ++-- esphome/components/mqtt/mqtt_client.cpp | 5 ++++- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/esphome/components/json/json_util.cpp b/esphome/components/json/json_util.cpp index bef494b64d..89ec13fe5b 100644 --- a/esphome/components/json/json_util.cpp +++ b/esphome/components/json/json_util.cpp @@ -62,7 +62,7 @@ std::string build_json(const json_build_t &f) { } } -void parse_json(const std::string &data, const json_parse_t &f) { +bool parse_json(const std::string &data, const json_parse_t &f) { // Here we are allocating 1.5 times the data size, // with the heap size minus 2kb to be safe if less than that // as we can not have a true dynamic sized document. @@ -76,14 +76,13 @@ void parse_json(const std::string &data, const json_parse_t &f) { #elif defined(USE_LIBRETINY) const size_t free_heap = lt_heap_get_free(); #endif - bool pass = false; size_t request_size = std::min(free_heap, (size_t) (data.size() * 1.5)); - do { + while (true) { DynamicJsonDocument json_document(request_size); if (json_document.capacity() == 0) { ESP_LOGE(TAG, "Could not allocate memory for JSON document! Requested %u bytes, free heap: %u", request_size, free_heap); - return; + return false; } DeserializationError err = deserializeJson(json_document, data); json_document.shrinkToFit(); @@ -91,21 +90,21 @@ void parse_json(const std::string &data, const json_parse_t &f) { JsonObject root = json_document.as(); if (err == DeserializationError::Ok) { - pass = true; - f(root); + return f(root); } else if (err == DeserializationError::NoMemory) { if (request_size * 2 >= free_heap) { ESP_LOGE(TAG, "Can not allocate more memory for deserialization. Consider making source string smaller"); - return; + return false; } ESP_LOGV(TAG, "Increasing memory allocation."); request_size *= 2; continue; } else { ESP_LOGE(TAG, "JSON parse error: %s", err.c_str()); - return; + return false; } - } while (!pass); + }; + return false; } } // namespace json diff --git a/esphome/components/json/json_util.h b/esphome/components/json/json_util.h index 2299a4cfed..72d31c8afe 100644 --- a/esphome/components/json/json_util.h +++ b/esphome/components/json/json_util.h @@ -14,7 +14,7 @@ namespace esphome { namespace json { /// Callback function typedef for parsing JsonObjects. -using json_parse_t = std::function; +using json_parse_t = std::function; /// Callback function typedef for building JsonObjects. using json_build_t = std::function; @@ -23,7 +23,7 @@ using json_build_t = std::function; std::string build_json(const json_build_t &f); /// Parse a JSON string and run the provided json parse function if it's valid. -void parse_json(const std::string &data, const json_parse_t &f); +bool parse_json(const std::string &data, const json_parse_t &f); } // namespace json } // namespace esphome diff --git a/esphome/components/mqtt/mqtt_client.cpp b/esphome/components/mqtt/mqtt_client.cpp index abcbb414d9..d70b9cbd30 100644 --- a/esphome/components/mqtt/mqtt_client.cpp +++ b/esphome/components/mqtt/mqtt_client.cpp @@ -410,7 +410,10 @@ void MQTTClientComponent::subscribe(const std::string &topic, mqtt_callback_t ca void MQTTClientComponent::subscribe_json(const std::string &topic, const mqtt_json_callback_t &callback, uint8_t qos) { auto f = [callback](const std::string &topic, const std::string &payload) { - json::parse_json(payload, [topic, callback](JsonObject root) { callback(topic, root); }); + json::parse_json(payload, [topic, callback](JsonObject root) -> bool { + callback(topic, root); + return true; + }); }; MQTTSubscription subscription{ .topic = topic, From 7dc07c5632a14986c7050639897eca8a7768d100 Mon Sep 17 00:00:00 2001 From: esphomebot Date: Tue, 11 Jun 2024 11:33:42 +1200 Subject: [PATCH 1563/2101] Update webserver local assets to 20240610-230854 (#6886) --- .../components/web_server/server_index_v2.h | 1246 +++++++++-------- .../components/web_server/server_index_v3.h | 728 +++++----- 2 files changed, 994 insertions(+), 980 deletions(-) diff --git a/esphome/components/web_server/server_index_v2.h b/esphome/components/web_server/server_index_v2.h index 7417f37015..c942cda592 100644 --- a/esphome/components/web_server/server_index_v2.h +++ b/esphome/components/web_server/server_index_v2.h @@ -10,625 +10,633 @@ namespace esphome { namespace web_server { const uint8_t INDEX_GZ[] PROGMEM = { - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xcd, 0x7d, 0xd9, 0x92, 0xdb, 0x46, 0xb6, 0xe0, 0xf3, - 0xdc, 0xaf, 0x40, 0xa5, 0xab, 0x4b, 0xc8, 0x66, 0x12, 0x45, 0xb2, 0xb4, 0x19, 0xac, 0x24, 0xbb, 0x54, 0x92, 0x5b, - 0x76, 0x6b, 0xb1, 0x55, 0x92, 0xdd, 0x36, 0xcd, 0xae, 0x42, 0x11, 0x49, 0x32, 0x2d, 0x10, 0x49, 0x03, 0xc9, 0x5a, - 0x4c, 0xe2, 0xc6, 0x7c, 0xc0, 0x44, 0x4c, 0xc4, 0x3c, 0xcd, 0xcb, 0xc4, 0xdc, 0x87, 0xf9, 0x88, 0x79, 0xbe, 0x9f, - 0x72, 0x7f, 0x60, 0xe6, 0x13, 0x26, 0x4e, 0x2e, 0x40, 0x82, 0x4b, 0xa9, 0xbc, 0xdc, 0x1b, 0x13, 0x0a, 0x49, 0x44, - 0xae, 0x27, 0x4f, 0x9e, 0x3c, 0x7b, 0x02, 0xc7, 0x7b, 0xb1, 0x18, 0xc9, 0xdb, 0x39, 0xf3, 0xa6, 0x72, 0x96, 0xf4, - 0x8e, 0xcd, 0xbf, 0x2c, 0x8a, 0x7b, 0xc7, 0x09, 0x4f, 0x3f, 0x7a, 0x19, 0x4b, 0x28, 0x1f, 0x89, 0xd4, 0x9b, 0x66, - 0x6c, 0x4c, 0xe3, 0x48, 0x46, 0x21, 0x9f, 0x45, 0x13, 0xe6, 0x1d, 0xf6, 0x8e, 0x67, 0x4c, 0x46, 0xde, 0x68, 0x1a, - 0x65, 0x39, 0x93, 0xf4, 0xc3, 0xfb, 0x2f, 0x9a, 0x4f, 0x7b, 0xc7, 0xf9, 0x28, 0xe3, 0x73, 0xe9, 0xc1, 0x90, 0x74, - 0x26, 0xe2, 0x45, 0xc2, 0x7a, 0x87, 0x87, 0xd7, 0xd7, 0xd7, 0xc1, 0x4f, 0xf9, 0x3f, 0x8d, 0x44, 0x9a, 0x4b, 0xef, - 0x15, 0xbd, 0xe6, 0x69, 0x2c, 0xae, 0x09, 0x93, 0xf4, 0x55, 0x70, 0x36, 0x8d, 0x62, 0x71, 0xfd, 0x4e, 0x08, 0x79, - 0x70, 0xe0, 0xeb, 0xc7, 0xdb, 0xd3, 0xb3, 0x33, 0x4a, 0xe9, 0x95, 0xe0, 0xb1, 0xd7, 0x5a, 0xad, 0xaa, 0xc2, 0x20, - 0x8d, 0x24, 0xbf, 0x62, 0xba, 0x0b, 0x3e, 0x38, 0x40, 0x51, 0x2c, 0xe6, 0x92, 0xc5, 0x67, 0xf2, 0x36, 0x61, 0x67, - 0x53, 0xc6, 0x64, 0x8e, 0x78, 0xea, 0x3d, 0x17, 0xa3, 0xc5, 0x8c, 0xa5, 0x32, 0x98, 0x67, 0x42, 0x0a, 0x80, 0xe4, - 0xe0, 0x00, 0x65, 0x6c, 0x9e, 0x44, 0x23, 0x06, 0xf5, 0xa7, 0x67, 0x67, 0x55, 0x8f, 0xaa, 0x11, 0xe1, 0x92, 0x9e, - 0xdd, 0xce, 0x2e, 0x45, 0xe2, 0x63, 0x92, 0x48, 0x9a, 0xb2, 0x6b, 0xef, 0x3b, 0x16, 0x7d, 0x7c, 0x1d, 0xcd, 0xbb, - 0xa3, 0x24, 0xca, 0x73, 0xef, 0x52, 0x2e, 0xd5, 0x12, 0xb2, 0xc5, 0x48, 0x8a, 0xcc, 0x97, 0x84, 0x11, 0x8e, 0x97, - 0x7c, 0xec, 0xcb, 0x29, 0xcf, 0x83, 0xf3, 0xfd, 0x51, 0x9e, 0xbf, 0x63, 0xf9, 0x22, 0x91, 0xfb, 0x74, 0xaf, 0x45, - 0xf8, 0x1e, 0xa5, 0x5c, 0x62, 0x39, 0xcd, 0xc4, 0xb5, 0xf7, 0x22, 0xcb, 0x44, 0xe6, 0xa3, 0xd3, 0xb3, 0x33, 0xdd, - 0xc2, 0xe3, 0xb9, 0x97, 0x0a, 0xe9, 0x95, 0xe3, 0x45, 0x97, 0x09, 0x0b, 0xbc, 0x0f, 0x39, 0xf3, 0x2e, 0x16, 0x69, - 0x1e, 0x8d, 0xd9, 0xe9, 0xd9, 0xd9, 0x85, 0x27, 0x32, 0xef, 0x62, 0x94, 0xe7, 0x17, 0x1e, 0x4f, 0x73, 0xc9, 0xa2, - 0x38, 0x40, 0xb8, 0xab, 0x26, 0x1b, 0xe5, 0xf9, 0x7b, 0x76, 0x23, 0xa9, 0x24, 0xea, 0x51, 0x52, 0x56, 0x4c, 0x98, - 0xf4, 0xf2, 0x72, 0x5d, 0x3e, 0x5e, 0x26, 0x4c, 0x7a, 0x92, 0xaa, 0x7a, 0xd1, 0xd5, 0xb8, 0x67, 0xfa, 0x51, 0x76, - 0xf9, 0xd8, 0x67, 0xf2, 0xe0, 0x40, 0x96, 0x78, 0xc6, 0x7a, 0x69, 0x1e, 0xa7, 0x6c, 0xcf, 0x96, 0x1d, 0x1c, 0xb0, - 0x20, 0x61, 0xe9, 0x44, 0x4e, 0x29, 0xa5, 0xed, 0x2e, 0x3f, 0x38, 0xf0, 0x25, 0x4d, 0x64, 0x30, 0x61, 0xd2, 0x67, - 0x18, 0x93, 0xaa, 0xf7, 0xc1, 0x81, 0xaf, 0x91, 0x20, 0xa8, 0x46, 0x5c, 0x0d, 0xc7, 0x38, 0x30, 0xd8, 0x3f, 0xbb, - 0x4d, 0x47, 0xbe, 0x0b, 0x3f, 0x26, 0xfc, 0xe0, 0x20, 0x91, 0x41, 0x0e, 0x23, 0x12, 0x89, 0x71, 0x91, 0x31, 0xb9, - 0xc8, 0x52, 0x4f, 0x16, 0x52, 0x9c, 0xc9, 0x8c, 0xa7, 0x13, 0x1f, 0x2f, 0x6d, 0x99, 0xd3, 0xb1, 0x28, 0x34, 0xb8, - 0x5f, 0x4b, 0x9a, 0xd1, 0x1e, 0xcc, 0x78, 0x29, 0x7d, 0xd8, 0x45, 0x31, 0xf6, 0x32, 0x4a, 0x51, 0xae, 0xfa, 0xa2, - 0x7e, 0x16, 0x66, 0x0d, 0x84, 0x88, 0x86, 0x92, 0x70, 0x89, 0xc9, 0x47, 0xea, 0x67, 0x24, 0x08, 0x02, 0x89, 0x69, - 0x6f, 0x69, 0xb1, 0x92, 0x39, 0xeb, 0xec, 0x67, 0x83, 0xd6, 0x30, 0x94, 0x41, 0xc6, 0xe2, 0xc5, 0x88, 0xf9, 0x3e, - 0x27, 0x39, 0x49, 0x31, 0xed, 0xf1, 0x86, 0x2f, 0x68, 0x0f, 0xb6, 0x5b, 0xd4, 0xf7, 0x9a, 0xd2, 0xbd, 0x16, 0x36, - 0x30, 0x0a, 0x0b, 0x20, 0x60, 0xd8, 0xc0, 0x23, 0x28, 0x45, 0xe9, 0x62, 0x76, 0xc9, 0x32, 0x54, 0x36, 0xeb, 0xd6, - 0xc8, 0x62, 0x91, 0x33, 0x6f, 0x94, 0xe7, 0xde, 0x78, 0x91, 0x8e, 0x24, 0x17, 0xa9, 0x87, 0x1a, 0xa2, 0x81, 0x34, - 0x39, 0x94, 0xd4, 0x80, 0x70, 0x81, 0xfd, 0x1c, 0x37, 0xb2, 0x41, 0xda, 0x68, 0x0f, 0x09, 0x40, 0x89, 0xbb, 0x66, - 0x3c, 0x83, 0x00, 0x46, 0x32, 0x58, 0x63, 0x41, 0x3e, 0x48, 0x58, 0xa5, 0x5a, 0x22, 0x93, 0xfd, 0x2c, 0xd8, 0x3c, - 0x28, 0x54, 0x06, 0xb3, 0x68, 0xee, 0x33, 0xda, 0x63, 0x8a, 0xb8, 0xa2, 0x74, 0x04, 0xb0, 0xd6, 0xf6, 0xad, 0xcf, - 0x42, 0x16, 0x54, 0x24, 0x85, 0x43, 0x19, 0x8c, 0x45, 0xf6, 0x22, 0x1a, 0x4d, 0xa1, 0x5f, 0x49, 0x30, 0xb1, 0x3d, - 0x6f, 0xa3, 0x8c, 0x45, 0x92, 0xbd, 0x48, 0x18, 0x3c, 0xf9, 0x48, 0xf5, 0x44, 0x98, 0xe4, 0xf4, 0x55, 0x90, 0x70, - 0xf9, 0x46, 0xa4, 0x23, 0xd6, 0xcd, 0x1d, 0xea, 0xe2, 0xb0, 0xef, 0x27, 0x52, 0x66, 0xfc, 0x72, 0x21, 0x99, 0x8f, - 0x52, 0x68, 0x81, 0x48, 0x8e, 0x09, 0x0f, 0x24, 0xbb, 0x91, 0xa7, 0x22, 0x95, 0x2c, 0x95, 0x94, 0x59, 0xa4, 0x92, - 0x2c, 0x88, 0xe6, 0x73, 0x96, 0xc6, 0xa7, 0x53, 0x9e, 0xc4, 0x3e, 0xc7, 0x05, 0x2e, 0x48, 0x24, 0x29, 0xac, 0x91, - 0xf6, 0xb2, 0x10, 0xfe, 0xd9, 0xbd, 0x1a, 0x5f, 0xd2, 0x9e, 0x3a, 0x14, 0x8c, 0x22, 0xd4, 0x1d, 0x8b, 0xcc, 0x37, - 0x2b, 0xf0, 0xc4, 0xd8, 0x93, 0x30, 0xc7, 0xbb, 0x45, 0xc2, 0x72, 0xcc, 0x1a, 0x94, 0x97, 0xdb, 0x68, 0x10, 0xfc, - 0x35, 0x50, 0x7c, 0x81, 0xfd, 0x0c, 0x87, 0x59, 0xf7, 0x2a, 0xca, 0xbc, 0x2f, 0xcc, 0x89, 0xfa, 0xc9, 0x72, 0xb3, - 0xa9, 0xa4, 0x3f, 0x05, 0x32, 0x5b, 0xe4, 0x92, 0xc5, 0xef, 0x6f, 0xe7, 0x2c, 0x27, 0xef, 0x25, 0x9d, 0xca, 0xfe, - 0x54, 0x06, 0x6c, 0x36, 0x97, 0xb7, 0x67, 0x8a, 0x31, 0x86, 0x08, 0x91, 0x11, 0xb4, 0xcc, 0x58, 0x34, 0x02, 0x66, - 0x66, 0xb0, 0xf5, 0xb5, 0x48, 0x6e, 0xc7, 0x3c, 0x49, 0xce, 0x16, 0xf3, 0xb9, 0xc8, 0x24, 0xf9, 0x2b, 0x5d, 0x4a, - 0x51, 0xa1, 0x06, 0xf6, 0x72, 0x99, 0x5f, 0x73, 0x39, 0x9a, 0xfa, 0x12, 0x2f, 0x47, 0x51, 0xce, 0xbc, 0x67, 0x42, - 0x24, 0x2c, 0x4a, 0xc3, 0x8c, 0x66, 0xfd, 0xf7, 0x32, 0x4c, 0x17, 0x49, 0xd2, 0xbd, 0xcc, 0x58, 0xf4, 0xb1, 0xab, - 0xaa, 0xdf, 0x5e, 0xfe, 0xc4, 0x46, 0x32, 0x54, 0xbf, 0x4f, 0xb2, 0x2c, 0xba, 0x85, 0x86, 0x94, 0x42, 0xb3, 0x7e, - 0x16, 0x7e, 0x75, 0xf6, 0xf6, 0x4d, 0xa0, 0x0f, 0x09, 0x1f, 0xdf, 0xfa, 0x59, 0x79, 0xf0, 0xb2, 0x82, 0x8c, 0x33, - 0x31, 0x5b, 0x9b, 0x5a, 0x63, 0x2d, 0xeb, 0xee, 0x00, 0x81, 0xd1, 0x6c, 0x4f, 0x0f, 0xed, 0x42, 0xf0, 0x46, 0xd1, - 0x3c, 0x54, 0x52, 0x33, 0x2f, 0xfc, 0x13, 0xea, 0x62, 0x3f, 0xc3, 0x77, 0x43, 0x2b, 0xb3, 0xdb, 0x25, 0xa3, 0x0a, - 0xce, 0x39, 0x48, 0x18, 0x80, 0x71, 0x14, 0xc9, 0xd1, 0x74, 0xc9, 0xd4, 0x60, 0x85, 0x85, 0x98, 0x15, 0x05, 0xb9, - 0x2e, 0xe9, 0x5d, 0xee, 0x51, 0x9a, 0x29, 0x46, 0x45, 0xe5, 0x6a, 0x95, 0x51, 0x9a, 0x61, 0xf2, 0x1d, 0x5d, 0x46, - 0x76, 0x3d, 0xe1, 0x5e, 0x8b, 0xc0, 0xb9, 0x0c, 0x35, 0x77, 0x21, 0x23, 0x91, 0x5e, 0xb1, 0x4c, 0xb2, 0x2c, 0xfc, - 0x2b, 0xc9, 0xd8, 0x38, 0x01, 0x28, 0xf6, 0xda, 0x64, 0x1a, 0xe5, 0xa7, 0xd3, 0x28, 0x9d, 0xb0, 0x38, 0xbc, 0x96, - 0x05, 0xf9, 0x3b, 0x45, 0x63, 0x9e, 0x46, 0x09, 0xff, 0x85, 0xc5, 0xc8, 0x48, 0x83, 0x13, 0x8f, 0xdd, 0x48, 0x96, - 0xc6, 0xb9, 0xf7, 0xf2, 0xfd, 0xeb, 0x57, 0x66, 0x1f, 0x6b, 0x02, 0x02, 0x2f, 0xf3, 0xc5, 0x9c, 0x65, 0x3e, 0x26, - 0x46, 0x40, 0xbc, 0xe0, 0x8a, 0x39, 0xbe, 0x8e, 0xe6, 0xba, 0x84, 0xe7, 0x1f, 0xe6, 0x71, 0x24, 0xd9, 0xd7, 0x2c, - 0x8d, 0x79, 0x3a, 0xa1, 0x7b, 0x6d, 0x5d, 0x3e, 0x8d, 0x4c, 0x45, 0x5c, 0x16, 0x9d, 0xef, 0xbf, 0x48, 0xd4, 0xba, - 0xcb, 0xc7, 0x85, 0x8f, 0x8b, 0x5c, 0x46, 0x92, 0x8f, 0xbc, 0x28, 0x8e, 0xbf, 0x4c, 0xb9, 0xe4, 0x0a, 0xc0, 0x0c, - 0xb6, 0x07, 0x48, 0x94, 0x69, 0x51, 0x61, 0x01, 0xf7, 0x31, 0xf1, 0x7d, 0x23, 0x00, 0xa6, 0xd8, 0xec, 0xd7, 0xc1, - 0x41, 0xc5, 0xee, 0xfb, 0x2c, 0xd4, 0x95, 0x74, 0x30, 0xc4, 0xc1, 0x7c, 0x91, 0xc3, 0x46, 0xdb, 0x29, 0x40, 0xba, - 0x88, 0xcb, 0x9c, 0x65, 0x57, 0x2c, 0x2e, 0x89, 0x23, 0xf7, 0xf1, 0x72, 0x6d, 0x0e, 0x73, 0x2c, 0x24, 0x1d, 0x0c, - 0xbb, 0x2e, 0xdf, 0x66, 0x86, 0xce, 0x33, 0x31, 0x67, 0x99, 0xe4, 0x2c, 0x2f, 0x59, 0x89, 0x0f, 0x52, 0xb4, 0x64, - 0x27, 0x39, 0xb5, 0xeb, 0x9b, 0xfb, 0x9c, 0x30, 0x5c, 0x63, 0x18, 0x56, 0xd0, 0xbe, 0xb8, 0x52, 0x12, 0x23, 0x27, - 0x1c, 0x13, 0xa9, 0x21, 0xcd, 0x31, 0x2e, 0x30, 0x91, 0x16, 0x5c, 0xcd, 0x8a, 0xcc, 0x6c, 0xb7, 0x20, 0xaa, 0xe9, - 0x77, 0x4a, 0x54, 0x03, 0x43, 0x8b, 0x24, 0x3b, 0x38, 0xf0, 0x59, 0x50, 0x12, 0x05, 0xdd, 0x6b, 0x9b, 0x3d, 0x72, - 0x90, 0xb5, 0x03, 0x6c, 0x98, 0x58, 0x12, 0x86, 0xc9, 0x1e, 0x0b, 0x52, 0x71, 0x32, 0x1a, 0xb1, 0x3c, 0x17, 0xd9, - 0xc1, 0xc1, 0x9e, 0x6a, 0x5f, 0x6a, 0x13, 0xb0, 0x87, 0x6f, 0xaf, 0xd3, 0x0a, 0x02, 0x5c, 0x49, 0x58, 0x23, 0x17, - 0x24, 0xc8, 0x29, 0xa5, 0x70, 0xa0, 0xbe, 0x55, 0x3c, 0x42, 0x74, 0x7e, 0x8e, 0x1a, 0x92, 0x18, 0x34, 0x4c, 0x98, - 0x9d, 0xfa, 0xf6, 0x39, 0xd3, 0xaa, 0x95, 0x52, 0x3c, 0x36, 0x30, 0xa3, 0xcf, 0x4f, 0x10, 0xb3, 0x31, 0x4f, 0x9d, - 0x65, 0xd7, 0x40, 0x22, 0x92, 0xe4, 0xb8, 0x70, 0x36, 0x74, 0xeb, 0xd0, 0x4a, 0xa7, 0xd1, 0x3b, 0xb7, 0x9c, 0x28, - 0x3d, 0xc2, 0xd9, 0xc6, 0x01, 0x1b, 0x16, 0x44, 0xa1, 0xde, 0xae, 0x26, 0x55, 0x80, 0x0e, 0xe4, 0xb0, 0x6b, 0xea, - 0x69, 0xae, 0x31, 0x97, 0xb1, 0x9f, 0x17, 0x2c, 0x97, 0x9a, 0x8e, 0x7d, 0x49, 0x52, 0xc2, 0x71, 0x01, 0xc7, 0x6d, - 0xcc, 0x27, 0x8b, 0x0c, 0xd4, 0x1d, 0x38, 0x8a, 0x2c, 0x5d, 0xcc, 0x98, 0x7d, 0xda, 0x06, 0xdb, 0xdb, 0x39, 0x08, - 0xc4, 0x1c, 0x68, 0xfa, 0x6e, 0x72, 0x02, 0x58, 0x25, 0x5e, 0xad, 0xbe, 0xb3, 0x83, 0x54, 0x5b, 0x59, 0xaa, 0x68, - 0x6b, 0x7b, 0xf2, 0x77, 0x6c, 0xe4, 0xf1, 0x5e, 0x5b, 0x43, 0xff, 0xf7, 0x21, 0xdd, 0x6b, 0x95, 0x14, 0x6c, 0x70, - 0xaa, 0x81, 0xd1, 0x28, 0x7c, 0xab, 0x07, 0xc2, 0x4a, 0xba, 0xd7, 0x88, 0x25, 0x98, 0x6e, 0xd0, 0xe9, 0x94, 0x0e, - 0x40, 0xcf, 0x08, 0xa6, 0xc3, 0x5d, 0xc4, 0x64, 0xb9, 0x81, 0x2f, 0x37, 0xeb, 0x2a, 0xa6, 0x71, 0x55, 0x67, 0x1a, - 0x6b, 0x8b, 0x40, 0xf3, 0xb2, 0x0b, 0x2a, 0x69, 0xcc, 0x1c, 0xf3, 0xaa, 0x8a, 0x70, 0x05, 0x4c, 0xb5, 0x24, 0x67, - 0x88, 0x37, 0xd1, 0x8c, 0xe5, 0x3e, 0xc3, 0x64, 0x57, 0x03, 0x4d, 0x9c, 0xd0, 0x64, 0xe8, 0x88, 0xcd, 0x1c, 0xc4, - 0x26, 0xc7, 0x5a, 0x2b, 0xab, 0x1f, 0xb7, 0x9c, 0xb0, 0x41, 0x3e, 0xac, 0x94, 0x39, 0x67, 0xf1, 0x4a, 0x1e, 0x1b, - 0xea, 0xb6, 0xf8, 0xd3, 0x65, 0x1a, 0x69, 0x4a, 0x69, 0xc8, 0x31, 0xd9, 0x6b, 0xad, 0xef, 0xa3, 0x6d, 0x55, 0xad, - 0x71, 0x30, 0x84, 0x7d, 0x50, 0xe2, 0x22, 0xe0, 0xb9, 0xfa, 0xbf, 0x76, 0xce, 0x00, 0x6d, 0x67, 0x40, 0x16, 0xc1, - 0x38, 0x89, 0xa4, 0xdf, 0x3e, 0x6c, 0x81, 0x26, 0x7a, 0xc5, 0x40, 0x9a, 0x60, 0xbc, 0xb9, 0x14, 0x16, 0x2c, 0xd2, - 0x7c, 0xca, 0xc7, 0xd2, 0x8f, 0xa4, 0x62, 0x28, 0x2c, 0xc9, 0x99, 0x27, 0x6b, 0xfa, 0xb0, 0x62, 0x36, 0x11, 0x90, - 0x5a, 0xa9, 0x7c, 0x31, 0x0b, 0xa9, 0x62, 0x5a, 0xc0, 0x1b, 0x2a, 0x5d, 0xba, 0xe2, 0x31, 0xb6, 0x35, 0x07, 0x7d, - 0xb1, 0xdd, 0xd7, 0x23, 0x86, 0x86, 0x15, 0x70, 0x47, 0x65, 0xe5, 0xa1, 0xcb, 0x1f, 0x4c, 0xa1, 0x0c, 0xa4, 0x78, - 0x25, 0xae, 0x59, 0x76, 0x1a, 0x01, 0xf0, 0xa1, 0xee, 0x5e, 0x68, 0x31, 0xa0, 0xb8, 0xbd, 0xec, 0x5a, 0x7a, 0x39, - 0x57, 0x0b, 0xff, 0x3a, 0x13, 0x33, 0x9e, 0x33, 0xd0, 0xd4, 0x34, 0xfe, 0x53, 0x38, 0x65, 0xea, 0x38, 0x82, 0xa8, - 0x61, 0x25, 0x7d, 0x9d, 0xbc, 0xaa, 0xd3, 0xd7, 0xf9, 0xfe, 0x8b, 0x89, 0x65, 0x7f, 0xf5, 0x43, 0x8c, 0x89, 0x6f, - 0xec, 0x09, 0x47, 0xca, 0x05, 0x53, 0x6c, 0xc4, 0xfb, 0x6a, 0x25, 0x1d, 0xb3, 0xad, 0xa6, 0x2b, 0x32, 0x7d, 0x6c, - 0x70, 0x11, 0xc5, 0x31, 0x68, 0x75, 0x99, 0x48, 0x12, 0x47, 0x50, 0x11, 0xde, 0x2d, 0x45, 0xd3, 0xf9, 0xfe, 0x8b, - 0xb3, 0xbb, 0xa4, 0x13, 0xd4, 0xbb, 0x02, 0xca, 0x02, 0x9a, 0xc6, 0x2c, 0x03, 0x33, 0xd2, 0xd9, 0x2d, 0x23, 0x63, - 0x4f, 0x45, 0x9a, 0xb2, 0x91, 0x64, 0x31, 0x58, 0x29, 0x9c, 0xca, 0x60, 0x2a, 0x72, 0x59, 0x16, 0x56, 0xd0, 0x73, - 0x07, 0x7a, 0x1e, 0x8c, 0xa2, 0x24, 0xf1, 0xb5, 0x45, 0x32, 0x13, 0x57, 0x6c, 0x0b, 0xd4, 0xdd, 0x1a, 0xc8, 0xe5, - 0x30, 0xcc, 0x19, 0x86, 0x05, 0xf9, 0x3c, 0xe1, 0x23, 0x56, 0x0a, 0xae, 0xb3, 0x80, 0xa7, 0x31, 0xbb, 0x01, 0x3e, - 0x82, 0x7b, 0xbd, 0x5e, 0x8b, 0xb4, 0x71, 0xa1, 0x11, 0xbe, 0xdc, 0x40, 0xec, 0x1d, 0x22, 0x13, 0x88, 0x8c, 0xf6, - 0x96, 0xdb, 0xf8, 0x01, 0xc3, 0x8e, 0x9c, 0xe4, 0xd6, 0xb2, 0xd2, 0xbc, 0x19, 0x93, 0x98, 0x25, 0x4c, 0x32, 0xcb, - 0xcb, 0x41, 0x7f, 0xd6, 0x47, 0xf7, 0x5d, 0x89, 0xbf, 0x92, 0x9c, 0xec, 0x29, 0xb3, 0x7b, 0x9e, 0x97, 0x96, 0x7a, - 0xb5, 0x3d, 0x15, 0xb6, 0xfb, 0x52, 0x6f, 0x4f, 0x24, 0x65, 0x34, 0x9a, 0x6a, 0x13, 0xdd, 0xdf, 0x58, 0x52, 0x35, - 0x86, 0xe1, 0xeb, 0xe5, 0x21, 0xfa, 0x60, 0xc1, 0xdc, 0x86, 0x82, 0x33, 0xc3, 0x14, 0x18, 0x58, 0x7d, 0x7a, 0xdb, - 0x4e, 0xa3, 0x24, 0xb9, 0x8c, 0x46, 0x1f, 0xeb, 0xd4, 0x5f, 0x91, 0x01, 0x5d, 0xe7, 0xc6, 0x4e, 0x95, 0xc3, 0xb2, - 0xdc, 0x75, 0x5b, 0x2e, 0x5d, 0x3b, 0x28, 0xfe, 0x5e, 0xab, 0x22, 0xfb, 0xfa, 0x46, 0xef, 0xa4, 0x76, 0x05, 0x11, - 0x37, 0x2b, 0xf3, 0x81, 0x0b, 0x7c, 0x92, 0xe2, 0x2c, 0x3f, 0x30, 0x74, 0x07, 0xb6, 0x46, 0xb1, 0x06, 0x88, 0xc4, - 0xcb, 0x22, 0xe6, 0xf9, 0x6e, 0x0c, 0xfc, 0x21, 0x50, 0x3e, 0x77, 0x66, 0xb8, 0x2f, 0xa0, 0x25, 0x8f, 0x33, 0x2a, - 0x73, 0x09, 0x99, 0xd1, 0x26, 0x2c, 0xa3, 0xf9, 0x1b, 0x68, 0x2e, 0x8a, 0xde, 0xdf, 0xea, 0x2a, 0xd0, 0xc9, 0x00, - 0x8a, 0xbc, 0xeb, 0x2a, 0x13, 0x35, 0x0a, 0x30, 0x3c, 0x95, 0x2b, 0x91, 0x9b, 0xd6, 0x8c, 0x47, 0xa3, 0xae, 0x6b, - 0xfb, 0xdb, 0xb0, 0x5c, 0x41, 0x7d, 0xdf, 0xcf, 0xc1, 0x7e, 0xb3, 0x7a, 0x7d, 0xb5, 0x88, 0x7c, 0x63, 0x11, 0x79, - 0xe0, 0x18, 0x59, 0xb8, 0xa2, 0x65, 0xa7, 0x7b, 0xf8, 0x57, 0xec, 0x36, 0x02, 0x65, 0x35, 0x00, 0xfe, 0x8c, 0x4b, - 0x76, 0x9b, 0x50, 0x49, 0x84, 0x31, 0x70, 0x0c, 0xa5, 0x01, 0xc3, 0xa8, 0xba, 0xa4, 0x58, 0x1f, 0x8d, 0x9a, 0xb1, - 0x9b, 0x12, 0x81, 0xd7, 0x34, 0xfb, 0xa2, 0x30, 0x38, 0x62, 0xd8, 0xec, 0x4d, 0x4d, 0x25, 0x76, 0xb0, 0x42, 0x52, - 0x6a, 0xd4, 0x60, 0xad, 0xf5, 0xac, 0xe3, 0xa6, 0x1c, 0x17, 0x0e, 0x6a, 0x85, 0x9a, 0x9a, 0x3e, 0x69, 0x15, 0xab, - 0x14, 0x93, 0xa9, 0xd5, 0x48, 0x45, 0xb5, 0x6e, 0x4a, 0x91, 0xf5, 0x46, 0xa0, 0xfe, 0xb2, 0x66, 0x12, 0x86, 0x4e, - 0xb3, 0x22, 0x04, 0x96, 0x2a, 0xb6, 0xa1, 0x7b, 0x1b, 0xcd, 0xd4, 0xc6, 0x71, 0x10, 0x2e, 0x5c, 0x84, 0x3b, 0x98, - 0x4d, 0x35, 0xe7, 0x4a, 0x87, 0x74, 0x5a, 0xef, 0xeb, 0x33, 0x22, 0xf4, 0x3e, 0x6c, 0x20, 0x71, 0x5d, 0xf1, 0x54, - 0x24, 0x08, 0x06, 0x6c, 0x0e, 0xca, 0x9d, 0x2b, 0x1f, 0x7c, 0x80, 0x9d, 0xaf, 0x56, 0x1b, 0x44, 0xb7, 0x55, 0xff, - 0xc4, 0x41, 0x65, 0x14, 0xae, 0x56, 0xd7, 0x12, 0xfb, 0x46, 0xf3, 0x25, 0x0c, 0xf7, 0x2d, 0xc7, 0x3d, 0x79, 0x05, - 0xad, 0x94, 0x22, 0x5a, 0x95, 0x94, 0x26, 0x43, 0x9d, 0x66, 0xeb, 0xfb, 0x24, 0x1d, 0xb6, 0x7d, 0xba, 0xc1, 0xbd, - 0x54, 0xa1, 0x11, 0xd3, 0xd5, 0x92, 0x4f, 0xcd, 0xd0, 0x1c, 0x63, 0x1c, 0xe6, 0xca, 0x8a, 0xd9, 0xdb, 0x66, 0x58, - 0x1e, 0x1c, 0xe4, 0xce, 0x40, 0xe7, 0x25, 0x9b, 0xf8, 0xc9, 0x07, 0x91, 0x9c, 0xdf, 0xa6, 0x4a, 0x77, 0xf9, 0xc9, - 0x0a, 0xa1, 0x0d, 0xb3, 0xb4, 0xd5, 0x05, 0x6b, 0x3c, 0xba, 0x8e, 0xb8, 0xf4, 0xca, 0x51, 0xb4, 0x35, 0xee, 0x33, - 0xbc, 0x34, 0xaa, 0x46, 0x90, 0x31, 0x50, 0x1e, 0x81, 0x27, 0x58, 0x15, 0x5a, 0xd3, 0xfd, 0x68, 0xca, 0xc0, 0x11, - 0x6c, 0xb5, 0x88, 0xd2, 0x2e, 0xdc, 0x33, 0x52, 0xc4, 0x0c, 0xbc, 0x1d, 0xf6, 0x62, 0xbd, 0x7b, 0xcd, 0x0e, 0x98, - 0xb3, 0x6c, 0x2c, 0xb2, 0x99, 0xad, 0x2b, 0xd6, 0x9e, 0x0d, 0x67, 0xe4, 0x63, 0x7f, 0xeb, 0xd8, 0x46, 0xfd, 0xef, - 0xae, 0x19, 0xdd, 0x95, 0xb9, 0x5e, 0x13, 0xa5, 0xa5, 0xf4, 0xd5, 0xfe, 0x40, 0x4b, 0x99, 0xb9, 0x6b, 0xde, 0x1b, - 0x67, 0x6a, 0x57, 0x3b, 0x4c, 0xf6, 0xda, 0xdd, 0xd2, 0xe6, 0xb3, 0xd4, 0xd0, 0xd5, 0x8e, 0x0d, 0x23, 0x52, 0xc5, - 0x22, 0x89, 0x0d, 0xb0, 0x1c, 0x13, 0x66, 0xe8, 0xe8, 0x9a, 0x27, 0x49, 0x55, 0xfa, 0x6b, 0xf8, 0x7a, 0x6e, 0xf8, - 0x7a, 0x6a, 0xf9, 0x3a, 0x70, 0x0a, 0xe0, 0xeb, 0x7a, 0xb8, 0xaa, 0x7b, 0xba, 0x71, 0x3a, 0x53, 0xcd, 0xd1, 0x73, - 0x65, 0x47, 0xc3, 0x7c, 0x0b, 0x0b, 0x01, 0x2e, 0x35, 0xaf, 0x8f, 0xbe, 0x71, 0xc2, 0x80, 0x01, 0xa8, 0x5d, 0x98, - 0xcc, 0x75, 0x51, 0x7c, 0xf4, 0x31, 0xc9, 0x0b, 0x56, 0x52, 0xf6, 0xc9, 0x0b, 0x70, 0xd2, 0x39, 0xcb, 0x01, 0x21, - 0xa6, 0x8a, 0x7f, 0x95, 0x12, 0x65, 0x57, 0xc7, 0xcd, 0xea, 0x72, 0xbb, 0x3a, 0xe0, 0xf4, 0xd5, 0xea, 0xe2, 0xbb, - 0x79, 0xbd, 0x5a, 0x1e, 0x2f, 0x97, 0x57, 0xed, 0xf7, 0x6a, 0xe5, 0xaf, 0x95, 0x80, 0xff, 0xde, 0x98, 0x28, 0x59, - 0x39, 0x3a, 0xf0, 0x00, 0x17, 0x33, 0x50, 0x50, 0xe8, 0x45, 0x97, 0x22, 0xee, 0xd5, 0xa7, 0x1c, 0x3c, 0xca, 0x4d, - 0xaf, 0xfb, 0x9f, 0x8a, 0xd9, 0x1c, 0xb4, 0xb1, 0x35, 0x92, 0x9e, 0x30, 0x33, 0x61, 0x55, 0x5f, 0x6c, 0x29, 0xab, - 0xf5, 0x51, 0xe7, 0xb1, 0x46, 0x4d, 0xa5, 0xbd, 0xbc, 0xd7, 0x2a, 0x16, 0x65, 0x51, 0xc9, 0x38, 0xb6, 0x39, 0x55, - 0x4e, 0xd7, 0x5d, 0x32, 0xb6, 0xe2, 0xad, 0xcf, 0x35, 0x1f, 0xe6, 0xc0, 0xeb, 0x1c, 0xf6, 0x63, 0xc9, 0xdd, 0xdd, - 0xff, 0xa2, 0x42, 0xce, 0xb2, 0x58, 0x43, 0xdf, 0xb2, 0x28, 0x4e, 0xb4, 0x91, 0x4d, 0x4e, 0x76, 0x5b, 0xc3, 0x55, - 0x9d, 0x31, 0x16, 0x07, 0x43, 0x72, 0xb2, 0xa9, 0x3a, 0xd2, 0xe5, 0x4c, 0xc4, 0x2c, 0x44, 0x62, 0xce, 0x52, 0x54, - 0x80, 0x57, 0xd5, 0xec, 0xfd, 0x48, 0xfa, 0xcb, 0x77, 0x75, 0xf7, 0x6a, 0x78, 0x52, 0x80, 0xf7, 0xeb, 0x8b, 0x4d, - 0xc7, 0xeb, 0xb7, 0x2c, 0xcb, 0x95, 0x22, 0x5a, 0xea, 0xb4, 0x5f, 0x54, 0x62, 0xe9, 0x8b, 0x70, 0x67, 0xfb, 0xca, - 0x04, 0x41, 0xed, 0xe0, 0x71, 0x70, 0x84, 0xb0, 0x72, 0x0b, 0x7f, 0x65, 0x0e, 0xfc, 0x73, 0xeb, 0x16, 0x7e, 0x41, - 0x9f, 0xd7, 0xbd, 0xc2, 0xb1, 0xa4, 0x2f, 0xfa, 0x2f, 0xac, 0xc5, 0x2c, 0x12, 0x3e, 0xba, 0xf5, 0x51, 0xc2, 0x65, - 0x13, 0x42, 0x6f, 0x88, 0x2c, 0x75, 0x05, 0xb8, 0x14, 0x95, 0x3b, 0xbb, 0xb0, 0xb6, 0x1e, 0x91, 0x92, 0xa2, 0xfd, - 0x84, 0xcb, 0x7d, 0x44, 0x66, 0xf4, 0x02, 0x7e, 0xec, 0x2f, 0xfd, 0xd7, 0x91, 0x9c, 0x06, 0x59, 0x94, 0xc6, 0x62, - 0xe6, 0xe3, 0x06, 0x42, 0x38, 0xc8, 0x95, 0xbd, 0xf1, 0x39, 0x2e, 0xf6, 0x2f, 0xc8, 0x8d, 0xa4, 0xa8, 0x8f, 0x1a, - 0x33, 0xf2, 0x52, 0xd2, 0x8b, 0xe3, 0xfd, 0xe5, 0x8d, 0x2c, 0x7a, 0x17, 0xe4, 0xa6, 0xf4, 0xd8, 0x93, 0xaf, 0xa9, - 0x8f, 0x69, 0xef, 0xc6, 0x40, 0x73, 0x2a, 0x66, 0xda, 0x73, 0x8f, 0x30, 0xf9, 0x00, 0x71, 0x95, 0xac, 0xe2, 0x36, - 0x26, 0xb4, 0xb2, 0x47, 0x91, 0x50, 0x2e, 0x02, 0x74, 0x70, 0xe0, 0x94, 0x95, 0xaa, 0x02, 0x39, 0x91, 0xb4, 0x66, - 0x90, 0x93, 0x37, 0x2a, 0x42, 0x73, 0x22, 0xfd, 0x0c, 0xdb, 0x61, 0x7c, 0xeb, 0x87, 0x36, 0x47, 0x33, 0x1b, 0x68, - 0x0f, 0x43, 0xc0, 0x25, 0xcb, 0x22, 0x29, 0xb2, 0x21, 0x76, 0xd5, 0x0f, 0xf2, 0x37, 0x7a, 0x31, 0xf0, 0xfe, 0xd3, - 0x3f, 0xfd, 0x38, 0xfe, 0x31, 0x1b, 0x5e, 0x90, 0xb7, 0xf4, 0xf0, 0xd8, 0xef, 0x87, 0xfe, 0x5e, 0xb3, 0xb9, 0xfa, - 0xf1, 0x70, 0xf0, 0x8f, 0xa8, 0xf9, 0xcb, 0x49, 0xf3, 0x87, 0x21, 0x5e, 0xf9, 0x3f, 0x1e, 0xf6, 0x07, 0xe6, 0x69, - 0xf0, 0x8f, 0xde, 0x8f, 0xf9, 0xf0, 0xcf, 0xba, 0x70, 0x1f, 0xe3, 0xc3, 0x09, 0x59, 0x48, 0x7a, 0xd8, 0x6c, 0xf6, - 0x0e, 0x27, 0x64, 0x2e, 0xe9, 0x21, 0xfc, 0x7f, 0x49, 0xdf, 0xb1, 0xc9, 0x8b, 0x9b, 0xb9, 0x7f, 0xd1, 0x5b, 0xed, - 0x2f, 0xff, 0x56, 0xc0, 0xa8, 0x83, 0x7f, 0xfc, 0xf8, 0x63, 0x8e, 0x1e, 0xf4, 0xe8, 0xe1, 0xb0, 0x81, 0x7d, 0x28, - 0xfd, 0x33, 0x55, 0xff, 0xfa, 0xfd, 0x70, 0xf0, 0x0f, 0x03, 0x05, 0x7a, 0xf0, 0xe3, 0xc5, 0x71, 0x8f, 0x0e, 0x57, - 0x3e, 0x5a, 0x3d, 0xc0, 0x2b, 0x8c, 0x57, 0xfb, 0xf8, 0x82, 0xa0, 0x09, 0xc2, 0x64, 0x22, 0xe9, 0xe1, 0x83, 0xc3, - 0x09, 0xb9, 0x92, 0xf4, 0x10, 0x1d, 0x4e, 0xc8, 0x0b, 0x49, 0x0f, 0xff, 0xe1, 0xf7, 0x43, 0xed, 0x61, 0x5b, 0x29, - 0xf7, 0xc6, 0x0a, 0x82, 0x1b, 0x51, 0xc6, 0xa2, 0x95, 0xe4, 0x32, 0x61, 0x78, 0xff, 0x90, 0x93, 0x33, 0x85, 0x26, - 0x5f, 0x82, 0x13, 0x06, 0x6c, 0x3b, 0x7f, 0x79, 0x0e, 0x9b, 0x0d, 0x34, 0xb3, 0x1f, 0x66, 0x44, 0xfb, 0x01, 0xf2, - 0x50, 0x92, 0xab, 0x28, 0x59, 0xb0, 0x3c, 0x64, 0x05, 0x26, 0x23, 0x7a, 0x26, 0xfd, 0x36, 0x26, 0xef, 0x24, 0xfc, - 0xe8, 0x60, 0x72, 0x66, 0x02, 0x98, 0x70, 0x90, 0x35, 0x51, 0xa5, 0x42, 0x6b, 0x2c, 0x08, 0x93, 0xf9, 0x96, 0x4a, - 0x39, 0x05, 0xef, 0x02, 0x26, 0xe3, 0x5a, 0xb8, 0x93, 0x5c, 0x53, 0x4b, 0x12, 0xef, 0x33, 0xc6, 0xbe, 0x8b, 0x92, - 0x8f, 0x2c, 0xf3, 0x6f, 0x48, 0xbb, 0xf3, 0x39, 0x51, 0x2e, 0xe8, 0xbd, 0x36, 0xee, 0x96, 0xb1, 0xaa, 0x53, 0xa9, - 0x63, 0x04, 0x20, 0x64, 0xeb, 0xbe, 0x18, 0xd8, 0xf1, 0xbd, 0x6c, 0xc3, 0x61, 0x95, 0x45, 0xd7, 0x08, 0xd7, 0xe3, - 0xa2, 0x3c, 0xbd, 0x8a, 0x12, 0x1e, 0x7b, 0x92, 0xcd, 0xe6, 0x49, 0x24, 0x99, 0x67, 0xd6, 0xeb, 0x45, 0x30, 0x10, - 0x2a, 0x55, 0x86, 0xd8, 0x31, 0x38, 0x63, 0x1b, 0x70, 0x82, 0xb3, 0xe2, 0x43, 0x74, 0xca, 0xa8, 0x1d, 0xaf, 0xab, - 0xe0, 0xd7, 0x7a, 0x7c, 0xaf, 0xd9, 0x06, 0x47, 0xd8, 0x50, 0x89, 0xe7, 0x9c, 0xa4, 0x14, 0x84, 0x68, 0xa7, 0x8f, - 0x8e, 0xf3, 0xab, 0x49, 0x0f, 0x41, 0x6c, 0x46, 0xd0, 0xb7, 0xca, 0x2f, 0x04, 0x0d, 0xa6, 0xb4, 0xd5, 0x9d, 0x1e, - 0xb3, 0xee, 0xb4, 0xd1, 0xb0, 0x3a, 0x74, 0x42, 0xb3, 0xc1, 0x54, 0x77, 0x8f, 0x48, 0x4c, 0x16, 0xb4, 0xd9, 0x26, - 0x13, 0xda, 0x52, 0x5d, 0xba, 0x93, 0xe3, 0xc4, 0x4c, 0x73, 0x70, 0xe0, 0x8b, 0x20, 0x89, 0x72, 0xf9, 0x25, 0x18, - 0xfb, 0x74, 0x42, 0x62, 0x2a, 0x02, 0x76, 0xc3, 0x46, 0x7e, 0x82, 0x49, 0x6c, 0x38, 0x0d, 0xee, 0xe2, 0x09, 0x75, - 0x9a, 0x81, 0x11, 0x41, 0xdf, 0xf6, 0xe3, 0x41, 0x7b, 0x48, 0x29, 0x45, 0x7b, 0xcd, 0x26, 0xea, 0x0b, 0xba, 0x90, - 0x21, 0x94, 0x38, 0xaa, 0x32, 0x9d, 0x43, 0x51, 0xc7, 0x29, 0xf2, 0x5f, 0xc8, 0x40, 0xb2, 0x5c, 0xfa, 0x50, 0x0c, - 0xe6, 0x7f, 0x6e, 0x09, 0x1b, 0x1d, 0x1f, 0xa2, 0x06, 0x94, 0x2a, 0xe2, 0xc4, 0x44, 0xd0, 0x4b, 0x1c, 0xc6, 0x83, - 0xa3, 0xa1, 0xcb, 0xff, 0x55, 0x21, 0x4c, 0x7e, 0xd9, 0x8f, 0x07, 0x2d, 0x35, 0x79, 0x0f, 0xf5, 0x7d, 0x41, 0x73, - 0xad, 0xa0, 0xf5, 0xf3, 0xf0, 0xad, 0x5a, 0x2a, 0x0e, 0x0d, 0x70, 0x66, 0xde, 0x05, 0x6d, 0x76, 0x42, 0x7f, 0xe1, - 0x2e, 0xa2, 0x09, 0x93, 0x19, 0x2c, 0x90, 0x88, 0x42, 0x7b, 0x22, 0x28, 0xcc, 0x58, 0x75, 0xbb, 0x0c, 0xcd, 0xf3, - 0x03, 0xf4, 0xa0, 0x7f, 0x25, 0xc3, 0x89, 0xd4, 0xd3, 0x5f, 0xc9, 0xd5, 0x0a, 0xfe, 0x9f, 0xc8, 0xbe, 0xa0, 0x97, - 0xaa, 0x68, 0x61, 0x8a, 0xe6, 0x50, 0xf4, 0x36, 0x04, 0x50, 0x49, 0x5e, 0x2a, 0x59, 0x7a, 0x4f, 0xae, 0xa8, 0x82, - 0xfd, 0xe0, 0x20, 0x1b, 0x4c, 0x1b, 0xed, 0x21, 0xf8, 0xf7, 0x33, 0x99, 0x7f, 0xc7, 0xe5, 0xd4, 0x47, 0x87, 0x3d, - 0x84, 0xfb, 0xc8, 0x83, 0xad, 0xed, 0xa6, 0x0d, 0xaa, 0x31, 0x9c, 0x34, 0x5e, 0xca, 0x70, 0xd1, 0xa3, 0xad, 0xbe, - 0xcf, 0x8d, 0x3f, 0x0f, 0x93, 0xc4, 0x30, 0xce, 0x16, 0x59, 0xe0, 0x86, 0x94, 0x0d, 0xfb, 0xbc, 0xc0, 0x8d, 0x59, - 0xe3, 0x0a, 0x87, 0x49, 0x63, 0xd6, 0xf0, 0x17, 0x94, 0xd2, 0x66, 0xa7, 0xec, 0x66, 0xa5, 0xdf, 0x14, 0x87, 0x57, - 0xd6, 0xd9, 0x39, 0x50, 0xc7, 0x21, 0x6d, 0xf8, 0xd9, 0x80, 0x0d, 0x57, 0x2b, 0x74, 0xdc, 0xef, 0x21, 0xdc, 0xf0, - 0x2d, 0xa1, 0x1d, 0x5a, 0x4a, 0xc3, 0x98, 0xf0, 0x61, 0x61, 0x42, 0x49, 0xef, 0x6b, 0x61, 0xa3, 0x65, 0x75, 0xd8, - 0x1d, 0x1e, 0xc0, 0x8a, 0xd2, 0x8e, 0xd1, 0xfa, 0xea, 0x1c, 0x96, 0x69, 0x89, 0x39, 0xa5, 0x2d, 0x22, 0xa8, 0xf5, - 0x5d, 0x4f, 0xa9, 0xac, 0x08, 0x3e, 0xa1, 0x55, 0x73, 0x32, 0x88, 0x48, 0x3c, 0xa4, 0xaf, 0xb5, 0x3d, 0xd2, 0xb5, - 0x7e, 0x71, 0x96, 0xd0, 0xf7, 0x6b, 0xd1, 0xdb, 0x08, 0x62, 0x2b, 0xd7, 0xc1, 0x68, 0x91, 0x65, 0x2c, 0x95, 0x6f, - 0x44, 0x6c, 0xd4, 0x34, 0x96, 0x80, 0xa5, 0x04, 0x61, 0x59, 0x02, 0x3a, 0x5a, 0xc7, 0x9e, 0x8c, 0xc5, 0x46, 0xf5, - 0x84, 0x2e, 0xb4, 0xfa, 0xa4, 0x82, 0xb5, 0xdd, 0x89, 0xb1, 0x8b, 0x7d, 0x4c, 0x16, 0x26, 0x8a, 0xeb, 0x07, 0x41, - 0x30, 0x09, 0x46, 0x50, 0x0d, 0x13, 0xe4, 0xb8, 0x50, 0xe7, 0xc8, 0xcf, 0xe9, 0x75, 0x90, 0xb2, 0x1b, 0x35, 0xab, - 0x8f, 0x2b, 0xc9, 0x6c, 0x8f, 0xd7, 0xf1, 0xb4, 0xab, 0xd8, 0x4d, 0x1e, 0xa4, 0x22, 0x66, 0x80, 0x1e, 0x88, 0xdb, - 0x9b, 0xa2, 0x69, 0x94, 0xbb, 0xf1, 0xa9, 0x0a, 0xbe, 0x81, 0xeb, 0xbc, 0x9e, 0x80, 0xc7, 0x57, 0xe9, 0x5a, 0x65, - 0x63, 0xed, 0x06, 0xc7, 0x98, 0x8f, 0xfd, 0x49, 0x00, 0x71, 0x3d, 0x45, 0x42, 0x12, 0x4c, 0xb9, 0x89, 0x4b, 0x54, - 0xb3, 0x72, 0xcc, 0x2b, 0x1a, 0x0f, 0x44, 0xa3, 0xa1, 0xbc, 0xd0, 0x0b, 0x4d, 0x12, 0x13, 0x4c, 0xae, 0xca, 0xb3, - 0x65, 0xdb, 0xbd, 0x95, 0xb4, 0x3e, 0x95, 0x7f, 0x55, 0x77, 0xe7, 0x36, 0xa4, 0xc4, 0xca, 0x53, 0x28, 0xfd, 0x19, - 0x26, 0xcf, 0xe8, 0xa1, 0x3f, 0x08, 0xfa, 0x7f, 0x19, 0xe2, 0xbe, 0x1f, 0xfc, 0x19, 0x1f, 0x6a, 0xce, 0x71, 0x85, - 0xbb, 0x89, 0x9e, 0x63, 0xa9, 0xe2, 0x97, 0x6d, 0xa2, 0x3c, 0x89, 0x61, 0x4a, 0xd2, 0x68, 0xc6, 0xc2, 0x67, 0x70, - 0xc8, 0x2d, 0xe1, 0xbc, 0x95, 0x04, 0x28, 0x29, 0x7c, 0x66, 0x78, 0x49, 0x80, 0xfa, 0xaf, 0x64, 0xf9, 0xd4, 0x47, - 0xfd, 0xe7, 0xd5, 0xd3, 0x5f, 0x50, 0xff, 0x17, 0x19, 0xfe, 0x5c, 0x18, 0x6f, 0x77, 0x6d, 0x8e, 0xc7, 0x76, 0x8e, - 0x42, 0x6f, 0x8d, 0x83, 0xbb, 0x05, 0xde, 0x74, 0x74, 0x4c, 0x70, 0xc1, 0xc7, 0x25, 0x33, 0xca, 0x03, 0x19, 0x4d, - 0x00, 0xa9, 0xce, 0x1e, 0xe4, 0x6e, 0x5c, 0xbf, 0x5a, 0x31, 0x90, 0x8a, 0xa5, 0x57, 0x40, 0xe6, 0xa4, 0xd7, 0xc2, - 0xcb, 0x5a, 0x5b, 0xa5, 0x33, 0xd5, 0xe3, 0xe8, 0x25, 0x9f, 0xbe, 0xa2, 0xad, 0xee, 0xd5, 0xf1, 0xa4, 0x7b, 0xd5, - 0x68, 0xe0, 0xdc, 0x92, 0xd6, 0x62, 0x70, 0x35, 0x24, 0x5f, 0x83, 0x53, 0xcf, 0xa5, 0x25, 0x52, 0x5b, 0x5e, 0xc7, - 0x2c, 0xaf, 0xd1, 0x48, 0x0b, 0xdc, 0x75, 0xba, 0x4e, 0x74, 0xd7, 0xa2, 0xd0, 0x38, 0x59, 0x27, 0xb5, 0xa7, 0x58, - 0x95, 0x40, 0x32, 0x14, 0xa5, 0xf4, 0x46, 0xe2, 0xad, 0xa3, 0xc2, 0x98, 0xd0, 0x5d, 0x9d, 0x59, 0x60, 0x9f, 0x5a, - 0x4a, 0xf8, 0x80, 0x05, 0xe8, 0x5a, 0x7a, 0x82, 0x67, 0x64, 0xd1, 0x68, 0x2b, 0x32, 0x6f, 0xb6, 0xbb, 0xf5, 0xb1, - 0x9e, 0x54, 0x63, 0x91, 0x45, 0x83, 0xce, 0x4a, 0x2c, 0x15, 0x69, 0xa3, 0x51, 0xd4, 0x83, 0x9d, 0xf6, 0xe4, 0xd6, - 0x02, 0x10, 0x37, 0xeb, 0x49, 0x19, 0x56, 0xc2, 0x56, 0x32, 0x95, 0x07, 0x3c, 0x4d, 0x59, 0x06, 0x52, 0x94, 0x4a, - 0xc2, 0x8b, 0xa2, 0x92, 0xec, 0x20, 0x46, 0x09, 0xa3, 0x19, 0x70, 0x1e, 0x65, 0x77, 0x91, 0x94, 0x08, 0x32, 0x55, - 0x7c, 0x83, 0x52, 0x7a, 0x66, 0xd3, 0x59, 0xa4, 0xe2, 0x41, 0x09, 0xe5, 0x8e, 0x4c, 0xca, 0x29, 0x0b, 0xce, 0xf7, - 0x4f, 0xc5, 0x9d, 0x36, 0xd9, 0x80, 0x0f, 0x43, 0xd5, 0x2c, 0x31, 0x9c, 0x2b, 0xa2, 0x1f, 0x7c, 0x89, 0xcb, 0xe8, - 0x48, 0xa0, 0x18, 0xe0, 0x73, 0x9e, 0x31, 0xa5, 0x83, 0xef, 0x5b, 0xbb, 0x2f, 0xa9, 0x2b, 0x90, 0x89, 0xeb, 0xbd, - 0x01, 0x44, 0x46, 0xe0, 0xdc, 0x49, 0xe9, 0x46, 0xb3, 0xf3, 0xfd, 0x93, 0xb7, 0xdb, 0x6c, 0xe0, 0xd5, 0xca, 0x58, - 0xbf, 0x4a, 0xb7, 0x21, 0x51, 0x05, 0x69, 0x62, 0x7e, 0x84, 0x7e, 0xa2, 0x54, 0xa4, 0xc8, 0xcf, 0x80, 0x8a, 0xce, - 0xf7, 0x4f, 0xde, 0xfb, 0x99, 0xf2, 0x2d, 0x61, 0xe2, 0x2e, 0xdb, 0x17, 0xd4, 0x9f, 0x52, 0x86, 0xf5, 0xda, 0x4b, - 0xd6, 0x25, 0x1c, 0x01, 0x1e, 0x4e, 0x55, 0x25, 0x58, 0x10, 0x03, 0x3e, 0xa4, 0x89, 0xc1, 0x00, 0x4d, 0x30, 0x49, - 0x6a, 0x76, 0x19, 0x85, 0x0d, 0x50, 0x73, 0x9d, 0xc1, 0x4e, 0x04, 0x5a, 0xf5, 0xc3, 0x24, 0x51, 0xb3, 0xca, 0x42, - 0x0b, 0x8f, 0x67, 0x1b, 0x59, 0x69, 0x95, 0x39, 0xfa, 0x2d, 0xd8, 0x4e, 0xf6, 0xe1, 0x0d, 0xb5, 0x96, 0x84, 0x29, - 0x78, 0x6e, 0xd3, 0xc7, 0xce, 0xf7, 0x4f, 0x5e, 0x9b, 0x0c, 0xb2, 0x79, 0x64, 0xf9, 0xfd, 0x86, 0x89, 0x79, 0xf2, - 0x3a, 0xa8, 0x6a, 0x55, 0xe3, 0xf3, 0xfd, 0x93, 0x0f, 0xdb, 0x9a, 0x41, 0x79, 0xb1, 0xa8, 0x6c, 0x7c, 0x05, 0xdf, - 0x92, 0x25, 0xe1, 0xd2, 0x08, 0x87, 0x90, 0x17, 0x44, 0x09, 0xa4, 0x30, 0x2f, 0x4a, 0xd7, 0xc8, 0x73, 0x92, 0x52, - 0x15, 0x06, 0xaa, 0xef, 0x9a, 0x51, 0xf3, 0xb8, 0x48, 0xcf, 0x46, 0x62, 0xce, 0x76, 0xc4, 0x86, 0x6e, 0x70, 0xc0, - 0x67, 0x90, 0x3a, 0xa3, 0x40, 0xe7, 0x64, 0xaf, 0x85, 0xbb, 0x75, 0xf1, 0x95, 0x2a, 0x22, 0x15, 0x35, 0xd9, 0x42, - 0xa6, 0xb4, 0x45, 0x12, 0xda, 0x22, 0x11, 0xcd, 0x07, 0x2d, 0x2d, 0x20, 0xba, 0x51, 0x39, 0xae, 0x16, 0x33, 0x90, - 0x15, 0x66, 0x4e, 0xab, 0x16, 0xc0, 0x71, 0x37, 0x52, 0xbe, 0x47, 0x25, 0xd3, 0x63, 0x45, 0x16, 0x6f, 0x7c, 0x41, - 0x84, 0x1a, 0xf8, 0x8c, 0x5f, 0x26, 0x90, 0x58, 0x02, 0xab, 0x22, 0x12, 0x87, 0x65, 0xd3, 0xb6, 0x69, 0x1a, 0x05, - 0x6a, 0x9f, 0x04, 0x89, 0x02, 0xe0, 0xdc, 0x24, 0x32, 0x79, 0x38, 0xf9, 0x66, 0x97, 0xc7, 0x07, 0x07, 0xbe, 0xee, - 0xf4, 0xa5, 0xf4, 0x85, 0xad, 0xaf, 0x22, 0x77, 0xdf, 0x6a, 0x5e, 0x11, 0x63, 0x05, 0x7f, 0xa3, 0x91, 0x0c, 0x0b, - 0x08, 0x43, 0xfb, 0x51, 0x1d, 0x83, 0x16, 0x78, 0xa5, 0xeb, 0xd5, 0x97, 0xdf, 0x68, 0x94, 0x51, 0xda, 0x3a, 0xb6, - 0x6e, 0x48, 0x5a, 0x5c, 0xf9, 0x65, 0xea, 0x4f, 0x6b, 0x23, 0x5f, 0xca, 0x82, 0x80, 0xb9, 0x4b, 0xb3, 0xdc, 0x2e, - 0xc6, 0x39, 0x12, 0x1c, 0xda, 0x7d, 0x69, 0xb2, 0x16, 0x88, 0xca, 0xae, 0x32, 0x8d, 0x2c, 0x3b, 0xeb, 0xe0, 0xd0, - 0x36, 0x82, 0xa8, 0x14, 0x34, 0x6a, 0x14, 0x86, 0xbc, 0xdf, 0x6c, 0xe6, 0x5c, 0x92, 0x1c, 0x1b, 0x27, 0x97, 0x82, - 0x42, 0x21, 0xab, 0x53, 0x22, 0xe5, 0x25, 0x9d, 0xef, 0x26, 0xf9, 0x13, 0x87, 0xe4, 0x9f, 0x51, 0xe6, 0x90, 0xbf, - 0x76, 0x71, 0x04, 0xc2, 0x38, 0x17, 0x72, 0x5b, 0x75, 0x3a, 0xa7, 0xe0, 0x44, 0xab, 0x63, 0xb4, 0x16, 0x56, 0xdc, - 0xc1, 0x50, 0xdc, 0x13, 0xa2, 0xdc, 0x90, 0xc4, 0xc6, 0x80, 0xfd, 0x2a, 0xa8, 0x06, 0x53, 0x6f, 0xf3, 0xe9, 0xb9, - 0x1c, 0xf0, 0xe4, 0xc3, 0xdd, 0xf1, 0xd0, 0xd3, 0xf9, 0xe6, 0xc9, 0x75, 0x72, 0x3f, 0x61, 0xd5, 0xce, 0xc1, 0xad, - 0x67, 0x82, 0xc2, 0xfc, 0x65, 0x1c, 0xbb, 0xce, 0x7c, 0xd6, 0x0e, 0xa1, 0x95, 0x7f, 0x00, 0x6d, 0xbb, 0xad, 0x5a, - 0x30, 0x67, 0x58, 0xe0, 0x47, 0x3a, 0x03, 0x35, 0xca, 0x76, 0xb0, 0x8f, 0x13, 0xd5, 0x80, 0xa5, 0xf1, 0xf6, 0xea, - 0x67, 0x85, 0x21, 0x13, 0x0d, 0x1a, 0x5e, 0x02, 0xff, 0xd3, 0x24, 0x0f, 0x74, 0xa3, 0xe4, 0x02, 0x20, 0x68, 0xae, - 0xf0, 0x54, 0x21, 0x0c, 0xa1, 0xca, 0xfb, 0xfe, 0x72, 0x8f, 0xd2, 0x79, 0xe5, 0x7d, 0x7c, 0x57, 0xa5, 0x5e, 0x01, - 0x59, 0xe0, 0x10, 0xcc, 0xc7, 0xb2, 0x40, 0x87, 0x2f, 0xcf, 0x6c, 0x73, 0x65, 0x42, 0x06, 0x95, 0xc6, 0xed, 0x84, - 0x36, 0x95, 0x5b, 0x4e, 0xd7, 0x5b, 0x34, 0xac, 0xd5, 0xee, 0x43, 0xed, 0x1b, 0xa9, 0x60, 0x84, 0xe7, 0xf7, 0xaa, - 0xb5, 0x1d, 0xb7, 0xf8, 0xb8, 0x9e, 0xbf, 0xb2, 0xb6, 0x29, 0x01, 0x4f, 0x73, 0x96, 0xc9, 0x67, 0x6c, 0x2c, 0x32, - 0x88, 0x59, 0x94, 0x38, 0xc1, 0xc5, 0xbe, 0xe3, 0xb7, 0x53, 0xeb, 0x73, 0x02, 0x05, 0x6b, 0x0b, 0x54, 0xbf, 0x3e, - 0xaa, 0xa0, 0xf5, 0xf9, 0x7a, 0xaf, 0xf9, 0xc1, 0xc1, 0x87, 0x0a, 0x4d, 0x06, 0x4a, 0x05, 0x85, 0xc3, 0xb4, 0xb4, - 0x4a, 0x63, 0x22, 0xb9, 0xfb, 0x7e, 0xe9, 0x04, 0xb0, 0x0c, 0xc3, 0xe5, 0x3d, 0x2f, 0xa9, 0x2c, 0x26, 0xeb, 0x2c, - 0xde, 0x38, 0x27, 0xb8, 0x6b, 0xb8, 0x00, 0x87, 0x07, 0x53, 0x5b, 0x7b, 0x8b, 0xf2, 0x2a, 0x19, 0xb6, 0x84, 0xe1, - 0x14, 0x90, 0xe5, 0x2b, 0x33, 0xc4, 0xa1, 0xc0, 0xad, 0x66, 0xc9, 0x29, 0xe8, 0x95, 0x53, 0x92, 0x07, 0x53, 0x48, - 0x7f, 0xad, 0x1d, 0x59, 0x8c, 0x89, 0x4e, 0xcc, 0x71, 0x52, 0x09, 0x4e, 0x5e, 0x6e, 0x73, 0x29, 0x5b, 0xa2, 0x66, - 0x4a, 0xea, 0xa8, 0x16, 0xb8, 0xec, 0x10, 0x5c, 0xf9, 0xdc, 0x28, 0x6e, 0x36, 0x6e, 0x06, 0x0c, 0xf8, 0x99, 0xf4, - 0x75, 0x30, 0x0a, 0x64, 0x86, 0x08, 0x16, 0x7e, 0x6d, 0xea, 0xae, 0x50, 0xdd, 0x88, 0x41, 0xdc, 0xd4, 0x45, 0x93, - 0x50, 0x71, 0xbd, 0xd3, 0x8a, 0x97, 0x8e, 0x75, 0x06, 0xb5, 0xb4, 0x5c, 0xb0, 0x4a, 0x24, 0x71, 0x96, 0x3f, 0xd6, - 0x49, 0xd1, 0x65, 0x23, 0xc2, 0x14, 0x18, 0xef, 0xd5, 0x1e, 0xb0, 0x02, 0xfe, 0x5f, 0x9e, 0x48, 0x67, 0x47, 0xad, - 0x13, 0x5b, 0xcd, 0xe9, 0x48, 0xfd, 0x77, 0x90, 0xea, 0xb2, 0x7e, 0xe6, 0x5f, 0x2a, 0x59, 0xc8, 0x49, 0x5e, 0x63, - 0xec, 0xa9, 0x62, 0xec, 0x18, 0xf4, 0x34, 0x9b, 0xf8, 0xdd, 0x37, 0x19, 0x2f, 0xdc, 0x48, 0x39, 0x43, 0x62, 0x5f, - 0x97, 0xd1, 0x72, 0xe7, 0xf7, 0xda, 0x6e, 0x84, 0x9c, 0x42, 0x16, 0x10, 0x31, 0x9c, 0x3d, 0xc5, 0x24, 0x6f, 0x34, - 0xba, 0xf9, 0x31, 0xab, 0x9c, 0x24, 0x15, 0x8c, 0x1c, 0x02, 0xba, 0x40, 0xf0, 0x35, 0x19, 0x0a, 0x21, 0x7f, 0x9b, - 0x99, 0x9d, 0x83, 0xaf, 0xfd, 0xe4, 0x9d, 0xef, 0x72, 0x35, 0xb7, 0x6d, 0x19, 0x34, 0x85, 0xf5, 0xf8, 0x55, 0xc0, - 0xe5, 0xeb, 0xbb, 0x13, 0x3c, 0x00, 0xee, 0xbd, 0x36, 0x81, 0x54, 0x34, 0xdc, 0x95, 0x9a, 0x25, 0x94, 0xa7, 0xaf, - 0x8b, 0xab, 0xac, 0x44, 0x77, 0xb2, 0xae, 0xac, 0x8c, 0x59, 0x49, 0xf3, 0xa2, 0xc8, 0x59, 0x15, 0xde, 0x5f, 0x4b, - 0xbf, 0x54, 0xc2, 0x65, 0xd3, 0xdb, 0x7e, 0x3a, 0xa7, 0x92, 0x38, 0x84, 0xfa, 0xf5, 0xae, 0xd8, 0x47, 0x05, 0x26, - 0x9c, 0x6b, 0x23, 0x14, 0x7f, 0xde, 0x26, 0x14, 0x49, 0x6a, 0x8e, 0xbc, 0x12, 0x88, 0xed, 0x7b, 0x08, 0x44, 0xe3, - 0x66, 0xb7, 0x32, 0x11, 0xd4, 0x91, 0x9a, 0x4c, 0xac, 0x6f, 0x29, 0x4d, 0x09, 0x37, 0xbb, 0xd1, 0xeb, 0xac, 0x56, - 0x7c, 0xd0, 0x02, 0x37, 0x12, 0x42, 0xf0, 0xb3, 0xad, 0x7f, 0x3a, 0x9c, 0x58, 0xbb, 0x81, 0x7d, 0x5e, 0x9a, 0x2c, - 0x38, 0x80, 0x04, 0x67, 0x5f, 0x25, 0x65, 0x29, 0x9a, 0x36, 0x14, 0x64, 0x08, 0x9c, 0xf2, 0x32, 0xcc, 0x04, 0x10, - 0x2b, 0x59, 0x61, 0x0c, 0x48, 0x7f, 0x6b, 0xee, 0x9f, 0x35, 0x2f, 0x3f, 0xad, 0x89, 0xd6, 0xe4, 0x8a, 0x56, 0x1f, - 0x6a, 0xf9, 0x06, 0x06, 0x02, 0xa3, 0x1f, 0xee, 0x29, 0x13, 0xb4, 0x12, 0xe5, 0xd8, 0x95, 0x43, 0xa4, 0x05, 0x4e, - 0xb4, 0xbd, 0x0f, 0x3a, 0xc2, 0xbb, 0x45, 0x9a, 0x10, 0xe1, 0xd0, 0xf5, 0x4b, 0x2a, 0x6b, 0xac, 0x64, 0x4a, 0x8d, - 0xa5, 0x44, 0x22, 0x45, 0xa6, 0x92, 0xa6, 0x83, 0xd6, 0x10, 0x14, 0xd0, 0x6e, 0x72, 0x9c, 0x56, 0x26, 0x70, 0xd2, - 0x68, 0xe0, 0xc8, 0xce, 0x3a, 0x1d, 0xf0, 0x46, 0x32, 0x24, 0x8c, 0x24, 0xda, 0x30, 0x39, 0x3b, 0x38, 0xf0, 0xa3, - 0x6a, 0xde, 0x41, 0x32, 0xc4, 0x44, 0xac, 0x56, 0xbe, 0x02, 0x2b, 0xc2, 0xab, 0x55, 0xe4, 0x82, 0xa5, 0xaa, 0xa1, - 0xdb, 0xbc, 0x2f, 0xe9, 0x5c, 0x09, 0xc0, 0x39, 0x40, 0xd8, 0xa0, 0x7e, 0x64, 0xdc, 0x7b, 0x11, 0xb8, 0xa3, 0x1a, - 0xe9, 0x20, 0x69, 0xb4, 0x87, 0x0e, 0xe3, 0x1a, 0x24, 0x43, 0x1a, 0x15, 0xe2, 0xe0, 0x60, 0x2f, 0x37, 0x22, 0xf2, - 0x27, 0x10, 0x65, 0x3f, 0x29, 0xc9, 0xa2, 0x07, 0x74, 0x77, 0x63, 0xdd, 0x19, 0x50, 0x52, 0x94, 0xd9, 0x56, 0xdb, - 0xae, 0x96, 0x05, 0x51, 0x36, 0x22, 0x26, 0x18, 0xdc, 0x07, 0xcb, 0xbe, 0x24, 0xf3, 0x57, 0xb2, 0xcc, 0xb1, 0xfe, - 0x79, 0x6b, 0x66, 0x75, 0x10, 0x04, 0x51, 0x36, 0x51, 0xb1, 0x0c, 0x1b, 0x86, 0x55, 0xc4, 0x7f, 0x64, 0xc0, 0x74, - 0x26, 0x1e, 0x94, 0x73, 0x0d, 0xa9, 0x06, 0xdf, 0xaa, 0x36, 0xf6, 0x2e, 0xc9, 0x4f, 0x5b, 0xbd, 0x0c, 0x1a, 0x92, - 0xe7, 0xbf, 0x15, 0x92, 0x87, 0x06, 0x12, 0x4d, 0x1e, 0x6b, 0x38, 0xdb, 0x81, 0x8b, 0x9f, 0xe4, 0x1a, 0xce, 0x76, - 0xe3, 0xd6, 0x62, 0xea, 0x97, 0x5d, 0xf0, 0x39, 0xbc, 0x41, 0x03, 0x5a, 0x15, 0x38, 0x50, 0x3e, 0x5a, 0xd7, 0xbd, - 0x34, 0x2b, 0x05, 0x61, 0x2a, 0xa9, 0xcf, 0xeb, 0x07, 0xa0, 0xd2, 0x46, 0x1d, 0xc3, 0x97, 0x87, 0x73, 0xec, 0xb8, - 0x04, 0xea, 0xa9, 0x2b, 0x40, 0x4e, 0xc6, 0xdb, 0x3e, 0x3f, 0x38, 0x00, 0xdb, 0x00, 0x94, 0xb8, 0x60, 0x14, 0xcd, - 0xe5, 0x22, 0x03, 0x55, 0x2a, 0xb7, 0xbf, 0xa1, 0x18, 0x6e, 0x81, 0xa8, 0x32, 0xf8, 0x01, 0x05, 0xf3, 0x28, 0xcf, - 0xf9, 0x95, 0x2e, 0x33, 0xbf, 0x89, 0xa0, 0x96, 0x94, 0x73, 0xad, 0x13, 0xa6, 0xb8, 0x9b, 0x1a, 0x3a, 0xad, 0xa3, - 0xed, 0xc5, 0x15, 0x4b, 0xe5, 0x2b, 0x9e, 0x4b, 0x96, 0xc2, 0xf2, 0x2b, 0x8a, 0x83, 0x15, 0xe5, 0x18, 0x0e, 0x6c, - 0xad, 0x57, 0x14, 0xc7, 0x77, 0x76, 0x91, 0x75, 0x1d, 0x68, 0x1a, 0xa5, 0x71, 0xa2, 0x27, 0x71, 0xf3, 0x19, 0x6d, - 0x0e, 0x67, 0xd9, 0xd2, 0xcd, 0xa7, 0xa9, 0x94, 0x0d, 0xc5, 0xdd, 0x7d, 0x4e, 0xad, 0x24, 0xb0, 0xd2, 0xf3, 0x4e, - 0xad, 0x05, 0x22, 0xde, 0x3b, 0x36, 0xc1, 0x5d, 0x09, 0x91, 0x0e, 0x47, 0x0d, 0xea, 0x70, 0x5a, 0xba, 0xf9, 0x72, - 0xeb, 0x95, 0xb6, 0x6d, 0xc2, 0x41, 0xd1, 0xc9, 0xe3, 0xdd, 0x96, 0xd5, 0x6b, 0x2b, 0x39, 0xac, 0xb4, 0xe0, 0xf7, - 0x65, 0xcc, 0x78, 0x69, 0xc9, 0x0b, 0xdb, 0xa3, 0xb8, 0x2f, 0xe9, 0x73, 0xb8, 0x33, 0xf4, 0x52, 0xce, 0x92, 0xb5, - 0xab, 0x31, 0xdd, 0xfd, 0x52, 0xfb, 0xdf, 0x97, 0xfe, 0x7b, 0xf2, 0x06, 0x02, 0xbb, 0x5f, 0x55, 0xcd, 0x37, 0x03, - 0xba, 0x5f, 0x55, 0x08, 0xfa, 0x2a, 0xdc, 0x68, 0xe7, 0x04, 0x72, 0x3b, 0xc1, 0xd3, 0xa0, 0x85, 0xac, 0xb6, 0xf4, - 0xb3, 0x0e, 0x23, 0xe9, 0x4c, 0x4b, 0x75, 0x1e, 0x48, 0x95, 0xa7, 0x06, 0xf9, 0x72, 0x75, 0x0b, 0x89, 0x99, 0x0c, - 0x43, 0xad, 0xc3, 0xef, 0xda, 0x1e, 0x23, 0x63, 0x52, 0x6d, 0x67, 0x7c, 0x1d, 0x65, 0x72, 0x1f, 0x4e, 0x99, 0xd8, - 0xb8, 0x87, 0x37, 0xa5, 0xe0, 0x41, 0xbb, 0xdf, 0x14, 0x8e, 0xb1, 0x9d, 0xeb, 0x7b, 0x40, 0xee, 0xf8, 0x54, 0x58, - 0xdd, 0xad, 0x6e, 0x65, 0x7c, 0x0d, 0xf6, 0x3f, 0x26, 0x53, 0x7b, 0x39, 0x8e, 0x19, 0x0e, 0xcc, 0xc2, 0x65, 0x51, - 0x3a, 0x05, 0x84, 0x56, 0xde, 0x32, 0x4c, 0x44, 0xa1, 0x02, 0xdc, 0x3f, 0x90, 0x6f, 0x0c, 0x4b, 0x1c, 0x97, 0x1c, - 0xe7, 0xe4, 0xbe, 0x1c, 0x51, 0x83, 0x5f, 0xc6, 0xef, 0x81, 0x8e, 0x15, 0x85, 0x16, 0x96, 0x8a, 0x9e, 0x0b, 0xb3, - 0x90, 0x9d, 0x69, 0xa9, 0x84, 0x95, 0x29, 0x35, 0x6a, 0x9a, 0x2d, 0x79, 0x9c, 0xd6, 0xca, 0x96, 0xe5, 0xa9, 0xaa, - 0xcd, 0x8b, 0x77, 0x60, 0xb1, 0x0a, 0x2d, 0xae, 0x56, 0x7e, 0x1d, 0xd5, 0x94, 0x3b, 0x91, 0x0c, 0x4c, 0xb8, 0x93, - 0x51, 0x51, 0xd3, 0xac, 0x75, 0x1f, 0x1f, 0xaf, 0x27, 0x14, 0x59, 0xdd, 0xbc, 0x06, 0x87, 0xeb, 0x42, 0xd0, 0xdd, - 0x5d, 0x9f, 0x02, 0xd1, 0xab, 0x2b, 0x27, 0x72, 0x30, 0xf4, 0x73, 0x99, 0x2a, 0x5b, 0xe5, 0xb4, 0x6e, 0xc1, 0x2f, - 0xbe, 0x23, 0x59, 0xd6, 0xa0, 0x6e, 0xb3, 0xde, 0x49, 0x36, 0x7a, 0x2e, 0x76, 0x25, 0x1b, 0xd5, 0xb4, 0xdd, 0xbd, - 0x16, 0xbe, 0x3b, 0x2d, 0x55, 0xcf, 0xb5, 0xbd, 0xc9, 0x6f, 0x98, 0xae, 0x0d, 0xb4, 0xa9, 0xd1, 0x6c, 0xb9, 0xca, - 0x59, 0x51, 0x8c, 0xcb, 0xcb, 0x04, 0x2a, 0x77, 0x67, 0xac, 0xe9, 0xdf, 0x58, 0x8d, 0xea, 0x3a, 0xae, 0xff, 0x03, - 0x9d, 0x24, 0xe2, 0x32, 0x4a, 0xde, 0xc3, 0x7c, 0x55, 0xe5, 0xcb, 0xdb, 0x38, 0x8b, 0x24, 0x33, 0xdc, 0xa5, 0x82, - 0xe1, 0x07, 0x07, 0x86, 0x1f, 0x34, 0x9f, 0xae, 0xfa, 0x93, 0xe5, 0xab, 0x72, 0x80, 0x70, 0x5c, 0x58, 0x96, 0x71, - 0x2e, 0xb7, 0xcf, 0xb1, 0xce, 0xc2, 0xce, 0x4b, 0x16, 0x76, 0x2e, 0xfd, 0xf5, 0xa1, 0x7c, 0xff, 0x9b, 0xed, 0xa3, - 0x6c, 0x72, 0xb6, 0x6f, 0xaa, 0x83, 0xff, 0x4d, 0x78, 0x67, 0x1f, 0x87, 0xcb, 0x1d, 0x05, 0x47, 0x2a, 0x5d, 0x45, - 0x83, 0xfc, 0x0e, 0xd2, 0x0e, 0x24, 0xed, 0x39, 0x77, 0x0e, 0x2a, 0x39, 0x65, 0x13, 0x81, 0xfc, 0xd1, 0x22, 0x97, - 0x62, 0x66, 0xc6, 0xcc, 0xcd, 0x35, 0x23, 0x55, 0x09, 0xae, 0x68, 0x15, 0x6d, 0x0f, 0xeb, 0x17, 0xb9, 0x96, 0x1f, - 0x79, 0x1a, 0x87, 0x39, 0x31, 0x52, 0x24, 0x0f, 0xd3, 0x82, 0xda, 0x64, 0xe3, 0xcd, 0x3a, 0x32, 0xe6, 0x29, 0xcf, - 0xa7, 0x2c, 0xf3, 0x05, 0x5e, 0xee, 0x9a, 0x4c, 0x40, 0x40, 0x46, 0x4f, 0x46, 0xbe, 0xad, 0x2e, 0xfc, 0x05, 0x30, - 0x1a, 0xf8, 0x81, 0x66, 0x4c, 0x4e, 0x45, 0x0c, 0x89, 0x29, 0x41, 0x5c, 0xde, 0x68, 0x3a, 0x38, 0xd8, 0xf3, 0x91, - 0x72, 0x4b, 0xc0, 0xd5, 0x6f, 0xb7, 0x06, 0xf7, 0x97, 0x70, 0x3d, 0xa7, 0x9a, 0x9a, 0xe1, 0x25, 0x5b, 0xbf, 0xc9, - 0x22, 0x83, 0x8f, 0xec, 0x96, 0x64, 0xb8, 0x28, 0x42, 0x0d, 0x35, 0x1a, 0x73, 0x96, 0xc4, 0x88, 0x7c, 0x64, 0xb7, - 0x61, 0x79, 0x5b, 0x5c, 0x5d, 0x6e, 0x56, 0x1b, 0x88, 0xc4, 0x75, 0x8a, 0x48, 0x35, 0x49, 0xb8, 0x2c, 0x88, 0xc8, - 0xf8, 0x04, 0x88, 0xf3, 0x6f, 0xec, 0x36, 0xd4, 0xe3, 0x71, 0xe7, 0xb2, 0x1e, 0x5e, 0x5a, 0xd4, 0x07, 0x4e, 0xb1, - 0xbb, 0x0d, 0xc6, 0xa0, 0x18, 0xa8, 0xbe, 0x43, 0x5a, 0x6b, 0x57, 0x99, 0x87, 0x18, 0x17, 0xf7, 0x5d, 0x0a, 0xf9, - 0xc2, 0x15, 0x6d, 0xb2, 0x96, 0xfa, 0xba, 0xd6, 0x89, 0x41, 0x87, 0x2a, 0xd7, 0xe3, 0xdc, 0xcf, 0xec, 0xa9, 0x33, - 0x77, 0x10, 0x1c, 0x47, 0xd8, 0x17, 0xd2, 0x0c, 0x1a, 0x7e, 0xab, 0x53, 0x42, 0xaa, 0x48, 0xd2, 0xeb, 0xaa, 0x9f, - 0x77, 0xee, 0x03, 0xde, 0x21, 0xa5, 0x25, 0x52, 0xd7, 0x31, 0x0b, 0x9b, 0x2e, 0xfa, 0x9d, 0xa4, 0xfe, 0xd2, 0x2e, - 0x21, 0xcc, 0x5c, 0x2c, 0xca, 0x02, 0xa8, 0xd0, 0xd0, 0x97, 0xce, 0x00, 0xe4, 0x63, 0x9f, 0x6f, 0x48, 0xcd, 0x54, - 0x49, 0xcd, 0xc0, 0xc1, 0xf8, 0x0e, 0x29, 0xc9, 0x14, 0x32, 0x94, 0x12, 0xa9, 0x84, 0x9e, 0xd9, 0x5c, 0x43, 0x42, - 0xee, 0x86, 0x96, 0xd7, 0xe7, 0xf4, 0x9e, 0xa7, 0x35, 0xb0, 0x7c, 0x35, 0x0e, 0x2e, 0x42, 0x58, 0x12, 0xd3, 0x0d, - 0x0a, 0xeb, 0xce, 0xc9, 0x6c, 0x7e, 0xab, 0x2f, 0x02, 0xbb, 0x2c, 0x6a, 0x51, 0xe2, 0x4f, 0xf1, 0x32, 0xf3, 0xa7, - 0x24, 0x85, 0x7c, 0x44, 0x51, 0x94, 0xf0, 0x33, 0x77, 0x37, 0x6a, 0xd9, 0xca, 0xdb, 0xaf, 0xf8, 0x81, 0x32, 0x2f, - 0x21, 0x47, 0x93, 0x64, 0x96, 0xa7, 0x64, 0xbe, 0xba, 0x6b, 0xe7, 0x6c, 0xdb, 0x57, 0x26, 0x45, 0xc7, 0x00, 0xf6, - 0x9d, 0xf4, 0x97, 0xce, 0x2a, 0xdc, 0xbb, 0xdc, 0xe6, 0xca, 0x9f, 0x09, 0xf6, 0x55, 0x49, 0xa4, 0x7e, 0x4e, 0xd7, - 0x24, 0xce, 0xdd, 0xb9, 0x96, 0x3f, 0x2f, 0x58, 0x76, 0x7b, 0xc6, 0x20, 0xd7, 0x59, 0xc0, 0x5d, 0xdf, 0x6a, 0x1b, - 0xaa, 0x3c, 0xf5, 0x7e, 0xaa, 0x94, 0x95, 0xa2, 0x7e, 0x09, 0x70, 0xfd, 0x8a, 0x60, 0xa1, 0xa2, 0x8d, 0x8e, 0x23, - 0x46, 0x9f, 0x16, 0xb6, 0xf3, 0xf2, 0x24, 0xeb, 0x72, 0xf0, 0xaf, 0x55, 0x98, 0x36, 0xc1, 0x02, 0x22, 0xdc, 0x0b, - 0xa9, 0x83, 0x7c, 0xb8, 0xee, 0x95, 0x81, 0x22, 0x08, 0xdf, 0xa5, 0xbb, 0x97, 0xba, 0x2d, 0x6b, 0x76, 0xf7, 0x52, - 0x6b, 0x41, 0x3f, 0x95, 0xf2, 0x43, 0xcc, 0x3c, 0xe5, 0xe5, 0x65, 0x5e, 0x14, 0xb8, 0x00, 0xf0, 0xbe, 0xef, 0xfa, - 0xfe, 0xf7, 0x26, 0x69, 0x30, 0x80, 0x58, 0xec, 0x59, 0x22, 0x2c, 0x13, 0xaf, 0xe6, 0xff, 0x7e, 0x63, 0xfe, 0xef, - 0x9d, 0x2b, 0xa7, 0x60, 0x1a, 0x4d, 0x52, 0x16, 0x5b, 0xd6, 0x89, 0x35, 0x01, 0x2a, 0xbd, 0x2d, 0x97, 0xf4, 0xe3, - 0x45, 0x08, 0x1a, 0xd7, 0x72, 0x2c, 0x52, 0xd9, 0x1c, 0x47, 0x33, 0x9e, 0xdc, 0x86, 0x0b, 0xde, 0x9c, 0x89, 0x54, - 0xe4, 0xf3, 0x68, 0xc4, 0x48, 0x7e, 0x9b, 0x4b, 0x36, 0x6b, 0x2e, 0x38, 0x79, 0xc9, 0x92, 0x2b, 0x26, 0xf9, 0x28, - 0x22, 0xe8, 0x24, 0xe3, 0x51, 0xe2, 0xbd, 0x89, 0xb2, 0x4c, 0x5c, 0x23, 0xf2, 0x4e, 0x5c, 0x0a, 0x29, 0xc8, 0xdb, - 0x9b, 0xdb, 0x09, 0x4b, 0xc9, 0x87, 0xcb, 0x45, 0x2a, 0x17, 0x24, 0x8f, 0xd2, 0xbc, 0x99, 0xb3, 0x8c, 0x8f, 0xbb, - 0x23, 0x91, 0x88, 0xac, 0x09, 0x29, 0xdb, 0x33, 0x16, 0x26, 0x7c, 0x32, 0x95, 0x5e, 0x1c, 0x65, 0x1f, 0xbb, 0xcd, - 0xe6, 0x3c, 0xe3, 0xb3, 0x28, 0xbb, 0x6d, 0xaa, 0x16, 0xe1, 0x67, 0xad, 0xa3, 0xe8, 0xf3, 0xf1, 0xc3, 0xae, 0xcc, - 0xa2, 0x34, 0xe7, 0xb0, 0x4d, 0x61, 0x94, 0x24, 0xde, 0xd1, 0xa3, 0xd6, 0x2c, 0xdf, 0xd3, 0x81, 0xbc, 0x28, 0x95, - 0xc5, 0x05, 0xf9, 0x08, 0x70, 0x07, 0x97, 0x32, 0x25, 0x97, 0x0b, 0x29, 0x45, 0xba, 0x1c, 0x2d, 0xb2, 0x5c, 0x64, - 0xe1, 0x5c, 0xf0, 0x54, 0xb2, 0xac, 0x7b, 0x29, 0xb2, 0x98, 0x65, 0xcd, 0x2c, 0x8a, 0xf9, 0x22, 0x0f, 0x1f, 0xce, - 0x6f, 0xba, 0xa0, 0x59, 0x4c, 0x32, 0xb1, 0x48, 0x63, 0x33, 0x17, 0x4f, 0xa7, 0x2c, 0xe3, 0xd2, 0xad, 0x50, 0xaf, - 0x30, 0x09, 0x13, 0x9e, 0xb2, 0x28, 0x6b, 0x4e, 0xa0, 0x33, 0x98, 0x45, 0xad, 0x98, 0x4d, 0x48, 0x36, 0xb9, 0x8c, - 0xfc, 0x76, 0xe7, 0x09, 0xb1, 0x7f, 0x83, 0x47, 0xd8, 0x6b, 0x6d, 0x2f, 0x6e, 0xb7, 0x5a, 0x7f, 0xc2, 0xdd, 0xb5, - 0x59, 0x14, 0x40, 0x61, 0x7b, 0x7e, 0xe3, 0xe5, 0x02, 0x72, 0xda, 0xb6, 0xf5, 0xec, 0xce, 0xa3, 0x18, 0x12, 0x82, - 0xc3, 0xce, 0xfc, 0xa6, 0x80, 0xd5, 0x85, 0x3a, 0xc9, 0xd4, 0x2c, 0xd2, 0x3c, 0x2d, 0x7f, 0x2b, 0xc4, 0x4f, 0xb7, - 0x43, 0xdc, 0xb1, 0x10, 0x57, 0x58, 0x6f, 0xc6, 0x8b, 0x4c, 0xc5, 0x56, 0xc3, 0x76, 0xae, 0x01, 0x99, 0x8a, 0x2b, - 0x96, 0x59, 0x38, 0xd4, 0xc3, 0x6f, 0x06, 0xa3, 0xb3, 0x1d, 0x8c, 0xa7, 0x9f, 0x02, 0x23, 0x4b, 0xe3, 0x65, 0x7d, - 0x5f, 0xdb, 0x19, 0x9b, 0x75, 0xa7, 0x0c, 0xe8, 0x29, 0xec, 0xc0, 0xef, 0x6b, 0x1e, 0xcb, 0xa9, 0xfe, 0xa9, 0xc8, - 0xf9, 0x5a, 0xd7, 0x3d, 0x6a, 0xb5, 0xf4, 0x73, 0xce, 0x7f, 0x61, 0x61, 0x3b, 0x80, 0x06, 0xc5, 0x05, 0xf9, 0x5b, - 0x79, 0x99, 0xb7, 0xce, 0x3d, 0xc9, 0x0f, 0xee, 0x2d, 0x5f, 0x27, 0x49, 0xb1, 0xba, 0x11, 0x4d, 0x32, 0x2b, 0x2b, - 0xb5, 0xf0, 0x01, 0xb7, 0x9d, 0x3a, 0x4f, 0x94, 0xf7, 0xca, 0x5b, 0x9c, 0xbc, 0xff, 0x83, 0xce, 0xbb, 0x08, 0x21, - 0xd2, 0xe1, 0x24, 0x1b, 0x8a, 0x6e, 0xda, 0xa3, 0xad, 0x6e, 0xda, 0x6c, 0x62, 0x5f, 0xd0, 0x6c, 0x90, 0x9a, 0xf4, - 0x3c, 0x9f, 0xf7, 0x85, 0x32, 0xb6, 0x73, 0x1c, 0x0a, 0xb8, 0x6a, 0xba, 0x5a, 0x55, 0x61, 0x00, 0xae, 0xae, 0x6b, - 0xfc, 0x4d, 0x9a, 0x06, 0x24, 0x77, 0x38, 0x79, 0x6a, 0x5f, 0xec, 0x92, 0x59, 0x5e, 0x91, 0x88, 0x91, 0xc2, 0x5c, - 0x30, 0x8f, 0xe4, 0x14, 0xbc, 0x14, 0xa5, 0xf8, 0xa9, 0x92, 0x98, 0xd0, 0x21, 0xc2, 0xfd, 0xac, 0xcc, 0x70, 0x83, - 0x4c, 0xbe, 0xac, 0x80, 0x51, 0xbe, 0x91, 0x14, 0x46, 0x24, 0xbf, 0x50, 0x6d, 0xd3, 0x59, 0x8b, 0x6e, 0x7c, 0x5f, - 0x8b, 0x8e, 0xa5, 0x92, 0xab, 0xdc, 0x6d, 0x1b, 0x71, 0x98, 0x46, 0xf9, 0xf9, 0x48, 0xdf, 0x95, 0xcc, 0xab, 0x9b, - 0x01, 0x91, 0x82, 0x5e, 0x1b, 0x69, 0x2c, 0x53, 0xf6, 0xe8, 0xf7, 0x72, 0xa7, 0x7d, 0x92, 0xdd, 0x65, 0x9f, 0x94, - 0x0b, 0xcf, 0xc5, 0x22, 0x1b, 0x41, 0x38, 0xd2, 0x48, 0xbd, 0x4d, 0xc7, 0x0d, 0x52, 0x2a, 0x06, 0x22, 0xd2, 0xc9, - 0x04, 0x95, 0x84, 0xbb, 0x2f, 0x95, 0x60, 0x2a, 0xe4, 0xa5, 0xef, 0x6b, 0x18, 0x11, 0x67, 0x97, 0x04, 0x32, 0x3b, - 0x56, 0x49, 0x8d, 0x7e, 0x4a, 0x7b, 0x69, 0xb0, 0x48, 0xf9, 0xcf, 0x0b, 0x76, 0xce, 0x41, 0xd7, 0xe4, 0x01, 0x8f, - 0x55, 0xac, 0x09, 0x64, 0x5f, 0xb3, 0x0d, 0xc1, 0x0b, 0x1e, 0xeb, 0x8d, 0x49, 0x55, 0xa5, 0xc9, 0x6d, 0x42, 0x4d, - 0x04, 0xfe, 0x62, 0xd0, 0x0e, 0x38, 0x89, 0xc5, 0x2c, 0xe2, 0x69, 0xa8, 0x5c, 0xbe, 0xe5, 0x60, 0x21, 0xb4, 0x26, - 0x3c, 0x0e, 0x53, 0xb3, 0x3d, 0x6d, 0x1c, 0xfc, 0x24, 0x78, 0xaa, 0xba, 0x16, 0x5d, 0xa1, 0x10, 0xaa, 0xd1, 0x47, - 0x2d, 0x82, 0x4f, 0xb4, 0x5c, 0x13, 0x98, 0xb8, 0xd5, 0xe5, 0xb5, 0xf3, 0xda, 0x0e, 0xb4, 0xd6, 0x36, 0x4a, 0x1b, - 0x01, 0x62, 0xbd, 0x34, 0x17, 0x99, 0xf4, 0xfd, 0x29, 0x49, 0x30, 0xed, 0x4d, 0x95, 0xb3, 0xeb, 0x38, 0x51, 0xff, - 0xf5, 0x9b, 0xed, 0xb0, 0x5d, 0x9a, 0xef, 0xb5, 0xdb, 0xc0, 0x3a, 0x39, 0xca, 0xdc, 0x28, 0x55, 0xcb, 0x28, 0x7f, - 0xeb, 0xa5, 0x56, 0xcf, 0xe5, 0x72, 0x89, 0x39, 0x6e, 0x5a, 0x54, 0xf9, 0x35, 0x20, 0x54, 0xb0, 0x68, 0xc7, 0x54, - 0xb8, 0xa8, 0xd6, 0x5d, 0xaa, 0x92, 0x17, 0x5a, 0x44, 0x9f, 0xef, 0x2f, 0x33, 0x33, 0x63, 0x71, 0xc1, 0xad, 0x93, - 0xa9, 0x4e, 0x72, 0x85, 0xc1, 0x88, 0xa3, 0x87, 0x6e, 0x6b, 0xa6, 0x61, 0xb9, 0xa5, 0xd9, 0x56, 0xba, 0x0d, 0xf4, - 0x23, 0xcb, 0x68, 0x15, 0xee, 0xda, 0x18, 0x00, 0x72, 0xf5, 0xb6, 0x01, 0x06, 0x66, 0x6b, 0x2e, 0xed, 0x12, 0x40, - 0x1b, 0x1b, 0x33, 0xb8, 0x48, 0x73, 0xb1, 0xbf, 0xfc, 0x46, 0x16, 0x87, 0x4e, 0x53, 0xf5, 0x9b, 0xc7, 0xf0, 0x3f, - 0x48, 0xc0, 0xa5, 0x56, 0x4a, 0x43, 0xf4, 0xf5, 0xdb, 0xb3, 0xf7, 0x88, 0x5c, 0x8a, 0xf8, 0x36, 0x44, 0x32, 0x5b, - 0x30, 0x54, 0xe0, 0x40, 0x4e, 0x59, 0x5a, 0xbe, 0x8c, 0x47, 0x24, 0x2c, 0x48, 0xc4, 0x44, 0x5f, 0xca, 0x5c, 0x37, - 0x92, 0x47, 0x17, 0xc7, 0xea, 0x25, 0x53, 0xbd, 0x63, 0xa9, 0x5f, 0xef, 0x25, 0x33, 0xf8, 0xd9, 0x83, 0x10, 0xca, - 0xf1, 0xa1, 0x9c, 0xaa, 0x87, 0x33, 0x38, 0x30, 0xea, 0x69, 0x7f, 0xb9, 0x41, 0x4c, 0x7d, 0x18, 0x62, 0xda, 0xd3, - 0x4b, 0xc8, 0x55, 0xab, 0x8b, 0x70, 0x74, 0x71, 0x51, 0x1c, 0x1f, 0xc2, 0x58, 0x87, 0x76, 0x5c, 0x80, 0xd0, 0xf6, - 0x2f, 0x09, 0x0c, 0x5e, 0x36, 0x94, 0xd1, 0x1e, 0x0c, 0x01, 0xf3, 0xc6, 0x3d, 0x58, 0x24, 0x10, 0x18, 0xf4, 0x8e, - 0xcb, 0x12, 0x75, 0x62, 0x75, 0xd1, 0x2e, 0x08, 0x74, 0xc3, 0x8a, 0xee, 0xb5, 0x37, 0xb5, 0xda, 0x5f, 0x0b, 0x52, - 0xec, 0x42, 0x77, 0x81, 0xe1, 0x7f, 0x05, 0xd9, 0xf1, 0xa1, 0xc6, 0xc3, 0x85, 0xfb, 0x6a, 0x13, 0xfd, 0xda, 0x81, - 0x12, 0x5b, 0x83, 0x5c, 0x92, 0x8f, 0x92, 0x7c, 0xbc, 0x50, 0x4d, 0xad, 0x30, 0x02, 0x2d, 0x09, 0x84, 0x76, 0xcb, - 0x6a, 0x1d, 0x23, 0x91, 0x24, 0xd1, 0x3c, 0x67, 0xa1, 0xfd, 0x61, 0xe4, 0x12, 0x88, 0xb7, 0x4d, 0x45, 0xc0, 0xa4, - 0xd7, 0x9c, 0x82, 0xba, 0xb0, 0xa9, 0xa5, 0x5c, 0x45, 0x99, 0xdf, 0x6c, 0x8e, 0x9a, 0x97, 0x13, 0x5c, 0xc8, 0xe9, - 0xd2, 0x95, 0x6a, 0x8f, 0x5b, 0xad, 0x2e, 0xe4, 0x42, 0x36, 0xa3, 0x84, 0x4f, 0xd2, 0x30, 0x61, 0x63, 0x59, 0x48, - 0xb8, 0xa5, 0xb6, 0xb4, 0x6a, 0x44, 0xd0, 0x79, 0x94, 0xb1, 0x99, 0x17, 0xc0, 0xbf, 0x77, 0x4f, 0x5c, 0xc8, 0x38, - 0x4c, 0xe5, 0xb4, 0xa9, 0xb2, 0x6e, 0xe1, 0xce, 0x80, 0x9c, 0xd6, 0x9e, 0x97, 0xce, 0x44, 0x23, 0x06, 0x2a, 0x56, - 0x21, 0x33, 0x4f, 0x4e, 0x89, 0xcc, 0xdc, 0x76, 0x29, 0x5e, 0x6e, 0xac, 0x60, 0x53, 0xd2, 0x1f, 0xe1, 0x22, 0x57, - 0x8a, 0xf1, 0x66, 0x63, 0xab, 0x2e, 0xd5, 0x9f, 0x36, 0xd0, 0xe7, 0x28, 0x76, 0x85, 0x76, 0x2c, 0x2f, 0x75, 0x8f, - 0xfb, 0x20, 0xb3, 0xa6, 0x72, 0x12, 0xb7, 0x07, 0x2e, 0x78, 0x3a, 0x5f, 0xc8, 0x81, 0x72, 0x6a, 0x67, 0x70, 0x41, - 0x62, 0x48, 0x9c, 0x12, 0xc0, 0xc1, 0x70, 0xa9, 0x81, 0x19, 0x45, 0xc9, 0xc8, 0x07, 0x88, 0xbc, 0xa6, 0xf7, 0x34, - 0x63, 0x33, 0xdc, 0x9d, 0xf1, 0xb4, 0xa9, 0xeb, 0x1e, 0x39, 0x6a, 0x49, 0xf0, 0x04, 0x9e, 0x8a, 0x40, 0x8d, 0x46, - 0x54, 0xee, 0xea, 0x16, 0x5c, 0x5e, 0x0c, 0x8b, 0xa2, 0x9b, 0x49, 0x7f, 0xf0, 0xda, 0xc7, 0x43, 0xf2, 0x8b, 0xf3, - 0x72, 0x16, 0x64, 0x8f, 0x0a, 0x22, 0x1d, 0xbc, 0xa3, 0x89, 0x7b, 0x16, 0x54, 0xb3, 0x5f, 0x28, 0x34, 0x7c, 0xe7, - 0x23, 0x96, 0xcf, 0x9b, 0x9a, 0x77, 0x35, 0x15, 0xc9, 0x22, 0xe8, 0x8a, 0x8d, 0xa7, 0xf6, 0x7b, 0xb9, 0x54, 0x6c, - 0xc9, 0x5c, 0xd2, 0xd0, 0xce, 0x84, 0x61, 0x79, 0xa9, 0xc7, 0x3c, 0xbb, 0xd7, 0x78, 0x70, 0x8d, 0x9f, 0x5c, 0x9c, - 0xd4, 0x79, 0x1c, 0xf0, 0xa5, 0xf2, 0x05, 0x76, 0x51, 0x92, 0xc0, 0x84, 0x17, 0x56, 0x7d, 0x71, 0x5f, 0xfa, 0x31, - 0x90, 0x43, 0x1f, 0x17, 0xe6, 0x9c, 0x3e, 0x53, 0x2a, 0xa5, 0xf3, 0xd6, 0xbc, 0x3d, 0x69, 0x83, 0x45, 0x5a, 0xfa, - 0x72, 0x08, 0x77, 0xd7, 0xf2, 0xa2, 0xbb, 0x15, 0xef, 0xd2, 0x0a, 0xa9, 0xa7, 0x16, 0x44, 0x51, 0x96, 0xc6, 0xc8, - 0xfb, 0xcb, 0x28, 0xe1, 0xa3, 0x8f, 0x14, 0xed, 0x2f, 0x7d, 0xbc, 0x79, 0xed, 0x51, 0x71, 0x05, 0xcb, 0xb0, 0x71, - 0xdd, 0x91, 0x9e, 0x06, 0x0e, 0x2f, 0xd6, 0x6f, 0xc5, 0x41, 0xbd, 0xfd, 0x25, 0x30, 0x1e, 0x3d, 0x4f, 0xef, 0xa2, - 0x38, 0xaf, 0xde, 0x75, 0x55, 0x41, 0x01, 0x68, 0xd6, 0xe5, 0x9e, 0x22, 0x2a, 0x8a, 0x3e, 0x49, 0x69, 0xc8, 0xd3, - 0x4c, 0x0d, 0xe0, 0x94, 0x86, 0xbf, 0x21, 0xef, 0x2f, 0x65, 0x19, 0x2b, 0x3d, 0x1a, 0x2a, 0x25, 0x83, 0x22, 0x98, - 0x0b, 0xcc, 0xd8, 0x20, 0x66, 0x32, 0xe2, 0x89, 0xee, 0xd2, 0xb5, 0x06, 0xf8, 0xda, 0x8a, 0x56, 0xab, 0xbc, 0xbe, - 0x16, 0x5e, 0xc7, 0xa0, 0x5a, 0xd9, 0xf1, 0x61, 0x05, 0xb7, 0x5a, 0x99, 0x3a, 0x93, 0x6e, 0x68, 0xb0, 0x5a, 0xa1, - 0xae, 0xf3, 0xfe, 0x32, 0x52, 0xd7, 0x86, 0x00, 0x40, 0x61, 0x00, 0x84, 0xa0, 0xb5, 0xbe, 0x16, 0xe3, 0x27, 0x54, - 0x04, 0x32, 0xca, 0x26, 0x4c, 0xae, 0x21, 0x36, 0xd1, 0x39, 0xaa, 0x5d, 0x1b, 0xa0, 0xde, 0x80, 0x36, 0xaa, 0x43, - 0x7b, 0x01, 0x48, 0xef, 0xef, 0x2f, 0x79, 0x41, 0xf7, 0x97, 0x2c, 0x1d, 0x89, 0x98, 0x7d, 0x78, 0xf7, 0x25, 0x5c, - 0x72, 0x14, 0x29, 0x18, 0x16, 0x53, 0x0c, 0x82, 0x53, 0x6d, 0x8e, 0x16, 0x21, 0x42, 0x89, 0x10, 0xcd, 0x09, 0x3c, - 0x35, 0x97, 0x02, 0xb1, 0x40, 0x5e, 0x5f, 0x43, 0xce, 0x62, 0x0d, 0x33, 0x4d, 0x55, 0x2f, 0x51, 0x1c, 0x1f, 0xea, - 0xd6, 0x5a, 0x04, 0xe8, 0x46, 0x80, 0x04, 0x75, 0x4e, 0x2b, 0x1c, 0x40, 0x5e, 0xb3, 0x8b, 0x87, 0x98, 0x5f, 0x95, - 0xc4, 0xa6, 0x2e, 0x50, 0xf5, 0x8e, 0x93, 0xe8, 0x92, 0x25, 0xbd, 0xfd, 0x65, 0xba, 0x5a, 0xb5, 0x8a, 0xe3, 0x43, - 0xfd, 0xe8, 0x1d, 0x2b, 0xbe, 0xa1, 0x5f, 0x78, 0xa9, 0xb6, 0x18, 0x6e, 0x25, 0x42, 0xb6, 0xa7, 0x4d, 0x73, 0x0a, - 0xcd, 0x00, 0x05, 0xf2, 0x54, 0x82, 0x85, 0x6a, 0x54, 0x2a, 0x44, 0x05, 0xf2, 0x78, 0xbc, 0x59, 0x96, 0x4b, 0x36, - 0x87, 0xd2, 0xe9, 0x6a, 0xd5, 0x2e, 0x90, 0x37, 0xe3, 0x29, 0x3c, 0xa5, 0xab, 0x95, 0xba, 0xf0, 0x37, 0xe3, 0xa9, - 0xdf, 0x02, 0xb2, 0x45, 0xde, 0x2c, 0xba, 0x51, 0x0b, 0xb6, 0x35, 0xd1, 0x8d, 0xdf, 0x36, 0x55, 0x41, 0x89, 0x9f, - 0x1c, 0x28, 0xae, 0xda, 0xd1, 0xc4, 0xec, 0x68, 0x4c, 0x16, 0xfa, 0x2a, 0x13, 0xf5, 0x63, 0x9a, 0x6c, 0xdf, 0xd1, - 0xd8, 0xee, 0xe8, 0x62, 0xc7, 0x8e, 0x2e, 0xee, 0xd8, 0xd1, 0xc8, 0xec, 0x9e, 0x57, 0xe2, 0x4e, 0xac, 0x56, 0xed, - 0x56, 0x85, 0xbd, 0xe3, 0xc3, 0x98, 0x5f, 0xc1, 0x6e, 0x80, 0x9a, 0x27, 0xf9, 0x8c, 0x6d, 0x27, 0xca, 0x3a, 0x8a, - 0xd9, 0xaf, 0xc2, 0x64, 0x85, 0x85, 0xb4, 0x8e, 0x05, 0x97, 0xae, 0xcb, 0x98, 0xdb, 0x1f, 0x49, 0xd9, 0x1c, 0xf0, - 0x90, 0x03, 0x1e, 0xa6, 0xf6, 0x05, 0x98, 0x3e, 0x7a, 0x8f, 0x08, 0xf2, 0x90, 0x25, 0xeb, 0x8b, 0xe2, 0x1c, 0x64, - 0x84, 0x5a, 0xdf, 0xbd, 0x68, 0x11, 0x5a, 0xa3, 0xde, 0x6e, 0x9a, 0x83, 0xf0, 0xf8, 0xb5, 0xc8, 0x62, 0x14, 0xea, - 0xa6, 0xbf, 0x0a, 0x55, 0x33, 0x9e, 0x9a, 0x64, 0xab, 0x9d, 0xb4, 0x56, 0xd5, 0xbb, 0x14, 0xd7, 0x79, 0xf4, 0x48, - 0xb7, 0x98, 0x47, 0x52, 0xb2, 0x2c, 0x35, 0x94, 0x8b, 0xd0, 0xff, 0x17, 0x54, 0xb8, 0x85, 0xaf, 0x44, 0x76, 0x03, - 0x2c, 0x01, 0x1a, 0x85, 0xdd, 0xf0, 0x7c, 0x2d, 0x9e, 0xf6, 0x2a, 0x0d, 0xf6, 0x16, 0xbb, 0x46, 0x83, 0x2e, 0x02, - 0x1b, 0x66, 0x31, 0x63, 0xf1, 0xb9, 0x62, 0xd0, 0xfd, 0xd1, 0x85, 0x51, 0x58, 0xd7, 0xc4, 0x5d, 0xd5, 0x81, 0xa0, - 0x1f, 0x17, 0x9d, 0x27, 0x0f, 0x4f, 0x11, 0xd1, 0x3c, 0x5e, 0x8c, 0xc7, 0x08, 0x17, 0xde, 0xfd, 0xba, 0xb5, 0x1f, - 0xfe, 0xb8, 0xf8, 0xe2, 0x45, 0xeb, 0x8b, 0xb2, 0x73, 0x0a, 0x44, 0x64, 0xe2, 0xfb, 0x56, 0x54, 0x39, 0xf0, 0xda, - 0x15, 0x8d, 0xa3, 0x74, 0xf7, 0x72, 0x06, 0xee, 0x72, 0xf2, 0x39, 0x63, 0x31, 0x10, 0x27, 0xd9, 0x28, 0x3d, 0x4f, - 0xd8, 0x15, 0xb3, 0x6f, 0x1e, 0xdc, 0x32, 0xd9, 0x96, 0x1e, 0x23, 0xb1, 0x48, 0xa5, 0x49, 0x74, 0x30, 0xac, 0xd6, - 0x59, 0xd2, 0x85, 0x5a, 0x83, 0x6b, 0x23, 0xdc, 0x6a, 0x39, 0x57, 0x97, 0x5e, 0xc5, 0x05, 0x41, 0x0e, 0x00, 0x3b, - 0x21, 0xeb, 0xef, 0x28, 0x0f, 0x5b, 0xa4, 0xb5, 0x0b, 0x36, 0xd2, 0xc6, 0x21, 0x42, 0x43, 0x8b, 0x27, 0xe5, 0xab, - 0xac, 0xbd, 0x30, 0x62, 0x27, 0xbe, 0x3e, 0x89, 0x81, 0xcb, 0x0c, 0x06, 0x4b, 0x59, 0x9e, 0xef, 0x44, 0x40, 0xb9, - 0x89, 0x04, 0x55, 0xad, 0xd1, 0x8e, 0x51, 0x48, 0x8b, 0xc0, 0x09, 0x53, 0x00, 0x97, 0x11, 0x53, 0xd3, 0x8a, 0x8d, - 0xc7, 0x6c, 0x54, 0xba, 0x7a, 0x21, 0xf6, 0x35, 0xe6, 0x89, 0x84, 0x10, 0x90, 0x8a, 0xcd, 0xa0, 0x37, 0x22, 0x65, - 0x08, 0xdb, 0x6c, 0x4e, 0x03, 0xbf, 0x91, 0xff, 0xdb, 0xe1, 0xd1, 0x23, 0xd6, 0x61, 0x31, 0xb3, 0xac, 0x56, 0xd6, - 0xcd, 0x53, 0x2b, 0xaf, 0x23, 0x52, 0x28, 0x3f, 0xce, 0xae, 0x03, 0x74, 0xbf, 0x63, 0xb2, 0x6c, 0x7f, 0xf1, 0xa8, - 0xdd, 0x2a, 0x10, 0x41, 0x30, 0xdc, 0x7d, 0x4f, 0x89, 0xea, 0x75, 0x04, 0xbd, 0x16, 0xe9, 0xaf, 0xe9, 0xd7, 0x69, - 0x7f, 0xde, 0x46, 0x44, 0xbf, 0x48, 0x00, 0x17, 0x25, 0x33, 0x18, 0x81, 0xf3, 0xf3, 0x77, 0x2f, 0xa5, 0x3e, 0xf8, - 0xfd, 0xe0, 0x79, 0xdc, 0x6e, 0x21, 0x82, 0x72, 0x29, 0xe6, 0xbf, 0x62, 0x09, 0x47, 0x88, 0xa0, 0x51, 0x22, 0x72, - 0xe6, 0xae, 0x41, 0xab, 0xb3, 0xbf, 0x7f, 0x11, 0x1a, 0xa2, 0x79, 0xc6, 0xf2, 0xdc, 0x73, 0xc7, 0x37, 0xa4, 0xf4, - 0x09, 0x86, 0xb9, 0x95, 0xe2, 0x72, 0x26, 0x15, 0x5e, 0xf4, 0x1d, 0x7f, 0x97, 0xaa, 0x74, 0xd9, 0x06, 0xb1, 0x29, - 0x11, 0x50, 0x32, 0x36, 0xad, 0x5d, 0x7d, 0x72, 0xe6, 0x2d, 0x47, 0x4f, 0x4f, 0xac, 0x63, 0xc2, 0x9b, 0x13, 0xd4, - 0x4a, 0x66, 0x3c, 0x3d, 0xdf, 0x52, 0x1a, 0xdd, 0x6c, 0x29, 0x05, 0x95, 0xad, 0x84, 0xce, 0xbc, 0x7e, 0xe6, 0xd3, - 0x58, 0xaf, 0x14, 0x1f, 0x17, 0xc4, 0x58, 0xf9, 0x2d, 0x3f, 0x01, 0xa9, 0xb3, 0x0d, 0x6a, 0x84, 0xdf, 0x3e, 0x1d, - 0x94, 0xfc, 0x9a, 0xe9, 0xca, 0x51, 0x7e, 0xdf, 0x0a, 0xa1, 0xb4, 0x09, 0xfe, 0xeb, 0xe4, 0x57, 0xad, 0x95, 0xdd, - 0x7c, 0x9a, 0xe0, 0x1c, 0xad, 0xea, 0x77, 0x6c, 0xbd, 0xb9, 0xc7, 0xbe, 0xbe, 0xf7, 0x5b, 0x8a, 0x8d, 0xe2, 0x53, - 0xee, 0xff, 0x28, 0xe1, 0xb3, 0x8a, 0x04, 0x36, 0xc1, 0x54, 0x1a, 0x0f, 0x24, 0x33, 0xb9, 0x83, 0x68, 0xd5, 0xe7, - 0x1c, 0xae, 0x68, 0xc2, 0x7b, 0x30, 0x16, 0x19, 0x3b, 0x4f, 0xc4, 0xf5, 0xfa, 0x7b, 0xbd, 0x76, 0x37, 0x9e, 0xf2, - 0xc9, 0xd4, 0xb9, 0x77, 0xc5, 0x68, 0xb9, 0x09, 0x77, 0x4e, 0x50, 0xfc, 0xeb, 0xbf, 0x04, 0xc1, 0xbf, 0xfe, 0xcb, - 0x27, 0x9b, 0xc2, 0xf0, 0xc5, 0x05, 0x91, 0xd5, 0xb0, 0xbb, 0x4f, 0xd7, 0xf6, 0x99, 0xea, 0x38, 0xdf, 0xde, 0x66, - 0x63, 0x13, 0xa0, 0x7e, 0x63, 0x0b, 0x36, 0x0a, 0xf5, 0xe9, 0xf3, 0x7e, 0x0b, 0x60, 0xb0, 0xae, 0x4f, 0x42, 0x06, - 0x8d, 0x7e, 0x17, 0x68, 0x17, 0x38, 0xbc, 0xd7, 0x8e, 0xfc, 0x76, 0x0c, 0x7f, 0x6a, 0x0d, 0xbf, 0x13, 0x7c, 0xe3, - 0x9f, 0x18, 0x5d, 0x5c, 0x94, 0x09, 0x76, 0x6e, 0x57, 0xb8, 0xc0, 0xdf, 0xdf, 0x28, 0x31, 0x8a, 0x47, 0xd8, 0xc2, - 0x3d, 0x75, 0x3d, 0x90, 0x8e, 0x2e, 0x5e, 0xc3, 0x5b, 0x7b, 0x8e, 0x2f, 0x33, 0xeb, 0xe0, 0xbd, 0x43, 0x38, 0xc0, - 0x10, 0xf5, 0x55, 0xa9, 0x41, 0x37, 0x24, 0x03, 0x94, 0x82, 0xb9, 0x01, 0x60, 0x92, 0xd1, 0x85, 0xb1, 0x36, 0x4f, - 0xb5, 0x1b, 0x26, 0x5c, 0x27, 0x6d, 0xe3, 0x9e, 0xa9, 0x21, 0x9d, 0x78, 0xef, 0x15, 0xbe, 0x54, 0x63, 0x56, 0x59, - 0xf7, 0xca, 0xd5, 0x05, 0x76, 0xc4, 0x45, 0xa1, 0xc2, 0xf4, 0x7f, 0xdd, 0x15, 0x49, 0xfc, 0xfb, 0xa7, 0x23, 0x89, - 0xe2, 0x5e, 0x91, 0xc4, 0xbf, 0xff, 0xe1, 0x91, 0xc4, 0xbf, 0xba, 0x91, 0x44, 0xd8, 0xc4, 0x2f, 0xef, 0x15, 0xed, - 0xb3, 0x91, 0x18, 0x71, 0x9d, 0xd3, 0xb6, 0x51, 0xa3, 0x13, 0x31, 0x81, 0x50, 0xdf, 0xbf, 0x7f, 0xe4, 0x2e, 0x11, - 0x13, 0x37, 0x6e, 0x07, 0x6f, 0x6d, 0x85, 0x40, 0x5d, 0xd7, 0x46, 0xd8, 0x4c, 0xac, 0xac, 0x55, 0xde, 0x48, 0x69, - 0x3e, 0xb4, 0x6f, 0x50, 0x40, 0x61, 0xf9, 0x16, 0xa4, 0x16, 0xe9, 0xd8, 0x68, 0x5a, 0xa8, 0x02, 0x71, 0x65, 0xc7, - 0x4e, 0xc3, 0x5e, 0xb7, 0x70, 0x47, 0xe8, 0xda, 0xb7, 0xbc, 0xe8, 0xdb, 0xf7, 0x4b, 0xf4, 0xe3, 0x4d, 0xfb, 0xd9, - 0xa0, 0xdd, 0x3d, 0x6a, 0xcf, 0x50, 0x88, 0x40, 0x44, 0xaa, 0x82, 0x56, 0xf7, 0xe8, 0x08, 0x0a, 0xae, 0x9d, 0x82, - 0x0e, 0x14, 0x70, 0xa7, 0xe0, 0x11, 0x14, 0x8c, 0x9c, 0x82, 0xc7, 0x50, 0x10, 0x3b, 0x05, 0x4f, 0xa0, 0xe0, 0x0a, - 0x15, 0x03, 0x5e, 0x82, 0xfb, 0x04, 0x0f, 0x89, 0xb6, 0x5c, 0x6c, 0xd9, 0x13, 0xd2, 0x86, 0x10, 0x5e, 0x34, 0x51, - 0x99, 0x47, 0xe0, 0x10, 0x0c, 0x05, 0xb9, 0x9e, 0xb2, 0x34, 0x84, 0x20, 0xea, 0x73, 0x25, 0x63, 0x02, 0x29, 0xde, - 0xf3, 0x19, 0xb3, 0xdf, 0xcb, 0xb0, 0x78, 0xf0, 0x10, 0x1e, 0xb4, 0x86, 0x45, 0xb7, 0xdc, 0x39, 0x1d, 0xfb, 0x33, - 0x59, 0x28, 0x7a, 0x2f, 0xab, 0x3a, 0x3d, 0x5d, 0xb3, 0xdc, 0xf3, 0x1d, 0x31, 0x24, 0xc7, 0x17, 0x31, 0x4e, 0xc4, - 0x75, 0xf3, 0x06, 0xf5, 0xb6, 0xc7, 0x95, 0x00, 0xa2, 0x32, 0xae, 0xa4, 0xd6, 0x54, 0x3e, 0xbd, 0x8f, 0x26, 0xe5, - 0xef, 0xd7, 0x2c, 0xcf, 0xa3, 0x89, 0x69, 0xb9, 0x3b, 0x8e, 0xa4, 0x40, 0x74, 0x63, 0x48, 0x16, 0x08, 0x88, 0x05, - 0xc1, 0x66, 0x81, 0x2d, 0x6f, 0x42, 0x43, 0x80, 0x9d, 0x7a, 0x54, 0x49, 0x4d, 0x5f, 0x2f, 0x92, 0xd1, 0xa4, 0x2a, - 0x38, 0x9e, 0x67, 0x4c, 0x95, 0x6a, 0x0c, 0x17, 0xc7, 0x87, 0x50, 0xa0, 0xab, 0x77, 0x44, 0x8f, 0xac, 0xe3, 0x60, - 0x77, 0x0c, 0xc9, 0xb3, 0xd1, 0x23, 0x37, 0xdf, 0xa6, 0x4c, 0xb6, 0xd9, 0x8c, 0x59, 0x7c, 0xd6, 0x1e, 0xc1, 0x1f, - 0x13, 0x11, 0xf9, 0x6c, 0x3c, 0x1e, 0xdf, 0x19, 0x4d, 0xfa, 0x2c, 0x1e, 0xb3, 0x0e, 0x7b, 0xd4, 0x85, 0x5c, 0x8c, - 0xa6, 0x89, 0x41, 0xb4, 0x0b, 0x85, 0xbb, 0xe5, 0xfd, 0x1a, 0x43, 0xb8, 0x42, 0x4e, 0x97, 0xf7, 0x8f, 0x2c, 0x15, - 0xf3, 0x8c, 0x2d, 0x67, 0x51, 0x36, 0xe1, 0x69, 0xd8, 0x2a, 0x82, 0x2b, 0x13, 0x8a, 0xf9, 0xec, 0xe9, 0xd3, 0xa7, - 0x45, 0x10, 0xdb, 0xa7, 0x56, 0x1c, 0x17, 0xc1, 0x68, 0x59, 0x2e, 0xa3, 0xd5, 0x1a, 0x8f, 0x8b, 0x80, 0xdb, 0x82, - 0xa3, 0xce, 0x28, 0x3e, 0xea, 0x14, 0xc1, 0xb5, 0xd3, 0xa2, 0x08, 0x98, 0x79, 0xca, 0x58, 0x5c, 0x4b, 0xe8, 0x78, - 0xd2, 0x6a, 0x15, 0x81, 0x26, 0xb4, 0x25, 0x98, 0x63, 0xfa, 0x67, 0x18, 0x2d, 0xa4, 0x00, 0x96, 0xdc, 0x15, 0xd2, - 0x1f, 0x9c, 0x9b, 0x97, 0x65, 0xe8, 0x0f, 0x4b, 0x14, 0x78, 0x48, 0xbe, 0x74, 0x83, 0x26, 0x40, 0xcc, 0x2a, 0x58, - 0x22, 0x6c, 0x4c, 0xa5, 0x56, 0x0d, 0x94, 0xa5, 0xaa, 0xbf, 0xa4, 0xa2, 0x8a, 0xa5, 0x00, 0xff, 0x81, 0x96, 0xfa, - 0xad, 0x6e, 0x92, 0xed, 0xe0, 0xfa, 0x8c, 0x7d, 0x92, 0xeb, 0xdf, 0xde, 0x87, 0xe9, 0x33, 0xf6, 0x47, 0x33, 0x7d, - 0xf3, 0xea, 0x53, 0xcd, 0xf4, 0x35, 0x5b, 0x9b, 0x49, 0x8a, 0x46, 0x53, 0x36, 0xfa, 0x78, 0x29, 0x6e, 0x9a, 0x70, - 0x24, 0x32, 0xa4, 0xf8, 0xe9, 0xfe, 0x6f, 0x4d, 0xfe, 0xb0, 0x83, 0x39, 0xdf, 0xa5, 0x50, 0x62, 0xf3, 0x6d, 0x4a, - 0xd1, 0x5b, 0x6b, 0xd3, 0xe9, 0x92, 0xf1, 0x98, 0xa2, 0xb7, 0xe3, 0x31, 0xb2, 0x57, 0xfe, 0x22, 0xc9, 0x54, 0xab, - 0x37, 0xb5, 0x12, 0xd5, 0xea, 0x8b, 0x2f, 0xdc, 0x32, 0xb7, 0xc0, 0x84, 0x5c, 0xdc, 0xf0, 0x8a, 0xa9, 0x89, 0x79, - 0x0e, 0x47, 0x0d, 0x3e, 0x97, 0x51, 0x7f, 0xe7, 0x60, 0x56, 0x7b, 0x3d, 0x74, 0x09, 0xf0, 0x96, 0x77, 0x5a, 0xaf, - 0xdf, 0x77, 0x9f, 0x30, 0x9b, 0x7e, 0xf7, 0xec, 0xf6, 0xcb, 0xd8, 0x9f, 0x49, 0x5c, 0xf0, 0xfc, 0x6d, 0xba, 0x76, - 0x97, 0x45, 0xc3, 0x48, 0xa9, 0xbb, 0xac, 0x42, 0x8a, 0xc9, 0x24, 0x81, 0x0f, 0x96, 0x2c, 0x6b, 0xef, 0x41, 0xd5, - 0xdd, 0xfb, 0xb5, 0xf5, 0x86, 0x6e, 0x47, 0xf3, 0xd6, 0x50, 0xf5, 0xfd, 0x24, 0x9d, 0x03, 0x7d, 0x65, 0x3e, 0xa4, - 0xa3, 0xcc, 0xc1, 0xa5, 0xe1, 0xff, 0x4b, 0x9d, 0x39, 0x2b, 0x21, 0x6b, 0x44, 0x0f, 0x1c, 0x17, 0x85, 0xb9, 0x73, - 0x10, 0xf3, 0x7c, 0x0e, 0xef, 0xe7, 0xd4, 0x3d, 0xd9, 0xa7, 0x58, 0x78, 0x7e, 0xed, 0xc4, 0x35, 0x6a, 0xdb, 0x55, - 0xd8, 0xc0, 0x86, 0x76, 0x14, 0xcf, 0x64, 0x81, 0x8c, 0xbf, 0xd9, 0x22, 0x11, 0x79, 0x1a, 0x9f, 0x3a, 0xe2, 0xe2, - 0xac, 0x10, 0x9c, 0xbe, 0xe5, 0x86, 0xd8, 0x2a, 0x5b, 0x50, 0xb8, 0x71, 0x3b, 0x55, 0xa3, 0xb1, 0xa5, 0xa2, 0x04, - 0xf9, 0x3c, 0x4a, 0x35, 0x1b, 0xa5, 0x48, 0xf3, 0x83, 0xfd, 0x65, 0xb5, 0xf3, 0x05, 0xb2, 0x60, 0x6b, 0xe2, 0xed, - 0x1d, 0x1f, 0x42, 0x87, 0x9e, 0x57, 0x03, 0x3d, 0xdd, 0x08, 0x2e, 0x7c, 0x22, 0xcc, 0x7f, 0x11, 0xe4, 0xd7, 0x24, - 0xc8, 0xaf, 0xbd, 0x3f, 0x2f, 0x9b, 0xd7, 0xec, 0xf2, 0x23, 0x97, 0x4d, 0x19, 0xcd, 0x9b, 0xa0, 0xf0, 0x2b, 0xa7, - 0xa0, 0x61, 0xcf, 0x2a, 0x59, 0x4d, 0xdf, 0xd8, 0xef, 0x2e, 0x72, 0xc8, 0x06, 0x50, 0x6a, 0x6b, 0x98, 0x8a, 0x94, - 0x75, 0xeb, 0x49, 0x89, 0x6e, 0x70, 0xd9, 0x62, 0x6b, 0xb8, 0x14, 0x90, 0x3d, 0x20, 0x6f, 0xc3, 0x96, 0x61, 0xeb, - 0x2d, 0x1b, 0x39, 0x6e, 0x6d, 0x6d, 0x1f, 0x1a, 0xe4, 0x36, 0x94, 0xf4, 0xca, 0x36, 0x23, 0xe8, 0xbb, 0x22, 0xe0, - 0x9f, 0x4a, 0xd1, 0x03, 0x57, 0xa2, 0xfd, 0xeb, 0xe4, 0x36, 0xae, 0x17, 0xab, 0x14, 0xbd, 0xfb, 0x40, 0x16, 0x46, - 0x63, 0xc9, 0x32, 0x72, 0x9f, 0x96, 0x97, 0xea, 0x36, 0xcd, 0x12, 0xc4, 0x4c, 0xd8, 0x7e, 0x3a, 0xbf, 0xb9, 0xff, - 0xf0, 0x77, 0x2f, 0xbf, 0x30, 0x38, 0xb2, 0x6f, 0x97, 0x41, 0xa8, 0x0b, 0x07, 0x21, 0x89, 0x6e, 0x43, 0x9e, 0x2a, - 0x99, 0x77, 0x09, 0xfe, 0xc0, 0xee, 0x5c, 0x98, 0x5c, 0xd3, 0x8c, 0x25, 0xea, 0x53, 0x72, 0x66, 0x2b, 0x8e, 0x1e, - 0xcf, 0x6f, 0xec, 0x6e, 0xb4, 0xd7, 0x72, 0x48, 0xff, 0xd0, 0x54, 0xd1, 0xdd, 0xb9, 0xa9, 0xf5, 0x74, 0xc7, 0x47, - 0xf3, 0x9b, 0xae, 0x16, 0xb4, 0xcd, 0x4c, 0x43, 0xd5, 0x9a, 0xdf, 0xb8, 0xc9, 0xb2, 0xd5, 0x40, 0x5e, 0x70, 0x94, - 0x7b, 0x2c, 0xca, 0x59, 0x17, 0xde, 0x9f, 0xcd, 0x47, 0x51, 0x62, 0x84, 0xf9, 0x8c, 0xc7, 0x71, 0xc2, 0xba, 0x56, - 0x5e, 0x7b, 0xed, 0xc7, 0x90, 0x6b, 0xea, 0x6e, 0x59, 0x7d, 0x57, 0x1c, 0xe4, 0x95, 0x78, 0x8a, 0x2e, 0x73, 0x91, - 0xc0, 0xc7, 0x2b, 0xb6, 0xa2, 0xd3, 0x24, 0x61, 0xb6, 0x2a, 0xe4, 0xa9, 0xdf, 0xf5, 0xb5, 0x3c, 0x6a, 0xfd, 0xa9, - 0xab, 0x36, 0xbc, 0xd5, 0x95, 0x62, 0x1e, 0x36, 0x8f, 0xea, 0x0b, 0x81, 0xaa, 0x72, 0x09, 0x64, 0xcb, 0xb2, 0x08, - 0x48, 0x2b, 0xcd, 0xa7, 0xbd, 0xa0, 0x6d, 0xca, 0xd4, 0x00, 0xf0, 0xa2, 0xe7, 0xb2, 0xa8, 0xa8, 0x2f, 0xe6, 0xdf, - 0xe7, 0xb4, 0x7c, 0xbe, 0xfd, 0xb4, 0x7c, 0x6e, 0x4f, 0xcb, 0xdd, 0x14, 0xfb, 0xd9, 0xb8, 0x0d, 0x7f, 0xba, 0xd5, - 0x82, 0xc2, 0x96, 0x77, 0x34, 0xbf, 0xf1, 0x40, 0x4f, 0x6b, 0x76, 0xe6, 0x37, 0x3a, 0x55, 0x18, 0x62, 0x16, 0x2d, - 0x48, 0x9e, 0x25, 0x2d, 0x0f, 0x0a, 0xe1, 0x6f, 0xab, 0x56, 0xd5, 0x7e, 0x08, 0x75, 0xd0, 0xeb, 0xd1, 0x66, 0x5d, - 0xe7, 0xee, 0x43, 0x1b, 0xa6, 0x42, 0xfa, 0xa1, 0xe5, 0xc6, 0x38, 0x90, 0xd1, 0xe5, 0x25, 0x8b, 0xc3, 0xb1, 0x18, - 0x2d, 0xf2, 0x7f, 0x36, 0xf0, 0x1b, 0x24, 0xde, 0x79, 0xa4, 0xd7, 0xc6, 0xb1, 0x5d, 0x75, 0xe2, 0xb2, 0x1d, 0x61, - 0x59, 0xee, 0x53, 0x98, 0x8f, 0xa2, 0x84, 0xf9, 0x9d, 0xe0, 0xe1, 0x96, 0x43, 0xf0, 0x1f, 0xb2, 0x37, 0x5b, 0x17, - 0xf3, 0x7b, 0x91, 0x71, 0x27, 0x12, 0x7e, 0x15, 0x0e, 0xdc, 0x3d, 0x6c, 0x3d, 0xdd, 0x0e, 0xee, 0xc0, 0xce, 0x34, - 0xb4, 0x42, 0xc1, 0xc8, 0x9d, 0x98, 0x8d, 0xa3, 0x45, 0x22, 0xef, 0x1e, 0x75, 0x17, 0x65, 0x6c, 0x8c, 0x7a, 0x07, - 0x43, 0xaf, 0xda, 0xde, 0x93, 0x4b, 0x7f, 0xf6, 0xf9, 0x43, 0xf8, 0xa3, 0xf3, 0x9e, 0x6e, 0x2b, 0x5d, 0x5d, 0xdb, - 0xaa, 0xa0, 0xab, 0xef, 0xd7, 0x94, 0x71, 0x2d, 0xc2, 0x95, 0x3e, 0x7e, 0xdf, 0xd6, 0xa0, 0x55, 0xde, 0xab, 0xb9, - 0xd1, 0xb2, 0x7e, 0x55, 0xeb, 0x5f, 0x37, 0xf8, 0x3d, 0xdb, 0x8e, 0xb4, 0xe6, 0x5a, 0x6f, 0x6b, 0xbe, 0xa5, 0xb7, - 0xd1, 0xd8, 0x62, 0x5c, 0xb5, 0xdf, 0xa7, 0xb7, 0xa5, 0x89, 0xa2, 0xa3, 0x90, 0x60, 0xa5, 0xec, 0x6b, 0x2b, 0x85, - 0x33, 0xfa, 0x00, 0xde, 0x64, 0xeb, 0xdd, 0xcc, 0x92, 0x34, 0xa7, 0x68, 0x2a, 0xe5, 0x3c, 0xd4, 0x1f, 0x5f, 0xbd, - 0x3e, 0x0a, 0x44, 0x36, 0x39, 0xec, 0xb4, 0x5a, 0x2d, 0x78, 0x03, 0x29, 0xf2, 0xae, 0x38, 0xbb, 0x7e, 0x26, 0x6e, - 0x28, 0x7a, 0xe2, 0x3d, 0xf5, 0x9e, 0x1c, 0x79, 0x8f, 0x1e, 0x23, 0x4f, 0xb1, 0x73, 0x8a, 0x9e, 0x1c, 0x21, 0x4f, - 0xb3, 0x73, 0x8a, 0x1e, 0x3d, 0x46, 0xbd, 0xe3, 0x89, 0x55, 0xc9, 0xe0, 0x0a, 0xa3, 0xd6, 0x77, 0x72, 0x99, 0x89, - 0x8f, 0xac, 0x7e, 0x70, 0x75, 0x99, 0xc9, 0x8c, 0xeb, 0xd8, 0x47, 0x38, 0xbd, 0xa3, 0x68, 0x1e, 0x2a, 0xa2, 0x70, - 0x0b, 0xc1, 0x2d, 0xa3, 0x4b, 0xd5, 0x14, 0xa0, 0x66, 0x5e, 0xa2, 0xde, 0x31, 0x64, 0xb1, 0x7b, 0x31, 0x45, 0xaf, - 0x3b, 0x4f, 0xbc, 0xf6, 0xe3, 0xab, 0xe6, 0xc3, 0x51, 0xab, 0xd9, 0xf6, 0xda, 0xcd, 0x4e, 0xf0, 0xc4, 0xeb, 0xe8, - 0x7f, 0xbd, 0x96, 0x77, 0xe4, 0xb5, 0x83, 0x27, 0xde, 0x91, 0xd7, 0x09, 0x9e, 0x5c, 0x3d, 0xd4, 0xc9, 0x0c, 0x11, - 0x3a, 0xec, 0x1d, 0xc3, 0x87, 0x34, 0x6f, 0x28, 0xfa, 0x1c, 0xe9, 0xcf, 0xd5, 0xa2, 0xcf, 0xdc, 0xd2, 0xf6, 0xd3, - 0xad, 0xc5, 0x9d, 0x27, 0x5b, 0x8b, 0x8f, 0x1e, 0x6f, 0x2d, 0x7e, 0xf8, 0xa8, 0x5e, 0x7c, 0x38, 0xd1, 0x55, 0xe5, - 0x29, 0xa7, 0x68, 0x16, 0xc9, 0x8c, 0xdf, 0xf8, 0x6d, 0xaf, 0xe5, 0xb5, 0xbc, 0x26, 0xfc, 0xf7, 0xa4, 0x83, 0xcb, - 0x5e, 0x97, 0xd0, 0xab, 0x5c, 0xe5, 0x93, 0xa7, 0x5e, 0xfb, 0xf1, 0xcb, 0xce, 0xe3, 0x11, 0xb4, 0x53, 0x0b, 0x6d, - 0x7b, 0xed, 0xab, 0xa3, 0xa7, 0xa3, 0x96, 0x07, 0x1d, 0xdb, 0xf0, 0x67, 0xfa, 0xa8, 0x33, 0xd2, 0x0f, 0x2d, 0xa8, - 0xff, 0xb6, 0xfd, 0x24, 0x6f, 0x35, 0xdb, 0xf0, 0xe7, 0x97, 0x52, 0x23, 0x06, 0x7d, 0xdc, 0x1d, 0xf7, 0x61, 0xcb, - 0x3b, 0x7a, 0x3a, 0xed, 0x04, 0x9f, 0x5f, 0x3d, 0x09, 0x9e, 0x4e, 0xdb, 0x4f, 0xbe, 0xd5, 0x4f, 0x49, 0xb3, 0x13, - 0x7c, 0x0e, 0x7f, 0xbf, 0x3d, 0x6a, 0x4d, 0x9b, 0xed, 0xe0, 0xe9, 0xd5, 0x51, 0x70, 0x94, 0x34, 0x1f, 0x07, 0x4f, - 0xe1, 0x6f, 0x35, 0xdc, 0x54, 0xcc, 0x18, 0xf2, 0x60, 0xbf, 0xd7, 0xcc, 0x2d, 0x77, 0x8e, 0xce, 0x43, 0xef, 0xd1, - 0xc3, 0x97, 0x4f, 0xaf, 0x9a, 0x0f, 0xa7, 0xed, 0xce, 0x55, 0x73, 0xe7, 0xcf, 0x6f, 0x01, 0xf1, 0x66, 0xe0, 0x88, - 0xc1, 0x75, 0x22, 0x8b, 0x38, 0xf5, 0x36, 0xdc, 0x07, 0x24, 0xdf, 0x65, 0x5e, 0x67, 0x9f, 0x36, 0xaf, 0x53, 0x76, - 0x1f, 0xfb, 0x3a, 0xfb, 0xc3, 0xed, 0xeb, 0x9c, 0xad, 0x39, 0x55, 0x6f, 0xe5, 0x86, 0x19, 0xbd, 0x6e, 0x7b, 0xbd, - 0x93, 0xfe, 0x80, 0xc3, 0x57, 0x97, 0x8a, 0xee, 0x2d, 0xbc, 0x70, 0xdb, 0xf5, 0x36, 0x08, 0x38, 0xc8, 0xb7, 0x52, - 0x9f, 0x64, 0xb1, 0x0b, 0x21, 0xc9, 0xa7, 0x11, 0xf2, 0xed, 0x7d, 0xf0, 0x91, 0xfc, 0xe1, 0xf8, 0x10, 0x2e, 0x3e, - 0x6a, 0x7e, 0x5e, 0x65, 0xcf, 0x2a, 0x7b, 0xf4, 0x4c, 0x3d, 0xfb, 0x70, 0xe3, 0xa4, 0x81, 0x0e, 0x19, 0x14, 0xe5, - 0x48, 0xc7, 0x15, 0x5e, 0xfe, 0x1a, 0x97, 0xb4, 0xbe, 0x5e, 0x46, 0x91, 0x31, 0xfe, 0xe7, 0xf0, 0x65, 0x05, 0xfb, - 0x70, 0xa5, 0x2f, 0x3c, 0x53, 0xd4, 0x09, 0x5a, 0x41, 0xab, 0x74, 0x1c, 0xc0, 0x95, 0x42, 0xba, 0x14, 0x32, 0x82, - 0x8f, 0x7b, 0x26, 0x62, 0xa2, 0x3e, 0x03, 0x0a, 0x2f, 0x5f, 0x57, 0x1f, 0x64, 0xd5, 0xef, 0xbd, 0x0f, 0x11, 0x32, - 0x2f, 0x22, 0x80, 0x2b, 0x6b, 0xdf, 0xc0, 0xb5, 0x3e, 0xeb, 0xb1, 0x9e, 0x81, 0x4d, 0xfd, 0x9a, 0xc5, 0x3c, 0xf2, - 0x91, 0x3f, 0xcf, 0xd8, 0x98, 0x65, 0x79, 0xb3, 0x76, 0xd7, 0x4d, 0x5d, 0x73, 0xc3, 0xc8, 0x7e, 0x46, 0x32, 0x83, - 0x97, 0x09, 0xd3, 0x81, 0xf1, 0x6a, 0x21, 0xa3, 0xe6, 0xa3, 0x82, 0xd8, 0x92, 0x0c, 0x38, 0x7a, 0xa5, 0x1a, 0x20, - 0xad, 0x1b, 0xb4, 0x83, 0xce, 0x23, 0xac, 0x79, 0x09, 0xbc, 0xa4, 0xf5, 0x7b, 0xbf, 0x79, 0xd4, 0xfa, 0x13, 0x76, - 0xba, 0x95, 0x03, 0x0d, 0x8d, 0x53, 0x27, 0xab, 0x3e, 0xbf, 0x5b, 0xbf, 0x88, 0x88, 0x34, 0x45, 0x7c, 0xa6, 0xd7, - 0x0e, 0xaf, 0x7b, 0x35, 0xf1, 0x43, 0x7d, 0x9d, 0x7e, 0xcc, 0x27, 0xbe, 0xfb, 0x71, 0x55, 0xfd, 0x12, 0x58, 0xf5, - 0x4d, 0x66, 0x5c, 0x54, 0x4d, 0x32, 0xbc, 0x54, 0xbe, 0x78, 0x9e, 0x7a, 0xd9, 0x6a, 0xe5, 0x67, 0xe0, 0x88, 0xa5, - 0x0e, 0x4e, 0xe1, 0x19, 0xd7, 0x90, 0x9c, 0x91, 0x12, 0x20, 0x85, 0x60, 0x9a, 0xe9, 0xff, 0xab, 0x62, 0xfb, 0xc3, - 0xb8, 0x57, 0x82, 0x24, 0x4a, 0x27, 0x40, 0x85, 0x51, 0x3a, 0xd9, 0x70, 0xde, 0xe8, 0x70, 0xc2, 0x5a, 0x69, 0x35, - 0x54, 0xe5, 0xa4, 0xc9, 0x9f, 0xdd, 0xbe, 0x37, 0x6f, 0x8b, 0x42, 0xe0, 0x03, 0x55, 0xbe, 0xef, 0xea, 0xcd, 0xb6, - 0x0d, 0xfa, 0x40, 0x7f, 0xae, 0x5c, 0x65, 0xc3, 0x81, 0xf4, 0x83, 0x2b, 0x86, 0x9e, 0xb1, 0x79, 0x28, 0xd2, 0xb2, - 0x2f, 0x66, 0x57, 0x7c, 0x64, 0x44, 0x18, 0xf1, 0xcc, 0x35, 0xeb, 0xa6, 0xda, 0x1a, 0xda, 0x26, 0xda, 0xea, 0x1f, - 0x45, 0x2a, 0xdf, 0x99, 0xa6, 0x02, 0xf5, 0x1e, 0x94, 0xdf, 0x8a, 0xdc, 0xb5, 0x09, 0xf0, 0x0d, 0xf5, 0x41, 0xc6, - 0x92, 0x7f, 0xa6, 0x0f, 0xe0, 0x2b, 0xea, 0x0f, 0x86, 0xf0, 0x01, 0xef, 0x40, 0x89, 0x82, 0x07, 0xd5, 0xc7, 0xd4, - 0x81, 0x0f, 0x36, 0x6e, 0x66, 0x09, 0xb9, 0xaf, 0xf8, 0x36, 0xa2, 0xba, 0xf3, 0xa8, 0x12, 0xd5, 0x9d, 0x47, 0xae, - 0xf4, 0x6c, 0x7b, 0xed, 0x4e, 0xf0, 0xc8, 0x11, 0x00, 0x57, 0x4d, 0xf8, 0xbf, 0x26, 0x02, 0x1e, 0x06, 0x8f, 0x4a, - 0x19, 0xf0, 0xaa, 0xdd, 0x09, 0x8e, 0xb4, 0xb8, 0xe9, 0x04, 0x8f, 0x7e, 0x50, 0x0c, 0x5a, 0x33, 0xe7, 0xfa, 0x81, - 0xd8, 0x12, 0xaa, 0xd1, 0x19, 0x7d, 0x88, 0xf8, 0xe5, 0x17, 0xe9, 0xcc, 0xf9, 0x34, 0x2e, 0xa1, 0xe7, 0x51, 0x06, - 0x9f, 0x05, 0xa9, 0x9f, 0xdd, 0x5a, 0x1d, 0xa9, 0xf1, 0x8b, 0x2d, 0x53, 0xc0, 0x09, 0x47, 0xc4, 0xbd, 0xa7, 0x0c, - 0x97, 0x7c, 0xd5, 0x4b, 0x94, 0xed, 0xbb, 0xe4, 0x76, 0x93, 0xb6, 0x6e, 0x68, 0xdf, 0x57, 0xa7, 0x98, 0x05, 0x57, - 0x2f, 0xac, 0x57, 0x93, 0x7c, 0x19, 0x17, 0xeb, 0xf3, 0x43, 0x62, 0x61, 0x26, 0x9c, 0xab, 0xda, 0xac, 0x4a, 0x87, - 0x8f, 0x39, 0x5c, 0xae, 0x2f, 0x0a, 0x0b, 0x7a, 0xcd, 0x19, 0x58, 0x61, 0x49, 0xf1, 0x0b, 0x96, 0xf7, 0x11, 0x14, - 0xa1, 0x10, 0x29, 0x47, 0x12, 0x2a, 0x3f, 0x8d, 0x52, 0x12, 0x76, 0x55, 0x40, 0xd4, 0x95, 0x16, 0x38, 0xb5, 0x80, - 0x1f, 0x84, 0x0f, 0x0e, 0x76, 0x9e, 0x17, 0xa5, 0x8d, 0xc1, 0x5a, 0xab, 0x4f, 0x2a, 0xb8, 0xac, 0x08, 0xb9, 0x88, - 0x2e, 0xc7, 0x55, 0x28, 0xc4, 0x06, 0x4f, 0x97, 0x2c, 0x92, 0x41, 0x94, 0xea, 0x14, 0x05, 0x87, 0x61, 0x91, 0x36, - 0x3b, 0xc2, 0x85, 0x90, 0x91, 0xf3, 0xcd, 0x54, 0x73, 0xce, 0x85, 0x8c, 0xec, 0xc5, 0xc3, 0x54, 0xd6, 0x32, 0xf3, - 0xa7, 0x9d, 0xde, 0xdb, 0xf7, 0x27, 0x9e, 0x3e, 0x9e, 0xc7, 0x87, 0xd3, 0x4e, 0xef, 0x58, 0x59, 0xe6, 0xfa, 0xda, - 0x12, 0xd5, 0xd7, 0x96, 0x3c, 0x73, 0x85, 0x0d, 0xe2, 0x35, 0xc5, 0xa1, 0x5e, 0x36, 0xf2, 0x58, 0x3a, 0xd2, 0x3e, - 0xc5, 0xd9, 0x22, 0x91, 0x1c, 0x5e, 0x08, 0x7c, 0x08, 0x5d, 0x9b, 0xb0, 0x61, 0x65, 0x96, 0xab, 0xd5, 0x70, 0x64, - 0x6a, 0x3d, 0x90, 0x63, 0x9e, 0x30, 0x9b, 0xd7, 0x6a, 0x86, 0x2a, 0xf3, 0xb0, 0x37, 0x5b, 0xe7, 0x8b, 0xcb, 0x19, - 0x97, 0xc8, 0x66, 0x8b, 0x7f, 0x30, 0x1d, 0x8e, 0xd5, 0x54, 0xbd, 0x8b, 0xc2, 0xb8, 0x48, 0xed, 0xc7, 0x4f, 0xd6, - 0x3e, 0x37, 0xaf, 0x57, 0x6f, 0x24, 0x04, 0xdc, 0x3f, 0x9a, 0x1e, 0xf5, 0x4a, 0xa7, 0xa4, 0x5b, 0x57, 0x1c, 0x1f, - 0x4e, 0x8f, 0x7a, 0x17, 0xe1, 0xdc, 0x8c, 0xf7, 0x4a, 0x6c, 0x7c, 0xba, 0xbe, 0xe4, 0x98, 0x7d, 0x95, 0x68, 0xaf, - 0x6f, 0x74, 0x1a, 0x80, 0x47, 0x22, 0x41, 0xbd, 0x63, 0xa3, 0x0c, 0x78, 0x2a, 0xe8, 0x8a, 0x1e, 0xb5, 0x6c, 0xee, - 0x7e, 0x22, 0x94, 0xb6, 0xa4, 0xbb, 0x38, 0x93, 0xd4, 0xfc, 0xba, 0xd3, 0x76, 0xef, 0x38, 0x32, 0x6a, 0x26, 0x30, - 0x8f, 0x3c, 0x3c, 0x84, 0xce, 0xa0, 0xcb, 0x05, 0x5c, 0x1c, 0x5e, 0xb3, 0xcb, 0x66, 0x34, 0xe7, 0x95, 0x13, 0x15, - 0x94, 0x8e, 0x72, 0x4a, 0x51, 0xcd, 0x04, 0x3f, 0xa3, 0xb5, 0x45, 0x2a, 0x16, 0x5e, 0x18, 0x0f, 0xad, 0xd2, 0xd5, - 0x59, 0x24, 0x91, 0xa7, 0x39, 0xbc, 0xf5, 0xe4, 0x1a, 0xd9, 0x5b, 0xa0, 0xde, 0xbf, 0xfd, 0x8f, 0xff, 0x65, 0x9c, - 0xb3, 0xc7, 0x87, 0xd3, 0xb6, 0x1d, 0x6b, 0x0d, 0xd1, 0xc5, 0x31, 0x5c, 0x77, 0xab, 0xa2, 0x89, 0xec, 0xa6, 0x39, - 0xc9, 0x78, 0xdc, 0x9c, 0x46, 0xc9, 0x18, 0xf5, 0x76, 0x23, 0xc8, 0xbd, 0xe7, 0x62, 0xa0, 0xae, 0x17, 0x01, 0x09, - 0xfe, 0xa6, 0x9b, 0x1a, 0x36, 0xe1, 0x5f, 0x9d, 0x56, 0xf7, 0xde, 0x46, 0x75, 0xa0, 0x6a, 0x77, 0x37, 0x32, 0xf3, - 0x8d, 0x24, 0xc3, 0xd4, 0xb2, 0xda, 0x95, 0x8d, 0x02, 0x79, 0x65, 0x34, 0xe4, 0xff, 0xfe, 0xcf, 0xff, 0xf2, 0xdf, - 0xec, 0x23, 0x04, 0x39, 0xfe, 0xed, 0xbf, 0xff, 0xe7, 0xff, 0xf3, 0xbf, 0xff, 0x2b, 0xa4, 0xf9, 0x9b, 0x40, 0x88, - 0xe2, 0x13, 0x5e, 0x15, 0x05, 0xd1, 0x0c, 0xc3, 0x83, 0x4c, 0xb8, 0x19, 0xcf, 0x25, 0x1f, 0xd5, 0x2f, 0x71, 0x9c, - 0xa9, 0x09, 0xd5, 0x61, 0x33, 0xd0, 0xa9, 0x43, 0x5b, 0x54, 0x34, 0x52, 0x43, 0xb9, 0xa2, 0xc5, 0xe2, 0xf8, 0x10, - 0xf0, 0x7d, 0xbf, 0x7b, 0x6f, 0x41, 0xb9, 0x1d, 0x4b, 0xeb, 0xfa, 0x83, 0x92, 0xa2, 0x2a, 0xf7, 0xc0, 0x29, 0xbf, - 0x84, 0xc7, 0xb0, 0xe3, 0x14, 0xab, 0xdd, 0xab, 0xf5, 0xe9, 0xfe, 0xb4, 0xc8, 0x25, 0x1f, 0x03, 0xca, 0xb5, 0x83, - 0x51, 0xc5, 0x3f, 0x9b, 0xa0, 0xfe, 0x25, 0xb7, 0x85, 0x1a, 0x45, 0xdb, 0x8c, 0x0f, 0x9f, 0xfe, 0xa9, 0xf8, 0xcb, - 0x0c, 0x94, 0x2c, 0xcf, 0x9f, 0x45, 0x37, 0xc6, 0x92, 0x7c, 0xdc, 0x6a, 0xcd, 0x6f, 0xf0, 0xb2, 0x9a, 0x81, 0xec, - 0x9a, 0x4c, 0x39, 0x25, 0xdd, 0x01, 0x55, 0xe0, 0xb4, 0xf4, 0x7f, 0xb6, 0x3c, 0x70, 0xa2, 0x7a, 0xad, 0xa2, 0xf8, - 0xf3, 0x52, 0xb9, 0xe0, 0xf8, 0x2f, 0x10, 0xe0, 0x34, 0xde, 0xca, 0x4b, 0xe1, 0x2e, 0x6e, 0xe9, 0xf4, 0xea, 0xe8, - 0x5e, 0xd3, 0xf6, 0xe6, 0x75, 0x2e, 0x37, 0x40, 0xeb, 0x86, 0x56, 0x1f, 0x42, 0xb0, 0x74, 0xda, 0x26, 0xd3, 0xce, - 0xb2, 0x1c, 0x5e, 0x4a, 0x31, 0x73, 0x23, 0xb2, 0x2c, 0x62, 0x23, 0x36, 0xb6, 0x5e, 0x5e, 0x53, 0xaf, 0xa3, 0xad, - 0xc5, 0xf4, 0x68, 0xcb, 0x5c, 0x06, 0x24, 0x15, 0x89, 0xf5, 0x5a, 0xc5, 0x67, 0x70, 0x02, 0x97, 0xe3, 0x44, 0x44, - 0x32, 0x54, 0x04, 0xdb, 0x75, 0xe3, 0xba, 0x11, 0xb0, 0x19, 0xb1, 0x74, 0xe0, 0xe9, 0xea, 0xa6, 0xe0, 0x6f, 0xad, - 0x5f, 0xba, 0x2b, 0x02, 0xd5, 0xdd, 0x1d, 0x4a, 0xbb, 0x6b, 0xbe, 0x35, 0xe1, 0xd2, 0x97, 0x35, 0x3f, 0x87, 0x91, - 0x31, 0x1d, 0xbc, 0xbd, 0x5e, 0x8b, 0x6a, 0x5d, 0xfb, 0x95, 0xf4, 0x91, 0x02, 0x13, 0xad, 0xb7, 0x52, 0x85, 0xd0, - 0xea, 0x25, 0xfd, 0xb6, 0xb4, 0x82, 0xa2, 0xf9, 0x5c, 0x35, 0xc4, 0xdd, 0xe3, 0x43, 0xad, 0xbc, 0x02, 0xf7, 0x50, - 0xb9, 0x00, 0x3a, 0xf4, 0x6e, 0x1a, 0x99, 0xa3, 0xa0, 0x7f, 0x99, 0xa0, 0x3c, 0x7c, 0x3c, 0xab, 0xf7, 0xff, 0x00, - 0x08, 0x50, 0x84, 0x3d, 0xcd, 0x86, 0x00, 0x00}; + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xcd, 0x7d, 0xdb, 0x72, 0xdb, 0xc6, 0xb6, 0xe0, 0xf3, + 0xe4, 0x2b, 0x20, 0x44, 0x5b, 0x41, 0x6f, 0x36, 0x21, 0x92, 0xba, 0x58, 0x06, 0xd5, 0xe4, 0x96, 0x65, 0x67, 0x3b, + 0x3b, 0xbe, 0xc5, 0xb2, 0x93, 0x9d, 0x30, 0xdc, 0x12, 0x44, 0x34, 0xc9, 0xb6, 0x41, 0x34, 0x03, 0x34, 0x29, 0x29, + 0x24, 0x4e, 0xcd, 0x07, 0x4c, 0xd5, 0x54, 0xcd, 0xd3, 0xbc, 0x4c, 0xcd, 0x79, 0x98, 0x8f, 0x98, 0xe7, 0xf3, 0x29, + 0xe7, 0x07, 0x66, 0x3e, 0x61, 0x6a, 0xf5, 0x05, 0x68, 0xf0, 0x22, 0xcb, 0x49, 0xce, 0x39, 0x53, 0xa9, 0x58, 0x44, + 0x5f, 0x57, 0xaf, 0x5e, 0xbd, 0xee, 0x0d, 0x9c, 0xee, 0x44, 0x7c, 0x20, 0xee, 0xa6, 0xd4, 0x19, 0x8b, 0x49, 0xdc, + 0x39, 0xd5, 0xff, 0xd2, 0x30, 0xea, 0x9c, 0xc6, 0x2c, 0xf9, 0xe8, 0xa4, 0x34, 0x26, 0x6c, 0xc0, 0x13, 0x67, 0x9c, + 0xd2, 0x21, 0x89, 0x42, 0x11, 0x06, 0x6c, 0x12, 0x8e, 0xa8, 0xb3, 0xdf, 0x39, 0x9d, 0x50, 0x11, 0x3a, 0x83, 0x71, + 0x98, 0x66, 0x54, 0x90, 0xf7, 0xef, 0xbe, 0xae, 0x9f, 0x74, 0x4e, 0xb3, 0x41, 0xca, 0xa6, 0xc2, 0x81, 0x21, 0xc9, + 0x84, 0x47, 0xb3, 0x98, 0x76, 0xf6, 0xf7, 0x6f, 0x6e, 0x6e, 0xfc, 0x0f, 0xd9, 0x17, 0x03, 0x9e, 0x64, 0xc2, 0x79, + 0x41, 0x6e, 0x58, 0x12, 0xf1, 0x1b, 0x4c, 0x05, 0x79, 0xe1, 0x5f, 0x8c, 0xc3, 0x88, 0xdf, 0xbc, 0xe5, 0x5c, 0xec, + 0xed, 0x79, 0xea, 0xf1, 0xee, 0xfc, 0xe2, 0x82, 0x10, 0x32, 0xe7, 0x2c, 0x72, 0x1a, 0xcb, 0x65, 0x59, 0xe8, 0x27, + 0xa1, 0x60, 0x73, 0xaa, 0xba, 0xa0, 0xbd, 0x3d, 0x37, 0x8c, 0xf8, 0x54, 0xd0, 0xe8, 0x42, 0xdc, 0xc5, 0xf4, 0x62, + 0x4c, 0xa9, 0xc8, 0x5c, 0x96, 0x38, 0x4f, 0xf9, 0x60, 0x36, 0xa1, 0x89, 0xf0, 0xa7, 0x29, 0x17, 0x1c, 0x20, 0xd9, + 0xdb, 0x73, 0x53, 0x3a, 0x8d, 0xc3, 0x01, 0x85, 0xfa, 0xf3, 0x8b, 0x8b, 0xb2, 0x47, 0xd9, 0x08, 0x33, 0x41, 0x2e, + 0xee, 0x26, 0xd7, 0x3c, 0xf6, 0x10, 0x8e, 0x05, 0x49, 0xe8, 0x8d, 0xf3, 0x03, 0x0d, 0x3f, 0xbe, 0x0c, 0xa7, 0xed, + 0x41, 0x1c, 0x66, 0x99, 0x73, 0x2d, 0x16, 0x72, 0x09, 0xe9, 0x6c, 0x20, 0x78, 0xea, 0x09, 0x4c, 0x31, 0x43, 0x0b, + 0x36, 0xf4, 0xc4, 0x98, 0x65, 0xfe, 0xe5, 0xee, 0x20, 0xcb, 0xde, 0xd2, 0x6c, 0x16, 0x8b, 0x5d, 0xb2, 0xd3, 0xc0, + 0x6c, 0x87, 0x10, 0x26, 0x90, 0x18, 0xa7, 0xfc, 0xc6, 0x79, 0x96, 0xa6, 0x3c, 0xf5, 0xdc, 0xf3, 0x8b, 0x0b, 0xd5, + 0xc2, 0x61, 0x99, 0x93, 0x70, 0xe1, 0x14, 0xe3, 0x85, 0xd7, 0x31, 0xf5, 0x9d, 0xf7, 0x19, 0x75, 0xae, 0x66, 0x49, + 0x16, 0x0e, 0xe9, 0xf9, 0xc5, 0xc5, 0x95, 0xc3, 0x53, 0xe7, 0x6a, 0x90, 0x65, 0x57, 0x0e, 0x4b, 0x32, 0x41, 0xc3, + 0xc8, 0x77, 0x51, 0x5b, 0x4e, 0x36, 0xc8, 0xb2, 0x77, 0xf4, 0x56, 0x10, 0x81, 0xe5, 0xa3, 0x20, 0x34, 0x1f, 0x51, + 0xe1, 0x64, 0xc5, 0xba, 0x3c, 0xb4, 0x88, 0xa9, 0x70, 0x04, 0x91, 0xf5, 0xbc, 0xad, 0x70, 0x4f, 0xd5, 0xa3, 0x68, + 0xb3, 0xa1, 0x47, 0xc5, 0xde, 0x9e, 0x28, 0xf0, 0x8c, 0xd4, 0xd2, 0x1c, 0x46, 0xe8, 0x8e, 0x29, 0xdb, 0xdb, 0xa3, + 0x7e, 0x4c, 0x93, 0x91, 0x18, 0x13, 0x42, 0x9a, 0x6d, 0xb6, 0xb7, 0xe7, 0x09, 0x12, 0x0b, 0x7f, 0x44, 0x85, 0x47, + 0x11, 0xc2, 0x65, 0xef, 0xbd, 0x3d, 0x4f, 0x21, 0x81, 0x13, 0x85, 0xb8, 0x0a, 0x8e, 0x91, 0xaf, 0xb1, 0x7f, 0x71, + 0x97, 0x0c, 0x3c, 0x1b, 0x7e, 0x84, 0xd9, 0xde, 0x5e, 0x2c, 0xfc, 0x0c, 0x46, 0xc4, 0x02, 0xa1, 0x3c, 0xa5, 0x62, + 0x96, 0x26, 0x8e, 0xc8, 0x05, 0xbf, 0x10, 0x29, 0x4b, 0x46, 0x1e, 0x5a, 0x98, 0x32, 0xab, 0x63, 0x9e, 0x2b, 0x70, + 0xdf, 0x08, 0x92, 0x92, 0x0e, 0xcc, 0x78, 0x2d, 0x3c, 0xd8, 0x45, 0x3e, 0x74, 0x52, 0x42, 0xdc, 0x4c, 0xf6, 0x75, + 0xbb, 0x69, 0x90, 0xd6, 0x5c, 0x17, 0x2b, 0x28, 0x31, 0x13, 0x08, 0x7f, 0x24, 0x5e, 0x8a, 0x7d, 0xdf, 0x17, 0x88, + 0x74, 0x16, 0x06, 0x2b, 0xa9, 0xb5, 0xce, 0x6e, 0xda, 0x6b, 0xf4, 0x03, 0xe1, 0xa7, 0x34, 0x9a, 0x0d, 0xa8, 0xe7, + 0x31, 0x9c, 0xe1, 0x04, 0x91, 0x0e, 0xab, 0x79, 0x9c, 0x74, 0x60, 0xbb, 0x79, 0x75, 0xaf, 0x09, 0xd9, 0x69, 0x20, + 0x0d, 0x23, 0x37, 0x00, 0x02, 0x86, 0x35, 0x3c, 0x9c, 0x10, 0x37, 0x99, 0x4d, 0xae, 0x69, 0xea, 0x16, 0xcd, 0xda, + 0x15, 0xb2, 0x98, 0x65, 0xd4, 0x19, 0x64, 0x99, 0x33, 0x9c, 0x25, 0x03, 0xc1, 0x78, 0xe2, 0xb8, 0x35, 0x5e, 0x73, + 0x15, 0x39, 0x14, 0xd4, 0xe0, 0xa2, 0x1c, 0x79, 0x19, 0xaa, 0xa5, 0xbd, 0xa4, 0xd6, 0xec, 0x63, 0x80, 0x12, 0xb5, + 0xf5, 0x78, 0x1a, 0x01, 0x14, 0xa7, 0xb0, 0xc6, 0x1c, 0xbf, 0x17, 0xb0, 0x4a, 0xb9, 0x44, 0x2a, 0xba, 0xa9, 0xbf, + 0x7e, 0x50, 0x88, 0xf0, 0x27, 0xe1, 0xd4, 0xa3, 0xa4, 0x43, 0x25, 0x71, 0x85, 0xc9, 0x00, 0x60, 0xad, 0xec, 0x5b, + 0x97, 0x06, 0xd4, 0x2f, 0x49, 0x0a, 0x05, 0xc2, 0x1f, 0xf2, 0xf4, 0x59, 0x38, 0x18, 0x43, 0xbf, 0x82, 0x60, 0x22, + 0x73, 0xde, 0x06, 0x29, 0x0d, 0x05, 0x7d, 0x16, 0x53, 0x78, 0xf2, 0x5c, 0xd9, 0xd3, 0x45, 0x38, 0x23, 0x2f, 0xfc, + 0x98, 0x89, 0x57, 0x3c, 0x19, 0xd0, 0x76, 0x66, 0x51, 0x17, 0x83, 0x7d, 0x3f, 0x13, 0x22, 0x65, 0xd7, 0x33, 0x41, + 0x3d, 0x37, 0x81, 0x16, 0x2e, 0xce, 0x10, 0x66, 0xbe, 0xa0, 0xb7, 0xe2, 0x9c, 0x27, 0x82, 0x26, 0x82, 0x50, 0x83, + 0x54, 0x9c, 0xfa, 0xe1, 0x74, 0x4a, 0x93, 0xe8, 0x7c, 0xcc, 0xe2, 0xc8, 0x63, 0x28, 0x47, 0x39, 0x0e, 0x05, 0x81, + 0x35, 0x92, 0x4e, 0x1a, 0xc0, 0x3f, 0xdb, 0x57, 0xe3, 0x09, 0xd2, 0x91, 0x87, 0x82, 0x12, 0xd7, 0x6d, 0x0f, 0x79, + 0xea, 0xe9, 0x15, 0x38, 0x7c, 0xe8, 0x08, 0x98, 0xe3, 0xed, 0x2c, 0xa6, 0x19, 0xa2, 0x35, 0xc2, 0x8a, 0x6d, 0xd4, + 0x08, 0x7e, 0x03, 0x14, 0x9f, 0x23, 0x2f, 0x45, 0x41, 0xda, 0x9e, 0x87, 0xa9, 0xf3, 0xb5, 0x3e, 0x51, 0x4f, 0x0d, + 0x37, 0x1b, 0x0b, 0xf2, 0xd4, 0x17, 0xe9, 0x2c, 0x13, 0x34, 0x7a, 0x77, 0x37, 0xa5, 0x19, 0x7e, 0x27, 0xc8, 0x58, + 0x74, 0xc7, 0xc2, 0xa7, 0x93, 0xa9, 0xb8, 0xbb, 0x90, 0x8c, 0x31, 0x70, 0x5d, 0x3c, 0x80, 0x96, 0x29, 0x0d, 0x07, + 0xc0, 0xcc, 0x34, 0xb6, 0xde, 0xf0, 0xf8, 0x6e, 0xc8, 0xe2, 0xf8, 0x62, 0x36, 0x9d, 0xf2, 0x54, 0xe0, 0xbf, 0x92, + 0x85, 0xe0, 0x25, 0x6a, 0x60, 0x2f, 0x17, 0xd9, 0x0d, 0x13, 0x83, 0xb1, 0x27, 0xd0, 0x62, 0x10, 0x66, 0xd4, 0x79, + 0xc2, 0x79, 0x4c, 0xc3, 0x24, 0x48, 0x49, 0xda, 0x7d, 0x27, 0x82, 0x64, 0x16, 0xc7, 0xed, 0xeb, 0x94, 0x86, 0x1f, + 0xdb, 0xb2, 0xfa, 0xf5, 0xf5, 0x07, 0x3a, 0x10, 0x81, 0xfc, 0x7d, 0x96, 0xa6, 0xe1, 0x1d, 0x34, 0x24, 0x04, 0x9a, + 0x75, 0xd3, 0xe0, 0x6f, 0x17, 0xaf, 0x5f, 0xf9, 0xea, 0x90, 0xb0, 0xe1, 0x9d, 0x97, 0x16, 0x07, 0x2f, 0xcd, 0xf1, + 0x30, 0xe5, 0x93, 0x95, 0xa9, 0x15, 0xd6, 0xd2, 0xf6, 0x16, 0x10, 0x28, 0x49, 0x77, 0xd4, 0xd0, 0x36, 0x04, 0xaf, + 0x24, 0xcd, 0x43, 0x25, 0xd1, 0xf3, 0xc2, 0x3f, 0x81, 0x2a, 0xf6, 0x52, 0x74, 0x3f, 0xb4, 0x22, 0xbd, 0x5b, 0x50, + 0x22, 0xe1, 0x9c, 0x82, 0x84, 0x01, 0x18, 0x07, 0xa1, 0x18, 0x8c, 0x17, 0x54, 0x0e, 0x96, 0x1b, 0x88, 0x69, 0x9e, + 0xe3, 0x9b, 0x82, 0xde, 0xc5, 0x0e, 0x21, 0xa9, 0x64, 0x54, 0x44, 0x2c, 0x97, 0x29, 0x21, 0x29, 0xc2, 0x3f, 0x90, + 0x45, 0x68, 0xd6, 0x13, 0xec, 0x34, 0x30, 0x9c, 0xcb, 0x40, 0x71, 0x17, 0x3c, 0xe0, 0xc9, 0x9c, 0xa6, 0x82, 0xa6, + 0xc1, 0x5f, 0x71, 0x4a, 0x87, 0x31, 0x40, 0xb1, 0xd3, 0xc4, 0xe3, 0x30, 0x3b, 0x1f, 0x87, 0xc9, 0x88, 0x46, 0xc1, + 0x8d, 0xc8, 0xf1, 0xdf, 0x89, 0x3b, 0x64, 0x49, 0x18, 0xb3, 0x5f, 0x69, 0xe4, 0x6a, 0x69, 0x70, 0xeb, 0xd0, 0x5b, + 0x41, 0x93, 0x28, 0x73, 0x9e, 0xbf, 0x7b, 0xf9, 0x42, 0xef, 0x63, 0x45, 0x40, 0xa0, 0x45, 0x36, 0x9b, 0xd2, 0xd4, + 0x43, 0x58, 0x0b, 0x88, 0x67, 0x4c, 0x32, 0xc7, 0x97, 0xe1, 0x54, 0x95, 0xb0, 0xec, 0xfd, 0x34, 0x0a, 0x05, 0x7d, + 0x43, 0x93, 0x88, 0x25, 0x23, 0xb2, 0xd3, 0x54, 0xe5, 0xe3, 0x50, 0x57, 0x44, 0x45, 0xd1, 0xe5, 0xee, 0xb3, 0x58, + 0xae, 0xbb, 0x78, 0x9c, 0x79, 0x28, 0xcf, 0x44, 0x28, 0xd8, 0xc0, 0x09, 0xa3, 0xe8, 0x9b, 0x84, 0x09, 0x26, 0x01, + 0x4c, 0x61, 0x7b, 0x80, 0x44, 0xa9, 0x12, 0x15, 0x06, 0x70, 0x0f, 0x61, 0xcf, 0xd3, 0x02, 0x60, 0x8c, 0xf4, 0x7e, + 0xed, 0xed, 0x95, 0xec, 0xbe, 0x4b, 0x03, 0x55, 0x49, 0x7a, 0x7d, 0xe4, 0x4f, 0x67, 0x19, 0x6c, 0xb4, 0x99, 0x02, + 0xa4, 0x0b, 0xbf, 0xce, 0x68, 0x3a, 0xa7, 0x51, 0x41, 0x1c, 0x99, 0x87, 0x16, 0x2b, 0x73, 0xe8, 0x63, 0x21, 0x48, + 0xaf, 0xdf, 0xb6, 0xf9, 0x36, 0xd5, 0x74, 0x9e, 0xf2, 0x29, 0x4d, 0x05, 0xa3, 0x59, 0xc1, 0x4a, 0x3c, 0x90, 0xa2, + 0x05, 0x3b, 0xc9, 0x88, 0x59, 0xdf, 0xd4, 0x63, 0x98, 0xa2, 0x0a, 0xc3, 0x30, 0x82, 0xf6, 0xd9, 0x5c, 0x4a, 0x8c, + 0x0c, 0x33, 0x84, 0x85, 0x82, 0x34, 0x43, 0x28, 0x47, 0x58, 0x18, 0x70, 0x15, 0x2b, 0xd2, 0xb3, 0xdd, 0x81, 0xa8, + 0x26, 0x3f, 0x48, 0x51, 0x0d, 0x0c, 0x2d, 0x14, 0x74, 0x6f, 0xcf, 0xa3, 0x7e, 0x41, 0x14, 0x64, 0xa7, 0xa9, 0xf7, + 0xc8, 0x42, 0xd6, 0x16, 0xb0, 0x61, 0x62, 0x81, 0x29, 0xc2, 0x3b, 0xd4, 0x4f, 0xf8, 0xd9, 0x60, 0x40, 0xb3, 0x8c, + 0xa7, 0x7b, 0x7b, 0x3b, 0xb2, 0x7d, 0xa1, 0x4d, 0xc0, 0x1e, 0xbe, 0xbe, 0x49, 0x4a, 0x08, 0x50, 0x29, 0x61, 0xb5, + 0x5c, 0x10, 0x20, 0xa7, 0xa4, 0xc2, 0xe1, 0x76, 0x8d, 0xe2, 0x11, 0xb8, 0x97, 0x97, 0x6e, 0x4d, 0x60, 0x8d, 0x86, + 0x11, 0x35, 0x53, 0xdf, 0x3d, 0xa5, 0x4a, 0xb5, 0x92, 0x8a, 0xc7, 0x1a, 0x66, 0xd4, 0xf9, 0xf1, 0x23, 0x3a, 0x64, + 0x89, 0xb5, 0xec, 0x0a, 0x48, 0x58, 0xe0, 0x0c, 0xe5, 0xd6, 0x86, 0x6e, 0x1c, 0x5a, 0xea, 0x34, 0x6a, 0xe7, 0x16, + 0x23, 0xa9, 0x47, 0x58, 0xdb, 0xd8, 0xa3, 0xfd, 0x1c, 0x4b, 0xd4, 0x9b, 0xd5, 0x24, 0x12, 0xd0, 0x9e, 0xe8, 0xb7, + 0x75, 0x3d, 0xc9, 0x14, 0xe6, 0x52, 0xfa, 0xcb, 0x8c, 0x66, 0x42, 0xd1, 0xb1, 0x27, 0x70, 0x82, 0x19, 0xca, 0xe1, + 0xb8, 0x0d, 0xd9, 0x68, 0x96, 0x82, 0xba, 0x03, 0x47, 0x91, 0x26, 0xb3, 0x09, 0x35, 0x4f, 0x9b, 0x60, 0x7b, 0x3d, + 0x05, 0x81, 0x98, 0x01, 0x4d, 0xdf, 0x4f, 0x4e, 0x00, 0xab, 0x40, 0xcb, 0xe5, 0x0f, 0x66, 0x90, 0x72, 0x2b, 0x0b, + 0x15, 0x6d, 0x65, 0x4f, 0xfe, 0x8e, 0xb4, 0x3c, 0xde, 0x69, 0x2a, 0xe8, 0xff, 0xde, 0x27, 0x3b, 0x8d, 0x82, 0x82, + 0x35, 0x4e, 0x15, 0x30, 0x0a, 0x85, 0xaf, 0xd5, 0x40, 0x48, 0x4a, 0xf7, 0x0a, 0xb1, 0xf8, 0xe3, 0x35, 0x3a, 0x1d, + 0x93, 0x1e, 0xe8, 0x19, 0xfe, 0xb8, 0xbf, 0x8d, 0x98, 0x0c, 0x37, 0xf0, 0xc4, 0x7a, 0x5d, 0xc9, 0x34, 0xe6, 0x55, + 0xa6, 0xb1, 0xb2, 0x08, 0x77, 0x5a, 0x74, 0x71, 0x0b, 0x1a, 0xd3, 0xc7, 0xbc, 0xac, 0xc2, 0x4c, 0x02, 0x53, 0x2e, + 0xc9, 0x1a, 0xe2, 0x55, 0x38, 0xa1, 0x99, 0x47, 0x11, 0xde, 0xd6, 0x40, 0x11, 0x27, 0x34, 0xe9, 0x5b, 0x62, 0x33, + 0x03, 0xb1, 0xc9, 0x90, 0xd2, 0xca, 0xaa, 0xc7, 0x2d, 0xc3, 0xb4, 0x97, 0xf5, 0x4b, 0x65, 0xce, 0x5a, 0xbc, 0x94, + 0xc7, 0x9a, 0xba, 0x0d, 0xfe, 0x54, 0x99, 0x42, 0x9a, 0x54, 0x1a, 0x32, 0x84, 0x77, 0x1a, 0xab, 0xfb, 0x68, 0x5a, + 0x95, 0x6b, 0xec, 0xf5, 0x61, 0x1f, 0xa4, 0xb8, 0xf0, 0x59, 0x26, 0xff, 0x56, 0xce, 0x19, 0xa0, 0xed, 0x02, 0xc8, + 0xc2, 0x1f, 0xc6, 0xa1, 0xf0, 0x9a, 0xfb, 0x0d, 0xd0, 0x44, 0xe7, 0x14, 0xa4, 0x09, 0x42, 0xeb, 0x4b, 0xa1, 0xfe, + 0x2c, 0xc9, 0xc6, 0x6c, 0x28, 0xbc, 0x50, 0x48, 0x86, 0x42, 0xe3, 0x8c, 0x3a, 0xa2, 0xa2, 0x0f, 0x4b, 0x66, 0x13, + 0x02, 0xa9, 0x15, 0xca, 0x17, 0x35, 0x90, 0x4a, 0xa6, 0x05, 0xbc, 0xa1, 0xd4, 0xa5, 0x4b, 0x1e, 0x63, 0x5a, 0x33, + 0xd0, 0x17, 0x9b, 0x5d, 0x35, 0x62, 0xa0, 0x59, 0x01, 0xb3, 0x54, 0x56, 0x16, 0xd8, 0xfc, 0x41, 0x17, 0x0a, 0x5f, + 0xf0, 0x17, 0xfc, 0x86, 0xa6, 0xe7, 0x21, 0x00, 0x1f, 0xa8, 0xee, 0xb9, 0x12, 0x03, 0x92, 0xdb, 0x8b, 0xb6, 0xa1, + 0x97, 0x4b, 0xb9, 0xf0, 0x37, 0x29, 0x9f, 0xb0, 0x8c, 0x82, 0xa6, 0xa6, 0xf0, 0x9f, 0xc0, 0x29, 0x93, 0xc7, 0x11, + 0x44, 0x0d, 0x2d, 0xe8, 0xeb, 0xec, 0x45, 0x95, 0xbe, 0x2e, 0x77, 0x9f, 0x8d, 0x0c, 0xfb, 0xab, 0x1e, 0x62, 0x84, + 0x3d, 0x6d, 0x4f, 0x58, 0x52, 0xce, 0x1f, 0x23, 0x2d, 0xde, 0x97, 0x4b, 0x61, 0x99, 0x6d, 0x15, 0x5d, 0x91, 0xaa, + 0x63, 0x83, 0xf2, 0x30, 0x8a, 0x40, 0xab, 0x4b, 0x79, 0x1c, 0x5b, 0x82, 0x0a, 0xb3, 0x76, 0x21, 0x9a, 0x2e, 0x77, + 0x9f, 0x5d, 0xdc, 0x27, 0x9d, 0xa0, 0xde, 0x16, 0x50, 0x06, 0xd0, 0x24, 0xa2, 0x29, 0x98, 0x91, 0xd6, 0x6e, 0x69, + 0x19, 0x7b, 0xce, 0x93, 0x84, 0x0e, 0x04, 0x8d, 0xc0, 0x4a, 0x61, 0x44, 0xf8, 0x63, 0x9e, 0x89, 0xa2, 0xb0, 0x84, + 0x9e, 0x59, 0xd0, 0x33, 0x7f, 0x10, 0xc6, 0xb1, 0xa7, 0x2c, 0x92, 0x09, 0x9f, 0xd3, 0x0d, 0x50, 0xb7, 0x2b, 0x20, + 0x17, 0xc3, 0x50, 0x6b, 0x18, 0xea, 0x67, 0xd3, 0x98, 0x0d, 0x68, 0x21, 0xb8, 0x2e, 0x7c, 0x96, 0x44, 0xf4, 0x16, + 0xf8, 0x08, 0xea, 0x74, 0x3a, 0x0d, 0xdc, 0x44, 0xb9, 0x42, 0xf8, 0x62, 0x0d, 0xb1, 0xf7, 0x88, 0x4c, 0x20, 0x32, + 0xd2, 0x59, 0x6c, 0xe2, 0x07, 0x14, 0x59, 0x72, 0x92, 0x19, 0xcb, 0x4a, 0xf1, 0x66, 0x84, 0x23, 0x1a, 0x53, 0x41, + 0x0d, 0x2f, 0x07, 0xfd, 0x59, 0x1d, 0xdd, 0xb7, 0x05, 0xfe, 0x0a, 0x72, 0x32, 0xa7, 0xcc, 0xec, 0x79, 0x56, 0x58, + 0xea, 0xe5, 0xf6, 0x94, 0xd8, 0xee, 0x0a, 0xb5, 0x3d, 0xa1, 0x10, 0xe1, 0x60, 0xac, 0x4c, 0x74, 0x6f, 0x6d, 0x49, + 0xe5, 0x18, 0x9a, 0xaf, 0x17, 0x87, 0xe8, 0xbd, 0x01, 0x73, 0x13, 0x0a, 0x2e, 0x34, 0x53, 0xa0, 0x60, 0xf5, 0xa9, + 0x6d, 0x3b, 0x0f, 0xe3, 0xf8, 0x3a, 0x1c, 0x7c, 0xac, 0x52, 0x7f, 0x49, 0x06, 0x64, 0x95, 0x1b, 0x5b, 0x55, 0x16, + 0xcb, 0xb2, 0xd7, 0x6d, 0xb8, 0x74, 0xe5, 0xa0, 0x78, 0x3b, 0x8d, 0x92, 0xec, 0xab, 0x1b, 0xbd, 0x95, 0xda, 0x25, + 0x44, 0x4c, 0xaf, 0xcc, 0x03, 0x2e, 0xf0, 0x49, 0x8a, 0x33, 0xfc, 0x40, 0xd3, 0x1d, 0xd8, 0x1a, 0xf9, 0x0a, 0x20, + 0x02, 0x2d, 0xf2, 0x88, 0x65, 0xdb, 0x31, 0xf0, 0x87, 0x40, 0xf9, 0xd4, 0x9a, 0xe1, 0xa1, 0x80, 0x16, 0x3c, 0x4e, + 0xab, 0xcc, 0x05, 0x64, 0x5a, 0x9b, 0x30, 0x8c, 0xe6, 0x5b, 0xd0, 0x5c, 0x24, 0xbd, 0xbf, 0x56, 0x55, 0xa0, 0x93, + 0x01, 0x14, 0x59, 0xdb, 0x56, 0x26, 0x2a, 0x14, 0xa0, 0x79, 0x2a, 0x93, 0x22, 0x37, 0xa9, 0x18, 0x8f, 0x5a, 0x5d, + 0x57, 0xf6, 0xb7, 0x66, 0xb9, 0x9c, 0x78, 0x9e, 0x97, 0x81, 0xfd, 0x66, 0xf4, 0xfa, 0x72, 0x11, 0xd9, 0xda, 0x22, + 0x32, 0xdf, 0x32, 0xb2, 0x50, 0x49, 0xcb, 0x56, 0xf7, 0xe0, 0xaf, 0xc8, 0x6e, 0x04, 0xca, 0xaa, 0x0f, 0xfc, 0x19, + 0x15, 0xec, 0x36, 0x26, 0x02, 0x73, 0x6d, 0xe0, 0x68, 0x4a, 0x03, 0x86, 0x51, 0x76, 0x49, 0x90, 0x3a, 0x1a, 0x15, + 0x63, 0x37, 0xc1, 0x1c, 0xad, 0x68, 0xf6, 0x79, 0xae, 0x71, 0x44, 0x91, 0xde, 0x9b, 0x8a, 0x4a, 0x6c, 0x61, 0x05, + 0x27, 0x44, 0xab, 0xc1, 0x4a, 0xeb, 0x59, 0xc5, 0x4d, 0x31, 0x2e, 0x1c, 0xd4, 0x12, 0x35, 0x15, 0x7d, 0xd2, 0x28, + 0x56, 0x09, 0xc2, 0x63, 0xa3, 0x91, 0xf2, 0x72, 0xdd, 0x84, 0xb8, 0xc6, 0x1b, 0xe1, 0x76, 0x17, 0x15, 0x93, 0x30, + 0xb0, 0x9a, 0xe5, 0x01, 0xb0, 0x54, 0xbe, 0x09, 0xdd, 0x9b, 0x68, 0xa6, 0x32, 0x8e, 0x85, 0x70, 0x6e, 0x23, 0xdc, + 0xc2, 0x6c, 0xa2, 0x38, 0x57, 0xd2, 0x27, 0xe3, 0x6a, 0x5f, 0x8f, 0x62, 0xae, 0xf6, 0x61, 0x0d, 0x89, 0xab, 0x8a, + 0xa7, 0x24, 0x41, 0x30, 0x60, 0x33, 0x50, 0xee, 0x6c, 0xf9, 0xe0, 0x01, 0xec, 0x6c, 0xb9, 0x5c, 0x23, 0xba, 0x8d, + 0xfa, 0x27, 0xf2, 0x4b, 0xa3, 0x70, 0xb9, 0xbc, 0x11, 0xc8, 0xd3, 0x9a, 0x2f, 0xa6, 0xa8, 0x6b, 0x38, 0xee, 0xd9, + 0x0b, 0x68, 0x25, 0x15, 0xd1, 0xb2, 0xa4, 0x30, 0x19, 0xaa, 0x34, 0x5b, 0xdd, 0x27, 0x61, 0xb1, 0xed, 0xf3, 0x35, + 0xee, 0x25, 0x0b, 0xb5, 0x98, 0x2e, 0x97, 0x7c, 0xae, 0x87, 0x66, 0x08, 0xa1, 0x20, 0x93, 0x56, 0xcc, 0xce, 0x26, + 0xc3, 0x72, 0x6f, 0x2f, 0xb3, 0x06, 0xba, 0x2c, 0xd8, 0xc4, 0x07, 0x0f, 0x44, 0x72, 0x76, 0x97, 0x48, 0xdd, 0xe5, + 0x83, 0x11, 0x42, 0x6b, 0x66, 0x69, 0xa3, 0x0d, 0xd6, 0x78, 0x78, 0x13, 0x32, 0xe1, 0x14, 0xa3, 0x28, 0x6b, 0xdc, + 0xa3, 0x68, 0xa1, 0x55, 0x0d, 0x3f, 0xa5, 0xa0, 0x3c, 0x02, 0x4f, 0x30, 0x2a, 0xb4, 0xa2, 0xfb, 0xc1, 0x98, 0x82, + 0x23, 0xd8, 0x68, 0x11, 0x85, 0x5d, 0xb8, 0xa3, 0xa5, 0x88, 0x1e, 0x78, 0x33, 0xec, 0xf9, 0x6a, 0xf7, 0x8a, 0x1d, + 0x30, 0xa5, 0xe9, 0x90, 0xa7, 0x13, 0x53, 0x97, 0xaf, 0x3c, 0x6b, 0xce, 0xc8, 0x86, 0xde, 0xc6, 0xb1, 0xb5, 0xfa, + 0xdf, 0x5e, 0x31, 0xba, 0x4b, 0x73, 0xbd, 0x22, 0x4a, 0x0b, 0xe9, 0xab, 0xfc, 0x81, 0x86, 0x32, 0x33, 0xdb, 0xbc, + 0xd7, 0xce, 0xd4, 0xb6, 0x72, 0x98, 0xec, 0x34, 0xdb, 0x85, 0xcd, 0x67, 0xa8, 0xa1, 0xad, 0x1c, 0x1b, 0x5a, 0xa4, + 0xf2, 0x59, 0x1c, 0x69, 0x60, 0x19, 0xc2, 0x54, 0xd3, 0xd1, 0x0d, 0x8b, 0xe3, 0xb2, 0xf4, 0x73, 0xf8, 0x7a, 0xa6, + 0xf9, 0x7a, 0x62, 0xf8, 0x3a, 0x70, 0x0a, 0xe0, 0xeb, 0x6a, 0xb8, 0xb2, 0x7b, 0xb2, 0x76, 0x3a, 0x13, 0xc5, 0xd1, + 0x33, 0x69, 0x47, 0xc3, 0x7c, 0x33, 0x03, 0x01, 0x2a, 0x34, 0xaf, 0x8f, 0x9e, 0x76, 0xc2, 0x80, 0x01, 0xa8, 0x5c, + 0x98, 0xd4, 0x76, 0x51, 0x7c, 0xf4, 0x10, 0xce, 0x72, 0x5a, 0x50, 0xf6, 0xd9, 0x33, 0x70, 0xd2, 0x59, 0xcb, 0x01, + 0x21, 0x26, 0x8b, 0x3f, 0x4b, 0x89, 0x32, 0xab, 0x63, 0x7a, 0x75, 0x99, 0x59, 0x1d, 0x70, 0xfa, 0x72, 0x75, 0xd1, + 0xfd, 0xbc, 0x5e, 0x2e, 0x8f, 0x15, 0xcb, 0x2b, 0xf7, 0x7b, 0xb9, 0xf4, 0x56, 0x4a, 0xc0, 0x7f, 0xaf, 0x4d, 0x94, + 0xb4, 0x18, 0x1d, 0x78, 0x80, 0x8d, 0x19, 0x28, 0xc8, 0xd5, 0xa2, 0x0b, 0x11, 0xf7, 0xe2, 0x53, 0x0e, 0x1e, 0xe9, + 0xa6, 0x57, 0xfd, 0xcf, 0xf9, 0x64, 0x0a, 0xda, 0xd8, 0x0a, 0x49, 0x8f, 0xa8, 0x9e, 0xb0, 0xac, 0xcf, 0x37, 0x94, + 0x55, 0xfa, 0xc8, 0xf3, 0x58, 0xa1, 0xa6, 0xc2, 0x5e, 0xde, 0x69, 0xe4, 0xb3, 0xa2, 0xa8, 0x60, 0x1c, 0x9b, 0x9c, + 0x2a, 0xe7, 0xab, 0x2e, 0x19, 0x53, 0xf1, 0xda, 0x63, 0x8a, 0x0f, 0x33, 0xe0, 0x75, 0x16, 0xfb, 0x31, 0xe4, 0x6e, + 0xef, 0x7f, 0x5e, 0x22, 0x67, 0x91, 0xaf, 0xa0, 0x6f, 0x91, 0xe7, 0xb7, 0xca, 0xc8, 0xc6, 0xb7, 0xdb, 0xad, 0xe1, + 0xb2, 0x4e, 0x1b, 0x8b, 0xbd, 0x3e, 0xbe, 0x5d, 0x57, 0x1d, 0xc9, 0x62, 0xc2, 0x23, 0x1a, 0xb8, 0x7c, 0x4a, 0x13, + 0x37, 0x07, 0xaf, 0xaa, 0xde, 0xfb, 0x81, 0xf0, 0x16, 0x6f, 0xab, 0xee, 0xd5, 0xe0, 0x36, 0x07, 0xef, 0xd7, 0xd7, + 0xeb, 0x8e, 0xd7, 0xef, 0x69, 0x9a, 0x49, 0x45, 0xb4, 0xd0, 0x69, 0xbf, 0x2e, 0xc5, 0xd2, 0xd7, 0xc1, 0xd6, 0xf6, + 0xa5, 0x09, 0xe2, 0x36, 0xfd, 0x63, 0xff, 0xc0, 0x45, 0xd2, 0x2d, 0xfc, 0x93, 0x3e, 0xf0, 0x1f, 0x8c, 0x5b, 0xf8, + 0x19, 0xf9, 0x50, 0xf5, 0x0a, 0x47, 0x82, 0x3c, 0xeb, 0x3e, 0x33, 0x16, 0x33, 0x8f, 0xd9, 0xe0, 0xce, 0x73, 0x63, + 0x26, 0xea, 0x10, 0x7a, 0x73, 0xf1, 0x42, 0x55, 0x80, 0x4b, 0x51, 0xba, 0xb3, 0x73, 0x63, 0xeb, 0x61, 0x21, 0x88, + 0xbb, 0x1b, 0x33, 0xb1, 0xeb, 0xe2, 0x09, 0xb9, 0x82, 0x1f, 0xbb, 0x0b, 0xef, 0x65, 0x28, 0xc6, 0x7e, 0x1a, 0x26, + 0x11, 0x9f, 0x78, 0xa8, 0xe6, 0xba, 0xc8, 0xcf, 0xa4, 0xbd, 0xf1, 0x18, 0xe5, 0xbb, 0x57, 0xf8, 0x4c, 0x10, 0xb7, + 0xeb, 0xd6, 0x26, 0xf8, 0x95, 0x20, 0x57, 0xa7, 0xbb, 0x8b, 0x33, 0x91, 0x77, 0xae, 0xf0, 0x59, 0xe1, 0xb1, 0xc7, + 0x6f, 0x88, 0x87, 0x48, 0xe7, 0x4c, 0x43, 0x73, 0xce, 0x27, 0xca, 0x73, 0xef, 0x22, 0xfc, 0x1e, 0xe2, 0x2a, 0x69, + 0xc9, 0x6d, 0x74, 0x68, 0x65, 0x87, 0xb8, 0x5c, 0xba, 0x08, 0xdc, 0xbd, 0x3d, 0xab, 0xac, 0x50, 0x15, 0xf0, 0xad, + 0x20, 0x15, 0x83, 0x1c, 0xbf, 0x95, 0x11, 0x9a, 0x5b, 0xe1, 0xa5, 0xc8, 0x0c, 0xe3, 0x19, 0x3f, 0xb4, 0x3e, 0x9a, + 0x69, 0x4f, 0x79, 0x18, 0x7c, 0x26, 0x68, 0x1a, 0x0a, 0x9e, 0xf6, 0x91, 0xad, 0x7e, 0xe0, 0xbf, 0x91, 0xab, 0x9e, + 0xf3, 0x9f, 0xbe, 0xf8, 0x79, 0xf8, 0x73, 0xda, 0xbf, 0xc2, 0xaf, 0xc9, 0xfe, 0xa9, 0xd7, 0x0d, 0xbc, 0x9d, 0x7a, + 0x7d, 0xf9, 0xf3, 0x7e, 0xef, 0x1f, 0x61, 0xfd, 0xd7, 0xb3, 0xfa, 0x4f, 0x7d, 0xb4, 0xf4, 0x7e, 0xde, 0xef, 0xf6, + 0xf4, 0x53, 0xef, 0x1f, 0x9d, 0x9f, 0xb3, 0xfe, 0x9f, 0x55, 0xe1, 0x2e, 0x42, 0xfb, 0x23, 0x3c, 0x13, 0x64, 0xbf, + 0x5e, 0xef, 0xec, 0x8f, 0xf0, 0x54, 0x90, 0x7d, 0xf8, 0x7b, 0x4d, 0xde, 0xd2, 0xd1, 0xb3, 0xdb, 0xa9, 0x77, 0xd5, + 0x59, 0xee, 0x2e, 0xfe, 0x96, 0xc3, 0xa8, 0xbd, 0x7f, 0xfc, 0xfc, 0x73, 0xe6, 0x7e, 0xd5, 0x21, 0xfb, 0xfd, 0x1a, + 0xf2, 0xa0, 0xf4, 0xcf, 0x44, 0xfe, 0xeb, 0x75, 0x83, 0xde, 0x3f, 0x34, 0x14, 0xee, 0x57, 0x3f, 0x5f, 0x9d, 0x76, + 0x48, 0x7f, 0xe9, 0xb9, 0xcb, 0xaf, 0xd0, 0x12, 0xa1, 0xe5, 0x2e, 0xba, 0xc2, 0xee, 0xc8, 0x45, 0x78, 0x24, 0xc8, + 0xfe, 0x57, 0xfb, 0x23, 0x3c, 0x17, 0x64, 0xdf, 0xdd, 0x1f, 0xe1, 0x67, 0x82, 0xec, 0xff, 0xc3, 0xeb, 0x06, 0xca, + 0xc3, 0xb6, 0x94, 0xee, 0x8d, 0x25, 0x04, 0x37, 0xc2, 0x94, 0x86, 0x4b, 0xc1, 0x44, 0x4c, 0xd1, 0xee, 0x3e, 0xc3, + 0x17, 0x12, 0x4d, 0x9e, 0x00, 0x27, 0x0c, 0xd8, 0x76, 0xde, 0xe2, 0x12, 0x36, 0x1b, 0x68, 0x66, 0x37, 0x48, 0xb1, + 0xf2, 0x03, 0x64, 0x81, 0xc0, 0xf3, 0x30, 0x9e, 0xd1, 0x2c, 0xa0, 0x39, 0xc2, 0x03, 0x72, 0x21, 0xbc, 0x26, 0xc2, + 0xcf, 0x05, 0xfc, 0x68, 0x21, 0x7c, 0xa1, 0x03, 0x98, 0x70, 0x90, 0x15, 0x51, 0x25, 0x5c, 0x69, 0x2c, 0x2e, 0xc2, + 0xd3, 0x0d, 0x95, 0x62, 0x0c, 0xde, 0x05, 0x84, 0x87, 0x95, 0x70, 0x27, 0xbe, 0x21, 0x86, 0x24, 0xde, 0xa5, 0x94, + 0xfe, 0x10, 0xc6, 0x1f, 0x69, 0xea, 0x9d, 0xe1, 0x66, 0xeb, 0x31, 0x96, 0x2e, 0xe8, 0x9d, 0x26, 0x6a, 0x17, 0xb1, + 0xaa, 0x73, 0xa1, 0x62, 0x04, 0x20, 0x64, 0xab, 0xbe, 0x18, 0xd8, 0xf1, 0x9d, 0x74, 0xcd, 0x61, 0x95, 0x86, 0x37, + 0x2e, 0xaa, 0xc6, 0x45, 0x59, 0x32, 0x0f, 0x63, 0x16, 0x39, 0x82, 0x4e, 0xa6, 0x71, 0x28, 0xa8, 0xa3, 0xd7, 0xeb, + 0x84, 0x30, 0x90, 0x5b, 0xa8, 0x0c, 0x91, 0x65, 0x70, 0x46, 0x26, 0xe0, 0x04, 0x67, 0xc5, 0x83, 0xe8, 0x94, 0x56, + 0x3b, 0x5e, 0x96, 0xc1, 0xaf, 0xd5, 0xf8, 0x5e, 0xbd, 0x09, 0x8e, 0xb0, 0xbe, 0x14, 0xcf, 0x19, 0x4e, 0x08, 0x08, + 0xd1, 0x56, 0xd7, 0x3d, 0xcd, 0xe6, 0xa3, 0x8e, 0x0b, 0xb1, 0x19, 0x4e, 0x5e, 0x4b, 0xbf, 0x10, 0x34, 0x18, 0x93, + 0x46, 0x7b, 0x7c, 0x4a, 0xdb, 0xe3, 0x5a, 0xcd, 0xe8, 0xd0, 0x31, 0x49, 0x7b, 0x63, 0xd5, 0x3d, 0xc4, 0x11, 0x9e, + 0x91, 0x7a, 0x13, 0x8f, 0x48, 0x43, 0x76, 0x69, 0x8f, 0x4e, 0x63, 0x3d, 0xcd, 0xde, 0x9e, 0xc7, 0xfd, 0x38, 0xcc, + 0xc4, 0x37, 0x60, 0xec, 0x93, 0x11, 0x8e, 0x08, 0xf7, 0xe9, 0x2d, 0x1d, 0x78, 0x31, 0xc2, 0x91, 0xe6, 0x34, 0xa8, + 0x8d, 0x46, 0xc4, 0x6a, 0x06, 0x46, 0x04, 0x79, 0xdd, 0x8d, 0x7a, 0xcd, 0x3e, 0x21, 0xc4, 0xdd, 0xa9, 0xd7, 0xdd, + 0x2e, 0x27, 0x33, 0x11, 0x40, 0x89, 0xa5, 0x2a, 0x93, 0x29, 0x14, 0xb5, 0xac, 0x22, 0xef, 0x99, 0xf0, 0x05, 0xcd, + 0x84, 0x07, 0xc5, 0x60, 0xfe, 0x67, 0x86, 0xb0, 0xdd, 0xd3, 0x7d, 0xb7, 0x06, 0xa5, 0x92, 0x38, 0x11, 0xe6, 0xe4, + 0x1a, 0x05, 0x51, 0xef, 0xa0, 0x6f, 0xf3, 0x7f, 0x59, 0x08, 0x93, 0x5f, 0x77, 0xa3, 0x5e, 0x43, 0x4e, 0xde, 0x71, + 0xbb, 0x1e, 0x27, 0x99, 0x52, 0xd0, 0xba, 0x59, 0xf0, 0x5a, 0x2e, 0x15, 0x05, 0x1a, 0x38, 0x3d, 0xef, 0x8c, 0xd4, + 0x5b, 0x81, 0x37, 0xb3, 0x17, 0x51, 0x87, 0xc9, 0x34, 0x16, 0x70, 0x48, 0xa0, 0x3d, 0xe6, 0x04, 0x66, 0x2c, 0xbb, + 0x5d, 0x07, 0xfa, 0xf9, 0x2b, 0xf7, 0xab, 0xee, 0x5c, 0x04, 0x23, 0xa1, 0xa6, 0x9f, 0x8b, 0xe5, 0x12, 0xfe, 0x8e, + 0x44, 0x97, 0x93, 0x6b, 0x59, 0x34, 0xd3, 0x45, 0x53, 0x28, 0x7a, 0x1d, 0x00, 0xa8, 0x38, 0x2b, 0x94, 0x2c, 0xb5, + 0x27, 0x73, 0x22, 0x61, 0xdf, 0xdb, 0x4b, 0x7b, 0xe3, 0x5a, 0xb3, 0x0f, 0xfe, 0xfd, 0x54, 0x64, 0x3f, 0x30, 0x31, + 0xf6, 0xdc, 0xfd, 0x8e, 0x8b, 0xba, 0xae, 0x03, 0x5b, 0xdb, 0x4e, 0x6a, 0x44, 0x61, 0x38, 0xae, 0xbd, 0x12, 0xc1, + 0xac, 0x43, 0x1a, 0x5d, 0x8f, 0x69, 0x7f, 0x1e, 0xc2, 0xb1, 0x66, 0x9c, 0x0d, 0x3c, 0x43, 0x35, 0x21, 0x6a, 0xe6, + 0x79, 0x86, 0x6a, 0x93, 0xda, 0x1c, 0x05, 0x71, 0x6d, 0x52, 0xf3, 0x66, 0x84, 0x90, 0x7a, 0xab, 0xe8, 0x66, 0xa4, + 0xdf, 0x18, 0x05, 0x73, 0xe3, 0xec, 0xec, 0xc9, 0xe3, 0x90, 0xd4, 0xbc, 0xb4, 0x47, 0xfb, 0xcb, 0xa5, 0x7b, 0xda, + 0xed, 0xb8, 0xa8, 0xe6, 0x19, 0x42, 0xdb, 0x37, 0x94, 0x86, 0x10, 0x66, 0xfd, 0x5c, 0x87, 0x92, 0xde, 0x55, 0xc2, + 0x46, 0x8b, 0xf2, 0xb0, 0x5b, 0x3c, 0x80, 0xe6, 0x85, 0x1d, 0xa3, 0xf4, 0xd5, 0x29, 0x2c, 0xd3, 0x10, 0x73, 0x42, + 0x1a, 0x98, 0x13, 0xe3, 0xbb, 0x1e, 0x13, 0x51, 0x12, 0x7c, 0x4c, 0xca, 0xe6, 0xb8, 0x17, 0xe2, 0xa8, 0x4f, 0x5e, + 0x2a, 0x7b, 0xa4, 0x6d, 0xfc, 0xe2, 0x34, 0x26, 0xef, 0x56, 0xa2, 0xb7, 0x21, 0xc4, 0x56, 0x6e, 0xfc, 0xc1, 0x2c, + 0x4d, 0x69, 0x22, 0x5e, 0xf1, 0x48, 0xab, 0x69, 0x34, 0x06, 0x4b, 0x09, 0xc2, 0xb2, 0x18, 0x74, 0xb4, 0x96, 0x39, + 0x19, 0xb3, 0xb5, 0xea, 0x11, 0x99, 0x29, 0xf5, 0x49, 0x06, 0x6b, 0xdb, 0x23, 0x6d, 0x17, 0x7b, 0x08, 0xcf, 0x74, + 0x14, 0xd7, 0xf3, 0x7d, 0x7f, 0xe4, 0x0f, 0xa0, 0x1a, 0x26, 0xc8, 0x50, 0x2e, 0xcf, 0x91, 0x97, 0x91, 0x1b, 0x3f, + 0xa1, 0xb7, 0x72, 0x56, 0x0f, 0x95, 0x92, 0xd9, 0x1c, 0xaf, 0xd3, 0x71, 0x5b, 0xb2, 0x9b, 0xcc, 0x4f, 0x78, 0x44, + 0x01, 0x3d, 0x10, 0xb7, 0xd7, 0x45, 0xe3, 0x30, 0xb3, 0xe3, 0x53, 0x25, 0x7c, 0x3d, 0xdb, 0x79, 0x3d, 0x02, 0x8f, + 0xaf, 0xd4, 0xb5, 0x8a, 0xc6, 0xca, 0x0d, 0x8e, 0x10, 0x1b, 0x7a, 0x23, 0x1f, 0xe2, 0x7a, 0x92, 0x84, 0x04, 0x98, + 0x72, 0x23, 0x9b, 0xa8, 0x26, 0xc5, 0x98, 0x73, 0x12, 0xf5, 0x78, 0xad, 0x26, 0xbd, 0xd0, 0x33, 0x45, 0x12, 0x23, + 0x84, 0xe7, 0xc5, 0xd9, 0x32, 0xed, 0x5e, 0x0b, 0x52, 0x9d, 0xca, 0x9b, 0x57, 0xdd, 0xb9, 0x35, 0x21, 0x90, 0xf4, + 0x14, 0x0a, 0x6f, 0x82, 0xf0, 0x13, 0xb2, 0xef, 0xf5, 0xfc, 0xee, 0x5f, 0xfa, 0xa8, 0xeb, 0xf9, 0x7f, 0x46, 0xfb, + 0x8a, 0x73, 0xcc, 0x51, 0x3b, 0x56, 0x73, 0x2c, 0x64, 0xfc, 0xb2, 0x89, 0xa5, 0x27, 0x31, 0x48, 0x70, 0x12, 0x4e, + 0x68, 0xf0, 0x04, 0x0e, 0xb9, 0x21, 0x9c, 0xd7, 0x02, 0x03, 0x25, 0x05, 0x4f, 0x34, 0x2f, 0xf1, 0xdd, 0xee, 0x0b, + 0x51, 0x3c, 0x75, 0xdd, 0xee, 0x87, 0xf2, 0xe9, 0x2f, 0x6e, 0xf7, 0x1b, 0x11, 0xfc, 0x9a, 0x6b, 0x6f, 0x77, 0x65, + 0x8e, 0x63, 0x33, 0x47, 0xae, 0xb6, 0xc6, 0xc2, 0xdd, 0x0c, 0xad, 0x3b, 0x3a, 0x46, 0x28, 0x67, 0xc3, 0x82, 0x19, + 0x65, 0xbe, 0x08, 0x47, 0x80, 0x54, 0x6b, 0x0f, 0x32, 0x3b, 0xae, 0x5f, 0xae, 0x18, 0x48, 0xc5, 0xd0, 0x2b, 0x20, + 0x73, 0xd4, 0x69, 0xa0, 0x45, 0xa5, 0xad, 0xd4, 0x99, 0xaa, 0x71, 0xf4, 0x82, 0x4f, 0xcf, 0x49, 0xa3, 0x3d, 0x3f, + 0x1d, 0xb5, 0xe7, 0xb5, 0x1a, 0xca, 0x0c, 0x69, 0xcd, 0x7a, 0xf3, 0x3e, 0x7e, 0x03, 0x4e, 0x3d, 0x9b, 0x96, 0x70, + 0x65, 0x79, 0x2d, 0xbd, 0xbc, 0x5a, 0x2d, 0xc9, 0x51, 0xdb, 0xea, 0x3a, 0x52, 0x5d, 0xf3, 0x5c, 0xe1, 0x64, 0x95, + 0xd4, 0x4e, 0x90, 0x2c, 0x81, 0x64, 0x28, 0x42, 0xc8, 0x99, 0x40, 0x1b, 0x47, 0x85, 0x31, 0xa1, 0xbb, 0x3c, 0xb3, + 0xc0, 0x3e, 0x95, 0x94, 0xf0, 0x00, 0x0b, 0xd0, 0xb5, 0xf0, 0x04, 0x4f, 0xf0, 0xac, 0xd6, 0x94, 0x64, 0x5e, 0x6f, + 0xb6, 0xab, 0x63, 0x3d, 0x2a, 0xc7, 0xc2, 0xb3, 0x1a, 0x99, 0x14, 0x58, 0xca, 0x93, 0x5a, 0x2d, 0xaf, 0x06, 0x3b, + 0xcd, 0xc9, 0xad, 0x04, 0x20, 0xce, 0x56, 0x93, 0x32, 0x8c, 0x84, 0x2d, 0x65, 0x2a, 0xf3, 0x59, 0x92, 0xd0, 0x14, + 0xa4, 0x28, 0x11, 0x98, 0xe5, 0x79, 0x29, 0xd9, 0x41, 0x8c, 0x62, 0x4a, 0x52, 0xe0, 0x3c, 0xd2, 0xee, 0xc2, 0x09, + 0xe6, 0x78, 0x2c, 0xf9, 0x06, 0x21, 0xe4, 0xc2, 0xa4, 0xb3, 0x08, 0xc9, 0x83, 0x62, 0xc2, 0x2c, 0x99, 0x94, 0x11, + 0xea, 0x5f, 0xee, 0x9e, 0xf3, 0x7b, 0x6d, 0xb2, 0x1e, 0xeb, 0x07, 0xb2, 0x59, 0xac, 0x39, 0x57, 0x48, 0xde, 0x7b, + 0x02, 0x15, 0xd1, 0x11, 0x5f, 0x32, 0xc0, 0xa7, 0x2c, 0xa5, 0x52, 0x07, 0xdf, 0x35, 0x76, 0x5f, 0x5c, 0x55, 0x20, + 0x63, 0xdb, 0x7b, 0x03, 0x88, 0x0c, 0xc1, 0xb9, 0x93, 0x90, 0xb5, 0x66, 0x97, 0xbb, 0x67, 0xaf, 0x37, 0xd9, 0xc0, + 0xcb, 0xa5, 0xb6, 0x7e, 0xa5, 0x6e, 0x83, 0xc3, 0x12, 0xd2, 0x58, 0xff, 0x08, 0xbc, 0x58, 0xaa, 0x48, 0xa1, 0x97, + 0x02, 0x15, 0x5d, 0xee, 0x9e, 0xbd, 0xf3, 0x52, 0xe9, 0x5b, 0x42, 0xd8, 0x5e, 0xb6, 0xc7, 0x89, 0x37, 0x26, 0x14, + 0xa9, 0xb5, 0x17, 0xac, 0x8b, 0x5b, 0x02, 0x3c, 0x18, 0xcb, 0x4a, 0xb0, 0x20, 0x7a, 0xac, 0x4f, 0x62, 0x8d, 0x01, + 0x12, 0x23, 0x1c, 0x57, 0xec, 0x32, 0x02, 0x1b, 0x20, 0xe7, 0xba, 0x80, 0x9d, 0xf0, 0x95, 0xea, 0x87, 0x70, 0x2c, + 0x67, 0x15, 0xb9, 0x12, 0x1e, 0x4f, 0xd6, 0xb2, 0xd2, 0x4a, 0x73, 0xf4, 0x7b, 0xb0, 0x9d, 0xcc, 0xc3, 0x2b, 0x62, + 0x2c, 0x09, 0x5d, 0xf0, 0xd4, 0xa4, 0x8f, 0x5d, 0xee, 0x9e, 0xbd, 0xd4, 0x19, 0x64, 0xd3, 0xd0, 0xf0, 0xfb, 0x35, + 0x13, 0xf3, 0xec, 0xa5, 0x5f, 0xd6, 0xca, 0xc6, 0x97, 0xbb, 0x67, 0xef, 0x37, 0x35, 0x83, 0xf2, 0x7c, 0x56, 0xda, + 0xf8, 0x12, 0xbe, 0x05, 0x8d, 0x83, 0x85, 0x16, 0x0e, 0x01, 0xcb, 0xb1, 0x14, 0x48, 0x41, 0x96, 0x17, 0xae, 0x91, + 0xa7, 0x38, 0x21, 0x32, 0x0c, 0x54, 0xdd, 0x35, 0xad, 0xe6, 0x31, 0x9e, 0x5c, 0x0c, 0xf8, 0x94, 0x6e, 0x89, 0x0d, + 0x9d, 0x21, 0x9f, 0x4d, 0x20, 0x75, 0x46, 0x82, 0xce, 0xf0, 0x4e, 0x03, 0xb5, 0xab, 0xe2, 0x2b, 0x91, 0x44, 0xca, + 0x2b, 0xb2, 0x05, 0x8f, 0x49, 0x03, 0xc7, 0xa4, 0x81, 0x43, 0x92, 0xf5, 0x1a, 0x4a, 0x40, 0xb4, 0xc3, 0x62, 0x5c, + 0x25, 0x66, 0x20, 0x2b, 0x4c, 0x9f, 0x56, 0x25, 0x80, 0xa3, 0x76, 0x28, 0x7d, 0x8f, 0x52, 0xa6, 0x47, 0x92, 0x2c, + 0xde, 0x7a, 0x1c, 0x73, 0x39, 0xf0, 0x05, 0xbb, 0x8e, 0x21, 0xb1, 0x04, 0x56, 0x85, 0x05, 0x0a, 0x8a, 0xa6, 0x4d, + 0xdd, 0x34, 0xf4, 0xe5, 0x3e, 0x71, 0x1c, 0xfa, 0xc0, 0xb9, 0x71, 0xa8, 0xf3, 0x70, 0xb2, 0xf5, 0x2e, 0xc7, 0x7b, + 0x7b, 0x9e, 0xea, 0xf4, 0x8b, 0xf0, 0xb8, 0xa9, 0x2f, 0x23, 0x77, 0xdf, 0x2b, 0x5e, 0x11, 0x21, 0x09, 0x7f, 0xad, + 0x16, 0xf7, 0x73, 0x08, 0x43, 0x7b, 0x61, 0x15, 0x83, 0x06, 0x78, 0xa9, 0xeb, 0x55, 0x97, 0x5f, 0xab, 0x15, 0x51, + 0xda, 0x2a, 0xb6, 0xce, 0x70, 0x92, 0xcf, 0xbd, 0x22, 0xf5, 0xa7, 0xb1, 0x96, 0x2f, 0x65, 0x40, 0x40, 0xcc, 0xa6, + 0x59, 0x66, 0x16, 0x63, 0x1d, 0x09, 0x06, 0xed, 0xbe, 0xd1, 0x59, 0x0b, 0x58, 0x66, 0x57, 0xe9, 0x46, 0x86, 0x9d, + 0xb5, 0x50, 0x60, 0x1a, 0x41, 0x54, 0x0a, 0x1a, 0xd5, 0x72, 0x4d, 0xde, 0x6f, 0xd7, 0x73, 0x2e, 0x71, 0x86, 0xb4, + 0x93, 0x4b, 0x42, 0x21, 0x91, 0xd5, 0x2a, 0x90, 0xf2, 0x9c, 0x4c, 0xb7, 0x93, 0xfc, 0x99, 0x45, 0xf2, 0x4f, 0x08, + 0xb5, 0xc8, 0x5f, 0xb9, 0x38, 0x7c, 0xae, 0x9d, 0x0b, 0x99, 0xa9, 0x3a, 0x9f, 0x12, 0x70, 0xa2, 0x55, 0x31, 0x5a, + 0x09, 0x2b, 0x6e, 0x61, 0x28, 0xf6, 0x09, 0x91, 0x6e, 0x48, 0x6c, 0x62, 0xc0, 0x5e, 0x19, 0x54, 0x83, 0xa9, 0x37, + 0xf9, 0xf4, 0x6c, 0x0e, 0x78, 0xf6, 0xfe, 0xfe, 0x78, 0xe8, 0xf9, 0x74, 0xfd, 0xe4, 0x5a, 0xb9, 0x9f, 0xb0, 0x6a, + 0xeb, 0xe0, 0x56, 0x33, 0x41, 0x61, 0xfe, 0x22, 0x8e, 0x5d, 0x65, 0x3e, 0x2b, 0x87, 0xd0, 0xc8, 0x3f, 0x80, 0xb6, + 0xd9, 0x94, 0x2d, 0xa8, 0x35, 0x2c, 0xf0, 0x23, 0x95, 0x81, 0x1a, 0xa6, 0x5b, 0xd8, 0xc7, 0x99, 0x6c, 0x40, 0x93, + 0x68, 0x73, 0xf5, 0x93, 0x5c, 0x93, 0x89, 0x02, 0x0d, 0x2d, 0x80, 0xff, 0x29, 0x92, 0x07, 0xba, 0x91, 0x72, 0x01, + 0x10, 0x34, 0x95, 0x78, 0x2a, 0x11, 0xe6, 0xba, 0xa5, 0xf7, 0xfd, 0xf9, 0x0e, 0x21, 0xd3, 0xd2, 0xfb, 0xf8, 0xb6, + 0x4c, 0xbd, 0x02, 0xb2, 0x40, 0x01, 0x98, 0x8f, 0x45, 0x81, 0x0a, 0x5f, 0x5e, 0x98, 0xe6, 0xd2, 0x84, 0xf4, 0x4b, + 0x8d, 0xdb, 0x0a, 0x6d, 0x4a, 0xb7, 0x9c, 0xaa, 0x37, 0x68, 0x58, 0xa9, 0xdd, 0x85, 0xda, 0xb7, 0x42, 0xc2, 0x08, + 0xcf, 0xef, 0x64, 0x6b, 0x33, 0x6e, 0xfe, 0x71, 0x35, 0x7f, 0x65, 0x65, 0x53, 0x7c, 0x96, 0x64, 0x34, 0x15, 0x4f, + 0xe8, 0x90, 0xa7, 0x10, 0xb3, 0x28, 0x70, 0x82, 0xf2, 0x5d, 0xcb, 0x6f, 0x27, 0xd7, 0x67, 0x05, 0x0a, 0x56, 0x16, + 0x28, 0x7f, 0x7d, 0x94, 0x41, 0xeb, 0xcb, 0xd5, 0x5e, 0xd3, 0xbd, 0xbd, 0xf7, 0x25, 0x9a, 0x34, 0x94, 0x12, 0x0a, + 0x8b, 0x69, 0x29, 0x95, 0x46, 0x47, 0x72, 0x77, 0xbd, 0xc2, 0x09, 0x60, 0x18, 0x86, 0xcd, 0x7b, 0x9e, 0x13, 0x91, + 0x8f, 0x56, 0x59, 0xbc, 0x76, 0x4e, 0x30, 0xdb, 0x70, 0x01, 0x0e, 0x0f, 0xa6, 0xb6, 0xf2, 0x16, 0x65, 0x65, 0x32, + 0x6c, 0x01, 0xc3, 0x39, 0x20, 0xcb, 0x93, 0x66, 0x88, 0x45, 0x81, 0x1b, 0xcd, 0x92, 0x73, 0xd0, 0x2b, 0xc7, 0x38, + 0xf3, 0xc7, 0x90, 0xfe, 0x5a, 0x39, 0xb2, 0x08, 0x61, 0x95, 0x98, 0x63, 0xa5, 0x12, 0x9c, 0x3d, 0xdf, 0xe4, 0x52, + 0x36, 0x44, 0x4d, 0xa5, 0xd4, 0x91, 0x2d, 0x50, 0xd1, 0xc1, 0x9f, 0x7b, 0x4c, 0x2b, 0x6e, 0x26, 0x6e, 0x06, 0x0c, + 0xf8, 0x89, 0xf0, 0x54, 0x30, 0x0a, 0x64, 0x06, 0xf7, 0x67, 0x5e, 0x65, 0xea, 0x36, 0x97, 0xdd, 0xb0, 0x46, 0xdc, + 0xd8, 0x46, 0x13, 0x97, 0x71, 0xbd, 0xf3, 0x92, 0x97, 0x0e, 0x55, 0x06, 0xb5, 0x30, 0x5c, 0xb0, 0x4c, 0x24, 0xb1, + 0x96, 0x3f, 0x54, 0x49, 0xd1, 0x45, 0x23, 0x4c, 0x25, 0x18, 0xef, 0xe4, 0x1e, 0xd0, 0x1c, 0xfe, 0x2e, 0x6e, 0x85, + 0xb5, 0xa3, 0xc6, 0x89, 0x2d, 0xe7, 0xb4, 0xa4, 0xfe, 0x5b, 0x48, 0x75, 0x59, 0x3d, 0xf3, 0xcf, 0xa5, 0x2c, 0x64, + 0x38, 0xab, 0x30, 0xf6, 0x44, 0x32, 0x76, 0x04, 0x7a, 0x9a, 0x49, 0xfc, 0xee, 0xea, 0x8c, 0x17, 0xa6, 0xa5, 0x9c, + 0x26, 0xb1, 0x37, 0x45, 0xb4, 0xdc, 0xfa, 0xbd, 0xb2, 0x1b, 0x01, 0x23, 0x90, 0x05, 0x84, 0x35, 0x67, 0x4f, 0x10, + 0xce, 0x6a, 0xb5, 0x76, 0x76, 0x4a, 0x4b, 0x27, 0x49, 0x09, 0x23, 0x83, 0x80, 0x2e, 0x10, 0x7c, 0x45, 0x86, 0x42, + 0xc8, 0xdf, 0x64, 0x66, 0x67, 0xe0, 0x6b, 0x3f, 0x7b, 0xeb, 0xd9, 0x5c, 0xcd, 0x6e, 0x5b, 0x04, 0x4d, 0x61, 0x3d, + 0x5e, 0x19, 0x70, 0x79, 0x73, 0x7f, 0x82, 0x07, 0xc0, 0xbd, 0xd3, 0xc4, 0x90, 0x8a, 0x86, 0xda, 0x42, 0xb1, 0x84, + 0xe2, 0xf4, 0xb5, 0x51, 0x99, 0x95, 0x68, 0x4f, 0xd6, 0x16, 0xa5, 0x31, 0x2b, 0x48, 0x96, 0xe7, 0x19, 0x2d, 0xc3, + 0xfb, 0x2b, 0xe9, 0x97, 0x52, 0xb8, 0xac, 0x7b, 0xdb, 0xcf, 0xa7, 0x44, 0x60, 0x8b, 0x50, 0xdf, 0x6c, 0x8b, 0x7d, + 0x94, 0x60, 0xc2, 0xb9, 0xd6, 0x42, 0xf1, 0xd7, 0x4d, 0x42, 0x11, 0x27, 0xfa, 0xc8, 0x4b, 0x81, 0xd8, 0x7c, 0x80, + 0x40, 0xd4, 0x6e, 0x76, 0x23, 0x13, 0x41, 0x1d, 0xa9, 0xc8, 0xc4, 0xea, 0x96, 0x92, 0x04, 0x33, 0xbd, 0x1b, 0x9d, + 0xd6, 0x72, 0xc9, 0x7a, 0x0d, 0x70, 0x23, 0xb9, 0x2e, 0xfc, 0x6c, 0xaa, 0x9f, 0x16, 0x27, 0x56, 0x6e, 0x60, 0x8f, + 0x15, 0x26, 0x0b, 0xf2, 0x21, 0xc1, 0xd9, 0x93, 0x49, 0x59, 0x92, 0xa6, 0x35, 0x05, 0x69, 0x02, 0x27, 0xac, 0x08, + 0x33, 0x01, 0xc4, 0x52, 0x56, 0x68, 0x03, 0xd2, 0xdb, 0x98, 0xfb, 0x67, 0xcc, 0xcb, 0x4f, 0x6b, 0xa2, 0x15, 0xb9, + 0xa2, 0xd4, 0x87, 0x4a, 0xbe, 0x81, 0x86, 0x40, 0xeb, 0x87, 0x3b, 0xd2, 0x04, 0x2d, 0x45, 0x39, 0xb2, 0xe5, 0x10, + 0x6e, 0x80, 0x13, 0x6d, 0xe7, 0xbd, 0x8a, 0xf0, 0x6e, 0x90, 0x26, 0x98, 0x5b, 0x74, 0xfd, 0x9c, 0x88, 0x0a, 0x2b, + 0x19, 0x13, 0x6d, 0x29, 0xe1, 0x50, 0x92, 0xa9, 0x20, 0x49, 0xaf, 0xd1, 0x07, 0x05, 0xb4, 0x1d, 0x9f, 0x26, 0xa5, + 0x09, 0x1c, 0xd7, 0x6a, 0x28, 0x34, 0xb3, 0x8e, 0x7b, 0xac, 0x16, 0xf7, 0x31, 0xc5, 0xb1, 0x32, 0x4c, 0x2e, 0xf6, + 0xf6, 0xbc, 0xb0, 0x9c, 0xb7, 0x17, 0xf7, 0x11, 0xe6, 0xcb, 0xa5, 0x27, 0xc1, 0x0a, 0xd1, 0x72, 0x19, 0xda, 0x60, + 0xc9, 0x6a, 0xe8, 0x36, 0xed, 0x0a, 0x32, 0x95, 0x02, 0x70, 0x0a, 0x10, 0xd6, 0x88, 0x17, 0x6a, 0xf7, 0x5e, 0x08, + 0xee, 0xa8, 0x5a, 0xd2, 0x8b, 0x6b, 0xcd, 0xbe, 0xc5, 0xb8, 0x7a, 0x71, 0x9f, 0x84, 0x39, 0xdf, 0xdb, 0xdb, 0xc9, + 0xb4, 0x88, 0xfc, 0x00, 0xa2, 0xec, 0x83, 0x94, 0x2c, 0x6a, 0x40, 0x7b, 0x37, 0x56, 0x9d, 0x01, 0x05, 0x45, 0xe9, + 0x6d, 0x35, 0xed, 0x2a, 0x59, 0x10, 0x45, 0x23, 0xac, 0x83, 0xc1, 0x5d, 0xb0, 0xec, 0x0b, 0x32, 0x7f, 0x21, 0x8a, + 0x1c, 0xeb, 0x5f, 0x37, 0x66, 0x56, 0xfb, 0xbe, 0x1f, 0xa6, 0x23, 0x19, 0xcb, 0x30, 0x61, 0x58, 0x49, 0xfc, 0x07, + 0x1a, 0x4c, 0x6b, 0xe2, 0x5e, 0x31, 0x57, 0x9f, 0x28, 0xf0, 0x8d, 0x6a, 0x63, 0xee, 0x92, 0x3c, 0xdd, 0xe8, 0x65, + 0x50, 0x90, 0x7c, 0xf8, 0xad, 0x90, 0x1c, 0x6a, 0x48, 0x14, 0x79, 0xac, 0xe0, 0x6c, 0x0b, 0x2e, 0x9e, 0x8a, 0x15, + 0x9c, 0x6d, 0xc7, 0xad, 0xc1, 0xd4, 0x37, 0xdb, 0xe0, 0xb3, 0x78, 0x83, 0x02, 0xb4, 0x2c, 0xb0, 0xa0, 0x3c, 0x5a, + 0xd5, 0xbd, 0x14, 0x2b, 0x05, 0x61, 0x2a, 0x88, 0xc7, 0xaa, 0x07, 0xa0, 0xd4, 0x46, 0x2d, 0xc3, 0x97, 0x05, 0x53, + 0x64, 0xb9, 0x04, 0xaa, 0xa9, 0x2b, 0x40, 0x4e, 0xda, 0xdb, 0x3e, 0xdd, 0xdb, 0x03, 0xdb, 0x00, 0x94, 0x38, 0x7f, + 0x10, 0x4e, 0xc5, 0x2c, 0x05, 0x55, 0x2a, 0x33, 0xbf, 0xa1, 0x18, 0x6e, 0x81, 0xc8, 0x32, 0xf8, 0x01, 0x05, 0xd3, + 0x30, 0xcb, 0xd8, 0x5c, 0x95, 0xe9, 0xdf, 0x98, 0x13, 0x43, 0xca, 0x99, 0xd2, 0x09, 0x13, 0xd4, 0x4e, 0x34, 0x9d, + 0x56, 0xd1, 0xf6, 0x6c, 0x4e, 0x13, 0xf1, 0x82, 0x65, 0x82, 0x26, 0xb0, 0xfc, 0x92, 0xe2, 0x60, 0x45, 0x19, 0x82, + 0x03, 0x5b, 0xe9, 0x15, 0x46, 0xd1, 0xbd, 0x5d, 0x44, 0x55, 0x07, 0x1a, 0x87, 0x49, 0x14, 0xab, 0x49, 0xec, 0x7c, + 0x46, 0x93, 0xc3, 0x59, 0xb4, 0xb4, 0xf3, 0x69, 0x4a, 0x65, 0x43, 0x72, 0x77, 0x8f, 0x11, 0x23, 0x09, 0x8c, 0xf4, + 0xbc, 0x57, 0x6b, 0x81, 0x88, 0xf7, 0x96, 0x4d, 0xb0, 0x57, 0x82, 0x85, 0xc5, 0x51, 0xfd, 0x2a, 0x9c, 0x86, 0x6e, + 0x7e, 0xd9, 0x78, 0xa5, 0x6d, 0x93, 0x70, 0x90, 0x74, 0x72, 0xbc, 0xdd, 0xb2, 0x7a, 0x69, 0x24, 0x87, 0x91, 0x16, + 0xec, 0xa1, 0x8c, 0x19, 0x2d, 0x0c, 0x79, 0x21, 0x73, 0x14, 0x77, 0x05, 0xf9, 0x00, 0x77, 0x86, 0x9e, 0x8b, 0x49, + 0xbc, 0x72, 0x35, 0xa6, 0xbd, 0x5b, 0x68, 0xff, 0xbb, 0xc2, 0x7b, 0x87, 0xdf, 0x42, 0x60, 0xf7, 0xa7, 0xb2, 0xf9, + 0x7a, 0x40, 0xf7, 0xa7, 0x12, 0x41, 0x3f, 0x05, 0x6b, 0xed, 0xac, 0x40, 0x6e, 0xcb, 0x3f, 0xf1, 0x1b, 0xae, 0xd1, + 0x96, 0x7e, 0x55, 0x61, 0x24, 0x95, 0x69, 0x29, 0xcf, 0x03, 0x2e, 0xf3, 0xd4, 0x20, 0x5f, 0xae, 0x6a, 0x21, 0x51, + 0x9d, 0x61, 0xa8, 0x74, 0xf8, 0x6d, 0xdb, 0xa3, 0x65, 0x4c, 0xa2, 0xec, 0x8c, 0x37, 0x61, 0x2a, 0x76, 0xe1, 0x94, + 0xf1, 0xb5, 0x7b, 0x78, 0x63, 0x02, 0x1e, 0xb4, 0x87, 0x4d, 0x61, 0x19, 0xdb, 0x99, 0xba, 0x07, 0x64, 0x8f, 0x4f, + 0xb8, 0xd1, 0xdd, 0xaa, 0x56, 0xc6, 0x1b, 0xb0, 0xff, 0x11, 0x1e, 0x9b, 0xcb, 0x71, 0x54, 0x73, 0x60, 0x1a, 0x2c, + 0xf2, 0xc2, 0x29, 0xc0, 0x95, 0xf2, 0x96, 0x22, 0xcc, 0x73, 0x19, 0xe0, 0xfe, 0x16, 0x7f, 0xa7, 0x59, 0xe2, 0xb0, + 0xe0, 0x38, 0xb7, 0x0f, 0xe5, 0x88, 0x0a, 0xfc, 0x22, 0x7e, 0x0f, 0x74, 0x2c, 0x29, 0x34, 0x37, 0x54, 0xf4, 0x94, + 0xeb, 0x85, 0x6c, 0x4d, 0x4b, 0xc5, 0xb4, 0x48, 0xa9, 0x91, 0xd3, 0x6c, 0xc8, 0xe3, 0x34, 0x56, 0xb6, 0x28, 0x4e, + 0x55, 0x65, 0x5e, 0xb4, 0x05, 0x8b, 0x65, 0x68, 0x71, 0xb9, 0xf4, 0xaa, 0xa8, 0x26, 0xcc, 0x8a, 0x64, 0x20, 0xcc, + 0xac, 0x8c, 0x8a, 0x8a, 0x66, 0xad, 0xfa, 0x78, 0x68, 0x35, 0xa1, 0xc8, 0xe8, 0xe6, 0x15, 0x38, 0x6c, 0x17, 0x82, + 0xea, 0x6e, 0xfb, 0x14, 0xb0, 0x5a, 0x5d, 0x31, 0x91, 0x85, 0xa1, 0x5f, 0x8b, 0x54, 0xd9, 0x32, 0xa7, 0x75, 0x03, + 0x7e, 0xd1, 0x3d, 0xc9, 0xb2, 0x1a, 0x75, 0xeb, 0xf5, 0x56, 0xb2, 0xd1, 0x53, 0xbe, 0x2d, 0xd9, 0xa8, 0xa2, 0xed, + 0xee, 0x34, 0xd0, 0xfd, 0x69, 0xa9, 0x6a, 0xae, 0xcd, 0x4d, 0x7e, 0xc3, 0x74, 0x4d, 0xa0, 0x4d, 0x85, 0x66, 0xc3, + 0x55, 0x2e, 0xf2, 0x7c, 0x58, 0x5c, 0x26, 0x90, 0xb9, 0x3b, 0x43, 0x45, 0xff, 0xda, 0x6a, 0x94, 0xd7, 0x71, 0xbd, + 0x6f, 0xc9, 0x28, 0xe6, 0xd7, 0x61, 0xfc, 0x0e, 0xe6, 0x2b, 0x2b, 0x9f, 0xdf, 0x45, 0x69, 0x28, 0xa8, 0xe6, 0x2e, + 0x25, 0x0c, 0xdf, 0x5a, 0x30, 0x7c, 0xab, 0xf8, 0x74, 0xd9, 0x1f, 0x2f, 0x5e, 0x14, 0x03, 0x04, 0xc3, 0xdc, 0xb0, + 0x8c, 0x4b, 0xb1, 0x79, 0x8e, 0x55, 0x16, 0x76, 0x59, 0xb0, 0xb0, 0x4b, 0xe1, 0xad, 0x0e, 0xe5, 0x79, 0xdf, 0x6d, + 0x1e, 0x65, 0x9d, 0xb3, 0x7d, 0x57, 0x1e, 0xfc, 0xef, 0x82, 0x7b, 0xfb, 0x58, 0x5c, 0xee, 0xc0, 0x3f, 0x90, 0xe9, + 0x2a, 0x0a, 0xe4, 0xe7, 0x90, 0x76, 0x20, 0x48, 0xc7, 0xba, 0x73, 0x50, 0xca, 0x29, 0x93, 0x08, 0xe4, 0x0d, 0x66, + 0x99, 0xe0, 0x13, 0x3d, 0x66, 0xa6, 0xaf, 0x19, 0xc9, 0x4a, 0x70, 0x45, 0xcb, 0x68, 0x7b, 0x50, 0xbd, 0xc8, 0xb5, + 0xf8, 0xc8, 0x92, 0x28, 0xc8, 0xb0, 0x96, 0x22, 0x59, 0x90, 0xe4, 0xc4, 0x24, 0x1b, 0xaf, 0xd7, 0xe1, 0x21, 0x4b, + 0x58, 0x36, 0xa6, 0xa9, 0xc7, 0xd1, 0x62, 0xdb, 0x64, 0x1c, 0x02, 0x32, 0x6a, 0x32, 0xfc, 0x7d, 0x79, 0xe1, 0xcf, + 0x87, 0xd1, 0xc0, 0x0f, 0x34, 0xa1, 0x62, 0xcc, 0x23, 0x48, 0x4c, 0xf1, 0xa3, 0xe2, 0x46, 0xd3, 0xde, 0xde, 0x8e, + 0xe7, 0x4a, 0xb7, 0x04, 0x5c, 0xfd, 0xb6, 0x6b, 0x50, 0x77, 0x01, 0xd7, 0x73, 0xca, 0xa9, 0x29, 0x5a, 0xd0, 0xd5, + 0x9b, 0x2c, 0xc2, 0xff, 0x48, 0xef, 0x70, 0x8a, 0xf2, 0x3c, 0x50, 0x50, 0xbb, 0x43, 0x46, 0xe3, 0xc8, 0xc5, 0x1f, + 0xe9, 0x5d, 0x50, 0xdc, 0x16, 0x97, 0x97, 0x9b, 0xe5, 0x06, 0xba, 0xfc, 0x26, 0x71, 0x71, 0x39, 0x49, 0xb0, 0xc8, + 0x31, 0x4f, 0xd9, 0x08, 0x88, 0xf3, 0x5b, 0x7a, 0x17, 0xa8, 0xf1, 0x98, 0x75, 0x59, 0x0f, 0x2d, 0x0c, 0xea, 0x7d, + 0xab, 0xd8, 0xde, 0x06, 0x6d, 0x50, 0xf4, 0x64, 0xdf, 0x3e, 0xa9, 0xb4, 0x2b, 0xcd, 0x43, 0x84, 0xf2, 0x87, 0x2e, + 0x05, 0x7f, 0x6d, 0x8b, 0x36, 0x51, 0x49, 0x7d, 0x5d, 0xe9, 0x44, 0xa1, 0x43, 0x99, 0xeb, 0x71, 0xe9, 0xa5, 0xe6, + 0xd4, 0xe9, 0x3b, 0x08, 0x96, 0x23, 0xec, 0x6b, 0xa1, 0x07, 0x0d, 0xbe, 0x57, 0x29, 0x21, 0x65, 0x24, 0xe9, 0x65, + 0xd9, 0xcf, 0xb9, 0xf4, 0x00, 0xef, 0x90, 0xd2, 0x12, 0xca, 0xeb, 0x98, 0xb9, 0x49, 0x17, 0xfd, 0x41, 0x10, 0x6f, + 0x61, 0x96, 0x10, 0xa4, 0x36, 0x16, 0x45, 0x0e, 0x54, 0xa8, 0xe9, 0x4b, 0x65, 0x00, 0xb2, 0xa1, 0xc7, 0xd6, 0xa4, + 0x66, 0x22, 0xa5, 0xa6, 0x6f, 0x61, 0x7c, 0x8b, 0x94, 0xa4, 0x12, 0x19, 0x52, 0x89, 0x94, 0x42, 0x4f, 0x6f, 0xae, + 0x26, 0x21, 0x7b, 0x43, 0x8b, 0xeb, 0x73, 0x6a, 0xcf, 0x93, 0x0a, 0x58, 0x9e, 0x1c, 0x07, 0xe5, 0x01, 0x2c, 0x89, + 0xaa, 0x06, 0xb9, 0x71, 0xe7, 0xa4, 0x26, 0xbf, 0xd5, 0xe3, 0xbe, 0x59, 0x16, 0x31, 0x28, 0xf1, 0xc6, 0x68, 0x91, + 0x7a, 0x63, 0x9c, 0x40, 0x3e, 0x22, 0xcf, 0x0b, 0xf8, 0xa9, 0xbd, 0x1b, 0x95, 0x6c, 0xe5, 0xcd, 0x57, 0xfc, 0x40, + 0x99, 0x17, 0x90, 0xa3, 0x89, 0x53, 0xc3, 0x53, 0x52, 0x4f, 0xde, 0xb5, 0xb3, 0xb6, 0xed, 0x27, 0x9d, 0xa2, 0xa3, + 0x01, 0xfb, 0x41, 0x78, 0x0b, 0x6b, 0x15, 0xf6, 0x5d, 0x6e, 0x7d, 0xe5, 0x4f, 0x07, 0xfb, 0xca, 0x24, 0x52, 0x2f, + 0x23, 0x2b, 0x12, 0xe7, 0xfe, 0x5c, 0xcb, 0x5f, 0x66, 0x34, 0xbd, 0xbb, 0xa0, 0x90, 0xeb, 0xcc, 0xe1, 0xae, 0x6f, + 0xb9, 0x0d, 0x65, 0x9e, 0x7a, 0x37, 0x91, 0xca, 0x4a, 0x5e, 0xbd, 0x04, 0xb8, 0x7a, 0x45, 0x30, 0x97, 0xd1, 0x46, + 0xcb, 0x11, 0xa3, 0x4e, 0x0b, 0xdd, 0x7a, 0x79, 0x92, 0xb6, 0x19, 0xf8, 0xd7, 0x4a, 0x4c, 0xeb, 0x60, 0x01, 0xe6, + 0xf6, 0x85, 0xd4, 0x5e, 0xd6, 0x5f, 0xf5, 0xca, 0x40, 0x11, 0x84, 0xef, 0x92, 0xed, 0x4b, 0xdd, 0x94, 0x35, 0xbb, + 0x7d, 0xa9, 0x95, 0xa0, 0x9f, 0x4c, 0xf9, 0xc1, 0x7a, 0x9e, 0xe2, 0xf2, 0x32, 0xcb, 0x73, 0x94, 0x03, 0x78, 0x3f, + 0xb6, 0x3d, 0xef, 0x47, 0x9d, 0x34, 0xe8, 0x43, 0x2c, 0xf6, 0x22, 0xe6, 0x86, 0x89, 0x97, 0xf3, 0xff, 0xb8, 0x36, + 0xff, 0x8f, 0xd6, 0x95, 0x53, 0x30, 0x8d, 0x46, 0x09, 0x8d, 0x0c, 0xeb, 0x44, 0x8a, 0x00, 0xa5, 0xde, 0x96, 0x09, + 0xf2, 0xf1, 0x2a, 0x00, 0x8d, 0x6b, 0x31, 0xe4, 0x89, 0xa8, 0x0f, 0xc3, 0x09, 0x8b, 0xef, 0x82, 0x19, 0xab, 0x4f, + 0x78, 0xc2, 0xb3, 0x69, 0x38, 0xa0, 0x38, 0xbb, 0xcb, 0x04, 0x9d, 0xd4, 0x67, 0x0c, 0x3f, 0xa7, 0xf1, 0x9c, 0x0a, + 0x36, 0x08, 0xb1, 0x7b, 0x96, 0xb2, 0x30, 0x76, 0x5e, 0x85, 0x69, 0xca, 0x6f, 0x5c, 0xfc, 0x96, 0x5f, 0x73, 0xc1, + 0xf1, 0xeb, 0xdb, 0xbb, 0x11, 0x4d, 0xf0, 0xfb, 0xeb, 0x59, 0x22, 0x66, 0x38, 0x0b, 0x93, 0xac, 0x9e, 0xd1, 0x94, + 0x0d, 0xdb, 0x03, 0x1e, 0xf3, 0xb4, 0x0e, 0x29, 0xdb, 0x13, 0x1a, 0xc4, 0x6c, 0x34, 0x16, 0x4e, 0x14, 0xa6, 0x1f, + 0xdb, 0xf5, 0xfa, 0x34, 0x65, 0x93, 0x30, 0xbd, 0xab, 0xcb, 0x16, 0xc1, 0x97, 0x8d, 0x83, 0xf0, 0xf1, 0xf0, 0xb0, + 0x2d, 0xd2, 0x30, 0xc9, 0x18, 0x6c, 0x53, 0x10, 0xc6, 0xb1, 0x73, 0x70, 0xd4, 0x98, 0x64, 0x3b, 0x2a, 0x90, 0x17, + 0x26, 0x22, 0xbf, 0xc2, 0x1f, 0x01, 0x6e, 0xff, 0x5a, 0x24, 0xf8, 0x7a, 0x26, 0x04, 0x4f, 0x16, 0x83, 0x59, 0x9a, + 0xf1, 0x34, 0x98, 0x72, 0x96, 0x08, 0x9a, 0xb6, 0xaf, 0x79, 0x1a, 0xd1, 0xb4, 0x9e, 0x86, 0x11, 0x9b, 0x65, 0xc1, + 0xe1, 0xf4, 0xb6, 0x0d, 0x9a, 0xc5, 0x28, 0xe5, 0xb3, 0x24, 0xd2, 0x73, 0xb1, 0x64, 0x4c, 0x53, 0x26, 0xec, 0x0a, + 0xf9, 0x0a, 0x93, 0x20, 0x66, 0x09, 0x0d, 0xd3, 0xfa, 0x08, 0x3a, 0x83, 0x59, 0xd4, 0x88, 0xe8, 0x08, 0xa7, 0xa3, + 0xeb, 0xd0, 0x6b, 0xb6, 0x1e, 0x61, 0xf3, 0xbf, 0x7f, 0x84, 0x9c, 0xc6, 0xe6, 0xe2, 0x66, 0xa3, 0xf1, 0x27, 0xd4, + 0x5e, 0x99, 0x45, 0x02, 0x14, 0x34, 0xa7, 0xb7, 0x4e, 0xc6, 0x21, 0xa7, 0x6d, 0x53, 0xcf, 0xf6, 0x34, 0x8c, 0x20, + 0x21, 0x38, 0x68, 0x4d, 0x6f, 0x73, 0x58, 0x5d, 0xa0, 0x92, 0x4c, 0xf5, 0x22, 0xf5, 0xd3, 0xe2, 0xb7, 0x42, 0x7c, + 0xb2, 0x19, 0xe2, 0x96, 0x81, 0xb8, 0xc4, 0x7a, 0x3d, 0x9a, 0xa5, 0x32, 0xb6, 0x1a, 0x34, 0x33, 0x05, 0xc8, 0x98, + 0xcf, 0x69, 0x6a, 0xe0, 0x90, 0x0f, 0xbf, 0x19, 0x8c, 0xd6, 0x66, 0x30, 0x4e, 0x3e, 0x05, 0x46, 0x9a, 0x44, 0x8b, + 0xea, 0xbe, 0x36, 0x53, 0x3a, 0x69, 0x8f, 0x29, 0xd0, 0x53, 0xd0, 0x82, 0xdf, 0x37, 0x2c, 0x12, 0x63, 0xf5, 0x53, + 0x92, 0xf3, 0x8d, 0xaa, 0x3b, 0x6a, 0x34, 0xd4, 0x73, 0xc6, 0x7e, 0xa5, 0x41, 0xd3, 0x87, 0x06, 0xf9, 0x15, 0xfe, + 0x5b, 0x71, 0x99, 0xb7, 0xca, 0x3d, 0xf1, 0xb7, 0xf6, 0x2d, 0x5f, 0x2b, 0x49, 0xb1, 0xbc, 0x11, 0x8d, 0x53, 0x23, + 0x2b, 0x95, 0xf0, 0x01, 0xb7, 0x9d, 0x3c, 0x4f, 0x84, 0x75, 0x8a, 0x5b, 0x9c, 0xac, 0xfb, 0xad, 0xca, 0xbb, 0x08, + 0x20, 0xd2, 0x61, 0x25, 0x1b, 0xf2, 0x76, 0xd2, 0x21, 0x8d, 0x76, 0x52, 0xaf, 0x23, 0x8f, 0x93, 0xb4, 0x97, 0xe8, + 0xf4, 0x3c, 0x8f, 0x75, 0xb9, 0x34, 0xb6, 0x33, 0x14, 0x70, 0xb8, 0x6a, 0xba, 0x5c, 0x96, 0x61, 0x00, 0x26, 0xaf, + 0x6b, 0xfc, 0x4d, 0xe8, 0x06, 0x38, 0xb3, 0x38, 0x79, 0x62, 0x5e, 0xec, 0x92, 0x1a, 0x5e, 0x11, 0xf3, 0x81, 0xc4, + 0x9c, 0x3f, 0x0d, 0xc5, 0x18, 0xbc, 0x14, 0x85, 0xf8, 0x29, 0x93, 0x98, 0xdc, 0x7d, 0x17, 0x75, 0xd3, 0x22, 0xc3, + 0x0d, 0x32, 0xf9, 0xd2, 0x1c, 0x46, 0xf9, 0x4e, 0x10, 0x18, 0x11, 0x7f, 0x43, 0x94, 0x4d, 0x67, 0x2c, 0xba, 0xe1, + 0x43, 0x2d, 0x3a, 0x9a, 0x08, 0x26, 0x73, 0xb7, 0x4d, 0xc4, 0x61, 0x1c, 0x66, 0x97, 0x03, 0x75, 0x57, 0x32, 0x2b, + 0x6f, 0x06, 0x84, 0x12, 0x7a, 0x65, 0xa4, 0xd1, 0x54, 0xda, 0xa3, 0x3f, 0x8a, 0xad, 0xf6, 0x49, 0x7a, 0x9f, 0x7d, + 0x52, 0x2c, 0x3c, 0xe3, 0xb3, 0x74, 0x00, 0xe1, 0x48, 0x2d, 0xf5, 0xd6, 0x1d, 0x37, 0xae, 0x54, 0x31, 0x5c, 0x2c, + 0xac, 0x4c, 0x50, 0x81, 0x99, 0xfd, 0x52, 0x09, 0x2a, 0x43, 0x5e, 0xea, 0xbe, 0x86, 0x16, 0x71, 0x66, 0x49, 0x20, + 0xb3, 0x23, 0x99, 0xd4, 0xe8, 0x25, 0xa4, 0x93, 0xf8, 0xb3, 0x84, 0xfd, 0x32, 0xa3, 0x97, 0x0c, 0x74, 0x4d, 0xe6, + 0xb3, 0x48, 0xc6, 0x9a, 0x40, 0xf6, 0xd5, 0x9b, 0x10, 0xbc, 0x60, 0x91, 0xda, 0x98, 0x44, 0x56, 0xea, 0xdc, 0x26, + 0xb7, 0xee, 0x82, 0xbf, 0x18, 0xb4, 0x03, 0x86, 0x23, 0x3e, 0x09, 0x59, 0x12, 0x48, 0x97, 0x6f, 0x31, 0x58, 0x00, + 0xad, 0x31, 0x8b, 0x82, 0x44, 0x6f, 0x4f, 0x13, 0xf9, 0x1f, 0x38, 0x4b, 0x64, 0xd7, 0xbc, 0xcd, 0x25, 0x42, 0x15, + 0xfa, 0x88, 0x41, 0xf0, 0x99, 0x92, 0x6b, 0x1c, 0x61, 0xbb, 0xba, 0xb8, 0x76, 0x5e, 0xd9, 0x81, 0xc6, 0xca, 0x46, + 0x29, 0x23, 0x80, 0xaf, 0x96, 0x66, 0x3c, 0x15, 0x9e, 0x37, 0xc6, 0x31, 0x22, 0x9d, 0xb1, 0x74, 0x76, 0x9d, 0xc6, + 0xf2, 0x4f, 0xb7, 0xde, 0x0c, 0x9a, 0x85, 0xf9, 0x5e, 0xb9, 0x0d, 0xac, 0x92, 0xa3, 0xf4, 0x8d, 0x52, 0xb9, 0x8c, + 0xe2, 0xb7, 0x5a, 0x6a, 0xf9, 0x5c, 0x2c, 0x17, 0xeb, 0xe3, 0xa6, 0x44, 0x95, 0x57, 0x01, 0x42, 0x06, 0x8b, 0xb6, + 0x4c, 0x85, 0xf2, 0x72, 0xdd, 0x85, 0x2a, 0x79, 0xa5, 0x44, 0xf4, 0xe5, 0xee, 0x22, 0xd5, 0x33, 0xe6, 0x57, 0xcc, + 0x38, 0x99, 0xaa, 0x24, 0x97, 0x6b, 0x8c, 0x58, 0x7a, 0xe8, 0xa6, 0x66, 0x0a, 0x96, 0x3b, 0x92, 0x6e, 0xa4, 0x5b, + 0x5f, 0x3d, 0xd2, 0x94, 0x94, 0xe1, 0xae, 0xb5, 0x01, 0x20, 0x57, 0x6f, 0x13, 0x60, 0x60, 0xb6, 0x66, 0xc2, 0x2c, + 0x01, 0xb4, 0xb1, 0x21, 0x85, 0x8b, 0x34, 0x57, 0xbb, 0x8b, 0xef, 0x44, 0xbe, 0x6f, 0x35, 0x95, 0xbf, 0x59, 0x04, + 0x7f, 0x41, 0x02, 0x2e, 0x94, 0x52, 0x1a, 0xb8, 0x6f, 0x5e, 0x5f, 0xbc, 0x73, 0xf1, 0x35, 0x8f, 0xee, 0x02, 0x57, + 0xa4, 0x33, 0xea, 0xe6, 0xc8, 0x17, 0x63, 0x9a, 0x14, 0x2f, 0xe3, 0xe1, 0x31, 0xf5, 0x63, 0x3e, 0x52, 0x97, 0x32, + 0x57, 0x8d, 0xe4, 0xc1, 0xd5, 0xa9, 0x7c, 0xc9, 0x54, 0xe7, 0x54, 0xa8, 0xd7, 0x7b, 0x89, 0x14, 0x7e, 0x76, 0x20, + 0x84, 0x72, 0xba, 0x2f, 0xc6, 0xf2, 0xe1, 0x02, 0x0e, 0x8c, 0x7c, 0xda, 0x5d, 0xac, 0x11, 0x53, 0x17, 0x86, 0x18, + 0x77, 0xd4, 0x12, 0x32, 0xd9, 0xea, 0x2a, 0x18, 0x5c, 0x5d, 0xe5, 0xa7, 0xfb, 0x30, 0xd6, 0xbe, 0x19, 0x17, 0x20, + 0x34, 0xfd, 0x0b, 0x02, 0x83, 0x97, 0x0d, 0xa5, 0xa4, 0x03, 0x43, 0xc0, 0xbc, 0x51, 0x07, 0x16, 0x09, 0x04, 0x06, + 0xbd, 0xa3, 0xa2, 0x44, 0x9e, 0x58, 0x55, 0xb4, 0x0d, 0x02, 0xd5, 0xb0, 0xa4, 0x7b, 0xe5, 0x4d, 0x2d, 0xf7, 0xd7, + 0x80, 0x14, 0xd9, 0xd0, 0x5d, 0x21, 0xf8, 0x2b, 0x21, 0x3b, 0xdd, 0x57, 0x78, 0xb8, 0xb2, 0x5f, 0x6d, 0xa2, 0x5e, + 0x3b, 0x50, 0x60, 0xab, 0x97, 0x09, 0xfc, 0x51, 0xe0, 0x8f, 0x57, 0xb2, 0xa9, 0x11, 0x46, 0xa0, 0x25, 0x81, 0xd0, + 0x6e, 0x18, 0xad, 0x63, 0xc0, 0xe3, 0x38, 0x9c, 0x66, 0x34, 0x30, 0x3f, 0xb4, 0x5c, 0x02, 0xf1, 0xb6, 0xae, 0x08, + 0xe8, 0xf4, 0x9a, 0x73, 0x50, 0x17, 0xd6, 0xb5, 0x94, 0x79, 0x98, 0x7a, 0xf5, 0xfa, 0xa0, 0x7e, 0x3d, 0x42, 0xb9, + 0x18, 0x2f, 0x6c, 0xa9, 0x76, 0xdc, 0x68, 0xb4, 0x21, 0x17, 0xb2, 0x1e, 0xc6, 0x6c, 0x94, 0x04, 0x31, 0x1d, 0x8a, + 0x5c, 0xc0, 0x2d, 0xb5, 0x85, 0x51, 0x23, 0xfc, 0xd6, 0x51, 0x4a, 0x27, 0x8e, 0x0f, 0xff, 0xde, 0x3f, 0x71, 0x2e, + 0xa2, 0x20, 0x11, 0xe3, 0xba, 0xcc, 0xba, 0x85, 0x3b, 0x03, 0x62, 0x5c, 0x79, 0x5e, 0x58, 0x13, 0x0d, 0x28, 0xa8, + 0x58, 0xb9, 0x48, 0x1d, 0x31, 0xc6, 0x22, 0xb5, 0xdb, 0x25, 0x68, 0xb1, 0xb6, 0x82, 0x75, 0x49, 0x7f, 0x80, 0xf2, + 0x4c, 0x2a, 0xc6, 0xeb, 0x8d, 0x8d, 0xba, 0x54, 0x7d, 0x5a, 0x43, 0x9f, 0xa5, 0xd8, 0xe5, 0xca, 0xb1, 0xbc, 0x50, + 0x3d, 0x1e, 0x82, 0xcc, 0x8a, 0xca, 0x89, 0xed, 0x1e, 0x28, 0x67, 0xc9, 0x74, 0x26, 0x7a, 0xd2, 0xa9, 0x9d, 0xc2, + 0x05, 0x89, 0x3e, 0xb6, 0x4a, 0x00, 0x07, 0xfd, 0x85, 0x02, 0x66, 0x10, 0xc6, 0x03, 0x0f, 0x20, 0x72, 0xea, 0xce, + 0x49, 0x4a, 0x27, 0xa8, 0x3d, 0x61, 0x49, 0x5d, 0xd5, 0x1d, 0x59, 0x6a, 0x89, 0xff, 0x08, 0x9e, 0x72, 0x5f, 0x8e, + 0x86, 0x65, 0xee, 0xea, 0x06, 0x5c, 0x5e, 0xf5, 0xf3, 0xbc, 0x9d, 0x0a, 0xaf, 0xf7, 0xd2, 0x43, 0x7d, 0xfc, 0x8d, + 0xf5, 0x72, 0x16, 0xd7, 0x1c, 0x15, 0x17, 0xb7, 0xd0, 0x96, 0x26, 0xf6, 0x59, 0x90, 0xcd, 0xbe, 0x21, 0xd0, 0xf0, + 0xb9, 0xe7, 0xd2, 0x6c, 0x5a, 0x57, 0xbc, 0xab, 0x2e, 0x49, 0xd6, 0x85, 0xae, 0x48, 0x7b, 0x6a, 0x7f, 0x14, 0x0b, + 0xc9, 0x96, 0xf4, 0x25, 0x0d, 0xe5, 0x4c, 0xe8, 0x17, 0x97, 0x7a, 0xf4, 0xb3, 0x7d, 0x8d, 0x07, 0x55, 0xf8, 0xc9, + 0xd5, 0x59, 0x95, 0xc7, 0x01, 0x5f, 0x2a, 0x5e, 0x60, 0x17, 0xc6, 0x31, 0x4c, 0x78, 0x65, 0xd4, 0x17, 0xfb, 0xa5, + 0x1f, 0x3d, 0xd1, 0xf7, 0x50, 0xae, 0xcf, 0xe9, 0x13, 0xa9, 0x52, 0x5a, 0x6f, 0xcd, 0xdb, 0x11, 0x26, 0x58, 0xa4, + 0xa4, 0x2f, 0x83, 0x70, 0x77, 0x25, 0x2f, 0xba, 0x5d, 0xf2, 0x2e, 0xa5, 0x90, 0x3a, 0x72, 0x41, 0xc4, 0x4d, 0x93, + 0xc8, 0x75, 0xfe, 0x32, 0x88, 0xd9, 0xe0, 0x23, 0x71, 0x77, 0x17, 0x1e, 0x5a, 0xbf, 0xf6, 0x28, 0xb9, 0x82, 0x61, + 0xd8, 0xa8, 0xea, 0x48, 0x4f, 0x7c, 0x8b, 0x17, 0xab, 0xb7, 0xe2, 0xb8, 0x9d, 0xdd, 0x05, 0x30, 0x1e, 0x35, 0x4f, + 0xe7, 0x2a, 0xbf, 0x2c, 0xdf, 0x75, 0x55, 0x42, 0x01, 0x68, 0x56, 0xe5, 0x8e, 0x24, 0x2a, 0xe2, 0x7e, 0x92, 0xd2, + 0x5c, 0x47, 0x31, 0x35, 0x80, 0x53, 0x68, 0xfe, 0xe6, 0x3a, 0x7f, 0x29, 0xca, 0x68, 0xe1, 0xd1, 0x90, 0x29, 0x19, + 0xc4, 0x85, 0xb9, 0xc0, 0x8c, 0xf5, 0x23, 0x2a, 0x42, 0x16, 0xab, 0x2e, 0x6d, 0x63, 0x80, 0xaf, 0xac, 0x68, 0xb9, + 0xcc, 0xaa, 0x6b, 0x61, 0x55, 0x0c, 0xca, 0x95, 0x9d, 0xee, 0x97, 0x70, 0xcb, 0x95, 0xc9, 0x33, 0x69, 0x87, 0x06, + 0xcb, 0x15, 0xaa, 0x3a, 0xe7, 0x2f, 0x03, 0x79, 0x6d, 0x08, 0x00, 0xe4, 0x1a, 0x40, 0x08, 0x5a, 0xab, 0x6b, 0x31, + 0x5e, 0x4c, 0xb8, 0x2f, 0xc2, 0x74, 0x44, 0xc5, 0x0a, 0x62, 0x63, 0x95, 0xa3, 0xda, 0x36, 0x01, 0xea, 0x35, 0x68, + 0xc3, 0x2a, 0xb4, 0x57, 0x80, 0xf4, 0xee, 0xee, 0x82, 0xe5, 0x64, 0x77, 0x41, 0x93, 0x01, 0x8f, 0xe8, 0xfb, 0xb7, + 0xdf, 0xc0, 0x25, 0x47, 0x9e, 0x80, 0x61, 0x31, 0x46, 0x20, 0x38, 0xe5, 0xe6, 0x28, 0x11, 0xc2, 0xa5, 0x08, 0x51, + 0x9c, 0xc0, 0x91, 0x73, 0x49, 0x10, 0x73, 0xd7, 0xe9, 0x2a, 0xc8, 0x69, 0xa4, 0x60, 0x26, 0x89, 0xec, 0xc5, 0xf3, + 0xd3, 0x7d, 0xd5, 0x5a, 0x89, 0x00, 0xd5, 0x08, 0x90, 0x20, 0xcf, 0x69, 0x89, 0x03, 0xc8, 0x6b, 0xb6, 0xf1, 0x10, + 0xb1, 0x79, 0x41, 0x6c, 0xf2, 0x02, 0x55, 0xe7, 0x34, 0x0e, 0xaf, 0x69, 0xdc, 0xd9, 0x5d, 0x24, 0xcb, 0x65, 0x23, + 0x3f, 0xdd, 0x57, 0x8f, 0xce, 0xa9, 0xe4, 0x1b, 0xea, 0x85, 0x97, 0x72, 0x8b, 0xe1, 0x56, 0x22, 0x64, 0x7b, 0x9a, + 0x34, 0xa7, 0x40, 0x0f, 0x90, 0xbb, 0x8e, 0x4c, 0xb0, 0x90, 0x8d, 0x0a, 0x85, 0x28, 0x77, 0x1d, 0x16, 0xad, 0x97, + 0x65, 0x82, 0x4e, 0xa1, 0x74, 0xbc, 0x5c, 0x36, 0x73, 0xd7, 0x99, 0xb0, 0x04, 0x9e, 0x92, 0xe5, 0x52, 0x5e, 0xf8, + 0x9b, 0xb0, 0xc4, 0x6b, 0x00, 0xd9, 0xba, 0xce, 0x24, 0xbc, 0x95, 0x0b, 0x36, 0x35, 0xe1, 0xad, 0xd7, 0xd4, 0x55, + 0x7e, 0x81, 0x9f, 0x0c, 0x28, 0xae, 0xdc, 0xd1, 0x58, 0xef, 0x68, 0x84, 0x67, 0xea, 0x2a, 0x13, 0xf1, 0x22, 0x12, + 0x6f, 0xde, 0xd1, 0xc8, 0xec, 0xe8, 0x6c, 0xcb, 0x8e, 0xce, 0xee, 0xd9, 0xd1, 0x50, 0xef, 0x9e, 0x53, 0xe0, 0x8e, + 0x2f, 0x97, 0xcd, 0x46, 0x89, 0xbd, 0xd3, 0xfd, 0x88, 0xcd, 0x61, 0x37, 0x40, 0xcd, 0x13, 0x6c, 0x42, 0x37, 0x13, + 0x65, 0x15, 0xc5, 0xf4, 0xb3, 0x30, 0x59, 0x62, 0x21, 0xa9, 0x62, 0xc1, 0xa6, 0xeb, 0x22, 0xe6, 0xf6, 0x47, 0x52, + 0x36, 0x03, 0x3c, 0x64, 0x80, 0x87, 0xb1, 0x79, 0x01, 0xa6, 0xe7, 0xbe, 0x73, 0xb1, 0xeb, 0xb8, 0x86, 0xac, 0xaf, + 0xf2, 0x4b, 0x90, 0x11, 0x72, 0x7d, 0x0f, 0xa2, 0x45, 0x68, 0xed, 0x76, 0xb6, 0xd3, 0x1c, 0x84, 0xc7, 0x6f, 0x78, + 0x1a, 0xb9, 0x81, 0x6a, 0xfa, 0x59, 0xa8, 0x9a, 0xb0, 0x44, 0x27, 0x5b, 0x6d, 0xa5, 0xb5, 0xb2, 0xde, 0xa6, 0xb8, + 0xd6, 0xd1, 0x91, 0x6a, 0x31, 0x0d, 0x85, 0xa0, 0x69, 0xa2, 0x29, 0xd7, 0x75, 0xff, 0xbf, 0xa0, 0xc2, 0x0d, 0x7c, + 0x25, 0x34, 0x1b, 0x60, 0x08, 0x50, 0x2b, 0xec, 0x9a, 0xe7, 0x2b, 0xf1, 0xb4, 0x53, 0x6a, 0xb0, 0x77, 0xc8, 0x36, + 0x1a, 0x54, 0x11, 0xd8, 0x30, 0xb3, 0x09, 0x8d, 0x2e, 0x25, 0x83, 0xee, 0x0e, 0xae, 0xb4, 0xc2, 0xba, 0x22, 0xee, + 0xca, 0x0e, 0xd8, 0xfd, 0x79, 0xd6, 0x7a, 0x74, 0x78, 0xee, 0x62, 0xc5, 0xe3, 0xf9, 0x70, 0xe8, 0xa2, 0xdc, 0x79, + 0x58, 0xb7, 0xe6, 0xe1, 0xcf, 0xb3, 0xaf, 0x9f, 0x35, 0xbe, 0x2e, 0x3a, 0x27, 0x40, 0x44, 0x3a, 0xbe, 0x6f, 0x44, + 0x95, 0x05, 0xaf, 0x59, 0xd1, 0x30, 0x4c, 0xb6, 0x2f, 0xa7, 0x67, 0x2f, 0x27, 0x9b, 0x52, 0x1a, 0x01, 0x71, 0xe2, + 0xb5, 0xd2, 0xcb, 0x98, 0xce, 0xa9, 0x79, 0xf3, 0xe0, 0x86, 0xc9, 0x36, 0xf4, 0x18, 0xf0, 0x59, 0x22, 0x74, 0xa2, + 0x83, 0x66, 0xb5, 0xd6, 0x92, 0xae, 0xe4, 0x1a, 0x6c, 0x1b, 0xe1, 0x4e, 0xc9, 0xb9, 0xaa, 0xf4, 0xca, 0xaf, 0xb0, + 0x6b, 0x01, 0xb0, 0x15, 0xb2, 0xee, 0x96, 0xf2, 0xa0, 0x81, 0x1b, 0xdb, 0x60, 0xc3, 0x4d, 0x14, 0xb8, 0x6e, 0xdf, + 0xe0, 0x49, 0xfa, 0x2a, 0x2b, 0x2f, 0x8c, 0xd8, 0x8a, 0xaf, 0x4f, 0x62, 0xe0, 0x3a, 0x85, 0xc1, 0x12, 0x9a, 0x65, + 0x5b, 0x11, 0x50, 0x6c, 0x22, 0x76, 0xcb, 0xd6, 0xee, 0x96, 0x51, 0x70, 0x03, 0xc3, 0x09, 0x93, 0x00, 0x17, 0x11, + 0x53, 0xdd, 0x8a, 0x0e, 0x87, 0x74, 0x50, 0xb8, 0x7a, 0x21, 0xf6, 0x35, 0x64, 0xb1, 0x80, 0x10, 0x90, 0x8c, 0xcd, + 0xb8, 0xaf, 0x78, 0x42, 0x5d, 0x64, 0xb2, 0x39, 0x35, 0xfc, 0x5a, 0xfe, 0x6f, 0x86, 0x47, 0x8d, 0x58, 0x85, 0x45, + 0xcf, 0xb2, 0x5c, 0x1a, 0x37, 0x4f, 0xa5, 0xbc, 0x8a, 0x48, 0x2e, 0xfd, 0x38, 0xdb, 0x0e, 0xd0, 0xc3, 0x8e, 0xc9, + 0xa2, 0xf9, 0xf5, 0x51, 0xb3, 0x91, 0xbb, 0xd8, 0x85, 0xe1, 0x1e, 0x7a, 0x4a, 0x64, 0xaf, 0x03, 0xe8, 0x35, 0x4b, + 0x3e, 0xa7, 0x5f, 0xab, 0xf9, 0xb8, 0xe9, 0x62, 0xf5, 0x22, 0x01, 0x94, 0x17, 0xcc, 0x60, 0x00, 0xce, 0xcf, 0xdf, + 0xbd, 0x94, 0xea, 0xe0, 0x0f, 0x83, 0xe7, 0xb8, 0xd9, 0x70, 0xb1, 0x9b, 0x09, 0x3e, 0xfd, 0x8c, 0x25, 0x1c, 0xb8, + 0xd8, 0x1d, 0xc4, 0x3c, 0xa3, 0xf6, 0x1a, 0x94, 0x3a, 0xfb, 0xfb, 0x17, 0xa1, 0x20, 0x9a, 0xa6, 0x34, 0xcb, 0x1c, + 0x7b, 0x7c, 0x4d, 0x4a, 0x9f, 0x60, 0x98, 0x1b, 0x29, 0x2e, 0xa3, 0x42, 0xe2, 0x45, 0xdd, 0xf1, 0xb7, 0xa9, 0x4a, + 0x95, 0xad, 0x11, 0x9b, 0x14, 0x01, 0x05, 0x63, 0x53, 0xda, 0xd5, 0x27, 0x67, 0xde, 0x70, 0xf4, 0xd4, 0xc4, 0x2a, + 0x26, 0xbc, 0x3e, 0x41, 0xa5, 0x64, 0xc2, 0x92, 0xcb, 0x0d, 0xa5, 0xe1, 0xed, 0x86, 0x52, 0x50, 0xd9, 0x0a, 0xe8, + 0xf4, 0xeb, 0x67, 0x3e, 0x8d, 0xf5, 0x52, 0xf1, 0xb1, 0x41, 0x8c, 0xa4, 0xdf, 0xf2, 0x13, 0x90, 0x5a, 0xdb, 0x20, + 0x47, 0xf8, 0xed, 0xd3, 0x41, 0xc9, 0xe7, 0x4c, 0x57, 0x8c, 0xf2, 0xfb, 0x56, 0x08, 0xa5, 0x75, 0xf0, 0x5f, 0xc7, + 0x9f, 0xb5, 0x56, 0x7a, 0xfb, 0x69, 0x82, 0xb3, 0xb4, 0xaa, 0xdf, 0xb1, 0xf5, 0xfa, 0x1e, 0xfb, 0xea, 0xde, 0x6f, + 0x28, 0xd6, 0x8a, 0x4f, 0xb1, 0xff, 0x83, 0x98, 0x4d, 0x4a, 0x12, 0x58, 0x07, 0x53, 0x6a, 0x3c, 0x90, 0xcc, 0x64, + 0x0f, 0xa2, 0x54, 0x9f, 0x4b, 0xb8, 0xa2, 0x09, 0xef, 0xc1, 0x98, 0xa5, 0xf4, 0x32, 0xe6, 0x37, 0xab, 0xef, 0xf5, + 0xda, 0xde, 0x78, 0xcc, 0x46, 0x63, 0xeb, 0xde, 0x15, 0x25, 0xc5, 0x26, 0xdc, 0x3b, 0x41, 0xfe, 0x2f, 0xff, 0xec, + 0xfb, 0xff, 0xf2, 0xcf, 0x9f, 0x6c, 0x0a, 0xc3, 0xe7, 0x57, 0x58, 0x94, 0xc3, 0x6e, 0x3f, 0x5d, 0x9b, 0x67, 0xaa, + 0xe2, 0x7c, 0x73, 0x9b, 0xb5, 0x4d, 0x80, 0xfa, 0xb5, 0x2d, 0x58, 0x2b, 0x54, 0xa7, 0xcf, 0xf9, 0x2d, 0x80, 0xc1, + 0xba, 0x3e, 0x09, 0x19, 0x34, 0xfa, 0x5d, 0xa0, 0x5d, 0xa1, 0xe0, 0x41, 0x3b, 0xf2, 0xdb, 0x31, 0xfc, 0xa9, 0x35, + 0xfc, 0x4e, 0xf0, 0xb5, 0x7f, 0x62, 0x70, 0x75, 0x55, 0x24, 0xd8, 0xd9, 0x5d, 0xe1, 0x02, 0x7f, 0x77, 0xad, 0x44, + 0x2b, 0x1e, 0x41, 0x03, 0x75, 0xe4, 0xf5, 0x40, 0x32, 0xb8, 0x7a, 0x09, 0x6f, 0xed, 0x39, 0xbd, 0x4e, 0x8d, 0x83, + 0xf7, 0x1e, 0xe1, 0x00, 0x43, 0x54, 0x57, 0x25, 0x07, 0x5d, 0x93, 0x0c, 0x50, 0x0a, 0xe6, 0x06, 0x80, 0x89, 0x07, + 0x57, 0xda, 0xda, 0x3c, 0x57, 0x6e, 0x98, 0x60, 0x95, 0xb4, 0xb5, 0x7b, 0xa6, 0x82, 0x74, 0xec, 0xbc, 0x93, 0xf8, + 0x92, 0x8d, 0x69, 0x69, 0xdd, 0x4b, 0x57, 0x17, 0xd8, 0x11, 0x57, 0xb9, 0x0c, 0xd3, 0xff, 0x75, 0x5b, 0x24, 0xf1, + 0xef, 0x9f, 0x8e, 0x24, 0xf2, 0x07, 0x45, 0x12, 0xff, 0xfe, 0x87, 0x47, 0x12, 0xff, 0x6a, 0x47, 0x12, 0x61, 0x13, + 0x7f, 0x79, 0x50, 0xb4, 0xcf, 0x44, 0x62, 0xf8, 0x4d, 0x46, 0x9a, 0x5a, 0x8d, 0x8e, 0xf9, 0x08, 0x42, 0x7d, 0xff, + 0xf6, 0x91, 0xbb, 0x98, 0x8f, 0xec, 0xb8, 0x1d, 0xbc, 0xb5, 0x15, 0x02, 0x75, 0x6d, 0x13, 0x61, 0xd3, 0xb1, 0xb2, + 0x46, 0x71, 0x23, 0xa5, 0x7e, 0x68, 0xde, 0xa0, 0xe0, 0x06, 0xc5, 0x5b, 0x90, 0x1a, 0xb8, 0x65, 0xa2, 0x69, 0x81, + 0x0c, 0xc4, 0x15, 0x1d, 0x5b, 0x35, 0x73, 0xdd, 0xc2, 0x1e, 0xa1, 0x6d, 0xde, 0xf2, 0xa2, 0x6e, 0xdf, 0x2f, 0xdc, + 0x9f, 0x6f, 0x9b, 0x4f, 0x7a, 0xcd, 0xf6, 0x41, 0x73, 0xe2, 0x06, 0x2e, 0x88, 0x48, 0x59, 0xd0, 0x68, 0x1f, 0x1c, + 0x40, 0xc1, 0x8d, 0x55, 0xd0, 0x82, 0x02, 0x66, 0x15, 0x1c, 0x41, 0xc1, 0xc0, 0x2a, 0x38, 0x86, 0x82, 0xc8, 0x2a, + 0x78, 0x04, 0x05, 0x73, 0x37, 0xef, 0xb1, 0x02, 0xdc, 0x47, 0xa8, 0x8f, 0x95, 0xe5, 0x62, 0xca, 0x1e, 0xe1, 0x26, + 0x84, 0xf0, 0xc2, 0x91, 0xcc, 0x3c, 0x02, 0x87, 0x60, 0xc0, 0xf1, 0xcd, 0x98, 0x26, 0x01, 0x04, 0x51, 0x9f, 0x4a, + 0x19, 0xe3, 0x0b, 0xfe, 0x8e, 0x4d, 0xa8, 0xf9, 0x5e, 0x86, 0xc1, 0x83, 0xe3, 0xa2, 0x5e, 0xa3, 0x9f, 0xb7, 0x8b, + 0x9d, 0x53, 0xb1, 0x3f, 0x9d, 0x85, 0xa2, 0xf6, 0xb2, 0xac, 0x53, 0xd3, 0xd5, 0x8b, 0x3d, 0xdf, 0x12, 0x43, 0xb2, + 0x7c, 0x11, 0xc3, 0x98, 0xdf, 0xd4, 0x6f, 0xdd, 0xce, 0xe6, 0xb8, 0x12, 0x40, 0x54, 0xc4, 0x95, 0xe4, 0x9a, 0x8a, + 0xa7, 0x77, 0xe1, 0xa8, 0xf8, 0xfd, 0x92, 0x66, 0x59, 0x38, 0xd2, 0x2d, 0xb7, 0xc7, 0x91, 0x24, 0x88, 0x76, 0x0c, + 0xc9, 0x00, 0x01, 0xb1, 0x20, 0xd8, 0x2c, 0xb0, 0xe5, 0x75, 0x68, 0x08, 0xb0, 0x53, 0x8d, 0x2a, 0xc9, 0xe9, 0xab, + 0x45, 0x22, 0x1c, 0x95, 0x05, 0xa7, 0xd3, 0x94, 0xca, 0x52, 0x85, 0xe1, 0xfc, 0x74, 0x1f, 0x0a, 0x54, 0xf5, 0x96, + 0xe8, 0x91, 0x71, 0x1c, 0x6c, 0x8f, 0x21, 0x39, 0x26, 0x7a, 0x64, 0xe7, 0xdb, 0x14, 0xc9, 0x36, 0xeb, 0x31, 0x8b, + 0x2f, 0x9b, 0x03, 0xf8, 0x4f, 0x47, 0x44, 0xbe, 0x1c, 0x0e, 0x87, 0xf7, 0x46, 0x93, 0xbe, 0x8c, 0x86, 0xb4, 0x45, + 0x8f, 0xda, 0x90, 0x8b, 0x51, 0xd7, 0x31, 0x88, 0x66, 0x2e, 0x71, 0xb7, 0x78, 0x58, 0x63, 0x08, 0x57, 0x88, 0xf1, + 0xe2, 0xe1, 0x91, 0xa5, 0x7c, 0x9a, 0xd2, 0xc5, 0x24, 0x4c, 0x47, 0x2c, 0x09, 0x1a, 0xb9, 0x3f, 0xd7, 0xa1, 0x98, + 0x2f, 0x4f, 0x4e, 0x4e, 0x72, 0x3f, 0x32, 0x4f, 0x8d, 0x28, 0xca, 0xfd, 0xc1, 0xa2, 0x58, 0x46, 0xa3, 0x31, 0x1c, + 0xe6, 0x3e, 0x33, 0x05, 0x07, 0xad, 0x41, 0x74, 0xd0, 0xca, 0xfd, 0x1b, 0xab, 0x45, 0xee, 0x53, 0xfd, 0x94, 0xd2, + 0xa8, 0x92, 0xd0, 0xf1, 0xa8, 0xd1, 0xc8, 0x7d, 0x45, 0x68, 0x0b, 0x30, 0xc7, 0xd4, 0xcf, 0x20, 0x9c, 0x09, 0x0e, + 0x2c, 0xb9, 0xcd, 0x85, 0xd7, 0xbb, 0xd4, 0x2f, 0xcb, 0x50, 0x1f, 0x96, 0xc8, 0x51, 0x1f, 0xff, 0x62, 0x07, 0x4d, + 0x80, 0x98, 0x65, 0xb0, 0x84, 0x9b, 0x98, 0x4a, 0xa5, 0x1a, 0x28, 0x4b, 0x56, 0xff, 0x42, 0x78, 0x19, 0x4b, 0x01, + 0xfe, 0x03, 0x2d, 0xd5, 0x5b, 0xdd, 0x04, 0xdd, 0xc2, 0xf5, 0x29, 0xfd, 0x24, 0xd7, 0xbf, 0x7b, 0x08, 0xd3, 0xa7, + 0xf4, 0x8f, 0x66, 0xfa, 0xfa, 0xd5, 0xa7, 0x8a, 0xe9, 0x2b, 0xb6, 0x36, 0x11, 0xc4, 0x1d, 0x8c, 0xe9, 0xe0, 0xe3, + 0x35, 0xbf, 0xad, 0xc3, 0x91, 0x48, 0x5d, 0xc9, 0x4f, 0x77, 0x7f, 0x6b, 0xf2, 0x87, 0x19, 0xcc, 0xfa, 0x2e, 0x85, + 0x14, 0x9b, 0xaf, 0x13, 0xe2, 0xbe, 0x36, 0x36, 0x9d, 0x2a, 0x19, 0x0e, 0x89, 0xfb, 0x7a, 0x38, 0x74, 0xcd, 0x95, + 0xbf, 0x50, 0x50, 0xd9, 0xea, 0x55, 0xa5, 0x44, 0xb6, 0xfa, 0xfa, 0x6b, 0xbb, 0xcc, 0x2e, 0xd0, 0x21, 0x17, 0x3b, + 0xbc, 0xa2, 0x6b, 0x22, 0x96, 0xc1, 0x51, 0x83, 0xcf, 0x65, 0x54, 0xdf, 0x39, 0x98, 0x56, 0x5e, 0x0f, 0x5d, 0x00, + 0xbc, 0xe1, 0x9d, 0xd6, 0xab, 0xf7, 0xdd, 0x47, 0xd4, 0xa4, 0xdf, 0x3d, 0xb9, 0xfb, 0x26, 0xf2, 0x26, 0x02, 0xe5, + 0x2c, 0x7b, 0x9d, 0xac, 0xdc, 0x65, 0x51, 0x30, 0x12, 0x62, 0x2f, 0x2b, 0x17, 0x7c, 0x34, 0x8a, 0xe1, 0x83, 0x25, + 0x8b, 0xca, 0x7b, 0x50, 0x55, 0xf7, 0x6e, 0x65, 0xbd, 0x81, 0xdd, 0x51, 0xbf, 0x35, 0x54, 0x7e, 0x3f, 0x49, 0xe5, + 0x40, 0xcf, 0xf5, 0x87, 0x74, 0xa4, 0x39, 0xb8, 0xd0, 0xfc, 0x7f, 0xa1, 0x32, 0x67, 0x05, 0x64, 0x8d, 0xa8, 0x81, + 0xa3, 0x3c, 0xd7, 0x77, 0x0e, 0x22, 0x96, 0x4d, 0xe1, 0xfd, 0x9c, 0xaa, 0x27, 0xfd, 0x14, 0x0b, 0xcf, 0x6e, 0xac, + 0xb8, 0x46, 0x65, 0xbb, 0x72, 0x13, 0xd8, 0x50, 0x8e, 0xe2, 0x89, 0xc8, 0x5d, 0xed, 0x6f, 0x36, 0x48, 0x74, 0x1d, + 0x85, 0x4f, 0x15, 0x71, 0xb1, 0x56, 0x08, 0x4e, 0xdf, 0x62, 0x43, 0x4c, 0x95, 0x29, 0xc8, 0xed, 0xb8, 0x9d, 0xac, + 0x51, 0xd8, 0x92, 0x51, 0x82, 0x6c, 0x1a, 0x26, 0x8a, 0x8d, 0x12, 0x57, 0xf1, 0x83, 0xdd, 0x45, 0xb9, 0xf3, 0xb9, + 0x6b, 0xc0, 0x56, 0xc4, 0xdb, 0x39, 0xdd, 0x87, 0x0e, 0x1d, 0xa7, 0x02, 0x7a, 0xb2, 0x16, 0x5c, 0xf8, 0x44, 0x98, + 0xff, 0xca, 0xcf, 0x6e, 0xb0, 0x9f, 0xdd, 0x38, 0x7f, 0x5e, 0xd4, 0x6f, 0xe8, 0xf5, 0x47, 0x26, 0xea, 0x22, 0x9c, + 0xd6, 0x41, 0xe1, 0x97, 0x4e, 0x41, 0xcd, 0x9e, 0x65, 0xb2, 0x9a, 0xba, 0xb1, 0xdf, 0x9e, 0x65, 0x90, 0x0d, 0x20, + 0xd5, 0xd6, 0x20, 0xe1, 0x09, 0x6d, 0x57, 0x93, 0x12, 0xed, 0xe0, 0xb2, 0xc1, 0x56, 0x7f, 0xc1, 0x21, 0x7b, 0x40, + 0xdc, 0x05, 0x0d, 0xcd, 0xd6, 0x1b, 0x26, 0x72, 0xdc, 0xd8, 0xd8, 0x3e, 0xd0, 0xc8, 0xad, 0x49, 0xe9, 0x95, 0xae, + 0x47, 0xd0, 0xb7, 0x45, 0xc0, 0x3f, 0x95, 0xa2, 0x07, 0xae, 0x44, 0xf3, 0xbf, 0x95, 0xdb, 0xb8, 0x5a, 0x2c, 0x53, + 0xf4, 0x1e, 0x02, 0x59, 0x10, 0x0e, 0x05, 0x4d, 0xf1, 0x43, 0x5a, 0x5e, 0xcb, 0xdb, 0x34, 0x0b, 0x10, 0x33, 0x41, + 0xf3, 0x64, 0x7a, 0xfb, 0xf0, 0xe1, 0xef, 0x5f, 0x7e, 0xae, 0x71, 0x64, 0xde, 0x2e, 0xe3, 0xba, 0x6d, 0x38, 0x08, + 0x71, 0x78, 0x17, 0xb0, 0x44, 0xca, 0xbc, 0x6b, 0xf0, 0x07, 0xb6, 0xa7, 0x5c, 0xe7, 0x9a, 0xa6, 0x34, 0x96, 0x9f, + 0x92, 0xd3, 0x5b, 0x71, 0x70, 0x3c, 0xbd, 0x35, 0xbb, 0xd1, 0x5c, 0xc9, 0x21, 0xfd, 0x43, 0x53, 0x45, 0xb7, 0xe7, + 0xa6, 0x56, 0xd3, 0x1d, 0x8f, 0xa6, 0xb7, 0x6d, 0x25, 0x68, 0xeb, 0xa9, 0x82, 0xaa, 0x31, 0xbd, 0xb5, 0x93, 0x65, + 0xcb, 0x81, 0x1c, 0xff, 0x20, 0x73, 0x68, 0x98, 0xd1, 0x36, 0xbc, 0x3f, 0x9b, 0x0d, 0xc2, 0x58, 0x0b, 0xf3, 0x09, + 0x8b, 0xa2, 0x98, 0xb6, 0x8d, 0xbc, 0x76, 0x9a, 0xc7, 0x90, 0x6b, 0x6a, 0x6f, 0x59, 0x75, 0x57, 0x2c, 0xe4, 0x15, + 0x78, 0x0a, 0xaf, 0x33, 0x1e, 0xc3, 0xc7, 0x2b, 0x36, 0xa2, 0x53, 0x27, 0x61, 0x36, 0x4a, 0xe4, 0xc9, 0xdf, 0xd5, + 0xb5, 0x1c, 0x35, 0xfe, 0xd4, 0x96, 0x1b, 0xde, 0x68, 0x0b, 0x3e, 0x0d, 0xea, 0x07, 0xd5, 0x85, 0x40, 0x55, 0xb1, + 0x04, 0xbc, 0x61, 0x59, 0x18, 0xa4, 0x95, 0xe2, 0xd3, 0x8e, 0xdf, 0xd4, 0x65, 0x72, 0x00, 0x78, 0xd1, 0x73, 0x51, + 0x94, 0x57, 0x17, 0xf3, 0x6f, 0x73, 0x5a, 0x1e, 0x6f, 0x3e, 0x2d, 0x8f, 0xcd, 0x69, 0xb9, 0x9f, 0x62, 0xbf, 0x1c, + 0x36, 0xe1, 0xbf, 0x76, 0xb9, 0xa0, 0xa0, 0xe1, 0x1c, 0x4c, 0x6f, 0x1d, 0xd0, 0xd3, 0xea, 0xad, 0xe9, 0xad, 0x4a, + 0x15, 0x86, 0x98, 0x45, 0x03, 0x92, 0x67, 0x71, 0xc3, 0x81, 0x42, 0xf8, 0xbf, 0x51, 0xa9, 0x6a, 0x1e, 0x42, 0x1d, + 0xf4, 0x3a, 0x5a, 0xaf, 0x6b, 0xdd, 0x7f, 0x68, 0x83, 0x84, 0x0b, 0x2f, 0x30, 0xdc, 0x18, 0xf9, 0x22, 0xbc, 0xbe, + 0xa6, 0x51, 0x30, 0xe4, 0x83, 0x59, 0xf6, 0x4f, 0x1a, 0x7e, 0x8d, 0xc4, 0x7b, 0x8f, 0xf4, 0xca, 0x38, 0xa6, 0xab, + 0x4a, 0x5c, 0x36, 0x23, 0x2c, 0x8a, 0x7d, 0x0a, 0xb2, 0x41, 0x18, 0x53, 0xaf, 0xe5, 0x1f, 0x6e, 0x38, 0x04, 0xff, + 0x2e, 0x7b, 0xb3, 0x71, 0x31, 0xbf, 0x17, 0x19, 0xf7, 0x22, 0xe1, 0xb3, 0x70, 0x60, 0xef, 0x61, 0xe3, 0x64, 0x33, + 0xb8, 0x3d, 0x33, 0x53, 0xdf, 0x08, 0x05, 0x2d, 0x77, 0x22, 0x3a, 0x0c, 0x67, 0xb1, 0xb8, 0x7f, 0xd4, 0x6d, 0x94, + 0xb1, 0x36, 0xea, 0x3d, 0x0c, 0xbd, 0x6c, 0xfb, 0x40, 0x2e, 0xfd, 0xe5, 0xe3, 0x43, 0xf8, 0x4f, 0xe5, 0x3d, 0xdd, + 0x95, 0xba, 0xba, 0xb2, 0x55, 0x41, 0x57, 0xdf, 0xad, 0x28, 0xe3, 0x4a, 0x84, 0x4b, 0x7d, 0xfc, 0xa1, 0xad, 0x41, + 0xab, 0x7c, 0x50, 0x73, 0xad, 0x65, 0x7d, 0x56, 0xeb, 0xcf, 0x1b, 0xfc, 0x81, 0x6d, 0x07, 0x4a, 0x73, 0xad, 0xb6, + 0xd5, 0xdf, 0xd2, 0x5b, 0x6b, 0x6c, 0x30, 0x2e, 0xdb, 0xef, 0x92, 0xbb, 0xc2, 0x44, 0x51, 0x51, 0x48, 0xb0, 0x52, + 0x76, 0x95, 0x95, 0xc2, 0x28, 0xb9, 0x3a, 0xed, 0xde, 0x4e, 0x62, 0x67, 0xae, 0x6e, 0xfd, 0x11, 0xb7, 0xe9, 0x37, + 0x5c, 0x47, 0xc6, 0xbf, 0xe1, 0xed, 0xe3, 0xae, 0xfc, 0x46, 0xab, 0xdb, 0x05, 0x4d, 0x6b, 0x3e, 0x92, 0x9a, 0xdd, + 0x8b, 0xf0, 0x8e, 0xa6, 0x97, 0x2d, 0xd7, 0x01, 0xef, 0x4a, 0x5d, 0xa5, 0x0a, 0xc8, 0x32, 0xa7, 0xe5, 0x3a, 0xb7, + 0x93, 0x38, 0xc9, 0x88, 0x3b, 0x16, 0x62, 0x1a, 0xa8, 0x8f, 0xb8, 0xde, 0x1c, 0xf8, 0x3c, 0x1d, 0xed, 0xb7, 0x1a, + 0x8d, 0x06, 0xbc, 0xc9, 0xd4, 0x75, 0xe6, 0x8c, 0xde, 0x3c, 0xe1, 0xb7, 0xc4, 0x6d, 0x38, 0x0d, 0xa7, 0xd9, 0x3a, + 0x71, 0x9a, 0xad, 0x43, 0xff, 0xf8, 0xc4, 0xed, 0x7c, 0xe1, 0x38, 0xa7, 0x11, 0x1d, 0x66, 0xf0, 0xc3, 0x71, 0x4e, + 0xa5, 0xe2, 0xa5, 0x7e, 0x3b, 0x8e, 0x3f, 0x88, 0xb3, 0x7a, 0xd3, 0x59, 0xe8, 0x47, 0xc7, 0x81, 0xbb, 0x91, 0x81, + 0xf3, 0xe5, 0xb0, 0x35, 0x3c, 0x1c, 0x3e, 0x6e, 0xeb, 0xe2, 0xfc, 0x8b, 0x4a, 0x73, 0xac, 0xfe, 0xb6, 0xac, 0x6e, + 0x99, 0x48, 0xf9, 0x47, 0xaa, 0x73, 0xf1, 0x1c, 0x10, 0x3d, 0x1b, 0xbb, 0xb6, 0xd6, 0x67, 0x6a, 0x9e, 0x5c, 0x0f, + 0x86, 0xad, 0xb2, 0xb9, 0x84, 0x71, 0xbf, 0x00, 0xf2, 0x74, 0xdf, 0x80, 0x7e, 0x6a, 0xa3, 0xa9, 0x59, 0xdf, 0x84, + 0xa8, 0xa6, 0xab, 0xd7, 0x38, 0x32, 0xeb, 0x3b, 0x85, 0x54, 0x7c, 0xa3, 0xab, 0x4a, 0x08, 0x5c, 0x27, 0x22, 0xee, + 0xcb, 0x66, 0xeb, 0x04, 0x37, 0x9b, 0xc7, 0xfe, 0xf1, 0xc9, 0xa0, 0x81, 0x0f, 0xfd, 0xc3, 0xfa, 0x81, 0x7f, 0x8c, + 0x4f, 0xea, 0x27, 0xf8, 0xe4, 0xf9, 0xc9, 0xa0, 0x7e, 0xe8, 0x1f, 0xe2, 0x46, 0xfd, 0x04, 0x0a, 0xeb, 0x27, 0xf5, + 0x93, 0x79, 0xfd, 0xf0, 0x64, 0xd0, 0x90, 0xa5, 0x2d, 0xff, 0xe8, 0xa8, 0xde, 0x6c, 0xf8, 0x47, 0x47, 0xf8, 0xc8, + 0x3f, 0x3e, 0xae, 0x37, 0x0f, 0xfc, 0xe3, 0xe3, 0x17, 0x47, 0x27, 0xfe, 0x01, 0xd4, 0x1d, 0x1c, 0x0c, 0x0e, 0xfc, + 0x66, 0xb3, 0x0e, 0xff, 0xe0, 0x13, 0xbf, 0xa5, 0x7e, 0x34, 0x9b, 0xfe, 0x41, 0x13, 0x37, 0xe2, 0xa3, 0x96, 0x7f, + 0xfc, 0x18, 0xcb, 0x7f, 0x65, 0x33, 0x2c, 0xff, 0x81, 0x61, 0xf0, 0x63, 0xbf, 0x75, 0xac, 0x7e, 0xc9, 0x01, 0xe7, + 0x87, 0x27, 0x3f, 0xb9, 0xfb, 0x5b, 0xd7, 0xd0, 0x54, 0x6b, 0x38, 0x39, 0xf2, 0x0f, 0x0e, 0xf0, 0x61, 0xd3, 0x3f, + 0x39, 0x18, 0xd7, 0x0f, 0x5b, 0xfe, 0xf1, 0xa3, 0x41, 0xbd, 0xe9, 0x3f, 0x7a, 0x84, 0x1b, 0xf5, 0x03, 0xbf, 0x85, + 0x9b, 0xfe, 0xe1, 0x81, 0xfc, 0x71, 0xe0, 0xb7, 0xe6, 0x8f, 0x1e, 0xfb, 0xc7, 0x47, 0xe3, 0x63, 0xff, 0xf0, 0xfb, + 0xc3, 0x13, 0xbf, 0x75, 0x30, 0x3e, 0x38, 0xf6, 0x5b, 0x8f, 0xe6, 0xc7, 0xfe, 0xe1, 0xb8, 0xde, 0x3a, 0xbe, 0xb7, + 0x67, 0xb3, 0xe5, 0x03, 0x8e, 0x64, 0x35, 0x54, 0x60, 0x5d, 0x01, 0xff, 0x8f, 0x65, 0xdf, 0x7f, 0xc7, 0x61, 0xb2, + 0xf5, 0xae, 0x8f, 0xfd, 0x93, 0x47, 0x03, 0xd5, 0x1c, 0x0a, 0xea, 0xa6, 0x05, 0x74, 0x99, 0xd7, 0xd5, 0xb4, 0x72, + 0xb8, 0xba, 0x19, 0xc8, 0xfc, 0xaf, 0x27, 0x9b, 0xd7, 0x61, 0x62, 0x35, 0xef, 0x7f, 0xe8, 0x38, 0xc5, 0x96, 0x9f, + 0xee, 0x8f, 0x14, 0xe9, 0x8f, 0x3a, 0x5f, 0xa8, 0xd7, 0x14, 0x7f, 0x71, 0x85, 0xb3, 0x6d, 0x8e, 0x8f, 0xf4, 0xd3, + 0x8e, 0x8f, 0x84, 0x3e, 0xc4, 0xf3, 0x91, 0xfe, 0xe1, 0x9e, 0x8f, 0x8c, 0xae, 0xb8, 0xbb, 0xef, 0xc4, 0x9a, 0x83, + 0x63, 0xd5, 0x2a, 0x7e, 0x2e, 0xbc, 0x1e, 0x83, 0xef, 0x61, 0xe5, 0xed, 0x3b, 0x78, 0x15, 0xba, 0xed, 0x07, 0xe2, + 0xc0, 0x62, 0xef, 0x84, 0xe2, 0xb1, 0x7c, 0x1b, 0x42, 0xe2, 0x4f, 0x23, 0xe4, 0xfb, 0x87, 0xe0, 0x23, 0xfe, 0xc3, + 0xf1, 0xc1, 0x6d, 0x7c, 0x54, 0x3c, 0xf0, 0xd2, 0xd3, 0x20, 0x3d, 0x05, 0x17, 0xf2, 0xd9, 0x83, 0xbb, 0x40, 0x35, + 0x77, 0x9f, 0x42, 0x51, 0xe6, 0xaa, 0x88, 0xcf, 0xab, 0xcf, 0x09, 0x16, 0xa8, 0x8b, 0x7f, 0xc4, 0xd5, 0x6e, 0x99, + 0xa9, 0x94, 0x3a, 0xfa, 0xa1, 0x10, 0x4a, 0x2d, 0xbf, 0xe1, 0x37, 0x0a, 0x97, 0x0e, 0x5c, 0xf6, 0x24, 0x0b, 0x2e, + 0x42, 0xf8, 0xec, 0x6a, 0xcc, 0x47, 0xf2, 0x03, 0xad, 0xf0, 0x5a, 0x7c, 0xf9, 0xa9, 0x5c, 0xf5, 0x45, 0x82, 0xc0, + 0x75, 0xf5, 0x2b, 0x22, 0xe0, 0x32, 0xe1, 0x77, 0x70, 0xe1, 0xd2, 0xc4, 0x12, 0x26, 0xe0, 0xed, 0x78, 0x49, 0x23, + 0x16, 0x7a, 0xae, 0x37, 0x4d, 0xe9, 0x90, 0xa6, 0x59, 0xbd, 0x72, 0x0b, 0x51, 0x5e, 0x40, 0x44, 0xae, 0xf9, 0xc0, + 0x67, 0x0a, 0xaf, 0x79, 0x26, 0x3d, 0xed, 0x6f, 0x74, 0xb5, 0x01, 0xe6, 0xe6, 0xd8, 0x94, 0xa4, 0x20, 0x6b, 0x4b, + 0xa5, 0xcd, 0x55, 0x5a, 0x5b, 0xd3, 0x6f, 0x1d, 0x21, 0x47, 0x16, 0xc3, 0xeb, 0x73, 0x7f, 0xf4, 0xea, 0x07, 0x8d, + 0x3f, 0x21, 0xab, 0x5b, 0x31, 0x50, 0x5f, 0xbb, 0xdb, 0xd2, 0xf2, 0xc3, 0xc8, 0xd5, 0x2b, 0xa2, 0xae, 0xa2, 0x88, + 0x2f, 0xd5, 0xda, 0xe1, 0x45, 0xbc, 0x3a, 0xb2, 0xab, 0x5e, 0x74, 0x30, 0x64, 0x23, 0xcf, 0xfe, 0xec, 0xad, 0x7a, + 0x3d, 0xaf, 0xfc, 0x5a, 0x36, 0xca, 0xcb, 0x26, 0x29, 0x5a, 0xc8, 0x28, 0x09, 0x4b, 0x9c, 0x74, 0xb9, 0xf4, 0x52, + 0x70, 0x91, 0x13, 0x0b, 0xa7, 0xf0, 0x8c, 0x2a, 0x48, 0x4e, 0x71, 0x01, 0x90, 0x44, 0x30, 0x49, 0xd5, 0xdf, 0xb2, + 0xd8, 0xfc, 0xd0, 0x8e, 0x2f, 0x3f, 0x0e, 0x93, 0x11, 0x50, 0x61, 0x98, 0x8c, 0xd6, 0xdc, 0x6a, 0x2a, 0xd0, 0xb3, + 0x52, 0x5a, 0x0e, 0x55, 0xba, 0xcf, 0xb2, 0x27, 0x77, 0xef, 0xf4, 0x7b, 0xbc, 0x5c, 0xf0, 0x4e, 0xcb, 0xa8, 0x44, + 0xf9, 0xce, 0xe1, 0x1a, 0xf9, 0x4a, 0x7d, 0x48, 0x5e, 0xca, 0x54, 0xd0, 0x27, 0xe0, 0xf2, 0xa7, 0xa3, 0xad, 0x51, + 0xe2, 0x4a, 0xe9, 0x4e, 0x22, 0x3a, 0x67, 0x03, 0x2d, 0xea, 0xb1, 0xa3, 0x2f, 0xc0, 0xd7, 0xe5, 0xd6, 0x90, 0x26, + 0x56, 0xfe, 0x98, 0x41, 0x28, 0x33, 0xd1, 0x49, 0xc2, 0xdd, 0xce, 0x57, 0xc5, 0x57, 0x3c, 0xb7, 0x6d, 0x02, 0x7c, + 0xdd, 0xbe, 0x97, 0xd2, 0xf8, 0x9f, 0xc8, 0x57, 0xf0, 0x7d, 0xfb, 0xaf, 0xfa, 0xf0, 0x69, 0x75, 0x5f, 0x7e, 0xe5, + 0xfe, 0xab, 0xf2, 0x33, 0xf7, 0xc0, 0x08, 0x6b, 0xb7, 0x93, 0x18, 0x4b, 0x8d, 0xe9, 0x01, 0x0a, 0x91, 0x02, 0xd7, + 0x6d, 0x1d, 0xb9, 0x8e, 0xb2, 0x89, 0xe5, 0xef, 0x8e, 0x12, 0xa7, 0x52, 0x09, 0x70, 0x9a, 0x2d, 0xff, 0x68, 0xdc, + 0xf2, 0x1f, 0xcf, 0x1f, 0xf9, 0x27, 0xe3, 0xe6, 0xa3, 0x79, 0x1d, 0xfe, 0xb6, 0xfc, 0xc7, 0x71, 0xbd, 0xe5, 0x3f, + 0x86, 0xff, 0xbf, 0x3f, 0xf4, 0x8f, 0xc6, 0xf5, 0xa6, 0x7f, 0x32, 0x3f, 0xf0, 0x0f, 0x5e, 0x34, 0x5b, 0xfe, 0x81, + 0xd3, 0x74, 0x54, 0x3f, 0x60, 0xd7, 0x8a, 0x3b, 0x7f, 0xb5, 0x72, 0x20, 0x36, 0x04, 0xd1, 0x54, 0xae, 0xa5, 0x8b, + 0xbd, 0xe2, 0x5b, 0x81, 0xfa, 0x7c, 0x6a, 0x67, 0xdd, 0xd3, 0x30, 0x85, 0x0f, 0xb6, 0x54, 0xcf, 0x6e, 0xa5, 0x0e, + 0x57, 0xf8, 0xc5, 0x86, 0x29, 0xe0, 0x84, 0xbb, 0xd8, 0xbe, 0x41, 0x0e, 0xd7, 0xaf, 0xe5, 0xeb, 0xad, 0xcd, 0x5b, + 0xfe, 0xb6, 0x93, 0xb6, 0x6a, 0x68, 0xde, 0x24, 0x28, 0x99, 0x05, 0x93, 0x9f, 0x12, 0x90, 0x93, 0x7c, 0x13, 0xe5, + 0xab, 0xf3, 0x43, 0xca, 0x67, 0xca, 0xad, 0x4b, 0xf4, 0xb4, 0xbc, 0xa8, 0x10, 0x31, 0x78, 0xed, 0x41, 0x9e, 0x1b, + 0xd0, 0x2b, 0x6e, 0xda, 0x12, 0x4b, 0x92, 0x5f, 0xd0, 0xac, 0xeb, 0x42, 0x91, 0x1b, 0xb8, 0xd2, 0xc5, 0xe7, 0x16, + 0x1f, 0xad, 0x29, 0x08, 0xbb, 0x2c, 0xc0, 0xf2, 0xb2, 0x11, 0x9c, 0x5a, 0xc0, 0x8f, 0x8b, 0xf6, 0xf6, 0xb6, 0x9e, + 0x17, 0xa9, 0x40, 0xc2, 0x5a, 0xcb, 0x8f, 0x5d, 0xd8, 0xac, 0xc8, 0xb5, 0x11, 0x5d, 0x8c, 0x2b, 0x51, 0x88, 0x34, + 0x9e, 0xae, 0x69, 0x28, 0xfc, 0x30, 0x51, 0xc9, 0x23, 0x16, 0xc3, 0xc2, 0x4d, 0x7a, 0x80, 0x72, 0x2e, 0x42, 0xeb, + 0x6b, 0xb6, 0xfa, 0x9c, 0x73, 0x11, 0x9a, 0x2b, 0xa1, 0x89, 0xa8, 0xdc, 0x99, 0x18, 0xb7, 0x3a, 0xaf, 0xdf, 0x9d, + 0x39, 0xea, 0x78, 0x9e, 0xee, 0x8f, 0x5b, 0x9d, 0x53, 0xe9, 0x33, 0x51, 0x17, 0xca, 0x88, 0xba, 0x50, 0xe6, 0xe8, + 0xcb, 0x85, 0x10, 0x49, 0xcb, 0xf7, 0xd5, 0xb2, 0xa5, 0xcd, 0xa0, 0xbc, 0xbd, 0x93, 0x59, 0x2c, 0x18, 0xbc, 0xaa, + 0x79, 0x1f, 0xba, 0xd6, 0x61, 0xc3, 0x8a, 0xfc, 0x63, 0xad, 0x1d, 0x5e, 0x8b, 0xc4, 0xf8, 0x86, 0x87, 0x2c, 0xa6, + 0x26, 0xe3, 0x58, 0x0f, 0x55, 0x64, 0xc8, 0xaf, 0xb7, 0xce, 0x66, 0xd7, 0x13, 0x26, 0x5c, 0x93, 0xc7, 0xff, 0x5e, + 0x77, 0x38, 0x95, 0x53, 0x75, 0xae, 0x72, 0xed, 0xbc, 0x36, 0x9f, 0xa5, 0xa9, 0x6e, 0xa9, 0x5e, 0xbd, 0x96, 0x10, + 0x70, 0x33, 0x6c, 0x7c, 0xd0, 0x29, 0xdc, 0xc5, 0x76, 0x5d, 0x7e, 0xba, 0x3f, 0x3e, 0xe8, 0x5c, 0x05, 0x53, 0x3d, + 0xde, 0x0b, 0x3e, 0xda, 0x3c, 0x56, 0xcc, 0x47, 0x5d, 0x79, 0x05, 0x42, 0xdd, 0xb5, 0x35, 0xca, 0x2f, 0x8f, 0xdd, + 0xce, 0xa9, 0x56, 0x06, 0x1c, 0x19, 0x0e, 0x77, 0x8f, 0x1a, 0xe6, 0x56, 0x45, 0xcc, 0x47, 0x70, 0x20, 0x55, 0x17, + 0x6b, 0x92, 0x8a, 0xc7, 0x7d, 0xdc, 0xec, 0x9c, 0x86, 0x8e, 0xe4, 0x2d, 0x92, 0x79, 0x64, 0xc1, 0x3e, 0x74, 0x1e, + 0xf3, 0x09, 0xf5, 0x19, 0xdf, 0xbf, 0xa1, 0xd7, 0xf5, 0x70, 0xca, 0x4a, 0xf7, 0x36, 0x28, 0x1d, 0xc5, 0x94, 0xbc, + 0x9c, 0x09, 0x7e, 0x86, 0x2b, 0x8b, 0x94, 0x2c, 0x3c, 0xd7, 0xbe, 0x73, 0xb0, 0x55, 0x80, 0x84, 0x5c, 0x47, 0x71, + 0x78, 0xe3, 0x63, 0xd7, 0xb2, 0x37, 0x77, 0x3b, 0xff, 0xfa, 0x3f, 0xfe, 0x97, 0x76, 0x9b, 0x9f, 0xee, 0x8f, 0x9b, + 0x66, 0xac, 0x15, 0x44, 0xe7, 0xa7, 0x70, 0x11, 0xb1, 0x8c, 0xf3, 0xd2, 0xdb, 0xfa, 0x28, 0x65, 0x51, 0x7d, 0x1c, + 0xc6, 0x43, 0xb7, 0xb3, 0x1d, 0x41, 0xf6, 0x0d, 0x24, 0x0d, 0x75, 0xb5, 0x08, 0x48, 0xf0, 0x37, 0xdd, 0xa1, 0x31, + 0x57, 0x31, 0xe4, 0x69, 0xb5, 0x6f, 0xd4, 0x94, 0x07, 0xaa, 0x72, 0xab, 0x26, 0xd5, 0x5f, 0xaf, 0xd2, 0x4c, 0x2d, + 0xad, 0x5c, 0xa6, 0xc9, 0x5d, 0xa7, 0x88, 0x53, 0xfd, 0xdf, 0xff, 0xf9, 0x5f, 0xfe, 0x9b, 0x79, 0x84, 0xf0, 0xd3, + 0xbf, 0xfe, 0xf7, 0xff, 0xfc, 0x7f, 0xfe, 0xf7, 0x7f, 0x85, 0x0b, 0x18, 0x3a, 0x44, 0x25, 0xf9, 0x84, 0x53, 0xc6, + 0xa7, 0x14, 0xc3, 0x70, 0x20, 0x47, 0x71, 0xc2, 0x32, 0xc1, 0x06, 0xd5, 0xeb, 0x35, 0x17, 0x72, 0x42, 0x79, 0xd8, + 0x34, 0x74, 0xf2, 0xd0, 0xe6, 0x25, 0x8d, 0x54, 0x50, 0x2e, 0x69, 0x31, 0x3f, 0xdd, 0x07, 0x7c, 0x3f, 0xec, 0x46, + 0xa2, 0x5f, 0x6c, 0xc7, 0xc2, 0x38, 0x65, 0xa1, 0x24, 0x2f, 0xcb, 0x1d, 0x08, 0x97, 0x2c, 0xe0, 0x31, 0x68, 0x59, + 0xc5, 0x72, 0xf7, 0x2a, 0x7d, 0xda, 0x1f, 0x66, 0x99, 0x60, 0x43, 0x40, 0xb9, 0x72, 0xfd, 0xca, 0xc8, 0x74, 0x1d, + 0xd4, 0xbf, 0xf8, 0x2e, 0x97, 0xa3, 0x28, 0xdb, 0xfa, 0xf0, 0xe4, 0x4f, 0xf9, 0x5f, 0x26, 0xa0, 0x64, 0x39, 0xde, + 0x24, 0xbc, 0xd5, 0x16, 0xf7, 0x71, 0xa3, 0x31, 0xbd, 0x45, 0x8b, 0x72, 0x06, 0xbc, 0x6d, 0x32, 0xe9, 0x2e, 0xb6, + 0x07, 0x94, 0x21, 0xed, 0xc2, 0x33, 0xdd, 0x70, 0xc0, 0xbd, 0xed, 0x34, 0xf2, 0xfc, 0xcf, 0x0b, 0xe9, 0x1c, 0x65, + 0xbf, 0x42, 0xe8, 0x59, 0xfb, 0x91, 0xaf, 0xb9, 0xbd, 0xb8, 0x85, 0xd5, 0xab, 0xa5, 0x7a, 0x8d, 0x9b, 0xeb, 0x17, + 0xed, 0xec, 0xd0, 0xb9, 0x1d, 0xf4, 0x3e, 0x84, 0x30, 0xf6, 0xb8, 0x89, 0xc7, 0xad, 0x45, 0x31, 0xbc, 0x10, 0x7c, + 0x62, 0xc7, 0xca, 0x69, 0x48, 0x07, 0x74, 0x68, 0xfc, 0xef, 0xba, 0x5e, 0xc5, 0xc1, 0xf3, 0xf1, 0xc1, 0x86, 0xb9, + 0x34, 0x48, 0x32, 0x46, 0xee, 0x34, 0xf2, 0x2f, 0xe1, 0x04, 0x2e, 0x86, 0x31, 0x0f, 0x45, 0x20, 0x09, 0xb6, 0x6d, + 0x47, 0xdc, 0x43, 0x60, 0x33, 0x7c, 0x61, 0xc1, 0xd3, 0x56, 0x4d, 0xc1, 0x13, 0x5e, 0xbd, 0x0e, 0x99, 0xfb, 0xb2, + 0xbb, 0x3d, 0x94, 0x72, 0xa4, 0x7d, 0xaf, 0x03, 0xd9, 0xaf, 0x2a, 0x1e, 0x28, 0x2d, 0x63, 0x5a, 0x68, 0x73, 0xbd, + 0x12, 0xd5, 0xaa, 0xf6, 0x27, 0xe1, 0xb9, 0x12, 0x4c, 0x77, 0xb5, 0x95, 0x2c, 0x84, 0x56, 0xaf, 0xc8, 0xf7, 0x85, + 0x15, 0x14, 0x4e, 0xa7, 0xb2, 0x21, 0x6a, 0x9f, 0xee, 0x2b, 0xe5, 0x15, 0xb8, 0x87, 0xcc, 0xd2, 0x50, 0x49, 0x11, + 0xba, 0x91, 0x3e, 0x0a, 0xea, 0x97, 0x4e, 0x97, 0x80, 0xcf, 0x9a, 0x75, 0xfe, 0x1f, 0xd6, 0xb2, 0x30, 0xa4, 0x67, + 0x88, 0x00, 0x00}; } // namespace web_server } // namespace esphome diff --git a/esphome/components/web_server/server_index_v3.h b/esphome/components/web_server/server_index_v3.h index f649a9385e..bde1ce1fb5 100644 --- a/esphome/components/web_server/server_index_v3.h +++ b/esphome/components/web_server/server_index_v3.h @@ -3632,367 +3632,373 @@ const uint8_t INDEX_GZ[] PROGMEM = { 0xe7, 0xec, 0xd8, 0x98, 0x31, 0x94, 0x4f, 0x43, 0x40, 0x9e, 0xd0, 0xf7, 0x01, 0xcd, 0x25, 0x67, 0x23, 0xad, 0x2b, 0xfb, 0x10, 0x17, 0x97, 0xdc, 0x84, 0x6a, 0x31, 0x6f, 0x2b, 0x3d, 0x2a, 0xc4, 0x1b, 0x16, 0x80, 0x65, 0xe9, 0x69, 0x93, 0x82, 0x6c, 0x94, 0x54, 0x45, 0xfe, 0x13, 0xbf, 0x03, 0xae, 0xad, 0xac, 0xe4, 0x0a, 0x78, 0xf5, 0xff, 0xd3, - 0xdc, 0xd3, 0x2f, 0xb7, 0x8d, 0x1b, 0xff, 0x7f, 0x9f, 0x82, 0x61, 0xd2, 0x1c, 0x99, 0x90, 0x34, 0x29, 0x59, 0xb6, - 0x23, 0x59, 0xf6, 0xdd, 0x25, 0xb9, 0xa9, 0x3b, 0xbe, 0xcb, 0x4d, 0xe2, 0x66, 0xda, 0xf3, 0x79, 0x2c, 0x4a, 0x82, - 0x24, 0x36, 0x14, 0xa9, 0x21, 0x29, 0x5b, 0x3e, 0x85, 0x7d, 0x96, 0x3e, 0x4b, 0x9f, 0xec, 0x37, 0xbb, 0x0b, 0x80, - 0xe0, 0x87, 0x3e, 0x7c, 0xc9, 0xb5, 0xbf, 0xb9, 0xba, 0x11, 0x41, 0x00, 0x04, 0x16, 0xc0, 0x62, 0xbf, 0xd7, 0x9f, - 0x72, 0xd9, 0x8b, 0x65, 0xb0, 0xfd, 0x3e, 0xf7, 0xf9, 0x33, 0x73, 0x70, 0x4b, 0x02, 0xc1, 0xe7, 0x64, 0xf1, 0x74, - 0x1a, 0x32, 0x43, 0x17, 0xc9, 0x43, 0x74, 0x4b, 0x7e, 0xe6, 0xfc, 0x89, 0x2b, 0x22, 0x76, 0x9a, 0xf9, 0xa6, 0xa3, - 0x25, 0x66, 0xcc, 0x64, 0x48, 0x3b, 0xa2, 0x5c, 0x51, 0x36, 0x7b, 0x87, 0xea, 0x0d, 0xbe, 0x2e, 0xc5, 0xd1, 0xb5, - 0xc7, 0xf1, 0x72, 0x18, 0x32, 0x1b, 0xb7, 0x3b, 0x7c, 0x72, 0x3d, 0x5c, 0x0e, 0x87, 0x90, 0xa5, 0xe5, 0x89, 0x6b, - 0x41, 0xdc, 0x99, 0x38, 0x45, 0x7e, 0x30, 0x37, 0x7b, 0x30, 0x29, 0x27, 0xab, 0x0e, 0x1f, 0x6c, 0x45, 0x40, 0xd4, - 0x43, 0x1f, 0xc8, 0x80, 0xf7, 0x6b, 0x38, 0xb5, 0x7d, 0xfd, 0x03, 0xec, 0xbe, 0x54, 0xef, 0x35, 0x1d, 0xfd, 0xfe, - 0xb5, 0xfe, 0x01, 0x61, 0x8c, 0xd9, 0x8b, 0x5f, 0xd3, 0xee, 0xd5, 0x2d, 0x9d, 0x94, 0xde, 0x4b, 0xcc, 0x63, 0x00, - 0x42, 0xdf, 0x37, 0x81, 0x3f, 0x8d, 0xe2, 0x34, 0x0b, 0x46, 0xfa, 0x4d, 0xef, 0x22, 0x30, 0xae, 0xe7, 0x99, 0x61, - 0xde, 0x58, 0xa3, 0x4c, 0x4d, 0x81, 0x22, 0x10, 0x26, 0x66, 0x40, 0xd9, 0x54, 0x49, 0x3d, 0x41, 0x5b, 0x2b, 0x0a, - 0xd4, 0x8c, 0x95, 0x46, 0x59, 0x1f, 0xea, 0x55, 0xf2, 0xa9, 0x60, 0x62, 0x28, 0x1d, 0x5b, 0x9a, 0x3d, 0xe2, 0x54, - 0x5e, 0x2f, 0xd7, 0x78, 0x95, 0x67, 0xc5, 0x6d, 0x89, 0x31, 0x80, 0x85, 0xe3, 0x0c, 0x3d, 0x3f, 0x51, 0x8d, 0x3e, - 0x4b, 0xf7, 0xee, 0xe0, 0xbb, 0x32, 0x5d, 0x00, 0xf7, 0x37, 0x58, 0x5c, 0x44, 0x71, 0xa6, 0x41, 0x60, 0x1b, 0xf8, - 0xe2, 0xa0, 0x6a, 0x24, 0xc6, 0x7b, 0x35, 0xcc, 0x9c, 0x23, 0x83, 0xef, 0xf1, 0xf2, 0x33, 0x78, 0x78, 0xb3, 0x52, - 0x04, 0x0b, 0x62, 0x16, 0x22, 0x58, 0xc0, 0x2c, 0xbe, 0x8c, 0xef, 0xab, 0x7a, 0x90, 0xd7, 0x83, 0xdd, 0x77, 0xaf, - 0x21, 0xc8, 0x64, 0x91, 0xd5, 0xcf, 0xe0, 0x89, 0x49, 0x05, 0xa1, 0x53, 0x39, 0x53, 0x68, 0xf8, 0x21, 0x68, 0x98, - 0x0c, 0xec, 0xc4, 0xf0, 0x2e, 0x00, 0x94, 0xc4, 0xaf, 0xe9, 0x41, 0x7e, 0x2b, 0x52, 0x27, 0x8b, 0xc4, 0xc5, 0xca, - 0xe5, 0x0c, 0xd8, 0x35, 0x5a, 0x2c, 0x33, 0x0c, 0xb5, 0x0b, 0x03, 0x60, 0xb9, 0xae, 0x61, 0xe8, 0x4e, 0xc0, 0xd2, - 0x05, 0x99, 0x98, 0xeb, 0x5a, 0x30, 0xae, 0x97, 0x71, 0xa2, 0x17, 0x90, 0x17, 0xe2, 0x77, 0x14, 0x54, 0xc1, 0x63, - 0xc2, 0xa7, 0x31, 0xb2, 0x8a, 0x38, 0xf5, 0xc6, 0x08, 0x15, 0x3a, 0x0d, 0x98, 0x61, 0x44, 0xfd, 0xf4, 0x8c, 0xb0, - 0x71, 0xb2, 0x10, 0x7e, 0xb3, 0x34, 0xcd, 0xc1, 0xb3, 0x75, 0x94, 0x9f, 0x3f, 0x5b, 0xa7, 0x79, 0xff, 0xd9, 0xda, - 0x97, 0xb6, 0x02, 0xfa, 0x95, 0x4e, 0x86, 0x02, 0x03, 0x04, 0xc3, 0x20, 0xbf, 0x2d, 0x3c, 0x77, 0x8a, 0xf9, 0xc2, - 0x2e, 0xa3, 0x72, 0x0d, 0x55, 0xf7, 0x7d, 0xae, 0xa0, 0x5f, 0x24, 0xc1, 0xdc, 0x4f, 0x1e, 0x48, 0x9f, 0x6f, 0xa9, - 0x4a, 0x7f, 0x53, 0xd7, 0x08, 0xd1, 0x13, 0x00, 0x08, 0xe7, 0xeb, 0xda, 0xb7, 0xb2, 0x8c, 0xf1, 0xd9, 0x4a, 0xa5, - 0x26, 0x7c, 0xeb, 0x56, 0x7f, 0xc9, 0x9c, 0x31, 0xcb, 0xfc, 0x20, 0xa4, 0x26, 0x3d, 0x91, 0xad, 0xbe, 0x36, 0xbd, - 0xb4, 0x3c, 0xbd, 0xa8, 0xbc, 0x7f, 0x70, 0x32, 0x74, 0x05, 0xd0, 0xb8, 0x71, 0x66, 0x98, 0xc5, 0xaa, 0x79, 0x45, - 0xe9, 0xdd, 0x7f, 0x75, 0x39, 0x18, 0x2c, 0x47, 0x04, 0xcb, 0xc1, 0xa2, 0x51, 0x3c, 0x66, 0x7f, 0x7b, 0x7f, 0x21, - 0xd3, 0x66, 0x81, 0x04, 0x68, 0xc0, 0x37, 0x66, 0x8a, 0xf4, 0x43, 0x82, 0xb4, 0x03, 0x25, 0xb8, 0xd2, 0xe4, 0x16, - 0x4a, 0x72, 0x5d, 0x3b, 0xa7, 0xb1, 0xb3, 0x31, 0x8d, 0xba, 0x1f, 0x63, 0xab, 0x24, 0x3f, 0x3d, 0xa0, 0xda, 0x74, - 0xdb, 0x51, 0x25, 0x00, 0x43, 0x02, 0x33, 0x2c, 0xa0, 0x00, 0x19, 0x3e, 0xfb, 0x5e, 0xc1, 0x50, 0x38, 0x73, 0x94, - 0xb3, 0x7b, 0xe7, 0x65, 0x52, 0x05, 0x5b, 0xe9, 0x67, 0xa7, 0x98, 0xb3, 0x0b, 0xee, 0x6b, 0x88, 0xf2, 0x71, 0x7a, - 0x40, 0x8f, 0x5a, 0xe5, 0x44, 0x14, 0x9d, 0x08, 0xd6, 0xae, 0xcb, 0x3b, 0x78, 0xd4, 0x51, 0x81, 0x14, 0xf1, 0x50, - 0xea, 0xe7, 0xba, 0x36, 0xe7, 0xa4, 0x11, 0x0f, 0x27, 0x04, 0xb1, 0x06, 0x5c, 0x38, 0xbb, 0xba, 0x36, 0xf7, 0x57, - 0x38, 0x73, 0xf1, 0xc6, 0x5f, 0x19, 0x1e, 0x7f, 0x55, 0x9c, 0xb5, 0xb4, 0x7c, 0xd6, 0x46, 0x7c, 0x71, 0xc1, 0x91, - 0x40, 0x72, 0xd6, 0x33, 0x54, 0xd0, 0x36, 0x2c, 0xee, 0x4c, 0x2c, 0xee, 0x78, 0xc3, 0xe2, 0x8e, 0xb7, 0x2c, 0x6e, - 0xc8, 0x17, 0x52, 0x93, 0xa0, 0x4b, 0xd0, 0x39, 0x4c, 0x02, 0x8f, 0x13, 0x1a, 0x5d, 0x7e, 0xce, 0x10, 0x4e, 0x76, - 0x1a, 0x82, 0x71, 0xd4, 0x06, 0x58, 0x35, 0xc1, 0x45, 0x01, 0x44, 0x7d, 0xe2, 0xf2, 0xd4, 0x89, 0x79, 0x43, 0x0e, - 0x4e, 0x23, 0xac, 0xce, 0x17, 0x76, 0x29, 0xe5, 0x17, 0x37, 0x66, 0x1b, 0x66, 0x3a, 0xdb, 0x32, 0xd3, 0x51, 0xe9, - 0xe8, 0xf2, 0x69, 0xd3, 0x21, 0x54, 0x27, 0x05, 0x7b, 0x10, 0x0c, 0x46, 0x71, 0xcb, 0x94, 0xf7, 0xe1, 0x66, 0x1c, - 0xab, 0xec, 0xa8, 0x85, 0x9f, 0xa6, 0xf7, 0x71, 0x02, 0x1a, 0x17, 0xe8, 0xe6, 0x71, 0x5b, 0x6a, 0x1e, 0x44, 0x3c, - 0x98, 0xcb, 0xc6, 0xcd, 0x54, 0xbc, 0x57, 0xb7, 0x54, 0xab, 0xd3, 0xa1, 0x1a, 0x0b, 0x3f, 0xcb, 0x58, 0x82, 0x40, - 0xf7, 0x21, 0xea, 0xf7, 0xff, 0x93, 0x6d, 0xd6, 0x80, 0x43, 0x42, 0x05, 0xab, 0x23, 0x86, 0x5e, 0x00, 0x6d, 0x95, - 0x88, 0x8b, 0x58, 0x09, 0x0c, 0x97, 0x48, 0xc0, 0xff, 0x84, 0xc7, 0xd5, 0x48, 0x14, 0xd7, 0x25, 0xef, 0xc8, 0x74, - 0x16, 0xfe, 0xf8, 0x03, 0x28, 0xf6, 0x8c, 0x96, 0x05, 0x46, 0xba, 0x6a, 0x18, 0xb8, 0x84, 0x88, 0xbd, 0x51, 0x81, - 0x24, 0x11, 0x4b, 0x72, 0x13, 0x28, 0xf0, 0x9e, 0xf4, 0xed, 0xc9, 0xcd, 0xba, 0x95, 0x1f, 0x4c, 0x03, 0xb3, 0x86, - 0x35, 0x01, 0xb5, 0x85, 0xfd, 0x33, 0xc9, 0x73, 0x85, 0x96, 0x77, 0x64, 0x82, 0xe4, 0xf7, 0x1a, 0xf2, 0x99, 0xba, - 0x82, 0xa1, 0x1d, 0x24, 0x70, 0x6b, 0x5d, 0xbb, 0x37, 0xf9, 0xf3, 0x29, 0xfe, 0xf2, 0x6e, 0xf2, 0xe7, 0x43, 0xfc, - 0xd5, 0xba, 0xc1, 0xcc, 0x75, 0x0d, 0x8c, 0xbc, 0x32, 0x67, 0xfd, 0xac, 0xb4, 0x9f, 0xc8, 0xfe, 0xec, 0x11, 0xdb, - 0x86, 0x2f, 0xf0, 0xd3, 0x67, 0xeb, 0x14, 0x3c, 0x2e, 0xd5, 0x39, 0x44, 0x4e, 0x62, 0xe6, 0x8d, 0xe5, 0xd3, 0x0d, - 0xe5, 0x43, 0xf3, 0xbf, 0x7c, 0xf1, 0xe3, 0x2e, 0x89, 0x8b, 0x3b, 0xa5, 0x2c, 0x86, 0xb8, 0x1d, 0x06, 0x91, 0x9f, - 0x3c, 0xdc, 0x12, 0x7b, 0x61, 0x08, 0xda, 0x5d, 0x8a, 0x57, 0x88, 0xbc, 0x2c, 0xab, 0xbb, 0x32, 0x45, 0xc0, 0xfb, - 0xc0, 0x2f, 0xfa, 0xfe, 0xdf, 0x13, 0x85, 0x6c, 0x2b, 0x31, 0xa0, 0x7c, 0x41, 0x4a, 0x1f, 0xba, 0x7d, 0xb6, 0x36, - 0x58, 0xbd, 0x9b, 0xca, 0x6c, 0x2b, 0x74, 0x21, 0x2c, 0x0f, 0x32, 0xb3, 0xf3, 0x71, 0xd0, 0x45, 0x7d, 0xd6, 0x30, - 0x5e, 0xd9, 0xcf, 0xd6, 0xd9, 0xb9, 0x3e, 0xf7, 0x93, 0x4f, 0x6c, 0x6c, 0x8f, 0x82, 0x64, 0x14, 0x32, 0xbd, 0xab, - 0x0f, 0x43, 0x3f, 0xfa, 0xc4, 0x1f, 0xed, 0x78, 0x99, 0xa1, 0x86, 0x7a, 0x27, 0xef, 0x2b, 0x60, 0x42, 0x22, 0x3b, - 0x24, 0x56, 0x1b, 0xa0, 0xa0, 0xbd, 0x96, 0x02, 0xaf, 0x82, 0x50, 0x2c, 0x6a, 0x59, 0x60, 0x60, 0x09, 0x4a, 0x73, - 0xf0, 0x58, 0xb5, 0x74, 0x5c, 0x2f, 0xdd, 0x52, 0xa7, 0x4a, 0xc2, 0x4a, 0x99, 0x72, 0xf1, 0x16, 0x7b, 0xf8, 0xfd, - 0x9f, 0xa3, 0x64, 0xd8, 0xfb, 0x7f, 0x4e, 0xf6, 0xf2, 0x65, 0x33, 0x84, 0x52, 0x9b, 0x3c, 0x25, 0x1e, 0xf1, 0x71, - 0x4e, 0x60, 0x6e, 0xfe, 0xb4, 0xda, 0xd8, 0x4f, 0xd3, 0xe5, 0x9c, 0x8d, 0x49, 0x33, 0x78, 0x5e, 0x0c, 0xaa, 0xcc, - 0x59, 0xa8, 0x03, 0xfb, 0x75, 0xd9, 0x3a, 0x3e, 0x7c, 0x0d, 0x16, 0x0b, 0x40, 0x50, 0xc6, 0x93, 0x89, 0x5e, 0xf0, - 0xf8, 0x3b, 0x9a, 0x79, 0x87, 0xbf, 0x2e, 0x7f, 0x78, 0xeb, 0xfe, 0x20, 0x1b, 0x47, 0x40, 0x18, 0x0b, 0xf5, 0x2b, - 0xa7, 0x8b, 0x95, 0xf1, 0x8a, 0x19, 0x4d, 0xfc, 0x68, 0xf3, 0x74, 0xae, 0x4b, 0x5b, 0x7c, 0xc1, 0xd8, 0x18, 0x08, - 0x6e, 0xab, 0x56, 0x7a, 0x1b, 0xb2, 0x3b, 0x26, 0x55, 0xbb, 0xf5, 0x8f, 0x35, 0xb4, 0xc0, 0xd8, 0x73, 0x5c, 0x65, - 0xcc, 0xa9, 0x3a, 0x65, 0x4a, 0x03, 0x9c, 0x03, 0x9f, 0xb9, 0x7a, 0xc4, 0x2a, 0x47, 0x6a, 0x60, 0xe9, 0xca, 0x00, - 0x36, 0x8e, 0xec, 0x7c, 0x43, 0x79, 0x17, 0x13, 0x4f, 0x37, 0x8f, 0xcd, 0xf2, 0xcc, 0x2e, 0xc4, 0xea, 0xe6, 0x70, - 0x0a, 0xe1, 0xe4, 0x19, 0x85, 0x38, 0x64, 0x13, 0xc4, 0x9a, 0x84, 0x64, 0x3a, 0x49, 0x5f, 0x84, 0xb5, 0x23, 0x9a, - 0xfd, 0x0a, 0x39, 0x54, 0xe3, 0xda, 0x68, 0xe5, 0x99, 0x0f, 0x31, 0xa1, 0x6b, 0xc4, 0xd2, 0x74, 0x23, 0xc0, 0xe4, - 0xa2, 0x5b, 0x7a, 0x51, 0xbb, 0x0c, 0x8f, 0xa2, 0xdc, 0x72, 0x2d, 0x20, 0x09, 0x70, 0x82, 0xd5, 0x6f, 0xe1, 0xf5, - 0x72, 0x3b, 0xe7, 0xf6, 0x2a, 0xc9, 0x74, 0xa8, 0x73, 0x5b, 0x82, 0x4d, 0xef, 0xef, 0x75, 0x3e, 0xa8, 0xd2, 0x35, - 0xdd, 0x38, 0x34, 0xa3, 0x84, 0x7a, 0x6b, 0xe2, 0x22, 0xec, 0x40, 0x8c, 0xa9, 0x82, 0x5f, 0xd9, 0x64, 0xc2, 0x46, - 0x59, 0x6a, 0x0a, 0xe1, 0x91, 0x8c, 0x1e, 0x0b, 0x5e, 0x43, 0x4f, 0xfa, 0xfa, 0x4f, 0xe0, 0x43, 0x2f, 0x82, 0x2c, - 0xf1, 0x01, 0x09, 0x9e, 0xa9, 0x19, 0x4c, 0xd4, 0x63, 0x19, 0x44, 0xfc, 0x2b, 0x90, 0x1c, 0xbc, 0xa1, 0x1c, 0x87, - 0xc6, 0xef, 0x9f, 0x62, 0x5f, 0xc4, 0xd2, 0xaa, 0x65, 0x3b, 0x2a, 0xda, 0x76, 0x7c, 0xd7, 0xde, 0x0f, 0x1d, 0xcf, - 0xcd, 0x75, 0x0b, 0x7c, 0xb7, 0x3e, 0xed, 0x7b, 0xe8, 0xb1, 0x55, 0x1b, 0x5a, 0x2d, 0xa3, 0xc7, 0xb4, 0x6b, 0x79, - 0xaf, 0x3c, 0xdd, 0x22, 0x93, 0x39, 0x05, 0xb7, 0x8d, 0xe2, 0x3b, 0x96, 0x7c, 0xf1, 0x54, 0xca, 0x9d, 0xef, 0x37, - 0x9e, 0x23, 0xcf, 0x05, 0x24, 0x9c, 0xc5, 0x8b, 0x47, 0x4c, 0xa1, 0xad, 0x5b, 0xfa, 0x28, 0x8c, 0x53, 0xa6, 0xce, - 0x81, 0x84, 0x20, 0x5f, 0x38, 0x89, 0x9f, 0xdf, 0xbf, 0xfd, 0xf0, 0x41, 0xb7, 0x30, 0x13, 0x68, 0xaa, 0xf6, 0xce, - 0x37, 0xd4, 0x0e, 0xec, 0xdf, 0xb8, 0xef, 0xe8, 0x86, 0x21, 0xa6, 0xb6, 0xbc, 0xe7, 0xa8, 0xac, 0xb6, 0xe5, 0xf8, - 0xcd, 0xc3, 0xbf, 0x4c, 0x9c, 0xe8, 0x5e, 0xf3, 0x6a, 0xc0, 0x0d, 0xdb, 0xaf, 0xb7, 0x52, 0xc9, 0x3c, 0x88, 0x6e, - 0x1b, 0x4a, 0xfd, 0x55, 0x43, 0x29, 0xb0, 0x72, 0x35, 0x5c, 0xb5, 0x8c, 0xe7, 0x0a, 0x69, 0x00, 0x89, 0x9c, 0x77, - 0x81, 0x4b, 0xe1, 0xa7, 0xbe, 0x60, 0xd0, 0x3c, 0x92, 0x7b, 0x75, 0xd4, 0x0d, 0xc5, 0x9c, 0x09, 0x92, 0xb0, 0x1d, - 0x85, 0x60, 0xf0, 0xc7, 0x54, 0xad, 0x5c, 0x99, 0x6c, 0x94, 0xe6, 0xba, 0x4a, 0x27, 0x44, 0xde, 0xde, 0x66, 0x6c, - 0xbe, 0x60, 0x89, 0x9f, 0x2d, 0x13, 0x76, 0x1b, 0xc6, 0xf7, 0x4f, 0x0a, 0x73, 0xfa, 0x1d, 0x95, 0x67, 0xc1, 0x74, - 0x26, 0x6b, 0x9f, 0x1b, 0xac, 0x2f, 0x17, 0x70, 0xeb, 0x07, 0xf2, 0xff, 0xfc, 0xdb, 0x71, 0xfe, 0xf3, 0xef, 0x9d, - 0x55, 0xa1, 0xfb, 0x7c, 0x60, 0x65, 0xfd, 0x3d, 0xf6, 0x45, 0xf3, 0x97, 0xca, 0x30, 0x6f, 0xae, 0x53, 0x5b, 0x04, - 0x78, 0x5f, 0x5b, 0x82, 0x5a, 0x61, 0x79, 0xdf, 0x3c, 0x6a, 0x60, 0x30, 0xaf, 0x9d, 0x23, 0x83, 0x4a, 0x5f, 0x34, - 0xb4, 0x81, 0xd9, 0xdd, 0x6b, 0x45, 0x7e, 0x3f, 0x84, 0x77, 0xcd, 0xe1, 0x0b, 0x87, 0xcf, 0xe5, 0x92, 0xaf, 0x07, - 0x03, 0x99, 0x5b, 0x4e, 0x6d, 0x0a, 0x26, 0xfe, 0xe7, 0xb5, 0x12, 0x7e, 0x79, 0x76, 0x5d, 0x93, 0x7c, 0xef, 0xfb, - 0xaf, 0x07, 0x68, 0x8c, 0x76, 0x3a, 0x4c, 0x0a, 0x62, 0x65, 0x23, 0x6a, 0x23, 0x63, 0xf2, 0x5a, 0xa7, 0x35, 0xbc, - 0x06, 0xa5, 0x98, 0x70, 0x2c, 0x1f, 0x98, 0xd6, 0xeb, 0x01, 0x17, 0x2c, 0x71, 0xfb, 0xd7, 0x6e, 0x75, 0x6b, 0x73, - 0xb1, 0x6c, 0x09, 0xe8, 0x96, 0x46, 0xfa, 0x1f, 0xac, 0xcc, 0x0a, 0x39, 0x1e, 0x0a, 0xf8, 0x41, 0xa2, 0x30, 0xc8, - 0x31, 0xdf, 0xc9, 0xbb, 0x4d, 0x36, 0x62, 0x3f, 0xef, 0xb6, 0x11, 0xbb, 0xda, 0xcb, 0x46, 0xec, 0xe7, 0xaf, 0x6e, - 0x23, 0xf6, 0x4e, 0xb5, 0x11, 0x83, 0x45, 0x7c, 0xcb, 0xf6, 0x32, 0xdc, 0x12, 0x56, 0x1b, 0xf1, 0x7d, 0xda, 0xf7, - 0x38, 0x49, 0x9b, 0x8e, 0x66, 0x0c, 0x64, 0x04, 0x7c, 0x55, 0xc2, 0x78, 0x0a, 0x46, 0x5c, 0x7f, 0xbc, 0xb9, 0x55, - 0x18, 0x4f, 0x55, 0x63, 0xab, 0x88, 0x47, 0x7c, 0x2d, 0xa2, 0x38, 0x91, 0x81, 0x93, 0x6b, 0x89, 0x98, 0x4f, 0xf6, - 0xa1, 0xa9, 0x64, 0xb5, 0x96, 0xd6, 0x6b, 0x2d, 0x61, 0x02, 0xd5, 0x45, 0xeb, 0x29, 0xd9, 0xb0, 0xf5, 0x52, 0xc4, - 0xb6, 0x50, 0x7b, 0x90, 0x56, 0xc2, 0x14, 0x27, 0x62, 0xad, 0xff, 0xba, 0xf2, 0xbe, 0xbf, 0xf6, 0x7a, 0x6d, 0x0f, - 0x9c, 0xb3, 0x81, 0xc3, 0xc4, 0x02, 0xb7, 0xd7, 0x6e, 0x43, 0xc1, 0xbd, 0x52, 0xd0, 0x82, 0x82, 0x40, 0x29, 0xe8, - 0x40, 0xc1, 0x48, 0x29, 0x38, 0x82, 0x82, 0xb1, 0x52, 0x70, 0x0c, 0x05, 0x77, 0x7a, 0x7e, 0x1d, 0xc9, 0xe1, 0x1e, - 0x9b, 0x37, 0x16, 0x31, 0x15, 0xa2, 0xec, 0xd8, 0xf2, 0xc0, 0x6a, 0xca, 0x9f, 0x76, 0x63, 0x8b, 0xa4, 0x8b, 0xdd, - 0xc4, 0xba, 0x9f, 0x31, 0x0a, 0x14, 0xfd, 0x06, 0xef, 0x1c, 0x27, 0x8b, 0xc1, 0x6e, 0x5a, 0x04, 0x60, 0x10, 0x70, - 0xd0, 0x74, 0x13, 0x04, 0x46, 0x3d, 0xb9, 0x72, 0x22, 0x88, 0x85, 0xb2, 0x96, 0xc5, 0x3b, 0xfa, 0x9c, 0x2d, 0xb7, - 0x40, 0x61, 0x71, 0x62, 0xa8, 0x52, 0xc9, 0xaf, 0x61, 0x77, 0xf0, 0x86, 0x0d, 0x97, 0x53, 0xed, 0x32, 0x9e, 0xee, - 0x34, 0x21, 0x50, 0x5f, 0xc1, 0x28, 0x75, 0x52, 0xbf, 0xd8, 0x62, 0x5b, 0xf2, 0x6f, 0xd1, 0x63, 0x5e, 0xae, 0x9f, - 0xc1, 0xd8, 0xb4, 0x8c, 0x0c, 0x58, 0xe0, 0x3b, 0x00, 0x23, 0x45, 0x87, 0x7f, 0x09, 0x70, 0x56, 0x9e, 0xaf, 0x7c, - 0x65, 0x3c, 0x67, 0x3f, 0xb2, 0x34, 0xf5, 0xa7, 0xa2, 0x7e, 0x7d, 0x9c, 0x60, 0xb4, 0x23, 0xf9, 0x2f, 0x04, 0x20, - 0x48, 0xf2, 0x82, 0x9a, 0x6d, 0x46, 0x12, 0xdf, 0x6b, 0x60, 0xfd, 0x03, 0x1b, 0xaa, 0xb0, 0x53, 0x08, 0x1c, 0x58, - 0xc2, 0xb2, 0x45, 0x01, 0x1c, 0xfe, 0x3b, 0x16, 0x56, 0x0b, 0x33, 0x7f, 0x5a, 0x2d, 0xa2, 0x7d, 0x90, 0xab, 0x63, - 0x93, 0x0a, 0xfd, 0x52, 0xe1, 0x97, 0x68, 0xa8, 0xc3, 0x78, 0xfa, 0x87, 0xaa, 0xa7, 0xb7, 0x98, 0x15, 0x7c, 0x88, - 0xac, 0x20, 0x1b, 0x38, 0x08, 0x63, 0xcd, 0x01, 0x10, 0x76, 0xa3, 0x6c, 0x66, 0xa3, 0x6b, 0x99, 0xd1, 0x8a, 0x4c, - 0xcb, 0xc1, 0xb5, 0x5d, 0x57, 0x1d, 0x6a, 0xbb, 0xc9, 0x74, 0xe8, 0x1b, 0x5e, 0xeb, 0xd8, 0x12, 0x7f, 0x8e, 0xdb, - 0x31, 0x73, 0xec, 0x41, 0x1b, 0x07, 0x77, 0xeb, 0x49, 0x1c, 0x65, 0xf6, 0xc4, 0x9f, 0x07, 0xe1, 0x43, 0x77, 0x1e, - 0x47, 0x71, 0xba, 0xf0, 0x47, 0xac, 0x57, 0x30, 0xd4, 0x3d, 0x0c, 0xd5, 0xc0, 0xbd, 0x05, 0x3d, 0xa7, 0x95, 0xb0, - 0x39, 0xb5, 0x96, 0x91, 0x18, 0x26, 0x21, 0x5b, 0xe5, 0xfc, 0xf3, 0xa5, 0xca, 0x54, 0x15, 0xb7, 0x1c, 0xb5, 0x00, - 0x8a, 0x94, 0x87, 0x79, 0x80, 0xe0, 0x46, 0xbd, 0x85, 0x3f, 0xc6, 0xc8, 0x84, 0x4e, 0xab, 0x93, 0xb0, 0xb9, 0xe6, - 0x74, 0x36, 0x76, 0x9e, 0xc4, 0xf7, 0x67, 0x30, 0x5a, 0x6c, 0x6c, 0xa7, 0x2c, 0x9c, 0xe0, 0x1b, 0x1b, 0x3d, 0x4b, - 0x44, 0x3f, 0x36, 0x32, 0xe2, 0xd0, 0x1b, 0x9b, 0xf7, 0xe0, 0x75, 0xb7, 0xa5, 0xb9, 0xbd, 0x79, 0x10, 0xd9, 0x34, - 0x9d, 0x63, 0x77, 0xa1, 0xf4, 0xa5, 0xc2, 0xcf, 0x5c, 0x63, 0x75, 0x4f, 0x73, 0x7b, 0xc0, 0xac, 0x4d, 0xc2, 0xf8, - 0xbe, 0x3b, 0x0b, 0xc6, 0x63, 0x16, 0xf5, 0x70, 0xcc, 0xb2, 0x90, 0x85, 0x61, 0xb0, 0x48, 0x83, 0xb4, 0x37, 0xf7, - 0x57, 0xbc, 0xd7, 0xc3, 0x4d, 0xbd, 0xb6, 0x79, 0xaf, 0xed, 0xbd, 0x7b, 0x55, 0xba, 0x01, 0x2f, 0x16, 0xea, 0x87, - 0x0f, 0xad, 0xa3, 0xb9, 0x95, 0x79, 0xee, 0xdd, 0xeb, 0x22, 0x61, 0xeb, 0xb9, 0x9f, 0x4c, 0x83, 0xa8, 0xeb, 0xe6, - 0xce, 0xdd, 0x9a, 0x36, 0xc6, 0xd3, 0x93, 0x93, 0x93, 0xdc, 0x19, 0x8b, 0x27, 0x77, 0x3c, 0xce, 0x9d, 0x91, 0x78, - 0x9a, 0x4c, 0x5c, 0x77, 0x32, 0xc9, 0x9d, 0x40, 0x14, 0xb4, 0x5b, 0xa3, 0x71, 0xbb, 0x95, 0x3b, 0xf7, 0x4a, 0x8d, - 0xdc, 0x61, 0xfc, 0x29, 0x61, 0xe3, 0x1e, 0x6e, 0x24, 0x32, 0x2b, 0xed, 0x1e, 0xbb, 0x6e, 0x8e, 0x18, 0xe0, 0xba, - 0x84, 0x9b, 0x50, 0xd6, 0x73, 0xb3, 0xde, 0xbb, 0xa6, 0x56, 0x7c, 0x6e, 0x34, 0x6a, 0xac, 0x37, 0xf6, 0x93, 0x4f, - 0x37, 0x9a, 0x32, 0x0b, 0xdf, 0xa7, 0x6a, 0x6b, 0x01, 0x06, 0x7b, 0xd5, 0x85, 0x90, 0x5d, 0xbd, 0x61, 0x9c, 0xc0, - 0x99, 0x4d, 0xfc, 0x71, 0xb0, 0x4c, 0xbb, 0x5e, 0x6b, 0xb1, 0x12, 0x45, 0x7c, 0xaf, 0x17, 0x05, 0x78, 0xf6, 0xba, - 0x69, 0x1c, 0x06, 0x63, 0x51, 0xb4, 0xe9, 0x2c, 0x79, 0x2d, 0xb3, 0x87, 0x0e, 0xeb, 0x01, 0x86, 0x5d, 0xf0, 0xc3, - 0x50, 0x73, 0xda, 0xa9, 0xc6, 0xfc, 0x14, 0xe5, 0xcb, 0x9a, 0x9b, 0x12, 0x5c, 0xd0, 0x39, 0xdd, 0x3b, 0x5c, 0xac, - 0xe4, 0x9e, 0xf7, 0x8e, 0x16, 0xab, 0xfc, 0xdb, 0x39, 0x1b, 0x07, 0xbe, 0x66, 0x14, 0xbb, 0xc9, 0x73, 0x41, 0x06, - 0x6d, 0xae, 0x37, 0x6c, 0x53, 0x71, 0x2c, 0x20, 0xb4, 0xe1, 0x93, 0x60, 0xbe, 0x88, 0x93, 0xcc, 0x8f, 0xb2, 0x3c, - 0x1f, 0xdc, 0xe4, 0x79, 0xef, 0x2a, 0x30, 0xae, 0xff, 0x61, 0xd0, 0x3d, 0x4d, 0x3a, 0x9b, 0xdc, 0xbc, 0xb1, 0xde, - 0x32, 0xd5, 0x66, 0x04, 0xae, 0x31, 0xb4, 0x17, 0x51, 0x2b, 0xd3, 0x2d, 0x59, 0xaf, 0x4c, 0x40, 0x96, 0xd5, 0xc9, - 0x06, 0xa5, 0x5c, 0x05, 0x6f, 0x20, 0xa8, 0xf0, 0x96, 0xf5, 0xaf, 0x14, 0xfb, 0x13, 0x20, 0x56, 0xb0, 0x32, 0xf9, - 0x15, 0x3c, 0xdb, 0x44, 0x33, 0x7e, 0xb7, 0x9b, 0x66, 0xfc, 0x25, 0xdb, 0x87, 0x66, 0xfc, 0xee, 0xab, 0xd3, 0x8c, - 0xcf, 0xea, 0x7e, 0x05, 0x17, 0x71, 0x5f, 0x97, 0x1a, 0x06, 0xb8, 0x9a, 0x12, 0x8a, 0xd8, 0x73, 0xf1, 0xbb, 0xdd, - 0x00, 0x44, 0x6f, 0x94, 0x83, 0x8e, 0x6e, 0x6e, 0x90, 0xc7, 0xbe, 0x8b, 0xfa, 0x7f, 0x4f, 0xd4, 0xe7, 0xc9, 0xa4, - 0xff, 0x26, 0x56, 0x0a, 0xe4, 0x13, 0x37, 0xbe, 0x28, 0x45, 0x57, 0xa0, 0x37, 0xc2, 0x0a, 0x13, 0xf3, 0x4f, 0x80, - 0x73, 0x36, 0x59, 0x1d, 0x8f, 0xa5, 0xf5, 0x59, 0xaf, 0x3c, 0x04, 0x43, 0x9a, 0x7c, 0x0a, 0x17, 0x9c, 0x9a, 0x28, - 0x71, 0xca, 0x32, 0xee, 0x33, 0xfb, 0xfd, 0xc3, 0xc5, 0xd8, 0xb8, 0x88, 0xcd, 0x3c, 0x48, 0xdf, 0x55, 0x1d, 0x60, - 0xb8, 0xee, 0xa7, 0xaf, 0x4e, 0x27, 0xe7, 0x16, 0x64, 0x6a, 0x82, 0x69, 0x78, 0x4d, 0xcd, 0xcf, 0x4b, 0x33, 0xed, - 0xaa, 0x0d, 0x79, 0xa2, 0xab, 0xda, 0x65, 0xcc, 0xbd, 0x0f, 0xd6, 0x9c, 0x02, 0xc4, 0xdc, 0x5d, 0xe8, 0x37, 0x3c, - 0xa6, 0xe6, 0xc1, 0x38, 0xcf, 0xcd, 0x9e, 0x00, 0x84, 0x72, 0xd1, 0xb2, 0x5d, 0x44, 0x5c, 0x7a, 0x2f, 0x6d, 0x1a, - 0xb8, 0x86, 0x90, 0xd4, 0x7f, 0x17, 0xa0, 0x50, 0xe7, 0xca, 0x42, 0x0e, 0x33, 0x5d, 0x23, 0xf0, 0x91, 0xa1, 0x85, - 0x32, 0x21, 0xd0, 0x00, 0x4b, 0xf8, 0x8b, 0x57, 0xa2, 0xa0, 0x6e, 0xc3, 0x49, 0xc0, 0x41, 0x8b, 0x00, 0xf0, 0xf2, - 0x17, 0x72, 0x6d, 0x42, 0x3b, 0xbc, 0x0e, 0x3e, 0xe4, 0xba, 0xa4, 0xfd, 0x70, 0xfb, 0x9d, 0x9d, 0x1e, 0x40, 0x83, - 0xb3, 0x8a, 0xe1, 0xc0, 0x0e, 0x0b, 0x45, 0x20, 0x25, 0xd2, 0x7b, 0xcb, 0x49, 0xef, 0xb5, 0x17, 0x6b, 0x11, 0x21, - 0x23, 0xf3, 0x17, 0x36, 0xb0, 0xf8, 0x88, 0x7b, 0x39, 0xc6, 0x53, 0x82, 0x71, 0xf4, 0x96, 0x29, 0xe0, 0x46, 0x64, - 0x54, 0x11, 0xff, 0xf4, 0x46, 0xcb, 0x24, 0x8d, 0x93, 0xee, 0x22, 0x0e, 0xa2, 0x8c, 0x25, 0x39, 0x82, 0xea, 0x1a, - 0xe1, 0x23, 0xc0, 0x73, 0xb3, 0x8e, 0x17, 0xfe, 0x28, 0xc8, 0x1e, 0xba, 0x2e, 0x27, 0x29, 0xdc, 0x1e, 0xa7, 0x0e, - 0xdc, 0xc6, 0xfa, 0x5d, 0x0e, 0xcd, 0x97, 0x48, 0xf8, 0x25, 0x75, 0x72, 0x46, 0xdd, 0xe6, 0x3d, 0xe5, 0x2d, 0xc5, - 0x08, 0x01, 0xf2, 0xc3, 0x4f, 0xec, 0x29, 0x60, 0x79, 0x58, 0x6a, 0x77, 0xcc, 0xa6, 0x16, 0x62, 0x6d, 0x90, 0xcb, - 0x8b, 0x3f, 0xa7, 0x63, 0x6a, 0x6e, 0x73, 0x31, 0x50, 0x3c, 0xe6, 0x3e, 0x23, 0xeb, 0xfa, 0x90, 0x51, 0xcb, 0xda, - 0xa7, 0xe6, 0x90, 0x4d, 0xe2, 0x84, 0x51, 0x3c, 0x59, 0xef, 0x64, 0xb1, 0xda, 0xbf, 0xfb, 0xed, 0xd3, 0x6f, 0xee, - 0x27, 0x8a, 0x33, 0x43, 0x74, 0x66, 0xee, 0xe8, 0xad, 0x7e, 0x9f, 0x01, 0x69, 0x48, 0x90, 0x1f, 0x51, 0xe8, 0xae, - 0xae, 0xae, 0xf7, 0x1a, 0xc3, 0x76, 0x2d, 0x62, 0x7e, 0xe7, 0x25, 0x2c, 0xf4, 0xb3, 0xe0, 0x4e, 0xd0, 0x8c, 0xed, - 0xa3, 0xc5, 0x4a, 0xac, 0x31, 0x5e, 0x78, 0x8f, 0x58, 0xa4, 0xca, 0x50, 0xc4, 0x22, 0x55, 0x8b, 0x71, 0x91, 0x7a, - 0xb5, 0xd9, 0x88, 0x48, 0x16, 0x95, 0x9b, 0xbe, 0xb3, 0x58, 0xa9, 0x57, 0x74, 0xd1, 0x4c, 0xde, 0xd4, 0xd5, 0x10, - 0x64, 0xf3, 0x60, 0x3c, 0x0e, 0x59, 0x5e, 0x5a, 0xe8, 0xf2, 0x5a, 0x2a, 0xc0, 0x91, 0x70, 0xf0, 0x87, 0x69, 0x1c, - 0x2e, 0x33, 0xd6, 0x0c, 0x2e, 0x02, 0x4e, 0xcb, 0x2d, 0x80, 0x83, 0xbf, 0xcb, 0x63, 0xed, 0x00, 0xb9, 0x0d, 0xdb, - 0xc4, 0xed, 0x41, 0xc4, 0x61, 0xbb, 0x5d, 0x1e, 0x3a, 0xbc, 0x92, 0x83, 0xb6, 0x1a, 0x26, 0x62, 0xc1, 0xb5, 0x44, - 0xd8, 0x5b, 0x73, 0x3c, 0x5e, 0x26, 0xa3, 0xae, 0xca, 0xa2, 0xbc, 0x3c, 0x99, 0x3f, 0xe6, 0x8c, 0xbd, 0x6a, 0x3e, - 0x63, 0xaf, 0xc4, 0x19, 0xdb, 0xbe, 0x33, 0x9f, 0x4e, 0x3c, 0xf8, 0xaf, 0x57, 0x4c, 0xa8, 0xeb, 0x6a, 0xed, 0xc5, - 0x4a, 0xf3, 0x16, 0x2b, 0xcd, 0x6e, 0x2d, 0x56, 0x1a, 0x76, 0x8d, 0xf6, 0x20, 0x96, 0xd3, 0x32, 0x2d, 0x57, 0x83, - 0x42, 0xf8, 0x73, 0x4b, 0xaf, 0xbc, 0x43, 0x78, 0x07, 0xad, 0x3a, 0xf5, 0x77, 0xad, 0xed, 0x47, 0x9d, 0xce, 0x92, - 0x40, 0xda, 0xa6, 0x93, 0xf9, 0xc3, 0x21, 0x1b, 0x77, 0x27, 0xf1, 0x68, 0x99, 0xfe, 0x8b, 0x8f, 0x9f, 0x03, 0x71, - 0x2b, 0x22, 0xa8, 0xf4, 0x23, 0x9a, 0x82, 0xa2, 0xe4, 0x8e, 0x89, 0x1e, 0xd6, 0x72, 0x9d, 0xba, 0x14, 0x1e, 0xb9, - 0xe5, 0x1c, 0x36, 0x6c, 0xf2, 0x66, 0x40, 0xff, 0x61, 0xab, 0xb4, 0x19, 0xc5, 0x7c, 0x01, 0x58, 0xb6, 0x82, 0xe3, - 0xf1, 0xd0, 0xe0, 0xab, 0xe9, 0x9e, 0x34, 0x0f, 0xf7, 0x5a, 0x7c, 0xe9, 0x46, 0x5c, 0x2a, 0xfc, 0xde, 0xe2, 0x8e, - 0x29, 0xdb, 0x7b, 0xdd, 0xb4, 0x47, 0x6a, 0xbd, 0x6e, 0xb9, 0x10, 0x8a, 0xba, 0x7b, 0x62, 0xf9, 0xa7, 0xaf, 0x0e, - 0xe1, 0x3f, 0xa2, 0xea, 0x7f, 0xc9, 0x9a, 0x08, 0xf5, 0x8b, 0xb2, 0x25, 0x38, 0x91, 0x4a, 0x48, 0x88, 0xef, 0x5f, - 0x7f, 0x32, 0x79, 0x5c, 0x83, 0xbd, 0x6b, 0x93, 0x29, 0x55, 0xb5, 0xf6, 0xf7, 0x71, 0x0c, 0xa9, 0x3b, 0xeb, 0xd5, - 0x05, 0x78, 0xc8, 0xd8, 0x3d, 0xeb, 0x43, 0x23, 0xc1, 0x47, 0x90, 0x16, 0x5f, 0xc7, 0x36, 0xc4, 0x4a, 0xbc, 0xdd, - 0xc4, 0x4a, 0xbc, 0xd9, 0xcd, 0x4a, 0xfc, 0x75, 0x2f, 0x56, 0xe2, 0xcd, 0x57, 0x67, 0x25, 0xde, 0xd6, 0x59, 0x89, - 0xab, 0x58, 0xd8, 0xcf, 0x5a, 0x17, 0x4b, 0xfe, 0xf3, 0x23, 0x29, 0xe5, 0x2e, 0xe3, 0x7e, 0xc7, 0xa5, 0x90, 0xc7, - 0x57, 0xbf, 0x9b, 0xb1, 0xc0, 0x8d, 0xf8, 0x1e, 0xcd, 0xc9, 0x0a, 0xd6, 0x82, 0x63, 0x76, 0xfc, 0x8e, 0x52, 0x1c, - 0xc6, 0xd1, 0xf4, 0x67, 0x50, 0xca, 0x82, 0x38, 0x30, 0x51, 0x5e, 0x04, 0xe9, 0xcf, 0xf1, 0x62, 0xb9, 0xb8, 0x80, - 0xbe, 0x3e, 0x06, 0x69, 0x30, 0x0c, 0x99, 0xf4, 0x44, 0x26, 0xf3, 0x37, 0x2e, 0x13, 0x07, 0x8b, 0x53, 0xf1, 0xd3, - 0x5f, 0x89, 0x9f, 0x68, 0x93, 0xca, 0x7f, 0x93, 0x5d, 0x9d, 0xde, 0xcc, 0x88, 0x08, 0x25, 0xa0, 0x32, 0xe8, 0xc7, - 0x33, 0x23, 0x57, 0xb1, 0xd9, 0x30, 0x4b, 0x61, 0xef, 0xb0, 0xb1, 0x1f, 0x56, 0x63, 0x6a, 0x96, 0xa6, 0x25, 0x43, - 0x70, 0xd5, 0xc5, 0xf0, 0xf3, 0x78, 0x99, 0xb2, 0x71, 0x7c, 0x1f, 0xe9, 0x56, 0x24, 0x9d, 0x0c, 0x40, 0xc3, 0x29, - 0xdb, 0x60, 0xf2, 0xc8, 0x0f, 0x48, 0x28, 0xc7, 0x89, 0xa1, 0x43, 0xee, 0xd2, 0xe5, 0xc2, 0x26, 0x55, 0xb3, 0x8d, - 0x53, 0xd4, 0x65, 0x96, 0xa3, 0x27, 0x86, 0x11, 0xf7, 0x1f, 0xd7, 0x52, 0x98, 0x6a, 0xc4, 0x0e, 0x97, 0x0a, 0xa7, - 0x46, 0x24, 0x84, 0x8b, 0x22, 0x0e, 0x46, 0xc3, 0xc2, 0xf1, 0x37, 0xe4, 0xba, 0x5a, 0xbc, 0x85, 0x28, 0x22, 0xf9, - 0x92, 0xaf, 0x07, 0x8f, 0x0a, 0x41, 0x8f, 0xaf, 0x15, 0x30, 0xbe, 0xbb, 0x63, 0x49, 0xe8, 0x3f, 0x18, 0x66, 0x1e, - 0x47, 0x3f, 0x02, 0x00, 0xde, 0xc4, 0xf7, 0x91, 0x5a, 0x01, 0x93, 0xb5, 0x34, 0xec, 0xa5, 0xc6, 0xf8, 0x25, 0xe0, - 0xb8, 0xa2, 0x8c, 0x00, 0xd2, 0xe4, 0x4e, 0xd9, 0xdf, 0x2d, 0xfa, 0xf7, 0x1f, 0x66, 0x6e, 0x5d, 0xc6, 0xf2, 0x43, - 0x7f, 0x5b, 0xec, 0xf1, 0x99, 0xe7, 0xcf, 0x9f, 0x6c, 0x9e, 0x76, 0x39, 0x3d, 0x7b, 0x43, 0x6b, 0x73, 0xe3, 0x29, - 0x80, 0x51, 0x5c, 0xc5, 0xcb, 0xd1, 0x0c, 0x0d, 0x5d, 0xbf, 0xde, 0x7c, 0x33, 0xe8, 0x13, 0xb3, 0x94, 0xca, 0xa9, - 0x57, 0x8a, 0x0a, 0x28, 0xe0, 0xf7, 0xdf, 0x42, 0x00, 0xce, 0xff, 0x21, 0x18, 0xea, 0xbb, 0x86, 0x73, 0xf1, 0xc1, - 0xe3, 0x36, 0x6f, 0x0f, 0x92, 0x69, 0xf2, 0xd0, 0x16, 0x42, 0xb9, 0xd6, 0x8c, 0x64, 0xf2, 0x2a, 0xd0, 0xd4, 0x30, - 0x72, 0x9b, 0x22, 0xe4, 0x89, 0xaf, 0x30, 0x87, 0xd8, 0x74, 0xee, 0x68, 0x60, 0x31, 0x8e, 0xad, 0x2a, 0x48, 0x86, - 0x9b, 0x3c, 0x30, 0x44, 0x5f, 0xd5, 0x77, 0xf3, 0x20, 0xb2, 0x30, 0x0a, 0x7c, 0xfd, 0x8d, 0xbf, 0x82, 0x38, 0xc8, - 0x80, 0xdc, 0xaa, 0xaf, 0xa0, 0xd0, 0x52, 0xfd, 0xe6, 0x20, 0xd5, 0x93, 0xde, 0x08, 0x09, 0xa1, 0xc5, 0x1b, 0xfc, - 0x49, 0xd3, 0x34, 0x4d, 0xb2, 0x11, 0x9a, 0xe4, 0x23, 0xb0, 0x1c, 0xd9, 0x01, 0xd0, 0x96, 0xe4, 0x8b, 0x15, 0x95, - 0x00, 0x67, 0x80, 0x3a, 0x59, 0x51, 0xc0, 0x43, 0xfd, 0x75, 0x5c, 0x51, 0x20, 0x18, 0x7a, 0x08, 0xd3, 0xe6, 0x27, - 0x10, 0x11, 0xb8, 0xab, 0x21, 0xc3, 0x8e, 0x6f, 0xb9, 0x24, 0x58, 0x73, 0xe9, 0x71, 0xd0, 0x63, 0xcd, 0x31, 0xe1, - 0x22, 0x05, 0x0b, 0x82, 0xd6, 0xa1, 0x12, 0xe2, 0xd9, 0x62, 0x0d, 0xb8, 0x11, 0xf9, 0xa2, 0x55, 0x36, 0x67, 0xd1, - 0x52, 0xc7, 0x9c, 0x50, 0x18, 0xa3, 0x0f, 0xea, 0xbc, 0x21, 0x62, 0x0b, 0xb0, 0x4d, 0x73, 0xcb, 0x19, 0xdd, 0x85, - 0x29, 0x47, 0xa9, 0xbe, 0x35, 0xe2, 0x8a, 0xcd, 0x94, 0xe3, 0xb6, 0xea, 0x0d, 0xc1, 0x97, 0x34, 0xae, 0x3a, 0x72, - 0x91, 0x25, 0x34, 0xf4, 0x41, 0xd1, 0x31, 0xb8, 0xb8, 0x48, 0x80, 0xdd, 0xf0, 0xab, 0x8b, 0x26, 0x35, 0x32, 0x7e, - 0x45, 0x50, 0x94, 0x98, 0xf5, 0x6e, 0xf8, 0x38, 0x21, 0x30, 0xd1, 0xc6, 0x7e, 0x46, 0xb5, 0x7e, 0x36, 0x4c, 0xfa, - 0x13, 0x7b, 0xa0, 0x8b, 0x84, 0x40, 0xf5, 0x89, 0x3d, 0x80, 0xed, 0xdf, 0x5b, 0x90, 0xa6, 0xe8, 0x5b, 0xd0, 0xb5, - 0x05, 0xa1, 0xfe, 0x47, 0x10, 0xac, 0x6a, 0xcb, 0x01, 0x72, 0xf3, 0x2d, 0x58, 0x1c, 0x41, 0x0c, 0x59, 0x9d, 0xc5, - 0x21, 0xe6, 0x26, 0xfe, 0x46, 0x23, 0x8c, 0xed, 0x86, 0xa3, 0x61, 0xbe, 0xf0, 0x5c, 0xf7, 0xa0, 0x56, 0x1f, 0x04, - 0xd9, 0x4d, 0xb5, 0x4d, 0x2b, 0xeb, 0x7b, 0xae, 0x1d, 0xbc, 0x70, 0x5a, 0xbd, 0xda, 0x1d, 0xad, 0xc4, 0x92, 0x1c, - 0xa0, 0xf8, 0xeb, 0xec, 0xd9, 0xda, 0xa8, 0x1d, 0x48, 0xb3, 0x6a, 0x32, 0x8f, 0x63, 0xcb, 0xb9, 0xfc, 0x6b, 0x50, - 0xbf, 0xfa, 0x29, 0x92, 0x25, 0xe5, 0x35, 0x19, 0x40, 0x34, 0x64, 0x03, 0x8e, 0xd1, 0x9f, 0xb5, 0x97, 0x9a, 0x41, - 0xc7, 0xc7, 0x34, 0x07, 0x32, 0x5d, 0xb6, 0xf0, 0x29, 0x53, 0x3b, 0xa8, 0x7c, 0x31, 0xad, 0x62, 0x38, 0x1e, 0x77, - 0x95, 0x15, 0x1a, 0xbd, 0xad, 0xd4, 0x02, 0xf6, 0xbf, 0xe1, 0xfa, 0x74, 0x86, 0x10, 0x97, 0x00, 0x6a, 0x40, 0xec, - 0xf4, 0x9d, 0x1d, 0x2e, 0x17, 0xe5, 0xee, 0xca, 0x97, 0xe4, 0xfe, 0x9d, 0xe1, 0xa5, 0x83, 0x3a, 0x34, 0xd9, 0x5f, - 0xf3, 0x75, 0xf7, 0xc8, 0x2e, 0x59, 0x34, 0x2e, 0x77, 0x58, 0xb9, 0xbf, 0xf6, 0xef, 0xae, 0x84, 0x51, 0x20, 0xa9, - 0x40, 0xdc, 0x80, 0x51, 0xf2, 0x38, 0xc2, 0xcd, 0x4f, 0xc7, 0x2d, 0xd8, 0x8b, 0x8a, 0xc1, 0x06, 0x14, 0x11, 0x4c, - 0x36, 0x53, 0x84, 0xe2, 0x10, 0xb9, 0x1a, 0xdd, 0x82, 0x0d, 0x41, 0x88, 0x6e, 0xdc, 0x89, 0x99, 0xb0, 0x29, 0x2c, - 0xda, 0x04, 0x3c, 0x16, 0xe5, 0xbe, 0x52, 0xeb, 0x60, 0xb7, 0xd4, 0x3a, 0xdb, 0x25, 0xb5, 0x26, 0x77, 0xaa, 0xfb, - 0xc4, 0x5f, 0x28, 0x1e, 0x79, 0x82, 0x38, 0x57, 0x1d, 0xf3, 0x4a, 0xa2, 0x6e, 0xf4, 0xbe, 0x12, 0xad, 0x6a, 0xbd, - 0x91, 0x95, 0x20, 0x8a, 0xbf, 0x15, 0x06, 0x45, 0x28, 0xd4, 0x55, 0xd9, 0xf8, 0x55, 0x21, 0x1b, 0x27, 0xae, 0xa6, - 0x70, 0xa4, 0x11, 0xd4, 0xbf, 0xe2, 0xa4, 0x26, 0xb9, 0x83, 0xc2, 0x59, 0xad, 0x18, 0xa9, 0xe2, 0x7e, 0x55, 0x30, - 0x1a, 0x8a, 0x53, 0x9f, 0xe0, 0x32, 0xca, 0xbe, 0x7d, 0xe5, 0xaa, 0x85, 0xf7, 0x55, 0x51, 0x0e, 0x52, 0x77, 0x1c, - 0xb2, 0x2c, 0x56, 0xb7, 0x4d, 0xd9, 0xfd, 0x46, 0x7d, 0xad, 0x6c, 0x12, 0xe9, 0x27, 0x43, 0x00, 0x16, 0x62, 0xfa, - 0x8a, 0x5e, 0x5b, 0xda, 0x40, 0xe0, 0x20, 0x1b, 0xdc, 0xfa, 0x76, 0x4b, 0xe7, 0x29, 0x5f, 0x42, 0xa1, 0x85, 0x57, - 0x65, 0x10, 0x08, 0xdf, 0x9b, 0x75, 0xc3, 0x2d, 0x8f, 0x97, 0x3c, 0xbf, 0xdf, 0x41, 0xbc, 0xa8, 0xb9, 0xaa, 0x22, - 0x1f, 0x4f, 0xa6, 0x4d, 0xe6, 0xb9, 0x58, 0xb5, 0xde, 0x29, 0x09, 0x71, 0xd6, 0xdc, 0x33, 0xa6, 0x2c, 0xa3, 0xe7, - 0x35, 0xba, 0xe2, 0xbb, 0x7c, 0xeb, 0x24, 0xcb, 0x08, 0x63, 0xdb, 0xdb, 0x59, 0xe2, 0x8f, 0x3e, 0x29, 0x43, 0x16, - 0x72, 0x4e, 0x90, 0x01, 0x97, 0x35, 0x05, 0x3d, 0x1f, 0x43, 0x41, 0xb2, 0xae, 0xd3, 0x4a, 0x15, 0xe9, 0x4b, 0xf7, - 0xa9, 0xdb, 0xf6, 0x5f, 0x4d, 0x0e, 0x2b, 0x42, 0xd1, 0x56, 0xa7, 0x2c, 0x32, 0xdf, 0x30, 0x8e, 0x6c, 0xb6, 0x9c, - 0x0f, 0xd7, 0xaa, 0x6c, 0x55, 0x11, 0xb9, 0xd6, 0xc5, 0xac, 0xea, 0x67, 0x27, 0x93, 0x49, 0x59, 0xd0, 0xe8, 0x6a, - 0x87, 0x28, 0x2c, 0x7c, 0xea, 0xba, 0x6e, 0x75, 0xec, 0xdb, 0xc1, 0x6e, 0xa3, 0xdc, 0xf6, 0xa4, 0x71, 0xc4, 0x08, - 0xdb, 0x5d, 0xf0, 0xab, 0x83, 0x23, 0x77, 0x8a, 0x93, 0x5d, 0x32, 0x8b, 0xe8, 0x91, 0x31, 0x44, 0x90, 0xb1, 0x79, - 0xda, 0x1d, 0x31, 0xd4, 0xc1, 0x38, 0xca, 0x81, 0x46, 0xc3, 0x01, 0x7b, 0x0a, 0xa6, 0x22, 0x9e, 0xd8, 0x15, 0xae, - 0x86, 0xf2, 0xf0, 0x9a, 0xf0, 0x5e, 0x7c, 0x04, 0x0f, 0xca, 0xba, 0x2e, 0xd3, 0xc6, 0x69, 0x75, 0xdc, 0x3f, 0x97, - 0xea, 0x69, 0x70, 0x01, 0xae, 0x85, 0x42, 0x9b, 0xe4, 0xb3, 0xf8, 0xff, 0x52, 0xfe, 0xff, 0x6a, 0xb1, 0x2a, 0xdb, - 0x8f, 0x9c, 0x80, 0x44, 0xbb, 0x38, 0x2d, 0x34, 0xea, 0xa6, 0x3d, 0x20, 0xad, 0x0c, 0x26, 0xaa, 0x02, 0x1d, 0x94, - 0xf4, 0xa5, 0x04, 0x20, 0x0d, 0xe2, 0x77, 0xa4, 0x98, 0x61, 0x89, 0x0b, 0x11, 0x62, 0x91, 0xbe, 0x0e, 0xe6, 0x60, - 0xbd, 0x3c, 0x41, 0xfd, 0x41, 0x69, 0x4f, 0x80, 0x36, 0xbe, 0x36, 0xb7, 0xbd, 0xc4, 0xfd, 0x55, 0xbd, 0x96, 0xe8, - 0x18, 0x40, 0xe6, 0xc1, 0x21, 0x44, 0x43, 0x02, 0xad, 0xb2, 0xb9, 0x69, 0x94, 0xf2, 0xad, 0xaa, 0x67, 0x13, 0x03, - 0xc3, 0xee, 0x9a, 0xab, 0x50, 0xdf, 0x42, 0x5b, 0x00, 0x93, 0xe5, 0xdb, 0x0f, 0x9f, 0x6d, 0x58, 0x62, 0x75, 0x3f, - 0x7a, 0xb8, 0xe4, 0xb8, 0x7f, 0x6d, 0xbc, 0x3b, 0x53, 0x3a, 0xff, 0x28, 0x5f, 0xfc, 0x6b, 0xa3, 0x40, 0xef, 0xaa, - 0x24, 0xa1, 0xe3, 0xd6, 0xe2, 0x2d, 0x73, 0xaf, 0xda, 0xf3, 0x20, 0xda, 0xbf, 0xae, 0xbf, 0xda, 0xbb, 0x2e, 0x5c, - 0x18, 0x7b, 0x57, 0x86, 0x1b, 0x87, 0x2c, 0x17, 0xb2, 0xfe, 0x5f, 0x15, 0x81, 0xa2, 0xea, 0x75, 0xac, 0x63, 0x2b, - 0xa2, 0xf2, 0xaf, 0x96, 0x40, 0x7c, 0xee, 0x95, 0xe0, 0x41, 0x13, 0x39, 0xda, 0xf4, 0x63, 0xed, 0x44, 0x3b, 0x6e, - 0x6b, 0x47, 0xae, 0x4e, 0x5c, 0x58, 0x5f, 0xef, 0xb4, 0x0a, 0x6f, 0xc2, 0x43, 0x57, 0x3f, 0x3b, 0x9d, 0x8a, 0x4b, - 0x62, 0x12, 0x84, 0x21, 0xa1, 0x8a, 0x34, 0x4b, 0xe2, 0x4f, 0xac, 0xac, 0x66, 0xa1, 0x32, 0x6e, 0x04, 0xd2, 0x12, - 0x8f, 0x70, 0x76, 0x46, 0xfe, 0xa2, 0x8b, 0x67, 0x43, 0x2d, 0x04, 0x03, 0x4e, 0x2a, 0xc5, 0x4f, 0xc0, 0x1d, 0x3c, - 0xd4, 0xcf, 0x4e, 0x21, 0x84, 0xa1, 0x36, 0xee, 0xeb, 0x3f, 0xb6, 0x8e, 0x35, 0xaf, 0x73, 0x67, 0xb7, 0x47, 0xae, - 0xed, 0x39, 0x87, 0x9a, 0xeb, 0x1c, 0xd9, 0x2d, 0xe7, 0x58, 0x6b, 0x39, 0x1d, 0xf8, 0x77, 0xe4, 0x39, 0xaf, 0x34, - 0x17, 0x9e, 0x34, 0xcf, 0x69, 0xe3, 0xbf, 0x2d, 0xe7, 0xf8, 0xae, 0x4d, 0x37, 0xbd, 0x2f, 0xdd, 0xaa, 0x2a, 0xa3, - 0x00, 0x27, 0x10, 0xfd, 0xe0, 0xec, 0x74, 0x99, 0x32, 0x6d, 0xd5, 0xd7, 0x5f, 0xe9, 0xda, 0x2c, 0x61, 0x93, 0xbe, - 0xfe, 0xd4, 0x57, 0x4a, 0xbd, 0x93, 0xc6, 0xe2, 0xd6, 0x71, 0x63, 0x71, 0xfb, 0xa8, 0xb1, 0xf8, 0xb0, 0x53, 0x2e, - 0x3e, 0x98, 0xd2, 0x2b, 0x25, 0x83, 0xe0, 0xdc, 0xcf, 0x92, 0x60, 0x65, 0x78, 0x1a, 0xa0, 0x6b, 0x1b, 0xfe, 0x39, - 0x6e, 0x99, 0xb2, 0xd5, 0x10, 0x5a, 0x49, 0x68, 0x1c, 0x9f, 0x68, 0xde, 0xd1, 0x5f, 0x5a, 0x47, 0x23, 0xa8, 0x07, - 0xf9, 0x2e, 0xe1, 0xef, 0xae, 0x7d, 0x32, 0x72, 0x35, 0x68, 0xe8, 0xc1, 0x7f, 0xb3, 0x4e, 0x6b, 0x44, 0x0f, 0x2e, - 0xbc, 0xff, 0xe8, 0x1d, 0xa7, 0xae, 0xed, 0xc1, 0x7f, 0xbf, 0x49, 0x95, 0x3b, 0x28, 0xfc, 0xd5, 0x7e, 0x0f, 0x5d, - 0xad, 0x7d, 0x32, 0x6b, 0x39, 0xaf, 0xee, 0x8e, 0x9d, 0x93, 0x99, 0x77, 0xfc, 0x91, 0x9e, 0x42, 0xbb, 0xe5, 0xbc, - 0x82, 0xbf, 0x8f, 0x6d, 0x77, 0x66, 0x7b, 0xce, 0xc9, 0x5d, 0xdb, 0x69, 0x87, 0xf6, 0x91, 0x73, 0x02, 0x7f, 0xbf, - 0x01, 0x78, 0x01, 0xae, 0x3c, 0x41, 0xa9, 0x06, 0x1b, 0xa3, 0x62, 0xbf, 0xa1, 0x7e, 0xa4, 0x75, 0xa8, 0x75, 0x0e, - 0xff, 0x72, 0x72, 0x67, 0x1f, 0xce, 0xbc, 0xd6, 0x9d, 0xbd, 0xf1, 0xe7, 0x47, 0x80, 0xfc, 0xf6, 0x85, 0x03, 0x30, - 0x62, 0x46, 0x92, 0x3f, 0x0d, 0xac, 0xcb, 0x4d, 0x62, 0xf4, 0xf7, 0xbb, 0xc5, 0xe8, 0x3f, 0x2c, 0xf7, 0x11, 0xa3, - 0xbf, 0xff, 0xea, 0x62, 0xf4, 0xcb, 0xaa, 0x15, 0xf7, 0xfb, 0x6a, 0xe4, 0xf4, 0x5f, 0xd6, 0x55, 0x22, 0x39, 0xf0, - 0x8d, 0xeb, 0xab, 0xe5, 0x0d, 0xc4, 0xfe, 0x79, 0x1f, 0xf7, 0x7f, 0x58, 0x96, 0x4c, 0x94, 0x62, 0xc0, 0x00, 0xef, - 0x63, 0xc2, 0x00, 0xbf, 0x2d, 0xfb, 0x60, 0x17, 0xc1, 0x6f, 0xcd, 0x60, 0x6c, 0xcf, 0xfc, 0x70, 0x22, 0x6f, 0x5c, - 0x28, 0xe9, 0x61, 0x31, 0xd8, 0xcc, 0xc3, 0x65, 0x02, 0xca, 0x9a, 0xe5, 0x3c, 0x4a, 0xbb, 0x47, 0x2e, 0xa0, 0xf9, - 0xd6, 0x24, 0xc9, 0x2b, 0x8d, 0x1d, 0x11, 0x2d, 0xe9, 0x96, 0xdb, 0xf4, 0x6f, 0x7c, 0x8f, 0x26, 0x6b, 0xcd, 0xbd, - 0x7b, 0xf5, 0x7e, 0x35, 0xb0, 0x05, 0x11, 0x26, 0x7d, 0x40, 0x6c, 0x34, 0xbd, 0x2f, 0x1b, 0x8e, 0x55, 0x4c, 0x05, - 0x37, 0x8f, 0x14, 0x46, 0x52, 0x6d, 0xef, 0x95, 0x0d, 0xcf, 0x76, 0x4d, 0xb3, 0xe1, 0xf3, 0xa5, 0xe6, 0x5b, 0xac, - 0xde, 0x64, 0xc7, 0x55, 0x50, 0x55, 0xf2, 0x7e, 0x35, 0x02, 0xa4, 0xa0, 0x3d, 0x0b, 0xd3, 0xb8, 0x82, 0xf0, 0x71, - 0x35, 0xbc, 0x8d, 0x5d, 0xe5, 0x5d, 0xa9, 0x4f, 0xd5, 0x9c, 0xee, 0xc5, 0x1a, 0xe9, 0xc1, 0xe0, 0x37, 0x20, 0x6c, - 0xf8, 0x7d, 0x3c, 0x8c, 0x55, 0x38, 0xaf, 0x95, 0x7e, 0x89, 0xd4, 0xce, 0x67, 0xde, 0xba, 0x4e, 0xda, 0x6c, 0x34, - 0xa4, 0xf5, 0xd8, 0x5c, 0xdc, 0xd1, 0xf8, 0x79, 0x32, 0x5b, 0xcd, 0xc9, 0xb4, 0x18, 0x2d, 0x73, 0xb7, 0x75, 0x26, - 0xea, 0x3d, 0x85, 0x4d, 0x6c, 0xf1, 0x07, 0xd5, 0x6b, 0x7d, 0x3d, 0x81, 0x1c, 0xcd, 0x5d, 0x24, 0x22, 0x14, 0x0a, - 0xaa, 0x85, 0x36, 0xb6, 0xbd, 0x2d, 0xe6, 0x1f, 0x6a, 0xc7, 0xbc, 0x13, 0xb4, 0xd5, 0xdd, 0x66, 0x31, 0x22, 0x5d, - 0x1b, 0xd6, 0x25, 0x05, 0xaa, 0xd7, 0x39, 0xb6, 0xbc, 0x23, 0xcb, 0x39, 0xee, 0x98, 0xb9, 0x38, 0x70, 0x6a, 0x97, - 0x25, 0x80, 0x80, 0xc9, 0xae, 0x1c, 0x66, 0x10, 0x05, 0x59, 0xe0, 0x87, 0x39, 0xa0, 0xfa, 0x32, 0xcd, 0xfb, 0xcf, - 0x65, 0x9a, 0xc1, 0x1c, 0x05, 0x49, 0x86, 0xe6, 0xca, 0xf6, 0x90, 0x65, 0xf7, 0x8c, 0x45, 0x1b, 0x54, 0xb9, 0x55, - 0xeb, 0xe7, 0x3f, 0xce, 0x16, 0x34, 0x27, 0x3b, 0x8b, 0x61, 0x16, 0xf1, 0xfd, 0x21, 0x4c, 0x75, 0xf3, 0x81, 0xf5, - 0xd3, 0x26, 0x84, 0xfb, 0xcf, 0xdd, 0x08, 0x37, 0x63, 0xfb, 0x20, 0xdc, 0x7f, 0x7e, 0x75, 0x84, 0xfb, 0x93, 0x8a, - 0x70, 0x4b, 0x9e, 0x2a, 0x85, 0x4c, 0xf4, 0x03, 0x3e, 0x1b, 0x10, 0x72, 0xf8, 0xa5, 0x7e, 0x40, 0xe4, 0xa5, 0xae, - 0xa4, 0x82, 0xfd, 0x58, 0xca, 0x6d, 0x83, 0x2c, 0x3b, 0x86, 0x48, 0xa5, 0x3c, 0x1a, 0x90, 0x26, 0x55, 0x26, 0xfc, - 0x86, 0x3e, 0x2f, 0xa2, 0x2c, 0x74, 0xde, 0x73, 0xb6, 0x04, 0x54, 0x10, 0x3f, 0xc4, 0xc9, 0xdc, 0xc7, 0xf0, 0x70, - 0x3a, 0xe6, 0xc4, 0x83, 0x07, 0x17, 0xbc, 0xa3, 0x46, 0x71, 0x34, 0x96, 0x72, 0x74, 0xd6, 0xbf, 0x26, 0x7a, 0x50, - 0x7f, 0x60, 0x7e, 0xa2, 0x5b, 0xf4, 0x1a, 0x16, 0xf7, 0x45, 0xdb, 0x7d, 0xd1, 0x3a, 0x7c, 0x71, 0xe4, 0xc2, 0xff, - 0x3c, 0xd6, 0xce, 0x2d, 0x5e, 0x71, 0x1e, 0x47, 0x90, 0x96, 0x43, 0xd4, 0xdc, 0x54, 0xed, 0x9e, 0xb1, 0x4f, 0x45, - 0xad, 0xe3, 0xe6, 0x4a, 0x63, 0xff, 0xa1, 0xa8, 0xd3, 0x58, 0x63, 0x16, 0x2f, 0x95, 0x61, 0x35, 0x8c, 0x26, 0x88, - 0x96, 0x20, 0x19, 0x52, 0x6a, 0xa8, 0xaf, 0xf9, 0x74, 0x8b, 0x79, 0xb1, 0x76, 0x7e, 0x53, 0xe4, 0xfe, 0x11, 0x39, - 0x48, 0x76, 0x42, 0x90, 0x0b, 0xd5, 0x5d, 0x8c, 0x1c, 0x8e, 0xd9, 0x6f, 0x34, 0xc8, 0xbc, 0x57, 0x24, 0x78, 0xc7, - 0x05, 0xca, 0x92, 0x65, 0x34, 0xa2, 0x1c, 0xee, 0xfe, 0x30, 0x35, 0x82, 0x03, 0x88, 0x1d, 0x8a, 0x1f, 0x36, 0x71, - 0xd5, 0xfc, 0x33, 0xb7, 0x48, 0x94, 0x90, 0x8a, 0x55, 0xf1, 0x5f, 0x64, 0x56, 0x42, 0xe9, 0x55, 0x71, 0x69, 0xed, - 0xbe, 0xff, 0x42, 0x36, 0x7c, 0x91, 0x59, 0x90, 0xe2, 0x14, 0x96, 0xfb, 0xf9, 0x73, 0xaa, 0x05, 0x49, 0x07, 0x69, - 0x5a, 0xe7, 0xa3, 0x22, 0xf8, 0x98, 0xe6, 0x4f, 0x63, 0x8a, 0x3f, 0xd6, 0x1d, 0x59, 0xf1, 0xcb, 0x97, 0x67, 0x7d, - 0xcf, 0xe4, 0x29, 0x33, 0x4b, 0xf9, 0x9d, 0x2e, 0xf7, 0x53, 0x8d, 0x9b, 0x8d, 0x4e, 0x5b, 0x8b, 0x20, 0x9a, 0x0a, - 0xcd, 0xb4, 0xc4, 0x5e, 0x90, 0x6f, 0x81, 0x54, 0x60, 0xbe, 0x50, 0x51, 0x8b, 0x3a, 0x77, 0x2c, 0x81, 0x74, 0x9f, - 0x7d, 0xbd, 0xed, 0xb8, 0x8e, 0xab, 0xcb, 0x86, 0x93, 0x60, 0xda, 0x5f, 0xc7, 0x99, 0x0f, 0x99, 0x6b, 0xc2, 0x78, - 0x0a, 0x9e, 0x1f, 0x59, 0x90, 0x85, 0x90, 0x06, 0x05, 0x5c, 0x40, 0xe6, 0xc4, 0x35, 0xe6, 0xdc, 0x1e, 0xd7, 0x4f, - 0x3e, 0x61, 0x2a, 0x3c, 0xe1, 0xf4, 0x85, 0xf1, 0x70, 0x7e, 0x84, 0xcb, 0xd0, 0xd0, 0x0d, 0x48, 0xc4, 0xc8, 0x92, - 0xd4, 0x56, 0xed, 0xdb, 0xbb, 0x1a, 0xb4, 0x81, 0x24, 0xe9, 0xd8, 0xc1, 0x24, 0xf1, 0xe7, 0x10, 0x31, 0x7c, 0x9d, - 0x5b, 0x1c, 0xd3, 0xea, 0x1c, 0xd5, 0x6a, 0xde, 0xab, 0x23, 0x4b, 0x6b, 0x79, 0x96, 0xe6, 0x02, 0xba, 0xd5, 0x73, - 0x6b, 0x9d, 0xdf, 0xf4, 0x76, 0xa9, 0xe8, 0x08, 0xbf, 0x3c, 0xa5, 0x79, 0x90, 0x72, 0x8e, 0x0b, 0x3f, 0x33, 0x0a, - 0x6f, 0x68, 0x28, 0xb1, 0xbc, 0x03, 0x12, 0xd3, 0x5f, 0xb1, 0x55, 0x66, 0x62, 0x9a, 0x10, 0x5e, 0x25, 0x30, 0xd7, - 0xe8, 0x9a, 0x16, 0x44, 0x5a, 0xf0, 0xf9, 0xb3, 0x11, 0x80, 0xf9, 0x7d, 0x5f, 0x81, 0x0f, 0x3c, 0x9b, 0x25, 0x80, - 0x05, 0x85, 0x62, 0x09, 0x81, 0x05, 0xbe, 0x31, 0xf0, 0x6f, 0x51, 0x2c, 0x7e, 0x70, 0xc5, 0x9e, 0x13, 0xfa, 0xd1, - 0x14, 0x50, 0x9a, 0x1f, 0x4d, 0x6b, 0x06, 0x04, 0xe4, 0x5d, 0x57, 0x29, 0x2d, 0xba, 0x2a, 0x94, 0xfb, 0xe9, 0xf7, - 0x0f, 0x57, 0x94, 0x06, 0x09, 0x52, 0x6e, 0xfb, 0x63, 0x74, 0x05, 0x2b, 0x74, 0x0f, 0x2f, 0xfb, 0xdf, 0x9c, 0xce, - 0x59, 0xe6, 0x93, 0xe0, 0x12, 0x58, 0x3c, 0x20, 0x07, 0xb4, 0x91, 0x48, 0x61, 0x4a, 0x0c, 0xde, 0x98, 0xdd, 0x05, - 0x23, 0xce, 0xa7, 0x59, 0x1a, 0xbf, 0xa7, 0x6c, 0xb4, 0x51, 0xea, 0x7b, 0x16, 0x99, 0xc8, 0x8e, 0x7c, 0x0c, 0x82, - 0xd8, 0x8f, 0x62, 0xfd, 0xec, 0x1b, 0xe9, 0x4d, 0xb4, 0x69, 0x11, 0x20, 0x17, 0xe1, 0x75, 0xc2, 0xc2, 0x7f, 0xf5, - 0xbf, 0x81, 0x8b, 0xfb, 0x9b, 0x1b, 0xdd, 0xec, 0x65, 0x0e, 0xf2, 0x31, 0xdf, 0x34, 0xe4, 0xe4, 0x43, 0x1e, 0x95, - 0x33, 0x9b, 0x6d, 0x85, 0xd9, 0x84, 0xdf, 0xbb, 0x59, 0xd7, 0xb3, 0x53, 0xbc, 0xd0, 0xce, 0x80, 0xbb, 0x58, 0x97, - 0x78, 0x4e, 0xaf, 0x87, 0x0c, 0xea, 0x30, 0xf4, 0x47, 0x9f, 0x04, 0x87, 0xaa, 0x3e, 0xec, 0xc3, 0x8b, 0x4a, 0xca, - 0xae, 0x71, 0x2f, 0xe3, 0x56, 0x5e, 0xe3, 0x97, 0xf1, 0x53, 0xf7, 0xb3, 0x20, 0x93, 0xcc, 0x30, 0x3e, 0xe4, 0xa0, - 0xcd, 0xc1, 0xf1, 0x15, 0xec, 0x0f, 0x30, 0xa8, 0xde, 0xc9, 0x5f, 0x3a, 0x77, 0x9e, 0x3b, 0x6b, 0x79, 0x0e, 0xb0, - 0x39, 0xb3, 0xb6, 0x73, 0x1c, 0xda, 0x6d, 0xe7, 0x18, 0xfe, 0x3e, 0x02, 0xeb, 0x65, 0xb7, 0x9c, 0xc3, 0x8f, 0x5e, - 0x2b, 0xb4, 0x4f, 0x9c, 0x63, 0xf8, 0xbb, 0xa4, 0x56, 0xbf, 0x20, 0xd3, 0x03, 0x0c, 0xcf, 0x37, 0x25, 0x2c, 0xa0, - 0xfc, 0x96, 0x5a, 0x04, 0xab, 0x74, 0xbd, 0x35, 0x68, 0x22, 0x00, 0x65, 0xe8, 0x96, 0x08, 0x51, 0x18, 0xf5, 0x0c, - 0x48, 0x12, 0x8e, 0xe1, 0xed, 0x85, 0x41, 0x46, 0x54, 0x24, 0xbc, 0xdf, 0x7c, 0x8c, 0x78, 0x9b, 0xe6, 0x70, 0xe0, - 0x22, 0x6f, 0x12, 0xa9, 0x2e, 0xfe, 0xb6, 0xc0, 0x10, 0x3b, 0x22, 0x80, 0xb9, 0x82, 0x95, 0x8a, 0xdc, 0x7d, 0xf9, - 0xee, 0x81, 0xa3, 0xdf, 0x28, 0x93, 0xb9, 0x63, 0xbe, 0x6a, 0xdf, 0x5c, 0x9d, 0x21, 0x7b, 0xff, 0xbd, 0xfd, 0x60, - 0xca, 0x54, 0xea, 0x47, 0xc4, 0x1a, 0x1d, 0x07, 0x89, 0x1c, 0x9e, 0x82, 0xa2, 0xbd, 0xe6, 0x38, 0xea, 0x26, 0x24, - 0xd9, 0xb8, 0x00, 0x2a, 0xf9, 0xce, 0x0f, 0x15, 0xd3, 0x0b, 0xa5, 0xe5, 0x13, 0x89, 0xf9, 0x9f, 0x3f, 0x2f, 0x06, - 0x67, 0x57, 0xc6, 0x7d, 0xea, 0x75, 0xe0, 0xda, 0xed, 0xb0, 0xf6, 0x56, 0x2b, 0xa0, 0xdd, 0xc1, 0x6a, 0x8b, 0x60, - 0x96, 0x42, 0xd3, 0x2f, 0x74, 0x8c, 0x1b, 0x4d, 0x91, 0x6a, 0x1a, 0x46, 0x08, 0xf3, 0x5b, 0x61, 0x75, 0x74, 0xb3, - 0x17, 0x09, 0x85, 0x59, 0xb4, 0x25, 0x40, 0x2f, 0xe7, 0xc5, 0x74, 0x00, 0xcd, 0x96, 0x79, 0xec, 0x70, 0x69, 0xfc, - 0x5f, 0x4f, 0x02, 0xdd, 0x8b, 0x40, 0xc3, 0x57, 0x39, 0xad, 0x25, 0x77, 0x13, 0x79, 0xaf, 0xd2, 0x85, 0xca, 0xd2, - 0x73, 0x1d, 0x8a, 0x20, 0xfb, 0x12, 0x26, 0x5c, 0x93, 0xe6, 0x4d, 0xf2, 0xb6, 0x28, 0x0a, 0xac, 0x00, 0x22, 0x54, - 0x1b, 0xc2, 0xd5, 0xc9, 0x7c, 0xfe, 0x7c, 0xe3, 0x25, 0x44, 0xea, 0x64, 0x35, 0xef, 0xa4, 0xae, 0xe2, 0x37, 0x5d, - 0x45, 0x31, 0xb2, 0x5f, 0xc4, 0x1a, 0xc2, 0x2a, 0x8b, 0xf6, 0x1e, 0xfe, 0x1c, 0x32, 0x3f, 0x73, 0xb8, 0x1e, 0xc4, - 0x50, 0x2e, 0x77, 0xcb, 0x63, 0x6d, 0xb0, 0xc7, 0xe2, 0x91, 0xb8, 0x78, 0xa4, 0xbb, 0x67, 0xeb, 0x8f, 0x4b, 0xee, - 0x87, 0x0c, 0x7d, 0x7c, 0x76, 0x8b, 0xe0, 0x29, 0xef, 0x32, 0x9f, 0x22, 0x6c, 0xa8, 0x57, 0x6e, 0x9c, 0xf9, 0x22, - 0xcb, 0x09, 0xd0, 0xe5, 0xbd, 0x46, 0x85, 0xa1, 0xe2, 0xab, 0x7c, 0xf6, 0xee, 0xea, 0x3b, 0x8d, 0xef, 0x7f, 0xd2, - 0x6f, 0x21, 0x23, 0x43, 0x31, 0xf9, 0xfb, 0x14, 0x93, 0x5f, 0xe3, 0x49, 0x2e, 0x20, 0xb2, 0x7d, 0x7e, 0x40, 0x10, - 0xd4, 0x35, 0x16, 0x8d, 0x48, 0xeb, 0x37, 0x5f, 0x86, 0x59, 0xb0, 0xf0, 0x93, 0xec, 0x00, 0x9a, 0xda, 0x80, 0xe4, - 0xf4, 0x4d, 0x1e, 0xcc, 0xa4, 0x38, 0x14, 0x42, 0xb5, 0x2c, 0x12, 0x9a, 0xc3, 0x49, 0x10, 0x4a, 0xc5, 0xa1, 0xf8, - 0x80, 0x3f, 0x1a, 0xb1, 0x45, 0xd6, 0xd7, 0xfd, 0x05, 0xe4, 0x66, 0xc0, 0x68, 0xcb, 0x07, 0xf1, 0x28, 0x63, 0x99, - 0x9d, 0x66, 0x09, 0xf3, 0xe7, 0xba, 0x0c, 0x34, 0x5a, 0xef, 0x2f, 0x5d, 0x0e, 0xe7, 0x41, 0x26, 0x23, 0xf5, 0xd1, - 0x04, 0x41, 0x85, 0x07, 0x43, 0x3c, 0x1b, 0xe4, 0x1c, 0x84, 0x97, 0xf1, 0xb4, 0xb2, 0xa3, 0x0a, 0xca, 0xe5, 0x1c, - 0xe3, 0xc0, 0xf2, 0x78, 0xfc, 0x63, 0xf4, 0xc8, 0xb9, 0xe5, 0x5e, 0xd7, 0x32, 0xa0, 0xa0, 0x7e, 0x76, 0xca, 0xd9, - 0x5b, 0x0d, 0x03, 0x05, 0xe8, 0x1d, 0x17, 0x22, 0xdd, 0x6e, 0xf2, 0xc7, 0x3e, 0xe0, 0x95, 0xe1, 0x6a, 0xa2, 0x9e, - 0x31, 0x0a, 0x39, 0x8d, 0xe5, 0x0a, 0x08, 0xa1, 0x92, 0x8a, 0x77, 0xe6, 0x9d, 0x49, 0x07, 0x20, 0x1c, 0x15, 0xd2, - 0x4a, 0x9f, 0x3f, 0xbf, 0x1e, 0xfc, 0xe7, 0xdf, 0x10, 0x2a, 0x7d, 0xe6, 0x09, 0x2f, 0xe8, 0x6b, 0xb5, 0x16, 0xa7, - 0x3e, 0xad, 0x01, 0xaa, 0xf7, 0xd9, 0x58, 0x84, 0x05, 0x11, 0x5b, 0x2b, 0x1f, 0xdc, 0x88, 0x50, 0x4f, 0x90, 0x0e, - 0xc1, 0x14, 0xbe, 0xda, 0x03, 0x58, 0xde, 0x81, 0x08, 0x11, 0xa0, 0xfd, 0xba, 0xfa, 0xfe, 0x18, 0x42, 0x01, 0xd7, - 0xb2, 0x14, 0x28, 0x03, 0xc4, 0x3d, 0x74, 0x76, 0xea, 0x73, 0xe1, 0x2b, 0x90, 0x1f, 0x69, 0xf7, 0x00, 0xa6, 0x39, - 0x8b, 0xe7, 0xcc, 0x09, 0xe2, 0x83, 0x7b, 0x36, 0xb4, 0xfd, 0x45, 0x40, 0xf2, 0x65, 0x94, 0xbb, 0x69, 0x44, 0xf9, - 0x49, 0x05, 0x2d, 0xd1, 0xd7, 0x79, 0x01, 0xca, 0xb8, 0x00, 0x14, 0xfc, 0xf4, 0xcf, 0xca, 0xd1, 0x03, 0x1d, 0x11, - 0xbf, 0xbe, 0x8c, 0xe5, 0xcf, 0x29, 0x08, 0xa0, 0x88, 0xf7, 0x57, 0x3c, 0xd8, 0xf1, 0x64, 0xa2, 0x46, 0xfc, 0x73, - 0xca, 0xdf, 0x97, 0x50, 0x29, 0xf6, 0x6c, 0xbc, 0xa0, 0x2f, 0xd5, 0x3f, 0x21, 0x7f, 0x42, 0xee, 0x5e, 0x1e, 0x1c, - 0x12, 0xce, 0x73, 0x2d, 0x72, 0xa0, 0x04, 0xc9, 0x53, 0xaa, 0xc4, 0x11, 0x45, 0x35, 0x4e, 0xf5, 0x06, 0xd2, 0xe4, - 0x49, 0xbf, 0x4f, 0x78, 0xac, 0x8a, 0xce, 0x00, 0x4a, 0x0d, 0xb1, 0xfc, 0x61, 0xb2, 0x19, 0x34, 0xb4, 0xc9, 0x83, - 0x0b, 0x1b, 0x55, 0xa7, 0x53, 0x1f, 0xe3, 0x81, 0x2f, 0xf6, 0x57, 0x69, 0x07, 0xc2, 0xce, 0xe2, 0x0b, 0x0b, 0x08, - 0x5c, 0xf4, 0x53, 0xc1, 0xe3, 0xda, 0xb7, 0x84, 0xb2, 0xed, 0xd0, 0x7f, 0x88, 0x15, 0xcd, 0x3a, 0x77, 0xb2, 0xbf, - 0xc4, 0xd2, 0x2b, 0xe1, 0xdc, 0x56, 0x3b, 0x49, 0x32, 0x1e, 0x7a, 0xfd, 0x34, 0xa9, 0x01, 0xcc, 0x77, 0x1d, 0x26, - 0xb5, 0x6e, 0x79, 0x32, 0x88, 0x1d, 0xf3, 0xe2, 0xa0, 0x95, 0x5e, 0xe2, 0xb9, 0xcf, 0x4f, 0x0f, 0x60, 0x7e, 0x10, - 0x18, 0xa0, 0x44, 0x19, 0x05, 0x26, 0x44, 0x1f, 0xf0, 0x53, 0xb2, 0x0e, 0xb8, 0x18, 0x0b, 0xa2, 0x0e, 0x39, 0x47, - 0x19, 0x9a, 0xb4, 0x54, 0xa5, 0x4e, 0xac, 0xb8, 0xcd, 0x54, 0xde, 0xee, 0xfc, 0x01, 0xbf, 0x2d, 0x31, 0x79, 0x40, - 0xde, 0xcb, 0x98, 0xf0, 0xbb, 0xbd, 0xcc, 0x36, 0xb8, 0xe6, 0x6e, 0xaa, 0x42, 0x04, 0xeb, 0x96, 0x0a, 0xc5, 0x3e, - 0xde, 0x56, 0xab, 0x20, 0x8d, 0x64, 0xb5, 0x85, 0x6f, 0xe8, 0x4f, 0x71, 0xc7, 0xd7, 0x6a, 0x63, 0x29, 0xd4, 0xbb, - 0xcc, 0xfa, 0x50, 0x55, 0x08, 0xdb, 0xfd, 0xc5, 0x82, 0x2a, 0x9b, 0xbd, 0xd3, 0x03, 0xe2, 0x3b, 0xcf, 0x68, 0x87, - 0x9d, 0x9d, 0x82, 0x75, 0x21, 0x2d, 0xba, 0xbf, 0x58, 0xf0, 0x25, 0xa5, 0x5f, 0xf4, 0xe6, 0x60, 0x96, 0xcd, 0xc3, - 0xb3, 0xff, 0x03, 0x1c, 0x2a, 0x1a, 0x60, 0x9f, 0x5a, 0x03, 0x00}; + 0xdc, 0x93, 0x2e, 0xb7, 0x6d, 0x24, 0xfd, 0x3f, 0x4f, 0x01, 0xc3, 0x5e, 0x87, 0xb0, 0x01, 0x08, 0x00, 0x45, 0x89, + 0x26, 0x45, 0x69, 0x13, 0x1f, 0xb5, 0x4e, 0x29, 0x71, 0xca, 0x56, 0x5c, 0xbb, 0x51, 0x54, 0x22, 0x48, 0x0e, 0x49, + 0xac, 0x41, 0x80, 0x05, 0x80, 0x3a, 0x42, 0x63, 0x9f, 0x65, 0x9f, 0x65, 0x9f, 0xec, 0xab, 0xee, 0x9e, 0x19, 0x0c, + 0x0e, 0x1e, 0x8a, 0x9d, 0xdd, 0xaf, 0x12, 0xdb, 0xc4, 0xdc, 0xd3, 0x33, 0xd3, 0xd3, 0xd3, 0xa7, 0x3f, 0xe3, 0xbc, + 0x17, 0xb3, 0xc5, 0xf6, 0xeb, 0xee, 0xf3, 0x67, 0x66, 0xe3, 0x96, 0x04, 0x82, 0xcf, 0xce, 0xe2, 0xd9, 0x2c, 0x64, + 0x2d, 0x5d, 0x04, 0x0f, 0xd1, 0x4d, 0xd9, 0xcd, 0xd9, 0x23, 0x47, 0x78, 0xec, 0x34, 0xf2, 0x4d, 0x47, 0x4b, 0xcc, + 0x98, 0x49, 0x97, 0x76, 0x44, 0xb9, 0x22, 0x6f, 0xf6, 0x06, 0xc5, 0x1b, 0x7c, 0x5d, 0x8a, 0xa3, 0x6b, 0x4d, 0xe2, + 0xd5, 0x28, 0x64, 0x16, 0x6e, 0x77, 0xe8, 0x72, 0x3d, 0x5a, 0x8d, 0x46, 0x10, 0xa5, 0xe5, 0x91, 0x63, 0x82, 0xdf, + 0x99, 0x38, 0xc5, 0xf7, 0x60, 0x6e, 0xf4, 0x61, 0x52, 0x76, 0x56, 0x1d, 0x3e, 0xe8, 0x8a, 0x00, 0xab, 0x87, 0x3a, + 0xc8, 0xe0, 0xed, 0xd7, 0x70, 0x6a, 0x07, 0xfa, 0x07, 0xd8, 0x7d, 0xa9, 0xde, 0x6f, 0x3a, 0xfa, 0x83, 0x4b, 0xfd, + 0x03, 0xc2, 0x18, 0xa3, 0x17, 0xbf, 0xa4, 0xdd, 0xab, 0x9b, 0x3a, 0x09, 0xbd, 0x57, 0x18, 0xc7, 0x00, 0x98, 0xbe, + 0xaf, 0x02, 0x7f, 0x16, 0xc5, 0x69, 0x16, 0x8c, 0xf5, 0xab, 0xfe, 0xdb, 0xa0, 0x75, 0xb9, 0xc8, 0x5a, 0xc6, 0x95, + 0x39, 0xce, 0xd4, 0x10, 0x28, 0x02, 0x61, 0x62, 0x04, 0x94, 0x4d, 0x85, 0xd4, 0x13, 0xb4, 0xb5, 0xa0, 0x40, 0xcd, + 0x58, 0x68, 0x9c, 0x0d, 0xa0, 0x5c, 0x25, 0x9e, 0x0a, 0x06, 0x86, 0xd2, 0xb1, 0xa6, 0xd1, 0xa7, 0x97, 0xca, 0xcb, + 0xd5, 0x1a, 0xaf, 0xf2, 0xac, 0xb8, 0x2d, 0xd1, 0x07, 0xb0, 0x30, 0x9c, 0xa1, 0xef, 0x47, 0xaa, 0xd2, 0x67, 0xe9, + 0xde, 0x1d, 0x7e, 0x57, 0xa6, 0x0b, 0xe0, 0xfe, 0x06, 0x8d, 0x8b, 0x28, 0xce, 0x34, 0x70, 0x6c, 0x03, 0x3d, 0x0e, + 0xab, 0x4a, 0x62, 0xbc, 0xd5, 0x96, 0x91, 0x73, 0x64, 0xf0, 0x3d, 0x5e, 0x7e, 0x2d, 0xee, 0xde, 0xac, 0xe4, 0xc1, + 0x82, 0x1e, 0x0b, 0x11, 0x2c, 0x60, 0x16, 0x9f, 0xc7, 0xb7, 0x55, 0x39, 0xc8, 0xcb, 0xe1, 0xee, 0xbb, 0xb7, 0x25, + 0xc8, 0x64, 0x11, 0xd5, 0xaf, 0xc5, 0x03, 0x93, 0x0a, 0x42, 0xa7, 0x72, 0xa6, 0x50, 0xf1, 0x43, 0xd0, 0x30, 0x19, + 0xe8, 0x89, 0xe1, 0x5d, 0x00, 0x28, 0x89, 0x5f, 0xd3, 0xc3, 0xfc, 0x5a, 0x84, 0x4e, 0x16, 0x81, 0x8b, 0x95, 0xcb, + 0x19, 0xb0, 0x6b, 0xb4, 0x5c, 0x65, 0xe8, 0x6a, 0x17, 0x06, 0xc0, 0x72, 0x5d, 0x43, 0xd7, 0x9d, 0x80, 0xa5, 0x0b, + 0x32, 0x31, 0xd7, 0xb5, 0x60, 0x52, 0x4f, 0xe3, 0x44, 0x2f, 0x20, 0x2f, 0xc4, 0xef, 0xc8, 0xa8, 0x82, 0xcf, 0x84, + 0x4f, 0x63, 0x6c, 0x16, 0x7e, 0xea, 0x5b, 0x63, 0x14, 0xe8, 0x34, 0x60, 0x86, 0x31, 0xb5, 0xd3, 0x6f, 0x85, 0x8d, + 0x93, 0x05, 0xf7, 0x9b, 0xa5, 0x69, 0x0e, 0x9f, 0xac, 0xa3, 0xfc, 0xec, 0xc9, 0x3a, 0xcd, 0x07, 0x4f, 0xd6, 0xbe, + 0xd4, 0x15, 0xd0, 0x2f, 0x74, 0x52, 0x14, 0x18, 0x22, 0x18, 0x86, 0xf9, 0x75, 0x61, 0xb9, 0x53, 0xcc, 0x17, 0x76, + 0x19, 0xa5, 0x6b, 0x28, 0xba, 0x1f, 0x70, 0x01, 0xfd, 0x32, 0x09, 0x16, 0x7e, 0x72, 0x4f, 0xf2, 0x7c, 0x53, 0x15, + 0xfa, 0x1b, 0xba, 0x46, 0x88, 0x9e, 0x00, 0x40, 0x38, 0x5f, 0xd7, 0xfe, 0x2a, 0xd3, 0x18, 0x9f, 0xad, 0x14, 0x6a, + 0x42, 0x5f, 0xd7, 0xfa, 0x73, 0x66, 0x4f, 0x58, 0xe6, 0x07, 0x21, 0x55, 0xe9, 0x8b, 0x68, 0xf5, 0xb5, 0xe9, 0xa5, + 0xe5, 0xe9, 0x45, 0xe5, 0xfd, 0x83, 0x93, 0xa1, 0x2b, 0x80, 0xc6, 0x8d, 0x33, 0xc3, 0x28, 0x56, 0xcd, 0x2b, 0x4a, + 0x79, 0xff, 0xd5, 0xe5, 0x60, 0xb0, 0x1c, 0x11, 0x2c, 0x07, 0x8b, 0xc6, 0xf1, 0x84, 0xfd, 0xf2, 0xfe, 0xad, 0x0c, + 0x9b, 0x05, 0x1c, 0xa0, 0x21, 0xdf, 0x98, 0x29, 0xd2, 0x0f, 0x09, 0xd2, 0x0e, 0x14, 0xe0, 0x4a, 0x93, 0x5b, 0x28, + 0xc9, 0x75, 0xed, 0x8c, 0xc6, 0xce, 0x26, 0x34, 0xea, 0x41, 0x8c, 0xb5, 0x92, 0xfc, 0xe4, 0x80, 0x4a, 0xd3, 0x6d, + 0x47, 0x85, 0x00, 0x0c, 0x09, 0xcc, 0xb0, 0x80, 0x02, 0x44, 0xf8, 0x1c, 0xb8, 0xc5, 0x83, 0xc2, 0x5e, 0x20, 0x9f, + 0xdd, 0x3d, 0x2b, 0x93, 0x2a, 0x58, 0x4b, 0x3f, 0x3d, 0xc1, 0x98, 0x5d, 0x70, 0x5f, 0x83, 0x97, 0x8f, 0x93, 0x03, + 0xfa, 0xd4, 0x2a, 0x27, 0xa2, 0x68, 0x44, 0x3c, 0xed, 0x7a, 0xbc, 0x81, 0x07, 0x1d, 0x15, 0x08, 0x11, 0x0f, 0xa9, + 0x7e, 0xae, 0x6b, 0x0b, 0x4e, 0x1a, 0x71, 0x77, 0x42, 0xe0, 0x6b, 0xc0, 0x81, 0xb3, 0xab, 0x6b, 0x0b, 0xff, 0x0e, + 0x67, 0x2e, 0x72, 0xfc, 0xbb, 0x96, 0xcb, 0xb3, 0x8a, 0xb3, 0x96, 0x96, 0xcf, 0xda, 0x98, 0x2f, 0x2e, 0x18, 0x12, + 0xc8, 0x97, 0xf5, 0x1c, 0x05, 0xb4, 0x0d, 0x8b, 0x3b, 0x17, 0x8b, 0x3b, 0xd9, 0xb0, 0xb8, 0x93, 0x2d, 0x8b, 0x1b, + 0xf2, 0x85, 0xd4, 0x24, 0xe8, 0x12, 0x34, 0x0e, 0x93, 0xc0, 0xe3, 0x84, 0x46, 0x8f, 0x9f, 0x33, 0x84, 0x93, 0x95, + 0x86, 0xa0, 0x1c, 0xb5, 0x01, 0x56, 0x4d, 0x70, 0x51, 0x00, 0x51, 0x9f, 0xb8, 0x3c, 0x75, 0x62, 0xde, 0x10, 0x83, + 0xb3, 0x15, 0x56, 0xe7, 0x0b, 0xbb, 0x94, 0xe2, 0x8b, 0xb7, 0xe6, 0x1b, 0x66, 0x3a, 0xdf, 0x32, 0xd3, 0x71, 0xe9, + 0xe8, 0xf2, 0x69, 0xd3, 0x21, 0x54, 0x27, 0x05, 0x7b, 0x10, 0x14, 0x46, 0x71, 0xcb, 0x94, 0xf7, 0xe1, 0x66, 0x1c, + 0xab, 0xec, 0xa8, 0xa5, 0x9f, 0xa6, 0xb7, 0x71, 0x02, 0x12, 0x17, 0x68, 0xe6, 0x61, 0x5b, 0x6a, 0x11, 0x44, 0xdc, + 0x99, 0xcb, 0xc6, 0xcd, 0x54, 0xe4, 0xab, 0x5b, 0xca, 0xeb, 0x74, 0xa8, 0xc4, 0xd2, 0xcf, 0x32, 0x96, 0x20, 0xd0, + 0x7d, 0xf0, 0xfa, 0xfd, 0xff, 0x64, 0x9b, 0x35, 0xe0, 0x90, 0x50, 0xc1, 0xea, 0x88, 0xa1, 0x97, 0x40, 0x5b, 0x25, + 0xe2, 0x22, 0x56, 0x1c, 0xc3, 0x25, 0x12, 0xf0, 0x3f, 0xe1, 0x71, 0x6d, 0x25, 0x8a, 0xe9, 0x92, 0x7b, 0x64, 0xd8, + 0x4b, 0x7f, 0xf2, 0x01, 0x04, 0x7b, 0x2d, 0xcf, 0x04, 0x25, 0x5d, 0xd5, 0x0d, 0x5c, 0x42, 0xc4, 0xde, 0xb8, 0x40, + 0x92, 0x88, 0x25, 0xb9, 0x0a, 0x14, 0x58, 0x4f, 0xfa, 0xd6, 0xf4, 0x6a, 0xed, 0xe5, 0x07, 0xb3, 0xc0, 0xa8, 0x61, + 0x4d, 0x40, 0x6d, 0xe1, 0xe0, 0x54, 0xbe, 0xb9, 0x42, 0xd3, 0x3d, 0x32, 0x80, 0xf3, 0x7b, 0x09, 0xf1, 0x4c, 0x1d, + 0xf1, 0xa0, 0x1d, 0x26, 0x70, 0x6b, 0x5d, 0x3a, 0x57, 0xf9, 0xd3, 0x19, 0xfe, 0x72, 0xaf, 0xf2, 0xa7, 0x23, 0xfc, + 0xe5, 0x5d, 0x61, 0xe4, 0xba, 0x86, 0x87, 0xbc, 0x32, 0x67, 0xfd, 0xb4, 0xb4, 0x9f, 0x48, 0xff, 0xec, 0x01, 0xdb, + 0x86, 0x2f, 0xf0, 0xe3, 0x27, 0xeb, 0x14, 0x2c, 0x2e, 0xd5, 0x39, 0x44, 0x76, 0x62, 0xe4, 0x8d, 0xe9, 0xb3, 0x0d, + 0xe9, 0x23, 0xe3, 0xbf, 0x7c, 0xf1, 0xe3, 0x2e, 0x89, 0x8b, 0x3b, 0xa5, 0xcc, 0x86, 0xb8, 0x1e, 0x05, 0x91, 0x9f, + 0xdc, 0x5f, 0xd3, 0xf3, 0xa2, 0x25, 0x68, 0x77, 0xc9, 0x5e, 0x21, 0xf2, 0xb2, 0x2c, 0xee, 0xca, 0x14, 0x06, 0xef, + 0x3d, 0xbf, 0xe8, 0x07, 0x7f, 0x4f, 0x14, 0xb2, 0xad, 0xf4, 0x00, 0xe5, 0x0b, 0x52, 0xea, 0xe8, 0xfa, 0xc9, 0xba, + 0xc5, 0xea, 0xcd, 0x54, 0x66, 0x5b, 0xa1, 0x0b, 0x61, 0x79, 0xf0, 0x31, 0xbb, 0x98, 0x04, 0x3d, 0x94, 0x67, 0x8d, + 0xe2, 0x3b, 0xeb, 0xc9, 0x3a, 0x3b, 0xd3, 0x17, 0x7e, 0xf2, 0x89, 0x4d, 0xac, 0x71, 0x90, 0x8c, 0x43, 0xa6, 0xf7, + 0xf4, 0x51, 0xe8, 0x47, 0x9f, 0xf8, 0xa7, 0x15, 0xaf, 0x32, 0x94, 0x50, 0xef, 0x7c, 0xfb, 0x0a, 0x98, 0x10, 0xcb, + 0x0e, 0x89, 0xd5, 0x06, 0x28, 0x68, 0x2f, 0x25, 0xc3, 0xab, 0x20, 0x14, 0x8b, 0x52, 0x26, 0x28, 0x58, 0x82, 0xd0, + 0x1c, 0x2c, 0x56, 0x4d, 0x1d, 0xd7, 0x4b, 0x37, 0xd5, 0xa9, 0x12, 0xb3, 0x52, 0x86, 0x5c, 0xbc, 0xc6, 0x16, 0xfe, + 0x78, 0x77, 0x14, 0x0c, 0x7b, 0xff, 0xee, 0x64, 0x2b, 0x5f, 0x36, 0x43, 0x48, 0xb5, 0xc8, 0x52, 0xe2, 0x01, 0x9d, + 0x73, 0x02, 0x73, 0x73, 0xd7, 0x6a, 0x65, 0x3f, 0x4d, 0x57, 0x0b, 0x36, 0x21, 0xc9, 0xe0, 0x59, 0x31, 0xa8, 0xf2, + 0xcb, 0x42, 0x1d, 0xd8, 0x6f, 0x2b, 0xef, 0xf8, 0xf0, 0x25, 0x68, 0x2c, 0x00, 0x41, 0x19, 0x4f, 0xa7, 0x7a, 0xf1, + 0xc6, 0xdf, 0x51, 0xcd, 0x3d, 0xfc, 0x6d, 0xf5, 0xe6, 0xb5, 0xf3, 0x46, 0x56, 0x8e, 0x80, 0x30, 0x16, 0xe2, 0x57, + 0x4e, 0x17, 0x2b, 0xe3, 0x15, 0x33, 0x9a, 0xfa, 0xd1, 0xe6, 0xe9, 0x5c, 0x96, 0xb6, 0xf8, 0x92, 0xb1, 0x09, 0x10, + 0xdc, 0x66, 0x2d, 0xf5, 0x3a, 0x64, 0x37, 0x4c, 0x8a, 0x76, 0xeb, 0x9d, 0x35, 0xd4, 0x40, 0xdf, 0x73, 0x5c, 0x64, + 0xcc, 0xa9, 0x3a, 0x65, 0x4a, 0x43, 0x9c, 0x03, 0x9f, 0xb9, 0x7a, 0xc4, 0x2a, 0x47, 0x6a, 0x68, 0xea, 0xca, 0x00, + 0x36, 0x8e, 0xec, 0x6c, 0x43, 0x7a, 0x0f, 0x03, 0x4f, 0x37, 0x8f, 0xcd, 0x74, 0x8d, 0x1e, 0xf8, 0xea, 0xe6, 0x70, + 0x0a, 0xe1, 0xe4, 0xb5, 0x0a, 0x76, 0xc8, 0x26, 0x88, 0x35, 0x31, 0xc9, 0x74, 0xe2, 0xbe, 0x08, 0x6d, 0x47, 0x54, + 0xfb, 0x15, 0x7c, 0xa8, 0xc6, 0xb5, 0xd1, 0xca, 0x33, 0x1f, 0x61, 0x40, 0xd7, 0x88, 0xa5, 0xe9, 0x46, 0x80, 0xc9, + 0x45, 0x37, 0xf5, 0xa2, 0x74, 0x19, 0x1e, 0x45, 0xba, 0xe9, 0x98, 0x40, 0x12, 0xe0, 0x04, 0xab, 0x7d, 0xe1, 0xf5, + 0x72, 0xbd, 0xe0, 0xfa, 0x2a, 0xc9, 0x6c, 0xa4, 0x73, 0x5d, 0x82, 0x4d, 0xf9, 0xb7, 0x3a, 0x1f, 0x54, 0xe9, 0x9a, + 0x6e, 0x1c, 0x5a, 0xab, 0x84, 0x7a, 0x6b, 0xec, 0x22, 0x6c, 0x40, 0x8c, 0xa9, 0x82, 0x5f, 0xd9, 0x74, 0xca, 0xc6, + 0x59, 0x6a, 0x08, 0xe6, 0x91, 0xf4, 0x1e, 0x0b, 0x56, 0x43, 0x8f, 0x06, 0xfa, 0x4f, 0x60, 0x43, 0x2f, 0x9c, 0x2c, + 0xf1, 0x01, 0x89, 0x37, 0x53, 0x33, 0x98, 0xa8, 0xc5, 0x32, 0x88, 0x78, 0x2f, 0x10, 0x1c, 0xbc, 0x21, 0x1d, 0x87, + 0xc6, 0xef, 0x9f, 0x62, 0x5f, 0xc4, 0x52, 0xab, 0x65, 0x3b, 0x2a, 0xda, 0x76, 0x7c, 0xd7, 0xee, 0x9b, 0x8e, 0xeb, + 0xe4, 0xba, 0x09, 0xb6, 0x5b, 0x9f, 0xf6, 0x3d, 0xf4, 0x58, 0xab, 0x0d, 0xb5, 0x56, 0xd1, 0x43, 0xea, 0x79, 0xee, + 0x0b, 0x57, 0x37, 0x49, 0x65, 0x4e, 0xc1, 0x6d, 0xe3, 0xf8, 0x86, 0x25, 0x5f, 0x3c, 0x95, 0x72, 0xe3, 0xfb, 0x8d, + 0xe7, 0xc8, 0x75, 0x00, 0x09, 0x67, 0xf1, 0xf2, 0x01, 0x53, 0x68, 0xeb, 0xa6, 0x3e, 0x0e, 0xe3, 0x94, 0xa9, 0x73, + 0x20, 0x26, 0xc8, 0x17, 0x4e, 0xe2, 0xe7, 0xf7, 0xaf, 0x3f, 0x7c, 0xd0, 0x4d, 0x8c, 0x04, 0x9a, 0xaa, 0xad, 0xf3, + 0x0d, 0xb5, 0x03, 0xfb, 0x37, 0xee, 0x3b, 0xba, 0x61, 0xe8, 0x51, 0x5b, 0xde, 0x73, 0x94, 0x56, 0xdb, 0x72, 0xfc, + 0xe6, 0xe1, 0x3d, 0xd3, 0x4b, 0x74, 0xaf, 0x79, 0x35, 0xe0, 0x86, 0xed, 0xd7, 0x5b, 0x29, 0x65, 0x11, 0x44, 0xd7, + 0x0d, 0xa9, 0xfe, 0x5d, 0x43, 0x2a, 0x3c, 0xe5, 0x6a, 0xb8, 0x6a, 0x15, 0x2f, 0x14, 0xd2, 0x00, 0x02, 0x39, 0xef, + 0x02, 0x97, 0xf2, 0x9e, 0xfa, 0x82, 0x41, 0x73, 0x4f, 0xee, 0xd5, 0x51, 0x37, 0x24, 0xf3, 0x47, 0x90, 0x84, 0xed, + 0x38, 0x04, 0x85, 0x3f, 0xa6, 0x4a, 0xe5, 0xca, 0x64, 0xa3, 0x54, 0xd7, 0x55, 0x1a, 0x21, 0xf2, 0xf6, 0x3a, 0x63, + 0x8b, 0x25, 0x4b, 0xfc, 0x6c, 0x95, 0xb0, 0xeb, 0x30, 0xbe, 0x7d, 0x54, 0xa8, 0xd3, 0xef, 0x28, 0x3c, 0x0f, 0x66, + 0x73, 0x59, 0xfa, 0xac, 0xc5, 0x06, 0x72, 0x01, 0xb7, 0x76, 0x90, 0xff, 0xe7, 0xdf, 0xb6, 0xfd, 0x9f, 0x7f, 0xef, + 0x2c, 0x0a, 0xcd, 0xe7, 0x43, 0x33, 0x1b, 0xec, 0xb1, 0x2f, 0x9a, 0x7b, 0x2a, 0xc3, 0xbc, 0xb9, 0x4c, 0x6d, 0x11, + 0x20, 0xbf, 0xb6, 0x04, 0xb5, 0xc4, 0xf2, 0xbe, 0x79, 0xd0, 0xc0, 0x60, 0x5e, 0x3b, 0x47, 0x06, 0x85, 0xbe, 0x68, + 0x68, 0x43, 0xa3, 0xb7, 0xd7, 0x8a, 0xfc, 0x71, 0x08, 0xef, 0x9a, 0xc3, 0x17, 0x0e, 0x9f, 0xf3, 0x25, 0x5f, 0x0e, + 0x87, 0x32, 0xb6, 0x9c, 0x5a, 0x15, 0x54, 0xfc, 0xcf, 0x6a, 0x29, 0xfc, 0xf2, 0xec, 0x39, 0x06, 0xd9, 0xde, 0x0f, + 0x5e, 0x0e, 0x51, 0x19, 0xed, 0x64, 0x94, 0x14, 0xc4, 0xca, 0x46, 0xd4, 0x46, 0xca, 0xe4, 0xb5, 0x46, 0x6b, 0x78, + 0x0d, 0x52, 0x31, 0xe0, 0x58, 0x3e, 0x34, 0xcc, 0x97, 0x43, 0xce, 0x58, 0xe2, 0xfa, 0xaf, 0xbd, 0xea, 0xd6, 0xe6, + 0x6c, 0xd9, 0x12, 0xd0, 0x4d, 0x8d, 0xe4, 0x3f, 0x58, 0x98, 0x15, 0x7c, 0x3c, 0x64, 0xf0, 0x03, 0x47, 0x61, 0x98, + 0x63, 0xbc, 0x93, 0x77, 0x9b, 0x74, 0xc4, 0x7e, 0xde, 0xad, 0x23, 0x76, 0xb1, 0x97, 0x8e, 0xd8, 0xcf, 0x5f, 0x5d, + 0x47, 0xec, 0x9d, 0xaa, 0x23, 0x06, 0x8b, 0xf8, 0x9a, 0xed, 0xa5, 0xb8, 0x25, 0xb4, 0x36, 0xe2, 0xdb, 0x74, 0xe0, + 0x72, 0x92, 0x36, 0x1d, 0xcf, 0x19, 0xf0, 0x08, 0xf8, 0xaa, 0x84, 0xf1, 0x0c, 0x94, 0xb8, 0xfe, 0x7c, 0x75, 0xab, + 0x30, 0x9e, 0xa9, 0xca, 0x56, 0x11, 0xf7, 0xf8, 0x5a, 0x78, 0x71, 0x22, 0x05, 0x27, 0xc7, 0x14, 0x3e, 0x9f, 0xac, + 0x43, 0x43, 0x89, 0x6a, 0x2d, 0xb5, 0xd7, 0x3c, 0xa1, 0x02, 0xd5, 0x43, 0xed, 0x29, 0x59, 0xd1, 0x7b, 0x2e, 0x7c, + 0x5b, 0xa8, 0x2d, 0x48, 0x2d, 0x61, 0xf2, 0x13, 0xb1, 0xd6, 0x7f, 0xbb, 0x73, 0xbf, 0xbf, 0x74, 0xfb, 0x6d, 0x17, + 0x8c, 0xb3, 0xe1, 0x85, 0x89, 0x09, 0x4e, 0xbf, 0xdd, 0x86, 0x84, 0x5b, 0x25, 0xc1, 0x83, 0x84, 0x40, 0x49, 0xe8, + 0x40, 0xc2, 0x58, 0x49, 0x38, 0x82, 0x84, 0x89, 0x92, 0x70, 0x0c, 0x09, 0x37, 0x7a, 0x7e, 0x19, 0xc9, 0xe1, 0x1e, + 0x1b, 0x57, 0x26, 0x3d, 0x2a, 0x44, 0xda, 0xb1, 0xe9, 0x82, 0xd6, 0x94, 0x3f, 0xeb, 0xc5, 0x26, 0x71, 0x17, 0x7b, + 0x89, 0x79, 0x3b, 0x67, 0xe4, 0x28, 0xfa, 0x15, 0xde, 0x39, 0x76, 0x16, 0x83, 0xde, 0xb4, 0x70, 0xc0, 0x20, 0xe0, + 0xa0, 0xe9, 0x06, 0x30, 0x8c, 0xfa, 0x72, 0xe5, 0x84, 0x13, 0x0b, 0x65, 0x2d, 0x8b, 0x3c, 0xea, 0xce, 0x92, 0x5b, + 0xa0, 0xd0, 0x38, 0x69, 0xa9, 0x5c, 0xc9, 0xaf, 0xa1, 0x77, 0xf0, 0x8a, 0x8d, 0x56, 0x33, 0xed, 0x3c, 0x9e, 0xed, + 0x54, 0x21, 0x50, 0xb3, 0x60, 0x94, 0x3a, 0x89, 0x5f, 0x2c, 0xb1, 0x2d, 0x79, 0x5f, 0xf4, 0x99, 0x97, 0xcb, 0x67, + 0x30, 0x36, 0x2d, 0x23, 0x05, 0x16, 0xe8, 0x07, 0x60, 0xa4, 0xc8, 0xf0, 0xcf, 0x01, 0xce, 0xca, 0xf7, 0x85, 0xaf, + 0x8c, 0xe7, 0xf4, 0x47, 0x96, 0xa6, 0xfe, 0x4c, 0x94, 0xaf, 0x8f, 0x13, 0x94, 0x76, 0xe4, 0xfb, 0x0b, 0x01, 0x08, + 0x9c, 0xbc, 0xa0, 0xa6, 0x9b, 0x91, 0xc4, 0xb7, 0x1a, 0x68, 0xff, 0xc0, 0x86, 0x2a, 0xf4, 0x14, 0x02, 0x1b, 0x96, + 0xb0, 0xac, 0x51, 0x00, 0x87, 0xff, 0x86, 0x85, 0xd5, 0xc4, 0xcc, 0x9f, 0x55, 0x93, 0x68, 0x1f, 0xe4, 0xea, 0xd8, + 0xa4, 0x40, 0xbf, 0x94, 0xf8, 0x25, 0x12, 0xea, 0x30, 0x9e, 0xfd, 0xa9, 0xe2, 0xe9, 0x2d, 0x6a, 0x05, 0x1f, 0x22, + 0x33, 0xc8, 0x86, 0x36, 0xc2, 0x58, 0xb3, 0x01, 0x84, 0xbd, 0x28, 0x9b, 0x5b, 0x68, 0x5a, 0xd6, 0xf2, 0x22, 0xc3, + 0xb4, 0x71, 0x6d, 0xd7, 0x55, 0x83, 0xda, 0x5e, 0x32, 0x1b, 0xf9, 0x2d, 0xd7, 0x3b, 0x36, 0xc5, 0x1f, 0xdb, 0xe9, + 0x18, 0x39, 0xb6, 0xa0, 0x4d, 0x82, 0x9b, 0xf5, 0x34, 0x8e, 0x32, 0x6b, 0xea, 0x2f, 0x82, 0xf0, 0xbe, 0xb7, 0x88, + 0xa3, 0x38, 0x5d, 0xfa, 0x63, 0xd6, 0x2f, 0x1e, 0xd4, 0x7d, 0x74, 0xd5, 0xc0, 0xad, 0x05, 0x5d, 0xdb, 0x4b, 0xd8, + 0x82, 0x6a, 0x4b, 0x4f, 0x0c, 0xd3, 0x90, 0xdd, 0xe5, 0xbc, 0xfb, 0x52, 0x61, 0x2a, 0x8a, 0x5b, 0x8e, 0x6a, 0x00, + 0x45, 0xca, 0xdd, 0x3c, 0x80, 0x73, 0xa3, 0xfe, 0xd2, 0x9f, 0xa0, 0x67, 0x42, 0xdb, 0xeb, 0x24, 0x6c, 0xa1, 0xd9, + 0x9d, 0x8d, 0x8d, 0x27, 0xf1, 0xed, 0x29, 0x8c, 0x16, 0x2b, 0x5b, 0x29, 0x0b, 0xa7, 0x98, 0x63, 0xa1, 0x65, 0x89, + 0x68, 0xc7, 0xc2, 0x87, 0x38, 0xb4, 0xc6, 0x16, 0x7d, 0xc8, 0xee, 0x79, 0x9a, 0xd3, 0x5f, 0x04, 0x91, 0x45, 0xd3, + 0x39, 0x76, 0x96, 0x4a, 0x5b, 0x2a, 0xfc, 0x8c, 0x35, 0x16, 0x77, 0x35, 0xa7, 0x0f, 0x8f, 0xb5, 0x69, 0x18, 0xdf, + 0xf6, 0xe6, 0xc1, 0x64, 0xc2, 0xa2, 0x3e, 0x8e, 0x59, 0x26, 0xb2, 0x30, 0x0c, 0x96, 0x69, 0x90, 0xf6, 0x17, 0xfe, + 0x1d, 0x6f, 0xf5, 0x70, 0x53, 0xab, 0x6d, 0xde, 0x6a, 0x7b, 0xef, 0x56, 0x95, 0x66, 0xc0, 0x8a, 0x85, 0xda, 0xe1, + 0x43, 0xeb, 0x68, 0x4e, 0x65, 0x9e, 0x7b, 0xb7, 0xba, 0x4c, 0xd8, 0x7a, 0xe1, 0x27, 0xb3, 0x20, 0xea, 0x39, 0xb9, + 0x7d, 0xb3, 0xa6, 0x8d, 0xf1, 0xb8, 0xdb, 0xed, 0xe6, 0xf6, 0x44, 0x7c, 0x39, 0x93, 0x49, 0x6e, 0x8f, 0xc5, 0xd7, + 0x74, 0xea, 0x38, 0xd3, 0x69, 0x6e, 0x07, 0x22, 0xa1, 0xed, 0x8d, 0x27, 0x6d, 0x2f, 0xb7, 0x6f, 0x95, 0x12, 0xb9, + 0xcd, 0xf8, 0x57, 0xc2, 0x26, 0x7d, 0xdc, 0x48, 0xa4, 0x56, 0xda, 0x3b, 0x76, 0x9c, 0x1c, 0x31, 0xc0, 0x65, 0x09, + 0x37, 0x21, 0xaf, 0xe7, 0x6a, 0xbd, 0x77, 0x49, 0xad, 0xe8, 0x6e, 0x3c, 0x6e, 0x2c, 0x37, 0xf1, 0x93, 0x4f, 0x57, + 0x9a, 0x32, 0x0b, 0xdf, 0xa7, 0x62, 0x6b, 0x01, 0x06, 0xeb, 0xae, 0x07, 0x2e, 0xbb, 0xfa, 0xa3, 0x38, 0x81, 0x33, + 0x9b, 0xf8, 0x93, 0x60, 0x95, 0xf6, 0x5c, 0x6f, 0x79, 0x27, 0x92, 0xf8, 0x5e, 0x2f, 0x12, 0xf0, 0xec, 0xf5, 0xd2, + 0x38, 0x0c, 0x26, 0x22, 0x69, 0xd3, 0x59, 0x72, 0x3d, 0xa3, 0x8f, 0x06, 0xeb, 0x01, 0xba, 0x5d, 0xf0, 0xc3, 0x50, + 0xb3, 0xdb, 0xa9, 0xc6, 0xfc, 0x14, 0xf9, 0xcb, 0x9a, 0x93, 0x12, 0x5c, 0xd0, 0x38, 0xdd, 0x3d, 0x5c, 0xde, 0xc9, + 0x3d, 0xef, 0x1e, 0x2d, 0xef, 0xf2, 0xbf, 0x2e, 0xd8, 0x24, 0xf0, 0xb5, 0x56, 0xb1, 0x9b, 0x5c, 0x07, 0x78, 0xd0, + 0xc6, 0x7a, 0xc3, 0x36, 0x15, 0xc7, 0x02, 0x5c, 0x1b, 0x3e, 0x0a, 0x16, 0xcb, 0x38, 0xc9, 0xfc, 0x28, 0xcb, 0xf3, + 0xe1, 0x55, 0x9e, 0xf7, 0x2f, 0x82, 0xd6, 0xe5, 0x3f, 0x5a, 0x74, 0x4f, 0x93, 0xcc, 0x26, 0x37, 0xae, 0xcc, 0xd7, + 0x4c, 0xd5, 0x19, 0x81, 0x6b, 0x0c, 0xf5, 0x45, 0xd4, 0xc2, 0x74, 0x4b, 0xd6, 0x0b, 0x13, 0x90, 0x65, 0x71, 0xd2, + 0x41, 0x29, 0x17, 0xc1, 0x1b, 0x08, 0x0a, 0xbc, 0x66, 0x83, 0x0b, 0x45, 0xff, 0x04, 0x88, 0x15, 0x2c, 0x4c, 0x76, + 0x05, 0x4f, 0x36, 0xd1, 0x8c, 0xdf, 0xed, 0xa6, 0x19, 0x7f, 0xcd, 0xf6, 0xa1, 0x19, 0xbf, 0xfb, 0xea, 0x34, 0xe3, + 0x93, 0xba, 0x5d, 0xc1, 0xdb, 0x78, 0xa0, 0x4b, 0x09, 0x03, 0x5c, 0x4d, 0x09, 0x79, 0xec, 0x79, 0xfb, 0x87, 0xcd, + 0x00, 0x44, 0x6b, 0x14, 0x83, 0x8e, 0x6e, 0x6e, 0xe0, 0xc7, 0xbe, 0x8b, 0x06, 0x7f, 0x4f, 0xd4, 0xef, 0xe9, 0x74, + 0xf0, 0x2a, 0x56, 0x12, 0xe4, 0x17, 0x57, 0xbe, 0x28, 0x79, 0x57, 0xa0, 0x1c, 0xa1, 0x85, 0x89, 0xf1, 0x27, 0xc0, + 0x38, 0x9b, 0xb4, 0x8e, 0x27, 0x52, 0xfb, 0xac, 0x5f, 0x1e, 0x42, 0x4b, 0xaa, 0x7c, 0x0a, 0x13, 0x9c, 0x1a, 0x2b, + 0x71, 0xc6, 0x32, 0x6e, 0x33, 0xfb, 0xfd, 0xfd, 0xdb, 0x49, 0xeb, 0x6d, 0x6c, 0xe4, 0x41, 0xfa, 0xae, 0x6a, 0x00, + 0xc3, 0x65, 0x3f, 0x03, 0x75, 0x3a, 0x39, 0xd7, 0x20, 0x53, 0x03, 0x4c, 0x43, 0x36, 0x55, 0x3f, 0x2b, 0xcd, 0xb4, + 0xa7, 0x56, 0xe4, 0x81, 0xae, 0x6a, 0x97, 0x31, 0xb7, 0x3e, 0x58, 0x73, 0x0a, 0x10, 0x63, 0x77, 0xa1, 0xdd, 0xf0, + 0x84, 0xaa, 0x07, 0x93, 0x3c, 0x37, 0xfa, 0x02, 0x10, 0xca, 0x45, 0xcb, 0x76, 0x11, 0x71, 0xe9, 0xad, 0xd4, 0x69, + 0xe0, 0x12, 0x42, 0x12, 0xff, 0xbd, 0x05, 0x81, 0x3a, 0x17, 0x16, 0x72, 0x98, 0xe9, 0x1a, 0x81, 0x8f, 0x14, 0x2d, + 0x94, 0x09, 0x81, 0x04, 0x58, 0xc2, 0x5f, 0x64, 0x89, 0x84, 0xba, 0x0e, 0x27, 0x01, 0x07, 0x35, 0x02, 0xc0, 0xca, + 0x5f, 0xf0, 0xb5, 0x09, 0xed, 0xf0, 0x32, 0xf8, 0x91, 0xeb, 0x92, 0xf6, 0xc3, 0xed, 0x77, 0x7a, 0x72, 0x00, 0x15, + 0x4e, 0x2b, 0x8a, 0x03, 0x3b, 0x34, 0x14, 0x81, 0x94, 0x48, 0x6f, 0x4d, 0x3b, 0xbd, 0xd5, 0x9e, 0xad, 0x85, 0x87, + 0x8c, 0xcc, 0x5f, 0x5a, 0xf0, 0xc4, 0x47, 0xdc, 0xcb, 0x31, 0x9e, 0xe2, 0x8c, 0xa3, 0xbf, 0x4a, 0x01, 0x37, 0xe2, + 0x43, 0x15, 0xf1, 0x4f, 0x7f, 0xbc, 0x4a, 0xd2, 0x38, 0xe9, 0x2d, 0xe3, 0x20, 0xca, 0x58, 0x92, 0x23, 0xa8, 0x2e, + 0x11, 0x3e, 0x02, 0x3c, 0x57, 0xeb, 0x78, 0xe9, 0x8f, 0x83, 0xec, 0xbe, 0xe7, 0x70, 0x92, 0xc2, 0xe9, 0x73, 0xea, + 0xc0, 0x69, 0x2c, 0xdf, 0xe3, 0xd0, 0x7c, 0x8e, 0x84, 0x5f, 0x52, 0x27, 0x67, 0xd4, 0x6d, 0xde, 0x57, 0x72, 0xc9, + 0x47, 0x08, 0x90, 0x1f, 0x7e, 0x62, 0xcd, 0x00, 0xcb, 0xc3, 0x52, 0x3b, 0x13, 0x36, 0x33, 0x11, 0x6b, 0x03, 0x5f, + 0x5e, 0xfc, 0xb1, 0x3b, 0x86, 0xe6, 0x34, 0x27, 0x03, 0xc5, 0x63, 0xec, 0x33, 0xb2, 0x9e, 0x0f, 0x11, 0xb5, 0xcc, + 0x7d, 0x4a, 0x8e, 0xd8, 0x34, 0x4e, 0x18, 0xf9, 0x93, 0x75, 0xbb, 0xcb, 0xbb, 0xfd, 0x9b, 0xdf, 0x3e, 0xfd, 0xe6, + 0x76, 0xa2, 0x38, 0x6b, 0x89, 0xc6, 0x8c, 0x1d, 0xad, 0xd5, 0xef, 0x33, 0x20, 0x0d, 0x09, 0xf2, 0x63, 0x72, 0xdd, + 0xd5, 0xd3, 0xf5, 0x7e, 0xa3, 0xdb, 0xae, 0x65, 0xcc, 0xef, 0xbc, 0x84, 0x85, 0x7e, 0x16, 0xdc, 0x08, 0x9a, 0xb1, + 0x7d, 0xb4, 0xbc, 0x13, 0x6b, 0x8c, 0x17, 0xde, 0x03, 0x16, 0xa9, 0x32, 0x14, 0xb1, 0x48, 0xd5, 0x64, 0x5c, 0xa4, + 0x7e, 0x6d, 0x36, 0xc2, 0x93, 0x45, 0xe5, 0xa6, 0xef, 0x2c, 0xef, 0xd4, 0x2b, 0xba, 0xa8, 0x26, 0x6f, 0xea, 0xaa, + 0x0b, 0xb2, 0x45, 0x30, 0x99, 0x84, 0x2c, 0x2f, 0x2d, 0x74, 0x79, 0x2d, 0x15, 0xe0, 0x48, 0x38, 0xf8, 0xa3, 0x34, + 0x0e, 0x57, 0x19, 0x6b, 0x06, 0x17, 0x01, 0xc7, 0x73, 0x0a, 0xe0, 0xe0, 0xef, 0xf2, 0x58, 0x3b, 0x40, 0x6e, 0xc3, + 0x36, 0x71, 0xfa, 0xe0, 0x71, 0xd8, 0x6a, 0x97, 0x87, 0x0e, 0x59, 0x72, 0xd0, 0x66, 0xc3, 0x44, 0x4c, 0xb8, 0x96, + 0x08, 0x7b, 0x6b, 0xb6, 0xcb, 0xd3, 0xa4, 0xd7, 0x55, 0x99, 0x94, 0x97, 0x27, 0xf3, 0xe7, 0x9c, 0xb1, 0x17, 0xcd, + 0x67, 0xec, 0x85, 0x38, 0x63, 0xdb, 0x77, 0xe6, 0xe3, 0xa9, 0x0b, 0xff, 0xf5, 0x8b, 0x09, 0xf5, 0x1c, 0xad, 0xbd, + 0xbc, 0xd3, 0xdc, 0xe5, 0x9d, 0x66, 0x79, 0xcb, 0x3b, 0x0d, 0x9b, 0x46, 0x7d, 0x10, 0xd3, 0xf6, 0x0c, 0xd3, 0xd1, + 0x20, 0x11, 0xfe, 0x38, 0xa5, 0x2c, 0xf7, 0x10, 0xf2, 0xa0, 0x56, 0xa7, 0x9e, 0xe7, 0x6d, 0x3f, 0xea, 0x74, 0x96, + 0x04, 0xd2, 0x36, 0xec, 0xcc, 0x1f, 0x8d, 0xd8, 0xa4, 0x37, 0x8d, 0xc7, 0xab, 0xf4, 0x5f, 0x7c, 0xfc, 0x1c, 0x88, + 0x5b, 0x11, 0x41, 0xa5, 0x1d, 0x51, 0x15, 0x04, 0x25, 0x37, 0x4c, 0xb4, 0xb0, 0x96, 0xeb, 0xd4, 0x23, 0xf7, 0xc8, + 0x9e, 0x7d, 0xd8, 0xb0, 0xc9, 0x9b, 0x01, 0xfd, 0xa7, 0xad, 0xd2, 0x66, 0x14, 0xf3, 0x05, 0x60, 0xd9, 0x0a, 0x8e, + 0x87, 0x43, 0x83, 0xaf, 0xa6, 0xd3, 0x6d, 0x1e, 0xee, 0xa5, 0xe8, 0xe9, 0x4a, 0x5c, 0x2a, 0xfc, 0xde, 0xe2, 0x86, + 0x29, 0xdb, 0x5b, 0xdd, 0xb4, 0x47, 0x6a, 0xad, 0x6e, 0xb9, 0x10, 0x8a, 0xb2, 0x7b, 0x62, 0xf9, 0xc7, 0x2f, 0x0e, + 0xe1, 0x3f, 0xa2, 0xea, 0x7f, 0xcd, 0x9a, 0x08, 0xf5, 0xb7, 0x65, 0x4d, 0x70, 0x22, 0x95, 0x90, 0x10, 0xdf, 0xbf, + 0xfc, 0x74, 0xfa, 0xb0, 0x0a, 0x7b, 0x97, 0x26, 0x55, 0xaa, 0x6a, 0xe9, 0xef, 0xe3, 0x18, 0x42, 0x77, 0xd6, 0x8b, + 0x0b, 0xf0, 0x90, 0xb2, 0x7b, 0x36, 0x80, 0x4a, 0xe2, 0x1d, 0x41, 0x52, 0x7c, 0x1d, 0xeb, 0xd0, 0x53, 0xe2, 0xf5, + 0xa6, 0xa7, 0xc4, 0xab, 0xdd, 0x4f, 0x89, 0x1f, 0xf6, 0x7a, 0x4a, 0xbc, 0xfa, 0xea, 0x4f, 0x89, 0xd7, 0xf5, 0xa7, + 0xc4, 0x45, 0x2c, 0xf4, 0x67, 0xcd, 0xb7, 0x2b, 0xfe, 0xf3, 0x23, 0x09, 0xe5, 0xce, 0xe3, 0x41, 0xc7, 0x21, 0x97, + 0xc7, 0x17, 0x7f, 0xf8, 0x61, 0x81, 0x1b, 0xf1, 0x3d, 0xaa, 0x93, 0x15, 0x4f, 0x0b, 0x8e, 0xd9, 0xb1, 0x1f, 0x25, + 0x39, 0x8c, 0xa3, 0xd9, 0xcf, 0x20, 0x94, 0x05, 0x76, 0x60, 0xa2, 0x64, 0x04, 0xe9, 0xcf, 0xf1, 0x72, 0xb5, 0x7c, + 0x0b, 0x6d, 0x7d, 0x0c, 0xd2, 0x60, 0x14, 0x32, 0x69, 0x89, 0x4c, 0xea, 0x6f, 0x9c, 0x27, 0x0e, 0x1a, 0xa7, 0xe2, + 0xa7, 0x7f, 0x27, 0x7e, 0xa2, 0x4e, 0x2a, 0xff, 0x4d, 0x7a, 0x75, 0x7a, 0xf3, 0x43, 0x44, 0x08, 0x01, 0x95, 0x41, + 0x3f, 0xfc, 0x31, 0x72, 0x11, 0x1b, 0x0d, 0xb3, 0x14, 0xfa, 0x0e, 0x1b, 0xdb, 0x61, 0xb5, 0x47, 0xcd, 0xca, 0x30, + 0xa5, 0x0b, 0xae, 0x3a, 0x1b, 0x7e, 0x11, 0xaf, 0x52, 0x36, 0x89, 0x6f, 0x23, 0xdd, 0x8c, 0xa4, 0x91, 0x01, 0x48, + 0x38, 0x65, 0x1d, 0x0c, 0x1e, 0xf9, 0x01, 0x09, 0xe5, 0x38, 0x69, 0xe9, 0x10, 0xbb, 0x74, 0xb5, 0xb4, 0x48, 0xd4, + 0x6c, 0xe1, 0x14, 0x75, 0x19, 0xe5, 0xe8, 0x51, 0xab, 0x15, 0x0f, 0x1e, 0x56, 0x53, 0xa8, 0x6a, 0xc4, 0x36, 0xe7, + 0x0a, 0xa7, 0xad, 0x48, 0x30, 0x17, 0x85, 0x1f, 0x8c, 0x86, 0x85, 0xe3, 0x39, 0x64, 0xba, 0x5a, 0xe4, 0x82, 0x17, + 0x91, 0x7c, 0xc5, 0xd7, 0x83, 0x7b, 0x85, 0xa0, 0xcf, 0x97, 0x0a, 0x18, 0xdf, 0xdd, 0xb0, 0x24, 0xf4, 0xef, 0x5b, + 0x46, 0x1e, 0x47, 0x3f, 0x02, 0x00, 0x5e, 0xc5, 0xb7, 0x91, 0x5a, 0x00, 0x83, 0xb5, 0x34, 0xec, 0xa5, 0x46, 0xff, + 0x25, 0x60, 0xb8, 0xa2, 0x8c, 0x00, 0xc2, 0xe4, 0xce, 0xd8, 0xdf, 0x4d, 0xfa, 0xf7, 0x1f, 0x46, 0x6e, 0x9e, 0xc7, + 0xb2, 0xa3, 0x5f, 0x96, 0x7b, 0x74, 0xf3, 0xf4, 0xe9, 0xa3, 0xcd, 0xd3, 0x2e, 0x87, 0x67, 0x6f, 0xa8, 0x6d, 0x6c, + 0x3c, 0x05, 0x30, 0x8a, 0x8b, 0x78, 0x35, 0x9e, 0xa3, 0xa2, 0xeb, 0xd7, 0x9b, 0x6f, 0x06, 0x6d, 0x62, 0x94, 0x52, + 0x39, 0xf5, 0x4a, 0x52, 0x01, 0x05, 0xec, 0xff, 0x35, 0x38, 0xe0, 0xfc, 0x1f, 0x82, 0xa1, 0xbe, 0x6b, 0xf8, 0x2b, + 0x3e, 0x78, 0xd8, 0xe6, 0xed, 0x43, 0x30, 0x4d, 0xee, 0xda, 0x42, 0x08, 0xd7, 0x9a, 0x91, 0x4c, 0x5e, 0x05, 0x9a, + 0xea, 0x46, 0x6e, 0x93, 0x87, 0x3c, 0xd1, 0x0b, 0xb3, 0xe9, 0x99, 0xce, 0x0d, 0x0d, 0x4c, 0xc6, 0xb1, 0x55, 0x05, + 0xc9, 0x70, 0x95, 0x07, 0x86, 0xe8, 0xab, 0x9a, 0xb7, 0x08, 0x22, 0x13, 0xbd, 0xc0, 0xd7, 0x73, 0xfc, 0x3b, 0xf0, + 0x83, 0x0c, 0xc8, 0xad, 0x9a, 0x05, 0x89, 0xa6, 0x6a, 0x37, 0x07, 0xa1, 0x9e, 0xf4, 0x46, 0x48, 0x08, 0x29, 0xde, + 0xf0, 0x1b, 0x4d, 0xd3, 0x34, 0xf9, 0x8c, 0xd0, 0xe4, 0x3b, 0x02, 0xd3, 0xf1, 0x39, 0x00, 0xd2, 0x92, 0x7c, 0x79, + 0x47, 0x29, 0xf0, 0x32, 0x40, 0x99, 0xac, 0x48, 0xe0, 0xae, 0xfe, 0x3a, 0x8e, 0x48, 0x10, 0x0f, 0x7a, 0x70, 0xd3, + 0xe6, 0x27, 0xe0, 0x11, 0xb8, 0xa7, 0xe1, 0x83, 0x1d, 0x73, 0x39, 0x27, 0x58, 0x73, 0xe8, 0x73, 0xd8, 0x67, 0xcd, + 0x3e, 0xe1, 0x22, 0x05, 0x0b, 0x82, 0xd4, 0xa1, 0xe2, 0xe2, 0xd9, 0x64, 0x0d, 0xb8, 0x11, 0xdf, 0x45, 0x77, 0xd9, + 0x82, 0x45, 0x2b, 0x1d, 0x63, 0x42, 0xa1, 0x8f, 0x3e, 0x28, 0xf3, 0x8a, 0x88, 0x2d, 0xc0, 0x36, 0xcd, 0x35, 0xe7, + 0x74, 0x17, 0xa6, 0x1c, 0xa5, 0xfa, 0xe6, 0x98, 0x0b, 0x36, 0x53, 0x8e, 0xdb, 0xaa, 0x37, 0x04, 0x5f, 0xd2, 0xb8, + 0x6a, 0xc8, 0x45, 0x9a, 0xd0, 0xd0, 0x06, 0x79, 0xc7, 0xe0, 0xec, 0x22, 0x01, 0xf6, 0x96, 0x5f, 0x5d, 0x34, 0x29, + 0x91, 0xf1, 0x2b, 0x8c, 0xa2, 0xc4, 0xa8, 0x37, 0xc3, 0xc7, 0x09, 0x8e, 0x89, 0x36, 0xb6, 0x33, 0xae, 0xb5, 0xb3, + 0x61, 0xd2, 0x9f, 0xd8, 0x3d, 0x5d, 0x24, 0x04, 0xaa, 0x4f, 0xec, 0x1e, 0x74, 0xff, 0x5e, 0x03, 0x37, 0x45, 0xdf, + 0x82, 0xae, 0x4d, 0x70, 0xf5, 0x3f, 0x06, 0x67, 0x55, 0x5b, 0x0e, 0x90, 0x93, 0x6f, 0xc1, 0xe2, 0x08, 0x62, 0x88, + 0xea, 0x2c, 0x0e, 0x31, 0x57, 0xf1, 0x6f, 0x35, 0xc2, 0xd8, 0x6a, 0x38, 0x1a, 0xc6, 0x33, 0xd7, 0x71, 0x0e, 0x6a, + 0xe5, 0x81, 0x91, 0xdd, 0x54, 0xda, 0x30, 0xb3, 0x81, 0xeb, 0x58, 0xc1, 0x33, 0xdb, 0xeb, 0xd7, 0xee, 0x68, 0xc5, + 0x97, 0xe4, 0x10, 0xd9, 0x5f, 0xa7, 0x4f, 0xd6, 0xad, 0xda, 0x81, 0x34, 0xaa, 0x2a, 0xf3, 0x38, 0xb6, 0x9c, 0xf3, + 0xbf, 0x86, 0xf5, 0xab, 0x9f, 0x3c, 0x59, 0x52, 0x5c, 0x93, 0x21, 0x78, 0x43, 0x6e, 0xc1, 0x31, 0xfa, 0x8b, 0xf6, + 0x5c, 0x6b, 0xd1, 0xf1, 0x31, 0x8c, 0xa1, 0x0c, 0x97, 0x2d, 0x6c, 0xca, 0xd4, 0x06, 0x2a, 0x3d, 0xa6, 0x55, 0x0c, + 0xc7, 0xfd, 0xae, 0xb2, 0x42, 0xa2, 0xb7, 0x95, 0x5a, 0xc0, 0xf6, 0x37, 0x5c, 0x9f, 0xf6, 0x08, 0xfc, 0x12, 0x40, + 0x09, 0xf0, 0x9d, 0xbe, 0xb3, 0xc1, 0xd5, 0xb2, 0xdc, 0x5c, 0xf9, 0x92, 0xdc, 0xbf, 0x31, 0xbc, 0x74, 0x50, 0x86, + 0x26, 0xdb, 0x6b, 0xbe, 0xee, 0x1e, 0xd8, 0x24, 0x8b, 0x26, 0xe5, 0x06, 0x2b, 0xf7, 0xd7, 0xfe, 0xcd, 0x95, 0x30, + 0x0a, 0x04, 0x15, 0x88, 0x1b, 0x30, 0x4a, 0x1e, 0x47, 0xb8, 0xf9, 0xe9, 0xb8, 0x05, 0x7b, 0x51, 0x31, 0x58, 0x81, + 0x3c, 0x82, 0xc9, 0x6a, 0x0a, 0x53, 0x1c, 0x3c, 0x57, 0xa3, 0x59, 0x70, 0x4b, 0x10, 0xa2, 0x1b, 0x77, 0x62, 0x26, + 0x74, 0x0a, 0x8b, 0x3a, 0x01, 0xf7, 0x45, 0xb9, 0x2f, 0xd7, 0x3a, 0xd8, 0xcd, 0xb5, 0xce, 0x76, 0x71, 0xad, 0xc9, + 0x9c, 0xea, 0x36, 0xf1, 0x97, 0x8a, 0x45, 0x9e, 0x20, 0xce, 0x55, 0xc3, 0xbc, 0x12, 0xab, 0x1b, 0xad, 0xaf, 0x44, + 0xad, 0x5a, 0x6b, 0xa4, 0x25, 0x88, 0xec, 0x6f, 0xe5, 0x81, 0x22, 0x04, 0xea, 0x2a, 0x6f, 0xfc, 0xa2, 0xe0, 0x8d, + 0xd3, 0xab, 0xa6, 0x30, 0xa4, 0x11, 0xd4, 0xbf, 0x62, 0xa4, 0x26, 0x5f, 0x07, 0x85, 0xb1, 0x5a, 0x31, 0x52, 0xc5, + 0xfc, 0xaa, 0x78, 0x68, 0x28, 0x46, 0x7d, 0xe2, 0x95, 0x51, 0xb6, 0xed, 0x2b, 0x17, 0x2d, 0xac, 0xaf, 0x8a, 0x74, + 0xe0, 0xba, 0xe3, 0x90, 0x65, 0xb2, 0xba, 0x6d, 0xca, 0xe6, 0x37, 0x6a, 0xb6, 0xb2, 0x49, 0xa4, 0x9d, 0x0c, 0x01, + 0x58, 0xb0, 0xe9, 0x2b, 0x72, 0x6d, 0xa9, 0x03, 0x81, 0x83, 0x6c, 0x30, 0xeb, 0xdb, 0xcd, 0x9d, 0xa7, 0x78, 0x09, + 0x85, 0x14, 0x5e, 0xe5, 0x41, 0x20, 0x7c, 0xaf, 0xd6, 0x0d, 0xb7, 0x3c, 0x5e, 0xf2, 0xfc, 0x7e, 0x07, 0xf6, 0xa2, + 0xe6, 0xa8, 0x82, 0x7c, 0x3c, 0x99, 0x16, 0xa9, 0xe7, 0x62, 0xd1, 0x7a, 0xa3, 0xc4, 0xc4, 0x59, 0x73, 0xcb, 0x98, + 0x32, 0x8f, 0x9e, 0x97, 0xe8, 0x89, 0x7e, 0xf9, 0xd6, 0x49, 0x56, 0x11, 0xfa, 0xb6, 0xb7, 0xb2, 0xc4, 0x1f, 0x7f, + 0x52, 0x86, 0x2c, 0xf8, 0x9c, 0xc0, 0x03, 0x2e, 0x4b, 0x0a, 0xfa, 0x3e, 0xba, 0x82, 0x64, 0x3d, 0xdb, 0x4b, 0x15, + 0xee, 0x4b, 0xef, 0xb1, 0xd3, 0xf6, 0x5f, 0x4c, 0x0f, 0x2b, 0x4c, 0x51, 0xaf, 0x53, 0x66, 0x99, 0x6f, 0x18, 0x47, + 0x36, 0x5f, 0x2d, 0x46, 0x6b, 0x95, 0xb7, 0xaa, 0xb0, 0x5c, 0xeb, 0x6c, 0x56, 0xb5, 0xdb, 0xe9, 0x74, 0x5a, 0x66, + 0x34, 0x3a, 0xda, 0x21, 0x32, 0x0b, 0x1f, 0x3b, 0x8e, 0x53, 0x1d, 0xfb, 0x76, 0xb0, 0x5b, 0xc8, 0xb7, 0xed, 0x36, + 0x8e, 0x18, 0x61, 0xbb, 0x0b, 0x7e, 0x75, 0x70, 0xe4, 0x76, 0x71, 0xb2, 0x4b, 0x6a, 0x11, 0x7d, 0x52, 0x86, 0x08, + 0x32, 0xb6, 0x48, 0x7b, 0x63, 0x86, 0x32, 0x18, 0x5b, 0x39, 0xd0, 0xa8, 0x38, 0x60, 0xcd, 0x40, 0x55, 0xc4, 0x15, + 0xbb, 0xc2, 0xd1, 0x90, 0x1f, 0x5e, 0x63, 0xde, 0x8b, 0x4e, 0xf0, 0xa0, 0xac, 0xeb, 0x3c, 0x6d, 0x9c, 0x56, 0xc7, + 0xf9, 0x4b, 0xa9, 0x9c, 0x06, 0x17, 0xe0, 0x5a, 0x08, 0xb4, 0x89, 0x3f, 0x8b, 0x7f, 0x4b, 0xfe, 0xff, 0x8b, 0xe5, + 0x5d, 0x59, 0x7f, 0xa4, 0x0b, 0x1c, 0xed, 0xe2, 0xb4, 0xd0, 0xa8, 0x9b, 0xf6, 0x80, 0xd4, 0x32, 0x98, 0xaa, 0x02, + 0x74, 0x10, 0xd2, 0x97, 0x02, 0x80, 0x34, 0xb0, 0xdf, 0x91, 0x62, 0x86, 0x25, 0x2e, 0x58, 0x88, 0x45, 0xf8, 0x3a, + 0x98, 0x83, 0xf9, 0xbc, 0x8b, 0xf2, 0x83, 0xd2, 0x9e, 0x00, 0x69, 0x7c, 0x6d, 0x6e, 0x7b, 0xb1, 0xfb, 0xab, 0x72, + 0x2d, 0xd1, 0x30, 0x80, 0xcc, 0x85, 0x43, 0x88, 0x8a, 0x04, 0x5a, 0x65, 0x73, 0xd3, 0x28, 0x65, 0xae, 0x2a, 0x67, + 0x13, 0x03, 0xc3, 0xe6, 0x9a, 0x8b, 0x50, 0xdb, 0x42, 0x5a, 0x00, 0x93, 0xe5, 0xdb, 0x0f, 0xbf, 0x2d, 0x58, 0x62, + 0x75, 0x3f, 0xba, 0xb8, 0xe4, 0xb8, 0x7f, 0x2d, 0xbc, 0x3b, 0x53, 0x3a, 0xff, 0xc8, 0x5f, 0xfc, 0xa1, 0x91, 0xa1, + 0x77, 0x51, 0xe2, 0xd0, 0x71, 0x6d, 0x71, 0xcf, 0xd8, 0xab, 0xf4, 0x22, 0x88, 0xf6, 0x2f, 0xeb, 0xdf, 0xed, 0x5d, + 0x16, 0x2e, 0x8c, 0xbd, 0x0b, 0xc3, 0x8d, 0x43, 0x9a, 0x0b, 0xd9, 0xe0, 0x07, 0x85, 0xa1, 0xa8, 0x5a, 0x1d, 0xeb, + 0x58, 0x8b, 0xa8, 0xfc, 0x8b, 0xd5, 0x60, 0x78, 0x72, 0x76, 0xb7, 0x08, 0xb5, 0x1b, 0x96, 0x40, 0x68, 0x9f, 0x81, + 0xee, 0xda, 0x8e, 0xae, 0xa1, 0x0d, 0x6d, 0x10, 0xcd, 0x06, 0xfa, 0x2f, 0x17, 0x6f, 0xac, 0xae, 0x7e, 0x06, 0x22, + 0xda, 0x9b, 0x19, 0x5e, 0x7b, 0xe7, 0xfe, 0x3d, 0x4b, 0xae, 0x3d, 0x5d, 0xc3, 0x08, 0x3e, 0x74, 0xe1, 0x61, 0x9a, + 0xe6, 0xe9, 0x7b, 0x04, 0x8a, 0xd0, 0x44, 0xac, 0x37, 0x1d, 0x50, 0x8e, 0xeb, 0x75, 0x35, 0xd7, 0x3b, 0xb4, 0x8f, + 0xba, 0xfa, 0xe9, 0x37, 0x9a, 0x76, 0x32, 0x61, 0xd3, 0xf4, 0x14, 0x9f, 0x68, 0x27, 0x78, 0x47, 0xd0, 0x6f, 0x4d, + 0xb3, 0xc7, 0x61, 0x6a, 0xb9, 0xda, 0x9a, 0x7f, 0x6a, 0xda, 0x34, 0x08, 0xc3, 0x9e, 0xf6, 0x78, 0xea, 0x4d, 0x0f, + 0xa7, 0x2f, 0xfa, 0x3c, 0x39, 0xff, 0xa6, 0x54, 0xdc, 0xa4, 0x7f, 0x3d, 0xa5, 0x5a, 0x9a, 0x25, 0xf1, 0x27, 0xc6, + 0xd5, 0x4e, 0x34, 0xf9, 0x78, 0xac, 0x56, 0xf5, 0xea, 0x3d, 0xb9, 0xdd, 0xd1, 0x78, 0xea, 0x15, 0xc5, 0x71, 0x8c, + 0x07, 0x72, 0x90, 0x27, 0x07, 0x62, 0xe8, 0x27, 0x2a, 0x98, 0x5c, 0xab, 0x09, 0x50, 0xae, 0xce, 0xe7, 0x38, 0x13, + 0xf3, 0x3b, 0x01, 0x3f, 0x8c, 0xd2, 0x5c, 0x17, 0x46, 0xa0, 0x6b, 0x93, 0x81, 0xfe, 0xa3, 0xeb, 0x75, 0x4d, 0xd7, + 0x3d, 0xb2, 0x8f, 0xba, 0x63, 0xc7, 0x3c, 0xb4, 0x0f, 0xad, 0xb6, 0x7d, 0x64, 0x76, 0xad, 0xae, 0xd9, 0xfd, 0x5b, + 0x77, 0x6c, 0x1d, 0xda, 0x87, 0xa6, 0x63, 0x75, 0x21, 0xd1, 0xea, 0x5a, 0xdd, 0x1b, 0xeb, 0xb0, 0x3b, 0x76, 0x30, + 0xd5, 0xb3, 0x3b, 0x1d, 0xcb, 0x75, 0xec, 0x4e, 0xc7, 0xec, 0xd8, 0x47, 0x47, 0x96, 0xdb, 0xb6, 0x8f, 0x8e, 0xce, + 0x3b, 0x5d, 0xbb, 0x0d, 0x79, 0xed, 0xf6, 0xb8, 0x6d, 0xbb, 0xae, 0x05, 0x7f, 0x99, 0x5d, 0xdb, 0xa3, 0x1f, 0xae, + 0x6b, 0xb7, 0x5d, 0xd3, 0x09, 0x3b, 0x9e, 0x7d, 0xf4, 0xc2, 0xc4, 0xbf, 0xb1, 0x98, 0x89, 0x7f, 0x41, 0x33, 0xe6, + 0x0b, 0xdb, 0x3b, 0xa2, 0x5f, 0xd8, 0xe0, 0xcd, 0x61, 0xf7, 0x57, 0xfd, 0x60, 0xe3, 0x1c, 0x5c, 0x9a, 0x43, 0xb7, + 0x63, 0xb7, 0xdb, 0xe6, 0xa1, 0x6b, 0x77, 0xdb, 0x73, 0xeb, 0xd0, 0xb3, 0x8f, 0x8e, 0xc7, 0x96, 0x6b, 0x1f, 0x1f, + 0x9b, 0x8e, 0xd5, 0xb6, 0x3d, 0xd3, 0xb5, 0x0f, 0xdb, 0xf8, 0xa3, 0x6d, 0x7b, 0x37, 0xc7, 0x2f, 0xec, 0xa3, 0xce, + 0xfc, 0xc8, 0x3e, 0xfc, 0x78, 0xd8, 0xb5, 0xbd, 0xf6, 0xbc, 0x7d, 0x64, 0x7b, 0xc7, 0x37, 0x47, 0xf6, 0xe1, 0xdc, + 0xf2, 0x8e, 0xb6, 0xd6, 0x74, 0x3d, 0x1b, 0x60, 0x84, 0xd9, 0x90, 0x61, 0xf2, 0x0c, 0xf8, 0x33, 0xc7, 0xba, 0xff, + 0xc5, 0x66, 0xd2, 0x7a, 0xd5, 0x17, 0x76, 0xf7, 0x78, 0x4c, 0xc5, 0x21, 0xc1, 0x12, 0x25, 0xa0, 0xca, 0x8d, 0x45, + 0xdd, 0x62, 0x73, 0x96, 0x68, 0x48, 0xfc, 0xe1, 0x9d, 0xdd, 0x58, 0xd0, 0x31, 0xf5, 0xfb, 0x3f, 0x6d, 0x47, 0x2e, + 0x39, 0x44, 0xae, 0xfc, 0x86, 0xff, 0x43, 0x41, 0x5f, 0x86, 0xe6, 0xf9, 0x26, 0x41, 0xc5, 0xfb, 0xdd, 0x82, 0x8a, + 0x37, 0xab, 0x7d, 0x04, 0x15, 0xef, 0xbf, 0xba, 0xa0, 0xe2, 0xbc, 0xaa, 0x27, 0xff, 0xbe, 0xea, 0x9b, 0xfe, 0xd7, + 0x75, 0xf5, 0x19, 0x12, 0xf8, 0xad, 0xcb, 0x8b, 0xd5, 0x15, 0x78, 0x57, 0x7a, 0x1f, 0x0f, 0xde, 0xac, 0x4a, 0x4a, + 0x60, 0x31, 0xe0, 0xd8, 0xf7, 0x31, 0xe1, 0xd8, 0xdf, 0x57, 0x03, 0xd0, 0x3c, 0xe1, 0x74, 0x49, 0x30, 0xb1, 0xe6, + 0x7e, 0x38, 0x95, 0x34, 0x0d, 0xa4, 0xf4, 0x31, 0x19, 0xac, 0x12, 0xe0, 0xba, 0x06, 0x71, 0xd8, 0x6a, 0x11, 0xa5, + 0xbd, 0x23, 0x07, 0x2e, 0x52, 0x6f, 0x9a, 0xe4, 0x95, 0xca, 0xb6, 0xf0, 0x47, 0x75, 0xcd, 0xad, 0x26, 0x36, 0xe6, + 0xa3, 0x52, 0x60, 0x73, 0xeb, 0x6e, 0xbd, 0x5d, 0x0d, 0xb4, 0x6d, 0x84, 0xd2, 0x24, 0x90, 0x73, 0x4d, 0xf9, 0x65, + 0xd5, 0xbc, 0x8a, 0x32, 0xe6, 0xe6, 0x91, 0xc2, 0x48, 0xaa, 0xf5, 0xdd, 0xb2, 0x6a, 0xdf, 0xae, 0x69, 0x36, 0x74, + 0x5f, 0xaa, 0xbe, 0x45, 0xaf, 0x50, 0x36, 0x5c, 0x05, 0x55, 0x25, 0xb2, 0x5a, 0x23, 0x40, 0x0a, 0xea, 0xbe, 0x50, + 0x3e, 0x2c, 0x48, 0x4b, 0x47, 0x43, 0x7a, 0xc7, 0x51, 0xf2, 0x4a, 0x6d, 0xaa, 0x0a, 0x8b, 0xcf, 0xd6, 0x48, 0x71, + 0x07, 0xbf, 0x03, 0xe9, 0xc8, 0x29, 0x9e, 0x51, 0xac, 0xc2, 0x79, 0xad, 0xb4, 0x4b, 0x8f, 0x99, 0x7c, 0xee, 0xae, + 0xeb, 0xc4, 0xe3, 0x46, 0x55, 0x65, 0x97, 0x2d, 0x04, 0x15, 0x84, 0xdd, 0x93, 0x62, 0x70, 0x4e, 0xca, 0xdb, 0xa8, + 0xfb, 0xbc, 0xad, 0x31, 0x51, 0xee, 0x31, 0x6c, 0x62, 0x93, 0x7f, 0xa8, 0x7e, 0x01, 0xd6, 0x53, 0x88, 0x82, 0xdd, + 0x43, 0x32, 0x4d, 0xa1, 0x51, 0x3d, 0xd4, 0x62, 0xee, 0x6f, 0x51, 0xb0, 0x51, 0x1b, 0xe6, 0x8d, 0xa0, 0x36, 0xf4, + 0x36, 0x9d, 0x1c, 0x69, 0x3c, 0xb2, 0x2e, 0x89, 0xa8, 0xdd, 0xce, 0xb1, 0xe9, 0x1e, 0x99, 0xf6, 0x71, 0xc7, 0xc8, + 0xc5, 0x81, 0x53, 0x9b, 0x2c, 0x01, 0x04, 0x94, 0xa2, 0xe5, 0x30, 0x83, 0x28, 0xc8, 0x02, 0x3f, 0xcc, 0x81, 0x3e, + 0x2e, 0xbf, 0x2a, 0xfe, 0xb9, 0x4a, 0x33, 0x98, 0xa3, 0x20, 0x7a, 0x51, 0x21, 0xdc, 0x1a, 0xb1, 0xec, 0x96, 0xb1, + 0x68, 0x83, 0xb0, 0xbc, 0xaa, 0x5f, 0xfe, 0xe7, 0x69, 0xdb, 0xe6, 0xa4, 0xc9, 0x32, 0xca, 0x22, 0xbe, 0x3f, 0x84, + 0x32, 0x74, 0x3e, 0x34, 0x7f, 0xda, 0x84, 0x70, 0xff, 0xb9, 0x1b, 0xe1, 0x66, 0x6c, 0x1f, 0x84, 0xfb, 0xcf, 0xaf, + 0x8e, 0x70, 0x7f, 0x52, 0x11, 0x6e, 0xc9, 0x16, 0xa8, 0xe0, 0x3a, 0x7f, 0xc0, 0xef, 0x16, 0x38, 0x75, 0x7e, 0xae, + 0x1f, 0x10, 0x01, 0xaf, 0x2b, 0xc1, 0x76, 0x3f, 0x96, 0xa2, 0x07, 0x21, 0x53, 0x04, 0x9d, 0xd0, 0x52, 0xa4, 0x12, + 0x08, 0x44, 0x2b, 0x43, 0xaa, 0x43, 0x9b, 0x6f, 0xa3, 0x2c, 0xb4, 0xdf, 0xf3, 0x87, 0x1f, 0x08, 0x79, 0xde, 0xc4, + 0xc9, 0xc2, 0x47, 0x07, 0x7c, 0x3a, 0x46, 0x1d, 0x84, 0x0f, 0x07, 0xec, 0xcf, 0xc6, 0x71, 0x34, 0x91, 0x92, 0x0a, + 0x36, 0xb8, 0x24, 0x8a, 0x5b, 0xbf, 0x67, 0x7e, 0xa2, 0x9b, 0x94, 0x0d, 0x8b, 0xfb, 0xac, 0xed, 0x3c, 0xf3, 0x0e, + 0x9f, 0x1d, 0x39, 0xf0, 0xbf, 0xcb, 0xda, 0xb9, 0xc9, 0x0b, 0x2e, 0xe2, 0x08, 0x02, 0x9f, 0x88, 0x92, 0x9b, 0x8a, + 0xdd, 0x32, 0xf6, 0xa9, 0x28, 0x75, 0xdc, 0x5c, 0x68, 0xe2, 0xdf, 0x17, 0x65, 0x1a, 0x4b, 0xcc, 0xe3, 0x95, 0x32, + 0xac, 0x86, 0xd1, 0x04, 0xd1, 0x0a, 0x78, 0x6f, 0x4a, 0x09, 0x35, 0x9b, 0x4f, 0xb7, 0x98, 0x17, 0x6b, 0xe7, 0x57, + 0x45, 0x74, 0x25, 0x11, 0xe5, 0x65, 0x27, 0x04, 0xb9, 0xd8, 0xc2, 0x41, 0xdf, 0xec, 0x18, 0x5f, 0x48, 0x83, 0xd8, + 0x86, 0x62, 0x81, 0x7c, 0x5a, 0xa0, 0x2c, 0x59, 0x45, 0xe3, 0x16, 0xfe, 0xf4, 0x47, 0x69, 0x2b, 0x38, 0x00, 0xef, + 0xac, 0xd8, 0xb1, 0x81, 0xab, 0xe6, 0x9f, 0x3a, 0x45, 0x28, 0x8a, 0x54, 0xac, 0x8a, 0xff, 0x2c, 0x33, 0x13, 0x0a, + 0x60, 0x8b, 0x4b, 0x6b, 0x0d, 0xfc, 0x67, 0xb2, 0xe2, 0xb3, 0xcc, 0x84, 0x20, 0xb2, 0xb0, 0xdc, 0x4f, 0x9f, 0x52, + 0x29, 0x08, 0xeb, 0x48, 0xd3, 0x3a, 0x1b, 0x17, 0xee, 0xdd, 0x34, 0x7f, 0x16, 0x93, 0x87, 0xb7, 0xde, 0xd8, 0x8c, + 0x9f, 0x3f, 0x3f, 0x1d, 0xb8, 0x06, 0x0f, 0x4a, 0x5a, 0x8a, 0xa0, 0x75, 0xbe, 0x9f, 0xf2, 0x81, 0xd1, 0x68, 0x16, + 0xb7, 0x84, 0x37, 0x93, 0x23, 0x54, 0x94, 0x39, 0xf6, 0x82, 0x88, 0x16, 0x24, 0x64, 0xf4, 0x85, 0x12, 0x80, 0x28, + 0x23, 0x5f, 0x5d, 0x6d, 0xdb, 0xb1, 0x1d, 0x5d, 0x56, 0x9c, 0x06, 0xb3, 0xc1, 0x3a, 0xce, 0x7c, 0x88, 0x0d, 0x14, + 0xc6, 0x33, 0xb0, 0xad, 0xc9, 0x82, 0x2c, 0x84, 0x40, 0x33, 0x60, 0x64, 0xb3, 0xa0, 0x77, 0x79, 0xce, 0x35, 0x9e, + 0xfd, 0xe4, 0x13, 0x06, 0x1b, 0x14, 0x66, 0x75, 0xe8, 0x71, 0xe8, 0x47, 0xb8, 0x0c, 0x5b, 0x7a, 0x0b, 0x42, 0x5d, + 0xb2, 0x24, 0xb5, 0x54, 0x0b, 0x82, 0x9e, 0x06, 0x75, 0x20, 0x0c, 0x3d, 0x36, 0x30, 0x4d, 0xfc, 0x05, 0xf8, 0x64, + 0x5f, 0xe7, 0x26, 0xc7, 0xb4, 0x3a, 0x47, 0xb5, 0x9a, 0xfb, 0xe2, 0xc8, 0xd4, 0x3c, 0xd7, 0xd4, 0x1c, 0x40, 0xb7, + 0x7a, 0x6e, 0xae, 0xf3, 0xab, 0xfe, 0x2e, 0x21, 0x28, 0xe1, 0x97, 0xc7, 0x34, 0x0f, 0x12, 0x7f, 0x72, 0xf6, 0x72, + 0x46, 0x0e, 0x24, 0x5b, 0x8a, 0xb7, 0xf4, 0x80, 0x04, 0x21, 0x17, 0xec, 0x2e, 0x33, 0x30, 0x10, 0x0b, 0x2f, 0x12, + 0x18, 0x6b, 0x34, 0xfe, 0x0b, 0x22, 0x2d, 0xf8, 0xfc, 0xb9, 0x15, 0x80, 0x81, 0xc3, 0x40, 0x81, 0x0f, 0x7c, 0x1b, + 0x25, 0x80, 0x05, 0x85, 0xe8, 0x0e, 0x81, 0x05, 0xd6, 0x47, 0xf0, 0x6f, 0x91, 0x2c, 0x7e, 0x70, 0xd1, 0xa9, 0x1d, + 0xfa, 0xd1, 0x0c, 0x50, 0x9a, 0x1f, 0xcd, 0x6a, 0x2a, 0x1a, 0x64, 0xbf, 0x58, 0x49, 0x2d, 0x9a, 0x2a, 0xd4, 0x27, + 0xd2, 0xef, 0xef, 0x2f, 0x28, 0xd0, 0x14, 0x04, 0x35, 0xf7, 0x27, 0x68, 0x6c, 0x57, 0x48, 0x77, 0x9e, 0x0f, 0xbe, + 0x3d, 0x59, 0xb0, 0xcc, 0x27, 0xd6, 0x30, 0x3c, 0x7e, 0x81, 0x1c, 0xd0, 0xc6, 0x22, 0x48, 0x2c, 0x05, 0x93, 0x9f, + 0xb0, 0x9b, 0x60, 0xcc, 0xdf, 0xa5, 0xa6, 0xc6, 0xef, 0x29, 0x0b, 0xb5, 0xc0, 0x06, 0xae, 0x49, 0x4a, 0xc8, 0x63, + 0x1f, 0xdd, 0x4c, 0x0e, 0xa2, 0x58, 0x3f, 0xfd, 0x56, 0xda, 0x6b, 0x6d, 0x5a, 0x04, 0x88, 0xf6, 0x78, 0x99, 0xb0, + 0xf0, 0x5f, 0x83, 0x6f, 0xe1, 0xe2, 0xfe, 0xf6, 0x4a, 0x37, 0xfa, 0x99, 0x3d, 0x4f, 0xd8, 0x74, 0xf0, 0x6d, 0x43, + 0xd4, 0x43, 0x7c, 0xde, 0xd3, 0x58, 0xf4, 0xb6, 0x57, 0x38, 0x07, 0x6a, 0xef, 0xf5, 0xa8, 0x3f, 0xe5, 0xaf, 0x75, + 0x78, 0x01, 0xae, 0x4b, 0x6f, 0x6c, 0xb7, 0x8f, 0xef, 0xe7, 0x51, 0xe8, 0x8f, 0x3f, 0xf5, 0x29, 0xa7, 0xf4, 0x61, + 0xc1, 0x6d, 0x3d, 0xf6, 0x97, 0x3d, 0xbc, 0x5e, 0xd5, 0x44, 0x30, 0xd7, 0xa4, 0x54, 0x49, 0xd9, 0x35, 0xee, 0x65, + 0xdc, 0xca, 0x6b, 0xec, 0x19, 0xbb, 0xba, 0x9d, 0x07, 0x19, 0x13, 0x5d, 0xe1, 0x47, 0x9e, 0x8b, 0x87, 0x3a, 0x3d, + 0x51, 0xf1, 0x61, 0x6d, 0xb7, 0x35, 0xb7, 0xfb, 0xb7, 0xce, 0x8d, 0xeb, 0xcc, 0x3d, 0xd7, 0xee, 0x7e, 0x74, 0xbb, + 0xf3, 0xb6, 0x7d, 0x1c, 0x5a, 0x6d, 0xfb, 0x18, 0xfe, 0x7c, 0x3c, 0xb6, 0xbb, 0x73, 0xcb, 0xb3, 0x0f, 0x3f, 0xba, + 0x5e, 0x68, 0x75, 0xed, 0x63, 0xf8, 0x73, 0x4e, 0xb5, 0xe0, 0x01, 0x44, 0xef, 0x9d, 0x6f, 0x4b, 0x58, 0x40, 0xf9, + 0x2d, 0xe5, 0x34, 0x66, 0xe9, 0x7a, 0x6b, 0x90, 0xf5, 0x00, 0xca, 0xd0, 0x4d, 0xe1, 0x04, 0x32, 0xea, 0xb7, 0x20, + 0x0c, 0x3b, 0x06, 0x10, 0x10, 0x2a, 0x2f, 0xc2, 0x2e, 0x55, 0xb8, 0xd2, 0x6f, 0x3c, 0x46, 0xbc, 0x4e, 0xb3, 0xc3, + 0x75, 0x11, 0x99, 0x8a, 0x84, 0x43, 0xbf, 0x2c, 0xd1, 0x89, 0x91, 0x70, 0x11, 0xaf, 0x60, 0xa5, 0x22, 0x3a, 0x62, + 0xbe, 0x7b, 0xe0, 0x68, 0x99, 0xcb, 0x64, 0x74, 0x9e, 0xaf, 0xda, 0x36, 0x17, 0x18, 0xc9, 0xd6, 0xff, 0x68, 0x3b, + 0x18, 0x94, 0x96, 0xda, 0x11, 0xde, 0x5c, 0x27, 0x41, 0x22, 0x87, 0xa7, 0xa0, 0x68, 0xb7, 0xd9, 0x53, 0xbd, 0x01, + 0x61, 0x4c, 0xde, 0x02, 0x95, 0x7c, 0xe3, 0x87, 0x8a, 0x72, 0x8b, 0x52, 0xf3, 0x91, 0xc4, 0xfc, 0x4f, 0x9f, 0x16, + 0x83, 0xb3, 0x2a, 0xe3, 0x3e, 0x71, 0x3b, 0x70, 0xed, 0x76, 0x58, 0x7b, 0xab, 0x9e, 0xd5, 0x6e, 0x77, 0xc0, 0x85, + 0xbb, 0x50, 0xa1, 0x4b, 0x21, 0xa4, 0xb8, 0x1b, 0x95, 0xbd, 0x6a, 0x32, 0x5c, 0x70, 0xa4, 0x5c, 0x79, 0xea, 0xe8, + 0x46, 0x3f, 0x12, 0x22, 0xc9, 0x68, 0x8b, 0x0b, 0x64, 0xfe, 0x16, 0xd3, 0x01, 0x34, 0x5b, 0xe6, 0xb1, 0xc3, 0x68, + 0xf4, 0x7f, 0x3d, 0x09, 0x34, 0xe0, 0x02, 0x19, 0x6a, 0xe5, 0xb4, 0x96, 0x0c, 0x7a, 0xe4, 0xbd, 0x4a, 0x17, 0x2a, + 0x4b, 0xcf, 0x74, 0x48, 0x82, 0xf8, 0x56, 0x18, 0xd2, 0x4e, 0x2a, 0x90, 0xc9, 0xdb, 0xa2, 0x48, 0x30, 0x03, 0xf0, + 0x01, 0xde, 0x12, 0xc6, 0x64, 0xc6, 0xd3, 0xa7, 0x1b, 0x2f, 0x21, 0x12, 0xd8, 0xab, 0x91, 0x3d, 0x75, 0x15, 0xbf, + 0xe9, 0x2a, 0x8a, 0x91, 0xed, 0x22, 0xd6, 0x10, 0x7a, 0x6f, 0xb4, 0xf7, 0xf0, 0xe7, 0x88, 0xf9, 0x99, 0xcd, 0x25, + 0x4d, 0x2d, 0xe5, 0x72, 0x37, 0x5d, 0xd6, 0x06, 0x8d, 0x37, 0xee, 0xeb, 0x8c, 0xfb, 0x12, 0x7c, 0xb2, 0xfe, 0xb8, + 0xe2, 0x96, 0xde, 0xd0, 0xc6, 0x67, 0xa7, 0x70, 0x4f, 0xf3, 0x2e, 0xf3, 0xc9, 0x87, 0x89, 0x7a, 0xe5, 0xc6, 0x99, + 0x2f, 0xe2, 0xc8, 0x00, 0x5d, 0xde, 0x6f, 0x14, 0xc9, 0x2a, 0xd6, 0xe0, 0xa7, 0xef, 0x2e, 0xbe, 0xd3, 0xf8, 0xfe, + 0x27, 0x09, 0x22, 0x3e, 0x64, 0x28, 0xea, 0xc1, 0x80, 0xa2, 0x1e, 0x68, 0x3c, 0x8c, 0x08, 0xc4, 0x0e, 0xc8, 0x0f, + 0x08, 0x82, 0xc8, 0x80, 0x26, 0xb9, 0xea, 0x62, 0x15, 0x66, 0xc1, 0xd2, 0x4f, 0xb2, 0x03, 0xa8, 0x6a, 0x01, 0x92, + 0xd3, 0x37, 0xd9, 0x88, 0x93, 0x68, 0x56, 0xb8, 0xd8, 0xcb, 0x22, 0x21, 0x9b, 0x9d, 0x06, 0xa1, 0x14, 0xcd, 0x8a, + 0x0e, 0xfc, 0xf1, 0x98, 0x2d, 0xb3, 0x81, 0xee, 0x2f, 0x21, 0xfa, 0x05, 0xfa, 0xb3, 0x3e, 0x88, 0xc7, 0x19, 0xcb, + 0xac, 0x34, 0x4b, 0x98, 0xbf, 0xd0, 0xa5, 0x2b, 0xd7, 0x7a, 0x7b, 0xe9, 0x6a, 0xb4, 0x08, 0x32, 0xe9, 0x0b, 0x91, + 0x26, 0x08, 0x42, 0x52, 0x18, 0xe2, 0xe9, 0x30, 0xe7, 0x20, 0x3c, 0x8f, 0x67, 0x95, 0x1d, 0x55, 0x50, 0x2e, 0x67, + 0xe8, 0x69, 0x97, 0x47, 0x3c, 0x98, 0xa0, 0xcd, 0xd3, 0x35, 0xb7, 0x6b, 0x97, 0x2e, 0x1b, 0xf5, 0xd3, 0x13, 0xfe, + 0xbc, 0xd5, 0xd0, 0x15, 0x83, 0xde, 0x71, 0xc0, 0x97, 0xf0, 0x26, 0x8b, 0xf7, 0x03, 0x5e, 0x18, 0xae, 0x26, 0x6a, + 0x19, 0xfd, 0xbc, 0xd3, 0x58, 0x2e, 0x80, 0x10, 0x2a, 0x09, 0xd1, 0xe7, 0xee, 0xa9, 0x34, 0xb1, 0xc2, 0x51, 0x21, + 0xad, 0xf4, 0xf9, 0xf3, 0xcb, 0xe1, 0x7f, 0xfe, 0x0d, 0xce, 0xe8, 0xe7, 0xae, 0xb0, 0x33, 0xbf, 0x54, 0x4b, 0x71, + 0xea, 0xd3, 0x1c, 0xa2, 0x02, 0x05, 0x9b, 0x08, 0xc7, 0x2b, 0x62, 0x6b, 0xe5, 0xc3, 0x2b, 0xe1, 0x4c, 0x0b, 0x02, + 0x4e, 0x18, 0xc2, 0x1a, 0x7e, 0x08, 0xcb, 0x3b, 0x14, 0x4e, 0x18, 0xb4, 0xdf, 0xee, 0xbe, 0x3f, 0x06, 0x67, 0xcb, + 0xb5, 0x38, 0x10, 0xca, 0x00, 0x71, 0x0f, 0x9d, 0x9e, 0xf8, 0x1a, 0x12, 0x2d, 0x48, 0x7e, 0xa4, 0xbd, 0x03, 0x98, + 0xe6, 0x3c, 0x5e, 0x30, 0x3b, 0x88, 0x0f, 0x6e, 0xd9, 0xc8, 0xf2, 0x97, 0x01, 0xc9, 0xea, 0x91, 0xef, 0xa6, 0x11, + 0xe5, 0x27, 0x45, 0xe0, 0x44, 0x5f, 0xe7, 0x05, 0x28, 0xe3, 0x02, 0x50, 0xf0, 0xd3, 0x3f, 0x2d, 0xfb, 0x67, 0xb4, + 0x45, 0x84, 0x80, 0x32, 0x96, 0x3f, 0x23, 0x37, 0x8b, 0xc2, 0xa3, 0x62, 0xf1, 0x61, 0xc5, 0xd3, 0xa9, 0xea, 0x53, + 0xd1, 0x2e, 0xf7, 0x2f, 0xa1, 0x52, 0xec, 0xd9, 0x78, 0x49, 0x3d, 0xd5, 0xbb, 0x90, 0x3f, 0x21, 0x3a, 0x32, 0x77, + 0xbf, 0x09, 0xe7, 0xb9, 0xe6, 0x9b, 0x51, 0x82, 0xe4, 0x31, 0x15, 0xe2, 0x88, 0xa2, 0xea, 0x09, 0x7c, 0x03, 0x69, + 0xf2, 0x68, 0x30, 0x20, 0x3c, 0x56, 0x45, 0x67, 0x00, 0xa5, 0x86, 0x68, 0x09, 0x30, 0xd9, 0x0c, 0x2a, 0x5a, 0x64, + 0x23, 0x87, 0x95, 0xaa, 0xd3, 0xa9, 0x8f, 0xf1, 0xc0, 0x17, 0xfb, 0xab, 0xb4, 0x03, 0x61, 0x67, 0xf1, 0x85, 0x05, + 0x04, 0x2e, 0xda, 0xa9, 0xe0, 0x71, 0xed, 0xaf, 0x84, 0xb2, 0xad, 0xd0, 0xbf, 0x8f, 0x15, 0xdd, 0x05, 0xee, 0xc6, + 0xe0, 0x1c, 0x53, 0x2f, 0x84, 0xf9, 0x60, 0xed, 0x24, 0x49, 0x8f, 0xf3, 0xf5, 0xd3, 0xa4, 0xba, 0x88, 0xdf, 0x75, + 0x98, 0xd4, 0xb2, 0xe5, 0xc9, 0x20, 0x76, 0xcc, 0x8b, 0x83, 0x56, 0xca, 0xc4, 0x73, 0x9f, 0x9f, 0x1c, 0xc0, 0xfc, + 0xc0, 0xf5, 0x42, 0x89, 0x32, 0x0a, 0x0c, 0xf0, 0xef, 0xe0, 0xa7, 0xa4, 0x7f, 0xf1, 0x76, 0x22, 0x88, 0x3a, 0x7c, + 0x39, 0x4a, 0xe7, 0xaf, 0xa5, 0x22, 0x75, 0x62, 0xc5, 0x69, 0xa6, 0xf2, 0x76, 0x47, 0x68, 0xf8, 0x7d, 0x85, 0xe1, + 0x19, 0xf2, 0x7e, 0xc6, 0x84, 0x65, 0xf3, 0x79, 0xb6, 0xc1, 0xf8, 0x79, 0x53, 0x11, 0x22, 0x58, 0xb7, 0x14, 0x28, + 0xf6, 0xf1, 0xb6, 0x52, 0x05, 0x69, 0x24, 0x8b, 0x2d, 0xfd, 0x96, 0xfe, 0x18, 0x77, 0x7c, 0xad, 0x34, 0xa6, 0x42, + 0xb9, 0xf3, 0x6c, 0x00, 0x45, 0x05, 0xb3, 0xdd, 0x5f, 0x2e, 0xa9, 0xb0, 0xd1, 0x3f, 0x39, 0xa0, 0x77, 0xe7, 0x29, + 0xed, 0xb0, 0xd3, 0x13, 0xd0, 0xdf, 0xa4, 0x45, 0xf7, 0x97, 0x4b, 0xbe, 0xa4, 0xf4, 0x8b, 0x72, 0x0e, 0xe6, 0xd9, + 0x22, 0x3c, 0xfd, 0x3f, 0x1d, 0xdb, 0x6f, 0x83, 0x01, 0x5c, 0x03, 0x00}; } // namespace web_server } // namespace esphome From 3cd2fb08431f170d5c853cfaf87476ae0997e24a Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 12 Jun 2024 09:57:36 +1200 Subject: [PATCH 1564/2101] [core] Update Entities (#6885) --- CODEOWNERS | 2 + esphome/components/api/api.proto | 44 +++ esphome/components/api/api_connection.cpp | 45 +++ esphome/components/api/api_connection.h | 6 + esphome/components/api/api_pb2.cpp | 256 ++++++++++++++++++ esphome/components/api/api_pb2.h | 55 ++++ esphome/components/api/api_pb2_service.cpp | 42 +++ esphome/components/api/api_pb2_service.h | 15 + esphome/components/api/api_server.cpp | 7 + 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.cpp | 3 + esphome/components/api/subscribe_state.h | 3 + .../http_request/ota/ota_http_request.cpp | 2 + .../http_request/ota/ota_http_request.h | 1 - .../http_request/update/__init__.py | 44 +++ .../update/http_request_update.cpp | 157 +++++++++++ .../http_request/update/http_request_update.h | 37 +++ esphome/components/mqtt/__init__.py | 1 + esphome/components/mqtt/mqtt_const.h | 2 + esphome/components/mqtt/mqtt_update.cpp | 62 +++++ esphome/components/mqtt/mqtt_update.h | 41 +++ esphome/components/update/__init__.py | 108 ++++++++ esphome/components/update/update_entity.cpp | 12 + esphome/components/update/update_entity.h | 51 ++++ .../components/web_server/list_entities.cpp | 9 + esphome/components/web_server/list_entities.h | 3 + esphome/components/web_server/web_server.cpp | 71 +++++ esphome/components/web_server/web_server.h | 12 +- esphome/const.py | 1 + esphome/core/application.h | 20 ++ esphome/core/component_iterator.cpp | 15 + esphome/core/component_iterator.h | 6 + esphome/core/controller.cpp | 6 + esphome/core/controller.h | 6 + esphome/core/defines.h | 1 + tests/components/http_request/common.yaml | 6 + tests/components/mqtt/common-update.yaml | 13 + tests/components/mqtt/test.esp32-c3-idf.yaml | 1 + tests/components/mqtt/test.esp32-c3.yaml | 4 + tests/components/mqtt/test.esp32-idf.yaml | 1 + tests/components/mqtt/test.esp32.yaml | 4 + tests/components/mqtt/test.esp8266.yaml | 4 + tests/components/update/common.yaml | 1 + tests/components/update/test.esp32-ard.yaml | 1 + tests/components/update/test.esp32-idf.yaml | 1 + tests/components/update/test.esp8266.yaml | 1 + tests/components/update/test.rp2040.yaml | 1 + 49 files changed, 1191 insertions(+), 2 deletions(-) create mode 100644 esphome/components/http_request/update/__init__.py create mode 100644 esphome/components/http_request/update/http_request_update.cpp create mode 100644 esphome/components/http_request/update/http_request_update.h create mode 100644 esphome/components/mqtt/mqtt_update.cpp create mode 100644 esphome/components/mqtt/mqtt_update.h create mode 100644 esphome/components/update/__init__.py create mode 100644 esphome/components/update/update_entity.cpp create mode 100644 esphome/components/update/update_entity.h create mode 100644 tests/components/mqtt/common-update.yaml create mode 100644 tests/components/update/common.yaml create mode 100644 tests/components/update/test.esp32-ard.yaml create mode 100644 tests/components/update/test.esp32-idf.yaml create mode 100644 tests/components/update/test.esp8266.yaml create mode 100644 tests/components/update/test.rp2040.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 90574ca9ba..bbb39c26ad 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -172,6 +172,7 @@ esphome/components/host/time/* @clydebarrow esphome/components/hrxl_maxsonar_wr/* @netmikey esphome/components/hte501/* @Stock-M esphome/components/http_request/ota/* @oarcher +esphome/components/http_request/update/* @jesserockz esphome/components/htu31d/* @betterengineering esphome/components/hydreon_rgxx/* @functionpointer esphome/components/hyt271/* @Philippe12 @@ -410,6 +411,7 @@ esphome/components/uart/button/* @ssieb esphome/components/ufire_ec/* @pvizeli esphome/components/ufire_ise/* @pvizeli esphome/components/ultrasonic/* @OttoWinter +esphome/components/update/* @jesserockz esphome/components/uponor_smatrix/* @kroimon esphome/components/valve/* @esphome/core esphome/components/vbus/* @ssieb diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index 0becec2348..812a1d74ae 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -48,6 +48,7 @@ service APIConnection { rpc date_command (DateCommandRequest) returns (void) {} rpc time_command (TimeCommandRequest) returns (void) {} rpc datetime_command (DateTimeCommandRequest) returns (void) {} + rpc update_command (UpdateCommandRequest) returns (void) {} rpc subscribe_bluetooth_le_advertisements(SubscribeBluetoothLEAdvertisementsRequest) returns (void) {} rpc bluetooth_device_request(BluetoothDeviceRequest) returns (void) {} @@ -1837,3 +1838,46 @@ message DateTimeCommandRequest { fixed32 key = 1; fixed32 epoch_seconds = 2; } + +// ==================== UPDATE ==================== +message ListEntitiesUpdateResponse { + option (id) = 116; + option (source) = SOURCE_SERVER; + option (ifdef) = "USE_UPDATE"; + + string object_id = 1; + fixed32 key = 2; + string name = 3; + string unique_id = 4; + + string icon = 5; + bool disabled_by_default = 6; + EntityCategory entity_category = 7; + string device_class = 8; +} +message UpdateStateResponse { + option (id) = 117; + option (source) = SOURCE_SERVER; + option (ifdef) = "USE_UPDATE"; + option (no_delay) = true; + + fixed32 key = 1; + bool missing_state = 2; + bool in_progress = 3; + bool has_progress = 4; + float progress = 5; + string current_version = 6; + string latest_version = 7; + string title = 8; + string release_summary = 9; + string release_url = 10; +} +message UpdateCommandRequest { + option (id) = 118; + option (source) = SOURCE_CLIENT; + option (ifdef) = "USE_UPDATE"; + option (no_delay) = true; + + fixed32 key = 1; + bool install = 2; +} diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 253f04aa39..2e73a8336e 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1287,6 +1287,51 @@ bool APIConnection::send_event_info(event::Event *event) { } #endif +#ifdef USE_UPDATE +bool APIConnection::send_update_state(update::UpdateEntity *update) { + if (!this->state_subscription_) + return false; + + UpdateStateResponse resp{}; + resp.key = update->get_object_id_hash(); + resp.missing_state = !update->has_state(); + if (update->has_state()) { + resp.in_progress = update->state == update::UpdateState::UPDATE_STATE_INSTALLING; + if (update->update_info.has_progress) { + resp.has_progress = true; + resp.progress = update->update_info.progress; + } + resp.current_version = update->update_info.current_version; + resp.latest_version = update->update_info.latest_version; + resp.title = update->update_info.title; + resp.release_summary = update->update_info.summary; + resp.release_url = update->update_info.release_url; + } + + return this->send_update_state_response(resp); +} +bool APIConnection::send_update_info(update::UpdateEntity *update) { + ListEntitiesUpdateResponse msg; + msg.key = update->get_object_id_hash(); + msg.object_id = update->get_object_id(); + if (update->has_own_name()) + msg.name = update->get_name(); + msg.unique_id = get_default_unique_id("update", update); + msg.icon = update->get_icon(); + msg.disabled_by_default = update->is_disabled_by_default(); + msg.entity_category = static_cast(update->get_entity_category()); + msg.device_class = update->get_device_class(); + return this->send_list_entities_update_response(msg); +} +void APIConnection::update_command(const UpdateCommandRequest &msg) { + update::UpdateEntity *update = App.get_update_by_key(msg.key); + if (update == nullptr) + return; + + update->perform(); +} +#endif + bool APIConnection::send_log_message(int level, const char *tag, const char *line) { if (this->log_subscription_ < level) return false; diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index 293da17fa4..714e806470 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -164,6 +164,12 @@ class APIConnection : public APIServerConnection { bool send_event_info(event::Event *event); #endif +#ifdef USE_UPDATE + bool send_update_state(update::UpdateEntity *update); + bool send_update_info(update::UpdateEntity *update); + void update_command(const UpdateCommandRequest &msg) override; +#endif + void on_disconnect_response(const DisconnectResponse &value) override; void on_ping_response(const PingResponse &value) override { // we initiated ping diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index 9db6482c49..e6e905c6d1 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -8376,6 +8376,262 @@ void DateTimeCommandRequest::dump_to(std::string &out) const { out.append("}"); } #endif +bool ListEntitiesUpdateResponse::decode_varint(uint32_t field_id, ProtoVarInt value) { + switch (field_id) { + case 6: { + this->disabled_by_default = value.as_bool(); + return true; + } + case 7: { + this->entity_category = value.as_enum(); + return true; + } + default: + return false; + } +} +bool ListEntitiesUpdateResponse::decode_length(uint32_t field_id, ProtoLengthDelimited value) { + switch (field_id) { + case 1: { + this->object_id = value.as_string(); + return true; + } + case 3: { + this->name = value.as_string(); + return true; + } + case 4: { + this->unique_id = value.as_string(); + return true; + } + case 5: { + this->icon = value.as_string(); + return true; + } + case 8: { + this->device_class = value.as_string(); + return true; + } + default: + return false; + } +} +bool ListEntitiesUpdateResponse::decode_32bit(uint32_t field_id, Proto32Bit value) { + switch (field_id) { + case 2: { + this->key = value.as_fixed32(); + return true; + } + default: + return false; + } +} +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); + buffer.encode_string(4, this->unique_id); + buffer.encode_string(5, this->icon); + buffer.encode_bool(6, this->disabled_by_default); + buffer.encode_enum(7, this->entity_category); + buffer.encode_string(8, this->device_class); +} +#ifdef HAS_PROTO_MESSAGE_DUMP +void ListEntitiesUpdateResponse::dump_to(std::string &out) const { + __attribute__((unused)) char buffer[64]; + out.append("ListEntitiesUpdateResponse {\n"); + out.append(" object_id: "); + out.append("'").append(this->object_id).append("'"); + out.append("\n"); + + out.append(" key: "); + sprintf(buffer, "%" PRIu32, this->key); + out.append(buffer); + out.append("\n"); + + out.append(" name: "); + out.append("'").append(this->name).append("'"); + out.append("\n"); + + out.append(" unique_id: "); + out.append("'").append(this->unique_id).append("'"); + out.append("\n"); + + out.append(" icon: "); + out.append("'").append(this->icon).append("'"); + out.append("\n"); + + out.append(" disabled_by_default: "); + out.append(YESNO(this->disabled_by_default)); + out.append("\n"); + + out.append(" entity_category: "); + out.append(proto_enum_to_string(this->entity_category)); + out.append("\n"); + + out.append(" device_class: "); + out.append("'").append(this->device_class).append("'"); + out.append("\n"); + out.append("}"); +} +#endif +bool UpdateStateResponse::decode_varint(uint32_t field_id, ProtoVarInt value) { + switch (field_id) { + case 2: { + this->missing_state = value.as_bool(); + return true; + } + case 3: { + this->in_progress = value.as_bool(); + return true; + } + case 4: { + this->has_progress = value.as_bool(); + return true; + } + default: + return false; + } +} +bool UpdateStateResponse::decode_length(uint32_t field_id, ProtoLengthDelimited value) { + switch (field_id) { + case 6: { + this->current_version = value.as_string(); + return true; + } + case 7: { + this->latest_version = value.as_string(); + return true; + } + case 8: { + this->title = value.as_string(); + return true; + } + case 9: { + this->release_summary = value.as_string(); + return true; + } + case 10: { + this->release_url = value.as_string(); + return true; + } + default: + return false; + } +} +bool UpdateStateResponse::decode_32bit(uint32_t field_id, Proto32Bit value) { + switch (field_id) { + case 1: { + this->key = value.as_fixed32(); + return true; + } + case 5: { + this->progress = value.as_float(); + return true; + } + default: + return false; + } +} +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); + 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); +} +#ifdef HAS_PROTO_MESSAGE_DUMP +void UpdateStateResponse::dump_to(std::string &out) const { + __attribute__((unused)) char buffer[64]; + out.append("UpdateStateResponse {\n"); + out.append(" key: "); + sprintf(buffer, "%" PRIu32, this->key); + out.append(buffer); + out.append("\n"); + + out.append(" missing_state: "); + out.append(YESNO(this->missing_state)); + out.append("\n"); + + out.append(" in_progress: "); + out.append(YESNO(this->in_progress)); + out.append("\n"); + + out.append(" has_progress: "); + out.append(YESNO(this->has_progress)); + out.append("\n"); + + out.append(" progress: "); + sprintf(buffer, "%g", this->progress); + out.append(buffer); + out.append("\n"); + + out.append(" current_version: "); + out.append("'").append(this->current_version).append("'"); + out.append("\n"); + + out.append(" latest_version: "); + out.append("'").append(this->latest_version).append("'"); + out.append("\n"); + + out.append(" title: "); + out.append("'").append(this->title).append("'"); + out.append("\n"); + + out.append(" release_summary: "); + out.append("'").append(this->release_summary).append("'"); + out.append("\n"); + + out.append(" release_url: "); + out.append("'").append(this->release_url).append("'"); + out.append("\n"); + out.append("}"); +} +#endif +bool UpdateCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { + switch (field_id) { + case 2: { + this->install = value.as_bool(); + return true; + } + default: + return false; + } +} +bool UpdateCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { + switch (field_id) { + case 1: { + this->key = value.as_fixed32(); + return true; + } + default: + return false; + } +} +void UpdateCommandRequest::encode(ProtoWriteBuffer buffer) const { + buffer.encode_fixed32(1, this->key); + buffer.encode_bool(2, this->install); +} +#ifdef HAS_PROTO_MESSAGE_DUMP +void UpdateCommandRequest::dump_to(std::string &out) const { + __attribute__((unused)) char buffer[64]; + out.append("UpdateCommandRequest {\n"); + out.append(" key: "); + sprintf(buffer, "%" PRIu32, this->key); + out.append(buffer); + out.append("\n"); + + out.append(" install: "); + out.append(YESNO(this->install)); + out.append("\n"); + out.append("}"); +} +#endif } // namespace api } // namespace esphome diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index 54cbd20559..ef051eecf1 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -2130,6 +2130,61 @@ class DateTimeCommandRequest : public ProtoMessage { protected: bool decode_32bit(uint32_t field_id, Proto32Bit value) override; }; +class ListEntitiesUpdateResponse : public ProtoMessage { + public: + std::string object_id{}; + uint32_t key{0}; + std::string name{}; + std::string unique_id{}; + std::string icon{}; + bool disabled_by_default{false}; + enums::EntityCategory entity_category{}; + std::string device_class{}; + void encode(ProtoWriteBuffer buffer) const override; +#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 UpdateStateResponse : public ProtoMessage { + public: + uint32_t key{0}; + bool missing_state{false}; + bool in_progress{false}; + bool has_progress{false}; + float progress{0.0f}; + std::string current_version{}; + std::string latest_version{}; + std::string title{}; + std::string release_summary{}; + std::string release_url{}; + void encode(ProtoWriteBuffer buffer) const override; +#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 UpdateCommandRequest : public ProtoMessage { + public: + uint32_t key{0}; + bool install{false}; + void encode(ProtoWriteBuffer buffer) const override; +#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_varint(uint32_t field_id, ProtoVarInt value) override; +}; } // namespace api } // namespace esphome diff --git a/esphome/components/api/api_pb2_service.cpp b/esphome/components/api/api_pb2_service.cpp index 7c95bb03ad..269a755e9e 100644 --- a/esphome/components/api/api_pb2_service.cpp +++ b/esphome/components/api/api_pb2_service.cpp @@ -611,6 +611,24 @@ bool APIServerConnectionBase::send_date_time_state_response(const DateTimeStateR #endif #ifdef USE_DATETIME_DATETIME #endif +#ifdef USE_UPDATE +bool APIServerConnectionBase::send_list_entities_update_response(const ListEntitiesUpdateResponse &msg) { +#ifdef HAS_PROTO_MESSAGE_DUMP + ESP_LOGVV(TAG, "send_list_entities_update_response: %s", msg.dump().c_str()); +#endif + return this->send_message_(msg, 116); +} +#endif +#ifdef USE_UPDATE +bool APIServerConnectionBase::send_update_state_response(const UpdateStateResponse &msg) { +#ifdef HAS_PROTO_MESSAGE_DUMP + ESP_LOGVV(TAG, "send_update_state_response: %s", msg.dump().c_str()); +#endif + return this->send_message_(msg, 117); +} +#endif +#ifdef USE_UPDATE +#endif bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) { switch (msg_type) { case 1: { @@ -1106,6 +1124,17 @@ bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, ESP_LOGVV(TAG, "on_voice_assistant_timer_event_response: %s", msg.dump().c_str()); #endif this->on_voice_assistant_timer_event_response(msg); +#endif + break; + } + case 118: { +#ifdef USE_UPDATE + 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()); +#endif + this->on_update_command_request(msg); #endif break; } @@ -1434,6 +1463,19 @@ void APIServerConnection::on_date_time_command_request(const DateTimeCommandRequ this->datetime_command(msg); } #endif +#ifdef USE_UPDATE +void APIServerConnection::on_update_command_request(const UpdateCommandRequest &msg) { + if (!this->is_connection_setup()) { + this->on_no_setup_connection(); + return; + } + if (!this->is_authenticated()) { + this->on_unauthenticated_access(); + return; + } + this->update_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 2f8a2b3def..83bfc2ed98 100644 --- a/esphome/components/api/api_pb2_service.h +++ b/esphome/components/api/api_pb2_service.h @@ -306,6 +306,15 @@ class APIServerConnectionBase : public ProtoService { #endif #ifdef USE_DATETIME_DATETIME virtual void on_date_time_command_request(const DateTimeCommandRequest &value){}; +#endif +#ifdef USE_UPDATE + bool send_list_entities_update_response(const ListEntitiesUpdateResponse &msg); +#endif +#ifdef USE_UPDATE + bool send_update_state_response(const UpdateStateResponse &msg); +#endif +#ifdef USE_UPDATE + virtual void on_update_command_request(const UpdateCommandRequest &value){}; #endif protected: bool read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) override; @@ -373,6 +382,9 @@ class APIServerConnection : public APIServerConnectionBase { #ifdef USE_DATETIME_DATETIME virtual void datetime_command(const DateTimeCommandRequest &msg) = 0; #endif +#ifdef USE_UPDATE + virtual void update_command(const UpdateCommandRequest &msg) = 0; +#endif #ifdef USE_BLUETOOTH_PROXY virtual void subscribe_bluetooth_le_advertisements(const SubscribeBluetoothLEAdvertisementsRequest &msg) = 0; #endif @@ -471,6 +483,9 @@ class APIServerConnection : public APIServerConnectionBase { #ifdef USE_DATETIME_DATETIME void on_date_time_command_request(const DateTimeCommandRequest &msg) override; #endif +#ifdef USE_UPDATE + void on_update_command_request(const UpdateCommandRequest &msg) override; +#endif #ifdef USE_BLUETOOTH_PROXY void on_subscribe_bluetooth_le_advertisements_request(const SubscribeBluetoothLEAdvertisementsRequest &msg) override; #endif diff --git a/esphome/components/api/api_server.cpp b/esphome/components/api/api_server.cpp index 0725547771..a61ae89243 100644 --- a/esphome/components/api/api_server.cpp +++ b/esphome/components/api/api_server.cpp @@ -334,6 +334,13 @@ void APIServer::on_event(event::Event *obj, const std::string &event_type) { } #endif +#ifdef USE_UPDATE +void APIServer::on_update(update::UpdateEntity *obj) { + for (auto &c : this->clients_) + c->send_update_state(obj); +} +#endif + float APIServer::get_setup_priority() const { return setup_priority::AFTER_WIFI; } void APIServer::set_port(uint16_t port) { this->port_ = port; } APIServer *global_api_server = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) diff --git a/esphome/components/api/api_server.h b/esphome/components/api/api_server.h index 2e1fbdf67c..43bc8a7348 100644 --- a/esphome/components/api/api_server.h +++ b/esphome/components/api/api_server.h @@ -102,6 +102,9 @@ class APIServer : public Component, public Controller { #ifdef USE_EVENT void on_event(event::Event *obj, const std::string &event_type) override; #endif +#ifdef USE_UPDATE + void on_update(update::UpdateEntity *obj) override; +#endif bool is_connected() const; diff --git a/esphome/components/api/list_entities.cpp b/esphome/components/api/list_entities.cpp index a7dbf9a6e7..5fa360d170 100644 --- a/esphome/components/api/list_entities.cpp +++ b/esphome/components/api/list_entities.cpp @@ -98,6 +98,9 @@ bool ListEntitiesIterator::on_alarm_control_panel(alarm_control_panel::AlarmCont #ifdef USE_EVENT bool ListEntitiesIterator::on_event(event::Event *event) { return this->client_->send_event_info(event); } #endif +#ifdef USE_UPDATE +bool ListEntitiesIterator::on_update(update::UpdateEntity *update) { return this->client_->send_update_info(update); } +#endif } // namespace api } // namespace esphome diff --git a/esphome/components/api/list_entities.h b/esphome/components/api/list_entities.h index c1fd8b82c4..a37586de0f 100644 --- a/esphome/components/api/list_entities.h +++ b/esphome/components/api/list_entities.h @@ -75,6 +75,9 @@ class ListEntitiesIterator : public ComponentIterator { #endif #ifdef USE_EVENT bool on_event(event::Event *event) override; +#endif +#ifdef USE_UPDATE + bool on_update(update::UpdateEntity *update) override; #endif bool on_end() override; diff --git a/esphome/components/api/subscribe_state.cpp b/esphome/components/api/subscribe_state.cpp index 005ab0e6da..5861b1f465 100644 --- a/esphome/components/api/subscribe_state.cpp +++ b/esphome/components/api/subscribe_state.cpp @@ -77,6 +77,9 @@ bool InitialStateIterator::on_alarm_control_panel(alarm_control_panel::AlarmCont return this->client_->send_alarm_control_panel_state(a_alarm_control_panel); } #endif +#ifdef USE_UPDATE +bool InitialStateIterator::on_update(update::UpdateEntity *update) { return this->client_->send_update_state(update); } +#endif InitialStateIterator::InitialStateIterator(APIConnection *client) : client_(client) {} } // namespace api diff --git a/esphome/components/api/subscribe_state.h b/esphome/components/api/subscribe_state.h index 8c725e422e..67c4346210 100644 --- a/esphome/components/api/subscribe_state.h +++ b/esphome/components/api/subscribe_state.h @@ -72,6 +72,9 @@ class InitialStateIterator : public ComponentIterator { #endif #ifdef USE_EVENT bool on_event(event::Event *event) override { return true; }; +#endif +#ifdef USE_UPDATE + bool on_update(update::UpdateEntity *update) override; #endif protected: APIConnection *client_; diff --git a/esphome/components/http_request/ota/ota_http_request.cpp b/esphome/components/http_request/ota/ota_http_request.cpp index a41f552baf..dcc783ea47 100644 --- a/esphome/components/http_request/ota/ota_http_request.cpp +++ b/esphome/components/http_request/ota/ota_http_request.cpp @@ -15,6 +15,8 @@ namespace esphome { namespace http_request { +static const char *const TAG = "http_request.ota"; + void OtaHttpRequestComponent::setup() { #ifdef USE_OTA_STATE_CALLBACK ota::register_ota_platform(this); diff --git a/esphome/components/http_request/ota/ota_http_request.h b/esphome/components/http_request/ota/ota_http_request.h index 91c7085517..6a86b4ab43 100644 --- a/esphome/components/http_request/ota/ota_http_request.h +++ b/esphome/components/http_request/ota/ota_http_request.h @@ -14,7 +14,6 @@ namespace esphome { namespace http_request { -static const char *const TAG = "http_request.ota"; static const uint8_t MD5_SIZE = 32; enum OtaHttpRequestError : uint8_t { diff --git a/esphome/components/http_request/update/__init__.py b/esphome/components/http_request/update/__init__.py new file mode 100644 index 0000000000..356afa1432 --- /dev/null +++ b/esphome/components/http_request/update/__init__.py @@ -0,0 +1,44 @@ +import esphome.config_validation as cv +import esphome.codegen as cg + +from esphome.components import update +from esphome.const import ( + CONF_SOURCE, +) + +from .. import http_request_ns, CONF_HTTP_REQUEST_ID, HttpRequestComponent +from ..ota import OtaHttpRequestComponent + + +AUTO_LOAD = ["json"] +CODEOWNERS = ["@jesserockz"] +DEPENDENCIES = ["ota.http_request"] + +HttpRequestUpdate = http_request_ns.class_( + "HttpRequestUpdate", update.UpdateEntity, cg.PollingComponent +) + +CONF_OTA_ID = "ota_id" + +CONFIG_SCHEMA = update.UPDATE_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(HttpRequestUpdate), + cv.GenerateID(CONF_OTA_ID): cv.use_id(OtaHttpRequestComponent), + cv.GenerateID(CONF_HTTP_REQUEST_ID): cv.use_id(HttpRequestComponent), + cv.Required(CONF_SOURCE): cv.url, + } +).extend(cv.polling_component_schema("6h")) + + +async def to_code(config): + var = await update.new_update(config) + ota_parent = await cg.get_variable(config[CONF_OTA_ID]) + cg.add(var.set_ota_parent(ota_parent)) + request_parent = await cg.get_variable(config[CONF_HTTP_REQUEST_ID]) + cg.add(var.set_request_parent(request_parent)) + + cg.add(var.set_source_url(config[CONF_SOURCE])) + + cg.add_define("USE_OTA_STATE_CALLBACK") + + await cg.register_component(var, config) diff --git a/esphome/components/http_request/update/http_request_update.cpp b/esphome/components/http_request/update/http_request_update.cpp new file mode 100644 index 0000000000..98129e59dc --- /dev/null +++ b/esphome/components/http_request/update/http_request_update.cpp @@ -0,0 +1,157 @@ +#include "http_request_update.h" + +#include "esphome/core/application.h" +#include "esphome/core/version.h" + +#include "esphome/components/json/json_util.h" +#include "esphome/components/network/util.h" + +namespace esphome { +namespace http_request { + +static const char *const TAG = "http_request.update"; + +static const size_t MAX_READ_SIZE = 256; + +void HttpRequestUpdate::setup() { + this->ota_parent_->add_on_state_callback([this](ota::OTAState state, float progress, uint8_t err) { + if (state == ota::OTAState::OTA_IN_PROGRESS) { + this->state_ = update::UPDATE_STATE_INSTALLING; + this->update_info_.has_progress = true; + this->update_info_.progress = progress; + this->publish_state(); + } else if (state == ota::OTAState::OTA_ABORT || state == ota::OTAState::OTA_ERROR) { + this->state_ = update::UPDATE_STATE_AVAILABLE; + this->status_set_error("Failed to install firmware"); + this->publish_state(); + } + }); +} + +void HttpRequestUpdate::update() { + auto container = this->request_parent_->get(this->source_url_); + + if (container == nullptr) { + std::string msg = str_sprintf("Failed to fetch manifest from %s", this->source_url_.c_str()); + this->status_set_error(msg.c_str()); + return; + } + + ExternalRAMAllocator allocator(ExternalRAMAllocator::ALLOW_FAILURE); + uint8_t *data = allocator.allocate(container->content_length); + if (data == nullptr) { + std::string msg = str_sprintf("Failed to allocate %d bytes for manifest", container->content_length); + this->status_set_error(msg.c_str()); + container->end(); + 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); + + App.feed_wdt(); + yield(); + + read_index += read_bytes; + } + + std::string response((char *) data, read_index); + allocator.deallocate(data, container->content_length); + + container->end(); + + bool valid = json::parse_json(response, [this](JsonObject root) -> bool { + if (!root.containsKey("name") || !root.containsKey("version") || !root.containsKey("builds")) { + ESP_LOGE(TAG, "Manifest does not contain required fields"); + return false; + } + this->update_info_.title = root["name"].as(); + this->update_info_.latest_version = root["version"].as(); + + for (auto build : root["builds"].as()) { + if (!build.containsKey("chipFamily")) { + ESP_LOGE(TAG, "Manifest does not contain required fields"); + return false; + } + if (build["chipFamily"] == ESPHOME_VARIANT) { + if (!build.containsKey("ota")) { + ESP_LOGE(TAG, "Manifest does not contain required fields"); + return false; + } + auto ota = build["ota"]; + if (!ota.containsKey("path") || !ota.containsKey("md5")) { + ESP_LOGE(TAG, "Manifest does not contain required fields"); + return false; + } + this->update_info_.firmware_url = ota["path"].as(); + this->update_info_.md5 = ota["md5"].as(); + + if (ota.containsKey("summary")) + this->update_info_.summary = ota["summary"].as(); + if (ota.containsKey("release_url")) + this->update_info_.release_url = ota["release_url"].as(); + + return true; + } + } + return false; + }); + + if (!valid) { + std::string msg = str_sprintf("Failed to parse JSON from %s", this->source_url_.c_str()); + this->status_set_error(msg.c_str()); + return; + } + + // Merge source_url_ and this->update_info_.firmware_url + if (this->update_info_.firmware_url.find("http") == std::string::npos) { + std::string path = this->update_info_.firmware_url; + if (path[0] == '/') { + std::string domain = this->source_url_.substr(0, this->source_url_.find('/', 8)); + this->update_info_.firmware_url = domain + path; + } else { + std::string domain = this->source_url_.substr(0, this->source_url_.rfind('/') + 1); + this->update_info_.firmware_url = domain + path; + } + } + + std::string current_version = this->current_version_; + if (current_version.empty()) { +#ifdef ESPHOME_PROJECT_VERSION + current_version = ESPHOME_PROJECT_VERSION; +#else + current_version = ESPHOME_VERSION; +#endif + } + this->update_info_.current_version = current_version; + + if (this->update_info_.latest_version.empty()) { + this->state_ = update::UPDATE_STATE_NO_UPDATE; + } else if (this->update_info_.latest_version != this->current_version_) { + 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(); +} + +void HttpRequestUpdate::perform() { + if (this->state_ != update::UPDATE_STATE_AVAILABLE) { + return; + } + + this->state_ = update::UPDATE_STATE_INSTALLING; + this->publish_state(); + + this->ota_parent_->set_md5(this->update_info.md5); + this->ota_parent_->set_url(this->update_info.firmware_url); + // Flash in the next loop + this->defer([this]() { this->ota_parent_->flash(); }); +} + +} // namespace http_request +} // namespace esphome diff --git a/esphome/components/http_request/update/http_request_update.h b/esphome/components/http_request/update/http_request_update.h new file mode 100644 index 0000000000..1337822ecc --- /dev/null +++ b/esphome/components/http_request/update/http_request_update.h @@ -0,0 +1,37 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/core/helpers.h" + +#include "esphome/components/http_request/http_request.h" +#include "esphome/components/http_request/ota/ota_http_request.h" +#include "esphome/components/update/update_entity.h" + +namespace esphome { +namespace http_request { + +class HttpRequestUpdate : public update::UpdateEntity, public PollingComponent { + public: + void setup() override; + void update() override; + + void perform() override; + + void set_source_url(const std::string &source_url) { this->source_url_ = source_url; } + + void set_request_parent(HttpRequestComponent *request_parent) { this->request_parent_ = request_parent; } + void set_ota_parent(OtaHttpRequestComponent *ota_parent) { this->ota_parent_ = ota_parent; } + + void set_current_version(const std::string ¤t_version) { this->current_version_ = current_version; } + + float get_setup_priority() const override { return setup_priority::AFTER_WIFI; } + + protected: + HttpRequestComponent *request_parent_; + OtaHttpRequestComponent *ota_parent_; + std::string source_url_; + std::string current_version_{""}; +}; + +} // namespace http_request +} // namespace esphome diff --git a/esphome/components/mqtt/__init__.py b/esphome/components/mqtt/__init__.py index 31cbb2cf97..96a02cb60e 100644 --- a/esphome/components/mqtt/__init__.py +++ b/esphome/components/mqtt/__init__.py @@ -126,6 +126,7 @@ MQTTSelectComponent = mqtt_ns.class_("MQTTSelectComponent", MQTTComponent) MQTTButtonComponent = mqtt_ns.class_("MQTTButtonComponent", MQTTComponent) MQTTLockComponent = mqtt_ns.class_("MQTTLockComponent", MQTTComponent) MQTTEventComponent = mqtt_ns.class_("MQTTEventComponent", MQTTComponent) +MQTTUpdateComponent = mqtt_ns.class_("MQTTUpdateComponent", MQTTComponent) MQTTValveComponent = mqtt_ns.class_("MQTTValveComponent", MQTTComponent) MQTTDiscoveryUniqueIdGenerator = mqtt_ns.enum("MQTTDiscoveryUniqueIdGenerator") diff --git a/esphome/components/mqtt/mqtt_const.h b/esphome/components/mqtt/mqtt_const.h index 66872680bb..0e063c66d2 100644 --- a/esphome/components/mqtt/mqtt_const.h +++ b/esphome/components/mqtt/mqtt_const.h @@ -137,6 +137,7 @@ constexpr const char *const MQTT_PAYLOAD_CLOSE = "pl_cls"; constexpr const char *const MQTT_PAYLOAD_DISARM = "pl_disarm"; constexpr const char *const MQTT_PAYLOAD_HIGH_SPEED = "pl_hi_spd"; constexpr const char *const MQTT_PAYLOAD_HOME = "pl_home"; +constexpr const char *const MQTT_PAYLOAD_INSTALL = "pl_inst"; constexpr const char *const MQTT_PAYLOAD_LOCATE = "pl_loc"; constexpr const char *const MQTT_PAYLOAD_LOCK = "pl_lock"; constexpr const char *const MQTT_PAYLOAD_LOW_SPEED = "pl_lo_spd"; @@ -396,6 +397,7 @@ constexpr const char *const MQTT_PAYLOAD_CLOSE = "payload_close"; constexpr const char *const MQTT_PAYLOAD_DISARM = "payload_disarm"; constexpr const char *const MQTT_PAYLOAD_HIGH_SPEED = "payload_high_speed"; constexpr const char *const MQTT_PAYLOAD_HOME = "payload_home"; +constexpr const char *const MQTT_PAYLOAD_INSTALL = "payload_install"; constexpr const char *const MQTT_PAYLOAD_LOCATE = "payload_locate"; constexpr const char *const MQTT_PAYLOAD_LOCK = "payload_lock"; constexpr const char *const MQTT_PAYLOAD_LOW_SPEED = "payload_low_speed"; diff --git a/esphome/components/mqtt/mqtt_update.cpp b/esphome/components/mqtt/mqtt_update.cpp new file mode 100644 index 0000000000..2ed8faf074 --- /dev/null +++ b/esphome/components/mqtt/mqtt_update.cpp @@ -0,0 +1,62 @@ +#include "mqtt_update.h" +#include "esphome/core/log.h" + +#include "mqtt_const.h" + +#ifdef USE_MQTT +#ifdef USE_UPDATE + +namespace esphome { +namespace mqtt { + +static const char *const TAG = "mqtt.update"; + +using namespace esphome::update; + +MQTTUpdateComponent::MQTTUpdateComponent(UpdateEntity *update) : update_(update) {} + +void MQTTUpdateComponent::setup() { + this->subscribe(this->get_command_topic_(), [this](const std::string &topic, const std::string &payload) { + if (payload == "INSTALL") { + this->update_->perform(); + } else { + ESP_LOGW(TAG, "'%s': Received unknown update payload: %s", this->friendly_name().c_str(), payload.c_str()); + this->status_momentary_warning("state", 5000); + } + }); + + this->update_->add_on_state_callback([this]() { this->defer("send", [this]() { this->publish_state(); }); }); +} + +bool MQTTUpdateComponent::publish_state() { + return this->publish_json(this->get_state_topic_(), [this](JsonObject root) { + root["installed_version"] = this->update_->update_info.current_version; + root["latest_version"] = this->update_->update_info.latest_version; + root["title"] = this->update_->update_info.title; + if (!this->update_->update_info.summary.empty()) + root["release_summary"] = this->update_->update_info.summary; + if (!this->update_->update_info.release_url.empty()) + root["release_url"] = this->update_->update_info.release_url; + }); +} + +void MQTTUpdateComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { + root["schema"] = "json"; + root[MQTT_PAYLOAD_INSTALL] = "INSTALL"; +} + +bool MQTTUpdateComponent::send_initial_state() { return this->publish_state(); } + +void MQTTUpdateComponent::dump_config() { + ESP_LOGCONFIG(TAG, "MQTT Update '%s': ", this->update_->get_name().c_str()); + LOG_MQTT_COMPONENT(true, true); +} + +std::string MQTTUpdateComponent::component_type() const { return "update"; } +const EntityBase *MQTTUpdateComponent::get_entity() const { return this->update_; } + +} // namespace mqtt +} // namespace esphome + +#endif // USE_UPDATE +#endif // USE_MQTT diff --git a/esphome/components/mqtt/mqtt_update.h b/esphome/components/mqtt/mqtt_update.h new file mode 100644 index 0000000000..6fe04c4ea7 --- /dev/null +++ b/esphome/components/mqtt/mqtt_update.h @@ -0,0 +1,41 @@ +#pragma once + +#include "esphome/core/defines.h" + +#ifdef USE_MQTT +#ifdef USE_UPDATE + +#include "esphome/components/update/update_entity.h" +#include "mqtt_component.h" + +namespace esphome { +namespace mqtt { + +class MQTTUpdateComponent : public mqtt::MQTTComponent { + public: + explicit MQTTUpdateComponent(update::UpdateEntity *update); + + // ========== INTERNAL METHODS ========== + // (In most use cases you won't need these) + void setup() override; + void dump_config() override; + + void send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) override; + + bool send_initial_state() override; + + bool publish_state(); + + protected: + /// "update" component type. + std::string component_type() const override; + const EntityBase *get_entity() const override; + + update::UpdateEntity *update_; +}; + +} // namespace mqtt +} // namespace esphome + +#endif // USE_UPDATE +#endif // USE_MQTT diff --git a/esphome/components/update/__init__.py b/esphome/components/update/__init__.py new file mode 100644 index 0000000000..ae3d5062ab --- /dev/null +++ b/esphome/components/update/__init__.py @@ -0,0 +1,108 @@ +from esphome import automation +from esphome.components import mqtt, web_server +import esphome.config_validation as cv +import esphome.codegen as cg +from esphome.const import ( + CONF_DEVICE_CLASS, + CONF_ID, + CONF_MQTT_ID, + CONF_WEB_SERVER_ID, + DEVICE_CLASS_FIRMWARE, +) +from esphome.core import CORE, coroutine_with_priority +from esphome.cpp_helpers import setup_entity + +CODEOWNERS = ["@jesserockz"] +IS_PLATFORM_COMPONENT = True + +update_ns = cg.esphome_ns.namespace("update") +UpdateEntity = update_ns.class_("UpdateEntity", cg.EntityBase) + +UpdateInfo = update_ns.struct("UpdateInfo") + +PerformAction = update_ns.class_("PerformAction", automation.Action) +IsAvailableCondition = update_ns.class_("IsAvailableCondition", automation.Condition) + +DEVICE_CLASSES = [ + DEVICE_CLASS_FIRMWARE, +] + +CONF_ON_UPDATE_AVAILABLE = "on_update_available" + +UPDATE_SCHEMA = ( + cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA) + .extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA) + .extend( + { + cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTUpdateComponent), + cv.Optional(CONF_DEVICE_CLASS): cv.one_of(*DEVICE_CLASSES, lower=True), + cv.Optional(CONF_ON_UPDATE_AVAILABLE): automation.validate_automation( + single=True + ), + } + ) +) + + +async def setup_update_core_(var, config): + await setup_entity(var, config) + + if device_class_config := config.get(CONF_DEVICE_CLASS): + cg.add(var.set_device_class(device_class_config)) + + if on_update_available := config.get(CONF_ON_UPDATE_AVAILABLE): + await automation.build_automation( + var.get_update_available_trigger(), + [(UpdateInfo.operator("ref").operator("const"), "x")], + on_update_available, + ) + + if mqtt_id_config := config.get(CONF_MQTT_ID): + mqtt_ = cg.new_Pvariable(mqtt_id_config, var) + await mqtt.register_mqtt_component(mqtt_, config) + + if web_server_id_config := config.get(CONF_WEB_SERVER_ID): + web_server_ = cg.get_variable(web_server_id_config) + web_server.add_entity_to_sorting_list(web_server_, var, config) + + +async def register_update(var, config): + if not CORE.has_id(config[CONF_ID]): + var = cg.Pvariable(config[CONF_ID], var) + cg.add(cg.App.register_update(var)) + await setup_update_core_(var, config) + + +async def new_update(config): + var = cg.new_Pvariable(config[CONF_ID]) + await register_update(var, config) + return var + + +@coroutine_with_priority(100.0) +async def to_code(config): + cg.add_define("USE_UPDATE") + cg.add_global(update_ns.using) + + +UPDATE_AUTOMATION_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.use_id(UpdateEntity), + } +) + + +@automation.register_action("update.perform", PerformAction, UPDATE_AUTOMATION_SCHEMA) +async def update_perform_action_to_code(config, action_id, template_arg, args): + paren = await cg.get_variable(config[CONF_ID]) + return cg.new_Pvariable(action_id, paren, paren) + + +@automation.register_condition( + "update.is_available", IsAvailableCondition, UPDATE_AUTOMATION_SCHEMA +) +async def update_is_available_condition_to_code( + config, condition_id, template_arg, args +): + paren = await cg.get_variable(config[CONF_ID]) + return cg.new_Pvariable(condition_id, paren, paren) diff --git a/esphome/components/update/update_entity.cpp b/esphome/components/update/update_entity.cpp new file mode 100644 index 0000000000..501cb6635f --- /dev/null +++ b/esphome/components/update/update_entity.cpp @@ -0,0 +1,12 @@ +#include "update_entity.h" + +namespace esphome { +namespace update { + +void UpdateEntity::publish_state() { + this->has_state_ = true; + this->state_callback_.call(); +} + +} // namespace update +} // namespace esphome diff --git a/esphome/components/update/update_entity.h b/esphome/components/update/update_entity.h new file mode 100644 index 0000000000..5984c8e35b --- /dev/null +++ b/esphome/components/update/update_entity.h @@ -0,0 +1,51 @@ +#pragma once + +#include "esphome/core/automation.h" +#include "esphome/core/component.h" +#include "esphome/core/entity_base.h" + +namespace esphome { +namespace update { + +struct UpdateInfo { + std::string latest_version; + std::string current_version; + std::string title; + std::string summary; + std::string release_url; + std::string firmware_url; + std::string md5; + bool has_progress{false}; + float progress; +}; + +enum UpdateState : uint8_t { + UPDATE_STATE_UNKNOWN, + UPDATE_STATE_NO_UPDATE, + UPDATE_STATE_AVAILABLE, + UPDATE_STATE_INSTALLING, +}; + +class UpdateEntity : public EntityBase, public EntityBase_DeviceClass { + public: + bool has_state() const { return this->has_state_; } + + void publish_state(); + + virtual void perform() = 0; + + const UpdateInfo &update_info = update_info_; + const UpdateState &state = state_; + + void add_on_state_callback(std::function &&callback) { this->state_callback_.add(std::move(callback)); } + + protected: + UpdateState state_{UPDATE_STATE_UNKNOWN}; + UpdateInfo update_info_; + bool has_state_{false}; + + CallbackManager state_callback_{}; +}; + +} // namespace update +} // namespace esphome diff --git a/esphome/components/web_server/list_entities.cpp b/esphome/components/web_server/list_entities.cpp index 42af72e872..332f358352 100644 --- a/esphome/components/web_server/list_entities.cpp +++ b/esphome/components/web_server/list_entities.cpp @@ -177,5 +177,14 @@ bool ListEntitiesIterator::on_event(event::Event *event) { } #endif +#ifdef USE_UPDATE +bool ListEntitiesIterator::on_update(update::UpdateEntity *update) { + if (this->web_server_->events_.count() == 0) + return true; + this->web_server_->events_.send(this->web_server_->update_json(update, DETAIL_ALL).c_str(), "state"); + return true; +} +#endif + } // namespace web_server } // namespace esphome diff --git a/esphome/components/web_server/list_entities.h b/esphome/components/web_server/list_entities.h index 47d427d9b5..5ff6ec0412 100644 --- a/esphome/components/web_server/list_entities.h +++ b/esphome/components/web_server/list_entities.h @@ -68,6 +68,9 @@ class ListEntitiesIterator : public ComponentIterator { #ifdef USE_EVENT bool on_event(event::Event *event) override; #endif +#ifdef USE_UPDATE + bool on_update(update::UpdateEntity *update) override; +#endif protected: WebServer *web_server_; diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index 5bb36f9600..9a1641e86f 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -1501,6 +1501,65 @@ std::string WebServer::event_json(event::Event *obj, const std::string &event_ty } #endif +#ifdef USE_UPDATE +void WebServer::on_update(update::UpdateEntity *obj) { + if (this->events_.count() == 0) + return; + this->events_.send(this->update_json(obj, DETAIL_STATE).c_str(), "state"); +} +void WebServer::handle_update_request(AsyncWebServerRequest *request, const UrlMatch &match) { + for (update::UpdateEntity *obj : App.get_updates()) { + if (obj->get_object_id() != match.id) + continue; + + if (request->method() == HTTP_GET && match.method.empty()) { + std::string data = this->update_json(obj, DETAIL_STATE); + request->send(200, "application/json", data.c_str()); + return; + } + + if (match.method != "install") { + request->send(404); + return; + } + + this->schedule_([obj]() mutable { obj->perform(); }); + request->send(200); + return; + } + request->send(404); +} +std::string WebServer::update_json(update::UpdateEntity *obj, JsonDetail start_config) { + return json::build_json([this, obj, start_config](JsonObject root) { + set_json_id(root, obj, "update-" + obj->get_object_id(), start_config); + root["value"] = obj->update_info.latest_version; + switch (obj->state) { + case update::UPDATE_STATE_NO_UPDATE: + root["state"] = "NO UPDATE"; + break; + case update::UPDATE_STATE_AVAILABLE: + root["state"] = "UPDATE AVAILABLE"; + break; + case update::UPDATE_STATE_INSTALLING: + root["state"] = "INSTALLING"; + break; + default: + root["state"] = "UNKNOWN"; + break; + } + if (start_config == DETAIL_ALL) { + root["current_version"] = obj->update_info.current_version; + root["title"] = obj->update_info.title; + root["summary"] = obj->update_info.summary; + root["release_url"] = obj->update_info.release_url; + if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) { + root["sorting_weight"] = this->sorting_entitys_[obj].weight; + } + } + }); +} +#endif + bool WebServer::canHandle(AsyncWebServerRequest *request) { if (request->url() == "/") return true; @@ -1620,6 +1679,11 @@ bool WebServer::canHandle(AsyncWebServerRequest *request) { return true; #endif +#ifdef USE_UPDATE + if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain == "update") + return true; +#endif + return false; } void WebServer::handleRequest(AsyncWebServerRequest *request) { @@ -1777,6 +1841,13 @@ void WebServer::handleRequest(AsyncWebServerRequest *request) { return; } #endif + +#ifdef USE_UPDATE + if (match.domain == "update") { + this->handle_update_request(request, match); + return; + } +#endif } bool WebServer::isRequestHandlerTrivial() { return false; } diff --git a/esphome/components/web_server/web_server.h b/esphome/components/web_server/web_server.h index 0fb40e2c33..5b98806af1 100644 --- a/esphome/components/web_server/web_server.h +++ b/esphome/components/web_server/web_server.h @@ -7,8 +7,8 @@ #include "esphome/core/controller.h" #include "esphome/core/entity_base.h" -#include #include +#include #ifdef USE_ESP32 #include #include @@ -319,6 +319,16 @@ class WebServer : public Controller, public Component, public AsyncWebHandler { std::string event_json(event::Event *obj, const std::string &event_type, JsonDetail start_config); #endif +#ifdef USE_UPDATE + void on_update(update::UpdateEntity *obj) override; + + /// Handle a update request under '/update/'. + void handle_update_request(AsyncWebServerRequest *request, const UrlMatch &match); + + /// Dump the update state with its value as a JSON string. + std::string update_json(update::UpdateEntity *obj, JsonDetail start_config); +#endif + /// Override the web handler's canHandle method. bool canHandle(AsyncWebServerRequest *request) override; /// Override the web handler's handleRequest method. diff --git a/esphome/const.py b/esphome/const.py index dcb353ab1c..cbd932e3cc 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1083,6 +1083,7 @@ DEVICE_CLASS_DURATION = "duration" DEVICE_CLASS_EMPTY = "" DEVICE_CLASS_ENERGY = "energy" DEVICE_CLASS_ENERGY_STORAGE = "energy_storage" +DEVICE_CLASS_FIRMWARE = "firmware" DEVICE_CLASS_FREQUENCY = "frequency" DEVICE_CLASS_GARAGE = "garage" DEVICE_CLASS_GARAGE_DOOR = "garage_door" diff --git a/esphome/core/application.h b/esphome/core/application.h index c4c745b687..2697357456 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -69,6 +69,9 @@ #ifdef USE_EVENT #include "esphome/components/event/event.h" #endif +#ifdef USE_UPDATE +#include "esphome/components/update/update_entity.h" +#endif namespace esphome { @@ -178,6 +181,10 @@ class Application { void register_event(event::Event *event) { this->events_.push_back(event); } #endif +#ifdef USE_UPDATE + void register_update(update::UpdateEntity *update) { this->updates_.push_back(update); } +#endif + /// Register the component in this Application instance. template C *register_component(C *c) { static_assert(std::is_base_of::value, "Only Component subclasses can be registered"); @@ -421,6 +428,16 @@ class Application { } #endif +#ifdef USE_UPDATE + const std::vector &get_updates() { return this->updates_; } + update::UpdateEntity *get_update_by_key(uint32_t key, bool include_internal = false) { + for (auto *obj : this->updates_) + if (obj->get_object_id_hash() == key && (include_internal || !obj->is_internal())) + return obj; + return nullptr; + } +#endif + Scheduler scheduler; protected: @@ -495,6 +512,9 @@ class Application { #ifdef USE_ALARM_CONTROL_PANEL std::vector alarm_control_panels_{}; #endif +#ifdef USE_UPDATE + std::vector updates_{}; +#endif std::string name_; std::string friendly_name_; diff --git a/esphome/core/component_iterator.cpp b/esphome/core/component_iterator.cpp index 9b02bf527b..da593340c1 100644 --- a/esphome/core/component_iterator.cpp +++ b/esphome/core/component_iterator.cpp @@ -351,6 +351,21 @@ void ComponentIterator::advance() { } } break; +#endif +#ifdef USE_UPDATE + case IteratorState::UPDATE: + if (this->at_ >= App.get_updates().size()) { + advance_platform = true; + } else { + auto *update = App.get_updates()[this->at_]; + if (update->is_internal() && !this->include_internal_) { + success = true; + break; + } else { + success = this->on_update(update); + } + } + break; #endif case IteratorState::MAX: if (this->on_end()) { diff --git a/esphome/core/component_iterator.h b/esphome/core/component_iterator.h index 2b847bc088..9e187f6c57 100644 --- a/esphome/core/component_iterator.h +++ b/esphome/core/component_iterator.h @@ -86,6 +86,9 @@ class ComponentIterator { #endif #ifdef USE_EVENT virtual bool on_event(event::Event *event) = 0; +#endif +#ifdef USE_UPDATE + virtual bool on_update(update::UpdateEntity *update) = 0; #endif virtual bool on_end(); @@ -158,6 +161,9 @@ class ComponentIterator { #endif #ifdef USE_EVENT EVENT, +#endif +#ifdef USE_UPDATE + UPDATE, #endif MAX, } state_{IteratorState::NONE}; diff --git a/esphome/core/controller.cpp b/esphome/core/controller.cpp index 0957329500..d6d98a4316 100644 --- a/esphome/core/controller.cpp +++ b/esphome/core/controller.cpp @@ -121,6 +121,12 @@ void Controller::setup_controller(bool include_internal) { obj->add_on_event_callback([this, obj](const std::string &event_type) { this->on_event(obj, event_type); }); } #endif +#ifdef USE_UPDATE + for (auto *obj : App.get_updates()) { + if (include_internal || !obj->is_internal()) + obj->add_on_state_callback([this, obj]() { this->on_update(obj); }); + } +#endif } } // namespace esphome diff --git a/esphome/core/controller.h b/esphome/core/controller.h index e1bf93193a..39e0b2ba26 100644 --- a/esphome/core/controller.h +++ b/esphome/core/controller.h @@ -61,6 +61,9 @@ #ifdef USE_EVENT #include "esphome/components/event/event.h" #endif +#ifdef USE_UPDATE +#include "esphome/components/update/update_entity.h" +#endif namespace esphome { @@ -124,6 +127,9 @@ class Controller { #ifdef USE_EVENT virtual void on_event(event::Event *obj, const std::string &event_type){}; #endif +#ifdef USE_UPDATE + virtual void on_update(update::UpdateEntity *obj){}; +#endif }; } // namespace esphome diff --git a/esphome/core/defines.h b/esphome/core/defines.h index affcd78089..1e6f3517db 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -59,6 +59,7 @@ #define USE_TIME #define USE_TOUCHSCREEN #define USE_UART_DEBUGGER +#define USE_UPDATE #define USE_VALVE #define USE_WIFI #define USE_WIFI_AP diff --git a/tests/components/http_request/common.yaml b/tests/components/http_request/common.yaml index 2b6996c0b9..83b334ca2d 100644 --- a/tests/components/http_request/common.yaml +++ b/tests/components/http_request/common.yaml @@ -73,3 +73,9 @@ button: url: http://my.ha.net:8123/local/esphome/firmware.bin - logger.log: "This message should be not displayed (reboot)" + +update: + - platform: http_request + name: OTA Update + id: ota_update + source: http://my.ha.net:8123/local/esphome/manifest.json diff --git a/tests/components/mqtt/common-update.yaml b/tests/components/mqtt/common-update.yaml new file mode 100644 index 0000000000..25f57cfef2 --- /dev/null +++ b/tests/components/mqtt/common-update.yaml @@ -0,0 +1,13 @@ +substitutions: + verify_ssl: "true" + +http_request: + verify_ssl: ${verify_ssl} + +ota: + - platform: http_request + +update: + - platform: http_request + name: "OTA Update" + source: https://example.com/ota.json diff --git a/tests/components/mqtt/test.esp32-c3-idf.yaml b/tests/components/mqtt/test.esp32-c3-idf.yaml index 25cb37a0b4..d19609b55e 100644 --- a/tests/components/mqtt/test.esp32-c3-idf.yaml +++ b/tests/components/mqtt/test.esp32-c3-idf.yaml @@ -1,2 +1,3 @@ packages: common: !include common.yaml + update: !include common-update.yaml diff --git a/tests/components/mqtt/test.esp32-c3.yaml b/tests/components/mqtt/test.esp32-c3.yaml index 25cb37a0b4..4c70fb37d9 100644 --- a/tests/components/mqtt/test.esp32-c3.yaml +++ b/tests/components/mqtt/test.esp32-c3.yaml @@ -1,2 +1,6 @@ +substitutions: + verify_ssl: "false" + packages: common: !include common.yaml + update: !include common-update.yaml diff --git a/tests/components/mqtt/test.esp32-idf.yaml b/tests/components/mqtt/test.esp32-idf.yaml index 25cb37a0b4..d19609b55e 100644 --- a/tests/components/mqtt/test.esp32-idf.yaml +++ b/tests/components/mqtt/test.esp32-idf.yaml @@ -1,2 +1,3 @@ packages: common: !include common.yaml + update: !include common-update.yaml diff --git a/tests/components/mqtt/test.esp32.yaml b/tests/components/mqtt/test.esp32.yaml index 25cb37a0b4..4c70fb37d9 100644 --- a/tests/components/mqtt/test.esp32.yaml +++ b/tests/components/mqtt/test.esp32.yaml @@ -1,2 +1,6 @@ +substitutions: + verify_ssl: "false" + packages: common: !include common.yaml + update: !include common-update.yaml diff --git a/tests/components/mqtt/test.esp8266.yaml b/tests/components/mqtt/test.esp8266.yaml index 25cb37a0b4..4c70fb37d9 100644 --- a/tests/components/mqtt/test.esp8266.yaml +++ b/tests/components/mqtt/test.esp8266.yaml @@ -1,2 +1,6 @@ +substitutions: + verify_ssl: "false" + packages: common: !include common.yaml + update: !include common-update.yaml diff --git a/tests/components/update/common.yaml b/tests/components/update/common.yaml new file mode 100644 index 0000000000..91b8669505 --- /dev/null +++ b/tests/components/update/common.yaml @@ -0,0 +1 @@ +update: diff --git a/tests/components/update/test.esp32-ard.yaml b/tests/components/update/test.esp32-ard.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/update/test.esp32-ard.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/update/test.esp32-idf.yaml b/tests/components/update/test.esp32-idf.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/update/test.esp32-idf.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/update/test.esp8266.yaml b/tests/components/update/test.esp8266.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/update/test.esp8266.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/update/test.rp2040.yaml b/tests/components/update/test.rp2040.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/update/test.rp2040.yaml @@ -0,0 +1 @@ +<<: !include common.yaml From 1f8449ec0e56d7fe7f0cca999f7d87843403d76b Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Tue, 11 Jun 2024 15:38:26 -0700 Subject: [PATCH 1565/2101] [Dockerfile] Sync platformio version with requirements.txt (#6888) --- docker/Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 36be700f55..fcb5a5e7ae 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -81,7 +81,8 @@ RUN \ fi; \ pip3 install \ --break-system-packages --no-cache-dir \ - platformio==6.1.13 \ + # Keep platformio version in sync with requirements.txt + platformio==6.1.15 \ # Change some platformio settings && platformio settings set enable_telemetry No \ && platformio settings set check_platformio_interval 1000000 \ From 3a97244b8346bc4e1ca5eebcdccbfbde10f66a32 Mon Sep 17 00:00:00 2001 From: Anton Sergunov Date: Wed, 12 Jun 2024 04:42:20 +0600 Subject: [PATCH 1566/2101] [Deep sleep] Compilation error with IDF >= 5.* (#6879) --- esphome/components/deep_sleep/deep_sleep_component.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/esphome/components/deep_sleep/deep_sleep_component.h b/esphome/components/deep_sleep/deep_sleep_component.h index be56b529ba..7a640b9ea5 100644 --- a/esphome/components/deep_sleep/deep_sleep_component.h +++ b/esphome/components/deep_sleep/deep_sleep_component.h @@ -34,10 +34,12 @@ enum WakeupPinMode { WAKEUP_PIN_MODE_INVERT_WAKEUP, }; +#if defined(USE_ESP32) && !defined(USE_ESP32_VARIANT_ESP32C3) struct Ext1Wakeup { uint64_t mask; esp_sleep_ext1_wakeup_mode_t wakeup_mode; }; +#endif struct WakeupCauseToRunDuration { // Run duration if woken up by timer or any other reason besides those below. @@ -114,7 +116,11 @@ class DeepSleepComponent : public Component { #ifdef USE_ESP32 InternalGPIOPin *wakeup_pin_; WakeupPinMode wakeup_pin_mode_{WAKEUP_PIN_MODE_IGNORE}; + +#if !defined(USE_ESP32_VARIANT_ESP32C3) optional ext1_wakeup_; +#endif + optional touch_wakeup_; optional wakeup_cause_to_run_duration_; #endif From c723fd1f8077b1d113b1d166c6bd43c35bc648a8 Mon Sep 17 00:00:00 2001 From: Landon Rohatensky Date: Tue, 11 Jun 2024 15:56:27 -0700 Subject: [PATCH 1567/2101] [animation] Allow loading external url at build time (#6876) --- esphome/components/animation/__init__.py | 53 ++++++++++++++++++++++-- esphome/components/image/__init__.py | 6 +-- 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/esphome/components/animation/__init__.py b/esphome/components/animation/__init__.py index a7a955bead..dbfc82c891 100644 --- a/esphome/components/animation/__init__.py +++ b/esphome/components/animation/__init__.py @@ -3,7 +3,13 @@ import logging from esphome import automation, core from esphome.components import font import esphome.components.image as espImage -from esphome.components.image import CONF_USE_TRANSPARENCY +from esphome.components.image import ( + CONF_USE_TRANSPARENCY, + LOCAL_SCHEMA, + WEB_SCHEMA, + SOURCE_WEB, + SOURCE_LOCAL, +) import esphome.config_validation as cv import esphome.codegen as cg from esphome.const import ( @@ -13,6 +19,9 @@ from esphome.const import ( CONF_REPEAT, CONF_RESIZE, CONF_TYPE, + CONF_SOURCE, + CONF_PATH, + CONF_URL, ) from esphome.core import CORE, HexInt @@ -43,6 +52,40 @@ SetFrameAction = animation_ns.class_( "AnimationSetFrameAction", automation.Action, cg.Parented.template(Animation_) ) +TYPED_FILE_SCHEMA = cv.typed_schema( + { + SOURCE_LOCAL: LOCAL_SCHEMA, + SOURCE_WEB: WEB_SCHEMA, + }, + key=CONF_SOURCE, +) + + +def _file_schema(value): + if isinstance(value, str): + return validate_file_shorthand(value) + return TYPED_FILE_SCHEMA(value) + + +FILE_SCHEMA = cv.Schema(_file_schema) + + +def validate_file_shorthand(value): + value = cv.string_strict(value) + if value.startswith("http://") or value.startswith("https://"): + return FILE_SCHEMA( + { + CONF_SOURCE: SOURCE_WEB, + CONF_URL: value, + } + ) + return FILE_SCHEMA( + { + CONF_SOURCE: SOURCE_LOCAL, + CONF_PATH: value, + } + ) + def validate_cross_dependencies(config): """ @@ -67,7 +110,7 @@ ANIMATION_SCHEMA = cv.Schema( cv.All( { cv.Required(CONF_ID): cv.declare_id(Animation_), - cv.Required(CONF_FILE): cv.file_, + cv.Required(CONF_FILE): FILE_SCHEMA, cv.Optional(CONF_RESIZE): cv.dimensions, cv.Optional(CONF_TYPE, default="BINARY"): cv.enum( espImage.IMAGE_TYPE, upper=True @@ -124,7 +167,11 @@ async def animation_action_to_code(config, action_id, template_arg, args): async def to_code(config): from PIL import Image - path = CORE.relative_config_path(config[CONF_FILE]) + conf_file = config[CONF_FILE] + if conf_file[CONF_SOURCE] == SOURCE_LOCAL: + path = CORE.relative_config_path(conf_file[CONF_PATH]) + elif conf_file[CONF_SOURCE] == SOURCE_WEB: + path = espImage.compute_local_image_path(conf_file).as_posix() try: image = Image.open(path) except Exception as e: diff --git a/esphome/components/image/__init__.py b/esphome/components/image/__init__.py index 73dc73aa45..b23ed3445a 100644 --- a/esphome/components/image/__init__.py +++ b/esphome/components/image/__init__.py @@ -68,7 +68,7 @@ def _compute_local_icon_path(value: dict) -> Path: return base_dir / f"{value[CONF_ICON]}.svg" -def _compute_local_image_path(value: dict) -> Path: +def compute_local_image_path(value: dict) -> Path: url = value[CONF_URL] h = hashlib.new("sha256") h.update(url.encode()) @@ -117,7 +117,7 @@ def download_mdi(value): def download_image(value): url = value[CONF_URL] - path = _compute_local_image_path(value) + path = compute_local_image_path(value) download_content(url, path) @@ -295,7 +295,7 @@ async def to_code(config): path = _compute_local_icon_path(conf_file).as_posix() elif conf_file[CONF_SOURCE] == SOURCE_WEB: - path = _compute_local_image_path(conf_file).as_posix() + path = compute_local_image_path(conf_file).as_posix() try: with open(path, "rb") as f: From a64106e48c47098999b7a52a683765cc18224ddd Mon Sep 17 00:00:00 2001 From: Peter Ericson Date: Wed, 12 Jun 2024 01:51:04 +0200 Subject: [PATCH 1568/2101] [waveshare_epaper] Add support for 13.3in-k (#6443) --- .../components/waveshare_epaper/display.py | 4 + .../waveshare_epaper/waveshare_epaper.cpp | 83 +++++++++++++++++++ .../waveshare_epaper/waveshare_epaper.h | 24 ++++++ 3 files changed, 111 insertions(+) diff --git a/esphome/components/waveshare_epaper/display.py b/esphome/components/waveshare_epaper/display.py index 9ad948e915..4d3965449f 100644 --- a/esphome/components/waveshare_epaper/display.py +++ b/esphome/components/waveshare_epaper/display.py @@ -94,6 +94,9 @@ WaveshareEPaper2P13InV2 = waveshare_epaper_ns.class_( WaveshareEPaper2P13InV3 = waveshare_epaper_ns.class_( "WaveshareEPaper2P13InV3", WaveshareEPaper ) +WaveshareEPaper13P3InK = waveshare_epaper_ns.class_( + "WaveshareEPaper13P3InK", WaveshareEPaper +) GDEW0154M09 = waveshare_epaper_ns.class_("GDEW0154M09", WaveshareEPaper) WaveshareEPaperTypeAModel = waveshare_epaper_ns.enum("WaveshareEPaperTypeAModel") @@ -133,6 +136,7 @@ MODELS = { "2.13in-ttgo-dke": ("c", WaveshareEPaper2P13InDKE), "2.13inv3": ("c", WaveshareEPaper2P13InV3), "1.54in-m5coreink-m09": ("c", GDEW0154M09), + "13.3in-k": ("b", WaveshareEPaper13P3InK), } RESET_PIN_REQUIRED_MODELS = ("2.13inv2", "2.13in-ttgo-b74") diff --git a/esphome/components/waveshare_epaper/waveshare_epaper.cpp b/esphome/components/waveshare_epaper/waveshare_epaper.cpp index 5428f4ec80..24df428e6f 100644 --- a/esphome/components/waveshare_epaper/waveshare_epaper.cpp +++ b/esphome/components/waveshare_epaper/waveshare_epaper.cpp @@ -2963,5 +2963,88 @@ void WaveshareEPaper2P13InDKE::set_full_update_every(uint32_t full_update_every) this->full_update_every_ = full_update_every; } +// ======================================================== +// 13.3in (K version) +// Datasheet/Specification/Reference: +// - https://files.waveshare.com/wiki/13.3inch-e-Paper-HAT-(K)/13.3-inch-e-Paper-(K)-user-manual.pdf +// - https://github.com/waveshareteam/e-Paper/tree/master/Arduino/epd13in3k +// ======================================================== + +// using default wait_until_idle_() function +void WaveshareEPaper13P3InK::initialize() { + this->wait_until_idle_(); + this->command(0x12); // SWRESET + this->wait_until_idle_(); + + this->command(0x0c); // set soft start + this->data(0xae); + this->data(0xc7); + this->data(0xc3); + this->data(0xc0); + this->data(0x80); + + this->command(0x01); // driver output control + this->data((get_height_internal() - 1) % 256); // Y + this->data((get_height_internal() - 1) / 256); // Y + this->data(0x00); + + this->command(0x11); // data entry mode + this->data(0x03); + + // SET WINDOWS + // XRAM_START_AND_END_POSITION + this->command(0x44); + this->data(0 & 0xFF); + this->data((0 >> 8) & 0x03); + this->data((get_width_internal() - 1) & 0xFF); + this->data(((get_width_internal() - 1) >> 8) & 0x03); + // YRAM_START_AND_END_POSITION + this->command(0x45); + this->data(0 & 0xFF); + this->data((0 >> 8) & 0x03); + this->data((get_height_internal() - 1) & 0xFF); + this->data(((get_height_internal() - 1) >> 8) & 0x03); + + this->command(0x3C); // Border setting + this->data(0x01); + + this->command(0x18); // use the internal temperature sensor + this->data(0x80); + + // SET CURSOR + // XRAM_ADDRESS + this->command(0x4E); + this->data(0 & 0xFF); + this->data((0 >> 8) & 0x03); + // YRAM_ADDRESS + this->command(0x4F); + this->data(0 & 0xFF); + this->data((0 >> 8) & 0x03); +} +void HOT WaveshareEPaper13P3InK::display() { + // do single full update + this->command(0x24); + this->start_data_(); + this->write_array(this->buffer_, this->get_buffer_length_()); + this->end_data_(); + + // COMMAND DISPLAY REFRESH + this->command(0x22); + this->data(0xF7); + this->command(0x20); +} + +int WaveshareEPaper13P3InK::get_width_internal() { return 960; } +int WaveshareEPaper13P3InK::get_height_internal() { return 680; } +uint32_t WaveshareEPaper13P3InK::idle_timeout_() { return 10000; } +void WaveshareEPaper13P3InK::dump_config() { + LOG_DISPLAY("", "Waveshare E-Paper", this); + ESP_LOGCONFIG(TAG, " Model: 13.3inK"); + LOG_PIN(" Reset Pin: ", this->reset_pin_); + LOG_PIN(" DC Pin: ", this->dc_pin_); + LOG_PIN(" Busy Pin: ", this->busy_pin_); + LOG_UPDATE_INTERVAL(this); +} + } // namespace waveshare_epaper } // namespace esphome diff --git a/esphome/components/waveshare_epaper/waveshare_epaper.h b/esphome/components/waveshare_epaper/waveshare_epaper.h index 4a5844ae88..7572982a20 100644 --- a/esphome/components/waveshare_epaper/waveshare_epaper.h +++ b/esphome/components/waveshare_epaper/waveshare_epaper.h @@ -163,6 +163,7 @@ enum WaveshareEPaperTypeBModel { WAVESHARE_EPAPER_7_5_IN, WAVESHARE_EPAPER_7_5_INV2, WAVESHARE_EPAPER_7_5_IN_B_V2, + WAVESHARE_EPAPER_13_3_IN_K, }; class WaveshareEPaper2P7In : public WaveshareEPaper { @@ -769,5 +770,28 @@ class WaveshareEPaper2P13InV3 : public WaveshareEPaper { bool is_busy_{false}; void write_lut_(const uint8_t *lut); }; + +class WaveshareEPaper13P3InK : public WaveshareEPaper { + public: + void initialize() override; + + void display() override; + + void dump_config() override; + + void deep_sleep() override { + // COMMAND DEEP SLEEP + this->command(0x10); + this->data(0x01); + } + + protected: + int get_width_internal() override; + + int get_height_internal() override; + + uint32_t idle_timeout_() override; +}; + } // namespace waveshare_epaper } // namespace esphome From 562700bd2c4014d8caf224cdeb45ae3969dcc7a4 Mon Sep 17 00:00:00 2001 From: Daniel D'Abate Date: Wed, 12 Jun 2024 02:04:25 +0200 Subject: [PATCH 1569/2101] Climate IR LG - Support fan only mode and all "on" commands (#3712) --- .../climate_ir_lg/climate_ir_lg.cpp | 187 ++++++++++-------- .../components/climate_ir_lg/climate_ir_lg.h | 2 +- 2 files changed, 102 insertions(+), 87 deletions(-) diff --git a/esphome/components/climate_ir_lg/climate_ir_lg.cpp b/esphome/components/climate_ir_lg/climate_ir_lg.cpp index d2199c1cbe..c65f24ebc0 100644 --- a/esphome/components/climate_ir_lg/climate_ir_lg.cpp +++ b/esphome/components/climate_ir_lg/climate_ir_lg.cpp @@ -6,18 +6,24 @@ namespace climate_ir_lg { static const char *const TAG = "climate.climate_ir_lg"; -const uint32_t COMMAND_ON = 0x00000; -const uint32_t COMMAND_ON_AI = 0x03000; -const uint32_t COMMAND_COOL = 0x08000; -const uint32_t COMMAND_HEAT = 0x0C000; +// Commands +const uint32_t COMMAND_MASK = 0xFF000; const uint32_t COMMAND_OFF = 0xC0000; const uint32_t COMMAND_SWING = 0x10000; -// On, 25C, Mode: Auto, Fan: Auto, Zone Follow: Off, Sensor Temp: Ignore. -const uint32_t COMMAND_AUTO = 0x0B000; -const uint32_t COMMAND_DRY_FAN = 0x09000; -const uint32_t COMMAND_MASK = 0xFF000; +const uint32_t COMMAND_ON_COOL = 0x00000; +const uint32_t COMMAND_ON_DRY = 0x01000; +const uint32_t COMMAND_ON_FAN_ONLY = 0x02000; +const uint32_t COMMAND_ON_AI = 0x03000; +const uint32_t COMMAND_ON_HEAT = 0x04000; +const uint32_t COMMAND_COOL = 0x08000; +const uint32_t COMMAND_DRY = 0x09000; +const uint32_t COMMAND_FAN_ONLY = 0x0A000; +const uint32_t COMMAND_AI = 0x0B000; +const uint32_t COMMAND_HEAT = 0x0C000; + +// Fan speed const uint32_t FAN_MASK = 0xF0; const uint32_t FAN_AUTO = 0x50; const uint32_t FAN_MIN = 0x00; @@ -35,69 +41,67 @@ void LgIrClimate::transmit_state() { uint32_t remote_state = 0x8800000; // ESP_LOGD(TAG, "climate_lg_ir mode_before_ code: 0x%02X", modeBefore_); + + // Set command if (send_swing_cmd_) { send_swing_cmd_ = false; remote_state |= COMMAND_SWING; } else { - if (mode_before_ == climate::CLIMATE_MODE_OFF && this->mode == climate::CLIMATE_MODE_HEAT_COOL) { - remote_state |= COMMAND_ON_AI; - } else if (mode_before_ == climate::CLIMATE_MODE_OFF && this->mode != climate::CLIMATE_MODE_OFF) { - remote_state |= COMMAND_ON; - this->mode = climate::CLIMATE_MODE_COOL; - } else { - switch (this->mode) { - case climate::CLIMATE_MODE_COOL: - remote_state |= COMMAND_COOL; - break; - case climate::CLIMATE_MODE_HEAT: - remote_state |= COMMAND_HEAT; - break; - case climate::CLIMATE_MODE_HEAT_COOL: - remote_state |= COMMAND_AUTO; - break; - case climate::CLIMATE_MODE_DRY: - remote_state |= COMMAND_DRY_FAN; - break; - case climate::CLIMATE_MODE_OFF: - default: - remote_state |= COMMAND_OFF; - break; - } - } - mode_before_ = this->mode; - - ESP_LOGD(TAG, "climate_lg_ir mode code: 0x%02X", this->mode); - - if (this->mode == climate::CLIMATE_MODE_OFF) { - remote_state |= FAN_AUTO; - } else if (this->mode == climate::CLIMATE_MODE_COOL || this->mode == climate::CLIMATE_MODE_DRY || - this->mode == climate::CLIMATE_MODE_HEAT) { - switch (this->fan_mode.value()) { - case climate::CLIMATE_FAN_HIGH: - remote_state |= FAN_MAX; - break; - case climate::CLIMATE_FAN_MEDIUM: - remote_state |= FAN_MED; - break; - case climate::CLIMATE_FAN_LOW: - remote_state |= FAN_MIN; - break; - case climate::CLIMATE_FAN_AUTO: - default: - remote_state |= FAN_AUTO; - break; - } - } - - if (this->mode == climate::CLIMATE_MODE_HEAT_COOL) { - this->fan_mode = climate::CLIMATE_FAN_AUTO; - // remote_state |= FAN_MODE_AUTO_DRY; - } - if (this->mode == climate::CLIMATE_MODE_COOL || this->mode == climate::CLIMATE_MODE_HEAT) { - auto temp = (uint8_t) roundf(clamp(this->target_temperature, TEMP_MIN, TEMP_MAX)); - remote_state |= ((temp - 15) << TEMP_SHIFT); + bool climate_is_off = (mode_before_ == climate::CLIMATE_MODE_OFF); + switch (this->mode) { + case climate::CLIMATE_MODE_COOL: + remote_state |= climate_is_off ? COMMAND_ON_COOL : COMMAND_COOL; + break; + case climate::CLIMATE_MODE_DRY: + remote_state |= climate_is_off ? COMMAND_ON_DRY : COMMAND_DRY; + break; + case climate::CLIMATE_MODE_FAN_ONLY: + remote_state |= climate_is_off ? COMMAND_ON_FAN_ONLY : COMMAND_FAN_ONLY; + break; + case climate::CLIMATE_MODE_HEAT_COOL: + remote_state |= climate_is_off ? COMMAND_ON_AI : COMMAND_AI; + break; + case climate::CLIMATE_MODE_HEAT: + remote_state |= climate_is_off ? COMMAND_ON_HEAT : COMMAND_HEAT; + break; + case climate::CLIMATE_MODE_OFF: + default: + remote_state |= COMMAND_OFF; + break; } } + + mode_before_ = this->mode; + + ESP_LOGD(TAG, "climate_lg_ir mode code: 0x%02X", this->mode); + + // Set fan speed + if (this->mode == climate::CLIMATE_MODE_OFF) { + remote_state |= FAN_AUTO; + } else { + switch (this->fan_mode.value()) { + case climate::CLIMATE_FAN_HIGH: + remote_state |= FAN_MAX; + break; + case climate::CLIMATE_FAN_MEDIUM: + remote_state |= FAN_MED; + break; + case climate::CLIMATE_FAN_LOW: + remote_state |= FAN_MIN; + break; + case climate::CLIMATE_FAN_AUTO: + default: + remote_state |= FAN_AUTO; + break; + } + } + + // Set temperature + if (this->mode == climate::CLIMATE_MODE_COOL || this->mode == climate::CLIMATE_MODE_HEAT) { + auto temp = (uint8_t) roundf(clamp(this->target_temperature, TEMP_MIN, TEMP_MAX)); + remote_state |= ((temp - 15) << TEMP_SHIFT); + } + transmit_(remote_state); this->publish_state(); } @@ -125,37 +129,42 @@ bool LgIrClimate::on_receive(remote_base::RemoteReceiveData data) { if ((remote_state & 0xFF00000) != 0x8800000) return false; - if ((remote_state & COMMAND_MASK) == COMMAND_ON) { - this->mode = climate::CLIMATE_MODE_COOL; - } else if ((remote_state & COMMAND_MASK) == COMMAND_ON_AI) { - this->mode = climate::CLIMATE_MODE_HEAT_COOL; - } - + // Get command if ((remote_state & COMMAND_MASK) == COMMAND_OFF) { this->mode = climate::CLIMATE_MODE_OFF; } else if ((remote_state & COMMAND_MASK) == COMMAND_SWING) { this->swing_mode = this->swing_mode == climate::CLIMATE_SWING_OFF ? climate::CLIMATE_SWING_VERTICAL : climate::CLIMATE_SWING_OFF; } else { - if ((remote_state & COMMAND_MASK) == COMMAND_AUTO) { - this->mode = climate::CLIMATE_MODE_HEAT_COOL; - } else if ((remote_state & COMMAND_MASK) == COMMAND_DRY_FAN) { - this->mode = climate::CLIMATE_MODE_DRY; - } else if ((remote_state & COMMAND_MASK) == COMMAND_HEAT) { - this->mode = climate::CLIMATE_MODE_HEAT; - } else { - this->mode = climate::CLIMATE_MODE_COOL; + switch (remote_state & COMMAND_MASK) { + case COMMAND_DRY: + case COMMAND_ON_DRY: + this->mode = climate::CLIMATE_MODE_DRY; + break; + case COMMAND_FAN_ONLY: + case COMMAND_ON_FAN_ONLY: + this->mode = climate::CLIMATE_MODE_FAN_ONLY; + break; + case COMMAND_AI: + case COMMAND_ON_AI: + this->mode = climate::CLIMATE_MODE_HEAT_COOL; + break; + case COMMAND_HEAT: + case COMMAND_ON_HEAT: + this->mode = climate::CLIMATE_MODE_HEAT; + break; + case COMMAND_COOL: + case COMMAND_ON_COOL: + default: + this->mode = climate::CLIMATE_MODE_COOL; + break; } - // Temperature - if (this->mode == climate::CLIMATE_MODE_COOL || this->mode == climate::CLIMATE_MODE_HEAT) - this->target_temperature = ((remote_state & TEMP_MASK) >> TEMP_SHIFT) + 15; - - // Fan Speed + // Get fan speed if (this->mode == climate::CLIMATE_MODE_HEAT_COOL) { this->fan_mode = climate::CLIMATE_FAN_AUTO; - } else if (this->mode == climate::CLIMATE_MODE_COOL || this->mode == climate::CLIMATE_MODE_HEAT || - this->mode == climate::CLIMATE_MODE_DRY) { + } else if (this->mode == climate::CLIMATE_MODE_COOL || this->mode == climate::CLIMATE_MODE_DRY || + this->mode == climate::CLIMATE_MODE_FAN_ONLY || this->mode == climate::CLIMATE_MODE_HEAT) { if ((remote_state & FAN_MASK) == FAN_AUTO) { this->fan_mode = climate::CLIMATE_FAN_AUTO; } else if ((remote_state & FAN_MASK) == FAN_MIN) { @@ -166,11 +175,17 @@ bool LgIrClimate::on_receive(remote_base::RemoteReceiveData data) { this->fan_mode = climate::CLIMATE_FAN_HIGH; } } + + // Get temperature + if (this->mode == climate::CLIMATE_MODE_COOL || this->mode == climate::CLIMATE_MODE_HEAT) { + this->target_temperature = ((remote_state & TEMP_MASK) >> TEMP_SHIFT) + 15; + } } this->publish_state(); return true; } + void LgIrClimate::transmit_(uint32_t value) { calc_checksum_(value); ESP_LOGD(TAG, "Sending climate_lg_ir code: 0x%02" PRIX32, value); diff --git a/esphome/components/climate_ir_lg/climate_ir_lg.h b/esphome/components/climate_ir_lg/climate_ir_lg.h index 34f50744ef..7ee041b86f 100644 --- a/esphome/components/climate_ir_lg/climate_ir_lg.h +++ b/esphome/components/climate_ir_lg/climate_ir_lg.h @@ -14,7 +14,7 @@ const uint8_t TEMP_MAX = 30; // Celsius class LgIrClimate : public climate_ir::ClimateIR { public: LgIrClimate() - : climate_ir::ClimateIR(TEMP_MIN, TEMP_MAX, 1.0f, true, false, + : climate_ir::ClimateIR(TEMP_MIN, 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}) {} From 7b60543afd02960058e2cff58c70acebf68acc57 Mon Sep 17 00:00:00 2001 From: NMartin354 Date: Tue, 11 Jun 2024 19:38:20 -0500 Subject: [PATCH 1570/2101] [safe_mode] Allow user-defined interval for successful boot (#6882) Co-authored-by: Keith Burzinski --- esphome/components/safe_mode/__init__.py | 8 +++++++- esphome/components/safe_mode/safe_mode.cpp | 8 ++++++-- esphome/components/safe_mode/safe_mode.h | 13 +++++++------ tests/components/safe_mode/common.yaml | 1 + 4 files changed, 21 insertions(+), 9 deletions(-) diff --git a/esphome/components/safe_mode/__init__.py b/esphome/components/safe_mode/__init__.py index 92b285e279..881937890d 100644 --- a/esphome/components/safe_mode/__init__.py +++ b/esphome/components/safe_mode/__init__.py @@ -16,6 +16,7 @@ from esphome import automation CODEOWNERS = ["@paulmonigatti", "@jsuanet", "@kbx81"] +CONF_BOOT_IS_GOOD_AFTER = "boot_is_good_after" CONF_ON_SAFE_MODE = "on_safe_mode" safe_mode_ns = cg.esphome_ns.namespace("safe_mode") @@ -34,6 +35,9 @@ CONFIG_SCHEMA = cv.All( cv.Schema( { cv.GenerateID(): cv.declare_id(SafeModeComponent), + cv.Optional( + CONF_BOOT_IS_GOOD_AFTER, default="1min" + ): cv.positive_time_period_milliseconds, cv.Optional(CONF_DISABLED, default=False): cv.boolean, cv.Optional(CONF_NUM_ATTEMPTS, default="10"): cv.positive_not_null_int, cv.Optional( @@ -63,7 +67,9 @@ async def to_code(config): await automation.build_automation(trigger, [], conf) condition = var.should_enter_safe_mode( - config[CONF_NUM_ATTEMPTS], config[CONF_REBOOT_TIMEOUT] + config[CONF_NUM_ATTEMPTS], + config[CONF_REBOOT_TIMEOUT], + config[CONF_BOOT_IS_GOOD_AFTER], ) cg.add(RawExpression(f"if ({condition}) return")) CORE.data[CONF_SAFE_MODE] = {} diff --git a/esphome/components/safe_mode/safe_mode.cpp b/esphome/components/safe_mode/safe_mode.cpp index 6934dcb9d9..aa1a4b6822 100644 --- a/esphome/components/safe_mode/safe_mode.cpp +++ b/esphome/components/safe_mode/safe_mode.cpp @@ -16,6 +16,8 @@ static const char *const TAG = "safe_mode"; void SafeModeComponent::dump_config() { ESP_LOGCONFIG(TAG, "Safe Mode:"); + ESP_LOGCONFIG(TAG, " Boot considered successful after %" PRIu32 " seconds", + this->safe_mode_boot_is_good_after_ / 1000); // because milliseconds ESP_LOGCONFIG(TAG, " Invoke after %u boot attempts", this->safe_mode_num_attempts_); ESP_LOGCONFIG(TAG, " Remain in safe mode for %" PRIu32 " seconds", this->safe_mode_enable_time_ / 1000); // because milliseconds @@ -34,7 +36,7 @@ void SafeModeComponent::dump_config() { float SafeModeComponent::get_setup_priority() const { return setup_priority::AFTER_WIFI; } void SafeModeComponent::loop() { - if (!this->boot_successful_ && (millis() - this->safe_mode_start_time_) > this->safe_mode_enable_time_) { + 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(); @@ -60,9 +62,11 @@ bool SafeModeComponent::get_safe_mode_pending() { return this->read_rtc_() == SafeModeComponent::ENTER_SAFE_MODE_MAGIC; } -bool SafeModeComponent::should_enter_safe_mode(uint8_t num_attempts, uint32_t enable_time) { +bool SafeModeComponent::should_enter_safe_mode(uint8_t num_attempts, uint32_t enable_time, + uint32_t boot_is_good_after) { this->safe_mode_start_time_ = millis(); 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(233825507UL, false); this->safe_mode_rtc_value_ = this->read_rtc_(); diff --git a/esphome/components/safe_mode/safe_mode.h b/esphome/components/safe_mode/safe_mode.h index 0ec3c29529..37e2c3a3d6 100644 --- a/esphome/components/safe_mode/safe_mode.h +++ b/esphome/components/safe_mode/safe_mode.h @@ -11,7 +11,7 @@ namespace safe_mode { /// SafeModeComponent provides a safe way to recover from repeated boot failures class SafeModeComponent : public Component { public: - bool should_enter_safe_mode(uint8_t num_attempts, uint32_t enable_time); + bool should_enter_safe_mode(uint8_t num_attempts, uint32_t enable_time, uint32_t boot_is_good_after); /// Set to true if the next startup will enter safe mode void set_safe_mode_pending(const bool &pending); @@ -33,11 +33,12 @@ class SafeModeComponent : public Component { void write_rtc_(uint32_t val); uint32_t read_rtc_(); - bool boot_successful_{false}; ///< set to true after boot is considered successful - uint32_t safe_mode_start_time_; ///< stores when safe mode was enabled - uint32_t safe_mode_enable_time_{60000}; ///< The time safe mode should remain active for - uint32_t safe_mode_rtc_value_; - uint8_t safe_mode_num_attempts_; + bool boot_successful_{false}; ///< set to true after boot is considered successful + uint32_t safe_mode_boot_is_good_after_{60000}; ///< The amount of time after which the boot is considered successful + uint32_t safe_mode_enable_time_{60000}; ///< The time safe mode should remain active for + uint32_t safe_mode_rtc_value_{0}; + uint32_t safe_mode_start_time_{0}; ///< stores when safe mode was enabled + uint8_t safe_mode_num_attempts_{0}; ESPPreferenceObject rtc_; CallbackManager safe_mode_callback_{}; diff --git a/tests/components/safe_mode/common.yaml b/tests/components/safe_mode/common.yaml index ce8bf2f0cf..c24f49e6b6 100644 --- a/tests/components/safe_mode/common.yaml +++ b/tests/components/safe_mode/common.yaml @@ -3,6 +3,7 @@ wifi: password: password1 safe_mode: + boot_is_good_after: 2min num_attempts: 3 reboot_timeout: 2min on_safe_mode: From 13fabf1cd8eae9fe783a9a83b5d4665b66c5b180 Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Tue, 11 Jun 2024 18:05:44 -0700 Subject: [PATCH 1571/2101] change to new 1-wire platform (#6860) Co-authored-by: Samuel Sieb Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- CODEOWNERS | 3 + esphome/components/dallas/__init__.py | 24 +- .../components/dallas/dallas_component.cpp | 287 ------------------ esphome/components/dallas/dallas_component.h | 79 ----- esphome/components/dallas/esp_one_wire.cpp | 252 --------------- esphome/components/dallas/esp_one_wire.h | 68 ----- esphome/components/dallas/sensor.py | 51 +--- esphome/components/dallas_temp/__init__.py | 1 + .../components/dallas_temp/dallas_temp.cpp | 172 +++++++++++ esphome/components/dallas_temp/dallas_temp.h | 32 ++ esphome/components/dallas_temp/sensor.py | 43 +++ esphome/components/gpio/one_wire/__init__.py | 25 ++ .../gpio/one_wire/gpio_one_wire.cpp | 199 ++++++++++++ .../components/gpio/one_wire/gpio_one_wire.h | 41 +++ esphome/components/one_wire/__init__.py | 40 +++ esphome/components/one_wire/one_wire.cpp | 40 +++ esphome/components/one_wire/one_wire.h | 44 +++ esphome/components/one_wire/one_wire_bus.cpp | 88 ++++++ esphome/components/one_wire/one_wire_bus.h | 61 ++++ script/ci-custom.py | 3 +- .../{dallas => dallas_temp}/common.yaml | 10 +- .../test.esp32-c3-idf.yaml | 0 .../test.esp32-c3.yaml | 0 .../test.esp32-idf.yaml | 0 .../{dallas => dallas_temp}/test.esp32.yaml | 0 .../{dallas => dallas_temp}/test.esp8266.yaml | 0 .../{dallas => dallas_temp}/test.rp2040.yaml | 0 tests/test1.yaml | 12 - 28 files changed, 802 insertions(+), 773 deletions(-) delete mode 100644 esphome/components/dallas/dallas_component.cpp delete mode 100644 esphome/components/dallas/dallas_component.h delete mode 100644 esphome/components/dallas/esp_one_wire.cpp delete mode 100644 esphome/components/dallas/esp_one_wire.h create mode 100644 esphome/components/dallas_temp/__init__.py create mode 100644 esphome/components/dallas_temp/dallas_temp.cpp create mode 100644 esphome/components/dallas_temp/dallas_temp.h create mode 100644 esphome/components/dallas_temp/sensor.py create mode 100644 esphome/components/gpio/one_wire/__init__.py create mode 100644 esphome/components/gpio/one_wire/gpio_one_wire.cpp create mode 100644 esphome/components/gpio/one_wire/gpio_one_wire.h create mode 100644 esphome/components/one_wire/__init__.py create mode 100644 esphome/components/one_wire/one_wire.cpp create mode 100644 esphome/components/one_wire/one_wire.h create mode 100644 esphome/components/one_wire/one_wire_bus.cpp create mode 100644 esphome/components/one_wire/one_wire_bus.h rename tests/components/{dallas => dallas_temp}/common.yaml (55%) rename tests/components/{dallas => dallas_temp}/test.esp32-c3-idf.yaml (100%) rename tests/components/{dallas => dallas_temp}/test.esp32-c3.yaml (100%) rename tests/components/{dallas => dallas_temp}/test.esp32-idf.yaml (100%) rename tests/components/{dallas => dallas_temp}/test.esp32.yaml (100%) rename tests/components/{dallas => dallas_temp}/test.esp8266.yaml (100%) rename tests/components/{dallas => dallas_temp}/test.rp2040.yaml (100%) diff --git a/CODEOWNERS b/CODEOWNERS index bbb39c26ad..75ea4fe523 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -94,6 +94,7 @@ esphome/components/current_based/* @djwmarcx esphome/components/dac7678/* @NickB1 esphome/components/daikin_arc/* @MagicBear esphome/components/daikin_brc/* @hagak +esphome/components/dallas_temp/* @ssieb esphome/components/daly_bms/* @s1lvi0 esphome/components/dashboard_import/* @esphome/core esphome/components/datetime/* @jesserockz @rfdarter @@ -144,6 +145,7 @@ esphome/components/gdk101/* @Szewcson esphome/components/globals/* @esphome/core esphome/components/gp8403/* @jesserockz esphome/components/gpio/* @esphome/core +esphome/components/gpio/one_wire/* @ssieb esphome/components/gps/* @coogle esphome/components/graph/* @synco esphome/components/graphical_display_menu/* @MrMDavidson @@ -270,6 +272,7 @@ esphome/components/nextion/text_sensor/* @senexcrenshaw esphome/components/nfc/* @jesserockz @kbx81 esphome/components/noblex/* @AGalfra esphome/components/number/* @esphome/core +esphome/components/one_wire/* @ssieb esphome/components/ota/* @esphome/core esphome/components/output/* @esphome/core esphome/components/pca6416a/* @Mat931 diff --git a/esphome/components/dallas/__init__.py b/esphome/components/dallas/__init__.py index 0f71399a7c..6c2a9d830e 100644 --- a/esphome/components/dallas/__init__.py +++ b/esphome/components/dallas/__init__.py @@ -1,25 +1,7 @@ -import esphome.codegen as cg import esphome.config_validation as cv -from esphome import pins -from esphome.const import CONF_ID, CONF_PIN MULTI_CONF = True -AUTO_LOAD = ["sensor"] -dallas_ns = cg.esphome_ns.namespace("dallas") -DallasComponent = dallas_ns.class_("DallasComponent", cg.PollingComponent) - -CONFIG_SCHEMA = cv.Schema( - { - cv.GenerateID(): cv.declare_id(DallasComponent), - cv.Required(CONF_PIN): pins.internal_gpio_output_pin_schema, - } -).extend(cv.polling_component_schema("60s")) - - -async def to_code(config): - var = cg.new_Pvariable(config[CONF_ID]) - await cg.register_component(var, config) - - pin = await cg.gpio_pin_expression(config[CONF_PIN]) - cg.add(var.set_pin(pin)) +CONFIG_SCHEMA = cv.invalid( + 'The "dallas" component has been replaced by the "one_wire" component.\nhttps://esphome.io/components/one_wire' +) diff --git a/esphome/components/dallas/dallas_component.cpp b/esphome/components/dallas/dallas_component.cpp deleted file mode 100644 index a51bc369a1..0000000000 --- a/esphome/components/dallas/dallas_component.cpp +++ /dev/null @@ -1,287 +0,0 @@ -#include "dallas_component.h" -#include "esphome/core/log.h" - -namespace esphome { -namespace dallas { - -static const char *const TAG = "dallas.sensor"; - -static const uint8_t DALLAS_MODEL_DS18S20 = 0x10; -static const uint8_t DALLAS_MODEL_DS1822 = 0x22; -static const uint8_t DALLAS_MODEL_DS18B20 = 0x28; -static const uint8_t DALLAS_MODEL_DS1825 = 0x3B; -static const uint8_t DALLAS_MODEL_DS28EA00 = 0x42; -static const uint8_t DALLAS_COMMAND_START_CONVERSION = 0x44; -static const uint8_t DALLAS_COMMAND_READ_SCRATCH_PAD = 0xBE; -static const uint8_t DALLAS_COMMAND_WRITE_SCRATCH_PAD = 0x4E; - -uint16_t DallasTemperatureSensor::millis_to_wait_for_conversion() const { - switch (this->resolution_) { - case 9: - return 94; - case 10: - return 188; - case 11: - return 375; - default: - return 750; - } -} - -void DallasComponent::setup() { - ESP_LOGCONFIG(TAG, "Setting up DallasComponent..."); - - pin_->setup(); - - // clear bus with 480µs high, otherwise initial reset in search_vec() fails - pin_->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP); - delayMicroseconds(480); - - one_wire_ = new ESPOneWire(pin_); // NOLINT(cppcoreguidelines-owning-memory) - - std::vector raw_sensors; - raw_sensors = this->one_wire_->search_vec(); - - for (auto &address : raw_sensors) { - auto *address8 = reinterpret_cast(&address); - if (crc8(address8, 7) != address8[7]) { - ESP_LOGW(TAG, "Dallas device 0x%s has invalid CRC.", format_hex(address).c_str()); - continue; - } - if (address8[0] != DALLAS_MODEL_DS18S20 && address8[0] != DALLAS_MODEL_DS1822 && - address8[0] != DALLAS_MODEL_DS18B20 && address8[0] != DALLAS_MODEL_DS1825 && - address8[0] != DALLAS_MODEL_DS28EA00) { - ESP_LOGW(TAG, "Unknown device type 0x%02X.", address8[0]); - continue; - } - this->found_sensors_.push_back(address); - } - - for (auto *sensor : this->sensors_) { - if (sensor->get_index().has_value()) { - if (*sensor->get_index() >= this->found_sensors_.size()) { - this->status_set_error("Sensor configured by index but not found"); - continue; - } - sensor->set_address(this->found_sensors_[*sensor->get_index()]); - } - - if (!sensor->setup_sensor()) { - this->status_set_error(); - } - } -} -void DallasComponent::dump_config() { - ESP_LOGCONFIG(TAG, "DallasComponent:"); - LOG_PIN(" Pin: ", this->pin_); - LOG_UPDATE_INTERVAL(this); - - if (this->found_sensors_.empty()) { - ESP_LOGW(TAG, " Found no sensors!"); - } else { - ESP_LOGD(TAG, " Found sensors:"); - for (auto &address : this->found_sensors_) { - ESP_LOGD(TAG, " 0x%s", format_hex(address).c_str()); - } - } - - for (auto *sensor : this->sensors_) { - LOG_SENSOR(" ", "Device", sensor); - if (sensor->get_index().has_value()) { - ESP_LOGCONFIG(TAG, " Index %u", *sensor->get_index()); - if (*sensor->get_index() >= this->found_sensors_.size()) { - ESP_LOGE(TAG, "Couldn't find sensor by index - not connected. Proceeding without it."); - continue; - } - } - ESP_LOGCONFIG(TAG, " Address: %s", sensor->get_address_name().c_str()); - ESP_LOGCONFIG(TAG, " Resolution: %u", sensor->get_resolution()); - } -} - -void DallasComponent::register_sensor(DallasTemperatureSensor *sensor) { this->sensors_.push_back(sensor); } -void DallasComponent::update() { - this->status_clear_warning(); - - bool result; - { - InterruptLock lock; - result = this->one_wire_->reset(); - } - if (!result) { - if (!this->found_sensors_.empty()) { - // Only log error if at the start sensors were found (and thus are disconnected during uptime) - ESP_LOGE(TAG, "Requesting conversion failed"); - this->status_set_warning(); - } - - for (auto *sensor : this->sensors_) { - sensor->publish_state(NAN); - } - return; - } - - { - InterruptLock lock; - this->one_wire_->skip(); - this->one_wire_->write8(DALLAS_COMMAND_START_CONVERSION); - } - - for (auto *sensor : this->sensors_) { - if (sensor->get_address() == 0) { - ESP_LOGV(TAG, "'%s' - Indexed sensor not found at startup, skipping update", sensor->get_name().c_str()); - sensor->publish_state(NAN); - continue; - } - - this->set_timeout(sensor->get_address_name(), sensor->millis_to_wait_for_conversion(), [this, sensor] { - bool res = sensor->read_scratch_pad(); - - if (!res) { - ESP_LOGW(TAG, "'%s' - Resetting bus for read failed!", sensor->get_name().c_str()); - sensor->publish_state(NAN); - this->status_set_warning(); - return; - } - if (!sensor->check_scratch_pad()) { - sensor->publish_state(NAN); - this->status_set_warning(); - return; - } - - float tempc = sensor->get_temp_c(); - ESP_LOGD(TAG, "'%s': Got Temperature=%.1f°C", sensor->get_name().c_str(), tempc); - sensor->publish_state(tempc); - }); - } -} - -void DallasTemperatureSensor::set_address(uint64_t address) { this->address_ = address; } -uint8_t DallasTemperatureSensor::get_resolution() const { return this->resolution_; } -void DallasTemperatureSensor::set_resolution(uint8_t resolution) { this->resolution_ = resolution; } -optional DallasTemperatureSensor::get_index() const { return this->index_; } -void DallasTemperatureSensor::set_index(uint8_t index) { this->index_ = index; } -uint8_t *DallasTemperatureSensor::get_address8() { return reinterpret_cast(&this->address_); } -uint64_t DallasTemperatureSensor::get_address() { return this->address_; } - -const std::string &DallasTemperatureSensor::get_address_name() { - if (this->address_name_.empty()) { - this->address_name_ = std::string("0x") + format_hex(this->address_); - } - - return this->address_name_; -} -bool IRAM_ATTR DallasTemperatureSensor::read_scratch_pad() { - auto *wire = this->parent_->one_wire_; - - { - InterruptLock lock; - - if (!wire->reset()) { - return false; - } - - wire->select(this->address_); - wire->write8(DALLAS_COMMAND_READ_SCRATCH_PAD); - - for (unsigned char &i : this->scratch_pad_) { - i = wire->read8(); - } - } - - return true; -} -bool DallasTemperatureSensor::setup_sensor() { - bool r = this->read_scratch_pad(); - - if (!r) { - ESP_LOGE(TAG, "Reading scratchpad failed: reset"); - return false; - } - if (!this->check_scratch_pad()) - return false; - - if (this->scratch_pad_[4] == this->resolution_) - return false; - - if (this->get_address8()[0] == DALLAS_MODEL_DS18S20) { - // DS18S20 doesn't support resolution. - ESP_LOGW(TAG, "DS18S20 doesn't support setting resolution."); - return false; - } - - switch (this->resolution_) { - case 12: - this->scratch_pad_[4] = 0x7F; - break; - case 11: - this->scratch_pad_[4] = 0x5F; - break; - case 10: - this->scratch_pad_[4] = 0x3F; - break; - case 9: - default: - this->scratch_pad_[4] = 0x1F; - break; - } - - auto *wire = this->parent_->one_wire_; - { - InterruptLock lock; - if (wire->reset()) { - wire->select(this->address_); - wire->write8(DALLAS_COMMAND_WRITE_SCRATCH_PAD); - wire->write8(this->scratch_pad_[2]); // high alarm temp - wire->write8(this->scratch_pad_[3]); // low alarm temp - wire->write8(this->scratch_pad_[4]); // resolution - wire->reset(); - - // write value to EEPROM - wire->select(this->address_); - wire->write8(0x48); - } - } - - delay(20); // allow it to finish operation - wire->reset(); - return true; -} -bool DallasTemperatureSensor::check_scratch_pad() { - bool chksum_validity = (crc8(this->scratch_pad_, 8) == this->scratch_pad_[8]); - bool config_validity = false; - - switch (this->get_address8()[0]) { - case DALLAS_MODEL_DS18B20: - config_validity = ((this->scratch_pad_[4] & 0x9F) == 0x1F); - break; - default: - config_validity = ((this->scratch_pad_[4] & 0x10) == 0x10); - } - -#ifdef ESPHOME_LOG_LEVEL_VERY_VERBOSE - ESP_LOGVV(TAG, "Scratch pad: %02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X (%02X)", this->scratch_pad_[0], - this->scratch_pad_[1], this->scratch_pad_[2], this->scratch_pad_[3], this->scratch_pad_[4], - this->scratch_pad_[5], this->scratch_pad_[6], this->scratch_pad_[7], this->scratch_pad_[8], - crc8(this->scratch_pad_, 8)); -#endif - if (!chksum_validity) { - ESP_LOGW(TAG, "'%s' - Scratch pad checksum invalid!", this->get_name().c_str()); - } else if (!config_validity) { - ESP_LOGW(TAG, "'%s' - Scratch pad config register invalid!", this->get_name().c_str()); - } - return chksum_validity && config_validity; -} -float DallasTemperatureSensor::get_temp_c() { - int16_t temp = (int16_t(this->scratch_pad_[1]) << 11) | (int16_t(this->scratch_pad_[0]) << 3); - if (this->get_address8()[0] == DALLAS_MODEL_DS18S20) { - int diff = (this->scratch_pad_[7] - this->scratch_pad_[6]) << 7; - temp = ((temp & 0xFFF0) << 3) - 16 + (diff / this->scratch_pad_[7]); - } - - return temp / 128.0f; -} -std::string DallasTemperatureSensor::unique_id() { return "dallas-" + str_lower_case(format_hex(this->address_)); } - -} // namespace dallas -} // namespace esphome diff --git a/esphome/components/dallas/dallas_component.h b/esphome/components/dallas/dallas_component.h deleted file mode 100644 index 10bde7338b..0000000000 --- a/esphome/components/dallas/dallas_component.h +++ /dev/null @@ -1,79 +0,0 @@ -#pragma once - -#include "esphome/core/component.h" -#include "esphome/components/sensor/sensor.h" -#include "esp_one_wire.h" - -#include - -namespace esphome { -namespace dallas { - -class DallasTemperatureSensor; - -class DallasComponent : public PollingComponent { - public: - void set_pin(InternalGPIOPin *pin) { pin_ = pin; } - void register_sensor(DallasTemperatureSensor *sensor); - - void setup() override; - void dump_config() override; - float get_setup_priority() const override { return setup_priority::DATA; } - - void update() override; - - protected: - friend DallasTemperatureSensor; - - InternalGPIOPin *pin_; - ESPOneWire *one_wire_; - std::vector sensors_; - std::vector found_sensors_; -}; - -/// Internal class that helps us create multiple sensors for one Dallas hub. -class DallasTemperatureSensor : public sensor::Sensor { - public: - void set_parent(DallasComponent *parent) { parent_ = parent; } - /// Helper to get a pointer to the address as uint8_t. - uint8_t *get_address8(); - uint64_t get_address(); - /// Helper to create (and cache) the name for this sensor. For example "0xfe0000031f1eaf29". - const std::string &get_address_name(); - - /// Set the 64-bit unsigned address for this sensor. - void set_address(uint64_t address); - /// Get the index of this sensor. (0 if using address.) - optional get_index() const; - /// Set the index of this sensor. If using index, address will be set after setup. - void set_index(uint8_t index); - /// Get the set resolution for this sensor. - uint8_t get_resolution() const; - /// Set the resolution for this sensor. - void set_resolution(uint8_t resolution); - /// Get the number of milliseconds we have to wait for the conversion phase. - uint16_t millis_to_wait_for_conversion() const; - - bool setup_sensor(); - bool read_scratch_pad(); - - bool check_scratch_pad(); - - float get_temp_c(); - - std::string unique_id() override; - - protected: - DallasComponent *parent_; - uint64_t address_; - optional index_; - - uint8_t resolution_; - std::string address_name_; - uint8_t scratch_pad_[9] = { - 0, - }; -}; - -} // namespace dallas -} // namespace esphome diff --git a/esphome/components/dallas/esp_one_wire.cpp b/esphome/components/dallas/esp_one_wire.cpp deleted file mode 100644 index 32ddf07fb6..0000000000 --- a/esphome/components/dallas/esp_one_wire.cpp +++ /dev/null @@ -1,252 +0,0 @@ -#include "esp_one_wire.h" -#include "esphome/core/log.h" -#include "esphome/core/helpers.h" - -namespace esphome { -namespace dallas { - -static const char *const TAG = "dallas.one_wire"; - -const uint8_t ONE_WIRE_ROM_SELECT = 0x55; -const int ONE_WIRE_ROM_SEARCH = 0xF0; - -ESPOneWire::ESPOneWire(InternalGPIOPin *pin) { pin_ = pin->to_isr(); } - -bool HOT IRAM_ATTR ESPOneWire::reset() { - // See reset here: - // https://www.maximintegrated.com/en/design/technical-documents/app-notes/1/126.html - // Wait for communication to clear (delay G) - pin_.pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP); - uint8_t retries = 125; - do { - if (--retries == 0) - return false; - delayMicroseconds(2); - } while (!pin_.digital_read()); - - // Send 480µs LOW TX reset pulse (drive bus low, delay H) - pin_.pin_mode(gpio::FLAG_OUTPUT); - pin_.digital_write(false); - delayMicroseconds(480); - - // Release the bus, delay I - pin_.pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP); - delayMicroseconds(70); - - // sample bus, 0=device(s) present, 1=no device present - bool r = !pin_.digital_read(); - // delay J - delayMicroseconds(410); - return r; -} - -void HOT IRAM_ATTR ESPOneWire::write_bit(bool bit) { - // drive bus low - pin_.pin_mode(gpio::FLAG_OUTPUT); - pin_.digital_write(false); - - // from datasheet: - // write 0 low time: t_low0: min=60µs, max=120µs - // write 1 low time: t_low1: min=1µs, max=15µs - // time slot: t_slot: min=60µs, max=120µs - // recovery time: t_rec: min=1µs - // ds18b20 appears to read the bus after roughly 14µs - uint32_t delay0 = bit ? 6 : 60; - uint32_t delay1 = bit ? 54 : 5; - - // delay A/C - delayMicroseconds(delay0); - // release bus - pin_.digital_write(true); - // delay B/D - delayMicroseconds(delay1); -} - -bool HOT IRAM_ATTR ESPOneWire::read_bit() { - // drive bus low - pin_.pin_mode(gpio::FLAG_OUTPUT); - pin_.digital_write(false); - - // note: for reading we'll need very accurate timing, as the - // timing for the digital_read() is tight; according to the datasheet, - // we should read at the end of 16µs starting from the bus low - // typically, the ds18b20 pulls the line high after 11µs for a logical 1 - // and 29µs for a logical 0 - - uint32_t start = micros(); - // datasheet says >1µs - delayMicroseconds(3); - - // release bus, delay E - pin_.pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP); - - // Unfortunately some frameworks have different characteristics than others - // esp32 arduino appears to pull the bus low only after the digital_write(false), - // whereas on esp-idf it already happens during the pin_mode(OUTPUT) - // manually correct for this with these constants. - -#ifdef USE_ESP32 - uint32_t timing_constant = 12; -#else - uint32_t timing_constant = 14; -#endif - - // measure from start value directly, to get best accurate timing no matter - // how long pin_mode/delayMicroseconds took - while (micros() - start < timing_constant) - ; - - // sample bus to read bit from peer - bool r = pin_.digital_read(); - - // read slot is at least 60µs; get as close to 60µs to spend less time with interrupts locked - uint32_t now = micros(); - if (now - start < 60) - delayMicroseconds(60 - (now - start)); - - return r; -} - -void IRAM_ATTR ESPOneWire::write8(uint8_t val) { - for (uint8_t i = 0; i < 8; i++) { - this->write_bit(bool((1u << i) & val)); - } -} - -void IRAM_ATTR ESPOneWire::write64(uint64_t val) { - for (uint8_t i = 0; i < 64; i++) { - this->write_bit(bool((1ULL << i) & val)); - } -} - -uint8_t IRAM_ATTR ESPOneWire::read8() { - uint8_t ret = 0; - for (uint8_t i = 0; i < 8; i++) { - ret |= (uint8_t(this->read_bit()) << i); - } - return ret; -} -uint64_t IRAM_ATTR ESPOneWire::read64() { - uint64_t ret = 0; - for (uint8_t i = 0; i < 8; i++) { - ret |= (uint64_t(this->read_bit()) << i); - } - return ret; -} -void IRAM_ATTR ESPOneWire::select(uint64_t address) { - this->write8(ONE_WIRE_ROM_SELECT); - this->write64(address); -} -void IRAM_ATTR ESPOneWire::reset_search() { - this->last_discrepancy_ = 0; - this->last_device_flag_ = false; - this->rom_number_ = 0; -} -uint64_t IRAM_ATTR ESPOneWire::search() { - if (this->last_device_flag_) { - return 0u; - } - - { - InterruptLock lock; - if (!this->reset()) { - // Reset failed or no devices present - this->reset_search(); - return 0u; - } - } - - uint8_t id_bit_number = 1; - uint8_t last_zero = 0; - uint8_t rom_byte_number = 0; - bool search_result = false; - uint8_t rom_byte_mask = 1; - - { - InterruptLock lock; - // Initiate search - this->write8(ONE_WIRE_ROM_SEARCH); - do { - // read bit - bool id_bit = this->read_bit(); - // read its complement - bool cmp_id_bit = this->read_bit(); - - if (id_bit && cmp_id_bit) { - // No devices participating in search - break; - } - - bool branch; - - if (id_bit != cmp_id_bit) { - // only chose one branch, the other one doesn't have any devices. - branch = id_bit; - } else { - // there are devices with both 0s and 1s at this bit - if (id_bit_number < this->last_discrepancy_) { - branch = (this->rom_number8_()[rom_byte_number] & rom_byte_mask) > 0; - } else { - branch = id_bit_number == this->last_discrepancy_; - } - - if (!branch) { - last_zero = id_bit_number; - } - } - - if (branch) { - // set bit - this->rom_number8_()[rom_byte_number] |= rom_byte_mask; - } else { - // clear bit - this->rom_number8_()[rom_byte_number] &= ~rom_byte_mask; - } - - // choose/announce branch - this->write_bit(branch); - id_bit_number++; - rom_byte_mask <<= 1; - if (rom_byte_mask == 0u) { - // go to next byte - rom_byte_number++; - rom_byte_mask = 1; - } - } while (rom_byte_number < 8); // loop through all bytes - } - - if (id_bit_number >= 65) { - this->last_discrepancy_ = last_zero; - if (this->last_discrepancy_ == 0) { - // we're at root and have no choices left, so this was the last one. - this->last_device_flag_ = true; - } - search_result = true; - } - - search_result = search_result && (this->rom_number8_()[0] != 0); - if (!search_result) { - this->reset_search(); - return 0u; - } - - return this->rom_number_; -} -std::vector ESPOneWire::search_vec() { - std::vector res; - - this->reset_search(); - uint64_t address; - while ((address = this->search()) != 0u) - res.push_back(address); - - return res; -} -void IRAM_ATTR ESPOneWire::skip() { - this->write8(0xCC); // skip ROM -} - -uint8_t IRAM_ATTR *ESPOneWire::rom_number8_() { return reinterpret_cast(&this->rom_number_); } - -} // namespace dallas -} // namespace esphome diff --git a/esphome/components/dallas/esp_one_wire.h b/esphome/components/dallas/esp_one_wire.h deleted file mode 100644 index 7544a6fe98..0000000000 --- a/esphome/components/dallas/esp_one_wire.h +++ /dev/null @@ -1,68 +0,0 @@ -#pragma once - -#include "esphome/core/hal.h" -#include - -namespace esphome { -namespace dallas { - -extern const uint8_t ONE_WIRE_ROM_SELECT; -extern const int ONE_WIRE_ROM_SEARCH; - -class ESPOneWire { - public: - explicit ESPOneWire(InternalGPIOPin *pin); - - /** Reset the bus, should be done before all write operations. - * - * Takes approximately 1ms. - * - * @return Whether the operation was successful. - */ - bool reset(); - - /// Write a single bit to the bus, takes about 70µs. - void write_bit(bool bit); - - /// Read a single bit from the bus, takes about 70µs - bool read_bit(); - - /// Write a word to the bus. LSB first. - void write8(uint8_t val); - - /// Write a 64 bit unsigned integer to the bus. LSB first. - void write64(uint64_t val); - - /// Write a command to the bus that addresses all devices by skipping the ROM. - void skip(); - - /// Read an 8 bit word from the bus. - uint8_t read8(); - - /// Read an 64-bit unsigned integer from the bus. - uint64_t read64(); - - /// Select a specific address on the bus for the following command. - void select(uint64_t address); - - /// Reset the device search. - void reset_search(); - - /// Search for a 1-Wire device on the bus. Returns 0 if all devices have been found. - uint64_t search(); - - /// Helper that wraps search in a std::vector. - std::vector search_vec(); - - protected: - /// Helper to get the internal 64-bit unsigned rom number as a 8-bit integer pointer. - inline uint8_t *rom_number8_(); - - ISRInternalGPIOPin pin_; - uint8_t last_discrepancy_{0}; - bool last_device_flag_{false}; - uint64_t rom_number_{0}; -}; - -} // namespace dallas -} // namespace esphome diff --git a/esphome/components/dallas/sensor.py b/esphome/components/dallas/sensor.py index c6ebda62c8..69f8fc3b9e 100644 --- a/esphome/components/dallas/sensor.py +++ b/esphome/components/dallas/sensor.py @@ -1,50 +1,5 @@ -import esphome.codegen as cg import esphome.config_validation as cv -from esphome.components import sensor -from esphome.const import ( - CONF_ADDRESS, - CONF_DALLAS_ID, - CONF_INDEX, - CONF_RESOLUTION, - DEVICE_CLASS_TEMPERATURE, - STATE_CLASS_MEASUREMENT, - UNIT_CELSIUS, + +CONFIG_SCHEMA = cv.invalid( + 'The "dallas" sensor is now "dallas_temp"\nhttps://esphome.io/components/sensor/dallas_temp' ) -from . import DallasComponent, dallas_ns - -DallasTemperatureSensor = dallas_ns.class_("DallasTemperatureSensor", sensor.Sensor) - -CONFIG_SCHEMA = cv.All( - sensor.sensor_schema( - DallasTemperatureSensor, - unit_of_measurement=UNIT_CELSIUS, - accuracy_decimals=1, - device_class=DEVICE_CLASS_TEMPERATURE, - state_class=STATE_CLASS_MEASUREMENT, - ).extend( - { - cv.GenerateID(CONF_DALLAS_ID): cv.use_id(DallasComponent), - cv.Optional(CONF_ADDRESS): cv.hex_uint64_t, - cv.Optional(CONF_INDEX): cv.positive_int, - cv.Optional(CONF_RESOLUTION, default=12): cv.int_range(min=9, max=12), - } - ), - cv.has_exactly_one_key(CONF_ADDRESS, CONF_INDEX), -) - - -async def to_code(config): - hub = await cg.get_variable(config[CONF_DALLAS_ID]) - var = await sensor.new_sensor(config) - - if CONF_ADDRESS in config: - cg.add(var.set_address(config[CONF_ADDRESS])) - else: - cg.add(var.set_index(config[CONF_INDEX])) - - if CONF_RESOLUTION in config: - cg.add(var.set_resolution(config[CONF_RESOLUTION])) - - cg.add(var.set_parent(hub)) - - cg.add(hub.register_sensor(var)) diff --git a/esphome/components/dallas_temp/__init__.py b/esphome/components/dallas_temp/__init__.py new file mode 100644 index 0000000000..3f73044ca8 --- /dev/null +++ b/esphome/components/dallas_temp/__init__.py @@ -0,0 +1 @@ +CODEOWNERS = ["@ssieb"] diff --git a/esphome/components/dallas_temp/dallas_temp.cpp b/esphome/components/dallas_temp/dallas_temp.cpp new file mode 100644 index 0000000000..fe7c9a95ea --- /dev/null +++ b/esphome/components/dallas_temp/dallas_temp.cpp @@ -0,0 +1,172 @@ +#include "dallas_temp.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace dallas_temp { + +static const char *const TAG = "dallas.temp.sensor"; + +static const uint8_t DALLAS_MODEL_DS18S20 = 0x10; +static const uint8_t DALLAS_COMMAND_START_CONVERSION = 0x44; +static const uint8_t DALLAS_COMMAND_READ_SCRATCH_PAD = 0xBE; +static const uint8_t DALLAS_COMMAND_WRITE_SCRATCH_PAD = 0x4E; +static const uint8_t DALLAS_COMMAND_COPY_SCRATCH_PAD = 0x48; + +uint16_t DallasTemperatureSensor::millis_to_wait_for_conversion_() const { + switch (this->resolution_) { + case 9: + return 94; + case 10: + return 188; + case 11: + return 375; + default: + return 750; + } +} + +void DallasTemperatureSensor::dump_config() { + ESP_LOGCONFIG(TAG, "Dallas Temperature Sensor:"); + if (this->address_ == 0) { + ESP_LOGW(TAG, " Unable to select an address"); + return; + } + LOG_ONE_WIRE_DEVICE(this); + ESP_LOGCONFIG(TAG, " Resolution: %u bits", this->resolution_); + LOG_UPDATE_INTERVAL(this); +} + +void DallasTemperatureSensor::update() { + if (this->address_ == 0) + return; + + this->status_clear_warning(); + + this->send_command_(DALLAS_COMMAND_START_CONVERSION); + + this->set_timeout(this->get_address_name(), this->millis_to_wait_for_conversion_(), [this] { + if (!this->read_scratch_pad_() || !this->check_scratch_pad_()) { + this->publish_state(NAN); + return; + } + + float tempc = this->get_temp_c_(); + ESP_LOGD(TAG, "'%s': Got Temperature=%.1f°C", this->get_name().c_str(), tempc); + this->publish_state(tempc); + }); +} + +void IRAM_ATTR DallasTemperatureSensor::read_scratch_pad_int_() { + for (uint8_t &i : this->scratch_pad_) { + i = this->bus_->read8(); + } +} + +bool DallasTemperatureSensor::read_scratch_pad_() { + bool success; + { + InterruptLock lock; + success = this->send_command_(DALLAS_COMMAND_READ_SCRATCH_PAD); + if (success) + this->read_scratch_pad_int_(); + } + if (!success) { + ESP_LOGW(TAG, "'%s' - reading scratch pad failed bus reset", this->get_name().c_str()); + this->status_set_warning("bus reset failed"); + } + return success; +} + +void DallasTemperatureSensor::setup() { + ESP_LOGCONFIG(TAG, "setting up Dallas temperature sensor..."); + if (!this->check_address_()) + return; + if (!this->read_scratch_pad_()) + return; + if (!this->check_scratch_pad_()) + return; + + if ((this->address_ & 0xff) == DALLAS_MODEL_DS18S20) { + // DS18S20 doesn't support resolution. + ESP_LOGW(TAG, "DS18S20 doesn't support setting resolution."); + return; + } + + uint8_t res; + switch (this->resolution_) { + case 12: + res = 0x7F; + break; + case 11: + res = 0x5F; + break; + case 10: + res = 0x3F; + break; + case 9: + default: + res = 0x1F; + break; + } + + if (this->scratch_pad_[4] == res) + return; + this->scratch_pad_[4] = res; + + { + InterruptLock lock; + if (this->send_command_(DALLAS_COMMAND_WRITE_SCRATCH_PAD)) { + this->bus_->write8(this->scratch_pad_[2]); // high alarm temp + this->bus_->write8(this->scratch_pad_[3]); // low alarm temp + this->bus_->write8(this->scratch_pad_[4]); // resolution + } + + // write value to EEPROM + this->send_command_(DALLAS_COMMAND_COPY_SCRATCH_PAD); + } +} + +bool DallasTemperatureSensor::check_scratch_pad_() { + bool chksum_validity = (crc8(this->scratch_pad_, 8) == this->scratch_pad_[8]); + +#ifdef ESPHOME_LOG_LEVEL_VERY_VERBOSE + ESP_LOGVV(TAG, "Scratch pad: %02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X (%02X)", this->scratch_pad_[0], + this->scratch_pad_[1], this->scratch_pad_[2], this->scratch_pad_[3], this->scratch_pad_[4], + this->scratch_pad_[5], this->scratch_pad_[6], this->scratch_pad_[7], this->scratch_pad_[8], + crc8(this->scratch_pad_, 8)); +#endif + if (!chksum_validity) { + ESP_LOGW(TAG, "'%s' - Scratch pad checksum invalid!", this->get_name().c_str()); + this->status_set_warning("scratch pad checksum invalid"); + } + return chksum_validity; +} + +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] != 0x10) + ESP_LOGE(TAG, "unexpected COUNT_PER_C value: %u", this->scratch_pad_[7]); + temp = ((temp & 0xfff7) << 3) + (0x10 - this->scratch_pad_[6]) - 4; + } else { + switch (this->resolution_) { + case 9: + temp &= 0xfff8; + break; + case 10: + temp &= 0xfffc; + break; + case 11: + temp &= 0xfffe; + break; + case 12: + default: + break; + } + } + + return temp / 16.0f; +} + +} // namespace dallas_temp +} // namespace esphome diff --git a/esphome/components/dallas_temp/dallas_temp.h b/esphome/components/dallas_temp/dallas_temp.h new file mode 100644 index 0000000000..604c9d0cd7 --- /dev/null +++ b/esphome/components/dallas_temp/dallas_temp.h @@ -0,0 +1,32 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/components/sensor/sensor.h" +#include "esphome/components/one_wire/one_wire.h" + +namespace esphome { +namespace dallas_temp { + +class DallasTemperatureSensor : public PollingComponent, public sensor::Sensor, public one_wire::OneWireDevice { + public: + void setup() override; + void update() override; + void dump_config() override; + + /// Set the resolution for this sensor. + void set_resolution(uint8_t resolution) { this->resolution_ = resolution; } + + protected: + uint8_t resolution_; + uint8_t scratch_pad_[9] = {0}; + + /// Get the number of milliseconds we have to wait for the conversion phase. + uint16_t millis_to_wait_for_conversion_() const; + bool read_scratch_pad_(); + void read_scratch_pad_int_(); + bool check_scratch_pad_(); + float get_temp_c_(); +}; + +} // namespace dallas_temp +} // namespace esphome diff --git a/esphome/components/dallas_temp/sensor.py b/esphome/components/dallas_temp/sensor.py new file mode 100644 index 0000000000..ab14a9afd5 --- /dev/null +++ b/esphome/components/dallas_temp/sensor.py @@ -0,0 +1,43 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import one_wire, sensor +from esphome.const import ( + CONF_RESOLUTION, + DEVICE_CLASS_TEMPERATURE, + STATE_CLASS_MEASUREMENT, + UNIT_CELSIUS, +) + +dallas_temp_ns = cg.esphome_ns.namespace("dallas_temp") + +DallasTemperatureSensor = dallas_temp_ns.class_( + "DallasTemperatureSensor", + cg.PollingComponent, + sensor.Sensor, + one_wire.OneWireDevice, +) + +CONFIG_SCHEMA = ( + sensor.sensor_schema( + DallasTemperatureSensor, + unit_of_measurement=UNIT_CELSIUS, + accuracy_decimals=1, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + ) + .extend( + { + cv.Optional(CONF_RESOLUTION, default=12): cv.int_range(min=9, max=12), + } + ) + .extend(one_wire.one_wire_device_schema()) + .extend(cv.polling_component_schema("60s")) +) + + +async def to_code(config): + var = await sensor.new_sensor(config) + await cg.register_component(var, config) + await one_wire.register_one_wire_device(var, config) + + cg.add(var.set_resolution(config[CONF_RESOLUTION])) diff --git a/esphome/components/gpio/one_wire/__init__.py b/esphome/components/gpio/one_wire/__init__.py new file mode 100644 index 0000000000..2166e92083 --- /dev/null +++ b/esphome/components/gpio/one_wire/__init__.py @@ -0,0 +1,25 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome import pins +from esphome.const import CONF_ID, CONF_PIN +from esphome.components.one_wire import OneWireBus +from .. import gpio_ns + +CODEOWNERS = ["@ssieb"] + +GPIOOneWireBus = gpio_ns.class_("GPIOOneWireBus", OneWireBus, cg.Component) + +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.declare_id(GPIOOneWireBus), + cv.Required(CONF_PIN): pins.internal_gpio_output_pin_schema, + } +).extend(cv.COMPONENT_SCHEMA) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, config) + + pin = await cg.gpio_pin_expression(config[CONF_PIN]) + cg.add(var.set_pin(pin)) diff --git a/esphome/components/gpio/one_wire/gpio_one_wire.cpp b/esphome/components/gpio/one_wire/gpio_one_wire.cpp new file mode 100644 index 0000000000..f47e8d58e3 --- /dev/null +++ b/esphome/components/gpio/one_wire/gpio_one_wire.cpp @@ -0,0 +1,199 @@ +#include "gpio_one_wire.h" +#include "esphome/core/log.h" +#include "esphome/core/helpers.h" + +namespace esphome { +namespace gpio { + +static const char *const TAG = "gpio.one_wire"; + +void GPIOOneWireBus::setup() { + ESP_LOGCONFIG(TAG, "Setting up 1-wire bus..."); + this->search(); +} + +void GPIOOneWireBus::dump_config() { + ESP_LOGCONFIG(TAG, "GPIO 1-wire bus:"); + LOG_PIN(" Pin: ", this->t_pin_); + this->dump_devices_(TAG); +} + +bool HOT IRAM_ATTR GPIOOneWireBus::reset() { + // See reset here: + // https://www.maximintegrated.com/en/design/technical-documents/app-notes/1/126.html + // Wait for communication to clear (delay G) + pin_.pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP); + uint8_t retries = 125; + do { + if (--retries == 0) + return false; + delayMicroseconds(2); + } while (!pin_.digital_read()); + + bool r; + + // Send 480µs LOW TX reset pulse (drive bus low, delay H) + pin_.pin_mode(gpio::FLAG_OUTPUT); + pin_.digital_write(false); + delayMicroseconds(480); + + // Release the bus, delay I + pin_.pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP); + delayMicroseconds(70); + + // sample bus, 0=device(s) present, 1=no device present + r = !pin_.digital_read(); + // delay J + delayMicroseconds(410); + return r; +} + +void HOT IRAM_ATTR GPIOOneWireBus::write_bit_(bool bit) { + // drive bus low + pin_.pin_mode(gpio::FLAG_OUTPUT); + pin_.digital_write(false); + + // from datasheet: + // write 0 low time: t_low0: min=60µs, max=120µs + // write 1 low time: t_low1: min=1µs, max=15µs + // time slot: t_slot: min=60µs, max=120µs + // recovery time: t_rec: min=1µs + // ds18b20 appears to read the bus after roughly 14µs + uint32_t delay0 = bit ? 6 : 60; + uint32_t delay1 = bit ? 54 : 5; + + // delay A/C + delayMicroseconds(delay0); + // release bus + pin_.digital_write(true); + // delay B/D + delayMicroseconds(delay1); +} + +bool HOT IRAM_ATTR GPIOOneWireBus::read_bit_() { + // drive bus low + pin_.pin_mode(gpio::FLAG_OUTPUT); + pin_.digital_write(false); + + // note: for reading we'll need very accurate timing, as the + // timing for the digital_read() is tight; according to the datasheet, + // we should read at the end of 16µs starting from the bus low + // typically, the ds18b20 pulls the line high after 11µs for a logical 1 + // and 29µs for a logical 0 + + uint32_t start = micros(); + // datasheet says >1µs + delayMicroseconds(2); + + // release bus, delay E + pin_.pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP); + + // measure from start value directly, to get best accurate timing no matter + // how long pin_mode/delayMicroseconds took + delayMicroseconds(12 - (micros() - start)); + + // sample bus to read bit from peer + bool r = pin_.digital_read(); + + // read slot is at least 60µs; get as close to 60µs to spend less time with interrupts locked + uint32_t now = micros(); + if (now - start < 60) + delayMicroseconds(60 - (now - start)); + + return r; +} + +void IRAM_ATTR GPIOOneWireBus::write8(uint8_t val) { + for (uint8_t i = 0; i < 8; i++) { + this->write_bit_(bool((1u << i) & val)); + } +} + +void IRAM_ATTR GPIOOneWireBus::write64(uint64_t val) { + for (uint8_t i = 0; i < 64; i++) { + this->write_bit_(bool((1ULL << i) & val)); + } +} + +uint8_t IRAM_ATTR GPIOOneWireBus::read8() { + uint8_t ret = 0; + for (uint8_t i = 0; i < 8; i++) { + ret |= (uint8_t(this->read_bit_()) << i); + } + return ret; +} + +uint64_t IRAM_ATTR GPIOOneWireBus::read64() { + uint64_t ret = 0; + for (uint8_t i = 0; i < 8; i++) { + ret |= (uint64_t(this->read_bit_()) << i); + } + return ret; +} + +void GPIOOneWireBus::reset_search() { + this->last_discrepancy_ = 0; + this->last_device_flag_ = false; + this->address_ = 0; +} + +uint64_t IRAM_ATTR GPIOOneWireBus::search_int() { + if (this->last_device_flag_) + return 0u; + + uint8_t last_zero = 0; + uint64_t bit_mask = 1; + uint64_t address = this->address_; + + // Initiate search + for (int bit_number = 1; bit_number <= 64; bit_number++, bit_mask <<= 1) { + // read bit + bool id_bit = this->read_bit_(); + // read its complement + bool cmp_id_bit = this->read_bit_(); + + if (id_bit && cmp_id_bit) { + // No devices participating in search + return 0; + } + + bool branch; + + if (id_bit != cmp_id_bit) { + // only chose one branch, the other one doesn't have any devices. + branch = id_bit; + } else { + // there are devices with both 0s and 1s at this bit + if (bit_number < this->last_discrepancy_) { + branch = (address & bit_mask) > 0; + } else { + branch = bit_number == this->last_discrepancy_; + } + + if (!branch) { + last_zero = bit_number; + } + } + + if (branch) { + address |= bit_mask; + } else { + address &= ~bit_mask; + } + + // choose/announce branch + this->write_bit_(branch); + } + + this->last_discrepancy_ = last_zero; + if (this->last_discrepancy_ == 0) { + // we're at root and have no choices left, so this was the last one. + this->last_device_flag_ = true; + } + + this->address_ = address; + return address; +} + +} // namespace gpio +} // namespace esphome diff --git a/esphome/components/gpio/one_wire/gpio_one_wire.h b/esphome/components/gpio/one_wire/gpio_one_wire.h new file mode 100644 index 0000000000..fe949baec3 --- /dev/null +++ b/esphome/components/gpio/one_wire/gpio_one_wire.h @@ -0,0 +1,41 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/core/hal.h" +#include "esphome/components/one_wire/one_wire.h" + +namespace esphome { +namespace gpio { + +class GPIOOneWireBus : public one_wire::OneWireBus, public Component { + public: + void setup() override; + void dump_config() override; + float get_setup_priority() const override { return setup_priority::BUS; } + + void set_pin(InternalGPIOPin *pin) { + this->t_pin_ = pin; + this->pin_ = pin->to_isr(); + } + + bool reset() override; + void write8(uint8_t val) override; + void write64(uint64_t val) override; + uint8_t read8() override; + uint64_t read64() override; + + protected: + InternalGPIOPin *t_pin_; + ISRInternalGPIOPin pin_; + uint8_t last_discrepancy_{0}; + bool last_device_flag_{false}; + uint64_t address_; + + void reset_search() override; + uint64_t search_int() override; + void write_bit_(bool bit); + bool read_bit_(); +}; + +} // namespace gpio +} // namespace esphome diff --git a/esphome/components/one_wire/__init__.py b/esphome/components/one_wire/__init__.py new file mode 100644 index 0000000000..99a1ccd1eb --- /dev/null +++ b/esphome/components/one_wire/__init__.py @@ -0,0 +1,40 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.const import CONF_ADDRESS + +CODEOWNERS = ["@ssieb"] + +IS_PLATFORM_COMPONENT = True + +CONF_ONE_WIRE_ID = "one_wire_id" + +one_wire_ns = cg.esphome_ns.namespace("one_wire") +OneWireBus = one_wire_ns.class_("OneWireBus") +OneWireDevice = one_wire_ns.class_("OneWireDevice") + + +def one_wire_device_schema(): + """Create a schema for a 1-wire device. + + :return: The 1-wire device schema, `extend` this in your config schema. + """ + schema = cv.Schema( + { + cv.GenerateID(CONF_ONE_WIRE_ID): cv.use_id(OneWireBus), + cv.Optional(CONF_ADDRESS): cv.hex_uint64_t, + } + ) + return schema + + +async def register_one_wire_device(var, config): + """Register an 1-wire device with the given config. + + Sets the 1-wire bus to use and the 1-wire address. + + This is a coroutine, you need to await it with a 'yield' expression! + """ + parent = await cg.get_variable(config[CONF_ONE_WIRE_ID]) + cg.add(var.set_one_wire_bus(parent)) + if (address := config.get(CONF_ADDRESS)) is not None: + cg.add(var.set_address(address)) diff --git a/esphome/components/one_wire/one_wire.cpp b/esphome/components/one_wire/one_wire.cpp new file mode 100644 index 0000000000..131bc4fbfe --- /dev/null +++ b/esphome/components/one_wire/one_wire.cpp @@ -0,0 +1,40 @@ +#include "one_wire.h" + +namespace esphome { +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_); + return this->address_name_; +} + +std::string OneWireDevice::unique_id() { return "dallas-" + str_lower_case(format_hex(this->address_)); } + +bool OneWireDevice::send_command_(uint8_t cmd) { + if (!this->bus_->select(this->address_)) + return false; + this->bus_->write8(cmd); + return true; +} + +bool OneWireDevice::check_address_() { + if (this->address_ != 0) + return true; + auto devices = this->bus_->get_devices(); + if (devices.empty()) { + ESP_LOGE(TAG, "No devices, can't auto-select address"); + return false; + } + if (devices.size() > 1) { + ESP_LOGE(TAG, "More than one device, can't auto-select address"); + return false; + } + this->address_ = devices[0]; + return true; +} + +} // namespace one_wire +} // namespace esphome diff --git a/esphome/components/one_wire/one_wire.h b/esphome/components/one_wire/one_wire.h new file mode 100644 index 0000000000..bf10e4f82e --- /dev/null +++ b/esphome/components/one_wire/one_wire.h @@ -0,0 +1,44 @@ +#pragma once + +#include "one_wire_bus.h" +#include "esphome/core/helpers.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace one_wire { + +#define LOG_ONE_WIRE_DEVICE(this) \ + ESP_LOGCONFIG(TAG, " Address: %s (%s)", this->get_address_name().c_str(), \ + LOG_STR_ARG(this->bus_->get_model_str(this->address_ & 0xff))); + +class OneWireDevice { + public: + /// @brief store the address of the device + /// @param address of the device + void set_address(uint64_t address) { this->address_ = address; } + + /// @brief store the pointer to the OneWireBus to use + /// @param bus pointer to the OneWireBus object + void set_one_wire_bus(OneWireBus *bus) { this->bus_ = bus; } + + /// Helper to create (and cache) the name for this sensor. For example "0xfe0000031f1eaf29". + const std::string &get_address_name(); + + std::string unique_id(); + + protected: + uint64_t address_{0}; + OneWireBus *bus_{nullptr}; ///< pointer to OneWireBus instance + std::string address_name_; + + /// @brief find an address if necessary + /// should be called from setup + bool check_address_(); + + /// @brief send command on the bus + /// @param cmd command to send + bool send_command_(uint8_t cmd); +}; + +} // namespace one_wire +} // namespace esphome diff --git a/esphome/components/one_wire/one_wire_bus.cpp b/esphome/components/one_wire/one_wire_bus.cpp new file mode 100644 index 0000000000..a8d29428d3 --- /dev/null +++ b/esphome/components/one_wire/one_wire_bus.cpp @@ -0,0 +1,88 @@ +#include "one_wire_bus.h" +#include "esphome/core/helpers.h" + +namespace esphome { +namespace one_wire { + +static const char *const TAG = "one_wire"; + +static const uint8_t DALLAS_MODEL_DS18S20 = 0x10; +static const uint8_t DALLAS_MODEL_DS1822 = 0x22; +static const uint8_t DALLAS_MODEL_DS18B20 = 0x28; +static const uint8_t DALLAS_MODEL_DS1825 = 0x3B; +static const uint8_t DALLAS_MODEL_DS28EA00 = 0x42; + +const uint8_t ONE_WIRE_ROM_SELECT = 0x55; +const uint8_t ONE_WIRE_ROM_SEARCH = 0xF0; + +const std::vector &OneWireBus::get_devices() { return this->devices_; } + +bool IRAM_ATTR OneWireBus::select(uint64_t address) { + if (!this->reset()) + return false; + this->write8(ONE_WIRE_ROM_SELECT); + this->write64(address); + return true; +} + +void OneWireBus::search() { + this->devices_.clear(); + + this->reset_search(); + uint64_t address; + while (true) { + { + InterruptLock lock; + if (!this->reset()) { + // Reset failed or no devices present + return; + } + + this->write8(ONE_WIRE_ROM_SEARCH); + address = this->search_int(); + } + if (address == 0) + break; + auto *address8 = reinterpret_cast(&address); + if (crc8(address8, 7) != address8[7]) { + ESP_LOGW(TAG, "Dallas device 0x%s has invalid CRC.", format_hex(address).c_str()); + } else { + this->devices_.push_back(address); + } + } +} + +void OneWireBus::skip() { + this->write8(0xCC); // skip ROM +} + +const LogString *OneWireBus::get_model_str(uint8_t model) { + switch (model) { + case DALLAS_MODEL_DS18S20: + return LOG_STR("DS18S20"); + case DALLAS_MODEL_DS1822: + return LOG_STR("DS1822"); + case DALLAS_MODEL_DS18B20: + return LOG_STR("DS18B20"); + case DALLAS_MODEL_DS1825: + return LOG_STR("DS1825"); + case DALLAS_MODEL_DS28EA00: + return LOG_STR("DS28EA00"); + default: + return LOG_STR("Unknown"); + } +} + +void OneWireBus::dump_devices_(const char *tag) { + if (this->devices_.empty()) { + ESP_LOGW(tag, " Found no devices!"); + } else { + ESP_LOGCONFIG(tag, " Found devices:"); + for (auto &address : this->devices_) { + ESP_LOGCONFIG(tag, " 0x%s (%s)", format_hex(address).c_str(), LOG_STR_ARG(get_model_str(address & 0xff))); + } + } +} + +} // namespace one_wire +} // namespace esphome diff --git a/esphome/components/one_wire/one_wire_bus.h b/esphome/components/one_wire/one_wire_bus.h new file mode 100644 index 0000000000..6818b17499 --- /dev/null +++ b/esphome/components/one_wire/one_wire_bus.h @@ -0,0 +1,61 @@ +#pragma once + +#include "esphome/core/hal.h" +#include "esphome/core/log.h" +#include + +namespace esphome { +namespace one_wire { + +class OneWireBus { + public: + /** Reset the bus, should be done before all write operations. + * + * Takes approximately 1ms. + * + * @return Whether the operation was successful. + */ + virtual bool reset() = 0; + + /// Write a word to the bus. LSB first. + virtual void write8(uint8_t val) = 0; + + /// Write a 64 bit unsigned integer to the bus. LSB first. + virtual void write64(uint64_t val) = 0; + + /// Write a command to the bus that addresses all devices by skipping the ROM. + void skip(); + + /// Read an 8 bit word from the bus. + virtual uint8_t read8() = 0; + + /// Read an 64-bit unsigned integer from the bus. + virtual uint64_t read64() = 0; + + /// Select a specific address on the bus for the following command. + bool select(uint64_t address); + + /// Return the list of found devices. + const std::vector &get_devices(); + + /// Search for 1-Wire devices on the bus. + void search(); + + /// Get the description string for this model. + const LogString *get_model_str(uint8_t model); + + protected: + std::vector devices_; + + /// log the found devices + void dump_devices_(const char *tag); + + /// Reset the device search. + virtual void reset_search() = 0; + + /// Search for a 1-Wire device on the bus. Returns 0 if all devices have been found. + virtual uint64_t search_int() = 0; +}; + +} // namespace one_wire +} // namespace esphome diff --git a/script/ci-custom.py b/script/ci-custom.py index e2ee81f742..9a97d3e4a8 100755 --- a/script/ci-custom.py +++ b/script/ci-custom.py @@ -630,7 +630,7 @@ def lint_trailing_whitespace(fname, match): "esphome/components/lock/lock.h", "esphome/components/mqtt/mqtt_component.h", "esphome/components/number/number.h", - "esphome/components/text/text.h", + "esphome/components/one_wire/one_wire.h", "esphome/components/output/binary_output.h", "esphome/components/output/float_output.h", "esphome/components/nextion/nextion_base.h", @@ -638,6 +638,7 @@ def lint_trailing_whitespace(fname, match): "esphome/components/sensor/sensor.h", "esphome/components/stepper/stepper.h", "esphome/components/switch/switch.h", + "esphome/components/text/text.h", "esphome/components/text_sensor/text_sensor.h", "esphome/components/valve/valve.h", "esphome/core/component.h", diff --git a/tests/components/dallas/common.yaml b/tests/components/dallas_temp/common.yaml similarity index 55% rename from tests/components/dallas/common.yaml rename to tests/components/dallas_temp/common.yaml index 7975977107..2f846ca278 100644 --- a/tests/components/dallas/common.yaml +++ b/tests/components/dallas_temp/common.yaml @@ -1,11 +1,11 @@ -dallas: - pin: 4 +one_wire: + - platform: gpio + pin: 4 sensor: - - platform: dallas + - platform: dallas_temp address: 0x1C0000031EDD2A28 name: Dallas Temperature resolution: 9 - - platform: dallas - index: 1 + - platform: dallas_temp name: Dallas Temperature diff --git a/tests/components/dallas/test.esp32-c3-idf.yaml b/tests/components/dallas_temp/test.esp32-c3-idf.yaml similarity index 100% rename from tests/components/dallas/test.esp32-c3-idf.yaml rename to tests/components/dallas_temp/test.esp32-c3-idf.yaml diff --git a/tests/components/dallas/test.esp32-c3.yaml b/tests/components/dallas_temp/test.esp32-c3.yaml similarity index 100% rename from tests/components/dallas/test.esp32-c3.yaml rename to tests/components/dallas_temp/test.esp32-c3.yaml diff --git a/tests/components/dallas/test.esp32-idf.yaml b/tests/components/dallas_temp/test.esp32-idf.yaml similarity index 100% rename from tests/components/dallas/test.esp32-idf.yaml rename to tests/components/dallas_temp/test.esp32-idf.yaml diff --git a/tests/components/dallas/test.esp32.yaml b/tests/components/dallas_temp/test.esp32.yaml similarity index 100% rename from tests/components/dallas/test.esp32.yaml rename to tests/components/dallas_temp/test.esp32.yaml diff --git a/tests/components/dallas/test.esp8266.yaml b/tests/components/dallas_temp/test.esp8266.yaml similarity index 100% rename from tests/components/dallas/test.esp8266.yaml rename to tests/components/dallas_temp/test.esp8266.yaml diff --git a/tests/components/dallas/test.rp2040.yaml b/tests/components/dallas_temp/test.rp2040.yaml similarity index 100% rename from tests/components/dallas/test.rp2040.yaml rename to tests/components/dallas_temp/test.rp2040.yaml diff --git a/tests/test1.yaml b/tests/test1.yaml index 2dacfda536..79cb1bba2b 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -315,11 +315,6 @@ as5600: slow_filter: 8x fast_filter: lsb6 -dallas: - pin: - allow_other_uses: true - number: GPIO23 - as3935_spi: cs_pin: ignore_strapping_warning: true @@ -714,13 +709,6 @@ sensor: update_interval: 15s iir_filter: 16x i2c_id: i2c_bus - - platform: dallas - address: 0x1C0000031EDD2A28 - name: Living Room Temperature - resolution: 9 - - platform: dallas - index: 1 - name: Living Room Temperature 2 - platform: dht pin: allow_other_uses: true From e2784d077dea978ba449759be6449f8d9fdde47e Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Wed, 12 Jun 2024 11:09:20 +1000 Subject: [PATCH 1572/2101] [he60r] Don't publish state unless it has changed. [BUGFIX] (#6869) --- esphome/components/he60r/he60r.cpp | 46 ++++++++++++++---------------- esphome/components/he60r/he60r.h | 7 ++--- 2 files changed, 24 insertions(+), 29 deletions(-) diff --git a/esphome/components/he60r/he60r.cpp b/esphome/components/he60r/he60r.cpp index 05f3f528a5..83e895543d 100644 --- a/esphome/components/he60r/he60r.cpp +++ b/esphome/components/he60r/he60r.cpp @@ -56,7 +56,7 @@ void HE60rCover::endstop_reached_(CoverOperation operation) { this->position = new_position; this->current_operation = COVER_OPERATION_IDLE; if (this->last_command_ == operation) { - float dur = (now - this->start_dir_time_) / 1e3f; + float dur = (float) (now - this->start_dir_time_) / 1e3f; ESP_LOGD(TAG, "'%s' - %s endstop reached. Took %.1fs.", this->name_.c_str(), operation == COVER_OPERATION_OPENING ? "Open" : "Close", dur); } @@ -69,7 +69,6 @@ void HE60rCover::set_current_operation_(cover::CoverOperation operation) { this->current_operation = operation; if (operation != COVER_OPERATION_IDLE) this->last_recompute_time_ = millis(); - this->publish_state(); } } @@ -129,7 +128,7 @@ void HE60rCover::update_() { if (this->toggles_needed_ != 0) { if ((this->counter_++ & 0x3) == 0) { this->toggles_needed_--; - ESP_LOGD(TAG, "Writing byte 0x30, still needed=%" PRIu32, this->toggles_needed_); + ESP_LOGD(TAG, "Writing byte 0x30, still needed=%u", this->toggles_needed_); this->write_byte(TOGGLE_BYTE); } else { this->write_byte(QUERY_BYTE); @@ -235,31 +234,28 @@ void HE60rCover::recompute_position_() { return; const uint32_t now = millis(); - float dir; - float action_dur; - - switch (this->current_operation) { - case COVER_OPERATION_OPENING: - dir = 1.0f; - action_dur = this->open_duration_; - break; - case COVER_OPERATION_CLOSING: - dir = -1.0f; - action_dur = this->close_duration_; - break; - default: - return; - } - if (now > this->last_recompute_time_) { - auto diff = now - last_recompute_time_; - auto delta = dir * diff / action_dur; + auto diff = (unsigned) (now - last_recompute_time_); + float delta; + switch (this->current_operation) { + case COVER_OPERATION_OPENING: + delta = (float) diff / (float) this->open_duration_; + break; + case COVER_OPERATION_CLOSING: + delta = -(float) diff / (float) this->close_duration_; + break; + default: + return; + } + // make sure our guesstimate never reaches full open or close. - this->position = clamp(delta + this->position, COVER_CLOSED + 0.01f, COVER_OPEN - 0.01f); - ESP_LOGD(TAG, "Recompute %dms, dir=%f, action_dur=%f, delta=%f, pos=%f", (int) diff, dir, action_dur, delta, - this->position); + auto new_position = clamp(delta + this->position, COVER_CLOSED + 0.01f, COVER_OPEN - 0.01f); + ESP_LOGD(TAG, "Recompute %ums, dir=%u, delta=%f, pos=%f", diff, this->current_operation, delta, new_position); this->last_recompute_time_ = now; - this->publish_state(); + if (this->position != new_position) { + this->position = new_position; + this->publish_state(); + } } } diff --git a/esphome/components/he60r/he60r.h b/esphome/components/he60r/he60r.h index 624b61fc65..e41e2203c1 100644 --- a/esphome/components/he60r/he60r.h +++ b/esphome/components/he60r/he60r.h @@ -25,15 +25,14 @@ class HE60rCover : public cover::Cover, public Component, public uart::UARTDevic void control(const cover::CoverCall &call) override; bool is_at_target_() const; void start_direction_(cover::CoverOperation dir); - void update_operation_(cover::CoverOperation dir); void endstop_reached_(cover::CoverOperation operation); void recompute_position_(); void set_current_operation_(cover::CoverOperation operation); void process_rx_(uint8_t data); - uint32_t open_duration_{0}; - uint32_t close_duration_{0}; - uint32_t toggles_needed_{0}; + unsigned open_duration_{0}; + unsigned close_duration_{0}; + unsigned toggles_needed_{0}; cover::CoverOperation next_direction_{cover::COVER_OPERATION_IDLE}; cover::CoverOperation last_command_{cover::COVER_OPERATION_IDLE}; uint32_t last_recompute_time_{0}; From 699d00e21850c813e3f995c7d4fec0411cd58ef7 Mon Sep 17 00:00:00 2001 From: guillempages Date: Wed, 12 Jun 2024 03:11:00 +0200 Subject: [PATCH 1573/2101] [image] Make PIL import local (#6864) --- esphome/components/image/__init__.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/esphome/components/image/__init__.py b/esphome/components/image/__init__.py index b23ed3445a..c275136427 100644 --- a/esphome/components/image/__init__.py +++ b/esphome/components/image/__init__.py @@ -9,8 +9,6 @@ import re import requests from magic import Magic -from PIL import Image - from esphome import core from esphome.components import font from esphome import external_files @@ -267,6 +265,9 @@ CONFIG_SCHEMA = cv.All(font.validate_pillow_installed, IMAGE_SCHEMA) def load_svg_image(file: bytes, resize: tuple[int, int]): + # Local import only to allow "validate_pillow_installed" to run *before* importing it + from PIL import Image + # This import is only needed in case of SVG images; adding it # to the top would force configurations not using SVG to also have it # installed for no reason. @@ -286,6 +287,9 @@ def load_svg_image(file: bytes, resize: tuple[int, int]): async def to_code(config): + # Local import only to allow "validate_pillow_installed" to run *before* importing it + from PIL import Image + conf_file = config[CONF_FILE] if conf_file[CONF_SOURCE] == SOURCE_LOCAL: From 7b9fb57bb22a86a15ae4f637b886ef3e415c75f4 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Wed, 12 Jun 2024 11:15:57 +1000 Subject: [PATCH 1574/2101] [config] Retain path information in validated configuration (#6785) --- esphome/config.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/config.py b/esphome/config.py index 2b231fc402..afb7207edb 100644 --- a/esphome/config.py +++ b/esphome/config.py @@ -23,7 +23,7 @@ from esphome.const import ( CONF_EXTERNAL_COMPONENTS, TARGET_PLATFORMS, ) -from esphome.core import CORE, EsphomeError +from esphome.core import CORE, EsphomeError, DocumentRange from esphome.helpers import indent from esphome.util import safe_print, OrderedDict @@ -184,7 +184,7 @@ class Config(OrderedDict, fv.FinalValidateConfig): def get_deepest_document_range_for_path( self, path: ConfigPath, get_key: bool = False - ) -> ESPHomeDataBase | None: + ) -> DocumentRange | None: data = self doc_range = None for index, path_item in enumerate(path): @@ -1123,4 +1123,4 @@ def read_config(command_line_substitutions): safe_print("") return None - return OrderedDict(res) + return res From 4bf7c9708852758237b8da13c77c5bd568b7cdc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Poczkodi?= Date: Wed, 12 Jun 2024 03:19:18 +0200 Subject: [PATCH 1575/2101] WebSocket overrides check_origin for reverse proxy configuration (#6845) --- esphome/dashboard/web_server.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/esphome/dashboard/web_server.py b/esphome/dashboard/web_server.py index 9ee2312781..33c83ffb1a 100644 --- a/esphome/dashboard/web_server.py +++ b/esphome/dashboard/web_server.py @@ -17,6 +17,7 @@ import time from collections.abc import Iterable from pathlib import Path from typing import TYPE_CHECKING, Any, Callable, TypeVar +from urllib.parse import urlparse import tornado import tornado.concurrent @@ -166,6 +167,18 @@ class EsphomeCommandWebSocket(tornado.websocket.WebSocketHandler): # use Popen() with a reading thread instead self._use_popen = os.name == "nt" + def check_origin(self, origin): + if "ESPHOME_TRUSTED_DOMAINS" not in os.environ: + return super().check_origin(origin) + trusted_domains = [ + s.strip() for s in os.environ["ESPHOME_TRUSTED_DOMAINS"].split(",") + ] + url = urlparse(origin) + if url.hostname in trusted_domains: + return True + _LOGGER.info("check_origin %s, domain is not trusted", origin) + return False + def open(self, *args: str, **kwargs: str) -> None: """Handle new WebSocket connection.""" # Ensure messages from the subprocess are sent immediately From 7c843437a70f825d71e2198bf17fd8e5d1d48db5 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Wed, 12 Jun 2024 11:26:43 +1000 Subject: [PATCH 1576/2101] [config] Early termination of validation steps on error (#6837) --- esphome/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/config.py b/esphome/config.py index afb7207edb..925a31fed0 100644 --- a/esphome/config.py +++ b/esphome/config.py @@ -139,7 +139,7 @@ class Config(OrderedDict, fv.FinalValidateConfig): ) def run_validation_steps(self): - while self._validation_tasks: + while self._validation_tasks and not self.errors: task = heapq.heappop(self._validation_tasks) task.step.run(self) From e2c1af199c4b6504350fb0a133ea450a470165b1 Mon Sep 17 00:00:00 2001 From: Tudor Sandu Date: Tue, 11 Jun 2024 18:39:01 -0700 Subject: [PATCH 1577/2101] Fix media_player.volume_set when media player is not started (#6859) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- .../media_player/i2s_audio_media_player.cpp | 54 ++++++++++--------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/esphome/components/i2s_audio/media_player/i2s_audio_media_player.cpp b/esphome/components/i2s_audio/media_player/i2s_audio_media_player.cpp index 5140a923b4..34ed5b02a0 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 @@ -37,38 +37,14 @@ void I2SAudioMediaPlayer::control(const media_player::MediaPlayerCall &call) { this->set_volume_(volume); this->unmute_(); } - if (this->i2s_state_ != I2S_STATE_RUNNING) { - return; - } if (call.get_command().has_value()) { switch (call.get_command().value()) { - 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_MUTE: this->mute_(); break; case media_player::MEDIA_PLAYER_COMMAND_UNMUTE: this->unmute_(); 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; case media_player::MEDIA_PLAYER_COMMAND_VOLUME_UP: { float new_volume = this->volume + 0.1f; if (new_volume > 1.0f) @@ -85,6 +61,36 @@ void I2SAudioMediaPlayer::control(const media_player::MediaPlayerCall &call) { this->unmute_(); break; } + default: + break; + } + if (this->i2s_state_ != I2S_STATE_RUNNING) { + return; + } + switch (call.get_command().value()) { + 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(); From bc408ad08cc8ba8e8ce90f2cabb7b647377e75e9 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Wed, 12 Jun 2024 11:42:01 +1000 Subject: [PATCH 1578/2101] [display] SDL2 display driver for host platform (#6825) --- .github/workflows/ci.yml | 2 +- CODEOWNERS | 1 + esphome/components/sdl/__init__.py | 1 + esphome/components/sdl/display.py | 72 ++++++++++++++ esphome/components/sdl/sdl_esphome.cpp | 96 +++++++++++++++++++ esphome/components/sdl/sdl_esphome.h | 54 +++++++++++ .../components/sdl/touchscreen/__init__.py | 22 +++++ .../sdl/touchscreen/sdl_touchscreen.h | 26 +++++ tests/components/sdl/common.yaml | 12 +++ tests/components/sdl/test.host.yaml | 1 + 10 files changed, 286 insertions(+), 1 deletion(-) create mode 100644 esphome/components/sdl/__init__.py create mode 100644 esphome/components/sdl/display.py create mode 100644 esphome/components/sdl/sdl_esphome.cpp create mode 100644 esphome/components/sdl/sdl_esphome.h create mode 100644 esphome/components/sdl/touchscreen/__init__.py create mode 100644 esphome/components/sdl/touchscreen/sdl_touchscreen.h create mode 100644 tests/components/sdl/common.yaml create mode 100644 tests/components/sdl/test.host.yaml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2b3c80cb35..5a1887c33c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -455,7 +455,7 @@ jobs: file: ${{ fromJson(needs.list-components.outputs.components) }} steps: - name: Install libsodium - run: sudo apt-get install libsodium-dev + run: sudo apt-get install libsodium-dev libsdl2-dev - name: Check out code from GitHub uses: actions/checkout@v4.1.6 diff --git a/CODEOWNERS b/CODEOWNERS index 75ea4fe523..5c14d30371 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -320,6 +320,7 @@ esphome/components/rtttl/* @glmnet esphome/components/safe_mode/* @jsuanet @kbx81 @paulmonigatti esphome/components/scd4x/* @martgras @sjtrny esphome/components/script/* @esphome/core +esphome/components/sdl/* @clydebarrow esphome/components/sdm_meter/* @jesserockz @polyfaces esphome/components/sdp3x/* @Azimath esphome/components/seeed_mr24hpc1/* @limengdu diff --git a/esphome/components/sdl/__init__.py b/esphome/components/sdl/__init__.py new file mode 100644 index 0000000000..c58ce8a01e --- /dev/null +++ b/esphome/components/sdl/__init__.py @@ -0,0 +1 @@ +CODEOWNERS = ["@clydebarrow"] diff --git a/esphome/components/sdl/display.py b/esphome/components/sdl/display.py new file mode 100644 index 0000000000..18dc570f88 --- /dev/null +++ b/esphome/components/sdl/display.py @@ -0,0 +1,72 @@ +import subprocess + +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import display +from esphome.const import ( + CONF_ID, + CONF_DIMENSIONS, + CONF_WIDTH, + CONF_HEIGHT, + CONF_LAMBDA, + PLATFORM_HOST, +) + +sdl_ns = cg.esphome_ns.namespace("sdl") +Sdl = sdl_ns.class_("Sdl", display.Display, cg.Component) + + +CONF_SDL_OPTIONS = "sdl_options" +CONF_SDL_ID = "sdl_id" + + +def get_sdl_options(value): + if value != "": + return value + try: + return subprocess.check_output(["sdl2-config", "--cflags", "--libs"]).decode() + except Exception as e: + raise cv.Invalid("Unable to run sdl2-config - have you installed sdl2?") from e + + +CONFIG_SCHEMA = cv.All( + display.FULL_DISPLAY_SCHEMA.extend( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(Sdl), + cv.Optional(CONF_SDL_OPTIONS, default=""): get_sdl_options, + cv.Required(CONF_DIMENSIONS): cv.Any( + cv.dimensions, + cv.Schema( + { + cv.Required(CONF_WIDTH): cv.int_, + cv.Required(CONF_HEIGHT): cv.int_, + } + ), + ), + } + ) + ), + cv.only_on(PLATFORM_HOST), +) + + +async def to_code(config): + for option in config[CONF_SDL_OPTIONS].split(): + cg.add_build_flag(option) + cg.add_build_flag("-DSDL_BYTEORDER=4321") + var = cg.new_Pvariable(config[CONF_ID]) + await display.register_display(var, config) + + dimensions = config[CONF_DIMENSIONS] + if isinstance(dimensions, dict): + cg.add(var.set_dimensions(dimensions[CONF_WIDTH], dimensions[CONF_HEIGHT])) + else: + (width, height) = dimensions + cg.add(var.set_dimensions(width, height)) + + if lamb := config.get(CONF_LAMBDA): + lambda_ = await cg.process_lambda( + lamb, [(display.DisplayRef, "it")], return_type=cg.void + ) + cg.add(var.set_writer(lambda_)) diff --git a/esphome/components/sdl/sdl_esphome.cpp b/esphome/components/sdl/sdl_esphome.cpp new file mode 100644 index 0000000000..5e17ca5650 --- /dev/null +++ b/esphome/components/sdl/sdl_esphome.cpp @@ -0,0 +1,96 @@ +#ifdef USE_HOST +#include "sdl_esphome.h" +#include "esphome/components/display/display_color_utils.h" + +namespace esphome { +namespace sdl { + +void Sdl::setup() { + ESP_LOGD(TAG, "Starting setup"); + SDL_Init(SDL_INIT_VIDEO); + this->window_ = SDL_CreateWindow(App.get_name().c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, + this->width_, this->height_, 0); + this->renderer_ = SDL_CreateRenderer(this->window_, -1, SDL_RENDERER_SOFTWARE); + this->texture_ = + SDL_CreateTexture(this->renderer_, SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_STATIC, this->width_, this->height_); + SDL_SetTextureBlendMode(this->texture_, SDL_BLENDMODE_BLEND); + ESP_LOGD(TAG, "Setup Complete"); +} +void Sdl::update() { + this->do_update_(); + if ((this->x_high_ < this->x_low_) || (this->y_high_ < this->y_low_)) + return; + SDL_Rect rect{this->x_low_, this->y_low_, this->x_high_ + 1 - this->x_low_, this->y_high_ + 1 - this->y_low_}; + this->x_low_ = this->width_; + this->y_low_ = this->height_; + this->x_high_ = 0; + this->y_high_ = 0; + SDL_RenderCopy(this->renderer_, this->texture_, &rect, &rect); + SDL_RenderPresent(this->renderer_); +} + +void Sdl::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) { + SDL_Rect rect{x_start, y_start, w, h}; + if (this->rotation_ != display::DISPLAY_ROTATION_0_DEGREES || bitness != display::COLOR_BITNESS_565 || big_endian) { + display::Display::draw_pixels_at(x_start, y_start, w, h, ptr, order, bitness, big_endian, x_offset, y_offset, + x_pad); + } else { + auto stride = x_offset + w + x_pad; + auto data = ptr + (stride * y_offset + x_offset) * 2; + SDL_UpdateTexture(this->texture_, &rect, data, stride * 2); + } + SDL_RenderCopy(this->renderer_, this->texture_, &rect, &rect); + SDL_RenderPresent(this->renderer_); +} + +void Sdl::draw_pixel_at(int x, int y, Color color) { + 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); + if (x < this->x_low_) + this->x_low_ = x; + if (y < this->y_low_) + this->y_low_ = y; + if (x > this->x_high_) + this->x_high_ = x; + if (y > this->y_high_) + this->y_high_ = y; +} + +void Sdl::loop() { + SDL_Event e; + if (SDL_PollEvent(&e)) { + switch (e.type) { + case SDL_QUIT: + exit(0); + + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + if (e.button.button == 1) { + this->mouse_x = e.button.x; + this->mouse_y = e.button.y; + this->mouse_down = e.button.state != 0; + } + break; + + case SDL_MOUSEMOTION: + if (e.motion.state & 1) { + this->mouse_x = e.button.x; + this->mouse_y = e.button.y; + this->mouse_down = true; + } else { + this->mouse_down = false; + } + break; + + default: + ESP_LOGV(TAG, "Event %d", e.type); + break; + } + } +} + +} // namespace sdl +} // namespace esphome +#endif diff --git a/esphome/components/sdl/sdl_esphome.h b/esphome/components/sdl/sdl_esphome.h new file mode 100644 index 0000000000..e4b2d9dd9f --- /dev/null +++ b/esphome/components/sdl/sdl_esphome.h @@ -0,0 +1,54 @@ +#pragma once + +#ifdef USE_HOST +#include "esphome/core/component.h" +#include "esphome/core/log.h" +#include "esphome/core/application.h" +#include "esphome/components/display/display.h" +#define SDL_MAIN_HANDLED +#include "SDL.h" + +namespace esphome { +namespace sdl { + +constexpr static const char *const TAG = "sdl"; + +class Sdl : public display::Display { + public: + display::DisplayType get_display_type() override { return display::DISPLAY_TYPE_COLOR; } + void update() override; + void loop() override; + void setup() 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 draw_pixel_at(int x, int y, Color color) override; + void set_dimensions(uint16_t width, uint16_t height) { + this->width_ = width; + this->height_ = height; + } + int get_width() override { return this->width_; } + 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); } + + int mouse_x{}; + int mouse_y{}; + bool mouse_down{}; + + protected: + int get_width_internal() override { return this->width_; } + int get_height_internal() override { return this->height_; } + int width_{}; + int height_{}; + SDL_Renderer *renderer_{}; + SDL_Window *window_{}; + SDL_Texture *texture_{}; + uint16_t x_low_{0}; + uint16_t y_low_{0}; + uint16_t x_high_{0}; + uint16_t y_high_{0}; +}; +} // namespace sdl +} // namespace esphome + +#endif diff --git a/esphome/components/sdl/touchscreen/__init__.py b/esphome/components/sdl/touchscreen/__init__.py new file mode 100644 index 0000000000..d6c0ed1c03 --- /dev/null +++ b/esphome/components/sdl/touchscreen/__init__.py @@ -0,0 +1,22 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.const import CONF_ID + +from esphome.components import touchscreen +from ..display import Sdl, sdl_ns, CONF_SDL_ID + +SdlTouchscreen = sdl_ns.class_("SdlTouchscreen", touchscreen.Touchscreen) + + +CONFIG_SCHEMA = touchscreen.TOUCHSCREEN_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(SdlTouchscreen), + cv.GenerateID(CONF_SDL_ID): cv.use_id(Sdl), + } +) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_parented(var, config[CONF_SDL_ID]) + await touchscreen.register_touchscreen(var, config) diff --git a/esphome/components/sdl/touchscreen/sdl_touchscreen.h b/esphome/components/sdl/touchscreen/sdl_touchscreen.h new file mode 100644 index 0000000000..a1f0fb15e3 --- /dev/null +++ b/esphome/components/sdl/touchscreen/sdl_touchscreen.h @@ -0,0 +1,26 @@ +#pragma once + +#ifdef USE_HOST +#include "../sdl_esphome.h" +#include "esphome/components/touchscreen/touchscreen.h" + +namespace esphome { +namespace sdl { + +class SdlTouchscreen : public touchscreen::Touchscreen, public Parented { + public: + void setup() override { + this->x_raw_max_ = this->display_->get_width(); + this->y_raw_max_ = this->display_->get_height(); + } + + void update_touches() override { + if (this->parent_->mouse_down) { + add_raw_touch_position_(0, this->parent_->mouse_x, this->parent_->mouse_y); + } + } +}; + +} // namespace sdl +} // namespace esphome +#endif diff --git a/tests/components/sdl/common.yaml b/tests/components/sdl/common.yaml new file mode 100644 index 0000000000..0192f054b5 --- /dev/null +++ b/tests/components/sdl/common.yaml @@ -0,0 +1,12 @@ +host: + mac_address: "62:23:45:AF:B3:DD" + +display: + - platform: sdl + id: sdl_display + update_interval: 1s + auto_clear_enabled: false + show_test_card: true + dimensions: + width: 450 + height: 600 diff --git a/tests/components/sdl/test.host.yaml b/tests/components/sdl/test.host.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/sdl/test.host.yaml @@ -0,0 +1 @@ +<<: !include common.yaml From f25c2963037a7d165e11eac1a874c9da2674e7c6 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Wed, 12 Jun 2024 11:47:52 +1000 Subject: [PATCH 1579/2101] [ili9xxx] Implement st7735 support (#6838) --- esphome/components/ili9xxx/display.py | 2 + esphome/components/ili9xxx/ili9xxx_defines.h | 2 + .../components/ili9xxx/ili9xxx_display.cpp | 18 +++++-- esphome/components/ili9xxx/ili9xxx_display.h | 10 +++- esphome/components/ili9xxx/ili9xxx_init.h | 51 +++++++++++++++++++ 5 files changed, 77 insertions(+), 6 deletions(-) diff --git a/esphome/components/ili9xxx/display.py b/esphome/components/ili9xxx/display.py index f0ac5ba9ef..483f2b886c 100644 --- a/esphome/components/ili9xxx/display.py +++ b/esphome/components/ili9xxx/display.py @@ -69,6 +69,7 @@ MODELS = { "ILI9486": ili9xxx_ns.class_("ILI9XXXILI9486", ILI9XXXDisplay), "ILI9488": ili9xxx_ns.class_("ILI9XXXILI9488", ILI9XXXDisplay), "ILI9488_A": ili9xxx_ns.class_("ILI9XXXILI9488A", ILI9XXXDisplay), + "ST7735": ili9xxx_ns.class_("ILI9XXXST7735", ILI9XXXDisplay), "ST7796": ili9xxx_ns.class_("ILI9XXXST7796", ILI9XXXDisplay), "ST7789V": ili9xxx_ns.class_("ILI9XXXST7789V", ILI9XXXDisplay), "S3BOX": ili9xxx_ns.class_("ILI9XXXS3Box", ILI9XXXDisplay), @@ -134,6 +135,7 @@ def _validate(config): "ILI9341", "ILI9342", "ST7789V", + "ST7735", ]: raise cv.Invalid("Selected model can't run on ESP8266.") diff --git a/esphome/components/ili9xxx/ili9xxx_defines.h b/esphome/components/ili9xxx/ili9xxx_defines.h index 29483ee15e..744013db3d 100644 --- a/esphome/components/ili9xxx/ili9xxx_defines.h +++ b/esphome/components/ili9xxx/ili9xxx_defines.h @@ -70,6 +70,7 @@ static const uint8_t ILI9XXX_PWCTR2 = 0xC1; static const uint8_t ILI9XXX_PWCTR3 = 0xC2; static const uint8_t ILI9XXX_PWCTR4 = 0xC3; static const uint8_t ILI9XXX_PWCTR5 = 0xC4; +static const uint8_t ILI9XXX_PWCTR6 = 0xF6; static const uint8_t ILI9XXX_VMCTR1 = 0xC5; static const uint8_t ILI9XXX_IFCTR = 0xC6; static const uint8_t ILI9XXX_VMCTR2 = 0xC7; @@ -91,6 +92,7 @@ static const uint8_t ILI9XXX_GMCTRN1 = 0xE1; static const uint8_t ILI9XXX_CSCON = 0xF0; static const uint8_t ILI9XXX_ADJCTL3 = 0xF7; +static const uint8_t ILI9XXX_DELAY = 0xFF; // followed by one byte of delay time in ms } // namespace ili9xxx } // namespace esphome diff --git a/esphome/components/ili9xxx/ili9xxx_display.cpp b/esphome/components/ili9xxx/ili9xxx_display.cpp index 463e3dd851..21d46ea825 100644 --- a/esphome/components/ili9xxx/ili9xxx_display.cpp +++ b/esphome/components/ili9xxx/ili9xxx_display.cpp @@ -411,11 +411,19 @@ void ILI9XXXDisplay::init_lcd_(const uint8_t *addr) { uint8_t cmd, x, num_args; while ((cmd = *addr++) != 0) { x = *addr++; - num_args = x & 0x7F; - this->send_command(cmd, addr, num_args); - addr += num_args; - if (x & 0x80) - delay(150); // NOLINT + if (cmd == ILI9XXX_DELAY) { + ESP_LOGD(TAG, "Delay %dms", x); + delay(x); + } else { + num_args = x & 0x7F; + ESP_LOGD(TAG, "Command %02X, length %d, bits %02X", cmd, num_args, *addr); + this->send_command(cmd, addr, num_args); + addr += num_args; + if (x & 0x80) { + ESP_LOGD(TAG, "Delay 150ms"); + delay(150); // NOLINT + } + } } } diff --git a/esphome/components/ili9xxx/ili9xxx_display.h b/esphome/components/ili9xxx/ili9xxx_display.h index 4446686e7b..7a320dac7b 100644 --- a/esphome/components/ili9xxx/ili9xxx_display.h +++ b/esphome/components/ili9xxx/ili9xxx_display.h @@ -35,7 +35,6 @@ class ILI9XXXDisplay : public display::DisplayBuffer, while ((cmd = *addr++) != 0) { num_args = *addr++ & 0x7F; bits = *addr; - esph_log_d(TAG, "Command %02X, length %d, bits %02X", cmd, num_args, bits); switch (cmd) { case ILI9XXX_MADCTL: { this->swap_xy_ = (bits & MADCTL_MV) != 0; @@ -51,6 +50,9 @@ class ILI9XXXDisplay : public display::DisplayBuffer, break; } + case ILI9XXX_DELAY: + continue; // no args to skip + default: break; } @@ -269,5 +271,11 @@ class ILI9XXXGC9A01A : public ILI9XXXDisplay { ILI9XXXGC9A01A() : ILI9XXXDisplay(INITCMD_GC9A01A, 240, 240, true) {} }; +//----------- ILI9XXX_24_TFT display -------------- +class ILI9XXXST7735 : public ILI9XXXDisplay { + public: + ILI9XXXST7735() : ILI9XXXDisplay(INITCMD_ST7735, 128, 160, false) {} +}; + } // namespace ili9xxx } // namespace esphome diff --git a/esphome/components/ili9xxx/ili9xxx_init.h b/esphome/components/ili9xxx/ili9xxx_init.h index ea90f83f30..260bde4c80 100644 --- a/esphome/components/ili9xxx/ili9xxx_init.h +++ b/esphome/components/ili9xxx/ili9xxx_init.h @@ -370,6 +370,57 @@ static const uint8_t PROGMEM INITCMD_GC9A01A[] = { 0x00 // End of list }; +static const uint8_t PROGMEM INITCMD_ST7735[] = { + ILI9XXX_SWRESET, 0, // Soft reset, then delay 10ms + ILI9XXX_DELAY, 10, + ILI9XXX_SLPOUT , 0, // Exit Sleep, delay + ILI9XXX_DELAY, 10, + ILI9XXX_PIXFMT , 1, 0x05, + ILI9XXX_FRMCTR1, 3, // 4: Frame rate control, 3 args + delay: + 0x01, 0x2C, 0x2D, // Rate = fosc/(1x2+40) * (LINE+2C+2D) + ILI9XXX_FRMCTR2, 3, // 4: Framerate ctrl - idle mode, 3 args: + 0x01, 0x2C, 0x2D, // Rate = fosc/(1x2+40) * (LINE+2C+2D) + ILI9XXX_FRMCTR3, 6, // 5: Framerate - partial mode, 6 args: + 0x01, 0x2C, 0x2D, // Dot inversion mode + 0x01, 0x2C, 0x2D, // Line inversion mode + + ILI9XXX_INVCTR, 1, // 7: Display inversion control, 1 arg: + 0x7, // Line inversion + ILI9XXX_PWCTR1, 3, // 7: Power control, 3 args, no delay: + 0xA2, + 0x02, // -4.6V + 0x84, // AUTO mode + ILI9XXX_PWCTR2, 1, // 8: Power control, 1 arg, no delay: + 0xC5, // VGH25=2.4C VGSEL=-10 VGH=3 * AVDD + ILI9XXX_PWCTR3, 2, // 9: Power control, 2 args, no delay: + 0x0A, // Opamp current small + 0x00, // Boost frequency + ILI9XXX_PWCTR4, 2, // 10: Power control, 2 args, no delay: + 0x8A, // BCLK/2, + 0x2A, // opamp current small & medium low + ILI9XXX_PWCTR5, 2, // 11: Power control, 2 args, no delay: + 0x8A, 0xEE, + + ILI9XXX_VMCTR1, 1, // 11: Power control, 2 args + delay: + 0x0E, + ILI9XXX_GMCTRP1, 16, // 13: Gamma Adjustments (pos. polarity), 16 args + delay: + 0x02, 0x1c, 0x07, 0x12, // (Not entirely necessary, but provides + 0x37, 0x32, 0x29, 0x2d, // accurate colors) + 0x29, 0x25, 0x2B, 0x39, + 0x00, 0x01, 0x03, 0x10, + ILI9XXX_GMCTRN1, 16, // 14: Gamma Adjustments (neg. polarity), 16 args + delay: + 0x03, 0x1d, 0x07, 0x06, // (Not entirely necessary, but provides + 0x2E, 0x2C, 0x29, 0x2D, // accurate colors) + 0x2E, 0x2E, 0x37, 0x3F, + 0x00, 0x00, 0x02, 0x10, + ILI9XXX_MADCTL , 1, 0x00, // Memory Access Control, BGR + ILI9XXX_NORON , 0, + ILI9XXX_DELAY, 10, + ILI9XXX_DISPON , 0, // Display on + ILI9XXX_DELAY, 10, + 00, // endo of list +}; + // clang-format on } // namespace ili9xxx } // namespace esphome From f9f98fa6c6d2d120efd39721133a7b44c5fd4ee3 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 12 Jun 2024 14:16:43 +1200 Subject: [PATCH 1580/2101] Bump version to 2024.6.0b1 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index cbd932e3cc..0117e8a238 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.6.0-dev" +__version__ = "2024.6.0b1" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From bd7e8fbf86b086d2b1211173d2b20efc0efafb7e Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 12 Jun 2024 14:16:43 +1200 Subject: [PATCH 1581/2101] Bump version to 2024.7.0-dev --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index cbd932e3cc..dff14d7cf0 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.6.0-dev" +__version__ = "2024.7.0-dev" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From b401b5eca83b69fc5027deb154cbb2571cfde9c7 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 12 Jun 2024 19:36:57 +1200 Subject: [PATCH 1582/2101] [CI] Update device class sync script for update entities (#6895) --- script/sync-device_class.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/script/sync-device_class.py b/script/sync-device_class.py index 12e1bb6a9f..121c89b8f9 100755 --- a/script/sync-device_class.py +++ b/script/sync-device_class.py @@ -10,6 +10,7 @@ from homeassistant.components.event import EventDeviceClass from homeassistant.components.number import NumberDeviceClass from homeassistant.components.sensor import SensorDeviceClass from homeassistant.components.switch import SwitchDeviceClass +from homeassistant.components.update import UpdateDeviceClass from homeassistant.components.valve import ValveDeviceClass # pylint: enable=import-error @@ -27,6 +28,7 @@ DOMAINS = { "number": NumberDeviceClass, "sensor": SensorDeviceClass, "switch": SwitchDeviceClass, + "update": UpdateDeviceClass, "valve": ValveDeviceClass, } From 2044c7e4d4506b840dd2978d2fce5e455d304627 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 12 Jun 2024 19:58:56 +1200 Subject: [PATCH 1583/2101] [CI] Fix for sdl (#6892) --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5a1887c33c..b49237db26 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -454,7 +454,7 @@ jobs: matrix: file: ${{ fromJson(needs.list-components.outputs.components) }} steps: - - name: Install libsodium + - name: Install dependencies run: sudo apt-get install libsodium-dev libsdl2-dev - name: Check out code from GitHub @@ -508,8 +508,8 @@ jobs: - name: List components run: echo ${{ matrix.components }} - - name: Install libsodium - run: sudo apt-get install libsodium-dev + - name: Install dependencies + run: sudo apt-get install libsodium-dev libsdl2-dev - name: Check out code from GitHub uses: actions/checkout@v4.1.6 From df52bc3493c9834e2fc327e433c0368c58733c51 Mon Sep 17 00:00:00 2001 From: Oliver Hihn <43825356+oliverhihn@users.noreply.github.com> Date: Wed, 12 Jun 2024 11:09:26 +0200 Subject: [PATCH 1584/2101] Add step_delay option to X9C component (#6890) --- esphome/components/x9c/output.py | 3 +++ esphome/components/x9c/x9c.cpp | 5 +++-- esphome/components/x9c/x9c.h | 2 ++ esphome/const.py | 1 + tests/components/x9c/test.esp32-c3-idf.yaml | 1 + tests/components/x9c/test.esp32-c3.yaml | 1 + tests/components/x9c/test.esp32-idf.yaml | 1 + tests/components/x9c/test.esp32.yaml | 1 + tests/components/x9c/test.esp8266.yaml | 1 + tests/components/x9c/test.rp2040.yaml | 1 + 10 files changed, 15 insertions(+), 2 deletions(-) diff --git a/esphome/components/x9c/output.py b/esphome/components/x9c/output.py index 44e9d729b3..56820efdfa 100644 --- a/esphome/components/x9c/output.py +++ b/esphome/components/x9c/output.py @@ -8,6 +8,7 @@ from esphome.const import ( CONF_INC_PIN, CONF_UD_PIN, CONF_INITIAL_VALUE, + CONF_STEP_DELAY, ) CODEOWNERS = ["@EtienneMD"] @@ -26,6 +27,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_INITIAL_VALUE, default=1.0): cv.float_range( min=0.01, max=1.0 ), + cv.Optional(CONF_STEP_DELAY, default=1): cv.int_range(min=1, max=100), } ) ) @@ -44,3 +46,4 @@ async def to_code(config): cg.add(var.set_ud_pin(ud_pin)) cg.add(var.set_initial_value(config[CONF_INITIAL_VALUE])) + cg.add(var.set_step_delay(config[CONF_STEP_DELAY])) diff --git a/esphome/components/x9c/x9c.cpp b/esphome/components/x9c/x9c.cpp index 32a1375f02..4e7a94266e 100644 --- a/esphome/components/x9c/x9c.cpp +++ b/esphome/components/x9c/x9c.cpp @@ -22,9 +22,9 @@ void X9cOutput::trim_value(int change_amount) { for (int i = 0; i < abs(change_amount); i++) { // Move wiper this->inc_pin_->digital_write(true); - delayMicroseconds(1); + delayMicroseconds(this->step_delay_); this->inc_pin_->digital_write(false); - delayMicroseconds(1); + delayMicroseconds(this->step_delay_); } delayMicroseconds(100); // Let value settle @@ -69,6 +69,7 @@ void X9cOutput::dump_config() { LOG_PIN(" Increment Pin: ", this->inc_pin_); LOG_PIN(" Up/Down Pin: ", this->ud_pin_); ESP_LOGCONFIG(TAG, " Initial Value: %f", this->initial_value_); + ESP_LOGCONFIG(TAG, " Step Delay: %d", this->step_delay_); LOG_FLOAT_OUTPUT(this); } diff --git a/esphome/components/x9c/x9c.h b/esphome/components/x9c/x9c.h index 924460c841..e7cc29a6cc 100644 --- a/esphome/components/x9c/x9c.h +++ b/esphome/components/x9c/x9c.h @@ -13,6 +13,7 @@ class X9cOutput : public output::FloatOutput, public Component { void set_inc_pin(InternalGPIOPin *pin) { inc_pin_ = pin; } void set_ud_pin(InternalGPIOPin *pin) { ud_pin_ = pin; } void set_initial_value(float initial_value) { initial_value_ = initial_value; } + void set_step_delay(int step_delay) { step_delay_ = step_delay; } void setup() override; void dump_config() override; @@ -26,6 +27,7 @@ class X9cOutput : public output::FloatOutput, public Component { InternalGPIOPin *ud_pin_; float initial_value_; float pot_value_; + int step_delay_; }; } // namespace x9c diff --git a/esphome/const.py b/esphome/const.py index dff14d7cf0..9c4e451029 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -784,6 +784,7 @@ CONF_STATIC_IP = "static_ip" CONF_STATUS = "status" CONF_STB_PIN = "stb_pin" CONF_STEP = "step" +CONF_STEP_DELAY = "step_delay" CONF_STEP_MODE = "step_mode" CONF_STEP_PIN = "step_pin" CONF_STOP = "stop" diff --git a/tests/components/x9c/test.esp32-c3-idf.yaml b/tests/components/x9c/test.esp32-c3-idf.yaml index a0480aa68f..1234581329 100644 --- a/tests/components/x9c/test.esp32-c3-idf.yaml +++ b/tests/components/x9c/test.esp32-c3-idf.yaml @@ -5,3 +5,4 @@ output: inc_pin: 4 ud_pin: 5 initial_value: 0.5 + step_delay: 50 diff --git a/tests/components/x9c/test.esp32-c3.yaml b/tests/components/x9c/test.esp32-c3.yaml index a0480aa68f..1234581329 100644 --- a/tests/components/x9c/test.esp32-c3.yaml +++ b/tests/components/x9c/test.esp32-c3.yaml @@ -5,3 +5,4 @@ output: inc_pin: 4 ud_pin: 5 initial_value: 0.5 + step_delay: 50 diff --git a/tests/components/x9c/test.esp32-idf.yaml b/tests/components/x9c/test.esp32-idf.yaml index 28b18f7a92..5f1468e94b 100644 --- a/tests/components/x9c/test.esp32-idf.yaml +++ b/tests/components/x9c/test.esp32-idf.yaml @@ -5,3 +5,4 @@ output: inc_pin: 14 ud_pin: 15 initial_value: 0.5 + step_delay: 50 diff --git a/tests/components/x9c/test.esp32.yaml b/tests/components/x9c/test.esp32.yaml index 28b18f7a92..5f1468e94b 100644 --- a/tests/components/x9c/test.esp32.yaml +++ b/tests/components/x9c/test.esp32.yaml @@ -5,3 +5,4 @@ output: inc_pin: 14 ud_pin: 15 initial_value: 0.5 + step_delay: 50 diff --git a/tests/components/x9c/test.esp8266.yaml b/tests/components/x9c/test.esp8266.yaml index 28b18f7a92..5f1468e94b 100644 --- a/tests/components/x9c/test.esp8266.yaml +++ b/tests/components/x9c/test.esp8266.yaml @@ -5,3 +5,4 @@ output: inc_pin: 14 ud_pin: 15 initial_value: 0.5 + step_delay: 50 diff --git a/tests/components/x9c/test.rp2040.yaml b/tests/components/x9c/test.rp2040.yaml index a0480aa68f..1234581329 100644 --- a/tests/components/x9c/test.rp2040.yaml +++ b/tests/components/x9c/test.rp2040.yaml @@ -5,3 +5,4 @@ output: inc_pin: 4 ud_pin: 5 initial_value: 0.5 + step_delay: 50 From 1a242f94db4923b099496497ba6e98b5f72e745d Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 12 Jun 2024 21:20:46 +1200 Subject: [PATCH 1585/2101] [host] Execute host program when using run command (#6897) --- esphome/__main__.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/esphome/__main__.py b/esphome/__main__.py index f3c4ff3e23..5ff1a28ec7 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -488,6 +488,15 @@ def command_run(args, config): if exit_code != 0: return exit_code _LOGGER.info("Successfully compiled program.") + if CORE.is_host: + from esphome.platformio_api import get_idedata + + idedata = get_idedata(config) + if idedata is None: + return 1 + program_path = idedata.raw["prog_path"] + return run_external_process(program_path) + port = choose_upload_log_host( default=args.device, check_default=None, From 68dbf35b096be83e46e3fc7e82ae3100d2866ac2 Mon Sep 17 00:00:00 2001 From: Oliver Hihn <43825356+oliverhihn@users.noreply.github.com> Date: Wed, 12 Jun 2024 20:14:03 +0200 Subject: [PATCH 1586/2101] X9C step delay with units (#6898) --- esphome/components/x9c/output.py | 8 +++++++- tests/components/x9c/test.esp32-c3-idf.yaml | 2 +- tests/components/x9c/test.esp32-c3.yaml | 2 +- tests/components/x9c/test.esp32-idf.yaml | 2 +- tests/components/x9c/test.esp32.yaml | 2 +- tests/components/x9c/test.esp8266.yaml | 2 +- tests/components/x9c/test.rp2040.yaml | 2 +- 7 files changed, 13 insertions(+), 7 deletions(-) diff --git a/esphome/components/x9c/output.py b/esphome/components/x9c/output.py index 56820efdfa..4497994982 100644 --- a/esphome/components/x9c/output.py +++ b/esphome/components/x9c/output.py @@ -27,7 +27,13 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_INITIAL_VALUE, default=1.0): cv.float_range( min=0.01, max=1.0 ), - cv.Optional(CONF_STEP_DELAY, default=1): cv.int_range(min=1, max=100), + cv.Optional(CONF_STEP_DELAY, default="1us"): cv.All( + cv.positive_time_period_microseconds, + cv.Range( + min=cv.TimePeriod(microseconds=1), + max=cv.TimePeriod(microseconds=100), + ), + ), } ) ) diff --git a/tests/components/x9c/test.esp32-c3-idf.yaml b/tests/components/x9c/test.esp32-c3-idf.yaml index 1234581329..972c743fcd 100644 --- a/tests/components/x9c/test.esp32-c3-idf.yaml +++ b/tests/components/x9c/test.esp32-c3-idf.yaml @@ -5,4 +5,4 @@ output: inc_pin: 4 ud_pin: 5 initial_value: 0.5 - step_delay: 50 + step_delay: 50us diff --git a/tests/components/x9c/test.esp32-c3.yaml b/tests/components/x9c/test.esp32-c3.yaml index 1234581329..972c743fcd 100644 --- a/tests/components/x9c/test.esp32-c3.yaml +++ b/tests/components/x9c/test.esp32-c3.yaml @@ -5,4 +5,4 @@ output: inc_pin: 4 ud_pin: 5 initial_value: 0.5 - step_delay: 50 + step_delay: 50us diff --git a/tests/components/x9c/test.esp32-idf.yaml b/tests/components/x9c/test.esp32-idf.yaml index 5f1468e94b..f587b69b4f 100644 --- a/tests/components/x9c/test.esp32-idf.yaml +++ b/tests/components/x9c/test.esp32-idf.yaml @@ -5,4 +5,4 @@ output: inc_pin: 14 ud_pin: 15 initial_value: 0.5 - step_delay: 50 + step_delay: 50us diff --git a/tests/components/x9c/test.esp32.yaml b/tests/components/x9c/test.esp32.yaml index 5f1468e94b..f587b69b4f 100644 --- a/tests/components/x9c/test.esp32.yaml +++ b/tests/components/x9c/test.esp32.yaml @@ -5,4 +5,4 @@ output: inc_pin: 14 ud_pin: 15 initial_value: 0.5 - step_delay: 50 + step_delay: 50us diff --git a/tests/components/x9c/test.esp8266.yaml b/tests/components/x9c/test.esp8266.yaml index 5f1468e94b..f587b69b4f 100644 --- a/tests/components/x9c/test.esp8266.yaml +++ b/tests/components/x9c/test.esp8266.yaml @@ -5,4 +5,4 @@ output: inc_pin: 14 ud_pin: 15 initial_value: 0.5 - step_delay: 50 + step_delay: 50us diff --git a/tests/components/x9c/test.rp2040.yaml b/tests/components/x9c/test.rp2040.yaml index 1234581329..972c743fcd 100644 --- a/tests/components/x9c/test.rp2040.yaml +++ b/tests/components/x9c/test.rp2040.yaml @@ -5,4 +5,4 @@ output: inc_pin: 4 ud_pin: 5 initial_value: 0.5 - step_delay: 50 + step_delay: 50us From 8453d9a70da397baac09a1b3a158b6d88f27e2ce Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Jun 2024 09:27:15 +1200 Subject: [PATCH 1587/2101] Bump actions/checkout from 4.1.6 to 4.1.7 (#6900) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-api-proto.yml | 2 +- .github/workflows/ci-docker.yml | 2 +- .github/workflows/ci.yml | 32 +++++++++++------------ .github/workflows/release.yml | 8 +++--- .github/workflows/sync-device-classes.yml | 4 +-- .github/workflows/yaml-lint.yml | 2 +- 6 files changed, 25 insertions(+), 25 deletions(-) diff --git a/.github/workflows/ci-api-proto.yml b/.github/workflows/ci-api-proto.yml index 1628464061..ee08a0246d 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@v4.1.6 + uses: actions/checkout@v4.1.7 - name: Set up Python uses: actions/setup-python@v5.1.0 with: diff --git a/.github/workflows/ci-docker.yml b/.github/workflows/ci-docker.yml index dd5c051cfb..421a885f74 100644 --- a/.github/workflows/ci-docker.yml +++ b/.github/workflows/ci-docker.yml @@ -40,7 +40,7 @@ jobs: arch: [amd64, armv7, aarch64] build_type: ["ha-addon", "docker", "lint"] steps: - - uses: actions/checkout@v4.1.6 + - uses: actions/checkout@v4.1.7 - name: Set up Python uses: actions/setup-python@v5.1.0 with: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b49237db26..3c10e5dac7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,7 +34,7 @@ jobs: cache-key: ${{ steps.cache-key.outputs.key }} steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.6 + uses: actions/checkout@v4.1.7 - name: Generate cache-key id: cache-key run: echo key="${{ hashFiles('requirements.txt', 'requirements_optional.txt', 'requirements_test.txt') }}" >> $GITHUB_OUTPUT @@ -66,7 +66,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.6 + uses: actions/checkout@v4.1.7 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -87,7 +87,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.6 + uses: actions/checkout@v4.1.7 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -108,7 +108,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.6 + uses: actions/checkout@v4.1.7 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -129,7 +129,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.6 + uses: actions/checkout@v4.1.7 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -150,7 +150,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.6 + uses: actions/checkout@v4.1.7 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -199,7 +199,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.6 + uses: actions/checkout@v4.1.7 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -229,7 +229,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.6 + uses: actions/checkout@v4.1.7 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -254,7 +254,7 @@ jobs: matrix: ${{ steps.set-matrix.outputs.matrix }} steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.6 + uses: actions/checkout@v4.1.7 - name: Find all YAML test files id: set-matrix run: echo "matrix=$(ls tests/test*.yaml | jq -R -s -c 'split("\n")[:-1]')" >> $GITHUB_OUTPUT @@ -271,7 +271,7 @@ jobs: file: ${{ fromJson(needs.compile-tests-list.outputs.matrix) }} steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.6 + uses: actions/checkout@v4.1.7 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -303,7 +303,7 @@ jobs: file: ${{ fromJson(needs.compile-tests-list.outputs.matrix) }} steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.6 + uses: actions/checkout@v4.1.7 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -358,7 +358,7 @@ jobs: steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.6 + uses: actions/checkout@v4.1.7 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -410,7 +410,7 @@ jobs: count: ${{ steps.list-components.outputs.count }} steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.6 + uses: actions/checkout@v4.1.7 with: # Fetch enough history so `git merge-base refs/remotes/origin/dev HEAD` works. fetch-depth: 500 @@ -458,7 +458,7 @@ jobs: run: sudo apt-get install libsodium-dev libsdl2-dev - name: Check out code from GitHub - uses: actions/checkout@v4.1.6 + uses: actions/checkout@v4.1.7 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -484,7 +484,7 @@ jobs: matrix: ${{ steps.split.outputs.components }} steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.6 + uses: actions/checkout@v4.1.7 - name: Split components into 20 groups id: split run: | @@ -512,7 +512,7 @@ jobs: run: sudo apt-get install libsodium-dev libsdl2-dev - name: Check out code from GitHub - uses: actions/checkout@v4.1.6 + uses: actions/checkout@v4.1.7 - name: Restore Python uses: ./.github/actions/restore-python with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 563d485b6a..9c07335104 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,7 +19,7 @@ jobs: tag: ${{ steps.tag.outputs.tag }} branch_build: ${{ steps.tag.outputs.branch_build }} steps: - - uses: actions/checkout@v4.1.6 + - uses: actions/checkout@v4.1.7 - name: Get tag id: tag # yamllint disable rule:line-length @@ -51,7 +51,7 @@ jobs: contents: read id-token: write steps: - - uses: actions/checkout@v4.1.6 + - uses: actions/checkout@v4.1.7 - name: Set up Python uses: actions/setup-python@v5.1.0 with: @@ -83,7 +83,7 @@ jobs: - linux/arm/v7 - linux/arm64 steps: - - uses: actions/checkout@v4.1.6 + - uses: actions/checkout@v4.1.7 - name: Set up Python uses: actions/setup-python@v5.1.0 with: @@ -174,7 +174,7 @@ jobs: - ghcr - dockerhub steps: - - uses: actions/checkout@v4.1.6 + - uses: actions/checkout@v4.1.7 - name: Download digests uses: actions/download-artifact@v4.1.7 diff --git a/.github/workflows/sync-device-classes.yml b/.github/workflows/sync-device-classes.yml index e65e851f3c..45f6b27127 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@v4.1.6 + uses: actions/checkout@v4.1.7 - name: Checkout Home Assistant - uses: actions/checkout@v4.1.6 + uses: actions/checkout@v4.1.7 with: repository: home-assistant/core path: lib/home-assistant diff --git a/.github/workflows/yaml-lint.yml b/.github/workflows/yaml-lint.yml index f009643629..1c0b5f58ad 100644 --- a/.github/workflows/yaml-lint.yml +++ b/.github/workflows/yaml-lint.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.6 + uses: actions/checkout@v4.1.7 - name: Run yamllint uses: frenck/action-yamllint@v1.5.0 with: From c4c46c206fd5d8edfab0a2769821db0beaae5908 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 13 Jun 2024 10:12:36 +1200 Subject: [PATCH 1588/2101] Bump esphome-dashboard to 20240613.0 (#6901) --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 05e46ca31e..a7b08f8a14 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ pyserial==3.5 platformio==6.1.15 # When updating platformio, also update Dockerfile esptool==4.7.0 click==8.1.7 -esphome-dashboard==20240429.1 +esphome-dashboard==20240613.0 aioesphomeapi==24.3.0 zeroconf==0.132.2 python-magic==0.4.27 From fdefc825bb473fedc4fb2b8001ba6ce3f4fe2c7f Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 12 Jun 2024 19:58:56 +1200 Subject: [PATCH 1589/2101] [CI] Fix for sdl (#6892) --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5a1887c33c..b49237db26 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -454,7 +454,7 @@ jobs: matrix: file: ${{ fromJson(needs.list-components.outputs.components) }} steps: - - name: Install libsodium + - name: Install dependencies run: sudo apt-get install libsodium-dev libsdl2-dev - name: Check out code from GitHub @@ -508,8 +508,8 @@ jobs: - name: List components run: echo ${{ matrix.components }} - - name: Install libsodium - run: sudo apt-get install libsodium-dev + - name: Install dependencies + run: sudo apt-get install libsodium-dev libsdl2-dev - name: Check out code from GitHub uses: actions/checkout@v4.1.6 From be486e0ca65bad647289c3a4cfd4d09a09b02e64 Mon Sep 17 00:00:00 2001 From: Oliver Hihn <43825356+oliverhihn@users.noreply.github.com> Date: Wed, 12 Jun 2024 11:09:26 +0200 Subject: [PATCH 1590/2101] Add step_delay option to X9C component (#6890) --- esphome/components/x9c/output.py | 3 +++ esphome/components/x9c/x9c.cpp | 5 +++-- esphome/components/x9c/x9c.h | 2 ++ esphome/const.py | 1 + tests/components/x9c/test.esp32-c3-idf.yaml | 1 + tests/components/x9c/test.esp32-c3.yaml | 1 + tests/components/x9c/test.esp32-idf.yaml | 1 + tests/components/x9c/test.esp32.yaml | 1 + tests/components/x9c/test.esp8266.yaml | 1 + tests/components/x9c/test.rp2040.yaml | 1 + 10 files changed, 15 insertions(+), 2 deletions(-) diff --git a/esphome/components/x9c/output.py b/esphome/components/x9c/output.py index 44e9d729b3..56820efdfa 100644 --- a/esphome/components/x9c/output.py +++ b/esphome/components/x9c/output.py @@ -8,6 +8,7 @@ from esphome.const import ( CONF_INC_PIN, CONF_UD_PIN, CONF_INITIAL_VALUE, + CONF_STEP_DELAY, ) CODEOWNERS = ["@EtienneMD"] @@ -26,6 +27,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_INITIAL_VALUE, default=1.0): cv.float_range( min=0.01, max=1.0 ), + cv.Optional(CONF_STEP_DELAY, default=1): cv.int_range(min=1, max=100), } ) ) @@ -44,3 +46,4 @@ async def to_code(config): cg.add(var.set_ud_pin(ud_pin)) cg.add(var.set_initial_value(config[CONF_INITIAL_VALUE])) + cg.add(var.set_step_delay(config[CONF_STEP_DELAY])) diff --git a/esphome/components/x9c/x9c.cpp b/esphome/components/x9c/x9c.cpp index 32a1375f02..4e7a94266e 100644 --- a/esphome/components/x9c/x9c.cpp +++ b/esphome/components/x9c/x9c.cpp @@ -22,9 +22,9 @@ void X9cOutput::trim_value(int change_amount) { for (int i = 0; i < abs(change_amount); i++) { // Move wiper this->inc_pin_->digital_write(true); - delayMicroseconds(1); + delayMicroseconds(this->step_delay_); this->inc_pin_->digital_write(false); - delayMicroseconds(1); + delayMicroseconds(this->step_delay_); } delayMicroseconds(100); // Let value settle @@ -69,6 +69,7 @@ void X9cOutput::dump_config() { LOG_PIN(" Increment Pin: ", this->inc_pin_); LOG_PIN(" Up/Down Pin: ", this->ud_pin_); ESP_LOGCONFIG(TAG, " Initial Value: %f", this->initial_value_); + ESP_LOGCONFIG(TAG, " Step Delay: %d", this->step_delay_); LOG_FLOAT_OUTPUT(this); } diff --git a/esphome/components/x9c/x9c.h b/esphome/components/x9c/x9c.h index 924460c841..e7cc29a6cc 100644 --- a/esphome/components/x9c/x9c.h +++ b/esphome/components/x9c/x9c.h @@ -13,6 +13,7 @@ class X9cOutput : public output::FloatOutput, public Component { void set_inc_pin(InternalGPIOPin *pin) { inc_pin_ = pin; } void set_ud_pin(InternalGPIOPin *pin) { ud_pin_ = pin; } void set_initial_value(float initial_value) { initial_value_ = initial_value; } + void set_step_delay(int step_delay) { step_delay_ = step_delay; } void setup() override; void dump_config() override; @@ -26,6 +27,7 @@ class X9cOutput : public output::FloatOutput, public Component { InternalGPIOPin *ud_pin_; float initial_value_; float pot_value_; + int step_delay_; }; } // namespace x9c diff --git a/esphome/const.py b/esphome/const.py index 0117e8a238..4d0223fa22 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -784,6 +784,7 @@ CONF_STATIC_IP = "static_ip" CONF_STATUS = "status" CONF_STB_PIN = "stb_pin" CONF_STEP = "step" +CONF_STEP_DELAY = "step_delay" CONF_STEP_MODE = "step_mode" CONF_STEP_PIN = "step_pin" CONF_STOP = "stop" diff --git a/tests/components/x9c/test.esp32-c3-idf.yaml b/tests/components/x9c/test.esp32-c3-idf.yaml index a0480aa68f..1234581329 100644 --- a/tests/components/x9c/test.esp32-c3-idf.yaml +++ b/tests/components/x9c/test.esp32-c3-idf.yaml @@ -5,3 +5,4 @@ output: inc_pin: 4 ud_pin: 5 initial_value: 0.5 + step_delay: 50 diff --git a/tests/components/x9c/test.esp32-c3.yaml b/tests/components/x9c/test.esp32-c3.yaml index a0480aa68f..1234581329 100644 --- a/tests/components/x9c/test.esp32-c3.yaml +++ b/tests/components/x9c/test.esp32-c3.yaml @@ -5,3 +5,4 @@ output: inc_pin: 4 ud_pin: 5 initial_value: 0.5 + step_delay: 50 diff --git a/tests/components/x9c/test.esp32-idf.yaml b/tests/components/x9c/test.esp32-idf.yaml index 28b18f7a92..5f1468e94b 100644 --- a/tests/components/x9c/test.esp32-idf.yaml +++ b/tests/components/x9c/test.esp32-idf.yaml @@ -5,3 +5,4 @@ output: inc_pin: 14 ud_pin: 15 initial_value: 0.5 + step_delay: 50 diff --git a/tests/components/x9c/test.esp32.yaml b/tests/components/x9c/test.esp32.yaml index 28b18f7a92..5f1468e94b 100644 --- a/tests/components/x9c/test.esp32.yaml +++ b/tests/components/x9c/test.esp32.yaml @@ -5,3 +5,4 @@ output: inc_pin: 14 ud_pin: 15 initial_value: 0.5 + step_delay: 50 diff --git a/tests/components/x9c/test.esp8266.yaml b/tests/components/x9c/test.esp8266.yaml index 28b18f7a92..5f1468e94b 100644 --- a/tests/components/x9c/test.esp8266.yaml +++ b/tests/components/x9c/test.esp8266.yaml @@ -5,3 +5,4 @@ output: inc_pin: 14 ud_pin: 15 initial_value: 0.5 + step_delay: 50 diff --git a/tests/components/x9c/test.rp2040.yaml b/tests/components/x9c/test.rp2040.yaml index a0480aa68f..1234581329 100644 --- a/tests/components/x9c/test.rp2040.yaml +++ b/tests/components/x9c/test.rp2040.yaml @@ -5,3 +5,4 @@ output: inc_pin: 4 ud_pin: 5 initial_value: 0.5 + step_delay: 50 From 91e72fe121acf4d0994bfd084f05e149ce2de92b Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 12 Jun 2024 21:20:46 +1200 Subject: [PATCH 1591/2101] [host] Execute host program when using run command (#6897) --- esphome/__main__.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/esphome/__main__.py b/esphome/__main__.py index f3c4ff3e23..5ff1a28ec7 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -488,6 +488,15 @@ def command_run(args, config): if exit_code != 0: return exit_code _LOGGER.info("Successfully compiled program.") + if CORE.is_host: + from esphome.platformio_api import get_idedata + + idedata = get_idedata(config) + if idedata is None: + return 1 + program_path = idedata.raw["prog_path"] + return run_external_process(program_path) + port = choose_upload_log_host( default=args.device, check_default=None, From 73cb3ec852a3bbdca1430578d4bc3cba114eb115 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 13 Jun 2024 10:12:36 +1200 Subject: [PATCH 1592/2101] Bump esphome-dashboard to 20240613.0 (#6901) --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 05e46ca31e..a7b08f8a14 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ pyserial==3.5 platformio==6.1.15 # When updating platformio, also update Dockerfile esptool==4.7.0 click==8.1.7 -esphome-dashboard==20240429.1 +esphome-dashboard==20240613.0 aioesphomeapi==24.3.0 zeroconf==0.132.2 python-magic==0.4.27 From 3db71b98ae4278fa5f54112e7eb885794c258d6b Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 13 Jun 2024 10:31:08 +1200 Subject: [PATCH 1593/2101] Bump version to 2024.6.0b2 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 4d0223fa22..e2dc5c259a 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.6.0b1" +__version__ = "2024.6.0b2" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From b29e1acab81ddc3bfef041c1cdba0048be2b8c86 Mon Sep 17 00:00:00 2001 From: esphomebot Date: Thu, 13 Jun 2024 19:24:36 +1200 Subject: [PATCH 1594/2101] Synchronise Device Classes from Home Assistant (#6904) --- esphome/components/update/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/components/update/__init__.py b/esphome/components/update/__init__.py index ae3d5062ab..ea1cf778b6 100644 --- a/esphome/components/update/__init__.py +++ b/esphome/components/update/__init__.py @@ -7,6 +7,7 @@ from esphome.const import ( CONF_ID, CONF_MQTT_ID, CONF_WEB_SERVER_ID, + DEVICE_CLASS_EMPTY, DEVICE_CLASS_FIRMWARE, ) from esphome.core import CORE, coroutine_with_priority @@ -24,6 +25,7 @@ PerformAction = update_ns.class_("PerformAction", automation.Action) IsAvailableCondition = update_ns.class_("IsAvailableCondition", automation.Condition) DEVICE_CLASSES = [ + DEVICE_CLASS_EMPTY, DEVICE_CLASS_FIRMWARE, ] From 761aae6f892edc3d447e4478e4d20c3d124a66a1 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Thu, 13 Jun 2024 05:15:38 -0500 Subject: [PATCH 1595/2101] [CI] Allow clang-tidy to see IDF components (#6903) * Allow clang-tidy to see IDF components * Remove camera, add tflite-micro --- .github/workflows/ci.yml | 7 +++++++ esphome/idf_component.yml | 9 +++++++++ script/clang-tidy | 6 ++++-- 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 esphome/idf_component.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3c10e5dac7..df7a9178e1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -387,6 +387,13 @@ jobs: echo "::add-matcher::.github/workflows/matchers/gcc.json" echo "::add-matcher::.github/workflows/matchers/clang-tidy.json" + - name: Run 'pio run --list-targets -e esp32-idf-tidy' + if: matrix.name == 'Run script/clang-tidy for ESP32 IDF' + run: | + . venv/bin/activate + mkdir -p .temp + pio run --list-targets -e esp32-idf-tidy + - name: Run clang-tidy run: | . venv/bin/activate diff --git a/esphome/idf_component.yml b/esphome/idf_component.yml new file mode 100644 index 0000000000..ba1a6312e2 --- /dev/null +++ b/esphome/idf_component.yml @@ -0,0 +1,9 @@ +dependencies: + esp-tflite-micro: + git: https://github.com/espressif/esp-tflite-micro.git + mdns: + git: https://github.com/espressif/esp-protocols.git + version: mdns-v1.2.5 + path: components/mdns + rules: + - if: "idf_version >=5.0" diff --git a/script/clang-tidy b/script/clang-tidy index 84b02306d5..bd919825fd 100755 --- a/script/clang-tidy +++ b/script/clang-tidy @@ -101,8 +101,10 @@ def clang_options(idedata): # add library include directories using -isystem to suppress their errors for directory in sorted(set(idedata["includes"]["build"])): # skip our own directories, we add those later - if not directory.startswith(f"{root_path}/") or directory.startswith( - f"{root_path}/.pio/" + if ( + not directory.startswith(f"{root_path}/") + or directory.startswith(f"{root_path}/.pio/") + or directory.startswith(f"{root_path}/managed_components/") ): cmd.extend(["-isystem", directory]) From 5adadeaa07939f593a761cd2a044db8f8d4385d3 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Thu, 13 Jun 2024 05:42:08 -0500 Subject: [PATCH 1596/2101] [esp32_camera] Use newer library version (for #6802) (#6809) --- esphome/components/esp32_camera/__init__.py | 9 ++++++--- esphome/idf_component.yml | 3 +++ platformio.ini | 1 - 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/esphome/components/esp32_camera/__init__.py b/esphome/components/esp32_camera/__init__.py index 462900d401..4187429412 100644 --- a/esphome/components/esp32_camera/__init__.py +++ b/esphome/components/esp32_camera/__init__.py @@ -17,7 +17,7 @@ from esphome.const import ( CONF_VSYNC_PIN, ) from esphome.core import CORE -from esphome.components.esp32 import add_idf_sdkconfig_option +from esphome.components.esp32 import add_idf_component from esphome.cpp_helpers import setup_entity DEPENDENCIES = ["esp32"] @@ -290,8 +290,11 @@ async def to_code(config): cg.add_define("USE_ESP32_CAMERA") if CORE.using_esp_idf: - cg.add_library("espressif/esp32-camera", "1.0.0") - add_idf_sdkconfig_option("CONFIG_RTCIO_SUPPORT_RTC_GPIO_DESC", True) + add_idf_component( + name="esp32-camera", + repo="https://github.com/espressif/esp32-camera.git", + ref="v2.0.9", + ) for conf in config.get(CONF_ON_STREAM_START, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) diff --git a/esphome/idf_component.yml b/esphome/idf_component.yml index ba1a6312e2..c031b2192f 100644 --- a/esphome/idf_component.yml +++ b/esphome/idf_component.yml @@ -1,6 +1,9 @@ dependencies: esp-tflite-micro: git: https://github.com/espressif/esp-tflite-micro.git + esp32_camera: + git: https://github.com/espressif/esp32-camera.git + version: v2.0.9 mdns: git: https://github.com/espressif/esp-protocols.git version: mdns-v1.2.5 diff --git a/platformio.ini b/platformio.ini index 6b34b2f05d..ee82dee243 100644 --- a/platformio.ini +++ b/platformio.ini @@ -142,7 +142,6 @@ platform_packages = framework = espidf lib_deps = ${common:idf.lib_deps} - espressif/esp32-camera@1.0.0 ; esp32_camera droscy/esp_wireguard@0.4.1 ; wireguard build_flags = ${common:idf.build_flags} From 2fc43fa9c71e7f1a5785efffee787033366ca188 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Thu, 13 Jun 2024 19:38:35 -0500 Subject: [PATCH 1597/2101] [micro_wake_word] Pin to esp-tflite-micro v1.3.1 (#6906) --- esphome/components/micro_wake_word/__init__.py | 1 + esphome/idf_component.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/esphome/components/micro_wake_word/__init__.py b/esphome/components/micro_wake_word/__init__.py index def2808e54..35ee3cfedc 100644 --- a/esphome/components/micro_wake_word/__init__.py +++ b/esphome/components/micro_wake_word/__init__.py @@ -312,6 +312,7 @@ async def to_code(config): esp32.add_idf_component( name="esp-tflite-micro", repo="https://github.com/espressif/esp-tflite-micro", + ref="v1.3.1", ) cg.add_build_flag("-DTF_LITE_STATIC_MEMORY") diff --git a/esphome/idf_component.yml b/esphome/idf_component.yml index c031b2192f..5f4701b5a3 100644 --- a/esphome/idf_component.yml +++ b/esphome/idf_component.yml @@ -1,6 +1,7 @@ dependencies: esp-tflite-micro: git: https://github.com/espressif/esp-tflite-micro.git + version: v1.3.1 esp32_camera: git: https://github.com/espressif/esp32-camera.git version: v2.0.9 From 290816be11016699c9413d2c62fb92149f201bb4 Mon Sep 17 00:00:00 2001 From: Anton Viktorov Date: Sun, 16 Jun 2024 09:50:00 +0200 Subject: [PATCH 1598/2101] VEML7700 Fix GCC build warnings (#6881) --- esphome/components/veml7700/veml7700.cpp | 2 +- esphome/components/veml7700/veml7700.h | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/esphome/components/veml7700/veml7700.cpp b/esphome/components/veml7700/veml7700.cpp index 68550811a1..a8c1411c68 100644 --- a/esphome/components/veml7700/veml7700.cpp +++ b/esphome/components/veml7700/veml7700.cpp @@ -243,7 +243,7 @@ ErrorCode VEML7700Component::configure_() { } PSMRegister psm{0}; - psm.PSM = PSM::PSM_MODE_1; + psm.PSM = PSMMode::PSM_MODE_1; psm.PSM_EN = false; ESP_LOGV(TAG, "Setting PSM to 0x%04X", psm.raw); err = this->write_register((uint8_t) CommandRegisters::PWR_SAVING, psm.raw_bytes, VEML_REG_SIZE); diff --git a/esphome/components/veml7700/veml7700.h b/esphome/components/veml7700/veml7700.h index fe5e1158e3..17fee6b851 100644 --- a/esphome/components/veml7700/veml7700.h +++ b/esphome/components/veml7700/veml7700.h @@ -24,7 +24,7 @@ enum class CommandRegisters : uint8_t { ALS_INT = 0x06 // R: ALS INT trigger event }; -enum Gain : uint8_t { +enum Gain : uint16_t { X_1 = 0, X_2 = 1, X_1_8 = 2, @@ -32,7 +32,7 @@ enum Gain : uint8_t { }; const uint8_t GAINS_COUNT = 4; -enum IntegrationTime : uint8_t { +enum IntegrationTime : uint16_t { INTEGRATION_TIME_25MS = 0b1100, INTEGRATION_TIME_50MS = 0b1000, INTEGRATION_TIME_100MS = 0b0000, @@ -42,14 +42,14 @@ enum IntegrationTime : uint8_t { }; const uint8_t INTEGRATION_TIMES_COUNT = 6; -enum Persistence : uint8_t { +enum Persistence : uint16_t { PERSISTENCE_1 = 0, PERSISTENCE_2 = 1, PERSISTENCE_4 = 2, PERSISTENCE_8 = 3, }; -enum PSM : uint8_t { +enum PSMMode : uint16_t { PSM_MODE_1 = 0, PSM_MODE_2 = 1, PSM_MODE_3 = 2, @@ -92,7 +92,7 @@ union PSMRegister { uint8_t raw_bytes[2]; struct { bool PSM_EN : 1; - uint8_t PSM : 2; + PSMMode PSM : 2; uint16_t reserved : 13; } __attribute__((packed)); }; From d49f2cbec80355694f046088ac0c35ef6483f77a Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Sun, 16 Jun 2024 03:02:15 -0500 Subject: [PATCH 1599/2101] IDF 5 fixes for #6802 (#6911) --- esphome/components/ethernet/ethernet_component.cpp | 2 +- esphome/components/voice_assistant/voice_assistant.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index 75bdd29be7..7370cb4b44 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -631,7 +631,7 @@ void EthernetComponent::write_phy_register_(esp_eth_mac_t *mac, PHYRegister regi ESPHL_ERROR_CHECK(err, "Writing PHY Register failed"); if (this->type_ == ETHERNET_TYPE_RTL8201 && register_data.page) { - ESP_LOGD(TAG, "Select PHY Register Page 0x%02" PRIX32, 0x0); + 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"); } diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index 1fa8236cf4..8a8a9e92aa 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -799,7 +799,7 @@ void VoiceAssistant::on_audio(const api::VoiceAssistantAudio &msg) { this->speaker_buffer_index_ += msg.data.length(); this->speaker_buffer_size_ += msg.data.length(); this->speaker_bytes_received_ += msg.data.length(); - ESP_LOGV(TAG, "Received audio: %" PRId32 " bytes from API", msg.data.length()); + ESP_LOGV(TAG, "Received audio: %u bytes from API", msg.data.length()); } else { ESP_LOGE(TAG, "Cannot receive audio, buffer is full"); } From 253303f3a9f27012660e30b7745ddccd5a713715 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 17 Jun 2024 13:01:07 +1200 Subject: [PATCH 1600/2101] [ili9xxx] Fix init for GC9A01A (#6913) --- .../components/ili9xxx/ili9xxx_display.cpp | 20 ++++++++++++++++--- esphome/components/ili9xxx/ili9xxx_display.h | 3 ++- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/esphome/components/ili9xxx/ili9xxx_display.cpp b/esphome/components/ili9xxx/ili9xxx_display.cpp index 21d46ea825..de03df5d41 100644 --- a/esphome/components/ili9xxx/ili9xxx_display.cpp +++ b/esphome/components/ili9xxx/ili9xxx_display.cpp @@ -34,8 +34,8 @@ void ILI9XXXDisplay::setup() { ESP_LOGD(TAG, "Setting up ILI9xxx"); this->setup_pins_(); - this->init_lcd_(this->init_sequence_); - this->init_lcd_(this->extra_init_sequence_.data()); + this->init_lcd(this->init_sequence_); + this->init_lcd(this->extra_init_sequence_.data()); switch (this->pixel_mode_) { case PIXEL_MODE_16: if (this->is_18bitdisplay_) { @@ -405,7 +405,7 @@ void ILI9XXXDisplay::reset_() { } } -void ILI9XXXDisplay::init_lcd_(const uint8_t *addr) { +void ILI9XXXDisplay::init_lcd(const uint8_t *addr) { if (addr == nullptr) return; uint8_t cmd, x, num_args; @@ -427,6 +427,20 @@ void ILI9XXXDisplay::init_lcd_(const uint8_t *addr) { } } +void ILI9XXXGC9A01A::init_lcd(const uint8_t *addr) { + if (addr == nullptr) + return; + uint8_t cmd, x, num_args; + while ((cmd = *addr++) != 0) { + x = *addr++; + num_args = x & 0x7F; + this->send_command(cmd, addr, num_args); + addr += num_args; + if (x & 0x80) + delay(150); // NOLINT + } +} + // Tell the display controller where we want to draw pixels. void ILI9XXXDisplay::set_addr_window_(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) { x1 += this->offset_x_; diff --git a/esphome/components/ili9xxx/ili9xxx_display.h b/esphome/components/ili9xxx/ili9xxx_display.h index 7a320dac7b..b60047a8c3 100644 --- a/esphome/components/ili9xxx/ili9xxx_display.h +++ b/esphome/components/ili9xxx/ili9xxx_display.h @@ -109,7 +109,7 @@ class ILI9XXXDisplay : public display::DisplayBuffer, virtual void set_madctl(); void display_(); - void init_lcd_(const uint8_t *addr); + virtual void init_lcd(const uint8_t *addr); void set_addr_window_(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2); void reset_(); @@ -269,6 +269,7 @@ class ILI9XXXS3BoxLite : public ILI9XXXDisplay { class ILI9XXXGC9A01A : public ILI9XXXDisplay { public: ILI9XXXGC9A01A() : ILI9XXXDisplay(INITCMD_GC9A01A, 240, 240, true) {} + void init_lcd(const uint8_t *addr) override; }; //----------- ILI9XXX_24_TFT display -------------- From 6b89763ad61f4bd0ab5cb8d6417dd678972b6ed6 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 17 Jun 2024 13:20:04 +1200 Subject: [PATCH 1601/2101] [mqtt] Fix datetime copy pasta (#6914) --- esphome/components/mqtt/mqtt_datetime.cpp | 6 +++--- esphome/components/mqtt/mqtt_datetime.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/esphome/components/mqtt/mqtt_datetime.cpp b/esphome/components/mqtt/mqtt_datetime.cpp index 4fa44aafb8..4ae6d0d416 100644 --- a/esphome/components/mqtt/mqtt_datetime.cpp +++ b/esphome/components/mqtt/mqtt_datetime.cpp @@ -6,12 +6,12 @@ #include "mqtt_const.h" #ifdef USE_MQTT -#ifdef USE_DATETIME_TIME +#ifdef USE_DATETIME_DATETIME namespace esphome { namespace mqtt { -static const char *const TAG = "mqtt.datetime.time"; +static const char *const TAG = "mqtt.datetime.datetime"; using namespace esphome::datetime; @@ -80,5 +80,5 @@ bool MQTTDateTimeComponent::publish_state(uint16_t year, uint8_t month, uint8_t } // namespace mqtt } // namespace esphome -#endif // USE_DATETIME_TIME +#endif // USE_DATETIME_DATETIME #endif // USE_MQTT diff --git a/esphome/components/mqtt/mqtt_datetime.h b/esphome/components/mqtt/mqtt_datetime.h index f0d68ad2e1..ba81c06cb3 100644 --- a/esphome/components/mqtt/mqtt_datetime.h +++ b/esphome/components/mqtt/mqtt_datetime.h @@ -3,7 +3,7 @@ #include "esphome/core/defines.h" #ifdef USE_MQTT -#ifdef USE_DATETIME_TIME +#ifdef USE_DATETIME_DATETIME #include "esphome/components/datetime/datetime_entity.h" #include "mqtt_component.h" @@ -17,7 +17,7 @@ class MQTTDateTimeComponent : public mqtt::MQTTComponent { * * @param time The time entity. */ - explicit MQTTDateTimeComponent(datetime::DateTimeEntity *time); + explicit MQTTDateTimeComponent(datetime::DateTimeEntity *datetime); // ========== INTERNAL METHODS ========== // (In most use cases you won't need these) @@ -41,5 +41,5 @@ class MQTTDateTimeComponent : public mqtt::MQTTComponent { } // namespace mqtt } // namespace esphome -#endif // USE_DATETIME_DATE +#endif // USE_DATETIME_DATETIME #endif // USE_MQTT From eb50f0eafd7e920c7405ae476a6878e3c53ee6ba Mon Sep 17 00:00:00 2001 From: esphomebot Date: Thu, 13 Jun 2024 19:24:36 +1200 Subject: [PATCH 1602/2101] Synchronise Device Classes from Home Assistant (#6904) --- esphome/components/update/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/components/update/__init__.py b/esphome/components/update/__init__.py index ae3d5062ab..ea1cf778b6 100644 --- a/esphome/components/update/__init__.py +++ b/esphome/components/update/__init__.py @@ -7,6 +7,7 @@ from esphome.const import ( CONF_ID, CONF_MQTT_ID, CONF_WEB_SERVER_ID, + DEVICE_CLASS_EMPTY, DEVICE_CLASS_FIRMWARE, ) from esphome.core import CORE, coroutine_with_priority @@ -24,6 +25,7 @@ PerformAction = update_ns.class_("PerformAction", automation.Action) IsAvailableCondition = update_ns.class_("IsAvailableCondition", automation.Condition) DEVICE_CLASSES = [ + DEVICE_CLASS_EMPTY, DEVICE_CLASS_FIRMWARE, ] From 1e66241b2696c80f222dd853db76bd10acb48ac4 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 17 Jun 2024 13:01:07 +1200 Subject: [PATCH 1603/2101] [ili9xxx] Fix init for GC9A01A (#6913) --- .../components/ili9xxx/ili9xxx_display.cpp | 20 ++++++++++++++++--- esphome/components/ili9xxx/ili9xxx_display.h | 3 ++- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/esphome/components/ili9xxx/ili9xxx_display.cpp b/esphome/components/ili9xxx/ili9xxx_display.cpp index 21d46ea825..de03df5d41 100644 --- a/esphome/components/ili9xxx/ili9xxx_display.cpp +++ b/esphome/components/ili9xxx/ili9xxx_display.cpp @@ -34,8 +34,8 @@ void ILI9XXXDisplay::setup() { ESP_LOGD(TAG, "Setting up ILI9xxx"); this->setup_pins_(); - this->init_lcd_(this->init_sequence_); - this->init_lcd_(this->extra_init_sequence_.data()); + this->init_lcd(this->init_sequence_); + this->init_lcd(this->extra_init_sequence_.data()); switch (this->pixel_mode_) { case PIXEL_MODE_16: if (this->is_18bitdisplay_) { @@ -405,7 +405,7 @@ void ILI9XXXDisplay::reset_() { } } -void ILI9XXXDisplay::init_lcd_(const uint8_t *addr) { +void ILI9XXXDisplay::init_lcd(const uint8_t *addr) { if (addr == nullptr) return; uint8_t cmd, x, num_args; @@ -427,6 +427,20 @@ void ILI9XXXDisplay::init_lcd_(const uint8_t *addr) { } } +void ILI9XXXGC9A01A::init_lcd(const uint8_t *addr) { + if (addr == nullptr) + return; + uint8_t cmd, x, num_args; + while ((cmd = *addr++) != 0) { + x = *addr++; + num_args = x & 0x7F; + this->send_command(cmd, addr, num_args); + addr += num_args; + if (x & 0x80) + delay(150); // NOLINT + } +} + // Tell the display controller where we want to draw pixels. void ILI9XXXDisplay::set_addr_window_(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) { x1 += this->offset_x_; diff --git a/esphome/components/ili9xxx/ili9xxx_display.h b/esphome/components/ili9xxx/ili9xxx_display.h index 7a320dac7b..b60047a8c3 100644 --- a/esphome/components/ili9xxx/ili9xxx_display.h +++ b/esphome/components/ili9xxx/ili9xxx_display.h @@ -109,7 +109,7 @@ class ILI9XXXDisplay : public display::DisplayBuffer, virtual void set_madctl(); void display_(); - void init_lcd_(const uint8_t *addr); + virtual void init_lcd(const uint8_t *addr); void set_addr_window_(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2); void reset_(); @@ -269,6 +269,7 @@ class ILI9XXXS3BoxLite : public ILI9XXXDisplay { class ILI9XXXGC9A01A : public ILI9XXXDisplay { public: ILI9XXXGC9A01A() : ILI9XXXDisplay(INITCMD_GC9A01A, 240, 240, true) {} + void init_lcd(const uint8_t *addr) override; }; //----------- ILI9XXX_24_TFT display -------------- From 65638bf61420b2278b5043fc98f713475be2b749 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 17 Jun 2024 13:20:04 +1200 Subject: [PATCH 1604/2101] [mqtt] Fix datetime copy pasta (#6914) --- esphome/components/mqtt/mqtt_datetime.cpp | 6 +++--- esphome/components/mqtt/mqtt_datetime.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/esphome/components/mqtt/mqtt_datetime.cpp b/esphome/components/mqtt/mqtt_datetime.cpp index 4fa44aafb8..4ae6d0d416 100644 --- a/esphome/components/mqtt/mqtt_datetime.cpp +++ b/esphome/components/mqtt/mqtt_datetime.cpp @@ -6,12 +6,12 @@ #include "mqtt_const.h" #ifdef USE_MQTT -#ifdef USE_DATETIME_TIME +#ifdef USE_DATETIME_DATETIME namespace esphome { namespace mqtt { -static const char *const TAG = "mqtt.datetime.time"; +static const char *const TAG = "mqtt.datetime.datetime"; using namespace esphome::datetime; @@ -80,5 +80,5 @@ bool MQTTDateTimeComponent::publish_state(uint16_t year, uint8_t month, uint8_t } // namespace mqtt } // namespace esphome -#endif // USE_DATETIME_TIME +#endif // USE_DATETIME_DATETIME #endif // USE_MQTT diff --git a/esphome/components/mqtt/mqtt_datetime.h b/esphome/components/mqtt/mqtt_datetime.h index f0d68ad2e1..ba81c06cb3 100644 --- a/esphome/components/mqtt/mqtt_datetime.h +++ b/esphome/components/mqtt/mqtt_datetime.h @@ -3,7 +3,7 @@ #include "esphome/core/defines.h" #ifdef USE_MQTT -#ifdef USE_DATETIME_TIME +#ifdef USE_DATETIME_DATETIME #include "esphome/components/datetime/datetime_entity.h" #include "mqtt_component.h" @@ -17,7 +17,7 @@ class MQTTDateTimeComponent : public mqtt::MQTTComponent { * * @param time The time entity. */ - explicit MQTTDateTimeComponent(datetime::DateTimeEntity *time); + explicit MQTTDateTimeComponent(datetime::DateTimeEntity *datetime); // ========== INTERNAL METHODS ========== // (In most use cases you won't need these) @@ -41,5 +41,5 @@ class MQTTDateTimeComponent : public mqtt::MQTTComponent { } // namespace mqtt } // namespace esphome -#endif // USE_DATETIME_DATE +#endif // USE_DATETIME_DATETIME #endif // USE_MQTT From 25a3db1637d82fbc36a45c0e1d68f0bee7748718 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 17 Jun 2024 15:35:53 +1200 Subject: [PATCH 1605/2101] Bump version to 2024.6.0b3 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index e2dc5c259a..a0fe325282 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.6.0b2" +__version__ = "2024.6.0b3" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 51c5d1714cb8ee434b1c64d50280e328a11f4abf Mon Sep 17 00:00:00 2001 From: Giel van Schijndel Date: Mon, 17 Jun 2024 07:48:56 +0200 Subject: [PATCH 1606/2101] fix(dallas): make recovery time for 1-bit equal to that of 0-bit (#6763) --- esphome/components/gpio/one_wire/gpio_one_wire.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/gpio/one_wire/gpio_one_wire.cpp b/esphome/components/gpio/one_wire/gpio_one_wire.cpp index f47e8d58e3..34c2cf3c29 100644 --- a/esphome/components/gpio/one_wire/gpio_one_wire.cpp +++ b/esphome/components/gpio/one_wire/gpio_one_wire.cpp @@ -60,7 +60,7 @@ void HOT IRAM_ATTR GPIOOneWireBus::write_bit_(bool bit) { // recovery time: t_rec: min=1µs // ds18b20 appears to read the bus after roughly 14µs uint32_t delay0 = bit ? 6 : 60; - uint32_t delay1 = bit ? 54 : 5; + uint32_t delay1 = bit ? 59 : 5; // delay A/C delayMicroseconds(delay0); From 015cd42a2ed8197e189cc851aea0207bb0fd2b6e Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Mon, 17 Jun 2024 02:06:25 -0500 Subject: [PATCH 1607/2101] [CI-ethernet] Add/fix/organize/clean up ethernet component tests (#6916) --- ...{lan8720.esp32-idf.yaml => common-dp83848.yaml} | 2 +- .../{lan8720.esp32.yaml => common-ip101.yaml} | 2 +- tests/components/ethernet/common-jl1101.yaml | 12 ++++++++++++ tests/components/ethernet/common-ksz8081.yaml | 12 ++++++++++++ tests/components/ethernet/common-ksz8081rna.yaml | 12 ++++++++++++ .../ethernet/{common.yaml => common-lan8720.yaml} | 0 tests/components/ethernet/common-rtl8201.yaml | 12 ++++++++++++ .../{w5500.esp32.yaml => common-w5500.yaml} | 12 ++++++------ .../ethernet/test-dp83848.esp32-idf.yaml | 1 + tests/components/ethernet/test-dp83848.esp32.yaml | 1 + .../components/ethernet/test-ip101.esp32-idf.yaml | 1 + tests/components/ethernet/test-ip101.esp32.yaml | 1 + .../components/ethernet/test-jl1101.esp32-idf.yaml | 1 + tests/components/ethernet/test-jl1101.esp32.yaml | 1 + .../ethernet/test-ksz8081.esp32-idf.yaml | 1 + tests/components/ethernet/test-ksz8081.esp32.yaml | 1 + .../ethernet/test-ksz8081rna.esp32-idf.yaml | 1 + .../components/ethernet/test-ksz8081rna.esp32.yaml | 1 + .../ethernet/test-lan8720.esp32-idf.yaml | 1 + tests/components/ethernet/test-lan8720.esp32.yaml | 1 + .../ethernet/test-rtl8201.esp32-idf.yaml | 1 + tests/components/ethernet/test-rtl8201.esp32.yaml | 1 + .../components/ethernet/test-w5500.esp32-idf.yaml | 1 + tests/components/ethernet/test-w5500.esp32.yaml | 1 + tests/components/ethernet/test.esp32-idf.yaml | 1 - tests/components/ethernet/test.esp32.yaml | 1 - tests/components/ethernet/w5500.esp32-idf.yaml | 14 -------------- 27 files changed, 72 insertions(+), 24 deletions(-) rename tests/components/ethernet/{lan8720.esp32-idf.yaml => common-dp83848.yaml} (92%) rename tests/components/ethernet/{lan8720.esp32.yaml => common-ip101.yaml} (92%) create mode 100644 tests/components/ethernet/common-jl1101.yaml create mode 100644 tests/components/ethernet/common-ksz8081.yaml create mode 100644 tests/components/ethernet/common-ksz8081rna.yaml rename tests/components/ethernet/{common.yaml => common-lan8720.yaml} (100%) create mode 100644 tests/components/ethernet/common-rtl8201.yaml rename tests/components/ethernet/{w5500.esp32.yaml => common-w5500.yaml} (57%) create mode 100644 tests/components/ethernet/test-dp83848.esp32-idf.yaml create mode 100644 tests/components/ethernet/test-dp83848.esp32.yaml create mode 100644 tests/components/ethernet/test-ip101.esp32-idf.yaml create mode 100644 tests/components/ethernet/test-ip101.esp32.yaml create mode 100644 tests/components/ethernet/test-jl1101.esp32-idf.yaml create mode 100644 tests/components/ethernet/test-jl1101.esp32.yaml create mode 100644 tests/components/ethernet/test-ksz8081.esp32-idf.yaml create mode 100644 tests/components/ethernet/test-ksz8081.esp32.yaml create mode 100644 tests/components/ethernet/test-ksz8081rna.esp32-idf.yaml create mode 100644 tests/components/ethernet/test-ksz8081rna.esp32.yaml create mode 100644 tests/components/ethernet/test-lan8720.esp32-idf.yaml create mode 100644 tests/components/ethernet/test-lan8720.esp32.yaml create mode 100644 tests/components/ethernet/test-rtl8201.esp32-idf.yaml create mode 100644 tests/components/ethernet/test-rtl8201.esp32.yaml create mode 100644 tests/components/ethernet/test-w5500.esp32-idf.yaml create mode 100644 tests/components/ethernet/test-w5500.esp32.yaml delete mode 100644 tests/components/ethernet/test.esp32-idf.yaml delete mode 100644 tests/components/ethernet/test.esp32.yaml delete mode 100644 tests/components/ethernet/w5500.esp32-idf.yaml diff --git a/tests/components/ethernet/lan8720.esp32-idf.yaml b/tests/components/ethernet/common-dp83848.yaml similarity index 92% rename from tests/components/ethernet/lan8720.esp32-idf.yaml rename to tests/components/ethernet/common-dp83848.yaml index b9ed9cb036..5b6ed3e8d0 100644 --- a/tests/components/ethernet/lan8720.esp32-idf.yaml +++ b/tests/components/ethernet/common-dp83848.yaml @@ -1,5 +1,5 @@ ethernet: - type: LAN8720 + type: DP83848 mdc_pin: 23 mdio_pin: 25 clk_mode: GPIO0_IN diff --git a/tests/components/ethernet/lan8720.esp32.yaml b/tests/components/ethernet/common-ip101.yaml similarity index 92% rename from tests/components/ethernet/lan8720.esp32.yaml rename to tests/components/ethernet/common-ip101.yaml index b9ed9cb036..5ca369cce1 100644 --- a/tests/components/ethernet/lan8720.esp32.yaml +++ b/tests/components/ethernet/common-ip101.yaml @@ -1,5 +1,5 @@ ethernet: - type: LAN8720 + type: IP101 mdc_pin: 23 mdio_pin: 25 clk_mode: GPIO0_IN diff --git a/tests/components/ethernet/common-jl1101.yaml b/tests/components/ethernet/common-jl1101.yaml new file mode 100644 index 0000000000..639542d807 --- /dev/null +++ b/tests/components/ethernet/common-jl1101.yaml @@ -0,0 +1,12 @@ +ethernet: + type: JL1101 + mdc_pin: 23 + mdio_pin: 25 + clk_mode: GPIO0_IN + phy_addr: 0 + power_pin: 26 + manual_ip: + static_ip: 192.168.178.56 + gateway: 192.168.178.1 + subnet: 255.255.255.0 + domain: .local diff --git a/tests/components/ethernet/common-ksz8081.yaml b/tests/components/ethernet/common-ksz8081.yaml new file mode 100644 index 0000000000..167606a1eb --- /dev/null +++ b/tests/components/ethernet/common-ksz8081.yaml @@ -0,0 +1,12 @@ +ethernet: + type: KSZ8081 + mdc_pin: 23 + mdio_pin: 25 + clk_mode: GPIO0_IN + phy_addr: 0 + power_pin: 26 + manual_ip: + static_ip: 192.168.178.56 + gateway: 192.168.178.1 + subnet: 255.255.255.0 + domain: .local diff --git a/tests/components/ethernet/common-ksz8081rna.yaml b/tests/components/ethernet/common-ksz8081rna.yaml new file mode 100644 index 0000000000..f506906b1b --- /dev/null +++ b/tests/components/ethernet/common-ksz8081rna.yaml @@ -0,0 +1,12 @@ +ethernet: + type: KSZ8081RNA + mdc_pin: 23 + mdio_pin: 25 + clk_mode: GPIO0_IN + phy_addr: 0 + power_pin: 26 + manual_ip: + static_ip: 192.168.178.56 + gateway: 192.168.178.1 + subnet: 255.255.255.0 + domain: .local diff --git a/tests/components/ethernet/common.yaml b/tests/components/ethernet/common-lan8720.yaml similarity index 100% rename from tests/components/ethernet/common.yaml rename to tests/components/ethernet/common-lan8720.yaml diff --git a/tests/components/ethernet/common-rtl8201.yaml b/tests/components/ethernet/common-rtl8201.yaml new file mode 100644 index 0000000000..43842e7c9f --- /dev/null +++ b/tests/components/ethernet/common-rtl8201.yaml @@ -0,0 +1,12 @@ +ethernet: + type: RTL8201 + mdc_pin: 23 + mdio_pin: 25 + clk_mode: GPIO0_IN + phy_addr: 0 + power_pin: 26 + manual_ip: + static_ip: 192.168.178.56 + gateway: 192.168.178.1 + subnet: 255.255.255.0 + domain: .local diff --git a/tests/components/ethernet/w5500.esp32.yaml b/tests/components/ethernet/common-w5500.yaml similarity index 57% rename from tests/components/ethernet/w5500.esp32.yaml rename to tests/components/ethernet/common-w5500.yaml index 6fdccb36e3..76661a75c3 100644 --- a/tests/components/ethernet/w5500.esp32.yaml +++ b/tests/components/ethernet/common-w5500.yaml @@ -1,11 +1,11 @@ ethernet: type: W5500 - clk_pin: GPIO19 - mosi_pin: GPIO21 - miso_pin: GPIO23 - cs_pin: GPIO18 - interrupt_pin: GPIO36 - reset_pin: GPIO22 + 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 diff --git a/tests/components/ethernet/test-dp83848.esp32-idf.yaml b/tests/components/ethernet/test-dp83848.esp32-idf.yaml new file mode 100644 index 0000000000..906bfba17c --- /dev/null +++ b/tests/components/ethernet/test-dp83848.esp32-idf.yaml @@ -0,0 +1 @@ +<<: !include common-dp83848.yaml diff --git a/tests/components/ethernet/test-dp83848.esp32.yaml b/tests/components/ethernet/test-dp83848.esp32.yaml new file mode 100644 index 0000000000..906bfba17c --- /dev/null +++ b/tests/components/ethernet/test-dp83848.esp32.yaml @@ -0,0 +1 @@ +<<: !include common-dp83848.yaml diff --git a/tests/components/ethernet/test-ip101.esp32-idf.yaml b/tests/components/ethernet/test-ip101.esp32-idf.yaml new file mode 100644 index 0000000000..e52329d7ea --- /dev/null +++ b/tests/components/ethernet/test-ip101.esp32-idf.yaml @@ -0,0 +1 @@ +<<: !include common-ip101.yaml diff --git a/tests/components/ethernet/test-ip101.esp32.yaml b/tests/components/ethernet/test-ip101.esp32.yaml new file mode 100644 index 0000000000..e52329d7ea --- /dev/null +++ b/tests/components/ethernet/test-ip101.esp32.yaml @@ -0,0 +1 @@ +<<: !include common-ip101.yaml diff --git a/tests/components/ethernet/test-jl1101.esp32-idf.yaml b/tests/components/ethernet/test-jl1101.esp32-idf.yaml new file mode 100644 index 0000000000..95d8cd1f21 --- /dev/null +++ b/tests/components/ethernet/test-jl1101.esp32-idf.yaml @@ -0,0 +1 @@ +<<: !include common-jl1101.yaml diff --git a/tests/components/ethernet/test-jl1101.esp32.yaml b/tests/components/ethernet/test-jl1101.esp32.yaml new file mode 100644 index 0000000000..95d8cd1f21 --- /dev/null +++ b/tests/components/ethernet/test-jl1101.esp32.yaml @@ -0,0 +1 @@ +<<: !include common-jl1101.yaml diff --git a/tests/components/ethernet/test-ksz8081.esp32-idf.yaml b/tests/components/ethernet/test-ksz8081.esp32-idf.yaml new file mode 100644 index 0000000000..8f3c750c77 --- /dev/null +++ b/tests/components/ethernet/test-ksz8081.esp32-idf.yaml @@ -0,0 +1 @@ +<<: !include common-ksz8081.yaml diff --git a/tests/components/ethernet/test-ksz8081.esp32.yaml b/tests/components/ethernet/test-ksz8081.esp32.yaml new file mode 100644 index 0000000000..8f3c750c77 --- /dev/null +++ b/tests/components/ethernet/test-ksz8081.esp32.yaml @@ -0,0 +1 @@ +<<: !include common-ksz8081.yaml diff --git a/tests/components/ethernet/test-ksz8081rna.esp32-idf.yaml b/tests/components/ethernet/test-ksz8081rna.esp32-idf.yaml new file mode 100644 index 0000000000..a48e591996 --- /dev/null +++ b/tests/components/ethernet/test-ksz8081rna.esp32-idf.yaml @@ -0,0 +1 @@ +<<: !include common-ksz8081rna.yaml diff --git a/tests/components/ethernet/test-ksz8081rna.esp32.yaml b/tests/components/ethernet/test-ksz8081rna.esp32.yaml new file mode 100644 index 0000000000..a48e591996 --- /dev/null +++ b/tests/components/ethernet/test-ksz8081rna.esp32.yaml @@ -0,0 +1 @@ +<<: !include common-ksz8081rna.yaml diff --git a/tests/components/ethernet/test-lan8720.esp32-idf.yaml b/tests/components/ethernet/test-lan8720.esp32-idf.yaml new file mode 100644 index 0000000000..3df9ac874a --- /dev/null +++ b/tests/components/ethernet/test-lan8720.esp32-idf.yaml @@ -0,0 +1 @@ +<<: !include common-lan8720.yaml diff --git a/tests/components/ethernet/test-lan8720.esp32.yaml b/tests/components/ethernet/test-lan8720.esp32.yaml new file mode 100644 index 0000000000..3df9ac874a --- /dev/null +++ b/tests/components/ethernet/test-lan8720.esp32.yaml @@ -0,0 +1 @@ +<<: !include common-lan8720.yaml diff --git a/tests/components/ethernet/test-rtl8201.esp32-idf.yaml b/tests/components/ethernet/test-rtl8201.esp32-idf.yaml new file mode 100644 index 0000000000..e69f88dc94 --- /dev/null +++ b/tests/components/ethernet/test-rtl8201.esp32-idf.yaml @@ -0,0 +1 @@ +<<: !include common-rtl8201.yaml diff --git a/tests/components/ethernet/test-rtl8201.esp32.yaml b/tests/components/ethernet/test-rtl8201.esp32.yaml new file mode 100644 index 0000000000..e69f88dc94 --- /dev/null +++ b/tests/components/ethernet/test-rtl8201.esp32.yaml @@ -0,0 +1 @@ +<<: !include common-rtl8201.yaml diff --git a/tests/components/ethernet/test-w5500.esp32-idf.yaml b/tests/components/ethernet/test-w5500.esp32-idf.yaml new file mode 100644 index 0000000000..36f1b5365f --- /dev/null +++ b/tests/components/ethernet/test-w5500.esp32-idf.yaml @@ -0,0 +1 @@ +<<: !include common-w5500.yaml diff --git a/tests/components/ethernet/test-w5500.esp32.yaml b/tests/components/ethernet/test-w5500.esp32.yaml new file mode 100644 index 0000000000..36f1b5365f --- /dev/null +++ b/tests/components/ethernet/test-w5500.esp32.yaml @@ -0,0 +1 @@ +<<: !include common-w5500.yaml diff --git a/tests/components/ethernet/test.esp32-idf.yaml b/tests/components/ethernet/test.esp32-idf.yaml deleted file mode 100644 index dade44d145..0000000000 --- a/tests/components/ethernet/test.esp32-idf.yaml +++ /dev/null @@ -1 +0,0 @@ -<<: !include common.yaml diff --git a/tests/components/ethernet/test.esp32.yaml b/tests/components/ethernet/test.esp32.yaml deleted file mode 100644 index dade44d145..0000000000 --- a/tests/components/ethernet/test.esp32.yaml +++ /dev/null @@ -1 +0,0 @@ -<<: !include common.yaml diff --git a/tests/components/ethernet/w5500.esp32-idf.yaml b/tests/components/ethernet/w5500.esp32-idf.yaml deleted file mode 100644 index 6fdccb36e3..0000000000 --- a/tests/components/ethernet/w5500.esp32-idf.yaml +++ /dev/null @@ -1,14 +0,0 @@ -ethernet: - type: W5500 - clk_pin: GPIO19 - mosi_pin: GPIO21 - miso_pin: GPIO23 - cs_pin: GPIO18 - interrupt_pin: GPIO36 - reset_pin: GPIO22 - clock_speed: 10Mhz - manual_ip: - static_ip: 192.168.178.56 - gateway: 192.168.178.1 - subnet: 255.255.255.0 - domain: .local From 67d8c7c69164c48debffff6868c2dc9282ffc37b Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Mon, 17 Jun 2024 02:14:19 -0500 Subject: [PATCH 1608/2101] [CI-a01nyub] Consolidate test files (#6917) --- tests/components/a01nyub/common.yaml | 11 +++++++++++ tests/components/a01nyub/test.esp32-c3-idf.yaml | 16 ++++------------ tests/components/a01nyub/test.esp32-c3.yaml | 16 ++++------------ tests/components/a01nyub/test.esp32-idf.yaml | 16 ++++------------ tests/components/a01nyub/test.esp32.yaml | 16 ++++------------ tests/components/a01nyub/test.esp8266.yaml | 16 ++++------------ tests/components/a01nyub/test.rp2040.yaml | 16 ++++------------ 7 files changed, 35 insertions(+), 72 deletions(-) create mode 100644 tests/components/a01nyub/common.yaml diff --git a/tests/components/a01nyub/common.yaml b/tests/components/a01nyub/common.yaml new file mode 100644 index 0000000000..0717acfff7 --- /dev/null +++ b/tests/components/a01nyub/common.yaml @@ -0,0 +1,11 @@ +uart: + - id: uart_a01nyub + tx_pin: ${tx_pin} + rx_pin: ${rx_pin} + baud_rate: 9600 + +sensor: + - platform: a01nyub + id: a01nyub_sensor + name: a01nyub Distance + uart_id: uart_a01nyub diff --git a/tests/components/a01nyub/test.esp32-c3-idf.yaml b/tests/components/a01nyub/test.esp32-c3-idf.yaml index 3132f77136..b516342f3b 100644 --- a/tests/components/a01nyub/test.esp32-c3-idf.yaml +++ b/tests/components/a01nyub/test.esp32-c3-idf.yaml @@ -1,13 +1,5 @@ -uart: - - id: uart_a01nyub - tx_pin: - number: 4 - rx_pin: - number: 5 - baud_rate: 9600 +substitutions: + tx_pin: GPIO4 + rx_pin: GPIO5 -sensor: - - platform: a01nyub - id: a01nyub_sensor - name: a01nyub Distance - uart_id: uart_a01nyub +<<: !include common.yaml diff --git a/tests/components/a01nyub/test.esp32-c3.yaml b/tests/components/a01nyub/test.esp32-c3.yaml index 3132f77136..b516342f3b 100644 --- a/tests/components/a01nyub/test.esp32-c3.yaml +++ b/tests/components/a01nyub/test.esp32-c3.yaml @@ -1,13 +1,5 @@ -uart: - - id: uart_a01nyub - tx_pin: - number: 4 - rx_pin: - number: 5 - baud_rate: 9600 +substitutions: + tx_pin: GPIO4 + rx_pin: GPIO5 -sensor: - - platform: a01nyub - id: a01nyub_sensor - name: a01nyub Distance - uart_id: uart_a01nyub +<<: !include common.yaml diff --git a/tests/components/a01nyub/test.esp32-idf.yaml b/tests/components/a01nyub/test.esp32-idf.yaml index 79fc9c5fbf..f486544afa 100644 --- a/tests/components/a01nyub/test.esp32-idf.yaml +++ b/tests/components/a01nyub/test.esp32-idf.yaml @@ -1,13 +1,5 @@ -uart: - - id: uart_a01nyub - tx_pin: - number: 17 - rx_pin: - number: 16 - baud_rate: 9600 +substitutions: + tx_pin: GPIO17 + rx_pin: GPIO16 -sensor: - - platform: a01nyub - id: a01nyub_sensor - name: a01nyub Distance - uart_id: uart_a01nyub +<<: !include common.yaml diff --git a/tests/components/a01nyub/test.esp32.yaml b/tests/components/a01nyub/test.esp32.yaml index 79fc9c5fbf..f486544afa 100644 --- a/tests/components/a01nyub/test.esp32.yaml +++ b/tests/components/a01nyub/test.esp32.yaml @@ -1,13 +1,5 @@ -uart: - - id: uart_a01nyub - tx_pin: - number: 17 - rx_pin: - number: 16 - baud_rate: 9600 +substitutions: + tx_pin: GPIO17 + rx_pin: GPIO16 -sensor: - - platform: a01nyub - id: a01nyub_sensor - name: a01nyub Distance - uart_id: uart_a01nyub +<<: !include common.yaml diff --git a/tests/components/a01nyub/test.esp8266.yaml b/tests/components/a01nyub/test.esp8266.yaml index 3132f77136..b516342f3b 100644 --- a/tests/components/a01nyub/test.esp8266.yaml +++ b/tests/components/a01nyub/test.esp8266.yaml @@ -1,13 +1,5 @@ -uart: - - id: uart_a01nyub - tx_pin: - number: 4 - rx_pin: - number: 5 - baud_rate: 9600 +substitutions: + tx_pin: GPIO4 + rx_pin: GPIO5 -sensor: - - platform: a01nyub - id: a01nyub_sensor - name: a01nyub Distance - uart_id: uart_a01nyub +<<: !include common.yaml diff --git a/tests/components/a01nyub/test.rp2040.yaml b/tests/components/a01nyub/test.rp2040.yaml index 3132f77136..b516342f3b 100644 --- a/tests/components/a01nyub/test.rp2040.yaml +++ b/tests/components/a01nyub/test.rp2040.yaml @@ -1,13 +1,5 @@ -uart: - - id: uart_a01nyub - tx_pin: - number: 4 - rx_pin: - number: 5 - baud_rate: 9600 +substitutions: + tx_pin: GPIO4 + rx_pin: GPIO5 -sensor: - - platform: a01nyub - id: a01nyub_sensor - name: a01nyub Distance - uart_id: uart_a01nyub +<<: !include common.yaml From d604c8ae644ee91c714c1ae887b7fcbf400a759b Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Mon, 17 Jun 2024 02:18:04 -0500 Subject: [PATCH 1609/2101] [CI-api] Test fix for IDF 5+ (#6918) --- tests/components/api/common.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/components/api/common.yaml b/tests/components/api/common.yaml index 3c56811b95..e0b900f92d 100644 --- a/tests/components/api/common.yaml +++ b/tests/components/api/common.yaml @@ -50,12 +50,12 @@ api: then: - logger.log: # yamllint disable rule:line-length - format: "Bool: %s (%u), Int: %d (%u), Float: %f (%u), String: %s (%u)" + format: "Bool: %s (%u), Int: %ld (%u), Float: %f (%u), String: %s (%u)" # yamllint enable rule:line-length args: - YESNO(bool_arr[0]) - bool_arr.size() - - int_arr[0] + - (long) int_arr[0] - int_arr.size() - float_arr[0] - float_arr.size() From 41f810f8285c7f94d0f629e30828848d13cb734b Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Mon, 17 Jun 2024 02:21:15 -0500 Subject: [PATCH 1610/2101] [CI-http_request] Test fix for IDF 5+ (#6919) --- tests/components/http_request/common.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/components/http_request/common.yaml b/tests/components/http_request/common.yaml index 83b334ca2d..589b7fb4b4 100644 --- a/tests/components/http_request/common.yaml +++ b/tests/components/http_request/common.yaml @@ -15,10 +15,10 @@ esphome: on_response: then: - logger.log: - format: "Response status: %d, Duration: %u ms" + format: "Response status: %d, Duration: %lu ms" args: - response->status_code - - response->duration_ms + - (long) response->duration_ms - http_request.post: url: https://esphome.io headers: From c30913ccdeebb4627a864132e8cd37c5264e88a5 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Mon, 17 Jun 2024 02:23:24 -0500 Subject: [PATCH 1611/2101] [CI-wireguard] Test file consolidation (#6920) --- tests/components/wireguard/common.yaml | 59 ++++++++++++++++++ tests/components/wireguard/test.bk72xx.yaml | 60 +----------------- .../wireguard/test.esp32-c3-idf.yaml | 61 +------------------ tests/components/wireguard/test.esp32-c3.yaml | 61 +------------------ .../components/wireguard/test.esp32-idf.yaml | 60 +----------------- tests/components/wireguard/test.esp32.yaml | 60 +----------------- tests/components/wireguard/test.esp8266.yaml | 60 +----------------- 7 files changed, 65 insertions(+), 356 deletions(-) create mode 100644 tests/components/wireguard/common.yaml diff --git a/tests/components/wireguard/common.yaml b/tests/components/wireguard/common.yaml new file mode 100644 index 0000000000..cd7ab1075e --- /dev/null +++ b/tests/components/wireguard/common.yaml @@ -0,0 +1,59 @@ +wifi: + ssid: "MySSID1" + password: "password1" + +time: + - platform: sntp + +wireguard: + address: 172.16.34.100 + netmask: 255.255.255.0 + # NEVER use the following keys for your VPN -- they are now public! + private_key: wPBMxtNYH3mChicrbpsRpZIasIdPq3yZuthn23FbGG8= + peer_public_key: Hs2JfikvYU03/Kv3YoAs1hrUIPPTEkpsZKSPUljE9yc= + peer_preshared_key: 20fjM5GRnSolGPC5SRj9ljgIUyQfruv0B0bvLl3Yt60= + peer_endpoint: wg.server.example + peer_persistent_keepalive: 25s + peer_allowed_ips: + - 172.16.34.0/24 + - 192.168.4.0/24 + +binary_sensor: + - platform: wireguard + status: + name: 'WireGuard Status' + enabled: + name: 'WireGuard Enabled' + +sensor: + - platform: wireguard + latest_handshake: + name: 'WireGuard Latest Handshake' + +text_sensor: + - platform: wireguard + address: + name: 'WireGuard Address' + +button: + - platform: template + name: 'Toggle WireGuard' + entity_category: config + on_press: + - if: + condition: wireguard.enabled + then: + - wireguard.disable: + else: + - wireguard.enable: + + - platform: template + name: 'Log WireGuard status' + entity_category: config + on_press: + - if: + condition: wireguard.peer_online + then: + - logger.log: 'wireguard remote peer is online' + else: + - logger.log: 'wireguard remote peer is offline' diff --git a/tests/components/wireguard/test.bk72xx.yaml b/tests/components/wireguard/test.bk72xx.yaml index 85325139a9..dade44d145 100644 --- a/tests/components/wireguard/test.bk72xx.yaml +++ b/tests/components/wireguard/test.bk72xx.yaml @@ -1,59 +1 @@ -wifi: - ssid: "MySSID1" - password: "password1" - -time: - - platform: sntp - -wireguard: - address: 172.16.34.100 - netmask: 255.255.255.0 - # NEVER use the following keys for your vpn, they are now public! - private_key: wPBMxtNYH3mChicrbpsRpZIasIdPq3yZuthn23FbGG8= - peer_public_key: Hs2JfikvYU03/Kv3YoAs1hrUIPPTEkpsZKSPUljE9yc= - peer_preshared_key: 20fjM5GRnSolGPC5SRj9ljgIUyQfruv0B0bvLl3Yt60= - peer_endpoint: wg.server.example - peer_persistent_keepalive: 25s - peer_allowed_ips: - - 172.16.34.0/24 - - 192.168.4.0/24 - -binary_sensor: - - platform: wireguard - status: - name: 'WireGuard Status' - enabled: - name: 'WireGuard Enabled' - -sensor: - - platform: wireguard - latest_handshake: - name: 'WireGuard Latest Handshake' - -text_sensor: - - platform: wireguard - address: - name: 'WireGuard Address' - -button: - - platform: template - name: 'Toggle WireGuard' - entity_category: config - on_press: - - if: - condition: wireguard.enabled - then: - - wireguard.disable: - else: - - wireguard.enable: - - - platform: template - name: 'Log WireGuard status' - entity_category: config - on_press: - - if: - condition: wireguard.peer_online - then: - - logger.log: 'wireguard remote peer is online' - else: - - logger.log: 'wireguard remote peer is offline' +<<: !include common.yaml diff --git a/tests/components/wireguard/test.esp32-c3-idf.yaml b/tests/components/wireguard/test.esp32-c3-idf.yaml index 37d1727842..dade44d145 100644 --- a/tests/components/wireguard/test.esp32-c3-idf.yaml +++ b/tests/components/wireguard/test.esp32-c3-idf.yaml @@ -1,60 +1 @@ -wifi: - ssid: MySSID - password: password1 - -time: - - platform: sntp - -wireguard: - id: vpn - address: 172.16.34.100 - netmask: 255.255.255.0 - # NEVER use the following keys for your vpn, they are now public! - private_key: wPBMxtNYH3mChicrbpsRpZIasIdPq3yZuthn23FbGG8= - peer_public_key: Hs2JfikvYU03/Kv3YoAs1hrUIPPTEkpsZKSPUljE9yc= - peer_preshared_key: 20fjM5GRnSolGPC5SRj9ljgIUyQfruv0B0bvLl3Yt60= - peer_endpoint: wg.server.example - peer_persistent_keepalive: 25s - peer_allowed_ips: - - 172.16.34.0/24 - - 192.168.4.0/24 - -binary_sensor: - - platform: wireguard - status: - name: 'WireGuard Status' - enabled: - name: 'WireGuard Enabled' - -sensor: - - platform: wireguard - latest_handshake: - name: 'WireGuard Latest Handshake' - -text_sensor: - - platform: wireguard - address: - name: 'WireGuard Address' - -button: - - platform: template - name: 'Toggle WireGuard' - entity_category: config - on_press: - - if: - condition: wireguard.enabled - then: - - wireguard.disable: - else: - - wireguard.enable: - - - platform: template - name: 'Log WireGuard status' - entity_category: config - on_press: - - if: - condition: wireguard.peer_online - then: - - logger.log: 'wireguard remote peer is online' - else: - - logger.log: 'wireguard remote peer is offline' +<<: !include common.yaml diff --git a/tests/components/wireguard/test.esp32-c3.yaml b/tests/components/wireguard/test.esp32-c3.yaml index 37d1727842..dade44d145 100644 --- a/tests/components/wireguard/test.esp32-c3.yaml +++ b/tests/components/wireguard/test.esp32-c3.yaml @@ -1,60 +1 @@ -wifi: - ssid: MySSID - password: password1 - -time: - - platform: sntp - -wireguard: - id: vpn - address: 172.16.34.100 - netmask: 255.255.255.0 - # NEVER use the following keys for your vpn, they are now public! - private_key: wPBMxtNYH3mChicrbpsRpZIasIdPq3yZuthn23FbGG8= - peer_public_key: Hs2JfikvYU03/Kv3YoAs1hrUIPPTEkpsZKSPUljE9yc= - peer_preshared_key: 20fjM5GRnSolGPC5SRj9ljgIUyQfruv0B0bvLl3Yt60= - peer_endpoint: wg.server.example - peer_persistent_keepalive: 25s - peer_allowed_ips: - - 172.16.34.0/24 - - 192.168.4.0/24 - -binary_sensor: - - platform: wireguard - status: - name: 'WireGuard Status' - enabled: - name: 'WireGuard Enabled' - -sensor: - - platform: wireguard - latest_handshake: - name: 'WireGuard Latest Handshake' - -text_sensor: - - platform: wireguard - address: - name: 'WireGuard Address' - -button: - - platform: template - name: 'Toggle WireGuard' - entity_category: config - on_press: - - if: - condition: wireguard.enabled - then: - - wireguard.disable: - else: - - wireguard.enable: - - - platform: template - name: 'Log WireGuard status' - entity_category: config - on_press: - - if: - condition: wireguard.peer_online - then: - - logger.log: 'wireguard remote peer is online' - else: - - logger.log: 'wireguard remote peer is offline' +<<: !include common.yaml diff --git a/tests/components/wireguard/test.esp32-idf.yaml b/tests/components/wireguard/test.esp32-idf.yaml index 9ea7f00bdb..2798f8e566 100644 --- a/tests/components/wireguard/test.esp32-idf.yaml +++ b/tests/components/wireguard/test.esp32-idf.yaml @@ -1,62 +1,4 @@ -wifi: - ssid: "MySSID1" - password: "password1" +<<: !include common.yaml network: enable_ipv6: true - -time: - - platform: sntp - -wireguard: - address: 172.16.34.100 - netmask: 255.255.255.0 - # NEVER use the following keys for your vpn, they are now public! - private_key: wPBMxtNYH3mChicrbpsRpZIasIdPq3yZuthn23FbGG8= - peer_public_key: Hs2JfikvYU03/Kv3YoAs1hrUIPPTEkpsZKSPUljE9yc= - peer_preshared_key: 20fjM5GRnSolGPC5SRj9ljgIUyQfruv0B0bvLl3Yt60= - peer_endpoint: wg.server.example - peer_persistent_keepalive: 25s - peer_allowed_ips: - - 172.16.34.0/24 - - 192.168.4.0/24 - -binary_sensor: - - platform: wireguard - status: - name: 'WireGuard Status' - enabled: - name: 'WireGuard Enabled' - -sensor: - - platform: wireguard - latest_handshake: - name: 'WireGuard Latest Handshake' - -text_sensor: - - platform: wireguard - address: - name: 'WireGuard Address' - -button: - - platform: template - name: 'Toggle WireGuard' - entity_category: config - on_press: - - if: - condition: wireguard.enabled - then: - - wireguard.disable: - else: - - wireguard.enable: - - - platform: template - name: 'Log WireGuard status' - entity_category: config - on_press: - - if: - condition: wireguard.peer_online - then: - - logger.log: 'wireguard remote peer is online' - else: - - logger.log: 'wireguard remote peer is offline' diff --git a/tests/components/wireguard/test.esp32.yaml b/tests/components/wireguard/test.esp32.yaml index 9ea7f00bdb..2798f8e566 100644 --- a/tests/components/wireguard/test.esp32.yaml +++ b/tests/components/wireguard/test.esp32.yaml @@ -1,62 +1,4 @@ -wifi: - ssid: "MySSID1" - password: "password1" +<<: !include common.yaml network: enable_ipv6: true - -time: - - platform: sntp - -wireguard: - address: 172.16.34.100 - netmask: 255.255.255.0 - # NEVER use the following keys for your vpn, they are now public! - private_key: wPBMxtNYH3mChicrbpsRpZIasIdPq3yZuthn23FbGG8= - peer_public_key: Hs2JfikvYU03/Kv3YoAs1hrUIPPTEkpsZKSPUljE9yc= - peer_preshared_key: 20fjM5GRnSolGPC5SRj9ljgIUyQfruv0B0bvLl3Yt60= - peer_endpoint: wg.server.example - peer_persistent_keepalive: 25s - peer_allowed_ips: - - 172.16.34.0/24 - - 192.168.4.0/24 - -binary_sensor: - - platform: wireguard - status: - name: 'WireGuard Status' - enabled: - name: 'WireGuard Enabled' - -sensor: - - platform: wireguard - latest_handshake: - name: 'WireGuard Latest Handshake' - -text_sensor: - - platform: wireguard - address: - name: 'WireGuard Address' - -button: - - platform: template - name: 'Toggle WireGuard' - entity_category: config - on_press: - - if: - condition: wireguard.enabled - then: - - wireguard.disable: - else: - - wireguard.enable: - - - platform: template - name: 'Log WireGuard status' - entity_category: config - on_press: - - if: - condition: wireguard.peer_online - then: - - logger.log: 'wireguard remote peer is online' - else: - - logger.log: 'wireguard remote peer is offline' diff --git a/tests/components/wireguard/test.esp8266.yaml b/tests/components/wireguard/test.esp8266.yaml index 9ea7f00bdb..2798f8e566 100644 --- a/tests/components/wireguard/test.esp8266.yaml +++ b/tests/components/wireguard/test.esp8266.yaml @@ -1,62 +1,4 @@ -wifi: - ssid: "MySSID1" - password: "password1" +<<: !include common.yaml network: enable_ipv6: true - -time: - - platform: sntp - -wireguard: - address: 172.16.34.100 - netmask: 255.255.255.0 - # NEVER use the following keys for your vpn, they are now public! - private_key: wPBMxtNYH3mChicrbpsRpZIasIdPq3yZuthn23FbGG8= - peer_public_key: Hs2JfikvYU03/Kv3YoAs1hrUIPPTEkpsZKSPUljE9yc= - peer_preshared_key: 20fjM5GRnSolGPC5SRj9ljgIUyQfruv0B0bvLl3Yt60= - peer_endpoint: wg.server.example - peer_persistent_keepalive: 25s - peer_allowed_ips: - - 172.16.34.0/24 - - 192.168.4.0/24 - -binary_sensor: - - platform: wireguard - status: - name: 'WireGuard Status' - enabled: - name: 'WireGuard Enabled' - -sensor: - - platform: wireguard - latest_handshake: - name: 'WireGuard Latest Handshake' - -text_sensor: - - platform: wireguard - address: - name: 'WireGuard Address' - -button: - - platform: template - name: 'Toggle WireGuard' - entity_category: config - on_press: - - if: - condition: wireguard.enabled - then: - - wireguard.disable: - else: - - wireguard.enable: - - - platform: template - name: 'Log WireGuard status' - entity_category: config - on_press: - - if: - condition: wireguard.peer_online - then: - - logger.log: 'wireguard remote peer is online' - else: - - logger.log: 'wireguard remote peer is offline' From a59c9b4f771f6d6a65af6caa33b0c0edae6af087 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Mon, 17 Jun 2024 02:30:54 -0500 Subject: [PATCH 1612/2101] [CI-esp32_hall] Remove IDF test (#6921) --- tests/components/esp32_hall/common.yaml | 3 --- tests/components/esp32_hall/test.esp32-idf.yaml | 1 - tests/components/esp32_hall/test.esp32.yaml | 4 +++- 3 files changed, 3 insertions(+), 5 deletions(-) delete mode 100644 tests/components/esp32_hall/common.yaml delete mode 100644 tests/components/esp32_hall/test.esp32-idf.yaml diff --git a/tests/components/esp32_hall/common.yaml b/tests/components/esp32_hall/common.yaml deleted file mode 100644 index f8429f5aa0..0000000000 --- a/tests/components/esp32_hall/common.yaml +++ /dev/null @@ -1,3 +0,0 @@ -sensor: - - platform: esp32_hall - name: ESP32 Hall Sensor diff --git a/tests/components/esp32_hall/test.esp32-idf.yaml b/tests/components/esp32_hall/test.esp32-idf.yaml deleted file mode 100644 index dade44d145..0000000000 --- a/tests/components/esp32_hall/test.esp32-idf.yaml +++ /dev/null @@ -1 +0,0 @@ -<<: !include common.yaml diff --git a/tests/components/esp32_hall/test.esp32.yaml b/tests/components/esp32_hall/test.esp32.yaml index dade44d145..f8429f5aa0 100644 --- a/tests/components/esp32_hall/test.esp32.yaml +++ b/tests/components/esp32_hall/test.esp32.yaml @@ -1 +1,3 @@ -<<: !include common.yaml +sensor: + - platform: esp32_hall + name: ESP32 Hall Sensor From f6848fe24d58ac7bcb1bc79e210a41a2f09bf571 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Mon, 17 Jun 2024 16:32:11 -0500 Subject: [PATCH 1613/2101] [CI] Introduce testing for IDF 5 (and other arbitrary framework versions) (#6802) * Initial changes to support testing of additional framework versions * Rename Arduino test files --- script/test_build_components | 25 ++++++++++--------- .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...t.esp32-s2.yaml => test.esp32-s2-ard.yaml} | 0 ...t.esp32-s3.yaml => test.esp32-s3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...{test.bk72xx.yaml => test.bk72xx-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...esp32.yaml => test-dp83848.esp32-ard.yaml} | 0 ...1.esp32.yaml => test-ip101.esp32-ard.yaml} | 0 ....esp32.yaml => test-jl1101.esp32-ard.yaml} | 0 ...esp32.yaml => test-ksz8081.esp32-ard.yaml} | 0 ...32.yaml => test-ksz8081rna.esp32-ard.yaml} | 0 ...esp32.yaml => test-lan8720.esp32-ard.yaml} | 0 ...esp32.yaml => test-rtl8201.esp32-ard.yaml} | 0 ...0.esp32.yaml => test-w5500.esp32-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...{test.bk72xx.yaml => test.bk72xx-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...p8266.yaml => test-nossl.esp8266-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...t.esp32-s2.yaml => test.esp32-s2-ard.yaml} | 0 ...t.esp32-s3.yaml => test.esp32-s3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...{test.bk72xx.yaml => test.bk72xx-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-s2.yaml => test.esp32-c3-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-s2-ard.yaml} | 0 ...t.esp32-s3.yaml => test.esp32-s3-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...{test.bk72xx.yaml => test.bk72xx-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...t.esp32-s2.yaml => test.esp32-s2-ard.yaml} | 0 ...t.esp32-s3.yaml => test.esp32-s3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...t.esp32-s2.yaml => test.esp32-s2-ard.yaml} | 0 ...t.esp32-s3.yaml => test.esp32-s3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...{test.bk72xx.yaml => test.bk72xx-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...{test.bk72xx.yaml => test.bk72xx-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...{test.bk72xx.yaml => test.bk72xx-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...t.esp32-s2.yaml => test.esp32-s2-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...t.esp32-s2.yaml => test.esp32-s2-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...{test.bk72xx.yaml => test.bk72xx-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-s3.yaml => test.esp32-s3-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-s3.yaml => test.esp32-s3-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-s3.yaml => test.esp32-s3-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-s3.yaml => test.esp32-s3-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-s3.yaml => test.esp32-s3-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-s3.yaml => test.esp32-s3-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-s3.yaml => test.esp32-s3-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-s3.yaml => test.esp32-s3-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...t.esp32-s2.yaml => test.esp32-s2-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...test.esp32-c3.yaml => test.esp32-ard.yaml} | 0 ...test.esp32.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 .../{test.esp32.yaml => test.esp32-ard.yaml} | 0 ...t.esp32-c3.yaml => test.esp32-c3-ard.yaml} | 0 ...est.esp8266.yaml => test.esp8266-ard.yaml} | 0 ...{test.rp2040.yaml => test.rp2040-ard.yaml} | 0 ... => build_components_base.bk72xx-ard.yaml} | 0 ...build_components_base.esp32-c3-idf-50.yaml | 19 ++++++++++++++ .../build_components_base.esp32-idf-50.yaml | 19 ++++++++++++++ ...build_components_base.esp32-s2-idf-50.yaml | 20 +++++++++++++++ .../build_components_base.esp32-s2-idf.yaml | 2 +- ...build_components_base.esp32-s3-idf-50.yaml | 20 +++++++++++++++ .../build_components_base.esp32-s3-idf.yaml | 2 +- ...=> build_components_base.esp8266-ard.yaml} | 2 +- ... => build_components_base.rp2040-ard.yaml} | 2 +- 1689 files changed, 95 insertions(+), 16 deletions(-) rename tests/components/a01nyub/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/a01nyub/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/a01nyub/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/a01nyub/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/a02yyuw/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/a02yyuw/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/a02yyuw/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/a02yyuw/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/a4988/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/a4988/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/a4988/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/a4988/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/absolute_humidity/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/absolute_humidity/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/absolute_humidity/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/absolute_humidity/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ac_dimmer/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ac_dimmer/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ac_dimmer/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ac_dimmer/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/adc/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/adc/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/adc/{test.esp32-s2.yaml => test.esp32-s2-ard.yaml} (100%) rename tests/components/adc/{test.esp32-s3.yaml => test.esp32-s3-ard.yaml} (100%) rename tests/components/adc/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/adc/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/adc128s102/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/adc128s102/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/adc128s102/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/adc128s102/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/addressable_light/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/addressable_light/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ade7880/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ade7880/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ade7880/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ade7880/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ade7953_i2c/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ade7953_i2c/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ade7953_i2c/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ade7953_i2c/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ade7953_spi/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ade7953_spi/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ade7953_spi/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ade7953_spi/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ads1115/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ads1115/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ads1115/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ads1115/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ags10/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ags10/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ags10/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/aht10/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/aht10/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/aht10/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/aht10/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/airthings_wave_mini/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/airthings_wave_mini/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/airthings_wave_plus/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/airthings_wave_plus/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/alarm_control_panel/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/alarm_control_panel/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/alarm_control_panel/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/alarm_control_panel/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/alpha3/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/alpha3/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/am2315c/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/am2315c/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/am2315c/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/am2315c/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/am2320/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/am2320/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/am2320/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/am2320/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/am43/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/am43/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/analog_threshold/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/analog_threshold/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/analog_threshold/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/analog_threshold/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/animation/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/animation/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/animation/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/animation/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/anova/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/anova/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/apds9960/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/apds9960/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/apds9960/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/apds9960/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/api/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/api/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/api/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/api/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/as3935_i2c/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/as3935_i2c/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/as3935_i2c/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/as3935_i2c/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/as3935_spi/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/as3935_spi/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/as3935_spi/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/as3935_spi/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/as5600/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/as5600/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/as5600/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/as5600/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/as7341/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/as7341/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/as7341/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/as7341/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/at581x/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/at581x/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/at581x/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/at581x/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/atc_mithermometer/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/atc_mithermometer/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/atm90e26/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/atm90e26/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/atm90e26/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/atm90e26/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/atm90e32/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/atm90e32/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/atm90e32/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/atm90e32/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/b_parasite/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/b_parasite/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ballu/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ballu/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/bang_bang/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/bang_bang/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/bang_bang/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/bang_bang/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/bedjet/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/bedjet/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/beken_spi_led_strip/{test.bk72xx.yaml => test.bk72xx-ard.yaml} (100%) rename tests/components/bh1750/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/bh1750/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/bh1750/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/bh1750/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/binary_sensor_map/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/binary_sensor_map/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/binary_sensor_map/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/binary_sensor_map/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/bl0939/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/bl0939/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/bl0939/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/bl0939/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/bl0940/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/bl0940/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/bl0940/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/bl0940/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/bl0942/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/bl0942/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/bl0942/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/bl0942/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ble_client/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ble_client/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ble_presence/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ble_presence/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ble_rssi/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ble_rssi/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ble_scanner/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ble_scanner/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/bme280_i2c/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/bme280_i2c/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/bme280_i2c/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/bme280_i2c/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/bme280_spi/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/bme280_spi/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/bme280_spi/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/bme280_spi/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/bme680/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/bme680/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/bme680/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/bme680/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/bme680_bsec/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/bme680_bsec/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/bmi160/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/bmi160/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/bmi160/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/bmi160/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/bmp085/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/bmp085/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/bmp085/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/bmp085/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/bmp280/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/bmp280/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/bmp280/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/bmp280/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/bmp3xx_i2c/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/bmp3xx_i2c/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/bmp3xx_i2c/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/bmp3xx_i2c/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/bmp3xx_spi/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/bmp3xx_spi/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/bmp3xx_spi/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/bmp3xx_spi/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/bmp581/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/bmp581/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/bmp581/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/bmp581/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/bp1658cj/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/bp1658cj/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/bp1658cj/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/bp1658cj/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/bp5758d/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/bp5758d/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/bp5758d/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/bp5758d/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/button/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/button/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/button/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/button/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/canbus/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/canbus/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/cap1188/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/cap1188/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/cap1188/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/cap1188/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/captive_portal/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/captive_portal/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/captive_portal/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ccs811/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ccs811/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ccs811/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ccs811/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/cd74hc4067/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/cd74hc4067/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/cd74hc4067/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/cd74hc4067/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/climate_ir_lg/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/climate_ir_lg/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/climate_ir_lg/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/color/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/color/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/color/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/color/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/color_temperature/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/color_temperature/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/color_temperature/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/color_temperature/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/combination/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/combination/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/combination/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/combination/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/coolix/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/coolix/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/coolix/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/copy/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/copy/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/copy/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/copy/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/cs5460a/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/cs5460a/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/cs5460a/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/cs5460a/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/cse7761/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/cse7761/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/cse7761/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/cse7761/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/cse7766/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/cse7766/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/cse7766/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/cse7766/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/cst226/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/cst816/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ct_clamp/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ct_clamp/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ct_clamp/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ct_clamp/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/current_based/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/current_based/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/current_based/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/current_based/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/cwww/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/cwww/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/cwww/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/cwww/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/dac7678/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/dac7678/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/dac7678/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/dac7678/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/daikin/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/daikin/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/daikin_arc/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/daikin_arc/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/daikin_brc/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/daikin_brc/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/daikin_brc/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/dallas_temp/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/dallas_temp/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/dallas_temp/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/dallas_temp/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/daly_bms/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/daly_bms/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/daly_bms/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/daly_bms/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/debug/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/debug/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/debug/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/debug/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/deep_sleep/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/deep_sleep/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/deep_sleep/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/delonghi/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/delonghi/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/delonghi/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/dfplayer/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/dfplayer/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/dfplayer/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/dfplayer/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/dfrobot_sen0395/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/dfrobot_sen0395/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/dfrobot_sen0395/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/dfrobot_sen0395/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/dht/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/dht/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/dht/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/dht/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/dht12/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/dht12/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/dht12/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/dht12/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/display/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/dps310/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/dps310/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/dps310/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/dps310/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ds1307/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ds1307/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ds1307/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ds1307/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/dsmr/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/dsmr/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/dsmr/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/dsmr/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/duty_cycle/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/duty_cycle/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/duty_cycle/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/duty_cycle/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/duty_time/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/duty_time/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/duty_time/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/duty_time/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/e131/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/e131/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/e131/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/e131/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ee895/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ee895/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ee895/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ee895/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ektf2232/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ektf2232/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ektf2232/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ektf2232/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/emc2101/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/emc2101/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/emc2101/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/emc2101/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/emmeti/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/emmeti/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/endstop/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/endstop/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/endstop/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/endstop/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ens160_i2c/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ens160_i2c/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ens160_i2c/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ens160_i2c/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ens160_spi/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ens160_spi/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ens160_spi/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ens160_spi/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ens210/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ens210/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ens210/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ens210/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/esp32_ble/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/esp32_ble/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/esp32_ble_beacon/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/esp32_ble_beacon/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/esp32_ble_client/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/esp32_ble_client/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/esp32_ble_server/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/esp32_ble_server/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/esp32_ble_tracker/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/esp32_ble_tracker/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/esp32_camera/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/esp32_camera_web_server/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/esp32_can/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/esp32_can/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/esp32_dac/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/esp32_hall/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/esp32_improv/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/esp32_improv/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/esp32_rmt_led_strip/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/esp32_rmt_led_strip/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/esp32_touch/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/esp8266_pwm/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ethernet/{test-dp83848.esp32.yaml => test-dp83848.esp32-ard.yaml} (100%) rename tests/components/ethernet/{test-ip101.esp32.yaml => test-ip101.esp32-ard.yaml} (100%) rename tests/components/ethernet/{test-jl1101.esp32.yaml => test-jl1101.esp32-ard.yaml} (100%) rename tests/components/ethernet/{test-ksz8081.esp32.yaml => test-ksz8081.esp32-ard.yaml} (100%) rename tests/components/ethernet/{test-ksz8081rna.esp32.yaml => test-ksz8081rna.esp32-ard.yaml} (100%) rename tests/components/ethernet/{test-lan8720.esp32.yaml => test-lan8720.esp32-ard.yaml} (100%) rename tests/components/ethernet/{test-rtl8201.esp32.yaml => test-rtl8201.esp32-ard.yaml} (100%) rename tests/components/ethernet/{test-w5500.esp32.yaml => test-w5500.esp32-ard.yaml} (100%) rename tests/components/ethernet_info/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/event/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/event/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/event/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/event/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/exposure_notifications/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/exposure_notifications/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/external_components/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/external_components/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/external_components/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/external_components/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ezo/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ezo/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ezo/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ezo/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ezo_pmp/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ezo_pmp/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ezo_pmp/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ezo_pmp/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/factory_reset/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/factory_reset/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/factory_reset/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/factory_reset/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/fastled_clockless/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/fastled_spi/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/feedback/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/feedback/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/feedback/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/feedback/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/fingerprint_grow/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/fingerprint_grow/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/fingerprint_grow/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/fingerprint_grow/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/font/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/font/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/font/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/font/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/fs3000/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/fs3000/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/fs3000/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/fs3000/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ft5x06/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ft5x06/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ft5x06/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ft5x06/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ft63x6/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ft63x6/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ft63x6/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ft63x6/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/fujitsu_general/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/fujitsu_general/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/fujitsu_general/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/gcja5/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/gcja5/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/gcja5/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/gcja5/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/gdk101/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/gdk101/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/gdk101/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/globals/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/globals/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/globals/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/globals/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/gp8403/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/gp8403/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/gp8403/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/gp8403/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/gpio/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/gpio/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/gpio/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/gpio/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/gps/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/gps/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/gps/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/gps/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/graph/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/graph/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/graph/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/graph/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/graphical_display_menu/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/graphical_display_menu/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/graphical_display_menu/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/graphical_display_menu/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/gree/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/gree/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/gree/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/grove_tb6612fng/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/grove_tb6612fng/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/grove_tb6612fng/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/grove_tb6612fng/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/growatt_solar/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/growatt_solar/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/growatt_solar/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/growatt_solar/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/gt911/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/gt911/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/gt911/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/gt911/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/haier/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/haier/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/haier/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/haier/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/havells_solar/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/havells_solar/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/havells_solar/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/havells_solar/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/hbridge/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/hbridge/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/hbridge/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/hbridge/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/hdc1080/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/hdc1080/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/hdc1080/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/hdc1080/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/he60r/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/he60r/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/he60r/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/he60r/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/heatpumpir/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/heatpumpir/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/hitachi_ac344/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/hitachi_ac344/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/hitachi_ac344/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/hitachi_ac424/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/hitachi_ac424/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/hitachi_ac424/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/hlw8012/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/hlw8012/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/hlw8012/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/hlw8012/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/hm3301/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/hm3301/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/hm3301/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/hm3301/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/hmc5883l/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/hmc5883l/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/hmc5883l/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/hmc5883l/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/homeassistant/{test.bk72xx.yaml => test.bk72xx-ard.yaml} (100%) rename tests/components/homeassistant/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/homeassistant/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/homeassistant/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/homeassistant/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/honeywell_hih_i2c/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/honeywell_hih_i2c/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/honeywell_hih_i2c/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/honeywell_hih_i2c/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/honeywellabp/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/honeywellabp/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/honeywellabp/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/honeywellabp/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/honeywellabp2_i2c/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/honeywellabp2_i2c/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/honeywellabp2_i2c/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/honeywellabp2_i2c/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/hrxl_maxsonar_wr/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/hrxl_maxsonar_wr/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/hrxl_maxsonar_wr/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/hrxl_maxsonar_wr/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/hte501/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/hte501/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/hte501/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/hte501/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/http_request/{test-nossl.esp8266.yaml => test-nossl.esp8266-ard.yaml} (100%) rename tests/components/http_request/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/http_request/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/http_request/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/http_request/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/htu21d/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/htu21d/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/htu21d/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/htu21d/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/htu31d/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/htu31d/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/hx711/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/hx711/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/hx711/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/hx711/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/hydreon_rgxx/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/hydreon_rgxx/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/hydreon_rgxx/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/hydreon_rgxx/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/hyt271/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/hyt271/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/hyt271/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/hyt271/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/i2c/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/i2c/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/i2c/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/i2c/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/i2s_audio/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/i2s_audio/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/iaqcore/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/iaqcore/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/iaqcore/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/iaqcore/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ili9xxx/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ili9xxx/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ili9xxx/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ili9xxx/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/image/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/image/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/image/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/image/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/improv_serial/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/improv_serial/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/improv_serial/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/improv_serial/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ina219/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ina219/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ina219/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ina219/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ina226/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ina226/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ina226/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ina226/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ina260/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ina260/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ina260/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ina260/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ina2xx_i2c/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ina2xx_i2c/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ina2xx_i2c/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ina2xx_i2c/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ina2xx_spi/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ina2xx_spi/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ina2xx_spi/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ina2xx_spi/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ina3221/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ina3221/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ina3221/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ina3221/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/inkbird_ibsth1_mini/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/inkbird_ibsth1_mini/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/inkplate6/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/integration/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/integration/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/integration/{test.esp32-s2.yaml => test.esp32-s2-ard.yaml} (100%) rename tests/components/integration/{test.esp32-s3.yaml => test.esp32-s3-ard.yaml} (100%) rename tests/components/integration/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/integration/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/internal_temperature/{test.bk72xx.yaml => test.bk72xx-ard.yaml} (100%) rename tests/components/internal_temperature/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/internal_temperature/{test.esp32-s2.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/internal_temperature/{test.esp32.yaml => test.esp32-s2-ard.yaml} (100%) rename tests/components/internal_temperature/{test.esp32-s3.yaml => test.esp32-s3-ard.yaml} (100%) rename tests/components/internal_temperature/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/interval/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/interval/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/interval/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/interval/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/jsn_sr04t/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/jsn_sr04t/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/jsn_sr04t/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/jsn_sr04t/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/kamstrup_kmp/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/kamstrup_kmp/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/key_collector/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/key_collector/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/key_collector/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/key_collector/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/kmeteriso/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/kmeteriso/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/kmeteriso/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/kmeteriso/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/kuntze/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/kuntze/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/kuntze/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/kuntze/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/lcd_gpio/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/lcd_gpio/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/lcd_gpio/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/lcd_gpio/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/lcd_menu/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/lcd_menu/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/lcd_menu/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/lcd_menu/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/lcd_pcf8574/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/lcd_pcf8574/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/lcd_pcf8574/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/lcd_pcf8574/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ld2410/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ld2410/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ld2410/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ld2410/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ld2420/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ld2420/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ld2420/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ld2420/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ledc/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ledc/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/light/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/light/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/light/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/light/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/lightwaverf/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/lilygo_t5_47/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/lilygo_t5_47/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/lilygo_t5_47/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/lilygo_t5_47/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/lock/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/lock/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/lock/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/lock/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/logger/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/logger/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/logger/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/logger/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ltr390/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ltr390/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ltr390/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ltr390/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ltr_als_ps/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ltr_als_ps/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ltr_als_ps/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ltr_als_ps/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/matrix_keypad/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/matrix_keypad/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/matrix_keypad/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/matrix_keypad/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/max31855/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/max31855/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/max31855/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/max31855/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/max31856/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/max31856/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/max31856/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/max31856/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/max31865/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/max31865/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/max31865/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/max31865/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/max44009/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/max44009/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/max44009/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/max44009/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/max6675/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/max6675/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/max6675/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/max6675/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/max6956/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/max6956/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/max6956/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/max6956/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/max7219/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/max7219/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/max7219/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/max7219/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/max7219digit/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/max7219digit/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/max7219digit/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/max7219digit/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/max9611/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/max9611/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/max9611/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/max9611/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/mcp23008/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/mcp23008/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/mcp23008/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/mcp23008/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/mcp23016/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/mcp23016/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/mcp23016/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/mcp23016/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/mcp23017/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/mcp23017/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/mcp23017/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/mcp23017/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/mcp23s08/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/mcp23s08/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/mcp23s08/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/mcp23s08/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/mcp23s17/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/mcp23s17/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/mcp23s17/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/mcp23s17/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/mcp2515/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/mcp2515/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/mcp2515/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/mcp2515/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/mcp3008/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/mcp3008/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/mcp3008/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/mcp3008/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/mcp3204/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/mcp3204/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/mcp3204/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/mcp3204/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/mcp4725/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/mcp4725/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/mcp4725/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/mcp4725/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/mcp4728/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/mcp4728/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/mcp4728/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/mcp4728/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/mcp47a1/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/mcp47a1/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/mcp47a1/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/mcp47a1/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/mcp9600/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/mcp9600/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/mcp9600/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/mcp9600/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/mcp9808/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/mcp9808/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/mcp9808/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/mcp9808/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/mdns/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/mdns/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/mdns/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/mdns/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/media_player/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/mhz19/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/mhz19/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/mhz19/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/mhz19/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/micronova/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/micronova/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/micronova/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/micronova/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/microphone/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/microphone/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/mics_4514/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/mics_4514/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/mics_4514/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/mics_4514/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/midea/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/midea/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/midea/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/midea_ir/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/midea_ir/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/midea_ir/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/mitsubishi/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/mitsubishi/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/mitsubishi/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/mlx90393/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/mlx90393/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/mlx90393/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/mlx90393/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/mlx90614/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/mlx90614/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/mlx90614/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/mlx90614/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/mmc5603/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/mmc5603/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/mmc5603/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/mmc5603/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/mmc5983/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/mmc5983/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/mmc5983/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/mmc5983/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/modbus/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/modbus/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/modbus/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/modbus/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/modbus_controller/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/modbus_controller/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/modbus_controller/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/modbus_controller/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/monochromatic/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/monochromatic/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/monochromatic/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/monochromatic/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/mopeka_ble/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/mopeka_ble/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/mopeka_pro_check/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/mopeka_pro_check/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/mopeka_std_check/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/mopeka_std_check/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/mpl3115a2/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/mpl3115a2/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/mpl3115a2/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/mpl3115a2/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/mpr121/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/mpr121/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/mpr121/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/mpr121/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/mpu6050/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/mpu6050/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/mpu6050/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/mpu6050/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/mpu6886/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/mpu6886/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/mpu6886/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/mpu6886/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/mqtt/{test.bk72xx.yaml => test.bk72xx-ard.yaml} (100%) rename tests/components/mqtt/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/mqtt/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/mqtt/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/mqtt_subscribe/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/mqtt_subscribe/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/mqtt_subscribe/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ms5611/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ms5611/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ms5611/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ms5611/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/my9231/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/my9231/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/my9231/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/my9231/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/neopixelbus/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/neopixelbus/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/neopixelbus/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/network/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/network/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/network/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/network/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/nextion/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/nextion/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/nextion/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/nextion/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/noblex/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/noblex/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/noblex/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ntc/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ntc/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ntc/{test.esp32-s2.yaml => test.esp32-s2-ard.yaml} (100%) rename tests/components/ntc/{test.esp32-s3.yaml => test.esp32-s3-ard.yaml} (100%) rename tests/components/ntc/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ntc/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ota/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ota/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ota/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ota/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/output/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/output/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/output/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/output/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/partition/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/partition/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/pca6416a/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/pca6416a/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/pca6416a/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/pca6416a/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/pca9554/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/pca9554/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/pca9554/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/pca9554/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/pca9685/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/pca9685/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/pca9685/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/pca9685/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/pcd8544/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/pcd8544/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/pcd8544/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/pcd8544/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/pcf85063/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/pcf85063/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/pcf85063/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/pcf85063/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/pcf8563/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/pcf8563/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/pcf8563/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/pcf8563/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/pcf8574/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/pcf8574/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/pcf8574/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/pcf8574/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/pid/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/pid/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/pid/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/pid/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/pipsolar/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/pipsolar/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/pipsolar/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/pipsolar/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/pm1006/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/pm1006/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/pm1006/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/pm1006/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/pmsa003i/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/pmsa003i/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/pmsa003i/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/pmsa003i/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/pmsx003/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/pmsx003/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/pmsx003/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/pmsx003/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/pmwcs3/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/pmwcs3/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/pmwcs3/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/pmwcs3/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/pn532_i2c/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/pn532_i2c/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/pn532_i2c/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/pn532_i2c/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/pn532_spi/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/pn532_spi/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/pn532_spi/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/pn532_spi/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/pn7150_i2c/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/pn7150_i2c/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/pn7150_i2c/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/pn7150_i2c/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/pn7160_i2c/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/pn7160_i2c/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/pn7160_i2c/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/pn7160_i2c/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/pn7160_spi/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/pn7160_spi/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/pn7160_spi/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/pn7160_spi/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/power_supply/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/power_supply/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/power_supply/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/power_supply/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/prometheus/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/prometheus/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/prometheus/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/psram/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/psram/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/pulse_counter/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/pulse_counter/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/pulse_counter/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/pulse_counter/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/pulse_meter/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/pulse_meter/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/pulse_meter/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/pulse_meter/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/pulse_width/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/pulse_width/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/pulse_width/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/pulse_width/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/pvvx_mithermometer/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/pvvx_mithermometer/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/pylontech/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/pylontech/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/pylontech/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/pylontech/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/pzem004t/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/pzem004t/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/pzem004t/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/pzem004t/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/pzemac/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/pzemac/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/pzemac/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/pzemac/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/pzemdc/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/pzemdc/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/pzemdc/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/pzemdc/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/qmc5883l/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/qmc5883l/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/qmc5883l/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/qmc5883l/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/qmp6988/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/qmp6988/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/qmp6988/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/qmp6988/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/qr_code/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/qr_code/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/qr_code/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/qr_code/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/qwiic_pir/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/qwiic_pir/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/qwiic_pir/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/qwiic_pir/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/radon_eye_ble/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/radon_eye_ble/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/radon_eye_rd200/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/radon_eye_rd200/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/rc522_i2c/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/rc522_i2c/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/rc522_i2c/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/rc522_i2c/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/rc522_spi/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/rc522_spi/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/rc522_spi/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/rc522_spi/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/rdm6300/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/rdm6300/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/rdm6300/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/rdm6300/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/remote_receiver/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/remote_receiver/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/remote_receiver/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/remote_transmitter/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/remote_transmitter/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/remote_transmitter/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/resistance/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/resistance/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/resistance/{test.esp32-s2.yaml => test.esp32-s2-ard.yaml} (100%) rename tests/components/resistance/{test.esp32-s3.yaml => test.esp32-s3-ard.yaml} (100%) rename tests/components/resistance/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/resistance/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/restart/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/restart/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/restart/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/restart/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/rf_bridge/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/rf_bridge/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/rf_bridge/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/rf_bridge/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/rgb/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/rgb/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/rgb/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/rgb/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/rgbct/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/rgbct/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/rgbct/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/rgbct/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/rgbw/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/rgbw/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/rgbw/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/rgbw/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/rgbww/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/rgbww/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/rgbww/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/rgbww/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/rotary_encoder/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/rotary_encoder/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/rotary_encoder/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/rotary_encoder/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/rp2040_pio_led_strip/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/rp2040_pwm/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/rtttl/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/rtttl/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/rtttl/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/rtttl/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ruuvi_ble/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ruuvi_ble/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ruuvitag/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ruuvitag/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/safe_mode/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/safe_mode/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/safe_mode/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/safe_mode/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/scd30/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/scd30/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/scd30/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/scd30/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/scd4x/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/scd4x/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/scd4x/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/scd4x/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/script/{test.bk72xx.yaml => test.bk72xx-ard.yaml} (100%) rename tests/components/script/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/script/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/script/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/script/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/sdm_meter/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/sdm_meter/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/sdm_meter/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/sdm_meter/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/sdp3x/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/sdp3x/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/sdp3x/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/sdp3x/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/sds011/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/sds011/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/sds011/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/sds011/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/seeed_mr24hpc1/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/selec_meter/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/selec_meter/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/selec_meter/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/selec_meter/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/sen0321/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/sen0321/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/sen0321/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/sen0321/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/sen21231/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/sen21231/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/sen21231/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/sen21231/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/sen5x/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/sen5x/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/sen5x/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/sen5x/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/senseair/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/senseair/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/senseair/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/senseair/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/servo/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/servo/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/servo/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/servo/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/sfa30/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/sfa30/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/sfa30/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/sfa30/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/sgp30/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/sgp30/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/sgp30/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/sgp30/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/sgp4x/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/sgp4x/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/sgp4x/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/sgp4x/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/shelly_dimmer/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/sht3xd/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/sht3xd/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/sht3xd/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/sht3xd/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/sht4x/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/sht4x/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/sht4x/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/sht4x/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/shtcx/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/shtcx/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/shtcx/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/shtcx/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/shutdown/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/shutdown/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/shutdown/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/shutdown/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/sigma_delta_output/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/sigma_delta_output/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/sigma_delta_output/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/sigma_delta_output/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/sim800l/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/sim800l/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/sim800l/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/sim800l/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/slow_pwm/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/slow_pwm/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/slow_pwm/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/slow_pwm/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/sm16716/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/sm16716/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/sm16716/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/sm16716/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/sm2135/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/sm2135/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/sm2135/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/sm2135/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/sm2235/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/sm2235/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/sm2235/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/sm2235/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/sm2335/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/sm2335/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/sm2335/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/sm2335/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/sm300d2/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/sm300d2/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/sm300d2/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/sm300d2/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/sml/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/sml/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/sml/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/sml/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/smt100/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/smt100/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/smt100/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/smt100/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/sn74hc165/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/sn74hc165/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/sn74hc165/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/sn74hc165/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/sn74hc595/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/sn74hc595/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/sn74hc595/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/sn74hc595/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/sntp/{test.bk72xx.yaml => test.bk72xx-ard.yaml} (100%) rename tests/components/sntp/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/sntp/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/sntp/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/sntp/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/sonoff_d1/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/sonoff_d1/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/speaker/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/speaker/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/speed/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/speed/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/speed/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/speed/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/spi/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/spi/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/spi/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/spi/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/spi_device/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/spi_device/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/spi_device/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/spi_device/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/spi_led_strip/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/spi_led_strip/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/spi_led_strip/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/spi_led_strip/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/sprinkler/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/sprinkler/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/sprinkler/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/sprinkler/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/sps30/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/sps30/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/sps30/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/sps30/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ssd1306_i2c/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ssd1306_i2c/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ssd1306_i2c/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ssd1306_i2c/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ssd1306_spi/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ssd1306_spi/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ssd1306_spi/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ssd1306_spi/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ssd1322_spi/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ssd1322_spi/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ssd1322_spi/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ssd1322_spi/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ssd1325_spi/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ssd1325_spi/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ssd1325_spi/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ssd1325_spi/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ssd1327_i2c/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ssd1327_i2c/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ssd1327_i2c/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ssd1327_i2c/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ssd1327_spi/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ssd1327_spi/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ssd1327_spi/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ssd1327_spi/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ssd1331_spi/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ssd1331_spi/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ssd1331_spi/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ssd1331_spi/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ssd1351_spi/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ssd1351_spi/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ssd1351_spi/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ssd1351_spi/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/st7567_i2c/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/st7567_i2c/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/st7567_i2c/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/st7567_i2c/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/st7567_spi/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/st7567_spi/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/st7567_spi/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/st7567_spi/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/st7735/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/st7735/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/st7735/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/st7735/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/st7789v/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/st7789v/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/st7789v/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/st7789v/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/st7920/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/st7920/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/st7920/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/st7920/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/status/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/status/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/status/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/status/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/status_led/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/status_led/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/status_led/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/status_led/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/stepper/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/stepper/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/stepper/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/stepper/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/sts3x/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/sts3x/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/sts3x/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/sts3x/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/sun/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/sun/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/sun/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/sun/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/sun_gtil2/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/sun_gtil2/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/sun_gtil2/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/sun_gtil2/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/sx1509/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/sx1509/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/sx1509/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/sx1509/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/t6615/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/t6615/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/t6615/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/t6615/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/tca9548a/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/tca9548a/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/tca9548a/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/tca9548a/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/tcl112/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/tcl112/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/tcl112/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/tcs34725/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/tcs34725/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/tcs34725/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/tcs34725/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/tee501/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/tee501/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/tee501/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/tee501/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/teleinfo/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/teleinfo/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/teleinfo/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/teleinfo/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/template/{test.bk72xx.yaml => test.bk72xx-ard.yaml} (100%) rename tests/components/template/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/template/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/template/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/template/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/thermostat/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/thermostat/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/thermostat/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/thermostat/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/time/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/time/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/time/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/time/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/time_based/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/time_based/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/time_based/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/time_based/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/tlc59208f/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/tlc59208f/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/tlc59208f/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/tlc59208f/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/tlc5947/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/tlc5947/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/tlc5947/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/tlc5947/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/tlc5971/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/tlc5971/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/tlc5971/{test.esp32-s2.yaml => test.esp32-s2-ard.yaml} (100%) rename tests/components/tlc5971/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/tlc5971/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/tm1621/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/tm1621/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/tm1621/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/tm1621/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/tm1637/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/tm1637/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/tm1637/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/tm1637/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/tm1638/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/tm1638/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/tm1638/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/tm1638/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/tm1651/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/tm1651/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/tm1651/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/tm1651/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/tmp102/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/tmp102/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/tmp102/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/tmp102/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/tmp1075/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/tmp1075/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/tmp1075/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/tmp1075/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/tmp117/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/tmp117/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/tmp117/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/tmp117/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/tof10120/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/tof10120/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/tof10120/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/tof10120/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/toshiba/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/toshiba/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/toshiba/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/total_daily_energy/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/total_daily_energy/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/total_daily_energy/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/total_daily_energy/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/tsl2561/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/tsl2561/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/tsl2561/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/tsl2561/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/tsl2591/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/tsl2591/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/tsl2591/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/tsl2591/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/tt21100/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/tt21100/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/tt21100/{test.esp32-s2.yaml => test.esp32-s2-ard.yaml} (100%) rename tests/components/tt21100/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/tt21100/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ttp229_bsf/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ttp229_bsf/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ttp229_bsf/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ttp229_bsf/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ttp229_lsf/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ttp229_lsf/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ttp229_lsf/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ttp229_lsf/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/tuya/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/tuya/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/tuya/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/tuya/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/tx20/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/tx20/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/tx20/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/tx20/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/uart/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/uart/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/uart/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/uart/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ufire_ec/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ufire_ec/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ufire_ec/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ufire_ec/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ufire_ise/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ufire_ise/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ufire_ise/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ufire_ise/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/uln2003/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/uln2003/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/uln2003/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/uln2003/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/ultrasonic/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/ultrasonic/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/ultrasonic/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/ultrasonic/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/update/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/update/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/uponor_smatrix/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/uponor_smatrix/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/uponor_smatrix/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/uponor_smatrix/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/uptime/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/uptime/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/uptime/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/uptime/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/vbus/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/vbus/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/vbus/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/vbus/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/veml3235/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/veml3235/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/veml3235/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/veml3235/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/veml7700/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/veml7700/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/veml7700/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/veml7700/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/version/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/version/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/version/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/version/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/vl53l0x/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/vl53l0x/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/vl53l0x/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/vl53l0x/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/voice_assistant/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/voice_assistant/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/wake_on_lan/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/wake_on_lan/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/wake_on_lan/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/wake_on_lan/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/waveshare_epaper/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/waveshare_epaper/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/waveshare_epaper/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/waveshare_epaper/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/web_server/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/web_server/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/web_server/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/whirlpool/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/whirlpool/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/whirlpool/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/whynter/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/whynter/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/whynter/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/wiegand/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/wiegand/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/wiegand/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/wiegand/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/wifi/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/wifi/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/wifi/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/wifi/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/wifi_info/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/wifi_info/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/wifi_info/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/wifi_info/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/wifi_signal/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/wifi_signal/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/wifi_signal/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/wifi_signal/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/wireguard/{test.bk72xx.yaml => test.bk72xx-ard.yaml} (100%) rename tests/components/wireguard/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/wireguard/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/wireguard/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/wk2132_i2c/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/wk2132_i2c/{test.esp32-s3.yaml => test.esp32-s3-ard.yaml} (100%) rename tests/components/wk2132_spi/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/wk2132_spi/{test.esp32-s3.yaml => test.esp32-s3-ard.yaml} (100%) rename tests/components/wk2168_i2c/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/wk2168_i2c/{test.esp32-s3.yaml => test.esp32-s3-ard.yaml} (100%) rename tests/components/wk2168_spi/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/wk2168_spi/{test.esp32-s3.yaml => test.esp32-s3-ard.yaml} (100%) rename tests/components/wk2204_i2c/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/wk2204_i2c/{test.esp32-s3.yaml => test.esp32-s3-ard.yaml} (100%) rename tests/components/wk2204_spi/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/wk2204_spi/{test.esp32-s3.yaml => test.esp32-s3-ard.yaml} (100%) rename tests/components/wk2212_i2c/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/wk2212_i2c/{test.esp32-s3.yaml => test.esp32-s3-ard.yaml} (100%) rename tests/components/wk2212_spi/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/wk2212_spi/{test.esp32-s3.yaml => test.esp32-s3-ard.yaml} (100%) rename tests/components/wl_134/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/wl_134/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/wl_134/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/wl_134/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/wled/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/wled/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/wled/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/x9c/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/x9c/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/x9c/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/x9c/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/xgzp68xx/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/xgzp68xx/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/xgzp68xx/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/xgzp68xx/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/xiaomi_ble/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/xiaomi_ble/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/xiaomi_cgd1/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/xiaomi_cgd1/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/xiaomi_cgdk2/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/xiaomi_cgdk2/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/xiaomi_cgg1/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/xiaomi_cgg1/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/xiaomi_cgpr1/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/xiaomi_cgpr1/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/xiaomi_gcls002/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/xiaomi_gcls002/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/xiaomi_hhccjcy01/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/xiaomi_hhccjcy01/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/xiaomi_hhccpot002/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/xiaomi_hhccpot002/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/xiaomi_jqjcy01ym/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/xiaomi_jqjcy01ym/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/xiaomi_lywsd02/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/xiaomi_lywsd02/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/xiaomi_lywsd03mmc/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/xiaomi_lywsd03mmc/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/xiaomi_lywsdcgq/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/xiaomi_lywsdcgq/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/xiaomi_mhoc303/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/xiaomi_mhoc303/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/xiaomi_mhoc401/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/xiaomi_mhoc401/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/xiaomi_miscale copy/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/xiaomi_miscale copy/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/xiaomi_miscale/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/xiaomi_miscale/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/xiaomi_mjyd02yla/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/xiaomi_mjyd02yla/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/xiaomi_mue4094rt/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/xiaomi_mue4094rt/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/xiaomi_rtcgq02lm/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/xiaomi_rtcgq02lm/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/xiaomi_wx08zm/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/xiaomi_wx08zm/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/xl9535/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/xl9535/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/xl9535/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/xl9535/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/xpt2046/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/xpt2046/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/xpt2046/{test.esp32-s2.yaml => test.esp32-s2-ard.yaml} (100%) rename tests/components/xpt2046/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/xpt2046/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/yashima/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/yashima/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/yashima/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/zhlt01/{test.esp32-c3.yaml => test.esp32-ard.yaml} (100%) rename tests/components/zhlt01/{test.esp32.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/zhlt01/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/zio_ultrasonic/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/zio_ultrasonic/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/zio_ultrasonic/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/zio_ultrasonic/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/components/zyaura/{test.esp32.yaml => test.esp32-ard.yaml} (100%) rename tests/components/zyaura/{test.esp32-c3.yaml => test.esp32-c3-ard.yaml} (100%) rename tests/components/zyaura/{test.esp8266.yaml => test.esp8266-ard.yaml} (100%) rename tests/components/zyaura/{test.rp2040.yaml => test.rp2040-ard.yaml} (100%) rename tests/test_build_components/{build_components_base.bk72xx.yaml => build_components_base.bk72xx-ard.yaml} (100%) create mode 100644 tests/test_build_components/build_components_base.esp32-c3-idf-50.yaml create mode 100644 tests/test_build_components/build_components_base.esp32-idf-50.yaml create mode 100644 tests/test_build_components/build_components_base.esp32-s2-idf-50.yaml create mode 100644 tests/test_build_components/build_components_base.esp32-s3-idf-50.yaml rename tests/test_build_components/{build_components_base.esp8266.yaml => build_components_base.esp8266-ard.yaml} (87%) rename tests/test_build_components/{build_components_base.rp2040.yaml => build_components_base.rp2040-ard.yaml} (92%) diff --git a/script/test_build_components b/script/test_build_components index f82dd5c3b6..9bbb694dcc 100755 --- a/script/test_build_components +++ b/script/test_build_components @@ -24,8 +24,8 @@ fi start_esphome() { # create dynamic yaml file in `build` folder. - # `./tests/test_build_components/build/[target_component].[test_name].[target_platform].yaml` - component_test_file="./tests/test_build_components/build/$target_component.$test_name.$target_platform.yaml" + # `./tests/test_build_components/build/[target_component].[test_name].[target_platform_with_version].yaml` + component_test_file="./tests/test_build_components/build/$target_component.$test_name.$target_platform_with_version.yaml" cp $target_platform_file $component_test_file if [[ "$OSTYPE" == "darwin"* ]]; then @@ -36,7 +36,7 @@ start_esphome() { fi # Start esphome process - echo "> [$target_component] [$test_name] [$target_platform]" + echo "> [$target_component] [$test_name] [$target_platform_with_version]" set -x # TODO: Validate escape of Command line substitution value python -m esphome -s component_name $target_component -s component_dir ../../components/$target_component -s test_name $test_name -s target_platform $target_platform $esphome_command $component_test_file @@ -76,16 +76,17 @@ for f in ./tests/components/$target_component/*.*.yaml; do # 2. `./tests/test_build_components/build_components_base.[target_platform]-ard.yaml` target_platform_file="./tests/test_build_components/build_components_base.$target_platform.yaml" if ! [ -f "$target_platform_file" ]; then - # Try find arduino test framework as platform. - target_platform_ard="$target_platform-ard" - target_platform_file="./tests/test_build_components/build_components_base.$target_platform_ard.yaml" - if ! [ -f "$target_platform_file" ]; then - echo "No base test file [./tests/test_build_components/build_components_base.$target_platform.yaml, ./tests/build_components_base.$target_platform_ard.yaml] for component test [$f] found." - exit 1 - fi - target_platform=$target_platform_ard + echo "No base test file [./tests/test_build_components/build_components_base.$target_platform.yaml] for component test [$f] found." + exit 1 fi - start_esphome + for target_platform_file in ./tests/test_build_components/build_components_base.$target_platform*.yaml; do + # trim off "./tests/test_build_components/build_components_base." prefix + target_platform_with_version=${target_platform_file:52} + # ...now remove suffix starting with "." leaving just the test target hardware and software platform (possibly with version) + # For example: "esp32-s3-idf-50" + target_platform_with_version=${target_platform_with_version%.*} + start_esphome + done fi done diff --git a/tests/components/a01nyub/test.esp32.yaml b/tests/components/a01nyub/test.esp32-ard.yaml similarity index 100% rename from tests/components/a01nyub/test.esp32.yaml rename to tests/components/a01nyub/test.esp32-ard.yaml diff --git a/tests/components/a01nyub/test.esp32-c3.yaml b/tests/components/a01nyub/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/a01nyub/test.esp32-c3.yaml rename to tests/components/a01nyub/test.esp32-c3-ard.yaml diff --git a/tests/components/a01nyub/test.esp8266.yaml b/tests/components/a01nyub/test.esp8266-ard.yaml similarity index 100% rename from tests/components/a01nyub/test.esp8266.yaml rename to tests/components/a01nyub/test.esp8266-ard.yaml diff --git a/tests/components/a01nyub/test.rp2040.yaml b/tests/components/a01nyub/test.rp2040-ard.yaml similarity index 100% rename from tests/components/a01nyub/test.rp2040.yaml rename to tests/components/a01nyub/test.rp2040-ard.yaml diff --git a/tests/components/a02yyuw/test.esp32.yaml b/tests/components/a02yyuw/test.esp32-ard.yaml similarity index 100% rename from tests/components/a02yyuw/test.esp32.yaml rename to tests/components/a02yyuw/test.esp32-ard.yaml diff --git a/tests/components/a02yyuw/test.esp32-c3.yaml b/tests/components/a02yyuw/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/a02yyuw/test.esp32-c3.yaml rename to tests/components/a02yyuw/test.esp32-c3-ard.yaml diff --git a/tests/components/a02yyuw/test.esp8266.yaml b/tests/components/a02yyuw/test.esp8266-ard.yaml similarity index 100% rename from tests/components/a02yyuw/test.esp8266.yaml rename to tests/components/a02yyuw/test.esp8266-ard.yaml diff --git a/tests/components/a02yyuw/test.rp2040.yaml b/tests/components/a02yyuw/test.rp2040-ard.yaml similarity index 100% rename from tests/components/a02yyuw/test.rp2040.yaml rename to tests/components/a02yyuw/test.rp2040-ard.yaml diff --git a/tests/components/a4988/test.esp32.yaml b/tests/components/a4988/test.esp32-ard.yaml similarity index 100% rename from tests/components/a4988/test.esp32.yaml rename to tests/components/a4988/test.esp32-ard.yaml diff --git a/tests/components/a4988/test.esp32-c3.yaml b/tests/components/a4988/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/a4988/test.esp32-c3.yaml rename to tests/components/a4988/test.esp32-c3-ard.yaml diff --git a/tests/components/a4988/test.esp8266.yaml b/tests/components/a4988/test.esp8266-ard.yaml similarity index 100% rename from tests/components/a4988/test.esp8266.yaml rename to tests/components/a4988/test.esp8266-ard.yaml diff --git a/tests/components/a4988/test.rp2040.yaml b/tests/components/a4988/test.rp2040-ard.yaml similarity index 100% rename from tests/components/a4988/test.rp2040.yaml rename to tests/components/a4988/test.rp2040-ard.yaml diff --git a/tests/components/absolute_humidity/test.esp32-c3.yaml b/tests/components/absolute_humidity/test.esp32-ard.yaml similarity index 100% rename from tests/components/absolute_humidity/test.esp32-c3.yaml rename to tests/components/absolute_humidity/test.esp32-ard.yaml diff --git a/tests/components/absolute_humidity/test.esp32.yaml b/tests/components/absolute_humidity/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/absolute_humidity/test.esp32.yaml rename to tests/components/absolute_humidity/test.esp32-c3-ard.yaml diff --git a/tests/components/absolute_humidity/test.esp8266.yaml b/tests/components/absolute_humidity/test.esp8266-ard.yaml similarity index 100% rename from tests/components/absolute_humidity/test.esp8266.yaml rename to tests/components/absolute_humidity/test.esp8266-ard.yaml diff --git a/tests/components/absolute_humidity/test.rp2040.yaml b/tests/components/absolute_humidity/test.rp2040-ard.yaml similarity index 100% rename from tests/components/absolute_humidity/test.rp2040.yaml rename to tests/components/absolute_humidity/test.rp2040-ard.yaml diff --git a/tests/components/ac_dimmer/test.esp32.yaml b/tests/components/ac_dimmer/test.esp32-ard.yaml similarity index 100% rename from tests/components/ac_dimmer/test.esp32.yaml rename to tests/components/ac_dimmer/test.esp32-ard.yaml diff --git a/tests/components/ac_dimmer/test.esp32-c3.yaml b/tests/components/ac_dimmer/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ac_dimmer/test.esp32-c3.yaml rename to tests/components/ac_dimmer/test.esp32-c3-ard.yaml diff --git a/tests/components/ac_dimmer/test.esp8266.yaml b/tests/components/ac_dimmer/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ac_dimmer/test.esp8266.yaml rename to tests/components/ac_dimmer/test.esp8266-ard.yaml diff --git a/tests/components/ac_dimmer/test.rp2040.yaml b/tests/components/ac_dimmer/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ac_dimmer/test.rp2040.yaml rename to tests/components/ac_dimmer/test.rp2040-ard.yaml diff --git a/tests/components/adc/test.esp32.yaml b/tests/components/adc/test.esp32-ard.yaml similarity index 100% rename from tests/components/adc/test.esp32.yaml rename to tests/components/adc/test.esp32-ard.yaml diff --git a/tests/components/adc/test.esp32-c3.yaml b/tests/components/adc/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/adc/test.esp32-c3.yaml rename to tests/components/adc/test.esp32-c3-ard.yaml diff --git a/tests/components/adc/test.esp32-s2.yaml b/tests/components/adc/test.esp32-s2-ard.yaml similarity index 100% rename from tests/components/adc/test.esp32-s2.yaml rename to tests/components/adc/test.esp32-s2-ard.yaml diff --git a/tests/components/adc/test.esp32-s3.yaml b/tests/components/adc/test.esp32-s3-ard.yaml similarity index 100% rename from tests/components/adc/test.esp32-s3.yaml rename to tests/components/adc/test.esp32-s3-ard.yaml diff --git a/tests/components/adc/test.esp8266.yaml b/tests/components/adc/test.esp8266-ard.yaml similarity index 100% rename from tests/components/adc/test.esp8266.yaml rename to tests/components/adc/test.esp8266-ard.yaml diff --git a/tests/components/adc/test.rp2040.yaml b/tests/components/adc/test.rp2040-ard.yaml similarity index 100% rename from tests/components/adc/test.rp2040.yaml rename to tests/components/adc/test.rp2040-ard.yaml diff --git a/tests/components/adc128s102/test.esp32.yaml b/tests/components/adc128s102/test.esp32-ard.yaml similarity index 100% rename from tests/components/adc128s102/test.esp32.yaml rename to tests/components/adc128s102/test.esp32-ard.yaml diff --git a/tests/components/adc128s102/test.esp32-c3.yaml b/tests/components/adc128s102/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/adc128s102/test.esp32-c3.yaml rename to tests/components/adc128s102/test.esp32-c3-ard.yaml diff --git a/tests/components/adc128s102/test.esp8266.yaml b/tests/components/adc128s102/test.esp8266-ard.yaml similarity index 100% rename from tests/components/adc128s102/test.esp8266.yaml rename to tests/components/adc128s102/test.esp8266-ard.yaml diff --git a/tests/components/adc128s102/test.rp2040.yaml b/tests/components/adc128s102/test.rp2040-ard.yaml similarity index 100% rename from tests/components/adc128s102/test.rp2040.yaml rename to tests/components/adc128s102/test.rp2040-ard.yaml diff --git a/tests/components/addressable_light/test.esp32.yaml b/tests/components/addressable_light/test.esp32-ard.yaml similarity index 100% rename from tests/components/addressable_light/test.esp32.yaml rename to tests/components/addressable_light/test.esp32-ard.yaml diff --git a/tests/components/addressable_light/test.esp32-c3.yaml b/tests/components/addressable_light/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/addressable_light/test.esp32-c3.yaml rename to tests/components/addressable_light/test.esp32-c3-ard.yaml diff --git a/tests/components/ade7880/test.esp32.yaml b/tests/components/ade7880/test.esp32-ard.yaml similarity index 100% rename from tests/components/ade7880/test.esp32.yaml rename to tests/components/ade7880/test.esp32-ard.yaml diff --git a/tests/components/ade7880/test.esp32-c3.yaml b/tests/components/ade7880/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ade7880/test.esp32-c3.yaml rename to tests/components/ade7880/test.esp32-c3-ard.yaml diff --git a/tests/components/ade7880/test.esp8266.yaml b/tests/components/ade7880/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ade7880/test.esp8266.yaml rename to tests/components/ade7880/test.esp8266-ard.yaml diff --git a/tests/components/ade7880/test.rp2040.yaml b/tests/components/ade7880/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ade7880/test.rp2040.yaml rename to tests/components/ade7880/test.rp2040-ard.yaml diff --git a/tests/components/ade7953_i2c/test.esp32.yaml b/tests/components/ade7953_i2c/test.esp32-ard.yaml similarity index 100% rename from tests/components/ade7953_i2c/test.esp32.yaml rename to tests/components/ade7953_i2c/test.esp32-ard.yaml diff --git a/tests/components/ade7953_i2c/test.esp32-c3.yaml b/tests/components/ade7953_i2c/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ade7953_i2c/test.esp32-c3.yaml rename to tests/components/ade7953_i2c/test.esp32-c3-ard.yaml diff --git a/tests/components/ade7953_i2c/test.esp8266.yaml b/tests/components/ade7953_i2c/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ade7953_i2c/test.esp8266.yaml rename to tests/components/ade7953_i2c/test.esp8266-ard.yaml diff --git a/tests/components/ade7953_i2c/test.rp2040.yaml b/tests/components/ade7953_i2c/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ade7953_i2c/test.rp2040.yaml rename to tests/components/ade7953_i2c/test.rp2040-ard.yaml diff --git a/tests/components/ade7953_spi/test.esp32.yaml b/tests/components/ade7953_spi/test.esp32-ard.yaml similarity index 100% rename from tests/components/ade7953_spi/test.esp32.yaml rename to tests/components/ade7953_spi/test.esp32-ard.yaml diff --git a/tests/components/ade7953_spi/test.esp32-c3.yaml b/tests/components/ade7953_spi/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ade7953_spi/test.esp32-c3.yaml rename to tests/components/ade7953_spi/test.esp32-c3-ard.yaml diff --git a/tests/components/ade7953_spi/test.esp8266.yaml b/tests/components/ade7953_spi/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ade7953_spi/test.esp8266.yaml rename to tests/components/ade7953_spi/test.esp8266-ard.yaml diff --git a/tests/components/ade7953_spi/test.rp2040.yaml b/tests/components/ade7953_spi/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ade7953_spi/test.rp2040.yaml rename to tests/components/ade7953_spi/test.rp2040-ard.yaml diff --git a/tests/components/ads1115/test.esp32.yaml b/tests/components/ads1115/test.esp32-ard.yaml similarity index 100% rename from tests/components/ads1115/test.esp32.yaml rename to tests/components/ads1115/test.esp32-ard.yaml diff --git a/tests/components/ads1115/test.esp32-c3.yaml b/tests/components/ads1115/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ads1115/test.esp32-c3.yaml rename to tests/components/ads1115/test.esp32-c3-ard.yaml diff --git a/tests/components/ads1115/test.esp8266.yaml b/tests/components/ads1115/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ads1115/test.esp8266.yaml rename to tests/components/ads1115/test.esp8266-ard.yaml diff --git a/tests/components/ads1115/test.rp2040.yaml b/tests/components/ads1115/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ads1115/test.rp2040.yaml rename to tests/components/ads1115/test.rp2040-ard.yaml diff --git a/tests/components/ags10/test.esp32.yaml b/tests/components/ags10/test.esp32-ard.yaml similarity index 100% rename from tests/components/ags10/test.esp32.yaml rename to tests/components/ags10/test.esp32-ard.yaml diff --git a/tests/components/ags10/test.esp32-c3.yaml b/tests/components/ags10/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ags10/test.esp32-c3.yaml rename to tests/components/ags10/test.esp32-c3-ard.yaml diff --git a/tests/components/ags10/test.esp8266.yaml b/tests/components/ags10/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ags10/test.esp8266.yaml rename to tests/components/ags10/test.esp8266-ard.yaml diff --git a/tests/components/aht10/test.esp32.yaml b/tests/components/aht10/test.esp32-ard.yaml similarity index 100% rename from tests/components/aht10/test.esp32.yaml rename to tests/components/aht10/test.esp32-ard.yaml diff --git a/tests/components/aht10/test.esp32-c3.yaml b/tests/components/aht10/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/aht10/test.esp32-c3.yaml rename to tests/components/aht10/test.esp32-c3-ard.yaml diff --git a/tests/components/aht10/test.esp8266.yaml b/tests/components/aht10/test.esp8266-ard.yaml similarity index 100% rename from tests/components/aht10/test.esp8266.yaml rename to tests/components/aht10/test.esp8266-ard.yaml diff --git a/tests/components/aht10/test.rp2040.yaml b/tests/components/aht10/test.rp2040-ard.yaml similarity index 100% rename from tests/components/aht10/test.rp2040.yaml rename to tests/components/aht10/test.rp2040-ard.yaml diff --git a/tests/components/airthings_wave_mini/test.esp32-c3.yaml b/tests/components/airthings_wave_mini/test.esp32-ard.yaml similarity index 100% rename from tests/components/airthings_wave_mini/test.esp32-c3.yaml rename to tests/components/airthings_wave_mini/test.esp32-ard.yaml diff --git a/tests/components/airthings_wave_mini/test.esp32.yaml b/tests/components/airthings_wave_mini/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/airthings_wave_mini/test.esp32.yaml rename to tests/components/airthings_wave_mini/test.esp32-c3-ard.yaml diff --git a/tests/components/airthings_wave_plus/test.esp32-c3.yaml b/tests/components/airthings_wave_plus/test.esp32-ard.yaml similarity index 100% rename from tests/components/airthings_wave_plus/test.esp32-c3.yaml rename to tests/components/airthings_wave_plus/test.esp32-ard.yaml diff --git a/tests/components/airthings_wave_plus/test.esp32.yaml b/tests/components/airthings_wave_plus/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/airthings_wave_plus/test.esp32.yaml rename to tests/components/airthings_wave_plus/test.esp32-c3-ard.yaml diff --git a/tests/components/alarm_control_panel/test.esp32-c3.yaml b/tests/components/alarm_control_panel/test.esp32-ard.yaml similarity index 100% rename from tests/components/alarm_control_panel/test.esp32-c3.yaml rename to tests/components/alarm_control_panel/test.esp32-ard.yaml diff --git a/tests/components/alarm_control_panel/test.esp32.yaml b/tests/components/alarm_control_panel/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/alarm_control_panel/test.esp32.yaml rename to tests/components/alarm_control_panel/test.esp32-c3-ard.yaml diff --git a/tests/components/alarm_control_panel/test.esp8266.yaml b/tests/components/alarm_control_panel/test.esp8266-ard.yaml similarity index 100% rename from tests/components/alarm_control_panel/test.esp8266.yaml rename to tests/components/alarm_control_panel/test.esp8266-ard.yaml diff --git a/tests/components/alarm_control_panel/test.rp2040.yaml b/tests/components/alarm_control_panel/test.rp2040-ard.yaml similarity index 100% rename from tests/components/alarm_control_panel/test.rp2040.yaml rename to tests/components/alarm_control_panel/test.rp2040-ard.yaml diff --git a/tests/components/alpha3/test.esp32-c3.yaml b/tests/components/alpha3/test.esp32-ard.yaml similarity index 100% rename from tests/components/alpha3/test.esp32-c3.yaml rename to tests/components/alpha3/test.esp32-ard.yaml diff --git a/tests/components/alpha3/test.esp32.yaml b/tests/components/alpha3/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/alpha3/test.esp32.yaml rename to tests/components/alpha3/test.esp32-c3-ard.yaml diff --git a/tests/components/am2315c/test.esp32.yaml b/tests/components/am2315c/test.esp32-ard.yaml similarity index 100% rename from tests/components/am2315c/test.esp32.yaml rename to tests/components/am2315c/test.esp32-ard.yaml diff --git a/tests/components/am2315c/test.esp32-c3.yaml b/tests/components/am2315c/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/am2315c/test.esp32-c3.yaml rename to tests/components/am2315c/test.esp32-c3-ard.yaml diff --git a/tests/components/am2315c/test.esp8266.yaml b/tests/components/am2315c/test.esp8266-ard.yaml similarity index 100% rename from tests/components/am2315c/test.esp8266.yaml rename to tests/components/am2315c/test.esp8266-ard.yaml diff --git a/tests/components/am2315c/test.rp2040.yaml b/tests/components/am2315c/test.rp2040-ard.yaml similarity index 100% rename from tests/components/am2315c/test.rp2040.yaml rename to tests/components/am2315c/test.rp2040-ard.yaml diff --git a/tests/components/am2320/test.esp32.yaml b/tests/components/am2320/test.esp32-ard.yaml similarity index 100% rename from tests/components/am2320/test.esp32.yaml rename to tests/components/am2320/test.esp32-ard.yaml diff --git a/tests/components/am2320/test.esp32-c3.yaml b/tests/components/am2320/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/am2320/test.esp32-c3.yaml rename to tests/components/am2320/test.esp32-c3-ard.yaml diff --git a/tests/components/am2320/test.esp8266.yaml b/tests/components/am2320/test.esp8266-ard.yaml similarity index 100% rename from tests/components/am2320/test.esp8266.yaml rename to tests/components/am2320/test.esp8266-ard.yaml diff --git a/tests/components/am2320/test.rp2040.yaml b/tests/components/am2320/test.rp2040-ard.yaml similarity index 100% rename from tests/components/am2320/test.rp2040.yaml rename to tests/components/am2320/test.rp2040-ard.yaml diff --git a/tests/components/am43/test.esp32-c3.yaml b/tests/components/am43/test.esp32-ard.yaml similarity index 100% rename from tests/components/am43/test.esp32-c3.yaml rename to tests/components/am43/test.esp32-ard.yaml diff --git a/tests/components/am43/test.esp32.yaml b/tests/components/am43/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/am43/test.esp32.yaml rename to tests/components/am43/test.esp32-c3-ard.yaml diff --git a/tests/components/analog_threshold/test.esp32-c3.yaml b/tests/components/analog_threshold/test.esp32-ard.yaml similarity index 100% rename from tests/components/analog_threshold/test.esp32-c3.yaml rename to tests/components/analog_threshold/test.esp32-ard.yaml diff --git a/tests/components/analog_threshold/test.esp32.yaml b/tests/components/analog_threshold/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/analog_threshold/test.esp32.yaml rename to tests/components/analog_threshold/test.esp32-c3-ard.yaml diff --git a/tests/components/analog_threshold/test.esp8266.yaml b/tests/components/analog_threshold/test.esp8266-ard.yaml similarity index 100% rename from tests/components/analog_threshold/test.esp8266.yaml rename to tests/components/analog_threshold/test.esp8266-ard.yaml diff --git a/tests/components/analog_threshold/test.rp2040.yaml b/tests/components/analog_threshold/test.rp2040-ard.yaml similarity index 100% rename from tests/components/analog_threshold/test.rp2040.yaml rename to tests/components/analog_threshold/test.rp2040-ard.yaml diff --git a/tests/components/animation/test.esp32.yaml b/tests/components/animation/test.esp32-ard.yaml similarity index 100% rename from tests/components/animation/test.esp32.yaml rename to tests/components/animation/test.esp32-ard.yaml diff --git a/tests/components/animation/test.esp32-c3.yaml b/tests/components/animation/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/animation/test.esp32-c3.yaml rename to tests/components/animation/test.esp32-c3-ard.yaml diff --git a/tests/components/animation/test.esp8266.yaml b/tests/components/animation/test.esp8266-ard.yaml similarity index 100% rename from tests/components/animation/test.esp8266.yaml rename to tests/components/animation/test.esp8266-ard.yaml diff --git a/tests/components/animation/test.rp2040.yaml b/tests/components/animation/test.rp2040-ard.yaml similarity index 100% rename from tests/components/animation/test.rp2040.yaml rename to tests/components/animation/test.rp2040-ard.yaml diff --git a/tests/components/anova/test.esp32-c3.yaml b/tests/components/anova/test.esp32-ard.yaml similarity index 100% rename from tests/components/anova/test.esp32-c3.yaml rename to tests/components/anova/test.esp32-ard.yaml diff --git a/tests/components/anova/test.esp32.yaml b/tests/components/anova/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/anova/test.esp32.yaml rename to tests/components/anova/test.esp32-c3-ard.yaml diff --git a/tests/components/apds9960/test.esp32.yaml b/tests/components/apds9960/test.esp32-ard.yaml similarity index 100% rename from tests/components/apds9960/test.esp32.yaml rename to tests/components/apds9960/test.esp32-ard.yaml diff --git a/tests/components/apds9960/test.esp32-c3.yaml b/tests/components/apds9960/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/apds9960/test.esp32-c3.yaml rename to tests/components/apds9960/test.esp32-c3-ard.yaml diff --git a/tests/components/apds9960/test.esp8266.yaml b/tests/components/apds9960/test.esp8266-ard.yaml similarity index 100% rename from tests/components/apds9960/test.esp8266.yaml rename to tests/components/apds9960/test.esp8266-ard.yaml diff --git a/tests/components/apds9960/test.rp2040.yaml b/tests/components/apds9960/test.rp2040-ard.yaml similarity index 100% rename from tests/components/apds9960/test.rp2040.yaml rename to tests/components/apds9960/test.rp2040-ard.yaml diff --git a/tests/components/api/test.esp32-c3.yaml b/tests/components/api/test.esp32-ard.yaml similarity index 100% rename from tests/components/api/test.esp32-c3.yaml rename to tests/components/api/test.esp32-ard.yaml diff --git a/tests/components/api/test.esp32.yaml b/tests/components/api/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/api/test.esp32.yaml rename to tests/components/api/test.esp32-c3-ard.yaml diff --git a/tests/components/api/test.esp8266.yaml b/tests/components/api/test.esp8266-ard.yaml similarity index 100% rename from tests/components/api/test.esp8266.yaml rename to tests/components/api/test.esp8266-ard.yaml diff --git a/tests/components/api/test.rp2040.yaml b/tests/components/api/test.rp2040-ard.yaml similarity index 100% rename from tests/components/api/test.rp2040.yaml rename to tests/components/api/test.rp2040-ard.yaml diff --git a/tests/components/as3935_i2c/test.esp32.yaml b/tests/components/as3935_i2c/test.esp32-ard.yaml similarity index 100% rename from tests/components/as3935_i2c/test.esp32.yaml rename to tests/components/as3935_i2c/test.esp32-ard.yaml diff --git a/tests/components/as3935_i2c/test.esp32-c3.yaml b/tests/components/as3935_i2c/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/as3935_i2c/test.esp32-c3.yaml rename to tests/components/as3935_i2c/test.esp32-c3-ard.yaml diff --git a/tests/components/as3935_i2c/test.esp8266.yaml b/tests/components/as3935_i2c/test.esp8266-ard.yaml similarity index 100% rename from tests/components/as3935_i2c/test.esp8266.yaml rename to tests/components/as3935_i2c/test.esp8266-ard.yaml diff --git a/tests/components/as3935_i2c/test.rp2040.yaml b/tests/components/as3935_i2c/test.rp2040-ard.yaml similarity index 100% rename from tests/components/as3935_i2c/test.rp2040.yaml rename to tests/components/as3935_i2c/test.rp2040-ard.yaml diff --git a/tests/components/as3935_spi/test.esp32.yaml b/tests/components/as3935_spi/test.esp32-ard.yaml similarity index 100% rename from tests/components/as3935_spi/test.esp32.yaml rename to tests/components/as3935_spi/test.esp32-ard.yaml diff --git a/tests/components/as3935_spi/test.esp32-c3.yaml b/tests/components/as3935_spi/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/as3935_spi/test.esp32-c3.yaml rename to tests/components/as3935_spi/test.esp32-c3-ard.yaml diff --git a/tests/components/as3935_spi/test.esp8266.yaml b/tests/components/as3935_spi/test.esp8266-ard.yaml similarity index 100% rename from tests/components/as3935_spi/test.esp8266.yaml rename to tests/components/as3935_spi/test.esp8266-ard.yaml diff --git a/tests/components/as3935_spi/test.rp2040.yaml b/tests/components/as3935_spi/test.rp2040-ard.yaml similarity index 100% rename from tests/components/as3935_spi/test.rp2040.yaml rename to tests/components/as3935_spi/test.rp2040-ard.yaml diff --git a/tests/components/as5600/test.esp32.yaml b/tests/components/as5600/test.esp32-ard.yaml similarity index 100% rename from tests/components/as5600/test.esp32.yaml rename to tests/components/as5600/test.esp32-ard.yaml diff --git a/tests/components/as5600/test.esp32-c3.yaml b/tests/components/as5600/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/as5600/test.esp32-c3.yaml rename to tests/components/as5600/test.esp32-c3-ard.yaml diff --git a/tests/components/as5600/test.esp8266.yaml b/tests/components/as5600/test.esp8266-ard.yaml similarity index 100% rename from tests/components/as5600/test.esp8266.yaml rename to tests/components/as5600/test.esp8266-ard.yaml diff --git a/tests/components/as5600/test.rp2040.yaml b/tests/components/as5600/test.rp2040-ard.yaml similarity index 100% rename from tests/components/as5600/test.rp2040.yaml rename to tests/components/as5600/test.rp2040-ard.yaml diff --git a/tests/components/as7341/test.esp32.yaml b/tests/components/as7341/test.esp32-ard.yaml similarity index 100% rename from tests/components/as7341/test.esp32.yaml rename to tests/components/as7341/test.esp32-ard.yaml diff --git a/tests/components/as7341/test.esp32-c3.yaml b/tests/components/as7341/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/as7341/test.esp32-c3.yaml rename to tests/components/as7341/test.esp32-c3-ard.yaml diff --git a/tests/components/as7341/test.esp8266.yaml b/tests/components/as7341/test.esp8266-ard.yaml similarity index 100% rename from tests/components/as7341/test.esp8266.yaml rename to tests/components/as7341/test.esp8266-ard.yaml diff --git a/tests/components/as7341/test.rp2040.yaml b/tests/components/as7341/test.rp2040-ard.yaml similarity index 100% rename from tests/components/as7341/test.rp2040.yaml rename to tests/components/as7341/test.rp2040-ard.yaml diff --git a/tests/components/at581x/test.esp32.yaml b/tests/components/at581x/test.esp32-ard.yaml similarity index 100% rename from tests/components/at581x/test.esp32.yaml rename to tests/components/at581x/test.esp32-ard.yaml diff --git a/tests/components/at581x/test.esp32-c3.yaml b/tests/components/at581x/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/at581x/test.esp32-c3.yaml rename to tests/components/at581x/test.esp32-c3-ard.yaml diff --git a/tests/components/at581x/test.esp8266.yaml b/tests/components/at581x/test.esp8266-ard.yaml similarity index 100% rename from tests/components/at581x/test.esp8266.yaml rename to tests/components/at581x/test.esp8266-ard.yaml diff --git a/tests/components/at581x/test.rp2040.yaml b/tests/components/at581x/test.rp2040-ard.yaml similarity index 100% rename from tests/components/at581x/test.rp2040.yaml rename to tests/components/at581x/test.rp2040-ard.yaml diff --git a/tests/components/atc_mithermometer/test.esp32-c3.yaml b/tests/components/atc_mithermometer/test.esp32-ard.yaml similarity index 100% rename from tests/components/atc_mithermometer/test.esp32-c3.yaml rename to tests/components/atc_mithermometer/test.esp32-ard.yaml diff --git a/tests/components/atc_mithermometer/test.esp32.yaml b/tests/components/atc_mithermometer/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/atc_mithermometer/test.esp32.yaml rename to tests/components/atc_mithermometer/test.esp32-c3-ard.yaml diff --git a/tests/components/atm90e26/test.esp32.yaml b/tests/components/atm90e26/test.esp32-ard.yaml similarity index 100% rename from tests/components/atm90e26/test.esp32.yaml rename to tests/components/atm90e26/test.esp32-ard.yaml diff --git a/tests/components/atm90e26/test.esp32-c3.yaml b/tests/components/atm90e26/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/atm90e26/test.esp32-c3.yaml rename to tests/components/atm90e26/test.esp32-c3-ard.yaml diff --git a/tests/components/atm90e26/test.esp8266.yaml b/tests/components/atm90e26/test.esp8266-ard.yaml similarity index 100% rename from tests/components/atm90e26/test.esp8266.yaml rename to tests/components/atm90e26/test.esp8266-ard.yaml diff --git a/tests/components/atm90e26/test.rp2040.yaml b/tests/components/atm90e26/test.rp2040-ard.yaml similarity index 100% rename from tests/components/atm90e26/test.rp2040.yaml rename to tests/components/atm90e26/test.rp2040-ard.yaml diff --git a/tests/components/atm90e32/test.esp32.yaml b/tests/components/atm90e32/test.esp32-ard.yaml similarity index 100% rename from tests/components/atm90e32/test.esp32.yaml rename to tests/components/atm90e32/test.esp32-ard.yaml diff --git a/tests/components/atm90e32/test.esp32-c3.yaml b/tests/components/atm90e32/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/atm90e32/test.esp32-c3.yaml rename to tests/components/atm90e32/test.esp32-c3-ard.yaml diff --git a/tests/components/atm90e32/test.esp8266.yaml b/tests/components/atm90e32/test.esp8266-ard.yaml similarity index 100% rename from tests/components/atm90e32/test.esp8266.yaml rename to tests/components/atm90e32/test.esp8266-ard.yaml diff --git a/tests/components/atm90e32/test.rp2040.yaml b/tests/components/atm90e32/test.rp2040-ard.yaml similarity index 100% rename from tests/components/atm90e32/test.rp2040.yaml rename to tests/components/atm90e32/test.rp2040-ard.yaml diff --git a/tests/components/b_parasite/test.esp32-c3.yaml b/tests/components/b_parasite/test.esp32-ard.yaml similarity index 100% rename from tests/components/b_parasite/test.esp32-c3.yaml rename to tests/components/b_parasite/test.esp32-ard.yaml diff --git a/tests/components/b_parasite/test.esp32.yaml b/tests/components/b_parasite/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/b_parasite/test.esp32.yaml rename to tests/components/b_parasite/test.esp32-c3-ard.yaml diff --git a/tests/components/ballu/test.esp32.yaml b/tests/components/ballu/test.esp32-ard.yaml similarity index 100% rename from tests/components/ballu/test.esp32.yaml rename to tests/components/ballu/test.esp32-ard.yaml diff --git a/tests/components/ballu/test.esp8266.yaml b/tests/components/ballu/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ballu/test.esp8266.yaml rename to tests/components/ballu/test.esp8266-ard.yaml diff --git a/tests/components/bang_bang/test.esp32-c3.yaml b/tests/components/bang_bang/test.esp32-ard.yaml similarity index 100% rename from tests/components/bang_bang/test.esp32-c3.yaml rename to tests/components/bang_bang/test.esp32-ard.yaml diff --git a/tests/components/bang_bang/test.esp32.yaml b/tests/components/bang_bang/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/bang_bang/test.esp32.yaml rename to tests/components/bang_bang/test.esp32-c3-ard.yaml diff --git a/tests/components/bang_bang/test.esp8266.yaml b/tests/components/bang_bang/test.esp8266-ard.yaml similarity index 100% rename from tests/components/bang_bang/test.esp8266.yaml rename to tests/components/bang_bang/test.esp8266-ard.yaml diff --git a/tests/components/bang_bang/test.rp2040.yaml b/tests/components/bang_bang/test.rp2040-ard.yaml similarity index 100% rename from tests/components/bang_bang/test.rp2040.yaml rename to tests/components/bang_bang/test.rp2040-ard.yaml diff --git a/tests/components/bedjet/test.esp32-c3.yaml b/tests/components/bedjet/test.esp32-ard.yaml similarity index 100% rename from tests/components/bedjet/test.esp32-c3.yaml rename to tests/components/bedjet/test.esp32-ard.yaml diff --git a/tests/components/bedjet/test.esp32.yaml b/tests/components/bedjet/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/bedjet/test.esp32.yaml rename to tests/components/bedjet/test.esp32-c3-ard.yaml diff --git a/tests/components/beken_spi_led_strip/test.bk72xx.yaml b/tests/components/beken_spi_led_strip/test.bk72xx-ard.yaml similarity index 100% rename from tests/components/beken_spi_led_strip/test.bk72xx.yaml rename to tests/components/beken_spi_led_strip/test.bk72xx-ard.yaml diff --git a/tests/components/bh1750/test.esp32.yaml b/tests/components/bh1750/test.esp32-ard.yaml similarity index 100% rename from tests/components/bh1750/test.esp32.yaml rename to tests/components/bh1750/test.esp32-ard.yaml diff --git a/tests/components/bh1750/test.esp32-c3.yaml b/tests/components/bh1750/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/bh1750/test.esp32-c3.yaml rename to tests/components/bh1750/test.esp32-c3-ard.yaml diff --git a/tests/components/bh1750/test.esp8266.yaml b/tests/components/bh1750/test.esp8266-ard.yaml similarity index 100% rename from tests/components/bh1750/test.esp8266.yaml rename to tests/components/bh1750/test.esp8266-ard.yaml diff --git a/tests/components/bh1750/test.rp2040.yaml b/tests/components/bh1750/test.rp2040-ard.yaml similarity index 100% rename from tests/components/bh1750/test.rp2040.yaml rename to tests/components/bh1750/test.rp2040-ard.yaml diff --git a/tests/components/binary_sensor_map/test.esp32-c3.yaml b/tests/components/binary_sensor_map/test.esp32-ard.yaml similarity index 100% rename from tests/components/binary_sensor_map/test.esp32-c3.yaml rename to tests/components/binary_sensor_map/test.esp32-ard.yaml diff --git a/tests/components/binary_sensor_map/test.esp32.yaml b/tests/components/binary_sensor_map/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/binary_sensor_map/test.esp32.yaml rename to tests/components/binary_sensor_map/test.esp32-c3-ard.yaml diff --git a/tests/components/binary_sensor_map/test.esp8266.yaml b/tests/components/binary_sensor_map/test.esp8266-ard.yaml similarity index 100% rename from tests/components/binary_sensor_map/test.esp8266.yaml rename to tests/components/binary_sensor_map/test.esp8266-ard.yaml diff --git a/tests/components/binary_sensor_map/test.rp2040.yaml b/tests/components/binary_sensor_map/test.rp2040-ard.yaml similarity index 100% rename from tests/components/binary_sensor_map/test.rp2040.yaml rename to tests/components/binary_sensor_map/test.rp2040-ard.yaml diff --git a/tests/components/bl0939/test.esp32.yaml b/tests/components/bl0939/test.esp32-ard.yaml similarity index 100% rename from tests/components/bl0939/test.esp32.yaml rename to tests/components/bl0939/test.esp32-ard.yaml diff --git a/tests/components/bl0939/test.esp32-c3.yaml b/tests/components/bl0939/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/bl0939/test.esp32-c3.yaml rename to tests/components/bl0939/test.esp32-c3-ard.yaml diff --git a/tests/components/bl0939/test.esp8266.yaml b/tests/components/bl0939/test.esp8266-ard.yaml similarity index 100% rename from tests/components/bl0939/test.esp8266.yaml rename to tests/components/bl0939/test.esp8266-ard.yaml diff --git a/tests/components/bl0939/test.rp2040.yaml b/tests/components/bl0939/test.rp2040-ard.yaml similarity index 100% rename from tests/components/bl0939/test.rp2040.yaml rename to tests/components/bl0939/test.rp2040-ard.yaml diff --git a/tests/components/bl0940/test.esp32.yaml b/tests/components/bl0940/test.esp32-ard.yaml similarity index 100% rename from tests/components/bl0940/test.esp32.yaml rename to tests/components/bl0940/test.esp32-ard.yaml diff --git a/tests/components/bl0940/test.esp32-c3.yaml b/tests/components/bl0940/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/bl0940/test.esp32-c3.yaml rename to tests/components/bl0940/test.esp32-c3-ard.yaml diff --git a/tests/components/bl0940/test.esp8266.yaml b/tests/components/bl0940/test.esp8266-ard.yaml similarity index 100% rename from tests/components/bl0940/test.esp8266.yaml rename to tests/components/bl0940/test.esp8266-ard.yaml diff --git a/tests/components/bl0940/test.rp2040.yaml b/tests/components/bl0940/test.rp2040-ard.yaml similarity index 100% rename from tests/components/bl0940/test.rp2040.yaml rename to tests/components/bl0940/test.rp2040-ard.yaml diff --git a/tests/components/bl0942/test.esp32.yaml b/tests/components/bl0942/test.esp32-ard.yaml similarity index 100% rename from tests/components/bl0942/test.esp32.yaml rename to tests/components/bl0942/test.esp32-ard.yaml diff --git a/tests/components/bl0942/test.esp32-c3.yaml b/tests/components/bl0942/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/bl0942/test.esp32-c3.yaml rename to tests/components/bl0942/test.esp32-c3-ard.yaml diff --git a/tests/components/bl0942/test.esp8266.yaml b/tests/components/bl0942/test.esp8266-ard.yaml similarity index 100% rename from tests/components/bl0942/test.esp8266.yaml rename to tests/components/bl0942/test.esp8266-ard.yaml diff --git a/tests/components/bl0942/test.rp2040.yaml b/tests/components/bl0942/test.rp2040-ard.yaml similarity index 100% rename from tests/components/bl0942/test.rp2040.yaml rename to tests/components/bl0942/test.rp2040-ard.yaml diff --git a/tests/components/ble_client/test.esp32-c3.yaml b/tests/components/ble_client/test.esp32-ard.yaml similarity index 100% rename from tests/components/ble_client/test.esp32-c3.yaml rename to tests/components/ble_client/test.esp32-ard.yaml diff --git a/tests/components/ble_client/test.esp32.yaml b/tests/components/ble_client/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ble_client/test.esp32.yaml rename to tests/components/ble_client/test.esp32-c3-ard.yaml diff --git a/tests/components/ble_presence/test.esp32-c3.yaml b/tests/components/ble_presence/test.esp32-ard.yaml similarity index 100% rename from tests/components/ble_presence/test.esp32-c3.yaml rename to tests/components/ble_presence/test.esp32-ard.yaml diff --git a/tests/components/ble_presence/test.esp32.yaml b/tests/components/ble_presence/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ble_presence/test.esp32.yaml rename to tests/components/ble_presence/test.esp32-c3-ard.yaml diff --git a/tests/components/ble_rssi/test.esp32-c3.yaml b/tests/components/ble_rssi/test.esp32-ard.yaml similarity index 100% rename from tests/components/ble_rssi/test.esp32-c3.yaml rename to tests/components/ble_rssi/test.esp32-ard.yaml diff --git a/tests/components/ble_rssi/test.esp32.yaml b/tests/components/ble_rssi/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ble_rssi/test.esp32.yaml rename to tests/components/ble_rssi/test.esp32-c3-ard.yaml diff --git a/tests/components/ble_scanner/test.esp32-c3.yaml b/tests/components/ble_scanner/test.esp32-ard.yaml similarity index 100% rename from tests/components/ble_scanner/test.esp32-c3.yaml rename to tests/components/ble_scanner/test.esp32-ard.yaml diff --git a/tests/components/ble_scanner/test.esp32.yaml b/tests/components/ble_scanner/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ble_scanner/test.esp32.yaml rename to tests/components/ble_scanner/test.esp32-c3-ard.yaml diff --git a/tests/components/bme280_i2c/test.esp32.yaml b/tests/components/bme280_i2c/test.esp32-ard.yaml similarity index 100% rename from tests/components/bme280_i2c/test.esp32.yaml rename to tests/components/bme280_i2c/test.esp32-ard.yaml diff --git a/tests/components/bme280_i2c/test.esp32-c3.yaml b/tests/components/bme280_i2c/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/bme280_i2c/test.esp32-c3.yaml rename to tests/components/bme280_i2c/test.esp32-c3-ard.yaml diff --git a/tests/components/bme280_i2c/test.esp8266.yaml b/tests/components/bme280_i2c/test.esp8266-ard.yaml similarity index 100% rename from tests/components/bme280_i2c/test.esp8266.yaml rename to tests/components/bme280_i2c/test.esp8266-ard.yaml diff --git a/tests/components/bme280_i2c/test.rp2040.yaml b/tests/components/bme280_i2c/test.rp2040-ard.yaml similarity index 100% rename from tests/components/bme280_i2c/test.rp2040.yaml rename to tests/components/bme280_i2c/test.rp2040-ard.yaml diff --git a/tests/components/bme280_spi/test.esp32.yaml b/tests/components/bme280_spi/test.esp32-ard.yaml similarity index 100% rename from tests/components/bme280_spi/test.esp32.yaml rename to tests/components/bme280_spi/test.esp32-ard.yaml diff --git a/tests/components/bme280_spi/test.esp32-c3.yaml b/tests/components/bme280_spi/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/bme280_spi/test.esp32-c3.yaml rename to tests/components/bme280_spi/test.esp32-c3-ard.yaml diff --git a/tests/components/bme280_spi/test.esp8266.yaml b/tests/components/bme280_spi/test.esp8266-ard.yaml similarity index 100% rename from tests/components/bme280_spi/test.esp8266.yaml rename to tests/components/bme280_spi/test.esp8266-ard.yaml diff --git a/tests/components/bme280_spi/test.rp2040.yaml b/tests/components/bme280_spi/test.rp2040-ard.yaml similarity index 100% rename from tests/components/bme280_spi/test.rp2040.yaml rename to tests/components/bme280_spi/test.rp2040-ard.yaml diff --git a/tests/components/bme680/test.esp32.yaml b/tests/components/bme680/test.esp32-ard.yaml similarity index 100% rename from tests/components/bme680/test.esp32.yaml rename to tests/components/bme680/test.esp32-ard.yaml diff --git a/tests/components/bme680/test.esp32-c3.yaml b/tests/components/bme680/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/bme680/test.esp32-c3.yaml rename to tests/components/bme680/test.esp32-c3-ard.yaml diff --git a/tests/components/bme680/test.esp8266.yaml b/tests/components/bme680/test.esp8266-ard.yaml similarity index 100% rename from tests/components/bme680/test.esp8266.yaml rename to tests/components/bme680/test.esp8266-ard.yaml diff --git a/tests/components/bme680/test.rp2040.yaml b/tests/components/bme680/test.rp2040-ard.yaml similarity index 100% rename from tests/components/bme680/test.rp2040.yaml rename to tests/components/bme680/test.rp2040-ard.yaml diff --git a/tests/components/bme680_bsec/test.esp32.yaml b/tests/components/bme680_bsec/test.esp32-ard.yaml similarity index 100% rename from tests/components/bme680_bsec/test.esp32.yaml rename to tests/components/bme680_bsec/test.esp32-ard.yaml diff --git a/tests/components/bme680_bsec/test.esp8266.yaml b/tests/components/bme680_bsec/test.esp8266-ard.yaml similarity index 100% rename from tests/components/bme680_bsec/test.esp8266.yaml rename to tests/components/bme680_bsec/test.esp8266-ard.yaml diff --git a/tests/components/bmi160/test.esp32.yaml b/tests/components/bmi160/test.esp32-ard.yaml similarity index 100% rename from tests/components/bmi160/test.esp32.yaml rename to tests/components/bmi160/test.esp32-ard.yaml diff --git a/tests/components/bmi160/test.esp32-c3.yaml b/tests/components/bmi160/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/bmi160/test.esp32-c3.yaml rename to tests/components/bmi160/test.esp32-c3-ard.yaml diff --git a/tests/components/bmi160/test.esp8266.yaml b/tests/components/bmi160/test.esp8266-ard.yaml similarity index 100% rename from tests/components/bmi160/test.esp8266.yaml rename to tests/components/bmi160/test.esp8266-ard.yaml diff --git a/tests/components/bmi160/test.rp2040.yaml b/tests/components/bmi160/test.rp2040-ard.yaml similarity index 100% rename from tests/components/bmi160/test.rp2040.yaml rename to tests/components/bmi160/test.rp2040-ard.yaml diff --git a/tests/components/bmp085/test.esp32.yaml b/tests/components/bmp085/test.esp32-ard.yaml similarity index 100% rename from tests/components/bmp085/test.esp32.yaml rename to tests/components/bmp085/test.esp32-ard.yaml diff --git a/tests/components/bmp085/test.esp32-c3.yaml b/tests/components/bmp085/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/bmp085/test.esp32-c3.yaml rename to tests/components/bmp085/test.esp32-c3-ard.yaml diff --git a/tests/components/bmp085/test.esp8266.yaml b/tests/components/bmp085/test.esp8266-ard.yaml similarity index 100% rename from tests/components/bmp085/test.esp8266.yaml rename to tests/components/bmp085/test.esp8266-ard.yaml diff --git a/tests/components/bmp085/test.rp2040.yaml b/tests/components/bmp085/test.rp2040-ard.yaml similarity index 100% rename from tests/components/bmp085/test.rp2040.yaml rename to tests/components/bmp085/test.rp2040-ard.yaml diff --git a/tests/components/bmp280/test.esp32.yaml b/tests/components/bmp280/test.esp32-ard.yaml similarity index 100% rename from tests/components/bmp280/test.esp32.yaml rename to tests/components/bmp280/test.esp32-ard.yaml diff --git a/tests/components/bmp280/test.esp32-c3.yaml b/tests/components/bmp280/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/bmp280/test.esp32-c3.yaml rename to tests/components/bmp280/test.esp32-c3-ard.yaml diff --git a/tests/components/bmp280/test.esp8266.yaml b/tests/components/bmp280/test.esp8266-ard.yaml similarity index 100% rename from tests/components/bmp280/test.esp8266.yaml rename to tests/components/bmp280/test.esp8266-ard.yaml diff --git a/tests/components/bmp280/test.rp2040.yaml b/tests/components/bmp280/test.rp2040-ard.yaml similarity index 100% rename from tests/components/bmp280/test.rp2040.yaml rename to tests/components/bmp280/test.rp2040-ard.yaml diff --git a/tests/components/bmp3xx_i2c/test.esp32.yaml b/tests/components/bmp3xx_i2c/test.esp32-ard.yaml similarity index 100% rename from tests/components/bmp3xx_i2c/test.esp32.yaml rename to tests/components/bmp3xx_i2c/test.esp32-ard.yaml diff --git a/tests/components/bmp3xx_i2c/test.esp32-c3.yaml b/tests/components/bmp3xx_i2c/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/bmp3xx_i2c/test.esp32-c3.yaml rename to tests/components/bmp3xx_i2c/test.esp32-c3-ard.yaml diff --git a/tests/components/bmp3xx_i2c/test.esp8266.yaml b/tests/components/bmp3xx_i2c/test.esp8266-ard.yaml similarity index 100% rename from tests/components/bmp3xx_i2c/test.esp8266.yaml rename to tests/components/bmp3xx_i2c/test.esp8266-ard.yaml diff --git a/tests/components/bmp3xx_i2c/test.rp2040.yaml b/tests/components/bmp3xx_i2c/test.rp2040-ard.yaml similarity index 100% rename from tests/components/bmp3xx_i2c/test.rp2040.yaml rename to tests/components/bmp3xx_i2c/test.rp2040-ard.yaml diff --git a/tests/components/bmp3xx_spi/test.esp32.yaml b/tests/components/bmp3xx_spi/test.esp32-ard.yaml similarity index 100% rename from tests/components/bmp3xx_spi/test.esp32.yaml rename to tests/components/bmp3xx_spi/test.esp32-ard.yaml diff --git a/tests/components/bmp3xx_spi/test.esp32-c3.yaml b/tests/components/bmp3xx_spi/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/bmp3xx_spi/test.esp32-c3.yaml rename to tests/components/bmp3xx_spi/test.esp32-c3-ard.yaml diff --git a/tests/components/bmp3xx_spi/test.esp8266.yaml b/tests/components/bmp3xx_spi/test.esp8266-ard.yaml similarity index 100% rename from tests/components/bmp3xx_spi/test.esp8266.yaml rename to tests/components/bmp3xx_spi/test.esp8266-ard.yaml diff --git a/tests/components/bmp3xx_spi/test.rp2040.yaml b/tests/components/bmp3xx_spi/test.rp2040-ard.yaml similarity index 100% rename from tests/components/bmp3xx_spi/test.rp2040.yaml rename to tests/components/bmp3xx_spi/test.rp2040-ard.yaml diff --git a/tests/components/bmp581/test.esp32.yaml b/tests/components/bmp581/test.esp32-ard.yaml similarity index 100% rename from tests/components/bmp581/test.esp32.yaml rename to tests/components/bmp581/test.esp32-ard.yaml diff --git a/tests/components/bmp581/test.esp32-c3.yaml b/tests/components/bmp581/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/bmp581/test.esp32-c3.yaml rename to tests/components/bmp581/test.esp32-c3-ard.yaml diff --git a/tests/components/bmp581/test.esp8266.yaml b/tests/components/bmp581/test.esp8266-ard.yaml similarity index 100% rename from tests/components/bmp581/test.esp8266.yaml rename to tests/components/bmp581/test.esp8266-ard.yaml diff --git a/tests/components/bmp581/test.rp2040.yaml b/tests/components/bmp581/test.rp2040-ard.yaml similarity index 100% rename from tests/components/bmp581/test.rp2040.yaml rename to tests/components/bmp581/test.rp2040-ard.yaml diff --git a/tests/components/bp1658cj/test.esp32.yaml b/tests/components/bp1658cj/test.esp32-ard.yaml similarity index 100% rename from tests/components/bp1658cj/test.esp32.yaml rename to tests/components/bp1658cj/test.esp32-ard.yaml diff --git a/tests/components/bp1658cj/test.esp32-c3.yaml b/tests/components/bp1658cj/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/bp1658cj/test.esp32-c3.yaml rename to tests/components/bp1658cj/test.esp32-c3-ard.yaml diff --git a/tests/components/bp1658cj/test.esp8266.yaml b/tests/components/bp1658cj/test.esp8266-ard.yaml similarity index 100% rename from tests/components/bp1658cj/test.esp8266.yaml rename to tests/components/bp1658cj/test.esp8266-ard.yaml diff --git a/tests/components/bp1658cj/test.rp2040.yaml b/tests/components/bp1658cj/test.rp2040-ard.yaml similarity index 100% rename from tests/components/bp1658cj/test.rp2040.yaml rename to tests/components/bp1658cj/test.rp2040-ard.yaml diff --git a/tests/components/bp5758d/test.esp32.yaml b/tests/components/bp5758d/test.esp32-ard.yaml similarity index 100% rename from tests/components/bp5758d/test.esp32.yaml rename to tests/components/bp5758d/test.esp32-ard.yaml diff --git a/tests/components/bp5758d/test.esp32-c3.yaml b/tests/components/bp5758d/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/bp5758d/test.esp32-c3.yaml rename to tests/components/bp5758d/test.esp32-c3-ard.yaml diff --git a/tests/components/bp5758d/test.esp8266.yaml b/tests/components/bp5758d/test.esp8266-ard.yaml similarity index 100% rename from tests/components/bp5758d/test.esp8266.yaml rename to tests/components/bp5758d/test.esp8266-ard.yaml diff --git a/tests/components/bp5758d/test.rp2040.yaml b/tests/components/bp5758d/test.rp2040-ard.yaml similarity index 100% rename from tests/components/bp5758d/test.rp2040.yaml rename to tests/components/bp5758d/test.rp2040-ard.yaml diff --git a/tests/components/button/test.esp32-c3.yaml b/tests/components/button/test.esp32-ard.yaml similarity index 100% rename from tests/components/button/test.esp32-c3.yaml rename to tests/components/button/test.esp32-ard.yaml diff --git a/tests/components/button/test.esp32.yaml b/tests/components/button/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/button/test.esp32.yaml rename to tests/components/button/test.esp32-c3-ard.yaml diff --git a/tests/components/button/test.esp8266.yaml b/tests/components/button/test.esp8266-ard.yaml similarity index 100% rename from tests/components/button/test.esp8266.yaml rename to tests/components/button/test.esp8266-ard.yaml diff --git a/tests/components/button/test.rp2040.yaml b/tests/components/button/test.rp2040-ard.yaml similarity index 100% rename from tests/components/button/test.rp2040.yaml rename to tests/components/button/test.rp2040-ard.yaml diff --git a/tests/components/canbus/test.esp32-c3.yaml b/tests/components/canbus/test.esp32-ard.yaml similarity index 100% rename from tests/components/canbus/test.esp32-c3.yaml rename to tests/components/canbus/test.esp32-ard.yaml diff --git a/tests/components/canbus/test.esp32.yaml b/tests/components/canbus/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/canbus/test.esp32.yaml rename to tests/components/canbus/test.esp32-c3-ard.yaml diff --git a/tests/components/cap1188/test.esp32.yaml b/tests/components/cap1188/test.esp32-ard.yaml similarity index 100% rename from tests/components/cap1188/test.esp32.yaml rename to tests/components/cap1188/test.esp32-ard.yaml diff --git a/tests/components/cap1188/test.esp32-c3.yaml b/tests/components/cap1188/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/cap1188/test.esp32-c3.yaml rename to tests/components/cap1188/test.esp32-c3-ard.yaml diff --git a/tests/components/cap1188/test.esp8266.yaml b/tests/components/cap1188/test.esp8266-ard.yaml similarity index 100% rename from tests/components/cap1188/test.esp8266.yaml rename to tests/components/cap1188/test.esp8266-ard.yaml diff --git a/tests/components/cap1188/test.rp2040.yaml b/tests/components/cap1188/test.rp2040-ard.yaml similarity index 100% rename from tests/components/cap1188/test.rp2040.yaml rename to tests/components/cap1188/test.rp2040-ard.yaml diff --git a/tests/components/captive_portal/test.esp32-c3.yaml b/tests/components/captive_portal/test.esp32-ard.yaml similarity index 100% rename from tests/components/captive_portal/test.esp32-c3.yaml rename to tests/components/captive_portal/test.esp32-ard.yaml diff --git a/tests/components/captive_portal/test.esp32.yaml b/tests/components/captive_portal/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/captive_portal/test.esp32.yaml rename to tests/components/captive_portal/test.esp32-c3-ard.yaml diff --git a/tests/components/captive_portal/test.esp8266.yaml b/tests/components/captive_portal/test.esp8266-ard.yaml similarity index 100% rename from tests/components/captive_portal/test.esp8266.yaml rename to tests/components/captive_portal/test.esp8266-ard.yaml diff --git a/tests/components/ccs811/test.esp32.yaml b/tests/components/ccs811/test.esp32-ard.yaml similarity index 100% rename from tests/components/ccs811/test.esp32.yaml rename to tests/components/ccs811/test.esp32-ard.yaml diff --git a/tests/components/ccs811/test.esp32-c3.yaml b/tests/components/ccs811/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ccs811/test.esp32-c3.yaml rename to tests/components/ccs811/test.esp32-c3-ard.yaml diff --git a/tests/components/ccs811/test.esp8266.yaml b/tests/components/ccs811/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ccs811/test.esp8266.yaml rename to tests/components/ccs811/test.esp8266-ard.yaml diff --git a/tests/components/ccs811/test.rp2040.yaml b/tests/components/ccs811/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ccs811/test.rp2040.yaml rename to tests/components/ccs811/test.rp2040-ard.yaml diff --git a/tests/components/cd74hc4067/test.esp32.yaml b/tests/components/cd74hc4067/test.esp32-ard.yaml similarity index 100% rename from tests/components/cd74hc4067/test.esp32.yaml rename to tests/components/cd74hc4067/test.esp32-ard.yaml diff --git a/tests/components/cd74hc4067/test.esp32-c3.yaml b/tests/components/cd74hc4067/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/cd74hc4067/test.esp32-c3.yaml rename to tests/components/cd74hc4067/test.esp32-c3-ard.yaml diff --git a/tests/components/cd74hc4067/test.esp8266.yaml b/tests/components/cd74hc4067/test.esp8266-ard.yaml similarity index 100% rename from tests/components/cd74hc4067/test.esp8266.yaml rename to tests/components/cd74hc4067/test.esp8266-ard.yaml diff --git a/tests/components/cd74hc4067/test.rp2040.yaml b/tests/components/cd74hc4067/test.rp2040-ard.yaml similarity index 100% rename from tests/components/cd74hc4067/test.rp2040.yaml rename to tests/components/cd74hc4067/test.rp2040-ard.yaml diff --git a/tests/components/climate_ir_lg/test.esp32-c3.yaml b/tests/components/climate_ir_lg/test.esp32-ard.yaml similarity index 100% rename from tests/components/climate_ir_lg/test.esp32-c3.yaml rename to tests/components/climate_ir_lg/test.esp32-ard.yaml diff --git a/tests/components/climate_ir_lg/test.esp32.yaml b/tests/components/climate_ir_lg/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/climate_ir_lg/test.esp32.yaml rename to tests/components/climate_ir_lg/test.esp32-c3-ard.yaml diff --git a/tests/components/climate_ir_lg/test.esp8266.yaml b/tests/components/climate_ir_lg/test.esp8266-ard.yaml similarity index 100% rename from tests/components/climate_ir_lg/test.esp8266.yaml rename to tests/components/climate_ir_lg/test.esp8266-ard.yaml diff --git a/tests/components/color/test.esp32-c3.yaml b/tests/components/color/test.esp32-ard.yaml similarity index 100% rename from tests/components/color/test.esp32-c3.yaml rename to tests/components/color/test.esp32-ard.yaml diff --git a/tests/components/color/test.esp32.yaml b/tests/components/color/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/color/test.esp32.yaml rename to tests/components/color/test.esp32-c3-ard.yaml diff --git a/tests/components/color/test.esp8266.yaml b/tests/components/color/test.esp8266-ard.yaml similarity index 100% rename from tests/components/color/test.esp8266.yaml rename to tests/components/color/test.esp8266-ard.yaml diff --git a/tests/components/color/test.rp2040.yaml b/tests/components/color/test.rp2040-ard.yaml similarity index 100% rename from tests/components/color/test.rp2040.yaml rename to tests/components/color/test.rp2040-ard.yaml diff --git a/tests/components/color_temperature/test.esp32.yaml b/tests/components/color_temperature/test.esp32-ard.yaml similarity index 100% rename from tests/components/color_temperature/test.esp32.yaml rename to tests/components/color_temperature/test.esp32-ard.yaml diff --git a/tests/components/color_temperature/test.esp32-c3.yaml b/tests/components/color_temperature/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/color_temperature/test.esp32-c3.yaml rename to tests/components/color_temperature/test.esp32-c3-ard.yaml diff --git a/tests/components/color_temperature/test.esp8266.yaml b/tests/components/color_temperature/test.esp8266-ard.yaml similarity index 100% rename from tests/components/color_temperature/test.esp8266.yaml rename to tests/components/color_temperature/test.esp8266-ard.yaml diff --git a/tests/components/color_temperature/test.rp2040.yaml b/tests/components/color_temperature/test.rp2040-ard.yaml similarity index 100% rename from tests/components/color_temperature/test.rp2040.yaml rename to tests/components/color_temperature/test.rp2040-ard.yaml diff --git a/tests/components/combination/test.esp32-c3.yaml b/tests/components/combination/test.esp32-ard.yaml similarity index 100% rename from tests/components/combination/test.esp32-c3.yaml rename to tests/components/combination/test.esp32-ard.yaml diff --git a/tests/components/combination/test.esp32.yaml b/tests/components/combination/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/combination/test.esp32.yaml rename to tests/components/combination/test.esp32-c3-ard.yaml diff --git a/tests/components/combination/test.esp8266.yaml b/tests/components/combination/test.esp8266-ard.yaml similarity index 100% rename from tests/components/combination/test.esp8266.yaml rename to tests/components/combination/test.esp8266-ard.yaml diff --git a/tests/components/combination/test.rp2040.yaml b/tests/components/combination/test.rp2040-ard.yaml similarity index 100% rename from tests/components/combination/test.rp2040.yaml rename to tests/components/combination/test.rp2040-ard.yaml diff --git a/tests/components/coolix/test.esp32-c3.yaml b/tests/components/coolix/test.esp32-ard.yaml similarity index 100% rename from tests/components/coolix/test.esp32-c3.yaml rename to tests/components/coolix/test.esp32-ard.yaml diff --git a/tests/components/coolix/test.esp32.yaml b/tests/components/coolix/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/coolix/test.esp32.yaml rename to tests/components/coolix/test.esp32-c3-ard.yaml diff --git a/tests/components/coolix/test.esp8266.yaml b/tests/components/coolix/test.esp8266-ard.yaml similarity index 100% rename from tests/components/coolix/test.esp8266.yaml rename to tests/components/coolix/test.esp8266-ard.yaml diff --git a/tests/components/copy/test.esp32.yaml b/tests/components/copy/test.esp32-ard.yaml similarity index 100% rename from tests/components/copy/test.esp32.yaml rename to tests/components/copy/test.esp32-ard.yaml diff --git a/tests/components/copy/test.esp32-c3.yaml b/tests/components/copy/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/copy/test.esp32-c3.yaml rename to tests/components/copy/test.esp32-c3-ard.yaml diff --git a/tests/components/copy/test.esp8266.yaml b/tests/components/copy/test.esp8266-ard.yaml similarity index 100% rename from tests/components/copy/test.esp8266.yaml rename to tests/components/copy/test.esp8266-ard.yaml diff --git a/tests/components/copy/test.rp2040.yaml b/tests/components/copy/test.rp2040-ard.yaml similarity index 100% rename from tests/components/copy/test.rp2040.yaml rename to tests/components/copy/test.rp2040-ard.yaml diff --git a/tests/components/cs5460a/test.esp32.yaml b/tests/components/cs5460a/test.esp32-ard.yaml similarity index 100% rename from tests/components/cs5460a/test.esp32.yaml rename to tests/components/cs5460a/test.esp32-ard.yaml diff --git a/tests/components/cs5460a/test.esp32-c3.yaml b/tests/components/cs5460a/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/cs5460a/test.esp32-c3.yaml rename to tests/components/cs5460a/test.esp32-c3-ard.yaml diff --git a/tests/components/cs5460a/test.esp8266.yaml b/tests/components/cs5460a/test.esp8266-ard.yaml similarity index 100% rename from tests/components/cs5460a/test.esp8266.yaml rename to tests/components/cs5460a/test.esp8266-ard.yaml diff --git a/tests/components/cs5460a/test.rp2040.yaml b/tests/components/cs5460a/test.rp2040-ard.yaml similarity index 100% rename from tests/components/cs5460a/test.rp2040.yaml rename to tests/components/cs5460a/test.rp2040-ard.yaml diff --git a/tests/components/cse7761/test.esp32.yaml b/tests/components/cse7761/test.esp32-ard.yaml similarity index 100% rename from tests/components/cse7761/test.esp32.yaml rename to tests/components/cse7761/test.esp32-ard.yaml diff --git a/tests/components/cse7761/test.esp32-c3.yaml b/tests/components/cse7761/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/cse7761/test.esp32-c3.yaml rename to tests/components/cse7761/test.esp32-c3-ard.yaml diff --git a/tests/components/cse7761/test.esp8266.yaml b/tests/components/cse7761/test.esp8266-ard.yaml similarity index 100% rename from tests/components/cse7761/test.esp8266.yaml rename to tests/components/cse7761/test.esp8266-ard.yaml diff --git a/tests/components/cse7761/test.rp2040.yaml b/tests/components/cse7761/test.rp2040-ard.yaml similarity index 100% rename from tests/components/cse7761/test.rp2040.yaml rename to tests/components/cse7761/test.rp2040-ard.yaml diff --git a/tests/components/cse7766/test.esp32.yaml b/tests/components/cse7766/test.esp32-ard.yaml similarity index 100% rename from tests/components/cse7766/test.esp32.yaml rename to tests/components/cse7766/test.esp32-ard.yaml diff --git a/tests/components/cse7766/test.esp32-c3.yaml b/tests/components/cse7766/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/cse7766/test.esp32-c3.yaml rename to tests/components/cse7766/test.esp32-c3-ard.yaml diff --git a/tests/components/cse7766/test.esp8266.yaml b/tests/components/cse7766/test.esp8266-ard.yaml similarity index 100% rename from tests/components/cse7766/test.esp8266.yaml rename to tests/components/cse7766/test.esp8266-ard.yaml diff --git a/tests/components/cse7766/test.rp2040.yaml b/tests/components/cse7766/test.rp2040-ard.yaml similarity index 100% rename from tests/components/cse7766/test.rp2040.yaml rename to tests/components/cse7766/test.rp2040-ard.yaml diff --git a/tests/components/cst226/test.esp32-c3.yaml b/tests/components/cst226/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/cst226/test.esp32-c3.yaml rename to tests/components/cst226/test.esp32-c3-ard.yaml diff --git a/tests/components/cst816/test.esp32.yaml b/tests/components/cst816/test.esp32-ard.yaml similarity index 100% rename from tests/components/cst816/test.esp32.yaml rename to tests/components/cst816/test.esp32-ard.yaml diff --git a/tests/components/ct_clamp/test.esp32.yaml b/tests/components/ct_clamp/test.esp32-ard.yaml similarity index 100% rename from tests/components/ct_clamp/test.esp32.yaml rename to tests/components/ct_clamp/test.esp32-ard.yaml diff --git a/tests/components/ct_clamp/test.esp32-c3.yaml b/tests/components/ct_clamp/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ct_clamp/test.esp32-c3.yaml rename to tests/components/ct_clamp/test.esp32-c3-ard.yaml diff --git a/tests/components/ct_clamp/test.esp8266.yaml b/tests/components/ct_clamp/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ct_clamp/test.esp8266.yaml rename to tests/components/ct_clamp/test.esp8266-ard.yaml diff --git a/tests/components/ct_clamp/test.rp2040.yaml b/tests/components/ct_clamp/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ct_clamp/test.rp2040.yaml rename to tests/components/ct_clamp/test.rp2040-ard.yaml diff --git a/tests/components/current_based/test.esp32.yaml b/tests/components/current_based/test.esp32-ard.yaml similarity index 100% rename from tests/components/current_based/test.esp32.yaml rename to tests/components/current_based/test.esp32-ard.yaml diff --git a/tests/components/current_based/test.esp32-c3.yaml b/tests/components/current_based/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/current_based/test.esp32-c3.yaml rename to tests/components/current_based/test.esp32-c3-ard.yaml diff --git a/tests/components/current_based/test.esp8266.yaml b/tests/components/current_based/test.esp8266-ard.yaml similarity index 100% rename from tests/components/current_based/test.esp8266.yaml rename to tests/components/current_based/test.esp8266-ard.yaml diff --git a/tests/components/current_based/test.rp2040.yaml b/tests/components/current_based/test.rp2040-ard.yaml similarity index 100% rename from tests/components/current_based/test.rp2040.yaml rename to tests/components/current_based/test.rp2040-ard.yaml diff --git a/tests/components/cwww/test.esp32.yaml b/tests/components/cwww/test.esp32-ard.yaml similarity index 100% rename from tests/components/cwww/test.esp32.yaml rename to tests/components/cwww/test.esp32-ard.yaml diff --git a/tests/components/cwww/test.esp32-c3.yaml b/tests/components/cwww/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/cwww/test.esp32-c3.yaml rename to tests/components/cwww/test.esp32-c3-ard.yaml diff --git a/tests/components/cwww/test.esp8266.yaml b/tests/components/cwww/test.esp8266-ard.yaml similarity index 100% rename from tests/components/cwww/test.esp8266.yaml rename to tests/components/cwww/test.esp8266-ard.yaml diff --git a/tests/components/cwww/test.rp2040.yaml b/tests/components/cwww/test.rp2040-ard.yaml similarity index 100% rename from tests/components/cwww/test.rp2040.yaml rename to tests/components/cwww/test.rp2040-ard.yaml diff --git a/tests/components/dac7678/test.esp32.yaml b/tests/components/dac7678/test.esp32-ard.yaml similarity index 100% rename from tests/components/dac7678/test.esp32.yaml rename to tests/components/dac7678/test.esp32-ard.yaml diff --git a/tests/components/dac7678/test.esp32-c3.yaml b/tests/components/dac7678/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/dac7678/test.esp32-c3.yaml rename to tests/components/dac7678/test.esp32-c3-ard.yaml diff --git a/tests/components/dac7678/test.esp8266.yaml b/tests/components/dac7678/test.esp8266-ard.yaml similarity index 100% rename from tests/components/dac7678/test.esp8266.yaml rename to tests/components/dac7678/test.esp8266-ard.yaml diff --git a/tests/components/dac7678/test.rp2040.yaml b/tests/components/dac7678/test.rp2040-ard.yaml similarity index 100% rename from tests/components/dac7678/test.rp2040.yaml rename to tests/components/dac7678/test.rp2040-ard.yaml diff --git a/tests/components/daikin/test.esp32.yaml b/tests/components/daikin/test.esp32-ard.yaml similarity index 100% rename from tests/components/daikin/test.esp32.yaml rename to tests/components/daikin/test.esp32-ard.yaml diff --git a/tests/components/daikin/test.esp8266.yaml b/tests/components/daikin/test.esp8266-ard.yaml similarity index 100% rename from tests/components/daikin/test.esp8266.yaml rename to tests/components/daikin/test.esp8266-ard.yaml diff --git a/tests/components/daikin_arc/test.esp32.yaml b/tests/components/daikin_arc/test.esp32-ard.yaml similarity index 100% rename from tests/components/daikin_arc/test.esp32.yaml rename to tests/components/daikin_arc/test.esp32-ard.yaml diff --git a/tests/components/daikin_arc/test.esp8266.yaml b/tests/components/daikin_arc/test.esp8266-ard.yaml similarity index 100% rename from tests/components/daikin_arc/test.esp8266.yaml rename to tests/components/daikin_arc/test.esp8266-ard.yaml diff --git a/tests/components/daikin_brc/test.esp32-c3.yaml b/tests/components/daikin_brc/test.esp32-ard.yaml similarity index 100% rename from tests/components/daikin_brc/test.esp32-c3.yaml rename to tests/components/daikin_brc/test.esp32-ard.yaml diff --git a/tests/components/daikin_brc/test.esp32.yaml b/tests/components/daikin_brc/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/daikin_brc/test.esp32.yaml rename to tests/components/daikin_brc/test.esp32-c3-ard.yaml diff --git a/tests/components/daikin_brc/test.esp8266.yaml b/tests/components/daikin_brc/test.esp8266-ard.yaml similarity index 100% rename from tests/components/daikin_brc/test.esp8266.yaml rename to tests/components/daikin_brc/test.esp8266-ard.yaml diff --git a/tests/components/dallas_temp/test.esp32-c3.yaml b/tests/components/dallas_temp/test.esp32-ard.yaml similarity index 100% rename from tests/components/dallas_temp/test.esp32-c3.yaml rename to tests/components/dallas_temp/test.esp32-ard.yaml diff --git a/tests/components/dallas_temp/test.esp32.yaml b/tests/components/dallas_temp/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/dallas_temp/test.esp32.yaml rename to tests/components/dallas_temp/test.esp32-c3-ard.yaml diff --git a/tests/components/dallas_temp/test.esp8266.yaml b/tests/components/dallas_temp/test.esp8266-ard.yaml similarity index 100% rename from tests/components/dallas_temp/test.esp8266.yaml rename to tests/components/dallas_temp/test.esp8266-ard.yaml diff --git a/tests/components/dallas_temp/test.rp2040.yaml b/tests/components/dallas_temp/test.rp2040-ard.yaml similarity index 100% rename from tests/components/dallas_temp/test.rp2040.yaml rename to tests/components/dallas_temp/test.rp2040-ard.yaml diff --git a/tests/components/daly_bms/test.esp32.yaml b/tests/components/daly_bms/test.esp32-ard.yaml similarity index 100% rename from tests/components/daly_bms/test.esp32.yaml rename to tests/components/daly_bms/test.esp32-ard.yaml diff --git a/tests/components/daly_bms/test.esp32-c3.yaml b/tests/components/daly_bms/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/daly_bms/test.esp32-c3.yaml rename to tests/components/daly_bms/test.esp32-c3-ard.yaml diff --git a/tests/components/daly_bms/test.esp8266.yaml b/tests/components/daly_bms/test.esp8266-ard.yaml similarity index 100% rename from tests/components/daly_bms/test.esp8266.yaml rename to tests/components/daly_bms/test.esp8266-ard.yaml diff --git a/tests/components/daly_bms/test.rp2040.yaml b/tests/components/daly_bms/test.rp2040-ard.yaml similarity index 100% rename from tests/components/daly_bms/test.rp2040.yaml rename to tests/components/daly_bms/test.rp2040-ard.yaml diff --git a/tests/components/debug/test.esp32-c3.yaml b/tests/components/debug/test.esp32-ard.yaml similarity index 100% rename from tests/components/debug/test.esp32-c3.yaml rename to tests/components/debug/test.esp32-ard.yaml diff --git a/tests/components/debug/test.esp32.yaml b/tests/components/debug/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/debug/test.esp32.yaml rename to tests/components/debug/test.esp32-c3-ard.yaml diff --git a/tests/components/debug/test.esp8266.yaml b/tests/components/debug/test.esp8266-ard.yaml similarity index 100% rename from tests/components/debug/test.esp8266.yaml rename to tests/components/debug/test.esp8266-ard.yaml diff --git a/tests/components/debug/test.rp2040.yaml b/tests/components/debug/test.rp2040-ard.yaml similarity index 100% rename from tests/components/debug/test.rp2040.yaml rename to tests/components/debug/test.rp2040-ard.yaml diff --git a/tests/components/deep_sleep/test.esp32-c3.yaml b/tests/components/deep_sleep/test.esp32-ard.yaml similarity index 100% rename from tests/components/deep_sleep/test.esp32-c3.yaml rename to tests/components/deep_sleep/test.esp32-ard.yaml diff --git a/tests/components/deep_sleep/test.esp32.yaml b/tests/components/deep_sleep/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/deep_sleep/test.esp32.yaml rename to tests/components/deep_sleep/test.esp32-c3-ard.yaml diff --git a/tests/components/deep_sleep/test.esp8266.yaml b/tests/components/deep_sleep/test.esp8266-ard.yaml similarity index 100% rename from tests/components/deep_sleep/test.esp8266.yaml rename to tests/components/deep_sleep/test.esp8266-ard.yaml diff --git a/tests/components/delonghi/test.esp32-c3.yaml b/tests/components/delonghi/test.esp32-ard.yaml similarity index 100% rename from tests/components/delonghi/test.esp32-c3.yaml rename to tests/components/delonghi/test.esp32-ard.yaml diff --git a/tests/components/delonghi/test.esp32.yaml b/tests/components/delonghi/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/delonghi/test.esp32.yaml rename to tests/components/delonghi/test.esp32-c3-ard.yaml diff --git a/tests/components/delonghi/test.esp8266.yaml b/tests/components/delonghi/test.esp8266-ard.yaml similarity index 100% rename from tests/components/delonghi/test.esp8266.yaml rename to tests/components/delonghi/test.esp8266-ard.yaml diff --git a/tests/components/dfplayer/test.esp32.yaml b/tests/components/dfplayer/test.esp32-ard.yaml similarity index 100% rename from tests/components/dfplayer/test.esp32.yaml rename to tests/components/dfplayer/test.esp32-ard.yaml diff --git a/tests/components/dfplayer/test.esp32-c3.yaml b/tests/components/dfplayer/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/dfplayer/test.esp32-c3.yaml rename to tests/components/dfplayer/test.esp32-c3-ard.yaml diff --git a/tests/components/dfplayer/test.esp8266.yaml b/tests/components/dfplayer/test.esp8266-ard.yaml similarity index 100% rename from tests/components/dfplayer/test.esp8266.yaml rename to tests/components/dfplayer/test.esp8266-ard.yaml diff --git a/tests/components/dfplayer/test.rp2040.yaml b/tests/components/dfplayer/test.rp2040-ard.yaml similarity index 100% rename from tests/components/dfplayer/test.rp2040.yaml rename to tests/components/dfplayer/test.rp2040-ard.yaml diff --git a/tests/components/dfrobot_sen0395/test.esp32.yaml b/tests/components/dfrobot_sen0395/test.esp32-ard.yaml similarity index 100% rename from tests/components/dfrobot_sen0395/test.esp32.yaml rename to tests/components/dfrobot_sen0395/test.esp32-ard.yaml diff --git a/tests/components/dfrobot_sen0395/test.esp32-c3.yaml b/tests/components/dfrobot_sen0395/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/dfrobot_sen0395/test.esp32-c3.yaml rename to tests/components/dfrobot_sen0395/test.esp32-c3-ard.yaml diff --git a/tests/components/dfrobot_sen0395/test.esp8266.yaml b/tests/components/dfrobot_sen0395/test.esp8266-ard.yaml similarity index 100% rename from tests/components/dfrobot_sen0395/test.esp8266.yaml rename to tests/components/dfrobot_sen0395/test.esp8266-ard.yaml diff --git a/tests/components/dfrobot_sen0395/test.rp2040.yaml b/tests/components/dfrobot_sen0395/test.rp2040-ard.yaml similarity index 100% rename from tests/components/dfrobot_sen0395/test.rp2040.yaml rename to tests/components/dfrobot_sen0395/test.rp2040-ard.yaml diff --git a/tests/components/dht/test.esp32-c3.yaml b/tests/components/dht/test.esp32-ard.yaml similarity index 100% rename from tests/components/dht/test.esp32-c3.yaml rename to tests/components/dht/test.esp32-ard.yaml diff --git a/tests/components/dht/test.esp32.yaml b/tests/components/dht/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/dht/test.esp32.yaml rename to tests/components/dht/test.esp32-c3-ard.yaml diff --git a/tests/components/dht/test.esp8266.yaml b/tests/components/dht/test.esp8266-ard.yaml similarity index 100% rename from tests/components/dht/test.esp8266.yaml rename to tests/components/dht/test.esp8266-ard.yaml diff --git a/tests/components/dht/test.rp2040.yaml b/tests/components/dht/test.rp2040-ard.yaml similarity index 100% rename from tests/components/dht/test.rp2040.yaml rename to tests/components/dht/test.rp2040-ard.yaml diff --git a/tests/components/dht12/test.esp32.yaml b/tests/components/dht12/test.esp32-ard.yaml similarity index 100% rename from tests/components/dht12/test.esp32.yaml rename to tests/components/dht12/test.esp32-ard.yaml diff --git a/tests/components/dht12/test.esp32-c3.yaml b/tests/components/dht12/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/dht12/test.esp32-c3.yaml rename to tests/components/dht12/test.esp32-c3-ard.yaml diff --git a/tests/components/dht12/test.esp8266.yaml b/tests/components/dht12/test.esp8266-ard.yaml similarity index 100% rename from tests/components/dht12/test.esp8266.yaml rename to tests/components/dht12/test.esp8266-ard.yaml diff --git a/tests/components/dht12/test.rp2040.yaml b/tests/components/dht12/test.rp2040-ard.yaml similarity index 100% rename from tests/components/dht12/test.rp2040.yaml rename to tests/components/dht12/test.rp2040-ard.yaml diff --git a/tests/components/display/test.esp32.yaml b/tests/components/display/test.esp32-ard.yaml similarity index 100% rename from tests/components/display/test.esp32.yaml rename to tests/components/display/test.esp32-ard.yaml diff --git a/tests/components/dps310/test.esp32.yaml b/tests/components/dps310/test.esp32-ard.yaml similarity index 100% rename from tests/components/dps310/test.esp32.yaml rename to tests/components/dps310/test.esp32-ard.yaml diff --git a/tests/components/dps310/test.esp32-c3.yaml b/tests/components/dps310/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/dps310/test.esp32-c3.yaml rename to tests/components/dps310/test.esp32-c3-ard.yaml diff --git a/tests/components/dps310/test.esp8266.yaml b/tests/components/dps310/test.esp8266-ard.yaml similarity index 100% rename from tests/components/dps310/test.esp8266.yaml rename to tests/components/dps310/test.esp8266-ard.yaml diff --git a/tests/components/dps310/test.rp2040.yaml b/tests/components/dps310/test.rp2040-ard.yaml similarity index 100% rename from tests/components/dps310/test.rp2040.yaml rename to tests/components/dps310/test.rp2040-ard.yaml diff --git a/tests/components/ds1307/test.esp32.yaml b/tests/components/ds1307/test.esp32-ard.yaml similarity index 100% rename from tests/components/ds1307/test.esp32.yaml rename to tests/components/ds1307/test.esp32-ard.yaml diff --git a/tests/components/ds1307/test.esp32-c3.yaml b/tests/components/ds1307/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ds1307/test.esp32-c3.yaml rename to tests/components/ds1307/test.esp32-c3-ard.yaml diff --git a/tests/components/ds1307/test.esp8266.yaml b/tests/components/ds1307/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ds1307/test.esp8266.yaml rename to tests/components/ds1307/test.esp8266-ard.yaml diff --git a/tests/components/ds1307/test.rp2040.yaml b/tests/components/ds1307/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ds1307/test.rp2040.yaml rename to tests/components/ds1307/test.rp2040-ard.yaml diff --git a/tests/components/dsmr/test.esp32.yaml b/tests/components/dsmr/test.esp32-ard.yaml similarity index 100% rename from tests/components/dsmr/test.esp32.yaml rename to tests/components/dsmr/test.esp32-ard.yaml diff --git a/tests/components/dsmr/test.esp32-c3.yaml b/tests/components/dsmr/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/dsmr/test.esp32-c3.yaml rename to tests/components/dsmr/test.esp32-c3-ard.yaml diff --git a/tests/components/dsmr/test.esp8266.yaml b/tests/components/dsmr/test.esp8266-ard.yaml similarity index 100% rename from tests/components/dsmr/test.esp8266.yaml rename to tests/components/dsmr/test.esp8266-ard.yaml diff --git a/tests/components/dsmr/test.rp2040.yaml b/tests/components/dsmr/test.rp2040-ard.yaml similarity index 100% rename from tests/components/dsmr/test.rp2040.yaml rename to tests/components/dsmr/test.rp2040-ard.yaml diff --git a/tests/components/duty_cycle/test.esp32-c3.yaml b/tests/components/duty_cycle/test.esp32-ard.yaml similarity index 100% rename from tests/components/duty_cycle/test.esp32-c3.yaml rename to tests/components/duty_cycle/test.esp32-ard.yaml diff --git a/tests/components/duty_cycle/test.esp32.yaml b/tests/components/duty_cycle/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/duty_cycle/test.esp32.yaml rename to tests/components/duty_cycle/test.esp32-c3-ard.yaml diff --git a/tests/components/duty_cycle/test.esp8266.yaml b/tests/components/duty_cycle/test.esp8266-ard.yaml similarity index 100% rename from tests/components/duty_cycle/test.esp8266.yaml rename to tests/components/duty_cycle/test.esp8266-ard.yaml diff --git a/tests/components/duty_cycle/test.rp2040.yaml b/tests/components/duty_cycle/test.rp2040-ard.yaml similarity index 100% rename from tests/components/duty_cycle/test.rp2040.yaml rename to tests/components/duty_cycle/test.rp2040-ard.yaml diff --git a/tests/components/duty_time/test.esp32-c3.yaml b/tests/components/duty_time/test.esp32-ard.yaml similarity index 100% rename from tests/components/duty_time/test.esp32-c3.yaml rename to tests/components/duty_time/test.esp32-ard.yaml diff --git a/tests/components/duty_time/test.esp32.yaml b/tests/components/duty_time/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/duty_time/test.esp32.yaml rename to tests/components/duty_time/test.esp32-c3-ard.yaml diff --git a/tests/components/duty_time/test.esp8266.yaml b/tests/components/duty_time/test.esp8266-ard.yaml similarity index 100% rename from tests/components/duty_time/test.esp8266.yaml rename to tests/components/duty_time/test.esp8266-ard.yaml diff --git a/tests/components/duty_time/test.rp2040.yaml b/tests/components/duty_time/test.rp2040-ard.yaml similarity index 100% rename from tests/components/duty_time/test.rp2040.yaml rename to tests/components/duty_time/test.rp2040-ard.yaml diff --git a/tests/components/e131/test.esp32-c3.yaml b/tests/components/e131/test.esp32-ard.yaml similarity index 100% rename from tests/components/e131/test.esp32-c3.yaml rename to tests/components/e131/test.esp32-ard.yaml diff --git a/tests/components/e131/test.esp32.yaml b/tests/components/e131/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/e131/test.esp32.yaml rename to tests/components/e131/test.esp32-c3-ard.yaml diff --git a/tests/components/e131/test.esp8266.yaml b/tests/components/e131/test.esp8266-ard.yaml similarity index 100% rename from tests/components/e131/test.esp8266.yaml rename to tests/components/e131/test.esp8266-ard.yaml diff --git a/tests/components/e131/test.rp2040.yaml b/tests/components/e131/test.rp2040-ard.yaml similarity index 100% rename from tests/components/e131/test.rp2040.yaml rename to tests/components/e131/test.rp2040-ard.yaml diff --git a/tests/components/ee895/test.esp32.yaml b/tests/components/ee895/test.esp32-ard.yaml similarity index 100% rename from tests/components/ee895/test.esp32.yaml rename to tests/components/ee895/test.esp32-ard.yaml diff --git a/tests/components/ee895/test.esp32-c3.yaml b/tests/components/ee895/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ee895/test.esp32-c3.yaml rename to tests/components/ee895/test.esp32-c3-ard.yaml diff --git a/tests/components/ee895/test.esp8266.yaml b/tests/components/ee895/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ee895/test.esp8266.yaml rename to tests/components/ee895/test.esp8266-ard.yaml diff --git a/tests/components/ee895/test.rp2040.yaml b/tests/components/ee895/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ee895/test.rp2040.yaml rename to tests/components/ee895/test.rp2040-ard.yaml diff --git a/tests/components/ektf2232/test.esp32.yaml b/tests/components/ektf2232/test.esp32-ard.yaml similarity index 100% rename from tests/components/ektf2232/test.esp32.yaml rename to tests/components/ektf2232/test.esp32-ard.yaml diff --git a/tests/components/ektf2232/test.esp32-c3.yaml b/tests/components/ektf2232/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ektf2232/test.esp32-c3.yaml rename to tests/components/ektf2232/test.esp32-c3-ard.yaml diff --git a/tests/components/ektf2232/test.esp8266.yaml b/tests/components/ektf2232/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ektf2232/test.esp8266.yaml rename to tests/components/ektf2232/test.esp8266-ard.yaml diff --git a/tests/components/ektf2232/test.rp2040.yaml b/tests/components/ektf2232/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ektf2232/test.rp2040.yaml rename to tests/components/ektf2232/test.rp2040-ard.yaml diff --git a/tests/components/emc2101/test.esp32.yaml b/tests/components/emc2101/test.esp32-ard.yaml similarity index 100% rename from tests/components/emc2101/test.esp32.yaml rename to tests/components/emc2101/test.esp32-ard.yaml diff --git a/tests/components/emc2101/test.esp32-c3.yaml b/tests/components/emc2101/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/emc2101/test.esp32-c3.yaml rename to tests/components/emc2101/test.esp32-c3-ard.yaml diff --git a/tests/components/emc2101/test.esp8266.yaml b/tests/components/emc2101/test.esp8266-ard.yaml similarity index 100% rename from tests/components/emc2101/test.esp8266.yaml rename to tests/components/emc2101/test.esp8266-ard.yaml diff --git a/tests/components/emc2101/test.rp2040.yaml b/tests/components/emc2101/test.rp2040-ard.yaml similarity index 100% rename from tests/components/emc2101/test.rp2040.yaml rename to tests/components/emc2101/test.rp2040-ard.yaml diff --git a/tests/components/emmeti/test.esp32.yaml b/tests/components/emmeti/test.esp32-ard.yaml similarity index 100% rename from tests/components/emmeti/test.esp32.yaml rename to tests/components/emmeti/test.esp32-ard.yaml diff --git a/tests/components/emmeti/test.esp8266.yaml b/tests/components/emmeti/test.esp8266-ard.yaml similarity index 100% rename from tests/components/emmeti/test.esp8266.yaml rename to tests/components/emmeti/test.esp8266-ard.yaml diff --git a/tests/components/endstop/test.esp32-c3.yaml b/tests/components/endstop/test.esp32-ard.yaml similarity index 100% rename from tests/components/endstop/test.esp32-c3.yaml rename to tests/components/endstop/test.esp32-ard.yaml diff --git a/tests/components/endstop/test.esp32.yaml b/tests/components/endstop/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/endstop/test.esp32.yaml rename to tests/components/endstop/test.esp32-c3-ard.yaml diff --git a/tests/components/endstop/test.esp8266.yaml b/tests/components/endstop/test.esp8266-ard.yaml similarity index 100% rename from tests/components/endstop/test.esp8266.yaml rename to tests/components/endstop/test.esp8266-ard.yaml diff --git a/tests/components/endstop/test.rp2040.yaml b/tests/components/endstop/test.rp2040-ard.yaml similarity index 100% rename from tests/components/endstop/test.rp2040.yaml rename to tests/components/endstop/test.rp2040-ard.yaml diff --git a/tests/components/ens160_i2c/test.esp32.yaml b/tests/components/ens160_i2c/test.esp32-ard.yaml similarity index 100% rename from tests/components/ens160_i2c/test.esp32.yaml rename to tests/components/ens160_i2c/test.esp32-ard.yaml diff --git a/tests/components/ens160_i2c/test.esp32-c3.yaml b/tests/components/ens160_i2c/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ens160_i2c/test.esp32-c3.yaml rename to tests/components/ens160_i2c/test.esp32-c3-ard.yaml diff --git a/tests/components/ens160_i2c/test.esp8266.yaml b/tests/components/ens160_i2c/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ens160_i2c/test.esp8266.yaml rename to tests/components/ens160_i2c/test.esp8266-ard.yaml diff --git a/tests/components/ens160_i2c/test.rp2040.yaml b/tests/components/ens160_i2c/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ens160_i2c/test.rp2040.yaml rename to tests/components/ens160_i2c/test.rp2040-ard.yaml diff --git a/tests/components/ens160_spi/test.esp32.yaml b/tests/components/ens160_spi/test.esp32-ard.yaml similarity index 100% rename from tests/components/ens160_spi/test.esp32.yaml rename to tests/components/ens160_spi/test.esp32-ard.yaml diff --git a/tests/components/ens160_spi/test.esp32-c3.yaml b/tests/components/ens160_spi/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ens160_spi/test.esp32-c3.yaml rename to tests/components/ens160_spi/test.esp32-c3-ard.yaml diff --git a/tests/components/ens160_spi/test.esp8266.yaml b/tests/components/ens160_spi/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ens160_spi/test.esp8266.yaml rename to tests/components/ens160_spi/test.esp8266-ard.yaml diff --git a/tests/components/ens160_spi/test.rp2040.yaml b/tests/components/ens160_spi/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ens160_spi/test.rp2040.yaml rename to tests/components/ens160_spi/test.rp2040-ard.yaml diff --git a/tests/components/ens210/test.esp32.yaml b/tests/components/ens210/test.esp32-ard.yaml similarity index 100% rename from tests/components/ens210/test.esp32.yaml rename to tests/components/ens210/test.esp32-ard.yaml diff --git a/tests/components/ens210/test.esp32-c3.yaml b/tests/components/ens210/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ens210/test.esp32-c3.yaml rename to tests/components/ens210/test.esp32-c3-ard.yaml diff --git a/tests/components/ens210/test.esp8266.yaml b/tests/components/ens210/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ens210/test.esp8266.yaml rename to tests/components/ens210/test.esp8266-ard.yaml diff --git a/tests/components/ens210/test.rp2040.yaml b/tests/components/ens210/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ens210/test.rp2040.yaml rename to tests/components/ens210/test.rp2040-ard.yaml diff --git a/tests/components/esp32_ble/test.esp32-c3.yaml b/tests/components/esp32_ble/test.esp32-ard.yaml similarity index 100% rename from tests/components/esp32_ble/test.esp32-c3.yaml rename to tests/components/esp32_ble/test.esp32-ard.yaml diff --git a/tests/components/esp32_ble/test.esp32.yaml b/tests/components/esp32_ble/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/esp32_ble/test.esp32.yaml rename to tests/components/esp32_ble/test.esp32-c3-ard.yaml diff --git a/tests/components/esp32_ble_beacon/test.esp32-c3.yaml b/tests/components/esp32_ble_beacon/test.esp32-ard.yaml similarity index 100% rename from tests/components/esp32_ble_beacon/test.esp32-c3.yaml rename to tests/components/esp32_ble_beacon/test.esp32-ard.yaml diff --git a/tests/components/esp32_ble_beacon/test.esp32.yaml b/tests/components/esp32_ble_beacon/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/esp32_ble_beacon/test.esp32.yaml rename to tests/components/esp32_ble_beacon/test.esp32-c3-ard.yaml diff --git a/tests/components/esp32_ble_client/test.esp32-c3.yaml b/tests/components/esp32_ble_client/test.esp32-ard.yaml similarity index 100% rename from tests/components/esp32_ble_client/test.esp32-c3.yaml rename to tests/components/esp32_ble_client/test.esp32-ard.yaml diff --git a/tests/components/esp32_ble_client/test.esp32.yaml b/tests/components/esp32_ble_client/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/esp32_ble_client/test.esp32.yaml rename to tests/components/esp32_ble_client/test.esp32-c3-ard.yaml diff --git a/tests/components/esp32_ble_server/test.esp32-c3.yaml b/tests/components/esp32_ble_server/test.esp32-ard.yaml similarity index 100% rename from tests/components/esp32_ble_server/test.esp32-c3.yaml rename to tests/components/esp32_ble_server/test.esp32-ard.yaml diff --git a/tests/components/esp32_ble_server/test.esp32.yaml b/tests/components/esp32_ble_server/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/esp32_ble_server/test.esp32.yaml rename to tests/components/esp32_ble_server/test.esp32-c3-ard.yaml diff --git a/tests/components/esp32_ble_tracker/test.esp32-c3.yaml b/tests/components/esp32_ble_tracker/test.esp32-ard.yaml similarity index 100% rename from tests/components/esp32_ble_tracker/test.esp32-c3.yaml rename to tests/components/esp32_ble_tracker/test.esp32-ard.yaml diff --git a/tests/components/esp32_ble_tracker/test.esp32.yaml b/tests/components/esp32_ble_tracker/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/esp32_ble_tracker/test.esp32.yaml rename to tests/components/esp32_ble_tracker/test.esp32-c3-ard.yaml diff --git a/tests/components/esp32_camera/test.esp32.yaml b/tests/components/esp32_camera/test.esp32-ard.yaml similarity index 100% rename from tests/components/esp32_camera/test.esp32.yaml rename to tests/components/esp32_camera/test.esp32-ard.yaml diff --git a/tests/components/esp32_camera_web_server/test.esp32.yaml b/tests/components/esp32_camera_web_server/test.esp32-ard.yaml similarity index 100% rename from tests/components/esp32_camera_web_server/test.esp32.yaml rename to tests/components/esp32_camera_web_server/test.esp32-ard.yaml diff --git a/tests/components/esp32_can/test.esp32.yaml b/tests/components/esp32_can/test.esp32-ard.yaml similarity index 100% rename from tests/components/esp32_can/test.esp32.yaml rename to tests/components/esp32_can/test.esp32-ard.yaml diff --git a/tests/components/esp32_can/test.esp32-c3.yaml b/tests/components/esp32_can/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/esp32_can/test.esp32-c3.yaml rename to tests/components/esp32_can/test.esp32-c3-ard.yaml diff --git a/tests/components/esp32_dac/test.esp32.yaml b/tests/components/esp32_dac/test.esp32-ard.yaml similarity index 100% rename from tests/components/esp32_dac/test.esp32.yaml rename to tests/components/esp32_dac/test.esp32-ard.yaml diff --git a/tests/components/esp32_hall/test.esp32.yaml b/tests/components/esp32_hall/test.esp32-ard.yaml similarity index 100% rename from tests/components/esp32_hall/test.esp32.yaml rename to tests/components/esp32_hall/test.esp32-ard.yaml diff --git a/tests/components/esp32_improv/test.esp32-c3.yaml b/tests/components/esp32_improv/test.esp32-ard.yaml similarity index 100% rename from tests/components/esp32_improv/test.esp32-c3.yaml rename to tests/components/esp32_improv/test.esp32-ard.yaml diff --git a/tests/components/esp32_improv/test.esp32.yaml b/tests/components/esp32_improv/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/esp32_improv/test.esp32.yaml rename to tests/components/esp32_improv/test.esp32-c3-ard.yaml diff --git a/tests/components/esp32_rmt_led_strip/test.esp32.yaml b/tests/components/esp32_rmt_led_strip/test.esp32-ard.yaml similarity index 100% rename from tests/components/esp32_rmt_led_strip/test.esp32.yaml rename to tests/components/esp32_rmt_led_strip/test.esp32-ard.yaml diff --git a/tests/components/esp32_rmt_led_strip/test.esp32-c3.yaml b/tests/components/esp32_rmt_led_strip/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/esp32_rmt_led_strip/test.esp32-c3.yaml rename to tests/components/esp32_rmt_led_strip/test.esp32-c3-ard.yaml diff --git a/tests/components/esp32_touch/test.esp32.yaml b/tests/components/esp32_touch/test.esp32-ard.yaml similarity index 100% rename from tests/components/esp32_touch/test.esp32.yaml rename to tests/components/esp32_touch/test.esp32-ard.yaml diff --git a/tests/components/esp8266_pwm/test.esp8266.yaml b/tests/components/esp8266_pwm/test.esp8266-ard.yaml similarity index 100% rename from tests/components/esp8266_pwm/test.esp8266.yaml rename to tests/components/esp8266_pwm/test.esp8266-ard.yaml diff --git a/tests/components/ethernet/test-dp83848.esp32.yaml b/tests/components/ethernet/test-dp83848.esp32-ard.yaml similarity index 100% rename from tests/components/ethernet/test-dp83848.esp32.yaml rename to tests/components/ethernet/test-dp83848.esp32-ard.yaml diff --git a/tests/components/ethernet/test-ip101.esp32.yaml b/tests/components/ethernet/test-ip101.esp32-ard.yaml similarity index 100% rename from tests/components/ethernet/test-ip101.esp32.yaml rename to tests/components/ethernet/test-ip101.esp32-ard.yaml diff --git a/tests/components/ethernet/test-jl1101.esp32.yaml b/tests/components/ethernet/test-jl1101.esp32-ard.yaml similarity index 100% rename from tests/components/ethernet/test-jl1101.esp32.yaml rename to tests/components/ethernet/test-jl1101.esp32-ard.yaml diff --git a/tests/components/ethernet/test-ksz8081.esp32.yaml b/tests/components/ethernet/test-ksz8081.esp32-ard.yaml similarity index 100% rename from tests/components/ethernet/test-ksz8081.esp32.yaml rename to tests/components/ethernet/test-ksz8081.esp32-ard.yaml diff --git a/tests/components/ethernet/test-ksz8081rna.esp32.yaml b/tests/components/ethernet/test-ksz8081rna.esp32-ard.yaml similarity index 100% rename from tests/components/ethernet/test-ksz8081rna.esp32.yaml rename to tests/components/ethernet/test-ksz8081rna.esp32-ard.yaml diff --git a/tests/components/ethernet/test-lan8720.esp32.yaml b/tests/components/ethernet/test-lan8720.esp32-ard.yaml similarity index 100% rename from tests/components/ethernet/test-lan8720.esp32.yaml rename to tests/components/ethernet/test-lan8720.esp32-ard.yaml diff --git a/tests/components/ethernet/test-rtl8201.esp32.yaml b/tests/components/ethernet/test-rtl8201.esp32-ard.yaml similarity index 100% rename from tests/components/ethernet/test-rtl8201.esp32.yaml rename to tests/components/ethernet/test-rtl8201.esp32-ard.yaml diff --git a/tests/components/ethernet/test-w5500.esp32.yaml b/tests/components/ethernet/test-w5500.esp32-ard.yaml similarity index 100% rename from tests/components/ethernet/test-w5500.esp32.yaml rename to tests/components/ethernet/test-w5500.esp32-ard.yaml diff --git a/tests/components/ethernet_info/test.esp32.yaml b/tests/components/ethernet_info/test.esp32-ard.yaml similarity index 100% rename from tests/components/ethernet_info/test.esp32.yaml rename to tests/components/ethernet_info/test.esp32-ard.yaml diff --git a/tests/components/event/test.esp32-c3.yaml b/tests/components/event/test.esp32-ard.yaml similarity index 100% rename from tests/components/event/test.esp32-c3.yaml rename to tests/components/event/test.esp32-ard.yaml diff --git a/tests/components/event/test.esp32.yaml b/tests/components/event/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/event/test.esp32.yaml rename to tests/components/event/test.esp32-c3-ard.yaml diff --git a/tests/components/event/test.esp8266.yaml b/tests/components/event/test.esp8266-ard.yaml similarity index 100% rename from tests/components/event/test.esp8266.yaml rename to tests/components/event/test.esp8266-ard.yaml diff --git a/tests/components/event/test.rp2040.yaml b/tests/components/event/test.rp2040-ard.yaml similarity index 100% rename from tests/components/event/test.rp2040.yaml rename to tests/components/event/test.rp2040-ard.yaml diff --git a/tests/components/exposure_notifications/test.esp32-c3.yaml b/tests/components/exposure_notifications/test.esp32-ard.yaml similarity index 100% rename from tests/components/exposure_notifications/test.esp32-c3.yaml rename to tests/components/exposure_notifications/test.esp32-ard.yaml diff --git a/tests/components/exposure_notifications/test.esp32.yaml b/tests/components/exposure_notifications/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/exposure_notifications/test.esp32.yaml rename to tests/components/exposure_notifications/test.esp32-c3-ard.yaml diff --git a/tests/components/external_components/test.esp32-c3.yaml b/tests/components/external_components/test.esp32-ard.yaml similarity index 100% rename from tests/components/external_components/test.esp32-c3.yaml rename to tests/components/external_components/test.esp32-ard.yaml diff --git a/tests/components/external_components/test.esp32.yaml b/tests/components/external_components/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/external_components/test.esp32.yaml rename to tests/components/external_components/test.esp32-c3-ard.yaml diff --git a/tests/components/external_components/test.esp8266.yaml b/tests/components/external_components/test.esp8266-ard.yaml similarity index 100% rename from tests/components/external_components/test.esp8266.yaml rename to tests/components/external_components/test.esp8266-ard.yaml diff --git a/tests/components/external_components/test.rp2040.yaml b/tests/components/external_components/test.rp2040-ard.yaml similarity index 100% rename from tests/components/external_components/test.rp2040.yaml rename to tests/components/external_components/test.rp2040-ard.yaml diff --git a/tests/components/ezo/test.esp32.yaml b/tests/components/ezo/test.esp32-ard.yaml similarity index 100% rename from tests/components/ezo/test.esp32.yaml rename to tests/components/ezo/test.esp32-ard.yaml diff --git a/tests/components/ezo/test.esp32-c3.yaml b/tests/components/ezo/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ezo/test.esp32-c3.yaml rename to tests/components/ezo/test.esp32-c3-ard.yaml diff --git a/tests/components/ezo/test.esp8266.yaml b/tests/components/ezo/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ezo/test.esp8266.yaml rename to tests/components/ezo/test.esp8266-ard.yaml diff --git a/tests/components/ezo/test.rp2040.yaml b/tests/components/ezo/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ezo/test.rp2040.yaml rename to tests/components/ezo/test.rp2040-ard.yaml diff --git a/tests/components/ezo_pmp/test.esp32.yaml b/tests/components/ezo_pmp/test.esp32-ard.yaml similarity index 100% rename from tests/components/ezo_pmp/test.esp32.yaml rename to tests/components/ezo_pmp/test.esp32-ard.yaml diff --git a/tests/components/ezo_pmp/test.esp32-c3.yaml b/tests/components/ezo_pmp/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ezo_pmp/test.esp32-c3.yaml rename to tests/components/ezo_pmp/test.esp32-c3-ard.yaml diff --git a/tests/components/ezo_pmp/test.esp8266.yaml b/tests/components/ezo_pmp/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ezo_pmp/test.esp8266.yaml rename to tests/components/ezo_pmp/test.esp8266-ard.yaml diff --git a/tests/components/ezo_pmp/test.rp2040.yaml b/tests/components/ezo_pmp/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ezo_pmp/test.rp2040.yaml rename to tests/components/ezo_pmp/test.rp2040-ard.yaml diff --git a/tests/components/factory_reset/test.esp32-c3.yaml b/tests/components/factory_reset/test.esp32-ard.yaml similarity index 100% rename from tests/components/factory_reset/test.esp32-c3.yaml rename to tests/components/factory_reset/test.esp32-ard.yaml diff --git a/tests/components/factory_reset/test.esp32.yaml b/tests/components/factory_reset/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/factory_reset/test.esp32.yaml rename to tests/components/factory_reset/test.esp32-c3-ard.yaml diff --git a/tests/components/factory_reset/test.esp8266.yaml b/tests/components/factory_reset/test.esp8266-ard.yaml similarity index 100% rename from tests/components/factory_reset/test.esp8266.yaml rename to tests/components/factory_reset/test.esp8266-ard.yaml diff --git a/tests/components/factory_reset/test.rp2040.yaml b/tests/components/factory_reset/test.rp2040-ard.yaml similarity index 100% rename from tests/components/factory_reset/test.rp2040.yaml rename to tests/components/factory_reset/test.rp2040-ard.yaml diff --git a/tests/components/fastled_clockless/test.esp32.yaml b/tests/components/fastled_clockless/test.esp32-ard.yaml similarity index 100% rename from tests/components/fastled_clockless/test.esp32.yaml rename to tests/components/fastled_clockless/test.esp32-ard.yaml diff --git a/tests/components/fastled_spi/test.esp32.yaml b/tests/components/fastled_spi/test.esp32-ard.yaml similarity index 100% rename from tests/components/fastled_spi/test.esp32.yaml rename to tests/components/fastled_spi/test.esp32-ard.yaml diff --git a/tests/components/feedback/test.esp32-c3.yaml b/tests/components/feedback/test.esp32-ard.yaml similarity index 100% rename from tests/components/feedback/test.esp32-c3.yaml rename to tests/components/feedback/test.esp32-ard.yaml diff --git a/tests/components/feedback/test.esp32.yaml b/tests/components/feedback/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/feedback/test.esp32.yaml rename to tests/components/feedback/test.esp32-c3-ard.yaml diff --git a/tests/components/feedback/test.esp8266.yaml b/tests/components/feedback/test.esp8266-ard.yaml similarity index 100% rename from tests/components/feedback/test.esp8266.yaml rename to tests/components/feedback/test.esp8266-ard.yaml diff --git a/tests/components/feedback/test.rp2040.yaml b/tests/components/feedback/test.rp2040-ard.yaml similarity index 100% rename from tests/components/feedback/test.rp2040.yaml rename to tests/components/feedback/test.rp2040-ard.yaml diff --git a/tests/components/fingerprint_grow/test.esp32.yaml b/tests/components/fingerprint_grow/test.esp32-ard.yaml similarity index 100% rename from tests/components/fingerprint_grow/test.esp32.yaml rename to tests/components/fingerprint_grow/test.esp32-ard.yaml diff --git a/tests/components/fingerprint_grow/test.esp32-c3.yaml b/tests/components/fingerprint_grow/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/fingerprint_grow/test.esp32-c3.yaml rename to tests/components/fingerprint_grow/test.esp32-c3-ard.yaml diff --git a/tests/components/fingerprint_grow/test.esp8266.yaml b/tests/components/fingerprint_grow/test.esp8266-ard.yaml similarity index 100% rename from tests/components/fingerprint_grow/test.esp8266.yaml rename to tests/components/fingerprint_grow/test.esp8266-ard.yaml diff --git a/tests/components/fingerprint_grow/test.rp2040.yaml b/tests/components/fingerprint_grow/test.rp2040-ard.yaml similarity index 100% rename from tests/components/fingerprint_grow/test.rp2040.yaml rename to tests/components/fingerprint_grow/test.rp2040-ard.yaml diff --git a/tests/components/font/test.esp32.yaml b/tests/components/font/test.esp32-ard.yaml similarity index 100% rename from tests/components/font/test.esp32.yaml rename to tests/components/font/test.esp32-ard.yaml diff --git a/tests/components/font/test.esp32-c3.yaml b/tests/components/font/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/font/test.esp32-c3.yaml rename to tests/components/font/test.esp32-c3-ard.yaml diff --git a/tests/components/font/test.esp8266.yaml b/tests/components/font/test.esp8266-ard.yaml similarity index 100% rename from tests/components/font/test.esp8266.yaml rename to tests/components/font/test.esp8266-ard.yaml diff --git a/tests/components/font/test.rp2040.yaml b/tests/components/font/test.rp2040-ard.yaml similarity index 100% rename from tests/components/font/test.rp2040.yaml rename to tests/components/font/test.rp2040-ard.yaml diff --git a/tests/components/fs3000/test.esp32.yaml b/tests/components/fs3000/test.esp32-ard.yaml similarity index 100% rename from tests/components/fs3000/test.esp32.yaml rename to tests/components/fs3000/test.esp32-ard.yaml diff --git a/tests/components/fs3000/test.esp32-c3.yaml b/tests/components/fs3000/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/fs3000/test.esp32-c3.yaml rename to tests/components/fs3000/test.esp32-c3-ard.yaml diff --git a/tests/components/fs3000/test.esp8266.yaml b/tests/components/fs3000/test.esp8266-ard.yaml similarity index 100% rename from tests/components/fs3000/test.esp8266.yaml rename to tests/components/fs3000/test.esp8266-ard.yaml diff --git a/tests/components/fs3000/test.rp2040.yaml b/tests/components/fs3000/test.rp2040-ard.yaml similarity index 100% rename from tests/components/fs3000/test.rp2040.yaml rename to tests/components/fs3000/test.rp2040-ard.yaml diff --git a/tests/components/ft5x06/test.esp32.yaml b/tests/components/ft5x06/test.esp32-ard.yaml similarity index 100% rename from tests/components/ft5x06/test.esp32.yaml rename to tests/components/ft5x06/test.esp32-ard.yaml diff --git a/tests/components/ft5x06/test.esp32-c3.yaml b/tests/components/ft5x06/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ft5x06/test.esp32-c3.yaml rename to tests/components/ft5x06/test.esp32-c3-ard.yaml diff --git a/tests/components/ft5x06/test.esp8266.yaml b/tests/components/ft5x06/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ft5x06/test.esp8266.yaml rename to tests/components/ft5x06/test.esp8266-ard.yaml diff --git a/tests/components/ft5x06/test.rp2040.yaml b/tests/components/ft5x06/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ft5x06/test.rp2040.yaml rename to tests/components/ft5x06/test.rp2040-ard.yaml diff --git a/tests/components/ft63x6/test.esp32.yaml b/tests/components/ft63x6/test.esp32-ard.yaml similarity index 100% rename from tests/components/ft63x6/test.esp32.yaml rename to tests/components/ft63x6/test.esp32-ard.yaml diff --git a/tests/components/ft63x6/test.esp32-c3.yaml b/tests/components/ft63x6/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ft63x6/test.esp32-c3.yaml rename to tests/components/ft63x6/test.esp32-c3-ard.yaml diff --git a/tests/components/ft63x6/test.esp8266.yaml b/tests/components/ft63x6/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ft63x6/test.esp8266.yaml rename to tests/components/ft63x6/test.esp8266-ard.yaml diff --git a/tests/components/ft63x6/test.rp2040.yaml b/tests/components/ft63x6/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ft63x6/test.rp2040.yaml rename to tests/components/ft63x6/test.rp2040-ard.yaml diff --git a/tests/components/fujitsu_general/test.esp32-c3.yaml b/tests/components/fujitsu_general/test.esp32-ard.yaml similarity index 100% rename from tests/components/fujitsu_general/test.esp32-c3.yaml rename to tests/components/fujitsu_general/test.esp32-ard.yaml diff --git a/tests/components/fujitsu_general/test.esp32.yaml b/tests/components/fujitsu_general/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/fujitsu_general/test.esp32.yaml rename to tests/components/fujitsu_general/test.esp32-c3-ard.yaml diff --git a/tests/components/fujitsu_general/test.esp8266.yaml b/tests/components/fujitsu_general/test.esp8266-ard.yaml similarity index 100% rename from tests/components/fujitsu_general/test.esp8266.yaml rename to tests/components/fujitsu_general/test.esp8266-ard.yaml diff --git a/tests/components/gcja5/test.esp32.yaml b/tests/components/gcja5/test.esp32-ard.yaml similarity index 100% rename from tests/components/gcja5/test.esp32.yaml rename to tests/components/gcja5/test.esp32-ard.yaml diff --git a/tests/components/gcja5/test.esp32-c3.yaml b/tests/components/gcja5/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/gcja5/test.esp32-c3.yaml rename to tests/components/gcja5/test.esp32-c3-ard.yaml diff --git a/tests/components/gcja5/test.esp8266.yaml b/tests/components/gcja5/test.esp8266-ard.yaml similarity index 100% rename from tests/components/gcja5/test.esp8266.yaml rename to tests/components/gcja5/test.esp8266-ard.yaml diff --git a/tests/components/gcja5/test.rp2040.yaml b/tests/components/gcja5/test.rp2040-ard.yaml similarity index 100% rename from tests/components/gcja5/test.rp2040.yaml rename to tests/components/gcja5/test.rp2040-ard.yaml diff --git a/tests/components/gdk101/test.esp32.yaml b/tests/components/gdk101/test.esp32-ard.yaml similarity index 100% rename from tests/components/gdk101/test.esp32.yaml rename to tests/components/gdk101/test.esp32-ard.yaml diff --git a/tests/components/gdk101/test.esp8266.yaml b/tests/components/gdk101/test.esp8266-ard.yaml similarity index 100% rename from tests/components/gdk101/test.esp8266.yaml rename to tests/components/gdk101/test.esp8266-ard.yaml diff --git a/tests/components/gdk101/test.rp2040.yaml b/tests/components/gdk101/test.rp2040-ard.yaml similarity index 100% rename from tests/components/gdk101/test.rp2040.yaml rename to tests/components/gdk101/test.rp2040-ard.yaml diff --git a/tests/components/globals/test.esp32-c3.yaml b/tests/components/globals/test.esp32-ard.yaml similarity index 100% rename from tests/components/globals/test.esp32-c3.yaml rename to tests/components/globals/test.esp32-ard.yaml diff --git a/tests/components/globals/test.esp32.yaml b/tests/components/globals/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/globals/test.esp32.yaml rename to tests/components/globals/test.esp32-c3-ard.yaml diff --git a/tests/components/globals/test.esp8266.yaml b/tests/components/globals/test.esp8266-ard.yaml similarity index 100% rename from tests/components/globals/test.esp8266.yaml rename to tests/components/globals/test.esp8266-ard.yaml diff --git a/tests/components/globals/test.rp2040.yaml b/tests/components/globals/test.rp2040-ard.yaml similarity index 100% rename from tests/components/globals/test.rp2040.yaml rename to tests/components/globals/test.rp2040-ard.yaml diff --git a/tests/components/gp8403/test.esp32.yaml b/tests/components/gp8403/test.esp32-ard.yaml similarity index 100% rename from tests/components/gp8403/test.esp32.yaml rename to tests/components/gp8403/test.esp32-ard.yaml diff --git a/tests/components/gp8403/test.esp32-c3.yaml b/tests/components/gp8403/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/gp8403/test.esp32-c3.yaml rename to tests/components/gp8403/test.esp32-c3-ard.yaml diff --git a/tests/components/gp8403/test.esp8266.yaml b/tests/components/gp8403/test.esp8266-ard.yaml similarity index 100% rename from tests/components/gp8403/test.esp8266.yaml rename to tests/components/gp8403/test.esp8266-ard.yaml diff --git a/tests/components/gp8403/test.rp2040.yaml b/tests/components/gp8403/test.rp2040-ard.yaml similarity index 100% rename from tests/components/gp8403/test.rp2040.yaml rename to tests/components/gp8403/test.rp2040-ard.yaml diff --git a/tests/components/gpio/test.esp32.yaml b/tests/components/gpio/test.esp32-ard.yaml similarity index 100% rename from tests/components/gpio/test.esp32.yaml rename to tests/components/gpio/test.esp32-ard.yaml diff --git a/tests/components/gpio/test.esp32-c3.yaml b/tests/components/gpio/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/gpio/test.esp32-c3.yaml rename to tests/components/gpio/test.esp32-c3-ard.yaml diff --git a/tests/components/gpio/test.esp8266.yaml b/tests/components/gpio/test.esp8266-ard.yaml similarity index 100% rename from tests/components/gpio/test.esp8266.yaml rename to tests/components/gpio/test.esp8266-ard.yaml diff --git a/tests/components/gpio/test.rp2040.yaml b/tests/components/gpio/test.rp2040-ard.yaml similarity index 100% rename from tests/components/gpio/test.rp2040.yaml rename to tests/components/gpio/test.rp2040-ard.yaml diff --git a/tests/components/gps/test.esp32.yaml b/tests/components/gps/test.esp32-ard.yaml similarity index 100% rename from tests/components/gps/test.esp32.yaml rename to tests/components/gps/test.esp32-ard.yaml diff --git a/tests/components/gps/test.esp32-c3.yaml b/tests/components/gps/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/gps/test.esp32-c3.yaml rename to tests/components/gps/test.esp32-c3-ard.yaml diff --git a/tests/components/gps/test.esp8266.yaml b/tests/components/gps/test.esp8266-ard.yaml similarity index 100% rename from tests/components/gps/test.esp8266.yaml rename to tests/components/gps/test.esp8266-ard.yaml diff --git a/tests/components/gps/test.rp2040.yaml b/tests/components/gps/test.rp2040-ard.yaml similarity index 100% rename from tests/components/gps/test.rp2040.yaml rename to tests/components/gps/test.rp2040-ard.yaml diff --git a/tests/components/graph/test.esp32.yaml b/tests/components/graph/test.esp32-ard.yaml similarity index 100% rename from tests/components/graph/test.esp32.yaml rename to tests/components/graph/test.esp32-ard.yaml diff --git a/tests/components/graph/test.esp32-c3.yaml b/tests/components/graph/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/graph/test.esp32-c3.yaml rename to tests/components/graph/test.esp32-c3-ard.yaml diff --git a/tests/components/graph/test.esp8266.yaml b/tests/components/graph/test.esp8266-ard.yaml similarity index 100% rename from tests/components/graph/test.esp8266.yaml rename to tests/components/graph/test.esp8266-ard.yaml diff --git a/tests/components/graph/test.rp2040.yaml b/tests/components/graph/test.rp2040-ard.yaml similarity index 100% rename from tests/components/graph/test.rp2040.yaml rename to tests/components/graph/test.rp2040-ard.yaml diff --git a/tests/components/graphical_display_menu/test.esp32.yaml b/tests/components/graphical_display_menu/test.esp32-ard.yaml similarity index 100% rename from tests/components/graphical_display_menu/test.esp32.yaml rename to tests/components/graphical_display_menu/test.esp32-ard.yaml diff --git a/tests/components/graphical_display_menu/test.esp32-c3.yaml b/tests/components/graphical_display_menu/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/graphical_display_menu/test.esp32-c3.yaml rename to tests/components/graphical_display_menu/test.esp32-c3-ard.yaml diff --git a/tests/components/graphical_display_menu/test.esp8266.yaml b/tests/components/graphical_display_menu/test.esp8266-ard.yaml similarity index 100% rename from tests/components/graphical_display_menu/test.esp8266.yaml rename to tests/components/graphical_display_menu/test.esp8266-ard.yaml diff --git a/tests/components/graphical_display_menu/test.rp2040.yaml b/tests/components/graphical_display_menu/test.rp2040-ard.yaml similarity index 100% rename from tests/components/graphical_display_menu/test.rp2040.yaml rename to tests/components/graphical_display_menu/test.rp2040-ard.yaml diff --git a/tests/components/gree/test.esp32-c3.yaml b/tests/components/gree/test.esp32-ard.yaml similarity index 100% rename from tests/components/gree/test.esp32-c3.yaml rename to tests/components/gree/test.esp32-ard.yaml diff --git a/tests/components/gree/test.esp32.yaml b/tests/components/gree/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/gree/test.esp32.yaml rename to tests/components/gree/test.esp32-c3-ard.yaml diff --git a/tests/components/gree/test.esp8266.yaml b/tests/components/gree/test.esp8266-ard.yaml similarity index 100% rename from tests/components/gree/test.esp8266.yaml rename to tests/components/gree/test.esp8266-ard.yaml diff --git a/tests/components/grove_tb6612fng/test.esp32.yaml b/tests/components/grove_tb6612fng/test.esp32-ard.yaml similarity index 100% rename from tests/components/grove_tb6612fng/test.esp32.yaml rename to tests/components/grove_tb6612fng/test.esp32-ard.yaml diff --git a/tests/components/grove_tb6612fng/test.esp32-c3.yaml b/tests/components/grove_tb6612fng/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/grove_tb6612fng/test.esp32-c3.yaml rename to tests/components/grove_tb6612fng/test.esp32-c3-ard.yaml diff --git a/tests/components/grove_tb6612fng/test.esp8266.yaml b/tests/components/grove_tb6612fng/test.esp8266-ard.yaml similarity index 100% rename from tests/components/grove_tb6612fng/test.esp8266.yaml rename to tests/components/grove_tb6612fng/test.esp8266-ard.yaml diff --git a/tests/components/grove_tb6612fng/test.rp2040.yaml b/tests/components/grove_tb6612fng/test.rp2040-ard.yaml similarity index 100% rename from tests/components/grove_tb6612fng/test.rp2040.yaml rename to tests/components/grove_tb6612fng/test.rp2040-ard.yaml diff --git a/tests/components/growatt_solar/test.esp32.yaml b/tests/components/growatt_solar/test.esp32-ard.yaml similarity index 100% rename from tests/components/growatt_solar/test.esp32.yaml rename to tests/components/growatt_solar/test.esp32-ard.yaml diff --git a/tests/components/growatt_solar/test.esp32-c3.yaml b/tests/components/growatt_solar/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/growatt_solar/test.esp32-c3.yaml rename to tests/components/growatt_solar/test.esp32-c3-ard.yaml diff --git a/tests/components/growatt_solar/test.esp8266.yaml b/tests/components/growatt_solar/test.esp8266-ard.yaml similarity index 100% rename from tests/components/growatt_solar/test.esp8266.yaml rename to tests/components/growatt_solar/test.esp8266-ard.yaml diff --git a/tests/components/growatt_solar/test.rp2040.yaml b/tests/components/growatt_solar/test.rp2040-ard.yaml similarity index 100% rename from tests/components/growatt_solar/test.rp2040.yaml rename to tests/components/growatt_solar/test.rp2040-ard.yaml diff --git a/tests/components/gt911/test.esp32.yaml b/tests/components/gt911/test.esp32-ard.yaml similarity index 100% rename from tests/components/gt911/test.esp32.yaml rename to tests/components/gt911/test.esp32-ard.yaml diff --git a/tests/components/gt911/test.esp32-c3.yaml b/tests/components/gt911/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/gt911/test.esp32-c3.yaml rename to tests/components/gt911/test.esp32-c3-ard.yaml diff --git a/tests/components/gt911/test.esp8266.yaml b/tests/components/gt911/test.esp8266-ard.yaml similarity index 100% rename from tests/components/gt911/test.esp8266.yaml rename to tests/components/gt911/test.esp8266-ard.yaml diff --git a/tests/components/gt911/test.rp2040.yaml b/tests/components/gt911/test.rp2040-ard.yaml similarity index 100% rename from tests/components/gt911/test.rp2040.yaml rename to tests/components/gt911/test.rp2040-ard.yaml diff --git a/tests/components/haier/test.esp32.yaml b/tests/components/haier/test.esp32-ard.yaml similarity index 100% rename from tests/components/haier/test.esp32.yaml rename to tests/components/haier/test.esp32-ard.yaml diff --git a/tests/components/haier/test.esp32-c3.yaml b/tests/components/haier/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/haier/test.esp32-c3.yaml rename to tests/components/haier/test.esp32-c3-ard.yaml diff --git a/tests/components/haier/test.esp8266.yaml b/tests/components/haier/test.esp8266-ard.yaml similarity index 100% rename from tests/components/haier/test.esp8266.yaml rename to tests/components/haier/test.esp8266-ard.yaml diff --git a/tests/components/haier/test.rp2040.yaml b/tests/components/haier/test.rp2040-ard.yaml similarity index 100% rename from tests/components/haier/test.rp2040.yaml rename to tests/components/haier/test.rp2040-ard.yaml diff --git a/tests/components/havells_solar/test.esp32.yaml b/tests/components/havells_solar/test.esp32-ard.yaml similarity index 100% rename from tests/components/havells_solar/test.esp32.yaml rename to tests/components/havells_solar/test.esp32-ard.yaml diff --git a/tests/components/havells_solar/test.esp32-c3.yaml b/tests/components/havells_solar/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/havells_solar/test.esp32-c3.yaml rename to tests/components/havells_solar/test.esp32-c3-ard.yaml diff --git a/tests/components/havells_solar/test.esp8266.yaml b/tests/components/havells_solar/test.esp8266-ard.yaml similarity index 100% rename from tests/components/havells_solar/test.esp8266.yaml rename to tests/components/havells_solar/test.esp8266-ard.yaml diff --git a/tests/components/havells_solar/test.rp2040.yaml b/tests/components/havells_solar/test.rp2040-ard.yaml similarity index 100% rename from tests/components/havells_solar/test.rp2040.yaml rename to tests/components/havells_solar/test.rp2040-ard.yaml diff --git a/tests/components/hbridge/test.esp32.yaml b/tests/components/hbridge/test.esp32-ard.yaml similarity index 100% rename from tests/components/hbridge/test.esp32.yaml rename to tests/components/hbridge/test.esp32-ard.yaml diff --git a/tests/components/hbridge/test.esp32-c3.yaml b/tests/components/hbridge/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/hbridge/test.esp32-c3.yaml rename to tests/components/hbridge/test.esp32-c3-ard.yaml diff --git a/tests/components/hbridge/test.esp8266.yaml b/tests/components/hbridge/test.esp8266-ard.yaml similarity index 100% rename from tests/components/hbridge/test.esp8266.yaml rename to tests/components/hbridge/test.esp8266-ard.yaml diff --git a/tests/components/hbridge/test.rp2040.yaml b/tests/components/hbridge/test.rp2040-ard.yaml similarity index 100% rename from tests/components/hbridge/test.rp2040.yaml rename to tests/components/hbridge/test.rp2040-ard.yaml diff --git a/tests/components/hdc1080/test.esp32.yaml b/tests/components/hdc1080/test.esp32-ard.yaml similarity index 100% rename from tests/components/hdc1080/test.esp32.yaml rename to tests/components/hdc1080/test.esp32-ard.yaml diff --git a/tests/components/hdc1080/test.esp32-c3.yaml b/tests/components/hdc1080/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/hdc1080/test.esp32-c3.yaml rename to tests/components/hdc1080/test.esp32-c3-ard.yaml diff --git a/tests/components/hdc1080/test.esp8266.yaml b/tests/components/hdc1080/test.esp8266-ard.yaml similarity index 100% rename from tests/components/hdc1080/test.esp8266.yaml rename to tests/components/hdc1080/test.esp8266-ard.yaml diff --git a/tests/components/hdc1080/test.rp2040.yaml b/tests/components/hdc1080/test.rp2040-ard.yaml similarity index 100% rename from tests/components/hdc1080/test.rp2040.yaml rename to tests/components/hdc1080/test.rp2040-ard.yaml diff --git a/tests/components/he60r/test.esp32.yaml b/tests/components/he60r/test.esp32-ard.yaml similarity index 100% rename from tests/components/he60r/test.esp32.yaml rename to tests/components/he60r/test.esp32-ard.yaml diff --git a/tests/components/he60r/test.esp32-c3.yaml b/tests/components/he60r/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/he60r/test.esp32-c3.yaml rename to tests/components/he60r/test.esp32-c3-ard.yaml diff --git a/tests/components/he60r/test.esp8266.yaml b/tests/components/he60r/test.esp8266-ard.yaml similarity index 100% rename from tests/components/he60r/test.esp8266.yaml rename to tests/components/he60r/test.esp8266-ard.yaml diff --git a/tests/components/he60r/test.rp2040.yaml b/tests/components/he60r/test.rp2040-ard.yaml similarity index 100% rename from tests/components/he60r/test.rp2040.yaml rename to tests/components/he60r/test.rp2040-ard.yaml diff --git a/tests/components/heatpumpir/test.esp32.yaml b/tests/components/heatpumpir/test.esp32-ard.yaml similarity index 100% rename from tests/components/heatpumpir/test.esp32.yaml rename to tests/components/heatpumpir/test.esp32-ard.yaml diff --git a/tests/components/heatpumpir/test.esp8266.yaml b/tests/components/heatpumpir/test.esp8266-ard.yaml similarity index 100% rename from tests/components/heatpumpir/test.esp8266.yaml rename to tests/components/heatpumpir/test.esp8266-ard.yaml diff --git a/tests/components/hitachi_ac344/test.esp32-c3.yaml b/tests/components/hitachi_ac344/test.esp32-ard.yaml similarity index 100% rename from tests/components/hitachi_ac344/test.esp32-c3.yaml rename to tests/components/hitachi_ac344/test.esp32-ard.yaml diff --git a/tests/components/hitachi_ac344/test.esp32.yaml b/tests/components/hitachi_ac344/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/hitachi_ac344/test.esp32.yaml rename to tests/components/hitachi_ac344/test.esp32-c3-ard.yaml diff --git a/tests/components/hitachi_ac344/test.esp8266.yaml b/tests/components/hitachi_ac344/test.esp8266-ard.yaml similarity index 100% rename from tests/components/hitachi_ac344/test.esp8266.yaml rename to tests/components/hitachi_ac344/test.esp8266-ard.yaml diff --git a/tests/components/hitachi_ac424/test.esp32-c3.yaml b/tests/components/hitachi_ac424/test.esp32-ard.yaml similarity index 100% rename from tests/components/hitachi_ac424/test.esp32-c3.yaml rename to tests/components/hitachi_ac424/test.esp32-ard.yaml diff --git a/tests/components/hitachi_ac424/test.esp32.yaml b/tests/components/hitachi_ac424/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/hitachi_ac424/test.esp32.yaml rename to tests/components/hitachi_ac424/test.esp32-c3-ard.yaml diff --git a/tests/components/hitachi_ac424/test.esp8266.yaml b/tests/components/hitachi_ac424/test.esp8266-ard.yaml similarity index 100% rename from tests/components/hitachi_ac424/test.esp8266.yaml rename to tests/components/hitachi_ac424/test.esp8266-ard.yaml diff --git a/tests/components/hlw8012/test.esp32.yaml b/tests/components/hlw8012/test.esp32-ard.yaml similarity index 100% rename from tests/components/hlw8012/test.esp32.yaml rename to tests/components/hlw8012/test.esp32-ard.yaml diff --git a/tests/components/hlw8012/test.esp32-c3.yaml b/tests/components/hlw8012/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/hlw8012/test.esp32-c3.yaml rename to tests/components/hlw8012/test.esp32-c3-ard.yaml diff --git a/tests/components/hlw8012/test.esp8266.yaml b/tests/components/hlw8012/test.esp8266-ard.yaml similarity index 100% rename from tests/components/hlw8012/test.esp8266.yaml rename to tests/components/hlw8012/test.esp8266-ard.yaml diff --git a/tests/components/hlw8012/test.rp2040.yaml b/tests/components/hlw8012/test.rp2040-ard.yaml similarity index 100% rename from tests/components/hlw8012/test.rp2040.yaml rename to tests/components/hlw8012/test.rp2040-ard.yaml diff --git a/tests/components/hm3301/test.esp32.yaml b/tests/components/hm3301/test.esp32-ard.yaml similarity index 100% rename from tests/components/hm3301/test.esp32.yaml rename to tests/components/hm3301/test.esp32-ard.yaml diff --git a/tests/components/hm3301/test.esp32-c3.yaml b/tests/components/hm3301/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/hm3301/test.esp32-c3.yaml rename to tests/components/hm3301/test.esp32-c3-ard.yaml diff --git a/tests/components/hm3301/test.esp8266.yaml b/tests/components/hm3301/test.esp8266-ard.yaml similarity index 100% rename from tests/components/hm3301/test.esp8266.yaml rename to tests/components/hm3301/test.esp8266-ard.yaml diff --git a/tests/components/hm3301/test.rp2040.yaml b/tests/components/hm3301/test.rp2040-ard.yaml similarity index 100% rename from tests/components/hm3301/test.rp2040.yaml rename to tests/components/hm3301/test.rp2040-ard.yaml diff --git a/tests/components/hmc5883l/test.esp32.yaml b/tests/components/hmc5883l/test.esp32-ard.yaml similarity index 100% rename from tests/components/hmc5883l/test.esp32.yaml rename to tests/components/hmc5883l/test.esp32-ard.yaml diff --git a/tests/components/hmc5883l/test.esp32-c3.yaml b/tests/components/hmc5883l/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/hmc5883l/test.esp32-c3.yaml rename to tests/components/hmc5883l/test.esp32-c3-ard.yaml diff --git a/tests/components/hmc5883l/test.esp8266.yaml b/tests/components/hmc5883l/test.esp8266-ard.yaml similarity index 100% rename from tests/components/hmc5883l/test.esp8266.yaml rename to tests/components/hmc5883l/test.esp8266-ard.yaml diff --git a/tests/components/hmc5883l/test.rp2040.yaml b/tests/components/hmc5883l/test.rp2040-ard.yaml similarity index 100% rename from tests/components/hmc5883l/test.rp2040.yaml rename to tests/components/hmc5883l/test.rp2040-ard.yaml diff --git a/tests/components/homeassistant/test.bk72xx.yaml b/tests/components/homeassistant/test.bk72xx-ard.yaml similarity index 100% rename from tests/components/homeassistant/test.bk72xx.yaml rename to tests/components/homeassistant/test.bk72xx-ard.yaml diff --git a/tests/components/homeassistant/test.esp32-c3.yaml b/tests/components/homeassistant/test.esp32-ard.yaml similarity index 100% rename from tests/components/homeassistant/test.esp32-c3.yaml rename to tests/components/homeassistant/test.esp32-ard.yaml diff --git a/tests/components/homeassistant/test.esp32.yaml b/tests/components/homeassistant/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/homeassistant/test.esp32.yaml rename to tests/components/homeassistant/test.esp32-c3-ard.yaml diff --git a/tests/components/homeassistant/test.esp8266.yaml b/tests/components/homeassistant/test.esp8266-ard.yaml similarity index 100% rename from tests/components/homeassistant/test.esp8266.yaml rename to tests/components/homeassistant/test.esp8266-ard.yaml diff --git a/tests/components/homeassistant/test.rp2040.yaml b/tests/components/homeassistant/test.rp2040-ard.yaml similarity index 100% rename from tests/components/homeassistant/test.rp2040.yaml rename to tests/components/homeassistant/test.rp2040-ard.yaml diff --git a/tests/components/honeywell_hih_i2c/test.esp32.yaml b/tests/components/honeywell_hih_i2c/test.esp32-ard.yaml similarity index 100% rename from tests/components/honeywell_hih_i2c/test.esp32.yaml rename to tests/components/honeywell_hih_i2c/test.esp32-ard.yaml diff --git a/tests/components/honeywell_hih_i2c/test.esp32-c3.yaml b/tests/components/honeywell_hih_i2c/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/honeywell_hih_i2c/test.esp32-c3.yaml rename to tests/components/honeywell_hih_i2c/test.esp32-c3-ard.yaml diff --git a/tests/components/honeywell_hih_i2c/test.esp8266.yaml b/tests/components/honeywell_hih_i2c/test.esp8266-ard.yaml similarity index 100% rename from tests/components/honeywell_hih_i2c/test.esp8266.yaml rename to tests/components/honeywell_hih_i2c/test.esp8266-ard.yaml diff --git a/tests/components/honeywell_hih_i2c/test.rp2040.yaml b/tests/components/honeywell_hih_i2c/test.rp2040-ard.yaml similarity index 100% rename from tests/components/honeywell_hih_i2c/test.rp2040.yaml rename to tests/components/honeywell_hih_i2c/test.rp2040-ard.yaml diff --git a/tests/components/honeywellabp/test.esp32.yaml b/tests/components/honeywellabp/test.esp32-ard.yaml similarity index 100% rename from tests/components/honeywellabp/test.esp32.yaml rename to tests/components/honeywellabp/test.esp32-ard.yaml diff --git a/tests/components/honeywellabp/test.esp32-c3.yaml b/tests/components/honeywellabp/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/honeywellabp/test.esp32-c3.yaml rename to tests/components/honeywellabp/test.esp32-c3-ard.yaml diff --git a/tests/components/honeywellabp/test.esp8266.yaml b/tests/components/honeywellabp/test.esp8266-ard.yaml similarity index 100% rename from tests/components/honeywellabp/test.esp8266.yaml rename to tests/components/honeywellabp/test.esp8266-ard.yaml diff --git a/tests/components/honeywellabp/test.rp2040.yaml b/tests/components/honeywellabp/test.rp2040-ard.yaml similarity index 100% rename from tests/components/honeywellabp/test.rp2040.yaml rename to tests/components/honeywellabp/test.rp2040-ard.yaml diff --git a/tests/components/honeywellabp2_i2c/test.esp32.yaml b/tests/components/honeywellabp2_i2c/test.esp32-ard.yaml similarity index 100% rename from tests/components/honeywellabp2_i2c/test.esp32.yaml rename to tests/components/honeywellabp2_i2c/test.esp32-ard.yaml diff --git a/tests/components/honeywellabp2_i2c/test.esp32-c3.yaml b/tests/components/honeywellabp2_i2c/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/honeywellabp2_i2c/test.esp32-c3.yaml rename to tests/components/honeywellabp2_i2c/test.esp32-c3-ard.yaml diff --git a/tests/components/honeywellabp2_i2c/test.esp8266.yaml b/tests/components/honeywellabp2_i2c/test.esp8266-ard.yaml similarity index 100% rename from tests/components/honeywellabp2_i2c/test.esp8266.yaml rename to tests/components/honeywellabp2_i2c/test.esp8266-ard.yaml diff --git a/tests/components/honeywellabp2_i2c/test.rp2040.yaml b/tests/components/honeywellabp2_i2c/test.rp2040-ard.yaml similarity index 100% rename from tests/components/honeywellabp2_i2c/test.rp2040.yaml rename to tests/components/honeywellabp2_i2c/test.rp2040-ard.yaml diff --git a/tests/components/hrxl_maxsonar_wr/test.esp32.yaml b/tests/components/hrxl_maxsonar_wr/test.esp32-ard.yaml similarity index 100% rename from tests/components/hrxl_maxsonar_wr/test.esp32.yaml rename to tests/components/hrxl_maxsonar_wr/test.esp32-ard.yaml diff --git a/tests/components/hrxl_maxsonar_wr/test.esp32-c3.yaml b/tests/components/hrxl_maxsonar_wr/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/hrxl_maxsonar_wr/test.esp32-c3.yaml rename to tests/components/hrxl_maxsonar_wr/test.esp32-c3-ard.yaml diff --git a/tests/components/hrxl_maxsonar_wr/test.esp8266.yaml b/tests/components/hrxl_maxsonar_wr/test.esp8266-ard.yaml similarity index 100% rename from tests/components/hrxl_maxsonar_wr/test.esp8266.yaml rename to tests/components/hrxl_maxsonar_wr/test.esp8266-ard.yaml diff --git a/tests/components/hrxl_maxsonar_wr/test.rp2040.yaml b/tests/components/hrxl_maxsonar_wr/test.rp2040-ard.yaml similarity index 100% rename from tests/components/hrxl_maxsonar_wr/test.rp2040.yaml rename to tests/components/hrxl_maxsonar_wr/test.rp2040-ard.yaml diff --git a/tests/components/hte501/test.esp32.yaml b/tests/components/hte501/test.esp32-ard.yaml similarity index 100% rename from tests/components/hte501/test.esp32.yaml rename to tests/components/hte501/test.esp32-ard.yaml diff --git a/tests/components/hte501/test.esp32-c3.yaml b/tests/components/hte501/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/hte501/test.esp32-c3.yaml rename to tests/components/hte501/test.esp32-c3-ard.yaml diff --git a/tests/components/hte501/test.esp8266.yaml b/tests/components/hte501/test.esp8266-ard.yaml similarity index 100% rename from tests/components/hte501/test.esp8266.yaml rename to tests/components/hte501/test.esp8266-ard.yaml diff --git a/tests/components/hte501/test.rp2040.yaml b/tests/components/hte501/test.rp2040-ard.yaml similarity index 100% rename from tests/components/hte501/test.rp2040.yaml rename to tests/components/hte501/test.rp2040-ard.yaml diff --git a/tests/components/http_request/test-nossl.esp8266.yaml b/tests/components/http_request/test-nossl.esp8266-ard.yaml similarity index 100% rename from tests/components/http_request/test-nossl.esp8266.yaml rename to tests/components/http_request/test-nossl.esp8266-ard.yaml diff --git a/tests/components/http_request/test.esp32-c3.yaml b/tests/components/http_request/test.esp32-ard.yaml similarity index 100% rename from tests/components/http_request/test.esp32-c3.yaml rename to tests/components/http_request/test.esp32-ard.yaml diff --git a/tests/components/http_request/test.esp32.yaml b/tests/components/http_request/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/http_request/test.esp32.yaml rename to tests/components/http_request/test.esp32-c3-ard.yaml diff --git a/tests/components/http_request/test.esp8266.yaml b/tests/components/http_request/test.esp8266-ard.yaml similarity index 100% rename from tests/components/http_request/test.esp8266.yaml rename to tests/components/http_request/test.esp8266-ard.yaml diff --git a/tests/components/http_request/test.rp2040.yaml b/tests/components/http_request/test.rp2040-ard.yaml similarity index 100% rename from tests/components/http_request/test.rp2040.yaml rename to tests/components/http_request/test.rp2040-ard.yaml diff --git a/tests/components/htu21d/test.esp32.yaml b/tests/components/htu21d/test.esp32-ard.yaml similarity index 100% rename from tests/components/htu21d/test.esp32.yaml rename to tests/components/htu21d/test.esp32-ard.yaml diff --git a/tests/components/htu21d/test.esp32-c3.yaml b/tests/components/htu21d/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/htu21d/test.esp32-c3.yaml rename to tests/components/htu21d/test.esp32-c3-ard.yaml diff --git a/tests/components/htu21d/test.esp8266.yaml b/tests/components/htu21d/test.esp8266-ard.yaml similarity index 100% rename from tests/components/htu21d/test.esp8266.yaml rename to tests/components/htu21d/test.esp8266-ard.yaml diff --git a/tests/components/htu21d/test.rp2040.yaml b/tests/components/htu21d/test.rp2040-ard.yaml similarity index 100% rename from tests/components/htu21d/test.rp2040.yaml rename to tests/components/htu21d/test.rp2040-ard.yaml diff --git a/tests/components/htu31d/test.esp32.yaml b/tests/components/htu31d/test.esp32-ard.yaml similarity index 100% rename from tests/components/htu31d/test.esp32.yaml rename to tests/components/htu31d/test.esp32-ard.yaml diff --git a/tests/components/htu31d/test.esp8266.yaml b/tests/components/htu31d/test.esp8266-ard.yaml similarity index 100% rename from tests/components/htu31d/test.esp8266.yaml rename to tests/components/htu31d/test.esp8266-ard.yaml diff --git a/tests/components/hx711/test.esp32.yaml b/tests/components/hx711/test.esp32-ard.yaml similarity index 100% rename from tests/components/hx711/test.esp32.yaml rename to tests/components/hx711/test.esp32-ard.yaml diff --git a/tests/components/hx711/test.esp32-c3.yaml b/tests/components/hx711/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/hx711/test.esp32-c3.yaml rename to tests/components/hx711/test.esp32-c3-ard.yaml diff --git a/tests/components/hx711/test.esp8266.yaml b/tests/components/hx711/test.esp8266-ard.yaml similarity index 100% rename from tests/components/hx711/test.esp8266.yaml rename to tests/components/hx711/test.esp8266-ard.yaml diff --git a/tests/components/hx711/test.rp2040.yaml b/tests/components/hx711/test.rp2040-ard.yaml similarity index 100% rename from tests/components/hx711/test.rp2040.yaml rename to tests/components/hx711/test.rp2040-ard.yaml diff --git a/tests/components/hydreon_rgxx/test.esp32.yaml b/tests/components/hydreon_rgxx/test.esp32-ard.yaml similarity index 100% rename from tests/components/hydreon_rgxx/test.esp32.yaml rename to tests/components/hydreon_rgxx/test.esp32-ard.yaml diff --git a/tests/components/hydreon_rgxx/test.esp32-c3.yaml b/tests/components/hydreon_rgxx/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/hydreon_rgxx/test.esp32-c3.yaml rename to tests/components/hydreon_rgxx/test.esp32-c3-ard.yaml diff --git a/tests/components/hydreon_rgxx/test.esp8266.yaml b/tests/components/hydreon_rgxx/test.esp8266-ard.yaml similarity index 100% rename from tests/components/hydreon_rgxx/test.esp8266.yaml rename to tests/components/hydreon_rgxx/test.esp8266-ard.yaml diff --git a/tests/components/hydreon_rgxx/test.rp2040.yaml b/tests/components/hydreon_rgxx/test.rp2040-ard.yaml similarity index 100% rename from tests/components/hydreon_rgxx/test.rp2040.yaml rename to tests/components/hydreon_rgxx/test.rp2040-ard.yaml diff --git a/tests/components/hyt271/test.esp32.yaml b/tests/components/hyt271/test.esp32-ard.yaml similarity index 100% rename from tests/components/hyt271/test.esp32.yaml rename to tests/components/hyt271/test.esp32-ard.yaml diff --git a/tests/components/hyt271/test.esp32-c3.yaml b/tests/components/hyt271/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/hyt271/test.esp32-c3.yaml rename to tests/components/hyt271/test.esp32-c3-ard.yaml diff --git a/tests/components/hyt271/test.esp8266.yaml b/tests/components/hyt271/test.esp8266-ard.yaml similarity index 100% rename from tests/components/hyt271/test.esp8266.yaml rename to tests/components/hyt271/test.esp8266-ard.yaml diff --git a/tests/components/hyt271/test.rp2040.yaml b/tests/components/hyt271/test.rp2040-ard.yaml similarity index 100% rename from tests/components/hyt271/test.rp2040.yaml rename to tests/components/hyt271/test.rp2040-ard.yaml diff --git a/tests/components/i2c/test.esp32.yaml b/tests/components/i2c/test.esp32-ard.yaml similarity index 100% rename from tests/components/i2c/test.esp32.yaml rename to tests/components/i2c/test.esp32-ard.yaml diff --git a/tests/components/i2c/test.esp32-c3.yaml b/tests/components/i2c/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/i2c/test.esp32-c3.yaml rename to tests/components/i2c/test.esp32-c3-ard.yaml diff --git a/tests/components/i2c/test.esp8266.yaml b/tests/components/i2c/test.esp8266-ard.yaml similarity index 100% rename from tests/components/i2c/test.esp8266.yaml rename to tests/components/i2c/test.esp8266-ard.yaml diff --git a/tests/components/i2c/test.rp2040.yaml b/tests/components/i2c/test.rp2040-ard.yaml similarity index 100% rename from tests/components/i2c/test.rp2040.yaml rename to tests/components/i2c/test.rp2040-ard.yaml diff --git a/tests/components/i2s_audio/test.esp32.yaml b/tests/components/i2s_audio/test.esp32-ard.yaml similarity index 100% rename from tests/components/i2s_audio/test.esp32.yaml rename to tests/components/i2s_audio/test.esp32-ard.yaml diff --git a/tests/components/i2s_audio/test.esp32-c3.yaml b/tests/components/i2s_audio/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/i2s_audio/test.esp32-c3.yaml rename to tests/components/i2s_audio/test.esp32-c3-ard.yaml diff --git a/tests/components/iaqcore/test.esp32.yaml b/tests/components/iaqcore/test.esp32-ard.yaml similarity index 100% rename from tests/components/iaqcore/test.esp32.yaml rename to tests/components/iaqcore/test.esp32-ard.yaml diff --git a/tests/components/iaqcore/test.esp32-c3.yaml b/tests/components/iaqcore/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/iaqcore/test.esp32-c3.yaml rename to tests/components/iaqcore/test.esp32-c3-ard.yaml diff --git a/tests/components/iaqcore/test.esp8266.yaml b/tests/components/iaqcore/test.esp8266-ard.yaml similarity index 100% rename from tests/components/iaqcore/test.esp8266.yaml rename to tests/components/iaqcore/test.esp8266-ard.yaml diff --git a/tests/components/iaqcore/test.rp2040.yaml b/tests/components/iaqcore/test.rp2040-ard.yaml similarity index 100% rename from tests/components/iaqcore/test.rp2040.yaml rename to tests/components/iaqcore/test.rp2040-ard.yaml diff --git a/tests/components/ili9xxx/test.esp32.yaml b/tests/components/ili9xxx/test.esp32-ard.yaml similarity index 100% rename from tests/components/ili9xxx/test.esp32.yaml rename to tests/components/ili9xxx/test.esp32-ard.yaml diff --git a/tests/components/ili9xxx/test.esp32-c3.yaml b/tests/components/ili9xxx/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ili9xxx/test.esp32-c3.yaml rename to tests/components/ili9xxx/test.esp32-c3-ard.yaml diff --git a/tests/components/ili9xxx/test.esp8266.yaml b/tests/components/ili9xxx/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ili9xxx/test.esp8266.yaml rename to tests/components/ili9xxx/test.esp8266-ard.yaml diff --git a/tests/components/ili9xxx/test.rp2040.yaml b/tests/components/ili9xxx/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ili9xxx/test.rp2040.yaml rename to tests/components/ili9xxx/test.rp2040-ard.yaml diff --git a/tests/components/image/test.esp32.yaml b/tests/components/image/test.esp32-ard.yaml similarity index 100% rename from tests/components/image/test.esp32.yaml rename to tests/components/image/test.esp32-ard.yaml diff --git a/tests/components/image/test.esp32-c3.yaml b/tests/components/image/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/image/test.esp32-c3.yaml rename to tests/components/image/test.esp32-c3-ard.yaml diff --git a/tests/components/image/test.esp8266.yaml b/tests/components/image/test.esp8266-ard.yaml similarity index 100% rename from tests/components/image/test.esp8266.yaml rename to tests/components/image/test.esp8266-ard.yaml diff --git a/tests/components/image/test.rp2040.yaml b/tests/components/image/test.rp2040-ard.yaml similarity index 100% rename from tests/components/image/test.rp2040.yaml rename to tests/components/image/test.rp2040-ard.yaml diff --git a/tests/components/improv_serial/test.esp32-c3.yaml b/tests/components/improv_serial/test.esp32-ard.yaml similarity index 100% rename from tests/components/improv_serial/test.esp32-c3.yaml rename to tests/components/improv_serial/test.esp32-ard.yaml diff --git a/tests/components/improv_serial/test.esp32.yaml b/tests/components/improv_serial/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/improv_serial/test.esp32.yaml rename to tests/components/improv_serial/test.esp32-c3-ard.yaml diff --git a/tests/components/improv_serial/test.esp8266.yaml b/tests/components/improv_serial/test.esp8266-ard.yaml similarity index 100% rename from tests/components/improv_serial/test.esp8266.yaml rename to tests/components/improv_serial/test.esp8266-ard.yaml diff --git a/tests/components/improv_serial/test.rp2040.yaml b/tests/components/improv_serial/test.rp2040-ard.yaml similarity index 100% rename from tests/components/improv_serial/test.rp2040.yaml rename to tests/components/improv_serial/test.rp2040-ard.yaml diff --git a/tests/components/ina219/test.esp32.yaml b/tests/components/ina219/test.esp32-ard.yaml similarity index 100% rename from tests/components/ina219/test.esp32.yaml rename to tests/components/ina219/test.esp32-ard.yaml diff --git a/tests/components/ina219/test.esp32-c3.yaml b/tests/components/ina219/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ina219/test.esp32-c3.yaml rename to tests/components/ina219/test.esp32-c3-ard.yaml diff --git a/tests/components/ina219/test.esp8266.yaml b/tests/components/ina219/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ina219/test.esp8266.yaml rename to tests/components/ina219/test.esp8266-ard.yaml diff --git a/tests/components/ina219/test.rp2040.yaml b/tests/components/ina219/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ina219/test.rp2040.yaml rename to tests/components/ina219/test.rp2040-ard.yaml diff --git a/tests/components/ina226/test.esp32.yaml b/tests/components/ina226/test.esp32-ard.yaml similarity index 100% rename from tests/components/ina226/test.esp32.yaml rename to tests/components/ina226/test.esp32-ard.yaml diff --git a/tests/components/ina226/test.esp32-c3.yaml b/tests/components/ina226/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ina226/test.esp32-c3.yaml rename to tests/components/ina226/test.esp32-c3-ard.yaml diff --git a/tests/components/ina226/test.esp8266.yaml b/tests/components/ina226/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ina226/test.esp8266.yaml rename to tests/components/ina226/test.esp8266-ard.yaml diff --git a/tests/components/ina226/test.rp2040.yaml b/tests/components/ina226/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ina226/test.rp2040.yaml rename to tests/components/ina226/test.rp2040-ard.yaml diff --git a/tests/components/ina260/test.esp32.yaml b/tests/components/ina260/test.esp32-ard.yaml similarity index 100% rename from tests/components/ina260/test.esp32.yaml rename to tests/components/ina260/test.esp32-ard.yaml diff --git a/tests/components/ina260/test.esp32-c3.yaml b/tests/components/ina260/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ina260/test.esp32-c3.yaml rename to tests/components/ina260/test.esp32-c3-ard.yaml diff --git a/tests/components/ina260/test.esp8266.yaml b/tests/components/ina260/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ina260/test.esp8266.yaml rename to tests/components/ina260/test.esp8266-ard.yaml diff --git a/tests/components/ina260/test.rp2040.yaml b/tests/components/ina260/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ina260/test.rp2040.yaml rename to tests/components/ina260/test.rp2040-ard.yaml diff --git a/tests/components/ina2xx_i2c/test.esp32.yaml b/tests/components/ina2xx_i2c/test.esp32-ard.yaml similarity index 100% rename from tests/components/ina2xx_i2c/test.esp32.yaml rename to tests/components/ina2xx_i2c/test.esp32-ard.yaml diff --git a/tests/components/ina2xx_i2c/test.esp32-c3.yaml b/tests/components/ina2xx_i2c/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ina2xx_i2c/test.esp32-c3.yaml rename to tests/components/ina2xx_i2c/test.esp32-c3-ard.yaml diff --git a/tests/components/ina2xx_i2c/test.esp8266.yaml b/tests/components/ina2xx_i2c/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ina2xx_i2c/test.esp8266.yaml rename to tests/components/ina2xx_i2c/test.esp8266-ard.yaml diff --git a/tests/components/ina2xx_i2c/test.rp2040.yaml b/tests/components/ina2xx_i2c/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ina2xx_i2c/test.rp2040.yaml rename to tests/components/ina2xx_i2c/test.rp2040-ard.yaml diff --git a/tests/components/ina2xx_spi/test.esp32.yaml b/tests/components/ina2xx_spi/test.esp32-ard.yaml similarity index 100% rename from tests/components/ina2xx_spi/test.esp32.yaml rename to tests/components/ina2xx_spi/test.esp32-ard.yaml diff --git a/tests/components/ina2xx_spi/test.esp32-c3.yaml b/tests/components/ina2xx_spi/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ina2xx_spi/test.esp32-c3.yaml rename to tests/components/ina2xx_spi/test.esp32-c3-ard.yaml diff --git a/tests/components/ina2xx_spi/test.esp8266.yaml b/tests/components/ina2xx_spi/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ina2xx_spi/test.esp8266.yaml rename to tests/components/ina2xx_spi/test.esp8266-ard.yaml diff --git a/tests/components/ina2xx_spi/test.rp2040.yaml b/tests/components/ina2xx_spi/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ina2xx_spi/test.rp2040.yaml rename to tests/components/ina2xx_spi/test.rp2040-ard.yaml diff --git a/tests/components/ina3221/test.esp32.yaml b/tests/components/ina3221/test.esp32-ard.yaml similarity index 100% rename from tests/components/ina3221/test.esp32.yaml rename to tests/components/ina3221/test.esp32-ard.yaml diff --git a/tests/components/ina3221/test.esp32-c3.yaml b/tests/components/ina3221/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ina3221/test.esp32-c3.yaml rename to tests/components/ina3221/test.esp32-c3-ard.yaml diff --git a/tests/components/ina3221/test.esp8266.yaml b/tests/components/ina3221/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ina3221/test.esp8266.yaml rename to tests/components/ina3221/test.esp8266-ard.yaml diff --git a/tests/components/ina3221/test.rp2040.yaml b/tests/components/ina3221/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ina3221/test.rp2040.yaml rename to tests/components/ina3221/test.rp2040-ard.yaml diff --git a/tests/components/inkbird_ibsth1_mini/test.esp32-c3.yaml b/tests/components/inkbird_ibsth1_mini/test.esp32-ard.yaml similarity index 100% rename from tests/components/inkbird_ibsth1_mini/test.esp32-c3.yaml rename to tests/components/inkbird_ibsth1_mini/test.esp32-ard.yaml diff --git a/tests/components/inkbird_ibsth1_mini/test.esp32.yaml b/tests/components/inkbird_ibsth1_mini/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/inkbird_ibsth1_mini/test.esp32.yaml rename to tests/components/inkbird_ibsth1_mini/test.esp32-c3-ard.yaml diff --git a/tests/components/inkplate6/test.esp32.yaml b/tests/components/inkplate6/test.esp32-ard.yaml similarity index 100% rename from tests/components/inkplate6/test.esp32.yaml rename to tests/components/inkplate6/test.esp32-ard.yaml diff --git a/tests/components/integration/test.esp32.yaml b/tests/components/integration/test.esp32-ard.yaml similarity index 100% rename from tests/components/integration/test.esp32.yaml rename to tests/components/integration/test.esp32-ard.yaml diff --git a/tests/components/integration/test.esp32-c3.yaml b/tests/components/integration/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/integration/test.esp32-c3.yaml rename to tests/components/integration/test.esp32-c3-ard.yaml diff --git a/tests/components/integration/test.esp32-s2.yaml b/tests/components/integration/test.esp32-s2-ard.yaml similarity index 100% rename from tests/components/integration/test.esp32-s2.yaml rename to tests/components/integration/test.esp32-s2-ard.yaml diff --git a/tests/components/integration/test.esp32-s3.yaml b/tests/components/integration/test.esp32-s3-ard.yaml similarity index 100% rename from tests/components/integration/test.esp32-s3.yaml rename to tests/components/integration/test.esp32-s3-ard.yaml diff --git a/tests/components/integration/test.esp8266.yaml b/tests/components/integration/test.esp8266-ard.yaml similarity index 100% rename from tests/components/integration/test.esp8266.yaml rename to tests/components/integration/test.esp8266-ard.yaml diff --git a/tests/components/integration/test.rp2040.yaml b/tests/components/integration/test.rp2040-ard.yaml similarity index 100% rename from tests/components/integration/test.rp2040.yaml rename to tests/components/integration/test.rp2040-ard.yaml diff --git a/tests/components/internal_temperature/test.bk72xx.yaml b/tests/components/internal_temperature/test.bk72xx-ard.yaml similarity index 100% rename from tests/components/internal_temperature/test.bk72xx.yaml rename to tests/components/internal_temperature/test.bk72xx-ard.yaml diff --git a/tests/components/internal_temperature/test.esp32-c3.yaml b/tests/components/internal_temperature/test.esp32-ard.yaml similarity index 100% rename from tests/components/internal_temperature/test.esp32-c3.yaml rename to tests/components/internal_temperature/test.esp32-ard.yaml diff --git a/tests/components/internal_temperature/test.esp32-s2.yaml b/tests/components/internal_temperature/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/internal_temperature/test.esp32-s2.yaml rename to tests/components/internal_temperature/test.esp32-c3-ard.yaml diff --git a/tests/components/internal_temperature/test.esp32.yaml b/tests/components/internal_temperature/test.esp32-s2-ard.yaml similarity index 100% rename from tests/components/internal_temperature/test.esp32.yaml rename to tests/components/internal_temperature/test.esp32-s2-ard.yaml diff --git a/tests/components/internal_temperature/test.esp32-s3.yaml b/tests/components/internal_temperature/test.esp32-s3-ard.yaml similarity index 100% rename from tests/components/internal_temperature/test.esp32-s3.yaml rename to tests/components/internal_temperature/test.esp32-s3-ard.yaml diff --git a/tests/components/internal_temperature/test.rp2040.yaml b/tests/components/internal_temperature/test.rp2040-ard.yaml similarity index 100% rename from tests/components/internal_temperature/test.rp2040.yaml rename to tests/components/internal_temperature/test.rp2040-ard.yaml diff --git a/tests/components/interval/test.esp32-c3.yaml b/tests/components/interval/test.esp32-ard.yaml similarity index 100% rename from tests/components/interval/test.esp32-c3.yaml rename to tests/components/interval/test.esp32-ard.yaml diff --git a/tests/components/interval/test.esp32.yaml b/tests/components/interval/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/interval/test.esp32.yaml rename to tests/components/interval/test.esp32-c3-ard.yaml diff --git a/tests/components/interval/test.esp8266.yaml b/tests/components/interval/test.esp8266-ard.yaml similarity index 100% rename from tests/components/interval/test.esp8266.yaml rename to tests/components/interval/test.esp8266-ard.yaml diff --git a/tests/components/interval/test.rp2040.yaml b/tests/components/interval/test.rp2040-ard.yaml similarity index 100% rename from tests/components/interval/test.rp2040.yaml rename to tests/components/interval/test.rp2040-ard.yaml diff --git a/tests/components/jsn_sr04t/test.esp32.yaml b/tests/components/jsn_sr04t/test.esp32-ard.yaml similarity index 100% rename from tests/components/jsn_sr04t/test.esp32.yaml rename to tests/components/jsn_sr04t/test.esp32-ard.yaml diff --git a/tests/components/jsn_sr04t/test.esp32-c3.yaml b/tests/components/jsn_sr04t/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/jsn_sr04t/test.esp32-c3.yaml rename to tests/components/jsn_sr04t/test.esp32-c3-ard.yaml diff --git a/tests/components/jsn_sr04t/test.esp8266.yaml b/tests/components/jsn_sr04t/test.esp8266-ard.yaml similarity index 100% rename from tests/components/jsn_sr04t/test.esp8266.yaml rename to tests/components/jsn_sr04t/test.esp8266-ard.yaml diff --git a/tests/components/jsn_sr04t/test.rp2040.yaml b/tests/components/jsn_sr04t/test.rp2040-ard.yaml similarity index 100% rename from tests/components/jsn_sr04t/test.rp2040.yaml rename to tests/components/jsn_sr04t/test.rp2040-ard.yaml diff --git a/tests/components/kamstrup_kmp/test.esp32.yaml b/tests/components/kamstrup_kmp/test.esp32-ard.yaml similarity index 100% rename from tests/components/kamstrup_kmp/test.esp32.yaml rename to tests/components/kamstrup_kmp/test.esp32-ard.yaml diff --git a/tests/components/kamstrup_kmp/test.esp8266.yaml b/tests/components/kamstrup_kmp/test.esp8266-ard.yaml similarity index 100% rename from tests/components/kamstrup_kmp/test.esp8266.yaml rename to tests/components/kamstrup_kmp/test.esp8266-ard.yaml diff --git a/tests/components/key_collector/test.esp32.yaml b/tests/components/key_collector/test.esp32-ard.yaml similarity index 100% rename from tests/components/key_collector/test.esp32.yaml rename to tests/components/key_collector/test.esp32-ard.yaml diff --git a/tests/components/key_collector/test.esp32-c3.yaml b/tests/components/key_collector/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/key_collector/test.esp32-c3.yaml rename to tests/components/key_collector/test.esp32-c3-ard.yaml diff --git a/tests/components/key_collector/test.esp8266.yaml b/tests/components/key_collector/test.esp8266-ard.yaml similarity index 100% rename from tests/components/key_collector/test.esp8266.yaml rename to tests/components/key_collector/test.esp8266-ard.yaml diff --git a/tests/components/key_collector/test.rp2040.yaml b/tests/components/key_collector/test.rp2040-ard.yaml similarity index 100% rename from tests/components/key_collector/test.rp2040.yaml rename to tests/components/key_collector/test.rp2040-ard.yaml diff --git a/tests/components/kmeteriso/test.esp32.yaml b/tests/components/kmeteriso/test.esp32-ard.yaml similarity index 100% rename from tests/components/kmeteriso/test.esp32.yaml rename to tests/components/kmeteriso/test.esp32-ard.yaml diff --git a/tests/components/kmeteriso/test.esp32-c3.yaml b/tests/components/kmeteriso/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/kmeteriso/test.esp32-c3.yaml rename to tests/components/kmeteriso/test.esp32-c3-ard.yaml diff --git a/tests/components/kmeteriso/test.esp8266.yaml b/tests/components/kmeteriso/test.esp8266-ard.yaml similarity index 100% rename from tests/components/kmeteriso/test.esp8266.yaml rename to tests/components/kmeteriso/test.esp8266-ard.yaml diff --git a/tests/components/kmeteriso/test.rp2040.yaml b/tests/components/kmeteriso/test.rp2040-ard.yaml similarity index 100% rename from tests/components/kmeteriso/test.rp2040.yaml rename to tests/components/kmeteriso/test.rp2040-ard.yaml diff --git a/tests/components/kuntze/test.esp32.yaml b/tests/components/kuntze/test.esp32-ard.yaml similarity index 100% rename from tests/components/kuntze/test.esp32.yaml rename to tests/components/kuntze/test.esp32-ard.yaml diff --git a/tests/components/kuntze/test.esp32-c3.yaml b/tests/components/kuntze/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/kuntze/test.esp32-c3.yaml rename to tests/components/kuntze/test.esp32-c3-ard.yaml diff --git a/tests/components/kuntze/test.esp8266.yaml b/tests/components/kuntze/test.esp8266-ard.yaml similarity index 100% rename from tests/components/kuntze/test.esp8266.yaml rename to tests/components/kuntze/test.esp8266-ard.yaml diff --git a/tests/components/kuntze/test.rp2040.yaml b/tests/components/kuntze/test.rp2040-ard.yaml similarity index 100% rename from tests/components/kuntze/test.rp2040.yaml rename to tests/components/kuntze/test.rp2040-ard.yaml diff --git a/tests/components/lcd_gpio/test.esp32.yaml b/tests/components/lcd_gpio/test.esp32-ard.yaml similarity index 100% rename from tests/components/lcd_gpio/test.esp32.yaml rename to tests/components/lcd_gpio/test.esp32-ard.yaml diff --git a/tests/components/lcd_gpio/test.esp32-c3.yaml b/tests/components/lcd_gpio/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/lcd_gpio/test.esp32-c3.yaml rename to tests/components/lcd_gpio/test.esp32-c3-ard.yaml diff --git a/tests/components/lcd_gpio/test.esp8266.yaml b/tests/components/lcd_gpio/test.esp8266-ard.yaml similarity index 100% rename from tests/components/lcd_gpio/test.esp8266.yaml rename to tests/components/lcd_gpio/test.esp8266-ard.yaml diff --git a/tests/components/lcd_gpio/test.rp2040.yaml b/tests/components/lcd_gpio/test.rp2040-ard.yaml similarity index 100% rename from tests/components/lcd_gpio/test.rp2040.yaml rename to tests/components/lcd_gpio/test.rp2040-ard.yaml diff --git a/tests/components/lcd_menu/test.esp32.yaml b/tests/components/lcd_menu/test.esp32-ard.yaml similarity index 100% rename from tests/components/lcd_menu/test.esp32.yaml rename to tests/components/lcd_menu/test.esp32-ard.yaml diff --git a/tests/components/lcd_menu/test.esp32-c3.yaml b/tests/components/lcd_menu/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/lcd_menu/test.esp32-c3.yaml rename to tests/components/lcd_menu/test.esp32-c3-ard.yaml diff --git a/tests/components/lcd_menu/test.esp8266.yaml b/tests/components/lcd_menu/test.esp8266-ard.yaml similarity index 100% rename from tests/components/lcd_menu/test.esp8266.yaml rename to tests/components/lcd_menu/test.esp8266-ard.yaml diff --git a/tests/components/lcd_menu/test.rp2040.yaml b/tests/components/lcd_menu/test.rp2040-ard.yaml similarity index 100% rename from tests/components/lcd_menu/test.rp2040.yaml rename to tests/components/lcd_menu/test.rp2040-ard.yaml diff --git a/tests/components/lcd_pcf8574/test.esp32.yaml b/tests/components/lcd_pcf8574/test.esp32-ard.yaml similarity index 100% rename from tests/components/lcd_pcf8574/test.esp32.yaml rename to tests/components/lcd_pcf8574/test.esp32-ard.yaml diff --git a/tests/components/lcd_pcf8574/test.esp32-c3.yaml b/tests/components/lcd_pcf8574/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/lcd_pcf8574/test.esp32-c3.yaml rename to tests/components/lcd_pcf8574/test.esp32-c3-ard.yaml diff --git a/tests/components/lcd_pcf8574/test.esp8266.yaml b/tests/components/lcd_pcf8574/test.esp8266-ard.yaml similarity index 100% rename from tests/components/lcd_pcf8574/test.esp8266.yaml rename to tests/components/lcd_pcf8574/test.esp8266-ard.yaml diff --git a/tests/components/lcd_pcf8574/test.rp2040.yaml b/tests/components/lcd_pcf8574/test.rp2040-ard.yaml similarity index 100% rename from tests/components/lcd_pcf8574/test.rp2040.yaml rename to tests/components/lcd_pcf8574/test.rp2040-ard.yaml diff --git a/tests/components/ld2410/test.esp32.yaml b/tests/components/ld2410/test.esp32-ard.yaml similarity index 100% rename from tests/components/ld2410/test.esp32.yaml rename to tests/components/ld2410/test.esp32-ard.yaml diff --git a/tests/components/ld2410/test.esp32-c3.yaml b/tests/components/ld2410/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ld2410/test.esp32-c3.yaml rename to tests/components/ld2410/test.esp32-c3-ard.yaml diff --git a/tests/components/ld2410/test.esp8266.yaml b/tests/components/ld2410/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ld2410/test.esp8266.yaml rename to tests/components/ld2410/test.esp8266-ard.yaml diff --git a/tests/components/ld2410/test.rp2040.yaml b/tests/components/ld2410/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ld2410/test.rp2040.yaml rename to tests/components/ld2410/test.rp2040-ard.yaml diff --git a/tests/components/ld2420/test.esp32.yaml b/tests/components/ld2420/test.esp32-ard.yaml similarity index 100% rename from tests/components/ld2420/test.esp32.yaml rename to tests/components/ld2420/test.esp32-ard.yaml diff --git a/tests/components/ld2420/test.esp32-c3.yaml b/tests/components/ld2420/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ld2420/test.esp32-c3.yaml rename to tests/components/ld2420/test.esp32-c3-ard.yaml diff --git a/tests/components/ld2420/test.esp8266.yaml b/tests/components/ld2420/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ld2420/test.esp8266.yaml rename to tests/components/ld2420/test.esp8266-ard.yaml diff --git a/tests/components/ld2420/test.rp2040.yaml b/tests/components/ld2420/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ld2420/test.rp2040.yaml rename to tests/components/ld2420/test.rp2040-ard.yaml diff --git a/tests/components/ledc/test.esp32-c3.yaml b/tests/components/ledc/test.esp32-ard.yaml similarity index 100% rename from tests/components/ledc/test.esp32-c3.yaml rename to tests/components/ledc/test.esp32-ard.yaml diff --git a/tests/components/ledc/test.esp32.yaml b/tests/components/ledc/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ledc/test.esp32.yaml rename to tests/components/ledc/test.esp32-c3-ard.yaml diff --git a/tests/components/light/test.esp32.yaml b/tests/components/light/test.esp32-ard.yaml similarity index 100% rename from tests/components/light/test.esp32.yaml rename to tests/components/light/test.esp32-ard.yaml diff --git a/tests/components/light/test.esp32-c3.yaml b/tests/components/light/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/light/test.esp32-c3.yaml rename to tests/components/light/test.esp32-c3-ard.yaml diff --git a/tests/components/light/test.esp8266.yaml b/tests/components/light/test.esp8266-ard.yaml similarity index 100% rename from tests/components/light/test.esp8266.yaml rename to tests/components/light/test.esp8266-ard.yaml diff --git a/tests/components/light/test.rp2040.yaml b/tests/components/light/test.rp2040-ard.yaml similarity index 100% rename from tests/components/light/test.rp2040.yaml rename to tests/components/light/test.rp2040-ard.yaml diff --git a/tests/components/lightwaverf/test.esp8266.yaml b/tests/components/lightwaverf/test.esp8266-ard.yaml similarity index 100% rename from tests/components/lightwaverf/test.esp8266.yaml rename to tests/components/lightwaverf/test.esp8266-ard.yaml diff --git a/tests/components/lilygo_t5_47/test.esp32.yaml b/tests/components/lilygo_t5_47/test.esp32-ard.yaml similarity index 100% rename from tests/components/lilygo_t5_47/test.esp32.yaml rename to tests/components/lilygo_t5_47/test.esp32-ard.yaml diff --git a/tests/components/lilygo_t5_47/test.esp32-c3.yaml b/tests/components/lilygo_t5_47/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/lilygo_t5_47/test.esp32-c3.yaml rename to tests/components/lilygo_t5_47/test.esp32-c3-ard.yaml diff --git a/tests/components/lilygo_t5_47/test.esp8266.yaml b/tests/components/lilygo_t5_47/test.esp8266-ard.yaml similarity index 100% rename from tests/components/lilygo_t5_47/test.esp8266.yaml rename to tests/components/lilygo_t5_47/test.esp8266-ard.yaml diff --git a/tests/components/lilygo_t5_47/test.rp2040.yaml b/tests/components/lilygo_t5_47/test.rp2040-ard.yaml similarity index 100% rename from tests/components/lilygo_t5_47/test.rp2040.yaml rename to tests/components/lilygo_t5_47/test.rp2040-ard.yaml diff --git a/tests/components/lock/test.esp32-c3.yaml b/tests/components/lock/test.esp32-ard.yaml similarity index 100% rename from tests/components/lock/test.esp32-c3.yaml rename to tests/components/lock/test.esp32-ard.yaml diff --git a/tests/components/lock/test.esp32.yaml b/tests/components/lock/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/lock/test.esp32.yaml rename to tests/components/lock/test.esp32-c3-ard.yaml diff --git a/tests/components/lock/test.esp8266.yaml b/tests/components/lock/test.esp8266-ard.yaml similarity index 100% rename from tests/components/lock/test.esp8266.yaml rename to tests/components/lock/test.esp8266-ard.yaml diff --git a/tests/components/lock/test.rp2040.yaml b/tests/components/lock/test.rp2040-ard.yaml similarity index 100% rename from tests/components/lock/test.rp2040.yaml rename to tests/components/lock/test.rp2040-ard.yaml diff --git a/tests/components/logger/test.esp32-c3.yaml b/tests/components/logger/test.esp32-ard.yaml similarity index 100% rename from tests/components/logger/test.esp32-c3.yaml rename to tests/components/logger/test.esp32-ard.yaml diff --git a/tests/components/logger/test.esp32.yaml b/tests/components/logger/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/logger/test.esp32.yaml rename to tests/components/logger/test.esp32-c3-ard.yaml diff --git a/tests/components/logger/test.esp8266.yaml b/tests/components/logger/test.esp8266-ard.yaml similarity index 100% rename from tests/components/logger/test.esp8266.yaml rename to tests/components/logger/test.esp8266-ard.yaml diff --git a/tests/components/logger/test.rp2040.yaml b/tests/components/logger/test.rp2040-ard.yaml similarity index 100% rename from tests/components/logger/test.rp2040.yaml rename to tests/components/logger/test.rp2040-ard.yaml diff --git a/tests/components/ltr390/test.esp32.yaml b/tests/components/ltr390/test.esp32-ard.yaml similarity index 100% rename from tests/components/ltr390/test.esp32.yaml rename to tests/components/ltr390/test.esp32-ard.yaml diff --git a/tests/components/ltr390/test.esp32-c3.yaml b/tests/components/ltr390/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ltr390/test.esp32-c3.yaml rename to tests/components/ltr390/test.esp32-c3-ard.yaml diff --git a/tests/components/ltr390/test.esp8266.yaml b/tests/components/ltr390/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ltr390/test.esp8266.yaml rename to tests/components/ltr390/test.esp8266-ard.yaml diff --git a/tests/components/ltr390/test.rp2040.yaml b/tests/components/ltr390/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ltr390/test.rp2040.yaml rename to tests/components/ltr390/test.rp2040-ard.yaml diff --git a/tests/components/ltr_als_ps/test.esp32.yaml b/tests/components/ltr_als_ps/test.esp32-ard.yaml similarity index 100% rename from tests/components/ltr_als_ps/test.esp32.yaml rename to tests/components/ltr_als_ps/test.esp32-ard.yaml diff --git a/tests/components/ltr_als_ps/test.esp32-c3.yaml b/tests/components/ltr_als_ps/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ltr_als_ps/test.esp32-c3.yaml rename to tests/components/ltr_als_ps/test.esp32-c3-ard.yaml diff --git a/tests/components/ltr_als_ps/test.esp8266.yaml b/tests/components/ltr_als_ps/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ltr_als_ps/test.esp8266.yaml rename to tests/components/ltr_als_ps/test.esp8266-ard.yaml diff --git a/tests/components/ltr_als_ps/test.rp2040.yaml b/tests/components/ltr_als_ps/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ltr_als_ps/test.rp2040.yaml rename to tests/components/ltr_als_ps/test.rp2040-ard.yaml diff --git a/tests/components/matrix_keypad/test.esp32.yaml b/tests/components/matrix_keypad/test.esp32-ard.yaml similarity index 100% rename from tests/components/matrix_keypad/test.esp32.yaml rename to tests/components/matrix_keypad/test.esp32-ard.yaml diff --git a/tests/components/matrix_keypad/test.esp32-c3.yaml b/tests/components/matrix_keypad/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/matrix_keypad/test.esp32-c3.yaml rename to tests/components/matrix_keypad/test.esp32-c3-ard.yaml diff --git a/tests/components/matrix_keypad/test.esp8266.yaml b/tests/components/matrix_keypad/test.esp8266-ard.yaml similarity index 100% rename from tests/components/matrix_keypad/test.esp8266.yaml rename to tests/components/matrix_keypad/test.esp8266-ard.yaml diff --git a/tests/components/matrix_keypad/test.rp2040.yaml b/tests/components/matrix_keypad/test.rp2040-ard.yaml similarity index 100% rename from tests/components/matrix_keypad/test.rp2040.yaml rename to tests/components/matrix_keypad/test.rp2040-ard.yaml diff --git a/tests/components/max31855/test.esp32.yaml b/tests/components/max31855/test.esp32-ard.yaml similarity index 100% rename from tests/components/max31855/test.esp32.yaml rename to tests/components/max31855/test.esp32-ard.yaml diff --git a/tests/components/max31855/test.esp32-c3.yaml b/tests/components/max31855/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/max31855/test.esp32-c3.yaml rename to tests/components/max31855/test.esp32-c3-ard.yaml diff --git a/tests/components/max31855/test.esp8266.yaml b/tests/components/max31855/test.esp8266-ard.yaml similarity index 100% rename from tests/components/max31855/test.esp8266.yaml rename to tests/components/max31855/test.esp8266-ard.yaml diff --git a/tests/components/max31855/test.rp2040.yaml b/tests/components/max31855/test.rp2040-ard.yaml similarity index 100% rename from tests/components/max31855/test.rp2040.yaml rename to tests/components/max31855/test.rp2040-ard.yaml diff --git a/tests/components/max31856/test.esp32.yaml b/tests/components/max31856/test.esp32-ard.yaml similarity index 100% rename from tests/components/max31856/test.esp32.yaml rename to tests/components/max31856/test.esp32-ard.yaml diff --git a/tests/components/max31856/test.esp32-c3.yaml b/tests/components/max31856/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/max31856/test.esp32-c3.yaml rename to tests/components/max31856/test.esp32-c3-ard.yaml diff --git a/tests/components/max31856/test.esp8266.yaml b/tests/components/max31856/test.esp8266-ard.yaml similarity index 100% rename from tests/components/max31856/test.esp8266.yaml rename to tests/components/max31856/test.esp8266-ard.yaml diff --git a/tests/components/max31856/test.rp2040.yaml b/tests/components/max31856/test.rp2040-ard.yaml similarity index 100% rename from tests/components/max31856/test.rp2040.yaml rename to tests/components/max31856/test.rp2040-ard.yaml diff --git a/tests/components/max31865/test.esp32.yaml b/tests/components/max31865/test.esp32-ard.yaml similarity index 100% rename from tests/components/max31865/test.esp32.yaml rename to tests/components/max31865/test.esp32-ard.yaml diff --git a/tests/components/max31865/test.esp32-c3.yaml b/tests/components/max31865/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/max31865/test.esp32-c3.yaml rename to tests/components/max31865/test.esp32-c3-ard.yaml diff --git a/tests/components/max31865/test.esp8266.yaml b/tests/components/max31865/test.esp8266-ard.yaml similarity index 100% rename from tests/components/max31865/test.esp8266.yaml rename to tests/components/max31865/test.esp8266-ard.yaml diff --git a/tests/components/max31865/test.rp2040.yaml b/tests/components/max31865/test.rp2040-ard.yaml similarity index 100% rename from tests/components/max31865/test.rp2040.yaml rename to tests/components/max31865/test.rp2040-ard.yaml diff --git a/tests/components/max44009/test.esp32.yaml b/tests/components/max44009/test.esp32-ard.yaml similarity index 100% rename from tests/components/max44009/test.esp32.yaml rename to tests/components/max44009/test.esp32-ard.yaml diff --git a/tests/components/max44009/test.esp32-c3.yaml b/tests/components/max44009/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/max44009/test.esp32-c3.yaml rename to tests/components/max44009/test.esp32-c3-ard.yaml diff --git a/tests/components/max44009/test.esp8266.yaml b/tests/components/max44009/test.esp8266-ard.yaml similarity index 100% rename from tests/components/max44009/test.esp8266.yaml rename to tests/components/max44009/test.esp8266-ard.yaml diff --git a/tests/components/max44009/test.rp2040.yaml b/tests/components/max44009/test.rp2040-ard.yaml similarity index 100% rename from tests/components/max44009/test.rp2040.yaml rename to tests/components/max44009/test.rp2040-ard.yaml diff --git a/tests/components/max6675/test.esp32.yaml b/tests/components/max6675/test.esp32-ard.yaml similarity index 100% rename from tests/components/max6675/test.esp32.yaml rename to tests/components/max6675/test.esp32-ard.yaml diff --git a/tests/components/max6675/test.esp32-c3.yaml b/tests/components/max6675/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/max6675/test.esp32-c3.yaml rename to tests/components/max6675/test.esp32-c3-ard.yaml diff --git a/tests/components/max6675/test.esp8266.yaml b/tests/components/max6675/test.esp8266-ard.yaml similarity index 100% rename from tests/components/max6675/test.esp8266.yaml rename to tests/components/max6675/test.esp8266-ard.yaml diff --git a/tests/components/max6675/test.rp2040.yaml b/tests/components/max6675/test.rp2040-ard.yaml similarity index 100% rename from tests/components/max6675/test.rp2040.yaml rename to tests/components/max6675/test.rp2040-ard.yaml diff --git a/tests/components/max6956/test.esp32.yaml b/tests/components/max6956/test.esp32-ard.yaml similarity index 100% rename from tests/components/max6956/test.esp32.yaml rename to tests/components/max6956/test.esp32-ard.yaml diff --git a/tests/components/max6956/test.esp32-c3.yaml b/tests/components/max6956/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/max6956/test.esp32-c3.yaml rename to tests/components/max6956/test.esp32-c3-ard.yaml diff --git a/tests/components/max6956/test.esp8266.yaml b/tests/components/max6956/test.esp8266-ard.yaml similarity index 100% rename from tests/components/max6956/test.esp8266.yaml rename to tests/components/max6956/test.esp8266-ard.yaml diff --git a/tests/components/max6956/test.rp2040.yaml b/tests/components/max6956/test.rp2040-ard.yaml similarity index 100% rename from tests/components/max6956/test.rp2040.yaml rename to tests/components/max6956/test.rp2040-ard.yaml diff --git a/tests/components/max7219/test.esp32.yaml b/tests/components/max7219/test.esp32-ard.yaml similarity index 100% rename from tests/components/max7219/test.esp32.yaml rename to tests/components/max7219/test.esp32-ard.yaml diff --git a/tests/components/max7219/test.esp32-c3.yaml b/tests/components/max7219/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/max7219/test.esp32-c3.yaml rename to tests/components/max7219/test.esp32-c3-ard.yaml diff --git a/tests/components/max7219/test.esp8266.yaml b/tests/components/max7219/test.esp8266-ard.yaml similarity index 100% rename from tests/components/max7219/test.esp8266.yaml rename to tests/components/max7219/test.esp8266-ard.yaml diff --git a/tests/components/max7219/test.rp2040.yaml b/tests/components/max7219/test.rp2040-ard.yaml similarity index 100% rename from tests/components/max7219/test.rp2040.yaml rename to tests/components/max7219/test.rp2040-ard.yaml diff --git a/tests/components/max7219digit/test.esp32.yaml b/tests/components/max7219digit/test.esp32-ard.yaml similarity index 100% rename from tests/components/max7219digit/test.esp32.yaml rename to tests/components/max7219digit/test.esp32-ard.yaml diff --git a/tests/components/max7219digit/test.esp32-c3.yaml b/tests/components/max7219digit/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/max7219digit/test.esp32-c3.yaml rename to tests/components/max7219digit/test.esp32-c3-ard.yaml diff --git a/tests/components/max7219digit/test.esp8266.yaml b/tests/components/max7219digit/test.esp8266-ard.yaml similarity index 100% rename from tests/components/max7219digit/test.esp8266.yaml rename to tests/components/max7219digit/test.esp8266-ard.yaml diff --git a/tests/components/max7219digit/test.rp2040.yaml b/tests/components/max7219digit/test.rp2040-ard.yaml similarity index 100% rename from tests/components/max7219digit/test.rp2040.yaml rename to tests/components/max7219digit/test.rp2040-ard.yaml diff --git a/tests/components/max9611/test.esp32.yaml b/tests/components/max9611/test.esp32-ard.yaml similarity index 100% rename from tests/components/max9611/test.esp32.yaml rename to tests/components/max9611/test.esp32-ard.yaml diff --git a/tests/components/max9611/test.esp32-c3.yaml b/tests/components/max9611/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/max9611/test.esp32-c3.yaml rename to tests/components/max9611/test.esp32-c3-ard.yaml diff --git a/tests/components/max9611/test.esp8266.yaml b/tests/components/max9611/test.esp8266-ard.yaml similarity index 100% rename from tests/components/max9611/test.esp8266.yaml rename to tests/components/max9611/test.esp8266-ard.yaml diff --git a/tests/components/max9611/test.rp2040.yaml b/tests/components/max9611/test.rp2040-ard.yaml similarity index 100% rename from tests/components/max9611/test.rp2040.yaml rename to tests/components/max9611/test.rp2040-ard.yaml diff --git a/tests/components/mcp23008/test.esp32.yaml b/tests/components/mcp23008/test.esp32-ard.yaml similarity index 100% rename from tests/components/mcp23008/test.esp32.yaml rename to tests/components/mcp23008/test.esp32-ard.yaml diff --git a/tests/components/mcp23008/test.esp32-c3.yaml b/tests/components/mcp23008/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/mcp23008/test.esp32-c3.yaml rename to tests/components/mcp23008/test.esp32-c3-ard.yaml diff --git a/tests/components/mcp23008/test.esp8266.yaml b/tests/components/mcp23008/test.esp8266-ard.yaml similarity index 100% rename from tests/components/mcp23008/test.esp8266.yaml rename to tests/components/mcp23008/test.esp8266-ard.yaml diff --git a/tests/components/mcp23008/test.rp2040.yaml b/tests/components/mcp23008/test.rp2040-ard.yaml similarity index 100% rename from tests/components/mcp23008/test.rp2040.yaml rename to tests/components/mcp23008/test.rp2040-ard.yaml diff --git a/tests/components/mcp23016/test.esp32.yaml b/tests/components/mcp23016/test.esp32-ard.yaml similarity index 100% rename from tests/components/mcp23016/test.esp32.yaml rename to tests/components/mcp23016/test.esp32-ard.yaml diff --git a/tests/components/mcp23016/test.esp32-c3.yaml b/tests/components/mcp23016/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/mcp23016/test.esp32-c3.yaml rename to tests/components/mcp23016/test.esp32-c3-ard.yaml diff --git a/tests/components/mcp23016/test.esp8266.yaml b/tests/components/mcp23016/test.esp8266-ard.yaml similarity index 100% rename from tests/components/mcp23016/test.esp8266.yaml rename to tests/components/mcp23016/test.esp8266-ard.yaml diff --git a/tests/components/mcp23016/test.rp2040.yaml b/tests/components/mcp23016/test.rp2040-ard.yaml similarity index 100% rename from tests/components/mcp23016/test.rp2040.yaml rename to tests/components/mcp23016/test.rp2040-ard.yaml diff --git a/tests/components/mcp23017/test.esp32.yaml b/tests/components/mcp23017/test.esp32-ard.yaml similarity index 100% rename from tests/components/mcp23017/test.esp32.yaml rename to tests/components/mcp23017/test.esp32-ard.yaml diff --git a/tests/components/mcp23017/test.esp32-c3.yaml b/tests/components/mcp23017/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/mcp23017/test.esp32-c3.yaml rename to tests/components/mcp23017/test.esp32-c3-ard.yaml diff --git a/tests/components/mcp23017/test.esp8266.yaml b/tests/components/mcp23017/test.esp8266-ard.yaml similarity index 100% rename from tests/components/mcp23017/test.esp8266.yaml rename to tests/components/mcp23017/test.esp8266-ard.yaml diff --git a/tests/components/mcp23017/test.rp2040.yaml b/tests/components/mcp23017/test.rp2040-ard.yaml similarity index 100% rename from tests/components/mcp23017/test.rp2040.yaml rename to tests/components/mcp23017/test.rp2040-ard.yaml diff --git a/tests/components/mcp23s08/test.esp32.yaml b/tests/components/mcp23s08/test.esp32-ard.yaml similarity index 100% rename from tests/components/mcp23s08/test.esp32.yaml rename to tests/components/mcp23s08/test.esp32-ard.yaml diff --git a/tests/components/mcp23s08/test.esp32-c3.yaml b/tests/components/mcp23s08/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/mcp23s08/test.esp32-c3.yaml rename to tests/components/mcp23s08/test.esp32-c3-ard.yaml diff --git a/tests/components/mcp23s08/test.esp8266.yaml b/tests/components/mcp23s08/test.esp8266-ard.yaml similarity index 100% rename from tests/components/mcp23s08/test.esp8266.yaml rename to tests/components/mcp23s08/test.esp8266-ard.yaml diff --git a/tests/components/mcp23s08/test.rp2040.yaml b/tests/components/mcp23s08/test.rp2040-ard.yaml similarity index 100% rename from tests/components/mcp23s08/test.rp2040.yaml rename to tests/components/mcp23s08/test.rp2040-ard.yaml diff --git a/tests/components/mcp23s17/test.esp32.yaml b/tests/components/mcp23s17/test.esp32-ard.yaml similarity index 100% rename from tests/components/mcp23s17/test.esp32.yaml rename to tests/components/mcp23s17/test.esp32-ard.yaml diff --git a/tests/components/mcp23s17/test.esp32-c3.yaml b/tests/components/mcp23s17/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/mcp23s17/test.esp32-c3.yaml rename to tests/components/mcp23s17/test.esp32-c3-ard.yaml diff --git a/tests/components/mcp23s17/test.esp8266.yaml b/tests/components/mcp23s17/test.esp8266-ard.yaml similarity index 100% rename from tests/components/mcp23s17/test.esp8266.yaml rename to tests/components/mcp23s17/test.esp8266-ard.yaml diff --git a/tests/components/mcp23s17/test.rp2040.yaml b/tests/components/mcp23s17/test.rp2040-ard.yaml similarity index 100% rename from tests/components/mcp23s17/test.rp2040.yaml rename to tests/components/mcp23s17/test.rp2040-ard.yaml diff --git a/tests/components/mcp2515/test.esp32.yaml b/tests/components/mcp2515/test.esp32-ard.yaml similarity index 100% rename from tests/components/mcp2515/test.esp32.yaml rename to tests/components/mcp2515/test.esp32-ard.yaml diff --git a/tests/components/mcp2515/test.esp32-c3.yaml b/tests/components/mcp2515/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/mcp2515/test.esp32-c3.yaml rename to tests/components/mcp2515/test.esp32-c3-ard.yaml diff --git a/tests/components/mcp2515/test.esp8266.yaml b/tests/components/mcp2515/test.esp8266-ard.yaml similarity index 100% rename from tests/components/mcp2515/test.esp8266.yaml rename to tests/components/mcp2515/test.esp8266-ard.yaml diff --git a/tests/components/mcp2515/test.rp2040.yaml b/tests/components/mcp2515/test.rp2040-ard.yaml similarity index 100% rename from tests/components/mcp2515/test.rp2040.yaml rename to tests/components/mcp2515/test.rp2040-ard.yaml diff --git a/tests/components/mcp3008/test.esp32.yaml b/tests/components/mcp3008/test.esp32-ard.yaml similarity index 100% rename from tests/components/mcp3008/test.esp32.yaml rename to tests/components/mcp3008/test.esp32-ard.yaml diff --git a/tests/components/mcp3008/test.esp32-c3.yaml b/tests/components/mcp3008/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/mcp3008/test.esp32-c3.yaml rename to tests/components/mcp3008/test.esp32-c3-ard.yaml diff --git a/tests/components/mcp3008/test.esp8266.yaml b/tests/components/mcp3008/test.esp8266-ard.yaml similarity index 100% rename from tests/components/mcp3008/test.esp8266.yaml rename to tests/components/mcp3008/test.esp8266-ard.yaml diff --git a/tests/components/mcp3008/test.rp2040.yaml b/tests/components/mcp3008/test.rp2040-ard.yaml similarity index 100% rename from tests/components/mcp3008/test.rp2040.yaml rename to tests/components/mcp3008/test.rp2040-ard.yaml diff --git a/tests/components/mcp3204/test.esp32.yaml b/tests/components/mcp3204/test.esp32-ard.yaml similarity index 100% rename from tests/components/mcp3204/test.esp32.yaml rename to tests/components/mcp3204/test.esp32-ard.yaml diff --git a/tests/components/mcp3204/test.esp32-c3.yaml b/tests/components/mcp3204/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/mcp3204/test.esp32-c3.yaml rename to tests/components/mcp3204/test.esp32-c3-ard.yaml diff --git a/tests/components/mcp3204/test.esp8266.yaml b/tests/components/mcp3204/test.esp8266-ard.yaml similarity index 100% rename from tests/components/mcp3204/test.esp8266.yaml rename to tests/components/mcp3204/test.esp8266-ard.yaml diff --git a/tests/components/mcp3204/test.rp2040.yaml b/tests/components/mcp3204/test.rp2040-ard.yaml similarity index 100% rename from tests/components/mcp3204/test.rp2040.yaml rename to tests/components/mcp3204/test.rp2040-ard.yaml diff --git a/tests/components/mcp4725/test.esp32.yaml b/tests/components/mcp4725/test.esp32-ard.yaml similarity index 100% rename from tests/components/mcp4725/test.esp32.yaml rename to tests/components/mcp4725/test.esp32-ard.yaml diff --git a/tests/components/mcp4725/test.esp32-c3.yaml b/tests/components/mcp4725/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/mcp4725/test.esp32-c3.yaml rename to tests/components/mcp4725/test.esp32-c3-ard.yaml diff --git a/tests/components/mcp4725/test.esp8266.yaml b/tests/components/mcp4725/test.esp8266-ard.yaml similarity index 100% rename from tests/components/mcp4725/test.esp8266.yaml rename to tests/components/mcp4725/test.esp8266-ard.yaml diff --git a/tests/components/mcp4725/test.rp2040.yaml b/tests/components/mcp4725/test.rp2040-ard.yaml similarity index 100% rename from tests/components/mcp4725/test.rp2040.yaml rename to tests/components/mcp4725/test.rp2040-ard.yaml diff --git a/tests/components/mcp4728/test.esp32.yaml b/tests/components/mcp4728/test.esp32-ard.yaml similarity index 100% rename from tests/components/mcp4728/test.esp32.yaml rename to tests/components/mcp4728/test.esp32-ard.yaml diff --git a/tests/components/mcp4728/test.esp32-c3.yaml b/tests/components/mcp4728/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/mcp4728/test.esp32-c3.yaml rename to tests/components/mcp4728/test.esp32-c3-ard.yaml diff --git a/tests/components/mcp4728/test.esp8266.yaml b/tests/components/mcp4728/test.esp8266-ard.yaml similarity index 100% rename from tests/components/mcp4728/test.esp8266.yaml rename to tests/components/mcp4728/test.esp8266-ard.yaml diff --git a/tests/components/mcp4728/test.rp2040.yaml b/tests/components/mcp4728/test.rp2040-ard.yaml similarity index 100% rename from tests/components/mcp4728/test.rp2040.yaml rename to tests/components/mcp4728/test.rp2040-ard.yaml diff --git a/tests/components/mcp47a1/test.esp32.yaml b/tests/components/mcp47a1/test.esp32-ard.yaml similarity index 100% rename from tests/components/mcp47a1/test.esp32.yaml rename to tests/components/mcp47a1/test.esp32-ard.yaml diff --git a/tests/components/mcp47a1/test.esp32-c3.yaml b/tests/components/mcp47a1/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/mcp47a1/test.esp32-c3.yaml rename to tests/components/mcp47a1/test.esp32-c3-ard.yaml diff --git a/tests/components/mcp47a1/test.esp8266.yaml b/tests/components/mcp47a1/test.esp8266-ard.yaml similarity index 100% rename from tests/components/mcp47a1/test.esp8266.yaml rename to tests/components/mcp47a1/test.esp8266-ard.yaml diff --git a/tests/components/mcp47a1/test.rp2040.yaml b/tests/components/mcp47a1/test.rp2040-ard.yaml similarity index 100% rename from tests/components/mcp47a1/test.rp2040.yaml rename to tests/components/mcp47a1/test.rp2040-ard.yaml diff --git a/tests/components/mcp9600/test.esp32.yaml b/tests/components/mcp9600/test.esp32-ard.yaml similarity index 100% rename from tests/components/mcp9600/test.esp32.yaml rename to tests/components/mcp9600/test.esp32-ard.yaml diff --git a/tests/components/mcp9600/test.esp32-c3.yaml b/tests/components/mcp9600/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/mcp9600/test.esp32-c3.yaml rename to tests/components/mcp9600/test.esp32-c3-ard.yaml diff --git a/tests/components/mcp9600/test.esp8266.yaml b/tests/components/mcp9600/test.esp8266-ard.yaml similarity index 100% rename from tests/components/mcp9600/test.esp8266.yaml rename to tests/components/mcp9600/test.esp8266-ard.yaml diff --git a/tests/components/mcp9600/test.rp2040.yaml b/tests/components/mcp9600/test.rp2040-ard.yaml similarity index 100% rename from tests/components/mcp9600/test.rp2040.yaml rename to tests/components/mcp9600/test.rp2040-ard.yaml diff --git a/tests/components/mcp9808/test.esp32.yaml b/tests/components/mcp9808/test.esp32-ard.yaml similarity index 100% rename from tests/components/mcp9808/test.esp32.yaml rename to tests/components/mcp9808/test.esp32-ard.yaml diff --git a/tests/components/mcp9808/test.esp32-c3.yaml b/tests/components/mcp9808/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/mcp9808/test.esp32-c3.yaml rename to tests/components/mcp9808/test.esp32-c3-ard.yaml diff --git a/tests/components/mcp9808/test.esp8266.yaml b/tests/components/mcp9808/test.esp8266-ard.yaml similarity index 100% rename from tests/components/mcp9808/test.esp8266.yaml rename to tests/components/mcp9808/test.esp8266-ard.yaml diff --git a/tests/components/mcp9808/test.rp2040.yaml b/tests/components/mcp9808/test.rp2040-ard.yaml similarity index 100% rename from tests/components/mcp9808/test.rp2040.yaml rename to tests/components/mcp9808/test.rp2040-ard.yaml diff --git a/tests/components/mdns/test.esp32-c3.yaml b/tests/components/mdns/test.esp32-ard.yaml similarity index 100% rename from tests/components/mdns/test.esp32-c3.yaml rename to tests/components/mdns/test.esp32-ard.yaml diff --git a/tests/components/mdns/test.esp32.yaml b/tests/components/mdns/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/mdns/test.esp32.yaml rename to tests/components/mdns/test.esp32-c3-ard.yaml diff --git a/tests/components/mdns/test.esp8266.yaml b/tests/components/mdns/test.esp8266-ard.yaml similarity index 100% rename from tests/components/mdns/test.esp8266.yaml rename to tests/components/mdns/test.esp8266-ard.yaml diff --git a/tests/components/mdns/test.rp2040.yaml b/tests/components/mdns/test.rp2040-ard.yaml similarity index 100% rename from tests/components/mdns/test.rp2040.yaml rename to tests/components/mdns/test.rp2040-ard.yaml diff --git a/tests/components/media_player/test.esp32.yaml b/tests/components/media_player/test.esp32-ard.yaml similarity index 100% rename from tests/components/media_player/test.esp32.yaml rename to tests/components/media_player/test.esp32-ard.yaml diff --git a/tests/components/mhz19/test.esp32.yaml b/tests/components/mhz19/test.esp32-ard.yaml similarity index 100% rename from tests/components/mhz19/test.esp32.yaml rename to tests/components/mhz19/test.esp32-ard.yaml diff --git a/tests/components/mhz19/test.esp32-c3.yaml b/tests/components/mhz19/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/mhz19/test.esp32-c3.yaml rename to tests/components/mhz19/test.esp32-c3-ard.yaml diff --git a/tests/components/mhz19/test.esp8266.yaml b/tests/components/mhz19/test.esp8266-ard.yaml similarity index 100% rename from tests/components/mhz19/test.esp8266.yaml rename to tests/components/mhz19/test.esp8266-ard.yaml diff --git a/tests/components/mhz19/test.rp2040.yaml b/tests/components/mhz19/test.rp2040-ard.yaml similarity index 100% rename from tests/components/mhz19/test.rp2040.yaml rename to tests/components/mhz19/test.rp2040-ard.yaml diff --git a/tests/components/micronova/test.esp32.yaml b/tests/components/micronova/test.esp32-ard.yaml similarity index 100% rename from tests/components/micronova/test.esp32.yaml rename to tests/components/micronova/test.esp32-ard.yaml diff --git a/tests/components/micronova/test.esp32-c3.yaml b/tests/components/micronova/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/micronova/test.esp32-c3.yaml rename to tests/components/micronova/test.esp32-c3-ard.yaml diff --git a/tests/components/micronova/test.esp8266.yaml b/tests/components/micronova/test.esp8266-ard.yaml similarity index 100% rename from tests/components/micronova/test.esp8266.yaml rename to tests/components/micronova/test.esp8266-ard.yaml diff --git a/tests/components/micronova/test.rp2040.yaml b/tests/components/micronova/test.rp2040-ard.yaml similarity index 100% rename from tests/components/micronova/test.rp2040.yaml rename to tests/components/micronova/test.rp2040-ard.yaml diff --git a/tests/components/microphone/test.esp32.yaml b/tests/components/microphone/test.esp32-ard.yaml similarity index 100% rename from tests/components/microphone/test.esp32.yaml rename to tests/components/microphone/test.esp32-ard.yaml diff --git a/tests/components/microphone/test.esp32-c3.yaml b/tests/components/microphone/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/microphone/test.esp32-c3.yaml rename to tests/components/microphone/test.esp32-c3-ard.yaml diff --git a/tests/components/mics_4514/test.esp32.yaml b/tests/components/mics_4514/test.esp32-ard.yaml similarity index 100% rename from tests/components/mics_4514/test.esp32.yaml rename to tests/components/mics_4514/test.esp32-ard.yaml diff --git a/tests/components/mics_4514/test.esp32-c3.yaml b/tests/components/mics_4514/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/mics_4514/test.esp32-c3.yaml rename to tests/components/mics_4514/test.esp32-c3-ard.yaml diff --git a/tests/components/mics_4514/test.esp8266.yaml b/tests/components/mics_4514/test.esp8266-ard.yaml similarity index 100% rename from tests/components/mics_4514/test.esp8266.yaml rename to tests/components/mics_4514/test.esp8266-ard.yaml diff --git a/tests/components/mics_4514/test.rp2040.yaml b/tests/components/mics_4514/test.rp2040-ard.yaml similarity index 100% rename from tests/components/mics_4514/test.rp2040.yaml rename to tests/components/mics_4514/test.rp2040-ard.yaml diff --git a/tests/components/midea/test.esp32.yaml b/tests/components/midea/test.esp32-ard.yaml similarity index 100% rename from tests/components/midea/test.esp32.yaml rename to tests/components/midea/test.esp32-ard.yaml diff --git a/tests/components/midea/test.esp32-c3.yaml b/tests/components/midea/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/midea/test.esp32-c3.yaml rename to tests/components/midea/test.esp32-c3-ard.yaml diff --git a/tests/components/midea/test.esp8266.yaml b/tests/components/midea/test.esp8266-ard.yaml similarity index 100% rename from tests/components/midea/test.esp8266.yaml rename to tests/components/midea/test.esp8266-ard.yaml diff --git a/tests/components/midea_ir/test.esp32-c3.yaml b/tests/components/midea_ir/test.esp32-ard.yaml similarity index 100% rename from tests/components/midea_ir/test.esp32-c3.yaml rename to tests/components/midea_ir/test.esp32-ard.yaml diff --git a/tests/components/midea_ir/test.esp32.yaml b/tests/components/midea_ir/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/midea_ir/test.esp32.yaml rename to tests/components/midea_ir/test.esp32-c3-ard.yaml diff --git a/tests/components/midea_ir/test.esp8266.yaml b/tests/components/midea_ir/test.esp8266-ard.yaml similarity index 100% rename from tests/components/midea_ir/test.esp8266.yaml rename to tests/components/midea_ir/test.esp8266-ard.yaml diff --git a/tests/components/mitsubishi/test.esp32-c3.yaml b/tests/components/mitsubishi/test.esp32-ard.yaml similarity index 100% rename from tests/components/mitsubishi/test.esp32-c3.yaml rename to tests/components/mitsubishi/test.esp32-ard.yaml diff --git a/tests/components/mitsubishi/test.esp32.yaml b/tests/components/mitsubishi/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/mitsubishi/test.esp32.yaml rename to tests/components/mitsubishi/test.esp32-c3-ard.yaml diff --git a/tests/components/mitsubishi/test.esp8266.yaml b/tests/components/mitsubishi/test.esp8266-ard.yaml similarity index 100% rename from tests/components/mitsubishi/test.esp8266.yaml rename to tests/components/mitsubishi/test.esp8266-ard.yaml diff --git a/tests/components/mlx90393/test.esp32.yaml b/tests/components/mlx90393/test.esp32-ard.yaml similarity index 100% rename from tests/components/mlx90393/test.esp32.yaml rename to tests/components/mlx90393/test.esp32-ard.yaml diff --git a/tests/components/mlx90393/test.esp32-c3.yaml b/tests/components/mlx90393/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/mlx90393/test.esp32-c3.yaml rename to tests/components/mlx90393/test.esp32-c3-ard.yaml diff --git a/tests/components/mlx90393/test.esp8266.yaml b/tests/components/mlx90393/test.esp8266-ard.yaml similarity index 100% rename from tests/components/mlx90393/test.esp8266.yaml rename to tests/components/mlx90393/test.esp8266-ard.yaml diff --git a/tests/components/mlx90393/test.rp2040.yaml b/tests/components/mlx90393/test.rp2040-ard.yaml similarity index 100% rename from tests/components/mlx90393/test.rp2040.yaml rename to tests/components/mlx90393/test.rp2040-ard.yaml diff --git a/tests/components/mlx90614/test.esp32.yaml b/tests/components/mlx90614/test.esp32-ard.yaml similarity index 100% rename from tests/components/mlx90614/test.esp32.yaml rename to tests/components/mlx90614/test.esp32-ard.yaml diff --git a/tests/components/mlx90614/test.esp32-c3.yaml b/tests/components/mlx90614/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/mlx90614/test.esp32-c3.yaml rename to tests/components/mlx90614/test.esp32-c3-ard.yaml diff --git a/tests/components/mlx90614/test.esp8266.yaml b/tests/components/mlx90614/test.esp8266-ard.yaml similarity index 100% rename from tests/components/mlx90614/test.esp8266.yaml rename to tests/components/mlx90614/test.esp8266-ard.yaml diff --git a/tests/components/mlx90614/test.rp2040.yaml b/tests/components/mlx90614/test.rp2040-ard.yaml similarity index 100% rename from tests/components/mlx90614/test.rp2040.yaml rename to tests/components/mlx90614/test.rp2040-ard.yaml diff --git a/tests/components/mmc5603/test.esp32.yaml b/tests/components/mmc5603/test.esp32-ard.yaml similarity index 100% rename from tests/components/mmc5603/test.esp32.yaml rename to tests/components/mmc5603/test.esp32-ard.yaml diff --git a/tests/components/mmc5603/test.esp32-c3.yaml b/tests/components/mmc5603/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/mmc5603/test.esp32-c3.yaml rename to tests/components/mmc5603/test.esp32-c3-ard.yaml diff --git a/tests/components/mmc5603/test.esp8266.yaml b/tests/components/mmc5603/test.esp8266-ard.yaml similarity index 100% rename from tests/components/mmc5603/test.esp8266.yaml rename to tests/components/mmc5603/test.esp8266-ard.yaml diff --git a/tests/components/mmc5603/test.rp2040.yaml b/tests/components/mmc5603/test.rp2040-ard.yaml similarity index 100% rename from tests/components/mmc5603/test.rp2040.yaml rename to tests/components/mmc5603/test.rp2040-ard.yaml diff --git a/tests/components/mmc5983/test.esp32.yaml b/tests/components/mmc5983/test.esp32-ard.yaml similarity index 100% rename from tests/components/mmc5983/test.esp32.yaml rename to tests/components/mmc5983/test.esp32-ard.yaml diff --git a/tests/components/mmc5983/test.esp32-c3.yaml b/tests/components/mmc5983/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/mmc5983/test.esp32-c3.yaml rename to tests/components/mmc5983/test.esp32-c3-ard.yaml diff --git a/tests/components/mmc5983/test.esp8266.yaml b/tests/components/mmc5983/test.esp8266-ard.yaml similarity index 100% rename from tests/components/mmc5983/test.esp8266.yaml rename to tests/components/mmc5983/test.esp8266-ard.yaml diff --git a/tests/components/mmc5983/test.rp2040.yaml b/tests/components/mmc5983/test.rp2040-ard.yaml similarity index 100% rename from tests/components/mmc5983/test.rp2040.yaml rename to tests/components/mmc5983/test.rp2040-ard.yaml diff --git a/tests/components/modbus/test.esp32.yaml b/tests/components/modbus/test.esp32-ard.yaml similarity index 100% rename from tests/components/modbus/test.esp32.yaml rename to tests/components/modbus/test.esp32-ard.yaml diff --git a/tests/components/modbus/test.esp32-c3.yaml b/tests/components/modbus/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/modbus/test.esp32-c3.yaml rename to tests/components/modbus/test.esp32-c3-ard.yaml diff --git a/tests/components/modbus/test.esp8266.yaml b/tests/components/modbus/test.esp8266-ard.yaml similarity index 100% rename from tests/components/modbus/test.esp8266.yaml rename to tests/components/modbus/test.esp8266-ard.yaml diff --git a/tests/components/modbus/test.rp2040.yaml b/tests/components/modbus/test.rp2040-ard.yaml similarity index 100% rename from tests/components/modbus/test.rp2040.yaml rename to tests/components/modbus/test.rp2040-ard.yaml diff --git a/tests/components/modbus_controller/test.esp32.yaml b/tests/components/modbus_controller/test.esp32-ard.yaml similarity index 100% rename from tests/components/modbus_controller/test.esp32.yaml rename to tests/components/modbus_controller/test.esp32-ard.yaml diff --git a/tests/components/modbus_controller/test.esp32-c3.yaml b/tests/components/modbus_controller/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/modbus_controller/test.esp32-c3.yaml rename to tests/components/modbus_controller/test.esp32-c3-ard.yaml diff --git a/tests/components/modbus_controller/test.esp8266.yaml b/tests/components/modbus_controller/test.esp8266-ard.yaml similarity index 100% rename from tests/components/modbus_controller/test.esp8266.yaml rename to tests/components/modbus_controller/test.esp8266-ard.yaml diff --git a/tests/components/modbus_controller/test.rp2040.yaml b/tests/components/modbus_controller/test.rp2040-ard.yaml similarity index 100% rename from tests/components/modbus_controller/test.rp2040.yaml rename to tests/components/modbus_controller/test.rp2040-ard.yaml diff --git a/tests/components/monochromatic/test.esp32-c3.yaml b/tests/components/monochromatic/test.esp32-ard.yaml similarity index 100% rename from tests/components/monochromatic/test.esp32-c3.yaml rename to tests/components/monochromatic/test.esp32-ard.yaml diff --git a/tests/components/monochromatic/test.esp32.yaml b/tests/components/monochromatic/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/monochromatic/test.esp32.yaml rename to tests/components/monochromatic/test.esp32-c3-ard.yaml diff --git a/tests/components/monochromatic/test.esp8266.yaml b/tests/components/monochromatic/test.esp8266-ard.yaml similarity index 100% rename from tests/components/monochromatic/test.esp8266.yaml rename to tests/components/monochromatic/test.esp8266-ard.yaml diff --git a/tests/components/monochromatic/test.rp2040.yaml b/tests/components/monochromatic/test.rp2040-ard.yaml similarity index 100% rename from tests/components/monochromatic/test.rp2040.yaml rename to tests/components/monochromatic/test.rp2040-ard.yaml diff --git a/tests/components/mopeka_ble/test.esp32-c3.yaml b/tests/components/mopeka_ble/test.esp32-ard.yaml similarity index 100% rename from tests/components/mopeka_ble/test.esp32-c3.yaml rename to tests/components/mopeka_ble/test.esp32-ard.yaml diff --git a/tests/components/mopeka_ble/test.esp32.yaml b/tests/components/mopeka_ble/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/mopeka_ble/test.esp32.yaml rename to tests/components/mopeka_ble/test.esp32-c3-ard.yaml diff --git a/tests/components/mopeka_pro_check/test.esp32-c3.yaml b/tests/components/mopeka_pro_check/test.esp32-ard.yaml similarity index 100% rename from tests/components/mopeka_pro_check/test.esp32-c3.yaml rename to tests/components/mopeka_pro_check/test.esp32-ard.yaml diff --git a/tests/components/mopeka_pro_check/test.esp32.yaml b/tests/components/mopeka_pro_check/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/mopeka_pro_check/test.esp32.yaml rename to tests/components/mopeka_pro_check/test.esp32-c3-ard.yaml diff --git a/tests/components/mopeka_std_check/test.esp32-c3.yaml b/tests/components/mopeka_std_check/test.esp32-ard.yaml similarity index 100% rename from tests/components/mopeka_std_check/test.esp32-c3.yaml rename to tests/components/mopeka_std_check/test.esp32-ard.yaml diff --git a/tests/components/mopeka_std_check/test.esp32.yaml b/tests/components/mopeka_std_check/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/mopeka_std_check/test.esp32.yaml rename to tests/components/mopeka_std_check/test.esp32-c3-ard.yaml diff --git a/tests/components/mpl3115a2/test.esp32.yaml b/tests/components/mpl3115a2/test.esp32-ard.yaml similarity index 100% rename from tests/components/mpl3115a2/test.esp32.yaml rename to tests/components/mpl3115a2/test.esp32-ard.yaml diff --git a/tests/components/mpl3115a2/test.esp32-c3.yaml b/tests/components/mpl3115a2/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/mpl3115a2/test.esp32-c3.yaml rename to tests/components/mpl3115a2/test.esp32-c3-ard.yaml diff --git a/tests/components/mpl3115a2/test.esp8266.yaml b/tests/components/mpl3115a2/test.esp8266-ard.yaml similarity index 100% rename from tests/components/mpl3115a2/test.esp8266.yaml rename to tests/components/mpl3115a2/test.esp8266-ard.yaml diff --git a/tests/components/mpl3115a2/test.rp2040.yaml b/tests/components/mpl3115a2/test.rp2040-ard.yaml similarity index 100% rename from tests/components/mpl3115a2/test.rp2040.yaml rename to tests/components/mpl3115a2/test.rp2040-ard.yaml diff --git a/tests/components/mpr121/test.esp32.yaml b/tests/components/mpr121/test.esp32-ard.yaml similarity index 100% rename from tests/components/mpr121/test.esp32.yaml rename to tests/components/mpr121/test.esp32-ard.yaml diff --git a/tests/components/mpr121/test.esp32-c3.yaml b/tests/components/mpr121/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/mpr121/test.esp32-c3.yaml rename to tests/components/mpr121/test.esp32-c3-ard.yaml diff --git a/tests/components/mpr121/test.esp8266.yaml b/tests/components/mpr121/test.esp8266-ard.yaml similarity index 100% rename from tests/components/mpr121/test.esp8266.yaml rename to tests/components/mpr121/test.esp8266-ard.yaml diff --git a/tests/components/mpr121/test.rp2040.yaml b/tests/components/mpr121/test.rp2040-ard.yaml similarity index 100% rename from tests/components/mpr121/test.rp2040.yaml rename to tests/components/mpr121/test.rp2040-ard.yaml diff --git a/tests/components/mpu6050/test.esp32.yaml b/tests/components/mpu6050/test.esp32-ard.yaml similarity index 100% rename from tests/components/mpu6050/test.esp32.yaml rename to tests/components/mpu6050/test.esp32-ard.yaml diff --git a/tests/components/mpu6050/test.esp32-c3.yaml b/tests/components/mpu6050/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/mpu6050/test.esp32-c3.yaml rename to tests/components/mpu6050/test.esp32-c3-ard.yaml diff --git a/tests/components/mpu6050/test.esp8266.yaml b/tests/components/mpu6050/test.esp8266-ard.yaml similarity index 100% rename from tests/components/mpu6050/test.esp8266.yaml rename to tests/components/mpu6050/test.esp8266-ard.yaml diff --git a/tests/components/mpu6050/test.rp2040.yaml b/tests/components/mpu6050/test.rp2040-ard.yaml similarity index 100% rename from tests/components/mpu6050/test.rp2040.yaml rename to tests/components/mpu6050/test.rp2040-ard.yaml diff --git a/tests/components/mpu6886/test.esp32.yaml b/tests/components/mpu6886/test.esp32-ard.yaml similarity index 100% rename from tests/components/mpu6886/test.esp32.yaml rename to tests/components/mpu6886/test.esp32-ard.yaml diff --git a/tests/components/mpu6886/test.esp32-c3.yaml b/tests/components/mpu6886/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/mpu6886/test.esp32-c3.yaml rename to tests/components/mpu6886/test.esp32-c3-ard.yaml diff --git a/tests/components/mpu6886/test.esp8266.yaml b/tests/components/mpu6886/test.esp8266-ard.yaml similarity index 100% rename from tests/components/mpu6886/test.esp8266.yaml rename to tests/components/mpu6886/test.esp8266-ard.yaml diff --git a/tests/components/mpu6886/test.rp2040.yaml b/tests/components/mpu6886/test.rp2040-ard.yaml similarity index 100% rename from tests/components/mpu6886/test.rp2040.yaml rename to tests/components/mpu6886/test.rp2040-ard.yaml diff --git a/tests/components/mqtt/test.bk72xx.yaml b/tests/components/mqtt/test.bk72xx-ard.yaml similarity index 100% rename from tests/components/mqtt/test.bk72xx.yaml rename to tests/components/mqtt/test.bk72xx-ard.yaml diff --git a/tests/components/mqtt/test.esp32-c3.yaml b/tests/components/mqtt/test.esp32-ard.yaml similarity index 100% rename from tests/components/mqtt/test.esp32-c3.yaml rename to tests/components/mqtt/test.esp32-ard.yaml diff --git a/tests/components/mqtt/test.esp32.yaml b/tests/components/mqtt/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/mqtt/test.esp32.yaml rename to tests/components/mqtt/test.esp32-c3-ard.yaml diff --git a/tests/components/mqtt/test.esp8266.yaml b/tests/components/mqtt/test.esp8266-ard.yaml similarity index 100% rename from tests/components/mqtt/test.esp8266.yaml rename to tests/components/mqtt/test.esp8266-ard.yaml diff --git a/tests/components/mqtt_subscribe/test.esp32-c3.yaml b/tests/components/mqtt_subscribe/test.esp32-ard.yaml similarity index 100% rename from tests/components/mqtt_subscribe/test.esp32-c3.yaml rename to tests/components/mqtt_subscribe/test.esp32-ard.yaml diff --git a/tests/components/mqtt_subscribe/test.esp32.yaml b/tests/components/mqtt_subscribe/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/mqtt_subscribe/test.esp32.yaml rename to tests/components/mqtt_subscribe/test.esp32-c3-ard.yaml diff --git a/tests/components/mqtt_subscribe/test.esp8266.yaml b/tests/components/mqtt_subscribe/test.esp8266-ard.yaml similarity index 100% rename from tests/components/mqtt_subscribe/test.esp8266.yaml rename to tests/components/mqtt_subscribe/test.esp8266-ard.yaml diff --git a/tests/components/ms5611/test.esp32.yaml b/tests/components/ms5611/test.esp32-ard.yaml similarity index 100% rename from tests/components/ms5611/test.esp32.yaml rename to tests/components/ms5611/test.esp32-ard.yaml diff --git a/tests/components/ms5611/test.esp32-c3.yaml b/tests/components/ms5611/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ms5611/test.esp32-c3.yaml rename to tests/components/ms5611/test.esp32-c3-ard.yaml diff --git a/tests/components/ms5611/test.esp8266.yaml b/tests/components/ms5611/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ms5611/test.esp8266.yaml rename to tests/components/ms5611/test.esp8266-ard.yaml diff --git a/tests/components/ms5611/test.rp2040.yaml b/tests/components/ms5611/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ms5611/test.rp2040.yaml rename to tests/components/ms5611/test.rp2040-ard.yaml diff --git a/tests/components/my9231/test.esp32-c3.yaml b/tests/components/my9231/test.esp32-ard.yaml similarity index 100% rename from tests/components/my9231/test.esp32-c3.yaml rename to tests/components/my9231/test.esp32-ard.yaml diff --git a/tests/components/my9231/test.esp32.yaml b/tests/components/my9231/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/my9231/test.esp32.yaml rename to tests/components/my9231/test.esp32-c3-ard.yaml diff --git a/tests/components/my9231/test.esp8266.yaml b/tests/components/my9231/test.esp8266-ard.yaml similarity index 100% rename from tests/components/my9231/test.esp8266.yaml rename to tests/components/my9231/test.esp8266-ard.yaml diff --git a/tests/components/my9231/test.rp2040.yaml b/tests/components/my9231/test.rp2040-ard.yaml similarity index 100% rename from tests/components/my9231/test.rp2040.yaml rename to tests/components/my9231/test.rp2040-ard.yaml diff --git a/tests/components/neopixelbus/test.esp32.yaml b/tests/components/neopixelbus/test.esp32-ard.yaml similarity index 100% rename from tests/components/neopixelbus/test.esp32.yaml rename to tests/components/neopixelbus/test.esp32-ard.yaml diff --git a/tests/components/neopixelbus/test.esp32-c3.yaml b/tests/components/neopixelbus/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/neopixelbus/test.esp32-c3.yaml rename to tests/components/neopixelbus/test.esp32-c3-ard.yaml diff --git a/tests/components/neopixelbus/test.esp8266.yaml b/tests/components/neopixelbus/test.esp8266-ard.yaml similarity index 100% rename from tests/components/neopixelbus/test.esp8266.yaml rename to tests/components/neopixelbus/test.esp8266-ard.yaml diff --git a/tests/components/network/test.esp32-c3.yaml b/tests/components/network/test.esp32-ard.yaml similarity index 100% rename from tests/components/network/test.esp32-c3.yaml rename to tests/components/network/test.esp32-ard.yaml diff --git a/tests/components/network/test.esp32.yaml b/tests/components/network/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/network/test.esp32.yaml rename to tests/components/network/test.esp32-c3-ard.yaml diff --git a/tests/components/network/test.esp8266.yaml b/tests/components/network/test.esp8266-ard.yaml similarity index 100% rename from tests/components/network/test.esp8266.yaml rename to tests/components/network/test.esp8266-ard.yaml diff --git a/tests/components/network/test.rp2040.yaml b/tests/components/network/test.rp2040-ard.yaml similarity index 100% rename from tests/components/network/test.rp2040.yaml rename to tests/components/network/test.rp2040-ard.yaml diff --git a/tests/components/nextion/test.esp32.yaml b/tests/components/nextion/test.esp32-ard.yaml similarity index 100% rename from tests/components/nextion/test.esp32.yaml rename to tests/components/nextion/test.esp32-ard.yaml diff --git a/tests/components/nextion/test.esp32-c3.yaml b/tests/components/nextion/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/nextion/test.esp32-c3.yaml rename to tests/components/nextion/test.esp32-c3-ard.yaml diff --git a/tests/components/nextion/test.esp8266.yaml b/tests/components/nextion/test.esp8266-ard.yaml similarity index 100% rename from tests/components/nextion/test.esp8266.yaml rename to tests/components/nextion/test.esp8266-ard.yaml diff --git a/tests/components/nextion/test.rp2040.yaml b/tests/components/nextion/test.rp2040-ard.yaml similarity index 100% rename from tests/components/nextion/test.rp2040.yaml rename to tests/components/nextion/test.rp2040-ard.yaml diff --git a/tests/components/noblex/test.esp32-c3.yaml b/tests/components/noblex/test.esp32-ard.yaml similarity index 100% rename from tests/components/noblex/test.esp32-c3.yaml rename to tests/components/noblex/test.esp32-ard.yaml diff --git a/tests/components/noblex/test.esp32.yaml b/tests/components/noblex/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/noblex/test.esp32.yaml rename to tests/components/noblex/test.esp32-c3-ard.yaml diff --git a/tests/components/noblex/test.esp8266.yaml b/tests/components/noblex/test.esp8266-ard.yaml similarity index 100% rename from tests/components/noblex/test.esp8266.yaml rename to tests/components/noblex/test.esp8266-ard.yaml diff --git a/tests/components/ntc/test.esp32.yaml b/tests/components/ntc/test.esp32-ard.yaml similarity index 100% rename from tests/components/ntc/test.esp32.yaml rename to tests/components/ntc/test.esp32-ard.yaml diff --git a/tests/components/ntc/test.esp32-c3.yaml b/tests/components/ntc/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ntc/test.esp32-c3.yaml rename to tests/components/ntc/test.esp32-c3-ard.yaml diff --git a/tests/components/ntc/test.esp32-s2.yaml b/tests/components/ntc/test.esp32-s2-ard.yaml similarity index 100% rename from tests/components/ntc/test.esp32-s2.yaml rename to tests/components/ntc/test.esp32-s2-ard.yaml diff --git a/tests/components/ntc/test.esp32-s3.yaml b/tests/components/ntc/test.esp32-s3-ard.yaml similarity index 100% rename from tests/components/ntc/test.esp32-s3.yaml rename to tests/components/ntc/test.esp32-s3-ard.yaml diff --git a/tests/components/ntc/test.esp8266.yaml b/tests/components/ntc/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ntc/test.esp8266.yaml rename to tests/components/ntc/test.esp8266-ard.yaml diff --git a/tests/components/ntc/test.rp2040.yaml b/tests/components/ntc/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ntc/test.rp2040.yaml rename to tests/components/ntc/test.rp2040-ard.yaml diff --git a/tests/components/ota/test.esp32-c3.yaml b/tests/components/ota/test.esp32-ard.yaml similarity index 100% rename from tests/components/ota/test.esp32-c3.yaml rename to tests/components/ota/test.esp32-ard.yaml diff --git a/tests/components/ota/test.esp32.yaml b/tests/components/ota/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ota/test.esp32.yaml rename to tests/components/ota/test.esp32-c3-ard.yaml diff --git a/tests/components/ota/test.esp8266.yaml b/tests/components/ota/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ota/test.esp8266.yaml rename to tests/components/ota/test.esp8266-ard.yaml diff --git a/tests/components/ota/test.rp2040.yaml b/tests/components/ota/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ota/test.rp2040.yaml rename to tests/components/ota/test.rp2040-ard.yaml diff --git a/tests/components/output/test.esp32.yaml b/tests/components/output/test.esp32-ard.yaml similarity index 100% rename from tests/components/output/test.esp32.yaml rename to tests/components/output/test.esp32-ard.yaml diff --git a/tests/components/output/test.esp32-c3.yaml b/tests/components/output/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/output/test.esp32-c3.yaml rename to tests/components/output/test.esp32-c3-ard.yaml diff --git a/tests/components/output/test.esp8266.yaml b/tests/components/output/test.esp8266-ard.yaml similarity index 100% rename from tests/components/output/test.esp8266.yaml rename to tests/components/output/test.esp8266-ard.yaml diff --git a/tests/components/output/test.rp2040.yaml b/tests/components/output/test.rp2040-ard.yaml similarity index 100% rename from tests/components/output/test.rp2040.yaml rename to tests/components/output/test.rp2040-ard.yaml diff --git a/tests/components/partition/test.esp32.yaml b/tests/components/partition/test.esp32-ard.yaml similarity index 100% rename from tests/components/partition/test.esp32.yaml rename to tests/components/partition/test.esp32-ard.yaml diff --git a/tests/components/partition/test.esp32-c3.yaml b/tests/components/partition/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/partition/test.esp32-c3.yaml rename to tests/components/partition/test.esp32-c3-ard.yaml diff --git a/tests/components/pca6416a/test.esp32.yaml b/tests/components/pca6416a/test.esp32-ard.yaml similarity index 100% rename from tests/components/pca6416a/test.esp32.yaml rename to tests/components/pca6416a/test.esp32-ard.yaml diff --git a/tests/components/pca6416a/test.esp32-c3.yaml b/tests/components/pca6416a/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/pca6416a/test.esp32-c3.yaml rename to tests/components/pca6416a/test.esp32-c3-ard.yaml diff --git a/tests/components/pca6416a/test.esp8266.yaml b/tests/components/pca6416a/test.esp8266-ard.yaml similarity index 100% rename from tests/components/pca6416a/test.esp8266.yaml rename to tests/components/pca6416a/test.esp8266-ard.yaml diff --git a/tests/components/pca6416a/test.rp2040.yaml b/tests/components/pca6416a/test.rp2040-ard.yaml similarity index 100% rename from tests/components/pca6416a/test.rp2040.yaml rename to tests/components/pca6416a/test.rp2040-ard.yaml diff --git a/tests/components/pca9554/test.esp32.yaml b/tests/components/pca9554/test.esp32-ard.yaml similarity index 100% rename from tests/components/pca9554/test.esp32.yaml rename to tests/components/pca9554/test.esp32-ard.yaml diff --git a/tests/components/pca9554/test.esp32-c3.yaml b/tests/components/pca9554/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/pca9554/test.esp32-c3.yaml rename to tests/components/pca9554/test.esp32-c3-ard.yaml diff --git a/tests/components/pca9554/test.esp8266.yaml b/tests/components/pca9554/test.esp8266-ard.yaml similarity index 100% rename from tests/components/pca9554/test.esp8266.yaml rename to tests/components/pca9554/test.esp8266-ard.yaml diff --git a/tests/components/pca9554/test.rp2040.yaml b/tests/components/pca9554/test.rp2040-ard.yaml similarity index 100% rename from tests/components/pca9554/test.rp2040.yaml rename to tests/components/pca9554/test.rp2040-ard.yaml diff --git a/tests/components/pca9685/test.esp32.yaml b/tests/components/pca9685/test.esp32-ard.yaml similarity index 100% rename from tests/components/pca9685/test.esp32.yaml rename to tests/components/pca9685/test.esp32-ard.yaml diff --git a/tests/components/pca9685/test.esp32-c3.yaml b/tests/components/pca9685/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/pca9685/test.esp32-c3.yaml rename to tests/components/pca9685/test.esp32-c3-ard.yaml diff --git a/tests/components/pca9685/test.esp8266.yaml b/tests/components/pca9685/test.esp8266-ard.yaml similarity index 100% rename from tests/components/pca9685/test.esp8266.yaml rename to tests/components/pca9685/test.esp8266-ard.yaml diff --git a/tests/components/pca9685/test.rp2040.yaml b/tests/components/pca9685/test.rp2040-ard.yaml similarity index 100% rename from tests/components/pca9685/test.rp2040.yaml rename to tests/components/pca9685/test.rp2040-ard.yaml diff --git a/tests/components/pcd8544/test.esp32.yaml b/tests/components/pcd8544/test.esp32-ard.yaml similarity index 100% rename from tests/components/pcd8544/test.esp32.yaml rename to tests/components/pcd8544/test.esp32-ard.yaml diff --git a/tests/components/pcd8544/test.esp32-c3.yaml b/tests/components/pcd8544/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/pcd8544/test.esp32-c3.yaml rename to tests/components/pcd8544/test.esp32-c3-ard.yaml diff --git a/tests/components/pcd8544/test.esp8266.yaml b/tests/components/pcd8544/test.esp8266-ard.yaml similarity index 100% rename from tests/components/pcd8544/test.esp8266.yaml rename to tests/components/pcd8544/test.esp8266-ard.yaml diff --git a/tests/components/pcd8544/test.rp2040.yaml b/tests/components/pcd8544/test.rp2040-ard.yaml similarity index 100% rename from tests/components/pcd8544/test.rp2040.yaml rename to tests/components/pcd8544/test.rp2040-ard.yaml diff --git a/tests/components/pcf85063/test.esp32.yaml b/tests/components/pcf85063/test.esp32-ard.yaml similarity index 100% rename from tests/components/pcf85063/test.esp32.yaml rename to tests/components/pcf85063/test.esp32-ard.yaml diff --git a/tests/components/pcf85063/test.esp32-c3.yaml b/tests/components/pcf85063/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/pcf85063/test.esp32-c3.yaml rename to tests/components/pcf85063/test.esp32-c3-ard.yaml diff --git a/tests/components/pcf85063/test.esp8266.yaml b/tests/components/pcf85063/test.esp8266-ard.yaml similarity index 100% rename from tests/components/pcf85063/test.esp8266.yaml rename to tests/components/pcf85063/test.esp8266-ard.yaml diff --git a/tests/components/pcf85063/test.rp2040.yaml b/tests/components/pcf85063/test.rp2040-ard.yaml similarity index 100% rename from tests/components/pcf85063/test.rp2040.yaml rename to tests/components/pcf85063/test.rp2040-ard.yaml diff --git a/tests/components/pcf8563/test.esp32.yaml b/tests/components/pcf8563/test.esp32-ard.yaml similarity index 100% rename from tests/components/pcf8563/test.esp32.yaml rename to tests/components/pcf8563/test.esp32-ard.yaml diff --git a/tests/components/pcf8563/test.esp32-c3.yaml b/tests/components/pcf8563/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/pcf8563/test.esp32-c3.yaml rename to tests/components/pcf8563/test.esp32-c3-ard.yaml diff --git a/tests/components/pcf8563/test.esp8266.yaml b/tests/components/pcf8563/test.esp8266-ard.yaml similarity index 100% rename from tests/components/pcf8563/test.esp8266.yaml rename to tests/components/pcf8563/test.esp8266-ard.yaml diff --git a/tests/components/pcf8563/test.rp2040.yaml b/tests/components/pcf8563/test.rp2040-ard.yaml similarity index 100% rename from tests/components/pcf8563/test.rp2040.yaml rename to tests/components/pcf8563/test.rp2040-ard.yaml diff --git a/tests/components/pcf8574/test.esp32.yaml b/tests/components/pcf8574/test.esp32-ard.yaml similarity index 100% rename from tests/components/pcf8574/test.esp32.yaml rename to tests/components/pcf8574/test.esp32-ard.yaml diff --git a/tests/components/pcf8574/test.esp32-c3.yaml b/tests/components/pcf8574/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/pcf8574/test.esp32-c3.yaml rename to tests/components/pcf8574/test.esp32-c3-ard.yaml diff --git a/tests/components/pcf8574/test.esp8266.yaml b/tests/components/pcf8574/test.esp8266-ard.yaml similarity index 100% rename from tests/components/pcf8574/test.esp8266.yaml rename to tests/components/pcf8574/test.esp8266-ard.yaml diff --git a/tests/components/pcf8574/test.rp2040.yaml b/tests/components/pcf8574/test.rp2040-ard.yaml similarity index 100% rename from tests/components/pcf8574/test.rp2040.yaml rename to tests/components/pcf8574/test.rp2040-ard.yaml diff --git a/tests/components/pid/test.esp32-c3.yaml b/tests/components/pid/test.esp32-ard.yaml similarity index 100% rename from tests/components/pid/test.esp32-c3.yaml rename to tests/components/pid/test.esp32-ard.yaml diff --git a/tests/components/pid/test.esp32.yaml b/tests/components/pid/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/pid/test.esp32.yaml rename to tests/components/pid/test.esp32-c3-ard.yaml diff --git a/tests/components/pid/test.esp8266.yaml b/tests/components/pid/test.esp8266-ard.yaml similarity index 100% rename from tests/components/pid/test.esp8266.yaml rename to tests/components/pid/test.esp8266-ard.yaml diff --git a/tests/components/pid/test.rp2040.yaml b/tests/components/pid/test.rp2040-ard.yaml similarity index 100% rename from tests/components/pid/test.rp2040.yaml rename to tests/components/pid/test.rp2040-ard.yaml diff --git a/tests/components/pipsolar/test.esp32.yaml b/tests/components/pipsolar/test.esp32-ard.yaml similarity index 100% rename from tests/components/pipsolar/test.esp32.yaml rename to tests/components/pipsolar/test.esp32-ard.yaml diff --git a/tests/components/pipsolar/test.esp32-c3.yaml b/tests/components/pipsolar/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/pipsolar/test.esp32-c3.yaml rename to tests/components/pipsolar/test.esp32-c3-ard.yaml diff --git a/tests/components/pipsolar/test.esp8266.yaml b/tests/components/pipsolar/test.esp8266-ard.yaml similarity index 100% rename from tests/components/pipsolar/test.esp8266.yaml rename to tests/components/pipsolar/test.esp8266-ard.yaml diff --git a/tests/components/pipsolar/test.rp2040.yaml b/tests/components/pipsolar/test.rp2040-ard.yaml similarity index 100% rename from tests/components/pipsolar/test.rp2040.yaml rename to tests/components/pipsolar/test.rp2040-ard.yaml diff --git a/tests/components/pm1006/test.esp32.yaml b/tests/components/pm1006/test.esp32-ard.yaml similarity index 100% rename from tests/components/pm1006/test.esp32.yaml rename to tests/components/pm1006/test.esp32-ard.yaml diff --git a/tests/components/pm1006/test.esp32-c3.yaml b/tests/components/pm1006/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/pm1006/test.esp32-c3.yaml rename to tests/components/pm1006/test.esp32-c3-ard.yaml diff --git a/tests/components/pm1006/test.esp8266.yaml b/tests/components/pm1006/test.esp8266-ard.yaml similarity index 100% rename from tests/components/pm1006/test.esp8266.yaml rename to tests/components/pm1006/test.esp8266-ard.yaml diff --git a/tests/components/pm1006/test.rp2040.yaml b/tests/components/pm1006/test.rp2040-ard.yaml similarity index 100% rename from tests/components/pm1006/test.rp2040.yaml rename to tests/components/pm1006/test.rp2040-ard.yaml diff --git a/tests/components/pmsa003i/test.esp32.yaml b/tests/components/pmsa003i/test.esp32-ard.yaml similarity index 100% rename from tests/components/pmsa003i/test.esp32.yaml rename to tests/components/pmsa003i/test.esp32-ard.yaml diff --git a/tests/components/pmsa003i/test.esp32-c3.yaml b/tests/components/pmsa003i/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/pmsa003i/test.esp32-c3.yaml rename to tests/components/pmsa003i/test.esp32-c3-ard.yaml diff --git a/tests/components/pmsa003i/test.esp8266.yaml b/tests/components/pmsa003i/test.esp8266-ard.yaml similarity index 100% rename from tests/components/pmsa003i/test.esp8266.yaml rename to tests/components/pmsa003i/test.esp8266-ard.yaml diff --git a/tests/components/pmsa003i/test.rp2040.yaml b/tests/components/pmsa003i/test.rp2040-ard.yaml similarity index 100% rename from tests/components/pmsa003i/test.rp2040.yaml rename to tests/components/pmsa003i/test.rp2040-ard.yaml diff --git a/tests/components/pmsx003/test.esp32.yaml b/tests/components/pmsx003/test.esp32-ard.yaml similarity index 100% rename from tests/components/pmsx003/test.esp32.yaml rename to tests/components/pmsx003/test.esp32-ard.yaml diff --git a/tests/components/pmsx003/test.esp32-c3.yaml b/tests/components/pmsx003/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/pmsx003/test.esp32-c3.yaml rename to tests/components/pmsx003/test.esp32-c3-ard.yaml diff --git a/tests/components/pmsx003/test.esp8266.yaml b/tests/components/pmsx003/test.esp8266-ard.yaml similarity index 100% rename from tests/components/pmsx003/test.esp8266.yaml rename to tests/components/pmsx003/test.esp8266-ard.yaml diff --git a/tests/components/pmsx003/test.rp2040.yaml b/tests/components/pmsx003/test.rp2040-ard.yaml similarity index 100% rename from tests/components/pmsx003/test.rp2040.yaml rename to tests/components/pmsx003/test.rp2040-ard.yaml diff --git a/tests/components/pmwcs3/test.esp32.yaml b/tests/components/pmwcs3/test.esp32-ard.yaml similarity index 100% rename from tests/components/pmwcs3/test.esp32.yaml rename to tests/components/pmwcs3/test.esp32-ard.yaml diff --git a/tests/components/pmwcs3/test.esp32-c3.yaml b/tests/components/pmwcs3/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/pmwcs3/test.esp32-c3.yaml rename to tests/components/pmwcs3/test.esp32-c3-ard.yaml diff --git a/tests/components/pmwcs3/test.esp8266.yaml b/tests/components/pmwcs3/test.esp8266-ard.yaml similarity index 100% rename from tests/components/pmwcs3/test.esp8266.yaml rename to tests/components/pmwcs3/test.esp8266-ard.yaml diff --git a/tests/components/pmwcs3/test.rp2040.yaml b/tests/components/pmwcs3/test.rp2040-ard.yaml similarity index 100% rename from tests/components/pmwcs3/test.rp2040.yaml rename to tests/components/pmwcs3/test.rp2040-ard.yaml diff --git a/tests/components/pn532_i2c/test.esp32.yaml b/tests/components/pn532_i2c/test.esp32-ard.yaml similarity index 100% rename from tests/components/pn532_i2c/test.esp32.yaml rename to tests/components/pn532_i2c/test.esp32-ard.yaml diff --git a/tests/components/pn532_i2c/test.esp32-c3.yaml b/tests/components/pn532_i2c/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/pn532_i2c/test.esp32-c3.yaml rename to tests/components/pn532_i2c/test.esp32-c3-ard.yaml diff --git a/tests/components/pn532_i2c/test.esp8266.yaml b/tests/components/pn532_i2c/test.esp8266-ard.yaml similarity index 100% rename from tests/components/pn532_i2c/test.esp8266.yaml rename to tests/components/pn532_i2c/test.esp8266-ard.yaml diff --git a/tests/components/pn532_i2c/test.rp2040.yaml b/tests/components/pn532_i2c/test.rp2040-ard.yaml similarity index 100% rename from tests/components/pn532_i2c/test.rp2040.yaml rename to tests/components/pn532_i2c/test.rp2040-ard.yaml diff --git a/tests/components/pn532_spi/test.esp32.yaml b/tests/components/pn532_spi/test.esp32-ard.yaml similarity index 100% rename from tests/components/pn532_spi/test.esp32.yaml rename to tests/components/pn532_spi/test.esp32-ard.yaml diff --git a/tests/components/pn532_spi/test.esp32-c3.yaml b/tests/components/pn532_spi/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/pn532_spi/test.esp32-c3.yaml rename to tests/components/pn532_spi/test.esp32-c3-ard.yaml diff --git a/tests/components/pn532_spi/test.esp8266.yaml b/tests/components/pn532_spi/test.esp8266-ard.yaml similarity index 100% rename from tests/components/pn532_spi/test.esp8266.yaml rename to tests/components/pn532_spi/test.esp8266-ard.yaml diff --git a/tests/components/pn532_spi/test.rp2040.yaml b/tests/components/pn532_spi/test.rp2040-ard.yaml similarity index 100% rename from tests/components/pn532_spi/test.rp2040.yaml rename to tests/components/pn532_spi/test.rp2040-ard.yaml diff --git a/tests/components/pn7150_i2c/test.esp32.yaml b/tests/components/pn7150_i2c/test.esp32-ard.yaml similarity index 100% rename from tests/components/pn7150_i2c/test.esp32.yaml rename to tests/components/pn7150_i2c/test.esp32-ard.yaml diff --git a/tests/components/pn7150_i2c/test.esp32-c3.yaml b/tests/components/pn7150_i2c/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/pn7150_i2c/test.esp32-c3.yaml rename to tests/components/pn7150_i2c/test.esp32-c3-ard.yaml diff --git a/tests/components/pn7150_i2c/test.esp8266.yaml b/tests/components/pn7150_i2c/test.esp8266-ard.yaml similarity index 100% rename from tests/components/pn7150_i2c/test.esp8266.yaml rename to tests/components/pn7150_i2c/test.esp8266-ard.yaml diff --git a/tests/components/pn7150_i2c/test.rp2040.yaml b/tests/components/pn7150_i2c/test.rp2040-ard.yaml similarity index 100% rename from tests/components/pn7150_i2c/test.rp2040.yaml rename to tests/components/pn7150_i2c/test.rp2040-ard.yaml diff --git a/tests/components/pn7160_i2c/test.esp32.yaml b/tests/components/pn7160_i2c/test.esp32-ard.yaml similarity index 100% rename from tests/components/pn7160_i2c/test.esp32.yaml rename to tests/components/pn7160_i2c/test.esp32-ard.yaml diff --git a/tests/components/pn7160_i2c/test.esp32-c3.yaml b/tests/components/pn7160_i2c/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/pn7160_i2c/test.esp32-c3.yaml rename to tests/components/pn7160_i2c/test.esp32-c3-ard.yaml diff --git a/tests/components/pn7160_i2c/test.esp8266.yaml b/tests/components/pn7160_i2c/test.esp8266-ard.yaml similarity index 100% rename from tests/components/pn7160_i2c/test.esp8266.yaml rename to tests/components/pn7160_i2c/test.esp8266-ard.yaml diff --git a/tests/components/pn7160_i2c/test.rp2040.yaml b/tests/components/pn7160_i2c/test.rp2040-ard.yaml similarity index 100% rename from tests/components/pn7160_i2c/test.rp2040.yaml rename to tests/components/pn7160_i2c/test.rp2040-ard.yaml diff --git a/tests/components/pn7160_spi/test.esp32.yaml b/tests/components/pn7160_spi/test.esp32-ard.yaml similarity index 100% rename from tests/components/pn7160_spi/test.esp32.yaml rename to tests/components/pn7160_spi/test.esp32-ard.yaml diff --git a/tests/components/pn7160_spi/test.esp32-c3.yaml b/tests/components/pn7160_spi/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/pn7160_spi/test.esp32-c3.yaml rename to tests/components/pn7160_spi/test.esp32-c3-ard.yaml diff --git a/tests/components/pn7160_spi/test.esp8266.yaml b/tests/components/pn7160_spi/test.esp8266-ard.yaml similarity index 100% rename from tests/components/pn7160_spi/test.esp8266.yaml rename to tests/components/pn7160_spi/test.esp8266-ard.yaml diff --git a/tests/components/pn7160_spi/test.rp2040.yaml b/tests/components/pn7160_spi/test.rp2040-ard.yaml similarity index 100% rename from tests/components/pn7160_spi/test.rp2040.yaml rename to tests/components/pn7160_spi/test.rp2040-ard.yaml diff --git a/tests/components/power_supply/test.esp32-c3.yaml b/tests/components/power_supply/test.esp32-ard.yaml similarity index 100% rename from tests/components/power_supply/test.esp32-c3.yaml rename to tests/components/power_supply/test.esp32-ard.yaml diff --git a/tests/components/power_supply/test.esp32.yaml b/tests/components/power_supply/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/power_supply/test.esp32.yaml rename to tests/components/power_supply/test.esp32-c3-ard.yaml diff --git a/tests/components/power_supply/test.esp8266.yaml b/tests/components/power_supply/test.esp8266-ard.yaml similarity index 100% rename from tests/components/power_supply/test.esp8266.yaml rename to tests/components/power_supply/test.esp8266-ard.yaml diff --git a/tests/components/power_supply/test.rp2040.yaml b/tests/components/power_supply/test.rp2040-ard.yaml similarity index 100% rename from tests/components/power_supply/test.rp2040.yaml rename to tests/components/power_supply/test.rp2040-ard.yaml diff --git a/tests/components/prometheus/test.esp32-c3.yaml b/tests/components/prometheus/test.esp32-ard.yaml similarity index 100% rename from tests/components/prometheus/test.esp32-c3.yaml rename to tests/components/prometheus/test.esp32-ard.yaml diff --git a/tests/components/prometheus/test.esp32.yaml b/tests/components/prometheus/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/prometheus/test.esp32.yaml rename to tests/components/prometheus/test.esp32-c3-ard.yaml diff --git a/tests/components/prometheus/test.esp8266.yaml b/tests/components/prometheus/test.esp8266-ard.yaml similarity index 100% rename from tests/components/prometheus/test.esp8266.yaml rename to tests/components/prometheus/test.esp8266-ard.yaml diff --git a/tests/components/psram/test.esp32-c3.yaml b/tests/components/psram/test.esp32-ard.yaml similarity index 100% rename from tests/components/psram/test.esp32-c3.yaml rename to tests/components/psram/test.esp32-ard.yaml diff --git a/tests/components/psram/test.esp32.yaml b/tests/components/psram/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/psram/test.esp32.yaml rename to tests/components/psram/test.esp32-c3-ard.yaml diff --git a/tests/components/pulse_counter/test.esp32-c3.yaml b/tests/components/pulse_counter/test.esp32-ard.yaml similarity index 100% rename from tests/components/pulse_counter/test.esp32-c3.yaml rename to tests/components/pulse_counter/test.esp32-ard.yaml diff --git a/tests/components/pulse_counter/test.esp32.yaml b/tests/components/pulse_counter/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/pulse_counter/test.esp32.yaml rename to tests/components/pulse_counter/test.esp32-c3-ard.yaml diff --git a/tests/components/pulse_counter/test.esp8266.yaml b/tests/components/pulse_counter/test.esp8266-ard.yaml similarity index 100% rename from tests/components/pulse_counter/test.esp8266.yaml rename to tests/components/pulse_counter/test.esp8266-ard.yaml diff --git a/tests/components/pulse_counter/test.rp2040.yaml b/tests/components/pulse_counter/test.rp2040-ard.yaml similarity index 100% rename from tests/components/pulse_counter/test.rp2040.yaml rename to tests/components/pulse_counter/test.rp2040-ard.yaml diff --git a/tests/components/pulse_meter/test.esp32-c3.yaml b/tests/components/pulse_meter/test.esp32-ard.yaml similarity index 100% rename from tests/components/pulse_meter/test.esp32-c3.yaml rename to tests/components/pulse_meter/test.esp32-ard.yaml diff --git a/tests/components/pulse_meter/test.esp32.yaml b/tests/components/pulse_meter/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/pulse_meter/test.esp32.yaml rename to tests/components/pulse_meter/test.esp32-c3-ard.yaml diff --git a/tests/components/pulse_meter/test.esp8266.yaml b/tests/components/pulse_meter/test.esp8266-ard.yaml similarity index 100% rename from tests/components/pulse_meter/test.esp8266.yaml rename to tests/components/pulse_meter/test.esp8266-ard.yaml diff --git a/tests/components/pulse_meter/test.rp2040.yaml b/tests/components/pulse_meter/test.rp2040-ard.yaml similarity index 100% rename from tests/components/pulse_meter/test.rp2040.yaml rename to tests/components/pulse_meter/test.rp2040-ard.yaml diff --git a/tests/components/pulse_width/test.esp32-c3.yaml b/tests/components/pulse_width/test.esp32-ard.yaml similarity index 100% rename from tests/components/pulse_width/test.esp32-c3.yaml rename to tests/components/pulse_width/test.esp32-ard.yaml diff --git a/tests/components/pulse_width/test.esp32.yaml b/tests/components/pulse_width/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/pulse_width/test.esp32.yaml rename to tests/components/pulse_width/test.esp32-c3-ard.yaml diff --git a/tests/components/pulse_width/test.esp8266.yaml b/tests/components/pulse_width/test.esp8266-ard.yaml similarity index 100% rename from tests/components/pulse_width/test.esp8266.yaml rename to tests/components/pulse_width/test.esp8266-ard.yaml diff --git a/tests/components/pulse_width/test.rp2040.yaml b/tests/components/pulse_width/test.rp2040-ard.yaml similarity index 100% rename from tests/components/pulse_width/test.rp2040.yaml rename to tests/components/pulse_width/test.rp2040-ard.yaml diff --git a/tests/components/pvvx_mithermometer/test.esp32-c3.yaml b/tests/components/pvvx_mithermometer/test.esp32-ard.yaml similarity index 100% rename from tests/components/pvvx_mithermometer/test.esp32-c3.yaml rename to tests/components/pvvx_mithermometer/test.esp32-ard.yaml diff --git a/tests/components/pvvx_mithermometer/test.esp32.yaml b/tests/components/pvvx_mithermometer/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/pvvx_mithermometer/test.esp32.yaml rename to tests/components/pvvx_mithermometer/test.esp32-c3-ard.yaml diff --git a/tests/components/pylontech/test.esp32.yaml b/tests/components/pylontech/test.esp32-ard.yaml similarity index 100% rename from tests/components/pylontech/test.esp32.yaml rename to tests/components/pylontech/test.esp32-ard.yaml diff --git a/tests/components/pylontech/test.esp32-c3.yaml b/tests/components/pylontech/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/pylontech/test.esp32-c3.yaml rename to tests/components/pylontech/test.esp32-c3-ard.yaml diff --git a/tests/components/pylontech/test.esp8266.yaml b/tests/components/pylontech/test.esp8266-ard.yaml similarity index 100% rename from tests/components/pylontech/test.esp8266.yaml rename to tests/components/pylontech/test.esp8266-ard.yaml diff --git a/tests/components/pylontech/test.rp2040.yaml b/tests/components/pylontech/test.rp2040-ard.yaml similarity index 100% rename from tests/components/pylontech/test.rp2040.yaml rename to tests/components/pylontech/test.rp2040-ard.yaml diff --git a/tests/components/pzem004t/test.esp32.yaml b/tests/components/pzem004t/test.esp32-ard.yaml similarity index 100% rename from tests/components/pzem004t/test.esp32.yaml rename to tests/components/pzem004t/test.esp32-ard.yaml diff --git a/tests/components/pzem004t/test.esp32-c3.yaml b/tests/components/pzem004t/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/pzem004t/test.esp32-c3.yaml rename to tests/components/pzem004t/test.esp32-c3-ard.yaml diff --git a/tests/components/pzem004t/test.esp8266.yaml b/tests/components/pzem004t/test.esp8266-ard.yaml similarity index 100% rename from tests/components/pzem004t/test.esp8266.yaml rename to tests/components/pzem004t/test.esp8266-ard.yaml diff --git a/tests/components/pzem004t/test.rp2040.yaml b/tests/components/pzem004t/test.rp2040-ard.yaml similarity index 100% rename from tests/components/pzem004t/test.rp2040.yaml rename to tests/components/pzem004t/test.rp2040-ard.yaml diff --git a/tests/components/pzemac/test.esp32.yaml b/tests/components/pzemac/test.esp32-ard.yaml similarity index 100% rename from tests/components/pzemac/test.esp32.yaml rename to tests/components/pzemac/test.esp32-ard.yaml diff --git a/tests/components/pzemac/test.esp32-c3.yaml b/tests/components/pzemac/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/pzemac/test.esp32-c3.yaml rename to tests/components/pzemac/test.esp32-c3-ard.yaml diff --git a/tests/components/pzemac/test.esp8266.yaml b/tests/components/pzemac/test.esp8266-ard.yaml similarity index 100% rename from tests/components/pzemac/test.esp8266.yaml rename to tests/components/pzemac/test.esp8266-ard.yaml diff --git a/tests/components/pzemac/test.rp2040.yaml b/tests/components/pzemac/test.rp2040-ard.yaml similarity index 100% rename from tests/components/pzemac/test.rp2040.yaml rename to tests/components/pzemac/test.rp2040-ard.yaml diff --git a/tests/components/pzemdc/test.esp32.yaml b/tests/components/pzemdc/test.esp32-ard.yaml similarity index 100% rename from tests/components/pzemdc/test.esp32.yaml rename to tests/components/pzemdc/test.esp32-ard.yaml diff --git a/tests/components/pzemdc/test.esp32-c3.yaml b/tests/components/pzemdc/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/pzemdc/test.esp32-c3.yaml rename to tests/components/pzemdc/test.esp32-c3-ard.yaml diff --git a/tests/components/pzemdc/test.esp8266.yaml b/tests/components/pzemdc/test.esp8266-ard.yaml similarity index 100% rename from tests/components/pzemdc/test.esp8266.yaml rename to tests/components/pzemdc/test.esp8266-ard.yaml diff --git a/tests/components/pzemdc/test.rp2040.yaml b/tests/components/pzemdc/test.rp2040-ard.yaml similarity index 100% rename from tests/components/pzemdc/test.rp2040.yaml rename to tests/components/pzemdc/test.rp2040-ard.yaml diff --git a/tests/components/qmc5883l/test.esp32.yaml b/tests/components/qmc5883l/test.esp32-ard.yaml similarity index 100% rename from tests/components/qmc5883l/test.esp32.yaml rename to tests/components/qmc5883l/test.esp32-ard.yaml diff --git a/tests/components/qmc5883l/test.esp32-c3.yaml b/tests/components/qmc5883l/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/qmc5883l/test.esp32-c3.yaml rename to tests/components/qmc5883l/test.esp32-c3-ard.yaml diff --git a/tests/components/qmc5883l/test.esp8266.yaml b/tests/components/qmc5883l/test.esp8266-ard.yaml similarity index 100% rename from tests/components/qmc5883l/test.esp8266.yaml rename to tests/components/qmc5883l/test.esp8266-ard.yaml diff --git a/tests/components/qmc5883l/test.rp2040.yaml b/tests/components/qmc5883l/test.rp2040-ard.yaml similarity index 100% rename from tests/components/qmc5883l/test.rp2040.yaml rename to tests/components/qmc5883l/test.rp2040-ard.yaml diff --git a/tests/components/qmp6988/test.esp32.yaml b/tests/components/qmp6988/test.esp32-ard.yaml similarity index 100% rename from tests/components/qmp6988/test.esp32.yaml rename to tests/components/qmp6988/test.esp32-ard.yaml diff --git a/tests/components/qmp6988/test.esp32-c3.yaml b/tests/components/qmp6988/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/qmp6988/test.esp32-c3.yaml rename to tests/components/qmp6988/test.esp32-c3-ard.yaml diff --git a/tests/components/qmp6988/test.esp8266.yaml b/tests/components/qmp6988/test.esp8266-ard.yaml similarity index 100% rename from tests/components/qmp6988/test.esp8266.yaml rename to tests/components/qmp6988/test.esp8266-ard.yaml diff --git a/tests/components/qmp6988/test.rp2040.yaml b/tests/components/qmp6988/test.rp2040-ard.yaml similarity index 100% rename from tests/components/qmp6988/test.rp2040.yaml rename to tests/components/qmp6988/test.rp2040-ard.yaml diff --git a/tests/components/qr_code/test.esp32.yaml b/tests/components/qr_code/test.esp32-ard.yaml similarity index 100% rename from tests/components/qr_code/test.esp32.yaml rename to tests/components/qr_code/test.esp32-ard.yaml diff --git a/tests/components/qr_code/test.esp32-c3.yaml b/tests/components/qr_code/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/qr_code/test.esp32-c3.yaml rename to tests/components/qr_code/test.esp32-c3-ard.yaml diff --git a/tests/components/qr_code/test.esp8266.yaml b/tests/components/qr_code/test.esp8266-ard.yaml similarity index 100% rename from tests/components/qr_code/test.esp8266.yaml rename to tests/components/qr_code/test.esp8266-ard.yaml diff --git a/tests/components/qr_code/test.rp2040.yaml b/tests/components/qr_code/test.rp2040-ard.yaml similarity index 100% rename from tests/components/qr_code/test.rp2040.yaml rename to tests/components/qr_code/test.rp2040-ard.yaml diff --git a/tests/components/qwiic_pir/test.esp32.yaml b/tests/components/qwiic_pir/test.esp32-ard.yaml similarity index 100% rename from tests/components/qwiic_pir/test.esp32.yaml rename to tests/components/qwiic_pir/test.esp32-ard.yaml diff --git a/tests/components/qwiic_pir/test.esp32-c3.yaml b/tests/components/qwiic_pir/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/qwiic_pir/test.esp32-c3.yaml rename to tests/components/qwiic_pir/test.esp32-c3-ard.yaml diff --git a/tests/components/qwiic_pir/test.esp8266.yaml b/tests/components/qwiic_pir/test.esp8266-ard.yaml similarity index 100% rename from tests/components/qwiic_pir/test.esp8266.yaml rename to tests/components/qwiic_pir/test.esp8266-ard.yaml diff --git a/tests/components/qwiic_pir/test.rp2040.yaml b/tests/components/qwiic_pir/test.rp2040-ard.yaml similarity index 100% rename from tests/components/qwiic_pir/test.rp2040.yaml rename to tests/components/qwiic_pir/test.rp2040-ard.yaml diff --git a/tests/components/radon_eye_ble/test.esp32-c3.yaml b/tests/components/radon_eye_ble/test.esp32-ard.yaml similarity index 100% rename from tests/components/radon_eye_ble/test.esp32-c3.yaml rename to tests/components/radon_eye_ble/test.esp32-ard.yaml diff --git a/tests/components/radon_eye_ble/test.esp32.yaml b/tests/components/radon_eye_ble/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/radon_eye_ble/test.esp32.yaml rename to tests/components/radon_eye_ble/test.esp32-c3-ard.yaml diff --git a/tests/components/radon_eye_rd200/test.esp32-c3.yaml b/tests/components/radon_eye_rd200/test.esp32-ard.yaml similarity index 100% rename from tests/components/radon_eye_rd200/test.esp32-c3.yaml rename to tests/components/radon_eye_rd200/test.esp32-ard.yaml diff --git a/tests/components/radon_eye_rd200/test.esp32.yaml b/tests/components/radon_eye_rd200/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/radon_eye_rd200/test.esp32.yaml rename to tests/components/radon_eye_rd200/test.esp32-c3-ard.yaml diff --git a/tests/components/rc522_i2c/test.esp32.yaml b/tests/components/rc522_i2c/test.esp32-ard.yaml similarity index 100% rename from tests/components/rc522_i2c/test.esp32.yaml rename to tests/components/rc522_i2c/test.esp32-ard.yaml diff --git a/tests/components/rc522_i2c/test.esp32-c3.yaml b/tests/components/rc522_i2c/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/rc522_i2c/test.esp32-c3.yaml rename to tests/components/rc522_i2c/test.esp32-c3-ard.yaml diff --git a/tests/components/rc522_i2c/test.esp8266.yaml b/tests/components/rc522_i2c/test.esp8266-ard.yaml similarity index 100% rename from tests/components/rc522_i2c/test.esp8266.yaml rename to tests/components/rc522_i2c/test.esp8266-ard.yaml diff --git a/tests/components/rc522_i2c/test.rp2040.yaml b/tests/components/rc522_i2c/test.rp2040-ard.yaml similarity index 100% rename from tests/components/rc522_i2c/test.rp2040.yaml rename to tests/components/rc522_i2c/test.rp2040-ard.yaml diff --git a/tests/components/rc522_spi/test.esp32.yaml b/tests/components/rc522_spi/test.esp32-ard.yaml similarity index 100% rename from tests/components/rc522_spi/test.esp32.yaml rename to tests/components/rc522_spi/test.esp32-ard.yaml diff --git a/tests/components/rc522_spi/test.esp32-c3.yaml b/tests/components/rc522_spi/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/rc522_spi/test.esp32-c3.yaml rename to tests/components/rc522_spi/test.esp32-c3-ard.yaml diff --git a/tests/components/rc522_spi/test.esp8266.yaml b/tests/components/rc522_spi/test.esp8266-ard.yaml similarity index 100% rename from tests/components/rc522_spi/test.esp8266.yaml rename to tests/components/rc522_spi/test.esp8266-ard.yaml diff --git a/tests/components/rc522_spi/test.rp2040.yaml b/tests/components/rc522_spi/test.rp2040-ard.yaml similarity index 100% rename from tests/components/rc522_spi/test.rp2040.yaml rename to tests/components/rc522_spi/test.rp2040-ard.yaml diff --git a/tests/components/rdm6300/test.esp32.yaml b/tests/components/rdm6300/test.esp32-ard.yaml similarity index 100% rename from tests/components/rdm6300/test.esp32.yaml rename to tests/components/rdm6300/test.esp32-ard.yaml diff --git a/tests/components/rdm6300/test.esp32-c3.yaml b/tests/components/rdm6300/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/rdm6300/test.esp32-c3.yaml rename to tests/components/rdm6300/test.esp32-c3-ard.yaml diff --git a/tests/components/rdm6300/test.esp8266.yaml b/tests/components/rdm6300/test.esp8266-ard.yaml similarity index 100% rename from tests/components/rdm6300/test.esp8266.yaml rename to tests/components/rdm6300/test.esp8266-ard.yaml diff --git a/tests/components/rdm6300/test.rp2040.yaml b/tests/components/rdm6300/test.rp2040-ard.yaml similarity index 100% rename from tests/components/rdm6300/test.rp2040.yaml rename to tests/components/rdm6300/test.rp2040-ard.yaml diff --git a/tests/components/remote_receiver/test.esp32-c3.yaml b/tests/components/remote_receiver/test.esp32-ard.yaml similarity index 100% rename from tests/components/remote_receiver/test.esp32-c3.yaml rename to tests/components/remote_receiver/test.esp32-ard.yaml diff --git a/tests/components/remote_receiver/test.esp32.yaml b/tests/components/remote_receiver/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/remote_receiver/test.esp32.yaml rename to tests/components/remote_receiver/test.esp32-c3-ard.yaml diff --git a/tests/components/remote_receiver/test.esp8266.yaml b/tests/components/remote_receiver/test.esp8266-ard.yaml similarity index 100% rename from tests/components/remote_receiver/test.esp8266.yaml rename to tests/components/remote_receiver/test.esp8266-ard.yaml diff --git a/tests/components/remote_transmitter/test.esp32.yaml b/tests/components/remote_transmitter/test.esp32-ard.yaml similarity index 100% rename from tests/components/remote_transmitter/test.esp32.yaml rename to tests/components/remote_transmitter/test.esp32-ard.yaml diff --git a/tests/components/remote_transmitter/test.esp32-c3.yaml b/tests/components/remote_transmitter/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/remote_transmitter/test.esp32-c3.yaml rename to tests/components/remote_transmitter/test.esp32-c3-ard.yaml diff --git a/tests/components/remote_transmitter/test.esp8266.yaml b/tests/components/remote_transmitter/test.esp8266-ard.yaml similarity index 100% rename from tests/components/remote_transmitter/test.esp8266.yaml rename to tests/components/remote_transmitter/test.esp8266-ard.yaml diff --git a/tests/components/resistance/test.esp32.yaml b/tests/components/resistance/test.esp32-ard.yaml similarity index 100% rename from tests/components/resistance/test.esp32.yaml rename to tests/components/resistance/test.esp32-ard.yaml diff --git a/tests/components/resistance/test.esp32-c3.yaml b/tests/components/resistance/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/resistance/test.esp32-c3.yaml rename to tests/components/resistance/test.esp32-c3-ard.yaml diff --git a/tests/components/resistance/test.esp32-s2.yaml b/tests/components/resistance/test.esp32-s2-ard.yaml similarity index 100% rename from tests/components/resistance/test.esp32-s2.yaml rename to tests/components/resistance/test.esp32-s2-ard.yaml diff --git a/tests/components/resistance/test.esp32-s3.yaml b/tests/components/resistance/test.esp32-s3-ard.yaml similarity index 100% rename from tests/components/resistance/test.esp32-s3.yaml rename to tests/components/resistance/test.esp32-s3-ard.yaml diff --git a/tests/components/resistance/test.esp8266.yaml b/tests/components/resistance/test.esp8266-ard.yaml similarity index 100% rename from tests/components/resistance/test.esp8266.yaml rename to tests/components/resistance/test.esp8266-ard.yaml diff --git a/tests/components/resistance/test.rp2040.yaml b/tests/components/resistance/test.rp2040-ard.yaml similarity index 100% rename from tests/components/resistance/test.rp2040.yaml rename to tests/components/resistance/test.rp2040-ard.yaml diff --git a/tests/components/restart/test.esp32-c3.yaml b/tests/components/restart/test.esp32-ard.yaml similarity index 100% rename from tests/components/restart/test.esp32-c3.yaml rename to tests/components/restart/test.esp32-ard.yaml diff --git a/tests/components/restart/test.esp32.yaml b/tests/components/restart/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/restart/test.esp32.yaml rename to tests/components/restart/test.esp32-c3-ard.yaml diff --git a/tests/components/restart/test.esp8266.yaml b/tests/components/restart/test.esp8266-ard.yaml similarity index 100% rename from tests/components/restart/test.esp8266.yaml rename to tests/components/restart/test.esp8266-ard.yaml diff --git a/tests/components/restart/test.rp2040.yaml b/tests/components/restart/test.rp2040-ard.yaml similarity index 100% rename from tests/components/restart/test.rp2040.yaml rename to tests/components/restart/test.rp2040-ard.yaml diff --git a/tests/components/rf_bridge/test.esp32.yaml b/tests/components/rf_bridge/test.esp32-ard.yaml similarity index 100% rename from tests/components/rf_bridge/test.esp32.yaml rename to tests/components/rf_bridge/test.esp32-ard.yaml diff --git a/tests/components/rf_bridge/test.esp32-c3.yaml b/tests/components/rf_bridge/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/rf_bridge/test.esp32-c3.yaml rename to tests/components/rf_bridge/test.esp32-c3-ard.yaml diff --git a/tests/components/rf_bridge/test.esp8266.yaml b/tests/components/rf_bridge/test.esp8266-ard.yaml similarity index 100% rename from tests/components/rf_bridge/test.esp8266.yaml rename to tests/components/rf_bridge/test.esp8266-ard.yaml diff --git a/tests/components/rf_bridge/test.rp2040.yaml b/tests/components/rf_bridge/test.rp2040-ard.yaml similarity index 100% rename from tests/components/rf_bridge/test.rp2040.yaml rename to tests/components/rf_bridge/test.rp2040-ard.yaml diff --git a/tests/components/rgb/test.esp32.yaml b/tests/components/rgb/test.esp32-ard.yaml similarity index 100% rename from tests/components/rgb/test.esp32.yaml rename to tests/components/rgb/test.esp32-ard.yaml diff --git a/tests/components/rgb/test.esp32-c3.yaml b/tests/components/rgb/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/rgb/test.esp32-c3.yaml rename to tests/components/rgb/test.esp32-c3-ard.yaml diff --git a/tests/components/rgb/test.esp8266.yaml b/tests/components/rgb/test.esp8266-ard.yaml similarity index 100% rename from tests/components/rgb/test.esp8266.yaml rename to tests/components/rgb/test.esp8266-ard.yaml diff --git a/tests/components/rgb/test.rp2040.yaml b/tests/components/rgb/test.rp2040-ard.yaml similarity index 100% rename from tests/components/rgb/test.rp2040.yaml rename to tests/components/rgb/test.rp2040-ard.yaml diff --git a/tests/components/rgbct/test.esp32.yaml b/tests/components/rgbct/test.esp32-ard.yaml similarity index 100% rename from tests/components/rgbct/test.esp32.yaml rename to tests/components/rgbct/test.esp32-ard.yaml diff --git a/tests/components/rgbct/test.esp32-c3.yaml b/tests/components/rgbct/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/rgbct/test.esp32-c3.yaml rename to tests/components/rgbct/test.esp32-c3-ard.yaml diff --git a/tests/components/rgbct/test.esp8266.yaml b/tests/components/rgbct/test.esp8266-ard.yaml similarity index 100% rename from tests/components/rgbct/test.esp8266.yaml rename to tests/components/rgbct/test.esp8266-ard.yaml diff --git a/tests/components/rgbct/test.rp2040.yaml b/tests/components/rgbct/test.rp2040-ard.yaml similarity index 100% rename from tests/components/rgbct/test.rp2040.yaml rename to tests/components/rgbct/test.rp2040-ard.yaml diff --git a/tests/components/rgbw/test.esp32.yaml b/tests/components/rgbw/test.esp32-ard.yaml similarity index 100% rename from tests/components/rgbw/test.esp32.yaml rename to tests/components/rgbw/test.esp32-ard.yaml diff --git a/tests/components/rgbw/test.esp32-c3.yaml b/tests/components/rgbw/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/rgbw/test.esp32-c3.yaml rename to tests/components/rgbw/test.esp32-c3-ard.yaml diff --git a/tests/components/rgbw/test.esp8266.yaml b/tests/components/rgbw/test.esp8266-ard.yaml similarity index 100% rename from tests/components/rgbw/test.esp8266.yaml rename to tests/components/rgbw/test.esp8266-ard.yaml diff --git a/tests/components/rgbw/test.rp2040.yaml b/tests/components/rgbw/test.rp2040-ard.yaml similarity index 100% rename from tests/components/rgbw/test.rp2040.yaml rename to tests/components/rgbw/test.rp2040-ard.yaml diff --git a/tests/components/rgbww/test.esp32.yaml b/tests/components/rgbww/test.esp32-ard.yaml similarity index 100% rename from tests/components/rgbww/test.esp32.yaml rename to tests/components/rgbww/test.esp32-ard.yaml diff --git a/tests/components/rgbww/test.esp32-c3.yaml b/tests/components/rgbww/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/rgbww/test.esp32-c3.yaml rename to tests/components/rgbww/test.esp32-c3-ard.yaml diff --git a/tests/components/rgbww/test.esp8266.yaml b/tests/components/rgbww/test.esp8266-ard.yaml similarity index 100% rename from tests/components/rgbww/test.esp8266.yaml rename to tests/components/rgbww/test.esp8266-ard.yaml diff --git a/tests/components/rgbww/test.rp2040.yaml b/tests/components/rgbww/test.rp2040-ard.yaml similarity index 100% rename from tests/components/rgbww/test.rp2040.yaml rename to tests/components/rgbww/test.rp2040-ard.yaml diff --git a/tests/components/rotary_encoder/test.esp32.yaml b/tests/components/rotary_encoder/test.esp32-ard.yaml similarity index 100% rename from tests/components/rotary_encoder/test.esp32.yaml rename to tests/components/rotary_encoder/test.esp32-ard.yaml diff --git a/tests/components/rotary_encoder/test.esp32-c3.yaml b/tests/components/rotary_encoder/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/rotary_encoder/test.esp32-c3.yaml rename to tests/components/rotary_encoder/test.esp32-c3-ard.yaml diff --git a/tests/components/rotary_encoder/test.esp8266.yaml b/tests/components/rotary_encoder/test.esp8266-ard.yaml similarity index 100% rename from tests/components/rotary_encoder/test.esp8266.yaml rename to tests/components/rotary_encoder/test.esp8266-ard.yaml diff --git a/tests/components/rotary_encoder/test.rp2040.yaml b/tests/components/rotary_encoder/test.rp2040-ard.yaml similarity index 100% rename from tests/components/rotary_encoder/test.rp2040.yaml rename to tests/components/rotary_encoder/test.rp2040-ard.yaml diff --git a/tests/components/rp2040_pio_led_strip/test.rp2040.yaml b/tests/components/rp2040_pio_led_strip/test.rp2040-ard.yaml similarity index 100% rename from tests/components/rp2040_pio_led_strip/test.rp2040.yaml rename to tests/components/rp2040_pio_led_strip/test.rp2040-ard.yaml diff --git a/tests/components/rp2040_pwm/test.rp2040.yaml b/tests/components/rp2040_pwm/test.rp2040-ard.yaml similarity index 100% rename from tests/components/rp2040_pwm/test.rp2040.yaml rename to tests/components/rp2040_pwm/test.rp2040-ard.yaml diff --git a/tests/components/rtttl/test.esp32.yaml b/tests/components/rtttl/test.esp32-ard.yaml similarity index 100% rename from tests/components/rtttl/test.esp32.yaml rename to tests/components/rtttl/test.esp32-ard.yaml diff --git a/tests/components/rtttl/test.esp32-c3.yaml b/tests/components/rtttl/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/rtttl/test.esp32-c3.yaml rename to tests/components/rtttl/test.esp32-c3-ard.yaml diff --git a/tests/components/rtttl/test.esp8266.yaml b/tests/components/rtttl/test.esp8266-ard.yaml similarity index 100% rename from tests/components/rtttl/test.esp8266.yaml rename to tests/components/rtttl/test.esp8266-ard.yaml diff --git a/tests/components/rtttl/test.rp2040.yaml b/tests/components/rtttl/test.rp2040-ard.yaml similarity index 100% rename from tests/components/rtttl/test.rp2040.yaml rename to tests/components/rtttl/test.rp2040-ard.yaml diff --git a/tests/components/ruuvi_ble/test.esp32-c3.yaml b/tests/components/ruuvi_ble/test.esp32-ard.yaml similarity index 100% rename from tests/components/ruuvi_ble/test.esp32-c3.yaml rename to tests/components/ruuvi_ble/test.esp32-ard.yaml diff --git a/tests/components/ruuvi_ble/test.esp32.yaml b/tests/components/ruuvi_ble/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ruuvi_ble/test.esp32.yaml rename to tests/components/ruuvi_ble/test.esp32-c3-ard.yaml diff --git a/tests/components/ruuvitag/test.esp32-c3.yaml b/tests/components/ruuvitag/test.esp32-ard.yaml similarity index 100% rename from tests/components/ruuvitag/test.esp32-c3.yaml rename to tests/components/ruuvitag/test.esp32-ard.yaml diff --git a/tests/components/ruuvitag/test.esp32.yaml b/tests/components/ruuvitag/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ruuvitag/test.esp32.yaml rename to tests/components/ruuvitag/test.esp32-c3-ard.yaml diff --git a/tests/components/safe_mode/test.esp32-c3.yaml b/tests/components/safe_mode/test.esp32-ard.yaml similarity index 100% rename from tests/components/safe_mode/test.esp32-c3.yaml rename to tests/components/safe_mode/test.esp32-ard.yaml diff --git a/tests/components/safe_mode/test.esp32.yaml b/tests/components/safe_mode/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/safe_mode/test.esp32.yaml rename to tests/components/safe_mode/test.esp32-c3-ard.yaml diff --git a/tests/components/safe_mode/test.esp8266.yaml b/tests/components/safe_mode/test.esp8266-ard.yaml similarity index 100% rename from tests/components/safe_mode/test.esp8266.yaml rename to tests/components/safe_mode/test.esp8266-ard.yaml diff --git a/tests/components/safe_mode/test.rp2040.yaml b/tests/components/safe_mode/test.rp2040-ard.yaml similarity index 100% rename from tests/components/safe_mode/test.rp2040.yaml rename to tests/components/safe_mode/test.rp2040-ard.yaml diff --git a/tests/components/scd30/test.esp32.yaml b/tests/components/scd30/test.esp32-ard.yaml similarity index 100% rename from tests/components/scd30/test.esp32.yaml rename to tests/components/scd30/test.esp32-ard.yaml diff --git a/tests/components/scd30/test.esp32-c3.yaml b/tests/components/scd30/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/scd30/test.esp32-c3.yaml rename to tests/components/scd30/test.esp32-c3-ard.yaml diff --git a/tests/components/scd30/test.esp8266.yaml b/tests/components/scd30/test.esp8266-ard.yaml similarity index 100% rename from tests/components/scd30/test.esp8266.yaml rename to tests/components/scd30/test.esp8266-ard.yaml diff --git a/tests/components/scd30/test.rp2040.yaml b/tests/components/scd30/test.rp2040-ard.yaml similarity index 100% rename from tests/components/scd30/test.rp2040.yaml rename to tests/components/scd30/test.rp2040-ard.yaml diff --git a/tests/components/scd4x/test.esp32.yaml b/tests/components/scd4x/test.esp32-ard.yaml similarity index 100% rename from tests/components/scd4x/test.esp32.yaml rename to tests/components/scd4x/test.esp32-ard.yaml diff --git a/tests/components/scd4x/test.esp32-c3.yaml b/tests/components/scd4x/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/scd4x/test.esp32-c3.yaml rename to tests/components/scd4x/test.esp32-c3-ard.yaml diff --git a/tests/components/scd4x/test.esp8266.yaml b/tests/components/scd4x/test.esp8266-ard.yaml similarity index 100% rename from tests/components/scd4x/test.esp8266.yaml rename to tests/components/scd4x/test.esp8266-ard.yaml diff --git a/tests/components/scd4x/test.rp2040.yaml b/tests/components/scd4x/test.rp2040-ard.yaml similarity index 100% rename from tests/components/scd4x/test.rp2040.yaml rename to tests/components/scd4x/test.rp2040-ard.yaml diff --git a/tests/components/script/test.bk72xx.yaml b/tests/components/script/test.bk72xx-ard.yaml similarity index 100% rename from tests/components/script/test.bk72xx.yaml rename to tests/components/script/test.bk72xx-ard.yaml diff --git a/tests/components/script/test.esp32-c3.yaml b/tests/components/script/test.esp32-ard.yaml similarity index 100% rename from tests/components/script/test.esp32-c3.yaml rename to tests/components/script/test.esp32-ard.yaml diff --git a/tests/components/script/test.esp32.yaml b/tests/components/script/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/script/test.esp32.yaml rename to tests/components/script/test.esp32-c3-ard.yaml diff --git a/tests/components/script/test.esp8266.yaml b/tests/components/script/test.esp8266-ard.yaml similarity index 100% rename from tests/components/script/test.esp8266.yaml rename to tests/components/script/test.esp8266-ard.yaml diff --git a/tests/components/script/test.rp2040.yaml b/tests/components/script/test.rp2040-ard.yaml similarity index 100% rename from tests/components/script/test.rp2040.yaml rename to tests/components/script/test.rp2040-ard.yaml diff --git a/tests/components/sdm_meter/test.esp32.yaml b/tests/components/sdm_meter/test.esp32-ard.yaml similarity index 100% rename from tests/components/sdm_meter/test.esp32.yaml rename to tests/components/sdm_meter/test.esp32-ard.yaml diff --git a/tests/components/sdm_meter/test.esp32-c3.yaml b/tests/components/sdm_meter/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/sdm_meter/test.esp32-c3.yaml rename to tests/components/sdm_meter/test.esp32-c3-ard.yaml diff --git a/tests/components/sdm_meter/test.esp8266.yaml b/tests/components/sdm_meter/test.esp8266-ard.yaml similarity index 100% rename from tests/components/sdm_meter/test.esp8266.yaml rename to tests/components/sdm_meter/test.esp8266-ard.yaml diff --git a/tests/components/sdm_meter/test.rp2040.yaml b/tests/components/sdm_meter/test.rp2040-ard.yaml similarity index 100% rename from tests/components/sdm_meter/test.rp2040.yaml rename to tests/components/sdm_meter/test.rp2040-ard.yaml diff --git a/tests/components/sdp3x/test.esp32.yaml b/tests/components/sdp3x/test.esp32-ard.yaml similarity index 100% rename from tests/components/sdp3x/test.esp32.yaml rename to tests/components/sdp3x/test.esp32-ard.yaml diff --git a/tests/components/sdp3x/test.esp32-c3.yaml b/tests/components/sdp3x/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/sdp3x/test.esp32-c3.yaml rename to tests/components/sdp3x/test.esp32-c3-ard.yaml diff --git a/tests/components/sdp3x/test.esp8266.yaml b/tests/components/sdp3x/test.esp8266-ard.yaml similarity index 100% rename from tests/components/sdp3x/test.esp8266.yaml rename to tests/components/sdp3x/test.esp8266-ard.yaml diff --git a/tests/components/sdp3x/test.rp2040.yaml b/tests/components/sdp3x/test.rp2040-ard.yaml similarity index 100% rename from tests/components/sdp3x/test.rp2040.yaml rename to tests/components/sdp3x/test.rp2040-ard.yaml diff --git a/tests/components/sds011/test.esp32.yaml b/tests/components/sds011/test.esp32-ard.yaml similarity index 100% rename from tests/components/sds011/test.esp32.yaml rename to tests/components/sds011/test.esp32-ard.yaml diff --git a/tests/components/sds011/test.esp32-c3.yaml b/tests/components/sds011/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/sds011/test.esp32-c3.yaml rename to tests/components/sds011/test.esp32-c3-ard.yaml diff --git a/tests/components/sds011/test.esp8266.yaml b/tests/components/sds011/test.esp8266-ard.yaml similarity index 100% rename from tests/components/sds011/test.esp8266.yaml rename to tests/components/sds011/test.esp8266-ard.yaml diff --git a/tests/components/sds011/test.rp2040.yaml b/tests/components/sds011/test.rp2040-ard.yaml similarity index 100% rename from tests/components/sds011/test.rp2040.yaml rename to tests/components/sds011/test.rp2040-ard.yaml diff --git a/tests/components/seeed_mr24hpc1/test.esp32-c3.yaml b/tests/components/seeed_mr24hpc1/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/seeed_mr24hpc1/test.esp32-c3.yaml rename to tests/components/seeed_mr24hpc1/test.esp32-c3-ard.yaml diff --git a/tests/components/selec_meter/test.esp32.yaml b/tests/components/selec_meter/test.esp32-ard.yaml similarity index 100% rename from tests/components/selec_meter/test.esp32.yaml rename to tests/components/selec_meter/test.esp32-ard.yaml diff --git a/tests/components/selec_meter/test.esp32-c3.yaml b/tests/components/selec_meter/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/selec_meter/test.esp32-c3.yaml rename to tests/components/selec_meter/test.esp32-c3-ard.yaml diff --git a/tests/components/selec_meter/test.esp8266.yaml b/tests/components/selec_meter/test.esp8266-ard.yaml similarity index 100% rename from tests/components/selec_meter/test.esp8266.yaml rename to tests/components/selec_meter/test.esp8266-ard.yaml diff --git a/tests/components/selec_meter/test.rp2040.yaml b/tests/components/selec_meter/test.rp2040-ard.yaml similarity index 100% rename from tests/components/selec_meter/test.rp2040.yaml rename to tests/components/selec_meter/test.rp2040-ard.yaml diff --git a/tests/components/sen0321/test.esp32.yaml b/tests/components/sen0321/test.esp32-ard.yaml similarity index 100% rename from tests/components/sen0321/test.esp32.yaml rename to tests/components/sen0321/test.esp32-ard.yaml diff --git a/tests/components/sen0321/test.esp32-c3.yaml b/tests/components/sen0321/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/sen0321/test.esp32-c3.yaml rename to tests/components/sen0321/test.esp32-c3-ard.yaml diff --git a/tests/components/sen0321/test.esp8266.yaml b/tests/components/sen0321/test.esp8266-ard.yaml similarity index 100% rename from tests/components/sen0321/test.esp8266.yaml rename to tests/components/sen0321/test.esp8266-ard.yaml diff --git a/tests/components/sen0321/test.rp2040.yaml b/tests/components/sen0321/test.rp2040-ard.yaml similarity index 100% rename from tests/components/sen0321/test.rp2040.yaml rename to tests/components/sen0321/test.rp2040-ard.yaml diff --git a/tests/components/sen21231/test.esp32.yaml b/tests/components/sen21231/test.esp32-ard.yaml similarity index 100% rename from tests/components/sen21231/test.esp32.yaml rename to tests/components/sen21231/test.esp32-ard.yaml diff --git a/tests/components/sen21231/test.esp32-c3.yaml b/tests/components/sen21231/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/sen21231/test.esp32-c3.yaml rename to tests/components/sen21231/test.esp32-c3-ard.yaml diff --git a/tests/components/sen21231/test.esp8266.yaml b/tests/components/sen21231/test.esp8266-ard.yaml similarity index 100% rename from tests/components/sen21231/test.esp8266.yaml rename to tests/components/sen21231/test.esp8266-ard.yaml diff --git a/tests/components/sen21231/test.rp2040.yaml b/tests/components/sen21231/test.rp2040-ard.yaml similarity index 100% rename from tests/components/sen21231/test.rp2040.yaml rename to tests/components/sen21231/test.rp2040-ard.yaml diff --git a/tests/components/sen5x/test.esp32.yaml b/tests/components/sen5x/test.esp32-ard.yaml similarity index 100% rename from tests/components/sen5x/test.esp32.yaml rename to tests/components/sen5x/test.esp32-ard.yaml diff --git a/tests/components/sen5x/test.esp32-c3.yaml b/tests/components/sen5x/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/sen5x/test.esp32-c3.yaml rename to tests/components/sen5x/test.esp32-c3-ard.yaml diff --git a/tests/components/sen5x/test.esp8266.yaml b/tests/components/sen5x/test.esp8266-ard.yaml similarity index 100% rename from tests/components/sen5x/test.esp8266.yaml rename to tests/components/sen5x/test.esp8266-ard.yaml diff --git a/tests/components/sen5x/test.rp2040.yaml b/tests/components/sen5x/test.rp2040-ard.yaml similarity index 100% rename from tests/components/sen5x/test.rp2040.yaml rename to tests/components/sen5x/test.rp2040-ard.yaml diff --git a/tests/components/senseair/test.esp32.yaml b/tests/components/senseair/test.esp32-ard.yaml similarity index 100% rename from tests/components/senseair/test.esp32.yaml rename to tests/components/senseair/test.esp32-ard.yaml diff --git a/tests/components/senseair/test.esp32-c3.yaml b/tests/components/senseair/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/senseair/test.esp32-c3.yaml rename to tests/components/senseair/test.esp32-c3-ard.yaml diff --git a/tests/components/senseair/test.esp8266.yaml b/tests/components/senseair/test.esp8266-ard.yaml similarity index 100% rename from tests/components/senseair/test.esp8266.yaml rename to tests/components/senseair/test.esp8266-ard.yaml diff --git a/tests/components/senseair/test.rp2040.yaml b/tests/components/senseair/test.rp2040-ard.yaml similarity index 100% rename from tests/components/senseair/test.rp2040.yaml rename to tests/components/senseair/test.rp2040-ard.yaml diff --git a/tests/components/servo/test.esp32.yaml b/tests/components/servo/test.esp32-ard.yaml similarity index 100% rename from tests/components/servo/test.esp32.yaml rename to tests/components/servo/test.esp32-ard.yaml diff --git a/tests/components/servo/test.esp32-c3.yaml b/tests/components/servo/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/servo/test.esp32-c3.yaml rename to tests/components/servo/test.esp32-c3-ard.yaml diff --git a/tests/components/servo/test.esp8266.yaml b/tests/components/servo/test.esp8266-ard.yaml similarity index 100% rename from tests/components/servo/test.esp8266.yaml rename to tests/components/servo/test.esp8266-ard.yaml diff --git a/tests/components/servo/test.rp2040.yaml b/tests/components/servo/test.rp2040-ard.yaml similarity index 100% rename from tests/components/servo/test.rp2040.yaml rename to tests/components/servo/test.rp2040-ard.yaml diff --git a/tests/components/sfa30/test.esp32.yaml b/tests/components/sfa30/test.esp32-ard.yaml similarity index 100% rename from tests/components/sfa30/test.esp32.yaml rename to tests/components/sfa30/test.esp32-ard.yaml diff --git a/tests/components/sfa30/test.esp32-c3.yaml b/tests/components/sfa30/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/sfa30/test.esp32-c3.yaml rename to tests/components/sfa30/test.esp32-c3-ard.yaml diff --git a/tests/components/sfa30/test.esp8266.yaml b/tests/components/sfa30/test.esp8266-ard.yaml similarity index 100% rename from tests/components/sfa30/test.esp8266.yaml rename to tests/components/sfa30/test.esp8266-ard.yaml diff --git a/tests/components/sfa30/test.rp2040.yaml b/tests/components/sfa30/test.rp2040-ard.yaml similarity index 100% rename from tests/components/sfa30/test.rp2040.yaml rename to tests/components/sfa30/test.rp2040-ard.yaml diff --git a/tests/components/sgp30/test.esp32.yaml b/tests/components/sgp30/test.esp32-ard.yaml similarity index 100% rename from tests/components/sgp30/test.esp32.yaml rename to tests/components/sgp30/test.esp32-ard.yaml diff --git a/tests/components/sgp30/test.esp32-c3.yaml b/tests/components/sgp30/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/sgp30/test.esp32-c3.yaml rename to tests/components/sgp30/test.esp32-c3-ard.yaml diff --git a/tests/components/sgp30/test.esp8266.yaml b/tests/components/sgp30/test.esp8266-ard.yaml similarity index 100% rename from tests/components/sgp30/test.esp8266.yaml rename to tests/components/sgp30/test.esp8266-ard.yaml diff --git a/tests/components/sgp30/test.rp2040.yaml b/tests/components/sgp30/test.rp2040-ard.yaml similarity index 100% rename from tests/components/sgp30/test.rp2040.yaml rename to tests/components/sgp30/test.rp2040-ard.yaml diff --git a/tests/components/sgp4x/test.esp32.yaml b/tests/components/sgp4x/test.esp32-ard.yaml similarity index 100% rename from tests/components/sgp4x/test.esp32.yaml rename to tests/components/sgp4x/test.esp32-ard.yaml diff --git a/tests/components/sgp4x/test.esp32-c3.yaml b/tests/components/sgp4x/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/sgp4x/test.esp32-c3.yaml rename to tests/components/sgp4x/test.esp32-c3-ard.yaml diff --git a/tests/components/sgp4x/test.esp8266.yaml b/tests/components/sgp4x/test.esp8266-ard.yaml similarity index 100% rename from tests/components/sgp4x/test.esp8266.yaml rename to tests/components/sgp4x/test.esp8266-ard.yaml diff --git a/tests/components/sgp4x/test.rp2040.yaml b/tests/components/sgp4x/test.rp2040-ard.yaml similarity index 100% rename from tests/components/sgp4x/test.rp2040.yaml rename to tests/components/sgp4x/test.rp2040-ard.yaml diff --git a/tests/components/shelly_dimmer/test.esp8266.yaml b/tests/components/shelly_dimmer/test.esp8266-ard.yaml similarity index 100% rename from tests/components/shelly_dimmer/test.esp8266.yaml rename to tests/components/shelly_dimmer/test.esp8266-ard.yaml diff --git a/tests/components/sht3xd/test.esp32.yaml b/tests/components/sht3xd/test.esp32-ard.yaml similarity index 100% rename from tests/components/sht3xd/test.esp32.yaml rename to tests/components/sht3xd/test.esp32-ard.yaml diff --git a/tests/components/sht3xd/test.esp32-c3.yaml b/tests/components/sht3xd/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/sht3xd/test.esp32-c3.yaml rename to tests/components/sht3xd/test.esp32-c3-ard.yaml diff --git a/tests/components/sht3xd/test.esp8266.yaml b/tests/components/sht3xd/test.esp8266-ard.yaml similarity index 100% rename from tests/components/sht3xd/test.esp8266.yaml rename to tests/components/sht3xd/test.esp8266-ard.yaml diff --git a/tests/components/sht3xd/test.rp2040.yaml b/tests/components/sht3xd/test.rp2040-ard.yaml similarity index 100% rename from tests/components/sht3xd/test.rp2040.yaml rename to tests/components/sht3xd/test.rp2040-ard.yaml diff --git a/tests/components/sht4x/test.esp32.yaml b/tests/components/sht4x/test.esp32-ard.yaml similarity index 100% rename from tests/components/sht4x/test.esp32.yaml rename to tests/components/sht4x/test.esp32-ard.yaml diff --git a/tests/components/sht4x/test.esp32-c3.yaml b/tests/components/sht4x/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/sht4x/test.esp32-c3.yaml rename to tests/components/sht4x/test.esp32-c3-ard.yaml diff --git a/tests/components/sht4x/test.esp8266.yaml b/tests/components/sht4x/test.esp8266-ard.yaml similarity index 100% rename from tests/components/sht4x/test.esp8266.yaml rename to tests/components/sht4x/test.esp8266-ard.yaml diff --git a/tests/components/sht4x/test.rp2040.yaml b/tests/components/sht4x/test.rp2040-ard.yaml similarity index 100% rename from tests/components/sht4x/test.rp2040.yaml rename to tests/components/sht4x/test.rp2040-ard.yaml diff --git a/tests/components/shtcx/test.esp32.yaml b/tests/components/shtcx/test.esp32-ard.yaml similarity index 100% rename from tests/components/shtcx/test.esp32.yaml rename to tests/components/shtcx/test.esp32-ard.yaml diff --git a/tests/components/shtcx/test.esp32-c3.yaml b/tests/components/shtcx/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/shtcx/test.esp32-c3.yaml rename to tests/components/shtcx/test.esp32-c3-ard.yaml diff --git a/tests/components/shtcx/test.esp8266.yaml b/tests/components/shtcx/test.esp8266-ard.yaml similarity index 100% rename from tests/components/shtcx/test.esp8266.yaml rename to tests/components/shtcx/test.esp8266-ard.yaml diff --git a/tests/components/shtcx/test.rp2040.yaml b/tests/components/shtcx/test.rp2040-ard.yaml similarity index 100% rename from tests/components/shtcx/test.rp2040.yaml rename to tests/components/shtcx/test.rp2040-ard.yaml diff --git a/tests/components/shutdown/test.esp32-c3.yaml b/tests/components/shutdown/test.esp32-ard.yaml similarity index 100% rename from tests/components/shutdown/test.esp32-c3.yaml rename to tests/components/shutdown/test.esp32-ard.yaml diff --git a/tests/components/shutdown/test.esp32.yaml b/tests/components/shutdown/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/shutdown/test.esp32.yaml rename to tests/components/shutdown/test.esp32-c3-ard.yaml diff --git a/tests/components/shutdown/test.esp8266.yaml b/tests/components/shutdown/test.esp8266-ard.yaml similarity index 100% rename from tests/components/shutdown/test.esp8266.yaml rename to tests/components/shutdown/test.esp8266-ard.yaml diff --git a/tests/components/shutdown/test.rp2040.yaml b/tests/components/shutdown/test.rp2040-ard.yaml similarity index 100% rename from tests/components/shutdown/test.rp2040.yaml rename to tests/components/shutdown/test.rp2040-ard.yaml diff --git a/tests/components/sigma_delta_output/test.esp32-c3.yaml b/tests/components/sigma_delta_output/test.esp32-ard.yaml similarity index 100% rename from tests/components/sigma_delta_output/test.esp32-c3.yaml rename to tests/components/sigma_delta_output/test.esp32-ard.yaml diff --git a/tests/components/sigma_delta_output/test.esp32.yaml b/tests/components/sigma_delta_output/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/sigma_delta_output/test.esp32.yaml rename to tests/components/sigma_delta_output/test.esp32-c3-ard.yaml diff --git a/tests/components/sigma_delta_output/test.esp8266.yaml b/tests/components/sigma_delta_output/test.esp8266-ard.yaml similarity index 100% rename from tests/components/sigma_delta_output/test.esp8266.yaml rename to tests/components/sigma_delta_output/test.esp8266-ard.yaml diff --git a/tests/components/sigma_delta_output/test.rp2040.yaml b/tests/components/sigma_delta_output/test.rp2040-ard.yaml similarity index 100% rename from tests/components/sigma_delta_output/test.rp2040.yaml rename to tests/components/sigma_delta_output/test.rp2040-ard.yaml diff --git a/tests/components/sim800l/test.esp32.yaml b/tests/components/sim800l/test.esp32-ard.yaml similarity index 100% rename from tests/components/sim800l/test.esp32.yaml rename to tests/components/sim800l/test.esp32-ard.yaml diff --git a/tests/components/sim800l/test.esp32-c3.yaml b/tests/components/sim800l/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/sim800l/test.esp32-c3.yaml rename to tests/components/sim800l/test.esp32-c3-ard.yaml diff --git a/tests/components/sim800l/test.esp8266.yaml b/tests/components/sim800l/test.esp8266-ard.yaml similarity index 100% rename from tests/components/sim800l/test.esp8266.yaml rename to tests/components/sim800l/test.esp8266-ard.yaml diff --git a/tests/components/sim800l/test.rp2040.yaml b/tests/components/sim800l/test.rp2040-ard.yaml similarity index 100% rename from tests/components/sim800l/test.rp2040.yaml rename to tests/components/sim800l/test.rp2040-ard.yaml diff --git a/tests/components/slow_pwm/test.esp32-c3.yaml b/tests/components/slow_pwm/test.esp32-ard.yaml similarity index 100% rename from tests/components/slow_pwm/test.esp32-c3.yaml rename to tests/components/slow_pwm/test.esp32-ard.yaml diff --git a/tests/components/slow_pwm/test.esp32.yaml b/tests/components/slow_pwm/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/slow_pwm/test.esp32.yaml rename to tests/components/slow_pwm/test.esp32-c3-ard.yaml diff --git a/tests/components/slow_pwm/test.esp8266.yaml b/tests/components/slow_pwm/test.esp8266-ard.yaml similarity index 100% rename from tests/components/slow_pwm/test.esp8266.yaml rename to tests/components/slow_pwm/test.esp8266-ard.yaml diff --git a/tests/components/slow_pwm/test.rp2040.yaml b/tests/components/slow_pwm/test.rp2040-ard.yaml similarity index 100% rename from tests/components/slow_pwm/test.rp2040.yaml rename to tests/components/slow_pwm/test.rp2040-ard.yaml diff --git a/tests/components/sm16716/test.esp32-c3.yaml b/tests/components/sm16716/test.esp32-ard.yaml similarity index 100% rename from tests/components/sm16716/test.esp32-c3.yaml rename to tests/components/sm16716/test.esp32-ard.yaml diff --git a/tests/components/sm16716/test.esp32.yaml b/tests/components/sm16716/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/sm16716/test.esp32.yaml rename to tests/components/sm16716/test.esp32-c3-ard.yaml diff --git a/tests/components/sm16716/test.esp8266.yaml b/tests/components/sm16716/test.esp8266-ard.yaml similarity index 100% rename from tests/components/sm16716/test.esp8266.yaml rename to tests/components/sm16716/test.esp8266-ard.yaml diff --git a/tests/components/sm16716/test.rp2040.yaml b/tests/components/sm16716/test.rp2040-ard.yaml similarity index 100% rename from tests/components/sm16716/test.rp2040.yaml rename to tests/components/sm16716/test.rp2040-ard.yaml diff --git a/tests/components/sm2135/test.esp32-c3.yaml b/tests/components/sm2135/test.esp32-ard.yaml similarity index 100% rename from tests/components/sm2135/test.esp32-c3.yaml rename to tests/components/sm2135/test.esp32-ard.yaml diff --git a/tests/components/sm2135/test.esp32.yaml b/tests/components/sm2135/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/sm2135/test.esp32.yaml rename to tests/components/sm2135/test.esp32-c3-ard.yaml diff --git a/tests/components/sm2135/test.esp8266.yaml b/tests/components/sm2135/test.esp8266-ard.yaml similarity index 100% rename from tests/components/sm2135/test.esp8266.yaml rename to tests/components/sm2135/test.esp8266-ard.yaml diff --git a/tests/components/sm2135/test.rp2040.yaml b/tests/components/sm2135/test.rp2040-ard.yaml similarity index 100% rename from tests/components/sm2135/test.rp2040.yaml rename to tests/components/sm2135/test.rp2040-ard.yaml diff --git a/tests/components/sm2235/test.esp32-c3.yaml b/tests/components/sm2235/test.esp32-ard.yaml similarity index 100% rename from tests/components/sm2235/test.esp32-c3.yaml rename to tests/components/sm2235/test.esp32-ard.yaml diff --git a/tests/components/sm2235/test.esp32.yaml b/tests/components/sm2235/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/sm2235/test.esp32.yaml rename to tests/components/sm2235/test.esp32-c3-ard.yaml diff --git a/tests/components/sm2235/test.esp8266.yaml b/tests/components/sm2235/test.esp8266-ard.yaml similarity index 100% rename from tests/components/sm2235/test.esp8266.yaml rename to tests/components/sm2235/test.esp8266-ard.yaml diff --git a/tests/components/sm2235/test.rp2040.yaml b/tests/components/sm2235/test.rp2040-ard.yaml similarity index 100% rename from tests/components/sm2235/test.rp2040.yaml rename to tests/components/sm2235/test.rp2040-ard.yaml diff --git a/tests/components/sm2335/test.esp32-c3.yaml b/tests/components/sm2335/test.esp32-ard.yaml similarity index 100% rename from tests/components/sm2335/test.esp32-c3.yaml rename to tests/components/sm2335/test.esp32-ard.yaml diff --git a/tests/components/sm2335/test.esp32.yaml b/tests/components/sm2335/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/sm2335/test.esp32.yaml rename to tests/components/sm2335/test.esp32-c3-ard.yaml diff --git a/tests/components/sm2335/test.esp8266.yaml b/tests/components/sm2335/test.esp8266-ard.yaml similarity index 100% rename from tests/components/sm2335/test.esp8266.yaml rename to tests/components/sm2335/test.esp8266-ard.yaml diff --git a/tests/components/sm2335/test.rp2040.yaml b/tests/components/sm2335/test.rp2040-ard.yaml similarity index 100% rename from tests/components/sm2335/test.rp2040.yaml rename to tests/components/sm2335/test.rp2040-ard.yaml diff --git a/tests/components/sm300d2/test.esp32.yaml b/tests/components/sm300d2/test.esp32-ard.yaml similarity index 100% rename from tests/components/sm300d2/test.esp32.yaml rename to tests/components/sm300d2/test.esp32-ard.yaml diff --git a/tests/components/sm300d2/test.esp32-c3.yaml b/tests/components/sm300d2/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/sm300d2/test.esp32-c3.yaml rename to tests/components/sm300d2/test.esp32-c3-ard.yaml diff --git a/tests/components/sm300d2/test.esp8266.yaml b/tests/components/sm300d2/test.esp8266-ard.yaml similarity index 100% rename from tests/components/sm300d2/test.esp8266.yaml rename to tests/components/sm300d2/test.esp8266-ard.yaml diff --git a/tests/components/sm300d2/test.rp2040.yaml b/tests/components/sm300d2/test.rp2040-ard.yaml similarity index 100% rename from tests/components/sm300d2/test.rp2040.yaml rename to tests/components/sm300d2/test.rp2040-ard.yaml diff --git a/tests/components/sml/test.esp32.yaml b/tests/components/sml/test.esp32-ard.yaml similarity index 100% rename from tests/components/sml/test.esp32.yaml rename to tests/components/sml/test.esp32-ard.yaml diff --git a/tests/components/sml/test.esp32-c3.yaml b/tests/components/sml/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/sml/test.esp32-c3.yaml rename to tests/components/sml/test.esp32-c3-ard.yaml diff --git a/tests/components/sml/test.esp8266.yaml b/tests/components/sml/test.esp8266-ard.yaml similarity index 100% rename from tests/components/sml/test.esp8266.yaml rename to tests/components/sml/test.esp8266-ard.yaml diff --git a/tests/components/sml/test.rp2040.yaml b/tests/components/sml/test.rp2040-ard.yaml similarity index 100% rename from tests/components/sml/test.rp2040.yaml rename to tests/components/sml/test.rp2040-ard.yaml diff --git a/tests/components/smt100/test.esp32.yaml b/tests/components/smt100/test.esp32-ard.yaml similarity index 100% rename from tests/components/smt100/test.esp32.yaml rename to tests/components/smt100/test.esp32-ard.yaml diff --git a/tests/components/smt100/test.esp32-c3.yaml b/tests/components/smt100/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/smt100/test.esp32-c3.yaml rename to tests/components/smt100/test.esp32-c3-ard.yaml diff --git a/tests/components/smt100/test.esp8266.yaml b/tests/components/smt100/test.esp8266-ard.yaml similarity index 100% rename from tests/components/smt100/test.esp8266.yaml rename to tests/components/smt100/test.esp8266-ard.yaml diff --git a/tests/components/smt100/test.rp2040.yaml b/tests/components/smt100/test.rp2040-ard.yaml similarity index 100% rename from tests/components/smt100/test.rp2040.yaml rename to tests/components/smt100/test.rp2040-ard.yaml diff --git a/tests/components/sn74hc165/test.esp32.yaml b/tests/components/sn74hc165/test.esp32-ard.yaml similarity index 100% rename from tests/components/sn74hc165/test.esp32.yaml rename to tests/components/sn74hc165/test.esp32-ard.yaml diff --git a/tests/components/sn74hc165/test.esp32-c3.yaml b/tests/components/sn74hc165/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/sn74hc165/test.esp32-c3.yaml rename to tests/components/sn74hc165/test.esp32-c3-ard.yaml diff --git a/tests/components/sn74hc165/test.esp8266.yaml b/tests/components/sn74hc165/test.esp8266-ard.yaml similarity index 100% rename from tests/components/sn74hc165/test.esp8266.yaml rename to tests/components/sn74hc165/test.esp8266-ard.yaml diff --git a/tests/components/sn74hc165/test.rp2040.yaml b/tests/components/sn74hc165/test.rp2040-ard.yaml similarity index 100% rename from tests/components/sn74hc165/test.rp2040.yaml rename to tests/components/sn74hc165/test.rp2040-ard.yaml diff --git a/tests/components/sn74hc595/test.esp32.yaml b/tests/components/sn74hc595/test.esp32-ard.yaml similarity index 100% rename from tests/components/sn74hc595/test.esp32.yaml rename to tests/components/sn74hc595/test.esp32-ard.yaml diff --git a/tests/components/sn74hc595/test.esp32-c3.yaml b/tests/components/sn74hc595/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/sn74hc595/test.esp32-c3.yaml rename to tests/components/sn74hc595/test.esp32-c3-ard.yaml diff --git a/tests/components/sn74hc595/test.esp8266.yaml b/tests/components/sn74hc595/test.esp8266-ard.yaml similarity index 100% rename from tests/components/sn74hc595/test.esp8266.yaml rename to tests/components/sn74hc595/test.esp8266-ard.yaml diff --git a/tests/components/sn74hc595/test.rp2040.yaml b/tests/components/sn74hc595/test.rp2040-ard.yaml similarity index 100% rename from tests/components/sn74hc595/test.rp2040.yaml rename to tests/components/sn74hc595/test.rp2040-ard.yaml diff --git a/tests/components/sntp/test.bk72xx.yaml b/tests/components/sntp/test.bk72xx-ard.yaml similarity index 100% rename from tests/components/sntp/test.bk72xx.yaml rename to tests/components/sntp/test.bk72xx-ard.yaml diff --git a/tests/components/sntp/test.esp32-c3.yaml b/tests/components/sntp/test.esp32-ard.yaml similarity index 100% rename from tests/components/sntp/test.esp32-c3.yaml rename to tests/components/sntp/test.esp32-ard.yaml diff --git a/tests/components/sntp/test.esp32.yaml b/tests/components/sntp/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/sntp/test.esp32.yaml rename to tests/components/sntp/test.esp32-c3-ard.yaml diff --git a/tests/components/sntp/test.esp8266.yaml b/tests/components/sntp/test.esp8266-ard.yaml similarity index 100% rename from tests/components/sntp/test.esp8266.yaml rename to tests/components/sntp/test.esp8266-ard.yaml diff --git a/tests/components/sntp/test.rp2040.yaml b/tests/components/sntp/test.rp2040-ard.yaml similarity index 100% rename from tests/components/sntp/test.rp2040.yaml rename to tests/components/sntp/test.rp2040-ard.yaml diff --git a/tests/components/sonoff_d1/test.esp32.yaml b/tests/components/sonoff_d1/test.esp32-ard.yaml similarity index 100% rename from tests/components/sonoff_d1/test.esp32.yaml rename to tests/components/sonoff_d1/test.esp32-ard.yaml diff --git a/tests/components/sonoff_d1/test.esp8266.yaml b/tests/components/sonoff_d1/test.esp8266-ard.yaml similarity index 100% rename from tests/components/sonoff_d1/test.esp8266.yaml rename to tests/components/sonoff_d1/test.esp8266-ard.yaml diff --git a/tests/components/speaker/test.esp32.yaml b/tests/components/speaker/test.esp32-ard.yaml similarity index 100% rename from tests/components/speaker/test.esp32.yaml rename to tests/components/speaker/test.esp32-ard.yaml diff --git a/tests/components/speaker/test.esp32-c3.yaml b/tests/components/speaker/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/speaker/test.esp32-c3.yaml rename to tests/components/speaker/test.esp32-c3-ard.yaml diff --git a/tests/components/speed/test.esp32.yaml b/tests/components/speed/test.esp32-ard.yaml similarity index 100% rename from tests/components/speed/test.esp32.yaml rename to tests/components/speed/test.esp32-ard.yaml diff --git a/tests/components/speed/test.esp32-c3.yaml b/tests/components/speed/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/speed/test.esp32-c3.yaml rename to tests/components/speed/test.esp32-c3-ard.yaml diff --git a/tests/components/speed/test.esp8266.yaml b/tests/components/speed/test.esp8266-ard.yaml similarity index 100% rename from tests/components/speed/test.esp8266.yaml rename to tests/components/speed/test.esp8266-ard.yaml diff --git a/tests/components/speed/test.rp2040.yaml b/tests/components/speed/test.rp2040-ard.yaml similarity index 100% rename from tests/components/speed/test.rp2040.yaml rename to tests/components/speed/test.rp2040-ard.yaml diff --git a/tests/components/spi/test.esp32.yaml b/tests/components/spi/test.esp32-ard.yaml similarity index 100% rename from tests/components/spi/test.esp32.yaml rename to tests/components/spi/test.esp32-ard.yaml diff --git a/tests/components/spi/test.esp32-c3.yaml b/tests/components/spi/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/spi/test.esp32-c3.yaml rename to tests/components/spi/test.esp32-c3-ard.yaml diff --git a/tests/components/spi/test.esp8266.yaml b/tests/components/spi/test.esp8266-ard.yaml similarity index 100% rename from tests/components/spi/test.esp8266.yaml rename to tests/components/spi/test.esp8266-ard.yaml diff --git a/tests/components/spi/test.rp2040.yaml b/tests/components/spi/test.rp2040-ard.yaml similarity index 100% rename from tests/components/spi/test.rp2040.yaml rename to tests/components/spi/test.rp2040-ard.yaml diff --git a/tests/components/spi_device/test.esp32.yaml b/tests/components/spi_device/test.esp32-ard.yaml similarity index 100% rename from tests/components/spi_device/test.esp32.yaml rename to tests/components/spi_device/test.esp32-ard.yaml diff --git a/tests/components/spi_device/test.esp32-c3.yaml b/tests/components/spi_device/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/spi_device/test.esp32-c3.yaml rename to tests/components/spi_device/test.esp32-c3-ard.yaml diff --git a/tests/components/spi_device/test.esp8266.yaml b/tests/components/spi_device/test.esp8266-ard.yaml similarity index 100% rename from tests/components/spi_device/test.esp8266.yaml rename to tests/components/spi_device/test.esp8266-ard.yaml diff --git a/tests/components/spi_device/test.rp2040.yaml b/tests/components/spi_device/test.rp2040-ard.yaml similarity index 100% rename from tests/components/spi_device/test.rp2040.yaml rename to tests/components/spi_device/test.rp2040-ard.yaml diff --git a/tests/components/spi_led_strip/test.esp32.yaml b/tests/components/spi_led_strip/test.esp32-ard.yaml similarity index 100% rename from tests/components/spi_led_strip/test.esp32.yaml rename to tests/components/spi_led_strip/test.esp32-ard.yaml diff --git a/tests/components/spi_led_strip/test.esp32-c3.yaml b/tests/components/spi_led_strip/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/spi_led_strip/test.esp32-c3.yaml rename to tests/components/spi_led_strip/test.esp32-c3-ard.yaml diff --git a/tests/components/spi_led_strip/test.esp8266.yaml b/tests/components/spi_led_strip/test.esp8266-ard.yaml similarity index 100% rename from tests/components/spi_led_strip/test.esp8266.yaml rename to tests/components/spi_led_strip/test.esp8266-ard.yaml diff --git a/tests/components/spi_led_strip/test.rp2040.yaml b/tests/components/spi_led_strip/test.rp2040-ard.yaml similarity index 100% rename from tests/components/spi_led_strip/test.rp2040.yaml rename to tests/components/spi_led_strip/test.rp2040-ard.yaml diff --git a/tests/components/sprinkler/test.esp32-c3.yaml b/tests/components/sprinkler/test.esp32-ard.yaml similarity index 100% rename from tests/components/sprinkler/test.esp32-c3.yaml rename to tests/components/sprinkler/test.esp32-ard.yaml diff --git a/tests/components/sprinkler/test.esp32.yaml b/tests/components/sprinkler/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/sprinkler/test.esp32.yaml rename to tests/components/sprinkler/test.esp32-c3-ard.yaml diff --git a/tests/components/sprinkler/test.esp8266.yaml b/tests/components/sprinkler/test.esp8266-ard.yaml similarity index 100% rename from tests/components/sprinkler/test.esp8266.yaml rename to tests/components/sprinkler/test.esp8266-ard.yaml diff --git a/tests/components/sprinkler/test.rp2040.yaml b/tests/components/sprinkler/test.rp2040-ard.yaml similarity index 100% rename from tests/components/sprinkler/test.rp2040.yaml rename to tests/components/sprinkler/test.rp2040-ard.yaml diff --git a/tests/components/sps30/test.esp32.yaml b/tests/components/sps30/test.esp32-ard.yaml similarity index 100% rename from tests/components/sps30/test.esp32.yaml rename to tests/components/sps30/test.esp32-ard.yaml diff --git a/tests/components/sps30/test.esp32-c3.yaml b/tests/components/sps30/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/sps30/test.esp32-c3.yaml rename to tests/components/sps30/test.esp32-c3-ard.yaml diff --git a/tests/components/sps30/test.esp8266.yaml b/tests/components/sps30/test.esp8266-ard.yaml similarity index 100% rename from tests/components/sps30/test.esp8266.yaml rename to tests/components/sps30/test.esp8266-ard.yaml diff --git a/tests/components/sps30/test.rp2040.yaml b/tests/components/sps30/test.rp2040-ard.yaml similarity index 100% rename from tests/components/sps30/test.rp2040.yaml rename to tests/components/sps30/test.rp2040-ard.yaml diff --git a/tests/components/ssd1306_i2c/test.esp32.yaml b/tests/components/ssd1306_i2c/test.esp32-ard.yaml similarity index 100% rename from tests/components/ssd1306_i2c/test.esp32.yaml rename to tests/components/ssd1306_i2c/test.esp32-ard.yaml diff --git a/tests/components/ssd1306_i2c/test.esp32-c3.yaml b/tests/components/ssd1306_i2c/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ssd1306_i2c/test.esp32-c3.yaml rename to tests/components/ssd1306_i2c/test.esp32-c3-ard.yaml diff --git a/tests/components/ssd1306_i2c/test.esp8266.yaml b/tests/components/ssd1306_i2c/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ssd1306_i2c/test.esp8266.yaml rename to tests/components/ssd1306_i2c/test.esp8266-ard.yaml diff --git a/tests/components/ssd1306_i2c/test.rp2040.yaml b/tests/components/ssd1306_i2c/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ssd1306_i2c/test.rp2040.yaml rename to tests/components/ssd1306_i2c/test.rp2040-ard.yaml diff --git a/tests/components/ssd1306_spi/test.esp32.yaml b/tests/components/ssd1306_spi/test.esp32-ard.yaml similarity index 100% rename from tests/components/ssd1306_spi/test.esp32.yaml rename to tests/components/ssd1306_spi/test.esp32-ard.yaml diff --git a/tests/components/ssd1306_spi/test.esp32-c3.yaml b/tests/components/ssd1306_spi/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ssd1306_spi/test.esp32-c3.yaml rename to tests/components/ssd1306_spi/test.esp32-c3-ard.yaml diff --git a/tests/components/ssd1306_spi/test.esp8266.yaml b/tests/components/ssd1306_spi/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ssd1306_spi/test.esp8266.yaml rename to tests/components/ssd1306_spi/test.esp8266-ard.yaml diff --git a/tests/components/ssd1306_spi/test.rp2040.yaml b/tests/components/ssd1306_spi/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ssd1306_spi/test.rp2040.yaml rename to tests/components/ssd1306_spi/test.rp2040-ard.yaml diff --git a/tests/components/ssd1322_spi/test.esp32.yaml b/tests/components/ssd1322_spi/test.esp32-ard.yaml similarity index 100% rename from tests/components/ssd1322_spi/test.esp32.yaml rename to tests/components/ssd1322_spi/test.esp32-ard.yaml diff --git a/tests/components/ssd1322_spi/test.esp32-c3.yaml b/tests/components/ssd1322_spi/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ssd1322_spi/test.esp32-c3.yaml rename to tests/components/ssd1322_spi/test.esp32-c3-ard.yaml diff --git a/tests/components/ssd1322_spi/test.esp8266.yaml b/tests/components/ssd1322_spi/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ssd1322_spi/test.esp8266.yaml rename to tests/components/ssd1322_spi/test.esp8266-ard.yaml diff --git a/tests/components/ssd1322_spi/test.rp2040.yaml b/tests/components/ssd1322_spi/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ssd1322_spi/test.rp2040.yaml rename to tests/components/ssd1322_spi/test.rp2040-ard.yaml diff --git a/tests/components/ssd1325_spi/test.esp32.yaml b/tests/components/ssd1325_spi/test.esp32-ard.yaml similarity index 100% rename from tests/components/ssd1325_spi/test.esp32.yaml rename to tests/components/ssd1325_spi/test.esp32-ard.yaml diff --git a/tests/components/ssd1325_spi/test.esp32-c3.yaml b/tests/components/ssd1325_spi/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ssd1325_spi/test.esp32-c3.yaml rename to tests/components/ssd1325_spi/test.esp32-c3-ard.yaml diff --git a/tests/components/ssd1325_spi/test.esp8266.yaml b/tests/components/ssd1325_spi/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ssd1325_spi/test.esp8266.yaml rename to tests/components/ssd1325_spi/test.esp8266-ard.yaml diff --git a/tests/components/ssd1325_spi/test.rp2040.yaml b/tests/components/ssd1325_spi/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ssd1325_spi/test.rp2040.yaml rename to tests/components/ssd1325_spi/test.rp2040-ard.yaml diff --git a/tests/components/ssd1327_i2c/test.esp32.yaml b/tests/components/ssd1327_i2c/test.esp32-ard.yaml similarity index 100% rename from tests/components/ssd1327_i2c/test.esp32.yaml rename to tests/components/ssd1327_i2c/test.esp32-ard.yaml diff --git a/tests/components/ssd1327_i2c/test.esp32-c3.yaml b/tests/components/ssd1327_i2c/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ssd1327_i2c/test.esp32-c3.yaml rename to tests/components/ssd1327_i2c/test.esp32-c3-ard.yaml diff --git a/tests/components/ssd1327_i2c/test.esp8266.yaml b/tests/components/ssd1327_i2c/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ssd1327_i2c/test.esp8266.yaml rename to tests/components/ssd1327_i2c/test.esp8266-ard.yaml diff --git a/tests/components/ssd1327_i2c/test.rp2040.yaml b/tests/components/ssd1327_i2c/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ssd1327_i2c/test.rp2040.yaml rename to tests/components/ssd1327_i2c/test.rp2040-ard.yaml diff --git a/tests/components/ssd1327_spi/test.esp32.yaml b/tests/components/ssd1327_spi/test.esp32-ard.yaml similarity index 100% rename from tests/components/ssd1327_spi/test.esp32.yaml rename to tests/components/ssd1327_spi/test.esp32-ard.yaml diff --git a/tests/components/ssd1327_spi/test.esp32-c3.yaml b/tests/components/ssd1327_spi/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ssd1327_spi/test.esp32-c3.yaml rename to tests/components/ssd1327_spi/test.esp32-c3-ard.yaml diff --git a/tests/components/ssd1327_spi/test.esp8266.yaml b/tests/components/ssd1327_spi/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ssd1327_spi/test.esp8266.yaml rename to tests/components/ssd1327_spi/test.esp8266-ard.yaml diff --git a/tests/components/ssd1327_spi/test.rp2040.yaml b/tests/components/ssd1327_spi/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ssd1327_spi/test.rp2040.yaml rename to tests/components/ssd1327_spi/test.rp2040-ard.yaml diff --git a/tests/components/ssd1331_spi/test.esp32.yaml b/tests/components/ssd1331_spi/test.esp32-ard.yaml similarity index 100% rename from tests/components/ssd1331_spi/test.esp32.yaml rename to tests/components/ssd1331_spi/test.esp32-ard.yaml diff --git a/tests/components/ssd1331_spi/test.esp32-c3.yaml b/tests/components/ssd1331_spi/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ssd1331_spi/test.esp32-c3.yaml rename to tests/components/ssd1331_spi/test.esp32-c3-ard.yaml diff --git a/tests/components/ssd1331_spi/test.esp8266.yaml b/tests/components/ssd1331_spi/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ssd1331_spi/test.esp8266.yaml rename to tests/components/ssd1331_spi/test.esp8266-ard.yaml diff --git a/tests/components/ssd1331_spi/test.rp2040.yaml b/tests/components/ssd1331_spi/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ssd1331_spi/test.rp2040.yaml rename to tests/components/ssd1331_spi/test.rp2040-ard.yaml diff --git a/tests/components/ssd1351_spi/test.esp32.yaml b/tests/components/ssd1351_spi/test.esp32-ard.yaml similarity index 100% rename from tests/components/ssd1351_spi/test.esp32.yaml rename to tests/components/ssd1351_spi/test.esp32-ard.yaml diff --git a/tests/components/ssd1351_spi/test.esp32-c3.yaml b/tests/components/ssd1351_spi/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ssd1351_spi/test.esp32-c3.yaml rename to tests/components/ssd1351_spi/test.esp32-c3-ard.yaml diff --git a/tests/components/ssd1351_spi/test.esp8266.yaml b/tests/components/ssd1351_spi/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ssd1351_spi/test.esp8266.yaml rename to tests/components/ssd1351_spi/test.esp8266-ard.yaml diff --git a/tests/components/ssd1351_spi/test.rp2040.yaml b/tests/components/ssd1351_spi/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ssd1351_spi/test.rp2040.yaml rename to tests/components/ssd1351_spi/test.rp2040-ard.yaml diff --git a/tests/components/st7567_i2c/test.esp32.yaml b/tests/components/st7567_i2c/test.esp32-ard.yaml similarity index 100% rename from tests/components/st7567_i2c/test.esp32.yaml rename to tests/components/st7567_i2c/test.esp32-ard.yaml diff --git a/tests/components/st7567_i2c/test.esp32-c3.yaml b/tests/components/st7567_i2c/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/st7567_i2c/test.esp32-c3.yaml rename to tests/components/st7567_i2c/test.esp32-c3-ard.yaml diff --git a/tests/components/st7567_i2c/test.esp8266.yaml b/tests/components/st7567_i2c/test.esp8266-ard.yaml similarity index 100% rename from tests/components/st7567_i2c/test.esp8266.yaml rename to tests/components/st7567_i2c/test.esp8266-ard.yaml diff --git a/tests/components/st7567_i2c/test.rp2040.yaml b/tests/components/st7567_i2c/test.rp2040-ard.yaml similarity index 100% rename from tests/components/st7567_i2c/test.rp2040.yaml rename to tests/components/st7567_i2c/test.rp2040-ard.yaml diff --git a/tests/components/st7567_spi/test.esp32.yaml b/tests/components/st7567_spi/test.esp32-ard.yaml similarity index 100% rename from tests/components/st7567_spi/test.esp32.yaml rename to tests/components/st7567_spi/test.esp32-ard.yaml diff --git a/tests/components/st7567_spi/test.esp32-c3.yaml b/tests/components/st7567_spi/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/st7567_spi/test.esp32-c3.yaml rename to tests/components/st7567_spi/test.esp32-c3-ard.yaml diff --git a/tests/components/st7567_spi/test.esp8266.yaml b/tests/components/st7567_spi/test.esp8266-ard.yaml similarity index 100% rename from tests/components/st7567_spi/test.esp8266.yaml rename to tests/components/st7567_spi/test.esp8266-ard.yaml diff --git a/tests/components/st7567_spi/test.rp2040.yaml b/tests/components/st7567_spi/test.rp2040-ard.yaml similarity index 100% rename from tests/components/st7567_spi/test.rp2040.yaml rename to tests/components/st7567_spi/test.rp2040-ard.yaml diff --git a/tests/components/st7735/test.esp32.yaml b/tests/components/st7735/test.esp32-ard.yaml similarity index 100% rename from tests/components/st7735/test.esp32.yaml rename to tests/components/st7735/test.esp32-ard.yaml diff --git a/tests/components/st7735/test.esp32-c3.yaml b/tests/components/st7735/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/st7735/test.esp32-c3.yaml rename to tests/components/st7735/test.esp32-c3-ard.yaml diff --git a/tests/components/st7735/test.esp8266.yaml b/tests/components/st7735/test.esp8266-ard.yaml similarity index 100% rename from tests/components/st7735/test.esp8266.yaml rename to tests/components/st7735/test.esp8266-ard.yaml diff --git a/tests/components/st7735/test.rp2040.yaml b/tests/components/st7735/test.rp2040-ard.yaml similarity index 100% rename from tests/components/st7735/test.rp2040.yaml rename to tests/components/st7735/test.rp2040-ard.yaml diff --git a/tests/components/st7789v/test.esp32.yaml b/tests/components/st7789v/test.esp32-ard.yaml similarity index 100% rename from tests/components/st7789v/test.esp32.yaml rename to tests/components/st7789v/test.esp32-ard.yaml diff --git a/tests/components/st7789v/test.esp32-c3.yaml b/tests/components/st7789v/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/st7789v/test.esp32-c3.yaml rename to tests/components/st7789v/test.esp32-c3-ard.yaml diff --git a/tests/components/st7789v/test.esp8266.yaml b/tests/components/st7789v/test.esp8266-ard.yaml similarity index 100% rename from tests/components/st7789v/test.esp8266.yaml rename to tests/components/st7789v/test.esp8266-ard.yaml diff --git a/tests/components/st7789v/test.rp2040.yaml b/tests/components/st7789v/test.rp2040-ard.yaml similarity index 100% rename from tests/components/st7789v/test.rp2040.yaml rename to tests/components/st7789v/test.rp2040-ard.yaml diff --git a/tests/components/st7920/test.esp32.yaml b/tests/components/st7920/test.esp32-ard.yaml similarity index 100% rename from tests/components/st7920/test.esp32.yaml rename to tests/components/st7920/test.esp32-ard.yaml diff --git a/tests/components/st7920/test.esp32-c3.yaml b/tests/components/st7920/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/st7920/test.esp32-c3.yaml rename to tests/components/st7920/test.esp32-c3-ard.yaml diff --git a/tests/components/st7920/test.esp8266.yaml b/tests/components/st7920/test.esp8266-ard.yaml similarity index 100% rename from tests/components/st7920/test.esp8266.yaml rename to tests/components/st7920/test.esp8266-ard.yaml diff --git a/tests/components/st7920/test.rp2040.yaml b/tests/components/st7920/test.rp2040-ard.yaml similarity index 100% rename from tests/components/st7920/test.rp2040.yaml rename to tests/components/st7920/test.rp2040-ard.yaml diff --git a/tests/components/status/test.esp32-c3.yaml b/tests/components/status/test.esp32-ard.yaml similarity index 100% rename from tests/components/status/test.esp32-c3.yaml rename to tests/components/status/test.esp32-ard.yaml diff --git a/tests/components/status/test.esp32.yaml b/tests/components/status/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/status/test.esp32.yaml rename to tests/components/status/test.esp32-c3-ard.yaml diff --git a/tests/components/status/test.esp8266.yaml b/tests/components/status/test.esp8266-ard.yaml similarity index 100% rename from tests/components/status/test.esp8266.yaml rename to tests/components/status/test.esp8266-ard.yaml diff --git a/tests/components/status/test.rp2040.yaml b/tests/components/status/test.rp2040-ard.yaml similarity index 100% rename from tests/components/status/test.rp2040.yaml rename to tests/components/status/test.rp2040-ard.yaml diff --git a/tests/components/status_led/test.esp32-c3.yaml b/tests/components/status_led/test.esp32-ard.yaml similarity index 100% rename from tests/components/status_led/test.esp32-c3.yaml rename to tests/components/status_led/test.esp32-ard.yaml diff --git a/tests/components/status_led/test.esp32.yaml b/tests/components/status_led/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/status_led/test.esp32.yaml rename to tests/components/status_led/test.esp32-c3-ard.yaml diff --git a/tests/components/status_led/test.esp8266.yaml b/tests/components/status_led/test.esp8266-ard.yaml similarity index 100% rename from tests/components/status_led/test.esp8266.yaml rename to tests/components/status_led/test.esp8266-ard.yaml diff --git a/tests/components/status_led/test.rp2040.yaml b/tests/components/status_led/test.rp2040-ard.yaml similarity index 100% rename from tests/components/status_led/test.rp2040.yaml rename to tests/components/status_led/test.rp2040-ard.yaml diff --git a/tests/components/stepper/test.esp32-c3.yaml b/tests/components/stepper/test.esp32-ard.yaml similarity index 100% rename from tests/components/stepper/test.esp32-c3.yaml rename to tests/components/stepper/test.esp32-ard.yaml diff --git a/tests/components/stepper/test.esp32.yaml b/tests/components/stepper/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/stepper/test.esp32.yaml rename to tests/components/stepper/test.esp32-c3-ard.yaml diff --git a/tests/components/stepper/test.esp8266.yaml b/tests/components/stepper/test.esp8266-ard.yaml similarity index 100% rename from tests/components/stepper/test.esp8266.yaml rename to tests/components/stepper/test.esp8266-ard.yaml diff --git a/tests/components/stepper/test.rp2040.yaml b/tests/components/stepper/test.rp2040-ard.yaml similarity index 100% rename from tests/components/stepper/test.rp2040.yaml rename to tests/components/stepper/test.rp2040-ard.yaml diff --git a/tests/components/sts3x/test.esp32.yaml b/tests/components/sts3x/test.esp32-ard.yaml similarity index 100% rename from tests/components/sts3x/test.esp32.yaml rename to tests/components/sts3x/test.esp32-ard.yaml diff --git a/tests/components/sts3x/test.esp32-c3.yaml b/tests/components/sts3x/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/sts3x/test.esp32-c3.yaml rename to tests/components/sts3x/test.esp32-c3-ard.yaml diff --git a/tests/components/sts3x/test.esp8266.yaml b/tests/components/sts3x/test.esp8266-ard.yaml similarity index 100% rename from tests/components/sts3x/test.esp8266.yaml rename to tests/components/sts3x/test.esp8266-ard.yaml diff --git a/tests/components/sts3x/test.rp2040.yaml b/tests/components/sts3x/test.rp2040-ard.yaml similarity index 100% rename from tests/components/sts3x/test.rp2040.yaml rename to tests/components/sts3x/test.rp2040-ard.yaml diff --git a/tests/components/sun/test.esp32-c3.yaml b/tests/components/sun/test.esp32-ard.yaml similarity index 100% rename from tests/components/sun/test.esp32-c3.yaml rename to tests/components/sun/test.esp32-ard.yaml diff --git a/tests/components/sun/test.esp32.yaml b/tests/components/sun/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/sun/test.esp32.yaml rename to tests/components/sun/test.esp32-c3-ard.yaml diff --git a/tests/components/sun/test.esp8266.yaml b/tests/components/sun/test.esp8266-ard.yaml similarity index 100% rename from tests/components/sun/test.esp8266.yaml rename to tests/components/sun/test.esp8266-ard.yaml diff --git a/tests/components/sun/test.rp2040.yaml b/tests/components/sun/test.rp2040-ard.yaml similarity index 100% rename from tests/components/sun/test.rp2040.yaml rename to tests/components/sun/test.rp2040-ard.yaml diff --git a/tests/components/sun_gtil2/test.esp32.yaml b/tests/components/sun_gtil2/test.esp32-ard.yaml similarity index 100% rename from tests/components/sun_gtil2/test.esp32.yaml rename to tests/components/sun_gtil2/test.esp32-ard.yaml diff --git a/tests/components/sun_gtil2/test.esp32-c3.yaml b/tests/components/sun_gtil2/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/sun_gtil2/test.esp32-c3.yaml rename to tests/components/sun_gtil2/test.esp32-c3-ard.yaml diff --git a/tests/components/sun_gtil2/test.esp8266.yaml b/tests/components/sun_gtil2/test.esp8266-ard.yaml similarity index 100% rename from tests/components/sun_gtil2/test.esp8266.yaml rename to tests/components/sun_gtil2/test.esp8266-ard.yaml diff --git a/tests/components/sun_gtil2/test.rp2040.yaml b/tests/components/sun_gtil2/test.rp2040-ard.yaml similarity index 100% rename from tests/components/sun_gtil2/test.rp2040.yaml rename to tests/components/sun_gtil2/test.rp2040-ard.yaml diff --git a/tests/components/sx1509/test.esp32.yaml b/tests/components/sx1509/test.esp32-ard.yaml similarity index 100% rename from tests/components/sx1509/test.esp32.yaml rename to tests/components/sx1509/test.esp32-ard.yaml diff --git a/tests/components/sx1509/test.esp32-c3.yaml b/tests/components/sx1509/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/sx1509/test.esp32-c3.yaml rename to tests/components/sx1509/test.esp32-c3-ard.yaml diff --git a/tests/components/sx1509/test.esp8266.yaml b/tests/components/sx1509/test.esp8266-ard.yaml similarity index 100% rename from tests/components/sx1509/test.esp8266.yaml rename to tests/components/sx1509/test.esp8266-ard.yaml diff --git a/tests/components/sx1509/test.rp2040.yaml b/tests/components/sx1509/test.rp2040-ard.yaml similarity index 100% rename from tests/components/sx1509/test.rp2040.yaml rename to tests/components/sx1509/test.rp2040-ard.yaml diff --git a/tests/components/t6615/test.esp32.yaml b/tests/components/t6615/test.esp32-ard.yaml similarity index 100% rename from tests/components/t6615/test.esp32.yaml rename to tests/components/t6615/test.esp32-ard.yaml diff --git a/tests/components/t6615/test.esp32-c3.yaml b/tests/components/t6615/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/t6615/test.esp32-c3.yaml rename to tests/components/t6615/test.esp32-c3-ard.yaml diff --git a/tests/components/t6615/test.esp8266.yaml b/tests/components/t6615/test.esp8266-ard.yaml similarity index 100% rename from tests/components/t6615/test.esp8266.yaml rename to tests/components/t6615/test.esp8266-ard.yaml diff --git a/tests/components/t6615/test.rp2040.yaml b/tests/components/t6615/test.rp2040-ard.yaml similarity index 100% rename from tests/components/t6615/test.rp2040.yaml rename to tests/components/t6615/test.rp2040-ard.yaml diff --git a/tests/components/tca9548a/test.esp32.yaml b/tests/components/tca9548a/test.esp32-ard.yaml similarity index 100% rename from tests/components/tca9548a/test.esp32.yaml rename to tests/components/tca9548a/test.esp32-ard.yaml diff --git a/tests/components/tca9548a/test.esp32-c3.yaml b/tests/components/tca9548a/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/tca9548a/test.esp32-c3.yaml rename to tests/components/tca9548a/test.esp32-c3-ard.yaml diff --git a/tests/components/tca9548a/test.esp8266.yaml b/tests/components/tca9548a/test.esp8266-ard.yaml similarity index 100% rename from tests/components/tca9548a/test.esp8266.yaml rename to tests/components/tca9548a/test.esp8266-ard.yaml diff --git a/tests/components/tca9548a/test.rp2040.yaml b/tests/components/tca9548a/test.rp2040-ard.yaml similarity index 100% rename from tests/components/tca9548a/test.rp2040.yaml rename to tests/components/tca9548a/test.rp2040-ard.yaml diff --git a/tests/components/tcl112/test.esp32-c3.yaml b/tests/components/tcl112/test.esp32-ard.yaml similarity index 100% rename from tests/components/tcl112/test.esp32-c3.yaml rename to tests/components/tcl112/test.esp32-ard.yaml diff --git a/tests/components/tcl112/test.esp32.yaml b/tests/components/tcl112/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/tcl112/test.esp32.yaml rename to tests/components/tcl112/test.esp32-c3-ard.yaml diff --git a/tests/components/tcl112/test.esp8266.yaml b/tests/components/tcl112/test.esp8266-ard.yaml similarity index 100% rename from tests/components/tcl112/test.esp8266.yaml rename to tests/components/tcl112/test.esp8266-ard.yaml diff --git a/tests/components/tcs34725/test.esp32.yaml b/tests/components/tcs34725/test.esp32-ard.yaml similarity index 100% rename from tests/components/tcs34725/test.esp32.yaml rename to tests/components/tcs34725/test.esp32-ard.yaml diff --git a/tests/components/tcs34725/test.esp32-c3.yaml b/tests/components/tcs34725/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/tcs34725/test.esp32-c3.yaml rename to tests/components/tcs34725/test.esp32-c3-ard.yaml diff --git a/tests/components/tcs34725/test.esp8266.yaml b/tests/components/tcs34725/test.esp8266-ard.yaml similarity index 100% rename from tests/components/tcs34725/test.esp8266.yaml rename to tests/components/tcs34725/test.esp8266-ard.yaml diff --git a/tests/components/tcs34725/test.rp2040.yaml b/tests/components/tcs34725/test.rp2040-ard.yaml similarity index 100% rename from tests/components/tcs34725/test.rp2040.yaml rename to tests/components/tcs34725/test.rp2040-ard.yaml diff --git a/tests/components/tee501/test.esp32.yaml b/tests/components/tee501/test.esp32-ard.yaml similarity index 100% rename from tests/components/tee501/test.esp32.yaml rename to tests/components/tee501/test.esp32-ard.yaml diff --git a/tests/components/tee501/test.esp32-c3.yaml b/tests/components/tee501/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/tee501/test.esp32-c3.yaml rename to tests/components/tee501/test.esp32-c3-ard.yaml diff --git a/tests/components/tee501/test.esp8266.yaml b/tests/components/tee501/test.esp8266-ard.yaml similarity index 100% rename from tests/components/tee501/test.esp8266.yaml rename to tests/components/tee501/test.esp8266-ard.yaml diff --git a/tests/components/tee501/test.rp2040.yaml b/tests/components/tee501/test.rp2040-ard.yaml similarity index 100% rename from tests/components/tee501/test.rp2040.yaml rename to tests/components/tee501/test.rp2040-ard.yaml diff --git a/tests/components/teleinfo/test.esp32.yaml b/tests/components/teleinfo/test.esp32-ard.yaml similarity index 100% rename from tests/components/teleinfo/test.esp32.yaml rename to tests/components/teleinfo/test.esp32-ard.yaml diff --git a/tests/components/teleinfo/test.esp32-c3.yaml b/tests/components/teleinfo/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/teleinfo/test.esp32-c3.yaml rename to tests/components/teleinfo/test.esp32-c3-ard.yaml diff --git a/tests/components/teleinfo/test.esp8266.yaml b/tests/components/teleinfo/test.esp8266-ard.yaml similarity index 100% rename from tests/components/teleinfo/test.esp8266.yaml rename to tests/components/teleinfo/test.esp8266-ard.yaml diff --git a/tests/components/teleinfo/test.rp2040.yaml b/tests/components/teleinfo/test.rp2040-ard.yaml similarity index 100% rename from tests/components/teleinfo/test.rp2040.yaml rename to tests/components/teleinfo/test.rp2040-ard.yaml diff --git a/tests/components/template/test.bk72xx.yaml b/tests/components/template/test.bk72xx-ard.yaml similarity index 100% rename from tests/components/template/test.bk72xx.yaml rename to tests/components/template/test.bk72xx-ard.yaml diff --git a/tests/components/template/test.esp32-c3.yaml b/tests/components/template/test.esp32-ard.yaml similarity index 100% rename from tests/components/template/test.esp32-c3.yaml rename to tests/components/template/test.esp32-ard.yaml diff --git a/tests/components/template/test.esp32.yaml b/tests/components/template/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/template/test.esp32.yaml rename to tests/components/template/test.esp32-c3-ard.yaml diff --git a/tests/components/template/test.esp8266.yaml b/tests/components/template/test.esp8266-ard.yaml similarity index 100% rename from tests/components/template/test.esp8266.yaml rename to tests/components/template/test.esp8266-ard.yaml diff --git a/tests/components/template/test.rp2040.yaml b/tests/components/template/test.rp2040-ard.yaml similarity index 100% rename from tests/components/template/test.rp2040.yaml rename to tests/components/template/test.rp2040-ard.yaml diff --git a/tests/components/thermostat/test.esp32-c3.yaml b/tests/components/thermostat/test.esp32-ard.yaml similarity index 100% rename from tests/components/thermostat/test.esp32-c3.yaml rename to tests/components/thermostat/test.esp32-ard.yaml diff --git a/tests/components/thermostat/test.esp32.yaml b/tests/components/thermostat/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/thermostat/test.esp32.yaml rename to tests/components/thermostat/test.esp32-c3-ard.yaml diff --git a/tests/components/thermostat/test.esp8266.yaml b/tests/components/thermostat/test.esp8266-ard.yaml similarity index 100% rename from tests/components/thermostat/test.esp8266.yaml rename to tests/components/thermostat/test.esp8266-ard.yaml diff --git a/tests/components/thermostat/test.rp2040.yaml b/tests/components/thermostat/test.rp2040-ard.yaml similarity index 100% rename from tests/components/thermostat/test.rp2040.yaml rename to tests/components/thermostat/test.rp2040-ard.yaml diff --git a/tests/components/time/test.esp32-c3.yaml b/tests/components/time/test.esp32-ard.yaml similarity index 100% rename from tests/components/time/test.esp32-c3.yaml rename to tests/components/time/test.esp32-ard.yaml diff --git a/tests/components/time/test.esp32.yaml b/tests/components/time/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/time/test.esp32.yaml rename to tests/components/time/test.esp32-c3-ard.yaml diff --git a/tests/components/time/test.esp8266.yaml b/tests/components/time/test.esp8266-ard.yaml similarity index 100% rename from tests/components/time/test.esp8266.yaml rename to tests/components/time/test.esp8266-ard.yaml diff --git a/tests/components/time/test.rp2040.yaml b/tests/components/time/test.rp2040-ard.yaml similarity index 100% rename from tests/components/time/test.rp2040.yaml rename to tests/components/time/test.rp2040-ard.yaml diff --git a/tests/components/time_based/test.esp32-c3.yaml b/tests/components/time_based/test.esp32-ard.yaml similarity index 100% rename from tests/components/time_based/test.esp32-c3.yaml rename to tests/components/time_based/test.esp32-ard.yaml diff --git a/tests/components/time_based/test.esp32.yaml b/tests/components/time_based/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/time_based/test.esp32.yaml rename to tests/components/time_based/test.esp32-c3-ard.yaml diff --git a/tests/components/time_based/test.esp8266.yaml b/tests/components/time_based/test.esp8266-ard.yaml similarity index 100% rename from tests/components/time_based/test.esp8266.yaml rename to tests/components/time_based/test.esp8266-ard.yaml diff --git a/tests/components/time_based/test.rp2040.yaml b/tests/components/time_based/test.rp2040-ard.yaml similarity index 100% rename from tests/components/time_based/test.rp2040.yaml rename to tests/components/time_based/test.rp2040-ard.yaml diff --git a/tests/components/tlc59208f/test.esp32.yaml b/tests/components/tlc59208f/test.esp32-ard.yaml similarity index 100% rename from tests/components/tlc59208f/test.esp32.yaml rename to tests/components/tlc59208f/test.esp32-ard.yaml diff --git a/tests/components/tlc59208f/test.esp32-c3.yaml b/tests/components/tlc59208f/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/tlc59208f/test.esp32-c3.yaml rename to tests/components/tlc59208f/test.esp32-c3-ard.yaml diff --git a/tests/components/tlc59208f/test.esp8266.yaml b/tests/components/tlc59208f/test.esp8266-ard.yaml similarity index 100% rename from tests/components/tlc59208f/test.esp8266.yaml rename to tests/components/tlc59208f/test.esp8266-ard.yaml diff --git a/tests/components/tlc59208f/test.rp2040.yaml b/tests/components/tlc59208f/test.rp2040-ard.yaml similarity index 100% rename from tests/components/tlc59208f/test.rp2040.yaml rename to tests/components/tlc59208f/test.rp2040-ard.yaml diff --git a/tests/components/tlc5947/test.esp32.yaml b/tests/components/tlc5947/test.esp32-ard.yaml similarity index 100% rename from tests/components/tlc5947/test.esp32.yaml rename to tests/components/tlc5947/test.esp32-ard.yaml diff --git a/tests/components/tlc5947/test.esp32-c3.yaml b/tests/components/tlc5947/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/tlc5947/test.esp32-c3.yaml rename to tests/components/tlc5947/test.esp32-c3-ard.yaml diff --git a/tests/components/tlc5947/test.esp8266.yaml b/tests/components/tlc5947/test.esp8266-ard.yaml similarity index 100% rename from tests/components/tlc5947/test.esp8266.yaml rename to tests/components/tlc5947/test.esp8266-ard.yaml diff --git a/tests/components/tlc5947/test.rp2040.yaml b/tests/components/tlc5947/test.rp2040-ard.yaml similarity index 100% rename from tests/components/tlc5947/test.rp2040.yaml rename to tests/components/tlc5947/test.rp2040-ard.yaml diff --git a/tests/components/tlc5971/test.esp32.yaml b/tests/components/tlc5971/test.esp32-ard.yaml similarity index 100% rename from tests/components/tlc5971/test.esp32.yaml rename to tests/components/tlc5971/test.esp32-ard.yaml diff --git a/tests/components/tlc5971/test.esp32-c3.yaml b/tests/components/tlc5971/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/tlc5971/test.esp32-c3.yaml rename to tests/components/tlc5971/test.esp32-c3-ard.yaml diff --git a/tests/components/tlc5971/test.esp32-s2.yaml b/tests/components/tlc5971/test.esp32-s2-ard.yaml similarity index 100% rename from tests/components/tlc5971/test.esp32-s2.yaml rename to tests/components/tlc5971/test.esp32-s2-ard.yaml diff --git a/tests/components/tlc5971/test.esp8266.yaml b/tests/components/tlc5971/test.esp8266-ard.yaml similarity index 100% rename from tests/components/tlc5971/test.esp8266.yaml rename to tests/components/tlc5971/test.esp8266-ard.yaml diff --git a/tests/components/tlc5971/test.rp2040.yaml b/tests/components/tlc5971/test.rp2040-ard.yaml similarity index 100% rename from tests/components/tlc5971/test.rp2040.yaml rename to tests/components/tlc5971/test.rp2040-ard.yaml diff --git a/tests/components/tm1621/test.esp32.yaml b/tests/components/tm1621/test.esp32-ard.yaml similarity index 100% rename from tests/components/tm1621/test.esp32.yaml rename to tests/components/tm1621/test.esp32-ard.yaml diff --git a/tests/components/tm1621/test.esp32-c3.yaml b/tests/components/tm1621/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/tm1621/test.esp32-c3.yaml rename to tests/components/tm1621/test.esp32-c3-ard.yaml diff --git a/tests/components/tm1621/test.esp8266.yaml b/tests/components/tm1621/test.esp8266-ard.yaml similarity index 100% rename from tests/components/tm1621/test.esp8266.yaml rename to tests/components/tm1621/test.esp8266-ard.yaml diff --git a/tests/components/tm1621/test.rp2040.yaml b/tests/components/tm1621/test.rp2040-ard.yaml similarity index 100% rename from tests/components/tm1621/test.rp2040.yaml rename to tests/components/tm1621/test.rp2040-ard.yaml diff --git a/tests/components/tm1637/test.esp32.yaml b/tests/components/tm1637/test.esp32-ard.yaml similarity index 100% rename from tests/components/tm1637/test.esp32.yaml rename to tests/components/tm1637/test.esp32-ard.yaml diff --git a/tests/components/tm1637/test.esp32-c3.yaml b/tests/components/tm1637/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/tm1637/test.esp32-c3.yaml rename to tests/components/tm1637/test.esp32-c3-ard.yaml diff --git a/tests/components/tm1637/test.esp8266.yaml b/tests/components/tm1637/test.esp8266-ard.yaml similarity index 100% rename from tests/components/tm1637/test.esp8266.yaml rename to tests/components/tm1637/test.esp8266-ard.yaml diff --git a/tests/components/tm1637/test.rp2040.yaml b/tests/components/tm1637/test.rp2040-ard.yaml similarity index 100% rename from tests/components/tm1637/test.rp2040.yaml rename to tests/components/tm1637/test.rp2040-ard.yaml diff --git a/tests/components/tm1638/test.esp32-c3.yaml b/tests/components/tm1638/test.esp32-ard.yaml similarity index 100% rename from tests/components/tm1638/test.esp32-c3.yaml rename to tests/components/tm1638/test.esp32-ard.yaml diff --git a/tests/components/tm1638/test.esp32.yaml b/tests/components/tm1638/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/tm1638/test.esp32.yaml rename to tests/components/tm1638/test.esp32-c3-ard.yaml diff --git a/tests/components/tm1638/test.esp8266.yaml b/tests/components/tm1638/test.esp8266-ard.yaml similarity index 100% rename from tests/components/tm1638/test.esp8266.yaml rename to tests/components/tm1638/test.esp8266-ard.yaml diff --git a/tests/components/tm1638/test.rp2040.yaml b/tests/components/tm1638/test.rp2040-ard.yaml similarity index 100% rename from tests/components/tm1638/test.rp2040.yaml rename to tests/components/tm1638/test.rp2040-ard.yaml diff --git a/tests/components/tm1651/test.esp32-c3.yaml b/tests/components/tm1651/test.esp32-ard.yaml similarity index 100% rename from tests/components/tm1651/test.esp32-c3.yaml rename to tests/components/tm1651/test.esp32-ard.yaml diff --git a/tests/components/tm1651/test.esp32.yaml b/tests/components/tm1651/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/tm1651/test.esp32.yaml rename to tests/components/tm1651/test.esp32-c3-ard.yaml diff --git a/tests/components/tm1651/test.esp8266.yaml b/tests/components/tm1651/test.esp8266-ard.yaml similarity index 100% rename from tests/components/tm1651/test.esp8266.yaml rename to tests/components/tm1651/test.esp8266-ard.yaml diff --git a/tests/components/tm1651/test.rp2040.yaml b/tests/components/tm1651/test.rp2040-ard.yaml similarity index 100% rename from tests/components/tm1651/test.rp2040.yaml rename to tests/components/tm1651/test.rp2040-ard.yaml diff --git a/tests/components/tmp102/test.esp32.yaml b/tests/components/tmp102/test.esp32-ard.yaml similarity index 100% rename from tests/components/tmp102/test.esp32.yaml rename to tests/components/tmp102/test.esp32-ard.yaml diff --git a/tests/components/tmp102/test.esp32-c3.yaml b/tests/components/tmp102/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/tmp102/test.esp32-c3.yaml rename to tests/components/tmp102/test.esp32-c3-ard.yaml diff --git a/tests/components/tmp102/test.esp8266.yaml b/tests/components/tmp102/test.esp8266-ard.yaml similarity index 100% rename from tests/components/tmp102/test.esp8266.yaml rename to tests/components/tmp102/test.esp8266-ard.yaml diff --git a/tests/components/tmp102/test.rp2040.yaml b/tests/components/tmp102/test.rp2040-ard.yaml similarity index 100% rename from tests/components/tmp102/test.rp2040.yaml rename to tests/components/tmp102/test.rp2040-ard.yaml diff --git a/tests/components/tmp1075/test.esp32.yaml b/tests/components/tmp1075/test.esp32-ard.yaml similarity index 100% rename from tests/components/tmp1075/test.esp32.yaml rename to tests/components/tmp1075/test.esp32-ard.yaml diff --git a/tests/components/tmp1075/test.esp32-c3.yaml b/tests/components/tmp1075/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/tmp1075/test.esp32-c3.yaml rename to tests/components/tmp1075/test.esp32-c3-ard.yaml diff --git a/tests/components/tmp1075/test.esp8266.yaml b/tests/components/tmp1075/test.esp8266-ard.yaml similarity index 100% rename from tests/components/tmp1075/test.esp8266.yaml rename to tests/components/tmp1075/test.esp8266-ard.yaml diff --git a/tests/components/tmp1075/test.rp2040.yaml b/tests/components/tmp1075/test.rp2040-ard.yaml similarity index 100% rename from tests/components/tmp1075/test.rp2040.yaml rename to tests/components/tmp1075/test.rp2040-ard.yaml diff --git a/tests/components/tmp117/test.esp32.yaml b/tests/components/tmp117/test.esp32-ard.yaml similarity index 100% rename from tests/components/tmp117/test.esp32.yaml rename to tests/components/tmp117/test.esp32-ard.yaml diff --git a/tests/components/tmp117/test.esp32-c3.yaml b/tests/components/tmp117/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/tmp117/test.esp32-c3.yaml rename to tests/components/tmp117/test.esp32-c3-ard.yaml diff --git a/tests/components/tmp117/test.esp8266.yaml b/tests/components/tmp117/test.esp8266-ard.yaml similarity index 100% rename from tests/components/tmp117/test.esp8266.yaml rename to tests/components/tmp117/test.esp8266-ard.yaml diff --git a/tests/components/tmp117/test.rp2040.yaml b/tests/components/tmp117/test.rp2040-ard.yaml similarity index 100% rename from tests/components/tmp117/test.rp2040.yaml rename to tests/components/tmp117/test.rp2040-ard.yaml diff --git a/tests/components/tof10120/test.esp32.yaml b/tests/components/tof10120/test.esp32-ard.yaml similarity index 100% rename from tests/components/tof10120/test.esp32.yaml rename to tests/components/tof10120/test.esp32-ard.yaml diff --git a/tests/components/tof10120/test.esp32-c3.yaml b/tests/components/tof10120/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/tof10120/test.esp32-c3.yaml rename to tests/components/tof10120/test.esp32-c3-ard.yaml diff --git a/tests/components/tof10120/test.esp8266.yaml b/tests/components/tof10120/test.esp8266-ard.yaml similarity index 100% rename from tests/components/tof10120/test.esp8266.yaml rename to tests/components/tof10120/test.esp8266-ard.yaml diff --git a/tests/components/tof10120/test.rp2040.yaml b/tests/components/tof10120/test.rp2040-ard.yaml similarity index 100% rename from tests/components/tof10120/test.rp2040.yaml rename to tests/components/tof10120/test.rp2040-ard.yaml diff --git a/tests/components/toshiba/test.esp32-c3.yaml b/tests/components/toshiba/test.esp32-ard.yaml similarity index 100% rename from tests/components/toshiba/test.esp32-c3.yaml rename to tests/components/toshiba/test.esp32-ard.yaml diff --git a/tests/components/toshiba/test.esp32.yaml b/tests/components/toshiba/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/toshiba/test.esp32.yaml rename to tests/components/toshiba/test.esp32-c3-ard.yaml diff --git a/tests/components/toshiba/test.esp8266.yaml b/tests/components/toshiba/test.esp8266-ard.yaml similarity index 100% rename from tests/components/toshiba/test.esp8266.yaml rename to tests/components/toshiba/test.esp8266-ard.yaml diff --git a/tests/components/total_daily_energy/test.esp32.yaml b/tests/components/total_daily_energy/test.esp32-ard.yaml similarity index 100% rename from tests/components/total_daily_energy/test.esp32.yaml rename to tests/components/total_daily_energy/test.esp32-ard.yaml diff --git a/tests/components/total_daily_energy/test.esp32-c3.yaml b/tests/components/total_daily_energy/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/total_daily_energy/test.esp32-c3.yaml rename to tests/components/total_daily_energy/test.esp32-c3-ard.yaml diff --git a/tests/components/total_daily_energy/test.esp8266.yaml b/tests/components/total_daily_energy/test.esp8266-ard.yaml similarity index 100% rename from tests/components/total_daily_energy/test.esp8266.yaml rename to tests/components/total_daily_energy/test.esp8266-ard.yaml diff --git a/tests/components/total_daily_energy/test.rp2040.yaml b/tests/components/total_daily_energy/test.rp2040-ard.yaml similarity index 100% rename from tests/components/total_daily_energy/test.rp2040.yaml rename to tests/components/total_daily_energy/test.rp2040-ard.yaml diff --git a/tests/components/tsl2561/test.esp32.yaml b/tests/components/tsl2561/test.esp32-ard.yaml similarity index 100% rename from tests/components/tsl2561/test.esp32.yaml rename to tests/components/tsl2561/test.esp32-ard.yaml diff --git a/tests/components/tsl2561/test.esp32-c3.yaml b/tests/components/tsl2561/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/tsl2561/test.esp32-c3.yaml rename to tests/components/tsl2561/test.esp32-c3-ard.yaml diff --git a/tests/components/tsl2561/test.esp8266.yaml b/tests/components/tsl2561/test.esp8266-ard.yaml similarity index 100% rename from tests/components/tsl2561/test.esp8266.yaml rename to tests/components/tsl2561/test.esp8266-ard.yaml diff --git a/tests/components/tsl2561/test.rp2040.yaml b/tests/components/tsl2561/test.rp2040-ard.yaml similarity index 100% rename from tests/components/tsl2561/test.rp2040.yaml rename to tests/components/tsl2561/test.rp2040-ard.yaml diff --git a/tests/components/tsl2591/test.esp32.yaml b/tests/components/tsl2591/test.esp32-ard.yaml similarity index 100% rename from tests/components/tsl2591/test.esp32.yaml rename to tests/components/tsl2591/test.esp32-ard.yaml diff --git a/tests/components/tsl2591/test.esp32-c3.yaml b/tests/components/tsl2591/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/tsl2591/test.esp32-c3.yaml rename to tests/components/tsl2591/test.esp32-c3-ard.yaml diff --git a/tests/components/tsl2591/test.esp8266.yaml b/tests/components/tsl2591/test.esp8266-ard.yaml similarity index 100% rename from tests/components/tsl2591/test.esp8266.yaml rename to tests/components/tsl2591/test.esp8266-ard.yaml diff --git a/tests/components/tsl2591/test.rp2040.yaml b/tests/components/tsl2591/test.rp2040-ard.yaml similarity index 100% rename from tests/components/tsl2591/test.rp2040.yaml rename to tests/components/tsl2591/test.rp2040-ard.yaml diff --git a/tests/components/tt21100/test.esp32.yaml b/tests/components/tt21100/test.esp32-ard.yaml similarity index 100% rename from tests/components/tt21100/test.esp32.yaml rename to tests/components/tt21100/test.esp32-ard.yaml diff --git a/tests/components/tt21100/test.esp32-c3.yaml b/tests/components/tt21100/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/tt21100/test.esp32-c3.yaml rename to tests/components/tt21100/test.esp32-c3-ard.yaml diff --git a/tests/components/tt21100/test.esp32-s2.yaml b/tests/components/tt21100/test.esp32-s2-ard.yaml similarity index 100% rename from tests/components/tt21100/test.esp32-s2.yaml rename to tests/components/tt21100/test.esp32-s2-ard.yaml diff --git a/tests/components/tt21100/test.esp8266.yaml b/tests/components/tt21100/test.esp8266-ard.yaml similarity index 100% rename from tests/components/tt21100/test.esp8266.yaml rename to tests/components/tt21100/test.esp8266-ard.yaml diff --git a/tests/components/tt21100/test.rp2040.yaml b/tests/components/tt21100/test.rp2040-ard.yaml similarity index 100% rename from tests/components/tt21100/test.rp2040.yaml rename to tests/components/tt21100/test.rp2040-ard.yaml diff --git a/tests/components/ttp229_bsf/test.esp32.yaml b/tests/components/ttp229_bsf/test.esp32-ard.yaml similarity index 100% rename from tests/components/ttp229_bsf/test.esp32.yaml rename to tests/components/ttp229_bsf/test.esp32-ard.yaml diff --git a/tests/components/ttp229_bsf/test.esp32-c3.yaml b/tests/components/ttp229_bsf/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ttp229_bsf/test.esp32-c3.yaml rename to tests/components/ttp229_bsf/test.esp32-c3-ard.yaml diff --git a/tests/components/ttp229_bsf/test.esp8266.yaml b/tests/components/ttp229_bsf/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ttp229_bsf/test.esp8266.yaml rename to tests/components/ttp229_bsf/test.esp8266-ard.yaml diff --git a/tests/components/ttp229_bsf/test.rp2040.yaml b/tests/components/ttp229_bsf/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ttp229_bsf/test.rp2040.yaml rename to tests/components/ttp229_bsf/test.rp2040-ard.yaml diff --git a/tests/components/ttp229_lsf/test.esp32.yaml b/tests/components/ttp229_lsf/test.esp32-ard.yaml similarity index 100% rename from tests/components/ttp229_lsf/test.esp32.yaml rename to tests/components/ttp229_lsf/test.esp32-ard.yaml diff --git a/tests/components/ttp229_lsf/test.esp32-c3.yaml b/tests/components/ttp229_lsf/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ttp229_lsf/test.esp32-c3.yaml rename to tests/components/ttp229_lsf/test.esp32-c3-ard.yaml diff --git a/tests/components/ttp229_lsf/test.esp8266.yaml b/tests/components/ttp229_lsf/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ttp229_lsf/test.esp8266.yaml rename to tests/components/ttp229_lsf/test.esp8266-ard.yaml diff --git a/tests/components/ttp229_lsf/test.rp2040.yaml b/tests/components/ttp229_lsf/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ttp229_lsf/test.rp2040.yaml rename to tests/components/ttp229_lsf/test.rp2040-ard.yaml diff --git a/tests/components/tuya/test.esp32.yaml b/tests/components/tuya/test.esp32-ard.yaml similarity index 100% rename from tests/components/tuya/test.esp32.yaml rename to tests/components/tuya/test.esp32-ard.yaml diff --git a/tests/components/tuya/test.esp32-c3.yaml b/tests/components/tuya/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/tuya/test.esp32-c3.yaml rename to tests/components/tuya/test.esp32-c3-ard.yaml diff --git a/tests/components/tuya/test.esp8266.yaml b/tests/components/tuya/test.esp8266-ard.yaml similarity index 100% rename from tests/components/tuya/test.esp8266.yaml rename to tests/components/tuya/test.esp8266-ard.yaml diff --git a/tests/components/tuya/test.rp2040.yaml b/tests/components/tuya/test.rp2040-ard.yaml similarity index 100% rename from tests/components/tuya/test.rp2040.yaml rename to tests/components/tuya/test.rp2040-ard.yaml diff --git a/tests/components/tx20/test.esp32-c3.yaml b/tests/components/tx20/test.esp32-ard.yaml similarity index 100% rename from tests/components/tx20/test.esp32-c3.yaml rename to tests/components/tx20/test.esp32-ard.yaml diff --git a/tests/components/tx20/test.esp32.yaml b/tests/components/tx20/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/tx20/test.esp32.yaml rename to tests/components/tx20/test.esp32-c3-ard.yaml diff --git a/tests/components/tx20/test.esp8266.yaml b/tests/components/tx20/test.esp8266-ard.yaml similarity index 100% rename from tests/components/tx20/test.esp8266.yaml rename to tests/components/tx20/test.esp8266-ard.yaml diff --git a/tests/components/tx20/test.rp2040.yaml b/tests/components/tx20/test.rp2040-ard.yaml similarity index 100% rename from tests/components/tx20/test.rp2040.yaml rename to tests/components/tx20/test.rp2040-ard.yaml diff --git a/tests/components/uart/test.esp32.yaml b/tests/components/uart/test.esp32-ard.yaml similarity index 100% rename from tests/components/uart/test.esp32.yaml rename to tests/components/uart/test.esp32-ard.yaml diff --git a/tests/components/uart/test.esp32-c3.yaml b/tests/components/uart/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/uart/test.esp32-c3.yaml rename to tests/components/uart/test.esp32-c3-ard.yaml diff --git a/tests/components/uart/test.esp8266.yaml b/tests/components/uart/test.esp8266-ard.yaml similarity index 100% rename from tests/components/uart/test.esp8266.yaml rename to tests/components/uart/test.esp8266-ard.yaml diff --git a/tests/components/uart/test.rp2040.yaml b/tests/components/uart/test.rp2040-ard.yaml similarity index 100% rename from tests/components/uart/test.rp2040.yaml rename to tests/components/uart/test.rp2040-ard.yaml diff --git a/tests/components/ufire_ec/test.esp32.yaml b/tests/components/ufire_ec/test.esp32-ard.yaml similarity index 100% rename from tests/components/ufire_ec/test.esp32.yaml rename to tests/components/ufire_ec/test.esp32-ard.yaml diff --git a/tests/components/ufire_ec/test.esp32-c3.yaml b/tests/components/ufire_ec/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ufire_ec/test.esp32-c3.yaml rename to tests/components/ufire_ec/test.esp32-c3-ard.yaml diff --git a/tests/components/ufire_ec/test.esp8266.yaml b/tests/components/ufire_ec/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ufire_ec/test.esp8266.yaml rename to tests/components/ufire_ec/test.esp8266-ard.yaml diff --git a/tests/components/ufire_ec/test.rp2040.yaml b/tests/components/ufire_ec/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ufire_ec/test.rp2040.yaml rename to tests/components/ufire_ec/test.rp2040-ard.yaml diff --git a/tests/components/ufire_ise/test.esp32.yaml b/tests/components/ufire_ise/test.esp32-ard.yaml similarity index 100% rename from tests/components/ufire_ise/test.esp32.yaml rename to tests/components/ufire_ise/test.esp32-ard.yaml diff --git a/tests/components/ufire_ise/test.esp32-c3.yaml b/tests/components/ufire_ise/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ufire_ise/test.esp32-c3.yaml rename to tests/components/ufire_ise/test.esp32-c3-ard.yaml diff --git a/tests/components/ufire_ise/test.esp8266.yaml b/tests/components/ufire_ise/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ufire_ise/test.esp8266.yaml rename to tests/components/ufire_ise/test.esp8266-ard.yaml diff --git a/tests/components/ufire_ise/test.rp2040.yaml b/tests/components/ufire_ise/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ufire_ise/test.rp2040.yaml rename to tests/components/ufire_ise/test.rp2040-ard.yaml diff --git a/tests/components/uln2003/test.esp32.yaml b/tests/components/uln2003/test.esp32-ard.yaml similarity index 100% rename from tests/components/uln2003/test.esp32.yaml rename to tests/components/uln2003/test.esp32-ard.yaml diff --git a/tests/components/uln2003/test.esp32-c3.yaml b/tests/components/uln2003/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/uln2003/test.esp32-c3.yaml rename to tests/components/uln2003/test.esp32-c3-ard.yaml diff --git a/tests/components/uln2003/test.esp8266.yaml b/tests/components/uln2003/test.esp8266-ard.yaml similarity index 100% rename from tests/components/uln2003/test.esp8266.yaml rename to tests/components/uln2003/test.esp8266-ard.yaml diff --git a/tests/components/uln2003/test.rp2040.yaml b/tests/components/uln2003/test.rp2040-ard.yaml similarity index 100% rename from tests/components/uln2003/test.rp2040.yaml rename to tests/components/uln2003/test.rp2040-ard.yaml diff --git a/tests/components/ultrasonic/test.esp32-c3.yaml b/tests/components/ultrasonic/test.esp32-ard.yaml similarity index 100% rename from tests/components/ultrasonic/test.esp32-c3.yaml rename to tests/components/ultrasonic/test.esp32-ard.yaml diff --git a/tests/components/ultrasonic/test.esp32.yaml b/tests/components/ultrasonic/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/ultrasonic/test.esp32.yaml rename to tests/components/ultrasonic/test.esp32-c3-ard.yaml diff --git a/tests/components/ultrasonic/test.esp8266.yaml b/tests/components/ultrasonic/test.esp8266-ard.yaml similarity index 100% rename from tests/components/ultrasonic/test.esp8266.yaml rename to tests/components/ultrasonic/test.esp8266-ard.yaml diff --git a/tests/components/ultrasonic/test.rp2040.yaml b/tests/components/ultrasonic/test.rp2040-ard.yaml similarity index 100% rename from tests/components/ultrasonic/test.rp2040.yaml rename to tests/components/ultrasonic/test.rp2040-ard.yaml diff --git a/tests/components/update/test.esp8266.yaml b/tests/components/update/test.esp8266-ard.yaml similarity index 100% rename from tests/components/update/test.esp8266.yaml rename to tests/components/update/test.esp8266-ard.yaml diff --git a/tests/components/update/test.rp2040.yaml b/tests/components/update/test.rp2040-ard.yaml similarity index 100% rename from tests/components/update/test.rp2040.yaml rename to tests/components/update/test.rp2040-ard.yaml diff --git a/tests/components/uponor_smatrix/test.esp32.yaml b/tests/components/uponor_smatrix/test.esp32-ard.yaml similarity index 100% rename from tests/components/uponor_smatrix/test.esp32.yaml rename to tests/components/uponor_smatrix/test.esp32-ard.yaml diff --git a/tests/components/uponor_smatrix/test.esp32-c3.yaml b/tests/components/uponor_smatrix/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/uponor_smatrix/test.esp32-c3.yaml rename to tests/components/uponor_smatrix/test.esp32-c3-ard.yaml diff --git a/tests/components/uponor_smatrix/test.esp8266.yaml b/tests/components/uponor_smatrix/test.esp8266-ard.yaml similarity index 100% rename from tests/components/uponor_smatrix/test.esp8266.yaml rename to tests/components/uponor_smatrix/test.esp8266-ard.yaml diff --git a/tests/components/uponor_smatrix/test.rp2040.yaml b/tests/components/uponor_smatrix/test.rp2040-ard.yaml similarity index 100% rename from tests/components/uponor_smatrix/test.rp2040.yaml rename to tests/components/uponor_smatrix/test.rp2040-ard.yaml diff --git a/tests/components/uptime/test.esp32-c3.yaml b/tests/components/uptime/test.esp32-ard.yaml similarity index 100% rename from tests/components/uptime/test.esp32-c3.yaml rename to tests/components/uptime/test.esp32-ard.yaml diff --git a/tests/components/uptime/test.esp32.yaml b/tests/components/uptime/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/uptime/test.esp32.yaml rename to tests/components/uptime/test.esp32-c3-ard.yaml diff --git a/tests/components/uptime/test.esp8266.yaml b/tests/components/uptime/test.esp8266-ard.yaml similarity index 100% rename from tests/components/uptime/test.esp8266.yaml rename to tests/components/uptime/test.esp8266-ard.yaml diff --git a/tests/components/uptime/test.rp2040.yaml b/tests/components/uptime/test.rp2040-ard.yaml similarity index 100% rename from tests/components/uptime/test.rp2040.yaml rename to tests/components/uptime/test.rp2040-ard.yaml diff --git a/tests/components/vbus/test.esp32.yaml b/tests/components/vbus/test.esp32-ard.yaml similarity index 100% rename from tests/components/vbus/test.esp32.yaml rename to tests/components/vbus/test.esp32-ard.yaml diff --git a/tests/components/vbus/test.esp32-c3.yaml b/tests/components/vbus/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/vbus/test.esp32-c3.yaml rename to tests/components/vbus/test.esp32-c3-ard.yaml diff --git a/tests/components/vbus/test.esp8266.yaml b/tests/components/vbus/test.esp8266-ard.yaml similarity index 100% rename from tests/components/vbus/test.esp8266.yaml rename to tests/components/vbus/test.esp8266-ard.yaml diff --git a/tests/components/vbus/test.rp2040.yaml b/tests/components/vbus/test.rp2040-ard.yaml similarity index 100% rename from tests/components/vbus/test.rp2040.yaml rename to tests/components/vbus/test.rp2040-ard.yaml diff --git a/tests/components/veml3235/test.esp32.yaml b/tests/components/veml3235/test.esp32-ard.yaml similarity index 100% rename from tests/components/veml3235/test.esp32.yaml rename to tests/components/veml3235/test.esp32-ard.yaml diff --git a/tests/components/veml3235/test.esp32-c3.yaml b/tests/components/veml3235/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/veml3235/test.esp32-c3.yaml rename to tests/components/veml3235/test.esp32-c3-ard.yaml diff --git a/tests/components/veml3235/test.esp8266.yaml b/tests/components/veml3235/test.esp8266-ard.yaml similarity index 100% rename from tests/components/veml3235/test.esp8266.yaml rename to tests/components/veml3235/test.esp8266-ard.yaml diff --git a/tests/components/veml3235/test.rp2040.yaml b/tests/components/veml3235/test.rp2040-ard.yaml similarity index 100% rename from tests/components/veml3235/test.rp2040.yaml rename to tests/components/veml3235/test.rp2040-ard.yaml diff --git a/tests/components/veml7700/test.esp32.yaml b/tests/components/veml7700/test.esp32-ard.yaml similarity index 100% rename from tests/components/veml7700/test.esp32.yaml rename to tests/components/veml7700/test.esp32-ard.yaml diff --git a/tests/components/veml7700/test.esp32-c3.yaml b/tests/components/veml7700/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/veml7700/test.esp32-c3.yaml rename to tests/components/veml7700/test.esp32-c3-ard.yaml diff --git a/tests/components/veml7700/test.esp8266.yaml b/tests/components/veml7700/test.esp8266-ard.yaml similarity index 100% rename from tests/components/veml7700/test.esp8266.yaml rename to tests/components/veml7700/test.esp8266-ard.yaml diff --git a/tests/components/veml7700/test.rp2040.yaml b/tests/components/veml7700/test.rp2040-ard.yaml similarity index 100% rename from tests/components/veml7700/test.rp2040.yaml rename to tests/components/veml7700/test.rp2040-ard.yaml diff --git a/tests/components/version/test.esp32-c3.yaml b/tests/components/version/test.esp32-ard.yaml similarity index 100% rename from tests/components/version/test.esp32-c3.yaml rename to tests/components/version/test.esp32-ard.yaml diff --git a/tests/components/version/test.esp32.yaml b/tests/components/version/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/version/test.esp32.yaml rename to tests/components/version/test.esp32-c3-ard.yaml diff --git a/tests/components/version/test.esp8266.yaml b/tests/components/version/test.esp8266-ard.yaml similarity index 100% rename from tests/components/version/test.esp8266.yaml rename to tests/components/version/test.esp8266-ard.yaml diff --git a/tests/components/version/test.rp2040.yaml b/tests/components/version/test.rp2040-ard.yaml similarity index 100% rename from tests/components/version/test.rp2040.yaml rename to tests/components/version/test.rp2040-ard.yaml diff --git a/tests/components/vl53l0x/test.esp32.yaml b/tests/components/vl53l0x/test.esp32-ard.yaml similarity index 100% rename from tests/components/vl53l0x/test.esp32.yaml rename to tests/components/vl53l0x/test.esp32-ard.yaml diff --git a/tests/components/vl53l0x/test.esp32-c3.yaml b/tests/components/vl53l0x/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/vl53l0x/test.esp32-c3.yaml rename to tests/components/vl53l0x/test.esp32-c3-ard.yaml diff --git a/tests/components/vl53l0x/test.esp8266.yaml b/tests/components/vl53l0x/test.esp8266-ard.yaml similarity index 100% rename from tests/components/vl53l0x/test.esp8266.yaml rename to tests/components/vl53l0x/test.esp8266-ard.yaml diff --git a/tests/components/vl53l0x/test.rp2040.yaml b/tests/components/vl53l0x/test.rp2040-ard.yaml similarity index 100% rename from tests/components/vl53l0x/test.rp2040.yaml rename to tests/components/vl53l0x/test.rp2040-ard.yaml diff --git a/tests/components/voice_assistant/test.esp32.yaml b/tests/components/voice_assistant/test.esp32-ard.yaml similarity index 100% rename from tests/components/voice_assistant/test.esp32.yaml rename to tests/components/voice_assistant/test.esp32-ard.yaml diff --git a/tests/components/voice_assistant/test.esp32-c3.yaml b/tests/components/voice_assistant/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/voice_assistant/test.esp32-c3.yaml rename to tests/components/voice_assistant/test.esp32-c3-ard.yaml diff --git a/tests/components/wake_on_lan/test.esp32-c3.yaml b/tests/components/wake_on_lan/test.esp32-ard.yaml similarity index 100% rename from tests/components/wake_on_lan/test.esp32-c3.yaml rename to tests/components/wake_on_lan/test.esp32-ard.yaml diff --git a/tests/components/wake_on_lan/test.esp32.yaml b/tests/components/wake_on_lan/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/wake_on_lan/test.esp32.yaml rename to tests/components/wake_on_lan/test.esp32-c3-ard.yaml diff --git a/tests/components/wake_on_lan/test.esp8266.yaml b/tests/components/wake_on_lan/test.esp8266-ard.yaml similarity index 100% rename from tests/components/wake_on_lan/test.esp8266.yaml rename to tests/components/wake_on_lan/test.esp8266-ard.yaml diff --git a/tests/components/wake_on_lan/test.rp2040.yaml b/tests/components/wake_on_lan/test.rp2040-ard.yaml similarity index 100% rename from tests/components/wake_on_lan/test.rp2040.yaml rename to tests/components/wake_on_lan/test.rp2040-ard.yaml diff --git a/tests/components/waveshare_epaper/test.esp32.yaml b/tests/components/waveshare_epaper/test.esp32-ard.yaml similarity index 100% rename from tests/components/waveshare_epaper/test.esp32.yaml rename to tests/components/waveshare_epaper/test.esp32-ard.yaml diff --git a/tests/components/waveshare_epaper/test.esp32-c3.yaml b/tests/components/waveshare_epaper/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/waveshare_epaper/test.esp32-c3.yaml rename to tests/components/waveshare_epaper/test.esp32-c3-ard.yaml diff --git a/tests/components/waveshare_epaper/test.esp8266.yaml b/tests/components/waveshare_epaper/test.esp8266-ard.yaml similarity index 100% rename from tests/components/waveshare_epaper/test.esp8266.yaml rename to tests/components/waveshare_epaper/test.esp8266-ard.yaml diff --git a/tests/components/waveshare_epaper/test.rp2040.yaml b/tests/components/waveshare_epaper/test.rp2040-ard.yaml similarity index 100% rename from tests/components/waveshare_epaper/test.rp2040.yaml rename to tests/components/waveshare_epaper/test.rp2040-ard.yaml diff --git a/tests/components/web_server/test.esp32-c3.yaml b/tests/components/web_server/test.esp32-ard.yaml similarity index 100% rename from tests/components/web_server/test.esp32-c3.yaml rename to tests/components/web_server/test.esp32-ard.yaml diff --git a/tests/components/web_server/test.esp32.yaml b/tests/components/web_server/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/web_server/test.esp32.yaml rename to tests/components/web_server/test.esp32-c3-ard.yaml diff --git a/tests/components/web_server/test.esp8266.yaml b/tests/components/web_server/test.esp8266-ard.yaml similarity index 100% rename from tests/components/web_server/test.esp8266.yaml rename to tests/components/web_server/test.esp8266-ard.yaml diff --git a/tests/components/whirlpool/test.esp32-c3.yaml b/tests/components/whirlpool/test.esp32-ard.yaml similarity index 100% rename from tests/components/whirlpool/test.esp32-c3.yaml rename to tests/components/whirlpool/test.esp32-ard.yaml diff --git a/tests/components/whirlpool/test.esp32.yaml b/tests/components/whirlpool/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/whirlpool/test.esp32.yaml rename to tests/components/whirlpool/test.esp32-c3-ard.yaml diff --git a/tests/components/whirlpool/test.esp8266.yaml b/tests/components/whirlpool/test.esp8266-ard.yaml similarity index 100% rename from tests/components/whirlpool/test.esp8266.yaml rename to tests/components/whirlpool/test.esp8266-ard.yaml diff --git a/tests/components/whynter/test.esp32-c3.yaml b/tests/components/whynter/test.esp32-ard.yaml similarity index 100% rename from tests/components/whynter/test.esp32-c3.yaml rename to tests/components/whynter/test.esp32-ard.yaml diff --git a/tests/components/whynter/test.esp32.yaml b/tests/components/whynter/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/whynter/test.esp32.yaml rename to tests/components/whynter/test.esp32-c3-ard.yaml diff --git a/tests/components/whynter/test.esp8266.yaml b/tests/components/whynter/test.esp8266-ard.yaml similarity index 100% rename from tests/components/whynter/test.esp8266.yaml rename to tests/components/whynter/test.esp8266-ard.yaml diff --git a/tests/components/wiegand/test.esp32-c3.yaml b/tests/components/wiegand/test.esp32-ard.yaml similarity index 100% rename from tests/components/wiegand/test.esp32-c3.yaml rename to tests/components/wiegand/test.esp32-ard.yaml diff --git a/tests/components/wiegand/test.esp32.yaml b/tests/components/wiegand/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/wiegand/test.esp32.yaml rename to tests/components/wiegand/test.esp32-c3-ard.yaml diff --git a/tests/components/wiegand/test.esp8266.yaml b/tests/components/wiegand/test.esp8266-ard.yaml similarity index 100% rename from tests/components/wiegand/test.esp8266.yaml rename to tests/components/wiegand/test.esp8266-ard.yaml diff --git a/tests/components/wiegand/test.rp2040.yaml b/tests/components/wiegand/test.rp2040-ard.yaml similarity index 100% rename from tests/components/wiegand/test.rp2040.yaml rename to tests/components/wiegand/test.rp2040-ard.yaml diff --git a/tests/components/wifi/test.esp32-c3.yaml b/tests/components/wifi/test.esp32-ard.yaml similarity index 100% rename from tests/components/wifi/test.esp32-c3.yaml rename to tests/components/wifi/test.esp32-ard.yaml diff --git a/tests/components/wifi/test.esp32.yaml b/tests/components/wifi/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/wifi/test.esp32.yaml rename to tests/components/wifi/test.esp32-c3-ard.yaml diff --git a/tests/components/wifi/test.esp8266.yaml b/tests/components/wifi/test.esp8266-ard.yaml similarity index 100% rename from tests/components/wifi/test.esp8266.yaml rename to tests/components/wifi/test.esp8266-ard.yaml diff --git a/tests/components/wifi/test.rp2040.yaml b/tests/components/wifi/test.rp2040-ard.yaml similarity index 100% rename from tests/components/wifi/test.rp2040.yaml rename to tests/components/wifi/test.rp2040-ard.yaml diff --git a/tests/components/wifi_info/test.esp32-c3.yaml b/tests/components/wifi_info/test.esp32-ard.yaml similarity index 100% rename from tests/components/wifi_info/test.esp32-c3.yaml rename to tests/components/wifi_info/test.esp32-ard.yaml diff --git a/tests/components/wifi_info/test.esp32.yaml b/tests/components/wifi_info/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/wifi_info/test.esp32.yaml rename to tests/components/wifi_info/test.esp32-c3-ard.yaml diff --git a/tests/components/wifi_info/test.esp8266.yaml b/tests/components/wifi_info/test.esp8266-ard.yaml similarity index 100% rename from tests/components/wifi_info/test.esp8266.yaml rename to tests/components/wifi_info/test.esp8266-ard.yaml diff --git a/tests/components/wifi_info/test.rp2040.yaml b/tests/components/wifi_info/test.rp2040-ard.yaml similarity index 100% rename from tests/components/wifi_info/test.rp2040.yaml rename to tests/components/wifi_info/test.rp2040-ard.yaml diff --git a/tests/components/wifi_signal/test.esp32-c3.yaml b/tests/components/wifi_signal/test.esp32-ard.yaml similarity index 100% rename from tests/components/wifi_signal/test.esp32-c3.yaml rename to tests/components/wifi_signal/test.esp32-ard.yaml diff --git a/tests/components/wifi_signal/test.esp32.yaml b/tests/components/wifi_signal/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/wifi_signal/test.esp32.yaml rename to tests/components/wifi_signal/test.esp32-c3-ard.yaml diff --git a/tests/components/wifi_signal/test.esp8266.yaml b/tests/components/wifi_signal/test.esp8266-ard.yaml similarity index 100% rename from tests/components/wifi_signal/test.esp8266.yaml rename to tests/components/wifi_signal/test.esp8266-ard.yaml diff --git a/tests/components/wifi_signal/test.rp2040.yaml b/tests/components/wifi_signal/test.rp2040-ard.yaml similarity index 100% rename from tests/components/wifi_signal/test.rp2040.yaml rename to tests/components/wifi_signal/test.rp2040-ard.yaml diff --git a/tests/components/wireguard/test.bk72xx.yaml b/tests/components/wireguard/test.bk72xx-ard.yaml similarity index 100% rename from tests/components/wireguard/test.bk72xx.yaml rename to tests/components/wireguard/test.bk72xx-ard.yaml diff --git a/tests/components/wireguard/test.esp32.yaml b/tests/components/wireguard/test.esp32-ard.yaml similarity index 100% rename from tests/components/wireguard/test.esp32.yaml rename to tests/components/wireguard/test.esp32-ard.yaml diff --git a/tests/components/wireguard/test.esp32-c3.yaml b/tests/components/wireguard/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/wireguard/test.esp32-c3.yaml rename to tests/components/wireguard/test.esp32-c3-ard.yaml diff --git a/tests/components/wireguard/test.esp8266.yaml b/tests/components/wireguard/test.esp8266-ard.yaml similarity index 100% rename from tests/components/wireguard/test.esp8266.yaml rename to tests/components/wireguard/test.esp8266-ard.yaml diff --git a/tests/components/wk2132_i2c/test.esp32.yaml b/tests/components/wk2132_i2c/test.esp32-ard.yaml similarity index 100% rename from tests/components/wk2132_i2c/test.esp32.yaml rename to tests/components/wk2132_i2c/test.esp32-ard.yaml diff --git a/tests/components/wk2132_i2c/test.esp32-s3.yaml b/tests/components/wk2132_i2c/test.esp32-s3-ard.yaml similarity index 100% rename from tests/components/wk2132_i2c/test.esp32-s3.yaml rename to tests/components/wk2132_i2c/test.esp32-s3-ard.yaml diff --git a/tests/components/wk2132_spi/test.esp32.yaml b/tests/components/wk2132_spi/test.esp32-ard.yaml similarity index 100% rename from tests/components/wk2132_spi/test.esp32.yaml rename to tests/components/wk2132_spi/test.esp32-ard.yaml diff --git a/tests/components/wk2132_spi/test.esp32-s3.yaml b/tests/components/wk2132_spi/test.esp32-s3-ard.yaml similarity index 100% rename from tests/components/wk2132_spi/test.esp32-s3.yaml rename to tests/components/wk2132_spi/test.esp32-s3-ard.yaml diff --git a/tests/components/wk2168_i2c/test.esp32.yaml b/tests/components/wk2168_i2c/test.esp32-ard.yaml similarity index 100% rename from tests/components/wk2168_i2c/test.esp32.yaml rename to tests/components/wk2168_i2c/test.esp32-ard.yaml diff --git a/tests/components/wk2168_i2c/test.esp32-s3.yaml b/tests/components/wk2168_i2c/test.esp32-s3-ard.yaml similarity index 100% rename from tests/components/wk2168_i2c/test.esp32-s3.yaml rename to tests/components/wk2168_i2c/test.esp32-s3-ard.yaml diff --git a/tests/components/wk2168_spi/test.esp32.yaml b/tests/components/wk2168_spi/test.esp32-ard.yaml similarity index 100% rename from tests/components/wk2168_spi/test.esp32.yaml rename to tests/components/wk2168_spi/test.esp32-ard.yaml diff --git a/tests/components/wk2168_spi/test.esp32-s3.yaml b/tests/components/wk2168_spi/test.esp32-s3-ard.yaml similarity index 100% rename from tests/components/wk2168_spi/test.esp32-s3.yaml rename to tests/components/wk2168_spi/test.esp32-s3-ard.yaml diff --git a/tests/components/wk2204_i2c/test.esp32.yaml b/tests/components/wk2204_i2c/test.esp32-ard.yaml similarity index 100% rename from tests/components/wk2204_i2c/test.esp32.yaml rename to tests/components/wk2204_i2c/test.esp32-ard.yaml diff --git a/tests/components/wk2204_i2c/test.esp32-s3.yaml b/tests/components/wk2204_i2c/test.esp32-s3-ard.yaml similarity index 100% rename from tests/components/wk2204_i2c/test.esp32-s3.yaml rename to tests/components/wk2204_i2c/test.esp32-s3-ard.yaml diff --git a/tests/components/wk2204_spi/test.esp32.yaml b/tests/components/wk2204_spi/test.esp32-ard.yaml similarity index 100% rename from tests/components/wk2204_spi/test.esp32.yaml rename to tests/components/wk2204_spi/test.esp32-ard.yaml diff --git a/tests/components/wk2204_spi/test.esp32-s3.yaml b/tests/components/wk2204_spi/test.esp32-s3-ard.yaml similarity index 100% rename from tests/components/wk2204_spi/test.esp32-s3.yaml rename to tests/components/wk2204_spi/test.esp32-s3-ard.yaml diff --git a/tests/components/wk2212_i2c/test.esp32.yaml b/tests/components/wk2212_i2c/test.esp32-ard.yaml similarity index 100% rename from tests/components/wk2212_i2c/test.esp32.yaml rename to tests/components/wk2212_i2c/test.esp32-ard.yaml diff --git a/tests/components/wk2212_i2c/test.esp32-s3.yaml b/tests/components/wk2212_i2c/test.esp32-s3-ard.yaml similarity index 100% rename from tests/components/wk2212_i2c/test.esp32-s3.yaml rename to tests/components/wk2212_i2c/test.esp32-s3-ard.yaml diff --git a/tests/components/wk2212_spi/test.esp32.yaml b/tests/components/wk2212_spi/test.esp32-ard.yaml similarity index 100% rename from tests/components/wk2212_spi/test.esp32.yaml rename to tests/components/wk2212_spi/test.esp32-ard.yaml diff --git a/tests/components/wk2212_spi/test.esp32-s3.yaml b/tests/components/wk2212_spi/test.esp32-s3-ard.yaml similarity index 100% rename from tests/components/wk2212_spi/test.esp32-s3.yaml rename to tests/components/wk2212_spi/test.esp32-s3-ard.yaml diff --git a/tests/components/wl_134/test.esp32.yaml b/tests/components/wl_134/test.esp32-ard.yaml similarity index 100% rename from tests/components/wl_134/test.esp32.yaml rename to tests/components/wl_134/test.esp32-ard.yaml diff --git a/tests/components/wl_134/test.esp32-c3.yaml b/tests/components/wl_134/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/wl_134/test.esp32-c3.yaml rename to tests/components/wl_134/test.esp32-c3-ard.yaml diff --git a/tests/components/wl_134/test.esp8266.yaml b/tests/components/wl_134/test.esp8266-ard.yaml similarity index 100% rename from tests/components/wl_134/test.esp8266.yaml rename to tests/components/wl_134/test.esp8266-ard.yaml diff --git a/tests/components/wl_134/test.rp2040.yaml b/tests/components/wl_134/test.rp2040-ard.yaml similarity index 100% rename from tests/components/wl_134/test.rp2040.yaml rename to tests/components/wl_134/test.rp2040-ard.yaml diff --git a/tests/components/wled/test.esp32-c3.yaml b/tests/components/wled/test.esp32-ard.yaml similarity index 100% rename from tests/components/wled/test.esp32-c3.yaml rename to tests/components/wled/test.esp32-ard.yaml diff --git a/tests/components/wled/test.esp32.yaml b/tests/components/wled/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/wled/test.esp32.yaml rename to tests/components/wled/test.esp32-c3-ard.yaml diff --git a/tests/components/wled/test.esp8266.yaml b/tests/components/wled/test.esp8266-ard.yaml similarity index 100% rename from tests/components/wled/test.esp8266.yaml rename to tests/components/wled/test.esp8266-ard.yaml diff --git a/tests/components/x9c/test.esp32.yaml b/tests/components/x9c/test.esp32-ard.yaml similarity index 100% rename from tests/components/x9c/test.esp32.yaml rename to tests/components/x9c/test.esp32-ard.yaml diff --git a/tests/components/x9c/test.esp32-c3.yaml b/tests/components/x9c/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/x9c/test.esp32-c3.yaml rename to tests/components/x9c/test.esp32-c3-ard.yaml diff --git a/tests/components/x9c/test.esp8266.yaml b/tests/components/x9c/test.esp8266-ard.yaml similarity index 100% rename from tests/components/x9c/test.esp8266.yaml rename to tests/components/x9c/test.esp8266-ard.yaml diff --git a/tests/components/x9c/test.rp2040.yaml b/tests/components/x9c/test.rp2040-ard.yaml similarity index 100% rename from tests/components/x9c/test.rp2040.yaml rename to tests/components/x9c/test.rp2040-ard.yaml diff --git a/tests/components/xgzp68xx/test.esp32.yaml b/tests/components/xgzp68xx/test.esp32-ard.yaml similarity index 100% rename from tests/components/xgzp68xx/test.esp32.yaml rename to tests/components/xgzp68xx/test.esp32-ard.yaml diff --git a/tests/components/xgzp68xx/test.esp32-c3.yaml b/tests/components/xgzp68xx/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/xgzp68xx/test.esp32-c3.yaml rename to tests/components/xgzp68xx/test.esp32-c3-ard.yaml diff --git a/tests/components/xgzp68xx/test.esp8266.yaml b/tests/components/xgzp68xx/test.esp8266-ard.yaml similarity index 100% rename from tests/components/xgzp68xx/test.esp8266.yaml rename to tests/components/xgzp68xx/test.esp8266-ard.yaml diff --git a/tests/components/xgzp68xx/test.rp2040.yaml b/tests/components/xgzp68xx/test.rp2040-ard.yaml similarity index 100% rename from tests/components/xgzp68xx/test.rp2040.yaml rename to tests/components/xgzp68xx/test.rp2040-ard.yaml diff --git a/tests/components/xiaomi_ble/test.esp32-c3.yaml b/tests/components/xiaomi_ble/test.esp32-ard.yaml similarity index 100% rename from tests/components/xiaomi_ble/test.esp32-c3.yaml rename to tests/components/xiaomi_ble/test.esp32-ard.yaml diff --git a/tests/components/xiaomi_ble/test.esp32.yaml b/tests/components/xiaomi_ble/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/xiaomi_ble/test.esp32.yaml rename to tests/components/xiaomi_ble/test.esp32-c3-ard.yaml diff --git a/tests/components/xiaomi_cgd1/test.esp32-c3.yaml b/tests/components/xiaomi_cgd1/test.esp32-ard.yaml similarity index 100% rename from tests/components/xiaomi_cgd1/test.esp32-c3.yaml rename to tests/components/xiaomi_cgd1/test.esp32-ard.yaml diff --git a/tests/components/xiaomi_cgd1/test.esp32.yaml b/tests/components/xiaomi_cgd1/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/xiaomi_cgd1/test.esp32.yaml rename to tests/components/xiaomi_cgd1/test.esp32-c3-ard.yaml diff --git a/tests/components/xiaomi_cgdk2/test.esp32-c3.yaml b/tests/components/xiaomi_cgdk2/test.esp32-ard.yaml similarity index 100% rename from tests/components/xiaomi_cgdk2/test.esp32-c3.yaml rename to tests/components/xiaomi_cgdk2/test.esp32-ard.yaml diff --git a/tests/components/xiaomi_cgdk2/test.esp32.yaml b/tests/components/xiaomi_cgdk2/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/xiaomi_cgdk2/test.esp32.yaml rename to tests/components/xiaomi_cgdk2/test.esp32-c3-ard.yaml diff --git a/tests/components/xiaomi_cgg1/test.esp32-c3.yaml b/tests/components/xiaomi_cgg1/test.esp32-ard.yaml similarity index 100% rename from tests/components/xiaomi_cgg1/test.esp32-c3.yaml rename to tests/components/xiaomi_cgg1/test.esp32-ard.yaml diff --git a/tests/components/xiaomi_cgg1/test.esp32.yaml b/tests/components/xiaomi_cgg1/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/xiaomi_cgg1/test.esp32.yaml rename to tests/components/xiaomi_cgg1/test.esp32-c3-ard.yaml diff --git a/tests/components/xiaomi_cgpr1/test.esp32-c3.yaml b/tests/components/xiaomi_cgpr1/test.esp32-ard.yaml similarity index 100% rename from tests/components/xiaomi_cgpr1/test.esp32-c3.yaml rename to tests/components/xiaomi_cgpr1/test.esp32-ard.yaml diff --git a/tests/components/xiaomi_cgpr1/test.esp32.yaml b/tests/components/xiaomi_cgpr1/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/xiaomi_cgpr1/test.esp32.yaml rename to tests/components/xiaomi_cgpr1/test.esp32-c3-ard.yaml diff --git a/tests/components/xiaomi_gcls002/test.esp32-c3.yaml b/tests/components/xiaomi_gcls002/test.esp32-ard.yaml similarity index 100% rename from tests/components/xiaomi_gcls002/test.esp32-c3.yaml rename to tests/components/xiaomi_gcls002/test.esp32-ard.yaml diff --git a/tests/components/xiaomi_gcls002/test.esp32.yaml b/tests/components/xiaomi_gcls002/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/xiaomi_gcls002/test.esp32.yaml rename to tests/components/xiaomi_gcls002/test.esp32-c3-ard.yaml diff --git a/tests/components/xiaomi_hhccjcy01/test.esp32-c3.yaml b/tests/components/xiaomi_hhccjcy01/test.esp32-ard.yaml similarity index 100% rename from tests/components/xiaomi_hhccjcy01/test.esp32-c3.yaml rename to tests/components/xiaomi_hhccjcy01/test.esp32-ard.yaml diff --git a/tests/components/xiaomi_hhccjcy01/test.esp32.yaml b/tests/components/xiaomi_hhccjcy01/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/xiaomi_hhccjcy01/test.esp32.yaml rename to tests/components/xiaomi_hhccjcy01/test.esp32-c3-ard.yaml diff --git a/tests/components/xiaomi_hhccpot002/test.esp32-c3.yaml b/tests/components/xiaomi_hhccpot002/test.esp32-ard.yaml similarity index 100% rename from tests/components/xiaomi_hhccpot002/test.esp32-c3.yaml rename to tests/components/xiaomi_hhccpot002/test.esp32-ard.yaml diff --git a/tests/components/xiaomi_hhccpot002/test.esp32.yaml b/tests/components/xiaomi_hhccpot002/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/xiaomi_hhccpot002/test.esp32.yaml rename to tests/components/xiaomi_hhccpot002/test.esp32-c3-ard.yaml diff --git a/tests/components/xiaomi_jqjcy01ym/test.esp32-c3.yaml b/tests/components/xiaomi_jqjcy01ym/test.esp32-ard.yaml similarity index 100% rename from tests/components/xiaomi_jqjcy01ym/test.esp32-c3.yaml rename to tests/components/xiaomi_jqjcy01ym/test.esp32-ard.yaml diff --git a/tests/components/xiaomi_jqjcy01ym/test.esp32.yaml b/tests/components/xiaomi_jqjcy01ym/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/xiaomi_jqjcy01ym/test.esp32.yaml rename to tests/components/xiaomi_jqjcy01ym/test.esp32-c3-ard.yaml diff --git a/tests/components/xiaomi_lywsd02/test.esp32-c3.yaml b/tests/components/xiaomi_lywsd02/test.esp32-ard.yaml similarity index 100% rename from tests/components/xiaomi_lywsd02/test.esp32-c3.yaml rename to tests/components/xiaomi_lywsd02/test.esp32-ard.yaml diff --git a/tests/components/xiaomi_lywsd02/test.esp32.yaml b/tests/components/xiaomi_lywsd02/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/xiaomi_lywsd02/test.esp32.yaml rename to tests/components/xiaomi_lywsd02/test.esp32-c3-ard.yaml diff --git a/tests/components/xiaomi_lywsd03mmc/test.esp32-c3.yaml b/tests/components/xiaomi_lywsd03mmc/test.esp32-ard.yaml similarity index 100% rename from tests/components/xiaomi_lywsd03mmc/test.esp32-c3.yaml rename to tests/components/xiaomi_lywsd03mmc/test.esp32-ard.yaml diff --git a/tests/components/xiaomi_lywsd03mmc/test.esp32.yaml b/tests/components/xiaomi_lywsd03mmc/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/xiaomi_lywsd03mmc/test.esp32.yaml rename to tests/components/xiaomi_lywsd03mmc/test.esp32-c3-ard.yaml diff --git a/tests/components/xiaomi_lywsdcgq/test.esp32-c3.yaml b/tests/components/xiaomi_lywsdcgq/test.esp32-ard.yaml similarity index 100% rename from tests/components/xiaomi_lywsdcgq/test.esp32-c3.yaml rename to tests/components/xiaomi_lywsdcgq/test.esp32-ard.yaml diff --git a/tests/components/xiaomi_lywsdcgq/test.esp32.yaml b/tests/components/xiaomi_lywsdcgq/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/xiaomi_lywsdcgq/test.esp32.yaml rename to tests/components/xiaomi_lywsdcgq/test.esp32-c3-ard.yaml diff --git a/tests/components/xiaomi_mhoc303/test.esp32-c3.yaml b/tests/components/xiaomi_mhoc303/test.esp32-ard.yaml similarity index 100% rename from tests/components/xiaomi_mhoc303/test.esp32-c3.yaml rename to tests/components/xiaomi_mhoc303/test.esp32-ard.yaml diff --git a/tests/components/xiaomi_mhoc303/test.esp32.yaml b/tests/components/xiaomi_mhoc303/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/xiaomi_mhoc303/test.esp32.yaml rename to tests/components/xiaomi_mhoc303/test.esp32-c3-ard.yaml diff --git a/tests/components/xiaomi_mhoc401/test.esp32-c3.yaml b/tests/components/xiaomi_mhoc401/test.esp32-ard.yaml similarity index 100% rename from tests/components/xiaomi_mhoc401/test.esp32-c3.yaml rename to tests/components/xiaomi_mhoc401/test.esp32-ard.yaml diff --git a/tests/components/xiaomi_mhoc401/test.esp32.yaml b/tests/components/xiaomi_mhoc401/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/xiaomi_mhoc401/test.esp32.yaml rename to tests/components/xiaomi_mhoc401/test.esp32-c3-ard.yaml diff --git a/tests/components/xiaomi_miscale copy/test.esp32-c3.yaml b/tests/components/xiaomi_miscale copy/test.esp32-ard.yaml similarity index 100% rename from tests/components/xiaomi_miscale copy/test.esp32-c3.yaml rename to tests/components/xiaomi_miscale copy/test.esp32-ard.yaml diff --git a/tests/components/xiaomi_miscale copy/test.esp32.yaml b/tests/components/xiaomi_miscale copy/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/xiaomi_miscale copy/test.esp32.yaml rename to tests/components/xiaomi_miscale copy/test.esp32-c3-ard.yaml diff --git a/tests/components/xiaomi_miscale/test.esp32-c3.yaml b/tests/components/xiaomi_miscale/test.esp32-ard.yaml similarity index 100% rename from tests/components/xiaomi_miscale/test.esp32-c3.yaml rename to tests/components/xiaomi_miscale/test.esp32-ard.yaml diff --git a/tests/components/xiaomi_miscale/test.esp32.yaml b/tests/components/xiaomi_miscale/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/xiaomi_miscale/test.esp32.yaml rename to tests/components/xiaomi_miscale/test.esp32-c3-ard.yaml diff --git a/tests/components/xiaomi_mjyd02yla/test.esp32-c3.yaml b/tests/components/xiaomi_mjyd02yla/test.esp32-ard.yaml similarity index 100% rename from tests/components/xiaomi_mjyd02yla/test.esp32-c3.yaml rename to tests/components/xiaomi_mjyd02yla/test.esp32-ard.yaml diff --git a/tests/components/xiaomi_mjyd02yla/test.esp32.yaml b/tests/components/xiaomi_mjyd02yla/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/xiaomi_mjyd02yla/test.esp32.yaml rename to tests/components/xiaomi_mjyd02yla/test.esp32-c3-ard.yaml diff --git a/tests/components/xiaomi_mue4094rt/test.esp32-c3.yaml b/tests/components/xiaomi_mue4094rt/test.esp32-ard.yaml similarity index 100% rename from tests/components/xiaomi_mue4094rt/test.esp32-c3.yaml rename to tests/components/xiaomi_mue4094rt/test.esp32-ard.yaml diff --git a/tests/components/xiaomi_mue4094rt/test.esp32.yaml b/tests/components/xiaomi_mue4094rt/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/xiaomi_mue4094rt/test.esp32.yaml rename to tests/components/xiaomi_mue4094rt/test.esp32-c3-ard.yaml diff --git a/tests/components/xiaomi_rtcgq02lm/test.esp32-c3.yaml b/tests/components/xiaomi_rtcgq02lm/test.esp32-ard.yaml similarity index 100% rename from tests/components/xiaomi_rtcgq02lm/test.esp32-c3.yaml rename to tests/components/xiaomi_rtcgq02lm/test.esp32-ard.yaml diff --git a/tests/components/xiaomi_rtcgq02lm/test.esp32.yaml b/tests/components/xiaomi_rtcgq02lm/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/xiaomi_rtcgq02lm/test.esp32.yaml rename to tests/components/xiaomi_rtcgq02lm/test.esp32-c3-ard.yaml diff --git a/tests/components/xiaomi_wx08zm/test.esp32-c3.yaml b/tests/components/xiaomi_wx08zm/test.esp32-ard.yaml similarity index 100% rename from tests/components/xiaomi_wx08zm/test.esp32-c3.yaml rename to tests/components/xiaomi_wx08zm/test.esp32-ard.yaml diff --git a/tests/components/xiaomi_wx08zm/test.esp32.yaml b/tests/components/xiaomi_wx08zm/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/xiaomi_wx08zm/test.esp32.yaml rename to tests/components/xiaomi_wx08zm/test.esp32-c3-ard.yaml diff --git a/tests/components/xl9535/test.esp32.yaml b/tests/components/xl9535/test.esp32-ard.yaml similarity index 100% rename from tests/components/xl9535/test.esp32.yaml rename to tests/components/xl9535/test.esp32-ard.yaml diff --git a/tests/components/xl9535/test.esp32-c3.yaml b/tests/components/xl9535/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/xl9535/test.esp32-c3.yaml rename to tests/components/xl9535/test.esp32-c3-ard.yaml diff --git a/tests/components/xl9535/test.esp8266.yaml b/tests/components/xl9535/test.esp8266-ard.yaml similarity index 100% rename from tests/components/xl9535/test.esp8266.yaml rename to tests/components/xl9535/test.esp8266-ard.yaml diff --git a/tests/components/xl9535/test.rp2040.yaml b/tests/components/xl9535/test.rp2040-ard.yaml similarity index 100% rename from tests/components/xl9535/test.rp2040.yaml rename to tests/components/xl9535/test.rp2040-ard.yaml diff --git a/tests/components/xpt2046/test.esp32.yaml b/tests/components/xpt2046/test.esp32-ard.yaml similarity index 100% rename from tests/components/xpt2046/test.esp32.yaml rename to tests/components/xpt2046/test.esp32-ard.yaml diff --git a/tests/components/xpt2046/test.esp32-c3.yaml b/tests/components/xpt2046/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/xpt2046/test.esp32-c3.yaml rename to tests/components/xpt2046/test.esp32-c3-ard.yaml diff --git a/tests/components/xpt2046/test.esp32-s2.yaml b/tests/components/xpt2046/test.esp32-s2-ard.yaml similarity index 100% rename from tests/components/xpt2046/test.esp32-s2.yaml rename to tests/components/xpt2046/test.esp32-s2-ard.yaml diff --git a/tests/components/xpt2046/test.esp8266.yaml b/tests/components/xpt2046/test.esp8266-ard.yaml similarity index 100% rename from tests/components/xpt2046/test.esp8266.yaml rename to tests/components/xpt2046/test.esp8266-ard.yaml diff --git a/tests/components/xpt2046/test.rp2040.yaml b/tests/components/xpt2046/test.rp2040-ard.yaml similarity index 100% rename from tests/components/xpt2046/test.rp2040.yaml rename to tests/components/xpt2046/test.rp2040-ard.yaml diff --git a/tests/components/yashima/test.esp32-c3.yaml b/tests/components/yashima/test.esp32-ard.yaml similarity index 100% rename from tests/components/yashima/test.esp32-c3.yaml rename to tests/components/yashima/test.esp32-ard.yaml diff --git a/tests/components/yashima/test.esp32.yaml b/tests/components/yashima/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/yashima/test.esp32.yaml rename to tests/components/yashima/test.esp32-c3-ard.yaml diff --git a/tests/components/yashima/test.esp8266.yaml b/tests/components/yashima/test.esp8266-ard.yaml similarity index 100% rename from tests/components/yashima/test.esp8266.yaml rename to tests/components/yashima/test.esp8266-ard.yaml diff --git a/tests/components/zhlt01/test.esp32-c3.yaml b/tests/components/zhlt01/test.esp32-ard.yaml similarity index 100% rename from tests/components/zhlt01/test.esp32-c3.yaml rename to tests/components/zhlt01/test.esp32-ard.yaml diff --git a/tests/components/zhlt01/test.esp32.yaml b/tests/components/zhlt01/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/zhlt01/test.esp32.yaml rename to tests/components/zhlt01/test.esp32-c3-ard.yaml diff --git a/tests/components/zhlt01/test.esp8266.yaml b/tests/components/zhlt01/test.esp8266-ard.yaml similarity index 100% rename from tests/components/zhlt01/test.esp8266.yaml rename to tests/components/zhlt01/test.esp8266-ard.yaml diff --git a/tests/components/zio_ultrasonic/test.esp32.yaml b/tests/components/zio_ultrasonic/test.esp32-ard.yaml similarity index 100% rename from tests/components/zio_ultrasonic/test.esp32.yaml rename to tests/components/zio_ultrasonic/test.esp32-ard.yaml diff --git a/tests/components/zio_ultrasonic/test.esp32-c3.yaml b/tests/components/zio_ultrasonic/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/zio_ultrasonic/test.esp32-c3.yaml rename to tests/components/zio_ultrasonic/test.esp32-c3-ard.yaml diff --git a/tests/components/zio_ultrasonic/test.esp8266.yaml b/tests/components/zio_ultrasonic/test.esp8266-ard.yaml similarity index 100% rename from tests/components/zio_ultrasonic/test.esp8266.yaml rename to tests/components/zio_ultrasonic/test.esp8266-ard.yaml diff --git a/tests/components/zio_ultrasonic/test.rp2040.yaml b/tests/components/zio_ultrasonic/test.rp2040-ard.yaml similarity index 100% rename from tests/components/zio_ultrasonic/test.rp2040.yaml rename to tests/components/zio_ultrasonic/test.rp2040-ard.yaml diff --git a/tests/components/zyaura/test.esp32.yaml b/tests/components/zyaura/test.esp32-ard.yaml similarity index 100% rename from tests/components/zyaura/test.esp32.yaml rename to tests/components/zyaura/test.esp32-ard.yaml diff --git a/tests/components/zyaura/test.esp32-c3.yaml b/tests/components/zyaura/test.esp32-c3-ard.yaml similarity index 100% rename from tests/components/zyaura/test.esp32-c3.yaml rename to tests/components/zyaura/test.esp32-c3-ard.yaml diff --git a/tests/components/zyaura/test.esp8266.yaml b/tests/components/zyaura/test.esp8266-ard.yaml similarity index 100% rename from tests/components/zyaura/test.esp8266.yaml rename to tests/components/zyaura/test.esp8266-ard.yaml diff --git a/tests/components/zyaura/test.rp2040.yaml b/tests/components/zyaura/test.rp2040-ard.yaml similarity index 100% rename from tests/components/zyaura/test.rp2040.yaml rename to tests/components/zyaura/test.rp2040-ard.yaml diff --git a/tests/test_build_components/build_components_base.bk72xx.yaml b/tests/test_build_components/build_components_base.bk72xx-ard.yaml similarity index 100% rename from tests/test_build_components/build_components_base.bk72xx.yaml rename to tests/test_build_components/build_components_base.bk72xx-ard.yaml diff --git a/tests/test_build_components/build_components_base.esp32-c3-idf-50.yaml b/tests/test_build_components/build_components_base.esp32-c3-idf-50.yaml new file mode 100644 index 0000000000..08d4d8679c --- /dev/null +++ b/tests/test_build_components/build_components_base.esp32-c3-idf-50.yaml @@ -0,0 +1,19 @@ +esphome: + name: componenttestesp32c3idf50 + friendly_name: $component_name + +esp32: + board: lolin_c3_mini + framework: + type: esp-idf + version: 5.0.2 + platform_version: 6.3.2 + +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/build_components_base.esp32-idf-50.yaml b/tests/test_build_components/build_components_base.esp32-idf-50.yaml new file mode 100644 index 0000000000..c9f2c1e943 --- /dev/null +++ b/tests/test_build_components/build_components_base.esp32-idf-50.yaml @@ -0,0 +1,19 @@ +esphome: + name: componenttestesp32idf50 + friendly_name: $component_name + +esp32: + board: nodemcu-32s + framework: + type: esp-idf + version: 5.0.2 + platform_version: 6.3.2 + +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/build_components_base.esp32-s2-idf-50.yaml b/tests/test_build_components/build_components_base.esp32-s2-idf-50.yaml new file mode 100644 index 0000000000..351f5fb019 --- /dev/null +++ b/tests/test_build_components/build_components_base.esp32-s2-idf-50.yaml @@ -0,0 +1,20 @@ +esphome: + name: componenttestesp32s2idf50 + friendly_name: $component_name + +esp32: + board: esp32-s2-saola-1 + variant: ESP32S2 + framework: + type: esp-idf + version: 5.0.2 + platform_version: 6.3.2 + +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/build_components_base.esp32-s2-idf.yaml b/tests/test_build_components/build_components_base.esp32-s2-idf.yaml index 62f0f4f7bc..484906e8df 100644 --- a/tests/test_build_components/build_components_base.esp32-s2-idf.yaml +++ b/tests/test_build_components/build_components_base.esp32-s2-idf.yaml @@ -1,5 +1,5 @@ esphome: - name: componenttestesp32s2ard + name: componenttestesp32s2idf friendly_name: $component_name esp32: diff --git a/tests/test_build_components/build_components_base.esp32-s3-idf-50.yaml b/tests/test_build_components/build_components_base.esp32-s3-idf-50.yaml new file mode 100644 index 0000000000..c05378903f --- /dev/null +++ b/tests/test_build_components/build_components_base.esp32-s3-idf-50.yaml @@ -0,0 +1,20 @@ +esphome: + name: componenttestesp32s3idf50 + friendly_name: $component_name + +esp32: + board: esp32s3box + variant: ESP32S3 + framework: + type: esp-idf + version: 5.0.2 + platform_version: 6.3.2 + +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/build_components_base.esp32-s3-idf.yaml b/tests/test_build_components/build_components_base.esp32-s3-idf.yaml index b1d08fcdf8..ee209000e9 100644 --- a/tests/test_build_components/build_components_base.esp32-s3-idf.yaml +++ b/tests/test_build_components/build_components_base.esp32-s3-idf.yaml @@ -1,5 +1,5 @@ esphome: - name: componenttestesp32s3ard + name: componenttestesp32s3idf friendly_name: $component_name esp32: diff --git a/tests/test_build_components/build_components_base.esp8266.yaml b/tests/test_build_components/build_components_base.esp8266-ard.yaml similarity index 87% rename from tests/test_build_components/build_components_base.esp8266.yaml rename to tests/test_build_components/build_components_base.esp8266-ard.yaml index ecf9acd2ba..e4d6607c86 100644 --- a/tests/test_build_components/build_components_base.esp8266.yaml +++ b/tests/test_build_components/build_components_base.esp8266-ard.yaml @@ -1,5 +1,5 @@ esphome: - name: componenttestesp8266 + name: componenttestesp8266ard friendly_name: $component_name esp8266: diff --git a/tests/test_build_components/build_components_base.rp2040.yaml b/tests/test_build_components/build_components_base.rp2040-ard.yaml similarity index 92% rename from tests/test_build_components/build_components_base.rp2040.yaml rename to tests/test_build_components/build_components_base.rp2040-ard.yaml index 335642374b..6c6a27e0a7 100644 --- a/tests/test_build_components/build_components_base.rp2040.yaml +++ b/tests/test_build_components/build_components_base.rp2040-ard.yaml @@ -1,5 +1,5 @@ esphome: - name: componenttestrp2040 + name: componenttestrp2040ard friendly_name: $component_name rp2040: From a78b2d0128bd3a3c54fdb092d8180497cd03a8a8 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 18 Jun 2024 13:07:43 +1200 Subject: [PATCH 1614/2101] [wifi] Fix some access point bugs related to esp-idf 4.4.7 (#6928) * Set dhcp server range to only 10 IPs * Change log level to errors to make it clearer * We want to stop the dhcp server, not client --- .../wifi/wifi_component_esp32_arduino.cpp | 12 ++++++------ .../components/wifi/wifi_component_esp8266.cpp | 14 +++++++------- .../components/wifi/wifi_component_esp_idf.cpp | 16 ++++++++-------- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/esphome/components/wifi/wifi_component_esp32_arduino.cpp b/esphome/components/wifi/wifi_component_esp32_arduino.cpp index ef7a624cd5..fc954a2333 100644 --- a/esphome/components/wifi/wifi_component_esp32_arduino.cpp +++ b/esphome/components/wifi/wifi_component_esp32_arduino.cpp @@ -694,15 +694,15 @@ bool WiFiComponent::wifi_ap_ip_config_(optional manual_ip) { info.netmask = network::IPAddress(255, 255, 255, 0); } - err = esp_netif_dhcpc_stop(s_ap_netif); + err = esp_netif_dhcps_stop(s_ap_netif); if (err != ESP_OK && err != ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED) { - ESP_LOGV(TAG, "esp_netif_dhcpc_stop failed: %s", esp_err_to_name(err)); + ESP_LOGE(TAG, "esp_netif_dhcps_stop failed: %s", esp_err_to_name(err)); return false; } err = esp_netif_set_ip_info(s_ap_netif, &info); if (err != ESP_OK) { - ESP_LOGV(TAG, "esp_netif_set_ip_info failed! %d", err); + ESP_LOGE(TAG, "esp_netif_set_ip_info failed! %d", err); return false; } @@ -712,20 +712,20 @@ bool WiFiComponent::wifi_ap_ip_config_(optional manual_ip) { start_address += 99; lease.start_ip = start_address; ESP_LOGV(TAG, "DHCP server IP lease start: %s", start_address.str().c_str()); - start_address += 100; + start_address += 10; lease.end_ip = start_address; ESP_LOGV(TAG, "DHCP server IP lease end: %s", start_address.str().c_str()); err = esp_netif_dhcps_option(s_ap_netif, ESP_NETIF_OP_SET, ESP_NETIF_REQUESTED_IP_ADDRESS, &lease, sizeof(lease)); if (err != ESP_OK) { - ESP_LOGV(TAG, "esp_netif_dhcps_option failed! %d", err); + ESP_LOGE(TAG, "esp_netif_dhcps_option failed! %d", err); return false; } err = esp_netif_dhcps_start(s_ap_netif); if (err != ESP_OK) { - ESP_LOGV(TAG, "esp_netif_dhcps_start failed! %d", err); + ESP_LOGE(TAG, "esp_netif_dhcps_start failed! %d", err); return false; } diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index 838250972b..997457e2d2 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -716,12 +716,12 @@ bool WiFiComponent::wifi_ap_ip_config_(optional manual_ip) { if (wifi_softap_dhcps_status() == DHCP_STARTED) { if (!wifi_softap_dhcps_stop()) { - ESP_LOGV(TAG, "Stopping DHCP server failed!"); + ESP_LOGW(TAG, "Stopping DHCP server failed!"); } } if (!wifi_set_ip_info(SOFTAP_IF, &info)) { - ESP_LOGV(TAG, "Setting SoftAP info failed!"); + ESP_LOGE(TAG, "Setting SoftAP info failed!"); return false; } @@ -735,17 +735,17 @@ bool WiFiComponent::wifi_ap_ip_config_(optional manual_ip) { start_address += 99; lease.start_ip = start_address; ESP_LOGV(TAG, "DHCP server IP lease start: %s", start_address.str().c_str()); - start_address += 100; + start_address += 10; lease.end_ip = start_address; ESP_LOGV(TAG, "DHCP server IP lease end: %s", start_address.str().c_str()); if (!wifi_softap_set_dhcps_lease(&lease)) { - ESP_LOGV(TAG, "Setting SoftAP DHCP lease failed!"); + ESP_LOGE(TAG, "Setting SoftAP DHCP lease failed!"); return false; } // lease time 1440 minutes (=24 hours) if (!wifi_softap_set_dhcps_lease_time(1440)) { - ESP_LOGV(TAG, "Setting SoftAP DHCP lease time failed!"); + ESP_LOGE(TAG, "Setting SoftAP DHCP lease time failed!"); return false; } @@ -755,13 +755,13 @@ bool WiFiComponent::wifi_ap_ip_config_(optional manual_ip) { uint8_t mode = 1; // bit0, 1 enables router information from ESP8266 SoftAP DHCP server. if (!wifi_softap_set_dhcps_offer_option(OFFER_ROUTER, &mode)) { - ESP_LOGV(TAG, "wifi_softap_set_dhcps_offer_option failed!"); + ESP_LOGE(TAG, "wifi_softap_set_dhcps_offer_option failed!"); return false; } #endif if (!wifi_softap_dhcps_start()) { - ESP_LOGV(TAG, "Starting SoftAP DHCPS failed!"); + ESP_LOGE(TAG, "Starting SoftAP DHCPS failed!"); return false; } diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index bc575e6a2d..c21486fee4 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -823,15 +823,15 @@ bool WiFiComponent::wifi_ap_ip_config_(optional manual_ip) { info.netmask = network::IPAddress(255, 255, 255, 0); } - err = esp_netif_dhcpc_stop(s_ap_netif); + err = esp_netif_dhcps_stop(s_ap_netif); if (err != ESP_OK && err != ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED) { - ESP_LOGV(TAG, "esp_netif_dhcpc_stop failed: %s", esp_err_to_name(err)); + ESP_LOGE(TAG, "esp_netif_dhcps_stop failed: %s", esp_err_to_name(err)); return false; } err = esp_netif_set_ip_info(s_ap_netif, &info); if (err != ESP_OK) { - ESP_LOGV(TAG, "esp_netif_set_ip_info failed! %d", err); + ESP_LOGE(TAG, "esp_netif_set_ip_info failed! %d", err); return false; } @@ -841,20 +841,20 @@ bool WiFiComponent::wifi_ap_ip_config_(optional manual_ip) { start_address += 99; lease.start_ip = start_address; ESP_LOGV(TAG, "DHCP server IP lease start: %s", start_address.str().c_str()); - start_address += 100; + start_address += 10; lease.end_ip = start_address; ESP_LOGV(TAG, "DHCP server IP lease end: %s", start_address.str().c_str()); err = esp_netif_dhcps_option(s_ap_netif, ESP_NETIF_OP_SET, ESP_NETIF_REQUESTED_IP_ADDRESS, &lease, sizeof(lease)); if (err != ESP_OK) { - ESP_LOGV(TAG, "esp_netif_dhcps_option failed! %d", err); + ESP_LOGE(TAG, "esp_netif_dhcps_option failed! %d", err); return false; } err = esp_netif_dhcps_start(s_ap_netif); if (err != ESP_OK) { - ESP_LOGV(TAG, "esp_netif_dhcps_start failed! %d", err); + ESP_LOGE(TAG, "esp_netif_dhcps_start failed! %d", err); return false; } @@ -887,12 +887,12 @@ bool WiFiComponent::wifi_start_ap_(const WiFiAP &ap) { esp_err_t err = esp_wifi_set_config(WIFI_IF_AP, &conf); if (err != ESP_OK) { - ESP_LOGV(TAG, "esp_wifi_set_config failed! %d", err); + ESP_LOGE(TAG, "esp_wifi_set_config failed! %d", err); return false; } if (!this->wifi_ap_ip_config_(ap.get_manual_ip())) { - ESP_LOGV(TAG, "wifi_ap_ip_config_ failed!"); + ESP_LOGE(TAG, "wifi_ap_ip_config_ failed!"); return false; } From 4c313bc1982c2eabc3ccfe54b84008323c8fc5ad Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 18 Jun 2024 14:12:55 +1200 Subject: [PATCH 1615/2101] Rename legacy/modern to ota/factory (#6922) * Rename legacy/modern to ota/factory * Add modern/legacy in brackets --- esphome/components/esp32/__init__.py | 14 +++++------ esphome/components/esp32/post_build.py.script | 13 ++++++++++- .../components/esp8266/post_build.py.script | 10 +++++++- esphome/components/rp2040/__init__.py | 18 +++++++++++++-- .../components/rp2040/post_build.py.script | 23 +++++++++++++++++++ 5 files changed, 67 insertions(+), 11 deletions(-) create mode 100644 esphome/components/rp2040/post_build.py.script diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 8f46567266..1effea708f 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -96,16 +96,16 @@ def get_board(core_obj=None): def get_download_types(storage_json): return [ { - "title": "Modern format", + "title": "Factory format (Previously Modern)", "description": "For use with ESPHome Web and other tools.", - "file": "firmware-factory.bin", - "download": f"{storage_json.name}-factory.bin", + "file": "firmware.factory.bin", + "download": f"{storage_json.name}.factory.bin", }, { - "title": "Legacy format", - "description": "For use with ESPHome Flasher.", - "file": "firmware.bin", - "download": f"{storage_json.name}.bin", + "title": "OTA format (Previously Legacy)", + "description": "For OTA updating a device.", + "file": "firmware.ota.bin", + "download": f"{storage_json.name}.ota.bin", }, ] diff --git a/esphome/components/esp32/post_build.py.script b/esphome/components/esp32/post_build.py.script index c941bdb386..c181cf30b1 100644 --- a/esphome/components/esp32/post_build.py.script +++ b/esphome/components/esp32/post_build.py.script @@ -17,17 +17,19 @@ from SCons.Script import ARGUMENTS # Copy over the default sdkconfig. from os import path + if path.exists("./sdkconfig.defaults"): os.makedirs(".temp", exist_ok=True) shutil.copy("./sdkconfig.defaults", "./.temp/sdkconfig-esp32-idf") + def esp32_create_combined_bin(source, target, env): verbose = bool(int(ARGUMENTS.get("PIOVERBOSE", "0"))) if verbose: print("Generating combined binary for serial flashing") app_offset = 0x10000 - new_file_name = env.subst("$BUILD_DIR/${PROGNAME}-factory.bin") + new_file_name = env.subst("$BUILD_DIR/${PROGNAME}.factory.bin") sections = env.subst(env.get("FLASH_EXTRA_IMAGES")) firmware_name = env.subst("$BUILD_DIR/${PROGNAME}.bin") chip = env.get("BOARD_MCU") @@ -62,5 +64,14 @@ def esp32_create_combined_bin(source, target, env): else: subprocess.run(["esptool.py", *cmd]) + +def esp32_copy_ota_bin(source, target, env): + firmware_name = env.subst("$BUILD_DIR/${PROGNAME}.bin") + new_file_name = env.subst("$BUILD_DIR/${PROGNAME}.ota.bin") + + shutil.copyfile(firmware_name, new_file_name) + + # pylint: disable=E0602 env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", esp32_create_combined_bin) # noqa +env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", esp32_copy_ota_bin) # noqa diff --git a/esphome/components/esp8266/post_build.py.script b/esphome/components/esp8266/post_build.py.script index 4dab1cbd27..0a854d7599 100644 --- a/esphome/components/esp8266/post_build.py.script +++ b/esphome/components/esp8266/post_build.py.script @@ -6,10 +6,18 @@ Import("env") # noqa def esp8266_copy_factory_bin(source, target, env): firmware_name = env.subst("$BUILD_DIR/${PROGNAME}.bin") - new_file_name = env.subst("$BUILD_DIR/${PROGNAME}-factory.bin") + new_file_name = env.subst("$BUILD_DIR/${PROGNAME}.factory.bin") + + shutil.copyfile(firmware_name, new_file_name) + + +def esp8266_copy_ota_bin(source, target, env): + firmware_name = env.subst("$BUILD_DIR/${PROGNAME}.bin") + new_file_name = env.subst("$BUILD_DIR/${PROGNAME}.ota.bin") shutil.copyfile(firmware_name, new_file_name) # pylint: disable=E0602 env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", esp8266_copy_factory_bin) # noqa +env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", esp8266_copy_ota_bin) # noqa diff --git a/esphome/components/rp2040/__init__.py b/esphome/components/rp2040/__init__.py index ace455add7..f5c3b8bda2 100644 --- a/esphome/components/rp2040/__init__.py +++ b/esphome/components/rp2040/__init__.py @@ -47,10 +47,16 @@ def set_core_data(config): def get_download_types(storage_json): return [ { - "title": "UF2 format", + "title": "UF2 factory format", "description": "For copying to RP2040 over USB.", "file": "firmware.uf2", - "download": f"{storage_json.name}.uf2", + "download": f"{storage_json.name}.factory.uf2", + }, + { + "title": "OTA format", + "description": "For OTA updating a device.", + "file": "firmware.ota.bin", + "download": f"{storage_json.name}.ota.bin", }, ] @@ -160,6 +166,8 @@ async def to_code(config): cg.add_define("ESPHOME_BOARD", config[CONF_BOARD]) cg.add_define("ESPHOME_VARIANT", "RP2040") + cg.add_platformio_option("extra_scripts", ["post:post_build.py"]) + conf = config[CONF_FRAMEWORK] cg.add_platformio_option("framework", "arduino") cg.add_build_flag("-DUSE_ARDUINO") @@ -225,4 +233,10 @@ def generate_pio_files() -> bool: # Called by writer.py def copy_files() -> bool: + dir = os.path.dirname(__file__) + post_build_file = os.path.join(dir, "post_build.py.script") + copy_file_if_changed( + post_build_file, + CORE.relative_build_path("post_build.py"), + ) return generate_pio_files() diff --git a/esphome/components/rp2040/post_build.py.script b/esphome/components/rp2040/post_build.py.script new file mode 100644 index 0000000000..7dcd7e52a6 --- /dev/null +++ b/esphome/components/rp2040/post_build.py.script @@ -0,0 +1,23 @@ +import shutil + +# pylint: disable=E0602 +Import("env") # noqa + + +def rp2040_copy_factory_uf2(source, target, env): + firmware_name = env.subst("$BUILD_DIR/${PROGNAME}.uf2") + new_file_name = env.subst("$BUILD_DIR/${PROGNAME}.factory.uf2") + + shutil.copyfile(firmware_name, new_file_name) + + +def rp2040_copy_ota_bin(source, target, env): + firmware_name = env.subst("$BUILD_DIR/${PROGNAME}.bin") + new_file_name = env.subst("$BUILD_DIR/${PROGNAME}.ota.bin") + + shutil.copyfile(firmware_name, new_file_name) + + +# pylint: disable=E0602 +env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", rp2040_copy_factory_uf2) # noqa +env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", rp2040_copy_ota_bin) # noqa From 7d642147c154ad4c825f23c726ac73bcf4210f8a Mon Sep 17 00:00:00 2001 From: Faidon Liambotis Date: Tue, 18 Jun 2024 05:22:50 +0300 Subject: [PATCH 1616/2101] uart: allow setting the UART id in final_validate_device_schema (#6923) --- esphome/components/uart/__init__.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/esphome/components/uart/__init__.py b/esphome/components/uart/__init__.py index 088227afe5..b036288078 100644 --- a/esphome/components/uart/__init__.py +++ b/esphome/components/uart/__init__.py @@ -258,6 +258,7 @@ KEY_UART_DEVICES = "uart_devices" def final_validate_device_schema( name: str, *, + uart_bus: str = CONF_UART_ID, baud_rate: Optional[int] = None, require_tx: bool = False, require_rx: bool = False, @@ -268,7 +269,7 @@ def final_validate_device_schema( def validate_baud_rate(value): if value != baud_rate: raise cv.Invalid( - f"Component {name} requires baud rate {baud_rate} for the uart bus" + f"Component {name} requires baud rate {baud_rate} for the uart referenced by {uart_bus}" ) return value @@ -287,21 +288,21 @@ def final_validate_device_schema( def validate_data_bits(value): if value != data_bits: raise cv.Invalid( - f"Component {name} requires {data_bits} data bits for the uart bus" + f"Component {name} requires {data_bits} data bits for the uart referenced by {uart_bus}" ) return value def validate_parity(value): if value != parity: raise cv.Invalid( - f"Component {name} requires parity {parity} for the uart bus" + f"Component {name} requires parity {parity} for the uart referenced by {uart_bus}" ) return value def validate_stop_bits(value): if value != stop_bits: raise cv.Invalid( - f"Component {name} requires {stop_bits} stop bits for the uart bus" + f"Component {name} requires {stop_bits} stop bits for the uart referenced by {uart_bus}" ) return value @@ -316,14 +317,14 @@ def final_validate_device_schema( hub_schema[ cv.Required( CONF_TX_PIN, - msg=f"Component {name} requires this uart bus to declare a tx_pin", + msg=f"Component {name} requires uart referenced by {uart_bus} to declare a tx_pin", ) ] = validate_pin(CONF_TX_PIN, device) if require_rx and uart_id_type_str in NATIVE_UART_CLASSES: hub_schema[ cv.Required( CONF_RX_PIN, - msg=f"Component {name} requires this uart bus to declare a rx_pin", + msg=f"Component {name} requires uart referenced by {uart_bus} to declare a rx_pin", ) ] = validate_pin(CONF_RX_PIN, device) if baud_rate is not None: @@ -337,7 +338,7 @@ def final_validate_device_schema( return cv.Schema(hub_schema, extra=cv.ALLOW_EXTRA)(hub_config) return cv.Schema( - {cv.Required(CONF_UART_ID): fv.id_declaration_match_schema(validate_hub)}, + {cv.Required(uart_bus): fv.id_declaration_match_schema(validate_hub)}, extra=cv.ALLOW_EXTRA, ) From 5dec62bf1e464baca86d9e8cda94ca4ada2e0913 Mon Sep 17 00:00:00 2001 From: Giel van Schijndel Date: Mon, 17 Jun 2024 07:48:56 +0200 Subject: [PATCH 1617/2101] fix(dallas): make recovery time for 1-bit equal to that of 0-bit (#6763) --- esphome/components/gpio/one_wire/gpio_one_wire.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/gpio/one_wire/gpio_one_wire.cpp b/esphome/components/gpio/one_wire/gpio_one_wire.cpp index f47e8d58e3..34c2cf3c29 100644 --- a/esphome/components/gpio/one_wire/gpio_one_wire.cpp +++ b/esphome/components/gpio/one_wire/gpio_one_wire.cpp @@ -60,7 +60,7 @@ void HOT IRAM_ATTR GPIOOneWireBus::write_bit_(bool bit) { // recovery time: t_rec: min=1µs // ds18b20 appears to read the bus after roughly 14µs uint32_t delay0 = bit ? 6 : 60; - uint32_t delay1 = bit ? 54 : 5; + uint32_t delay1 = bit ? 59 : 5; // delay A/C delayMicroseconds(delay0); From d27e7b3b70310a7970ee44213bb3680a554bd5b1 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 18 Jun 2024 13:07:43 +1200 Subject: [PATCH 1618/2101] [wifi] Fix some access point bugs related to esp-idf 4.4.7 (#6928) * Set dhcp server range to only 10 IPs * Change log level to errors to make it clearer * We want to stop the dhcp server, not client --- .../wifi/wifi_component_esp32_arduino.cpp | 12 ++++++------ .../components/wifi/wifi_component_esp8266.cpp | 14 +++++++------- .../components/wifi/wifi_component_esp_idf.cpp | 16 ++++++++-------- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/esphome/components/wifi/wifi_component_esp32_arduino.cpp b/esphome/components/wifi/wifi_component_esp32_arduino.cpp index ef7a624cd5..fc954a2333 100644 --- a/esphome/components/wifi/wifi_component_esp32_arduino.cpp +++ b/esphome/components/wifi/wifi_component_esp32_arduino.cpp @@ -694,15 +694,15 @@ bool WiFiComponent::wifi_ap_ip_config_(optional manual_ip) { info.netmask = network::IPAddress(255, 255, 255, 0); } - err = esp_netif_dhcpc_stop(s_ap_netif); + err = esp_netif_dhcps_stop(s_ap_netif); if (err != ESP_OK && err != ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED) { - ESP_LOGV(TAG, "esp_netif_dhcpc_stop failed: %s", esp_err_to_name(err)); + ESP_LOGE(TAG, "esp_netif_dhcps_stop failed: %s", esp_err_to_name(err)); return false; } err = esp_netif_set_ip_info(s_ap_netif, &info); if (err != ESP_OK) { - ESP_LOGV(TAG, "esp_netif_set_ip_info failed! %d", err); + ESP_LOGE(TAG, "esp_netif_set_ip_info failed! %d", err); return false; } @@ -712,20 +712,20 @@ bool WiFiComponent::wifi_ap_ip_config_(optional manual_ip) { start_address += 99; lease.start_ip = start_address; ESP_LOGV(TAG, "DHCP server IP lease start: %s", start_address.str().c_str()); - start_address += 100; + start_address += 10; lease.end_ip = start_address; ESP_LOGV(TAG, "DHCP server IP lease end: %s", start_address.str().c_str()); err = esp_netif_dhcps_option(s_ap_netif, ESP_NETIF_OP_SET, ESP_NETIF_REQUESTED_IP_ADDRESS, &lease, sizeof(lease)); if (err != ESP_OK) { - ESP_LOGV(TAG, "esp_netif_dhcps_option failed! %d", err); + ESP_LOGE(TAG, "esp_netif_dhcps_option failed! %d", err); return false; } err = esp_netif_dhcps_start(s_ap_netif); if (err != ESP_OK) { - ESP_LOGV(TAG, "esp_netif_dhcps_start failed! %d", err); + ESP_LOGE(TAG, "esp_netif_dhcps_start failed! %d", err); return false; } diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index 838250972b..997457e2d2 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -716,12 +716,12 @@ bool WiFiComponent::wifi_ap_ip_config_(optional manual_ip) { if (wifi_softap_dhcps_status() == DHCP_STARTED) { if (!wifi_softap_dhcps_stop()) { - ESP_LOGV(TAG, "Stopping DHCP server failed!"); + ESP_LOGW(TAG, "Stopping DHCP server failed!"); } } if (!wifi_set_ip_info(SOFTAP_IF, &info)) { - ESP_LOGV(TAG, "Setting SoftAP info failed!"); + ESP_LOGE(TAG, "Setting SoftAP info failed!"); return false; } @@ -735,17 +735,17 @@ bool WiFiComponent::wifi_ap_ip_config_(optional manual_ip) { start_address += 99; lease.start_ip = start_address; ESP_LOGV(TAG, "DHCP server IP lease start: %s", start_address.str().c_str()); - start_address += 100; + start_address += 10; lease.end_ip = start_address; ESP_LOGV(TAG, "DHCP server IP lease end: %s", start_address.str().c_str()); if (!wifi_softap_set_dhcps_lease(&lease)) { - ESP_LOGV(TAG, "Setting SoftAP DHCP lease failed!"); + ESP_LOGE(TAG, "Setting SoftAP DHCP lease failed!"); return false; } // lease time 1440 minutes (=24 hours) if (!wifi_softap_set_dhcps_lease_time(1440)) { - ESP_LOGV(TAG, "Setting SoftAP DHCP lease time failed!"); + ESP_LOGE(TAG, "Setting SoftAP DHCP lease time failed!"); return false; } @@ -755,13 +755,13 @@ bool WiFiComponent::wifi_ap_ip_config_(optional manual_ip) { uint8_t mode = 1; // bit0, 1 enables router information from ESP8266 SoftAP DHCP server. if (!wifi_softap_set_dhcps_offer_option(OFFER_ROUTER, &mode)) { - ESP_LOGV(TAG, "wifi_softap_set_dhcps_offer_option failed!"); + ESP_LOGE(TAG, "wifi_softap_set_dhcps_offer_option failed!"); return false; } #endif if (!wifi_softap_dhcps_start()) { - ESP_LOGV(TAG, "Starting SoftAP DHCPS failed!"); + ESP_LOGE(TAG, "Starting SoftAP DHCPS failed!"); return false; } diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index bc575e6a2d..c21486fee4 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -823,15 +823,15 @@ bool WiFiComponent::wifi_ap_ip_config_(optional manual_ip) { info.netmask = network::IPAddress(255, 255, 255, 0); } - err = esp_netif_dhcpc_stop(s_ap_netif); + err = esp_netif_dhcps_stop(s_ap_netif); if (err != ESP_OK && err != ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED) { - ESP_LOGV(TAG, "esp_netif_dhcpc_stop failed: %s", esp_err_to_name(err)); + ESP_LOGE(TAG, "esp_netif_dhcps_stop failed: %s", esp_err_to_name(err)); return false; } err = esp_netif_set_ip_info(s_ap_netif, &info); if (err != ESP_OK) { - ESP_LOGV(TAG, "esp_netif_set_ip_info failed! %d", err); + ESP_LOGE(TAG, "esp_netif_set_ip_info failed! %d", err); return false; } @@ -841,20 +841,20 @@ bool WiFiComponent::wifi_ap_ip_config_(optional manual_ip) { start_address += 99; lease.start_ip = start_address; ESP_LOGV(TAG, "DHCP server IP lease start: %s", start_address.str().c_str()); - start_address += 100; + start_address += 10; lease.end_ip = start_address; ESP_LOGV(TAG, "DHCP server IP lease end: %s", start_address.str().c_str()); err = esp_netif_dhcps_option(s_ap_netif, ESP_NETIF_OP_SET, ESP_NETIF_REQUESTED_IP_ADDRESS, &lease, sizeof(lease)); if (err != ESP_OK) { - ESP_LOGV(TAG, "esp_netif_dhcps_option failed! %d", err); + ESP_LOGE(TAG, "esp_netif_dhcps_option failed! %d", err); return false; } err = esp_netif_dhcps_start(s_ap_netif); if (err != ESP_OK) { - ESP_LOGV(TAG, "esp_netif_dhcps_start failed! %d", err); + ESP_LOGE(TAG, "esp_netif_dhcps_start failed! %d", err); return false; } @@ -887,12 +887,12 @@ bool WiFiComponent::wifi_start_ap_(const WiFiAP &ap) { esp_err_t err = esp_wifi_set_config(WIFI_IF_AP, &conf); if (err != ESP_OK) { - ESP_LOGV(TAG, "esp_wifi_set_config failed! %d", err); + ESP_LOGE(TAG, "esp_wifi_set_config failed! %d", err); return false; } if (!this->wifi_ap_ip_config_(ap.get_manual_ip())) { - ESP_LOGV(TAG, "wifi_ap_ip_config_ failed!"); + ESP_LOGE(TAG, "wifi_ap_ip_config_ failed!"); return false; } From 43b5c2deb747114eae8367f7fbfba34296c24146 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 18 Jun 2024 14:12:55 +1200 Subject: [PATCH 1619/2101] Rename legacy/modern to ota/factory (#6922) * Rename legacy/modern to ota/factory * Add modern/legacy in brackets --- esphome/components/esp32/__init__.py | 14 +++++------ esphome/components/esp32/post_build.py.script | 13 ++++++++++- .../components/esp8266/post_build.py.script | 10 +++++++- esphome/components/rp2040/__init__.py | 18 +++++++++++++-- .../components/rp2040/post_build.py.script | 23 +++++++++++++++++++ 5 files changed, 67 insertions(+), 11 deletions(-) create mode 100644 esphome/components/rp2040/post_build.py.script diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 8f46567266..1effea708f 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -96,16 +96,16 @@ def get_board(core_obj=None): def get_download_types(storage_json): return [ { - "title": "Modern format", + "title": "Factory format (Previously Modern)", "description": "For use with ESPHome Web and other tools.", - "file": "firmware-factory.bin", - "download": f"{storage_json.name}-factory.bin", + "file": "firmware.factory.bin", + "download": f"{storage_json.name}.factory.bin", }, { - "title": "Legacy format", - "description": "For use with ESPHome Flasher.", - "file": "firmware.bin", - "download": f"{storage_json.name}.bin", + "title": "OTA format (Previously Legacy)", + "description": "For OTA updating a device.", + "file": "firmware.ota.bin", + "download": f"{storage_json.name}.ota.bin", }, ] diff --git a/esphome/components/esp32/post_build.py.script b/esphome/components/esp32/post_build.py.script index c941bdb386..c181cf30b1 100644 --- a/esphome/components/esp32/post_build.py.script +++ b/esphome/components/esp32/post_build.py.script @@ -17,17 +17,19 @@ from SCons.Script import ARGUMENTS # Copy over the default sdkconfig. from os import path + if path.exists("./sdkconfig.defaults"): os.makedirs(".temp", exist_ok=True) shutil.copy("./sdkconfig.defaults", "./.temp/sdkconfig-esp32-idf") + def esp32_create_combined_bin(source, target, env): verbose = bool(int(ARGUMENTS.get("PIOVERBOSE", "0"))) if verbose: print("Generating combined binary for serial flashing") app_offset = 0x10000 - new_file_name = env.subst("$BUILD_DIR/${PROGNAME}-factory.bin") + new_file_name = env.subst("$BUILD_DIR/${PROGNAME}.factory.bin") sections = env.subst(env.get("FLASH_EXTRA_IMAGES")) firmware_name = env.subst("$BUILD_DIR/${PROGNAME}.bin") chip = env.get("BOARD_MCU") @@ -62,5 +64,14 @@ def esp32_create_combined_bin(source, target, env): else: subprocess.run(["esptool.py", *cmd]) + +def esp32_copy_ota_bin(source, target, env): + firmware_name = env.subst("$BUILD_DIR/${PROGNAME}.bin") + new_file_name = env.subst("$BUILD_DIR/${PROGNAME}.ota.bin") + + shutil.copyfile(firmware_name, new_file_name) + + # pylint: disable=E0602 env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", esp32_create_combined_bin) # noqa +env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", esp32_copy_ota_bin) # noqa diff --git a/esphome/components/esp8266/post_build.py.script b/esphome/components/esp8266/post_build.py.script index 4dab1cbd27..0a854d7599 100644 --- a/esphome/components/esp8266/post_build.py.script +++ b/esphome/components/esp8266/post_build.py.script @@ -6,10 +6,18 @@ Import("env") # noqa def esp8266_copy_factory_bin(source, target, env): firmware_name = env.subst("$BUILD_DIR/${PROGNAME}.bin") - new_file_name = env.subst("$BUILD_DIR/${PROGNAME}-factory.bin") + new_file_name = env.subst("$BUILD_DIR/${PROGNAME}.factory.bin") + + shutil.copyfile(firmware_name, new_file_name) + + +def esp8266_copy_ota_bin(source, target, env): + firmware_name = env.subst("$BUILD_DIR/${PROGNAME}.bin") + new_file_name = env.subst("$BUILD_DIR/${PROGNAME}.ota.bin") shutil.copyfile(firmware_name, new_file_name) # pylint: disable=E0602 env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", esp8266_copy_factory_bin) # noqa +env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", esp8266_copy_ota_bin) # noqa diff --git a/esphome/components/rp2040/__init__.py b/esphome/components/rp2040/__init__.py index ace455add7..f5c3b8bda2 100644 --- a/esphome/components/rp2040/__init__.py +++ b/esphome/components/rp2040/__init__.py @@ -47,10 +47,16 @@ def set_core_data(config): def get_download_types(storage_json): return [ { - "title": "UF2 format", + "title": "UF2 factory format", "description": "For copying to RP2040 over USB.", "file": "firmware.uf2", - "download": f"{storage_json.name}.uf2", + "download": f"{storage_json.name}.factory.uf2", + }, + { + "title": "OTA format", + "description": "For OTA updating a device.", + "file": "firmware.ota.bin", + "download": f"{storage_json.name}.ota.bin", }, ] @@ -160,6 +166,8 @@ async def to_code(config): cg.add_define("ESPHOME_BOARD", config[CONF_BOARD]) cg.add_define("ESPHOME_VARIANT", "RP2040") + cg.add_platformio_option("extra_scripts", ["post:post_build.py"]) + conf = config[CONF_FRAMEWORK] cg.add_platformio_option("framework", "arduino") cg.add_build_flag("-DUSE_ARDUINO") @@ -225,4 +233,10 @@ def generate_pio_files() -> bool: # Called by writer.py def copy_files() -> bool: + dir = os.path.dirname(__file__) + post_build_file = os.path.join(dir, "post_build.py.script") + copy_file_if_changed( + post_build_file, + CORE.relative_build_path("post_build.py"), + ) return generate_pio_files() diff --git a/esphome/components/rp2040/post_build.py.script b/esphome/components/rp2040/post_build.py.script new file mode 100644 index 0000000000..7dcd7e52a6 --- /dev/null +++ b/esphome/components/rp2040/post_build.py.script @@ -0,0 +1,23 @@ +import shutil + +# pylint: disable=E0602 +Import("env") # noqa + + +def rp2040_copy_factory_uf2(source, target, env): + firmware_name = env.subst("$BUILD_DIR/${PROGNAME}.uf2") + new_file_name = env.subst("$BUILD_DIR/${PROGNAME}.factory.uf2") + + shutil.copyfile(firmware_name, new_file_name) + + +def rp2040_copy_ota_bin(source, target, env): + firmware_name = env.subst("$BUILD_DIR/${PROGNAME}.bin") + new_file_name = env.subst("$BUILD_DIR/${PROGNAME}.ota.bin") + + shutil.copyfile(firmware_name, new_file_name) + + +# pylint: disable=E0602 +env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", rp2040_copy_factory_uf2) # noqa +env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", rp2040_copy_ota_bin) # noqa From ff07637dfdfb5364076966fba12dc1de949e8748 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 18 Jun 2024 14:26:24 +1200 Subject: [PATCH 1620/2101] Bump version to 2024.6.0b4 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index a0fe325282..eea437bcdc 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.6.0b3" +__version__ = "2024.6.0b4" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 65a79acfb972876bfd54d777393bd553cdfde8e1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Jun 2024 16:44:20 +1200 Subject: [PATCH 1621/2101] Bump pypa/gh-action-pypi-publish from 1.8.14 to 1.9.0 (#6926) 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 9c07335104..a1942e8cac 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -65,7 +65,7 @@ jobs: pip3 install build python3 -m build - name: Publish - uses: pypa/gh-action-pypi-publish@v1.8.14 + uses: pypa/gh-action-pypi-publish@v1.9.0 deploy-docker: name: Build ESPHome ${{ matrix.platform }} From c18056bdda129136f05b52388e738ceec8242e62 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Jun 2024 19:16:10 +1200 Subject: [PATCH 1622/2101] Bump docker/build-push-action from 5.4.0 to 6.0.0 in /.github/actions/build-image (#6927) 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 d792ab5f4c..c685e80bec 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -46,7 +46,7 @@ runs: - name: Build and push to ghcr by digest id: build-ghcr - uses: docker/build-push-action@v5.4.0 + uses: docker/build-push-action@v6.0.0 with: context: . file: ./docker/Dockerfile @@ -69,7 +69,7 @@ runs: - name: Build and push to dockerhub by digest id: build-dockerhub - uses: docker/build-push-action@v5.4.0 + uses: docker/build-push-action@v6.0.0 with: context: . file: ./docker/Dockerfile From 65b05af0143a11a5d0e290f7025a275808cbd143 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Jun 2024 07:38:31 +1200 Subject: [PATCH 1623/2101] Bump peter-evans/create-pull-request from 6.0.5 to 6.1.0 (#6935) 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 45f6b27127..89a3627c64 100644 --- a/.github/workflows/sync-device-classes.yml +++ b/.github/workflows/sync-device-classes.yml @@ -36,7 +36,7 @@ jobs: python ./script/sync-device_class.py - name: Commit changes - uses: peter-evans/create-pull-request@v6.0.5 + uses: peter-evans/create-pull-request@v6.1.0 with: commit-message: "Synchronise Device Classes from Home Assistant" committer: esphomebot From ed6462fa00b2162d541a433076c01d67fb3c8e84 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Jun 2024 07:38:50 +1200 Subject: [PATCH 1624/2101] Bump docker/build-push-action from 6.0.0 to 6.0.1 in /.github/actions/build-image (#6934) 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 c685e80bec..53cd836573 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -46,7 +46,7 @@ runs: - name: Build and push to ghcr by digest id: build-ghcr - uses: docker/build-push-action@v6.0.0 + uses: docker/build-push-action@v6.0.1 with: context: . file: ./docker/Dockerfile @@ -69,7 +69,7 @@ runs: - name: Build and push to dockerhub by digest id: build-dockerhub - uses: docker/build-push-action@v6.0.0 + uses: docker/build-push-action@v6.0.1 with: context: . file: ./docker/Dockerfile From 896cdab22dfde5fbd64f3d0506d0d0d3990ef28b Mon Sep 17 00:00:00 2001 From: Manuel Kasper Date: Tue, 18 Jun 2024 21:53:01 +0200 Subject: [PATCH 1625/2101] Fix garbled graphics on LILYGO T4-S3 display (#6910) --- esphome/components/qspi_amoled/display.py | 20 +++++++++++++++---- .../components/qspi_amoled/qspi_amoled.cpp | 13 ++++++++++++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/esphome/components/qspi_amoled/display.py b/esphome/components/qspi_amoled/display.py index 84bf9553cb..77d1e3d095 100644 --- a/esphome/components/qspi_amoled/display.py +++ b/esphome/components/qspi_amoled/display.py @@ -42,6 +42,14 @@ COLOR_ORDERS = { } DATA_PIN_SCHEMA = pins.internal_gpio_output_pin_schema + +def validate_dimension(value): + value = cv.positive_int(value) + if value % 2 != 0: + raise cv.Invalid("Width/height/offset must be divisible by 2") + return value + + CONFIG_SCHEMA = cv.All( display.FULL_DISPLAY_SCHEMA.extend( cv.Schema( @@ -52,10 +60,14 @@ CONFIG_SCHEMA = cv.All( cv.dimensions, cv.Schema( { - cv.Required(CONF_WIDTH): cv.int_, - cv.Required(CONF_HEIGHT): cv.int_, - cv.Optional(CONF_OFFSET_HEIGHT, default=0): cv.int_, - cv.Optional(CONF_OFFSET_WIDTH, default=0): cv.int_, + cv.Required(CONF_WIDTH): validate_dimension, + cv.Required(CONF_HEIGHT): validate_dimension, + cv.Optional( + CONF_OFFSET_HEIGHT, default=0 + ): validate_dimension, + cv.Optional( + CONF_OFFSET_WIDTH, default=0 + ): validate_dimension, } ), ), diff --git a/esphome/components/qspi_amoled/qspi_amoled.cpp b/esphome/components/qspi_amoled/qspi_amoled.cpp index 697989e861..36e9b03252 100644 --- a/esphome/components/qspi_amoled/qspi_amoled.cpp +++ b/esphome/components/qspi_amoled/qspi_amoled.cpp @@ -26,6 +26,19 @@ void QspiAmoLed::setup() { void QspiAmoLed::update() { this->do_update_(); + // Start addresses and widths/heights must be divisible by 2 (CASET/RASET restriction in datasheet) + if (this->x_low_ % 2 == 1) { + this->x_low_--; + } + if (this->x_high_ % 2 == 0) { + this->x_high_++; + } + if (this->y_low_ % 2 == 1) { + this->y_low_--; + } + if (this->y_high_ % 2 == 0) { + this->y_high_++; + } int w = this->x_high_ - this->x_low_ + 1; int h = this->y_high_ - this->y_low_ + 1; this->draw_pixels_at(this->x_low_, this->y_low_, w, h, this->buffer_, this->color_mode_, display::COLOR_BITNESS_565, From 310f850ee4a7dd7ed5084bd307122c0cbb2d4991 Mon Sep 17 00:00:00 2001 From: peter--s Date: Wed, 19 Jun 2024 03:28:03 +0200 Subject: [PATCH 1626/2101] Update cover.h for open() and close() compiler warnings (#6936) --- esphome/components/cover/cover.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/cover/cover.h b/esphome/components/cover/cover.h index 89598a9636..8b6f5b8a72 100644 --- a/esphome/components/cover/cover.h +++ b/esphome/components/cover/cover.h @@ -129,13 +129,13 @@ class Cover : public EntityBase, public EntityBase_DeviceClass { * * This is a legacy method and may be removed later, please use `.make_call()` instead. */ - ESPDEPRECATED("open() is deprecated, use make_call().set_command_open() instead.", "2021.9") + ESPDEPRECATED("open() is deprecated, use make_call().set_command_open().perform() instead.", "2021.9") void open(); /** Close the cover. * * This is a legacy method and may be removed later, please use `.make_call()` instead. */ - ESPDEPRECATED("close() is deprecated, use make_call().set_command_close() instead.", "2021.9") + ESPDEPRECATED("close() is deprecated, use make_call().set_command_close().perform() instead.", "2021.9") void close(); /** Stop the cover. * From 8567877f07d2900a067c6b0fc57e5b0e07685f1d Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 19 Jun 2024 15:09:16 +1200 Subject: [PATCH 1627/2101] [network] Default ipv6 to false to always set the flags (#6937) * [network] Default ipv6 to false to always set the flags * Separate tests for ipv6 disabled and enabled * Forgot other platforms wouldnt have the variable in config --- esphome/components/network/__init__.py | 26 +++++++++++-------- tests/components/network/common.yaml | 5 +++- .../network/test-ipv6.esp32-ard.yaml | 4 +++ .../network/test-ipv6.esp32-c3-ard.yaml | 4 +++ .../network/test-ipv6.esp32-c3-idf.yaml | 4 +++ .../network/test-ipv6.esp32-idf.yaml | 4 +++ .../network/test-ipv6.esp8266-ard.yaml | 4 +++ .../network/test-ipv6.rp2040-ard.yaml | 4 +++ tests/components/network/test.host.yaml | 1 + 9 files changed, 44 insertions(+), 12 deletions(-) create mode 100644 tests/components/network/test-ipv6.esp32-ard.yaml create mode 100644 tests/components/network/test-ipv6.esp32-c3-ard.yaml create mode 100644 tests/components/network/test-ipv6.esp32-c3-idf.yaml create mode 100644 tests/components/network/test-ipv6.esp32-idf.yaml create mode 100644 tests/components/network/test-ipv6.esp8266-ard.yaml create mode 100644 tests/components/network/test-ipv6.rp2040-ard.yaml create mode 100644 tests/components/network/test.host.yaml diff --git a/esphome/components/network/__init__.py b/esphome/components/network/__init__.py index 36144ff0a4..9ef75e0fb9 100644 --- a/esphome/components/network/__init__.py +++ b/esphome/components/network/__init__.py @@ -19,7 +19,12 @@ IPAddress = network_ns.class_("IPAddress") CONFIG_SCHEMA = cv.Schema( { - cv.SplitDefault(CONF_ENABLE_IPV6): cv.All( + cv.SplitDefault( + CONF_ENABLE_IPV6, + esp8266=False, + esp32=False, + rp2040=False, + ): cv.All( cv.boolean, cv.only_on([PLATFORM_ESP32, PLATFORM_ESP8266, PLATFORM_RP2040]) ), cv.Optional(CONF_MIN_IPV6_ADDR_COUNT, default=0): cv.positive_int, @@ -28,18 +33,17 @@ CONFIG_SCHEMA = cv.Schema( async def to_code(config): - if CONF_ENABLE_IPV6 in config: - cg.add_define("USE_NETWORK_IPV6", config[CONF_ENABLE_IPV6]) - cg.add_define( - "USE_NETWORK_MIN_IPV6_ADDR_COUNT", config[CONF_MIN_IPV6_ADDR_COUNT] - ) - if CORE.using_esp_idf: - add_idf_sdkconfig_option("CONFIG_LWIP_IPV6", config[CONF_ENABLE_IPV6]) - add_idf_sdkconfig_option( - "CONFIG_LWIP_IPV6_AUTOCONFIG", config[CONF_ENABLE_IPV6] + if (enable_ipv6 := config.get(CONF_ENABLE_IPV6, None)) is not None: + cg.add_define("USE_NETWORK_IPV6", enable_ipv6) + if enable_ipv6: + cg.add_define( + "USE_NETWORK_MIN_IPV6_ADDR_COUNT", config[CONF_MIN_IPV6_ADDR_COUNT] ) + if CORE.using_esp_idf: + add_idf_sdkconfig_option("CONFIG_LWIP_IPV6", enable_ipv6) + add_idf_sdkconfig_option("CONFIG_LWIP_IPV6_AUTOCONFIG", enable_ipv6) else: - if config[CONF_ENABLE_IPV6]: + if enable_ipv6: cg.add_build_flag("-DCONFIG_LWIP_IPV6") cg.add_build_flag("-DCONFIG_LWIP_IPV6_AUTOCONFIG") if CORE.is_rp2040: diff --git a/tests/components/network/common.yaml b/tests/components/network/common.yaml index 147afd1e81..dca00cbeb6 100644 --- a/tests/components/network/common.yaml +++ b/tests/components/network/common.yaml @@ -1,6 +1,9 @@ +substitutions: + network_enable_ipv6: "false" + wifi: ssid: MySSID password: password1 network: - enable_ipv6: true + enable_ipv6: ${network_enable_ipv6} diff --git a/tests/components/network/test-ipv6.esp32-ard.yaml b/tests/components/network/test-ipv6.esp32-ard.yaml new file mode 100644 index 0000000000..da1324b17e --- /dev/null +++ b/tests/components/network/test-ipv6.esp32-ard.yaml @@ -0,0 +1,4 @@ +substitutions: + network_enable_ipv6: "true" + +<<: !include common.yaml diff --git a/tests/components/network/test-ipv6.esp32-c3-ard.yaml b/tests/components/network/test-ipv6.esp32-c3-ard.yaml new file mode 100644 index 0000000000..da1324b17e --- /dev/null +++ b/tests/components/network/test-ipv6.esp32-c3-ard.yaml @@ -0,0 +1,4 @@ +substitutions: + network_enable_ipv6: "true" + +<<: !include common.yaml diff --git a/tests/components/network/test-ipv6.esp32-c3-idf.yaml b/tests/components/network/test-ipv6.esp32-c3-idf.yaml new file mode 100644 index 0000000000..da1324b17e --- /dev/null +++ b/tests/components/network/test-ipv6.esp32-c3-idf.yaml @@ -0,0 +1,4 @@ +substitutions: + network_enable_ipv6: "true" + +<<: !include common.yaml diff --git a/tests/components/network/test-ipv6.esp32-idf.yaml b/tests/components/network/test-ipv6.esp32-idf.yaml new file mode 100644 index 0000000000..da1324b17e --- /dev/null +++ b/tests/components/network/test-ipv6.esp32-idf.yaml @@ -0,0 +1,4 @@ +substitutions: + network_enable_ipv6: "true" + +<<: !include common.yaml diff --git a/tests/components/network/test-ipv6.esp8266-ard.yaml b/tests/components/network/test-ipv6.esp8266-ard.yaml new file mode 100644 index 0000000000..da1324b17e --- /dev/null +++ b/tests/components/network/test-ipv6.esp8266-ard.yaml @@ -0,0 +1,4 @@ +substitutions: + network_enable_ipv6: "true" + +<<: !include common.yaml diff --git a/tests/components/network/test-ipv6.rp2040-ard.yaml b/tests/components/network/test-ipv6.rp2040-ard.yaml new file mode 100644 index 0000000000..da1324b17e --- /dev/null +++ b/tests/components/network/test-ipv6.rp2040-ard.yaml @@ -0,0 +1,4 @@ +substitutions: + network_enable_ipv6: "true" + +<<: !include common.yaml diff --git a/tests/components/network/test.host.yaml b/tests/components/network/test.host.yaml new file mode 100644 index 0000000000..61889b0361 --- /dev/null +++ b/tests/components/network/test.host.yaml @@ -0,0 +1 @@ +network: From fd7a212562089d1e2ce55b4f698cd20343de8094 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Jun 2024 16:44:20 +1200 Subject: [PATCH 1628/2101] Bump pypa/gh-action-pypi-publish from 1.8.14 to 1.9.0 (#6926) 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 563d485b6a..62031e925a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -65,7 +65,7 @@ jobs: pip3 install build python3 -m build - name: Publish - uses: pypa/gh-action-pypi-publish@v1.8.14 + uses: pypa/gh-action-pypi-publish@v1.9.0 deploy-docker: name: Build ESPHome ${{ matrix.platform }} From acf69bb56f53b636932e224fc466ef8cab65ef0d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Jun 2024 19:16:10 +1200 Subject: [PATCH 1629/2101] Bump docker/build-push-action from 5.4.0 to 6.0.0 in /.github/actions/build-image (#6927) 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 d792ab5f4c..c685e80bec 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -46,7 +46,7 @@ runs: - name: Build and push to ghcr by digest id: build-ghcr - uses: docker/build-push-action@v5.4.0 + uses: docker/build-push-action@v6.0.0 with: context: . file: ./docker/Dockerfile @@ -69,7 +69,7 @@ runs: - name: Build and push to dockerhub by digest id: build-dockerhub - uses: docker/build-push-action@v5.4.0 + uses: docker/build-push-action@v6.0.0 with: context: . file: ./docker/Dockerfile From c17090c1e556aebeb0186f0042824f9611266896 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Jun 2024 07:38:50 +1200 Subject: [PATCH 1630/2101] Bump docker/build-push-action from 6.0.0 to 6.0.1 in /.github/actions/build-image (#6934) 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 c685e80bec..53cd836573 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -46,7 +46,7 @@ runs: - name: Build and push to ghcr by digest id: build-ghcr - uses: docker/build-push-action@v6.0.0 + uses: docker/build-push-action@v6.0.1 with: context: . file: ./docker/Dockerfile @@ -69,7 +69,7 @@ runs: - name: Build and push to dockerhub by digest id: build-dockerhub - uses: docker/build-push-action@v6.0.0 + uses: docker/build-push-action@v6.0.1 with: context: . file: ./docker/Dockerfile From 6682451ee0c53a30d577d67574f827ec82952b17 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 19 Jun 2024 15:09:16 +1200 Subject: [PATCH 1631/2101] [network] Default ipv6 to false to always set the flags (#6937) * [network] Default ipv6 to false to always set the flags * Separate tests for ipv6 disabled and enabled * Forgot other platforms wouldnt have the variable in config --- esphome/components/network/__init__.py | 26 +++++++++++-------- tests/components/network/common.yaml | 5 +++- .../network/test-ipv6.esp32-ard.yaml | 4 +++ .../network/test-ipv6.esp32-c3-ard.yaml | 4 +++ .../network/test-ipv6.esp32-c3-idf.yaml | 4 +++ .../network/test-ipv6.esp32-idf.yaml | 4 +++ .../network/test-ipv6.esp8266-ard.yaml | 4 +++ .../network/test-ipv6.rp2040-ard.yaml | 4 +++ tests/components/network/test.host.yaml | 1 + 9 files changed, 44 insertions(+), 12 deletions(-) create mode 100644 tests/components/network/test-ipv6.esp32-ard.yaml create mode 100644 tests/components/network/test-ipv6.esp32-c3-ard.yaml create mode 100644 tests/components/network/test-ipv6.esp32-c3-idf.yaml create mode 100644 tests/components/network/test-ipv6.esp32-idf.yaml create mode 100644 tests/components/network/test-ipv6.esp8266-ard.yaml create mode 100644 tests/components/network/test-ipv6.rp2040-ard.yaml create mode 100644 tests/components/network/test.host.yaml diff --git a/esphome/components/network/__init__.py b/esphome/components/network/__init__.py index 36144ff0a4..9ef75e0fb9 100644 --- a/esphome/components/network/__init__.py +++ b/esphome/components/network/__init__.py @@ -19,7 +19,12 @@ IPAddress = network_ns.class_("IPAddress") CONFIG_SCHEMA = cv.Schema( { - cv.SplitDefault(CONF_ENABLE_IPV6): cv.All( + cv.SplitDefault( + CONF_ENABLE_IPV6, + esp8266=False, + esp32=False, + rp2040=False, + ): cv.All( cv.boolean, cv.only_on([PLATFORM_ESP32, PLATFORM_ESP8266, PLATFORM_RP2040]) ), cv.Optional(CONF_MIN_IPV6_ADDR_COUNT, default=0): cv.positive_int, @@ -28,18 +33,17 @@ CONFIG_SCHEMA = cv.Schema( async def to_code(config): - if CONF_ENABLE_IPV6 in config: - cg.add_define("USE_NETWORK_IPV6", config[CONF_ENABLE_IPV6]) - cg.add_define( - "USE_NETWORK_MIN_IPV6_ADDR_COUNT", config[CONF_MIN_IPV6_ADDR_COUNT] - ) - if CORE.using_esp_idf: - add_idf_sdkconfig_option("CONFIG_LWIP_IPV6", config[CONF_ENABLE_IPV6]) - add_idf_sdkconfig_option( - "CONFIG_LWIP_IPV6_AUTOCONFIG", config[CONF_ENABLE_IPV6] + if (enable_ipv6 := config.get(CONF_ENABLE_IPV6, None)) is not None: + cg.add_define("USE_NETWORK_IPV6", enable_ipv6) + if enable_ipv6: + cg.add_define( + "USE_NETWORK_MIN_IPV6_ADDR_COUNT", config[CONF_MIN_IPV6_ADDR_COUNT] ) + if CORE.using_esp_idf: + add_idf_sdkconfig_option("CONFIG_LWIP_IPV6", enable_ipv6) + add_idf_sdkconfig_option("CONFIG_LWIP_IPV6_AUTOCONFIG", enable_ipv6) else: - if config[CONF_ENABLE_IPV6]: + if enable_ipv6: cg.add_build_flag("-DCONFIG_LWIP_IPV6") cg.add_build_flag("-DCONFIG_LWIP_IPV6_AUTOCONFIG") if CORE.is_rp2040: diff --git a/tests/components/network/common.yaml b/tests/components/network/common.yaml index 147afd1e81..dca00cbeb6 100644 --- a/tests/components/network/common.yaml +++ b/tests/components/network/common.yaml @@ -1,6 +1,9 @@ +substitutions: + network_enable_ipv6: "false" + wifi: ssid: MySSID password: password1 network: - enable_ipv6: true + enable_ipv6: ${network_enable_ipv6} diff --git a/tests/components/network/test-ipv6.esp32-ard.yaml b/tests/components/network/test-ipv6.esp32-ard.yaml new file mode 100644 index 0000000000..da1324b17e --- /dev/null +++ b/tests/components/network/test-ipv6.esp32-ard.yaml @@ -0,0 +1,4 @@ +substitutions: + network_enable_ipv6: "true" + +<<: !include common.yaml diff --git a/tests/components/network/test-ipv6.esp32-c3-ard.yaml b/tests/components/network/test-ipv6.esp32-c3-ard.yaml new file mode 100644 index 0000000000..da1324b17e --- /dev/null +++ b/tests/components/network/test-ipv6.esp32-c3-ard.yaml @@ -0,0 +1,4 @@ +substitutions: + network_enable_ipv6: "true" + +<<: !include common.yaml diff --git a/tests/components/network/test-ipv6.esp32-c3-idf.yaml b/tests/components/network/test-ipv6.esp32-c3-idf.yaml new file mode 100644 index 0000000000..da1324b17e --- /dev/null +++ b/tests/components/network/test-ipv6.esp32-c3-idf.yaml @@ -0,0 +1,4 @@ +substitutions: + network_enable_ipv6: "true" + +<<: !include common.yaml diff --git a/tests/components/network/test-ipv6.esp32-idf.yaml b/tests/components/network/test-ipv6.esp32-idf.yaml new file mode 100644 index 0000000000..da1324b17e --- /dev/null +++ b/tests/components/network/test-ipv6.esp32-idf.yaml @@ -0,0 +1,4 @@ +substitutions: + network_enable_ipv6: "true" + +<<: !include common.yaml diff --git a/tests/components/network/test-ipv6.esp8266-ard.yaml b/tests/components/network/test-ipv6.esp8266-ard.yaml new file mode 100644 index 0000000000..da1324b17e --- /dev/null +++ b/tests/components/network/test-ipv6.esp8266-ard.yaml @@ -0,0 +1,4 @@ +substitutions: + network_enable_ipv6: "true" + +<<: !include common.yaml diff --git a/tests/components/network/test-ipv6.rp2040-ard.yaml b/tests/components/network/test-ipv6.rp2040-ard.yaml new file mode 100644 index 0000000000..da1324b17e --- /dev/null +++ b/tests/components/network/test-ipv6.rp2040-ard.yaml @@ -0,0 +1,4 @@ +substitutions: + network_enable_ipv6: "true" + +<<: !include common.yaml diff --git a/tests/components/network/test.host.yaml b/tests/components/network/test.host.yaml new file mode 100644 index 0000000000..61889b0361 --- /dev/null +++ b/tests/components/network/test.host.yaml @@ -0,0 +1 @@ +network: From 8bac82f80497b7e25639abc94102c125082e59cf Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 19 Jun 2024 15:37:43 +1200 Subject: [PATCH 1632/2101] Bump version to 2024.6.0b5 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index eea437bcdc..3aba12b9dd 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.6.0b4" +__version__ = "2024.6.0b5" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From ff803aa108214331d292fc90574ac06e84b82409 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 19 Jun 2024 16:37:33 +1200 Subject: [PATCH 1633/2101] Rename test files --- .../{test-ipv6.esp8266-ard.yaml => test-ipv6.esp8266.yaml} | 0 .../network/{test-ipv6.rp2040-ard.yaml => test-ipv6.rp2040.yaml} | 0 tests/components/network/{test.esp32.yaml => test.esp32-ard.yaml} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename tests/components/network/{test-ipv6.esp8266-ard.yaml => test-ipv6.esp8266.yaml} (100%) rename tests/components/network/{test-ipv6.rp2040-ard.yaml => test-ipv6.rp2040.yaml} (100%) rename tests/components/network/{test.esp32.yaml => test.esp32-ard.yaml} (100%) diff --git a/tests/components/network/test-ipv6.esp8266-ard.yaml b/tests/components/network/test-ipv6.esp8266.yaml similarity index 100% rename from tests/components/network/test-ipv6.esp8266-ard.yaml rename to tests/components/network/test-ipv6.esp8266.yaml diff --git a/tests/components/network/test-ipv6.rp2040-ard.yaml b/tests/components/network/test-ipv6.rp2040.yaml similarity index 100% rename from tests/components/network/test-ipv6.rp2040-ard.yaml rename to tests/components/network/test-ipv6.rp2040.yaml diff --git a/tests/components/network/test.esp32.yaml b/tests/components/network/test.esp32-ard.yaml similarity index 100% rename from tests/components/network/test.esp32.yaml rename to tests/components/network/test.esp32-ard.yaml From a6d1aa91de821726d114c46c30a0c9cb36c147ff Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 19 Jun 2024 21:52:47 +1200 Subject: [PATCH 1634/2101] Bump version to 2024.6.0 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 3aba12b9dd..0f5caa7f9d 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.6.0b5" +__version__ = "2024.6.0" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 80e5e1995653a3b51193b456d9861ec7f7f81c24 Mon Sep 17 00:00:00 2001 From: Cossid <83468485+Cossid@users.noreply.github.com> Date: Wed, 19 Jun 2024 19:59:37 -0500 Subject: [PATCH 1635/2101] debug_libretiny - Fix typo (#6942) --- esphome/components/debug/debug_libretiny.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/debug/debug_libretiny.cpp b/esphome/components/debug/debug_libretiny.cpp index c3418cf96c..b5e2a5b310 100644 --- a/esphome/components/debug/debug_libretiny.cpp +++ b/esphome/components/debug/debug_libretiny.cpp @@ -12,7 +12,7 @@ std::string DebugComponent::get_reset_reason_() { return lt_get_reboot_reason_na uint32_t DebugComponent::get_free_heap_() { return lt_heap_get_free(); } void DebugComponent::get_device_info_(std::string &device_info) { - str::string reset_reason = get_reset_reason_(); + std::string reset_reason = get_reset_reason_(); ESP_LOGD(TAG, "LibreTiny Version: %s", lt_get_version()); ESP_LOGD(TAG, "Chip: %s (%04x) @ %u MHz", lt_cpu_get_model_name(), lt_cpu_get_model(), lt_cpu_get_freq_mhz()); ESP_LOGD(TAG, "Chip ID: 0x%06X", lt_cpu_get_mac_id()); From 775e03cfd95d6532292e7665f82b5301924795b9 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 20 Jun 2024 14:12:38 +1200 Subject: [PATCH 1636/2101] Bump esphome-dashboard to 20240620.0 (#6944) --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index a7b08f8a14..0cbe5e7265 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ pyserial==3.5 platformio==6.1.15 # When updating platformio, also update Dockerfile esptool==4.7.0 click==8.1.7 -esphome-dashboard==20240613.0 +esphome-dashboard==20240620.0 aioesphomeapi==24.3.0 zeroconf==0.132.2 python-magic==0.4.27 From 96f1a146a66e5266d4417e7afb0db2781e243048 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Wed, 19 Jun 2024 21:32:29 -0500 Subject: [PATCH 1637/2101] [CI] Add debug component test for LibreTiny (#6945) --- tests/components/debug/test.bk72xx-ard.yaml | 1 + 1 file changed, 1 insertion(+) create mode 100644 tests/components/debug/test.bk72xx-ard.yaml diff --git a/tests/components/debug/test.bk72xx-ard.yaml b/tests/components/debug/test.bk72xx-ard.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/debug/test.bk72xx-ard.yaml @@ -0,0 +1 @@ +<<: !include common.yaml From ad8cf698973ea821ec1a8e4ec7ad74caa691b6cb Mon Sep 17 00:00:00 2001 From: Cossid <83468485+Cossid@users.noreply.github.com> Date: Wed, 19 Jun 2024 19:59:37 -0500 Subject: [PATCH 1638/2101] debug_libretiny - Fix typo (#6942) --- esphome/components/debug/debug_libretiny.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/debug/debug_libretiny.cpp b/esphome/components/debug/debug_libretiny.cpp index c3418cf96c..b5e2a5b310 100644 --- a/esphome/components/debug/debug_libretiny.cpp +++ b/esphome/components/debug/debug_libretiny.cpp @@ -12,7 +12,7 @@ std::string DebugComponent::get_reset_reason_() { return lt_get_reboot_reason_na uint32_t DebugComponent::get_free_heap_() { return lt_heap_get_free(); } void DebugComponent::get_device_info_(std::string &device_info) { - str::string reset_reason = get_reset_reason_(); + std::string reset_reason = get_reset_reason_(); ESP_LOGD(TAG, "LibreTiny Version: %s", lt_get_version()); ESP_LOGD(TAG, "Chip: %s (%04x) @ %u MHz", lt_cpu_get_model_name(), lt_cpu_get_model(), lt_cpu_get_freq_mhz()); ESP_LOGD(TAG, "Chip ID: 0x%06X", lt_cpu_get_mac_id()); From c868dae44a141ca3e0cbbf76a5c92b6bba7f5bbe Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 20 Jun 2024 14:12:38 +1200 Subject: [PATCH 1639/2101] Bump esphome-dashboard to 20240620.0 (#6944) --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index a7b08f8a14..0cbe5e7265 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ pyserial==3.5 platformio==6.1.15 # When updating platformio, also update Dockerfile esptool==4.7.0 click==8.1.7 -esphome-dashboard==20240613.0 +esphome-dashboard==20240620.0 aioesphomeapi==24.3.0 zeroconf==0.132.2 python-magic==0.4.27 From a7a9eb6f71677e8b1ec29cfcea86569452d16d57 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 20 Jun 2024 15:59:27 +1200 Subject: [PATCH 1640/2101] Bump version to 2024.6.1 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 0f5caa7f9d..3b3bdd1a17 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.6.0" +__version__ = "2024.6.1" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 6f074d369205ad91523bfc7eedaba34093dce423 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 21 Jun 2024 12:49:26 +1200 Subject: [PATCH 1641/2101] [dooya] Flip bit timings (#6947) --- esphome/components/remote_base/dooya_protocol.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/remote_base/dooya_protocol.cpp b/esphome/components/remote_base/dooya_protocol.cpp index d979bca8c5..04c5fef8f3 100644 --- a/esphome/components/remote_base/dooya_protocol.cpp +++ b/esphome/components/remote_base/dooya_protocol.cpp @@ -8,10 +8,10 @@ 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 = 750; -static const uint32_t BIT_ZERO_LOW_US = 350; -static const uint32_t BIT_ONE_HIGH_US = 350; -static const uint32_t BIT_ONE_LOW_US = 750; +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; void DooyaProtocol::encode(RemoteTransmitData *dst, const DooyaData &data) { dst->set_carrier_frequency(0); From 8045b889d39c7675ba69afa0d38e7fd7b952d93c Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 21 Jun 2024 13:09:00 +1200 Subject: [PATCH 1642/2101] [core] Fix package merging with lists of primitives (#6952) --- esphome/config_helpers.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/esphome/config_helpers.py b/esphome/config_helpers.py index b5e0b26143..54242bc259 100644 --- a/esphome/config_helpers.py +++ b/esphome/config_helpers.py @@ -58,17 +58,21 @@ def merge_config(full_old, full_new): ids = { v_id: i for i, v in enumerate(res) - if (v_id := v.get(CONF_ID)) and isinstance(v_id, str) + if isinstance(v, dict) + and (v_id := v.get(CONF_ID)) + and isinstance(v_id, str) } extend_ids = { v_id.value: i for i, v in enumerate(res) - if (v_id := v.get(CONF_ID)) and isinstance(v_id, Extend) + if isinstance(v, dict) + and (v_id := v.get(CONF_ID)) + and isinstance(v_id, Extend) } ids_to_delete = [] for v in new: - if new_id := v.get(CONF_ID): + if isinstance(v, dict) and (new_id := v.get(CONF_ID)): if isinstance(new_id, Extend): new_id = new_id.value if new_id in ids: From e7556271e72f85e09d1381bee68e43bde8843387 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 21 Jun 2024 14:59:52 +1200 Subject: [PATCH 1643/2101] [update] Set entity_category to config & Publish state to logs (#6954) --- esphome/components/update/__init__.py | 5 ++++ esphome/components/update/update_entity.cpp | 26 +++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/esphome/components/update/__init__.py b/esphome/components/update/__init__.py index ea1cf778b6..20a9373a06 100644 --- a/esphome/components/update/__init__.py +++ b/esphome/components/update/__init__.py @@ -4,11 +4,13 @@ import esphome.config_validation as cv import esphome.codegen as cg from esphome.const import ( CONF_DEVICE_CLASS, + CONF_ENTITY_CATEGORY, CONF_ID, CONF_MQTT_ID, CONF_WEB_SERVER_ID, DEVICE_CLASS_EMPTY, DEVICE_CLASS_FIRMWARE, + ENTITY_CATEGORY_CONFIG, ) from esphome.core import CORE, coroutine_with_priority from esphome.cpp_helpers import setup_entity @@ -41,6 +43,9 @@ UPDATE_SCHEMA = ( cv.Optional(CONF_ON_UPDATE_AVAILABLE): automation.validate_automation( single=True ), + cv.Optional( + CONF_ENTITY_CATEGORY, default=ENTITY_CATEGORY_CONFIG + ): cv.entity_category, } ) ) diff --git a/esphome/components/update/update_entity.cpp b/esphome/components/update/update_entity.cpp index 501cb6635f..ed9a0480d8 100644 --- a/esphome/components/update/update_entity.cpp +++ b/esphome/components/update/update_entity.cpp @@ -1,9 +1,35 @@ #include "update_entity.h" +#include "esphome/core/log.h" + namespace esphome { namespace update { +static const char *const TAG = "update"; + void UpdateEntity::publish_state() { + ESP_LOGD(TAG, "'%s' - Publishing:", this->name_.c_str()); + ESP_LOGD(TAG, " Current Version: %s", 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()); + } + if (!this->update_info_.firmware_url.empty()) { + ESP_LOGD(TAG, " Firmware URL: %s", this->update_info_.firmware_url.c_str()); + } + + ESP_LOGD(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()); + } + if (!this->update_info_.release_url.empty()) { + ESP_LOGD(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); + } + this->has_state_ = true; this->state_callback_.call(); } From 6c11f0bd5152b32579b3f86802365f2e308e9ca4 Mon Sep 17 00:00:00 2001 From: Manuel Kasper Date: Fri, 21 Jun 2024 16:46:06 +0200 Subject: [PATCH 1644/2101] [qspi_amoled] Fix display remaining blank after update() before setup completion (#6958) --- esphome/components/qspi_amoled/qspi_amoled.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/esphome/components/qspi_amoled/qspi_amoled.cpp b/esphome/components/qspi_amoled/qspi_amoled.cpp index 36e9b03252..b1f651025a 100644 --- a/esphome/components/qspi_amoled/qspi_amoled.cpp +++ b/esphome/components/qspi_amoled/qspi_amoled.cpp @@ -25,6 +25,9 @@ void QspiAmoLed::setup() { } void QspiAmoLed::update() { + if (!this->setup_complete_) { + return; + } this->do_update_(); // Start addresses and widths/heights must be divisible by 2 (CASET/RASET restriction in datasheet) if (this->x_low_ % 2 == 1) { From 67bd5db6d6eb6c23e44b430200fefa9a371e2491 Mon Sep 17 00:00:00 2001 From: "Kevin P. Fleming" Date: Fri, 21 Jun 2024 17:18:43 -0400 Subject: [PATCH 1645/2101] Fix infinite loop in http_request for ESP-IDF. (#6963) --- esphome/components/http_request/http_request_idf.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/http_request/http_request_idf.cpp b/esphome/components/http_request/http_request_idf.cpp index 138e0438f4..d6fac7a133 100644 --- a/esphome/components/http_request/http_request_idf.cpp +++ b/esphome/components/http_request/http_request_idf.cpp @@ -90,7 +90,7 @@ std::shared_ptr HttpRequestIDF::start(std::string url, std::strin int write_left = body_len; int write_index = 0; const char *buf = body.c_str(); - while (body_len > 0) { + while (write_left > 0) { int written = esp_http_client_write(client, buf + write_index, write_left); if (written < 0) { err = ESP_FAIL; From 0a9703bff998a5196e15a3aefa35257b7d651c98 Mon Sep 17 00:00:00 2001 From: "Kevin P. Fleming" Date: Fri, 21 Jun 2024 17:28:11 -0400 Subject: [PATCH 1646/2101] ESP-IDF 4.x expects seconds for esp_task_wdt_init(), not milliseconds. (#6964) --- esphome/components/http_request/watchdog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/http_request/watchdog.cpp b/esphome/components/http_request/watchdog.cpp index e609feb4dd..a8519c59ed 100644 --- a/esphome/components/http_request/watchdog.cpp +++ b/esphome/components/http_request/watchdog.cpp @@ -46,7 +46,7 @@ void WatchdogManager::set_timeout_(uint32_t timeout_ms) { }; esp_task_wdt_reconfigure(&wdt_config); #else - esp_task_wdt_init(timeout_ms, true); + esp_task_wdt_init(timeout_ms / 1000, true); #endif // ESP_IDF_VERSION_MAJOR #endif // USE_ESP32 From 9c5507ab4680ce4df996910807100cc72f911e1f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 22 Jun 2024 12:50:21 +0200 Subject: [PATCH 1647/2101] Bump docker/build-push-action from 6.0.1 to 6.1.0 in /.github/actions/build-image (#6962) 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 53cd836573..27d2ffc533 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -46,7 +46,7 @@ runs: - name: Build and push to ghcr by digest id: build-ghcr - uses: docker/build-push-action@v6.0.1 + uses: docker/build-push-action@v6.1.0 with: context: . file: ./docker/Dockerfile @@ -69,7 +69,7 @@ runs: - name: Build and push to dockerhub by digest id: build-dockerhub - uses: docker/build-push-action@v6.0.1 + uses: docker/build-push-action@v6.1.0 with: context: . file: ./docker/Dockerfile From 2aacf14e960d005aee29e7a259f47b90ae1d3970 Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Sat, 22 Jun 2024 04:57:27 -0700 Subject: [PATCH 1648/2101] Onewire (#6967) * retry scan * setup pin and log retries * fix retries * remove retries --------- Co-authored-by: Samuel Sieb --- esphome/components/gpio/one_wire/gpio_one_wire.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/esphome/components/gpio/one_wire/gpio_one_wire.cpp b/esphome/components/gpio/one_wire/gpio_one_wire.cpp index 34c2cf3c29..b4e69e975a 100644 --- a/esphome/components/gpio/one_wire/gpio_one_wire.cpp +++ b/esphome/components/gpio/one_wire/gpio_one_wire.cpp @@ -9,6 +9,10 @@ static const char *const TAG = "gpio.one_wire"; void GPIOOneWireBus::setup() { ESP_LOGCONFIG(TAG, "Setting up 1-wire bus..."); + this->t_pin_->setup(); + // clear bus with 480µs high, otherwise initial reset in search might fail + this->t_pin_->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP); + delayMicroseconds(480); this->search(); } From 18690d51f51c0d8a145c8ca71a234a496a06b3d9 Mon Sep 17 00:00:00 2001 From: esphomebot Date: Sun, 23 Jun 2024 01:27:47 +1200 Subject: [PATCH 1649/2101] Synchronise Device Classes from Home Assistant (#6966) --- esphome/components/number/__init__.py | 2 ++ esphome/components/sensor/__init__.py | 2 ++ esphome/const.py | 1 + 3 files changed, 5 insertions(+) diff --git a/esphome/components/number/__init__.py b/esphome/components/number/__init__.py index 303535c138..d9c16fd7a9 100644 --- a/esphome/components/number/__init__.py +++ b/esphome/components/number/__init__.py @@ -26,6 +26,7 @@ from esphome.const import ( DEVICE_CLASS_BATTERY, DEVICE_CLASS_CARBON_DIOXIDE, DEVICE_CLASS_CARBON_MONOXIDE, + DEVICE_CLASS_CONDUCTIVITY, DEVICE_CLASS_CURRENT, DEVICE_CLASS_DATA_RATE, DEVICE_CLASS_DATA_SIZE, @@ -82,6 +83,7 @@ DEVICE_CLASSES = [ DEVICE_CLASS_BATTERY, DEVICE_CLASS_CARBON_DIOXIDE, DEVICE_CLASS_CARBON_MONOXIDE, + DEVICE_CLASS_CONDUCTIVITY, DEVICE_CLASS_CURRENT, DEVICE_CLASS_DATA_RATE, DEVICE_CLASS_DATA_SIZE, diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index 6077f5dc1f..262e69d75b 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -43,6 +43,7 @@ from esphome.const import ( DEVICE_CLASS_BATTERY, DEVICE_CLASS_CARBON_DIOXIDE, DEVICE_CLASS_CARBON_MONOXIDE, + DEVICE_CLASS_CONDUCTIVITY, DEVICE_CLASS_CURRENT, DEVICE_CLASS_DATA_RATE, DEVICE_CLASS_DATA_SIZE, @@ -103,6 +104,7 @@ DEVICE_CLASSES = [ DEVICE_CLASS_BATTERY, DEVICE_CLASS_CARBON_DIOXIDE, DEVICE_CLASS_CARBON_MONOXIDE, + DEVICE_CLASS_CONDUCTIVITY, DEVICE_CLASS_CURRENT, DEVICE_CLASS_DATA_RATE, DEVICE_CLASS_DATA_SIZE, diff --git a/esphome/const.py b/esphome/const.py index 9c4e451029..a13a0af8eb 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1070,6 +1070,7 @@ DEVICE_CLASS_BUTTON = "button" DEVICE_CLASS_CARBON_DIOXIDE = "carbon_dioxide" DEVICE_CLASS_CARBON_MONOXIDE = "carbon_monoxide" DEVICE_CLASS_COLD = "cold" +DEVICE_CLASS_CONDUCTIVITY = "conductivity" DEVICE_CLASS_CONNECTIVITY = "connectivity" DEVICE_CLASS_CURRENT = "current" DEVICE_CLASS_CURTAIN = "curtain" From 1e05bcaa614040617ef94340a54ca3f22871c4ac Mon Sep 17 00:00:00 2001 From: Manuel Kasper Date: Sat, 22 Jun 2024 17:10:22 +0200 Subject: [PATCH 1650/2101] [qspi_amoled] Fix clear/fill with rotation (#6960) --- esphome/components/qspi_amoled/qspi_amoled.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/esphome/components/qspi_amoled/qspi_amoled.h b/esphome/components/qspi_amoled/qspi_amoled.h index 28d243f548..c766b4e685 100644 --- a/esphome/components/qspi_amoled/qspi_amoled.h +++ b/esphome/components/qspi_amoled/qspi_amoled.h @@ -65,13 +65,10 @@ class QspiAmoLed : public display::DisplayBuffer, void set_reset_pin(GPIOPin *reset_pin) { this->reset_pin_ = reset_pin; } void set_enable_pin(GPIOPin *enable_pin) { this->enable_pin_ = enable_pin; } - void set_width(uint16_t width) { this->width_ = width; } void set_dimensions(uint16_t width, uint16_t height) { this->width_ = width; this->height_ = height; } - int get_width() override { return this->width_; } - int get_height() override { return this->height_; } void set_invert_colors(bool invert_colors) { this->invert_colors_ = invert_colors; this->reset_params_(); From 17204baac0168b6a6dd2f6ad87968cd83717f7de Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Sun, 23 Jun 2024 15:22:08 -0700 Subject: [PATCH 1651/2101] allow template parameters (#6972) --- esphome/components/script/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/script/__init__.py b/esphome/components/script/__init__.py index 483357f85b..16b1d4c54e 100644 --- a/esphome/components/script/__init__.py +++ b/esphome/components/script/__init__.py @@ -88,7 +88,7 @@ def validate_parameter_name(value): raise cv.Invalid(f"Script's parameter name cannot be {CONF_ID}") -ALLOWED_PARAM_TYPE_CHARSET = set("abcdefghijklmnopqrstuvwxyz0123456789_:*&[]") +ALLOWED_PARAM_TYPE_CHARSET = set("abcdefghijklmnopqrstuvwxyz0123456789_:*&[]<>") def validate_parameter_type(value): From 0f49b58e0a727284c055246188a4ce9fee687eae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Poczkodi?= Date: Mon, 24 Jun 2024 06:32:20 +0200 Subject: [PATCH 1652/2101] [http_request] memory leak fix (#6973) --- esphome/components/http_request/http_request.h | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/http_request/http_request.h b/esphome/components/http_request/http_request.h index df6bc7dea7..6281adddb6 100644 --- a/esphome/components/http_request/http_request.h +++ b/esphome/components/http_request/http_request.h @@ -149,6 +149,7 @@ template class HttpRequestSendAction : public Action { } response_body.reserve(read_index); response_body.assign((char *) buf, read_index); + allocator.deallocate(buf, max_length); } } From 7ee1406f64a04807bf1737cbd407f978744004ab Mon Sep 17 00:00:00 2001 From: Brian Kaufman Date: Sun, 23 Jun 2024 21:54:30 -0700 Subject: [PATCH 1653/2101] Await cg.get_variable in Update component (#6974) --- esphome/components/update/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/update/__init__.py b/esphome/components/update/__init__.py index 20a9373a06..45bf082fa4 100644 --- a/esphome/components/update/__init__.py +++ b/esphome/components/update/__init__.py @@ -69,7 +69,7 @@ async def setup_update_core_(var, config): await mqtt.register_mqtt_component(mqtt_, config) if web_server_id_config := config.get(CONF_WEB_SERVER_ID): - web_server_ = cg.get_variable(web_server_id_config) + web_server_ = await cg.get_variable(web_server_id_config) web_server.add_entity_to_sorting_list(web_server_, var, config) From f7af51b92c9d3fee019f2ff5abda5880cf18061e Mon Sep 17 00:00:00 2001 From: Sergey Dudanov Date: Mon, 24 Jun 2024 10:22:07 +0400 Subject: [PATCH 1654/2101] [haier] climate ID auto generation (#6949) --- esphome/components/haier/binary_sensor/__init__.py | 8 ++++---- esphome/components/haier/button/__init__.py | 2 +- esphome/components/haier/climate.py | 11 +++-------- esphome/components/haier/sensor/__init__.py | 10 +++++----- esphome/components/haier/text_sensor/__init__.py | 8 ++++---- tests/components/haier/test.esp32-c3-ard.yaml | 4 ---- tests/components/haier/test.esp32-c3-idf.yaml | 4 ---- tests/components/haier/test.esp32-idf.yaml | 4 ---- tests/components/haier/test.esp8266-ard.yaml | 4 ---- tests/components/haier/test.rp2040-ard.yaml | 4 ---- 10 files changed, 17 insertions(+), 42 deletions(-) diff --git a/esphome/components/haier/binary_sensor/__init__.py b/esphome/components/haier/binary_sensor/__init__.py index 8e9d5ec578..3a4935b22d 100644 --- a/esphome/components/haier/binary_sensor/__init__.py +++ b/esphome/components/haier/binary_sensor/__init__.py @@ -56,7 +56,7 @@ SENSOR_TYPES = { CONFIG_SCHEMA = cv.Schema( { - cv.Required(CONF_HAIER_ID): cv.use_id(HonClimate), + cv.GenerateID(CONF_HAIER_ID): cv.use_id(HonClimate), } ).extend({cv.Optional(type): schema for type, schema in SENSOR_TYPES.items()}) @@ -64,8 +64,8 @@ CONFIG_SCHEMA = cv.Schema( async def to_code(config): paren = await cg.get_variable(config[CONF_HAIER_ID]) - for type, _ in SENSOR_TYPES.items(): - if conf := config.get(type): + for type_ in SENSOR_TYPES: + if conf := config.get(type_): sens = await binary_sensor.new_binary_sensor(conf) - binary_sensor_type = getattr(BinarySensorTypeEnum, type.upper()) + binary_sensor_type = getattr(BinarySensorTypeEnum, type_.upper()) cg.add(paren.set_sub_binary_sensor(binary_sensor_type, sens)) diff --git a/esphome/components/haier/button/__init__.py b/esphome/components/haier/button/__init__.py index efe6180aaf..745ad95fb6 100644 --- a/esphome/components/haier/button/__init__.py +++ b/esphome/components/haier/button/__init__.py @@ -21,7 +21,7 @@ ICON_SPRAY_BOTTLE = "mdi:spray-bottle" CONFIG_SCHEMA = cv.Schema( { - cv.Required(CONF_HAIER_ID): cv.use_id(HonClimate), + cv.GenerateID(CONF_HAIER_ID): cv.use_id(HonClimate), cv.Optional(CONF_SELF_CLEANING): button.button_schema( SelfCleaningButton, icon=ICON_SPRAY_BOTTLE, diff --git a/esphome/components/haier/climate.py b/esphome/components/haier/climate.py index 1562708a4f..3dcb35708c 100644 --- a/esphome/components/haier/climate.py +++ b/esphome/components/haier/climate.py @@ -183,7 +183,6 @@ BASE_CONFIG_SCHEMA = ( cv.Optional( CONF_SUPPORTED_SWING_MODES, default=[ - "OFF", "VERTICAL", "HORIZONTAL", "BOTH", @@ -211,7 +210,7 @@ CONFIG_SCHEMA = cv.All( ): cv.boolean, cv.Optional( CONF_SUPPORTED_PRESETS, - default=list(["BOOST", "COMFORT"]), # No AWAY by default + default=["BOOST", "COMFORT"], # No AWAY by default ): cv.ensure_list( cv.enum(SUPPORTED_CLIMATE_PRESETS_SMARTAIR2_OPTIONS, upper=True) ), @@ -231,7 +230,7 @@ CONFIG_SCHEMA = cv.All( ): cv.int_range(min=PROTOCOL_CONTROL_PACKET_SIZE, max=50), cv.Optional( CONF_SUPPORTED_PRESETS, - default=list(["BOOST", "ECO", "SLEEP"]), # No AWAY by default + default=["BOOST", "ECO", "SLEEP"], # No AWAY by default ): cv.ensure_list( cv.enum(SUPPORTED_CLIMATE_PRESETS_HON_OPTIONS, upper=True) ), @@ -427,11 +426,7 @@ def _final_validate(config): "No logger component found, logging for Haier protocol is disabled" ) cg.add_build_flag("-DHAIER_LOG_LEVEL=0") - if ( - (CONF_WIFI_SIGNAL in config) - and (config[CONF_WIFI_SIGNAL]) - and CONF_WIFI not in full_config - ): + if config.get(CONF_WIFI_SIGNAL) and CONF_WIFI not in full_config: raise cv.Invalid( f"No WiFi configured, if you want to use haier climate without WiFi add {CONF_WIFI_SIGNAL}: false to climate configuration" ) diff --git a/esphome/components/haier/sensor/__init__.py b/esphome/components/haier/sensor/__init__.py index b2717631e0..23c1d6f008 100644 --- a/esphome/components/haier/sensor/__init__.py +++ b/esphome/components/haier/sensor/__init__.py @@ -137,16 +137,16 @@ SENSOR_TYPES = { CONFIG_SCHEMA = cv.Schema( { - cv.Required(CONF_HAIER_ID): cv.use_id(HonClimate), + cv.GenerateID(CONF_HAIER_ID): cv.use_id(HonClimate), } -).extend({cv.Optional(type): schema for type, schema in SENSOR_TYPES.items()}) +).extend({cv.Optional(type_): schema for type_, schema in SENSOR_TYPES.items()}) async def to_code(config): paren = await cg.get_variable(config[CONF_HAIER_ID]) - for type, _ in SENSOR_TYPES.items(): - if conf := config.get(type): + for type_ in SENSOR_TYPES: + if conf := config.get(type_): sens = await sensor.new_sensor(conf) - sensor_type = getattr(SensorTypeEnum, type.upper()) + sensor_type = getattr(SensorTypeEnum, type_.upper()) cg.add(paren.set_sub_sensor(sensor_type, sens)) diff --git a/esphome/components/haier/text_sensor/__init__.py b/esphome/components/haier/text_sensor/__init__.py index 528b70d83e..d28c5a8c0e 100644 --- a/esphome/components/haier/text_sensor/__init__.py +++ b/esphome/components/haier/text_sensor/__init__.py @@ -39,7 +39,7 @@ TEXT_SENSOR_TYPES = { CONFIG_SCHEMA = cv.Schema( { - cv.Required(CONF_HAIER_ID): cv.use_id(HonClimate), + cv.GenerateID(CONF_HAIER_ID): cv.use_id(HonClimate), } ).extend({cv.Optional(type): schema for type, schema in TEXT_SENSOR_TYPES.items()}) @@ -47,8 +47,8 @@ CONFIG_SCHEMA = cv.Schema( async def to_code(config): paren = await cg.get_variable(config[CONF_HAIER_ID]) - for type, _ in TEXT_SENSOR_TYPES.items(): - if conf := config.get(type): + for type_ in TEXT_SENSOR_TYPES: + if conf := config.get(type_): sens = await text_sensor.new_text_sensor(conf) - text_sensor_type = getattr(TextSensorTypeEnum, type.upper()) + text_sensor_type = getattr(TextSensorTypeEnum, type_.upper()) cg.add(paren.set_sub_text_sensor(text_sensor_type, sens)) diff --git a/tests/components/haier/test.esp32-c3-ard.yaml b/tests/components/haier/test.esp32-c3-ard.yaml index fed573bd1d..0053220669 100644 --- a/tests/components/haier/test.esp32-c3-ard.yaml +++ b/tests/components/haier/test.esp32-c3-ard.yaml @@ -54,7 +54,6 @@ climate: sensor: - platform: haier - haier_id: haier_ac outdoor_temperature: name: Haier outdoor temperature humidity: @@ -80,7 +79,6 @@ sensor: binary_sensor: - platform: haier - haier_id: haier_ac compressor_status: name: Haier Outdoor Compressor Status defrost_status: @@ -96,7 +94,6 @@ binary_sensor: button: - platform: haier - haier_id: haier_ac self_cleaning: name: Haier start self cleaning steri_cleaning: @@ -104,7 +101,6 @@ button: text_sensor: - platform: haier - haier_id: haier_ac appliance_name: name: Haier appliance name cleaning_status: diff --git a/tests/components/haier/test.esp32-c3-idf.yaml b/tests/components/haier/test.esp32-c3-idf.yaml index fed573bd1d..0053220669 100644 --- a/tests/components/haier/test.esp32-c3-idf.yaml +++ b/tests/components/haier/test.esp32-c3-idf.yaml @@ -54,7 +54,6 @@ climate: sensor: - platform: haier - haier_id: haier_ac outdoor_temperature: name: Haier outdoor temperature humidity: @@ -80,7 +79,6 @@ sensor: binary_sensor: - platform: haier - haier_id: haier_ac compressor_status: name: Haier Outdoor Compressor Status defrost_status: @@ -96,7 +94,6 @@ binary_sensor: button: - platform: haier - haier_id: haier_ac self_cleaning: name: Haier start self cleaning steri_cleaning: @@ -104,7 +101,6 @@ button: text_sensor: - platform: haier - haier_id: haier_ac appliance_name: name: Haier appliance name cleaning_status: diff --git a/tests/components/haier/test.esp32-idf.yaml b/tests/components/haier/test.esp32-idf.yaml index efff532d25..54e384f3ce 100644 --- a/tests/components/haier/test.esp32-idf.yaml +++ b/tests/components/haier/test.esp32-idf.yaml @@ -54,7 +54,6 @@ climate: sensor: - platform: haier - haier_id: haier_ac outdoor_temperature: name: Haier outdoor temperature humidity: @@ -80,7 +79,6 @@ sensor: binary_sensor: - platform: haier - haier_id: haier_ac compressor_status: name: Haier Outdoor Compressor Status defrost_status: @@ -96,7 +94,6 @@ binary_sensor: button: - platform: haier - haier_id: haier_ac self_cleaning: name: Haier start self cleaning steri_cleaning: @@ -104,7 +101,6 @@ button: text_sensor: - platform: haier - haier_id: haier_ac appliance_name: name: Haier appliance name cleaning_status: diff --git a/tests/components/haier/test.esp8266-ard.yaml b/tests/components/haier/test.esp8266-ard.yaml index fed573bd1d..0053220669 100644 --- a/tests/components/haier/test.esp8266-ard.yaml +++ b/tests/components/haier/test.esp8266-ard.yaml @@ -54,7 +54,6 @@ climate: sensor: - platform: haier - haier_id: haier_ac outdoor_temperature: name: Haier outdoor temperature humidity: @@ -80,7 +79,6 @@ sensor: binary_sensor: - platform: haier - haier_id: haier_ac compressor_status: name: Haier Outdoor Compressor Status defrost_status: @@ -96,7 +94,6 @@ binary_sensor: button: - platform: haier - haier_id: haier_ac self_cleaning: name: Haier start self cleaning steri_cleaning: @@ -104,7 +101,6 @@ button: text_sensor: - platform: haier - haier_id: haier_ac appliance_name: name: Haier appliance name cleaning_status: diff --git a/tests/components/haier/test.rp2040-ard.yaml b/tests/components/haier/test.rp2040-ard.yaml index fed573bd1d..0053220669 100644 --- a/tests/components/haier/test.rp2040-ard.yaml +++ b/tests/components/haier/test.rp2040-ard.yaml @@ -54,7 +54,6 @@ climate: sensor: - platform: haier - haier_id: haier_ac outdoor_temperature: name: Haier outdoor temperature humidity: @@ -80,7 +79,6 @@ sensor: binary_sensor: - platform: haier - haier_id: haier_ac compressor_status: name: Haier Outdoor Compressor Status defrost_status: @@ -96,7 +94,6 @@ binary_sensor: button: - platform: haier - haier_id: haier_ac self_cleaning: name: Haier start self cleaning steri_cleaning: @@ -104,7 +101,6 @@ button: text_sensor: - platform: haier - haier_id: haier_ac appliance_name: name: Haier appliance name cleaning_status: From b1868123db2107a84ad093a6776e4f096829ba1a Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Mon, 24 Jun 2024 04:21:28 -0700 Subject: [PATCH 1655/2101] fix potential hang (#6976) Co-authored-by: Samuel Sieb --- esphome/components/gpio/one_wire/gpio_one_wire.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/esphome/components/gpio/one_wire/gpio_one_wire.cpp b/esphome/components/gpio/one_wire/gpio_one_wire.cpp index b4e69e975a..36eaf2160a 100644 --- a/esphome/components/gpio/one_wire/gpio_one_wire.cpp +++ b/esphome/components/gpio/one_wire/gpio_one_wire.cpp @@ -94,13 +94,15 @@ bool HOT IRAM_ATTR GPIOOneWireBus::read_bit_() { // measure from start value directly, to get best accurate timing no matter // how long pin_mode/delayMicroseconds took - delayMicroseconds(12 - (micros() - start)); + uint32_t now = micros(); + if (now - start < 12) + delayMicroseconds(12 - (now - start)); // sample bus to read bit from peer bool r = pin_.digital_read(); // read slot is at least 60µs; get as close to 60µs to spend less time with interrupts locked - uint32_t now = micros(); + now = micros(); if (now - start < 60) delayMicroseconds(60 - (now - start)); From 78450da6f33366735aeb8da0521c2791160ac12d Mon Sep 17 00:00:00 2001 From: Sergey Dudanov Date: Tue, 25 Jun 2024 00:04:58 +0400 Subject: [PATCH 1656/2101] [midea] fix fan speed compatibility with some models (#6978) --- esphome/components/midea/climate.py | 2 +- platformio.ini | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/midea/climate.py b/esphome/components/midea/climate.py index 83540a061a..e5612796a3 100644 --- a/esphome/components/midea/climate.py +++ b/esphome/components/midea/climate.py @@ -293,4 +293,4 @@ 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)) - cg.add_library("dudanov/MideaUART", "1.1.8") + cg.add_library("dudanov/MideaUART", "1.1.9") diff --git a/platformio.ini b/platformio.ini index ee82dee243..e106114ff6 100644 --- a/platformio.ini +++ b/platformio.ini @@ -64,7 +64,7 @@ lib_deps = freekode/TM1651@1.0.1 ; tm1651 glmnet/Dsmr@0.7 ; dsmr rweather/Crypto@0.4.0 ; dsmr - dudanov/MideaUART@1.1.8 ; midea + dudanov/MideaUART@1.1.9 ; midea tonia/HeatpumpIR@1.0.23 ; heatpumpir build_flags = ${common.build_flags} From a21dab334c48da775189085d7206fe88ecdaa3a5 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 21 Jun 2024 13:09:00 +1200 Subject: [PATCH 1657/2101] [core] Fix package merging with lists of primitives (#6952) --- esphome/config_helpers.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/esphome/config_helpers.py b/esphome/config_helpers.py index b5e0b26143..54242bc259 100644 --- a/esphome/config_helpers.py +++ b/esphome/config_helpers.py @@ -58,17 +58,21 @@ def merge_config(full_old, full_new): ids = { v_id: i for i, v in enumerate(res) - if (v_id := v.get(CONF_ID)) and isinstance(v_id, str) + if isinstance(v, dict) + and (v_id := v.get(CONF_ID)) + and isinstance(v_id, str) } extend_ids = { v_id.value: i for i, v in enumerate(res) - if (v_id := v.get(CONF_ID)) and isinstance(v_id, Extend) + if isinstance(v, dict) + and (v_id := v.get(CONF_ID)) + and isinstance(v_id, Extend) } ids_to_delete = [] for v in new: - if new_id := v.get(CONF_ID): + if isinstance(v, dict) and (new_id := v.get(CONF_ID)): if isinstance(new_id, Extend): new_id = new_id.value if new_id in ids: From 7dbc20b776c56c6cce910e25fe6f12871e9d9b47 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 21 Jun 2024 14:59:52 +1200 Subject: [PATCH 1658/2101] [update] Set entity_category to config & Publish state to logs (#6954) --- esphome/components/update/__init__.py | 5 ++++ esphome/components/update/update_entity.cpp | 26 +++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/esphome/components/update/__init__.py b/esphome/components/update/__init__.py index ea1cf778b6..20a9373a06 100644 --- a/esphome/components/update/__init__.py +++ b/esphome/components/update/__init__.py @@ -4,11 +4,13 @@ import esphome.config_validation as cv import esphome.codegen as cg from esphome.const import ( CONF_DEVICE_CLASS, + CONF_ENTITY_CATEGORY, CONF_ID, CONF_MQTT_ID, CONF_WEB_SERVER_ID, DEVICE_CLASS_EMPTY, DEVICE_CLASS_FIRMWARE, + ENTITY_CATEGORY_CONFIG, ) from esphome.core import CORE, coroutine_with_priority from esphome.cpp_helpers import setup_entity @@ -41,6 +43,9 @@ UPDATE_SCHEMA = ( cv.Optional(CONF_ON_UPDATE_AVAILABLE): automation.validate_automation( single=True ), + cv.Optional( + CONF_ENTITY_CATEGORY, default=ENTITY_CATEGORY_CONFIG + ): cv.entity_category, } ) ) diff --git a/esphome/components/update/update_entity.cpp b/esphome/components/update/update_entity.cpp index 501cb6635f..ed9a0480d8 100644 --- a/esphome/components/update/update_entity.cpp +++ b/esphome/components/update/update_entity.cpp @@ -1,9 +1,35 @@ #include "update_entity.h" +#include "esphome/core/log.h" + namespace esphome { namespace update { +static const char *const TAG = "update"; + void UpdateEntity::publish_state() { + ESP_LOGD(TAG, "'%s' - Publishing:", this->name_.c_str()); + ESP_LOGD(TAG, " Current Version: %s", 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()); + } + if (!this->update_info_.firmware_url.empty()) { + ESP_LOGD(TAG, " Firmware URL: %s", this->update_info_.firmware_url.c_str()); + } + + ESP_LOGD(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()); + } + if (!this->update_info_.release_url.empty()) { + ESP_LOGD(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); + } + this->has_state_ = true; this->state_callback_.call(); } From ae2962259ec004777ecfb96cd409bba85b56e0d4 Mon Sep 17 00:00:00 2001 From: "Kevin P. Fleming" Date: Fri, 21 Jun 2024 17:18:43 -0400 Subject: [PATCH 1659/2101] Fix infinite loop in http_request for ESP-IDF. (#6963) --- esphome/components/http_request/http_request_idf.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/http_request/http_request_idf.cpp b/esphome/components/http_request/http_request_idf.cpp index 138e0438f4..d6fac7a133 100644 --- a/esphome/components/http_request/http_request_idf.cpp +++ b/esphome/components/http_request/http_request_idf.cpp @@ -90,7 +90,7 @@ std::shared_ptr HttpRequestIDF::start(std::string url, std::strin int write_left = body_len; int write_index = 0; const char *buf = body.c_str(); - while (body_len > 0) { + while (write_left > 0) { int written = esp_http_client_write(client, buf + write_index, write_left); if (written < 0) { err = ESP_FAIL; From 96d63de292eba3fa4c6c820faf1b482e0fff205e Mon Sep 17 00:00:00 2001 From: "Kevin P. Fleming" Date: Fri, 21 Jun 2024 17:28:11 -0400 Subject: [PATCH 1660/2101] ESP-IDF 4.x expects seconds for esp_task_wdt_init(), not milliseconds. (#6964) --- esphome/components/http_request/watchdog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/http_request/watchdog.cpp b/esphome/components/http_request/watchdog.cpp index e609feb4dd..a8519c59ed 100644 --- a/esphome/components/http_request/watchdog.cpp +++ b/esphome/components/http_request/watchdog.cpp @@ -46,7 +46,7 @@ void WatchdogManager::set_timeout_(uint32_t timeout_ms) { }; esp_task_wdt_reconfigure(&wdt_config); #else - esp_task_wdt_init(timeout_ms, true); + esp_task_wdt_init(timeout_ms / 1000, true); #endif // ESP_IDF_VERSION_MAJOR #endif // USE_ESP32 From 0d3cf5cb7809e13de16c5edb75c0437705efa4ce Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Sat, 22 Jun 2024 04:57:27 -0700 Subject: [PATCH 1661/2101] Onewire (#6967) * retry scan * setup pin and log retries * fix retries * remove retries --------- Co-authored-by: Samuel Sieb --- esphome/components/gpio/one_wire/gpio_one_wire.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/esphome/components/gpio/one_wire/gpio_one_wire.cpp b/esphome/components/gpio/one_wire/gpio_one_wire.cpp index 34c2cf3c29..b4e69e975a 100644 --- a/esphome/components/gpio/one_wire/gpio_one_wire.cpp +++ b/esphome/components/gpio/one_wire/gpio_one_wire.cpp @@ -9,6 +9,10 @@ static const char *const TAG = "gpio.one_wire"; void GPIOOneWireBus::setup() { ESP_LOGCONFIG(TAG, "Setting up 1-wire bus..."); + this->t_pin_->setup(); + // clear bus with 480µs high, otherwise initial reset in search might fail + this->t_pin_->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP); + delayMicroseconds(480); this->search(); } From e39961f7f1c329ae70422ded669b548c43226d0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Poczkodi?= Date: Mon, 24 Jun 2024 06:32:20 +0200 Subject: [PATCH 1662/2101] [http_request] memory leak fix (#6973) --- esphome/components/http_request/http_request.h | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/http_request/http_request.h b/esphome/components/http_request/http_request.h index df6bc7dea7..6281adddb6 100644 --- a/esphome/components/http_request/http_request.h +++ b/esphome/components/http_request/http_request.h @@ -149,6 +149,7 @@ template class HttpRequestSendAction : public Action { } response_body.reserve(read_index); response_body.assign((char *) buf, read_index); + allocator.deallocate(buf, max_length); } } From 5bd5b777a6ff949f539b9e58ed537b223e40020e Mon Sep 17 00:00:00 2001 From: Brian Kaufman Date: Sun, 23 Jun 2024 21:54:30 -0700 Subject: [PATCH 1663/2101] Await cg.get_variable in Update component (#6974) --- esphome/components/update/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/update/__init__.py b/esphome/components/update/__init__.py index 20a9373a06..45bf082fa4 100644 --- a/esphome/components/update/__init__.py +++ b/esphome/components/update/__init__.py @@ -69,7 +69,7 @@ async def setup_update_core_(var, config): await mqtt.register_mqtt_component(mqtt_, config) if web_server_id_config := config.get(CONF_WEB_SERVER_ID): - web_server_ = cg.get_variable(web_server_id_config) + web_server_ = await cg.get_variable(web_server_id_config) web_server.add_entity_to_sorting_list(web_server_, var, config) From c5aae8ee254f3e16ed204912457637ba62743818 Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Mon, 24 Jun 2024 04:21:28 -0700 Subject: [PATCH 1664/2101] fix potential hang (#6976) Co-authored-by: Samuel Sieb --- esphome/components/gpio/one_wire/gpio_one_wire.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/esphome/components/gpio/one_wire/gpio_one_wire.cpp b/esphome/components/gpio/one_wire/gpio_one_wire.cpp index b4e69e975a..36eaf2160a 100644 --- a/esphome/components/gpio/one_wire/gpio_one_wire.cpp +++ b/esphome/components/gpio/one_wire/gpio_one_wire.cpp @@ -94,13 +94,15 @@ bool HOT IRAM_ATTR GPIOOneWireBus::read_bit_() { // measure from start value directly, to get best accurate timing no matter // how long pin_mode/delayMicroseconds took - delayMicroseconds(12 - (micros() - start)); + uint32_t now = micros(); + if (now - start < 12) + delayMicroseconds(12 - (now - start)); // sample bus to read bit from peer bool r = pin_.digital_read(); // read slot is at least 60µs; get as close to 60µs to spend less time with interrupts locked - uint32_t now = micros(); + now = micros(); if (now - start < 60) delayMicroseconds(60 - (now - start)); From a6e1ef2dd144dff244800fa00624285c8bd6e70e Mon Sep 17 00:00:00 2001 From: Sergey Dudanov Date: Tue, 25 Jun 2024 00:04:58 +0400 Subject: [PATCH 1665/2101] [midea] fix fan speed compatibility with some models (#6978) --- esphome/components/midea/climate.py | 2 +- platformio.ini | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/midea/climate.py b/esphome/components/midea/climate.py index 83540a061a..e5612796a3 100644 --- a/esphome/components/midea/climate.py +++ b/esphome/components/midea/climate.py @@ -293,4 +293,4 @@ 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)) - cg.add_library("dudanov/MideaUART", "1.1.8") + cg.add_library("dudanov/MideaUART", "1.1.9") diff --git a/platformio.ini b/platformio.ini index 6b34b2f05d..14e9ea9fc6 100644 --- a/platformio.ini +++ b/platformio.ini @@ -64,7 +64,7 @@ lib_deps = freekode/TM1651@1.0.1 ; tm1651 glmnet/Dsmr@0.7 ; dsmr rweather/Crypto@0.4.0 ; dsmr - dudanov/MideaUART@1.1.8 ; midea + dudanov/MideaUART@1.1.9 ; midea tonia/HeatpumpIR@1.0.23 ; heatpumpir build_flags = ${common.build_flags} From 09a947beaa45b45f71dbfb3aac06de2b138abebf Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 25 Jun 2024 08:57:38 +1200 Subject: [PATCH 1666/2101] Bump version to 2024.6.2 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 3b3bdd1a17..cde917ca98 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.6.1" +__version__ = "2024.6.2" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 11b8e2e1af4af190f407cdd0922f778899e19412 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 25 Jun 2024 16:43:30 +1200 Subject: [PATCH 1667/2101] [core] Add script to extract actions, conditions, and pin_providers (#6929) --- script/extract_automations.py | 25 +++++++++++++++++++++++ script/list-components.py | 38 ++++++++++++++++++----------------- 2 files changed, 45 insertions(+), 18 deletions(-) create mode 100755 script/extract_automations.py diff --git a/script/extract_automations.py b/script/extract_automations.py new file mode 100755 index 0000000000..943eb7110a --- /dev/null +++ b/script/extract_automations.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 + +import json + +from helpers import git_ls_files + +from esphome.automation import ACTION_REGISTRY, CONDITION_REGISTRY +from esphome.pins import PIN_SCHEMA_REGISTRY + +list_components = __import__("list-components") + + +if __name__ == "__main__": + files = git_ls_files() + files = filter(list_components.filter_component_files, files) + + components = list_components.get_components(files, True) + + dump = { + "actions": sorted(list(ACTION_REGISTRY.keys())), + "conditions": sorted(list(CONDITION_REGISTRY.keys())), + "pin_providers": sorted(list(PIN_SCHEMA_REGISTRY.keys())), + } + + print(json.dumps(dump, indent=2)) diff --git a/script/list-components.py b/script/list-components.py index 5b5fa5811f..4eccdbf96c 100755 --- a/script/list-components.py +++ b/script/list-components.py @@ -50,6 +50,7 @@ def create_components_graph(): {KEY_TARGET_FRAMEWORK: "arduino", KEY_TARGET_PLATFORM: None}, {KEY_TARGET_FRAMEWORK: "esp-idf", KEY_TARGET_PLATFORM: None}, {KEY_TARGET_FRAMEWORK: None, KEY_TARGET_PLATFORM: PLATFORM_ESP32}, + {KEY_TARGET_FRAMEWORK: None, KEY_TARGET_PLATFORM: PLATFORM_ESP8266}, ] CORE.data[KEY_CORE] = TARGET_CONFIGURATIONS[0] @@ -119,6 +120,23 @@ def find_children_of_component(components_graph, component_name, depth=0): return list(set(children)) +def get_components(files: list[str], get_dependencies: bool = False): + components = extract_component_names_array_from_files_array(files) + + if get_dependencies: + components_graph = create_components_graph() + + all_components = components.copy() + for c in components: + all_components.extend(find_children_of_component(components_graph, c)) + # Remove duplicate values + all_changed_components = list(set(all_components)) + + return sorted(all_changed_components) + + return sorted(components) + + def main(): parser = argparse.ArgumentParser() parser.add_argument( @@ -142,24 +160,8 @@ def main(): changed = changed_files() files = [f for f in files if f in changed] - components = extract_component_names_array_from_files_array(files) - - if args.changed: - components_graph = create_components_graph() - - all_changed_components = components.copy() - for c in components: - all_changed_components.extend( - find_children_of_component(components_graph, c) - ) - # Remove duplicate values - all_changed_components = list(set(all_changed_components)) - - for c in sorted(all_changed_components): - print(c) - else: - for c in sorted(components): - print(c) + for c in get_components(files, args.changed): + print(c) if __name__ == "__main__": From 8a25bedaf9323c6e1f62a9324b46344d9292ed24 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 25 Jun 2024 17:42:55 +1200 Subject: [PATCH 1668/2101] [external_files] Move common ``download_content`` function to ``external_files.py`` (#6982) --- esphome/components/font/__init__.py | 30 ++------------------------- esphome/components/image/__init__.py | 31 ++-------------------------- esphome/external_files.py | 26 +++++++++++++++++++++++ 3 files changed, 30 insertions(+), 57 deletions(-) diff --git a/esphome/components/font/__init__.py b/esphome/components/font/__init__.py index b3a5beb199..7e4674ffda 100644 --- a/esphome/components/font/__init__.py +++ b/esphome/components/font/__init__.py @@ -17,7 +17,6 @@ from esphome.helpers import ( cpp_string_escape, ) from esphome.const import ( - __version__, CONF_FAMILY, CONF_FILE, CONF_GLYPHS, @@ -185,31 +184,6 @@ def get_font_path(value, type) -> Path: return None -def download_content(url: str, path: Path) -> None: - if not external_files.has_remote_file_changed(url, path): - _LOGGER.debug("Remote file has not changed %s", url) - return - - _LOGGER.debug( - "Remote file has changed, downloading from %s to %s", - url, - path, - ) - - try: - req = requests.get( - url, - timeout=external_files.NETWORK_TIMEOUT, - headers={"User-agent": f"ESPHome/{__version__} (https://esphome.io)"}, - ) - req.raise_for_status() - except requests.exceptions.RequestException as e: - raise cv.Invalid(f"Could not download from {url}: {e}") - - path.parent.mkdir(parents=True, exist_ok=True) - path.write_bytes(req.content) - - def download_gfont(value): name = ( f"{value[CONF_FAMILY]}:ital,wght@{int(value[CONF_ITALIC])},{value[CONF_WEIGHT]}" @@ -236,7 +210,7 @@ def download_gfont(value): ttf_url = match.group(1) _LOGGER.debug("download_gfont: ttf_url=%s", ttf_url) - download_content(ttf_url, path) + external_files.download_content(ttf_url, path) return value @@ -244,7 +218,7 @@ def download_web_font(value): url = value[CONF_URL] path = get_font_path(value, TYPE_WEB) - download_content(url, path) + external_files.download_content(url, path) _LOGGER.debug("download_web_font: path=%s", path) return value diff --git a/esphome/components/image/__init__.py b/esphome/components/image/__init__.py index c275136427..e5a205f1e0 100644 --- a/esphome/components/image/__init__.py +++ b/esphome/components/image/__init__.py @@ -6,7 +6,6 @@ import hashlib import io from pathlib import Path import re -import requests from magic import Magic from esphome import core @@ -15,7 +14,6 @@ from esphome import external_files import esphome.config_validation as cv import esphome.codegen as cg from esphome.const import ( - __version__, CONF_DITHER, CONF_FILE, CONF_ICON, @@ -75,31 +73,6 @@ def compute_local_image_path(value: dict) -> Path: return base_dir / key -def download_content(url: str, path: Path) -> None: - if not external_files.has_remote_file_changed(url, path): - _LOGGER.debug("Remote file has not changed %s", url) - return - - _LOGGER.debug( - "Remote file has changed, downloading from %s to %s", - url, - path, - ) - - try: - req = requests.get( - url, - timeout=IMAGE_DOWNLOAD_TIMEOUT, - headers={"User-agent": f"ESPHome/{__version__} (https://esphome.io)"}, - ) - req.raise_for_status() - except requests.exceptions.RequestException as e: - raise cv.Invalid(f"Could not download from {url}: {e}") - - path.parent.mkdir(parents=True, exist_ok=True) - path.write_bytes(req.content) - - def download_mdi(value): validate_cairosvg_installed(value) @@ -108,7 +81,7 @@ def download_mdi(value): url = f"https://raw.githubusercontent.com/Templarian/MaterialDesign/master/svg/{mdi_id}.svg" - download_content(url, path) + external_files.download_content(url, path, IMAGE_DOWNLOAD_TIMEOUT) return value @@ -117,7 +90,7 @@ def download_image(value): url = value[CONF_URL] path = compute_local_image_path(value) - download_content(url, path) + external_files.download_content(url, path, IMAGE_DOWNLOAD_TIMEOUT) return value diff --git a/esphome/external_files.py b/esphome/external_files.py index a1422d02b1..f8eb1dcabe 100644 --- a/esphome/external_files.py +++ b/esphome/external_files.py @@ -7,6 +7,7 @@ from datetime import datetime import requests import esphome.config_validation as cv from esphome.core import CORE, TimePeriodSeconds +from esphome.const import __version__ _LOGGER = logging.getLogger(__name__) CODEOWNERS = ["@landonr"] @@ -75,3 +76,28 @@ def compute_local_file_dir(domain: str) -> Path: base_directory.mkdir(parents=True, exist_ok=True) return base_directory + + +def download_content(url: str, path: Path, timeout=NETWORK_TIMEOUT) -> None: + if not has_remote_file_changed(url, path): + _LOGGER.debug("Remote file has not changed %s", url) + return + + _LOGGER.debug( + "Remote file has changed, downloading from %s to %s", + url, + path, + ) + + try: + req = requests.get( + url, + timeout=timeout, + headers={"User-agent": f"ESPHome/{__version__} (https://esphome.io)"}, + ) + req.raise_for_status() + except requests.exceptions.RequestException as e: + raise cv.Invalid(f"Could not download from {url}: {e}") + + path.parent.mkdir(parents=True, exist_ok=True) + path.write_bytes(req.content) From c9a0daf4b6435533bf14594c0b579f829719aa15 Mon Sep 17 00:00:00 2001 From: Markus <974709+Links2004@users.noreply.github.com> Date: Tue, 25 Jun 2024 10:05:37 +0200 Subject: [PATCH 1669/2101] Do not build mDNS when mDNS is disabled via yaml (#6979) --- esphome/components/mdns/__init__.py | 6 +++--- esphome/components/mdns/mdns_component.cpp | 4 +++- esphome/components/mdns/mdns_component.h | 4 +++- esphome/components/mdns/mdns_esp32.cpp | 3 ++- esphome/components/mdns/mdns_esp8266.cpp | 3 ++- esphome/components/mdns/mdns_host.cpp | 3 ++- esphome/components/mdns/mdns_libretiny.cpp | 3 ++- esphome/components/mdns/mdns_rp2040.cpp | 3 ++- 8 files changed, 19 insertions(+), 10 deletions(-) diff --git a/esphome/components/mdns/__init__.py b/esphome/components/mdns/__init__.py index 82cf087fdc..fb90986314 100644 --- a/esphome/components/mdns/__init__.py +++ b/esphome/components/mdns/__init__.py @@ -74,6 +74,9 @@ def mdns_service( @coroutine_with_priority(55.0) async def to_code(config): + if config[CONF_DISABLED] is True: + return + if CORE.using_arduino: if CORE.is_esp32: cg.add_library("ESPmDNS", None) @@ -92,9 +95,6 @@ async def to_code(config): path="components/mdns", ) - if config[CONF_DISABLED]: - return - cg.add_define("USE_MDNS") var = cg.new_Pvariable(config[CONF_ID]) diff --git a/esphome/components/mdns/mdns_component.cpp b/esphome/components/mdns/mdns_component.cpp index e2e562670b..2fc09330cd 100644 --- a/esphome/components/mdns/mdns_component.cpp +++ b/esphome/components/mdns/mdns_component.cpp @@ -1,5 +1,6 @@ -#include "mdns_component.h" #include "esphome/core/defines.h" +#ifdef USE_MDNS +#include "mdns_component.h" #include "esphome/core/version.h" #include "esphome/core/application.h" #include "esphome/core/log.h" @@ -125,3 +126,4 @@ void MDNSComponent::dump_config() { } // namespace mdns } // namespace esphome +#endif diff --git a/esphome/components/mdns/mdns_component.h b/esphome/components/mdns/mdns_component.h index b2cb10db62..dfb5b72292 100644 --- a/esphome/components/mdns/mdns_component.h +++ b/esphome/components/mdns/mdns_component.h @@ -1,5 +1,6 @@ #pragma once - +#include "esphome/core/defines.h" +#ifdef USE_MDNS #include #include #include "esphome/core/component.h" @@ -46,3 +47,4 @@ class MDNSComponent : public Component { } // namespace mdns } // namespace esphome +#endif diff --git a/esphome/components/mdns/mdns_esp32.cpp b/esphome/components/mdns/mdns_esp32.cpp index 6081c96637..8006eb27f1 100644 --- a/esphome/components/mdns/mdns_esp32.cpp +++ b/esphome/components/mdns/mdns_esp32.cpp @@ -1,4 +1,5 @@ -#ifdef USE_ESP32 +#include "esphome/core/defines.h" +#if defined(USE_ESP32) && defined(USE_MDNS) #include #include diff --git a/esphome/components/mdns/mdns_esp8266.cpp b/esphome/components/mdns/mdns_esp8266.cpp index 5ff1b86341..7b6e7ec448 100644 --- a/esphome/components/mdns/mdns_esp8266.cpp +++ b/esphome/components/mdns/mdns_esp8266.cpp @@ -1,4 +1,5 @@ -#if defined(USE_ESP8266) && defined(USE_ARDUINO) +#include "esphome/core/defines.h" +#if defined(USE_ESP8266) && defined(USE_ARDUINO) && defined(USE_MDNS) #include #include "esphome/components/network/ip_address.h" diff --git a/esphome/components/mdns/mdns_host.cpp b/esphome/components/mdns/mdns_host.cpp index 3f89146f02..78767ed136 100644 --- a/esphome/components/mdns/mdns_host.cpp +++ b/esphome/components/mdns/mdns_host.cpp @@ -1,4 +1,5 @@ -#ifdef USE_HOST +#include "esphome/core/defines.h" +#if defined(USE_HOST) && defined(USE_MDNS) #include "esphome/components/network/ip_address.h" #include "esphome/components/network/util.h" diff --git a/esphome/components/mdns/mdns_libretiny.cpp b/esphome/components/mdns/mdns_libretiny.cpp index ccb79c88b9..c9a9a289dd 100644 --- a/esphome/components/mdns/mdns_libretiny.cpp +++ b/esphome/components/mdns/mdns_libretiny.cpp @@ -1,4 +1,5 @@ -#ifdef USE_LIBRETINY +#include "esphome/core/defines.h" +#if defined(USE_LIBRETINY) && defined(USE_MDNS) #include "esphome/components/network/ip_address.h" #include "esphome/components/network/util.h" diff --git a/esphome/components/mdns/mdns_rp2040.cpp b/esphome/components/mdns/mdns_rp2040.cpp index 56afd6f5e1..89e668ee59 100644 --- a/esphome/components/mdns/mdns_rp2040.cpp +++ b/esphome/components/mdns/mdns_rp2040.cpp @@ -1,4 +1,5 @@ -#ifdef USE_RP2040 +#include "esphome/core/defines.h" +#if defined(USE_RP2040) && defined(USE_MDNS) #include "esphome/components/network/ip_address.h" #include "esphome/components/network/util.h" From 481cf7384ae081e2cabe568cba31a6a6dde68754 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 25 Jun 2024 21:07:19 +1200 Subject: [PATCH 1670/2101] [safe_mode] Set safe mode core data in disabled cases (#6983) --- esphome/components/safe_mode/__init__.py | 25 ++++++++++++------------ 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/esphome/components/safe_mode/__init__.py b/esphome/components/safe_mode/__init__.py index 881937890d..185c0e70b1 100644 --- a/esphome/components/safe_mode/__init__.py +++ b/esphome/components/safe_mode/__init__.py @@ -56,21 +56,20 @@ CONFIG_SCHEMA = cv.All( @coroutine_with_priority(50.0) async def to_code(config): - if config[CONF_DISABLED]: - return + if not config[CONF_DISABLED]: + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, 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) - for conf in config.get(CONF_ON_SAFE_MODE, []): - 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], + config[CONF_REBOOT_TIMEOUT], + config[CONF_BOOT_IS_GOOD_AFTER], + ) + cg.add(RawExpression(f"if ({condition}) return")) - condition = var.should_enter_safe_mode( - config[CONF_NUM_ATTEMPTS], - config[CONF_REBOOT_TIMEOUT], - config[CONF_BOOT_IS_GOOD_AFTER], - ) - cg.add(RawExpression(f"if ({condition}) return")) CORE.data[CONF_SAFE_MODE] = {} CORE.data[CONF_SAFE_MODE][KEY_PAST_SAFE_MODE] = True From fb9844463b53d3aee6fd5e67bd5f71a7568c6a98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=2E=20=C3=81rkosi=20R=C3=B3bert?= Date: Tue, 25 Jun 2024 11:08:57 +0200 Subject: [PATCH 1671/2101] Bump HeatpumpIR and IRremoteESP8266 (#6948) --- esphome/components/heatpumpir/climate.py | 10 ++++++++-- esphome/components/heatpumpir/heatpumpir.cpp | 6 ++++++ esphome/components/heatpumpir/heatpumpir.h | 6 ++++++ platformio.ini | 6 +++--- 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/esphome/components/heatpumpir/climate.py b/esphome/components/heatpumpir/climate.py index 8af4ca590f..b86d405b7e 100644 --- a/esphome/components/heatpumpir/climate.py +++ b/esphome/components/heatpumpir/climate.py @@ -34,6 +34,7 @@ PROTOCOLS = { "greeyan": Protocol.PROTOCOL_GREEYAN, "greeyac": Protocol.PROTOCOL_GREEYAC, "greeyt": Protocol.PROTOCOL_GREEYT, + "greeyap": Protocol.PROTOCOL_GREEYAP, "hisense_aud": Protocol.PROTOCOL_HISENSE_AUD, "hitachi": Protocol.PROTOCOL_HITACHI, "hyundai": Protocol.PROTOCOL_HYUNDAI, @@ -61,6 +62,11 @@ PROTOCOLS = { "toshiba_daiseikai": Protocol.PROTOCOL_TOSHIBA_DAISEIKAI, "toshiba": Protocol.PROTOCOL_TOSHIBA, "zhlt01": Protocol.PROTOCOL_ZHLT01, + "nibe": Protocol.PROTOCOL_NIBE, + "carrier_qlima_1": Protocol.PROTOCOL_QLIMA_1, + "carrier_qlima_2": Protocol.PROTOCOL_QLIMA_2, + "samsung_aqv12msan": Protocol.PROTOCOL_SAMSUNG_AQV12MSAN, + "zhjg01": Protocol.PROTOCOL_ZHJG01, } CONF_HORIZONTAL_DEFAULT = "horizontal_default" @@ -116,7 +122,7 @@ 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.23") + cg.add_library("tonia/HeatpumpIR", "1.0.26") if CORE.is_esp8266 or CORE.is_esp32: - cg.add_library("crankyoldgit/IRremoteESP8266", "2.8.4") + cg.add_library("crankyoldgit/IRremoteESP8266", "2.8.6") diff --git a/esphome/components/heatpumpir/heatpumpir.cpp b/esphome/components/heatpumpir/heatpumpir.cpp index 5e7237b63c..22a5779c8d 100644 --- a/esphome/components/heatpumpir/heatpumpir.cpp +++ b/esphome/components/heatpumpir/heatpumpir.cpp @@ -28,6 +28,7 @@ const std::map> PROTOCOL_CONSTRUCTOR_MAP {PROTOCOL_GREEYAN, []() { return new GreeYANHeatpumpIR(); }}, // NOLINT {PROTOCOL_GREEYAC, []() { return new GreeYACHeatpumpIR(); }}, // NOLINT {PROTOCOL_GREEYT, []() { return new GreeYTHeatpumpIR(); }}, // NOLINT + {PROTOCOL_GREEYAP, []() { return new GreeYAPHeatpumpIR(); }}, // NOLINT {PROTOCOL_HISENSE_AUD, []() { return new HisenseHeatpumpIR(); }}, // NOLINT {PROTOCOL_HITACHI, []() { return new HitachiHeatpumpIR(); }}, // NOLINT {PROTOCOL_HYUNDAI, []() { return new HyundaiHeatpumpIR(); }}, // NOLINT @@ -55,6 +56,11 @@ const std::map> PROTOCOL_CONSTRUCTOR_MAP {PROTOCOL_TOSHIBA_DAISEIKAI, []() { return new ToshibaDaiseikaiHeatpumpIR(); }}, // NOLINT {PROTOCOL_TOSHIBA, []() { return new ToshibaHeatpumpIR(); }}, // NOLINT {PROTOCOL_ZHLT01, []() { return new ZHLT01HeatpumpIR(); }}, // NOLINT + {PROTOCOL_NIBE, []() { return new NibeHeatpumpIR(); }}, // NOLINT + {PROTOCOL_QLIMA_1, []() { return new Qlima1HeatpumpIR(); }}, // NOLINT + {PROTOCOL_QLIMA_2, []() { return new Qlima2HeatpumpIR(); }}, // NOLINT + {PROTOCOL_SAMSUNG_AQV12MSAN, []() { return new SamsungAQV12MSANHeatpumpIR(); }}, // NOLINT + {PROTOCOL_ZHJG01, []() { return new ZHJG01HeatpumpIR(); }}, // NOLINT }; void HeatpumpIRClimate::setup() { diff --git a/esphome/components/heatpumpir/heatpumpir.h b/esphome/components/heatpumpir/heatpumpir.h index e8b03b4c26..0e6ea2218f 100644 --- a/esphome/components/heatpumpir/heatpumpir.h +++ b/esphome/components/heatpumpir/heatpumpir.h @@ -28,6 +28,7 @@ enum Protocol { PROTOCOL_GREEYAN, PROTOCOL_GREEYAC, PROTOCOL_GREEYT, + PROTOCOL_GREEYAP, PROTOCOL_HISENSE_AUD, PROTOCOL_HITACHI, PROTOCOL_HYUNDAI, @@ -55,6 +56,11 @@ enum Protocol { PROTOCOL_TOSHIBA_DAISEIKAI, PROTOCOL_TOSHIBA, PROTOCOL_ZHLT01, + PROTOCOL_NIBE, + PROTOCOL_QLIMA_1, + PROTOCOL_QLIMA_2, + PROTOCOL_SAMSUNG_AQV12MSAN, + PROTOCOL_ZHJG01, }; // Simple enum to represent horizontal directios diff --git a/platformio.ini b/platformio.ini index e106114ff6..e2e66bf672 100644 --- a/platformio.ini +++ b/platformio.ini @@ -65,7 +65,7 @@ lib_deps = glmnet/Dsmr@0.7 ; dsmr rweather/Crypto@0.4.0 ; dsmr dudanov/MideaUART@1.1.9 ; midea - tonia/HeatpumpIR@1.0.23 ; heatpumpir + tonia/HeatpumpIR@1.0.26 ; heatpumpir build_flags = ${common.build_flags} -DUSE_ARDUINO @@ -93,7 +93,7 @@ lib_deps = ESP8266HTTPClient ; http_request (Arduino built-in) ESP8266mDNS ; mdns (Arduino built-in) DNSServer ; captive_portal (Arduino built-in) - crankyoldgit/IRremoteESP8266@~2.8.4 ; heatpumpir + crankyoldgit/IRremoteESP8266@2.8.6 ; heatpumpir droscy/esp_wireguard@0.4.1 ; wireguard build_flags = ${common:arduino.build_flags} @@ -123,7 +123,7 @@ lib_deps = ESPmDNS ; mdns (Arduino built-in) DNSServer ; captive_portal (Arduino built-in) esphome/ESP32-audioI2S@2.0.7 ; i2s_audio - crankyoldgit/IRremoteESP8266@~2.8.4 ; heatpumpir + crankyoldgit/IRremoteESP8266@2.8.6 ; heatpumpir droscy/esp_wireguard@0.4.1 ; wireguard build_flags = ${common:arduino.build_flags} From d8a5c1ea0c440ff488a2b6c1cd84f8440ab81e51 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Tue, 25 Jun 2024 15:57:15 -0500 Subject: [PATCH 1672/2101] [ota-esphome] Validate for multiple esphome ota instances (#6984) --- esphome/components/esphome/ota/__init__.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/esphome/components/esphome/ota/__init__.py b/esphome/components/esphome/ota/__init__.py index c5903974c2..88e729f230 100644 --- a/esphome/components/esphome/ota/__init__.py +++ b/esphome/components/esphome/ota/__init__.py @@ -1,10 +1,14 @@ import esphome.codegen as cg import esphome.config_validation as cv +import esphome.final_validate as fv from esphome.components.ota import BASE_OTA_SCHEMA, ota_to_code, OTAComponent from esphome.const import ( + CONF_ESPHOME, CONF_ID, CONF_NUM_ATTEMPTS, + CONF_OTA, CONF_PASSWORD, + CONF_PLATFORM, CONF_PORT, CONF_REBOOT_TIMEOUT, CONF_SAFE_MODE, @@ -21,6 +25,19 @@ esphome = cg.esphome_ns.namespace("esphome") ESPHomeOTAComponent = esphome.class_("ESPHomeOTAComponent", OTAComponent) +def ota_esphome_final_validate(config): + fconf = fv.full_config.get()[CONF_OTA] + used_ports = [] + for ota_conf in fconf: + if ota_conf.get(CONF_PLATFORM) == CONF_ESPHOME: + if (plat_port := ota_conf.get(CONF_PORT)) not in used_ports: + used_ports.append(plat_port) + else: + raise cv.Invalid( + f"Only one instance of the {CONF_ESPHOME} {CONF_OTA} {CONF_PLATFORM} is allowed per port. Note that this error may result from OTA specified in packages" + ) + + CONFIG_SCHEMA = ( cv.Schema( { @@ -50,6 +67,8 @@ CONFIG_SCHEMA = ( .extend(cv.COMPONENT_SCHEMA) ) +FINAL_VALIDATE_SCHEMA = ota_esphome_final_validate + @coroutine_with_priority(52.0) async def to_code(config): From 0179358f9cbb212d30627999a2f7233ff18e12ea Mon Sep 17 00:00:00 2001 From: "Kevin P. Fleming" Date: Tue, 25 Jun 2024 19:50:54 -0400 Subject: [PATCH 1673/2101] Improve 'body' handling in http_request on_response triggers (#6968) --- esphome/codegen.py | 1 + esphome/components/http_request/__init__.py | 2 +- .../components/http_request/http_request.h | 19 ++++++++++++++----- esphome/cpp_types.py | 1 + 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/esphome/codegen.py b/esphome/codegen.py index b552490129..6b000b53a1 100644 --- a/esphome/codegen.py +++ b/esphome/codegen.py @@ -60,6 +60,7 @@ from esphome.cpp_types import ( # noqa std_ns, std_shared_ptr, std_string, + std_string_ref, std_vector, uint8, uint16, diff --git a/esphome/components/http_request/__init__.py b/esphome/components/http_request/__init__.py index 37487ec9a7..ade7024bed 100644 --- a/esphome/components/http_request/__init__.py +++ b/esphome/components/http_request/__init__.py @@ -257,7 +257,7 @@ async def http_request_action_to_code(config, action_id, template_arg, args): trigger, [ (cg.std_shared_ptr.template(HttpContainer), "response"), - (cg.std_string, "body"), + (cg.std_string_ref, "body"), ], conf, ) diff --git a/esphome/components/http_request/http_request.h b/esphome/components/http_request/http_request.h index 6281adddb6..82b7392648 100644 --- a/esphome/components/http_request/http_request.h +++ b/esphome/components/http_request/http_request.h @@ -43,10 +43,10 @@ class HttpContainer : public Parented { bool secure_{false}; }; -class HttpRequestResponseTrigger : public Trigger, std::string> { +class HttpRequestResponseTrigger : public Trigger, std::string &> { public: - void process(std::shared_ptr container, std::string response_body) { - this->trigger(std::move(container), std::move(response_body)); + void process(std::shared_ptr container, std::string &response_body) { + this->trigger(std::move(container), response_body); } }; @@ -153,8 +153,17 @@ template class HttpRequestSendAction : public Action { } } - for (auto *trigger : this->response_triggers_) { - trigger->process(container, response_body); + if (this->response_triggers_.size() == 1) { + // if there is only one trigger, no need to copy the response body + this->response_triggers_[0]->process(container, response_body); + } else { + for (auto *trigger : this->response_triggers_) { + // with multiple triggers, pass a copy of the response body to each + // one so that modifications made in one trigger are not visible to + // the others + auto response_body_copy = std::string(response_body); + trigger->process(container, response_body_copy); + } } container->end(); } diff --git a/esphome/cpp_types.py b/esphome/cpp_types.py index bd79d3b2f9..dab993f87f 100644 --- a/esphome/cpp_types.py +++ b/esphome/cpp_types.py @@ -10,6 +10,7 @@ int_ = global_ns.namespace("int") std_ns = global_ns.namespace("std") std_shared_ptr = std_ns.class_("shared_ptr") std_string = std_ns.class_("string") +std_string_ref = std_ns.namespace("string &") std_vector = std_ns.class_("vector") uint8 = global_ns.namespace("uint8_t") uint16 = global_ns.namespace("uint16_t") From bc26de2d68283d0d743a1e5a08921abfa6c00820 Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Tue, 25 Jun 2024 16:54:02 -0700 Subject: [PATCH 1674/2101] [ds1307] Initialize uninitialized struct members (#6985) --- esphome/components/ds1307/ds1307.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/esphome/components/ds1307/ds1307.cpp b/esphome/components/ds1307/ds1307.cpp index 472ccc7a9a..9df8a1d373 100644 --- a/esphome/components/ds1307/ds1307.cpp +++ b/esphome/components/ds1307/ds1307.cpp @@ -37,14 +37,18 @@ void DS1307Component::read_time() { ESP_LOGW(TAG, "RTC halted, not syncing to system clock."); return; } - ESPTime rtc_time{.second = uint8_t(ds1307_.reg.second + 10 * ds1307_.reg.second_10), - .minute = uint8_t(ds1307_.reg.minute + 10u * ds1307_.reg.minute_10), - .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)}; + ESPTime rtc_time{ + .second = uint8_t(ds1307_.reg.second + 10 * ds1307_.reg.second_10), + .minute = uint8_t(ds1307_.reg.minute + 10u * ds1307_.reg.minute_10), + .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()) { ESP_LOGE(TAG, "Invalid RTC time, not syncing to system clock."); From cc4f1c667ed15f1962c6bacaa7b30c0a7f329b43 Mon Sep 17 00:00:00 2001 From: Petapton <14984292+Petapton@users.noreply.github.com> Date: Wed, 26 Jun 2024 02:08:16 +0200 Subject: [PATCH 1675/2101] Fix float encoding in modbus server (#6986) --- esphome/components/modbus_controller/modbus_controller.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/esphome/components/modbus_controller/modbus_controller.cpp b/esphome/components/modbus_controller/modbus_controller.cpp index 9f73988b03..29d3137603 100644 --- a/esphome/components/modbus_controller/modbus_controller.cpp +++ b/esphome/components/modbus_controller/modbus_controller.cpp @@ -116,7 +116,8 @@ void ModbusController::on_modbus_read_registers(uint8_t function_code, uint16_t ESP_LOGD(TAG, "Matched register. Address: 0x%02X. Value type: %zu. Register count: %u. Value: %0.1f.", server_register->address, static_cast(server_register->value_type), server_register->register_count, value); - number_to_payload(sixteen_bit_response, value, server_register->value_type); + std::vector payload = float_to_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; break; From 91766afb64e804db97cc03f8ba6174e13968f742 Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Wed, 26 Jun 2024 00:27:07 -0700 Subject: [PATCH 1676/2101] [dallas_temp] fix ds18s20 temp calc (#6988) --- .../components/dallas_temp/dallas_temp.cpp | 33 +++++++++---------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/esphome/components/dallas_temp/dallas_temp.cpp b/esphome/components/dallas_temp/dallas_temp.cpp index fe7c9a95ea..ae567d6a76 100644 --- a/esphome/components/dallas_temp/dallas_temp.cpp +++ b/esphome/components/dallas_temp/dallas_temp.cpp @@ -145,24 +145,21 @@ 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] != 0x10) - ESP_LOGE(TAG, "unexpected COUNT_PER_C value: %u", this->scratch_pad_[7]); - temp = ((temp & 0xfff7) << 3) + (0x10 - this->scratch_pad_[6]) - 4; - } else { - switch (this->resolution_) { - case 9: - temp &= 0xfff8; - break; - case 10: - temp &= 0xfffc; - break; - case 11: - temp &= 0xfffe; - break; - case 12: - default: - break; - } + return (temp >> 1) + (this->scratch_pad_[7] - this->scratch_pad_[6]) / float(this->scratch_pad_[7]) - 0.25; + } + switch (this->resolution_) { + case 9: + temp &= 0xfff8; + break; + case 10: + temp &= 0xfffc; + break; + case 11: + temp &= 0xfffe; + break; + case 12: + default: + break; } return temp / 16.0f; From 01bcf5fb97643d73a96fbf7119ea48a768f85b73 Mon Sep 17 00:00:00 2001 From: Sergey Dudanov Date: Wed, 26 Jun 2024 14:38:11 +0400 Subject: [PATCH 1677/2101] [modbus-text-sensor] fix potential buffer overflow (#6993) --- .../modbus_controller/text_sensor/modbus_textsensor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/modbus_controller/text_sensor/modbus_textsensor.cpp b/esphome/components/modbus_controller/text_sensor/modbus_textsensor.cpp index 359c6e2f50..da5c0fba37 100644 --- a/esphome/components/modbus_controller/text_sensor/modbus_textsensor.cpp +++ b/esphome/components/modbus_controller/text_sensor/modbus_textsensor.cpp @@ -15,7 +15,7 @@ void ModbusTextSensor::parse_and_publish(const std::vector &data) { std::ostringstream output; uint8_t items_left = this->response_bytes; uint8_t index = this->offset; - char buffer[4]; + char buffer[5]; while ((items_left > 0) && index < data.size()) { uint8_t b = data[index]; switch (this->encode_) { From 7be071a0e91771019fce9be8704e6dffc1d6e0af Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 25 Jun 2024 21:07:19 +1200 Subject: [PATCH 1678/2101] [safe_mode] Set safe mode core data in disabled cases (#6983) --- esphome/components/safe_mode/__init__.py | 25 ++++++++++++------------ 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/esphome/components/safe_mode/__init__.py b/esphome/components/safe_mode/__init__.py index 881937890d..185c0e70b1 100644 --- a/esphome/components/safe_mode/__init__.py +++ b/esphome/components/safe_mode/__init__.py @@ -56,21 +56,20 @@ CONFIG_SCHEMA = cv.All( @coroutine_with_priority(50.0) async def to_code(config): - if config[CONF_DISABLED]: - return + if not config[CONF_DISABLED]: + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, 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) - for conf in config.get(CONF_ON_SAFE_MODE, []): - 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], + config[CONF_REBOOT_TIMEOUT], + config[CONF_BOOT_IS_GOOD_AFTER], + ) + cg.add(RawExpression(f"if ({condition}) return")) - condition = var.should_enter_safe_mode( - config[CONF_NUM_ATTEMPTS], - config[CONF_REBOOT_TIMEOUT], - config[CONF_BOOT_IS_GOOD_AFTER], - ) - cg.add(RawExpression(f"if ({condition}) return")) CORE.data[CONF_SAFE_MODE] = {} CORE.data[CONF_SAFE_MODE][KEY_PAST_SAFE_MODE] = True From d8a6d8594a246fd038c6051f157c7ce2eaf8b0eb Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Tue, 25 Jun 2024 15:57:15 -0500 Subject: [PATCH 1679/2101] [ota-esphome] Validate for multiple esphome ota instances (#6984) --- esphome/components/esphome/ota/__init__.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/esphome/components/esphome/ota/__init__.py b/esphome/components/esphome/ota/__init__.py index c5903974c2..88e729f230 100644 --- a/esphome/components/esphome/ota/__init__.py +++ b/esphome/components/esphome/ota/__init__.py @@ -1,10 +1,14 @@ import esphome.codegen as cg import esphome.config_validation as cv +import esphome.final_validate as fv from esphome.components.ota import BASE_OTA_SCHEMA, ota_to_code, OTAComponent from esphome.const import ( + CONF_ESPHOME, CONF_ID, CONF_NUM_ATTEMPTS, + CONF_OTA, CONF_PASSWORD, + CONF_PLATFORM, CONF_PORT, CONF_REBOOT_TIMEOUT, CONF_SAFE_MODE, @@ -21,6 +25,19 @@ esphome = cg.esphome_ns.namespace("esphome") ESPHomeOTAComponent = esphome.class_("ESPHomeOTAComponent", OTAComponent) +def ota_esphome_final_validate(config): + fconf = fv.full_config.get()[CONF_OTA] + used_ports = [] + for ota_conf in fconf: + if ota_conf.get(CONF_PLATFORM) == CONF_ESPHOME: + if (plat_port := ota_conf.get(CONF_PORT)) not in used_ports: + used_ports.append(plat_port) + else: + raise cv.Invalid( + f"Only one instance of the {CONF_ESPHOME} {CONF_OTA} {CONF_PLATFORM} is allowed per port. Note that this error may result from OTA specified in packages" + ) + + CONFIG_SCHEMA = ( cv.Schema( { @@ -50,6 +67,8 @@ CONFIG_SCHEMA = ( .extend(cv.COMPONENT_SCHEMA) ) +FINAL_VALIDATE_SCHEMA = ota_esphome_final_validate + @coroutine_with_priority(52.0) async def to_code(config): From 1579dfeb80a7b49d6cc4cfeb4f52074c026621b3 Mon Sep 17 00:00:00 2001 From: "Kevin P. Fleming" Date: Tue, 25 Jun 2024 19:50:54 -0400 Subject: [PATCH 1680/2101] Improve 'body' handling in http_request on_response triggers (#6968) --- esphome/codegen.py | 1 + esphome/components/http_request/__init__.py | 2 +- .../components/http_request/http_request.h | 19 ++++++++++++++----- esphome/cpp_types.py | 1 + 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/esphome/codegen.py b/esphome/codegen.py index b552490129..6b000b53a1 100644 --- a/esphome/codegen.py +++ b/esphome/codegen.py @@ -60,6 +60,7 @@ from esphome.cpp_types import ( # noqa std_ns, std_shared_ptr, std_string, + std_string_ref, std_vector, uint8, uint16, diff --git a/esphome/components/http_request/__init__.py b/esphome/components/http_request/__init__.py index 37487ec9a7..ade7024bed 100644 --- a/esphome/components/http_request/__init__.py +++ b/esphome/components/http_request/__init__.py @@ -257,7 +257,7 @@ async def http_request_action_to_code(config, action_id, template_arg, args): trigger, [ (cg.std_shared_ptr.template(HttpContainer), "response"), - (cg.std_string, "body"), + (cg.std_string_ref, "body"), ], conf, ) diff --git a/esphome/components/http_request/http_request.h b/esphome/components/http_request/http_request.h index 6281adddb6..82b7392648 100644 --- a/esphome/components/http_request/http_request.h +++ b/esphome/components/http_request/http_request.h @@ -43,10 +43,10 @@ class HttpContainer : public Parented { bool secure_{false}; }; -class HttpRequestResponseTrigger : public Trigger, std::string> { +class HttpRequestResponseTrigger : public Trigger, std::string &> { public: - void process(std::shared_ptr container, std::string response_body) { - this->trigger(std::move(container), std::move(response_body)); + void process(std::shared_ptr container, std::string &response_body) { + this->trigger(std::move(container), response_body); } }; @@ -153,8 +153,17 @@ template class HttpRequestSendAction : public Action { } } - for (auto *trigger : this->response_triggers_) { - trigger->process(container, response_body); + if (this->response_triggers_.size() == 1) { + // if there is only one trigger, no need to copy the response body + this->response_triggers_[0]->process(container, response_body); + } else { + for (auto *trigger : this->response_triggers_) { + // with multiple triggers, pass a copy of the response body to each + // one so that modifications made in one trigger are not visible to + // the others + auto response_body_copy = std::string(response_body); + trigger->process(container, response_body_copy); + } } container->end(); } diff --git a/esphome/cpp_types.py b/esphome/cpp_types.py index bd79d3b2f9..dab993f87f 100644 --- a/esphome/cpp_types.py +++ b/esphome/cpp_types.py @@ -10,6 +10,7 @@ int_ = global_ns.namespace("int") std_ns = global_ns.namespace("std") std_shared_ptr = std_ns.class_("shared_ptr") std_string = std_ns.class_("string") +std_string_ref = std_ns.namespace("string &") std_vector = std_ns.class_("vector") uint8 = global_ns.namespace("uint8_t") uint16 = global_ns.namespace("uint16_t") From 169fb79c977aa451655fa1840b738dfee9bfca13 Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Tue, 25 Jun 2024 16:54:02 -0700 Subject: [PATCH 1681/2101] [ds1307] Initialize uninitialized struct members (#6985) --- esphome/components/ds1307/ds1307.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/esphome/components/ds1307/ds1307.cpp b/esphome/components/ds1307/ds1307.cpp index 472ccc7a9a..9df8a1d373 100644 --- a/esphome/components/ds1307/ds1307.cpp +++ b/esphome/components/ds1307/ds1307.cpp @@ -37,14 +37,18 @@ void DS1307Component::read_time() { ESP_LOGW(TAG, "RTC halted, not syncing to system clock."); return; } - ESPTime rtc_time{.second = uint8_t(ds1307_.reg.second + 10 * ds1307_.reg.second_10), - .minute = uint8_t(ds1307_.reg.minute + 10u * ds1307_.reg.minute_10), - .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)}; + ESPTime rtc_time{ + .second = uint8_t(ds1307_.reg.second + 10 * ds1307_.reg.second_10), + .minute = uint8_t(ds1307_.reg.minute + 10u * ds1307_.reg.minute_10), + .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()) { ESP_LOGE(TAG, "Invalid RTC time, not syncing to system clock."); From bbd7c9cf861d199c7e671aa175c3d225a3bea14f Mon Sep 17 00:00:00 2001 From: Petapton <14984292+Petapton@users.noreply.github.com> Date: Wed, 26 Jun 2024 02:08:16 +0200 Subject: [PATCH 1682/2101] Fix float encoding in modbus server (#6986) --- esphome/components/modbus_controller/modbus_controller.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/esphome/components/modbus_controller/modbus_controller.cpp b/esphome/components/modbus_controller/modbus_controller.cpp index 9f73988b03..29d3137603 100644 --- a/esphome/components/modbus_controller/modbus_controller.cpp +++ b/esphome/components/modbus_controller/modbus_controller.cpp @@ -116,7 +116,8 @@ void ModbusController::on_modbus_read_registers(uint8_t function_code, uint16_t ESP_LOGD(TAG, "Matched register. Address: 0x%02X. Value type: %zu. Register count: %u. Value: %0.1f.", server_register->address, static_cast(server_register->value_type), server_register->register_count, value); - number_to_payload(sixteen_bit_response, value, server_register->value_type); + std::vector payload = float_to_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; break; From c747d7d45d15469c111635045e2c95437bedccc1 Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Wed, 26 Jun 2024 00:27:07 -0700 Subject: [PATCH 1683/2101] [dallas_temp] fix ds18s20 temp calc (#6988) --- .../components/dallas_temp/dallas_temp.cpp | 33 +++++++++---------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/esphome/components/dallas_temp/dallas_temp.cpp b/esphome/components/dallas_temp/dallas_temp.cpp index fe7c9a95ea..ae567d6a76 100644 --- a/esphome/components/dallas_temp/dallas_temp.cpp +++ b/esphome/components/dallas_temp/dallas_temp.cpp @@ -145,24 +145,21 @@ 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] != 0x10) - ESP_LOGE(TAG, "unexpected COUNT_PER_C value: %u", this->scratch_pad_[7]); - temp = ((temp & 0xfff7) << 3) + (0x10 - this->scratch_pad_[6]) - 4; - } else { - switch (this->resolution_) { - case 9: - temp &= 0xfff8; - break; - case 10: - temp &= 0xfffc; - break; - case 11: - temp &= 0xfffe; - break; - case 12: - default: - break; - } + return (temp >> 1) + (this->scratch_pad_[7] - this->scratch_pad_[6]) / float(this->scratch_pad_[7]) - 0.25; + } + switch (this->resolution_) { + case 9: + temp &= 0xfff8; + break; + case 10: + temp &= 0xfffc; + break; + case 11: + temp &= 0xfffe; + break; + case 12: + default: + break; } return temp / 16.0f; From 9c2af6318ced3de3927db404172fe358fd0afa7d Mon Sep 17 00:00:00 2001 From: Sergey Dudanov Date: Wed, 26 Jun 2024 14:38:11 +0400 Subject: [PATCH 1684/2101] [modbus-text-sensor] fix potential buffer overflow (#6993) --- .../modbus_controller/text_sensor/modbus_textsensor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/modbus_controller/text_sensor/modbus_textsensor.cpp b/esphome/components/modbus_controller/text_sensor/modbus_textsensor.cpp index 359c6e2f50..da5c0fba37 100644 --- a/esphome/components/modbus_controller/text_sensor/modbus_textsensor.cpp +++ b/esphome/components/modbus_controller/text_sensor/modbus_textsensor.cpp @@ -15,7 +15,7 @@ void ModbusTextSensor::parse_and_publish(const std::vector &data) { std::ostringstream output; uint8_t items_left = this->response_bytes; uint8_t index = this->offset; - char buffer[4]; + char buffer[5]; while ((items_left > 0) && index < data.size()) { uint8_t b = data[index]; switch (this->encode_) { From 86791422f02a5401c2fff948bba4eb1b0d82ac85 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 26 Jun 2024 22:41:48 +1200 Subject: [PATCH 1685/2101] Bump version to 2024.6.3 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index cde917ca98..2434609191 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.6.2" +__version__ = "2024.6.3" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 7174cf35dd9dc3e9e48ab84466dfcd69f2cb2f03 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Wed, 26 Jun 2024 17:53:29 -0500 Subject: [PATCH 1686/2101] [CI] Add more mdns and safe_mode tests (#6990) --- tests/components/mdns/{common.yaml => common-enabled.yaml} | 0 tests/components/mdns/test-disabled.esp32-idf.yaml | 6 ++++++ tests/components/mdns/test-enabled.esp32-ard.yaml | 1 + tests/components/mdns/test-enabled.esp32-c3-ard.yaml | 1 + tests/components/mdns/test-enabled.esp32-c3-idf.yaml | 1 + tests/components/mdns/test-enabled.esp32-idf.yaml | 1 + tests/components/mdns/test-enabled.esp8266-ard.yaml | 1 + tests/components/mdns/test-enabled.rp2040-ard.yaml | 1 + tests/components/mdns/test.esp32-ard.yaml | 1 - tests/components/mdns/test.esp32-c3-ard.yaml | 1 - tests/components/mdns/test.esp32-c3-idf.yaml | 1 - tests/components/mdns/test.esp32-idf.yaml | 1 - tests/components/mdns/test.esp8266-ard.yaml | 1 - tests/components/mdns/test.rp2040-ard.yaml | 1 - .../safe_mode/{common.yaml => common-enabled.yaml} | 0 tests/components/safe_mode/test-disabled.esp32-idf.yaml | 6 ++++++ tests/components/safe_mode/test-enabled.esp32-ard.yaml | 1 + tests/components/safe_mode/test-enabled.esp32-c3-ard.yaml | 1 + tests/components/safe_mode/test-enabled.esp32-c3-idf.yaml | 1 + tests/components/safe_mode/test-enabled.esp32-idf.yaml | 1 + tests/components/safe_mode/test-enabled.esp8266-ard.yaml | 1 + tests/components/safe_mode/test-enabled.rp2040-ard.yaml | 1 + tests/components/safe_mode/test.esp32-ard.yaml | 1 - tests/components/safe_mode/test.esp32-c3-ard.yaml | 1 - tests/components/safe_mode/test.esp32-c3-idf.yaml | 1 - tests/components/safe_mode/test.esp32-idf.yaml | 1 - tests/components/safe_mode/test.esp8266-ard.yaml | 1 - tests/components/safe_mode/test.rp2040-ard.yaml | 1 - 28 files changed, 24 insertions(+), 12 deletions(-) rename tests/components/mdns/{common.yaml => common-enabled.yaml} (100%) create mode 100644 tests/components/mdns/test-disabled.esp32-idf.yaml create mode 100644 tests/components/mdns/test-enabled.esp32-ard.yaml create mode 100644 tests/components/mdns/test-enabled.esp32-c3-ard.yaml create mode 100644 tests/components/mdns/test-enabled.esp32-c3-idf.yaml create mode 100644 tests/components/mdns/test-enabled.esp32-idf.yaml create mode 100644 tests/components/mdns/test-enabled.esp8266-ard.yaml create mode 100644 tests/components/mdns/test-enabled.rp2040-ard.yaml delete mode 100644 tests/components/mdns/test.esp32-ard.yaml delete mode 100644 tests/components/mdns/test.esp32-c3-ard.yaml delete mode 100644 tests/components/mdns/test.esp32-c3-idf.yaml delete mode 100644 tests/components/mdns/test.esp32-idf.yaml delete mode 100644 tests/components/mdns/test.esp8266-ard.yaml delete mode 100644 tests/components/mdns/test.rp2040-ard.yaml rename tests/components/safe_mode/{common.yaml => common-enabled.yaml} (100%) create mode 100644 tests/components/safe_mode/test-disabled.esp32-idf.yaml create mode 100644 tests/components/safe_mode/test-enabled.esp32-ard.yaml create mode 100644 tests/components/safe_mode/test-enabled.esp32-c3-ard.yaml create mode 100644 tests/components/safe_mode/test-enabled.esp32-c3-idf.yaml create mode 100644 tests/components/safe_mode/test-enabled.esp32-idf.yaml create mode 100644 tests/components/safe_mode/test-enabled.esp8266-ard.yaml create mode 100644 tests/components/safe_mode/test-enabled.rp2040-ard.yaml delete mode 100644 tests/components/safe_mode/test.esp32-ard.yaml delete mode 100644 tests/components/safe_mode/test.esp32-c3-ard.yaml delete mode 100644 tests/components/safe_mode/test.esp32-c3-idf.yaml delete mode 100644 tests/components/safe_mode/test.esp32-idf.yaml delete mode 100644 tests/components/safe_mode/test.esp8266-ard.yaml delete mode 100644 tests/components/safe_mode/test.rp2040-ard.yaml diff --git a/tests/components/mdns/common.yaml b/tests/components/mdns/common-enabled.yaml similarity index 100% rename from tests/components/mdns/common.yaml rename to tests/components/mdns/common-enabled.yaml diff --git a/tests/components/mdns/test-disabled.esp32-idf.yaml b/tests/components/mdns/test-disabled.esp32-idf.yaml new file mode 100644 index 0000000000..07c70bf248 --- /dev/null +++ b/tests/components/mdns/test-disabled.esp32-idf.yaml @@ -0,0 +1,6 @@ +wifi: + ssid: MySSID + password: password1 + +mdns: + disabled: true diff --git a/tests/components/mdns/test-enabled.esp32-ard.yaml b/tests/components/mdns/test-enabled.esp32-ard.yaml new file mode 100644 index 0000000000..97fd63d70e --- /dev/null +++ b/tests/components/mdns/test-enabled.esp32-ard.yaml @@ -0,0 +1 @@ +<<: !include common-enabled.yaml diff --git a/tests/components/mdns/test-enabled.esp32-c3-ard.yaml b/tests/components/mdns/test-enabled.esp32-c3-ard.yaml new file mode 100644 index 0000000000..97fd63d70e --- /dev/null +++ b/tests/components/mdns/test-enabled.esp32-c3-ard.yaml @@ -0,0 +1 @@ +<<: !include common-enabled.yaml diff --git a/tests/components/mdns/test-enabled.esp32-c3-idf.yaml b/tests/components/mdns/test-enabled.esp32-c3-idf.yaml new file mode 100644 index 0000000000..97fd63d70e --- /dev/null +++ b/tests/components/mdns/test-enabled.esp32-c3-idf.yaml @@ -0,0 +1 @@ +<<: !include common-enabled.yaml diff --git a/tests/components/mdns/test-enabled.esp32-idf.yaml b/tests/components/mdns/test-enabled.esp32-idf.yaml new file mode 100644 index 0000000000..97fd63d70e --- /dev/null +++ b/tests/components/mdns/test-enabled.esp32-idf.yaml @@ -0,0 +1 @@ +<<: !include common-enabled.yaml diff --git a/tests/components/mdns/test-enabled.esp8266-ard.yaml b/tests/components/mdns/test-enabled.esp8266-ard.yaml new file mode 100644 index 0000000000..97fd63d70e --- /dev/null +++ b/tests/components/mdns/test-enabled.esp8266-ard.yaml @@ -0,0 +1 @@ +<<: !include common-enabled.yaml diff --git a/tests/components/mdns/test-enabled.rp2040-ard.yaml b/tests/components/mdns/test-enabled.rp2040-ard.yaml new file mode 100644 index 0000000000..97fd63d70e --- /dev/null +++ b/tests/components/mdns/test-enabled.rp2040-ard.yaml @@ -0,0 +1 @@ +<<: !include common-enabled.yaml diff --git a/tests/components/mdns/test.esp32-ard.yaml b/tests/components/mdns/test.esp32-ard.yaml deleted file mode 100644 index dade44d145..0000000000 --- a/tests/components/mdns/test.esp32-ard.yaml +++ /dev/null @@ -1 +0,0 @@ -<<: !include common.yaml diff --git a/tests/components/mdns/test.esp32-c3-ard.yaml b/tests/components/mdns/test.esp32-c3-ard.yaml deleted file mode 100644 index dade44d145..0000000000 --- a/tests/components/mdns/test.esp32-c3-ard.yaml +++ /dev/null @@ -1 +0,0 @@ -<<: !include common.yaml diff --git a/tests/components/mdns/test.esp32-c3-idf.yaml b/tests/components/mdns/test.esp32-c3-idf.yaml deleted file mode 100644 index dade44d145..0000000000 --- a/tests/components/mdns/test.esp32-c3-idf.yaml +++ /dev/null @@ -1 +0,0 @@ -<<: !include common.yaml diff --git a/tests/components/mdns/test.esp32-idf.yaml b/tests/components/mdns/test.esp32-idf.yaml deleted file mode 100644 index dade44d145..0000000000 --- a/tests/components/mdns/test.esp32-idf.yaml +++ /dev/null @@ -1 +0,0 @@ -<<: !include common.yaml diff --git a/tests/components/mdns/test.esp8266-ard.yaml b/tests/components/mdns/test.esp8266-ard.yaml deleted file mode 100644 index dade44d145..0000000000 --- a/tests/components/mdns/test.esp8266-ard.yaml +++ /dev/null @@ -1 +0,0 @@ -<<: !include common.yaml diff --git a/tests/components/mdns/test.rp2040-ard.yaml b/tests/components/mdns/test.rp2040-ard.yaml deleted file mode 100644 index dade44d145..0000000000 --- a/tests/components/mdns/test.rp2040-ard.yaml +++ /dev/null @@ -1 +0,0 @@ -<<: !include common.yaml diff --git a/tests/components/safe_mode/common.yaml b/tests/components/safe_mode/common-enabled.yaml similarity index 100% rename from tests/components/safe_mode/common.yaml rename to tests/components/safe_mode/common-enabled.yaml diff --git a/tests/components/safe_mode/test-disabled.esp32-idf.yaml b/tests/components/safe_mode/test-disabled.esp32-idf.yaml new file mode 100644 index 0000000000..291f5a2c7c --- /dev/null +++ b/tests/components/safe_mode/test-disabled.esp32-idf.yaml @@ -0,0 +1,6 @@ +wifi: + ssid: MySSID + password: password1 + +safe_mode: + disabled: true diff --git a/tests/components/safe_mode/test-enabled.esp32-ard.yaml b/tests/components/safe_mode/test-enabled.esp32-ard.yaml new file mode 100644 index 0000000000..97fd63d70e --- /dev/null +++ b/tests/components/safe_mode/test-enabled.esp32-ard.yaml @@ -0,0 +1 @@ +<<: !include common-enabled.yaml diff --git a/tests/components/safe_mode/test-enabled.esp32-c3-ard.yaml b/tests/components/safe_mode/test-enabled.esp32-c3-ard.yaml new file mode 100644 index 0000000000..97fd63d70e --- /dev/null +++ b/tests/components/safe_mode/test-enabled.esp32-c3-ard.yaml @@ -0,0 +1 @@ +<<: !include common-enabled.yaml diff --git a/tests/components/safe_mode/test-enabled.esp32-c3-idf.yaml b/tests/components/safe_mode/test-enabled.esp32-c3-idf.yaml new file mode 100644 index 0000000000..97fd63d70e --- /dev/null +++ b/tests/components/safe_mode/test-enabled.esp32-c3-idf.yaml @@ -0,0 +1 @@ +<<: !include common-enabled.yaml diff --git a/tests/components/safe_mode/test-enabled.esp32-idf.yaml b/tests/components/safe_mode/test-enabled.esp32-idf.yaml new file mode 100644 index 0000000000..97fd63d70e --- /dev/null +++ b/tests/components/safe_mode/test-enabled.esp32-idf.yaml @@ -0,0 +1 @@ +<<: !include common-enabled.yaml diff --git a/tests/components/safe_mode/test-enabled.esp8266-ard.yaml b/tests/components/safe_mode/test-enabled.esp8266-ard.yaml new file mode 100644 index 0000000000..97fd63d70e --- /dev/null +++ b/tests/components/safe_mode/test-enabled.esp8266-ard.yaml @@ -0,0 +1 @@ +<<: !include common-enabled.yaml diff --git a/tests/components/safe_mode/test-enabled.rp2040-ard.yaml b/tests/components/safe_mode/test-enabled.rp2040-ard.yaml new file mode 100644 index 0000000000..97fd63d70e --- /dev/null +++ b/tests/components/safe_mode/test-enabled.rp2040-ard.yaml @@ -0,0 +1 @@ +<<: !include common-enabled.yaml diff --git a/tests/components/safe_mode/test.esp32-ard.yaml b/tests/components/safe_mode/test.esp32-ard.yaml deleted file mode 100644 index dade44d145..0000000000 --- a/tests/components/safe_mode/test.esp32-ard.yaml +++ /dev/null @@ -1 +0,0 @@ -<<: !include common.yaml diff --git a/tests/components/safe_mode/test.esp32-c3-ard.yaml b/tests/components/safe_mode/test.esp32-c3-ard.yaml deleted file mode 100644 index dade44d145..0000000000 --- a/tests/components/safe_mode/test.esp32-c3-ard.yaml +++ /dev/null @@ -1 +0,0 @@ -<<: !include common.yaml diff --git a/tests/components/safe_mode/test.esp32-c3-idf.yaml b/tests/components/safe_mode/test.esp32-c3-idf.yaml deleted file mode 100644 index dade44d145..0000000000 --- a/tests/components/safe_mode/test.esp32-c3-idf.yaml +++ /dev/null @@ -1 +0,0 @@ -<<: !include common.yaml diff --git a/tests/components/safe_mode/test.esp32-idf.yaml b/tests/components/safe_mode/test.esp32-idf.yaml deleted file mode 100644 index dade44d145..0000000000 --- a/tests/components/safe_mode/test.esp32-idf.yaml +++ /dev/null @@ -1 +0,0 @@ -<<: !include common.yaml diff --git a/tests/components/safe_mode/test.esp8266-ard.yaml b/tests/components/safe_mode/test.esp8266-ard.yaml deleted file mode 100644 index dade44d145..0000000000 --- a/tests/components/safe_mode/test.esp8266-ard.yaml +++ /dev/null @@ -1 +0,0 @@ -<<: !include common.yaml diff --git a/tests/components/safe_mode/test.rp2040-ard.yaml b/tests/components/safe_mode/test.rp2040-ard.yaml deleted file mode 100644 index dade44d145..0000000000 --- a/tests/components/safe_mode/test.rp2040-ard.yaml +++ /dev/null @@ -1 +0,0 @@ -<<: !include common.yaml From 300d48a55e14f9d6170069364d4eaf9b0217a7d5 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Wed, 26 Jun 2024 17:54:17 -0500 Subject: [PATCH 1687/2101] [CI] Remove old test yamls (#6991) --- .github/workflows/ci.yml | 67 ---------------------------------------- 1 file changed, 67 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index df7a9178e1..45fe336d77 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -248,72 +248,6 @@ jobs: run: script/ci-suggest-changes if: always() - compile-tests-list: - runs-on: ubuntu-latest - outputs: - matrix: ${{ steps.set-matrix.outputs.matrix }} - steps: - - name: Check out code from GitHub - uses: actions/checkout@v4.1.7 - - name: Find all YAML test files - id: set-matrix - run: echo "matrix=$(ls tests/test*.yaml | jq -R -s -c 'split("\n")[:-1]')" >> $GITHUB_OUTPUT - - validate-tests: - name: Validate YAML test ${{ matrix.file }} - runs-on: ubuntu-latest - needs: - - common - - compile-tests-list - strategy: - fail-fast: false - matrix: - file: ${{ fromJson(needs.compile-tests-list.outputs.matrix) }} - steps: - - name: Check out code from GitHub - uses: actions/checkout@v4.1.7 - - name: Restore Python - uses: ./.github/actions/restore-python - with: - python-version: ${{ env.DEFAULT_PYTHON }} - cache-key: ${{ needs.common.outputs.cache-key }} - - name: Run esphome config ${{ matrix.file }} - run: | - . venv/bin/activate - esphome config ${{ matrix.file }} - - compile-tests: - name: Run YAML test ${{ matrix.file }} - runs-on: ubuntu-latest - needs: - - common - - black - - ci-custom - - clang-format - - flake8 - - pylint - - pytest - - pyupgrade - - compile-tests-list - - validate-tests - strategy: - fail-fast: false - max-parallel: 2 - matrix: - file: ${{ fromJson(needs.compile-tests-list.outputs.matrix) }} - steps: - - name: Check out code from GitHub - uses: actions/checkout@v4.1.7 - - name: Restore Python - uses: ./.github/actions/restore-python - with: - python-version: ${{ env.DEFAULT_PYTHON }} - cache-key: ${{ needs.common.outputs.cache-key }} - - name: Run esphome compile ${{ matrix.file }} - run: | - . venv/bin/activate - esphome compile ${{ matrix.file }} - clang-tidy: name: ${{ matrix.name }} runs-on: ubuntu-latest @@ -550,7 +484,6 @@ jobs: - pylint - pytest - pyupgrade - - compile-tests - clang-tidy - list-components - test-build-components From 855d154439906ea0b150eb57ae7fa866bf52ca3d Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Wed, 26 Jun 2024 17:55:05 -0500 Subject: [PATCH 1688/2101] [CI] Update tests to run against IDF 5.1 (#6992) --- ...f-50.yaml => build_components_base.esp32-c3-idf-51.yaml} | 6 +++--- ...-idf-50.yaml => build_components_base.esp32-idf-51.yaml} | 6 +++--- ...f-50.yaml => build_components_base.esp32-s2-idf-51.yaml} | 6 +++--- ...f-50.yaml => build_components_base.esp32-s3-idf-51.yaml} | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) rename tests/test_build_components/{build_components_base.esp32-c3-idf-50.yaml => build_components_base.esp32-c3-idf-51.yaml} (76%) rename tests/test_build_components/{build_components_base.esp32-idf-50.yaml => build_components_base.esp32-idf-51.yaml} (77%) rename tests/test_build_components/{build_components_base.esp32-s2-idf-50.yaml => build_components_base.esp32-s2-idf-51.yaml} (78%) rename tests/test_build_components/{build_components_base.esp32-s3-idf-50.yaml => build_components_base.esp32-s3-idf-51.yaml} (77%) diff --git a/tests/test_build_components/build_components_base.esp32-c3-idf-50.yaml b/tests/test_build_components/build_components_base.esp32-c3-idf-51.yaml similarity index 76% rename from tests/test_build_components/build_components_base.esp32-c3-idf-50.yaml rename to tests/test_build_components/build_components_base.esp32-c3-idf-51.yaml index 08d4d8679c..73d2c8fa19 100644 --- a/tests/test_build_components/build_components_base.esp32-c3-idf-50.yaml +++ b/tests/test_build_components/build_components_base.esp32-c3-idf-51.yaml @@ -1,13 +1,13 @@ esphome: - name: componenttestesp32c3idf50 + name: componenttestesp32c3idf51 friendly_name: $component_name esp32: board: lolin_c3_mini framework: type: esp-idf - version: 5.0.2 - platform_version: 6.3.2 + version: 5.1.2 + platform_version: 6.6.0 logger: level: VERY_VERBOSE diff --git a/tests/test_build_components/build_components_base.esp32-idf-50.yaml b/tests/test_build_components/build_components_base.esp32-idf-51.yaml similarity index 77% rename from tests/test_build_components/build_components_base.esp32-idf-50.yaml rename to tests/test_build_components/build_components_base.esp32-idf-51.yaml index c9f2c1e943..6c8eb3c193 100644 --- a/tests/test_build_components/build_components_base.esp32-idf-50.yaml +++ b/tests/test_build_components/build_components_base.esp32-idf-51.yaml @@ -1,13 +1,13 @@ esphome: - name: componenttestesp32idf50 + name: componenttestesp32idf51 friendly_name: $component_name esp32: board: nodemcu-32s framework: type: esp-idf - version: 5.0.2 - platform_version: 6.3.2 + version: 5.1.2 + platform_version: 6.6.0 logger: level: VERY_VERBOSE diff --git a/tests/test_build_components/build_components_base.esp32-s2-idf-50.yaml b/tests/test_build_components/build_components_base.esp32-s2-idf-51.yaml similarity index 78% rename from tests/test_build_components/build_components_base.esp32-s2-idf-50.yaml rename to tests/test_build_components/build_components_base.esp32-s2-idf-51.yaml index 351f5fb019..8894efb6b8 100644 --- a/tests/test_build_components/build_components_base.esp32-s2-idf-50.yaml +++ b/tests/test_build_components/build_components_base.esp32-s2-idf-51.yaml @@ -1,5 +1,5 @@ esphome: - name: componenttestesp32s2idf50 + name: componenttestesp32s2idf51 friendly_name: $component_name esp32: @@ -7,8 +7,8 @@ esp32: variant: ESP32S2 framework: type: esp-idf - version: 5.0.2 - platform_version: 6.3.2 + version: 5.1.2 + platform_version: 6.6.0 logger: level: VERY_VERBOSE diff --git a/tests/test_build_components/build_components_base.esp32-s3-idf-50.yaml b/tests/test_build_components/build_components_base.esp32-s3-idf-51.yaml similarity index 77% rename from tests/test_build_components/build_components_base.esp32-s3-idf-50.yaml rename to tests/test_build_components/build_components_base.esp32-s3-idf-51.yaml index c05378903f..efeffa5a0f 100644 --- a/tests/test_build_components/build_components_base.esp32-s3-idf-50.yaml +++ b/tests/test_build_components/build_components_base.esp32-s3-idf-51.yaml @@ -1,5 +1,5 @@ esphome: - name: componenttestesp32s3idf50 + name: componenttestesp32s3idf51 friendly_name: $component_name esp32: @@ -7,8 +7,8 @@ esp32: variant: ESP32S3 framework: type: esp-idf - version: 5.0.2 - platform_version: 6.3.2 + version: 5.1.2 + platform_version: 6.6.0 logger: level: VERY_VERBOSE From 192718fee626852690acd575efae60dc06453df6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 27 Jun 2024 10:55:42 +1200 Subject: [PATCH 1689/2101] Bump docker/build-push-action from 6.1.0 to 6.2.0 in /.github/actions/build-image (#6999) 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 27d2ffc533..b038a285ef 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -46,7 +46,7 @@ runs: - name: Build and push to ghcr by digest id: build-ghcr - uses: docker/build-push-action@v6.1.0 + uses: docker/build-push-action@v6.2.0 with: context: . file: ./docker/Dockerfile @@ -69,7 +69,7 @@ runs: - name: Build and push to dockerhub by digest id: build-dockerhub - uses: docker/build-push-action@v6.1.0 + uses: docker/build-push-action@v6.2.0 with: context: . file: ./docker/Dockerfile From 10504c4d68b9808b86d51763f3b92ee0a41b96db Mon Sep 17 00:00:00 2001 From: Christiaan de Ridder Date: Thu, 27 Jun 2024 01:03:55 +0200 Subject: [PATCH 1690/2101] Tuya invalid command 0x22 (#6980) --- esphome/components/tuya/tuya.cpp | 10 ++++++++-- esphome/components/tuya/tuya.h | 4 +++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/esphome/components/tuya/tuya.cpp b/esphome/components/tuya/tuya.cpp index 402953bb3b..1443d10254 100644 --- a/esphome/components/tuya/tuya.cpp +++ b/esphome/components/tuya/tuya.cpp @@ -223,13 +223,19 @@ void Tuya::handle_command_(uint8_t command, uint8_t version, const uint8_t *buff break; case TuyaCommandType::DATAPOINT_DELIVER: break; - case TuyaCommandType::DATAPOINT_REPORT: + case TuyaCommandType::DATAPOINT_REPORT_ASYNC: + case TuyaCommandType::DATAPOINT_REPORT_SYNC: if (this->init_state_ == TuyaInitState::INIT_DATAPOINT) { this->init_state_ = TuyaInitState::INIT_DONE; this->set_timeout("datapoint_dump", 1000, [this] { this->dump_config(); }); this->initialized_callback_.call(); } this->handle_datapoints_(buffer, len); + + if (command_type == TuyaCommandType::DATAPOINT_REPORT_SYNC) { + this->send_command_( + TuyaCommand{.cmd = TuyaCommandType::DATAPOINT_REPORT_ACK, .payload = std::vector{0x01}}); + } break; case TuyaCommandType::DATAPOINT_QUERY: break; @@ -423,7 +429,7 @@ void Tuya::send_raw_command_(TuyaCommand command) { break; case TuyaCommandType::DATAPOINT_DELIVER: case TuyaCommandType::DATAPOINT_QUERY: - this->expected_response_ = TuyaCommandType::DATAPOINT_REPORT; + this->expected_response_ = TuyaCommandType::DATAPOINT_REPORT_ASYNC; break; default: break; diff --git a/esphome/components/tuya/tuya.h b/esphome/components/tuya/tuya.h index 6db417d474..76431ddfe4 100644 --- a/esphome/components/tuya/tuya.h +++ b/esphome/components/tuya/tuya.h @@ -53,10 +53,12 @@ enum class TuyaCommandType : uint8_t { WIFI_RESET = 0x04, WIFI_SELECT = 0x05, DATAPOINT_DELIVER = 0x06, - DATAPOINT_REPORT = 0x07, + DATAPOINT_REPORT_ASYNC = 0x07, DATAPOINT_QUERY = 0x08, WIFI_TEST = 0x0E, LOCAL_TIME_QUERY = 0x1C, + DATAPOINT_REPORT_SYNC = 0x22, + DATAPOINT_REPORT_ACK = 0x23, WIFI_RSSI = 0x24, VACUUM_MAP_UPLOAD = 0x28, GET_NETWORK_STATUS = 0x2B, From cd7894ae8f235df2d601e03b20a725b61b5a2921 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Wed, 26 Jun 2024 20:07:07 -0500 Subject: [PATCH 1691/2101] [ota-esphome] Merge configurations by port (#7001) --- esphome/components/esphome/ota/__init__.py | 65 +++++++++++++++++++--- 1 file changed, 58 insertions(+), 7 deletions(-) diff --git a/esphome/components/esphome/ota/__init__.py b/esphome/components/esphome/ota/__init__.py index 88e729f230..a852d8d001 100644 --- a/esphome/components/esphome/ota/__init__.py +++ b/esphome/components/esphome/ota/__init__.py @@ -1,7 +1,10 @@ +import logging + import esphome.codegen as cg import esphome.config_validation as cv import esphome.final_validate as fv from esphome.components.ota import BASE_OTA_SCHEMA, ota_to_code, OTAComponent +from esphome.config_helpers import merge_config from esphome.const import ( CONF_ESPHOME, CONF_ID, @@ -16,6 +19,8 @@ from esphome.const import ( ) from esphome.core import coroutine_with_priority +_LOGGER = logging.getLogger(__name__) + CODEOWNERS = ["@esphome/core"] AUTO_LOAD = ["md5", "socket"] @@ -26,16 +31,62 @@ ESPHomeOTAComponent = esphome.class_("ESPHomeOTAComponent", OTAComponent) def ota_esphome_final_validate(config): - fconf = fv.full_config.get()[CONF_OTA] - used_ports = [] - for ota_conf in fconf: + full_conf = fv.full_config.get() + full_ota_conf = full_conf[CONF_OTA] + new_ota_conf = [] + merged_ota_esphome_configs_by_port = {} + ports_with_merged_configs = [] + for ota_conf in full_ota_conf: if ota_conf.get(CONF_PLATFORM) == CONF_ESPHOME: - if (plat_port := ota_conf.get(CONF_PORT)) not in used_ports: - used_ports.append(plat_port) + if ( + conf_port := ota_conf.get(CONF_PORT) + ) not in merged_ota_esphome_configs_by_port: + merged_ota_esphome_configs_by_port[conf_port] = ota_conf else: - raise cv.Invalid( - f"Only one instance of the {CONF_ESPHOME} {CONF_OTA} {CONF_PLATFORM} is allowed per port. Note that this error may result from OTA specified in packages" + if merged_ota_esphome_configs_by_port[conf_port][ + CONF_VERSION + ] != ota_conf.get(CONF_VERSION): + raise cv.Invalid( + f"Found multiple configurations but {CONF_VERSION} is inconsistent" + ) + if ( + merged_ota_esphome_configs_by_port[conf_port][CONF_ID].is_manual + and ota_conf.get(CONF_ID).is_manual + ): + raise cv.Invalid( + f"Found multiple configurations but {CONF_ID} is inconsistent" + ) + if ( + CONF_PASSWORD in merged_ota_esphome_configs_by_port[conf_port] + and CONF_PASSWORD in ota_conf + and merged_ota_esphome_configs_by_port[conf_port][CONF_PASSWORD] + != ota_conf.get(CONF_PASSWORD) + ): + raise cv.Invalid( + f"Found multiple configurations but {CONF_PASSWORD} is inconsistent" + ) + + ports_with_merged_configs.append(conf_port) + merged_ota_esphome_configs_by_port[conf_port] = merge_config( + merged_ota_esphome_configs_by_port[conf_port], ota_conf ) + else: + new_ota_conf.append(ota_conf) + + for port_conf in merged_ota_esphome_configs_by_port.values(): + new_ota_conf.append(port_conf) + + full_conf[CONF_OTA] = new_ota_conf + fv.full_config.set(full_conf) + + if len(ports_with_merged_configs) > 0: + _LOGGER.warning( + "Found and merged multiple configurations for %s %s %s port(s) %s", + CONF_OTA, + CONF_PLATFORM, + CONF_ESPHOME, + ports_with_merged_configs, + ) CONFIG_SCHEMA = ( From bfdf63055fa1113be5b2ee664e464f7763cab808 Mon Sep 17 00:00:00 2001 From: Simone Rossetto Date: Thu, 27 Jun 2024 03:42:16 +0200 Subject: [PATCH 1692/2101] Allow wireguard to bind to PPP interface (#6989) Co-authored-by: Tim Lunn --- esphome/components/wireguard/__init__.py | 2 +- platformio.ini | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/esphome/components/wireguard/__init__.py b/esphome/components/wireguard/__init__.py index 5d5f620b51..16d0d0226e 100644 --- a/esphome/components/wireguard/__init__.py +++ b/esphome/components/wireguard/__init__.py @@ -132,7 +132,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.1") + cg.add_library("droscy/esp_wireguard", "0.4.2") await cg.register_component(var, config) diff --git a/platformio.ini b/platformio.ini index e2e66bf672..aa73437222 100644 --- a/platformio.ini +++ b/platformio.ini @@ -94,7 +94,7 @@ lib_deps = ESP8266mDNS ; mdns (Arduino built-in) DNSServer ; captive_portal (Arduino built-in) crankyoldgit/IRremoteESP8266@2.8.6 ; heatpumpir - droscy/esp_wireguard@0.4.1 ; wireguard + droscy/esp_wireguard@0.4.2 ; wireguard build_flags = ${common:arduino.build_flags} -Wno-nonnull-compare @@ -124,7 +124,7 @@ lib_deps = DNSServer ; captive_portal (Arduino built-in) esphome/ESP32-audioI2S@2.0.7 ; i2s_audio crankyoldgit/IRremoteESP8266@2.8.6 ; heatpumpir - droscy/esp_wireguard@0.4.1 ; wireguard + droscy/esp_wireguard@0.4.2 ; wireguard build_flags = ${common:arduino.build_flags} -DUSE_ESP32 @@ -142,7 +142,7 @@ platform_packages = framework = espidf lib_deps = ${common:idf.lib_deps} - droscy/esp_wireguard@0.4.1 ; wireguard + droscy/esp_wireguard@0.4.2 ; wireguard build_flags = ${common:idf.build_flags} -Wno-nonnull-compare @@ -174,7 +174,7 @@ extends = common:arduino platform = libretiny framework = arduino lib_deps = - droscy/esp_wireguard@0.4.1 ; wireguard + droscy/esp_wireguard@0.4.2 ; wireguard build_flags = ${common:arduino.build_flags} -DUSE_LIBRETINY From decf50ed492a06aeba7ce1735a0ab324bc4dad73 Mon Sep 17 00:00:00 2001 From: Markus <974709+Links2004@users.noreply.github.com> Date: Thu, 27 Jun 2024 03:48:01 +0200 Subject: [PATCH 1693/2101] Fix LEDC 100% is not 100% duty with ESP32 IDF (#6997) --- esphome/components/ledc/ledc_output.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/esphome/components/ledc/ledc_output.cpp b/esphome/components/ledc/ledc_output.cpp index 1040ac25b6..90e11fe4ad 100644 --- a/esphome/components/ledc/ledc_output.cpp +++ b/esphome/components/ledc/ledc_output.cpp @@ -115,12 +115,15 @@ 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(duty_rounded); - #ifdef USE_ARDUINO ESP_LOGV(TAG, "Setting duty: %u on channel %u", duty, this->channel_); ledcWrite(this->channel_, duty); #endif #ifdef USE_ESP_IDF + // ensure that 100% on is not 99.975% on + if ((duty == max_duty) && (max_duty != 1)) { + duty = max_duty + 1; + } auto speed_mode = get_speed_mode(channel_); auto chan_num = static_cast(channel_ % 8); int hpoint = ledc_angle_to_htop(this->phase_angle_, this->bit_depth_); From 9a26cdb3364fa40957a05309d16b007f96f29c0f Mon Sep 17 00:00:00 2001 From: Sergey Dudanov Date: Thu, 27 Jun 2024 05:50:25 +0400 Subject: [PATCH 1694/2101] [modbus_text_sensor] new default ANSI encoding type (#6975) --- esphome/components/modbus_controller/text_sensor/__init__.py | 3 ++- .../modbus_controller/text_sensor/modbus_textsensor.cpp | 5 ++++- .../modbus_controller/text_sensor/modbus_textsensor.h | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/esphome/components/modbus_controller/text_sensor/__init__.py b/esphome/components/modbus_controller/text_sensor/__init__.py index 763336e104..81d6453c6f 100644 --- a/esphome/components/modbus_controller/text_sensor/__init__.py +++ b/esphome/components/modbus_controller/text_sensor/__init__.py @@ -37,6 +37,7 @@ RAW_ENCODING = { "NONE": RawEncoding.NONE, "HEXBYTES": RawEncoding.HEXBYTES, "COMMA": RawEncoding.COMMA, + "ANSI": RawEncoding.ANSI, } CONFIG_SCHEMA = cv.All( @@ -49,7 +50,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_REGISTER_TYPE): cv.enum(MODBUS_REGISTER_TYPE), cv.Optional(CONF_REGISTER_COUNT, default=0): cv.positive_int, cv.Optional(CONF_RESPONSE_SIZE, default=2): cv.positive_int, - cv.Optional(CONF_RAW_ENCODE, default="NONE"): cv.enum(RAW_ENCODING), + cv.Optional(CONF_RAW_ENCODE, default="ANSI"): cv.enum(RAW_ENCODING), } ), validate_modbus_register, diff --git a/esphome/components/modbus_controller/text_sensor/modbus_textsensor.cpp b/esphome/components/modbus_controller/text_sensor/modbus_textsensor.cpp index da5c0fba37..acdcacc083 100644 --- a/esphome/components/modbus_controller/text_sensor/modbus_textsensor.cpp +++ b/esphome/components/modbus_controller/text_sensor/modbus_textsensor.cpp @@ -27,8 +27,11 @@ void ModbusTextSensor::parse_and_publish(const std::vector &data) { sprintf(buffer, index != this->offset ? ",%d" : "%d", b); output << buffer; break; + case RawEncoding::ANSI: + if (b < 0x20) + break; + // FALLTHROUGH // Anything else no encoding - case RawEncoding::NONE: default: output << (char) b; break; diff --git a/esphome/components/modbus_controller/text_sensor/modbus_textsensor.h b/esphome/components/modbus_controller/text_sensor/modbus_textsensor.h index 9cc0db05a5..d6eb5fd230 100644 --- a/esphome/components/modbus_controller/text_sensor/modbus_textsensor.h +++ b/esphome/components/modbus_controller/text_sensor/modbus_textsensor.h @@ -9,7 +9,7 @@ namespace esphome { namespace modbus_controller { -enum class RawEncoding { NONE = 0, HEXBYTES = 1, COMMA = 2 }; +enum class RawEncoding { NONE = 0, HEXBYTES = 1, COMMA = 2, ANSI = 3 }; class ModbusTextSensor : public Component, public text_sensor::TextSensor, public SensorItem { public: From e23153d090061c93a314a4de7bfb0c58ff05a006 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Wed, 26 Jun 2024 21:34:39 -0500 Subject: [PATCH 1695/2101] [CI] Remove old test yaml files (#7002) --- tests/test1.1.yaml | 232 --- tests/test1.yaml | 4427 ------------------------------------------- tests/test11.5.yaml | 809 -------- tests/test2.yaml | 879 --------- tests/test3.1.yaml | 734 ------- tests/test3.yaml | 1432 -------------- tests/test4.yaml | 998 ---------- tests/test5.yaml | 747 -------- tests/test6.yaml | 77 - tests/test7.yaml | 27 - tests/test8.1.yaml | 78 - tests/test8.2.yaml | 75 - tests/test8.yaml | 125 -- tests/test9.1.yaml | 29 - tests/test9.yaml | 35 - 15 files changed, 10704 deletions(-) delete mode 100644 tests/test1.1.yaml delete mode 100644 tests/test1.yaml delete mode 100644 tests/test11.5.yaml delete mode 100644 tests/test2.yaml delete mode 100644 tests/test3.1.yaml delete mode 100644 tests/test3.yaml delete mode 100644 tests/test4.yaml delete mode 100644 tests/test5.yaml delete mode 100644 tests/test6.yaml delete mode 100644 tests/test7.yaml delete mode 100644 tests/test8.1.yaml delete mode 100644 tests/test8.2.yaml delete mode 100644 tests/test8.yaml delete mode 100644 tests/test9.1.yaml delete mode 100644 tests/test9.yaml diff --git a/tests/test1.1.yaml b/tests/test1.1.yaml deleted file mode 100644 index c71aa6e0ef..0000000000 --- a/tests/test1.1.yaml +++ /dev/null @@ -1,232 +0,0 @@ ---- -substitutions: - devicename: test1_1 - sensorname: my - textname: template - roomname: fastled_room - -esphome: - name: test1-1 - name_add_mac_suffix: true - platform: ESP32 - board: nodemcu-32s - platformio_options: - board_build.partitions: huge_app.csv - on_loop: - then: - - light.addressable_set: - id: addr1 - range_from: 0 - range_to: 100 - red: 100% - green: !lambda "return 255;" - blue: 0% - white: 100% - -wled: - -wifi: - networks: - - ssid: "MySSID" - password: "password1" - -uart: - - id: adalight_uart - tx_pin: GPIO25 - rx_pin: GPIO26 - baud_rate: 115200 - rx_buffer_size: 1024 - -adalight: - -network: - -e131: - -power_supply: - - id: atx_power_supply - enable_time: 20ms - keep_on_time: 10s - enable_on_boot: true - pin: - number: 13 - inverted: true - -i2c: - sda: 21 - scl: - number: 22 - allow_other_uses: true - scan: true - frequency: 100kHz - setup_priority: -100 - id: i2c_bus - -pca9685: - frequency: 500 - address: 0x0 - i2c_id: i2c_bus - -output: - - platform: pca9685 - id: pca_0 - channel: 0 - - platform: pca9685 - id: pca_1 - channel: 1 - - platform: pca9685 - id: pca_2 - channel: 2 - -light: - - platform: rgb - name: Living Room Lights - id: ${roomname}_lights - red: pca_0 - green: pca_1 - blue: pca_2 - - platform: fastled_clockless - id: addr1 - chipset: WS2811 - pin: - allow_other_uses: true - number: GPIO23 - num_leds: 60 - rgb_order: BRG - max_refresh_rate: 20ms - power_supply: atx_power_supply - color_correct: [75%, 100%, 50%] - name: FastLED WS2811 Light - effects: - - addressable_color_wipe: - - addressable_color_wipe: - name: Color Wipe Effect With Custom Values - colors: - - red: 100% - green: 100% - blue: 100% - num_leds: 1 - - red: 0% - green: 0% - blue: 0% - num_leds: 1 - add_led_interval: 100ms - reverse: false - - addressable_scan: - - addressable_scan: - name: Scan Effect With Custom Values - move_interval: 100ms - - addressable_twinkle: - - addressable_twinkle: - name: Twinkle Effect With Custom Values - twinkle_probability: 5% - progress_interval: 4ms - - addressable_random_twinkle: - - addressable_random_twinkle: - name: Random Twinkle Effect With Custom Values - twinkle_probability: 5% - progress_interval: 32ms - - addressable_fireworks: - - addressable_fireworks: - name: Fireworks Effect With Custom Values - update_interval: 32ms - spark_probability: 10% - use_random_color: false - fade_out_rate: 120 - - addressable_flicker: - - addressable_flicker: - name: Flicker Effect With Custom Values - update_interval: 16ms - intensity: 5% - - addressable_lambda: - name: Test For Custom Lambda Effect - lambda: |- - if (initial_run) { - it[0] = current_color; - } - - - wled: - port: 11111 - - - adalight: - uart_id: adalight_uart - - - e131: - universe: 1 - - - automation: - name: Custom Effect - sequence: - - light.addressable_set: - id: addr1 - red: 100% - green: 100% - blue: 0% - - delay: 100ms - - light.addressable_set: - id: addr1 - red: 0% - green: 100% - blue: 0% - - - platform: fastled_spi - id: addr2 - chipset: WS2801 - data_pin: - allow_other_uses: true - number: GPIO23 - clock_pin: - number: GPIO22 - allow_other_uses: true - data_rate: 2MHz - num_leds: 60 - rgb_order: BRG - name: FastLED SPI Light - - platform: neopixelbus - id: addr3 - name: Neopixelbus Light - gamma_correct: 2.8 - color_correct: [0.0, 0.0, 0.0, 0.0] - default_transition_length: 10s - power_supply: atx_power_supply - effects: - - addressable_flicker: - name: Flicker Effect With Custom Values - update_interval: 16ms - intensity: 5% - type: GRBW - variant: SK6812 - method: ESP32_I2S_0 - num_leds: 60 - pin: - allow_other_uses: true - number: GPIO23 - - platform: partition - name: Partition Light - segments: - - id: addr1 - from: 0 - to: 0 - - id: addr2 - from: 1 - to: 10 - - id: addr2 - from: 20 - to: 25 - - single_light_id: ${roomname}_lights - -canbus: - - platform: esp32_can - id: esp32_internal_can - rx_pin: GPIO04 - tx_pin: GPIO05 - can_id: 4 - bit_rate: 50kbps - -button: - - platform: template - name: Canbus Actions - on_press: - - canbus.send: "abc" - - canbus.send: [0, 1, 2] - - canbus.send: !lambda return {0, 1, 2}; diff --git a/tests/test1.yaml b/tests/test1.yaml deleted file mode 100644 index 79cb1bba2b..0000000000 --- a/tests/test1.yaml +++ /dev/null @@ -1,4427 +0,0 @@ ---- -substitutions: - devicename: test1 - sensorname: my - textname: template - roomname: living_room - -esphome: - name: test1 - name_add_mac_suffix: true - platform: ESP32 - board: nodemcu-32s - platformio_options: - board_build.partitions: huge_app.csv - on_boot: - priority: 150.0 - then: - - lambda: >- - ESP_LOGD("main", "ON BOOT!"); - on_shutdown: - then: - - lambda: >- - ESP_LOGD("main", "ON SHUTDOWN!"); - on_loop: - then: - - lambda: >- - ESP_LOGV("main", "ON LOOP!"); - build_path: build/test1 - -packages: - wifi: !include test_packages/test_packages_package_wifi.yaml - pkg_test: !include test_packages/test_packages_package1.yaml - -wifi: - networks: - - ssid: "MySSID" - password: "password1" - - ssid: "MySSID2" - password: "" - channel: 14 - bssid: "A1:63:95:47:D3:1D" - manual_ip: - static_ip: 192.168.178.230 - gateway: 192.168.178.1 - subnet: 255.255.255.0 - dns1: 1.1.1.1 - dns2: 1.2.2.1 - domain: .local - reboot_timeout: 120s - power_save_mode: light - on_connect: - - light.turn_on: ${roomname}_lights - on_disconnect: - - light.turn_off: ${roomname}_lights - -network: - enable_ipv6: true - -mdns: - disabled: false - -mqtt: - broker: "192.168.178.84" - port: 1883 - username: "debug" - password: "debug" - client_id: someclient - use_abbreviations: false - discovery: true - discovery_retain: false - discovery_prefix: discovery - discovery_unique_id_generator: legacy - topic_prefix: helloworld - log_topic: - topic: helloworld/hi - level: INFO - birth_message: - will_message: - shutdown_message: - topic: topic/to/send/to - payload: hi - qos: 2 - retain: true - keepalive: 60s - reboot_timeout: 60s - on_message: - - topic: my/custom/topic - qos: 0 - then: - - lambda: >- - ESP_LOGD("main", "Got message %s", x.c_str()); - - topic: livingroom/ota_mode - then: - - deep_sleep.prevent - - deep_sleep.allow - - topic: livingroom/ota_mode - then: - - deep_sleep.enter: - on_json_message: - topic: the/topic - then: - - if: - condition: - - wifi.connected: - - mqtt.connected: - - light.is_on: kitchen - - light.is_off: kitchen - - fan.is_on: fan_speed - - fan.is_off: fan_speed - then: - - lambda: |- - int data = x["my_data"]; - ESP_LOGD("main", "The data is: %d", data); - - light.turn_on: - id: ${roomname}_lights - brightness: !lambda |- - float brightness = 1.0; - if (x.containsKey("brightness")) - brightness = x["brightness"]; - return brightness; - effect: !lambda |- - const char *effect = "None"; - if (x.containsKey("effect")) - effect = x["effect"]; - return effect; - - light.control: - id: ${roomname}_lights - # yamllint disable-line rule:line-length - brightness: !lambda "return id(${roomname}_lights).current_values.get_brightness() + 0.5;" - - light.dim_relative: - id: ${roomname}_lights - relative_brightness: 5% - - uart.write: - id: uart_0 - data: Hello World - - uart.write: - id: uart_0 - data: [0x00, 0x20, 0x30] - - uart.write: - id: uart_0 - data: !lambda |- - return {}; - - bluetooth_password.set: - id: my_ld2410 - password: abcdef - on_connect: - - light.turn_on: ${roomname}_lights - - mqtt.publish: - topic: some/topic - payload: Hello - on_disconnect: - - light.turn_off: ${roomname}_lights - -i2c: - sda: - allow_other_uses: true - number: 21 - scl: - allow_other_uses: true - number: 22 - scan: true - frequency: 100kHz - setup_priority: -100 - id: i2c_bus - -spi: - id: spi_bus - clk_pin: - allow_other_uses: true - number: GPIO21 - mosi_pin: - allow_other_uses: true - number: GPIO22 - miso_pin: - allow_other_uses: true - number: GPIO23 - -uart: - - tx_pin: - allow_other_uses: true - number: GPIO22 - inverted: true - rx_pin: - allow_other_uses: true - number: GPIO23 - inverted: true - baud_rate: 115200 - id: uart_0 - parity: NONE - data_bits: 8 - stop_bits: 1 - rx_buffer_size: 512 - debug: - dummy_receiver: true - direction: both - after: - bytes: 50 - timeout: 500ms - delimiter: "\r\n" - sequence: - - lambda: UARTDebug::log_hex(direction, bytes, ':'); - - lambda: UARTDebug::log_string(direction, bytes); - - lambda: UARTDebug::log_int(direction, bytes, ','); - - lambda: UARTDebug::log_binary(direction, bytes, ';'); - - id: ld2410_uart - tx_pin: - allow_other_uses: true - number: 18 - rx_pin: - allow_other_uses: true - number: 23 - baud_rate: 256000 - parity: NONE - stop_bits: 1 - - id: dfrobot_mmwave_uart - tx_pin: - allow_other_uses: true - number: 14 - rx_pin: - allow_other_uses: true - number: 27 - baud_rate: 115200 - - id: ld2420_uart - tx_pin: - allow_other_uses: true - number: 17 - rx_pin: - allow_other_uses: true - number: 16 - baud_rate: 115200 - parity: NONE - stop_bits: 1 - - id: gcja5_uart - rx_pin: GPIO10 - parity: EVEN - baud_rate: 9600 - -safe_mode: - num_attempts: 3 - reboot_timeout: 2min - -ota: - - platform: esphome - password: "superlongpasswordthatnoonewillknow" - port: 3286 - on_state_change: - then: - lambda: >- - ESP_LOGD("ota", "State %d", state); - on_begin: - then: - logger.log: OTA begin - on_progress: - then: - lambda: >- - ESP_LOGD("ota", "Got progress %f", x); - on_end: - then: - logger.log: OTA end - on_error: - then: - lambda: >- - ESP_LOGD("ota", "Got error code %d", x); - -logger: - baud_rate: 0 - level: VERBOSE - logs: - mqtt.component: DEBUG - mqtt.client: ERROR - -web_server: - port: 8080 - version: 2 - -power_supply: - id: atx_power_supply - enable_time: 20ms - keep_on_time: 10s - pin: - number: 13 - allow_other_uses: true - inverted: true - -deep_sleep: - run_duration: 20s - sleep_duration: 50s - wakeup_pin: - allow_other_uses: true - number: GPIO2 - ignore_strapping_warning: true - wakeup_pin_mode: INVERT_WAKEUP - -ads1115: - address: 0x48 - i2c_id: i2c_bus - -ads1118: - spi_id: spi_bus - cs_pin: - allow_other_uses: true - number: GPIO12 - -as5600: - i2c_id: i2c_bus - dir_pin: - number: 27 - allow_other_uses: true - direction: clockwise - start_position: 90deg - range: 180deg - watchdog: true - power_mode: low1 - hysteresis: lsb1 - slow_filter: 8x - fast_filter: lsb6 - -as3935_spi: - cs_pin: - ignore_strapping_warning: true - allow_other_uses: true - number: GPIO12 - irq_pin: - allow_other_uses: true - number: GPIO13 - -esp32_ble: - io_capability: keyboard_only - -esp32_ble_tracker: - -ble_client: - - mac_address: AA:BB:CC:DD:EE:FF - id: ble_foo - auto_connect: true - - mac_address: 11:22:33:44:55:66 - id: ble_blah - auto_connect: false - on_connect: - then: - - switch.turn_on: ble1_status - on_disconnect: - then: - - switch.turn_on: ble1_status - on_passkey_request: - then: - - ble_client.passkey_reply: - id: ble_blah - passkey: 123456 - on_passkey_notification: - then: - - logger.log: "Passkey notification received" - on_numeric_comparison_request: - then: - - ble_client.numeric_comparison_reply: - id: ble_blah - accept: true - - mac_address: C4:4F:33:11:22:33 - id: my_bedjet_ble_client - -bedjet: - - ble_client_id: my_bedjet_ble_client - id: my_bedjet_client - time_id: sntp_time -mcp23s08: - - id: mcp23s08_hub - cs_pin: - ignore_strapping_warning: true - number: GPIO12 - allow_other_uses: true - deviceaddress: 0 - -mcp23s17: - - id: mcp23s17_hub - cs_pin: - ignore_strapping_warning: true - number: GPIO12 - allow_other_uses: true - deviceaddress: 1 - -micronova: - enable_rx_pin: - allow_other_uses: true - number: 4 - uart_id: uart_0 - -dfrobot_sen0395: - - id: mmwave - uart_id: dfrobot_mmwave_uart - -sensor: - - platform: xgzp68xx - i2c_id: i2c_bus - temperature: - name: Pressure Temperature - pressure: - name: Differential pressure - k_value: 4096 - - - platform: pmwcs3 - i2c_id: i2c_bus - e25: - name: pmwcs3_e25 - ec: - name: pmwcs3_ec - temperature: - name: pmwcs3_temperature - vwc: - name: pmwcs3_vwc - - platform: gcja5 - pm_1_0: - name: "Particulate Matter <1.0µm Concentration" - pm_2_5: - name: "Particulate Matter <2.5µm Concentration" - pm_10_0: - name: "Particulate Matter <10.0µm Concentration" - pmc_0_5: - name: "PMC 0.5" - pmc_1_0: - name: "PMC 1.0" - pmc_2_5: - name: "PMC 2.5" - pmc_5_0: - name: "PMC 5.0" - pmc_10_0: - name: "PMC 10.0" - uart_id: gcja5_uart - - platform: internal_temperature - name: Internal Temperature - - platform: ble_client - type: characteristic - ble_client_id: ble_foo - name: Green iTag btn - service_uuid: ffe0 - characteristic_uuid: ffe1 - descriptor_uuid: ffe2 - notify: true - update_interval: never - lambda: |- - ESP_LOGD("main", "Length of data is %i", x.size()); - return x[0]; - on_notify: - then: - - lambda: |- - ESP_LOGD("green_btn", "Button was pressed, val%f", x); - - platform: ble_client - type: rssi - ble_client_id: ble_foo - name: Green iTag RSSI - update_interval: 15s - - platform: adc - pin: A0 - name: Living Room Brightness - update_interval: "1:01" - attenuation: 2.5db - unit_of_measurement: "°C" - icon: "mdi:water-percent" - accuracy_decimals: 5 - expire_after: 120s - setup_priority: -100 - force_update: true - filters: - - offset: 2.0 - - multiply: 1.2 - - calibrate_linear: - datapoints: - - 0.0 -> 0.0 - - 40.0 -> 45.0 - - 100.0 -> 102.5 - - clamp: - min_value: -100 - max_value: 100 - - filter_out: 42.0 - - filter_out: nan - - median: - window_size: 5 - send_every: 5 - send_first_at: 3 - - min: - window_size: 5 - send_every: 5 - send_first_at: 3 - - max: - window_size: 5 - send_every: 5 - send_first_at: 3 - - sliding_window_moving_average: - window_size: 15 - send_every: 15 - send_first_at: 15 - - exponential_moving_average: - alpha: 0.1 - send_every: 15 - send_first_at: 15 - - throttle_average: 60s - - throttle: 1s - - heartbeat: 5s - - debounce: 0.1s - - delta: 5.0 - - delta: 1% - - or: - - throttle: 1s - - delta: 5.0 - - lambda: return x * (9.0/5.0) + 32.0; - on_value: - then: - # yamllint disable rule:line-length - - lambda: |- - ESP_LOGD("main", "Got value %f", x); - id(${sensorname}_sensor).publish_state(42.0); - ESP_LOGI("main", "Value of my sensor: %f", id(${sensorname}_sensor).state); - ESP_LOGI("main", "Raw Value of my sensor: %f", id(${sensorname}_sensor).state); - # yamllint enable rule:line-length - on_value_range: - above: 5 - below: 10 - then: - - lambda: >- - ESP_LOGD("main", "Got value range %f", x); - - wait_until: wifi.connected - - wait_until: - condition: - binary_sensor.is_on: binary_sensor1 - timeout: 1s - on_raw_value: - - lambda: >- - ESP_LOGD("main", "Got raw value %f", x); - - logger.log: - level: DEBUG - format: Got raw value %f - args: ["x"] - - logger.log: Got raw value NAN - - mqtt.publish: - topic: some/topic - payload: Hello - qos: 2 - retain: true - - platform: esp32_hall - name: ESP32 Hall Sensor - - platform: ads1115 - multiplexer: A0_A1 - gain: 1.024 - id: ${sensorname}_sensor - filters: - state_topic: hi/me - retain: false - availability: - - platform: ads1118 - name: ads1118 adc - multiplexer: A0_A1 - gain: 1.024 - type: adc - - platform: ads1118 - name: ads1118 temperature - type: temperature - - platform: as5600 - name: AS5600 Position - raw_position: - name: AS5600 Raw Position - gain: - name: AS5600 Gain - magnitude: - name: AS5600 Magnitude - status: - name: AS5600 Status - - platform: as7341 - update_interval: 15s - gain: X8 - atime: 120 - astep: 99 - f1: - name: F1 - f2: - name: F2 - f3: - name: F3 - f4: - name: F4 - f5: - name: F5 - f6: - name: F6 - f7: - name: F7 - f8: - name: F8 - clear: - name: Clear - nir: - name: NIR - i2c_id: i2c_bus - - platform: atm90e26 - cs_pin: - allow_other_uses: true - number: 5 - voltage: - name: Line Voltage - current: - name: CT Amps - power: - name: Active Watts - power_factor: - name: Power Factor - frequency: - name: Line Frequency - line_frequency: 50Hz - meter_constant: 1000 - pl_const: 1429876 - gain_pga: 1X - gain_metering: 7481 - gain_voltage: 26400 - gain_ct: 31251 - - platform: atm90e32 - cs_pin: - allow_other_uses: true - number: 5 - phase_a: - voltage: - name: EMON Line Voltage A - current: - name: EMON CT1 Current - power: - name: EMON Active Power CT1 - reactive_power: - name: EMON Reactive Power CT1 - power_factor: - name: EMON Power Factor CT1 - gain_voltage: 7305 - gain_ct: 27961 - phase_b: - current: - name: EMON CT2 Current - power: - name: EMON Active Power CT2 - reactive_power: - name: EMON Reactive Power CT2 - power_factor: - name: EMON Power Factor CT2 - gain_voltage: 7305 - gain_ct: 27961 - phase_c: - current: - name: EMON CT3 Current - power: - name: EMON Active Power CT3 - reactive_power: - name: EMON Reactive Power CT3 - power_factor: - name: EMON Power Factor CT3 - gain_voltage: 7305 - gain_ct: 27961 - frequency: - name: EMON Line Frequency - chip_temperature: - name: EMON Chip Temp A - line_frequency: 60Hz - current_phases: 3 - gain_pga: 2X - - platform: bh1750 - name: Living Room Brightness 3 - internal: true - address: 0x23 - update_interval: 30s - qos: 2 - retain: false - availability: - state_topic: livingroom/custom_state_topic - i2c_id: i2c_bus - - platform: max44009 - name: Outside Brightness 1 - internal: true - address: 0x4A - update_interval: 30s - mode: low_power - i2c_id: i2c_bus - - platform: bme680 - temperature: - name: Outside Temperature - oversampling: 16x - pressure: - name: Outside Pressure - humidity: - name: Outside Humidity - gas_resistance: - name: Outside Gas Sensor - address: 0x77 - heater: - temperature: 320 - duration: 150ms - update_interval: 15s - i2c_id: i2c_bus - - platform: bmp085 - temperature: - name: Outside Temperature - pressure: - name: Outside Pressure - filters: - - lambda: >- - return x / powf(1.0 - (x / 44330.0), 5.255); - update_interval: 15s - i2c_id: i2c_bus - - platform: bmp280 - temperature: - name: Outside Temperature - oversampling: 16x - pressure: - name: Outside Pressure - address: 0x77 - update_interval: 15s - iir_filter: 16x - i2c_id: i2c_bus - - platform: dht - pin: - allow_other_uses: true - number: GPIO26 - temperature: - id: dht_temperature - name: Living Room Temperature 3 - humidity: - id: dht_humidity - name: Living Room Humidity 3 - model: AM2302 - update_interval: 15s - - platform: dht12 - temperature: - name: Living Room Temperature 4 - humidity: - name: Living Room Humidity 4 - update_interval: 15s - i2c_id: i2c_bus - - platform: duty_cycle - pin: - allow_other_uses: true - number: GPIO25 - name: Duty Cycle Sensor - - platform: ee895 - co2: - name: Office CO2 1 - temperature: - name: Office Temperature 1 - pressure: - name: Office Pressure 1 - address: 0x5F - i2c_id: i2c_bus - - platform: esp32_hall - name: ESP32 Hall Sensor - update_interval: 15s - - platform: ens210 - temperature: - name: Living Room Temperature 5 - humidity: - name: Living Room Humidity 5 - update_interval: 15s - i2c_id: i2c_bus - - platform: hdc1080 - temperature: - name: Living Room Temperature 6 - humidity: - name: Living Room Humidity 5 - update_interval: 15s - i2c_id: i2c_bus - - platform: hlw8012 - sel_pin: - allow_other_uses: true - number: 5 - cf_pin: - allow_other_uses: true - number: 14 - cf1_pin: - allow_other_uses: true - number: 13 - current: - name: HLW8012 Current - voltage: - name: HLW8012 Voltage - power: - name: HLW8012 Power - id: hlw8012_power - energy: - name: HLW8012 Energy - id: hlw8012_energy - update_interval: 15s - current_resistor: 0.001 ohm - voltage_divider: 2351 - change_mode_every: "never" - initial_mode: VOLTAGE - model: hlw8012 - - platform: total_daily_energy - power_id: hlw8012_power - name: HLW8012 Total Daily Energy - - platform: integration - sensor: hlw8012_power - name: Integration Sensor - time_unit: s - - platform: integration - sensor: hlw8012_power - name: Integration Sensor lazy - time_unit: s - - platform: hmc5883l - address: 0x68 - field_strength_x: - name: HMC5883L Field Strength X - field_strength_y: - name: HMC5883L Field Strength Y - field_strength_z: - name: HMC5883L Field Strength Z - heading: - name: HMC5883L Heading - range: 130uT - oversampling: 8x - update_interval: 15s - i2c_id: i2c_bus - - platform: honeywell_hih_i2c - temperature: - name: Living Room Temperature 7 - humidity: - name: Living Room Humidity 7 - update_interval: 15s - i2c_id: i2c_bus - - platform: honeywellabp - pressure: - name: Honeywell pressure - min_pressure: 0 - max_pressure: 15 - temperature: - name: Honeywell temperature - cs_pin: - allow_other_uses: true - number: GPIO5 - - platform: honeywellabp2_i2c - pressure: - name: Honeywell2 pressure - min_pressure: 0 - max_pressure: 16000 - transfer_function: A - temperature: - name: Honeywell temperature - i2c_id: i2c_bus - address: 0x28 - - platform: hte501 - temperature: - name: Office Temperature 2 - humidity: - name: Office Humidity 1 - address: 0x40 - i2c_id: i2c_bus - - platform: qmc5883l - address: 0x0D - field_strength_x: - name: QMC5883L Field Strength X - field_strength_y: - name: QMC5883L Field Strength Y - field_strength_z: - name: QMC5883L Field Strength Z - heading: - name: QMC5883L Heading - range: 800uT - oversampling: 256x - update_interval: 15s - i2c_id: i2c_bus - - platform: hx711 - name: HX711 Value - dout_pin: - allow_other_uses: true - number: GPIO23 - clk_pin: - allow_other_uses: true - number: GPIO25 - gain: 128 - update_interval: 15s - - platform: ina219 - address: 0x40 - shunt_resistance: 0.1 ohm - current: - name: INA219 Current - power: - name: INA219 Power - bus_voltage: - name: INA219 Bus Voltage - shunt_voltage: - name: INA219 Shunt Voltage - max_voltage: 32.0V - max_current: 3.2A - update_interval: 15s - i2c_id: i2c_bus - - platform: ina226 - address: 0x40 - shunt_resistance: 0.1 ohm - current: - name: INA226 Current - power: - name: INA226 Power - bus_voltage: - name: INA226 Bus Voltage - shunt_voltage: - name: INA226 Shunt Voltage - max_current: 3.2A - update_interval: 15s - i2c_id: i2c_bus - - platform: ina3221 - address: 0x40 - channel_1: - shunt_resistance: 0.1 ohm - current: - name: INA3221 Channel 1 Current - power: - name: INA3221 Channel 1 Power - bus_voltage: - name: INA3221 Channel 1 Bus Voltage - shunt_voltage: - name: INA3221 Channel 1 Shunt Voltage - update_interval: 15s - i2c_id: i2c_bus - - platform: kmeteriso - temperature: - name: Outside Temperature - internal_temperature: - name: Internal Ttemperature - update_interval: 15s - i2c_id: i2c_bus - - platform: combination - type: kalman - name: Kalman-filtered temperature - process_std_dev: 0.00139 - sources: - - source: scd30_temperature - error: !lambda |- - return 0.4 + std::abs(x - 25) * 0.023; - - source: scd4x_temperature - error: 1.5 - - platform: combination - type: linear - name: Linearly combined temperatures - sources: - - source: scd30_temperature - coeffecient: !lambda |- - return 0.4 + std::abs(x - 25) * 0.023; - - source: scd4x_temperature - coeffecient: 1.5 - - platform: combination - type: max - name: Max of combined temperatures - sources: - - source: scd30_temperature - - source: scd4x_temperature - - platform: combination - type: mean - name: Mean of combined temperatures - sources: - - source: scd30_temperature - - source: scd4x_temperature - - platform: combination - type: median - name: Median of combined temperatures - sources: - - source: scd30_temperature - - source: scd4x_temperature - - platform: combination - type: min - name: Min of combined temperatures - sources: - - source: scd30_temperature - - source: scd4x_temperature - - platform: combination - type: most_recently_updated - name: Most recently updated of combined temperatures - sources: - - source: scd30_temperature - - source: scd4x_temperature - - platform: combination - type: range - name: Range of combined temperatures - sources: - - source: scd30_temperature - - source: scd4x_temperature - - platform: combination - type: sum - name: Sum of combined temperatures - sources: - - source: scd30_temperature - - source: scd4x_temperature - - platform: htu21d - temperature: - name: Living Room Temperature 6 - humidity: - name: Living Room Humidity 6 - heater: - name: Living Room Heater 6 - update_interval: 15s - i2c_id: i2c_bus - - platform: max6675 - name: Living Room Temperature - cs_pin: - allow_other_uses: true - number: GPIO23 - update_interval: 15s - - platform: max31855 - name: Den Temperature - cs_pin: - allow_other_uses: true - number: GPIO23 - update_interval: 15s - reference_temperature: - name: MAX31855 Internal Temperature - - platform: max31856 - name: BBQ Temperature - cs_pin: - allow_other_uses: true - number: GPIO17 - update_interval: 15s - mains_filter: 50Hz - - platform: max31865 - name: Water Tank Temperature - cs_pin: - allow_other_uses: true - number: GPIO23 - update_interval: 15s - reference_resistance: 430 Ω - rtd_nominal_resistance: 100 Ω - - platform: mhz19 - uart_id: uart_0 - co2: - name: MH-Z19 CO2 Value - temperature: - name: MH-Z19 Temperature - update_interval: 15s - automatic_baseline_calibration: false - - platform: mpu6050 - address: 0x68 - accel_x: - name: MPU6050 Accel X - accel_y: - name: MPU6050 Accel Y - accel_z: - name: MPU6050 Accel z - gyro_x: - name: MPU6050 Gyro X - gyro_y: - name: MPU6050 Gyro Y - gyro_z: - name: MPU6050 Gyro z - temperature: - name: MPU6050 Temperature - i2c_id: i2c_bus - - platform: mpu6886 - address: 0x68 - accel_x: - name: MPU6886 Accel X - accel_y: - name: MPU6886 Accel Y - accel_z: - name: MPU6886 Accel z - gyro_x: - name: MPU6886 Gyro X - gyro_y: - name: MPU6886 Gyro Y - gyro_z: - name: MPU6886 Gyro z - temperature: - name: MPU6886 Temperature - i2c_id: i2c_bus - - platform: bmi160 - address: 0x68 - acceleration_x: - name: BMI160 Accel X - acceleration_y: - name: BMI160 Accel Y - acceleration_z: - name: BMI160 Accel z - gyroscope_x: - name: BMI160 Gyro X - gyroscope_y: - name: BMI160 Gyro Y - gyroscope_z: - name: BMI160 Gyro z - temperature: - name: BMI160 Temperature - i2c_id: i2c_bus - - platform: mmc5603 - address: 0x30 - field_strength_x: - name: HMC5883L Field Strength X - field_strength_y: - name: HMC5883L Field Strength Y - field_strength_z: - name: HMC5883L Field Strength Z - i2c_id: i2c_bus - - platform: dps310 - temperature: - name: DPS310 Temperature - pressure: - name: DPS310 Pressure - address: 0x77 - update_interval: 15s - i2c_id: i2c_bus - - platform: ms5611 - temperature: - name: Outside Temperature - pressure: - name: Outside Pressure - address: 0x77 - update_interval: 15s - i2c_id: i2c_bus - - platform: pmsa003i - pm_1_0: - name: PMSA003i PM1.0 - pm_2_5: - name: PMSA003i PM2.5 - pm_10_0: - name: PMSA003i PM10.0 - pmc_0_3: - name: PMSA003i PMC <0.3µm - pmc_0_5: - name: PMSA003i PMC <0.5µm - pmc_1_0: - name: PMSA003i PMC <1µm - pmc_2_5: - name: PMSA003i PMC <2.5µm - pmc_5_0: - name: PMSA003i PMC <5µm - pmc_10_0: - name: PMSA003i PMC <10µm - address: 0x12 - standard_units: true - i2c_id: i2c_bus - - platform: pulse_counter - name: Pulse Counter - pin: - ignore_strapping_warning: true - number: GPIO12 - allow_other_uses: true - count_mode: - rising_edge: INCREMENT - falling_edge: DECREMENT - internal_filter: 13us - update_interval: 15s - - platform: pulse_meter - name: Pulse Meter - id: pulse_meter_sensor - pin: - ignore_strapping_warning: true - number: GPIO12 - allow_other_uses: true - internal_filter: 100ms - timeout: 2 min - on_value: - - pulse_meter.set_total_pulses: - id: pulse_meter_sensor - value: 12345 - total: - name: Pulse Meter Total - - platform: qmp6988 - temperature: - name: Living Temperature QMP - oversampling: 32x - pressure: - name: Living Pressure QMP - oversampling: 2x - address: 0x70 - update_interval: 30s - iir_filter: 16x - i2c_id: i2c_bus - - platform: rotary_encoder - name: Rotary Encoder - id: rotary_encoder1 - pin_a: - allow_other_uses: true - number: GPIO23 - pin_b: - allow_other_uses: true - number: GPIO25 - pin_reset: - allow_other_uses: true - number: GPIO25 - filters: - - or: - - debounce: 0.1s - - delta: 10 - resolution: 4 - min_value: -10 - max_value: 30 - on_value: - - sensor.rotary_encoder.set_value: - id: rotary_encoder1 - value: 10 - - sensor.rotary_encoder.set_value: - id: rotary_encoder1 - value: !lambda "return -1;" - on_clockwise: - - logger.log: Clockwise - - display_menu.down: test_lcd_menu - - display_menu.down: test_graphical_display_menu - on_anticlockwise: - - logger.log: Anticlockwise - - display_menu.up: test_lcd_menu - - display_menu.up: test_graphical_display_menu - - platform: pulse_width - name: Pulse Width - pin: - allow_other_uses: true - number: GPIO12 - - platform: sm300d2 - uart_id: uart_0 - co2: - name: SM300D2 CO2 Value - formaldehyde: - name: SM300D2 Formaldehyde Value - tvoc: - name: SM300D2 TVOC Value - pm_2_5: - name: SM300D2 PM2.5 Value - pm_10_0: - name: SM300D2 PM10 Value - temperature: - name: SM300D2 Temperature Value - humidity: - name: SM300D2 Humidity Value - update_interval: 60s - - platform: sht3xd - temperature: - name: Living Room Temperature 8 - humidity: - name: Living Room Humidity 8 - address: 0x44 - i2c_id: i2c_bus - update_interval: 15s - - platform: sts3x - name: Living Room Temperature 9 - address: 0x4A - i2c_id: i2c_bus - - platform: scd30 - co2: - name: Living Room CO2 9 - temperature: - id: scd30_temperature - name: Living Room Temperature 9 - humidity: - name: Living Room Humidity 9 - address: 0x61 - update_interval: 15s - automatic_self_calibration: true - altitude_compensation: 10m - ambient_pressure_compensation: 961mBar - temperature_offset: 4.2C - i2c_id: i2c_bus - - platform: scd4x - id: scd40 - co2: - name: SCD4X CO2 - temperature: - id: scd4x_temperature - name: SCD4X Temperature - humidity: - name: SCD4X Humidity - update_interval: 15s - automatic_self_calibration: true - altitude_compensation: 10m - ambient_pressure_compensation: 961mBar - temperature_offset: 4.2C - i2c_id: i2c_bus - - platform: sfa30 - formaldehyde: - name: "SFA30 formaldehyde" - temperature: - name: "SFA30 temperature" - humidity: - name: "SFA30 humidity" - i2c_id: i2c_bus - address: 0x5D - update_interval: 30s - - platform: sen0321 - name: Workshop Ozone Sensor - id: sen0321_ozone - update_interval: 10s - i2c_id: i2c_bus - - platform: sgp30 - eco2: - name: Workshop eCO2 - accuracy_decimals: 1 - tvoc: - name: Workshop TVOC - accuracy_decimals: 1 - address: 0x58 - update_interval: 5s - i2c_id: i2c_bus - - platform: sps30 - pm_1_0: - name: Workshop PM <1µm Weight concentration - id: workshop_PM_1_0 - pm_2_5: - name: Workshop PM <2.5µm Weight concentration - id: workshop_PM_2_5 - pm_4_0: - name: Workshop PM <4µm Weight concentration - id: workshop_PM_4_0 - pm_10_0: - name: Workshop PM <10µm Weight concentration - id: workshop_PM_10_0 - pmc_0_5: - name: Workshop PM <0.5µm Number concentration - id: workshop_PMC_0_5 - pmc_1_0: - name: Workshop PM <1µm Number concentration - id: workshop_PMC_1_0 - pmc_2_5: - name: Workshop PM <2.5µm Number concentration - id: workshop_PMC_2_5 - pmc_4_0: - name: Workshop PM <4µm Number concentration - id: workshop_PMC_4_0 - pmc_10_0: - name: Workshop PM <10µm Number concentration - id: workshop_PMC_10_0 - address: 0x69 - update_interval: 10s - i2c_id: i2c_bus - - platform: sht4x - temperature: - name: SHT4X Temperature - humidity: - name: SHT4X Humidity - address: 0x44 - update_interval: 15s - i2c_id: i2c_bus - - platform: shtcx - temperature: - name: Living Room Temperature 10 - humidity: - name: Living Room Humidity 10 - address: 0x70 - update_interval: 15s - i2c_id: i2c_bus - - platform: template - name: Template Sensor - state_class: measurement - id: template_sensor - lambda: |- - if (id(ultrasonic_sensor1).state > 1) { - return 42.0; - } else { - return {}; - } - update_interval: 15s - on_value: - - sensor.template.publish: - id: template_sensor - state: 43.0 - - sensor.template.publish: - id: template_sensor - state: !lambda "return NAN;" - - platform: tsl2561 - name: TSL2561 Ambient Light - address: 0x39 - update_interval: 15s - is_cs_package: true - integration_time: 402ms - gain: 16x - i2c_id: i2c_bus - - platform: tsl2591 - id: this_little_light_of_mine - address: 0x29 - update_interval: 15s - integration_time: 600ms - gain: high - visible: - name: tsl2591 visible - id: tsl2591_vis - unit_of_measurement: pH - infrared: - name: tsl2591 infrared - id: tsl2591_ir - full_spectrum: - name: tsl2591 full_spectrum - id: tsl2591_fs - calculated_lux: - name: tsl2591 calculated_lux - id: tsl2591_cl - i2c_id: i2c_bus - - platform: veml3235 - id: veml3235_sensor - name: VEML3235 Light Sensor - i2c_id: i2c_bus - auto_gain: true - auto_gain_threshold_high: 90% - auto_gain_threshold_low: 15% - digital_gain: 1X - gain: 1X - integration_time: 50ms - - platform: tee501 - name: Office Temperature 3 - address: 0x48 - i2c_id: i2c_bus - - platform: ultrasonic - trigger_pin: - allow_other_uses: true - number: GPIO25 - echo_pin: - number: GPIO23 - allow_other_uses: true - inverted: true - name: Ultrasonic Sensor - timeout: 5.5m - id: ultrasonic_sensor1 - - platform: uptime - name: Uptime Sensor - - id: !extend ${devicename}_uptime_pcg - unit_of_measurement: s - - platform: wifi_signal - name: WiFi Signal Sensor - update_interval: 15s - - platform: mqtt_subscribe - name: MQTT Subscribe Sensor 1 - topic: mqtt/topic - id: the_sensor - qos: 2 - on_value: - - mqtt.publish_json: - topic: the/topic - payload: |- - root["key"] = id(the_sensor).state; - root["greeting"] = "Hello World"; - - platform: sds011 - uart_id: uart_0 - pm_2_5: - name: SDS011 PM2.5 - pm_10_0: - name: SDS011 PM10.0 - update_interval: 5min - rx_only: false - - platform: ccs811 - eco2: - name: CCS811 eCO2 - tvoc: - name: CCS811 TVOC - update_interval: 30s - baseline: 0x4242 - i2c_id: i2c_bus - - platform: tx20 - wind_speed: - name: Windspeed - wind_direction_degrees: - name: Winddirection Degrees - pin: - number: GPIO04 - mode: INPUT - allow_other_uses: true - - platform: zyaura - clock_pin: - allow_other_uses: true - number: GPIO5 - data_pin: - allow_other_uses: true - number: GPIO4 - co2: - name: ZyAura CO2 - temperature: - name: ZyAura Temperature - humidity: - name: ZyAura Humidity - - platform: as3935 - lightning_energy: - name: Lightning Energy - distance: - name: Distance Storm - - platform: tmp117 - name: TMP117 Temperature - update_interval: 5s - i2c_id: i2c_bus - - platform: hm3301 - pm_1_0: - name: PM1.0 - pm_2_5: - name: PM2.5 - pm_10_0: - name: PM10.0 - aqi: - name: AQI - calculation_type: CAQI - i2c_id: i2c_bus - - platform: teleinfo - tag_name: HCHC - name: hchc - unit_of_measurement: Wh - icon: mdi:flash - teleinfo_id: myteleinfo - - platform: mcp9808 - name: MCP9808 Temperature - update_interval: 15s - i2c_id: i2c_bus - - platform: ezo - id: ph_ezo - address: 99 - unit_of_measurement: pH - i2c_id: i2c_bus - - platform: sdp3x - name: HVAC Filter Pressure drop - id: filter_pressure - update_interval: 5s - accuracy_decimals: 3 - i2c_id: i2c_bus - - platform: cs5460a - id: cs5460a1 - current: - name: Socket current - voltage: - name: Mains voltage - power: - name: Socket power - on_value: - then: - cs5460a.restart: cs5460a1 - samples: 1600 - pga_gain: 10X - current_gain: 0.01 - voltage_gain: 0.000573 - current_hpf: true - voltage_hpf: true - phase_offset: 20 - pulse_energy: 0.01 kWh - cs_pin: - mcp23xxx: mcp23017_hub - number: 14 - - platform: max9611 - i2c_id: i2c_bus - shunt_resistance: 0.2 ohm - gain: 1X - voltage: - name: Max9611 Voltage - current: - name: Max9611 Current - power: - name: Max9611 Watts - temperature: - name: Max9611 Temp - update_interval: 1s - - platform: mlx90614 - i2c_id: i2c_bus - ambient: - name: Ambient - object: - name: Object - emissivity: 1.0 - - platform: mpl3115a2 - i2c_id: i2c_bus - temperature: - name: "MPL3115A2 Temperature" - pressure: - name: "MPL3115A2 Pressure" - update_interval: 10s - - platform: alpha3 - ble_client_id: ble_foo - flow: - name: "Radiator Pump Flow" - head: - name: "Radiator Pump Head" - power: - name: "Radiator Pump Power" - speed: - name: "Radiator Pump Speed" - - platform: ld2410 - light: - name: light - moving_distance: - name: "Moving distance (cm)" - still_distance: - name: "Still Distance (cm)" - moving_energy: - name: "Move Energy (%)" - still_energy: - name: "Still Energy (%)" - detection_distance: - name: "Distance Detection (cm)" - g0: - move_energy: - name: g0 move energy - still_energy: - name: g0 still energy - g1: - move_energy: - name: g1 move energy - still_energy: - name: g1 still energy - g2: - move_energy: - name: g2 move energy - still_energy: - name: g2 still energy - g3: - move_energy: - name: g3 move energy - still_energy: - name: g3 still energy - g4: - move_energy: - name: g4 move energy - still_energy: - name: g4 still energy - g5: - move_energy: - name: g5 move energy - still_energy: - name: g5 still energy - g6: - move_energy: - name: g6 move energy - still_energy: - name: g6 still energy - g7: - move_energy: - name: g7 move energy - still_energy: - name: g7 still energy - g8: - move_energy: - name: g8 move energy - still_energy: - name: g8 still energy - - - platform: ld2420 - moving_distance: - name: "Moving distance (cm)" - - platform: sen21231 - name: "Person Sensor" - i2c_id: i2c_bus - - platform: fs3000 - name: "Air Velocity" - model: 1005 - update_interval: 60s - i2c_id: i2c_bus - - platform: absolute_humidity - name: DHT Absolute Humidity - temperature: dht_temperature - humidity: dht_humidity - - platform: hyt271 - i2c_id: i2c_bus - temperature: - name: "Temperature hyt271" - id: temp_etuve - humidity: - name: "Humidity hyt271" - - platform: iaqcore - i2c_id: i2c_bus - co2: - name: "iAQ Core CO2 Sensor" - tvoc: - name: "iAQ Core TVOC Sensor" - - platform: tmp1075 - name: "Temperature TMP1075" - update_interval: 10s - i2c_id: i2c_bus - conversion_rate: 27.5ms - alert: - limit_low: 50 - limit_high: 75 - fault_count: 1 - polarity: active_high - function: comparator - - platform: zio_ultrasonic - name: "Distance" - update_interval: 60s - i2c_id: i2c_bus - - platform: bmp581 - i2c_id: i2c_bus - temperature: - name: "BMP581 Temperature" - iir_filter: 2x - pressure: - name: "BMP581 Pressure" - oversampling: 128x - - platform: debug - free: - name: "Heap Free" - block: - name: "Heap Max Block" - loop_time: - name: "Loop Time" - psram: - name: "PSRAM Free" - - platform: mmc5983 - i2c_id: i2c_bus - field_strength_x: - name: "Magnet X" - id: magnet_x - field_strength_y: - name: "Magnet Y" - id: magnet_y - field_strength_z: - name: "Magnet Z" - id: magnet_z - - platform: micronova - room_temperature: - name: Room Temperature - fumes_temperature: - name: Fumes Temperature - water_temperature: - name: Water temperature - water_pressure: - name: Water pressure - stove_power: - name: Stove Power - fan_speed: - fan_rpm_offset: 240 - name: Fan RPM - memory_address_sensor: - memory_location: 0x20 - memory_address: 0x7d - name: Adres sensor - - platform: ade7880 - i2c_id: i2c_bus - irq0_pin: - number: GPIO13 - allow_other_uses: true - irq1_pin: - number: GPIO5 - allow_other_uses: true - reset_pin: - number: GPIO16 - allow_other_uses: true - frequency: 60Hz - phase_a: - name: Channel A - voltage: Voltage - current: Current - active_power: Active Power - power_factor: Power Factor - forward_active_energy: Forward Active Energy - reverse_active_energy: Reverse Active Energy - calibration: - current_gain: 3116628 - voltage_gain: -757178 - power_gain: -1344457 - phase_angle: 188 - phase_b: - name: Channel B - voltage: Voltage - current: Current - active_power: Active Power - power_factor: Power Factor - forward_active_energy: Forward Active Energy - reverse_active_energy: Reverse Active Energy - calibration: - current_gain: 3133655 - voltage_gain: -755235 - power_gain: -1345638 - phase_angle: 188 - phase_c: - name: Channel C - voltage: Voltage - current: Current - active_power: Active Power - power_factor: Power Factor - forward_active_energy: Forward Active Energy - reverse_active_energy: Reverse Active Energy - calibration: - current_gain: 3111158 - voltage_gain: -743813 - power_gain: -1351437 - phase_angle: 180 - neutral: - name: Neutral - current: Current - calibration: - current_gain: 3189 - -psram: - -esp32_touch: - setup_mode: false - iir_filter: 10ms - sleep_duration: 27ms - measurement_duration: 8ms - low_voltage_reference: 0.5V - high_voltage_reference: 2.7V - voltage_attenuation: 1.5V - -binary_sensor: - - platform: gpio - name: "MCP23S08 Pin #1" - pin: - mcp23xxx: mcp23s08_hub - # Use pin number 1 - number: 1 - # One of INPUT or INPUT_PULLUP - mode: INPUT_PULLUP - inverted: false - - platform: gpio - name: "MCP23S17 Pin #1" - pin: - mcp23xxx: mcp23s17_hub - # Use pin number 1 - number: 1 - allow_other_uses: true - # One of INPUT or INPUT_PULLUP - mode: INPUT_PULLUP - inverted: false - - platform: gpio - name: "MCP23S17 Pin #1 with interrupt" - pin: - mcp23xxx: mcp23s17_hub - # Use pin number 1 - allow_other_uses: true - number: 1 - # One of INPUT or INPUT_PULLUP - mode: INPUT_PULLUP - inverted: false - interrupt: FALLING - - platform: gpio - pin: - allow_other_uses: true - number: GPIO9 - name: Living Room Window - device_class: window - filters: - - invert: - - delayed_on_off: 40ms - - delayed_on_off: - time_on: 10s - time_off: !lambda "return 1000;" - - delayed_on: 40ms - - delayed_off: 40ms - - delayed_on_off: !lambda "return 10;" - - delayed_on: !lambda "return 1000;" - - delayed_off: !lambda "return 0;" - - settle: 40ms - - settle: !lambda "return 10;" - on_press: - then: - - lambda: >- - ESP_LOGD("main", "Pressed"); - on_release: - then: - - lambda: >- - ESP_LOGD("main", "Released"); - on_click: - - min_length: 50ms - max_length: 350ms - then: - - lambda: >- - ESP_LOGD("main", "Clicked"); - - then: - - lambda: >- - ESP_LOGD("main", "Clicked"); - on_double_click: - - min_length: 50ms - max_length: 350ms - then: - - lambda: >- - ESP_LOGD("main", "Double Clicked"); - - then: - - lambda: >- - ESP_LOGD("main", "Double Clicked"); - on_multi_click: - - timing: - - ON for at most 1s - - OFF for at most 1s - - ON for at most 1s - - OFF for at least 0.2s - then: - - logger.log: - format: Multi Clicked TWO - level: warn - - timing: - - OFF for 1s to 2s - - ON for 1s to 2s - - OFF for at least 0.5s - then: - - logger.log: - format: Multi Clicked LONG SINGLE - level: warn - - timing: - - ON for at most 1s - - OFF for at least 0.5s - then: - - logger.log: - format: Multi Clicked SINGLE - level: warn - id: binary_sensor1 - - platform: gpio - pin: - number: GPIO9 - allow_other_uses: true - mode: INPUT_PULLUP - name: Living Room Window 2 - - platform: gpio - pin: - number: GPIO9 - allow_other_uses: true - mode: INPUT_OUTPUT_OPEN_DRAIN - name: Living Room Button - - platform: status - name: Living Room Status - - platform: esp32_touch - name: ESP32 Touch Pad GPIO27 - pin: GPIO27 - threshold: 1000 - id: btn_left - on_press: - - if: - condition: - display_menu.is_active: test_lcd_menu - then: - - display_menu.enter: test_lcd_menu - else: - - display_menu.left: test_lcd_menu - - display_menu.right: test_lcd_menu - - display_menu.show: test_lcd_menu - - if: - condition: - display_menu.is_active: test_graphical_display_menu - then: - - display_menu.enter: test_graphical_display_menu - else: - - display_menu.left: test_graphical_display_menu - - display_menu.right: test_graphical_display_menu - - display_menu.show: test_graphical_display_menu - - platform: template - name: Garage Door Open - id: garage_door - lambda: |- - if (isnan(id(${sensorname}_sensor).state)) { - // isnan checks if the ultrasonic sensor echo - // has timed out, resulting in a NaN (not a number) state - // in that case, return {} to indicate that we don't know. - return {}; - } else if (id(${sensorname}_sensor).state > 30) { - // Garage Door is open. - return true; - } else { - // Garage Door is closed. - return false; - } - on_press: - - binary_sensor.template.publish: - id: garage_door - state: false - - output.ledc.set_frequency: - id: gpio_19 - frequency: 500.0Hz - - output.ledc.set_frequency: - id: gpio_19 - frequency: !lambda "return 500.0;" - - platform: pn532 - pn532_id: pn532_bs - uid: 74-10-37-94 - name: PN532 NFC Tag - - platform: rdm6300 - uid: 7616525 - name: RDM6300 NFC Tag - - platform: gpio - name: PCF binary sensor - pin: - pcf8574: pcf8574_hub - number: 1 - mode: INPUT - inverted: true - - platform: gpio - name: PCA9554 binary sensor - pin: - pca9554: pca9554_hub - number: 1 - mode: INPUT - inverted: true - - platform: gpio - name: PCA6416A binary sensor - pin: - pca6416a: pca6416a_hub - number: 15 - mode: INPUT - inverted: true - - platform: gpio - name: MCP21 binary sensor - pin: - mcp23xxx: mcp23017_hub - number: 1 - allow_other_uses: true - mode: INPUT - inverted: true - - platform: gpio - name: MCP22 binary sensor - pin: - mcp23xxx: mcp23008_hub - number: 7 - mode: INPUT_PULLUP - inverted: false - - platform: gpio - name: MCP23 binary sensor - pin: - mcp23016: mcp23016_hub - number: 7 - mode: INPUT - inverted: false - - platform: gpio - name: Speed Fan Cycle binary sensor" - pin: - number: 18 - allow_other_uses: true - mode: - input: true - pulldown: true - on_press: - - fan.cycle_speed: - id: fan_speed - off_speed_cycle: false - - logger.log: "Cycle speed clicked" - - platform: remote_receiver - name: Raw Remote Receiver Test - raw: - code: - [ - 5685, - -4252, - 1711, - -2265, - 1712, - -2265, - 1711, - -2264, - 1712, - -2266, - 3700, - -2263, - 1712, - -4254, - 1711, - -4249, - 1715, - -2266, - 1710, - -2267, - 1709, - -2265, - 3704, - -4250, - 1712, - -4254, - 3700, - -2260, - 1714, - -2265, - 1712, - -2262, - 1714, - -2267, - 1709, - ] - - platform: remote_receiver - name: Coolix Test 1 - coolix: 0xB21F98 - - platform: remote_receiver - name: Coolix Test 2 - coolix: - first: 0xB2E003 - - platform: remote_receiver - name: Coolix Test 3 - coolix: - first: 0xB2E003 - second: 0xB21F98 - - platform: as3935 - name: Storm Alert - - platform: analog_threshold - name: Analog Trheshold 1 - sensor_id: template_sensor - threshold: - upper: 110 - lower: 90 - filters: - - delayed_on: 0s - - delayed_off: 10s - - platform: analog_threshold - name: Analog Trheshold 2 - sensor_id: template_sensor - threshold: 100 - filters: - - invert: - - platform: template - id: open_endstop_sensor - - platform: template - id: open_sensor - - platform: template - id: open_obstacle_sensor - - - platform: template - id: close_endstop_sensor - - platform: template - id: close_sensor - - platform: template - id: close_obstacle_sensor - - platform: ld2410 - has_target: - name: presence - has_moving_target: - name: movement - has_still_target: - name: still - out_pin_presence_status: - name: out pin presence status - - platform: qwiic_pir - i2c_id: i2c_bus - name: "Qwiic PIR Motion Sensor" - - platform: dfrobot_sen0395 - id: mmwave_detected_uart - dfrobot_sen0395_id: mmwave - - platform: nfc - nfcc_id: nfcc_pn7160_i2c - ndef_contains: pulse - name: MFC Tag 1 - - platform: nfc - nfcc_id: nfcc_pn7160_i2c - tag_id: pulse - name: MFC Tag 2 - - platform: nfc - nfcc_id: nfcc_pn7160_i2c - uid: 59-FC-AB-15 - name: MFC Tag 3 - -pca9685: - frequency: 500 - address: 0x0 - i2c_id: i2c_bus - -tlc59208f: - - address: 0x20 - id: tlc59208f_1 - i2c_id: i2c_bus - - address: 0x22 - id: tlc59208f_2 - i2c_id: i2c_bus - - address: 0x24 - id: tlc59208f_3 - i2c_id: i2c_bus - -my9231: - data_pin: - allow_other_uses: true - number: GPIO12 - clock_pin: - allow_other_uses: true - number: GPIO14 - num_channels: 6 - num_chips: 2 - bit_depth: 16 - -sm2235: - data_pin: - allow_other_uses: true - number: GPIO4 - clock_pin: - allow_other_uses: true - number: GPIO5 - max_power_color_channels: 9 - max_power_white_channels: 9 - -sm2335: - data_pin: - allow_other_uses: true - number: GPIO4 - clock_pin: - allow_other_uses: true - number: GPIO5 - max_power_color_channels: 9 - max_power_white_channels: 9 - -bp1658cj: - data_pin: - allow_other_uses: true - number: GPIO3 - clock_pin: - allow_other_uses: true - number: GPIO5 - max_power_color_channels: 4 - max_power_white_channels: 6 - -bp5758d: - data_pin: - allow_other_uses: true - number: GPIO3 - clock_pin: - allow_other_uses: true - number: GPIO5 - -output: - - platform: gpio - pin: - allow_other_uses: true - number: GPIO26 - id: gpio_26 - power_supply: atx_power_supply - inverted: false - - platform: ledc - pin: - allow_other_uses: true - number: 19 - id: gpio_19 - frequency: 1500Hz - channel: 14 - max_power: 0.5 - - platform: pca9685 - id: pca_0 - channel: 0 - - platform: pca9685 - id: pca_1 - channel: 1 - - platform: pca9685 - id: pca_2 - channel: 2 - - platform: pca9685 - id: pca_3 - channel: 3 - - platform: pca9685 - id: pca_4 - channel: 4 - - platform: pca9685 - id: pca_5 - channel: 5 - - platform: pca9685 - id: pca_6 - channel: 6 - - platform: pca9685 - id: pca_7 - channel: 7 - - platform: tlc59208f - id: tlc_0 - channel: 0 - tlc59208f_id: tlc59208f_1 - - platform: tlc59208f - id: tlc_1 - channel: 1 - tlc59208f_id: tlc59208f_1 - - platform: tlc59208f - id: tlc_2 - channel: 2 - tlc59208f_id: tlc59208f_1 - - platform: tlc59208f - id: tlc_3 - channel: 0 - tlc59208f_id: tlc59208f_2 - - platform: tlc59208f - id: tlc_4 - channel: 1 - tlc59208f_id: tlc59208f_2 - - platform: tlc59208f - id: tlc_5 - channel: 2 - tlc59208f_id: tlc59208f_2 - - platform: tlc59208f - id: tlc_6 - channel: 0 - tlc59208f_id: tlc59208f_3 - - platform: tlc59208f - id: tlc_7 - channel: 1 - tlc59208f_id: tlc59208f_3 - - platform: tlc59208f - id: tlc_8 - channel: 2 - tlc59208f_id: tlc59208f_3 - - platform: gpio - id: id2 - pin: - pcf8574: pcf8574_hub - number: 0 - # allow_other_uses: true - mode: OUTPUT - inverted: false - - platform: gpio - id: id26 - pin: - pca9554: pca9554_hub - number: 0 - # allow_other_uses: true - mode: OUTPUT - inverted: false - - platform: gpio - id: id22 - pin: - mcp23xxx: mcp23017_hub - number: 0 - mode: OUTPUT - inverted: false - - platform: gpio - id: id23 - pin: - mcp23xxx: mcp23008_hub - number: 0 - mode: OUTPUT - inverted: false - - platform: gpio - id: id25 - pin: - mcp23016: mcp23016_hub - number: 0 - mode: OUTPUT - inverted: false - - platform: my9231 - id: my_0 - channel: 0 - - platform: my9231 - id: my_1 - channel: 1 - - platform: my9231 - id: my_2 - channel: 2 - - platform: my9231 - id: my_3 - channel: 3 - - platform: my9231 - id: my_4 - channel: 4 - - platform: my9231 - id: my_5 - channel: 5 - - platform: sm2235 - id: sm2235_red - channel: 1 - - platform: sm2235 - id: sm2235_green - channel: 0 - - platform: sm2235 - id: sm2235_blue - channel: 2 - - platform: sm2235 - id: sm2235_coldwhite - channel: 4 - - platform: sm2235 - id: sm2235_warmwhite - channel: 3 - - platform: sm2335 - id: sm2335_red - channel: 1 - - platform: sm2335 - id: sm2335_green - channel: 0 - - platform: sm2335 - id: sm2335_blue - channel: 2 - - platform: sm2335 - id: sm2335_coldwhite - channel: 4 - - platform: sm2335 - id: sm2335_warmwhite - channel: 3 - - platform: slow_pwm - id: id24 - pin: - allow_other_uses: true - number: GPIO26 - period: 15s - - platform: ac_dimmer - id: dimmer1 - gate_pin: - allow_other_uses: true - number: GPIO5 - zero_cross_pin: - allow_other_uses: true - number: GPIO26 - - platform: esp32_dac - pin: - allow_other_uses: true - number: GPIO25 - id: dac_output - - platform: mcp4725 - id: mcp4725_dac_output - i2c_id: i2c_bus - - platform: mcp4728 - id: mcp4728_dac_output_a - channel: A - vref: vdd - power_down: normal - - platform: mcp4728 - id: mcp4728_dac_output_b - channel: B - vref: internal - gain: X1 - power_down: gnd_1k - - platform: mcp4728 - id: mcp4728_dac_output_c - channel: C - vref: vdd - power_down: gnd_100k - - platform: mcp4728 - id: mcp4728_dac_output_d - channel: D - vref: internal - gain: X2 - power_down: gnd_500k - - platform: bp1658cj - id: bp1658cj_red - channel: 1 - - platform: bp1658cj - id: bp1658cj_green - channel: 2 - - platform: bp1658cj - id: bp1658cj_blue - channel: 0 - - platform: bp1658cj - id: bp1658cj_coldwhite - channel: 3 - - platform: bp1658cj - id: bp1658cj_warmwhite - channel: 4 - - platform: bp5758d - id: bp5758d_red - channel: 2 - current: 10 - - platform: bp5758d - id: bp5758d_green - channel: 3 - current: 10 - - platform: bp5758d - id: bp5758d_blue - channel: 1 - current: 10 - - platform: bp5758d - id: bp5758d_coldwhite - channel: 5 - current: 10 - - platform: bp5758d - id: bp5758d_warmwhite - channel: 4 - current: 10 - - platform: x9c - id: test_x9c - cs_pin: - allow_other_uses: true - number: GPIO25 - inc_pin: - allow_other_uses: true - number: GPIO26 - ud_pin: - allow_other_uses: true - number: GPIO27 - initial_value: 0.5 - -light: - - platform: binary - name: Desk Lamp - output: gpio_26 - effects: - - strobe: - - strobe: - name: My Strobe - colors: - - state: true - duration: 250ms - - state: false - duration: 250ms - on_turn_on: - - switch.template.publish: - id: livingroom_lights - state: true - on_turn_off: - - switch.template.publish: - id: livingroom_lights - state: true - - platform: monochromatic - name: Kitchen Lights - id: kitchen - output: gpio_19 - gamma_correct: 2.8 - default_transition_length: 2s - effects: - - strobe: - - flicker: - - flicker: - name: My Flicker - alpha: 98% - intensity: 1.5% - - lambda: - name: My Custom Effect - update_interval: 1s - lambda: |- - static int state = 0; - state += 1; - if (state == 4) - state = 0; - - pulse: - transition_length: 10s - update_interval: 20s - min_brightness: 10% - max_brightness: 90% - - pulse: - name: pulse2 - transition_length: - on_length: 10s - off_length: 5s - update_interval: 15s - min_brightness: 10% - max_brightness: 90% - - - platform: rgb - name: Living Room Lights - id: ${roomname}_lights - red: pca_0 - green: pca_1 - blue: pca_2 - - platform: rgbw - name: Living Room Lights 2 - red: pca_3 - green: pca_4 - blue: pca_5 - white: pca_6 - color_interlock: true - - platform: rgbww - name: Living Room Lights 2 - red: pca_3 - green: pca_4 - blue: pca_5 - cold_white: pca_6 - warm_white: pca_6 - cold_white_color_temperature: 153 mireds - warm_white_color_temperature: 500 mireds - color_interlock: true - - platform: rgbct - name: Living Room Lights 2 - red: pca_3 - green: pca_4 - blue: pca_5 - color_temperature: pca_6 - white_brightness: pca_6 - cold_white_color_temperature: 153 mireds - warm_white_color_temperature: 500 mireds - color_interlock: true - - platform: cwww - name: Living Room Lights 2 - cold_white: pca_6 - warm_white: pca_6 - cold_white_color_temperature: 153 mireds - warm_white_color_temperature: 500 mireds - constant_brightness: true - - platform: color_temperature - name: Living Room Lights 2 - color_temperature: pca_6 - brightness: pca_6 - cold_white_color_temperature: 153 mireds - warm_white_color_temperature: 500 mireds - -remote_transmitter: - - pin: - allow_other_uses: true - number: 32 - carrier_duty_percent: 100% - -climate: - - platform: tcl112 - name: TCL112 Climate With Sensor - supports_heat: true - supports_cool: true - sensor: ${sensorname}_sensor - - platform: tcl112 - name: TCL112 Climate - action_state_topic: action/state/topic - away_command_topic: away/command/topic - away_state_topic: away/state/topic - current_temperature_state_topic: current/temperature/state/topic - fan_mode_command_topic: fan_mode/mode/command/topic - fan_mode_state_topic: fan_mode/mode/state/topic - mode_command_topic: mode/command/topic - mode_state_topic: mode/state/topic - swing_mode_command_topic: swing_mode/command/topic - swing_mode_state_topic: swing_mode/state/topic - target_temperature_command_topic: target/temperature/command/topic - target_temperature_high_command_topic: target/temperature/high/command/topic - target_temperature_high_state_topic: target/temperature/high/state/topic - target_temperature_low_command_topic: target/temperature/low/command/topic - target_temperature_low_state_topic: target/temperature/low/state/topic - target_temperature_state_topic: target/temperature/state/topic - - platform: coolix - name: Coolix Climate With Sensor - supports_heat: true - supports_cool: true - sensor: ${sensorname}_sensor - - platform: coolix - name: Coolix Climate - - platform: fujitsu_general - name: Fujitsu General Climate - - platform: daikin - name: Daikin Climate - - platform: daikin_brc - name: Daikin BRC Climate - use_fahrenheit: true - - platform: delonghi - name: Delonghi Climate - - platform: yashima - name: Yashima Climate - - platform: mitsubishi - name: Mitsubishi - supports_dry: "true" - supports_fan_only: "true" - horizontal_default: "left" - vertical_default: "down" - - platform: whirlpool - name: Whirlpool Climate - - platform: climate_ir_lg - name: LG Climate - - platform: toshiba - name: Toshiba Climate - - platform: hitachi_ac344 - name: Hitachi Climate - - platform: heatpumpir - protocol: mitsubishi_heavy_zm - horizontal_default: left - vertical_default: up - name: HeatpumpIR Climate - min_temperature: 18 - max_temperature: 30 - - platform: heatpumpir - protocol: greeyt - horizontal_default: left - vertical_default: up - name: HeatpumpIR Climate - min_temperature: 18 - max_temperature: 30 - - platform: midea_ir - name: Midea IR - use_fahrenheit: true - - platform: midea - on_control: - - logger.log: Control message received! - - lambda: |- - x.set_mode(CLIMATE_MODE_FAN_ONLY); - on_state: - - logger.log: State changed! - - lambda: |- - if (x.mode == CLIMATE_MODE_FAN_ONLY) - id(binary_sensor1).publish_state(true); - id: midea_unit - uart_id: uart_0 - name: Midea Climate - transmitter_id: - period: 1s - num_attempts: 5 - timeout: 2s - beeper: false - autoconf: true - visual: - min_temperature: 17 °C - max_temperature: 30 °C - temperature_step: 0.5 °C - supported_modes: - - FAN_ONLY - - HEAT_COOL - - COOL - - HEAT - - DRY - custom_fan_modes: - - SILENT - - TURBO - supported_presets: - - ECO - - BOOST - - SLEEP - custom_presets: - - FREEZE_PROTECTION - supported_swing_modes: - - VERTICAL - - HORIZONTAL - - BOTH - outdoor_temperature: - name: Temp - power_usage: - name: Power - humidity_setpoint: - name: Humidity - - platform: anova - name: Anova cooker - ble_client_id: ble_blah - unit_of_measurement: c - icon: mdi:stove - - platform: bedjet - name: My Bedjet - bedjet_id: my_bedjet_client - heat_mode: extended - - platform: whynter - name: Whynter - - platform: noblex - name: AC Living - id: noblex_ac - sensor: ${sensorname}_sensor - receiver_id: rcvr - - platform: gree - name: GREE - model: generic - - platform: zhlt01 - name: ZH/LT-01 Climate - -script: - - id: climate_custom - then: - - climate.control: - id: midea_unit - custom_preset: FREEZE_PROTECTION - custom_fan_mode: SILENT - - id: climate_preset - then: - - climate.control: - id: midea_unit - preset: SLEEP - -switch: - - platform: template - name: MIDEA_AC_BEEPER_CONTROL - optimistic: true - turn_on_action: - midea_ac.beeper_on: - turn_off_action: - midea_ac.beeper_off: - - platform: template - name: MIDEA_RAW - turn_on_action: - - remote_transmitter.transmit_coolix: - first: 0xB21F98 - - remote_transmitter.transmit_coolix: - first: 0xB21F98 - second: 0xB21F98 - - remote_transmitter.transmit_coolix: - first: !lambda "return 0xB21F98;" - second: !lambda "return 0xB21F98;" - - remote_transmitter.transmit_midea: - code: [0xA2, 0x08, 0xFF, 0xFF, 0xFF] - - remote_transmitter.transmit_midea: - code: !lambda "return {0xA2, 0x08, 0xFF, 0xFF, 0xFF};" - - platform: gpio - name: "MCP23S08 Pin #0" - pin: - mcp23xxx: mcp23s08_hub - # Use pin number 0 - number: 0 - mode: OUTPUT - inverted: false - - platform: gpio - name: "MCP23S17 Pin #0" - pin: - mcp23xxx: mcp23s17_hub - # Use pin number 0 - number: 1 - allow_other_uses: true - mode: OUTPUT - inverted: false - - platform: gpio - pin: - allow_other_uses: true - number: GPIO25 - name: Living Room Dehumidifier - icon: "mdi:restart" - inverted: true - command_topic: custom_command_topic - command_retain: true - restore_mode: ALWAYS_OFF - - platform: template - name: JVC Off - id: living_room_lights_on - turn_on_action: - remote_transmitter.transmit_jvc: - data: 0x10EF - - platform: template - name: MagiQuest - turn_on_action: - remote_transmitter.transmit_magiquest: - wand_id: 0x01234567 - - platform: template - name: NEC - id: living_room_lights_off - turn_on_action: - remote_transmitter.transmit_nec: - address: 0x4242 - command: 0x8484 - - platform: template - name: LG - turn_on_action: - remote_transmitter.transmit_lg: - data: 4294967295 - nbits: 28 - - platform: template - name: Samsung - turn_on_action: - remote_transmitter.transmit_samsung: - data: 0xABCDEF - - platform: template - name: Samsung36 - turn_on_action: - remote_transmitter.transmit_samsung36: - address: 0x0400 - command: 0x000E00FF - - platform: template - name: ToshibaAC - turn_on_action: - - remote_transmitter.transmit_toshiba_ac: - rc_code_1: 0xB24DBF4050AF - rc_code_2: 0xD5660001003C - - platform: template - name: Sony - turn_on_action: - remote_transmitter.transmit_sony: - data: 0xABCDEF - nbits: 12 - - platform: template - name: Panasonic - turn_on_action: - remote_transmitter.transmit_panasonic: - address: 0x4004 - command: 0x1000BCD - - platform: template - name: Pioneer - turn_on_action: - - remote_transmitter.transmit_pioneer: - rc_code_1: 0xA556 - rc_code_2: 0xA506 - repeat: - times: 2 - - platform: template - name: RC Switch Raw - turn_on_action: - remote_transmitter.transmit_rc_switch_raw: - code: "00101001100111110101xxxx" - protocol: 1 - - platform: template - name: RC Switch Type A - turn_on_action: - remote_transmitter.transmit_rc_switch_type_a: - group: "11001" - device: "01000" - state: true - protocol: - pulse_length: 175 - sync: [1, 31] - zero: [1, 3] - one: [3, 1] - inverted: false - - platform: template - name: RC Switch Type B - turn_on_action: - remote_transmitter.transmit_rc_switch_type_b: - address: 4 - channel: 2 - state: true - - platform: template - name: RC Switch Type C - turn_on_action: - remote_transmitter.transmit_rc_switch_type_c: - family: "a" - group: 1 - device: 2 - state: true - - platform: template - name: RC Switch Type D - turn_on_action: - remote_transmitter.transmit_rc_switch_type_d: - group: "a" - device: 2 - state: true - - platform: template - name: RC5 - turn_on_action: - remote_transmitter.transmit_rc5: - address: 0x00 - command: 0x0B - - platform: template - name: RC5 - turn_on_action: - remote_transmitter.transmit_raw: - code: [1000, -1000] - - platform: template - name: AEHA - id: eaha_hitachi_climate_power_on - turn_on_action: - remote_transmitter.transmit_aeha: - address: 0x8008 - carrier_frequency: 36700Hz - data: - [ - 0x00, - 0x02, - 0xFD, - 0xFF, - 0x00, - 0x33, - 0xCC, - 0x49, - 0xB6, - 0xC8, - 0x37, - 0x16, - 0xE9, - 0x00, - 0xFF, - 0x00, - 0xFF, - 0x00, - 0xFF, - 0x00, - 0xFF, - 0x00, - 0xFF, - 0xCA, - 0x35, - 0x8F, - 0x70, - 0x00, - 0xFF, - 0x00, - 0xFF, - 0x00, - 0xFF, - 0x00, - 0xFF, - ] - - platform: template - name: Haier - turn_on_action: - remote_transmitter.transmit_haier: - code: - [ - 0xA6, - 0xDA, - 0x00, - 0x00, - 0x40, - 0x40, - 0x00, - 0x80, - 0x00, - 0x00, - 0x00, - 0x00, - 0x05, - ] - - platform: template - name: Living Room Lights - id: livingroom_lights - optimistic: true - assumed_state: true - turn_on_action: - - switch.turn_on: living_room_lights_on - - output.set_level: - id: gpio_19 - level: 50% - - output.set_level: - id: gpio_19 - level: !lambda "return 0.5;" - - output.set_level: - id: dac_output - level: 50% - - output.set_level: - id: dac_output - level: !lambda "return 0.5;" - - output.set_level: - id: mcp4725_dac_output - level: !lambda "return 0.5;" - - output.set_level: - id: mcp4728_dac_output_a - level: !lambda "return 0.5;" - turn_off_action: - - switch.turn_on: living_room_lights_off - on_turn_on: - - switch.template.publish: - id: livingroom_lights - state: true - - platform: restart - name: Living Room Restart - - platform: safe_mode - name: Living Room Restart (Safe Mode) - - platform: factory_reset - name: Living Room Restart (Factory Default Settings) - - platform: shutdown - name: Living Room Shutdown - - platform: output - name: Generic Output - output: pca_6 - - platform: template - name: Template Switch - id: my_switch - lambda: |- - if (id(binary_sensor1).state) { - return true; - } else { - return {}; - } - id(my_switch).publish_state(false); - id(my_switch).publish_state(true); - if (id(my_switch).state) { - // Switch is ON, do something here - id(my_switch).turn_off(); - id(my_switch).turn_on(); - } else { - // Switch is OFF, do something else here - } - optimistic: true - assumed_state: false - on_turn_off: - - switch.template.publish: - id: my_switch - state: !lambda "return false;" - - platform: uart - uart_id: uart_0 - name: UART String Output - data: DataToSend - - platform: uart - uart_id: uart_0 - name: UART Bytes Output - data: [0xDE, 0xAD, 0xBE, 0xEF] - - platform: uart - uart_id: uart_0 - name: UART Recurring Output - data: [0xDE, 0xAD, 0xBE, 0xEF] - send_every: 1s - - platform: uart - uart_id: uart_0 - name: "UART On/Off" - data: - turn_on: "TurnOn\r\n" - turn_off: "TurnOff\r\n" - - platform: template - assumed_state: true - name: Stepper Switch - turn_on_action: - - stepper.set_target: - id: my_stepper - target: !lambda |- - static int32_t i = 0; - i += 1000; - if (i > 5000) { - i = -5000; - } - return i; - - stepper.report_position: - id: my_stepper - position: 0 - - - platform: gpio - name: "SN74HC595 Pin #0" - pin: - sn74hc595: sn74hc595_hub_2 - # Use pin number 0 - number: 0 - inverted: false - - platform: template - id: ble1_status - optimistic: true - - platform: template - id: outlet_switch - optimistic: true - device_class: outlet - - platform: ld2410 - engineering_mode: - name: "control ld2410 engineering mode" - bluetooth: - name: "control ld2410 bluetooth" - - platform: micronova - stove: - name: Stove on/off - -fan: - - platform: binary - output: gpio_26 - name: Living Room Fan 1 - oscillation_output: gpio_19 - direction_output: gpio_26 - - platform: speed - id: fan_speed - icon: mdi:weather-windy - output: pca_6 - speed_count: 10 - name: Living Room Fan 2 - oscillation_output: gpio_19 - direction_output: gpio_26 - oscillation_state_topic: oscillation/state/topic - oscillation_command_topic: oscillation/command/topic - speed_level_state_topic: speed_level/state/topic - speed_level_command_topic: speed_level/command/topic - speed_state_topic: speed/state/topic - speed_command_topic: speed/command/topic - on_speed_set: - then: - - logger.log: Fan speed was changed! - - platform: speed - id: fan_speed_presets - icon: mdi:weather-windy - output: pca_6 - speed_count: 10 - name: Speed Fan w/ Presets - oscillation_output: gpio_19 - direction_output: gpio_26 - preset_modes: - - Preset 1 - - Preset 2 - on_preset_set: - then: - - logger.log: Preset mode was changed! - - platform: hbridge - id: fan_hbridge_presets - icon: mdi:weather-windy - speed_count: 4 - name: H-bridge Fan w/ Presets - pin_a: pca_6 - pin_b: pca_7 - preset_modes: - - Preset 1 - - Preset 2 - on_preset_set: - then: - - logger.log: Preset mode was changed! - - platform: bedjet - name: My Bedjet fan - bedjet_id: my_bedjet_client - - platform: copy - source_id: fan_speed - name: Fan Speed Copy - -interval: - - interval: 10s - then: - - display.page.show: !lambda |- - if (true) return id(page1); else return id(page2); - - display.page.show_next: display1 - - display.page.show_previous: display1 - - interval: 2s - then: - # yamllint disable rule:line-length - - lambda: |- - static uint16_t btn_left_state = id(btn_left)->get_value(); - - ESP_LOGD("adaptive touch", "___ Touch Pad '%s' (T%u): val: %u state: %u tres:%u", id(btn_left)->get_name().c_str(), id(btn_left)->get_touch_pad(), id(btn_left)->get_value(), btn_left_state, id(btn_left)->get_threshold()); - - btn_left_state = ((uint32_t) id(btn_left)->get_value() + 63 * (uint32_t)btn_left_state) >> 6; - - id(btn_left)->set_threshold(btn_left_state * 0.9); - # yamllint enable rule:line-length - - if: - condition: - display.is_displaying_page: - id: display1 - page_id: page1 - then: - - logger.log: Seeing page 1 - - interval: 60min - then: - - ble_client.connect: ble_blah - - ble_client.ble_write: - id: ble_blah - service_uuid: EBE0CCB0-7A0A-4B0C-8A1A-6FF2997DA3A6 - characteristic_uuid: EBE0CCB7-7A0A-4B0C-8A1A-6FF2997DA3A6 - value: !lambda |- - return {1, 0}; - - ble_client.disconnect: ble_blah - -color: - - id: kbx_red - red: 100% - green_int: 123 - blue: 2% - - id: kbx_blue - red: 0% - green: 1% - blue: 100% - - id: kbx_green - hex: "3DEC55" - -display: - - platform: lcd_gpio - id: my_lcd_gpio - dimensions: 18x4 - data_pins: - - allow_other_uses: true - number: GPIO19 - - allow_other_uses: true - number: GPIO21 - - allow_other_uses: true - number: GPIO22 - - allow_other_uses: true - number: GPIO23 - enable_pin: - allow_other_uses: true - number: GPIO23 - rs_pin: - allow_other_uses: true - number: GPIO25 - lambda: |- - it.print("Hello World!"); - - platform: lcd_pcf8574 - dimensions: 18x4 - address: 0x3F - user_characters: - - position: 0 - data: - - 0b00000 - - 0b01010 - - 0b00000 - - 0b00100 - - 0b00100 - - 0b10001 - - 0b01110 - - 0b00000 - lambda: |- - it.print("Hello World!"); - i2c_id: i2c_bus - - platform: max7219 - cs_pin: - allow_other_uses: true - number: GPIO23 - num_chips: 1 - lambda: |- - it.print("01234567"); - - platform: tm1637 - clk_pin: - allow_other_uses: true - number: GPIO23 - dio_pin: - allow_other_uses: true - number: GPIO25 - intensity: 3 - lambda: |- - it.print("1234"); - - platform: tm1637 - clk_pin: - mcp23xxx: mcp23017_hub - number: 1 - allow_other_uses: true - dio_pin: - mcp23xxx: mcp23017_hub - number: 2 - intensity: 3 - inverted: true - length: 4 - lambda: |- - it.print("1234"); - - platform: pcd8544 - cs_pin: - allow_other_uses: true - number: GPIO23 - dc_pin: - allow_other_uses: true - number: GPIO23 - reset_pin: - allow_other_uses: true - number: GPIO23 - contrast: 60 - lambda: |- - it.rectangle(0, 0, it.get_width(), it.get_height()); - - platform: ssd1306_i2c - model: SSD1306_128X64 - reset_pin: - allow_other_uses: true - number: GPIO23 - address: 0x3C - id: display1 - contrast: 60% - pages: - - id: page1 - lambda: |- - it.qr_code(0, 0, id(homepage_qr)); - it.rectangle(0, 0, it.get_width(), it.get_height()); - - id: page2 - lambda: |- - // Nothing - on_page_change: - from: page1 - to: page2 - then: - lambda: |- - ESP_LOGD("display", "1 -> 2"); - i2c_id: i2c_bus - - platform: ssd1306_spi - model: SSD1306 128x64 - cs_pin: - allow_other_uses: true - number: GPIO23 - dc_pin: - allow_other_uses: true - number: GPIO23 - reset_pin: - allow_other_uses: true - number: GPIO23 - lambda: |- - it.rectangle(0, 0, it.get_width(), it.get_height()); - - platform: ssd1322_spi - model: SSD1322 256x64 - cs_pin: - allow_other_uses: true - number: GPIO23 - dc_pin: - allow_other_uses: true - number: GPIO23 - reset_pin: - allow_other_uses: true - number: GPIO23 - lambda: |- - it.rectangle(0, 0, it.get_width(), it.get_height()); - - platform: ssd1325_spi - model: SSD1325 128x64 - cs_pin: - allow_other_uses: true - number: GPIO23 - dc_pin: - allow_other_uses: true - number: GPIO23 - reset_pin: - allow_other_uses: true - number: GPIO23 - lambda: |- - it.rectangle(0, 0, it.get_width(), it.get_height()); - - platform: ssd1327_i2c - model: SSD1327 128X128 - reset_pin: - allow_other_uses: true - number: GPIO23 - address: 0x3D - id: display1327 - brightness: 60% - pages: - - id: page13271 - lambda: |- - it.rectangle(0, 0, it.get_width(), it.get_height()); - - id: page13272 - lambda: |- - // Nothing - i2c_id: i2c_bus - - platform: ssd1327_spi - model: SSD1327 128x128 - cs_pin: - allow_other_uses: true - number: GPIO23 - dc_pin: - allow_other_uses: true - number: GPIO23 - reset_pin: - allow_other_uses: true - number: GPIO23 - lambda: |- - it.rectangle(0, 0, it.get_width(), it.get_height()); - - platform: ssd1331_spi - cs_pin: - allow_other_uses: true - number: GPIO23 - dc_pin: - allow_other_uses: true - number: GPIO23 - reset_pin: - allow_other_uses: true - number: GPIO23 - lambda: |- - it.rectangle(0, 0, it.get_width(), it.get_height()); - - platform: ssd1351_spi - model: SSD1351 128x128 - cs_pin: - allow_other_uses: true - number: GPIO23 - dc_pin: - allow_other_uses: true - number: GPIO23 - reset_pin: - allow_other_uses: true - number: GPIO23 - lambda: |- - it.rectangle(0, 0, it.get_width(), it.get_height()); - - platform: st7789v - model: TTGO TDisplay 135x240 - cs_pin: - allow_other_uses: true - number: GPIO5 - dc_pin: - allow_other_uses: true - number: GPIO16 - reset_pin: - allow_other_uses: true - number: GPIO23 - backlight_pin: false - lambda: |- - it.rectangle(0, 0, it.get_width(), it.get_height()); - - platform: st7920 - width: 128 - height: 64 - cs_pin: - allow_other_uses: true - number: GPIO23 - inverted: true - lambda: |- - it.rectangle(0, 0, it.get_width(), it.get_height()); - - platform: st7567_i2c - id: st7735_display_i2c - address: 0x3F - i2c_id: i2c_bus - lambda: |- - it.rectangle(0, 0, it.get_width(), it.get_height()); - - platform: st7567_spi - id: st7735_display_spi - cs_pin: - allow_other_uses: true - number: GPIO5 - dc_pin: - allow_other_uses: true - number: GPIO16 - reset_pin: - allow_other_uses: true - number: GPIO23 - lambda: |- - it.rectangle(0, 0, it.get_width(), it.get_height()); - - platform: st7735 - id: st7735_display - model: INITR_BLACKTAB - cs_pin: - allow_other_uses: true - number: GPIO5 - dc_pin: - allow_other_uses: true - number: GPIO16 - reset_pin: - allow_other_uses: true - number: GPIO23 - rotation: 0 - device_width: 128 - device_height: 160 - col_start: 0 - row_start: 0 - lambda: |- - it.rectangle(0, 0, it.get_width(), it.get_height()); - - platform: ili9xxx - invert_colors: true - dimensions: 320x240 - transform: - swap_xy: true - mirror_x: true - mirror_y: false - model: TFT 2.4 - cs_pin: - allow_other_uses: true - number: GPIO5 - dc_pin: - allow_other_uses: true - number: GPIO4 - color_palette: GRAYSCALE - reset_pin: - allow_other_uses: true - number: GPIO22 - lambda: |- - it.rectangle(0, 0, it.get_width(), it.get_height()); - - platform: ili9xxx - dimensions: - width: 320 - height: 240 - offset_width: 20 - offset_height: 10 - model: TFT 2.4 - cs_pin: - allow_other_uses: true - number: GPIO5 - dc_pin: - allow_other_uses: true - number: GPIO4 - reset_pin: - allow_other_uses: true - number: GPIO22 - auto_clear_enabled: false - rotation: 90 - lambda: |- - if (!id(glob_bool_processed)) { - it.fill(Color::WHITE); - id(glob_bool_processed) = true; - } - - platform: pvvx_mithermometer - ble_client_id: ble_foo - time_id: sntp_time - disconnect_delay: 3s - update_interval: 10min - validity_period: 20min - lambda: |- - it.print_bignum(188.8); - it.print_unit(pvvx_mithermometer::UNIT_DEG_E); - it.print_smallnum(88); - it.print_percent(true); - it.print_happy(true); - it.print_sad(true); - it.print_bracket(true); - it.print_battery(true); - - platform: tm1621 - id: tm1621_display - cs_pin: - allow_other_uses: true - number: GPIO17 - data_pin: - allow_other_uses: true - number: GPIO5 - read_pin: - allow_other_uses: true - number: GPIO23 - write_pin: - allow_other_uses: true - number: GPIO18 - lambda: |- - it.printf(0, "%.1f", id(dht_temperature).state); - it.display_celsius(true); - it.printf(1, "%.1f", id(dht_humidity).state); - it.display_humidity(true); - -tm1651: - id: tm1651_battery - clk_pin: - allow_other_uses: true - number: GPIO23 - dio_pin: - allow_other_uses: true - number: GPIO23 - -remote_receiver: - id: rcvr - pin: - allow_other_uses: true - number: GPIO32 - dump: all - on_coolix: - then: - delay: !lambda "return x.first + x.second;" - on_rc_switch: - then: - delay: !lambda "return uint32_t(x.code) + x.protocol;" - -status_led: - pin: - allow_other_uses: true - number: GPIO2 - ignore_strapping_warning: true - -pn532_spi: - id: pn532_bs - cs_pin: - allow_other_uses: true - number: GPIO23 - update_interval: 1s - on_tag: - - lambda: |- - ESP_LOGD("main", "Found tag %s", x.c_str()); - - mqtt.publish: - topic: the/topic - payload: !lambda "return x;" - on_tag_removed: - - lambda: |- - ESP_LOGD("main", "Removed tag %s", x.c_str()); - - mqtt.publish: - topic: the/topic - payload: !lambda "return x;" - -pn532_i2c: - i2c_id: i2c_bus - -pn7150_i2c: - id: nfcc_pn7150_i2c - i2c_id: i2c_bus - irq_pin: - allow_other_uses: true - number: GPIO32 - ven_pin: - allow_other_uses: true - number: GPIO16 - -pn7160_i2c: - id: nfcc_pn7160_i2c - i2c_id: i2c_bus - dwl_req_pin: - allow_other_uses: true - number: GPIO17 - irq_pin: - allow_other_uses: true - number: GPIO35 - ven_pin: - allow_other_uses: true - number: GPIO16 - wkup_req_pin: - allow_other_uses: true - number: GPIO21 - emulation_message: https://www.home-assistant.io/tag/pulse_ce - tag_ttl: 1000ms - -pn7160_spi: - id: nfcc_pn7160_spi - cs_pin: - number: GPIO15 - dwl_req_pin: - allow_other_uses: true - number: GPIO17 - irq_pin: - allow_other_uses: true - number: GPIO35 - ven_pin: - allow_other_uses: true - number: GPIO16 - wkup_req_pin: - allow_other_uses: true - number: GPIO21 - emulation_message: https://www.home-assistant.io/tag/pulse_ce - tag_ttl: 1000ms - -rdm6300: - uart_id: uart_0 - -rc522_spi: - cs_pin: - allow_other_uses: true - number: GPIO23 - update_interval: 1s - on_tag: - - lambda: |- - ESP_LOGD("main", "Found tag %s", x.c_str()); - -rc522_i2c: - - update_interval: 1s - on_tag: - - lambda: |- - ESP_LOGD("main", "Found tag %s", x.c_str()); - i2c_id: i2c_bus - - - update_interval: 1s - on_tag: - - lambda: |- - ESP_LOGD("main", "Found tag %s", x.c_str()); - i2c_id: i2c_bus - -mcp4728: - - id: mcp4728_dac - store_in_eeprom: false - address: 0x60 - i2c_id: i2c_bus - -gps: - uart_id: uart_0 - -time: - - platform: sntp - id: sntp_time - servers: - - 0.pool.ntp.org - - 1.pool.ntp.org - - 192.168.178.1 - on_time: - cron: "/30 0-30,30/5 * ? JAN-DEC MON,SAT-SUN,TUE-FRI" - then: - - lambda: 'ESP_LOGD("main", "time");' - - platform: gps - on_time_sync: - then: - ds1307.write_time: - id: ds1307_time - - platform: ds1307 - id: ds1307_time - update_interval: never - i2c_id: i2c_bus - on_time: - - seconds: 0 - then: ds1307.read_time - - at: "16:00:00" - then: - - if: - condition: - or: - - binary_sensor.is_on: close_sensor - - binary_sensor.is_on: open_sensor - then: - logger.log: "close_sensor or open_sensor is on" - - if: - condition: - and: - - binary_sensor.is_on: close_sensor - - binary_sensor.is_on: open_sensor - then: - logger.log: "close_sensor and open_sensor are both on" - - if: - condition: - xor: - - binary_sensor.is_on: close_sensor - - binary_sensor.is_on: open_sensor - then: - logger.log: "close_sensor or open_sensor is exclusively on" - - if: - condition: - not: - - binary_sensor.is_on: close_sensor - then: - logger.log: "close_sensor is not on" -cover: - - platform: template - name: Template Cover - id: template_cover - lambda: |- - if (id(binary_sensor1).state) { - return COVER_OPEN; - } else { - return {}; - } - optimistic: true - open_action: - - cover.template.publish: - id: template_cover - state: CLOSED - assumed_state: false - has_position: true - position_state_topic: position/state/topic - position_command_topic: position/command/topic - tilt_lambda: !lambda "return 0.5;" - tilt_state_topic: tilt/state/topic - tilt_command_topic: tilt/command/topic - on_open: - then: - - lambda: 'ESP_LOGD("cover", "open");' - on_closed: - then: - - lambda: 'ESP_LOGD("cover", "closed");' - - platform: am43 - name: Test AM43 - id: am43_test - ble_client_id: ble_foo - icon: mdi:blinds - - platform: feedback - name: Feedback Cover - id: gate - device_class: gate - - infer_endstop_from_movement: false - has_built_in_endstop: false - max_duration: 30s - direction_change_wait_time: 300ms - acceleration_wait_time: 150ms - obstacle_rollback: 10% - - open_duration: 22.1s - open_endstop: open_endstop_sensor - open_sensor: open_sensor - open_obstacle_sensor: open_obstacle_sensor - - close_duration: 22.4s - close_endstop: close_endstop_sensor - close_sensor: close_sensor - close_obstacle_sensor: close_obstacle_sensor - - open_action: - - logger.log: Open Action - - close_action: - - logger.log: Close Action - - stop_action: - - logger.log: Stop Action - -debug: - -tca9548a: - - address: 0x70 - id: multiplex0 - channels: - - bus_id: multiplex0_chan0 - channel: 0 - i2c_id: i2c_bus - - address: 0x71 - id: multiplex1 - i2c_id: multiplex0_chan0 - -pcf8574: - - id: pcf8574_hub - address: 0x21 - pcf8575: false - i2c_id: i2c_bus - -pca9554: - - id: pca9554_hub - pin_count: 8 - address: 0x3F - i2c_id: i2c_bus - -pca6416a: - - id: pca6416a_hub - address: 0x21 - i2c_id: i2c_bus - -mcp23017: - - id: mcp23017_hub - open_drain_interrupt: true - i2c_id: i2c_bus - -mcp23008: - - id: mcp23008_hub - address: 0x22 - open_drain_interrupt: true - i2c_id: i2c_bus - -mcp23016: - - id: mcp23016_hub - address: 0x23 - i2c_id: i2c_bus - -stepper: - - platform: a4988 - id: my_stepper - step_pin: - allow_other_uses: true - number: GPIO23 - dir_pin: - allow_other_uses: true - number: GPIO25 - sleep_pin: - allow_other_uses: true - number: GPIO25 - max_speed: 250 steps/s - acceleration: 100 steps/s^2 - deceleration: 200 steps/s^2 - -globals: - - id: glob_int - type: int - restore_value: true - initial_value: "0" - - id: glob_float - type: float - restore_value: true - initial_value: "0.0f" - - id: glob_bool - type: bool - restore_value: false - initial_value: "true" - - id: glob_string - type: std::string - restore_value: false - # initial_value: "" - - id: glob_bool_processed - type: bool - restore_value: false - initial_value: "false" - -text_sensor: - - platform: ble_client - ble_client_id: ble_foo - name: Sensor Location - service_uuid: "180d" - characteristic_uuid: "2a38" - descriptor_uuid: "2902" - notify: true - update_interval: never - on_notify: - then: - - lambda: |- - ESP_LOGD("green_btn", "Location changed: %s", x.c_str()); - - platform: mqtt_subscribe - name: MQTT Subscribe Text - topic: "the/topic" - qos: 2 - on_value: - - text_sensor.template.publish: - id: ${textname}_text - state: Hello World - - text_sensor.template.publish: - id: ${textname}_text - state: |- - return "Hello World2"; - - globals.set: - id: glob_int - value: "0" - - canbus.send: - canbus_id: mcp2515_can - can_id: 23 - data: [0x10, 0x20, 0x30] - - canbus.send: - canbus_id: mcp2515_can - can_id: 23 - data: !lambda return {0x10, 0x20, 0x30}; - - canbus.send: - canbus_id: esp32_internal_can - can_id: 23 - data: [0x10, 0x20, 0x30] - - canbus.send: - canbus_id: mcp2515_can - can_id: 24 - remote_transmission_request: true - data: [] - - canbus.send: - canbus_id: esp32_internal_can - can_id: 24 - remote_transmission_request: true - data: [] - - platform: template - name: Template Text Sensor - id: ${textname}_text - - platform: template - name: Template Text Sensor Timestamp - id: ${textname}_text_timestamp - device_class: timestamp - - platform: wifi_info - scan_results: - name: Scan Results - ip_address: - name: IP Address - ssid: - name: SSID - bssid: - name: BSSID - mac_address: - name: Mac Address - dns_address: - name: DNS ADdress - - platform: version - name: ESPHome Version No Timestamp - hide_timestamp: true - - platform: teleinfo - tag_name: OPTARIF - name: optarif - teleinfo_id: myteleinfo - - platform: ld2410 - version: - name: "presenece sensor version" - mac_address: - name: "presenece sensor mac address" - -sn74hc595: - - id: sn74hc595_hub - data_pin: - allow_other_uses: true - number: GPIO21 - clock_pin: - allow_other_uses: true - number: GPIO23 - latch_pin: - allow_other_uses: true - number: GPIO22 - oe_pin: - allow_other_uses: true - number: GPIO32 - sr_count: 2 - - id: sn74hc595_hub_2 - latch_pin: - allow_other_uses: true - number: GPIO22 - oe_pin: - allow_other_uses: true - number: GPIO32 - sr_count: 2 - spi_id: spi_bus - type: spi - -rtttl: - output: gpio_19 - -canbus: - - platform: mcp2515 - id: mcp2515_can - cs_pin: - pca9554: pca9554_hub - number: 7 - mode: - output: true - inverted: true - can_id: 4 - bit_rate: 50kbps - on_frame: - - can_id: 500 - then: - - lambda: |- - std::string b(x.begin(), x.end()); - ESP_LOGD("canid 500", "%s", b.c_str()); - - can_id: 23 - then: - - if: - condition: - lambda: "return x[0] == 0x11;" - then: - light.toggle: ${roomname}_lights - - can_id: 0b00000000000000000000001000000 - can_id_mask: 0b11111000000000011111111000000 - use_extended_id: true - then: - - lambda: |- - auto pdo_id = can_id >> 14; - switch (pdo_id) - { - case 117: - ESP_LOGD("canbus", "exhaust_fan_duty"); - break; - case 118: - ESP_LOGD("canbus", "supply_fan_duty"); - break; - case 119: - ESP_LOGD("canbus", "supply_fan_flow"); - break; - // to be continued... - } - - platform: esp32_can - id: esp32_internal_can - rx_pin: - allow_other_uses: true - number: GPIO04 - tx_pin: - allow_other_uses: true - number: GPIO05 - can_id: 4 - bit_rate: 50kbps - on_frame: - - can_id: 500 - then: - - lambda: |- - std::string b(x.begin(), x.end()); - ESP_LOGD("canid 500", "%s", b.c_str() ); - - can_id: 23 - then: - - if: - condition: - lambda: "return x[0] == 0x11;" - then: - light.toggle: ${roomname}_lights - - can_id: 0b00000000000000000000001000000 - can_id_mask: 0b11111000000000011111111000000 - use_extended_id: true - then: - - lambda: |- - auto pdo_id = can_id >> 14; - switch (pdo_id) - { - case 117: - ESP_LOGD("canbus", "exhaust_fan_duty"); - break; - case 118: - ESP_LOGD("canbus", "supply_fan_duty"); - break; - case 119: - ESP_LOGD("canbus", "supply_fan_flow"); - break; - // to be continued... - } - -teleinfo: - id: myteleinfo - uart_id: uart_0 - update_interval: 60s - historical_mode: true - -number: - - platform: template - id: test_number - state_topic: livingroom/custom_state_topic - command_topic: livingroom/custom_command_topic - min_value: 0 - step: 1 - max_value: 10 - optimistic: true - - platform: ld2410 - light_threshold: - name: light threshold - timeout: - name: timeout - max_move_distance_gate: - name: max move distance gate - max_still_distance_gate: - name: max still distance gate - g0: - move_threshold: - name: g0 move threshold - still_threshold: - name: g0 still threshold - g1: - move_threshold: - name: g1 move threshold - still_threshold: - name: g1 still threshold - g2: - move_threshold: - name: g2 move threshold - still_threshold: - name: g2 still threshold - g3: - move_threshold: - name: g3 move threshold - still_threshold: - name: g3 still threshold - g4: - move_threshold: - name: g4 move threshold - still_threshold: - name: g4 still threshold - g5: - move_threshold: - name: g5 move threshold - still_threshold: - name: g5 still threshold - g6: - move_threshold: - name: g6 move threshold - still_threshold: - name: g6 still threshold - g7: - move_threshold: - name: g7 move threshold - still_threshold: - name: g7 still threshold - g8: - move_threshold: - name: g8 move threshold - still_threshold: - name: g8 still threshold - - platform: micronova - thermostat_temperature: - name: Micronova Thermostaat - step: 1 - power_level: - name: Micronova Power level - -select: - - platform: template - id: test_select - state_topic: livingroom/custom_state_topic - command_topic: livingroom/custom_command_topic - options: - - one - - two - optimistic: true - - platform: copy - source_id: test_select - name: Test Select Copy - - platform: ld2410 - distance_resolution: - name: distance resolution - baud_rate: - name: baud rate - light_function: - name: light function - out_pin_level: - name: out ping level - -qr_code: - - id: homepage_qr - value: https://esphome.io/index.html - -lock: - - platform: template - id: test_lock1 - name: Template Switch - lambda: |- - if (id(binary_sensor1).state) { - return LOCK_STATE_LOCKED; - }else{ - return LOCK_STATE_UNLOCKED; - } - optimistic: true - assumed_state: false - on_unlock: - - lock.template.publish: - id: test_lock1 - state: !lambda "return LOCK_STATE_UNLOCKED;" - on_lock: - - lock.template.publish: - id: test_lock1 - state: !lambda "return LOCK_STATE_LOCKED;" - - platform: output - name: Generic Output Lock - id: test_lock2 - output: pca_6 - - platform: copy - source_id: test_lock2 - name: Generic Output Lock Copy - -button: - - platform: template - name: Start calibration - on_press: - - scd4x.perform_forced_calibration: - value: 419 - id: scd40 - - scd4x.factory_reset: - id: scd40 - - platform: template - name: Midea Display Toggle - on_press: - midea_ac.display_toggle: - - platform: template - name: Midea Swing Step - on_press: - midea_ac.swing_step: - - platform: template - name: Midea Power On - on_press: - midea_ac.power_on: - - platform: template - name: Midea Power Off - on_press: - midea_ac.power_off: - - platform: template - name: Midea Power Inverse - on_press: - midea_ac.power_toggle: - - platform: template - name: Update Mmwave Sensor Settings - on_press: - - dfrobot_sen0395.settings: - id: mmwave - factory_reset: true - detection_segments: - - [0cm, 5m] - - 600cm - - !lambda |- - return 7; - output_latency: - delay_after_detect: 0s - delay_after_disappear: 0s - sensitivity: 6 - - platform: template - name: Reset Mmwave Sensor - on_press: - - dfrobot_sen0395.reset: - - platform: template - name: Poller component suspend test - on_press: - - component.suspend: myteleinfo - - delay: 20s - - component.update: myteleinfo - - delay: 20s - - component.resume: myteleinfo - - delay: 20s - - component.resume: - id: myteleinfo - update_interval: 2s - - delay: 20s - - component.resume: - id: myteleinfo - update_interval: !lambda return 2500; - - platform: ld2410 - factory_reset: - name: "factory reset" - restart: - name: "restart" - query_params: - name: query params - - platform: uart - uart_id: uart_0 - name: UART button - data: "Pressed\r\n" - - platform: micronova - custom_button: - name: Custom Micronova Button - memory_location: 0xA0 - memory_address: 0x7D - memory_data: 0x0F - -ld2410: - id: my_ld2410 - uart_id: ld2410_uart - -ld2420: - id: my_ld2420 - uart_id: ld2420_uart - -lcd_menu: - id: test_lcd_menu - display_id: my_lcd_gpio - mark_back: 0x5e - mark_selected: 0x3e - mark_editing: 0x2a - mark_submenu: 0x7e - active: false - mode: rotary - on_enter: - then: - lambda: 'ESP_LOGI("lcd_menu", "root enter");' - on_leave: - then: - lambda: 'ESP_LOGI("lcd_menu", "root leave");' - items: - - type: back - text: Back - - type: label - - type: menu - text: Submenu 1 - items: - - type: back - text: Back - - type: menu - text: Submenu 21 - items: - - type: back - text: Back - - type: command - text: Show Main - on_value: - then: - - display_menu.show_main: test_lcd_menu - - type: select - text: Enum Item - immediate_edit: true - select: test_select - on_enter: - then: - lambda: 'ESP_LOGI("lcd_menu", "select enter: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' - on_leave: - then: - lambda: 'ESP_LOGI("lcd_menu", "select leave: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' - on_value: - then: - lambda: 'ESP_LOGI("lcd_menu", "select value: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' - - type: number - text: Number - number: test_number - on_enter: - then: - lambda: 'ESP_LOGI("lcd_menu", "number enter: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' - on_leave: - then: - lambda: 'ESP_LOGI("lcd_menu", "number leave: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' - on_value: - then: - lambda: 'ESP_LOGI("lcd_menu", "number value: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' - - type: command - text: Hide - on_value: - then: - - display_menu.hide: test_lcd_menu - - type: switch - text: Switch - switch: my_switch - on_text: Bright - off_text: Dark - immediate_edit: false - on_value: - then: - lambda: 'ESP_LOGI("lcd_menu", "switch value: %s", it->get_value_text().c_str());' - - type: custom - text: !lambda 'return "Custom";' - value_lambda: 'return "Val";' - on_next: - then: - lambda: 'ESP_LOGI("lcd_menu", "custom next: %s", it->get_text().c_str());' - on_prev: - then: - lambda: 'ESP_LOGI("lcd_menu", "custom prev: %s", it->get_text().c_str());' - -font: - - file: "gfonts://Roboto" - id: roboto - size: 20 - -graphical_display_menu: - id: test_graphical_display_menu - display: st7735_display - font: roboto - active: false - mode: rotary - on_enter: - then: - lambda: 'ESP_LOGI("graphical_display_menu", "root enter");' - on_leave: - then: - lambda: 'ESP_LOGI("graphical_display_menu", "root leave");' - items: - - type: back - text: "Back" - - type: label - - type: menu - text: "Submenu 1" - items: - - type: back - text: "Back" - - type: menu - text: "Submenu 21" - items: - - type: back - text: "Back" - - type: command - text: "Show Main" - on_value: - then: - - display_menu.show_main: test_graphical_display_menu - - type: select - text: "Enum Item" - immediate_edit: true - select: test_select - on_enter: - then: - lambda: 'ESP_LOGI("graphical_display_menu", "select enter: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' - on_leave: - then: - lambda: 'ESP_LOGI("graphical_display_menu", "select leave: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' - on_value: - then: - lambda: 'ESP_LOGI("graphical_display_menu", "select value: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' - - type: number - text: "Number" - number: test_number - on_enter: - then: - lambda: 'ESP_LOGI("graphical_display_menu", "number enter: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' - on_leave: - then: - lambda: 'ESP_LOGI("graphical_display_menu", "number leave: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' - on_value: - then: - lambda: 'ESP_LOGI("graphical_display_menu", "number value: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());' - - type: command - text: "Hide" - on_value: - then: - - display_menu.hide: test_graphical_display_menu - - type: switch - text: "Switch" - switch: my_switch - on_text: "Bright" - off_text: "Dark" - immediate_edit: false - on_value: - then: - lambda: 'ESP_LOGI("graphical_display_menu", "switch value: %s", it->get_value_text().c_str());' - - type: custom - text: !lambda 'return "Custom";' - value_lambda: 'return "Val";' - on_next: - then: - lambda: 'ESP_LOGI("graphical_display_menu", "custom next: %s", it->get_text().c_str());' - on_prev: - then: - lambda: 'ESP_LOGI("graphical_display_menu", "custom prev: %s", it->get_text().c_str());' - -alarm_control_panel: - - platform: template - id: alarmcontrolpanel1 - name: Alarm Panel - codes: - - "1234" - requires_code_to_arm: true - arming_home_time: 1s - arming_away_time: 15s - pending_time: 15s - trigger_time: 30s - binary_sensors: - - binary_sensor1 - on_state: - then: - - lambda: !lambda |- - ESP_LOGD("TEST", "State change %s", alarm_control_panel_state_to_string(id(alarmcontrolpanel1)->get_state())); diff --git a/tests/test11.5.yaml b/tests/test11.5.yaml deleted file mode 100644 index 758f295a6c..0000000000 --- a/tests/test11.5.yaml +++ /dev/null @@ -1,809 +0,0 @@ ---- -# copy of test5.yaml configured to build on IDF 5 -esphome: - name: test11-5 - build_path: build/test11.5 - project: - name: esphome.test11_5_project - version: "1.0.0" - -esp32: - board: nodemcu-32s - framework: - type: esp-idf - version: 5.0.2 - platform_version: 6.3.2 - advanced: - ignore_efuse_mac_crc: true - -wifi: - networks: - - ssid: "MySSID" - password: "password1" - manual_ip: - static_ip: 192.168.1.23 - gateway: 192.168.1.1 - subnet: 255.255.255.0 - -network: - enable_ipv6: true - -api: - -ota: - - platform: esphome - -logger: - -debug: - -psram: - -uart: - - id: uart_1 - tx_pin: 1 - rx_pin: 3 - baud_rate: 9600 - - id: uart_2 - tx_pin: - allow_other_uses: true - number: 17 - rx_pin: - allow_other_uses: true - number: 16 - baud_rate: 19200 - -i2c: - sda: - number: 21 - allow_other_uses: true - frequency: 100khz - -spi: - - id: spi_1 - clk_pin: - allow_other_uses: true - number: 12 - mosi_pin: - allow_other_uses: true - number: 13 - miso_pin: - allow_other_uses: true - number: 14 - - id: spi_2 - clk_pin: - allow_other_uses: true - number: 32 - mosi_pin: 33 - -modbus: - uart_id: uart_1 - flow_control_pin: - allow_other_uses: true - number: 5 - id: mod_bus1 - -modbus_controller: - - id: modbus_controller_test - address: 0x2 - modbus_id: mod_bus1 - -mqtt: - broker: test.mosquitto.org - port: 1883 - discovery: true - discovery_prefix: homeassistant - idf_send_async: false - on_message: - topic: testing/sensor/testing_sensor/state - qos: 0 - then: - # yamllint disable rule:line-length - - lambda: |- - ESP_LOGD("Mqtt Test", "testing/sensor/testing_sensor/state=[%s]", x.c_str()); - # yamllint enable rule:line-length - -vbus: - - uart_id: uart_2 - -binary_sensor: - - platform: gpio - pin: GPIO0 - id: io0_button - icon: mdi:gesture-tap-button - - - platform: modbus_controller - modbus_controller_id: modbus_controller_test - id: modbus_binsensortest - register_type: read - address: 0x3200 - bitmask: 0x80 # (bit 8) - lambda: "return x;" - - - platform: tm1638 - id: Button0 - key: 0 - filters: - - delayed_on: 10ms - on_press: - then: - - switch.turn_on: Led0 - on_release: - then: - - switch.turn_off: Led0 - - if: - condition: ble.enabled - then: - - ble.disable: - else: - - ble.enable: - - - platform: tm1638 - id: Button1 - key: 1 - on_press: - then: - - switch.turn_on: Led1 - on_release: - then: - - switch.turn_off: Led1 - - - platform: tm1638 - id: Button2 - key: 2 - on_press: - then: - - switch.turn_on: Led2 - on_release: - then: - - switch.turn_off: Led2 - - - platform: tm1638 - id: Button3 - key: 3 - on_press: - then: - - switch.turn_on: Led3 - on_release: - then: - - switch.turn_off: Led3 - - - platform: tm1638 - id: Button4 - key: 4 - on_press: - then: - - output.turn_on: Led4 - on_release: - then: - - output.turn_off: Led4 - - - platform: tm1638 - id: Button5 - key: 5 - on_press: - then: - - output.turn_on: Led5 - on_release: - then: - - output.turn_off: Led5 - - - platform: tm1638 - id: Button6 - key: 6 - on_press: - then: - - output.turn_on: Led6 - on_release: - then: - - output.turn_off: Led6 - - - platform: tm1638 - id: Button7 - key: 7 - on_press: - then: - - output.turn_on: Led7 - on_release: - then: - - output.turn_off: Led7 - - - platform: gpio - id: sn74hc165_pin_0 - pin: - sn74hc165: sn74hc165_hub - number: 0 - - - platform: ezo_pmp - pump_state: - name: "Pump State" - is_paused: - name: "Is Paused" - - - platform: matrix_keypad - keypad_id: keypad - id: key4 - row: 1 - col: 1 - - platform: matrix_keypad - id: key1 - key: 1 - - - platform: vbus - model: deltasol_bs_plus - relay2: - name: Relay 2 On - sensor1_error: - name: Sensor 1 Error - - - platform: vbus - model: custom - command: 0x100 - source: 0x1234 - dest: 0x10 - binary_sensors: - - id: vcustom_b - name: VBus Custom Binary Sensor - lambda: return x[0] & 1; - -tlc5947: - data_pin: - allow_other_uses: true - number: GPIO12 - clock_pin: - allow_other_uses: true - number: GPIO14 - lat_pin: - allow_other_uses: true - number: GPIO15 - -gp8403: - - id: gp8403_5v - voltage: 5V - - id: gp8403_10v - voltage: 10V - -output: - - platform: gpio - pin: GPIO2 - id: built_in_led - - - platform: tlc5947 - id: output_red - channel: 0 - max_power: 0.8 - - - platform: mcp47a1 - id: output_mcp47a1 - - - platform: modbus_controller - modbus_controller_id: modbus_controller_test - id: modbus_output_test - lambda: |- - return x * 1.0 ; - address: 0x9001 - value_type: U_WORD - - - platform: tm1638 - id: Led4 - led: 4 - - - platform: tm1638 - id: Led5 - led: 5 - - - platform: tm1638 - id: Led6 - led: 6 - - - platform: tm1638 - id: Led7 - led: 7 - - - platform: gp8403 - id: gp8403_output_0 - gp8403_id: gp8403_5v - channel: 0 - - platform: gp8403 - gp8403_id: gp8403_10v - id: gp8403_output_1 - channel: 1 - -demo: - -esp32_ble: - enable_on_boot: false - -esp32_ble_server: - manufacturer: ESPHome - model: Test11 - -esp32_improv: - authorizer: io0_button - authorized_duration: 1min - status_indicator: built_in_led - -ezo_pmp: - id: hcl_pump - update_interval: 1s - -number: - - platform: template - name: My template number - id: template_number_id - optimistic: true - max_value: 100 - min_value: 0 - step: 5 - unit_of_measurement: "%" - mode: slider - device_class: humidity - on_value: - - logger.log: - format: Number changed to %f - args: [x] - set_action: - - logger.log: - format: Template Number set to %f - args: [x] - - number.set: - id: template_number_id - value: 50 - - number.to_min: template_number_id - - number.to_min: - id: template_number_id - - number.to_max: template_number_id - - number.to_max: - id: template_number_id - - number.increment: template_number_id - - number.increment: - id: template_number_id - cycle: false - - number.decrement: template_number_id - - number.decrement: - id: template_number_id - cycle: false - - number.operation: - id: template_number_id - operation: Increment - cycle: false - - number.operation: - id: template_number_id - operation: !lambda "return NUMBER_OP_INCREMENT;" - cycle: !lambda "return false;" - - - id: modbus_numbertest - platform: modbus_controller - modbus_controller_id: modbus_controller_test - name: ModbusNumber - address: 0x9002 - value_type: U_WORD - lambda: "return x * 1.0;" - write_lambda: |- - return x * 1.0 ; - multiply: 1.0 - -select: - - platform: template - name: My template select - id: template_select_id - optimistic: true - initial_option: two - restore_value: true - on_value: - - logger.log: - format: Select changed to %s (index %d)" - args: ["x.c_str()", "i"] - set_action: - - logger.log: - format: Template Select set to %s - args: ["x.c_str()"] - - select.set: - id: template_select_id - option: two - - select.first: template_select_id - - select.last: - id: template_select_id - - select.previous: template_select_id - - select.next: - id: template_select_id - cycle: false - - select.operation: - id: template_select_id - operation: Previous - cycle: false - - select.operation: - id: template_select_id - operation: !lambda "return SELECT_OP_PREVIOUS;" - cycle: !lambda "return true;" - - select.set_index: - id: template_select_id - index: 1 - - select.set_index: - id: template_select_id - index: !lambda "return 1 + 1;" - options: - - one - - two - - three - - - platform: modbus_controller - name: Modbus Select Register 1000 - address: 1000 - value_type: U_WORD - optionsmap: - "Zero": 0 - "One": 1 - "Two": 2 - "Three": 3 - -sensor: - - platform: adc - id: adc_sensor_p32 - name: ADC pin 32 - pin: - allow_other_uses: true - number: 32 - attenuation: 11db - update_interval: 1s - - platform: internal_temperature - name: Internal Temperature - - platform: selec_meter - total_active_energy: - name: SelecEM2M Total Active Energy - import_active_energy: - name: SelecEM2M Import Active Energy - export_active_energy: - name: SelecEM2M Export Active Energy - total_reactive_energy: - name: SelecEM2M Total Reactive Energy - import_reactive_energy: - name: SelecEM2M Import Reactive Energy - export_reactive_energy: - name: SelecEM2M Export Reactive Energy - apparent_energy: - name: SelecEM2M Apparent Energy - active_power: - name: SelecEM2M Active Power - reactive_power: - name: SelecEM2M Reactive Power - apparent_power: - name: SelecEM2M Apparent Power - voltage: - name: SelecEM2M Voltage - current: - name: SelecEM2M Current - power_factor: - name: SelecEM2M Power Factor - frequency: - name: SelecEM2M Frequency - maximum_demand_active_power: - name: SelecEM2M Maximum Demand Active Power - disabled_by_default: true - maximum_demand_reactive_power: - name: SelecEM2M Maximum Demand Reactive Power - disabled_by_default: true - maximum_demand_apparent_power: - name: SelecEM2M Maximum Demand Apparent Power - disabled_by_default: true - - - id: modbus_sensortest - platform: modbus_controller - modbus_controller_id: modbus_controller_test - address: 0x331A - register_type: read - value_type: U_WORD - - - platform: t6615 - uart_id: uart_2 - co2: - name: CO2 Sensor - - - platform: sen5x - id: sen54 - 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 - algorithm_tuning: - index_offset: 100 - learning_time_offset_hours: 12 - learning_time_gain_hours: 12 - gating_max_duration_minutes: 180 - std_initial: 50 - gain_factor: 230 - temperature_compensation: - offset: 0 - normalized_offset_slope: 0 - time_constant: 0 - auto_cleaning_interval: 604800s - acceleration_mode: low - store_baseline: true - address: 0x69 - - platform: mcp9600 - thermocouple_type: K - hot_junction: - name: Thermocouple Temperature - cold_junction: - name: Ambient Temperature - - - platform: ezo_pmp - current_volume_dosed: - name: Current Volume Dosed - total_volume_dosed: - name: Total Volume Dosed - absolute_total_volume_dosed: - name: Absolute Total Volume Dosed - pump_voltage: - name: Pump Voltage - last_volume_requested: - name: Last Volume Requested - max_flow_rate: - name: Max Flow Rate - - - platform: vbus - model: deltasol c - temperature_3: - name: Temperature 3 - operating_hours_1: - name: Operating Hours 1 - heat_quantity: - name: Heat Quantity - time: - name: System Time - - - platform: debug - free: - name: "Heap Free" - block: - name: "Heap Max Block" - loop_time: - name: "Loop Time" - psram: - name: "PSRAM Free" - - - platform: vbus - model: custom - command: 0x100 - source: 0x1234 - dest: 0x10 - sensors: - - id: vcustom - name: VBus Custom Sensor - lambda: return x[0] / 10.0; - - - platform: kuntze - ph: - name: Kuntze pH - temperature: - name: Kuntze temperature - - - platform: ade7953_i2c - irq_pin: - allow_other_uses: true - number: 16 - voltage: - name: ADE7953 Voltage - current_a: - name: ADE7953 Current A - current_b: - name: ADE7953 Current B - power_factor_a: - name: "ADE7953 Power Factor A" - power_factor_b: - name: "ADE7953 Power Factor B" - apparent_power_a: - name: "ADE7953 Apparent Power A" - apparent_power_b: - name: "ADE7953 Apparent Power B" - active_power_a: - name: ADE7953 Active Power A - active_power_b: - name: ADE7953 Active Power B - reactive_power_a: - name: "ADE7953 Reactive Power A" - reactive_power_b: - name: "ADE7953 Reactive Power B" - update_interval: 1s - - - platform: ade7953_spi - spi_id: spi_1 - cs_pin: 04 - irq_pin: - allow_other_uses: true - number: 16 - voltage: - name: ADE7953 Voltage - current_a: - name: ADE7953 Current A - current_b: - name: ADE7953 Current B - power_factor_a: - name: "ADE7953 Power Factor A" - power_factor_b: - name: "ADE7953 Power Factor B" - apparent_power_a: - name: "ADE7953 Apparent Power A" - apparent_power_b: - name: "ADE7953 Apparent Power B" - active_power_a: - name: ADE7953 Active Power A - active_power_b: - name: ADE7953 Active Power B - reactive_power_a: - name: "ADE7953 Reactive Power A" - reactive_power_b: - name: "ADE7953 Reactive Power B" - update_interval: 1s - -script: - - id: automation_test - then: - - repeat: - count: 5 - then: - - logger.log: looping! - - - id: zero_repeat_test - then: - - repeat: - count: !lambda "return 0;" - then: - - logger.log: shouldn't see mee! - -switch: - - platform: modbus_controller - modbus_controller_id: modbus_controller_test - id: modbus_switch_test - register_type: coil - address: 2 - bitmask: 1 - - - platform: tm1638 - id: Led0 - led: 0 - name: TM1638Led0 - - - platform: tm1638 - id: Led1 - led: 1 - name: TM1638Led1 - - - platform: tm1638 - id: Led2 - led: 2 - name: TM1638Led2 - - - platform: tm1638 - id: Led3 - led: 3 - name: TM1638Led3 - -display: - - platform: tm1638 - id: primarydisplay - stb_pin: - allow_other_uses: true - number: 5 # TM1638 STB - clk_pin: 18 # TM1638 CLK - dio_pin: 23 # TM1638 DIO - update_interval: 5s - intensity: 5 - lambda: |- - it.print("81818181"); - -time: - - platform: pcf85063 - - platform: pcf8563 - -text_sensor: - - platform: ezo_pmp - dosing_mode: - name: Dosing Mode - calibration_status: - name: Calibration Status - on_value: - - ezo_pmp.dose_volume: - id: hcl_pump - volume: 10 - - ezo_pmp.dose_volume_over_time: - id: hcl_pump - volume: 10 - duration: 2 - - ezo_pmp.dose_with_constant_flow_rate: - id: hcl_pump - volume_per_minute: 10 - duration: 2 - - ezo_pmp.set_calibration_volume: - id: hcl_pump - volume: 10 - - ezo_pmp.find: hcl_pump - - ezo_pmp.dose_continuously: hcl_pump - - ezo_pmp.clear_total_volume_dosed: hcl_pump - - ezo_pmp.clear_calibration: hcl_pump - - ezo_pmp.pause_dosing: hcl_pump - - ezo_pmp.stop_dosing: hcl_pump - - ezo_pmp.arbitrary_command: - id: hcl_pump - command: D,? - -sn74hc165: - id: sn74hc165_hub - data_pin: - allow_other_uses: true - number: GPIO12 - clock_pin: - allow_other_uses: true - number: GPIO14 - load_pin: - number: GPIO27 - clock_inhibit_pin: - number: GPIO26 - sr_count: 4 - -matrix_keypad: - id: keypad - rows: - - pin: - allow_other_uses: true - number: 21 - - pin: 19 - columns: - - pin: - allow_other_uses: true - number: 17 - - pin: - allow_other_uses: true - number: 16 - keys: "1234" - -key_collector: - - id: reader - source_id: keypad - min_length: 4 - max_length: 4 - -light: - - platform: esp32_rmt_led_strip - id: led_strip - pin: - allow_other_uses: true - number: 13 - num_leds: 60 - rmt_channel: 6 - rgb_order: GRB - chipset: ws2812 - - platform: esp32_rmt_led_strip - id: led_strip2 - pin: - allow_other_uses: true - number: 15 - num_leds: 60 - rmt_channel: 2 - rgb_order: RGB - bit0_high: 100us - bit0_low: 100us - bit1_high: 100us - bit1_low: 100us diff --git a/tests/test2.yaml b/tests/test2.yaml deleted file mode 100644 index 92977697c1..0000000000 --- a/tests/test2.yaml +++ /dev/null @@ -1,879 +0,0 @@ ---- -esphome: - name: $devicename - build_path: build/test2 - -esp32: - board: esp32dev - flash_size: 8MB - -globals: - - id: my_global_string - type: std::string - restore_value: true - max_restore_data_length: 70 - initial_value: '"DefaultValue"' - -substitutions: - devicename: test2 - -ethernet: - type: LAN8720 - mdc_pin: - allow_other_uses: true - number: GPIO23 - mdio_pin: - allow_other_uses: true - number: GPIO25 - clk_mode: GPIO0_IN - phy_addr: 0 - power_pin: - allow_other_uses: true - number: GPIO25 - manual_ip: - static_ip: 192.168.178.56 - gateway: 192.168.178.1 - subnet: 255.255.255.0 - domain: .local - -network: - enable_ipv6: true - -mdns: - disabled: true - -api: - -i2c: - sda: - allow_other_uses: true - number: 21 - scl: - allow_other_uses: true - number: 22 - scan: false - -spi: - clk_pin: - allow_other_uses: true - number: GPIO21 - mosi_pin: - allow_other_uses: true - number: GPIO22 - miso_pin: - allow_other_uses: true - number: GPIO23 - -uart: - tx_pin: - allow_other_uses: true - number: GPIO22 - rx_pin: - allow_other_uses: true - number: GPIO23 - baud_rate: 115200 - # Specifically added for testing debug with no after: definition. - debug: - dummy_receiver: false - direction: rx - sequence: - - lambda: UARTDebug::log_hex(direction, bytes, ':'); - -safe_mode: - -ota: - - platform: esphome - port: 3286 - -logger: - level: DEBUG - -debug: - -deep_sleep: - run_duration: - default: 20s - gpio_wakeup_reason: 10s - touch_wakeup_reason: 15s - sleep_duration: 50s - wakeup_pin: - allow_other_uses: true - number: GPIO2 - wakeup_pin_mode: INVERT_WAKEUP - -as3935_i2c: - irq_pin: - allow_other_uses: true - number: GPIO12 - -mcp3008: - - id: mcp3008_hub - cs_pin: - allow_other_uses: true - number: GPIO12 - -output: - - platform: ac_dimmer - id: dimmer1 - gate_pin: GPIO5 - zero_cross_pin: - allow_other_uses: true - number: GPIO12 - -sensor: - - platform: homeassistant - entity_id: sensor.hello_world - id: ha_hello_world - - platform: homeassistant - entity_id: climate.living_room - attribute: temperature - id: ha_hello_world_temperature - - platform: ble_rssi - mac_address: AC:37:43:77:5F:4C - name: BLE Google Home Mini RSSI value - - platform: ble_rssi - service_uuid: 11aa - name: BLE Test Service 16 - - platform: ble_rssi - service_uuid: "11223344" - name: BLE Test Service 32 - - platform: ble_rssi - service_uuid: 11223344-5566-7788-99aa-bbccddeeff00 - name: BLE Test Service 128 - - platform: ble_rssi - service_uuid: 11223344-5566-7788-99aa-bbccddeeff00 - name: BLE Test iBeacon UUID - - platform: b_parasite - mac_address: F0:CA:F0:CA:01:01 - humidity: - name: b-parasite Air Humidity - temperature: - name: b-parasite Air Temperature - moisture: - name: b-parasite Soil Moisture - battery_voltage: - name: b-parasite Battery Voltage - illuminance: - name: b-parasite Illuminance - - platform: senseair - id: senseair0 - co2: - name: SenseAir CO2 Value - on_value: - then: - - senseair.background_calibration: senseair0 - - senseair.background_calibration_result: senseair0 - - senseair.abc_get_period: senseair0 - - senseair.abc_enable: senseair0 - - senseair.abc_disable: senseair0 - update_interval: 15s - - platform: ruuvitag - mac_address: FF:56:D3:2F:7D:E8 - humidity: - name: RuuviTag Humidity - temperature: - name: RuuviTag Temperature - pressure: - name: RuuviTag Pressure - acceleration_x: - name: RuuviTag Acceleration X - acceleration_y: - name: RuuviTag Acceleration Y - acceleration_z: - name: RuuviTag Acceleration Z - battery_voltage: - name: RuuviTag Battery Voltage - tx_power: - name: RuuviTag TX Power - movement_counter: - name: RuuviTag Movement Counter - measurement_sequence_number: - name: RuuviTag Measurement Sequence Number - - platform: as3935 - lightning_energy: - name: Lightning Energy - distance: - name: Distance Storm - - platform: xiaomi_hhccjcy01 - mac_address: 94:2B:FF:5C:91:61 - temperature: - name: Xiaomi HHCCJCY01 Temperature - moisture: - name: Xiaomi HHCCJCY01 Moisture - illuminance: - name: Xiaomi HHCCJCY01 Illuminance - conductivity: - name: Xiaomi HHCCJCY01 Soil Conductivity - battery_level: - name: Xiaomi HHCCJCY01 Battery Level - - platform: xiaomi_hhccjcy10 - mac_address: DD:25:6D:E4:FF:8F - temperature: - name: "Xiaomi HHCCJCY10 Temperature" - moisture: - name: "Xiaomi HHCCJCY10 Moisture" - illuminance: - name: "Xiaomi HHCCJCY10 Illuminance" - conductivity: - name: "Xiaomi HHCCJCY10 Soil Conductivity" - battery_level: - name: "Xiaomi HHCCJCY10 Battery Level" - - platform: xiaomi_lywsdcgq - mac_address: 7A:80:8E:19:36:BA - temperature: - name: Xiaomi LYWSDCGQ Temperature - humidity: - name: Xiaomi LYWSDCGQ Humidity - battery_level: - name: Xiaomi LYWSDCGQ Battery Level - - platform: xiaomi_lywsd02 - mac_address: 3F:5B:7D:82:58:4E - temperature: - name: Xiaomi LYWSD02 Temperature - humidity: - name: Xiaomi LYWSD02 Humidity - battery_level: - name: Xiaomi LYWSD02 Battery Level - - platform: xiaomi_cgg1 - mac_address: 7A:80:8E:19:36:BA - temperature: - name: Xiaomi CGG1 Temperature - humidity: - name: Xiaomi CGG1 Humidity - battery_level: - name: Xiaomi CGG1 Battery Level - - platform: xiaomi_gcls002 - mac_address: 94:2B:FF:5C:91:61 - temperature: - name: GCLS02 Temperature - moisture: - name: GCLS02 Moisture - conductivity: - name: GCLS02 Soil Conductivity - illuminance: - name: GCLS02 Illuminance - - platform: xiaomi_hhccpot002 - mac_address: 94:2B:FF:5C:91:61 - moisture: - name: HHCCPOT002 Moisture - conductivity: - name: HHCCPOT002 Soil Conductivity - - platform: xiaomi_lywsd03mmc - mac_address: A4:C1:38:4E:16:78 - bindkey: e9efaa6873f9f9c87a5e75a5f814801c - temperature: - name: Xiaomi LYWSD03MMC Temperature - humidity: - name: Xiaomi LYWSD03MMC Humidity - battery_level: - name: Xiaomi LYWSD03MMC Battery Level - - platform: xiaomi_cgd1 - mac_address: A4:C1:38:D1:61:7D - bindkey: c99d2313182473b38001086febf781bd - temperature: - name: Xiaomi CGD1 Temperature - humidity: - name: Xiaomi CGD1 Humidity - battery_level: - name: Xiaomi CGD1 Battery Level - - platform: xiaomi_jqjcy01ym - mac_address: 7A:80:8E:19:36:BA - temperature: - name: JQJCY01YM Temperature - humidity: - name: JQJCY01YM Humidity - formaldehyde: - name: JQJCY01YM Formaldehyde - battery_level: - name: JQJCY01YM Battery Level - - platform: xiaomi_mhoc303 - mac_address: E7:50:59:32:A0:1C - temperature: - name: MHO-C303 Temperature - humidity: - name: MHO-C303 Humidity - battery_level: - name: MHO-C303 Battery Level - - platform: atc_mithermometer - mac_address: A4:C1:38:4E:16:78 - temperature: - name: ATC Temperature - humidity: - name: ATC Humidity - battery_level: - name: ATC Battery-Level - battery_voltage: - name: ATC Battery-Voltage - - platform: pvvx_mithermometer - mac_address: A4:C1:38:4E:16:78 - temperature: - name: PVVX Temperature - humidity: - name: PVVX Humidity - battery_level: - name: PVVX Battery-Level - battery_voltage: - name: PVVX Battery-Voltage - - platform: inkbird_ibsth1_mini - mac_address: 38:81:D7:0A:9C:11 - temperature: - name: Inkbird IBS-TH1 Temperature - humidity: - name: Inkbird IBS-TH1 Humidity - battery_level: - name: Inkbird IBS-TH1 Battery Level - - platform: xiaomi_rtcgq02lm - id: motion_rtcgq02lm - battery_level: - name: Mi Motion Sensor 2 Battery level - - platform: ltr390 - uv: - name: LTR390 UV - uv_index: - name: LTR390 UVI - light: - name: LTR390 Light - ambient_light: - name: LTR390 ALS - gain: X3 - resolution: 18 - window_correction_factor: 1.0 - address: 0x53 - update_interval: 60s - - platform: sgp4x - voc: - name: VOC Index - id: sgp40_voc_index - algorithm_tuning: - index_offset: 100 - learning_time_offset_hours: 12 - learning_time_gain_hours: 12 - gating_max_duration_minutes: 180 - std_initial: 50 - gain_factor: 230 - nox: - name: NOx - algorithm_tuning: - index_offset: 100 - learning_time_offset_hours: 12 - learning_time_gain_hours: 12 - gating_max_duration_minutes: 180 - std_initial: 50 - gain_factor: 230 - update_interval: 5s - - platform: mcp3008 - update_interval: 5s - mcp3008_id: mcp3008_hub - id: freezer_temp_source - reference_voltage: 3.19 - number: 0 - - id: airthingswp - platform: airthings_wave_plus - ble_client_id: airthings01 - update_interval: 5min - battery_update_interval: 12h - temperature: - name: Wave Plus Temperature - radon: - name: Wave Plus Radon - radon_long_term: - name: Wave Plus Radon Long Term - pressure: - name: Wave Plus Pressure - humidity: - name: Wave Plus Humidity - co2: - name: Wave Plus CO2 - tvoc: - name: Wave Plus VOC - battery_voltage: - name: Wave Plus Battery Voltage - - id: airthingswm - platform: airthings_wave_mini - ble_client_id: airthingsmini01 - update_interval: 5min - battery_update_interval: 12h - temperature: - name: Wave Mini Temperature - humidity: - name: Wave Mini Humidity - pressure: - name: Wave Mini Pressure - tvoc: - name: Wave Mini VOC - battery_voltage: - name: Wave Mini Battery Voltage - - platform: ina260 - address: 0x40 - current: - name: INA260 Current - power: - name: INA260 Power - bus_voltage: - name: INA260 Voltage - update_interval: 60s - - platform: radon_eye_rd200 - ble_client_id: radon_eye_ble_id - update_interval: 10min - radon: - name: RD200 Radon - radon_long_term: - name: RD200 Radon Long Term - - platform: mopeka_pro_check - mac_address: D3:75:F2:DC:16:91 - tank_type: CUSTOM - custom_distance_full: 40cm - custom_distance_empty: 10mm - temperature: - name: Propane test temp - level: - name: Propane test level - distance: - name: Propane test distance - battery_level: - name: Propane test battery level - - platform: ufire_ec - id: ufire_ec_board - ec: - name: Ufire EC - temperature_sensor: ha_hello_world_temperature - temperature_compensation: 20.0 - temperature_coefficient: 0.019 - - platform: ufire_ise - id: ufire_ise_board - temperature_sensor: ha_hello_world_temperature - ph: - name: Ufire pH - - platform: mics_4514 - update_interval: 60s - nitrogen_dioxide: - name: MICS-4514 NO2 - carbon_monoxide: - name: MICS-4514 CO - methane: - name: MICS-4514 CH4 - hydrogen: - name: MICS-4514 H2 - ethanol: - name: MICS-4514 C2H5OH - ammonia: - name: MICS-4514 NH3 - - platform: mopeka_std_check - mac_address: D3:75:F2:DC:16:91 - tank_type: CUSTOM - custom_distance_full: 40cm - custom_distance_empty: 10mm - temperature: - name: Propane test temp - level: - name: Propane test level - distance: - name: Propane test distance - battery_level: - name: Propane test battery level - - platform: duty_time - id: duty_time1 - name: Test Duty Time - restore: true - last_time: - name: Test Last Duty Time Sensor - sensor: ha_hello_world_binary - - platform: duty_time - id: duty_time2 - name: Test Duty Time 2 - restore: false - lambda: "return true;" - -time: - - platform: homeassistant - on_time: - - at: "16:00:00" - then: - - logger.log: It's 16:00 - - if: - condition: - - sensor.duty_time.is_running: duty_time2 - then: - - sensor.duty_time.start: duty_time1 - - if: - condition: - - sensor.duty_time.is_not_running: duty_time1 - then: - - sensor.duty_time.stop: duty_time2 - - sensor.duty_time.reset: duty_time1 - -esp32_touch: - setup_mode: true - -binary_sensor: - - platform: homeassistant - entity_id: binary_sensor.hello_world - id: ha_hello_world_binary - - platform: homeassistant - entity_id: binary_sensor.hello - attribute: world - id: ha_hello_world_binary_attribute - - platform: ble_presence - mac_address: AC:37:43:77:5F:4C - name: ESP32 BLE Tracker Google Home Mini - timeout: 30s - - platform: ble_presence - service_uuid: 11aa - name: BLE Test Service 16 Presence - - platform: ble_presence - service_uuid: "11223344" - name: BLE Test Service 32 Presence - - platform: ble_presence - service_uuid: 11223344-5566-7788-99aa-bbccddeeff00 - name: BLE Test Service 128 Presence - - platform: ble_presence - ibeacon_uuid: 11223344-5566-7788-99aa-bbccddeeff00 - ibeacon_major: 100 - ibeacon_minor: 1 - name: BLE Test iBeacon Presence - - platform: esp32_touch - name: ESP32 Touch Pad GPIO27 - pin: GPIO27 - threshold: 1000 - - platform: as3935 - name: Storm Alert - - platform: xiaomi_mue4094rt - name: MUE4094RT Motion - mac_address: 7A:80:8E:19:36:BA - timeout: 5s - - platform: xiaomi_mjyd02yla - name: MJYD02YL-A Motion - mac_address: 50:EC:50:CD:32:02 - bindkey: 48403ebe2d385db8d0c187f81e62cb64 - idle_time: - name: MJYD02YL-A Idle Time - light: - name: MJYD02YL-A Light Status - battery_level: - name: MJYD02YL-A Battery Level - - platform: xiaomi_wx08zm - name: WX08ZM Activation State - mac_address: 74:a3:4a:b5:07:34 - tablet: - name: WX08ZM Tablet Resource - battery_level: - name: WX08ZM Battery Level - - platform: xiaomi_cgpr1 - name: CGPR1 Motion - mac_address: "12:34:56:12:34:56" - bindkey: 48403ebe2d385db8d0c187f81e62cb64 - battery_level: - name: CGPR1 battery Level - idle_time: - name: CGPR1 Idle Time - illuminance: - name: CGPR1 Illuminance - - platform: xiaomi_rtcgq02lm - id: motion_rtcgq02lm - motion: - name: Mi Motion Sensor 2 - light: - name: Mi Motion Sensor 2 Light - button: - name: Mi Motion Sensor 2 Button - - platform: gpio - id: gpio_set_retry_test - pin: - allow_other_uses: true - number: GPIO9 - on_press: - then: - - lambda: |- - App.scheduler.set_retry(id(gpio_set_retry_test), "set_retry_test", 100, 3, [](const uint8_t remaining) { - return remaining ? RetryResult::RETRY : RetryResult::DONE; // just to reference both symbols - }, 5.0f); - -esp32_ble_tracker: - on_ble_advertise: - - mac_address: - - AA:BB:CC:DD:EE:FF - - FF:EE:DD:CC:BB:AA - then: - # yamllint disable rule:line-length - - lambda: !lambda |- - ESP_LOGD("main", "The device address (%s) exists in list", x.address_str().c_str()); - # yamllint enable rule:line-length - - mac_address: AC:37:43:77:5F:4C - then: - # yamllint disable rule:line-length - - lambda: !lambda |- - ESP_LOGD("main", "The device address is %s", x.address_str().c_str()); - # yamllint enable rule:line-length - - then: - # yamllint disable rule:line-length - - lambda: !lambda |- - ESP_LOGD("main", "The device address is %s", x.address_str().c_str()); - # yamllint enable rule:line-length - on_ble_service_data_advertise: - - service_uuid: ABCD - then: - - lambda: !lambda |- - ESP_LOGD("main", "Length of service data is %i", x.size()); - on_ble_manufacturer_data_advertise: - - manufacturer_id: ABCD - then: - - lambda: !lambda |- - ESP_LOGD("main", "Length of manufacturer data is %i", x.size()); - -ble_client: - - mac_address: 01:02:03:04:05:06 - id: airthings01 - - mac_address: 01:02:03:04:05:06 - id: airthingsmini01 - - mac_address: 01:02:03:04:05:06 - id: radon_eye_ble_id - -airthings_ble: - -radon_eye_ble: - -ruuvi_ble: - -xiaomi_ble: - -mopeka_ble: - -bluetooth_proxy: - active: true - -xiaomi_rtcgq02lm: - - id: motion_rtcgq02lm - mac_address: 01:02:03:04:05:06 - bindkey: "48403ebe2d385db8d0c187f81e62cb64" - -status_led: - pin: - allow_other_uses: true - number: GPIO2 - -text_sensor: - - platform: version - name: ESPHome Version - icon: mdi:icon - id: version_sensor - on_value: - - if: - condition: - - api.connected: - then: - # yamllint disable rule:line-length - - lambda: !lambda |- - ESP_LOGD("main", "The state is %s=%s", x.c_str(), id(version_sensor).state.c_str()); - # yamllint enable rule:line-length - - script.execute: my_script - - script.execute: - id: my_script_with_params - prefix: Running my_script_with_params - param2: 100 - param3: true - - script.execute: - id: my_script_with_params - prefix: Running my_script_with_params using lambda parameters - param2: !lambda return 200; - param3: !lambda return true; - - homeassistant.service: - service: notify.html5 - data: - title: New Humidity - data_template: - message: The humidity is {{ my_variable }}%. - variables: - my_variable: |- - return id(version_sensor).state; - my_variable_str: |- - return "Hello World"; - - homeassistant.service: - service: light.turn_on - data: - entity_id: light.my_light - - homeassistant.tag_scanned: - tag: 1234-abcd - - homeassistant.tag_scanned: 1234-abcd - - deep_sleep.enter: - sleep_duration: 30min - - deep_sleep.enter: - sleep_duration: !lambda "return 30 * 60 * 1000;" - - platform: template - name: Template Text Sensor - lambda: |- - return {"Hello World"}; - filters: - - to_upper: - - to_lower: - - append: xyz - - prepend: abcd - - substitute: - - Hello -> Goodbye - - map: - - red -> green - - lambda: 'return {"1234"};' - - platform: homeassistant - entity_id: sensor.hello_world2 - id: ha_hello_world2 - - platform: homeassistant - entity_id: sensor.hello_world3 - id: ha_hello_world3 - attribute: some_attribute - - platform: ble_scanner - name: Scanner - -script: - - id: my_script - mode: single - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_queued - mode: queued - max_runs: 2 - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_parallel - mode: parallel - max_runs: 2 - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_restart - mode: restart - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_with_params - parameters: - prefix: string - param2: int - param3: bool - then: - - lambda: 'ESP_LOGD("main", (prefix + " Hello World!" + to_string(param2) + " " + to_string(param3)).c_str());' - -stepper: - - platform: uln2003 - id: my_stepper - pin_a: - allow_other_uses: true - number: GPIO23 - pin_b: GPIO27 - pin_c: - allow_other_uses: true - number: GPIO25 - pin_d: GPIO26 - sleep_when_done: false - step_mode: HALF_STEP - max_speed: 250 steps/s - - # Optional: - acceleration: inf - deceleration: inf - -interval: - interval: 5s - startup_delay: 10s - then: - - logger.log: Interval Run - -display: - - platform: st7789v - model: LILYGO_T-EMBED_170X320 - spi_mode: mode0 - height: 320 - width: 170 - offset_height: 35 - offset_width: 0 - dc_pin: GPIO13 - reset_pin: - allow_other_uses: true - number: GPIO9 - -image: - - id: binary_image - file: pnglogo.png - type: BINARY - dither: FloydSteinberg - - id: transparent_transparent_image - file: pnglogo.png - type: TRANSPARENT_BINARY - - id: rgba_image - file: pnglogo.png - type: RGBA - resize: 50x50 - - id: rgb24_image - file: pnglogo.png - type: RGB24 - use_transparency: true - - id: rgb565_image - file: pnglogo.png - type: RGB565 - use_transparency: false - - id: web_svg_image - file: https://raw.githubusercontent.com/esphome/esphome-docs/a62d7ab193c1a464ed791670170c7d518189109b/images/logo.svg - resize: 256x48 - type: TRANSPARENT_BINARY - - id: web_tiff_image - file: https://upload.wikimedia.org/wikipedia/commons/b/b6/SIPI_Jelly_Beans_4.1.07.tiff - type: RGB24 - resize: 48x48 - - id: web_redirect_image - file: https://avatars.githubusercontent.com/u/3060199?s=48&v=4 - type: RGB24 - resize: 48x48 - - - id: mdi_alert - file: mdi:alert-circle-outline - resize: 50x50 - - id: another_alert_icon - file: mdi:alert-outline - type: BINARY - -graph: - - id: my_graph - sensor: ha_hello_world_temperature - duration: 1h - width: 100 - height: 100 - -cap1188: - id: cap1188_component - address: 0x29 - touch_threshold: 0x20 - allow_multiple_touches: true - reset_pin: 14 - -switch: - - platform: template - name: Test BLE Write Action - turn_on_action: - - ble_client.ble_write: - id: airthings01 - service_uuid: F61E3BE9-2826-A81B-970A-4D4DECFABBAE - characteristic_uuid: 6490FAFE-0734-732C-8705-91B653A081FC - value: [0x01, 0xab, 0xff] - - ble_client.ble_write: - id: airthings01 - service_uuid: F61E3BE9-2826-A81B-970A-4D4DECFABBAE - characteristic_uuid: 6490FAFE-0734-732C-8705-91B653A081FC - value: !lambda |- - return {0x13, 0x37}; - -esp32_ble_server: - id: ble - manufacturer_data: [0x72, 0x4, 0x00, 0x23] - -text: - - platform: template - name: My Text - id: my_text - min_length: 0 - max_length: 20 - mode: text - pattern: "[a-z]+" - optimistic: true - restore_value: true - initial_value: "Hello World" - - platform: copy - name: My Text Copy - id: my_text_copy - source_id: my_text - mode: password diff --git a/tests/test3.1.yaml b/tests/test3.1.yaml deleted file mode 100644 index c3b078fe67..0000000000 --- a/tests/test3.1.yaml +++ /dev/null @@ -1,734 +0,0 @@ ---- -esphome: - name: $device_name - comment: $device_comment - build_path: build/test3.1 - includes: - - custom.h - -esp8266: - board: d1_mini - -substitutions: - device_name: test3-1 - device_comment: test3-1 device - min_sub: "0.03" - max_sub: "12.0%" - -api: - -wifi: - ssid: "MySSID" - password: "password1" - -network: - enable_ipv6: true - -web_server: - port: 80 - version: 2 - -i2c: - sda: - allow_other_uses: true - number: 4 - scl: - allow_other_uses: true - number: 5 - scan: false - -spi: - clk_pin: - allow_other_uses: true - number: GPIO12 - mosi_pin: - allow_other_uses: true - number: GPIO13 - miso_pin: - allow_other_uses: true - number: GPIO14 - -ota: - - platform: esphome - version: 2 - -logger: - -debug: - -sensor: - - platform: apds9960 - type: proximity - name: APDS9960 Proximity - - platform: vl53l0x - name: VL53L0x Distance - address: 0x29 - update_interval: 60s - enable_pin: - allow_other_uses: true - number: GPIO13 - timeout: 200us - - platform: apds9960 - type: clear - name: APDS9960 Clear - - platform: apds9960 - type: red - name: APDS9960 Red - - platform: apds9960 - type: green - name: APDS9960 Green - - platform: apds9960 - type: blue - name: APDS9960 Blue - - - platform: aht10 - temperature: - name: Temperature - humidity: - name: Humidity - - platform: am2320 - temperature: - name: Temperature - humidity: - name: Humidity - - platform: adc - pin: VCC - id: my_sensor - filters: - - offset: 5.0 - - multiply: 2.0 - - filter_out: NAN - - sliding_window_moving_average: - - exponential_moving_average: - - quantile: - window_size: 5 - send_every: 5 - send_first_at: 3 - quantile: .8 - - lambda: "return 0;" - - delta: 100 - - throttle: 100ms - - debounce: 500s - - timeout: 10min - - timeout: - timeout: 10min - value: 0 - - calibrate_linear: - method: exact - datapoints: - - -1 -> 3 - - 0.0 -> 1.0 - - 1.0 -> 2.0 - - 2.0 -> 3.0 - - calibrate_polynomial: - degree: 3 - datapoints: - - 0 -> 0 - - 100 -> 200 - - 400 -> 500 - - -50 -> -1000 - - -100 -> -10000 - - platform: cd74hc4067 - id: cd74hc4067_0 - number: 0 - sensor: my_sensor - - platform: resistance - sensor: my_sensor - configuration: DOWNSTREAM - resistor: 10kΩ - reference_voltage: 3.3V - name: Resistance - id: resist - - platform: ntc - sensor: resist - name: NTC Sensor - calibration: - b_constant: 3950 - reference_resistance: 10k - reference_temperature: 25°C - - platform: ntc - sensor: resist - name: NTC Sensor2 - calibration: - - 10.0kOhm -> 25°C - - 27.219kOhm -> 0°C - - 14.674kOhm -> 15°C - - platform: ct_clamp - sensor: my_sensor - name: CT Clamp - sample_duration: 500ms - update_interval: 5s - - - platform: tcs34725 - red_channel: - name: Red Channel - green_channel: - name: Green Channel - blue_channel: - name: Blue Channel - clear_channel: - name: Clear Channel - illuminance: - name: Illuminance - color_temperature: - name: Color Temperature - integration_time: 614ms - gain: 60x - - platform: custom - lambda: |- - auto s = new CustomSensor(); - App.register_component(s); - return {s}; - sensors: - - id: custom_sensor - name: Custom Sensor - - - platform: ade7953_i2c - irq_pin: - allow_other_uses: true - number: GPIO16 - voltage: - name: ADE7953 Voltage - id: ade7953_voltage - current_a: - name: ADE7953 Current A - id: ade7953_current_a - current_b: - name: ADE7953 Current B - id: ade7953_current_b - power_factor_a: - name: "ADE7953 Power Factor A" - power_factor_b: - name: "ADE7953 Power Factor B" - apparent_power_a: - name: "ADE7953 Apparent Power A" - apparent_power_b: - name: "ADE7953 Apparent Power B" - active_power_a: - name: ADE7953 Active Power A - active_power_b: - name: ADE7953 Active Power B - reactive_power_a: - name: "ADE7953 Reactive Power A" - reactive_power_b: - name: "ADE7953 Reactive Power B" - update_interval: 1s - - - platform: ade7953_spi - cs_pin: - allow_other_uses: true - number: GPIO04 - irq_pin: - allow_other_uses: true - number: GPIO16 - voltage: - name: ADE7953 Voltage - current_a: - name: ADE7953 Current A - current_b: - name: ADE7953 Current B - power_factor_a: - name: "ADE7953 Power Factor A" - power_factor_b: - name: "ADE7953 Power Factor B" - apparent_power_a: - name: "ADE7953 Apparent Power A" - apparent_power_b: - name: "ADE7953 Apparent Power B" - active_power_a: - name: ADE7953 Active Power A - active_power_b: - name: ADE7953 Active Power B - reactive_power_a: - name: "ADE7953 Reactive Power A" - reactive_power_b: - name: "ADE7953 Reactive Power B" - update_interval: 1s - - - platform: tmp102 - name: TMP102 Temperature - - platform: hm3301 - pm_1_0: - name: PM1.0 - pm_2_5: - name: PM2.5 - pm_10_0: - name: PM10.0 - aqi: - name: AQI - calculation_type: AQI - - platform: ezo - id: ph_ezo - address: 99 - unit_of_measurement: pH - - platform: tof10120 - name: Distance sensor - update_interval: 5s - - - platform: mlx90393 - oversampling: 1 - filter: 0 - gain: 3X - x_axis: - name: mlxxaxis - y_axis: - name: mlxyaxis - z_axis: - name: mlxzaxis - resolution: 17BIT - temperature: - name: mlxtemp - oversampling: 2 - - - platform: adc128s102 - id: adc128s102_channel_0 - channel: 0 - - - platform: ade7880 - irq0_pin: - number: GPIO13 - allow_other_uses: true - irq1_pin: - number: GPIO5 - allow_other_uses: true - reset_pin: - number: GPIO16 - allow_other_uses: true - frequency: 60Hz - phase_a: - name: Channel A - voltage: Voltage - current: Current - active_power: Active Power - power_factor: Power Factor - forward_active_energy: Forward Active Energy - reverse_active_energy: Reverse Active Energy - calibration: - current_gain: 3116628 - voltage_gain: -757178 - power_gain: -1344457 - phase_angle: 188 - phase_b: - name: Channel B - voltage: Voltage - current: Current - active_power: Active Power - power_factor: Power Factor - forward_active_energy: Forward Active Energy - reverse_active_energy: Reverse Active Energy - calibration: - current_gain: 3133655 - voltage_gain: -755235 - power_gain: -1345638 - phase_angle: 188 - phase_c: - name: Channel C - voltage: Voltage - current: Current - active_power: Active Power - power_factor: Power Factor - forward_active_energy: Forward Active Energy - reverse_active_energy: Reverse Active Energy - calibration: - current_gain: 3111158 - voltage_gain: -743813 - power_gain: -1351437 - phase_angle: 180 - neutral: - name: Neutral - current: Current - calibration: - current_gain: 3189 - -apds9960: - address: 0x20 - update_interval: 60s - -binary_sensor: - - platform: apds9960 - direction: up - name: APDS9960 Up - device_class: motion - filters: - - invert - - delayed_on: 20ms - - delayed_off: 20ms - - lambda: "return false;" - on_state: - - logger.log: New state - id: my_binary_sensor - - platform: apds9960 - direction: down - name: APDS9960 Down - - platform: apds9960 - direction: left - name: APDS9960 Left - - platform: apds9960 - direction: right - name: APDS9960 Right - - - platform: ttp229_lsf - channel: 1 - name: TTP229 LSF Test - - platform: ttp229_bsf - channel: 1 - name: TTP229 BSF Test - - platform: custom - lambda: |- - auto s = new CustomBinarySensor(); - App.register_component(s); - return {s}; - binary_sensors: - - id: custom_binary_sensor - name: Custom Binary Sensor - - - platform: template - id: cover_toggle - on_press: - then: - - cover.toggle: time_based_cover - - cover.toggle: endstop_cover - - cover.toggle: current_based_cover - -globals: - - id: my_global_string - type: std::string - initial_value: '""' - -text_sensor: - - platform: custom - lambda: |- - auto s = new CustomTextSensor(); - App.register_component(s); - return {s}; - text_sensors: - - id: custom_text_sensor - name: Custom Text Sensor - -sm2135: - data_pin: - allow_other_uses: true - number: GPIO12 - clock_pin: - allow_other_uses: true - number: GPIO14 - rgb_current: 20mA - cw_current: 60mA - -grove_tb6612fng: - id: test_motor - address: 0x14 - -switch: - - platform: gpio - id: gpio_switch1 - pin: - mcp23xxx: mcp23017_hub - number: 0 - mode: OUTPUT - interlock: &interlock [gpio_switch1, gpio_switch2, gpio_switch3] - - platform: gpio - id: gpio_switch2 - pin: - mcp23xxx: mcp23008_hub - number: 0 - mode: OUTPUT - interlock: *interlock - - platform: gpio - id: gpio_switch3 - pin: - allow_other_uses: true - number: GPIO1 - interlock: *interlock - - platform: custom - lambda: |- - auto s = new CustomSwitch(); - return {s}; - switches: - - id: custom_switch - name: Custom Switch - - platform: template - name: open_vent - id: open_vent - optimistic: true - on_turn_on: - then: - - grove_tb6612fng.run: - channel: 1 - speed: 255 - direction: BACKWARD - id: test_motor - -custom_component: - lambda: |- - auto s = new CustomComponent(); - s->set_update_interval(15000); - return {s}; - -stepper: - - platform: uln2003 - id: my_stepper - pin_a: - allow_other_uses: true - number: GPIO12 - pin_b: - allow_other_uses: true - number: GPIO13 - pin_c: - allow_other_uses: true - number: GPIO14 - pin_d: - allow_other_uses: true - number: GPIO15 - sleep_when_done: false - step_mode: HALF_STEP - max_speed: 250 steps/s - acceleration: inf - deceleration: inf - - platform: a4988 - id: my_stepper2 - step_pin: - allow_other_uses: true - number: GPIO1 - dir_pin: - allow_other_uses: true - number: GPIO2 - max_speed: 0.1 steps/s - acceleration: 10 steps/s^2 - deceleration: 10 steps/s^2 - -interval: - interval: 5s - then: - - logger.log: Interval Run - - stepper.set_target: - id: my_stepper2 - target: 500 - - stepper.set_target: - id: my_stepper - target: !lambda "return 0;" - - stepper.report_position: - id: my_stepper2 - position: 0 - - stepper.report_position: - id: my_stepper - position: !lambda "return 50/100.0;" - -cover: - - platform: endstop - name: Endstop Cover - id: endstop_cover - stop_action: - - switch.turn_on: gpio_switch1 - open_endstop: my_binary_sensor - open_action: - - switch.turn_on: gpio_switch1 - open_duration: 5min - close_endstop: my_binary_sensor - close_action: - - switch.turn_on: gpio_switch2 - - output.set_level: - id: out - level: 50% - - output.esp8266_pwm.set_frequency: - id: out - frequency: 500.0Hz - - output.esp8266_pwm.set_frequency: - id: out - frequency: !lambda "return 500.0;" - - servo.write: - id: my_servo - level: -100% - - servo.write: - id: my_servo - level: !lambda "return -1.0;" - - delay: 2s - - servo.detach: my_servo - close_duration: 4.5min - max_duration: 10min - - platform: time_based - name: Time Based Cover - id: time_based_cover - stop_action: - - switch.turn_on: gpio_switch1 - open_action: - - switch.turn_on: gpio_switch1 - open_duration: 5min - close_action: - - switch.turn_on: gpio_switch2 - close_duration: 4.5min - - platform: current_based - name: Current Based Cover - id: current_based_cover - open_sensor: ade7953_current_a - open_moving_current_threshold: 0.5 - open_obstacle_current_threshold: 0.8 - open_duration: 12s - open_action: - - switch.turn_on: gpio_switch1 - close_sensor: ade7953_current_b - close_moving_current_threshold: 0.5 - close_obstacle_current_threshold: 0.8 - close_duration: 10s - close_action: - - switch.turn_on: gpio_switch2 - stop_action: - - switch.turn_off: gpio_switch1 - - switch.turn_off: gpio_switch2 - obstacle_rollback: 30% - start_sensing_delay: 0.8s - malfunction_detection: true - malfunction_action: - then: - - logger.log: Malfunction Detected - - platform: template - name: Template Cover with Tilt - tilt_lambda: "return 0.5;" - tilt_action: - - output.set_level: - id: out - level: !lambda "return tilt;" - position_action: - - output.set_level: - id: out - level: !lambda "return pos;" - -output: - - platform: esp8266_pwm - id: out - pin: - number: D3 - frequency: 50Hz - - platform: esp8266_pwm - id: out2 - pin: - allow_other_uses: true - number: D4 - - platform: custom - type: binary - lambda: |- - auto s = new CustomBinaryOutput(); - App.register_component(s); - return {s}; - outputs: - - id: custom_binary - - platform: sigma_delta_output - id: sddac - update_interval: 60s - pin: - allow_other_uses: true - number: D4 - turn_on_action: - then: - - logger.log: "Turned on" - turn_off_action: - then: - - logger.log: "Turned off" - state_change_action: - then: - - logger.log: - format: "Changed state: %d" - args: ["state"] - - platform: custom - type: float - lambda: |- - auto s = new CustomFloatOutput(); - App.register_component(s); - return {s}; - outputs: - - id: custom_float - - platform: slow_pwm - pin: - allow_other_uses: true - number: GPIO5 - id: my_slow_pwm - period: 15s - restart_cycle_on_state_change: false - - platform: sm2135 - id: sm2135_0 - channel: 0 - - platform: sm2135 - id: sm2135_1 - channel: 1 - - platform: sm2135 - id: sm2135_2 - channel: 2 - - platform: sm2135 - id: sm2135_3 - channel: 3 - - platform: sm2135 - id: sm2135_4 - channel: 4 - -mcp23017: - id: mcp23017_hub - -mcp23008: - id: mcp23008_hub - -light: - - platform: hbridge - name: Icicle Lights - pin_a: out - pin_b: out2 - -servo: - id: my_servo - output: out - restore: true - min_level: $min_sub - max_level: $max_sub - -ttp229_lsf: - -ttp229_bsf: - sdo_pin: - allow_other_uses: true - number: D2 - scl_pin: - allow_other_uses: true - number: D1 - -display: - - platform: max7219digit - cs_pin: - allow_other_uses: true - number: GPIO15 - num_chips: 4 - rotate_chip: 0 - intensity: 10 - scroll_mode: STOP - id: my_matrix - lambda: |- - it.printdigit("hello"); - -button: - - platform: output - id: output_button - output: out - duration: 100ms - - platform: wake_on_lan - target_mac_address: 12:34:56:78:90:ab - name: wol_test_1 - id: wol_1 - - platform: factory_reset - name: Restart Button (Factory Default Settings) - -cd74hc4067: - pin_s0: - allow_other_uses: true - number: GPIO12 - pin_s1: - allow_other_uses: true - number: GPIO13 - pin_s2: - allow_other_uses: true - number: GPIO14 - pin_s3: - allow_other_uses: true - number: GPIO15 - -adc128s102: - cs_pin: - allow_other_uses: true - number: GPIO12 diff --git a/tests/test3.yaml b/tests/test3.yaml deleted file mode 100644 index d10413b142..0000000000 --- a/tests/test3.yaml +++ /dev/null @@ -1,1432 +0,0 @@ ---- -esphome: - name: $device_name - comment: $device_comment - build_path: build/test3 - on_boot: - - if: - condition: - - api.connected - - wifi.connected - - time.has_time - then: - - logger.log: Have time - -esp8266: - board: d1_mini - early_pin_init: true - -substitutions: - device_name: test3 - device_comment: test3 device - -api: - port: 8000 - password: pwd - reboot_timeout: 0min - encryption: - key: bOFFzzvfpg5DB94DuBGLXD/hMnhpDKgP9UQyBulwWVU= - services: - - service: hello_world - variables: - name: string - then: - - logger.log: - format: Hello World %s! - args: - - name.c_str() - - service: empty_service - then: - - logger.log: Service Called - - service: all_types - variables: - bool_: bool - int_: int - float_: float - string_: string - then: - - logger.log: Something happened - - service: array_types - variables: - bool_arr: bool[] - int_arr: int[] - float_arr: float[] - string_arr: string[] - then: - - logger.log: - # yamllint disable rule:line-length - format: "Bool: %s (%u), Int: %d (%u), Float: %f (%u), String: %s (%u)" - # yamllint enable rule:line-length - args: - - YESNO(bool_arr[0]) - - bool_arr.size() - - int_arr[0] - - int_arr.size() - - float_arr[0] - - float_arr.size() - - string_arr[0].c_str() - - string_arr.size() - - service: dfplayer_next - then: - - dfplayer.play_next: - - service: dfplayer_previous - then: - - dfplayer.play_previous: - - service: dfplayer_play - variables: - file: int - then: - - dfplayer.play: !lambda "return file;" - - service: dfplayer_play_loop - variables: - file: int - loop_: bool - then: - - dfplayer.play: - file: !lambda "return file;" - loop: !lambda "return loop_;" - - service: dfplayer_play_folder - variables: - folder: int - file: int - then: - - dfplayer.play_folder: - folder: !lambda "return folder;" - file: !lambda "return file;" - - - service: dfplayer_play_loo_folder - variables: - folder: int - then: - - dfplayer.play_folder: - folder: !lambda "return folder;" - loop: true - - - service: dfplayer_set_device - variables: - device: int - then: - - dfplayer.set_device: - device: TF_CARD - - - service: dfplayer_set_volume - variables: - volume: int - then: - - dfplayer.set_volume: !lambda "return volume;" - - service: dfplayer_set_eq - variables: - preset: int - then: - # yamllint disable rule:line-length - - dfplayer.set_eq: !lambda "return static_cast(preset);" - # yamllint enable rule:line-length - - - service: dfplayer_sleep - then: - - dfplayer.sleep - - - service: dfplayer_reset - then: - - dfplayer.reset - - - service: dfplayer_start - then: - - dfplayer.start - - - service: dfplayer_pause - then: - - dfplayer.pause - - - service: dfplayer_stop - then: - - dfplayer.stop - - - service: dfplayer_random - then: - - dfplayer.random - - - service: dfplayer_volume_up - then: - - dfplayer.volume_up - - - service: dfplayer_volume_down - then: - - dfplayer.volume_down - - - service: battery_level_percent - variables: - level_percent: int - then: - - tm1651.set_level_percent: - id: tm1651_battery - level_percent: !lambda "return level_percent;" - - service: battery_level - variables: - level: int - then: - - tm1651.set_level: - id: tm1651_battery - level: !lambda "return level;" - - service: battery_brightness - variables: - brightness: int - then: - - tm1651.set_brightness: - id: tm1651_battery - brightness: !lambda "return brightness;" - - service: battery_turn_on - then: - - tm1651.turn_on: - id: tm1651_battery - - service: battery_turn_on - then: - - tm1651.turn_off: - id: tm1651_battery - - service: pid_set_control_parameters - then: - - climate.pid.set_control_parameters: - id: pid_climate - kp: 1.0 - kd: 1.0 - ki: 1.0 - - service: fingerprint_grow_enroll - variables: - finger_id: int - num_scans: int - then: - - fingerprint_grow.enroll: - finger_id: !lambda "return finger_id;" - num_scans: !lambda "return num_scans;" - - service: fingerprint_grow_cancel_enroll - then: - - fingerprint_grow.cancel_enroll: - - service: fingerprint_grow_delete - variables: - finger_id: int - then: - - fingerprint_grow.delete: - finger_id: !lambda "return finger_id;" - - service: fingerprint_grow_delete_all - then: - - fingerprint_grow.delete_all: - -wifi: - ssid: "MySSID" - password: "password1" - -network: - enable_ipv6: true - -uart: - - id: uart_1 - tx_pin: - number: GPIO1 - inverted: true - allow_other_uses: true - rx_pin: - allow_other_uses: true - number: GPIO3 - baud_rate: 115200 - - id: uart_2 - tx_pin: - allow_other_uses: true - number: GPIO4 - rx_pin: - allow_other_uses: true - number: GPIO5 - baud_rate: 9600 - - id: uart_3 - tx_pin: - allow_other_uses: true - number: GPIO4 - rx_pin: - allow_other_uses: true - number: GPIO5 - baud_rate: 4800 - - id: uart_4 - tx_pin: - allow_other_uses: true - number: GPIO4 - rx_pin: - allow_other_uses: true - number: GPIO5 - baud_rate: 9600 - - id: uart_5 - tx_pin: - allow_other_uses: true - number: GPIO4 - rx_pin: - allow_other_uses: true - number: GPIO5 - baud_rate: 9600 - - id: uart_6 - tx_pin: - allow_other_uses: true - number: GPIO4 - rx_pin: - allow_other_uses: true - number: GPIO5 - baud_rate: 9600 - - id: uart_7 - tx_pin: - allow_other_uses: true - number: GPIO4 - rx_pin: - allow_other_uses: true - number: GPIO5 - baud_rate: 38400 - - id: uart_8 - tx_pin: - allow_other_uses: true - number: GPIO4 - rx_pin: - allow_other_uses: true - number: GPIO5 - baud_rate: 4800 - parity: NONE - stop_bits: 2 - # Specifically added for testing debug with no options at all. - debug: - - id: uart_9 - tx_pin: - allow_other_uses: true - number: GPIO4 - rx_pin: - allow_other_uses: true - number: GPIO5 - baud_rate: 9600 - - id: uart_10 - tx_pin: - allow_other_uses: true - number: GPIO4 - rx_pin: - allow_other_uses: true - number: GPIO5 - baud_rate: 9600 - - id: uart_11 - tx_pin: - allow_other_uses: true - number: GPIO4 - rx_pin: - allow_other_uses: true - number: GPIO5 - baud_rate: 9600 - - id: uart_12 - tx_pin: - allow_other_uses: true - number: GPIO4 - rx_pin: - allow_other_uses: true - number: GPIO5 - baud_rate: 9600 - -modbus: - uart_id: uart_1 - -vbus: - uart_id: uart_4 - -safe_mode: - num_attempts: 5 - reboot_timeout: 10min - -ota: - - platform: esphome - port: 3286 - -logger: - hardware_uart: UART1 - level: DEBUG - esp8266_store_log_strings_in_flash: true - -debug: - -improv_serial: - next_url: https://esphome.io/?name={{device_name}}&version={{esphome_version}}&ip={{ip_address}} - -deep_sleep: - run_duration: 20s - sleep_duration: 50s - -wled: - -adalight: - -sensor: - - platform: daly_bms - voltage: - name: Battery Voltage - current: - name: Battery Current - battery_level: - name: Battery Level - max_cell_voltage: - name: Max Cell Voltage - max_cell_voltage_number: - name: Max Cell Voltage Number - min_cell_voltage: - name: Min Cell Voltage - min_cell_voltage_number: - name: Min Cell Voltage Number - max_temperature: - name: Max Temperature - max_temperature_probe_number: - name: Max Temperature Probe Number - min_temperature: - name: Min Temperature - min_temperature_probe_number: - name: Min Temperature Probe Number - remaining_capacity: - name: Remaining Capacity - cells_number: - name: Cells Number - temperature_1: - name: Temperature 1 - temperature_2: - name: Temperature 2 - - - platform: homeassistant - entity_id: sensor.hello_world - id: ha_hello_world - - - platform: hydreon_rgxx - model: RG 9 - uart_id: uart_6 - id: hydreon_rg9 - moisture: - name: hydreon_rain - id: hydreon_rain - temperature: - name: hydreon_temperature - disable_led: true - - - platform: hydreon_rgxx - model: RG_15 - uart_id: uart_6 - acc: - name: hydreon_acc - event_acc: - name: hydreon_event_acc - total_acc: - name: hydreon_total_acc - r_int: - name: hydreon_r_int - resolution: low - - - platform: adc - pin: VCC - id: my_sensor - - - platform: binary_sensor_map - name: Binary Sensor Map - type: group - channels: - - binary_sensor: bin1 - value: 10.0 - - binary_sensor: bin2 - value: 15.0 - - binary_sensor: bin3 - value: 100.0 - - - platform: binary_sensor_map - name: Binary Sensor Map - type: sum - channels: - - binary_sensor: bin1 - value: 10.0 - - binary_sensor: bin2 - value: 15.0 - - binary_sensor: bin3 - value: 100.0 - - - platform: binary_sensor_map - name: Binary Sensor Map - type: bayesian - prior: 0.4 - observations: - - binary_sensor: bin1 - prob_given_true: 0.9 - prob_given_false: 0.4 - - binary_sensor: bin2 - prob_given_true: 0.7 - prob_given_false: 0.05 - - binary_sensor: bin3 - prob_given_true: 0.8 - prob_given_false: 0.2 - - - platform: bl0939 - uart_id: uart_8 - voltage: - name: BL0939 Voltage - current_1: - name: BL0939 Current 1 - current_2: - name: BL0939 Current 2 - active_power_1: - name: BL0939 Active Power 1 - active_power_2: - name: BL0939 Active Power 2 - energy_1: - name: BL0939 Energy 1 - energy_2: - name: BL0939 Energy 2 - energy_total: - name: BL0939 Total energy - - platform: bl0940 - uart_id: uart_3 - voltage: - name: BL0940 Voltage - current: - name: BL0940 Current - power: - name: BL0940 Power - energy: - name: BL0940 Energy - internal_temperature: - name: BL0940 Internal temperature - external_temperature: - name: BL0940 External temperature - - platform: bl0942 - uart_id: uart_3 - voltage: - name: BL0942 Voltage - current: - name: BL0942 Current - power: - name: BL0942 Power - energy: - name: BL0942 Energy - frequency: - name: BL0942 Frequency - - platform: pzem004t - uart_id: uart_3 - voltage: - name: PZEM004T Voltage - current: - name: PZEM004T Current - power: - name: PZEM004T Power - - platform: pzemac - id: pzemac1 - voltage: - name: PZEMAC Voltage - current: - name: PZEMAC Current - power: - name: PZEMAC Power - energy: - name: PZEMAC Energy - frequency: - name: PZEMAC Frequency - power_factor: - name: PZEMAC Power Factor - - platform: pzemdc - id: pzemdc1 - voltage: - name: PZEMDC Voltage - current: - name: PZEMDC Current - power: - name: PZEMDC Power - energy: - name: PZEMDC Energy - - platform: pmsx003 - uart_id: uart_9 - type: PMSX003 - pm_1_0: - name: PM 1.0 Concentration - pm_2_5: - name: PM 2.5 Concentration - pm_10_0: - name: PM 10.0 Concentration - pm_1_0_std: - name: PM 1.0 Standard Atmospher Concentration - pm_2_5_std: - name: PM 2.5 Standard Atmospher Concentration - pm_10_0_std: - name: PM 10.0 Standard Atmospher Concentration - pm_0_3um: - name: Particulate Count >0.3um - pm_0_5um: - name: Particulate Count >0.5um - pm_1_0um: - name: Particulate Count >1.0um - pm_2_5um: - name: Particulate Count >2.5um - pm_5_0um: - name: Particulate Count >5.0um - pm_10_0um: - name: Particulate Count >10.0um - update_interval: 30s - - platform: pmsx003 - uart_id: uart_5 - type: PMS5003T - pm_1_0: - name: PM 1.0 Concentration - pm_2_5: - name: PM 2.5 Concentration - pm_10_0: - name: PM 10.0 Concentration - pm_1_0_std: - name: PM 1.0 Standard Atmospher Concentration - pm_2_5_std: - name: PM 2.5 Standard Atmospher Concentration - pm_10_0_std: - name: PM 10.0 Standard Atmospher Concentration - pm_0_3um: - name: Particulate Count >0.3um - pm_0_5um: - name: Particulate Count >0.5um - pm_1_0um: - name: Particulate Count >1.0um - pm_2_5um: - name: Particulate Count >2.5um - temperature: - name: PMS Temperature - humidity: - name: PMS Humidity - - platform: pmsx003 - uart_id: uart_6 - type: PMS5003ST - pm_1_0: - name: PM 1.0 Concentration - pm_2_5: - name: PM 2.5 Concentration - pm_10_0: - name: PM 10.0 Concentration - pm_1_0_std: - name: PM 1.0 Standard Atmospher Concentration - pm_2_5_std: - name: PM 2.5 Standard Atmospher Concentration - pm_10_0_std: - name: PM 10.0 Standard Atmospher Concentration - pm_0_3um: - name: Particulate Count >0.3um - pm_0_5um: - name: Particulate Count >0.5um - pm_1_0um: - name: Particulate Count >1.0um - pm_2_5um: - name: Particulate Count >2.5um - pm_5_0um: - name: Particulate Count >5.0um - pm_10_0um: - name: Particulate Count >10.0um - temperature: - name: PMS Temperature - humidity: - name: PMS Humidity - formaldehyde: - name: PMS Formaldehyde Concentration - - platform: cse7761 - uart_id: uart_7 - voltage: - name: CSE7761 Voltage - current_1: - name: CSE7761 Current 1 - current_2: - name: CSE7761 Current 2 - active_power_1: - name: CSE7761 Active Power 1 - active_power_2: - name: CSE7761 Active Power 2 - - platform: cse7766 - uart_id: uart_3 - voltage: - name: CSE7766 Voltage - current: - name: CSE7766 Current - power: - name: CSE7766 Power - apparent_power: - name: CSE7766 Apparent Power - power_factor: - name: CSE7766 Power Factor - - - platform: fingerprint_grow - fingerprint_count: - name: Fingerprint Count - status: - name: Fingerprint Status - capacity: - name: Fingerprint Capacity - security_level: - name: Fingerprint Security Level - last_finger_id: - name: Fingerprint Last Finger ID - last_confidence: - name: Fingerprint Last Confidence - - platform: sdm_meter - phase_a: - current: - name: Phase A Current - voltage: - name: Phase A Voltage - active_power: - name: Phase A Power - power_factor: - name: Phase A Power Factor - apparent_power: - name: Phase A Apparent Power - reactive_power: - name: Phase A Reactive Power - phase_angle: - name: Phase A Phase Angle - phase_b: - current: - name: Phase B Current - voltage: - name: Phase B Voltage - active_power: - name: Phase B Power - power_factor: - name: Phase B Power Factor - apparent_power: - name: Phase B Apparent Power - reactive_power: - name: Phase B Reactive Power - phase_angle: - name: Phase B Phase Angle - phase_c: - current: - name: Phase C Current - voltage: - name: Phase C Voltage - active_power: - name: Phase C Power - power_factor: - name: Phase C Power Factor - apparent_power: - name: Phase C Apparent Power - reactive_power: - name: Phase C Reactive Power - phase_angle: - name: Phase C Phase Angle - frequency: - name: Frequency - import_active_energy: - name: Import Active Energy - export_active_energy: - name: Export Active Energy - import_reactive_energy: - name: Import Reactive Energy - export_reactive_energy: - name: Export Reactive Energy - - platform: dsmr - energy_delivered_tariff1: - name: dsmr_energy_delivered_tariff1 - - - platform: nextion - id: testnumber - name: testnumber - variable_name: testnumber - - platform: nextion - id: testwave - name: testwave - component_id: 2 - wave_channel_id: 1 - - platform: smt100 - uart_id: uart_10 - counts: - name: Counts - dielectric_constant: - name: Dielectric Constant - temperature: - name: Temperature - moisture: - name: Moisture - voltage: - name: Voltage - update_interval: 60s - - - platform: vbus - model: deltasol c - temperature_1: - name: Temperature 1 - - - platform: kuntze - ph: - name: Kuntze pH - temperature: - name: Kuntze temperature - - - platform: haier - haier_id: haier_climate - compressor_current: - name: Haier AC compressor current - compressor_frequency: - name: Haier AC compressor frequency - expansion_valve_open_degree: - name: Haier AC expansion valve open degree - humidity: - name: Haier AC indoor humidity - indoor_coil_temperature: - name: Haier AC indoor coil temperature - outdoor_coil_temperature: - name: Haier AC outdoor coil temperature - outdoor_defrost_temperature: - name: Haier AC outdoor defrost temperature - outdoor_in_air_temperature: - name: Haier AC outdoor in air temperature - outdoor_out_air_temperature: - name: Haier AC outdoor out air temperature - outdoor_temperature: - name: Haier AC outdoor temperature - power: - name: Haier AC power - -time: - - platform: homeassistant - -binary_sensor: - - platform: daly_bms - charging_mos_enabled: - name: Charging MOS - discharging_mos_enabled: - name: Discharging MOS - - - platform: homeassistant - entity_id: binary_sensor.hello_world - id: ha_hello_world_binary - - - platform: fingerprint_grow - name: Fingerprint Enrolling - - platform: nextion - page_id: 0 - component_id: 2 - name: Nextion Component 2 Touch - - platform: nextion - id: r0_sensor - name: R0 Sensor - component_name: page0.r0 - - - platform: hydreon_rgxx - hydreon_rgxx_id: hydreon_rg9 - too_cold: - name: rg9_toocold - em_sat: - name: rg9_emsat - lens_bad: - name: rg9_lens_bad - - - platform: template - id: pzemac_reset_energy - on_press: - then: - - pzemac.reset_energy: pzemac1 - - platform: template - id: pzemdc_reset_energy - on_press: - then: - - pzemdc.reset_energy: pzemdc1 - - - platform: vbus - model: deltasol_bs_plus - relay1: - name: Relay 1 On - - - platform: gpio - id: bin1 - pin: - allow_other_uses: true - number: 1 - - platform: gpio - id: bin2 - pin: - allow_other_uses: true - number: 2 - - platform: gpio - id: bin3 - pin: - allow_other_uses: true - number: 3 - - - platform: haier - haier_id: haier_climate - compressor_status: - name: Haier AC compressor status - defrost_status: - name: Haier AC defrost status - four_way_valve_status: - name: Haier AC four-way valve status - indoor_electric_heating_status: - name: Haier AC indoor electric heating status - indoor_fan_status: - name: Haier AC indoor fan status - outdoor_fan_status: - name: Haier AC outdoor fan status - -globals: - - id: my_global_string - type: std::string - initial_value: '""' - -remote_receiver: - pin: - allow_other_uses: true - number: GPIO12 - dump: [] - -status_led: - pin: - allow_other_uses: true - number: GPIO2 - -text_sensor: - - platform: daly_bms - status: - name: BMS Status - - platform: version - name: ESPHome Version - icon: mdi:icon - id: version_sensor - on_value: - # yamllint disable rule:line-length - - lambda: !lambda |- - ESP_LOGD("main", "The state is %s=%s", x.c_str(), id(version_sensor).state.c_str()); - # yamllint enable rule:line-length - - script.execute: my_script - - script.wait: my_script - - script.stop: my_script - - homeassistant.service: - service: notify.html5 - data: - title: New Humidity - data_template: - message: The humidity is {{ my_variable }}%. - variables: - my_variable: |- - return id(version_sensor).state; - - platform: template - name: Template Text Sensor - lambda: |- - return {"Hello World"}; - - platform: homeassistant - entity_id: sensor.hello_world2 - id: ha_hello_world2 - - platform: nextion - name: text0 - id: text0 - update_interval: 4s - component_name: text0 - - platform: dsmr - identification: - name: dsmr_identification - p1_version: - name: dsmr_p1_version - -script: - - id: my_script - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - -switch: - - platform: gpio - id: gpio_switch1 - pin: - allow_other_uses: true - number: 1 - - platform: gpio - id: gpio_switch2 - pin: - allow_other_uses: true - number: 2 - - platform: gpio - id: gpio_switch3 - pin: - allow_other_uses: true - number: 3 - - - platform: nextion - id: r0 - name: R0 Switch - component_name: page0.r0 - -climate: - - platform: bang_bang - name: Bang Bang Climate - sensor: ha_hello_world - humidity_sensor: ha_hello_world - default_target_temperature_low: 18°C - default_target_temperature_high: 24°C - idle_action: - - switch.turn_on: gpio_switch1 - cool_action: - - switch.turn_on: gpio_switch2 - heat_action: - - switch.turn_on: gpio_switch1 - away_config: - default_target_temperature_low: 16°C - default_target_temperature_high: 20°C - - platform: thermostat - name: Thermostat Climate - sensor: ha_hello_world - humidity_sensor: ha_hello_world - preset: - - name: Default Preset - default_target_temperature_low: 18°C - default_target_temperature_high: 24°C - - name: Away - default_target_temperature_low: 16°C - default_target_temperature_high: 20°C - idle_action: - - switch.turn_on: gpio_switch1 - cool_action: - - switch.turn_on: gpio_switch2 - supplemental_cooling_action: - - switch.turn_on: gpio_switch3 - heat_action: - - switch.turn_on: gpio_switch1 - supplemental_heating_action: - - switch.turn_on: gpio_switch3 - dry_action: - - switch.turn_on: gpio_switch2 - fan_only_action: - - switch.turn_on: gpio_switch1 - auto_mode: - - switch.turn_on: gpio_switch2 - off_mode: - - switch.turn_on: gpio_switch1 - heat_mode: - - switch.turn_on: gpio_switch2 - cool_mode: - - switch.turn_on: gpio_switch1 - dry_mode: - - switch.turn_on: gpio_switch2 - fan_only_mode: - - switch.turn_on: gpio_switch1 - fan_mode_auto_action: - - switch.turn_on: gpio_switch2 - fan_mode_on_action: - - switch.turn_on: gpio_switch1 - fan_mode_off_action: - - switch.turn_on: gpio_switch2 - fan_mode_low_action: - - switch.turn_on: gpio_switch1 - fan_mode_medium_action: - - switch.turn_on: gpio_switch2 - fan_mode_high_action: - - switch.turn_on: gpio_switch1 - fan_mode_middle_action: - - switch.turn_on: gpio_switch2 - fan_mode_focus_action: - - switch.turn_on: gpio_switch1 - fan_mode_diffuse_action: - - switch.turn_on: gpio_switch2 - fan_mode_quiet_action: - - switch.turn_on: gpio_switch1 - swing_off_action: - - switch.turn_on: gpio_switch2 - swing_horizontal_action: - - switch.turn_on: gpio_switch1 - swing_vertical_action: - - switch.turn_on: gpio_switch2 - swing_both_action: - - switch.turn_on: gpio_switch1 - startup_delay: true - supplemental_cooling_delta: 2.0 - cool_deadband: 0.5 - cool_overrun: 0.5 - min_cooling_off_time: 300s - min_cooling_run_time: 300s - max_cooling_run_time: 600s - supplemental_heating_delta: 2.0 - heat_deadband: 0.5 - heat_overrun: 0.5 - min_heating_off_time: 300s - min_heating_run_time: 300s - max_heating_run_time: 600s - min_fanning_off_time: 30s - min_fanning_run_time: 30s - min_fan_mode_switching_time: 15s - min_idle_time: 30s - set_point_minimum_differential: 0.5 - fan_only_action_uses_fan_mode_timer: true - fan_only_cooling: true - fan_with_cooling: true - fan_with_heating: true - - platform: pid - id: pid_climate - name: PID Climate Controller - sensor: ha_hello_world - humidity_sensor: ha_hello_world - default_target_temperature: 21°C - heat_output: my_slow_pwm - control_parameters: - kp: 0.0 - ki: 0.0 - kd: 0.0 - max_integral: 0.0 - output_averaging_samples: 1 - derivative_averaging_samples: 1 - deadband_parameters: - threshold_high: 0.4 - threshold_low: -2.0 - kp_multiplier: 0.0 - ki_multiplier: 0.0 - kd_multiplier: 0.0 - deadband_output_averaging_samples: 1 - - platform: haier - id: haier_climate - protocol: hOn - name: Haier AC - uart_id: uart_12 - wifi_signal: true - answer_timeout: 200ms - beeper: true - visual: - min_temperature: 16 °C - max_temperature: 30 °C - temperature_step: - target_temperature: 1 - current_temperature: 0.5 - supported_modes: - - "OFF" - - HEAT_COOL - - COOL - - HEAT - - DRY - - FAN_ONLY - supported_swing_modes: - - "OFF" - - VERTICAL - - HORIZONTAL - - BOTH - supported_presets: - - AWAY - - BOOST - - ECO - - SLEEP - on_alarm_start: - then: - - logger.log: - level: DEBUG - format: 'Alarm activated. Code: %d. Message: "%s"' - args: [code, message] - on_alarm_end: - then: - - logger.log: - level: DEBUG - format: 'Alarm deactivated. Code: %d. Message: "%s"' - args: [code, message] - -sprinkler: - - id: yard_sprinkler_ctrlr - main_switch: Yard Sprinklers - auto_advance_switch: Yard Sprinklers Auto Advance - reverse_switch: Yard Sprinklers Reverse - pump_start_pump_delay: 2s - pump_stop_valve_delay: 4s - pump_switch_off_during_valve_open_delay: true - valve_open_delay: 5s - valves: - - valve_switch: Yard Valve 0 - enable_switch: Enable Yard Valve 0 - pump_switch_id: gpio_switch1 - run_duration: 10s - valve_switch_id: gpio_switch2 - - valve_switch: Yard Valve 1 - enable_switch: Enable Yard Valve 1 - pump_switch_id: gpio_switch1 - run_duration: 10s - valve_switch_id: gpio_switch2 - - valve_switch: Yard Valve 2 - enable_switch: Enable Yard Valve 2 - pump_switch_id: gpio_switch1 - run_duration: 10s - valve_switch_id: gpio_switch2 - - id: garden_sprinkler_ctrlr - main_switch: Garden Sprinklers - auto_advance_switch: Garden Sprinklers Auto Advance - reverse_switch: Garden Sprinklers Reverse - valve_overlap: 5s - valves: - - valve_switch: Garden Valve 0 - enable_switch: Enable Garden Valve 0 - pump_switch_id: gpio_switch1 - run_duration: 10s - valve_switch_id: gpio_switch2 - - valve_switch: Garden Valve 1 - enable_switch: Enable Garden Valve 1 - pump_switch_id: gpio_switch1 - run_duration: 10s - valve_switch_id: gpio_switch2 - -output: - - platform: esp8266_pwm - id: out - pin: - number: D3 - frequency: 50Hz - - platform: esp8266_pwm - id: out2 - pin: - allow_other_uses: true - number: D4 - - platform: slow_pwm - pin: - allow_other_uses: true - number: GPIO5 - id: my_slow_pwm - period: 15s - restart_cycle_on_state_change: false - -e131: - -light: - - platform: neopixelbus - name: Neopixelbus Light - pin: - allow_other_uses: true - number: GPIO1 - type: GRBW - variant: SK6812 - method: ESP8266_UART0 - num_leds: 100 - effects: - - wled: - - adalight: - uart_id: uart_3 - - e131: - universe: 1 - - platform: hbridge - name: Icicle Lights - pin_a: out - pin_b: out2 - - platform: sonoff_d1 - uart_id: uart_2 - use_rm433_remote: false - name: Sonoff D1 Dimmer - id: d1_light - restore_mode: RESTORE_DEFAULT_OFF - - platform: shelly_dimmer - name: "Shelly Dimmer Light" - power: - name: "Shelly Dimmer Power" - voltage: - name: "Shelly Dimmer Voltage" - current: - name: "Shelly Dimmer Current" - max_brightness: 500 - firmware: "51.6" - uart_id: uart_11 - nrst_pin: - number: 5 - allow_other_uses: true - boot0_pin: - number: 4 - allow_other_uses: true - -sim800l: - uart_id: uart_4 - on_sms_received: - - lambda: |- - std::string str; - str = sender; - str = message; - - sim800l.send_sms: - message: hello you - recipient: "+1234" - - sim800l.dial: - recipient: "+1234" - -dfplayer: - uart_id: uart_5 - on_finished_playback: - then: - if: - condition: - not: dfplayer.is_playing - then: - logger.log: Playback finished event -tm1651: - id: tm1651_battery - clk_pin: - allow_other_uses: true - number: D6 - dio_pin: - allow_other_uses: true - number: D5 - -rf_bridge: - uart_id: uart_5 - on_code_received: - - lambda: |- - uint32_t test; - test = data.sync; - test = data.low; - test = data.high; - test = data.code; - - rf_bridge.send_code: - sync: 0x1234 - low: 0x1234 - high: 0x1234 - code: 0x123456 - - rf_bridge.learn - - on_advanced_code_received: - - lambda: |- - uint32_t test; - std::string test_code; - test = data.length; - test = data.protocol; - test_code = data.code; - - rf_bridge.start_advanced_sniffing: - - rf_bridge.stop_advanced_sniffing: - - rf_bridge.send_advanced_code: - length: 0x04 - protocol: 0x01 - code: "ABC123" - - rf_bridge.send_raw: - raw: "AAA5070008001000ABC12355" - -display: - - platform: nextion - uart_id: uart_1 - tft_url: http://esphome.io/default35.tft - 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);' - -fingerprint_grow: - sensing_pin: - allow_other_uses: true - number: 4 - sensor_power_pin: - allow_other_uses: true - number: 5 - inverted: true - idle_period_to_sleep: 5s - password: 0x12FE37DC - new_password: 0xA65B9840 - on_finger_scan_start: - - homeassistant.event: - event: esphome.${device_name}_fingerprint_grow_finger_scan_start - on_finger_scan_invalid: - - homeassistant.event: - event: esphome.${device_name}_fingerprint_grow_finger_scan_invalid - on_finger_scan_matched: - - homeassistant.event: - event: esphome.${device_name}_fingerprint_grow_finger_scan_matched - data: - finger_id: !lambda "return finger_id;" - confidence: !lambda "return confidence;" - on_finger_scan_unmatched: - - homeassistant.event: - event: esphome.${device_name}_fingerprint_grow_finger_scan_unmatched - on_finger_scan_misplaced: - - homeassistant.event: - event: esphome.${device_name}_fingerprint_grow_finger_scan_misplaced - on_enrollment_scan: - - homeassistant.event: - event: esphome.${device_name}_fingerprint_grow_enrollment_scan - data: - finger_id: !lambda "return finger_id;" - scan_num: !lambda "return scan_num;" - on_enrollment_done: - - homeassistant.event: - event: esphome.${device_name}_fingerprint_grow_node_enrollment_done - data: - finger_id: !lambda "return finger_id;" - on_enrollment_failed: - - homeassistant.event: - event: esphome.${device_name}_fingerprint_grow_enrollment_failed - data: - finger_id: !lambda "return finger_id;" - uart_id: uart_6 - -dsmr: - decryption_key: 00112233445566778899aabbccddeeff - uart_id: uart_6 - max_telegram_length: 1000 - request_pin: - allow_other_uses: true - number: D5 - request_interval: 20s - receive_timeout: 100ms - -daly_bms: - update_interval: 20s - uart_id: uart_1 - -qr_code: - - id: homepage_qr - value: https://esphome.io/index.html - -lightwaverf: - read_pin: - number: 13 - write_pin: - allow_other_uses: true - number: 14 - -alarm_control_panel: - - platform: template - id: alarmcontrolpanel1 - name: Alarm Panel - codes: - - "1234" - requires_code_to_arm: true - arming_home_time: 1s - arming_night_time: 1s - arming_away_time: 15s - pending_time: 15s - trigger_time: 30s - binary_sensors: - - input: bin1 - bypass_armed_home: true - bypass_armed_night: true - on_state: - then: - - lambda: !lambda |- - ESP_LOGD("TEST", "State change %s", alarm_control_panel_state_to_string(id(alarmcontrolpanel1)->get_state())); - - platform: template - id: alarmcontrolpanel2 - name: Alarm Panel - codes: - - "1234" - requires_code_to_arm: true - arming_home_time: 1s - arming_night_time: 1s - arming_away_time: 15s - pending_time: 15s - trigger_time: 30s - binary_sensors: - - input: bin1 - bypass_armed_home: true - bypass_armed_night: true - on_disarmed: - then: - - logger.log: "### DISARMED ###" - on_pending: - then: - - logger.log: "### PENDING ###" - on_arming: - then: - - logger.log: "### ARMING ###" - on_armed_home: - then: - - logger.log: "### ARMED HOME ###" - on_armed_night: - then: - - logger.log: "### ARMED NIGHT ###" - on_armed_away: - then: - - logger.log: "### ARMED AWAY ###" - on_triggered: - then: - - logger.log: "### TRIGGERED ###" - on_cleared: - then: - - logger.log: "### CLEARED ###" diff --git a/tests/test4.yaml b/tests/test4.yaml deleted file mode 100644 index c9e8a27317..0000000000 --- a/tests/test4.yaml +++ /dev/null @@ -1,998 +0,0 @@ ---- -esphome: - name: $devicename - platform: ESP32 - board: nodemcu-32s - build_path: build/test4 - -substitutions: - devicename: test-4 - -ethernet: - type: LAN8720 - mdc_pin: - allow_other_uses: true - number: GPIO23 - mdio_pin: - allow_other_uses: true - number: GPIO25 - clk_mode: GPIO0_IN - phy_addr: 0 - power_pin: - allow_other_uses: true - number: GPIO25 - manual_ip: - static_ip: 192.168.178.56 - gateway: 192.168.178.1 - subnet: 255.255.255.0 - domain: .local - -network: - enable_ipv6: true - -mqtt: - broker: test.mosquitto.org - port: 1883 - discovery: true - discovery_prefix: homeassistant - topic_prefix: - -api: - -i2c: - sda: - allow_other_uses: true - number: 21 - scl: - allow_other_uses: true - number: 22 - scan: false - -spi: - - id: spi_id_1 - clk_pin: - allow_other_uses: true - number: GPIO21 - mosi_pin: - allow_other_uses: true - number: GPIO22 - miso_pin: - allow_other_uses: true - number: GPIO23 - interface: hardware - - id: spi_id_2 - clk_pin: - number: GPIO32 - mosi_pin: - number: GPIO33 - interface: hardware - -uart: - - id: uart115200 - tx_pin: - allow_other_uses: true - number: GPIO22 - rx_pin: - allow_other_uses: true - number: GPIO23 - baud_rate: 115200 - - id: uart9600 - tx_pin: - allow_other_uses: true - number: GPIO25 - rx_pin: - allow_other_uses: true - number: GPIO26 - baud_rate: 9600 - - id: uart_a02yyuw - tx_pin: - allow_other_uses: true - number: GPIO22 - rx_pin: - allow_other_uses: true - number: GPIO23 - baud_rate: 9600 - - id: uart_he60r - tx_pin: - number: GPIO18 - allow_other_uses: true - rx_pin: - number: GPIO36 - allow_other_uses: true - baud_rate: 1200 - parity: EVEN - -safe_mode: - -ota: - - platform: esphome - port: 3286 - -logger: - level: DEBUG - -debug: - -web_server: - ota: false - auth: - username: admin - password: admin - include_internal: true - -time: - - platform: sntp - id: sntp_time - -tuya: - time_id: sntp_time - uart_id: uart115200 - status_pin: - number: GPIO5 - inverted: true - allow_other_uses: true - -select: - - platform: tuya - id: tuya_select - enum_datapoint: 42 - options: - 0: Internal - 1: Floor - 2: Both - -pipsolar: - id: inverter0 - uart_id: uart115200 - -pylontech: - - id: pylontech0 - uart_id: uart115200 - - id: pylontech1 - uart_id: uart115200 - -sx1509: - - id: sx1509_hub - address: 0x3E - -mcp3204: - spi_id: spi_id_1 - cs_pin: - allow_other_uses: true - number: GPIO23 - -dac7678: - address: 0x4A - id: dac7678_hub1 - internal_reference: true - -sensor: - - platform: pylontech - pylontech_id: pylontech0 - battery: 1 - voltage: - id: pyl01_voltage - current: - id: pyl01_current - coulomb: - id: pyl01_soc - mos_temperature: - id: pyl01_mos_temperature - - platform: pylontech - pylontech_id: pylontech1 - battery: 1 - voltage: - id: pyl13_voltage - temperature_low: - id: pyl13_temperature_low - temperature_high: - id: pyl13_temperature_high - voltage_low: - id: pyl13_voltage_low - voltage_high: - id: pyl13_voltage_high - - platform: homeassistant - entity_id: sensor.hello_world - id: ha_hello_world - - platform: tuya - id: tuya_sensor - sensor_datapoint: 1 - - platform: pipsolar - pipsolar_id: inverter0 - grid_rating_voltage: - id: inverter0_grid_rating_voltage - name: inverter0_grid_rating_voltage - grid_rating_current: - id: inverter0_grid_rating_current - name: inverter0_grid_rating_current - ac_output_rating_voltage: - id: inverter0_ac_output_rating_voltage - name: inverter0_ac_output_rating_voltage - ac_output_rating_frequency: - id: inverter0_ac_output_rating_frequency - name: inverter0_ac_output_rating_frequency - ac_output_rating_current: - id: inverter0_ac_output_rating_current - name: inverter0_ac_output_rating_current - ac_output_rating_apparent_power: - id: inverter0_ac_output_rating_apparent_power - name: inverter0_ac_output_rating_apparent_power - ac_output_rating_active_power: - id: inverter0_ac_output_rating_active_power - name: inverter0_ac_output_rating_active_power - battery_rating_voltage: - id: inverter0_battery_rating_voltage - name: inverter0_battery_rating_voltage - battery_recharge_voltage: - id: inverter0_battery_recharge_voltage - name: inverter0_battery_recharge_voltage - battery_under_voltage: - id: inverter0_battery_under_voltage - name: inverter0_battery_under_voltage - battery_bulk_voltage: - id: inverter0_battery_bulk_voltage - name: inverter0_battery_bulk_voltage - battery_float_voltage: - id: inverter0_battery_float_voltage - name: inverter0_battery_float_voltage - battery_type: - id: inverter0_battery_type - name: inverter0_battery_type - current_max_ac_charging_current: - id: inverter0_current_max_ac_charging_current - name: inverter0_current_max_ac_charging_current - current_max_charging_current: - id: inverter0_current_max_charging_current - name: inverter0_current_max_charging_current - input_voltage_range: - id: inverter0_input_voltage_range - name: inverter0_input_voltage_range - output_source_priority: - id: inverter0_output_source_priority - name: inverter0_output_source_priority - charger_source_priority: - id: inverter0_charger_source_priority - name: inverter0_charger_source_priority - parallel_max_num: - id: inverter0_parallel_max_num - name: inverter0_parallel_max_num - machine_type: - id: inverter0_machine_type - name: inverter0_machine_type - topology: - id: inverter0_topology - name: inverter0_topology - output_mode: - id: inverter0_output_mode - name: inverter0_output_mode - battery_redischarge_voltage: - id: inverter0_battery_redischarge_voltage - name: inverter0_battery_redischarge_voltage - pv_ok_condition_for_parallel: - id: inverter0_pv_ok_condition_for_parallel - name: inverter0_pv_ok_condition_for_parallel - pv_power_balance: - id: inverter0_pv_power_balance - name: inverter0_pv_power_balance - grid_voltage: - id: inverter0_grid_voltage - name: inverter0_grid_voltage - grid_frequency: - id: inverter0_grid_frequency - name: inverter0_grid_frequency - ac_output_voltage: - id: inverter0_ac_output_voltage - name: inverter0_ac_output_voltage - ac_output_frequency: - id: inverter0_ac_output_frequency - name: inverter0_ac_output_frequency - ac_output_apparent_power: - id: inverter0_ac_output_apparent_power - name: inverter0_ac_output_apparent_power - ac_output_active_power: - id: inverter0_ac_output_active_power - name: inverter0_ac_output_active_power - output_load_percent: - id: inverter0_output_load_percent - name: inverter0_output_load_percent - bus_voltage: - id: inverter0_bus_voltage - name: inverter0_bus_voltage - battery_voltage: - id: inverter0_battery_voltage - name: inverter0_battery_voltage - battery_charging_current: - id: inverter0_battery_charging_current - name: inverter0_battery_charging_current - battery_capacity_percent: - id: inverter0_battery_capacity_percent - name: inverter0_battery_capacity_percent - inverter_heat_sink_temperature: - id: inverter0_inverter_heat_sink_temperature - name: inverter0_inverter_heat_sink_temperature - pv_input_current_for_battery: - id: inverter0_pv_input_current_for_battery - name: inverter0_pv_input_current_for_battery - pv_input_voltage: - id: inverter0_pv_input_voltage - name: inverter0_pv_input_voltage - battery_voltage_scc: - id: inverter0_battery_voltage_scc - name: inverter0_battery_voltage_scc - battery_discharge_current: - id: inverter0_battery_discharge_current - name: inverter0_battery_discharge_current - battery_voltage_offset_for_fans_on: - id: inverter0_battery_voltage_offset_for_fans_on - name: inverter0_battery_voltage_offset_for_fans_on - eeprom_version: - id: inverter0_eeprom_version - name: inverter0_eeprom_version - pv_charging_power: - id: inverter0_pv_charging_power - name: inverter0_pv_charging_power - - platform: hrxl_maxsonar_wr - name: Rainwater Tank Level - uart_id: uart115200 - filters: - - sliding_window_moving_average: - window_size: 12 - send_every: 12 - - or: - - throttle: 20min - - delta: 0.02 - - platform: mcp3204 - name: MCP3204 Pin 1 - number: 1 - id: mcp_sensor - - platform: copy - source_id: mcp_sensor - name: MCP binary sensor copy - - platform: ufire_ec - id: ufire_ec_board - temperature: - name: Ufire Temperature - ec: - name: Ufire EC - temperature_compensation: 20.0 - temperature_coefficient: 0.019 - - platform: ufire_ise - id: ufire_ise_board - temperature: - name: Ufire Temperature - ph: - name: Ufire pH - - platform: a01nyub - id: a01nyub_sensor - name: "a01nyub Distance" - uart_id: uart9600 - state_topic: "esphome/sensor/a01nyub_sensor/state" - - platform: a02yyuw - id: a02yyuw_sensor - name: "a02yyuw Distance" - uart_id: uart_a02yyuw - state_topic: "esphome/sensor/a02yyuw_sensor/state" - -# -# platform sensor.apds9960 requires component apds9960 -# -# - platform: apds9960 -# type: proximity -# name: APDS9960 Proximity -# - platform: apds9960 -# type: clear -# name: APDS9960 Clear -# - platform: apds9960 -# type: red -# name: APDS9960 Red -# - platform: apds9960 -# type: green -# name: APDS9960 Green -# - platform: apds9960 -# type: blue -# name: APDS9960 Blue - -binary_sensor: - - platform: tuya - id: tuya_binary_sensor - sensor_datapoint: 1 - - platform: pipsolar - pipsolar_id: inverter0 - add_sbu_priority_version: - id: inverter0_add_sbu_priority_version - name: inverter0_add_sbu_priority_version - configuration_status: - id: inverter0_configuration_status - name: inverter0_configuration_status - scc_firmware_version: - id: inverter0_scc_firmware_version - name: inverter0_scc_firmware_version - load_status: - id: inverter0_load_status - name: inverter0_load_status - battery_voltage_to_steady_while_charging: - id: inverter0_battery_voltage_to_steady_while_charging - name: inverter0_battery_voltage_to_steady_while_charging - charging_status: - id: inverter0_charging_status - name: inverter0_charging_status - scc_charging_status: - id: inverter0_scc_charging_status - name: inverter0_scc_charging_status - ac_charging_status: - id: inverter0_ac_charging_status - name: inverter0_ac_charging_status - charging_to_floating_mode: - id: inverter0_charging_to_floating_mode - name: inverter0_charging_to_floating_mode - switch_on: - id: inverter0_switch_on - name: inverter0_switch_on - dustproof_installed: - id: inverter0_dustproof_installed - name: inverter0_dustproof_installed - silence_buzzer_open_buzzer: - id: inverter0_silence_buzzer_open_buzzer - name: inverter0_silence_buzzer_open_buzzer - overload_bypass_function: - id: inverter0_overload_bypass_function - name: inverter0_overload_bypass_function - lcd_escape_to_default: - id: inverter0_lcd_escape_to_default - name: inverter0_lcd_escape_to_default - overload_restart_function: - id: inverter0_overload_restart_function - name: inverter0_overload_restart_function - over_temperature_restart_function: - id: inverter0_over_temperature_restart_function - name: inverter0_over_temperature_restart_function - backlight_on: - id: inverter0_backlight_on - name: inverter0_backlight_on - - platform: template - id: ar1 - lambda: "return {};" - filters: - - autorepeat: - - delay: 2s - time_off: 100ms - time_on: 900ms - - delay: 4s - time_off: 100ms - time_on: 400ms - on_state: - then: - - lambda: 'ESP_LOGI("ar1:", "%d", x);' - - platform: touchscreen - touchscreen_id: xpt_touchscreen - id: touch_key0 - x_min: 80 - x_max: 160 - y_min: 106 - y_max: 212 - on_press: - - logger.log: Touched - - - platform: gpio - name: GPIO SX1509 test - pin: - sx1509: sx1509_hub - number: 3 - - - platform: touchscreen - touchscreen_id: lilygo_touchscreen - id: touch_key1 - x_min: 0 - x_max: 100 - y_min: 0 - y_max: 100 - on_press: - - logger.log: Touched - - platform: gt911 - id: touch_key_911 - index: 0 - - - platform: gpio - name: MaxIn Pin 4 - pin: - max6956: max6956_1 - number: 4 - - mode: - input: true - pullup: true - inverted: false - - - platform: gpio - name: XL9535 Pin 0 - pin: - xl9535: xl9535_hub - number: 0 - mode: - input: true - inverted: false - - - platform: gpio - name: XL9535 Pin 17 - pin: - xl9535: xl9535_hub - number: 17 - mode: - input: true - inverted: false - -climate: - - platform: tuya - id: tuya_climate - switch_datapoint: 1 - target_temperature_datapoint: 3 - current_temperature_multiplier: 0.5 - target_temperature_multiplier: 0.5 - reports_fahrenheit: true - -switch: - - platform: tuya - id: tuya_switch - switch_datapoint: 1 - - platform: pipsolar - pipsolar_id: inverter0 - output_source_priority_utility: - name: inverter0_output_source_priority_utility - output_source_priority_solar: - name: inverter0_output_source_priority_solar - output_source_priority_battery: - name: inverter0_output_source_priority_battery - input_voltage_range: - name: inverter0_input_voltage_range - pv_ok_condition_for_parallel: - name: inverter0_pv_ok_condition_for_parallel - pv_power_balance: - name: inverter0_pv_power_balance - - platform: copy - source_id: tuya_switch - name: Tuya Switch Copy - -light: - - platform: fastled_clockless - id: led_matrix_32x8 - name: led_matrix_32x8 - chipset: WS2812B - pin: - allow_other_uses: true - number: GPIO15 - num_leds: 256 - rgb_order: GRB - default_transition_length: 0s - color_correct: [50%, 50%, 50%] - - platform: tuya - id: tuya_light - switch_datapoint: 1 - dimmer_datapoint: 2 - min_value_datapoint: 3 - color_temperature_datapoint: 4 - min_value: 1 - max_value: 100 - cold_white_color_temperature: 153 mireds - warm_white_color_temperature: 500 mireds - gamma_correct: 1 - -cover: - - platform: tuya - id: tuya_cover - position_datapoint: 2 - - platform: copy - source_id: tuya_cover - name: Tuya Cover copy - - platform: he60r - uart_id: uart_he60r - id: garage_door - name: Garage Door - open_duration: 14s - close_duration: 14s - -display: - - platform: addressable_light - id: led_matrix_32x8_display - addressable_light_id: led_matrix_32x8 - width: 32 - height: 8 - pixel_mapper: |- - if (x % 2 == 0) { - return (x * 8) + y; - } - return (x * 8) + (7 - y); - lambda: |- - Color red = Color(0xFF0000); - Color green = Color(0x00FF00); - Color blue = Color(0x0000FF); - it.rectangle(0, 0, it.get_width(), it.get_height(), red); - it.rectangle(1, 1, it.get_width()-2, it.get_height()-2, green); - it.rectangle(2, 2, it.get_width()-4, it.get_height()-4, blue); - it.rectangle(3, 3, it.get_width()-6, it.get_height()-6, red); - auto touch = id(ft63_touchscreen)->get_touch(); - if (touch) { ESP_LOGD("touch", "%d/%d", touch.value().x, touch.value().y); } - rotation: 0° - update_interval: 16ms - - - platform: inkplate6 - id: inkplate_display - greyscale: false - partial_updating: false - update_interval: 60s - display_data_1_pin: - number: GPIO5 - allow_other_uses: true - display_data_2_pin: - number: GPIO18 - allow_other_uses: true - display_data_3_pin: - number: GPIO19 - allow_other_uses: true - display_data_5_pin: - number: GPIO25 - allow_other_uses: true - display_data_4_pin: - number: GPIO23 - allow_other_uses: true - display_data_6_pin: - number: GPIO26 - allow_other_uses: true - display_data_7_pin: - number: GPIO27 - allow_other_uses: true - ckv_pin: - number: GPIO1 - allow_other_uses: true - sph_pin: - number: GPIO1 - allow_other_uses: true - gmod_pin: - number: GPIO1 - allow_other_uses: true - gpio0_enable_pin: - number: GPIO1 - allow_other_uses: true - oe_pin: - number: GPIO1 - allow_other_uses: true - spv_pin: - number: GPIO1 - allow_other_uses: true - powerup_pin: - number: GPIO1 - allow_other_uses: true - wakeup_pin: - number: GPIO1 - allow_other_uses: true - vcom_pin: - number: GPIO1 - allow_other_uses: true - -number: - - platform: tuya - id: tuya_number - number_datapoint: 102 - min_value: 0 - max_value: 17 - step: 1 - - platform: copy - source_id: tuya_number - name: Tuya Number Copy - -text_sensor: - - platform: pylontech - pylontech_id: pylontech0 - battery: 1 - base_state: - id: pyl0_base_state - voltage_state: - id: pyl0_voltage_state - current_state: - id: pyl0_current_state - temperature_state: - id: pyl0_temperature_state - - platform: pipsolar - pipsolar_id: inverter0 - device_mode: - id: inverter0_device_mode - name: inverter0_device_mode - last_qpigs: - id: inverter0_last_qpigs - name: inverter0_last_qpigs - last_qpiri: - id: inverter0_last_qpiri - name: inverter0_last_qpiri - last_qmod: - id: inverter0_last_qmod - name: inverter0_last_qmod - last_qflag: - id: inverter0_last_qflag - name: inverter0_last_qflag - - platform: copy - source_id: inverter0_device_mode - name: Inverter Text Sensor Copy - - platform: ethernet_info - ip_address: - name: IP Address - -output: - - platform: pipsolar - pipsolar_id: inverter0 - battery_recharge_voltage: - id: inverter0_battery_recharge_voltage_out - - platform: dac7678 - dac7678_id: dac7678_hub1 - channel: 0 - id: dac7678_1_ch0 - - platform: dac7678 - dac7678_id: dac7678_hub1 - channel: 1 - id: dac7678_1_ch1 - - platform: dac7678 - dac7678_id: dac7678_hub1 - channel: 2 - id: dac7678_1_ch2 - - platform: dac7678 - dac7678_id: dac7678_hub1 - channel: 3 - id: dac7678_1_ch3 - - platform: dac7678 - dac7678_id: dac7678_hub1 - channel: 4 - id: dac7678_1_ch4 - - platform: dac7678 - dac7678_id: dac7678_hub1 - channel: 5 - id: dac7678_1_ch5 - - platform: dac7678 - dac7678_id: dac7678_hub1 - channel: 6 - id: dac7678_1_ch6 - - platform: dac7678 - dac7678_id: dac7678_hub1 - channel: 7 - id: dac7678_1_ch7 -esp32_camera: - name: ESP-32 Camera - data_pins: - - number: GPIO17 - allow_other_uses: true - - number: GPIO35 - allow_other_uses: true - - number: GPIO34 - - number: GPIO5 - allow_other_uses: true - - number: GPIO39 - allow_other_uses: true - - number: GPIO18 - allow_other_uses: true - - number: GPIO36 - allow_other_uses: true - - number: GPIO19 - allow_other_uses: true - vsync_pin: - allow_other_uses: true - number: GPIO22 - href_pin: - allow_other_uses: true - number: GPIO26 - pixel_clock_pin: - allow_other_uses: true - number: GPIO21 - external_clock: - pin: - allow_other_uses: true - number: GPIO27 - frequency: 20MHz - i2c_pins: - sda: - allow_other_uses: true - number: GPIO25 - scl: - allow_other_uses: true - number: GPIO23 - reset_pin: - allow_other_uses: true - number: GPIO15 - power_down_pin: - allow_other_uses: true - number: GPIO1 - resolution: 640x480 - jpeg_quality: 10 - on_image: - then: - - lambda: |- - ESP_LOGD("main", "image len=%d, data=%c", image.length, image.data[0]); - -esp32_camera_web_server: - - port: 8080 - mode: stream - - port: 8081 - mode: snapshot - -external_components: - - source: github://esphome/esphome@dev - refresh: 1d - components: [bh1750] - - source: ../esphome/components - components: [sntp] - -button: - - platform: restart - name: Restart Button - - platform: safe_mode - name: Safe Mode Button - - platform: shutdown - name: Shutdown Button - id: shutdown_btn - - platform: copy - source_id: shutdown_btn - name: Shutdown Button Copy - -touchscreen: - - platform: ektf2232 - interrupt_pin: - allow_other_uses: true - number: GPIO36 - rts_pin: - allow_other_uses: true - number: GPIO5 - display: inkplate_display - on_touch: - - logger.log: - format: Touch at (%d, %d) - args: [touch.x, touch.y] - - - platform: xpt2046 - id: xpt_touchscreen - spi_id: spi_id_2 - cs_pin: - allow_other_uses: true - number: GPIO17 - interrupt_pin: - number: GPIO16 - display: inkplate_display - update_interval: 50ms - threshold: 400 - calibration: - x_min: 3860 - x_max: 280 - y_min: 340 - y_max: 3860 - on_touch: - - logger.log: - format: Touch at (%d, %d) - args: [touch.x, touch.y] - - - platform: lilygo_t5_47 - id: lilygo_touchscreen - interrupt_pin: - allow_other_uses: true - number: GPIO36 - display: inkplate_display - on_touch: - - logger.log: - format: Touch at (%d, %d) - args: [touch.x, touch.y] - - platform: gt911 - interrupt_pin: - number: GPIO3 - display: inkplate_display - - - platform: ft63x6 - id: ft63_touchscreen - interrupt_pin: - allow_other_uses: true - number: GPIO39 - reset_pin: - allow_other_uses: true - number: GPIO5 - display: inkplate_display - on_touch: - - logger.log: - format: Touch at (%d, %d) - args: [touch.x, touch.y] - -i2s_audio: - i2s_lrclk_pin: - allow_other_uses: true - number: GPIO26 - i2s_bclk_pin: - allow_other_uses: true - number: GPIO27 - i2s_mclk_pin: - allow_other_uses: true - number: GPIO25 - -media_player: - - platform: i2s_audio - name: None - dac_type: external - i2s_dout_pin: - allow_other_uses: true - number: GPIO25 - mute_pin: - number: GPIO14 - on_state: - - media_player.play: - - media_player.play_media: http://localhost/media.mp3 - - media_player.play_media: !lambda 'return "http://localhost/media.mp3";' - on_idle: - - media_player.pause: - on_play: - - media_player.stop: - on_pause: - - media_player.toggle: - - wait_until: - media_player.is_idle: - - wait_until: - media_player.is_playing: - - media_player.volume_up: - - media_player.volume_down: - - media_player.volume_set: 50% - -prometheus: - include_internal: true - relabel: - ha_hello_world: - id: hellow_world - name: Hello World - -microphone: - - platform: i2s_audio - id: mic_id_adc - adc_pin: - allow_other_uses: true - number: GPIO35 - adc_type: internal - - - platform: i2s_audio - id: mic_id_external - i2s_din_pin: - allow_other_uses: true - number: GPIO23 - adc_type: external - pdm: false - -speaker: - - platform: i2s_audio - id: speaker_id - dac_type: external - i2s_dout_pin: - allow_other_uses: true - number: GPIO25 - mode: mono - -voice_assistant: - microphone: mic_id_external - speaker: speaker_id - on_listening: - - logger.log: "Voice assistant microphone listening" - on_start: - - logger.log: "Voice assistant started" - on_stt_end: - - logger.log: - format: "Voice assistant STT ended with result %s" - args: [x.c_str()] - on_tts_start: - - logger.log: - format: "Voice assistant TTS started with text %s" - args: [x.c_str()] - on_tts_end: - - logger.log: - format: "Voice assistant TTS ended with url %s" - args: [x.c_str()] - on_end: - - logger.log: "Voice assistant ended" - on_error: - - logger.log: - format: "Voice assistant error - code %s, message: %s" - args: [code.c_str(), message.c_str()] - -max6956: - - id: max6956_1 - address: 0x40 - -xl9535: - - id: xl9535_hub - address: 0x20 diff --git a/tests/test5.yaml b/tests/test5.yaml deleted file mode 100644 index f7a34d5a1b..0000000000 --- a/tests/test5.yaml +++ /dev/null @@ -1,747 +0,0 @@ ---- -esphome: - name: test5 - build_path: build/test5 - project: - name: esphome.test5_project - version: "1.0.0" - -esp32: - board: nodemcu-32s - framework: - type: esp-idf - advanced: - ignore_efuse_mac_crc: true - -wifi: - networks: - - ssid: "MySSID" - password: "password1" - manual_ip: - static_ip: 192.168.1.23 - gateway: 192.168.1.1 - subnet: 255.255.255.0 - -network: - enable_ipv6: true - -api: - -ota: - - platform: esphome - -logger: - -debug: - -psram: - -uart: - - id: uart_1 - tx_pin: 1 - rx_pin: 3 - baud_rate: 9600 - - id: uart_2 - tx_pin: - allow_other_uses: true - number: 17 - inverted: true - rx_pin: - allow_other_uses: true - number: 16 - baud_rate: 19200 - -i2c: - sda: - allow_other_uses: true - number: 21 - scl: - number: 22 - frequency: 100khz - -modbus: - uart_id: uart_1 - flow_control_pin: - allow_other_uses: true - number: 5 - id: mod_bus1 - -modbus_controller: - - id: modbus_controller_test - address: 0x2 - modbus_id: mod_bus1 - -mqtt: - broker: test.mosquitto.org - port: 1883 - discovery: true - discovery_prefix: homeassistant - idf_send_async: false - log_topic: - on_message: - topic: testing/sensor/testing_sensor/state - qos: 0 - then: - # yamllint disable rule:line-length - - lambda: |- - ESP_LOGD("Mqtt Test", "testing/sensor/testing_sensor/state=[%s]", x.c_str()); - # yamllint enable rule:line-length - -vbus: - - uart_id: uart_2 - -binary_sensor: - - platform: gpio - pin: GPIO0 - id: io0_button - icon: mdi:gesture-tap-button - - - platform: modbus_controller - modbus_controller_id: modbus_controller_test - id: modbus_binsensortest - register_type: read - address: 0x3200 - bitmask: 0x80 # (bit 8) - lambda: "return x;" - - - platform: tm1638 - id: Button0 - key: 0 - filters: - - delayed_on: 10ms - on_press: - then: - - switch.turn_on: Led0 - on_release: - then: - - switch.turn_off: Led0 - - - platform: tm1638 - id: Button1 - key: 1 - on_press: - then: - - switch.turn_on: Led1 - on_release: - then: - - switch.turn_off: Led1 - - - platform: tm1638 - id: Button2 - key: 2 - on_press: - then: - - switch.turn_on: Led2 - on_release: - then: - - switch.turn_off: Led2 - - - platform: tm1638 - id: Button3 - key: 3 - on_press: - then: - - switch.turn_on: Led3 - on_release: - then: - - switch.turn_off: Led3 - - - platform: tm1638 - id: Button4 - key: 4 - on_press: - then: - - output.turn_on: Led4 - on_release: - then: - - output.turn_off: Led4 - - - platform: tm1638 - id: Button5 - key: 5 - on_press: - then: - - output.turn_on: Led5 - on_release: - then: - - output.turn_off: Led5 - - - platform: tm1638 - id: Button6 - key: 6 - on_press: - then: - - output.turn_on: Led6 - on_release: - then: - - output.turn_off: Led6 - - - platform: tm1638 - id: Button7 - key: 7 - on_press: - then: - - output.turn_on: Led7 - on_release: - then: - - output.turn_off: Led7 - - - platform: gpio - id: sn74hc165_pin_0 - pin: - sn74hc165: sn74hc165_hub - number: 0 - - - platform: ezo_pmp - pump_state: - name: "Pump State" - is_paused: - name: "Is Paused" - - - platform: matrix_keypad - keypad_id: keypad - id: key4 - row: 1 - col: 1 - - platform: matrix_keypad - id: key1 - key: 1 - - - platform: vbus - model: deltasol_bs_plus - relay2: - name: Relay 2 On - sensor1_error: - name: Sensor 1 Error - - - platform: vbus - model: custom - command: 0x100 - source: 0x1234 - dest: 0x10 - binary_sensors: - - id: vcustom_b - name: VBus Custom Binary Sensor - lambda: return x[0] & 1; - -tlc5947: - data_pin: - number: GPIO12 - allow_other_uses: true - clock_pin: - allow_other_uses: true - number: GPIO14 - lat_pin: - allow_other_uses: true - number: GPIO15 - -gp8403: - - id: gp8403_5v - voltage: 5V - - id: gp8403_10v - voltage: 10V - -output: - - platform: gpio - pin: GPIO2 - id: built_in_led - - - platform: tlc5947 - id: output_red - channel: 0 - max_power: 0.8 - - - platform: mcp47a1 - id: output_mcp47a1 - - - platform: modbus_controller - modbus_controller_id: modbus_controller_test - id: modbus_output_test - lambda: |- - return x * 1.0 ; - address: 0x9001 - value_type: U_WORD - - - platform: tm1638 - id: Led4 - led: 4 - - - platform: tm1638 - id: Led5 - led: 5 - - - platform: tm1638 - id: Led6 - led: 6 - - - platform: tm1638 - id: Led7 - led: 7 - - - platform: gp8403 - id: gp8403_output_0 - gp8403_id: gp8403_5v - channel: 0 - - platform: gp8403 - gp8403_id: gp8403_10v - id: gp8403_output_1 - channel: 1 - -demo: - -esp32_ble: - -esp32_ble_server: - manufacturer: ESPHome - model: Test5 - -esp32_improv: - authorizer: io0_button - authorized_duration: 1min - status_indicator: built_in_led - -ezo_pmp: - id: hcl_pump - update_interval: 1s - -number: - - platform: template - name: My template number - id: template_number_id - optimistic: true - max_value: 100 - min_value: 0 - step: 5 - unit_of_measurement: "%" - mode: slider - device_class: humidity - on_value: - - logger.log: - format: Number changed to %f - args: [x] - set_action: - - logger.log: - format: Template Number set to %f - args: [x] - - number.set: - id: template_number_id - value: 50 - - number.to_min: template_number_id - - number.to_min: - id: template_number_id - - number.to_max: template_number_id - - number.to_max: - id: template_number_id - - number.increment: template_number_id - - number.increment: - id: template_number_id - cycle: false - - number.decrement: template_number_id - - number.decrement: - id: template_number_id - cycle: false - - number.operation: - id: template_number_id - operation: Increment - cycle: false - - number.operation: - id: template_number_id - operation: !lambda "return NUMBER_OP_INCREMENT;" - cycle: !lambda "return false;" - - - id: modbus_numbertest - platform: modbus_controller - modbus_controller_id: modbus_controller_test - name: ModbusNumber - address: 0x9002 - value_type: U_WORD - lambda: "return x * 1.0;" - write_lambda: |- - return x * 1.0 ; - multiply: 1.0 - -select: - - platform: template - name: My template select - id: template_select_id - optimistic: true - initial_option: two - restore_value: true - on_value: - - logger.log: - format: Select changed to %s (index %d)" - args: ["x.c_str()", "i"] - set_action: - - logger.log: - format: Template Select set to %s - args: ["x.c_str()"] - - select.set: - id: template_select_id - option: two - - select.first: template_select_id - - select.last: - id: template_select_id - - select.previous: template_select_id - - select.next: - id: template_select_id - cycle: false - - select.operation: - id: template_select_id - operation: Previous - cycle: false - - select.operation: - id: template_select_id - operation: !lambda "return SELECT_OP_PREVIOUS;" - cycle: !lambda "return true;" - - select.set_index: - id: template_select_id - index: 1 - - select.set_index: - id: template_select_id - index: !lambda "return 1 + 1;" - options: - - one - - two - - three - - - platform: modbus_controller - name: Modbus Select Register 1000 - address: 1000 - value_type: U_WORD - optionsmap: - "Zero": 0 - "One": 1 - "Two": 2 - "Three": 3 - -sensor: - - platform: adc - id: adc_sensor_p32 - name: ADC pin 32 - pin: 32 - attenuation: 11db - update_interval: 1s - - platform: internal_temperature - name: Internal Temperature - state_topic: - - platform: selec_meter - total_active_energy: - name: SelecEM2M Total Active Energy - import_active_energy: - name: SelecEM2M Import Active Energy - export_active_energy: - name: SelecEM2M Export Active Energy - total_reactive_energy: - name: SelecEM2M Total Reactive Energy - import_reactive_energy: - name: SelecEM2M Import Reactive Energy - export_reactive_energy: - name: SelecEM2M Export Reactive Energy - apparent_energy: - name: SelecEM2M Apparent Energy - active_power: - name: SelecEM2M Active Power - reactive_power: - name: SelecEM2M Reactive Power - apparent_power: - name: SelecEM2M Apparent Power - voltage: - name: SelecEM2M Voltage - current: - name: SelecEM2M Current - power_factor: - name: SelecEM2M Power Factor - frequency: - name: SelecEM2M Frequency - maximum_demand_active_power: - name: SelecEM2M Maximum Demand Active Power - disabled_by_default: true - maximum_demand_reactive_power: - name: SelecEM2M Maximum Demand Reactive Power - disabled_by_default: true - maximum_demand_apparent_power: - name: SelecEM2M Maximum Demand Apparent Power - disabled_by_default: true - - - id: modbus_sensortest - platform: modbus_controller - modbus_controller_id: modbus_controller_test - address: 0x331A - register_type: read - value_type: U_WORD - - - platform: t6615 - uart_id: uart_2 - co2: - name: CO2 Sensor - - - platform: ms8607 - temperature: - name: Temperature - humidity: - name: Humidity - pressure: - name: Pressure - - platform: ms8607 - id: ms8607_more_config - temperature: - name: Indoor Temperature - accuracy_decimals: 1 - pressure: - name: Indoor Pressure - internal: true - humidity: - name: Indoor Humidity - address: 0x41 - i2c_id: - i2c_id: - address: 0x77 - update_interval: 10min - - - platform: sen5x - id: sen54 - 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 - algorithm_tuning: - index_offset: 100 - learning_time_offset_hours: 12 - learning_time_gain_hours: 12 - gating_max_duration_minutes: 180 - std_initial: 50 - gain_factor: 230 - temperature_compensation: - offset: 0 - normalized_offset_slope: 0 - time_constant: 0 - auto_cleaning_interval: 604800s - acceleration_mode: low - store_baseline: true - address: 0x69 - - platform: mcp9600 - thermocouple_type: K - hot_junction: - name: Thermocouple Temperature - cold_junction: - name: Ambient Temperature - - - platform: ezo_pmp - current_volume_dosed: - name: Current Volume Dosed - total_volume_dosed: - name: Total Volume Dosed - absolute_total_volume_dosed: - name: Absolute Total Volume Dosed - pump_voltage: - name: Pump Voltage - last_volume_requested: - name: Last Volume Requested - max_flow_rate: - name: Max Flow Rate - - - platform: vbus - model: deltasol c - temperature_3: - name: Temperature 3 - operating_hours_1: - name: Operating Hours 1 - heat_quantity: - name: Heat Quantity - time: - name: System Time - - - platform: debug - free: - name: "Heap Free" - block: - name: "Heap Max Block" - loop_time: - name: "Loop Time" - psram: - name: "PSRAM Free" - - - platform: vbus - model: custom - command: 0x100 - source: 0x1234 - dest: 0x10 - sensors: - - id: vcustom - name: VBus Custom Sensor - lambda: return x[0] / 10.0; - - - platform: kuntze - ph: - name: Kuntze pH - temperature: - name: Kuntze temperature - -script: - - id: automation_test - then: - - repeat: - count: 5 - then: - - logger.log: looping! - - - id: zero_repeat_test - then: - - repeat: - count: !lambda "return 0;" - then: - - logger.log: shouldn't see mee! - -switch: - - platform: modbus_controller - modbus_controller_id: modbus_controller_test - id: modbus_switch_test - register_type: coil - address: 2 - bitmask: 1 - - - platform: tm1638 - id: Led0 - led: 0 - name: TM1638Led0 - - - platform: tm1638 - id: Led1 - led: 1 - name: TM1638Led1 - - - platform: tm1638 - id: Led2 - led: 2 - name: TM1638Led2 - - - platform: tm1638 - id: Led3 - led: 3 - name: TM1638Led3 - -display: - - platform: tm1638 - id: primarydisplay - stb_pin: - allow_other_uses: true - number: 5 # TM1638 STB - clk_pin: 18 # TM1638 CLK - dio_pin: 23 # TM1638 DIO - update_interval: 5s - intensity: 5 - lambda: |- - it.print("81818181"); - -time: - - platform: pcf85063 - - platform: pcf8563 - -text_sensor: - - platform: ezo_pmp - dosing_mode: - name: Dosing Mode - calibration_status: - name: Calibration Status - on_value: - - ezo_pmp.dose_volume: - id: hcl_pump - volume: 10 - - ezo_pmp.dose_volume_over_time: - id: hcl_pump - volume: 10 - duration: 2 - - ezo_pmp.dose_with_constant_flow_rate: - id: hcl_pump - volume_per_minute: 10 - duration: 2 - - ezo_pmp.set_calibration_volume: - id: hcl_pump - volume: 10 - - ezo_pmp.find: hcl_pump - - ezo_pmp.dose_continuously: hcl_pump - - ezo_pmp.clear_total_volume_dosed: hcl_pump - - ezo_pmp.clear_calibration: hcl_pump - - ezo_pmp.pause_dosing: hcl_pump - - ezo_pmp.stop_dosing: hcl_pump - - ezo_pmp.arbitrary_command: - id: hcl_pump - command: D,? - -sn74hc165: - id: sn74hc165_hub - data_pin: - allow_other_uses: true - number: GPIO12 - clock_pin: - allow_other_uses: true - number: GPIO14 - load_pin: GPIO27 - clock_inhibit_pin: GPIO26 - sr_count: 4 - -matrix_keypad: - id: keypad - rows: - - pin: - allow_other_uses: true - number: 21 - - pin: 19 - columns: - - pin: - allow_other_uses: true - number: 17 - - pin: - allow_other_uses: true - number: 16 - keys: "1234" - has_pulldowns: true - -key_collector: - - id: reader - source_id: keypad - min_length: 4 - max_length: 4 - -light: - - platform: esp32_rmt_led_strip - id: led_strip - pin: 13 - num_leds: 60 - rmt_channel: 6 - rgb_order: GRB - chipset: ws2812 - - platform: esp32_rmt_led_strip - id: led_strip2 - pin: - allow_other_uses: true - number: 15 - num_leds: 60 - rmt_channel: 2 - rgb_order: RGB - bit0_high: 100us - bit0_low: 100us - bit1_high: 100us - bit1_low: 100us diff --git a/tests/test6.yaml b/tests/test6.yaml deleted file mode 100644 index b1103eb126..0000000000 --- a/tests/test6.yaml +++ /dev/null @@ -1,77 +0,0 @@ ---- -esphome: - name: test6 - project: - name: esphome.test6_project - version: "1.0.0" - -rp2040: - board: rpipicow - framework: - # Waiting for https://github.com/platformio/platform-raspberrypi/pull/36 - platform_version: https://github.com/maxgerhardt/platform-raspberrypi.git - -wifi: - networks: - - ssid: "MySSID" - password: "password1" - -network: - enable_ipv6: true - -api: - -ota: - - platform: esphome - -logger: - -debug: - -binary_sensor: - - platform: gpio - pin: GPIO5 - id: pin_5_button - -output: - - platform: gpio - pin: GPIO4 - id: pin_4 - -switch: - - platform: output - output: pin_4 - id: pin_4_switch - -spi: # Pins are for SPI1 on the RP2040 Pico-W - miso_pin: 8 - clk_pin: 10 - mosi_pin: 11 - id: spi_0 - interface: hardware - -# light: -# - platform: rp2040_pio_led_strip -# id: led_strip -# pin: GPIO13 -# num_leds: 60 -# pio: 0 -# rgb_order: GRB -# chipset: WS2812 -# - platform: rp2040_pio_led_strip -# id: led_strip_custom_timings -# pin: GPIO13 -# num_leds: 60 -# pio: 1 -# rgb_order: GRB -# bit0_high: .1us -# bit0_low: 1.2us -# bit1_high: .69us -# bit1_low: .4us - -sensor: - - platform: internal_temperature - name: Internal Temperature - - platform: adc - pin: VCC - name: VSYS diff --git a/tests/test7.yaml b/tests/test7.yaml deleted file mode 100644 index ac193eae4e..0000000000 --- a/tests/test7.yaml +++ /dev/null @@ -1,27 +0,0 @@ -# Tests for ESP32-C3 boards which use toolchain-riscv32-esp ---- -wifi: - ssid: "ssid" - -network: - enable_ipv6: true - -esp32: - board: lolin_c3_mini - framework: - type: arduino - -esphome: - name: test7 - -logger: - -debug: - -sensor: - - platform: adc - id: adc_sensor_p4 - name: ADC pin 4 - pin: 4 - attenuation: 11db - update_interval: 1s diff --git a/tests/test8.1.yaml b/tests/test8.1.yaml deleted file mode 100644 index ab3d0d44aa..0000000000 --- a/tests/test8.1.yaml +++ /dev/null @@ -1,78 +0,0 @@ -# Tests for ESP32-S3 boards - IDf ---- -wifi: - ssid: "ssid" - -network: - enable_ipv6: true - -esp32: - board: esp32s3box - variant: ESP32S3 - framework: - type: esp-idf - -esphome: - name: esp32-s3-test - -logger: - -debug: - -psram: - -spi: - - id: spi_id_1 - type: single - clk_pin: - number: GPIO7 - allow_other_uses: false - mosi_pin: GPIO6 - interface: hardware -spi_device: - id: spidev - data_rate: 2MHz - spi_id: spi_id_1 - mode: 3 - bit_order: lsb_first - -display: - - platform: ili9xxx - id: displ8 - model: ili9342 - cs_pin: GPIO5 - dc_pin: GPIO4 - reset_pin: - number: GPIO48 - allow_other_uses: true - -i2c: - scl: GPIO18 - sda: GPIO8 - -touchscreen: - - platform: tt21100 - display: displ8 - interrupt_pin: - number: GPIO3 - ignore_strapping_warning: true - allow_other_uses: false - reset_pin: - number: GPIO48 - allow_other_uses: true - -binary_sensor: - - platform: tt21100 - name: Home Button - index: 1 - -sensor: - - platform: debug - free: - name: "Heap Free" - block: - name: "Max Block Free" - loop_time: - name: "Loop Time" - psram: - name: "PSRAM Free" diff --git a/tests/test8.2.yaml b/tests/test8.2.yaml deleted file mode 100644 index ae892559e5..0000000000 --- a/tests/test8.2.yaml +++ /dev/null @@ -1,75 +0,0 @@ -# Tests for ESP32-C3 boards - IDf ---- -wifi: - ssid: "ssid" - -network: - enable_ipv6: true - -esp32: - board: lolin_c3_mini - variant: ESP32C3 - framework: - type: esp-idf - -esphome: - name: esp32-c3-test - -logger: - -debug: - -psram: - -spi: - - id: spi_id_1 - clk_pin: - number: GPIO7 - allow_other_uses: false - mosi_pin: GPIO6 - interface: any - -spi_device: - id: spidev - data_rate: 2MHz - spi_id: spi_id_1 - mode: 3 - bit_order: lsb_first - -display: - - platform: ili9xxx - id: displ8 - model: ili9342 - cs_pin: GPIO5 - dc_pin: GPIO4 - reset_pin: - number: GPIO21 - -i2c: - scl: GPIO18 - sda: GPIO8 - -touchscreen: - - platform: tt21100 - display: displ8 - interrupt_pin: - number: GPIO3 - allow_other_uses: false - reset_pin: - number: GPIO20 - -binary_sensor: - - platform: tt21100 - name: Home Button - index: 1 - -sensor: - - platform: debug - free: - name: "Heap Free" - block: - name: "Max Block Free" - loop_time: - name: "Loop Time" - psram: - name: "PSRAM Free" diff --git a/tests/test8.yaml b/tests/test8.yaml deleted file mode 100644 index fcc93c6154..0000000000 --- a/tests/test8.yaml +++ /dev/null @@ -1,125 +0,0 @@ -# Tests for ESP32-S3 boards ---- -wifi: - ssid: "ssid" - -network: - enable_ipv6: true - -esp32: - board: esp32s3box - variant: ESP32S3 - framework: - type: arduino - -esphome: - name: esp32-s3-test - -logger: - -debug: - -psram: - -light: - - platform: neopixelbus - type: GRB - variant: WS2812 - pin: GPIO38 - num_leds: 1 - id: neopixel - method: esp32_rmt - name: neopixel-enable - internal: false - restore_mode: ALWAYS_OFF - - platform: spi_led_strip - num_leds: 4 - color_correct: [80%, 60%, 100%] - id: rgb_led - name: "RGB LED" - data_rate: 8MHz - - platform: binary - name: "Red Info Light" - output: board_info_ed - entity_category: diagnostic - restore_mode: ALWAYS_OFF - -spi: - id: spi_id_1 - clk_pin: GPIO7 - mosi_pin: GPIO6 - interface: any - -spi_device: - id: spidev - data_rate: 2MHz - spi_id: spi_id_1 - mode: 3 - bit_order: lsb_first - -font: - - file: "gfonts://Roboto" - id: roboto - size: 20 - -display: - - platform: ili9xxx - id: displ8 - model: ili9342 - cs_pin: GPIO5 - dc_pin: GPIO4 - reset_pin: - number: GPIO48 - allow_other_uses: true - lambda: |- - it.printf(10, 100, id(roboto), Color(0x123456), COLOR_OFF, display::TextAlign::BASELINE, "%f", id(heap_free).state); - -i2c: - scl: GPIO18 - sda: GPIO8 - -output: - - platform: gpio - id: board_info_ed - pin: - # This pin is reserved on the ESP32S3! - number: 26 - ignore_pin_validation_error: true - -touchscreen: - - platform: tt21100 - display: displ8 - interrupt_pin: - number: GPIO3 - ignore_strapping_warning: true - allow_other_uses: false - reset_pin: - number: GPIO48 - allow_other_uses: true - -binary_sensor: - - platform: tt21100 - name: Home Button - index: 1 - -sensor: - - platform: debug - free: - id: heap_free - name: "Heap Free" - block: - name: "Max Block Free" - loop_time: - name: "Loop Time" - psram: - name: "PSRAM Free" - -# Purposely test that `animation:` does auto-load `image:` -# Keep the `image:` undefined. -# image: - -animation: - - id: rgb565_animation - file: pnglogo.png - type: RGB565 - use_transparency: false diff --git a/tests/test9.1.yaml b/tests/test9.1.yaml deleted file mode 100644 index 2d205ef4e6..0000000000 --- a/tests/test9.1.yaml +++ /dev/null @@ -1,29 +0,0 @@ -# Tests for rtl87xx boards using LibreTiny ---- -wifi: - ssid: "ssid" - -rtl87xx: - board: generic-rtl8710bn-2mb-788k - -esphome: - name: rtl87xx-test - -logger: - -ota: - - platform: esphome - -captive_portal: - -binary_sensor: - - platform: gpio - name: Home Button - pin: GPIO11 - -sensor: - - platform: adc - id: adc_sensor - name: ADC - pin: PA19 - update_interval: 1s diff --git a/tests/test9.yaml b/tests/test9.yaml deleted file mode 100644 index 5017ccc5ed..0000000000 --- a/tests/test9.yaml +++ /dev/null @@ -1,35 +0,0 @@ -# Tests for bk7xx boards using LibreTiny ---- -wifi: - ssid: "ssid" - -bk72xx: - board: cb2s - -esphome: - name: bk72xx-test - -logger: - -ota: - - platform: esphome - -captive_portal: - -binary_sensor: - - platform: gpio - name: Home Button - pin: GPIO24 - -sensor: - - platform: adc - id: adc_sensor - name: ADC - pin: GPIO23 - update_interval: 1s - -mqtt: - broker: test.mosquitto.org - port: 1883 - discovery: true - discovery_prefix: homeassistant From dc4a93f5d0ec268bc1a0de28ac2f9d4c7b96aa6d Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 27 Jun 2024 17:15:02 +1200 Subject: [PATCH 1696/2101] Revert "[CI] Update tests to run against IDF 5.1" (#7003) --- ...f-51.yaml => build_components_base.esp32-c3-idf-50.yaml} | 6 +++--- ...-idf-51.yaml => build_components_base.esp32-idf-50.yaml} | 6 +++--- ...f-51.yaml => build_components_base.esp32-s2-idf-50.yaml} | 6 +++--- ...f-51.yaml => build_components_base.esp32-s3-idf-50.yaml} | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) rename tests/test_build_components/{build_components_base.esp32-c3-idf-51.yaml => build_components_base.esp32-c3-idf-50.yaml} (76%) rename tests/test_build_components/{build_components_base.esp32-idf-51.yaml => build_components_base.esp32-idf-50.yaml} (77%) rename tests/test_build_components/{build_components_base.esp32-s2-idf-51.yaml => build_components_base.esp32-s2-idf-50.yaml} (78%) rename tests/test_build_components/{build_components_base.esp32-s3-idf-51.yaml => build_components_base.esp32-s3-idf-50.yaml} (77%) diff --git a/tests/test_build_components/build_components_base.esp32-c3-idf-51.yaml b/tests/test_build_components/build_components_base.esp32-c3-idf-50.yaml similarity index 76% rename from tests/test_build_components/build_components_base.esp32-c3-idf-51.yaml rename to tests/test_build_components/build_components_base.esp32-c3-idf-50.yaml index 73d2c8fa19..08d4d8679c 100644 --- a/tests/test_build_components/build_components_base.esp32-c3-idf-51.yaml +++ b/tests/test_build_components/build_components_base.esp32-c3-idf-50.yaml @@ -1,13 +1,13 @@ esphome: - name: componenttestesp32c3idf51 + name: componenttestesp32c3idf50 friendly_name: $component_name esp32: board: lolin_c3_mini framework: type: esp-idf - version: 5.1.2 - platform_version: 6.6.0 + version: 5.0.2 + platform_version: 6.3.2 logger: level: VERY_VERBOSE diff --git a/tests/test_build_components/build_components_base.esp32-idf-51.yaml b/tests/test_build_components/build_components_base.esp32-idf-50.yaml similarity index 77% rename from tests/test_build_components/build_components_base.esp32-idf-51.yaml rename to tests/test_build_components/build_components_base.esp32-idf-50.yaml index 6c8eb3c193..c9f2c1e943 100644 --- a/tests/test_build_components/build_components_base.esp32-idf-51.yaml +++ b/tests/test_build_components/build_components_base.esp32-idf-50.yaml @@ -1,13 +1,13 @@ esphome: - name: componenttestesp32idf51 + name: componenttestesp32idf50 friendly_name: $component_name esp32: board: nodemcu-32s framework: type: esp-idf - version: 5.1.2 - platform_version: 6.6.0 + version: 5.0.2 + platform_version: 6.3.2 logger: level: VERY_VERBOSE diff --git a/tests/test_build_components/build_components_base.esp32-s2-idf-51.yaml b/tests/test_build_components/build_components_base.esp32-s2-idf-50.yaml similarity index 78% rename from tests/test_build_components/build_components_base.esp32-s2-idf-51.yaml rename to tests/test_build_components/build_components_base.esp32-s2-idf-50.yaml index 8894efb6b8..351f5fb019 100644 --- a/tests/test_build_components/build_components_base.esp32-s2-idf-51.yaml +++ b/tests/test_build_components/build_components_base.esp32-s2-idf-50.yaml @@ -1,5 +1,5 @@ esphome: - name: componenttestesp32s2idf51 + name: componenttestesp32s2idf50 friendly_name: $component_name esp32: @@ -7,8 +7,8 @@ esp32: variant: ESP32S2 framework: type: esp-idf - version: 5.1.2 - platform_version: 6.6.0 + version: 5.0.2 + platform_version: 6.3.2 logger: level: VERY_VERBOSE diff --git a/tests/test_build_components/build_components_base.esp32-s3-idf-51.yaml b/tests/test_build_components/build_components_base.esp32-s3-idf-50.yaml similarity index 77% rename from tests/test_build_components/build_components_base.esp32-s3-idf-51.yaml rename to tests/test_build_components/build_components_base.esp32-s3-idf-50.yaml index efeffa5a0f..c05378903f 100644 --- a/tests/test_build_components/build_components_base.esp32-s3-idf-51.yaml +++ b/tests/test_build_components/build_components_base.esp32-s3-idf-50.yaml @@ -1,5 +1,5 @@ esphome: - name: componenttestesp32s3idf51 + name: componenttestesp32s3idf50 friendly_name: $component_name esp32: @@ -7,8 +7,8 @@ esp32: variant: ESP32S3 framework: type: esp-idf - version: 5.1.2 - platform_version: 6.6.0 + version: 5.0.2 + platform_version: 6.3.2 logger: level: VERY_VERBOSE From 0e50cac39930770cb9321a06a03403ff938206fd Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Wed, 26 Jun 2024 20:07:07 -0500 Subject: [PATCH 1697/2101] [ota-esphome] Merge configurations by port (#7001) --- esphome/components/esphome/ota/__init__.py | 65 +++++++++++++++++++--- 1 file changed, 58 insertions(+), 7 deletions(-) diff --git a/esphome/components/esphome/ota/__init__.py b/esphome/components/esphome/ota/__init__.py index 88e729f230..a852d8d001 100644 --- a/esphome/components/esphome/ota/__init__.py +++ b/esphome/components/esphome/ota/__init__.py @@ -1,7 +1,10 @@ +import logging + import esphome.codegen as cg import esphome.config_validation as cv import esphome.final_validate as fv from esphome.components.ota import BASE_OTA_SCHEMA, ota_to_code, OTAComponent +from esphome.config_helpers import merge_config from esphome.const import ( CONF_ESPHOME, CONF_ID, @@ -16,6 +19,8 @@ from esphome.const import ( ) from esphome.core import coroutine_with_priority +_LOGGER = logging.getLogger(__name__) + CODEOWNERS = ["@esphome/core"] AUTO_LOAD = ["md5", "socket"] @@ -26,16 +31,62 @@ ESPHomeOTAComponent = esphome.class_("ESPHomeOTAComponent", OTAComponent) def ota_esphome_final_validate(config): - fconf = fv.full_config.get()[CONF_OTA] - used_ports = [] - for ota_conf in fconf: + full_conf = fv.full_config.get() + full_ota_conf = full_conf[CONF_OTA] + new_ota_conf = [] + merged_ota_esphome_configs_by_port = {} + ports_with_merged_configs = [] + for ota_conf in full_ota_conf: if ota_conf.get(CONF_PLATFORM) == CONF_ESPHOME: - if (plat_port := ota_conf.get(CONF_PORT)) not in used_ports: - used_ports.append(plat_port) + if ( + conf_port := ota_conf.get(CONF_PORT) + ) not in merged_ota_esphome_configs_by_port: + merged_ota_esphome_configs_by_port[conf_port] = ota_conf else: - raise cv.Invalid( - f"Only one instance of the {CONF_ESPHOME} {CONF_OTA} {CONF_PLATFORM} is allowed per port. Note that this error may result from OTA specified in packages" + if merged_ota_esphome_configs_by_port[conf_port][ + CONF_VERSION + ] != ota_conf.get(CONF_VERSION): + raise cv.Invalid( + f"Found multiple configurations but {CONF_VERSION} is inconsistent" + ) + if ( + merged_ota_esphome_configs_by_port[conf_port][CONF_ID].is_manual + and ota_conf.get(CONF_ID).is_manual + ): + raise cv.Invalid( + f"Found multiple configurations but {CONF_ID} is inconsistent" + ) + if ( + CONF_PASSWORD in merged_ota_esphome_configs_by_port[conf_port] + and CONF_PASSWORD in ota_conf + and merged_ota_esphome_configs_by_port[conf_port][CONF_PASSWORD] + != ota_conf.get(CONF_PASSWORD) + ): + raise cv.Invalid( + f"Found multiple configurations but {CONF_PASSWORD} is inconsistent" + ) + + ports_with_merged_configs.append(conf_port) + merged_ota_esphome_configs_by_port[conf_port] = merge_config( + merged_ota_esphome_configs_by_port[conf_port], ota_conf ) + else: + new_ota_conf.append(ota_conf) + + for port_conf in merged_ota_esphome_configs_by_port.values(): + new_ota_conf.append(port_conf) + + full_conf[CONF_OTA] = new_ota_conf + fv.full_config.set(full_conf) + + if len(ports_with_merged_configs) > 0: + _LOGGER.warning( + "Found and merged multiple configurations for %s %s %s port(s) %s", + CONF_OTA, + CONF_PLATFORM, + CONF_ESPHOME, + ports_with_merged_configs, + ) CONFIG_SCHEMA = ( From 3a48b1075700bbc1e7a46b9bfda062b1a4400f2d Mon Sep 17 00:00:00 2001 From: Markus <974709+Links2004@users.noreply.github.com> Date: Thu, 27 Jun 2024 03:48:01 +0200 Subject: [PATCH 1698/2101] Fix LEDC 100% is not 100% duty with ESP32 IDF (#6997) --- esphome/components/ledc/ledc_output.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/esphome/components/ledc/ledc_output.cpp b/esphome/components/ledc/ledc_output.cpp index 1040ac25b6..90e11fe4ad 100644 --- a/esphome/components/ledc/ledc_output.cpp +++ b/esphome/components/ledc/ledc_output.cpp @@ -115,12 +115,15 @@ 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(duty_rounded); - #ifdef USE_ARDUINO ESP_LOGV(TAG, "Setting duty: %u on channel %u", duty, this->channel_); ledcWrite(this->channel_, duty); #endif #ifdef USE_ESP_IDF + // ensure that 100% on is not 99.975% on + if ((duty == max_duty) && (max_duty != 1)) { + duty = max_duty + 1; + } auto speed_mode = get_speed_mode(channel_); auto chan_num = static_cast(channel_ % 8); int hpoint = ledc_angle_to_htop(this->phase_angle_, this->bit_depth_); From 7904d3b157280387295d57e1dc9f60b253836b56 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 27 Jun 2024 17:19:13 +1200 Subject: [PATCH 1699/2101] Bump version to 2024.6.4 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 2434609191..b26d8d2851 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.6.3" +__version__ = "2024.6.4" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From d0ab2a16a6774d0acf8efe5d475049d9439752ac Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Sat, 29 Jun 2024 14:12:59 +1200 Subject: [PATCH 1700/2101] [mpr121] await register parented (#7014) fixes https://github.com/esphome/issues/issues/5913 --- esphome/components/mpr121/binary_sensor/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/mpr121/binary_sensor/__init__.py b/esphome/components/mpr121/binary_sensor/__init__.py index 292c631c37..dfae92a9af 100644 --- a/esphome/components/mpr121/binary_sensor/__init__.py +++ b/esphome/components/mpr121/binary_sensor/__init__.py @@ -27,7 +27,7 @@ async def to_code(config): var = await binary_sensor.new_binary_sensor(config) hub = await cg.get_variable(config[CONF_MPR121_ID]) cg.add(var.set_channel(config[CONF_CHANNEL])) - cg.register_parented(var, hub) + await cg.register_parented(var, hub) if CONF_TOUCH_THRESHOLD in config: cg.add(var.set_touch_threshold(config[CONF_TOUCH_THRESHOLD])) From e9cf3623d1e2238b7f92fa8f9eaf6bdd788ad3e1 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 1 Jul 2024 08:54:04 +1200 Subject: [PATCH 1701/2101] Bump dockerfile dependencies (#7017) --- docker/Dockerfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index fcb5a5e7ae..eabd118939 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -34,7 +34,7 @@ RUN \ python3-wheel=0.38.4-2 \ iputils-ping=3:20221126-1 \ git=1:2.39.2-1.1 \ - curl=7.88.1-10+deb12u5 \ + curl=7.88.1-10+deb12u6 \ openssh-client=1:9.2p1-2+deb12u2 \ python3-cffi=1.15.1-5 \ libcairo2=1.16.0-7 \ @@ -190,8 +190,8 @@ RUN \ clang-format-13=1:13.0.1-11+b2 \ clang-tidy-14=1:14.0.6-12 \ patch=2.7.6-7 \ - software-properties-common=0.99.30-4 \ - nano=7.2-1 \ + software-properties-common=0.99.30-4.1~deb12u1 \ + nano=7.2-1+deb12u1 \ build-essential=12.9 \ python3-dev=3.11.2-1+b1 \ && rm -rf \ From 6294c3b913d1f36b92f3c3845c4101644343e95e Mon Sep 17 00:00:00 2001 From: orland0m Date: Sun, 30 Jun 2024 16:06:59 -0700 Subject: [PATCH 1702/2101] Enable devcontainer linters (#7019) --- .devcontainer/devcontainer.json | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 4596b59200..8d9565ad5f 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,7 +1,9 @@ { "name": "ESPHome Dev", "image": "ghcr.io/esphome/esphome-lint:dev", - "postCreateCommand": ["script/devcontainer-post-create"], + "postCreateCommand": [ + "script/devcontainer-post-create" + ], "containerEnv": { "DEVCONTAINER": "1", "PIP_BREAK_SYSTEM_PACKAGES": "1", @@ -27,6 +29,9 @@ "extensions": [ // python "ms-python.python", + "ms-python.pylint", + "ms-python.flake8", + "ms-python.black-formatter", "visualstudioexptteam.vscodeintellicode", // yaml "redhat.vscode-yaml", @@ -38,9 +43,21 @@ "settings": { "python.languageServer": "Pylance", "python.pythonPath": "/usr/bin/python3", - "python.linting.pylintEnabled": true, - "python.linting.enabled": true, - "python.formatting.provider": "black", + "pylint.args": [ + "--rcfile=${workspaceFolder}/pyproject.toml" + ], + "flake8.args": [ + "--config=${workspaceFolder}/.flake8" + ], + "black-formatter.args": [ + "--config", + "${workspaceFolder}/pyproject.toml" + ], + "[python]": { + // VS will say "Value is not accepted" before building the devcontainer, but the warning + // should go away after build is completed. + "editor.defaultFormatter": "ms-python.black-formatter" + }, "editor.formatOnPaste": false, "editor.formatOnSave": true, "editor.formatOnType": true, From 715184070d92ac437db85d37c64c30c135725b53 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 1 Jul 2024 11:17:44 +1200 Subject: [PATCH 1703/2101] [docker] Bump versions inside armv7 block (#7022) --- docker/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index eabd118939..b0c800f167 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -46,8 +46,8 @@ RUN \ python3-dev=3.11.2-1+b1 \ zlib1g-dev=1:1.2.13.dfsg-1 \ libjpeg-dev=1:2.1.5-2 \ - libfreetype-dev=2.12.1+dfsg-5 \ - libssl-dev=3.0.11-1~deb12u2 \ + libfreetype-dev=2.12.1+dfsg-5+deb12u3 \ + libssl-dev=3.0.13-1~deb12u1 \ libffi-dev=3.4.4-1 \ libopenjp2-7=2.5.0-2 \ libtiff6=4.5.0-6+deb12u1 \ From b89dea97d9bfbe81f0eb639544e4e186b67c8378 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 1 Jul 2024 11:51:51 +1200 Subject: [PATCH 1704/2101] [docker] Fix docker build error fall through (#7021) --- docker/Dockerfile | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index b0c800f167..16f37274c6 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -39,23 +39,27 @@ RUN \ python3-cffi=1.15.1-5 \ libcairo2=1.16.0-7 \ libmagic1=1:5.44-3 \ - patch=2.7.6-7; \ - if [ "$TARGETARCH$TARGETVARIANT" = "armv7" ]; then \ - apt-get install -y --no-install-recommends \ - build-essential=12.9 \ - python3-dev=3.11.2-1+b1 \ - zlib1g-dev=1:1.2.13.dfsg-1 \ - libjpeg-dev=1:2.1.5-2 \ - libfreetype-dev=2.12.1+dfsg-5+deb12u3 \ - libssl-dev=3.0.13-1~deb12u1 \ - libffi-dev=3.4.4-1 \ - libopenjp2-7=2.5.0-2 \ - libtiff6=4.5.0-6+deb12u1 \ - cargo=0.66.0+ds1-1 \ - pkg-config=1.8.1-1 \ - gcc-arm-linux-gnueabihf=4:12.2.0-3; \ - fi; \ - rm -rf \ + patch=2.7.6-7 \ + && ( \ + ( \ + [ "$TARGETARCH$TARGETVARIANT" = "armv7" ] && \ + apt-get install -y --no-install-recommends \ + build-essential=12.9 \ + python3-dev=3.11.2-1+b1 \ + zlib1g-dev=1:1.2.13.dfsg-1 \ + libjpeg-dev=1:2.1.5-2 \ + libfreetype-dev=2.12.1+dfsg-5+deb12u3 \ + libssl-dev=3.0.13-1~deb12u1 \ + libffi-dev=3.4.4-1 \ + libopenjp2-7=2.5.0-2 \ + libtiff6=4.5.0-6+deb12u1 \ + cargo=0.66.0+ds1-1 \ + pkg-config=1.8.1-1 \ + gcc-arm-linux-gnueabihf=4:12.2.0-3 \ + ) \ + || [ "$TARGETARCH$TARGETVARIANT" != "armv7" ] \ + ) \ + && rm -rf \ /tmp/* \ /var/{cache,log}/* \ /var/lib/apt/lists/* From 5278ae4b5e620cd6983f2371759c18099878e1fe Mon Sep 17 00:00:00 2001 From: "Kevin P. Fleming" Date: Sun, 30 Jun 2024 19:52:05 -0400 Subject: [PATCH 1705/2101] 'uart' and 'improv_serial' need to understand non-UART logger configurations (#6998) --- .../improv_serial/improv_serial_component.cpp | 16 +++++----- .../uart/uart_component_esp32_arduino.cpp | 22 +++++++++++--- .../uart/uart_component_esp_idf.cpp | 24 +++++++++++++-- .../{common.yaml => common-default_uart.yaml} | 0 tests/components/logger/common-usb_cdc.yaml | 8 +++++ .../logger/common-usb_serial_jtag.yaml | 8 +++++ .../logger/test-usb_cdc.esp32-c3-ard.yaml | 1 + .../logger/test-usb_cdc.esp32-s2-ard.yaml | 1 + .../logger/test-usb_cdc.esp32-s2-idf.yaml | 1 + .../logger/test-usb_cdc.esp32-s3-ard.yaml | 1 + .../test-usb_serial_jtag.esp32-c3-idf.yaml | 1 + .../test-usb_serial_jtag.esp32-s3-idf.yaml | 1 + tests/components/logger/test.esp32-ard.yaml | 2 +- .../components/logger/test.esp32-c3-ard.yaml | 2 +- .../components/logger/test.esp32-c3-idf.yaml | 2 +- tests/components/logger/test.esp32-idf.yaml | 2 +- tests/components/logger/test.esp8266-ard.yaml | 2 +- tests/components/logger/test.rp2040-ard.yaml | 2 +- ...st-uart_max_with_usb_cdc.esp32-c3-ard.yaml | 30 +++++++++++++++++++ ...st-uart_max_with_usb_cdc.esp32-s2-ard.yaml | 30 +++++++++++++++++++ ...st-uart_max_with_usb_cdc.esp32-s2-idf.yaml | 30 +++++++++++++++++++ ...st-uart_max_with_usb_cdc.esp32-s3-ard.yaml | 30 +++++++++++++++++++ ...max_with_usb_serial_jtag.esp32-c3-idf.yaml | 30 +++++++++++++++++++ ...max_with_usb_serial_jtag.esp32-s3-idf.yaml | 30 +++++++++++++++++++ 24 files changed, 256 insertions(+), 20 deletions(-) rename tests/components/logger/{common.yaml => common-default_uart.yaml} (100%) create mode 100644 tests/components/logger/common-usb_cdc.yaml create mode 100644 tests/components/logger/common-usb_serial_jtag.yaml create mode 100644 tests/components/logger/test-usb_cdc.esp32-c3-ard.yaml create mode 100644 tests/components/logger/test-usb_cdc.esp32-s2-ard.yaml create mode 100644 tests/components/logger/test-usb_cdc.esp32-s2-idf.yaml create mode 100644 tests/components/logger/test-usb_cdc.esp32-s3-ard.yaml create mode 100644 tests/components/logger/test-usb_serial_jtag.esp32-c3-idf.yaml create mode 100644 tests/components/logger/test-usb_serial_jtag.esp32-s3-idf.yaml create mode 100644 tests/components/uart/test-uart_max_with_usb_cdc.esp32-c3-ard.yaml create mode 100644 tests/components/uart/test-uart_max_with_usb_cdc.esp32-s2-ard.yaml create mode 100644 tests/components/uart/test-uart_max_with_usb_cdc.esp32-s2-idf.yaml create mode 100644 tests/components/uart/test-uart_max_with_usb_cdc.esp32-s3-ard.yaml create mode 100644 tests/components/uart/test-uart_max_with_usb_serial_jtag.esp32-c3-idf.yaml create mode 100644 tests/components/uart/test-uart_max_with_usb_serial_jtag.esp32-s3-idf.yaml diff --git a/esphome/components/improv_serial/improv_serial_component.cpp b/esphome/components/improv_serial/improv_serial_component.cpp index 2937720496..02ffa9f31c 100644 --- a/esphome/components/improv_serial/improv_serial_component.cpp +++ b/esphome/components/improv_serial/improv_serial_component.cpp @@ -57,7 +57,7 @@ optional ImprovSerialComponent::read_byte_() { } } break; -#if defined(CONFIG_ESP_CONSOLE_USB_CDC) && (defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3)) +#ifdef USE_LOGGER_USB_CDC case logger::UART_SELECTION_USB_CDC: #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) if (esp_usb_console_available_for_read()) { @@ -68,15 +68,15 @@ optional ImprovSerialComponent::read_byte_() { byte = data; } break; -#endif // USE_ESP32_VARIANT_ESP32S2 || USE_ESP32_VARIANT_ESP32S3 -#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S3) +#endif // USE_LOGGER_USB_CDC +#ifdef USE_LOGGER_USB_SERIAL_JTAG case logger::UART_SELECTION_USB_SERIAL_JTAG: { if (usb_serial_jtag_read_bytes((char *) &data, 1, 0)) { byte = data; } break; } -#endif // USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C6 || USE_ESP32_VARIANT_ESP32S3 +#endif // USE_LOGGER_USB_SERIAL_JTAG default: break; } @@ -99,19 +99,19 @@ void ImprovSerialComponent::write_data_(std::vector &data) { #endif // !USE_ESP32_VARIANT_ESP32C3 && !USE_ESP32_VARIANT_ESP32S2 && !USE_ESP32_VARIANT_ESP32S3 uart_write_bytes(this->uart_num_, data.data(), data.size()); break; -#if defined(CONFIG_ESP_CONSOLE_USB_CDC) && (defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3)) +#ifdef USE_LOGGER_USB_CDC case logger::UART_SELECTION_USB_CDC: { const char *msg = (char *) data.data(); esp_usb_console_write_buf(msg, data.size()); break; } -#endif // USE_ESP32_VARIANT_ESP32S2 || USE_ESP32_VARIANT_ESP32S3 -#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S3) +#endif // USE_LOGGER_USB_CDC +#ifdef USE_LOGGER_USB_SERIAL_JTAG case logger::UART_SELECTION_USB_SERIAL_JTAG: usb_serial_jtag_write_bytes((char *) data.data(), data.size(), 20 / portTICK_PERIOD_MS); usb_serial_jtag_ll_txfifo_flush(); // fixes for issue in IDF 4.4.7 break; -#endif // USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32S3 +#endif // USE_LOGGER_USB_SERIAL_JTAG default: break; } diff --git a/esphome/components/uart/uart_component_esp32_arduino.cpp b/esphome/components/uart/uart_component_esp32_arduino.cpp index f77783e20e..793c1d52f4 100644 --- a/esphome/components/uart/uart_component_esp32_arduino.cpp +++ b/esphome/components/uart/uart_component_esp32_arduino.cpp @@ -96,10 +96,24 @@ void ESP32ArduinoUARTComponent::setup() { next_uart_num++; } else { #ifdef USE_LOGGER - // The logger doesn't use this UART component, instead it targets the UARTs - // directly (i.e. Serial/Serial0, Serial1, and Serial2). If the logger is - // enabled, skip the UART that it is configured to use. - if (logger::global_logger->get_baud_rate() > 0 && logger::global_logger->get_uart() == next_uart_num) { + bool logger_uses_hardware_uart = true; + +#ifdef USE_LOGGER_USB_CDC + if (logger::global_logger->get_uart() == logger::UART_SELECTION_USB_CDC) { + // this is not a hardware UART, ignore it + logger_uses_hardware_uart = false; + } +#endif // USE_LOGGER_USB_CDC + +#ifdef USE_LOGGER_USB_SERIAL_JTAG + if (logger::global_logger->get_uart() == logger::UART_SELECTION_USB_SERIAL_JTAG) { + // this is not a hardware UART, ignore it + logger_uses_hardware_uart = false; + } +#endif // USE_LOGGER_USB_SERIAL_JTAG + + if (logger_uses_hardware_uart && logger::global_logger->get_baud_rate() > 0 && + logger::global_logger->get_uart() == next_uart_num) { next_uart_num++; } #endif // USE_LOGGER diff --git a/esphome/components/uart/uart_component_esp_idf.cpp b/esphome/components/uart/uart_component_esp_idf.cpp index c66753b0c4..6999dfb619 100644 --- a/esphome/components/uart/uart_component_esp_idf.cpp +++ b/esphome/components/uart/uart_component_esp_idf.cpp @@ -60,10 +60,30 @@ uart_config_t IDFUARTComponent::get_config_() { void IDFUARTComponent::setup() { static uint8_t next_uart_num = 0; + #ifdef USE_LOGGER - if (logger::global_logger->get_uart_num() == next_uart_num) + bool logger_uses_hardware_uart = true; + +#ifdef USE_LOGGER_USB_CDC + if (logger::global_logger->get_uart() == logger::UART_SELECTION_USB_CDC) { + // this is not a hardware UART, ignore it + logger_uses_hardware_uart = false; + } +#endif // USE_LOGGER_USB_CDC + +#ifdef USE_LOGGER_USB_SERIAL_JTAG + if (logger::global_logger->get_uart() == logger::UART_SELECTION_USB_SERIAL_JTAG) { + // this is not a hardware UART, ignore it + logger_uses_hardware_uart = false; + } +#endif // USE_LOGGER_USB_SERIAL_JTAG + + if (logger_uses_hardware_uart && logger::global_logger->get_baud_rate() > 0 && + logger::global_logger->get_uart_num() == next_uart_num) { next_uart_num++; -#endif + } +#endif // USE_LOGGER + if (next_uart_num >= UART_NUM_MAX) { ESP_LOGW(TAG, "Maximum number of UART components created already."); this->mark_failed(); diff --git a/tests/components/logger/common.yaml b/tests/components/logger/common-default_uart.yaml similarity index 100% rename from tests/components/logger/common.yaml rename to tests/components/logger/common-default_uart.yaml diff --git a/tests/components/logger/common-usb_cdc.yaml b/tests/components/logger/common-usb_cdc.yaml new file mode 100644 index 0000000000..4df320527d --- /dev/null +++ b/tests/components/logger/common-usb_cdc.yaml @@ -0,0 +1,8 @@ +esphome: + on_boot: + then: + - logger.log: Hello world + +logger: + level: DEBUG + hardware_uart: USB_CDC diff --git a/tests/components/logger/common-usb_serial_jtag.yaml b/tests/components/logger/common-usb_serial_jtag.yaml new file mode 100644 index 0000000000..5891c9ea40 --- /dev/null +++ b/tests/components/logger/common-usb_serial_jtag.yaml @@ -0,0 +1,8 @@ +esphome: + on_boot: + then: + - logger.log: Hello world + +logger: + level: DEBUG + hardware_uart: USB_SERIAL_JTAG diff --git a/tests/components/logger/test-usb_cdc.esp32-c3-ard.yaml b/tests/components/logger/test-usb_cdc.esp32-c3-ard.yaml new file mode 100644 index 0000000000..cfdaec9771 --- /dev/null +++ b/tests/components/logger/test-usb_cdc.esp32-c3-ard.yaml @@ -0,0 +1 @@ +<<: !include common-usb_cdc.yaml diff --git a/tests/components/logger/test-usb_cdc.esp32-s2-ard.yaml b/tests/components/logger/test-usb_cdc.esp32-s2-ard.yaml new file mode 100644 index 0000000000..cfdaec9771 --- /dev/null +++ b/tests/components/logger/test-usb_cdc.esp32-s2-ard.yaml @@ -0,0 +1 @@ +<<: !include common-usb_cdc.yaml diff --git a/tests/components/logger/test-usb_cdc.esp32-s2-idf.yaml b/tests/components/logger/test-usb_cdc.esp32-s2-idf.yaml new file mode 100644 index 0000000000..cfdaec9771 --- /dev/null +++ b/tests/components/logger/test-usb_cdc.esp32-s2-idf.yaml @@ -0,0 +1 @@ +<<: !include common-usb_cdc.yaml diff --git a/tests/components/logger/test-usb_cdc.esp32-s3-ard.yaml b/tests/components/logger/test-usb_cdc.esp32-s3-ard.yaml new file mode 100644 index 0000000000..cfdaec9771 --- /dev/null +++ b/tests/components/logger/test-usb_cdc.esp32-s3-ard.yaml @@ -0,0 +1 @@ +<<: !include common-usb_cdc.yaml diff --git a/tests/components/logger/test-usb_serial_jtag.esp32-c3-idf.yaml b/tests/components/logger/test-usb_serial_jtag.esp32-c3-idf.yaml new file mode 100644 index 0000000000..46a927ff10 --- /dev/null +++ b/tests/components/logger/test-usb_serial_jtag.esp32-c3-idf.yaml @@ -0,0 +1 @@ +<<: !include common-usb_serial_jtag.yaml diff --git a/tests/components/logger/test-usb_serial_jtag.esp32-s3-idf.yaml b/tests/components/logger/test-usb_serial_jtag.esp32-s3-idf.yaml new file mode 100644 index 0000000000..46a927ff10 --- /dev/null +++ b/tests/components/logger/test-usb_serial_jtag.esp32-s3-idf.yaml @@ -0,0 +1 @@ +<<: !include common-usb_serial_jtag.yaml diff --git a/tests/components/logger/test.esp32-ard.yaml b/tests/components/logger/test.esp32-ard.yaml index dade44d145..3fe04e18a3 100644 --- a/tests/components/logger/test.esp32-ard.yaml +++ b/tests/components/logger/test.esp32-ard.yaml @@ -1 +1 @@ -<<: !include common.yaml +<<: !include common-default_uart.yaml diff --git a/tests/components/logger/test.esp32-c3-ard.yaml b/tests/components/logger/test.esp32-c3-ard.yaml index dade44d145..3fe04e18a3 100644 --- a/tests/components/logger/test.esp32-c3-ard.yaml +++ b/tests/components/logger/test.esp32-c3-ard.yaml @@ -1 +1 @@ -<<: !include common.yaml +<<: !include common-default_uart.yaml diff --git a/tests/components/logger/test.esp32-c3-idf.yaml b/tests/components/logger/test.esp32-c3-idf.yaml index dade44d145..3fe04e18a3 100644 --- a/tests/components/logger/test.esp32-c3-idf.yaml +++ b/tests/components/logger/test.esp32-c3-idf.yaml @@ -1 +1 @@ -<<: !include common.yaml +<<: !include common-default_uart.yaml diff --git a/tests/components/logger/test.esp32-idf.yaml b/tests/components/logger/test.esp32-idf.yaml index dade44d145..3fe04e18a3 100644 --- a/tests/components/logger/test.esp32-idf.yaml +++ b/tests/components/logger/test.esp32-idf.yaml @@ -1 +1 @@ -<<: !include common.yaml +<<: !include common-default_uart.yaml diff --git a/tests/components/logger/test.esp8266-ard.yaml b/tests/components/logger/test.esp8266-ard.yaml index dade44d145..3fe04e18a3 100644 --- a/tests/components/logger/test.esp8266-ard.yaml +++ b/tests/components/logger/test.esp8266-ard.yaml @@ -1 +1 @@ -<<: !include common.yaml +<<: !include common-default_uart.yaml diff --git a/tests/components/logger/test.rp2040-ard.yaml b/tests/components/logger/test.rp2040-ard.yaml index dade44d145..3fe04e18a3 100644 --- a/tests/components/logger/test.rp2040-ard.yaml +++ b/tests/components/logger/test.rp2040-ard.yaml @@ -1 +1 @@ -<<: !include common.yaml +<<: !include common-default_uart.yaml diff --git a/tests/components/uart/test-uart_max_with_usb_cdc.esp32-c3-ard.yaml b/tests/components/uart/test-uart_max_with_usb_cdc.esp32-c3-ard.yaml new file mode 100644 index 0000000000..2a73826c51 --- /dev/null +++ b/tests/components/uart/test-uart_max_with_usb_cdc.esp32-c3-ard.yaml @@ -0,0 +1,30 @@ +<<: !include ../logger/common-usb_cdc.yaml + +esphome: + on_boot: + then: + - uart.write: + id: uart_1 + data: 'Hello World' + - uart.write: + id: uart_1 + data: [0x00, 0x20, 0x42] + +uart: + - id: uart_1 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + data_bits: 8 + rx_buffer_size: 512 + parity: EVEN + stop_bits: 2 + + - id: uart_2 + tx_pin: 6 + rx_pin: 7 + baud_rate: 9600 + data_bits: 8 + rx_buffer_size: 512 + parity: EVEN + stop_bits: 2 diff --git a/tests/components/uart/test-uart_max_with_usb_cdc.esp32-s2-ard.yaml b/tests/components/uart/test-uart_max_with_usb_cdc.esp32-s2-ard.yaml new file mode 100644 index 0000000000..2a73826c51 --- /dev/null +++ b/tests/components/uart/test-uart_max_with_usb_cdc.esp32-s2-ard.yaml @@ -0,0 +1,30 @@ +<<: !include ../logger/common-usb_cdc.yaml + +esphome: + on_boot: + then: + - uart.write: + id: uart_1 + data: 'Hello World' + - uart.write: + id: uart_1 + data: [0x00, 0x20, 0x42] + +uart: + - id: uart_1 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + data_bits: 8 + rx_buffer_size: 512 + parity: EVEN + stop_bits: 2 + + - id: uart_2 + tx_pin: 6 + rx_pin: 7 + baud_rate: 9600 + data_bits: 8 + rx_buffer_size: 512 + parity: EVEN + stop_bits: 2 diff --git a/tests/components/uart/test-uart_max_with_usb_cdc.esp32-s2-idf.yaml b/tests/components/uart/test-uart_max_with_usb_cdc.esp32-s2-idf.yaml new file mode 100644 index 0000000000..2a73826c51 --- /dev/null +++ b/tests/components/uart/test-uart_max_with_usb_cdc.esp32-s2-idf.yaml @@ -0,0 +1,30 @@ +<<: !include ../logger/common-usb_cdc.yaml + +esphome: + on_boot: + then: + - uart.write: + id: uart_1 + data: 'Hello World' + - uart.write: + id: uart_1 + data: [0x00, 0x20, 0x42] + +uart: + - id: uart_1 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + data_bits: 8 + rx_buffer_size: 512 + parity: EVEN + stop_bits: 2 + + - id: uart_2 + tx_pin: 6 + rx_pin: 7 + baud_rate: 9600 + data_bits: 8 + rx_buffer_size: 512 + parity: EVEN + stop_bits: 2 diff --git a/tests/components/uart/test-uart_max_with_usb_cdc.esp32-s3-ard.yaml b/tests/components/uart/test-uart_max_with_usb_cdc.esp32-s3-ard.yaml new file mode 100644 index 0000000000..2a73826c51 --- /dev/null +++ b/tests/components/uart/test-uart_max_with_usb_cdc.esp32-s3-ard.yaml @@ -0,0 +1,30 @@ +<<: !include ../logger/common-usb_cdc.yaml + +esphome: + on_boot: + then: + - uart.write: + id: uart_1 + data: 'Hello World' + - uart.write: + id: uart_1 + data: [0x00, 0x20, 0x42] + +uart: + - id: uart_1 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + data_bits: 8 + rx_buffer_size: 512 + parity: EVEN + stop_bits: 2 + + - id: uart_2 + tx_pin: 6 + rx_pin: 7 + baud_rate: 9600 + data_bits: 8 + rx_buffer_size: 512 + parity: EVEN + stop_bits: 2 diff --git a/tests/components/uart/test-uart_max_with_usb_serial_jtag.esp32-c3-idf.yaml b/tests/components/uart/test-uart_max_with_usb_serial_jtag.esp32-c3-idf.yaml new file mode 100644 index 0000000000..e0a07dde91 --- /dev/null +++ b/tests/components/uart/test-uart_max_with_usb_serial_jtag.esp32-c3-idf.yaml @@ -0,0 +1,30 @@ +<<: !include ../logger/common-usb_serial_jtag.yaml + +esphome: + on_boot: + then: + - uart.write: + id: uart_1 + data: 'Hello World' + - uart.write: + id: uart_1 + data: [0x00, 0x20, 0x42] + +uart: + - id: uart_1 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + data_bits: 8 + rx_buffer_size: 512 + parity: EVEN + stop_bits: 2 + + - id: uart_2 + tx_pin: 6 + rx_pin: 7 + baud_rate: 9600 + data_bits: 8 + rx_buffer_size: 512 + parity: EVEN + stop_bits: 2 diff --git a/tests/components/uart/test-uart_max_with_usb_serial_jtag.esp32-s3-idf.yaml b/tests/components/uart/test-uart_max_with_usb_serial_jtag.esp32-s3-idf.yaml new file mode 100644 index 0000000000..e0a07dde91 --- /dev/null +++ b/tests/components/uart/test-uart_max_with_usb_serial_jtag.esp32-s3-idf.yaml @@ -0,0 +1,30 @@ +<<: !include ../logger/common-usb_serial_jtag.yaml + +esphome: + on_boot: + then: + - uart.write: + id: uart_1 + data: 'Hello World' + - uart.write: + id: uart_1 + data: [0x00, 0x20, 0x42] + +uart: + - id: uart_1 + tx_pin: 4 + rx_pin: 5 + baud_rate: 9600 + data_bits: 8 + rx_buffer_size: 512 + parity: EVEN + stop_bits: 2 + + - id: uart_2 + tx_pin: 6 + rx_pin: 7 + baud_rate: 9600 + data_bits: 8 + rx_buffer_size: 512 + parity: EVEN + stop_bits: 2 From 7aaa5ce9c859426964bcca238418c4a75dd0017a Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Mon, 1 Jul 2024 01:20:59 -0500 Subject: [PATCH 1706/2101] Move some consts for #4585 (#7023) --- esphome/components/bme680_bsec/__init__.py | 3 +-- esphome/components/bme680_bsec/sensor.py | 12 ++++++------ esphome/components/bme680_bsec/text_sensor.py | 2 +- esphome/components/i2s_audio/microphone/__init__.py | 3 +-- esphome/const.py | 2 ++ 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/esphome/components/bme680_bsec/__init__.py b/esphome/components/bme680_bsec/__init__.py index 62ab50b8f7..743ef6e85d 100644 --- a/esphome/components/bme680_bsec/__init__.py +++ b/esphome/components/bme680_bsec/__init__.py @@ -1,7 +1,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import i2c, esp32 -from esphome.const import CONF_ID, CONF_TEMPERATURE_OFFSET +from esphome.const import CONF_ID, CONF_SAMPLE_RATE, CONF_TEMPERATURE_OFFSET CODEOWNERS = ["@trvrnrth"] DEPENDENCIES = ["i2c"] @@ -11,7 +11,6 @@ MULTI_CONF = True CONF_BME680_BSEC_ID = "bme680_bsec_id" CONF_IAQ_MODE = "iaq_mode" CONF_SUPPLY_VOLTAGE = "supply_voltage" -CONF_SAMPLE_RATE = "sample_rate" CONF_STATE_SAVE_INTERVAL = "state_save_interval" bme680_bsec_ns = cg.esphome_ns.namespace("bme680_bsec") diff --git a/esphome/components/bme680_bsec/sensor.py b/esphome/components/bme680_bsec/sensor.py index 43b068b926..aa96998232 100644 --- a/esphome/components/bme680_bsec/sensor.py +++ b/esphome/components/bme680_bsec/sensor.py @@ -4,33 +4,33 @@ from esphome.components import sensor from esphome.const import ( CONF_GAS_RESISTANCE, CONF_HUMIDITY, + CONF_IAQ_ACCURACY, CONF_PRESSURE, + CONF_SAMPLE_RATE, CONF_TEMPERATURE, + DEVICE_CLASS_ATMOSPHERIC_PRESSURE, DEVICE_CLASS_CARBON_DIOXIDE, DEVICE_CLASS_HUMIDITY, - DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS_PARTS, - DEVICE_CLASS_ATMOSPHERIC_PRESSURE, DEVICE_CLASS_TEMPERATURE, + DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS_PARTS, + ICON_GAS_CYLINDER, + ICON_GAUGE, STATE_CLASS_MEASUREMENT, UNIT_CELSIUS, UNIT_HECTOPASCAL, UNIT_OHM, UNIT_PARTS_PER_MILLION, UNIT_PERCENT, - ICON_GAS_CYLINDER, - ICON_GAUGE, ) from . import ( BME680BSECComponent, CONF_BME680_BSEC_ID, - CONF_SAMPLE_RATE, SAMPLE_RATE_OPTIONS, ) DEPENDENCIES = ["bme680_bsec"] CONF_IAQ = "iaq" -CONF_IAQ_ACCURACY = "iaq_accuracy" CONF_CO2_EQUIVALENT = "co2_equivalent" CONF_BREATH_VOC_EQUIVALENT = "breath_voc_equivalent" UNIT_IAQ = "IAQ" diff --git a/esphome/components/bme680_bsec/text_sensor.py b/esphome/components/bme680_bsec/text_sensor.py index 3494ba0cac..6b46e501da 100644 --- a/esphome/components/bme680_bsec/text_sensor.py +++ b/esphome/components/bme680_bsec/text_sensor.py @@ -1,11 +1,11 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import text_sensor +from esphome.const import CONF_IAQ_ACCURACY from . import BME680BSECComponent, CONF_BME680_BSEC_ID DEPENDENCIES = ["bme680_bsec"] -CONF_IAQ_ACCURACY = "iaq_accuracy" ICON_ACCURACY = "mdi:checkbox-marked-circle-outline" TYPES = [CONF_IAQ_ACCURACY] diff --git a/esphome/components/i2s_audio/microphone/__init__.py b/esphome/components/i2s_audio/microphone/__init__.py index 5ee359dc26..d9c31e8e7b 100644 --- a/esphome/components/i2s_audio/microphone/__init__.py +++ b/esphome/components/i2s_audio/microphone/__init__.py @@ -2,7 +2,7 @@ import esphome.config_validation as cv import esphome.codegen as cg from esphome import pins -from esphome.const import CONF_CHANNEL, CONF_ID, CONF_NUMBER +from esphome.const import CONF_CHANNEL, CONF_ID, CONF_NUMBER, CONF_SAMPLE_RATE from esphome.components import microphone, esp32 from esphome.components.adc import ESP32_VARIANT_ADC1_PIN_TO_CHANNEL, validate_adc_pin @@ -20,7 +20,6 @@ DEPENDENCIES = ["i2s_audio"] CONF_ADC_PIN = "adc_pin" CONF_ADC_TYPE = "adc_type" CONF_PDM = "pdm" -CONF_SAMPLE_RATE = "sample_rate" CONF_BITS_PER_SAMPLE = "bits_per_sample" CONF_USE_APLL = "use_apll" diff --git a/esphome/const.py b/esphome/const.py index a13a0af8eb..543b1d00cc 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -355,6 +355,7 @@ CONF_HUMIDITY_SENSOR = "humidity_sensor" CONF_HYSTERESIS = "hysteresis" CONF_I2C = "i2c" CONF_I2C_ID = "i2c_id" +CONF_IAQ_ACCURACY = "iaq_accuracy" CONF_IBEACON_MAJOR = "ibeacon_major" CONF_IBEACON_MINOR = "ibeacon_minor" CONF_IBEACON_UUID = "ibeacon_uuid" @@ -719,6 +720,7 @@ CONF_RX_BUFFER_SIZE = "rx_buffer_size" CONF_RX_ONLY = "rx_only" CONF_RX_PIN = "rx_pin" CONF_SAFE_MODE = "safe_mode" +CONF_SAMPLE_RATE = "sample_rate" CONF_SAMSUNG = "samsung" CONF_SATELLITES = "satellites" CONF_SCAN = "scan" From 582386d3a2cf0812e84f5e245b3f1764b185c88b Mon Sep 17 00:00:00 2001 From: Andreas Fritiofson Date: Tue, 2 Jul 2024 03:47:56 +0200 Subject: [PATCH 1707/2101] Make crc8 const-correct (#7027) --- esphome/core/helpers.cpp | 2 +- esphome/core/helpers.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/core/helpers.cpp b/esphome/core/helpers.cpp index dee771d4e9..7f040f855f 100644 --- a/esphome/core/helpers.cpp +++ b/esphome/core/helpers.cpp @@ -93,7 +93,7 @@ std::string to_string(long double value) { return str_snprintf("%Lf", 32, value) // Mathematics float lerp(float completion, float start, float end) { return start + (end - start) * completion; } -uint8_t crc8(uint8_t *data, uint8_t len) { +uint8_t crc8(const uint8_t *data, uint8_t len) { uint8_t crc = 0; while ((len--) != 0u) { diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 4af840f77b..b4ad22b083 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -155,7 +155,7 @@ template T remap(U value, U min, U max, T min_out, T max } /// Calculate a CRC-8 checksum of \p data with size \p len. -uint8_t crc8(uint8_t *data, uint8_t len); +uint8_t crc8(const uint8_t *data, uint8_t len); /// Calculate a CRC-16 checksum of \p data with size \p len. uint16_t crc16(const uint8_t *data, uint16_t len, uint16_t crc = 0xffff, uint16_t reverse_poly = 0xa001, From 83f9664efbc04fa0b66780c23aabc85557aa85f0 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Mon, 1 Jul 2024 21:06:33 -0500 Subject: [PATCH 1708/2101] [CI] Run all tests when a base test changes (#7010) --- script/list-components.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/script/list-components.py b/script/list-components.py index 4eccdbf96c..559919bb8a 100755 --- a/script/list-components.py +++ b/script/list-components.py @@ -140,7 +140,10 @@ def get_components(files: list[str], get_dependencies: bool = False): def main(): parser = argparse.ArgumentParser() parser.add_argument( - "-c", "--changed", action="store_true", help="Only run on changed files" + "-c", + "--changed", + action="store_true", + help="List all components required for testing based on changes", ) parser.add_argument( "-b", "--branch", help="Branch to compare changed files against" @@ -158,7 +161,9 @@ def main(): changed = changed_files(args.branch) else: changed = changed_files() - files = [f for f in files if f in changed] + # If any base test file(s) changed, there's no need to filter out components + if not any("tests/test_build_components" in file for file in changed): + files = [f for f in files if f in changed] for c in get_components(files, args.changed): print(c) From 5e6c69b9307724f62ff25873d7c687cf239104dc Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Mon, 1 Jul 2024 21:07:36 -0500 Subject: [PATCH 1709/2101] [CI] Update tests to run against IDF 5.1 (#7011) --- ...f-50.yaml => build_components_base.esp32-c3-idf-51.yaml} | 6 +++--- ...-idf-50.yaml => build_components_base.esp32-idf-51.yaml} | 6 +++--- ...f-50.yaml => build_components_base.esp32-s2-idf-51.yaml} | 6 +++--- ...f-50.yaml => build_components_base.esp32-s3-idf-51.yaml} | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) rename tests/test_build_components/{build_components_base.esp32-c3-idf-50.yaml => build_components_base.esp32-c3-idf-51.yaml} (76%) rename tests/test_build_components/{build_components_base.esp32-idf-50.yaml => build_components_base.esp32-idf-51.yaml} (77%) rename tests/test_build_components/{build_components_base.esp32-s2-idf-50.yaml => build_components_base.esp32-s2-idf-51.yaml} (78%) rename tests/test_build_components/{build_components_base.esp32-s3-idf-50.yaml => build_components_base.esp32-s3-idf-51.yaml} (77%) diff --git a/tests/test_build_components/build_components_base.esp32-c3-idf-50.yaml b/tests/test_build_components/build_components_base.esp32-c3-idf-51.yaml similarity index 76% rename from tests/test_build_components/build_components_base.esp32-c3-idf-50.yaml rename to tests/test_build_components/build_components_base.esp32-c3-idf-51.yaml index 08d4d8679c..eb5b23a4ec 100644 --- a/tests/test_build_components/build_components_base.esp32-c3-idf-50.yaml +++ b/tests/test_build_components/build_components_base.esp32-c3-idf-51.yaml @@ -1,13 +1,13 @@ esphome: - name: componenttestesp32c3idf50 + name: componenttestesp32c3idf51 friendly_name: $component_name esp32: board: lolin_c3_mini framework: type: esp-idf - version: 5.0.2 - platform_version: 6.3.2 + version: 5.1.2 + platform_version: 6.5.0 logger: level: VERY_VERBOSE diff --git a/tests/test_build_components/build_components_base.esp32-idf-50.yaml b/tests/test_build_components/build_components_base.esp32-idf-51.yaml similarity index 77% rename from tests/test_build_components/build_components_base.esp32-idf-50.yaml rename to tests/test_build_components/build_components_base.esp32-idf-51.yaml index c9f2c1e943..b5e3dd6d83 100644 --- a/tests/test_build_components/build_components_base.esp32-idf-50.yaml +++ b/tests/test_build_components/build_components_base.esp32-idf-51.yaml @@ -1,13 +1,13 @@ esphome: - name: componenttestesp32idf50 + name: componenttestesp32idf51 friendly_name: $component_name esp32: board: nodemcu-32s framework: type: esp-idf - version: 5.0.2 - platform_version: 6.3.2 + version: 5.1.2 + platform_version: 6.5.0 logger: level: VERY_VERBOSE diff --git a/tests/test_build_components/build_components_base.esp32-s2-idf-50.yaml b/tests/test_build_components/build_components_base.esp32-s2-idf-51.yaml similarity index 78% rename from tests/test_build_components/build_components_base.esp32-s2-idf-50.yaml rename to tests/test_build_components/build_components_base.esp32-s2-idf-51.yaml index 351f5fb019..11b077509e 100644 --- a/tests/test_build_components/build_components_base.esp32-s2-idf-50.yaml +++ b/tests/test_build_components/build_components_base.esp32-s2-idf-51.yaml @@ -1,5 +1,5 @@ esphome: - name: componenttestesp32s2idf50 + name: componenttestesp32s2idf51 friendly_name: $component_name esp32: @@ -7,8 +7,8 @@ esp32: variant: ESP32S2 framework: type: esp-idf - version: 5.0.2 - platform_version: 6.3.2 + version: 5.1.2 + platform_version: 6.5.0 logger: level: VERY_VERBOSE diff --git a/tests/test_build_components/build_components_base.esp32-s3-idf-50.yaml b/tests/test_build_components/build_components_base.esp32-s3-idf-51.yaml similarity index 77% rename from tests/test_build_components/build_components_base.esp32-s3-idf-50.yaml rename to tests/test_build_components/build_components_base.esp32-s3-idf-51.yaml index c05378903f..4357b3581b 100644 --- a/tests/test_build_components/build_components_base.esp32-s3-idf-50.yaml +++ b/tests/test_build_components/build_components_base.esp32-s3-idf-51.yaml @@ -1,5 +1,5 @@ esphome: - name: componenttestesp32s3idf50 + name: componenttestesp32s3idf51 friendly_name: $component_name esp32: @@ -7,8 +7,8 @@ esp32: variant: ESP32S3 framework: type: esp-idf - version: 5.0.2 - platform_version: 6.3.2 + version: 5.1.2 + platform_version: 6.5.0 logger: level: VERY_VERBOSE From d8f0dce08f6e76cddd1ccc784713f14befb4c36f Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 2 Jul 2024 14:29:49 +1200 Subject: [PATCH 1710/2101] [uptime] Add new timestamp type for uptime sensor (#7029) * [uptime] Add new timestamp type for uptime sensor * Remove debug logs --- esphome/components/uptime/sensor.py | 55 +++++++++++++++---- ...e_sensor.cpp => uptime_seconds_sensor.cpp} | 18 +++--- ...ptime_sensor.h => uptime_seconds_sensor.h} | 4 +- .../uptime/uptime_timestamp_sensor.cpp | 39 +++++++++++++ .../uptime/uptime_timestamp_sensor.h | 30 ++++++++++ tests/components/uptime/common.yaml | 12 ++++ 6 files changed, 138 insertions(+), 20 deletions(-) rename esphome/components/uptime/{uptime_sensor.cpp => uptime_seconds_sensor.cpp} (72%) rename esphome/components/uptime/{uptime_sensor.h => uptime_seconds_sensor.h} (82%) create mode 100644 esphome/components/uptime/uptime_timestamp_sensor.cpp create mode 100644 esphome/components/uptime/uptime_timestamp_sensor.h diff --git a/esphome/components/uptime/sensor.py b/esphome/components/uptime/sensor.py index 07d7d8f2cf..30220751b6 100644 --- a/esphome/components/uptime/sensor.py +++ b/esphome/components/uptime/sensor.py @@ -1,7 +1,9 @@ import esphome.codegen as cg import esphome.config_validation as cv -from esphome.components import sensor +from esphome.components import sensor, time from esphome.const import ( + CONF_TIME_ID, + DEVICE_CLASS_TIMESTAMP, ENTITY_CATEGORY_DIAGNOSTIC, STATE_CLASS_TOTAL_INCREASING, UNIT_SECOND, @@ -10,19 +12,50 @@ from esphome.const import ( ) uptime_ns = cg.esphome_ns.namespace("uptime") -UptimeSensor = uptime_ns.class_("UptimeSensor", sensor.Sensor, cg.PollingComponent) +UptimeSecondsSensor = uptime_ns.class_( + "UptimeSecondsSensor", sensor.Sensor, cg.PollingComponent +) +UptimeTimestampSensor = uptime_ns.class_( + "UptimeTimestampSensor", sensor.Sensor, cg.Component +) -CONFIG_SCHEMA = sensor.sensor_schema( - UptimeSensor, - unit_of_measurement=UNIT_SECOND, - icon=ICON_TIMER, - accuracy_decimals=0, - state_class=STATE_CLASS_TOTAL_INCREASING, - device_class=DEVICE_CLASS_DURATION, - entity_category=ENTITY_CATEGORY_DIAGNOSTIC, -).extend(cv.polling_component_schema("60s")) + +CONFIG_SCHEMA = cv.typed_schema( + { + "seconds": sensor.sensor_schema( + UptimeSecondsSensor, + unit_of_measurement=UNIT_SECOND, + icon=ICON_TIMER, + accuracy_decimals=0, + state_class=STATE_CLASS_TOTAL_INCREASING, + device_class=DEVICE_CLASS_DURATION, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + ).extend(cv.polling_component_schema("60s")), + "timestamp": sensor.sensor_schema( + UptimeTimestampSensor, + icon=ICON_TIMER, + accuracy_decimals=0, + device_class=DEVICE_CLASS_TIMESTAMP, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + ) + .extend( + cv.Schema( + { + cv.GenerateID(CONF_TIME_ID): cv.All( + cv.requires_component("time"), cv.use_id(time.RealTimeClock) + ), + } + ) + ) + .extend(cv.COMPONENT_SCHEMA), + }, + default_type="seconds", +) async def to_code(config): var = await sensor.new_sensor(config) await cg.register_component(var, config) + if time_id_config := config.get(CONF_TIME_ID): + time_id = await cg.get_variable(time_id_config) + cg.add(var.set_time(time_id)) diff --git a/esphome/components/uptime/uptime_sensor.cpp b/esphome/components/uptime/uptime_seconds_sensor.cpp similarity index 72% rename from esphome/components/uptime/uptime_sensor.cpp rename to esphome/components/uptime/uptime_seconds_sensor.cpp index 40325d2a36..fa6b9d621d 100644 --- a/esphome/components/uptime/uptime_sensor.cpp +++ b/esphome/components/uptime/uptime_seconds_sensor.cpp @@ -1,14 +1,15 @@ -#include "uptime_sensor.h" -#include "esphome/core/log.h" -#include "esphome/core/helpers.h" +#include "uptime_seconds_sensor.h" + #include "esphome/core/hal.h" +#include "esphome/core/helpers.h" +#include "esphome/core/log.h" namespace esphome { namespace uptime { static const char *const TAG = "uptime.sensor"; -void UptimeSensor::update() { +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; @@ -26,9 +27,12 @@ void UptimeSensor::update() { const float seconds = float(seconds_int) + (this->uptime_ % 1000ULL) / 1000.0f; this->publish_state(seconds); } -std::string UptimeSensor::unique_id() { return get_mac_address() + "-uptime"; } -float UptimeSensor::get_setup_priority() const { return setup_priority::HARDWARE; } -void UptimeSensor::dump_config() { LOG_SENSOR("", "Uptime Sensor", this); } +std::string UptimeSecondsSensor::unique_id() { return get_mac_address() + "-uptime"; } +float UptimeSecondsSensor::get_setup_priority() const { return setup_priority::HARDWARE; } +void UptimeSecondsSensor::dump_config() { + LOG_SENSOR("", "Uptime Sensor", this); + ESP_LOGCONFIG(TAG, " Type: Seconds"); +} } // namespace uptime } // namespace esphome diff --git a/esphome/components/uptime/uptime_sensor.h b/esphome/components/uptime/uptime_seconds_sensor.h similarity index 82% rename from esphome/components/uptime/uptime_sensor.h rename to esphome/components/uptime/uptime_seconds_sensor.h index dab380d2d9..41b3647822 100644 --- a/esphome/components/uptime/uptime_sensor.h +++ b/esphome/components/uptime/uptime_seconds_sensor.h @@ -1,12 +1,12 @@ #pragma once -#include "esphome/core/component.h" #include "esphome/components/sensor/sensor.h" +#include "esphome/core/component.h" namespace esphome { namespace uptime { -class UptimeSensor : public sensor::Sensor, public PollingComponent { +class UptimeSecondsSensor : public sensor::Sensor, public PollingComponent { public: void update() override; void dump_config() override; diff --git a/esphome/components/uptime/uptime_timestamp_sensor.cpp b/esphome/components/uptime/uptime_timestamp_sensor.cpp new file mode 100644 index 0000000000..fa8cb2bb61 --- /dev/null +++ b/esphome/components/uptime/uptime_timestamp_sensor.cpp @@ -0,0 +1,39 @@ +#include "uptime_timestamp_sensor.h" + +#ifdef USE_TIME + +#include "esphome/core/hal.h" +#include "esphome/core/helpers.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace uptime { + +static const char *const TAG = "uptime.sensor"; + +void UptimeTimestampSensor::setup() { + this->time_->add_on_time_sync_callback([this]() { + if (this->has_state_) + return; // No need to update the timestamp if it's already set + + auto now = this->time_->now(); + const uint32_t ms = millis(); + if (!now.is_valid()) + return; // No need to update the timestamp if the time is not valid + + time_t timestamp = now.timestamp; + uint32_t seconds = ms / 1000; + timestamp -= seconds; + this->publish_state(timestamp); + }); +} +float UptimeTimestampSensor::get_setup_priority() const { return setup_priority::HARDWARE; } +void UptimeTimestampSensor::dump_config() { + LOG_SENSOR("", "Uptime Sensor", this); + ESP_LOGCONFIG(TAG, " Type: Timestamp"); +} + +} // namespace uptime +} // namespace esphome + +#endif // USE_TIME diff --git a/esphome/components/uptime/uptime_timestamp_sensor.h b/esphome/components/uptime/uptime_timestamp_sensor.h new file mode 100644 index 0000000000..f38b5d53b4 --- /dev/null +++ b/esphome/components/uptime/uptime_timestamp_sensor.h @@ -0,0 +1,30 @@ +#pragma once + +#include "esphome/core/defines.h" + +#ifdef USE_TIME + +#include "esphome/components/sensor/sensor.h" +#include "esphome/components/time/real_time_clock.h" +#include "esphome/core/component.h" + +namespace esphome { +namespace uptime { + +class UptimeTimestampSensor : public sensor::Sensor, public Component { + public: + void setup() override; + void dump_config() override; + + float get_setup_priority() const override; + + void set_time(time::RealTimeClock *time) { this->time_ = time; } + + protected: + time::RealTimeClock *time_; +}; + +} // namespace uptime +} // namespace esphome + +#endif // USE_TIME diff --git a/tests/components/uptime/common.yaml b/tests/components/uptime/common.yaml index 872a0e7402..f63f80b050 100644 --- a/tests/components/uptime/common.yaml +++ b/tests/components/uptime/common.yaml @@ -1,3 +1,15 @@ +wifi: + ap: + +time: + - platform: sntp + sensor: - platform: uptime name: Uptime Sensor + - platform: uptime + name: Uptime Sensor Seconds + type: seconds + - platform: uptime + name: Uptime Sensor Timestamp + type: timestamp From 3fb9c93a24b3b9683c5987af3ebe88cfa0492e49 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 3 Jul 2024 14:21:41 +1200 Subject: [PATCH 1711/2101] [wifi] Only set default ttls phase 2 on esp-idf (#7033) * [wifi] Only set default ttls phase 2 on esp-idf * Add eap arduino test --- esphome/components/wifi/__init__.py | 4 ++-- tests/components/wifi/test-eap.esp32-ard.yaml | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 tests/components/wifi/test-eap.esp32-ard.yaml diff --git a/esphome/components/wifi/__init__.py b/esphome/components/wifi/__init__.py index 3b9e00956f..624bcdabdc 100644 --- a/esphome/components/wifi/__init__.py +++ b/esphome/components/wifi/__init__.py @@ -114,7 +114,7 @@ EAP_AUTH_SCHEMA = cv.All( cv.Optional(CONF_USERNAME): cv.string_strict, cv.Optional(CONF_PASSWORD): cv.string_strict, cv.Optional(CONF_CERTIFICATE_AUTHORITY): wpa2_eap.validate_certificate, - cv.Optional(CONF_TTLS_PHASE_2): cv.All( + cv.SplitDefault(CONF_TTLS_PHASE_2, esp32_idf="mschapv2"): cv.All( cv.enum(TTLS_PHASE_2), cv.only_with_esp_idf ), cv.Inclusive( @@ -350,7 +350,7 @@ def eap_auth(config): ("ca_cert", ca_cert), ("client_cert", client_cert), ("client_key", key), - ("ttls_phase_2", config.get(CONF_TTLS_PHASE_2, TTLS_PHASE_2["mschapv2"])), + ("ttls_phase_2", config.get(CONF_TTLS_PHASE_2)), ) diff --git a/tests/components/wifi/test-eap.esp32-ard.yaml b/tests/components/wifi/test-eap.esp32-ard.yaml new file mode 100644 index 0000000000..779cd6b49a --- /dev/null +++ b/tests/components/wifi/test-eap.esp32-ard.yaml @@ -0,0 +1,7 @@ +wifi: + networks: + - ssid: MySSID + eap: + username: username + password: password + identity: identity From 12f00a9d3d4e5354bd3c21b414b60cc14e04ee73 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Sat, 29 Jun 2024 14:12:59 +1200 Subject: [PATCH 1712/2101] [mpr121] await register parented (#7014) fixes https://github.com/esphome/issues/issues/5913 --- esphome/components/mpr121/binary_sensor/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/mpr121/binary_sensor/__init__.py b/esphome/components/mpr121/binary_sensor/__init__.py index 292c631c37..dfae92a9af 100644 --- a/esphome/components/mpr121/binary_sensor/__init__.py +++ b/esphome/components/mpr121/binary_sensor/__init__.py @@ -27,7 +27,7 @@ async def to_code(config): var = await binary_sensor.new_binary_sensor(config) hub = await cg.get_variable(config[CONF_MPR121_ID]) cg.add(var.set_channel(config[CONF_CHANNEL])) - cg.register_parented(var, hub) + await cg.register_parented(var, hub) if CONF_TOUCH_THRESHOLD in config: cg.add(var.set_touch_threshold(config[CONF_TOUCH_THRESHOLD])) From 0914dc719889d25e71bf12a4025c821ed6542504 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Mon, 1 Jul 2024 01:20:59 -0500 Subject: [PATCH 1713/2101] Move some consts for #4585 (#7023) --- esphome/components/bme680_bsec/__init__.py | 3 +-- esphome/components/bme680_bsec/sensor.py | 12 ++++++------ esphome/components/bme680_bsec/text_sensor.py | 2 +- esphome/components/i2s_audio/microphone/__init__.py | 3 +-- esphome/const.py | 2 ++ 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/esphome/components/bme680_bsec/__init__.py b/esphome/components/bme680_bsec/__init__.py index 62ab50b8f7..743ef6e85d 100644 --- a/esphome/components/bme680_bsec/__init__.py +++ b/esphome/components/bme680_bsec/__init__.py @@ -1,7 +1,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import i2c, esp32 -from esphome.const import CONF_ID, CONF_TEMPERATURE_OFFSET +from esphome.const import CONF_ID, CONF_SAMPLE_RATE, CONF_TEMPERATURE_OFFSET CODEOWNERS = ["@trvrnrth"] DEPENDENCIES = ["i2c"] @@ -11,7 +11,6 @@ MULTI_CONF = True CONF_BME680_BSEC_ID = "bme680_bsec_id" CONF_IAQ_MODE = "iaq_mode" CONF_SUPPLY_VOLTAGE = "supply_voltage" -CONF_SAMPLE_RATE = "sample_rate" CONF_STATE_SAVE_INTERVAL = "state_save_interval" bme680_bsec_ns = cg.esphome_ns.namespace("bme680_bsec") diff --git a/esphome/components/bme680_bsec/sensor.py b/esphome/components/bme680_bsec/sensor.py index 43b068b926..aa96998232 100644 --- a/esphome/components/bme680_bsec/sensor.py +++ b/esphome/components/bme680_bsec/sensor.py @@ -4,33 +4,33 @@ from esphome.components import sensor from esphome.const import ( CONF_GAS_RESISTANCE, CONF_HUMIDITY, + CONF_IAQ_ACCURACY, CONF_PRESSURE, + CONF_SAMPLE_RATE, CONF_TEMPERATURE, + DEVICE_CLASS_ATMOSPHERIC_PRESSURE, DEVICE_CLASS_CARBON_DIOXIDE, DEVICE_CLASS_HUMIDITY, - DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS_PARTS, - DEVICE_CLASS_ATMOSPHERIC_PRESSURE, DEVICE_CLASS_TEMPERATURE, + DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS_PARTS, + ICON_GAS_CYLINDER, + ICON_GAUGE, STATE_CLASS_MEASUREMENT, UNIT_CELSIUS, UNIT_HECTOPASCAL, UNIT_OHM, UNIT_PARTS_PER_MILLION, UNIT_PERCENT, - ICON_GAS_CYLINDER, - ICON_GAUGE, ) from . import ( BME680BSECComponent, CONF_BME680_BSEC_ID, - CONF_SAMPLE_RATE, SAMPLE_RATE_OPTIONS, ) DEPENDENCIES = ["bme680_bsec"] CONF_IAQ = "iaq" -CONF_IAQ_ACCURACY = "iaq_accuracy" CONF_CO2_EQUIVALENT = "co2_equivalent" CONF_BREATH_VOC_EQUIVALENT = "breath_voc_equivalent" UNIT_IAQ = "IAQ" diff --git a/esphome/components/bme680_bsec/text_sensor.py b/esphome/components/bme680_bsec/text_sensor.py index 3494ba0cac..6b46e501da 100644 --- a/esphome/components/bme680_bsec/text_sensor.py +++ b/esphome/components/bme680_bsec/text_sensor.py @@ -1,11 +1,11 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import text_sensor +from esphome.const import CONF_IAQ_ACCURACY from . import BME680BSECComponent, CONF_BME680_BSEC_ID DEPENDENCIES = ["bme680_bsec"] -CONF_IAQ_ACCURACY = "iaq_accuracy" ICON_ACCURACY = "mdi:checkbox-marked-circle-outline" TYPES = [CONF_IAQ_ACCURACY] diff --git a/esphome/components/i2s_audio/microphone/__init__.py b/esphome/components/i2s_audio/microphone/__init__.py index 5ee359dc26..d9c31e8e7b 100644 --- a/esphome/components/i2s_audio/microphone/__init__.py +++ b/esphome/components/i2s_audio/microphone/__init__.py @@ -2,7 +2,7 @@ import esphome.config_validation as cv import esphome.codegen as cg from esphome import pins -from esphome.const import CONF_CHANNEL, CONF_ID, CONF_NUMBER +from esphome.const import CONF_CHANNEL, CONF_ID, CONF_NUMBER, CONF_SAMPLE_RATE from esphome.components import microphone, esp32 from esphome.components.adc import ESP32_VARIANT_ADC1_PIN_TO_CHANNEL, validate_adc_pin @@ -20,7 +20,6 @@ DEPENDENCIES = ["i2s_audio"] CONF_ADC_PIN = "adc_pin" CONF_ADC_TYPE = "adc_type" CONF_PDM = "pdm" -CONF_SAMPLE_RATE = "sample_rate" CONF_BITS_PER_SAMPLE = "bits_per_sample" CONF_USE_APLL = "use_apll" diff --git a/esphome/const.py b/esphome/const.py index b26d8d2851..fee9c1796a 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -355,6 +355,7 @@ CONF_HUMIDITY_SENSOR = "humidity_sensor" CONF_HYSTERESIS = "hysteresis" CONF_I2C = "i2c" CONF_I2C_ID = "i2c_id" +CONF_IAQ_ACCURACY = "iaq_accuracy" CONF_IBEACON_MAJOR = "ibeacon_major" CONF_IBEACON_MINOR = "ibeacon_minor" CONF_IBEACON_UUID = "ibeacon_uuid" @@ -719,6 +720,7 @@ CONF_RX_BUFFER_SIZE = "rx_buffer_size" CONF_RX_ONLY = "rx_only" CONF_RX_PIN = "rx_pin" CONF_SAFE_MODE = "safe_mode" +CONF_SAMPLE_RATE = "sample_rate" CONF_SAMSUNG = "samsung" CONF_SATELLITES = "satellites" CONF_SCAN = "scan" From 5cb80619ddd362c055e9e418f9da1c4c175687b5 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 3 Jul 2024 14:21:41 +1200 Subject: [PATCH 1714/2101] [wifi] Only set default ttls phase 2 on esp-idf (#7033) * [wifi] Only set default ttls phase 2 on esp-idf * Add eap arduino test --- esphome/components/wifi/__init__.py | 4 ++-- tests/components/wifi/test-eap.esp32-ard.yaml | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 tests/components/wifi/test-eap.esp32-ard.yaml diff --git a/esphome/components/wifi/__init__.py b/esphome/components/wifi/__init__.py index 3b9e00956f..624bcdabdc 100644 --- a/esphome/components/wifi/__init__.py +++ b/esphome/components/wifi/__init__.py @@ -114,7 +114,7 @@ EAP_AUTH_SCHEMA = cv.All( cv.Optional(CONF_USERNAME): cv.string_strict, cv.Optional(CONF_PASSWORD): cv.string_strict, cv.Optional(CONF_CERTIFICATE_AUTHORITY): wpa2_eap.validate_certificate, - cv.Optional(CONF_TTLS_PHASE_2): cv.All( + cv.SplitDefault(CONF_TTLS_PHASE_2, esp32_idf="mschapv2"): cv.All( cv.enum(TTLS_PHASE_2), cv.only_with_esp_idf ), cv.Inclusive( @@ -350,7 +350,7 @@ def eap_auth(config): ("ca_cert", ca_cert), ("client_cert", client_cert), ("client_key", key), - ("ttls_phase_2", config.get(CONF_TTLS_PHASE_2, TTLS_PHASE_2["mschapv2"])), + ("ttls_phase_2", config.get(CONF_TTLS_PHASE_2)), ) diff --git a/tests/components/wifi/test-eap.esp32-ard.yaml b/tests/components/wifi/test-eap.esp32-ard.yaml new file mode 100644 index 0000000000..779cd6b49a --- /dev/null +++ b/tests/components/wifi/test-eap.esp32-ard.yaml @@ -0,0 +1,7 @@ +wifi: + networks: + - ssid: MySSID + eap: + username: username + password: password + identity: identity From 995db1d0e11554fed3fa62672df3faa535b7f1ba Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 3 Jul 2024 15:45:30 +1200 Subject: [PATCH 1715/2101] Bump version to 2024.6.5 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index fee9c1796a..5b441faa6c 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.6.4" +__version__ = "2024.6.5" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From ee6f2bfecb1bb728d37f4f4283b05301894eaab9 Mon Sep 17 00:00:00 2001 From: lhy Date: Wed, 3 Jul 2024 17:03:54 +0900 Subject: [PATCH 1716/2101] Fix compile errors on ESP32-C6 with W5500 SPI ethernet (#7030) --- esphome/components/ethernet/ethernet_component.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index 7370cb4b44..6b34157b9d 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -65,7 +65,8 @@ void EthernetComponent::setup() { .intr_flags = 0, }; -#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) +#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) || \ + defined(USE_ESP32_VARIANT_ESP32C6) auto host = SPI2_HOST; #else auto host = SPI3_HOST; From 849a98d5b4e93ba61cd323cd224d46774d3566bc Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 1 Jul 2024 08:54:04 +1200 Subject: [PATCH 1717/2101] Bump dockerfile dependencies (#7017) --- docker/Dockerfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index fcb5a5e7ae..eabd118939 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -34,7 +34,7 @@ RUN \ python3-wheel=0.38.4-2 \ iputils-ping=3:20221126-1 \ git=1:2.39.2-1.1 \ - curl=7.88.1-10+deb12u5 \ + curl=7.88.1-10+deb12u6 \ openssh-client=1:9.2p1-2+deb12u2 \ python3-cffi=1.15.1-5 \ libcairo2=1.16.0-7 \ @@ -190,8 +190,8 @@ RUN \ clang-format-13=1:13.0.1-11+b2 \ clang-tidy-14=1:14.0.6-12 \ patch=2.7.6-7 \ - software-properties-common=0.99.30-4 \ - nano=7.2-1 \ + software-properties-common=0.99.30-4.1~deb12u1 \ + nano=7.2-1+deb12u1 \ build-essential=12.9 \ python3-dev=3.11.2-1+b1 \ && rm -rf \ From c013c3bf6194ab257c108ef66b27af18939bcf5f Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 1 Jul 2024 11:17:44 +1200 Subject: [PATCH 1718/2101] [docker] Bump versions inside armv7 block (#7022) --- docker/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index eabd118939..b0c800f167 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -46,8 +46,8 @@ RUN \ python3-dev=3.11.2-1+b1 \ zlib1g-dev=1:1.2.13.dfsg-1 \ libjpeg-dev=1:2.1.5-2 \ - libfreetype-dev=2.12.1+dfsg-5 \ - libssl-dev=3.0.11-1~deb12u2 \ + libfreetype-dev=2.12.1+dfsg-5+deb12u3 \ + libssl-dev=3.0.13-1~deb12u1 \ libffi-dev=3.4.4-1 \ libopenjp2-7=2.5.0-2 \ libtiff6=4.5.0-6+deb12u1 \ From fc3f806555eb395452c0526b3e9cf1503fdcee51 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 1 Jul 2024 11:51:51 +1200 Subject: [PATCH 1719/2101] [docker] Fix docker build error fall through (#7021) --- docker/Dockerfile | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index b0c800f167..16f37274c6 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -39,23 +39,27 @@ RUN \ python3-cffi=1.15.1-5 \ libcairo2=1.16.0-7 \ libmagic1=1:5.44-3 \ - patch=2.7.6-7; \ - if [ "$TARGETARCH$TARGETVARIANT" = "armv7" ]; then \ - apt-get install -y --no-install-recommends \ - build-essential=12.9 \ - python3-dev=3.11.2-1+b1 \ - zlib1g-dev=1:1.2.13.dfsg-1 \ - libjpeg-dev=1:2.1.5-2 \ - libfreetype-dev=2.12.1+dfsg-5+deb12u3 \ - libssl-dev=3.0.13-1~deb12u1 \ - libffi-dev=3.4.4-1 \ - libopenjp2-7=2.5.0-2 \ - libtiff6=4.5.0-6+deb12u1 \ - cargo=0.66.0+ds1-1 \ - pkg-config=1.8.1-1 \ - gcc-arm-linux-gnueabihf=4:12.2.0-3; \ - fi; \ - rm -rf \ + patch=2.7.6-7 \ + && ( \ + ( \ + [ "$TARGETARCH$TARGETVARIANT" = "armv7" ] && \ + apt-get install -y --no-install-recommends \ + build-essential=12.9 \ + python3-dev=3.11.2-1+b1 \ + zlib1g-dev=1:1.2.13.dfsg-1 \ + libjpeg-dev=1:2.1.5-2 \ + libfreetype-dev=2.12.1+dfsg-5+deb12u3 \ + libssl-dev=3.0.13-1~deb12u1 \ + libffi-dev=3.4.4-1 \ + libopenjp2-7=2.5.0-2 \ + libtiff6=4.5.0-6+deb12u1 \ + cargo=0.66.0+ds1-1 \ + pkg-config=1.8.1-1 \ + gcc-arm-linux-gnueabihf=4:12.2.0-3 \ + ) \ + || [ "$TARGETARCH$TARGETVARIANT" != "armv7" ] \ + ) \ + && rm -rf \ /tmp/* \ /var/{cache,log}/* \ /var/lib/apt/lists/* From 3727342bce096a38d6f3d20d00aa89e7295c8c89 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 3 Jul 2024 20:14:27 +1200 Subject: [PATCH 1720/2101] Bump version to 2024.6.6 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 5b441faa6c..0d79908226 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.6.5" +__version__ = "2024.6.6" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From de19588d10a3350ae2625e490387dbccd6048677 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Jul 2024 11:22:06 +1200 Subject: [PATCH 1721/2101] Bump docker/setup-buildx-action from 3.3.0 to 3.4.0 (#7043) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-docker.yml | 2 +- .github/workflows/release.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-docker.yml b/.github/workflows/ci-docker.yml index 421a885f74..59b58ad82c 100644 --- a/.github/workflows/ci-docker.yml +++ b/.github/workflows/ci-docker.yml @@ -46,7 +46,7 @@ jobs: with: python-version: "3.9" - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3.3.0 + uses: docker/setup-buildx-action@v3.4.0 - name: Set up QEMU uses: docker/setup-qemu-action@v3.0.0 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a1942e8cac..70b88bfd71 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -90,7 +90,7 @@ jobs: python-version: "3.9" - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3.3.0 + uses: docker/setup-buildx-action@v3.4.0 - name: Set up QEMU if: matrix.platform != 'linux/amd64' uses: docker/setup-qemu-action@v3.0.0 @@ -184,7 +184,7 @@ jobs: merge-multiple: true - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3.3.0 + uses: docker/setup-buildx-action@v3.4.0 - name: Log in to docker hub if: matrix.registry == 'dockerhub' From 803f3f2e13cc27470113a23708558a1bd7b934b1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Jul 2024 11:31:50 +1200 Subject: [PATCH 1722/2101] Bump docker/build-push-action from 6.2.0 to 6.3.0 in /.github/actions/build-image (#7038) 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 b038a285ef..d5baf339aa 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -46,7 +46,7 @@ runs: - name: Build and push to ghcr by digest id: build-ghcr - uses: docker/build-push-action@v6.2.0 + uses: docker/build-push-action@v6.3.0 with: context: . file: ./docker/Dockerfile @@ -69,7 +69,7 @@ runs: - name: Build and push to dockerhub by digest id: build-dockerhub - uses: docker/build-push-action@v6.2.0 + uses: docker/build-push-action@v6.3.0 with: context: . file: ./docker/Dockerfile From 5fa54b0885e3c55f2afb518b2b4fbbad50dd10b9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Jul 2024 13:27:46 +1200 Subject: [PATCH 1723/2101] Bump docker/setup-qemu-action from 3.0.0 to 3.1.0 (#7039) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-docker.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-docker.yml b/.github/workflows/ci-docker.yml index 59b58ad82c..147efe089e 100644 --- a/.github/workflows/ci-docker.yml +++ b/.github/workflows/ci-docker.yml @@ -48,7 +48,7 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3.4.0 - name: Set up QEMU - uses: docker/setup-qemu-action@v3.0.0 + uses: docker/setup-qemu-action@v3.1.0 - name: Set TAG run: | diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 70b88bfd71..71a366d535 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -93,7 +93,7 @@ jobs: uses: docker/setup-buildx-action@v3.4.0 - name: Set up QEMU if: matrix.platform != 'linux/amd64' - uses: docker/setup-qemu-action@v3.0.0 + uses: docker/setup-qemu-action@v3.1.0 - name: Log in to docker hub uses: docker/login-action@v3.2.0 From b0a3b5e080d457708decc70b35abd0aad7ca3b69 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 6 Jul 2024 16:23:37 +1200 Subject: [PATCH 1724/2101] Bump actions/upload-artifact from 4.3.3 to 4.3.4 (#7047) 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 71a366d535..83641d8aa5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -141,7 +141,7 @@ jobs: echo name=$(cat /tmp/platform) >> $GITHUB_OUTPUT - name: Upload digests - uses: actions/upload-artifact@v4.3.3 + uses: actions/upload-artifact@v4.3.4 with: name: digests-${{ steps.sanitize.outputs.name }} path: /tmp/digests From 6ca7b30f7514572dec8019f9335c1ea3ce73db1a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 6 Jul 2024 16:23:47 +1200 Subject: [PATCH 1725/2101] Bump actions/download-artifact from 4.1.7 to 4.1.8 (#7046) 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 83641d8aa5..f66c504bda 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -177,7 +177,7 @@ jobs: - uses: actions/checkout@v4.1.7 - name: Download digests - uses: actions/download-artifact@v4.1.7 + uses: actions/download-artifact@v4.1.8 with: pattern: digests-* path: /tmp/digests From dd1e480142ad378e4e93b82fd435da70635de2c4 Mon Sep 17 00:00:00 2001 From: leejoow Date: Sat, 6 Jul 2024 06:57:30 +0200 Subject: [PATCH 1726/2101] Fix display of update state in webinterfae (#7045) Co-authored-by: Leo Schelvis --- .../http_request/update/http_request_update.cpp | 13 ++++++------- .../http_request/update/http_request_update.h | 3 --- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/esphome/components/http_request/update/http_request_update.cpp b/esphome/components/http_request/update/http_request_update.cpp index 98129e59dc..0a14dfd933 100644 --- a/esphome/components/http_request/update/http_request_update.cpp +++ b/esphome/components/http_request/update/http_request_update.cpp @@ -116,19 +116,18 @@ void HttpRequestUpdate::update() { } } - std::string current_version = this->current_version_; - if (current_version.empty()) { + std::string current_version; #ifdef ESPHOME_PROJECT_VERSION - current_version = ESPHOME_PROJECT_VERSION; + current_version = ESPHOME_PROJECT_VERSION; #else - current_version = ESPHOME_VERSION; + current_version = ESPHOME_VERSION; #endif - } + this->update_info_.current_version = current_version; - if (this->update_info_.latest_version.empty()) { + if (this->update_info_.latest_version.empty() || this->update_info_.latest_version == update_info_.current_version) { this->state_ = update::UPDATE_STATE_NO_UPDATE; - } else if (this->update_info_.latest_version != this->current_version_) { + } else { this->state_ = update::UPDATE_STATE_AVAILABLE; } diff --git a/esphome/components/http_request/update/http_request_update.h b/esphome/components/http_request/update/http_request_update.h index 1337822ecc..a6bc97392b 100644 --- a/esphome/components/http_request/update/http_request_update.h +++ b/esphome/components/http_request/update/http_request_update.h @@ -22,15 +22,12 @@ class HttpRequestUpdate : public update::UpdateEntity, public PollingComponent { void set_request_parent(HttpRequestComponent *request_parent) { this->request_parent_ = request_parent; } void set_ota_parent(OtaHttpRequestComponent *ota_parent) { this->ota_parent_ = ota_parent; } - void set_current_version(const std::string ¤t_version) { this->current_version_ = current_version; } - float get_setup_priority() const override { return setup_priority::AFTER_WIFI; } protected: HttpRequestComponent *request_parent_; OtaHttpRequestComponent *ota_parent_; std::string source_url_; - std::string current_version_{""}; }; } // namespace http_request From ddaa84683be70cba79a1dcc191eec23f59a4f973 Mon Sep 17 00:00:00 2001 From: Pavlo Dudnytskyi Date: Sat, 6 Jul 2024 09:00:44 +0200 Subject: [PATCH 1727/2101] Haier component update to support more protocol variations (#7040) Co-authored-by: Pavlo Dudnytskyi --- esphome/components/haier/climate.py | 41 ++++- esphome/components/haier/haier_base.cpp | 4 + esphome/components/haier/haier_base.h | 12 +- esphome/components/haier/hon_climate.cpp | 164 ++++++++++++------ esphome/components/haier/hon_climate.h | 8 +- esphome/components/haier/hon_packet.h | 5 + .../components/haier/smartair2_climate.cpp | 1 + platformio.ini | 2 +- tests/components/haier/common.yaml | 114 ++++++++++++ tests/components/haier/test.esp32-ard.yaml | 116 +------------ tests/components/haier/test.esp32-c3-ard.yaml | 112 +----------- tests/components/haier/test.esp32-c3-idf.yaml | 112 +----------- tests/components/haier/test.esp32-idf.yaml | 112 +----------- tests/components/haier/test.esp8266-ard.yaml | 112 +----------- tests/components/haier/test.rp2040-ard.yaml | 112 +----------- 15 files changed, 316 insertions(+), 711 deletions(-) create mode 100644 tests/components/haier/common.yaml diff --git a/esphome/components/haier/climate.py b/esphome/components/haier/climate.py index 3dcb35708c..f7423a1356 100644 --- a/esphome/components/haier/climate.py +++ b/esphome/components/haier/climate.py @@ -38,6 +38,9 @@ PROTOCOL_MAX_TEMPERATURE = 30.0 PROTOCOL_TARGET_TEMPERATURE_STEP = 1.0 PROTOCOL_CURRENT_TEMPERATURE_STEP = 0.5 PROTOCOL_CONTROL_PACKET_SIZE = 10 +PROTOCOL_MIN_SENSORS_PACKET_SIZE = 18 +PROTOCOL_DEFAULT_SENSORS_PACKET_SIZE = 22 +PROTOCOL_STATUS_MESSAGE_HEADER_SIZE = 0 CODEOWNERS = ["@paveldn"] DEPENDENCIES = ["climate", "uart"] @@ -48,6 +51,9 @@ CONF_CONTROL_PACKET_SIZE = "control_packet_size" CONF_HORIZONTAL_AIRFLOW = "horizontal_airflow" CONF_ON_ALARM_START = "on_alarm_start" CONF_ON_ALARM_END = "on_alarm_end" +CONF_ON_STATUS_MESSAGE = "on_status_message" +CONF_SENSORS_PACKET_SIZE = "sensors_packet_size" +CONF_STATUS_MESSAGE_HEADER_SIZE = "status_message_header_size" CONF_VERTICAL_AIRFLOW = "vertical_airflow" CONF_WIFI_SIGNAL = "wifi_signal" @@ -129,6 +135,11 @@ HaierAlarmEndTrigger = haier_ns.class_( 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: @@ -193,6 +204,11 @@ BASE_CONFIG_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), + } + ), } ) .extend(uart.UART_DEVICE_SCHEMA) @@ -228,6 +244,14 @@ CONFIG_SCHEMA = cv.All( cv.Optional( CONF_CONTROL_PACKET_SIZE, default=PROTOCOL_CONTROL_PACKET_SIZE ): cv.int_range(min=PROTOCOL_CONTROL_PACKET_SIZE, max=50), + cv.Optional( + CONF_SENSORS_PACKET_SIZE, + default=PROTOCOL_DEFAULT_SENSORS_PACKET_SIZE, + ): cv.int_range(min=PROTOCOL_MIN_SENSORS_PACKET_SIZE, max=50), + cv.Optional( + CONF_STATUS_MESSAGE_HEADER_SIZE, + default=PROTOCOL_STATUS_MESSAGE_HEADER_SIZE, + ): cv.int_range(min=PROTOCOL_STATUS_MESSAGE_HEADER_SIZE), cv.Optional( CONF_SUPPORTED_PRESETS, default=["BOOST", "ECO", "SLEEP"], # No AWAY by default @@ -468,6 +492,16 @@ async def to_code(config): config[CONF_CONTROL_PACKET_SIZE] - PROTOCOL_CONTROL_PACKET_SIZE ) ) + if CONF_SENSORS_PACKET_SIZE in config: + cg.add( + var.set_extra_sensors_packet_bytes_size( + config[CONF_SENSORS_PACKET_SIZE] - PROTOCOL_MIN_SENSORS_PACKET_SIZE + ) + ) + if CONF_STATUS_MESSAGE_HEADER_SIZE in config: + cg.add( + 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( @@ -478,5 +512,10 @@ async def to_code(config): await automation.build_automation( trigger, [(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 + ) # https://github.com/paveldn/HaierProtocol - cg.add_library("pavlodn/HaierProtocol", "0.9.28") + cg.add_library("pavlodn/HaierProtocol", "0.9.31") diff --git a/esphome/components/haier/haier_base.cpp b/esphome/components/haier/haier_base.cpp index 1fca3dfb85..0bd3863160 100644 --- a/esphome/components/haier/haier_base.cpp +++ b/esphome/components/haier/haier_base.cpp @@ -186,6 +186,10 @@ 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 &&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 f261a106a2..c0bf878519 100644 --- a/esphome/components/haier/haier_base.h +++ b/esphome/components/haier/haier_base.h @@ -4,6 +4,7 @@ #include #include "esphome/components/climate/climate.h" #include "esphome/components/uart/uart.h" +#include "esphome/core/automation.h" // HaierProtocol #include @@ -56,6 +57,7 @@ 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 &&callback); protected: enum class ProtocolPhases { @@ -140,11 +142,19 @@ class HaierClimateBase : public esphome::Component, esphome::climate::ClimateTraits traits_; HvacSettings current_hvac_settings_; HvacSettings next_hvac_settings_; - std::unique_ptr last_status_message_; + std::unique_ptr last_status_message_{nullptr}; std::chrono::steady_clock::time_point last_request_timestamp_; // For interval between messages std::chrono::steady_clock::time_point last_valid_status_timestamp_; // For protocol timeout std::chrono::steady_clock::time_point last_status_request_; // To request AC status std::chrono::steady_clock::time_point last_signal_request_; // To send WiFI signal level + CallbackManager status_message_callback_{}; +}; + +class StatusMessageTrigger : public Trigger { + 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 diff --git a/esphome/components/haier/hon_climate.cpp b/esphome/components/haier/hon_climate.cpp index 903f7964da..a1c5098cec 100644 --- a/esphome/components/haier/hon_climate.cpp +++ b/esphome/components/haier/hon_climate.cpp @@ -18,12 +18,13 @@ constexpr int PROTOCOL_OUTDOOR_TEMPERATURE_OFFSET = -64; constexpr uint8_t CONTROL_MESSAGE_RETRIES = 5; constexpr std::chrono::milliseconds CONTROL_MESSAGE_RETRIES_INTERVAL = std::chrono::milliseconds(500); constexpr size_t ALARM_STATUS_REQUEST_INTERVAL_MS = 600000; +const uint8_t ONE_BUF[] = {0x00, 0x01}; +const uint8_t ZERO_BUF[] = {0x00, 0x00}; HonClimate::HonClimate() : cleaning_status_(CleaningState::NO_CLEANING), got_valid_outdoor_temp_(false), active_alarms_{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} { - last_status_message_ = std::unique_ptr(new uint8_t[sizeof(hon_protocol::HaierPacketControl)]); this->fan_mode_speed_ = (uint8_t) hon_protocol::FanMode::FAN_MID; this->other_modes_fan_speed_ = (uint8_t) hon_protocol::FanMode::FAN_AUTO; } @@ -169,11 +170,18 @@ haier_protocol::HandlerError HonClimate::status_handler_(haier_protocol::FrameTy this->action_request_.reset(); this->force_send_control_ = false; } else { - if (data_size >= sizeof(hon_protocol::HaierPacketControl) + 2) { - memcpy(this->last_status_message_.get(), data + 2, sizeof(hon_protocol::HaierPacketControl)); + if (!this->last_status_message_) { + this->real_control_packet_size_ = sizeof(hon_protocol::HaierPacketControl) + this->extra_control_packet_bytes_; + this->real_sensors_packet_size_ = sizeof(hon_protocol::HaierPacketSensors) + this->extra_sensors_packet_bytes_; + this->last_status_message_.reset(); + this->last_status_message_ = std::unique_ptr(new uint8_t[this->real_control_packet_size_]); + }; + if (data_size >= this->real_control_packet_size_ + 2) { + memcpy(this->last_status_message_.get(), data + 2 + this->status_message_header_size_, + this->real_control_packet_size_); + this->status_message_callback_.call((const char *) data, data_size); } else { - ESP_LOGW(TAG, "Status packet too small: %d (should be >= %d)", data_size, - sizeof(hon_protocol::HaierPacketControl)); + ESP_LOGW(TAG, "Status packet too small: %d (should be >= %d)", data_size, this->real_control_packet_size_); } switch (this->protocol_phase_) { case ProtocolPhases::SENDING_FIRST_STATUS_REQUEST: @@ -479,8 +487,8 @@ void HonClimate::initialization() { } haier_protocol::HaierMessage HonClimate::get_control_message() { - uint8_t control_out_buffer[sizeof(hon_protocol::HaierPacketControl)]; - memcpy(control_out_buffer, this->last_status_message_.get(), sizeof(hon_protocol::HaierPacketControl)); + uint8_t control_out_buffer[haier_protocol::MAX_FRAME_SIZE]; + memcpy(control_out_buffer, this->last_status_message_.get(), this->real_control_packet_size_); hon_protocol::HaierPacketControl *out_data = (hon_protocol::HaierPacketControl *) control_out_buffer; control_out_buffer[4] = 0; // This byte should be cleared before setting values bool has_hvac_settings = false; @@ -636,7 +644,7 @@ haier_protocol::HaierMessage HonClimate::get_control_message() { out_data->health_mode = this->health_mode_ ? 1 : 0; return haier_protocol::HaierMessage(haier_protocol::FrameType::CONTROL, (uint16_t) hon_protocol::SubcommandsControl::SET_GROUP_PARAMETERS, - control_out_buffer, sizeof(hon_protocol::HaierPacketControl)); + control_out_buffer, this->real_control_packet_size_); } void HonClimate::process_alarm_message_(const uint8_t *packet, uint8_t size, bool check_new) { @@ -758,15 +766,17 @@ void HonClimate::update_sub_text_sensor_(SubTextSensorType type, const std::stri #endif // USE_TEXT_SENSOR haier_protocol::HandlerError HonClimate::process_status_message_(const uint8_t *packet_buffer, uint8_t size) { - size_t expected_size = 2 + sizeof(hon_protocol::HaierPacketControl) + sizeof(hon_protocol::HaierPacketSensors) + - this->extra_control_packet_bytes_; - if (size < expected_size) + size_t expected_size = + 2 + this->status_message_header_size_ + this->real_control_packet_size_ + this->real_sensors_packet_size_; + if (size < expected_size) { + ESP_LOGW(TAG, "Unexpected message size %d (expexted >= %d)", size, expected_size); return haier_protocol::HandlerError::WRONG_MESSAGE_STRUCTURE; + } uint16_t subtype = (((uint16_t) packet_buffer[0]) << 8) + packet_buffer[1]; - if ((subtype == 0x7D01) && (size >= expected_size + 4 + sizeof(hon_protocol::HaierPacketBigData))) { + if ((subtype == 0x7D01) && (size >= expected_size + sizeof(hon_protocol::HaierPacketBigData))) { // Got BigData packet const hon_protocol::HaierPacketBigData *bd_packet = - (const hon_protocol::HaierPacketBigData *) (&packet_buffer[expected_size + 4]); + (const hon_protocol::HaierPacketBigData *) (&packet_buffer[expected_size]); #ifdef USE_SENSOR this->update_sub_sensor_(SubSensorType::INDOOR_COIL_TEMPERATURE, bd_packet->indoor_coil_temperature / 2.0 - 20); this->update_sub_sensor_(SubSensorType::OUTDOOR_COIL_TEMPERATURE, bd_packet->outdoor_coil_temperature - 64); @@ -795,9 +805,9 @@ haier_protocol::HandlerError HonClimate::process_status_message_(const uint8_t * hon_protocol::HaierPacketControl control; hon_protocol::HaierPacketSensors sensors; } packet; - memcpy(&packet.control, packet_buffer + 2, sizeof(hon_protocol::HaierPacketControl)); - memcpy(&packet.sensors, - packet_buffer + 2 + sizeof(hon_protocol::HaierPacketControl) + this->extra_control_packet_bytes_, + memcpy(&packet.control, packet_buffer + 2 + this->status_message_header_size_, + sizeof(hon_protocol::HaierPacketControl)); + memcpy(&packet.sensors, packet_buffer + 2 + this->status_message_header_size_ + this->real_control_packet_size_, sizeof(hon_protocol::HaierPacketSensors)); if (packet.sensors.error_status != 0) { ESP_LOGW(TAG, "HVAC error, code=0x%02X", packet.sensors.error_status); @@ -996,8 +1006,6 @@ haier_protocol::HandlerError HonClimate::process_status_message_(const uint8_t * } void HonClimate::fill_control_messages_queue_() { - static uint8_t one_buf[] = {0x00, 0x01}; - static uint8_t zero_buf[] = {0x00, 0x00}; if (!this->current_hvac_settings_.valid && !this->force_send_control_) return; this->clear_control_messages_queue_(); @@ -1009,7 +1017,7 @@ void HonClimate::fill_control_messages_queue_() { haier_protocol::HaierMessage(haier_protocol::FrameType::CONTROL, (uint16_t) hon_protocol::SubcommandsControl::SET_SINGLE_PARAMETER + (uint8_t) hon_protocol::DataParameters::BEEPER_STATUS, - this->beeper_status_ ? zero_buf : one_buf, 2)); + this->beeper_status_ ? ZERO_BUF : ONE_BUF, 2)); } // Health mode { @@ -1017,7 +1025,7 @@ void HonClimate::fill_control_messages_queue_() { haier_protocol::HaierMessage(haier_protocol::FrameType::CONTROL, (uint16_t) hon_protocol::SubcommandsControl::SET_SINGLE_PARAMETER + (uint8_t) hon_protocol::DataParameters::HEALTH_MODE, - this->health_mode_ ? one_buf : zero_buf, 2)); + this->health_mode_ ? ONE_BUF : ZERO_BUF, 2)); } // Climate mode bool new_power = this->mode != CLIMATE_MODE_OFF; @@ -1092,7 +1100,7 @@ void HonClimate::fill_control_messages_queue_() { haier_protocol::HaierMessage(haier_protocol::FrameType::CONTROL, (uint16_t) hon_protocol::SubcommandsControl::SET_SINGLE_PARAMETER + (uint8_t) hon_protocol::DataParameters::AC_POWER, - new_power ? one_buf : zero_buf, 2)); + new_power ? ONE_BUF : ZERO_BUF, 2)); } // CLimate preset { @@ -1165,6 +1173,35 @@ void HonClimate::fill_control_messages_queue_() { (uint8_t) hon_protocol::DataParameters::SET_POINT, buffer, 2)); } + // Vertical swing mode + if (climate_control.swing_mode.has_value()) { + uint8_t vertical_swing_buf[] = {0x00, (uint8_t) hon_protocol::VerticalSwingMode::AUTO}; + uint8_t horizontal_swing_buf[] = {0x00, (uint8_t) hon_protocol::HorizontalSwingMode::AUTO}; + switch (climate_control.swing_mode.value()) { + case CLIMATE_SWING_OFF: + horizontal_swing_buf[1] = (uint8_t) this->settings_.last_horizontal_swing; + vertical_swing_buf[1] = (uint8_t) this->settings_.last_vertiacal_swing; + break; + case CLIMATE_SWING_VERTICAL: + horizontal_swing_buf[1] = (uint8_t) this->settings_.last_horizontal_swing; + break; + case CLIMATE_SWING_HORIZONTAL: + vertical_swing_buf[1] = (uint8_t) this->settings_.last_vertiacal_swing; + break; + case CLIMATE_SWING_BOTH: + break; + } + this->control_messages_queue_.push( + haier_protocol::HaierMessage(haier_protocol::FrameType::CONTROL, + (uint16_t) hon_protocol::SubcommandsControl::SET_SINGLE_PARAMETER + + (uint8_t) hon_protocol::DataParameters::HORIZONTAL_SWING_MODE, + horizontal_swing_buf, 2)); + this->control_messages_queue_.push( + haier_protocol::HaierMessage(haier_protocol::FrameType::CONTROL, + (uint16_t) hon_protocol::SubcommandsControl::SET_SINGLE_PARAMETER + + (uint8_t) hon_protocol::DataParameters::VERTICAL_SWING_MODE, + vertical_swing_buf, 2)); + } // Fan mode if (climate_control.fan_mode.has_value()) { switch (climate_control.fan_mode.value()) { @@ -1202,40 +1239,56 @@ void HonClimate::clear_control_messages_queue_() { bool HonClimate::prepare_pending_action() { switch (this->action_request_.value().action) { - case ActionRequest::START_SELF_CLEAN: { - uint8_t control_out_buffer[sizeof(hon_protocol::HaierPacketControl)]; - memcpy(control_out_buffer, this->last_status_message_.get(), sizeof(hon_protocol::HaierPacketControl)); - hon_protocol::HaierPacketControl *out_data = (hon_protocol::HaierPacketControl *) control_out_buffer; - out_data->self_cleaning_status = 1; - out_data->steri_clean = 0; - out_data->set_point = 0x06; - out_data->vertical_swing_mode = (uint8_t) hon_protocol::VerticalSwingMode::CENTER; - out_data->horizontal_swing_mode = (uint8_t) hon_protocol::HorizontalSwingMode::CENTER; - 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( - haier_protocol::FrameType::CONTROL, (uint16_t) hon_protocol::SubcommandsControl::SET_GROUP_PARAMETERS, - control_out_buffer, sizeof(hon_protocol::HaierPacketControl)); - } - return true; - case ActionRequest::START_STERI_CLEAN: { - uint8_t control_out_buffer[sizeof(hon_protocol::HaierPacketControl)]; - memcpy(control_out_buffer, this->last_status_message_.get(), sizeof(hon_protocol::HaierPacketControl)); - hon_protocol::HaierPacketControl *out_data = (hon_protocol::HaierPacketControl *) control_out_buffer; - out_data->self_cleaning_status = 0; - out_data->steri_clean = 1; - out_data->set_point = 0x06; - out_data->vertical_swing_mode = (uint8_t) hon_protocol::VerticalSwingMode::CENTER; - out_data->horizontal_swing_mode = (uint8_t) hon_protocol::HorizontalSwingMode::CENTER; - 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( - haier_protocol::FrameType::CONTROL, (uint16_t) hon_protocol::SubcommandsControl::SET_GROUP_PARAMETERS, - control_out_buffer, sizeof(hon_protocol::HaierPacketControl)); - } - return true; + case ActionRequest::START_SELF_CLEAN: + if (this->control_method_ == HonControlMethod::SET_GROUP_PARAMETERS) { + uint8_t control_out_buffer[haier_protocol::MAX_FRAME_SIZE]; + memcpy(control_out_buffer, this->last_status_message_.get(), this->real_control_packet_size_); + hon_protocol::HaierPacketControl *out_data = (hon_protocol::HaierPacketControl *) control_out_buffer; + out_data->self_cleaning_status = 1; + out_data->steri_clean = 0; + out_data->set_point = 0x06; + out_data->vertical_swing_mode = (uint8_t) hon_protocol::VerticalSwingMode::CENTER; + out_data->horizontal_swing_mode = (uint8_t) hon_protocol::HorizontalSwingMode::CENTER; + 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( + 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 = + haier_protocol::HaierMessage(haier_protocol::FrameType::CONTROL, + (uint16_t) hon_protocol::SubcommandsControl::SET_SINGLE_PARAMETER + + (uint8_t) hon_protocol::DataParameters::SELF_CLEANING, + ONE_BUF, 2); + return true; + } else { + this->action_request_.reset(); + return false; + } + case ActionRequest::START_STERI_CLEAN: + if (this->control_method_ == HonControlMethod::SET_GROUP_PARAMETERS) { + uint8_t control_out_buffer[haier_protocol::MAX_FRAME_SIZE]; + memcpy(control_out_buffer, this->last_status_message_.get(), this->real_control_packet_size_); + hon_protocol::HaierPacketControl *out_data = (hon_protocol::HaierPacketControl *) control_out_buffer; + out_data->self_cleaning_status = 0; + out_data->steri_clean = 1; + out_data->set_point = 0x06; + out_data->vertical_swing_mode = (uint8_t) hon_protocol::VerticalSwingMode::CENTER; + out_data->horizontal_swing_mode = (uint8_t) hon_protocol::HorizontalSwingMode::CENTER; + 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( + haier_protocol::FrameType::CONTROL, (uint16_t) hon_protocol::SubcommandsControl::SET_GROUP_PARAMETERS, + control_out_buffer, this->real_control_packet_size_); + return true; + } else { + // No Steri clean support (yet?) in SET_SINGLE_PARAMETER + this->action_request_.reset(); + return false; + } default: return HaierClimateBase::prepare_pending_action(); } @@ -1251,6 +1304,7 @@ void HonClimate::process_protocol_reset() { #endif // USE_SENSOR this->got_valid_outdoor_temp_ = false; this->hvac_hardware_info_.reset(); + this->last_status_message_.reset(nullptr); } bool HonClimate::should_get_big_data_() { diff --git a/esphome/components/haier/hon_climate.h b/esphome/components/haier/hon_climate.h index 7b4fcee6b9..64c54186ed 100644 --- a/esphome/components/haier/hon_climate.h +++ b/esphome/components/haier/hon_climate.h @@ -104,6 +104,8 @@ class HonClimate : public HaierClimateBase { void start_self_cleaning(); void start_steri_cleaning(); void set_extra_control_packet_bytes_size(size_t size) { this->extra_control_packet_bytes_ = size; }; + 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 &&callback); void add_alarm_end_callback(std::function &&callback); @@ -158,7 +160,11 @@ class HonClimate : public HaierClimateBase { esphome::optional pending_horizontal_direction_{}; esphome::optional hvac_hardware_info_{}; uint8_t active_alarms_[8]; - int extra_control_packet_bytes_; + int extra_control_packet_bytes_{0}; + int extra_sensors_packet_bytes_{4}; + int status_message_header_size_{0}; + int real_control_packet_size_{sizeof(hon_protocol::HaierPacketControl)}; + int real_sensors_packet_size_{sizeof(hon_protocol::HaierPacketSensors) + 4}; HonControlMethod control_method_; std::queue control_messages_queue_; CallbackManager alarm_start_callback_{}; diff --git a/esphome/components/haier/hon_packet.h b/esphome/components/haier/hon_packet.h index a03ac2831f..615f93528e 100644 --- a/esphome/components/haier/hon_packet.h +++ b/esphome/components/haier/hon_packet.h @@ -41,15 +41,20 @@ enum class ConditioningMode : uint8_t { enum class DataParameters : uint8_t { AC_POWER = 0x01, SET_POINT = 0x02, + VERTICAL_SWING_MODE = 0x03, AC_MODE = 0x04, FAN_MODE = 0x05, USE_FAHRENHEIT = 0x07, + DISPLAY_STATUS = 0x09, TEN_DEGREE = 0x0A, HEALTH_MODE = 0x0B, + HORIZONTAL_SWING_MODE = 0x0C, + SELF_CLEANING = 0x0D, BEEPER_STATUS = 0x16, LOCK_REMOTE = 0x17, QUIET_MODE = 0x19, FAST_MODE = 0x1A, + SLEEP_MODE = 0x1B, }; enum class SpecialMode : uint8_t { NONE = 0x00, ELDERLY = 0x01, CHILDREN = 0x02, PREGNANT = 0x03 }; diff --git a/esphome/components/haier/smartair2_climate.cpp b/esphome/components/haier/smartair2_climate.cpp index 00590694d5..028e8a4087 100644 --- a/esphome/components/haier/smartair2_climate.cpp +++ b/esphome/components/haier/smartair2_climate.cpp @@ -37,6 +37,7 @@ haier_protocol::HandlerError Smartair2Climate::status_handler_(haier_protocol::F } else { if (data_size >= sizeof(smartair2_protocol::HaierPacketControl) + 2) { memcpy(this->last_status_message_.get(), data + 2, sizeof(smartair2_protocol::HaierPacketControl)); + this->status_message_callback_.call((const char *) data, data_size); } else { ESP_LOGW(TAG, "Status packet too small: %d (should be >= %d)", data_size, sizeof(smartair2_protocol::HaierPacketControl)); diff --git a/platformio.ini b/platformio.ini index aa73437222..a72bf598c5 100644 --- a/platformio.ini +++ b/platformio.ini @@ -39,7 +39,7 @@ lib_deps = bblanchon/ArduinoJson@6.18.5 ; json wjtje/qr-code-generator-library@1.7.0 ; qr_code functionpointer/arduino-MLX90393@1.0.0 ; mlx90393 - pavlodn/HaierProtocol@0.9.28 ; haier + pavlodn/HaierProtocol@0.9.31 ; haier ; 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 build_flags = diff --git a/tests/components/haier/common.yaml b/tests/components/haier/common.yaml new file mode 100644 index 0000000000..b8a23bac5a --- /dev/null +++ b/tests/components/haier/common.yaml @@ -0,0 +1,114 @@ +wifi: + ssid: MySSID + password: password1 + +uart: + - id: uart_haier + tx_pin: ${tx_pin} + rx_pin: ${rx_pin} + baud_rate: 9600 + +climate: + - platform: haier + id: haier_ac + uart_id: uart_haier + protocol: hOn + name: Haier AC + wifi_signal: true + answer_timeout: 200ms + beeper: true + visual: + min_temperature: 16 °C + max_temperature: 30 °C + temperature_step: + target_temperature: 1 + current_temperature: 0.5 + supported_modes: + - 'OFF' + - HEAT_COOL + - COOL + - HEAT + - DRY + - FAN_ONLY + supported_swing_modes: + - 'OFF' + - VERTICAL + - HORIZONTAL + - BOTH + supported_presets: + - AWAY + - BOOST + - ECO + - SLEEP + on_alarm_start: + then: + - logger.log: + level: DEBUG + format: "Alarm activated. Code: %d. Message: \"%s\"" + args: [code, message] + on_alarm_end: + then: + - logger.log: + level: DEBUG + format: "Alarm deactivated. Code: %d. Message: \"%s\"" + args: [code, message] + +sensor: + - platform: haier + haier_id: haier_ac + outdoor_temperature: + name: Haier outdoor temperature + humidity: + name: Haier Indoor Humidity + compressor_current: + name: Haier Compressor Current + compressor_frequency: + name: Haier Compressor Frequency + expansion_valve_open_degree: + name: Haier Expansion Valve Open Degree + indoor_coil_temperature: + name: Haier Indoor Coil Temperature + outdoor_coil_temperature: + name: Haier Outdoor Coil Temperature + outdoor_defrost_temperature: + name: Haier Outdoor Defrost Temperature + outdoor_in_air_temperature: + name: Haier Outdoor In Air Temperature + outdoor_out_air_temperature: + name: Haier Outdoor Out Air Temperature + power: + name: Haier Power + +binary_sensor: + - platform: haier + haier_id: haier_ac + compressor_status: + name: Haier Outdoor Compressor Status + defrost_status: + name: Haier Defrost Status + four_way_valve_status: + name: Haier Four Way Valve Status + indoor_electric_heating_status: + name: Haier Indoor Electric Heating Status + indoor_fan_status: + name: Haier Indoor Fan Status + outdoor_fan_status: + name: Haier Outdoor Fan Status + +button: + - platform: haier + haier_id: haier_ac + self_cleaning: + name: Haier start self cleaning + steri_cleaning: + name: Haier start 56°C steri-cleaning + +text_sensor: + - platform: haier + haier_id: haier_ac + appliance_name: + name: Haier appliance name + cleaning_status: + name: Haier cleaning status + protocol_version: + name: Haier protocol version diff --git a/tests/components/haier/test.esp32-ard.yaml b/tests/components/haier/test.esp32-ard.yaml index efff532d25..f486544afa 100644 --- a/tests/components/haier/test.esp32-ard.yaml +++ b/tests/components/haier/test.esp32-ard.yaml @@ -1,113 +1,5 @@ -wifi: - ssid: MySSID - password: password1 +substitutions: + tx_pin: GPIO17 + rx_pin: GPIO16 -uart: - - id: uart_haier - tx_pin: 17 - rx_pin: 16 - baud_rate: 9600 - -climate: - - platform: haier - id: haier_ac - protocol: hOn - name: Haier AC - wifi_signal: true - answer_timeout: 200ms - beeper: true - visual: - min_temperature: 16 °C - max_temperature: 30 °C - temperature_step: - target_temperature: 1 - current_temperature: 0.5 - supported_modes: - - 'OFF' - - HEAT_COOL - - COOL - - HEAT - - DRY - - FAN_ONLY - supported_swing_modes: - - 'OFF' - - VERTICAL - - HORIZONTAL - - BOTH - supported_presets: - - AWAY - - BOOST - - ECO - - SLEEP - on_alarm_start: - then: - - logger.log: - level: DEBUG - format: "Alarm activated. Code: %d. Message: \"%s\"" - args: [code, message] - on_alarm_end: - then: - - logger.log: - level: DEBUG - format: "Alarm deactivated. Code: %d. Message: \"%s\"" - args: [code, message] - -sensor: - - platform: haier - haier_id: haier_ac - outdoor_temperature: - name: Haier outdoor temperature - humidity: - name: Haier Indoor Humidity - compressor_current: - name: Haier Compressor Current - compressor_frequency: - name: Haier Compressor Frequency - expansion_valve_open_degree: - name: Haier Expansion Valve Open Degree - indoor_coil_temperature: - name: Haier Indoor Coil Temperature - outdoor_coil_temperature: - name: Haier Outdoor Coil Temperature - outdoor_defrost_temperature: - name: Haier Outdoor Defrost Temperature - outdoor_in_air_temperature: - name: Haier Outdoor In Air Temperature - outdoor_out_air_temperature: - name: Haier Outdoor Out Air Temperature - power: - name: Haier Power - -binary_sensor: - - platform: haier - haier_id: haier_ac - compressor_status: - name: Haier Outdoor Compressor Status - defrost_status: - name: Haier Defrost Status - four_way_valve_status: - name: Haier Four Way Valve Status - indoor_electric_heating_status: - name: Haier Indoor Electric Heating Status - indoor_fan_status: - name: Haier Indoor Fan Status - outdoor_fan_status: - name: Haier Outdoor Fan Status - -button: - - platform: haier - haier_id: haier_ac - self_cleaning: - name: Haier start self cleaning - steri_cleaning: - name: Haier start 56°C steri-cleaning - -text_sensor: - - platform: haier - haier_id: haier_ac - appliance_name: - name: Haier appliance name - cleaning_status: - name: Haier cleaning status - protocol_version: - name: Haier protocol version +<<: !include common.yaml diff --git a/tests/components/haier/test.esp32-c3-ard.yaml b/tests/components/haier/test.esp32-c3-ard.yaml index 0053220669..b516342f3b 100644 --- a/tests/components/haier/test.esp32-c3-ard.yaml +++ b/tests/components/haier/test.esp32-c3-ard.yaml @@ -1,109 +1,5 @@ -wifi: - ssid: MySSID - password: password1 +substitutions: + tx_pin: GPIO4 + rx_pin: GPIO5 -uart: - - id: uart_haier - tx_pin: 4 - rx_pin: 5 - baud_rate: 9600 - -climate: - - platform: haier - id: haier_ac - protocol: hOn - name: Haier AC - wifi_signal: true - answer_timeout: 200ms - beeper: true - visual: - min_temperature: 16 °C - max_temperature: 30 °C - temperature_step: - target_temperature: 1 - current_temperature: 0.5 - supported_modes: - - 'OFF' - - HEAT_COOL - - COOL - - HEAT - - DRY - - FAN_ONLY - supported_swing_modes: - - 'OFF' - - VERTICAL - - HORIZONTAL - - BOTH - supported_presets: - - AWAY - - BOOST - - ECO - - SLEEP - on_alarm_start: - then: - - logger.log: - level: DEBUG - format: "Alarm activated. Code: %d. Message: \"%s\"" - args: [code, message] - on_alarm_end: - then: - - logger.log: - level: DEBUG - format: "Alarm deactivated. Code: %d. Message: \"%s\"" - args: [code, message] - -sensor: - - platform: haier - outdoor_temperature: - name: Haier outdoor temperature - humidity: - name: Haier Indoor Humidity - compressor_current: - name: Haier Compressor Current - compressor_frequency: - name: Haier Compressor Frequency - expansion_valve_open_degree: - name: Haier Expansion Valve Open Degree - indoor_coil_temperature: - name: Haier Indoor Coil Temperature - outdoor_coil_temperature: - name: Haier Outdoor Coil Temperature - outdoor_defrost_temperature: - name: Haier Outdoor Defrost Temperature - outdoor_in_air_temperature: - name: Haier Outdoor In Air Temperature - outdoor_out_air_temperature: - name: Haier Outdoor Out Air Temperature - power: - name: Haier Power - -binary_sensor: - - platform: haier - compressor_status: - name: Haier Outdoor Compressor Status - defrost_status: - name: Haier Defrost Status - four_way_valve_status: - name: Haier Four Way Valve Status - indoor_electric_heating_status: - name: Haier Indoor Electric Heating Status - indoor_fan_status: - name: Haier Indoor Fan Status - outdoor_fan_status: - name: Haier Outdoor Fan Status - -button: - - platform: haier - self_cleaning: - name: Haier start self cleaning - steri_cleaning: - name: Haier start 56°C steri-cleaning - -text_sensor: - - platform: haier - appliance_name: - name: Haier appliance name - cleaning_status: - name: Haier cleaning status - protocol_version: - name: Haier protocol version +<<: !include common.yaml diff --git a/tests/components/haier/test.esp32-c3-idf.yaml b/tests/components/haier/test.esp32-c3-idf.yaml index 0053220669..b516342f3b 100644 --- a/tests/components/haier/test.esp32-c3-idf.yaml +++ b/tests/components/haier/test.esp32-c3-idf.yaml @@ -1,109 +1,5 @@ -wifi: - ssid: MySSID - password: password1 +substitutions: + tx_pin: GPIO4 + rx_pin: GPIO5 -uart: - - id: uart_haier - tx_pin: 4 - rx_pin: 5 - baud_rate: 9600 - -climate: - - platform: haier - id: haier_ac - protocol: hOn - name: Haier AC - wifi_signal: true - answer_timeout: 200ms - beeper: true - visual: - min_temperature: 16 °C - max_temperature: 30 °C - temperature_step: - target_temperature: 1 - current_temperature: 0.5 - supported_modes: - - 'OFF' - - HEAT_COOL - - COOL - - HEAT - - DRY - - FAN_ONLY - supported_swing_modes: - - 'OFF' - - VERTICAL - - HORIZONTAL - - BOTH - supported_presets: - - AWAY - - BOOST - - ECO - - SLEEP - on_alarm_start: - then: - - logger.log: - level: DEBUG - format: "Alarm activated. Code: %d. Message: \"%s\"" - args: [code, message] - on_alarm_end: - then: - - logger.log: - level: DEBUG - format: "Alarm deactivated. Code: %d. Message: \"%s\"" - args: [code, message] - -sensor: - - platform: haier - outdoor_temperature: - name: Haier outdoor temperature - humidity: - name: Haier Indoor Humidity - compressor_current: - name: Haier Compressor Current - compressor_frequency: - name: Haier Compressor Frequency - expansion_valve_open_degree: - name: Haier Expansion Valve Open Degree - indoor_coil_temperature: - name: Haier Indoor Coil Temperature - outdoor_coil_temperature: - name: Haier Outdoor Coil Temperature - outdoor_defrost_temperature: - name: Haier Outdoor Defrost Temperature - outdoor_in_air_temperature: - name: Haier Outdoor In Air Temperature - outdoor_out_air_temperature: - name: Haier Outdoor Out Air Temperature - power: - name: Haier Power - -binary_sensor: - - platform: haier - compressor_status: - name: Haier Outdoor Compressor Status - defrost_status: - name: Haier Defrost Status - four_way_valve_status: - name: Haier Four Way Valve Status - indoor_electric_heating_status: - name: Haier Indoor Electric Heating Status - indoor_fan_status: - name: Haier Indoor Fan Status - outdoor_fan_status: - name: Haier Outdoor Fan Status - -button: - - platform: haier - self_cleaning: - name: Haier start self cleaning - steri_cleaning: - name: Haier start 56°C steri-cleaning - -text_sensor: - - platform: haier - appliance_name: - name: Haier appliance name - cleaning_status: - name: Haier cleaning status - protocol_version: - name: Haier protocol version +<<: !include common.yaml diff --git a/tests/components/haier/test.esp32-idf.yaml b/tests/components/haier/test.esp32-idf.yaml index 54e384f3ce..f486544afa 100644 --- a/tests/components/haier/test.esp32-idf.yaml +++ b/tests/components/haier/test.esp32-idf.yaml @@ -1,109 +1,5 @@ -wifi: - ssid: MySSID - password: password1 +substitutions: + tx_pin: GPIO17 + rx_pin: GPIO16 -uart: - - id: uart_haier - tx_pin: 17 - rx_pin: 16 - baud_rate: 9600 - -climate: - - platform: haier - id: haier_ac - protocol: hOn - name: Haier AC - wifi_signal: true - answer_timeout: 200ms - beeper: true - visual: - min_temperature: 16 °C - max_temperature: 30 °C - temperature_step: - target_temperature: 1 - current_temperature: 0.5 - supported_modes: - - 'OFF' - - HEAT_COOL - - COOL - - HEAT - - DRY - - FAN_ONLY - supported_swing_modes: - - 'OFF' - - VERTICAL - - HORIZONTAL - - BOTH - supported_presets: - - AWAY - - BOOST - - ECO - - SLEEP - on_alarm_start: - then: - - logger.log: - level: DEBUG - format: "Alarm activated. Code: %d. Message: \"%s\"" - args: [code, message] - on_alarm_end: - then: - - logger.log: - level: DEBUG - format: "Alarm deactivated. Code: %d. Message: \"%s\"" - args: [code, message] - -sensor: - - platform: haier - outdoor_temperature: - name: Haier outdoor temperature - humidity: - name: Haier Indoor Humidity - compressor_current: - name: Haier Compressor Current - compressor_frequency: - name: Haier Compressor Frequency - expansion_valve_open_degree: - name: Haier Expansion Valve Open Degree - indoor_coil_temperature: - name: Haier Indoor Coil Temperature - outdoor_coil_temperature: - name: Haier Outdoor Coil Temperature - outdoor_defrost_temperature: - name: Haier Outdoor Defrost Temperature - outdoor_in_air_temperature: - name: Haier Outdoor In Air Temperature - outdoor_out_air_temperature: - name: Haier Outdoor Out Air Temperature - power: - name: Haier Power - -binary_sensor: - - platform: haier - compressor_status: - name: Haier Outdoor Compressor Status - defrost_status: - name: Haier Defrost Status - four_way_valve_status: - name: Haier Four Way Valve Status - indoor_electric_heating_status: - name: Haier Indoor Electric Heating Status - indoor_fan_status: - name: Haier Indoor Fan Status - outdoor_fan_status: - name: Haier Outdoor Fan Status - -button: - - platform: haier - self_cleaning: - name: Haier start self cleaning - steri_cleaning: - name: Haier start 56°C steri-cleaning - -text_sensor: - - platform: haier - appliance_name: - name: Haier appliance name - cleaning_status: - name: Haier cleaning status - protocol_version: - name: Haier protocol version +<<: !include common.yaml diff --git a/tests/components/haier/test.esp8266-ard.yaml b/tests/components/haier/test.esp8266-ard.yaml index 0053220669..b516342f3b 100644 --- a/tests/components/haier/test.esp8266-ard.yaml +++ b/tests/components/haier/test.esp8266-ard.yaml @@ -1,109 +1,5 @@ -wifi: - ssid: MySSID - password: password1 +substitutions: + tx_pin: GPIO4 + rx_pin: GPIO5 -uart: - - id: uart_haier - tx_pin: 4 - rx_pin: 5 - baud_rate: 9600 - -climate: - - platform: haier - id: haier_ac - protocol: hOn - name: Haier AC - wifi_signal: true - answer_timeout: 200ms - beeper: true - visual: - min_temperature: 16 °C - max_temperature: 30 °C - temperature_step: - target_temperature: 1 - current_temperature: 0.5 - supported_modes: - - 'OFF' - - HEAT_COOL - - COOL - - HEAT - - DRY - - FAN_ONLY - supported_swing_modes: - - 'OFF' - - VERTICAL - - HORIZONTAL - - BOTH - supported_presets: - - AWAY - - BOOST - - ECO - - SLEEP - on_alarm_start: - then: - - logger.log: - level: DEBUG - format: "Alarm activated. Code: %d. Message: \"%s\"" - args: [code, message] - on_alarm_end: - then: - - logger.log: - level: DEBUG - format: "Alarm deactivated. Code: %d. Message: \"%s\"" - args: [code, message] - -sensor: - - platform: haier - outdoor_temperature: - name: Haier outdoor temperature - humidity: - name: Haier Indoor Humidity - compressor_current: - name: Haier Compressor Current - compressor_frequency: - name: Haier Compressor Frequency - expansion_valve_open_degree: - name: Haier Expansion Valve Open Degree - indoor_coil_temperature: - name: Haier Indoor Coil Temperature - outdoor_coil_temperature: - name: Haier Outdoor Coil Temperature - outdoor_defrost_temperature: - name: Haier Outdoor Defrost Temperature - outdoor_in_air_temperature: - name: Haier Outdoor In Air Temperature - outdoor_out_air_temperature: - name: Haier Outdoor Out Air Temperature - power: - name: Haier Power - -binary_sensor: - - platform: haier - compressor_status: - name: Haier Outdoor Compressor Status - defrost_status: - name: Haier Defrost Status - four_way_valve_status: - name: Haier Four Way Valve Status - indoor_electric_heating_status: - name: Haier Indoor Electric Heating Status - indoor_fan_status: - name: Haier Indoor Fan Status - outdoor_fan_status: - name: Haier Outdoor Fan Status - -button: - - platform: haier - self_cleaning: - name: Haier start self cleaning - steri_cleaning: - name: Haier start 56°C steri-cleaning - -text_sensor: - - platform: haier - appliance_name: - name: Haier appliance name - cleaning_status: - name: Haier cleaning status - protocol_version: - name: Haier protocol version +<<: !include common.yaml diff --git a/tests/components/haier/test.rp2040-ard.yaml b/tests/components/haier/test.rp2040-ard.yaml index 0053220669..b516342f3b 100644 --- a/tests/components/haier/test.rp2040-ard.yaml +++ b/tests/components/haier/test.rp2040-ard.yaml @@ -1,109 +1,5 @@ -wifi: - ssid: MySSID - password: password1 +substitutions: + tx_pin: GPIO4 + rx_pin: GPIO5 -uart: - - id: uart_haier - tx_pin: 4 - rx_pin: 5 - baud_rate: 9600 - -climate: - - platform: haier - id: haier_ac - protocol: hOn - name: Haier AC - wifi_signal: true - answer_timeout: 200ms - beeper: true - visual: - min_temperature: 16 °C - max_temperature: 30 °C - temperature_step: - target_temperature: 1 - current_temperature: 0.5 - supported_modes: - - 'OFF' - - HEAT_COOL - - COOL - - HEAT - - DRY - - FAN_ONLY - supported_swing_modes: - - 'OFF' - - VERTICAL - - HORIZONTAL - - BOTH - supported_presets: - - AWAY - - BOOST - - ECO - - SLEEP - on_alarm_start: - then: - - logger.log: - level: DEBUG - format: "Alarm activated. Code: %d. Message: \"%s\"" - args: [code, message] - on_alarm_end: - then: - - logger.log: - level: DEBUG - format: "Alarm deactivated. Code: %d. Message: \"%s\"" - args: [code, message] - -sensor: - - platform: haier - outdoor_temperature: - name: Haier outdoor temperature - humidity: - name: Haier Indoor Humidity - compressor_current: - name: Haier Compressor Current - compressor_frequency: - name: Haier Compressor Frequency - expansion_valve_open_degree: - name: Haier Expansion Valve Open Degree - indoor_coil_temperature: - name: Haier Indoor Coil Temperature - outdoor_coil_temperature: - name: Haier Outdoor Coil Temperature - outdoor_defrost_temperature: - name: Haier Outdoor Defrost Temperature - outdoor_in_air_temperature: - name: Haier Outdoor In Air Temperature - outdoor_out_air_temperature: - name: Haier Outdoor Out Air Temperature - power: - name: Haier Power - -binary_sensor: - - platform: haier - compressor_status: - name: Haier Outdoor Compressor Status - defrost_status: - name: Haier Defrost Status - four_way_valve_status: - name: Haier Four Way Valve Status - indoor_electric_heating_status: - name: Haier Indoor Electric Heating Status - indoor_fan_status: - name: Haier Indoor Fan Status - outdoor_fan_status: - name: Haier Outdoor Fan Status - -button: - - platform: haier - self_cleaning: - name: Haier start self cleaning - steri_cleaning: - name: Haier start 56°C steri-cleaning - -text_sensor: - - platform: haier - appliance_name: - name: Haier appliance name - cleaning_status: - name: Haier cleaning status - protocol_version: - name: Haier protocol version +<<: !include common.yaml From 4c6a17e304002b741388335db30c06725a6730c6 Mon Sep 17 00:00:00 2001 From: Colm Date: Sat, 6 Jul 2024 08:02:41 +0100 Subject: [PATCH 1728/2101] Don't test for IPv6 addresses when min_ipv6_addr_count is 0 (#7037) --- esphome/components/wifi/wifi_component_esp_idf.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index c21486fee4..96fa837767 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -757,7 +757,7 @@ void WiFiComponent::wifi_process_event_(IDFWiFiEvent *data) { WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() { if (s_sta_connected && this->got_ipv4_address_) { -#if USE_NETWORK_IPV6 +#if USE_NETWORK_IPV6 && (USE_NETWORK_MIN_IPV6_ADDR_COUNT > 0) if (this->num_ipv6_addresses_ >= USE_NETWORK_MIN_IPV6_ADDR_COUNT) { return WiFiSTAConnectStatus::CONNECTED; } From 894d81c57767444425c15e340fec292b3341aacb Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Tue, 9 Jul 2024 04:07:54 +0200 Subject: [PATCH 1729/2101] [CI] Allow running specific target test(s) only (#7051) --- script/test_build_components | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/script/test_build_components b/script/test_build_components index 9bbb694dcc..e885294b99 100755 --- a/script/test_build_components +++ b/script/test_build_components @@ -7,12 +7,13 @@ set -e # - `c` - Component folder name to test. Default `*`. esphome_command="compile" target_component="*" -while getopts e:c: flag +while getopts e:c:t: flag do case $flag in e) esphome_command=${OPTARG};; c) target_component=${OPTARG};; - \?) echo "Usage: $0 [-e ] [-c ]" 1>&2; exit 1;; + t) requested_target_platform=${OPTARG};; + \?) echo "Usage: $0 [-e ] [-c ] [-t ]" 1>&2; exit 1;; esac done @@ -23,6 +24,10 @@ if ! [ -d "./tests/test_build_components/build" ]; then fi start_esphome() { + if [ -n "$requested_target_platform" ] && [ "$requested_target_platform" != "$target_platform" ]; then + echo "Skiping $target_platform" + return + fi # create dynamic yaml file in `build` folder. # `./tests/test_build_components/build/[target_component].[test_name].[target_platform_with_version].yaml` component_test_file="./tests/test_build_components/build/$target_component.$test_name.$target_platform_with_version.yaml" From ee398441b664722d9af67699035af5fd38b6ab28 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 10 Jul 2024 23:21:11 +0200 Subject: [PATCH 1730/2101] Bump actions/setup-python from 5.1.0 to 5.1.1 in /.github/actions/restore-python (#7071) 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 4ad9e2eaed..d3fe2a89dc 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@v5.1.0 + uses: actions/setup-python@v5.1.1 with: python-version: ${{ inputs.python-version }} - name: Restore Python virtual environment From 2da939c81c1ec506eb96010a101e6263060f9a1c Mon Sep 17 00:00:00 2001 From: MichD Date: Wed, 10 Jul 2024 23:37:50 +0100 Subject: [PATCH 1731/2101] Fix RC Switch protocol not transmitting correctly via IR (#5411) --- esphome/components/remote_base/rc_switch_protocol.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/remote_base/rc_switch_protocol.cpp b/esphome/components/remote_base/rc_switch_protocol.cpp index 1f38fdca67..cb8a077975 100644 --- a/esphome/components/remote_base/rc_switch_protocol.cpp +++ b/esphome/components/remote_base/rc_switch_protocol.cpp @@ -54,7 +54,7 @@ void RCSwitchBase::sync(RemoteTransmitData *dst) const { } } void RCSwitchBase::transmit(RemoteTransmitData *dst, uint64_t code, uint8_t len) const { - dst->set_carrier_frequency(0); + dst->set_carrier_frequency(38000); this->sync(dst); for (int16_t i = len - 1; i >= 0; i--) { if (code & ((uint64_t) 1 << i)) { From 2873c6bbaffc22383f870dc5203f4246279c709e Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt Date: Wed, 10 Jul 2024 21:21:04 -0400 Subject: [PATCH 1732/2101] [micro_wake_word] Version 2 (#7032) --- .../components/micro_wake_word/__init__.py | 262 +++++++-- .../audio_preprocessor_int8_model_data.h | 493 ----------------- .../micro_wake_word/micro_wake_word.cpp | 522 ++++++++---------- .../micro_wake_word/micro_wake_word.h | 190 +++---- .../micro_wake_word/preprocessor_settings.h | 20 + .../micro_wake_word/streaming_model.cpp | 189 +++++++ .../micro_wake_word/streaming_model.h | 84 +++ esphome/core/defines.h | 1 + platformio.ini | 3 +- tests/components/micro_wake_word/common.yaml | 6 +- .../micro_wake_word/test.esp32-idf.yaml | 1 + 11 files changed, 822 insertions(+), 949 deletions(-) delete mode 100644 esphome/components/micro_wake_word/audio_preprocessor_int8_model_data.h create mode 100644 esphome/components/micro_wake_word/preprocessor_settings.h create mode 100644 esphome/components/micro_wake_word/streaming_model.cpp create mode 100644 esphome/components/micro_wake_word/streaming_model.h create mode 100644 tests/components/micro_wake_word/test.esp32-idf.yaml diff --git a/esphome/components/micro_wake_word/__init__.py b/esphome/components/micro_wake_word/__init__.py index 35ee3cfedc..3d3459ccab 100644 --- a/esphome/components/micro_wake_word/__init__.py +++ b/esphome/components/micro_wake_word/__init__.py @@ -9,7 +9,7 @@ import requests import esphome.config_validation as cv import esphome.codegen as cg -from esphome.core import CORE, HexInt, EsphomeError +from esphome.core import CORE, HexInt from esphome.components import esp32, microphone from esphome import automation, git, external_files @@ -41,9 +41,15 @@ CODEOWNERS = ["@kahrendt", "@jesserockz"] DEPENDENCIES = ["microphone"] DOMAIN = "micro_wake_word" + +CONF_FEATURE_STEP_SIZE = "feature_step_size" +CONF_MODELS = "models" +CONF_ON_WAKE_WORD_DETECTED = "on_wake_word_detected" CONF_PROBABILITY_CUTOFF = "probability_cutoff" CONF_SLIDING_WINDOW_AVERAGE_SIZE = "sliding_window_average_size" -CONF_ON_WAKE_WORD_DETECTED = "on_wake_word_detected" +CONF_SLIDING_WINDOW_SIZE = "sliding_window_size" +CONF_TENSOR_ARENA_SIZE = "tensor_arena_size" +CONF_VAD = "vad" TYPE_HTTP = "http" @@ -98,12 +104,14 @@ GIT_SCHEMA = cv.All( _process_git_source, ) -KEY_WAKE_WORD = "wake_word" + KEY_AUTHOR = "author" -KEY_WEBSITE = "website" -KEY_VERSION = "version" KEY_MICRO = "micro" KEY_MINIMUM_ESPHOME_VERSION = "minimum_esphome_version" +KEY_TRAINED_LANGUAGES = "trained_languages" +KEY_VERSION = "version" +KEY_WAKE_WORD = "wake_word" +KEY_WEBSITE = "website" MANIFEST_SCHEMA_V1 = cv.Schema( { @@ -125,6 +133,29 @@ MANIFEST_SCHEMA_V1 = cv.Schema( } ) +MANIFEST_SCHEMA_V2 = cv.Schema( + { + cv.Required(CONF_TYPE): "micro", + cv.Required(CONF_MODEL): cv.string, + cv.Required(KEY_AUTHOR): cv.string, + cv.Required(KEY_VERSION): cv.All(cv.int_, 2), + cv.Required(KEY_WAKE_WORD): cv.string, + cv.Required(KEY_TRAINED_LANGUAGES): cv.ensure_list(cv.string), + cv.Optional(KEY_WEBSITE): cv.url, + cv.Required(KEY_MICRO): cv.Schema( + { + cv.Required(CONF_FEATURE_STEP_SIZE): cv.int_range(min=0, max=30), + cv.Required(CONF_TENSOR_ARENA_SIZE): cv.int_, + cv.Required(CONF_PROBABILITY_CUTOFF): cv.float_, + cv.Required(CONF_SLIDING_WINDOW_SIZE): cv.positive_int, + cv.Required(KEY_MINIMUM_ESPHOME_VERSION): cv.All( + cv.version_number, cv.validate_esphome_version + ), + } + ), + } +) + def _compute_local_file_path(config: dict) -> Path: url = config[CONF_URL] @@ -135,6 +166,24 @@ def _compute_local_file_path(config: dict) -> Path: return base_dir / key +def _convert_manifest_v1_to_v2(v1_manifest): + v2_manifest = v1_manifest.copy() + + v2_manifest[KEY_VERSION] = 2 + v2_manifest[KEY_MICRO][CONF_SLIDING_WINDOW_SIZE] = v1_manifest[KEY_MICRO][ + CONF_SLIDING_WINDOW_AVERAGE_SIZE + ] + del v2_manifest[KEY_MICRO][CONF_SLIDING_WINDOW_AVERAGE_SIZE] + v2_manifest[KEY_MICRO][ + CONF_TENSOR_ARENA_SIZE + ] = 45672 # Original Inception-based V1 manifest models require a minimum of 45672 bytes + v2_manifest[KEY_MICRO][ + CONF_FEATURE_STEP_SIZE + ] = 20 # Original Inception-based V1 manifest models use a 20 ms feature step size + + return v2_manifest + + def _download_file(url: str, path: Path) -> bytes: if not external_files.has_remote_file_changed(url, path): _LOGGER.debug("Remote file has not changed, skipping download") @@ -155,6 +204,24 @@ def _download_file(url: str, path: Path) -> bytes: return req.content +def _validate_manifest_version(manifest_data): + if manifest_version := manifest_data.get(KEY_VERSION): + if manifest_version == 1: + try: + MANIFEST_SCHEMA_V1(manifest_data) + except cv.Invalid as e: + raise cv.Invalid(f"Invalid manifest file: {e}") from e + elif manifest_version == 2: + try: + MANIFEST_SCHEMA_V2(manifest_data) + except cv.Invalid as e: + raise cv.Invalid(f"Invalid manifest file: {e}") from e + else: + raise cv.Invalid("Invalid manifest version") + else: + raise cv.Invalid("Invalid manifest file, missing 'version' key.") + + def _process_http_source(config): url = config[CONF_URL] path = _compute_local_file_path(config) @@ -167,11 +234,6 @@ def _process_http_source(config): if not isinstance(manifest_data, dict): raise cv.Invalid("Manifest file must contain a JSON object") - try: - MANIFEST_SCHEMA_V1(manifest_data) - except cv.Invalid as e: - raise cv.Invalid(f"Invalid manifest file: {e}") from e - model = manifest_data[CONF_MODEL] model_url = urljoin(url, model) @@ -206,7 +268,7 @@ def _validate_source_model_name(value): return MODEL_SOURCE_SCHEMA( { CONF_TYPE: TYPE_HTTP, - CONF_URL: f"https://github.com/esphome/micro-wake-word-models/raw/main/models/{value}.json", + CONF_URL: f"https://github.com/esphome/micro-wake-word-models/raw/main/models/v2/{value}.json", } ) @@ -260,18 +322,55 @@ MODEL_SOURCE_SCHEMA = cv.Any( msg="Not a valid model name, local path, http(s) url, or github shorthand", ) +MODEL_SCHEMA = cv.Schema( + { + cv.Optional(CONF_MODEL): MODEL_SOURCE_SCHEMA, + cv.Optional(CONF_PROBABILITY_CUTOFF): cv.percentage, + cv.Optional(CONF_SLIDING_WINDOW_SIZE): cv.positive_int, + cv.GenerateID(CONF_RAW_DATA_ID): cv.declare_id(cg.uint8), + } +) + +# Provide a default VAD model that could be overridden +VAD_MODEL_SCHEMA = MODEL_SCHEMA.extend( + cv.Schema( + { + cv.Optional( + CONF_MODEL, + default="vad", + ): MODEL_SOURCE_SCHEMA, + } + ) +) + + +def _maybe_empty_vad_schema(value): + # Idea borrowed from uart/__init__.py's ``maybe_empty_debug`` function. Accessed 2 July 2024. + # Loads a default VAD model without any parameters overridden. + if value is None: + value = {} + return VAD_MODEL_SCHEMA(value) + + CONFIG_SCHEMA = cv.All( cv.Schema( { cv.GenerateID(): cv.declare_id(MicroWakeWord), cv.GenerateID(CONF_MICROPHONE): cv.use_id(microphone.Microphone), - cv.Optional(CONF_PROBABILITY_CUTOFF): cv.percentage, - cv.Optional(CONF_SLIDING_WINDOW_AVERAGE_SIZE): cv.positive_int, + cv.Required(CONF_MODELS): cv.ensure_list(MODEL_SCHEMA), cv.Optional(CONF_ON_WAKE_WORD_DETECTED): automation.validate_automation( single=True ), - cv.Required(CONF_MODEL): MODEL_SOURCE_SCHEMA, - cv.GenerateID(CONF_RAW_DATA_ID): cv.declare_id(cg.uint8), + cv.Optional(CONF_VAD): _maybe_empty_vad_schema, + cv.Optional(CONF_MODEL): cv.invalid( + f"The {CONF_MODEL} parameter has moved to be a list element under the {CONF_MODELS} parameter." + ), + cv.Optional(CONF_PROBABILITY_CUTOFF): cv.invalid( + f"The {CONF_PROBABILITY_CUTOFF} parameter has moved to be a list element under the {CONF_MODELS} parameter." + ), + cv.Optional(CONF_SLIDING_WINDOW_AVERAGE_SIZE): cv.invalid( + f"The {CONF_SLIDING_WINDOW_AVERAGE_SIZE} parameter has been renamed to {CONF_SLIDING_WINDOW_SIZE} and moved to be a list element under the {CONF_MODELS} parameter." + ), } ).extend(cv.COMPONENT_SCHEMA), cv.only_with_esp_idf, @@ -282,45 +381,20 @@ def _load_model_data(manifest_path: Path): with open(manifest_path, encoding="utf-8") as f: manifest = json.load(f) - try: - MANIFEST_SCHEMA_V1(manifest) - except cv.Invalid as e: - raise EsphomeError(f"Invalid manifest file: {e}") from e + _validate_manifest_version(manifest) model_path = manifest_path.parent / manifest[CONF_MODEL] with open(model_path, "rb") as f: model = f.read() + if manifest.get(KEY_VERSION) == 1: + manifest = _convert_manifest_v1_to_v2(manifest) + return manifest, model -async def to_code(config): - var = cg.new_Pvariable(config[CONF_ID]) - await cg.register_component(var, config) - - mic = await cg.get_variable(config[CONF_MICROPHONE]) - cg.add(var.set_microphone(mic)) - - if on_wake_word_detection_config := config.get(CONF_ON_WAKE_WORD_DETECTED): - await automation.build_automation( - var.get_wake_word_detected_trigger(), - [(cg.std_string, "wake_word")], - on_wake_word_detection_config, - ) - - esp32.add_idf_component( - name="esp-tflite-micro", - repo="https://github.com/espressif/esp-tflite-micro", - ref="v1.3.1", - ) - - cg.add_build_flag("-DTF_LITE_STATIC_MEMORY") - cg.add_build_flag("-DTF_LITE_DISABLE_X86_NEON") - cg.add_build_flag("-DESP_NN") - - model_config = config.get(CONF_MODEL) - data = [] +def _model_config_to_manifest_data(model_config): if model_config[CONF_TYPE] == TYPE_GIT: # compute path to model file key = f"{model_config[CONF_URL]}@{model_config.get(CONF_REF)}" @@ -338,23 +412,95 @@ async def to_code(config): else: raise ValueError("Unsupported config type: {model_config[CONF_TYPE]}") - manifest, data = _load_model_data(file) + return _load_model_data(file) - rhs = [HexInt(x) for x in data] - prog_arr = cg.progmem_array(config[CONF_RAW_DATA_ID], rhs) - cg.add(var.set_model_start(prog_arr)) - probability_cutoff = config.get( - CONF_PROBABILITY_CUTOFF, manifest[KEY_MICRO][CONF_PROBABILITY_CUTOFF] +def _feature_step_size_validate(config): + features_step_size = None + + for model_parameters in config[CONF_MODELS]: + model_config = model_parameters.get(CONF_MODEL) + manifest, _ = _model_config_to_manifest_data(model_config) + + model_step_size = manifest[KEY_MICRO][CONF_FEATURE_STEP_SIZE] + + if features_step_size is None: + features_step_size = model_step_size + elif features_step_size != model_step_size: + raise cv.Invalid("Cannot load models with different features step sizes.") + + +FINAL_VALIDATE_SCHEMA = _feature_step_size_validate + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, config) + + mic = await cg.get_variable(config[CONF_MICROPHONE]) + cg.add(var.set_microphone(mic)) + + esp32.add_idf_component( + name="esp-tflite-micro", + repo="https://github.com/espressif/esp-tflite-micro", + ref="v1.3.1", ) - cg.add(var.set_probability_cutoff(probability_cutoff)) - sliding_window_average_size = config.get( - CONF_SLIDING_WINDOW_AVERAGE_SIZE, - manifest[KEY_MICRO][CONF_SLIDING_WINDOW_AVERAGE_SIZE], - ) - cg.add(var.set_sliding_window_average_size(sliding_window_average_size)) - cg.add(var.set_wake_word(manifest[KEY_WAKE_WORD])) + cg.add_build_flag("-DTF_LITE_STATIC_MEMORY") + cg.add_build_flag("-DTF_LITE_DISABLE_X86_NEON") + cg.add_build_flag("-DESP_NN") + + if on_wake_word_detection_config := config.get(CONF_ON_WAKE_WORD_DETECTED): + await automation.build_automation( + var.get_wake_word_detected_trigger(), + [(cg.std_string, "wake_word")], + on_wake_word_detection_config, + ) + + if vad_model := config.get(CONF_VAD): + cg.add_define("USE_MICRO_WAKE_WORD_VAD") + + # Use the general model loading code for the VAD codegen + config[CONF_MODELS].append(vad_model) + + for model_parameters in config[CONF_MODELS]: + model_config = model_parameters.get(CONF_MODEL) + data = [] + manifest, data = _model_config_to_manifest_data(model_config) + + rhs = [HexInt(x) for x in data] + prog_arr = cg.progmem_array(model_parameters[CONF_RAW_DATA_ID], rhs) + + probability_cutoff = model_parameters.get( + CONF_PROBABILITY_CUTOFF, manifest[KEY_MICRO][CONF_PROBABILITY_CUTOFF] + ) + sliding_window_size = model_parameters.get( + CONF_SLIDING_WINDOW_SIZE, + manifest[KEY_MICRO][CONF_SLIDING_WINDOW_SIZE], + ) + + if manifest[KEY_WAKE_WORD] == "vad": + cg.add( + var.add_vad_model( + prog_arr, + probability_cutoff, + sliding_window_size, + manifest[KEY_MICRO][CONF_TENSOR_ARENA_SIZE], + ) + ) + else: + cg.add( + var.add_wake_word_model( + prog_arr, + probability_cutoff, + sliding_window_size, + manifest[KEY_WAKE_WORD], + manifest[KEY_MICRO][CONF_TENSOR_ARENA_SIZE], + ) + ) + + cg.add(var.set_features_step_size(manifest[KEY_MICRO][CONF_FEATURE_STEP_SIZE])) + cg.add_library("kahrendt/ESPMicroSpeechFeatures", "1.0.0") MICRO_WAKE_WORD_ACTION_SCHEMA = cv.Schema({cv.GenerateID(): cv.use_id(MicroWakeWord)}) diff --git a/esphome/components/micro_wake_word/audio_preprocessor_int8_model_data.h b/esphome/components/micro_wake_word/audio_preprocessor_int8_model_data.h deleted file mode 100644 index 918e76045f..0000000000 --- a/esphome/components/micro_wake_word/audio_preprocessor_int8_model_data.h +++ /dev/null @@ -1,493 +0,0 @@ -#pragma once - -#ifdef USE_ESP_IDF - -// Converted audio_preprocessor_int8.tflite -// From https://github.com/tensorflow/tflite-micro/tree/main/tensorflow/lite/micro/examples/micro_speech/models accessed -// January 2024 -// -// Copyright 2023 The TensorFlow Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -namespace esphome { -namespace micro_wake_word { - -const unsigned char G_AUDIO_PREPROCESSOR_INT8_TFLITE[] = { - 0x1c, 0x00, 0x00, 0x00, 0x54, 0x46, 0x4c, 0x33, 0x14, 0x00, 0x20, 0x00, 0x1c, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, - 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x88, 0x00, - 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x80, 0x0e, 0x00, 0x00, 0x90, 0x0e, 0x00, 0x00, 0xcc, 0x1f, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe2, 0xeb, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, - 0x1c, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, - 0x5f, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x94, 0xff, - 0xff, 0xff, 0x2a, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x6f, 0x75, 0x74, 0x70, 0x75, - 0x74, 0x5f, 0x30, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xc2, 0xf5, 0xff, 0xff, - 0x04, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, - 0x00, 0x02, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xdc, 0xff, 0xff, 0xff, 0x2d, 0x00, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x43, 0x4f, 0x4e, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, - 0x4e, 0x5f, 0x4d, 0x45, 0x54, 0x41, 0x44, 0x41, 0x54, 0x41, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x6d, 0x69, 0x6e, - 0x5f, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x2e, 0x00, - 0x00, 0x00, 0x9c, 0x0d, 0x00, 0x00, 0x94, 0x0d, 0x00, 0x00, 0xc4, 0x09, 0x00, 0x00, 0x6c, 0x09, 0x00, 0x00, 0x48, - 0x09, 0x00, 0x00, 0x34, 0x09, 0x00, 0x00, 0x20, 0x09, 0x00, 0x00, 0x0c, 0x09, 0x00, 0x00, 0xf8, 0x08, 0x00, 0x00, - 0xec, 0x07, 0x00, 0x00, 0x88, 0x07, 0x00, 0x00, 0x24, 0x07, 0x00, 0x00, 0xc0, 0x06, 0x00, 0x00, 0x38, 0x04, 0x00, - 0x00, 0xb0, 0x01, 0x00, 0x00, 0x9c, 0x01, 0x00, 0x00, 0x88, 0x01, 0x00, 0x00, 0x74, 0x01, 0x00, 0x00, 0x60, 0x01, - 0x00, 0x00, 0x4c, 0x01, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, 0x3c, 0x01, 0x00, 0x00, 0x34, 0x01, 0x00, 0x00, 0x2c, - 0x01, 0x00, 0x00, 0x24, 0x01, 0x00, 0x00, 0x1c, 0x01, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x0c, 0x01, 0x00, 0x00, - 0x04, 0x01, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, - 0x00, 0xdc, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0xbc, 0x00, - 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x94, - 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xf2, 0xf6, 0xff, 0xff, - 0x04, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, - 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x08, 0x00, - 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0a, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x32, 0x2e, 0x31, 0x32, 0x2e, 0x30, 0x00, - 0x00, 0x56, 0xf7, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x32, 0x2e, 0x38, 0x2e, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0xe1, 0xff, 0xff, 0xd8, 0xe1, 0xff, 0xff, 0xdc, - 0xe1, 0xff, 0xff, 0xe0, 0xe1, 0xff, 0xff, 0xe4, 0xe1, 0xff, 0xff, 0xe8, 0xe1, 0xff, 0xff, 0xec, 0xe1, 0xff, 0xff, - 0xf0, 0xe1, 0xff, 0xff, 0xf4, 0xe1, 0xff, 0xff, 0xf8, 0xe1, 0xff, 0xff, 0xfc, 0xe1, 0xff, 0xff, 0x00, 0xe2, 0xff, - 0xff, 0x04, 0xe2, 0xff, 0xff, 0x08, 0xe2, 0xff, 0xff, 0x0c, 0xe2, 0xff, 0xff, 0x10, 0xe2, 0xff, 0xff, 0x14, 0xe2, - 0xff, 0xff, 0x18, 0xe2, 0xff, 0xff, 0x1c, 0xe2, 0xff, 0xff, 0x20, 0xe2, 0xff, 0xff, 0x24, 0xe2, 0xff, 0xff, 0x28, - 0xe2, 0xff, 0xff, 0x2c, 0xe2, 0xff, 0xff, 0x30, 0xe2, 0xff, 0xff, 0xd2, 0xf7, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x9a, 0x02, 0x00, 0x00, 0xe2, 0xf7, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0xf2, 0xf7, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0xff, - 0xff, 0xff, 0x02, 0xf8, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x12, - 0xf8, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x22, 0xf8, 0xff, 0xff, - 0x04, 0x00, 0x00, 0x00, 0x78, 0x02, 0x00, 0x00, 0x00, 0x00, 0x61, 0x05, 0x00, 0x00, 0x00, 0x00, 0x23, 0x0b, 0x41, - 0x01, 0x00, 0x00, 0x00, 0x00, 0xb3, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x0e, 0x80, 0x05, - 0x00, 0x00, 0x00, 0x00, 0xd1, 0x0c, 0x63, 0x04, 0x00, 0x00, 0x00, 0x00, 0x34, 0x0c, 0x3f, 0x04, 0x00, 0x00, 0x00, - 0x00, 0x81, 0x0c, 0xf7, 0x04, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x0d, 0x77, 0x06, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x0f, - 0xa9, 0x08, 0x01, 0x02, 0x7f, 0x0b, 0x22, 0x05, 0x00, 0x00, 0x00, 0x00, 0xe9, 0x0e, 0xd1, 0x08, 0xdb, 0x02, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x0d, 0x4a, 0x07, 0xad, 0x01, 0x2c, 0x0c, 0xc6, 0x06, 0x79, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x45, 0x0c, 0x29, 0x07, 0x23, 0x02, 0x34, 0x0d, 0x5b, 0x08, 0x96, 0x03, 0x00, 0x00, 0x00, 0x00, 0xe5, 0x0e, 0x48, - 0x0a, 0xbd, 0x05, 0x45, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0x0c, 0x88, 0x08, 0x43, 0x04, - 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe9, 0x0b, 0xd3, 0x07, 0xcb, 0x03, 0xd2, 0x0f, 0xe7, - 0x0b, 0x09, 0x08, 0x39, 0x04, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x0c, 0x14, 0x09, - 0x75, 0x05, 0xe2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x0e, 0xdd, 0x0a, 0x6b, 0x07, 0x03, - 0x04, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x0d, 0x09, 0x0a, 0xc9, 0x06, 0x93, 0x03, 0x65, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x0d, 0x25, 0x0a, 0x12, 0x07, 0x07, 0x04, 0x05, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x0a, 0x0e, 0x17, 0x0b, 0x2c, 0x08, 0x49, 0x05, 0x6d, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x98, 0x0f, 0xcb, 0x0c, 0x04, 0x0a, 0x44, 0x07, 0x8b, 0x04, 0xd8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x0f, 0x87, - 0x0c, 0xe7, 0x09, 0x4e, 0x07, 0xba, 0x04, 0x2d, 0x02, 0x00, 0x00, 0x00, 0x00, 0xa5, 0x0f, 0x23, 0x0d, 0xa7, 0x0a, - 0x30, 0x08, 0xbe, 0x05, 0x52, 0x03, 0xeb, 0x00, 0x89, 0x0e, 0x2c, 0x0c, 0xd4, 0x09, 0x81, 0x07, 0x33, 0x05, 0xe9, - 0x02, 0xa5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x0e, 0x29, 0x0c, 0xf1, 0x09, 0xbe, 0x07, 0x90, 0x05, 0x65, 0x03, - 0x3f, 0x01, 0x1d, 0x0f, 0xff, 0x0c, 0xe5, 0x0a, 0xcf, 0x08, 0xbc, 0x06, 0xae, 0x04, 0xa3, 0x02, 0x9c, 0x00, 0x99, - 0x0e, 0x99, 0x0c, 0x9d, 0x0a, 0xa4, 0x08, 0xaf, 0x06, 0xbd, 0x04, 0xcf, 0x02, 0xe4, 0x00, 0xfc, 0x0e, 0x17, 0x0d, - 0x36, 0x0b, 0x57, 0x09, 0x7c, 0x07, 0xa4, 0x05, 0xcf, 0x03, 0xfd, 0x01, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x62, 0x0e, 0x98, 0x0c, 0xd2, 0x0a, 0x0e, 0x09, 0x4d, 0x07, 0x8f, 0x05, 0xd4, 0x03, 0x1b, 0x02, - 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb1, 0x0e, 0x00, 0x0d, 0x52, 0x0b, 0xa6, 0x09, 0xfd, 0x07, 0x56, 0x06, 0xb1, - 0x04, 0x0f, 0x03, 0x6f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd2, 0x0f, 0x37, 0x0e, 0x9e, 0x0c, - 0x08, 0x0b, 0x73, 0x09, 0xe1, 0x07, 0x52, 0x06, 0xc4, 0x04, 0x38, 0x03, 0xaf, 0x01, 0x28, 0x00, 0xa3, 0x0e, 0x1f, - 0x0d, 0x9e, 0x0b, 0x1f, 0x0a, 0xa2, 0x08, 0x27, 0x07, 0xae, 0x05, 0x37, 0x04, 0xc2, 0x02, 0x4e, 0x01, 0x00, 0x00, - 0x00, 0x00, 0xdd, 0x0f, 0x6d, 0x0e, 0xff, 0x0c, 0x93, 0x0b, 0x29, 0x0a, 0xc1, 0x08, 0x5a, 0x07, 0xf5, 0x05, 0x92, - 0x04, 0x30, 0x03, 0xd1, 0x01, 0x73, 0x00, 0x16, 0x0f, 0xbc, 0x0d, 0x62, 0x0c, 0x0b, 0x0b, 0xb5, 0x09, 0x61, 0x08, - 0x0e, 0x07, 0xbd, 0x05, 0x6d, 0x04, 0x1f, 0x03, 0xd3, 0x01, 0x88, 0x00, 0x3e, 0x0f, 0xf6, 0x0d, 0xaf, 0x0c, 0x6a, - 0x0b, 0x27, 0x0a, 0xe4, 0x08, 0xa3, 0x07, 0x64, 0x06, 0x26, 0x05, 0xe9, 0x03, 0xae, 0x02, 0x74, 0x01, 0x3b, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x0f, 0xce, 0x0d, 0x99, 0x0c, 0x66, 0x0b, 0x34, 0x0a, 0x03, - 0x09, 0xd3, 0x07, 0xa5, 0x06, 0x78, 0x05, 0x4c, 0x04, 0x22, 0x03, 0xf8, 0x01, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xa9, 0x0f, 0x83, 0x0e, 0x5f, 0x0d, 0x3b, 0x0c, 0x19, 0x0b, 0xf8, 0x09, 0xd8, 0x08, 0xb9, 0x07, 0x9b, 0x06, 0x7e, - 0x05, 0x63, 0x04, 0x48, 0x03, 0x2f, 0x02, 0x17, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa6, 0xfa, 0xff, 0xff, 0x04, 0x00, - 0x00, 0x00, 0x78, 0x02, 0x00, 0x00, 0x00, 0x00, 0x9e, 0x0a, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x04, 0xbe, 0x0e, 0x00, - 0x00, 0x00, 0x00, 0x4c, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x01, 0x7f, 0x0a, 0x00, 0x00, - 0x00, 0x00, 0x2e, 0x03, 0x9c, 0x0b, 0x00, 0x00, 0x00, 0x00, 0xcb, 0x03, 0xc0, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x7e, - 0x03, 0x08, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x60, 0x02, 0x88, 0x09, 0x00, 0x00, 0x00, 0x00, 0x84, 0x00, 0x56, 0x07, - 0xfe, 0x0d, 0x80, 0x04, 0xdd, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x16, 0x01, 0x2e, 0x07, 0x24, 0x0d, 0x00, 0x00, 0x00, - 0x00, 0xfc, 0x02, 0xb5, 0x08, 0x52, 0x0e, 0xd3, 0x03, 0x39, 0x09, 0x86, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xba, 0x03, - 0xd6, 0x08, 0xdc, 0x0d, 0xcb, 0x02, 0xa4, 0x07, 0x69, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x01, 0xb7, 0x05, 0x42, - 0x0a, 0xba, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x03, 0x77, 0x07, 0xbc, 0x0b, 0xf1, 0x0f, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x04, 0x2c, 0x08, 0x34, 0x0c, 0x2d, 0x00, 0x18, 0x04, 0xf6, - 0x07, 0xc6, 0x0b, 0x89, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x03, 0xeb, 0x06, 0x8a, 0x0a, - 0x1d, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0x01, 0x22, 0x05, 0x94, 0x08, 0xfc, 0x0b, 0x59, - 0x0f, 0x00, 0x00, 0x00, 0x00, 0xac, 0x02, 0xf6, 0x05, 0x36, 0x09, 0x6c, 0x0c, 0x9a, 0x0f, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xbe, 0x02, 0xda, 0x05, 0xed, 0x08, 0xf8, 0x0b, 0xfa, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xf5, - 0x01, 0xe8, 0x04, 0xd3, 0x07, 0xb6, 0x0a, 0x92, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x00, - 0x34, 0x03, 0xfb, 0x05, 0xbb, 0x08, 0x74, 0x0b, 0x27, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x00, 0x78, 0x03, 0x18, - 0x06, 0xb1, 0x08, 0x45, 0x0b, 0xd2, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x00, 0xdc, 0x02, 0x58, 0x05, 0xcf, 0x07, - 0x41, 0x0a, 0xad, 0x0c, 0x14, 0x0f, 0x76, 0x01, 0xd3, 0x03, 0x2b, 0x06, 0x7e, 0x08, 0xcc, 0x0a, 0x16, 0x0d, 0x5a, - 0x0f, 0x00, 0x00, 0x00, 0x00, 0x9b, 0x01, 0xd6, 0x03, 0x0e, 0x06, 0x41, 0x08, 0x6f, 0x0a, 0x9a, 0x0c, 0xc0, 0x0e, - 0xe2, 0x00, 0x00, 0x03, 0x1a, 0x05, 0x30, 0x07, 0x43, 0x09, 0x51, 0x0b, 0x5c, 0x0d, 0x63, 0x0f, 0x66, 0x01, 0x66, - 0x03, 0x62, 0x05, 0x5b, 0x07, 0x50, 0x09, 0x42, 0x0b, 0x30, 0x0d, 0x1b, 0x0f, 0x03, 0x01, 0xe8, 0x02, 0xc9, 0x04, - 0xa8, 0x06, 0x83, 0x08, 0x5b, 0x0a, 0x30, 0x0c, 0x02, 0x0e, 0xd1, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x9d, 0x01, 0x67, 0x03, 0x2d, 0x05, 0xf1, 0x06, 0xb2, 0x08, 0x70, 0x0a, 0x2b, 0x0c, 0xe4, 0x0d, 0x9a, 0x0f, - 0x00, 0x00, 0x00, 0x00, 0x4e, 0x01, 0xff, 0x02, 0xad, 0x04, 0x59, 0x06, 0x02, 0x08, 0xa9, 0x09, 0x4e, 0x0b, 0xf0, - 0x0c, 0x90, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0xc8, 0x01, 0x61, 0x03, 0xf7, 0x04, - 0x8c, 0x06, 0x1e, 0x08, 0xad, 0x09, 0x3b, 0x0b, 0xc7, 0x0c, 0x50, 0x0e, 0xd7, 0x0f, 0x5c, 0x01, 0xe0, 0x02, 0x61, - 0x04, 0xe0, 0x05, 0x5d, 0x07, 0xd8, 0x08, 0x51, 0x0a, 0xc8, 0x0b, 0x3d, 0x0d, 0xb1, 0x0e, 0x00, 0x00, 0x00, 0x00, - 0x22, 0x00, 0x92, 0x01, 0x00, 0x03, 0x6c, 0x04, 0xd6, 0x05, 0x3e, 0x07, 0xa5, 0x08, 0x0a, 0x0a, 0x6d, 0x0b, 0xcf, - 0x0c, 0x2e, 0x0e, 0x8c, 0x0f, 0xe9, 0x00, 0x43, 0x02, 0x9d, 0x03, 0xf4, 0x04, 0x4a, 0x06, 0x9e, 0x07, 0xf1, 0x08, - 0x42, 0x0a, 0x92, 0x0b, 0xe0, 0x0c, 0x2c, 0x0e, 0x77, 0x0f, 0xc1, 0x00, 0x09, 0x02, 0x50, 0x03, 0x95, 0x04, 0xd8, - 0x05, 0x1b, 0x07, 0x5c, 0x08, 0x9b, 0x09, 0xd9, 0x0a, 0x16, 0x0c, 0x51, 0x0d, 0x8b, 0x0e, 0xc4, 0x0f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb, 0x00, 0x31, 0x02, 0x66, 0x03, 0x99, 0x04, 0xcb, 0x05, 0xfc, 0x06, 0x2c, - 0x08, 0x5a, 0x09, 0x87, 0x0a, 0xb3, 0x0b, 0xdd, 0x0c, 0x07, 0x0e, 0x2f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x56, 0x00, - 0x7c, 0x01, 0xa0, 0x02, 0xc4, 0x03, 0xe6, 0x04, 0x07, 0x06, 0x27, 0x07, 0x46, 0x08, 0x64, 0x09, 0x81, 0x0a, 0x9c, - 0x0b, 0xb7, 0x0c, 0xd0, 0x0d, 0xe8, 0x0e, 0x00, 0x10, 0x00, 0x00, 0x2a, 0xfd, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, - 0x52, 0x00, 0x00, 0x00, 0x04, 0x00, 0x06, 0x00, 0x08, 0x00, 0x08, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x0e, 0x00, 0x10, - 0x00, 0x12, 0x00, 0x16, 0x00, 0x18, 0x00, 0x1a, 0x00, 0x1e, 0x00, 0x20, 0x00, 0x24, 0x00, 0x26, 0x00, 0x2a, 0x00, - 0x2e, 0x00, 0x32, 0x00, 0x36, 0x00, 0x3a, 0x00, 0x40, 0x00, 0x44, 0x00, 0x4a, 0x00, 0x4e, 0x00, 0x54, 0x00, 0x5a, - 0x00, 0x62, 0x00, 0x68, 0x00, 0x70, 0x00, 0x78, 0x00, 0x80, 0x00, 0x88, 0x00, 0x92, 0x00, 0x9a, 0x00, 0xa6, 0x00, - 0xb0, 0x00, 0xbc, 0x00, 0xc8, 0x00, 0xd4, 0x00, 0xe2, 0x00, 0x00, 0x00, 0x8a, 0xfd, 0xff, 0xff, 0x04, 0x00, 0x00, - 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x14, 0x00, 0x18, 0x00, - 0x1c, 0x00, 0x20, 0x00, 0x24, 0x00, 0x28, 0x00, 0x2c, 0x00, 0x30, 0x00, 0x34, 0x00, 0x38, 0x00, 0x3c, 0x00, 0x44, - 0x00, 0x4c, 0x00, 0x50, 0x00, 0x58, 0x00, 0x60, 0x00, 0x68, 0x00, 0x70, 0x00, 0x78, 0x00, 0x80, 0x00, 0x88, 0x00, - 0x90, 0x00, 0x98, 0x00, 0xa0, 0x00, 0xa8, 0x00, 0xb0, 0x00, 0xb8, 0x00, 0xc4, 0x00, 0xd0, 0x00, 0xdc, 0x00, 0xe8, - 0x00, 0xf4, 0x00, 0x00, 0x01, 0x0c, 0x01, 0x1c, 0x01, 0x2c, 0x01, 0x00, 0x00, 0xea, 0xfd, 0xff, 0xff, 0x04, 0x00, - 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, - 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x08, 0x00, - 0x08, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, - 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, - 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x4a, 0xfe, 0xff, 0xff, 0x04, - 0x00, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x7c, 0x7f, 0x79, 0x7f, 0x76, 0x7f, 0xfa, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x70, 0x7f, 0xf4, 0xff, 0x00, 0x00, 0x00, 0x00, 0x64, 0x7f, 0xe9, 0xff, 0xfe, 0xff, 0x00, 0x00, 0x4b, 0x7f, 0xd0, - 0xff, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x7f, 0xa0, 0xff, 0x00, 0x00, 0x00, 0x00, 0xbb, 0x7e, 0x42, 0xff, 0x00, 0x00, - 0x00, 0x00, 0xfd, 0x7d, 0x86, 0xfe, 0x04, 0x00, 0x00, 0x00, 0x87, 0x7c, 0x1d, 0xfd, 0x12, 0x00, 0x00, 0x00, 0xb6, - 0x79, 0x7f, 0xfa, 0x3e, 0x00, 0x00, 0x00, 0x73, 0x74, 0xf9, 0xf5, 0xca, 0x00, 0x00, 0x00, 0x36, 0x6b, 0x33, 0xef, - 0x32, 0x02, 0x00, 0x00, 0x9b, 0x5c, 0x87, 0xe7, 0xce, 0x04, 0x00, 0x00, 0xf0, 0x48, 0xde, 0xe2, 0xa0, 0x07, 0x00, - 0x00, 0x6e, 0x33, 0x8a, 0xe4, 0xa4, 0x08, 0x00, 0x00, 0x9c, 0x20, 0x22, 0xeb, 0x4c, 0x07, 0x00, 0x00, 0x0a, 0x13, - 0x7d, 0xf2, 0x02, 0x05, 0x00, 0x00, 0x89, 0x0a, 0x17, 0xf8, 0x06, 0x03, 0x00, 0x00, 0xa6, 0x05, 0xa0, 0xfb, 0xb4, - 0x01, 0x00, 0x00, 0xfa, 0x02, 0xac, 0xfd, 0xe8, 0x00, 0x00, 0x00, 0x8e, 0x01, 0xc7, 0xfe, 0x7a, 0x00, 0x00, 0x00, - 0xcf, 0x00, 0x5c, 0xff, 0x40, 0x00, 0x00, 0x00, 0x6b, 0x00, 0xab, 0xff, 0x22, 0x00, 0x00, 0x00, 0x38, 0x00, 0xd3, - 0xff, 0x12, 0x00, 0x00, 0x00, 0x1d, 0x00, 0xea, 0xff, 0x08, 0x00, 0x00, 0x00, 0x0f, 0x00, 0xf3, 0xff, 0x06, 0x00, - 0x00, 0x00, 0x08, 0x00, 0xf8, 0xff, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x02, - 0x00, 0xfd, 0xff, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xfd, 0xff, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x62, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x00, 0xf1, 0x00, 0x00, 0x00, 0x72, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x82, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x4d, 0x01, 0x00, 0x00, - 0x92, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb2, 0xff, 0xff, 0xff, 0x04, 0x00, - 0x00, 0x00, 0x40, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, - 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x02, 0x00, 0x04, 0x00, 0x05, 0x00, 0x07, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x10, 0x00, 0x13, 0x00, 0x17, 0x00, - 0x1b, 0x00, 0x20, 0x00, 0x25, 0x00, 0x2a, 0x00, 0x30, 0x00, 0x35, 0x00, 0x3c, 0x00, 0x42, 0x00, 0x49, 0x00, 0x51, - 0x00, 0x58, 0x00, 0x60, 0x00, 0x68, 0x00, 0x71, 0x00, 0x7a, 0x00, 0x83, 0x00, 0x8d, 0x00, 0x97, 0x00, 0xa1, 0x00, - 0xac, 0x00, 0xb7, 0x00, 0xc2, 0x00, 0xcd, 0x00, 0xd9, 0x00, 0xe5, 0x00, 0xf2, 0x00, 0xff, 0x00, 0x0c, 0x01, 0x19, - 0x01, 0x27, 0x01, 0x35, 0x01, 0x43, 0x01, 0x52, 0x01, 0x61, 0x01, 0x70, 0x01, 0x7f, 0x01, 0x8f, 0x01, 0x9f, 0x01, - 0xaf, 0x01, 0xc0, 0x01, 0xd1, 0x01, 0xe2, 0x01, 0xf3, 0x01, 0x05, 0x02, 0x17, 0x02, 0x29, 0x02, 0x3c, 0x02, 0x4e, - 0x02, 0x61, 0x02, 0x75, 0x02, 0x88, 0x02, 0x9c, 0x02, 0xb0, 0x02, 0xc4, 0x02, 0xd8, 0x02, 0xed, 0x02, 0x02, 0x03, - 0x17, 0x03, 0x2c, 0x03, 0x41, 0x03, 0x57, 0x03, 0x6d, 0x03, 0x83, 0x03, 0x99, 0x03, 0xb0, 0x03, 0xc7, 0x03, 0xdd, - 0x03, 0xf4, 0x03, 0x0c, 0x04, 0x23, 0x04, 0x3b, 0x04, 0x52, 0x04, 0x6a, 0x04, 0x82, 0x04, 0x9a, 0x04, 0xb3, 0x04, - 0xcb, 0x04, 0xe4, 0x04, 0xfd, 0x04, 0x16, 0x05, 0x2f, 0x05, 0x48, 0x05, 0x61, 0x05, 0x7a, 0x05, 0x94, 0x05, 0xad, - 0x05, 0xc7, 0x05, 0xe1, 0x05, 0xfb, 0x05, 0x15, 0x06, 0x2f, 0x06, 0x49, 0x06, 0x63, 0x06, 0x7e, 0x06, 0x98, 0x06, - 0xb2, 0x06, 0xcd, 0x06, 0xe7, 0x06, 0x02, 0x07, 0x1d, 0x07, 0x37, 0x07, 0x52, 0x07, 0x6d, 0x07, 0x87, 0x07, 0xa2, - 0x07, 0xbd, 0x07, 0xd8, 0x07, 0xf3, 0x07, 0x0d, 0x08, 0x28, 0x08, 0x43, 0x08, 0x5e, 0x08, 0x79, 0x08, 0x93, 0x08, - 0xae, 0x08, 0xc9, 0x08, 0xe3, 0x08, 0xfe, 0x08, 0x19, 0x09, 0x33, 0x09, 0x4e, 0x09, 0x68, 0x09, 0x82, 0x09, 0x9d, - 0x09, 0xb7, 0x09, 0xd1, 0x09, 0xeb, 0x09, 0x05, 0x0a, 0x1f, 0x0a, 0x39, 0x0a, 0x53, 0x0a, 0x6c, 0x0a, 0x86, 0x0a, - 0x9f, 0x0a, 0xb8, 0x0a, 0xd1, 0x0a, 0xea, 0x0a, 0x03, 0x0b, 0x1c, 0x0b, 0x35, 0x0b, 0x4d, 0x0b, 0x66, 0x0b, 0x7e, - 0x0b, 0x96, 0x0b, 0xae, 0x0b, 0xc5, 0x0b, 0xdd, 0x0b, 0xf4, 0x0b, 0x0c, 0x0c, 0x23, 0x0c, 0x39, 0x0c, 0x50, 0x0c, - 0x67, 0x0c, 0x7d, 0x0c, 0x93, 0x0c, 0xa9, 0x0c, 0xbf, 0x0c, 0xd4, 0x0c, 0xe9, 0x0c, 0xfe, 0x0c, 0x13, 0x0d, 0x28, - 0x0d, 0x3c, 0x0d, 0x50, 0x0d, 0x64, 0x0d, 0x78, 0x0d, 0x8b, 0x0d, 0x9f, 0x0d, 0xb2, 0x0d, 0xc4, 0x0d, 0xd7, 0x0d, - 0xe9, 0x0d, 0xfb, 0x0d, 0x0d, 0x0e, 0x1e, 0x0e, 0x2f, 0x0e, 0x40, 0x0e, 0x51, 0x0e, 0x61, 0x0e, 0x71, 0x0e, 0x81, - 0x0e, 0x90, 0x0e, 0x9f, 0x0e, 0xae, 0x0e, 0xbd, 0x0e, 0xcb, 0x0e, 0xd9, 0x0e, 0xe7, 0x0e, 0xf4, 0x0e, 0x01, 0x0f, - 0x0e, 0x0f, 0x1b, 0x0f, 0x27, 0x0f, 0x33, 0x0f, 0x3e, 0x0f, 0x49, 0x0f, 0x54, 0x0f, 0x5f, 0x0f, 0x69, 0x0f, 0x73, - 0x0f, 0x7d, 0x0f, 0x86, 0x0f, 0x8f, 0x0f, 0x98, 0x0f, 0xa0, 0x0f, 0xa8, 0x0f, 0xaf, 0x0f, 0xb7, 0x0f, 0xbe, 0x0f, - 0xc4, 0x0f, 0xcb, 0x0f, 0xd0, 0x0f, 0xd6, 0x0f, 0xdb, 0x0f, 0xe0, 0x0f, 0xe5, 0x0f, 0xe9, 0x0f, 0xed, 0x0f, 0xf0, - 0x0f, 0xf3, 0x0f, 0xf6, 0x0f, 0xf9, 0x0f, 0xfb, 0x0f, 0xfc, 0x0f, 0xfe, 0x0f, 0xff, 0x0f, 0x00, 0x10, 0x00, 0x10, - 0x00, 0x10, 0x00, 0x10, 0xff, 0x0f, 0xfe, 0x0f, 0xfc, 0x0f, 0xfb, 0x0f, 0xf9, 0x0f, 0xf6, 0x0f, 0xf3, 0x0f, 0xf0, - 0x0f, 0xed, 0x0f, 0xe9, 0x0f, 0xe5, 0x0f, 0xe0, 0x0f, 0xdb, 0x0f, 0xd6, 0x0f, 0xd0, 0x0f, 0xcb, 0x0f, 0xc4, 0x0f, - 0xbe, 0x0f, 0xb7, 0x0f, 0xaf, 0x0f, 0xa8, 0x0f, 0xa0, 0x0f, 0x98, 0x0f, 0x8f, 0x0f, 0x86, 0x0f, 0x7d, 0x0f, 0x73, - 0x0f, 0x69, 0x0f, 0x5f, 0x0f, 0x54, 0x0f, 0x49, 0x0f, 0x3e, 0x0f, 0x33, 0x0f, 0x27, 0x0f, 0x1b, 0x0f, 0x0e, 0x0f, - 0x01, 0x0f, 0xf4, 0x0e, 0xe7, 0x0e, 0xd9, 0x0e, 0xcb, 0x0e, 0xbd, 0x0e, 0xae, 0x0e, 0x9f, 0x0e, 0x90, 0x0e, 0x81, - 0x0e, 0x71, 0x0e, 0x61, 0x0e, 0x51, 0x0e, 0x40, 0x0e, 0x2f, 0x0e, 0x1e, 0x0e, 0x0d, 0x0e, 0xfb, 0x0d, 0xe9, 0x0d, - 0xd7, 0x0d, 0xc4, 0x0d, 0xb2, 0x0d, 0x9f, 0x0d, 0x8b, 0x0d, 0x78, 0x0d, 0x64, 0x0d, 0x50, 0x0d, 0x3c, 0x0d, 0x28, - 0x0d, 0x13, 0x0d, 0xfe, 0x0c, 0xe9, 0x0c, 0xd4, 0x0c, 0xbf, 0x0c, 0xa9, 0x0c, 0x93, 0x0c, 0x7d, 0x0c, 0x67, 0x0c, - 0x50, 0x0c, 0x39, 0x0c, 0x23, 0x0c, 0x0c, 0x0c, 0xf4, 0x0b, 0xdd, 0x0b, 0xc5, 0x0b, 0xae, 0x0b, 0x96, 0x0b, 0x7e, - 0x0b, 0x66, 0x0b, 0x4d, 0x0b, 0x35, 0x0b, 0x1c, 0x0b, 0x03, 0x0b, 0xea, 0x0a, 0xd1, 0x0a, 0xb8, 0x0a, 0x9f, 0x0a, - 0x86, 0x0a, 0x6c, 0x0a, 0x53, 0x0a, 0x39, 0x0a, 0x1f, 0x0a, 0x05, 0x0a, 0xeb, 0x09, 0xd1, 0x09, 0xb7, 0x09, 0x9d, - 0x09, 0x82, 0x09, 0x68, 0x09, 0x4e, 0x09, 0x33, 0x09, 0x19, 0x09, 0xfe, 0x08, 0xe3, 0x08, 0xc9, 0x08, 0xae, 0x08, - 0x93, 0x08, 0x79, 0x08, 0x5e, 0x08, 0x43, 0x08, 0x28, 0x08, 0x0d, 0x08, 0xf3, 0x07, 0xd8, 0x07, 0xbd, 0x07, 0xa2, - 0x07, 0x87, 0x07, 0x6d, 0x07, 0x52, 0x07, 0x37, 0x07, 0x1d, 0x07, 0x02, 0x07, 0xe7, 0x06, 0xcd, 0x06, 0xb2, 0x06, - 0x98, 0x06, 0x7e, 0x06, 0x63, 0x06, 0x49, 0x06, 0x2f, 0x06, 0x15, 0x06, 0xfb, 0x05, 0xe1, 0x05, 0xc7, 0x05, 0xad, - 0x05, 0x94, 0x05, 0x7a, 0x05, 0x61, 0x05, 0x48, 0x05, 0x2f, 0x05, 0x16, 0x05, 0xfd, 0x04, 0xe4, 0x04, 0xcb, 0x04, - 0xb3, 0x04, 0x9a, 0x04, 0x82, 0x04, 0x6a, 0x04, 0x52, 0x04, 0x3b, 0x04, 0x23, 0x04, 0x0c, 0x04, 0xf4, 0x03, 0xdd, - 0x03, 0xc7, 0x03, 0xb0, 0x03, 0x99, 0x03, 0x83, 0x03, 0x6d, 0x03, 0x57, 0x03, 0x41, 0x03, 0x2c, 0x03, 0x17, 0x03, - 0x02, 0x03, 0xed, 0x02, 0xd8, 0x02, 0xc4, 0x02, 0xb0, 0x02, 0x9c, 0x02, 0x88, 0x02, 0x75, 0x02, 0x61, 0x02, 0x4e, - 0x02, 0x3c, 0x02, 0x29, 0x02, 0x17, 0x02, 0x05, 0x02, 0xf3, 0x01, 0xe2, 0x01, 0xd1, 0x01, 0xc0, 0x01, 0xaf, 0x01, - 0x9f, 0x01, 0x8f, 0x01, 0x7f, 0x01, 0x70, 0x01, 0x61, 0x01, 0x52, 0x01, 0x43, 0x01, 0x35, 0x01, 0x27, 0x01, 0x19, - 0x01, 0x0c, 0x01, 0xff, 0x00, 0xf2, 0x00, 0xe5, 0x00, 0xd9, 0x00, 0xcd, 0x00, 0xc2, 0x00, 0xb7, 0x00, 0xac, 0x00, - 0xa1, 0x00, 0x97, 0x00, 0x8d, 0x00, 0x83, 0x00, 0x7a, 0x00, 0x71, 0x00, 0x68, 0x00, 0x60, 0x00, 0x58, 0x00, 0x51, - 0x00, 0x49, 0x00, 0x42, 0x00, 0x3c, 0x00, 0x35, 0x00, 0x30, 0x00, 0x2a, 0x00, 0x25, 0x00, 0x20, 0x00, 0x1b, 0x00, - 0x17, 0x00, 0x13, 0x00, 0x10, 0x00, 0x0d, 0x00, 0x0a, 0x00, 0x07, 0x00, 0x05, 0x00, 0x04, 0x00, 0x02, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0xee, 0xff, 0xff, 0x38, 0xee, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x4d, 0x4c, - 0x49, 0x52, 0x20, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x65, 0x64, 0x2e, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, - 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0xf4, 0x05, 0x00, 0x00, 0xf8, 0x05, 0x00, - 0x00, 0xfc, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, - 0x00, 0x00, 0xa0, 0x05, 0x00, 0x00, 0x68, 0x05, 0x00, 0x00, 0x24, 0x05, 0x00, 0x00, 0xc8, 0x04, 0x00, 0x00, 0x70, - 0x04, 0x00, 0x00, 0x4c, 0x04, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0xc8, 0x03, 0x00, 0x00, 0xa4, 0x03, 0x00, 0x00, - 0x4c, 0x03, 0x00, 0x00, 0x14, 0x03, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0xc8, 0x01, 0x00, 0x00, 0x6c, 0x01, 0x00, - 0x00, 0x48, 0x01, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0x78, 0x00, - 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xf6, 0xfa, 0xff, 0xff, 0x0c, - 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x16, 0xfb, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, - 0x00, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x28, 0x00, - 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x3a, 0xfb, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, - 0x0e, 0x00, 0x00, 0x00, 0xa6, 0xfc, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x10, 0x00, 0x00, - 0x00, 0x14, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x68, 0xef, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x27, 0x00, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xd6, 0xfc, 0xff, 0xff, 0x14, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, - 0x98, 0xef, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, - 0x00, 0x12, 0x00, 0x00, 0x00, 0x06, 0xfd, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x10, 0x00, - 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0xc8, 0xef, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x25, - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x36, 0xfd, 0xff, 0xff, - 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, - 0x00, 0xf8, 0xef, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x23, 0x00, - 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x1e, 0xfc, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, - 0x84, 0xfc, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, - 0x00, 0x30, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x00, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x73, 0x63, 0x61, 0x6c, - 0x65, 0x00, 0x02, 0x24, 0x0f, 0x02, 0x01, 0x02, 0x03, 0x40, 0x04, 0x04, 0x04, 0x24, 0x01, 0x01, 0x00, 0x00, 0x00, - 0x22, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0xdc, 0xfc, 0xff, 0xff, 0x10, 0x00, 0x00, - 0x00, 0x24, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x73, 0x6e, - 0x72, 0x5f, 0x73, 0x68, 0x69, 0x66, 0x74, 0x00, 0x01, 0x0b, 0x01, 0x01, 0x01, 0x06, 0x04, 0x02, 0x24, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x20, 0xfd, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, - 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00, 0x61, 0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x5f, - 0x6f, 0x6e, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x75, 0x73, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, - 0x00, 0x61, 0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x69, 0x6e, - 0x67, 0x00, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x69, 0x6e, 0x67, 0x00, 0x6d, 0x69, 0x6e, 0x5f, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x00, 0x6e, 0x75, 0x6d, 0x5f, 0x63, 0x68, - 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x00, 0x6f, 0x6e, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x75, 0x73, 0x5f, 0x73, 0x6d, - 0x6f, 0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x00, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x00, 0x73, - 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x00, 0x73, 0x70, 0x65, 0x63, 0x74, - 0x72, 0x61, 0x6c, 0x5f, 0x73, 0x75, 0x62, 0x74, 0x72, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x69, 0x74, - 0x73, 0x00, 0x09, 0xa5, 0x88, 0x75, 0x6d, 0x59, 0x4d, 0x3a, 0x31, 0x23, 0x09, 0x00, 0x01, 0x00, 0x09, 0x00, 0x29, - 0x3c, 0xd7, 0x03, 0x00, 0x00, 0x33, 0x03, 0x28, 0x00, 0x67, 0x3e, 0x99, 0x01, 0x0a, 0x00, 0x0e, 0x00, 0x05, 0x05, - 0x69, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x1b, 0x25, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x20, 0xfe, 0xff, 0xff, 0x10, 0x00, - 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x24, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x1d, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x54, 0xfe, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, - 0x00, 0x2c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x6e, 0x75, 0x6d, 0x5f, 0x63, 0x68, - 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x00, 0x01, 0x0e, 0x01, 0x01, 0x01, 0x28, 0x04, 0x02, 0x24, 0x01, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, - 0x0c, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x62, 0xfe, 0xff, - 0xff, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0xca, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0a, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x8c, 0xf2, 0xff, 0xff, - 0x01, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x0b, 0x00, - 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x14, - 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xd0, 0xf2, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, - 0x00, 0xfe, 0xfe, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x64, 0xff, 0xff, 0xff, 0x10, - 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, - 0x65, 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x00, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x69, 0x6e, 0x64, - 0x65, 0x78, 0x00, 0x02, 0x17, 0x0e, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0xf1, 0x00, 0x05, 0x00, 0x05, 0x05, - 0x06, 0x25, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, - 0x00, 0x00, 0x00, 0xb8, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x54, 0x00, 0x66, 0x66, 0x74, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, - 0x68, 0x00, 0x02, 0x0e, 0x0d, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x02, 0x05, 0x05, 0x06, 0x25, - 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x10, - 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x24, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, - 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, - 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x10, 0x00, - 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x73, - 0x68, 0x69, 0x66, 0x74, 0x00, 0x01, 0x07, 0x01, 0x01, 0x01, 0x0c, 0x04, 0x02, 0x24, 0x01, 0x01, 0x00, 0x00, 0x00, - 0x13, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x2a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0xc4, 0x0a, - 0x00, 0x00, 0x74, 0x0a, 0x00, 0x00, 0x3c, 0x0a, 0x00, 0x00, 0x04, 0x0a, 0x00, 0x00, 0xd0, 0x09, 0x00, 0x00, 0x88, - 0x09, 0x00, 0x00, 0x40, 0x09, 0x00, 0x00, 0xfc, 0x08, 0x00, 0x00, 0xb8, 0x08, 0x00, 0x00, 0x6c, 0x08, 0x00, 0x00, - 0x20, 0x08, 0x00, 0x00, 0xd4, 0x07, 0x00, 0x00, 0x88, 0x07, 0x00, 0x00, 0x3c, 0x07, 0x00, 0x00, 0xf8, 0x06, 0x00, - 0x00, 0xb8, 0x06, 0x00, 0x00, 0x84, 0x06, 0x00, 0x00, 0x50, 0x06, 0x00, 0x00, 0x1c, 0x06, 0x00, 0x00, 0xd8, 0x05, - 0x00, 0x00, 0xa0, 0x05, 0x00, 0x00, 0x58, 0x05, 0x00, 0x00, 0x14, 0x05, 0x00, 0x00, 0xd8, 0x04, 0x00, 0x00, 0x98, - 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x20, 0x04, 0x00, 0x00, 0xe8, 0x03, 0x00, 0x00, 0xb0, 0x03, 0x00, 0x00, - 0x6c, 0x03, 0x00, 0x00, 0x1c, 0x03, 0x00, 0x00, 0xc4, 0x02, 0x00, 0x00, 0x68, 0x02, 0x00, 0x00, 0x2c, 0x02, 0x00, - 0x00, 0xe4, 0x01, 0x00, 0x00, 0xac, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, 0x08, 0x01, - 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xfe, - 0xf5, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x09, 0x20, 0x00, 0x00, 0x00, 0x44, 0xf5, 0xff, 0xff, 0x11, 0x00, 0x00, 0x00, 0x50, 0x61, 0x72, - 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x43, 0x61, 0x6c, 0x6c, 0x3a, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x3e, 0xf6, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, 0x14, - 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x84, 0xf5, 0xff, 0xff, - 0x0d, 0x00, 0x00, 0x00, 0x63, 0x6c, 0x69, 0x70, 0x5f, 0x62, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x7a, 0xf6, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, - 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x24, 0x00, 0x00, 0x00, 0xc0, - 0xf5, 0xff, 0xff, 0x15, 0x00, 0x00, 0x00, 0x63, 0x6c, 0x69, 0x70, 0x5f, 0x62, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x2f, 0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, - 0x00, 0xbe, 0xf6, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x28, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x00, 0x04, 0xf6, 0xff, 0xff, 0x05, 0x00, 0x00, 0x00, 0x61, - 0x64, 0x64, 0x5f, 0x31, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xf2, 0xf6, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x18, 0x00, 0x00, 0x00, 0x38, 0xf6, 0xff, 0xff, 0x0b, 0x00, 0x00, 0x00, 0x54, 0x72, 0x75, 0x6e, 0x63, 0x61, - 0x74, 0x65, 0x44, 0x69, 0x76, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x2a, 0xf7, 0xff, 0xff, 0x00, - 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, - 0x10, 0x00, 0x00, 0x00, 0x70, 0xf6, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x61, 0x64, 0x64, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x28, 0x00, 0x00, 0x00, 0x5a, 0xf7, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, - 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0xa0, 0xf6, 0xff, 0xff, 0x03, - 0x00, 0x00, 0x00, 0x6d, 0x75, 0x6c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x8a, 0xf7, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x14, 0x00, 0x00, 0x00, 0xd0, 0xf6, 0xff, 0xff, 0x06, 0x00, 0x00, 0x00, 0x43, 0x61, 0x73, 0x74, 0x5f, 0x32, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xbe, 0xf7, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x14, - 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x24, 0x00, 0x00, 0x00, - 0x04, 0xf7, 0xff, 0xff, 0x16, 0x00, 0x00, 0x00, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x5f, 0x66, 0x69, 0x6c, 0x74, - 0x65, 0x72, 0x5f, 0x62, 0x61, 0x6e, 0x6b, 0x5f, 0x6c, 0x6f, 0x67, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, - 0x00, 0x00, 0x02, 0xf8, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x22, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x18, 0x00, 0x00, 0x00, 0x48, 0xf7, 0xff, 0xff, 0x0b, 0x00, 0x00, 0x00, - 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x5f, 0x70, 0x63, 0x61, 0x6e, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, - 0x00, 0x3a, 0xf8, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x21, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x38, 0x00, 0x00, 0x00, 0x80, 0xf7, 0xff, 0xff, 0x28, 0x00, 0x00, 0x00, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x5f, 0x62, 0x61, 0x6e, 0x6b, 0x5f, 0x73, - 0x70, 0x65, 0x63, 0x74, 0x72, 0x61, 0x6c, 0x5f, 0x73, 0x75, 0x62, 0x74, 0x72, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x31, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x92, 0xf8, 0xff, 0xff, 0x00, 0x00, - 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x34, - 0x00, 0x00, 0x00, 0xd8, 0xf7, 0xff, 0xff, 0x27, 0x00, 0x00, 0x00, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x5f, 0x66, - 0x69, 0x6c, 0x74, 0x65, 0x72, 0x5f, 0x62, 0x61, 0x6e, 0x6b, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x74, 0x72, 0x61, 0x6c, - 0x5f, 0x73, 0x75, 0x62, 0x74, 0x72, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, - 0x00, 0x00, 0xe6, 0xf8, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1f, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x2c, 0x00, 0x00, 0x00, 0x2c, 0xf8, 0xff, 0xff, 0x1e, 0x00, 0x00, 0x00, - 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x5f, 0x62, 0x61, 0x6e, 0x6b, 0x5f, - 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, - 0x00, 0x00, 0x32, 0xf9, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1e, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x20, 0x00, 0x00, 0x00, 0x78, 0xf8, 0xff, 0xff, 0x12, 0x00, 0x00, 0x00, - 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x5f, 0x62, 0x61, 0x6e, 0x6b, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x72, 0xf9, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, - 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x14, 0x00, 0x00, 0x00, 0xb8, - 0xf8, 0xff, 0xff, 0x06, 0x00, 0x00, 0x00, 0x43, 0x61, 0x73, 0x74, 0x5f, 0x31, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x01, 0x01, 0x00, 0x00, 0xa6, 0xf9, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, - 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x00, 0xec, 0xf8, 0xff, 0xff, 0x06, 0x00, - 0x00, 0x00, 0x63, 0x6f, 0x6e, 0x63, 0x61, 0x74, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0xda, - 0xf9, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x20, 0xf9, 0xff, 0xff, 0x0d, 0x00, 0x00, 0x00, 0x73, 0x74, 0x72, - 0x69, 0x64, 0x65, 0x64, 0x5f, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xec, 0x00, - 0x00, 0x00, 0x16, 0xfa, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x00, 0x5c, 0xf9, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, - 0x43, 0x61, 0x73, 0x74, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x4a, 0xfa, 0xff, - 0xff, 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0f, 0x1c, 0x00, 0x00, 0x00, 0x90, 0xf9, 0xff, 0xff, 0x0d, 0x00, 0x00, 0x00, 0x73, 0x69, 0x67, 0x6e, 0x61, - 0x6c, 0x5f, 0x65, 0x6e, 0x65, 0x72, 0x67, 0x79, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, - 0x86, 0xfa, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x07, 0x18, 0x00, 0x00, 0x00, 0xcc, 0xf9, 0xff, 0xff, 0x0b, 0x00, 0x00, 0x00, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x66, 0x66, 0x74, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0xbe, - 0xfa, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x02, 0x24, 0x00, 0x00, 0x00, 0x04, 0xfa, 0xff, 0xff, 0x16, 0x00, 0x00, 0x00, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x6c, 0x5f, 0x66, 0x66, 0x74, 0x5f, 0x61, 0x75, 0x74, 0x6f, 0x5f, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x31, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfa, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, 0x14, - 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x24, 0x00, 0x00, 0x00, 0x44, 0xfa, 0xff, 0xff, - 0x15, 0x00, 0x00, 0x00, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x5f, 0x66, 0x66, 0x74, 0x5f, 0x61, 0x75, 0x74, 0x6f, - 0x5f, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x42, 0xfb, - 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x07, 0x14, 0x00, 0x00, 0x00, 0x88, 0xfa, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x52, 0x65, 0x73, 0x68, - 0x61, 0x70, 0x65, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x76, 0xfb, 0xff, 0xff, 0x00, 0x00, 0x00, - 0x01, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x1c, 0x00, - 0x00, 0x00, 0xbc, 0xfa, 0xff, 0xff, 0x0d, 0x00, 0x00, 0x00, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x5f, 0x77, 0x69, - 0x6e, 0x64, 0x6f, 0x77, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, - 0xb6, 0xfb, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x00, 0xfc, 0xfa, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x43, 0x6f, - 0x6e, 0x73, 0x74, 0x5f, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xfb, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x14, - 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x00, - 0x2c, 0xfb, 0xff, 0xff, 0x06, 0x00, 0x00, 0x00, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x16, 0xfc, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x11, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x00, 0x5c, 0xfb, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x43, - 0x6f, 0x6e, 0x73, 0x74, 0x5f, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0xfc, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, - 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, - 0x00, 0x8c, 0xfb, 0xff, 0xff, 0x0d, 0x00, 0x00, 0x00, 0x52, 0x65, 0x73, 0x68, 0x61, 0x70, 0x65, 0x2f, 0x73, 0x68, - 0x61, 0x70, 0x65, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x82, 0xfc, 0xff, 0xff, 0x00, - 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, - 0x24, 0x00, 0x00, 0x00, 0xc8, 0xfb, 0xff, 0xff, 0x17, 0x00, 0x00, 0x00, 0x63, 0x6c, 0x69, 0x70, 0x5f, 0x62, 0x79, - 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2f, 0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x2f, 0x79, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc2, 0xfc, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0e, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x28, 0x00, 0x00, 0x00, 0x08, 0xfc, 0xff, 0xff, 0x18, 0x00, 0x00, 0x00, - 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x5f, 0x62, 0x61, 0x6e, 0x6b, 0x2f, - 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3c, 0x01, 0x00, 0x00, 0x0a, 0xfd, - 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x07, 0x28, 0x00, 0x00, 0x00, 0x50, 0xfc, 0xff, 0xff, 0x1a, 0x00, 0x00, 0x00, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x6c, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x5f, 0x62, 0x61, 0x6e, 0x6b, 0x2f, 0x43, 0x6f, 0x6e, 0x73, - 0x74, 0x5f, 0x31, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3c, 0x01, 0x00, 0x00, 0x52, 0xfd, 0xff, 0xff, 0x00, 0x00, - 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x28, - 0x00, 0x00, 0x00, 0x98, 0xfc, 0xff, 0xff, 0x1a, 0x00, 0x00, 0x00, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x5f, 0x66, - 0x69, 0x6c, 0x74, 0x65, 0x72, 0x5f, 0x62, 0x61, 0x6e, 0x6b, 0x2f, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x5f, 0x32, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x9a, 0xfd, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, - 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x28, 0x00, 0x00, 0x00, 0xe0, - 0xfc, 0xff, 0xff, 0x1a, 0x00, 0x00, 0x00, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, - 0x72, 0x5f, 0x62, 0x61, 0x6e, 0x6b, 0x2f, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x5f, 0x33, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x29, 0x00, 0x00, 0x00, 0xe2, 0xfd, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, - 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x28, 0x00, 0x00, 0x00, 0x28, 0xfd, 0xff, 0xff, 0x1a, - 0x00, 0x00, 0x00, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x5f, 0x62, 0x61, - 0x6e, 0x6b, 0x2f, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x5f, 0x34, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, - 0x00, 0x2a, 0xfe, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x09, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x20, 0x00, 0x00, 0x00, 0x70, 0xfd, 0xff, 0xff, 0x11, 0x00, 0x00, 0x00, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x5f, 0x70, 0x63, 0x61, 0x6e, 0x2f, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x6a, 0xfe, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, - 0x00, 0x14, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0xb0, 0xfd, - 0xff, 0xff, 0x13, 0x00, 0x00, 0x00, 0x73, 0x74, 0x72, 0x69, 0x64, 0x65, 0x64, 0x5f, 0x73, 0x6c, 0x69, 0x63, 0x65, - 0x2f, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xfe, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x24, 0x00, 0x00, 0x00, 0xf0, 0xfd, 0xff, 0xff, 0x15, 0x00, 0x00, 0x00, 0x73, 0x74, 0x72, 0x69, 0x64, 0x65, - 0x64, 0x5f, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x2f, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x5f, 0x31, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xee, 0xfe, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, - 0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x24, 0x00, 0x00, 0x00, 0x34, 0xfe, 0xff, - 0xff, 0x15, 0x00, 0x00, 0x00, 0x73, 0x74, 0x72, 0x69, 0x64, 0x65, 0x64, 0x5f, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x2f, - 0x73, 0x74, 0x61, 0x63, 0x6b, 0x5f, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x32, - 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x00, 0x78, 0xfe, 0xff, 0xff, 0x06, 0x00, 0x00, 0x00, 0x43, 0x61, 0x73, - 0x74, 0x5f, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, - 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x00, 0xa8, - 0xfe, 0xff, 0xff, 0x05, 0x00, 0x00, 0x00, 0x7a, 0x65, 0x72, 0x6f, 0x73, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x96, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x00, 0xdc, 0xfe, 0xff, 0xff, 0x07, 0x00, - 0x00, 0x00, 0x7a, 0x65, 0x72, 0x6f, 0x73, 0x5f, 0x31, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xca, - 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x07, 0x14, 0x00, 0x00, 0x00, 0x10, 0xff, 0xff, 0xff, 0x05, 0x00, 0x00, 0x00, 0x43, 0x6f, 0x6e, - 0x73, 0x74, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x1c, 0x00, - 0x18, 0x00, 0x17, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x16, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x07, 0x2c, 0x00, 0x00, 0x00, 0x5c, 0xff, 0xff, 0xff, 0x1d, 0x00, 0x00, 0x00, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x5f, - 0x66, 0x72, 0x61, 0x6d, 0x65, 0x3a, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, - 0x01, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x1c, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0xc8, 0x01, 0x00, 0x00, - 0xa4, 0x01, 0x00, 0x00, 0x7c, 0x01, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00, 0x4c, 0x01, 0x00, 0x00, 0x3c, 0x01, 0x00, - 0x00, 0x10, 0x01, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x50, 0x00, - 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x00, 0x50, 0xfe, 0xff, 0xff, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x5c, 0xfe, 0xff, 0xff, - 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0x68, 0xfe, 0xff, 0xff, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x2a, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7c, 0xfe, 0xff, 0xff, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x12, 0x70, 0xfe, 0xff, 0xff, 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x13, - 0x00, 0x00, 0x00, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x42, 0x61, 0x6e, 0x6b, - 0x4c, 0x6f, 0x67, 0x00, 0x98, 0xfe, 0xff, 0xff, 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x20, 0x0a, 0x00, 0x00, 0x00, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x50, 0x43, 0x41, 0x4e, 0x00, 0x00, 0xb8, 0xfe, - 0xff, 0xff, 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x23, 0x00, 0x00, 0x00, 0x53, - 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x42, 0x61, 0x6e, 0x6b, 0x53, 0x70, 0x65, 0x63, - 0x74, 0x72, 0x61, 0x6c, 0x53, 0x75, 0x62, 0x74, 0x72, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xf0, 0xfe, 0xff, - 0xff, 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x1a, 0x00, 0x00, 0x00, 0x53, 0x69, - 0x67, 0x6e, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x42, 0x61, 0x6e, 0x6b, 0x53, 0x71, 0x75, 0x61, 0x72, - 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x00, 0x00, 0x20, 0xff, 0xff, 0xff, 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x74, 0x65, - 0x72, 0x42, 0x61, 0x6e, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x60, 0xff, 0xff, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x6c, 0xff, 0xff, 0xff, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x0c, 0x00, 0x10, 0x00, 0x0f, - 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x35, 0x7c, 0xff, 0xff, 0xff, 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x20, 0x0c, 0x00, 0x00, 0x00, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x45, 0x6e, 0x65, 0x72, 0x67, 0x79, 0x00, 0x00, - 0x00, 0x00, 0xa0, 0xff, 0xff, 0xff, 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x0a, - 0x00, 0x00, 0x00, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x52, 0x66, 0x66, 0x74, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, - 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x12, 0x00, 0x00, 0x00, 0x53, 0x69, 0x67, - 0x6e, 0x61, 0x6c, 0x46, 0x66, 0x74, 0x41, 0x75, 0x74, 0x6f, 0x53, 0x63, 0x61, 0x6c, 0x65, 0x00, 0x00, 0x0c, 0x00, - 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x16, 0x0c, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x0c, 0x00, 0x00, 0x00, 0x53, 0x69, 0x67, - 0x6e, 0x61, 0x6c, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x00, 0x00, 0x00, 0x00}; - -} // namespace micro_wake_word -} // namespace esphome - -#endif // USE_ESP_IDF diff --git a/esphome/components/micro_wake_word/micro_wake_word.cpp b/esphome/components/micro_wake_word/micro_wake_word.cpp index 5a89708127..b58c7ec434 100644 --- a/esphome/components/micro_wake_word/micro_wake_word.cpp +++ b/esphome/components/micro_wake_word/micro_wake_word.cpp @@ -1,12 +1,5 @@ #include "micro_wake_word.h" - -/** - * This is a workaround until we can figure out a way to get - * the tflite-micro idf component code available in CI - * - * */ -// -#ifndef CLANG_TIDY +#include "streaming_model.h" #ifdef USE_ESP_IDF @@ -14,13 +7,13 @@ #include "esphome/core/helpers.h" #include "esphome/core/log.h" -#include "audio_preprocessor_int8_model_data.h" +#include +#include #include #include #include -#include #include namespace esphome { @@ -29,9 +22,9 @@ namespace micro_wake_word { static const char *const TAG = "micro_wake_word"; static const size_t SAMPLE_RATE_HZ = 16000; // 16 kHz -static const size_t BUFFER_LENGTH = 500; // 0.5 seconds +static const size_t BUFFER_LENGTH = 64; // 0.064 seconds static const size_t BUFFER_SIZE = SAMPLE_RATE_HZ / 1000 * BUFFER_LENGTH; -static const size_t INPUT_BUFFER_SIZE = 32 * SAMPLE_RATE_HZ / 1000; // 32ms * 16kHz / 1000ms +static const size_t INPUT_BUFFER_SIZE = 16 * SAMPLE_RATE_HZ / 1000; // 16ms * 16kHz / 1000ms float MicroWakeWord::get_setup_priority() const { return setup_priority::AFTER_CONNECTION; } @@ -56,58 +49,56 @@ static const LogString *micro_wake_word_state_to_string(State state) { void MicroWakeWord::dump_config() { ESP_LOGCONFIG(TAG, "microWakeWord:"); - ESP_LOGCONFIG(TAG, " Wake Word: %s", this->get_wake_word().c_str()); - ESP_LOGCONFIG(TAG, " Probability cutoff: %.3f", this->probability_cutoff_); - ESP_LOGCONFIG(TAG, " Sliding window size: %d", this->sliding_window_average_size_); + ESP_LOGCONFIG(TAG, " models:"); + for (auto &model : this->wake_word_models_) { + model.log_model_config(); + } +#ifdef USE_MICRO_WAKE_WORD_VAD + this->vad_model_->log_model_config(); +#endif } void MicroWakeWord::setup() { ESP_LOGCONFIG(TAG, "Setting up microWakeWord..."); - if (!this->initialize_models()) { - ESP_LOGE(TAG, "Failed to initialize models"); - this->mark_failed(); - return; - } - - ExternalRAMAllocator allocator(ExternalRAMAllocator::ALLOW_FAILURE); - this->input_buffer_ = allocator.allocate(INPUT_BUFFER_SIZE * sizeof(int16_t)); - if (this->input_buffer_ == nullptr) { - ESP_LOGW(TAG, "Could not allocate input buffer"); - this->mark_failed(); - return; - } - - this->ring_buffer_ = RingBuffer::create(BUFFER_SIZE * sizeof(int16_t)); - if (this->ring_buffer_ == nullptr) { - ESP_LOGW(TAG, "Could not allocate ring buffer"); + if (!this->register_streaming_ops_(this->streaming_op_resolver_)) { this->mark_failed(); return; } ESP_LOGCONFIG(TAG, "Micro Wake Word initialized"); + + this->frontend_config_.window.size_ms = FEATURE_DURATION_MS; + this->frontend_config_.window.step_size_ms = this->features_step_size_; + this->frontend_config_.filterbank.num_channels = PREPROCESSOR_FEATURE_SIZE; + this->frontend_config_.filterbank.lower_band_limit = 125.0; + this->frontend_config_.filterbank.upper_band_limit = 7500.0; + this->frontend_config_.noise_reduction.smoothing_bits = 10; + this->frontend_config_.noise_reduction.even_smoothing = 0.025; + this->frontend_config_.noise_reduction.odd_smoothing = 0.06; + this->frontend_config_.noise_reduction.min_signal_remaining = 0.05; + this->frontend_config_.pcan_gain_control.enable_pcan = 1; + this->frontend_config_.pcan_gain_control.strength = 0.95; + this->frontend_config_.pcan_gain_control.offset = 80.0; + this->frontend_config_.pcan_gain_control.gain_bits = 21; + this->frontend_config_.log_scale.enable_log = 1; + this->frontend_config_.log_scale.scale_shift = 6; } -int MicroWakeWord::read_microphone_() { - size_t bytes_read = this->microphone_->read(this->input_buffer_, INPUT_BUFFER_SIZE * sizeof(int16_t)); - if (bytes_read == 0) { - return 0; - } - - size_t bytes_free = this->ring_buffer_->free(); - - if (bytes_free < bytes_read) { - ESP_LOGW(TAG, - "Not enough free bytes in ring buffer to store incoming audio data (free bytes=%d, incoming bytes=%d). " - "Resetting the ring buffer. Wake word detection accuracy will be reduced.", - bytes_free, bytes_read); - - this->ring_buffer_->reset(); - } - - return this->ring_buffer_->write((void *) this->input_buffer_, bytes_read); +void MicroWakeWord::add_wake_word_model(const uint8_t *model_start, float probability_cutoff, + size_t sliding_window_average_size, const std::string &wake_word, + size_t tensor_arena_size) { + this->wake_word_models_.emplace_back(model_start, probability_cutoff, sliding_window_average_size, wake_word, + tensor_arena_size); } +#ifdef USE_MICRO_WAKE_WORD_VAD +void MicroWakeWord::add_vad_model(const uint8_t *model_start, float probability_cutoff, size_t sliding_window_size, + size_t tensor_arena_size) { + this->vad_model_ = make_unique(model_start, probability_cutoff, sliding_window_size, tensor_arena_size); +} +#endif + void MicroWakeWord::loop() { switch (this->state_) { case State::IDLE: @@ -124,9 +115,12 @@ void MicroWakeWord::loop() { } break; case State::DETECTING_WAKE_WORD: - this->read_microphone_(); - if (this->detect_wake_word_()) { - ESP_LOGD(TAG, "Wake Word Detected"); + while (!this->has_enough_samples_()) { + this->read_microphone_(); + } + this->update_model_probabilities_(); + if (this->detect_wake_words_()) { + ESP_LOGD(TAG, "Wake Word '%s' Detected", (this->detected_wake_word_).c_str()); this->detected_ = true; this->set_state_(State::STOP_MICROPHONE); } @@ -136,13 +130,16 @@ void MicroWakeWord::loop() { this->microphone_->stop(); this->set_state_(State::STOPPING_MICROPHONE); this->high_freq_.stop(); + this->unload_models_(); + this->deallocate_buffers_(); break; case State::STOPPING_MICROPHONE: if (this->microphone_->is_stopped()) { this->set_state_(State::IDLE); if (this->detected_) { + this->wake_word_detected_trigger_->trigger(this->detected_wake_word_); this->detected_ = false; - this->wake_word_detected_trigger_->trigger(this->wake_word_); + this->detected_wake_word_ = ""; } } break; @@ -150,14 +147,34 @@ void MicroWakeWord::loop() { } void MicroWakeWord::start() { + if (!this->is_ready()) { + ESP_LOGW(TAG, "Wake word detection can't start as the component hasn't been setup yet"); + return; + } + if (this->is_failed()) { ESP_LOGW(TAG, "Wake word component is marked as failed. Please check setup logs"); return; } + + if (!this->load_models_() || !this->allocate_buffers_()) { + ESP_LOGE(TAG, "Failed to load the wake word model(s) or allocate buffers"); + this->status_set_error(); + } else { + this->status_clear_error(); + } + + if (this->status_has_error()) { + ESP_LOGW(TAG, "Wake word component has an error. Please check logs"); + return; + } + if (this->state_ != State::IDLE) { ESP_LOGW(TAG, "Wake word is already running"); return; } + + this->reset_states_(); this->set_state_(State::START_MICROPHONE); } @@ -179,289 +196,218 @@ void MicroWakeWord::set_state_(State state) { this->state_ = state; } -bool MicroWakeWord::initialize_models() { - ExternalRAMAllocator arena_allocator(ExternalRAMAllocator::ALLOW_FAILURE); - ExternalRAMAllocator features_allocator(ExternalRAMAllocator::ALLOW_FAILURE); +size_t MicroWakeWord::read_microphone_() { + size_t bytes_read = this->microphone_->read(this->input_buffer_, INPUT_BUFFER_SIZE * sizeof(int16_t)); + if (bytes_read == 0) { + return 0; + } + + size_t bytes_free = this->ring_buffer_->free(); + + if (bytes_free < bytes_read) { + ESP_LOGW(TAG, + "Not enough free bytes in ring buffer to store incoming audio data (free bytes=%d, incoming bytes=%d). " + "Resetting the ring buffer. Wake word detection accuracy will be reduced.", + bytes_free, bytes_read); + + this->ring_buffer_->reset(); + } + + return this->ring_buffer_->write((void *) this->input_buffer_, bytes_read); +} + +bool MicroWakeWord::allocate_buffers_() { ExternalRAMAllocator audio_samples_allocator(ExternalRAMAllocator::ALLOW_FAILURE); - this->streaming_tensor_arena_ = arena_allocator.allocate(STREAMING_MODEL_ARENA_SIZE); - if (this->streaming_tensor_arena_ == nullptr) { - ESP_LOGE(TAG, "Could not allocate the streaming model's tensor arena."); - return false; + if (this->input_buffer_ == nullptr) { + this->input_buffer_ = audio_samples_allocator.allocate(INPUT_BUFFER_SIZE * sizeof(int16_t)); + if (this->input_buffer_ == nullptr) { + ESP_LOGE(TAG, "Could not allocate input buffer"); + return false; + } } - this->streaming_var_arena_ = arena_allocator.allocate(STREAMING_MODEL_VARIABLE_ARENA_SIZE); - if (this->streaming_var_arena_ == nullptr) { - ESP_LOGE(TAG, "Could not allocate the streaming model variable's tensor arena."); - return false; - } - - this->preprocessor_tensor_arena_ = arena_allocator.allocate(PREPROCESSOR_ARENA_SIZE); - if (this->preprocessor_tensor_arena_ == nullptr) { - ESP_LOGE(TAG, "Could not allocate the audio preprocessor model's tensor arena."); - return false; - } - - this->new_features_data_ = features_allocator.allocate(PREPROCESSOR_FEATURE_SIZE); - if (this->new_features_data_ == nullptr) { - ESP_LOGE(TAG, "Could not allocate the audio features buffer."); - return false; - } - - this->preprocessor_audio_buffer_ = audio_samples_allocator.allocate(SAMPLE_DURATION_COUNT); if (this->preprocessor_audio_buffer_ == nullptr) { - ESP_LOGE(TAG, "Could not allocate the audio preprocessor's buffer."); - return false; + this->preprocessor_audio_buffer_ = audio_samples_allocator.allocate(this->new_samples_to_get_()); + if (this->preprocessor_audio_buffer_ == nullptr) { + ESP_LOGE(TAG, "Could not allocate the audio preprocessor's buffer."); + return false; + } } - this->preprocessor_model_ = tflite::GetModel(G_AUDIO_PREPROCESSOR_INT8_TFLITE); - if (this->preprocessor_model_->version() != TFLITE_SCHEMA_VERSION) { - ESP_LOGE(TAG, "Wake word's audio preprocessor model's schema is not supported"); - return false; - } - - this->streaming_model_ = tflite::GetModel(this->model_start_); - if (this->streaming_model_->version() != TFLITE_SCHEMA_VERSION) { - ESP_LOGE(TAG, "Wake word's streaming model's schema is not supported"); - return false; - } - - static tflite::MicroMutableOpResolver<18> preprocessor_op_resolver; - static tflite::MicroMutableOpResolver<17> streaming_op_resolver; - - if (!this->register_preprocessor_ops_(preprocessor_op_resolver)) - return false; - if (!this->register_streaming_ops_(streaming_op_resolver)) - return false; - - tflite::MicroAllocator *ma = - tflite::MicroAllocator::Create(this->streaming_var_arena_, STREAMING_MODEL_VARIABLE_ARENA_SIZE); - this->mrv_ = tflite::MicroResourceVariables::Create(ma, 15); - - static tflite::MicroInterpreter static_preprocessor_interpreter( - this->preprocessor_model_, preprocessor_op_resolver, this->preprocessor_tensor_arena_, PREPROCESSOR_ARENA_SIZE); - - static tflite::MicroInterpreter static_streaming_interpreter(this->streaming_model_, streaming_op_resolver, - this->streaming_tensor_arena_, - STREAMING_MODEL_ARENA_SIZE, this->mrv_); - - this->preprocessor_interperter_ = &static_preprocessor_interpreter; - this->streaming_interpreter_ = &static_streaming_interpreter; - - // Allocate tensors for each models. - if (this->preprocessor_interperter_->AllocateTensors() != kTfLiteOk) { - ESP_LOGE(TAG, "Failed to allocate tensors for the audio preprocessor"); - return false; - } - if (this->streaming_interpreter_->AllocateTensors() != kTfLiteOk) { - ESP_LOGE(TAG, "Failed to allocate tensors for the streaming model"); - return false; - } - - // Verify input tensor matches expected values - TfLiteTensor *input = this->streaming_interpreter_->input(0); - if ((input->dims->size != 3) || (input->dims->data[0] != 1) || (input->dims->data[0] != 1) || - (input->dims->data[1] != 1) || (input->dims->data[2] != PREPROCESSOR_FEATURE_SIZE)) { - ESP_LOGE(TAG, "Wake word detection model tensor input dimensions is not 1x1x%u", input->dims->data[2]); - return false; - } - - if (input->type != kTfLiteInt8) { - ESP_LOGE(TAG, "Wake word detection model tensor input is not int8."); - return false; - } - - // Verify output tensor matches expected values - TfLiteTensor *output = this->streaming_interpreter_->output(0); - if ((output->dims->size != 2) || (output->dims->data[0] != 1) || (output->dims->data[1] != 1)) { - ESP_LOGE(TAG, "Wake word detection model tensor output dimensions is not 1x1."); - } - - if (output->type != kTfLiteUInt8) { - ESP_LOGE(TAG, "Wake word detection model tensor input is not uint8."); - return false; - } - - this->recent_streaming_probabilities_.resize(this->sliding_window_average_size_, 0.0); - - return true; -} - -bool MicroWakeWord::update_features_() { - // Retrieve strided audio samples - int16_t *audio_samples = nullptr; - if (!this->stride_audio_samples_(&audio_samples)) { - return false; - } - - // Compute the features for the newest audio samples - if (!this->generate_single_feature_(audio_samples, SAMPLE_DURATION_COUNT, this->new_features_data_)) { - return false; + if (this->ring_buffer_ == nullptr) { + this->ring_buffer_ = RingBuffer::create(BUFFER_SIZE * sizeof(int16_t)); + if (this->ring_buffer_ == nullptr) { + ESP_LOGE(TAG, "Could not allocate ring buffer"); + return false; + } } return true; } -float MicroWakeWord::perform_streaming_inference_() { - TfLiteTensor *input = this->streaming_interpreter_->input(0); - - size_t bytes_to_copy = input->bytes; - - memcpy((void *) (tflite::GetTensorData(input)), (const void *) (this->new_features_data_), bytes_to_copy); - - uint32_t prior_invoke = millis(); - - TfLiteStatus invoke_status = this->streaming_interpreter_->Invoke(); - if (invoke_status != kTfLiteOk) { - ESP_LOGW(TAG, "Streaming Interpreter Invoke failed"); - return false; - } - - ESP_LOGV(TAG, "Streaming Inference Latency=%" PRIu32 " ms", (millis() - prior_invoke)); - - TfLiteTensor *output = this->streaming_interpreter_->output(0); - - return static_cast(output->data.uint8[0]) / 255.0; +void MicroWakeWord::deallocate_buffers_() { + ExternalRAMAllocator audio_samples_allocator(ExternalRAMAllocator::ALLOW_FAILURE); + audio_samples_allocator.deallocate(this->input_buffer_, INPUT_BUFFER_SIZE * sizeof(int16_t)); + this->input_buffer_ = nullptr; + audio_samples_allocator.deallocate(this->preprocessor_audio_buffer_, this->new_samples_to_get_()); + this->preprocessor_audio_buffer_ = nullptr; } -bool MicroWakeWord::detect_wake_word_() { - // Preprocess the newest audio samples into features - if (!this->update_features_()) { +bool MicroWakeWord::load_models_() { + // Setup preprocesor feature generator + if (!FrontendPopulateState(&this->frontend_config_, &this->frontend_state_, AUDIO_SAMPLE_FREQUENCY)) { + ESP_LOGD(TAG, "Failed to populate frontend state"); + FrontendFreeStateContents(&this->frontend_state_); return false; } - // Perform inference - float streaming_prob = this->perform_streaming_inference_(); + // Setup streaming models + for (auto &model : this->wake_word_models_) { + if (!model.load_model(this->streaming_op_resolver_)) { + ESP_LOGE(TAG, "Failed to initialize a wake word model."); + return false; + } + } +#ifdef USE_MICRO_WAKE_WORD_VAD + if (!this->vad_model_->load_model(this->streaming_op_resolver_)) { + ESP_LOGE(TAG, "Failed to initialize VAD model."); + return false; + } +#endif - // Add the most recent probability to the sliding window - this->recent_streaming_probabilities_[this->last_n_index_] = streaming_prob; - ++this->last_n_index_; - if (this->last_n_index_ == this->sliding_window_average_size_) - this->last_n_index_ = 0; + return true; +} - float sum = 0.0; - for (auto &prob : this->recent_streaming_probabilities_) { - sum += prob; +void MicroWakeWord::unload_models_() { + FrontendFreeStateContents(&this->frontend_state_); + + for (auto &model : this->wake_word_models_) { + model.unload_model(); + } +#ifdef USE_MICRO_WAKE_WORD_VAD + this->vad_model_->unload_model(); +#endif +} + +void MicroWakeWord::update_model_probabilities_() { + int8_t audio_features[PREPROCESSOR_FEATURE_SIZE]; + + if (!this->generate_features_for_window_(audio_features)) { + return; } - float sliding_window_average = sum / static_cast(this->sliding_window_average_size_); - - // Ensure we have enough samples since the last positive detection + // Increase the counter since the last positive detection this->ignore_windows_ = std::min(this->ignore_windows_ + 1, 0); + + for (auto &model : this->wake_word_models_) { + // Perform inference + model.perform_streaming_inference(audio_features); + } +#ifdef USE_MICRO_WAKE_WORD_VAD + this->vad_model_->perform_streaming_inference(audio_features); +#endif +} + +bool MicroWakeWord::detect_wake_words_() { + // Verify we have processed samples since the last positive detection if (this->ignore_windows_ < 0) { return false; } - // Detect the wake word if the sliding window average is above the cutoff - if (sliding_window_average > this->probability_cutoff_) { - this->ignore_windows_ = -MIN_SLICES_BEFORE_DETECTION; - for (auto &prob : this->recent_streaming_probabilities_) { - prob = 0; - } +#ifdef USE_MICRO_WAKE_WORD_VAD + bool vad_state = this->vad_model_->determine_detected(); +#endif - ESP_LOGD(TAG, "Wake word sliding average probability is %.3f and most recent probability is %.3f", - sliding_window_average, streaming_prob); - return true; + for (auto &model : this->wake_word_models_) { + if (model.determine_detected()) { +#ifdef USE_MICRO_WAKE_WORD_VAD + if (vad_state) { +#endif + this->detected_wake_word_ = model.get_wake_word(); + return true; +#ifdef USE_MICRO_WAKE_WORD_VAD + } else { + ESP_LOGD(TAG, "Wake word model predicts %s, but VAD model doesn't.", model.get_wake_word().c_str()); + } +#endif + } } return false; } -void MicroWakeWord::set_sliding_window_average_size(size_t size) { - this->sliding_window_average_size_ = size; - this->recent_streaming_probabilities_.resize(this->sliding_window_average_size_, 0.0); +bool MicroWakeWord::has_enough_samples_() { + return this->ring_buffer_->available() >= + (this->features_step_size_ * (AUDIO_SAMPLE_FREQUENCY / 1000)) * sizeof(int16_t); } -bool MicroWakeWord::slice_available_() { - size_t available = this->ring_buffer_->available(); - - return available > (NEW_SAMPLES_TO_GET * sizeof(int16_t)); -} - -bool MicroWakeWord::stride_audio_samples_(int16_t **audio_samples) { - if (!this->slice_available_()) { +bool MicroWakeWord::generate_features_for_window_(int8_t features[PREPROCESSOR_FEATURE_SIZE]) { + // Ensure we have enough new audio samples in the ring buffer for a full window + if (!this->has_enough_samples_()) { return false; } - // Copy the last 320 bytes (160 samples over 10 ms) from the audio buffer to the start of the audio buffer - memcpy((void *) (this->preprocessor_audio_buffer_), (void *) (this->preprocessor_audio_buffer_ + NEW_SAMPLES_TO_GET), - HISTORY_SAMPLES_TO_KEEP * sizeof(int16_t)); - - // Copy 640 bytes (320 samples over 20 ms) from the ring buffer into the audio buffer offset 320 bytes (160 samples - // over 10 ms) - size_t bytes_read = this->ring_buffer_->read((void *) (this->preprocessor_audio_buffer_ + HISTORY_SAMPLES_TO_KEEP), - NEW_SAMPLES_TO_GET * sizeof(int16_t), pdMS_TO_TICKS(200)); + size_t bytes_read = this->ring_buffer_->read((void *) (this->preprocessor_audio_buffer_), + this->new_samples_to_get_() * sizeof(int16_t), pdMS_TO_TICKS(200)); if (bytes_read == 0) { ESP_LOGE(TAG, "Could not read data from Ring Buffer"); - } else if (bytes_read < NEW_SAMPLES_TO_GET * sizeof(int16_t)) { + } else if (bytes_read < this->new_samples_to_get_() * sizeof(int16_t)) { ESP_LOGD(TAG, "Partial Read of Data by Model"); ESP_LOGD(TAG, "Could only read %d bytes when required %d bytes ", bytes_read, - (int) (NEW_SAMPLES_TO_GET * sizeof(int16_t))); + (int) (this->new_samples_to_get_() * sizeof(int16_t))); return false; } - *audio_samples = this->preprocessor_audio_buffer_; - return true; -} + size_t num_samples_read; + struct FrontendOutput frontend_output = FrontendProcessSamples( + &this->frontend_state_, this->preprocessor_audio_buffer_, this->new_samples_to_get_(), &num_samples_read); -bool MicroWakeWord::generate_single_feature_(const int16_t *audio_data, const int audio_data_size, - int8_t feature_output[PREPROCESSOR_FEATURE_SIZE]) { - TfLiteTensor *input = this->preprocessor_interperter_->input(0); - TfLiteTensor *output = this->preprocessor_interperter_->output(0); - std::copy_n(audio_data, audio_data_size, tflite::GetTensorData(input)); - - if (this->preprocessor_interperter_->Invoke() != kTfLiteOk) { - ESP_LOGE(TAG, "Failed to preprocess audio for local wake word."); - return false; + for (size_t i = 0; i < frontend_output.size; ++i) { + // These scaling values are set to match the TFLite audio frontend int8 output. + // The feature pipeline outputs 16-bit signed integers in roughly a 0 to 670 + // range. In training, these are then arbitrarily divided by 25.6 to get + // float values in the rough range of 0.0 to 26.0. This scaling is performed + // for historical reasons, to match up with the output of other feature + // generators. + // The process is then further complicated when we quantize the model. This + // means we have to scale the 0.0 to 26.0 real values to the -128 to 127 + // signed integer numbers. + // All this means that to get matching values from our integer feature + // output into the tensor input, we have to perform: + // input = (((feature / 25.6) / 26.0) * 256) - 128 + // To simplify this and perform it in 32-bit integer math, we rearrange to: + // input = (feature * 256) / (25.6 * 26.0) - 128 + constexpr int32_t value_scale = 256; + constexpr int32_t value_div = 666; // 666 = 25.6 * 26.0 after rounding + int32_t value = ((frontend_output.values[i] * value_scale) + (value_div / 2)) / value_div; + value -= 128; + if (value < -128) { + value = -128; + } + if (value > 127) { + value = 127; + } + features[i] = value; } - std::memcpy(feature_output, tflite::GetTensorData(output), PREPROCESSOR_FEATURE_SIZE * sizeof(int8_t)); return true; } -bool MicroWakeWord::register_preprocessor_ops_(tflite::MicroMutableOpResolver<18> &op_resolver) { - if (op_resolver.AddReshape() != kTfLiteOk) - return false; - if (op_resolver.AddCast() != kTfLiteOk) - return false; - if (op_resolver.AddStridedSlice() != kTfLiteOk) - return false; - if (op_resolver.AddConcatenation() != kTfLiteOk) - return false; - if (op_resolver.AddMul() != kTfLiteOk) - return false; - if (op_resolver.AddAdd() != kTfLiteOk) - return false; - if (op_resolver.AddDiv() != kTfLiteOk) - return false; - if (op_resolver.AddMinimum() != kTfLiteOk) - return false; - if (op_resolver.AddMaximum() != kTfLiteOk) - return false; - if (op_resolver.AddWindow() != kTfLiteOk) - return false; - if (op_resolver.AddFftAutoScale() != kTfLiteOk) - return false; - if (op_resolver.AddRfft() != kTfLiteOk) - return false; - if (op_resolver.AddEnergy() != kTfLiteOk) - return false; - if (op_resolver.AddFilterBank() != kTfLiteOk) - return false; - if (op_resolver.AddFilterBankSquareRoot() != kTfLiteOk) - return false; - if (op_resolver.AddFilterBankSpectralSubtraction() != kTfLiteOk) - return false; - if (op_resolver.AddPCAN() != kTfLiteOk) - return false; - if (op_resolver.AddFilterBankLog() != kTfLiteOk) - return false; - - return true; +void MicroWakeWord::reset_states_() { + ESP_LOGD(TAG, "Resetting buffers and probabilities"); + this->ring_buffer_->reset(); + this->ignore_windows_ = -MIN_SLICES_BEFORE_DETECTION; + for (auto &model : this->wake_word_models_) { + model.reset_probabilities(); + } +#ifdef USE_MICRO_WAKE_WORD_VAD + this->vad_model_->reset_probabilities(); +#endif } -bool MicroWakeWord::register_streaming_ops_(tflite::MicroMutableOpResolver<17> &op_resolver) { +bool MicroWakeWord::register_streaming_ops_(tflite::MicroMutableOpResolver<20> &op_resolver) { if (op_resolver.AddCallOnce() != kTfLiteOk) return false; if (op_resolver.AddVarHandle() != kTfLiteOk) @@ -496,6 +442,12 @@ bool MicroWakeWord::register_streaming_ops_(tflite::MicroMutableOpResolver<17> & return false; if (op_resolver.AddMaxPool2D() != kTfLiteOk) return false; + if (op_resolver.AddPad() != kTfLiteOk) + return false; + if (op_resolver.AddPack() != kTfLiteOk) + return false; + if (op_resolver.AddSplitV() != kTfLiteOk) + return false; return true; } @@ -504,5 +456,3 @@ bool MicroWakeWord::register_streaming_ops_(tflite::MicroMutableOpResolver<17> & } // namespace esphome #endif // USE_ESP_IDF - -#endif // CLANG_TIDY diff --git a/esphome/components/micro_wake_word/micro_wake_word.h b/esphome/components/micro_wake_word/micro_wake_word.h index 1d7c18d686..0c805b75fc 100644 --- a/esphome/components/micro_wake_word/micro_wake_word.h +++ b/esphome/components/micro_wake_word/micro_wake_word.h @@ -1,21 +1,18 @@ #pragma once -/** - * This is a workaround until we can figure out a way to get - * the tflite-micro idf component code available in CI - * - * */ -// -#ifndef CLANG_TIDY - #ifdef USE_ESP_IDF +#include "preprocessor_settings.h" +#include "streaming_model.h" + #include "esphome/core/automation.h" #include "esphome/core/component.h" #include "esphome/core/ring_buffer.h" #include "esphome/components/microphone/microphone.h" +#include + #include #include #include @@ -23,35 +20,6 @@ namespace esphome { namespace micro_wake_word { -// The following are dictated by the preprocessor model -// -// The number of features the audio preprocessor generates per slice -static const uint8_t PREPROCESSOR_FEATURE_SIZE = 40; -// How frequently the preprocessor generates a new set of features -static const uint8_t FEATURE_STRIDE_MS = 20; -// Duration of each slice used as input into the preprocessor -static const uint8_t FEATURE_DURATION_MS = 30; -// Audio sample frequency in hertz -static const uint16_t AUDIO_SAMPLE_FREQUENCY = 16000; -// The number of old audio samples that are saved to be part of the next feature window -static const uint16_t HISTORY_SAMPLES_TO_KEEP = - ((FEATURE_DURATION_MS - FEATURE_STRIDE_MS) * (AUDIO_SAMPLE_FREQUENCY / 1000)); -// The number of new audio samples to receive to be included with the next feature window -static const uint16_t NEW_SAMPLES_TO_GET = (FEATURE_STRIDE_MS * (AUDIO_SAMPLE_FREQUENCY / 1000)); -// The total number of audio samples included in the feature window -static const uint16_t SAMPLE_DURATION_COUNT = FEATURE_DURATION_MS * AUDIO_SAMPLE_FREQUENCY / 1000; -// Number of bytes in memory needed for the preprocessor arena -static const uint32_t PREPROCESSOR_ARENA_SIZE = 9528; - -// The following configure the streaming wake word model -// -// The number of audio slices to process before accepting a positive detection -static const uint8_t MIN_SLICES_BEFORE_DETECTION = 74; - -// Number of bytes in memory needed for the streaming wake word model -static const uint32_t STREAMING_MODEL_ARENA_SIZE = 64000; -static const uint32_t STREAMING_MODEL_VARIABLE_ARENA_SIZE = 1024; - enum State { IDLE, START_MICROPHONE, @@ -61,6 +29,9 @@ enum State { STOPPING_MICROPHONE, }; +// The number of audio slices to process before accepting a positive detection +static const uint8_t MIN_SLICES_BEFORE_DETECTION = 74; + class MicroWakeWord : public Component { public: void setup() override; @@ -73,28 +44,21 @@ class MicroWakeWord : public Component { bool is_running() const { return this->state_ != State::IDLE; } - bool initialize_models(); - - std::string get_wake_word() { return this->wake_word_; } - - // Increasing either of these will reduce the rate of false acceptances while increasing the false rejection rate - void set_probability_cutoff(float probability_cutoff) { this->probability_cutoff_ = probability_cutoff; } - void set_sliding_window_average_size(size_t size); + void set_features_step_size(uint8_t step_size) { this->features_step_size_ = step_size; } void set_microphone(microphone::Microphone *microphone) { this->microphone_ = microphone; } Trigger *get_wake_word_detected_trigger() const { return this->wake_word_detected_trigger_; } - void set_model_start(const uint8_t *model_start) { this->model_start_ = model_start; } - void set_wake_word(const std::string &wake_word) { this->wake_word_ = wake_word; } + void add_wake_word_model(const uint8_t *model_start, float probability_cutoff, size_t sliding_window_average_size, + const std::string &wake_word, size_t tensor_arena_size); + +#ifdef USE_MICRO_WAKE_WORD_VAD + void add_vad_model(const uint8_t *model_start, float probability_cutoff, size_t sliding_window_size, + size_t tensor_arena_size); +#endif protected: - void set_state_(State state); - int read_microphone_(); - - const uint8_t *model_start_; - std::string wake_word_; - microphone::Microphone *microphone_{nullptr}; Trigger *wake_word_detected_trigger_ = new Trigger(); State state_{State::IDLE}; @@ -102,85 +66,93 @@ class MicroWakeWord : public Component { std::unique_ptr ring_buffer_; - int16_t *input_buffer_; + std::vector wake_word_models_; - const tflite::Model *preprocessor_model_{nullptr}; - const tflite::Model *streaming_model_{nullptr}; - tflite::MicroInterpreter *streaming_interpreter_{nullptr}; - tflite::MicroInterpreter *preprocessor_interperter_{nullptr}; +#ifdef USE_MICRO_WAKE_WORD_VAD + std::unique_ptr vad_model_; +#endif - std::vector recent_streaming_probabilities_; - size_t last_n_index_{0}; + tflite::MicroMutableOpResolver<20> streaming_op_resolver_; - float probability_cutoff_{0.5}; - size_t sliding_window_average_size_{10}; + // Audio frontend handles generating spectrogram features + struct FrontendConfig frontend_config_; + struct FrontendState frontend_state_; - // When the wake word detection first starts or after the word has been detected once, we ignore this many audio - // feature slices before accepting a positive detection again + // When the wake word detection first starts, we ignore this many audio + // feature slices before accepting a positive detection int16_t ignore_windows_{-MIN_SLICES_BEFORE_DETECTION}; - uint8_t *streaming_var_arena_{nullptr}; - uint8_t *streaming_tensor_arena_{nullptr}; - uint8_t *preprocessor_tensor_arena_{nullptr}; - int8_t *new_features_data_{nullptr}; + uint8_t features_step_size_; - tflite::MicroResourceVariables *mrv_{nullptr}; - - // Stores audio fed into feature generator preprocessor - int16_t *preprocessor_audio_buffer_; + // Stores audio read from the microphone before being added to the ring buffer. + int16_t *input_buffer_{nullptr}; + // Stores audio to be fed into the audio frontend for generating features. + int16_t *preprocessor_audio_buffer_{nullptr}; bool detected_{false}; + std::string detected_wake_word_{""}; - /** Detects if wake word has been said + void set_state_(State state); + + /// @brief Tests if there are enough samples in the ring buffer to generate new features. + /// @return True if enough samples, false otherwise. + bool has_enough_samples_(); + + /** Reads audio from microphone into the ring buffer + * + * Audio data (16000 kHz with int16 samples) is read into the input_buffer_. + * Verifies the ring buffer has enough space for all audio data. If not, it logs + * a warning and resets the ring buffer entirely. + * @return Number of bytes written to the ring buffer + */ + size_t read_microphone_(); + + /// @brief Allocates memory for input_buffer_, preprocessor_audio_buffer_, and ring_buffer_ + /// @return True if successful, false otherwise + bool allocate_buffers_(); + + /// @brief Frees memory allocated for input_buffer_ and preprocessor_audio_buffer_ + void deallocate_buffers_(); + + /// @brief Loads streaming models and prepares the feature generation frontend + /// @return True if successful, false otherwise + bool load_models_(); + + /// @brief Deletes each model's TFLite interpreters and frees tensor arena memory. Frees memory used by the feature + /// generation frontend. + void unload_models_(); + + /** Performs inference with each configured model * * If enough audio samples are available, it will generate one slice of new features. - * If the streaming model predicts the wake word, then the nonstreaming model confirms it. - * @param ring_Buffer Ring buffer containing raw audio samples - * @return True if the wake word is detected, false otherwise + * It then loops through and performs inference with each of the loaded models. */ - bool detect_wake_word_(); + void update_model_probabilities_(); - /// @brief Returns true if there are enough audio samples in the buffer to generate another slice of features - bool slice_available_(); - - /** Shifts previous feature slices over by one and generates a new slice of features + /** Checks every model's recent probabilities to determine if the wake word has been predicted * - * @param ring_buffer ring buffer containing raw audio samples - * @return True if a new slice of features was generated, false otherwise + * Verifies the models have processed enough new samples for accurate predictions. + * Sets detected_wake_word_ to the wake word, if one is detected. + * @return True if a wake word is predicted, false otherwise */ - bool update_features_(); + bool detect_wake_words_(); - /** Generates features from audio samples + /** Generates features for a window of audio samples * - * Adapted from TFLite micro speech example - * @param audio_data Pointer to array with the audio samples - * @param audio_data_size The number of samples to use as input to the preprocessor model - * @param feature_output Array that will store the features + * Reads samples from the ring buffer and feeds them into the preprocessor frontend. + * Adapted from TFLite microspeech frontend. + * @param features int8_t array to store the audio features * @return True if successful, false otherwise. */ - bool generate_single_feature_(const int16_t *audio_data, int audio_data_size, - int8_t feature_output[PREPROCESSOR_FEATURE_SIZE]); + bool generate_features_for_window_(int8_t features[PREPROCESSOR_FEATURE_SIZE]); - /** Performs inference over the most recent feature slice with the streaming model - * - * @return Probability of the wake word between 0.0 and 1.0 - */ - float perform_streaming_inference_(); - - /** Strides the audio samples by keeping the last 10 ms of the previous slice - * - * Adapted from the TFLite micro speech example - * @param ring_buffer Ring buffer containing raw audio samples - * @param audio_samples Pointer to an array that will store the strided audio samples - * @return True if successful, false otherwise - */ - bool stride_audio_samples_(int16_t **audio_samples); - - /// @brief Returns true if successfully registered the preprocessor's TensorFlow operations - bool register_preprocessor_ops_(tflite::MicroMutableOpResolver<18> &op_resolver); + /// @brief Resets the ring buffer, ignore_windows_, and sliding window probabilities + void reset_states_(); /// @brief Returns true if successfully registered the streaming model's TensorFlow operations - bool register_streaming_ops_(tflite::MicroMutableOpResolver<17> &op_resolver); + bool register_streaming_ops_(tflite::MicroMutableOpResolver<20> &op_resolver); + + inline uint16_t new_samples_to_get_() { return (this->features_step_size_ * (AUDIO_SAMPLE_FREQUENCY / 1000)); } }; template class StartAction : public Action, public Parented { @@ -202,5 +174,3 @@ template class IsRunningCondition : public Condition, pub } // namespace esphome #endif // USE_ESP_IDF - -#endif // CLANG_TIDY diff --git a/esphome/components/micro_wake_word/preprocessor_settings.h b/esphome/components/micro_wake_word/preprocessor_settings.h new file mode 100644 index 0000000000..03f4fb5230 --- /dev/null +++ b/esphome/components/micro_wake_word/preprocessor_settings.h @@ -0,0 +1,20 @@ +#pragma once + +#ifdef USE_ESP_IDF + +#include + +namespace esphome { +namespace micro_wake_word { + +// The number of features the audio preprocessor generates per slice +static const uint8_t PREPROCESSOR_FEATURE_SIZE = 40; +// Duration of each slice used as input into the preprocessor +static const uint8_t FEATURE_DURATION_MS = 30; +// Audio sample frequency in hertz +static const uint16_t AUDIO_SAMPLE_FREQUENCY = 16000; + +} // namespace micro_wake_word +} // namespace esphome + +#endif diff --git a/esphome/components/micro_wake_word/streaming_model.cpp b/esphome/components/micro_wake_word/streaming_model.cpp new file mode 100644 index 0000000000..013fa2ce6e --- /dev/null +++ b/esphome/components/micro_wake_word/streaming_model.cpp @@ -0,0 +1,189 @@ +#ifdef USE_ESP_IDF + +#include "streaming_model.h" + +#include "esphome/core/hal.h" +#include "esphome/core/helpers.h" +#include "esphome/core/log.h" + +static const char *const TAG = "micro_wake_word"; + +namespace esphome { +namespace micro_wake_word { + +void WakeWordModel::log_model_config() { + ESP_LOGCONFIG(TAG, " - Wake Word: %s", this->wake_word_.c_str()); + ESP_LOGCONFIG(TAG, " Probability cutoff: %.3f", this->probability_cutoff_); + ESP_LOGCONFIG(TAG, " Sliding window size: %d", this->sliding_window_size_); +} + +void VADModel::log_model_config() { + ESP_LOGCONFIG(TAG, " - VAD Model"); + ESP_LOGCONFIG(TAG, " Probability cutoff: %.3f", this->probability_cutoff_); + ESP_LOGCONFIG(TAG, " Sliding window size: %d", this->sliding_window_size_); +} + +bool StreamingModel::load_model(tflite::MicroMutableOpResolver<20> &op_resolver) { + ExternalRAMAllocator arena_allocator(ExternalRAMAllocator::ALLOW_FAILURE); + + if (this->tensor_arena_ == nullptr) { + this->tensor_arena_ = arena_allocator.allocate(this->tensor_arena_size_); + if (this->tensor_arena_ == nullptr) { + ESP_LOGE(TAG, "Could not allocate the streaming model's tensor arena."); + return false; + } + } + + if (this->var_arena_ == nullptr) { + this->var_arena_ = arena_allocator.allocate(STREAMING_MODEL_VARIABLE_ARENA_SIZE); + if (this->var_arena_ == nullptr) { + ESP_LOGE(TAG, "Could not allocate the streaming model's variable tensor arena."); + return false; + } + this->ma_ = tflite::MicroAllocator::Create(this->var_arena_, STREAMING_MODEL_VARIABLE_ARENA_SIZE); + this->mrv_ = tflite::MicroResourceVariables::Create(this->ma_, 20); + } + + const tflite::Model *model = tflite::GetModel(this->model_start_); + if (model->version() != TFLITE_SCHEMA_VERSION) { + ESP_LOGE(TAG, "Streaming model's schema is not supported"); + return false; + } + + if (this->interpreter_ == nullptr) { + this->interpreter_ = make_unique( + tflite::GetModel(this->model_start_), op_resolver, this->tensor_arena_, this->tensor_arena_size_, this->mrv_); + if (this->interpreter_->AllocateTensors() != kTfLiteOk) { + ESP_LOGE(TAG, "Failed to allocate tensors for the streaming model"); + return false; + } + + // Verify input tensor matches expected values + // Dimension 3 will represent the first layer stride, so skip it may vary + TfLiteTensor *input = this->interpreter_->input(0); + if ((input->dims->size != 3) || (input->dims->data[0] != 1) || + (input->dims->data[2] != PREPROCESSOR_FEATURE_SIZE)) { + ESP_LOGE(TAG, "Streaming model tensor input dimensions has improper dimensions."); + return false; + } + + if (input->type != kTfLiteInt8) { + ESP_LOGE(TAG, "Streaming model tensor input is not int8."); + return false; + } + + // Verify output tensor matches expected values + 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."); + } + + if (output->type != kTfLiteUInt8) { + ESP_LOGE(TAG, "Streaming model tensor output is not uint8."); + return false; + } + } + + return true; +} + +void StreamingModel::unload_model() { + this->interpreter_.reset(); + + ExternalRAMAllocator arena_allocator(ExternalRAMAllocator::ALLOW_FAILURE); + + arena_allocator.deallocate(this->tensor_arena_, this->tensor_arena_size_); + this->tensor_arena_ = nullptr; + arena_allocator.deallocate(this->var_arena_, STREAMING_MODEL_VARIABLE_ARENA_SIZE); + this->var_arena_ = nullptr; +} + +bool StreamingModel::perform_streaming_inference(const int8_t features[PREPROCESSOR_FEATURE_SIZE]) { + if (this->interpreter_ != nullptr) { + TfLiteTensor *input = this->interpreter_->input(0); + + std::memmove( + (int8_t *) (tflite::GetTensorData(input)) + PREPROCESSOR_FEATURE_SIZE * this->current_stride_step_, + features, PREPROCESSOR_FEATURE_SIZE); + ++this->current_stride_step_; + + uint8_t stride = this->interpreter_->input(0)->dims->data[1]; + + if (this->current_stride_step_ >= stride) { + this->current_stride_step_ = 0; + + TfLiteStatus invoke_status = this->interpreter_->Invoke(); + if (invoke_status != kTfLiteOk) { + ESP_LOGW(TAG, "Streaming interpreter invoke failed"); + return false; + } + + TfLiteTensor *output = this->interpreter_->output(0); + + ++this->last_n_index_; + if (this->last_n_index_ == this->sliding_window_size_) + this->last_n_index_ = 0; + this->recent_streaming_probabilities_[this->last_n_index_] = output->data.uint8[0]; // probability; + } + return true; + } + ESP_LOGE(TAG, "Streaming interpreter is not initialized."); + return false; +} + +void StreamingModel::reset_probabilities() { + for (auto &prob : this->recent_streaming_probabilities_) { + prob = 0; + } +} + +WakeWordModel::WakeWordModel(const uint8_t *model_start, float probability_cutoff, size_t sliding_window_average_size, + const std::string &wake_word, size_t tensor_arena_size) { + this->model_start_ = model_start; + this->probability_cutoff_ = probability_cutoff; + this->sliding_window_size_ = sliding_window_average_size; + this->recent_streaming_probabilities_.resize(sliding_window_average_size, 0); + this->wake_word_ = wake_word; + this->tensor_arena_size_ = tensor_arena_size; +}; + +bool WakeWordModel::determine_detected() { + int32_t sum = 0; + for (auto &prob : this->recent_streaming_probabilities_) { + sum += prob; + } + + float sliding_window_average = static_cast(sum) / static_cast(255 * this->sliding_window_size_); + + // Detect the wake word if the sliding window average is above the cutoff + if (sliding_window_average > this->probability_cutoff_) { + ESP_LOGD(TAG, "The '%s' model sliding average probability is %.3f and most recent probability is %.3f", + this->wake_word_.c_str(), sliding_window_average, + this->recent_streaming_probabilities_[this->last_n_index_] / (255.0)); + return true; + } + return false; +} + +VADModel::VADModel(const uint8_t *model_start, float probability_cutoff, size_t sliding_window_size, + size_t tensor_arena_size) { + this->model_start_ = model_start; + this->probability_cutoff_ = probability_cutoff; + this->sliding_window_size_ = sliding_window_size; + this->recent_streaming_probabilities_.resize(sliding_window_size, 0); + this->tensor_arena_size_ = tensor_arena_size; +}; + +bool VADModel::determine_detected() { + uint8_t max = 0; + for (auto &prob : this->recent_streaming_probabilities_) { + max = std::max(prob, max); + } + + return max > this->probability_cutoff_; +} + +} // namespace micro_wake_word +} // namespace esphome + +#endif diff --git a/esphome/components/micro_wake_word/streaming_model.h b/esphome/components/micro_wake_word/streaming_model.h new file mode 100644 index 0000000000..0d85579f35 --- /dev/null +++ b/esphome/components/micro_wake_word/streaming_model.h @@ -0,0 +1,84 @@ +#pragma once + +#ifdef USE_ESP_IDF + +#include "preprocessor_settings.h" + +#include +#include +#include + +namespace esphome { +namespace micro_wake_word { + +static const uint32_t STREAMING_MODEL_VARIABLE_ARENA_SIZE = 1024; + +class StreamingModel { + public: + virtual void log_model_config() = 0; + virtual bool determine_detected() = 0; + + bool perform_streaming_inference(const int8_t features[PREPROCESSOR_FEATURE_SIZE]); + + /// @brief Sets all recent_streaming_probabilities to 0 + void reset_probabilities(); + + /// @brief Allocates tensor and variable arenas and sets up the model interpreter + /// @param op_resolver MicroMutableOpResolver object that must exist until the model is unloaded + /// @return True if successful, false otherwise + bool load_model(tflite::MicroMutableOpResolver<20> &op_resolver); + + /// @brief Destroys the TFLite interpreter and frees the tensor and variable arenas' memory + void unload_model(); + + protected: + uint8_t current_stride_step_{0}; + + float probability_cutoff_; + size_t sliding_window_size_; + size_t last_n_index_{0}; + size_t tensor_arena_size_; + std::vector recent_streaming_probabilities_; + + const uint8_t *model_start_; + uint8_t *tensor_arena_{nullptr}; + uint8_t *var_arena_{nullptr}; + std::unique_ptr interpreter_; + tflite::MicroResourceVariables *mrv_{nullptr}; + tflite::MicroAllocator *ma_{nullptr}; +}; + +class WakeWordModel final : public StreamingModel { + public: + WakeWordModel(const uint8_t *model_start, float probability_cutoff, size_t sliding_window_average_size, + const std::string &wake_word, size_t tensor_arena_size); + + void log_model_config() override; + + /// @brief Checks for the wake word by comparing the mean probability in the sliding window with the probability + /// cutoff + /// @return True if wake word is detected, false otherwise + bool determine_detected() override; + + const std::string &get_wake_word() const { return this->wake_word_; } + + protected: + std::string wake_word_; +}; + +class VADModel final : public StreamingModel { + public: + VADModel(const uint8_t *model_start, float probability_cutoff, size_t sliding_window_size, size_t tensor_arena_size); + + void log_model_config() override; + + /// @brief Checks for voice activity by comparing the max probability in the sliding window with the probability + /// cutoff + /// @return True if voice activity is detected, false otherwise + bool determine_detected() override; +}; + +} // namespace micro_wake_word +} // namespace esphome + +#endif diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 1e6f3517db..4831ed2c9e 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -86,6 +86,7 @@ #define USE_ESP32_BLE_SERVER #define USE_ESP32_CAMERA #define USE_IMPROV +#define USE_MICRO_WAKE_WORD_VAD #define USE_MICROPHONE #define USE_PSRAM #define USE_SOCKET_IMPL_BSD_SOCKETS diff --git a/platformio.ini b/platformio.ini index a72bf598c5..f07889526f 100644 --- a/platformio.ini +++ b/platformio.ini @@ -142,7 +142,8 @@ platform_packages = framework = espidf lib_deps = ${common:idf.lib_deps} - droscy/esp_wireguard@0.4.2 ; wireguard + droscy/esp_wireguard@0.4.2 ; wireguard + kahrendt/ESPMicroSpeechFeatures@1.0.0 ; micro_wake_word build_flags = ${common:idf.build_flags} -Wno-nonnull-compare diff --git a/tests/components/micro_wake_word/common.yaml b/tests/components/micro_wake_word/common.yaml index c0f3593cc6..8bd7345307 100644 --- a/tests/components/micro_wake_word/common.yaml +++ b/tests/components/micro_wake_word/common.yaml @@ -10,6 +10,10 @@ microphone: pdm: true micro_wake_word: - model: hey_jarvis on_wake_word_detected: - logger.log: "Wake word detected" + models: + - model: hey_jarvis + probability_cutoff: 0.7 + - model: okay_nabu + sliding_window_size: 5 diff --git a/tests/components/micro_wake_word/test.esp32-idf.yaml b/tests/components/micro_wake_word/test.esp32-idf.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/micro_wake_word/test.esp32-idf.yaml @@ -0,0 +1 @@ +<<: !include common.yaml From aa8c963c50467b194fa5d7ebb25f81a6692d3d19 Mon Sep 17 00:00:00 2001 From: Pavlo Dudnytskyi Date: Thu, 11 Jul 2024 03:30:55 +0200 Subject: [PATCH 1733/2101] UART component support added for host platform (#6912) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Co-authored-by: Pavlo Dudnytskyi --- esphome/components/uart/__init__.py | 66 +++- .../components/uart/uart_component_host.cpp | 295 ++++++++++++++++++ esphome/components/uart/uart_component_host.h | 38 +++ tests/components/uart/test.host.yaml | 13 + 4 files changed, 410 insertions(+), 2 deletions(-) create mode 100644 esphome/components/uart/uart_component_host.cpp create mode 100644 esphome/components/uart/uart_component_host.h create mode 100644 tests/components/uart/test.host.yaml diff --git a/esphome/components/uart/__init__.py b/esphome/components/uart/__init__.py index b036288078..0738a127e1 100644 --- a/esphome/components/uart/__init__.py +++ b/esphome/components/uart/__init__.py @@ -1,5 +1,5 @@ from typing import Optional - +import re import esphome.codegen as cg import esphome.config_validation as cv import esphome.final_validate as fv @@ -11,6 +11,7 @@ from esphome.const import ( CONF_NUMBER, CONF_RX_PIN, CONF_TX_PIN, + CONF_PORT, CONF_UART_ID, CONF_DATA, CONF_RX_BUFFER_SIZE, @@ -27,6 +28,7 @@ from esphome.const import ( CONF_DUMMY_RECEIVER, CONF_DUMMY_RECEIVER_ID, CONF_LAMBDA, + PLATFORM_HOST, ) from esphome.core import CORE @@ -45,6 +47,7 @@ RP2040UartComponent = uart_ns.class_("RP2040UartComponent", UARTComponent, cg.Co LibreTinyUARTComponent = uart_ns.class_( "LibreTinyUARTComponent", UARTComponent, cg.Component ) +HostUartComponent = uart_ns.class_("HostUartComponent", UARTComponent, cg.Component) NATIVE_UART_CLASSES = ( str(IDFUARTComponent), @@ -54,6 +57,39 @@ NATIVE_UART_CLASSES = ( str(LibreTinyUARTComponent), ) +HOST_BAUD_RATES = [ + 50, + 75, + 110, + 134, + 150, + 200, + 300, + 600, + 1200, + 1800, + 2400, + 4800, + 9600, + 19200, + 38400, + 57600, + 115200, + 230400, + 460800, + 500000, + 576000, + 921600, + 1000000, + 1152000, + 1500000, + 2000000, + 2500000, + 3000000, + 3500000, + 4000000, +] + UARTDevice = uart_ns.class_("UARTDevice") UARTWriteAction = uart_ns.class_("UARTWriteAction", automation.Action) UARTDebugger = uart_ns.class_("UARTDebugger", cg.Component, automation.Action) @@ -95,6 +131,20 @@ def validate_invert_esp32(config): return config +def validate_host_config(config): + if CORE.is_host: + if CONF_TX_PIN in config or CONF_RX_PIN in config: + raise cv.Invalid( + "TX and RX pins are not supported for UART on host platform." + ) + if config[CONF_BAUD_RATE] not in HOST_BAUD_RATES: + raise cv.Invalid( + f"Host platform doesn't support baud rate {config[CONF_BAUD_RATE]}", + path=[CONF_BAUD_RATE], + ) + return config + + def _uart_declare_type(value): if CORE.is_esp8266: return cv.declare_id(ESP8266UartComponent)(value) @@ -107,6 +157,8 @@ def _uart_declare_type(value): return cv.declare_id(RP2040UartComponent)(value) if CORE.is_libretiny: return cv.declare_id(LibreTinyUARTComponent)(value) + if CORE.is_host: + return cv.declare_id(HostUartComponent)(value) raise NotImplementedError @@ -149,6 +201,12 @@ def maybe_empty_debug(value): return DEBUG_SCHEMA(value) +def validate_port(value): + if not re.match(r"^/(?:[^/]+/)[^/]+$", value): + raise cv.Invalid("Port must be a valid device path") + return value + + DEBUG_SCHEMA = cv.Schema( { cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(UARTDebugger), @@ -181,6 +239,7 @@ CONFIG_SCHEMA = cv.All( cv.Required(CONF_BAUD_RATE): cv.int_range(min=1), cv.Optional(CONF_TX_PIN): pins.internal_gpio_output_pin_schema, cv.Optional(CONF_RX_PIN): validate_rx_pin, + cv.Optional(CONF_PORT): cv.All(validate_port, cv.only_on(PLATFORM_HOST)), cv.Optional(CONF_RX_BUFFER_SIZE, default=256): cv.validate_bytes, 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), @@ -193,8 +252,9 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_DEBUG): maybe_empty_debug, } ).extend(cv.COMPONENT_SCHEMA), - cv.has_at_least_one_key(CONF_TX_PIN, CONF_RX_PIN), + cv.has_at_least_one_key(CONF_TX_PIN, CONF_RX_PIN, CONF_PORT), validate_invert_esp32, + validate_host_config, ) @@ -236,6 +296,8 @@ async def to_code(config): if CONF_RX_PIN in config: rx_pin = await cg.gpio_pin_expression(config[CONF_RX_PIN]) cg.add(var.set_rx_pin(rx_pin)) + if CONF_PORT in config: + cg.add(var.set_name(config[CONF_PORT])) cg.add(var.set_rx_buffer_size(config[CONF_RX_BUFFER_SIZE])) cg.add(var.set_stop_bits(config[CONF_STOP_BITS])) cg.add(var.set_data_bits(config[CONF_DATA_BITS])) diff --git a/esphome/components/uart/uart_component_host.cpp b/esphome/components/uart/uart_component_host.cpp new file mode 100644 index 0000000000..d8d2fd75b8 --- /dev/null +++ b/esphome/components/uart/uart_component_host.cpp @@ -0,0 +1,295 @@ +#ifdef USE_HOST +#include "uart_component_host.h" +#include "esphome/core/application.h" +#include "esphome/core/defines.h" +#include "esphome/core/helpers.h" +#include "esphome/core/log.h" + +#ifndef __linux__ +#error This HostUartComponent implementation is only for Linux +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifdef USE_LOGGER +#include "esphome/components/logger/logger.h" +#endif + +namespace { + +speed_t get_baud(int baud) { + switch (baud) { + case 50: + return B50; + case 75: + return B75; + case 110: + return B110; + case 134: + return B134; + case 150: + return B150; + case 200: + return B200; + case 300: + return B300; + case 600: + return B600; + case 1200: + return B1200; + case 1800: + return B1800; + case 2400: + return B2400; + case 4800: + return B4800; + case 9600: + return B9600; + case 19200: + return B19200; + case 38400: + return B38400; + case 57600: + return B57600; + case 115200: + return B115200; + case 230400: + return B230400; + case 460800: + return B460800; + case 500000: + return B500000; + case 576000: + return B576000; + case 921600: + return B921600; + case 1000000: + return B1000000; + case 1152000: + return B1152000; + case 1500000: + return B1500000; + case 2000000: + return B2000000; + case 2500000: + return B2500000; + case 3000000: + return B3000000; + case 3500000: + return B3500000; + case 4000000: + return B4000000; + default: + return B0; + } +} + +} // namespace + +namespace esphome { +namespace uart { + +static const char *const TAG = "uart.host"; + +HostUartComponent::~HostUartComponent() { + if (this->file_descriptor_ != -1) { + close(this->file_descriptor_); + this->file_descriptor_ = -1; + } +} + +void HostUartComponent::setup() { + ESP_LOGCONFIG(TAG, "Opening UART port..."); + speed_t baud = get_baud(this->baud_rate_); + if (baud == B0) { + ESP_LOGE(TAG, "Unsupported baud rate: %d", this->baud_rate_); + this->mark_failed(); + return; + } + this->file_descriptor_ = ::open(this->port_name_.c_str(), O_RDWR | O_NOCTTY | O_NDELAY); + if (this->file_descriptor_ == -1) { + this->update_error_(strerror(errno)); + this->mark_failed(); + return; + } + fcntl(this->file_descriptor_, F_SETFL, 0); + struct termios options; + tcgetattr(this->file_descriptor_, &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; + // Set data bits + options.c_cflag &= ~CSIZE; // Mask the character size bits + switch (this->data_bits_) { + case 5: + options.c_cflag |= CS5; + break; + case 6: + options.c_cflag |= CS6; + break; + case 7: + options.c_cflag |= CS7; + break; + case 8: + default: + options.c_cflag |= CS8; + break; + } + // Set parity + switch (this->parity_) { + case UART_CONFIG_PARITY_NONE: + options.c_cflag &= ~PARENB; + break; + case UART_CONFIG_PARITY_EVEN: + options.c_cflag |= PARENB; + options.c_cflag &= ~PARODD; + break; + case UART_CONFIG_PARITY_ODD: + options.c_cflag |= PARENB; + options.c_cflag |= PARODD; + break; + }; + // Set stop bits + if (this->stop_bits_ == 2) { + options.c_cflag |= CSTOPB; + } else { + options.c_cflag &= ~CSTOPB; + } + cfsetispeed(&options, baud); + cfsetospeed(&options, baud); + tcsetattr(this->file_descriptor_, TCSANOW, &options); +} + +void HostUartComponent::dump_config() { + ESP_LOGCONFIG(TAG, "UART:"); + ESP_LOGCONFIG(TAG, " Port: %s", this->port_name_.c_str()); + if (this->file_descriptor_ == -1) { + ESP_LOGCONFIG(TAG, " Port status: Not opened"); + if (!this->first_error_.empty()) { + ESP_LOGCONFIG(TAG, " Error: %s", this->first_error_.c_str()); + } + return; + } + ESP_LOGCONFIG(TAG, " Port status: opened"); + ESP_LOGCONFIG(TAG, " Baud Rate: %d", this->baud_rate_); + ESP_LOGCONFIG(TAG, " Data Bits: %d", this->data_bits_); + ESP_LOGCONFIG(TAG, " Parity: %s", + this->parity_ == UART_CONFIG_PARITY_NONE ? "None" + : this->parity_ == UART_CONFIG_PARITY_EVEN ? "Even" + : "Odd"); + ESP_LOGCONFIG(TAG, " Stop Bits: %d", this->stop_bits_); + this->check_logger_conflict(); +} + +void HostUartComponent::write_array(const uint8_t *data, size_t len) { + if (this->file_descriptor_ == -1) { + return; + } + size_t written = ::write(this->file_descriptor_, data, len); + if (written != len) { + this->update_error_(strerror(errno)); + return; + } +#ifdef USE_UART_DEBUGGER + for (size_t i = 0; i < len; i++) { + this->debug_callback_.call(UART_DIRECTION_TX, data[i]); + } +#endif + return; +} + +bool HostUartComponent::peek_byte(uint8_t *data) { + if (this->file_descriptor_ == -1) { + return false; + } + if (!this->has_peek_) { + if (!this->check_read_timeout_()) { + return false; + } + if (::read(this->file_descriptor_, &this->peek_byte_, 1) != 1) { + this->update_error_(strerror(errno)); + return false; + } + this->has_peek_ = true; + } + *data = this->peek_byte_; + return true; +} + +bool HostUartComponent::read_array(uint8_t *data, size_t len) { + if ((this->file_descriptor_ == -1) || (len == 0)) { + return false; + } + 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++; + this->has_peek_ = false; + } + if (length_to_read > 0) { + int sz = ::read(this->file_descriptor_, data_ptr, length_to_read); + if (sz == -1) { + this->update_error_(strerror(errno)); + return false; + } + } +#ifdef USE_UART_DEBUGGER + for (size_t i = 0; i < len; i++) { + this->debug_callback_.call(UART_DIRECTION_RX, data[i]); + } +#endif + return true; +} + +int HostUartComponent::available() { + if (this->file_descriptor_ == -1) { + return 0; + } + int available; + int res = ioctl(this->file_descriptor_, FIONREAD, &available); + if (res == -1) { + this->update_error_(strerror(errno)); + return 0; + } + if (this->has_peek_) + available++; + return available; +}; + +void HostUartComponent::flush() { + if (this->file_descriptor_ == -1) { + return; + } + tcflush(this->file_descriptor_, TCIOFLUSH); + ESP_LOGV(TAG, " Flushing..."); +} + +void HostUartComponent::update_error_(const std::string &error) { + if (this->first_error_.empty()) { + this->first_error_ = error; + } + ESP_LOGE(TAG, "Port error: %s", error.c_str()); +} + +} // namespace uart +} // namespace esphome + +#endif // USE_HOST diff --git a/esphome/components/uart/uart_component_host.h b/esphome/components/uart/uart_component_host.h new file mode 100644 index 0000000000..c1f1dd0d2c --- /dev/null +++ b/esphome/components/uart/uart_component_host.h @@ -0,0 +1,38 @@ +#pragma once + +#ifdef USE_HOST + +#include "esphome/core/component.h" +#include "esphome/core/log.h" +#include "uart_component.h" + +namespace esphome { +namespace uart { + +class HostUartComponent : public UARTComponent, public Component { + public: + virtual ~HostUartComponent(); + void setup() override; + void dump_config() override; + float get_setup_priority() const override { return setup_priority::BUS; } + 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; + void flush() override; + void set_name(std::string port_name) { port_name_ = port_name; }; + + protected: + void update_error_(const std::string &error); + void check_logger_conflict() override {} + std::string port_name_; + std::string first_error_{""}; + int file_descriptor_ = -1; + bool has_peek_{false}; + uint8_t peek_byte_; +}; + +} // namespace uart +} // namespace esphome + +#endif // USE_HOST diff --git a/tests/components/uart/test.host.yaml b/tests/components/uart/test.host.yaml new file mode 100644 index 0000000000..63f0ade084 --- /dev/null +++ b/tests/components/uart/test.host.yaml @@ -0,0 +1,13 @@ +esphome: + on_boot: + then: + - uart.write: 'Hello World' + - uart.write: [0x00, 0x20, 0x42] + +uart: + - id: uart_uart + port: "/dev/ttyS0" + baud_rate: 9600 + data_bits: 8 + parity: EVEN + stop_bits: 2 From 2f669c99f8954ccc8c960fb527040ae2febe13cf Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Thu, 11 Jul 2024 03:32:17 +0200 Subject: [PATCH 1734/2101] Configure ap ip for RP2040 (#7065) --- .../components/wifi/wifi_component_pico_w.cpp | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/esphome/components/wifi/wifi_component_pico_w.cpp b/esphome/components/wifi/wifi_component_pico_w.cpp index 2bb1af5489..4afcf2d78b 100644 --- a/esphome/components/wifi/wifi_component_pico_w.cpp +++ b/esphome/components/wifi/wifi_component_pico_w.cpp @@ -141,13 +141,29 @@ bool WiFiComponent::wifi_scan_start_(bool passive) { #ifdef USE_WIFI_AP bool WiFiComponent::wifi_ap_ip_config_(optional manual_ip) { - // TODO: - return false; + 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); + return true; } bool WiFiComponent::wifi_start_ap_(const WiFiAP &ap) { if (!this->wifi_mode_({}, true)) return false; + if (!this->wifi_ap_ip_config_(ap.get_manual_ip())) { + ESP_LOGV(TAG, "wifi_ap_ip_config_ failed!"); + return false; + } WiFi.beginAP(ap.get_ssid().c_str(), ap.get_password().c_str(), ap.get_channel().value_or(1)); From d1b0e6b5fe11d0e77e20432c11f8f68b421ac841 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 11 Jul 2024 15:41:48 +1200 Subject: [PATCH 1735/2101] Bump version to 2024.8.0-dev --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 543b1d00cc..faf6ce19fa 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.7.0-dev" +__version__ = "2024.8.0-dev" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 6417f1f907d0dbbef3f2011905a3cb7c9abf9763 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 11 Jul 2024 15:41:48 +1200 Subject: [PATCH 1736/2101] Bump version to 2024.7.0b1 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 543b1d00cc..d672cc92af 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.7.0-dev" +__version__ = "2024.7.0b1" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From fb6c2aef59d5b3ca1463705eba01d0eb3de19535 Mon Sep 17 00:00:00 2001 From: Christian Ferbar <5595808+ferbar@users.noreply.github.com> Date: Thu, 11 Jul 2024 05:58:54 +0200 Subject: [PATCH 1737/2101] helpers.cpp: Fix GLIBCXX_RELEASE check < 8 (#7062) --- esphome/core/helpers.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/core/helpers.cpp b/esphome/core/helpers.cpp index 7f040f855f..e75b06ccd3 100644 --- a/esphome/core/helpers.cpp +++ b/esphome/core/helpers.cpp @@ -78,7 +78,7 @@ static const uint16_t CRC16_1021_BE_LUT_H[] = {0x0000, 0x1231, 0x2462, 0x3653, 0 // STL backports -#if _GLIBCXX_RELEASE < 7 +#if _GLIBCXX_RELEASE < 8 std::string to_string(int value) { return str_snprintf("%d", 32, value); } // NOLINT std::string to_string(long value) { return str_snprintf("%ld", 32, value); } // NOLINT std::string to_string(long long value) { return str_snprintf("%lld", 32, value); } // NOLINT From fa4fbf9d7384e1962e2982ab2ad0db449d33e4c6 Mon Sep 17 00:00:00 2001 From: Z3LIFF Date: Thu, 11 Jul 2024 00:01:14 -0400 Subject: [PATCH 1738/2101] Fix pmsa003i cold boot marked as failed on ESP32 et al (#7064) --- esphome/components/pmsa003i/pmsa003i.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/esphome/components/pmsa003i/pmsa003i.cpp b/esphome/components/pmsa003i/pmsa003i.cpp index ca3d28367a..a9665c6a5a 100644 --- a/esphome/components/pmsa003i/pmsa003i.cpp +++ b/esphome/components/pmsa003i/pmsa003i.cpp @@ -13,6 +13,15 @@ void PMSA003IComponent::setup() { PM25AQIData data; bool successful_read = this->read_data_(&data); + if (!successful_read) { + for (int i = 0; i < 3; i++) { + successful_read = this->read_data_(&data); + if (successful_read) { + break; + } + } + } + if (!successful_read) { this->mark_failed(); return; From dea1e9a1e05ea1b01c3a70d6789d02569498becf Mon Sep 17 00:00:00 2001 From: guillempages Date: Thu, 11 Jul 2024 06:08:51 +0200 Subject: [PATCH 1739/2101] [http_request] Fix follow_redirects on arduino (#7054) --- esphome/components/http_request/http_request_arduino.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/esphome/components/http_request/http_request_arduino.cpp b/esphome/components/http_request/http_request_arduino.cpp index 248a85a439..95b1cdc38e 100644 --- a/esphome/components/http_request/http_request_arduino.cpp +++ b/esphome/components/http_request/http_request_arduino.cpp @@ -32,6 +32,13 @@ std::shared_ptr HttpRequestArduino::start(std::string url, std::s watchdog::WatchdogManager wdm(this->get_watchdog_timeout()); + if (this->follow_redirects_) { + container->client_.setFollowRedirects(HTTPC_FORCE_FOLLOW_REDIRECTS); + container->client_.setRedirectLimit(this->redirect_limit_); + } else { + container->client_.setFollowRedirects(HTTPC_DISABLE_FOLLOW_REDIRECTS); + } + #if defined(USE_ESP8266) std::unique_ptr stream_ptr; #ifdef USE_HTTP_REQUEST_ESP8266_HTTPS @@ -59,8 +66,6 @@ std::shared_ptr HttpRequestArduino::start(std::string url, std::s "in your YAML, or use HTTPS"); } #endif // USE_ARDUINO_VERSION_CODE - - container->client_.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); bool status = container->client_.begin(*stream_ptr, url.c_str()); #elif defined(USE_RP2040) From ee4d5178d6fa54dcc8069b86bfdd63571d8a4f9e Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Thu, 11 Jul 2024 06:09:51 +0200 Subject: [PATCH 1740/2101] [ethernet] Fix compile warning for IPv6 (#7048) --- esphome/components/ethernet/ethernet_component.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index 6b34157b9d..962a864a29 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -394,7 +394,7 @@ void EthernetComponent::got_ip_event_handler(void *arg, esp_event_base_t event_b 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 +#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; #else global_eth_component->connected_ = true; @@ -407,8 +407,12 @@ void EthernetComponent::got_ip6_event_handler(void *arg, esp_event_base_t event_ 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); +#else + global_eth_component->connected_ = global_eth_component->got_ipv4_address_; +#endif } #endif /* USE_NETWORK_IPV6 */ From 1b57d8511be329fac18c039d22ac06679e616b8f Mon Sep 17 00:00:00 2001 From: esphomebot Date: Thu, 11 Jul 2024 16:10:18 +1200 Subject: [PATCH 1741/2101] Update webserver local assets to 20240704-081526 (#7041) --- .../components/web_server/server_index_v2.h | 83 +- .../components/web_server/server_index_v3.h | 735 +++++++++--------- 2 files changed, 410 insertions(+), 408 deletions(-) diff --git a/esphome/components/web_server/server_index_v2.h b/esphome/components/web_server/server_index_v2.h index c942cda592..c9932624ba 100644 --- a/esphome/components/web_server/server_index_v2.h +++ b/esphome/components/web_server/server_index_v2.h @@ -68,7 +68,7 @@ const uint8_t INDEX_GZ[] PROGMEM = { 0xe3, 0x9b, 0x82, 0xde, 0xc5, 0x0e, 0x21, 0xa9, 0x64, 0x54, 0x44, 0x2c, 0x97, 0x29, 0x21, 0x29, 0xc2, 0x3f, 0x90, 0x45, 0x68, 0xd6, 0x13, 0xec, 0x34, 0x30, 0x9c, 0xcb, 0x40, 0x71, 0x17, 0x3c, 0xe0, 0xc9, 0x9c, 0xa6, 0x82, 0xa6, 0xc1, 0x5f, 0x71, 0x4a, 0x87, 0x31, 0x40, 0xb1, 0xd3, 0xc4, 0xe3, 0x30, 0x3b, 0x1f, 0x87, 0xc9, 0x88, 0x46, 0xc1, - 0x8d, 0xc8, 0xf1, 0xdf, 0x89, 0x3b, 0x64, 0x49, 0x18, 0xb3, 0x5f, 0x69, 0xe4, 0x6a, 0x69, 0x70, 0xeb, 0xd0, 0x5b, + 0x8d, 0xc8, 0xf1, 0xdf, 0x89, 0x3b, 0x64, 0x49, 0x18, 0xb3, 0x5f, 0x69, 0xe4, 0x6a, 0x69, 0x70, 0xe6, 0xd0, 0x5b, 0x41, 0x93, 0x28, 0x73, 0x9e, 0xbf, 0x7b, 0xf9, 0x42, 0xef, 0x63, 0x45, 0x40, 0xa0, 0x45, 0x36, 0x9b, 0xd2, 0xd4, 0x43, 0x58, 0x0b, 0x88, 0x67, 0x4c, 0x32, 0xc7, 0x97, 0xe1, 0x54, 0x95, 0xb0, 0xec, 0xfd, 0x34, 0x0a, 0x05, 0x7d, 0x43, 0x93, 0x88, 0x25, 0x23, 0xb2, 0xd3, 0x54, 0xe5, 0xe3, 0x50, 0x57, 0x44, 0x45, 0xd1, 0xe5, 0xee, 0xb3, 0x58, @@ -150,19 +150,19 @@ const uint8_t INDEX_GZ[] PROGMEM = { 0xa6, 0x57, 0xfd, 0xcf, 0xf9, 0x64, 0x0a, 0xda, 0xd8, 0x0a, 0x49, 0x8f, 0xa8, 0x9e, 0xb0, 0xac, 0xcf, 0x37, 0x94, 0x55, 0xfa, 0xc8, 0xf3, 0x58, 0xa1, 0xa6, 0xc2, 0x5e, 0xde, 0x69, 0xe4, 0xb3, 0xa2, 0xa8, 0x60, 0x1c, 0x9b, 0x9c, 0x2a, 0xe7, 0xab, 0x2e, 0x19, 0x53, 0xf1, 0xda, 0x63, 0x8a, 0x0f, 0x33, 0xe0, 0x75, 0x16, 0xfb, 0x31, 0xe4, 0x6e, - 0xef, 0x7f, 0x5e, 0x22, 0x67, 0x91, 0xaf, 0xa0, 0x6f, 0x91, 0xe7, 0xb7, 0xca, 0xc8, 0xc6, 0xb7, 0xdb, 0xad, 0xe1, - 0xb2, 0x4e, 0x1b, 0x8b, 0xbd, 0x3e, 0xbe, 0x5d, 0x57, 0x1d, 0xc9, 0x62, 0xc2, 0x23, 0x1a, 0xb8, 0x7c, 0x4a, 0x13, - 0x37, 0x07, 0xaf, 0xaa, 0xde, 0xfb, 0x81, 0xf0, 0x16, 0x6f, 0xab, 0xee, 0xd5, 0xe0, 0x36, 0x07, 0xef, 0xd7, 0xd7, + 0xef, 0x7f, 0x5e, 0x22, 0x67, 0x91, 0xaf, 0xa0, 0x6f, 0x91, 0xe7, 0x67, 0xca, 0xc8, 0xc6, 0x67, 0xdb, 0xad, 0xe1, + 0xb2, 0x4e, 0x1b, 0x8b, 0xbd, 0x3e, 0x3e, 0x5b, 0x57, 0x1d, 0xc9, 0x62, 0xc2, 0x23, 0x1a, 0xb8, 0x7c, 0x4a, 0x13, + 0x37, 0x07, 0xaf, 0xaa, 0xde, 0xfb, 0x81, 0xf0, 0x16, 0x6f, 0xab, 0xee, 0xd5, 0xe0, 0x2c, 0x07, 0xef, 0xd7, 0xd7, 0xeb, 0x8e, 0xd7, 0xef, 0x69, 0x9a, 0x49, 0x45, 0xb4, 0xd0, 0x69, 0xbf, 0x2e, 0xc5, 0xd2, 0xd7, 0xc1, 0xd6, 0xf6, 0xa5, 0x09, 0xe2, 0x36, 0xfd, 0x63, 0xff, 0xc0, 0x45, 0xd2, 0x2d, 0xfc, 0x93, 0x3e, 0xf0, 0x1f, 0x8c, 0x5b, 0xf8, 0x19, 0xf9, 0x50, 0xf5, 0x0a, 0x47, 0x82, 0x3c, 0xeb, 0x3e, 0x33, 0x16, 0x33, 0x8f, 0xd9, 0xe0, 0xce, 0x73, 0x63, 0x26, 0xea, 0x10, 0x7a, 0x73, 0xf1, 0x42, 0x55, 0x80, 0x4b, 0x51, 0xba, 0xb3, 0x73, 0x63, 0xeb, 0x61, 0x21, 0x88, 0xbb, 0x1b, 0x33, 0xb1, 0xeb, 0xe2, 0x09, 0xb9, 0x82, 0x1f, 0xbb, 0x0b, 0xef, 0x65, 0x28, 0xc6, 0x7e, 0x1a, 0x26, - 0x11, 0x9f, 0x78, 0xa8, 0xe6, 0xba, 0xc8, 0xcf, 0xa4, 0xbd, 0xf1, 0x18, 0xe5, 0xbb, 0x57, 0xf8, 0x4c, 0x10, 0xb7, - 0xeb, 0xd6, 0x26, 0xf8, 0x95, 0x20, 0x57, 0xa7, 0xbb, 0x8b, 0x33, 0x91, 0x77, 0xae, 0xf0, 0x59, 0xe1, 0xb1, 0xc7, - 0x6f, 0x88, 0x87, 0x48, 0xe7, 0x4c, 0x43, 0x73, 0xce, 0x27, 0xca, 0x73, 0xef, 0x22, 0xfc, 0x1e, 0xe2, 0x2a, 0x69, - 0xc9, 0x6d, 0x74, 0x68, 0x65, 0x87, 0xb8, 0x5c, 0xba, 0x08, 0xdc, 0xbd, 0x3d, 0xab, 0xac, 0x50, 0x15, 0xf0, 0xad, - 0x20, 0x15, 0x83, 0x1c, 0xbf, 0x95, 0x11, 0x9a, 0x5b, 0xe1, 0xa5, 0xc8, 0x0c, 0xe3, 0x19, 0x3f, 0xb4, 0x3e, 0x9a, + 0x11, 0x9f, 0x78, 0xa8, 0xe6, 0xba, 0xc8, 0xcf, 0xa4, 0xbd, 0xf1, 0x18, 0xe5, 0xbb, 0x57, 0xf8, 0x56, 0x10, 0xb7, + 0xeb, 0xd6, 0x26, 0xf8, 0x95, 0x20, 0x57, 0xa7, 0xbb, 0x8b, 0x5b, 0x91, 0x77, 0xae, 0xf0, 0x6d, 0xe1, 0xb1, 0xc7, + 0x6f, 0x88, 0x87, 0x48, 0xe7, 0x56, 0x43, 0x73, 0xce, 0x27, 0xca, 0x73, 0xef, 0x22, 0xfc, 0x1e, 0xe2, 0x2a, 0x69, + 0xc9, 0x6d, 0x74, 0x68, 0x65, 0x87, 0xb8, 0x5c, 0xba, 0x08, 0xdc, 0xbd, 0x3d, 0xab, 0xac, 0x50, 0x15, 0xf0, 0x99, + 0x20, 0x15, 0x83, 0x1c, 0xbf, 0x95, 0x11, 0x9a, 0x33, 0xe1, 0xa5, 0xc8, 0x0c, 0xe3, 0x19, 0x3f, 0xb4, 0x3e, 0x9a, 0x69, 0x4f, 0x79, 0x18, 0x7c, 0x26, 0x68, 0x1a, 0x0a, 0x9e, 0xf6, 0x91, 0xad, 0x7e, 0xe0, 0xbf, 0x91, 0xab, 0x9e, 0xf3, 0x9f, 0xbe, 0xf8, 0x79, 0xf8, 0x73, 0xda, 0xbf, 0xc2, 0xaf, 0xc9, 0xfe, 0xa9, 0xd7, 0x0d, 0xbc, 0x9d, 0x7a, 0x7d, 0xf9, 0xf3, 0x7e, 0xef, 0x1f, 0x61, 0xfd, 0xd7, 0xb3, 0xfa, 0x4f, 0x7d, 0xb4, 0xf4, 0x7e, 0xde, 0xef, 0xf6, @@ -177,7 +177,7 @@ const uint8_t INDEX_GZ[] PROGMEM = { 0xf2, 0x03, 0x64, 0x81, 0xc0, 0xf3, 0x30, 0x9e, 0xd1, 0x2c, 0xa0, 0x39, 0xc2, 0x03, 0x72, 0x21, 0xbc, 0x26, 0xc2, 0xcf, 0x05, 0xfc, 0x68, 0x21, 0x7c, 0xa1, 0x03, 0x98, 0x70, 0x90, 0x15, 0x51, 0x25, 0x5c, 0x69, 0x2c, 0x2e, 0xc2, 0xd3, 0x0d, 0x95, 0x62, 0x0c, 0xde, 0x05, 0x84, 0x87, 0x95, 0x70, 0x27, 0xbe, 0x21, 0x86, 0x24, 0xde, 0xa5, 0x94, - 0xfe, 0x10, 0xc6, 0x1f, 0x69, 0xea, 0x9d, 0xe1, 0x66, 0xeb, 0x31, 0x96, 0x2e, 0xe8, 0x9d, 0x26, 0x6a, 0x17, 0xb1, + 0xfe, 0x10, 0xc6, 0x1f, 0x69, 0xea, 0xdd, 0xe2, 0x66, 0xeb, 0x31, 0x96, 0x2e, 0xe8, 0x9d, 0x26, 0x6a, 0x17, 0xb1, 0xaa, 0x73, 0xa1, 0x62, 0x04, 0x20, 0x64, 0xab, 0xbe, 0x18, 0xd8, 0xf1, 0x9d, 0x74, 0xcd, 0x61, 0x95, 0x86, 0x37, 0x2e, 0xaa, 0xc6, 0x45, 0x59, 0x32, 0x0f, 0x63, 0x16, 0x39, 0x82, 0x4e, 0xa6, 0x71, 0x28, 0xa8, 0xa3, 0xd7, 0xeb, 0x84, 0x30, 0x90, 0x5b, 0xa8, 0x0c, 0x91, 0x65, 0x70, 0x46, 0x26, 0xe0, 0x04, 0x67, 0xc5, 0x83, 0xe8, 0x94, 0x56, @@ -220,10 +220,10 @@ const uint8_t INDEX_GZ[] PROGMEM = { 0x73, 0xd4, 0x69, 0xa0, 0x45, 0xa5, 0xad, 0xd4, 0x99, 0xaa, 0x71, 0xf4, 0x82, 0x4f, 0xcf, 0x49, 0xa3, 0x3d, 0x3f, 0x1d, 0xb5, 0xe7, 0xb5, 0x1a, 0xca, 0x0c, 0x69, 0xcd, 0x7a, 0xf3, 0x3e, 0x7e, 0x03, 0x4e, 0x3d, 0x9b, 0x96, 0x70, 0x65, 0x79, 0x2d, 0xbd, 0xbc, 0x5a, 0x2d, 0xc9, 0x51, 0xdb, 0xea, 0x3a, 0x52, 0x5d, 0xf3, 0x5c, 0xe1, 0x64, 0x95, - 0xd4, 0x4e, 0x90, 0x2c, 0x81, 0x64, 0x28, 0x42, 0xc8, 0x99, 0x40, 0x1b, 0x47, 0x85, 0x31, 0xa1, 0xbb, 0x3c, 0xb3, + 0xd4, 0x4e, 0x90, 0x2c, 0x81, 0x64, 0x28, 0x42, 0xc8, 0xad, 0x40, 0x1b, 0x47, 0x85, 0x31, 0xa1, 0xbb, 0x3c, 0xb3, 0xc0, 0x3e, 0x95, 0x94, 0xf0, 0x00, 0x0b, 0xd0, 0xb5, 0xf0, 0x04, 0x4f, 0xf0, 0xac, 0xd6, 0x94, 0x64, 0x5e, 0x6f, 0xb6, 0xab, 0x63, 0x3d, 0x2a, 0xc7, 0xc2, 0xb3, 0x1a, 0x99, 0x14, 0x58, 0xca, 0x93, 0x5a, 0x2d, 0xaf, 0x06, 0x3b, - 0xcd, 0xc9, 0xad, 0x04, 0x20, 0xce, 0x56, 0x93, 0x32, 0x8c, 0x84, 0x2d, 0x65, 0x2a, 0xf3, 0x59, 0x92, 0xd0, 0x14, + 0xcd, 0xc9, 0xad, 0x04, 0x20, 0x6e, 0x57, 0x93, 0x32, 0x8c, 0x84, 0x2d, 0x65, 0x2a, 0xf3, 0x59, 0x92, 0xd0, 0x14, 0xa4, 0x28, 0x11, 0x98, 0xe5, 0x79, 0x29, 0xd9, 0x41, 0x8c, 0x62, 0x4a, 0x52, 0xe0, 0x3c, 0xd2, 0xee, 0xc2, 0x09, 0xe6, 0x78, 0x2c, 0xf9, 0x06, 0x21, 0xe4, 0xc2, 0xa4, 0xb3, 0x08, 0xc9, 0x83, 0x62, 0xc2, 0x2c, 0x99, 0x94, 0x11, 0xea, 0x5f, 0xee, 0x9e, 0xf3, 0x7b, 0x6d, 0xb2, 0x1e, 0xeb, 0x07, 0xb2, 0x59, 0xac, 0x39, 0x57, 0x48, 0xde, 0x7b, @@ -238,14 +238,14 @@ const uint8_t INDEX_GZ[] PROGMEM = { 0x13, 0xf3, 0xec, 0xa5, 0x5f, 0xd6, 0xca, 0xc6, 0x97, 0xbb, 0x67, 0xef, 0x37, 0x35, 0x83, 0xf2, 0x7c, 0x56, 0xda, 0xf8, 0x12, 0xbe, 0x05, 0x8d, 0x83, 0x85, 0x16, 0x0e, 0x01, 0xcb, 0xb1, 0x14, 0x48, 0x41, 0x96, 0x17, 0xae, 0x91, 0xa7, 0x38, 0x21, 0x32, 0x0c, 0x54, 0xdd, 0x35, 0xad, 0xe6, 0x31, 0x9e, 0x5c, 0x0c, 0xf8, 0x94, 0x6e, 0x89, 0x0d, - 0x9d, 0x21, 0x9f, 0x4d, 0x20, 0x75, 0x46, 0x82, 0xce, 0xf0, 0x4e, 0x03, 0xb5, 0xab, 0xe2, 0x2b, 0x91, 0x44, 0xca, + 0xdd, 0x22, 0x9f, 0x4d, 0x20, 0x75, 0x46, 0x82, 0xce, 0xf0, 0x4e, 0x03, 0xb5, 0xab, 0xe2, 0x2b, 0x91, 0x44, 0xca, 0x2b, 0xb2, 0x05, 0x8f, 0x49, 0x03, 0xc7, 0xa4, 0x81, 0x43, 0x92, 0xf5, 0x1a, 0x4a, 0x40, 0xb4, 0xc3, 0x62, 0x5c, 0x25, 0x66, 0x20, 0x2b, 0x4c, 0x9f, 0x56, 0x25, 0x80, 0xa3, 0x76, 0x28, 0x7d, 0x8f, 0x52, 0xa6, 0x47, 0x92, 0x2c, 0xde, 0x7a, 0x1c, 0x73, 0x39, 0xf0, 0x05, 0xbb, 0x8e, 0x21, 0xb1, 0x04, 0x56, 0x85, 0x05, 0x0a, 0x8a, 0xa6, 0x4d, 0xdd, 0x34, 0xf4, 0xe5, 0x3e, 0x71, 0x1c, 0xfa, 0xc0, 0xb9, 0x71, 0xa8, 0xf3, 0x70, 0xb2, 0xf5, 0x2e, 0xc7, 0x7b, 0x7b, 0x9e, 0xea, 0xf4, 0x8b, 0xf0, 0xb8, 0xa9, 0x2f, 0x23, 0x77, 0xdf, 0x2b, 0x5e, 0x11, 0x21, 0x09, 0x7f, 0xad, 0x16, 0xf7, 0x73, 0x08, 0x43, 0x7b, 0x61, 0x15, 0x83, 0x06, 0x78, 0xa9, 0xeb, 0x55, 0x97, 0x5f, 0xab, 0x15, 0x51, - 0xda, 0x2a, 0xb6, 0xce, 0x70, 0x92, 0xcf, 0xbd, 0x22, 0xf5, 0xa7, 0xb1, 0x96, 0x2f, 0x65, 0x40, 0x40, 0xcc, 0xa6, + 0xda, 0x2a, 0xb6, 0x6e, 0x71, 0x92, 0xcf, 0xbd, 0x22, 0xf5, 0xa7, 0xb1, 0x96, 0x2f, 0x65, 0x40, 0x40, 0xcc, 0xa6, 0x59, 0x66, 0x16, 0x63, 0x1d, 0x09, 0x06, 0xed, 0xbe, 0xd1, 0x59, 0x0b, 0x58, 0x66, 0x57, 0xe9, 0x46, 0x86, 0x9d, 0xb5, 0x50, 0x60, 0x1a, 0x41, 0x54, 0x0a, 0x1a, 0xd5, 0x72, 0x4d, 0xde, 0x6f, 0xd7, 0x73, 0x2e, 0x71, 0x86, 0xb4, 0x93, 0x4b, 0x42, 0x21, 0x91, 0xd5, 0x2a, 0x90, 0xf2, 0x9c, 0x4c, 0xb7, 0x93, 0xfc, 0x99, 0x45, 0xf2, 0x4f, 0x08, @@ -268,7 +268,7 @@ const uint8_t INDEX_GZ[] PROGMEM = { 0x36, 0x44, 0x4d, 0xa5, 0xd4, 0x91, 0x2d, 0x50, 0xd1, 0xc1, 0x9f, 0x7b, 0x4c, 0x2b, 0x6e, 0x26, 0x6e, 0x06, 0x0c, 0xf8, 0x89, 0xf0, 0x54, 0x30, 0x0a, 0x64, 0x06, 0xf7, 0x67, 0x5e, 0x65, 0xea, 0x36, 0x97, 0xdd, 0xb0, 0x46, 0xdc, 0xd8, 0x46, 0x13, 0x97, 0x71, 0xbd, 0xf3, 0x92, 0x97, 0x0e, 0x55, 0x06, 0xb5, 0x30, 0x5c, 0xb0, 0x4c, 0x24, 0xb1, - 0x96, 0x3f, 0x54, 0x49, 0xd1, 0x45, 0x23, 0x4c, 0x25, 0x18, 0xef, 0xe4, 0x1e, 0xd0, 0x1c, 0xfe, 0x2e, 0x6e, 0x85, + 0x96, 0x3f, 0x54, 0x49, 0xd1, 0x45, 0x23, 0x4c, 0x25, 0x18, 0xef, 0xe4, 0x1e, 0xd0, 0x1c, 0xfe, 0x2e, 0xce, 0x84, 0xb5, 0xa3, 0xc6, 0x89, 0x2d, 0xe7, 0xb4, 0xa4, 0xfe, 0x5b, 0x48, 0x75, 0x59, 0x3d, 0xf3, 0xcf, 0xa5, 0x2c, 0x64, 0x38, 0xab, 0x30, 0xf6, 0x44, 0x32, 0x76, 0x04, 0x7a, 0x9a, 0x49, 0xfc, 0xee, 0xea, 0x8c, 0x17, 0xa6, 0xa5, 0x9c, 0x26, 0xb1, 0x37, 0x45, 0xb4, 0xdc, 0xfa, 0xbd, 0xb2, 0x1b, 0x01, 0x23, 0x90, 0x05, 0x84, 0x35, 0x67, 0x4f, 0x10, @@ -312,7 +312,7 @@ const uint8_t INDEX_GZ[] PROGMEM = { 0xf1, 0xb5, 0x7b, 0x78, 0x63, 0x02, 0x1e, 0xb4, 0x87, 0x4d, 0x61, 0x19, 0xdb, 0x99, 0xba, 0x07, 0x64, 0x8f, 0x4f, 0xb8, 0xd1, 0xdd, 0xaa, 0x56, 0xc6, 0x1b, 0xb0, 0xff, 0x11, 0x1e, 0x9b, 0xcb, 0x71, 0x54, 0x73, 0x60, 0x1a, 0x2c, 0xf2, 0xc2, 0x29, 0xc0, 0x95, 0xf2, 0x96, 0x22, 0xcc, 0x73, 0x19, 0xe0, 0xfe, 0x16, 0x7f, 0xa7, 0x59, 0xe2, 0xb0, - 0xe0, 0x38, 0xb7, 0x0f, 0xe5, 0x88, 0x0a, 0xfc, 0x22, 0x7e, 0x0f, 0x74, 0x2c, 0x29, 0x34, 0x37, 0x54, 0xf4, 0x94, + 0xe0, 0x38, 0x67, 0x0f, 0xe5, 0x88, 0x0a, 0xfc, 0x22, 0x7e, 0x0f, 0x74, 0x2c, 0x29, 0x34, 0x37, 0x54, 0xf4, 0x94, 0xeb, 0x85, 0x6c, 0x4d, 0x4b, 0xc5, 0xb4, 0x48, 0xa9, 0x91, 0xd3, 0x6c, 0xc8, 0xe3, 0x34, 0x56, 0xb6, 0x28, 0x4e, 0x55, 0x65, 0x5e, 0xb4, 0x05, 0x8b, 0x65, 0x68, 0x71, 0xb9, 0xf4, 0xaa, 0xa8, 0x26, 0xcc, 0x8a, 0x64, 0x20, 0xcc, 0xac, 0x8c, 0x8a, 0x8a, 0x66, 0xad, 0xfa, 0x78, 0x68, 0x35, 0xa1, 0xc8, 0xe8, 0xe6, 0x15, 0x38, 0x6c, 0x17, 0x82, @@ -612,31 +612,32 @@ const uint8_t INDEX_GZ[] PROGMEM = { 0xde, 0x0b, 0x3e, 0xda, 0x3c, 0x56, 0xcc, 0x47, 0x5d, 0x79, 0x05, 0x42, 0xdd, 0xb5, 0x35, 0xca, 0x2f, 0x8f, 0xdd, 0xce, 0xa9, 0x56, 0x06, 0x1c, 0x19, 0x0e, 0x77, 0x8f, 0x1a, 0xe6, 0x56, 0x45, 0xcc, 0x47, 0x70, 0x20, 0x55, 0x17, 0x6b, 0x92, 0x8a, 0xc7, 0x7d, 0xdc, 0xec, 0x9c, 0x86, 0x8e, 0xe4, 0x2d, 0x92, 0x79, 0x64, 0xc1, 0x3e, 0x74, 0x1e, - 0xf3, 0x09, 0xf5, 0x19, 0xdf, 0xbf, 0xa1, 0xd7, 0xf5, 0x70, 0xca, 0x4a, 0xf7, 0x36, 0x28, 0x1d, 0xc5, 0x94, 0xbc, - 0x9c, 0x09, 0x7e, 0x86, 0x2b, 0x8b, 0x94, 0x2c, 0x3c, 0xd7, 0xbe, 0x73, 0xb0, 0x55, 0x80, 0x84, 0x5c, 0x47, 0x71, - 0x78, 0xe3, 0x63, 0xd7, 0xb2, 0x37, 0x77, 0x3b, 0xff, 0xfa, 0x3f, 0xfe, 0x97, 0x76, 0x9b, 0x9f, 0xee, 0x8f, 0x9b, - 0x66, 0xac, 0x15, 0x44, 0xe7, 0xa7, 0x70, 0x11, 0xb1, 0x8c, 0xf3, 0xd2, 0xdb, 0xfa, 0x28, 0x65, 0x51, 0x7d, 0x1c, - 0xc6, 0x43, 0xb7, 0xb3, 0x1d, 0x41, 0xf6, 0x0d, 0x24, 0x0d, 0x75, 0xb5, 0x08, 0x48, 0xf0, 0x37, 0xdd, 0xa1, 0x31, - 0x57, 0x31, 0xe4, 0x69, 0xb5, 0x6f, 0xd4, 0x94, 0x07, 0xaa, 0x72, 0xab, 0x26, 0xd5, 0x5f, 0xaf, 0xd2, 0x4c, 0x2d, - 0xad, 0x5c, 0xa6, 0xc9, 0x5d, 0xa7, 0x88, 0x53, 0xfd, 0xdf, 0xff, 0xf9, 0x5f, 0xfe, 0x9b, 0x79, 0x84, 0xf0, 0xd3, - 0xbf, 0xfe, 0xf7, 0xff, 0xfc, 0x7f, 0xfe, 0xf7, 0x7f, 0x85, 0x0b, 0x18, 0x3a, 0x44, 0x25, 0xf9, 0x84, 0x53, 0xc6, - 0xa7, 0x14, 0xc3, 0x70, 0x20, 0x47, 0x71, 0xc2, 0x32, 0xc1, 0x06, 0xd5, 0xeb, 0x35, 0x17, 0x72, 0x42, 0x79, 0xd8, - 0x34, 0x74, 0xf2, 0xd0, 0xe6, 0x25, 0x8d, 0x54, 0x50, 0x2e, 0x69, 0x31, 0x3f, 0xdd, 0x07, 0x7c, 0x3f, 0xec, 0x46, - 0xa2, 0x5f, 0x6c, 0xc7, 0xc2, 0x38, 0x65, 0xa1, 0x24, 0x2f, 0xcb, 0x1d, 0x08, 0x97, 0x2c, 0xe0, 0x31, 0x68, 0x59, - 0xc5, 0x72, 0xf7, 0x2a, 0x7d, 0xda, 0x1f, 0x66, 0x99, 0x60, 0x43, 0x40, 0xb9, 0x72, 0xfd, 0xca, 0xc8, 0x74, 0x1d, - 0xd4, 0xbf, 0xf8, 0x2e, 0x97, 0xa3, 0x28, 0xdb, 0xfa, 0xf0, 0xe4, 0x4f, 0xf9, 0x5f, 0x26, 0xa0, 0x64, 0x39, 0xde, - 0x24, 0xbc, 0xd5, 0x16, 0xf7, 0x71, 0xa3, 0x31, 0xbd, 0x45, 0x8b, 0x72, 0x06, 0xbc, 0x6d, 0x32, 0xe9, 0x2e, 0xb6, - 0x07, 0x94, 0x21, 0xed, 0xc2, 0x33, 0xdd, 0x70, 0xc0, 0xbd, 0xed, 0x34, 0xf2, 0xfc, 0xcf, 0x0b, 0xe9, 0x1c, 0x65, - 0xbf, 0x42, 0xe8, 0x59, 0xfb, 0x91, 0xaf, 0xb9, 0xbd, 0xb8, 0x85, 0xd5, 0xab, 0xa5, 0x7a, 0x8d, 0x9b, 0xeb, 0x17, - 0xed, 0xec, 0xd0, 0xb9, 0x1d, 0xf4, 0x3e, 0x84, 0x30, 0xf6, 0xb8, 0x89, 0xc7, 0xad, 0x45, 0x31, 0xbc, 0x10, 0x7c, - 0x62, 0xc7, 0xca, 0x69, 0x48, 0x07, 0x74, 0x68, 0xfc, 0xef, 0xba, 0x5e, 0xc5, 0xc1, 0xf3, 0xf1, 0xc1, 0x86, 0xb9, - 0x34, 0x48, 0x32, 0x46, 0xee, 0x34, 0xf2, 0x2f, 0xe1, 0x04, 0x2e, 0x86, 0x31, 0x0f, 0x45, 0x20, 0x09, 0xb6, 0x6d, - 0x47, 0xdc, 0x43, 0x60, 0x33, 0x7c, 0x61, 0xc1, 0xd3, 0x56, 0x4d, 0xc1, 0x13, 0x5e, 0xbd, 0x0e, 0x99, 0xfb, 0xb2, - 0xbb, 0x3d, 0x94, 0x72, 0xa4, 0x7d, 0xaf, 0x03, 0xd9, 0xaf, 0x2a, 0x1e, 0x28, 0x2d, 0x63, 0x5a, 0x68, 0x73, 0xbd, - 0x12, 0xd5, 0xaa, 0xf6, 0x27, 0xe1, 0xb9, 0x12, 0x4c, 0x77, 0xb5, 0x95, 0x2c, 0x84, 0x56, 0xaf, 0xc8, 0xf7, 0x85, - 0x15, 0x14, 0x4e, 0xa7, 0xb2, 0x21, 0x6a, 0x9f, 0xee, 0x2b, 0xe5, 0x15, 0xb8, 0x87, 0xcc, 0xd2, 0x50, 0x49, 0x11, - 0xba, 0x91, 0x3e, 0x0a, 0xea, 0x97, 0x4e, 0x97, 0x80, 0xcf, 0x9a, 0x75, 0xfe, 0x1f, 0xd6, 0xb2, 0x30, 0xa4, 0x67, - 0x88, 0x00, 0x00}; + 0xf3, 0x09, 0xf5, 0x19, 0xdf, 0xbf, 0xa1, 0xd7, 0xf5, 0x70, 0xca, 0x4a, 0xf7, 0x36, 0x28, 0x1d, 0xc5, 0x94, 0xdc, + 0x78, 0xc4, 0xf5, 0x9d, 0xa3, 0x56, 0xe9, 0x6e, 0x3b, 0x04, 0x9b, 0xc7, 0xb8, 0xe6, 0xa4, 0x4f, 0xce, 0x02, 0x8b, + 0x77, 0x4e, 0xf7, 0xc3, 0x15, 0x8c, 0x48, 0x7e, 0x9f, 0x6b, 0x47, 0x3b, 0x18, 0x36, 0x40, 0x6f, 0xae, 0xa3, 0xc4, + 0x81, 0x71, 0xc8, 0x6b, 0x41, 0x9d, 0xbb, 0x9d, 0x7f, 0xfd, 0x1f, 0xff, 0x4b, 0xfb, 0xd8, 0x4f, 0xf7, 0xc7, 0x4d, + 0x33, 0xd6, 0xca, 0xae, 0xe4, 0xa7, 0x70, 0x6b, 0xb1, 0x0c, 0x0a, 0xd3, 0xdb, 0xfa, 0x28, 0x65, 0x51, 0x7d, 0x1c, + 0xc6, 0x43, 0xb7, 0xb3, 0x1d, 0x9b, 0xf6, 0x75, 0x25, 0x0d, 0x75, 0xb5, 0x08, 0xe8, 0xf5, 0x37, 0x5d, 0xb8, 0x31, + 0xf7, 0x36, 0xe4, 0xd1, 0xb6, 0xaf, 0xdf, 0x94, 0xa7, 0xaf, 0x72, 0x05, 0x27, 0xd5, 0x9f, 0xba, 0xd2, 0x1c, 0x30, + 0xad, 0xdc, 0xbc, 0xc9, 0x5d, 0xa7, 0x08, 0x6a, 0xfd, 0xdf, 0xff, 0xf9, 0x5f, 0xfe, 0x9b, 0x79, 0x84, 0x58, 0xd5, + 0xbf, 0xfe, 0xf7, 0xff, 0xfc, 0x7f, 0xfe, 0xf7, 0x7f, 0x85, 0xdb, 0x1a, 0x3a, 0x9e, 0x25, 0x99, 0x8a, 0x53, 0x06, + 0xb3, 0x14, 0x77, 0x71, 0x20, 0xa1, 0x71, 0xc2, 0x32, 0xc1, 0x06, 0xd5, 0xbb, 0x38, 0x17, 0x72, 0x42, 0x79, 0x32, + 0x35, 0x74, 0xf2, 0x84, 0xe7, 0x25, 0x41, 0x55, 0x50, 0x2e, 0x09, 0x37, 0x3f, 0xdd, 0x07, 0x7c, 0x3f, 0xec, 0xfa, + 0xa2, 0x5f, 0x6c, 0xc7, 0xc2, 0x90, 0x09, 0x94, 0xe4, 0x65, 0xb9, 0x03, 0xb1, 0x95, 0x05, 0x3c, 0x06, 0x2d, 0xab, + 0x58, 0xee, 0x5e, 0xa5, 0x4f, 0xfb, 0xc3, 0x2c, 0x13, 0x6c, 0x08, 0x28, 0x57, 0x7e, 0x62, 0x19, 0xc6, 0xae, 0x83, + 0xae, 0x18, 0xdf, 0xe5, 0x72, 0x14, 0x45, 0xa0, 0x87, 0x27, 0x7f, 0xca, 0xff, 0x32, 0x01, 0x8d, 0xcc, 0xf1, 0x26, + 0xe1, 0xad, 0x36, 0xcf, 0x8f, 0x1b, 0x8d, 0xe9, 0x2d, 0x5a, 0x94, 0x33, 0xe0, 0x6d, 0x93, 0x49, 0x3a, 0xb6, 0x07, + 0x94, 0xf1, 0xef, 0xc2, 0x8d, 0xdd, 0x70, 0xc0, 0x17, 0xee, 0x34, 0xf2, 0xfc, 0xcf, 0x0b, 0xe9, 0x49, 0x65, 0xbf, + 0x42, 0x9c, 0x5a, 0x3b, 0x9d, 0xaf, 0xb9, 0xbd, 0xb8, 0x85, 0xd5, 0xab, 0xa5, 0x7a, 0x8d, 0x9b, 0xeb, 0xb7, 0xf2, + 0xec, 0x38, 0xbb, 0x1d, 0x21, 0x3f, 0x84, 0x98, 0xf7, 0xb8, 0x89, 0xc7, 0xad, 0x45, 0x31, 0xbc, 0x10, 0x7c, 0x62, + 0x07, 0xd6, 0x69, 0x48, 0x07, 0x74, 0x68, 0x9c, 0xf5, 0xba, 0x5e, 0x05, 0xcd, 0xf3, 0xf1, 0xc1, 0x86, 0xb9, 0x34, + 0x48, 0x32, 0xa0, 0xee, 0x34, 0xf2, 0x2f, 0xe1, 0x04, 0x2e, 0x86, 0x31, 0x0f, 0x45, 0x20, 0x09, 0xb6, 0x6d, 0x87, + 0xe7, 0x43, 0xe0, 0x49, 0x7c, 0x61, 0xc1, 0xd3, 0x56, 0x4d, 0xc1, 0x6d, 0x5e, 0xbd, 0x3b, 0x99, 0xfb, 0xb2, 0xbb, + 0x3d, 0x94, 0xf2, 0xba, 0x7d, 0xaf, 0xa3, 0xde, 0xaf, 0x2a, 0xee, 0x2a, 0x2d, 0x90, 0x5a, 0x68, 0x73, 0xbd, 0x92, + 0xeb, 0xaa, 0xf6, 0x27, 0xe1, 0xb9, 0x12, 0x4c, 0x77, 0xb5, 0x95, 0x2c, 0x84, 0x56, 0xaf, 0xc8, 0xf7, 0x85, 0xc9, + 0x14, 0x4e, 0xa7, 0xb2, 0x21, 0x6a, 0x9f, 0xee, 0x2b, 0x4d, 0x17, 0xb8, 0x87, 0x4c, 0xe9, 0x50, 0x19, 0x14, 0xba, + 0x91, 0x3e, 0x0a, 0xea, 0x97, 0xce, 0xad, 0x80, 0x6f, 0xa0, 0x75, 0xfe, 0x1f, 0xa2, 0x48, 0xf6, 0xdd, 0x94, 0x88, + 0x00, 0x00}; } // namespace web_server } // namespace esphome diff --git a/esphome/components/web_server/server_index_v3.h b/esphome/components/web_server/server_index_v3.h index bde1ce1fb5..0c16ea9f37 100644 --- a/esphome/components/web_server/server_index_v3.h +++ b/esphome/components/web_server/server_index_v3.h @@ -3632,373 +3632,374 @@ const uint8_t INDEX_GZ[] PROGMEM = { 0xe7, 0xec, 0xd8, 0x98, 0x31, 0x94, 0x4f, 0x43, 0x40, 0x9e, 0xd0, 0xf7, 0x01, 0xcd, 0x25, 0x67, 0x23, 0xad, 0x2b, 0xfb, 0x10, 0x17, 0x97, 0xdc, 0x84, 0x6a, 0x31, 0x6f, 0x2b, 0x3d, 0x2a, 0xc4, 0x1b, 0x16, 0x80, 0x65, 0xe9, 0x69, 0x93, 0x82, 0x6c, 0x94, 0x54, 0x45, 0xfe, 0x13, 0xbf, 0x03, 0xae, 0xad, 0xac, 0xe4, 0x0a, 0x78, 0xf5, 0xff, 0xd3, - 0xdc, 0x93, 0x2e, 0xb7, 0x6d, 0x24, 0xfd, 0x3f, 0x4f, 0x01, 0xc3, 0x5e, 0x87, 0xb0, 0x01, 0x08, 0x00, 0x45, 0x89, - 0x26, 0x45, 0x69, 0x13, 0x1f, 0xb5, 0x4e, 0x29, 0x71, 0xca, 0x56, 0x5c, 0xbb, 0x51, 0x54, 0x22, 0x48, 0x0e, 0x49, - 0xac, 0x41, 0x80, 0x05, 0x80, 0x3a, 0x42, 0x63, 0x9f, 0x65, 0x9f, 0x65, 0x9f, 0xec, 0xab, 0xee, 0x9e, 0x19, 0x0c, - 0x0e, 0x1e, 0x8a, 0x9d, 0xdd, 0xaf, 0x12, 0xdb, 0xc4, 0xdc, 0xd3, 0x33, 0xd3, 0xd3, 0xd3, 0xa7, 0x3f, 0xe3, 0xbc, - 0x17, 0xb3, 0xc5, 0xf6, 0xeb, 0xee, 0xf3, 0x67, 0x66, 0xe3, 0x96, 0x04, 0x82, 0xcf, 0xce, 0xe2, 0xd9, 0x2c, 0x64, - 0x2d, 0x5d, 0x04, 0x0f, 0xd1, 0x4d, 0xd9, 0xcd, 0xd9, 0x23, 0x47, 0x78, 0xec, 0x34, 0xf2, 0x4d, 0x47, 0x4b, 0xcc, - 0x98, 0x49, 0x97, 0x76, 0x44, 0xb9, 0x22, 0x6f, 0xf6, 0x06, 0xc5, 0x1b, 0x7c, 0x5d, 0x8a, 0xa3, 0x6b, 0x4d, 0xe2, - 0xd5, 0x28, 0x64, 0x16, 0x6e, 0x77, 0xe8, 0x72, 0x3d, 0x5a, 0x8d, 0x46, 0x10, 0xa5, 0xe5, 0x91, 0x63, 0x82, 0xdf, - 0x99, 0x38, 0xc5, 0xf7, 0x60, 0x6e, 0xf4, 0x61, 0x52, 0x76, 0x56, 0x1d, 0x3e, 0xe8, 0x8a, 0x00, 0xab, 0x87, 0x3a, - 0xc8, 0xe0, 0xed, 0xd7, 0x70, 0x6a, 0x07, 0xfa, 0x07, 0xd8, 0x7d, 0xa9, 0xde, 0x6f, 0x3a, 0xfa, 0x83, 0x4b, 0xfd, - 0x03, 0xc2, 0x18, 0xa3, 0x17, 0xbf, 0xa4, 0xdd, 0xab, 0x9b, 0x3a, 0x09, 0xbd, 0x57, 0x18, 0xc7, 0x00, 0x98, 0xbe, - 0xaf, 0x02, 0x7f, 0x16, 0xc5, 0x69, 0x16, 0x8c, 0xf5, 0xab, 0xfe, 0xdb, 0xa0, 0x75, 0xb9, 0xc8, 0x5a, 0xc6, 0x95, - 0x39, 0xce, 0xd4, 0x10, 0x28, 0x02, 0x61, 0x62, 0x04, 0x94, 0x4d, 0x85, 0xd4, 0x13, 0xb4, 0xb5, 0xa0, 0x40, 0xcd, - 0x58, 0x68, 0x9c, 0x0d, 0xa0, 0x5c, 0x25, 0x9e, 0x0a, 0x06, 0x86, 0xd2, 0xb1, 0xa6, 0xd1, 0xa7, 0x97, 0xca, 0xcb, - 0xd5, 0x1a, 0xaf, 0xf2, 0xac, 0xb8, 0x2d, 0xd1, 0x07, 0xb0, 0x30, 0x9c, 0xa1, 0xef, 0x47, 0xaa, 0xd2, 0x67, 0xe9, - 0xde, 0x1d, 0x7e, 0x57, 0xa6, 0x0b, 0xe0, 0xfe, 0x06, 0x8d, 0x8b, 0x28, 0xce, 0x34, 0x70, 0x6c, 0x03, 0x3d, 0x0e, - 0xab, 0x4a, 0x62, 0xbc, 0xd5, 0x96, 0x91, 0x73, 0x64, 0xf0, 0x3d, 0x5e, 0x7e, 0x2d, 0xee, 0xde, 0xac, 0xe4, 0xc1, - 0x82, 0x1e, 0x0b, 0x11, 0x2c, 0x60, 0x16, 0x9f, 0xc7, 0xb7, 0x55, 0x39, 0xc8, 0xcb, 0xe1, 0xee, 0xbb, 0xb7, 0x25, - 0xc8, 0x64, 0x11, 0xd5, 0xaf, 0xc5, 0x03, 0x93, 0x0a, 0x42, 0xa7, 0x72, 0xa6, 0x50, 0xf1, 0x43, 0xd0, 0x30, 0x19, - 0xe8, 0x89, 0xe1, 0x5d, 0x00, 0x28, 0x89, 0x5f, 0xd3, 0xc3, 0xfc, 0x5a, 0x84, 0x4e, 0x16, 0x81, 0x8b, 0x95, 0xcb, - 0x19, 0xb0, 0x6b, 0xb4, 0x5c, 0x65, 0xe8, 0x6a, 0x17, 0x06, 0xc0, 0x72, 0x5d, 0x43, 0xd7, 0x9d, 0x80, 0xa5, 0x0b, - 0x32, 0x31, 0xd7, 0xb5, 0x60, 0x52, 0x4f, 0xe3, 0x44, 0x2f, 0x20, 0x2f, 0xc4, 0xef, 0xc8, 0xa8, 0x82, 0xcf, 0x84, - 0x4f, 0x63, 0x6c, 0x16, 0x7e, 0xea, 0x5b, 0x63, 0x14, 0xe8, 0x34, 0x60, 0x86, 0x31, 0xb5, 0xd3, 0x6f, 0x85, 0x8d, - 0x93, 0x05, 0xf7, 0x9b, 0xa5, 0x69, 0x0e, 0x9f, 0xac, 0xa3, 0xfc, 0xec, 0xc9, 0x3a, 0xcd, 0x07, 0x4f, 0xd6, 0xbe, - 0xd4, 0x15, 0xd0, 0x2f, 0x74, 0x52, 0x14, 0x18, 0x22, 0x18, 0x86, 0xf9, 0x75, 0x61, 0xb9, 0x53, 0xcc, 0x17, 0x76, - 0x19, 0xa5, 0x6b, 0x28, 0xba, 0x1f, 0x70, 0x01, 0xfd, 0x32, 0x09, 0x16, 0x7e, 0x72, 0x4f, 0xf2, 0x7c, 0x53, 0x15, - 0xfa, 0x1b, 0xba, 0x46, 0x88, 0x9e, 0x00, 0x40, 0x38, 0x5f, 0xd7, 0xfe, 0x2a, 0xd3, 0x18, 0x9f, 0xad, 0x14, 0x6a, - 0x42, 0x5f, 0xd7, 0xfa, 0x73, 0x66, 0x4f, 0x58, 0xe6, 0x07, 0x21, 0x55, 0xe9, 0x8b, 0x68, 0xf5, 0xb5, 0xe9, 0xa5, - 0xe5, 0xe9, 0x45, 0xe5, 0xfd, 0x83, 0x93, 0xa1, 0x2b, 0x80, 0xc6, 0x8d, 0x33, 0xc3, 0x28, 0x56, 0xcd, 0x2b, 0x4a, - 0x79, 0xff, 0xd5, 0xe5, 0x60, 0xb0, 0x1c, 0x11, 0x2c, 0x07, 0x8b, 0xc6, 0xf1, 0x84, 0xfd, 0xf2, 0xfe, 0xad, 0x0c, - 0x9b, 0x05, 0x1c, 0xa0, 0x21, 0xdf, 0x98, 0x29, 0xd2, 0x0f, 0x09, 0xd2, 0x0e, 0x14, 0xe0, 0x4a, 0x93, 0x5b, 0x28, - 0xc9, 0x75, 0xed, 0x8c, 0xc6, 0xce, 0x26, 0x34, 0xea, 0x41, 0x8c, 0xb5, 0x92, 0xfc, 0xe4, 0x80, 0x4a, 0xd3, 0x6d, - 0x47, 0x85, 0x00, 0x0c, 0x09, 0xcc, 0xb0, 0x80, 0x02, 0x44, 0xf8, 0x1c, 0xb8, 0xc5, 0x83, 0xc2, 0x5e, 0x20, 0x9f, - 0xdd, 0x3d, 0x2b, 0x93, 0x2a, 0x58, 0x4b, 0x3f, 0x3d, 0xc1, 0x98, 0x5d, 0x70, 0x5f, 0x83, 0x97, 0x8f, 0x93, 0x03, - 0xfa, 0xd4, 0x2a, 0x27, 0xa2, 0x68, 0x44, 0x3c, 0xed, 0x7a, 0xbc, 0x81, 0x07, 0x1d, 0x15, 0x08, 0x11, 0x0f, 0xa9, - 0x7e, 0xae, 0x6b, 0x0b, 0x4e, 0x1a, 0x71, 0x77, 0x42, 0xe0, 0x6b, 0xc0, 0x81, 0xb3, 0xab, 0x6b, 0x0b, 0xff, 0x0e, - 0x67, 0x2e, 0x72, 0xfc, 0xbb, 0x96, 0xcb, 0xb3, 0x8a, 0xb3, 0x96, 0x96, 0xcf, 0xda, 0x98, 0x2f, 0x2e, 0x18, 0x12, - 0xc8, 0x97, 0xf5, 0x1c, 0x05, 0xb4, 0x0d, 0x8b, 0x3b, 0x17, 0x8b, 0x3b, 0xd9, 0xb0, 0xb8, 0x93, 0x2d, 0x8b, 0x1b, - 0xf2, 0x85, 0xd4, 0x24, 0xe8, 0x12, 0x34, 0x0e, 0x93, 0xc0, 0xe3, 0x84, 0x46, 0x8f, 0x9f, 0x33, 0x84, 0x93, 0x95, - 0x86, 0xa0, 0x1c, 0xb5, 0x01, 0x56, 0x4d, 0x70, 0x51, 0x00, 0x51, 0x9f, 0xb8, 0x3c, 0x75, 0x62, 0xde, 0x10, 0x83, - 0xb3, 0x15, 0x56, 0xe7, 0x0b, 0xbb, 0x94, 0xe2, 0x8b, 0xb7, 0xe6, 0x1b, 0x66, 0x3a, 0xdf, 0x32, 0xd3, 0x71, 0xe9, - 0xe8, 0xf2, 0x69, 0xd3, 0x21, 0x54, 0x27, 0x05, 0x7b, 0x10, 0x14, 0x46, 0x71, 0xcb, 0x94, 0xf7, 0xe1, 0x66, 0x1c, - 0xab, 0xec, 0xa8, 0xa5, 0x9f, 0xa6, 0xb7, 0x71, 0x02, 0x12, 0x17, 0x68, 0xe6, 0x61, 0x5b, 0x6a, 0x11, 0x44, 0xdc, - 0x99, 0xcb, 0xc6, 0xcd, 0x54, 0xe4, 0xab, 0x5b, 0xca, 0xeb, 0x74, 0xa8, 0xc4, 0xd2, 0xcf, 0x32, 0x96, 0x20, 0xd0, - 0x7d, 0xf0, 0xfa, 0xfd, 0xff, 0x64, 0x9b, 0x35, 0xe0, 0x90, 0x50, 0xc1, 0xea, 0x88, 0xa1, 0x97, 0x40, 0x5b, 0x25, - 0xe2, 0x22, 0x56, 0x1c, 0xc3, 0x25, 0x12, 0xf0, 0x3f, 0xe1, 0x71, 0x6d, 0x25, 0x8a, 0xe9, 0x92, 0x7b, 0x64, 0xd8, - 0x4b, 0x7f, 0xf2, 0x01, 0x04, 0x7b, 0x2d, 0xcf, 0x04, 0x25, 0x5d, 0xd5, 0x0d, 0x5c, 0x42, 0xc4, 0xde, 0xb8, 0x40, - 0x92, 0x88, 0x25, 0xb9, 0x0a, 0x14, 0x58, 0x4f, 0xfa, 0xd6, 0xf4, 0x6a, 0xed, 0xe5, 0x07, 0xb3, 0xc0, 0xa8, 0x61, - 0x4d, 0x40, 0x6d, 0xe1, 0xe0, 0x54, 0xbe, 0xb9, 0x42, 0xd3, 0x3d, 0x32, 0x80, 0xf3, 0x7b, 0x09, 0xf1, 0x4c, 0x1d, - 0xf1, 0xa0, 0x1d, 0x26, 0x70, 0x6b, 0x5d, 0x3a, 0x57, 0xf9, 0xd3, 0x19, 0xfe, 0x72, 0xaf, 0xf2, 0xa7, 0x23, 0xfc, - 0xe5, 0x5d, 0x61, 0xe4, 0xba, 0x86, 0x87, 0xbc, 0x32, 0x67, 0xfd, 0xb4, 0xb4, 0x9f, 0x48, 0xff, 0xec, 0x01, 0xdb, - 0x86, 0x2f, 0xf0, 0xe3, 0x27, 0xeb, 0x14, 0x2c, 0x2e, 0xd5, 0x39, 0x44, 0x76, 0x62, 0xe4, 0x8d, 0xe9, 0xb3, 0x0d, - 0xe9, 0x23, 0xe3, 0xbf, 0x7c, 0xf1, 0xe3, 0x2e, 0x89, 0x8b, 0x3b, 0xa5, 0xcc, 0x86, 0xb8, 0x1e, 0x05, 0x91, 0x9f, - 0xdc, 0x5f, 0xd3, 0xf3, 0xa2, 0x25, 0x68, 0x77, 0xc9, 0x5e, 0x21, 0xf2, 0xb2, 0x2c, 0xee, 0xca, 0x14, 0x06, 0xef, - 0x3d, 0xbf, 0xe8, 0x07, 0x7f, 0x4f, 0x14, 0xb2, 0xad, 0xf4, 0x00, 0xe5, 0x0b, 0x52, 0xea, 0xe8, 0xfa, 0xc9, 0xba, - 0xc5, 0xea, 0xcd, 0x54, 0x66, 0x5b, 0xa1, 0x0b, 0x61, 0x79, 0xf0, 0x31, 0xbb, 0x98, 0x04, 0x3d, 0x94, 0x67, 0x8d, - 0xe2, 0x3b, 0xeb, 0xc9, 0x3a, 0x3b, 0xd3, 0x17, 0x7e, 0xf2, 0x89, 0x4d, 0xac, 0x71, 0x90, 0x8c, 0x43, 0xa6, 0xf7, - 0xf4, 0x51, 0xe8, 0x47, 0x9f, 0xf8, 0xa7, 0x15, 0xaf, 0x32, 0x94, 0x50, 0xef, 0x7c, 0xfb, 0x0a, 0x98, 0x10, 0xcb, - 0x0e, 0x89, 0xd5, 0x06, 0x28, 0x68, 0x2f, 0x25, 0xc3, 0xab, 0x20, 0x14, 0x8b, 0x52, 0x26, 0x28, 0x58, 0x82, 0xd0, - 0x1c, 0x2c, 0x56, 0x4d, 0x1d, 0xd7, 0x4b, 0x37, 0xd5, 0xa9, 0x12, 0xb3, 0x52, 0x86, 0x5c, 0xbc, 0xc6, 0x16, 0xfe, - 0x78, 0x77, 0x14, 0x0c, 0x7b, 0xff, 0xee, 0x64, 0x2b, 0x5f, 0x36, 0x43, 0x48, 0xb5, 0xc8, 0x52, 0xe2, 0x01, 0x9d, - 0x73, 0x02, 0x73, 0x73, 0xd7, 0x6a, 0x65, 0x3f, 0x4d, 0x57, 0x0b, 0x36, 0x21, 0xc9, 0xe0, 0x59, 0x31, 0xa8, 0xf2, - 0xcb, 0x42, 0x1d, 0xd8, 0x6f, 0x2b, 0xef, 0xf8, 0xf0, 0x25, 0x68, 0x2c, 0x00, 0x41, 0x19, 0x4f, 0xa7, 0x7a, 0xf1, - 0xc6, 0xdf, 0x51, 0xcd, 0x3d, 0xfc, 0x6d, 0xf5, 0xe6, 0xb5, 0xf3, 0x46, 0x56, 0x8e, 0x80, 0x30, 0x16, 0xe2, 0x57, - 0x4e, 0x17, 0x2b, 0xe3, 0x15, 0x33, 0x9a, 0xfa, 0xd1, 0xe6, 0xe9, 0x5c, 0x96, 0xb6, 0xf8, 0x92, 0xb1, 0x09, 0x10, - 0xdc, 0x66, 0x2d, 0xf5, 0x3a, 0x64, 0x37, 0x4c, 0x8a, 0x76, 0xeb, 0x9d, 0x35, 0xd4, 0x40, 0xdf, 0x73, 0x5c, 0x64, - 0xcc, 0xa9, 0x3a, 0x65, 0x4a, 0x43, 0x9c, 0x03, 0x9f, 0xb9, 0x7a, 0xc4, 0x2a, 0x47, 0x6a, 0x68, 0xea, 0xca, 0x00, - 0x36, 0x8e, 0xec, 0x6c, 0x43, 0x7a, 0x0f, 0x03, 0x4f, 0x37, 0x8f, 0xcd, 0x74, 0x8d, 0x1e, 0xf8, 0xea, 0xe6, 0x70, - 0x0a, 0xe1, 0xe4, 0xb5, 0x0a, 0x76, 0xc8, 0x26, 0x88, 0x35, 0x31, 0xc9, 0x74, 0xe2, 0xbe, 0x08, 0x6d, 0x47, 0x54, - 0xfb, 0x15, 0x7c, 0xa8, 0xc6, 0xb5, 0xd1, 0xca, 0x33, 0x1f, 0x61, 0x40, 0xd7, 0x88, 0xa5, 0xe9, 0x46, 0x80, 0xc9, - 0x45, 0x37, 0xf5, 0xa2, 0x74, 0x19, 0x1e, 0x45, 0xba, 0xe9, 0x98, 0x40, 0x12, 0xe0, 0x04, 0xab, 0x7d, 0xe1, 0xf5, - 0x72, 0xbd, 0xe0, 0xfa, 0x2a, 0xc9, 0x6c, 0xa4, 0x73, 0x5d, 0x82, 0x4d, 0xf9, 0xb7, 0x3a, 0x1f, 0x54, 0xe9, 0x9a, - 0x6e, 0x1c, 0x5a, 0xab, 0x84, 0x7a, 0x6b, 0xec, 0x22, 0x6c, 0x40, 0x8c, 0xa9, 0x82, 0x5f, 0xd9, 0x74, 0xca, 0xc6, - 0x59, 0x6a, 0x08, 0xe6, 0x91, 0xf4, 0x1e, 0x0b, 0x56, 0x43, 0x8f, 0x06, 0xfa, 0x4f, 0x60, 0x43, 0x2f, 0x9c, 0x2c, - 0xf1, 0x01, 0x89, 0x37, 0x53, 0x33, 0x98, 0xa8, 0xc5, 0x32, 0x88, 0x78, 0x2f, 0x10, 0x1c, 0xbc, 0x21, 0x1d, 0x87, - 0xc6, 0xef, 0x9f, 0x62, 0x5f, 0xc4, 0x52, 0xab, 0x65, 0x3b, 0x2a, 0xda, 0x76, 0x7c, 0xd7, 0xee, 0x9b, 0x8e, 0xeb, - 0xe4, 0xba, 0x09, 0xb6, 0x5b, 0x9f, 0xf6, 0x3d, 0xf4, 0x58, 0xab, 0x0d, 0xb5, 0x56, 0xd1, 0x43, 0xea, 0x79, 0xee, - 0x0b, 0x57, 0x37, 0x49, 0x65, 0x4e, 0xc1, 0x6d, 0xe3, 0xf8, 0x86, 0x25, 0x5f, 0x3c, 0x95, 0x72, 0xe3, 0xfb, 0x8d, - 0xe7, 0xc8, 0x75, 0x00, 0x09, 0x67, 0xf1, 0xf2, 0x01, 0x53, 0x68, 0xeb, 0xa6, 0x3e, 0x0e, 0xe3, 0x94, 0xa9, 0x73, - 0x20, 0x26, 0xc8, 0x17, 0x4e, 0xe2, 0xe7, 0xf7, 0xaf, 0x3f, 0x7c, 0xd0, 0x4d, 0x8c, 0x04, 0x9a, 0xaa, 0xad, 0xf3, - 0x0d, 0xb5, 0x03, 0xfb, 0x37, 0xee, 0x3b, 0xba, 0x61, 0xe8, 0x51, 0x5b, 0xde, 0x73, 0x94, 0x56, 0xdb, 0x72, 0xfc, - 0xe6, 0xe1, 0x3d, 0xd3, 0x4b, 0x74, 0xaf, 0x79, 0x35, 0xe0, 0x86, 0xed, 0xd7, 0x5b, 0x29, 0x65, 0x11, 0x44, 0xd7, - 0x0d, 0xa9, 0xfe, 0x5d, 0x43, 0x2a, 0x3c, 0xe5, 0x6a, 0xb8, 0x6a, 0x15, 0x2f, 0x14, 0xd2, 0x00, 0x02, 0x39, 0xef, - 0x02, 0x97, 0xf2, 0x9e, 0xfa, 0x82, 0x41, 0x73, 0x4f, 0xee, 0xd5, 0x51, 0x37, 0x24, 0xf3, 0x47, 0x90, 0x84, 0xed, - 0x38, 0x04, 0x85, 0x3f, 0xa6, 0x4a, 0xe5, 0xca, 0x64, 0xa3, 0x54, 0xd7, 0x55, 0x1a, 0x21, 0xf2, 0xf6, 0x3a, 0x63, - 0x8b, 0x25, 0x4b, 0xfc, 0x6c, 0x95, 0xb0, 0xeb, 0x30, 0xbe, 0x7d, 0x54, 0xa8, 0xd3, 0xef, 0x28, 0x3c, 0x0f, 0x66, - 0x73, 0x59, 0xfa, 0xac, 0xc5, 0x06, 0x72, 0x01, 0xb7, 0x76, 0x90, 0xff, 0xe7, 0xdf, 0xb6, 0xfd, 0x9f, 0x7f, 0xef, - 0x2c, 0x0a, 0xcd, 0xe7, 0x43, 0x33, 0x1b, 0xec, 0xb1, 0x2f, 0x9a, 0x7b, 0x2a, 0xc3, 0xbc, 0xb9, 0x4c, 0x6d, 0x11, - 0x20, 0xbf, 0xb6, 0x04, 0xb5, 0xc4, 0xf2, 0xbe, 0x79, 0xd0, 0xc0, 0x60, 0x5e, 0x3b, 0x47, 0x06, 0x85, 0xbe, 0x68, - 0x68, 0x43, 0xa3, 0xb7, 0xd7, 0x8a, 0xfc, 0x71, 0x08, 0xef, 0x9a, 0xc3, 0x17, 0x0e, 0x9f, 0xf3, 0x25, 0x5f, 0x0e, - 0x87, 0x32, 0xb6, 0x9c, 0x5a, 0x15, 0x54, 0xfc, 0xcf, 0x6a, 0x29, 0xfc, 0xf2, 0xec, 0x39, 0x06, 0xd9, 0xde, 0x0f, - 0x5e, 0x0e, 0x51, 0x19, 0xed, 0x64, 0x94, 0x14, 0xc4, 0xca, 0x46, 0xd4, 0x46, 0xca, 0xe4, 0xb5, 0x46, 0x6b, 0x78, - 0x0d, 0x52, 0x31, 0xe0, 0x58, 0x3e, 0x34, 0xcc, 0x97, 0x43, 0xce, 0x58, 0xe2, 0xfa, 0xaf, 0xbd, 0xea, 0xd6, 0xe6, - 0x6c, 0xd9, 0x12, 0xd0, 0x4d, 0x8d, 0xe4, 0x3f, 0x58, 0x98, 0x15, 0x7c, 0x3c, 0x64, 0xf0, 0x03, 0x47, 0x61, 0x98, - 0x63, 0xbc, 0x93, 0x77, 0x9b, 0x74, 0xc4, 0x7e, 0xde, 0xad, 0x23, 0x76, 0xb1, 0x97, 0x8e, 0xd8, 0xcf, 0x5f, 0x5d, - 0x47, 0xec, 0x9d, 0xaa, 0x23, 0x06, 0x8b, 0xf8, 0x9a, 0xed, 0xa5, 0xb8, 0x25, 0xb4, 0x36, 0xe2, 0xdb, 0x74, 0xe0, - 0x72, 0x92, 0x36, 0x1d, 0xcf, 0x19, 0xf0, 0x08, 0xf8, 0xaa, 0x84, 0xf1, 0x0c, 0x94, 0xb8, 0xfe, 0x7c, 0x75, 0xab, - 0x30, 0x9e, 0xa9, 0xca, 0x56, 0x11, 0xf7, 0xf8, 0x5a, 0x78, 0x71, 0x22, 0x05, 0x27, 0xc7, 0x14, 0x3e, 0x9f, 0xac, - 0x43, 0x43, 0x89, 0x6a, 0x2d, 0xb5, 0xd7, 0x3c, 0xa1, 0x02, 0xd5, 0x43, 0xed, 0x29, 0x59, 0xd1, 0x7b, 0x2e, 0x7c, - 0x5b, 0xa8, 0x2d, 0x48, 0x2d, 0x61, 0xf2, 0x13, 0xb1, 0xd6, 0x7f, 0xbb, 0x73, 0xbf, 0xbf, 0x74, 0xfb, 0x6d, 0x17, - 0x8c, 0xb3, 0xe1, 0x85, 0x89, 0x09, 0x4e, 0xbf, 0xdd, 0x86, 0x84, 0x5b, 0x25, 0xc1, 0x83, 0x84, 0x40, 0x49, 0xe8, - 0x40, 0xc2, 0x58, 0x49, 0x38, 0x82, 0x84, 0x89, 0x92, 0x70, 0x0c, 0x09, 0x37, 0x7a, 0x7e, 0x19, 0xc9, 0xe1, 0x1e, - 0x1b, 0x57, 0x26, 0x3d, 0x2a, 0x44, 0xda, 0xb1, 0xe9, 0x82, 0xd6, 0x94, 0x3f, 0xeb, 0xc5, 0x26, 0x71, 0x17, 0x7b, - 0x89, 0x79, 0x3b, 0x67, 0xe4, 0x28, 0xfa, 0x15, 0xde, 0x39, 0x76, 0x16, 0x83, 0xde, 0xb4, 0x70, 0xc0, 0x20, 0xe0, - 0xa0, 0xe9, 0x06, 0x30, 0x8c, 0xfa, 0x72, 0xe5, 0x84, 0x13, 0x0b, 0x65, 0x2d, 0x8b, 0x3c, 0xea, 0xce, 0x92, 0x5b, - 0xa0, 0xd0, 0x38, 0x69, 0xa9, 0x5c, 0xc9, 0xaf, 0xa1, 0x77, 0xf0, 0x8a, 0x8d, 0x56, 0x33, 0xed, 0x3c, 0x9e, 0xed, - 0x54, 0x21, 0x50, 0xb3, 0x60, 0x94, 0x3a, 0x89, 0x5f, 0x2c, 0xb1, 0x2d, 0x79, 0x5f, 0xf4, 0x99, 0x97, 0xcb, 0x67, - 0x30, 0x36, 0x2d, 0x23, 0x05, 0x16, 0xe8, 0x07, 0x60, 0xa4, 0xc8, 0xf0, 0xcf, 0x01, 0xce, 0xca, 0xf7, 0x85, 0xaf, - 0x8c, 0xe7, 0xf4, 0x47, 0x96, 0xa6, 0xfe, 0x4c, 0x94, 0xaf, 0x8f, 0x13, 0x94, 0x76, 0xe4, 0xfb, 0x0b, 0x01, 0x08, - 0x9c, 0xbc, 0xa0, 0xa6, 0x9b, 0x91, 0xc4, 0xb7, 0x1a, 0x68, 0xff, 0xc0, 0x86, 0x2a, 0xf4, 0x14, 0x02, 0x1b, 0x96, - 0xb0, 0xac, 0x51, 0x00, 0x87, 0xff, 0x86, 0x85, 0xd5, 0xc4, 0xcc, 0x9f, 0x55, 0x93, 0x68, 0x1f, 0xe4, 0xea, 0xd8, - 0xa4, 0x40, 0xbf, 0x94, 0xf8, 0x25, 0x12, 0xea, 0x30, 0x9e, 0xfd, 0xa9, 0xe2, 0xe9, 0x2d, 0x6a, 0x05, 0x1f, 0x22, - 0x33, 0xc8, 0x86, 0x36, 0xc2, 0x58, 0xb3, 0x01, 0x84, 0xbd, 0x28, 0x9b, 0x5b, 0x68, 0x5a, 0xd6, 0xf2, 0x22, 0xc3, - 0xb4, 0x71, 0x6d, 0xd7, 0x55, 0x83, 0xda, 0x5e, 0x32, 0x1b, 0xf9, 0x2d, 0xd7, 0x3b, 0x36, 0xc5, 0x1f, 0xdb, 0xe9, - 0x18, 0x39, 0xb6, 0xa0, 0x4d, 0x82, 0x9b, 0xf5, 0x34, 0x8e, 0x32, 0x6b, 0xea, 0x2f, 0x82, 0xf0, 0xbe, 0xb7, 0x88, - 0xa3, 0x38, 0x5d, 0xfa, 0x63, 0xd6, 0x2f, 0x1e, 0xd4, 0x7d, 0x74, 0xd5, 0xc0, 0xad, 0x05, 0x5d, 0xdb, 0x4b, 0xd8, - 0x82, 0x6a, 0x4b, 0x4f, 0x0c, 0xd3, 0x90, 0xdd, 0xe5, 0xbc, 0xfb, 0x52, 0x61, 0x2a, 0x8a, 0x5b, 0x8e, 0x6a, 0x00, - 0x45, 0xca, 0xdd, 0x3c, 0x80, 0x73, 0xa3, 0xfe, 0xd2, 0x9f, 0xa0, 0x67, 0x42, 0xdb, 0xeb, 0x24, 0x6c, 0xa1, 0xd9, - 0x9d, 0x8d, 0x8d, 0x27, 0xf1, 0xed, 0x29, 0x8c, 0x16, 0x2b, 0x5b, 0x29, 0x0b, 0xa7, 0x98, 0x63, 0xa1, 0x65, 0x89, - 0x68, 0xc7, 0xc2, 0x87, 0x38, 0xb4, 0xc6, 0x16, 0x7d, 0xc8, 0xee, 0x79, 0x9a, 0xd3, 0x5f, 0x04, 0x91, 0x45, 0xd3, - 0x39, 0x76, 0x96, 0x4a, 0x5b, 0x2a, 0xfc, 0x8c, 0x35, 0x16, 0x77, 0x35, 0xa7, 0x0f, 0x8f, 0xb5, 0x69, 0x18, 0xdf, - 0xf6, 0xe6, 0xc1, 0x64, 0xc2, 0xa2, 0x3e, 0x8e, 0x59, 0x26, 0xb2, 0x30, 0x0c, 0x96, 0x69, 0x90, 0xf6, 0x17, 0xfe, - 0x1d, 0x6f, 0xf5, 0x70, 0x53, 0xab, 0x6d, 0xde, 0x6a, 0x7b, 0xef, 0x56, 0x95, 0x66, 0xc0, 0x8a, 0x85, 0xda, 0xe1, - 0x43, 0xeb, 0x68, 0x4e, 0x65, 0x9e, 0x7b, 0xb7, 0xba, 0x4c, 0xd8, 0x7a, 0xe1, 0x27, 0xb3, 0x20, 0xea, 0x39, 0xb9, - 0x7d, 0xb3, 0xa6, 0x8d, 0xf1, 0xb8, 0xdb, 0xed, 0xe6, 0xf6, 0x44, 0x7c, 0x39, 0x93, 0x49, 0x6e, 0x8f, 0xc5, 0xd7, - 0x74, 0xea, 0x38, 0xd3, 0x69, 0x6e, 0x07, 0x22, 0xa1, 0xed, 0x8d, 0x27, 0x6d, 0x2f, 0xb7, 0x6f, 0x95, 0x12, 0xb9, - 0xcd, 0xf8, 0x57, 0xc2, 0x26, 0x7d, 0xdc, 0x48, 0xa4, 0x56, 0xda, 0x3b, 0x76, 0x9c, 0x1c, 0x31, 0xc0, 0x65, 0x09, - 0x37, 0x21, 0xaf, 0xe7, 0x6a, 0xbd, 0x77, 0x49, 0xad, 0xe8, 0x6e, 0x3c, 0x6e, 0x2c, 0x37, 0xf1, 0x93, 0x4f, 0x57, - 0x9a, 0x32, 0x0b, 0xdf, 0xa7, 0x62, 0x6b, 0x01, 0x06, 0xeb, 0xae, 0x07, 0x2e, 0xbb, 0xfa, 0xa3, 0x38, 0x81, 0x33, - 0x9b, 0xf8, 0x93, 0x60, 0x95, 0xf6, 0x5c, 0x6f, 0x79, 0x27, 0x92, 0xf8, 0x5e, 0x2f, 0x12, 0xf0, 0xec, 0xf5, 0xd2, - 0x38, 0x0c, 0x26, 0x22, 0x69, 0xd3, 0x59, 0x72, 0x3d, 0xa3, 0x8f, 0x06, 0xeb, 0x01, 0xba, 0x5d, 0xf0, 0xc3, 0x50, - 0xb3, 0xdb, 0xa9, 0xc6, 0xfc, 0x14, 0xf9, 0xcb, 0x9a, 0x93, 0x12, 0x5c, 0xd0, 0x38, 0xdd, 0x3d, 0x5c, 0xde, 0xc9, - 0x3d, 0xef, 0x1e, 0x2d, 0xef, 0xf2, 0xbf, 0x2e, 0xd8, 0x24, 0xf0, 0xb5, 0x56, 0xb1, 0x9b, 0x5c, 0x07, 0x78, 0xd0, - 0xc6, 0x7a, 0xc3, 0x36, 0x15, 0xc7, 0x02, 0x5c, 0x1b, 0x3e, 0x0a, 0x16, 0xcb, 0x38, 0xc9, 0xfc, 0x28, 0xcb, 0xf3, - 0xe1, 0x55, 0x9e, 0xf7, 0x2f, 0x82, 0xd6, 0xe5, 0x3f, 0x5a, 0x74, 0x4f, 0x93, 0xcc, 0x26, 0x37, 0xae, 0xcc, 0xd7, - 0x4c, 0xd5, 0x19, 0x81, 0x6b, 0x0c, 0xf5, 0x45, 0xd4, 0xc2, 0x74, 0x4b, 0xd6, 0x0b, 0x13, 0x90, 0x65, 0x71, 0xd2, - 0x41, 0x29, 0x17, 0xc1, 0x1b, 0x08, 0x0a, 0xbc, 0x66, 0x83, 0x0b, 0x45, 0xff, 0x04, 0x88, 0x15, 0x2c, 0x4c, 0x76, - 0x05, 0x4f, 0x36, 0xd1, 0x8c, 0xdf, 0xed, 0xa6, 0x19, 0x7f, 0xcd, 0xf6, 0xa1, 0x19, 0xbf, 0xfb, 0xea, 0x34, 0xe3, - 0x93, 0xba, 0x5d, 0xc1, 0xdb, 0x78, 0xa0, 0x4b, 0x09, 0x03, 0x5c, 0x4d, 0x09, 0x79, 0xec, 0x79, 0xfb, 0x87, 0xcd, - 0x00, 0x44, 0x6b, 0x14, 0x83, 0x8e, 0x6e, 0x6e, 0xe0, 0xc7, 0xbe, 0x8b, 0x06, 0x7f, 0x4f, 0xd4, 0xef, 0xe9, 0x74, - 0xf0, 0x2a, 0x56, 0x12, 0xe4, 0x17, 0x57, 0xbe, 0x28, 0x79, 0x57, 0xa0, 0x1c, 0xa1, 0x85, 0x89, 0xf1, 0x27, 0xc0, - 0x38, 0x9b, 0xb4, 0x8e, 0x27, 0x52, 0xfb, 0xac, 0x5f, 0x1e, 0x42, 0x4b, 0xaa, 0x7c, 0x0a, 0x13, 0x9c, 0x1a, 0x2b, - 0x71, 0xc6, 0x32, 0x6e, 0x33, 0xfb, 0xfd, 0xfd, 0xdb, 0x49, 0xeb, 0x6d, 0x6c, 0xe4, 0x41, 0xfa, 0xae, 0x6a, 0x00, - 0xc3, 0x65, 0x3f, 0x03, 0x75, 0x3a, 0x39, 0xd7, 0x20, 0x53, 0x03, 0x4c, 0x43, 0x36, 0x55, 0x3f, 0x2b, 0xcd, 0xb4, - 0xa7, 0x56, 0xe4, 0x81, 0xae, 0x6a, 0x97, 0x31, 0xb7, 0x3e, 0x58, 0x73, 0x0a, 0x10, 0x63, 0x77, 0xa1, 0xdd, 0xf0, - 0x84, 0xaa, 0x07, 0x93, 0x3c, 0x37, 0xfa, 0x02, 0x10, 0xca, 0x45, 0xcb, 0x76, 0x11, 0x71, 0xe9, 0xad, 0xd4, 0x69, - 0xe0, 0x12, 0x42, 0x12, 0xff, 0xbd, 0x05, 0x81, 0x3a, 0x17, 0x16, 0x72, 0x98, 0xe9, 0x1a, 0x81, 0x8f, 0x14, 0x2d, - 0x94, 0x09, 0x81, 0x04, 0x58, 0xc2, 0x5f, 0x64, 0x89, 0x84, 0xba, 0x0e, 0x27, 0x01, 0x07, 0x35, 0x02, 0xc0, 0xca, - 0x5f, 0xf0, 0xb5, 0x09, 0xed, 0xf0, 0x32, 0xf8, 0x91, 0xeb, 0x92, 0xf6, 0xc3, 0xed, 0x77, 0x7a, 0x72, 0x00, 0x15, - 0x4e, 0x2b, 0x8a, 0x03, 0x3b, 0x34, 0x14, 0x81, 0x94, 0x48, 0x6f, 0x4d, 0x3b, 0xbd, 0xd5, 0x9e, 0xad, 0x85, 0x87, - 0x8c, 0xcc, 0x5f, 0x5a, 0xf0, 0xc4, 0x47, 0xdc, 0xcb, 0x31, 0x9e, 0xe2, 0x8c, 0xa3, 0xbf, 0x4a, 0x01, 0x37, 0xe2, - 0x43, 0x15, 0xf1, 0x4f, 0x7f, 0xbc, 0x4a, 0xd2, 0x38, 0xe9, 0x2d, 0xe3, 0x20, 0xca, 0x58, 0x92, 0x23, 0xa8, 0x2e, - 0x11, 0x3e, 0x02, 0x3c, 0x57, 0xeb, 0x78, 0xe9, 0x8f, 0x83, 0xec, 0xbe, 0xe7, 0x70, 0x92, 0xc2, 0xe9, 0x73, 0xea, - 0xc0, 0x69, 0x2c, 0xdf, 0xe3, 0xd0, 0x7c, 0x8e, 0x84, 0x5f, 0x52, 0x27, 0x67, 0xd4, 0x6d, 0xde, 0x57, 0x72, 0xc9, - 0x47, 0x08, 0x90, 0x1f, 0x7e, 0x62, 0xcd, 0x00, 0xcb, 0xc3, 0x52, 0x3b, 0x13, 0x36, 0x33, 0x11, 0x6b, 0x03, 0x5f, - 0x5e, 0xfc, 0xb1, 0x3b, 0x86, 0xe6, 0x34, 0x27, 0x03, 0xc5, 0x63, 0xec, 0x33, 0xb2, 0x9e, 0x0f, 0x11, 0xb5, 0xcc, - 0x7d, 0x4a, 0x8e, 0xd8, 0x34, 0x4e, 0x18, 0xf9, 0x93, 0x75, 0xbb, 0xcb, 0xbb, 0xfd, 0x9b, 0xdf, 0x3e, 0xfd, 0xe6, - 0x76, 0xa2, 0x38, 0x6b, 0x89, 0xc6, 0x8c, 0x1d, 0xad, 0xd5, 0xef, 0x33, 0x20, 0x0d, 0x09, 0xf2, 0x63, 0x72, 0xdd, - 0xd5, 0xd3, 0xf5, 0x7e, 0xa3, 0xdb, 0xae, 0x65, 0xcc, 0xef, 0xbc, 0x84, 0x85, 0x7e, 0x16, 0xdc, 0x08, 0x9a, 0xb1, - 0x7d, 0xb4, 0xbc, 0x13, 0x6b, 0x8c, 0x17, 0xde, 0x03, 0x16, 0xa9, 0x32, 0x14, 0xb1, 0x48, 0xd5, 0x64, 0x5c, 0xa4, - 0x7e, 0x6d, 0x36, 0xc2, 0x93, 0x45, 0xe5, 0xa6, 0xef, 0x2c, 0xef, 0xd4, 0x2b, 0xba, 0xa8, 0x26, 0x6f, 0xea, 0xaa, - 0x0b, 0xb2, 0x45, 0x30, 0x99, 0x84, 0x2c, 0x2f, 0x2d, 0x74, 0x79, 0x2d, 0x15, 0xe0, 0x48, 0x38, 0xf8, 0xa3, 0x34, - 0x0e, 0x57, 0x19, 0x6b, 0x06, 0x17, 0x01, 0xc7, 0x73, 0x0a, 0xe0, 0xe0, 0xef, 0xf2, 0x58, 0x3b, 0x40, 0x6e, 0xc3, - 0x36, 0x71, 0xfa, 0xe0, 0x71, 0xd8, 0x6a, 0x97, 0x87, 0x0e, 0x59, 0x72, 0xd0, 0x66, 0xc3, 0x44, 0x4c, 0xb8, 0x96, - 0x08, 0x7b, 0x6b, 0xb6, 0xcb, 0xd3, 0xa4, 0xd7, 0x55, 0x99, 0x94, 0x97, 0x27, 0xf3, 0xe7, 0x9c, 0xb1, 0x17, 0xcd, - 0x67, 0xec, 0x85, 0x38, 0x63, 0xdb, 0x77, 0xe6, 0xe3, 0xa9, 0x0b, 0xff, 0xf5, 0x8b, 0x09, 0xf5, 0x1c, 0xad, 0xbd, - 0xbc, 0xd3, 0xdc, 0xe5, 0x9d, 0x66, 0x79, 0xcb, 0x3b, 0x0d, 0x9b, 0x46, 0x7d, 0x10, 0xd3, 0xf6, 0x0c, 0xd3, 0xd1, - 0x20, 0x11, 0xfe, 0x38, 0xa5, 0x2c, 0xf7, 0x10, 0xf2, 0xa0, 0x56, 0xa7, 0x9e, 0xe7, 0x6d, 0x3f, 0xea, 0x74, 0x96, - 0x04, 0xd2, 0x36, 0xec, 0xcc, 0x1f, 0x8d, 0xd8, 0xa4, 0x37, 0x8d, 0xc7, 0xab, 0xf4, 0x5f, 0x7c, 0xfc, 0x1c, 0x88, - 0x5b, 0x11, 0x41, 0xa5, 0x1d, 0x51, 0x15, 0x04, 0x25, 0x37, 0x4c, 0xb4, 0xb0, 0x96, 0xeb, 0xd4, 0x23, 0xf7, 0xc8, - 0x9e, 0x7d, 0xd8, 0xb0, 0xc9, 0x9b, 0x01, 0xfd, 0xa7, 0xad, 0xd2, 0x66, 0x14, 0xf3, 0x05, 0x60, 0xd9, 0x0a, 0x8e, - 0x87, 0x43, 0x83, 0xaf, 0xa6, 0xd3, 0x6d, 0x1e, 0xee, 0xa5, 0xe8, 0xe9, 0x4a, 0x5c, 0x2a, 0xfc, 0xde, 0xe2, 0x86, - 0x29, 0xdb, 0x5b, 0xdd, 0xb4, 0x47, 0x6a, 0xad, 0x6e, 0xb9, 0x10, 0x8a, 0xb2, 0x7b, 0x62, 0xf9, 0xc7, 0x2f, 0x0e, - 0xe1, 0x3f, 0xa2, 0xea, 0x7f, 0xcd, 0x9a, 0x08, 0xf5, 0xb7, 0x65, 0x4d, 0x70, 0x22, 0x95, 0x90, 0x10, 0xdf, 0xbf, - 0xfc, 0x74, 0xfa, 0xb0, 0x0a, 0x7b, 0x97, 0x26, 0x55, 0xaa, 0x6a, 0xe9, 0xef, 0xe3, 0x18, 0x42, 0x77, 0xd6, 0x8b, - 0x0b, 0xf0, 0x90, 0xb2, 0x7b, 0x36, 0x80, 0x4a, 0xe2, 0x1d, 0x41, 0x52, 0x7c, 0x1d, 0xeb, 0xd0, 0x53, 0xe2, 0xf5, - 0xa6, 0xa7, 0xc4, 0xab, 0xdd, 0x4f, 0x89, 0x1f, 0xf6, 0x7a, 0x4a, 0xbc, 0xfa, 0xea, 0x4f, 0x89, 0xd7, 0xf5, 0xa7, - 0xc4, 0x45, 0x2c, 0xf4, 0x67, 0xcd, 0xb7, 0x2b, 0xfe, 0xf3, 0x23, 0x09, 0xe5, 0xce, 0xe3, 0x41, 0xc7, 0x21, 0x97, - 0xc7, 0x17, 0x7f, 0xf8, 0x61, 0x81, 0x1b, 0xf1, 0x3d, 0xaa, 0x93, 0x15, 0x4f, 0x0b, 0x8e, 0xd9, 0xb1, 0x1f, 0x25, - 0x39, 0x8c, 0xa3, 0xd9, 0xcf, 0x20, 0x94, 0x05, 0x76, 0x60, 0xa2, 0x64, 0x04, 0xe9, 0xcf, 0xf1, 0x72, 0xb5, 0x7c, - 0x0b, 0x6d, 0x7d, 0x0c, 0xd2, 0x60, 0x14, 0x32, 0x69, 0x89, 0x4c, 0xea, 0x6f, 0x9c, 0x27, 0x0e, 0x1a, 0xa7, 0xe2, - 0xa7, 0x7f, 0x27, 0x7e, 0xa2, 0x4e, 0x2a, 0xff, 0x4d, 0x7a, 0x75, 0x7a, 0xf3, 0x43, 0x44, 0x08, 0x01, 0x95, 0x41, - 0x3f, 0xfc, 0x31, 0x72, 0x11, 0x1b, 0x0d, 0xb3, 0x14, 0xfa, 0x0e, 0x1b, 0xdb, 0x61, 0xb5, 0x47, 0xcd, 0xca, 0x30, - 0xa5, 0x0b, 0xae, 0x3a, 0x1b, 0x7e, 0x11, 0xaf, 0x52, 0x36, 0x89, 0x6f, 0x23, 0xdd, 0x8c, 0xa4, 0x91, 0x01, 0x48, - 0x38, 0x65, 0x1d, 0x0c, 0x1e, 0xf9, 0x01, 0x09, 0xe5, 0x38, 0x69, 0xe9, 0x10, 0xbb, 0x74, 0xb5, 0xb4, 0x48, 0xd4, - 0x6c, 0xe1, 0x14, 0x75, 0x19, 0xe5, 0xe8, 0x51, 0xab, 0x15, 0x0f, 0x1e, 0x56, 0x53, 0xa8, 0x6a, 0xc4, 0x36, 0xe7, - 0x0a, 0xa7, 0xad, 0x48, 0x30, 0x17, 0x85, 0x1f, 0x8c, 0x86, 0x85, 0xe3, 0x39, 0x64, 0xba, 0x5a, 0xe4, 0x82, 0x17, - 0x91, 0x7c, 0xc5, 0xd7, 0x83, 0x7b, 0x85, 0xa0, 0xcf, 0x97, 0x0a, 0x18, 0xdf, 0xdd, 0xb0, 0x24, 0xf4, 0xef, 0x5b, - 0x46, 0x1e, 0x47, 0x3f, 0x02, 0x00, 0x5e, 0xc5, 0xb7, 0x91, 0x5a, 0x00, 0x83, 0xb5, 0x34, 0xec, 0xa5, 0x46, 0xff, - 0x25, 0x60, 0xb8, 0xa2, 0x8c, 0x00, 0xc2, 0xe4, 0xce, 0xd8, 0xdf, 0x4d, 0xfa, 0xf7, 0x1f, 0x46, 0x6e, 0x9e, 0xc7, - 0xb2, 0xa3, 0x5f, 0x96, 0x7b, 0x74, 0xf3, 0xf4, 0xe9, 0xa3, 0xcd, 0xd3, 0x2e, 0x87, 0x67, 0x6f, 0xa8, 0x6d, 0x6c, - 0x3c, 0x05, 0x30, 0x8a, 0x8b, 0x78, 0x35, 0x9e, 0xa3, 0xa2, 0xeb, 0xd7, 0x9b, 0x6f, 0x06, 0x6d, 0x62, 0x94, 0x52, - 0x39, 0xf5, 0x4a, 0x52, 0x01, 0x05, 0xec, 0xff, 0x35, 0x38, 0xe0, 0xfc, 0x1f, 0x82, 0xa1, 0xbe, 0x6b, 0xf8, 0x2b, - 0x3e, 0x78, 0xd8, 0xe6, 0xed, 0x43, 0x30, 0x4d, 0xee, 0xda, 0x42, 0x08, 0xd7, 0x9a, 0x91, 0x4c, 0x5e, 0x05, 0x9a, - 0xea, 0x46, 0x6e, 0x93, 0x87, 0x3c, 0xd1, 0x0b, 0xb3, 0xe9, 0x99, 0xce, 0x0d, 0x0d, 0x4c, 0xc6, 0xb1, 0x55, 0x05, - 0xc9, 0x70, 0x95, 0x07, 0x86, 0xe8, 0xab, 0x9a, 0xb7, 0x08, 0x22, 0x13, 0xbd, 0xc0, 0xd7, 0x73, 0xfc, 0x3b, 0xf0, - 0x83, 0x0c, 0xc8, 0xad, 0x9a, 0x05, 0x89, 0xa6, 0x6a, 0x37, 0x07, 0xa1, 0x9e, 0xf4, 0x46, 0x48, 0x08, 0x29, 0xde, - 0xf0, 0x1b, 0x4d, 0xd3, 0x34, 0xf9, 0x8c, 0xd0, 0xe4, 0x3b, 0x02, 0xd3, 0xf1, 0x39, 0x00, 0xd2, 0x92, 0x7c, 0x79, - 0x47, 0x29, 0xf0, 0x32, 0x40, 0x99, 0xac, 0x48, 0xe0, 0xae, 0xfe, 0x3a, 0x8e, 0x48, 0x10, 0x0f, 0x7a, 0x70, 0xd3, - 0xe6, 0x27, 0xe0, 0x11, 0xb8, 0xa7, 0xe1, 0x83, 0x1d, 0x73, 0x39, 0x27, 0x58, 0x73, 0xe8, 0x73, 0xd8, 0x67, 0xcd, - 0x3e, 0xe1, 0x22, 0x05, 0x0b, 0x82, 0xd4, 0xa1, 0xe2, 0xe2, 0xd9, 0x64, 0x0d, 0xb8, 0x11, 0xdf, 0x45, 0x77, 0xd9, - 0x82, 0x45, 0x2b, 0x1d, 0x63, 0x42, 0xa1, 0x8f, 0x3e, 0x28, 0xf3, 0x8a, 0x88, 0x2d, 0xc0, 0x36, 0xcd, 0x35, 0xe7, - 0x74, 0x17, 0xa6, 0x1c, 0xa5, 0xfa, 0xe6, 0x98, 0x0b, 0x36, 0x53, 0x8e, 0xdb, 0xaa, 0x37, 0x04, 0x5f, 0xd2, 0xb8, - 0x6a, 0xc8, 0x45, 0x9a, 0xd0, 0xd0, 0x06, 0x79, 0xc7, 0xe0, 0xec, 0x22, 0x01, 0xf6, 0x96, 0x5f, 0x5d, 0x34, 0x29, - 0x91, 0xf1, 0x2b, 0x8c, 0xa2, 0xc4, 0xa8, 0x37, 0xc3, 0xc7, 0x09, 0x8e, 0x89, 0x36, 0xb6, 0x33, 0xae, 0xb5, 0xb3, - 0x61, 0xd2, 0x9f, 0xd8, 0x3d, 0x5d, 0x24, 0x04, 0xaa, 0x4f, 0xec, 0x1e, 0x74, 0xff, 0x5e, 0x03, 0x37, 0x45, 0xdf, - 0x82, 0xae, 0x4d, 0x70, 0xf5, 0x3f, 0x06, 0x67, 0x55, 0x5b, 0x0e, 0x90, 0x93, 0x6f, 0xc1, 0xe2, 0x08, 0x62, 0x88, - 0xea, 0x2c, 0x0e, 0x31, 0x57, 0xf1, 0x6f, 0x35, 0xc2, 0xd8, 0x6a, 0x38, 0x1a, 0xc6, 0x33, 0xd7, 0x71, 0x0e, 0x6a, - 0xe5, 0x81, 0x91, 0xdd, 0x54, 0xda, 0x30, 0xb3, 0x81, 0xeb, 0x58, 0xc1, 0x33, 0xdb, 0xeb, 0xd7, 0xee, 0x68, 0xc5, - 0x97, 0xe4, 0x10, 0xd9, 0x5f, 0xa7, 0x4f, 0xd6, 0xad, 0xda, 0x81, 0x34, 0xaa, 0x2a, 0xf3, 0x38, 0xb6, 0x9c, 0xf3, - 0xbf, 0x86, 0xf5, 0xab, 0x9f, 0x3c, 0x59, 0x52, 0x5c, 0x93, 0x21, 0x78, 0x43, 0x6e, 0xc1, 0x31, 0xfa, 0x8b, 0xf6, - 0x5c, 0x6b, 0xd1, 0xf1, 0x31, 0x8c, 0xa1, 0x0c, 0x97, 0x2d, 0x6c, 0xca, 0xd4, 0x06, 0x2a, 0x3d, 0xa6, 0x55, 0x0c, - 0xc7, 0xfd, 0xae, 0xb2, 0x42, 0xa2, 0xb7, 0x95, 0x5a, 0xc0, 0xf6, 0x37, 0x5c, 0x9f, 0xf6, 0x08, 0xfc, 0x12, 0x40, - 0x09, 0xf0, 0x9d, 0xbe, 0xb3, 0xc1, 0xd5, 0xb2, 0xdc, 0x5c, 0xf9, 0x92, 0xdc, 0xbf, 0x31, 0xbc, 0x74, 0x50, 0x86, - 0x26, 0xdb, 0x6b, 0xbe, 0xee, 0x1e, 0xd8, 0x24, 0x8b, 0x26, 0xe5, 0x06, 0x2b, 0xf7, 0xd7, 0xfe, 0xcd, 0x95, 0x30, - 0x0a, 0x04, 0x15, 0x88, 0x1b, 0x30, 0x4a, 0x1e, 0x47, 0xb8, 0xf9, 0xe9, 0xb8, 0x05, 0x7b, 0x51, 0x31, 0x58, 0x81, - 0x3c, 0x82, 0xc9, 0x6a, 0x0a, 0x53, 0x1c, 0x3c, 0x57, 0xa3, 0x59, 0x70, 0x4b, 0x10, 0xa2, 0x1b, 0x77, 0x62, 0x26, - 0x74, 0x0a, 0x8b, 0x3a, 0x01, 0xf7, 0x45, 0xb9, 0x2f, 0xd7, 0x3a, 0xd8, 0xcd, 0xb5, 0xce, 0x76, 0x71, 0xad, 0xc9, - 0x9c, 0xea, 0x36, 0xf1, 0x97, 0x8a, 0x45, 0x9e, 0x20, 0xce, 0x55, 0xc3, 0xbc, 0x12, 0xab, 0x1b, 0xad, 0xaf, 0x44, - 0xad, 0x5a, 0x6b, 0xa4, 0x25, 0x88, 0xec, 0x6f, 0xe5, 0x81, 0x22, 0x04, 0xea, 0x2a, 0x6f, 0xfc, 0xa2, 0xe0, 0x8d, - 0xd3, 0xab, 0xa6, 0x30, 0xa4, 0x11, 0xd4, 0xbf, 0x62, 0xa4, 0x26, 0x5f, 0x07, 0x85, 0xb1, 0x5a, 0x31, 0x52, 0xc5, - 0xfc, 0xaa, 0x78, 0x68, 0x28, 0x46, 0x7d, 0xe2, 0x95, 0x51, 0xb6, 0xed, 0x2b, 0x17, 0x2d, 0xac, 0xaf, 0x8a, 0x74, - 0xe0, 0xba, 0xe3, 0x90, 0x65, 0xb2, 0xba, 0x6d, 0xca, 0xe6, 0x37, 0x6a, 0xb6, 0xb2, 0x49, 0xa4, 0x9d, 0x0c, 0x01, - 0x58, 0xb0, 0xe9, 0x2b, 0x72, 0x6d, 0xa9, 0x03, 0x81, 0x83, 0x6c, 0x30, 0xeb, 0xdb, 0xcd, 0x9d, 0xa7, 0x78, 0x09, - 0x85, 0x14, 0x5e, 0xe5, 0x41, 0x20, 0x7c, 0xaf, 0xd6, 0x0d, 0xb7, 0x3c, 0x5e, 0xf2, 0xfc, 0x7e, 0x07, 0xf6, 0xa2, - 0xe6, 0xa8, 0x82, 0x7c, 0x3c, 0x99, 0x16, 0xa9, 0xe7, 0x62, 0xd1, 0x7a, 0xa3, 0xc4, 0xc4, 0x59, 0x73, 0xcb, 0x98, - 0x32, 0x8f, 0x9e, 0x97, 0xe8, 0x89, 0x7e, 0xf9, 0xd6, 0x49, 0x56, 0x11, 0xfa, 0xb6, 0xb7, 0xb2, 0xc4, 0x1f, 0x7f, - 0x52, 0x86, 0x2c, 0xf8, 0x9c, 0xc0, 0x03, 0x2e, 0x4b, 0x0a, 0xfa, 0x3e, 0xba, 0x82, 0x64, 0x3d, 0xdb, 0x4b, 0x15, - 0xee, 0x4b, 0xef, 0xb1, 0xd3, 0xf6, 0x5f, 0x4c, 0x0f, 0x2b, 0x4c, 0x51, 0xaf, 0x53, 0x66, 0x99, 0x6f, 0x18, 0x47, - 0x36, 0x5f, 0x2d, 0x46, 0x6b, 0x95, 0xb7, 0xaa, 0xb0, 0x5c, 0xeb, 0x6c, 0x56, 0xb5, 0xdb, 0xe9, 0x74, 0x5a, 0x66, - 0x34, 0x3a, 0xda, 0x21, 0x32, 0x0b, 0x1f, 0x3b, 0x8e, 0x53, 0x1d, 0xfb, 0x76, 0xb0, 0x5b, 0xc8, 0xb7, 0xed, 0x36, - 0x8e, 0x18, 0x61, 0xbb, 0x0b, 0x7e, 0x75, 0x70, 0xe4, 0x76, 0x71, 0xb2, 0x4b, 0x6a, 0x11, 0x7d, 0x52, 0x86, 0x08, - 0x32, 0xb6, 0x48, 0x7b, 0x63, 0x86, 0x32, 0x18, 0x5b, 0x39, 0xd0, 0xa8, 0x38, 0x60, 0xcd, 0x40, 0x55, 0xc4, 0x15, - 0xbb, 0xc2, 0xd1, 0x90, 0x1f, 0x5e, 0x63, 0xde, 0x8b, 0x4e, 0xf0, 0xa0, 0xac, 0xeb, 0x3c, 0x6d, 0x9c, 0x56, 0xc7, - 0xf9, 0x4b, 0xa9, 0x9c, 0x06, 0x17, 0xe0, 0x5a, 0x08, 0xb4, 0x89, 0x3f, 0x8b, 0x7f, 0x4b, 0xfe, 0xff, 0x8b, 0xe5, - 0x5d, 0x59, 0x7f, 0xa4, 0x0b, 0x1c, 0xed, 0xe2, 0xb4, 0xd0, 0xa8, 0x9b, 0xf6, 0x80, 0xd4, 0x32, 0x98, 0xaa, 0x02, - 0x74, 0x10, 0xd2, 0x97, 0x02, 0x80, 0x34, 0xb0, 0xdf, 0x91, 0x62, 0x86, 0x25, 0x2e, 0x58, 0x88, 0x45, 0xf8, 0x3a, - 0x98, 0x83, 0xf9, 0xbc, 0x8b, 0xf2, 0x83, 0xd2, 0x9e, 0x00, 0x69, 0x7c, 0x6d, 0x6e, 0x7b, 0xb1, 0xfb, 0xab, 0x72, - 0x2d, 0xd1, 0x30, 0x80, 0xcc, 0x85, 0x43, 0x88, 0x8a, 0x04, 0x5a, 0x65, 0x73, 0xd3, 0x28, 0x65, 0xae, 0x2a, 0x67, - 0x13, 0x03, 0xc3, 0xe6, 0x9a, 0x8b, 0x50, 0xdb, 0x42, 0x5a, 0x00, 0x93, 0xe5, 0xdb, 0x0f, 0xbf, 0x2d, 0x58, 0x62, - 0x75, 0x3f, 0xba, 0xb8, 0xe4, 0xb8, 0x7f, 0x2d, 0xbc, 0x3b, 0x53, 0x3a, 0xff, 0xc8, 0x5f, 0xfc, 0xa1, 0x91, 0xa1, - 0x77, 0x51, 0xe2, 0xd0, 0x71, 0x6d, 0x71, 0xcf, 0xd8, 0xab, 0xf4, 0x22, 0x88, 0xf6, 0x2f, 0xeb, 0xdf, 0xed, 0x5d, - 0x16, 0x2e, 0x8c, 0xbd, 0x0b, 0xc3, 0x8d, 0x43, 0x9a, 0x0b, 0xd9, 0xe0, 0x07, 0x85, 0xa1, 0xa8, 0x5a, 0x1d, 0xeb, - 0x58, 0x8b, 0xa8, 0xfc, 0x8b, 0xd5, 0x60, 0x78, 0x72, 0x76, 0xb7, 0x08, 0xb5, 0x1b, 0x96, 0x40, 0x68, 0x9f, 0x81, - 0xee, 0xda, 0x8e, 0xae, 0xa1, 0x0d, 0x6d, 0x10, 0xcd, 0x06, 0xfa, 0x2f, 0x17, 0x6f, 0xac, 0xae, 0x7e, 0x06, 0x22, - 0xda, 0x9b, 0x19, 0x5e, 0x7b, 0xe7, 0xfe, 0x3d, 0x4b, 0xae, 0x3d, 0x5d, 0xc3, 0x08, 0x3e, 0x74, 0xe1, 0x61, 0x9a, - 0xe6, 0xe9, 0x7b, 0x04, 0x8a, 0xd0, 0x44, 0xac, 0x37, 0x1d, 0x50, 0x8e, 0xeb, 0x75, 0x35, 0xd7, 0x3b, 0xb4, 0x8f, - 0xba, 0xfa, 0xe9, 0x37, 0x9a, 0x76, 0x32, 0x61, 0xd3, 0xf4, 0x14, 0x9f, 0x68, 0x27, 0x78, 0x47, 0xd0, 0x6f, 0x4d, - 0xb3, 0xc7, 0x61, 0x6a, 0xb9, 0xda, 0x9a, 0x7f, 0x6a, 0xda, 0x34, 0x08, 0xc3, 0x9e, 0xf6, 0x78, 0xea, 0x4d, 0x0f, - 0xa7, 0x2f, 0xfa, 0x3c, 0x39, 0xff, 0xa6, 0x54, 0xdc, 0xa4, 0x7f, 0x3d, 0xa5, 0x5a, 0x9a, 0x25, 0xf1, 0x27, 0xc6, - 0xd5, 0x4e, 0x34, 0xf9, 0x78, 0xac, 0x56, 0xf5, 0xea, 0x3d, 0xb9, 0xdd, 0xd1, 0x78, 0xea, 0x15, 0xc5, 0x71, 0x8c, - 0x07, 0x72, 0x90, 0x27, 0x07, 0x62, 0xe8, 0x27, 0x2a, 0x98, 0x5c, 0xab, 0x09, 0x50, 0xae, 0xce, 0xe7, 0x38, 0x13, - 0xf3, 0x3b, 0x01, 0x3f, 0x8c, 0xd2, 0x5c, 0x17, 0x46, 0xa0, 0x6b, 0x93, 0x81, 0xfe, 0xa3, 0xeb, 0x75, 0x4d, 0xd7, - 0x3d, 0xb2, 0x8f, 0xba, 0x63, 0xc7, 0x3c, 0xb4, 0x0f, 0xad, 0xb6, 0x7d, 0x64, 0x76, 0xad, 0xae, 0xd9, 0xfd, 0x5b, - 0x77, 0x6c, 0x1d, 0xda, 0x87, 0xa6, 0x63, 0x75, 0x21, 0xd1, 0xea, 0x5a, 0xdd, 0x1b, 0xeb, 0xb0, 0x3b, 0x76, 0x30, - 0xd5, 0xb3, 0x3b, 0x1d, 0xcb, 0x75, 0xec, 0x4e, 0xc7, 0xec, 0xd8, 0x47, 0x47, 0x96, 0xdb, 0xb6, 0x8f, 0x8e, 0xce, - 0x3b, 0x5d, 0xbb, 0x0d, 0x79, 0xed, 0xf6, 0xb8, 0x6d, 0xbb, 0xae, 0x05, 0x7f, 0x99, 0x5d, 0xdb, 0xa3, 0x1f, 0xae, - 0x6b, 0xb7, 0x5d, 0xd3, 0x09, 0x3b, 0x9e, 0x7d, 0xf4, 0xc2, 0xc4, 0xbf, 0xb1, 0x98, 0x89, 0x7f, 0x41, 0x33, 0xe6, - 0x0b, 0xdb, 0x3b, 0xa2, 0x5f, 0xd8, 0xe0, 0xcd, 0x61, 0xf7, 0x57, 0xfd, 0x60, 0xe3, 0x1c, 0x5c, 0x9a, 0x43, 0xb7, - 0x63, 0xb7, 0xdb, 0xe6, 0xa1, 0x6b, 0x77, 0xdb, 0x73, 0xeb, 0xd0, 0xb3, 0x8f, 0x8e, 0xc7, 0x96, 0x6b, 0x1f, 0x1f, - 0x9b, 0x8e, 0xd5, 0xb6, 0x3d, 0xd3, 0xb5, 0x0f, 0xdb, 0xf8, 0xa3, 0x6d, 0x7b, 0x37, 0xc7, 0x2f, 0xec, 0xa3, 0xce, - 0xfc, 0xc8, 0x3e, 0xfc, 0x78, 0xd8, 0xb5, 0xbd, 0xf6, 0xbc, 0x7d, 0x64, 0x7b, 0xc7, 0x37, 0x47, 0xf6, 0xe1, 0xdc, - 0xf2, 0x8e, 0xb6, 0xd6, 0x74, 0x3d, 0x1b, 0x60, 0x84, 0xd9, 0x90, 0x61, 0xf2, 0x0c, 0xf8, 0x33, 0xc7, 0xba, 0xff, - 0xc5, 0x66, 0xd2, 0x7a, 0xd5, 0x17, 0x76, 0xf7, 0x78, 0x4c, 0xc5, 0x21, 0xc1, 0x12, 0x25, 0xa0, 0xca, 0x8d, 0x45, - 0xdd, 0x62, 0x73, 0x96, 0x68, 0x48, 0xfc, 0xe1, 0x9d, 0xdd, 0x58, 0xd0, 0x31, 0xf5, 0xfb, 0x3f, 0x6d, 0x47, 0x2e, - 0x39, 0x44, 0xae, 0xfc, 0x86, 0xff, 0x43, 0x41, 0x5f, 0x86, 0xe6, 0xf9, 0x26, 0x41, 0xc5, 0xfb, 0xdd, 0x82, 0x8a, - 0x37, 0xab, 0x7d, 0x04, 0x15, 0xef, 0xbf, 0xba, 0xa0, 0xe2, 0xbc, 0xaa, 0x27, 0xff, 0xbe, 0xea, 0x9b, 0xfe, 0xd7, - 0x75, 0xf5, 0x19, 0x12, 0xf8, 0xad, 0xcb, 0x8b, 0xd5, 0x15, 0x78, 0x57, 0x7a, 0x1f, 0x0f, 0xde, 0xac, 0x4a, 0x4a, - 0x60, 0x31, 0xe0, 0xd8, 0xf7, 0x31, 0xe1, 0xd8, 0xdf, 0x57, 0x03, 0xd0, 0x3c, 0xe1, 0x74, 0x49, 0x30, 0xb1, 0xe6, - 0x7e, 0x38, 0x95, 0x34, 0x0d, 0xa4, 0xf4, 0x31, 0x19, 0xac, 0x12, 0xe0, 0xba, 0x06, 0x71, 0xd8, 0x6a, 0x11, 0xa5, - 0xbd, 0x23, 0x07, 0x2e, 0x52, 0x6f, 0x9a, 0xe4, 0x95, 0xca, 0xb6, 0xf0, 0x47, 0x75, 0xcd, 0xad, 0x26, 0x36, 0xe6, - 0xa3, 0x52, 0x60, 0x73, 0xeb, 0x6e, 0xbd, 0x5d, 0x0d, 0xb4, 0x6d, 0x84, 0xd2, 0x24, 0x90, 0x73, 0x4d, 0xf9, 0x65, - 0xd5, 0xbc, 0x8a, 0x32, 0xe6, 0xe6, 0x91, 0xc2, 0x48, 0xaa, 0xf5, 0xdd, 0xb2, 0x6a, 0xdf, 0xae, 0x69, 0x36, 0x74, - 0x5f, 0xaa, 0xbe, 0x45, 0xaf, 0x50, 0x36, 0x5c, 0x05, 0x55, 0x25, 0xb2, 0x5a, 0x23, 0x40, 0x0a, 0xea, 0xbe, 0x50, - 0x3e, 0x2c, 0x48, 0x4b, 0x47, 0x43, 0x7a, 0xc7, 0x51, 0xf2, 0x4a, 0x6d, 0xaa, 0x0a, 0x8b, 0xcf, 0xd6, 0x48, 0x71, - 0x07, 0xbf, 0x03, 0xe9, 0xc8, 0x29, 0x9e, 0x51, 0xac, 0xc2, 0x79, 0xad, 0xb4, 0x4b, 0x8f, 0x99, 0x7c, 0xee, 0xae, - 0xeb, 0xc4, 0xe3, 0x46, 0x55, 0x65, 0x97, 0x2d, 0x04, 0x15, 0x84, 0xdd, 0x93, 0x62, 0x70, 0x4e, 0xca, 0xdb, 0xa8, - 0xfb, 0xbc, 0xad, 0x31, 0x51, 0xee, 0x31, 0x6c, 0x62, 0x93, 0x7f, 0xa8, 0x7e, 0x01, 0xd6, 0x53, 0x88, 0x82, 0xdd, - 0x43, 0x32, 0x4d, 0xa1, 0x51, 0x3d, 0xd4, 0x62, 0xee, 0x6f, 0x51, 0xb0, 0x51, 0x1b, 0xe6, 0x8d, 0xa0, 0x36, 0xf4, - 0x36, 0x9d, 0x1c, 0x69, 0x3c, 0xb2, 0x2e, 0x89, 0xa8, 0xdd, 0xce, 0xb1, 0xe9, 0x1e, 0x99, 0xf6, 0x71, 0xc7, 0xc8, - 0xc5, 0x81, 0x53, 0x9b, 0x2c, 0x01, 0x04, 0x94, 0xa2, 0xe5, 0x30, 0x83, 0x28, 0xc8, 0x02, 0x3f, 0xcc, 0x81, 0x3e, - 0x2e, 0xbf, 0x2a, 0xfe, 0xb9, 0x4a, 0x33, 0x98, 0xa3, 0x20, 0x7a, 0x51, 0x21, 0xdc, 0x1a, 0xb1, 0xec, 0x96, 0xb1, - 0x68, 0x83, 0xb0, 0xbc, 0xaa, 0x5f, 0xfe, 0xe7, 0x69, 0xdb, 0xe6, 0xa4, 0xc9, 0x32, 0xca, 0x22, 0xbe, 0x3f, 0x84, - 0x32, 0x74, 0x3e, 0x34, 0x7f, 0xda, 0x84, 0x70, 0xff, 0xb9, 0x1b, 0xe1, 0x66, 0x6c, 0x1f, 0x84, 0xfb, 0xcf, 0xaf, - 0x8e, 0x70, 0x7f, 0x52, 0x11, 0x6e, 0xc9, 0x16, 0xa8, 0xe0, 0x3a, 0x7f, 0xc0, 0xef, 0x16, 0x38, 0x75, 0x7e, 0xae, - 0x1f, 0x10, 0x01, 0xaf, 0x2b, 0xc1, 0x76, 0x3f, 0x96, 0xa2, 0x07, 0x21, 0x53, 0x04, 0x9d, 0xd0, 0x52, 0xa4, 0x12, - 0x08, 0x44, 0x2b, 0x43, 0xaa, 0x43, 0x9b, 0x6f, 0xa3, 0x2c, 0xb4, 0xdf, 0xf3, 0x87, 0x1f, 0x08, 0x79, 0xde, 0xc4, - 0xc9, 0xc2, 0x47, 0x07, 0x7c, 0x3a, 0x46, 0x1d, 0x84, 0x0f, 0x07, 0xec, 0xcf, 0xc6, 0x71, 0x34, 0x91, 0x92, 0x0a, - 0x36, 0xb8, 0x24, 0x8a, 0x5b, 0xbf, 0x67, 0x7e, 0xa2, 0x9b, 0x94, 0x0d, 0x8b, 0xfb, 0xac, 0xed, 0x3c, 0xf3, 0x0e, - 0x9f, 0x1d, 0x39, 0xf0, 0xbf, 0xcb, 0xda, 0xb9, 0xc9, 0x0b, 0x2e, 0xe2, 0x08, 0x02, 0x9f, 0x88, 0x92, 0x9b, 0x8a, - 0xdd, 0x32, 0xf6, 0xa9, 0x28, 0x75, 0xdc, 0x5c, 0x68, 0xe2, 0xdf, 0x17, 0x65, 0x1a, 0x4b, 0xcc, 0xe3, 0x95, 0x32, - 0xac, 0x86, 0xd1, 0x04, 0xd1, 0x0a, 0x78, 0x6f, 0x4a, 0x09, 0x35, 0x9b, 0x4f, 0xb7, 0x98, 0x17, 0x6b, 0xe7, 0x57, - 0x45, 0x74, 0x25, 0x11, 0xe5, 0x65, 0x27, 0x04, 0xb9, 0xd8, 0xc2, 0x41, 0xdf, 0xec, 0x18, 0x5f, 0x48, 0x83, 0xd8, - 0x86, 0x62, 0x81, 0x7c, 0x5a, 0xa0, 0x2c, 0x59, 0x45, 0xe3, 0x16, 0xfe, 0xf4, 0x47, 0x69, 0x2b, 0x38, 0x00, 0xef, - 0xac, 0xd8, 0xb1, 0x81, 0xab, 0xe6, 0x9f, 0x3a, 0x45, 0x28, 0x8a, 0x54, 0xac, 0x8a, 0xff, 0x2c, 0x33, 0x13, 0x0a, - 0x60, 0x8b, 0x4b, 0x6b, 0x0d, 0xfc, 0x67, 0xb2, 0xe2, 0xb3, 0xcc, 0x84, 0x20, 0xb2, 0xb0, 0xdc, 0x4f, 0x9f, 0x52, - 0x29, 0x08, 0xeb, 0x48, 0xd3, 0x3a, 0x1b, 0x17, 0xee, 0xdd, 0x34, 0x7f, 0x16, 0x93, 0x87, 0xb7, 0xde, 0xd8, 0x8c, - 0x9f, 0x3f, 0x3f, 0x1d, 0xb8, 0x06, 0x0f, 0x4a, 0x5a, 0x8a, 0xa0, 0x75, 0xbe, 0x9f, 0xf2, 0x81, 0xd1, 0x68, 0x16, - 0xb7, 0x84, 0x37, 0x93, 0x23, 0x54, 0x94, 0x39, 0xf6, 0x82, 0x88, 0x16, 0x24, 0x64, 0xf4, 0x85, 0x12, 0x80, 0x28, - 0x23, 0x5f, 0x5d, 0x6d, 0xdb, 0xb1, 0x1d, 0x5d, 0x56, 0x9c, 0x06, 0xb3, 0xc1, 0x3a, 0xce, 0x7c, 0x88, 0x0d, 0x14, - 0xc6, 0x33, 0xb0, 0xad, 0xc9, 0x82, 0x2c, 0x84, 0x40, 0x33, 0x60, 0x64, 0xb3, 0xa0, 0x77, 0x79, 0xce, 0x35, 0x9e, - 0xfd, 0xe4, 0x13, 0x06, 0x1b, 0x14, 0x66, 0x75, 0xe8, 0x71, 0xe8, 0x47, 0xb8, 0x0c, 0x5b, 0x7a, 0x0b, 0x42, 0x5d, - 0xb2, 0x24, 0xb5, 0x54, 0x0b, 0x82, 0x9e, 0x06, 0x75, 0x20, 0x0c, 0x3d, 0x36, 0x30, 0x4d, 0xfc, 0x05, 0xf8, 0x64, - 0x5f, 0xe7, 0x26, 0xc7, 0xb4, 0x3a, 0x47, 0xb5, 0x9a, 0xfb, 0xe2, 0xc8, 0xd4, 0x3c, 0xd7, 0xd4, 0x1c, 0x40, 0xb7, - 0x7a, 0x6e, 0xae, 0xf3, 0xab, 0xfe, 0x2e, 0x21, 0x28, 0xe1, 0x97, 0xc7, 0x34, 0x0f, 0x12, 0x7f, 0x72, 0xf6, 0x72, - 0x46, 0x0e, 0x24, 0x5b, 0x8a, 0xb7, 0xf4, 0x80, 0x04, 0x21, 0x17, 0xec, 0x2e, 0x33, 0x30, 0x10, 0x0b, 0x2f, 0x12, - 0x18, 0x6b, 0x34, 0xfe, 0x0b, 0x22, 0x2d, 0xf8, 0xfc, 0xb9, 0x15, 0x80, 0x81, 0xc3, 0x40, 0x81, 0x0f, 0x7c, 0x1b, - 0x25, 0x80, 0x05, 0x85, 0xe8, 0x0e, 0x81, 0x05, 0xd6, 0x47, 0xf0, 0x6f, 0x91, 0x2c, 0x7e, 0x70, 0xd1, 0xa9, 0x1d, - 0xfa, 0xd1, 0x0c, 0x50, 0x9a, 0x1f, 0xcd, 0x6a, 0x2a, 0x1a, 0x64, 0xbf, 0x58, 0x49, 0x2d, 0x9a, 0x2a, 0xd4, 0x27, - 0xd2, 0xef, 0xef, 0x2f, 0x28, 0xd0, 0x14, 0x04, 0x35, 0xf7, 0x27, 0x68, 0x6c, 0x57, 0x48, 0x77, 0x9e, 0x0f, 0xbe, - 0x3d, 0x59, 0xb0, 0xcc, 0x27, 0xd6, 0x30, 0x3c, 0x7e, 0x81, 0x1c, 0xd0, 0xc6, 0x22, 0x48, 0x2c, 0x05, 0x93, 0x9f, - 0xb0, 0x9b, 0x60, 0xcc, 0xdf, 0xa5, 0xa6, 0xc6, 0xef, 0x29, 0x0b, 0xb5, 0xc0, 0x06, 0xae, 0x49, 0x4a, 0xc8, 0x63, - 0x1f, 0xdd, 0x4c, 0x0e, 0xa2, 0x58, 0x3f, 0xfd, 0x56, 0xda, 0x6b, 0x6d, 0x5a, 0x04, 0x88, 0xf6, 0x78, 0x99, 0xb0, - 0xf0, 0x5f, 0x83, 0x6f, 0xe1, 0xe2, 0xfe, 0xf6, 0x4a, 0x37, 0xfa, 0x99, 0x3d, 0x4f, 0xd8, 0x74, 0xf0, 0x6d, 0x43, - 0xd4, 0x43, 0x7c, 0xde, 0xd3, 0x58, 0xf4, 0xb6, 0x57, 0x38, 0x07, 0x6a, 0xef, 0xf5, 0xa8, 0x3f, 0xe5, 0xaf, 0x75, - 0x78, 0x01, 0xae, 0x4b, 0x6f, 0x6c, 0xb7, 0x8f, 0xef, 0xe7, 0x51, 0xe8, 0x8f, 0x3f, 0xf5, 0x29, 0xa7, 0xf4, 0x61, - 0xc1, 0x6d, 0x3d, 0xf6, 0x97, 0x3d, 0xbc, 0x5e, 0xd5, 0x44, 0x30, 0xd7, 0xa4, 0x54, 0x49, 0xd9, 0x35, 0xee, 0x65, - 0xdc, 0xca, 0x6b, 0xec, 0x19, 0xbb, 0xba, 0x9d, 0x07, 0x19, 0x13, 0x5d, 0xe1, 0x47, 0x9e, 0x8b, 0x87, 0x3a, 0x3d, - 0x51, 0xf1, 0x61, 0x6d, 0xb7, 0x35, 0xb7, 0xfb, 0xb7, 0xce, 0x8d, 0xeb, 0xcc, 0x3d, 0xd7, 0xee, 0x7e, 0x74, 0xbb, - 0xf3, 0xb6, 0x7d, 0x1c, 0x5a, 0x6d, 0xfb, 0x18, 0xfe, 0x7c, 0x3c, 0xb6, 0xbb, 0x73, 0xcb, 0xb3, 0x0f, 0x3f, 0xba, - 0x5e, 0x68, 0x75, 0xed, 0x63, 0xf8, 0x73, 0x4e, 0xb5, 0xe0, 0x01, 0x44, 0xef, 0x9d, 0x6f, 0x4b, 0x58, 0x40, 0xf9, - 0x2d, 0xe5, 0x34, 0x66, 0xe9, 0x7a, 0x6b, 0x90, 0xf5, 0x00, 0xca, 0xd0, 0x4d, 0xe1, 0x04, 0x32, 0xea, 0xb7, 0x20, - 0x0c, 0x3b, 0x06, 0x10, 0x10, 0x2a, 0x2f, 0xc2, 0x2e, 0x55, 0xb8, 0xd2, 0x6f, 0x3c, 0x46, 0xbc, 0x4e, 0xb3, 0xc3, - 0x75, 0x11, 0x99, 0x8a, 0x84, 0x43, 0xbf, 0x2c, 0xd1, 0x89, 0x91, 0x70, 0x11, 0xaf, 0x60, 0xa5, 0x22, 0x3a, 0x62, - 0xbe, 0x7b, 0xe0, 0x68, 0x99, 0xcb, 0x64, 0x74, 0x9e, 0xaf, 0xda, 0x36, 0x17, 0x18, 0xc9, 0xd6, 0xff, 0x68, 0x3b, - 0x18, 0x94, 0x96, 0xda, 0x11, 0xde, 0x5c, 0x27, 0x41, 0x22, 0x87, 0xa7, 0xa0, 0x68, 0xb7, 0xd9, 0x53, 0xbd, 0x01, - 0x61, 0x4c, 0xde, 0x02, 0x95, 0x7c, 0xe3, 0x87, 0x8a, 0x72, 0x8b, 0x52, 0xf3, 0x91, 0xc4, 0xfc, 0x4f, 0x9f, 0x16, - 0x83, 0xb3, 0x2a, 0xe3, 0x3e, 0x71, 0x3b, 0x70, 0xed, 0x76, 0x58, 0x7b, 0xab, 0x9e, 0xd5, 0x6e, 0x77, 0xc0, 0x85, - 0xbb, 0x50, 0xa1, 0x4b, 0x21, 0xa4, 0xb8, 0x1b, 0x95, 0xbd, 0x6a, 0x32, 0x5c, 0x70, 0xa4, 0x5c, 0x79, 0xea, 0xe8, - 0x46, 0x3f, 0x12, 0x22, 0xc9, 0x68, 0x8b, 0x0b, 0x64, 0xfe, 0x16, 0xd3, 0x01, 0x34, 0x5b, 0xe6, 0xb1, 0xc3, 0x68, - 0xf4, 0x7f, 0x3d, 0x09, 0x34, 0xe0, 0x02, 0x19, 0x6a, 0xe5, 0xb4, 0x96, 0x0c, 0x7a, 0xe4, 0xbd, 0x4a, 0x17, 0x2a, - 0x4b, 0xcf, 0x74, 0x48, 0x82, 0xf8, 0x56, 0x18, 0xd2, 0x4e, 0x2a, 0x90, 0xc9, 0xdb, 0xa2, 0x48, 0x30, 0x03, 0xf0, - 0x01, 0xde, 0x12, 0xc6, 0x64, 0xc6, 0xd3, 0xa7, 0x1b, 0x2f, 0x21, 0x12, 0xd8, 0xab, 0x91, 0x3d, 0x75, 0x15, 0xbf, - 0xe9, 0x2a, 0x8a, 0x91, 0xed, 0x22, 0xd6, 0x10, 0x7a, 0x6f, 0xb4, 0xf7, 0xf0, 0xe7, 0x88, 0xf9, 0x99, 0xcd, 0x25, - 0x4d, 0x2d, 0xe5, 0x72, 0x37, 0x5d, 0xd6, 0x06, 0x8d, 0x37, 0xee, 0xeb, 0x8c, 0xfb, 0x12, 0x7c, 0xb2, 0xfe, 0xb8, - 0xe2, 0x96, 0xde, 0xd0, 0xc6, 0x67, 0xa7, 0x70, 0x4f, 0xf3, 0x2e, 0xf3, 0xc9, 0x87, 0x89, 0x7a, 0xe5, 0xc6, 0x99, - 0x2f, 0xe2, 0xc8, 0x00, 0x5d, 0xde, 0x6f, 0x14, 0xc9, 0x2a, 0xd6, 0xe0, 0xa7, 0xef, 0x2e, 0xbe, 0xd3, 0xf8, 0xfe, - 0x27, 0x09, 0x22, 0x3e, 0x64, 0x28, 0xea, 0xc1, 0x80, 0xa2, 0x1e, 0x68, 0x3c, 0x8c, 0x08, 0xc4, 0x0e, 0xc8, 0x0f, - 0x08, 0x82, 0xc8, 0x80, 0x26, 0xb9, 0xea, 0x62, 0x15, 0x66, 0xc1, 0xd2, 0x4f, 0xb2, 0x03, 0xa8, 0x6a, 0x01, 0x92, - 0xd3, 0x37, 0xd9, 0x88, 0x93, 0x68, 0x56, 0xb8, 0xd8, 0xcb, 0x22, 0x21, 0x9b, 0x9d, 0x06, 0xa1, 0x14, 0xcd, 0x8a, - 0x0e, 0xfc, 0xf1, 0x98, 0x2d, 0xb3, 0x81, 0xee, 0x2f, 0x21, 0xfa, 0x05, 0xfa, 0xb3, 0x3e, 0x88, 0xc7, 0x19, 0xcb, - 0xac, 0x34, 0x4b, 0x98, 0xbf, 0xd0, 0xa5, 0x2b, 0xd7, 0x7a, 0x7b, 0xe9, 0x6a, 0xb4, 0x08, 0x32, 0xe9, 0x0b, 0x91, - 0x26, 0x08, 0x42, 0x52, 0x18, 0xe2, 0xe9, 0x30, 0xe7, 0x20, 0x3c, 0x8f, 0x67, 0x95, 0x1d, 0x55, 0x50, 0x2e, 0x67, - 0xe8, 0x69, 0x97, 0x47, 0x3c, 0x98, 0xa0, 0xcd, 0xd3, 0x35, 0xb7, 0x6b, 0x97, 0x2e, 0x1b, 0xf5, 0xd3, 0x13, 0xfe, - 0xbc, 0xd5, 0xd0, 0x15, 0x83, 0xde, 0x71, 0xc0, 0x97, 0xf0, 0x26, 0x8b, 0xf7, 0x03, 0x5e, 0x18, 0xae, 0x26, 0x6a, - 0x19, 0xfd, 0xbc, 0xd3, 0x58, 0x2e, 0x80, 0x10, 0x2a, 0x09, 0xd1, 0xe7, 0xee, 0xa9, 0x34, 0xb1, 0xc2, 0x51, 0x21, - 0xad, 0xf4, 0xf9, 0xf3, 0xcb, 0xe1, 0x7f, 0xfe, 0x0d, 0xce, 0xe8, 0xe7, 0xae, 0xb0, 0x33, 0xbf, 0x54, 0x4b, 0x71, - 0xea, 0xd3, 0x1c, 0xa2, 0x02, 0x05, 0x9b, 0x08, 0xc7, 0x2b, 0x62, 0x6b, 0xe5, 0xc3, 0x2b, 0xe1, 0x4c, 0x0b, 0x02, - 0x4e, 0x18, 0xc2, 0x1a, 0x7e, 0x08, 0xcb, 0x3b, 0x14, 0x4e, 0x18, 0xb4, 0xdf, 0xee, 0xbe, 0x3f, 0x06, 0x67, 0xcb, - 0xb5, 0x38, 0x10, 0xca, 0x00, 0x71, 0x0f, 0x9d, 0x9e, 0xf8, 0x1a, 0x12, 0x2d, 0x48, 0x7e, 0xa4, 0xbd, 0x03, 0x98, - 0xe6, 0x3c, 0x5e, 0x30, 0x3b, 0x88, 0x0f, 0x6e, 0xd9, 0xc8, 0xf2, 0x97, 0x01, 0xc9, 0xea, 0x91, 0xef, 0xa6, 0x11, - 0xe5, 0x27, 0x45, 0xe0, 0x44, 0x5f, 0xe7, 0x05, 0x28, 0xe3, 0x02, 0x50, 0xf0, 0xd3, 0x3f, 0x2d, 0xfb, 0x67, 0xb4, - 0x45, 0x84, 0x80, 0x32, 0x96, 0x3f, 0x23, 0x37, 0x8b, 0xc2, 0xa3, 0x62, 0xf1, 0x61, 0xc5, 0xd3, 0xa9, 0xea, 0x53, - 0xd1, 0x2e, 0xf7, 0x2f, 0xa1, 0x52, 0xec, 0xd9, 0x78, 0x49, 0x3d, 0xd5, 0xbb, 0x90, 0x3f, 0x21, 0x3a, 0x32, 0x77, - 0xbf, 0x09, 0xe7, 0xb9, 0xe6, 0x9b, 0x51, 0x82, 0xe4, 0x31, 0x15, 0xe2, 0x88, 0xa2, 0xea, 0x09, 0x7c, 0x03, 0x69, - 0xf2, 0x68, 0x30, 0x20, 0x3c, 0x56, 0x45, 0x67, 0x00, 0xa5, 0x86, 0x68, 0x09, 0x30, 0xd9, 0x0c, 0x2a, 0x5a, 0x64, - 0x23, 0x87, 0x95, 0xaa, 0xd3, 0xa9, 0x8f, 0xf1, 0xc0, 0x17, 0xfb, 0xab, 0xb4, 0x03, 0x61, 0x67, 0xf1, 0x85, 0x05, - 0x04, 0x2e, 0xda, 0xa9, 0xe0, 0x71, 0xed, 0xaf, 0x84, 0xb2, 0xad, 0xd0, 0xbf, 0x8f, 0x15, 0xdd, 0x05, 0xee, 0xc6, - 0xe0, 0x1c, 0x53, 0x2f, 0x84, 0xf9, 0x60, 0xed, 0x24, 0x49, 0x8f, 0xf3, 0xf5, 0xd3, 0xa4, 0xba, 0x88, 0xdf, 0x75, - 0x98, 0xd4, 0xb2, 0xe5, 0xc9, 0x20, 0x76, 0xcc, 0x8b, 0x83, 0x56, 0xca, 0xc4, 0x73, 0x9f, 0x9f, 0x1c, 0xc0, 0xfc, - 0xc0, 0xf5, 0x42, 0x89, 0x32, 0x0a, 0x0c, 0xf0, 0xef, 0xe0, 0xa7, 0xa4, 0x7f, 0xf1, 0x76, 0x22, 0x88, 0x3a, 0x7c, - 0x39, 0x4a, 0xe7, 0xaf, 0xa5, 0x22, 0x75, 0x62, 0xc5, 0x69, 0xa6, 0xf2, 0x76, 0x47, 0x68, 0xf8, 0x7d, 0x85, 0xe1, - 0x19, 0xf2, 0x7e, 0xc6, 0x84, 0x65, 0xf3, 0x79, 0xb6, 0xc1, 0xf8, 0x79, 0x53, 0x11, 0x22, 0x58, 0xb7, 0x14, 0x28, - 0xf6, 0xf1, 0xb6, 0x52, 0x05, 0x69, 0x24, 0x8b, 0x2d, 0xfd, 0x96, 0xfe, 0x18, 0x77, 0x7c, 0xad, 0x34, 0xa6, 0x42, - 0xb9, 0xf3, 0x6c, 0x00, 0x45, 0x05, 0xb3, 0xdd, 0x5f, 0x2e, 0xa9, 0xb0, 0xd1, 0x3f, 0x39, 0xa0, 0x77, 0xe7, 0x29, - 0xed, 0xb0, 0xd3, 0x13, 0xd0, 0xdf, 0xa4, 0x45, 0xf7, 0x97, 0x4b, 0xbe, 0xa4, 0xf4, 0x8b, 0x72, 0x0e, 0xe6, 0xd9, - 0x22, 0x3c, 0xfd, 0x3f, 0x1d, 0xdb, 0x6f, 0x83, 0x01, 0x5c, 0x03, 0x00}; + 0xdc, 0xb3, 0x37, 0xb7, 0x6d, 0x23, 0xff, 0x7f, 0x3f, 0x05, 0xc3, 0xe4, 0x52, 0x31, 0x21, 0x69, 0x92, 0xb2, 0x6c, + 0x45, 0xb2, 0xec, 0x6b, 0xf3, 0x98, 0x4b, 0xc7, 0x6d, 0x3a, 0x89, 0x9b, 0xb9, 0xab, 0xeb, 0xb1, 0x28, 0x09, 0x92, + 0x78, 0xa1, 0x48, 0x0d, 0x49, 0xf9, 0x51, 0x85, 0xf7, 0x59, 0xee, 0xb3, 0xdc, 0x27, 0xfb, 0xcd, 0xee, 0x02, 0x20, + 0xf8, 0xd0, 0xc3, 0x4d, 0x7a, 0xf7, 0x9b, 0x36, 0x89, 0x08, 0x02, 0x4b, 0x60, 0x01, 0x2c, 0x16, 0xfb, 0xf4, 0x67, + 0x5c, 0xf6, 0x62, 0xb6, 0xd8, 0x7e, 0x9f, 0xfb, 0xfc, 0x99, 0xd9, 0xb8, 0x24, 0x81, 0xe1, 0xb3, 0xb3, 0x78, 0x36, + 0x0b, 0x59, 0x4b, 0x17, 0xc9, 0x43, 0x74, 0x53, 0x7e, 0xe6, 0xec, 0x91, 0x23, 0x22, 0x76, 0x1a, 0xf9, 0xa6, 0xad, + 0x25, 0x46, 0xcc, 0x64, 0x48, 0x3b, 0xe2, 0x5c, 0x51, 0x36, 0x7b, 0x83, 0xea, 0x0d, 0x3e, 0x2f, 0xc5, 0xd6, 0xb5, + 0x26, 0xf1, 0x6a, 0x14, 0x32, 0x0b, 0x97, 0x3b, 0x7c, 0x72, 0x3d, 0x5a, 0x8d, 0x46, 0x90, 0xa5, 0xe5, 0x91, 0x63, + 0x42, 0xdc, 0x99, 0x38, 0xc5, 0xfb, 0x60, 0x6e, 0xf4, 0x61, 0x50, 0x76, 0x56, 0xed, 0x3e, 0xd8, 0x8a, 0x80, 0xa8, + 0x87, 0x3e, 0x90, 0xc1, 0xdd, 0xaf, 0x61, 0xd7, 0x0e, 0xf4, 0x0f, 0xb0, 0xfa, 0x52, 0xbd, 0xdf, 0xb4, 0xf5, 0x07, + 0x97, 0xfa, 0x07, 0xc4, 0x31, 0x66, 0x2f, 0x7e, 0x49, 0xab, 0x57, 0x37, 0x75, 0x52, 0x7a, 0xaf, 0x30, 0x8f, 0x01, + 0x08, 0x7d, 0x5f, 0x05, 0xfe, 0x2c, 0x8a, 0xd3, 0x2c, 0x18, 0xeb, 0x57, 0xfd, 0xb7, 0x41, 0xeb, 0x72, 0x91, 0xb5, + 0x8c, 0x2b, 0x73, 0x9c, 0xa9, 0x29, 0x50, 0x04, 0xc1, 0xc4, 0x0c, 0x28, 0x9b, 0x2a, 0xa9, 0x3b, 0x68, 0x6b, 0x45, + 0x41, 0x9a, 0xb1, 0xd2, 0x38, 0x1b, 0x40, 0xbd, 0x4a, 0x3e, 0x15, 0x4c, 0x0c, 0xa5, 0x63, 0x4b, 0xa3, 0x4f, 0x37, + 0x95, 0x97, 0xab, 0x35, 0x1e, 0xe5, 0x59, 0x71, 0x5a, 0x62, 0x0c, 0x60, 0xe1, 0x38, 0x43, 0xcf, 0x8f, 0x54, 0xa3, + 0xcf, 0xd2, 0xb9, 0x3b, 0xfc, 0xae, 0xcc, 0x17, 0xc0, 0xf9, 0x0d, 0x16, 0x17, 0x51, 0x9c, 0x69, 0x10, 0xd8, 0x06, + 0xbe, 0x38, 0xac, 0x1a, 0x89, 0x71, 0xa8, 0x2d, 0x23, 0xe7, 0xc4, 0xe0, 0x7b, 0x3c, 0xfc, 0x5a, 0x3c, 0xbc, 0x59, + 0x29, 0x82, 0x05, 0x5d, 0x16, 0x22, 0x98, 0xc0, 0x2c, 0x3e, 0x8f, 0x6f, 0xab, 0x7a, 0x90, 0x97, 0xc3, 0xdd, 0x67, + 0x6f, 0x4b, 0xb0, 0xc9, 0x22, 0xab, 0x5f, 0x8b, 0x27, 0x26, 0x15, 0x8c, 0x4e, 0x65, 0x4f, 0xa1, 0xe1, 0x87, 0xe0, + 0x61, 0x32, 0xb0, 0x13, 0xc3, 0xb3, 0x00, 0x48, 0x12, 0x3f, 0xa6, 0x87, 0xf9, 0xb5, 0x48, 0x9d, 0x2c, 0x12, 0x17, + 0x2b, 0x87, 0x33, 0x50, 0xd7, 0x68, 0xb9, 0xca, 0x30, 0xd4, 0x2e, 0x74, 0x80, 0xe5, 0xba, 0x86, 0xa1, 0x3b, 0x81, + 0x4a, 0x17, 0x6c, 0x62, 0xae, 0x6b, 0xc1, 0xa4, 0x5e, 0xc6, 0x99, 0x5e, 0x20, 0x5e, 0x48, 0xdf, 0x51, 0x50, 0x05, + 0x8f, 0x09, 0x1f, 0xc6, 0xd8, 0x2c, 0xe2, 0xd4, 0xb7, 0xc6, 0xa8, 0xd0, 0x69, 0xa0, 0x0c, 0x63, 0x82, 0xd3, 0x6f, + 0x85, 0x8d, 0x83, 0x85, 0xf0, 0x9b, 0xa5, 0x61, 0x0e, 0x9f, 0xac, 0xa3, 0xfc, 0xec, 0xc9, 0x3a, 0xcd, 0x07, 0x4f, + 0xd6, 0xbe, 0xb4, 0x15, 0xd0, 0x2f, 0x74, 0x32, 0x14, 0x18, 0x22, 0x1a, 0x86, 0xf9, 0x75, 0xe1, 0xb9, 0x53, 0x8c, + 0x17, 0x56, 0x19, 0x95, 0x6b, 0xa8, 0xba, 0x1f, 0x70, 0x05, 0xfd, 0x32, 0x09, 0x16, 0x7e, 0x72, 0x4f, 0xfa, 0x7c, + 0x53, 0x55, 0xfa, 0x1b, 0xba, 0x46, 0x84, 0x9e, 0x10, 0x40, 0x34, 0x5f, 0xd7, 0xfe, 0x2a, 0xcb, 0x18, 0x1f, 0xad, + 0x54, 0x6a, 0xc2, 0xb7, 0xae, 0xf5, 0xe7, 0xcc, 0x9e, 0xb0, 0xcc, 0x0f, 0x42, 0x6a, 0xd2, 0x17, 0xd9, 0xea, 0x6b, + 0xc3, 0x4b, 0xcb, 0xc3, 0x8b, 0xca, 0xeb, 0x07, 0x07, 0x43, 0x47, 0x00, 0xf5, 0x1b, 0x47, 0x86, 0x59, 0xac, 0x9a, + 0x67, 0x94, 0xde, 0xfd, 0x57, 0xa7, 0x83, 0xc1, 0x74, 0x44, 0x30, 0x1d, 0x2c, 0x1a, 0xc7, 0x13, 0xf6, 0xcb, 0xfb, + 0xb7, 0x32, 0x6d, 0x16, 0x48, 0x80, 0x86, 0x7c, 0x61, 0xa6, 0xc8, 0x3f, 0x24, 0xc8, 0x3b, 0x50, 0x82, 0x2b, 0x4d, + 0x2e, 0xa1, 0x24, 0xd7, 0xb5, 0x33, 0xea, 0x3b, 0x9b, 0x50, 0xaf, 0x07, 0x31, 0xb6, 0x4a, 0xf2, 0x93, 0x03, 0xaa, + 0x4d, 0xa7, 0x1d, 0x55, 0x02, 0x34, 0x24, 0x30, 0xc2, 0x02, 0x0b, 0x90, 0xe1, 0x73, 0xe0, 0x16, 0x17, 0x0a, 0x7b, + 0x81, 0x72, 0x76, 0xf7, 0xac, 0xcc, 0xaa, 0x60, 0x2b, 0xfd, 0xf4, 0x04, 0x73, 0x76, 0xc1, 0x79, 0x0d, 0x51, 0x3e, + 0x4e, 0x0e, 0xe8, 0x51, 0xab, 0xec, 0x88, 0x02, 0x88, 0xb8, 0xda, 0xf5, 0x38, 0x80, 0x07, 0x6d, 0x15, 0x48, 0x11, + 0x0f, 0xa5, 0x7e, 0xae, 0x6b, 0x0b, 0xce, 0x1a, 0xf1, 0x70, 0x42, 0x10, 0x6b, 0xc0, 0x81, 0xbd, 0xab, 0x6b, 0x0b, + 0xff, 0x0e, 0x47, 0x2e, 0xde, 0xf8, 0x77, 0x2d, 0x97, 0xbf, 0x2a, 0xf6, 0x5a, 0x5a, 0xde, 0x6b, 0x63, 0x3e, 0xb9, + 0xe0, 0x48, 0x20, 0x6f, 0xd6, 0x73, 0x54, 0xd0, 0x36, 0x4c, 0xee, 0x5c, 0x4c, 0xee, 0x64, 0xc3, 0xe4, 0x4e, 0xb6, + 0x4c, 0x6e, 0xc8, 0x27, 0x52, 0x93, 0xa8, 0x4b, 0xd0, 0x39, 0x4c, 0x22, 0x8f, 0x33, 0x1a, 0x3d, 0xbe, 0xcf, 0x10, + 0x4f, 0x56, 0x1a, 0x82, 0x71, 0xd4, 0x06, 0x5c, 0x35, 0xe1, 0x45, 0x41, 0x44, 0x7d, 0xe0, 0x72, 0xd7, 0x89, 0x71, + 0x43, 0x0e, 0xce, 0x56, 0x58, 0x1d, 0x2f, 0xac, 0x52, 0xca, 0x2f, 0xde, 0x9a, 0x6f, 0x18, 0xe9, 0x7c, 0xcb, 0x48, + 0xc7, 0xa5, 0xad, 0xcb, 0x87, 0x4d, 0x9b, 0x50, 0x1d, 0x14, 0xac, 0x41, 0x30, 0x18, 0xc5, 0x25, 0x53, 0x5e, 0x87, + 0x9b, 0x69, 0xac, 0xb2, 0xa2, 0x96, 0x7e, 0x9a, 0xde, 0xc6, 0x09, 0x68, 0x5c, 0x00, 0xcc, 0xc3, 0x96, 0xd4, 0x22, + 0x88, 0x78, 0x30, 0x97, 0x8d, 0x8b, 0xa9, 0x78, 0xaf, 0x2e, 0x29, 0xaf, 0xd3, 0xa1, 0x1a, 0x4b, 0x3f, 0xcb, 0x58, + 0x82, 0x48, 0xf7, 0x21, 0xea, 0xf7, 0xff, 0x93, 0x65, 0xd6, 0x40, 0x43, 0x42, 0x85, 0xaa, 0x23, 0x85, 0x5e, 0x02, + 0x6f, 0x95, 0x88, 0x83, 0x58, 0x09, 0x0c, 0x97, 0x48, 0xc4, 0xff, 0x84, 0xdb, 0xb5, 0x95, 0x28, 0xae, 0x4b, 0xee, + 0x91, 0x61, 0x2f, 0xfd, 0xc9, 0x07, 0x50, 0xec, 0xb5, 0x3c, 0x13, 0x8c, 0x74, 0xd5, 0x30, 0x70, 0x09, 0x31, 0x7b, + 0xe3, 0x82, 0x48, 0x22, 0x95, 0xe4, 0x26, 0x50, 0xe0, 0x3d, 0xe9, 0x5b, 0xd3, 0xab, 0xb5, 0x97, 0x1f, 0xcc, 0x02, + 0xa3, 0x46, 0x35, 0x81, 0xb4, 0x85, 0x83, 0x53, 0x79, 0xe7, 0x0a, 0x4d, 0xf7, 0xc8, 0x00, 0xc9, 0xef, 0x25, 0xe4, + 0x33, 0x75, 0xc4, 0x85, 0x76, 0x98, 0xc0, 0xa9, 0x75, 0xe9, 0x5c, 0xe5, 0x4f, 0x67, 0xf8, 0xcb, 0xbd, 0xca, 0x9f, + 0x8e, 0xf0, 0x97, 0x77, 0x85, 0x99, 0xeb, 0x1a, 0x2e, 0xf2, 0xca, 0x98, 0xf5, 0xd3, 0xd2, 0x7a, 0x22, 0xfb, 0xb3, + 0x07, 0x2c, 0x1b, 0x3e, 0xc1, 0x8f, 0x9f, 0xac, 0x53, 0xf0, 0xb8, 0x54, 0xc7, 0x10, 0xd9, 0x89, 0x91, 0x37, 0x96, + 0xcf, 0x36, 0x94, 0x8f, 0x8c, 0xff, 0xf2, 0xc1, 0x8f, 0xab, 0x24, 0x2e, 0xce, 0x94, 0xb2, 0x18, 0xe2, 0x7a, 0x14, + 0x44, 0x7e, 0x72, 0x7f, 0x4d, 0xd7, 0x8b, 0x96, 0xe0, 0xdd, 0xa5, 0x78, 0x85, 0xd8, 0xcb, 0xb2, 0xba, 0x2b, 0x53, + 0x04, 0xbc, 0xf7, 0xfc, 0xa0, 0x1f, 0xfc, 0x3d, 0x51, 0xd8, 0xb6, 0xd2, 0x05, 0x94, 0x4f, 0x48, 0xe9, 0x43, 0xd7, + 0x4f, 0xd6, 0x2d, 0x56, 0x07, 0x53, 0x19, 0x6d, 0x85, 0x2f, 0x84, 0xe9, 0xc1, 0xcb, 0xec, 0x62, 0x12, 0xf4, 0x50, + 0x9f, 0x35, 0x8a, 0xef, 0xac, 0x27, 0xeb, 0xec, 0x4c, 0x5f, 0xf8, 0xc9, 0x27, 0x36, 0xb1, 0xc6, 0x41, 0x32, 0x0e, + 0x99, 0xde, 0xd3, 0x47, 0xa1, 0x1f, 0x7d, 0xe2, 0x8f, 0x56, 0xbc, 0xca, 0x50, 0x43, 0xbd, 0xf3, 0xee, 0x2b, 0x70, + 0x42, 0x22, 0x3b, 0x64, 0x56, 0x1b, 0xb0, 0xa0, 0xbd, 0x94, 0x02, 0xaf, 0x82, 0x51, 0x2c, 0x6a, 0x99, 0x60, 0x60, + 0x09, 0x4a, 0x73, 0xf0, 0x58, 0x35, 0x75, 0x9c, 0x2f, 0xdd, 0x54, 0x87, 0x4a, 0xc2, 0x4a, 0x99, 0x72, 0xf1, 0x1a, + 0x21, 0xfc, 0xf1, 0xcf, 0x51, 0x32, 0xec, 0xfd, 0x3f, 0x27, 0xa1, 0x7c, 0xd9, 0x08, 0xa1, 0xd4, 0x22, 0x4f, 0x89, + 0x07, 0x7c, 0x9c, 0x33, 0x98, 0x9b, 0x3f, 0xad, 0x36, 0xf6, 0xd3, 0x74, 0xb5, 0x60, 0x13, 0xd2, 0x0c, 0x9e, 0x15, + 0x9d, 0x2a, 0xdf, 0x2c, 0xd4, 0x8e, 0xfd, 0xb6, 0xf2, 0x8e, 0x0f, 0x5f, 0x82, 0xc5, 0x02, 0x30, 0x94, 0xf1, 0x74, + 0xaa, 0x17, 0x77, 0xfc, 0x1d, 0xcd, 0xdc, 0xc3, 0xdf, 0x56, 0x6f, 0x5e, 0x3b, 0x6f, 0x64, 0xe3, 0x08, 0x18, 0x63, + 0xa1, 0x7e, 0xe5, 0x7c, 0xb1, 0xd2, 0x5f, 0x31, 0xa2, 0xa9, 0x1f, 0x6d, 0x1e, 0xce, 0x65, 0x69, 0x89, 0x2f, 0x19, + 0x9b, 0x00, 0xc3, 0x6d, 0xd6, 0x4a, 0xaf, 0x43, 0x76, 0xc3, 0xa4, 0x6a, 0xb7, 0xfe, 0xb1, 0x86, 0x16, 0x18, 0x7b, + 0x8e, 0xab, 0x8c, 0x39, 0x57, 0xa7, 0x0c, 0x69, 0x88, 0x63, 0xe0, 0x23, 0x57, 0xb7, 0x58, 0x65, 0x4b, 0x0d, 0x4d, + 0x5d, 0xe9, 0xc0, 0xc6, 0x9e, 0x9d, 0x6d, 0x28, 0xef, 0x61, 0xe2, 0xe9, 0xe6, 0xbe, 0x99, 0xae, 0xd1, 0x83, 0x58, + 0xdd, 0x1c, 0x4f, 0x21, 0xec, 0xbc, 0x56, 0x21, 0x0e, 0xd9, 0x84, 0xb1, 0x26, 0x21, 0x99, 0x4e, 0xd2, 0x17, 0x61, + 0xed, 0x88, 0x66, 0xbf, 0x42, 0x0e, 0xd5, 0x38, 0x37, 0x5a, 0x79, 0xe4, 0x23, 0x4c, 0xe8, 0x1a, 0xb1, 0x34, 0xdd, + 0x88, 0x30, 0x39, 0xe9, 0xa6, 0x5e, 0xd4, 0x2e, 0xe3, 0xa3, 0x28, 0x37, 0x1d, 0x13, 0x58, 0x02, 0x1c, 0x60, 0xf5, + 0x5b, 0x78, 0xbc, 0x5c, 0x2f, 0xb8, 0xbd, 0x4a, 0x32, 0x1b, 0xe9, 0xdc, 0x96, 0x60, 0xd3, 0xfb, 0x5b, 0x9d, 0x77, + 0xaa, 0x74, 0x4c, 0x37, 0x76, 0xad, 0x55, 0x22, 0xbd, 0x35, 0x71, 0x11, 0x02, 0x10, 0x7d, 0xaa, 0xd0, 0x57, 0x36, + 0x9d, 0xb2, 0x71, 0x96, 0x1a, 0x42, 0x78, 0x24, 0xa3, 0xc7, 0x82, 0xd7, 0xd0, 0xa3, 0x81, 0xfe, 0x13, 0xf8, 0xd0, + 0x8b, 0x20, 0x4b, 0xbc, 0x43, 0xe2, 0xce, 0xd4, 0x8c, 0x26, 0x82, 0x58, 0x46, 0x11, 0xff, 0x0a, 0x24, 0x07, 0x6f, + 0x28, 0xc7, 0xae, 0xf1, 0xf3, 0xa7, 0x58, 0x17, 0xb1, 0xb4, 0x6a, 0xd9, 0x4e, 0x8a, 0xb6, 0x6d, 0xdf, 0xb5, 0xfb, + 0xa6, 0xe3, 0x3a, 0xb9, 0x6e, 0x82, 0xef, 0xd6, 0xa7, 0x7d, 0x37, 0x3d, 0xb6, 0x6a, 0x43, 0xab, 0x55, 0xf4, 0x90, + 0x76, 0x9e, 0xfb, 0xc2, 0xd5, 0x4d, 0x32, 0x99, 0x53, 0x68, 0xdb, 0x38, 0xbe, 0x61, 0xc9, 0x17, 0x0f, 0xa5, 0x0c, + 0x7c, 0xbf, 0xfe, 0x1c, 0xb9, 0x0e, 0x10, 0xe1, 0x2c, 0x5e, 0x3e, 0x60, 0x08, 0x6d, 0xdd, 0xd4, 0xc7, 0x61, 0x9c, + 0x32, 0x75, 0x0c, 0x24, 0x04, 0xf9, 0xc2, 0x41, 0xfc, 0xfc, 0xfe, 0xf5, 0x87, 0x0f, 0xba, 0x89, 0x99, 0x40, 0x53, + 0x15, 0x3a, 0x5f, 0x50, 0x3b, 0xa8, 0x7f, 0xe3, 0xba, 0xa3, 0x13, 0x86, 0x2e, 0xb5, 0xe5, 0x35, 0x47, 0x65, 0xb5, + 0x25, 0xc7, 0x4f, 0x1e, 0xfe, 0x65, 0xba, 0x89, 0xee, 0x35, 0xae, 0x06, 0xda, 0xb0, 0xfd, 0x78, 0x2b, 0x95, 0x2c, + 0x82, 0xe8, 0xba, 0xa1, 0xd4, 0xbf, 0x6b, 0x28, 0x85, 0xab, 0x5c, 0x8d, 0x56, 0xad, 0xe2, 0x85, 0xc2, 0x1a, 0x40, + 0x22, 0xe7, 0x5d, 0xe8, 0x52, 0xee, 0x53, 0x5f, 0xd0, 0x69, 0x1e, 0xc9, 0xbd, 0xda, 0xeb, 0x86, 0x62, 0x7e, 0x09, + 0x92, 0xb8, 0x1d, 0x87, 0x60, 0xf0, 0xc7, 0x54, 0xad, 0x5c, 0x99, 0x6d, 0x94, 0xe6, 0xba, 0x0a, 0x10, 0x62, 0x6f, + 0xaf, 0x33, 0xb6, 0x58, 0xb2, 0xc4, 0xcf, 0x56, 0x09, 0xbb, 0x0e, 0xe3, 0xdb, 0x47, 0x85, 0x39, 0xfd, 0x8e, 0xca, + 0xf3, 0x60, 0x36, 0x97, 0xb5, 0xcf, 0x5a, 0x6c, 0x20, 0x27, 0x70, 0xeb, 0x07, 0xf2, 0xff, 0xfc, 0xdb, 0xb6, 0xff, + 0xf3, 0xef, 0x9d, 0x55, 0x01, 0x7c, 0x3e, 0x34, 0xb3, 0xc1, 0x1e, 0xeb, 0xa2, 0xf9, 0x4b, 0x65, 0x9c, 0x37, 0xd7, + 0xa9, 0x4d, 0x02, 0xbc, 0xaf, 0x4d, 0x41, 0xad, 0xb0, 0xbc, 0x6e, 0x1e, 0xd4, 0x31, 0x18, 0xd7, 0xce, 0x9e, 0x41, + 0xa5, 0x2f, 0xea, 0xda, 0xd0, 0xe8, 0xed, 0x35, 0x23, 0x7f, 0x1c, 0xc3, 0xbb, 0xc6, 0xf0, 0x85, 0xdd, 0xe7, 0x72, + 0xc9, 0x97, 0xc3, 0xa1, 0xcc, 0x2d, 0xa7, 0x36, 0x05, 0x13, 0xff, 0xb3, 0x5a, 0x09, 0x3f, 0x3c, 0x7b, 0x8e, 0x41, + 0xbe, 0xf7, 0x83, 0x97, 0x43, 0x34, 0x46, 0x3b, 0x19, 0x25, 0x05, 0xb3, 0xb2, 0x91, 0xb4, 0x91, 0x31, 0x79, 0x0d, + 0x68, 0x8d, 0xae, 0x41, 0x29, 0x26, 0x1c, 0xcb, 0x87, 0x86, 0xf9, 0x72, 0xc8, 0x05, 0x4b, 0xdc, 0xfe, 0xb5, 0x57, + 0x5d, 0xda, 0x5c, 0x2c, 0x5b, 0x42, 0xba, 0xa9, 0x91, 0xfe, 0x07, 0x2b, 0xb3, 0x42, 0x8e, 0x87, 0x02, 0x7e, 0x90, + 0x28, 0x0c, 0x73, 0xcc, 0x77, 0xf2, 0x6e, 0x93, 0x8d, 0xd8, 0xcf, 0xbb, 0x6d, 0xc4, 0x2e, 0xf6, 0xb2, 0x11, 0xfb, + 0xf9, 0xab, 0xdb, 0x88, 0xbd, 0x53, 0x6d, 0xc4, 0x60, 0x12, 0x5f, 0xb3, 0xbd, 0x0c, 0xb7, 0x84, 0xd5, 0x46, 0x7c, + 0x9b, 0x0e, 0x5c, 0xce, 0xd2, 0xa6, 0xe3, 0x39, 0x03, 0x19, 0x01, 0x9f, 0x95, 0x30, 0x9e, 0x81, 0x11, 0xd7, 0x9f, + 0x6f, 0x6e, 0x15, 0xc6, 0x33, 0xd5, 0xd8, 0x2a, 0xe2, 0x11, 0x5f, 0x8b, 0x28, 0x4e, 0x64, 0xe0, 0xe4, 0x98, 0x22, + 0xe6, 0x93, 0x75, 0x68, 0x28, 0x59, 0xad, 0xa5, 0xf5, 0x9a, 0x27, 0x4c, 0xa0, 0x7a, 0x68, 0x3d, 0x25, 0x1b, 0x7a, + 0xcf, 0x45, 0x6c, 0x0b, 0x15, 0x82, 0xb4, 0x12, 0xa6, 0x38, 0x11, 0x6b, 0xfd, 0xb7, 0x3b, 0xf7, 0xfb, 0x4b, 0xb7, + 0xdf, 0x76, 0xc1, 0x39, 0x1b, 0x6e, 0x98, 0x58, 0xe0, 0xf4, 0xdb, 0x6d, 0x28, 0xb8, 0x55, 0x0a, 0x3c, 0x28, 0x08, + 0x94, 0x82, 0x0e, 0x14, 0x8c, 0x95, 0x82, 0x23, 0x28, 0x98, 0x28, 0x05, 0xc7, 0x50, 0x70, 0xa3, 0xe7, 0x97, 0x91, + 0xec, 0xee, 0xb1, 0x71, 0x65, 0xd2, 0xa5, 0x42, 0x94, 0x1d, 0x9b, 0x2e, 0x58, 0x4d, 0xf9, 0xb3, 0x5e, 0x6c, 0x92, + 0x74, 0xb1, 0x97, 0x98, 0xb7, 0x73, 0x46, 0x81, 0xa2, 0x5f, 0xe1, 0x99, 0x63, 0x67, 0x31, 0xd8, 0x4d, 0x8b, 0x00, + 0x0c, 0x02, 0x0f, 0x9a, 0x6e, 0x80, 0xc0, 0xa8, 0x2f, 0x67, 0x4e, 0x04, 0xb1, 0x50, 0xe6, 0xb2, 0x78, 0x47, 0x9f, + 0xb3, 0xe4, 0x12, 0x28, 0x2c, 0x4e, 0x5a, 0xaa, 0x54, 0xf2, 0x6b, 0xd8, 0x1d, 0xbc, 0x62, 0xa3, 0xd5, 0x4c, 0x3b, + 0x8f, 0x67, 0x3b, 0x4d, 0x08, 0xd4, 0x57, 0xd0, 0x4b, 0x9d, 0xd4, 0x2f, 0x96, 0x58, 0x96, 0xfc, 0x5b, 0xf4, 0x98, + 0x97, 0xeb, 0x67, 0xd0, 0x37, 0x2d, 0x23, 0x03, 0x16, 0xf8, 0x0e, 0xe0, 0x48, 0xd1, 0xe1, 0x9f, 0x03, 0x9e, 0x95, + 0xe7, 0x0b, 0x5f, 0xe9, 0xcf, 0xe9, 0x8f, 0x2c, 0x4d, 0xfd, 0x99, 0xa8, 0x5f, 0xef, 0x27, 0x18, 0xed, 0xc8, 0xfb, + 0x17, 0x22, 0x10, 0x24, 0x79, 0x41, 0xcd, 0x36, 0x23, 0x89, 0x6f, 0x35, 0xb0, 0xfe, 0x81, 0x05, 0x55, 0xd8, 0x29, + 0x04, 0x36, 0x4c, 0x61, 0xd9, 0xa2, 0x00, 0x36, 0xff, 0x0d, 0x0b, 0xab, 0x85, 0x99, 0x3f, 0xab, 0x16, 0xd1, 0x3a, + 0xc8, 0xd5, 0xbe, 0x49, 0x85, 0x7e, 0xa9, 0xf0, 0x4b, 0x34, 0xd4, 0x61, 0x3c, 0xfb, 0x53, 0xd5, 0xd3, 0x5b, 0xcc, + 0x0a, 0x3e, 0x44, 0x66, 0x90, 0x0d, 0x6d, 0xc4, 0xb1, 0x66, 0x03, 0x0a, 0x7b, 0x51, 0x36, 0xb7, 0xd0, 0xb5, 0xac, + 0xe5, 0x45, 0x86, 0x69, 0xe3, 0xdc, 0xae, 0xab, 0x0e, 0xb5, 0xbd, 0x64, 0x36, 0xf2, 0x5b, 0xae, 0x77, 0x6c, 0x8a, + 0x3f, 0xb6, 0xd3, 0x31, 0x72, 0x84, 0xa0, 0x4d, 0x82, 0x9b, 0xf5, 0x34, 0x8e, 0x32, 0x6b, 0xea, 0x2f, 0x82, 0xf0, + 0xbe, 0xb7, 0x88, 0xa3, 0x38, 0x5d, 0xfa, 0x63, 0xd6, 0x2f, 0x2e, 0xd4, 0x7d, 0x0c, 0xd5, 0xc0, 0xbd, 0x05, 0x5d, + 0xdb, 0x4b, 0xd8, 0x82, 0x5a, 0xcb, 0x48, 0x0c, 0xd3, 0x90, 0xdd, 0xe5, 0xfc, 0xf3, 0xa5, 0xca, 0x54, 0x15, 0x97, + 0x1c, 0xb5, 0x00, 0x8e, 0x94, 0x87, 0x79, 0x80, 0xe0, 0x46, 0xfd, 0xa5, 0x3f, 0xc1, 0xc8, 0x84, 0xb6, 0xd7, 0x49, + 0xd8, 0x42, 0xb3, 0x3b, 0x1b, 0x81, 0x27, 0xf1, 0xed, 0x29, 0xf4, 0x16, 0x1b, 0x5b, 0x29, 0x0b, 0xa7, 0xf8, 0xc6, + 0x42, 0xcf, 0x12, 0x01, 0xc7, 0xc2, 0x8b, 0x38, 0x40, 0x63, 0x8b, 0x3e, 0xbc, 0xee, 0x79, 0x9a, 0xd3, 0x5f, 0x04, + 0x91, 0x45, 0xc3, 0x39, 0x76, 0x96, 0x0a, 0x2c, 0x15, 0x7f, 0xc6, 0x1a, 0xab, 0xbb, 0x9a, 0xd3, 0x87, 0xcb, 0xda, + 0x34, 0x8c, 0x6f, 0x7b, 0xf3, 0x60, 0x32, 0x61, 0x51, 0x1f, 0xfb, 0x2c, 0x0b, 0x59, 0x18, 0x06, 0xcb, 0x34, 0x48, + 0xfb, 0x0b, 0xff, 0x8e, 0x43, 0x3d, 0xdc, 0x04, 0xb5, 0xcd, 0xa1, 0xb6, 0xf7, 0x86, 0xaa, 0x80, 0x01, 0x2f, 0x16, + 0x82, 0xc3, 0xbb, 0xd6, 0xd1, 0x9c, 0xca, 0x38, 0xf7, 0x86, 0xba, 0x4c, 0xd8, 0x7a, 0xe1, 0x27, 0xb3, 0x20, 0xea, + 0x39, 0xb9, 0x7d, 0xb3, 0xa6, 0x85, 0xf1, 0xb8, 0xdb, 0xed, 0xe6, 0xf6, 0x44, 0x3c, 0x39, 0x93, 0x49, 0x6e, 0x8f, + 0xc5, 0xd3, 0x74, 0xea, 0x38, 0xd3, 0x69, 0x6e, 0x07, 0xa2, 0xa0, 0xed, 0x8d, 0x27, 0x6d, 0x2f, 0xb7, 0x6f, 0x95, + 0x1a, 0xb9, 0xcd, 0xf8, 0x53, 0xc2, 0x26, 0x7d, 0x5c, 0x48, 0x64, 0x56, 0xda, 0x3b, 0x76, 0x9c, 0x1c, 0x29, 0xc0, + 0x65, 0x89, 0x36, 0xa1, 0xac, 0xe7, 0x6a, 0xbd, 0x77, 0x4d, 0xad, 0xf8, 0xdc, 0x78, 0xdc, 0x58, 0x6f, 0xe2, 0x27, + 0x9f, 0xae, 0x34, 0x65, 0x14, 0xbe, 0x4f, 0xd5, 0xd6, 0x02, 0x0d, 0xd6, 0x5d, 0x0f, 0x42, 0x76, 0xf5, 0x47, 0x71, + 0x02, 0x7b, 0x36, 0xf1, 0x27, 0xc1, 0x2a, 0xed, 0xb9, 0xde, 0xf2, 0x4e, 0x14, 0xf1, 0xb5, 0x5e, 0x14, 0xe0, 0xde, + 0xeb, 0xa5, 0x71, 0x18, 0x4c, 0x44, 0xd1, 0xa6, 0xbd, 0xe4, 0x7a, 0x46, 0x1f, 0x1d, 0xd6, 0x03, 0x0c, 0xbb, 0xe0, + 0x87, 0xa1, 0x66, 0xb7, 0x53, 0x8d, 0xf9, 0x29, 0xca, 0x97, 0x35, 0x27, 0x25, 0xbc, 0xa0, 0x73, 0xba, 0x7b, 0xb8, + 0xbc, 0x93, 0x6b, 0xde, 0x3d, 0x5a, 0xde, 0xe5, 0x7f, 0x5d, 0xb0, 0x49, 0xe0, 0x6b, 0xad, 0x62, 0x35, 0xb9, 0x0e, + 0xc8, 0xa0, 0x8d, 0xf5, 0x86, 0x65, 0x2a, 0xb6, 0x05, 0x84, 0x36, 0x7c, 0x14, 0x2c, 0x96, 0x71, 0x92, 0xf9, 0x51, + 0x96, 0xe7, 0xc3, 0xab, 0x3c, 0xef, 0x5f, 0x04, 0xad, 0xcb, 0x7f, 0xb4, 0xe8, 0x9c, 0x26, 0x9d, 0x4d, 0x6e, 0x5c, + 0x99, 0xaf, 0x99, 0x6a, 0x33, 0x02, 0xc7, 0x18, 0xda, 0x8b, 0xa8, 0x95, 0xe9, 0x94, 0xac, 0x57, 0x26, 0x24, 0xcb, + 0xea, 0x64, 0x83, 0x52, 0xae, 0x82, 0x27, 0x10, 0x54, 0x78, 0xcd, 0x06, 0x17, 0x8a, 0xfd, 0x09, 0x30, 0x2b, 0x58, + 0x99, 0xfc, 0x0a, 0x9e, 0x6c, 0xe2, 0x19, 0xbf, 0xdb, 0xcd, 0x33, 0xfe, 0x9a, 0xed, 0xc3, 0x33, 0x7e, 0xf7, 0xd5, + 0x79, 0xc6, 0x27, 0x75, 0xbf, 0x82, 0xb7, 0xf1, 0x40, 0x97, 0x1a, 0x06, 0x38, 0x9a, 0x12, 0x8a, 0xd8, 0xf3, 0xf6, + 0x0f, 0xbb, 0x01, 0x08, 0x68, 0x94, 0x83, 0x8e, 0x4e, 0x6e, 0x90, 0xc7, 0xbe, 0x8b, 0x06, 0x7f, 0x4f, 0xd4, 0xe7, + 0xe9, 0x74, 0xf0, 0x2a, 0x56, 0x0a, 0xe4, 0x13, 0x37, 0xbe, 0x28, 0x45, 0x57, 0xa0, 0x37, 0xc2, 0x0a, 0x13, 0xf3, + 0x4f, 0x80, 0x73, 0x36, 0x59, 0x1d, 0x4f, 0xa4, 0xf5, 0x59, 0xbf, 0xdc, 0x85, 0x96, 0x34, 0xf9, 0x14, 0x2e, 0x38, + 0x35, 0x51, 0xe2, 0x8c, 0x65, 0xdc, 0x67, 0xf6, 0xfb, 0xfb, 0xb7, 0x93, 0xd6, 0xdb, 0xd8, 0xc8, 0x83, 0xf4, 0x5d, + 0xd5, 0x01, 0x86, 0xeb, 0x7e, 0x06, 0xea, 0x70, 0x72, 0x6e, 0x41, 0xa6, 0x26, 0x98, 0x86, 0xd7, 0xd4, 0xfc, 0xac, + 0x34, 0xd2, 0x9e, 0xda, 0x90, 0x27, 0xba, 0xaa, 0x1d, 0xc6, 0xdc, 0xfb, 0x60, 0xcd, 0x39, 0x40, 0xcc, 0xdd, 0x85, + 0x7e, 0xc3, 0x13, 0x6a, 0x1e, 0x4c, 0xf2, 0xdc, 0xe8, 0x0b, 0x44, 0x28, 0x07, 0x2d, 0xdb, 0xc5, 0xc4, 0xa5, 0xb7, + 0xd2, 0xa6, 0x81, 0x6b, 0x08, 0x49, 0xfd, 0xf7, 0x16, 0x14, 0xea, 0x5c, 0x59, 0xc8, 0x71, 0xa6, 0x6b, 0x84, 0x3e, + 0x32, 0xb4, 0x50, 0x06, 0x04, 0x1a, 0x60, 0x89, 0x7f, 0xf1, 0x4a, 0x14, 0xd4, 0x6d, 0x38, 0x09, 0x39, 0x68, 0x11, + 0x00, 0x5e, 0xfe, 0x42, 0xae, 0x4d, 0x64, 0x87, 0xd7, 0xc1, 0x87, 0x5c, 0x97, 0xbc, 0x1f, 0x2e, 0xbf, 0xd3, 0x93, + 0x03, 0x68, 0x70, 0x5a, 0x31, 0x1c, 0xd8, 0x61, 0xa1, 0x08, 0xac, 0x44, 0x7a, 0x6b, 0xda, 0xe9, 0xad, 0xf6, 0x6c, + 0x2d, 0x22, 0x64, 0x64, 0xfe, 0xd2, 0x82, 0x2b, 0x3e, 0xd2, 0x5e, 0x4e, 0xf1, 0x94, 0x60, 0x1c, 0xfd, 0x55, 0x0a, + 0xb4, 0x11, 0x2f, 0xaa, 0x48, 0x7f, 0xfa, 0xe3, 0x55, 0x92, 0xc6, 0x49, 0x6f, 0x19, 0x07, 0x51, 0xc6, 0x92, 0x1c, + 0x51, 0x75, 0x89, 0xf8, 0x11, 0xe8, 0xb9, 0x5a, 0xc7, 0x4b, 0x7f, 0x1c, 0x64, 0xf7, 0x3d, 0x87, 0xb3, 0x14, 0x4e, + 0x9f, 0x73, 0x07, 0x4e, 0x63, 0xfd, 0x1e, 0xc7, 0xe6, 0x73, 0x64, 0xfc, 0x92, 0x3a, 0x3b, 0xa3, 0x2e, 0xf3, 0xbe, + 0xf2, 0x96, 0x62, 0x84, 0x00, 0xfb, 0xe1, 0x27, 0xd6, 0x0c, 0xa8, 0x3c, 0x4c, 0xb5, 0x33, 0x61, 0x33, 0x13, 0xa9, + 0x36, 0xc8, 0xe5, 0xc5, 0x1f, 0xbb, 0x63, 0x68, 0x4e, 0x73, 0x31, 0x70, 0x3c, 0xc6, 0x3e, 0x3d, 0xeb, 0xf9, 0x90, + 0x51, 0xcb, 0xdc, 0xa7, 0xe6, 0x88, 0x4d, 0xe3, 0x84, 0x51, 0x3c, 0x59, 0xb7, 0xbb, 0xbc, 0xdb, 0x1f, 0xfc, 0xf6, + 0xe1, 0x37, 0xc3, 0x89, 0xe2, 0xac, 0x25, 0x80, 0x19, 0x3b, 0xa0, 0xd5, 0xcf, 0x33, 0x60, 0x0d, 0x09, 0xf3, 0x63, + 0x0a, 0xdd, 0xd5, 0xd3, 0xf5, 0x7e, 0x63, 0xd8, 0xae, 0x65, 0xcc, 0xcf, 0xbc, 0x84, 0x85, 0x7e, 0x16, 0xdc, 0x08, + 0x9e, 0xb1, 0x7d, 0xb4, 0xbc, 0x13, 0x73, 0x8c, 0x07, 0xde, 0x03, 0x26, 0xa9, 0xd2, 0x15, 0x31, 0x49, 0xd5, 0x62, + 0x9c, 0xa4, 0x7e, 0x6d, 0x34, 0x22, 0x92, 0x45, 0xe5, 0xa4, 0xef, 0x2c, 0xef, 0xd4, 0x23, 0xba, 0x68, 0x26, 0x4f, + 0xea, 0x6a, 0x08, 0xb2, 0x45, 0x30, 0x99, 0x84, 0x2c, 0x2f, 0x4d, 0x74, 0x79, 0x2e, 0x15, 0xe4, 0x48, 0x3c, 0xf8, + 0xa3, 0x34, 0x0e, 0x57, 0x19, 0x6b, 0x46, 0x17, 0x21, 0xc7, 0x73, 0x0a, 0xe4, 0xe0, 0xef, 0x72, 0x5f, 0x3b, 0xc0, + 0x6e, 0xc3, 0x32, 0x71, 0xfa, 0x10, 0x71, 0xd8, 0x6a, 0x97, 0xbb, 0x0e, 0xaf, 0x64, 0xa7, 0xcd, 0x86, 0x81, 0x98, + 0x70, 0x2c, 0x11, 0xf5, 0xd6, 0x6c, 0x97, 0x97, 0xc9, 0xa8, 0xab, 0xb2, 0x28, 0x2f, 0x0f, 0xe6, 0xcf, 0xd9, 0x63, + 0x2f, 0x9a, 0xf7, 0xd8, 0x0b, 0xb1, 0xc7, 0xb6, 0xaf, 0xcc, 0xc7, 0x53, 0x17, 0xfe, 0xeb, 0x17, 0x03, 0xea, 0x39, + 0x5a, 0x7b, 0x79, 0xa7, 0xb9, 0xcb, 0x3b, 0xcd, 0xf2, 0x96, 0x77, 0x1a, 0x82, 0x46, 0x7b, 0x10, 0xd3, 0xf6, 0x0c, + 0xd3, 0xd1, 0xa0, 0x10, 0xfe, 0x38, 0xa5, 0x57, 0xee, 0x21, 0xbc, 0x83, 0x56, 0x9d, 0xfa, 0x3b, 0x6f, 0xfb, 0x56, + 0xa7, 0xbd, 0x24, 0x88, 0xb6, 0x61, 0x67, 0xfe, 0x68, 0xc4, 0x26, 0xbd, 0x69, 0x3c, 0x5e, 0xa5, 0xff, 0xe2, 0xfd, + 0xe7, 0x48, 0xdc, 0x4a, 0x08, 0x2a, 0x70, 0x44, 0x53, 0x50, 0x94, 0xdc, 0x30, 0x01, 0x61, 0x2d, 0xe7, 0xa9, 0x47, + 0xe1, 0x91, 0x3d, 0xfb, 0xb0, 0x61, 0x91, 0x37, 0x23, 0xfa, 0x4f, 0x9b, 0xa5, 0xcd, 0x24, 0xe6, 0x0b, 0xd0, 0xb2, + 0x15, 0x1d, 0x0f, 0xc7, 0x06, 0x9f, 0x4d, 0xa7, 0xdb, 0xdc, 0xdd, 0x4b, 0xf1, 0xa5, 0x2b, 0x71, 0xa8, 0xf0, 0x73, + 0x8b, 0x3b, 0xa6, 0x6c, 0x87, 0xba, 0x69, 0x8d, 0xd4, 0xa0, 0x6e, 0x39, 0x10, 0x8a, 0xba, 0x7b, 0x52, 0xf9, 0xc7, + 0x2f, 0x0e, 0xe1, 0x3f, 0xe2, 0xea, 0x7f, 0xcd, 0x9a, 0x18, 0xf5, 0xb7, 0x65, 0x4b, 0x70, 0x62, 0x95, 0x90, 0x11, + 0xdf, 0xbf, 0xfe, 0x74, 0xfa, 0xb0, 0x06, 0x7b, 0xd7, 0x26, 0x53, 0xaa, 0x6a, 0xed, 0xef, 0xe3, 0x18, 0x52, 0x77, + 0xd6, 0xab, 0x0b, 0xf4, 0x90, 0xb1, 0x7b, 0x36, 0x80, 0x46, 0xe2, 0x1e, 0x41, 0x5a, 0x7c, 0x1d, 0xdb, 0xd0, 0x55, + 0xe2, 0xf5, 0xa6, 0xab, 0xc4, 0xab, 0xdd, 0x57, 0x89, 0x1f, 0xf6, 0xba, 0x4a, 0xbc, 0xfa, 0xea, 0x57, 0x89, 0xd7, + 0xf5, 0xab, 0xc4, 0x45, 0x2c, 0xec, 0x67, 0xcd, 0xb7, 0x2b, 0xfe, 0xf3, 0x23, 0x29, 0xe5, 0xce, 0xe3, 0x41, 0xc7, + 0xa1, 0x90, 0xc7, 0x17, 0x7f, 0xf8, 0x62, 0x81, 0x0b, 0xf1, 0x3d, 0x9a, 0x93, 0x15, 0x57, 0x0b, 0x4e, 0xd9, 0xf1, + 0x3b, 0x4a, 0x71, 0x18, 0x47, 0xb3, 0x9f, 0x41, 0x29, 0x0b, 0xe2, 0xc0, 0x44, 0x79, 0x11, 0xa4, 0x3f, 0xc7, 0xcb, + 0xd5, 0xf2, 0x2d, 0xc0, 0xfa, 0x18, 0xa4, 0xc1, 0x28, 0x64, 0xd2, 0x13, 0x99, 0xcc, 0xdf, 0xb8, 0x4c, 0x1c, 0x2c, + 0x4e, 0xc5, 0x4f, 0xff, 0x4e, 0xfc, 0x44, 0x9b, 0x54, 0xfe, 0x9b, 0xec, 0xea, 0xf4, 0xe6, 0x8b, 0x88, 0x50, 0x02, + 0x2a, 0x9d, 0x7e, 0xf8, 0x65, 0xe4, 0x22, 0x36, 0x1a, 0x46, 0x29, 0xec, 0x1d, 0x36, 0xc2, 0x61, 0xb5, 0x4b, 0xcd, + 0xca, 0x30, 0x65, 0x08, 0xae, 0xba, 0x18, 0x7e, 0x11, 0xaf, 0x52, 0x36, 0x89, 0x6f, 0x23, 0xdd, 0x8c, 0xa4, 0x93, + 0x01, 0x68, 0x38, 0x65, 0x1b, 0x4c, 0x1e, 0xf9, 0x01, 0x19, 0xe5, 0x38, 0x69, 0xe9, 0x90, 0xbb, 0x74, 0xb5, 0xb4, + 0x48, 0xd5, 0x6c, 0xe1, 0x10, 0x75, 0x99, 0xe5, 0xe8, 0x51, 0xab, 0x15, 0x0f, 0x1e, 0xd6, 0x52, 0x98, 0x6a, 0xc4, + 0x36, 0x97, 0x0a, 0xa7, 0xad, 0x48, 0x08, 0x17, 0x45, 0x1c, 0x8c, 0x86, 0x89, 0xe3, 0x6f, 0xc8, 0x75, 0xb5, 0x78, + 0x0b, 0x51, 0x44, 0xf2, 0x15, 0x9f, 0x0f, 0x1e, 0x15, 0x82, 0x1e, 0x5f, 0x2a, 0x68, 0x7c, 0x77, 0xc3, 0x92, 0xd0, + 0xbf, 0x6f, 0x19, 0x79, 0x1c, 0xfd, 0x08, 0x08, 0x78, 0x15, 0xdf, 0x46, 0x6a, 0x05, 0x4c, 0xd6, 0xd2, 0xb0, 0x96, + 0x1a, 0xe3, 0x97, 0x80, 0xe3, 0x8a, 0xd2, 0x03, 0x48, 0x93, 0x3b, 0x63, 0x7f, 0x37, 0xe9, 0xdf, 0x7f, 0x18, 0xb9, + 0x79, 0x1e, 0xcb, 0x0f, 0xfd, 0xb2, 0xdc, 0xe3, 0x33, 0x4f, 0x9f, 0x3e, 0xda, 0x3c, 0xec, 0x72, 0x7a, 0xf6, 0x86, + 0xd6, 0xc6, 0xc6, 0x5d, 0x00, 0xbd, 0xb8, 0x88, 0x57, 0xe3, 0x39, 0x1a, 0xba, 0x7e, 0xbd, 0xf1, 0x66, 0x00, 0x13, + 0xb3, 0x94, 0xca, 0xa1, 0x57, 0x8a, 0x0a, 0x2c, 0xe0, 0xf7, 0x5f, 0x43, 0x00, 0xce, 0xff, 0x21, 0x1a, 0xea, 0xab, + 0x86, 0xdf, 0xe2, 0x83, 0x87, 0x2d, 0xde, 0x3e, 0x24, 0xd3, 0xe4, 0xa1, 0x2d, 0x84, 0x72, 0xad, 0x99, 0xc8, 0xe4, + 0x55, 0xa4, 0xa9, 0x61, 0xe4, 0x36, 0x45, 0xc8, 0x13, 0x5f, 0x61, 0x36, 0x5d, 0xd3, 0xb9, 0xa3, 0x81, 0xc9, 0x38, + 0xb5, 0xaa, 0x10, 0x19, 0x6e, 0xf2, 0xc0, 0x90, 0x7c, 0x55, 0xdf, 0x2d, 0x82, 0xc8, 0xc4, 0x28, 0xf0, 0xf5, 0x37, + 0xfe, 0x1d, 0xc4, 0x41, 0x06, 0xe2, 0x56, 0x7d, 0x05, 0x85, 0xa6, 0xea, 0x37, 0x07, 0xa9, 0x9e, 0xf4, 0x46, 0x4c, + 0x08, 0x2d, 0xde, 0xf0, 0x1b, 0x4d, 0xd3, 0x34, 0x79, 0x8d, 0xd0, 0xe4, 0x3d, 0x02, 0xcb, 0xf1, 0x3a, 0x00, 0xda, + 0x92, 0x7c, 0x79, 0x47, 0x25, 0x70, 0x33, 0x40, 0x9d, 0xac, 0x28, 0xe0, 0xa1, 0xfe, 0x3a, 0x8e, 0x28, 0x10, 0x17, + 0x7a, 0x08, 0xd3, 0xe6, 0x27, 0x10, 0x11, 0xb8, 0xa7, 0xe1, 0x85, 0x1d, 0xdf, 0x72, 0x49, 0xb0, 0xe6, 0xd0, 0xe3, + 0xb0, 0xcf, 0x9a, 0x63, 0xc2, 0x45, 0x0a, 0x15, 0x04, 0xad, 0x43, 0x25, 0xc4, 0xb3, 0xc9, 0x1a, 0x68, 0x23, 0xde, + 0x8b, 0xee, 0xb2, 0x05, 0x8b, 0x56, 0x3a, 0xe6, 0x84, 0xc2, 0x18, 0x7d, 0x50, 0xe7, 0x15, 0x31, 0x5b, 0x40, 0x6d, + 0x9a, 0x5b, 0xce, 0xe9, 0x2c, 0x4c, 0x39, 0x49, 0xf5, 0xcd, 0x31, 0x57, 0x6c, 0xa6, 0x9c, 0xb6, 0x55, 0x4f, 0x08, + 0x3e, 0xa5, 0x71, 0xd5, 0x91, 0x8b, 0x2c, 0xa1, 0x01, 0x06, 0x45, 0xc7, 0xe0, 0xe2, 0x22, 0x81, 0xf6, 0x96, 0x5f, + 0x9d, 0x34, 0xa9, 0x91, 0xf1, 0x2b, 0x82, 0xa2, 0xc4, 0xa8, 0x83, 0xe1, 0xfd, 0x84, 0xc0, 0x44, 0x1b, 0xe1, 0x8c, + 0x6b, 0x70, 0x36, 0x0c, 0xfa, 0x13, 0xbb, 0xa7, 0x83, 0x84, 0x50, 0xf5, 0x89, 0xdd, 0x83, 0xed, 0xdf, 0x6b, 0x90, + 0xa6, 0xe8, 0x5b, 0xc8, 0xb5, 0x09, 0xa1, 0xfe, 0xc7, 0x10, 0xac, 0x6a, 0xcb, 0x06, 0x72, 0xf2, 0x2d, 0x54, 0x1c, + 0x51, 0x0c, 0x59, 0x9d, 0xc5, 0x26, 0xe6, 0x26, 0xfe, 0xad, 0x46, 0x1c, 0x5b, 0x0d, 0x5b, 0xc3, 0x78, 0xe6, 0x3a, + 0xce, 0x41, 0xad, 0x3e, 0x08, 0xb2, 0x9b, 0x6a, 0x1b, 0x66, 0x36, 0x70, 0x1d, 0x2b, 0x78, 0x66, 0x7b, 0xfd, 0xda, + 0x19, 0xad, 0xc4, 0x92, 0x1c, 0xa2, 0xf8, 0xeb, 0xf4, 0xc9, 0xba, 0x55, 0xdb, 0x90, 0x46, 0xd5, 0x64, 0x1e, 0xfb, + 0x96, 0x73, 0xf9, 0xd7, 0xb0, 0x7e, 0xf4, 0x53, 0x24, 0x4b, 0xca, 0x6b, 0x32, 0x84, 0x68, 0xc8, 0x2d, 0xd8, 0x46, + 0x7f, 0xd1, 0x9e, 0x6b, 0x2d, 0xda, 0x3e, 0x86, 0x31, 0x94, 0xe9, 0xb2, 0x85, 0x4f, 0x99, 0x0a, 0xa0, 0xf2, 0xc5, + 0xb4, 0x4a, 0xe1, 0x78, 0xdc, 0x55, 0x56, 0x68, 0xf4, 0xb6, 0x72, 0x0b, 0x08, 0x7f, 0xc3, 0xf1, 0x69, 0x8f, 0x20, + 0x2e, 0x01, 0xd4, 0x80, 0xd8, 0xe9, 0x3b, 0x01, 0xae, 0x96, 0x65, 0x70, 0xe5, 0x43, 0x72, 0x7f, 0x60, 0x78, 0xe8, + 0xa0, 0x0e, 0x4d, 0xc2, 0x6b, 0x3e, 0xee, 0x1e, 0x08, 0x92, 0x45, 0x93, 0x32, 0xc0, 0xca, 0xf9, 0xb5, 0x3f, 0xb8, + 0x12, 0x45, 0x81, 0xa4, 0x02, 0x71, 0x03, 0x45, 0xc9, 0xe3, 0x08, 0x17, 0x3f, 0x6d, 0xb7, 0x60, 0x2f, 0x2e, 0x06, + 0x1b, 0x50, 0x44, 0x30, 0xd9, 0x4c, 0x11, 0x8a, 0x43, 0xe4, 0x6a, 0x74, 0x0b, 0x6e, 0x09, 0x46, 0x74, 0xe3, 0x4a, + 0xcc, 0x84, 0x4d, 0x61, 0xd1, 0x26, 0xe0, 0xb1, 0x28, 0xf7, 0x95, 0x5a, 0x07, 0xbb, 0xa5, 0xd6, 0xd9, 0x2e, 0xa9, + 0x35, 0xb9, 0x53, 0xdd, 0x26, 0xfe, 0x52, 0xf1, 0xc8, 0x13, 0xcc, 0xb9, 0xea, 0x98, 0x57, 0x12, 0x75, 0xa3, 0xf7, + 0x95, 0x68, 0x55, 0x83, 0x46, 0x56, 0x82, 0x28, 0xfe, 0x56, 0x2e, 0x28, 0x42, 0xa1, 0xae, 0xca, 0xc6, 0x2f, 0x0a, + 0xd9, 0x38, 0xdd, 0x6a, 0x0a, 0x47, 0x1a, 0xc1, 0xfd, 0x2b, 0x4e, 0x6a, 0xf2, 0x76, 0x50, 0x38, 0xab, 0x15, 0x3d, + 0x55, 0xdc, 0xaf, 0x8a, 0x8b, 0x86, 0xe2, 0xd4, 0x27, 0x6e, 0x19, 0x65, 0xdf, 0xbe, 0x72, 0xd5, 0xc2, 0xfb, 0xaa, + 0x28, 0x07, 0xa9, 0x3b, 0x76, 0x59, 0x16, 0xab, 0xcb, 0xa6, 0xec, 0x7e, 0xa3, 0xbe, 0x56, 0x16, 0x89, 0xf4, 0x93, + 0x21, 0x04, 0x0b, 0x31, 0x7d, 0x45, 0xaf, 0x2d, 0x6d, 0x20, 0xb0, 0x93, 0x0d, 0x6e, 0x7d, 0xbb, 0xa5, 0xf3, 0x94, + 0x2f, 0xa1, 0xd0, 0xc2, 0xab, 0x32, 0x08, 0xc4, 0xef, 0xd5, 0xba, 0xe1, 0x94, 0xc7, 0x43, 0x9e, 0x9f, 0xef, 0x20, + 0x5e, 0xd4, 0x1c, 0x55, 0x91, 0x8f, 0x3b, 0xd3, 0x22, 0xf3, 0x5c, 0xac, 0x5a, 0x07, 0x4a, 0x42, 0x9c, 0x35, 0xf7, + 0x8c, 0x29, 0xcb, 0xe8, 0x79, 0x8d, 0x9e, 0xf8, 0x2e, 0x5f, 0x3a, 0xc9, 0x2a, 0xc2, 0xd8, 0xf6, 0x56, 0x96, 0xf8, + 0xe3, 0x4f, 0x4a, 0x97, 0x85, 0x9c, 0x13, 0x64, 0xc0, 0x65, 0x4d, 0x41, 0xdf, 0xc7, 0x50, 0x90, 0xac, 0x67, 0x7b, + 0xa9, 0x22, 0x7d, 0xe9, 0x3d, 0x76, 0xda, 0xfe, 0x8b, 0xe9, 0x61, 0x45, 0x28, 0xea, 0x75, 0xca, 0x22, 0xf3, 0x0d, + 0xfd, 0xc8, 0xe6, 0xab, 0xc5, 0x68, 0xad, 0xca, 0x56, 0x15, 0x91, 0x6b, 0x5d, 0xcc, 0xaa, 0x7e, 0x76, 0x3a, 0x9d, + 0x96, 0x05, 0x8d, 0x8e, 0x76, 0x88, 0xc2, 0xc2, 0xc7, 0x8e, 0xe3, 0x54, 0xfb, 0xbe, 0x1d, 0xed, 0x16, 0xca, 0x6d, + 0xbb, 0x8d, 0x3d, 0x46, 0xdc, 0xee, 0xc2, 0x5f, 0x1d, 0x1d, 0xb9, 0x5d, 0xec, 0xec, 0x92, 0x59, 0x44, 0x9f, 0x8c, + 0x21, 0x82, 0x8c, 0x2d, 0xd2, 0xde, 0x98, 0xa1, 0x0e, 0xc6, 0x56, 0x36, 0x34, 0x1a, 0x0e, 0x58, 0x33, 0x30, 0x15, + 0x71, 0xc5, 0xaa, 0x70, 0x34, 0x94, 0x87, 0xd7, 0x84, 0xf7, 0xe2, 0x23, 0xb8, 0x51, 0xd6, 0x75, 0x99, 0x36, 0x0e, + 0xab, 0xe3, 0xfc, 0xa5, 0x54, 0x4f, 0x83, 0x03, 0x70, 0x2d, 0x14, 0xda, 0x24, 0x9f, 0xc5, 0xbf, 0xa5, 0xfc, 0xff, + 0xc5, 0xf2, 0xae, 0x6c, 0x3f, 0xd2, 0x05, 0x89, 0x76, 0xb1, 0x5b, 0xa8, 0xd7, 0x4d, 0x6b, 0x40, 0x5a, 0x19, 0x4c, + 0x55, 0x05, 0x3a, 0x28, 0xe9, 0x4b, 0x09, 0x40, 0x1a, 0xc4, 0xef, 0xc8, 0x31, 0xc3, 0x14, 0x17, 0x22, 0xc4, 0x22, + 0x7d, 0x1d, 0x8c, 0xc1, 0x7c, 0xde, 0x45, 0xfd, 0x41, 0x69, 0x4d, 0x80, 0x36, 0xbe, 0x36, 0xb6, 0xbd, 0xc4, 0xfd, + 0x55, 0xbd, 0x96, 0x00, 0x0c, 0x28, 0x73, 0x61, 0x13, 0xa2, 0x21, 0x81, 0x56, 0x59, 0xdc, 0xd4, 0x4b, 0xf9, 0x56, + 0xd5, 0xb3, 0x89, 0x8e, 0x21, 0xb8, 0xe6, 0x2a, 0x04, 0x5b, 0x68, 0x0b, 0x60, 0xb0, 0x7c, 0xf9, 0xe1, 0xb3, 0x05, + 0x53, 0xac, 0xae, 0x47, 0x17, 0xa7, 0x1c, 0xd7, 0xaf, 0x85, 0x67, 0x67, 0x4a, 0xfb, 0x1f, 0xe5, 0x8b, 0x3f, 0x34, + 0x0a, 0xf4, 0x2e, 0x4a, 0x12, 0x3a, 0x6e, 0x2d, 0xee, 0x19, 0x7b, 0xd5, 0x5e, 0x04, 0xd1, 0xfe, 0x75, 0xfd, 0xbb, + 0xbd, 0xeb, 0xc2, 0x81, 0xb1, 0x77, 0x65, 0x38, 0x71, 0xc8, 0x72, 0x21, 0x1b, 0xfc, 0xa0, 0x08, 0x14, 0x55, 0xaf, + 0x63, 0x1d, 0x5b, 0x11, 0x97, 0x7f, 0xb1, 0x1a, 0x0c, 0x4f, 0xce, 0xee, 0x16, 0xa1, 0x76, 0xc3, 0x12, 0x48, 0xed, + 0x33, 0xd0, 0x5d, 0xdb, 0xd1, 0x35, 0xf4, 0xa1, 0x0d, 0xa2, 0xd9, 0x40, 0xff, 0xe5, 0xe2, 0x8d, 0xd5, 0xd5, 0xcf, + 0x40, 0x45, 0x7b, 0x33, 0xc3, 0x63, 0xef, 0xdc, 0xbf, 0x67, 0xc9, 0xb5, 0xa7, 0x6b, 0x98, 0xc1, 0x87, 0x0e, 0x3c, + 0x2c, 0xd3, 0x3c, 0x7d, 0x8f, 0x44, 0x11, 0x9a, 0xc8, 0xf5, 0xa6, 0x03, 0xc9, 0x71, 0xbd, 0xae, 0xe6, 0x7a, 0x87, + 0xf6, 0x51, 0x57, 0x3f, 0xfd, 0x46, 0xd3, 0x4e, 0x26, 0x6c, 0x9a, 0x9e, 0xe2, 0x15, 0xed, 0x04, 0xcf, 0x08, 0xfa, + 0xad, 0x69, 0xf6, 0x38, 0x4c, 0x2d, 0x57, 0x5b, 0xf3, 0x47, 0x4d, 0x9b, 0x06, 0x61, 0xd8, 0xd3, 0x1e, 0x4f, 0xbd, + 0xe9, 0xe1, 0xf4, 0x45, 0x9f, 0x17, 0xe7, 0xdf, 0x94, 0xaa, 0x9b, 0xf4, 0xaf, 0xa7, 0x34, 0x4b, 0xb3, 0x24, 0xfe, + 0xc4, 0xb8, 0xd9, 0x89, 0x26, 0x2f, 0x8f, 0xd5, 0xa6, 0x5e, 0xfd, 0x4b, 0x6e, 0x77, 0x34, 0x9e, 0x7a, 0x45, 0x75, + 0xec, 0xe3, 0x81, 0xec, 0xe4, 0xc9, 0x81, 0xe8, 0xfa, 0x89, 0x8a, 0x26, 0xd7, 0x6a, 0x42, 0x94, 0xab, 0xf3, 0x31, + 0xce, 0xc4, 0xf8, 0x4e, 0x20, 0x0e, 0xa3, 0x74, 0xd7, 0x85, 0x1e, 0xe8, 0xda, 0x64, 0xa0, 0xff, 0xe8, 0x7a, 0x5d, + 0xd3, 0x75, 0x8f, 0xec, 0xa3, 0xee, 0xd8, 0x31, 0x0f, 0xed, 0x43, 0xab, 0x6d, 0x1f, 0x99, 0x5d, 0xab, 0x6b, 0x76, + 0xff, 0xd6, 0x1d, 0x5b, 0x87, 0xf6, 0xa1, 0xe9, 0x58, 0x5d, 0x28, 0xb4, 0xba, 0x56, 0xf7, 0xc6, 0x3a, 0xec, 0x8e, + 0x1d, 0x2c, 0xf5, 0xec, 0x4e, 0xc7, 0x72, 0x1d, 0xbb, 0xd3, 0x31, 0x3b, 0xf6, 0xd1, 0x91, 0xe5, 0xb6, 0xed, 0xa3, + 0xa3, 0xf3, 0x4e, 0xd7, 0x6e, 0xc3, 0xbb, 0x76, 0x7b, 0xdc, 0xb6, 0x5d, 0xd7, 0x82, 0xbf, 0xcc, 0xae, 0xed, 0xd1, + 0x0f, 0xd7, 0xb5, 0xdb, 0xae, 0xe9, 0x84, 0x1d, 0xcf, 0x3e, 0x7a, 0x61, 0xe2, 0xdf, 0x58, 0xcd, 0xc4, 0xbf, 0x00, + 0x8c, 0xf9, 0xc2, 0xf6, 0x8e, 0xe8, 0x17, 0x02, 0xbc, 0x39, 0xec, 0xfe, 0xaa, 0x1f, 0x6c, 0x1c, 0x83, 0x4b, 0x63, + 0xe8, 0x76, 0xec, 0x76, 0xdb, 0x3c, 0x74, 0xed, 0x6e, 0x7b, 0x6e, 0x1d, 0x7a, 0xf6, 0xd1, 0xf1, 0xd8, 0x72, 0xed, + 0xe3, 0x63, 0xd3, 0xb1, 0xda, 0xb6, 0x67, 0xba, 0xf6, 0x61, 0x1b, 0x7f, 0xb4, 0x6d, 0xef, 0xe6, 0xf8, 0x85, 0x7d, + 0xd4, 0x99, 0x1f, 0xd9, 0x87, 0x1f, 0x0f, 0xbb, 0xb6, 0xd7, 0x9e, 0xb7, 0x8f, 0x6c, 0xef, 0xf8, 0xe6, 0xc8, 0x3e, + 0x9c, 0x5b, 0xde, 0xd1, 0xd6, 0x96, 0xae, 0x67, 0x03, 0x8e, 0xf0, 0x35, 0xbc, 0x30, 0xf9, 0x0b, 0xf8, 0x33, 0xc7, + 0xb6, 0xff, 0x45, 0x30, 0x69, 0xbd, 0xe9, 0x0b, 0xbb, 0x7b, 0x3c, 0xa6, 0xea, 0x50, 0x60, 0x89, 0x1a, 0xd0, 0xe4, + 0xc6, 0xa2, 0xcf, 0x22, 0x38, 0x4b, 0x00, 0x12, 0x7f, 0xf8, 0xc7, 0x6e, 0x2c, 0xf8, 0x30, 0x7d, 0xf7, 0x7f, 0x0a, + 0x47, 0x4e, 0x39, 0x64, 0xae, 0xfc, 0x86, 0xff, 0x43, 0x49, 0x5f, 0x86, 0xe6, 0xf9, 0x26, 0x45, 0xc5, 0xfb, 0xdd, + 0x8a, 0x8a, 0x37, 0xab, 0x7d, 0x14, 0x15, 0xef, 0xbf, 0xba, 0xa2, 0xe2, 0xbc, 0x6a, 0x27, 0xff, 0xbe, 0x1a, 0x9b, + 0xfe, 0xd7, 0x75, 0xf5, 0x1a, 0x12, 0xf8, 0xad, 0xcb, 0x8b, 0xd5, 0x15, 0x44, 0x57, 0x7a, 0x1f, 0x0f, 0xde, 0xac, + 0x4a, 0x46, 0x60, 0x31, 0xd0, 0xd8, 0xf7, 0x31, 0xd1, 0xd8, 0xdf, 0x57, 0x03, 0xb0, 0x3c, 0xe1, 0x7c, 0x49, 0x30, + 0xb1, 0xe6, 0x7e, 0x38, 0x95, 0x3c, 0x0d, 0x94, 0xf4, 0xb1, 0x18, 0xbc, 0x12, 0xe0, 0xb8, 0x06, 0x75, 0xd8, 0x6a, + 0x11, 0xa5, 0xbd, 0x23, 0x07, 0x0e, 0x52, 0x6f, 0x9a, 0xe4, 0x95, 0xc6, 0xb6, 0x88, 0x47, 0x75, 0xcd, 0xbd, 0x26, + 0x36, 0xbe, 0x47, 0xa3, 0xc0, 0x66, 0xe8, 0x6e, 0x1d, 0xae, 0x06, 0xd6, 0x36, 0xc2, 0x68, 0x12, 0xd8, 0xb9, 0xa6, + 0xf7, 0x65, 0xd3, 0xbc, 0x8a, 0x31, 0xe6, 0xe6, 0x9e, 0x42, 0x4f, 0xaa, 0xed, 0xdd, 0xb2, 0x69, 0xdf, 0xae, 0x61, + 0x36, 0x7c, 0xbe, 0xd4, 0x7c, 0x8b, 0x5d, 0xa1, 0x04, 0x5c, 0x45, 0x55, 0x25, 0xb3, 0x5a, 0x23, 0x42, 0x0a, 0xee, + 0xbe, 0x30, 0x3e, 0x2c, 0x58, 0x4b, 0x47, 0x43, 0x7e, 0xc7, 0x51, 0xde, 0x95, 0x60, 0xaa, 0x06, 0x8b, 0xcf, 0xd6, + 0xc8, 0x71, 0x07, 0xbf, 0x03, 0xeb, 0xc8, 0x39, 0x9e, 0x51, 0xac, 0xe2, 0x79, 0xad, 0xc0, 0xa5, 0xcb, 0x4c, 0x3e, + 0x77, 0xd7, 0x75, 0xe6, 0x71, 0xa3, 0xa9, 0xb2, 0xcb, 0x16, 0x82, 0x0b, 0xc2, 0xcf, 0x93, 0x61, 0x70, 0x4e, 0xc6, + 0xdb, 0x68, 0xfb, 0xbc, 0x0d, 0x98, 0xa8, 0xf7, 0x18, 0x16, 0xb1, 0xc9, 0x1f, 0xd4, 0xb8, 0x00, 0xeb, 0x29, 0x64, + 0xc1, 0xee, 0x21, 0x9b, 0xa6, 0xf0, 0xa8, 0x1e, 0x5a, 0x31, 0xf7, 0xb7, 0x18, 0xd8, 0xa8, 0x80, 0x39, 0x10, 0xb4, + 0x86, 0xde, 0x66, 0x93, 0x23, 0x9d, 0x47, 0xd6, 0x25, 0x15, 0xb5, 0xdb, 0x39, 0x36, 0xdd, 0x23, 0xd3, 0x3e, 0xee, + 0x18, 0xb9, 0xd8, 0x70, 0x2a, 0xc8, 0x12, 0x42, 0xc0, 0x28, 0x5a, 0x76, 0x33, 0x88, 0x82, 0x2c, 0xf0, 0xc3, 0x1c, + 0xf8, 0xe3, 0xf2, 0xad, 0xe2, 0x9f, 0xab, 0x34, 0x83, 0x31, 0x0a, 0xa6, 0x17, 0x0d, 0xc2, 0xad, 0x11, 0xcb, 0x6e, + 0x19, 0x8b, 0x36, 0x28, 0xcb, 0xab, 0xf6, 0xe5, 0x7f, 0x9e, 0xb5, 0x6d, 0x4e, 0x96, 0x2c, 0xa3, 0x2c, 0xe2, 0xeb, + 0x43, 0x18, 0x43, 0xe7, 0x43, 0xf3, 0xa7, 0x4d, 0x04, 0xf7, 0x9f, 0xbb, 0x09, 0x6e, 0xc6, 0xf6, 0x21, 0xb8, 0xff, + 0xfc, 0xea, 0x04, 0xf7, 0x27, 0x95, 0xe0, 0x96, 0x7c, 0x81, 0x0a, 0xa9, 0xf3, 0x07, 0x7c, 0x6e, 0x41, 0x50, 0xe7, + 0xe7, 0xfa, 0x01, 0x31, 0xf0, 0xba, 0x92, 0x6c, 0xf7, 0x63, 0x29, 0x7b, 0x10, 0x0a, 0x45, 0x30, 0x08, 0x2d, 0x65, + 0x2a, 0x81, 0x44, 0xb4, 0x32, 0xa5, 0x3a, 0xc0, 0x7c, 0x1b, 0x65, 0xa1, 0xfd, 0x9e, 0x5f, 0xfc, 0x40, 0xc9, 0xf3, + 0x26, 0x4e, 0x16, 0x3e, 0x06, 0xe0, 0xd3, 0x31, 0xeb, 0x20, 0x3c, 0x38, 0xe0, 0x7f, 0x36, 0x8e, 0xa3, 0x89, 0xd4, + 0x54, 0xb0, 0xc1, 0x25, 0x71, 0xdc, 0xfa, 0x3d, 0xf3, 0x13, 0xdd, 0xa4, 0xd7, 0x30, 0xb9, 0xcf, 0xda, 0xce, 0x33, + 0xef, 0xf0, 0xd9, 0x91, 0x03, 0xff, 0xbb, 0xac, 0x9d, 0x9b, 0xbc, 0xe2, 0x22, 0x8e, 0x20, 0xf1, 0x89, 0xa8, 0xb9, + 0xa9, 0xda, 0x2d, 0x63, 0x9f, 0x8a, 0x5a, 0xc7, 0xcd, 0x95, 0x26, 0xfe, 0x7d, 0x51, 0xa7, 0xb1, 0xc6, 0x3c, 0x5e, + 0x29, 0xdd, 0x6a, 0xe8, 0x4d, 0x10, 0xad, 0x40, 0xf6, 0xa6, 0xd4, 0x50, 0x5f, 0xf3, 0xe1, 0x16, 0xe3, 0x62, 0xed, + 0xfc, 0xaa, 0xc8, 0xae, 0x24, 0xb2, 0xbc, 0xec, 0xc4, 0x20, 0x57, 0x5b, 0x38, 0x18, 0x9b, 0x1d, 0xf3, 0x0b, 0x69, + 0x90, 0xdb, 0x50, 0x4c, 0x90, 0x4f, 0x13, 0x94, 0x25, 0xab, 0x68, 0xdc, 0xc2, 0x9f, 0xfe, 0x28, 0x6d, 0x05, 0x07, + 0x10, 0x9d, 0x15, 0x3f, 0x6c, 0xe0, 0xac, 0xf9, 0xa7, 0x4e, 0x91, 0x8a, 0x22, 0x15, 0xb3, 0xe2, 0x3f, 0xcb, 0xcc, + 0x84, 0x12, 0xd8, 0xe2, 0xd4, 0x5a, 0x03, 0xff, 0x99, 0x6c, 0xf8, 0x2c, 0x33, 0x21, 0x89, 0x2c, 0x4c, 0xf7, 0xd3, + 0xa7, 0x54, 0x0b, 0xd2, 0x3a, 0xd2, 0xb0, 0xce, 0xc6, 0x45, 0x78, 0x37, 0xcd, 0x9f, 0xc5, 0x14, 0xe1, 0xad, 0x37, + 0x36, 0xe3, 0xe7, 0xcf, 0x4f, 0x07, 0xae, 0xc1, 0x93, 0x92, 0x96, 0x32, 0x68, 0x9d, 0xef, 0x67, 0x7c, 0x60, 0x34, + 0xba, 0xc5, 0x2d, 0xe1, 0xce, 0xe4, 0x08, 0x13, 0x65, 0x4e, 0xbd, 0x20, 0xa3, 0x05, 0x29, 0x19, 0x7d, 0x61, 0x04, + 0x20, 0xea, 0xc8, 0x5b, 0x57, 0xdb, 0x76, 0x6c, 0x47, 0x97, 0x0d, 0xa7, 0xc1, 0x6c, 0xb0, 0x8e, 0x33, 0x1f, 0x72, + 0x03, 0x85, 0xf1, 0x0c, 0x7c, 0x6b, 0xb2, 0x20, 0x0b, 0x21, 0xd1, 0x0c, 0x38, 0xd9, 0x2c, 0xe8, 0x5e, 0x9e, 0x73, + 0x8b, 0x67, 0x3f, 0xf9, 0x84, 0xc9, 0x06, 0x85, 0x5b, 0x1d, 0x46, 0x1c, 0xfa, 0x11, 0x0e, 0xc3, 0x96, 0xde, 0x82, + 0x54, 0x97, 0x2c, 0x49, 0x2d, 0xd5, 0x83, 0xa0, 0xa7, 0x41, 0x1b, 0x48, 0x43, 0x8f, 0x00, 0xa6, 0x89, 0xbf, 0x80, + 0x98, 0xec, 0xeb, 0xdc, 0xe4, 0x94, 0x56, 0xe7, 0xa4, 0x56, 0x73, 0x5f, 0x1c, 0x99, 0x9a, 0xe7, 0x9a, 0x9a, 0x03, + 0xe4, 0x56, 0xcf, 0xcd, 0x75, 0x7e, 0xd5, 0xdf, 0xa5, 0x04, 0x25, 0xfa, 0xf2, 0x98, 0xc6, 0x41, 0xea, 0x4f, 0x2e, + 0x5e, 0xce, 0x28, 0x80, 0x64, 0x4b, 0x89, 0x96, 0x1e, 0x90, 0x22, 0xe4, 0x82, 0xdd, 0x65, 0x06, 0x26, 0x62, 0xe1, + 0x55, 0x02, 0x63, 0x8d, 0xce, 0x7f, 0x41, 0xa4, 0x05, 0x9f, 0x3f, 0xb7, 0x02, 0x70, 0x70, 0x18, 0x28, 0xf8, 0x81, + 0x67, 0xa3, 0x84, 0xb0, 0xa0, 0x50, 0xdd, 0x21, 0xb2, 0xc0, 0xfb, 0x08, 0xfe, 0x2d, 0x8a, 0xc5, 0x0f, 0xae, 0x3a, + 0xb5, 0x43, 0x3f, 0x9a, 0x01, 0x49, 0xf3, 0xa3, 0x59, 0xcd, 0x44, 0x83, 0xfc, 0x17, 0x2b, 0xa5, 0x05, 0xa8, 0xc2, + 0x7c, 0x22, 0xfd, 0xfe, 0xfe, 0x82, 0x12, 0x4d, 0x41, 0x52, 0x73, 0x7f, 0x82, 0xce, 0x76, 0x85, 0x76, 0xe7, 0xf9, + 0xe0, 0xdb, 0x93, 0x05, 0xcb, 0x7c, 0x12, 0x0d, 0xc3, 0xe5, 0x17, 0xd8, 0x01, 0x6d, 0x2c, 0x92, 0xc4, 0x52, 0x32, + 0xf9, 0x09, 0xbb, 0x09, 0xc6, 0xfc, 0x5e, 0x6a, 0x6a, 0xfc, 0x9c, 0xb2, 0xd0, 0x0a, 0x6c, 0xe0, 0x9a, 0x64, 0x84, + 0x3c, 0xf6, 0x31, 0xcc, 0xe4, 0x20, 0x8a, 0xf5, 0xd3, 0x6f, 0xa5, 0xbf, 0xd6, 0xa6, 0x49, 0x80, 0x6c, 0x8f, 0x97, + 0x09, 0x0b, 0xff, 0x35, 0xf8, 0x16, 0x0e, 0xee, 0x6f, 0xaf, 0x74, 0xa3, 0x9f, 0xd9, 0xf3, 0x84, 0x4d, 0x07, 0xdf, + 0x36, 0x64, 0x3d, 0xc4, 0xeb, 0x3d, 0xf5, 0x45, 0x6f, 0x7b, 0x45, 0x70, 0xa0, 0xf6, 0x5e, 0x97, 0xfa, 0x53, 0x7e, + 0x5b, 0x87, 0x1b, 0xe0, 0xba, 0x74, 0xc7, 0x76, 0xfb, 0x78, 0x7f, 0x1e, 0x85, 0xfe, 0xf8, 0x53, 0x9f, 0xde, 0x94, + 0x1e, 0x2c, 0x38, 0xad, 0xc7, 0xfe, 0xb2, 0x87, 0xc7, 0xab, 0x5a, 0x08, 0xee, 0x9a, 0x54, 0x2a, 0x39, 0xbb, 0xc6, + 0xb5, 0x8c, 0x4b, 0x79, 0x8d, 0x5f, 0xc6, 0x4f, 0xdd, 0xce, 0x83, 0x8c, 0x89, 0x4f, 0xe1, 0x43, 0x9e, 0x8b, 0x8b, + 0x3a, 0x5d, 0x51, 0xf1, 0x62, 0x6d, 0xb7, 0x35, 0xb7, 0xfb, 0xb7, 0xce, 0x8d, 0xeb, 0xcc, 0x3d, 0xd7, 0xee, 0x7e, + 0x74, 0xbb, 0xf3, 0xb6, 0x7d, 0x1c, 0x5a, 0x6d, 0xfb, 0x18, 0xfe, 0x7c, 0x3c, 0xb6, 0xbb, 0x73, 0xcb, 0xb3, 0x0f, + 0x3f, 0xba, 0x5e, 0x68, 0x75, 0xed, 0x63, 0xf8, 0x73, 0x4e, 0xad, 0xe0, 0x02, 0x44, 0xf7, 0x9d, 0x6f, 0x4b, 0x54, + 0x40, 0xf9, 0x2d, 0xf5, 0x34, 0x66, 0xe9, 0x78, 0x6b, 0xd0, 0xf5, 0x00, 0xc9, 0xd0, 0x4d, 0x11, 0x04, 0x32, 0xea, + 0xb7, 0x20, 0x0d, 0x3b, 0x26, 0x10, 0x10, 0x26, 0x2f, 0xc2, 0x2f, 0x55, 0x84, 0xd2, 0x6f, 0xdc, 0x46, 0xbc, 0x4d, + 0x73, 0xc0, 0x75, 0x91, 0x99, 0x8a, 0x94, 0x43, 0xbf, 0x2c, 0x31, 0x88, 0x91, 0x08, 0x11, 0xaf, 0x50, 0xa5, 0x22, + 0x3b, 0x62, 0xbe, 0xbb, 0xe3, 0xe8, 0x99, 0xcb, 0x64, 0x76, 0x9e, 0xaf, 0x0a, 0x9b, 0x2b, 0x8c, 0x24, 0xf4, 0x3f, + 0x0a, 0x07, 0x93, 0xd2, 0x12, 0x1c, 0x11, 0xcd, 0x75, 0x12, 0x24, 0xb2, 0x7b, 0x0a, 0x89, 0x76, 0x9b, 0x23, 0xd5, + 0x1b, 0x90, 0xc6, 0xe4, 0x2d, 0x70, 0xc9, 0x37, 0x7e, 0xa8, 0x18, 0xb7, 0x28, 0x2d, 0x1f, 0x49, 0xca, 0xff, 0xf4, + 0x69, 0xd1, 0x39, 0xab, 0xd2, 0xef, 0x13, 0xb7, 0x03, 0xc7, 0x6e, 0x87, 0xb5, 0xb7, 0xda, 0x59, 0xed, 0x0e, 0x07, + 0x5c, 0x84, 0x0b, 0x15, 0xb6, 0x14, 0x42, 0x8b, 0xbb, 0xd1, 0xd8, 0xab, 0xa6, 0xc3, 0x85, 0x40, 0xca, 0x95, 0xab, + 0x8e, 0x6e, 0xf4, 0x23, 0xa1, 0x92, 0x8c, 0xb6, 0x84, 0x40, 0xe6, 0x77, 0x31, 0x1d, 0x50, 0xb3, 0x65, 0x1c, 0x3b, + 0x9c, 0x46, 0xff, 0xd7, 0x83, 0x40, 0x07, 0x2e, 0xd0, 0xa1, 0x56, 0x76, 0x6b, 0xc9, 0xa1, 0x47, 0x9e, 0xab, 0x74, + 0xa0, 0xb2, 0xf4, 0x4c, 0x87, 0x22, 0xc8, 0x6f, 0x85, 0x29, 0xed, 0xa4, 0x01, 0x99, 0x3c, 0x2d, 0x8a, 0x02, 0x33, + 0x80, 0x18, 0xe0, 0x2d, 0xe1, 0x4c, 0x66, 0x3c, 0x7d, 0xba, 0xf1, 0x10, 0x22, 0x85, 0xbd, 0x9a, 0xd9, 0x53, 0x57, + 0xe9, 0x9b, 0xae, 0x92, 0x18, 0x09, 0x17, 0xa9, 0x86, 0xb0, 0x7b, 0xa3, 0xb5, 0x87, 0x3f, 0x47, 0xcc, 0xcf, 0x6c, + 0xae, 0x69, 0x6a, 0x29, 0x87, 0xbb, 0xe9, 0xb2, 0x36, 0x58, 0xbc, 0xf1, 0x58, 0x67, 0x3c, 0x96, 0xe0, 0x93, 0xf5, + 0xc7, 0x15, 0xf7, 0xf4, 0x06, 0x18, 0x9f, 0x9d, 0x22, 0x3c, 0xcd, 0xbb, 0xcc, 0xa7, 0x18, 0x26, 0xea, 0x91, 0x1b, + 0x67, 0xbe, 0xc8, 0x23, 0x03, 0x7c, 0x79, 0xbf, 0x51, 0x25, 0xab, 0x78, 0x83, 0x9f, 0xbe, 0xbb, 0xf8, 0x4e, 0xe3, + 0xeb, 0x9f, 0x34, 0x88, 0x78, 0x91, 0xa1, 0xac, 0x07, 0x03, 0xca, 0x7a, 0xa0, 0xf1, 0x34, 0x22, 0x90, 0x3b, 0x20, + 0x3f, 0x20, 0x0c, 0xa2, 0x00, 0x9a, 0xf4, 0xaa, 0x8b, 0x55, 0x98, 0x05, 0x4b, 0x3f, 0xc9, 0x0e, 0xa0, 0xa9, 0x05, + 0x44, 0x4e, 0xdf, 0xe4, 0x23, 0x4e, 0xaa, 0x59, 0x11, 0x62, 0x2f, 0x8b, 0x84, 0x6e, 0x76, 0x1a, 0x84, 0x52, 0x35, + 0x2b, 0x3e, 0xe0, 0x8f, 0xc7, 0x6c, 0x99, 0x0d, 0x74, 0x7f, 0x09, 0xd9, 0x2f, 0x30, 0x9e, 0xf5, 0x41, 0x3c, 0xce, + 0x58, 0x66, 0xa5, 0x59, 0xc2, 0xfc, 0x85, 0x2e, 0x43, 0xb9, 0xd6, 0xe1, 0xa5, 0xab, 0xd1, 0x22, 0xc8, 0x64, 0x2c, + 0x44, 0x1a, 0x20, 0x28, 0x49, 0xa1, 0x8b, 0xa7, 0xc3, 0x9c, 0xa3, 0xf0, 0x3c, 0x9e, 0x55, 0x56, 0x54, 0xc1, 0xb9, + 0x9c, 0x61, 0xa4, 0x5d, 0x9e, 0xf1, 0x60, 0x82, 0x3e, 0x4f, 0xd7, 0xdc, 0xaf, 0x5d, 0x86, 0x6c, 0xd4, 0x4f, 0x4f, + 0xf8, 0xf5, 0x56, 0xc3, 0x50, 0x0c, 0x7a, 0xc7, 0x81, 0x58, 0xc2, 0x9b, 0x3c, 0xde, 0x0f, 0x78, 0x65, 0x38, 0x9a, + 0x08, 0x32, 0xc6, 0x79, 0xa7, 0xbe, 0x5c, 0x00, 0x23, 0x54, 0x52, 0xa2, 0xcf, 0xdd, 0x53, 0xe9, 0x62, 0x85, 0xbd, + 0x42, 0x5e, 0xe9, 0xf3, 0xe7, 0x97, 0xc3, 0xff, 0xfc, 0x1b, 0x82, 0xd1, 0xcf, 0x5d, 0xe1, 0x67, 0x7e, 0xa9, 0xd6, + 0xe2, 0xdc, 0xa7, 0x39, 0x44, 0x03, 0x0a, 0x36, 0x11, 0x81, 0x57, 0xc4, 0xd2, 0xca, 0x87, 0x57, 0x22, 0x98, 0x16, + 0x24, 0x9c, 0x30, 0x84, 0x37, 0xfc, 0x10, 0xa6, 0x77, 0x28, 0x82, 0x30, 0x68, 0xbf, 0xdd, 0x7d, 0x7f, 0x0c, 0xc1, + 0x96, 0x6b, 0x79, 0x20, 0x94, 0x0e, 0xe2, 0x1a, 0x3a, 0x3d, 0xf1, 0x35, 0x64, 0x5a, 0x90, 0xfd, 0x48, 0x7b, 0x07, + 0x30, 0xcc, 0x79, 0xbc, 0x60, 0x76, 0x10, 0x1f, 0xdc, 0xb2, 0x91, 0xe5, 0x2f, 0x03, 0xd2, 0xd5, 0xa3, 0xdc, 0x4d, + 0x23, 0xce, 0x4f, 0xaa, 0xc0, 0x89, 0xbf, 0xce, 0x0b, 0x54, 0xc6, 0xe5, 0xe8, 0x69, 0x1d, 0xaf, 0x50, 0xdc, 0x81, + 0x4f, 0xb3, 0x82, 0xc7, 0xf8, 0xf4, 0xe4, 0xc0, 0x3f, 0x2d, 0x87, 0x6f, 0xb4, 0x45, 0x02, 0x81, 0xf2, 0x21, 0x70, + 0x46, 0x51, 0x18, 0x45, 0xc0, 0xc5, 0xe2, 0xc1, 0x8a, 0xa7, 0x53, 0x35, 0xe4, 0xa2, 0x5d, 0xee, 0x9e, 0x44, 0x5a, + 0xb1, 0xa4, 0xe3, 0x25, 0x7d, 0xa9, 0xfe, 0x09, 0xf9, 0x13, 0x92, 0x27, 0xf3, 0xe8, 0x9c, 0xb0, 0xdd, 0x6b, 0xa1, + 0x1b, 0x25, 0xc6, 0x1e, 0x53, 0x25, 0x4e, 0x47, 0xaa, 0x81, 0xc2, 0x37, 0x70, 0x2e, 0x8f, 0x06, 0x03, 0x22, 0x73, + 0x55, 0x6a, 0x07, 0x48, 0x6c, 0x48, 0xa6, 0x00, 0x83, 0xcd, 0xa0, 0xa1, 0x45, 0x2e, 0x74, 0xd8, 0xa8, 0x3a, 0x9c, + 0x7a, 0x1f, 0x0f, 0x7c, 0xb1, 0xfc, 0x4a, 0x0b, 0x14, 0x16, 0x1e, 0x9f, 0x77, 0xa0, 0xef, 0x02, 0x4e, 0x85, 0xcc, + 0x6b, 0x7f, 0x25, 0x8a, 0x6e, 0x85, 0xfe, 0x7d, 0xac, 0x98, 0x36, 0xf0, 0x28, 0x07, 0xe7, 0x58, 0x7a, 0x21, 0xbc, + 0x0b, 0x6b, 0x1b, 0x4d, 0x06, 0xa4, 0xaf, 0x6f, 0x36, 0x35, 0x82, 0xfc, 0xae, 0xbd, 0xa6, 0xd6, 0x2d, 0x0f, 0x06, + 0x89, 0x67, 0x5e, 0xec, 0xc3, 0xd2, 0x4b, 0x24, 0x0b, 0xf9, 0xc9, 0x01, 0x8c, 0x0f, 0x22, 0x33, 0x94, 0x18, 0xa7, + 0xc0, 0x80, 0xf0, 0x0f, 0x7e, 0x4a, 0xe6, 0x19, 0x6f, 0x27, 0x82, 0xe7, 0xc3, 0x8b, 0xa5, 0x8c, 0x0d, 0x5b, 0xaa, + 0x52, 0xe7, 0x65, 0x9c, 0x66, 0x26, 0x70, 0x77, 0x02, 0x87, 0xdf, 0x57, 0x98, 0xbd, 0x21, 0xef, 0x67, 0x4c, 0x38, + 0x3e, 0x9f, 0x67, 0x1b, 0x7c, 0xa3, 0x37, 0x55, 0x21, 0x7e, 0x76, 0x4b, 0x85, 0x62, 0x1d, 0x6f, 0xab, 0x55, 0x70, + 0x4e, 0xb2, 0xda, 0xd2, 0x6f, 0xe9, 0x8f, 0x71, 0xc5, 0xd7, 0x6a, 0x63, 0x29, 0xd4, 0x3b, 0xcf, 0x06, 0x50, 0x55, + 0xc8, 0xe2, 0xfd, 0xe5, 0x92, 0x2a, 0x1b, 0xfd, 0x93, 0x03, 0xba, 0x96, 0x9e, 0xd2, 0x0a, 0x3b, 0x3d, 0x01, 0xf3, + 0x4e, 0x9a, 0x74, 0x7f, 0xb9, 0xe4, 0x53, 0x4a, 0xbf, 0xe8, 0xcd, 0xc1, 0x3c, 0x5b, 0x84, 0xa7, 0xff, 0x07, 0xc0, + 0xb1, 0x34, 0x8b, 0x20, 0x5c, 0x03, 0x00}; } // namespace web_server } // namespace esphome From 08b8ab837a2b6da234691cbd750625eea9fe38c0 Mon Sep 17 00:00:00 2001 From: Colm Date: Thu, 11 Jul 2024 05:10:58 +0100 Subject: [PATCH 1742/2101] Add braces to if statement to avoid compiler warning. (#7036) --- esphome/components/aht10/aht10.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/esphome/components/aht10/aht10.cpp b/esphome/components/aht10/aht10.cpp index 332218b9e9..441c1ac9df 100644 --- a/esphome/components/aht10/aht10.cpp +++ b/esphome/components/aht10/aht10.cpp @@ -93,8 +93,9 @@ void AHT10Component::restart_read_() { void AHT10Component::read_data_() { uint8_t data[6]; - if (this->read_count_ > 1) + if (this->read_count_ > 1) { ESP_LOGD(TAG, "Read attempt %d at %ums", this->read_count_, (unsigned) (millis() - this->start_time_)); + } if (this->read(data, 6) != i2c::ERROR_OK) { this->status_set_warning("AHT10 read failed, retrying soon"); this->restart_read_(); @@ -119,8 +120,9 @@ void AHT10Component::read_data_() { return; } } - if (this->read_count_ > 1) + if (this->read_count_ > 1) { ESP_LOGD(TAG, "Success at %ums", (unsigned) (millis() - this->start_time_)); + } uint32_t raw_temperature = ((data[3] & 0x0F) << 16) | (data[4] << 8) | data[5]; uint32_t raw_humidity = ((data[1] << 16) | (data[2] << 8) | data[3]) >> 4; From 6e624ff7974311bc22058466f0688d554a340b1f Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Wed, 10 Jul 2024 23:21:24 -0500 Subject: [PATCH 1743/2101] [wifi] Fix EAP for IDF 5.1+, add test (#7061) --- esphome/components/wifi/wifi_component.h | 4 ++ .../wifi/wifi_component_esp_idf.cpp | 48 ++++++++++++++++--- tests/components/wifi/common-eap.yaml | 7 +++ tests/components/wifi/test-eap.esp32-ard.yaml | 8 +--- tests/components/wifi/test-eap.esp32-idf.yaml | 1 + 5 files changed, 54 insertions(+), 14 deletions(-) create mode 100644 tests/components/wifi/common-eap.yaml create mode 100644 tests/components/wifi/test-eap.esp32-idf.yaml diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index 0b077819ae..d79cde0b18 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -20,8 +20,12 @@ #endif #if defined(USE_ESP_IDF) && defined(USE_WIFI_WPA2_EAP) +#if (ESP_IDF_VERSION_MAJOR >= 5) && (ESP_IDF_VERSION_MINOR >= 1) +#include +#else #include #endif +#endif #ifdef USE_ESP8266 #include diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index 96fa837767..a8d67ed44d 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -15,8 +15,12 @@ #include #include #ifdef USE_WIFI_WPA2_EAP +#if (ESP_IDF_VERSION_MAJOR >= 5) && (ESP_IDF_VERSION_MINOR >= 1) +#include +#else #include #endif +#endif #ifdef USE_WIFI_AP #include "dhcpserver/dhcpserver.h" @@ -364,48 +368,78 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) { if (ap.get_eap().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(); +#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 err = esp_wifi_sta_wpa2_ent_set_identity((uint8_t *) eap.identity.c_str(), eap.identity.length()); +#endif if (err != ESP_OK) { - ESP_LOGV(TAG, "esp_wifi_sta_wpa2_ent_set_identity failed! %d", err); + ESP_LOGV(TAG, "set_identity failed %d", err); } int ca_cert_len = strlen(eap.ca_cert); 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) + 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); +#endif if (err != ESP_OK) { - ESP_LOGV(TAG, "esp_wifi_sta_wpa2_ent_set_ca_cert failed! %d", err); + ESP_LOGV(TAG, "set_ca_cert failed %d", err); } } // workout what type of EAP this is // 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) + 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(), strlen(eap.password.c_str())); +#else err = esp_wifi_sta_wpa2_ent_set_cert_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(), strlen(eap.password.c_str())); +#endif if (err != ESP_OK) { - ESP_LOGV(TAG, "esp_wifi_sta_wpa2_ent_set_cert_key failed! %d", err); + ESP_LOGV(TAG, "set_cert_key failed %d", err); } } else { // in the absence of certs, assume this is username/password based +#if (ESP_IDF_VERSION_MAJOR >= 5) && (ESP_IDF_VERSION_MINOR >= 1) + 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()); +#endif if (err != ESP_OK) { - ESP_LOGV(TAG, "esp_wifi_sta_wpa2_ent_set_username failed! %d", err); + ESP_LOGV(TAG, "set_username failed %d", err); } +#if (ESP_IDF_VERSION_MAJOR >= 5) && (ESP_IDF_VERSION_MINOR >= 1) + 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()); +#endif if (err != ESP_OK) { - ESP_LOGV(TAG, "esp_wifi_sta_wpa2_ent_set_password failed! %d", err); + 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) + 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); +#endif if (err != ESP_OK) { - ESP_LOGV(TAG, "esp_wifi_sta_wpa2_ent_set_ttls_phase2_method failed! %d", err); + ESP_LOGV(TAG, "set_ttls_phase2_method failed %d", err); } } +#if (ESP_IDF_VERSION_MAJOR >= 5) && (ESP_IDF_VERSION_MINOR >= 1) + err = esp_wifi_sta_enterprise_enable(); +#else err = esp_wifi_sta_wpa2_ent_enable(); +#endif if (err != ESP_OK) { - ESP_LOGV(TAG, "esp_wifi_sta_wpa2_ent_enable failed! %d", err); + ESP_LOGV(TAG, "enterprise_enable failed %d", err); } } #endif // USE_WIFI_WPA2_EAP diff --git a/tests/components/wifi/common-eap.yaml b/tests/components/wifi/common-eap.yaml new file mode 100644 index 0000000000..779cd6b49a --- /dev/null +++ b/tests/components/wifi/common-eap.yaml @@ -0,0 +1,7 @@ +wifi: + networks: + - ssid: MySSID + eap: + username: username + password: password + identity: identity diff --git a/tests/components/wifi/test-eap.esp32-ard.yaml b/tests/components/wifi/test-eap.esp32-ard.yaml index 779cd6b49a..9177e5de10 100644 --- a/tests/components/wifi/test-eap.esp32-ard.yaml +++ b/tests/components/wifi/test-eap.esp32-ard.yaml @@ -1,7 +1 @@ -wifi: - networks: - - ssid: MySSID - eap: - username: username - password: password - identity: identity +<<: !include common-eap.yaml diff --git a/tests/components/wifi/test-eap.esp32-idf.yaml b/tests/components/wifi/test-eap.esp32-idf.yaml new file mode 100644 index 0000000000..9177e5de10 --- /dev/null +++ b/tests/components/wifi/test-eap.esp32-idf.yaml @@ -0,0 +1 @@ +<<: !include common-eap.yaml From 5ac875545fe14fa1d818336efb392f48f61b3fc1 Mon Sep 17 00:00:00 2001 From: ttaborda <80131527+ttaborda@users.noreply.github.com> Date: Thu, 11 Jul 2024 05:26:37 +0100 Subject: [PATCH 1744/2101] Update mitsubishi.cpp (#6909) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/mitsubishi/mitsubishi.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/mitsubishi/mitsubishi.cpp b/esphome/components/mitsubishi/mitsubishi.cpp index fd57adc586..a02aabf14d 100644 --- a/esphome/components/mitsubishi/mitsubishi.cpp +++ b/esphome/components/mitsubishi/mitsubishi.cpp @@ -52,6 +52,7 @@ const uint8_t MITSUBISHI_BYTE16 = 0X00; climate::ClimateTraits MitsubishiClimate::traits() { auto traits = climate::ClimateTraits(); + traits.set_supports_current_temperature(this->sensor_ != nullptr); traits.set_supports_action(false); traits.set_visual_min_temperature(MITSUBISHI_TEMP_MIN); traits.set_visual_max_temperature(MITSUBISHI_TEMP_MAX); From 66b36afe90431b89b8e7c26c782be2431f2e7890 Mon Sep 17 00:00:00 2001 From: Sergey Dudanov Date: Thu, 11 Jul 2024 08:23:29 +0300 Subject: [PATCH 1745/2101] [climate] fix dump output of unsupported features (#7005) --- esphome/components/climate/climate.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/esphome/components/climate/climate.cpp b/esphome/components/climate/climate.cpp index 1822707152..bc8d932089 100644 --- a/esphome/components/climate/climate.cpp +++ b/esphome/components/climate/climate.cpp @@ -574,21 +574,25 @@ void Climate::dump_traits_(const char *tag) { ESP_LOGCONFIG(tag, " - Max temperature: %.1f", traits.get_visual_max_temperature()); ESP_LOGCONFIG(tag, " - Temperature step:"); ESP_LOGCONFIG(tag, " Target: %.1f", traits.get_visual_target_temperature_step()); - ESP_LOGCONFIG(tag, " Current: %.1f", traits.get_visual_current_temperature_step()); - ESP_LOGCONFIG(tag, " - Min humidity: %.0f", traits.get_visual_min_humidity()); - ESP_LOGCONFIG(tag, " - Max humidity: %.0f", traits.get_visual_max_humidity()); if (traits.get_supports_current_temperature()) { - ESP_LOGCONFIG(tag, " [x] Supports current temperature"); + ESP_LOGCONFIG(tag, " Current: %.1f", traits.get_visual_current_temperature_step()); } - if (traits.get_supports_current_humidity()) { - ESP_LOGCONFIG(tag, " [x] Supports current humidity"); + if (traits.get_supports_target_humidity() || traits.get_supports_current_humidity()) { + ESP_LOGCONFIG(tag, " - Min humidity: %.0f", traits.get_visual_min_humidity()); + ESP_LOGCONFIG(tag, " - Max humidity: %.0f", traits.get_visual_max_humidity()); } if (traits.get_supports_two_point_target_temperature()) { ESP_LOGCONFIG(tag, " [x] Supports two-point target temperature"); } + if (traits.get_supports_current_temperature()) { + ESP_LOGCONFIG(tag, " [x] Supports current temperature"); + } if (traits.get_supports_target_humidity()) { ESP_LOGCONFIG(tag, " [x] Supports target humidity"); } + if (traits.get_supports_current_humidity()) { + ESP_LOGCONFIG(tag, " [x] Supports current humidity"); + } if (traits.get_supports_action()) { ESP_LOGCONFIG(tag, " [x] Supports action"); } From d071b05249fc4d4310fda64ed8227896bb3f51d6 Mon Sep 17 00:00:00 2001 From: Sergey Dudanov Date: Thu, 11 Jul 2024 08:24:36 +0300 Subject: [PATCH 1746/2101] [climate-traits] improved performance (#7006) --- esphome/components/climate/climate_traits.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/climate/climate_traits.h b/esphome/components/climate/climate_traits.h index fd5b025a03..58d7b586d7 100644 --- a/esphome/components/climate/climate_traits.h +++ b/esphome/components/climate/climate_traits.h @@ -73,7 +73,7 @@ class ClimateTraits { ESPDEPRECATED("This method is deprecated, use set_supported_modes() instead", "v1.20") void set_supports_dry_mode(bool supports_dry_mode) { set_mode_support_(CLIMATE_MODE_DRY, supports_dry_mode); } bool supports_mode(ClimateMode mode) const { return supported_modes_.count(mode); } - std::set get_supported_modes() const { return supported_modes_; } + const std::set &get_supported_modes() const { return supported_modes_; } void set_supports_action(bool supports_action) { supports_action_ = supports_action; } bool get_supports_action() const { return supports_action_; } @@ -101,7 +101,7 @@ class ClimateTraits { void set_supports_fan_mode_diffuse(bool supported) { set_fan_mode_support_(CLIMATE_FAN_DIFFUSE, supported); } bool supports_fan_mode(ClimateFanMode fan_mode) const { return supported_fan_modes_.count(fan_mode); } bool get_supports_fan_modes() const { return !supported_fan_modes_.empty() || !supported_custom_fan_modes_.empty(); } - std::set get_supported_fan_modes() const { return supported_fan_modes_; } + const std::set &get_supported_fan_modes() const { return supported_fan_modes_; } void set_supported_custom_fan_modes(std::set supported_custom_fan_modes) { supported_custom_fan_modes_ = std::move(supported_custom_fan_modes); @@ -140,7 +140,7 @@ class ClimateTraits { } bool supports_swing_mode(ClimateSwingMode swing_mode) const { return supported_swing_modes_.count(swing_mode); } bool get_supports_swing_modes() const { return !supported_swing_modes_.empty(); } - std::set get_supported_swing_modes() const { return supported_swing_modes_; } + const std::set &get_supported_swing_modes() const { return supported_swing_modes_; } float get_visual_min_temperature() const { return visual_min_temperature_; } void set_visual_min_temperature(float visual_min_temperature) { visual_min_temperature_ = visual_min_temperature; } From d209a2b45acff1e975d7ab68af5b75959624284e Mon Sep 17 00:00:00 2001 From: leejoow Date: Thu, 11 Jul 2024 22:20:58 +0200 Subject: [PATCH 1747/2101] Add default icon to restart button (#7076) Co-authored-by: Leo Schelvis --- esphome/components/restart/button/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/components/restart/button/__init__.py b/esphome/components/restart/button/__init__.py index 1b2c991261..6aff8cb351 100644 --- a/esphome/components/restart/button/__init__.py +++ b/esphome/components/restart/button/__init__.py @@ -5,6 +5,7 @@ from esphome.const import ( CONF_ID, DEVICE_CLASS_RESTART, ENTITY_CATEGORY_CONFIG, + ICON_RESTART, ) restart_ns = cg.esphome_ns.namespace("restart") @@ -12,6 +13,7 @@ RestartButton = restart_ns.class_("RestartButton", button.Button, cg.Component) CONFIG_SCHEMA = button.button_schema( RestartButton, + icon=ICON_RESTART, device_class=DEVICE_CLASS_RESTART, entity_category=ENTITY_CATEGORY_CONFIG, ).extend(cv.COMPONENT_SCHEMA) From 2e8a2fdbd4677b9075ae9bb572b4d66b8fc67794 Mon Sep 17 00:00:00 2001 From: Tomi Junnila Date: Thu, 11 Jul 2024 23:32:38 +0300 Subject: [PATCH 1748/2101] Add support for the Gree YAC1FB9 in climate_ir (#7056) --- esphome/components/gree/climate.py | 1 + esphome/components/gree/gree.cpp | 14 +++++++++++--- esphome/components/gree/gree.h | 6 +++++- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/esphome/components/gree/climate.py b/esphome/components/gree/climate.py index 02ce7b12d4..c88a428391 100644 --- a/esphome/components/gree/climate.py +++ b/esphome/components/gree/climate.py @@ -16,6 +16,7 @@ MODELS = { "yan": Model.GREE_YAN, "yaa": Model.GREE_YAA, "yac": Model.GREE_YAC, + "yac1fb9": Model.GREE_YAC1FB9, } CONFIG_SCHEMA = climate_ir.CLIMATE_IR_WITH_RECEIVER_SCHEMA.extend( diff --git a/esphome/components/gree/gree.cpp b/esphome/components/gree/gree.cpp index 1bbb443fce..cce2a8ffee 100644 --- a/esphome/components/gree/gree.cpp +++ b/esphome/components/gree/gree.cpp @@ -24,7 +24,7 @@ void GreeClimate::transmit_state() { remote_state[4] |= (this->horizontal_swing_() << 4); } - if (this->model_ == GREE_YAA || this->model_ == GREE_YAC) { + if (this->model_ == GREE_YAA || this->model_ == GREE_YAC || this->model_ == GREE_YAC1FB9) { remote_state[2] = 0x20; // bits 0..3 always 0000, bits 4..7 TURBO,LIGHT,HEALTH,X-FAN remote_state[3] = 0x50; // bits 4..7 always 0101 remote_state[6] = 0x20; // YAA1FB, FAA1FB1, YB1F2 bits 4..7 always 0010 @@ -53,7 +53,11 @@ void GreeClimate::transmit_state() { data->set_carrier_frequency(GREE_IR_FREQUENCY); data->mark(GREE_HEADER_MARK); - data->space(GREE_HEADER_SPACE); + if (this->model_ == GREE_YAC1FB9) { + data->space(GREE_YAC1FB9_HEADER_SPACE); + } else { + data->space(GREE_HEADER_SPACE); + } for (int i = 0; i < 4; i++) { for (uint8_t mask = 1; mask > 0; mask <<= 1) { // iterate through bit mask @@ -71,7 +75,11 @@ void GreeClimate::transmit_state() { data->space(GREE_ZERO_SPACE); data->mark(GREE_BIT_MARK); - data->space(GREE_MESSAGE_SPACE); + if (this->model_ == GREE_YAC1FB9) { + data->space(GREE_YAC1FB9_MESSAGE_SPACE); + } else { + data->space(GREE_MESSAGE_SPACE); + } for (int i = 4; i < 8; i++) { for (uint8_t mask = 1; mask > 0; mask <<= 1) { // iterate through bit mask diff --git a/esphome/components/gree/gree.h b/esphome/components/gree/gree.h index e7131a2b89..524a95aebd 100644 --- a/esphome/components/gree/gree.h +++ b/esphome/components/gree/gree.h @@ -41,6 +41,10 @@ const uint32_t GREE_YAC_HEADER_MARK = 6000; const uint32_t GREE_YAC_HEADER_SPACE = 3000; const uint32_t GREE_YAC_BIT_MARK = 650; +// Timing specific to YAC1FB9 +const uint32_t GREE_YAC1FB9_HEADER_SPACE = 4500; +const uint32_t GREE_YAC1FB9_MESSAGE_SPACE = 19980; + // State Frame size const uint8_t GREE_STATE_FRAME_SIZE = 8; @@ -67,7 +71,7 @@ const uint8_t GREE_HDIR_MRIGHT = 0x05; const uint8_t GREE_HDIR_RIGHT = 0x06; // Model codes -enum Model { GREE_GENERIC, GREE_YAN, GREE_YAA, GREE_YAC }; +enum Model { GREE_GENERIC, GREE_YAN, GREE_YAA, GREE_YAC, GREE_YAC1FB9 }; class GreeClimate : public climate_ir::ClimateIR { public: From 99cba0ae7fa0e9897c7f0dfb764a329ba6d431f4 Mon Sep 17 00:00:00 2001 From: Eugen Date: Thu, 11 Jul 2024 23:26:04 +0200 Subject: [PATCH 1749/2101] add ESP32-C6 support to esp32_can (#7063) --- esphome/components/esp32_can/canbus.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/esphome/components/esp32_can/canbus.py b/esphome/components/esp32_can/canbus.py index 74f331f30b..f4ba032009 100644 --- a/esphome/components/esp32_can/canbus.py +++ b/esphome/components/esp32_can/canbus.py @@ -11,6 +11,7 @@ from esphome.components.esp32.const import ( VARIANT_ESP32S2, VARIANT_ESP32S3, VARIANT_ESP32C3, + VARIANT_ESP32C6, VARIANT_ESP32H2, ) @@ -47,6 +48,7 @@ CAN_SPEEDS_ESP32_S2 = { CAN_SPEEDS_ESP32_S3 = {**CAN_SPEEDS_ESP32_S2} CAN_SPEEDS_ESP32_C3 = {**CAN_SPEEDS_ESP32_S2} +CAN_SPEEDS_ESP32_C6 = {**CAN_SPEEDS_ESP32_S2} CAN_SPEEDS_ESP32_H2 = {**CAN_SPEEDS_ESP32_S2} CAN_SPEEDS = { @@ -54,6 +56,7 @@ CAN_SPEEDS = { VARIANT_ESP32S2: CAN_SPEEDS_ESP32_S2, VARIANT_ESP32S3: CAN_SPEEDS_ESP32_S3, VARIANT_ESP32C3: CAN_SPEEDS_ESP32_C3, + VARIANT_ESP32C6: CAN_SPEEDS_ESP32_C6, VARIANT_ESP32H2: CAN_SPEEDS_ESP32_H2, } From 7f83bcfdd91aba4fed05d0c1918c2899dac1682e Mon Sep 17 00:00:00 2001 From: soeffi Date: Thu, 11 Jul 2024 23:30:45 +0200 Subject: [PATCH 1750/2101] jsn_sr04t component: AJ_SR04M compatibility mode in checksum calculation (#7044) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/jsn_sr04t/jsn_sr04t.cpp | 19 ++++++++++++++++++- esphome/components/jsn_sr04t/jsn_sr04t.h | 8 +++++++- esphome/components/jsn_sr04t/sensor.py | 13 +++++++++++++ 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/esphome/components/jsn_sr04t/jsn_sr04t.cpp b/esphome/components/jsn_sr04t/jsn_sr04t.cpp index b96bf8f762..077d4e58ea 100644 --- a/esphome/components/jsn_sr04t/jsn_sr04t.cpp +++ b/esphome/components/jsn_sr04t/jsn_sr04t.cpp @@ -31,7 +31,16 @@ void Jsnsr04tComponent::loop() { } void Jsnsr04tComponent::check_buffer_() { - uint8_t checksum = this->buffer_[0] + this->buffer_[1] + this->buffer_[2]; + uint8_t checksum = 0; + switch (this->model_) { + case JSN_SR04T: + checksum = this->buffer_[0] + this->buffer_[1] + this->buffer_[2]; + break; + case AJ_SR04M: + checksum = this->buffer_[1] + this->buffer_[2]; + break; + } + if (this->buffer_[3] == checksum) { uint16_t distance = encode_uint16(this->buffer_[1], this->buffer_[2]); if (distance > 250) { @@ -49,6 +58,14 @@ void Jsnsr04tComponent::check_buffer_() { void Jsnsr04tComponent::dump_config() { LOG_SENSOR("", "JST_SR04T Sensor", this); + switch (this->model_) { + case JSN_SR04T: + ESP_LOGCONFIG(TAG, " sensor model: jsn_sr04t"); + break; + case AJ_SR04M: + ESP_LOGCONFIG(TAG, " sensor model: aj_sr04m"); + break; + } LOG_UPDATE_INTERVAL(this); } diff --git a/esphome/components/jsn_sr04t/jsn_sr04t.h b/esphome/components/jsn_sr04t/jsn_sr04t.h index bd43252be8..2a22ff92ec 100644 --- a/esphome/components/jsn_sr04t/jsn_sr04t.h +++ b/esphome/components/jsn_sr04t/jsn_sr04t.h @@ -9,9 +9,14 @@ namespace esphome { namespace jsn_sr04t { +enum Model { + JSN_SR04T, + AJ_SR04M, +}; + class Jsnsr04tComponent : public sensor::Sensor, public PollingComponent, public uart::UARTDevice { public: - // Nothing really public. + void set_model(Model model) { this->model_ = model; } // ========== INTERNAL METHODS ========== void update() override; @@ -20,6 +25,7 @@ class Jsnsr04tComponent : public sensor::Sensor, public PollingComponent, public protected: void check_buffer_(); + Model model_; std::vector buffer_; }; diff --git a/esphome/components/jsn_sr04t/sensor.py b/esphome/components/jsn_sr04t/sensor.py index 4b062e81e9..682cf06570 100644 --- a/esphome/components/jsn_sr04t/sensor.py +++ b/esphome/components/jsn_sr04t/sensor.py @@ -5,6 +5,7 @@ from esphome.const import ( STATE_CLASS_MEASUREMENT, UNIT_METER, ICON_ARROW_EXPAND_VERTICAL, + CONF_MODEL, ) CODEOWNERS = ["@Mafus1"] @@ -14,6 +15,11 @@ jsn_sr04t_ns = cg.esphome_ns.namespace("jsn_sr04t") Jsnsr04tComponent = jsn_sr04t_ns.class_( "Jsnsr04tComponent", sensor.Sensor, cg.PollingComponent, uart.UARTDevice ) +Model = jsn_sr04t_ns.enum("Model") +MODEL = { + "jsn_sr04t": Model.JSN_SR04T, + "aj_sr04m": Model.AJ_SR04M, +} CONFIG_SCHEMA = ( sensor.sensor_schema( @@ -25,6 +31,11 @@ CONFIG_SCHEMA = ( ) .extend(cv.polling_component_schema("60s")) .extend(uart.UART_DEVICE_SCHEMA) + .extend( + { + cv.Optional(CONF_MODEL, default="jsn_sr04t"): cv.enum(MODEL, upper=False), + } + ) ) FINAL_VALIDATE_SCHEMA = uart.final_validate_device_schema( @@ -42,3 +53,5 @@ async def to_code(config): var = await sensor.new_sensor(config) await cg.register_component(var, config) await uart.register_uart_device(var, config) + + cg.add(var.set_model(config[CONF_MODEL])) From 4a80a09db3c3a871f2825a2b7b7f1621ffab0f8b Mon Sep 17 00:00:00 2001 From: kevdliu <1766838+kevdliu@users.noreply.github.com> Date: Thu, 11 Jul 2024 17:32:31 -0400 Subject: [PATCH 1751/2101] Fix voice assistant crash when no speaker configured (#7075) --- esphome/components/voice_assistant/voice_assistant.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index 8a8a9e92aa..e4f388db68 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -684,7 +684,9 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { this->defer([this, text]() { this->tts_start_trigger_->trigger(text); #ifdef USE_SPEAKER - this->speaker_->start(); + if (this->speaker_ != nullptr) { + this->speaker_->start(); + } #endif }); break; From 8a3f0e3b93878a24a6cc9cdbe9babb846243c522 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=2E=20=C3=81rkosi=20R=C3=B3bert?= Date: Fri, 12 Jul 2024 23:19:33 +0200 Subject: [PATCH 1752/2101] Bump HeatpumpIR, add protocols, remove IRremoteESP8266 (#6996) --- esphome/components/heatpumpir/climate.py | 11 ++++++----- esphome/components/heatpumpir/heatpumpir.cpp | 5 +++++ esphome/components/heatpumpir/heatpumpir.h | 5 +++++ platformio.ini | 6 +++--- .../heatpumpir/test.bk72xx-ard.yaml | 19 +++++++++++++++++++ 5 files changed, 38 insertions(+), 8 deletions(-) create mode 100644 tests/components/heatpumpir/test.bk72xx-ard.yaml diff --git a/esphome/components/heatpumpir/climate.py b/esphome/components/heatpumpir/climate.py index b86d405b7e..80900d7db9 100644 --- a/esphome/components/heatpumpir/climate.py +++ b/esphome/components/heatpumpir/climate.py @@ -8,7 +8,6 @@ from esphome.const import ( CONF_PROTOCOL, CONF_VISUAL, ) -from esphome.core import CORE CODEOWNERS = ["@rob-deutsch"] @@ -67,6 +66,11 @@ PROTOCOLS = { "carrier_qlima_2": Protocol.PROTOCOL_QLIMA_2, "samsung_aqv12msan": Protocol.PROTOCOL_SAMSUNG_AQV12MSAN, "zhjg01": Protocol.PROTOCOL_ZHJG01, + "airway": Protocol.PROTOCOL_AIRWAY, + "bgh_aud": Protocol.PROTOCOL_BGH_AUD, + "panasonic_altdke": Protocol.PROTOCOL_PANASONIC_ALTDKE, + "vaillantvai8": Protocol.PROTOCOL_VAILLANTVAI8, + "r51m": Protocol.PROTOCOL_R51M, } CONF_HORIZONTAL_DEFAULT = "horizontal_default" @@ -122,7 +126,4 @@ 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.26") - - if CORE.is_esp8266 or CORE.is_esp32: - cg.add_library("crankyoldgit/IRremoteESP8266", "2.8.6") + cg.add_library("tonia/HeatpumpIR", "1.0.27") diff --git a/esphome/components/heatpumpir/heatpumpir.cpp b/esphome/components/heatpumpir/heatpumpir.cpp index 22a5779c8d..144dcc9bfa 100644 --- a/esphome/components/heatpumpir/heatpumpir.cpp +++ b/esphome/components/heatpumpir/heatpumpir.cpp @@ -61,6 +61,11 @@ const std::map> PROTOCOL_CONSTRUCTOR_MAP {PROTOCOL_QLIMA_2, []() { return new Qlima2HeatpumpIR(); }}, // NOLINT {PROTOCOL_SAMSUNG_AQV12MSAN, []() { return new SamsungAQV12MSANHeatpumpIR(); }}, // NOLINT {PROTOCOL_ZHJG01, []() { return new ZHJG01HeatpumpIR(); }}, // NOLINT + {PROTOCOL_AIRWAY, []() { return new AIRWAYHeatpumpIR(); }}, // NOLINT + {PROTOCOL_BGH_AUD, []() { return new BGHHeatpumpIR(); }}, // NOLINT + {PROTOCOL_PANASONIC_ALTDKE, []() { return new PanasonicAltDKEHeatpumpIR(); }}, // NOLINT + {PROTOCOL_VAILLANTVAI8, []() { return new VaillantHeatpumpIR(); }}, // NOLINT + {PROTOCOL_R51M, []() { return new R51MHeatpumpIR(); }}, // NOLINT }; void HeatpumpIRClimate::setup() { diff --git a/esphome/components/heatpumpir/heatpumpir.h b/esphome/components/heatpumpir/heatpumpir.h index 0e6ea2218f..f6e7ff3cd6 100644 --- a/esphome/components/heatpumpir/heatpumpir.h +++ b/esphome/components/heatpumpir/heatpumpir.h @@ -61,6 +61,11 @@ enum Protocol { PROTOCOL_QLIMA_2, PROTOCOL_SAMSUNG_AQV12MSAN, PROTOCOL_ZHJG01, + PROTOCOL_AIRWAY, + PROTOCOL_BGH_AUD, + PROTOCOL_PANASONIC_ALTDKE, + PROTOCOL_VAILLANTVAI8, + PROTOCOL_R51M, }; // Simple enum to represent horizontal directios diff --git a/platformio.ini b/platformio.ini index f07889526f..fc7f35b6c3 100644 --- a/platformio.ini +++ b/platformio.ini @@ -65,7 +65,7 @@ lib_deps = glmnet/Dsmr@0.7 ; dsmr rweather/Crypto@0.4.0 ; dsmr dudanov/MideaUART@1.1.9 ; midea - tonia/HeatpumpIR@1.0.26 ; heatpumpir + tonia/HeatpumpIR@1.0.27 ; heatpumpir build_flags = ${common.build_flags} -DUSE_ARDUINO @@ -93,8 +93,8 @@ lib_deps = ESP8266HTTPClient ; http_request (Arduino built-in) ESP8266mDNS ; mdns (Arduino built-in) DNSServer ; captive_portal (Arduino built-in) - crankyoldgit/IRremoteESP8266@2.8.6 ; heatpumpir droscy/esp_wireguard@0.4.2 ; wireguard + build_flags = ${common:arduino.build_flags} -Wno-nonnull-compare @@ -123,8 +123,8 @@ lib_deps = ESPmDNS ; mdns (Arduino built-in) DNSServer ; captive_portal (Arduino built-in) esphome/ESP32-audioI2S@2.0.7 ; i2s_audio - crankyoldgit/IRremoteESP8266@2.8.6 ; heatpumpir droscy/esp_wireguard@0.4.2 ; wireguard + build_flags = ${common:arduino.build_flags} -DUSE_ESP32 diff --git a/tests/components/heatpumpir/test.bk72xx-ard.yaml b/tests/components/heatpumpir/test.bk72xx-ard.yaml new file mode 100644 index 0000000000..90259f1244 --- /dev/null +++ b/tests/components/heatpumpir/test.bk72xx-ard.yaml @@ -0,0 +1,19 @@ +remote_transmitter: + pin: 6 + carrier_duty_percent: 50% + +climate: + - platform: heatpumpir + protocol: daikin + horizontal_default: mleft + vertical_default: mup + name: HeatpumpIR Climate + min_temperature: 18 + max_temperature: 30 + - platform: heatpumpir + protocol: panasonic_altdke + horizontal_default: mright + vertical_default: mdown + name: HeatpumpIR Climate + min_temperature: 18 + max_temperature: 30 From feae794787ca3ad0cc1b20be9496a73117e6844f Mon Sep 17 00:00:00 2001 From: Anton Viktorov Date: Fri, 12 Jul 2024 21:42:41 +0000 Subject: [PATCH 1753/2101] LTR390 separate ALS and UV gain and resolution (#7026) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- CODEOWNERS | 2 +- esphome/components/ltr390/ltr390.cpp | 73 +++++++++++-------- esphome/components/ltr390/ltr390.h | 14 ++-- esphome/components/ltr390/sensor.py | 40 ++++++++-- tests/components/ltr390/test.esp32-ard.yaml | 18 +++++ tests/components/ltr390/test.esp8266-ard.yaml | 4 +- 6 files changed, 110 insertions(+), 41 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index 5c14d30371..210c567f78 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -214,7 +214,7 @@ esphome/components/lightwaverf/* @max246 esphome/components/lilygo_t5_47/touchscreen/* @jesserockz esphome/components/lock/* @esphome/core esphome/components/logger/* @esphome/core -esphome/components/ltr390/* @sjtrny +esphome/components/ltr390/* @latonita @sjtrny esphome/components/ltr_als_ps/* @latonita esphome/components/matrix_keypad/* @ssieb esphome/components/max31865/* @DAVe3283 diff --git a/esphome/components/ltr390/ltr390.cpp b/esphome/components/ltr390/ltr390.cpp index 4eb1ff2c46..198d15ebd8 100644 --- a/esphome/components/ltr390/ltr390.cpp +++ b/esphome/components/ltr390/ltr390.cpp @@ -19,6 +19,7 @@ static const uint8_t LTR390_MAIN_STATUS = 0x07; static const float GAINVALUES[5] = {1.0, 3.0, 6.0, 9.0, 18.0}; static const float RESOLUTIONVALUE[6] = {4.0, 2.0, 1.0, 0.5, 0.25, 0.125}; +static const uint8_t RESOLUTION_BITS[6] = {20, 19, 18, 17, 16, 13}; // Request fastest measurement rate - will be slowed by device if conversion rate is slower. static const float RESOLUTION_SETTING[6] = {0x00, 0x10, 0x20, 0x30, 0x40, 0x50}; @@ -74,7 +75,7 @@ void LTR390Component::read_als_() { uint32_t als = *val; if (this->light_sensor_ != nullptr) { - float lux = ((0.6 * als) / (GAINVALUES[this->gain_] * RESOLUTIONVALUE[this->res_])) * this->wfac_; + float lux = ((0.6 * als) / (GAINVALUES[this->gain_als_] * RESOLUTIONVALUE[this->res_als_])) * this->wfac_; this->light_sensor_->publish_state(lux); } @@ -90,7 +91,7 @@ void LTR390Component::read_uvs_() { uint32_t uv = *val; if (this->uvi_sensor_ != nullptr) { - this->uvi_sensor_->publish_state((uv / this->sensitivity_) * this->wfac_); + this->uvi_sensor_->publish_state((uv / this->sensitivity_uv_) * this->wfac_); } if (this->uv_sensor_ != nullptr) { @@ -107,24 +108,38 @@ void LTR390Component::read_mode_(int mode_index) { ctrl[LTR390_CTRL_EN] = true; this->reg(LTR390_MAIN_CTRL) = ctrl.to_ulong(); - // After the sensor integration time do the following - this->set_timeout(((uint32_t) RESOLUTIONVALUE[this->res_]) * 100 + LTR390_WAKEUP_TIME + LTR390_SETTLE_TIME, - [this, mode_index]() { - // Read from the sensor - std::get<1>(this->mode_funcs_[mode_index])(); + uint32_t int_time{0}; + // Set gain, resolution and measurement rate + switch (mode) { + case LTR390_MODE_ALS: + this->reg(LTR390_GAIN) = this->gain_als_; + this->reg(LTR390_MEAS_RATE) = RESOLUTION_SETTING[this->res_als_]; + int_time = ((uint32_t) RESOLUTIONVALUE[this->res_als_]) * 100; + break; + case LTR390_MODE_UVS: + this->reg(LTR390_GAIN) = this->gain_uv_; + this->reg(LTR390_MEAS_RATE) = RESOLUTION_SETTING[this->res_uv_]; + int_time = ((uint32_t) RESOLUTIONVALUE[this->res_uv_]) * 100; + break; + } - // If there are more modes to read then begin the next - // otherwise stop - if (mode_index + 1 < (int) this->mode_funcs_.size()) { - this->read_mode_(mode_index + 1); - } else { - // put sensor in standby - std::bitset<8> ctrl = this->reg(LTR390_MAIN_CTRL).get(); - ctrl[LTR390_CTRL_EN] = false; - this->reg(LTR390_MAIN_CTRL) = ctrl.to_ulong(); - this->reading_ = false; - } - }); + // After the sensor integration time do the following + this->set_timeout(int_time + LTR390_WAKEUP_TIME + LTR390_SETTLE_TIME, [this, mode_index]() { + // Read from the sensor + std::get<1>(this->mode_funcs_[mode_index])(); + + // If there are more modes to read then begin the next + // otherwise stop + if (mode_index + 1 < (int) this->mode_funcs_.size()) { + this->read_mode_(mode_index + 1); + } else { + // put sensor in standby + std::bitset<8> ctrl = this->reg(LTR390_MAIN_CTRL).get(); + ctrl[LTR390_CTRL_EN] = false; + this->reg(LTR390_MAIN_CTRL) = ctrl.to_ulong(); + this->reading_ = false; + } + }); } void LTR390Component::setup() { @@ -151,16 +166,10 @@ void LTR390Component::setup() { return; } - // Set gain - this->reg(LTR390_GAIN) = gain_; - - // Set resolution and measurement rate - this->reg(LTR390_MEAS_RATE) = RESOLUTION_SETTING[this->res_]; - // Set sensitivity by linearly scaling against known value in the datasheet - float gain_scale = GAINVALUES[this->gain_] / GAIN_MAX; - float intg_scale = (RESOLUTIONVALUE[this->res_] * 100) / INTG_MAX; - this->sensitivity_ = SENSITIVITY_MAX * gain_scale * intg_scale; + float gain_scale_uv = GAINVALUES[this->gain_uv_] / GAIN_MAX; + float intg_scale_uv = (RESOLUTIONVALUE[this->res_uv_] * 100) / INTG_MAX; + this->sensitivity_uv_ = SENSITIVITY_MAX * gain_scale_uv * intg_scale_uv; // Set sensor read state this->reading_ = false; @@ -176,7 +185,13 @@ void LTR390Component::setup() { } } -void LTR390Component::dump_config() { LOG_I2C_DEVICE(this); } +void LTR390Component::dump_config() { + LOG_I2C_DEVICE(this); + ESP_LOGCONFIG(TAG, " ALS Gain: X%.0f", GAINVALUES[this->gain_als_]); + ESP_LOGCONFIG(TAG, " ALS Resolution: %u-bit", RESOLUTION_BITS[this->res_als_]); + ESP_LOGCONFIG(TAG, " UV Gain: X%.0f", GAINVALUES[this->gain_uv_]); + ESP_LOGCONFIG(TAG, " UV Resolution: %u-bit", RESOLUTION_BITS[this->res_uv_]); +} void LTR390Component::update() { if (!this->reading_ && !mode_funcs_.empty()) { diff --git a/esphome/components/ltr390/ltr390.h b/esphome/components/ltr390/ltr390.h index bc98518fe9..24afd3c411 100644 --- a/esphome/components/ltr390/ltr390.h +++ b/esphome/components/ltr390/ltr390.h @@ -49,8 +49,10 @@ class LTR390Component : public PollingComponent, public i2c::I2CDevice { void dump_config() override; void update() override; - void set_gain_value(LTR390GAIN gain) { this->gain_ = gain; } - void set_res_value(LTR390RESOLUTION res) { this->res_ = res; } + void set_als_gain_value(LTR390GAIN gain) { this->gain_als_ = gain; } + void set_uv_gain_value(LTR390GAIN gain) { this->gain_uv_ = gain; } + void set_als_res_value(LTR390RESOLUTION res) { this->res_als_ = res; } + void set_uv_res_value(LTR390RESOLUTION res) { this->res_uv_ = res; } void set_wfac_value(float wfac) { this->wfac_ = wfac; } void set_light_sensor(sensor::Sensor *light_sensor) { this->light_sensor_ = light_sensor; } @@ -71,9 +73,11 @@ class LTR390Component : public PollingComponent, public i2c::I2CDevice { // a list of modes and corresponding read functions std::vector>> mode_funcs_; - LTR390GAIN gain_; - LTR390RESOLUTION res_; - float sensitivity_; + LTR390GAIN gain_als_; + LTR390GAIN gain_uv_; + LTR390RESOLUTION res_als_; + LTR390RESOLUTION res_uv_; + float sensitivity_uv_; float wfac_; sensor::Sensor *light_sensor_{nullptr}; diff --git a/esphome/components/ltr390/sensor.py b/esphome/components/ltr390/sensor.py index 8b2676599c..62c3edf8cb 100644 --- a/esphome/components/ltr390/sensor.py +++ b/esphome/components/ltr390/sensor.py @@ -13,7 +13,7 @@ from esphome.const import ( UNIT_LUX, ) -CODEOWNERS = ["@sjtrny"] +CODEOWNERS = ["@sjtrny", "@latonita"] DEPENDENCIES = ["i2c"] ltr390_ns = cg.esphome_ns.namespace("ltr390") @@ -76,8 +76,24 @@ CONFIG_SCHEMA = cv.All( accuracy_decimals=1, device_class=DEVICE_CLASS_EMPTY, ), - cv.Optional(CONF_GAIN, default="X18"): cv.enum(GAIN_OPTIONS), - cv.Optional(CONF_RESOLUTION, default=20): cv.enum(RES_OPTIONS), + cv.Optional(CONF_GAIN, default="X18"): cv.Any( + cv.enum(GAIN_OPTIONS), + cv.Schema( + { + cv.Required(CONF_AMBIENT_LIGHT): cv.enum(GAIN_OPTIONS), + cv.Required(CONF_UV): cv.enum(GAIN_OPTIONS), + } + ), + ), + cv.Optional(CONF_RESOLUTION, default=20): cv.Any( + cv.enum(RES_OPTIONS), + cv.Schema( + { + cv.Required(CONF_AMBIENT_LIGHT): cv.enum(RES_OPTIONS), + cv.Required(CONF_UV): cv.enum(RES_OPTIONS), + } + ), + ), cv.Optional(CONF_WINDOW_CORRECTION_FACTOR, default=1.0): cv.float_range( min=1.0 ), @@ -101,11 +117,25 @@ async def to_code(config): await cg.register_component(var, config) await i2c.register_i2c_device(var, config) - cg.add(var.set_gain_value(config[CONF_GAIN])) - cg.add(var.set_res_value(config[CONF_RESOLUTION])) cg.add(var.set_wfac_value(config[CONF_WINDOW_CORRECTION_FACTOR])) for key, funcName in TYPES.items(): if key in config: sens = await sensor.new_sensor(config[key]) cg.add(getattr(var, funcName)(sens)) + + gain_value = config[CONF_GAIN] + if isinstance(gain_value, dict): + cg.add(var.set_als_gain_value(gain_value[CONF_AMBIENT_LIGHT])) + cg.add(var.set_uv_gain_value(gain_value[CONF_UV])) + else: + cg.add(var.set_als_gain_value(gain_value)) + cg.add(var.set_uv_gain_value(gain_value)) + + res_value = config[CONF_RESOLUTION] + if isinstance(res_value, dict): + cg.add(var.set_als_res_value(res_value[CONF_AMBIENT_LIGHT])) + cg.add(var.set_uv_res_value(res_value[CONF_UV])) + else: + cg.add(var.set_als_res_value(res_value)) + cg.add(var.set_uv_res_value(res_value)) diff --git a/tests/components/ltr390/test.esp32-ard.yaml b/tests/components/ltr390/test.esp32-ard.yaml index 9786c7dac3..bdfe349b77 100644 --- a/tests/components/ltr390/test.esp32-ard.yaml +++ b/tests/components/ltr390/test.esp32-ard.yaml @@ -18,3 +18,21 @@ sensor: window_correction_factor: 1.0 address: 0x53 update_interval: 60s + - platform: ltr390 + uv: + name: LTR390 UV + uv_index: + name: LTR390 UVI + light: + name: LTR390 Light + ambient_light: + name: LTR390 ALS + gain: + ambient_light: X9 + uv: X3 + resolution: + ambient_light: 18 + uv: 13 + window_correction_factor: 1.0 + address: 0x53 + update_interval: 60s diff --git a/tests/components/ltr390/test.esp8266-ard.yaml b/tests/components/ltr390/test.esp8266-ard.yaml index fee0f37ce1..149f46f9c8 100644 --- a/tests/components/ltr390/test.esp8266-ard.yaml +++ b/tests/components/ltr390/test.esp8266-ard.yaml @@ -13,7 +13,9 @@ sensor: name: LTR390 Light ambient_light: name: LTR390 ALS - gain: X3 + gain: + ambient_light: X9 + uv: X3 resolution: 18 window_correction_factor: 1.0 address: 0x53 From d1bfad98906433899d529875f9b0613d5fc6c9c0 Mon Sep 17 00:00:00 2001 From: Christian Ferbar <5595808+ferbar@users.noreply.github.com> Date: Thu, 11 Jul 2024 05:58:54 +0200 Subject: [PATCH 1754/2101] helpers.cpp: Fix GLIBCXX_RELEASE check < 8 (#7062) --- esphome/core/helpers.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/core/helpers.cpp b/esphome/core/helpers.cpp index 7f040f855f..e75b06ccd3 100644 --- a/esphome/core/helpers.cpp +++ b/esphome/core/helpers.cpp @@ -78,7 +78,7 @@ static const uint16_t CRC16_1021_BE_LUT_H[] = {0x0000, 0x1231, 0x2462, 0x3653, 0 // STL backports -#if _GLIBCXX_RELEASE < 7 +#if _GLIBCXX_RELEASE < 8 std::string to_string(int value) { return str_snprintf("%d", 32, value); } // NOLINT std::string to_string(long value) { return str_snprintf("%ld", 32, value); } // NOLINT std::string to_string(long long value) { return str_snprintf("%lld", 32, value); } // NOLINT From 114476d8b15f173aac926ec653c69fccc2dccdc7 Mon Sep 17 00:00:00 2001 From: Z3LIFF Date: Thu, 11 Jul 2024 00:01:14 -0400 Subject: [PATCH 1755/2101] Fix pmsa003i cold boot marked as failed on ESP32 et al (#7064) --- esphome/components/pmsa003i/pmsa003i.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/esphome/components/pmsa003i/pmsa003i.cpp b/esphome/components/pmsa003i/pmsa003i.cpp index ca3d28367a..a9665c6a5a 100644 --- a/esphome/components/pmsa003i/pmsa003i.cpp +++ b/esphome/components/pmsa003i/pmsa003i.cpp @@ -13,6 +13,15 @@ void PMSA003IComponent::setup() { PM25AQIData data; bool successful_read = this->read_data_(&data); + if (!successful_read) { + for (int i = 0; i < 3; i++) { + successful_read = this->read_data_(&data); + if (successful_read) { + break; + } + } + } + if (!successful_read) { this->mark_failed(); return; From 8d28c53fd3e72120fcc8bd13759e67ee4892e91f Mon Sep 17 00:00:00 2001 From: guillempages Date: Thu, 11 Jul 2024 06:08:51 +0200 Subject: [PATCH 1756/2101] [http_request] Fix follow_redirects on arduino (#7054) --- esphome/components/http_request/http_request_arduino.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/esphome/components/http_request/http_request_arduino.cpp b/esphome/components/http_request/http_request_arduino.cpp index 248a85a439..95b1cdc38e 100644 --- a/esphome/components/http_request/http_request_arduino.cpp +++ b/esphome/components/http_request/http_request_arduino.cpp @@ -32,6 +32,13 @@ std::shared_ptr HttpRequestArduino::start(std::string url, std::s watchdog::WatchdogManager wdm(this->get_watchdog_timeout()); + if (this->follow_redirects_) { + container->client_.setFollowRedirects(HTTPC_FORCE_FOLLOW_REDIRECTS); + container->client_.setRedirectLimit(this->redirect_limit_); + } else { + container->client_.setFollowRedirects(HTTPC_DISABLE_FOLLOW_REDIRECTS); + } + #if defined(USE_ESP8266) std::unique_ptr stream_ptr; #ifdef USE_HTTP_REQUEST_ESP8266_HTTPS @@ -59,8 +66,6 @@ std::shared_ptr HttpRequestArduino::start(std::string url, std::s "in your YAML, or use HTTPS"); } #endif // USE_ARDUINO_VERSION_CODE - - container->client_.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); bool status = container->client_.begin(*stream_ptr, url.c_str()); #elif defined(USE_RP2040) From 8a89dac5d541f631e491832965f00a4549eb0210 Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Thu, 11 Jul 2024 06:09:51 +0200 Subject: [PATCH 1757/2101] [ethernet] Fix compile warning for IPv6 (#7048) --- esphome/components/ethernet/ethernet_component.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index 6b34157b9d..962a864a29 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -394,7 +394,7 @@ void EthernetComponent::got_ip_event_handler(void *arg, esp_event_base_t event_b 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 +#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; #else global_eth_component->connected_ = true; @@ -407,8 +407,12 @@ void EthernetComponent::got_ip6_event_handler(void *arg, esp_event_base_t event_ 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); +#else + global_eth_component->connected_ = global_eth_component->got_ipv4_address_; +#endif } #endif /* USE_NETWORK_IPV6 */ From bdd0a36aa3ada035ead9eff3a1bc29d2993e4cb5 Mon Sep 17 00:00:00 2001 From: esphomebot Date: Thu, 11 Jul 2024 16:10:18 +1200 Subject: [PATCH 1758/2101] Update webserver local assets to 20240704-081526 (#7041) --- .../components/web_server/server_index_v2.h | 83 +- .../components/web_server/server_index_v3.h | 735 +++++++++--------- 2 files changed, 410 insertions(+), 408 deletions(-) diff --git a/esphome/components/web_server/server_index_v2.h b/esphome/components/web_server/server_index_v2.h index c942cda592..c9932624ba 100644 --- a/esphome/components/web_server/server_index_v2.h +++ b/esphome/components/web_server/server_index_v2.h @@ -68,7 +68,7 @@ const uint8_t INDEX_GZ[] PROGMEM = { 0xe3, 0x9b, 0x82, 0xde, 0xc5, 0x0e, 0x21, 0xa9, 0x64, 0x54, 0x44, 0x2c, 0x97, 0x29, 0x21, 0x29, 0xc2, 0x3f, 0x90, 0x45, 0x68, 0xd6, 0x13, 0xec, 0x34, 0x30, 0x9c, 0xcb, 0x40, 0x71, 0x17, 0x3c, 0xe0, 0xc9, 0x9c, 0xa6, 0x82, 0xa6, 0xc1, 0x5f, 0x71, 0x4a, 0x87, 0x31, 0x40, 0xb1, 0xd3, 0xc4, 0xe3, 0x30, 0x3b, 0x1f, 0x87, 0xc9, 0x88, 0x46, 0xc1, - 0x8d, 0xc8, 0xf1, 0xdf, 0x89, 0x3b, 0x64, 0x49, 0x18, 0xb3, 0x5f, 0x69, 0xe4, 0x6a, 0x69, 0x70, 0xeb, 0xd0, 0x5b, + 0x8d, 0xc8, 0xf1, 0xdf, 0x89, 0x3b, 0x64, 0x49, 0x18, 0xb3, 0x5f, 0x69, 0xe4, 0x6a, 0x69, 0x70, 0xe6, 0xd0, 0x5b, 0x41, 0x93, 0x28, 0x73, 0x9e, 0xbf, 0x7b, 0xf9, 0x42, 0xef, 0x63, 0x45, 0x40, 0xa0, 0x45, 0x36, 0x9b, 0xd2, 0xd4, 0x43, 0x58, 0x0b, 0x88, 0x67, 0x4c, 0x32, 0xc7, 0x97, 0xe1, 0x54, 0x95, 0xb0, 0xec, 0xfd, 0x34, 0x0a, 0x05, 0x7d, 0x43, 0x93, 0x88, 0x25, 0x23, 0xb2, 0xd3, 0x54, 0xe5, 0xe3, 0x50, 0x57, 0x44, 0x45, 0xd1, 0xe5, 0xee, 0xb3, 0x58, @@ -150,19 +150,19 @@ const uint8_t INDEX_GZ[] PROGMEM = { 0xa6, 0x57, 0xfd, 0xcf, 0xf9, 0x64, 0x0a, 0xda, 0xd8, 0x0a, 0x49, 0x8f, 0xa8, 0x9e, 0xb0, 0xac, 0xcf, 0x37, 0x94, 0x55, 0xfa, 0xc8, 0xf3, 0x58, 0xa1, 0xa6, 0xc2, 0x5e, 0xde, 0x69, 0xe4, 0xb3, 0xa2, 0xa8, 0x60, 0x1c, 0x9b, 0x9c, 0x2a, 0xe7, 0xab, 0x2e, 0x19, 0x53, 0xf1, 0xda, 0x63, 0x8a, 0x0f, 0x33, 0xe0, 0x75, 0x16, 0xfb, 0x31, 0xe4, 0x6e, - 0xef, 0x7f, 0x5e, 0x22, 0x67, 0x91, 0xaf, 0xa0, 0x6f, 0x91, 0xe7, 0xb7, 0xca, 0xc8, 0xc6, 0xb7, 0xdb, 0xad, 0xe1, - 0xb2, 0x4e, 0x1b, 0x8b, 0xbd, 0x3e, 0xbe, 0x5d, 0x57, 0x1d, 0xc9, 0x62, 0xc2, 0x23, 0x1a, 0xb8, 0x7c, 0x4a, 0x13, - 0x37, 0x07, 0xaf, 0xaa, 0xde, 0xfb, 0x81, 0xf0, 0x16, 0x6f, 0xab, 0xee, 0xd5, 0xe0, 0x36, 0x07, 0xef, 0xd7, 0xd7, + 0xef, 0x7f, 0x5e, 0x22, 0x67, 0x91, 0xaf, 0xa0, 0x6f, 0x91, 0xe7, 0x67, 0xca, 0xc8, 0xc6, 0x67, 0xdb, 0xad, 0xe1, + 0xb2, 0x4e, 0x1b, 0x8b, 0xbd, 0x3e, 0x3e, 0x5b, 0x57, 0x1d, 0xc9, 0x62, 0xc2, 0x23, 0x1a, 0xb8, 0x7c, 0x4a, 0x13, + 0x37, 0x07, 0xaf, 0xaa, 0xde, 0xfb, 0x81, 0xf0, 0x16, 0x6f, 0xab, 0xee, 0xd5, 0xe0, 0x2c, 0x07, 0xef, 0xd7, 0xd7, 0xeb, 0x8e, 0xd7, 0xef, 0x69, 0x9a, 0x49, 0x45, 0xb4, 0xd0, 0x69, 0xbf, 0x2e, 0xc5, 0xd2, 0xd7, 0xc1, 0xd6, 0xf6, 0xa5, 0x09, 0xe2, 0x36, 0xfd, 0x63, 0xff, 0xc0, 0x45, 0xd2, 0x2d, 0xfc, 0x93, 0x3e, 0xf0, 0x1f, 0x8c, 0x5b, 0xf8, 0x19, 0xf9, 0x50, 0xf5, 0x0a, 0x47, 0x82, 0x3c, 0xeb, 0x3e, 0x33, 0x16, 0x33, 0x8f, 0xd9, 0xe0, 0xce, 0x73, 0x63, 0x26, 0xea, 0x10, 0x7a, 0x73, 0xf1, 0x42, 0x55, 0x80, 0x4b, 0x51, 0xba, 0xb3, 0x73, 0x63, 0xeb, 0x61, 0x21, 0x88, 0xbb, 0x1b, 0x33, 0xb1, 0xeb, 0xe2, 0x09, 0xb9, 0x82, 0x1f, 0xbb, 0x0b, 0xef, 0x65, 0x28, 0xc6, 0x7e, 0x1a, 0x26, - 0x11, 0x9f, 0x78, 0xa8, 0xe6, 0xba, 0xc8, 0xcf, 0xa4, 0xbd, 0xf1, 0x18, 0xe5, 0xbb, 0x57, 0xf8, 0x4c, 0x10, 0xb7, - 0xeb, 0xd6, 0x26, 0xf8, 0x95, 0x20, 0x57, 0xa7, 0xbb, 0x8b, 0x33, 0x91, 0x77, 0xae, 0xf0, 0x59, 0xe1, 0xb1, 0xc7, - 0x6f, 0x88, 0x87, 0x48, 0xe7, 0x4c, 0x43, 0x73, 0xce, 0x27, 0xca, 0x73, 0xef, 0x22, 0xfc, 0x1e, 0xe2, 0x2a, 0x69, - 0xc9, 0x6d, 0x74, 0x68, 0x65, 0x87, 0xb8, 0x5c, 0xba, 0x08, 0xdc, 0xbd, 0x3d, 0xab, 0xac, 0x50, 0x15, 0xf0, 0xad, - 0x20, 0x15, 0x83, 0x1c, 0xbf, 0x95, 0x11, 0x9a, 0x5b, 0xe1, 0xa5, 0xc8, 0x0c, 0xe3, 0x19, 0x3f, 0xb4, 0x3e, 0x9a, + 0x11, 0x9f, 0x78, 0xa8, 0xe6, 0xba, 0xc8, 0xcf, 0xa4, 0xbd, 0xf1, 0x18, 0xe5, 0xbb, 0x57, 0xf8, 0x56, 0x10, 0xb7, + 0xeb, 0xd6, 0x26, 0xf8, 0x95, 0x20, 0x57, 0xa7, 0xbb, 0x8b, 0x5b, 0x91, 0x77, 0xae, 0xf0, 0x6d, 0xe1, 0xb1, 0xc7, + 0x6f, 0x88, 0x87, 0x48, 0xe7, 0x56, 0x43, 0x73, 0xce, 0x27, 0xca, 0x73, 0xef, 0x22, 0xfc, 0x1e, 0xe2, 0x2a, 0x69, + 0xc9, 0x6d, 0x74, 0x68, 0x65, 0x87, 0xb8, 0x5c, 0xba, 0x08, 0xdc, 0xbd, 0x3d, 0xab, 0xac, 0x50, 0x15, 0xf0, 0x99, + 0x20, 0x15, 0x83, 0x1c, 0xbf, 0x95, 0x11, 0x9a, 0x33, 0xe1, 0xa5, 0xc8, 0x0c, 0xe3, 0x19, 0x3f, 0xb4, 0x3e, 0x9a, 0x69, 0x4f, 0x79, 0x18, 0x7c, 0x26, 0x68, 0x1a, 0x0a, 0x9e, 0xf6, 0x91, 0xad, 0x7e, 0xe0, 0xbf, 0x91, 0xab, 0x9e, 0xf3, 0x9f, 0xbe, 0xf8, 0x79, 0xf8, 0x73, 0xda, 0xbf, 0xc2, 0xaf, 0xc9, 0xfe, 0xa9, 0xd7, 0x0d, 0xbc, 0x9d, 0x7a, 0x7d, 0xf9, 0xf3, 0x7e, 0xef, 0x1f, 0x61, 0xfd, 0xd7, 0xb3, 0xfa, 0x4f, 0x7d, 0xb4, 0xf4, 0x7e, 0xde, 0xef, 0xf6, @@ -177,7 +177,7 @@ const uint8_t INDEX_GZ[] PROGMEM = { 0xf2, 0x03, 0x64, 0x81, 0xc0, 0xf3, 0x30, 0x9e, 0xd1, 0x2c, 0xa0, 0x39, 0xc2, 0x03, 0x72, 0x21, 0xbc, 0x26, 0xc2, 0xcf, 0x05, 0xfc, 0x68, 0x21, 0x7c, 0xa1, 0x03, 0x98, 0x70, 0x90, 0x15, 0x51, 0x25, 0x5c, 0x69, 0x2c, 0x2e, 0xc2, 0xd3, 0x0d, 0x95, 0x62, 0x0c, 0xde, 0x05, 0x84, 0x87, 0x95, 0x70, 0x27, 0xbe, 0x21, 0x86, 0x24, 0xde, 0xa5, 0x94, - 0xfe, 0x10, 0xc6, 0x1f, 0x69, 0xea, 0x9d, 0xe1, 0x66, 0xeb, 0x31, 0x96, 0x2e, 0xe8, 0x9d, 0x26, 0x6a, 0x17, 0xb1, + 0xfe, 0x10, 0xc6, 0x1f, 0x69, 0xea, 0xdd, 0xe2, 0x66, 0xeb, 0x31, 0x96, 0x2e, 0xe8, 0x9d, 0x26, 0x6a, 0x17, 0xb1, 0xaa, 0x73, 0xa1, 0x62, 0x04, 0x20, 0x64, 0xab, 0xbe, 0x18, 0xd8, 0xf1, 0x9d, 0x74, 0xcd, 0x61, 0x95, 0x86, 0x37, 0x2e, 0xaa, 0xc6, 0x45, 0x59, 0x32, 0x0f, 0x63, 0x16, 0x39, 0x82, 0x4e, 0xa6, 0x71, 0x28, 0xa8, 0xa3, 0xd7, 0xeb, 0x84, 0x30, 0x90, 0x5b, 0xa8, 0x0c, 0x91, 0x65, 0x70, 0x46, 0x26, 0xe0, 0x04, 0x67, 0xc5, 0x83, 0xe8, 0x94, 0x56, @@ -220,10 +220,10 @@ const uint8_t INDEX_GZ[] PROGMEM = { 0x73, 0xd4, 0x69, 0xa0, 0x45, 0xa5, 0xad, 0xd4, 0x99, 0xaa, 0x71, 0xf4, 0x82, 0x4f, 0xcf, 0x49, 0xa3, 0x3d, 0x3f, 0x1d, 0xb5, 0xe7, 0xb5, 0x1a, 0xca, 0x0c, 0x69, 0xcd, 0x7a, 0xf3, 0x3e, 0x7e, 0x03, 0x4e, 0x3d, 0x9b, 0x96, 0x70, 0x65, 0x79, 0x2d, 0xbd, 0xbc, 0x5a, 0x2d, 0xc9, 0x51, 0xdb, 0xea, 0x3a, 0x52, 0x5d, 0xf3, 0x5c, 0xe1, 0x64, 0x95, - 0xd4, 0x4e, 0x90, 0x2c, 0x81, 0x64, 0x28, 0x42, 0xc8, 0x99, 0x40, 0x1b, 0x47, 0x85, 0x31, 0xa1, 0xbb, 0x3c, 0xb3, + 0xd4, 0x4e, 0x90, 0x2c, 0x81, 0x64, 0x28, 0x42, 0xc8, 0xad, 0x40, 0x1b, 0x47, 0x85, 0x31, 0xa1, 0xbb, 0x3c, 0xb3, 0xc0, 0x3e, 0x95, 0x94, 0xf0, 0x00, 0x0b, 0xd0, 0xb5, 0xf0, 0x04, 0x4f, 0xf0, 0xac, 0xd6, 0x94, 0x64, 0x5e, 0x6f, 0xb6, 0xab, 0x63, 0x3d, 0x2a, 0xc7, 0xc2, 0xb3, 0x1a, 0x99, 0x14, 0x58, 0xca, 0x93, 0x5a, 0x2d, 0xaf, 0x06, 0x3b, - 0xcd, 0xc9, 0xad, 0x04, 0x20, 0xce, 0x56, 0x93, 0x32, 0x8c, 0x84, 0x2d, 0x65, 0x2a, 0xf3, 0x59, 0x92, 0xd0, 0x14, + 0xcd, 0xc9, 0xad, 0x04, 0x20, 0x6e, 0x57, 0x93, 0x32, 0x8c, 0x84, 0x2d, 0x65, 0x2a, 0xf3, 0x59, 0x92, 0xd0, 0x14, 0xa4, 0x28, 0x11, 0x98, 0xe5, 0x79, 0x29, 0xd9, 0x41, 0x8c, 0x62, 0x4a, 0x52, 0xe0, 0x3c, 0xd2, 0xee, 0xc2, 0x09, 0xe6, 0x78, 0x2c, 0xf9, 0x06, 0x21, 0xe4, 0xc2, 0xa4, 0xb3, 0x08, 0xc9, 0x83, 0x62, 0xc2, 0x2c, 0x99, 0x94, 0x11, 0xea, 0x5f, 0xee, 0x9e, 0xf3, 0x7b, 0x6d, 0xb2, 0x1e, 0xeb, 0x07, 0xb2, 0x59, 0xac, 0x39, 0x57, 0x48, 0xde, 0x7b, @@ -238,14 +238,14 @@ const uint8_t INDEX_GZ[] PROGMEM = { 0x13, 0xf3, 0xec, 0xa5, 0x5f, 0xd6, 0xca, 0xc6, 0x97, 0xbb, 0x67, 0xef, 0x37, 0x35, 0x83, 0xf2, 0x7c, 0x56, 0xda, 0xf8, 0x12, 0xbe, 0x05, 0x8d, 0x83, 0x85, 0x16, 0x0e, 0x01, 0xcb, 0xb1, 0x14, 0x48, 0x41, 0x96, 0x17, 0xae, 0x91, 0xa7, 0x38, 0x21, 0x32, 0x0c, 0x54, 0xdd, 0x35, 0xad, 0xe6, 0x31, 0x9e, 0x5c, 0x0c, 0xf8, 0x94, 0x6e, 0x89, 0x0d, - 0x9d, 0x21, 0x9f, 0x4d, 0x20, 0x75, 0x46, 0x82, 0xce, 0xf0, 0x4e, 0x03, 0xb5, 0xab, 0xe2, 0x2b, 0x91, 0x44, 0xca, + 0xdd, 0x22, 0x9f, 0x4d, 0x20, 0x75, 0x46, 0x82, 0xce, 0xf0, 0x4e, 0x03, 0xb5, 0xab, 0xe2, 0x2b, 0x91, 0x44, 0xca, 0x2b, 0xb2, 0x05, 0x8f, 0x49, 0x03, 0xc7, 0xa4, 0x81, 0x43, 0x92, 0xf5, 0x1a, 0x4a, 0x40, 0xb4, 0xc3, 0x62, 0x5c, 0x25, 0x66, 0x20, 0x2b, 0x4c, 0x9f, 0x56, 0x25, 0x80, 0xa3, 0x76, 0x28, 0x7d, 0x8f, 0x52, 0xa6, 0x47, 0x92, 0x2c, 0xde, 0x7a, 0x1c, 0x73, 0x39, 0xf0, 0x05, 0xbb, 0x8e, 0x21, 0xb1, 0x04, 0x56, 0x85, 0x05, 0x0a, 0x8a, 0xa6, 0x4d, 0xdd, 0x34, 0xf4, 0xe5, 0x3e, 0x71, 0x1c, 0xfa, 0xc0, 0xb9, 0x71, 0xa8, 0xf3, 0x70, 0xb2, 0xf5, 0x2e, 0xc7, 0x7b, 0x7b, 0x9e, 0xea, 0xf4, 0x8b, 0xf0, 0xb8, 0xa9, 0x2f, 0x23, 0x77, 0xdf, 0x2b, 0x5e, 0x11, 0x21, 0x09, 0x7f, 0xad, 0x16, 0xf7, 0x73, 0x08, 0x43, 0x7b, 0x61, 0x15, 0x83, 0x06, 0x78, 0xa9, 0xeb, 0x55, 0x97, 0x5f, 0xab, 0x15, 0x51, - 0xda, 0x2a, 0xb6, 0xce, 0x70, 0x92, 0xcf, 0xbd, 0x22, 0xf5, 0xa7, 0xb1, 0x96, 0x2f, 0x65, 0x40, 0x40, 0xcc, 0xa6, + 0xda, 0x2a, 0xb6, 0x6e, 0x71, 0x92, 0xcf, 0xbd, 0x22, 0xf5, 0xa7, 0xb1, 0x96, 0x2f, 0x65, 0x40, 0x40, 0xcc, 0xa6, 0x59, 0x66, 0x16, 0x63, 0x1d, 0x09, 0x06, 0xed, 0xbe, 0xd1, 0x59, 0x0b, 0x58, 0x66, 0x57, 0xe9, 0x46, 0x86, 0x9d, 0xb5, 0x50, 0x60, 0x1a, 0x41, 0x54, 0x0a, 0x1a, 0xd5, 0x72, 0x4d, 0xde, 0x6f, 0xd7, 0x73, 0x2e, 0x71, 0x86, 0xb4, 0x93, 0x4b, 0x42, 0x21, 0x91, 0xd5, 0x2a, 0x90, 0xf2, 0x9c, 0x4c, 0xb7, 0x93, 0xfc, 0x99, 0x45, 0xf2, 0x4f, 0x08, @@ -268,7 +268,7 @@ const uint8_t INDEX_GZ[] PROGMEM = { 0x36, 0x44, 0x4d, 0xa5, 0xd4, 0x91, 0x2d, 0x50, 0xd1, 0xc1, 0x9f, 0x7b, 0x4c, 0x2b, 0x6e, 0x26, 0x6e, 0x06, 0x0c, 0xf8, 0x89, 0xf0, 0x54, 0x30, 0x0a, 0x64, 0x06, 0xf7, 0x67, 0x5e, 0x65, 0xea, 0x36, 0x97, 0xdd, 0xb0, 0x46, 0xdc, 0xd8, 0x46, 0x13, 0x97, 0x71, 0xbd, 0xf3, 0x92, 0x97, 0x0e, 0x55, 0x06, 0xb5, 0x30, 0x5c, 0xb0, 0x4c, 0x24, 0xb1, - 0x96, 0x3f, 0x54, 0x49, 0xd1, 0x45, 0x23, 0x4c, 0x25, 0x18, 0xef, 0xe4, 0x1e, 0xd0, 0x1c, 0xfe, 0x2e, 0x6e, 0x85, + 0x96, 0x3f, 0x54, 0x49, 0xd1, 0x45, 0x23, 0x4c, 0x25, 0x18, 0xef, 0xe4, 0x1e, 0xd0, 0x1c, 0xfe, 0x2e, 0xce, 0x84, 0xb5, 0xa3, 0xc6, 0x89, 0x2d, 0xe7, 0xb4, 0xa4, 0xfe, 0x5b, 0x48, 0x75, 0x59, 0x3d, 0xf3, 0xcf, 0xa5, 0x2c, 0x64, 0x38, 0xab, 0x30, 0xf6, 0x44, 0x32, 0x76, 0x04, 0x7a, 0x9a, 0x49, 0xfc, 0xee, 0xea, 0x8c, 0x17, 0xa6, 0xa5, 0x9c, 0x26, 0xb1, 0x37, 0x45, 0xb4, 0xdc, 0xfa, 0xbd, 0xb2, 0x1b, 0x01, 0x23, 0x90, 0x05, 0x84, 0x35, 0x67, 0x4f, 0x10, @@ -312,7 +312,7 @@ const uint8_t INDEX_GZ[] PROGMEM = { 0xf1, 0xb5, 0x7b, 0x78, 0x63, 0x02, 0x1e, 0xb4, 0x87, 0x4d, 0x61, 0x19, 0xdb, 0x99, 0xba, 0x07, 0x64, 0x8f, 0x4f, 0xb8, 0xd1, 0xdd, 0xaa, 0x56, 0xc6, 0x1b, 0xb0, 0xff, 0x11, 0x1e, 0x9b, 0xcb, 0x71, 0x54, 0x73, 0x60, 0x1a, 0x2c, 0xf2, 0xc2, 0x29, 0xc0, 0x95, 0xf2, 0x96, 0x22, 0xcc, 0x73, 0x19, 0xe0, 0xfe, 0x16, 0x7f, 0xa7, 0x59, 0xe2, 0xb0, - 0xe0, 0x38, 0xb7, 0x0f, 0xe5, 0x88, 0x0a, 0xfc, 0x22, 0x7e, 0x0f, 0x74, 0x2c, 0x29, 0x34, 0x37, 0x54, 0xf4, 0x94, + 0xe0, 0x38, 0x67, 0x0f, 0xe5, 0x88, 0x0a, 0xfc, 0x22, 0x7e, 0x0f, 0x74, 0x2c, 0x29, 0x34, 0x37, 0x54, 0xf4, 0x94, 0xeb, 0x85, 0x6c, 0x4d, 0x4b, 0xc5, 0xb4, 0x48, 0xa9, 0x91, 0xd3, 0x6c, 0xc8, 0xe3, 0x34, 0x56, 0xb6, 0x28, 0x4e, 0x55, 0x65, 0x5e, 0xb4, 0x05, 0x8b, 0x65, 0x68, 0x71, 0xb9, 0xf4, 0xaa, 0xa8, 0x26, 0xcc, 0x8a, 0x64, 0x20, 0xcc, 0xac, 0x8c, 0x8a, 0x8a, 0x66, 0xad, 0xfa, 0x78, 0x68, 0x35, 0xa1, 0xc8, 0xe8, 0xe6, 0x15, 0x38, 0x6c, 0x17, 0x82, @@ -612,31 +612,32 @@ const uint8_t INDEX_GZ[] PROGMEM = { 0xde, 0x0b, 0x3e, 0xda, 0x3c, 0x56, 0xcc, 0x47, 0x5d, 0x79, 0x05, 0x42, 0xdd, 0xb5, 0x35, 0xca, 0x2f, 0x8f, 0xdd, 0xce, 0xa9, 0x56, 0x06, 0x1c, 0x19, 0x0e, 0x77, 0x8f, 0x1a, 0xe6, 0x56, 0x45, 0xcc, 0x47, 0x70, 0x20, 0x55, 0x17, 0x6b, 0x92, 0x8a, 0xc7, 0x7d, 0xdc, 0xec, 0x9c, 0x86, 0x8e, 0xe4, 0x2d, 0x92, 0x79, 0x64, 0xc1, 0x3e, 0x74, 0x1e, - 0xf3, 0x09, 0xf5, 0x19, 0xdf, 0xbf, 0xa1, 0xd7, 0xf5, 0x70, 0xca, 0x4a, 0xf7, 0x36, 0x28, 0x1d, 0xc5, 0x94, 0xbc, - 0x9c, 0x09, 0x7e, 0x86, 0x2b, 0x8b, 0x94, 0x2c, 0x3c, 0xd7, 0xbe, 0x73, 0xb0, 0x55, 0x80, 0x84, 0x5c, 0x47, 0x71, - 0x78, 0xe3, 0x63, 0xd7, 0xb2, 0x37, 0x77, 0x3b, 0xff, 0xfa, 0x3f, 0xfe, 0x97, 0x76, 0x9b, 0x9f, 0xee, 0x8f, 0x9b, - 0x66, 0xac, 0x15, 0x44, 0xe7, 0xa7, 0x70, 0x11, 0xb1, 0x8c, 0xf3, 0xd2, 0xdb, 0xfa, 0x28, 0x65, 0x51, 0x7d, 0x1c, - 0xc6, 0x43, 0xb7, 0xb3, 0x1d, 0x41, 0xf6, 0x0d, 0x24, 0x0d, 0x75, 0xb5, 0x08, 0x48, 0xf0, 0x37, 0xdd, 0xa1, 0x31, - 0x57, 0x31, 0xe4, 0x69, 0xb5, 0x6f, 0xd4, 0x94, 0x07, 0xaa, 0x72, 0xab, 0x26, 0xd5, 0x5f, 0xaf, 0xd2, 0x4c, 0x2d, - 0xad, 0x5c, 0xa6, 0xc9, 0x5d, 0xa7, 0x88, 0x53, 0xfd, 0xdf, 0xff, 0xf9, 0x5f, 0xfe, 0x9b, 0x79, 0x84, 0xf0, 0xd3, - 0xbf, 0xfe, 0xf7, 0xff, 0xfc, 0x7f, 0xfe, 0xf7, 0x7f, 0x85, 0x0b, 0x18, 0x3a, 0x44, 0x25, 0xf9, 0x84, 0x53, 0xc6, - 0xa7, 0x14, 0xc3, 0x70, 0x20, 0x47, 0x71, 0xc2, 0x32, 0xc1, 0x06, 0xd5, 0xeb, 0x35, 0x17, 0x72, 0x42, 0x79, 0xd8, - 0x34, 0x74, 0xf2, 0xd0, 0xe6, 0x25, 0x8d, 0x54, 0x50, 0x2e, 0x69, 0x31, 0x3f, 0xdd, 0x07, 0x7c, 0x3f, 0xec, 0x46, - 0xa2, 0x5f, 0x6c, 0xc7, 0xc2, 0x38, 0x65, 0xa1, 0x24, 0x2f, 0xcb, 0x1d, 0x08, 0x97, 0x2c, 0xe0, 0x31, 0x68, 0x59, - 0xc5, 0x72, 0xf7, 0x2a, 0x7d, 0xda, 0x1f, 0x66, 0x99, 0x60, 0x43, 0x40, 0xb9, 0x72, 0xfd, 0xca, 0xc8, 0x74, 0x1d, - 0xd4, 0xbf, 0xf8, 0x2e, 0x97, 0xa3, 0x28, 0xdb, 0xfa, 0xf0, 0xe4, 0x4f, 0xf9, 0x5f, 0x26, 0xa0, 0x64, 0x39, 0xde, - 0x24, 0xbc, 0xd5, 0x16, 0xf7, 0x71, 0xa3, 0x31, 0xbd, 0x45, 0x8b, 0x72, 0x06, 0xbc, 0x6d, 0x32, 0xe9, 0x2e, 0xb6, - 0x07, 0x94, 0x21, 0xed, 0xc2, 0x33, 0xdd, 0x70, 0xc0, 0xbd, 0xed, 0x34, 0xf2, 0xfc, 0xcf, 0x0b, 0xe9, 0x1c, 0x65, - 0xbf, 0x42, 0xe8, 0x59, 0xfb, 0x91, 0xaf, 0xb9, 0xbd, 0xb8, 0x85, 0xd5, 0xab, 0xa5, 0x7a, 0x8d, 0x9b, 0xeb, 0x17, - 0xed, 0xec, 0xd0, 0xb9, 0x1d, 0xf4, 0x3e, 0x84, 0x30, 0xf6, 0xb8, 0x89, 0xc7, 0xad, 0x45, 0x31, 0xbc, 0x10, 0x7c, - 0x62, 0xc7, 0xca, 0x69, 0x48, 0x07, 0x74, 0x68, 0xfc, 0xef, 0xba, 0x5e, 0xc5, 0xc1, 0xf3, 0xf1, 0xc1, 0x86, 0xb9, - 0x34, 0x48, 0x32, 0x46, 0xee, 0x34, 0xf2, 0x2f, 0xe1, 0x04, 0x2e, 0x86, 0x31, 0x0f, 0x45, 0x20, 0x09, 0xb6, 0x6d, - 0x47, 0xdc, 0x43, 0x60, 0x33, 0x7c, 0x61, 0xc1, 0xd3, 0x56, 0x4d, 0xc1, 0x13, 0x5e, 0xbd, 0x0e, 0x99, 0xfb, 0xb2, - 0xbb, 0x3d, 0x94, 0x72, 0xa4, 0x7d, 0xaf, 0x03, 0xd9, 0xaf, 0x2a, 0x1e, 0x28, 0x2d, 0x63, 0x5a, 0x68, 0x73, 0xbd, - 0x12, 0xd5, 0xaa, 0xf6, 0x27, 0xe1, 0xb9, 0x12, 0x4c, 0x77, 0xb5, 0x95, 0x2c, 0x84, 0x56, 0xaf, 0xc8, 0xf7, 0x85, - 0x15, 0x14, 0x4e, 0xa7, 0xb2, 0x21, 0x6a, 0x9f, 0xee, 0x2b, 0xe5, 0x15, 0xb8, 0x87, 0xcc, 0xd2, 0x50, 0x49, 0x11, - 0xba, 0x91, 0x3e, 0x0a, 0xea, 0x97, 0x4e, 0x97, 0x80, 0xcf, 0x9a, 0x75, 0xfe, 0x1f, 0xd6, 0xb2, 0x30, 0xa4, 0x67, - 0x88, 0x00, 0x00}; + 0xf3, 0x09, 0xf5, 0x19, 0xdf, 0xbf, 0xa1, 0xd7, 0xf5, 0x70, 0xca, 0x4a, 0xf7, 0x36, 0x28, 0x1d, 0xc5, 0x94, 0xdc, + 0x78, 0xc4, 0xf5, 0x9d, 0xa3, 0x56, 0xe9, 0x6e, 0x3b, 0x04, 0x9b, 0xc7, 0xb8, 0xe6, 0xa4, 0x4f, 0xce, 0x02, 0x8b, + 0x77, 0x4e, 0xf7, 0xc3, 0x15, 0x8c, 0x48, 0x7e, 0x9f, 0x6b, 0x47, 0x3b, 0x18, 0x36, 0x40, 0x6f, 0xae, 0xa3, 0xc4, + 0x81, 0x71, 0xc8, 0x6b, 0x41, 0x9d, 0xbb, 0x9d, 0x7f, 0xfd, 0x1f, 0xff, 0x4b, 0xfb, 0xd8, 0x4f, 0xf7, 0xc7, 0x4d, + 0x33, 0xd6, 0xca, 0xae, 0xe4, 0xa7, 0x70, 0x6b, 0xb1, 0x0c, 0x0a, 0xd3, 0xdb, 0xfa, 0x28, 0x65, 0x51, 0x7d, 0x1c, + 0xc6, 0x43, 0xb7, 0xb3, 0x1d, 0x9b, 0xf6, 0x75, 0x25, 0x0d, 0x75, 0xb5, 0x08, 0xe8, 0xf5, 0x37, 0x5d, 0xb8, 0x31, + 0xf7, 0x36, 0xe4, 0xd1, 0xb6, 0xaf, 0xdf, 0x94, 0xa7, 0xaf, 0x72, 0x05, 0x27, 0xd5, 0x9f, 0xba, 0xd2, 0x1c, 0x30, + 0xad, 0xdc, 0xbc, 0xc9, 0x5d, 0xa7, 0x08, 0x6a, 0xfd, 0xdf, 0xff, 0xf9, 0x5f, 0xfe, 0x9b, 0x79, 0x84, 0x58, 0xd5, + 0xbf, 0xfe, 0xf7, 0xff, 0xfc, 0x7f, 0xfe, 0xf7, 0x7f, 0x85, 0xdb, 0x1a, 0x3a, 0x9e, 0x25, 0x99, 0x8a, 0x53, 0x06, + 0xb3, 0x14, 0x77, 0x71, 0x20, 0xa1, 0x71, 0xc2, 0x32, 0xc1, 0x06, 0xd5, 0xbb, 0x38, 0x17, 0x72, 0x42, 0x79, 0x32, + 0x35, 0x74, 0xf2, 0x84, 0xe7, 0x25, 0x41, 0x55, 0x50, 0x2e, 0x09, 0x37, 0x3f, 0xdd, 0x07, 0x7c, 0x3f, 0xec, 0xfa, + 0xa2, 0x5f, 0x6c, 0xc7, 0xc2, 0x90, 0x09, 0x94, 0xe4, 0x65, 0xb9, 0x03, 0xb1, 0x95, 0x05, 0x3c, 0x06, 0x2d, 0xab, + 0x58, 0xee, 0x5e, 0xa5, 0x4f, 0xfb, 0xc3, 0x2c, 0x13, 0x6c, 0x08, 0x28, 0x57, 0x7e, 0x62, 0x19, 0xc6, 0xae, 0x83, + 0xae, 0x18, 0xdf, 0xe5, 0x72, 0x14, 0x45, 0xa0, 0x87, 0x27, 0x7f, 0xca, 0xff, 0x32, 0x01, 0x8d, 0xcc, 0xf1, 0x26, + 0xe1, 0xad, 0x36, 0xcf, 0x8f, 0x1b, 0x8d, 0xe9, 0x2d, 0x5a, 0x94, 0x33, 0xe0, 0x6d, 0x93, 0x49, 0x3a, 0xb6, 0x07, + 0x94, 0xf1, 0xef, 0xc2, 0x8d, 0xdd, 0x70, 0xc0, 0x17, 0xee, 0x34, 0xf2, 0xfc, 0xcf, 0x0b, 0xe9, 0x49, 0x65, 0xbf, + 0x42, 0x9c, 0x5a, 0x3b, 0x9d, 0xaf, 0xb9, 0xbd, 0xb8, 0x85, 0xd5, 0xab, 0xa5, 0x7a, 0x8d, 0x9b, 0xeb, 0xb7, 0xf2, + 0xec, 0x38, 0xbb, 0x1d, 0x21, 0x3f, 0x84, 0x98, 0xf7, 0xb8, 0x89, 0xc7, 0xad, 0x45, 0x31, 0xbc, 0x10, 0x7c, 0x62, + 0x07, 0xd6, 0x69, 0x48, 0x07, 0x74, 0x68, 0x9c, 0xf5, 0xba, 0x5e, 0x05, 0xcd, 0xf3, 0xf1, 0xc1, 0x86, 0xb9, 0x34, + 0x48, 0x32, 0xa0, 0xee, 0x34, 0xf2, 0x2f, 0xe1, 0x04, 0x2e, 0x86, 0x31, 0x0f, 0x45, 0x20, 0x09, 0xb6, 0x6d, 0x87, + 0xe7, 0x43, 0xe0, 0x49, 0x7c, 0x61, 0xc1, 0xd3, 0x56, 0x4d, 0xc1, 0x6d, 0x5e, 0xbd, 0x3b, 0x99, 0xfb, 0xb2, 0xbb, + 0x3d, 0x94, 0xf2, 0xba, 0x7d, 0xaf, 0xa3, 0xde, 0xaf, 0x2a, 0xee, 0x2a, 0x2d, 0x90, 0x5a, 0x68, 0x73, 0xbd, 0x92, + 0xeb, 0xaa, 0xf6, 0x27, 0xe1, 0xb9, 0x12, 0x4c, 0x77, 0xb5, 0x95, 0x2c, 0x84, 0x56, 0xaf, 0xc8, 0xf7, 0x85, 0xc9, + 0x14, 0x4e, 0xa7, 0xb2, 0x21, 0x6a, 0x9f, 0xee, 0x2b, 0x4d, 0x17, 0xb8, 0x87, 0x4c, 0xe9, 0x50, 0x19, 0x14, 0xba, + 0x91, 0x3e, 0x0a, 0xea, 0x97, 0xce, 0xad, 0x80, 0x6f, 0xa0, 0x75, 0xfe, 0x1f, 0xa2, 0x48, 0xf6, 0xdd, 0x94, 0x88, + 0x00, 0x00}; } // namespace web_server } // namespace esphome diff --git a/esphome/components/web_server/server_index_v3.h b/esphome/components/web_server/server_index_v3.h index bde1ce1fb5..0c16ea9f37 100644 --- a/esphome/components/web_server/server_index_v3.h +++ b/esphome/components/web_server/server_index_v3.h @@ -3632,373 +3632,374 @@ const uint8_t INDEX_GZ[] PROGMEM = { 0xe7, 0xec, 0xd8, 0x98, 0x31, 0x94, 0x4f, 0x43, 0x40, 0x9e, 0xd0, 0xf7, 0x01, 0xcd, 0x25, 0x67, 0x23, 0xad, 0x2b, 0xfb, 0x10, 0x17, 0x97, 0xdc, 0x84, 0x6a, 0x31, 0x6f, 0x2b, 0x3d, 0x2a, 0xc4, 0x1b, 0x16, 0x80, 0x65, 0xe9, 0x69, 0x93, 0x82, 0x6c, 0x94, 0x54, 0x45, 0xfe, 0x13, 0xbf, 0x03, 0xae, 0xad, 0xac, 0xe4, 0x0a, 0x78, 0xf5, 0xff, 0xd3, - 0xdc, 0x93, 0x2e, 0xb7, 0x6d, 0x24, 0xfd, 0x3f, 0x4f, 0x01, 0xc3, 0x5e, 0x87, 0xb0, 0x01, 0x08, 0x00, 0x45, 0x89, - 0x26, 0x45, 0x69, 0x13, 0x1f, 0xb5, 0x4e, 0x29, 0x71, 0xca, 0x56, 0x5c, 0xbb, 0x51, 0x54, 0x22, 0x48, 0x0e, 0x49, - 0xac, 0x41, 0x80, 0x05, 0x80, 0x3a, 0x42, 0x63, 0x9f, 0x65, 0x9f, 0x65, 0x9f, 0xec, 0xab, 0xee, 0x9e, 0x19, 0x0c, - 0x0e, 0x1e, 0x8a, 0x9d, 0xdd, 0xaf, 0x12, 0xdb, 0xc4, 0xdc, 0xd3, 0x33, 0xd3, 0xd3, 0xd3, 0xa7, 0x3f, 0xe3, 0xbc, - 0x17, 0xb3, 0xc5, 0xf6, 0xeb, 0xee, 0xf3, 0x67, 0x66, 0xe3, 0x96, 0x04, 0x82, 0xcf, 0xce, 0xe2, 0xd9, 0x2c, 0x64, - 0x2d, 0x5d, 0x04, 0x0f, 0xd1, 0x4d, 0xd9, 0xcd, 0xd9, 0x23, 0x47, 0x78, 0xec, 0x34, 0xf2, 0x4d, 0x47, 0x4b, 0xcc, - 0x98, 0x49, 0x97, 0x76, 0x44, 0xb9, 0x22, 0x6f, 0xf6, 0x06, 0xc5, 0x1b, 0x7c, 0x5d, 0x8a, 0xa3, 0x6b, 0x4d, 0xe2, - 0xd5, 0x28, 0x64, 0x16, 0x6e, 0x77, 0xe8, 0x72, 0x3d, 0x5a, 0x8d, 0x46, 0x10, 0xa5, 0xe5, 0x91, 0x63, 0x82, 0xdf, - 0x99, 0x38, 0xc5, 0xf7, 0x60, 0x6e, 0xf4, 0x61, 0x52, 0x76, 0x56, 0x1d, 0x3e, 0xe8, 0x8a, 0x00, 0xab, 0x87, 0x3a, - 0xc8, 0xe0, 0xed, 0xd7, 0x70, 0x6a, 0x07, 0xfa, 0x07, 0xd8, 0x7d, 0xa9, 0xde, 0x6f, 0x3a, 0xfa, 0x83, 0x4b, 0xfd, - 0x03, 0xc2, 0x18, 0xa3, 0x17, 0xbf, 0xa4, 0xdd, 0xab, 0x9b, 0x3a, 0x09, 0xbd, 0x57, 0x18, 0xc7, 0x00, 0x98, 0xbe, - 0xaf, 0x02, 0x7f, 0x16, 0xc5, 0x69, 0x16, 0x8c, 0xf5, 0xab, 0xfe, 0xdb, 0xa0, 0x75, 0xb9, 0xc8, 0x5a, 0xc6, 0x95, - 0x39, 0xce, 0xd4, 0x10, 0x28, 0x02, 0x61, 0x62, 0x04, 0x94, 0x4d, 0x85, 0xd4, 0x13, 0xb4, 0xb5, 0xa0, 0x40, 0xcd, - 0x58, 0x68, 0x9c, 0x0d, 0xa0, 0x5c, 0x25, 0x9e, 0x0a, 0x06, 0x86, 0xd2, 0xb1, 0xa6, 0xd1, 0xa7, 0x97, 0xca, 0xcb, - 0xd5, 0x1a, 0xaf, 0xf2, 0xac, 0xb8, 0x2d, 0xd1, 0x07, 0xb0, 0x30, 0x9c, 0xa1, 0xef, 0x47, 0xaa, 0xd2, 0x67, 0xe9, - 0xde, 0x1d, 0x7e, 0x57, 0xa6, 0x0b, 0xe0, 0xfe, 0x06, 0x8d, 0x8b, 0x28, 0xce, 0x34, 0x70, 0x6c, 0x03, 0x3d, 0x0e, - 0xab, 0x4a, 0x62, 0xbc, 0xd5, 0x96, 0x91, 0x73, 0x64, 0xf0, 0x3d, 0x5e, 0x7e, 0x2d, 0xee, 0xde, 0xac, 0xe4, 0xc1, - 0x82, 0x1e, 0x0b, 0x11, 0x2c, 0x60, 0x16, 0x9f, 0xc7, 0xb7, 0x55, 0x39, 0xc8, 0xcb, 0xe1, 0xee, 0xbb, 0xb7, 0x25, - 0xc8, 0x64, 0x11, 0xd5, 0xaf, 0xc5, 0x03, 0x93, 0x0a, 0x42, 0xa7, 0x72, 0xa6, 0x50, 0xf1, 0x43, 0xd0, 0x30, 0x19, - 0xe8, 0x89, 0xe1, 0x5d, 0x00, 0x28, 0x89, 0x5f, 0xd3, 0xc3, 0xfc, 0x5a, 0x84, 0x4e, 0x16, 0x81, 0x8b, 0x95, 0xcb, - 0x19, 0xb0, 0x6b, 0xb4, 0x5c, 0x65, 0xe8, 0x6a, 0x17, 0x06, 0xc0, 0x72, 0x5d, 0x43, 0xd7, 0x9d, 0x80, 0xa5, 0x0b, - 0x32, 0x31, 0xd7, 0xb5, 0x60, 0x52, 0x4f, 0xe3, 0x44, 0x2f, 0x20, 0x2f, 0xc4, 0xef, 0xc8, 0xa8, 0x82, 0xcf, 0x84, - 0x4f, 0x63, 0x6c, 0x16, 0x7e, 0xea, 0x5b, 0x63, 0x14, 0xe8, 0x34, 0x60, 0x86, 0x31, 0xb5, 0xd3, 0x6f, 0x85, 0x8d, - 0x93, 0x05, 0xf7, 0x9b, 0xa5, 0x69, 0x0e, 0x9f, 0xac, 0xa3, 0xfc, 0xec, 0xc9, 0x3a, 0xcd, 0x07, 0x4f, 0xd6, 0xbe, - 0xd4, 0x15, 0xd0, 0x2f, 0x74, 0x52, 0x14, 0x18, 0x22, 0x18, 0x86, 0xf9, 0x75, 0x61, 0xb9, 0x53, 0xcc, 0x17, 0x76, - 0x19, 0xa5, 0x6b, 0x28, 0xba, 0x1f, 0x70, 0x01, 0xfd, 0x32, 0x09, 0x16, 0x7e, 0x72, 0x4f, 0xf2, 0x7c, 0x53, 0x15, - 0xfa, 0x1b, 0xba, 0x46, 0x88, 0x9e, 0x00, 0x40, 0x38, 0x5f, 0xd7, 0xfe, 0x2a, 0xd3, 0x18, 0x9f, 0xad, 0x14, 0x6a, - 0x42, 0x5f, 0xd7, 0xfa, 0x73, 0x66, 0x4f, 0x58, 0xe6, 0x07, 0x21, 0x55, 0xe9, 0x8b, 0x68, 0xf5, 0xb5, 0xe9, 0xa5, - 0xe5, 0xe9, 0x45, 0xe5, 0xfd, 0x83, 0x93, 0xa1, 0x2b, 0x80, 0xc6, 0x8d, 0x33, 0xc3, 0x28, 0x56, 0xcd, 0x2b, 0x4a, - 0x79, 0xff, 0xd5, 0xe5, 0x60, 0xb0, 0x1c, 0x11, 0x2c, 0x07, 0x8b, 0xc6, 0xf1, 0x84, 0xfd, 0xf2, 0xfe, 0xad, 0x0c, - 0x9b, 0x05, 0x1c, 0xa0, 0x21, 0xdf, 0x98, 0x29, 0xd2, 0x0f, 0x09, 0xd2, 0x0e, 0x14, 0xe0, 0x4a, 0x93, 0x5b, 0x28, - 0xc9, 0x75, 0xed, 0x8c, 0xc6, 0xce, 0x26, 0x34, 0xea, 0x41, 0x8c, 0xb5, 0x92, 0xfc, 0xe4, 0x80, 0x4a, 0xd3, 0x6d, - 0x47, 0x85, 0x00, 0x0c, 0x09, 0xcc, 0xb0, 0x80, 0x02, 0x44, 0xf8, 0x1c, 0xb8, 0xc5, 0x83, 0xc2, 0x5e, 0x20, 0x9f, - 0xdd, 0x3d, 0x2b, 0x93, 0x2a, 0x58, 0x4b, 0x3f, 0x3d, 0xc1, 0x98, 0x5d, 0x70, 0x5f, 0x83, 0x97, 0x8f, 0x93, 0x03, - 0xfa, 0xd4, 0x2a, 0x27, 0xa2, 0x68, 0x44, 0x3c, 0xed, 0x7a, 0xbc, 0x81, 0x07, 0x1d, 0x15, 0x08, 0x11, 0x0f, 0xa9, - 0x7e, 0xae, 0x6b, 0x0b, 0x4e, 0x1a, 0x71, 0x77, 0x42, 0xe0, 0x6b, 0xc0, 0x81, 0xb3, 0xab, 0x6b, 0x0b, 0xff, 0x0e, - 0x67, 0x2e, 0x72, 0xfc, 0xbb, 0x96, 0xcb, 0xb3, 0x8a, 0xb3, 0x96, 0x96, 0xcf, 0xda, 0x98, 0x2f, 0x2e, 0x18, 0x12, - 0xc8, 0x97, 0xf5, 0x1c, 0x05, 0xb4, 0x0d, 0x8b, 0x3b, 0x17, 0x8b, 0x3b, 0xd9, 0xb0, 0xb8, 0x93, 0x2d, 0x8b, 0x1b, - 0xf2, 0x85, 0xd4, 0x24, 0xe8, 0x12, 0x34, 0x0e, 0x93, 0xc0, 0xe3, 0x84, 0x46, 0x8f, 0x9f, 0x33, 0x84, 0x93, 0x95, - 0x86, 0xa0, 0x1c, 0xb5, 0x01, 0x56, 0x4d, 0x70, 0x51, 0x00, 0x51, 0x9f, 0xb8, 0x3c, 0x75, 0x62, 0xde, 0x10, 0x83, - 0xb3, 0x15, 0x56, 0xe7, 0x0b, 0xbb, 0x94, 0xe2, 0x8b, 0xb7, 0xe6, 0x1b, 0x66, 0x3a, 0xdf, 0x32, 0xd3, 0x71, 0xe9, - 0xe8, 0xf2, 0x69, 0xd3, 0x21, 0x54, 0x27, 0x05, 0x7b, 0x10, 0x14, 0x46, 0x71, 0xcb, 0x94, 0xf7, 0xe1, 0x66, 0x1c, - 0xab, 0xec, 0xa8, 0xa5, 0x9f, 0xa6, 0xb7, 0x71, 0x02, 0x12, 0x17, 0x68, 0xe6, 0x61, 0x5b, 0x6a, 0x11, 0x44, 0xdc, - 0x99, 0xcb, 0xc6, 0xcd, 0x54, 0xe4, 0xab, 0x5b, 0xca, 0xeb, 0x74, 0xa8, 0xc4, 0xd2, 0xcf, 0x32, 0x96, 0x20, 0xd0, - 0x7d, 0xf0, 0xfa, 0xfd, 0xff, 0x64, 0x9b, 0x35, 0xe0, 0x90, 0x50, 0xc1, 0xea, 0x88, 0xa1, 0x97, 0x40, 0x5b, 0x25, - 0xe2, 0x22, 0x56, 0x1c, 0xc3, 0x25, 0x12, 0xf0, 0x3f, 0xe1, 0x71, 0x6d, 0x25, 0x8a, 0xe9, 0x92, 0x7b, 0x64, 0xd8, - 0x4b, 0x7f, 0xf2, 0x01, 0x04, 0x7b, 0x2d, 0xcf, 0x04, 0x25, 0x5d, 0xd5, 0x0d, 0x5c, 0x42, 0xc4, 0xde, 0xb8, 0x40, - 0x92, 0x88, 0x25, 0xb9, 0x0a, 0x14, 0x58, 0x4f, 0xfa, 0xd6, 0xf4, 0x6a, 0xed, 0xe5, 0x07, 0xb3, 0xc0, 0xa8, 0x61, - 0x4d, 0x40, 0x6d, 0xe1, 0xe0, 0x54, 0xbe, 0xb9, 0x42, 0xd3, 0x3d, 0x32, 0x80, 0xf3, 0x7b, 0x09, 0xf1, 0x4c, 0x1d, - 0xf1, 0xa0, 0x1d, 0x26, 0x70, 0x6b, 0x5d, 0x3a, 0x57, 0xf9, 0xd3, 0x19, 0xfe, 0x72, 0xaf, 0xf2, 0xa7, 0x23, 0xfc, - 0xe5, 0x5d, 0x61, 0xe4, 0xba, 0x86, 0x87, 0xbc, 0x32, 0x67, 0xfd, 0xb4, 0xb4, 0x9f, 0x48, 0xff, 0xec, 0x01, 0xdb, - 0x86, 0x2f, 0xf0, 0xe3, 0x27, 0xeb, 0x14, 0x2c, 0x2e, 0xd5, 0x39, 0x44, 0x76, 0x62, 0xe4, 0x8d, 0xe9, 0xb3, 0x0d, - 0xe9, 0x23, 0xe3, 0xbf, 0x7c, 0xf1, 0xe3, 0x2e, 0x89, 0x8b, 0x3b, 0xa5, 0xcc, 0x86, 0xb8, 0x1e, 0x05, 0x91, 0x9f, - 0xdc, 0x5f, 0xd3, 0xf3, 0xa2, 0x25, 0x68, 0x77, 0xc9, 0x5e, 0x21, 0xf2, 0xb2, 0x2c, 0xee, 0xca, 0x14, 0x06, 0xef, - 0x3d, 0xbf, 0xe8, 0x07, 0x7f, 0x4f, 0x14, 0xb2, 0xad, 0xf4, 0x00, 0xe5, 0x0b, 0x52, 0xea, 0xe8, 0xfa, 0xc9, 0xba, - 0xc5, 0xea, 0xcd, 0x54, 0x66, 0x5b, 0xa1, 0x0b, 0x61, 0x79, 0xf0, 0x31, 0xbb, 0x98, 0x04, 0x3d, 0x94, 0x67, 0x8d, - 0xe2, 0x3b, 0xeb, 0xc9, 0x3a, 0x3b, 0xd3, 0x17, 0x7e, 0xf2, 0x89, 0x4d, 0xac, 0x71, 0x90, 0x8c, 0x43, 0xa6, 0xf7, - 0xf4, 0x51, 0xe8, 0x47, 0x9f, 0xf8, 0xa7, 0x15, 0xaf, 0x32, 0x94, 0x50, 0xef, 0x7c, 0xfb, 0x0a, 0x98, 0x10, 0xcb, - 0x0e, 0x89, 0xd5, 0x06, 0x28, 0x68, 0x2f, 0x25, 0xc3, 0xab, 0x20, 0x14, 0x8b, 0x52, 0x26, 0x28, 0x58, 0x82, 0xd0, - 0x1c, 0x2c, 0x56, 0x4d, 0x1d, 0xd7, 0x4b, 0x37, 0xd5, 0xa9, 0x12, 0xb3, 0x52, 0x86, 0x5c, 0xbc, 0xc6, 0x16, 0xfe, - 0x78, 0x77, 0x14, 0x0c, 0x7b, 0xff, 0xee, 0x64, 0x2b, 0x5f, 0x36, 0x43, 0x48, 0xb5, 0xc8, 0x52, 0xe2, 0x01, 0x9d, - 0x73, 0x02, 0x73, 0x73, 0xd7, 0x6a, 0x65, 0x3f, 0x4d, 0x57, 0x0b, 0x36, 0x21, 0xc9, 0xe0, 0x59, 0x31, 0xa8, 0xf2, - 0xcb, 0x42, 0x1d, 0xd8, 0x6f, 0x2b, 0xef, 0xf8, 0xf0, 0x25, 0x68, 0x2c, 0x00, 0x41, 0x19, 0x4f, 0xa7, 0x7a, 0xf1, - 0xc6, 0xdf, 0x51, 0xcd, 0x3d, 0xfc, 0x6d, 0xf5, 0xe6, 0xb5, 0xf3, 0x46, 0x56, 0x8e, 0x80, 0x30, 0x16, 0xe2, 0x57, - 0x4e, 0x17, 0x2b, 0xe3, 0x15, 0x33, 0x9a, 0xfa, 0xd1, 0xe6, 0xe9, 0x5c, 0x96, 0xb6, 0xf8, 0x92, 0xb1, 0x09, 0x10, - 0xdc, 0x66, 0x2d, 0xf5, 0x3a, 0x64, 0x37, 0x4c, 0x8a, 0x76, 0xeb, 0x9d, 0x35, 0xd4, 0x40, 0xdf, 0x73, 0x5c, 0x64, - 0xcc, 0xa9, 0x3a, 0x65, 0x4a, 0x43, 0x9c, 0x03, 0x9f, 0xb9, 0x7a, 0xc4, 0x2a, 0x47, 0x6a, 0x68, 0xea, 0xca, 0x00, - 0x36, 0x8e, 0xec, 0x6c, 0x43, 0x7a, 0x0f, 0x03, 0x4f, 0x37, 0x8f, 0xcd, 0x74, 0x8d, 0x1e, 0xf8, 0xea, 0xe6, 0x70, - 0x0a, 0xe1, 0xe4, 0xb5, 0x0a, 0x76, 0xc8, 0x26, 0x88, 0x35, 0x31, 0xc9, 0x74, 0xe2, 0xbe, 0x08, 0x6d, 0x47, 0x54, - 0xfb, 0x15, 0x7c, 0xa8, 0xc6, 0xb5, 0xd1, 0xca, 0x33, 0x1f, 0x61, 0x40, 0xd7, 0x88, 0xa5, 0xe9, 0x46, 0x80, 0xc9, - 0x45, 0x37, 0xf5, 0xa2, 0x74, 0x19, 0x1e, 0x45, 0xba, 0xe9, 0x98, 0x40, 0x12, 0xe0, 0x04, 0xab, 0x7d, 0xe1, 0xf5, - 0x72, 0xbd, 0xe0, 0xfa, 0x2a, 0xc9, 0x6c, 0xa4, 0x73, 0x5d, 0x82, 0x4d, 0xf9, 0xb7, 0x3a, 0x1f, 0x54, 0xe9, 0x9a, - 0x6e, 0x1c, 0x5a, 0xab, 0x84, 0x7a, 0x6b, 0xec, 0x22, 0x6c, 0x40, 0x8c, 0xa9, 0x82, 0x5f, 0xd9, 0x74, 0xca, 0xc6, - 0x59, 0x6a, 0x08, 0xe6, 0x91, 0xf4, 0x1e, 0x0b, 0x56, 0x43, 0x8f, 0x06, 0xfa, 0x4f, 0x60, 0x43, 0x2f, 0x9c, 0x2c, - 0xf1, 0x01, 0x89, 0x37, 0x53, 0x33, 0x98, 0xa8, 0xc5, 0x32, 0x88, 0x78, 0x2f, 0x10, 0x1c, 0xbc, 0x21, 0x1d, 0x87, - 0xc6, 0xef, 0x9f, 0x62, 0x5f, 0xc4, 0x52, 0xab, 0x65, 0x3b, 0x2a, 0xda, 0x76, 0x7c, 0xd7, 0xee, 0x9b, 0x8e, 0xeb, - 0xe4, 0xba, 0x09, 0xb6, 0x5b, 0x9f, 0xf6, 0x3d, 0xf4, 0x58, 0xab, 0x0d, 0xb5, 0x56, 0xd1, 0x43, 0xea, 0x79, 0xee, - 0x0b, 0x57, 0x37, 0x49, 0x65, 0x4e, 0xc1, 0x6d, 0xe3, 0xf8, 0x86, 0x25, 0x5f, 0x3c, 0x95, 0x72, 0xe3, 0xfb, 0x8d, - 0xe7, 0xc8, 0x75, 0x00, 0x09, 0x67, 0xf1, 0xf2, 0x01, 0x53, 0x68, 0xeb, 0xa6, 0x3e, 0x0e, 0xe3, 0x94, 0xa9, 0x73, - 0x20, 0x26, 0xc8, 0x17, 0x4e, 0xe2, 0xe7, 0xf7, 0xaf, 0x3f, 0x7c, 0xd0, 0x4d, 0x8c, 0x04, 0x9a, 0xaa, 0xad, 0xf3, - 0x0d, 0xb5, 0x03, 0xfb, 0x37, 0xee, 0x3b, 0xba, 0x61, 0xe8, 0x51, 0x5b, 0xde, 0x73, 0x94, 0x56, 0xdb, 0x72, 0xfc, - 0xe6, 0xe1, 0x3d, 0xd3, 0x4b, 0x74, 0xaf, 0x79, 0x35, 0xe0, 0x86, 0xed, 0xd7, 0x5b, 0x29, 0x65, 0x11, 0x44, 0xd7, - 0x0d, 0xa9, 0xfe, 0x5d, 0x43, 0x2a, 0x3c, 0xe5, 0x6a, 0xb8, 0x6a, 0x15, 0x2f, 0x14, 0xd2, 0x00, 0x02, 0x39, 0xef, - 0x02, 0x97, 0xf2, 0x9e, 0xfa, 0x82, 0x41, 0x73, 0x4f, 0xee, 0xd5, 0x51, 0x37, 0x24, 0xf3, 0x47, 0x90, 0x84, 0xed, - 0x38, 0x04, 0x85, 0x3f, 0xa6, 0x4a, 0xe5, 0xca, 0x64, 0xa3, 0x54, 0xd7, 0x55, 0x1a, 0x21, 0xf2, 0xf6, 0x3a, 0x63, - 0x8b, 0x25, 0x4b, 0xfc, 0x6c, 0x95, 0xb0, 0xeb, 0x30, 0xbe, 0x7d, 0x54, 0xa8, 0xd3, 0xef, 0x28, 0x3c, 0x0f, 0x66, - 0x73, 0x59, 0xfa, 0xac, 0xc5, 0x06, 0x72, 0x01, 0xb7, 0x76, 0x90, 0xff, 0xe7, 0xdf, 0xb6, 0xfd, 0x9f, 0x7f, 0xef, - 0x2c, 0x0a, 0xcd, 0xe7, 0x43, 0x33, 0x1b, 0xec, 0xb1, 0x2f, 0x9a, 0x7b, 0x2a, 0xc3, 0xbc, 0xb9, 0x4c, 0x6d, 0x11, - 0x20, 0xbf, 0xb6, 0x04, 0xb5, 0xc4, 0xf2, 0xbe, 0x79, 0xd0, 0xc0, 0x60, 0x5e, 0x3b, 0x47, 0x06, 0x85, 0xbe, 0x68, - 0x68, 0x43, 0xa3, 0xb7, 0xd7, 0x8a, 0xfc, 0x71, 0x08, 0xef, 0x9a, 0xc3, 0x17, 0x0e, 0x9f, 0xf3, 0x25, 0x5f, 0x0e, - 0x87, 0x32, 0xb6, 0x9c, 0x5a, 0x15, 0x54, 0xfc, 0xcf, 0x6a, 0x29, 0xfc, 0xf2, 0xec, 0x39, 0x06, 0xd9, 0xde, 0x0f, - 0x5e, 0x0e, 0x51, 0x19, 0xed, 0x64, 0x94, 0x14, 0xc4, 0xca, 0x46, 0xd4, 0x46, 0xca, 0xe4, 0xb5, 0x46, 0x6b, 0x78, - 0x0d, 0x52, 0x31, 0xe0, 0x58, 0x3e, 0x34, 0xcc, 0x97, 0x43, 0xce, 0x58, 0xe2, 0xfa, 0xaf, 0xbd, 0xea, 0xd6, 0xe6, - 0x6c, 0xd9, 0x12, 0xd0, 0x4d, 0x8d, 0xe4, 0x3f, 0x58, 0x98, 0x15, 0x7c, 0x3c, 0x64, 0xf0, 0x03, 0x47, 0x61, 0x98, - 0x63, 0xbc, 0x93, 0x77, 0x9b, 0x74, 0xc4, 0x7e, 0xde, 0xad, 0x23, 0x76, 0xb1, 0x97, 0x8e, 0xd8, 0xcf, 0x5f, 0x5d, - 0x47, 0xec, 0x9d, 0xaa, 0x23, 0x06, 0x8b, 0xf8, 0x9a, 0xed, 0xa5, 0xb8, 0x25, 0xb4, 0x36, 0xe2, 0xdb, 0x74, 0xe0, - 0x72, 0x92, 0x36, 0x1d, 0xcf, 0x19, 0xf0, 0x08, 0xf8, 0xaa, 0x84, 0xf1, 0x0c, 0x94, 0xb8, 0xfe, 0x7c, 0x75, 0xab, - 0x30, 0x9e, 0xa9, 0xca, 0x56, 0x11, 0xf7, 0xf8, 0x5a, 0x78, 0x71, 0x22, 0x05, 0x27, 0xc7, 0x14, 0x3e, 0x9f, 0xac, - 0x43, 0x43, 0x89, 0x6a, 0x2d, 0xb5, 0xd7, 0x3c, 0xa1, 0x02, 0xd5, 0x43, 0xed, 0x29, 0x59, 0xd1, 0x7b, 0x2e, 0x7c, - 0x5b, 0xa8, 0x2d, 0x48, 0x2d, 0x61, 0xf2, 0x13, 0xb1, 0xd6, 0x7f, 0xbb, 0x73, 0xbf, 0xbf, 0x74, 0xfb, 0x6d, 0x17, - 0x8c, 0xb3, 0xe1, 0x85, 0x89, 0x09, 0x4e, 0xbf, 0xdd, 0x86, 0x84, 0x5b, 0x25, 0xc1, 0x83, 0x84, 0x40, 0x49, 0xe8, - 0x40, 0xc2, 0x58, 0x49, 0x38, 0x82, 0x84, 0x89, 0x92, 0x70, 0x0c, 0x09, 0x37, 0x7a, 0x7e, 0x19, 0xc9, 0xe1, 0x1e, - 0x1b, 0x57, 0x26, 0x3d, 0x2a, 0x44, 0xda, 0xb1, 0xe9, 0x82, 0xd6, 0x94, 0x3f, 0xeb, 0xc5, 0x26, 0x71, 0x17, 0x7b, - 0x89, 0x79, 0x3b, 0x67, 0xe4, 0x28, 0xfa, 0x15, 0xde, 0x39, 0x76, 0x16, 0x83, 0xde, 0xb4, 0x70, 0xc0, 0x20, 0xe0, - 0xa0, 0xe9, 0x06, 0x30, 0x8c, 0xfa, 0x72, 0xe5, 0x84, 0x13, 0x0b, 0x65, 0x2d, 0x8b, 0x3c, 0xea, 0xce, 0x92, 0x5b, - 0xa0, 0xd0, 0x38, 0x69, 0xa9, 0x5c, 0xc9, 0xaf, 0xa1, 0x77, 0xf0, 0x8a, 0x8d, 0x56, 0x33, 0xed, 0x3c, 0x9e, 0xed, - 0x54, 0x21, 0x50, 0xb3, 0x60, 0x94, 0x3a, 0x89, 0x5f, 0x2c, 0xb1, 0x2d, 0x79, 0x5f, 0xf4, 0x99, 0x97, 0xcb, 0x67, - 0x30, 0x36, 0x2d, 0x23, 0x05, 0x16, 0xe8, 0x07, 0x60, 0xa4, 0xc8, 0xf0, 0xcf, 0x01, 0xce, 0xca, 0xf7, 0x85, 0xaf, - 0x8c, 0xe7, 0xf4, 0x47, 0x96, 0xa6, 0xfe, 0x4c, 0x94, 0xaf, 0x8f, 0x13, 0x94, 0x76, 0xe4, 0xfb, 0x0b, 0x01, 0x08, - 0x9c, 0xbc, 0xa0, 0xa6, 0x9b, 0x91, 0xc4, 0xb7, 0x1a, 0x68, 0xff, 0xc0, 0x86, 0x2a, 0xf4, 0x14, 0x02, 0x1b, 0x96, - 0xb0, 0xac, 0x51, 0x00, 0x87, 0xff, 0x86, 0x85, 0xd5, 0xc4, 0xcc, 0x9f, 0x55, 0x93, 0x68, 0x1f, 0xe4, 0xea, 0xd8, - 0xa4, 0x40, 0xbf, 0x94, 0xf8, 0x25, 0x12, 0xea, 0x30, 0x9e, 0xfd, 0xa9, 0xe2, 0xe9, 0x2d, 0x6a, 0x05, 0x1f, 0x22, - 0x33, 0xc8, 0x86, 0x36, 0xc2, 0x58, 0xb3, 0x01, 0x84, 0xbd, 0x28, 0x9b, 0x5b, 0x68, 0x5a, 0xd6, 0xf2, 0x22, 0xc3, - 0xb4, 0x71, 0x6d, 0xd7, 0x55, 0x83, 0xda, 0x5e, 0x32, 0x1b, 0xf9, 0x2d, 0xd7, 0x3b, 0x36, 0xc5, 0x1f, 0xdb, 0xe9, - 0x18, 0x39, 0xb6, 0xa0, 0x4d, 0x82, 0x9b, 0xf5, 0x34, 0x8e, 0x32, 0x6b, 0xea, 0x2f, 0x82, 0xf0, 0xbe, 0xb7, 0x88, - 0xa3, 0x38, 0x5d, 0xfa, 0x63, 0xd6, 0x2f, 0x1e, 0xd4, 0x7d, 0x74, 0xd5, 0xc0, 0xad, 0x05, 0x5d, 0xdb, 0x4b, 0xd8, - 0x82, 0x6a, 0x4b, 0x4f, 0x0c, 0xd3, 0x90, 0xdd, 0xe5, 0xbc, 0xfb, 0x52, 0x61, 0x2a, 0x8a, 0x5b, 0x8e, 0x6a, 0x00, - 0x45, 0xca, 0xdd, 0x3c, 0x80, 0x73, 0xa3, 0xfe, 0xd2, 0x9f, 0xa0, 0x67, 0x42, 0xdb, 0xeb, 0x24, 0x6c, 0xa1, 0xd9, - 0x9d, 0x8d, 0x8d, 0x27, 0xf1, 0xed, 0x29, 0x8c, 0x16, 0x2b, 0x5b, 0x29, 0x0b, 0xa7, 0x98, 0x63, 0xa1, 0x65, 0x89, - 0x68, 0xc7, 0xc2, 0x87, 0x38, 0xb4, 0xc6, 0x16, 0x7d, 0xc8, 0xee, 0x79, 0x9a, 0xd3, 0x5f, 0x04, 0x91, 0x45, 0xd3, - 0x39, 0x76, 0x96, 0x4a, 0x5b, 0x2a, 0xfc, 0x8c, 0x35, 0x16, 0x77, 0x35, 0xa7, 0x0f, 0x8f, 0xb5, 0x69, 0x18, 0xdf, - 0xf6, 0xe6, 0xc1, 0x64, 0xc2, 0xa2, 0x3e, 0x8e, 0x59, 0x26, 0xb2, 0x30, 0x0c, 0x96, 0x69, 0x90, 0xf6, 0x17, 0xfe, - 0x1d, 0x6f, 0xf5, 0x70, 0x53, 0xab, 0x6d, 0xde, 0x6a, 0x7b, 0xef, 0x56, 0x95, 0x66, 0xc0, 0x8a, 0x85, 0xda, 0xe1, - 0x43, 0xeb, 0x68, 0x4e, 0x65, 0x9e, 0x7b, 0xb7, 0xba, 0x4c, 0xd8, 0x7a, 0xe1, 0x27, 0xb3, 0x20, 0xea, 0x39, 0xb9, - 0x7d, 0xb3, 0xa6, 0x8d, 0xf1, 0xb8, 0xdb, 0xed, 0xe6, 0xf6, 0x44, 0x7c, 0x39, 0x93, 0x49, 0x6e, 0x8f, 0xc5, 0xd7, - 0x74, 0xea, 0x38, 0xd3, 0x69, 0x6e, 0x07, 0x22, 0xa1, 0xed, 0x8d, 0x27, 0x6d, 0x2f, 0xb7, 0x6f, 0x95, 0x12, 0xb9, - 0xcd, 0xf8, 0x57, 0xc2, 0x26, 0x7d, 0xdc, 0x48, 0xa4, 0x56, 0xda, 0x3b, 0x76, 0x9c, 0x1c, 0x31, 0xc0, 0x65, 0x09, - 0x37, 0x21, 0xaf, 0xe7, 0x6a, 0xbd, 0x77, 0x49, 0xad, 0xe8, 0x6e, 0x3c, 0x6e, 0x2c, 0x37, 0xf1, 0x93, 0x4f, 0x57, - 0x9a, 0x32, 0x0b, 0xdf, 0xa7, 0x62, 0x6b, 0x01, 0x06, 0xeb, 0xae, 0x07, 0x2e, 0xbb, 0xfa, 0xa3, 0x38, 0x81, 0x33, - 0x9b, 0xf8, 0x93, 0x60, 0x95, 0xf6, 0x5c, 0x6f, 0x79, 0x27, 0x92, 0xf8, 0x5e, 0x2f, 0x12, 0xf0, 0xec, 0xf5, 0xd2, - 0x38, 0x0c, 0x26, 0x22, 0x69, 0xd3, 0x59, 0x72, 0x3d, 0xa3, 0x8f, 0x06, 0xeb, 0x01, 0xba, 0x5d, 0xf0, 0xc3, 0x50, - 0xb3, 0xdb, 0xa9, 0xc6, 0xfc, 0x14, 0xf9, 0xcb, 0x9a, 0x93, 0x12, 0x5c, 0xd0, 0x38, 0xdd, 0x3d, 0x5c, 0xde, 0xc9, - 0x3d, 0xef, 0x1e, 0x2d, 0xef, 0xf2, 0xbf, 0x2e, 0xd8, 0x24, 0xf0, 0xb5, 0x56, 0xb1, 0x9b, 0x5c, 0x07, 0x78, 0xd0, - 0xc6, 0x7a, 0xc3, 0x36, 0x15, 0xc7, 0x02, 0x5c, 0x1b, 0x3e, 0x0a, 0x16, 0xcb, 0x38, 0xc9, 0xfc, 0x28, 0xcb, 0xf3, - 0xe1, 0x55, 0x9e, 0xf7, 0x2f, 0x82, 0xd6, 0xe5, 0x3f, 0x5a, 0x74, 0x4f, 0x93, 0xcc, 0x26, 0x37, 0xae, 0xcc, 0xd7, - 0x4c, 0xd5, 0x19, 0x81, 0x6b, 0x0c, 0xf5, 0x45, 0xd4, 0xc2, 0x74, 0x4b, 0xd6, 0x0b, 0x13, 0x90, 0x65, 0x71, 0xd2, - 0x41, 0x29, 0x17, 0xc1, 0x1b, 0x08, 0x0a, 0xbc, 0x66, 0x83, 0x0b, 0x45, 0xff, 0x04, 0x88, 0x15, 0x2c, 0x4c, 0x76, - 0x05, 0x4f, 0x36, 0xd1, 0x8c, 0xdf, 0xed, 0xa6, 0x19, 0x7f, 0xcd, 0xf6, 0xa1, 0x19, 0xbf, 0xfb, 0xea, 0x34, 0xe3, - 0x93, 0xba, 0x5d, 0xc1, 0xdb, 0x78, 0xa0, 0x4b, 0x09, 0x03, 0x5c, 0x4d, 0x09, 0x79, 0xec, 0x79, 0xfb, 0x87, 0xcd, - 0x00, 0x44, 0x6b, 0x14, 0x83, 0x8e, 0x6e, 0x6e, 0xe0, 0xc7, 0xbe, 0x8b, 0x06, 0x7f, 0x4f, 0xd4, 0xef, 0xe9, 0x74, - 0xf0, 0x2a, 0x56, 0x12, 0xe4, 0x17, 0x57, 0xbe, 0x28, 0x79, 0x57, 0xa0, 0x1c, 0xa1, 0x85, 0x89, 0xf1, 0x27, 0xc0, - 0x38, 0x9b, 0xb4, 0x8e, 0x27, 0x52, 0xfb, 0xac, 0x5f, 0x1e, 0x42, 0x4b, 0xaa, 0x7c, 0x0a, 0x13, 0x9c, 0x1a, 0x2b, - 0x71, 0xc6, 0x32, 0x6e, 0x33, 0xfb, 0xfd, 0xfd, 0xdb, 0x49, 0xeb, 0x6d, 0x6c, 0xe4, 0x41, 0xfa, 0xae, 0x6a, 0x00, - 0xc3, 0x65, 0x3f, 0x03, 0x75, 0x3a, 0x39, 0xd7, 0x20, 0x53, 0x03, 0x4c, 0x43, 0x36, 0x55, 0x3f, 0x2b, 0xcd, 0xb4, - 0xa7, 0x56, 0xe4, 0x81, 0xae, 0x6a, 0x97, 0x31, 0xb7, 0x3e, 0x58, 0x73, 0x0a, 0x10, 0x63, 0x77, 0xa1, 0xdd, 0xf0, - 0x84, 0xaa, 0x07, 0x93, 0x3c, 0x37, 0xfa, 0x02, 0x10, 0xca, 0x45, 0xcb, 0x76, 0x11, 0x71, 0xe9, 0xad, 0xd4, 0x69, - 0xe0, 0x12, 0x42, 0x12, 0xff, 0xbd, 0x05, 0x81, 0x3a, 0x17, 0x16, 0x72, 0x98, 0xe9, 0x1a, 0x81, 0x8f, 0x14, 0x2d, - 0x94, 0x09, 0x81, 0x04, 0x58, 0xc2, 0x5f, 0x64, 0x89, 0x84, 0xba, 0x0e, 0x27, 0x01, 0x07, 0x35, 0x02, 0xc0, 0xca, - 0x5f, 0xf0, 0xb5, 0x09, 0xed, 0xf0, 0x32, 0xf8, 0x91, 0xeb, 0x92, 0xf6, 0xc3, 0xed, 0x77, 0x7a, 0x72, 0x00, 0x15, - 0x4e, 0x2b, 0x8a, 0x03, 0x3b, 0x34, 0x14, 0x81, 0x94, 0x48, 0x6f, 0x4d, 0x3b, 0xbd, 0xd5, 0x9e, 0xad, 0x85, 0x87, - 0x8c, 0xcc, 0x5f, 0x5a, 0xf0, 0xc4, 0x47, 0xdc, 0xcb, 0x31, 0x9e, 0xe2, 0x8c, 0xa3, 0xbf, 0x4a, 0x01, 0x37, 0xe2, - 0x43, 0x15, 0xf1, 0x4f, 0x7f, 0xbc, 0x4a, 0xd2, 0x38, 0xe9, 0x2d, 0xe3, 0x20, 0xca, 0x58, 0x92, 0x23, 0xa8, 0x2e, - 0x11, 0x3e, 0x02, 0x3c, 0x57, 0xeb, 0x78, 0xe9, 0x8f, 0x83, 0xec, 0xbe, 0xe7, 0x70, 0x92, 0xc2, 0xe9, 0x73, 0xea, - 0xc0, 0x69, 0x2c, 0xdf, 0xe3, 0xd0, 0x7c, 0x8e, 0x84, 0x5f, 0x52, 0x27, 0x67, 0xd4, 0x6d, 0xde, 0x57, 0x72, 0xc9, - 0x47, 0x08, 0x90, 0x1f, 0x7e, 0x62, 0xcd, 0x00, 0xcb, 0xc3, 0x52, 0x3b, 0x13, 0x36, 0x33, 0x11, 0x6b, 0x03, 0x5f, - 0x5e, 0xfc, 0xb1, 0x3b, 0x86, 0xe6, 0x34, 0x27, 0x03, 0xc5, 0x63, 0xec, 0x33, 0xb2, 0x9e, 0x0f, 0x11, 0xb5, 0xcc, - 0x7d, 0x4a, 0x8e, 0xd8, 0x34, 0x4e, 0x18, 0xf9, 0x93, 0x75, 0xbb, 0xcb, 0xbb, 0xfd, 0x9b, 0xdf, 0x3e, 0xfd, 0xe6, - 0x76, 0xa2, 0x38, 0x6b, 0x89, 0xc6, 0x8c, 0x1d, 0xad, 0xd5, 0xef, 0x33, 0x20, 0x0d, 0x09, 0xf2, 0x63, 0x72, 0xdd, - 0xd5, 0xd3, 0xf5, 0x7e, 0xa3, 0xdb, 0xae, 0x65, 0xcc, 0xef, 0xbc, 0x84, 0x85, 0x7e, 0x16, 0xdc, 0x08, 0x9a, 0xb1, - 0x7d, 0xb4, 0xbc, 0x13, 0x6b, 0x8c, 0x17, 0xde, 0x03, 0x16, 0xa9, 0x32, 0x14, 0xb1, 0x48, 0xd5, 0x64, 0x5c, 0xa4, - 0x7e, 0x6d, 0x36, 0xc2, 0x93, 0x45, 0xe5, 0xa6, 0xef, 0x2c, 0xef, 0xd4, 0x2b, 0xba, 0xa8, 0x26, 0x6f, 0xea, 0xaa, - 0x0b, 0xb2, 0x45, 0x30, 0x99, 0x84, 0x2c, 0x2f, 0x2d, 0x74, 0x79, 0x2d, 0x15, 0xe0, 0x48, 0x38, 0xf8, 0xa3, 0x34, - 0x0e, 0x57, 0x19, 0x6b, 0x06, 0x17, 0x01, 0xc7, 0x73, 0x0a, 0xe0, 0xe0, 0xef, 0xf2, 0x58, 0x3b, 0x40, 0x6e, 0xc3, - 0x36, 0x71, 0xfa, 0xe0, 0x71, 0xd8, 0x6a, 0x97, 0x87, 0x0e, 0x59, 0x72, 0xd0, 0x66, 0xc3, 0x44, 0x4c, 0xb8, 0x96, - 0x08, 0x7b, 0x6b, 0xb6, 0xcb, 0xd3, 0xa4, 0xd7, 0x55, 0x99, 0x94, 0x97, 0x27, 0xf3, 0xe7, 0x9c, 0xb1, 0x17, 0xcd, - 0x67, 0xec, 0x85, 0x38, 0x63, 0xdb, 0x77, 0xe6, 0xe3, 0xa9, 0x0b, 0xff, 0xf5, 0x8b, 0x09, 0xf5, 0x1c, 0xad, 0xbd, - 0xbc, 0xd3, 0xdc, 0xe5, 0x9d, 0x66, 0x79, 0xcb, 0x3b, 0x0d, 0x9b, 0x46, 0x7d, 0x10, 0xd3, 0xf6, 0x0c, 0xd3, 0xd1, - 0x20, 0x11, 0xfe, 0x38, 0xa5, 0x2c, 0xf7, 0x10, 0xf2, 0xa0, 0x56, 0xa7, 0x9e, 0xe7, 0x6d, 0x3f, 0xea, 0x74, 0x96, - 0x04, 0xd2, 0x36, 0xec, 0xcc, 0x1f, 0x8d, 0xd8, 0xa4, 0x37, 0x8d, 0xc7, 0xab, 0xf4, 0x5f, 0x7c, 0xfc, 0x1c, 0x88, - 0x5b, 0x11, 0x41, 0xa5, 0x1d, 0x51, 0x15, 0x04, 0x25, 0x37, 0x4c, 0xb4, 0xb0, 0x96, 0xeb, 0xd4, 0x23, 0xf7, 0xc8, - 0x9e, 0x7d, 0xd8, 0xb0, 0xc9, 0x9b, 0x01, 0xfd, 0xa7, 0xad, 0xd2, 0x66, 0x14, 0xf3, 0x05, 0x60, 0xd9, 0x0a, 0x8e, - 0x87, 0x43, 0x83, 0xaf, 0xa6, 0xd3, 0x6d, 0x1e, 0xee, 0xa5, 0xe8, 0xe9, 0x4a, 0x5c, 0x2a, 0xfc, 0xde, 0xe2, 0x86, - 0x29, 0xdb, 0x5b, 0xdd, 0xb4, 0x47, 0x6a, 0xad, 0x6e, 0xb9, 0x10, 0x8a, 0xb2, 0x7b, 0x62, 0xf9, 0xc7, 0x2f, 0x0e, - 0xe1, 0x3f, 0xa2, 0xea, 0x7f, 0xcd, 0x9a, 0x08, 0xf5, 0xb7, 0x65, 0x4d, 0x70, 0x22, 0x95, 0x90, 0x10, 0xdf, 0xbf, - 0xfc, 0x74, 0xfa, 0xb0, 0x0a, 0x7b, 0x97, 0x26, 0x55, 0xaa, 0x6a, 0xe9, 0xef, 0xe3, 0x18, 0x42, 0x77, 0xd6, 0x8b, - 0x0b, 0xf0, 0x90, 0xb2, 0x7b, 0x36, 0x80, 0x4a, 0xe2, 0x1d, 0x41, 0x52, 0x7c, 0x1d, 0xeb, 0xd0, 0x53, 0xe2, 0xf5, - 0xa6, 0xa7, 0xc4, 0xab, 0xdd, 0x4f, 0x89, 0x1f, 0xf6, 0x7a, 0x4a, 0xbc, 0xfa, 0xea, 0x4f, 0x89, 0xd7, 0xf5, 0xa7, - 0xc4, 0x45, 0x2c, 0xf4, 0x67, 0xcd, 0xb7, 0x2b, 0xfe, 0xf3, 0x23, 0x09, 0xe5, 0xce, 0xe3, 0x41, 0xc7, 0x21, 0x97, - 0xc7, 0x17, 0x7f, 0xf8, 0x61, 0x81, 0x1b, 0xf1, 0x3d, 0xaa, 0x93, 0x15, 0x4f, 0x0b, 0x8e, 0xd9, 0xb1, 0x1f, 0x25, - 0x39, 0x8c, 0xa3, 0xd9, 0xcf, 0x20, 0x94, 0x05, 0x76, 0x60, 0xa2, 0x64, 0x04, 0xe9, 0xcf, 0xf1, 0x72, 0xb5, 0x7c, - 0x0b, 0x6d, 0x7d, 0x0c, 0xd2, 0x60, 0x14, 0x32, 0x69, 0x89, 0x4c, 0xea, 0x6f, 0x9c, 0x27, 0x0e, 0x1a, 0xa7, 0xe2, - 0xa7, 0x7f, 0x27, 0x7e, 0xa2, 0x4e, 0x2a, 0xff, 0x4d, 0x7a, 0x75, 0x7a, 0xf3, 0x43, 0x44, 0x08, 0x01, 0x95, 0x41, - 0x3f, 0xfc, 0x31, 0x72, 0x11, 0x1b, 0x0d, 0xb3, 0x14, 0xfa, 0x0e, 0x1b, 0xdb, 0x61, 0xb5, 0x47, 0xcd, 0xca, 0x30, - 0xa5, 0x0b, 0xae, 0x3a, 0x1b, 0x7e, 0x11, 0xaf, 0x52, 0x36, 0x89, 0x6f, 0x23, 0xdd, 0x8c, 0xa4, 0x91, 0x01, 0x48, - 0x38, 0x65, 0x1d, 0x0c, 0x1e, 0xf9, 0x01, 0x09, 0xe5, 0x38, 0x69, 0xe9, 0x10, 0xbb, 0x74, 0xb5, 0xb4, 0x48, 0xd4, - 0x6c, 0xe1, 0x14, 0x75, 0x19, 0xe5, 0xe8, 0x51, 0xab, 0x15, 0x0f, 0x1e, 0x56, 0x53, 0xa8, 0x6a, 0xc4, 0x36, 0xe7, - 0x0a, 0xa7, 0xad, 0x48, 0x30, 0x17, 0x85, 0x1f, 0x8c, 0x86, 0x85, 0xe3, 0x39, 0x64, 0xba, 0x5a, 0xe4, 0x82, 0x17, - 0x91, 0x7c, 0xc5, 0xd7, 0x83, 0x7b, 0x85, 0xa0, 0xcf, 0x97, 0x0a, 0x18, 0xdf, 0xdd, 0xb0, 0x24, 0xf4, 0xef, 0x5b, - 0x46, 0x1e, 0x47, 0x3f, 0x02, 0x00, 0x5e, 0xc5, 0xb7, 0x91, 0x5a, 0x00, 0x83, 0xb5, 0x34, 0xec, 0xa5, 0x46, 0xff, - 0x25, 0x60, 0xb8, 0xa2, 0x8c, 0x00, 0xc2, 0xe4, 0xce, 0xd8, 0xdf, 0x4d, 0xfa, 0xf7, 0x1f, 0x46, 0x6e, 0x9e, 0xc7, - 0xb2, 0xa3, 0x5f, 0x96, 0x7b, 0x74, 0xf3, 0xf4, 0xe9, 0xa3, 0xcd, 0xd3, 0x2e, 0x87, 0x67, 0x6f, 0xa8, 0x6d, 0x6c, - 0x3c, 0x05, 0x30, 0x8a, 0x8b, 0x78, 0x35, 0x9e, 0xa3, 0xa2, 0xeb, 0xd7, 0x9b, 0x6f, 0x06, 0x6d, 0x62, 0x94, 0x52, - 0x39, 0xf5, 0x4a, 0x52, 0x01, 0x05, 0xec, 0xff, 0x35, 0x38, 0xe0, 0xfc, 0x1f, 0x82, 0xa1, 0xbe, 0x6b, 0xf8, 0x2b, - 0x3e, 0x78, 0xd8, 0xe6, 0xed, 0x43, 0x30, 0x4d, 0xee, 0xda, 0x42, 0x08, 0xd7, 0x9a, 0x91, 0x4c, 0x5e, 0x05, 0x9a, - 0xea, 0x46, 0x6e, 0x93, 0x87, 0x3c, 0xd1, 0x0b, 0xb3, 0xe9, 0x99, 0xce, 0x0d, 0x0d, 0x4c, 0xc6, 0xb1, 0x55, 0x05, - 0xc9, 0x70, 0x95, 0x07, 0x86, 0xe8, 0xab, 0x9a, 0xb7, 0x08, 0x22, 0x13, 0xbd, 0xc0, 0xd7, 0x73, 0xfc, 0x3b, 0xf0, - 0x83, 0x0c, 0xc8, 0xad, 0x9a, 0x05, 0x89, 0xa6, 0x6a, 0x37, 0x07, 0xa1, 0x9e, 0xf4, 0x46, 0x48, 0x08, 0x29, 0xde, - 0xf0, 0x1b, 0x4d, 0xd3, 0x34, 0xf9, 0x8c, 0xd0, 0xe4, 0x3b, 0x02, 0xd3, 0xf1, 0x39, 0x00, 0xd2, 0x92, 0x7c, 0x79, - 0x47, 0x29, 0xf0, 0x32, 0x40, 0x99, 0xac, 0x48, 0xe0, 0xae, 0xfe, 0x3a, 0x8e, 0x48, 0x10, 0x0f, 0x7a, 0x70, 0xd3, - 0xe6, 0x27, 0xe0, 0x11, 0xb8, 0xa7, 0xe1, 0x83, 0x1d, 0x73, 0x39, 0x27, 0x58, 0x73, 0xe8, 0x73, 0xd8, 0x67, 0xcd, - 0x3e, 0xe1, 0x22, 0x05, 0x0b, 0x82, 0xd4, 0xa1, 0xe2, 0xe2, 0xd9, 0x64, 0x0d, 0xb8, 0x11, 0xdf, 0x45, 0x77, 0xd9, - 0x82, 0x45, 0x2b, 0x1d, 0x63, 0x42, 0xa1, 0x8f, 0x3e, 0x28, 0xf3, 0x8a, 0x88, 0x2d, 0xc0, 0x36, 0xcd, 0x35, 0xe7, - 0x74, 0x17, 0xa6, 0x1c, 0xa5, 0xfa, 0xe6, 0x98, 0x0b, 0x36, 0x53, 0x8e, 0xdb, 0xaa, 0x37, 0x04, 0x5f, 0xd2, 0xb8, - 0x6a, 0xc8, 0x45, 0x9a, 0xd0, 0xd0, 0x06, 0x79, 0xc7, 0xe0, 0xec, 0x22, 0x01, 0xf6, 0x96, 0x5f, 0x5d, 0x34, 0x29, - 0x91, 0xf1, 0x2b, 0x8c, 0xa2, 0xc4, 0xa8, 0x37, 0xc3, 0xc7, 0x09, 0x8e, 0x89, 0x36, 0xb6, 0x33, 0xae, 0xb5, 0xb3, - 0x61, 0xd2, 0x9f, 0xd8, 0x3d, 0x5d, 0x24, 0x04, 0xaa, 0x4f, 0xec, 0x1e, 0x74, 0xff, 0x5e, 0x03, 0x37, 0x45, 0xdf, - 0x82, 0xae, 0x4d, 0x70, 0xf5, 0x3f, 0x06, 0x67, 0x55, 0x5b, 0x0e, 0x90, 0x93, 0x6f, 0xc1, 0xe2, 0x08, 0x62, 0x88, - 0xea, 0x2c, 0x0e, 0x31, 0x57, 0xf1, 0x6f, 0x35, 0xc2, 0xd8, 0x6a, 0x38, 0x1a, 0xc6, 0x33, 0xd7, 0x71, 0x0e, 0x6a, - 0xe5, 0x81, 0x91, 0xdd, 0x54, 0xda, 0x30, 0xb3, 0x81, 0xeb, 0x58, 0xc1, 0x33, 0xdb, 0xeb, 0xd7, 0xee, 0x68, 0xc5, - 0x97, 0xe4, 0x10, 0xd9, 0x5f, 0xa7, 0x4f, 0xd6, 0xad, 0xda, 0x81, 0x34, 0xaa, 0x2a, 0xf3, 0x38, 0xb6, 0x9c, 0xf3, - 0xbf, 0x86, 0xf5, 0xab, 0x9f, 0x3c, 0x59, 0x52, 0x5c, 0x93, 0x21, 0x78, 0x43, 0x6e, 0xc1, 0x31, 0xfa, 0x8b, 0xf6, - 0x5c, 0x6b, 0xd1, 0xf1, 0x31, 0x8c, 0xa1, 0x0c, 0x97, 0x2d, 0x6c, 0xca, 0xd4, 0x06, 0x2a, 0x3d, 0xa6, 0x55, 0x0c, - 0xc7, 0xfd, 0xae, 0xb2, 0x42, 0xa2, 0xb7, 0x95, 0x5a, 0xc0, 0xf6, 0x37, 0x5c, 0x9f, 0xf6, 0x08, 0xfc, 0x12, 0x40, - 0x09, 0xf0, 0x9d, 0xbe, 0xb3, 0xc1, 0xd5, 0xb2, 0xdc, 0x5c, 0xf9, 0x92, 0xdc, 0xbf, 0x31, 0xbc, 0x74, 0x50, 0x86, - 0x26, 0xdb, 0x6b, 0xbe, 0xee, 0x1e, 0xd8, 0x24, 0x8b, 0x26, 0xe5, 0x06, 0x2b, 0xf7, 0xd7, 0xfe, 0xcd, 0x95, 0x30, - 0x0a, 0x04, 0x15, 0x88, 0x1b, 0x30, 0x4a, 0x1e, 0x47, 0xb8, 0xf9, 0xe9, 0xb8, 0x05, 0x7b, 0x51, 0x31, 0x58, 0x81, - 0x3c, 0x82, 0xc9, 0x6a, 0x0a, 0x53, 0x1c, 0x3c, 0x57, 0xa3, 0x59, 0x70, 0x4b, 0x10, 0xa2, 0x1b, 0x77, 0x62, 0x26, - 0x74, 0x0a, 0x8b, 0x3a, 0x01, 0xf7, 0x45, 0xb9, 0x2f, 0xd7, 0x3a, 0xd8, 0xcd, 0xb5, 0xce, 0x76, 0x71, 0xad, 0xc9, - 0x9c, 0xea, 0x36, 0xf1, 0x97, 0x8a, 0x45, 0x9e, 0x20, 0xce, 0x55, 0xc3, 0xbc, 0x12, 0xab, 0x1b, 0xad, 0xaf, 0x44, - 0xad, 0x5a, 0x6b, 0xa4, 0x25, 0x88, 0xec, 0x6f, 0xe5, 0x81, 0x22, 0x04, 0xea, 0x2a, 0x6f, 0xfc, 0xa2, 0xe0, 0x8d, - 0xd3, 0xab, 0xa6, 0x30, 0xa4, 0x11, 0xd4, 0xbf, 0x62, 0xa4, 0x26, 0x5f, 0x07, 0x85, 0xb1, 0x5a, 0x31, 0x52, 0xc5, - 0xfc, 0xaa, 0x78, 0x68, 0x28, 0x46, 0x7d, 0xe2, 0x95, 0x51, 0xb6, 0xed, 0x2b, 0x17, 0x2d, 0xac, 0xaf, 0x8a, 0x74, - 0xe0, 0xba, 0xe3, 0x90, 0x65, 0xb2, 0xba, 0x6d, 0xca, 0xe6, 0x37, 0x6a, 0xb6, 0xb2, 0x49, 0xa4, 0x9d, 0x0c, 0x01, - 0x58, 0xb0, 0xe9, 0x2b, 0x72, 0x6d, 0xa9, 0x03, 0x81, 0x83, 0x6c, 0x30, 0xeb, 0xdb, 0xcd, 0x9d, 0xa7, 0x78, 0x09, - 0x85, 0x14, 0x5e, 0xe5, 0x41, 0x20, 0x7c, 0xaf, 0xd6, 0x0d, 0xb7, 0x3c, 0x5e, 0xf2, 0xfc, 0x7e, 0x07, 0xf6, 0xa2, - 0xe6, 0xa8, 0x82, 0x7c, 0x3c, 0x99, 0x16, 0xa9, 0xe7, 0x62, 0xd1, 0x7a, 0xa3, 0xc4, 0xc4, 0x59, 0x73, 0xcb, 0x98, - 0x32, 0x8f, 0x9e, 0x97, 0xe8, 0x89, 0x7e, 0xf9, 0xd6, 0x49, 0x56, 0x11, 0xfa, 0xb6, 0xb7, 0xb2, 0xc4, 0x1f, 0x7f, - 0x52, 0x86, 0x2c, 0xf8, 0x9c, 0xc0, 0x03, 0x2e, 0x4b, 0x0a, 0xfa, 0x3e, 0xba, 0x82, 0x64, 0x3d, 0xdb, 0x4b, 0x15, - 0xee, 0x4b, 0xef, 0xb1, 0xd3, 0xf6, 0x5f, 0x4c, 0x0f, 0x2b, 0x4c, 0x51, 0xaf, 0x53, 0x66, 0x99, 0x6f, 0x18, 0x47, - 0x36, 0x5f, 0x2d, 0x46, 0x6b, 0x95, 0xb7, 0xaa, 0xb0, 0x5c, 0xeb, 0x6c, 0x56, 0xb5, 0xdb, 0xe9, 0x74, 0x5a, 0x66, - 0x34, 0x3a, 0xda, 0x21, 0x32, 0x0b, 0x1f, 0x3b, 0x8e, 0x53, 0x1d, 0xfb, 0x76, 0xb0, 0x5b, 0xc8, 0xb7, 0xed, 0x36, - 0x8e, 0x18, 0x61, 0xbb, 0x0b, 0x7e, 0x75, 0x70, 0xe4, 0x76, 0x71, 0xb2, 0x4b, 0x6a, 0x11, 0x7d, 0x52, 0x86, 0x08, - 0x32, 0xb6, 0x48, 0x7b, 0x63, 0x86, 0x32, 0x18, 0x5b, 0x39, 0xd0, 0xa8, 0x38, 0x60, 0xcd, 0x40, 0x55, 0xc4, 0x15, - 0xbb, 0xc2, 0xd1, 0x90, 0x1f, 0x5e, 0x63, 0xde, 0x8b, 0x4e, 0xf0, 0xa0, 0xac, 0xeb, 0x3c, 0x6d, 0x9c, 0x56, 0xc7, - 0xf9, 0x4b, 0xa9, 0x9c, 0x06, 0x17, 0xe0, 0x5a, 0x08, 0xb4, 0x89, 0x3f, 0x8b, 0x7f, 0x4b, 0xfe, 0xff, 0x8b, 0xe5, - 0x5d, 0x59, 0x7f, 0xa4, 0x0b, 0x1c, 0xed, 0xe2, 0xb4, 0xd0, 0xa8, 0x9b, 0xf6, 0x80, 0xd4, 0x32, 0x98, 0xaa, 0x02, - 0x74, 0x10, 0xd2, 0x97, 0x02, 0x80, 0x34, 0xb0, 0xdf, 0x91, 0x62, 0x86, 0x25, 0x2e, 0x58, 0x88, 0x45, 0xf8, 0x3a, - 0x98, 0x83, 0xf9, 0xbc, 0x8b, 0xf2, 0x83, 0xd2, 0x9e, 0x00, 0x69, 0x7c, 0x6d, 0x6e, 0x7b, 0xb1, 0xfb, 0xab, 0x72, - 0x2d, 0xd1, 0x30, 0x80, 0xcc, 0x85, 0x43, 0x88, 0x8a, 0x04, 0x5a, 0x65, 0x73, 0xd3, 0x28, 0x65, 0xae, 0x2a, 0x67, - 0x13, 0x03, 0xc3, 0xe6, 0x9a, 0x8b, 0x50, 0xdb, 0x42, 0x5a, 0x00, 0x93, 0xe5, 0xdb, 0x0f, 0xbf, 0x2d, 0x58, 0x62, - 0x75, 0x3f, 0xba, 0xb8, 0xe4, 0xb8, 0x7f, 0x2d, 0xbc, 0x3b, 0x53, 0x3a, 0xff, 0xc8, 0x5f, 0xfc, 0xa1, 0x91, 0xa1, - 0x77, 0x51, 0xe2, 0xd0, 0x71, 0x6d, 0x71, 0xcf, 0xd8, 0xab, 0xf4, 0x22, 0x88, 0xf6, 0x2f, 0xeb, 0xdf, 0xed, 0x5d, - 0x16, 0x2e, 0x8c, 0xbd, 0x0b, 0xc3, 0x8d, 0x43, 0x9a, 0x0b, 0xd9, 0xe0, 0x07, 0x85, 0xa1, 0xa8, 0x5a, 0x1d, 0xeb, - 0x58, 0x8b, 0xa8, 0xfc, 0x8b, 0xd5, 0x60, 0x78, 0x72, 0x76, 0xb7, 0x08, 0xb5, 0x1b, 0x96, 0x40, 0x68, 0x9f, 0x81, - 0xee, 0xda, 0x8e, 0xae, 0xa1, 0x0d, 0x6d, 0x10, 0xcd, 0x06, 0xfa, 0x2f, 0x17, 0x6f, 0xac, 0xae, 0x7e, 0x06, 0x22, - 0xda, 0x9b, 0x19, 0x5e, 0x7b, 0xe7, 0xfe, 0x3d, 0x4b, 0xae, 0x3d, 0x5d, 0xc3, 0x08, 0x3e, 0x74, 0xe1, 0x61, 0x9a, - 0xe6, 0xe9, 0x7b, 0x04, 0x8a, 0xd0, 0x44, 0xac, 0x37, 0x1d, 0x50, 0x8e, 0xeb, 0x75, 0x35, 0xd7, 0x3b, 0xb4, 0x8f, - 0xba, 0xfa, 0xe9, 0x37, 0x9a, 0x76, 0x32, 0x61, 0xd3, 0xf4, 0x14, 0x9f, 0x68, 0x27, 0x78, 0x47, 0xd0, 0x6f, 0x4d, - 0xb3, 0xc7, 0x61, 0x6a, 0xb9, 0xda, 0x9a, 0x7f, 0x6a, 0xda, 0x34, 0x08, 0xc3, 0x9e, 0xf6, 0x78, 0xea, 0x4d, 0x0f, - 0xa7, 0x2f, 0xfa, 0x3c, 0x39, 0xff, 0xa6, 0x54, 0xdc, 0xa4, 0x7f, 0x3d, 0xa5, 0x5a, 0x9a, 0x25, 0xf1, 0x27, 0xc6, - 0xd5, 0x4e, 0x34, 0xf9, 0x78, 0xac, 0x56, 0xf5, 0xea, 0x3d, 0xb9, 0xdd, 0xd1, 0x78, 0xea, 0x15, 0xc5, 0x71, 0x8c, - 0x07, 0x72, 0x90, 0x27, 0x07, 0x62, 0xe8, 0x27, 0x2a, 0x98, 0x5c, 0xab, 0x09, 0x50, 0xae, 0xce, 0xe7, 0x38, 0x13, - 0xf3, 0x3b, 0x01, 0x3f, 0x8c, 0xd2, 0x5c, 0x17, 0x46, 0xa0, 0x6b, 0x93, 0x81, 0xfe, 0xa3, 0xeb, 0x75, 0x4d, 0xd7, - 0x3d, 0xb2, 0x8f, 0xba, 0x63, 0xc7, 0x3c, 0xb4, 0x0f, 0xad, 0xb6, 0x7d, 0x64, 0x76, 0xad, 0xae, 0xd9, 0xfd, 0x5b, - 0x77, 0x6c, 0x1d, 0xda, 0x87, 0xa6, 0x63, 0x75, 0x21, 0xd1, 0xea, 0x5a, 0xdd, 0x1b, 0xeb, 0xb0, 0x3b, 0x76, 0x30, - 0xd5, 0xb3, 0x3b, 0x1d, 0xcb, 0x75, 0xec, 0x4e, 0xc7, 0xec, 0xd8, 0x47, 0x47, 0x96, 0xdb, 0xb6, 0x8f, 0x8e, 0xce, - 0x3b, 0x5d, 0xbb, 0x0d, 0x79, 0xed, 0xf6, 0xb8, 0x6d, 0xbb, 0xae, 0x05, 0x7f, 0x99, 0x5d, 0xdb, 0xa3, 0x1f, 0xae, - 0x6b, 0xb7, 0x5d, 0xd3, 0x09, 0x3b, 0x9e, 0x7d, 0xf4, 0xc2, 0xc4, 0xbf, 0xb1, 0x98, 0x89, 0x7f, 0x41, 0x33, 0xe6, - 0x0b, 0xdb, 0x3b, 0xa2, 0x5f, 0xd8, 0xe0, 0xcd, 0x61, 0xf7, 0x57, 0xfd, 0x60, 0xe3, 0x1c, 0x5c, 0x9a, 0x43, 0xb7, - 0x63, 0xb7, 0xdb, 0xe6, 0xa1, 0x6b, 0x77, 0xdb, 0x73, 0xeb, 0xd0, 0xb3, 0x8f, 0x8e, 0xc7, 0x96, 0x6b, 0x1f, 0x1f, - 0x9b, 0x8e, 0xd5, 0xb6, 0x3d, 0xd3, 0xb5, 0x0f, 0xdb, 0xf8, 0xa3, 0x6d, 0x7b, 0x37, 0xc7, 0x2f, 0xec, 0xa3, 0xce, - 0xfc, 0xc8, 0x3e, 0xfc, 0x78, 0xd8, 0xb5, 0xbd, 0xf6, 0xbc, 0x7d, 0x64, 0x7b, 0xc7, 0x37, 0x47, 0xf6, 0xe1, 0xdc, - 0xf2, 0x8e, 0xb6, 0xd6, 0x74, 0x3d, 0x1b, 0x60, 0x84, 0xd9, 0x90, 0x61, 0xf2, 0x0c, 0xf8, 0x33, 0xc7, 0xba, 0xff, - 0xc5, 0x66, 0xd2, 0x7a, 0xd5, 0x17, 0x76, 0xf7, 0x78, 0x4c, 0xc5, 0x21, 0xc1, 0x12, 0x25, 0xa0, 0xca, 0x8d, 0x45, - 0xdd, 0x62, 0x73, 0x96, 0x68, 0x48, 0xfc, 0xe1, 0x9d, 0xdd, 0x58, 0xd0, 0x31, 0xf5, 0xfb, 0x3f, 0x6d, 0x47, 0x2e, - 0x39, 0x44, 0xae, 0xfc, 0x86, 0xff, 0x43, 0x41, 0x5f, 0x86, 0xe6, 0xf9, 0x26, 0x41, 0xc5, 0xfb, 0xdd, 0x82, 0x8a, - 0x37, 0xab, 0x7d, 0x04, 0x15, 0xef, 0xbf, 0xba, 0xa0, 0xe2, 0xbc, 0xaa, 0x27, 0xff, 0xbe, 0xea, 0x9b, 0xfe, 0xd7, - 0x75, 0xf5, 0x19, 0x12, 0xf8, 0xad, 0xcb, 0x8b, 0xd5, 0x15, 0x78, 0x57, 0x7a, 0x1f, 0x0f, 0xde, 0xac, 0x4a, 0x4a, - 0x60, 0x31, 0xe0, 0xd8, 0xf7, 0x31, 0xe1, 0xd8, 0xdf, 0x57, 0x03, 0xd0, 0x3c, 0xe1, 0x74, 0x49, 0x30, 0xb1, 0xe6, - 0x7e, 0x38, 0x95, 0x34, 0x0d, 0xa4, 0xf4, 0x31, 0x19, 0xac, 0x12, 0xe0, 0xba, 0x06, 0x71, 0xd8, 0x6a, 0x11, 0xa5, - 0xbd, 0x23, 0x07, 0x2e, 0x52, 0x6f, 0x9a, 0xe4, 0x95, 0xca, 0xb6, 0xf0, 0x47, 0x75, 0xcd, 0xad, 0x26, 0x36, 0xe6, - 0xa3, 0x52, 0x60, 0x73, 0xeb, 0x6e, 0xbd, 0x5d, 0x0d, 0xb4, 0x6d, 0x84, 0xd2, 0x24, 0x90, 0x73, 0x4d, 0xf9, 0x65, - 0xd5, 0xbc, 0x8a, 0x32, 0xe6, 0xe6, 0x91, 0xc2, 0x48, 0xaa, 0xf5, 0xdd, 0xb2, 0x6a, 0xdf, 0xae, 0x69, 0x36, 0x74, - 0x5f, 0xaa, 0xbe, 0x45, 0xaf, 0x50, 0x36, 0x5c, 0x05, 0x55, 0x25, 0xb2, 0x5a, 0x23, 0x40, 0x0a, 0xea, 0xbe, 0x50, - 0x3e, 0x2c, 0x48, 0x4b, 0x47, 0x43, 0x7a, 0xc7, 0x51, 0xf2, 0x4a, 0x6d, 0xaa, 0x0a, 0x8b, 0xcf, 0xd6, 0x48, 0x71, - 0x07, 0xbf, 0x03, 0xe9, 0xc8, 0x29, 0x9e, 0x51, 0xac, 0xc2, 0x79, 0xad, 0xb4, 0x4b, 0x8f, 0x99, 0x7c, 0xee, 0xae, - 0xeb, 0xc4, 0xe3, 0x46, 0x55, 0x65, 0x97, 0x2d, 0x04, 0x15, 0x84, 0xdd, 0x93, 0x62, 0x70, 0x4e, 0xca, 0xdb, 0xa8, - 0xfb, 0xbc, 0xad, 0x31, 0x51, 0xee, 0x31, 0x6c, 0x62, 0x93, 0x7f, 0xa8, 0x7e, 0x01, 0xd6, 0x53, 0x88, 0x82, 0xdd, - 0x43, 0x32, 0x4d, 0xa1, 0x51, 0x3d, 0xd4, 0x62, 0xee, 0x6f, 0x51, 0xb0, 0x51, 0x1b, 0xe6, 0x8d, 0xa0, 0x36, 0xf4, - 0x36, 0x9d, 0x1c, 0x69, 0x3c, 0xb2, 0x2e, 0x89, 0xa8, 0xdd, 0xce, 0xb1, 0xe9, 0x1e, 0x99, 0xf6, 0x71, 0xc7, 0xc8, - 0xc5, 0x81, 0x53, 0x9b, 0x2c, 0x01, 0x04, 0x94, 0xa2, 0xe5, 0x30, 0x83, 0x28, 0xc8, 0x02, 0x3f, 0xcc, 0x81, 0x3e, - 0x2e, 0xbf, 0x2a, 0xfe, 0xb9, 0x4a, 0x33, 0x98, 0xa3, 0x20, 0x7a, 0x51, 0x21, 0xdc, 0x1a, 0xb1, 0xec, 0x96, 0xb1, - 0x68, 0x83, 0xb0, 0xbc, 0xaa, 0x5f, 0xfe, 0xe7, 0x69, 0xdb, 0xe6, 0xa4, 0xc9, 0x32, 0xca, 0x22, 0xbe, 0x3f, 0x84, - 0x32, 0x74, 0x3e, 0x34, 0x7f, 0xda, 0x84, 0x70, 0xff, 0xb9, 0x1b, 0xe1, 0x66, 0x6c, 0x1f, 0x84, 0xfb, 0xcf, 0xaf, - 0x8e, 0x70, 0x7f, 0x52, 0x11, 0x6e, 0xc9, 0x16, 0xa8, 0xe0, 0x3a, 0x7f, 0xc0, 0xef, 0x16, 0x38, 0x75, 0x7e, 0xae, - 0x1f, 0x10, 0x01, 0xaf, 0x2b, 0xc1, 0x76, 0x3f, 0x96, 0xa2, 0x07, 0x21, 0x53, 0x04, 0x9d, 0xd0, 0x52, 0xa4, 0x12, - 0x08, 0x44, 0x2b, 0x43, 0xaa, 0x43, 0x9b, 0x6f, 0xa3, 0x2c, 0xb4, 0xdf, 0xf3, 0x87, 0x1f, 0x08, 0x79, 0xde, 0xc4, - 0xc9, 0xc2, 0x47, 0x07, 0x7c, 0x3a, 0x46, 0x1d, 0x84, 0x0f, 0x07, 0xec, 0xcf, 0xc6, 0x71, 0x34, 0x91, 0x92, 0x0a, - 0x36, 0xb8, 0x24, 0x8a, 0x5b, 0xbf, 0x67, 0x7e, 0xa2, 0x9b, 0x94, 0x0d, 0x8b, 0xfb, 0xac, 0xed, 0x3c, 0xf3, 0x0e, - 0x9f, 0x1d, 0x39, 0xf0, 0xbf, 0xcb, 0xda, 0xb9, 0xc9, 0x0b, 0x2e, 0xe2, 0x08, 0x02, 0x9f, 0x88, 0x92, 0x9b, 0x8a, - 0xdd, 0x32, 0xf6, 0xa9, 0x28, 0x75, 0xdc, 0x5c, 0x68, 0xe2, 0xdf, 0x17, 0x65, 0x1a, 0x4b, 0xcc, 0xe3, 0x95, 0x32, - 0xac, 0x86, 0xd1, 0x04, 0xd1, 0x0a, 0x78, 0x6f, 0x4a, 0x09, 0x35, 0x9b, 0x4f, 0xb7, 0x98, 0x17, 0x6b, 0xe7, 0x57, - 0x45, 0x74, 0x25, 0x11, 0xe5, 0x65, 0x27, 0x04, 0xb9, 0xd8, 0xc2, 0x41, 0xdf, 0xec, 0x18, 0x5f, 0x48, 0x83, 0xd8, - 0x86, 0x62, 0x81, 0x7c, 0x5a, 0xa0, 0x2c, 0x59, 0x45, 0xe3, 0x16, 0xfe, 0xf4, 0x47, 0x69, 0x2b, 0x38, 0x00, 0xef, - 0xac, 0xd8, 0xb1, 0x81, 0xab, 0xe6, 0x9f, 0x3a, 0x45, 0x28, 0x8a, 0x54, 0xac, 0x8a, 0xff, 0x2c, 0x33, 0x13, 0x0a, - 0x60, 0x8b, 0x4b, 0x6b, 0x0d, 0xfc, 0x67, 0xb2, 0xe2, 0xb3, 0xcc, 0x84, 0x20, 0xb2, 0xb0, 0xdc, 0x4f, 0x9f, 0x52, - 0x29, 0x08, 0xeb, 0x48, 0xd3, 0x3a, 0x1b, 0x17, 0xee, 0xdd, 0x34, 0x7f, 0x16, 0x93, 0x87, 0xb7, 0xde, 0xd8, 0x8c, - 0x9f, 0x3f, 0x3f, 0x1d, 0xb8, 0x06, 0x0f, 0x4a, 0x5a, 0x8a, 0xa0, 0x75, 0xbe, 0x9f, 0xf2, 0x81, 0xd1, 0x68, 0x16, - 0xb7, 0x84, 0x37, 0x93, 0x23, 0x54, 0x94, 0x39, 0xf6, 0x82, 0x88, 0x16, 0x24, 0x64, 0xf4, 0x85, 0x12, 0x80, 0x28, - 0x23, 0x5f, 0x5d, 0x6d, 0xdb, 0xb1, 0x1d, 0x5d, 0x56, 0x9c, 0x06, 0xb3, 0xc1, 0x3a, 0xce, 0x7c, 0x88, 0x0d, 0x14, - 0xc6, 0x33, 0xb0, 0xad, 0xc9, 0x82, 0x2c, 0x84, 0x40, 0x33, 0x60, 0x64, 0xb3, 0xa0, 0x77, 0x79, 0xce, 0x35, 0x9e, - 0xfd, 0xe4, 0x13, 0x06, 0x1b, 0x14, 0x66, 0x75, 0xe8, 0x71, 0xe8, 0x47, 0xb8, 0x0c, 0x5b, 0x7a, 0x0b, 0x42, 0x5d, - 0xb2, 0x24, 0xb5, 0x54, 0x0b, 0x82, 0x9e, 0x06, 0x75, 0x20, 0x0c, 0x3d, 0x36, 0x30, 0x4d, 0xfc, 0x05, 0xf8, 0x64, - 0x5f, 0xe7, 0x26, 0xc7, 0xb4, 0x3a, 0x47, 0xb5, 0x9a, 0xfb, 0xe2, 0xc8, 0xd4, 0x3c, 0xd7, 0xd4, 0x1c, 0x40, 0xb7, - 0x7a, 0x6e, 0xae, 0xf3, 0xab, 0xfe, 0x2e, 0x21, 0x28, 0xe1, 0x97, 0xc7, 0x34, 0x0f, 0x12, 0x7f, 0x72, 0xf6, 0x72, - 0x46, 0x0e, 0x24, 0x5b, 0x8a, 0xb7, 0xf4, 0x80, 0x04, 0x21, 0x17, 0xec, 0x2e, 0x33, 0x30, 0x10, 0x0b, 0x2f, 0x12, - 0x18, 0x6b, 0x34, 0xfe, 0x0b, 0x22, 0x2d, 0xf8, 0xfc, 0xb9, 0x15, 0x80, 0x81, 0xc3, 0x40, 0x81, 0x0f, 0x7c, 0x1b, - 0x25, 0x80, 0x05, 0x85, 0xe8, 0x0e, 0x81, 0x05, 0xd6, 0x47, 0xf0, 0x6f, 0x91, 0x2c, 0x7e, 0x70, 0xd1, 0xa9, 0x1d, - 0xfa, 0xd1, 0x0c, 0x50, 0x9a, 0x1f, 0xcd, 0x6a, 0x2a, 0x1a, 0x64, 0xbf, 0x58, 0x49, 0x2d, 0x9a, 0x2a, 0xd4, 0x27, - 0xd2, 0xef, 0xef, 0x2f, 0x28, 0xd0, 0x14, 0x04, 0x35, 0xf7, 0x27, 0x68, 0x6c, 0x57, 0x48, 0x77, 0x9e, 0x0f, 0xbe, - 0x3d, 0x59, 0xb0, 0xcc, 0x27, 0xd6, 0x30, 0x3c, 0x7e, 0x81, 0x1c, 0xd0, 0xc6, 0x22, 0x48, 0x2c, 0x05, 0x93, 0x9f, - 0xb0, 0x9b, 0x60, 0xcc, 0xdf, 0xa5, 0xa6, 0xc6, 0xef, 0x29, 0x0b, 0xb5, 0xc0, 0x06, 0xae, 0x49, 0x4a, 0xc8, 0x63, - 0x1f, 0xdd, 0x4c, 0x0e, 0xa2, 0x58, 0x3f, 0xfd, 0x56, 0xda, 0x6b, 0x6d, 0x5a, 0x04, 0x88, 0xf6, 0x78, 0x99, 0xb0, - 0xf0, 0x5f, 0x83, 0x6f, 0xe1, 0xe2, 0xfe, 0xf6, 0x4a, 0x37, 0xfa, 0x99, 0x3d, 0x4f, 0xd8, 0x74, 0xf0, 0x6d, 0x43, - 0xd4, 0x43, 0x7c, 0xde, 0xd3, 0x58, 0xf4, 0xb6, 0x57, 0x38, 0x07, 0x6a, 0xef, 0xf5, 0xa8, 0x3f, 0xe5, 0xaf, 0x75, - 0x78, 0x01, 0xae, 0x4b, 0x6f, 0x6c, 0xb7, 0x8f, 0xef, 0xe7, 0x51, 0xe8, 0x8f, 0x3f, 0xf5, 0x29, 0xa7, 0xf4, 0x61, - 0xc1, 0x6d, 0x3d, 0xf6, 0x97, 0x3d, 0xbc, 0x5e, 0xd5, 0x44, 0x30, 0xd7, 0xa4, 0x54, 0x49, 0xd9, 0x35, 0xee, 0x65, - 0xdc, 0xca, 0x6b, 0xec, 0x19, 0xbb, 0xba, 0x9d, 0x07, 0x19, 0x13, 0x5d, 0xe1, 0x47, 0x9e, 0x8b, 0x87, 0x3a, 0x3d, - 0x51, 0xf1, 0x61, 0x6d, 0xb7, 0x35, 0xb7, 0xfb, 0xb7, 0xce, 0x8d, 0xeb, 0xcc, 0x3d, 0xd7, 0xee, 0x7e, 0x74, 0xbb, - 0xf3, 0xb6, 0x7d, 0x1c, 0x5a, 0x6d, 0xfb, 0x18, 0xfe, 0x7c, 0x3c, 0xb6, 0xbb, 0x73, 0xcb, 0xb3, 0x0f, 0x3f, 0xba, - 0x5e, 0x68, 0x75, 0xed, 0x63, 0xf8, 0x73, 0x4e, 0xb5, 0xe0, 0x01, 0x44, 0xef, 0x9d, 0x6f, 0x4b, 0x58, 0x40, 0xf9, - 0x2d, 0xe5, 0x34, 0x66, 0xe9, 0x7a, 0x6b, 0x90, 0xf5, 0x00, 0xca, 0xd0, 0x4d, 0xe1, 0x04, 0x32, 0xea, 0xb7, 0x20, - 0x0c, 0x3b, 0x06, 0x10, 0x10, 0x2a, 0x2f, 0xc2, 0x2e, 0x55, 0xb8, 0xd2, 0x6f, 0x3c, 0x46, 0xbc, 0x4e, 0xb3, 0xc3, - 0x75, 0x11, 0x99, 0x8a, 0x84, 0x43, 0xbf, 0x2c, 0xd1, 0x89, 0x91, 0x70, 0x11, 0xaf, 0x60, 0xa5, 0x22, 0x3a, 0x62, - 0xbe, 0x7b, 0xe0, 0x68, 0x99, 0xcb, 0x64, 0x74, 0x9e, 0xaf, 0xda, 0x36, 0x17, 0x18, 0xc9, 0xd6, 0xff, 0x68, 0x3b, - 0x18, 0x94, 0x96, 0xda, 0x11, 0xde, 0x5c, 0x27, 0x41, 0x22, 0x87, 0xa7, 0xa0, 0x68, 0xb7, 0xd9, 0x53, 0xbd, 0x01, - 0x61, 0x4c, 0xde, 0x02, 0x95, 0x7c, 0xe3, 0x87, 0x8a, 0x72, 0x8b, 0x52, 0xf3, 0x91, 0xc4, 0xfc, 0x4f, 0x9f, 0x16, - 0x83, 0xb3, 0x2a, 0xe3, 0x3e, 0x71, 0x3b, 0x70, 0xed, 0x76, 0x58, 0x7b, 0xab, 0x9e, 0xd5, 0x6e, 0x77, 0xc0, 0x85, - 0xbb, 0x50, 0xa1, 0x4b, 0x21, 0xa4, 0xb8, 0x1b, 0x95, 0xbd, 0x6a, 0x32, 0x5c, 0x70, 0xa4, 0x5c, 0x79, 0xea, 0xe8, - 0x46, 0x3f, 0x12, 0x22, 0xc9, 0x68, 0x8b, 0x0b, 0x64, 0xfe, 0x16, 0xd3, 0x01, 0x34, 0x5b, 0xe6, 0xb1, 0xc3, 0x68, - 0xf4, 0x7f, 0x3d, 0x09, 0x34, 0xe0, 0x02, 0x19, 0x6a, 0xe5, 0xb4, 0x96, 0x0c, 0x7a, 0xe4, 0xbd, 0x4a, 0x17, 0x2a, - 0x4b, 0xcf, 0x74, 0x48, 0x82, 0xf8, 0x56, 0x18, 0xd2, 0x4e, 0x2a, 0x90, 0xc9, 0xdb, 0xa2, 0x48, 0x30, 0x03, 0xf0, - 0x01, 0xde, 0x12, 0xc6, 0x64, 0xc6, 0xd3, 0xa7, 0x1b, 0x2f, 0x21, 0x12, 0xd8, 0xab, 0x91, 0x3d, 0x75, 0x15, 0xbf, - 0xe9, 0x2a, 0x8a, 0x91, 0xed, 0x22, 0xd6, 0x10, 0x7a, 0x6f, 0xb4, 0xf7, 0xf0, 0xe7, 0x88, 0xf9, 0x99, 0xcd, 0x25, - 0x4d, 0x2d, 0xe5, 0x72, 0x37, 0x5d, 0xd6, 0x06, 0x8d, 0x37, 0xee, 0xeb, 0x8c, 0xfb, 0x12, 0x7c, 0xb2, 0xfe, 0xb8, - 0xe2, 0x96, 0xde, 0xd0, 0xc6, 0x67, 0xa7, 0x70, 0x4f, 0xf3, 0x2e, 0xf3, 0xc9, 0x87, 0x89, 0x7a, 0xe5, 0xc6, 0x99, - 0x2f, 0xe2, 0xc8, 0x00, 0x5d, 0xde, 0x6f, 0x14, 0xc9, 0x2a, 0xd6, 0xe0, 0xa7, 0xef, 0x2e, 0xbe, 0xd3, 0xf8, 0xfe, - 0x27, 0x09, 0x22, 0x3e, 0x64, 0x28, 0xea, 0xc1, 0x80, 0xa2, 0x1e, 0x68, 0x3c, 0x8c, 0x08, 0xc4, 0x0e, 0xc8, 0x0f, - 0x08, 0x82, 0xc8, 0x80, 0x26, 0xb9, 0xea, 0x62, 0x15, 0x66, 0xc1, 0xd2, 0x4f, 0xb2, 0x03, 0xa8, 0x6a, 0x01, 0x92, - 0xd3, 0x37, 0xd9, 0x88, 0x93, 0x68, 0x56, 0xb8, 0xd8, 0xcb, 0x22, 0x21, 0x9b, 0x9d, 0x06, 0xa1, 0x14, 0xcd, 0x8a, - 0x0e, 0xfc, 0xf1, 0x98, 0x2d, 0xb3, 0x81, 0xee, 0x2f, 0x21, 0xfa, 0x05, 0xfa, 0xb3, 0x3e, 0x88, 0xc7, 0x19, 0xcb, - 0xac, 0x34, 0x4b, 0x98, 0xbf, 0xd0, 0xa5, 0x2b, 0xd7, 0x7a, 0x7b, 0xe9, 0x6a, 0xb4, 0x08, 0x32, 0xe9, 0x0b, 0x91, - 0x26, 0x08, 0x42, 0x52, 0x18, 0xe2, 0xe9, 0x30, 0xe7, 0x20, 0x3c, 0x8f, 0x67, 0x95, 0x1d, 0x55, 0x50, 0x2e, 0x67, - 0xe8, 0x69, 0x97, 0x47, 0x3c, 0x98, 0xa0, 0xcd, 0xd3, 0x35, 0xb7, 0x6b, 0x97, 0x2e, 0x1b, 0xf5, 0xd3, 0x13, 0xfe, - 0xbc, 0xd5, 0xd0, 0x15, 0x83, 0xde, 0x71, 0xc0, 0x97, 0xf0, 0x26, 0x8b, 0xf7, 0x03, 0x5e, 0x18, 0xae, 0x26, 0x6a, - 0x19, 0xfd, 0xbc, 0xd3, 0x58, 0x2e, 0x80, 0x10, 0x2a, 0x09, 0xd1, 0xe7, 0xee, 0xa9, 0x34, 0xb1, 0xc2, 0x51, 0x21, - 0xad, 0xf4, 0xf9, 0xf3, 0xcb, 0xe1, 0x7f, 0xfe, 0x0d, 0xce, 0xe8, 0xe7, 0xae, 0xb0, 0x33, 0xbf, 0x54, 0x4b, 0x71, - 0xea, 0xd3, 0x1c, 0xa2, 0x02, 0x05, 0x9b, 0x08, 0xc7, 0x2b, 0x62, 0x6b, 0xe5, 0xc3, 0x2b, 0xe1, 0x4c, 0x0b, 0x02, - 0x4e, 0x18, 0xc2, 0x1a, 0x7e, 0x08, 0xcb, 0x3b, 0x14, 0x4e, 0x18, 0xb4, 0xdf, 0xee, 0xbe, 0x3f, 0x06, 0x67, 0xcb, - 0xb5, 0x38, 0x10, 0xca, 0x00, 0x71, 0x0f, 0x9d, 0x9e, 0xf8, 0x1a, 0x12, 0x2d, 0x48, 0x7e, 0xa4, 0xbd, 0x03, 0x98, - 0xe6, 0x3c, 0x5e, 0x30, 0x3b, 0x88, 0x0f, 0x6e, 0xd9, 0xc8, 0xf2, 0x97, 0x01, 0xc9, 0xea, 0x91, 0xef, 0xa6, 0x11, - 0xe5, 0x27, 0x45, 0xe0, 0x44, 0x5f, 0xe7, 0x05, 0x28, 0xe3, 0x02, 0x50, 0xf0, 0xd3, 0x3f, 0x2d, 0xfb, 0x67, 0xb4, - 0x45, 0x84, 0x80, 0x32, 0x96, 0x3f, 0x23, 0x37, 0x8b, 0xc2, 0xa3, 0x62, 0xf1, 0x61, 0xc5, 0xd3, 0xa9, 0xea, 0x53, - 0xd1, 0x2e, 0xf7, 0x2f, 0xa1, 0x52, 0xec, 0xd9, 0x78, 0x49, 0x3d, 0xd5, 0xbb, 0x90, 0x3f, 0x21, 0x3a, 0x32, 0x77, - 0xbf, 0x09, 0xe7, 0xb9, 0xe6, 0x9b, 0x51, 0x82, 0xe4, 0x31, 0x15, 0xe2, 0x88, 0xa2, 0xea, 0x09, 0x7c, 0x03, 0x69, - 0xf2, 0x68, 0x30, 0x20, 0x3c, 0x56, 0x45, 0x67, 0x00, 0xa5, 0x86, 0x68, 0x09, 0x30, 0xd9, 0x0c, 0x2a, 0x5a, 0x64, - 0x23, 0x87, 0x95, 0xaa, 0xd3, 0xa9, 0x8f, 0xf1, 0xc0, 0x17, 0xfb, 0xab, 0xb4, 0x03, 0x61, 0x67, 0xf1, 0x85, 0x05, - 0x04, 0x2e, 0xda, 0xa9, 0xe0, 0x71, 0xed, 0xaf, 0x84, 0xb2, 0xad, 0xd0, 0xbf, 0x8f, 0x15, 0xdd, 0x05, 0xee, 0xc6, - 0xe0, 0x1c, 0x53, 0x2f, 0x84, 0xf9, 0x60, 0xed, 0x24, 0x49, 0x8f, 0xf3, 0xf5, 0xd3, 0xa4, 0xba, 0x88, 0xdf, 0x75, - 0x98, 0xd4, 0xb2, 0xe5, 0xc9, 0x20, 0x76, 0xcc, 0x8b, 0x83, 0x56, 0xca, 0xc4, 0x73, 0x9f, 0x9f, 0x1c, 0xc0, 0xfc, - 0xc0, 0xf5, 0x42, 0x89, 0x32, 0x0a, 0x0c, 0xf0, 0xef, 0xe0, 0xa7, 0xa4, 0x7f, 0xf1, 0x76, 0x22, 0x88, 0x3a, 0x7c, - 0x39, 0x4a, 0xe7, 0xaf, 0xa5, 0x22, 0x75, 0x62, 0xc5, 0x69, 0xa6, 0xf2, 0x76, 0x47, 0x68, 0xf8, 0x7d, 0x85, 0xe1, - 0x19, 0xf2, 0x7e, 0xc6, 0x84, 0x65, 0xf3, 0x79, 0xb6, 0xc1, 0xf8, 0x79, 0x53, 0x11, 0x22, 0x58, 0xb7, 0x14, 0x28, - 0xf6, 0xf1, 0xb6, 0x52, 0x05, 0x69, 0x24, 0x8b, 0x2d, 0xfd, 0x96, 0xfe, 0x18, 0x77, 0x7c, 0xad, 0x34, 0xa6, 0x42, - 0xb9, 0xf3, 0x6c, 0x00, 0x45, 0x05, 0xb3, 0xdd, 0x5f, 0x2e, 0xa9, 0xb0, 0xd1, 0x3f, 0x39, 0xa0, 0x77, 0xe7, 0x29, - 0xed, 0xb0, 0xd3, 0x13, 0xd0, 0xdf, 0xa4, 0x45, 0xf7, 0x97, 0x4b, 0xbe, 0xa4, 0xf4, 0x8b, 0x72, 0x0e, 0xe6, 0xd9, - 0x22, 0x3c, 0xfd, 0x3f, 0x1d, 0xdb, 0x6f, 0x83, 0x01, 0x5c, 0x03, 0x00}; + 0xdc, 0xb3, 0x37, 0xb7, 0x6d, 0x23, 0xff, 0x7f, 0x3f, 0x05, 0xc3, 0xe4, 0x52, 0x31, 0x21, 0x69, 0x92, 0xb2, 0x6c, + 0x45, 0xb2, 0xec, 0x6b, 0xf3, 0x98, 0x4b, 0xc7, 0x6d, 0x3a, 0x89, 0x9b, 0xb9, 0xab, 0xeb, 0xb1, 0x28, 0x09, 0x92, + 0x78, 0xa1, 0x48, 0x0d, 0x49, 0xf9, 0x51, 0x85, 0xf7, 0x59, 0xee, 0xb3, 0xdc, 0x27, 0xfb, 0xcd, 0xee, 0x02, 0x20, + 0xf8, 0xd0, 0xc3, 0x4d, 0x7a, 0xf7, 0x9b, 0x36, 0x89, 0x08, 0x02, 0x4b, 0x60, 0x01, 0x2c, 0x16, 0xfb, 0xf4, 0x67, + 0x5c, 0xf6, 0x62, 0xb6, 0xd8, 0x7e, 0x9f, 0xfb, 0xfc, 0x99, 0xd9, 0xb8, 0x24, 0x81, 0xe1, 0xb3, 0xb3, 0x78, 0x36, + 0x0b, 0x59, 0x4b, 0x17, 0xc9, 0x43, 0x74, 0x53, 0x7e, 0xe6, 0xec, 0x91, 0x23, 0x22, 0x76, 0x1a, 0xf9, 0xa6, 0xad, + 0x25, 0x46, 0xcc, 0x64, 0x48, 0x3b, 0xe2, 0x5c, 0x51, 0x36, 0x7b, 0x83, 0xea, 0x0d, 0x3e, 0x2f, 0xc5, 0xd6, 0xb5, + 0x26, 0xf1, 0x6a, 0x14, 0x32, 0x0b, 0x97, 0x3b, 0x7c, 0x72, 0x3d, 0x5a, 0x8d, 0x46, 0x90, 0xa5, 0xe5, 0x91, 0x63, + 0x42, 0xdc, 0x99, 0x38, 0xc5, 0xfb, 0x60, 0x6e, 0xf4, 0x61, 0x50, 0x76, 0x56, 0xed, 0x3e, 0xd8, 0x8a, 0x80, 0xa8, + 0x87, 0x3e, 0x90, 0xc1, 0xdd, 0xaf, 0x61, 0xd7, 0x0e, 0xf4, 0x0f, 0xb0, 0xfa, 0x52, 0xbd, 0xdf, 0xb4, 0xf5, 0x07, + 0x97, 0xfa, 0x07, 0xc4, 0x31, 0x66, 0x2f, 0x7e, 0x49, 0xab, 0x57, 0x37, 0x75, 0x52, 0x7a, 0xaf, 0x30, 0x8f, 0x01, + 0x08, 0x7d, 0x5f, 0x05, 0xfe, 0x2c, 0x8a, 0xd3, 0x2c, 0x18, 0xeb, 0x57, 0xfd, 0xb7, 0x41, 0xeb, 0x72, 0x91, 0xb5, + 0x8c, 0x2b, 0x73, 0x9c, 0xa9, 0x29, 0x50, 0x04, 0xc1, 0xc4, 0x0c, 0x28, 0x9b, 0x2a, 0xa9, 0x3b, 0x68, 0x6b, 0x45, + 0x41, 0x9a, 0xb1, 0xd2, 0x38, 0x1b, 0x40, 0xbd, 0x4a, 0x3e, 0x15, 0x4c, 0x0c, 0xa5, 0x63, 0x4b, 0xa3, 0x4f, 0x37, + 0x95, 0x97, 0xab, 0x35, 0x1e, 0xe5, 0x59, 0x71, 0x5a, 0x62, 0x0c, 0x60, 0xe1, 0x38, 0x43, 0xcf, 0x8f, 0x54, 0xa3, + 0xcf, 0xd2, 0xb9, 0x3b, 0xfc, 0xae, 0xcc, 0x17, 0xc0, 0xf9, 0x0d, 0x16, 0x17, 0x51, 0x9c, 0x69, 0x10, 0xd8, 0x06, + 0xbe, 0x38, 0xac, 0x1a, 0x89, 0x71, 0xa8, 0x2d, 0x23, 0xe7, 0xc4, 0xe0, 0x7b, 0x3c, 0xfc, 0x5a, 0x3c, 0xbc, 0x59, + 0x29, 0x82, 0x05, 0x5d, 0x16, 0x22, 0x98, 0xc0, 0x2c, 0x3e, 0x8f, 0x6f, 0xab, 0x7a, 0x90, 0x97, 0xc3, 0xdd, 0x67, + 0x6f, 0x4b, 0xb0, 0xc9, 0x22, 0xab, 0x5f, 0x8b, 0x27, 0x26, 0x15, 0x8c, 0x4e, 0x65, 0x4f, 0xa1, 0xe1, 0x87, 0xe0, + 0x61, 0x32, 0xb0, 0x13, 0xc3, 0xb3, 0x00, 0x48, 0x12, 0x3f, 0xa6, 0x87, 0xf9, 0xb5, 0x48, 0x9d, 0x2c, 0x12, 0x17, + 0x2b, 0x87, 0x33, 0x50, 0xd7, 0x68, 0xb9, 0xca, 0x30, 0xd4, 0x2e, 0x74, 0x80, 0xe5, 0xba, 0x86, 0xa1, 0x3b, 0x81, + 0x4a, 0x17, 0x6c, 0x62, 0xae, 0x6b, 0xc1, 0xa4, 0x5e, 0xc6, 0x99, 0x5e, 0x20, 0x5e, 0x48, 0xdf, 0x51, 0x50, 0x05, + 0x8f, 0x09, 0x1f, 0xc6, 0xd8, 0x2c, 0xe2, 0xd4, 0xb7, 0xc6, 0xa8, 0xd0, 0x69, 0xa0, 0x0c, 0x63, 0x82, 0xd3, 0x6f, + 0x85, 0x8d, 0x83, 0x85, 0xf0, 0x9b, 0xa5, 0x61, 0x0e, 0x9f, 0xac, 0xa3, 0xfc, 0xec, 0xc9, 0x3a, 0xcd, 0x07, 0x4f, + 0xd6, 0xbe, 0xb4, 0x15, 0xd0, 0x2f, 0x74, 0x32, 0x14, 0x18, 0x22, 0x1a, 0x86, 0xf9, 0x75, 0xe1, 0xb9, 0x53, 0x8c, + 0x17, 0x56, 0x19, 0x95, 0x6b, 0xa8, 0xba, 0x1f, 0x70, 0x05, 0xfd, 0x32, 0x09, 0x16, 0x7e, 0x72, 0x4f, 0xfa, 0x7c, + 0x53, 0x55, 0xfa, 0x1b, 0xba, 0x46, 0x84, 0x9e, 0x10, 0x40, 0x34, 0x5f, 0xd7, 0xfe, 0x2a, 0xcb, 0x18, 0x1f, 0xad, + 0x54, 0x6a, 0xc2, 0xb7, 0xae, 0xf5, 0xe7, 0xcc, 0x9e, 0xb0, 0xcc, 0x0f, 0x42, 0x6a, 0xd2, 0x17, 0xd9, 0xea, 0x6b, + 0xc3, 0x4b, 0xcb, 0xc3, 0x8b, 0xca, 0xeb, 0x07, 0x07, 0x43, 0x47, 0x00, 0xf5, 0x1b, 0x47, 0x86, 0x59, 0xac, 0x9a, + 0x67, 0x94, 0xde, 0xfd, 0x57, 0xa7, 0x83, 0xc1, 0x74, 0x44, 0x30, 0x1d, 0x2c, 0x1a, 0xc7, 0x13, 0xf6, 0xcb, 0xfb, + 0xb7, 0x32, 0x6d, 0x16, 0x48, 0x80, 0x86, 0x7c, 0x61, 0xa6, 0xc8, 0x3f, 0x24, 0xc8, 0x3b, 0x50, 0x82, 0x2b, 0x4d, + 0x2e, 0xa1, 0x24, 0xd7, 0xb5, 0x33, 0xea, 0x3b, 0x9b, 0x50, 0xaf, 0x07, 0x31, 0xb6, 0x4a, 0xf2, 0x93, 0x03, 0xaa, + 0x4d, 0xa7, 0x1d, 0x55, 0x02, 0x34, 0x24, 0x30, 0xc2, 0x02, 0x0b, 0x90, 0xe1, 0x73, 0xe0, 0x16, 0x17, 0x0a, 0x7b, + 0x81, 0x72, 0x76, 0xf7, 0xac, 0xcc, 0xaa, 0x60, 0x2b, 0xfd, 0xf4, 0x04, 0x73, 0x76, 0xc1, 0x79, 0x0d, 0x51, 0x3e, + 0x4e, 0x0e, 0xe8, 0x51, 0xab, 0xec, 0x88, 0x02, 0x88, 0xb8, 0xda, 0xf5, 0x38, 0x80, 0x07, 0x6d, 0x15, 0x48, 0x11, + 0x0f, 0xa5, 0x7e, 0xae, 0x6b, 0x0b, 0xce, 0x1a, 0xf1, 0x70, 0x42, 0x10, 0x6b, 0xc0, 0x81, 0xbd, 0xab, 0x6b, 0x0b, + 0xff, 0x0e, 0x47, 0x2e, 0xde, 0xf8, 0x77, 0x2d, 0x97, 0xbf, 0x2a, 0xf6, 0x5a, 0x5a, 0xde, 0x6b, 0x63, 0x3e, 0xb9, + 0xe0, 0x48, 0x20, 0x6f, 0xd6, 0x73, 0x54, 0xd0, 0x36, 0x4c, 0xee, 0x5c, 0x4c, 0xee, 0x64, 0xc3, 0xe4, 0x4e, 0xb6, + 0x4c, 0x6e, 0xc8, 0x27, 0x52, 0x93, 0xa8, 0x4b, 0xd0, 0x39, 0x4c, 0x22, 0x8f, 0x33, 0x1a, 0x3d, 0xbe, 0xcf, 0x10, + 0x4f, 0x56, 0x1a, 0x82, 0x71, 0xd4, 0x06, 0x5c, 0x35, 0xe1, 0x45, 0x41, 0x44, 0x7d, 0xe0, 0x72, 0xd7, 0x89, 0x71, + 0x43, 0x0e, 0xce, 0x56, 0x58, 0x1d, 0x2f, 0xac, 0x52, 0xca, 0x2f, 0xde, 0x9a, 0x6f, 0x18, 0xe9, 0x7c, 0xcb, 0x48, + 0xc7, 0xa5, 0xad, 0xcb, 0x87, 0x4d, 0x9b, 0x50, 0x1d, 0x14, 0xac, 0x41, 0x30, 0x18, 0xc5, 0x25, 0x53, 0x5e, 0x87, + 0x9b, 0x69, 0xac, 0xb2, 0xa2, 0x96, 0x7e, 0x9a, 0xde, 0xc6, 0x09, 0x68, 0x5c, 0x00, 0xcc, 0xc3, 0x96, 0xd4, 0x22, + 0x88, 0x78, 0x30, 0x97, 0x8d, 0x8b, 0xa9, 0x78, 0xaf, 0x2e, 0x29, 0xaf, 0xd3, 0xa1, 0x1a, 0x4b, 0x3f, 0xcb, 0x58, + 0x82, 0x48, 0xf7, 0x21, 0xea, 0xf7, 0xff, 0x93, 0x65, 0xd6, 0x40, 0x43, 0x42, 0x85, 0xaa, 0x23, 0x85, 0x5e, 0x02, + 0x6f, 0x95, 0x88, 0x83, 0x58, 0x09, 0x0c, 0x97, 0x48, 0xc4, 0xff, 0x84, 0xdb, 0xb5, 0x95, 0x28, 0xae, 0x4b, 0xee, + 0x91, 0x61, 0x2f, 0xfd, 0xc9, 0x07, 0x50, 0xec, 0xb5, 0x3c, 0x13, 0x8c, 0x74, 0xd5, 0x30, 0x70, 0x09, 0x31, 0x7b, + 0xe3, 0x82, 0x48, 0x22, 0x95, 0xe4, 0x26, 0x50, 0xe0, 0x3d, 0xe9, 0x5b, 0xd3, 0xab, 0xb5, 0x97, 0x1f, 0xcc, 0x02, + 0xa3, 0x46, 0x35, 0x81, 0xb4, 0x85, 0x83, 0x53, 0x79, 0xe7, 0x0a, 0x4d, 0xf7, 0xc8, 0x00, 0xc9, 0xef, 0x25, 0xe4, + 0x33, 0x75, 0xc4, 0x85, 0x76, 0x98, 0xc0, 0xa9, 0x75, 0xe9, 0x5c, 0xe5, 0x4f, 0x67, 0xf8, 0xcb, 0xbd, 0xca, 0x9f, + 0x8e, 0xf0, 0x97, 0x77, 0x85, 0x99, 0xeb, 0x1a, 0x2e, 0xf2, 0xca, 0x98, 0xf5, 0xd3, 0xd2, 0x7a, 0x22, 0xfb, 0xb3, + 0x07, 0x2c, 0x1b, 0x3e, 0xc1, 0x8f, 0x9f, 0xac, 0x53, 0xf0, 0xb8, 0x54, 0xc7, 0x10, 0xd9, 0x89, 0x91, 0x37, 0x96, + 0xcf, 0x36, 0x94, 0x8f, 0x8c, 0xff, 0xf2, 0xc1, 0x8f, 0xab, 0x24, 0x2e, 0xce, 0x94, 0xb2, 0x18, 0xe2, 0x7a, 0x14, + 0x44, 0x7e, 0x72, 0x7f, 0x4d, 0xd7, 0x8b, 0x96, 0xe0, 0xdd, 0xa5, 0x78, 0x85, 0xd8, 0xcb, 0xb2, 0xba, 0x2b, 0x53, + 0x04, 0xbc, 0xf7, 0xfc, 0xa0, 0x1f, 0xfc, 0x3d, 0x51, 0xd8, 0xb6, 0xd2, 0x05, 0x94, 0x4f, 0x48, 0xe9, 0x43, 0xd7, + 0x4f, 0xd6, 0x2d, 0x56, 0x07, 0x53, 0x19, 0x6d, 0x85, 0x2f, 0x84, 0xe9, 0xc1, 0xcb, 0xec, 0x62, 0x12, 0xf4, 0x50, + 0x9f, 0x35, 0x8a, 0xef, 0xac, 0x27, 0xeb, 0xec, 0x4c, 0x5f, 0xf8, 0xc9, 0x27, 0x36, 0xb1, 0xc6, 0x41, 0x32, 0x0e, + 0x99, 0xde, 0xd3, 0x47, 0xa1, 0x1f, 0x7d, 0xe2, 0x8f, 0x56, 0xbc, 0xca, 0x50, 0x43, 0xbd, 0xf3, 0xee, 0x2b, 0x70, + 0x42, 0x22, 0x3b, 0x64, 0x56, 0x1b, 0xb0, 0xa0, 0xbd, 0x94, 0x02, 0xaf, 0x82, 0x51, 0x2c, 0x6a, 0x99, 0x60, 0x60, + 0x09, 0x4a, 0x73, 0xf0, 0x58, 0x35, 0x75, 0x9c, 0x2f, 0xdd, 0x54, 0x87, 0x4a, 0xc2, 0x4a, 0x99, 0x72, 0xf1, 0x1a, + 0x21, 0xfc, 0xf1, 0xcf, 0x51, 0x32, 0xec, 0xfd, 0x3f, 0x27, 0xa1, 0x7c, 0xd9, 0x08, 0xa1, 0xd4, 0x22, 0x4f, 0x89, + 0x07, 0x7c, 0x9c, 0x33, 0x98, 0x9b, 0x3f, 0xad, 0x36, 0xf6, 0xd3, 0x74, 0xb5, 0x60, 0x13, 0xd2, 0x0c, 0x9e, 0x15, + 0x9d, 0x2a, 0xdf, 0x2c, 0xd4, 0x8e, 0xfd, 0xb6, 0xf2, 0x8e, 0x0f, 0x5f, 0x82, 0xc5, 0x02, 0x30, 0x94, 0xf1, 0x74, + 0xaa, 0x17, 0x77, 0xfc, 0x1d, 0xcd, 0xdc, 0xc3, 0xdf, 0x56, 0x6f, 0x5e, 0x3b, 0x6f, 0x64, 0xe3, 0x08, 0x18, 0x63, + 0xa1, 0x7e, 0xe5, 0x7c, 0xb1, 0xd2, 0x5f, 0x31, 0xa2, 0xa9, 0x1f, 0x6d, 0x1e, 0xce, 0x65, 0x69, 0x89, 0x2f, 0x19, + 0x9b, 0x00, 0xc3, 0x6d, 0xd6, 0x4a, 0xaf, 0x43, 0x76, 0xc3, 0xa4, 0x6a, 0xb7, 0xfe, 0xb1, 0x86, 0x16, 0x18, 0x7b, + 0x8e, 0xab, 0x8c, 0x39, 0x57, 0xa7, 0x0c, 0x69, 0x88, 0x63, 0xe0, 0x23, 0x57, 0xb7, 0x58, 0x65, 0x4b, 0x0d, 0x4d, + 0x5d, 0xe9, 0xc0, 0xc6, 0x9e, 0x9d, 0x6d, 0x28, 0xef, 0x61, 0xe2, 0xe9, 0xe6, 0xbe, 0x99, 0xae, 0xd1, 0x83, 0x58, + 0xdd, 0x1c, 0x4f, 0x21, 0xec, 0xbc, 0x56, 0x21, 0x0e, 0xd9, 0x84, 0xb1, 0x26, 0x21, 0x99, 0x4e, 0xd2, 0x17, 0x61, + 0xed, 0x88, 0x66, 0xbf, 0x42, 0x0e, 0xd5, 0x38, 0x37, 0x5a, 0x79, 0xe4, 0x23, 0x4c, 0xe8, 0x1a, 0xb1, 0x34, 0xdd, + 0x88, 0x30, 0x39, 0xe9, 0xa6, 0x5e, 0xd4, 0x2e, 0xe3, 0xa3, 0x28, 0x37, 0x1d, 0x13, 0x58, 0x02, 0x1c, 0x60, 0xf5, + 0x5b, 0x78, 0xbc, 0x5c, 0x2f, 0xb8, 0xbd, 0x4a, 0x32, 0x1b, 0xe9, 0xdc, 0x96, 0x60, 0xd3, 0xfb, 0x5b, 0x9d, 0x77, + 0xaa, 0x74, 0x4c, 0x37, 0x76, 0xad, 0x55, 0x22, 0xbd, 0x35, 0x71, 0x11, 0x02, 0x10, 0x7d, 0xaa, 0xd0, 0x57, 0x36, + 0x9d, 0xb2, 0x71, 0x96, 0x1a, 0x42, 0x78, 0x24, 0xa3, 0xc7, 0x82, 0xd7, 0xd0, 0xa3, 0x81, 0xfe, 0x13, 0xf8, 0xd0, + 0x8b, 0x20, 0x4b, 0xbc, 0x43, 0xe2, 0xce, 0xd4, 0x8c, 0x26, 0x82, 0x58, 0x46, 0x11, 0xff, 0x0a, 0x24, 0x07, 0x6f, + 0x28, 0xc7, 0xae, 0xf1, 0xf3, 0xa7, 0x58, 0x17, 0xb1, 0xb4, 0x6a, 0xd9, 0x4e, 0x8a, 0xb6, 0x6d, 0xdf, 0xb5, 0xfb, + 0xa6, 0xe3, 0x3a, 0xb9, 0x6e, 0x82, 0xef, 0xd6, 0xa7, 0x7d, 0x37, 0x3d, 0xb6, 0x6a, 0x43, 0xab, 0x55, 0xf4, 0x90, + 0x76, 0x9e, 0xfb, 0xc2, 0xd5, 0x4d, 0x32, 0x99, 0x53, 0x68, 0xdb, 0x38, 0xbe, 0x61, 0xc9, 0x17, 0x0f, 0xa5, 0x0c, + 0x7c, 0xbf, 0xfe, 0x1c, 0xb9, 0x0e, 0x10, 0xe1, 0x2c, 0x5e, 0x3e, 0x60, 0x08, 0x6d, 0xdd, 0xd4, 0xc7, 0x61, 0x9c, + 0x32, 0x75, 0x0c, 0x24, 0x04, 0xf9, 0xc2, 0x41, 0xfc, 0xfc, 0xfe, 0xf5, 0x87, 0x0f, 0xba, 0x89, 0x99, 0x40, 0x53, + 0x15, 0x3a, 0x5f, 0x50, 0x3b, 0xa8, 0x7f, 0xe3, 0xba, 0xa3, 0x13, 0x86, 0x2e, 0xb5, 0xe5, 0x35, 0x47, 0x65, 0xb5, + 0x25, 0xc7, 0x4f, 0x1e, 0xfe, 0x65, 0xba, 0x89, 0xee, 0x35, 0xae, 0x06, 0xda, 0xb0, 0xfd, 0x78, 0x2b, 0x95, 0x2c, + 0x82, 0xe8, 0xba, 0xa1, 0xd4, 0xbf, 0x6b, 0x28, 0x85, 0xab, 0x5c, 0x8d, 0x56, 0xad, 0xe2, 0x85, 0xc2, 0x1a, 0x40, + 0x22, 0xe7, 0x5d, 0xe8, 0x52, 0xee, 0x53, 0x5f, 0xd0, 0x69, 0x1e, 0xc9, 0xbd, 0xda, 0xeb, 0x86, 0x62, 0x7e, 0x09, + 0x92, 0xb8, 0x1d, 0x87, 0x60, 0xf0, 0xc7, 0x54, 0xad, 0x5c, 0x99, 0x6d, 0x94, 0xe6, 0xba, 0x0a, 0x10, 0x62, 0x6f, + 0xaf, 0x33, 0xb6, 0x58, 0xb2, 0xc4, 0xcf, 0x56, 0x09, 0xbb, 0x0e, 0xe3, 0xdb, 0x47, 0x85, 0x39, 0xfd, 0x8e, 0xca, + 0xf3, 0x60, 0x36, 0x97, 0xb5, 0xcf, 0x5a, 0x6c, 0x20, 0x27, 0x70, 0xeb, 0x07, 0xf2, 0xff, 0xfc, 0xdb, 0xb6, 0xff, + 0xf3, 0xef, 0x9d, 0x55, 0x01, 0x7c, 0x3e, 0x34, 0xb3, 0xc1, 0x1e, 0xeb, 0xa2, 0xf9, 0x4b, 0x65, 0x9c, 0x37, 0xd7, + 0xa9, 0x4d, 0x02, 0xbc, 0xaf, 0x4d, 0x41, 0xad, 0xb0, 0xbc, 0x6e, 0x1e, 0xd4, 0x31, 0x18, 0xd7, 0xce, 0x9e, 0x41, + 0xa5, 0x2f, 0xea, 0xda, 0xd0, 0xe8, 0xed, 0x35, 0x23, 0x7f, 0x1c, 0xc3, 0xbb, 0xc6, 0xf0, 0x85, 0xdd, 0xe7, 0x72, + 0xc9, 0x97, 0xc3, 0xa1, 0xcc, 0x2d, 0xa7, 0x36, 0x05, 0x13, 0xff, 0xb3, 0x5a, 0x09, 0x3f, 0x3c, 0x7b, 0x8e, 0x41, + 0xbe, 0xf7, 0x83, 0x97, 0x43, 0x34, 0x46, 0x3b, 0x19, 0x25, 0x05, 0xb3, 0xb2, 0x91, 0xb4, 0x91, 0x31, 0x79, 0x0d, + 0x68, 0x8d, 0xae, 0x41, 0x29, 0x26, 0x1c, 0xcb, 0x87, 0x86, 0xf9, 0x72, 0xc8, 0x05, 0x4b, 0xdc, 0xfe, 0xb5, 0x57, + 0x5d, 0xda, 0x5c, 0x2c, 0x5b, 0x42, 0xba, 0xa9, 0x91, 0xfe, 0x07, 0x2b, 0xb3, 0x42, 0x8e, 0x87, 0x02, 0x7e, 0x90, + 0x28, 0x0c, 0x73, 0xcc, 0x77, 0xf2, 0x6e, 0x93, 0x8d, 0xd8, 0xcf, 0xbb, 0x6d, 0xc4, 0x2e, 0xf6, 0xb2, 0x11, 0xfb, + 0xf9, 0xab, 0xdb, 0x88, 0xbd, 0x53, 0x6d, 0xc4, 0x60, 0x12, 0x5f, 0xb3, 0xbd, 0x0c, 0xb7, 0x84, 0xd5, 0x46, 0x7c, + 0x9b, 0x0e, 0x5c, 0xce, 0xd2, 0xa6, 0xe3, 0x39, 0x03, 0x19, 0x01, 0x9f, 0x95, 0x30, 0x9e, 0x81, 0x11, 0xd7, 0x9f, + 0x6f, 0x6e, 0x15, 0xc6, 0x33, 0xd5, 0xd8, 0x2a, 0xe2, 0x11, 0x5f, 0x8b, 0x28, 0x4e, 0x64, 0xe0, 0xe4, 0x98, 0x22, + 0xe6, 0x93, 0x75, 0x68, 0x28, 0x59, 0xad, 0xa5, 0xf5, 0x9a, 0x27, 0x4c, 0xa0, 0x7a, 0x68, 0x3d, 0x25, 0x1b, 0x7a, + 0xcf, 0x45, 0x6c, 0x0b, 0x15, 0x82, 0xb4, 0x12, 0xa6, 0x38, 0x11, 0x6b, 0xfd, 0xb7, 0x3b, 0xf7, 0xfb, 0x4b, 0xb7, + 0xdf, 0x76, 0xc1, 0x39, 0x1b, 0x6e, 0x98, 0x58, 0xe0, 0xf4, 0xdb, 0x6d, 0x28, 0xb8, 0x55, 0x0a, 0x3c, 0x28, 0x08, + 0x94, 0x82, 0x0e, 0x14, 0x8c, 0x95, 0x82, 0x23, 0x28, 0x98, 0x28, 0x05, 0xc7, 0x50, 0x70, 0xa3, 0xe7, 0x97, 0x91, + 0xec, 0xee, 0xb1, 0x71, 0x65, 0xd2, 0xa5, 0x42, 0x94, 0x1d, 0x9b, 0x2e, 0x58, 0x4d, 0xf9, 0xb3, 0x5e, 0x6c, 0x92, + 0x74, 0xb1, 0x97, 0x98, 0xb7, 0x73, 0x46, 0x81, 0xa2, 0x5f, 0xe1, 0x99, 0x63, 0x67, 0x31, 0xd8, 0x4d, 0x8b, 0x00, + 0x0c, 0x02, 0x0f, 0x9a, 0x6e, 0x80, 0xc0, 0xa8, 0x2f, 0x67, 0x4e, 0x04, 0xb1, 0x50, 0xe6, 0xb2, 0x78, 0x47, 0x9f, + 0xb3, 0xe4, 0x12, 0x28, 0x2c, 0x4e, 0x5a, 0xaa, 0x54, 0xf2, 0x6b, 0xd8, 0x1d, 0xbc, 0x62, 0xa3, 0xd5, 0x4c, 0x3b, + 0x8f, 0x67, 0x3b, 0x4d, 0x08, 0xd4, 0x57, 0xd0, 0x4b, 0x9d, 0xd4, 0x2f, 0x96, 0x58, 0x96, 0xfc, 0x5b, 0xf4, 0x98, + 0x97, 0xeb, 0x67, 0xd0, 0x37, 0x2d, 0x23, 0x03, 0x16, 0xf8, 0x0e, 0xe0, 0x48, 0xd1, 0xe1, 0x9f, 0x03, 0x9e, 0x95, + 0xe7, 0x0b, 0x5f, 0xe9, 0xcf, 0xe9, 0x8f, 0x2c, 0x4d, 0xfd, 0x99, 0xa8, 0x5f, 0xef, 0x27, 0x18, 0xed, 0xc8, 0xfb, + 0x17, 0x22, 0x10, 0x24, 0x79, 0x41, 0xcd, 0x36, 0x23, 0x89, 0x6f, 0x35, 0xb0, 0xfe, 0x81, 0x05, 0x55, 0xd8, 0x29, + 0x04, 0x36, 0x4c, 0x61, 0xd9, 0xa2, 0x00, 0x36, 0xff, 0x0d, 0x0b, 0xab, 0x85, 0x99, 0x3f, 0xab, 0x16, 0xd1, 0x3a, + 0xc8, 0xd5, 0xbe, 0x49, 0x85, 0x7e, 0xa9, 0xf0, 0x4b, 0x34, 0xd4, 0x61, 0x3c, 0xfb, 0x53, 0xd5, 0xd3, 0x5b, 0xcc, + 0x0a, 0x3e, 0x44, 0x66, 0x90, 0x0d, 0x6d, 0xc4, 0xb1, 0x66, 0x03, 0x0a, 0x7b, 0x51, 0x36, 0xb7, 0xd0, 0xb5, 0xac, + 0xe5, 0x45, 0x86, 0x69, 0xe3, 0xdc, 0xae, 0xab, 0x0e, 0xb5, 0xbd, 0x64, 0x36, 0xf2, 0x5b, 0xae, 0x77, 0x6c, 0x8a, + 0x3f, 0xb6, 0xd3, 0x31, 0x72, 0x84, 0xa0, 0x4d, 0x82, 0x9b, 0xf5, 0x34, 0x8e, 0x32, 0x6b, 0xea, 0x2f, 0x82, 0xf0, + 0xbe, 0xb7, 0x88, 0xa3, 0x38, 0x5d, 0xfa, 0x63, 0xd6, 0x2f, 0x2e, 0xd4, 0x7d, 0x0c, 0xd5, 0xc0, 0xbd, 0x05, 0x5d, + 0xdb, 0x4b, 0xd8, 0x82, 0x5a, 0xcb, 0x48, 0x0c, 0xd3, 0x90, 0xdd, 0xe5, 0xfc, 0xf3, 0xa5, 0xca, 0x54, 0x15, 0x97, + 0x1c, 0xb5, 0x00, 0x8e, 0x94, 0x87, 0x79, 0x80, 0xe0, 0x46, 0xfd, 0xa5, 0x3f, 0xc1, 0xc8, 0x84, 0xb6, 0xd7, 0x49, + 0xd8, 0x42, 0xb3, 0x3b, 0x1b, 0x81, 0x27, 0xf1, 0xed, 0x29, 0xf4, 0x16, 0x1b, 0x5b, 0x29, 0x0b, 0xa7, 0xf8, 0xc6, + 0x42, 0xcf, 0x12, 0x01, 0xc7, 0xc2, 0x8b, 0x38, 0x40, 0x63, 0x8b, 0x3e, 0xbc, 0xee, 0x79, 0x9a, 0xd3, 0x5f, 0x04, + 0x91, 0x45, 0xc3, 0x39, 0x76, 0x96, 0x0a, 0x2c, 0x15, 0x7f, 0xc6, 0x1a, 0xab, 0xbb, 0x9a, 0xd3, 0x87, 0xcb, 0xda, + 0x34, 0x8c, 0x6f, 0x7b, 0xf3, 0x60, 0x32, 0x61, 0x51, 0x1f, 0xfb, 0x2c, 0x0b, 0x59, 0x18, 0x06, 0xcb, 0x34, 0x48, + 0xfb, 0x0b, 0xff, 0x8e, 0x43, 0x3d, 0xdc, 0x04, 0xb5, 0xcd, 0xa1, 0xb6, 0xf7, 0x86, 0xaa, 0x80, 0x01, 0x2f, 0x16, + 0x82, 0xc3, 0xbb, 0xd6, 0xd1, 0x9c, 0xca, 0x38, 0xf7, 0x86, 0xba, 0x4c, 0xd8, 0x7a, 0xe1, 0x27, 0xb3, 0x20, 0xea, + 0x39, 0xb9, 0x7d, 0xb3, 0xa6, 0x85, 0xf1, 0xb8, 0xdb, 0xed, 0xe6, 0xf6, 0x44, 0x3c, 0x39, 0x93, 0x49, 0x6e, 0x8f, + 0xc5, 0xd3, 0x74, 0xea, 0x38, 0xd3, 0x69, 0x6e, 0x07, 0xa2, 0xa0, 0xed, 0x8d, 0x27, 0x6d, 0x2f, 0xb7, 0x6f, 0x95, + 0x1a, 0xb9, 0xcd, 0xf8, 0x53, 0xc2, 0x26, 0x7d, 0x5c, 0x48, 0x64, 0x56, 0xda, 0x3b, 0x76, 0x9c, 0x1c, 0x29, 0xc0, + 0x65, 0x89, 0x36, 0xa1, 0xac, 0xe7, 0x6a, 0xbd, 0x77, 0x4d, 0xad, 0xf8, 0xdc, 0x78, 0xdc, 0x58, 0x6f, 0xe2, 0x27, + 0x9f, 0xae, 0x34, 0x65, 0x14, 0xbe, 0x4f, 0xd5, 0xd6, 0x02, 0x0d, 0xd6, 0x5d, 0x0f, 0x42, 0x76, 0xf5, 0x47, 0x71, + 0x02, 0x7b, 0x36, 0xf1, 0x27, 0xc1, 0x2a, 0xed, 0xb9, 0xde, 0xf2, 0x4e, 0x14, 0xf1, 0xb5, 0x5e, 0x14, 0xe0, 0xde, + 0xeb, 0xa5, 0x71, 0x18, 0x4c, 0x44, 0xd1, 0xa6, 0xbd, 0xe4, 0x7a, 0x46, 0x1f, 0x1d, 0xd6, 0x03, 0x0c, 0xbb, 0xe0, + 0x87, 0xa1, 0x66, 0xb7, 0x53, 0x8d, 0xf9, 0x29, 0xca, 0x97, 0x35, 0x27, 0x25, 0xbc, 0xa0, 0x73, 0xba, 0x7b, 0xb8, + 0xbc, 0x93, 0x6b, 0xde, 0x3d, 0x5a, 0xde, 0xe5, 0x7f, 0x5d, 0xb0, 0x49, 0xe0, 0x6b, 0xad, 0x62, 0x35, 0xb9, 0x0e, + 0xc8, 0xa0, 0x8d, 0xf5, 0x86, 0x65, 0x2a, 0xb6, 0x05, 0x84, 0x36, 0x7c, 0x14, 0x2c, 0x96, 0x71, 0x92, 0xf9, 0x51, + 0x96, 0xe7, 0xc3, 0xab, 0x3c, 0xef, 0x5f, 0x04, 0xad, 0xcb, 0x7f, 0xb4, 0xe8, 0x9c, 0x26, 0x9d, 0x4d, 0x6e, 0x5c, + 0x99, 0xaf, 0x99, 0x6a, 0x33, 0x02, 0xc7, 0x18, 0xda, 0x8b, 0xa8, 0x95, 0xe9, 0x94, 0xac, 0x57, 0x26, 0x24, 0xcb, + 0xea, 0x64, 0x83, 0x52, 0xae, 0x82, 0x27, 0x10, 0x54, 0x78, 0xcd, 0x06, 0x17, 0x8a, 0xfd, 0x09, 0x30, 0x2b, 0x58, + 0x99, 0xfc, 0x0a, 0x9e, 0x6c, 0xe2, 0x19, 0xbf, 0xdb, 0xcd, 0x33, 0xfe, 0x9a, 0xed, 0xc3, 0x33, 0x7e, 0xf7, 0xd5, + 0x79, 0xc6, 0x27, 0x75, 0xbf, 0x82, 0xb7, 0xf1, 0x40, 0x97, 0x1a, 0x06, 0x38, 0x9a, 0x12, 0x8a, 0xd8, 0xf3, 0xf6, + 0x0f, 0xbb, 0x01, 0x08, 0x68, 0x94, 0x83, 0x8e, 0x4e, 0x6e, 0x90, 0xc7, 0xbe, 0x8b, 0x06, 0x7f, 0x4f, 0xd4, 0xe7, + 0xe9, 0x74, 0xf0, 0x2a, 0x56, 0x0a, 0xe4, 0x13, 0x37, 0xbe, 0x28, 0x45, 0x57, 0xa0, 0x37, 0xc2, 0x0a, 0x13, 0xf3, + 0x4f, 0x80, 0x73, 0x36, 0x59, 0x1d, 0x4f, 0xa4, 0xf5, 0x59, 0xbf, 0xdc, 0x85, 0x96, 0x34, 0xf9, 0x14, 0x2e, 0x38, + 0x35, 0x51, 0xe2, 0x8c, 0x65, 0xdc, 0x67, 0xf6, 0xfb, 0xfb, 0xb7, 0x93, 0xd6, 0xdb, 0xd8, 0xc8, 0x83, 0xf4, 0x5d, + 0xd5, 0x01, 0x86, 0xeb, 0x7e, 0x06, 0xea, 0x70, 0x72, 0x6e, 0x41, 0xa6, 0x26, 0x98, 0x86, 0xd7, 0xd4, 0xfc, 0xac, + 0x34, 0xd2, 0x9e, 0xda, 0x90, 0x27, 0xba, 0xaa, 0x1d, 0xc6, 0xdc, 0xfb, 0x60, 0xcd, 0x39, 0x40, 0xcc, 0xdd, 0x85, + 0x7e, 0xc3, 0x13, 0x6a, 0x1e, 0x4c, 0xf2, 0xdc, 0xe8, 0x0b, 0x44, 0x28, 0x07, 0x2d, 0xdb, 0xc5, 0xc4, 0xa5, 0xb7, + 0xd2, 0xa6, 0x81, 0x6b, 0x08, 0x49, 0xfd, 0xf7, 0x16, 0x14, 0xea, 0x5c, 0x59, 0xc8, 0x71, 0xa6, 0x6b, 0x84, 0x3e, + 0x32, 0xb4, 0x50, 0x06, 0x04, 0x1a, 0x60, 0x89, 0x7f, 0xf1, 0x4a, 0x14, 0xd4, 0x6d, 0x38, 0x09, 0x39, 0x68, 0x11, + 0x00, 0x5e, 0xfe, 0x42, 0xae, 0x4d, 0x64, 0x87, 0xd7, 0xc1, 0x87, 0x5c, 0x97, 0xbc, 0x1f, 0x2e, 0xbf, 0xd3, 0x93, + 0x03, 0x68, 0x70, 0x5a, 0x31, 0x1c, 0xd8, 0x61, 0xa1, 0x08, 0xac, 0x44, 0x7a, 0x6b, 0xda, 0xe9, 0xad, 0xf6, 0x6c, + 0x2d, 0x22, 0x64, 0x64, 0xfe, 0xd2, 0x82, 0x2b, 0x3e, 0xd2, 0x5e, 0x4e, 0xf1, 0x94, 0x60, 0x1c, 0xfd, 0x55, 0x0a, + 0xb4, 0x11, 0x2f, 0xaa, 0x48, 0x7f, 0xfa, 0xe3, 0x55, 0x92, 0xc6, 0x49, 0x6f, 0x19, 0x07, 0x51, 0xc6, 0x92, 0x1c, + 0x51, 0x75, 0x89, 0xf8, 0x11, 0xe8, 0xb9, 0x5a, 0xc7, 0x4b, 0x7f, 0x1c, 0x64, 0xf7, 0x3d, 0x87, 0xb3, 0x14, 0x4e, + 0x9f, 0x73, 0x07, 0x4e, 0x63, 0xfd, 0x1e, 0xc7, 0xe6, 0x73, 0x64, 0xfc, 0x92, 0x3a, 0x3b, 0xa3, 0x2e, 0xf3, 0xbe, + 0xf2, 0x96, 0x62, 0x84, 0x00, 0xfb, 0xe1, 0x27, 0xd6, 0x0c, 0xa8, 0x3c, 0x4c, 0xb5, 0x33, 0x61, 0x33, 0x13, 0xa9, + 0x36, 0xc8, 0xe5, 0xc5, 0x1f, 0xbb, 0x63, 0x68, 0x4e, 0x73, 0x31, 0x70, 0x3c, 0xc6, 0x3e, 0x3d, 0xeb, 0xf9, 0x90, + 0x51, 0xcb, 0xdc, 0xa7, 0xe6, 0x88, 0x4d, 0xe3, 0x84, 0x51, 0x3c, 0x59, 0xb7, 0xbb, 0xbc, 0xdb, 0x1f, 0xfc, 0xf6, + 0xe1, 0x37, 0xc3, 0x89, 0xe2, 0xac, 0x25, 0x80, 0x19, 0x3b, 0xa0, 0xd5, 0xcf, 0x33, 0x60, 0x0d, 0x09, 0xf3, 0x63, + 0x0a, 0xdd, 0xd5, 0xd3, 0xf5, 0x7e, 0x63, 0xd8, 0xae, 0x65, 0xcc, 0xcf, 0xbc, 0x84, 0x85, 0x7e, 0x16, 0xdc, 0x08, + 0x9e, 0xb1, 0x7d, 0xb4, 0xbc, 0x13, 0x73, 0x8c, 0x07, 0xde, 0x03, 0x26, 0xa9, 0xd2, 0x15, 0x31, 0x49, 0xd5, 0x62, + 0x9c, 0xa4, 0x7e, 0x6d, 0x34, 0x22, 0x92, 0x45, 0xe5, 0xa4, 0xef, 0x2c, 0xef, 0xd4, 0x23, 0xba, 0x68, 0x26, 0x4f, + 0xea, 0x6a, 0x08, 0xb2, 0x45, 0x30, 0x99, 0x84, 0x2c, 0x2f, 0x4d, 0x74, 0x79, 0x2e, 0x15, 0xe4, 0x48, 0x3c, 0xf8, + 0xa3, 0x34, 0x0e, 0x57, 0x19, 0x6b, 0x46, 0x17, 0x21, 0xc7, 0x73, 0x0a, 0xe4, 0xe0, 0xef, 0x72, 0x5f, 0x3b, 0xc0, + 0x6e, 0xc3, 0x32, 0x71, 0xfa, 0x10, 0x71, 0xd8, 0x6a, 0x97, 0xbb, 0x0e, 0xaf, 0x64, 0xa7, 0xcd, 0x86, 0x81, 0x98, + 0x70, 0x2c, 0x11, 0xf5, 0xd6, 0x6c, 0x97, 0x97, 0xc9, 0xa8, 0xab, 0xb2, 0x28, 0x2f, 0x0f, 0xe6, 0xcf, 0xd9, 0x63, + 0x2f, 0x9a, 0xf7, 0xd8, 0x0b, 0xb1, 0xc7, 0xb6, 0xaf, 0xcc, 0xc7, 0x53, 0x17, 0xfe, 0xeb, 0x17, 0x03, 0xea, 0x39, + 0x5a, 0x7b, 0x79, 0xa7, 0xb9, 0xcb, 0x3b, 0xcd, 0xf2, 0x96, 0x77, 0x1a, 0x82, 0x46, 0x7b, 0x10, 0xd3, 0xf6, 0x0c, + 0xd3, 0xd1, 0xa0, 0x10, 0xfe, 0x38, 0xa5, 0x57, 0xee, 0x21, 0xbc, 0x83, 0x56, 0x9d, 0xfa, 0x3b, 0x6f, 0xfb, 0x56, + 0xa7, 0xbd, 0x24, 0x88, 0xb6, 0x61, 0x67, 0xfe, 0x68, 0xc4, 0x26, 0xbd, 0x69, 0x3c, 0x5e, 0xa5, 0xff, 0xe2, 0xfd, + 0xe7, 0x48, 0xdc, 0x4a, 0x08, 0x2a, 0x70, 0x44, 0x53, 0x50, 0x94, 0xdc, 0x30, 0x01, 0x61, 0x2d, 0xe7, 0xa9, 0x47, + 0xe1, 0x91, 0x3d, 0xfb, 0xb0, 0x61, 0x91, 0x37, 0x23, 0xfa, 0x4f, 0x9b, 0xa5, 0xcd, 0x24, 0xe6, 0x0b, 0xd0, 0xb2, + 0x15, 0x1d, 0x0f, 0xc7, 0x06, 0x9f, 0x4d, 0xa7, 0xdb, 0xdc, 0xdd, 0x4b, 0xf1, 0xa5, 0x2b, 0x71, 0xa8, 0xf0, 0x73, + 0x8b, 0x3b, 0xa6, 0x6c, 0x87, 0xba, 0x69, 0x8d, 0xd4, 0xa0, 0x6e, 0x39, 0x10, 0x8a, 0xba, 0x7b, 0x52, 0xf9, 0xc7, + 0x2f, 0x0e, 0xe1, 0x3f, 0xe2, 0xea, 0x7f, 0xcd, 0x9a, 0x18, 0xf5, 0xb7, 0x65, 0x4b, 0x70, 0x62, 0x95, 0x90, 0x11, + 0xdf, 0xbf, 0xfe, 0x74, 0xfa, 0xb0, 0x06, 0x7b, 0xd7, 0x26, 0x53, 0xaa, 0x6a, 0xed, 0xef, 0xe3, 0x18, 0x52, 0x77, + 0xd6, 0xab, 0x0b, 0xf4, 0x90, 0xb1, 0x7b, 0x36, 0x80, 0x46, 0xe2, 0x1e, 0x41, 0x5a, 0x7c, 0x1d, 0xdb, 0xd0, 0x55, + 0xe2, 0xf5, 0xa6, 0xab, 0xc4, 0xab, 0xdd, 0x57, 0x89, 0x1f, 0xf6, 0xba, 0x4a, 0xbc, 0xfa, 0xea, 0x57, 0x89, 0xd7, + 0xf5, 0xab, 0xc4, 0x45, 0x2c, 0xec, 0x67, 0xcd, 0xb7, 0x2b, 0xfe, 0xf3, 0x23, 0x29, 0xe5, 0xce, 0xe3, 0x41, 0xc7, + 0xa1, 0x90, 0xc7, 0x17, 0x7f, 0xf8, 0x62, 0x81, 0x0b, 0xf1, 0x3d, 0x9a, 0x93, 0x15, 0x57, 0x0b, 0x4e, 0xd9, 0xf1, + 0x3b, 0x4a, 0x71, 0x18, 0x47, 0xb3, 0x9f, 0x41, 0x29, 0x0b, 0xe2, 0xc0, 0x44, 0x79, 0x11, 0xa4, 0x3f, 0xc7, 0xcb, + 0xd5, 0xf2, 0x2d, 0xc0, 0xfa, 0x18, 0xa4, 0xc1, 0x28, 0x64, 0xd2, 0x13, 0x99, 0xcc, 0xdf, 0xb8, 0x4c, 0x1c, 0x2c, + 0x4e, 0xc5, 0x4f, 0xff, 0x4e, 0xfc, 0x44, 0x9b, 0x54, 0xfe, 0x9b, 0xec, 0xea, 0xf4, 0xe6, 0x8b, 0x88, 0x50, 0x02, + 0x2a, 0x9d, 0x7e, 0xf8, 0x65, 0xe4, 0x22, 0x36, 0x1a, 0x46, 0x29, 0xec, 0x1d, 0x36, 0xc2, 0x61, 0xb5, 0x4b, 0xcd, + 0xca, 0x30, 0x65, 0x08, 0xae, 0xba, 0x18, 0x7e, 0x11, 0xaf, 0x52, 0x36, 0x89, 0x6f, 0x23, 0xdd, 0x8c, 0xa4, 0x93, + 0x01, 0x68, 0x38, 0x65, 0x1b, 0x4c, 0x1e, 0xf9, 0x01, 0x19, 0xe5, 0x38, 0x69, 0xe9, 0x90, 0xbb, 0x74, 0xb5, 0xb4, + 0x48, 0xd5, 0x6c, 0xe1, 0x10, 0x75, 0x99, 0xe5, 0xe8, 0x51, 0xab, 0x15, 0x0f, 0x1e, 0xd6, 0x52, 0x98, 0x6a, 0xc4, + 0x36, 0x97, 0x0a, 0xa7, 0xad, 0x48, 0x08, 0x17, 0x45, 0x1c, 0x8c, 0x86, 0x89, 0xe3, 0x6f, 0xc8, 0x75, 0xb5, 0x78, + 0x0b, 0x51, 0x44, 0xf2, 0x15, 0x9f, 0x0f, 0x1e, 0x15, 0x82, 0x1e, 0x5f, 0x2a, 0x68, 0x7c, 0x77, 0xc3, 0x92, 0xd0, + 0xbf, 0x6f, 0x19, 0x79, 0x1c, 0xfd, 0x08, 0x08, 0x78, 0x15, 0xdf, 0x46, 0x6a, 0x05, 0x4c, 0xd6, 0xd2, 0xb0, 0x96, + 0x1a, 0xe3, 0x97, 0x80, 0xe3, 0x8a, 0xd2, 0x03, 0x48, 0x93, 0x3b, 0x63, 0x7f, 0x37, 0xe9, 0xdf, 0x7f, 0x18, 0xb9, + 0x79, 0x1e, 0xcb, 0x0f, 0xfd, 0xb2, 0xdc, 0xe3, 0x33, 0x4f, 0x9f, 0x3e, 0xda, 0x3c, 0xec, 0x72, 0x7a, 0xf6, 0x86, + 0xd6, 0xc6, 0xc6, 0x5d, 0x00, 0xbd, 0xb8, 0x88, 0x57, 0xe3, 0x39, 0x1a, 0xba, 0x7e, 0xbd, 0xf1, 0x66, 0x00, 0x13, + 0xb3, 0x94, 0xca, 0xa1, 0x57, 0x8a, 0x0a, 0x2c, 0xe0, 0xf7, 0x5f, 0x43, 0x00, 0xce, 0xff, 0x21, 0x1a, 0xea, 0xab, + 0x86, 0xdf, 0xe2, 0x83, 0x87, 0x2d, 0xde, 0x3e, 0x24, 0xd3, 0xe4, 0xa1, 0x2d, 0x84, 0x72, 0xad, 0x99, 0xc8, 0xe4, + 0x55, 0xa4, 0xa9, 0x61, 0xe4, 0x36, 0x45, 0xc8, 0x13, 0x5f, 0x61, 0x36, 0x5d, 0xd3, 0xb9, 0xa3, 0x81, 0xc9, 0x38, + 0xb5, 0xaa, 0x10, 0x19, 0x6e, 0xf2, 0xc0, 0x90, 0x7c, 0x55, 0xdf, 0x2d, 0x82, 0xc8, 0xc4, 0x28, 0xf0, 0xf5, 0x37, + 0xfe, 0x1d, 0xc4, 0x41, 0x06, 0xe2, 0x56, 0x7d, 0x05, 0x85, 0xa6, 0xea, 0x37, 0x07, 0xa9, 0x9e, 0xf4, 0x46, 0x4c, + 0x08, 0x2d, 0xde, 0xf0, 0x1b, 0x4d, 0xd3, 0x34, 0x79, 0x8d, 0xd0, 0xe4, 0x3d, 0x02, 0xcb, 0xf1, 0x3a, 0x00, 0xda, + 0x92, 0x7c, 0x79, 0x47, 0x25, 0x70, 0x33, 0x40, 0x9d, 0xac, 0x28, 0xe0, 0xa1, 0xfe, 0x3a, 0x8e, 0x28, 0x10, 0x17, + 0x7a, 0x08, 0xd3, 0xe6, 0x27, 0x10, 0x11, 0xb8, 0xa7, 0xe1, 0x85, 0x1d, 0xdf, 0x72, 0x49, 0xb0, 0xe6, 0xd0, 0xe3, + 0xb0, 0xcf, 0x9a, 0x63, 0xc2, 0x45, 0x0a, 0x15, 0x04, 0xad, 0x43, 0x25, 0xc4, 0xb3, 0xc9, 0x1a, 0x68, 0x23, 0xde, + 0x8b, 0xee, 0xb2, 0x05, 0x8b, 0x56, 0x3a, 0xe6, 0x84, 0xc2, 0x18, 0x7d, 0x50, 0xe7, 0x15, 0x31, 0x5b, 0x40, 0x6d, + 0x9a, 0x5b, 0xce, 0xe9, 0x2c, 0x4c, 0x39, 0x49, 0xf5, 0xcd, 0x31, 0x57, 0x6c, 0xa6, 0x9c, 0xb6, 0x55, 0x4f, 0x08, + 0x3e, 0xa5, 0x71, 0xd5, 0x91, 0x8b, 0x2c, 0xa1, 0x01, 0x06, 0x45, 0xc7, 0xe0, 0xe2, 0x22, 0x81, 0xf6, 0x96, 0x5f, + 0x9d, 0x34, 0xa9, 0x91, 0xf1, 0x2b, 0x82, 0xa2, 0xc4, 0xa8, 0x83, 0xe1, 0xfd, 0x84, 0xc0, 0x44, 0x1b, 0xe1, 0x8c, + 0x6b, 0x70, 0x36, 0x0c, 0xfa, 0x13, 0xbb, 0xa7, 0x83, 0x84, 0x50, 0xf5, 0x89, 0xdd, 0x83, 0xed, 0xdf, 0x6b, 0x90, + 0xa6, 0xe8, 0x5b, 0xc8, 0xb5, 0x09, 0xa1, 0xfe, 0xc7, 0x10, 0xac, 0x6a, 0xcb, 0x06, 0x72, 0xf2, 0x2d, 0x54, 0x1c, + 0x51, 0x0c, 0x59, 0x9d, 0xc5, 0x26, 0xe6, 0x26, 0xfe, 0xad, 0x46, 0x1c, 0x5b, 0x0d, 0x5b, 0xc3, 0x78, 0xe6, 0x3a, + 0xce, 0x41, 0xad, 0x3e, 0x08, 0xb2, 0x9b, 0x6a, 0x1b, 0x66, 0x36, 0x70, 0x1d, 0x2b, 0x78, 0x66, 0x7b, 0xfd, 0xda, + 0x19, 0xad, 0xc4, 0x92, 0x1c, 0xa2, 0xf8, 0xeb, 0xf4, 0xc9, 0xba, 0x55, 0xdb, 0x90, 0x46, 0xd5, 0x64, 0x1e, 0xfb, + 0x96, 0x73, 0xf9, 0xd7, 0xb0, 0x7e, 0xf4, 0x53, 0x24, 0x4b, 0xca, 0x6b, 0x32, 0x84, 0x68, 0xc8, 0x2d, 0xd8, 0x46, + 0x7f, 0xd1, 0x9e, 0x6b, 0x2d, 0xda, 0x3e, 0x86, 0x31, 0x94, 0xe9, 0xb2, 0x85, 0x4f, 0x99, 0x0a, 0xa0, 0xf2, 0xc5, + 0xb4, 0x4a, 0xe1, 0x78, 0xdc, 0x55, 0x56, 0x68, 0xf4, 0xb6, 0x72, 0x0b, 0x08, 0x7f, 0xc3, 0xf1, 0x69, 0x8f, 0x20, + 0x2e, 0x01, 0xd4, 0x80, 0xd8, 0xe9, 0x3b, 0x01, 0xae, 0x96, 0x65, 0x70, 0xe5, 0x43, 0x72, 0x7f, 0x60, 0x78, 0xe8, + 0xa0, 0x0e, 0x4d, 0xc2, 0x6b, 0x3e, 0xee, 0x1e, 0x08, 0x92, 0x45, 0x93, 0x32, 0xc0, 0xca, 0xf9, 0xb5, 0x3f, 0xb8, + 0x12, 0x45, 0x81, 0xa4, 0x02, 0x71, 0x03, 0x45, 0xc9, 0xe3, 0x08, 0x17, 0x3f, 0x6d, 0xb7, 0x60, 0x2f, 0x2e, 0x06, + 0x1b, 0x50, 0x44, 0x30, 0xd9, 0x4c, 0x11, 0x8a, 0x43, 0xe4, 0x6a, 0x74, 0x0b, 0x6e, 0x09, 0x46, 0x74, 0xe3, 0x4a, + 0xcc, 0x84, 0x4d, 0x61, 0xd1, 0x26, 0xe0, 0xb1, 0x28, 0xf7, 0x95, 0x5a, 0x07, 0xbb, 0xa5, 0xd6, 0xd9, 0x2e, 0xa9, + 0x35, 0xb9, 0x53, 0xdd, 0x26, 0xfe, 0x52, 0xf1, 0xc8, 0x13, 0xcc, 0xb9, 0xea, 0x98, 0x57, 0x12, 0x75, 0xa3, 0xf7, + 0x95, 0x68, 0x55, 0x83, 0x46, 0x56, 0x82, 0x28, 0xfe, 0x56, 0x2e, 0x28, 0x42, 0xa1, 0xae, 0xca, 0xc6, 0x2f, 0x0a, + 0xd9, 0x38, 0xdd, 0x6a, 0x0a, 0x47, 0x1a, 0xc1, 0xfd, 0x2b, 0x4e, 0x6a, 0xf2, 0x76, 0x50, 0x38, 0xab, 0x15, 0x3d, + 0x55, 0xdc, 0xaf, 0x8a, 0x8b, 0x86, 0xe2, 0xd4, 0x27, 0x6e, 0x19, 0x65, 0xdf, 0xbe, 0x72, 0xd5, 0xc2, 0xfb, 0xaa, + 0x28, 0x07, 0xa9, 0x3b, 0x76, 0x59, 0x16, 0xab, 0xcb, 0xa6, 0xec, 0x7e, 0xa3, 0xbe, 0x56, 0x16, 0x89, 0xf4, 0x93, + 0x21, 0x04, 0x0b, 0x31, 0x7d, 0x45, 0xaf, 0x2d, 0x6d, 0x20, 0xb0, 0x93, 0x0d, 0x6e, 0x7d, 0xbb, 0xa5, 0xf3, 0x94, + 0x2f, 0xa1, 0xd0, 0xc2, 0xab, 0x32, 0x08, 0xc4, 0xef, 0xd5, 0xba, 0xe1, 0x94, 0xc7, 0x43, 0x9e, 0x9f, 0xef, 0x20, + 0x5e, 0xd4, 0x1c, 0x55, 0x91, 0x8f, 0x3b, 0xd3, 0x22, 0xf3, 0x5c, 0xac, 0x5a, 0x07, 0x4a, 0x42, 0x9c, 0x35, 0xf7, + 0x8c, 0x29, 0xcb, 0xe8, 0x79, 0x8d, 0x9e, 0xf8, 0x2e, 0x5f, 0x3a, 0xc9, 0x2a, 0xc2, 0xd8, 0xf6, 0x56, 0x96, 0xf8, + 0xe3, 0x4f, 0x4a, 0x97, 0x85, 0x9c, 0x13, 0x64, 0xc0, 0x65, 0x4d, 0x41, 0xdf, 0xc7, 0x50, 0x90, 0xac, 0x67, 0x7b, + 0xa9, 0x22, 0x7d, 0xe9, 0x3d, 0x76, 0xda, 0xfe, 0x8b, 0xe9, 0x61, 0x45, 0x28, 0xea, 0x75, 0xca, 0x22, 0xf3, 0x0d, + 0xfd, 0xc8, 0xe6, 0xab, 0xc5, 0x68, 0xad, 0xca, 0x56, 0x15, 0x91, 0x6b, 0x5d, 0xcc, 0xaa, 0x7e, 0x76, 0x3a, 0x9d, + 0x96, 0x05, 0x8d, 0x8e, 0x76, 0x88, 0xc2, 0xc2, 0xc7, 0x8e, 0xe3, 0x54, 0xfb, 0xbe, 0x1d, 0xed, 0x16, 0xca, 0x6d, + 0xbb, 0x8d, 0x3d, 0x46, 0xdc, 0xee, 0xc2, 0x5f, 0x1d, 0x1d, 0xb9, 0x5d, 0xec, 0xec, 0x92, 0x59, 0x44, 0x9f, 0x8c, + 0x21, 0x82, 0x8c, 0x2d, 0xd2, 0xde, 0x98, 0xa1, 0x0e, 0xc6, 0x56, 0x36, 0x34, 0x1a, 0x0e, 0x58, 0x33, 0x30, 0x15, + 0x71, 0xc5, 0xaa, 0x70, 0x34, 0x94, 0x87, 0xd7, 0x84, 0xf7, 0xe2, 0x23, 0xb8, 0x51, 0xd6, 0x75, 0x99, 0x36, 0x0e, + 0xab, 0xe3, 0xfc, 0xa5, 0x54, 0x4f, 0x83, 0x03, 0x70, 0x2d, 0x14, 0xda, 0x24, 0x9f, 0xc5, 0xbf, 0xa5, 0xfc, 0xff, + 0xc5, 0xf2, 0xae, 0x6c, 0x3f, 0xd2, 0x05, 0x89, 0x76, 0xb1, 0x5b, 0xa8, 0xd7, 0x4d, 0x6b, 0x40, 0x5a, 0x19, 0x4c, + 0x55, 0x05, 0x3a, 0x28, 0xe9, 0x4b, 0x09, 0x40, 0x1a, 0xc4, 0xef, 0xc8, 0x31, 0xc3, 0x14, 0x17, 0x22, 0xc4, 0x22, + 0x7d, 0x1d, 0x8c, 0xc1, 0x7c, 0xde, 0x45, 0xfd, 0x41, 0x69, 0x4d, 0x80, 0x36, 0xbe, 0x36, 0xb6, 0xbd, 0xc4, 0xfd, + 0x55, 0xbd, 0x96, 0x00, 0x0c, 0x28, 0x73, 0x61, 0x13, 0xa2, 0x21, 0x81, 0x56, 0x59, 0xdc, 0xd4, 0x4b, 0xf9, 0x56, + 0xd5, 0xb3, 0x89, 0x8e, 0x21, 0xb8, 0xe6, 0x2a, 0x04, 0x5b, 0x68, 0x0b, 0x60, 0xb0, 0x7c, 0xf9, 0xe1, 0xb3, 0x05, + 0x53, 0xac, 0xae, 0x47, 0x17, 0xa7, 0x1c, 0xd7, 0xaf, 0x85, 0x67, 0x67, 0x4a, 0xfb, 0x1f, 0xe5, 0x8b, 0x3f, 0x34, + 0x0a, 0xf4, 0x2e, 0x4a, 0x12, 0x3a, 0x6e, 0x2d, 0xee, 0x19, 0x7b, 0xd5, 0x5e, 0x04, 0xd1, 0xfe, 0x75, 0xfd, 0xbb, + 0xbd, 0xeb, 0xc2, 0x81, 0xb1, 0x77, 0x65, 0x38, 0x71, 0xc8, 0x72, 0x21, 0x1b, 0xfc, 0xa0, 0x08, 0x14, 0x55, 0xaf, + 0x63, 0x1d, 0x5b, 0x11, 0x97, 0x7f, 0xb1, 0x1a, 0x0c, 0x4f, 0xce, 0xee, 0x16, 0xa1, 0x76, 0xc3, 0x12, 0x48, 0xed, + 0x33, 0xd0, 0x5d, 0xdb, 0xd1, 0x35, 0xf4, 0xa1, 0x0d, 0xa2, 0xd9, 0x40, 0xff, 0xe5, 0xe2, 0x8d, 0xd5, 0xd5, 0xcf, + 0x40, 0x45, 0x7b, 0x33, 0xc3, 0x63, 0xef, 0xdc, 0xbf, 0x67, 0xc9, 0xb5, 0xa7, 0x6b, 0x98, 0xc1, 0x87, 0x0e, 0x3c, + 0x2c, 0xd3, 0x3c, 0x7d, 0x8f, 0x44, 0x11, 0x9a, 0xc8, 0xf5, 0xa6, 0x03, 0xc9, 0x71, 0xbd, 0xae, 0xe6, 0x7a, 0x87, + 0xf6, 0x51, 0x57, 0x3f, 0xfd, 0x46, 0xd3, 0x4e, 0x26, 0x6c, 0x9a, 0x9e, 0xe2, 0x15, 0xed, 0x04, 0xcf, 0x08, 0xfa, + 0xad, 0x69, 0xf6, 0x38, 0x4c, 0x2d, 0x57, 0x5b, 0xf3, 0x47, 0x4d, 0x9b, 0x06, 0x61, 0xd8, 0xd3, 0x1e, 0x4f, 0xbd, + 0xe9, 0xe1, 0xf4, 0x45, 0x9f, 0x17, 0xe7, 0xdf, 0x94, 0xaa, 0x9b, 0xf4, 0xaf, 0xa7, 0x34, 0x4b, 0xb3, 0x24, 0xfe, + 0xc4, 0xb8, 0xd9, 0x89, 0x26, 0x2f, 0x8f, 0xd5, 0xa6, 0x5e, 0xfd, 0x4b, 0x6e, 0x77, 0x34, 0x9e, 0x7a, 0x45, 0x75, + 0xec, 0xe3, 0x81, 0xec, 0xe4, 0xc9, 0x81, 0xe8, 0xfa, 0x89, 0x8a, 0x26, 0xd7, 0x6a, 0x42, 0x94, 0xab, 0xf3, 0x31, + 0xce, 0xc4, 0xf8, 0x4e, 0x20, 0x0e, 0xa3, 0x74, 0xd7, 0x85, 0x1e, 0xe8, 0xda, 0x64, 0xa0, 0xff, 0xe8, 0x7a, 0x5d, + 0xd3, 0x75, 0x8f, 0xec, 0xa3, 0xee, 0xd8, 0x31, 0x0f, 0xed, 0x43, 0xab, 0x6d, 0x1f, 0x99, 0x5d, 0xab, 0x6b, 0x76, + 0xff, 0xd6, 0x1d, 0x5b, 0x87, 0xf6, 0xa1, 0xe9, 0x58, 0x5d, 0x28, 0xb4, 0xba, 0x56, 0xf7, 0xc6, 0x3a, 0xec, 0x8e, + 0x1d, 0x2c, 0xf5, 0xec, 0x4e, 0xc7, 0x72, 0x1d, 0xbb, 0xd3, 0x31, 0x3b, 0xf6, 0xd1, 0x91, 0xe5, 0xb6, 0xed, 0xa3, + 0xa3, 0xf3, 0x4e, 0xd7, 0x6e, 0xc3, 0xbb, 0x76, 0x7b, 0xdc, 0xb6, 0x5d, 0xd7, 0x82, 0xbf, 0xcc, 0xae, 0xed, 0xd1, + 0x0f, 0xd7, 0xb5, 0xdb, 0xae, 0xe9, 0x84, 0x1d, 0xcf, 0x3e, 0x7a, 0x61, 0xe2, 0xdf, 0x58, 0xcd, 0xc4, 0xbf, 0x00, + 0x8c, 0xf9, 0xc2, 0xf6, 0x8e, 0xe8, 0x17, 0x02, 0xbc, 0x39, 0xec, 0xfe, 0xaa, 0x1f, 0x6c, 0x1c, 0x83, 0x4b, 0x63, + 0xe8, 0x76, 0xec, 0x76, 0xdb, 0x3c, 0x74, 0xed, 0x6e, 0x7b, 0x6e, 0x1d, 0x7a, 0xf6, 0xd1, 0xf1, 0xd8, 0x72, 0xed, + 0xe3, 0x63, 0xd3, 0xb1, 0xda, 0xb6, 0x67, 0xba, 0xf6, 0x61, 0x1b, 0x7f, 0xb4, 0x6d, 0xef, 0xe6, 0xf8, 0x85, 0x7d, + 0xd4, 0x99, 0x1f, 0xd9, 0x87, 0x1f, 0x0f, 0xbb, 0xb6, 0xd7, 0x9e, 0xb7, 0x8f, 0x6c, 0xef, 0xf8, 0xe6, 0xc8, 0x3e, + 0x9c, 0x5b, 0xde, 0xd1, 0xd6, 0x96, 0xae, 0x67, 0x03, 0x8e, 0xf0, 0x35, 0xbc, 0x30, 0xf9, 0x0b, 0xf8, 0x33, 0xc7, + 0xb6, 0xff, 0x45, 0x30, 0x69, 0xbd, 0xe9, 0x0b, 0xbb, 0x7b, 0x3c, 0xa6, 0xea, 0x50, 0x60, 0x89, 0x1a, 0xd0, 0xe4, + 0xc6, 0xa2, 0xcf, 0x22, 0x38, 0x4b, 0x00, 0x12, 0x7f, 0xf8, 0xc7, 0x6e, 0x2c, 0xf8, 0x30, 0x7d, 0xf7, 0x7f, 0x0a, + 0x47, 0x4e, 0x39, 0x64, 0xae, 0xfc, 0x86, 0xff, 0x43, 0x49, 0x5f, 0x86, 0xe6, 0xf9, 0x26, 0x45, 0xc5, 0xfb, 0xdd, + 0x8a, 0x8a, 0x37, 0xab, 0x7d, 0x14, 0x15, 0xef, 0xbf, 0xba, 0xa2, 0xe2, 0xbc, 0x6a, 0x27, 0xff, 0xbe, 0x1a, 0x9b, + 0xfe, 0xd7, 0x75, 0xf5, 0x1a, 0x12, 0xf8, 0xad, 0xcb, 0x8b, 0xd5, 0x15, 0x44, 0x57, 0x7a, 0x1f, 0x0f, 0xde, 0xac, + 0x4a, 0x46, 0x60, 0x31, 0xd0, 0xd8, 0xf7, 0x31, 0xd1, 0xd8, 0xdf, 0x57, 0x03, 0xb0, 0x3c, 0xe1, 0x7c, 0x49, 0x30, + 0xb1, 0xe6, 0x7e, 0x38, 0x95, 0x3c, 0x0d, 0x94, 0xf4, 0xb1, 0x18, 0xbc, 0x12, 0xe0, 0xb8, 0x06, 0x75, 0xd8, 0x6a, + 0x11, 0xa5, 0xbd, 0x23, 0x07, 0x0e, 0x52, 0x6f, 0x9a, 0xe4, 0x95, 0xc6, 0xb6, 0x88, 0x47, 0x75, 0xcd, 0xbd, 0x26, + 0x36, 0xbe, 0x47, 0xa3, 0xc0, 0x66, 0xe8, 0x6e, 0x1d, 0xae, 0x06, 0xd6, 0x36, 0xc2, 0x68, 0x12, 0xd8, 0xb9, 0xa6, + 0xf7, 0x65, 0xd3, 0xbc, 0x8a, 0x31, 0xe6, 0xe6, 0x9e, 0x42, 0x4f, 0xaa, 0xed, 0xdd, 0xb2, 0x69, 0xdf, 0xae, 0x61, + 0x36, 0x7c, 0xbe, 0xd4, 0x7c, 0x8b, 0x5d, 0xa1, 0x04, 0x5c, 0x45, 0x55, 0x25, 0xb3, 0x5a, 0x23, 0x42, 0x0a, 0xee, + 0xbe, 0x30, 0x3e, 0x2c, 0x58, 0x4b, 0x47, 0x43, 0x7e, 0xc7, 0x51, 0xde, 0x95, 0x60, 0xaa, 0x06, 0x8b, 0xcf, 0xd6, + 0xc8, 0x71, 0x07, 0xbf, 0x03, 0xeb, 0xc8, 0x39, 0x9e, 0x51, 0xac, 0xe2, 0x79, 0xad, 0xc0, 0xa5, 0xcb, 0x4c, 0x3e, + 0x77, 0xd7, 0x75, 0xe6, 0x71, 0xa3, 0xa9, 0xb2, 0xcb, 0x16, 0x82, 0x0b, 0xc2, 0xcf, 0x93, 0x61, 0x70, 0x4e, 0xc6, + 0xdb, 0x68, 0xfb, 0xbc, 0x0d, 0x98, 0xa8, 0xf7, 0x18, 0x16, 0xb1, 0xc9, 0x1f, 0xd4, 0xb8, 0x00, 0xeb, 0x29, 0x64, + 0xc1, 0xee, 0x21, 0x9b, 0xa6, 0xf0, 0xa8, 0x1e, 0x5a, 0x31, 0xf7, 0xb7, 0x18, 0xd8, 0xa8, 0x80, 0x39, 0x10, 0xb4, + 0x86, 0xde, 0x66, 0x93, 0x23, 0x9d, 0x47, 0xd6, 0x25, 0x15, 0xb5, 0xdb, 0x39, 0x36, 0xdd, 0x23, 0xd3, 0x3e, 0xee, + 0x18, 0xb9, 0xd8, 0x70, 0x2a, 0xc8, 0x12, 0x42, 0xc0, 0x28, 0x5a, 0x76, 0x33, 0x88, 0x82, 0x2c, 0xf0, 0xc3, 0x1c, + 0xf8, 0xe3, 0xf2, 0xad, 0xe2, 0x9f, 0xab, 0x34, 0x83, 0x31, 0x0a, 0xa6, 0x17, 0x0d, 0xc2, 0xad, 0x11, 0xcb, 0x6e, + 0x19, 0x8b, 0x36, 0x28, 0xcb, 0xab, 0xf6, 0xe5, 0x7f, 0x9e, 0xb5, 0x6d, 0x4e, 0x96, 0x2c, 0xa3, 0x2c, 0xe2, 0xeb, + 0x43, 0x18, 0x43, 0xe7, 0x43, 0xf3, 0xa7, 0x4d, 0x04, 0xf7, 0x9f, 0xbb, 0x09, 0x6e, 0xc6, 0xf6, 0x21, 0xb8, 0xff, + 0xfc, 0xea, 0x04, 0xf7, 0x27, 0x95, 0xe0, 0x96, 0x7c, 0x81, 0x0a, 0xa9, 0xf3, 0x07, 0x7c, 0x6e, 0x41, 0x50, 0xe7, + 0xe7, 0xfa, 0x01, 0x31, 0xf0, 0xba, 0x92, 0x6c, 0xf7, 0x63, 0x29, 0x7b, 0x10, 0x0a, 0x45, 0x30, 0x08, 0x2d, 0x65, + 0x2a, 0x81, 0x44, 0xb4, 0x32, 0xa5, 0x3a, 0xc0, 0x7c, 0x1b, 0x65, 0xa1, 0xfd, 0x9e, 0x5f, 0xfc, 0x40, 0xc9, 0xf3, + 0x26, 0x4e, 0x16, 0x3e, 0x06, 0xe0, 0xd3, 0x31, 0xeb, 0x20, 0x3c, 0x38, 0xe0, 0x7f, 0x36, 0x8e, 0xa3, 0x89, 0xd4, + 0x54, 0xb0, 0xc1, 0x25, 0x71, 0xdc, 0xfa, 0x3d, 0xf3, 0x13, 0xdd, 0xa4, 0xd7, 0x30, 0xb9, 0xcf, 0xda, 0xce, 0x33, + 0xef, 0xf0, 0xd9, 0x91, 0x03, 0xff, 0xbb, 0xac, 0x9d, 0x9b, 0xbc, 0xe2, 0x22, 0x8e, 0x20, 0xf1, 0x89, 0xa8, 0xb9, + 0xa9, 0xda, 0x2d, 0x63, 0x9f, 0x8a, 0x5a, 0xc7, 0xcd, 0x95, 0x26, 0xfe, 0x7d, 0x51, 0xa7, 0xb1, 0xc6, 0x3c, 0x5e, + 0x29, 0xdd, 0x6a, 0xe8, 0x4d, 0x10, 0xad, 0x40, 0xf6, 0xa6, 0xd4, 0x50, 0x5f, 0xf3, 0xe1, 0x16, 0xe3, 0x62, 0xed, + 0xfc, 0xaa, 0xc8, 0xae, 0x24, 0xb2, 0xbc, 0xec, 0xc4, 0x20, 0x57, 0x5b, 0x38, 0x18, 0x9b, 0x1d, 0xf3, 0x0b, 0x69, + 0x90, 0xdb, 0x50, 0x4c, 0x90, 0x4f, 0x13, 0x94, 0x25, 0xab, 0x68, 0xdc, 0xc2, 0x9f, 0xfe, 0x28, 0x6d, 0x05, 0x07, + 0x10, 0x9d, 0x15, 0x3f, 0x6c, 0xe0, 0xac, 0xf9, 0xa7, 0x4e, 0x91, 0x8a, 0x22, 0x15, 0xb3, 0xe2, 0x3f, 0xcb, 0xcc, + 0x84, 0x12, 0xd8, 0xe2, 0xd4, 0x5a, 0x03, 0xff, 0x99, 0x6c, 0xf8, 0x2c, 0x33, 0x21, 0x89, 0x2c, 0x4c, 0xf7, 0xd3, + 0xa7, 0x54, 0x0b, 0xd2, 0x3a, 0xd2, 0xb0, 0xce, 0xc6, 0x45, 0x78, 0x37, 0xcd, 0x9f, 0xc5, 0x14, 0xe1, 0xad, 0x37, + 0x36, 0xe3, 0xe7, 0xcf, 0x4f, 0x07, 0xae, 0xc1, 0x93, 0x92, 0x96, 0x32, 0x68, 0x9d, 0xef, 0x67, 0x7c, 0x60, 0x34, + 0xba, 0xc5, 0x2d, 0xe1, 0xce, 0xe4, 0x08, 0x13, 0x65, 0x4e, 0xbd, 0x20, 0xa3, 0x05, 0x29, 0x19, 0x7d, 0x61, 0x04, + 0x20, 0xea, 0xc8, 0x5b, 0x57, 0xdb, 0x76, 0x6c, 0x47, 0x97, 0x0d, 0xa7, 0xc1, 0x6c, 0xb0, 0x8e, 0x33, 0x1f, 0x72, + 0x03, 0x85, 0xf1, 0x0c, 0x7c, 0x6b, 0xb2, 0x20, 0x0b, 0x21, 0xd1, 0x0c, 0x38, 0xd9, 0x2c, 0xe8, 0x5e, 0x9e, 0x73, + 0x8b, 0x67, 0x3f, 0xf9, 0x84, 0xc9, 0x06, 0x85, 0x5b, 0x1d, 0x46, 0x1c, 0xfa, 0x11, 0x0e, 0xc3, 0x96, 0xde, 0x82, + 0x54, 0x97, 0x2c, 0x49, 0x2d, 0xd5, 0x83, 0xa0, 0xa7, 0x41, 0x1b, 0x48, 0x43, 0x8f, 0x00, 0xa6, 0x89, 0xbf, 0x80, + 0x98, 0xec, 0xeb, 0xdc, 0xe4, 0x94, 0x56, 0xe7, 0xa4, 0x56, 0x73, 0x5f, 0x1c, 0x99, 0x9a, 0xe7, 0x9a, 0x9a, 0x03, + 0xe4, 0x56, 0xcf, 0xcd, 0x75, 0x7e, 0xd5, 0xdf, 0xa5, 0x04, 0x25, 0xfa, 0xf2, 0x98, 0xc6, 0x41, 0xea, 0x4f, 0x2e, + 0x5e, 0xce, 0x28, 0x80, 0x64, 0x4b, 0x89, 0x96, 0x1e, 0x90, 0x22, 0xe4, 0x82, 0xdd, 0x65, 0x06, 0x26, 0x62, 0xe1, + 0x55, 0x02, 0x63, 0x8d, 0xce, 0x7f, 0x41, 0xa4, 0x05, 0x9f, 0x3f, 0xb7, 0x02, 0x70, 0x70, 0x18, 0x28, 0xf8, 0x81, + 0x67, 0xa3, 0x84, 0xb0, 0xa0, 0x50, 0xdd, 0x21, 0xb2, 0xc0, 0xfb, 0x08, 0xfe, 0x2d, 0x8a, 0xc5, 0x0f, 0xae, 0x3a, + 0xb5, 0x43, 0x3f, 0x9a, 0x01, 0x49, 0xf3, 0xa3, 0x59, 0xcd, 0x44, 0x83, 0xfc, 0x17, 0x2b, 0xa5, 0x05, 0xa8, 0xc2, + 0x7c, 0x22, 0xfd, 0xfe, 0xfe, 0x82, 0x12, 0x4d, 0x41, 0x52, 0x73, 0x7f, 0x82, 0xce, 0x76, 0x85, 0x76, 0xe7, 0xf9, + 0xe0, 0xdb, 0x93, 0x05, 0xcb, 0x7c, 0x12, 0x0d, 0xc3, 0xe5, 0x17, 0xd8, 0x01, 0x6d, 0x2c, 0x92, 0xc4, 0x52, 0x32, + 0xf9, 0x09, 0xbb, 0x09, 0xc6, 0xfc, 0x5e, 0x6a, 0x6a, 0xfc, 0x9c, 0xb2, 0xd0, 0x0a, 0x6c, 0xe0, 0x9a, 0x64, 0x84, + 0x3c, 0xf6, 0x31, 0xcc, 0xe4, 0x20, 0x8a, 0xf5, 0xd3, 0x6f, 0xa5, 0xbf, 0xd6, 0xa6, 0x49, 0x80, 0x6c, 0x8f, 0x97, + 0x09, 0x0b, 0xff, 0x35, 0xf8, 0x16, 0x0e, 0xee, 0x6f, 0xaf, 0x74, 0xa3, 0x9f, 0xd9, 0xf3, 0x84, 0x4d, 0x07, 0xdf, + 0x36, 0x64, 0x3d, 0xc4, 0xeb, 0x3d, 0xf5, 0x45, 0x6f, 0x7b, 0x45, 0x70, 0xa0, 0xf6, 0x5e, 0x97, 0xfa, 0x53, 0x7e, + 0x5b, 0x87, 0x1b, 0xe0, 0xba, 0x74, 0xc7, 0x76, 0xfb, 0x78, 0x7f, 0x1e, 0x85, 0xfe, 0xf8, 0x53, 0x9f, 0xde, 0x94, + 0x1e, 0x2c, 0x38, 0xad, 0xc7, 0xfe, 0xb2, 0x87, 0xc7, 0xab, 0x5a, 0x08, 0xee, 0x9a, 0x54, 0x2a, 0x39, 0xbb, 0xc6, + 0xb5, 0x8c, 0x4b, 0x79, 0x8d, 0x5f, 0xc6, 0x4f, 0xdd, 0xce, 0x83, 0x8c, 0x89, 0x4f, 0xe1, 0x43, 0x9e, 0x8b, 0x8b, + 0x3a, 0x5d, 0x51, 0xf1, 0x62, 0x6d, 0xb7, 0x35, 0xb7, 0xfb, 0xb7, 0xce, 0x8d, 0xeb, 0xcc, 0x3d, 0xd7, 0xee, 0x7e, + 0x74, 0xbb, 0xf3, 0xb6, 0x7d, 0x1c, 0x5a, 0x6d, 0xfb, 0x18, 0xfe, 0x7c, 0x3c, 0xb6, 0xbb, 0x73, 0xcb, 0xb3, 0x0f, + 0x3f, 0xba, 0x5e, 0x68, 0x75, 0xed, 0x63, 0xf8, 0x73, 0x4e, 0xad, 0xe0, 0x02, 0x44, 0xf7, 0x9d, 0x6f, 0x4b, 0x54, + 0x40, 0xf9, 0x2d, 0xf5, 0x34, 0x66, 0xe9, 0x78, 0x6b, 0xd0, 0xf5, 0x00, 0xc9, 0xd0, 0x4d, 0x11, 0x04, 0x32, 0xea, + 0xb7, 0x20, 0x0d, 0x3b, 0x26, 0x10, 0x10, 0x26, 0x2f, 0xc2, 0x2f, 0x55, 0x84, 0xd2, 0x6f, 0xdc, 0x46, 0xbc, 0x4d, + 0x73, 0xc0, 0x75, 0x91, 0x99, 0x8a, 0x94, 0x43, 0xbf, 0x2c, 0x31, 0x88, 0x91, 0x08, 0x11, 0xaf, 0x50, 0xa5, 0x22, + 0x3b, 0x62, 0xbe, 0xbb, 0xe3, 0xe8, 0x99, 0xcb, 0x64, 0x76, 0x9e, 0xaf, 0x0a, 0x9b, 0x2b, 0x8c, 0x24, 0xf4, 0x3f, + 0x0a, 0x07, 0x93, 0xd2, 0x12, 0x1c, 0x11, 0xcd, 0x75, 0x12, 0x24, 0xb2, 0x7b, 0x0a, 0x89, 0x76, 0x9b, 0x23, 0xd5, + 0x1b, 0x90, 0xc6, 0xe4, 0x2d, 0x70, 0xc9, 0x37, 0x7e, 0xa8, 0x18, 0xb7, 0x28, 0x2d, 0x1f, 0x49, 0xca, 0xff, 0xf4, + 0x69, 0xd1, 0x39, 0xab, 0xd2, 0xef, 0x13, 0xb7, 0x03, 0xc7, 0x6e, 0x87, 0xb5, 0xb7, 0xda, 0x59, 0xed, 0x0e, 0x07, + 0x5c, 0x84, 0x0b, 0x15, 0xb6, 0x14, 0x42, 0x8b, 0xbb, 0xd1, 0xd8, 0xab, 0xa6, 0xc3, 0x85, 0x40, 0xca, 0x95, 0xab, + 0x8e, 0x6e, 0xf4, 0x23, 0xa1, 0x92, 0x8c, 0xb6, 0x84, 0x40, 0xe6, 0x77, 0x31, 0x1d, 0x50, 0xb3, 0x65, 0x1c, 0x3b, + 0x9c, 0x46, 0xff, 0xd7, 0x83, 0x40, 0x07, 0x2e, 0xd0, 0xa1, 0x56, 0x76, 0x6b, 0xc9, 0xa1, 0x47, 0x9e, 0xab, 0x74, + 0xa0, 0xb2, 0xf4, 0x4c, 0x87, 0x22, 0xc8, 0x6f, 0x85, 0x29, 0xed, 0xa4, 0x01, 0x99, 0x3c, 0x2d, 0x8a, 0x02, 0x33, + 0x80, 0x18, 0xe0, 0x2d, 0xe1, 0x4c, 0x66, 0x3c, 0x7d, 0xba, 0xf1, 0x10, 0x22, 0x85, 0xbd, 0x9a, 0xd9, 0x53, 0x57, + 0xe9, 0x9b, 0xae, 0x92, 0x18, 0x09, 0x17, 0xa9, 0x86, 0xb0, 0x7b, 0xa3, 0xb5, 0x87, 0x3f, 0x47, 0xcc, 0xcf, 0x6c, + 0xae, 0x69, 0x6a, 0x29, 0x87, 0xbb, 0xe9, 0xb2, 0x36, 0x58, 0xbc, 0xf1, 0x58, 0x67, 0x3c, 0x96, 0xe0, 0x93, 0xf5, + 0xc7, 0x15, 0xf7, 0xf4, 0x06, 0x18, 0x9f, 0x9d, 0x22, 0x3c, 0xcd, 0xbb, 0xcc, 0xa7, 0x18, 0x26, 0xea, 0x91, 0x1b, + 0x67, 0xbe, 0xc8, 0x23, 0x03, 0x7c, 0x79, 0xbf, 0x51, 0x25, 0xab, 0x78, 0x83, 0x9f, 0xbe, 0xbb, 0xf8, 0x4e, 0xe3, + 0xeb, 0x9f, 0x34, 0x88, 0x78, 0x91, 0xa1, 0xac, 0x07, 0x03, 0xca, 0x7a, 0xa0, 0xf1, 0x34, 0x22, 0x90, 0x3b, 0x20, + 0x3f, 0x20, 0x0c, 0xa2, 0x00, 0x9a, 0xf4, 0xaa, 0x8b, 0x55, 0x98, 0x05, 0x4b, 0x3f, 0xc9, 0x0e, 0xa0, 0xa9, 0x05, + 0x44, 0x4e, 0xdf, 0xe4, 0x23, 0x4e, 0xaa, 0x59, 0x11, 0x62, 0x2f, 0x8b, 0x84, 0x6e, 0x76, 0x1a, 0x84, 0x52, 0x35, + 0x2b, 0x3e, 0xe0, 0x8f, 0xc7, 0x6c, 0x99, 0x0d, 0x74, 0x7f, 0x09, 0xd9, 0x2f, 0x30, 0x9e, 0xf5, 0x41, 0x3c, 0xce, + 0x58, 0x66, 0xa5, 0x59, 0xc2, 0xfc, 0x85, 0x2e, 0x43, 0xb9, 0xd6, 0xe1, 0xa5, 0xab, 0xd1, 0x22, 0xc8, 0x64, 0x2c, + 0x44, 0x1a, 0x20, 0x28, 0x49, 0xa1, 0x8b, 0xa7, 0xc3, 0x9c, 0xa3, 0xf0, 0x3c, 0x9e, 0x55, 0x56, 0x54, 0xc1, 0xb9, + 0x9c, 0x61, 0xa4, 0x5d, 0x9e, 0xf1, 0x60, 0x82, 0x3e, 0x4f, 0xd7, 0xdc, 0xaf, 0x5d, 0x86, 0x6c, 0xd4, 0x4f, 0x4f, + 0xf8, 0xf5, 0x56, 0xc3, 0x50, 0x0c, 0x7a, 0xc7, 0x81, 0x58, 0xc2, 0x9b, 0x3c, 0xde, 0x0f, 0x78, 0x65, 0x38, 0x9a, + 0x08, 0x32, 0xc6, 0x79, 0xa7, 0xbe, 0x5c, 0x00, 0x23, 0x54, 0x52, 0xa2, 0xcf, 0xdd, 0x53, 0xe9, 0x62, 0x85, 0xbd, + 0x42, 0x5e, 0xe9, 0xf3, 0xe7, 0x97, 0xc3, 0xff, 0xfc, 0x1b, 0x82, 0xd1, 0xcf, 0x5d, 0xe1, 0x67, 0x7e, 0xa9, 0xd6, + 0xe2, 0xdc, 0xa7, 0x39, 0x44, 0x03, 0x0a, 0x36, 0x11, 0x81, 0x57, 0xc4, 0xd2, 0xca, 0x87, 0x57, 0x22, 0x98, 0x16, + 0x24, 0x9c, 0x30, 0x84, 0x37, 0xfc, 0x10, 0xa6, 0x77, 0x28, 0x82, 0x30, 0x68, 0xbf, 0xdd, 0x7d, 0x7f, 0x0c, 0xc1, + 0x96, 0x6b, 0x79, 0x20, 0x94, 0x0e, 0xe2, 0x1a, 0x3a, 0x3d, 0xf1, 0x35, 0x64, 0x5a, 0x90, 0xfd, 0x48, 0x7b, 0x07, + 0x30, 0xcc, 0x79, 0xbc, 0x60, 0x76, 0x10, 0x1f, 0xdc, 0xb2, 0x91, 0xe5, 0x2f, 0x03, 0xd2, 0xd5, 0xa3, 0xdc, 0x4d, + 0x23, 0xce, 0x4f, 0xaa, 0xc0, 0x89, 0xbf, 0xce, 0x0b, 0x54, 0xc6, 0xe5, 0xe8, 0x69, 0x1d, 0xaf, 0x50, 0xdc, 0x81, + 0x4f, 0xb3, 0x82, 0xc7, 0xf8, 0xf4, 0xe4, 0xc0, 0x3f, 0x2d, 0x87, 0x6f, 0xb4, 0x45, 0x02, 0x81, 0xf2, 0x21, 0x70, + 0x46, 0x51, 0x18, 0x45, 0xc0, 0xc5, 0xe2, 0xc1, 0x8a, 0xa7, 0x53, 0x35, 0xe4, 0xa2, 0x5d, 0xee, 0x9e, 0x44, 0x5a, + 0xb1, 0xa4, 0xe3, 0x25, 0x7d, 0xa9, 0xfe, 0x09, 0xf9, 0x13, 0x92, 0x27, 0xf3, 0xe8, 0x9c, 0xb0, 0xdd, 0x6b, 0xa1, + 0x1b, 0x25, 0xc6, 0x1e, 0x53, 0x25, 0x4e, 0x47, 0xaa, 0x81, 0xc2, 0x37, 0x70, 0x2e, 0x8f, 0x06, 0x03, 0x22, 0x73, + 0x55, 0x6a, 0x07, 0x48, 0x6c, 0x48, 0xa6, 0x00, 0x83, 0xcd, 0xa0, 0xa1, 0x45, 0x2e, 0x74, 0xd8, 0xa8, 0x3a, 0x9c, + 0x7a, 0x1f, 0x0f, 0x7c, 0xb1, 0xfc, 0x4a, 0x0b, 0x14, 0x16, 0x1e, 0x9f, 0x77, 0xa0, 0xef, 0x02, 0x4e, 0x85, 0xcc, + 0x6b, 0x7f, 0x25, 0x8a, 0x6e, 0x85, 0xfe, 0x7d, 0xac, 0x98, 0x36, 0xf0, 0x28, 0x07, 0xe7, 0x58, 0x7a, 0x21, 0xbc, + 0x0b, 0x6b, 0x1b, 0x4d, 0x06, 0xa4, 0xaf, 0x6f, 0x36, 0x35, 0x82, 0xfc, 0xae, 0xbd, 0xa6, 0xd6, 0x2d, 0x0f, 0x06, + 0x89, 0x67, 0x5e, 0xec, 0xc3, 0xd2, 0x4b, 0x24, 0x0b, 0xf9, 0xc9, 0x01, 0x8c, 0x0f, 0x22, 0x33, 0x94, 0x18, 0xa7, + 0xc0, 0x80, 0xf0, 0x0f, 0x7e, 0x4a, 0xe6, 0x19, 0x6f, 0x27, 0x82, 0xe7, 0xc3, 0x8b, 0xa5, 0x8c, 0x0d, 0x5b, 0xaa, + 0x52, 0xe7, 0x65, 0x9c, 0x66, 0x26, 0x70, 0x77, 0x02, 0x87, 0xdf, 0x57, 0x98, 0xbd, 0x21, 0xef, 0x67, 0x4c, 0x38, + 0x3e, 0x9f, 0x67, 0x1b, 0x7c, 0xa3, 0x37, 0x55, 0x21, 0x7e, 0x76, 0x4b, 0x85, 0x62, 0x1d, 0x6f, 0xab, 0x55, 0x70, + 0x4e, 0xb2, 0xda, 0xd2, 0x6f, 0xe9, 0x8f, 0x71, 0xc5, 0xd7, 0x6a, 0x63, 0x29, 0xd4, 0x3b, 0xcf, 0x06, 0x50, 0x55, + 0xc8, 0xe2, 0xfd, 0xe5, 0x92, 0x2a, 0x1b, 0xfd, 0x93, 0x03, 0xba, 0x96, 0x9e, 0xd2, 0x0a, 0x3b, 0x3d, 0x01, 0xf3, + 0x4e, 0x9a, 0x74, 0x7f, 0xb9, 0xe4, 0x53, 0x4a, 0xbf, 0xe8, 0xcd, 0xc1, 0x3c, 0x5b, 0x84, 0xa7, 0xff, 0x07, 0xc0, + 0xb1, 0x34, 0x8b, 0x20, 0x5c, 0x03, 0x00}; } // namespace web_server } // namespace esphome From d7f6d4436e1b4e894306ded3489f6ea337dfffbc Mon Sep 17 00:00:00 2001 From: Colm Date: Thu, 11 Jul 2024 05:10:58 +0100 Subject: [PATCH 1759/2101] Add braces to if statement to avoid compiler warning. (#7036) --- esphome/components/aht10/aht10.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/esphome/components/aht10/aht10.cpp b/esphome/components/aht10/aht10.cpp index 332218b9e9..441c1ac9df 100644 --- a/esphome/components/aht10/aht10.cpp +++ b/esphome/components/aht10/aht10.cpp @@ -93,8 +93,9 @@ void AHT10Component::restart_read_() { void AHT10Component::read_data_() { uint8_t data[6]; - if (this->read_count_ > 1) + if (this->read_count_ > 1) { ESP_LOGD(TAG, "Read attempt %d at %ums", this->read_count_, (unsigned) (millis() - this->start_time_)); + } if (this->read(data, 6) != i2c::ERROR_OK) { this->status_set_warning("AHT10 read failed, retrying soon"); this->restart_read_(); @@ -119,8 +120,9 @@ void AHT10Component::read_data_() { return; } } - if (this->read_count_ > 1) + if (this->read_count_ > 1) { ESP_LOGD(TAG, "Success at %ums", (unsigned) (millis() - this->start_time_)); + } uint32_t raw_temperature = ((data[3] & 0x0F) << 16) | (data[4] << 8) | data[5]; uint32_t raw_humidity = ((data[1] << 16) | (data[2] << 8) | data[3]) >> 4; From 2d826768b05f33951d1bdd917f62f9db3792c7ce Mon Sep 17 00:00:00 2001 From: ttaborda <80131527+ttaborda@users.noreply.github.com> Date: Thu, 11 Jul 2024 05:26:37 +0100 Subject: [PATCH 1760/2101] Update mitsubishi.cpp (#6909) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/mitsubishi/mitsubishi.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/mitsubishi/mitsubishi.cpp b/esphome/components/mitsubishi/mitsubishi.cpp index fd57adc586..a02aabf14d 100644 --- a/esphome/components/mitsubishi/mitsubishi.cpp +++ b/esphome/components/mitsubishi/mitsubishi.cpp @@ -52,6 +52,7 @@ const uint8_t MITSUBISHI_BYTE16 = 0X00; climate::ClimateTraits MitsubishiClimate::traits() { auto traits = climate::ClimateTraits(); + traits.set_supports_current_temperature(this->sensor_ != nullptr); traits.set_supports_action(false); traits.set_visual_min_temperature(MITSUBISHI_TEMP_MIN); traits.set_visual_max_temperature(MITSUBISHI_TEMP_MAX); From 531f33a158370f59fa246c064d01e28b80610bbc Mon Sep 17 00:00:00 2001 From: Sergey Dudanov Date: Thu, 11 Jul 2024 08:23:29 +0300 Subject: [PATCH 1761/2101] [climate] fix dump output of unsupported features (#7005) --- esphome/components/climate/climate.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/esphome/components/climate/climate.cpp b/esphome/components/climate/climate.cpp index 1822707152..bc8d932089 100644 --- a/esphome/components/climate/climate.cpp +++ b/esphome/components/climate/climate.cpp @@ -574,21 +574,25 @@ void Climate::dump_traits_(const char *tag) { ESP_LOGCONFIG(tag, " - Max temperature: %.1f", traits.get_visual_max_temperature()); ESP_LOGCONFIG(tag, " - Temperature step:"); ESP_LOGCONFIG(tag, " Target: %.1f", traits.get_visual_target_temperature_step()); - ESP_LOGCONFIG(tag, " Current: %.1f", traits.get_visual_current_temperature_step()); - ESP_LOGCONFIG(tag, " - Min humidity: %.0f", traits.get_visual_min_humidity()); - ESP_LOGCONFIG(tag, " - Max humidity: %.0f", traits.get_visual_max_humidity()); if (traits.get_supports_current_temperature()) { - ESP_LOGCONFIG(tag, " [x] Supports current temperature"); + ESP_LOGCONFIG(tag, " Current: %.1f", traits.get_visual_current_temperature_step()); } - if (traits.get_supports_current_humidity()) { - ESP_LOGCONFIG(tag, " [x] Supports current humidity"); + if (traits.get_supports_target_humidity() || traits.get_supports_current_humidity()) { + ESP_LOGCONFIG(tag, " - Min humidity: %.0f", traits.get_visual_min_humidity()); + ESP_LOGCONFIG(tag, " - Max humidity: %.0f", traits.get_visual_max_humidity()); } if (traits.get_supports_two_point_target_temperature()) { ESP_LOGCONFIG(tag, " [x] Supports two-point target temperature"); } + if (traits.get_supports_current_temperature()) { + ESP_LOGCONFIG(tag, " [x] Supports current temperature"); + } if (traits.get_supports_target_humidity()) { ESP_LOGCONFIG(tag, " [x] Supports target humidity"); } + if (traits.get_supports_current_humidity()) { + ESP_LOGCONFIG(tag, " [x] Supports current humidity"); + } if (traits.get_supports_action()) { ESP_LOGCONFIG(tag, " [x] Supports action"); } From 91bb38553d9eeec1f5a0347e48f9ffc5a70dadbf Mon Sep 17 00:00:00 2001 From: Sergey Dudanov Date: Thu, 11 Jul 2024 08:24:36 +0300 Subject: [PATCH 1762/2101] [climate-traits] improved performance (#7006) --- esphome/components/climate/climate_traits.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/climate/climate_traits.h b/esphome/components/climate/climate_traits.h index fd5b025a03..58d7b586d7 100644 --- a/esphome/components/climate/climate_traits.h +++ b/esphome/components/climate/climate_traits.h @@ -73,7 +73,7 @@ class ClimateTraits { ESPDEPRECATED("This method is deprecated, use set_supported_modes() instead", "v1.20") void set_supports_dry_mode(bool supports_dry_mode) { set_mode_support_(CLIMATE_MODE_DRY, supports_dry_mode); } bool supports_mode(ClimateMode mode) const { return supported_modes_.count(mode); } - std::set get_supported_modes() const { return supported_modes_; } + const std::set &get_supported_modes() const { return supported_modes_; } void set_supports_action(bool supports_action) { supports_action_ = supports_action; } bool get_supports_action() const { return supports_action_; } @@ -101,7 +101,7 @@ class ClimateTraits { void set_supports_fan_mode_diffuse(bool supported) { set_fan_mode_support_(CLIMATE_FAN_DIFFUSE, supported); } bool supports_fan_mode(ClimateFanMode fan_mode) const { return supported_fan_modes_.count(fan_mode); } bool get_supports_fan_modes() const { return !supported_fan_modes_.empty() || !supported_custom_fan_modes_.empty(); } - std::set get_supported_fan_modes() const { return supported_fan_modes_; } + const std::set &get_supported_fan_modes() const { return supported_fan_modes_; } void set_supported_custom_fan_modes(std::set supported_custom_fan_modes) { supported_custom_fan_modes_ = std::move(supported_custom_fan_modes); @@ -140,7 +140,7 @@ class ClimateTraits { } bool supports_swing_mode(ClimateSwingMode swing_mode) const { return supported_swing_modes_.count(swing_mode); } bool get_supports_swing_modes() const { return !supported_swing_modes_.empty(); } - std::set get_supported_swing_modes() const { return supported_swing_modes_; } + const std::set &get_supported_swing_modes() const { return supported_swing_modes_; } float get_visual_min_temperature() const { return visual_min_temperature_; } void set_visual_min_temperature(float visual_min_temperature) { visual_min_temperature_ = visual_min_temperature; } From a34cec217e50e9bbf26ce8494f9bec5abf9951ab Mon Sep 17 00:00:00 2001 From: leejoow Date: Thu, 11 Jul 2024 22:20:58 +0200 Subject: [PATCH 1763/2101] Add default icon to restart button (#7076) Co-authored-by: Leo Schelvis --- esphome/components/restart/button/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/components/restart/button/__init__.py b/esphome/components/restart/button/__init__.py index 1b2c991261..6aff8cb351 100644 --- a/esphome/components/restart/button/__init__.py +++ b/esphome/components/restart/button/__init__.py @@ -5,6 +5,7 @@ from esphome.const import ( CONF_ID, DEVICE_CLASS_RESTART, ENTITY_CATEGORY_CONFIG, + ICON_RESTART, ) restart_ns = cg.esphome_ns.namespace("restart") @@ -12,6 +13,7 @@ RestartButton = restart_ns.class_("RestartButton", button.Button, cg.Component) CONFIG_SCHEMA = button.button_schema( RestartButton, + icon=ICON_RESTART, device_class=DEVICE_CLASS_RESTART, entity_category=ENTITY_CATEGORY_CONFIG, ).extend(cv.COMPONENT_SCHEMA) From 54b77a1174b0912e028c5d8c1ba56068e30bc84e Mon Sep 17 00:00:00 2001 From: Tomi Junnila Date: Thu, 11 Jul 2024 23:32:38 +0300 Subject: [PATCH 1764/2101] Add support for the Gree YAC1FB9 in climate_ir (#7056) --- esphome/components/gree/climate.py | 1 + esphome/components/gree/gree.cpp | 14 +++++++++++--- esphome/components/gree/gree.h | 6 +++++- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/esphome/components/gree/climate.py b/esphome/components/gree/climate.py index 02ce7b12d4..c88a428391 100644 --- a/esphome/components/gree/climate.py +++ b/esphome/components/gree/climate.py @@ -16,6 +16,7 @@ MODELS = { "yan": Model.GREE_YAN, "yaa": Model.GREE_YAA, "yac": Model.GREE_YAC, + "yac1fb9": Model.GREE_YAC1FB9, } CONFIG_SCHEMA = climate_ir.CLIMATE_IR_WITH_RECEIVER_SCHEMA.extend( diff --git a/esphome/components/gree/gree.cpp b/esphome/components/gree/gree.cpp index 1bbb443fce..cce2a8ffee 100644 --- a/esphome/components/gree/gree.cpp +++ b/esphome/components/gree/gree.cpp @@ -24,7 +24,7 @@ void GreeClimate::transmit_state() { remote_state[4] |= (this->horizontal_swing_() << 4); } - if (this->model_ == GREE_YAA || this->model_ == GREE_YAC) { + if (this->model_ == GREE_YAA || this->model_ == GREE_YAC || this->model_ == GREE_YAC1FB9) { remote_state[2] = 0x20; // bits 0..3 always 0000, bits 4..7 TURBO,LIGHT,HEALTH,X-FAN remote_state[3] = 0x50; // bits 4..7 always 0101 remote_state[6] = 0x20; // YAA1FB, FAA1FB1, YB1F2 bits 4..7 always 0010 @@ -53,7 +53,11 @@ void GreeClimate::transmit_state() { data->set_carrier_frequency(GREE_IR_FREQUENCY); data->mark(GREE_HEADER_MARK); - data->space(GREE_HEADER_SPACE); + if (this->model_ == GREE_YAC1FB9) { + data->space(GREE_YAC1FB9_HEADER_SPACE); + } else { + data->space(GREE_HEADER_SPACE); + } for (int i = 0; i < 4; i++) { for (uint8_t mask = 1; mask > 0; mask <<= 1) { // iterate through bit mask @@ -71,7 +75,11 @@ void GreeClimate::transmit_state() { data->space(GREE_ZERO_SPACE); data->mark(GREE_BIT_MARK); - data->space(GREE_MESSAGE_SPACE); + if (this->model_ == GREE_YAC1FB9) { + data->space(GREE_YAC1FB9_MESSAGE_SPACE); + } else { + data->space(GREE_MESSAGE_SPACE); + } for (int i = 4; i < 8; i++) { for (uint8_t mask = 1; mask > 0; mask <<= 1) { // iterate through bit mask diff --git a/esphome/components/gree/gree.h b/esphome/components/gree/gree.h index e7131a2b89..524a95aebd 100644 --- a/esphome/components/gree/gree.h +++ b/esphome/components/gree/gree.h @@ -41,6 +41,10 @@ const uint32_t GREE_YAC_HEADER_MARK = 6000; const uint32_t GREE_YAC_HEADER_SPACE = 3000; const uint32_t GREE_YAC_BIT_MARK = 650; +// Timing specific to YAC1FB9 +const uint32_t GREE_YAC1FB9_HEADER_SPACE = 4500; +const uint32_t GREE_YAC1FB9_MESSAGE_SPACE = 19980; + // State Frame size const uint8_t GREE_STATE_FRAME_SIZE = 8; @@ -67,7 +71,7 @@ const uint8_t GREE_HDIR_MRIGHT = 0x05; const uint8_t GREE_HDIR_RIGHT = 0x06; // Model codes -enum Model { GREE_GENERIC, GREE_YAN, GREE_YAA, GREE_YAC }; +enum Model { GREE_GENERIC, GREE_YAN, GREE_YAA, GREE_YAC, GREE_YAC1FB9 }; class GreeClimate : public climate_ir::ClimateIR { public: From fbab0aceb024175c86b330048c6f45814248ae97 Mon Sep 17 00:00:00 2001 From: Eugen Date: Thu, 11 Jul 2024 23:26:04 +0200 Subject: [PATCH 1765/2101] add ESP32-C6 support to esp32_can (#7063) --- esphome/components/esp32_can/canbus.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/esphome/components/esp32_can/canbus.py b/esphome/components/esp32_can/canbus.py index 74f331f30b..f4ba032009 100644 --- a/esphome/components/esp32_can/canbus.py +++ b/esphome/components/esp32_can/canbus.py @@ -11,6 +11,7 @@ from esphome.components.esp32.const import ( VARIANT_ESP32S2, VARIANT_ESP32S3, VARIANT_ESP32C3, + VARIANT_ESP32C6, VARIANT_ESP32H2, ) @@ -47,6 +48,7 @@ CAN_SPEEDS_ESP32_S2 = { CAN_SPEEDS_ESP32_S3 = {**CAN_SPEEDS_ESP32_S2} CAN_SPEEDS_ESP32_C3 = {**CAN_SPEEDS_ESP32_S2} +CAN_SPEEDS_ESP32_C6 = {**CAN_SPEEDS_ESP32_S2} CAN_SPEEDS_ESP32_H2 = {**CAN_SPEEDS_ESP32_S2} CAN_SPEEDS = { @@ -54,6 +56,7 @@ CAN_SPEEDS = { VARIANT_ESP32S2: CAN_SPEEDS_ESP32_S2, VARIANT_ESP32S3: CAN_SPEEDS_ESP32_S3, VARIANT_ESP32C3: CAN_SPEEDS_ESP32_C3, + VARIANT_ESP32C6: CAN_SPEEDS_ESP32_C6, VARIANT_ESP32H2: CAN_SPEEDS_ESP32_H2, } From c6c1d3a3ad2e6fefecd6de60584eea1e263734e2 Mon Sep 17 00:00:00 2001 From: kevdliu <1766838+kevdliu@users.noreply.github.com> Date: Thu, 11 Jul 2024 17:32:31 -0400 Subject: [PATCH 1766/2101] Fix voice assistant crash when no speaker configured (#7075) --- esphome/components/voice_assistant/voice_assistant.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index 8a8a9e92aa..e4f388db68 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -684,7 +684,9 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { this->defer([this, text]() { this->tts_start_trigger_->trigger(text); #ifdef USE_SPEAKER - this->speaker_->start(); + if (this->speaker_ != nullptr) { + this->speaker_->start(); + } #endif }); break; From 0c2f9b9dbbfaa14af7b608e6c6223fd6527bda52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=2E=20=C3=81rkosi=20R=C3=B3bert?= Date: Fri, 12 Jul 2024 23:19:33 +0200 Subject: [PATCH 1767/2101] Bump HeatpumpIR, add protocols, remove IRremoteESP8266 (#6996) --- esphome/components/heatpumpir/climate.py | 11 ++++++----- esphome/components/heatpumpir/heatpumpir.cpp | 5 +++++ esphome/components/heatpumpir/heatpumpir.h | 5 +++++ platformio.ini | 6 +++--- .../heatpumpir/test.bk72xx-ard.yaml | 19 +++++++++++++++++++ 5 files changed, 38 insertions(+), 8 deletions(-) create mode 100644 tests/components/heatpumpir/test.bk72xx-ard.yaml diff --git a/esphome/components/heatpumpir/climate.py b/esphome/components/heatpumpir/climate.py index b86d405b7e..80900d7db9 100644 --- a/esphome/components/heatpumpir/climate.py +++ b/esphome/components/heatpumpir/climate.py @@ -8,7 +8,6 @@ from esphome.const import ( CONF_PROTOCOL, CONF_VISUAL, ) -from esphome.core import CORE CODEOWNERS = ["@rob-deutsch"] @@ -67,6 +66,11 @@ PROTOCOLS = { "carrier_qlima_2": Protocol.PROTOCOL_QLIMA_2, "samsung_aqv12msan": Protocol.PROTOCOL_SAMSUNG_AQV12MSAN, "zhjg01": Protocol.PROTOCOL_ZHJG01, + "airway": Protocol.PROTOCOL_AIRWAY, + "bgh_aud": Protocol.PROTOCOL_BGH_AUD, + "panasonic_altdke": Protocol.PROTOCOL_PANASONIC_ALTDKE, + "vaillantvai8": Protocol.PROTOCOL_VAILLANTVAI8, + "r51m": Protocol.PROTOCOL_R51M, } CONF_HORIZONTAL_DEFAULT = "horizontal_default" @@ -122,7 +126,4 @@ 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.26") - - if CORE.is_esp8266 or CORE.is_esp32: - cg.add_library("crankyoldgit/IRremoteESP8266", "2.8.6") + cg.add_library("tonia/HeatpumpIR", "1.0.27") diff --git a/esphome/components/heatpumpir/heatpumpir.cpp b/esphome/components/heatpumpir/heatpumpir.cpp index 22a5779c8d..144dcc9bfa 100644 --- a/esphome/components/heatpumpir/heatpumpir.cpp +++ b/esphome/components/heatpumpir/heatpumpir.cpp @@ -61,6 +61,11 @@ const std::map> PROTOCOL_CONSTRUCTOR_MAP {PROTOCOL_QLIMA_2, []() { return new Qlima2HeatpumpIR(); }}, // NOLINT {PROTOCOL_SAMSUNG_AQV12MSAN, []() { return new SamsungAQV12MSANHeatpumpIR(); }}, // NOLINT {PROTOCOL_ZHJG01, []() { return new ZHJG01HeatpumpIR(); }}, // NOLINT + {PROTOCOL_AIRWAY, []() { return new AIRWAYHeatpumpIR(); }}, // NOLINT + {PROTOCOL_BGH_AUD, []() { return new BGHHeatpumpIR(); }}, // NOLINT + {PROTOCOL_PANASONIC_ALTDKE, []() { return new PanasonicAltDKEHeatpumpIR(); }}, // NOLINT + {PROTOCOL_VAILLANTVAI8, []() { return new VaillantHeatpumpIR(); }}, // NOLINT + {PROTOCOL_R51M, []() { return new R51MHeatpumpIR(); }}, // NOLINT }; void HeatpumpIRClimate::setup() { diff --git a/esphome/components/heatpumpir/heatpumpir.h b/esphome/components/heatpumpir/heatpumpir.h index 0e6ea2218f..f6e7ff3cd6 100644 --- a/esphome/components/heatpumpir/heatpumpir.h +++ b/esphome/components/heatpumpir/heatpumpir.h @@ -61,6 +61,11 @@ enum Protocol { PROTOCOL_QLIMA_2, PROTOCOL_SAMSUNG_AQV12MSAN, PROTOCOL_ZHJG01, + PROTOCOL_AIRWAY, + PROTOCOL_BGH_AUD, + PROTOCOL_PANASONIC_ALTDKE, + PROTOCOL_VAILLANTVAI8, + PROTOCOL_R51M, }; // Simple enum to represent horizontal directios diff --git a/platformio.ini b/platformio.ini index f07889526f..fc7f35b6c3 100644 --- a/platformio.ini +++ b/platformio.ini @@ -65,7 +65,7 @@ lib_deps = glmnet/Dsmr@0.7 ; dsmr rweather/Crypto@0.4.0 ; dsmr dudanov/MideaUART@1.1.9 ; midea - tonia/HeatpumpIR@1.0.26 ; heatpumpir + tonia/HeatpumpIR@1.0.27 ; heatpumpir build_flags = ${common.build_flags} -DUSE_ARDUINO @@ -93,8 +93,8 @@ lib_deps = ESP8266HTTPClient ; http_request (Arduino built-in) ESP8266mDNS ; mdns (Arduino built-in) DNSServer ; captive_portal (Arduino built-in) - crankyoldgit/IRremoteESP8266@2.8.6 ; heatpumpir droscy/esp_wireguard@0.4.2 ; wireguard + build_flags = ${common:arduino.build_flags} -Wno-nonnull-compare @@ -123,8 +123,8 @@ lib_deps = ESPmDNS ; mdns (Arduino built-in) DNSServer ; captive_portal (Arduino built-in) esphome/ESP32-audioI2S@2.0.7 ; i2s_audio - crankyoldgit/IRremoteESP8266@2.8.6 ; heatpumpir droscy/esp_wireguard@0.4.2 ; wireguard + build_flags = ${common:arduino.build_flags} -DUSE_ESP32 diff --git a/tests/components/heatpumpir/test.bk72xx-ard.yaml b/tests/components/heatpumpir/test.bk72xx-ard.yaml new file mode 100644 index 0000000000..90259f1244 --- /dev/null +++ b/tests/components/heatpumpir/test.bk72xx-ard.yaml @@ -0,0 +1,19 @@ +remote_transmitter: + pin: 6 + carrier_duty_percent: 50% + +climate: + - platform: heatpumpir + protocol: daikin + horizontal_default: mleft + vertical_default: mup + name: HeatpumpIR Climate + min_temperature: 18 + max_temperature: 30 + - platform: heatpumpir + protocol: panasonic_altdke + horizontal_default: mright + vertical_default: mdown + name: HeatpumpIR Climate + min_temperature: 18 + max_temperature: 30 From 316a0e1c967ad28f4ec43144cafea512f519d0a4 Mon Sep 17 00:00:00 2001 From: Anton Viktorov Date: Fri, 12 Jul 2024 21:42:41 +0000 Subject: [PATCH 1768/2101] LTR390 separate ALS and UV gain and resolution (#7026) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- CODEOWNERS | 2 +- esphome/components/ltr390/ltr390.cpp | 73 +++++++++++-------- esphome/components/ltr390/ltr390.h | 14 ++-- esphome/components/ltr390/sensor.py | 40 ++++++++-- tests/components/ltr390/test.esp32-ard.yaml | 18 +++++ tests/components/ltr390/test.esp8266-ard.yaml | 4 +- 6 files changed, 110 insertions(+), 41 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index 5c14d30371..210c567f78 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -214,7 +214,7 @@ esphome/components/lightwaverf/* @max246 esphome/components/lilygo_t5_47/touchscreen/* @jesserockz esphome/components/lock/* @esphome/core esphome/components/logger/* @esphome/core -esphome/components/ltr390/* @sjtrny +esphome/components/ltr390/* @latonita @sjtrny esphome/components/ltr_als_ps/* @latonita esphome/components/matrix_keypad/* @ssieb esphome/components/max31865/* @DAVe3283 diff --git a/esphome/components/ltr390/ltr390.cpp b/esphome/components/ltr390/ltr390.cpp index 4eb1ff2c46..198d15ebd8 100644 --- a/esphome/components/ltr390/ltr390.cpp +++ b/esphome/components/ltr390/ltr390.cpp @@ -19,6 +19,7 @@ static const uint8_t LTR390_MAIN_STATUS = 0x07; static const float GAINVALUES[5] = {1.0, 3.0, 6.0, 9.0, 18.0}; static const float RESOLUTIONVALUE[6] = {4.0, 2.0, 1.0, 0.5, 0.25, 0.125}; +static const uint8_t RESOLUTION_BITS[6] = {20, 19, 18, 17, 16, 13}; // Request fastest measurement rate - will be slowed by device if conversion rate is slower. static const float RESOLUTION_SETTING[6] = {0x00, 0x10, 0x20, 0x30, 0x40, 0x50}; @@ -74,7 +75,7 @@ void LTR390Component::read_als_() { uint32_t als = *val; if (this->light_sensor_ != nullptr) { - float lux = ((0.6 * als) / (GAINVALUES[this->gain_] * RESOLUTIONVALUE[this->res_])) * this->wfac_; + float lux = ((0.6 * als) / (GAINVALUES[this->gain_als_] * RESOLUTIONVALUE[this->res_als_])) * this->wfac_; this->light_sensor_->publish_state(lux); } @@ -90,7 +91,7 @@ void LTR390Component::read_uvs_() { uint32_t uv = *val; if (this->uvi_sensor_ != nullptr) { - this->uvi_sensor_->publish_state((uv / this->sensitivity_) * this->wfac_); + this->uvi_sensor_->publish_state((uv / this->sensitivity_uv_) * this->wfac_); } if (this->uv_sensor_ != nullptr) { @@ -107,24 +108,38 @@ void LTR390Component::read_mode_(int mode_index) { ctrl[LTR390_CTRL_EN] = true; this->reg(LTR390_MAIN_CTRL) = ctrl.to_ulong(); - // After the sensor integration time do the following - this->set_timeout(((uint32_t) RESOLUTIONVALUE[this->res_]) * 100 + LTR390_WAKEUP_TIME + LTR390_SETTLE_TIME, - [this, mode_index]() { - // Read from the sensor - std::get<1>(this->mode_funcs_[mode_index])(); + uint32_t int_time{0}; + // Set gain, resolution and measurement rate + switch (mode) { + case LTR390_MODE_ALS: + this->reg(LTR390_GAIN) = this->gain_als_; + this->reg(LTR390_MEAS_RATE) = RESOLUTION_SETTING[this->res_als_]; + int_time = ((uint32_t) RESOLUTIONVALUE[this->res_als_]) * 100; + break; + case LTR390_MODE_UVS: + this->reg(LTR390_GAIN) = this->gain_uv_; + this->reg(LTR390_MEAS_RATE) = RESOLUTION_SETTING[this->res_uv_]; + int_time = ((uint32_t) RESOLUTIONVALUE[this->res_uv_]) * 100; + break; + } - // If there are more modes to read then begin the next - // otherwise stop - if (mode_index + 1 < (int) this->mode_funcs_.size()) { - this->read_mode_(mode_index + 1); - } else { - // put sensor in standby - std::bitset<8> ctrl = this->reg(LTR390_MAIN_CTRL).get(); - ctrl[LTR390_CTRL_EN] = false; - this->reg(LTR390_MAIN_CTRL) = ctrl.to_ulong(); - this->reading_ = false; - } - }); + // After the sensor integration time do the following + this->set_timeout(int_time + LTR390_WAKEUP_TIME + LTR390_SETTLE_TIME, [this, mode_index]() { + // Read from the sensor + std::get<1>(this->mode_funcs_[mode_index])(); + + // If there are more modes to read then begin the next + // otherwise stop + if (mode_index + 1 < (int) this->mode_funcs_.size()) { + this->read_mode_(mode_index + 1); + } else { + // put sensor in standby + std::bitset<8> ctrl = this->reg(LTR390_MAIN_CTRL).get(); + ctrl[LTR390_CTRL_EN] = false; + this->reg(LTR390_MAIN_CTRL) = ctrl.to_ulong(); + this->reading_ = false; + } + }); } void LTR390Component::setup() { @@ -151,16 +166,10 @@ void LTR390Component::setup() { return; } - // Set gain - this->reg(LTR390_GAIN) = gain_; - - // Set resolution and measurement rate - this->reg(LTR390_MEAS_RATE) = RESOLUTION_SETTING[this->res_]; - // Set sensitivity by linearly scaling against known value in the datasheet - float gain_scale = GAINVALUES[this->gain_] / GAIN_MAX; - float intg_scale = (RESOLUTIONVALUE[this->res_] * 100) / INTG_MAX; - this->sensitivity_ = SENSITIVITY_MAX * gain_scale * intg_scale; + float gain_scale_uv = GAINVALUES[this->gain_uv_] / GAIN_MAX; + float intg_scale_uv = (RESOLUTIONVALUE[this->res_uv_] * 100) / INTG_MAX; + this->sensitivity_uv_ = SENSITIVITY_MAX * gain_scale_uv * intg_scale_uv; // Set sensor read state this->reading_ = false; @@ -176,7 +185,13 @@ void LTR390Component::setup() { } } -void LTR390Component::dump_config() { LOG_I2C_DEVICE(this); } +void LTR390Component::dump_config() { + LOG_I2C_DEVICE(this); + ESP_LOGCONFIG(TAG, " ALS Gain: X%.0f", GAINVALUES[this->gain_als_]); + ESP_LOGCONFIG(TAG, " ALS Resolution: %u-bit", RESOLUTION_BITS[this->res_als_]); + ESP_LOGCONFIG(TAG, " UV Gain: X%.0f", GAINVALUES[this->gain_uv_]); + ESP_LOGCONFIG(TAG, " UV Resolution: %u-bit", RESOLUTION_BITS[this->res_uv_]); +} void LTR390Component::update() { if (!this->reading_ && !mode_funcs_.empty()) { diff --git a/esphome/components/ltr390/ltr390.h b/esphome/components/ltr390/ltr390.h index bc98518fe9..24afd3c411 100644 --- a/esphome/components/ltr390/ltr390.h +++ b/esphome/components/ltr390/ltr390.h @@ -49,8 +49,10 @@ class LTR390Component : public PollingComponent, public i2c::I2CDevice { void dump_config() override; void update() override; - void set_gain_value(LTR390GAIN gain) { this->gain_ = gain; } - void set_res_value(LTR390RESOLUTION res) { this->res_ = res; } + void set_als_gain_value(LTR390GAIN gain) { this->gain_als_ = gain; } + void set_uv_gain_value(LTR390GAIN gain) { this->gain_uv_ = gain; } + void set_als_res_value(LTR390RESOLUTION res) { this->res_als_ = res; } + void set_uv_res_value(LTR390RESOLUTION res) { this->res_uv_ = res; } void set_wfac_value(float wfac) { this->wfac_ = wfac; } void set_light_sensor(sensor::Sensor *light_sensor) { this->light_sensor_ = light_sensor; } @@ -71,9 +73,11 @@ class LTR390Component : public PollingComponent, public i2c::I2CDevice { // a list of modes and corresponding read functions std::vector>> mode_funcs_; - LTR390GAIN gain_; - LTR390RESOLUTION res_; - float sensitivity_; + LTR390GAIN gain_als_; + LTR390GAIN gain_uv_; + LTR390RESOLUTION res_als_; + LTR390RESOLUTION res_uv_; + float sensitivity_uv_; float wfac_; sensor::Sensor *light_sensor_{nullptr}; diff --git a/esphome/components/ltr390/sensor.py b/esphome/components/ltr390/sensor.py index 8b2676599c..62c3edf8cb 100644 --- a/esphome/components/ltr390/sensor.py +++ b/esphome/components/ltr390/sensor.py @@ -13,7 +13,7 @@ from esphome.const import ( UNIT_LUX, ) -CODEOWNERS = ["@sjtrny"] +CODEOWNERS = ["@sjtrny", "@latonita"] DEPENDENCIES = ["i2c"] ltr390_ns = cg.esphome_ns.namespace("ltr390") @@ -76,8 +76,24 @@ CONFIG_SCHEMA = cv.All( accuracy_decimals=1, device_class=DEVICE_CLASS_EMPTY, ), - cv.Optional(CONF_GAIN, default="X18"): cv.enum(GAIN_OPTIONS), - cv.Optional(CONF_RESOLUTION, default=20): cv.enum(RES_OPTIONS), + cv.Optional(CONF_GAIN, default="X18"): cv.Any( + cv.enum(GAIN_OPTIONS), + cv.Schema( + { + cv.Required(CONF_AMBIENT_LIGHT): cv.enum(GAIN_OPTIONS), + cv.Required(CONF_UV): cv.enum(GAIN_OPTIONS), + } + ), + ), + cv.Optional(CONF_RESOLUTION, default=20): cv.Any( + cv.enum(RES_OPTIONS), + cv.Schema( + { + cv.Required(CONF_AMBIENT_LIGHT): cv.enum(RES_OPTIONS), + cv.Required(CONF_UV): cv.enum(RES_OPTIONS), + } + ), + ), cv.Optional(CONF_WINDOW_CORRECTION_FACTOR, default=1.0): cv.float_range( min=1.0 ), @@ -101,11 +117,25 @@ async def to_code(config): await cg.register_component(var, config) await i2c.register_i2c_device(var, config) - cg.add(var.set_gain_value(config[CONF_GAIN])) - cg.add(var.set_res_value(config[CONF_RESOLUTION])) cg.add(var.set_wfac_value(config[CONF_WINDOW_CORRECTION_FACTOR])) for key, funcName in TYPES.items(): if key in config: sens = await sensor.new_sensor(config[key]) cg.add(getattr(var, funcName)(sens)) + + gain_value = config[CONF_GAIN] + if isinstance(gain_value, dict): + cg.add(var.set_als_gain_value(gain_value[CONF_AMBIENT_LIGHT])) + cg.add(var.set_uv_gain_value(gain_value[CONF_UV])) + else: + cg.add(var.set_als_gain_value(gain_value)) + cg.add(var.set_uv_gain_value(gain_value)) + + res_value = config[CONF_RESOLUTION] + if isinstance(res_value, dict): + cg.add(var.set_als_res_value(res_value[CONF_AMBIENT_LIGHT])) + cg.add(var.set_uv_res_value(res_value[CONF_UV])) + else: + cg.add(var.set_als_res_value(res_value)) + cg.add(var.set_uv_res_value(res_value)) diff --git a/tests/components/ltr390/test.esp32-ard.yaml b/tests/components/ltr390/test.esp32-ard.yaml index 9786c7dac3..bdfe349b77 100644 --- a/tests/components/ltr390/test.esp32-ard.yaml +++ b/tests/components/ltr390/test.esp32-ard.yaml @@ -18,3 +18,21 @@ sensor: window_correction_factor: 1.0 address: 0x53 update_interval: 60s + - platform: ltr390 + uv: + name: LTR390 UV + uv_index: + name: LTR390 UVI + light: + name: LTR390 Light + ambient_light: + name: LTR390 ALS + gain: + ambient_light: X9 + uv: X3 + resolution: + ambient_light: 18 + uv: 13 + window_correction_factor: 1.0 + address: 0x53 + update_interval: 60s diff --git a/tests/components/ltr390/test.esp8266-ard.yaml b/tests/components/ltr390/test.esp8266-ard.yaml index fee0f37ce1..149f46f9c8 100644 --- a/tests/components/ltr390/test.esp8266-ard.yaml +++ b/tests/components/ltr390/test.esp8266-ard.yaml @@ -13,7 +13,9 @@ sensor: name: LTR390 Light ambient_light: name: LTR390 ALS - gain: X3 + gain: + ambient_light: X9 + uv: X3 resolution: 18 window_correction_factor: 1.0 address: 0x53 From bb92ab01d736d8bffa0a2d90713d12ff2f03d774 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Sat, 13 Jul 2024 09:46:08 +1200 Subject: [PATCH 1769/2101] Bump version to 2024.7.0b2 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index d672cc92af..4776de4d67 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.7.0b1" +__version__ = "2024.7.0b2" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 44d609b205c1549ae4c2ab7be31d81b0f67e8755 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Sun, 14 Jul 2024 22:05:02 +0200 Subject: [PATCH 1770/2101] [CI] compile entire web_server during tests (#7084) --- tests/components/web_server/common.yaml | 35 +++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/tests/components/web_server/common.yaml b/tests/components/web_server/common.yaml index 94388726c3..338d9e97d2 100644 --- a/tests/components/web_server/common.yaml +++ b/tests/components/web_server/common.yaml @@ -5,3 +5,38 @@ wifi: web_server: port: 8080 version: 2 + +binary_sensor: +cover: +fan: +light: +sensor: +switch: +button: +text_sensor: +climate: +number: +text: +select: +lock: +valve: +alarm_control_panel: +api: +time: + - platform: homeassistant + id: homeassistant_time +datetime: + - platform: template + id: my_datetime_date + type: date + optimistic: yes + - platform: template + id: my_datetime_time + type: time + optimistic: yes + - platform: template + id: my_datetime + type: datetime + optimistic: yes +event: +update: From 896af84acc967aca74bc3cf832fb4e7da47ad032 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Sun, 14 Jul 2024 15:06:10 -0500 Subject: [PATCH 1771/2101] [improv_serial] Fix linker error created in #6998 (#7082) --- esphome/components/improv_serial/improv_serial_component.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/esphome/components/improv_serial/improv_serial_component.cpp b/esphome/components/improv_serial/improv_serial_component.cpp index 02ffa9f31c..12809e38cb 100644 --- a/esphome/components/improv_serial/improv_serial_component.cpp +++ b/esphome/components/improv_serial/improv_serial_component.cpp @@ -57,7 +57,7 @@ optional ImprovSerialComponent::read_byte_() { } } break; -#ifdef USE_LOGGER_USB_CDC +#if defined(USE_LOGGER_USB_CDC) && defined(CONFIG_ESP_CONSOLE_USB_CDC) case logger::UART_SELECTION_USB_CDC: #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) if (esp_usb_console_available_for_read()) { @@ -99,7 +99,7 @@ void ImprovSerialComponent::write_data_(std::vector &data) { #endif // !USE_ESP32_VARIANT_ESP32C3 && !USE_ESP32_VARIANT_ESP32S2 && !USE_ESP32_VARIANT_ESP32S3 uart_write_bytes(this->uart_num_, data.data(), data.size()); break; -#ifdef USE_LOGGER_USB_CDC +#if defined(USE_LOGGER_USB_CDC) && defined(CONFIG_ESP_CONSOLE_USB_CDC) case logger::UART_SELECTION_USB_CDC: { const char *msg = (char *) data.data(); esp_usb_console_write_buf(msg, data.size()); @@ -109,6 +109,7 @@ void ImprovSerialComponent::write_data_(std::vector &data) { #ifdef USE_LOGGER_USB_SERIAL_JTAG case logger::UART_SELECTION_USB_SERIAL_JTAG: usb_serial_jtag_write_bytes((char *) data.data(), data.size(), 20 / portTICK_PERIOD_MS); + delay(10); usb_serial_jtag_ll_txfifo_flush(); // fixes for issue in IDF 4.4.7 break; #endif // USE_LOGGER_USB_SERIAL_JTAG From 07b78fea760e78e5be5c0dbbf506f2fca490cff0 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Sun, 14 Jul 2024 15:32:10 -0500 Subject: [PATCH 1772/2101] [CI] Add more ``improv_serial`` tests (#7081) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- .../improv_serial/{common.yaml => common-uart0.yaml} | 3 +++ tests/components/improv_serial/common-usb_cdc.yaml | 8 ++++++++ .../components/improv_serial/common-usb_serial_jtag.yaml | 8 ++++++++ tests/components/improv_serial/test-uart0.esp32-ard.yaml | 1 + .../components/improv_serial/test-uart0.esp32-c3-ard.yaml | 1 + .../components/improv_serial/test-uart0.esp32-c3-idf.yaml | 1 + tests/components/improv_serial/test-uart0.esp32-idf.yaml | 1 + .../components/improv_serial/test-uart0.esp32-s2-ard.yaml | 1 + .../components/improv_serial/test-uart0.esp32-s2-idf.yaml | 1 + .../components/improv_serial/test-uart0.esp32-s3-ard.yaml | 1 + .../components/improv_serial/test-uart0.esp32-s3-idf.yaml | 1 + .../components/improv_serial/test-uart0.esp8266-ard.yaml | 1 + tests/components/improv_serial/test-uart0.rp2040-ard.yaml | 1 + .../improv_serial/test-usb_cdc.esp32-c3-ard.yaml | 1 + .../improv_serial/test-usb_cdc.esp32-s2-ard.yaml | 1 + .../improv_serial/test-usb_cdc.esp32-s2-idf.yaml | 1 + .../improv_serial/test-usb_cdc.esp32-s3-ard.yaml | 1 + .../components/improv_serial/test-usb_cdc.rp2040-ard.yaml | 1 + .../improv_serial/test-usb_serial_jtag.esp32-c3-idf.yaml | 1 + .../improv_serial/test-usb_serial_jtag.esp32-s3-idf.yaml | 1 + tests/components/improv_serial/test.esp32-ard.yaml | 1 - tests/components/improv_serial/test.esp32-c3-ard.yaml | 1 - tests/components/improv_serial/test.esp32-c3-idf.yaml | 1 - tests/components/improv_serial/test.esp32-idf.yaml | 1 - tests/components/improv_serial/test.esp8266-ard.yaml | 1 - tests/components/improv_serial/test.rp2040-ard.yaml | 1 - 26 files changed, 36 insertions(+), 6 deletions(-) rename tests/components/improv_serial/{common.yaml => common-uart0.yaml} (64%) create mode 100644 tests/components/improv_serial/common-usb_cdc.yaml create mode 100644 tests/components/improv_serial/common-usb_serial_jtag.yaml create mode 100644 tests/components/improv_serial/test-uart0.esp32-ard.yaml create mode 100644 tests/components/improv_serial/test-uart0.esp32-c3-ard.yaml create mode 100644 tests/components/improv_serial/test-uart0.esp32-c3-idf.yaml create mode 100644 tests/components/improv_serial/test-uart0.esp32-idf.yaml create mode 100644 tests/components/improv_serial/test-uart0.esp32-s2-ard.yaml create mode 100644 tests/components/improv_serial/test-uart0.esp32-s2-idf.yaml create mode 100644 tests/components/improv_serial/test-uart0.esp32-s3-ard.yaml create mode 100644 tests/components/improv_serial/test-uart0.esp32-s3-idf.yaml create mode 100644 tests/components/improv_serial/test-uart0.esp8266-ard.yaml create mode 100644 tests/components/improv_serial/test-uart0.rp2040-ard.yaml create mode 100644 tests/components/improv_serial/test-usb_cdc.esp32-c3-ard.yaml create mode 100644 tests/components/improv_serial/test-usb_cdc.esp32-s2-ard.yaml create mode 100644 tests/components/improv_serial/test-usb_cdc.esp32-s2-idf.yaml create mode 100644 tests/components/improv_serial/test-usb_cdc.esp32-s3-ard.yaml create mode 100644 tests/components/improv_serial/test-usb_cdc.rp2040-ard.yaml create mode 100644 tests/components/improv_serial/test-usb_serial_jtag.esp32-c3-idf.yaml create mode 100644 tests/components/improv_serial/test-usb_serial_jtag.esp32-s3-idf.yaml delete mode 100644 tests/components/improv_serial/test.esp32-ard.yaml delete mode 100644 tests/components/improv_serial/test.esp32-c3-ard.yaml delete mode 100644 tests/components/improv_serial/test.esp32-c3-idf.yaml delete mode 100644 tests/components/improv_serial/test.esp32-idf.yaml delete mode 100644 tests/components/improv_serial/test.esp8266-ard.yaml delete mode 100644 tests/components/improv_serial/test.rp2040-ard.yaml diff --git a/tests/components/improv_serial/common.yaml b/tests/components/improv_serial/common-uart0.yaml similarity index 64% rename from tests/components/improv_serial/common.yaml rename to tests/components/improv_serial/common-uart0.yaml index b36fe5a4a7..7b7730fd46 100644 --- a/tests/components/improv_serial/common.yaml +++ b/tests/components/improv_serial/common-uart0.yaml @@ -2,4 +2,7 @@ wifi: ssid: MySSID password: password1 +logger: + hardware_uart: UART0 + improv_serial: diff --git a/tests/components/improv_serial/common-usb_cdc.yaml b/tests/components/improv_serial/common-usb_cdc.yaml new file mode 100644 index 0000000000..fc72b6aa7e --- /dev/null +++ b/tests/components/improv_serial/common-usb_cdc.yaml @@ -0,0 +1,8 @@ +wifi: + ssid: MySSID + password: password1 + +logger: + hardware_uart: USB_CDC + +improv_serial: diff --git a/tests/components/improv_serial/common-usb_serial_jtag.yaml b/tests/components/improv_serial/common-usb_serial_jtag.yaml new file mode 100644 index 0000000000..0abcc07168 --- /dev/null +++ b/tests/components/improv_serial/common-usb_serial_jtag.yaml @@ -0,0 +1,8 @@ +wifi: + ssid: MySSID + password: password1 + +logger: + hardware_uart: USB_SERIAL_JTAG + +improv_serial: diff --git a/tests/components/improv_serial/test-uart0.esp32-ard.yaml b/tests/components/improv_serial/test-uart0.esp32-ard.yaml new file mode 100644 index 0000000000..ef8c799241 --- /dev/null +++ b/tests/components/improv_serial/test-uart0.esp32-ard.yaml @@ -0,0 +1 @@ +<<: !include common-uart0.yaml diff --git a/tests/components/improv_serial/test-uart0.esp32-c3-ard.yaml b/tests/components/improv_serial/test-uart0.esp32-c3-ard.yaml new file mode 100644 index 0000000000..ef8c799241 --- /dev/null +++ b/tests/components/improv_serial/test-uart0.esp32-c3-ard.yaml @@ -0,0 +1 @@ +<<: !include common-uart0.yaml diff --git a/tests/components/improv_serial/test-uart0.esp32-c3-idf.yaml b/tests/components/improv_serial/test-uart0.esp32-c3-idf.yaml new file mode 100644 index 0000000000..ef8c799241 --- /dev/null +++ b/tests/components/improv_serial/test-uart0.esp32-c3-idf.yaml @@ -0,0 +1 @@ +<<: !include common-uart0.yaml diff --git a/tests/components/improv_serial/test-uart0.esp32-idf.yaml b/tests/components/improv_serial/test-uart0.esp32-idf.yaml new file mode 100644 index 0000000000..ef8c799241 --- /dev/null +++ b/tests/components/improv_serial/test-uart0.esp32-idf.yaml @@ -0,0 +1 @@ +<<: !include common-uart0.yaml diff --git a/tests/components/improv_serial/test-uart0.esp32-s2-ard.yaml b/tests/components/improv_serial/test-uart0.esp32-s2-ard.yaml new file mode 100644 index 0000000000..ef8c799241 --- /dev/null +++ b/tests/components/improv_serial/test-uart0.esp32-s2-ard.yaml @@ -0,0 +1 @@ +<<: !include common-uart0.yaml diff --git a/tests/components/improv_serial/test-uart0.esp32-s2-idf.yaml b/tests/components/improv_serial/test-uart0.esp32-s2-idf.yaml new file mode 100644 index 0000000000..ef8c799241 --- /dev/null +++ b/tests/components/improv_serial/test-uart0.esp32-s2-idf.yaml @@ -0,0 +1 @@ +<<: !include common-uart0.yaml diff --git a/tests/components/improv_serial/test-uart0.esp32-s3-ard.yaml b/tests/components/improv_serial/test-uart0.esp32-s3-ard.yaml new file mode 100644 index 0000000000..ef8c799241 --- /dev/null +++ b/tests/components/improv_serial/test-uart0.esp32-s3-ard.yaml @@ -0,0 +1 @@ +<<: !include common-uart0.yaml diff --git a/tests/components/improv_serial/test-uart0.esp32-s3-idf.yaml b/tests/components/improv_serial/test-uart0.esp32-s3-idf.yaml new file mode 100644 index 0000000000..ef8c799241 --- /dev/null +++ b/tests/components/improv_serial/test-uart0.esp32-s3-idf.yaml @@ -0,0 +1 @@ +<<: !include common-uart0.yaml diff --git a/tests/components/improv_serial/test-uart0.esp8266-ard.yaml b/tests/components/improv_serial/test-uart0.esp8266-ard.yaml new file mode 100644 index 0000000000..ef8c799241 --- /dev/null +++ b/tests/components/improv_serial/test-uart0.esp8266-ard.yaml @@ -0,0 +1 @@ +<<: !include common-uart0.yaml diff --git a/tests/components/improv_serial/test-uart0.rp2040-ard.yaml b/tests/components/improv_serial/test-uart0.rp2040-ard.yaml new file mode 100644 index 0000000000..ef8c799241 --- /dev/null +++ b/tests/components/improv_serial/test-uart0.rp2040-ard.yaml @@ -0,0 +1 @@ +<<: !include common-uart0.yaml diff --git a/tests/components/improv_serial/test-usb_cdc.esp32-c3-ard.yaml b/tests/components/improv_serial/test-usb_cdc.esp32-c3-ard.yaml new file mode 100644 index 0000000000..cfdaec9771 --- /dev/null +++ b/tests/components/improv_serial/test-usb_cdc.esp32-c3-ard.yaml @@ -0,0 +1 @@ +<<: !include common-usb_cdc.yaml diff --git a/tests/components/improv_serial/test-usb_cdc.esp32-s2-ard.yaml b/tests/components/improv_serial/test-usb_cdc.esp32-s2-ard.yaml new file mode 100644 index 0000000000..cfdaec9771 --- /dev/null +++ b/tests/components/improv_serial/test-usb_cdc.esp32-s2-ard.yaml @@ -0,0 +1 @@ +<<: !include common-usb_cdc.yaml diff --git a/tests/components/improv_serial/test-usb_cdc.esp32-s2-idf.yaml b/tests/components/improv_serial/test-usb_cdc.esp32-s2-idf.yaml new file mode 100644 index 0000000000..cfdaec9771 --- /dev/null +++ b/tests/components/improv_serial/test-usb_cdc.esp32-s2-idf.yaml @@ -0,0 +1 @@ +<<: !include common-usb_cdc.yaml diff --git a/tests/components/improv_serial/test-usb_cdc.esp32-s3-ard.yaml b/tests/components/improv_serial/test-usb_cdc.esp32-s3-ard.yaml new file mode 100644 index 0000000000..cfdaec9771 --- /dev/null +++ b/tests/components/improv_serial/test-usb_cdc.esp32-s3-ard.yaml @@ -0,0 +1 @@ +<<: !include common-usb_cdc.yaml diff --git a/tests/components/improv_serial/test-usb_cdc.rp2040-ard.yaml b/tests/components/improv_serial/test-usb_cdc.rp2040-ard.yaml new file mode 100644 index 0000000000..cfdaec9771 --- /dev/null +++ b/tests/components/improv_serial/test-usb_cdc.rp2040-ard.yaml @@ -0,0 +1 @@ +<<: !include common-usb_cdc.yaml diff --git a/tests/components/improv_serial/test-usb_serial_jtag.esp32-c3-idf.yaml b/tests/components/improv_serial/test-usb_serial_jtag.esp32-c3-idf.yaml new file mode 100644 index 0000000000..46a927ff10 --- /dev/null +++ b/tests/components/improv_serial/test-usb_serial_jtag.esp32-c3-idf.yaml @@ -0,0 +1 @@ +<<: !include common-usb_serial_jtag.yaml diff --git a/tests/components/improv_serial/test-usb_serial_jtag.esp32-s3-idf.yaml b/tests/components/improv_serial/test-usb_serial_jtag.esp32-s3-idf.yaml new file mode 100644 index 0000000000..46a927ff10 --- /dev/null +++ b/tests/components/improv_serial/test-usb_serial_jtag.esp32-s3-idf.yaml @@ -0,0 +1 @@ +<<: !include common-usb_serial_jtag.yaml diff --git a/tests/components/improv_serial/test.esp32-ard.yaml b/tests/components/improv_serial/test.esp32-ard.yaml deleted file mode 100644 index dade44d145..0000000000 --- a/tests/components/improv_serial/test.esp32-ard.yaml +++ /dev/null @@ -1 +0,0 @@ -<<: !include common.yaml diff --git a/tests/components/improv_serial/test.esp32-c3-ard.yaml b/tests/components/improv_serial/test.esp32-c3-ard.yaml deleted file mode 100644 index dade44d145..0000000000 --- a/tests/components/improv_serial/test.esp32-c3-ard.yaml +++ /dev/null @@ -1 +0,0 @@ -<<: !include common.yaml diff --git a/tests/components/improv_serial/test.esp32-c3-idf.yaml b/tests/components/improv_serial/test.esp32-c3-idf.yaml deleted file mode 100644 index dade44d145..0000000000 --- a/tests/components/improv_serial/test.esp32-c3-idf.yaml +++ /dev/null @@ -1 +0,0 @@ -<<: !include common.yaml diff --git a/tests/components/improv_serial/test.esp32-idf.yaml b/tests/components/improv_serial/test.esp32-idf.yaml deleted file mode 100644 index dade44d145..0000000000 --- a/tests/components/improv_serial/test.esp32-idf.yaml +++ /dev/null @@ -1 +0,0 @@ -<<: !include common.yaml diff --git a/tests/components/improv_serial/test.esp8266-ard.yaml b/tests/components/improv_serial/test.esp8266-ard.yaml deleted file mode 100644 index dade44d145..0000000000 --- a/tests/components/improv_serial/test.esp8266-ard.yaml +++ /dev/null @@ -1 +0,0 @@ -<<: !include common.yaml diff --git a/tests/components/improv_serial/test.rp2040-ard.yaml b/tests/components/improv_serial/test.rp2040-ard.yaml deleted file mode 100644 index dade44d145..0000000000 --- a/tests/components/improv_serial/test.rp2040-ard.yaml +++ /dev/null @@ -1 +0,0 @@ -<<: !include common.yaml From f1d19416be8753ff189562f5719b3e96a783414f Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 16 Jul 2024 16:28:41 +1200 Subject: [PATCH 1773/2101] [i2s_audio] Allow config for primary/secondary i2s mode (#7092) --- esphome/components/i2s_audio/__init__.py | 10 ++++++++++ esphome/components/i2s_audio/microphone/__init__.py | 7 +++++++ .../i2s_audio/microphone/i2s_audio_microphone.cpp | 5 ++--- .../i2s_audio/microphone/i2s_audio_microphone.h | 3 +++ 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/esphome/components/i2s_audio/__init__.py b/esphome/components/i2s_audio/__init__.py index d72e13630f..05e44696d8 100644 --- a/esphome/components/i2s_audio/__init__.py +++ b/esphome/components/i2s_audio/__init__.py @@ -25,6 +25,10 @@ CONF_I2S_LRCLK_PIN = "i2s_lrclk_pin" CONF_I2S_AUDIO = "i2s_audio" CONF_I2S_AUDIO_ID = "i2s_audio_id" +CONF_I2S_MODE = "i2s_mode" +CONF_PRIMARY = "primary" +CONF_SECONDARY = "secondary" + i2s_audio_ns = cg.esphome_ns.namespace("i2s_audio") I2SAudioComponent = i2s_audio_ns.class_("I2SAudioComponent", cg.Component) I2SAudioIn = i2s_audio_ns.class_("I2SAudioIn", cg.Parented.template(I2SAudioComponent)) @@ -32,6 +36,12 @@ I2SAudioOut = i2s_audio_ns.class_( "I2SAudioOut", cg.Parented.template(I2SAudioComponent) ) +i2s_mode_t = cg.global_ns.enum("i2s_mode_t") +I2S_MODE_OPTIONS = { + CONF_PRIMARY: i2s_mode_t.I2S_MODE_MASTER, # NOLINT + CONF_SECONDARY: i2s_mode_t.I2S_MODE_SLAVE, # NOLINT +} + # https://github.com/espressif/esp-idf/blob/master/components/soc/{variant}/include/soc/soc_caps.h I2S_PORTS = { VARIANT_ESP32: 2, diff --git a/esphome/components/i2s_audio/microphone/__init__.py b/esphome/components/i2s_audio/microphone/__init__.py index d9c31e8e7b..844f176bea 100644 --- a/esphome/components/i2s_audio/microphone/__init__.py +++ b/esphome/components/i2s_audio/microphone/__init__.py @@ -7,6 +7,9 @@ from esphome.components import microphone, esp32 from esphome.components.adc import ESP32_VARIANT_ADC1_PIN_TO_CHANNEL, validate_adc_pin from .. import ( + CONF_I2S_MODE, + CONF_PRIMARY, + I2S_MODE_OPTIONS, i2s_audio_ns, I2SAudioComponent, I2SAudioIn, @@ -68,6 +71,9 @@ BASE_SCHEMA = microphone.MICROPHONE_SCHEMA.extend( _validate_bits, cv.enum(BITS_PER_SAMPLE) ), cv.Optional(CONF_USE_APLL, default=False): cv.boolean, + cv.Optional(CONF_I2S_MODE, default=CONF_PRIMARY): cv.enum( + I2S_MODE_OPTIONS, lower=True + ), } ).extend(cv.COMPONENT_SCHEMA) @@ -107,6 +113,7 @@ async def to_code(config): cg.add(var.set_din_pin(config[CONF_I2S_DIN_PIN])) cg.add(var.set_pdm(config[CONF_PDM])) + cg.add(var.set_i2s_mode(config[CONF_I2S_MODE])) cg.add(var.set_channel(config[CONF_CHANNEL])) cg.add(var.set_sample_rate(config[CONF_SAMPLE_RATE])) cg.add(var.set_bits_per_sample(config[CONF_BITS_PER_SAMPLE])) diff --git a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp index a672348d85..009fecdf90 100644 --- a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +++ b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp @@ -46,7 +46,7 @@ void I2SAudioMicrophone::start_() { return; // Waiting for another i2s to return lock } i2s_driver_config_t config = { - .mode = (i2s_mode_t) (I2S_MODE_MASTER | I2S_MODE_RX), + .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_, @@ -174,8 +174,7 @@ size_t I2SAudioMicrophone::read(int16_t *buf, size_t len) { size_t samples_read = bytes_read / sizeof(int32_t); samples.resize(samples_read); for (size_t i = 0; i < samples_read; i++) { - int32_t temp = reinterpret_cast(buf)[i] >> 14; - samples[i] = clamp(temp, INT16_MIN, INT16_MAX); + samples[i] = reinterpret_cast(buf)[i] >> 16; } memcpy(buf, samples.data(), samples_read * sizeof(int16_t)); return samples_read * sizeof(int16_t); diff --git a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.h b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.h index 68b9a94fbd..07ca0528aa 100644 --- a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.h +++ b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.h @@ -30,6 +30,8 @@ class I2SAudioMicrophone : public I2SAudioIn, public microphone::Microphone, pub } #endif + 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_sample_rate(uint32_t sample_rate) { this->sample_rate_ = sample_rate; } void set_bits_per_sample(i2s_bits_per_sample_t bits_per_sample) { this->bits_per_sample_ = bits_per_sample; } @@ -46,6 +48,7 @@ class I2SAudioMicrophone : public I2SAudioIn, public microphone::Microphone, pub bool adc_{false}; #endif bool pdm_{false}; + i2s_mode_t i2s_mode_{}; i2s_channel_fmt_t channel_; uint32_t sample_rate_; i2s_bits_per_sample_t bits_per_sample_; From c910fdf7e52354e8d4945bdeac44cd2000448d4c Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 16 Jul 2024 16:29:45 +1200 Subject: [PATCH 1774/2101] [micro_wake_word] Allow simpler model config (#7094) --- esphome/components/micro_wake_word/__init__.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/esphome/components/micro_wake_word/__init__.py b/esphome/components/micro_wake_word/__init__.py index 3d3459ccab..c2faca25f4 100644 --- a/esphome/components/micro_wake_word/__init__.py +++ b/esphome/components/micro_wake_word/__init__.py @@ -357,7 +357,9 @@ CONFIG_SCHEMA = cv.All( { cv.GenerateID(): cv.declare_id(MicroWakeWord), cv.GenerateID(CONF_MICROPHONE): cv.use_id(microphone.Microphone), - cv.Required(CONF_MODELS): cv.ensure_list(MODEL_SCHEMA), + cv.Required(CONF_MODELS): cv.ensure_list( + cv.maybe_simple_value(MODEL_SCHEMA, key=CONF_MODEL) + ), cv.Optional(CONF_ON_WAKE_WORD_DETECTED): automation.validate_automation( single=True ), From eaf2bb70d9008d040427ec446cf9c4f7e515d524 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Sun, 14 Jul 2024 15:06:10 -0500 Subject: [PATCH 1775/2101] [improv_serial] Fix linker error created in #6998 (#7082) --- esphome/components/improv_serial/improv_serial_component.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/esphome/components/improv_serial/improv_serial_component.cpp b/esphome/components/improv_serial/improv_serial_component.cpp index 02ffa9f31c..12809e38cb 100644 --- a/esphome/components/improv_serial/improv_serial_component.cpp +++ b/esphome/components/improv_serial/improv_serial_component.cpp @@ -57,7 +57,7 @@ optional ImprovSerialComponent::read_byte_() { } } break; -#ifdef USE_LOGGER_USB_CDC +#if defined(USE_LOGGER_USB_CDC) && defined(CONFIG_ESP_CONSOLE_USB_CDC) case logger::UART_SELECTION_USB_CDC: #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) if (esp_usb_console_available_for_read()) { @@ -99,7 +99,7 @@ void ImprovSerialComponent::write_data_(std::vector &data) { #endif // !USE_ESP32_VARIANT_ESP32C3 && !USE_ESP32_VARIANT_ESP32S2 && !USE_ESP32_VARIANT_ESP32S3 uart_write_bytes(this->uart_num_, data.data(), data.size()); break; -#ifdef USE_LOGGER_USB_CDC +#if defined(USE_LOGGER_USB_CDC) && defined(CONFIG_ESP_CONSOLE_USB_CDC) case logger::UART_SELECTION_USB_CDC: { const char *msg = (char *) data.data(); esp_usb_console_write_buf(msg, data.size()); @@ -109,6 +109,7 @@ void ImprovSerialComponent::write_data_(std::vector &data) { #ifdef USE_LOGGER_USB_SERIAL_JTAG case logger::UART_SELECTION_USB_SERIAL_JTAG: usb_serial_jtag_write_bytes((char *) data.data(), data.size(), 20 / portTICK_PERIOD_MS); + delay(10); usb_serial_jtag_ll_txfifo_flush(); // fixes for issue in IDF 4.4.7 break; #endif // USE_LOGGER_USB_SERIAL_JTAG From 41baf7066040900571bee2caeb5388578ce70268 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 16 Jul 2024 16:28:41 +1200 Subject: [PATCH 1776/2101] [i2s_audio] Allow config for primary/secondary i2s mode (#7092) --- esphome/components/i2s_audio/__init__.py | 10 ++++++++++ esphome/components/i2s_audio/microphone/__init__.py | 7 +++++++ .../i2s_audio/microphone/i2s_audio_microphone.cpp | 5 ++--- .../i2s_audio/microphone/i2s_audio_microphone.h | 3 +++ 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/esphome/components/i2s_audio/__init__.py b/esphome/components/i2s_audio/__init__.py index d72e13630f..05e44696d8 100644 --- a/esphome/components/i2s_audio/__init__.py +++ b/esphome/components/i2s_audio/__init__.py @@ -25,6 +25,10 @@ CONF_I2S_LRCLK_PIN = "i2s_lrclk_pin" CONF_I2S_AUDIO = "i2s_audio" CONF_I2S_AUDIO_ID = "i2s_audio_id" +CONF_I2S_MODE = "i2s_mode" +CONF_PRIMARY = "primary" +CONF_SECONDARY = "secondary" + i2s_audio_ns = cg.esphome_ns.namespace("i2s_audio") I2SAudioComponent = i2s_audio_ns.class_("I2SAudioComponent", cg.Component) I2SAudioIn = i2s_audio_ns.class_("I2SAudioIn", cg.Parented.template(I2SAudioComponent)) @@ -32,6 +36,12 @@ I2SAudioOut = i2s_audio_ns.class_( "I2SAudioOut", cg.Parented.template(I2SAudioComponent) ) +i2s_mode_t = cg.global_ns.enum("i2s_mode_t") +I2S_MODE_OPTIONS = { + CONF_PRIMARY: i2s_mode_t.I2S_MODE_MASTER, # NOLINT + CONF_SECONDARY: i2s_mode_t.I2S_MODE_SLAVE, # NOLINT +} + # https://github.com/espressif/esp-idf/blob/master/components/soc/{variant}/include/soc/soc_caps.h I2S_PORTS = { VARIANT_ESP32: 2, diff --git a/esphome/components/i2s_audio/microphone/__init__.py b/esphome/components/i2s_audio/microphone/__init__.py index d9c31e8e7b..844f176bea 100644 --- a/esphome/components/i2s_audio/microphone/__init__.py +++ b/esphome/components/i2s_audio/microphone/__init__.py @@ -7,6 +7,9 @@ from esphome.components import microphone, esp32 from esphome.components.adc import ESP32_VARIANT_ADC1_PIN_TO_CHANNEL, validate_adc_pin from .. import ( + CONF_I2S_MODE, + CONF_PRIMARY, + I2S_MODE_OPTIONS, i2s_audio_ns, I2SAudioComponent, I2SAudioIn, @@ -68,6 +71,9 @@ BASE_SCHEMA = microphone.MICROPHONE_SCHEMA.extend( _validate_bits, cv.enum(BITS_PER_SAMPLE) ), cv.Optional(CONF_USE_APLL, default=False): cv.boolean, + cv.Optional(CONF_I2S_MODE, default=CONF_PRIMARY): cv.enum( + I2S_MODE_OPTIONS, lower=True + ), } ).extend(cv.COMPONENT_SCHEMA) @@ -107,6 +113,7 @@ async def to_code(config): cg.add(var.set_din_pin(config[CONF_I2S_DIN_PIN])) cg.add(var.set_pdm(config[CONF_PDM])) + cg.add(var.set_i2s_mode(config[CONF_I2S_MODE])) cg.add(var.set_channel(config[CONF_CHANNEL])) cg.add(var.set_sample_rate(config[CONF_SAMPLE_RATE])) cg.add(var.set_bits_per_sample(config[CONF_BITS_PER_SAMPLE])) diff --git a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp index a672348d85..009fecdf90 100644 --- a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +++ b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp @@ -46,7 +46,7 @@ void I2SAudioMicrophone::start_() { return; // Waiting for another i2s to return lock } i2s_driver_config_t config = { - .mode = (i2s_mode_t) (I2S_MODE_MASTER | I2S_MODE_RX), + .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_, @@ -174,8 +174,7 @@ size_t I2SAudioMicrophone::read(int16_t *buf, size_t len) { size_t samples_read = bytes_read / sizeof(int32_t); samples.resize(samples_read); for (size_t i = 0; i < samples_read; i++) { - int32_t temp = reinterpret_cast(buf)[i] >> 14; - samples[i] = clamp(temp, INT16_MIN, INT16_MAX); + samples[i] = reinterpret_cast(buf)[i] >> 16; } memcpy(buf, samples.data(), samples_read * sizeof(int16_t)); return samples_read * sizeof(int16_t); diff --git a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.h b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.h index 68b9a94fbd..07ca0528aa 100644 --- a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.h +++ b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.h @@ -30,6 +30,8 @@ class I2SAudioMicrophone : public I2SAudioIn, public microphone::Microphone, pub } #endif + 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_sample_rate(uint32_t sample_rate) { this->sample_rate_ = sample_rate; } void set_bits_per_sample(i2s_bits_per_sample_t bits_per_sample) { this->bits_per_sample_ = bits_per_sample; } @@ -46,6 +48,7 @@ class I2SAudioMicrophone : public I2SAudioIn, public microphone::Microphone, pub bool adc_{false}; #endif bool pdm_{false}; + i2s_mode_t i2s_mode_{}; i2s_channel_fmt_t channel_; uint32_t sample_rate_; i2s_bits_per_sample_t bits_per_sample_; From 0bbefb5b2a08f0f6b163f4d86c05b025e704b648 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 16 Jul 2024 16:29:45 +1200 Subject: [PATCH 1777/2101] [micro_wake_word] Allow simpler model config (#7094) --- esphome/components/micro_wake_word/__init__.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/esphome/components/micro_wake_word/__init__.py b/esphome/components/micro_wake_word/__init__.py index 3d3459ccab..c2faca25f4 100644 --- a/esphome/components/micro_wake_word/__init__.py +++ b/esphome/components/micro_wake_word/__init__.py @@ -357,7 +357,9 @@ CONFIG_SCHEMA = cv.All( { cv.GenerateID(): cv.declare_id(MicroWakeWord), cv.GenerateID(CONF_MICROPHONE): cv.use_id(microphone.Microphone), - cv.Required(CONF_MODELS): cv.ensure_list(MODEL_SCHEMA), + cv.Required(CONF_MODELS): cv.ensure_list( + cv.maybe_simple_value(MODEL_SCHEMA, key=CONF_MODEL) + ), cv.Optional(CONF_ON_WAKE_WORD_DETECTED): automation.validate_automation( single=True ), From 4af8230b4f1b8c420caf53e7270d9f8e31d988c4 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 16 Jul 2024 16:51:13 +1200 Subject: [PATCH 1778/2101] Bump version to 2024.7.0b3 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 4776de4d67..dacd839eab 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.7.0b2" +__version__ = "2024.7.0b3" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 0b3fe73b74b44f0be4f282a4cbe74252ba51453c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Jul 2024 17:13:02 +1200 Subject: [PATCH 1779/2101] Bump docker/build-push-action from 6.3.0 to 6.4.0 in /.github/actions/build-image (#7089) 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 d5baf339aa..ac9a6ae53a 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -46,7 +46,7 @@ runs: - name: Build and push to ghcr by digest id: build-ghcr - uses: docker/build-push-action@v6.3.0 + uses: docker/build-push-action@v6.4.0 with: context: . file: ./docker/Dockerfile @@ -69,7 +69,7 @@ runs: - name: Build and push to dockerhub by digest id: build-dockerhub - uses: docker/build-push-action@v6.3.0 + uses: docker/build-push-action@v6.4.0 with: context: . file: ./docker/Dockerfile From 8980996b1aa84316e71b8ba5dea26c38c7b3f364 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Tue, 16 Jul 2024 07:14:33 +0200 Subject: [PATCH 1780/2101] [CI] add web_server v1 test (#7090) --- tests/components/web_server/common.yaml | 4 ---- tests/components/web_server/common_v1.yaml | 5 +++++ tests/components/web_server/common_v2.yaml | 5 +++++ tests/components/web_server/test.esp32-ard.yaml | 2 +- tests/components/web_server/test.esp32-c3-ard.yaml | 2 +- tests/components/web_server/test.esp32-c3-idf.yaml | 2 +- tests/components/web_server/test.esp32-idf.yaml | 2 +- tests/components/web_server/test.esp8266-ard.yaml | 2 +- tests/components/web_server/test_v1.esp32-ard.yaml | 1 + 9 files changed, 16 insertions(+), 9 deletions(-) create mode 100644 tests/components/web_server/common_v1.yaml create mode 100644 tests/components/web_server/common_v2.yaml create mode 100644 tests/components/web_server/test_v1.esp32-ard.yaml diff --git a/tests/components/web_server/common.yaml b/tests/components/web_server/common.yaml index 338d9e97d2..eb768eeb91 100644 --- a/tests/components/web_server/common.yaml +++ b/tests/components/web_server/common.yaml @@ -2,10 +2,6 @@ wifi: ssid: MySSID password: password1 -web_server: - port: 8080 - version: 2 - binary_sensor: cover: fan: diff --git a/tests/components/web_server/common_v1.yaml b/tests/components/web_server/common_v1.yaml new file mode 100644 index 0000000000..bf5aab4ce6 --- /dev/null +++ b/tests/components/web_server/common_v1.yaml @@ -0,0 +1,5 @@ +<<: !include common.yaml + +web_server: + port: 8080 + version: 1 diff --git a/tests/components/web_server/common_v2.yaml b/tests/components/web_server/common_v2.yaml new file mode 100644 index 0000000000..564c43e553 --- /dev/null +++ b/tests/components/web_server/common_v2.yaml @@ -0,0 +1,5 @@ +<<: !include common.yaml + +web_server: + port: 8080 + version: 2 diff --git a/tests/components/web_server/test.esp32-ard.yaml b/tests/components/web_server/test.esp32-ard.yaml index dade44d145..7e6658e20e 100644 --- a/tests/components/web_server/test.esp32-ard.yaml +++ b/tests/components/web_server/test.esp32-ard.yaml @@ -1 +1 @@ -<<: !include common.yaml +<<: !include common_v2.yaml diff --git a/tests/components/web_server/test.esp32-c3-ard.yaml b/tests/components/web_server/test.esp32-c3-ard.yaml index dade44d145..7e6658e20e 100644 --- a/tests/components/web_server/test.esp32-c3-ard.yaml +++ b/tests/components/web_server/test.esp32-c3-ard.yaml @@ -1 +1 @@ -<<: !include common.yaml +<<: !include common_v2.yaml diff --git a/tests/components/web_server/test.esp32-c3-idf.yaml b/tests/components/web_server/test.esp32-c3-idf.yaml index dade44d145..7e6658e20e 100644 --- a/tests/components/web_server/test.esp32-c3-idf.yaml +++ b/tests/components/web_server/test.esp32-c3-idf.yaml @@ -1 +1 @@ -<<: !include common.yaml +<<: !include common_v2.yaml diff --git a/tests/components/web_server/test.esp32-idf.yaml b/tests/components/web_server/test.esp32-idf.yaml index dade44d145..7e6658e20e 100644 --- a/tests/components/web_server/test.esp32-idf.yaml +++ b/tests/components/web_server/test.esp32-idf.yaml @@ -1 +1 @@ -<<: !include common.yaml +<<: !include common_v2.yaml diff --git a/tests/components/web_server/test.esp8266-ard.yaml b/tests/components/web_server/test.esp8266-ard.yaml index dade44d145..7e6658e20e 100644 --- a/tests/components/web_server/test.esp8266-ard.yaml +++ b/tests/components/web_server/test.esp8266-ard.yaml @@ -1 +1 @@ -<<: !include common.yaml +<<: !include common_v2.yaml diff --git a/tests/components/web_server/test_v1.esp32-ard.yaml b/tests/components/web_server/test_v1.esp32-ard.yaml new file mode 100644 index 0000000000..389a930284 --- /dev/null +++ b/tests/components/web_server/test_v1.esp32-ard.yaml @@ -0,0 +1 @@ +<<: !include common_v1.yaml From 659fdefccb851fa9e76d560b7574e5589b890d24 Mon Sep 17 00:00:00 2001 From: NewoPL <27411874+NewoPL@users.noreply.github.com> Date: Tue, 16 Jul 2024 08:28:23 +0200 Subject: [PATCH 1781/2101] [wifi] Hostname may not be set as expected on Arduino platform (#7050) * bug #6014: workaround for not setting hostname on arduino plarform * moving handle initailisation to ESPHOME_EVENT_ID_WIFI_STA_START callback --- esphome/components/wifi/wifi_component_esp32_arduino.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/esphome/components/wifi/wifi_component_esp32_arduino.cpp b/esphome/components/wifi/wifi_component_esp32_arduino.cpp index fc954a2333..71548b7a3e 100644 --- a/esphome/components/wifi/wifi_component_esp32_arduino.cpp +++ b/esphome/components/wifi/wifi_component_esp32_arduino.cpp @@ -82,8 +82,8 @@ bool WiFiComponent::wifi_mode_(optional sta, optional ap) { // WiFiClass::mode above calls esp_netif_create_default_wifi_sta() and // esp_netif_create_default_wifi_ap(), which creates the interfaces. - if (set_sta) - s_sta_netif = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"); + // s_sta_netif handle is set during ESPHOME_EVENT_ID_WIFI_STA_START event + #ifdef USE_WIFI_AP if (set_ap) s_ap_netif = esp_netif_get_handle_from_ifkey("WIFI_AP_DEF"); @@ -495,6 +495,7 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_ case ESPHOME_EVENT_ID_WIFI_STA_START: { ESP_LOGV(TAG, "Event: WiFi STA start"); // apply hostname + s_sta_netif = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"); esp_err_t err = esp_netif_set_hostname(s_sta_netif, App.get_name().c_str()); if (err != ERR_OK) { ESP_LOGW(TAG, "esp_netif_set_hostname failed: %s", esp_err_to_name(err)); From 193db50668d7f343e5ae22bcf6e3a5b1e2309adf Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 16 Jul 2024 19:18:43 +1200 Subject: [PATCH 1782/2101] [ota] Print Arduino update errors (#7096) --- .../ota/ota_backend_arduino_esp32.cpp | 29 ++++++++++++----- .../ota/ota_backend_arduino_esp8266.cpp | 31 ++++++++++++++----- .../ota/ota_backend_arduino_libretiny.cpp | 29 ++++++++++++----- .../ota/ota_backend_arduino_rp2040.cpp | 29 ++++++++++++----- 4 files changed, 89 insertions(+), 29 deletions(-) diff --git a/esphome/components/ota/ota_backend_arduino_esp32.cpp b/esphome/components/ota/ota_backend_arduino_esp32.cpp index 62c6a72388..15dfc98a6c 100644 --- a/esphome/components/ota/ota_backend_arduino_esp32.cpp +++ b/esphome/components/ota/ota_backend_arduino_esp32.cpp @@ -1,14 +1,17 @@ #ifdef USE_ESP32_FRAMEWORK_ARDUINO #include "esphome/core/defines.h" +#include "esphome/core/log.h" -#include "ota_backend_arduino_esp32.h" #include "ota_backend.h" +#include "ota_backend_arduino_esp32.h" #include namespace esphome { namespace ota { +static const char *const TAG = "ota.arduino_esp32"; + std::unique_ptr make_ota_backend() { return make_unique(); } OTAResponseTypes ArduinoESP32OTABackend::begin(size_t image_size) { @@ -20,6 +23,9 @@ OTAResponseTypes ArduinoESP32OTABackend::begin(size_t image_size) { uint8_t error = Update.getError(); if (error == UPDATE_ERROR_SIZE) return OTA_RESPONSE_ERROR_ESP32_NOT_ENOUGH_SPACE; + + ESP_LOGE(TAG, "Begin error: %d", error); + return OTA_RESPONSE_ERROR_UNKNOWN; } @@ -27,16 +33,25 @@ void ArduinoESP32OTABackend::set_update_md5(const char *md5) { Update.setMD5(md5 OTAResponseTypes ArduinoESP32OTABackend::write(uint8_t *data, size_t len) { size_t written = Update.write(data, len); - if (written != len) { - return OTA_RESPONSE_ERROR_WRITING_FLASH; + if (written == len) { + return OTA_RESPONSE_OK; } - return OTA_RESPONSE_OK; + + uint8_t error = Update.getError(); + ESP_LOGE(TAG, "Write error: %d", error); + + return OTA_RESPONSE_ERROR_WRITING_FLASH; } OTAResponseTypes ArduinoESP32OTABackend::end() { - if (!Update.end()) - return OTA_RESPONSE_ERROR_UPDATE_END; - return OTA_RESPONSE_OK; + if (Update.end()) { + return OTA_RESPONSE_OK; + } + + uint8_t error = Update.getError(); + ESP_LOGE(TAG, "End error: %d", error); + + return OTA_RESPONSE_ERROR_UPDATE_END; } void ArduinoESP32OTABackend::abort() { Update.abort(); } diff --git a/esphome/components/ota/ota_backend_arduino_esp8266.cpp b/esphome/components/ota/ota_backend_arduino_esp8266.cpp index b317075bd0..42edbf5d2b 100644 --- a/esphome/components/ota/ota_backend_arduino_esp8266.cpp +++ b/esphome/components/ota/ota_backend_arduino_esp8266.cpp @@ -1,16 +1,19 @@ #ifdef USE_ARDUINO #ifdef USE_ESP8266 -#include "ota_backend.h" #include "ota_backend_arduino_esp8266.h" +#include "ota_backend.h" -#include "esphome/core/defines.h" #include "esphome/components/esp8266/preferences.h" +#include "esphome/core/defines.h" +#include "esphome/core/log.h" #include namespace esphome { namespace ota { +static const char *const TAG = "ota.arduino_esp8266"; + std::unique_ptr make_ota_backend() { return make_unique(); } OTAResponseTypes ArduinoESP8266OTABackend::begin(size_t image_size) { @@ -29,6 +32,9 @@ OTAResponseTypes ArduinoESP8266OTABackend::begin(size_t image_size) { return OTA_RESPONSE_ERROR_WRONG_CURRENT_FLASH_CONFIG; if (error == UPDATE_ERROR_SPACE) return OTA_RESPONSE_ERROR_ESP8266_NOT_ENOUGH_SPACE; + + ESP_LOGE(TAG, "Begin error: %d", error); + return OTA_RESPONSE_ERROR_UNKNOWN; } @@ -36,16 +42,25 @@ void ArduinoESP8266OTABackend::set_update_md5(const char *md5) { Update.setMD5(m OTAResponseTypes ArduinoESP8266OTABackend::write(uint8_t *data, size_t len) { size_t written = Update.write(data, len); - if (written != len) { - return OTA_RESPONSE_ERROR_WRITING_FLASH; + if (written == len) { + return OTA_RESPONSE_OK; } - return OTA_RESPONSE_OK; + + uint8_t error = Update.getError(); + ESP_LOGE(TAG, "Write error: %d", error); + + return OTA_RESPONSE_ERROR_WRITING_FLASH; } OTAResponseTypes ArduinoESP8266OTABackend::end() { - if (!Update.end()) - return OTA_RESPONSE_ERROR_UPDATE_END; - return OTA_RESPONSE_OK; + if (Update.end()) { + return OTA_RESPONSE_OK; + } + + uint8_t error = Update.getError(); + ESP_LOGE(TAG, "End error: %d", error); + + return OTA_RESPONSE_ERROR_UPDATE_END; } void ArduinoESP8266OTABackend::abort() { diff --git a/esphome/components/ota/ota_backend_arduino_libretiny.cpp b/esphome/components/ota/ota_backend_arduino_libretiny.cpp index df4e774ebc..6b2cf80684 100644 --- a/esphome/components/ota/ota_backend_arduino_libretiny.cpp +++ b/esphome/components/ota/ota_backend_arduino_libretiny.cpp @@ -1,14 +1,17 @@ #ifdef USE_LIBRETINY -#include "ota_backend.h" #include "ota_backend_arduino_libretiny.h" +#include "ota_backend.h" #include "esphome/core/defines.h" +#include "esphome/core/log.h" #include namespace esphome { namespace ota { +static const char *const TAG = "ota.arduino_libretiny"; + std::unique_ptr make_ota_backend() { return make_unique(); } OTAResponseTypes ArduinoLibreTinyOTABackend::begin(size_t image_size) { @@ -20,6 +23,9 @@ OTAResponseTypes ArduinoLibreTinyOTABackend::begin(size_t image_size) { uint8_t error = Update.getError(); if (error == UPDATE_ERROR_SIZE) return OTA_RESPONSE_ERROR_ESP32_NOT_ENOUGH_SPACE; + + ESP_LOGE(TAG, "Begin error: %d", error); + return OTA_RESPONSE_ERROR_UNKNOWN; } @@ -27,16 +33,25 @@ void ArduinoLibreTinyOTABackend::set_update_md5(const char *md5) { Update.setMD5 OTAResponseTypes ArduinoLibreTinyOTABackend::write(uint8_t *data, size_t len) { size_t written = Update.write(data, len); - if (written != len) { - return OTA_RESPONSE_ERROR_WRITING_FLASH; + if (written == len) { + return OTA_RESPONSE_OK; } - return OTA_RESPONSE_OK; + + uint8_t error = Update.getError(); + ESP_LOGE(TAG, "Write error: %d", error); + + return OTA_RESPONSE_ERROR_WRITING_FLASH; } OTAResponseTypes ArduinoLibreTinyOTABackend::end() { - if (!Update.end()) - return OTA_RESPONSE_ERROR_UPDATE_END; - return OTA_RESPONSE_OK; + if (Update.end()) { + return OTA_RESPONSE_OK; + } + + uint8_t error = Update.getError(); + ESP_LOGE(TAG, "End error: %d", error); + + return OTA_RESPONSE_ERROR_UPDATE_END; } void ArduinoLibreTinyOTABackend::abort() { Update.abort(); } diff --git a/esphome/components/ota/ota_backend_arduino_rp2040.cpp b/esphome/components/ota/ota_backend_arduino_rp2040.cpp index 4448b0c95e..ffeab2e93f 100644 --- a/esphome/components/ota/ota_backend_arduino_rp2040.cpp +++ b/esphome/components/ota/ota_backend_arduino_rp2040.cpp @@ -1,16 +1,19 @@ #ifdef USE_ARDUINO #ifdef USE_RP2040 -#include "ota_backend.h" #include "ota_backend_arduino_rp2040.h" +#include "ota_backend.h" #include "esphome/components/rp2040/preferences.h" #include "esphome/core/defines.h" +#include "esphome/core/log.h" #include namespace esphome { namespace ota { +static const char *const TAG = "ota.arduino_rp2040"; + std::unique_ptr make_ota_backend() { return make_unique(); } OTAResponseTypes ArduinoRP2040OTABackend::begin(size_t image_size) { @@ -29,6 +32,9 @@ OTAResponseTypes ArduinoRP2040OTABackend::begin(size_t image_size) { return OTA_RESPONSE_ERROR_WRONG_CURRENT_FLASH_CONFIG; if (error == UPDATE_ERROR_SPACE) return OTA_RESPONSE_ERROR_RP2040_NOT_ENOUGH_SPACE; + + ESP_LOGE(TAG, "Begin error: %d", error); + return OTA_RESPONSE_ERROR_UNKNOWN; } @@ -36,16 +42,25 @@ void ArduinoRP2040OTABackend::set_update_md5(const char *md5) { Update.setMD5(md OTAResponseTypes ArduinoRP2040OTABackend::write(uint8_t *data, size_t len) { size_t written = Update.write(data, len); - if (written != len) { - return OTA_RESPONSE_ERROR_WRITING_FLASH; + if (written == len) { + return OTA_RESPONSE_OK; } - return OTA_RESPONSE_OK; + + uint8_t error = Update.getError(); + ESP_LOGE(TAG, "Write error: %d", error); + + return OTA_RESPONSE_ERROR_WRITING_FLASH; } OTAResponseTypes ArduinoRP2040OTABackend::end() { - if (!Update.end()) - return OTA_RESPONSE_ERROR_UPDATE_END; - return OTA_RESPONSE_OK; + if (Update.end()) { + return OTA_RESPONSE_OK; + } + + uint8_t error = Update.getError(); + ESP_LOGE(TAG, "End error: %d", error); + + return OTA_RESPONSE_ERROR_UPDATE_END; } void ArduinoRP2040OTABackend::abort() { From 10205e06cb1de3b65e81dfcdc5a20fe890155162 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Tue, 16 Jul 2024 19:06:27 +1000 Subject: [PATCH 1783/2101] Add host uart support for MacOS (#7095) --- esphome/components/uart/uart_component_host.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/esphome/components/uart/uart_component_host.cpp b/esphome/components/uart/uart_component_host.cpp index d8d2fd75b8..40d3e91ab2 100644 --- a/esphome/components/uart/uart_component_host.cpp +++ b/esphome/components/uart/uart_component_host.cpp @@ -5,8 +5,8 @@ #include "esphome/core/helpers.h" #include "esphome/core/log.h" -#ifndef __linux__ -#error This HostUartComponent implementation is only for Linux +#if !(defined(__linux__) || defined(__APPLE__)) +#error This HostUartComponent implementation is not supported on this host OS #endif #include @@ -24,6 +24,9 @@ namespace { speed_t get_baud(int baud) { +#ifdef __APPLE__ + return baud; +#else switch (baud) { case 50: return B50; @@ -88,6 +91,7 @@ speed_t get_baud(int baud) { default: return B0; } +#endif } } // namespace From f153a7b0fd20bdf9a6b0772553c99f05021b04b7 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 16 Jul 2024 19:18:43 +1200 Subject: [PATCH 1784/2101] [ota] Print Arduino update errors (#7096) --- .../ota/ota_backend_arduino_esp32.cpp | 29 ++++++++++++----- .../ota/ota_backend_arduino_esp8266.cpp | 31 ++++++++++++++----- .../ota/ota_backend_arduino_libretiny.cpp | 29 ++++++++++++----- .../ota/ota_backend_arduino_rp2040.cpp | 29 ++++++++++++----- 4 files changed, 89 insertions(+), 29 deletions(-) diff --git a/esphome/components/ota/ota_backend_arduino_esp32.cpp b/esphome/components/ota/ota_backend_arduino_esp32.cpp index 62c6a72388..15dfc98a6c 100644 --- a/esphome/components/ota/ota_backend_arduino_esp32.cpp +++ b/esphome/components/ota/ota_backend_arduino_esp32.cpp @@ -1,14 +1,17 @@ #ifdef USE_ESP32_FRAMEWORK_ARDUINO #include "esphome/core/defines.h" +#include "esphome/core/log.h" -#include "ota_backend_arduino_esp32.h" #include "ota_backend.h" +#include "ota_backend_arduino_esp32.h" #include namespace esphome { namespace ota { +static const char *const TAG = "ota.arduino_esp32"; + std::unique_ptr make_ota_backend() { return make_unique(); } OTAResponseTypes ArduinoESP32OTABackend::begin(size_t image_size) { @@ -20,6 +23,9 @@ OTAResponseTypes ArduinoESP32OTABackend::begin(size_t image_size) { uint8_t error = Update.getError(); if (error == UPDATE_ERROR_SIZE) return OTA_RESPONSE_ERROR_ESP32_NOT_ENOUGH_SPACE; + + ESP_LOGE(TAG, "Begin error: %d", error); + return OTA_RESPONSE_ERROR_UNKNOWN; } @@ -27,16 +33,25 @@ void ArduinoESP32OTABackend::set_update_md5(const char *md5) { Update.setMD5(md5 OTAResponseTypes ArduinoESP32OTABackend::write(uint8_t *data, size_t len) { size_t written = Update.write(data, len); - if (written != len) { - return OTA_RESPONSE_ERROR_WRITING_FLASH; + if (written == len) { + return OTA_RESPONSE_OK; } - return OTA_RESPONSE_OK; + + uint8_t error = Update.getError(); + ESP_LOGE(TAG, "Write error: %d", error); + + return OTA_RESPONSE_ERROR_WRITING_FLASH; } OTAResponseTypes ArduinoESP32OTABackend::end() { - if (!Update.end()) - return OTA_RESPONSE_ERROR_UPDATE_END; - return OTA_RESPONSE_OK; + if (Update.end()) { + return OTA_RESPONSE_OK; + } + + uint8_t error = Update.getError(); + ESP_LOGE(TAG, "End error: %d", error); + + return OTA_RESPONSE_ERROR_UPDATE_END; } void ArduinoESP32OTABackend::abort() { Update.abort(); } diff --git a/esphome/components/ota/ota_backend_arduino_esp8266.cpp b/esphome/components/ota/ota_backend_arduino_esp8266.cpp index b317075bd0..42edbf5d2b 100644 --- a/esphome/components/ota/ota_backend_arduino_esp8266.cpp +++ b/esphome/components/ota/ota_backend_arduino_esp8266.cpp @@ -1,16 +1,19 @@ #ifdef USE_ARDUINO #ifdef USE_ESP8266 -#include "ota_backend.h" #include "ota_backend_arduino_esp8266.h" +#include "ota_backend.h" -#include "esphome/core/defines.h" #include "esphome/components/esp8266/preferences.h" +#include "esphome/core/defines.h" +#include "esphome/core/log.h" #include namespace esphome { namespace ota { +static const char *const TAG = "ota.arduino_esp8266"; + std::unique_ptr make_ota_backend() { return make_unique(); } OTAResponseTypes ArduinoESP8266OTABackend::begin(size_t image_size) { @@ -29,6 +32,9 @@ OTAResponseTypes ArduinoESP8266OTABackend::begin(size_t image_size) { return OTA_RESPONSE_ERROR_WRONG_CURRENT_FLASH_CONFIG; if (error == UPDATE_ERROR_SPACE) return OTA_RESPONSE_ERROR_ESP8266_NOT_ENOUGH_SPACE; + + ESP_LOGE(TAG, "Begin error: %d", error); + return OTA_RESPONSE_ERROR_UNKNOWN; } @@ -36,16 +42,25 @@ void ArduinoESP8266OTABackend::set_update_md5(const char *md5) { Update.setMD5(m OTAResponseTypes ArduinoESP8266OTABackend::write(uint8_t *data, size_t len) { size_t written = Update.write(data, len); - if (written != len) { - return OTA_RESPONSE_ERROR_WRITING_FLASH; + if (written == len) { + return OTA_RESPONSE_OK; } - return OTA_RESPONSE_OK; + + uint8_t error = Update.getError(); + ESP_LOGE(TAG, "Write error: %d", error); + + return OTA_RESPONSE_ERROR_WRITING_FLASH; } OTAResponseTypes ArduinoESP8266OTABackend::end() { - if (!Update.end()) - return OTA_RESPONSE_ERROR_UPDATE_END; - return OTA_RESPONSE_OK; + if (Update.end()) { + return OTA_RESPONSE_OK; + } + + uint8_t error = Update.getError(); + ESP_LOGE(TAG, "End error: %d", error); + + return OTA_RESPONSE_ERROR_UPDATE_END; } void ArduinoESP8266OTABackend::abort() { diff --git a/esphome/components/ota/ota_backend_arduino_libretiny.cpp b/esphome/components/ota/ota_backend_arduino_libretiny.cpp index df4e774ebc..6b2cf80684 100644 --- a/esphome/components/ota/ota_backend_arduino_libretiny.cpp +++ b/esphome/components/ota/ota_backend_arduino_libretiny.cpp @@ -1,14 +1,17 @@ #ifdef USE_LIBRETINY -#include "ota_backend.h" #include "ota_backend_arduino_libretiny.h" +#include "ota_backend.h" #include "esphome/core/defines.h" +#include "esphome/core/log.h" #include namespace esphome { namespace ota { +static const char *const TAG = "ota.arduino_libretiny"; + std::unique_ptr make_ota_backend() { return make_unique(); } OTAResponseTypes ArduinoLibreTinyOTABackend::begin(size_t image_size) { @@ -20,6 +23,9 @@ OTAResponseTypes ArduinoLibreTinyOTABackend::begin(size_t image_size) { uint8_t error = Update.getError(); if (error == UPDATE_ERROR_SIZE) return OTA_RESPONSE_ERROR_ESP32_NOT_ENOUGH_SPACE; + + ESP_LOGE(TAG, "Begin error: %d", error); + return OTA_RESPONSE_ERROR_UNKNOWN; } @@ -27,16 +33,25 @@ void ArduinoLibreTinyOTABackend::set_update_md5(const char *md5) { Update.setMD5 OTAResponseTypes ArduinoLibreTinyOTABackend::write(uint8_t *data, size_t len) { size_t written = Update.write(data, len); - if (written != len) { - return OTA_RESPONSE_ERROR_WRITING_FLASH; + if (written == len) { + return OTA_RESPONSE_OK; } - return OTA_RESPONSE_OK; + + uint8_t error = Update.getError(); + ESP_LOGE(TAG, "Write error: %d", error); + + return OTA_RESPONSE_ERROR_WRITING_FLASH; } OTAResponseTypes ArduinoLibreTinyOTABackend::end() { - if (!Update.end()) - return OTA_RESPONSE_ERROR_UPDATE_END; - return OTA_RESPONSE_OK; + if (Update.end()) { + return OTA_RESPONSE_OK; + } + + uint8_t error = Update.getError(); + ESP_LOGE(TAG, "End error: %d", error); + + return OTA_RESPONSE_ERROR_UPDATE_END; } void ArduinoLibreTinyOTABackend::abort() { Update.abort(); } diff --git a/esphome/components/ota/ota_backend_arduino_rp2040.cpp b/esphome/components/ota/ota_backend_arduino_rp2040.cpp index 4448b0c95e..ffeab2e93f 100644 --- a/esphome/components/ota/ota_backend_arduino_rp2040.cpp +++ b/esphome/components/ota/ota_backend_arduino_rp2040.cpp @@ -1,16 +1,19 @@ #ifdef USE_ARDUINO #ifdef USE_RP2040 -#include "ota_backend.h" #include "ota_backend_arduino_rp2040.h" +#include "ota_backend.h" #include "esphome/components/rp2040/preferences.h" #include "esphome/core/defines.h" +#include "esphome/core/log.h" #include namespace esphome { namespace ota { +static const char *const TAG = "ota.arduino_rp2040"; + std::unique_ptr make_ota_backend() { return make_unique(); } OTAResponseTypes ArduinoRP2040OTABackend::begin(size_t image_size) { @@ -29,6 +32,9 @@ OTAResponseTypes ArduinoRP2040OTABackend::begin(size_t image_size) { return OTA_RESPONSE_ERROR_WRONG_CURRENT_FLASH_CONFIG; if (error == UPDATE_ERROR_SPACE) return OTA_RESPONSE_ERROR_RP2040_NOT_ENOUGH_SPACE; + + ESP_LOGE(TAG, "Begin error: %d", error); + return OTA_RESPONSE_ERROR_UNKNOWN; } @@ -36,16 +42,25 @@ void ArduinoRP2040OTABackend::set_update_md5(const char *md5) { Update.setMD5(md OTAResponseTypes ArduinoRP2040OTABackend::write(uint8_t *data, size_t len) { size_t written = Update.write(data, len); - if (written != len) { - return OTA_RESPONSE_ERROR_WRITING_FLASH; + if (written == len) { + return OTA_RESPONSE_OK; } - return OTA_RESPONSE_OK; + + uint8_t error = Update.getError(); + ESP_LOGE(TAG, "Write error: %d", error); + + return OTA_RESPONSE_ERROR_WRITING_FLASH; } OTAResponseTypes ArduinoRP2040OTABackend::end() { - if (!Update.end()) - return OTA_RESPONSE_ERROR_UPDATE_END; - return OTA_RESPONSE_OK; + if (Update.end()) { + return OTA_RESPONSE_OK; + } + + uint8_t error = Update.getError(); + ESP_LOGE(TAG, "End error: %d", error); + + return OTA_RESPONSE_ERROR_UPDATE_END; } void ArduinoRP2040OTABackend::abort() { From c512d5ebb66346cea81144b207408f19936f006d Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 17 Jul 2024 11:15:19 +1200 Subject: [PATCH 1785/2101] Bump version to 2024.7.0b4 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index dacd839eab..b59a2e9517 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.7.0b3" +__version__ = "2024.7.0b4" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From e15d0ee150e879e2a6dce7b53ad7d35a2d500624 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 17 Jul 2024 14:54:44 +1200 Subject: [PATCH 1786/2101] Bump version to 2024.7.0 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index b59a2e9517..d581f68470 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.7.0b4" +__version__ = "2024.7.0" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From dd20c5eab0ca2441e7911ae85638a5a8237534cc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 18 Jul 2024 15:33:30 +1200 Subject: [PATCH 1787/2101] Bump docker/build-push-action from 6.4.0 to 6.4.1 in /.github/actions/build-image (#7102) 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 ac9a6ae53a..e2febdad1b 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -46,7 +46,7 @@ runs: - name: Build and push to ghcr by digest id: build-ghcr - uses: docker/build-push-action@v6.4.0 + uses: docker/build-push-action@v6.4.1 with: context: . file: ./docker/Dockerfile @@ -69,7 +69,7 @@ runs: - name: Build and push to dockerhub by digest id: build-dockerhub - uses: docker/build-push-action@v6.4.0 + uses: docker/build-push-action@v6.4.1 with: context: . file: ./docker/Dockerfile From b32078a5fe8b05f6f3bf4234b24ec8b3a6871d02 Mon Sep 17 00:00:00 2001 From: Alex Cortelyou <1689668+acortelyou@users.noreply.github.com> Date: Thu, 18 Jul 2024 15:04:11 -0700 Subject: [PATCH 1788/2101] Prevent rename from deleting new config (#7104) --- esphome/__main__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/esphome/__main__.py b/esphome/__main__.py index 5ff1a28ec7..b13f96daf7 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -695,7 +695,8 @@ def command_rename(args, config): os.remove(new_path) return 1 - os.remove(CORE.config_path) + if CORE.config_path != new_path: + os.remove(CORE.config_path) print(color(Fore.BOLD_GREEN, "SUCCESS")) print() From 0fb89d186964bc31b28b9873d3245981d19ce8df Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 19 Jul 2024 11:26:21 +1200 Subject: [PATCH 1789/2101] [code-quality] Add some ruff configuration (#7103) --- pyproject.toml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index fe558f695f..cfc279845f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -105,3 +105,33 @@ disable = [ [tool.pylint.FORMAT] expected-line-ending-format = "LF" + +[tool.ruff] +required-version = ">=0.5.0" + +[tool.ruff.lint] +select = [ + "E", # pycodestyle + "F", # pyflakes/autoflake + "I", # isort + "PL", # pylint + "UP", # pyupgrade +] + +ignore = [ + "E501", # line too long + "PLR0911", # Too many return statements ({returns} > {max_returns}) + "PLR0912", # Too many branches ({branches} > {max_branches}) + "PLR0913", # Too many arguments to function call ({c_args} > {max_args}) + "PLR0915", # Too many statements ({statements} > {max_statements}) + "PLR2004", # Magic value used in comparison, consider replacing {value} with a constant variable + "PLW2901", # Outer {outer_kind} variable {name} overwritten by inner {inner_kind} target +] + +[tool.ruff.lint.isort] +force-sort-within-sections = true +known-first-party = [ + "esphome", +] +combine-as-imports = true +split-on-trailing-comma = false From c5b77f45902c7a3497278ecbadc6c4b799927d11 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Fri, 19 Jul 2024 06:35:41 +0200 Subject: [PATCH 1790/2101] [web_server] move v1 code to separate file (#7091) --- esphome/components/web_server/web_server.cpp | 209 ----------------- .../components/web_server/web_server_v1.cpp | 217 ++++++++++++++++++ 2 files changed, 217 insertions(+), 209 deletions(-) create mode 100644 esphome/components/web_server/web_server_v1.cpp diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index 9a1641e86f..6fb04f558a 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -46,29 +46,6 @@ static const char *const HEADER_CORS_REQ_PNA = "Access-Control-Request-Private-N static const char *const HEADER_CORS_ALLOW_PNA = "Access-Control-Allow-Private-Network"; #endif -#if USE_WEBSERVER_VERSION == 1 -void write_row(AsyncResponseStream *stream, EntityBase *obj, const std::string &klass, const std::string &action, - const std::function &action_func = nullptr) { - stream->print("print(klass.c_str()); - if (obj->is_internal()) - stream->print(" internal"); - stream->print("\" id=\""); - stream->print(klass.c_str()); - stream->print("-"); - stream->print(obj->get_object_id().c_str()); - stream->print("\">"); - stream->print(obj->get_name().c_str()); - stream->print(""); - stream->print(action.c_str()); - if (action_func) { - action_func(*stream, obj); - } - stream->print(""); - stream->print(""); -} -#endif - UrlMatch match_url(const std::string &url, bool only_domain = false) { UrlMatch match; match.valid = false; @@ -102,11 +79,6 @@ WebServer::WebServer(web_server_base::WebServerBase *base) #endif } -#if USE_WEBSERVER_VERSION == 1 -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; } -#endif - #ifdef USE_WEBSERVER_CSS_INCLUDE void WebServer::set_css_include(const char *css_include) { this->css_include_ = css_include; } #endif @@ -181,187 +153,6 @@ void WebServer::handle_index_request(AsyncWebServerRequest *request) { response->addHeader("Content-Encoding", "gzip"); request->send(response); } -#elif USE_WEBSERVER_VERSION == 1 -void WebServer::handle_index_request(AsyncWebServerRequest *request) { - AsyncResponseStream *stream = request->beginResponseStream("text/html"); - const std::string &title = App.get_name(); - stream->print(F("")); - stream->print(title.c_str()); - stream->print(F("")); -#ifdef USE_WEBSERVER_CSS_INCLUDE - stream->print(F("")); -#endif - if (strlen(this->css_url_) > 0) { - stream->print(F(R"(print(this->css_url_); - stream->print(F("\">")); - } - stream->print(F("")); - stream->print(F("

")); - stream->print(title.c_str()); - stream->print(F("

")); - stream->print(F("

States

")); - -#ifdef USE_SENSOR - for (auto *obj : App.get_sensors()) { - if (this->include_internal_ || !obj->is_internal()) - write_row(stream, obj, "sensor", ""); - } -#endif - -#ifdef USE_SWITCH - for (auto *obj : App.get_switches()) { - if (this->include_internal_ || !obj->is_internal()) - write_row(stream, obj, "switch", ""); - } -#endif - -#ifdef USE_BUTTON - for (auto *obj : App.get_buttons()) - write_row(stream, obj, "button", ""); -#endif - -#ifdef USE_BINARY_SENSOR - for (auto *obj : App.get_binary_sensors()) { - if (this->include_internal_ || !obj->is_internal()) - write_row(stream, obj, "binary_sensor", ""); - } -#endif - -#ifdef USE_FAN - for (auto *obj : App.get_fans()) { - if (this->include_internal_ || !obj->is_internal()) - write_row(stream, obj, "fan", ""); - } -#endif - -#ifdef USE_LIGHT - for (auto *obj : App.get_lights()) { - if (this->include_internal_ || !obj->is_internal()) - write_row(stream, obj, "light", ""); - } -#endif - -#ifdef USE_TEXT_SENSOR - for (auto *obj : App.get_text_sensors()) { - if (this->include_internal_ || !obj->is_internal()) - write_row(stream, obj, "text_sensor", ""); - } -#endif - -#ifdef USE_COVER - for (auto *obj : App.get_covers()) { - if (this->include_internal_ || !obj->is_internal()) - write_row(stream, obj, "cover", ""); - } -#endif - -#ifdef USE_NUMBER - for (auto *obj : App.get_numbers()) { - if (this->include_internal_ || !obj->is_internal()) { - write_row(stream, obj, "number", "", [](AsyncResponseStream &stream, EntityBase *obj) { - number::Number *number = (number::Number *) obj; - stream.print(R"(traits.get_min_value()); - stream.print(R"(" max=")"); - stream.print(number->traits.get_max_value()); - stream.print(R"(" step=")"); - stream.print(number->traits.get_step()); - stream.print(R"(" value=")"); - stream.print(number->state); - stream.print(R"("/>)"); - }); - } - } -#endif - -#ifdef USE_TEXT - for (auto *obj : App.get_texts()) { - if (this->include_internal_ || !obj->is_internal()) { - write_row(stream, obj, "text", "", [](AsyncResponseStream &stream, EntityBase *obj) { - text::Text *text = (text::Text *) obj; - auto mode = (int) text->traits.get_mode(); - stream.print(R"(traits.get_min_length()); - stream.print(R"(" maxlength=")"); - stream.print(text->traits.get_max_length()); - stream.print(R"(" pattern=")"); - stream.print(text->traits.get_pattern().c_str()); - stream.print(R"(" value=")"); - stream.print(text->state.c_str()); - stream.print(R"("/>)"); - }); - } - } -#endif - -#ifdef USE_SELECT - for (auto *obj : App.get_selects()) { - if (this->include_internal_ || !obj->is_internal()) { - write_row(stream, obj, "select", "", [](AsyncResponseStream &stream, EntityBase *obj) { - select::Select *select = (select::Select *) obj; - stream.print(""); - }); - } - } -#endif - -#ifdef USE_LOCK - for (auto *obj : App.get_locks()) { - if (this->include_internal_ || !obj->is_internal()) { - write_row(stream, obj, "lock", "", [](AsyncResponseStream &stream, EntityBase *obj) { - lock::Lock *lock = (lock::Lock *) obj; - stream.print(""); - if (lock->traits.get_supports_open()) { - stream.print(""); - } - }); - } - } -#endif - -#ifdef USE_CLIMATE - for (auto *obj : App.get_climates()) { - if (this->include_internal_ || !obj->is_internal()) - write_row(stream, obj, "climate", ""); - } -#endif - - stream->print(F("
NameStateActions

See ESPHome Web API for " - "REST API documentation.

")); - if (this->allow_ota_) { - stream->print( - F("

OTA Update

")); - } - stream->print(F("

Debug Log

"));
-#ifdef USE_WEBSERVER_JS_INCLUDE
-  if (this->js_include_ != nullptr) {
-    stream->print(F(""));
-  }
-#endif
-  if (strlen(this->js_url_) > 0) {
-    stream->print(F(""));
-  }
-  stream->print(F("
")); - request->send(stream); -} #elif USE_WEBSERVER_VERSION >= 2 void WebServer::handle_index_request(AsyncWebServerRequest *request) { AsyncWebServerResponse *response = diff --git a/esphome/components/web_server/web_server_v1.cpp b/esphome/components/web_server/web_server_v1.cpp new file mode 100644 index 0000000000..c9b38a2dc4 --- /dev/null +++ b/esphome/components/web_server/web_server_v1.cpp @@ -0,0 +1,217 @@ +#include "web_server.h" +#include "esphome/core/application.h" + +#if USE_WEBSERVER_VERSION == 1 + +namespace esphome { +namespace web_server { + +void write_row(AsyncResponseStream *stream, EntityBase *obj, const std::string &klass, const std::string &action, + const std::function &action_func = nullptr) { + stream->print("print(klass.c_str()); + if (obj->is_internal()) + stream->print(" internal"); + stream->print("\" id=\""); + stream->print(klass.c_str()); + stream->print("-"); + stream->print(obj->get_object_id().c_str()); + stream->print("\">"); + stream->print(obj->get_name().c_str()); + stream->print(""); + stream->print(action.c_str()); + if (action_func) { + action_func(*stream, obj); + } + stream->print(""); + stream->print(""); +} + +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"); + const std::string &title = App.get_name(); + stream->print(F("")); + stream->print(title.c_str()); + stream->print(F("")); +#ifdef USE_WEBSERVER_CSS_INCLUDE + stream->print(F("")); +#endif + if (strlen(this->css_url_) > 0) { + stream->print(F(R"(print(this->css_url_); + stream->print(F("\">")); + } + stream->print(F("")); + stream->print(F("

")); + stream->print(title.c_str()); + stream->print(F("

")); + stream->print(F("

States

")); + +#ifdef USE_SENSOR + for (auto *obj : App.get_sensors()) { + if (this->include_internal_ || !obj->is_internal()) + write_row(stream, obj, "sensor", ""); + } +#endif + +#ifdef USE_SWITCH + for (auto *obj : App.get_switches()) { + if (this->include_internal_ || !obj->is_internal()) + write_row(stream, obj, "switch", ""); + } +#endif + +#ifdef USE_BUTTON + for (auto *obj : App.get_buttons()) + write_row(stream, obj, "button", ""); +#endif + +#ifdef USE_BINARY_SENSOR + for (auto *obj : App.get_binary_sensors()) { + if (this->include_internal_ || !obj->is_internal()) + write_row(stream, obj, "binary_sensor", ""); + } +#endif + +#ifdef USE_FAN + for (auto *obj : App.get_fans()) { + if (this->include_internal_ || !obj->is_internal()) + write_row(stream, obj, "fan", ""); + } +#endif + +#ifdef USE_LIGHT + for (auto *obj : App.get_lights()) { + if (this->include_internal_ || !obj->is_internal()) + write_row(stream, obj, "light", ""); + } +#endif + +#ifdef USE_TEXT_SENSOR + for (auto *obj : App.get_text_sensors()) { + if (this->include_internal_ || !obj->is_internal()) + write_row(stream, obj, "text_sensor", ""); + } +#endif + +#ifdef USE_COVER + for (auto *obj : App.get_covers()) { + if (this->include_internal_ || !obj->is_internal()) + write_row(stream, obj, "cover", ""); + } +#endif + +#ifdef USE_NUMBER + for (auto *obj : App.get_numbers()) { + if (this->include_internal_ || !obj->is_internal()) { + write_row(stream, obj, "number", "", [](AsyncResponseStream &stream, EntityBase *obj) { + number::Number *number = (number::Number *) obj; + stream.print(R"(traits.get_min_value()); + stream.print(R"(" max=")"); + stream.print(number->traits.get_max_value()); + stream.print(R"(" step=")"); + stream.print(number->traits.get_step()); + stream.print(R"(" value=")"); + stream.print(number->state); + stream.print(R"("/>)"); + }); + } + } +#endif + +#ifdef USE_TEXT + for (auto *obj : App.get_texts()) { + if (this->include_internal_ || !obj->is_internal()) { + write_row(stream, obj, "text", "", [](AsyncResponseStream &stream, EntityBase *obj) { + text::Text *text = (text::Text *) obj; + auto mode = (int) text->traits.get_mode(); + stream.print(R"(traits.get_min_length()); + stream.print(R"(" maxlength=")"); + stream.print(text->traits.get_max_length()); + stream.print(R"(" pattern=")"); + stream.print(text->traits.get_pattern().c_str()); + stream.print(R"(" value=")"); + stream.print(text->state.c_str()); + stream.print(R"("/>)"); + }); + } + } +#endif + +#ifdef USE_SELECT + for (auto *obj : App.get_selects()) { + if (this->include_internal_ || !obj->is_internal()) { + write_row(stream, obj, "select", "", [](AsyncResponseStream &stream, EntityBase *obj) { + select::Select *select = (select::Select *) obj; + stream.print(""); + }); + } + } +#endif + +#ifdef USE_LOCK + for (auto *obj : App.get_locks()) { + if (this->include_internal_ || !obj->is_internal()) { + write_row(stream, obj, "lock", "", [](AsyncResponseStream &stream, EntityBase *obj) { + lock::Lock *lock = (lock::Lock *) obj; + stream.print(""); + if (lock->traits.get_supports_open()) { + stream.print(""); + } + }); + } + } +#endif + +#ifdef USE_CLIMATE + for (auto *obj : App.get_climates()) { + if (this->include_internal_ || !obj->is_internal()) + write_row(stream, obj, "climate", ""); + } +#endif + + stream->print(F("
NameStateActions

See ESPHome Web API for " + "REST API documentation.

")); + if (this->allow_ota_) { + stream->print( + F("

OTA Update

")); + } + stream->print(F("

Debug Log

"));
+#ifdef USE_WEBSERVER_JS_INCLUDE
+  if (this->js_include_ != nullptr) {
+    stream->print(F(""));
+  }
+#endif
+  if (strlen(this->js_url_) > 0) {
+    stream->print(F(""));
+  }
+  stream->print(F("
")); + request->send(stream); +} + +} // namespace web_server +} // namespace esphome +#endif From 32b927de7e319a4a1357a047959d365ccb85e919 Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt Date: Fri, 19 Jul 2024 15:15:11 -0400 Subject: [PATCH 1791/2101] revert bit shift to match previous behavior (#7109) --- .../components/i2s_audio/microphone/i2s_audio_microphone.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp index 009fecdf90..cb49a744fc 100644 --- a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +++ b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp @@ -174,7 +174,8 @@ size_t I2SAudioMicrophone::read(int16_t *buf, size_t len) { size_t samples_read = bytes_read / sizeof(int32_t); samples.resize(samples_read); for (size_t i = 0; i < samples_read; i++) { - samples[i] = reinterpret_cast(buf)[i] >> 16; + int32_t temp = reinterpret_cast(buf)[i] >> 14; + samples[i] = clamp(temp, INT16_MIN, INT16_MAX); } memcpy(buf, samples.data(), samples_read * sizeof(int16_t)); return samples_read * sizeof(int16_t); From 43b818f2b1ca949ccc1ec216db9b5682e051541c Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 22 Jul 2024 07:54:16 +1200 Subject: [PATCH 1792/2101] [validation] Add ``host`` to ``require_framework_version`` (#7107) --- esphome/config_validation.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/esphome/config_validation.py b/esphome/config_validation.py index 7259e3c062..3ef92ad460 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -829,7 +829,6 @@ def time_of_day(value): def date_time(date: bool, time: bool): - pattern_str = r"^" # Start of string if date: pattern_str += r"\d{4}-\d{1,2}-\d{1,2}" @@ -2031,6 +2030,7 @@ def require_framework_version( esp32_arduino=None, esp8266_arduino=None, rp2040_arduino=None, + host=None, max_version=False, extra_message=None, ): @@ -2065,6 +2065,13 @@ def require_framework_version( msg += f". {extra_message}" raise Invalid(msg) required = rp2040_arduino + elif CORE.is_host and framework == "host": + if host is None: + msg = "This feature is incompatible with host platform" + if extra_message: + msg += f". {extra_message}" + raise Invalid(msg) + required = host else: raise Invalid( f""" From cfb20abb9f0e7fc0b25b4cc792a560b4d91eb748 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 22 Jul 2024 08:09:06 +1200 Subject: [PATCH 1793/2101] [code-quality] Tidy up some duplicate CONFIG_SCHEMA assignments (#7106) --- esphome/components/ade7953/sensor.py | 2 +- esphome/components/bmp3xx/sensor.py | 2 +- esphome/components/ens160/sensor.py | 2 +- esphome/components/kalman_combinator/sensor.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/ade7953/sensor.py b/esphome/components/ade7953/sensor.py index 0caa2ef454..fc79888129 100644 --- a/esphome/components/ade7953/sensor.py +++ b/esphome/components/ade7953/sensor.py @@ -1,5 +1,5 @@ import esphome.config_validation as cv -CONFIG_SCHEMA = CONFIG_SCHEMA = cv.invalid( +CONFIG_SCHEMA = cv.invalid( "The ade7953 sensor component has been renamed to ade7953_i2c." ) diff --git a/esphome/components/bmp3xx/sensor.py b/esphome/components/bmp3xx/sensor.py index 89753768c3..3c7927f1a8 100644 --- a/esphome/components/bmp3xx/sensor.py +++ b/esphome/components/bmp3xx/sensor.py @@ -2,6 +2,6 @@ import esphome.config_validation as cv CODEOWNERS = ["@latonita"] -CONFIG_SCHEMA = CONFIG_SCHEMA = cv.invalid( +CONFIG_SCHEMA = cv.invalid( "The bmp3xx sensor component has been renamed to bmp3xx_i2c." ) diff --git a/esphome/components/ens160/sensor.py b/esphome/components/ens160/sensor.py index f666b530b3..441671fb7b 100644 --- a/esphome/components/ens160/sensor.py +++ b/esphome/components/ens160/sensor.py @@ -2,6 +2,6 @@ import esphome.config_validation as cv CODEOWNERS = ["@latonita"] -CONFIG_SCHEMA = CONFIG_SCHEMA = cv.invalid( +CONFIG_SCHEMA = cv.invalid( "The ens160 sensor component has been renamed to ens160_i2c." ) diff --git a/esphome/components/kalman_combinator/sensor.py b/esphome/components/kalman_combinator/sensor.py index eca1ba7b85..c19a17462d 100644 --- a/esphome/components/kalman_combinator/sensor.py +++ b/esphome/components/kalman_combinator/sensor.py @@ -1,6 +1,6 @@ import esphome.config_validation as cv -CONFIG_SCHEMA = CONFIG_SCHEMA = cv.invalid( +CONFIG_SCHEMA = cv.invalid( "The kalman_combinator sensor has moved.\nPlease use the combination platform instead with type: kalman.\n" "See https://esphome.io/components/sensor/combination.html" ) From fbc830176f612a341b5ace5418ab4f76cd4a578c Mon Sep 17 00:00:00 2001 From: Lucio Tarantino Date: Sun, 21 Jul 2024 23:16:51 +0200 Subject: [PATCH 1794/2101] [heatpumpir] Fix BK72XX Compile error with IRremoteESP8266 (#6955) --- esphome/components/heatpumpir/climate.py | 3 +++ tests/components/heatpumpir/test.bk72xx-ard.yaml | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/esphome/components/heatpumpir/climate.py b/esphome/components/heatpumpir/climate.py index 80900d7db9..9d31668deb 100644 --- a/esphome/components/heatpumpir/climate.py +++ b/esphome/components/heatpumpir/climate.py @@ -8,6 +8,7 @@ from esphome.const import ( CONF_PROTOCOL, CONF_VISUAL, ) +from esphome.core import CORE CODEOWNERS = ["@rob-deutsch"] @@ -127,3 +128,5 @@ def to_code(config): cg.add(var.set_min_temperature(config[CONF_MIN_TEMPERATURE])) cg.add_library("tonia/HeatpumpIR", "1.0.27") + if CORE.is_libretiny: + CORE.add_platformio_option("lib_ignore", "IRremoteESP8266") diff --git a/tests/components/heatpumpir/test.bk72xx-ard.yaml b/tests/components/heatpumpir/test.bk72xx-ard.yaml index 90259f1244..b616f9157c 100644 --- a/tests/components/heatpumpir/test.bk72xx-ard.yaml +++ b/tests/components/heatpumpir/test.bk72xx-ard.yaml @@ -3,6 +3,13 @@ remote_transmitter: carrier_duty_percent: 50% climate: + - platform: heatpumpir + protocol: mitsubishi_heavy_zm + horizontal_default: left + vertical_default: up + name: HeatpumpIR Climate + min_temperature: 18 + max_temperature: 30 - platform: heatpumpir protocol: daikin horizontal_default: mleft From 368662969ed4c4df267499c720497d195acbed06 Mon Sep 17 00:00:00 2001 From: Markus <974709+Links2004@users.noreply.github.com> Date: Sun, 21 Jul 2024 23:36:46 +0200 Subject: [PATCH 1795/2101] Move MQTT ip discovery to deticated config option. (#6673) --- esphome/components/mqtt/__init__.py | 8 ++++++++ esphome/components/mqtt/mqtt_client.cpp | 18 +++++++++++++++--- esphome/components/mqtt/mqtt_client.h | 6 +++++- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/esphome/components/mqtt/__init__.py b/esphome/components/mqtt/__init__.py index 96a02cb60e..f4bd34bfd3 100644 --- a/esphome/components/mqtt/__init__.py +++ b/esphome/components/mqtt/__init__.py @@ -61,6 +61,7 @@ def AUTO_LOAD(): return ["json"] +CONF_DISCOVER_IP = "discover_ip" CONF_IDF_SEND_ASYNC = "idf_send_async" CONF_SKIP_CERT_CN_CHECK = "skip_cert_cn_check" @@ -225,6 +226,7 @@ CONFIG_SCHEMA = cv.All( cv.boolean, cv.one_of("CLEAN", upper=True) ), 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, @@ -328,8 +330,12 @@ async def to_code(config): discovery_prefix = config[CONF_DISCOVERY_PREFIX] discovery_unique_id_generator = config[CONF_DISCOVERY_UNIQUE_ID_GENERATOR] discovery_object_id_generator = config[CONF_DISCOVERY_OBJECT_ID_GENERATOR] + discover_ip = config[CONF_DISCOVER_IP] if not discovery: + discovery_prefix = "" + + if not discovery and not discover_ip: cg.add(var.disable_discovery()) elif discovery == "CLEAN": cg.add( @@ -338,6 +344,7 @@ async def to_code(config): discovery_unique_id_generator, discovery_object_id_generator, discovery_retain, + discover_ip, True, ) ) @@ -348,6 +355,7 @@ async def to_code(config): discovery_unique_id_generator, discovery_object_id_generator, discovery_retain, + discover_ip, ) ) diff --git a/esphome/components/mqtt/mqtt_client.cpp b/esphome/components/mqtt/mqtt_client.cpp index d70b9cbd30..876367aaea 100644 --- a/esphome/components/mqtt/mqtt_client.cpp +++ b/esphome/components/mqtt/mqtt_client.cpp @@ -66,7 +66,7 @@ void MQTTClientComponent::setup() { } #endif - if (this->is_discovery_enabled()) { + if (this->is_discovery_ip_enabled()) { this->subscribe( "esphome/discover", [this](const std::string &topic, const std::string &payload) { this->send_device_info_(); }, 2); @@ -82,7 +82,7 @@ void MQTTClientComponent::setup() { } void MQTTClientComponent::send_device_info_() { - if (!this->is_connected() or !this->is_discovery_enabled()) { + if (!this->is_connected() or !this->is_discovery_ip_enabled()) { return; } std::string topic = "esphome/discover/"; @@ -99,6 +99,9 @@ void MQTTClientComponent::send_device_info_() { } } root["name"] = App.get_name(); + if (!App.get_friendly_name().empty()) { + root["friendly_name"] = App.get_friendly_name(); + } #ifdef USE_API root["port"] = api::global_api_server->get_port(); #endif @@ -130,6 +133,10 @@ void MQTTClientComponent::send_device_info_() { #ifdef USE_DASHBOARD_IMPORT root["package_import_url"] = dashboard_import::get_package_import_url(); #endif + +#ifdef USE_API_NOISE + root["api_encryption"] = "Noise_NNpsk0_25519_ChaChaPoly_SHA256"; +#endif }, 2, this->discovery_info_.retain); } @@ -140,6 +147,9 @@ void MQTTClientComponent::dump_config() { this->ip_.str().c_str()); ESP_LOGCONFIG(TAG, " Username: " LOG_SECRET("'%s'"), this->credentials_.username.c_str()); ESP_LOGCONFIG(TAG, " Client ID: " LOG_SECRET("'%s'"), this->credentials_.client_id.c_str()); + if (this->is_discovery_ip_enabled()) { + ESP_LOGCONFIG(TAG, " Discovery IP enabled"); + } if (!this->discovery_info_.prefix.empty()) { ESP_LOGCONFIG(TAG, " Discovery prefix: '%s'", this->discovery_info_.prefix.c_str()); ESP_LOGCONFIG(TAG, " Discovery retain: %s", YESNO(this->discovery_info_.retain)); @@ -581,6 +591,7 @@ void MQTTClientComponent::disable_shutdown_message() { this->recalculate_availability_(); } bool MQTTClientComponent::is_discovery_enabled() const { return !this->discovery_info_.prefix.empty(); } +bool MQTTClientComponent::is_discovery_ip_enabled() const { return this->discovery_info_.discover_ip; } const Availability &MQTTClientComponent::get_availability() { return this->availability_; } void MQTTClientComponent::recalculate_availability_() { if (this->birth_message_.topic.empty() || this->birth_message_.topic != this->last_will_.topic) { @@ -606,8 +617,9 @@ void MQTTClientComponent::set_shutdown_message(MQTTMessage &&message) { this->sh void MQTTClientComponent::set_discovery_info(std::string &&prefix, MQTTDiscoveryUniqueIdGenerator unique_id_generator, MQTTDiscoveryObjectIdGenerator object_id_generator, bool retain, - bool clean) { + bool discover_ip, bool clean) { this->discovery_info_.prefix = std::move(prefix); + this->discovery_info_.discover_ip = discover_ip; this->discovery_info_.unique_id_generator = unique_id_generator; this->discovery_info_.object_id_generator = object_id_generator; this->discovery_info_.retain = retain; diff --git a/esphome/components/mqtt/mqtt_client.h b/esphome/components/mqtt/mqtt_client.h index 454316aa87..b0d3bbe66d 100644 --- a/esphome/components/mqtt/mqtt_client.h +++ b/esphome/components/mqtt/mqtt_client.h @@ -79,6 +79,7 @@ enum MQTTDiscoveryObjectIdGenerator { struct MQTTDiscoveryInfo { std::string prefix; ///< The Home Assistant discovery prefix. Empty means disabled. bool retain; ///< Whether to retain discovery messages. + bool discover_ip; ///< Enable the Home Assistant device discovery. bool clean; MQTTDiscoveryUniqueIdGenerator unique_id_generator; MQTTDiscoveryObjectIdGenerator object_id_generator; @@ -122,12 +123,14 @@ class MQTTClientComponent : public Component { * @param retain Whether to retain discovery messages. */ void set_discovery_info(std::string &&prefix, MQTTDiscoveryUniqueIdGenerator unique_id_generator, - MQTTDiscoveryObjectIdGenerator object_id_generator, bool retain, bool clean = false); + MQTTDiscoveryObjectIdGenerator object_id_generator, bool retain, bool discover_ip, + bool clean = false); /// Get Home Assistant discovery info. const MQTTDiscoveryInfo &get_discovery_info() const; /// Globally disable Home Assistant discovery. void disable_discovery(); 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. @@ -290,6 +293,7 @@ class MQTTClientComponent : public Component { MQTTDiscoveryInfo discovery_info_{ .prefix = "homeassistant", .retain = true, + .discover_ip = true, .clean = false, .unique_id_generator = MQTT_LEGACY_UNIQUE_ID_GENERATOR, .object_id_generator = MQTT_NONE_OBJECT_ID_GENERATOR, From 40e79299d55cd61e2f81b9f694e37ac3598c3d56 Mon Sep 17 00:00:00 2001 From: rnauber <7414650+rnauber@users.noreply.github.com> Date: Sun, 21 Jul 2024 23:57:59 +0200 Subject: [PATCH 1796/2101] Feature/m5angle8: Add support for m5angle8 input device (#6799) Co-authored-by: Richard Nauber Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- CODEOWNERS | 1 + esphome/components/m5stack_8angle/__init__.py | 33 +++++++++ .../m5stack_8angle/binary_sensor/__init__.py | 30 ++++++++ .../m5stack_8angle_binary_sensor.cpp | 17 +++++ .../m5stack_8angle_binary_sensor.h | 19 +++++ .../m5stack_8angle/light/__init__.py | 31 ++++++++ .../light/m5stack_8angle_light.cpp | 45 +++++++++++ .../light/m5stack_8angle_light.h | 37 ++++++++++ .../m5stack_8angle/m5stack_8angle.cpp | 74 +++++++++++++++++++ .../m5stack_8angle/m5stack_8angle.h | 34 +++++++++ .../m5stack_8angle/sensor/__init__.py | 66 +++++++++++++++++ .../sensor/m5stack_8angle_sensor.cpp | 24 ++++++ .../sensor/m5stack_8angle_sensor.h | 27 +++++++ tests/components/m5stack_8angle/common.yaml | 30 ++++++++ .../m5stack_8angle/test.esp32-ard.yaml | 1 + .../m5stack_8angle/test.esp32-c3-ard.yaml | 1 + .../m5stack_8angle/test.esp32-c3-idf.yaml | 1 + .../m5stack_8angle/test.esp32-idf.yaml | 1 + .../m5stack_8angle/test.esp8266-ard.yaml | 1 + .../m5stack_8angle/test.rp2040-ard.yaml | 1 + 20 files changed, 474 insertions(+) create mode 100644 esphome/components/m5stack_8angle/__init__.py create mode 100644 esphome/components/m5stack_8angle/binary_sensor/__init__.py create mode 100644 esphome/components/m5stack_8angle/binary_sensor/m5stack_8angle_binary_sensor.cpp create mode 100644 esphome/components/m5stack_8angle/binary_sensor/m5stack_8angle_binary_sensor.h create mode 100644 esphome/components/m5stack_8angle/light/__init__.py create mode 100644 esphome/components/m5stack_8angle/light/m5stack_8angle_light.cpp create mode 100644 esphome/components/m5stack_8angle/light/m5stack_8angle_light.h create mode 100644 esphome/components/m5stack_8angle/m5stack_8angle.cpp create mode 100644 esphome/components/m5stack_8angle/m5stack_8angle.h create mode 100644 esphome/components/m5stack_8angle/sensor/__init__.py create mode 100644 esphome/components/m5stack_8angle/sensor/m5stack_8angle_sensor.cpp create mode 100644 esphome/components/m5stack_8angle/sensor/m5stack_8angle_sensor.h create mode 100644 tests/components/m5stack_8angle/common.yaml create mode 100644 tests/components/m5stack_8angle/test.esp32-ard.yaml create mode 100644 tests/components/m5stack_8angle/test.esp32-c3-ard.yaml create mode 100644 tests/components/m5stack_8angle/test.esp32-c3-idf.yaml create mode 100644 tests/components/m5stack_8angle/test.esp32-idf.yaml create mode 100644 tests/components/m5stack_8angle/test.esp8266-ard.yaml create mode 100644 tests/components/m5stack_8angle/test.rp2040-ard.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 210c567f78..ee76a072fc 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -216,6 +216,7 @@ esphome/components/lock/* @esphome/core esphome/components/logger/* @esphome/core esphome/components/ltr390/* @latonita @sjtrny esphome/components/ltr_als_ps/* @latonita +esphome/components/m5stack_8angle/* @rnauber esphome/components/matrix_keypad/* @ssieb esphome/components/max31865/* @DAVe3283 esphome/components/max44009/* @berfenger diff --git a/esphome/components/m5stack_8angle/__init__.py b/esphome/components/m5stack_8angle/__init__.py new file mode 100644 index 0000000000..1aaa86a6fd --- /dev/null +++ b/esphome/components/m5stack_8angle/__init__.py @@ -0,0 +1,33 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import i2c +from esphome.const import CONF_ID + + +DEPENDENCIES = ["i2c"] +CODEOWNERS = ["@rnauber"] +MULTI_CONF = True + +CONF_M5STACK_8ANGLE_ID = "m5stack_8angle_id" + +m5stack_8angle_ns = cg.esphome_ns.namespace("m5stack_8angle") +M5Stack8AngleComponent = m5stack_8angle_ns.class_( + "M5Stack8AngleComponent", + i2c.I2CDevice, + cg.Component, +) + +AnalogBits = m5stack_8angle_ns.enum("AnalogBits") + + +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.declare_id(M5Stack8AngleComponent), + } +).extend(i2c.i2c_device_schema(0x43)) + + +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) diff --git a/esphome/components/m5stack_8angle/binary_sensor/__init__.py b/esphome/components/m5stack_8angle/binary_sensor/__init__.py new file mode 100644 index 0000000000..a8b2690083 --- /dev/null +++ b/esphome/components/m5stack_8angle/binary_sensor/__init__.py @@ -0,0 +1,30 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import binary_sensor + +from .. import M5Stack8AngleComponent, m5stack_8angle_ns, CONF_M5STACK_8ANGLE_ID + + +M5Stack8AngleSwitchBinarySensor = m5stack_8angle_ns.class_( + "M5Stack8AngleSwitchBinarySensor", + binary_sensor.BinarySensor, + cg.PollingComponent, +) + + +CONFIG_SCHEMA = cv.All( + cv.Schema( + { + cv.GenerateID(CONF_M5STACK_8ANGLE_ID): cv.use_id(M5Stack8AngleComponent), + } + ) + .extend(binary_sensor.binary_sensor_schema(M5Stack8AngleSwitchBinarySensor)) + .extend(cv.polling_component_schema("10s")) +) + + +async def to_code(config): + hub = await cg.get_variable(config[CONF_M5STACK_8ANGLE_ID]) + sens = await binary_sensor.new_binary_sensor(config) + cg.add(sens.set_parent(hub)) + await cg.register_component(sens, config) diff --git a/esphome/components/m5stack_8angle/binary_sensor/m5stack_8angle_binary_sensor.cpp b/esphome/components/m5stack_8angle/binary_sensor/m5stack_8angle_binary_sensor.cpp new file mode 100644 index 0000000000..2f68d9f254 --- /dev/null +++ b/esphome/components/m5stack_8angle/binary_sensor/m5stack_8angle_binary_sensor.cpp @@ -0,0 +1,17 @@ +#include "m5stack_8angle_binary_sensor.h" + +namespace esphome { +namespace m5stack_8angle { + +void M5Stack8AngleSwitchBinarySensor::update() { + int8_t out = this->parent_->read_switch(); + if (out == -1) { + this->status_set_warning("Could not read binary sensor state from M5Stack 8Angle."); + return; + } + this->publish_state(out != 0); + this->status_clear_warning(); +} + +} // namespace m5stack_8angle +} // namespace esphome diff --git a/esphome/components/m5stack_8angle/binary_sensor/m5stack_8angle_binary_sensor.h b/esphome/components/m5stack_8angle/binary_sensor/m5stack_8angle_binary_sensor.h new file mode 100644 index 0000000000..b8bb601525 --- /dev/null +++ b/esphome/components/m5stack_8angle/binary_sensor/m5stack_8angle_binary_sensor.h @@ -0,0 +1,19 @@ +#pragma once + +#include "esphome/components/binary_sensor/binary_sensor.h" +#include "esphome/core/component.h" + +#include "../m5stack_8angle.h" + +namespace esphome { +namespace m5stack_8angle { + +class M5Stack8AngleSwitchBinarySensor : public binary_sensor::BinarySensor, + public PollingComponent, + public Parented { + public: + void update() override; +}; + +} // namespace m5stack_8angle +} // namespace esphome diff --git a/esphome/components/m5stack_8angle/light/__init__.py b/esphome/components/m5stack_8angle/light/__init__.py new file mode 100644 index 0000000000..07384ecd61 --- /dev/null +++ b/esphome/components/m5stack_8angle/light/__init__.py @@ -0,0 +1,31 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import light + +from esphome.const import CONF_OUTPUT_ID + +from .. import M5Stack8AngleComponent, m5stack_8angle_ns, CONF_M5STACK_8ANGLE_ID + + +M5Stack8AngleLightsComponent = m5stack_8angle_ns.class_( + "M5Stack8AngleLightOutput", + light.AddressableLight, +) + + +CONFIG_SCHEMA = cv.All( + light.ADDRESSABLE_LIGHT_SCHEMA.extend( + { + cv.GenerateID(CONF_M5STACK_8ANGLE_ID): cv.use_id(M5Stack8AngleComponent), + cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(M5Stack8AngleLightsComponent), + } + ) +) + + +async def to_code(config): + hub = await cg.get_variable(config[CONF_M5STACK_8ANGLE_ID]) + lights = cg.new_Pvariable(config[CONF_OUTPUT_ID]) + await light.register_light(lights, config) + await cg.register_component(lights, config) + cg.add(lights.set_parent(hub)) diff --git a/esphome/components/m5stack_8angle/light/m5stack_8angle_light.cpp b/esphome/components/m5stack_8angle/light/m5stack_8angle_light.cpp new file mode 100644 index 0000000000..95fd8cb98f --- /dev/null +++ b/esphome/components/m5stack_8angle/light/m5stack_8angle_light.cpp @@ -0,0 +1,45 @@ +#include "m5stack_8angle_light.h" + +#include "esphome/core/log.h" + +namespace esphome { +namespace m5stack_8angle { + +static const char *const TAG = "m5stack_8angle.light"; + +void M5Stack8AngleLightOutput::setup() { + ExternalRAMAllocator allocator(ExternalRAMAllocator::ALLOW_FAILURE); + this->buf_ = allocator.allocate(M5STACK_8ANGLE_NUM_LEDS * M5STACK_8ANGLE_BYTES_PER_LED); + if (this->buf_ == nullptr) { + ESP_LOGE(TAG, "Failed to allocate buffer of size %u", M5STACK_8ANGLE_NUM_LEDS * M5STACK_8ANGLE_BYTES_PER_LED); + this->mark_failed(); + return; + }; + memset(this->buf_, 0xFF, M5STACK_8ANGLE_NUM_LEDS * M5STACK_8ANGLE_BYTES_PER_LED); + + this->effect_data_ = allocator.allocate(M5STACK_8ANGLE_NUM_LEDS); + if (this->effect_data_ == nullptr) { + ESP_LOGE(TAG, "Failed to allocate effect data of size %u", M5STACK_8ANGLE_NUM_LEDS); + this->mark_failed(); + return; + }; + memset(this->effect_data_, 0x00, M5STACK_8ANGLE_NUM_LEDS); +} + +void M5Stack8AngleLightOutput::write_state(light::LightState *state) { + for (int i = 0; i < M5STACK_8ANGLE_NUM_LEDS; + i++) { // write one LED at a time, otherwise the message will be truncated + this->parent_->write_register(M5STACK_8ANGLE_REGISTER_RGB_24B + i * M5STACK_8ANGLE_BYTES_PER_LED, + this->buf_ + i * M5STACK_8ANGLE_BYTES_PER_LED, M5STACK_8ANGLE_BYTES_PER_LED); + } +} + +light::ESPColorView M5Stack8AngleLightOutput::get_view_internal(int32_t index) const { + size_t pos = index * M5STACK_8ANGLE_BYTES_PER_LED; + // red, green, blue, white, effect_data, color_correction + return {this->buf_ + pos, this->buf_ + pos + 1, this->buf_ + pos + 2, + nullptr, this->effect_data_ + index, &this->correction_}; +} + +} // namespace m5stack_8angle +} // namespace esphome diff --git a/esphome/components/m5stack_8angle/light/m5stack_8angle_light.h b/esphome/components/m5stack_8angle/light/m5stack_8angle_light.h new file mode 100644 index 0000000000..204f2c04c7 --- /dev/null +++ b/esphome/components/m5stack_8angle/light/m5stack_8angle_light.h @@ -0,0 +1,37 @@ +#pragma once + +#include "esphome/components/light/addressable_light.h" +#include "esphome/components/light/light_output.h" + +#include "../m5stack_8angle.h" + +namespace esphome { +namespace m5stack_8angle { + +static const uint8_t M5STACK_8ANGLE_NUM_LEDS = 9; +static const uint8_t M5STACK_8ANGLE_BYTES_PER_LED = 4; + +class M5Stack8AngleLightOutput : public light::AddressableLight, public Parented { + public: + void setup() override; + + void write_state(light::LightState *state) override; + + int32_t size() const override { return M5STACK_8ANGLE_NUM_LEDS; } + light::LightTraits get_traits() override { + auto traits = light::LightTraits(); + traits.set_supported_color_modes({light::ColorMode::RGB}); + return traits; + }; + + void clear_effect_data() override { memset(this->effect_data_, 0x00, M5STACK_8ANGLE_NUM_LEDS); }; + + protected: + light::ESPColorView get_view_internal(int32_t index) const override; + + uint8_t *buf_{nullptr}; + uint8_t *effect_data_{nullptr}; +}; + +} // namespace m5stack_8angle +} // namespace esphome diff --git a/esphome/components/m5stack_8angle/m5stack_8angle.cpp b/esphome/components/m5stack_8angle/m5stack_8angle.cpp new file mode 100644 index 0000000000..6a584eddbc --- /dev/null +++ b/esphome/components/m5stack_8angle/m5stack_8angle.cpp @@ -0,0 +1,74 @@ +#include "m5stack_8angle.h" +#include "esphome/core/hal.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace m5stack_8angle { + +static const char *const TAG = "m5stack_8angle"; + +void M5Stack8AngleComponent::setup() { + ESP_LOGCONFIG(TAG, "Setting up M5STACK_8ANGLE..."); + i2c::ErrorCode err; + + err = this->read(nullptr, 0); + if (err != i2c::NO_ERROR) { + ESP_LOGE(TAG, "I2C error %02X...", err); + this->mark_failed(); + return; + }; + + err = this->read_register(M5STACK_8ANGLE_REGISTER_FW_VERSION, &this->fw_version_, 1); + if (err != i2c::NO_ERROR) { + ESP_LOGE(TAG, "I2C error %02X...", err); + this->mark_failed(); + return; + }; +} + +void M5Stack8AngleComponent::dump_config() { + ESP_LOGCONFIG(TAG, "M5STACK_8ANGLE:"); + LOG_I2C_DEVICE(this); + ESP_LOGCONFIG(TAG, " Firmware version: %d ", this->fw_version_); +} + +float M5Stack8AngleComponent::read_knob_pos(uint8_t channel, AnalogBits bits) { + int32_t raw_pos = this->read_knob_pos_raw(channel, bits); + if (raw_pos == -1) { + return NAN; + } + return (float) raw_pos / ((1 << bits) - 1); +} + +int32_t M5Stack8AngleComponent::read_knob_pos_raw(uint8_t channel, AnalogBits bits) { + uint16_t knob_pos = 0; + i2c::ErrorCode err; + if (bits == BITS_8) { + err = this->read_register(M5STACK_8ANGLE_REGISTER_ANALOG_INPUT_8B + channel, (uint8_t *) &knob_pos, 1); + } else if (bits == BITS_12) { + err = this->read_register(M5STACK_8ANGLE_REGISTER_ANALOG_INPUT_12B + (channel * 2), (uint8_t *) &knob_pos, 2); + } else { + ESP_LOGE(TAG, "Invalid number of bits: %d", bits); + return -1; + } + if (err == i2c::NO_ERROR) { + return knob_pos; + } else { + return -1; + } +} + +int8_t M5Stack8AngleComponent::read_switch() { + uint8_t out; + i2c::ErrorCode err = this->read_register(M5STACK_8ANGLE_REGISTER_DIGITAL_INPUT, (uint8_t *) &out, 1); + if (err == i2c::NO_ERROR) { + return out ? 1 : 0; + } else { + return -1; + } +} + +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 new file mode 100644 index 0000000000..831b1422fd --- /dev/null +++ b/esphome/components/m5stack_8angle/m5stack_8angle.h @@ -0,0 +1,34 @@ +#pragma once + +#include "esphome/components/i2c/i2c.h" +#include "esphome/core/component.h" + +namespace esphome { +namespace m5stack_8angle { + +static const uint8_t M5STACK_8ANGLE_REGISTER_ANALOG_INPUT_12B = 0x00; +static const uint8_t M5STACK_8ANGLE_REGISTER_ANALOG_INPUT_8B = 0x10; +static const uint8_t M5STACK_8ANGLE_REGISTER_DIGITAL_INPUT = 0x20; +static const uint8_t M5STACK_8ANGLE_REGISTER_RGB_24B = 0x30; +static const uint8_t M5STACK_8ANGLE_REGISTER_FW_VERSION = 0xFE; + +enum AnalogBits : uint8_t { + BITS_8 = 8, + BITS_12 = 12, +}; + +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(); + + protected: + uint8_t fw_version_; +}; + +} // namespace m5stack_8angle +} // namespace esphome diff --git a/esphome/components/m5stack_8angle/sensor/__init__.py b/esphome/components/m5stack_8angle/sensor/__init__.py new file mode 100644 index 0000000000..70744a59e6 --- /dev/null +++ b/esphome/components/m5stack_8angle/sensor/__init__.py @@ -0,0 +1,66 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import sensor + +from esphome.const import ( + CONF_BIT_DEPTH, + CONF_CHANNEL, + CONF_RAW, + ICON_ROTATE_RIGHT, + STATE_CLASS_MEASUREMENT, +) + +from .. import ( + AnalogBits, + M5Stack8AngleComponent, + m5stack_8angle_ns, + CONF_M5STACK_8ANGLE_ID, +) + + +M5Stack8AngleKnobSensor = m5stack_8angle_ns.class_( + "M5Stack8AngleKnobSensor", + sensor.Sensor, + cg.PollingComponent, +) + + +BIT_DEPTHS = { + 8: AnalogBits.BITS_8, + 12: AnalogBits.BITS_12, +} + +_validate_bits = cv.float_with_unit("bits", "bit") + + +CONFIG_SCHEMA = cv.All( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(M5Stack8AngleKnobSensor), + cv.GenerateID(CONF_M5STACK_8ANGLE_ID): cv.use_id(M5Stack8AngleComponent), + cv.Required(CONF_CHANNEL): cv.int_range(min=1, max=8), + cv.Optional(CONF_BIT_DEPTH, default="8bit"): cv.All( + _validate_bits, cv.enum(BIT_DEPTHS) + ), + cv.Optional(CONF_RAW, default=False): cv.boolean, + } + ) + .extend( + sensor.sensor_schema( + M5Stack8AngleKnobSensor, + accuracy_decimals=2, + icon=ICON_ROTATE_RIGHT, + state_class=STATE_CLASS_MEASUREMENT, + ) + ) + .extend(cv.polling_component_schema("10s")) +) + + +async def to_code(config): + var = await sensor.new_sensor(config) + await cg.register_component(var, config) + await cg.register_parented(var, config[CONF_M5STACK_8ANGLE_ID]) + cg.add(var.set_channel(config[CONF_CHANNEL] - 1)) + cg.add(var.set_bit_depth(BIT_DEPTHS[config[CONF_BIT_DEPTH]])) + cg.add(var.set_raw(config[CONF_RAW])) diff --git a/esphome/components/m5stack_8angle/sensor/m5stack_8angle_sensor.cpp b/esphome/components/m5stack_8angle/sensor/m5stack_8angle_sensor.cpp new file mode 100644 index 0000000000..5e034f1dd3 --- /dev/null +++ b/esphome/components/m5stack_8angle/sensor/m5stack_8angle_sensor.cpp @@ -0,0 +1,24 @@ +#include "m5stack_8angle_sensor.h" + +namespace esphome { +namespace m5stack_8angle { + +void M5Stack8AngleKnobSensor::update() { + if (this->parent_ != nullptr) { + int32_t raw_pos = this->parent_->read_knob_pos_raw(this->channel_, this->bits_); + if (raw_pos == -1) { + this->status_set_warning("Could not read knob position from M5Stack 8Angle."); + return; + } + if (this->raw_) { + this->publish_state(raw_pos); + } else { + float knob_pos = (float) raw_pos / ((1 << this->bits_) - 1); + this->publish_state(knob_pos); + } + this->status_clear_warning(); + }; +} + +} // namespace m5stack_8angle +} // namespace esphome diff --git a/esphome/components/m5stack_8angle/sensor/m5stack_8angle_sensor.h b/esphome/components/m5stack_8angle/sensor/m5stack_8angle_sensor.h new file mode 100644 index 0000000000..4848f8f80f --- /dev/null +++ b/esphome/components/m5stack_8angle/sensor/m5stack_8angle_sensor.h @@ -0,0 +1,27 @@ +#pragma once + +#include "esphome/components/sensor/sensor.h" +#include "esphome/core/component.h" + +#include "../m5stack_8angle.h" + +namespace esphome { +namespace m5stack_8angle { + +class M5Stack8AngleKnobSensor : public sensor::Sensor, + public PollingComponent, + public Parented { + public: + void update() override; + void set_channel(uint8_t channel) { this->channel_ = channel; }; + void set_bit_depth(AnalogBits bits) { this->bits_ = bits; }; + void set_raw(bool raw) { this->raw_ = raw; }; + + protected: + uint8_t channel_; + AnalogBits bits_; + bool raw_; +}; + +} // namespace m5stack_8angle +} // namespace esphome diff --git a/tests/components/m5stack_8angle/common.yaml b/tests/components/m5stack_8angle/common.yaml new file mode 100644 index 0000000000..d7f988ed3a --- /dev/null +++ b/tests/components/m5stack_8angle/common.yaml @@ -0,0 +1,30 @@ +i2c: + sda: 0 + scl: 1 + id: bus_external + +m5stack_8angle: + i2c_id: bus_external + id: m5stack_8angle_base + +light: + - platform: m5stack_8angle + m5stack_8angle_id: m5stack_8angle_base + id: m8_angle_leds + name: Lights + effects: + - addressable_scan: + +sensor: + - platform: m5stack_8angle + m5stack_8angle_id: m5stack_8angle_base + channel: 1 + name: Knob 1 + - platform: m5stack_8angle + m5stack_8angle_id: m5stack_8angle_base + channel: 2 + name: Knob 2 +binary_sensor: + - platform: m5stack_8angle + m5stack_8angle_id: m5stack_8angle_base + name: Switch diff --git a/tests/components/m5stack_8angle/test.esp32-ard.yaml b/tests/components/m5stack_8angle/test.esp32-ard.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/m5stack_8angle/test.esp32-ard.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/m5stack_8angle/test.esp32-c3-ard.yaml b/tests/components/m5stack_8angle/test.esp32-c3-ard.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/m5stack_8angle/test.esp32-c3-ard.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/m5stack_8angle/test.esp32-c3-idf.yaml b/tests/components/m5stack_8angle/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/m5stack_8angle/test.esp32-c3-idf.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/m5stack_8angle/test.esp32-idf.yaml b/tests/components/m5stack_8angle/test.esp32-idf.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/m5stack_8angle/test.esp32-idf.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/m5stack_8angle/test.esp8266-ard.yaml b/tests/components/m5stack_8angle/test.esp8266-ard.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/m5stack_8angle/test.esp8266-ard.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/m5stack_8angle/test.rp2040-ard.yaml b/tests/components/m5stack_8angle/test.rp2040-ard.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/m5stack_8angle/test.rp2040-ard.yaml @@ -0,0 +1 @@ +<<: !include common.yaml From 1f4829598a62424170fdd3fcc58dcc4bd2224162 Mon Sep 17 00:00:00 2001 From: Olivier ARCHER Date: Mon, 22 Jul 2024 01:29:09 +0200 Subject: [PATCH 1797/2101] [http_request] allow basic auth for idf (#7086) --- esphome/components/http_request/http_request_idf.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/http_request/http_request_idf.cpp b/esphome/components/http_request/http_request_idf.cpp index d6fac7a133..68e0639b99 100644 --- a/esphome/components/http_request/http_request_idf.cpp +++ b/esphome/components/http_request/http_request_idf.cpp @@ -52,6 +52,7 @@ std::shared_ptr HttpRequestIDF::start(std::string url, std::strin config.timeout_ms = this->timeout_; 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) { config.crt_bundle_attach = esp_crt_bundle_attach; From f322ec8f3d1f70543578f0ec179d0049681c48c8 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Mon, 22 Jul 2024 01:33:26 +0200 Subject: [PATCH 1798/2101] use cache to build tests for compoenents (#7059) --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 45fe336d77..a8e93248bb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -468,6 +468,8 @@ jobs: - name: Compile config run: | . venv/bin/activate + mkdir build_cache + export PLATFORMIO_BUILD_CACHE_DIR=$PWD/build_cache for component in ${{ matrix.components }}; do ./script/test_build_components -e compile -c $component done From a464e46d4d5630f6fe18d5bcffe7026739fd8254 Mon Sep 17 00:00:00 2001 From: irgendwienet Date: Mon, 22 Jul 2024 01:42:09 +0200 Subject: [PATCH 1799/2101] Fixes sml parser to process extended length lists with a number of items that is dividable by 16 (#6148) --- esphome/components/sml/sml_parser.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/esphome/components/sml/sml_parser.cpp b/esphome/components/sml/sml_parser.cpp index 3b23522b21..c782c0fc5e 100644 --- a/esphome/components/sml/sml_parser.cpp +++ b/esphome/components/sml/sml_parser.cpp @@ -27,7 +27,7 @@ bool SmlFile::setup_node(SmlNode *node) { uint8_t parse_length = length; if (has_extended_length) { length = (length << 4) + (this->buffer_[this->pos_ + 1] & 0x0f); - parse_length = length - 1; + parse_length = length; this->pos_ += 1; } @@ -37,7 +37,9 @@ bool SmlFile::setup_node(SmlNode *node) { node->type = type & 0x07; node->nodes.clear(); node->value_bytes.clear(); - if (this->buffer_[this->pos_] == 0x00) { // end of message + + // if the list is a has_extended_length list with e.g. 16 elements this is a 0x00 byte but not the end of message + if (!has_extended_length && this->buffer_[this->pos_] == 0x00) { // end of message this->pos_ += 1; } else if (is_list) { // list this->pos_ += 1; From d187340fc4d5781de91c2db3958e7a2fb295d795 Mon Sep 17 00:00:00 2001 From: Alex Cortelyou <1689668+acortelyou@users.noreply.github.com> Date: Thu, 18 Jul 2024 15:04:11 -0700 Subject: [PATCH 1800/2101] Prevent rename from deleting new config (#7104) --- esphome/__main__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/esphome/__main__.py b/esphome/__main__.py index 5ff1a28ec7..b13f96daf7 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -695,7 +695,8 @@ def command_rename(args, config): os.remove(new_path) return 1 - os.remove(CORE.config_path) + if CORE.config_path != new_path: + os.remove(CORE.config_path) print(color(Fore.BOLD_GREEN, "SUCCESS")) print() From 74aee1d453f39b84d5783e9b051fe788e5fadb12 Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt Date: Fri, 19 Jul 2024 15:15:11 -0400 Subject: [PATCH 1801/2101] revert bit shift to match previous behavior (#7109) --- .../components/i2s_audio/microphone/i2s_audio_microphone.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp index 009fecdf90..cb49a744fc 100644 --- a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +++ b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp @@ -174,7 +174,8 @@ size_t I2SAudioMicrophone::read(int16_t *buf, size_t len) { size_t samples_read = bytes_read / sizeof(int32_t); samples.resize(samples_read); for (size_t i = 0; i < samples_read; i++) { - samples[i] = reinterpret_cast(buf)[i] >> 16; + int32_t temp = reinterpret_cast(buf)[i] >> 14; + samples[i] = clamp(temp, INT16_MIN, INT16_MAX); } memcpy(buf, samples.data(), samples_read * sizeof(int16_t)); return samples_read * sizeof(int16_t); From 626ed815fb289b7532eb64d210bbff142f6c7666 Mon Sep 17 00:00:00 2001 From: Lucio Tarantino Date: Sun, 21 Jul 2024 23:16:51 +0200 Subject: [PATCH 1802/2101] [heatpumpir] Fix BK72XX Compile error with IRremoteESP8266 (#6955) --- esphome/components/heatpumpir/climate.py | 3 +++ tests/components/heatpumpir/test.bk72xx-ard.yaml | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/esphome/components/heatpumpir/climate.py b/esphome/components/heatpumpir/climate.py index 80900d7db9..9d31668deb 100644 --- a/esphome/components/heatpumpir/climate.py +++ b/esphome/components/heatpumpir/climate.py @@ -8,6 +8,7 @@ from esphome.const import ( CONF_PROTOCOL, CONF_VISUAL, ) +from esphome.core import CORE CODEOWNERS = ["@rob-deutsch"] @@ -127,3 +128,5 @@ def to_code(config): cg.add(var.set_min_temperature(config[CONF_MIN_TEMPERATURE])) cg.add_library("tonia/HeatpumpIR", "1.0.27") + if CORE.is_libretiny: + CORE.add_platformio_option("lib_ignore", "IRremoteESP8266") diff --git a/tests/components/heatpumpir/test.bk72xx-ard.yaml b/tests/components/heatpumpir/test.bk72xx-ard.yaml index 90259f1244..b616f9157c 100644 --- a/tests/components/heatpumpir/test.bk72xx-ard.yaml +++ b/tests/components/heatpumpir/test.bk72xx-ard.yaml @@ -3,6 +3,13 @@ remote_transmitter: carrier_duty_percent: 50% climate: + - platform: heatpumpir + protocol: mitsubishi_heavy_zm + horizontal_default: left + vertical_default: up + name: HeatpumpIR Climate + min_temperature: 18 + max_temperature: 30 - platform: heatpumpir protocol: daikin horizontal_default: mleft From 5bec0a6534028a834df91aad8e6d9c95cc825c5f Mon Sep 17 00:00:00 2001 From: Olivier ARCHER Date: Mon, 22 Jul 2024 01:29:09 +0200 Subject: [PATCH 1803/2101] [http_request] allow basic auth for idf (#7086) --- esphome/components/http_request/http_request_idf.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/http_request/http_request_idf.cpp b/esphome/components/http_request/http_request_idf.cpp index d6fac7a133..68e0639b99 100644 --- a/esphome/components/http_request/http_request_idf.cpp +++ b/esphome/components/http_request/http_request_idf.cpp @@ -52,6 +52,7 @@ std::shared_ptr HttpRequestIDF::start(std::string url, std::strin config.timeout_ms = this->timeout_; 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) { config.crt_bundle_attach = esp_crt_bundle_attach; From 4690e227b858a7d2a34cd53aa55645fc03b93878 Mon Sep 17 00:00:00 2001 From: irgendwienet Date: Mon, 22 Jul 2024 01:42:09 +0200 Subject: [PATCH 1804/2101] Fixes sml parser to process extended length lists with a number of items that is dividable by 16 (#6148) --- esphome/components/sml/sml_parser.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/esphome/components/sml/sml_parser.cpp b/esphome/components/sml/sml_parser.cpp index 3b23522b21..c782c0fc5e 100644 --- a/esphome/components/sml/sml_parser.cpp +++ b/esphome/components/sml/sml_parser.cpp @@ -27,7 +27,7 @@ bool SmlFile::setup_node(SmlNode *node) { uint8_t parse_length = length; if (has_extended_length) { length = (length << 4) + (this->buffer_[this->pos_ + 1] & 0x0f); - parse_length = length - 1; + parse_length = length; this->pos_ += 1; } @@ -37,7 +37,9 @@ bool SmlFile::setup_node(SmlNode *node) { node->type = type & 0x07; node->nodes.clear(); node->value_bytes.clear(); - if (this->buffer_[this->pos_] == 0x00) { // end of message + + // if the list is a has_extended_length list with e.g. 16 elements this is a 0x00 byte but not the end of message + if (!has_extended_length && this->buffer_[this->pos_] == 0x00) { // end of message this->pos_ += 1; } else if (is_list) { // list this->pos_ += 1; From 41813b0a1ffeada67d4c5abbdaf9e4ac6095be75 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 22 Jul 2024 12:35:06 +1200 Subject: [PATCH 1805/2101] Bump version to 2024.7.1 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index d581f68470..ff5f7b699d 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.7.0" +__version__ = "2024.7.1" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 0a7d8836339ffc59c37d3363414a827ff4cf42ec Mon Sep 17 00:00:00 2001 From: leejoow Date: Mon, 22 Jul 2024 03:33:11 +0200 Subject: [PATCH 1806/2101] [modbus_controller] Add on_command_sent trigger (#7078) Co-authored-by: Leo Schelvis --- .../components/modbus_controller/__init__.py | 28 +++++++++++++++++-- .../components/modbus_controller/automation.h | 19 +++++++++++++ esphome/components/modbus_controller/const.py | 1 + .../modbus_controller/modbus_controller.cpp | 8 ++++++ .../modbus_controller/modbus_controller.h | 3 ++ 5 files changed, 57 insertions(+), 2 deletions(-) create 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 b8ab48fcc6..1d0f406783 100644 --- a/esphome/components/modbus_controller/__init__.py +++ b/esphome/components/modbus_controller/__init__.py @@ -1,8 +1,16 @@ import binascii import esphome.codegen as cg import esphome.config_validation as cv +from esphome import automation from esphome.components import modbus -from esphome.const import CONF_ADDRESS, CONF_ID, CONF_NAME, CONF_LAMBDA, CONF_OFFSET +from esphome.const import ( + CONF_ADDRESS, + CONF_ID, + CONF_NAME, + CONF_LAMBDA, + CONF_OFFSET, + CONF_TRIGGER_ID, +) from esphome.cpp_helpers import logging from .const import ( CONF_BITMASK, @@ -12,6 +20,7 @@ from .const import ( CONF_CUSTOM_COMMAND, CONF_FORCE_NEW_RANGE, CONF_MODBUS_CONTROLLER_ID, + CONF_ON_COMMAND_SENT, CONF_REGISTER_COUNT, CONF_REGISTER_TYPE, CONF_RESPONSE_SIZE, @@ -97,6 +106,10 @@ TYPE_REGISTER_MAP = { "FP32_R": 2, } +ModbusCommandSentTrigger = modbus_controller_ns.class_( + "ModbusCommandSentTrigger", automation.Trigger.template(cg.int_, cg.int_) +) + _LOGGER = logging.getLogger(__name__) ModbusServerRegisterSchema = cv.Schema( @@ -120,13 +133,19 @@ 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 + ), + } + ), } ) .extend(cv.polling_component_schema("60s")) .extend(modbus.modbus_device_schema(0x01)) ) - ModbusItemBaseSchema = cv.Schema( { cv.GenerateID(CONF_MODBUS_CONTROLLER_ID): cv.use_id(ModbusController), @@ -254,6 +273,11 @@ async def to_code(config): ) ) 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, [(int, "function_code"), (int, "address")], conf + ) async def register_modbus_device(var, config): diff --git a/esphome/components/modbus_controller/automation.h b/esphome/components/modbus_controller/automation.h new file mode 100644 index 0000000000..ad8de4b05d --- /dev/null +++ b/esphome/components/modbus_controller/automation.h @@ -0,0 +1,19 @@ +#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 { + public: + ModbusCommandSentTrigger(ModbusController *a_modbuscontroller) { + a_modbuscontroller->add_on_command_sent_callback( + [this](int function_code, int address) { this->trigger(function_code, address); }); + } +}; + +} // namespace modbus_controller +} // namespace esphome diff --git a/esphome/components/modbus_controller/const.py b/esphome/components/modbus_controller/const.py index 1a23640e17..1f5c39895c 100644 --- a/esphome/components/modbus_controller/const.py +++ b/esphome/components/modbus_controller/const.py @@ -6,6 +6,7 @@ CONF_CUSTOM_COMMAND = "custom_command" CONF_FORCE_NEW_RANGE = "force_new_range" CONF_MODBUS_CONTROLLER_ID = "modbus_controller_id" CONF_MODBUS_FUNCTIONCODE = "modbus_functioncode" +CONF_ON_COMMAND_SENT = "on_command_sent" CONF_RAW_ENCODE = "raw_encode" CONF_REGISTER_COUNT = "register_count" CONF_REGISTER_TYPE = "register_type" diff --git a/esphome/components/modbus_controller/modbus_controller.cpp b/esphome/components/modbus_controller/modbus_controller.cpp index 29d3137603..378e5c06c0 100644 --- a/esphome/components/modbus_controller/modbus_controller.cpp +++ b/esphome/components/modbus_controller/modbus_controller.cpp @@ -43,7 +43,11 @@ bool ModbusController::send_next_command_() { ESP_LOGV(TAG, "Sending next modbus command to device %d register 0x%02X count %d", this->address_, command->register_address, command->register_count); command->send(); + this->last_command_timestamp_ = millis(); + + this->command_sent_callback_.call((int) command->function_code, command->register_address); + // remove from queue if no handler is defined if (!command->on_data_func) { command_queue_.pop_front(); @@ -659,5 +663,9 @@ int64_t payload_to_number(const std::vector &data, SensorValueType sens return value; } +void ModbusController::add_on_command_sent_callback(std::function &&callback) { + this->command_sent_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 9b7d59c93f..3bc11da879 100644 --- a/esphome/components/modbus_controller/modbus_controller.h +++ b/esphome/components/modbus_controller/modbus_controller.h @@ -456,6 +456,8 @@ class ModbusController : public PollingComponent, public modbus::ModbusDevice { size_t get_command_queue_length() { return command_queue_.size(); } /// 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 &&callback); protected: /// parse sensormap_ and create range of sequential addresses @@ -488,6 +490,7 @@ class ModbusController : public PollingComponent, public modbus::ModbusDevice { bool module_offline_; /// how many updates to skip if module is offline uint16_t offline_skip_updates_; + CallbackManager command_sent_callback_{}; }; /** Convert vector response payload to float. From 8fc42694f69743561ee5d4474d768aeb2be9d35b Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Mon, 22 Jul 2024 11:42:25 +1000 Subject: [PATCH 1807/2101] [ili9xxx] Rework delay handling (#7115) --- esphome/components/ili9xxx/ili9xxx_defines.h | 4 ++- .../components/ili9xxx/ili9xxx_display.cpp | 31 ++++++------------- esphome/components/ili9xxx/ili9xxx_display.h | 12 +++---- esphome/components/ili9xxx/ili9xxx_init.h | 8 ++--- 4 files changed, 21 insertions(+), 34 deletions(-) diff --git a/esphome/components/ili9xxx/ili9xxx_defines.h b/esphome/components/ili9xxx/ili9xxx_defines.h index 744013db3d..f4c5aad957 100644 --- a/esphome/components/ili9xxx/ili9xxx_defines.h +++ b/esphome/components/ili9xxx/ili9xxx_defines.h @@ -92,7 +92,9 @@ static const uint8_t ILI9XXX_GMCTRN1 = 0xE1; static const uint8_t ILI9XXX_CSCON = 0xF0; static const uint8_t ILI9XXX_ADJCTL3 = 0xF7; -static const uint8_t ILI9XXX_DELAY = 0xFF; // followed by one byte of delay time in ms +static const uint8_t ILI9XXX_DELAY_FLAG = 0xFF; +// special marker for delay - command byte reprents ms, length byte is an impossible value +#define ILI9XXX_DELAY(ms) ((uint8_t) ((ms) | 0x80)), ILI9XXX_DELAY_FLAG } // namespace ili9xxx } // namespace esphome diff --git a/esphome/components/ili9xxx/ili9xxx_display.cpp b/esphome/components/ili9xxx/ili9xxx_display.cpp index de03df5d41..4f035edbb0 100644 --- a/esphome/components/ili9xxx/ili9xxx_display.cpp +++ b/esphome/components/ili9xxx/ili9xxx_display.cpp @@ -34,8 +34,8 @@ void ILI9XXXDisplay::setup() { ESP_LOGD(TAG, "Setting up ILI9xxx"); this->setup_pins_(); - this->init_lcd(this->init_sequence_); - this->init_lcd(this->extra_init_sequence_.data()); + this->init_lcd_(this->init_sequence_); + this->init_lcd_(this->extra_init_sequence_.data()); switch (this->pixel_mode_) { case PIXEL_MODE_16: if (this->is_18bitdisplay_) { @@ -405,42 +405,29 @@ void ILI9XXXDisplay::reset_() { } } -void ILI9XXXDisplay::init_lcd(const uint8_t *addr) { +void ILI9XXXDisplay::init_lcd_(const uint8_t *addr) { if (addr == nullptr) return; uint8_t cmd, x, num_args; while ((cmd = *addr++) != 0) { x = *addr++; - if (cmd == ILI9XXX_DELAY) { - ESP_LOGD(TAG, "Delay %dms", x); - delay(x); + if (x == ILI9XXX_DELAY_FLAG) { + cmd &= 0x7F; + ESP_LOGV(TAG, "Delay %dms", cmd); + delay(cmd); } else { num_args = x & 0x7F; - ESP_LOGD(TAG, "Command %02X, length %d, bits %02X", cmd, num_args, *addr); + ESP_LOGV(TAG, "Command %02X, length %d, bits %02X", cmd, num_args, *addr); this->send_command(cmd, addr, num_args); addr += num_args; if (x & 0x80) { - ESP_LOGD(TAG, "Delay 150ms"); + ESP_LOGV(TAG, "Delay 150ms"); delay(150); // NOLINT } } } } -void ILI9XXXGC9A01A::init_lcd(const uint8_t *addr) { - if (addr == nullptr) - return; - uint8_t cmd, x, num_args; - while ((cmd = *addr++) != 0) { - x = *addr++; - num_args = x & 0x7F; - this->send_command(cmd, addr, num_args); - addr += num_args; - if (x & 0x80) - delay(150); // NOLINT - } -} - // Tell the display controller where we want to draw pixels. void ILI9XXXDisplay::set_addr_window_(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) { x1 += this->offset_x_; diff --git a/esphome/components/ili9xxx/ili9xxx_display.h b/esphome/components/ili9xxx/ili9xxx_display.h index b60047a8c3..6121488d15 100644 --- a/esphome/components/ili9xxx/ili9xxx_display.h +++ b/esphome/components/ili9xxx/ili9xxx_display.h @@ -33,7 +33,9 @@ class ILI9XXXDisplay : public display::DisplayBuffer, uint8_t cmd, num_args, bits; const uint8_t *addr = init_sequence; while ((cmd = *addr++) != 0) { - num_args = *addr++ & 0x7F; + num_args = *addr++; + if (num_args == ILI9XXX_DELAY_FLAG) + continue; bits = *addr; switch (cmd) { case ILI9XXX_MADCTL: { @@ -50,13 +52,10 @@ class ILI9XXXDisplay : public display::DisplayBuffer, break; } - case ILI9XXX_DELAY: - continue; // no args to skip - default: break; } - addr += num_args; + addr += (num_args & 0x7F); } } @@ -109,7 +108,7 @@ class ILI9XXXDisplay : public display::DisplayBuffer, virtual void set_madctl(); void display_(); - virtual void init_lcd(const uint8_t *addr); + void init_lcd_(const uint8_t *addr); void set_addr_window_(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2); void reset_(); @@ -269,7 +268,6 @@ class ILI9XXXS3BoxLite : public ILI9XXXDisplay { class ILI9XXXGC9A01A : public ILI9XXXDisplay { public: ILI9XXXGC9A01A() : ILI9XXXDisplay(INITCMD_GC9A01A, 240, 240, true) {} - void init_lcd(const uint8_t *addr) override; }; //----------- ILI9XXX_24_TFT display -------------- diff --git a/esphome/components/ili9xxx/ili9xxx_init.h b/esphome/components/ili9xxx/ili9xxx_init.h index 260bde4c80..5a67812bc1 100644 --- a/esphome/components/ili9xxx/ili9xxx_init.h +++ b/esphome/components/ili9xxx/ili9xxx_init.h @@ -372,9 +372,9 @@ static const uint8_t PROGMEM INITCMD_GC9A01A[] = { static const uint8_t PROGMEM INITCMD_ST7735[] = { ILI9XXX_SWRESET, 0, // Soft reset, then delay 10ms - ILI9XXX_DELAY, 10, + ILI9XXX_DELAY(10), ILI9XXX_SLPOUT , 0, // Exit Sleep, delay - ILI9XXX_DELAY, 10, + ILI9XXX_DELAY(10), ILI9XXX_PIXFMT , 1, 0x05, ILI9XXX_FRMCTR1, 3, // 4: Frame rate control, 3 args + delay: 0x01, 0x2C, 0x2D, // Rate = fosc/(1x2+40) * (LINE+2C+2D) @@ -415,9 +415,9 @@ static const uint8_t PROGMEM INITCMD_ST7735[] = { 0x00, 0x00, 0x02, 0x10, ILI9XXX_MADCTL , 1, 0x00, // Memory Access Control, BGR ILI9XXX_NORON , 0, - ILI9XXX_DELAY, 10, + ILI9XXX_DELAY(10), ILI9XXX_DISPON , 0, // Display on - ILI9XXX_DELAY, 10, + ILI9XXX_DELAY(10), 00, // endo of list }; From 5d5f3276e9ec73f8463554137ee67f02aa4d91e5 Mon Sep 17 00:00:00 2001 From: Jan-Philipp Benecke Date: Mon, 22 Jul 2024 06:20:09 +0200 Subject: [PATCH 1808/2101] Inherit `esp32_ble_beacon` from `esp32_ble` (#6908) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/esp32_ble/__init__.py | 19 ++- esphome/components/esp32_ble/ble.cpp | 10 +- esphome/components/esp32_ble/ble.h | 9 + .../components/esp32_ble/ble_advertising.cpp | 51 +++++- .../components/esp32_ble/ble_advertising.h | 22 ++- .../components/esp32_ble_beacon/__init__.py | 18 +- .../esp32_ble_beacon/esp32_ble_beacon.cpp | 160 +++++------------- .../esp32_ble_beacon/esp32_ble_beacon.h | 36 ++-- .../components/esp32_ble_server/__init__.py | 1 - esphome/components/esp32_improv/__init__.py | 1 - 10 files changed, 176 insertions(+), 151 deletions(-) diff --git a/esphome/components/esp32_ble/__init__.py b/esphome/components/esp32_ble/__init__.py index d88161e3e0..472669a381 100644 --- a/esphome/components/esp32_ble/__init__.py +++ b/esphome/components/esp32_ble/__init__.py @@ -7,10 +7,10 @@ from esphome.components.esp32 import add_idf_sdkconfig_option, get_esp32_variant DEPENDENCIES = ["esp32"] CODEOWNERS = ["@jesserockz", "@Rapsssito"] -CONFLICTS_WITH = ["esp32_ble_beacon"] CONF_BLE_ID = "ble_id" CONF_IO_CAPABILITY = "io_capability" +CONF_ADVERTISING_CYCLE_TIME = "advertising_cycle_time" NO_BLUETOOTH_VARIANTS = [const.VARIANT_ESP32S2] @@ -34,6 +34,19 @@ IO_CAPABILITY = { "display_yes_no": IoCapability.IO_CAP_IO, } +esp_power_level_t = cg.global_ns.enum("esp_power_level_t") + +TX_POWER_LEVELS = { + -12: esp_power_level_t.ESP_PWR_LVL_N12, + -9: esp_power_level_t.ESP_PWR_LVL_N9, + -6: esp_power_level_t.ESP_PWR_LVL_N6, + -3: esp_power_level_t.ESP_PWR_LVL_N3, + 0: esp_power_level_t.ESP_PWR_LVL_N0, + 3: esp_power_level_t.ESP_PWR_LVL_P3, + 6: esp_power_level_t.ESP_PWR_LVL_P6, + 9: esp_power_level_t.ESP_PWR_LVL_P9, +} + CONFIG_SCHEMA = cv.Schema( { cv.GenerateID(): cv.declare_id(ESP32BLE), @@ -41,6 +54,9 @@ CONFIG_SCHEMA = cv.Schema( IO_CAPABILITY, lower=True ), cv.Optional(CONF_ENABLE_ON_BOOT, default=True): cv.boolean, + cv.Optional( + CONF_ADVERTISING_CYCLE_TIME, default="10s" + ): cv.positive_time_period_milliseconds, } ).extend(cv.COMPONENT_SCHEMA) @@ -58,6 +74,7 @@ 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])) + cg.add(var.set_advertising_cycle_time(config[CONF_ADVERTISING_CYCLE_TIME])) await cg.register_component(var, config) if CORE.using_esp_idf: diff --git a/esphome/components/esp32_ble/ble.cpp b/esphome/components/esp32_ble/ble.cpp index ceb6516a02..5d08b6e973 100644 --- a/esphome/components/esp32_ble/ble.cpp +++ b/esphome/components/esp32_ble/ble.cpp @@ -78,6 +78,11 @@ void ESP32BLE::advertising_set_manufacturer_data(const std::vector &dat this->advertising_start(); } +void ESP32BLE::advertising_register_raw_advertisement_callback(std::function &&callback) { + this->advertising_init_(); + this->advertising_->register_raw_advertisement_callback(std::move(callback)); +} + void ESP32BLE::advertising_add_service_uuid(ESPBTUUID uuid) { this->advertising_init_(); this->advertising_->add_service_uuid(uuid); @@ -102,7 +107,7 @@ bool ESP32BLE::ble_pre_setup_() { void ESP32BLE::advertising_init_() { if (this->advertising_ != nullptr) return; - this->advertising_ = new BLEAdvertising(); // NOLINT(cppcoreguidelines-owning-memory) + this->advertising_ = new BLEAdvertising(this->advertising_cycle_time_); // NOLINT(cppcoreguidelines-owning-memory) this->advertising_->set_scan_response(true); this->advertising_->set_min_preferred_interval(0x06); @@ -312,6 +317,9 @@ void ESP32BLE::loop() { delete ble_event; // NOLINT(cppcoreguidelines-owning-memory) ble_event = this->ble_events_.pop(); } + if (this->advertising_ != nullptr) { + this->advertising_->loop(); + } } void ESP32BLE::gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) { diff --git a/esphome/components/esp32_ble/ble.h b/esphome/components/esp32_ble/ble.h index 023960d6e4..7c55583852 100644 --- a/esphome/components/esp32_ble/ble.h +++ b/esphome/components/esp32_ble/ble.h @@ -3,6 +3,8 @@ #include "ble_advertising.h" #include "ble_uuid.h" +#include + #include "esphome/core/automation.h" #include "esphome/core/component.h" #include "esphome/core/defines.h" @@ -76,6 +78,11 @@ class ESP32BLE : public Component { public: void set_io_capability(IoCapability io_capability) { this->io_cap_ = (esp_ble_io_cap_t) io_capability; } + void set_advertising_cycle_time(uint32_t advertising_cycle_time) { + this->advertising_cycle_time_ = advertising_cycle_time; + } + uint32_t get_advertising_cycle_time() const { return this->advertising_cycle_time_; } + void enable(); void disable(); bool is_active(); @@ -89,6 +96,7 @@ class ESP32BLE : public Component { void advertising_set_manufacturer_data(const std::vector &data); void advertising_add_service_uuid(ESPBTUUID uuid); void advertising_remove_service_uuid(ESPBTUUID uuid); + void advertising_register_raw_advertisement_callback(std::function &&callback); void register_gap_event_handler(GAPEventHandler *handler) { this->gap_event_handlers_.push_back(handler); } void register_gattc_event_handler(GATTcEventHandler *handler) { this->gattc_event_handlers_.push_back(handler); } @@ -121,6 +129,7 @@ class ESP32BLE : public Component { Queue ble_events_; BLEAdvertising *advertising_; esp_ble_io_cap_t io_cap_{ESP_IO_CAP_NONE}; + uint32_t advertising_cycle_time_; bool enable_on_boot_; }; diff --git a/esphome/components/esp32_ble/ble_advertising.cpp b/esphome/components/esp32_ble/ble_advertising.cpp index 59d2398829..1d340c76d9 100644 --- a/esphome/components/esp32_ble/ble_advertising.cpp +++ b/esphome/components/esp32_ble/ble_advertising.cpp @@ -10,9 +10,9 @@ namespace esphome { namespace esp32_ble { -static const char *const TAG = "esp32_ble"; +static const char *const TAG = "esp32_ble.advertising"; -BLEAdvertising::BLEAdvertising() { +BLEAdvertising::BLEAdvertising(uint32_t advertising_cycle_time) : advertising_cycle_time_(advertising_cycle_time) { this->advertising_data_.set_scan_rsp = false; this->advertising_data_.include_name = true; this->advertising_data_.include_txpower = true; @@ -64,7 +64,7 @@ void BLEAdvertising::set_manufacturer_data(const std::vector &data) { } } -void BLEAdvertising::start() { +esp_err_t BLEAdvertising::services_advertisement_() { int num_services = this->advertising_uuids_.size(); if (num_services == 0) { this->advertising_data_.service_uuid_len = 0; @@ -87,8 +87,8 @@ void BLEAdvertising::start() { this->advertising_data_.include_txpower = !this->scan_response_; err = esp_ble_gap_config_adv_data(&this->advertising_data_); if (err != ESP_OK) { - ESP_LOGE(TAG, "esp_ble_gap_config_adv_data failed (Advertising): %d", err); - return; + ESP_LOGE(TAG, "esp_ble_gap_config_adv_data failed (Advertising): %s", esp_err_to_name(err)); + return err; } if (this->scan_response_) { @@ -101,8 +101,8 @@ void BLEAdvertising::start() { this->scan_response_data_.flag = 0; err = esp_ble_gap_config_adv_data(&this->scan_response_data_); if (err != ESP_OK) { - ESP_LOGE(TAG, "esp_ble_gap_config_adv_data failed (Scan response): %d", err); - return; + ESP_LOGE(TAG, "esp_ble_gap_config_adv_data failed (Scan response): %s", esp_err_to_name(err)); + return err; } } @@ -113,8 +113,18 @@ void BLEAdvertising::start() { err = esp_ble_gap_start_advertising(&this->advertising_params_); if (err != ESP_OK) { - ESP_LOGE(TAG, "esp_ble_gap_start_advertising failed: %d", err); - return; + ESP_LOGE(TAG, "esp_ble_gap_start_advertising failed: %s", esp_err_to_name(err)); + return err; + } + + return ESP_OK; +} + +void BLEAdvertising::start() { + if (this->current_adv_index_ == -1) { + this->services_advertisement_(); + } else { + this->raw_advertisements_callbacks_[this->current_adv_index_](true); } } @@ -124,6 +134,29 @@ void BLEAdvertising::stop() { ESP_LOGE(TAG, "esp_ble_gap_stop_advertising failed: %d", err); return; } + if (this->current_adv_index_ != -1) { + this->raw_advertisements_callbacks_[this->current_adv_index_](false); + } +} + +void BLEAdvertising::loop() { + if (this->raw_advertisements_callbacks_.empty()) { + return; + } + const uint32_t now = millis(); + if (now - this->last_advertisement_time_ > this->advertising_cycle_time_) { + this->stop(); + this->current_adv_index_ += 1; + if (this->current_adv_index_ >= this->raw_advertisements_callbacks_.size()) { + this->current_adv_index_ = -1; + } + this->start(); + this->last_advertisement_time_ = now; + } +} + +void BLEAdvertising::register_raw_advertisement_callback(std::function &&callback) { + this->raw_advertisements_callbacks_.push_back(std::move(callback)); } } // namespace esp32_ble diff --git a/esphome/components/esp32_ble/ble_advertising.h b/esphome/components/esp32_ble/ble_advertising.h index 16a7dd1d8e..946e414c1d 100644 --- a/esphome/components/esp32_ble/ble_advertising.h +++ b/esphome/components/esp32_ble/ble_advertising.h @@ -1,20 +1,31 @@ #pragma once +#include +#include #include #ifdef USE_ESP32 +#include #include #include namespace esphome { namespace esp32_ble { +using raw_adv_data_t = struct { + uint8_t *data; + size_t length; + esp_power_level_t power_level; +}; + class ESPBTUUID; class BLEAdvertising { public: - BLEAdvertising(); + BLEAdvertising(uint32_t advertising_cycle_time); + + void loop(); void add_service_uuid(ESPBTUUID uuid); void remove_service_uuid(ESPBTUUID uuid); @@ -22,16 +33,25 @@ class BLEAdvertising { void set_min_preferred_interval(uint16_t interval) { this->advertising_data_.min_interval = interval; } void set_manufacturer_data(const std::vector &data); void set_service_data(const std::vector &data); + void register_raw_advertisement_callback(std::function &&callback); void start(); void stop(); protected: + esp_err_t services_advertisement_(); + bool scan_response_; esp_ble_adv_data_t advertising_data_; esp_ble_adv_data_t scan_response_data_; esp_ble_adv_params_t advertising_params_; std::vector advertising_uuids_; + + std::vector> raw_advertisements_callbacks_; + + const uint32_t advertising_cycle_time_; + uint32_t last_advertisement_time_{0}; + int8_t current_adv_index_{-1}; // -1 means standard scan response }; } // namespace esp32_ble diff --git a/esphome/components/esp32_ble_beacon/__init__.py b/esphome/components/esp32_ble_beacon/__init__.py index 9aac48cbb2..d063209478 100644 --- a/esphome/components/esp32_ble_beacon/__init__.py +++ b/esphome/components/esp32_ble_beacon/__init__.py @@ -1,16 +1,21 @@ import esphome.codegen as cg import esphome.config_validation as cv +from esphome.components.esp32_ble import CONF_BLE_ID from esphome.const import CONF_ID, CONF_TYPE, CONF_UUID, CONF_TX_POWER from esphome.core import CORE, TimePeriod from esphome.components.esp32 import add_idf_sdkconfig_option from esphome.components import esp32_ble +AUTO_LOAD = ["esp32_ble"] DEPENDENCIES = ["esp32"] -CONFLICTS_WITH = ["esp32_ble_tracker"] esp32_ble_beacon_ns = cg.esphome_ns.namespace("esp32_ble_beacon") -ESP32BLEBeacon = esp32_ble_beacon_ns.class_("ESP32BLEBeacon", cg.Component) - +ESP32BLEBeacon = esp32_ble_beacon_ns.class_( + "ESP32BLEBeacon", + cg.Component, + esp32_ble.GAPEventHandler, + cg.Parented.template(esp32_ble.ESP32BLE), +) CONF_MAJOR = "major" CONF_MINOR = "minor" CONF_MIN_INTERVAL = "min_interval" @@ -28,6 +33,7 @@ CONFIG_SCHEMA = cv.All( cv.Schema( { cv.GenerateID(): cv.declare_id(ESP32BLEBeacon), + cv.GenerateID(CONF_BLE_ID): cv.use_id(esp32_ble.ESP32BLE), cv.Required(CONF_TYPE): cv.one_of("IBEACON", upper=True), cv.Required(CONF_UUID): cv.uuid, cv.Optional(CONF_MAJOR, default=10167): cv.uint16_t, @@ -48,7 +54,7 @@ CONFIG_SCHEMA = cv.All( min=-128, max=0 ), cv.Optional(CONF_TX_POWER, default="3dBm"): cv.All( - cv.decibel, cv.one_of(-12, -9, -6, -3, 0, 3, 6, 9, int=True) + cv.decibel, cv.enum(esp32_ble.TX_POWER_LEVELS, int=True) ), } ).extend(cv.COMPONENT_SCHEMA), @@ -62,6 +68,10 @@ async def to_code(config): uuid = config[CONF_UUID].hex uuid_arr = [cg.RawExpression(f"0x{uuid[i:i + 2]}") for i in range(0, len(uuid), 2)] var = cg.new_Pvariable(config[CONF_ID], uuid_arr) + + parent = await cg.get_variable(config[esp32_ble.CONF_BLE_ID]) + cg.add(parent.register_gap_event_handler(var)) + await cg.register_component(var, config) cg.add(var.set_major(config[CONF_MAJOR])) cg.add(var.set_minor(config[CONF_MINOR])) diff --git a/esphome/components/esp32_ble_beacon/esp32_ble_beacon.cpp b/esphome/components/esp32_ble_beacon/esp32_ble_beacon.cpp index 589fcc1e82..423fe61592 100644 --- a/esphome/components/esp32_ble_beacon/esp32_ble_beacon.cpp +++ b/esphome/components/esp32_ble_beacon/esp32_ble_beacon.cpp @@ -3,14 +3,16 @@ #ifdef USE_ESP32 -#include -#include -#include #include -#include +#include #include +#include +#include +#include #include + #include "esphome/core/hal.h" +#include "esphome/core/helpers.h" #ifdef USE_ARDUINO #include @@ -21,20 +23,6 @@ namespace esp32_ble_beacon { static const char *const TAG = "esp32_ble_beacon"; -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -static esp_ble_adv_params_t ble_adv_params = { - .adv_int_min = 0x20, - .adv_int_max = 0x40, - .adv_type = ADV_TYPE_NONCONN_IND, - .own_addr_type = BLE_ADDR_TYPE_PUBLIC, - .peer_addr = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - .peer_addr_type = BLE_ADDR_TYPE_PUBLIC, - .channel_map = ADV_CHNL_ALL, - .adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, -}; - -#define ENDIAN_CHANGE_U16(x) ((((x) &0xFF00) >> 8) + (((x) &0xFF) << 8)) - static const esp_ble_ibeacon_head_t IBEACON_COMMON_HEAD = { .flags = {0x02, 0x01, 0x06}, .length = 0x1A, .type = 0xFF, .company_id = {0x4C, 0x00}, .beacon_type = {0x02, 0x15}}; @@ -53,117 +41,62 @@ void ESP32BLEBeacon::dump_config() { " 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_); + (this->tx_power_ * 3) - 12); } +float ESP32BLEBeacon::get_setup_priority() const { return setup_priority::AFTER_BLUETOOTH; } + void ESP32BLEBeacon::setup() { - ESP_LOGCONFIG(TAG, "Setting up ESP32 BLE beacon..."); - global_esp32_ble_beacon = this; + this->ble_adv_params_ = { + .adv_int_min = static_cast(this->min_interval_ / 0.625f), + .adv_int_max = static_cast(this->max_interval_ / 0.625f), + .adv_type = ADV_TYPE_NONCONN_IND, + .own_addr_type = BLE_ADDR_TYPE_PUBLIC, + .peer_addr = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + .peer_addr_type = BLE_ADDR_TYPE_PUBLIC, + .channel_map = ADV_CHNL_ALL, + .adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, + }; - xTaskCreatePinnedToCore(ESP32BLEBeacon::ble_core_task, - "ble_task", // name - 10000, // stack size (in words) - nullptr, // input params - 1, // priority - nullptr, // Handle, not needed - 0 // core - ); + global_ble->advertising_register_raw_advertisement_callback([this](bool advertise) { + this->advertising_ = advertise; + if (advertise) { + this->on_advertise_(); + } + }); } -float ESP32BLEBeacon::get_setup_priority() const { return setup_priority::BLUETOOTH; } -void ESP32BLEBeacon::ble_core_task(void *params) { - ble_setup(); - - while (true) { - delay(1000); // NOLINT - } -} - -void ESP32BLEBeacon::ble_setup() { - ble_adv_params.adv_int_min = static_cast(global_esp32_ble_beacon->min_interval_ / 0.625f); - ble_adv_params.adv_int_max = static_cast(global_esp32_ble_beacon->max_interval_ / 0.625f); - - // Initialize non-volatile storage for the bluetooth controller - esp_err_t err = nvs_flash_init(); - if (err != ESP_OK) { - ESP_LOGE(TAG, "nvs_flash_init failed: %d", err); - return; - } - -#ifdef USE_ARDUINO - if (!btStart()) { - ESP_LOGE(TAG, "btStart failed: %d", esp_bt_controller_get_status()); - return; - } -#else - if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) { - // start bt controller - if (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_IDLE) { - esp_bt_controller_config_t cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); - err = esp_bt_controller_init(&cfg); - if (err != ESP_OK) { - ESP_LOGE(TAG, "esp_bt_controller_init failed: %s", esp_err_to_name(err)); - return; - } - while (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_IDLE) - ; - } - if (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_INITED) { - err = esp_bt_controller_enable(ESP_BT_MODE_BLE); - if (err != ESP_OK) { - ESP_LOGE(TAG, "esp_bt_controller_enable failed: %s", esp_err_to_name(err)); - return; - } - } - if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) { - ESP_LOGE(TAG, "esp bt controller enable failed"); - return; - } - } -#endif - - esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT); - - err = esp_bluedroid_init(); - if (err != ESP_OK) { - ESP_LOGE(TAG, "esp_bluedroid_init failed: %d", err); - return; - } - err = esp_bluedroid_enable(); - if (err != ESP_OK) { - ESP_LOGE(TAG, "esp_bluedroid_enable failed: %d", err); - return; - } - err = esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_ADV, - static_cast((global_esp32_ble_beacon->tx_power_ + 12) / 3)); - if (err != ESP_OK) { - ESP_LOGE(TAG, "esp_ble_tx_power_set failed: %s", esp_err_to_name(err)); - return; - } - err = esp_ble_gap_register_callback(ESP32BLEBeacon::gap_event_handler); - if (err != ESP_OK) { - ESP_LOGE(TAG, "esp_ble_gap_register_callback failed: %d", err); - return; - } - +void ESP32BLEBeacon::on_advertise_() { esp_ble_ibeacon_t ibeacon_adv_data; memcpy(&ibeacon_adv_data.ibeacon_head, &IBEACON_COMMON_HEAD, sizeof(esp_ble_ibeacon_head_t)); - memcpy(&ibeacon_adv_data.ibeacon_vendor.proximity_uuid, global_esp32_ble_beacon->uuid_.data(), + memcpy(&ibeacon_adv_data.ibeacon_vendor.proximity_uuid, this->uuid_.data(), sizeof(ibeacon_adv_data.ibeacon_vendor.proximity_uuid)); - ibeacon_adv_data.ibeacon_vendor.minor = ENDIAN_CHANGE_U16(global_esp32_ble_beacon->minor_); - ibeacon_adv_data.ibeacon_vendor.major = ENDIAN_CHANGE_U16(global_esp32_ble_beacon->major_); - ibeacon_adv_data.ibeacon_vendor.measured_power = static_cast(global_esp32_ble_beacon->measured_power_); + ibeacon_adv_data.ibeacon_vendor.minor = byteswap(this->minor_); + ibeacon_adv_data.ibeacon_vendor.major = byteswap(this->major_); + ibeacon_adv_data.ibeacon_vendor.measured_power = static_cast(this->measured_power_); - esp_ble_gap_config_adv_data_raw((uint8_t *) &ibeacon_adv_data, sizeof(ibeacon_adv_data)); + ESP_LOGD(TAG, "Setting BLE TX power"); + esp_err_t 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)); + } + 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)); + return; + } } void ESP32BLEBeacon::gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) { + if (!this->advertising_) + return; + esp_err_t err; switch (event) { case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT: { - err = esp_ble_gap_start_advertising(&ble_adv_params); + err = esp_ble_gap_start_advertising(&this->ble_adv_params_); if (err != ESP_OK) { - ESP_LOGE(TAG, "esp_ble_gap_start_advertising failed: %d", err); + ESP_LOGE(TAG, "esp_ble_gap_start_advertising failed: %s", esp_err_to_name(err)); } break; } @@ -181,6 +114,7 @@ void ESP32BLEBeacon::gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap } else { ESP_LOGD(TAG, "BLE stopped advertising successfully"); } + // this->advertising_ = false; break; } default: @@ -188,8 +122,6 @@ void ESP32BLEBeacon::gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap } } -ESP32BLEBeacon *global_esp32_ble_beacon = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) - } // namespace esp32_ble_beacon } // namespace esphome diff --git a/esphome/components/esp32_ble_beacon/esp32_ble_beacon.h b/esphome/components/esp32_ble_beacon/esp32_ble_beacon.h index 5208b67ea3..e37edf6cde 100644 --- a/esphome/components/esp32_ble_beacon/esp32_ble_beacon.h +++ b/esphome/components/esp32_ble_beacon/esp32_ble_beacon.h @@ -1,39 +1,39 @@ #pragma once +#include "esphome/components/esp32_ble/ble.h" #include "esphome/core/component.h" #ifdef USE_ESP32 -#include #include +#include namespace esphome { namespace esp32_ble_beacon { -// NOLINTNEXTLINE(modernize-use-using) -typedef struct { +using esp_ble_ibeacon_head_t = struct { uint8_t flags[3]; uint8_t length; uint8_t type; uint8_t company_id[2]; uint8_t beacon_type[2]; -} __attribute__((packed)) esp_ble_ibeacon_head_t; +} __attribute__((packed)); -// NOLINTNEXTLINE(modernize-use-using) -typedef struct { +using esp_ble_ibeacon_vendor_t = struct { uint8_t proximity_uuid[16]; uint16_t major; uint16_t minor; uint8_t measured_power; -} __attribute__((packed)) esp_ble_ibeacon_vendor_t; +} __attribute__((packed)); -// NOLINTNEXTLINE(modernize-use-using) -typedef struct { +using esp_ble_ibeacon_t = struct { esp_ble_ibeacon_head_t ibeacon_head; esp_ble_ibeacon_vendor_t ibeacon_vendor; -} __attribute__((packed)) esp_ble_ibeacon_t; +} __attribute__((packed)); -class ESP32BLEBeacon : public Component { +using namespace esp32_ble; + +class ESP32BLEBeacon : public Component, public GAPEventHandler, public Parented { public: explicit ESP32BLEBeacon(const std::array &uuid) : uuid_(uuid) {} @@ -46,12 +46,11 @@ class ESP32BLEBeacon : public Component { 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; } - void set_tx_power(int8_t val) { this->tx_power_ = val; } + void set_tx_power(esp_power_level_t val) { this->tx_power_ = val; } + void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) override; protected: - static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param); - static void ble_core_task(void *params); - static void ble_setup(); + void on_advertise_(); std::array uuid_; uint16_t major_{}; @@ -59,12 +58,11 @@ class ESP32BLEBeacon : public Component { uint16_t min_interval_{}; uint16_t max_interval_{}; int8_t measured_power_{}; - int8_t tx_power_{}; + esp_power_level_t tx_power_{}; + esp_ble_adv_params_t ble_adv_params_; + bool advertising_{false}; }; -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -extern ESP32BLEBeacon *global_esp32_ble_beacon; - } // namespace esp32_ble_beacon } // namespace esphome diff --git a/esphome/components/esp32_ble_server/__init__.py b/esphome/components/esp32_ble_server/__init__.py index f53c9450f4..ce9fdc2cf3 100644 --- a/esphome/components/esp32_ble_server/__init__.py +++ b/esphome/components/esp32_ble_server/__init__.py @@ -7,7 +7,6 @@ from esphome.components.esp32 import add_idf_sdkconfig_option AUTO_LOAD = ["esp32_ble"] CODEOWNERS = ["@jesserockz", "@clydebarrow", "@Rapsssito"] -CONFLICTS_WITH = ["esp32_ble_beacon"] DEPENDENCIES = ["esp32"] CONF_MANUFACTURER = "manufacturer" diff --git a/esphome/components/esp32_improv/__init__.py b/esphome/components/esp32_improv/__init__.py index 49d95d89e5..62d9cd376c 100644 --- a/esphome/components/esp32_improv/__init__.py +++ b/esphome/components/esp32_improv/__init__.py @@ -6,7 +6,6 @@ from esphome.const import CONF_ID AUTO_LOAD = ["esp32_ble_server"] CODEOWNERS = ["@jesserockz"] -CONFLICTS_WITH = ["esp32_ble_beacon"] DEPENDENCIES = ["wifi", "esp32"] CONF_AUTHORIZED_DURATION = "authorized_duration" From f1aa254e4810999d7bb70619ba9c09bb9be5cf98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aodren=20Auffr=C3=A9dou-Heinicke?= <54121510+aodrenah@users.noreply.github.com> Date: Sun, 21 Jul 2024 22:29:54 -0700 Subject: [PATCH 1809/2101] APDS9306 Ambient Light Sensor (#6709) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Co-authored-by: Keith Burzinski Co-authored-by: Mat931 <49403702+Mat931@users.noreply.github.com> --- CODEOWNERS | 1 + esphome/components/apds9306/__init__.py | 4 + esphome/components/apds9306/apds9306.cpp | 151 ++++++++++++++++++ esphome/components/apds9306/apds9306.h | 66 ++++++++ esphome/components/apds9306/sensor.py | 95 +++++++++++ tests/components/apds9306/common.yaml | 12 ++ tests/components/apds9306/test.esp32-ard.yaml | 5 + .../apds9306/test.esp32-c3-ard.yaml | 5 + .../apds9306/test.esp32-c3-idf.yaml | 5 + tests/components/apds9306/test.esp32-idf.yaml | 5 + .../components/apds9306/test.esp8266-ard.yaml | 5 + .../components/apds9306/test.rp2040-ard.yaml | 5 + 12 files changed, 359 insertions(+) create mode 100644 esphome/components/apds9306/__init__.py create mode 100644 esphome/components/apds9306/apds9306.cpp create mode 100644 esphome/components/apds9306/apds9306.h create mode 100644 esphome/components/apds9306/sensor.py create mode 100644 tests/components/apds9306/common.yaml create mode 100644 tests/components/apds9306/test.esp32-ard.yaml create mode 100644 tests/components/apds9306/test.esp32-c3-ard.yaml create mode 100644 tests/components/apds9306/test.esp32-c3-idf.yaml create mode 100644 tests/components/apds9306/test.esp32-idf.yaml create mode 100644 tests/components/apds9306/test.esp8266-ard.yaml create mode 100644 tests/components/apds9306/test.rp2040-ard.yaml diff --git a/CODEOWNERS b/CODEOWNERS index ee76a072fc..c5e144bdfa 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -37,6 +37,7 @@ esphome/components/am43/sensor/* @buxtronix esphome/components/analog_threshold/* @ianchi esphome/components/animation/* @syndlex esphome/components/anova/* @buxtronix +esphome/components/apds9306/* @aodrenah esphome/components/api/* @OttoWinter esphome/components/as5600/* @ammmze esphome/components/as5600/sensor/* @ammmze diff --git a/esphome/components/apds9306/__init__.py b/esphome/components/apds9306/__init__.py new file mode 100644 index 0000000000..3dc8fcf5ff --- /dev/null +++ b/esphome/components/apds9306/__init__.py @@ -0,0 +1,4 @@ +# Based on this datasheet: +# https://www.mouser.ca/datasheet/2/678/AVGO_S_A0002854364_1-2574547.pdf + +CODEOWNERS = ["@aodrenah"] diff --git a/esphome/components/apds9306/apds9306.cpp b/esphome/components/apds9306/apds9306.cpp new file mode 100644 index 0000000000..7b79b0964c --- /dev/null +++ b/esphome/components/apds9306/apds9306.cpp @@ -0,0 +1,151 @@ +// Based on this datasheet: +// https://www.mouser.ca/datasheet/2/678/AVGO_S_A0002854364_1-2574547.pdf + +#include "apds9306.h" +#include "esphome/core/helpers.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace apds9306 { + +static const char *const TAG = "apds9306"; + +enum { // APDS9306 registers + APDS9306_MAIN_CTRL = 0x00, + APDS9306_ALS_MEAS_RATE = 0x04, + APDS9306_ALS_GAIN = 0x05, + APDS9306_PART_ID = 0x06, + APDS9306_MAIN_STATUS = 0x07, + APDS9306_CLEAR_DATA_0 = 0x0A, // LSB + APDS9306_CLEAR_DATA_1 = 0x0B, + APDS9306_CLEAR_DATA_2 = 0x0C, // MSB + APDS9306_ALS_DATA_0 = 0x0D, // LSB + APDS9306_ALS_DATA_1 = 0x0E, + APDS9306_ALS_DATA_2 = 0x0F, // MSB + APDS9306_INT_CFG = 0x19, + APDS9306_INT_PERSISTENCE = 0x1A, + APDS9306_ALS_THRES_UP_0 = 0x21, // LSB + APDS9306_ALS_THRES_UP_1 = 0x22, + APDS9306_ALS_THRES_UP_2 = 0x23, // MSB + APDS9306_ALS_THRES_LOW_0 = 0x24, // LSB + APDS9306_ALS_THRES_LOW_1 = 0x25, + APDS9306_ALS_THRES_LOW_2 = 0x26, // MSB + APDS9306_ALS_THRES_VAR = 0x27 +}; + +#define APDS9306_ERROR_CHECK(func, error) \ + if (!(func)) { \ + ESP_LOGE(TAG, error); \ + this->mark_failed(); \ + return; \ + } +#define APDS9306_WARNING_CHECK(func, warning) \ + if (!(func)) { \ + ESP_LOGW(TAG, warning); \ + this->status_set_warning(); \ + return; \ + } +#define APDS9306_WRITE_BYTE(reg, value) \ + ESP_LOGV(TAG, "Writing 0x%02x to 0x%02x", value, reg); \ + if (!this->write_byte(reg, value)) { \ + ESP_LOGE(TAG, "Failed writing 0x%02x to 0x%02x", value, reg); \ + this->mark_failed(); \ + return; \ + } + +void APDS9306::setup() { + ESP_LOGCONFIG(TAG, "Setting up APDS9306..."); + + uint8_t id; + if (!this->read_byte(APDS9306_PART_ID, &id)) { // Part ID register + this->error_code_ = COMMUNICATION_FAILED; + this->mark_failed(); + return; + } + + if (id != 0xB1 && id != 0xB3) { // 0xB1 for APDS9306 0xB3 for APDS9306-065 + this->error_code_ = WRONG_ID; + this->mark_failed(); + return; + } + + // ALS resolution and measurement, see datasheet or init.py for options + uint8_t als_meas_rate = ((this->bit_width_ & 0x07) << 4) | (this->measurement_rate_ & 0x07); + APDS9306_WRITE_BYTE(APDS9306_ALS_MEAS_RATE, als_meas_rate); + + // ALS gain, see datasheet or init.py for options + uint8_t als_gain = (this->gain_ & 0x07); + APDS9306_WRITE_BYTE(APDS9306_ALS_GAIN, als_gain); + + // Set to standby mode + APDS9306_WRITE_BYTE(APDS9306_MAIN_CTRL, 0x00); + + // Check for data, clear main status + uint8_t status; + APDS9306_WARNING_CHECK(this->read_byte(APDS9306_MAIN_STATUS, &status), "Reading MAIN STATUS failed."); + + // Set to active mode + APDS9306_WRITE_BYTE(APDS9306_MAIN_CTRL, 0x02); + + ESP_LOGCONFIG(TAG, "APDS9306 setup complete"); +} + +void APDS9306::dump_config() { + LOG_SENSOR("", "APDS9306", this); + LOG_I2C_DEVICE(this); + + if (this->is_failed()) { + switch (this->error_code_) { + case COMMUNICATION_FAILED: + ESP_LOGE(TAG, "Communication with APDS9306 failed!"); + break; + case WRONG_ID: + ESP_LOGE(TAG, "APDS9306 has invalid id!"); + break; + default: + ESP_LOGE(TAG, "Setting up APDS9306 registers failed!"); + break; + } + } + + ESP_LOGCONFIG(TAG, " Gain: %u", AMBIENT_LIGHT_GAIN_VALUES[this->gain_]); + ESP_LOGCONFIG(TAG, " Measurement rate: %u", MEASUREMENT_RATE_VALUES[this->measurement_rate_]); + ESP_LOGCONFIG(TAG, " Measurement Resolution/Bit width: %d", MEASUREMENT_BIT_WIDTH_VALUES[this->bit_width_]); + + LOG_UPDATE_INTERVAL(this); +} + +void APDS9306::update() { + // Check for new data + uint8_t status; + APDS9306_WARNING_CHECK(this->read_byte(APDS9306_MAIN_STATUS, &status), "Reading MAIN STATUS failed."); + + this->status_clear_warning(); + + if (!(status &= 0b00001000)) { // No new data + return; + } + + // Set to standby mode + APDS9306_WRITE_BYTE(APDS9306_MAIN_CTRL, 0x00); + + // Clear MAIN STATUS + APDS9306_WARNING_CHECK(this->read_byte(APDS9306_MAIN_STATUS, &status), "Reading MAIN STATUS failed."); + + uint8_t als_data[3]; + APDS9306_WARNING_CHECK(this->read_bytes(APDS9306_ALS_DATA_0, als_data, 3), "Reading ALS data has failed."); + + // Set to active mode + APDS9306_WRITE_BYTE(APDS9306_MAIN_CTRL, 0x02); + + uint32_t light_level = 0x00 | encode_uint24(als_data[2], als_data[1], als_data[0]); + + float lux = ((float) light_level / AMBIENT_LIGHT_GAIN_VALUES[this->gain_]) * + (100.0f / MEASUREMENT_RATE_VALUES[this->measurement_rate_]); + + ESP_LOGD(TAG, "Got illuminance=%.1flx from", lux); + this->publish_state(lux); +} + +} // namespace apds9306 +} // namespace esphome diff --git a/esphome/components/apds9306/apds9306.h b/esphome/components/apds9306/apds9306.h new file mode 100644 index 0000000000..44362908c8 --- /dev/null +++ b/esphome/components/apds9306/apds9306.h @@ -0,0 +1,66 @@ +// Based on this datasheet: +// https://www.mouser.ca/datasheet/2/678/AVGO_S_A0002854364_1-2574547.pdf + +#pragma once + +#include "esphome/components/i2c/i2c.h" +#include "esphome/components/sensor/sensor.h" +#include "esphome/core/component.h" + +namespace esphome { +namespace apds9306 { + +enum MeasurementBitWidth : uint8_t { + MEASUREMENT_BIT_WIDTH_20 = 0, + MEASUREMENT_BIT_WIDTH_19 = 1, + MEASUREMENT_BIT_WIDTH_18 = 2, + MEASUREMENT_BIT_WIDTH_17 = 3, + MEASUREMENT_BIT_WIDTH_16 = 4, + MEASUREMENT_BIT_WIDTH_13 = 5, +}; +static const uint8_t MEASUREMENT_BIT_WIDTH_VALUES[] = {20, 19, 18, 17, 16, 13}; + +enum MeasurementRate : uint8_t { + MEASUREMENT_RATE_25 = 0, + MEASUREMENT_RATE_50 = 1, + MEASUREMENT_RATE_100 = 2, + MEASUREMENT_RATE_200 = 3, + MEASUREMENT_RATE_500 = 4, + MEASUREMENT_RATE_1000 = 5, + MEASUREMENT_RATE_2000 = 6, +}; +static const uint16_t MEASUREMENT_RATE_VALUES[] = {25, 50, 100, 200, 500, 1000, 2000}; + +enum AmbientLightGain : uint8_t { + AMBIENT_LIGHT_GAIN_1 = 0, + AMBIENT_LIGHT_GAIN_3 = 1, + AMBIENT_LIGHT_GAIN_6 = 2, + AMBIENT_LIGHT_GAIN_9 = 3, + AMBIENT_LIGHT_GAIN_18 = 4, +}; +static const uint8_t AMBIENT_LIGHT_GAIN_VALUES[] = {1, 3, 6, 9, 18}; + +class APDS9306 : public sensor::Sensor, public PollingComponent, public i2c::I2CDevice { + public: + void setup() override; + float get_setup_priority() const override { return setup_priority::BUS; } + void dump_config() override; + void update() override; + void set_bit_width(MeasurementBitWidth bit_width) { this->bit_width_ = bit_width; } + void set_measurement_rate(MeasurementRate measurement_rate) { this->measurement_rate_ = measurement_rate; } + void set_ambient_light_gain(AmbientLightGain gain) { this->gain_ = gain; } + + protected: + enum ErrorCode { + NONE = 0, + COMMUNICATION_FAILED, + WRONG_ID, + } error_code_{NONE}; + + MeasurementBitWidth bit_width_; + MeasurementRate measurement_rate_; + AmbientLightGain gain_; +}; + +} // namespace apds9306 +} // namespace esphome diff --git a/esphome/components/apds9306/sensor.py b/esphome/components/apds9306/sensor.py new file mode 100644 index 0000000000..25b301444f --- /dev/null +++ b/esphome/components/apds9306/sensor.py @@ -0,0 +1,95 @@ +# Based on this datasheet: +# https://www.mouser.ca/datasheet/2/678/AVGO_S_A0002854364_1-2574547.pdf + +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import i2c, sensor +from esphome.const import ( + CONF_GAIN, + DEVICE_CLASS_ILLUMINANCE, + ICON_LIGHTBULB, + STATE_CLASS_MEASUREMENT, + UNIT_LUX, +) + +DEPENDENCIES = ["i2c"] + +CONF_APDS9306_ID = "apds9306_id" +CONF_BIT_WIDTH = "bit_width" +CONF_MEASUREMENT_RATE = "measurement_rate" + +apds9306_ns = cg.esphome_ns.namespace("apds9306") +APDS9306 = apds9306_ns.class_( + "APDS9306", sensor.Sensor, cg.PollingComponent, i2c.I2CDevice +) + +MeasurementBitWidth = apds9306_ns.enum("MeasurementBitWidth") +MeasurementRate = apds9306_ns.enum("MeasurementRate") +AmbientLightGain = apds9306_ns.enum("AmbientLightGain") + +MEASUREMENT_BIT_WIDTHS = { + 20: MeasurementBitWidth.MEASUREMENT_BIT_WIDTH_20, + 19: MeasurementBitWidth.MEASUREMENT_BIT_WIDTH_19, + 18: MeasurementBitWidth.MEASUREMENT_BIT_WIDTH_18, + 17: MeasurementBitWidth.MEASUREMENT_BIT_WIDTH_17, + 16: MeasurementBitWidth.MEASUREMENT_BIT_WIDTH_16, + 13: MeasurementBitWidth.MEASUREMENT_BIT_WIDTH_13, +} + +MEASUREMENT_RATES = { + 25: MeasurementRate.MEASUREMENT_RATE_25, + 50: MeasurementRate.MEASUREMENT_RATE_50, + 100: MeasurementRate.MEASUREMENT_RATE_100, + 200: MeasurementRate.MEASUREMENT_RATE_200, + 500: MeasurementRate.MEASUREMENT_RATE_500, + 1000: MeasurementRate.MEASUREMENT_RATE_1000, + 2000: MeasurementRate.MEASUREMENT_RATE_2000, +} + +AMBIENT_LIGHT_GAINS = { + 1: AmbientLightGain.AMBIENT_LIGHT_GAIN_1, + 3: AmbientLightGain.AMBIENT_LIGHT_GAIN_3, + 6: AmbientLightGain.AMBIENT_LIGHT_GAIN_6, + 9: AmbientLightGain.AMBIENT_LIGHT_GAIN_9, + 18: AmbientLightGain.AMBIENT_LIGHT_GAIN_18, +} + + +def _validate_measurement_rate(value): + value = cv.positive_time_period_milliseconds(value) + return cv.enum(MEASUREMENT_RATES, int=True)(value.total_milliseconds) + + +CONFIG_SCHEMA = ( + sensor.sensor_schema( + APDS9306, + unit_of_measurement=UNIT_LUX, + accuracy_decimals=1, + device_class=DEVICE_CLASS_ILLUMINANCE, + state_class=STATE_CLASS_MEASUREMENT, + icon=ICON_LIGHTBULB, + ) + .extend( + { + cv.Optional(CONF_GAIN, default="1"): cv.enum(AMBIENT_LIGHT_GAINS, int=True), + cv.Optional(CONF_BIT_WIDTH, default="18"): cv.enum( + MEASUREMENT_BIT_WIDTHS, int=True + ), + cv.Optional( + CONF_MEASUREMENT_RATE, default="100ms" + ): _validate_measurement_rate, + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x52)) +) + + +async def to_code(config): + var = await sensor.new_sensor(config) + await cg.register_component(var, config) + await i2c.register_i2c_device(var, config) + + cg.add(var.set_bit_width(config[CONF_BIT_WIDTH])) + cg.add(var.set_measurement_rate(config[CONF_MEASUREMENT_RATE])) + cg.add(var.set_ambient_light_gain(config[CONF_GAIN])) diff --git a/tests/components/apds9306/common.yaml b/tests/components/apds9306/common.yaml new file mode 100644 index 0000000000..b3828e62ff --- /dev/null +++ b/tests/components/apds9306/common.yaml @@ -0,0 +1,12 @@ +i2c: + - id: i2c_apds9306 + scl: ${scl_pin} + sda: ${sda_pin} + +sensor: + - platform: apds9306 + name: "APDS9306 Light Level" + gain: 3 + bit_width: 16 + measurement_rate: 2000ms + update_interval: 60s diff --git a/tests/components/apds9306/test.esp32-ard.yaml b/tests/components/apds9306/test.esp32-ard.yaml new file mode 100644 index 0000000000..3b761d3fc1 --- /dev/null +++ b/tests/components/apds9306/test.esp32-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO22 + sda_pin: GPIO21 + +<<: !include common.yaml diff --git a/tests/components/apds9306/test.esp32-c3-ard.yaml b/tests/components/apds9306/test.esp32-c3-ard.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/apds9306/test.esp32-c3-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/apds9306/test.esp32-c3-idf.yaml b/tests/components/apds9306/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/apds9306/test.esp32-c3-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/apds9306/test.esp32-idf.yaml b/tests/components/apds9306/test.esp32-idf.yaml new file mode 100644 index 0000000000..3b761d3fc1 --- /dev/null +++ b/tests/components/apds9306/test.esp32-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO22 + sda_pin: GPIO21 + +<<: !include common.yaml diff --git a/tests/components/apds9306/test.esp8266-ard.yaml b/tests/components/apds9306/test.esp8266-ard.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/apds9306/test.esp8266-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/apds9306/test.rp2040-ard.yaml b/tests/components/apds9306/test.rp2040-ard.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/apds9306/test.rp2040-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml From dc24eefe08fb44491ef7623e7db551c319c11521 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Jul 2024 13:01:45 +1200 Subject: [PATCH 1810/2101] Bump docker/build-push-action from 6.4.1 to 6.5.0 in /.github/actions/build-image (#7119) 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 e2febdad1b..bd9ceb8072 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -46,7 +46,7 @@ runs: - name: Build and push to ghcr by digest id: build-ghcr - uses: docker/build-push-action@v6.4.1 + uses: docker/build-push-action@v6.5.0 with: context: . file: ./docker/Dockerfile @@ -69,7 +69,7 @@ runs: - name: Build and push to dockerhub by digest id: build-dockerhub - uses: docker/build-push-action@v6.4.1 + uses: docker/build-push-action@v6.5.0 with: context: . file: ./docker/Dockerfile From ae476bb400f14d51c0e569a3807264a7abcd01e1 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 23 Jul 2024 13:51:32 +1200 Subject: [PATCH 1811/2101] [http_request] Change default timeout to 4.5s (#7123) --- esphome/components/http_request/__init__.py | 2 +- esphome/components/http_request/http_request.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/http_request/__init__.py b/esphome/components/http_request/__init__.py index ade7024bed..ef387553fe 100644 --- a/esphome/components/http_request/__init__.py +++ b/esphome/components/http_request/__init__.py @@ -99,7 +99,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_FOLLOW_REDIRECTS, True): cv.boolean, cv.Optional(CONF_REDIRECT_LIMIT, 3): cv.int_, cv.Optional( - CONF_TIMEOUT, default="5s" + CONF_TIMEOUT, default="4.5s" ): cv.positive_time_period_milliseconds, cv.SplitDefault(CONF_ESP8266_DISABLE_SSL_SUPPORT, esp8266=False): cv.All( cv.only_on_esp8266, cv.boolean diff --git a/esphome/components/http_request/http_request.h b/esphome/components/http_request/http_request.h index 82b7392648..c01baf8644 100644 --- a/esphome/components/http_request/http_request.h +++ b/esphome/components/http_request/http_request.h @@ -80,7 +80,7 @@ class HttpRequestComponent : public Component { const char *useragent_{nullptr}; bool follow_redirects_; uint16_t redirect_limit_; - uint16_t timeout_{5000}; + uint16_t timeout_{4500}; uint32_t watchdog_timeout_{0}; }; From 2b2a83273fdad8c105acf5a7aedd1d63042891ef Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Jul 2024 14:20:44 +1200 Subject: [PATCH 1812/2101] Bump docker/setup-qemu-action from 3.1.0 to 3.2.0 (#7120) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-docker.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-docker.yml b/.github/workflows/ci-docker.yml index 147efe089e..999a2f03d2 100644 --- a/.github/workflows/ci-docker.yml +++ b/.github/workflows/ci-docker.yml @@ -48,7 +48,7 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3.4.0 - name: Set up QEMU - uses: docker/setup-qemu-action@v3.1.0 + uses: docker/setup-qemu-action@v3.2.0 - name: Set TAG run: | diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f66c504bda..2fdac00589 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -93,7 +93,7 @@ jobs: uses: docker/setup-buildx-action@v3.4.0 - name: Set up QEMU if: matrix.platform != 'linux/amd64' - uses: docker/setup-qemu-action@v3.1.0 + uses: docker/setup-qemu-action@v3.2.0 - name: Log in to docker hub uses: docker/login-action@v3.2.0 From f0d4b5f74051b596752f3df0e3332720ef79f089 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Jul 2024 14:20:54 +1200 Subject: [PATCH 1813/2101] Bump docker/login-action from 3.2.0 to 3.3.0 (#7121) 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 2fdac00589..c1488d8b89 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -96,12 +96,12 @@ jobs: uses: docker/setup-qemu-action@v3.2.0 - name: Log in to docker hub - uses: docker/login-action@v3.2.0 + uses: docker/login-action@v3.3.0 with: username: ${{ secrets.DOCKER_USER }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Log in to the GitHub container registry - uses: docker/login-action@v3.2.0 + uses: docker/login-action@v3.3.0 with: registry: ghcr.io username: ${{ github.actor }} @@ -188,13 +188,13 @@ jobs: - name: Log in to docker hub if: matrix.registry == 'dockerhub' - uses: docker/login-action@v3.2.0 + uses: docker/login-action@v3.3.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@v3.2.0 + uses: docker/login-action@v3.3.0 with: registry: ghcr.io username: ${{ github.actor }} From e88e32bf232080d9f7ab0cbb47e22d59557b9860 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Jul 2024 14:21:03 +1200 Subject: [PATCH 1814/2101] Bump docker/setup-buildx-action from 3.4.0 to 3.5.0 (#7122) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-docker.yml | 2 +- .github/workflows/release.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-docker.yml b/.github/workflows/ci-docker.yml index 999a2f03d2..2b4539105b 100644 --- a/.github/workflows/ci-docker.yml +++ b/.github/workflows/ci-docker.yml @@ -46,7 +46,7 @@ jobs: with: python-version: "3.9" - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3.4.0 + uses: docker/setup-buildx-action@v3.5.0 - name: Set up QEMU uses: docker/setup-qemu-action@v3.2.0 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c1488d8b89..efec556059 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -90,7 +90,7 @@ jobs: python-version: "3.9" - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3.4.0 + uses: docker/setup-buildx-action@v3.5.0 - name: Set up QEMU if: matrix.platform != 'linux/amd64' uses: docker/setup-qemu-action@v3.2.0 @@ -184,7 +184,7 @@ jobs: merge-multiple: true - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3.4.0 + uses: docker/setup-buildx-action@v3.5.0 - name: Log in to docker hub if: matrix.registry == 'dockerhub' From 19a787c2352bca62c3e642ed421a4e2a0185cfaa Mon Sep 17 00:00:00 2001 From: Daniel Date: Tue, 23 Jul 2024 04:53:31 +0200 Subject: [PATCH 1815/2101] [fan] fix initial FanCall to properly set speed (#7113) Speed settings were ignored for the first FanCall, if no speed has been restored before. This commit changes the behaviour to: set speed to 100%, iff current speed AND new speed are not set. --- esphome/components/fan/fan.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/fan/fan.cpp b/esphome/components/fan/fan.cpp index 95e3ae0758..1d560d2fc6 100644 --- a/esphome/components/fan/fan.cpp +++ b/esphome/components/fan/fan.cpp @@ -45,8 +45,8 @@ void FanCall::validate_() { this->speed_ = clamp(*this->speed_, 1, traits.supported_speed_count()); if (this->binary_state_.has_value() && *this->binary_state_) { - // when turning on, if current speed is zero, set speed to 100% - if (traits.supports_speed() && !this->parent_.state && this->parent_.speed == 0) { + // when turning on, if neither current nor new speed available, set speed to 100% + if (traits.supports_speed() && !this->parent_.state && this->parent_.speed == 0 && !this->speed_.has_value()) { this->speed_ = traits.supported_speed_count(); } } From 2cc14055cfa4080dfb3c0612cefa96ee0a76df9b Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Tue, 23 Jul 2024 14:12:23 +1000 Subject: [PATCH 1816/2101] Added ruff to pre-commit hooks (#7124) --- .pre-commit-config.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 74acfa1c1d..aeb434167a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,6 +2,15 @@ # See https://pre-commit.com for more information # See https://pre-commit.com/hooks.html for more hooks repos: + - repo: https://github.com/astral-sh/ruff-pre-commit + # Ruff version. + rev: v0.5.4 + hooks: + # Run the linter. + - id: ruff + args: [--fix] + # Run the formatter. + - id: ruff-format - repo: https://github.com/psf/black-pre-commit-mirror rev: 24.4.2 hooks: From 39de179e213f79f8016a1ae764c87fe77333d5dc Mon Sep 17 00:00:00 2001 From: dentra Date: Wed, 24 Jul 2024 03:12:59 +0300 Subject: [PATCH 1817/2101] [http_request] Fix ESP-IDF follow redirect (#7101) --- esphome/components/http_request/__init__.py | 14 ++-- .../http_request/http_request_idf.cpp | 66 +++++++++++++++---- 2 files changed, 62 insertions(+), 18 deletions(-) diff --git a/esphome/components/http_request/__init__.py b/esphome/components/http_request/__init__.py index ef387553fe..161486fbb2 100644 --- a/esphome/components/http_request/__init__.py +++ b/esphome/components/http_request/__init__.py @@ -1,17 +1,17 @@ -import esphome.codegen as cg -import esphome.config_validation as cv from esphome import automation +import esphome.codegen as cg +from esphome.components import esp32 +import esphome.config_validation as cv from esphome.const import ( - __version__, + CONF_ESP8266_DISABLE_SSL_SUPPORT, CONF_ID, - CONF_TIMEOUT, CONF_METHOD, + CONF_TIMEOUT, CONF_TRIGGER_ID, CONF_URL, - CONF_ESP8266_DISABLE_SSL_SUPPORT, + __version__, ) -from esphome.core import Lambda, CORE -from esphome.components import esp32 +from esphome.core import CORE, Lambda DEPENDENCIES = ["network"] AUTO_LOAD = ["json"] diff --git a/esphome/components/http_request/http_request_idf.cpp b/esphome/components/http_request/http_request_idf.cpp index 68e0639b99..1f03b5f3bf 100644 --- a/esphome/components/http_request/http_request_idf.cpp +++ b/esphome/components/http_request/http_request_idf.cpp @@ -77,7 +77,7 @@ std::shared_ptr HttpRequestIDF::start(std::string url, std::strin esp_http_client_set_header(client, header.name, header.value); } - int body_len = body.length(); + const int body_len = body.length(); esp_err_t err = esp_http_client_open(client, body_len); if (err != ESP_OK) { @@ -109,18 +109,62 @@ std::shared_ptr HttpRequestIDF::start(std::string url, std::strin return nullptr; } - container->content_length = esp_http_client_fetch_headers(client); - const auto status_code = esp_http_client_get_status_code(client); - container->status_code = status_code; + auto is_ok = [](int code) { return code >= HttpStatus_Ok && code < HttpStatus_MultipleChoices; }; - if (status_code < 200 || status_code >= 300) { - ESP_LOGE(TAG, "HTTP Request failed; URL: %s; Code: %d", url.c_str(), status_code); - this->status_momentary_error("failed", 1000); - esp_http_client_cleanup(client); - return nullptr; + container->content_length = esp_http_client_fetch_headers(client); + container->status_code = esp_http_client_get_status_code(client); + if (is_ok(container->status_code)) { + container->duration_ms = millis() - start; + return container; } - container->duration_ms = millis() - start; - return container; + + if (this->follow_redirects_) { + auto is_redirect = [](int code) { + return code == HttpStatus_MovedPermanently || code == HttpStatus_Found || code == HttpStatus_SeeOther || + code == HttpStatus_TemporaryRedirect || code == HttpStatus_PermanentRedirect; + }; + auto num_redirects = this->redirect_limit_; + while (is_redirect(container->status_code) && num_redirects > 0) { + 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); + esp_http_client_cleanup(client); + return nullptr; + } +#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE + char url[256]{}; + if (esp_http_client_get_url(client, url, sizeof(url) - 1) == ESP_OK) { + ESP_LOGV(TAG, "redirecting to url: %s", url); + } +#endif + 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); + esp_http_client_cleanup(client); + return nullptr; + } + + container->content_length = esp_http_client_fetch_headers(client); + container->status_code = esp_http_client_get_status_code(client); + if (is_ok(container->status_code)) { + container->duration_ms = millis() - start; + return container; + } + + num_redirects--; + } + + if (num_redirects == 0) { + ESP_LOGW(TAG, "Reach redirect limit count=%d", this->redirect_limit_); + } + } + + ESP_LOGE(TAG, "HTTP Request failed; URL: %s; Code: %d", url.c_str(), container->status_code); + this->status_momentary_error("failed", 1000); + esp_http_client_cleanup(client); + return nullptr; } int HttpContainerIDF::read(uint8_t *buf, size_t max_len) { From da10de9ea8c0129394cb98ccd3b79fcdcb78dfb0 Mon Sep 17 00:00:00 2001 From: esphomebot Date: Wed, 24 Jul 2024 13:57:02 +1200 Subject: [PATCH 1818/2101] Update webserver local assets to 20240724-013115 (#7126) --- .../components/web_server/server_index_v3.h | 7218 +++++++++-------- 1 file changed, 3615 insertions(+), 3603 deletions(-) diff --git a/esphome/components/web_server/server_index_v3.h b/esphome/components/web_server/server_index_v3.h index 0c16ea9f37..0f3f743a73 100644 --- a/esphome/components/web_server/server_index_v3.h +++ b/esphome/components/web_server/server_index_v3.h @@ -397,3609 +397,3621 @@ const uint8_t INDEX_GZ[] PROGMEM = { 0xa5, 0x01, 0xe6, 0xde, 0x48, 0xc3, 0x50, 0xf1, 0xe6, 0x90, 0xe9, 0x1b, 0xc6, 0xc4, 0xb7, 0x07, 0x71, 0x99, 0x4a, 0x91, 0xdf, 0xd9, 0xcf, 0x65, 0xd8, 0x25, 0x5d, 0x68, 0xb9, 0x4e, 0x86, 0x5c, 0xd0, 0xe2, 0xee, 0x5a, 0x31, 0xa1, 0x64, 0x71, 0x2d, 0xc7, 0xe3, 0xe5, 0xb7, 0x48, 0xcb, 0x7d, 0xb4, 0x4e, 0x14, 0x17, 0x93, 0x9c, 0x59, 0xa2, 0x64, - 0x10, 0xc1, 0x11, 0x73, 0xdb, 0xae, 0x69, 0xb2, 0x36, 0xe8, 0x70, 0xe7, 0x99, 0x76, 0x07, 0x69, 0xda, 0xbc, 0x61, - 0xc3, 0xcf, 0x5c, 0x5b, 0x3c, 0x6b, 0xaa, 0x1b, 0xf0, 0x78, 0x31, 0xcb, 0x30, 0x67, 0xc5, 0xd2, 0xd3, 0xf0, 0x56, - 0x8d, 0xea, 0x5c, 0x09, 0x73, 0x7a, 0x68, 0x3a, 0x6c, 0x42, 0xfc, 0x2f, 0x56, 0x94, 0x7b, 0x8c, 0x0b, 0x83, 0x31, - 0x06, 0x40, 0x9b, 0xbb, 0x24, 0x3c, 0x03, 0x4e, 0x5a, 0x2d, 0x7f, 0x3e, 0x34, 0x6d, 0x9d, 0xb4, 0x9d, 0x9c, 0xb2, - 0xd9, 0xae, 0xfd, 0x59, 0x27, 0x46, 0xed, 0xce, 0xfc, 0x76, 0xcf, 0xfc, 0xd3, 0xda, 0x6b, 0x6d, 0x13, 0x9f, 0x6d, - 0x38, 0x1d, 0x23, 0xbf, 0xb2, 0x5a, 0xce, 0xd3, 0x36, 0x9b, 0x75, 0x17, 0x0a, 0x0e, 0x1a, 0x43, 0x1b, 0xcd, 0x01, - 0xb6, 0x36, 0x33, 0x81, 0x75, 0xa4, 0x5c, 0x00, 0x5d, 0xb7, 0x67, 0x1b, 0xf4, 0xa1, 0x24, 0x18, 0x62, 0xef, 0x6c, - 0xb4, 0x3e, 0xac, 0xd6, 0x5e, 0x35, 0x30, 0xf8, 0x67, 0xfd, 0x57, 0xc5, 0x19, 0xbe, 0x60, 0x01, 0x67, 0xce, 0x1b, - 0xc9, 0xe9, 0xaa, 0xe5, 0xb8, 0xf1, 0x91, 0xae, 0x84, 0x04, 0xe3, 0xcb, 0x30, 0xa3, 0xb7, 0xd6, 0xa9, 0x61, 0xc6, - 0x05, 0x98, 0x4c, 0x21, 0xac, 0x03, 0xe3, 0xf2, 0x69, 0xd8, 0xd0, 0x48, 0xc7, 0xd0, 0xf0, 0x61, 0x27, 0x39, 0x3d, - 0x45, 0xb8, 0x85, 0x3b, 0xa7, 0xa7, 0x81, 0x34, 0x30, 0xd6, 0xbb, 0x8a, 0xee, 0x2a, 0xa9, 0x76, 0x94, 0x3c, 0x32, - 0x8d, 0x1e, 0xb5, 0x5b, 0x2d, 0x6c, 0x1c, 0xb7, 0xcb, 0xc2, 0x5c, 0xed, 0x68, 0xb6, 0xdd, 0x6a, 0x41, 0xb3, 0xf0, - 0xc7, 0xcd, 0xeb, 0x17, 0xb2, 0x6c, 0xa5, 0x2d, 0xdc, 0x4e, 0xdb, 0xb8, 0x93, 0x76, 0xf0, 0x71, 0x7a, 0x8c, 0x4f, - 0xd2, 0x13, 0x7c, 0x9a, 0x9e, 0xe2, 0xb3, 0xf4, 0x0c, 0xdf, 0x4f, 0xef, 0xe3, 0xf3, 0xf4, 0x1c, 0x3f, 0x48, 0x1f, - 0xe0, 0x87, 0x69, 0xbb, 0x85, 0x1f, 0xa5, 0xed, 0x36, 0x7e, 0x9c, 0xb6, 0x3b, 0xf8, 0x49, 0xda, 0x3e, 0xc6, 0x4f, - 0xd3, 0xf6, 0x09, 0x7e, 0x96, 0xb6, 0x4f, 0x31, 0x85, 0xdc, 0x21, 0xe4, 0x66, 0x90, 0x3b, 0x82, 0x5c, 0x06, 0xb9, - 0xe3, 0xb4, 0x7d, 0xba, 0xc6, 0xca, 0x06, 0x7b, 0x88, 0x5a, 0xed, 0xce, 0xf1, 0xc9, 0xe9, 0xd9, 0xfd, 0xf3, 0x07, - 0x0f, 0x1f, 0x3d, 0x7e, 0xf2, 0xf4, 0x59, 0x34, 0xc0, 0x43, 0xe3, 0x73, 0xa1, 0x44, 0x9f, 0x1f, 0xb4, 0x4f, 0x07, - 0xf8, 0xda, 0x7f, 0xc6, 0xfc, 0xa0, 0x73, 0xd2, 0x42, 0x97, 0x97, 0x27, 0x83, 0x46, 0x99, 0xfb, 0xde, 0xb8, 0x7a, - 0x54, 0x59, 0x84, 0x90, 0x18, 0x72, 0x10, 0xbe, 0x33, 0xf5, 0xde, 0xb3, 0x98, 0x27, 0x05, 0x3a, 0x38, 0x30, 0x3f, - 0x26, 0xfe, 0xc7, 0xd0, 0xff, 0xa0, 0xc1, 0x22, 0xdd, 0xd2, 0xd8, 0xf9, 0xfa, 0xea, 0xd2, 0xd2, 0xbe, 0x34, 0x62, - 0xd9, 0xe3, 0xce, 0x9c, 0xfc, 0xbf, 0x22, 0x6b, 0x2e, 0x42, 0x4e, 0xac, 0x4a, 0xe6, 0xb4, 0xc7, 0xc8, 0xb2, 0x48, - 0x3b, 0xa7, 0xa7, 0x07, 0xbf, 0xf4, 0x79, 0xbf, 0x3d, 0x18, 0x1c, 0xb6, 0xef, 0xe3, 0x49, 0x99, 0xd0, 0xb1, 0x09, - 0xc3, 0x32, 0xe1, 0xd8, 0x26, 0xd0, 0xd4, 0xd6, 0x86, 0xa4, 0x13, 0x93, 0x04, 0x25, 0xd6, 0xa9, 0x69, 0xfb, 0xbe, - 0x6d, 0xfb, 0x01, 0xd8, 0x31, 0x99, 0xe6, 0x5d, 0xd3, 0x17, 0x17, 0x27, 0x2b, 0xd7, 0x28, 0x9e, 0xa4, 0xae, 0x35, - 0x9f, 0x78, 0x32, 0x18, 0xe0, 0xa1, 0x49, 0x3c, 0xad, 0x12, 0xcf, 0x06, 0x03, 0xd7, 0xd5, 0x03, 0xd3, 0xd5, 0xfd, - 0x2a, 0xeb, 0x7c, 0x30, 0x30, 0x5d, 0x22, 0xe7, 0xb5, 0xae, 0xf4, 0xde, 0x97, 0x52, 0x73, 0xc0, 0x2f, 0x3a, 0xa7, - 0xa7, 0x3d, 0xc0, 0x30, 0x63, 0x8d, 0xea, 0x61, 0x74, 0x13, 0xc0, 0xe8, 0x0e, 0x7e, 0xf7, 0x86, 0x34, 0xbd, 0xa6, - 0x25, 0x90, 0x7a, 0xd1, 0x7f, 0x45, 0x0d, 0x6d, 0x60, 0x6e, 0xfe, 0x4c, 0xec, 0x9f, 0x21, 0x6a, 0x7c, 0xa1, 0x00, - 0x6e, 0xd0, 0x85, 0x78, 0x65, 0xa6, 0xe9, 0xf1, 0x33, 0x05, 0xe7, 0x92, 0xa9, 0xca, 0x69, 0x6f, 0x35, 0xbd, 0x19, - 0xae, 0xa6, 0xea, 0x0b, 0xfa, 0x33, 0xfe, 0x53, 0x1d, 0xc6, 0xfd, 0x66, 0x23, 0x61, 0x7f, 0x8e, 0xc0, 0x8b, 0xa5, - 0x97, 0x8e, 0xd8, 0x04, 0xf5, 0xfa, 0x7f, 0x2a, 0x3c, 0x68, 0x04, 0x19, 0x3f, 0x6c, 0xa7, 0x80, 0x8f, 0xcb, 0x66, - 0x62, 0xfc, 0x03, 0xea, 0xa1, 0xde, 0x9f, 0xea, 0xf0, 0x4f, 0x74, 0xef, 0xa8, 0x9a, 0xcb, 0xef, 0xd2, 0x6d, 0xe1, - 0x2a, 0xf0, 0xcd, 0x61, 0xb9, 0x85, 0x19, 0x6e, 0x37, 0x19, 0x84, 0x09, 0x03, 0x27, 0x68, 0x12, 0xcb, 0x06, 0x3f, - 0x3a, 0x6e, 0xa1, 0x1f, 0xda, 0x1d, 0x10, 0xeb, 0x9b, 0xe2, 0x70, 0x7b, 0xd3, 0x17, 0xcd, 0x63, 0xfc, 0xa0, 0x59, - 0xe0, 0x36, 0xc2, 0xcd, 0xb6, 0xd7, 0xb7, 0xf6, 0x55, 0xdc, 0x42, 0x58, 0xc5, 0xe7, 0xf0, 0xcf, 0x09, 0x1a, 0x54, - 0x1b, 0xf2, 0x8a, 0x6e, 0xf6, 0x0e, 0x1e, 0x9b, 0x24, 0x56, 0x0d, 0x7e, 0x74, 0xd6, 0x42, 0x3f, 0x9c, 0x99, 0x8e, - 0xd8, 0xa1, 0xde, 0xd1, 0x95, 0xc4, 0x27, 0x4d, 0x09, 0x1d, 0xb5, 0xca, 0x7e, 0x44, 0x7c, 0x8a, 0xb0, 0x88, 0x8f, - 0xe1, 0x9f, 0x76, 0xd8, 0xcf, 0xaf, 0x5b, 0xfd, 0x98, 0x79, 0xb7, 0x71, 0x72, 0x6a, 0x1d, 0x40, 0x95, 0xbd, 0x8d, - 0x6d, 0xb0, 0xcb, 0xb6, 0xb9, 0x46, 0x6a, 0x1f, 0xc1, 0x07, 0xc2, 0xfa, 0x90, 0x28, 0xcc, 0x0e, 0xc1, 0x73, 0x14, - 0x0c, 0x26, 0xd4, 0xc5, 0x71, 0x57, 0x35, 0x1a, 0x48, 0xf4, 0xd5, 0xe0, 0x90, 0xb4, 0x9b, 0xba, 0xc9, 0x30, 0xfc, - 0x6e, 0x90, 0x32, 0x1c, 0x99, 0xa8, 0x7a, 0x7d, 0xec, 0x7a, 0xb5, 0x77, 0xce, 0x1e, 0x3b, 0x08, 0x21, 0xaa, 0x17, - 0xeb, 0x26, 0x43, 0x47, 0xa2, 0x11, 0xeb, 0x0b, 0xd6, 0x3b, 0x4b, 0x5b, 0xc8, 0x60, 0xa7, 0xea, 0xc5, 0xac, 0xc9, - 0x21, 0xbd, 0x93, 0xc6, 0xbc, 0xa9, 0xe1, 0xd7, 0x49, 0x30, 0x0b, 0x01, 0x78, 0x57, 0xf9, 0xc1, 0x14, 0x47, 0x9d, - 0xd3, 0x53, 0x2c, 0x08, 0x4f, 0x26, 0xe6, 0x97, 0x22, 0x3c, 0x19, 0x9a, 0x5f, 0x92, 0x94, 0xf0, 0xb2, 0xbd, 0xe3, - 0x82, 0x04, 0xab, 0x6a, 0x52, 0x28, 0x2c, 0x68, 0x81, 0x8e, 0x3a, 0xfe, 0x42, 0x1a, 0x4f, 0xfd, 0x1c, 0x40, 0x00, - 0x2f, 0x8c, 0x2d, 0xa2, 0x6c, 0x16, 0x38, 0x27, 0xf4, 0x32, 0x39, 0xed, 0x4d, 0x8f, 0xe2, 0x4e, 0x53, 0x36, 0x0b, - 0x94, 0x4e, 0x8f, 0x4c, 0x4d, 0x9c, 0x91, 0xc7, 0xd4, 0xb6, 0x86, 0xa7, 0x70, 0x8b, 0x98, 0x91, 0xec, 0xf0, 0xac, - 0xd5, 0x48, 0x4e, 0x11, 0xee, 0x67, 0xab, 0x16, 0xce, 0x57, 0xab, 0x16, 0xa6, 0xc1, 0x32, 0x3c, 0x16, 0x1e, 0x20, - 0xa5, 0x8e, 0x68, 0x33, 0x2a, 0x4c, 0x8f, 0xc7, 0x1a, 0x6e, 0xc4, 0x35, 0xf8, 0x99, 0x68, 0xf0, 0x80, 0x49, 0xb9, - 0xbb, 0x8a, 0x42, 0x26, 0x2e, 0xde, 0x38, 0xd4, 0x1a, 0xbd, 0x16, 0x7e, 0x5d, 0xbd, 0x4d, 0xa3, 0x88, 0x7f, 0x97, - 0xd8, 0xa6, 0x05, 0xc5, 0xe8, 0x76, 0xb1, 0x5f, 0xe9, 0x56, 0xb1, 0x37, 0x3b, 0x8a, 0x5d, 0x6d, 0x17, 0xfb, 0x28, - 0x03, 0x1d, 0x17, 0xff, 0xe1, 0xf8, 0xac, 0xd5, 0x38, 0x06, 0x64, 0x3d, 0x3e, 0x6b, 0x55, 0x85, 0xee, 0xd1, 0x6a, - 0xad, 0x34, 0xf9, 0x4c, 0xad, 0x95, 0x3f, 0xf7, 0xee, 0xc6, 0x66, 0xe1, 0xac, 0xb3, 0x73, 0xe9, 0xd9, 0xdc, 0x3f, - 0x05, 0x2b, 0x0a, 0x61, 0xa8, 0x9d, 0xee, 0x9f, 0x0d, 0x7a, 0x53, 0x16, 0x37, 0x20, 0x15, 0xa5, 0x63, 0xed, 0x7e, - 0xa1, 0xf2, 0x32, 0xf5, 0xa3, 0x84, 0xa4, 0xce, 0x00, 0x61, 0x49, 0x1a, 0xba, 0x7f, 0x3c, 0x30, 0xe7, 0x5d, 0x01, - 0xbf, 0x4f, 0xcc, 0xef, 0x52, 0x95, 0xe1, 0x5c, 0x01, 0xa6, 0x37, 0xc3, 0xa8, 0x27, 0xc8, 0x6b, 0x1a, 0x1b, 0xeb, - 0x6e, 0x94, 0x96, 0x19, 0xea, 0x0b, 0x64, 0xbc, 0x29, 0x33, 0x04, 0x79, 0x2d, 0xdc, 0x6f, 0xbc, 0x2c, 0x52, 0xb0, - 0xf4, 0xc0, 0x93, 0x14, 0xac, 0x3c, 0xf0, 0x30, 0x15, 0xe0, 0x89, 0x40, 0x53, 0x16, 0xd8, 0x8f, 0x3f, 0x74, 0xba, - 0x23, 0x73, 0xdf, 0x49, 0x0c, 0x96, 0x76, 0x19, 0x9c, 0x14, 0x1f, 0x65, 0x0c, 0x7f, 0x1b, 0x1a, 0x61, 0x06, 0x6d, - 0x32, 0x84, 0x79, 0x52, 0x10, 0x48, 0xc3, 0x3c, 0x99, 0x10, 0x06, 0x4d, 0xf2, 0x64, 0x48, 0x58, 0xbf, 0x13, 0xa0, - 0xc9, 0x53, 0x03, 0x3b, 0x00, 0x0e, 0xaf, 0x5f, 0x21, 0x6b, 0xdb, 0x38, 0xdc, 0x4d, 0x43, 0x13, 0x82, 0x70, 0x15, - 0xc3, 0x2c, 0x60, 0x73, 0x9a, 0x9f, 0x9d, 0x2a, 0xf0, 0x22, 0x4f, 0xa8, 0xa1, 0xde, 0x7f, 0x01, 0x59, 0x8d, 0xef, - 0x2d, 0xd9, 0x1a, 0xef, 0xdd, 0x5b, 0x8a, 0xf5, 0x0f, 0xf0, 0x47, 0xb9, 0x3f, 0xda, 0x9c, 0x7e, 0x6b, 0xf4, 0x57, - 0x0a, 0xc5, 0x76, 0x94, 0x42, 0x7f, 0x79, 0x47, 0x34, 0x45, 0x96, 0xb7, 0x69, 0x34, 0xa2, 0xc5, 0xe7, 0x08, 0x7f, - 0x4a, 0xa3, 0x1c, 0x18, 0xc1, 0x08, 0x7f, 0x4c, 0xa3, 0x82, 0x45, 0xf8, 0x8f, 0x34, 0x1a, 0xe6, 0x8b, 0x08, 0x7f, - 0x48, 0xa3, 0x49, 0x11, 0xe1, 0xf7, 0xa0, 0x26, 0x1c, 0xf1, 0xc5, 0x2c, 0xc2, 0xbf, 0xa7, 0x91, 0x32, 0x76, 0xf8, - 0xf8, 0x61, 0x1a, 0x31, 0x16, 0xe1, 0x77, 0x69, 0x24, 0xf3, 0x08, 0x5f, 0xa5, 0x91, 0x2c, 0x22, 0xfc, 0x28, 0x8d, - 0x0a, 0x1a, 0xe1, 0xc7, 0x69, 0x04, 0x85, 0x26, 0x11, 0x7e, 0x92, 0x46, 0xd0, 0xb2, 0x8a, 0xf0, 0xdb, 0x34, 0xe2, - 0x22, 0xc2, 0xbf, 0xa5, 0x91, 0x5e, 0x14, 0xff, 0x2c, 0x24, 0x57, 0x11, 0x7e, 0x9a, 0x46, 0x53, 0x1e, 0xe1, 0x37, - 0x69, 0x54, 0xc8, 0x08, 0xbf, 0x4e, 0x23, 0x9a, 0x47, 0xf8, 0x55, 0x1a, 0xe5, 0x2c, 0xc2, 0xbf, 0xa6, 0xd1, 0x88, - 0x45, 0xf8, 0x65, 0x1a, 0xdd, 0xb1, 0x3c, 0x97, 0x11, 0x7e, 0x96, 0x46, 0x4c, 0x44, 0xf8, 0x97, 0x34, 0xca, 0xa6, - 0x11, 0xfe, 0x29, 0x8d, 0x68, 0xf1, 0x59, 0x45, 0xf8, 0x79, 0x1a, 0x31, 0x1a, 0xe1, 0x17, 0xb6, 0xa3, 0x49, 0x84, - 0x7f, 0x4e, 0xa3, 0x9b, 0x69, 0xb4, 0xc6, 0x4a, 0x91, 0xe5, 0x6b, 0x9e, 0xb1, 0x3f, 0x58, 0x1a, 0x8d, 0x5b, 0xe3, - 0xf3, 0xf1, 0x38, 0xc2, 0x54, 0x68, 0xfe, 0xcf, 0x82, 0xdd, 0x3c, 0xd5, 0x90, 0x48, 0xd9, 0x70, 0x74, 0x3f, 0xc2, - 0xf4, 0x9f, 0x05, 0x4d, 0xa3, 0xf1, 0xd8, 0x14, 0xf8, 0x67, 0x41, 0x67, 0xb4, 0x78, 0xcb, 0xd2, 0xe8, 0xfe, 0x78, - 0x3c, 0x1e, 0x9d, 0x44, 0x98, 0x7e, 0x5d, 0x7c, 0x34, 0x2d, 0x98, 0x02, 0x43, 0xc6, 0x27, 0x50, 0xf7, 0x74, 0x7c, - 0x3a, 0xca, 0x22, 0x3c, 0xe4, 0xea, 0x9f, 0x05, 0x7c, 0x8f, 0xd9, 0x49, 0x76, 0x12, 0xe1, 0x61, 0x4e, 0xb3, 0xcf, - 0x69, 0xd4, 0x32, 0xbf, 0xc4, 0x2f, 0x6c, 0xf4, 0x7a, 0x26, 0x8d, 0x12, 0x7d, 0xcc, 0x86, 0xd9, 0x28, 0xc2, 0x66, - 0x30, 0x63, 0xf8, 0xfb, 0x85, 0xbf, 0x63, 0x3a, 0x8d, 0xce, 0x69, 0x67, 0xc8, 0x3a, 0x11, 0x1e, 0xbe, 0xb9, 0x11, - 0x69, 0x44, 0x4f, 0x3b, 0xb4, 0x43, 0x23, 0x3c, 0x5c, 0x14, 0xf9, 0xdd, 0x8d, 0x94, 0x23, 0x00, 0xc2, 0xf0, 0xfc, - 0xfc, 0x7e, 0x84, 0x33, 0xfa, 0xab, 0x86, 0xda, 0xa7, 0xe3, 0x07, 0x8c, 0xb6, 0x22, 0xfc, 0x0b, 0x2d, 0xf4, 0xc7, - 0x85, 0x72, 0x03, 0x6d, 0x41, 0x8a, 0xcc, 0xde, 0x81, 0x82, 0x39, 0x1a, 0x75, 0xce, 0x1e, 0xb4, 0x59, 0x84, 0xb3, - 0xab, 0xd7, 0xd0, 0xdb, 0xfd, 0xf1, 0x69, 0x0b, 0x3e, 0x04, 0x48, 0x6a, 0xac, 0x80, 0x46, 0xce, 0x4e, 0x1e, 0x9c, - 0xb2, 0x91, 0x49, 0x54, 0x3c, 0xff, 0x6c, 0x66, 0x7f, 0x0e, 0xf3, 0xc9, 0x0a, 0x3e, 0x53, 0x52, 0xa4, 0xd1, 0x28, - 0x6b, 0x9f, 0x1c, 0x43, 0xc2, 0x1d, 0x15, 0x1e, 0x38, 0xb7, 0x50, 0xf5, 0x7c, 0x18, 0xe1, 0x5b, 0x9b, 0x7a, 0x3e, - 0x34, 0x1f, 0x93, 0x77, 0xbf, 0x8a, 0x37, 0xa3, 0x34, 0x1a, 0x9e, 0x9f, 0x9f, 0xb5, 0x20, 0xe1, 0x03, 0xbd, 0x4b, - 0x23, 0xfa, 0x00, 0xfe, 0x83, 0xec, 0x8f, 0xcf, 0xa0, 0x43, 0x18, 0xe1, 0xed, 0xe4, 0x63, 0x98, 0xf3, 0x79, 0x4a, - 0x3f, 0xf3, 0x34, 0x1a, 0x8e, 0x86, 0xf7, 0xcf, 0xa0, 0xde, 0x8c, 0x4e, 0x9e, 0x69, 0x0a, 0xed, 0xb6, 0x5a, 0xa6, - 0xe5, 0x77, 0xfc, 0x0b, 0x33, 0xd5, 0x4f, 0x4f, 0xcf, 0x86, 0x1d, 0x18, 0xc1, 0x15, 0xa8, 0x18, 0x60, 0x3c, 0xe7, - 0x99, 0x69, 0xf0, 0x2a, 0x7b, 0x3a, 0x4a, 0xa3, 0x07, 0x0f, 0x8e, 0x3b, 0x59, 0x16, 0xe1, 0xdb, 0x8f, 0x23, 0x5b, - 0xdb, 0xe4, 0x29, 0x80, 0x7d, 0x1a, 0xb1, 0x07, 0x0f, 0xce, 0xee, 0x53, 0xf8, 0x7e, 0x6e, 0xda, 0x3a, 0x1f, 0x0f, - 0xb3, 0x73, 0x68, 0xeb, 0x77, 0x98, 0xce, 0xc9, 0xf9, 0xf1, 0xc8, 0xf4, 0xf5, 0xbb, 0x19, 0x75, 0x67, 0x7c, 0x32, - 0x3e, 0x31, 0x99, 0x66, 0xa8, 0xe5, 0xe7, 0x6f, 0x2c, 0x8d, 0x32, 0x36, 0x6a, 0x47, 0xf8, 0xd6, 0x2d, 0xdc, 0x83, - 0x93, 0x56, 0x6b, 0x74, 0x1c, 0xe1, 0xd1, 0xc3, 0xf9, 0xfc, 0xad, 0x81, 0x60, 0xfb, 0xe4, 0x81, 0xfd, 0x56, 0x9f, - 0xef, 0xa0, 0xe9, 0xa1, 0x01, 0xda, 0x88, 0xcf, 0x4c, 0xcb, 0x67, 0x0f, 0xe0, 0x3f, 0xf3, 0x6d, 0x9a, 0x2e, 0xbf, - 0xe5, 0x68, 0x62, 0x17, 0xa5, 0xcd, 0x1e, 0xb4, 0xa0, 0xc6, 0x98, 0x7f, 0x1c, 0x16, 0x1c, 0xd0, 0x68, 0xd8, 0x81, - 0xff, 0x8b, 0xf0, 0x38, 0xbf, 0x7a, 0xed, 0x70, 0x76, 0x3c, 0xa6, 0xe3, 0x56, 0x84, 0xc7, 0xf2, 0xa3, 0xd2, 0x1f, - 0x1e, 0x8a, 0x34, 0xea, 0x74, 0xce, 0x87, 0xa6, 0xcc, 0xe2, 0x17, 0xc5, 0x0d, 0x1e, 0xb7, 0x4c, 0x2b, 0x13, 0xfa, - 0x56, 0x0d, 0xaf, 0x24, 0xac, 0x24, 0xfc, 0x17, 0xe1, 0x09, 0xe8, 0xa5, 0x5c, 0x2b, 0xe7, 0x76, 0x3b, 0x4c, 0xde, - 0x19, 0xd4, 0x1c, 0xdd, 0x07, 0x78, 0xf9, 0x65, 0x1c, 0x51, 0x7a, 0xda, 0x69, 0x45, 0xd8, 0x8c, 0xfa, 0xbc, 0x05, - 0xff, 0x45, 0xd8, 0x42, 0xce, 0xc0, 0x75, 0xf2, 0xf1, 0xd9, 0xcb, 0x9b, 0x34, 0xa2, 0xa3, 0xf1, 0x18, 0x96, 0xc4, - 0x4c, 0xc6, 0x17, 0x9b, 0x4a, 0xc1, 0xee, 0x7e, 0xbd, 0x71, 0xdb, 0xc5, 0x24, 0x68, 0x07, 0x9d, 0xb3, 0x07, 0xc3, - 0x93, 0x08, 0xbf, 0x1d, 0x71, 0x2a, 0x60, 0x95, 0xb2, 0xd1, 0x69, 0x76, 0x9a, 0x99, 0x84, 0x89, 0x4c, 0xa3, 0x13, - 0x58, 0xf2, 0x4e, 0x84, 0xf9, 0x97, 0xab, 0x3b, 0x8b, 0x6e, 0x50, 0xdb, 0x21, 0xc8, 0xb8, 0xc5, 0xce, 0xce, 0xb3, - 0x08, 0xe7, 0xf4, 0xcb, 0xb3, 0x5f, 0x8b, 0x34, 0x62, 0x67, 0xec, 0x6c, 0x4c, 0xfd, 0xf7, 0x1f, 0x6a, 0x6a, 0x6a, - 0xb4, 0xc6, 0xa7, 0x90, 0x74, 0x23, 0xcc, 0x58, 0xef, 0x67, 0x63, 0x83, 0x21, 0xaf, 0x66, 0x52, 0x64, 0x4f, 0xc7, - 0x63, 0x69, 0xb1, 0x98, 0xc2, 0x26, 0xfc, 0x04, 0xd0, 0xa6, 0xa3, 0xd1, 0x39, 0x3b, 0x8b, 0xf0, 0x27, 0xbb, 0x4b, - 0xdc, 0x04, 0x3e, 0x59, 0xcc, 0x66, 0x6e, 0xb7, 0x7f, 0xb2, 0x40, 0x81, 0xf9, 0x8e, 0xe9, 0x98, 0x8e, 0x3a, 0x11, - 0xfe, 0x64, 0xe0, 0x32, 0x3a, 0x86, 0xff, 0xa0, 0x00, 0x74, 0xf6, 0xa0, 0xc5, 0xd8, 0x83, 0x96, 0xf9, 0x0a, 0xf3, - 0xdc, 0xcc, 0x87, 0x67, 0x59, 0x3b, 0xc2, 0x9f, 0x1c, 0x3a, 0x8e, 0xc7, 0xb4, 0x05, 0xe8, 0xf8, 0xc9, 0xa1, 0x63, - 0xa7, 0x35, 0xec, 0x50, 0xf3, 0x6d, 0xb1, 0xe6, 0xfc, 0x7e, 0xc6, 0x60, 0x72, 0x9f, 0x2c, 0x42, 0xde, 0xbf, 0x7f, - 0x7e, 0xfe, 0xe0, 0x01, 0x7c, 0x9a, 0xb6, 0xcb, 0x4f, 0xa5, 0x1f, 0xe6, 0x06, 0xc9, 0x5a, 0xd9, 0x09, 0xd0, 0xc9, - 0x4f, 0x66, 0x8c, 0xe3, 0xf1, 0x98, 0xb5, 0x22, 0x9c, 0xf3, 0x19, 0xb3, 0x98, 0x60, 0x7f, 0x9b, 0x8e, 0x8e, 0x3b, - 0xd9, 0xe8, 0xb8, 0x13, 0xe1, 0xfc, 0xed, 0x33, 0x33, 0x9b, 0x16, 0xcc, 0xde, 0x6f, 0x39, 0x8f, 0x35, 0x33, 0xfa, - 0x06, 0x06, 0x09, 0x2b, 0x0d, 0x95, 0xdf, 0x07, 0xf4, 0xf0, 0xec, 0x2c, 0x1b, 0xc1, 0x40, 0xdf, 0x43, 0xb7, 0x00, - 0xc6, 0xf7, 0x76, 0xf3, 0x0d, 0xe9, 0xe9, 0x29, 0x4c, 0xf7, 0xfd, 0x7c, 0x51, 0xcc, 0x5f, 0xa5, 0xd1, 0x83, 0xe3, - 0xfb, 0xad, 0xd1, 0x30, 0xc2, 0xef, 0xdd, 0x04, 0x8f, 0xb3, 0xe1, 0xf1, 0xfd, 0x76, 0x84, 0xdf, 0x9b, 0xfd, 0x76, - 0x7f, 0x78, 0x76, 0x0e, 0xe7, 0xc6, 0x7b, 0x35, 0x2f, 0xde, 0x4e, 0x4c, 0x81, 0x31, 0x7d, 0x00, 0xcd, 0xfe, 0x66, - 0x76, 0xe3, 0xa8, 0x0d, 0x1b, 0xf9, 0xbd, 0xd9, 0x64, 0x06, 0x4f, 0xee, 0xb7, 0x4f, 0xcf, 0x4f, 0x23, 0x3c, 0xe3, - 0x23, 0x01, 0x04, 0xde, 0x6c, 0x94, 0x07, 0xed, 0x07, 0xf7, 0x5b, 0x11, 0x9e, 0xbd, 0xd5, 0xd9, 0x47, 0x3a, 0x33, - 0xd4, 0x78, 0x0c, 0x30, 0x9b, 0x71, 0xa5, 0xef, 0xde, 0x28, 0x47, 0x8f, 0x59, 0x3b, 0xc2, 0x33, 0x99, 0x65, 0x54, - 0xbd, 0xb5, 0x09, 0xc3, 0xd3, 0x08, 0x0b, 0xfa, 0x85, 0xfe, 0x2d, 0xfd, 0x66, 0x1a, 0x31, 0x3a, 0x32, 0x69, 0x06, - 0x87, 0x23, 0xfc, 0x6e, 0x04, 0xd7, 0x60, 0x69, 0x34, 0x1e, 0x8d, 0x4f, 0x01, 0x3c, 0x40, 0x80, 0x2c, 0x76, 0x03, - 0x34, 0xe0, 0x6b, 0xf4, 0x68, 0x98, 0x46, 0x67, 0xc3, 0x73, 0xd6, 0x39, 0x8e, 0x70, 0x49, 0x8d, 0xe8, 0x29, 0xe4, - 0x9b, 0xcf, 0x8f, 0x66, 0x4b, 0x9d, 0xd8, 0x04, 0x03, 0xa0, 0x11, 0xbd, 0xdf, 0x1a, 0x9d, 0x45, 0x78, 0xfe, 0x9a, - 0xf9, 0x3d, 0xc6, 0x18, 0x3b, 0x07, 0x58, 0x42, 0x92, 0x41, 0xa0, 0xf3, 0xf1, 0xf0, 0xc1, 0xb9, 0xf9, 0x06, 0x30, - 0xd0, 0x31, 0x63, 0x00, 0xa4, 0xf9, 0x6b, 0x56, 0x02, 0x62, 0x34, 0xbc, 0xdf, 0x02, 0xfa, 0x32, 0xa7, 0x73, 0x7a, - 0x47, 0x6f, 0x9e, 0xce, 0xcd, 0x9c, 0xc6, 0xa3, 0xd3, 0x08, 0xcf, 0x9f, 0xff, 0x32, 0x5f, 0x8c, 0xc7, 0x66, 0x42, - 0x74, 0xf8, 0x20, 0xc2, 0x73, 0x56, 0x2c, 0x60, 0x8d, 0xce, 0x4f, 0x8f, 0xc7, 0x11, 0x76, 0x68, 0x98, 0xb5, 0xb2, - 0x21, 0xdc, 0xf3, 0x2d, 0x66, 0x69, 0x34, 0x1a, 0xd1, 0xd6, 0x08, 0x6e, 0xfd, 0xe4, 0xcd, 0xaf, 0x85, 0x45, 0x23, - 0x66, 0xf0, 0xc1, 0xad, 0x21, 0xcc, 0x17, 0xe0, 0xf1, 0x71, 0xc8, 0xb2, 0x8c, 0xba, 0xc4, 0xb3, 0xb3, 0xe3, 0x63, - 0xc0, 0x3d, 0x3b, 0x43, 0x8b, 0x20, 0x6f, 0xd4, 0xdd, 0xb0, 0x90, 0x70, 0x74, 0x01, 0x51, 0x05, 0xb2, 0xfa, 0xe6, - 0xee, 0xb5, 0xa1, 0xab, 0xed, 0xb3, 0x07, 0xb0, 0x00, 0x8a, 0x8e, 0x46, 0xaf, 0xec, 0xe1, 0x76, 0x3e, 0x3c, 0x39, - 0x6d, 0x1f, 0x47, 0xd8, 0x6f, 0x04, 0x7a, 0xde, 0xba, 0xdf, 0x81, 0x12, 0x62, 0x74, 0x67, 0x4b, 0x8c, 0x4f, 0xe8, - 0xc9, 0x59, 0x2b, 0xc2, 0x7e, 0x6b, 0xb0, 0xf3, 0xe1, 0xe9, 0x7d, 0xf8, 0x54, 0x53, 0x96, 0xe7, 0x06, 0xbf, 0x4f, - 0x01, 0x2e, 0x8a, 0x3f, 0x13, 0x34, 0x8d, 0x68, 0xeb, 0xb4, 0xd3, 0x19, 0xc1, 0x67, 0xfe, 0x85, 0x15, 0x69, 0x94, - 0xb5, 0xe0, 0xbf, 0x08, 0x07, 0x3b, 0x89, 0x0d, 0x23, 0x6c, 0xf0, 0xee, 0x8c, 0x9e, 0x9a, 0xbd, 0xef, 0x76, 0x55, - 0xeb, 0xbc, 0x05, 0x1b, 0xd6, 0x6d, 0x2a, 0xf7, 0xa5, 0x84, 0xbc, 0x71, 0x24, 0x96, 0x46, 0x38, 0x40, 0xd0, 0xf1, - 0xfd, 0x71, 0x84, 0xfd, 0x8e, 0x3b, 0x39, 0x3b, 0xef, 0x00, 0x29, 0xd3, 0x40, 0x28, 0x46, 0x9d, 0xe1, 0x09, 0x90, - 0x26, 0xcd, 0x5e, 0x5b, 0x3c, 0x89, 0xb0, 0x7e, 0xaa, 0xf4, 0xab, 0x34, 0x1a, 0x9d, 0x0f, 0xc7, 0xa3, 0xf3, 0x08, - 0x6b, 0x39, 0xa3, 0x5a, 0x1a, 0x0a, 0x78, 0x7c, 0x72, 0x3f, 0xc2, 0x06, 0xcd, 0x5b, 0xac, 0x35, 0x6a, 0x45, 0xd8, - 0x1d, 0x25, 0x8c, 0x9d, 0x77, 0x60, 0x5a, 0x3f, 0x3f, 0xd7, 0x80, 0xcb, 0x23, 0x36, 0x3c, 0x8e, 0x70, 0x49, 0xef, - 0x0d, 0x21, 0x82, 0x2f, 0x35, 0x93, 0x9f, 0x1d, 0xeb, 0x01, 0xa4, 0xce, 0x6f, 0x78, 0x58, 0x86, 0x97, 0x37, 0x16, - 0x8d, 0xa8, 0xd9, 0xe2, 0xc1, 0x3d, 0xe8, 0x13, 0x1a, 0x7b, 0xb6, 0x9d, 0x93, 0xe5, 0x1a, 0x97, 0xe1, 0x45, 0x3f, - 0xb3, 0x3b, 0x15, 0x2b, 0x65, 0x38, 0xd9, 0x20, 0x05, 0x5c, 0x00, 0x9c, 0x41, 0xbd, 0xf3, 0x99, 0x04, 0x41, 0x52, - 0x90, 0x56, 0x57, 0x5c, 0x78, 0x3f, 0xce, 0xae, 0x80, 0xa0, 0x03, 0x90, 0x5e, 0x10, 0x4a, 0x34, 0xc4, 0x66, 0xb1, - 0xc2, 0xa4, 0x37, 0x6f, 0x37, 0x32, 0xa5, 0xb4, 0x06, 0xf3, 0x94, 0x50, 0x1f, 0x95, 0x1d, 0x2e, 0x69, 0x21, 0x6e, - 0x11, 0xea, 0x4a, 0x62, 0x62, 0x2c, 0xbf, 0x10, 0x3a, 0x56, 0xaa, 0x5f, 0x0c, 0x70, 0xfb, 0x0c, 0x61, 0x88, 0x5e, - 0x40, 0xfa, 0xf2, 0xf2, 0xb2, 0x7d, 0x76, 0x60, 0x84, 0xbe, 0xcb, 0xcb, 0x73, 0xfb, 0x03, 0xfe, 0x1d, 0x54, 0x11, - 0xa3, 0x61, 0x7c, 0x8f, 0x58, 0xa0, 0xd1, 0x33, 0xfc, 0xf5, 0x23, 0xb6, 0x5a, 0xc5, 0x8f, 0x18, 0x81, 0x19, 0xe3, - 0x47, 0x2c, 0x31, 0xb7, 0x06, 0xd6, 0x37, 0x85, 0xf4, 0x41, 0x73, 0xd6, 0xc2, 0x10, 0xc7, 0xdc, 0x73, 0xde, 0x8f, - 0x58, 0x9f, 0xd7, 0xfd, 0x9a, 0xab, 0xe0, 0xc1, 0x07, 0x07, 0xcb, 0x22, 0xd5, 0x56, 0x4c, 0xd0, 0x56, 0x4c, 0xd0, - 0x56, 0x4c, 0xd0, 0x55, 0xf8, 0xf6, 0x93, 0x1e, 0x48, 0x29, 0x46, 0xd9, 0xe2, 0x78, 0xea, 0x77, 0xa0, 0xf6, 0x00, - 0xed, 0x64, 0xaf, 0x52, 0x76, 0x94, 0xba, 0x8a, 0x9d, 0x0a, 0x8c, 0x9d, 0x89, 0x4e, 0xdb, 0x71, 0xf4, 0xef, 0xa8, - 0x3b, 0x5e, 0xd6, 0xc4, 0xb2, 0x77, 0x3b, 0xc5, 0x32, 0x58, 0x49, 0x23, 0x9a, 0xed, 0xdb, 0x48, 0x18, 0xba, 0x7f, - 0xdf, 0x08, 0x66, 0x55, 0x78, 0xb6, 0x06, 0x24, 0x75, 0x41, 0x0a, 0x39, 0x37, 0x52, 0x5a, 0x81, 0xd2, 0x91, 0x8e, - 0x0b, 0xd0, 0x50, 0x7a, 0x05, 0x65, 0x19, 0x45, 0xb4, 0x61, 0x00, 0xa2, 0xac, 0x8c, 0x66, 0x65, 0xb5, 0x53, 0x10, - 0x5d, 0x40, 0x13, 0x66, 0x24, 0x16, 0x68, 0x40, 0x98, 0x06, 0x84, 0xab, 0x0c, 0xe2, 0x8c, 0xcb, 0x3e, 0x31, 0xd9, - 0xca, 0x64, 0xab, 0x32, 0x5b, 0xfa, 0x6c, 0x2b, 0x24, 0x4a, 0x93, 0x2d, 0xcb, 0x6c, 0x90, 0xd9, 0xf0, 0x24, 0x55, - 0x78, 0x98, 0x4a, 0x2b, 0xaa, 0x55, 0xb2, 0xd5, 0x5b, 0x1a, 0x6a, 0x73, 0x0f, 0x0e, 0xe2, 0x52, 0x4e, 0x32, 0x6a, - 0xe2, 0x7b, 0x4b, 0x9e, 0x14, 0x46, 0x06, 0xe2, 0xc9, 0xc4, 0xfd, 0x1d, 0xae, 0x37, 0x65, 0xa5, 0x62, 0x32, 0xfc, - 0x46, 0x49, 0xf4, 0x97, 0x57, 0xa2, 0x3e, 0xe2, 0x26, 0xfe, 0xcc, 0x05, 0x49, 0x5a, 0xad, 0xe3, 0xf6, 0x71, 0xeb, - 0xbc, 0xc7, 0x0f, 0xdb, 0x9d, 0xe4, 0x41, 0x27, 0x35, 0x8a, 0x88, 0xb9, 0xbc, 0x01, 0x05, 0xcc, 0x51, 0x27, 0x39, - 0x41, 0x87, 0xed, 0xa4, 0x75, 0x7a, 0xda, 0x84, 0x7f, 0xf0, 0x7b, 0x5d, 0x56, 0x3b, 0x69, 0x9d, 0x9c, 0xf6, 0xf8, - 0xd1, 0x46, 0xa5, 0x98, 0x37, 0xa0, 0x20, 0x3a, 0x32, 0x95, 0x30, 0xd4, 0xaf, 0x96, 0xf7, 0xd9, 0x96, 0x9e, 0xe7, - 0xbd, 0x8e, 0x95, 0x55, 0xc5, 0x01, 0x54, 0xfd, 0xd7, 0xc4, 0x00, 0xd1, 0x7f, 0x0d, 0xcb, 0x18, 0xb1, 0xcb, 0x02, - 0x44, 0xed, 0x47, 0x3c, 0x16, 0x0d, 0x76, 0x18, 0xdb, 0x7c, 0x0d, 0x75, 0x9b, 0x10, 0xb7, 0x0d, 0x4f, 0x5c, 0xae, - 0x0a, 0x73, 0x27, 0x08, 0x35, 0x15, 0xe4, 0x0e, 0x5d, 0xae, 0x0c, 0x73, 0x87, 0x08, 0x35, 0x25, 0xe4, 0xd2, 0x94, - 0x27, 0x14, 0x72, 0x74, 0x42, 0x9b, 0x06, 0x92, 0xd5, 0xa2, 0x3c, 0x67, 0x7e, 0xd8, 0x7c, 0x0c, 0xcb, 0x63, 0x08, - 0x8a, 0x13, 0xa4, 0x05, 0xbc, 0xed, 0x51, 0x6a, 0x73, 0x5a, 0xb8, 0x54, 0xe3, 0x40, 0x46, 0x03, 0xfe, 0x39, 0x64, - 0xe6, 0xc1, 0x87, 0x56, 0xef, 0xf8, 0xac, 0x95, 0xb6, 0xc1, 0x49, 0x19, 0x64, 0x6d, 0x61, 0x65, 0x6d, 0xe1, 0x65, - 0x6d, 0xe1, 0x65, 0x6d, 0x10, 0xe0, 0x83, 0xbe, 0xff, 0x91, 0x35, 0xc3, 0x0f, 0x5e, 0x5a, 0x91, 0x58, 0x33, 0x81, - 0x58, 0xaf, 0x56, 0xcb, 0x35, 0xd8, 0xf8, 0x94, 0x35, 0xa4, 0xaa, 0xd4, 0x9f, 0xcb, 0x22, 0x6d, 0xe1, 0x49, 0x0a, - 0x5a, 0xee, 0x16, 0xa6, 0x66, 0x73, 0x7b, 0xaa, 0xb0, 0x19, 0x3f, 0xa6, 0xe7, 0xd5, 0xc9, 0x97, 0xe4, 0xd8, 0x68, - 0x8f, 0x97, 0x45, 0xca, 0x2d, 0xcd, 0xe0, 0x96, 0x66, 0x70, 0x4b, 0x33, 0xa0, 0x11, 0x5c, 0x16, 0x36, 0x65, 0x13, - 0x4a, 0xe0, 0x4a, 0xa0, 0x7f, 0x3c, 0x80, 0xf0, 0x79, 0xb1, 0x26, 0x66, 0xd4, 0x1b, 0x9d, 0xb7, 0x21, 0x5c, 0x98, - 0x2d, 0xa9, 0x13, 0x6a, 0xbc, 0xa6, 0xcb, 0x31, 0x7f, 0xad, 0xa1, 0x7d, 0x02, 0x6f, 0xb9, 0x3c, 0xd4, 0x71, 0x0b, - 0x8c, 0x26, 0xa2, 0x22, 0xea, 0x19, 0xb2, 0x90, 0x1a, 0x9d, 0x8d, 0x33, 0x86, 0xfe, 0xbc, 0xe1, 0x83, 0x6a, 0x29, - 0x41, 0xf8, 0x82, 0xc1, 0x67, 0x56, 0x39, 0xc5, 0x97, 0xb6, 0x9e, 0xce, 0x50, 0xcb, 0x1e, 0x09, 0x5d, 0x30, 0xd8, - 0xf6, 0xd1, 0x96, 0x7a, 0x82, 0x48, 0x65, 0xdc, 0x05, 0x49, 0x15, 0x2f, 0x18, 0xdc, 0x67, 0xc9, 0x2d, 0x35, 0xce, - 0x24, 0x2f, 0xec, 0x9f, 0xaf, 0x34, 0xf0, 0xb6, 0x2b, 0x26, 0x43, 0xef, 0xa4, 0x7a, 0x6d, 0xa2, 0xea, 0x90, 0xfd, - 0x7d, 0x6b, 0x4b, 0x6d, 0xbe, 0x36, 0x8d, 0xa9, 0x4d, 0xa2, 0xc9, 0x86, 0x1d, 0xea, 0xd7, 0xe8, 0x1f, 0xef, 0x2b, - 0x56, 0x4c, 0x86, 0x28, 0xa0, 0xd9, 0x06, 0xac, 0xaa, 0x02, 0x96, 0x72, 0xf5, 0x4a, 0x17, 0x42, 0xe8, 0xdd, 0x8c, - 0x79, 0x5d, 0x4c, 0x86, 0x3b, 0x1f, 0xfd, 0xb0, 0x3d, 0xf6, 0xde, 0xd2, 0xa0, 0x07, 0xaf, 0xda, 0x9e, 0xb2, 0xdb, - 0xef, 0xd5, 0xb9, 0xd9, 0x59, 0x47, 0xe5, 0xdf, 0xab, 0xf3, 0x74, 0x57, 0x9d, 0x19, 0xbf, 0x8d, 0xfd, 0xde, 0xd1, - 0x81, 0x1a, 0xdb, 0x18, 0xe8, 0x4c, 0x86, 0x10, 0xa5, 0x1d, 0xfe, 0xda, 0x58, 0x2a, 0x5d, 0x4f, 0xc2, 0x61, 0x15, - 0x64, 0x2f, 0x39, 0x4d, 0x19, 0xa6, 0xa4, 0x73, 0x58, 0x98, 0x68, 0x2a, 0x22, 0xa1, 0x4d, 0x95, 0x50, 0x9c, 0x93, - 0x38, 0xa6, 0x87, 0x19, 0xc4, 0x84, 0x69, 0xf7, 0x68, 0x1a, 0xd3, 0x46, 0x86, 0x8e, 0xe2, 0x76, 0x83, 0x1e, 0x66, - 0x08, 0x35, 0xda, 0xa0, 0x33, 0x95, 0xa4, 0xdd, 0xcc, 0x21, 0x4a, 0xa4, 0x21, 0xc5, 0xf9, 0xa1, 0x48, 0x8a, 0x86, - 0x3c, 0x54, 0x49, 0xd1, 0x48, 0x4e, 0xb1, 0x48, 0x26, 0x65, 0xf2, 0xc4, 0x24, 0x4f, 0x6c, 0xf2, 0xb0, 0x4c, 0x1e, - 0x9a, 0xe4, 0xa1, 0x4d, 0xa6, 0xa4, 0x38, 0x14, 0x09, 0x6d, 0xc4, 0xed, 0x66, 0x81, 0x0e, 0x61, 0x04, 0x7e, 0xf4, - 0x44, 0x84, 0xc1, 0xb9, 0xd7, 0xc6, 0xba, 0x65, 0x2e, 0x73, 0x17, 0x2e, 0xb3, 0x02, 0x52, 0xe9, 0x72, 0x04, 0x75, - 0x9e, 0x05, 0x60, 0xc2, 0xda, 0xfe, 0xf1, 0xc1, 0xe0, 0xd6, 0x59, 0x2e, 0x45, 0xe0, 0x52, 0x05, 0x56, 0xe0, 0x9f, - 0x9d, 0x23, 0x09, 0x40, 0x75, 0x4d, 0xf3, 0xf9, 0x94, 0x6e, 0xf9, 0xad, 0x16, 0x93, 0xa1, 0xdb, 0x59, 0x65, 0x33, - 0x8c, 0x16, 0x36, 0xc8, 0x72, 0xdd, 0xc3, 0x10, 0x40, 0xed, 0xbd, 0x1a, 0x13, 0x6a, 0x94, 0xe4, 0xb6, 0xc6, 0xa4, - 0x60, 0x77, 0x2a, 0xa3, 0x39, 0x8b, 0xab, 0x03, 0xb8, 0x1a, 0x26, 0x23, 0x2f, 0xc0, 0x16, 0xbd, 0x38, 0x4c, 0x8e, - 0x1b, 0x3a, 0x99, 0x1c, 0x26, 0xa7, 0x0f, 0x1a, 0x3a, 0x19, 0x1e, 0x26, 0xed, 0x76, 0x85, 0xb3, 0x49, 0x41, 0x74, - 0x32, 0x21, 0x1a, 0x34, 0x86, 0xb6, 0x51, 0x39, 0xa7, 0x60, 0x5c, 0xf5, 0x6f, 0x0c, 0xa3, 0xe1, 0x86, 0x21, 0xd8, - 0xc4, 0xc6, 0x9b, 0xdc, 0x1a, 0x43, 0xd8, 0x4d, 0xe7, 0xf4, 0xb4, 0xa9, 0x93, 0x02, 0x6b, 0xbb, 0x92, 0x4d, 0x9d, - 0x4c, 0xb0, 0xb6, 0xcb, 0xd7, 0xd4, 0xc9, 0xd0, 0x36, 0x65, 0x74, 0x80, 0x4c, 0x04, 0xc0, 0x7a, 0xce, 0x02, 0xc8, - 0x77, 0xbc, 0x7b, 0xc8, 0x1a, 0xb4, 0x86, 0xdf, 0x2b, 0xd7, 0xf4, 0x05, 0x15, 0xd5, 0x60, 0x64, 0xc3, 0xbe, 0x55, - 0xb4, 0x5d, 0x35, 0xc9, 0xfe, 0x75, 0xd9, 0xb2, 0xd9, 0x42, 0xea, 0x7a, 0xc1, 0x87, 0x35, 0x0c, 0x71, 0xa5, 0xdc, - 0xc1, 0xfd, 0x8a, 0x92, 0x18, 0xa2, 0xca, 0x99, 0x53, 0x88, 0x13, 0xaf, 0x47, 0x86, 0x24, 0xde, 0x68, 0xac, 0x51, - 0x1c, 0x9c, 0xb7, 0x4f, 0x43, 0xaa, 0xba, 0x15, 0x6a, 0x8e, 0x90, 0x68, 0x21, 0xac, 0x31, 0xe2, 0x28, 0x0a, 0x58, - 0x10, 0xa7, 0xdd, 0xad, 0x1d, 0x10, 0x07, 0x07, 0x9b, 0xe7, 0x85, 0x0f, 0xfa, 0xbf, 0x15, 0xe8, 0xbf, 0xb2, 0x64, - 0xf3, 0x4f, 0x11, 0x59, 0x1b, 0x57, 0x1e, 0x20, 0x8a, 0x0f, 0xfa, 0x74, 0xdf, 0x50, 0xf8, 0x7e, 0x15, 0xf1, 0xce, - 0xe5, 0x34, 0xcf, 0x4c, 0x86, 0xe9, 0x6b, 0x10, 0x8c, 0xed, 0x4d, 0x38, 0xa1, 0xd2, 0x4a, 0xef, 0x5f, 0x76, 0x1c, - 0x74, 0xe2, 0x9e, 0x4a, 0x09, 0x1b, 0xfd, 0x3b, 0xb4, 0x89, 0xad, 0x60, 0xe3, 0xbc, 0xa1, 0x57, 0xab, 0xda, 0xc3, - 0x38, 0xf6, 0xf9, 0x15, 0x74, 0x70, 0xc0, 0xd5, 0x33, 0x30, 0xe3, 0x65, 0x71, 0x23, 0x3c, 0x7c, 0xff, 0xa9, 0x9d, - 0xd6, 0x7f, 0x9b, 0x73, 0x35, 0x0d, 0x0e, 0xba, 0x87, 0xb5, 0xfc, 0x9d, 0x2b, 0xd1, 0xd3, 0x29, 0x77, 0x6b, 0xfd, - 0x77, 0x65, 0x24, 0xbd, 0xf5, 0x44, 0xd3, 0xc1, 0x01, 0xaf, 0x02, 0x25, 0x45, 0x3f, 0x44, 0xa8, 0x67, 0x64, 0x90, - 0x67, 0xb9, 0xa4, 0x70, 0x23, 0x0a, 0x57, 0x0c, 0x69, 0x83, 0x1f, 0x69, 0xfc, 0x87, 0xfc, 0xff, 0xd4, 0xc8, 0xa1, - 0x4e, 0x1b, 0x3c, 0x10, 0xc0, 0x42, 0x56, 0xa8, 0x0a, 0x51, 0x68, 0x20, 0x1d, 0xda, 0x3c, 0xa3, 0xf2, 0x30, 0xa7, - 0xf3, 0x79, 0x7e, 0x67, 0x5e, 0xa9, 0x0a, 0x38, 0xaa, 0xea, 0xa2, 0xc9, 0xc5, 0x87, 0xc3, 0x05, 0xf0, 0xf4, 0x80, - 0x7b, 0xc8, 0xf8, 0x77, 0x96, 0x97, 0xdb, 0x02, 0x81, 0x64, 0xa6, 0x88, 0x6c, 0xb6, 0xbb, 0xea, 0x12, 0xe4, 0xb2, - 0x66, 0x13, 0x69, 0x17, 0x36, 0x1b, 0x73, 0x90, 0xc9, 0x94, 0xf5, 0xe1, 0xdc, 0xb3, 0x05, 0x41, 0x72, 0x93, 0x46, - 0x64, 0xdb, 0x5d, 0x8a, 0x8f, 0x63, 0x40, 0x23, 0x64, 0x05, 0xbe, 0x50, 0x58, 0xe4, 0xc0, 0x75, 0x16, 0xbe, 0xe3, - 0x6f, 0xb4, 0x54, 0xf4, 0xd5, 0x60, 0x80, 0x0b, 0xf3, 0x30, 0x43, 0x39, 0x9f, 0x42, 0x05, 0x0f, 0xfd, 0x04, 0x22, - 0x0a, 0x5f, 0xad, 0xf6, 0xe1, 0x1d, 0x1d, 0xd7, 0x26, 0x38, 0x7d, 0xba, 0x9f, 0xd5, 0x9b, 0x19, 0x30, 0x0e, 0x46, - 0x5a, 0xe6, 0xa2, 0xd0, 0xc9, 0x9b, 0xec, 0x42, 0x74, 0x1b, 0x0d, 0x66, 0x42, 0x1c, 0x11, 0x88, 0x67, 0x06, 0x1e, - 0x79, 0xf0, 0xc7, 0x46, 0x2d, 0x52, 0xcc, 0xc6, 0x7e, 0x83, 0xa0, 0xd4, 0xb5, 0x84, 0xd5, 0x4a, 0xd9, 0xd8, 0x22, - 0x26, 0xc7, 0x46, 0x19, 0x29, 0xfb, 0x29, 0x83, 0x98, 0x56, 0x66, 0x1c, 0xdc, 0x6d, 0xf5, 0xb7, 0xd5, 0x7e, 0xde, - 0xe3, 0xf6, 0x1a, 0x8f, 0x1b, 0x8f, 0x7d, 0x03, 0xa8, 0xe5, 0xc6, 0x06, 0xb7, 0x16, 0xe6, 0xb1, 0x35, 0x87, 0x65, - 0x9b, 0x10, 0x14, 0xa5, 0x87, 0xba, 0xbd, 0xb9, 0xf5, 0x11, 0xfb, 0x94, 0x99, 0x93, 0x42, 0xba, 0x0f, 0x72, 0xf4, - 0x80, 0x40, 0xe7, 0xf6, 0x67, 0x45, 0x17, 0x2a, 0x99, 0xb8, 0x1c, 0xe3, 0x2f, 0xc1, 0x6d, 0x5e, 0x3f, 0xba, 0xbe, - 0x36, 0x9b, 0xfc, 0xfa, 0x3a, 0xc2, 0xa1, 0x59, 0x77, 0x14, 0xf0, 0x82, 0xd1, 0xa0, 0x0c, 0xea, 0x64, 0x36, 0x7e, - 0xb3, 0x5d, 0x35, 0xf6, 0x9e, 0x56, 0x78, 0x07, 0xcb, 0x63, 0x1a, 0xdf, 0x72, 0x83, 0xec, 0x73, 0x80, 0x37, 0xeb, - 0xf3, 0x41, 0xf7, 0x4d, 0xac, 0xd0, 0xc1, 0xc1, 0x9b, 0x58, 0xa2, 0xde, 0x15, 0x33, 0x77, 0x6e, 0xe0, 0x07, 0xdd, - 0xe7, 0x66, 0xf8, 0x32, 0x40, 0x80, 0x2b, 0xb6, 0x29, 0xd9, 0xbc, 0x35, 0x51, 0x27, 0x52, 0x88, 0x6a, 0x0d, 0xb1, - 0x75, 0x1d, 0x48, 0xa0, 0xd7, 0x37, 0x21, 0xb4, 0xbb, 0x8c, 0x30, 0x60, 0xe1, 0x4b, 0x2f, 0x35, 0x96, 0xcc, 0x58, - 0x31, 0x61, 0xc5, 0x6a, 0xf5, 0x9e, 0x5a, 0xcf, 0xb3, 0x8d, 0x20, 0x89, 0xaa, 0xdb, 0x68, 0x50, 0x33, 0x7e, 0x10, - 0x1f, 0xe8, 0x00, 0xef, 0xbf, 0x89, 0x0b, 0x84, 0xc0, 0xc2, 0x88, 0x8b, 0x85, 0xf7, 0xb2, 0xca, 0x6a, 0xeb, 0x52, - 0xa0, 0xb2, 0x91, 0x9c, 0xb4, 0xf0, 0x94, 0x64, 0xe5, 0x1a, 0x5d, 0x4c, 0xbb, 0x8d, 0x46, 0x8e, 0x64, 0x9c, 0xf5, - 0xf3, 0x01, 0xe6, 0xb8, 0x80, 0xcb, 0xd4, 0xed, 0x75, 0x98, 0xb3, 0x1a, 0xe5, 0x72, 0xf3, 0x5d, 0xda, 0xb1, 0xa6, - 0x8f, 0xe8, 0x3a, 0x00, 0xc6, 0x23, 0x1a, 0x10, 0x89, 0x5d, 0x40, 0x16, 0x16, 0xc8, 0xca, 0x03, 0x59, 0x18, 0x20, - 0x2b, 0xd4, 0x9b, 0x43, 0xb8, 0x20, 0x85, 0xd2, 0x2d, 0x8a, 0x5e, 0x0f, 0x6c, 0xe9, 0x9c, 0x26, 0x30, 0x37, 0xb1, - 0x15, 0xdc, 0x72, 0x80, 0x03, 0x85, 0xf3, 0xc3, 0x53, 0x64, 0x19, 0x45, 0x26, 0xc6, 0x2b, 0xbe, 0x35, 0x7f, 0x92, - 0x5b, 0x7c, 0x67, 0x7f, 0xdc, 0x05, 0xca, 0xa4, 0xe7, 0x35, 0x6d, 0x03, 0x77, 0x11, 0xd1, 0xa2, 0x24, 0x02, 0xb4, - 0x76, 0xe1, 0xfd, 0x44, 0xfd, 0xc5, 0x33, 0x65, 0x03, 0x31, 0x88, 0x06, 0x51, 0x58, 0x04, 0xa4, 0xf3, 0xcf, 0x3f, - 0x23, 0xd4, 0x13, 0x10, 0x47, 0xc7, 0x9d, 0x6c, 0xcd, 0x36, 0x6a, 0x44, 0x49, 0x94, 0xc6, 0x3e, 0x4c, 0x03, 0xec, - 0x8c, 0x28, 0x0a, 0x5e, 0x3b, 0x29, 0x87, 0xf1, 0xa1, 0x36, 0x0c, 0x33, 0xa8, 0x2a, 0xf0, 0xc4, 0xe5, 0x72, 0x33, - 0xcc, 0x8f, 0x81, 0xaa, 0x30, 0x31, 0x56, 0x90, 0x7d, 0x02, 0x8c, 0x11, 0x76, 0x70, 0xc0, 0xfa, 0x62, 0x10, 0xbc, - 0xe9, 0x55, 0x5d, 0x87, 0xeb, 0x70, 0xe1, 0x62, 0x0a, 0x71, 0xd6, 0x57, 0x2b, 0xfb, 0x97, 0x7c, 0x30, 0xd2, 0x0c, - 0x3c, 0xce, 0x16, 0x9c, 0xb1, 0x62, 0xb7, 0x2c, 0x96, 0x68, 0xf9, 0x3b, 0x98, 0xed, 0xb9, 0xa8, 0x79, 0xdc, 0x4d, - 0xb5, 0xed, 0xa1, 0x3e, 0x37, 0x1a, 0x85, 0x20, 0x66, 0x6d, 0x75, 0xa4, 0xe1, 0xb9, 0x0e, 0xf3, 0x6a, 0xb1, 0x67, - 0x33, 0x55, 0x86, 0x10, 0x85, 0x23, 0x25, 0x01, 0xbb, 0x6d, 0x43, 0x27, 0xe1, 0x47, 0x9d, 0x4a, 0x3a, 0x16, 0x12, - 0xa0, 0xc0, 0x91, 0xb9, 0x9c, 0x37, 0x21, 0xe2, 0x19, 0xda, 0x41, 0xe4, 0x02, 0x13, 0x9a, 0xba, 0x6c, 0xe9, 0x62, - 0x39, 0x45, 0x33, 0xb9, 0x50, 0x6c, 0x31, 0x87, 0xf3, 0xbd, 0x4c, 0xcb, 0x72, 0x9e, 0x7d, 0xae, 0xa7, 0x80, 0xfd, - 0xe5, 0xad, 0x9e, 0x31, 0xb1, 0x88, 0xdc, 0x3c, 0xbf, 0x5a, 0x71, 0xff, 0xcd, 0x0b, 0xfc, 0x88, 0x74, 0x0e, 0xbf, - 0xe2, 0x8f, 0x94, 0x3c, 0x6a, 0x7c, 0xc5, 0x13, 0x4e, 0x2c, 0x6f, 0x90, 0xbc, 0x79, 0x7d, 0xf5, 0xe2, 0xdd, 0x8b, - 0xf7, 0x4f, 0xaf, 0x5f, 0xbc, 0x7a, 0xf6, 0xe2, 0xd5, 0x8b, 0x77, 0x1f, 0xf1, 0x3f, 0x94, 0x7c, 0x3d, 0x6a, 0x9f, - 0xb7, 0xf0, 0x07, 0xf2, 0xf5, 0xa8, 0x83, 0x6f, 0x35, 0xf9, 0x7a, 0x74, 0x82, 0x73, 0x45, 0xbe, 0x1e, 0x76, 0x8e, - 0x8e, 0xf1, 0x42, 0xdb, 0x26, 0x73, 0x39, 0x69, 0xb7, 0xf0, 0x3f, 0xee, 0x0b, 0xc4, 0xfb, 0x6a, 0x16, 0x13, 0xb6, - 0x61, 0xfc, 0x60, 0xca, 0xd0, 0xa1, 0x32, 0x86, 0x28, 0x17, 0x01, 0x3a, 0x4d, 0x55, 0x88, 0x4e, 0x36, 0x88, 0x31, - 0xd8, 0x30, 0x02, 0x5a, 0x71, 0xe2, 0xda, 0xe1, 0x47, 0x6d, 0x76, 0x0c, 0xf4, 0x89, 0x97, 0xc2, 0x71, 0xa9, 0xc2, - 0x69, 0x3b, 0x2d, 0xc6, 0x38, 0x97, 0xb2, 0x88, 0x17, 0xc0, 0x08, 0x18, 0xad, 0x05, 0x3f, 0x2a, 0xa3, 0x25, 0x89, - 0x0b, 0xd2, 0xee, 0xb5, 0x53, 0x71, 0x41, 0x3a, 0xbd, 0x0e, 0xfc, 0x39, 0xed, 0x9d, 0xa6, 0xed, 0x16, 0x3a, 0x0c, - 0xc6, 0xf1, 0x47, 0x0d, 0xad, 0xfb, 0x03, 0xec, 0xba, 0x50, 0xff, 0x14, 0xda, 0xab, 0xf4, 0x84, 0x53, 0xc7, 0xb6, - 0xbb, 0xe2, 0x82, 0x19, 0x3d, 0x2c, 0xff, 0x01, 0x50, 0xdb, 0x38, 0x74, 0x94, 0x1b, 0xc7, 0xfd, 0xe2, 0x47, 0x02, - 0xd5, 0x42, 0xb2, 0xc4, 0x6c, 0xd5, 0x42, 0xc0, 0x34, 0x9a, 0x6c, 0x30, 0x07, 0x4a, 0x94, 0x2c, 0xb4, 0x0f, 0x2b, - 0xaf, 0x9a, 0x12, 0x25, 0x73, 0x39, 0x8f, 0x6b, 0xaa, 0x86, 0x5f, 0x03, 0x33, 0xc7, 0x7d, 0xae, 0x5e, 0xd1, 0x57, - 0x71, 0x8d, 0xe7, 0x09, 0x59, 0xbb, 0x70, 0x5b, 0xfc, 0xe2, 0xac, 0x28, 0x6a, 0xe0, 0x2a, 0x01, 0xeb, 0x47, 0xd5, - 0xd4, 0x17, 0xf0, 0x7e, 0x1e, 0x6b, 0xe8, 0x4b, 0x12, 0x50, 0xcf, 0x9f, 0x4a, 0x33, 0xae, 0x52, 0x19, 0xed, 0x15, - 0xd1, 0xc6, 0x2c, 0xc8, 0x2b, 0xa2, 0x2f, 0x94, 0x01, 0x82, 0x24, 0xbc, 0x2f, 0x06, 0x70, 0xe0, 0xdb, 0x01, 0x4a, - 0x43, 0xe7, 0x40, 0xad, 0x54, 0x99, 0x09, 0x99, 0x4f, 0x13, 0x1c, 0x00, 0x34, 0x4f, 0x95, 0x0a, 0xca, 0x7c, 0x62, - 0x89, 0x82, 0xa1, 0xff, 0x16, 0x6e, 0x80, 0xc3, 0xd8, 0xa0, 0x62, 0x90, 0x7d, 0x4f, 0xd4, 0xf3, 0xdb, 0xe7, 0xad, - 0xa3, 0xaf, 0x41, 0xfe, 0x48, 0x79, 0x7b, 0x8f, 0xbf, 0x03, 0x4a, 0x6e, 0xc3, 0x59, 0xb5, 0xb1, 0x8f, 0x44, 0xd6, - 0x0d, 0x01, 0x72, 0xa8, 0xd1, 0x91, 0x79, 0x4a, 0xb0, 0x8b, 0xf4, 0x21, 0x69, 0xb7, 0x20, 0x7c, 0xd8, 0x0e, 0xca, - 0xf7, 0xd3, 0x06, 0x4c, 0x75, 0x72, 0xdb, 0x04, 0x5a, 0x0d, 0xaf, 0x0b, 0xdd, 0x35, 0x79, 0x72, 0x87, 0x55, 0x80, - 0x33, 0xec, 0x90, 0x35, 0xc4, 0xa1, 0x40, 0x2e, 0xec, 0xaa, 0xdd, 0x00, 0x9a, 0x8a, 0x8e, 0x7d, 0xe5, 0xce, 0x1b, - 0x47, 0x5d, 0x34, 0x93, 0xd3, 0xc3, 0xaf, 0x07, 0x07, 0xb1, 0x6c, 0x90, 0x47, 0x08, 0x2f, 0x29, 0x58, 0x31, 0x83, - 0xd7, 0x17, 0xb7, 0x4c, 0x7c, 0xaa, 0x02, 0xea, 0xb8, 0x50, 0xb5, 0x63, 0xad, 0xea, 0xac, 0xdc, 0x0d, 0x7e, 0x4c, - 0x1d, 0xd4, 0x08, 0xd2, 0xec, 0xe8, 0x3a, 0x35, 0x28, 0xd7, 0x5c, 0xb4, 0x60, 0x5b, 0x36, 0x3e, 0x52, 0xf4, 0xc3, - 0xa3, 0xe6, 0xd7, 0x60, 0xc2, 0x35, 0xd3, 0xa4, 0x47, 0x8d, 0x47, 0xe8, 0x87, 0x47, 0x81, 0x93, 0x1d, 0xaf, 0xd8, - 0x13, 0xcf, 0x8d, 0xfc, 0x64, 0xb9, 0xd2, 0x9f, 0x40, 0xb2, 0x2f, 0xc8, 0x4f, 0x80, 0xe5, 0x94, 0xfc, 0x14, 0xcb, - 0x26, 0x04, 0x1f, 0x24, 0x3f, 0xc5, 0x05, 0xfc, 0xc8, 0xc9, 0x4f, 0x31, 0x60, 0x3b, 0x9e, 0x9a, 0x1f, 0x45, 0x09, - 0x0c, 0x70, 0xec, 0x92, 0xd6, 0xbf, 0xab, 0x58, 0xad, 0xc4, 0xc1, 0x81, 0xb4, 0xbf, 0xe8, 0x65, 0x76, 0x70, 0x90, - 0x5f, 0x4c, 0xab, 0xbe, 0x99, 0xde, 0x45, 0x5f, 0x0c, 0x42, 0xe1, 0xc0, 0x34, 0x8d, 0x87, 0x33, 0xfe, 0x14, 0x52, - 0x56, 0xd3, 0x40, 0xf3, 0xb8, 0x73, 0xff, 0xec, 0x1c, 0xc3, 0xbf, 0xf7, 0x83, 0x82, 0x3f, 0x97, 0x7c, 0x17, 0x69, - 0xb3, 0xe6, 0x59, 0x85, 0x6c, 0x97, 0x01, 0x3e, 0x63, 0x86, 0x9a, 0xe2, 0xe0, 0x80, 0x5f, 0x04, 0xb8, 0x8c, 0x19, - 0x6a, 0x04, 0x16, 0x7b, 0x0f, 0x4b, 0x7b, 0x32, 0xc3, 0x35, 0xc1, 0xb3, 0xb2, 0xbc, 0x5f, 0x0c, 0x2e, 0xb4, 0xa3, - 0x26, 0x61, 0xf0, 0x69, 0x45, 0x5a, 0x6e, 0x93, 0x75, 0x45, 0x53, 0x5d, 0xb6, 0xbb, 0x48, 0x12, 0xd5, 0x10, 0x97, - 0x97, 0x6d, 0x0c, 0x2a, 0xf9, 0x9e, 0x22, 0x32, 0x15, 0xc4, 0x3b, 0xc8, 0x2d, 0x73, 0x99, 0x2a, 0x3c, 0xe5, 0xa9, - 0xf0, 0x72, 0xf6, 0x6b, 0x6f, 0x3d, 0x6d, 0x5c, 0x16, 0x4d, 0xcf, 0x0c, 0x8b, 0x9e, 0x2a, 0x5d, 0xed, 0x60, 0x93, - 0xaa, 0x01, 0xbc, 0xda, 0x57, 0x62, 0x1e, 0xb3, 0xfe, 0x65, 0x0c, 0xa2, 0x22, 0xab, 0x46, 0x1b, 0x32, 0xe1, 0x73, - 0x9d, 0x2a, 0x18, 0xa8, 0x29, 0x7c, 0x01, 0x64, 0x2a, 0xab, 0x0c, 0xb3, 0x7d, 0xc3, 0x50, 0x40, 0x40, 0x81, 0x4b, - 0xc2, 0x02, 0x09, 0x1e, 0x6e, 0x3f, 0x02, 0xc2, 0x51, 0x27, 0x17, 0x76, 0x72, 0x17, 0x0a, 0xba, 0x13, 0x83, 0x0b, - 0xdd, 0x45, 0xa2, 0xd1, 0x70, 0xdc, 0xf6, 0xa5, 0x30, 0x83, 0x68, 0xb6, 0x07, 0x97, 0xac, 0x8b, 0x54, 0xb3, 0x59, - 0x1a, 0x40, 0x5e, 0xb6, 0x56, 0x2b, 0x75, 0xe1, 0x1b, 0xe9, 0xf9, 0x73, 0xdc, 0xf0, 0x5d, 0x5e, 0xf0, 0xfc, 0x4d, - 0x92, 0x7e, 0x04, 0x54, 0x15, 0xf8, 0x6c, 0x39, 0x8f, 0x70, 0x64, 0x1e, 0x74, 0x83, 0xbf, 0xe6, 0x21, 0xae, 0x08, - 0x47, 0xee, 0x8d, 0xb7, 0x68, 0x50, 0x0d, 0x96, 0x67, 0x65, 0x78, 0x72, 0x9e, 0x5c, 0x03, 0xe3, 0xa0, 0xff, 0x56, - 0x68, 0x59, 0xfd, 0x4e, 0x72, 0x17, 0xa8, 0x43, 0xf9, 0x67, 0xc7, 0xdc, 0xa8, 0xd6, 0xbb, 0x5d, 0x23, 0x39, 0x8e, - 0x7c, 0x55, 0x08, 0xdf, 0xff, 0x9d, 0x77, 0x0f, 0xdb, 0xee, 0xb9, 0xed, 0x65, 0xd9, 0x03, 0x70, 0xde, 0xeb, 0x35, - 0xc2, 0xbf, 0xc9, 0x9d, 0x6f, 0xef, 0x46, 0xd7, 0x52, 0x3c, 0xa1, 0x9a, 0x46, 0x8d, 0x37, 0xc6, 0xf0, 0xcd, 0xca, - 0x59, 0xdd, 0x6f, 0x8d, 0x83, 0xfd, 0x5b, 0xdd, 0x43, 0xe8, 0x84, 0xda, 0x33, 0x41, 0x56, 0xf6, 0x35, 0x01, 0x33, - 0x64, 0x60, 0xfa, 0xb6, 0x03, 0x1e, 0x7e, 0x8c, 0x14, 0x1c, 0x7a, 0x2d, 0x9f, 0x44, 0x21, 0x26, 0x69, 0xcd, 0x8d, - 0x18, 0x52, 0x6c, 0x1f, 0xc6, 0xe5, 0x74, 0x8d, 0x42, 0xae, 0x7b, 0xac, 0xea, 0xc4, 0xb4, 0xea, 0xc6, 0x48, 0x1d, - 0x6c, 0x93, 0x05, 0x67, 0x55, 0xef, 0x46, 0x42, 0xa9, 0x5e, 0x54, 0x33, 0xaf, 0x62, 0x36, 0xdb, 0xe6, 0x99, 0x61, - 0xfb, 0xee, 0x9a, 0x02, 0x43, 0xde, 0xfd, 0x32, 0x5c, 0xd4, 0x25, 0x1c, 0xbb, 0x71, 0x00, 0x59, 0x49, 0x2e, 0x97, - 0xee, 0x4d, 0x34, 0xde, 0x97, 0x83, 0x75, 0xf9, 0x42, 0x5a, 0x80, 0x07, 0xd5, 0x48, 0x45, 0x16, 0x72, 0x06, 0xfe, - 0x79, 0xc1, 0x9a, 0x7e, 0x88, 0x7f, 0x85, 0x03, 0xbe, 0x42, 0xd2, 0xd4, 0xaa, 0x9f, 0xe0, 0xe5, 0x22, 0x50, 0x78, - 0xdb, 0xba, 0x9f, 0x64, 0xe8, 0x22, 0x5a, 0xd7, 0xa9, 0x58, 0x2f, 0xcc, 0xba, 0x62, 0xa5, 0x2c, 0x1c, 0x1c, 0x77, - 0x31, 0x5a, 0xa7, 0xce, 0x63, 0xd3, 0x3d, 0x77, 0xf4, 0x50, 0xf0, 0x99, 0x71, 0xa4, 0x7b, 0x56, 0x40, 0xfc, 0xaa, - 0x50, 0x9f, 0xf6, 0xb3, 0x0c, 0xdf, 0xf3, 0xed, 0xc3, 0x3d, 0x61, 0xc9, 0x73, 0x96, 0x6f, 0x50, 0xc3, 0x02, 0x29, - 0xa0, 0x50, 0x0a, 0x8b, 0xd5, 0x2a, 0x16, 0x26, 0xaa, 0x81, 0x0b, 0x6a, 0xeb, 0x5e, 0xaf, 0x30, 0xfa, 0x3b, 0xa8, - 0x8b, 0xbd, 0x7a, 0xc4, 0x98, 0xb0, 0xa2, 0xf0, 0xd2, 0x49, 0x65, 0x41, 0x5f, 0xbb, 0xfa, 0x10, 0xd5, 0x94, 0x7b, - 0xb1, 0xd1, 0xf7, 0xbe, 0xe3, 0x33, 0x26, 0x17, 0xf0, 0x6c, 0x10, 0x66, 0x44, 0x31, 0xed, 0xbf, 0x81, 0x82, 0xc0, - 0xdb, 0x33, 0x3c, 0xc4, 0x47, 0xe0, 0xab, 0x3c, 0xad, 0x93, 0x99, 0x7f, 0x8c, 0x22, 0x32, 0xc1, 0x22, 0xa3, 0x5e, - 0x04, 0x5e, 0x43, 0x20, 0x42, 0x11, 0x12, 0x31, 0x31, 0x8a, 0x7a, 0x91, 0x71, 0x52, 0x8a, 0xc0, 0x6a, 0x0c, 0x94, - 0xdc, 0x11, 0x9e, 0xab, 0x8a, 0x88, 0x85, 0x35, 0x75, 0x50, 0x89, 0xa5, 0xc6, 0x4c, 0xfb, 0xa8, 0x53, 0x81, 0xb0, - 0xc8, 0x36, 0x05, 0x65, 0xbd, 0xa1, 0x2e, 0xc0, 0x92, 0x18, 0xd3, 0x5b, 0x9e, 0x5c, 0x03, 0x37, 0xc7, 0x46, 0xae, - 0xe8, 0x92, 0x5f, 0x81, 0x7a, 0x3a, 0x2d, 0xf0, 0xb5, 0x61, 0xd8, 0x46, 0x29, 0x5d, 0x13, 0x8e, 0x33, 0x52, 0x24, - 0xf4, 0x16, 0xa2, 0x3a, 0xcc, 0xb8, 0x48, 0x73, 0x3c, 0xa3, 0xb7, 0xe9, 0x14, 0xcf, 0xb8, 0x78, 0x62, 0x97, 0x3d, - 0x1d, 0x41, 0x92, 0xff, 0x58, 0xac, 0x89, 0x79, 0x94, 0xea, 0x77, 0xc5, 0x8a, 0x47, 0xc0, 0xab, 0xa8, 0x18, 0x75, - 0x47, 0xc6, 0xa6, 0x9c, 0xe9, 0xca, 0x78, 0xfd, 0xb5, 0x8e, 0x29, 0xce, 0x70, 0x8e, 0x92, 0x5c, 0x62, 0xd6, 0x13, - 0xe9, 0x6b, 0x88, 0xe8, 0x9c, 0x61, 0xfb, 0xa0, 0x15, 0xbf, 0x65, 0xf9, 0x33, 0x59, 0xbc, 0x37, 0x5b, 0x3e, 0x47, - 0x50, 0x08, 0x5c, 0x54, 0x44, 0x13, 0x6e, 0xf7, 0x16, 0x3d, 0x59, 0x35, 0x45, 0x6f, 0x6d, 0x53, 0x6e, 0x88, 0x53, - 0x08, 0x85, 0x9b, 0x4c, 0x79, 0xa3, 0x8d, 0x59, 0xaf, 0xf5, 0x9d, 0x46, 0xa7, 0xa8, 0x2c, 0x89, 0x30, 0xac, 0x55, - 0x53, 0xa5, 0x92, 0x88, 0xa6, 0x72, 0x12, 0xde, 0xd2, 0x00, 0x3b, 0x55, 0x38, 0x93, 0x0b, 0xa1, 0x53, 0x19, 0xe0, - 0x0d, 0xad, 0x36, 0xd7, 0xf2, 0xd6, 0x42, 0x4c, 0xe3, 0x3b, 0xfb, 0x83, 0xe1, 0x6b, 0xa3, 0xe2, 0x7f, 0x0b, 0x86, - 0x3d, 0x2a, 0x15, 0x00, 0x3f, 0x30, 0x9c, 0x05, 0xc8, 0x59, 0x7e, 0xf2, 0x16, 0xc0, 0x67, 0x59, 0xc8, 0x3b, 0x48, - 0x65, 0x26, 0xf5, 0x0e, 0x52, 0x19, 0xa4, 0x1a, 0x5f, 0xee, 0x7d, 0x51, 0x29, 0x8b, 0xc2, 0x06, 0x89, 0xc2, 0xa5, - 0x3a, 0x58, 0x12, 0x91, 0x40, 0xbb, 0x46, 0x94, 0x9b, 0x71, 0x01, 0x41, 0xfd, 0xa0, 0x71, 0xfb, 0x4d, 0x6f, 0xe1, - 0xfb, 0xce, 0xe6, 0x33, 0x9f, 0x7f, 0x67, 0xf3, 0x4d, 0x47, 0x1e, 0xe3, 0xeb, 0xb7, 0x9d, 0xc6, 0x32, 0x5e, 0x3a, - 0xac, 0xfd, 0x50, 0x3e, 0xa1, 0xd2, 0x32, 0x4f, 0x55, 0x93, 0x36, 0x9e, 0x04, 0x48, 0xd9, 0xac, 0x78, 0xb8, 0x0e, - 0x6e, 0xb7, 0x0e, 0x63, 0xde, 0x24, 0x6d, 0x84, 0x0e, 0x9d, 0x70, 0x25, 0x62, 0x23, 0x39, 0x1d, 0x3e, 0x3a, 0x82, - 0xbb, 0x97, 0x99, 0xda, 0xf0, 0x95, 0xb2, 0xd5, 0x9a, 0xed, 0xd6, 0x21, 0xdf, 0x59, 0xa5, 0xd1, 0xc6, 0x33, 0x46, - 0x96, 0xe0, 0x5c, 0x46, 0x0b, 0xab, 0x6a, 0x00, 0x27, 0xce, 0x17, 0xe2, 0xb7, 0x05, 0x1d, 0x99, 0xef, 0x43, 0x9b, - 0xf2, 0x7a, 0xa1, 0x7d, 0x52, 0x93, 0xc3, 0x20, 0x3a, 0xc8, 0x95, 0x0c, 0x72, 0x62, 0x7e, 0x44, 0x92, 0x53, 0x74, - 0xd1, 0xee, 0x25, 0xa7, 0x87, 0xfc, 0x90, 0xa7, 0xc0, 0xc3, 0xc6, 0x4d, 0x5f, 0xa1, 0xd9, 0xf6, 0x75, 0x1e, 0x2f, - 0x86, 0x3c, 0x73, 0xcd, 0x57, 0x1d, 0x94, 0xa9, 0x76, 0x8e, 0x90, 0x05, 0x28, 0xe6, 0x7b, 0x09, 0xb2, 0xeb, 0xdd, - 0x1c, 0xf2, 0x14, 0xfa, 0x81, 0x5a, 0x1d, 0x5b, 0xab, 0x1c, 0xdc, 0x6f, 0x0b, 0x40, 0x30, 0xdf, 0x51, 0x6d, 0x2e, - 0x36, 0xbd, 0x19, 0x57, 0x9d, 0x1d, 0xf2, 0x6a, 0x84, 0x61, 0x99, 0xed, 0xfe, 0xfc, 0xd4, 0xaa, 0x2e, 0x0f, 0x03, - 0x88, 0xfc, 0xb6, 0xe0, 0x22, 0xec, 0x34, 0xec, 0xd6, 0xe5, 0x84, 0x9d, 0xd6, 0x67, 0x19, 0x14, 0xd9, 0xee, 0x75, - 0x6b, 0xa6, 0xf5, 0xd9, 0x5e, 0x81, 0x8f, 0x20, 0x4c, 0xca, 0xac, 0x74, 0x06, 0x57, 0xe8, 0x87, 0x1f, 0x90, 0x6b, - 0xfd, 0xf5, 0x42, 0xfb, 0xfc, 0x12, 0x11, 0x20, 0xbb, 0xea, 0xba, 0xac, 0x0e, 0x7d, 0x94, 0x4d, 0x7c, 0x3d, 0xe4, - 0xc1, 0xca, 0x3d, 0xbd, 0x9d, 0xcb, 0xd4, 0xe3, 0x6b, 0xaf, 0x95, 0x6e, 0x21, 0x27, 0x10, 0x0f, 0xd7, 0x5d, 0x58, - 0x16, 0xe4, 0xec, 0xe6, 0x16, 0x4a, 0x86, 0x13, 0xf7, 0xa5, 0x3f, 0x30, 0x7b, 0xdd, 0xc0, 0x2f, 0x92, 0x53, 0x98, - 0xfa, 0x66, 0x0f, 0x87, 0x1d, 0xe8, 0xc3, 0xc0, 0x61, 0xb3, 0x41, 0x9f, 0x59, 0x41, 0xe4, 0x31, 0x2f, 0x2c, 0x9e, - 0x5d, 0x92, 0x76, 0x8f, 0xa7, 0x6e, 0x33, 0x19, 0xd1, 0xa8, 0xdd, 0xe4, 0xc1, 0xcc, 0x00, 0xbf, 0x5c, 0xd9, 0xb0, - 0x88, 0x5f, 0xa7, 0x00, 0x4a, 0xbe, 0x58, 0xb5, 0x3e, 0x15, 0xbc, 0xea, 0x0d, 0xa7, 0x9b, 0xe9, 0x7e, 0xdd, 0xe0, - 0x76, 0xd7, 0xc3, 0x13, 0x9e, 0x40, 0xb1, 0x68, 0xed, 0x27, 0x3e, 0x01, 0x0e, 0x28, 0x69, 0xdd, 0x3f, 0x05, 0x17, - 0xca, 0x12, 0x96, 0xdb, 0xe5, 0x66, 0x5b, 0xe5, 0x2c, 0x1c, 0x6d, 0xc9, 0x80, 0x3b, 0xd8, 0x84, 0x28, 0x74, 0x70, - 0xd8, 0xc1, 0x49, 0xbb, 0xdd, 0x39, 0xc5, 0xc9, 0xc9, 0x29, 0x0c, 0xb4, 0x91, 0x9c, 0x1e, 0xce, 0x94, 0x05, 0x60, - 0x90, 0xb3, 0x76, 0xed, 0x3e, 0x82, 0x70, 0x49, 0xa1, 0x78, 0xcd, 0x0f, 0xe3, 0xb8, 0x9d, 0xdc, 0x6f, 0xb5, 0x4f, - 0xcf, 0x1b, 0x00, 0xa0, 0xa6, 0xfb, 0x70, 0x35, 0x5e, 0x2f, 0x74, 0xbd, 0x4a, 0x89, 0xf0, 0xf5, 0x6a, 0x0d, 0x5f, - 0xad, 0xd1, 0x5e, 0x57, 0x53, 0xf0, 0x55, 0x9d, 0x70, 0x6e, 0x8b, 0x78, 0xa5, 0x4d, 0xb8, 0x2d, 0x62, 0x3b, 0x90, - 0x18, 0xa4, 0xf3, 0xe4, 0xb4, 0x73, 0x8a, 0xec, 0x58, 0xb4, 0xc3, 0x8f, 0x72, 0x9f, 0x6c, 0x15, 0x69, 0x68, 0x40, - 0x92, 0x72, 0x76, 0x72, 0x01, 0x12, 0x35, 0x27, 0x97, 0xed, 0xe6, 0x8c, 0x25, 0x7e, 0x02, 0x26, 0x15, 0x96, 0xb3, - 0x5c, 0x05, 0x97, 0x14, 0x00, 0xe2, 0x02, 0x8c, 0x8b, 0xee, 0x9f, 0xf6, 0xee, 0x27, 0xa7, 0x67, 0x1d, 0x4b, 0xf4, - 0xf8, 0x45, 0xa7, 0x96, 0x66, 0xa6, 0x9e, 0x9c, 0x9a, 0x34, 0xe8, 0x3a, 0xb9, 0x7f, 0x0a, 0x65, 0x5c, 0x4a, 0x58, - 0x0a, 0xc2, 0x3c, 0x54, 0xc5, 0x20, 0xb6, 0x43, 0x5a, 0xcb, 0x3d, 0xab, 0x65, 0x9f, 0x9f, 0x1c, 0xdf, 0x3f, 0x0d, - 0xa1, 0x56, 0xce, 0xc2, 0x2c, 0xb4, 0x9b, 0x88, 0x9f, 0x1d, 0x2c, 0x2d, 0x3a, 0x4c, 0x4e, 0xd3, 0xad, 0x09, 0xda, - 0x4d, 0x73, 0x68, 0x70, 0x20, 0x50, 0x38, 0x3e, 0x15, 0x4e, 0x5f, 0x12, 0xdc, 0x8f, 0x55, 0x86, 0x26, 0xa1, 0xc2, - 0xd9, 0xdf, 0x53, 0x06, 0x2f, 0x39, 0x86, 0x57, 0x95, 0x8f, 0xa9, 0xf8, 0x42, 0xd5, 0x1b, 0x0a, 0xb1, 0x2b, 0xc4, - 0x20, 0x72, 0x91, 0xb5, 0xeb, 0xb9, 0x3f, 0x81, 0x8b, 0x30, 0x13, 0x70, 0xa1, 0xe9, 0x95, 0xa0, 0x15, 0x2f, 0x30, - 0x0c, 0x1d, 0x6a, 0xcd, 0xb0, 0x7a, 0x3c, 0x75, 0x26, 0x05, 0xa1, 0x6e, 0xeb, 0x39, 0xff, 0x5e, 0xb9, 0xa4, 0xbc, - 0xca, 0x4e, 0x4e, 0x51, 0xe2, 0x2e, 0xcb, 0x93, 0x36, 0x4a, 0x02, 0x13, 0x12, 0x77, 0x24, 0x67, 0x19, 0xe9, 0x47, - 0xb7, 0x11, 0x8e, 0xee, 0x22, 0x1c, 0x59, 0x1f, 0xe6, 0x0f, 0xe0, 0x3c, 0x1f, 0xe1, 0xc8, 0xba, 0x32, 0x47, 0x38, - 0xd2, 0x4c, 0x40, 0x48, 0xab, 0x68, 0x80, 0x73, 0x28, 0x6d, 0x3c, 0xab, 0xcb, 0xd2, 0x8f, 0xfd, 0x57, 0xe9, 0x7a, - 0x6d, 0x53, 0x02, 0x29, 0x73, 0x6a, 0x76, 0xa8, 0x7d, 0x92, 0x39, 0xa2, 0x9e, 0x59, 0x8f, 0x30, 0x08, 0x20, 0xf4, - 0xce, 0x3f, 0xe9, 0x56, 0x45, 0xc3, 0x60, 0xc7, 0xb0, 0xd2, 0xe0, 0x67, 0x1e, 0x85, 0x67, 0x58, 0x84, 0xc7, 0xc2, - 0x17, 0x06, 0xb1, 0xc2, 0xff, 0xce, 0xa5, 0x9c, 0xfb, 0xdf, 0x5a, 0x96, 0xbf, 0xe0, 0x21, 0x10, 0x67, 0xd1, 0x02, - 0x96, 0x5b, 0x36, 0xf8, 0xce, 0x90, 0xd5, 0x47, 0x70, 0x3d, 0x76, 0x01, 0xd2, 0x40, 0x22, 0xbc, 0x36, 0x02, 0x95, - 0x97, 0x0f, 0xaf, 0x6d, 0xb0, 0x1e, 0xf3, 0x09, 0xd1, 0xba, 0x20, 0x20, 0xaf, 0x84, 0x0b, 0x8d, 0x49, 0xc1, 0x94, - 0x8a, 0x6c, 0x14, 0xbb, 0x48, 0x0a, 0xff, 0x2c, 0xa1, 0x4f, 0x19, 0x8b, 0xc8, 0x74, 0x58, 0x9f, 0xad, 0x15, 0x87, - 0x73, 0x59, 0xa8, 0xd4, 0xbe, 0x51, 0xe2, 0xc1, 0x58, 0x3d, 0x55, 0x9f, 0xe6, 0xd9, 0x1a, 0xdb, 0x3b, 0xec, 0xb2, - 0x90, 0xbb, 0xd2, 0x0e, 0x4b, 0x65, 0xd9, 0xfa, 0x5b, 0x13, 0x52, 0xb5, 0x19, 0x05, 0x13, 0xad, 0x06, 0x54, 0x85, - 0xb2, 0x80, 0xc2, 0x36, 0x1c, 0x4a, 0xba, 0x2c, 0x4b, 0xa6, 0xcb, 0x72, 0x19, 0x4e, 0x5a, 0xad, 0xf5, 0x1a, 0x17, - 0xcc, 0x84, 0x65, 0xd9, 0x59, 0x02, 0xf2, 0xd5, 0x54, 0xde, 0x04, 0xb9, 0x2a, 0x2d, 0x67, 0x69, 0x96, 0x28, 0x0a, - 0x8c, 0x60, 0xa3, 0x35, 0xfe, 0xc2, 0x15, 0x07, 0x78, 0xba, 0xd9, 0x0d, 0xa5, 0xcc, 0x19, 0x85, 0xe8, 0x5d, 0x41, - 0x93, 0x6b, 0x3c, 0xe5, 0x23, 0xb6, 0xbb, 0x4d, 0x30, 0x63, 0xfe, 0xf7, 0x5a, 0xf4, 0x08, 0x64, 0xd9, 0x3d, 0x83, - 0x3a, 0xb0, 0x88, 0x2b, 0xe8, 0x20, 0x94, 0xc1, 0x47, 0x21, 0x6e, 0xe6, 0xf4, 0x4e, 0x2e, 0x34, 0xc0, 0x65, 0xa1, - 0xe5, 0x1b, 0x17, 0xeb, 0x60, 0xbf, 0x85, 0x7d, 0xd8, 0x83, 0x25, 0x84, 0x0c, 0x68, 0x61, 0x1b, 0x23, 0xa2, 0x85, - 0x87, 0x52, 0x6b, 0x39, 0x4b, 0x5b, 0xd8, 0x04, 0x6c, 0x68, 0xad, 0xcb, 0xa8, 0x5a, 0xd7, 0xe5, 0x63, 0x8e, 0xd5, - 0x26, 0x58, 0x38, 0xe9, 0x50, 0x13, 0x1d, 0xdc, 0x1e, 0x32, 0xc2, 0x1b, 0x3f, 0x5f, 0xbd, 0x7e, 0xe5, 0x62, 0x26, - 0xf3, 0x31, 0xb8, 0x6c, 0x3a, 0xd5, 0xd8, 0xb5, 0x79, 0x05, 0x29, 0xae, 0x14, 0xa5, 0x56, 0x38, 0x85, 0x96, 0x5f, - 0x08, 0x9d, 0x27, 0xf6, 0xf2, 0xe2, 0x99, 0x2c, 0x66, 0xd4, 0xde, 0x18, 0xe1, 0x6b, 0xe5, 0x9e, 0x3d, 0x37, 0x2f, - 0xab, 0x54, 0x93, 0x7c, 0xb7, 0x79, 0x15, 0xb1, 0xc8, 0x8c, 0xfc, 0x0a, 0xda, 0x00, 0x53, 0xb9, 0x7c, 0xb5, 0xb6, - 0x20, 0x2e, 0xf2, 0x7c, 0x40, 0x5e, 0xde, 0x5a, 0xea, 0x12, 0x45, 0x0d, 0x6e, 0xf0, 0x93, 0x15, 0x3c, 0x0b, 0xae, - 0x0b, 0x0d, 0x7b, 0xe4, 0xc4, 0x8b, 0xa8, 0x15, 0xd5, 0x5f, 0x7d, 0x35, 0xaa, 0x04, 0x1f, 0xb5, 0x34, 0xc9, 0x25, - 0x88, 0x1e, 0xe5, 0x03, 0x73, 0x1c, 0x44, 0x13, 0x7f, 0xf7, 0x7c, 0xd9, 0xf6, 0x74, 0x36, 0xaf, 0xd4, 0x89, 0xe5, - 0x95, 0x09, 0x78, 0x38, 0xda, 0x27, 0x5c, 0x10, 0x0e, 0x12, 0x59, 0xa9, 0x3d, 0xf4, 0xb9, 0xa8, 0x1b, 0xe7, 0x17, - 0x6d, 0xd6, 0x3c, 0x59, 0xad, 0xf2, 0xcb, 0x36, 0x6b, 0x9f, 0xda, 0x07, 0xdf, 0x22, 0x95, 0x01, 0xcd, 0xe5, 0x63, - 0x9e, 0x45, 0xa0, 0x9d, 0x1d, 0x67, 0x26, 0x9c, 0x82, 0x0f, 0x51, 0x4c, 0x16, 0xba, 0xea, 0x4b, 0x82, 0x71, 0x29, - 0xb1, 0x7a, 0xfc, 0x02, 0xf5, 0xda, 0xe9, 0xb6, 0xab, 0x74, 0xb3, 0x7d, 0x18, 0x5c, 0xb8, 0x14, 0x08, 0x77, 0x20, - 0xe4, 0x01, 0xe8, 0x77, 0x97, 0x02, 0x4c, 0x83, 0x00, 0x95, 0x15, 0x88, 0xb4, 0x7c, 0xb6, 0x98, 0x3d, 0x2b, 0xa8, - 0x59, 0x86, 0x27, 0x7c, 0xc2, 0xb5, 0x4a, 0x29, 0x48, 0xb7, 0xbb, 0xd2, 0xd7, 0xbb, 0x25, 0xa8, 0xac, 0x16, 0xf9, - 0x35, 0xd1, 0x3c, 0xfb, 0xac, 0xdc, 0xc2, 0x21, 0x6c, 0x56, 0x56, 0xe0, 0x0c, 0xad, 0x71, 0x2e, 0x27, 0xb4, 0xe0, - 0x7a, 0x3a, 0xfb, 0xb7, 0x56, 0x87, 0xf5, 0xf5, 0xc0, 0x5c, 0x58, 0x01, 0x48, 0xa8, 0x18, 0xad, 0x56, 0xfc, 0xe8, - 0xfb, 0xf7, 0x49, 0xde, 0x27, 0xbc, 0x8d, 0x3b, 0xf8, 0x18, 0x9f, 0xe2, 0x76, 0x0b, 0xb7, 0x4f, 0xe1, 0xea, 0x3e, - 0xcb, 0x17, 0x23, 0xa6, 0x62, 0x78, 0xf9, 0x4b, 0x5f, 0x26, 0xe7, 0x87, 0x65, 0xbc, 0x7b, 0x5d, 0x24, 0x0e, 0x5d, - 0x82, 0xb0, 0xeb, 0x2e, 0x5e, 0x5d, 0x14, 0x85, 0xc1, 0xd2, 0xc6, 0xa1, 0xea, 0xa4, 0xd4, 0x2f, 0x5c, 0x1e, 0xf7, - 0xc0, 0x9e, 0xdb, 0xae, 0x6c, 0x13, 0xcc, 0xbe, 0xed, 0xcf, 0xb4, 0xfa, 0xd9, 0xd4, 0x25, 0x62, 0x78, 0xe8, 0x55, - 0xe8, 0x81, 0x2e, 0x49, 0xfb, 0xe0, 0x00, 0xac, 0x8e, 0x82, 0xd9, 0x70, 0x1b, 0xfd, 0x80, 0x37, 0x6b, 0x69, 0x10, - 0xac, 0x00, 0x8c, 0x3b, 0xdf, 0x70, 0xb2, 0xb4, 0xb0, 0xd5, 0x40, 0x85, 0x75, 0x11, 0x46, 0x74, 0x0b, 0x49, 0x85, - 0x11, 0xa2, 0xe1, 0x08, 0x73, 0x91, 0x4e, 0xf6, 0x5b, 0x58, 0x8e, 0xc7, 0x8a, 0x69, 0x38, 0x3a, 0x0a, 0xf6, 0x85, - 0x15, 0xca, 0x9c, 0x22, 0x43, 0x36, 0xe1, 0xe2, 0xa1, 0xfe, 0xc4, 0x0a, 0x69, 0x3e, 0x8d, 0x06, 0x23, 0x8d, 0xcc, - 0x2a, 0x46, 0x38, 0xcb, 0xf9, 0x1c, 0xaa, 0x4e, 0x0a, 0x70, 0xfa, 0x81, 0xbf, 0x7c, 0x94, 0x86, 0x6d, 0x02, 0xf9, - 0xfa, 0x60, 0x83, 0xd9, 0xe0, 0x51, 0x41, 0x6f, 0x5e, 0x8b, 0xc7, 0xb0, 0xa3, 0x1e, 0x16, 0x8c, 0x42, 0x36, 0x24, - 0xbd, 0x83, 0xa6, 0xe0, 0x03, 0xda, 0x7c, 0x69, 0x00, 0x97, 0x9e, 0x9b, 0x0f, 0x5b, 0xd1, 0x47, 0x0d, 0x4c, 0xca, - 0xb6, 0x4c, 0xa6, 0x39, 0xa5, 0xab, 0x4c, 0x1b, 0x97, 0xa9, 0x9c, 0xc2, 0x1a, 0xbb, 0xa8, 0x27, 0xe1, 0x60, 0x46, - 0x54, 0x4d, 0xd3, 0xfe, 0xc0, 0xfc, 0x7d, 0x6d, 0x4b, 0xb6, 0xb0, 0x0b, 0xb5, 0xb3, 0xc6, 0xe6, 0xc9, 0xce, 0xa0, - 0x7c, 0x1b, 0xc3, 0x3d, 0x2c, 0xbc, 0x1b, 0x59, 0x23, 0x9f, 0x27, 0x9e, 0x6c, 0x9e, 0xac, 0xd7, 0x66, 0x20, 0x2a, - 0x05, 0x3d, 0xd0, 0x5b, 0xbf, 0x6d, 0x5a, 0xb0, 0x3d, 0xca, 0xaf, 0xd3, 0x16, 0x9e, 0x71, 0x78, 0x06, 0xd3, 0xb7, - 0x77, 0xa5, 0x0b, 0xf9, 0xd9, 0x81, 0xa4, 0x15, 0xa4, 0xd8, 0xe9, 0x04, 0x9d, 0x1d, 0xe3, 0x60, 0xe4, 0x40, 0xcf, - 0xaf, 0x3e, 0x5b, 0x58, 0xfb, 0xdf, 0x6f, 0xca, 0x82, 0x39, 0x1d, 0xb2, 0xbc, 0x9c, 0x50, 0xe6, 0xcf, 0xcf, 0x37, - 0x3c, 0xa9, 0x50, 0xc1, 0xbd, 0x1f, 0x05, 0x7b, 0xda, 0x86, 0x98, 0x9c, 0xd1, 0xbf, 0xed, 0x0f, 0x1b, 0x11, 0xa8, - 0xd4, 0xb2, 0x65, 0x85, 0x54, 0xea, 0xa1, 0x4d, 0xb3, 0x47, 0x0f, 0x1c, 0x91, 0x2f, 0xa1, 0x0b, 0xe0, 0xf5, 0x47, - 0x85, 0x9c, 0x1b, 0x44, 0x70, 0xbf, 0xdd, 0xb8, 0x8d, 0xaf, 0x00, 0x78, 0x3b, 0xec, 0x55, 0xff, 0xb4, 0x80, 0xfd, - 0x8d, 0xca, 0x92, 0x7e, 0xbc, 0x1d, 0x7b, 0xfc, 0x17, 0x12, 0xe2, 0x95, 0x5b, 0x3c, 0x4c, 0x1c, 0x3a, 0x95, 0xac, - 0x59, 0xf9, 0x73, 0xab, 0x24, 0x60, 0x58, 0xbd, 0x60, 0xc8, 0xc6, 0x6d, 0x15, 0xb7, 0x99, 0xff, 0x41, 0x05, 0x83, - 0x05, 0xdf, 0x1a, 0x49, 0xc5, 0xb2, 0xf8, 0xed, 0x53, 0xe7, 0xbf, 0xea, 0x1c, 0xd7, 0xbe, 0xae, 0xbd, 0x51, 0x39, - 0x34, 0xf1, 0x81, 0x23, 0x74, 0x70, 0xb0, 0x91, 0x41, 0xc7, 0x00, 0x78, 0xe4, 0xd8, 0x2f, 0xbf, 0x7c, 0x9e, 0x1d, - 0x33, 0x9a, 0xc7, 0x22, 0x0a, 0x99, 0x3b, 0xcf, 0xcd, 0xd9, 0x89, 0x3c, 0xa1, 0x6a, 0xea, 0x0b, 0x03, 0x1c, 0x1f, - 0x6d, 0xa5, 0x02, 0xbe, 0x47, 0xeb, 0x1d, 0x13, 0xd8, 0xe0, 0xb7, 0xec, 0xa4, 0x76, 0x15, 0xf4, 0x0b, 0xb4, 0xdc, - 0xc5, 0x54, 0x6e, 0x2c, 0x70, 0xb4, 0x39, 0x91, 0x9d, 0x43, 0xdf, 0xa8, 0x53, 0xb2, 0x1e, 0x4f, 0x76, 0x1b, 0x7d, - 0x49, 0xb1, 0x2b, 0xb9, 0xa2, 0x6d, 0x43, 0x56, 0xbd, 0x53, 0xab, 0x2b, 0x53, 0xa7, 0xea, 0x9a, 0xb7, 0xb2, 0xb4, - 0x29, 0xed, 0x92, 0xec, 0xdd, 0x16, 0x0b, 0xaf, 0xc2, 0x1b, 0x8d, 0xf2, 0x22, 0x14, 0xec, 0xb1, 0xc4, 0xa0, 0xcb, - 0x09, 0x5c, 0x2f, 0xac, 0x56, 0x31, 0xfc, 0xd9, 0x35, 0x86, 0x5d, 0xa6, 0x4b, 0x1f, 0xf8, 0x06, 0xbf, 0x12, 0x84, - 0xca, 0x75, 0x76, 0x90, 0x60, 0xdd, 0xe5, 0x06, 0x0d, 0xc7, 0x89, 0xff, 0x82, 0x87, 0x9a, 0xb5, 0x77, 0x39, 0x98, - 0x64, 0xdf, 0x78, 0xdc, 0xad, 0x64, 0x2d, 0x6b, 0x71, 0xd6, 0x37, 0x24, 0x18, 0x62, 0x37, 0xa5, 0x73, 0xdc, 0x4a, - 0xda, 0x28, 0x72, 0xc5, 0x2a, 0xf4, 0xff, 0x56, 0x91, 0xcc, 0x66, 0xfe, 0xd7, 0xd9, 0xd9, 0x99, 0x4b, 0x71, 0x36, - 0x7f, 0xca, 0x78, 0xc0, 0x99, 0x04, 0xf6, 0x85, 0x67, 0xcc, 0xe8, 0x90, 0xdf, 0xc2, 0x50, 0x88, 0x20, 0x97, 0xc2, - 0xb1, 0x4b, 0xf0, 0xce, 0x20, 0x50, 0x1e, 0x60, 0xff, 0x9e, 0x6c, 0x94, 0xf3, 0x0f, 0x15, 0xf9, 0x40, 0xbe, 0x65, - 0x83, 0xec, 0x8b, 0xf9, 0xec, 0x5b, 0x33, 0x19, 0x88, 0xcd, 0x1f, 0x61, 0xfb, 0xdb, 0xb0, 0xb4, 0xce, 0x52, 0x06, - 0x47, 0x5a, 0x2e, 0xb2, 0xa9, 0xd5, 0xfc, 0xbb, 0x0f, 0x53, 0xd6, 0x3d, 0x72, 0x03, 0x41, 0xb9, 0xc8, 0xd2, 0xc5, - 0xa3, 0x8c, 0x7e, 0x2c, 0x43, 0x4f, 0xee, 0xbd, 0x62, 0x0b, 0xf6, 0x23, 0xde, 0xab, 0x52, 0xe0, 0xe3, 0x61, 0xc1, - 0x69, 0xfe, 0x23, 0xde, 0xab, 0x42, 0x50, 0x82, 0x2b, 0xa4, 0x89, 0xe2, 0x88, 0xcd, 0x83, 0xce, 0x69, 0x24, 0x80, - 0x82, 0xe6, 0x91, 0x39, 0xc8, 0x9e, 0xbb, 0xa8, 0x85, 0x49, 0x07, 0xbb, 0xb8, 0x5f, 0x36, 0x16, 0xa9, 0x0d, 0xe1, - 0x0d, 0x91, 0xdc, 0xca, 0xd9, 0x98, 0xaf, 0x47, 0x1b, 0x0b, 0x62, 0x94, 0xc9, 0xe4, 0xf2, 0x39, 0x8f, 0xb7, 0x16, - 0x0b, 0x85, 0xd5, 0x82, 0x05, 0xaa, 0x55, 0xa9, 0xd2, 0xc3, 0xe2, 0xdb, 0x05, 0xb3, 0xa0, 0x88, 0xd9, 0x7a, 0x0f, - 0x6f, 0xb9, 0x22, 0x20, 0x25, 0xbb, 0x24, 0x78, 0x93, 0xdb, 0x60, 0xaa, 0x7f, 0x82, 0x1d, 0x08, 0x3d, 0x53, 0x3a, - 0xc2, 0x26, 0x4f, 0x41, 0x24, 0xb1, 0xfd, 0x16, 0x76, 0xac, 0xd1, 0x0b, 0xe1, 0x85, 0x14, 0x38, 0x57, 0x4d, 0x13, - 0x33, 0xca, 0x4d, 0x74, 0xb1, 0x87, 0x6a, 0xce, 0x32, 0x6d, 0x11, 0x60, 0xdf, 0xa1, 0xa1, 0x14, 0xcf, 0x0d, 0x28, - 0xcc, 0x63, 0xd2, 0x2e, 0xe5, 0x31, 0x2c, 0x5e, 0x90, 0x02, 0x44, 0x8d, 0x8b, 0x49, 0x59, 0x67, 0x9e, 0x2f, 0x26, - 0x5c, 0x54, 0xc8, 0x50, 0x30, 0x35, 0x97, 0x02, 0xde, 0x72, 0x28, 0x8b, 0x18, 0x3a, 0x54, 0xc3, 0x77, 0x4b, 0xc2, - 0xca, 0x3a, 0xe6, 0x98, 0xe2, 0xa2, 0xaa, 0x01, 0xcc, 0xc5, 0xc3, 0xf0, 0xd1, 0x77, 0xf5, 0x5a, 0xbc, 0x93, 0xf3, - 0x2a, 0xdf, 0xd3, 0x38, 0x1f, 0x32, 0xdd, 0xd9, 0x0d, 0xa3, 0xb5, 0x79, 0x6e, 0x29, 0xd8, 0xbe, 0x1f, 0x78, 0xf5, - 0x04, 0xd9, 0xda, 0x3c, 0xd8, 0x54, 0x66, 0x0d, 0x59, 0xf9, 0x3a, 0x41, 0xd5, 0x5e, 0xbd, 0xaa, 0x14, 0xb6, 0x22, - 0x40, 0xa5, 0xe0, 0xa3, 0xad, 0xfc, 0x27, 0xda, 0xe6, 0xdb, 0x73, 0xa8, 0x0c, 0x0f, 0xe4, 0xc9, 0x50, 0xd5, 0x03, - 0x2e, 0xca, 0x0f, 0x01, 0x2c, 0x7e, 0x64, 0x22, 0xd7, 0xee, 0xba, 0x40, 0xe6, 0x4c, 0xc5, 0x12, 0x2f, 0xfb, 0x74, - 0x90, 0x5a, 0x79, 0x28, 0x95, 0x60, 0xdb, 0x73, 0x53, 0x70, 0xed, 0x43, 0xe4, 0xe2, 0x3e, 0x1b, 0xa4, 0xcb, 0x7a, - 0x18, 0x5d, 0x1b, 0xc8, 0xd7, 0x9b, 0x73, 0x9a, 0xb8, 0xb3, 0x74, 0x80, 0x73, 0x02, 0xb6, 0xc7, 0x9e, 0x3d, 0x7d, - 0x13, 0x67, 0xa8, 0x57, 0xe7, 0xf0, 0x97, 0x6b, 0x9c, 0xe3, 0x0c, 0xa5, 0x0f, 0x63, 0xb8, 0xc0, 0x5a, 0x63, 0x00, - 0x5f, 0x66, 0x49, 0x15, 0x78, 0xa4, 0x66, 0x46, 0x62, 0x75, 0x17, 0x81, 0x68, 0xa9, 0xc3, 0xdb, 0x71, 0xe6, 0x03, - 0x51, 0x1b, 0xee, 0xf5, 0x99, 0x11, 0x0e, 0x27, 0x59, 0x5c, 0x3b, 0x67, 0x38, 0xb9, 0xdc, 0xe7, 0xb5, 0x13, 0x13, - 0xac, 0xbd, 0xc3, 0x53, 0x05, 0xf4, 0x68, 0x70, 0xaa, 0x58, 0x1a, 0x02, 0x31, 0x13, 0xc0, 0x9b, 0x39, 0x3c, 0xda, - 0x02, 0x9c, 0x8f, 0xd6, 0x38, 0xf8, 0x4a, 0x6b, 0x5d, 0x6d, 0x2a, 0x51, 0xd6, 0x6b, 0xdc, 0x9f, 0x66, 0x78, 0x94, - 0xe1, 0x79, 0x36, 0x08, 0x8e, 0x9b, 0x59, 0x16, 0x9a, 0x74, 0xad, 0x56, 0x4f, 0x9d, 0x19, 0x21, 0xb2, 0x3f, 0x2d, - 0xfd, 0x41, 0x3d, 0x40, 0xf8, 0x14, 0xb2, 0x80, 0x96, 0xf4, 0xdc, 0xdf, 0x86, 0x7d, 0xa7, 0x1a, 0x35, 0x62, 0x9e, - 0x58, 0x32, 0xd2, 0xf3, 0x3f, 0xca, 0x2c, 0xdb, 0x5a, 0x23, 0x9a, 0xdf, 0xee, 0x45, 0x0d, 0xdf, 0x5e, 0xa0, 0x65, - 0x2b, 0xcd, 0x76, 0x00, 0x51, 0xac, 0x71, 0x92, 0x0e, 0xd6, 0x48, 0xae, 0x56, 0xb1, 0x4d, 0x21, 0x3c, 0x99, 0x31, - 0xaa, 0x16, 0x85, 0x79, 0xba, 0x2d, 0x56, 0x28, 0x31, 0xfc, 0x2e, 0x76, 0x36, 0xa2, 0xf0, 0x52, 0x9a, 0x04, 0xc3, - 0x8d, 0x58, 0x10, 0x59, 0x13, 0xb9, 0x87, 0x59, 0x65, 0x19, 0x24, 0x88, 0x30, 0x22, 0xbf, 0xbd, 0x2e, 0x15, 0xf6, - 0x71, 0x38, 0xfb, 0xc7, 0xf8, 0x02, 0xc2, 0xcd, 0xdb, 0x84, 0x16, 0x43, 0x3a, 0x01, 0x36, 0x16, 0xe2, 0x10, 0x6e, - 0x25, 0xac, 0x56, 0xfd, 0x41, 0x57, 0x18, 0xf2, 0xec, 0x9e, 0xae, 0x2b, 0x1b, 0xda, 0xdd, 0x00, 0x5c, 0x75, 0x5b, - 0x6a, 0xae, 0x8d, 0xee, 0x87, 0x9a, 0xd7, 0xb5, 0xb8, 0x4b, 0x72, 0x0f, 0x64, 0x54, 0x6f, 0x60, 0xd7, 0x2c, 0xc0, - 0x4d, 0xe8, 0x2a, 0x3c, 0xc2, 0x0b, 0x6b, 0xc3, 0x69, 0x9e, 0x52, 0xa2, 0xe6, 0x05, 0x25, 0x78, 0xb8, 0x99, 0xb0, - 0x7e, 0x36, 0xc0, 0x23, 0x1f, 0x68, 0x7b, 0xff, 0x6d, 0x3c, 0x42, 0xa8, 0x20, 0x06, 0xa6, 0xd6, 0x65, 0x7b, 0x54, - 0xd9, 0xed, 0x9b, 0x4c, 0xc3, 0x30, 0x18, 0x23, 0xe6, 0x51, 0x68, 0xc4, 0x9c, 0x37, 0x1a, 0x68, 0x41, 0x46, 0x60, - 0xc4, 0xbc, 0x08, 0x5a, 0x5b, 0xd8, 0x67, 0x36, 0x83, 0xf6, 0x16, 0x08, 0x75, 0x39, 0xd0, 0x34, 0x0d, 0x0f, 0x6a, - 0x54, 0x0f, 0x9a, 0xfb, 0xe7, 0x9d, 0x8e, 0x3a, 0xa0, 0x48, 0x18, 0x5f, 0xfa, 0x49, 0x58, 0xd7, 0x70, 0x3b, 0xee, - 0xb1, 0x19, 0xb7, 0xb3, 0x6d, 0x50, 0x7d, 0xd9, 0xcf, 0x06, 0x83, 0xae, 0xf4, 0x56, 0x12, 0x2d, 0x3c, 0xae, 0x9e, - 0xe0, 0xa8, 0x16, 0xef, 0x8b, 0xde, 0xbc, 0xf2, 0xe6, 0xfe, 0x65, 0xcf, 0xcd, 0xf3, 0x18, 0x38, 0xa0, 0x7d, 0xb8, - 0x1f, 0xaa, 0xe2, 0x83, 0x1d, 0x75, 0x20, 0x0a, 0x5a, 0xda, 0xaa, 0x09, 0xa4, 0xd6, 0xcc, 0x2e, 0xd6, 0x4d, 0x85, - 0x0e, 0x05, 0x84, 0x21, 0x53, 0x55, 0x77, 0x77, 0x2a, 0x50, 0x0d, 0x71, 0x38, 0xf5, 0x1f, 0x5b, 0x23, 0xd6, 0x38, - 0xea, 0x8c, 0x22, 0x63, 0x24, 0x69, 0x97, 0x0f, 0x5e, 0xdd, 0x01, 0x2b, 0x01, 0x1f, 0xfd, 0xd8, 0x24, 0x19, 0x43, - 0x82, 0xb7, 0x2c, 0xd3, 0x86, 0x0f, 0xe1, 0x0e, 0x41, 0x79, 0x62, 0x63, 0x6d, 0xba, 0x4a, 0x16, 0x72, 0x55, 0x97, - 0xd7, 0x01, 0x7a, 0xde, 0x95, 0xbf, 0xb1, 0xe1, 0xc8, 0x82, 0x81, 0x65, 0x5b, 0xfb, 0x04, 0x3c, 0xf2, 0x71, 0x85, - 0x20, 0x7e, 0x29, 0x74, 0x62, 0x22, 0x45, 0x5f, 0xc1, 0x06, 0xc5, 0x73, 0x70, 0x10, 0x74, 0x12, 0x1c, 0x06, 0xef, - 0x32, 0xab, 0x49, 0x36, 0xb8, 0x35, 0x23, 0xf1, 0x7c, 0xb5, 0x6a, 0xa1, 0xc3, 0x7f, 0xcc, 0x63, 0xc8, 0xe3, 0x52, - 0xe1, 0x3e, 0xae, 0x14, 0xee, 0x60, 0x09, 0x48, 0xc6, 0x81, 0xae, 0x1d, 0xcb, 0x50, 0x8d, 0x0e, 0x71, 0xba, 0x5f, - 0x40, 0xd4, 0x66, 0x77, 0x2c, 0x81, 0x9e, 0x7d, 0xab, 0x80, 0xd5, 0xb5, 0x97, 0x25, 0x90, 0x11, 0xdc, 0xfd, 0x26, - 0x30, 0x2a, 0x44, 0xe3, 0xf3, 0x67, 0xde, 0x53, 0xe0, 0x89, 0xf3, 0xe7, 0x9a, 0x19, 0xd6, 0xbd, 0xa0, 0x37, 0xa6, - 0xf9, 0x78, 0x8c, 0x9b, 0x63, 0x0b, 0xce, 0xa3, 0x0e, 0xfc, 0xb4, 0x10, 0x3d, 0xea, 0x60, 0x97, 0x8a, 0xc7, 0x25, - 0x90, 0x43, 0xf4, 0x74, 0x06, 0x52, 0xc0, 0x4a, 0xc7, 0x56, 0x8b, 0x34, 0x41, 0xab, 0xd5, 0xe4, 0x82, 0xb4, 0x10, - 0x5a, 0xaa, 0x1b, 0xae, 0xb3, 0x29, 0xf8, 0x48, 0x83, 0x62, 0xe0, 0x0d, 0xd5, 0xd3, 0x18, 0xe1, 0x31, 0x5a, 0x8e, - 0xd8, 0x98, 0x2e, 0x72, 0x9d, 0xaa, 0x1e, 0x4f, 0x6c, 0x28, 0x5b, 0x66, 0x23, 0xc1, 0x1d, 0x75, 0xf0, 0xc4, 0xf0, - 0x97, 0x8f, 0x8c, 0x39, 0x48, 0x91, 0x99, 0xe4, 0x89, 0x49, 0xc0, 0x3c, 0xc9, 0x72, 0xa9, 0x98, 0x6d, 0xa6, 0x6b, - 0x6d, 0xcb, 0x21, 0x18, 0x76, 0xa4, 0x0b, 0x6e, 0xac, 0x28, 0xa3, 0x74, 0x4a, 0x54, 0x4f, 0x1d, 0x75, 0xd2, 0x09, - 0xe6, 0x09, 0x70, 0x7a, 0xef, 0x64, 0xcc, 0x1a, 0xe5, 0xad, 0xe8, 0x0c, 0x1d, 0x4e, 0xb1, 0xa8, 0x2e, 0x51, 0x67, - 0xe8, 0x70, 0x82, 0xf0, 0xac, 0x41, 0x72, 0x05, 0x1e, 0xc3, 0x5c, 0xfc, 0x1f, 0x29, 0xff, 0xcd, 0x61, 0x43, 0xd0, - 0xe5, 0xb7, 0xb0, 0x53, 0xd8, 0x28, 0x4a, 0x73, 0x02, 0x5e, 0x8b, 0xed, 0x33, 0x9c, 0x91, 0x49, 0x33, 0xf7, 0x01, - 0xf7, 0x4c, 0x2b, 0x8d, 0x5b, 0x8d, 0x0e, 0x33, 0x3c, 0xda, 0x4c, 0x8a, 0xcd, 0x5c, 0x9b, 0x79, 0x9a, 0xc1, 0xf9, - 0x5e, 0x8d, 0xc2, 0x95, 0x5f, 0x6c, 0x26, 0x85, 0xe5, 0x1d, 0x70, 0x9b, 0x23, 0x2c, 0x9a, 0x14, 0xe7, 0x78, 0xd6, - 0xfc, 0x8a, 0x67, 0xcd, 0x0f, 0x65, 0x46, 0x63, 0x81, 0x05, 0x04, 0xef, 0x83, 0x44, 0x3c, 0xab, 0x92, 0x47, 0x58, - 0x34, 0x4c, 0x79, 0x3c, 0x6b, 0x54, 0xa5, 0x9b, 0x0b, 0x2c, 0x1a, 0xa6, 0x74, 0xe3, 0x03, 0x9e, 0x35, 0xbe, 0xfe, - 0x8b, 0x49, 0x47, 0x29, 0xa0, 0xcb, 0x1c, 0x2d, 0x33, 0x3b, 0xc4, 0xab, 0xdf, 0xde, 0xbe, 0x6b, 0x5f, 0x77, 0x0e, - 0x27, 0xd8, 0xaf, 0x5f, 0x66, 0x70, 0x2c, 0xd3, 0x31, 0x6b, 0x02, 0x44, 0x33, 0xdc, 0x39, 0x9c, 0xe2, 0xce, 0x61, - 0xe6, 0x9a, 0x5a, 0xcf, 0x1a, 0xe4, 0x56, 0x87, 0x50, 0xd4, 0x51, 0x1a, 0xc2, 0xc7, 0x4f, 0x36, 0x9d, 0xa0, 0x1a, - 0x28, 0xd1, 0xe1, 0xa4, 0x06, 0x2a, 0xf8, 0x5e, 0xd4, 0xbe, 0xab, 0x7a, 0x15, 0x06, 0x59, 0x28, 0xa1, 0x70, 0xcd, - 0x0d, 0x78, 0x6a, 0x29, 0x06, 0x32, 0x61, 0x8a, 0x05, 0xca, 0x77, 0x40, 0x61, 0x94, 0x27, 0x66, 0xe8, 0xc1, 0x74, - 0x4c, 0xe2, 0xff, 0xcf, 0x93, 0x29, 0x87, 0x5e, 0x6e, 0x99, 0xad, 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, - 0x3f, 0xac, 0xa0, 0xfb, 0x62, 0xab, 0xfb, 0xc2, 0x74, 0x1f, 0x36, 0x6d, 0x54, 0x39, 0x69, 0x55, 0xc9, 0x92, 0xff, - 0x3a, 0xdd, 0xda, 0x02, 0x8d, 0xa8, 0xd1, 0xb3, 0x49, 0xd8, 0xe0, 0x7e, 0x3b, 0xdd, 0x81, 0xcc, 0x6b, 0x6e, 0xdf, - 0xe6, 0x84, 0xc3, 0x37, 0xb8, 0x53, 0xbd, 0x6c, 0x81, 0xf7, 0xa6, 0x32, 0xfa, 0xca, 0x38, 0xb4, 0x1c, 0x2c, 0x36, - 0x4d, 0xb9, 0x8d, 0xb1, 0x74, 0x72, 0x8a, 0x8d, 0x2b, 0x22, 0x54, 0xba, 0xbd, 0x04, 0xa5, 0xf8, 0x58, 0x37, 0x99, - 0xf9, 0xba, 0xd0, 0x89, 0xb9, 0x84, 0x6a, 0x98, 0xcf, 0xbb, 0x4b, 0x9d, 0x68, 0x39, 0xb7, 0x79, 0x77, 0x17, 0xd0, - 0x27, 0x68, 0x58, 0x1b, 0x81, 0xdd, 0x3e, 0x2b, 0x9c, 0x7e, 0xa7, 0x3a, 0x04, 0xc3, 0x03, 0xc8, 0x91, 0x16, 0xdb, - 0x07, 0x36, 0xad, 0x61, 0xd7, 0x45, 0xb3, 0x4c, 0xb4, 0xad, 0x36, 0x4d, 0xae, 0xdd, 0xc3, 0x7c, 0x1e, 0xf2, 0x14, - 0xbc, 0xb0, 0xfa, 0xf1, 0x1d, 0xec, 0xc6, 0x6d, 0x8d, 0x91, 0xa8, 0x2b, 0x99, 0x4a, 0xe8, 0x27, 0xb7, 0x98, 0x25, - 0x77, 0xc6, 0x8b, 0x51, 0x19, 0x7f, 0x1f, 0x13, 0xa9, 0x3e, 0xaa, 0x24, 0x39, 0xb0, 0xec, 0x6f, 0xb0, 0xe4, 0x16, - 0xcc, 0x13, 0xcb, 0x6a, 0x12, 0xeb, 0xe4, 0x2e, 0x58, 0x44, 0x69, 0x1a, 0x59, 0x1b, 0x06, 0xd4, 0x34, 0x63, 0xd5, - 0x83, 0xfb, 0x10, 0xe8, 0xa1, 0x57, 0x96, 0xd2, 0xae, 0xb3, 0xb4, 0xd6, 0xbd, 0x36, 0xdd, 0x6f, 0x0e, 0x28, 0xe0, - 0x0b, 0x03, 0xae, 0xe9, 0x5f, 0x4d, 0x22, 0x19, 0xb2, 0xaf, 0x9c, 0x15, 0x8f, 0x17, 0x85, 0xc1, 0x34, 0xd1, 0xd3, - 0x49, 0x36, 0x6f, 0x83, 0xa9, 0x5e, 0x36, 0xef, 0xdc, 0x62, 0xf7, 0x7d, 0x67, 0xbf, 0xef, 0xb0, 0xe8, 0x31, 0x93, - 0x91, 0x32, 0x53, 0xcc, 0x7f, 0xdf, 0xd9, 0xef, 0x3b, 0xbc, 0x3d, 0x98, 0x1b, 0x7f, 0xa1, 0x58, 0xb2, 0x33, 0x5c, - 0x82, 0x09, 0x79, 0xc0, 0xdd, 0xd4, 0xb2, 0x4c, 0x10, 0xd8, 0x5a, 0x02, 0xc4, 0xf9, 0x7c, 0x1a, 0x57, 0xbc, 0x1a, - 0x02, 0xee, 0xd3, 0xbb, 0xb6, 0x57, 0xa9, 0xc0, 0x63, 0x82, 0x46, 0xc4, 0xc4, 0xb6, 0x31, 0xef, 0x6a, 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, 0x79, 0x13, 0x79, 0xec, 0x0b, 0xb3, 0x9f, - 0x99, 0x9e, 0x16, 0x72, 0x31, 0x99, 0x82, 0x0f, 0x2d, 0xb0, 0x0c, 0x85, 0xa9, 0x57, 0xd9, 0xfa, 0xd7, 0x24, 0x37, - 0x01, 0x14, 0x4e, 0x37, 0x65, 0x42, 0x33, 0xbd, 0xa0, 0xb9, 0xb1, 0x24, 0xe5, 0x62, 0xf2, 0x48, 0xde, 0xbe, 0x04, - 0xec, 0xa6, 0x44, 0x37, 0x76, 0xe4, 0xbd, 0x85, 0x1d, 0x80, 0x33, 0xc2, 0x76, 0x55, 0x7c, 0xa8, 0x40, 0xe7, 0x8f, - 0x73, 0xc2, 0x76, 0x55, 0x7d, 0xc2, 0x6c, 0xf6, 0x94, 0x6c, 0x0c, 0xb7, 0x17, 0x67, 0x8d, 0x1c, 0x1d, 0x75, 0xd2, - 0xbc, 0xeb, 0x89, 0x81, 0x05, 0x68, 0x00, 0xdc, 0xad, 0xed, 0x59, 0xde, 0xdd, 0x10, 0xd0, 0xbb, 0x64, 0xd2, 0x5e, - 0x97, 0x9b, 0x94, 0xd5, 0xaa, 0x53, 0x51, 0xc1, 0x02, 0x4f, 0x83, 0xbd, 0x40, 0xed, 0xd7, 0x0e, 0x8a, 0x73, 0x95, - 0x6d, 0x9a, 0x9e, 0x97, 0x7d, 0x77, 0x77, 0x2c, 0x32, 0xb6, 0x69, 0x6f, 0x77, 0x10, 0x09, 0xcb, 0x09, 0xeb, 0x80, - 0x13, 0xae, 0x6a, 0x07, 0x04, 0xe8, 0x3a, 0x10, 0xb9, 0xb1, 0x24, 0xcb, 0x75, 0x65, 0x74, 0x1f, 0xf8, 0xdd, 0x52, - 0x22, 0xdd, 0x68, 0x4b, 0x82, 0xe9, 0x13, 0x8c, 0x9a, 0xce, 0x3c, 0x8a, 0x5c, 0x7b, 0xef, 0x77, 0x53, 0xb4, 0xf5, - 0xaf, 0x0f, 0x63, 0xb3, 0x3d, 0x4c, 0x0c, 0x65, 0x10, 0x03, 0xbd, 0x8f, 0x78, 0xb7, 0xd1, 0xc8, 0x10, 0x28, 0x64, - 0xb2, 0x01, 0x96, 0x89, 0xd7, 0xa2, 0x1f, 0x1c, 0x18, 0x78, 0x54, 0x09, 0x08, 0x53, 0x10, 0x42, 0xc2, 0xae, 0x0d, - 0xc2, 0x86, 0xcb, 0x55, 0xcb, 0x85, 0x8d, 0x54, 0x1b, 0x3a, 0xf8, 0x7f, 0x85, 0xcb, 0x56, 0xcf, 0x2c, 0x17, 0xc5, - 0xe0, 0x66, 0x6e, 0xc0, 0x22, 0x41, 0x7a, 0xb4, 0xd9, 0x1e, 0x8a, 0xbb, 0x73, 0xb1, 0xd9, 0x10, 0x90, 0x98, 0xc3, - 0x04, 0x45, 0xc3, 0xb9, 0x31, 0xc6, 0x2a, 0xa9, 0xb4, 0xac, 0x35, 0x89, 0x39, 0xf0, 0xa5, 0x0b, 0xd7, 0x7d, 0x79, - 0x9b, 0x32, 0x7c, 0x97, 0x0a, 0x7c, 0x03, 0x9e, 0x34, 0xa9, 0xc4, 0xee, 0xf1, 0x82, 0x62, 0x4d, 0x74, 0xd7, 0xb3, - 0xb7, 0x05, 0xac, 0xb3, 0xd9, 0x23, 0x22, 0xf8, 0x5d, 0xfd, 0x6a, 0x83, 0xef, 0x16, 0xfe, 0x0a, 0xd6, 0xcf, 0xc1, - 0x49, 0x8a, 0x45, 0x43, 0x36, 0x0b, 0x77, 0x64, 0x40, 0xb9, 0x8a, 0x5f, 0x0e, 0x53, 0xb7, 0x8a, 0xe1, 0xda, 0xc7, - 0x57, 0xfc, 0x61, 0xa3, 0xdd, 0x86, 0x2a, 0x8b, 0xdb, 0xbd, 0x29, 0x1a, 0xb2, 0x6a, 0x7a, 0x47, 0xe6, 0x46, 0x4a, - 0xfd, 0xeb, 0x03, 0x6e, 0x6d, 0xb5, 0xef, 0xa7, 0xf9, 0xd6, 0xa3, 0x73, 0xd5, 0xb4, 0x4f, 0xad, 0x15, 0xc1, 0xc1, - 0xcf, 0x16, 0x6e, 0x6e, 0x0d, 0x38, 0x80, 0x9f, 0xbf, 0xa3, 0x79, 0x9c, 0x41, 0x74, 0x7a, 0xab, 0x19, 0x5f, 0xc5, - 0x7f, 0x8e, 0x1a, 0x71, 0x2f, 0xfd, 0x33, 0xf9, 0x73, 0xd4, 0x40, 0x3d, 0x14, 0xcf, 0x6f, 0x57, 0x6c, 0xb6, 0x82, - 0x60, 0x6b, 0xf7, 0x8e, 0xf0, 0xeb, 0xb0, 0x24, 0xd7, 0x34, 0xe7, 0xd9, 0xca, 0x3d, 0x45, 0xb7, 0x72, 0xef, 0xf4, - 0xac, 0xcc, 0xeb, 0x4a, 0xab, 0x58, 0x0e, 0x73, 0x08, 0x2c, 0x1c, 0xef, 0x35, 0x7b, 0xfd, 0x56, 0xf3, 0xc1, 0xc0, - 0xfe, 0x6b, 0x22, 0xdc, 0xa3, 0x5a, 0xc4, 0xb6, 0x37, 0x1b, 0x5b, 0x3f, 0x06, 0xc3, 0x0e, 0x08, 0x05, 0x0e, 0x72, - 0xe9, 0xe3, 0x0c, 0x59, 0xdf, 0x93, 0xd5, 0x8a, 0xb9, 0x68, 0xd6, 0x4e, 0x83, 0x5f, 0xc6, 0x66, 0x3a, 0x6c, 0x27, - 0x9d, 0xae, 0x17, 0x63, 0x49, 0x03, 0x22, 0x4d, 0x63, 0x06, 0x81, 0xa4, 0x96, 0x86, 0xc3, 0x9a, 0xdf, 0x46, 0x69, - 0x75, 0x7f, 0x04, 0x29, 0x3f, 0x44, 0x29, 0x3f, 0x22, 0x10, 0x40, 0xdb, 0x32, 0x47, 0x65, 0x43, 0xde, 0x77, 0xe9, - 0x9e, 0x71, 0x66, 0x68, 0xf0, 0xd5, 0xaa, 0x55, 0x0d, 0x53, 0x14, 0xf5, 0x61, 0x2e, 0xd7, 0x58, 0x90, 0x37, 0xa0, - 0x6b, 0x56, 0x44, 0xf4, 0x42, 0x57, 0x79, 0x78, 0x89, 0x17, 0x4b, 0x02, 0x4e, 0xfa, 0x3d, 0xd1, 0x2b, 0xc8, 0xe5, - 0xc3, 0x18, 0x7c, 0xcc, 0x30, 0xef, 0xeb, 0x7e, 0x31, 0x18, 0xa0, 0xd4, 0x39, 0x9d, 0xa5, 0x26, 0xe2, 0x4a, 0xe0, - 0x97, 0x5c, 0x80, 0x5f, 0xb2, 0x42, 0xac, 0x5f, 0x0c, 0xc8, 0xbd, 0x2c, 0x96, 0xe0, 0x94, 0xbf, 0xc3, 0xe7, 0xf1, - 0x61, 0x68, 0x60, 0x6a, 0x86, 0x65, 0x2e, 0xb2, 0xc1, 0x62, 0xce, 0x5a, 0x02, 0xc1, 0xcd, 0x80, 0xbb, 0xd4, 0x86, - 0x44, 0x63, 0x0d, 0x14, 0xdd, 0x46, 0xa1, 0x99, 0xd1, 0xd3, 0xad, 0x36, 0xfa, 0x91, 0xc3, 0x0b, 0x73, 0x0d, 0x63, - 0x11, 0xc8, 0x5c, 0xae, 0x7a, 0xec, 0x2f, 0x3f, 0x6c, 0x56, 0x18, 0xbc, 0xc2, 0x98, 0xec, 0x94, 0x56, 0x89, 0x66, - 0x7c, 0x95, 0x27, 0x8e, 0x21, 0xc8, 0xc4, 0x52, 0xe9, 0x86, 0x63, 0xe2, 0x4a, 0xfa, 0x4c, 0x0c, 0xd9, 0x6e, 0x78, - 0x66, 0x2e, 0x74, 0xb3, 0xfd, 0xc3, 0xb9, 0x9d, 0x73, 0xc2, 0x8d, 0x56, 0xd2, 0x68, 0xa3, 0x9e, 0x19, 0xaa, 0xea, - 0x82, 0xf9, 0x3d, 0x74, 0x5a, 0x5a, 0xec, 0x5c, 0xbd, 0xbb, 0xe1, 0xbb, 0x70, 0x65, 0xfc, 0x2d, 0x56, 0x85, 0x56, - 0x64, 0xb8, 0xdd, 0x42, 0xde, 0x9c, 0xe9, 0xa1, 0x57, 0xe4, 0x42, 0x75, 0xf8, 0x8b, 0xba, 0xc2, 0x3c, 0x15, 0x19, - 0x35, 0x84, 0x47, 0xbf, 0xd7, 0x19, 0x28, 0xff, 0x60, 0x62, 0x32, 0x67, 0xc9, 0x0d, 0x2d, 0x44, 0xfc, 0xe3, 0x0b, - 0x61, 0x62, 0x55, 0xed, 0xc1, 0x40, 0xf6, 0x4c, 0xc5, 0x3d, 0xb8, 0x35, 0xe1, 0x63, 0xce, 0x46, 0xe9, 0x5e, 0xf4, - 0x63, 0x43, 0x34, 0x7e, 0x8c, 0x7e, 0x04, 0x77, 0x67, 0xf7, 0x2e, 0x61, 0x19, 0x17, 0xc2, 0xdf, 0x63, 0x3d, 0x2c, - 0x55, 0xca, 0x58, 0x7b, 0xdd, 0x72, 0x78, 0x21, 0xf5, 0x26, 0x8b, 0x1f, 0x3a, 0x62, 0x6d, 0x53, 0xb0, 0x0e, 0x29, - 0x29, 0x3c, 0xbb, 0x62, 0x6e, 0xb5, 0x98, 0xbb, 0xd4, 0x12, 0xfe, 0xfa, 0xea, 0x61, 0xa9, 0x82, 0x86, 0x83, 0xd0, - 0x95, 0xb6, 0x90, 0x00, 0x03, 0x97, 0xd2, 0xa7, 0xd3, 0x9d, 0x49, 0x64, 0x96, 0xc5, 0xf0, 0xee, 0x41, 0x05, 0xf3, - 0xdf, 0xd9, 0x46, 0x58, 0x15, 0xb8, 0x5c, 0xa9, 0xa2, 0x5e, 0x4a, 0x02, 0x01, 0xe8, 0x4b, 0xef, 0x41, 0x79, 0x51, - 0x74, 0x1b, 0x0d, 0x09, 0x5a, 0x58, 0x6a, 0xae, 0x55, 0x31, 0xdd, 0x0f, 0xdf, 0xd3, 0x0b, 0x3e, 0xbc, 0x43, 0xda, - 0xc6, 0xa3, 0x96, 0x94, 0x50, 0xbb, 0x83, 0xf6, 0xc1, 0x2a, 0x3b, 0x28, 0xff, 0x36, 0xa6, 0xc8, 0xe6, 0xf7, 0xd9, - 0x0f, 0xd4, 0x75, 0x38, 0x70, 0x05, 0xab, 0x5e, 0xca, 0x28, 0x18, 0xc2, 0x3e, 0x60, 0x1f, 0x8b, 0x24, 0xa3, 0xd9, - 0x94, 0x81, 0xba, 0xdf, 0x16, 0xad, 0xe6, 0xf6, 0xa4, 0xee, 0x37, 0x64, 0x9c, 0x7d, 0x84, 0x71, 0xf6, 0x51, 0xe0, - 0xc5, 0x22, 0xc9, 0x1f, 0x32, 0xd6, 0x38, 0x56, 0x4d, 0x81, 0x8e, 0x3a, 0xc0, 0x9d, 0x81, 0x03, 0x0f, 0xd8, 0xa2, - 0x1c, 0x1c, 0x50, 0x67, 0x71, 0x4f, 0x1b, 0x99, 0xf7, 0xf6, 0x84, 0xda, 0x45, 0x2c, 0x70, 0xb3, 0x66, 0xa6, 0x05, - 0xad, 0x15, 0xc6, 0x79, 0x3c, 0xe0, 0x6d, 0x9e, 0xd5, 0xe2, 0x27, 0x6c, 0x58, 0x53, 0xd5, 0x6f, 0xa0, 0x39, 0xaa, - 0x05, 0xb9, 0x79, 0x62, 0xbc, 0x55, 0x49, 0x3f, 0x8a, 0x06, 0x96, 0x53, 0x21, 0x86, 0x64, 0xf4, 0x5b, 0x83, 0xe0, - 0x56, 0x7b, 0xb5, 0xe2, 0x1e, 0xf1, 0x45, 0xcd, 0x5b, 0xcd, 0xdc, 0x02, 0xd0, 0x22, 0x8e, 0xca, 0x7b, 0x93, 0x08, - 0xbc, 0x6f, 0xcb, 0x08, 0x69, 0xcb, 0xbe, 0x7d, 0x34, 0xb1, 0x54, 0x6c, 0xbe, 0xa3, 0x93, 0x41, 0x1a, 0xd9, 0x11, - 0x45, 0xf8, 0xba, 0x84, 0x24, 0x5c, 0x25, 0x5d, 0xab, 0x4c, 0xce, 0x99, 0x4a, 0x39, 0xbe, 0x2e, 0xa4, 0xd4, 0x57, - 0xf6, 0x4b, 0xe2, 0xea, 0x4e, 0x46, 0xe0, 0xeb, 0x09, 0xd3, 0xef, 0x68, 0x31, 0x61, 0xe0, 0x57, 0xe4, 0x6f, 0xc7, - 0x52, 0x4a, 0x2e, 0x9f, 0x88, 0xb8, 0x4f, 0x31, 0xbc, 0xf8, 0x39, 0xc0, 0xda, 0x84, 0x40, 0x29, 0x71, 0x11, 0x2e, - 0x88, 0xde, 0x14, 0xf2, 0xf6, 0x2e, 0x2e, 0xb0, 0x73, 0x00, 0x2c, 0x9d, 0x26, 0x01, 0xfe, 0xe5, 0x63, 0x3e, 0x56, - 0x63, 0x4e, 0x8d, 0xae, 0xdf, 0xfd, 0x4e, 0xae, 0x81, 0xde, 0x96, 0x8e, 0x82, 0xfd, 0xd6, 0x00, 0x72, 0xe1, 0x2e, - 0x0c, 0x2e, 0xbe, 0xc2, 0xda, 0xb2, 0x30, 0xde, 0x58, 0x00, 0xbd, 0xbf, 0x33, 0xb0, 0x60, 0xc3, 0x1c, 0x53, 0x78, - 0x2e, 0x75, 0xc2, 0x74, 0x10, 0x15, 0xe4, 0x49, 0xf9, 0x20, 0x66, 0xad, 0xf6, 0x5b, 0x36, 0x86, 0x3b, 0x8c, 0xe4, - 0xdb, 0x85, 0x13, 0x07, 0x1e, 0x90, 0x69, 0x32, 0xdb, 0xec, 0x1b, 0x1f, 0x79, 0xe4, 0xf5, 0x38, 0xde, 0xd5, 0x52, - 0x98, 0x6f, 0x56, 0x74, 0x8d, 0x21, 0x14, 0x45, 0xd8, 0xef, 0x17, 0x15, 0x53, 0x54, 0x19, 0xb4, 0x41, 0xc3, 0xf2, - 0x46, 0xfc, 0x02, 0x67, 0x0c, 0xad, 0x17, 0xb2, 0x77, 0x74, 0xd6, 0xe1, 0xcc, 0x61, 0xc6, 0x94, 0xc0, 0xa8, 0xb4, - 0x2c, 0xe8, 0x04, 0x1c, 0x9d, 0xab, 0x0f, 0xa2, 0xe2, 0xea, 0x58, 0x01, 0x78, 0x92, 0x29, 0xfc, 0x93, 0x6f, 0x82, - 0x75, 0xbf, 0x55, 0x33, 0x4c, 0xfd, 0x45, 0x6f, 0xbb, 0x96, 0x2f, 0x43, 0x1c, 0x69, 0x63, 0x08, 0xad, 0x73, 0x7b, - 0x07, 0x28, 0xe2, 0x82, 0x5e, 0xa4, 0x1a, 0x5f, 0xab, 0xc5, 0xd0, 0xac, 0xaf, 0x71, 0x1d, 0xd3, 0x06, 0x51, 0xac, - 0xbb, 0x26, 0xbe, 0xae, 0xde, 0x1f, 0x55, 0xa9, 0x82, 0x33, 0x48, 0x20, 0xac, 0xca, 0xcb, 0x86, 0x54, 0x92, 0x4b, - 0xd3, 0xa9, 0x34, 0x9d, 0x56, 0x08, 0xe5, 0xd2, 0x93, 0xf2, 0xfe, 0x15, 0x42, 0x18, 0x98, 0x32, 0x3b, 0xb0, 0x4a, - 0x6d, 0x61, 0x15, 0xbc, 0x7a, 0xb1, 0x81, 0x55, 0x12, 0x8e, 0xe7, 0x12, 0x8d, 0x8a, 0x0a, 0x87, 0x0c, 0xe9, 0x0b, - 0xb1, 0x08, 0x12, 0x00, 0x8b, 0xde, 0x65, 0x2e, 0xef, 0x7b, 0x38, 0x14, 0xf6, 0x24, 0x93, 0x70, 0xba, 0x09, 0xcd, - 0xe1, 0x61, 0x5a, 0xd5, 0xf3, 0x08, 0x01, 0x4b, 0xcf, 0x31, 0x3c, 0x48, 0xfc, 0xfd, 0x87, 0x50, 0x9d, 0x05, 0x79, - 0xfa, 0x2f, 0x51, 0x12, 0x1a, 0xfb, 0xcf, 0xf1, 0xd0, 0x21, 0x61, 0x38, 0xf0, 0xcd, 0x11, 0x56, 0x38, 0xb8, 0x55, - 0xc4, 0x67, 0x70, 0x87, 0x8f, 0x75, 0xe8, 0x01, 0x60, 0x09, 0xc5, 0x21, 0xc8, 0x37, 0x50, 0xcc, 0xe0, 0x80, 0x26, - 0xcb, 0xf0, 0x02, 0x17, 0xac, 0x16, 0xca, 0xfb, 0xdb, 0x96, 0x97, 0xd2, 0x6a, 0x97, 0xbc, 0xc6, 0x1c, 0xa8, 0xfc, - 0x0c, 0x2f, 0x7c, 0x85, 0x79, 0x29, 0xd9, 0x7d, 0xe1, 0x6b, 0x07, 0xf4, 0x14, 0x02, 0x46, 0xba, 0xdf, 0x6b, 0xc2, - 0x3d, 0x45, 0x2f, 0x73, 0x71, 0xd8, 0x76, 0xd0, 0xbd, 0xc0, 0x5c, 0x5d, 0x55, 0x59, 0x73, 0x30, 0x85, 0x06, 0x07, - 0x55, 0x38, 0x23, 0x30, 0x57, 0x2f, 0xca, 0x82, 0x73, 0x10, 0xef, 0x7b, 0xc2, 0xe4, 0x94, 0xd1, 0x00, 0x5e, 0x64, - 0xe5, 0xa3, 0x53, 0x3d, 0x0e, 0x2e, 0xe3, 0x86, 0x4d, 0x7c, 0x21, 0x7c, 0x2a, 0xb0, 0x92, 0xd6, 0x38, 0x34, 0xa2, - 0x23, 0x3a, 0x07, 0xb3, 0x0d, 0xa0, 0xe0, 0xee, 0x7c, 0xd8, 0x58, 0xa8, 0xe0, 0x31, 0xd8, 0xda, 0xdb, 0xcd, 0x84, - 0x38, 0x93, 0xa6, 0xe0, 0x6e, 0xdb, 0x20, 0x83, 0x37, 0xbf, 0xfd, 0xb7, 0xc2, 0x22, 0xc1, 0x80, 0x4a, 0x4d, 0x12, - 0x84, 0x27, 0x28, 0x8d, 0x74, 0x2b, 0x37, 0x13, 0x48, 0x27, 0xa2, 0x66, 0xd4, 0xbd, 0x71, 0xbe, 0x3a, 0x6a, 0x20, - 0x2a, 0x6a, 0xa0, 0x02, 0x6a, 0x20, 0xeb, 0xdb, 0xbf, 0x80, 0x85, 0xb0, 0x11, 0xaa, 0x44, 0x10, 0x10, 0x61, 0xae, - 0x0d, 0x1f, 0x50, 0x24, 0x21, 0xe4, 0x0d, 0xa0, 0x62, 0x4a, 0x5e, 0x82, 0xd1, 0x38, 0xbc, 0xde, 0x03, 0xee, 0x97, - 0x96, 0x61, 0xf0, 0x9c, 0x82, 0xc9, 0x7f, 0xeb, 0xf3, 0xa1, 0x7a, 0xb9, 0x3a, 0x08, 0xe1, 0x17, 0x10, 0x2b, 0xc2, - 0xf1, 0x17, 0xbf, 0x00, 0xd9, 0x54, 0x58, 0x1e, 0x1c, 0x48, 0x10, 0xf8, 0x21, 0x8a, 0x70, 0xc0, 0x33, 0xbc, 0xcc, - 0x36, 0x88, 0x9e, 0x9f, 0x95, 0xaa, 0x66, 0x25, 0x83, 0x59, 0x15, 0x9e, 0xc6, 0xd1, 0x35, 0x61, 0x20, 0xb8, 0x50, - 0xbb, 0x6f, 0x10, 0x02, 0x65, 0xcb, 0x8d, 0xa1, 0x4b, 0x4f, 0xc1, 0x7c, 0x34, 0x8e, 0xde, 0x32, 0x78, 0xd2, 0xd6, - 0x98, 0xfc, 0x33, 0x6d, 0x1e, 0xb8, 0x4f, 0xf7, 0xa2, 0x46, 0xe0, 0xa4, 0x4e, 0x51, 0xf2, 0xb7, 0xe4, 0x22, 0x8e, - 0x9a, 0x97, 0x11, 0x6a, 0xc0, 0xbf, 0x0d, 0x8e, 0xba, 0x34, 0xa1, 0xa3, 0x91, 0x0f, 0x7e, 0x93, 0x11, 0xb3, 0xc9, - 0x56, 0x2b, 0x51, 0x11, 0xf4, 0xc4, 0x6e, 0x30, 0x60, 0x25, 0x5e, 0x00, 0xfb, 0x60, 0x39, 0x58, 0xf2, 0x4e, 0xc4, - 0xca, 0x9f, 0x52, 0x18, 0xac, 0x9e, 0x33, 0x84, 0x70, 0x16, 0xc4, 0x6c, 0xfc, 0xcf, 0x67, 0x1a, 0xae, 0x9f, 0x9f, - 0xaf, 0x63, 0x44, 0xa4, 0x0f, 0x22, 0x57, 0x63, 0x47, 0x44, 0x10, 0xb6, 0x4c, 0xf7, 0x5d, 0x99, 0x1f, 0xbc, 0x75, - 0xf5, 0xc0, 0x86, 0x8b, 0x03, 0x03, 0x6a, 0x14, 0x18, 0xad, 0xe0, 0x9c, 0x94, 0x03, 0x07, 0x25, 0x84, 0x66, 0x45, - 0x3c, 0x25, 0x97, 0x10, 0x09, 0x2f, 0x43, 0x5d, 0x30, 0x2c, 0x08, 0x24, 0xa8, 0x29, 0x48, 0x50, 0x99, 0xaf, 0x3d, - 0x82, 0x59, 0xe7, 0x66, 0xb6, 0x53, 0xd4, 0x75, 0x41, 0x7e, 0x7e, 0xd1, 0xf1, 0x08, 0x58, 0xda, 0x83, 0x83, 0x02, - 0x22, 0x88, 0x01, 0x05, 0x2f, 0x25, 0xc0, 0x40, 0x03, 0x5e, 0x6c, 0x68, 0xc0, 0xe7, 0xda, 0x78, 0x1d, 0x18, 0x5b, - 0x9f, 0x32, 0xc8, 0xc5, 0xb3, 0x6a, 0x4f, 0x13, 0x42, 0xf6, 0x5b, 0x3d, 0x9d, 0x6e, 0x47, 0x48, 0xec, 0x7d, 0xd4, - 0x26, 0xd0, 0x98, 0x23, 0xdd, 0xd5, 0xc6, 0xfc, 0x5a, 0xd3, 0x23, 0x56, 0x93, 0x90, 0x2e, 0x48, 0x97, 0xe7, 0xd3, - 0x9e, 0xc1, 0x15, 0xab, 0x34, 0x72, 0x70, 0x01, 0xfa, 0x6c, 0x40, 0x80, 0x02, 0x95, 0xa6, 0x12, 0x45, 0x11, 0x17, - 0x49, 0xc9, 0x86, 0x61, 0x06, 0x61, 0x0a, 0xab, 0x95, 0xa0, 0x1b, 0x6b, 0x00, 0xbc, 0x33, 0xb3, 0x7f, 0x4a, 0x1f, - 0x6c, 0xba, 0xf6, 0xe6, 0x11, 0x40, 0x40, 0xf6, 0xdb, 0x25, 0xbb, 0x2e, 0x36, 0x2a, 0xb3, 0xb0, 0x96, 0xb1, 0x95, - 0xdb, 0xf6, 0x18, 0x7b, 0x27, 0xb6, 0xf9, 0x04, 0x08, 0x51, 0x5b, 0x32, 0x8d, 0x10, 0x21, 0xb1, 0x88, 0x75, 0x6d, - 0xc8, 0x46, 0x1b, 0xda, 0x37, 0x4f, 0xc2, 0x43, 0xec, 0x03, 0x50, 0xbc, 0x39, 0x2e, 0xc1, 0x21, 0xbc, 0xf0, 0x08, - 0x7f, 0x0b, 0x2c, 0x52, 0x81, 0x19, 0x96, 0xab, 0x15, 0xd4, 0xf3, 0x78, 0x9f, 0x6d, 0x06, 0x27, 0x95, 0x1b, 0x63, - 0x97, 0x76, 0xe2, 0x71, 0xd9, 0x84, 0xc4, 0x19, 0xf4, 0xeb, 0x2b, 0xa2, 0xde, 0x7e, 0x3b, 0x7d, 0xe2, 0xdf, 0x2b, - 0x73, 0x3b, 0x10, 0x1b, 0xd6, 0x1b, 0xac, 0x3e, 0x80, 0x96, 0xbf, 0xca, 0xfc, 0x43, 0x65, 0xc1, 0x4d, 0x82, 0xda, - 0x5c, 0xc4, 0x2e, 0xeb, 0x22, 0x46, 0x6a, 0x8b, 0xbb, 0x43, 0x88, 0x7f, 0xb5, 0x15, 0xc5, 0x80, 0x27, 0x15, 0xff, - 0x1c, 0xa3, 0x2e, 0x84, 0xa2, 0xb6, 0x1e, 0x36, 0x40, 0x69, 0x97, 0xeb, 0x4a, 0x8c, 0x0c, 0x09, 0xe4, 0x5b, 0x17, - 0x5e, 0xd0, 0x9c, 0x44, 0x0a, 0xe4, 0xe4, 0x20, 0x2a, 0x69, 0xb6, 0x21, 0xcc, 0x75, 0xb7, 0x70, 0xcc, 0x5c, 0x6d, - 0xd0, 0x22, 0x7e, 0x01, 0xec, 0x0c, 0x37, 0x92, 0xa5, 0x03, 0x9f, 0xaa, 0x81, 0xcf, 0xaf, 0xb9, 0xa1, 0x28, 0x0a, - 0xf5, 0xde, 0xd9, 0x47, 0xe6, 0xe0, 0x77, 0x1a, 0x88, 0x8f, 0xd4, 0xe9, 0x48, 0x36, 0x42, 0xad, 0x39, 0x3b, 0x5e, - 0xb6, 0x19, 0x61, 0x50, 0xd8, 0xe8, 0x7d, 0x15, 0xb2, 0x8a, 0x9d, 0x9d, 0x8a, 0x60, 0x4e, 0x5f, 0x54, 0xe5, 0x9c, - 0xca, 0x2d, 0xa3, 0x5a, 0x6a, 0x1a, 0x20, 0xc2, 0x95, 0x4f, 0x24, 0xef, 0x33, 0x13, 0xfe, 0xc1, 0x60, 0x5c, 0x3d, - 0x52, 0xf8, 0xfb, 0x5d, 0xb1, 0x43, 0xb6, 0xa3, 0xc3, 0x6d, 0x04, 0xcd, 0x0b, 0x15, 0x3c, 0xe0, 0xa8, 0x64, 0x09, - 0x91, 0x22, 0x97, 0xfb, 0xaa, 0x66, 0xca, 0x76, 0x1d, 0x21, 0x84, 0xb4, 0xc7, 0x59, 0x37, 0xb4, 0x7a, 0xe8, 0x91, - 0x2a, 0xca, 0xe1, 0x16, 0xcd, 0x75, 0x01, 0x2a, 0x8c, 0x40, 0xba, 0xfc, 0xcc, 0xee, 0x52, 0x09, 0xd1, 0xcb, 0xd7, - 0x2e, 0x84, 0xb1, 0xb3, 0xb2, 0xc4, 0x85, 0x19, 0xb5, 0x0d, 0xa3, 0xeb, 0x36, 0x86, 0xb3, 0x81, 0x31, 0xd3, 0xa0, - 0xa4, 0x05, 0xa1, 0xae, 0xbb, 0xf4, 0x22, 0x33, 0x81, 0x1e, 0x73, 0x42, 0x1b, 0x0c, 0x4f, 0x89, 0x06, 0xcb, 0xa6, - 0x02, 0x2c, 0xf8, 0x96, 0x45, 0x6a, 0x6d, 0x36, 0x59, 0xfc, 0x51, 0xc7, 0xe6, 0x69, 0xbf, 0xbc, 0x62, 0x9e, 0x0b, - 0x47, 0xdd, 0x9e, 0x67, 0x3e, 0x1e, 0xdd, 0xd3, 0x37, 0x57, 0x2f, 0x5e, 0xbe, 0x7e, 0xb5, 0x5a, 0xb5, 0x59, 0xb3, - 0x7d, 0x82, 0x7f, 0xd2, 0x65, 0x3c, 0xd8, 0x32, 0x0a, 0xd0, 0xc1, 0xc1, 0x3e, 0x37, 0x2e, 0x3c, 0x9f, 0xf9, 0x1c, - 0xe2, 0x06, 0xe9, 0x01, 0xce, 0x8a, 0x32, 0x26, 0xc8, 0x6d, 0xd4, 0x8b, 0xee, 0x22, 0x50, 0x42, 0x55, 0xe4, 0xef, - 0xc3, 0xe6, 0xec, 0xf7, 0x20, 0x30, 0x11, 0xd4, 0x87, 0x08, 0x20, 0x10, 0xaf, 0x14, 0x17, 0x84, 0xf9, 0x04, 0x88, - 0xe2, 0xbd, 0x00, 0xce, 0xd4, 0x44, 0xad, 0x5a, 0xa8, 0xb8, 0x00, 0x92, 0x68, 0xc3, 0x51, 0xd2, 0x23, 0x13, 0xc0, - 0x1b, 0x82, 0x52, 0xda, 0x5f, 0xdd, 0xdc, 0xb9, 0x4b, 0xe5, 0xa8, 0xd7, 0x4a, 0x73, 0x3c, 0x75, 0x9f, 0x53, 0xf8, - 0x9c, 0x76, 0xfd, 0xe9, 0x20, 0x0e, 0x73, 0xbc, 0x20, 0xe2, 0xd0, 0x3f, 0x8b, 0xb8, 0x9c, 0x17, 0xec, 0x0b, 0x97, - 0x0b, 0x95, 0x2e, 0x6f, 0x53, 0x99, 0xdc, 0x36, 0x47, 0x87, 0x71, 0x91, 0xdc, 0x36, 0x55, 0x72, 0x8b, 0xf0, 0x5d, - 0x2a, 0x93, 0x3b, 0x9b, 0x72, 0xd7, 0x54, 0x70, 0xf3, 0x85, 0x05, 0x1c, 0x8a, 0xb6, 0x68, 0x63, 0xb1, 0x59, 0xd4, - 0xa6, 0xb8, 0xa2, 0x01, 0x06, 0xff, 0xbe, 0x63, 0xe3, 0x87, 0xe1, 0x4b, 0x70, 0x69, 0xd2, 0x44, 0x7e, 0x02, 0xe9, - 0xa7, 0x55, 0x19, 0xb8, 0x4f, 0x49, 0xab, 0x3b, 0xbd, 0x10, 0xcd, 0x76, 0xb7, 0xd1, 0x98, 0xc2, 0xde, 0xcd, 0x48, - 0xee, 0x8b, 0x4d, 0x1b, 0x26, 0xbe, 0xce, 0x7e, 0xb6, 0x5a, 0xed, 0xe7, 0xc8, 0x6c, 0xb8, 0x09, 0x8b, 0x75, 0x7f, - 0x3a, 0xc0, 0x2d, 0xfc, 0x3c, 0x43, 0x68, 0xc9, 0xfa, 0xd3, 0x01, 0x61, 0xfd, 0x69, 0xa3, 0x3d, 0xb0, 0x86, 0x76, - 0x66, 0x2b, 0xae, 0x21, 0x84, 0xe6, 0x74, 0x70, 0x64, 0x4a, 0x4a, 0x97, 0x6f, 0xbf, 0x68, 0x15, 0xd0, 0x4f, 0xd5, - 0x82, 0x97, 0x49, 0xdc, 0x81, 0xbe, 0xe8, 0x85, 0x7d, 0xba, 0xb5, 0x20, 0xc7, 0x47, 0x95, 0xab, 0x3d, 0x45, 0xd8, - 0xf4, 0xa4, 0x0e, 0x8b, 0x43, 0xd3, 0x8c, 0xeb, 0x52, 0xba, 0xef, 0x50, 0x33, 0xf2, 0xd1, 0xc1, 0x02, 0x10, 0xa4, - 0x82, 0x47, 0x56, 0xb8, 0x70, 0x4a, 0x21, 0x5c, 0x1c, 0x54, 0xb6, 0x60, 0x92, 0x93, 0x56, 0x37, 0x37, 0x96, 0xfe, - 0xb9, 0x8b, 0x68, 0x4a, 0x31, 0x25, 0x99, 0x2f, 0x99, 0x1b, 0xb0, 0xd0, 0x4d, 0xca, 0x33, 0x05, 0xbd, 0xd2, 0x00, - 0x8f, 0x08, 0xc4, 0x43, 0xea, 0x16, 0xc6, 0xc0, 0x2b, 0x9e, 0x36, 0x8b, 0x3e, 0x1b, 0xa0, 0xa3, 0x63, 0x4c, 0xfb, - 0x7f, 0x65, 0xf3, 0x36, 0x3c, 0x16, 0xf8, 0xd7, 0x80, 0x4c, 0x9b, 0xb2, 0x4c, 0x10, 0x90, 0x30, 0x6a, 0xca, 0x43, - 0xd8, 0x4b, 0x08, 0x67, 0xb6, 0x62, 0xd6, 0x67, 0x83, 0xe6, 0xb4, 0xac, 0xd8, 0xf1, 0x15, 0x1b, 0xb2, 0x4c, 0xb0, - 0x15, 0x1b, 0xae, 0x62, 0xf8, 0x3a, 0x83, 0x01, 0x41, 0x08, 0x00, 0x06, 0x00, 0xd0, 0x28, 0x88, 0xe6, 0x8b, 0x15, - 0xf1, 0x9b, 0xdd, 0xde, 0xe3, 0xb7, 0xc0, 0x02, 0xad, 0xb6, 0xff, 0x77, 0xa1, 0x0c, 0xd8, 0x53, 0x16, 0x26, 0x66, - 0x6e, 0x61, 0x55, 0x74, 0x00, 0x95, 0x12, 0x61, 0x0a, 0x03, 0x99, 0xfd, 0xcc, 0x40, 0x2d, 0xd0, 0x1a, 0xe4, 0x7d, - 0x3d, 0x68, 0x66, 0x70, 0xc4, 0xc0, 0x3b, 0x34, 0x64, 0x6a, 0x8c, 0x09, 0xe3, 0x1c, 0xa6, 0x98, 0x19, 0xf0, 0x4c, - 0xd3, 0xd6, 0x5a, 0x1a, 0x59, 0xae, 0x97, 0xf7, 0xfe, 0xd1, 0xb1, 0xea, 0x17, 0xcd, 0xf6, 0x00, 0xed, 0x13, 0x62, - 0x3f, 0x06, 0xb0, 0xc9, 0x5c, 0x6a, 0xc3, 0x7c, 0x1f, 0x75, 0x52, 0xfb, 0x09, 0x7f, 0x06, 0x6b, 0xb3, 0x03, 0x40, - 0x47, 0x86, 0xcd, 0xfa, 0xcb, 0x9a, 0xca, 0xeb, 0xe3, 0xce, 0x28, 0x95, 0xbb, 0xde, 0x9d, 0x0e, 0x34, 0xc5, 0xa1, - 0xb7, 0x1e, 0x2e, 0x1f, 0xea, 0x21, 0x60, 0xc6, 0x60, 0x6e, 0x99, 0xd1, 0xf7, 0x42, 0x24, 0x17, 0x44, 0x62, 0x69, - 0xb0, 0x86, 0xc1, 0xde, 0x3a, 0x38, 0x30, 0xd5, 0x58, 0x03, 0x9e, 0x27, 0x45, 0x20, 0x18, 0xf8, 0x08, 0xca, 0x80, - 0x26, 0xca, 0xdc, 0x86, 0x93, 0x8f, 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, 0xdd, 0xcd, 0x74, - 0xca, 0x66, 0x3a, 0xdb, 0xcd, 0x84, 0x9a, 0x99, 0x6f, 0x59, 0x45, 0x9a, 0x93, 0x35, 0x51, 0x73, 0x2a, 0x7e, 0xa2, - 0x73, 0xd0, 0x8e, 0x72, 0x7b, 0xaf, 0x0a, 0x27, 0x57, 0x4e, 0x2e, 0xf7, 0x73, 0x43, 0x5c, 0x91, 0xb9, 0x50, 0x87, - 0x00, 0x2f, 0x2f, 0xca, 0xc7, 0x07, 0xb8, 0x14, 0xbf, 0xca, 0x91, 0x8b, 0x72, 0x2a, 0xa4, 0x96, 0x82, 0x45, 0xc8, - 0xa0, 0xaa, 0x8b, 0x81, 0xbd, 0xb4, 0x7b, 0x4f, 0xf4, 0x78, 0xbf, 0x8a, 0x98, 0x37, 0x30, 0xcf, 0x7d, 0x7c, 0x4f, - 0x53, 0xec, 0xd4, 0xc4, 0x19, 0xf9, 0x90, 0xc5, 0x39, 0xc8, 0x66, 0xfd, 0xea, 0xb5, 0xdf, 0x46, 0x1b, 0x17, 0xcd, - 0x58, 0xf4, 0xcc, 0x13, 0x27, 0x3f, 0x14, 0xc6, 0x38, 0xc0, 0x3a, 0xfa, 0x23, 0x4c, 0x2d, 0xd8, 0xb3, 0xc4, 0x53, - 0xe8, 0xe4, 0xd6, 0xa6, 0xdd, 0x85, 0x69, 0x77, 0x26, 0xad, 0x03, 0xe5, 0x80, 0x34, 0xbb, 0x32, 0x9d, 0x3b, 0xff, - 0x7d, 0x07, 0x2f, 0xdd, 0xae, 0x21, 0x12, 0xf7, 0xfc, 0x91, 0x31, 0x86, 0x78, 0x03, 0x36, 0xa2, 0xea, 0xe0, 0xe0, - 0x0f, 0xe7, 0x7d, 0x5b, 0xc9, 0x7d, 0xdf, 0x0a, 0x07, 0xb6, 0xc1, 0x54, 0xba, 0xbc, 0x91, 0xcc, 0x16, 0x60, 0xd7, - 0xb9, 0xff, 0x8d, 0x78, 0xf8, 0x22, 0x64, 0x5a, 0xac, 0xab, 0xf8, 0x2b, 0x39, 0x2a, 0x3d, 0x44, 0x35, 0x44, 0x20, - 0xad, 0xac, 0x4b, 0x43, 0xd3, 0xd1, 0xab, 0x29, 0x1d, 0xc9, 0x9b, 0xb7, 0x52, 0xea, 0x81, 0x7d, 0x91, 0x5b, 0x27, - 0xf0, 0x68, 0x61, 0x8d, 0xa1, 0xb9, 0x2b, 0xbd, 0x93, 0x6c, 0x40, 0xd4, 0xfa, 0xb8, 0x43, 0x49, 0x24, 0x16, 0xd5, - 0x5d, 0x08, 0x87, 0xbb, 0x10, 0xcc, 0xcb, 0xa0, 0x6d, 0x10, 0xbb, 0xdd, 0x05, 0x6d, 0x03, 0xa7, 0x6e, 0x1b, 0xb8, - 0x3d, 0x18, 0x2c, 0xec, 0x7d, 0x78, 0x39, 0x96, 0x63, 0xe1, 0xaf, 0xc9, 0xec, 0x03, 0x40, 0xa0, 0xf6, 0x61, 0xc5, - 0x13, 0x07, 0x82, 0xc4, 0x19, 0x8e, 0xbe, 0xe7, 0xec, 0xc6, 0x5a, 0x0e, 0xcf, 0xe6, 0x0b, 0xcd, 0x46, 0xe6, 0x8e, - 0x1a, 0x54, 0x7c, 0x75, 0x3f, 0xaf, 0x9f, 0xb2, 0x9a, 0x6e, 0xfc, 0x1e, 0x84, 0x91, 0x70, 0xca, 0x0e, 0xa3, 0x90, - 0xb0, 0xc1, 0xac, 0xca, 0x78, 0x6d, 0xbf, 0x41, 0xbc, 0x07, 0x6d, 0xc2, 0x09, 0x16, 0xb5, 0x0b, 0xaa, 0x08, 0xdb, - 0x78, 0x63, 0x41, 0x94, 0x87, 0x37, 0x5b, 0x46, 0xd3, 0xcb, 0x35, 0x04, 0x3a, 0xee, 0x45, 0xcd, 0xa8, 0xc1, 0x52, - 0x17, 0x94, 0xd9, 0x47, 0x18, 0x57, 0x17, 0x27, 0x26, 0x4e, 0x7b, 0xa9, 0x57, 0xff, 0x2d, 0x03, 0x03, 0x7c, 0x01, - 0x5e, 0x62, 0x61, 0x74, 0xd7, 0xbe, 0x6e, 0x40, 0x7d, 0xd9, 0x60, 0x03, 0xb4, 0x5a, 0xb5, 0xca, 0x67, 0xa0, 0xdc, - 0x35, 0x97, 0xb0, 0xd7, 0x5c, 0xc2, 0x5d, 0x73, 0x09, 0x7f, 0xcd, 0x25, 0xcc, 0x35, 0x97, 0xf0, 0xd7, 0x5c, 0x1e, - 0x84, 0x9f, 0x82, 0x38, 0x8e, 0x31, 0x87, 0xb8, 0x8a, 0xda, 0x46, 0xc6, 0x83, 0x0b, 0xcf, 0x7d, 0x96, 0xa8, 0x72, - 0xf9, 0xc3, 0x18, 0x72, 0x5b, 0xb6, 0x12, 0xc6, 0x6d, 0x8a, 0x29, 0x88, 0x9c, 0x7e, 0x70, 0x50, 0xba, 0x3b, 0x83, - 0x8f, 0x7a, 0xca, 0xf1, 0xd2, 0x3a, 0xd1, 0xfe, 0x01, 0x3a, 0x79, 0xf3, 0xeb, 0x63, 0x2a, 0xd7, 0x44, 0x38, 0x93, - 0xfb, 0xfd, 0xb6, 0xa7, 0x14, 0x9f, 0x32, 0x13, 0x9e, 0x9c, 0x27, 0xda, 0x88, 0x20, 0x08, 0x51, 0xa2, 0x70, 0x46, - 0xa4, 0xdd, 0xef, 0xde, 0x15, 0xde, 0xa8, 0xa2, 0xbc, 0x59, 0xc9, 0xe3, 0x1c, 0x9c, 0xd8, 0x8d, 0x15, 0x06, 0xea, - 0x82, 0x0b, 0x41, 0x66, 0x12, 0xfe, 0x68, 0xe6, 0x96, 0x9c, 0x65, 0x65, 0xd2, 0xc7, 0x66, 0x6e, 0x08, 0x58, 0x41, - 0xf6, 0x3d, 0xcc, 0x96, 0xb7, 0x29, 0xc5, 0x77, 0x69, 0x86, 0x87, 0xf2, 0x36, 0x2d, 0x42, 0x5b, 0x10, 0x7f, 0xf1, - 0x37, 0x8e, 0x23, 0x41, 0xc1, 0xdf, 0x27, 0xe2, 0x62, 0x8f, 0x6f, 0x78, 0x01, 0x2e, 0x33, 0x63, 0x51, 0x9d, 0x32, - 0xfc, 0x0d, 0x4b, 0x78, 0x08, 0x4e, 0xa6, 0xb1, 0x22, 0xf7, 0x38, 0xb0, 0x13, 0x92, 0x80, 0xc3, 0xd5, 0xed, 0x15, - 0xff, 0x0a, 0x17, 0x5f, 0xa5, 0xb3, 0x65, 0x73, 0x28, 0x6f, 0x23, 0x5c, 0x90, 0x37, 0xf0, 0xfa, 0xd6, 0xff, 0xcb, - 0xde, 0xdb, 0x36, 0xb7, 0x6d, 0x64, 0xeb, 0xa2, 0x7f, 0x45, 0x62, 0xd9, 0x0c, 0x60, 0x36, 0x29, 0xca, 0xe7, 0xcc, - 0x54, 0x5d, 0x50, 0x6d, 0x96, 0x63, 0xc7, 0x13, 0x67, 0x22, 0xdb, 0x63, 0x79, 0x32, 0xc9, 0xb0, 0x78, 0x19, 0x08, - 0x68, 0x0a, 0x70, 0x40, 0x80, 0x01, 0x40, 0x89, 0x34, 0x89, 0xff, 0x7e, 0x6a, 0xad, 0xd5, 0xaf, 0x20, 0x28, 0x7b, - 0xf6, 0x3e, 0xfb, 0xd3, 0xbd, 0x5f, 0x6c, 0xb1, 0xd1, 0x68, 0xf4, 0x7b, 0xaf, 0x5e, 0x2f, 0xcf, 0xd3, 0x93, 0xb1, - 0xba, 0x3d, 0x70, 0xd6, 0xa5, 0x14, 0x1d, 0x6f, 0x8a, 0xc3, 0xdb, 0xf3, 0xd9, 0x7e, 0x1b, 0x44, 0x6c, 0x17, 0x64, - 0x58, 0xeb, 0xa4, 0xe1, 0x3f, 0xd1, 0xd6, 0xc1, 0x62, 0x84, 0xfd, 0x5f, 0xd6, 0x03, 0x2f, 0x21, 0x35, 0x14, 0xb8, - 0x18, 0x6c, 0x38, 0x5a, 0xdb, 0x65, 0x1a, 0xb8, 0xa9, 0x41, 0xaf, 0xef, 0x29, 0x44, 0x79, 0xc9, 0x68, 0x6e, 0x04, - 0xeb, 0xc6, 0x90, 0x8b, 0xc3, 0x71, 0xb3, 0x1c, 0xf2, 0x92, 0xa6, 0xd3, 0x20, 0x94, 0xee, 0x2c, 0x6b, 0x48, 0xa2, - 0xec, 0x83, 0x50, 0xbb, 0xb6, 0xec, 0xb7, 0x81, 0xed, 0xcb, 0x1f, 0x0d, 0x63, 0xff, 0x62, 0xf9, 0x4c, 0x48, 0x17, - 0xf1, 0x1c, 0x04, 0x51, 0xfb, 0x79, 0x36, 0xdc, 0xf8, 0x17, 0xeb, 0x67, 0x42, 0xf9, 0x8d, 0xe7, 0xb6, 0x1c, 0x52, - 0x67, 0x2d, 0x7c, 0x61, 0x3c, 0x3c, 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, 0x01, 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, 0xee, 0x52, 0xa6, 0xcb, 0x80, 0x4b, 0xfa, 0x5d, 0xaa, 0x94, 0xc2, 0x7f, 0x22, 0x00, 0x9d, 0x83, 0x7b, 0x7c, - 0x39, 0x06, 0xd2, 0x0c, 0x0b, 0xbf, 0x35, 0x3b, 0xbe, 0x26, 0xe1, 0x36, 0x09, 0x2e, 0x06, 0x38, 0x47, 0x57, 0x61, - 0x79, 0x97, 0x42, 0x04, 0x55, 0x09, 0xf5, 0xad, 0x4c, 0x83, 0xd2, 0x56, 0x83, 0xb0, 0x26, 0xa1, 0xce, 0x24, 0x1b, - 0x95, 0xb6, 0x1b, 0x85, 0xd9, 0x22, 0xae, 0x67, 0x84, 0x35, 0x67, 0x33, 0xd5, 0xc0, 0xa4, 0xe1, 0xb8, 0x69, 0xb4, - 0x16, 0x15, 0x6a, 0x0a, 0xf3, 0x1a, 0x57, 0x95, 0xaa, 0xee, 0xe6, 0xd4, 0x52, 0x5a, 0xb6, 0x57, 0xdd, 0x24, 0x1b, - 0x72, 0x19, 0xca, 0x30, 0xd8, 0xc8, 0x11, 0x4c, 0x20, 0x49, 0xce, 0xfc, 0x8d, 0xfc, 0x43, 0x6d, 0xba, 0x16, 0x30, - 0xc7, 0x98, 0x65, 0xc3, 0x82, 0x5e, 0x81, 0x7b, 0xa0, 0x95, 0x9e, 0x4f, 0xb3, 0x8b, 0x3c, 0x48, 0x86, 0x85, 0x5e, - 0x36, 0x19, 0xff, 0x53, 0x18, 0x69, 0x32, 0x63, 0x25, 0x8b, 0x6c, 0x57, 0xa7, 0xc4, 0x79, 0x9c, 0xc0, 0xf6, 0x68, - 0x7a, 0xcb, 0xf7, 0x19, 0x44, 0x05, 0x81, 0x82, 0x19, 0xf3, 0x65, 0x17, 0xcf, 0x7d, 0x9f, 0x59, 0xa6, 0xee, 0xc3, - 0xc1, 0x98, 0xb1, 0xfd, 0x7e, 0x3f, 0xef, 0xf7, 0xd5, 0x7c, 0xeb, 0xf7, 0x93, 0x17, 0xe6, 0x6f, 0x0f, 0x18, 0x14, - 0xe4, 0x44, 0x34, 0x15, 0x22, 0xf8, 0x87, 0xe4, 0x19, 0x92, 0xd1, 0x1d, 0xf7, 0xb9, 0xe5, 0x6c, 0x59, 0x1d, 0x81, - 0x60, 0x1e, 0x0e, 0x97, 0x0a, 0xec, 0x5a, 0xa2, 0x48, 0xc8, 0xf2, 0x9f, 0x81, 0xf1, 0xcc, 0x7d, 0x80, 0x25, 0x03, - 0x10, 0xb6, 0xca, 0xd3, 0xf5, 0x9e, 0xaf, 0x82, 0x77, 0x3a, 0xde, 0x35, 0x56, 0x64, 0x20, 0x6e, 0x81, 0x8d, 0x58, - 0x6b, 0x0f, 0xc8, 0x99, 0x02, 0x1c, 0x2f, 0x0e, 0x87, 0x73, 0xf9, 0x4b, 0x37, 0x5b, 0x27, 0x50, 0x29, 0x70, 0x7b, - 0x74, 0x72, 0xf0, 0xdf, 0x81, 0x66, 0x50, 0x0e, 0xf3, 0x7a, 0xfb, 0x3b, 0x73, 0xf2, 0xd3, 0x53, 0xfc, 0x13, 0x1e, - 0xa2, 0xd3, 0x6f, 0xf7, 0xe6, 0x0f, 0x8a, 0xca, 0xc3, 0x41, 0x2d, 0xfe, 0x73, 0xce, 0x2b, 0xf8, 0x85, 0x6f, 0x02, - 0xb3, 0xc9, 0xd4, 0x3b, 0xf9, 0x26, 0xcf, 0x99, 0x7a, 0x8d, 0x57, 0x4c, 0xbe, 0xc3, 0xe1, 0x5c, 0x8c, 0xea, 0xed, - 0xc8, 0x89, 0x76, 0xca, 0x31, 0x0e, 0x06, 0xff, 0x45, 0xb4, 0x4d, 0x08, 0x30, 0xa4, 0x6e, 0x49, 0x33, 0x1b, 0x57, - 0x96, 0x78, 0x96, 0xce, 0x2f, 0x27, 0x75, 0xb9, 0xd3, 0x8a, 0xa7, 0x3d, 0xb0, 0xb8, 0xad, 0xc1, 0x0b, 0xe0, 0xde, - 0x62, 0xeb, 0x4a, 0xc1, 0xe1, 0x02, 0xe2, 0x14, 0x27, 0x20, 0x82, 0xf6, 0xfb, 0x12, 0xef, 0x15, 0xf4, 0x49, 0x3f, - 0x40, 0x30, 0xe4, 0xcf, 0x12, 0x70, 0xd7, 0xeb, 0xd5, 0x18, 0xdf, 0x4b, 0x21, 0xb8, 0x3e, 0xd3, 0x00, 0xb4, 0xe0, - 0x77, 0xf9, 0x58, 0x4e, 0xbf, 0x89, 0xc0, 0xb3, 0x65, 0x6f, 0xa2, 0xdc, 0x6d, 0x78, 0xda, 0x3f, 0x5a, 0x08, 0xc0, - 0x52, 0x3c, 0x53, 0x82, 0x05, 0x39, 0xc5, 0x5c, 0xfc, 0xbf, 0xe0, 0x23, 0xe6, 0x7b, 0xd2, 0x45, 0x6c, 0xbd, 0x7d, - 0x72, 0x61, 0x20, 0x81, 0xa6, 0x03, 0xf0, 0xe3, 0x55, 0x40, 0x57, 0xc6, 0xcf, 0xcf, 0xb2, 0x1e, 0xeb, 0xe3, 0x3f, - 0x05, 0xf7, 0xe9, 0x67, 0x0a, 0x1f, 0x1d, 0x8e, 0xab, 0x74, 0xb4, 0xa3, 0x14, 0x44, 0x47, 0xb7, 0xcf, 0xa7, 0x3c, - 0xfb, 0xa6, 0x02, 0x72, 0xcb, 0x51, 0x7b, 0x2a, 0x00, 0x8b, 0x2d, 0x1d, 0x81, 0x4f, 0xb3, 0x7c, 0x42, 0xbe, 0xd7, - 0x53, 0x71, 0x75, 0xa9, 0xd3, 0xc5, 0x8b, 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, 0x75, 0x8d, 0x82, 0x95, 0x80, 0x33, 0xed, 0x1a, 0x0c, 0x36, 0xb0, - 0x6e, 0x59, 0x06, 0x7f, 0xc3, 0x35, 0x4d, 0xe0, 0x86, 0x45, 0xd6, 0x7b, 0x83, 0xad, 0x74, 0x0d, 0x8e, 0x96, 0x89, - 0x73, 0x29, 0xc9, 0xca, 0x16, 0x19, 0x57, 0x8f, 0x42, 0xaa, 0xa6, 0xfb, 0x5b, 0x51, 0x3f, 0x08, 0x91, 0x07, 0xab, - 0x94, 0x45, 0xc5, 0x0a, 0x64, 0xf6, 0xe0, 0x1f, 0x21, 0x23, 0x47, 0x39, 0x70, 0x14, 0xfa, 0x5b, 0x13, 0xe8, 0x3c, - 0x3f, 0x85, 0x3a, 0x8f, 0x04, 0x5b, 0xa9, 0x87, 0xc2, 0xca, 0x0b, 0x88, 0x0e, 0xb6, 0x30, 0x56, 0x79, 0x12, 0x2a, - 0x36, 0x65, 0x22, 0x8f, 0x83, 0x5a, 0x02, 0xc6, 0x0a, 0x82, 0x39, 0xcb, 0xa5, 0x0b, 0x52, 0xd5, 0xe8, 0x61, 0x91, - 0xb9, 0x9f, 0x0a, 0xca, 0xff, 0x54, 0xe5, 0x84, 0xeb, 0xcb, 0x10, 0xe0, 0x68, 0x9f, 0x82, 0x28, 0x31, 0xd6, 0x2f, - 0x5a, 0xbc, 0x93, 0x99, 0xb3, 0xa9, 0xed, 0x25, 0xc8, 0xd8, 0x0e, 0xbf, 0x42, 0x68, 0xb5, 0x50, 0x64, 0xd1, 0x70, - 0xc1, 0x74, 0x7b, 0x4a, 0xab, 0xee, 0x61, 0xc3, 0xb3, 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, 0x69, - 0x34, 0x9f, 0xe5, 0x73, 0x1f, 0x15, 0x17, 0x93, 0xc1, 0x60, 0xe3, 0x67, 0xc3, 0x21, 0x4b, 0x86, 0xc3, 0x49, 0xf6, - 0x14, 0x5e, 0x7b, 0xca, 0x23, 0xb5, 0xa4, 0x92, 0xab, 0x0c, 0xf6, 0xf7, 0x01, 0x8f, 0x7c, 0xd6, 0xf9, 0x69, 0xd9, - 0x74, 0xe9, 0x7e, 0x66, 0xc7, 0x5d, 0xe8, 0x0e, 0xb0, 0xf1, 0xb6, 0x41, 0x47, 0xfe, 0xf5, 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, 0x07, 0xf7, 0x85, 0x15, 0x05, - 0xfe, 0xdf, 0xb2, 0x05, 0xbb, 0x97, 0xc7, 0xc0, 0x35, 0x3a, 0x26, 0xc1, 0x05, 0xe2, 0x9e, 0xdd, 0x82, 0x1d, 0x16, - 0xfe, 0x82, 0xeb, 0xe4, 0x98, 0xed, 0xf0, 0x51, 0xe8, 0x15, 0xec, 0xd6, 0x27, 0xa0, 0x5d, 0xb0, 0x35, 0x40, 0x36, - 0xb6, 0xc5, 0x47, 0x77, 0x87, 0xc3, 0xb5, 0xe7, 0xb3, 0x07, 0xfc, 0x71, 0x7e, 0x77, 0x38, 0xec, 0x3c, 0xa3, 0xde, - 0xbb, 0xe1, 0x09, 0x7b, 0xcf, 0x93, 0xc9, 0xcd, 0x15, 0x8f, 0x27, 0x83, 0xc1, 0x8d, 0xbf, 0xe0, 0xf5, 0xec, 0x06, - 0xb4, 0x03, 0xe7, 0x0b, 0xa9, 0x6b, 0xf6, 0x6e, 0x79, 0xe6, 0x2d, 0x70, 0x6c, 0x6e, 0xe1, 0xe8, 0xed, 0xf7, 0xbd, - 0x3b, 0x1e, 0x79, 0xb7, 0xa4, 0x62, 0x5a, 0x71, 0xc5, 0xf1, 0xb6, 0xc5, 0xfd, 0x74, 0xc5, 0x43, 0x78, 0x84, 0x55, - 0x99, 0xde, 0x04, 0xef, 0x7d, 0xb6, 0xd2, 0x2c, 0x70, 0x0f, 0x98, 0x63, 0x4d, 0x76, 0x42, 0x33, 0xf1, 0x57, 0xd8, - 0x3f, 0x37, 0xaa, 0x7f, 0x68, 0xfe, 0x97, 0xba, 0x9f, 0xc0, 0xed, 0x8b, 0x2c, 0x48, 0xec, 0x3d, 0xbf, 0x61, 0xf7, - 0xdc, 0xb0, 0xcd, 0x9e, 0x99, 0xb2, 0x4f, 0x94, 0x1a, 0x3f, 0x52, 0xea, 0xda, 0x32, 0xac, 0x64, 0xee, 0xbe, 0x8c, - 0xc0, 0xe1, 0x80, 0xfc, 0x74, 0x87, 0x38, 0x08, 0xad, 0x9b, 0xac, 0xe6, 0x8a, 0x72, 0x2e, 0xb4, 0x65, 0xe6, 0xe5, - 0xc0, 0x62, 0x96, 0x52, 0x68, 0x2c, 0x00, 0x10, 0x4c, 0x0a, 0xad, 0xbd, 0x97, 0x01, 0xe4, 0x04, 0x0d, 0x7f, 0x6c, - 0xae, 0x8a, 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, 0xa7, - 0xbc, 0x66, 0x82, 0xc8, 0x36, 0x2a, 0x7f, 0x52, 0xbc, 0x40, 0x32, 0x82, 0xe2, 0x69, 0xad, 0x32, 0x16, 0x86, 0x79, - 0xa0, 0x80, 0xbc, 0x7b, 0x77, 0xea, 0x5b, 0xfb, 0x63, 0xc7, 0x9e, 0xad, 0x55, 0xa8, 0x85, 0x9a, 0xc2, 0x25, 0x87, - 0xe8, 0x0a, 0x32, 0x50, 0xc8, 0x78, 0xf2, 0x7a, 0x70, 0x39, 0x89, 0xae, 0xb8, 0x40, 0x67, 0x7c, 0x7d, 0xd3, 0x4d, - 0x67, 0xd1, 0xd3, 0x6a, 0x3e, 0x21, 0x25, 0xd9, 0xe1, 0x90, 0x8d, 0xaa, 0xba, 0x58, 0x4f, 0x43, 0xf9, 0xd3, 0x43, - 0xf0, 0xf5, 0x82, 0x7a, 0x4d, 0x56, 0xa9, 0x7e, 0x4a, 0x95, 0xf2, 0xa2, 0xe1, 0xa5, 0xff, 0xb4, 0x92, 0xfb, 0x1e, - 0x90, 0xd6, 0xf2, 0x92, 0xcb, 0xf7, 0x23, 0xc4, 0x18, 0xf1, 0x03, 0xaf, 0xe4, 0x11, 0x0b, 0xd5, 0x14, 0xae, 0x79, - 0x84, 0x20, 0x6f, 0x99, 0x0e, 0xfe, 0xd6, 0x13, 0xa7, 0xfb, 0x13, 0xa5, 0x5d, 0x7c, 0x61, 0x51, 0xf7, 0x64, 0x6d, - 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, 0xf9, 0xb0, 0xe1, 0x11, 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, 0xfb, 0xb9, 0x80, 0x20, 0x88, 0x92, 0x78, 0x7c, 0xc0, 0xfb, 0xb2, 0x1a, 0x6a, 0x94, 0x7c, 0x2c, - 0x1b, 0xa9, 0xf4, 0x4a, 0xf4, 0x77, 0x63, 0x2e, 0x31, 0xe0, 0x75, 0xd5, 0x16, 0x14, 0xce, 0xf3, 0xc3, 0xe1, 0x3c, - 0x1f, 0x19, 0xcf, 0x32, 0x50, 0xad, 0x4c, 0xeb, 0x20, 0x36, 0xf3, 0xc5, 0xc2, 0x5f, 0xec, 0x9c, 0x44, 0x44, 0x41, - 0x60, 0x47, 0xc2, 0x83, 0x48, 0xfd, 0xaa, 0xf2, 0x74, 0xa7, 0xfa, 0x6c, 0xbf, 0xb0, 0x89, 0xf4, 0x82, 0x92, 0xc9, - 0x27, 0xc1, 0x5e, 0xf5, 0x77, 0x10, 0x36, 0x84, 0x37, 0xaf, 0x7a, 0x9d, 0x65, 0x6a, 0x56, 0x82, 0x84, 0x19, 0x73, - 0x04, 0x8f, 0xc3, 0x4e, 0x63, 0x1b, 0x1e, 0x5b, 0x70, 0x74, 0xde, 0x9a, 0xdd, 0xb1, 0x15, 0xbb, 0x55, 0x75, 0x5a, - 0xf0, 0x70, 0x3a, 0xbc, 0x0c, 0x70, 0xf5, 0xad, 0xcf, 0x39, 0xbf, 0xa3, 0x13, 0x6c, 0x3d, 0xe0, 0xd1, 0x44, 0xcc, - 0xd6, 0x4f, 0x23, 0xb5, 0x78, 0xd6, 0x43, 0xbe, 0xa0, 0xf5, 0x27, 0x66, 0x77, 0x26, 0xf9, 0x6e, 0xc0, 0x17, 0x93, - 0xf5, 0xd3, 0x08, 0x5e, 0x7d, 0x0a, 0x56, 0x8c, 0xcc, 0x99, 0x65, 0xeb, 0xa7, 0x11, 0x8e, 0xd9, 0xdd, 0xd3, 0x88, - 0x46, 0x6d, 0x25, 0xf7, 0xa5, 0xdb, 0x06, 0x84, 0x95, 0x5b, 0x16, 0xc3, 0x6b, 0x20, 0x9e, 0x69, 0x23, 0xe9, 0x5a, - 0x1a, 0x7a, 0x63, 0x1e, 0x4e, 0xe3, 0x60, 0x4d, 0xad, 0x90, 0x67, 0x86, 0x98, 0xc5, 0x4f, 0xa3, 0x39, 0x5b, 0x61, - 0x45, 0x36, 0x3c, 0x1e, 0x5c, 0x4e, 0x36, 0x57, 0x7c, 0x0d, 0xe4, 0x67, 0x93, 0x8d, 0xd9, 0xa2, 0x6e, 0xb9, 0x98, - 0x6d, 0x9e, 0x46, 0xf3, 0xc9, 0x0a, 0x7a, 0xd6, 0x1e, 0x30, 0xef, 0x0d, 0x88, 0x50, 0x12, 0x52, 0x53, 0x6e, 0x7a, - 0x3d, 0xb6, 0x1e, 0x07, 0x77, 0x6c, 0x7d, 0x19, 0xdc, 0xb2, 0xf5, 0x18, 0x88, 0x38, 0xa8, 0xdf, 0xbd, 0x0d, 0x2c, - 0xbe, 0x88, 0xad, 0x2f, 0x4d, 0xda, 0xe6, 0x69, 0xc4, 0xdc, 0xc1, 0x69, 0xe0, 0x82, 0xb5, 0xc9, 0xbc, 0x15, 0x83, - 0x4b, 0xc8, 0xd2, 0x8b, 0xd9, 0x66, 0x78, 0xc9, 0xd6, 0x23, 0x9c, 0xea, 0x89, 0xcf, 0xee, 0xf8, 0x2d, 0x4b, 0xf8, - 0xaa, 0x89, 0xaf, 0x36, 0xa0, 0x11, 0x3d, 0xca, 0xa0, 0xaf, 0xa0, 0x66, 0xe6, 0xbc, 0xb2, 0x30, 0x2a, 0xf7, 0x2d, - 0x38, 0xa0, 0x20, 0x6d, 0x03, 0x04, 0x49, 0x3c, 0xbb, 0x57, 0xe1, 0xfa, 0x46, 0x0a, 0x03, 0x6e, 0x02, 0x33, 0x60, - 0x60, 0xfa, 0x19, 0xfc, 0xb0, 0xd2, 0x25, 0x42, 0x9c, 0xfd, 0x94, 0x92, 0x64, 0x9e, 0x9f, 0x8a, 0x34, 0x77, 0x0b, - 0xd7, 0x29, 0xcc, 0x8a, 0x02, 0xd5, 0x4f, 0x49, 0x69, 0x60, 0xa1, 0x12, 0x99, 0x4a, 0xc1, 0x2f, 0x9b, 0xf3, 0x28, - 0x3b, 0x46, 0xe7, 0x3a, 0xbf, 0x9c, 0x38, 0xa7, 0x93, 0xbe, 0xff, 0xc0, 0x31, 0x6c, 0x21, 0x03, 0x17, 0xfe, 0xd4, - 0x13, 0xc6, 0xa9, 0x15, 0x88, 0xa9, 0xe4, 0xd9, 0x53, 0xf8, 0x4c, 0x68, 0x75, 0x74, 0xe1, 0xfb, 0x41, 0xa1, 0x4d, - 0xd2, 0x2d, 0x48, 0x52, 0xf0, 0x14, 0x3d, 0xe7, 0xbc, 0x0d, 0x54, 0x8a, 0x11, 0x2d, 0x88, 0xb4, 0xb5, 0xcc, 0x1c, - 0xa4, 0x2d, 0xcd, 0x77, 0x4d, 0xfc, 0x1c, 0x16, 0x70, 0x11, 0x2d, 0x6c, 0x0d, 0x8f, 0xaa, 0x58, 0xb9, 0x37, 0x79, - 0x8e, 0x70, 0x46, 0x97, 0x32, 0x01, 0x70, 0xbd, 0x5f, 0x87, 0xb5, 0xc2, 0x2b, 0x6a, 0x16, 0x79, 0x51, 0xd3, 0x27, - 0x5b, 0xe0, 0x3e, 0x16, 0x25, 0x0a, 0x9c, 0xb5, 0x60, 0xc0, 0x56, 0x58, 0xb2, 0x93, 0xc2, 0xa6, 0x68, 0x09, 0xbd, - 0x3d, 0x7e, 0x3a, 0xa8, 0x99, 0x0c, 0xa0, 0x09, 0xa0, 0xf1, 0xf8, 0x17, 0x80, 0x9a, 0xde, 0xd4, 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, 0x83, 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, 0x8b, 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, 0xb5, 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, 0x4e, 0x6e, 0x61, 0xcb, 0x4c, - 0x56, 0xf3, 0x7d, 0xc5, 0x1d, 0x94, 0x6f, 0xb6, 0xce, 0xf8, 0x5e, 0x22, 0x7b, 0xb7, 0x81, 0x12, 0x5e, 0x8c, 0xfe, - 0x82, 0xf4, 0xdb, 0x0c, 0xe3, 0x94, 0xdb, 0x4a, 0x5a, 0x80, 0xd3, 0x3f, 0x1c, 0xde, 0x57, 0x18, 0x34, 0x38, 0xc2, - 0x38, 0xb2, 0x7e, 0xff, 0xb6, 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, 0x9f, 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, 0x3a, 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, 0xeb, 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, 0x4f, 0x9f, - 0x03, 0x69, 0x59, 0xbf, 0x1f, 0xbd, 0xb8, 0x9c, 0x3e, 0x1f, 0x46, 0x01, 0x38, 0x76, 0xd9, 0xcb, 0xcb, 0x98, 0xaf, - 0x2e, 0x99, 0x65, 0x0a, 0x8b, 0x7c, 0x33, 0xa0, 0xba, 0x64, 0xb5, 0x74, 0xbd, 0x02, 0x2c, 0x5d, 0x7e, 0xf3, 0x10, - 0xa6, 0x06, 0x34, 0xb2, 0xe6, 0xee, 0x34, 0xd7, 0x02, 0xa5, 0x9e, 0xf7, 0x33, 0x43, 0xbe, 0x2e, 0x83, 0xae, 0x20, - 0xdd, 0xf3, 0x88, 0xf4, 0x72, 0x2f, 0x9d, 0xee, 0xf7, 0xa5, 0x00, 0x4b, 0x7d, 0x29, 0x3e, 0x83, 0xc2, 0xa2, 0xf1, - 0x8d, 0x00, 0x6d, 0x0d, 0xd5, 0xb4, 0x57, 0x8a, 0xaa, 0x17, 0xf4, 0x4a, 0xf1, 0xb9, 0xa7, 0x87, 0xca, 0x7c, 0x59, - 0x3a, 0xfa, 0x9f, 0x50, 0x73, 0xc1, 0x09, 0x31, 0x13, 0x73, 0x00, 0x95, 0xa0, 0x8d, 0x6f, 0x75, 0xb4, 0xf1, 0xa9, - 0x5e, 0xc5, 0x4d, 0x9f, 0xd7, 0xd6, 0x32, 0x27, 0x84, 0x4d, 0xf7, 0x12, 0xa0, 0x22, 0xaf, 0x84, 0x47, 0xb0, 0xfc, - 0xf2, 0x87, 0x3c, 0x5d, 0x21, 0x5a, 0xc7, 0x3d, 0xcb, 0x5c, 0x1a, 0xfb, 0x37, 0x06, 0xd3, 0xd7, 0xb7, 0xdb, 0x22, - 0x3f, 0x35, 0x31, 0x61, 0x3d, 0x56, 0xf4, 0xcd, 0xbb, 0x70, 0x25, 0x50, 0xe0, 0x50, 0x22, 0xb1, 0x4d, 0x15, 0x8a, - 0x78, 0x90, 0xf4, 0xe9, 0xa2, 0xf5, 0x69, 0x80, 0xa9, 0xb5, 0x1c, 0x98, 0x43, 0xb8, 0x8a, 0x0b, 0x1f, 0x3d, 0x7d, - 0x8b, 0x59, 0x38, 0x9f, 0x78, 0x1f, 0xbd, 0x62, 0x64, 0x3e, 0xee, 0xa3, 0x52, 0x49, 0xff, 0x3c, 0x1c, 0x66, 0xd5, - 0xdc, 0x77, 0xe8, 0x23, 0x3d, 0x54, 0xb9, 0xa0, 0xec, 0x8d, 0x31, 0x89, 0x40, 0x69, 0x8c, 0xf7, 0x71, 0x70, 0x9c, - 0xf7, 0x69, 0x00, 0xa9, 0x7d, 0xe2, 0x3d, 0x29, 0x39, 0x3c, 0xe7, 0x98, 0x13, 0x4a, 0x2b, 0xc2, 0x2a, 0xbe, 0xc8, - 0x50, 0xae, 0x3b, 0xa5, 0x60, 0x92, 0x43, 0x82, 0xe1, 0xaf, 0x9a, 0x37, 0xb1, 0x02, 0x61, 0xd7, 0xcc, 0xab, 0xd1, - 0x93, 0x2a, 0x09, 0x4b, 0x01, 0x47, 0x65, 0xe6, 0x19, 0xf6, 0x86, 0x27, 0x86, 0x91, 0x83, 0xe5, 0xfe, 0xa8, 0x4e, - 0x44, 0xee, 0xd1, 0x05, 0x46, 0x65, 0xe1, 0x79, 0x43, 0x57, 0x1a, 0x54, 0x92, 0x1d, 0x7f, 0xc5, 0x35, 0xa0, 0xb6, - 0xc6, 0x88, 0xa1, 0x80, 0x51, 0xf0, 0xda, 0xfe, 0x10, 0xb2, 0x28, 0x5b, 0xbf, 0xc1, 0x31, 0x9f, 0x95, 0xdc, 0xf5, - 0x0e, 0x67, 0xa1, 0x25, 0xe4, 0xc9, 0x1d, 0x83, 0x34, 0x8d, 0xa5, 0x11, 0x70, 0x22, 0x92, 0x6d, 0x2c, 0x85, 0x23, - 0x80, 0x80, 0x40, 0x37, 0x65, 0x86, 0x31, 0x1d, 0x8c, 0x3c, 0x4f, 0x7a, 0xc6, 0x7b, 0x15, 0x9e, 0x42, 0x9a, 0x6c, - 0x5f, 0xcf, 0xdf, 0x1b, 0x41, 0x56, 0x6e, 0x39, 0xc7, 0xc3, 0xe2, 0x1b, 0x67, 0x5f, 0xe5, 0xe4, 0x29, 0x66, 0x19, - 0xe9, 0x9d, 0x62, 0x5e, 0xc0, 0x9f, 0xca, 0x52, 0x9f, 0xa3, 0xf4, 0x96, 0xf9, 0x64, 0x15, 0x49, 0x97, 0xde, 0xa6, - 0xdf, 0x8f, 0x47, 0xea, 0x50, 0xf3, 0xf7, 0xf1, 0x48, 0x9e, 0x61, 0x1b, 0x96, 0xb0, 0xd0, 0x2a, 0x18, 0x03, 0x48, - 0x62, 0x23, 0xa2, 0xc1, 0x68, 0x6f, 0x0e, 0x87, 0xf3, 0x8d, 0x39, 0x4b, 0xf6, 0xe0, 0xfa, 0xca, 0x13, 0xf3, 0x0e, - 0x7c, 0x99, 0xc7, 0x04, 0x11, 0x9b, 0x79, 0x1b, 0x56, 0x83, 0x07, 0x3b, 0xb8, 0x3e, 0x62, 0x8b, 0x62, 0xad, 0x63, - 0xa9, 0xac, 0x83, 0xd3, 0x3a, 0x36, 0xcd, 0x48, 0x29, 0xb2, 0xcf, 0xb1, 0xbf, 0x77, 0x83, 0xab, 0x6b, 0x63, 0x50, - 0x6b, 0xdc, 0x61, 0xee, 0x9c, 0x0a, 0xa8, 0xc7, 0x74, 0x05, 0xd5, 0xb3, 0x9c, 0x7c, 0xf9, 0xad, 0x9d, 0x03, 0x82, - 0x46, 0x20, 0x70, 0xd1, 0x40, 0xab, 0x76, 0x29, 0xe7, 0x5d, 0x40, 0x88, 0x6f, 0x52, 0xd0, 0xa7, 0x33, 0xd8, 0xc4, - 0xe6, 0x13, 0x88, 0x45, 0xd3, 0x7d, 0xae, 0x35, 0xf3, 0xc5, 0x88, 0x76, 0x66, 0xdd, 0x2d, 0x72, 0xab, 0x85, 0x48, - 0x46, 0xcf, 0x36, 0x13, 0x2e, 0x3a, 0x94, 0x33, 0x12, 0x30, 0x41, 0x6b, 0x2b, 0x25, 0x9f, 0xeb, 0x5e, 0x27, 0x68, - 0x0f, 0x24, 0xad, 0xfb, 0x37, 0x8b, 0xce, 0x28, 0x39, 0xb9, 0xde, 0xe4, 0x0c, 0x52, 0xb0, 0x60, 0x7b, 0x99, 0x13, - 0x6e, 0x80, 0x4f, 0x6c, 0x96, 0x9c, 0xa6, 0x41, 0x1e, 0x0b, 0xe3, 0x91, 0xd7, 0xe6, 0x97, 0x05, 0x74, 0x28, 0x59, - 0x34, 0x42, 0x3c, 0xc0, 0xce, 0x21, 0xb9, 0x2a, 0x50, 0x37, 0x0d, 0x74, 0xe5, 0xca, 0x99, 0x62, 0x0a, 0x5c, 0x08, - 0x05, 0x51, 0x3b, 0x3a, 0x89, 0xca, 0x79, 0x9f, 0x54, 0x97, 0xf9, 0xb4, 0x90, 0xa6, 0x81, 0x7c, 0x5a, 0x39, 0xe6, - 0x81, 0x9d, 0x6d, 0x5c, 0x13, 0x18, 0xe8, 0xd4, 0xbe, 0x16, 0xe5, 0x1c, 0xab, 0x88, 0xde, 0xe7, 0x1f, 0x2a, 0x7b, - 0xfa, 0x20, 0xc2, 0x46, 0x05, 0x1a, 0x4b, 0x89, 0xb1, 0x91, 0xe3, 0xdf, 0x12, 0x65, 0x43, 0x86, 0x80, 0x10, 0xd2, - 0x46, 0x4e, 0x3f, 0xac, 0x2f, 0x6f, 0x33, 0xed, 0xff, 0x49, 0xe2, 0xb7, 0xc1, 0x5e, 0x4e, 0xfd, 0xa9, 0x47, 0x3c, - 0x5e, 0x6b, 0xf4, 0x98, 0x92, 0x6e, 0x83, 0x3c, 0x55, 0x9e, 0x82, 0x64, 0xc2, 0x58, 0x42, 0xb0, 0x28, 0x17, 0x3c, - 0xe7, 0x15, 0x97, 0x70, 0x1f, 0xb5, 0xac, 0x88, 0x50, 0x95, 0xc8, 0xe9, 0xf3, 0x15, 0xf0, 0x4c, 0x40, 0xa0, 0x63, - 0x8c, 0x34, 0xaa, 0xe0, 0x4b, 0x60, 0xac, 0x03, 0x65, 0xa7, 0x19, 0x09, 0x2e, 0xbb, 0x37, 0x48, 0x94, 0xfa, 0x9a, - 0x94, 0xa4, 0xd7, 0xa2, 0xc6, 0x2b, 0xb1, 0x8a, 0x48, 0x20, 0x43, 0x0d, 0x11, 0xab, 0xea, 0xa9, 0x7b, 0x55, 0x4c, - 0x06, 0x83, 0xca, 0x97, 0xd3, 0x13, 0x6f, 0x68, 0xa8, 0xbc, 0xeb, 0x8a, 0x76, 0x7a, 0xa2, 0x95, 0xf2, 0x16, 0xd2, - 0x12, 0x34, 0x0d, 0x23, 0xcd, 0xa1, 0xd4, 0x95, 0x74, 0x37, 0x06, 0xf1, 0x25, 0x13, 0x3d, 0xdb, 0xa9, 0x1d, 0xa5, - 0x2d, 0x69, 0x0f, 0x21, 0x3d, 0x77, 0xc9, 0xc7, 0x2c, 0xe4, 0xea, 0x4e, 0x39, 0x29, 0xaf, 0x42, 0x74, 0x72, 0xdf, - 0x63, 0x48, 0x04, 0xfa, 0x9c, 0x63, 0x58, 0x17, 0x0d, 0x75, 0x0e, 0x2b, 0xc4, 0x6c, 0xa1, 0x84, 0xf9, 0x92, 0xf1, - 0x54, 0x32, 0x68, 0x00, 0x64, 0xc0, 0x67, 0x2f, 0x03, 0xcb, 0x5f, 0x41, 0xfc, 0x68, 0xe3, 0xc3, 0xe1, 0xcf, 0x9a, - 0x42, 0x6c, 0xff, 0x84, 0xcd, 0x10, 0x1e, 0xd5, 0x03, 0x9e, 0xf9, 0x26, 0x4e, 0xd0, 0x0a, 0x48, 0xca, 0xec, 0x68, - 0x22, 0x7b, 0xd5, 0x43, 0x38, 0x95, 0x15, 0xa8, 0xa3, 0xac, 0xb3, 0x12, 0x7e, 0x84, 0xa9, 0x6e, 0x25, 0xd6, 0x02, - 0x6d, 0xae, 0x56, 0xac, 0x05, 0x70, 0xe0, 0xe7, 0x10, 0x3c, 0x91, 0xcf, 0xc1, 0xc5, 0xa0, 0x00, 0x9f, 0x03, 0xe0, - 0x45, 0xee, 0xc2, 0x83, 0x79, 0x64, 0x59, 0x8d, 0x30, 0x1c, 0x55, 0xc4, 0xfa, 0x35, 0xdb, 0x91, 0x0f, 0xdc, 0x8e, - 0xf1, 0xb9, 0xf6, 0x58, 0xb2, 0x1c, 0x8c, 0x32, 0xf7, 0x6a, 0x89, 0x9e, 0x37, 0x69, 0xdc, 0x8c, 0x9e, 0xec, 0x6b, - 0xf9, 0xbf, 0xa0, 0x97, 0x41, 0x7f, 0x0b, 0xb7, 0xbc, 0xe6, 0x77, 0x0b, 0x22, 0xcd, 0xf4, 0x0a, 0x22, 0x65, 0xd4, - 0x88, 0x8c, 0x21, 0x6c, 0x52, 0xdd, 0xdc, 0x26, 0xd5, 0x85, 0x80, 0xa7, 0x23, 0x52, 0x5d, 0x0b, 0x69, 0x23, 0x9f, - 0xd6, 0x81, 0x8c, 0x45, 0x7a, 0xf7, 0xc3, 0xdf, 0x5e, 0x7e, 0x7a, 0xfb, 0xcb, 0x0f, 0x8b, 0xb7, 0xef, 0xde, 0xbc, - 0x7d, 0xf7, 0xf6, 0xd3, 0x6f, 0x04, 0xe1, 0x31, 0x15, 0x2a, 0xc3, 0x87, 0xf7, 0x37, 0x6f, 0x9d, 0x0c, 0xb6, 0x37, - 0x43, 0xd6, 0xbe, 0x91, 0x83, 0x21, 0x10, 0xd9, 0x20, 0x64, 0x90, 0x9d, 0xda, 0xf6, 0x67, 0x62, 0x8e, 0xb1, 0x77, - 0x02, 0x93, 0x2d, 0xe0, 0x1c, 0xcb, 0xbc, 0x64, 0x44, 0xae, 0x0a, 0xad, 0x1f, 0xd0, 0x82, 0x6b, 0x70, 0x91, 0x49, - 0xf3, 0xbb, 0x5f, 0x08, 0x62, 0x9f, 0x56, 0x52, 0xee, 0xab, 0x6d, 0xcd, 0xf3, 0xed, 0xfd, 0x5e, 0xc2, 0xf9, 0xcf, - 0xa5, 0x11, 0xb5, 0x00, 0x07, 0xe0, 0x73, 0xf8, 0xe3, 0x4a, 0x5b, 0xd2, 0x64, 0x16, 0xed, 0x67, 0x0c, 0x41, 0x97, - 0x06, 0x1f, 0xc4, 0x1e, 0x79, 0xa9, 0x4f, 0x16, 0x12, 0xb8, 0x23, 0x86, 0x4f, 0x2b, 0x82, 0x5e, 0x31, 0xa2, 0xb8, - 0xe4, 0x0a, 0x95, 0x52, 0xf2, 0x6f, 0x94, 0x5d, 0x54, 0xc8, 0x59, 0xc1, 0xee, 0x15, 0x39, 0x32, 0x7e, 0x10, 0x4c, - 0x7c, 0x39, 0xb8, 0xff, 0x12, 0xef, 0x70, 0xa6, 0x38, 0x92, 0x13, 0xfe, 0x90, 0x61, 0x60, 0x7f, 0x0e, 0x3e, 0xaf, - 0x0e, 0xf3, 0xf2, 0x46, 0x9f, 0x72, 0x4b, 0x3e, 0x9e, 0x2c, 0xaf, 0xc0, 0x60, 0xbf, 0x54, 0xcd, 0x5d, 0xf3, 0x7a, - 0xb6, 0x9c, 0xb3, 0xfd, 0x2c, 0x9a, 0x07, 0x77, 0x6c, 0x96, 0xcd, 0x83, 0x55, 0xc3, 0xd7, 0xec, 0x96, 0xaf, 0xad, - 0xaa, 0xad, 0xed, 0xaa, 0x4d, 0x36, 0xfc, 0x16, 0x24, 0x84, 0x9b, 0xcc, 0x03, 0xde, 0xe3, 0x3b, 0x9f, 0x6d, 0x40, - 0xa2, 0x5d, 0xb1, 0x0d, 0x5c, 0xc4, 0xd6, 0xfc, 0x87, 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, 0x7d, 0x5a, 0x6d, 0xc2, - 0x0c, 0x3d, 0xcb, 0xe1, 0xa3, 0xad, 0x14, 0xfc, 0xf4, 0x02, 0xbf, 0x64, 0x47, 0x6d, 0xa5, 0x6d, 0xbb, 0x2a, 0xb1, - 0x15, 0xb4, 0x28, 0xb2, 0x5a, 0xe1, 0x81, 0x39, 0x7f, 0x01, 0x0b, 0x18, 0x7b, 0x8e, 0x73, 0x5e, 0xfb, 0x23, 0x64, - 0xbc, 0x77, 0x00, 0xd0, 0x32, 0xc7, 0x01, 0x1e, 0xb1, 0x62, 0x14, 0x0d, 0xde, 0xf9, 0xa5, 0xb2, 0x5a, 0x69, 0x4e, - 0x42, 0xdb, 0x88, 0x55, 0xcb, 0x91, 0xaa, 0x19, 0x91, 0x3e, 0x48, 0xcf, 0xfb, 0x1e, 0x51, 0x0d, 0xf6, 0x64, 0x5e, - 0x07, 0xf6, 0xe9, 0x55, 0x6b, 0x55, 0x77, 0x7e, 0x4f, 0x95, 0x2e, 0x39, 0xb2, 0xe5, 0xa7, 0xcb, 0xf0, 0x41, 0xfd, - 0x29, 0xb9, 0x3e, 0x14, 0x38, 0xc2, 0x63, 0x15, 0x70, 0xbe, 0x5e, 0x89, 0x76, 0x27, 0xc2, 0xae, 0x5c, 0x02, 0x42, - 0x7c, 0x49, 0xd3, 0x1c, 0x8f, 0x23, 0x9a, 0x88, 0xb0, 0x89, 0xd1, 0x5f, 0xd8, 0x7d, 0x28, 0xb1, 0x9c, 0xe7, 0x1a, - 0x94, 0x5c, 0x32, 0x78, 0x4f, 0xda, 0x6b, 0xd0, 0x2c, 0xaf, 0x4a, 0x4d, 0x26, 0x72, 0x50, 0x3e, 0x1c, 0x0a, 0xd8, - 0x4b, 0x8d, 0x9f, 0x26, 0xfc, 0x84, 0xe5, 0xad, 0xbd, 0x35, 0xa5, 0xa8, 0xa4, 0x01, 0x2a, 0xf0, 0x31, 0x83, 0xff, - 0xdd, 0x19, 0x62, 0xc1, 0x14, 0x1d, 0x3f, 0x9c, 0x89, 0xb9, 0xf5, 0xdc, 0x2a, 0xeb, 0x28, 0x5b, 0xa3, 0x9c, 0x80, - 0x7f, 0x4b, 0x75, 0x9c, 0x24, 0xc2, 0xa9, 0xf7, 0x88, 0x8b, 0xba, 0x97, 0x43, 0xd4, 0x0d, 0x7b, 0x5b, 0xe9, 0x60, - 0xcb, 0x69, 0x1a, 0x1c, 0x89, 0x5f, 0xa9, 0xcf, 0xde, 0x67, 0x16, 0x8f, 0x3a, 0xb2, 0x11, 0x25, 0x69, 0x1c, 0x8b, - 0x1c, 0xb6, 0xf7, 0x85, 0xdc, 0xff, 0xfb, 0x7d, 0x08, 0x27, 0xad, 0x82, 0xa4, 0xf4, 0x04, 0x22, 0xc2, 0xd1, 0xe1, - 0x47, 0x84, 0x27, 0x52, 0x55, 0xf8, 0xa4, 0x3e, 0x71, 0x63, 0x76, 0x2f, 0xcc, 0x51, 0xbd, 0x05, 0x18, 0xc6, 0x7a, - 0x6b, 0x11, 0x92, 0x68, 0xa5, 0x19, 0x6d, 0x3d, 0x20, 0x46, 0xbc, 0x5f, 0x5b, 0x64, 0x30, 0xd6, 0x96, 0x44, 0x02, - 0xf8, 0x1d, 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, 0xeb, 0xa3, 0x74, 0x92, 0x58, 0xdf, - 0x77, 0x95, 0x0a, 0x36, 0x9b, 0x1b, 0xd4, 0x97, 0x1d, 0x25, 0xbf, 0x02, 0x27, 0x1d, 0x27, 0x59, 0xe4, 0x20, 0x6a, - 0x51, 0x39, 0x37, 0x49, 0x58, 0xda, 0xd5, 0xa9, 0x36, 0xeb, 0x75, 0x51, 0xd6, 0xd5, 0x6b, 0x11, 0x29, 0x7a, 0x1f, - 0xf5, 0xe8, 0x89, 0x84, 0x54, 0x68, 0x55, 0x6a, 0x97, 0x47, 0xe0, 0xb6, 0xa9, 0x15, 0xdb, 0x72, 0x09, 0x4b, 0xd4, - 0xf8, 0x4f, 0xd0, 0x47, 0xb9, 0x78, 0x90, 0x01, 0x1a, 0x1d, 0x4f, 0xcd, 0x5b, 0x8f, 0xbc, 0x72, 0x94, 0x5f, 0x5a, - 0x6d, 0xd2, 0x2f, 0x80, 0xcc, 0x68, 0xff, 0x68, 0x29, 0x81, 0xcc, 0xc0, 0x4c, 0x5a, 0x1a, 0x12, 0x39, 0x8a, 0x59, - 0x9a, 0xff, 0x81, 0x2b, 0xb6, 0x42, 0xa4, 0x61, 0x35, 0xf7, 0xf8, 0xcb, 0xca, 0xab, 0xe5, 0x5a, 0x66, 0x9a, 0x9b, - 0x25, 0x8e, 0x15, 0x8b, 0x8b, 0x7a, 0x5d, 0x89, 0x2c, 0x10, 0xe2, 0x08, 0xd3, 0x58, 0x4f, 0xbd, 0x51, 0x5a, 0x7d, - 0x40, 0x42, 0x99, 0x1f, 0xb0, 0xb7, 0x63, 0xaf, 0x07, 0x59, 0x88, 0x63, 0xcb, 0xc1, 0x66, 0xeb, 0x7d, 0x2a, 0x53, - 0x11, 0x9f, 0xd5, 0xc5, 0xd9, 0xa6, 0x12, 0x67, 0x75, 0x22, 0xce, 0xbe, 0x83, 0x9c, 0xdf, 0x9d, 0x51, 0xd1, 0x67, - 0x0f, 0x69, 0x9d, 0x14, 0x9b, 0x9a, 0x9e, 0xbc, 0xc1, 0x32, 0xbe, 0x3b, 0x23, 0xae, 0x9a, 0x33, 0x1a, 0xc9, 0x78, - 0x74, 0xf6, 0x21, 0x03, 0x92, 0xd7, 0xb3, 0x74, 0x05, 0x83, 0x77, 0x16, 0xe6, 0xf1, 0x59, 0x29, 0xee, 0xc0, 0xe2, - 0x54, 0x76, 0xbe, 0x07, 0x19, 0x56, 0xe1, 0x1f, 0xe2, 0x0c, 0xa0, 0x5d, 0xcf, 0xd2, 0xfa, 0x2c, 0xad, 0xce, 0xf2, - 0xa2, 0x3e, 0x53, 0x52, 0x38, 0x84, 0xf1, 0xc3, 0x7b, 0xfa, 0xca, 0x2e, 0x6f, 0xb3, 0xb8, 0xcb, 0x22, 0x7f, 0x8a, - 0x5e, 0x45, 0xc4, 0xa4, 0x51, 0x09, 0xaf, 0xdd, 0xdf, 0x36, 0xf7, 0x0f, 0xaf, 0x1b, 0xbb, 0x9f, 0xdd, 0x31, 0xa2, - 0x0b, 0xea, 0xf1, 0x4a, 0x52, 0x2a, 0x28, 0x20, 0x70, 0xa2, 0x59, 0xe3, 0xc1, 0x1d, 0x07, 0xbc, 0x1a, 0xd8, 0x92, - 0xad, 0x7d, 0xfe, 0x22, 0x96, 0x61, 0xda, 0x9b, 0x00, 0xff, 0x2a, 0x7b, 0xd3, 0x75, 0xb0, 0xc4, 0xfb, 0x16, 0xb2, - 0x0d, 0xbd, 0x7d, 0xcd, 0x5f, 0x7a, 0xb9, 0xfa, 0x9b, 0xfd, 0x13, 0x80, 0x30, 0x20, 0x66, 0xd5, 0x47, 0x13, 0xf7, - 0xce, 0xca, 0xb2, 0x73, 0xb2, 0xec, 0x7a, 0xe8, 0xd7, 0x24, 0x46, 0xa5, 0x95, 0xa5, 0x74, 0xb2, 0x94, 0x90, 0x05, - 0x7c, 0x62, 0x34, 0xb5, 0x11, 0x40, 0xd8, 0x8e, 0x52, 0xf9, 0x42, 0xe5, 0x45, 0x14, 0xce, 0x09, 0x9e, 0x27, 0x62, - 0x74, 0x6f, 0x25, 0x03, 0x86, 0x43, 0x08, 0xe6, 0xa0, 0x2d, 0xf6, 0x86, 0x6e, 0x22, 0xfe, 0x7a, 0x53, 0x94, 0x6f, - 0x63, 0xf2, 0x29, 0xd8, 0x9d, 0x7c, 0x5c, 0xc2, 0xe3, 0xf2, 0xe4, 0xe3, 0x10, 0x3d, 0x12, 0x4e, 0x3e, 0x06, 0xdf, - 0x23, 0x39, 0xaf, 0xbb, 0x1e, 0x27, 0xc8, 0x2d, 0xa4, 0xfb, 0xdb, 0x31, 0x09, 0xd0, 0xbc, 0x86, 0xe5, 0xa8, 0xa9, - 0xb8, 0x66, 0x66, 0x8c, 0xe7, 0x8d, 0xde, 0x1f, 0x3b, 0xde, 0x32, 0x85, 0x62, 0x16, 0xf3, 0x1a, 0x7e, 0xcf, 0xaa, - 0x40, 0xdd, 0xf5, 0x36, 0xc9, 0x2d, 0xb3, 0x7a, 0x8e, 0x76, 0xdf, 0xf7, 0x75, 0x22, 0xa8, 0xfd, 0x1d, 0xf6, 0x3c, - 0xb3, 0xde, 0x55, 0x31, 0x70, 0xa9, 0x92, 0x1d, 0x32, 0x55, 0x4d, 0x0f, 0x54, 0x4a, 0x83, 0xa7, 0x97, 0xd6, 0xe5, - 0x4b, 0xa5, 0x8d, 0x3c, 0xd3, 0xfc, 0x06, 0xf0, 0x62, 0xea, 0xb2, 0xd8, 0x7d, 0x75, 0x5f, 0xc1, 0x6d, 0xbc, 0xdf, - 0x5f, 0x56, 0x9e, 0xf9, 0x89, 0x0b, 0xc0, 0xde, 0x54, 0x68, 0x9d, 0x40, 0xa9, 0x61, 0x1d, 0xbe, 0x4a, 0x44, 0xf4, - 0x47, 0xbb, 0x5c, 0x67, 0xae, 0x03, 0x46, 0x14, 0xf1, 0xdb, 0x78, 0xf4, 0x07, 0x28, 0xae, 0x8d, 0x3d, 0x20, 0xac, - 0x43, 0x42, 0x9f, 0x11, 0x80, 0xd4, 0x63, 0x8e, 0x12, 0xd0, 0xac, 0x68, 0xee, 0x98, 0xfc, 0x5c, 0x5f, 0x29, 0xfd, - 0xfd, 0xb2, 0xf2, 0xc8, 0x9c, 0xd2, 0x36, 0xd3, 0x58, 0xad, 0xa9, 0x04, 0xc2, 0x2b, 0x2a, 0x59, 0x85, 0xcf, 0xe6, - 0x8d, 0xe8, 0xf7, 0xe5, 0x11, 0x9e, 0x56, 0x3f, 0x6c, 0x31, 0xbe, 0x15, 0x10, 0x8d, 0x04, 0x40, 0x3f, 0x01, 0xcc, - 0x8b, 0x6c, 0x66, 0xf7, 0x71, 0x40, 0x95, 0x12, 0x4d, 0xe3, 0x6c, 0x9e, 0xdf, 0xd2, 0x9b, 0xb2, 0x83, 0x4e, 0x9d, - 0x2a, 0x70, 0xc1, 0x55, 0xc9, 0x78, 0x65, 0x3d, 0x91, 0xcf, 0x6f, 0x6e, 0x37, 0x69, 0x16, 0xbf, 0x2f, 0xff, 0x89, - 0x63, 0xab, 0xeb, 0xf0, 0xc8, 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, 0x4d, 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, 0x1e, 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, 0x45, 0x85, 0x3a, 0x27, 0x96, 0xf1, 0x1a, 0x80, 0xb5, 0x73, 0xd5, 0xcf, - 0xb3, 0x1a, 0x3c, 0x69, 0x88, 0xcf, 0xc7, 0x68, 0x7b, 0x65, 0x73, 0x50, 0x6d, 0xa7, 0xb3, 0xf2, 0x8a, 0xe9, 0x72, - 0x60, 0xdc, 0x37, 0xbc, 0xa2, 0x38, 0xc3, 0x8f, 0x1e, 0x6c, 0x71, 0xfe, 0x74, 0x43, 0xed, 0xc7, 0xdc, 0xa8, 0x87, - 0x81, 0xd6, 0x82, 0x37, 0x05, 0xb1, 0xfe, 0x7e, 0xe8, 0xc8, 0xf6, 0x5e, 0x8b, 0x8c, 0x26, 0x9f, 0xfd, 0xfc, 0x43, - 0x99, 0xae, 0x52, 0xb8, 0x2f, 0x39, 0x59, 0x34, 0xf3, 0x10, 0xd8, 0x1b, 0x62, 0xb8, 0x3e, 0x2a, 0x3c, 0xa2, 0xac, - 0xdf, 0x87, 0xdf, 0x57, 0x19, 0x98, 0x62, 0xe0, 0xba, 0x42, 0x30, 0x1e, 0x02, 0x41, 0x3c, 0x4c, 0xa3, 0x93, 0x41, - 0x0d, 0xda, 0xf0, 0x0d, 0x40, 0x66, 0x80, 0x47, 0xe6, 0xd2, 0x23, 0xe0, 0x2e, 0x70, 0xed, 0xc9, 0x78, 0xec, 0x4f, - 0x4c, 0x43, 0xa3, 0xa6, 0x34, 0xd3, 0x73, 0xe3, 0x37, 0x1d, 0xd5, 0x72, 0xed, 0xfc, 0xc7, 0x97, 0xfc, 0x06, 0xbd, - 0xa0, 0xe5, 0xe5, 0x3e, 0x52, 0x97, 0xfb, 0x8c, 0xe2, 0x32, 0x91, 0x1c, 0x16, 0xc4, 0xb2, 0x84, 0x03, 0x8f, 0x51, - 0xc9, 0x62, 0x4b, 0x8f, 0x55, 0xd1, 0xf2, 0x45, 0xb9, 0x41, 0x3a, 0x74, 0x42, 0xb0, 0x44, 0x05, 0xc1, 0x12, 0x18, - 0x17, 0xb1, 0xe6, 0x9b, 0x41, 0xce, 0xe2, 0xd9, 0x66, 0xce, 0x91, 0xb0, 0x2e, 0x39, 0x1c, 0x0a, 0x09, 0x36, 0x93, - 0xcd, 0xd6, 0x73, 0xb6, 0xf6, 0x19, 0x28, 0x01, 0x4a, 0x99, 0x26, 0x28, 0x4d, 0x2b, 0xb6, 0xe2, 0xa6, 0x35, 0x58, - 0xad, 0xa6, 0x6c, 0x55, 0x53, 0x76, 0x4e, 0x53, 0x8e, 0x2a, 0x28, 0x39, 0xa1, 0x14, 0x65, 0x18, 0xc0, 0x88, 0x4d, - 0xa2, 0xab, 0x0c, 0x7d, 0xbc, 0x13, 0x1e, 0x41, 0x15, 0x11, 0xf9, 0x84, 0x21, 0x04, 0x26, 0xa2, 0xb8, 0x50, 0x85, - 0x62, 0x80, 0x8c, 0x48, 0x20, 0x98, 0xa8, 0xd4, 0x29, 0x30, 0x1f, 0x4d, 0x15, 0xc3, 0xa6, 0x3d, 0x51, 0xbe, 0xa5, - 0x8e, 0x7b, 0x94, 0x6d, 0xfe, 0x2e, 0x76, 0x41, 0x88, 0xdc, 0x8d, 0x3b, 0xf5, 0x33, 0xe2, 0xbd, 0xdd, 0x11, 0xc6, - 0x4f, 0x76, 0xdc, 0x22, 0x5c, 0x11, 0x6c, 0xa9, 0xe6, 0x10, 0x8b, 0x79, 0x35, 0x49, 0x50, 0xcb, 0x92, 0xf8, 0x1b, - 0x9e, 0x0c, 0x72, 0xb6, 0x04, 0x0f, 0xda, 0x39, 0xcb, 0x00, 0x7f, 0xc5, 0x6a, 0xd1, 0x6f, 0xb5, 0xb7, 0x04, 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, 0x8f, 0xbd, 0x04, 0x3b, 0x07, 0xbc, 0x81, 0xb4, 0x81, - 0x37, 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, 0x22, 0x01, - 0xc0, 0xa4, 0xce, 0x81, 0x38, 0x33, 0xc1, 0x2e, 0x4d, 0x22, 0xcb, 0xc7, 0x30, 0xbf, 0x13, 0x6f, 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, 0x52, 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, 0xd7, 0x90, 0x74, 0x6c, - 0xe0, 0xb4, 0xfa, 0x14, 0x7c, 0x90, 0xe4, 0x60, 0xa2, 0x0e, 0x5e, 0xee, 0x2f, 0xfd, 0x3e, 0x6c, 0xd9, 0xb9, 0x94, - 0xea, 0x58, 0xa9, 0xb7, 0x6d, 0xed, 0x07, 0xd1, 0x16, 0x1c, 0x59, 0xc4, 0xdf, 0x67, 0x88, 0x08, 0x66, 0x06, 0x11, - 0x76, 0x2d, 0xd4, 0xdd, 0x9e, 0x52, 0xcb, 0xa2, 0xde, 0xf6, 0x94, 0x52, 0xb7, 0x61, 0xf8, 0x6e, 0x82, 0x99, 0xe2, - 0x86, 0xff, 0x91, 0x79, 0xa1, 0xde, 0x78, 0x2c, 0x0a, 0x74, 0xcf, 0xdf, 0x2f, 0x79, 0x35, 0xdb, 0x28, 0x13, 0xe6, - 0x1d, 0x5f, 0xce, 0x42, 0xd9, 0xd5, 0xd2, 0xb8, 0xf3, 0xd9, 0x5b, 0xaa, 0xf9, 0xe0, 0x1f, 0x0e, 0x09, 0xc4, 0x1b, - 0xc5, 0x57, 0x77, 0x8d, 0xdc, 0xba, 0x26, 0x9b, 0xab, 0x12, 0x50, 0xbf, 0xcf, 0xd7, 0xb8, 0xdf, 0x62, 0xfd, 0xbb, - 0xa7, 0x41, 0xc6, 0x6a, 0x86, 0x2b, 0xa6, 0xf0, 0x29, 0x00, 0x0c, 0x0e, 0xa7, 0x82, 0xb4, 0xc0, 0x1b, 0x5e, 0x0e, - 0x2f, 0x27, 0x1b, 0x32, 0xe9, 0x6e, 0x7c, 0xe4, 0xce, 0x02, 0x55, 0xef, 0x37, 0x14, 0x27, 0x0d, 0x12, 0x8d, 0xbd, - 0x06, 0x5f, 0x66, 0x19, 0xe5, 0xa2, 0x89, 0xfb, 0x98, 0x7c, 0xa5, 0x07, 0x30, 0x57, 0xa1, 0x04, 0x88, 0x7e, 0x63, - 0x59, 0x6c, 0x44, 0xdb, 0x62, 0x03, 0x4b, 0xa9, 0x9a, 0xeb, 0xd5, 0xf4, 0xd9, 0x2b, 0xd1, 0xbc, 0x8f, 0x66, 0x9c, - 0xd2, 0x68, 0xc0, 0x71, 0x1a, 0x85, 0xdb, 0xf7, 0xf7, 0xa2, 0x5c, 0x66, 0x60, 0xc9, 0x56, 0xe1, 0x14, 0x97, 0x8d, - 0x3a, 0x23, 0x5e, 0xe6, 0xb1, 0x02, 0xe8, 0x78, 0x4c, 0x00, 0x54, 0x17, 0x04, 0x54, 0x44, 0x4b, 0xe9, 0xad, 0xd0, - 0x62, 0xa1, 0xde, 0x70, 0x94, 0xc2, 0x1f, 0xe9, 0xcf, 0x83, 0x7c, 0x0a, 0x40, 0xec, 0xfa, 0x38, 0x7a, 0x53, 0x94, - 0xf4, 0xa9, 0x62, 0x96, 0xcb, 0xc1, 0x04, 0x76, 0x75, 0x22, 0x43, 0xad, 0x20, 0x6f, 0xd5, 0x95, 0xb7, 0x32, 0x79, - 0x1b, 0xe3, 0x94, 0xfc, 0xc8, 0x4d, 0xc7, 0x1a, 0x31, 0xf0, 0xca, 0xd3, 0x3a, 0x4d, 0x90, 0x26, 0x17, 0xc0, 0x30, - 0xc4, 0xb7, 0x99, 0xf7, 0xd2, 0x73, 0xa4, 0x2a, 0x48, 0x66, 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, 0xcb, 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, 0xb5, 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, 0x17, 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, 0x57, 0x99, 0xbe, 0x85, 0x98, 0x28, 0xa7, 0x1a, 0x21, 0x71, 0xa5, 0x24, 0x11, 0x1f, - 0x2f, 0x5a, 0x56, 0x8c, 0xca, 0xf0, 0x81, 0x57, 0xaa, 0x7c, 0x75, 0xaa, 0xf2, 0x62, 0xa4, 0x6d, 0x09, 0xbc, 0x26, - 0xff, 0x10, 0xb9, 0xe6, 0xad, 0xaf, 0xbb, 0xca, 0xd0, 0x6b, 0x59, 0x81, 0x8e, 0x60, 0x2b, 0x4b, 0xc9, 0x01, 0x9f, - 0x54, 0x77, 0xd5, 0xaa, 0xf5, 0x39, 0x65, 0x1b, 0xe1, 0x26, 0xbf, 0x8e, 0x1d, 0x1c, 0x29, 0xbf, 0xc1, 0x73, 0x01, - 0xec, 0x35, 0x60, 0x6f, 0xce, 0x59, 0xd1, 0x3c, 0x3a, 0xa4, 0x6d, 0x81, 0x46, 0x66, 0x6e, 0xe7, 0xea, 0xbe, 0x2d, - 0x8f, 0xd2, 0x18, 0x22, 0xd3, 0x1e, 0x99, 0x0e, 0x36, 0xa3, 0xfc, 0xb7, 0x94, 0xdf, 0x2a, 0x1c, 0x03, 0xdf, 0x4e, - 0xbd, 0x03, 0xa8, 0x7a, 0xda, 0x20, 0x63, 0xcd, 0x30, 0xb4, 0xb2, 0xcb, 0xa5, 0xd0, 0x12, 0xb4, 0xd4, 0x4d, 0x10, - 0x9c, 0x1f, 0x11, 0xe5, 0x08, 0x40, 0x17, 0x29, 0x60, 0x82, 0x9f, 0xd2, 0x76, 0xf7, 0xfb, 0xeb, 0xd4, 0x23, 0xf7, - 0xae, 0x50, 0xa3, 0x84, 0x12, 0x8c, 0xfd, 0x44, 0x63, 0x06, 0x1d, 0x5d, 0x91, 0x13, 0x9e, 0xb5, 0x3a, 0xac, 0xeb, - 0xa6, 0x0c, 0xca, 0xe2, 0x98, 0x57, 0xd3, 0xd9, 0xef, 0x4f, 0xf6, 0x75, 0x83, 0x2c, 0xe4, 0xbf, 0xb3, 0x1e, 0x92, - 0x41, 0xf7, 0x20, 0x14, 0xa2, 0x37, 0x0f, 0x66, 0xf8, 0x1f, 0xdb, 0xf0, 0xec, 0x1b, 0x6e, 0xd4, 0x09, 0x60, 0x8e, - 0xb8, 0x5e, 0x7a, 0x8a, 0xb6, 0x1e, 0x6e, 0x81, 0x6c, 0x8d, 0x97, 0xb7, 0xf6, 0x1a, 0xc8, 0x29, 0x8e, 0xff, 0x8e, - 0x67, 0x6a, 0x65, 0x83, 0x9f, 0x9e, 0xb2, 0x1d, 0x78, 0x78, 0x11, 0x02, 0x8a, 0x61, 0xd9, 0xf8, 0x3b, 0xcb, 0x71, - 0x46, 0xff, 0xcd, 0x23, 0x86, 0xc1, 0x22, 0xf2, 0xe3, 0xcb, 0x52, 0x88, 0x2f, 0xc2, 0x7b, 0x5b, 0x79, 0x77, 0xe4, - 0x94, 0x79, 0xa7, 0x87, 0xd1, 0x75, 0x49, 0xfa, 0x26, 0xf9, 0xd8, 0x1a, 0xb6, 0xdf, 0xb5, 0xfb, 0xcd, 0x10, 0x41, - 0x08, 0xe5, 0xf8, 0x39, 0xa3, 0x13, 0x1a, 0x1f, 0x56, 0xb3, 0xd3, 0xeb, 0xf7, 0xce, 0xf1, 0x82, 0xad, 0xd1, 0x00, - 0x8f, 0x87, 0x2e, 0xe6, 0x89, 0x1a, 0x3a, 0x5d, 0xd7, 0xce, 0xc1, 0x03, 0x83, 0x2c, 0x4f, 0xbe, 0x61, 0x58, 0x62, - 0x7f, 0x12, 0xf1, 0xa4, 0xad, 0xda, 0xd8, 0x1c, 0xa9, 0x36, 0x6a, 0x06, 0x7e, 0xf0, 0x0a, 0x0a, 0x8c, 0x2e, 0x48, - 0x2b, 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, 0x6f, 0xa9, 0x57, 0xfb, 0x32, 0x66, 0x85, 0x7a, 0x7d, 0x61, 0xda, 0xf5, 0x5a, 0x5a, 0x14, 0x50, - 0x71, 0xdb, 0xaa, 0xed, 0x91, 0x9c, 0xff, 0xf8, 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, 0x6f, - 0xa9, 0x57, 0xb5, 0xa9, 0xea, 0xc1, 0x1b, 0x2f, 0x70, 0xf6, 0x4e, 0x6b, 0x01, 0x01, 0x14, 0xb6, 0x96, 0xe5, 0xe0, - 0xdc, 0xed, 0xaa, 0x96, 0x8a, 0x32, 0xea, 0xf7, 0xcf, 0x7f, 0x4b, 0x51, 0x11, 0x7b, 0xaa, 0x38, 0x65, 0xfd, 0x76, - 0xcb, 0x5c, 0x54, 0x96, 0xbc, 0x41, 0x15, 0xad, 0xd5, 0x51, 0x53, 0xb9, 0x6e, 0xae, 0x5a, 0x32, 0x41, 0x8c, 0xee, - 0xd3, 0xb5, 0xce, 0x9d, 0x7a, 0xef, 0x55, 0x1c, 0x31, 0x10, 0xdc, 0x74, 0x8f, 0x0f, 0x0e, 0x42, 0xa3, 0xa2, 0x5c, - 0x70, 0xa3, 0xb4, 0xaa, 0xa4, 0x14, 0xf2, 0x56, 0x45, 0x73, 0xa6, 0x8f, 0x00, 0x88, 0x00, 0xab, 0x44, 0xfd, 0x1f, - 0xbe, 0x34, 0xc6, 0x83, 0x07, 0xbe, 0x26, 0xd7, 0xb1, 0xf5, 0xfe, 0x69, 0x8d, 0xb4, 0xda, 0x38, 0x26, 0xb5, 0xea, - 0x65, 0xab, 0x78, 0xd9, 0xbd, 0x4e, 0xc5, 0xe0, 0xf9, 0xff, 0xdc, 0x07, 0xa8, 0x11, 0x2d, 0x65, 0x70, 0xeb, 0x6a, - 0x80, 0xc6, 0x87, 0x63, 0xe1, 0x1b, 0x3f, 0x64, 0x9c, 0x0f, 0x66, 0xe8, 0xa8, 0x36, 0x07, 0x07, 0x04, 0x47, 0x75, - 0x8f, 0xc6, 0x84, 0x59, 0x38, 0xf7, 0x20, 0x50, 0x7d, 0xe2, 0x3e, 0xe3, 0xda, 0x0b, 0xda, 0x04, 0x3e, 0x59, 0xd7, - 0x35, 0x45, 0x80, 0x8b, 0xd8, 0x98, 0x88, 0x21, 0x2e, 0x9b, 0x44, 0xea, 0x9b, 0x31, 0x28, 0x00, 0x8a, 0x17, 0x15, - 0xc9, 0xa5, 0x8b, 0x34, 0xaf, 0x44, 0x59, 0xeb, 0x66, 0x54, 0xac, 0x18, 0x02, 0xc0, 0x43, 0x50, 0x5c, 0x55, 0x66, - 0x42, 0x23, 0x36, 0x90, 0xca, 0x52, 0xb0, 0x6a, 0x58, 0xf8, 0x4d, 0xfb, 0x4d, 0x72, 0xd2, 0x3b, 0x1f, 0xb7, 0xce, - 0x1d, 0xfb, 0xde, 0x51, 0x48, 0x69, 0x0f, 0xc5, 0x04, 0x41, 0xf0, 0xd3, 0x3a, 0x9c, 0x3f, 0xe3, 0x2f, 0x08, 0x4c, - 0x45, 0x36, 0x63, 0xc0, 0x41, 0x88, 0xc8, 0x8c, 0xdf, 0x73, 0xf8, 0x82, 0x97, 0x93, 0x70, 0x38, 0xf4, 0x41, 0x1f, - 0xca, 0xb3, 0x59, 0x38, 0x14, 0x73, 0xe9, 0xbd, 0x0e, 0xd6, 0xba, 0x90, 0xd7, 0x93, 0x10, 0xd1, 0x42, 0x43, 0x1f, - 0x9c, 0xd7, 0x5d, 0x73, 0x84, 0x25, 0x00, 0x4d, 0x1c, 0x7d, 0x59, 0xbf, 0x1f, 0x79, 0xda, 0xd0, 0x22, 0xc5, 0x45, - 0xa3, 0xcc, 0x66, 0xb9, 0xec, 0x84, 0x8d, 0x6b, 0xb7, 0x40, 0x28, 0x1e, 0xa6, 0x2d, 0x54, 0xad, 0xa7, 0x7a, 0x3d, - 0x37, 0xed, 0xbe, 0x7b, 0x54, 0xad, 0x72, 0xa4, 0xb3, 0x36, 0x5d, 0xa9, 0xd5, 0x2d, 0xa3, 0x6a, 0x9d, 0xa5, 0x11, - 0x55, 0x6e, 0x92, 0xbb, 0x46, 0x2d, 0xf8, 0x64, 0x43, 0x97, 0x29, 0x3b, 0x5b, 0x83, 0x13, 0x47, 0x9e, 0x4b, 0x6e, - 0xf9, 0xee, 0xbc, 0xa2, 0xbb, 0x53, 0xed, 0x5b, 0x80, 0x7b, 0x33, 0x6c, 0xc8, 0x9c, 0xd7, 0xd8, 0x69, 0x10, 0x26, - 0x81, 0x1f, 0xb1, 0x8f, 0x19, 0xb2, 0xc1, 0x80, 0x8e, 0x42, 0xfa, 0x5f, 0x5b, 0xe6, 0x48, 0xc0, 0xe4, 0xaf, 0xe7, - 0x7e, 0xb3, 0x28, 0x72, 0x58, 0x8c, 0x1f, 0x36, 0x18, 0x69, 0xac, 0xd6, 0x60, 0x58, 0xde, 0x21, 0xf2, 0xa7, 0x76, - 0xc7, 0x34, 0xd5, 0xf1, 0x66, 0xbd, 0xd6, 0xfc, 0xea, 0xe9, 0x53, 0x5d, 0x9f, 0xff, 0xf6, 0xfd, 0x65, 0x58, 0x33, - 0xfb, 0x43, 0x10, 0x4a, 0xbb, 0x77, 0x8b, 0x73, 0x47, 0xa2, 0x77, 0xac, 0x34, 0xb3, 0x4b, 0xbb, 0x64, 0x97, 0xa6, - 0xb4, 0x1b, 0x72, 0xbd, 0xfa, 0x4a, 0x79, 0x63, 0xe7, 0x15, 0xd3, 0xfd, 0x7b, 0xa1, 0x77, 0x94, 0x53, 0x35, 0x81, - 0x88, 0x26, 0xed, 0x48, 0xdc, 0xee, 0x95, 0xe1, 0xf3, 0x49, 0xde, 0x2e, 0xe1, 0xa8, 0x6b, 0x58, 0x6e, 0xbe, 0xfd, - 0xcf, 0xbc, 0xea, 0xac, 0x70, 0xfb, 0xa5, 0x31, 0x6b, 0x7f, 0x0a, 0xe2, 0xaa, 0xfe, 0xf0, 0x9e, 0xd4, 0x4c, 0xc9, - 0xff, 0x55, 0x8f, 0x81, 0xab, 0x9f, 0x4c, 0x3b, 0xba, 0xa7, 0x10, 0x36, 0x98, 0xfd, 0xfc, 0xf8, 0xa1, 0x05, 0xab, - 0xea, 0x02, 0x45, 0x72, 0x00, 0x9d, 0xbb, 0x64, 0x84, 0xf7, 0x3b, 0xc6, 0xb9, 0x7f, 0xf5, 0xbd, 0x9a, 0x1c, 0x21, - 0xa2, 0x5d, 0x84, 0x03, 0x80, 0xb8, 0xd3, 0x54, 0xd6, 0xa1, 0x06, 0xe8, 0x03, 0x02, 0xeb, 0xd0, 0xb7, 0x19, 0xc0, - 0x41, 0x1f, 0x6d, 0x9e, 0x45, 0x20, 0xaf, 0x7b, 0xf7, 0xec, 0x9a, 0xed, 0x7c, 0xfe, 0x62, 0x95, 0x7a, 0xf7, 0xe8, - 0x10, 0x7c, 0x3e, 0xf6, 0xa7, 0x97, 0x81, 0xc1, 0x85, 0x66, 0xd7, 0xcf, 0x04, 0xdb, 0xb1, 0xdd, 0x33, 0x44, 0x2a, - 0xea, 0xce, 0x3f, 0xbc, 0x34, 0xd1, 0xf3, 0xce, 0x0b, 0x77, 0x7c, 0x09, 0xe0, 0x81, 0x2c, 0x06, 0x14, 0x9f, 0xa5, - 0xf7, 0x2f, 0x96, 0x80, 0x9a, 0xfc, 0x96, 0xaf, 0xbd, 0x2f, 0x94, 0xba, 0x80, 0x3f, 0x07, 0x94, 0x3e, 0xc9, 0xb9, - 0x77, 0x37, 0xbc, 0xf5, 0x2f, 0x9e, 0x83, 0xf3, 0xc4, 0x6a, 0xb8, 0x80, 0xbf, 0x0a, 0x3e, 0xf4, 0xee, 0x06, 0x98, - 0x58, 0xf2, 0xa1, 0xb7, 0x1a, 0x40, 0xaa, 0xc2, 0x85, 0xc4, 0xd8, 0x87, 0x5f, 0x83, 0x9c, 0xe1, 0x1f, 0xbf, 0x69, - 0x0c, 0xd6, 0x5f, 0x83, 0x42, 0xa3, 0xb1, 0x96, 0x2a, 0x64, 0x29, 0x16, 0x67, 0x02, 0x6c, 0xc2, 0x71, 0xb7, 0x2f, - 0x56, 0xb5, 0x59, 0x0b, 0xfa, 0xf3, 0x11, 0xdf, 0xa3, 0xb1, 0xba, 0x2a, 0xe7, 0xa2, 0xfc, 0x88, 0xf4, 0xa9, 0x8e, - 0x8f, 0x51, 0xb1, 0xa9, 0xbb, 0xd3, 0xa9, 0x56, 0x1d, 0x69, 0xbf, 0x29, 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, 0x2f, 0x06, 0xb9, 0x0c, 0x8d, 0xf9, 0x80, 0x6c, 0x18, 0xca, 0x87, 0x16, 0x19, 0x12, 0x22, 0xde, 0x43, - 0x25, 0x60, 0xdb, 0x82, 0x32, 0x29, 0xe0, 0x2c, 0x1a, 0xfc, 0x56, 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, 0x1f, 0xae, 0xf2, 0x4f, 0xd1, 0x52, 0x0f, 0xff, 0x9f, 0x31, 0x85, 0xd2, - 0xbf, 0x4a, 0xcb, 0x68, 0xb3, 0x5a, 0x8a, 0x52, 0xe4, 0x91, 0x38, 0xf9, 0x5a, 0x64, 0xe7, 0xf2, 0x9d, 0x4f, 0xa1, - 0x5f, 0x00, 0x5a, 0xf6, 0x09, 0x32, 0xfa, 0x7b, 0x26, 0xf8, 0xf0, 0x7b, 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, 0x7b, 0x83, 0x90, 0xe2, 0xf9, 0x03, 0x5b, 0xad, 0x8b, 0x8b, 0xc4, 0x2b, 0x64, - 0xa2, 0x05, 0xb1, 0x14, 0x81, 0x19, 0x2f, 0x34, 0x8d, 0x30, 0x41, 0x99, 0x12, 0x2c, 0x5a, 0xa3, 0x43, 0xfb, 0xc3, - 0x12, 0x76, 0x8f, 0x31, 0x02, 0x04, 0xaa, 0x4c, 0x9f, 0xc3, 0xd6, 0x84, 0xd9, 0xd4, 0xc5, 0x06, 0x68, 0xab, 0x18, - 0x1a, 0x84, 0xb5, 0x21, 0xe6, 0x63, 0x9a, 0xdf, 0xfd, 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, 0xee, 0x1a, 0xfe, 0x21, 0xf3, 0x62, 0x96, 0x80, 0x7e, 0x77, 0xc5, 0x55, 0x83, 0xa0, 0x19, 0x1b, 0x76, - 0x0b, 0xbf, 0x25, 0xd6, 0x6e, 0xe9, 0x5f, 0x2c, 0xd9, 0xc2, 0xf4, 0x81, 0x6e, 0x1d, 0x60, 0x19, 0x51, 0x93, 0xef, - 0x91, 0x77, 0xd3, 0x59, 0x51, 0xb8, 0x3d, 0xb1, 0x85, 0xcf, 0xae, 0xcd, 0x9b, 0xf7, 0xcf, 0x22, 0xc8, 0xbd, 0xe3, - 0xde, 0xfd, 0xf0, 0xda, 0xbf, 0xd0, 0x2d, 0x90, 0x93, 0x59, 0xce, 0x40, 0xea, 0x88, 0x4f, 0x10, 0xad, 0xec, 0x29, - 0xdf, 0x09, 0xb9, 0xb3, 0xad, 0x9f, 0xdd, 0xbb, 0xdb, 0xda, 0xdd, 0xb3, 0x7b, 0x56, 0x8d, 0x28, 0x56, 0x9c, 0xa6, - 0x48, 0x98, 0x45, 0x1b, 0xe0, 0xa9, 0x97, 0xef, 0x77, 0xec, 0x98, 0xc3, 0xdd, 0xb3, 0x8e, 0x8e, 0x97, 0x73, 0xc0, - 0xee, 0xfe, 0xa3, 0x4d, 0xd8, 0x58, 0xe9, 0x5a, 0x85, 0x0e, 0x77, 0xcf, 0x32, 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, 0x2b, 0x2e, 0xbe, 0x3f, 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, 0x9c, 0xc5, 0x90, 0x08, 0xb0, 0xdd, 0xa1, 0x62, 0x5b, 0xb8, 0x78, - 0xce, 0x36, 0xbc, 0xe8, 0xf7, 0x33, 0xd5, 0x29, 0x64, 0xdd, 0x59, 0xf2, 0x8d, 0x6a, 0x8e, 0x35, 0xd4, 0x6c, 0x6d, - 0x92, 0xad, 0x71, 0x6e, 0x2b, 0x3e, 0xee, 0xda, 0x8a, 0x8f, 0x95, 0xb5, 0x2e, 0xdd, 0xeb, 0x3d, 0xaa, 0x0b, 0x60, - 0xeb, 0xbf, 0x3d, 0x5e, 0xb9, 0x9e, 0xcf, 0x08, 0xe0, 0x6b, 0xc1, 0xc7, 0x93, 0x05, 0x7a, 0x95, 0x2c, 0xfc, 0xdb, - 0x81, 0x1a, 0x7f, 0xa7, 0x73, 0x17, 0x00, 0x5d, 0x49, 0x79, 0x05, 0xe4, 0x1d, 0xe4, 0x98, 0x5b, 0x76, 0xe5, 0xfd, - 0xc9, 0x77, 0xd8, 0x35, 0xaf, 0x67, 0x8b, 0x39, 0xdb, 0x81, 0x53, 0x41, 0x32, 0xb0, 0x97, 0x15, 0xdb, 0x05, 0xb1, - 0x9d, 0xf0, 0x1b, 0x01, 0x53, 0xbe, 0x84, 0x20, 0xae, 0xe0, 0x16, 0xe2, 0xf0, 0xe4, 0x9f, 0x83, 0xfb, 0xd6, 0x66, - 0x7d, 0xcf, 0xac, 0xce, 0x09, 0xd6, 0xcc, 0xea, 0xc1, 0x60, 0xd9, 0x4c, 0x56, 0xfd, 0xbe, 0xb7, 0xd3, 0x8e, 0x4f, - 0x77, 0x52, 0x27, 0x76, 0x5a, 0xab, 0xb5, 0x60, 0xd7, 0x52, 0xeb, 0x62, 0x0c, 0x3d, 0x40, 0xfc, 0x74, 0x3b, 0xe0, - 0xf7, 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, 0xc7, 0x6c, 0xc7, 0xb8, - 0xf9, 0xe9, 0xe5, 0x0f, 0x4e, 0x58, 0xb2, 0x62, 0xb5, 0x3f, 0xfd, 0xfe, 0x99, 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, 0x99, 0xfa, 0xc0, 0x88, 0x25, 0x81, 0xda, 0x5e, - 0x66, 0xe9, 0x1d, 0xa8, 0xf0, 0x7b, 0xb8, 0x9a, 0x88, 0xfd, 0xdc, 0x92, 0xa2, 0x22, 0x1b, 0xe9, 0x0d, 0xad, 0xc1, - 0x23, 0xb4, 0xa6, 0x7c, 0xef, 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, 0xd7, 0x24, 0x61, 0x4f, 0x0c, - 0x3a, 0x85, 0xaa, 0xdc, 0xee, 0x8e, 0xb6, 0xc0, 0x75, 0xcc, 0x52, 0xf4, 0xd2, 0x16, 0xb9, 0x5b, 0xfe, 0xdd, 0x73, - 0x45, 0xce, 0x7e, 0x09, 0x08, 0x4e, 0xcd, 0x57, 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, 0xe6, 0x2e, 0xc9, 0x37, 0xe0, - 0xcc, 0x40, 0xa9, 0x96, 0x7e, 0xe0, 0x58, 0x2d, 0xa0, 0xc2, 0xc1, 0xec, 0xa4, 0x5e, 0x58, 0x46, 0x3d, 0xa6, 0xcf, - 0xcf, 0x60, 0xef, 0x08, 0x09, 0x80, 0xfb, 0x65, 0x1f, 0x90, 0x80, 0x87, 0xce, 0xec, 0x80, 0x70, 0xc2, 0x2c, 0xaa, - 0x02, 0x89, 0xe4, 0x48, 0x3f, 0x7b, 0xcc, 0x44, 0xf2, 0x07, 0xb3, 0x9e, 0x73, 0x4a, 0xf4, 0x58, 0x4f, 0x1d, 0x21, - 0x3d, 0xd6, 0xb3, 0x8e, 0x88, 0x1e, 0xeb, 0x59, 0xc7, 0x47, 0x8f, 0xf5, 0xcc, 0xb1, 0xd3, 0x83, 0xc0, 0x04, 0x88, - 0x3c, 0x60, 0x3d, 0x9a, 0x4c, 0x3d, 0xc5, 0x3d, 0x40, 0x34, 0x08, 0xac, 0x27, 0x85, 0xf3, 0x1e, 0x20, 0x8f, 0x91, - 0x58, 0x1d, 0xf4, 0xfe, 0x32, 0x7e, 0xda, 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, - 0x07, 0x51, 0xf3, 0xb4, 0xd5, 0x56, 0xc1, 0xfe, 0x0e, 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, 0x1f, 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, 0x7f, 0x95, 0xa5, 0xc6, 0x39, 0x32, 0x97, 0xeb, 0xbb, 0x2e, 0xee, 0xee, 0x68, 0x9b, 0xb0, 0x0a, 0x11, - 0xea, 0xb6, 0xa1, 0x72, 0x29, 0xcc, 0xc6, 0xa6, 0x69, 0x80, 0x2f, 0x14, 0x95, 0x4a, 0x55, 0x6a, 0x2b, 0x95, 0x9c, - 0xf0, 0xae, 0xaf, 0x6a, 0x91, 0xba, 0x22, 0xd8, 0xc6, 0x0c, 0xf5, 0x50, 0x6e, 0xd4, 0xd8, 0xd7, 0x1d, 0xab, 0xf4, - 0x0e, 0x13, 0xe4, 0x8c, 0xbc, 0xc8, 0xc1, 0x45, 0x49, 0x41, 0xe6, 0x6a, 0x08, 0xf3, 0x47, 0x0d, 0x9f, 0x16, 0x96, - 0x7b, 0x28, 0x01, 0xb3, 0xa3, 0x86, 0x97, 0x11, 0x02, 0x11, 0x97, 0xca, 0xbe, 0x62, 0xe2, 0xf7, 0x14, 0xcc, 0x92, - 0x09, 0xdd, 0x8b, 0x58, 0x18, 0xa1, 0x8d, 0x4f, 0x92, 0x64, 0xea, 0x69, 0x0a, 0x6e, 0xe4, 0x32, 0xcc, 0xd1, 0x08, - 0x2d, 0xf9, 0xc8, 0x81, 0xf4, 0xb5, 0x9c, 0x4a, 0xf0, 0x11, 0x75, 0x0a, 0x38, 0x9e, 0x9f, 0x17, 0xd6, 0x4f, 0x96, - 0x4b, 0xcc, 0x65, 0x6d, 0xfe, 0xcb, 0x8e, 0x8e, 0xc1, 0x2e, 0x4f, 0x13, 0xc7, 0xd5, 0x7f, 0x54, 0x25, 0xc5, 0xc3, - 0xcf, 0x69, 0x0e, 0x28, 0x82, 0x99, 0x3d, 0xc5, 0xf8, 0xd8, 0x67, 0x99, 0x02, 0xfe, 0x76, 0xbd, 0xb5, 0x64, 0x62, - 0x97, 0xb4, 0x9b, 0x2b, 0xe3, 0x97, 0xda, 0xb0, 0xe3, 0xe0, 0xdc, 0x00, 0x14, 0x67, 0x8d, 0x0e, 0xcb, 0x6b, 0xdd, - 0xb6, 0x2a, 0x54, 0xa0, 0xd6, 0xff, 0xd9, 0x2d, 0x4c, 0x79, 0x9b, 0x97, 0xca, 0xdb, 0x3c, 0x34, 0x01, 0x02, 0x91, - 0x19, 0xf2, 0xac, 0xe9, 0x98, 0x24, 0xee, 0x1d, 0x29, 0x69, 0xdf, 0x91, 0xe2, 0x47, 0xef, 0x48, 0xc8, 0xb7, 0x84, - 0x8e, 0xec, 0x4b, 0x4e, 0x4e, 0xa0, 0xcc, 0x60, 0x2f, 0xaf, 0x99, 0xec, 0x1f, 0xd0, 0x5e, 0x38, 0x97, 0xe5, 0x15, - 0xbf, 0x16, 0xde, 0xda, 0x9f, 0xae, 0x4f, 0xbb, 0xaa, 0xde, 0x7e, 0x65, 0x66, 0x1e, 0x0e, 0xc5, 0xe1, 0x50, 0x99, - 0xa0, 0xdd, 0x05, 0x17, 0x83, 0x9c, 0xdd, 0xbb, 0xf1, 0xf1, 0xd7, 0x1c, 0x45, 0x6c, 0xa5, 0x3c, 0x92, 0x2e, 0x54, - 0x62, 0x78, 0x69, 0xe0, 0x61, 0x76, 0x7c, 0x3c, 0xd9, 0x5d, 0xdd, 0x4f, 0x06, 0x83, 0x9d, 0xea, 0xdb, 0x2d, 0xaf, - 0x67, 0xbb, 0x39, 0x7b, 0xe0, 0xb7, 0xd3, 0x6d, 0xb0, 0x6f, 0x60, 0xdb, 0xdd, 0x5d, 0x89, 0xc3, 0x61, 0xf7, 0x82, - 0x2f, 0xfc, 0xfd, 0x03, 0x02, 0x3a, 0xf3, 0xf3, 0x71, 0x1b, 0xe3, 0xe7, 0xa6, 0xed, 0xaa, 0xb5, 0x03, 0x78, 0xfa, - 0x1f, 0xbc, 0x9b, 0xd9, 0x72, 0xee, 0xb3, 0x27, 0xfc, 0x01, 0xfc, 0xf3, 0x71, 0x93, 0x44, 0xea, 0x13, 0xed, 0x32, - 0x79, 0x03, 0x0e, 0xe4, 0x3b, 0x9f, 0xbd, 0xe5, 0x0f, 0xb3, 0xe5, 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, 0x76, 0xc3, - 0x22, 0x3f, 0x80, 0x0f, 0xb2, 0x9d, 0x3f, 0x91, 0x35, 0xa5, 0xfb, 0xc5, 0x13, 0xff, 0x70, 0xa0, 0xbf, 0xde, 0xfa, - 0x87, 0xc3, 0x7b, 0xf6, 0x80, 0xe0, 0xe8, 0x7c, 0x07, 0xfd, 0xa3, 0x6f, 0x1d, 0x50, 0x95, 0xe1, 0xf5, 0x6c, 0x33, - 0xf7, 0x5f, 0xac, 0xd8, 0x1d, 0x70, 0xa1, 0x28, 0x2f, 0xb4, 0x1b, 0xf6, 0x80, 0x5e, 0x67, 0xe4, 0x44, 0x34, 0xdb, - 0xcd, 0x7d, 0x16, 0xe3, 0x73, 0x75, 0x5f, 0x4c, 0xbe, 0x7a, 0x5f, 0xdc, 0xb1, 0x6d, 0xf7, 0x7d, 0x51, 0xbe, 0xe9, - 0xae, 0x9f, 0x2d, 0xdb, 0xb1, 0x07, 0x98, 0x61, 0xd7, 0xfc, 0xa6, 0x39, 0x76, 0x8c, 0xfd, 0xea, 0x8d, 0x11, 0x40, - 0x99, 0x2d, 0x58, 0x2c, 0x38, 0x28, 0xd5, 0xaa, 0x6d, 0x49, 0xe4, 0x95, 0x0e, 0x54, 0x9b, 0x11, 0xdc, 0x57, 0x0b, - 0x39, 0xf3, 0xcc, 0x40, 0xdf, 0x56, 0x88, 0x16, 0x0e, 0x1b, 0xf0, 0x57, 0xda, 0x3a, 0xc6, 0x30, 0xcd, 0x6a, 0xa6, - 0x6d, 0x51, 0x97, 0xdf, 0xf6, 0x9e, 0xc9, 0x6f, 0x64, 0x60, 0x0b, 0x91, 0x14, 0x8e, 0xe3, 0x8b, 0xe7, 0x27, 0xfc, - 0x57, 0x2d, 0x8f, 0x5a, 0xed, 0x17, 0x4a, 0x7d, 0xfa, 0x8a, 0x8e, 0x68, 0xe2, 0x5e, 0xb4, 0x65, 0x58, 0xa3, 0xac, - 0xa9, 0xa5, 0xc3, 0x30, 0xae, 0x61, 0x5f, 0x1e, 0x38, 0xf4, 0x1d, 0x10, 0x68, 0xab, 0x54, 0x0a, 0xb4, 0x70, 0x0c, - 0xa3, 0x30, 0x0b, 0x29, 0x8f, 0x0b, 0xb3, 0x94, 0xf7, 0x58, 0xa0, 0xc5, 0xad, 0xba, 0xc7, 0xd4, 0x76, 0x0b, 0x22, - 0xac, 0xde, 0x32, 0xce, 0x2f, 0x1b, 0x55, 0xb8, 0x2d, 0x40, 0x51, 0x04, 0x65, 0xb0, 0x27, 0xb9, 0x6d, 0xa1, 0xa4, - 0xd9, 0x28, 0xac, 0xc5, 0x5d, 0x51, 0xee, 0x7a, 0x0d, 0x5b, 0xe0, 0x05, 0x55, 0x3f, 0x21, 0x6c, 0xcb, 0x9e, 0x75, - 0x28, 0x17, 0xe9, 0x7f, 0x64, 0xe9, 0xf9, 0x76, 0x6b, 0xce, 0xff, 0xf4, 0x15, 0x7d, 0x54, 0xfe, 0xe7, 0x97, 0xf4, - 0x93, 0xc1, 0x32, 0x72, 0x4a, 0x7d, 0x1f, 0x8d, 0x6e, 0xd3, 0x9c, 0x30, 0xb6, 0x7c, 0xfd, 0xf4, 0x1b, 0x64, 0x0a, - 0x92, 0x43, 0x29, 0x55, 0x39, 0xd9, 0x43, 0x5f, 0x78, 0xdd, 0x87, 0x99, 0x60, 0x00, 0xc2, 0x6b, 0xb4, 0xa9, 0x26, - 0x4c, 0xe2, 0xd1, 0x15, 0xfc, 0xdf, 0x08, 0x62, 0xd0, 0x3e, 0x51, 0xd4, 0xb1, 0x6d, 0xa4, 0xeb, 0xb6, 0x73, 0x90, - 0xdc, 0xa9, 0x2b, 0x7f, 0x54, 0x4e, 0xfe, 0x13, 0x0d, 0x91, 0x57, 0x5c, 0x21, 0x56, 0x16, 0x5c, 0x62, 0x31, 0x54, - 0xa4, 0x00, 0xd7, 0x10, 0x44, 0xca, 0xa2, 0xa4, 0x70, 0xcb, 0x41, 0x55, 0x04, 0x60, 0x5c, 0xad, 0x8e, 0x3a, 0x11, - 0x3e, 0x6e, 0xad, 0x45, 0x08, 0x56, 0x34, 0x6a, 0x65, 0xad, 0xc0, 0x17, 0xa4, 0x2f, 0x1d, 0x0a, 0x62, 0x7a, 0x14, - 0x52, 0x55, 0x3a, 0x14, 0x48, 0x73, 0xa8, 0xf8, 0xc6, 0x60, 0xa3, 0xa8, 0x48, 0xcf, 0x5f, 0x9a, 0x94, 0x5c, 0x1a, - 0x33, 0x3e, 0x88, 0x32, 0x12, 0x79, 0x1d, 0xde, 0x89, 0x69, 0x81, 0x7c, 0xa3, 0xc7, 0x0f, 0x82, 0x4b, 0x78, 0x37, - 0xe4, 0x5e, 0x01, 0xb6, 0x04, 0xec, 0x00, 0xf7, 0xca, 0x8c, 0x72, 0x9d, 0xd6, 0xf5, 0x5b, 0xeb, 0xa1, 0x18, 0x86, - 0xcf, 0x2c, 0x81, 0xed, 0x68, 0x1d, 0x1d, 0xe9, 0xe1, 0xc3, 0xff, 0xba, 0xaa, 0x39, 0xea, 0x54, 0x2e, 0x67, 0xc7, - 0x13, 0x96, 0x22, 0x66, 0xd0, 0xfd, 0x75, 0xfb, 0x4a, 0x00, 0xdd, 0x2e, 0x8b, 0x79, 0x36, 0xda, 0xc9, 0xbf, 0xa5, - 0x1b, 0x2b, 0x4a, 0x9b, 0x78, 0x97, 0xf5, 0xc6, 0xfe, 0x70, 0xf4, 0x97, 0x67, 0x5f, 0x26, 0x84, 0xaa, 0xb3, 0x61, - 0x6b, 0x1d, 0xe7, 0xf2, 0xbf, 0xfe, 0x3a, 0x26, 0x2b, 0x08, 0x0a, 0xc2, 0xb2, 0x53, 0x4c, 0x54, 0x30, 0x8a, 0x14, - 0x6b, 0x3e, 0x9e, 0xac, 0x51, 0x27, 0xbc, 0xf6, 0x97, 0x5a, 0x27, 0x4c, 0x8c, 0xac, 0x54, 0xfe, 0x9a, 0x55, 0xec, - 0x4e, 0x65, 0x16, 0x90, 0x79, 0x90, 0x4f, 0xd6, 0x46, 0x83, 0xb9, 0xe2, 0xf5, 0x6c, 0x3d, 0x97, 0xca, 0x67, 0x30, - 0xe5, 0x2c, 0x07, 0x27, 0x4b, 0x61, 0xf7, 0x24, 0x50, 0xb4, 0x66, 0xe8, 0xda, 0x9f, 0x62, 0xab, 0x5e, 0xa7, 0x55, - 0x0d, 0xf0, 0x80, 0x10, 0x03, 0x43, 0xed, 0xd5, 0xc2, 0x43, 0x6b, 0x01, 0xac, 0xfd, 0x51, 0xe9, 0x07, 0xe3, 0xc9, - 0x92, 0x2f, 0x90, 0x7f, 0x39, 0x72, 0xd4, 0xee, 0xfd, 0xbe, 0x77, 0x0f, 0x52, 0x70, 0xe4, 0x5a, 0x28, 0x90, 0x08, - 0x68, 0xc1, 0x37, 0xbe, 0xf2, 0xc1, 0xb8, 0x46, 0x6d, 0x35, 0x28, 0xa8, 0x1d, 0xdd, 0xf2, 0xd8, 0xd1, 0x3b, 0xdf, - 0x9f, 0xd0, 0x57, 0x2f, 0xb4, 0x70, 0xfc, 0x95, 0x33, 0x72, 0xcd, 0x56, 0x1d, 0x72, 0x44, 0x33, 0xe9, 0x10, 0x22, - 0x56, 0x6c, 0xcd, 0xae, 0x49, 0xe5, 0xdc, 0x39, 0x64, 0xa7, 0x8f, 0x50, 0xa5, 0xd7, 0x7a, 0x7c, 0x3b, 0x51, 0xba, - 0xdb, 0xe3, 0xdd, 0xe4, 0x5b, 0x36, 0x11, 0x31, 0x18, 0xd0, 0x06, 0xe1, 0x8c, 0xac, 0x43, 0xa4, 0xd2, 0x01, 0x42, - 0xe0, 0x98, 0x80, 0xa6, 0xff, 0xf8, 0x9a, 0x44, 0x01, 0x47, 0xda, 0x08, 0x59, 0xcb, 0x0e, 0x87, 0x1c, 0x34, 0xca, - 0xcd, 0x1f, 0x5e, 0xa1, 0x4e, 0x73, 0x60, 0x9e, 0x2e, 0x61, 0xcf, 0xc1, 0x23, 0xbd, 0x38, 0x3e, 0xd2, 0xff, 0x3b, - 0x9a, 0xa8, 0xf1, 0x7f, 0xae, 0x89, 0x52, 0x5a, 0x24, 0x47, 0xb5, 0xf4, 0x4d, 0xea, 0x28, 0xb8, 0xc8, 0x3b, 0x6a, - 0x21, 0x7b, 0x96, 0x8d, 0x1b, 0xd5, 0xbc, 0xff, 0x5f, 0x2b, 0xf3, 0xff, 0x35, 0xad, 0x0c, 0x53, 0xb2, 0x63, 0xa9, - 0x66, 0x1e, 0x68, 0x15, 0xc3, 0xec, 0x67, 0x92, 0x10, 0x19, 0x2e, 0x0d, 0xf8, 0x51, 0x05, 0xfb, 0x38, 0xad, 0xd6, - 0x59, 0xb8, 0x43, 0x25, 0xea, 0xad, 0xb8, 0x4b, 0xf3, 0x97, 0xf5, 0xbf, 0x45, 0x59, 0xc0, 0xd4, 0xbe, 0x2b, 0xd3, - 0x38, 0x20, 0x0b, 0x7f, 0x16, 0x96, 0x38, 0xb9, 0xb1, 0x8d, 0x3f, 0xcb, 0xf1, 0xb4, 0x5f, 0x75, 0x66, 0x1e, 0x48, - 0xa0, 0x06, 0xe2, 0x8f, 0x9c, 0xcb, 0xca, 0xe2, 0x01, 0xa1, 0x9b, 0x7f, 0x28, 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, 0xa7, 0xb1, 0x88, 0x47, 0x3d, 0x45, 0xc9, 0xf2, 0x26, 0x77, 0xe5, 0x5c, 0x7f, - 0xff, 0x07, 0x05, 0xb0, 0x1b, 0x30, 0xdb, 0x16, 0xd8, 0x01, 0x40, 0x82, 0x02, 0xd9, 0x42, 0x9d, 0x46, 0x67, 0x6a, - 0xa9, 0xc0, 0x7b, 0xae, 0x07, 0xf8, 0x9b, 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, 0xb7, 0x53, 0x45, 0x1e, 0x1f, 0xa5, 0x21, 0xaf, - 0xc0, 0x93, 0x8c, 0x23, 0x49, 0x94, 0x08, 0xde, 0xe4, 0x8d, 0x19, 0x87, 0x97, 0x6d, 0xca, 0xa9, 0xbd, 0x59, 0x2f, - 0x00, 0xe7, 0x09, 0xda, 0x32, 0xc0, 0x58, 0xc0, 0xe0, 0x5c, 0x88, 0x25, 0x4f, 0x11, 0xfc, 0xd2, 0x89, 0x14, 0xc6, - 0x5d, 0x0e, 0xc3, 0x3c, 0x28, 0x7a, 0x97, 0xd4, 0x1f, 0xfd, 0x3e, 0x6a, 0x93, 0xc1, 0x10, 0x54, 0x02, 0xa8, 0xac, - 0x1b, 0x24, 0x06, 0x56, 0xa5, 0x85, 0xc4, 0x25, 0xc4, 0xcb, 0x7c, 0x35, 0xad, 0xa3, 0xe0, 0x7d, 0x3d, 0x21, 0x84, - 0x13, 0x8c, 0x0f, 0x71, 0x03, 0x04, 0x0c, 0x56, 0x71, 0x81, 0x41, 0xf2, 0x5c, 0xa2, 0xfb, 0xe3, 0xf9, 0x8e, 0x01, - 0xae, 0x9c, 0xf7, 0x54, 0xbb, 0x7a, 0x60, 0x2f, 0x57, 0xe9, 0x92, 0x11, 0xc2, 0x8a, 0xff, 0x8b, 0xc8, 0xfb, 0x76, - 0x98, 0x80, 0xda, 0x46, 0xfe, 0x18, 0x24, 0xe6, 0x32, 0x51, 0x04, 0xf1, 0x28, 0x2b, 0x58, 0x92, 0x06, 0x9b, 0x51, - 0x92, 0x82, 0x46, 0x13, 0x63, 0xc8, 0x54, 0x68, 0x87, 0xa4, 0xd1, 0x6c, 0x4c, 0xf6, 0x31, 0xe4, 0x35, 0x5c, 0x2c, - 0x16, 0x78, 0xdf, 0xcf, 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, 0xcb, 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, 0x86, 0xd2, 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, 0xb3, 0xac, 0xc9, 0x5c, 0xbc, 0x2e, 0x1e, 0xbc, - 0x82, 0x3d, 0xf7, 0x07, 0xfa, 0x57, 0xc9, 0x9e, 0xfb, 0x36, 0x93, 0xeb, 0x9f, 0x69, 0xd7, 0x68, 0xcc, 0x74, 0xbc, - 0x76, 0x05, 0x56, 0x68, 0x80, 0xfc, 0x82, 0x1d, 0xed, 0x6d, 0x0e, 0x02, 0x01, 0xba, 0x97, 0xe0, 0x28, 0x0a, 0x88, - 0x9a, 0x56, 0x95, 0x47, 0xa7, 0x7b, 0x7f, 0x8f, 0x6f, 0x94, 0x80, 0x4d, 0x9e, 0x5a, 0xf7, 0x96, 0xb1, 0x7f, 0x38, - 0x40, 0x08, 0xbd, 0x9c, 0x7e, 0xa3, 0x2d, 0xab, 0x47, 0x3b, 0x96, 0xfb, 0x86, 0x51, 0x4f, 0xc1, 0x18, 0x86, 0x2e, - 0xac, 0x62, 0x24, 0xcf, 0x80, 0xac, 0xf1, 0x1b, 0x44, 0x17, 0xb0, 0xe8, 0xf5, 0x5e, 0x1f, 0xd1, 0x20, 0x02, 0x2a, - 0xbd, 0xe6, 0x2f, 0x45, 0x3e, 0x57, 0x85, 0xe8, 0xbd, 0xb7, 0x76, 0xde, 0xcc, 0x48, 0x96, 0x49, 0x23, 0xd5, 0x6e, - 0x65, 0xb1, 0xae, 0xbc, 0xd9, 0x09, 0xe9, 0x62, 0x8e, 0xa1, 0x32, 0x78, 0x1c, 0x80, 0xd2, 0xf3, 0x6f, 0xa1, 0x57, - 0x32, 0x64, 0x9a, 0x25, 0x9a, 0xd9, 0x5d, 0xe3, 0x4f, 0x56, 0xa9, 0x17, 0x23, 0x62, 0x36, 0xb0, 0x85, 0xb8, 0x2d, - 0x2a, 0xdd, 0x16, 0x85, 0xb2, 0x45, 0x91, 0x3e, 0xd4, 0xce, 0x74, 0x67, 0x16, 0x3e, 0xab, 0x4c, 0xfb, 0xde, 0x66, - 0x66, 0x6c, 0x80, 0xb6, 0x8b, 0xf0, 0x0d, 0x74, 0xa0, 0x42, 0xc8, 0x7f, 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, 0x5f, 0x53, - 0xb7, 0x67, 0xe5, 0x64, 0x2f, 0x3a, 0x27, 0xfb, 0x74, 0x36, 0x0f, 0x04, 0x97, 0x3b, 0xf7, 0x79, 0x3e, 0xd5, 0xd3, - 0xae, 0xf2, 0x83, 0xd6, 0x10, 0x99, 0x2f, 0x7c, 0xaa, 0xba, 0xd7, 0x15, 0x2c, 0x60, 0x09, 0xee, 0xd6, 0x4b, 0xf3, - 0x5f, 0xb1, 0xfb, 0x7b, 0x41, 0x2f, 0xcd, 0x7f, 0xa3, 0x3f, 0x29, 0x80, 0x03, 0xd0, 0x98, 0xda, 0x2d, 0xf0, 0x10, - 0x43, 0x05, 0x85, 0xbb, 0x59, 0x39, 0xf7, 0x6a, 0x80, 0xc3, 0x24, 0x7d, 0x43, 0xab, 0x57, 0x5a, 0xec, 0x7a, 0x99, - 0xec, 0x15, 0xe0, 0xa1, 0x0a, 0x79, 0x78, 0x38, 0x44, 0x1d, 0xc3, 0x0e, 0xea, 0x08, 0x18, 0xf6, 0x10, 0x1a, 0x5b, - 0xe0, 0xf9, 0xf8, 0x29, 0xe3, 0x7b, 0x01, 0x6a, 0x23, 0x84, 0xc7, 0xab, 0x45, 0x19, 0x62, 0xcb, 0xde, 0x22, 0x95, - 0xd4, 0xcf, 0x02, 0x51, 0x46, 0xab, 0x80, 0xb6, 0xda, 0x63, 0x96, 0xc6, 0x1b, 0x08, 0x15, 0x4b, 0x7d, 0x0c, 0xa1, - 0x81, 0xc3, 0xef, 0x70, 0x00, 0x09, 0xbe, 0xe4, 0x9a, 0x6c, 0xee, 0x6d, 0x7e, 0x4f, 0xfb, 0xfc, 0xe1, 0x70, 0x7e, - 0x89, 0xa0, 0x74, 0x29, 0x7c, 0xa4, 0x12, 0x51, 0x3d, 0xc5, 0x4d, 0x09, 0xd9, 0x2c, 0x59, 0xe9, 0x07, 0xbf, 0xaa, - 0x5f, 0x00, 0x20, 0x0b, 0x81, 0x36, 0x91, 0xd9, 0x9f, 0xce, 0x54, 0x74, 0x01, 0x70, 0x88, 0x3f, 0x7e, 0x82, 0xe8, - 0x1b, 0x5a, 0xa6, 0xe5, 0xe3, 0x84, 0x87, 0xa0, 0xb5, 0x25, 0x9d, 0x44, 0xac, 0x14, 0xd8, 0x10, 0x09, 0xdf, 0xef, - 0x9f, 0xc7, 0x92, 0x0e, 0x34, 0x6a, 0x75, 0x6f, 0xdc, 0xea, 0x5e, 0xf9, 0xba, 0xee, 0xe4, 0xc6, 0x07, 0x45, 0xfb, - 0x6c, 0xde, 0xa8, 0x7c, 0xdf, 0xd6, 0x39, 0xbb, 0xd3, 0xbd, 0x23, 0xe7, 0xc4, 0xb7, 0xf7, 0x10, 0x8a, 0x1e, 0x9a, - 0x22, 0xcb, 0x92, 0x30, 0xa0, 0xb5, 0x76, 0xed, 0x59, 0x46, 0x07, 0xaf, 0x7d, 0x43, 0x88, 0xc8, 0x53, 0x7c, 0x12, - 0x72, 0x8b, 0xe3, 0x83, 0x02, 0xfd, 0x33, 0xe3, 0xcf, 0x9c, 0xf8, 0x61, 0xab, 0x5f, 0x00, 0xe7, 0xa6, 0x7b, 0xef, - 0x4e, 0xcc, 0x7a, 0x0c, 0xa5, 0x6c, 0xfc, 0xdf, 0xef, 0x13, 0x59, 0xa0, 0xd3, 0x11, 0x0d, 0x03, 0xc1, 0x5d, 0x54, - 0xff, 0xf7, 0x8a, 0xd7, 0x3d, 0x6b, 0x75, 0xbe, 0xfc, 0xd4, 0xe9, 0x49, 0xaf, 0x5e, 0xc6, 0x3d, 0xa0, 0x42, 0x07, - 0x08, 0xe7, 0x75, 0xbf, 0x61, 0xbb, 0x6f, 0x7e, 0x79, 0x77, 0xf4, 0x32, 0xb0, 0x49, 0x91, 0xd8, 0x56, 0xf2, 0x59, - 0x0f, 0x14, 0x7e, 0x3d, 0xd6, 0xab, 0x8b, 0x75, 0x8f, 0xf5, 0x50, 0x0b, 0x88, 0x1e, 0x16, 0xa0, 0xfe, 0xeb, 0xd9, - 0xa7, 0xa1, 0x70, 0x90, 0x8d, 0x53, 0x05, 0x8a, 0x2c, 0xf8, 0x0b, 0x31, 0x5a, 0x17, 0x04, 0x88, 0x6c, 0x09, 0x69, - 0xd5, 0xc9, 0xec, 0x71, 0xa9, 0x25, 0x19, 0x7c, 0x13, 0x90, 0xd9, 0x81, 0x95, 0x13, 0x94, 0x8e, 0x5b, 0x03, 0xae, - 0x6c, 0xf1, 0x68, 0xb7, 0x3f, 0x0d, 0xb2, 0xb3, 0xe6, 0xa4, 0xd1, 0x3e, 0xec, 0xd3, 0x3c, 0x40, 0x20, 0x92, 0xa9, - 0x08, 0x72, 0xcd, 0xbd, 0x25, 0x7d, 0x74, 0x38, 0xe7, 0x85, 0xfc, 0x73, 0x2a, 0x75, 0x88, 0x43, 0x89, 0x35, 0x10, - 0xa8, 0x3c, 0x43, 0x95, 0xc3, 0x06, 0x39, 0xfe, 0xd9, 0x91, 0xcc, 0x24, 0x26, 0x8b, 0xdc, 0xad, 0x99, 0x0a, 0x3f, - 0x10, 0x7c, 0xcc, 0x72, 0x0e, 0x5c, 0x60, 0xb3, 0xb9, 0xaf, 0xa6, 0xb8, 0xb8, 0x02, 0x7f, 0x4c, 0xe1, 0x57, 0x3c, - 0x85, 0x9d, 0x76, 0xbf, 0x2e, 0xaa, 0x14, 0x75, 0x1b, 0x85, 0x45, 0x25, 0x0b, 0xa6, 0x35, 0xa4, 0x89, 0x0e, 0xa3, - 0x3f, 0xc8, 0x19, 0x28, 0x08, 0xf9, 0x65, 0xd3, 0x00, 0x23, 0x95, 0x5c, 0x1e, 0x54, 0x49, 0xe0, 0x05, 0xd8, 0x06, - 0x15, 0x5b, 0x17, 0x10, 0x64, 0x9b, 0x14, 0x65, 0xfa, 0xa5, 0xc8, 0xeb, 0x30, 0x0b, 0xaa, 0x51, 0x5a, 0xfd, 0xa8, - 0x7f, 0x02, 0xf3, 0x36, 0x15, 0xa3, 0x5a, 0xc5, 0xe4, 0x37, 0xfa, 0xfd, 0x62, 0xd0, 0xfa, 0x90, 0xc1, 0x47, 0xaf, - 0x4d, 0x83, 0x3f, 0x3a, 0x0d, 0x76, 0x98, 0x68, 0x04, 0x40, 0x32, 0xa7, 0x96, 0x3c, 0x14, 0xfd, 0x11, 0xe4, 0x58, - 0xa3, 0xca, 0x29, 0x18, 0xac, 0xff, 0x78, 0xb4, 0x03, 0x53, 0x2f, 0x8e, 0xb6, 0x64, 0x07, 0xad, 0x7c, 0x03, 0xdc, - 0xaf, 0x91, 0x2d, 0x66, 0x39, 0x40, 0xb3, 0xd7, 0x88, 0x8c, 0x4f, 0x5e, 0x00, 0x63, 0xb6, 0xce, 0xc2, 0x48, 0xc4, - 0xc1, 0x58, 0x35, 0x66, 0xcc, 0xc0, 0xc0, 0x05, 0xba, 0x96, 0x49, 0x49, 0x1a, 0xd2, 0xc1, 0x80, 0x95, 0xb2, 0x85, - 0x03, 0x5e, 0x34, 0xc7, 0xed, 0x78, 0xd3, 0xa2, 0xf1, 0xc0, 0x76, 0xb1, 0xfd, 0xfd, 0xf7, 0xc5, 0xf6, 0x3a, 0xdc, - 0x92, 0x5e, 0x21, 0x67, 0x09, 0xfd, 0xfc, 0x51, 0xf6, 0x59, 0xc3, 0xc9, 0xa9, 0xd0, 0x0c, 0x2d, 0x45, 0x42, 0x29, - 0xde, 0xe9, 0x49, 0x81, 0xb1, 0x8c, 0x85, 0xbf, 0x07, 0xce, 0xe9, 0x42, 0x11, 0xb9, 0x03, 0xc7, 0xf1, 0x0d, 0x54, - 0x30, 0x6a, 0x38, 0x78, 0x19, 0xc3, 0xb6, 0x28, 0x66, 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, - 0xe5, 0x41, 0x04, 0x90, 0xcf, 0xe1, 0x7d, 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, 0x8b, 0x33, 0xd8, 0x38, - 0xd7, 0x99, 0xe0, 0xc0, 0x8b, 0xa4, 0xd6, 0x6b, 0xc6, 0x5f, 0x64, 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, 0xfe, 0x5c, 0x49, 0x1c, 0x5a, 0x16, 0xc9, 0xbf, 0x77, 0x3d, - 0x7d, 0x85, 0xd4, 0x9d, 0x2c, 0x90, 0x19, 0xe3, 0x65, 0x1e, 0x7f, 0x02, 0xc2, 0x6c, 0xd0, 0x46, 0x45, 0x21, 0x84, - 0x6c, 0x10, 0x83, 0xc6, 0xcb, 0x3c, 0xfe, 0x5e, 0xd1, 0x78, 0xc8, 0x47, 0x91, 0xaf, 0xfe, 0x2a, 0xf5, 0x5f, 0xa1, - 0xcf, 0x4c, 0xf0, 0x08, 0xd5, 0x44, 0xff, 0xee, 0xf9, 0xec, 0x1e, 0xd4, 0x86, 0x51, 0x98, 0x99, 0xf2, 0x2b, 0xdf, - 0x14, 0x67, 0xaf, 0xbf, 0xa2, 0xab, 0x6c, 0xeb, 0x7e, 0xf4, 0xf1, 0x88, 0xc0, 0xda, 0x18, 0x5d, 0x71, 0x63, 0x00, - 0x39, 0x4c, 0xde, 0xaf, 0x28, 0x2d, 0x87, 0x34, 0x08, 0x1d, 0x34, 0x04, 0xbd, 0x92, 0xe8, 0x03, 0x89, 0x45, 0x8c, - 0xe1, 0x85, 0x78, 0x46, 0x6a, 0x32, 0xd1, 0x10, 0xaf, 0x88, 0xfd, 0x10, 0x2d, 0x39, 0x35, 0xd1, 0x8d, 0x30, 0xc5, - 0x40, 0x62, 0x67, 0x90, 0x9c, 0x24, 0xb5, 0xf2, 0x8b, 0x67, 0x92, 0xb0, 0xc4, 0xce, 0x43, 0x0c, 0x26, 0xb5, 0x74, - 0xa7, 0x37, 0x55, 0x7a, 0x77, 0xa4, 0xe5, 0xa0, 0x7d, 0x00, 0x76, 0x29, 0xe9, 0xfd, 0x93, 0x42, 0x11, 0x1f, 0xc2, - 0x38, 0x86, 0xf0, 0x2d, 0xa2, 0xba, 0x02, 0xe7, 0x5a, 0x81, 0xc6, 0x6a, 0xe0, 0xa1, 0x99, 0x55, 0xf3, 0x21, 0xa7, - 0x9f, 0x4a, 0xcb, 0x1f, 0x23, 0x1a, 0x1b, 0xad, 0x9b, 0xc3, 0x61, 0x4f, 0xab, 0x5e, 0x3a, 0x07, 0x5d, 0x36, 0x93, - 0x98, 0xb8, 0x81, 0x74, 0xfd, 0xe8, 0x37, 0x13, 0xf6, 0x22, 0x2a, 0xe4, 0x52, 0x08, 0x0a, 0x5a, 0x1d, 0x08, 0x1c, - 0x0a, 0x6f, 0x51, 0xe6, 0x8b, 0x98, 0x36, 0x10, 0x06, 0x9f, 0x1f, 0xc8, 0xcf, 0x37, 0x05, 0xa9, 0xd8, 0xb1, 0xae, - 0xfd, 0xfe, 0xa6, 0xf4, 0x00, 0x4f, 0xce, 0x24, 0x79, 0xda, 0x0c, 0x61, 0x45, 0x00, 0x8d, 0x59, 0x4d, 0x16, 0x27, - 0x5c, 0x99, 0xc3, 0x8f, 0x95, 0x57, 0xb2, 0x94, 0xa9, 0xf3, 0x54, 0x2f, 0x80, 0xa8, 0xe3, 0x0d, 0x5a, 0x91, 0xfa, - 0x15, 0x3a, 0x7b, 0xcd, 0x4a, 0xc8, 0x78, 0x78, 0xce, 0x79, 0x3a, 0x7a, 0x60, 0x09, 0x8f, 0xf0, 0xaf, 0x64, 0xa2, - 0x0f, 0xbf, 0x07, 0x0e, 0x37, 0xe3, 0x84, 0x47, 0x6e, 0xb3, 0xf7, 0x55, 0xb8, 0x82, 0x9b, 0x69, 0x01, 0x48, 0x6e, - 0x41, 0xd2, 0x04, 0x94, 0x90, 0xc8, 0x84, 0xcc, 0x9a, 0x92, 0x9f, 0x5b, 0xda, 0x06, 0x6b, 0x98, 0x74, 0x1e, 0xf0, - 0xa2, 0xd5, 0x47, 0xab, 0x89, 0x76, 0x99, 0xe5, 0xf3, 0x21, 0xce, 0x50, 0xcd, 0x71, 0x77, 0x06, 0x3f, 0x07, 0xbc, - 0x62, 0x55, 0x93, 0x8e, 0x76, 0x03, 0x2e, 0x3c, 0xb9, 0xce, 0xd3, 0xd1, 0x16, 0x7f, 0xc9, 0xfd, 0x01, 0xa0, 0x83, - 0xa9, 0x4b, 0xe0, 0x4f, 0xd5, 0x56, 0x53, 0xa9, 0x5f, 0x5a, 0xfb, 0x75, 0xdd, 0x59, 0xad, 0xdc, 0xb3, 0x2e, 0x43, - 0x7b, 0x64, 0xc8, 0x19, 0x33, 0xe0, 0xcf, 0x19, 0x4b, 0xfe, 0x9c, 0xb1, 0xe2, 0xcf, 0x19, 0x37, 0x46, 0x06, 0x50, - 0x82, 0x7b, 0xc9, 0x5f, 0xec, 0x11, 0x33, 0xc4, 0x6a, 0x50, 0x09, 0xac, 0x2c, 0xe5, 0xdc, 0x47, 0x4e, 0x31, 0xe5, - 0x94, 0xe1, 0xa5, 0xd3, 0x99, 0x3b, 0x90, 0xf3, 0x60, 0xe6, 0x0e, 0x93, 0xb3, 0x3e, 0xc5, 0xb1, 0x34, 0x26, 0x45, - 0x05, 0xe9, 0x9c, 0x0e, 0x37, 0xaf, 0x8e, 0xf3, 0x84, 0x65, 0x7c, 0xdc, 0x3e, 0x53, 0x20, 0xc4, 0x16, 0xcf, 0x90, - 0x48, 0xa9, 0x9a, 0xe5, 0x36, 0x7f, 0x38, 0xd4, 0xa3, 0x07, 0xbd, 0xd3, 0xc3, 0xaf, 0x84, 0xfd, 0x92, 0x79, 0xf6, - 0x09, 0x02, 0x98, 0x24, 0xf2, 0x4c, 0xc2, 0xd1, 0x8f, 0xe5, 0xe8, 0x6f, 0x1a, 0xfe, 0x2e, 0x43, 0x75, 0x77, 0x08, - 0x4c, 0x6c, 0xd9, 0x81, 0x43, 0x70, 0xba, 0xaa, 0x44, 0x02, 0x0e, 0x36, 0x1b, 0x16, 0xe9, 0x3d, 0x1e, 0xe2, 0x7c, - 0x50, 0xf8, 0x08, 0x0d, 0x33, 0x7a, 0xbf, 0xbf, 0x11, 0x5e, 0x25, 0x5b, 0x79, 0x38, 0x24, 0xd6, 0x5d, 0xd8, 0xd1, - 0xc7, 0xd1, 0x1e, 0x25, 0xd4, 0x7e, 0x54, 0xeb, 0x4d, 0xa5, 0x1e, 0xe4, 0x66, 0x17, 0x12, 0x83, 0x8a, 0xa5, 0xfa, - 0xf4, 0x4a, 0xf5, 0xa1, 0x66, 0x9d, 0xdf, 0xd5, 0x71, 0x9f, 0x8a, 0xd1, 0x5a, 0x4e, 0x08, 0x70, 0x1d, 0x24, 0x1a, - 0x1d, 0x00, 0xe3, 0x6c, 0xb3, 0xe5, 0xa5, 0xb6, 0x4e, 0x94, 0x8e, 0xe3, 0x5c, 0x1f, 0xc7, 0x87, 0x83, 0x14, 0x33, - 0x2e, 0x8f, 0xc4, 0x8c, 0xcb, 0x06, 0xe0, 0xcd, 0x3a, 0x0f, 0xea, 0xc3, 0xe1, 0x92, 0x2e, 0x45, 0xa6, 0xb3, 0x8d, - 0xf2, 0xb3, 0x1e, 0x3d, 0x3c, 0x4b, 0xd0, 0xdc, 0x5b, 0x61, 0xef, 0x45, 0xb2, 0x3d, 0x93, 0x75, 0xea, 0x65, 0xe4, - 0xd3, 0x0b, 0xf7, 0xec, 0x92, 0xab, 0x1f, 0x56, 0x5f, 0x4f, 0x7f, 0x15, 0x5e, 0xc4, 0x2a, 0xda, 0xad, 0x4b, 0x26, - 0xec, 0x2d, 0xa5, 0x92, 0x56, 0x79, 0xf9, 0x74, 0xe3, 0x07, 0x98, 0x99, 0xf6, 0xf4, 0x41, 0x36, 0xa2, 0xfa, 0xb3, - 0x12, 0xb5, 0x32, 0x4c, 0x16, 0xce, 0x4b, 0xa6, 0x9e, 0x0c, 0x78, 0xcc, 0x4a, 0x1e, 0xc9, 0x4e, 0x6f, 0x0c, 0x82, - 0x00, 0xd6, 0x39, 0x69, 0xd5, 0x19, 0x47, 0xa3, 0x55, 0xe5, 0xe2, 0x74, 0x95, 0x0b, 0x0c, 0xb7, 0x5b, 0xb3, 0x8d, - 0xaa, 0xb3, 0xdc, 0xd4, 0x2a, 0xe5, 0x3b, 0x80, 0x8f, 0x65, 0x95, 0x0b, 0x3a, 0xa6, 0x4c, 0x9d, 0x37, 0x10, 0x8c, - 0xad, 0x6a, 0x5c, 0x38, 0x35, 0x2e, 0x78, 0x44, 0xed, 0x6e, 0x9a, 0x7a, 0xb4, 0x05, 0x96, 0xd2, 0xd1, 0x8e, 0x97, - 0xa8, 0x52, 0xf8, 0xbb, 0xe0, 0xfb, 0x30, 0x8e, 0xbf, 0x2f, 0xb6, 0xea, 0x40, 0xbc, 0x2d, 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, 0x09, 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, 0x58, 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, 0x1f, 0x55, 0x36, 0x76, 0x07, 0xe4, 0x90, 0x64, 0xb2, 0xb8, 0x1b, 0xdd, - 0x8a, 0x65, 0x51, 0x8a, 0x9f, 0xb1, 0x1e, 0xae, 0xd9, 0xc2, 0x7d, 0x06, 0x84, 0xf6, 0x13, 0xa5, 0xbd, 0x89, 0x34, - 0x41, 0xf7, 0x1d, 0x5b, 0x01, 0xc8, 0x00, 0x8a, 0xba, 0xda, 0xad, 0xcf, 0xf9, 0x39, 0x92, 0x66, 0x38, 0x8c, 0x6e, - 0x9f, 0xde, 0x05, 0x77, 0x83, 0x4b, 0xd4, 0x4a, 0x5f, 0xb2, 0xb8, 0x85, 0x41, 0xb5, 0x37, 0x4b, 0x38, 0xa8, 0x99, - 0xb5, 0x36, 0x02, 0xc1, 0x64, 0x0f, 0x05, 0x15, 0x73, 0x05, 0xfb, 0xa0, 0x60, 0x2d, 0x79, 0x1d, 0x1c, 0x6e, 0xed, - 0xcb, 0x4a, 0x71, 0xf1, 0xfc, 0x22, 0x69, 0x5d, 0x58, 0xca, 0x8b, 0xe7, 0x0d, 0x18, 0x5c, 0x8e, 0xb0, 0xa9, 0x2a, - 0x7f, 0xb2, 0x01, 0xd0, 0xad, 0x90, 0x22, 0x5e, 0x94, 0xc2, 0xb6, 0x95, 0xcf, 0x9c, 0xb0, 0xc1, 0x86, 0x3d, 0xc0, - 0xbd, 0x32, 0x28, 0x19, 0x5c, 0x88, 0x71, 0xbb, 0xd9, 0x05, 0xb8, 0x82, 0xa1, 0x30, 0xb6, 0xe6, 0x6f, 0x32, 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, 0x7c, 0xce, 0xbc, 0xa5, 0xcf, 0xde, 0x54, 0x32, 0x5a, 0x93, 0x44, - 0x79, 0xf5, 0x70, 0x09, 0x72, 0xc3, 0x72, 0xf4, 0xc0, 0x96, 0x20, 0x4e, 0x2c, 0x47, 0x09, 0x65, 0x74, 0x85, 0x7b, - 0x95, 0xd9, 0x32, 0x11, 0x48, 0x71, 0x60, 0x29, 0xe5, 0xde, 0x62, 0x1d, 0x2c, 0x71, 0x7f, 0x22, 0xb9, 0x80, 0x92, - 0x07, 0x50, 0xae, 0x14, 0x10, 0xf0, 0xe9, 0x00, 0xca, 0x97, 0xf2, 0x22, 0xfc, 0x89, 0x13, 0x35, 0x58, 0x8e, 0x1e, - 0x1a, 0xf6, 0xa3, 0x17, 0x5a, 0xf6, 0x87, 0x3b, 0xad, 0x69, 0x58, 0xf1, 0x3b, 0x98, 0x16, 0x13, 0xb7, 0x2f, 0x57, - 0x76, 0x55, 0x7c, 0xb6, 0x52, 0x67, 0x37, 0x35, 0x24, 0x61, 0x5f, 0x91, 0x55, 0x80, 0x83, 0x55, 0x11, 0xf7, 0x2c, - 0xcb, 0x7d, 0x18, 0xfd, 0xb9, 0x49, 0x4b, 0x61, 0xa1, 0x4a, 0xfa, 0xfb, 0xa6, 0x14, 0x48, 0x65, 0xa2, 0x13, 0x2d, - 0x04, 0x57, 0x60, 0x10, 0xb8, 0x17, 0x79, 0x0d, 0x80, 0x31, 0xe0, 0x52, 0xa0, 0x2c, 0xdb, 0x12, 0x42, 0xaa, 0xfb, - 0x19, 0xa8, 0xed, 0xc4, 0x7d, 0x1a, 0x91, 0xb5, 0x10, 0x7d, 0x15, 0x8c, 0x99, 0xf3, 0x52, 0xba, 0xc5, 0xa6, 0xab, - 0xcd, 0xea, 0x06, 0x9d, 0x4b, 0x5b, 0x6e, 0x7e, 0xc2, 0x16, 0x6b, 0x05, 0xca, 0x26, 0x24, 0x6d, 0xe7, 0x3c, 0x47, - 0xd9, 0x84, 0x96, 0xf6, 0x9e, 0x7a, 0x54, 0xa8, 0x4e, 0xb6, 0x5e, 0xaa, 0xa6, 0x16, 0x61, 0xb5, 0xb8, 0xa8, 0xfc, - 0x00, 0x74, 0x53, 0x69, 0xf5, 0xb2, 0xae, 0xd1, 0x14, 0x6a, 0xb5, 0x70, 0xdc, 0x68, 0x67, 0xd3, 0x65, 0x7a, 0x87, - 0x38, 0xab, 0xd2, 0x0e, 0xfd, 0x7d, 0xa6, 0x5d, 0x2f, 0x3b, 0xfa, 0xcd, 0xb8, 0xba, 0xc0, 0x85, 0xd8, 0x80, 0xcf, - 0xb9, 0xbf, 0xbc, 0xde, 0xf3, 0xb8, 0xe7, 0x1f, 0x0e, 0xc8, 0x9e, 0xd4, 0xfe, 0x50, 0x7d, 0xec, 0x0a, 0x86, 0x2c, - 0x8c, 0x52, 0x7f, 0x91, 0xf2, 0xde, 0x13, 0x1c, 0xf7, 0xcf, 0x55, 0x8f, 0xfd, 0x98, 0xf1, 0x7d, 0x5d, 0x6c, 0xa2, - 0x84, 0xa2, 0x1a, 0x7a, 0xab, 0x62, 0x53, 0x89, 0xb8, 0x78, 0xc8, 0x7b, 0x0c, 0x93, 0x61, 0x2c, 0x64, 0x2a, 0xfc, - 0x29, 0x53, 0xc1, 0x23, 0x84, 0x12, 0x37, 0xeb, 0x1e, 0x69, 0x37, 0x21, 0x4e, 0xa9, 0x16, 0xa5, 0x4c, 0xc6, 0xbf, - 0xf5, 0x13, 0x28, 0xcf, 0x29, 0x5a, 0xa6, 0x1f, 0x15, 0x2e, 0xd3, 0x37, 0xeb, 0xe3, 0xd2, 0x33, 0x11, 0xea, 0xcc, - 0xc5, 0xa6, 0xd6, 0xe9, 0x18, 0x3b, 0xa5, 0x53, 0x1b, 0xf6, 0xa5, 0x52, 0x5c, 0x56, 0x14, 0xfe, 0x8d, 0x44, 0x56, - 0x3d, 0x23, 0x8e, 0xff, 0x2b, 0x6b, 0x9f, 0x61, 0x15, 0xf8, 0x65, 0x20, 0xef, 0x17, 0x00, 0x1f, 0xd7, 0x75, 0x99, - 0xde, 0x6e, 0x80, 0x36, 0x84, 0x86, 0xbf, 0xe7, 0x23, 0x03, 0xa6, 0xfb, 0x08, 0x67, 0x48, 0x0f, 0x75, 0xce, 0xe9, - 0xac, 0x4c, 0xe7, 0x5c, 0x85, 0xb5, 0x04, 0x7b, 0x39, 0x69, 0x72, 0xb9, 0x2e, 0x41, 0xcd, 0x04, 0x6e, 0x1f, 0xda, - 0x23, 0x42, 0xa8, 0x4d, 0x59, 0x4d, 0x2f, 0xa1, 0xe6, 0x9d, 0x9c, 0x76, 0x34, 0x29, 0xc1, 0x55, 0x43, 0x67, 0xe5, - 0xfa, 0xaf, 0xc3, 0xa1, 0x77, 0x9b, 0x15, 0xd1, 0x1f, 0x3d, 0xf4, 0x77, 0xdc, 0xde, 0xa4, 0x5f, 0x20, 0x5a, 0xc6, - 0xfa, 0x1b, 0x32, 0xa0, 0xe3, 0xc9, 0xf0, 0xb6, 0xd8, 0xf6, 0xd8, 0x17, 0xd4, 0x60, 0xe9, 0xeb, 0xc7, 0x1f, 0x20, - 0xa1, 0xea, 0xda, 0x17, 0x16, 0x4f, 0x98, 0xa7, 0x44, 0xdb, 0xc2, 0x87, 0xb0, 0xd0, 0x2f, 0x10, 0x19, 0x09, 0xe1, - 0xa6, 0xb2, 0x7b, 0x94, 0xb4, 0x0b, 0x7d, 0xe9, 0x6b, 0xd9, 0x57, 0xbe, 0x73, 0x01, 0xb0, 0xb2, 0xcf, 0x6d, 0xb8, - 0x27, 0xfd, 0x29, 0xd5, 0x87, 0xed, 0x6f, 0xc9, 0x02, 0x0a, 0x2d, 0xac, 0xa7, 0x72, 0x76, 0xae, 0x4b, 0x9e, 0x66, - 0xd3, 0xfd, 0x1a, 0xf6, 0xa8, 0x7b, 0xf4, 0x9a, 0x0a, 0xce, 0x2f, 0xcd, 0xe8, 0xfd, 0xd3, 0x50, 0xa8, 0x8e, 0x3a, - 0x77, 0x90, 0x75, 0x69, 0x5d, 0x72, 0x7e, 0xb3, 0x72, 0x47, 0x61, 0x7e, 0x1f, 0x82, 0x67, 0x58, 0xf7, 0xee, 0xe2, - 0xbc, 0xf7, 0x67, 0x6b, 0x8e, 0xfc, 0x98, 0xcd, 0x52, 0xc4, 0x22, 0x99, 0x83, 0xd5, 0x0f, 0xfd, 0x3c, 0xf6, 0xdb, - 0x20, 0x87, 0xe3, 0xa6, 0x01, 0x1d, 0x36, 0x64, 0xd6, 0xbe, 0x44, 0xe0, 0x54, 0x23, 0x48, 0x53, 0x13, 0xd4, 0x2c, - 0x0f, 0x91, 0xd8, 0x2e, 0x65, 0xdb, 0x20, 0xd7, 0x5d, 0x30, 0xcd, 0x91, 0xf6, 0x0c, 0xde, 0x37, 0x69, 0x92, 0x0a, - 0xcd, 0x22, 0x6d, 0x95, 0x8c, 0x7f, 0x47, 0xda, 0x4c, 0xc9, 0x1e, 0x5b, 0x03, 0xef, 0x25, 0x28, 0x27, 0xc3, 0x14, - 0xc3, 0x77, 0x7c, 0xbd, 0xf3, 0x98, 0x7b, 0xce, 0x31, 0xdb, 0xa4, 0xec, 0x08, 0x26, 0xc9, 0xc6, 0x37, 0x14, 0x6f, - 0xf8, 0xfe, 0xb6, 0x12, 0x25, 0x80, 0x5e, 0x16, 0xfc, 0x85, 0xb4, 0xb9, 0x42, 0xb7, 0xbb, 0x77, 0x94, 0xc2, 0x2f, - 0x79, 0x79, 0x38, 0x6c, 0x53, 0x2f, 0x84, 0xce, 0x17, 0xf1, 0x3b, 0x30, 0x87, 0x31, 0xc4, 0x66, 0x04, 0x08, 0x73, - 0x7c, 0x40, 0x1d, 0xac, 0x1f, 0x01, 0x68, 0x9c, 0x40, 0x01, 0x46, 0x5f, 0x6d, 0x0b, 0xfa, 0x96, 0x17, 0x17, 0x11, - 0xa2, 0x46, 0x01, 0x26, 0x4a, 0x9a, 0xc5, 0x30, 0x1c, 0xe8, 0xfc, 0xbe, 0xb9, 0xad, 0x4b, 0x81, 0x43, 0xef, 0x58, - 0x86, 0xff, 0xfe, 0x3f, 0xd6, 0x96, 0x56, 0x95, 0xed, 0xd6, 0x38, 0xcd, 0xfc, 0x6f, 0xb7, 0x85, 0xbe, 0xff, 0x4a, - 0x28, 0x9e, 0x77, 0xbc, 0x6e, 0xbf, 0x83, 0xe8, 0x7d, 0xdd, 0xca, 0xbb, 0x52, 0xbb, 0x61, 0xa6, 0xfc, 0x21, 0xcd, - 0xe3, 0xe2, 0x61, 0x14, 0xb7, 0x8e, 0xbc, 0x49, 0x7a, 0xce, 0xf9, 0xbb, 0xaa, 0xdf, 0xf7, 0xde, 0x01, 0x19, 0xef, - 0x2b, 0x61, 0x1c, 0x31, 0x89, 0x83, 0x6f, 0x2f, 0x46, 0xd1, 0xa6, 0x84, 0x0d, 0xb9, 0x7d, 0x5a, 0x82, 0x66, 0xa6, - 0xdf, 0x47, 0x89, 0xd2, 0x9a, 0xef, 0x7f, 0x93, 0xf3, 0xfd, 0x95, 0x90, 0x37, 0x2b, 0xf9, 0xe1, 0xa3, 0x15, 0x06, - 0xbe, 0xc7, 0xe9, 0x17, 0xd1, 0x63, 0x77, 0xa5, 0x0f, 0xdf, 0x95, 0x96, 0x3e, 0xab, 0xa8, 0x7f, 0xa0, 0xa2, 0xe6, - 0x95, 0x18, 0x11, 0xf1, 0x20, 0x68, 0x67, 0xdb, 0xa5, 0x76, 0x2d, 0x41, 0xbb, 0x60, 0x53, 0xd8, 0xbf, 0x1f, 0x1d, - 0xf2, 0x7e, 0xff, 0x63, 0xee, 0xb5, 0x78, 0xdd, 0x75, 0x68, 0xca, 0x4f, 0x85, 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, 0x11, 0xeb, 0xa6, 0xa7, 0x55, 0x68, 0xf9, 0x1a, 0x82, 0x75, 0x91, 0x65, 0x1c, 0xc5, - 0x4c, 0x00, 0xb0, 0xf9, 0x08, 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, - 0x7b, 0xaa, 0x7a, 0x44, 0xa0, 0x57, 0x65, 0x5a, 0x45, 0x45, 0x9e, 0x8b, 0x08, 0x11, 0xaa, 0xa5, 0x73, 0x38, 0xf4, - 0x63, 0xbf, 0x8f, 0x03, 0x61, 0x5e, 0xfc, 0xe9, 0xb1, 0xae, 0xfc, 0xa9, 0xc0, 0xb5, 0x92, 0x02, 0xa7, 0xa2, 0x46, - 0x88, 0x10, 0xde, 0x9f, 0xc0, 0xb3, 0x9a, 0xfa, 0x7e, 0x63, 0x99, 0xe8, 0xfe, 0x99, 0x01, 0xe5, 0x0f, 0xc8, 0xd7, - 0x95, 0x14, 0x67, 0xea, 0xe4, 0x31, 0x71, 0xc6, 0x01, 0x88, 0xf9, 0xba, 0x44, 0xa3, 0xb1, 0xff, 0x01, 0x09, 0x86, - 0xea, 0x07, 0x3b, 0xdd, 0xd4, 0xfb, 0x57, 0x26, 0x71, 0x14, 0x7d, 0xda, 0x26, 0x8f, 0x25, 0x4b, 0xa3, 0x85, 0xa3, - 0xf7, 0x88, 0x61, 0x1c, 0x4e, 0xe7, 0x63, 0x92, 0x6d, 0x4c, 0x56, 0x01, 0xa4, 0x93, 0x99, 0x3a, 0xa6, 0xd4, 0xd1, - 0x38, 0xd7, 0x0b, 0xaa, 0xd0, 0x63, 0x5d, 0xf2, 0x1c, 0xac, 0x27, 0x3f, 0x78, 0xa5, 0x3f, 0x15, 0x72, 0x0e, 0x1b, - 0x89, 0xa0, 0xf0, 0x03, 0x5c, 0x0d, 0x56, 0x0a, 0x18, 0x4c, 0x7d, 0x0b, 0x5f, 0x13, 0xcf, 0x51, 0xf0, 0x28, 0xec, - 0x62, 0x6c, 0xad, 0x7c, 0xe7, 0x93, 0x82, 0x72, 0xcf, 0x8a, 0x39, 0xaf, 0x80, 0x73, 0x19, 0x14, 0xc2, 0x74, 0x3c, - 0xcb, 0xff, 0x99, 0xe4, 0xf5, 0xc4, 0x86, 0x00, 0x19, 0xfc, 0x29, 0x71, 0x5a, 0xba, 0x43, 0x77, 0x1e, 0x7a, 0x16, - 0x71, 0xd8, 0xe8, 0xc9, 0xba, 0x2c, 0xb6, 0x29, 0xea, 0x25, 0xcc, 0x0f, 0xe4, 0xe7, 0x2d, 0xf9, 0x3e, 0x44, 0xf1, - 0x36, 0xf8, 0x35, 0x63, 0xb1, 0xc0, 0xbf, 0xfe, 0x9e, 0x31, 0x9a, 0x68, 0xc1, 0xbf, 0xb3, 0x06, 0x89, 0x8a, 0x7f, - 0xca, 0x26, 0x00, 0xeb, 0xc8, 0xd5, 0x87, 0x4f, 0x89, 0xf1, 0xd6, 0x6c, 0x78, 0xe4, 0x9b, 0x15, 0xe8, 0xd4, 0xe7, - 0xee, 0xca, 0xf6, 0x54, 0x35, 0xfe, 0x9e, 0xea, 0x6a, 0xa4, 0xaa, 0x1a, 0x7f, 0x4f, 0xa9, 0x1a, 0xbf, 0x65, 0x14, - 0xbf, 0x53, 0xf9, 0x0c, 0x99, 0x93, 0x4d, 0x4c, 0xd2, 0xe9, 0x7b, 0xc3, 0x89, 0x5d, 0xf6, 0xab, 0xb7, 0x89, 0xcc, - 0x44, 0x0a, 0xb9, 0x37, 0x00, 0x6d, 0xbf, 0xcb, 0x0d, 0xa7, 0xc4, 0xf9, 0xb9, 0x87, 0x2b, 0x36, 0xad, 0x5e, 0xd1, - 0x82, 0x05, 0x36, 0x2f, 0xb3, 0x3c, 0x45, 0x02, 0xdb, 0xa6, 0xcc, 0xfa, 0x73, 0xee, 0x01, 0x04, 0x33, 0xa9, 0x09, - 0x00, 0x69, 0x21, 0x2a, 0x85, 0xc8, 0x5f, 0xe1, 0xac, 0x3e, 0xe7, 0xbd, 0x4d, 0x1e, 0x13, 0x69, 0x75, 0xaf, 0xdf, - 0x4f, 0xcf, 0xd2, 0x9c, 0x82, 0x1a, 0x8e, 0xb3, 0x4e, 0xbf, 0xcf, 0x82, 0x3a, 0x91, 0xab, 0xf4, 0x1f, 0x6e, 0x90, - 0x97, 0xf1, 0x7d, 0xdd, 0xf6, 0xfc, 0x89, 0xfa, 0x7b, 0x67, 0xfd, 0x6d, 0x81, 0xe0, 0x4e, 0x8e, 0xfd, 0x64, 0x55, - 0xca, 0x13, 0xe3, 0xd2, 0xde, 0xf3, 0x9b, 0xba, 0x28, 0xb2, 0x3a, 0x5d, 0x7f, 0x90, 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, 0xe8, 0x40, 0xbd, 0xb4, 0xd2, 0x3e, 0x82, 0x6e, - 0x05, 0x7a, 0x50, 0x0f, 0x7d, 0x9a, 0xb4, 0x2f, 0x24, 0xea, 0xf6, 0x56, 0xa7, 0xd1, 0x1f, 0x15, 0x5c, 0x4e, 0x61, - 0x72, 0xb8, 0xa1, 0x4f, 0xab, 0x70, 0xfb, 0x09, 0x9e, 0xfe, 0x0c, 0x94, 0x5b, 0x87, 0x43, 0x0e, 0x62, 0x0b, 0xb8, - 0x79, 0xac, 0xc2, 0xcf, 0x45, 0x29, 0x23, 0xea, 0xe3, 0x69, 0x01, 0xda, 0xbb, 0x00, 0x1d, 0xb0, 0x34, 0x88, 0x57, - 0x48, 0x9e, 0xb3, 0x11, 0xc0, 0xb2, 0x03, 0xcb, 0x59, 0xc6, 0x29, 0xcc, 0xb3, 0x7c, 0xa1, 0x56, 0xda, 0x59, 0x99, - 0x78, 0x35, 0xcb, 0xc0, 0x59, 0xe0, 0xa2, 0xf2, 0x59, 0xa6, 0x55, 0x4f, 0x55, 0x82, 0x3e, 0xaf, 0xe4, 0x04, 0x57, - 0x82, 0x93, 0x0d, 0xc8, 0x2f, 0x40, 0x92, 0xa6, 0x94, 0x35, 0xe5, 0x8b, 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, 0x3f, - 0x78, 0x4b, 0x7f, 0x3a, 0x0e, 0xc2, 0x21, 0x72, 0x43, 0xc5, 0x1c, 0xd8, 0xd3, 0x80, 0xc5, 0x26, 0xbe, 0xda, 0x4c, - 0xe2, 0xc1, 0xc0, 0xd7, 0x19, 0x8b, 0x59, 0x0c, 0x34, 0xc8, 0xf1, 0xe0, 0x72, 0xae, 0x4f, 0x08, 0xfd, 0x30, 0xa2, - 0x72, 0x54, 0xa0, 0x73, 0x10, 0x0d, 0x96, 0x80, 0xa7, 0xde, 0xca, 0x06, 0x49, 0xc6, 0x24, 0x93, 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, 0x3f, 0xcb, 0x07, 0x8e, 0x3b, 0x2a, 0x69, - 0x08, 0x0c, 0xde, 0x1e, 0xba, 0x9b, 0x19, 0x1a, 0xea, 0xa4, 0x7d, 0x18, 0x87, 0x72, 0x88, 0x55, 0x2b, 0x2e, 0xa4, - 0x37, 0x82, 0x6f, 0x17, 0x8a, 0xb1, 0x6c, 0xec, 0xd2, 0x50, 0x14, 0xfe, 0x0a, 0x60, 0x87, 0xda, 0x5f, 0xa9, 0xe4, - 0x63, 0x64, 0x54, 0xd3, 0x40, 0xc7, 0x00, 0x2c, 0x59, 0x9a, 0x48, 0xaa, 0x48, 0x23, 0xf1, 0x47, 0x66, 0xac, 0xa3, - 0xa6, 0xeb, 0x0b, 0xa6, 0xaa, 0x45, 0xd2, 0xed, 0x4c, 0x62, 0x39, 0x91, 0xa4, 0xb6, 0xfb, 0x88, 0x18, 0x0c, 0x7c, - 0xb0, 0x11, 0xd3, 0x4c, 0x84, 0x23, 0x1e, 0x95, 0xc8, 0xa2, 0xcb, 0x6f, 0xa3, 0x4c, 0xda, 0xbe, 0xac, 0xc8, 0x16, - 0x04, 0xd3, 0x93, 0xe8, 0x83, 0x24, 0xe5, 0x54, 0x24, 0xd2, 0x8c, 0x10, 0xe0, 0xc7, 0x93, 0xf2, 0x4a, 0x7f, 0x0e, - 0x9a, 0x56, 0x82, 0x97, 0x0c, 0x92, 0x47, 0xe2, 0x67, 0x52, 0x30, 0x8b, 0xb1, 0x6a, 0x30, 0xc0, 0x72, 0xaa, 0x67, - 0x8e, 0x49, 0xfa, 0x6f, 0x9d, 0x4e, 0xd8, 0x2f, 0xbd, 0xdc, 0xd6, 0xf2, 0xa6, 0xb9, 0xf7, 0xd2, 0xab, 0x58, 0xaa, - 0x61, 0x19, 0xf4, 0x5f, 0x13, 0xed, 0x82, 0xad, 0x2d, 0x63, 0xc2, 0xaa, 0x1f, 0x40, 0xda, 0x23, 0x5d, 0x5e, 0x35, - 0xcc, 0x99, 0xe0, 0xd1, 0x85, 0x35, 0x0f, 0xa2, 0x0b, 0xe1, 0x23, 0x97, 0xdd, 0x24, 0xb9, 0x1a, 0x4f, 0xfc, 0x70, - 0x30, 0x50, 0x00, 0xb4, 0xb4, 0x4e, 0x8a, 0x41, 0xf8, 0x4c, 0xc8, 0x81, 0x34, 0x3a, 0xaa, 0x02, 0x2c, 0x96, 0xd9, - 0x55, 0x39, 0xc9, 0x06, 0x03, 0x1f, 0xc4, 0xc6, 0xc4, 0x6e, 0x68, 0x36, 0xf7, 0xd9, 0x89, 0x82, 0xac, 0x36, 0x87, - 0xad, 0x99, 0x6e, 0x81, 0x01, 0xc0, 0x20, 0x22, 0x58, 0xee, 0x73, 0x23, 0x1f, 0x51, 0xa7, 0xa7, 0x30, 0x02, 0x82, - 0x5f, 0x4e, 0x04, 0x22, 0x17, 0x09, 0xd4, 0x03, 0xcc, 0x04, 0x98, 0x51, 0xc5, 0xf0, 0x12, 0xd8, 0xc5, 0x73, 0xf3, - 0x8a, 0x41, 0xff, 0xa2, 0x49, 0x96, 0x68, 0x2a, 0x71, 0x34, 0x46, 0x4e, 0xa5, 0x31, 0x32, 0x20, 0x76, 0x71, 0xfc, - 0x7b, 0x4a, 0x8f, 0x82, 0x94, 0x7d, 0xae, 0x0c, 0x71, 0x38, 0x8a, 0xaf, 0x60, 0xd5, 0x38, 0x1c, 0x6a, 0xf3, 0x7a, - 0x3a, 0xab, 0xe7, 0x03, 0x11, 0xc0, 0x7f, 0x43, 0xc1, 0x7e, 0xd1, 0x54, 0xe4, 0x06, 0xa9, 0xf3, 0x70, 0x48, 0x41, - 0x3e, 0xd5, 0x4d, 0xfe, 0xbe, 0x72, 0xf7, 0xd3, 0xd9, 0xdc, 0x9a, 0xa3, 0x17, 0x35, 0xae, 0x5b, 0xab, 0x1b, 0x0a, - 0x89, 0xd6, 0x34, 0x29, 0xae, 0xaa, 0x49, 0x31, 0xe0, 0xb9, 0x2f, 0x54, 0x17, 0x5b, 0x23, 0x58, 0xf8, 0x73, 0x0b, - 0x84, 0xc9, 0xb8, 0x17, 0x1f, 0x2d, 0xe4, 0x94, 0x76, 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, 0xf3, 0x20, 0xe3, 0x5e, 0x34, 0xec, 0xf8, 0x02, 0xec, 0xd5, 0x17, 0xcf, - 0x59, 0x34, 0xe0, 0xd5, 0x55, 0x3d, 0xcd, 0x82, 0x61, 0xc6, 0xa2, 0xab, 0x62, 0x08, 0x3e, 0xb4, 0x2f, 0xca, 0x41, - 0xe8, 0xfb, 0x66, 0xe7, 0xd0, 0xdd, 0x90, 0xc8, 0x23, 0xec, 0x47, 0x70, 0xdb, 0xd5, 0x12, 0x33, 0x98, 0x6c, 0xee, - 0x22, 0x66, 0xb0, 0xe5, 0x2f, 0x9e, 0x1b, 0x2e, 0xa1, 0xea, 0x85, 0xd4, 0x6c, 0x14, 0x68, 0x4e, 0xae, 0xd0, 0x9c, - 0xac, 0x84, 0x5a, 0xf2, 0x49, 0x85, 0x13, 0x76, 0x3e, 0xc9, 0x95, 0xdd, 0x68, 0x8c, 0x81, 0x8b, 0xf6, 0xdc, 0x16, - 0x46, 0x66, 0x3a, 0x4b, 0xd1, 0x80, 0x85, 0x67, 0xe2, 0x94, 0xc6, 0x80, 0xf6, 0xe5, 0xc0, 0xd2, 0x86, 0xfc, 0x28, - 0x67, 0x06, 0xda, 0x86, 0x94, 0x46, 0xcd, 0xc0, 0x9f, 0xa9, 0x09, 0xf3, 0x2b, 0x58, 0x89, 0x20, 0xaa, 0x0b, 0x30, - 0x49, 0x72, 0x32, 0x1a, 0x29, 0x2b, 0x91, 0x9c, 0x03, 0xde, 0x47, 0xf0, 0x64, 0x11, 0xdb, 0xda, 0x9f, 0xd2, 0xff, - 0xea, 0xf0, 0xb9, 0xf4, 0x9f, 0x09, 0x60, 0x21, 0x97, 0x06, 0x91, 0x81, 0xc2, 0x21, 0x35, 0x95, 0x88, 0x13, 0xc7, - 0x33, 0xf0, 0x0d, 0x5c, 0xa0, 0x29, 0xa0, 0x3f, 0xa8, 0x19, 0x45, 0x64, 0xe1, 0xaf, 0x9e, 0xdd, 0xd4, 0x8d, 0x9e, - 0x67, 0xce, 0x6b, 0xd0, 0xcc, 0x40, 0x48, 0x8f, 0x53, 0xf5, 0x36, 0x24, 0x3a, 0x2f, 0x2f, 0xf5, 0xcb, 0x84, 0x48, - 0x56, 0x44, 0x9e, 0xbe, 0xcf, 0xc1, 0x3c, 0xa2, 0x08, 0x1d, 0x5c, 0x99, 0x87, 0xc3, 0xb9, 0xa0, 0xf0, 0x1d, 0xe5, - 0xf9, 0x80, 0xd3, 0x2c, 0x4a, 0x40, 0x1b, 0xc8, 0x72, 0x53, 0xe6, 0x3a, 0x69, 0x99, 0xba, 0xf7, 0x60, 0x25, 0xa8, - 0xd0, 0xcd, 0x29, 0x28, 0x94, 0x91, 0xa0, 0x94, 0x56, 0x83, 0x50, 0xaa, 0xc3, 0x22, 0x88, 0x1c, 0xb2, 0x10, 0x70, - 0x33, 0x15, 0x8d, 0x96, 0x34, 0x3c, 0xc2, 0xb9, 0x81, 0x42, 0x00, 0x12, 0x7b, 0xaa, 0x28, 0xe3, 0x72, 0x08, 0xf8, - 0x28, 0xe1, 0x10, 0x67, 0x4d, 0xda, 0xf2, 0x1c, 0xc4, 0xb1, 0x5c, 0xf2, 0x75, 0x85, 0x60, 0x10, 0xa1, 0xcf, 0x90, - 0x3f, 0x59, 0xce, 0xbf, 0x5b, 0x87, 0x69, 0x47, 0xf8, 0xb0, 0xab, 0x2d, 0xb8, 0x98, 0xdd, 0xce, 0x27, 0x10, 0xdf, - 0x72, 0x3b, 0x3f, 0xc6, 0x10, 0x59, 0xf8, 0x83, 0xbb, 0xa1, 0xe4, 0x8a, 0x42, 0x97, 0xf5, 0x88, 0x14, 0xd9, 0xd3, - 0x35, 0x47, 0x10, 0x1c, 0x68, 0xd5, 0x20, 0x43, 0x23, 0xf1, 0xc5, 0x73, 0xc8, 0x1a, 0xac, 0xf9, 0xe7, 0x8a, 0x9c, - 0xd5, 0xfd, 0xc9, 0x06, 0xaa, 0x49, 0x26, 0x6b, 0x45, 0xe5, 0xfc, 0xf5, 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, 0xff, 0x15, 0xfc, 0x4b, 0x85, 0x2c, 0xd5, 0x69, 0x9d, 0x89, - 0x5f, 0x83, 0x25, 0xc3, 0x3f, 0x7e, 0x0b, 0xd6, 0x80, 0x25, 0x40, 0x96, 0xbb, 0x8d, 0x8d, 0xd6, 0x2b, 0xaf, 0x10, - 0x5f, 0x6a, 0x7d, 0xd1, 0x6f, 0xdd, 0x26, 0x6a, 0x05, 0x18, 0xa1, 0xd0, 0x22, 0xc0, 0x56, 0x0f, 0xdc, 0x53, 0xf0, - 0x03, 0x31, 0x9c, 0x6b, 0xd2, 0x9a, 0x3a, 0xe1, 0x75, 0x36, 0x8e, 0x44, 0x54, 0x6f, 0xe1, 0xe2, 0x5e, 0x6f, 0x2d, - 0xfe, 0x46, 0x05, 0x02, 0x20, 0x8b, 0x29, 0xd6, 0xce, 0x1b, 0xd2, 0x2b, 0xc3, 0x4e, 0x42, 0xef, 0x0d, 0x3b, 0x81, - 0xbc, 0x38, 0xec, 0x14, 0xba, 0x44, 0xdb, 0x29, 0x52, 0x13, 0x6d, 0x27, 0x2d, 0x56, 0x61, 0x09, 0xc1, 0xaf, 0xda, - 0x5b, 0x47, 0xd9, 0xbe, 0xc8, 0x12, 0xa6, 0x2d, 0x60, 0x94, 0x5b, 0xf5, 0x99, 0x53, 0xc4, 0x4a, 0xd9, 0x3b, 0x9d, - 0x54, 0xb9, 0x8b, 0x7c, 0x6a, 0x35, 0x45, 0x26, 0x7f, 0x7f, 0xdc, 0x22, 0xf9, 0xe4, 0xe7, 0x76, 0xc3, 0x64, 0xfa, - 0xc7, 0xa3, 0x2f, 0xa0, 0x2b, 0xb2, 0xd3, 0x27, 0x10, 0x90, 0xa9, 0xa0, 0x5a, 0xdd, 0x2a, 0xa6, 0x79, 0xbb, 0xca, - 0x6e, 0x2f, 0x94, 0x18, 0x4e, 0x67, 0x27, 0xe1, 0xd1, 0x66, 0xc8, 0xc0, 0x21, 0x08, 0x14, 0x42, 0x45, 0x31, 0x3c, - 0x02, 0xb5, 0x46, 0xf2, 0x01, 0x7e, 0xb4, 0x3b, 0x15, 0x44, 0x6a, 0x37, 0x15, 0x37, 0x4e, 0x6e, 0xba, 0x5e, 0x0a, - 0xd4, 0x3a, 0x25, 0x2b, 0x80, 0x12, 0xa2, 0xfe, 0x24, 0xb6, 0xf5, 0x2b, 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, 0x75, 0xbb, 0xe9, 0x98, 0xd8, 0xea, 0x9f, 0x45, 0xb5, 0xb9, 0x83, 0x8a, 0x88, 0xf8, 0x28, 0xbb, 0x79, 0xd2, - 0x7e, 0x07, 0x7b, 0xac, 0xd5, 0x20, 0xb2, 0xcf, 0xe0, 0x2a, 0xd7, 0x69, 0x91, 0xdb, 0x32, 0x38, 0xff, 0xf0, 0x6a, - 0x57, 0x61, 0x93, 0x63, 0x5d, 0x5d, 0xcd, 0x54, 0x27, 0x15, 0x1b, 0x18, 0x6b, 0x5a, 0x4b, 0x35, 0x8f, 0x21, 0xe9, - 0xae, 0x2c, 0xce, 0xaa, 0xa4, 0x9b, 0x9e, 0x1b, 0x67, 0x0a, 0x31, 0x70, 0xb6, 0x1a, 0x2d, 0x67, 0x18, 0xa2, 0xeb, - 0xc3, 0x2c, 0xf1, 0x5b, 0x3d, 0xe5, 0x3e, 0x0f, 0xb7, 0x7e, 0x57, 0x2f, 0x38, 0x99, 0xec, 0x27, 0xc7, 0xb9, 0xdb, - 0x45, 0xda, 0x4f, 0x7c, 0x1b, 0xe6, 0x5f, 0xdf, 0x20, 0xee, 0x44, 0xfd, 0xcf, 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, 0x7f, 0x7a, 0x35, 0x3b, 0x15, 0x54, 0x06, 0x6e, 0xc6, 0x7f, 0x7a, 0x82, 0x9d, 0xc2, 0x5a, - 0x01, 0x59, 0xe1, 0x4f, 0x2f, 0x7f, 0xe4, 0xfd, 0x8a, 0xff, 0xe9, 0x55, 0x8f, 0xbc, 0x8f, 0x38, 0x2f, 0x7f, 0x22, - 0xa9, 0x13, 0xa2, 0xba, 0xfc, 0x49, 0x98, 0x62, 0xab, 0x34, 0x7f, 0x4d, 0x0a, 0x9f, 0xe0, 0x33, 0xf0, 0x1d, 0xae, - 0xc2, 0xad, 0xf9, 0x0d, 0x1e, 0x3b, 0x16, 0xdb, 0x2e, 0xf5, 0x05, 0x94, 0x23, 0xb0, 0x88, 0xdc, 0x7e, 0xbb, 0xb2, - 0x5f, 0x2d, 0x8c, 0x32, 0xc6, 0xee, 0x4b, 0x56, 0xa2, 0x74, 0xd6, 0xef, 0x17, 0x52, 0x30, 0xb2, 0x0b, 0x6b, 0xb4, - 0x47, 0xa9, 0x7a, 0xf5, 0x3a, 0xac, 0xa3, 0x24, 0xcd, 0xef, 0x64, 0xf4, 0x91, 0x0c, 0x3b, 0xd2, 0x57, 0x52, 0xa2, - 0xbd, 0x56, 0x61, 0x39, 0x9a, 0xfd, 0xba, 0xe4, 0x40, 0x79, 0xdd, 0x0a, 0xca, 0x57, 0x4d, 0x00, 0xbd, 0x52, 0xed, - 0x33, 0xd0, 0x0a, 0x0a, 0x4b, 0xe5, 0xc1, 0x4a, 0x9c, 0x8b, 0x3e, 0x2b, 0x0e, 0x07, 0x75, 0x31, 0x24, 0x14, 0xa8, - 0x12, 0x27, 0xa1, 0x11, 0xcf, 0xe1, 0x42, 0x28, 0x5e, 0xe4, 0x18, 0x5b, 0x91, 0x03, 0x07, 0x32, 0xfc, 0x80, 0xc0, - 0x7b, 0xd9, 0xbf, 0x82, 0xc1, 0x30, 0xc1, 0x8d, 0x8c, 0x3a, 0x39, 0x67, 0x7f, 0x62, 0x60, 0x06, 0xf5, 0xa4, 0x76, - 0x9f, 0xdd, 0xab, 0xc0, 0x5e, 0x38, 0x03, 0xda, 0xbb, 0x31, 0xfa, 0x59, 0x15, 0x6b, 0x27, 0xfd, 0x53, 0xb1, 0x86, - 0x64, 0x3a, 0x2c, 0x8e, 0xb6, 0x69, 0x78, 0x24, 0x4f, 0x8e, 0xe3, 0x4d, 0xff, 0x70, 0x18, 0xe3, 0xc7, 0x51, 0x7e, - 0x6d, 0x01, 0xaf, 0xe2, 0x16, 0xd2, 0x58, 0xa4, 0xe8, 0x1d, 0x88, 0x39, 0x14, 0xbd, 0x64, 0xbf, 0x65, 0xbc, 0x9c, - 0x08, 0x4a, 0x49, 0x62, 0xc3, 0x3b, 0xd2, 0xd3, 0xb4, 0x1e, 0x6d, 0x65, 0xc0, 0x7e, 0x3d, 0xda, 0xd1, 0x5f, 0xa0, - 0x78, 0xb4, 0xf0, 0x97, 0xf4, 0x77, 0x71, 0x37, 0xf7, 0x9c, 0x6f, 0x1a, 0xdf, 0x11, 0x17, 0x28, 0xd6, 0xec, 0xfe, - 0x9a, 0x96, 0xce, 0x3a, 0x10, 0x1c, 0xf0, 0x16, 0xbb, 0x68, 0xdf, 0x6f, 0x5c, 0xa7, 0xa7, 0xfd, 0xb7, 0x6e, 0x8d, - 0xf2, 0xbd, 0x7f, 0x4a, 0x94, 0x83, 0xfd, 0x6b, 0x17, 0xcd, 0xdf, 0x7e, 0xca, 0x90, 0x54, 0x68, 0x6e, 0xb0, 0x9d, - 0x6c, 0x11, 0xd6, 0xc6, 0x38, 0xa8, 0xd8, 0x5d, 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, 0x5f, 0x11, 0x3e, 0xd4, 0x4e, 0x4a, 0x87, 0xf2, 0x57, 0xcf, 0xd9, - 0xff, 0xec, 0xb0, 0xa6, 0xa6, 0xdc, 0x00, 0x66, 0xce, 0x4a, 0xe4, 0x15, 0x42, 0xa7, 0xc8, 0xef, 0x55, 0x5d, 0x89, - 0xe1, 0xb2, 0x16, 0x65, 0x67, 0x76, 0xeb, 0x44, 0xef, 0x9c, 0x82, 0x5a, 0x2a, 0x1b, 0xe4, 0x24, 0xd5, 0xe6, 0x23, - 0x6b, 0x05, 0x25, 0xea, 0x1a, 0x05, 0x8e, 0x4f, 0xb9, 0x76, 0xff, 0xef, 0x9c, 0x09, 0x6a, 0xb6, 0x51, 0xdd, 0x5f, - 0xeb, 0xa7, 0xaa, 0x26, 0xb1, 0x00, 0x97, 0x93, 0x34, 0xef, 0x78, 0x84, 0xd5, 0x3f, 0x4e, 0x96, 0x22, 0xd0, 0xeb, - 0x88, 0x76, 0x25, 0x20, 0x41, 0x3b, 0x39, 0x0b, 0x15, 0x81, 0x02, 0x7d, 0xfd, 0xfb, 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, 0x0a, 0xb9, 0x41, 0x44, 0xd3, 0xef, 0x25, 0xaa, 0x1d, - 0x29, 0x90, 0x43, 0xc9, 0x4f, 0x88, 0xbf, 0x64, 0x6d, 0x8c, 0xfb, 0xa5, 0x53, 0xed, 0x57, 0x0a, 0xc1, 0xfd, 0x67, - 0x5b, 0x6c, 0x54, 0x79, 0xa2, 0x47, 0x9f, 0x62, 0xfd, 0x4f, 0x16, 0x50, 0xaa, 0xfb, 0x36, 0x38, 0x15, 0x8f, 0xc2, - 0x4d, 0x5d, 0xdc, 0x20, 0xb4, 0x40, 0x39, 0xaa, 0x8a, 0x4d, 0x19, 0x11, 0x27, 0xec, 0xa6, 0x2e, 0x7a, 0x9a, 0x03, - 0x9d, 0x3a, 0x2c, 0x4d, 0xe4, 0x89, 0xd0, 0x6e, 0x41, 0xf7, 0x34, 0xc7, 0x4a, 0xbc, 0x94, 0xa5, 0x83, 0xac, 0x13, - 0x69, 0x42, 0xe5, 0xae, 0xae, 0x3a, 0x2a, 0x95, 0xba, 0xe1, 0x4d, 0xaa, 0x19, 0x7f, 0x97, 0xe6, 0x4f, 0x2c, 0xfb, - 0x4d, 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, 0xb1, 0x28, 0xfe, 0xa8, 0xf4, 0x1d, 0x81, 0x8e, 0xee, 0xbc, 0xa8, 0xd3, 0xe5, 0xee, 0x03, 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, 0xbc, 0xc2, 0xfd, 0xa5, 0x22, 0x17, 0xfb, 0xce, 0x19, - 0xdd, 0x99, 0x59, 0xf7, 0xaa, 0xc2, 0xd5, 0x82, 0x5c, 0x1d, 0xd8, 0x5a, 0x76, 0x71, 0xb8, 0x61, 0x11, 0x05, 0x08, - 0xc4, 0xf4, 0x4a, 0xad, 0xfd, 0x11, 0x0d, 0x42, 0x3e, 0x18, 0xf8, 0x05, 0x06, 0xab, 0x02, 0x85, 0x0f, 0x14, 0xc9, - 0x5f, 0x7b, 0x02, 0x76, 0xf1, 0x0c, 0xd0, 0xad, 0xd8, 0xac, 0x18, 0x21, 0x42, 0x26, 0xcb, 0x59, 0x4d, 0x67, 0x90, - 0x4f, 0x7d, 0xf1, 0x8d, 0xad, 0x3a, 0x9d, 0xb7, 0x35, 0x55, 0x4e, 0x1d, 0x0a, 0xdd, 0xdd, 0xd4, 0x9d, 0x5b, 0x17, - 0x79, 0xea, 0x10, 0x72, 0xa5, 0x62, 0x25, 0xa6, 0xa1, 0xe6, 0x49, 0x9a, 0x51, 0x7f, 0xb1, 0xf7, 0x7b, 0x8d, 0xc2, - 0x29, 0x7f, 0x3a, 0x06, 0x55, 0xb8, 0xaa, 0x21, 0x8e, 0xa5, 0x2a, 0x1e, 0xd9, 0x20, 0xd0, 0xbc, 0xba, 0x55, 0x49, - 0x13, 0x32, 0xb9, 0x11, 0x3e, 0x35, 0x29, 0xe5, 0x69, 0xda, 0xa4, 0x95, 0x22, 0x75, 0xf0, 0x41, 0x9d, 0x6a, 0x3c, - 0x37, 0xab, 0x17, 0x00, 0x66, 0x9c, 0x5f, 0xf1, 0x4b, 0xc5, 0x65, 0xd4, 0x56, 0x66, 0xd2, 0xfe, 0xe4, 0x68, 0x6c, - 0xd4, 0xe5, 0xb4, 0x51, 0x46, 0x58, 0x29, 0xcd, 0x49, 0xb1, 0x1c, 0xcf, 0x3f, 0x60, 0xb0, 0xe6, 0x09, 0xec, 0x60, - 0xa2, 0x52, 0xde, 0x47, 0x40, 0x7c, 0x9d, 0xa4, 0x77, 0x09, 0xa4, 0x48, 0xff, 0xd2, 0x25, 0x77, 0x19, 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, 0xbe, 0x08, 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, 0xac, 0x3c, 0xe8, 0xff, 0x3a, 0x13, 0x96, 0xda, 0x4f, 0x4f, 0x07, 0x50, 0xc1, 0xfb, 0x8a, 0xb7, 0x11, 0xf1, - 0x7d, 0xe2, 0x67, 0xf1, 0x60, 0xf3, 0x6c, 0x03, 0xd6, 0xba, 0x27, 0xb9, 0xb1, 0xae, 0x12, 0x36, 0x10, 0xf0, 0x35, - 0x8a, 0xda, 0xf3, 0xda, 0xed, 0x1e, 0xfc, 0xd5, 0xbf, 0x08, 0x19, 0x30, 0x71, 0xfa, 0x3e, 0x73, 0xb2, 0x46, 0x17, - 0x99, 0x4c, 0x1f, 0x3a, 0xe9, 0x1b, 0x9d, 0xee, 0x3b, 0xe1, 0x1f, 0x15, 0xb3, 0xf8, 0x70, 0x4b, 0x5f, 0x69, 0x52, - 0xdc, 0x01, 0x2b, 0x9b, 0x47, 0x05, 0xa1, 0xce, 0x45, 0xf4, 0x95, 0x29, 0xdf, 0x12, 0x6a, 0xf6, 0x8d, 0x25, 0xa5, - 0x74, 0xaf, 0xa1, 0x37, 0x69, 0xad, 0xdf, 0x46, 0x09, 0xc6, 0x44, 0xc7, 0x93, 0x97, 0xf1, 0x58, 0x79, 0x1f, 0x8f, - 0x1b, 0xa9, 0x90, 0x07, 0x20, 0x02, 0x15, 0xe3, 0x4f, 0x57, 0x9e, 0x9c, 0xf4, 0xc2, 0x78, 0x15, 0x4a, 0x41, 0x61, - 0x40, 0x57, 0x20, 0x05, 0x3c, 0x6a, 0x4f, 0x74, 0x16, 0x76, 0x09, 0xf7, 0xe8, 0x26, 0x60, 0xac, 0xcf, 0x3f, 0x02, - 0x9a, 0xbb, 0x70, 0x87, 0x17, 0x03, 0xd4, 0xa6, 0x5e, 0xdd, 0x7d, 0x5c, 0xab, 0x73, 0x38, 0x04, 0x07, 0xab, 0x41, - 0x04, 0xa7, 0xf3, 0xa9, 0xa3, 0x59, 0x16, 0xa0, 0x72, 0xb2, 0xdc, 0xc8, 0x9b, 0x47, 0x8b, 0x5e, 0xdd, 0xf7, 0x96, - 0x69, 0x59, 0xd5, 0x41, 0xc6, 0xb2, 0xb0, 0x02, 0x5c, 0x1d, 0x5a, 0x3f, 0x08, 0x97, 0x85, 0xf3, 0x07, 0x42, 0x10, - 0xbb, 0x57, 0xdb, 0x92, 0xe7, 0x6a, 0x0e, 0x3f, 0x7b, 0xce, 0xd6, 0x5c, 0xa2, 0x4e, 0x3a, 0x13, 0x01, 0x88, 0x3d, - 0x35, 0xab, 0xe8, 0x1a, 0x48, 0xea, 0x34, 0xab, 0xe8, 0x9a, 0x9a, 0x6d, 0x8c, 0x03, 0xf9, 0x68, 0x95, 0x02, 0xf6, - 0xdd, 0x74, 0x1c, 0xac, 0x9e, 0xc5, 0xf2, 0x3a, 0x74, 0xf7, 0x6c, 0xa3, 0x7c, 0x06, 0x75, 0xab, 0x8d, 0x31, 0xb1, - 0xdd, 0x7c, 0x39, 0xd7, 0x6f, 0x07, 0x4b, 0xdf, 0x0e, 0x9a, 0x73, 0xca, 0xbe, 0xd3, 0x65, 0xaf, 0xec, 0xb2, 0xa9, - 0xe7, 0x8e, 0x8a, 0x56, 0x63, 0x40, 0x6f, 0x60, 0xc1, 0xfa, 0x5c, 0xa4, 0xd9, 0xaa, 0x54, 0x25, 0xe0, 0x85, 0xb1, - 0x62, 0x77, 0x7e, 0x23, 0x33, 0x24, 0x61, 0x1e, 0x67, 0xe2, 0x9a, 0xee, 0xb5, 0x30, 0x39, 0x8e, 0x45, 0x32, 0x25, - 0x74, 0x4a, 0x77, 0xb6, 0xa1, 0x73, 0x15, 0x46, 0x11, 0xad, 0x95, 0x54, 0x1a, 0x09, 0x4c, 0xcd, 0x00, 0x25, 0x73, - 0x05, 0x4e, 0xe9, 0x72, 0xff, 0x3b, 0x12, 0xe3, 0xcc, 0x17, 0x25, 0x33, 0xa0, 0x5b, 0x7e, 0x5d, 0xac, 0x5b, 0x29, - 0x32, 0xc2, 0xbc, 0x39, 0x6e, 0xaf, 0xeb, 0x43, 0x20, 0x57, 0xcb, 0x1e, 0x45, 0xe3, 0xa0, 0xd0, 0xe1, 0x52, 0x25, - 0xc0, 0xbe, 0x48, 0xfc, 0x8c, 0xb0, 0xa5, 0x3d, 0x90, 0xdb, 0xa3, 0x33, 0x61, 0xce, 0x39, 0x29, 0xcb, 0xce, 0xa5, - 0x19, 0x5c, 0x4e, 0x5c, 0x09, 0x2e, 0xd2, 0xdb, 0xf6, 0x34, 0x69, 0x69, 0xfb, 0xd8, 0x70, 0x8e, 0x86, 0xb6, 0x41, - 0x77, 0xec, 0x0f, 0xcd, 0xc5, 0x22, 0xb6, 0x2e, 0x16, 0xc3, 0xce, 0xec, 0x47, 0x8b, 0x05, 0xc8, 0x01, 0xe0, 0xa8, - 0xdb, 0xf0, 0x31, 0x5b, 0x02, 0xa7, 0xd5, 0x34, 0x9b, 0x7a, 0x1b, 0x5e, 0x3d, 0x53, 0x3d, 0xbd, 0xe4, 0xf9, 0x33, - 0x61, 0xc6, 0x62, 0xc3, 0xf3, 0x67, 0xd6, 0x91, 0x53, 0x3d, 0x13, 0x4a, 0xb4, 0x2e, 0xa0, 0x19, 0x78, 0x4d, 0x01, - 0x23, 0x96, 0x4c, 0xa6, 0x54, 0x91, 0xc7, 0xbd, 0xe9, 0x46, 0x0d, 0x5e, 0x50, 0x38, 0x04, 0x52, 0x3a, 0xfd, 0xe2, - 0x39, 0xd3, 0xef, 0x5d, 0x3c, 0xef, 0x90, 0xb5, 0x0d, 0xd3, 0xe5, 0x66, 0x98, 0x0c, 0x4a, 0xff, 0x99, 0x99, 0x18, - 0x17, 0xd6, 0x24, 0x01, 0xc4, 0xbf, 0xb1, 0xdf, 0x21, 0x85, 0x9b, 0xf7, 0x97, 0xc3, 0xf8, 0x91, 0xf7, 0x63, 0x64, - 0x4f, 0xd2, 0x0c, 0xb1, 0x66, 0x52, 0x21, 0x77, 0x5f, 0xad, 0x7f, 0x4c, 0xec, 0x26, 0x7b, 0x60, 0x01, 0x88, 0xad, - 0x69, 0xab, 0x5b, 0xde, 0xef, 0x7b, 0xa6, 0x08, 0xf0, 0x83, 0xf2, 0x8f, 0xee, 0x0c, 0xc9, 0xa0, 0xec, 0xba, 0x21, - 0xc4, 0x83, 0xb2, 0x69, 0xda, 0xeb, 0x6d, 0xef, 0xcc, 0x63, 0x75, 0x9d, 0x76, 0x16, 0x57, 0x8b, 0x0c, 0xd2, 0xea, - 0x43, 0x76, 0x9c, 0xd9, 0x67, 0x47, 0x4b, 0xa5, 0xfb, 0x7d, 0x88, 0x88, 0x3b, 0xca, 0xda, 0x7e, 0xbb, 0x05, 0xd7, - 0x70, 0x34, 0x08, 0x5d, 0xd9, 0xdb, 0x65, 0xb4, 0x71, 0x21, 0x8e, 0x7b, 0xa6, 0xf3, 0x05, 0x5f, 0x1e, 0xa5, 0x9d, - 0x07, 0xa7, 0x7a, 0xa2, 0xcf, 0x4d, 0x77, 0x95, 0xc9, 0xb5, 0x0e, 0xab, 0x31, 0xa8, 0xcd, 0xc2, 0x16, 0xee, 0xc2, - 0x36, 0x3a, 0x68, 0xed, 0xcb, 0x82, 0x7f, 0xca, 0x00, 0x7c, 0xe9, 0xd9, 0xb2, 0xed, 0x35, 0x69, 0xf5, 0x46, 0x46, - 0x21, 0xb6, 0xb4, 0xbd, 0xfa, 0x74, 0x94, 0x8f, 0x9b, 0x13, 0x8a, 0x0b, 0x39, 0xca, 0x8f, 0x5e, 0x43, 0xd4, 0xb5, - 0xae, 0xe3, 0x62, 0xd1, 0xe1, 0xc6, 0x55, 0xb7, 0xdd, 0xb8, 0x7e, 0x40, 0xbc, 0x35, 0xda, 0xa4, 0x50, 0x2b, 0x63, - 0x47, 0xf0, 0xb2, 0x7c, 0x38, 0x64, 0x62, 0x38, 0x94, 0x90, 0xa9, 0x8f, 0xdd, 0x1b, 0x9a, 0xf6, 0xf9, 0x69, 0xeb, - 0x47, 0x2c, 0x35, 0x8e, 0x62, 0xc3, 0x3b, 0x7d, 0xe7, 0xb1, 0x35, 0xae, 0xe4, 0xcb, 0x60, 0xb6, 0x2b, 0xa8, 0xb6, - 0xc6, 0x1b, 0xf6, 0x72, 0xfe, 0x7d, 0x25, 0x95, 0xfc, 0xed, 0xcf, 0x70, 0x0d, 0x6f, 0x6d, 0xe9, 0xa0, 0xa9, 0x66, - 0x39, 0xcb, 0xf5, 0xbd, 0xe0, 0xf8, 0xe3, 0xee, 0x15, 0xc1, 0xe0, 0xf7, 0x74, 0x14, 0xe4, 0x62, 0xa9, 0xd6, 0x80, - 0x82, 0x74, 0x64, 0xc7, 0x54, 0x16, 0x18, 0x06, 0xf0, 0x86, 0x0c, 0x90, 0xc7, 0x14, 0xee, 0x86, 0x0a, 0x2f, 0xfc, - 0xa5, 0x22, 0xbb, 0x04, 0xb6, 0x35, 0xe3, 0x63, 0x86, 0x3b, 0x08, 0xf9, 0x47, 0xb0, 0x3b, 0xb6, 0x62, 0xb7, 0x6c, - 0xc1, 0x90, 0x6c, 0x1c, 0x87, 0x31, 0xe6, 0xe3, 0x49, 0x7c, 0x25, 0x26, 0xf1, 0x80, 0x47, 0xe8, 0x18, 0xb1, 0xe6, - 0xf5, 0x2c, 0x96, 0x03, 0xc8, 0xee, 0xb8, 0xd2, 0x01, 0x21, 0x34, 0x36, 0xb4, 0xe4, 0x4d, 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, 0xdd, 0x45, 0x88, 0xf4, 0xb6, 0xe0, 0x77, 0x96, 0xa7, 0x0b, 0xbb, 0xe7, 0xd7, - 0x7c, 0xcc, 0xce, 0x7f, 0xf0, 0x20, 0x72, 0xf6, 0xfc, 0x23, 0xa0, 0x21, 0xde, 0xf3, 0xdb, 0xd4, 0xab, 0xd8, 0x2d, - 0x51, 0x10, 0xde, 0x82, 0x33, 0xd0, 0x3d, 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, 0xff, 0xc1, 0xdb, 0x51, 0xb9, 0xf0, 0x9f, 0xd7, 0x59, 0xf2, 0xce, 0x67, 0xd7, 0x03, 0xbe, 0x00, 0xbc, 0x25, - 0x74, 0xe0, 0xba, 0xf7, 0x99, 0xc4, 0x6b, 0xbb, 0xd6, 0xd7, 0x08, 0x24, 0xf2, 0x05, 0x60, 0xc4, 0xc4, 0xfc, 0xbe, - 0x86, 0x08, 0x8c, 0x04, 0x7c, 0x5b, 0xb5, 0x47, 0xfc, 0x96, 0x1b, 0xc0, 0xaf, 0xcc, 0x67, 0x0f, 0x3c, 0xd4, 0x3f, - 0x13, 0x9f, 0xdd, 0xf0, 0xf7, 0xfc, 0x85, 0x27, 0x25, 0xe9, 0x72, 0xf6, 0x7e, 0x0e, 0xd7, 0x43, 0x29, 0x4f, 0x87, - 0xf4, 0xb3, 0x31, 0x18, 0x40, 0x28, 0x64, 0xde, 0x78, 0xc0, 0x9a, 0x14, 0xe2, 0x5f, 0xc0, 0xb7, 0xa3, 0x84, 0xcd, - 0x1b, 0x6f, 0xeb, 0x6b, 0x79, 0xf3, 0xc6, 0x7b, 0xf0, 0x29, 0x0a, 0xb0, 0x0a, 0x4a, 0x59, 0x60, 0x15, 0x84, 0x8d, - 0x36, 0xc2, 0x18, 0xb8, 0x7a, 0xd7, 0x18, 0xea, 0x7a, 0x8e, 0xd8, 0xb6, 0xd2, 0x77, 0xe1, 0x3b, 0xc8, 0x80, 0x0f, - 0xde, 0x14, 0x25, 0xd1, 0xe7, 0xd4, 0x14, 0x49, 0xeb, 0x9e, 0xfb, 0xad, 0x75, 0x47, 0x6b, 0x4a, 0x7d, 0xe4, 0x6a, - 0x7c, 0x38, 0xd4, 0x2f, 0x84, 0x16, 0x09, 0xa6, 0xa0, 0x71, 0x0d, 0xda, 0x02, 0x04, 0x7d, 0x1e, 0x20, 0x6b, 0x49, - 0xb1, 0xe0, 0xdb, 0x5f, 0x21, 0x06, 0xaf, 0x4c, 0xef, 0x5c, 0xae, 0x32, 0x12, 0xb6, 0x17, 0x7e, 0x39, 0xac, 0xfd, - 0x89, 0x53, 0x0b, 0x4b, 0xab, 0x39, 0xa8, 0x9f, 0xd9, 0x72, 0x9c, 0xaa, 0xda, 0xbf, 0x25, 0x49, 0xb5, 0xab, 0xb4, - 0x9c, 0xde, 0xdb, 0x37, 0x5d, 0x26, 0xd8, 0xd8, 0x0f, 0xa8, 0x3a, 0xb2, 0x1a, 0x76, 0x5f, 0xa8, 0x2f, 0x7a, 0x4a, - 0x26, 0x34, 0x1f, 0x55, 0x34, 0xcf, 0xee, 0x37, 0x3b, 0xea, 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, 0x17, 0xe3, 0x69, 0x4d, 0x2c, 0xa9, 0x5d, 0x81, 0x31, 0x7a, 0x5c, 0x15, 0xb5, 0x4f, 0xfd, 0x02, 0x42, 0x91, - 0x6a, 0xcd, 0x1c, 0x6b, 0xdc, 0x18, 0x11, 0x77, 0x58, 0xb9, 0x76, 0x6a, 0xaf, 0x03, 0xb0, 0xbc, 0x1a, 0x17, 0x84, - 0x4d, 0x72, 0xec, 0x5c, 0xc0, 0x6a, 0x34, 0xa4, 0xda, 0x0d, 0xb7, 0x5e, 0x76, 0x7e, 0xf3, 0x38, 0xb1, 0xb5, 0x11, - 0x6e, 0x29, 0xa0, 0x8c, 0xf2, 0x1b, 0xcb, 0x09, 0xbb, 0x53, 0xbd, 0x23, 0x55, 0x3b, 0xe2, 0xc4, 0x05, 0x2c, 0x37, - 0x3c, 0xb5, 0xfa, 0x26, 0x06, 0x27, 0x42, 0xd5, 0x4a, 0xc7, 0x6b, 0x3f, 0xe2, 0x7e, 0x75, 0x5f, 0xf7, 0x4a, 0xf0, - 0x93, 0x90, 0xd7, 0x6f, 0x79, 0x07, 0x80, 0x15, 0x1f, 0xf2, 0x62, 0x5a, 0x38, 0x5a, 0x97, 0x41, 0x19, 0x20, 0x42, - 0x33, 0x00, 0x3a, 0xb9, 0x3a, 0x88, 0xd2, 0xc0, 0x15, 0x77, 0x88, 0xf0, 0xd3, 0xe8, 0x59, 0xfe, 0x22, 0x7c, 0x56, - 0x4d, 0xc3, 0x8b, 0x3c, 0x88, 0x2e, 0xaa, 0x20, 0x7a, 0x56, 0x5d, 0x85, 0xcf, 0xf2, 0x69, 0x74, 0x91, 0x07, 0xe1, - 0x45, 0xd5, 0xd8, 0x77, 0xed, 0xee, 0x9e, 0x90, 0xb7, 0x5d, 0xfd, 0x91, 0x73, 0x65, 0x4f, 0x99, 0x9e, 0x9f, 0xd7, - 0x7a, 0xa5, 0x76, 0x9b, 0xeb, 0x35, 0x6a, 0xa6, 0x3e, 0xca, 0xfe, 0x66, 0x1b, 0x0b, 0x8f, 0xe6, 0x10, 0xfa, 0x8c, - 0xb4, 0x98, 0x7b, 0x9c, 0xeb, 0xcd, 0x9e, 0x14, 0x06, 0x46, 0x4c, 0x2a, 0x19, 0x39, 0xbd, 0xc0, 0x45, 0xa8, 0x42, - 0x0c, 0x6b, 0xe9, 0x6a, 0x9f, 0x75, 0xe9, 0x0d, 0xd4, 0x35, 0xc5, 0xbe, 0x86, 0x0c, 0xbc, 0x68, 0x7a, 0x19, 0x8c, - 0x01, 0x39, 0x02, 0xef, 0xf8, 0x6c, 0x09, 0x07, 0xe6, 0x1a, 0xa0, 0x6f, 0x1e, 0xf5, 0x75, 0xb9, 0xe3, 0x6b, 0xd5, - 0x37, 0xd3, 0xf5, 0x48, 0x29, 0x3f, 0x56, 0xfc, 0xee, 0xe2, 0x39, 0xbb, 0xe5, 0x1a, 0x15, 0xe5, 0x17, 0xbd, 0x58, - 0xef, 0x81, 0xab, 0xee, 0x17, 0xb8, 0xcd, 0xe2, 0xb1, 0x2b, 0x0f, 0x58, 0xb6, 0x65, 0x0f, 0xec, 0x86, 0xbd, 0x67, - 0x4f, 0xd8, 0x5b, 0xf6, 0x8e, 0xfd, 0x84, 0xaa, 0x0d, 0x25, 0xe4, 0xf9, 0x0b, 0x7e, 0x2b, 0x4d, 0x8f, 0x12, 0x95, - 0xec, 0xc1, 0x36, 0xd3, 0x0c, 0x37, 0xec, 0x3d, 0x5f, 0x0c, 0x57, 0xec, 0x2d, 0x64, 0x43, 0x99, 0x78, 0xb0, 0x62, - 0x3f, 0x71, 0x05, 0x62, 0xa6, 0xcf, 0xc2, 0xd2, 0x12, 0x15, 0x4d, 0x99, 0x28, 0x43, 0xbf, 0xe5, 0xf8, 0x22, 0xfb, - 0x09, 0x8b, 0x90, 0x9f, 0x19, 0xae, 0xd8, 0x03, 0x5f, 0x0c, 0x56, 0xec, 0xbd, 0x36, 0x10, 0x0d, 0x36, 0x6e, 0x69, - 0x84, 0x64, 0xa5, 0xcb, 0x92, 0xd2, 0xf4, 0xd6, 0xbe, 0x06, 0x6e, 0xd8, 0x0d, 0xd6, 0xee, 0x09, 0x16, 0x8d, 0x02, - 0xff, 0x60, 0xc5, 0xde, 0x71, 0x09, 0xa0, 0xe6, 0x96, 0x27, 0xbd, 0x42, 0x75, 0x81, 0x74, 0x3f, 0x78, 0xc2, 0xe9, - 0x45, 0xf6, 0x0e, 0xcb, 0xa0, 0xaf, 0x0c, 0x57, 0x6c, 0x8b, 0xb5, 0xbb, 0x31, 0x96, 0x2d, 0xab, 0x7a, 0x12, 0x11, - 0x18, 0x05, 0x95, 0xd2, 0xf2, 0x6f, 0xc4, 0xb2, 0xa9, 0x9b, 0x06, 0xb5, 0xa1, 0x3f, 0x1f, 0x8c, 0xfe, 0xe2, 0xeb, - 0x77, 0x3f, 0x78, 0xa5, 0xbe, 0xf6, 0xfe, 0xe2, 0xb8, 0x56, 0x96, 0xe8, 0x5a, 0xf9, 0x2b, 0x2f, 0x67, 0xbf, 0xcc, - 0x27, 0xba, 0x96, 0xb4, 0xc3, 0x90, 0xaf, 0xe9, 0xec, 0x97, 0x0e, 0x67, 0xcb, 0x5f, 0x7d, 0xbf, 0x31, 0x5d, 0xac, - 0x3e, 0xab, 0x7b, 0xf7, 0x61, 0xb0, 0x69, 0x9c, 0x7a, 0xef, 0x4e, 0xd7, 0x1b, 0x9b, 0x59, 0x6b, 0xcf, 0xcc, 0xff, - 0xe1, 0x4a, 0x6f, 0x71, 0xe8, 0x6e, 0xf8, 0x76, 0xb8, 0xb1, 0x47, 0x41, 0x7e, 0x5f, 0x2a, 0x8d, 0xb3, 0x9a, 0xbf, - 0xf4, 0x3a, 0xa5, 0x58, 0x40, 0x34, 0xfa, 0x64, 0x24, 0xa1, 0x4b, 0x66, 0xe2, 0x19, 0xe2, 0x8b, 0x0c, 0x90, 0xb9, - 0x40, 0x34, 0xbb, 0xe7, 0xe3, 0xc9, 0xfd, 0x55, 0x3c, 0xb9, 0x1f, 0xf0, 0x4f, 0xa6, 0x05, 0xed, 0xc5, 0x76, 0xef, - 0xb3, 0x5f, 0x79, 0x61, 0x2f, 0xc7, 0x5f, 0x7c, 0xf6, 0x45, 0xb8, 0x2b, 0xf4, 0x17, 0x9f, 0xbd, 0x13, 0xfc, 0xd7, - 0x91, 0x26, 0xca, 0x60, 0xef, 0x6a, 0xfe, 0xeb, 0x08, 0x19, 0x3f, 0xd8, 0x67, 0xc1, 0xbf, 0x80, 0xef, 0x77, 0x95, - 0xa0, 0x55, 0xfc, 0x73, 0xad, 0x7e, 0xbe, 0x97, 0x71, 0x39, 0xf0, 0x26, 0xb4, 0x82, 0xde, 0xbc, 0xad, 0xe5, 0x4f, - 0xe2, 0xe1, 0x48, 0xd5, 0x53, 0xc3, 0x3f, 0x8b, 0xc5, 0x2c, 0xea, 0xa3, 0x74, 0x2a, 0x6f, 0x72, 0xcd, 0x33, 0x69, - 0x5d, 0xbe, 0x87, 0x50, 0xe0, 0x6b, 0x1b, 0xa2, 0x60, 0xc7, 0x71, 0x23, 0xb8, 0x66, 0xef, 0x84, 0xcf, 0xb2, 0xe9, - 0x96, 0xdf, 0xf0, 0x27, 0xfc, 0x1d, 0xdf, 0x05, 0x0f, 0xfc, 0x3d, 0x7f, 0xcb, 0x7f, 0xe2, 0x3b, 0xb6, 0x94, 0x68, - 0xa7, 0xf5, 0xf6, 0x32, 0xd8, 0xb2, 0x7a, 0x77, 0x19, 0x3c, 0xb0, 0x7a, 0xfb, 0x3c, 0xb8, 0x61, 0xf5, 0xee, 0x79, - 0xf0, 0x9e, 0x6d, 0x2f, 0x83, 0x27, 0x6c, 0x77, 0x19, 0xbc, 0x65, 0xdb, 0xe7, 0xc1, 0x3b, 0xb6, 0x7b, 0x1e, 0xfc, - 0x24, 0x31, 0x1e, 0xde, 0x09, 0xc9, 0x71, 0xf2, 0xae, 0x66, 0x86, 0x4f, 0x37, 0xf8, 0x2c, 0xac, 0x5f, 0x54, 0xc7, - 0xe0, 0x73, 0xcd, 0x74, 0x8b, 0x03, 0x21, 0x98, 0x6e, 0x6f, 0x70, 0x4b, 0x4f, 0x4c, 0xab, 0x82, 0x54, 0xb0, 0xae, - 0x76, 0x06, 0x8b, 0xba, 0x69, 0x9d, 0xc9, 0x8e, 0x5f, 0x62, 0xdc, 0xe1, 0x97, 0xb8, 0x60, 0xcb, 0xa6, 0xd3, 0x49, - 0xe7, 0xf4, 0x49, 0xa0, 0x37, 0x7f, 0xbd, 0xeb, 0x57, 0xd2, 0x77, 0xa6, 0x68, 0x78, 0xae, 0xb4, 0xc6, 0xad, 0x9d, - 0x3e, 0xb4, 0x76, 0x7a, 0x26, 0x55, 0x68, 0x11, 0x8b, 0xca, 0xa2, 0xaa, 0x90, 0x49, 0x3c, 0xc8, 0xb4, 0x3e, 0x2d, - 0x61, 0xa4, 0xc8, 0x04, 0x34, 0xfa, 0x82, 0x8e, 0x81, 0x9c, 0x2c, 0x0a, 0x6c, 0xc9, 0x37, 0x83, 0x84, 0xad, 0x79, - 0x3c, 0x1d, 0x26, 0xc1, 0x92, 0xdd, 0xf1, 0x61, 0xb7, 0x40, 0xb0, 0x52, 0x01, 0x4c, 0xfa, 0xe2, 0xd4, 0xde, 0xd7, - 0x79, 0x6f, 0x95, 0xc6, 0x71, 0x26, 0x50, 0xd9, 0x56, 0xe9, 0x0d, 0x7e, 0xeb, 0xec, 0xe7, 0x6b, 0xb5, 0xbf, 0x83, - 0xa4, 0xf0, 0x2b, 0x30, 0xec, 0x10, 0xe1, 0x1d, 0x54, 0x18, 0x79, 0x96, 0xcc, 0xa2, 0xaf, 0xec, 0x2d, 0x7d, 0x6b, - 0xb6, 0xe9, 0xff, 0xb4, 0x08, 0xda, 0xc7, 0x65, 0xe7, 0x7f, 0x32, 0xaf, 0xfe, 0xd6, 0xf1, 0xea, 0xc6, 0x9f, 0x3c, - 0xf0, 0x4f, 0x18, 0x96, 0x80, 0x89, 0x6c, 0xc7, 0x3f, 0x8d, 0xb6, 0x8d, 0x53, 0x9e, 0xdc, 0xc7, 0xff, 0xaf, 0x14, - 0x68, 0xef, 0xe4, 0x95, 0xbd, 0x23, 0x6e, 0x79, 0xc7, 0x3e, 0xbe, 0xb4, 0x36, 0x44, 0x03, 0x4d, 0xf2, 0x89, 0xbb, - 0xd1, 0xd0, 0xb0, 0x21, 0xfe, 0xc2, 0xab, 0xd9, 0xa7, 0xf9, 0x64, 0xcb, 0x8f, 0xb7, 0xc3, 0x4f, 0x1d, 0xdb, 0xe1, - 0x2f, 0xfe, 0x60, 0xd9, 0x7c, 0xad, 0x57, 0x3b, 0xb7, 0x71, 0xa7, 0xd2, 0x3b, 0x7e, 0xbc, 0x89, 0x0f, 0xff, 0xe3, - 0x4a, 0xef, 0xbe, 0xb9, 0xd2, 0x76, 0x95, 0xbb, 0x3b, 0xdf, 0x74, 0x7c, 0x23, 0x6b, 0x8d, 0x71, 0x66, 0x46, 0xb3, - 0xf8, 0x13, 0xcd, 0xd2, 0x20, 0xb2, 0x14, 0x8a, 0x3f, 0x99, 0x69, 0xa7, 0xee, 0x54, 0x59, 0xdd, 0x2d, 0xdf, 0xe2, - 0x1e, 0x7f, 0xcb, 0xc7, 0x6c, 0x61, 0x3c, 0x35, 0x6f, 0xaf, 0x16, 0x93, 0xc1, 0xe0, 0xd6, 0xdf, 0xdf, 0xf3, 0x70, - 0x76, 0x3b, 0x67, 0xd7, 0xfc, 0x9e, 0x16, 0xd3, 0x44, 0x35, 0xbd, 0x78, 0x4c, 0xf0, 0xba, 0xf5, 0xfd, 0x89, 0xc5, - 0xff, 0x6a, 0x5f, 0x34, 0x6f, 0xfd, 0x81, 0xb4, 0x46, 0xcb, 0x5d, 0xfd, 0xfd, 0xe3, 0x8a, 0x89, 0x5b, 0x10, 0x2f, - 0xde, 0xdb, 0x9a, 0x86, 0xb7, 0xfc, 0xa3, 0x77, 0xed, 0x4f, 0xaf, 0x75, 0xcc, 0xcd, 0x44, 0x1d, 0x49, 0x6f, 0x2f, - 0x9e, 0xb3, 0x5f, 0xf9, 0x27, 0x79, 0x9c, 0x7c, 0x11, 0x72, 0xd2, 0xde, 0x20, 0x77, 0x13, 0x9d, 0x12, 0xef, 0xdc, - 0x44, 0xc2, 0x82, 0x40, 0x18, 0x8e, 0x9a, 0x3f, 0x4c, 0xca, 0xa9, 0xb7, 0x03, 0x6e, 0x57, 0x6e, 0xeb, 0x9f, 0x6f, - 0x39, 0xe7, 0x8b, 0xe1, 0xe5, 0xf4, 0x5d, 0xb7, 0x4b, 0x8f, 0x8a, 0x66, 0x53, 0x81, 0x6e, 0xb7, 0x18, 0x7b, 0x75, - 0x32, 0xb3, 0xcc, 0x25, 0x5f, 0x7a, 0x57, 0x9b, 0x99, 0xc7, 0xf4, 0x7e, 0x33, 0xcd, 0x90, 0xc8, 0x17, 0x08, 0x99, - 0x0e, 0x87, 0xbb, 0x73, 0x2c, 0x8f, 0x0f, 0xdf, 0x3e, 0x7b, 0x32, 0x78, 0x82, 0x91, 0x5b, 0x56, 0x34, 0xc8, 0x3b, - 0x3e, 0xcc, 0xea, 0xd6, 0x6d, 0xe3, 0xe2, 0xf9, 0xf0, 0x17, 0xc8, 0x1b, 0x74, 0x3d, 0x34, 0x45, 0xb4, 0xca, 0xef, - 0x28, 0xfa, 0x44, 0xc9, 0x41, 0xc7, 0x13, 0xa8, 0x1d, 0x52, 0xe0, 0xbe, 0x7b, 0xc6, 0x41, 0xbf, 0x81, 0xa5, 0xf6, - 0xfb, 0xe7, 0x9f, 0x88, 0x47, 0x1a, 0xc6, 0xfb, 0xfb, 0x30, 0xfa, 0x23, 0x2e, 0x8b, 0x35, 0x9c, 0xae, 0x03, 0xf8, - 0xdc, 0x33, 0x7d, 0xfb, 0xba, 0xf3, 0x7d, 0x3f, 0xf0, 0xb6, 0xfc, 0x86, 0xbd, 0xe3, 0xde, 0xe5, 0xf0, 0xad, 0xff, - 0xec, 0x09, 0x88, 0x4e, 0x30, 0x2e, 0x9f, 0x31, 0x12, 0xb6, 0xa3, 0x18, 0xb5, 0x0a, 0x3f, 0xd7, 0x10, 0xa2, 0xf5, - 0x09, 0x19, 0xbb, 0x20, 0xfd, 0x83, 0x02, 0xf4, 0x13, 0x02, 0xab, 0x49, 0x6a, 0x14, 0x98, 0xc4, 0xb7, 0x35, 0x24, - 0x90, 0x82, 0x05, 0x42, 0x6f, 0xa0, 0xf8, 0x54, 0xf0, 0x77, 0xc3, 0xcf, 0x24, 0xf9, 0x2d, 0x6a, 0x3e, 0x86, 0xbf, - 0x61, 0x68, 0x26, 0xd5, 0x43, 0x5a, 0x47, 0x89, 0xf7, 0x93, 0xbf, 0x8f, 0xc2, 0x4a, 0xa8, 0x63, 0x21, 0x48, 0xc5, - 0x90, 0x0b, 0x71, 0xf1, 0x7c, 0x72, 0x5b, 0x8a, 0xf0, 0x8f, 0x09, 0x3e, 0x93, 0x0b, 0x4d, 0x3e, 0xa3, 0x27, 0x8d, - 0x7c, 0xff, 0x41, 0xbe, 0x2f, 0x3b, 0x35, 0x58, 0xd4, 0x43, 0x7e, 0x5b, 0xbb, 0xef, 0xcb, 0x29, 0x41, 0x8f, 0xec, - 0x07, 0x34, 0x05, 0x03, 0x35, 0x01, 0x29, 0x43, 0x70, 0x0b, 0x57, 0x7d, 0x4f, 0x15, 0xe4, 0xcb, 0xef, 0x7d, 0x16, - 0x32, 0x5c, 0x65, 0x41, 0x48, 0x72, 0xa9, 0x90, 0xc2, 0xc6, 0x6d, 0x3d, 0xf8, 0xac, 0x31, 0x49, 0x24, 0xe4, 0x94, - 0x80, 0x24, 0x69, 0x6f, 0x20, 0x49, 0xc4, 0xf4, 0x1f, 0xae, 0x93, 0xa6, 0x59, 0x49, 0xe9, 0x86, 0x38, 0x55, 0xaf, - 0x91, 0xe6, 0x2c, 0x78, 0xcf, 0x60, 0xe9, 0x48, 0xb1, 0xe2, 0x9d, 0x31, 0x18, 0xeb, 0x60, 0xa1, 0x3b, 0x59, 0xdc, - 0xaf, 0x92, 0x30, 0x8d, 0x44, 0x95, 0x2f, 0x42, 0xfe, 0xfc, 0x97, 0x12, 0x7f, 0xf4, 0x96, 0x06, 0x22, 0x10, 0xfc, - 0x00, 0xad, 0x07, 0xac, 0xf1, 0xe0, 0x27, 0x56, 0x97, 0x61, 0x5e, 0x65, 0x54, 0xde, 0x6c, 0xc7, 0xb6, 0x73, 0xa6, - 0xaa, 0x16, 0x7c, 0x16, 0x86, 0x16, 0xed, 0x6c, 0xd5, 0x9c, 0xdc, 0xe6, 0x0d, 0xbe, 0x33, 0x49, 0x22, 0xb5, 0x94, - 0x44, 0xda, 0xea, 0xfa, 0x74, 0xe9, 0x75, 0x8b, 0x0a, 0x1a, 0x23, 0x40, 0x2f, 0x49, 0x77, 0x95, 0x4f, 0x28, 0x5e, - 0x59, 0x0d, 0xab, 0xe1, 0xa5, 0x43, 0x11, 0xc6, 0xda, 0x9b, 0x2b, 0x79, 0x76, 0x07, 0xd6, 0x23, 0xb4, 0x76, 0x55, - 0xea, 0x10, 0xb6, 0x9f, 0xe8, 0x3d, 0xa7, 0x52, 0x7f, 0x03, 0xaa, 0xc0, 0xa9, 0xa3, 0xa1, 0x3e, 0x6a, 0xa7, 0x90, - 0xed, 0xdc, 0x5b, 0x12, 0x54, 0xae, 0xe4, 0xa6, 0x4a, 0x8b, 0x52, 0xca, 0x94, 0xaf, 0x65, 0xb6, 0xb2, 0xfb, 0x64, - 0x00, 0xf1, 0x6c, 0x50, 0x20, 0xb9, 0xa8, 0xad, 0xe6, 0x20, 0x7d, 0x34, 0x4b, 0x1c, 0x6b, 0x07, 0x85, 0x97, 0x55, - 0x60, 0xe6, 0x32, 0x97, 0xcb, 0x41, 0xc1, 0x72, 0xbd, 0xd5, 0x4c, 0x33, 0xd5, 0x17, 0xb9, 0xbd, 0xcd, 0x78, 0x99, - 0xfe, 0x9b, 0x25, 0x03, 0x1e, 0x5d, 0x3c, 0xf7, 0x03, 0x48, 0x93, 0xbc, 0x0e, 0x90, 0x04, 0x9b, 0x83, 0x5d, 0xec, - 0x30, 0x6c, 0x15, 0x2b, 0x7b, 0xf2, 0x74, 0xb9, 0x43, 0x53, 0x2e, 0x61, 0x24, 0x27, 0xe6, 0x52, 0xea, 0xfb, 0x92, - 0xea, 0x86, 0x82, 0x93, 0x4d, 0x13, 0x50, 0x0a, 0x68, 0xb7, 0xe0, 0xbf, 0xf0, 0xa9, 0xa1, 0xd3, 0x02, 0x2c, 0xb5, - 0xdd, 0x80, 0xff, 0x42, 0xbf, 0xd8, 0x3e, 0xa2, 0x7e, 0x60, 0x1e, 0xec, 0xcd, 0xda, 0xca, 0x18, 0x10, 0x91, 0xb8, - 0x82, 0x3c, 0x12, 0xfc, 0xa0, 0xd8, 0xd3, 0x65, 0xe2, 0xc0, 0x99, 0xe2, 0x62, 0x29, 0xb5, 0x99, 0x79, 0xed, 0xb7, - 0xd4, 0xc4, 0x9b, 0x28, 0x89, 0x0a, 0xdb, 0x21, 0x8d, 0x5e, 0x52, 0xc6, 0x54, 0xc1, 0x86, 0xe8, 0xbe, 0x6e, 0x82, - 0x29, 0xf0, 0xa6, 0xaa, 0x02, 0x22, 0xd4, 0x5e, 0x64, 0x79, 0x7e, 0xd3, 0x05, 0x56, 0x17, 0x7c, 0x6c, 0x4c, 0xb3, - 0x0b, 0x56, 0x72, 0x35, 0x93, 0x3e, 0xf3, 0x76, 0xa0, 0x85, 0xbc, 0xcb, 0xcb, 0xa2, 0x15, 0xba, 0x1e, 0x44, 0x0b, - 0x7f, 0xaf, 0x39, 0x1e, 0x3d, 0xdb, 0x56, 0x53, 0x9b, 0x7d, 0xad, 0xc5, 0x02, 0x19, 0x88, 0x86, 0xbe, 0x90, 0x33, - 0x0a, 0x77, 0x95, 0xe6, 0x6a, 0xb5, 0xaf, 0xca, 0x20, 0x81, 0x89, 0x20, 0x6b, 0x59, 0x78, 0x8f, 0xee, 0xd5, 0x23, - 0xcd, 0x2b, 0x09, 0x9e, 0xb9, 0xf8, 0x0b, 0x00, 0xa1, 0x3c, 0x49, 0xc8, 0x01, 0x39, 0x80, 0xbf, 0xa5, 0x28, 0x95, - 0x06, 0xf8, 0x67, 0x75, 0x39, 0xb6, 0xf5, 0xfd, 0x9d, 0x56, 0x31, 0xb8, 0xfe, 0x7c, 0xdd, 0xf5, 0xac, 0x1d, 0xe2, - 0x5c, 0xd9, 0xea, 0xb5, 0x65, 0x9a, 0xc7, 0x48, 0x5d, 0x03, 0x70, 0x27, 0xd2, 0x23, 0x10, 0xc9, 0x4c, 0x34, 0xc8, - 0xd9, 0x0b, 0x3e, 0x9e, 0x8a, 0xc7, 0xa4, 0xbd, 0xca, 0xf7, 0xcd, 0x85, 0x3e, 0x18, 0x63, 0xdf, 0x82, 0x06, 0xf1, - 0xd1, 0x6a, 0x6b, 0x05, 0x62, 0xbd, 0x55, 0xea, 0x43, 0x37, 0x46, 0x41, 0x07, 0x8f, 0xb8, 0x91, 0x0b, 0x8e, 0xed, - 0xae, 0xad, 0xa7, 0xf4, 0x15, 0x80, 0xb9, 0x0e, 0x54, 0x32, 0x0c, 0x52, 0xe7, 0x89, 0xc2, 0x24, 0x3f, 0x4f, 0x48, - 0x42, 0x44, 0x75, 0xb6, 0x1c, 0xa5, 0xdc, 0xb4, 0x80, 0xcb, 0x8c, 0x0c, 0x30, 0x9b, 0x34, 0xeb, 0x27, 0x97, 0x2f, - 0x41, 0x2a, 0x0d, 0x11, 0xdc, 0xb0, 0xbd, 0x64, 0x74, 0xeb, 0xa8, 0x1b, 0x54, 0x49, 0xe6, 0xfa, 0xcd, 0xed, 0x2c, - 0x52, 0xe6, 0xcd, 0x47, 0x18, 0x6b, 0xf2, 0x21, 0xac, 0x13, 0xfc, 0x36, 0x40, 0x25, 0x7d, 0x2a, 0xbc, 0x68, 0x04, - 0x10, 0xea, 0x3b, 0x55, 0xc6, 0xa7, 0xc2, 0xcb, 0x46, 0x5b, 0x96, 0x51, 0x0a, 0xd5, 0x05, 0xb3, 0x5b, 0xd3, 0x85, - 0xe8, 0x56, 0xd5, 0x40, 0x1b, 0xb8, 0x76, 0x1d, 0x28, 0xa0, 0xa1, 0xda, 0x95, 0x1b, 0x16, 0x80, 0xd5, 0x4c, 0x04, - 0x86, 0xcb, 0xbf, 0xcf, 0x5f, 0xa9, 0x18, 0x9e, 0x7e, 0x3f, 0xf4, 0xf6, 0xdb, 0x20, 0x1a, 0x6d, 0x2f, 0xd9, 0x2e, - 0x88, 0x46, 0xbb, 0xcb, 0x86, 0xd1, 0xef, 0xe7, 0xf4, 0xfb, 0x79, 0x03, 0x3a, 0x12, 0x61, 0xc2, 0xec, 0xf5, 0x1b, - 0xb5, 0x7c, 0xa5, 0xd6, 0xef, 0xd4, 0xf2, 0xa5, 0x1a, 0xde, 0xda, 0x93, 0x44, 0x10, 0x59, 0xaa, 0x9a, 0x07, 0x49, - 0x91, 0x6a, 0xe9, 0x72, 0x8c, 0x16, 0x23, 0x6a, 0x29, 0x6b, 0x8e, 0x75, 0x22, 0xed, 0x1c, 0x94, 0x0c, 0x70, 0xb4, - 0xb8, 0xaa, 0x31, 0xdd, 0xac, 0x68, 0x09, 0xc4, 0x08, 0x2b, 0xdb, 0x72, 0x71, 0x93, 0xfa, 0xe8, 0x9c, 0x7c, 0xdb, - 0x2a, 0xe5, 0xdb, 0x56, 0xf0, 0xfc, 0x2b, 0x0a, 0xe5, 0x92, 0x6b, 0xd7, 0xb2, 0x69, 0xa1, 0x14, 0xca, 0xb8, 0x06, - 0x5b, 0xfb, 0x26, 0x30, 0x64, 0x3e, 0x52, 0xd4, 0xd8, 0x5e, 0x34, 0xca, 0x21, 0xc8, 0xd6, 0xc1, 0xa8, 0x53, 0x16, - 0x2c, 0xbe, 0xdd, 0x21, 0x03, 0x19, 0xe8, 0xa8, 0x6a, 0xe3, 0xd5, 0xce, 0x4a, 0x7f, 0x58, 0x5e, 0x3c, 0x67, 0x89, - 0x95, 0x4e, 0x7e, 0x53, 0xa1, 0x3f, 0x08, 0xd1, 0x37, 0x65, 0xc3, 0xc1, 0x8b, 0x2e, 0xb6, 0x32, 0x20, 0xde, 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, 0xf3, 0x28, 0xd4, - 0x2c, 0x4f, 0x00, 0x0b, 0x5e, 0x98, 0x19, 0x2e, 0xcc, 0x0c, 0xc7, 0x21, 0x35, 0x4e, 0x0f, 0x7a, 0xaf, 0x73, 0xcf, - 0x2d, 0x77, 0xa3, 0xd3, 0x30, 0x6f, 0x47, 0x1b, 0xcc, 0xf1, 0x41, 0x38, 0x81, 0xf8, 0xc0, 0x12, 0x01, 0x7a, 0x34, - 0xac, 0x8e, 0x1a, 0x2a, 0x47, 0xf1, 0x65, 0x01, 0x48, 0x96, 0x04, 0x20, 0xb9, 0x57, 0xe3, 0x5c, 0x5a, 0x7e, 0x5d, - 0x25, 0x21, 0x47, 0x64, 0xbc, 0x94, 0x76, 0xf7, 0x84, 0x97, 0x23, 0x23, 0x34, 0x4f, 0x16, 0xa9, 0x97, 0xb3, 0x8c, - 0x8d, 0x11, 0xb8, 0x28, 0xf4, 0x9b, 0xaa, 0xdf, 0x4f, 0x4b, 0x2f, 0xa7, 0x76, 0x7e, 0x02, 0x7f, 0xcb, 0x53, 0x67, - 0x91, 0x23, 0xe4, 0xd5, 0xc8, 0x24, 0x2c, 0x2f, 0x95, 0x7a, 0xfa, 0x12, 0x66, 0x50, 0x77, 0x6f, 0x14, 0x80, 0x6b, - 0x91, 0x4b, 0xa7, 0xda, 0x12, 0xae, 0x4c, 0xb9, 0xc1, 0x3e, 0x0f, 0x79, 0x4e, 0x42, 0xa8, 0x44, 0x1e, 0x29, 0xac, - 0xfb, 0xf6, 0xc5, 0xf3, 0x89, 0xeb, 0xc3, 0x62, 0xa3, 0x11, 0x1c, 0x0e, 0x00, 0x73, 0x30, 0xf5, 0xa2, 0x01, 0x2f, - 0xd5, 0x9c, 0xf9, 0xe8, 0xe5, 0x84, 0x8d, 0x01, 0x6a, 0x8a, 0x81, 0x53, 0xd6, 0x33, 0xf9, 0xc8, 0xf8, 0x96, 0xf9, - 0x7e, 0x80, 0xef, 0xd6, 0x85, 0x84, 0x7c, 0x50, 0xa8, 0x04, 0x99, 0x42, 0x25, 0x48, 0x0c, 0x2a, 0x41, 0x6c, 0x50, - 0x09, 0x36, 0x0d, 0x5f, 0x4b, 0xe5, 0x6d, 0x04, 0x1c, 0x11, 0x3e, 0xf4, 0x2c, 0x6c, 0xac, 0x50, 0x3c, 0x1b, 0xb3, - 0x31, 0x2b, 0xd4, 0xce, 0x93, 0xcb, 0xa9, 0xd8, 0x59, 0x8c, 0x75, 0x13, 0x59, 0x26, 0x5e, 0x48, 0xd0, 0x71, 0xce, - 0x85, 0x44, 0x5d, 0xfd, 0xdc, 0x7b, 0x49, 0xc6, 0x92, 0x79, 0x43, 0xa3, 0x06, 0xf3, 0xb2, 0xeb, 0x00, 0xa6, 0x25, - 0xdf, 0x16, 0x34, 0x98, 0x4e, 0x95, 0x47, 0xa4, 0x49, 0x50, 0x3b, 0x97, 0x49, 0x91, 0x13, 0xc2, 0x24, 0xe8, 0x95, - 0xe0, 0x37, 0x12, 0xda, 0xff, 0xab, 0x9e, 0xef, 0x80, 0xc1, 0x44, 0xab, 0xe4, 0x0b, 0x58, 0x2d, 0x73, 0xfe, 0x52, - 0x7a, 0x62, 0x23, 0xfe, 0x62, 0x99, 0xc6, 0xa3, 0x2f, 0x6c, 0x88, 0x78, 0x56, 0x2f, 0xd1, 0xb4, 0x04, 0x75, 0x80, - 0x47, 0xf4, 0xd7, 0xe8, 0x8b, 0xe1, 0x4d, 0xe9, 0x6a, 0xa4, 0xae, 0xd9, 0x39, 0xe7, 0x5f, 0x6a, 0x43, 0x84, 0x8c, - 0x69, 0x53, 0x20, 0x19, 0x10, 0x48, 0x32, 0x10, 0x00, 0x98, 0x9a, 0xce, 0xec, 0x15, 0x40, 0x34, 0x10, 0xc0, 0xe3, - 0xbc, 0xe3, 0xf1, 0x23, 0xfd, 0x55, 0x1c, 0xf7, 0x4e, 0xd3, 0xb0, 0xfd, 0x17, 0xa0, 0x29, 0x86, 0x72, 0x3c, 0xdf, - 0x29, 0x48, 0xf6, 0x28, 0x65, 0xe9, 0xaa, 0x89, 0xec, 0x50, 0xac, 0x4f, 0x73, 0xca, 0x42, 0xda, 0x96, 0x63, 0xb4, - 0xc5, 0xfa, 0x31, 0xf2, 0xde, 0xdc, 0xa8, 0xc8, 0x07, 0x3d, 0xb8, 0xbd, 0xbd, 0x7d, 0xdd, 0x63, 0x36, 0xc9, 0x8a, - 0x45, 0xae, 0x22, 0x4e, 0x9c, 0xd6, 0x21, 0x07, 0x0c, 0xc8, 0x49, 0x08, 0x4c, 0x63, 0x5c, 0x2a, 0xd0, 0x41, 0xc9, - 0x72, 0x5e, 0x03, 0xb5, 0x2c, 0x22, 0x6b, 0x80, 0xa8, 0xa6, 0xf9, 0x57, 0x0d, 0xf9, 0x49, 0xd5, 0x9c, 0x52, 0xa8, - 0x7d, 0xc5, 0xc3, 0xea, 0xf4, 0x89, 0x55, 0x9b, 0x18, 0xeb, 0x5f, 0x6b, 0x4f, 0xd0, 0x56, 0xd2, 0x40, 0x7c, 0xe7, - 0xeb, 0xf4, 0x8e, 0x42, 0x77, 0x9c, 0x99, 0x78, 0xaa, 0x02, 0x63, 0xdf, 0xda, 0x11, 0x14, 0x0e, 0x4d, 0xd7, 0x01, - 0x87, 0x69, 0x74, 0xc2, 0xe2, 0x9f, 0xd2, 0x71, 0xf2, 0xa2, 0x56, 0x88, 0x24, 0xff, 0x10, 0x2e, 0x0c, 0x89, 0x05, - 0x79, 0x49, 0xa8, 0x23, 0x32, 0x62, 0x35, 0x2a, 0xd6, 0x42, 0x45, 0xc5, 0x29, 0x1e, 0x6f, 0x15, 0x14, 0x97, 0xa2, - 0x54, 0x29, 0x15, 0xb9, 0x51, 0x29, 0x20, 0x96, 0x0d, 0xbc, 0x5b, 0xc0, 0x01, 0x10, 0x74, 0x96, 0xbb, 0xb5, 0xed, - 0x6e, 0x23, 0xf3, 0x99, 0x69, 0x9e, 0x56, 0x1f, 0xd4, 0xdf, 0xef, 0x97, 0x18, 0x5b, 0xe3, 0xe9, 0xef, 0xdb, 0xb4, - 0xe0, 0xe6, 0x6f, 0x18, 0xa2, 0x3b, 0x40, 0xc4, 0x2c, 0xed, 0xa1, 0x90, 0x05, 0x13, 0x96, 0xa1, 0x2a, 0x4f, 0x39, - 0xea, 0xe5, 0x93, 0x5b, 0x80, 0x50, 0x43, 0xbf, 0x36, 0x3a, 0xd5, 0x55, 0x09, 0xc2, 0xf7, 0x5d, 0xa1, 0x1e, 0x9b, - 0x03, 0x9e, 0x0c, 0x80, 0xbf, 0x22, 0xaf, 0xf5, 0xd8, 0xfe, 0x41, 0x6f, 0xd4, 0x1b, 0x20, 0x88, 0xce, 0x79, 0xe1, - 0x1f, 0x71, 0xae, 0x53, 0x7f, 0xc6, 0x85, 0x20, 0xbe, 0xf5, 0x24, 0xbc, 0x17, 0x67, 0x69, 0x1c, 0x9c, 0xf5, 0x06, - 0xe6, 0x22, 0x50, 0x9c, 0xa5, 0xf9, 0x19, 0x88, 0xe5, 0x88, 0x89, 0x58, 0xb3, 0x3b, 0x80, 0x09, 0x2c, 0x75, 0x1c, - 0xb2, 0xea, 0xd8, 0x7e, 0xff, 0xcd, 0xc8, 0x90, 0xa5, 0x23, 0x0c, 0x8c, 0xfe, 0x5d, 0x81, 0x00, 0x05, 0xcb, 0xcc, - 0xf6, 0x60, 0xd2, 0xd5, 0x9e, 0xd5, 0xf3, 0x66, 0x93, 0x77, 0xf5, 0x8e, 0xd5, 0xb4, 0x9c, 0x9a, 0x56, 0x59, 0x4d, - 0x9b, 0xe4, 0x50, 0x33, 0xd1, 0xef, 0x6b, 0x50, 0xd4, 0x7c, 0x0e, 0x60, 0x6c, 0x98, 0xfc, 0x66, 0x56, 0xcd, 0xfb, - 0x7d, 0x4f, 0x3e, 0x82, 0x5f, 0xc8, 0x56, 0xe6, 0xd6, 0x58, 0x3e, 0x7d, 0x4d, 0x24, 0x66, 0x06, 0xe6, 0xe8, 0xee, - 0x08, 0xdf, 0xeb, 0x46, 0x78, 0x1d, 0x73, 0x85, 0xcd, 0xc4, 0xf4, 0x0d, 0x0c, 0x9e, 0x27, 0x7c, 0x70, 0x91, 0xa3, - 0xbf, 0x91, 0xc3, 0x4c, 0x61, 0x41, 0xce, 0xfd, 0xc9, 0x1b, 0xc4, 0x4b, 0x46, 0x78, 0x07, 0x9d, 0x4e, 0x78, 0x90, - 0xfd, 0xfe, 0x0a, 0x3a, 0xb3, 0x95, 0x4a, 0xd9, 0xaa, 0xa8, 0x4c, 0xd7, 0x75, 0x51, 0x56, 0xd0, 0xb1, 0xf4, 0xf3, - 0x56, 0xc8, 0xcc, 0xfa, 0x99, 0x05, 0xf7, 0xb4, 0x92, 0x00, 0x53, 0xb6, 0x6d, 0xa2, 0x36, 0xf0, 0xb2, 0x2e, 0x3e, - 0x17, 0x78, 0x74, 0xd6, 0x5e, 0x6f, 0x84, 0xda, 0xe7, 0x7c, 0xb4, 0x2e, 0xd6, 0x1e, 0xf8, 0xc1, 0xcc, 0xd2, 0xb9, - 0x22, 0xce, 0xc8, 0xfd, 0xd1, 0xe7, 0x22, 0xcd, 0x29, 0x0f, 0x70, 0x1f, 0x8a, 0xb9, 0xfd, 0x16, 0x48, 0x3f, 0xf4, - 0x16, 0xc8, 0x3e, 0x3a, 0xe7, 0xe4, 0x0d, 0x20, 0xd2, 0x21, 0x0c, 0x6e, 0x45, 0x82, 0x8e, 0x55, 0xc3, 0x5b, 0x0b, - 0xec, 0xb4, 0x97, 0xc6, 0xbd, 0x34, 0x3f, 0x4b, 0xfb, 0x7d, 0x83, 0x9a, 0x99, 0x22, 0x1c, 0x3c, 0xce, 0xc8, 0x45, - 0xd2, 0x82, 0x2d, 0xa5, 0xfd, 0x57, 0x03, 0x47, 0x10, 0xf2, 0xf7, 0x3f, 0x84, 0xf7, 0x04, 0x20, 0x36, 0x69, 0x03, - 0xae, 0x7a, 0x4c, 0x47, 0x63, 0x4b, 0xa2, 0x56, 0x9d, 0x0d, 0x90, 0x38, 0x55, 0x5a, 0x4f, 0xb9, 0x59, 0x53, 0x18, - 0xa4, 0xca, 0x42, 0xfd, 0xc6, 0x7a, 0x32, 0x59, 0xe5, 0x22, 0x23, 0x8e, 0xca, 0xf4, 0xa5, 0x66, 0x04, 0xd3, 0xa5, - 0x9f, 0x2f, 0x60, 0xc9, 0xc6, 0x1f, 0x71, 0xf2, 0x96, 0x80, 0x63, 0x3b, 0x6b, 0x57, 0xd5, 0x2e, 0xc7, 0xad, 0xdd, - 0x1c, 0xe0, 0x7b, 0xbd, 0xd1, 0x68, 0xa4, 0x9d, 0xe3, 0x04, 0x0c, 0x55, 0x4f, 0x2d, 0x85, 0x1e, 0xab, 0x15, 0xa0, - 0x6e, 0x47, 0x2e, 0xb3, 0x64, 0x30, 0x5f, 0x18, 0xc7, 0xaf, 0xcc, 0x47, 0x1f, 0x2f, 0x95, 0xb5, 0xeb, 0x88, 0xaf, - 0xff, 0x20, 0xab, 0xf5, 0x2d, 0xef, 0xaa, 0x26, 0xe0, 0x8b, 0x2a, 0xa0, 0xf4, 0x1b, 0xde, 0x93, 0xbd, 0x8b, 0xaf, - 0xdd, 0x60, 0x97, 0x7c, 0xcb, 0x5b, 0xd4, 0x79, 0xbe, 0x72, 0x70, 0xa3, 0x4a, 0xb7, 0xf7, 0x92, 0x05, 0xae, 0xbd, - 0xa3, 0xa6, 0xb1, 0x9e, 0xf9, 0xd1, 0xc3, 0x22, 0x64, 0x3b, 0x1f, 0x7b, 0x5f, 0x35, 0x4f, 0xcf, 0x1a, 0x7a, 0x93, - 0x1a, 0xfa, 0xd8, 0x8b, 0xb2, 0x7d, 0x6a, 0x1a, 0xd1, 0x6b, 0xd8, 0xd0, 0xc7, 0xde, 0x92, 0x93, 0x43, 0x22, 0xc0, - 0xa9, 0x31, 0x7f, 0x7c, 0x38, 0x9d, 0xe1, 0xef, 0x18, 0x50, 0x09, 0xc4, 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, 0x24, 0x77, 0xa5, 0x37, 0xb0, 0x02, 0x69, 0x5b, 0x54, 0x1f, 0xca, - 0xa5, 0xb7, 0x53, 0x87, 0x76, 0xe5, 0x4f, 0xf2, 0xc3, 0xa1, 0x18, 0x99, 0x63, 0x1c, 0xc0, 0x4d, 0x0a, 0x25, 0x47, - 0xc9, 0x5a, 0x82, 0xe8, 0x94, 0xc6, 0x53, 0x59, 0xaf, 0xad, 0x88, 0xbc, 0x1a, 0x71, 0x1e, 0x82, 0x1f, 0x3d, 0x50, - 0x8b, 0xbf, 0xd0, 0x82, 0xd8, 0x63, 0x9f, 0x2a, 0xa5, 0x17, 0xbc, 0x2a, 0x20, 0x44, 0xec, 0xef, 0x06, 0xda, 0x41, - 0x09, 0x0e, 0x25, 0xdc, 0x07, 0x84, 0x85, 0x7e, 0xed, 0xe5, 0x33, 0x19, 0xa3, 0xdc, 0x1b, 0x54, 0x73, 0x06, 0x30, - 0x95, 0x3e, 0x03, 0xbf, 0x4b, 0x80, 0x3a, 0xc5, 0xa7, 0xe8, 0x54, 0x6f, 0x1e, 0x36, 0x5d, 0x9f, 0x96, 0x28, 0x8a, - 0xe8, 0xce, 0xcf, 0xc7, 0x80, 0xd8, 0xd9, 0xb5, 0x19, 0x69, 0xd7, 0x7e, 0x83, 0x06, 0x2b, 0x25, 0x89, 0x76, 0x4e, - 0x09, 0xbb, 0x9d, 0x8f, 0x6c, 0xe9, 0x47, 0x29, 0x10, 0x73, 0xc7, 0x89, 0x44, 0xf6, 0x60, 0x23, 0x27, 0x70, 0x8b, - 0xf6, 0x8e, 0x0e, 0x40, 0xe5, 0x46, 0x41, 0x7e, 0x35, 0x47, 0x72, 0xc7, 0x77, 0xbd, 0xef, 0x06, 0xf5, 0xe0, 0xbb, - 0xde, 0x59, 0x4a, 0x72, 0x47, 0x78, 0xa6, 0xa6, 0x84, 0x88, 0xcf, 0xbe, 0x1b, 0xe4, 0x03, 0x3c, 0x4b, 0xb4, 0x48, - 0x8b, 0x84, 0x6a, 0x75, 0x8d, 0x9b, 0xf0, 0x22, 0x91, 0xdc, 0x43, 0xbb, 0xce, 0x23, 0x62, 0x01, 0xc8, 0x58, 0x7c, - 0x36, 0x6f, 0x28, 0xd4, 0xdd, 0xc4, 0x6c, 0xd1, 0x5d, 0x16, 0xfb, 0xfd, 0x6d, 0x9e, 0xd6, 0x3d, 0x1d, 0x1f, 0x83, - 0x2f, 0x48, 0x35, 0x01, 0x1e, 0xed, 0xaf, 0xcd, 0xf1, 0xea, 0xd5, 0xe6, 0x48, 0x59, 0xa8, 0x12, 0xf5, 0x5b, 0xac, - 0x66, 0x3d, 0x84, 0xe1, 0xce, 0x32, 0x63, 0x6d, 0x2f, 0x78, 0x25, 0x67, 0x55, 0x6c, 0x97, 0xe3, 0x2b, 0x96, 0xda, - 0x4a, 0xa2, 0x72, 0xb4, 0x1e, 0x6b, 0x53, 0x8c, 0xfc, 0x4a, 0x21, 0x51, 0x16, 0x1d, 0x5b, 0x0b, 0x05, 0xc4, 0x0b, - 0xd0, 0x97, 0xec, 0x4c, 0x03, 0xac, 0x37, 0x7a, 0x15, 0x11, 0x5a, 0x3e, 0x52, 0xe1, 0x4d, 0x6e, 0xaa, 0xcc, 0xca, - 0x66, 0xd1, 0xee, 0xa7, 0x8a, 0x57, 0x08, 0x56, 0x6f, 0xd4, 0x1e, 0x05, 0xa8, 0x3d, 0xb4, 0x50, 0x06, 0x90, 0xd2, - 0x34, 0x03, 0x40, 0x06, 0x00, 0x99, 0x2a, 0xe2, 0x33, 0x01, 0x2a, 0x6d, 0x75, 0xa3, 0xc0, 0x89, 0xf4, 0x1a, 0x68, - 0x16, 0x58, 0xe9, 0x23, 0x05, 0x19, 0x2c, 0xb6, 0x08, 0xc0, 0xca, 0x91, 0x33, 0x4c, 0x63, 0xc8, 0x36, 0x9a, 0xb8, - 0x24, 0xcd, 0xef, 0xc3, 0x2c, 0x95, 0x78, 0x12, 0x3f, 0xc8, 0x1a, 0x23, 0x00, 0x90, 0xbe, 0x4f, 0x2f, 0x8a, 0x2c, - 0x26, 0x1c, 0x38, 0xeb, 0xa9, 0x83, 0xa2, 0x26, 0xe7, 0x5a, 0xd3, 0xea, 0x59, 0x6d, 0xf2, 0x90, 0x05, 0x3a, 0x7b, - 0x30, 0x26, 0xb5, 0x7c, 0xcf, 0x23, 0xfb, 0x2b, 0xc7, 0x33, 0xc2, 0x77, 0xdd, 0xc1, 0xa9, 0xff, 0x6e, 0x6a, 0x60, - 0x62, 0x4a, 0x00, 0x36, 0x06, 0x47, 0x13, 0xe2, 0x77, 0x3a, 0x26, 0x53, 0x9b, 0x14, 0x81, 0xc0, 0x43, 0xf0, 0x0a, - 0x9e, 0x1b, 0x2e, 0xb7, 0xdc, 0xd8, 0x59, 0xe4, 0x69, 0x02, 0x70, 0xe2, 0x05, 0xdf, 0x02, 0x1c, 0xa7, 0x5e, 0x15, - 0xb2, 0x67, 0xcf, 0xc5, 0x74, 0x36, 0x0f, 0x1e, 0x12, 0xda, 0xbf, 0x98, 0xf0, 0x9b, 0xee, 0x2a, 0xb9, 0x32, 0xb5, - 0xee, 0x4d, 0x74, 0x95, 0xcb, 0x9d, 0x3e, 0xad, 0x38, 0x86, 0x39, 0x83, 0x55, 0x40, 0xce, 0xd9, 0x90, 0xbf, 0x38, - 0x07, 0xc0, 0x96, 0x95, 0xf0, 0x22, 0xfe, 0x22, 0x94, 0xd5, 0x02, 0xb8, 0x47, 0xce, 0x23, 0xf3, 0xcb, 0x57, 0xdb, - 0xa1, 0x9c, 0x53, 0x14, 0xc6, 0x72, 0x6a, 0x5a, 0x52, 0x9c, 0x0e, 0x3d, 0x05, 0x93, 0xa9, 0x2d, 0x7f, 0x6f, 0x13, - 0x97, 0xd9, 0x9b, 0x49, 0x38, 0x5f, 0x47, 0xb6, 0xad, 0x55, 0xf7, 0xd0, 0x0d, 0xc1, 0xa0, 0x8f, 0x11, 0xb4, 0x6c, - 0xae, 0xef, 0xd6, 0x83, 0x81, 0xc2, 0xf6, 0xad, 0xe9, 0xa6, 0x45, 0xa7, 0x38, 0xe0, 0xcc, 0x5a, 0xd7, 0xa8, 0x54, - 0x15, 0x87, 0x5e, 0xf2, 0x6e, 0x59, 0x95, 0x5d, 0x96, 0x5e, 0x08, 0x52, 0xa3, 0xae, 0x22, 0x44, 0x4a, 0xc5, 0x0e, - 0xef, 0xc9, 0xaf, 0x81, 0x89, 0x67, 0x56, 0x8e, 0xd2, 0x78, 0x0e, 0x30, 0x41, 0x0a, 0x7d, 0x53, 0x7e, 0x05, 0xb8, - 0xa1, 0x8b, 0x28, 0xcc, 0xde, 0xc6, 0x55, 0x50, 0x5b, 0x4d, 0xbf, 0x77, 0x70, 0x62, 0xcf, 0xeb, 0x7e, 0x3f, 0x25, - 0x1a, 0x3f, 0x0c, 0xbd, 0xc0, 0xbf, 0xc7, 0xd3, 0x7d, 0x13, 0xa4, 0xe6, 0x95, 0x07, 0x78, 0x45, 0x97, 0x5b, 0x9b, - 0x72, 0x45, 0xe3, 0x62, 0x5e, 0x23, 0x22, 0x7c, 0xea, 0x28, 0xb6, 0xdb, 0xfc, 0x38, 0xb5, 0x31, 0x18, 0x84, 0x70, - 0xdf, 0xca, 0xf8, 0x7d, 0xe2, 0xe5, 0xb3, 0x68, 0x0e, 0x8a, 0xd2, 0x4c, 0x93, 0x84, 0x14, 0xd2, 0x4b, 0x80, 0x3e, - 0x1a, 0x84, 0x5a, 0x5d, 0xf9, 0x47, 0xe2, 0xa5, 0x6a, 0x5a, 0x9b, 0xa7, 0x58, 0xa3, 0x40, 0xcc, 0xa2, 0x79, 0xc3, - 0x32, 0x3a, 0x24, 0xd5, 0xe5, 0xd2, 0x34, 0xe3, 0x0f, 0xab, 0x19, 0xaa, 0x15, 0x47, 0x4d, 0x50, 0xa3, 0x74, 0x03, - 0x17, 0xc0, 0xbf, 0xd3, 0x1d, 0x47, 0x35, 0x8a, 0x14, 0x0d, 0xf8, 0x04, 0x81, 0x61, 0xcd, 0xe6, 0x09, 0x6b, 0x4d, - 0x5d, 0x33, 0xfa, 0x7d, 0x19, 0x27, 0x64, 0x92, 0x90, 0x9c, 0x0f, 0x97, 0xeb, 0x47, 0x52, 0x5d, 0x00, 0xa9, 0x72, - 0xc5, 0x66, 0xbd, 0xde, 0x1c, 0x30, 0x7a, 0x61, 0xfd, 0xc2, 0xc6, 0x15, 0x9c, 0x5f, 0x12, 0xe6, 0xae, 0xfa, 0x11, - 0x66, 0x19, 0x54, 0x01, 0x69, 0x7e, 0x2c, 0x78, 0xf3, 0xdc, 0x05, 0xa2, 0x7e, 0x33, 0x52, 0x17, 0x94, 0x59, 0x3a, - 0xb7, 0x88, 0x40, 0xc0, 0x6b, 0x58, 0x3d, 0x81, 0x64, 0x5f, 0x3e, 0xf6, 0x69, 0x46, 0x81, 0xea, 0x08, 0x40, 0xd9, - 0xac, 0x1f, 0xc2, 0xfe, 0x01, 0xe1, 0x84, 0xfa, 0x9b, 0x37, 0x72, 0xd6, 0x90, 0x3c, 0x90, 0x6a, 0xc2, 0x63, 0x38, - 0x35, 0x16, 0xf8, 0xd2, 0xa2, 0x37, 0x15, 0xbc, 0x26, 0x38, 0xee, 0x05, 0x5a, 0xfb, 0x16, 0x70, 0x84, 0x08, 0x2e, - 0x43, 0x13, 0xa7, 0xbd, 0x5d, 0x2f, 0x40, 0x42, 0x73, 0x0b, 0xe7, 0xfa, 0xda, 0x05, 0x2d, 0x4e, 0x91, 0x93, 0x45, - 0x17, 0x18, 0xe8, 0x82, 0xcc, 0x1b, 0xff, 0xaa, 0x60, 0xe5, 0x02, 0x64, 0x2f, 0x15, 0x2b, 0x89, 0xd8, 0x76, 0xea, - 0x8f, 0x52, 0xd9, 0x6f, 0xcf, 0xac, 0x09, 0xfc, 0x2a, 0xb1, 0x5f, 0x22, 0x93, 0x6f, 0x7a, 0x6c, 0xf2, 0x95, 0xb1, - 0xd0, 0xa9, 0x65, 0x70, 0x4e, 0x8f, 0x0c, 0xce, 0xbd, 0x9d, 0x55, 0x9b, 0x10, 0x86, 0x82, 0x24, 0xd0, 0x74, 0xe9, - 0x61, 0xdd, 0xf4, 0xe7, 0x27, 0x2d, 0x7e, 0xad, 0xda, 0xb7, 0xee, 0xc7, 0x21, 0x76, 0xf1, 0xab, 0xc4, 0x33, 0xec, - 0xa3, 0x3e, 0x70, 0x80, 0xc9, 0x88, 0x89, 0xcb, 0x7e, 0x1f, 0x0a, 0x9b, 0x8d, 0xe7, 0xa3, 0xba, 0xf8, 0xb9, 0x78, - 0x00, 0x28, 0x87, 0x0a, 0xec, 0x72, 0x28, 0x43, 0x19, 0xb1, 0xa9, 0x2d, 0xf7, 0xfc, 0xfe, 0x2a, 0xcc, 0x41, 0xde, - 0xd1, 0x98, 0x38, 0x67, 0x20, 0x86, 0xc1, 0xd7, 0xbf, 0x7b, 0xb2, 0x4f, 0x9b, 0xef, 0xce, 0xe0, 0xbb, 0xa3, 0xb3, - 0x0f, 0xc8, 0x71, 0x73, 0xb6, 0x2e, 0x8b, 0xfb, 0x34, 0x16, 0x67, 0xdf, 0x41, 0xea, 0x77, 0x67, 0x45, 0x79, 0xf6, - 0x9d, 0xaa, 0xcc, 0x77, 0x67, 0xb4, 0xe0, 0x46, 0xbf, 0x5b, 0x13, 0xef, 0x9f, 0x95, 0xa6, 0x3d, 0x5b, 0x42, 0x38, - 0x96, 0x56, 0x3f, 0x82, 0x12, 0x51, 0x91, 0xa2, 0xca, 0x50, 0x56, 0x6b, 0xc7, 0x79, 0x9f, 0x68, 0x78, 0x6c, 0x9a, - 0x90, 0xb8, 0x5a, 0xc2, 0x3a, 0xd4, 0xb3, 0xd3, 0x26, 0xd9, 0x71, 0x1e, 0xa8, 0x03, 0x22, 0xe7, 0x2f, 0xf2, 0xd1, - 0x96, 0xbe, 0x06, 0xdf, 0x3a, 0x1c, 0xf2, 0xd1, 0xce, 0xfc, 0xf4, 0xc9, 0x5a, 0x29, 0x83, 0x8d, 0x14, 0xa3, 0x10, - 0x12, 0xc5, 0x6d, 0x7b, 0x0c, 0x80, 0xff, 0xfd, 0xc3, 0x81, 0x7e, 0xef, 0xe4, 0x6f, 0xb5, 0x5b, 0x5a, 0xf5, 0xfc, - 0xd0, 0x22, 0xcc, 0x78, 0x5d, 0x1b, 0x76, 0xb6, 0xbd, 0x04, 0x94, 0xde, 0x37, 0x0d, 0x6a, 0x8a, 0xe8, 0x27, 0xac, - 0x26, 0x56, 0x71, 0x58, 0x90, 0x12, 0x87, 0x18, 0x8e, 0xd1, 0x0e, 0x3d, 0x4e, 0x17, 0x35, 0x4f, 0xee, 0x3b, 0x64, - 0xdc, 0xfa, 0x3e, 0x20, 0xb9, 0x14, 0xce, 0x3f, 0x78, 0xa1, 0xc1, 0x44, 0x2f, 0xf2, 0xaa, 0xc8, 0xc4, 0x48, 0xd0, - 0x28, 0xbf, 0x25, 0x71, 0xe6, 0x0c, 0x6b, 0x71, 0xa6, 0x10, 0xc2, 0x42, 0x42, 0xe5, 0x2e, 0x4a, 0x4a, 0x0f, 0xce, - 0x9e, 0xec, 0xcb, 0xe6, 0x77, 0xc2, 0x84, 0x18, 0x2d, 0x80, 0x06, 0x67, 0xd7, 0x2e, 0xef, 0x21, 0x2c, 0x73, 0xef, - 0xf7, 0xb7, 0x77, 0x79, 0x01, 0x71, 0x99, 0x67, 0x52, 0xb1, 0x5a, 0x9e, 0x01, 0x4d, 0x9e, 0x88, 0xcf, 0xc2, 0x4a, - 0x4e, 0x83, 0xaa, 0xa3, 0x58, 0xbd, 0x8d, 0xe7, 0x1e, 0xf0, 0x7a, 0xbf, 0x4f, 0x80, 0xc0, 0xdd, 0x67, 0x6f, 0x94, - 0x5b, 0x2a, 0xe9, 0x91, 0xe7, 0x18, 0x22, 0x99, 0x00, 0xaf, 0x33, 0x04, 0x47, 0x0a, 0xab, 0xe7, 0x26, 0xc8, 0x3f, - 0xbe, 0x3e, 0xa1, 0xf8, 0xa2, 0x79, 0x14, 0x35, 0x2c, 0x64, 0x09, 0x1c, 0x0f, 0xc9, 0x2c, 0x9b, 0x23, 0x35, 0x79, - 0xda, 0x9e, 0x22, 0x1d, 0x9d, 0x58, 0xe2, 0xb7, 0x35, 0xa9, 0x5e, 0xa4, 0xc2, 0x2e, 0x69, 0x67, 0x2b, 0x73, 0x2f, - 0x84, 0xa1, 0x4a, 0xb8, 0xf7, 0xba, 0x9e, 0x85, 0x72, 0x53, 0xb4, 0x2a, 0x66, 0x0f, 0x53, 0x62, 0x86, 0x29, 0xd6, - 0x5f, 0xd8, 0xf0, 0x9b, 0xc4, 0x8b, 0xc1, 0x70, 0xbd, 0xe4, 0xe5, 0x6c, 0x63, 0x16, 0xc2, 0xe1, 0xb0, 0x99, 0x14, - 0xb3, 0x25, 0xc4, 0xb6, 0x2e, 0xe7, 0x87, 0x43, 0x57, 0xcb, 0xd6, 0xc2, 0x83, 0x87, 0xaa, 0x85, 0x9b, 0x86, 0xe5, - 0xf0, 0x33, 0x99, 0xc5, 0xd8, 0xbe, 0xc6, 0x67, 0xf6, 0xe7, 0x8b, 0xee, 0x59, 0x82, 0x8c, 0x1b, 0x6b, 0xe0, 0x1a, - 0x9b, 0xb5, 0x3b, 0x5c, 0x8d, 0x80, 0xe4, 0x71, 0x37, 0xfa, 0xbb, 0xb2, 0x93, 0x9c, 0x04, 0x09, 0xa3, 0x15, 0xc2, - 0xef, 0xbe, 0xf1, 0x27, 0x5a, 0xec, 0x41, 0xbb, 0x8d, 0x2d, 0x21, 0xaa, 0x69, 0xcf, 0xe5, 0x4a, 0xb1, 0x34, 0x6f, - 0xa5, 0x0d, 0x99, 0x0f, 0xeb, 0x73, 0xdf, 0xc8, 0x81, 0x82, 0x31, 0xe2, 0xa9, 0x75, 0x10, 0xcd, 0xe6, 0xc0, 0x7d, - 0x81, 0xe6, 0x11, 0x9e, 0x5a, 0x90, 0xa0, 0xcc, 0xda, 0xb0, 0x9f, 0x24, 0x27, 0xcb, 0xe3, 0xf0, 0x2d, 0xfc, 0xcb, - 0x67, 0xd8, 0x24, 0xa6, 0x28, 0x1e, 0x7f, 0xab, 0x14, 0xff, 0x1d, 0x5b, 0x10, 0xc1, 0xda, 0x8d, 0xa8, 0x0d, 0x7f, - 0xc3, 0xbf, 0x85, 0x7d, 0x84, 0xfd, 0x86, 0x26, 0x08, 0x03, 0x58, 0x7f, 0x26, 0x10, 0x17, 0x16, 0x82, 0x04, 0x7f, - 0xab, 0x24, 0xff, 0x9c, 0xf0, 0xd9, 0xa2, 0x04, 0xb2, 0x3a, 0x8c, 0xe2, 0x13, 0x8a, 0x89, 0x42, 0x18, 0x6e, 0x09, - 0xbd, 0xa3, 0xff, 0x46, 0x94, 0x64, 0x93, 0xdc, 0x8a, 0xf5, 0x40, 0x26, 0x49, 0x30, 0xc1, 0xca, 0x0b, 0xe5, 0x4b, - 0xf7, 0x42, 0xa9, 0xb5, 0x16, 0xb4, 0x7e, 0xf9, 0x93, 0xc4, 0x33, 0xa0, 0x7b, 0x20, 0x63, 0xd0, 0x6d, 0x44, 0x35, - 0xc9, 0x31, 0x7d, 0x94, 0xce, 0x33, 0x50, 0x01, 0x9d, 0xad, 0xb3, 0xb0, 0x5e, 0x16, 0xe5, 0xaa, 0x15, 0x1e, 0x2a, - 0x4b, 0x1f, 0xa9, 0xc7, 0x98, 0x17, 0xe6, 0xc9, 0x89, 0x7c, 0xf0, 0x08, 0xd0, 0xf0, 0x28, 0x4f, 0xab, 0x8e, 0xd2, - 0xfa, 0x81, 0x65, 0xc0, 0x08, 0x9c, 0x28, 0x03, 0x1e, 0x61, 0x19, 0x98, 0xa7, 0x5d, 0x86, 0x1a, 0xc4, 0x1a, 0x55, - 0x57, 0x6a, 0x83, 0x39, 0x51, 0x94, 0x7c, 0x8a, 0xa5, 0x15, 0xc6, 0xd0, 0xd4, 0x95, 0x47, 0xd6, 0x4b, 0x4e, 0xd8, - 0x93, 0xdd, 0x40, 0xba, 0x85, 0x8d, 0x02, 0x17, 0x74, 0x2d, 0x4b, 0x94, 0x8b, 0x6e, 0x19, 0x51, 0x26, 0x42, 0xea, - 0x67, 0x0f, 0x67, 0x5a, 0xed, 0x37, 0x76, 0xd2, 0xbe, 0x3d, 0x52, 0xf4, 0x82, 0x81, 0xf8, 0xb4, 0x47, 0x4a, 0x3d, - 0x6b, 0xe4, 0x32, 0xb0, 0xa5, 0x4b, 0x55, 0xcf, 0x7f, 0x83, 0xf2, 0x1d, 0xcc, 0x8c, 0xb3, 0xd9, 0xef, 0x7a, 0x73, - 0x7b, 0xb2, 0xaf, 0x9b, 0xdf, 0x59, 0xaf, 0x07, 0x5b, 0x83, 0x4c, 0x7c, 0xa9, 0xa8, 0xa7, 0xac, 0x42, 0xac, 0xc8, - 0xec, 0x7f, 0x0b, 0xef, 0x77, 0x78, 0x6b, 0x84, 0x66, 0x65, 0x3c, 0xcc, 0x47, 0x4f, 0xf6, 0xa2, 0xf9, 0xbd, 0xb3, - 0x6c, 0x2b, 0x57, 0x25, 0xb3, 0xfd, 0x7e, 0x94, 0x34, 0x67, 0x8f, 0xd7, 0x48, 0xea, 0x00, 0x1f, 0xaf, 0xcf, 0xf0, - 0x91, 0x4a, 0x28, 0xb5, 0xa0, 0xaa, 0x41, 0xeb, 0x63, 0xbf, 0xb7, 0x9e, 0xd3, 0xc7, 0x8f, 0xe5, 0x74, 0x4b, 0x8a, - 0x30, 0x7e, 0x60, 0x30, 0x65, 0x27, 0x4e, 0x5d, 0xf2, 0x66, 0x48, 0xef, 0xba, 0x55, 0x52, 0x97, 0x3d, 0x4a, 0x04, - 0xa1, 0x0e, 0xd6, 0x2f, 0xf6, 0x43, 0x98, 0xd9, 0xa2, 0x3f, 0x6c, 0x56, 0x73, 0x42, 0x41, 0x04, 0x88, 0x56, 0x79, - 0x1f, 0x38, 0x26, 0x09, 0xb3, 0xe6, 0x86, 0x74, 0xeb, 0xcd, 0x95, 0xf6, 0x4a, 0x0a, 0xe8, 0xe7, 0x20, 0x73, 0xfb, - 0xe8, 0x96, 0xab, 0x96, 0x79, 0x2e, 0x6d, 0x39, 0x60, 0xd1, 0x42, 0x74, 0x66, 0xe7, 0xd2, 0xe1, 0xe0, 0x3f, 0xa8, - 0x2b, 0x51, 0x45, 0x04, 0x1d, 0x45, 0x0b, 0x46, 0xab, 0x55, 0xbb, 0x9c, 0x6c, 0x2a, 0x64, 0x4b, 0x22, 0x9c, 0x28, - 0xd9, 0x2b, 0xa1, 0x3e, 0xca, 0xd5, 0x9e, 0x69, 0x88, 0x3f, 0x13, 0xb0, 0x69, 0x83, 0xbf, 0x05, 0xee, 0x65, 0x70, - 0x66, 0xda, 0xa7, 0x61, 0x04, 0x44, 0xe6, 0x10, 0xec, 0xe7, 0x77, 0x3d, 0xa8, 0xe0, 0x41, 0x47, 0xfa, 0xeb, 0x7a, - 0x56, 0xe0, 0x99, 0x7b, 0xe2, 0xf9, 0x9b, 0x13, 0xe9, 0x45, 0x0e, 0x0f, 0x34, 0xf7, 0x61, 0xc6, 0x5f, 0x96, 0x65, - 0xb8, 0x1b, 0x2d, 0xcb, 0x62, 0xe5, 0x45, 0x7a, 0x1f, 0xcf, 0xa4, 0x18, 0x48, 0x74, 0x98, 0x19, 0x5d, 0xc5, 0x3a, - 0xce, 0x61, 0xdc, 0xdb, 0x93, 0xb0, 0x42, 0xfb, 0x67, 0x89, 0xbd, 0x2e, 0x00, 0xc0, 0x21, 0x6b, 0xd0, 0x0a, 0xef, - 0x74, 0x7b, 0xbb, 0xc7, 0x25, 0x25, 0x8a, 0x1b, 0x35, 0x3f, 0xab, 0xa1, 0x65, 0x82, 0x5a, 0x66, 0xdd, 0xc9, 0x64, - 0x8a, 0x24, 0xf0, 0x6d, 0xd8, 0x1b, 0x56, 0xe4, 0xf3, 0x46, 0x6e, 0x0f, 0xef, 0xc2, 0x95, 0x88, 0xb5, 0x05, 0x9d, - 0x74, 0x64, 0x1c, 0xee, 0x85, 0xe6, 0x46, 0xba, 0x7f, 0x52, 0x25, 0x61, 0x29, 0x62, 0xb8, 0x05, 0xb2, 0xbd, 0xda, - 0x56, 0x82, 0x12, 0x48, 0x60, 0x3f, 0x94, 0x62, 0x99, 0x6e, 0x05, 0x80, 0x39, 0xf0, 0x3f, 0x25, 0x0c, 0xa1, 0xbb, - 0xf3, 0x10, 0xaf, 0x1a, 0x79, 0xdf, 0x20, 0x04, 0xfb, 0x6b, 0x90, 0xd3, 0x80, 0x41, 0xa4, 0x18, 0xc9, 0x82, 0x81, - 0x04, 0x20, 0xe7, 0x6b, 0x30, 0xc9, 0x4d, 0x73, 0xcf, 0x0f, 0x72, 0xdd, 0xc1, 0xb4, 0x0f, 0xba, 0x17, 0xd7, 0x9a, - 0xe5, 0xe0, 0x15, 0x13, 0xf1, 0xbf, 0xd7, 0x5e, 0xc9, 0x72, 0x96, 0xf9, 0x8d, 0xb9, 0xe8, 0x64, 0x70, 0xd5, 0x10, - 0x7e, 0x31, 0xcb, 0xe6, 0x3c, 0x9a, 0x65, 0x3a, 0xd4, 0xbf, 0x68, 0x8e, 0x4a, 0x01, 0x0c, 0x75, 0xbc, 0x00, 0x6b, - 0xbc, 0x2b, 0xdd, 0xb4, 0xe2, 0x91, 0xc6, 0x18, 0x05, 0x15, 0x3a, 0x08, 0xfd, 0xbd, 0x06, 0x78, 0x0d, 0x26, 0xb9, - 0x11, 0x2a, 0x1f, 0x5c, 0xd0, 0x0d, 0xdd, 0x72, 0xe5, 0x12, 0xd4, 0xa4, 0x6a, 0xf9, 0xe5, 0x08, 0xf5, 0xae, 0x96, - 0x5c, 0xaa, 0xcd, 0xa7, 0x46, 0x59, 0x23, 0xc8, 0xe4, 0x28, 0xfd, 0x3e, 0xe5, 0xc2, 0xad, 0x8c, 0xc9, 0xfa, 0x70, - 0xf0, 0x0a, 0x6e, 0x6a, 0xfc, 0x3a, 0x27, 0x16, 0x51, 0x7b, 0x48, 0x84, 0xad, 0xdd, 0x0a, 0xdd, 0x7b, 0xdc, 0x28, - 0xcd, 0xa3, 0x6c, 0x13, 0x8b, 0xca, 0xeb, 0x25, 0x60, 0x2d, 0xee, 0x01, 0x19, 0x2a, 0x2d, 0xfd, 0x8a, 0x15, 0x00, - 0x19, 0x20, 0x85, 0x8d, 0x1f, 0x90, 0xf6, 0xea, 0x83, 0x97, 0xfa, 0xfd, 0xbe, 0x31, 0xe5, 0xbf, 0x7f, 0xc8, 0x81, - 0x99, 0x50, 0x94, 0xf5, 0x0e, 0x26, 0x10, 0x5c, 0x3b, 0x49, 0x7b, 0x56, 0xf3, 0x17, 0xeb, 0xda, 0x03, 0x52, 0x2b, - 0xdf, 0x62, 0xae, 0x7a, 0x6d, 0x5f, 0x6c, 0xf6, 0x69, 0x75, 0x63, 0x34, 0x0e, 0x82, 0xa5, 0xd5, 0x5b, 0xad, 0x72, - 0xc8, 0x1b, 0x5e, 0x81, 0x48, 0x65, 0x5d, 0x5d, 0x2b, 0xe7, 0xea, 0x5a, 0x70, 0x24, 0x90, 0x2d, 0x79, 0x0e, 0xff, - 0x85, 0xdc, 0x2b, 0x0f, 0x87, 0xc2, 0xef, 0xf7, 0xd3, 0x19, 0x69, 0x65, 0x81, 0x32, 0x6d, 0x5d, 0x7b, 0xa1, 0x7f, - 0x38, 0xfc, 0x00, 0x5e, 0x23, 0xfe, 0xe1, 0x50, 0xf6, 0xfb, 0x1f, 0xcd, 0x4d, 0xe6, 0x7c, 0xac, 0x94, 0xb2, 0x97, - 0xa8, 0x74, 0x7f, 0x9b, 0xf0, 0xde, 0xff, 0x1e, 0xfd, 0xef, 0xd1, 0x65, 0x4f, 0x05, 0x80, 0x25, 0x7c, 0x86, 0x37, - 0x74, 0xa6, 0x2e, 0xe7, 0x4c, 0xba, 0xbb, 0x2b, 0x3f, 0xf4, 0x9e, 0xc6, 0x87, 0xef, 0xcd, 0x4d, 0x1b, 0x7f, 0xad, - 0x8e, 0x34, 0x09, 0x1d, 0x17, 0xfd, 0xc3, 0xe1, 0x53, 0xa2, 0xf5, 0x69, 0xa9, 0xd2, 0xa7, 0x29, 0xf0, 0x24, 0xc3, - 0x86, 0xeb, 0x16, 0xa6, 0xa3, 0xf9, 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, 0x5b, 0xe5, 0x0a, 0xde, 0xda, - 0xe3, 0xdd, 0x60, 0x44, 0xa9, 0x23, 0x7d, 0xd2, 0x86, 0xd0, 0x25, 0x95, 0xfc, 0x47, 0x91, 0xc7, 0x18, 0xb3, 0xf1, - 0x9a, 0xc8, 0x3e, 0x8b, 0xfc, 0x55, 0x01, 0x80, 0x45, 0x80, 0x80, 0x9c, 0xce, 0x1d, 0x49, 0xfc, 0xe7, 0xe4, 0xdb, - 0x3f, 0xa6, 0x4b, 0xfb, 0x50, 0x16, 0x77, 0xa5, 0xa8, 0xaa, 0xa3, 0xd2, 0x76, 0xb6, 0x5c, 0x0f, 0xf4, 0xa1, 0xfd, - 0xbe, 0xa4, 0x0f, 0x4d, 0x31, 0x14, 0x05, 0x6e, 0x8d, 0xbd, 0x69, 0xca, 0x15, 0x4d, 0xf5, 0xc8, 0x58, 0x3f, 0xbf, - 0xdf, 0xbd, 0x8d, 0xbd, 0xd4, 0x0f, 0x52, 0x10, 0x84, 0x35, 0x7e, 0x52, 0x8a, 0x24, 0x70, 0x3e, 0xc3, 0x54, 0xe2, - 0xd3, 0xa5, 0x54, 0xf9, 0xc3, 0x48, 0xf3, 0x61, 0x0a, 0x7a, 0xd9, 0x7f, 0x54, 0x30, 0xff, 0x75, 0x7b, 0xb0, 0x3e, - 0xad, 0xcb, 0x34, 0xaa, 0x88, 0x2a, 0x2f, 0x4c, 0xb5, 0x09, 0x44, 0xf0, 0x17, 0xc2, 0x22, 0xf9, 0xf5, 0xc9, 0x91, - 0xa0, 0x31, 0x93, 0xe5, 0xe3, 0x91, 0xfb, 0x85, 0x7d, 0xe5, 0x3a, 0x9e, 0xff, 0xb9, 0x99, 0xff, 0x03, 0x74, 0x86, - 0x2c, 0x5e, 0x70, 0xcb, 0x60, 0x81, 0xb3, 0x5f, 0xba, 0x7a, 0xc0, 0xdf, 0xcc, 0x13, 0x2f, 0x80, 0x83, 0xf9, 0x05, - 0xba, 0x2a, 0xa6, 0xb3, 0x62, 0x00, 0x04, 0xb6, 0x7e, 0x63, 0xcd, 0x89, 0x37, 0x16, 0xcf, 0x95, 0x5c, 0x10, 0xfa, - 0xba, 0x0a, 0xb3, 0x71, 0x55, 0x6c, 0x2a, 0x51, 0x6c, 0xea, 0x1e, 0xa9, 0x65, 0xf3, 0x69, 0x6d, 0x2b, 0x64, 0x7f, - 0x12, 0x2d, 0xda, 0x2e, 0x43, 0x35, 0x19, 0x65, 0xe9, 0x7a, 0x0a, 0xa4, 0x7a, 0x01, 0x9c, 0x45, 0xe6, 0x95, 0x2f, - 0xce, 0x1e, 0xb0, 0x45, 0xe3, 0x29, 0x30, 0xa2, 0xd2, 0x1f, 0x79, 0x63, 0x74, 0x7a, 0xa2, 0xdf, 0xcf, 0xa7, 0x14, - 0xf2, 0xf5, 0x13, 0x60, 0x72, 0xd5, 0x72, 0x01, 0xfa, 0x32, 0xd4, 0x41, 0x25, 0x4a, 0xad, 0x18, 0x46, 0x2c, 0xfc, - 0x24, 0x90, 0xbd, 0x99, 0x82, 0x9a, 0x55, 0x94, 0x84, 0x4a, 0x54, 0x4a, 0xb6, 0x26, 0xa8, 0xa5, 0xf7, 0x45, 0x51, - 0xef, 0x2b, 0x70, 0x94, 0x8c, 0xb4, 0x59, 0x4e, 0x99, 0x71, 0x51, 0xe6, 0xa2, 0x1f, 0xec, 0xdf, 0x95, 0xe7, 0x37, - 0x32, 0x9f, 0xe5, 0xbe, 0xa3, 0x73, 0xda, 0x8e, 0x0b, 0x94, 0xb9, 0xe5, 0xb4, 0xd5, 0x92, 0xc7, 0xe4, 0x3d, 0x0b, - 0xb6, 0xfd, 0x97, 0x09, 0xf2, 0x2a, 0xc2, 0x7c, 0x42, 0x95, 0xcd, 0x3f, 0x20, 0xcc, 0x16, 0x07, 0xf6, 0xd8, 0x85, - 0x89, 0x48, 0x6f, 0xc1, 0x92, 0x18, 0x66, 0xa5, 0x08, 0xe3, 0x1d, 0x78, 0xff, 0x6c, 0x2a, 0x31, 0x3a, 0x43, 0x27, - 0xf7, 0xb3, 0x87, 0xb4, 0x4e, 0xce, 0xde, 0xbe, 0x3e, 0xfb, 0xae, 0x37, 0x28, 0x46, 0x69, 0x3c, 0xe8, 0x7d, 0x77, - 0xb6, 0xda, 0x00, 0x44, 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, 0x74, 0x7b, 0x22, 0xed, 0xaa, 0x74, 0x05, 0x84, 0x1e, - 0x00, 0x27, 0x5d, 0xf9, 0xf3, 0x70, 0x10, 0x09, 0x84, 0x5a, 0x30, 0x27, 0xd3, 0x88, 0x6e, 0x48, 0xaf, 0xb0, 0xcf, - 0xc0, 0x2c, 0xa4, 0x34, 0x0f, 0x6e, 0xae, 0x16, 0x2d, 0x77, 0xc5, 0xca, 0x51, 0x58, 0xad, 0x45, 0x54, 0x23, 0xd5, - 0x31, 0x38, 0xef, 0x40, 0x04, 0x80, 0x62, 0x04, 0xcf, 0x78, 0xd4, 0xef, 0x47, 0x2a, 0x28, 0x27, 0xa1, 0x5f, 0x14, - 0xfa, 0xa5, 0x31, 0x28, 0x63, 0xfe, 0x2e, 0xd4, 0xc4, 0x00, 0xf5, 0x96, 0x87, 0x8a, 0x23, 0x00, 0x97, 0x73, 0xc4, - 0x8c, 0xf3, 0x1e, 0x77, 0xd1, 0x38, 0x15, 0xef, 0x84, 0xba, 0x0e, 0x96, 0x0a, 0x75, 0xde, 0xd4, 0x47, 0x7a, 0x4e, - 0x9a, 0x04, 0x0d, 0xe2, 0x06, 0x1e, 0xaf, 0x86, 0x80, 0x6a, 0x25, 0xa4, 0xde, 0x42, 0xa7, 0x54, 0x75, 0x08, 0xac, - 0x01, 0x2e, 0x51, 0xd8, 0x56, 0x98, 0x1c, 0xd1, 0xa6, 0x2c, 0x45, 0x7e, 0xc4, 0x06, 0xed, 0x92, 0x91, 0xa9, 0x83, - 0xcb, 0xe5, 0x72, 0x22, 0xea, 0x5f, 0xf3, 0x2d, 0x80, 0xf3, 0x42, 0x7e, 0x6b, 0x37, 0x5b, 0x26, 0xd9, 0xae, 0x2b, - 0xc3, 0x59, 0x52, 0x8a, 0x6a, 0x5d, 0xe4, 0x55, 0x7a, 0x2f, 0x7e, 0xd6, 0x0f, 0x5d, 0x02, 0x29, 0xf4, 0x23, 0xbd, - 0x6e, 0x37, 0x47, 0xaa, 0x71, 0x74, 0x39, 0xb6, 0xa7, 0xd2, 0x4e, 0xf6, 0xaa, 0xc5, 0x9b, 0x2d, 0x73, 0x25, 0x69, - 0x1c, 0x8b, 0xfc, 0x6d, 0x1e, 0xa7, 0x91, 0x95, 0x1c, 0xfe, 0x1f, 0xde, 0xbe, 0x85, 0xbb, 0x6d, 0x1b, 0x5b, 0xf7, - 0xaf, 0x58, 0xbc, 0xa9, 0x4a, 0x44, 0x90, 0x2c, 0x39, 0x49, 0x67, 0x4a, 0x19, 0xd6, 0x71, 0xf3, 0x68, 0xd3, 0x36, - 0x71, 0x1a, 0xa7, 0x9d, 0xce, 0xe8, 0xea, 0xb8, 0x34, 0x09, 0x5b, 0x6c, 0x68, 0x40, 0x25, 0x29, 0x3f, 0x22, 0xf1, - 0xbf, 0xdf, 0xb5, 0x37, 0x9e, 0xa4, 0x68, 0x27, 0x33, 0xf7, 0xdc, 0xbb, 0xb2, 0x56, 0x2c, 0x82, 0x20, 0xde, 0xd8, - 0xd8, 0xd8, 0x8f, 0x6f, 0xeb, 0x00, 0xd5, 0x2e, 0xf2, 0x95, 0x8b, 0x8d, 0xfc, 0x22, 0x2b, 0x31, 0x60, 0x70, 0xa3, - 0x51, 0xad, 0x50, 0x53, 0x26, 0xf0, 0x85, 0x7c, 0x8f, 0x11, 0xb7, 0x59, 0x99, 0x00, 0xc3, 0x8f, 0x89, 0xfa, 0x92, - 0x9e, 0x42, 0x94, 0x07, 0x15, 0x8f, 0xfb, 0x05, 0x47, 0xc4, 0x6b, 0xab, 0x32, 0x07, 0x26, 0x5b, 0xab, 0x20, 0x11, - 0xec, 0x2e, 0x9b, 0xeb, 0x45, 0xb4, 0x50, 0x77, 0xa1, 0x5e, 0xbc, 0xdd, 0xf6, 0x12, 0x45, 0x07, 0x9c, 0xfc, 0x34, - 0x78, 0x15, 0x67, 0x39, 0x4f, 0xf7, 0x2a, 0xb9, 0xa7, 0x36, 0xd4, 0x9e, 0x72, 0xe6, 0x80, 0x9d, 0xf7, 0x75, 0xb5, - 0xa7, 0xd7, 0xf4, 0x9e, 0x6e, 0xe7, 0x1e, 0x5c, 0x30, 0x70, 0xe7, 0x5e, 0x66, 0xd7, 0x5c, 0xec, 0x81, 0x32, 0xd0, - 0x1a, 0x0f, 0xd4, 0xa2, 0x1a, 0xa9, 0x89, 0xd1, 0x81, 0xab, 0x13, 0x7d, 0x30, 0x07, 0xf4, 0x7b, 0x88, 0x15, 0xde, - 0x7a, 0xbb, 0xd2, 0x07, 0x6d, 0x40, 0x7f, 0x5e, 0x9a, 0x3e, 0xe8, 0x68, 0xf1, 0x2a, 0x24, 0x70, 0x63, 0x48, 0x35, - 0x52, 0xab, 0x91, 0x55, 0xa0, 0x78, 0xc3, 0x5b, 0xbc, 0x3b, 0xd7, 0x92, 0x8d, 0xf7, 0x12, 0x81, 0xbd, 0x32, 0x51, - 0xc5, 0x99, 0x38, 0xf6, 0x52, 0x79, 0xad, 0x9d, 0x64, 0x84, 0xf1, 0x2d, 0x2b, 0xa9, 0xbf, 0x43, 0xcc, 0x2d, 0xd2, - 0x1c, 0x06, 0x2f, 0xc3, 0x8a, 0xcc, 0x78, 0xbf, 0x2f, 0x67, 0x32, 0x2a, 0x67, 0x62, 0xbf, 0x8c, 0x14, 0x42, 0xdb, - 0x7d, 0x22, 0xa0, 0x07, 0x25, 0x40, 0xbe, 0x00, 0xa8, 0x7a, 0x48, 0xf8, 0xf3, 0x90, 0xd4, 0xa7, 0x53, 0xe8, 0x53, - 0x68, 0xeb, 0x15, 0xaf, 0xa0, 0xaa, 0x6e, 0x8c, 0x6c, 0xa3, 0x82, 0x16, 0x8f, 0xe5, 0x59, 0x6d, 0x18, 0x9b, 0x53, - 0xeb, 0x5d, 0x6f, 0x36, 0x98, 0xb2, 0xb9, 0x50, 0xab, 0x30, 0x24, 0xd1, 0x4d, 0xe9, 0x85, 0x0f, 0xb1, 0x58, 0x59, - 0xad, 0xcd, 0x6f, 0x62, 0x7f, 0x64, 0x22, 0xc5, 0xfd, 0x6c, 0x89, 0x73, 0x17, 0x8f, 0xe7, 0x55, 0x5f, 0x6b, 0x69, - 0x91, 0x69, 0xf3, 0x9d, 0xbe, 0x0c, 0x69, 0x2a, 0x6a, 0x48, 0xa3, 0xce, 0x0c, 0xba, 0x6f, 0x97, 0x57, 0x54, 0x23, - 0x4c, 0x80, 0x57, 0x3a, 0x83, 0x6e, 0x34, 0x1e, 0x88, 0xa2, 0x1a, 0x15, 0x6b, 0x21, 0x10, 0x6d, 0x18, 0x72, 0xcc, - 0x2c, 0x21, 0xc9, 0x3e, 0xf1, 0xef, 0x54, 0x70, 0x85, 0x22, 0xbe, 0x31, 0x70, 0xde, 0x95, 0xf5, 0xec, 0xae, 0x23, - 0x3f, 0x27, 0x16, 0x56, 0xfb, 0x0f, 0xcd, 0xa3, 0xd6, 0x38, 0x0b, 0x68, 0x6b, 0x5a, 0xdd, 0x70, 0xb8, 0x47, 0x75, - 0x2c, 0x4a, 0x03, 0x48, 0xec, 0x91, 0xe5, 0xa2, 0x75, 0xcc, 0xa0, 0x01, 0xfd, 0x6d, 0x76, 0xb5, 0xbe, 0x42, 0xd4, - 0xb6, 0x12, 0x59, 0x27, 0xa9, 0xfc, 0x4b, 0xda, 0xa3, 0xae, 0xed, 0xa9, 0xfc, 0x6f, 0xdb, 0x54, 0x39, 0xb4, 0x40, - 0xf2, 0xd8, 0xcd, 0x59, 0xa0, 0x3a, 0x12, 0x44, 0x81, 0xda, 0x7a, 0xc1, 0xd4, 0x3b, 0x65, 0x8a, 0x0e, 0xe4, 0xe7, - 0xc2, 0x9c, 0x61, 0x5f, 0x70, 0xc4, 0x98, 0xa5, 0x12, 0x83, 0xa9, 0x8f, 0x31, 0xaa, 0x69, 0xad, 0x00, 0x5d, 0x3f, - 0xdd, 0xc0, 0x9f, 0xa8, 0xa8, 0xd1, 0x50, 0x6b, 0x24, 0x85, 0xa2, 0x89, 0x0a, 0x3a, 0x96, 0x16, 0x3a, 0x98, 0x42, - 0x27, 0x91, 0xb0, 0x04, 0x34, 0x4c, 0x88, 0x4e, 0x2a, 0xf0, 0xd6, 0x00, 0xce, 0x7c, 0x5c, 0x94, 0xeb, 0x42, 0x1b, - 0xcc, 0xfd, 0x10, 0x5f, 0xf3, 0xd7, 0x2f, 0x9c, 0x51, 0x7d, 0xcb, 0x5a, 0xdf, 0xd3, 0x82, 0xfc, 0x10, 0x72, 0x8a, - 0x0e, 0x4c, 0xec, 0x68, 0x83, 0xc6, 0x18, 0x65, 0xad, 0x43, 0x5d, 0x9c, 0xe8, 0xf8, 0x2b, 0xda, 0x04, 0xef, 0x01, - 0x4f, 0x11, 0x6d, 0x78, 0x28, 0x8c, 0x55, 0x35, 0x3e, 0x95, 0xac, 0xa5, 0x07, 0x2b, 0x78, 0xba, 0x4e, 0x78, 0x08, - 0x7a, 0x24, 0xc2, 0x8e, 0xc2, 0x62, 0x1e, 0x2f, 0xe0, 0x38, 0x29, 0x08, 0xa8, 0x1d, 0xf4, 0x15, 0x7c, 0xbe, 0x40, - 0xf7, 0x57, 0x89, 0x1e, 0x60, 0x68, 0x41, 0xdc, 0x0c, 0x7d, 0x3a, 0xba, 0x8a, 0x57, 0x0d, 0x15, 0x09, 0x9f, 0x17, - 0x60, 0x3b, 0xa4, 0xd4, 0x53, 0xa0, 0x85, 0x4a, 0x94, 0x7e, 0x18, 0xf8, 0x0e, 0x0d, 0x7c, 0xad, 0x75, 0x80, 0x86, - 0x7e, 0xc6, 0x34, 0xb5, 0xce, 0x50, 0xf9, 0xcc, 0xbb, 0x67, 0x46, 0xcb, 0x99, 0x05, 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, 0xe3, 0x50, 0x69, 0x73, 0x20, 0xbe, 0x11, 0x1a, 0xf7, 0x4f, - 0xc3, 0xd8, 0x6a, 0x8a, 0xad, 0xdd, 0xdb, 0x76, 0xfb, 0x7b, 0xe9, 0xa5, 0xd3, 0x9c, 0xf4, 0x18, 0xfb, 0xbd, 0x0c, - 0x8b, 0x91, 0xed, 0x08, 0x81, 0x25, 0xe7, 0x7d, 0xea, 0xbf, 0xa2, 0xe5, 0x3c, 0x01, 0xd3, 0x11, 0x1d, 0x21, 0x17, - 0x28, 0x3b, 0x46, 0x71, 0x07, 0x06, 0x57, 0xf4, 0xfb, 0x60, 0x95, 0x61, 0x2e, 0x24, 0x4b, 0x92, 0x32, 0x78, 0x9e, - 0x7a, 0x18, 0xf0, 0x6b, 0xa6, 0xcc, 0x5d, 0x94, 0xf5, 0xe9, 0x92, 0x4c, 0x53, 0x64, 0x20, 0xd6, 0xe1, 0x26, 0x4b, - 0xa3, 0x44, 0x89, 0xc8, 0x96, 0xe8, 0x1f, 0x69, 0x28, 0x96, 0x0e, 0xd7, 0x8b, 0x54, 0x89, 0x50, 0x31, 0x4f, 0xf1, - 0xa4, 0x4e, 0xeb, 0x74, 0x84, 0xf1, 0x26, 0x41, 0x29, 0x57, 0xc3, 0x40, 0x95, 0x54, 0x2f, 0x85, 0x4d, 0xb1, 0xdd, - 0xea, 0x8b, 0x95, 0x98, 0xc7, 0x0b, 0x7c, 0x29, 0x70, 0x14, 0x7f, 0xe2, 0x5e, 0xac, 0x29, 0xb5, 0x3d, 0xa8, 0x1d, - 0x51, 0x42, 0x7f, 0xe2, 0x70, 0x91, 0xf8, 0x4e, 0xea, 0xb8, 0x7f, 0x68, 0x11, 0x72, 0xa6, 0x0e, 0x52, 0xc3, 0x0d, - 0xed, 0x08, 0xff, 0x0d, 0xd7, 0x67, 0x9c, 0xd1, 0x9b, 0x6a, 0x46, 0x8d, 0xdf, 0xeb, 0xe1, 0x19, 0xa3, 0x3e, 0x1b, - 0x38, 0xac, 0x10, 0x85, 0x36, 0xec, 0xa8, 0x54, 0xa2, 0x85, 0xa1, 0x54, 0x7f, 0x09, 0x15, 0x47, 0xdc, 0x99, 0x51, - 0x96, 0x8c, 0x4f, 0xcb, 0x43, 0x31, 0x1d, 0x0c, 0x4a, 0x52, 0x19, 0x0b, 0x3d, 0xb8, 0x1e, 0x78, 0xfe, 0x3d, 0x70, - 0x0b, 0xf1, 0xe0, 0x90, 0xc5, 0x90, 0x1b, 0x70, 0xfc, 0x16, 0x27, 0x57, 0x8d, 0x4a, 0x15, 0xbc, 0x9a, 0xa8, 0x16, - 0xfc, 0x54, 0x86, 0x01, 0xfa, 0x24, 0x05, 0x60, 0x32, 0x98, 0xf2, 0x5b, 0x90, 0x28, 0x9d, 0xa9, 0x1b, 0xd2, 0xaf, - 0xa2, 0xe0, 0x17, 0xbc, 0xe0, 0x22, 0x71, 0x05, 0x58, 0xde, 0xc1, 0xf6, 0x3a, 0xaa, 0xa8, 0x02, 0xe2, 0x35, 0x3d, - 0x8e, 0xb8, 0xf1, 0xfe, 0x33, 0x3d, 0xb6, 0x40, 0xad, 0xd6, 0xb1, 0xc1, 0x67, 0x8e, 0xc1, 0x05, 0x5d, 0x4b, 0x6c, - 0x0d, 0xd5, 0xb0, 0x22, 0x30, 0x70, 0x01, 0x07, 0x61, 0x89, 0xe2, 0xd8, 0x4a, 0x5e, 0x91, 0x86, 0x94, 0xf6, 0x81, - 0xe1, 0x68, 0x93, 0x1c, 0xdf, 0x66, 0xd9, 0x4d, 0xe0, 0x7c, 0xd1, 0x39, 0x69, 0x26, 0x96, 0x0d, 0xde, 0xe7, 0xcd, - 0xf9, 0x75, 0xff, 0x90, 0x50, 0x15, 0xec, 0x86, 0xb7, 0x83, 0xdd, 0x38, 0xe1, 0xd7, 0x5c, 0x2c, 0x74, 0x7c, 0x16, - 0x73, 0xc9, 0xf2, 0x5b, 0xeb, 0xdd, 0x92, 0xa4, 0x56, 0x40, 0xfb, 0x2c, 0x0b, 0x6a, 0x22, 0x00, 0xdd, 0x0f, 0x7f, - 0x81, 0xd0, 0x19, 0xfe, 0xf6, 0x18, 0x5c, 0x91, 0xc2, 0x7b, 0x87, 0x40, 0x58, 0xd3, 0xcd, 0x9d, 0xda, 0x80, 0x2f, - 0xc6, 0xfd, 0x19, 0x53, 0x4f, 0xbf, 0xcd, 0xe4, 0xae, 0xae, 0xdb, 0x23, 0xcb, 0xf0, 0x11, 0xae, 0x14, 0x00, 0xcb, - 0x84, 0xbf, 0x18, 0x5b, 0x52, 0x7d, 0x02, 0x70, 0x6a, 0x3a, 0xa2, 0x4f, 0x10, 0x18, 0x38, 0x25, 0x5a, 0x8c, 0xae, - 0x95, 0x23, 0x9a, 0x41, 0x5a, 0xd3, 0xad, 0x30, 0xde, 0x7a, 0xd0, 0x42, 0xcf, 0x34, 0x9c, 0xf8, 0x0f, 0x9a, 0x79, - 0x55, 0x40, 0x00, 0xad, 0x8c, 0xe0, 0xad, 0xf5, 0xd1, 0x1c, 0x21, 0x3e, 0x61, 0x49, 0x34, 0x61, 0xf1, 0x4c, 0xf1, - 0x63, 0x42, 0x37, 0x4d, 0x6d, 0xd3, 0x07, 0xa4, 0xbf, 0xb8, 0x66, 0xfd, 0x94, 0x65, 0xed, 0xdb, 0x43, 0xc5, 0x8b, - 0x69, 0x33, 0xf8, 0x61, 0xa2, 0x8a, 0xf1, 0xbf, 0xa8, 0x7c, 0xa9, 0x15, 0xc0, 0x30, 0x77, 0xd5, 0xd3, 0xef, 0x37, - 0xb3, 0xe5, 0x40, 0xa8, 0xfc, 0xce, 0x20, 0xe9, 0xd3, 0xf1, 0xfc, 0xc0, 0x26, 0x51, 0x5b, 0xe8, 0xf9, 0xe3, 0x52, - 0x37, 0xa1, 0xf2, 0xda, 0xd4, 0x88, 0x56, 0xc8, 0x50, 0xd9, 0x3a, 0x60, 0x7d, 0xff, 0x10, 0xee, 0x2e, 0x6a, 0x1a, - 0x6a, 0xdd, 0x73, 0xd7, 0xa2, 0xe0, 0xc4, 0x1f, 0x60, 0x2c, 0x2e, 0x24, 0xb5, 0x0e, 0xc2, 0xa4, 0x1f, 0x2d, 0x4e, - 0x72, 0xa3, 0xae, 0x4e, 0xce, 0x14, 0xf3, 0x04, 0x2e, 0xaa, 0x65, 0xdb, 0x5f, 0x51, 0xa9, 0x4b, 0xb9, 0xbd, 0xa2, - 0x34, 0x3d, 0xa4, 0xed, 0x55, 0x9c, 0xb7, 0x05, 0x17, 0xfc, 0x0b, 0x05, 0x17, 0xd6, 0xc1, 0xba, 0xe3, 0x4e, 0xd9, - 0x13, 0x9e, 0x28, 0xd3, 0xda, 0xe0, 0xae, 0x1b, 0x8c, 0x89, 0xb1, 0xdf, 0x5d, 0xf2, 0xe4, 0x23, 0xb2, 0xe0, 0xdf, - 0x65, 0x02, 0x3c, 0x93, 0xdd, 0x2b, 0x95, 0xff, 0x07, 0xff, 0x6a, 0x6b, 0xdf, 0x59, 0xf3, 0x4f, 0xcf, 0x7a, 0xb8, - 0x73, 0x98, 0xfc, 0x00, 0x9d, 0x01, 0xdd, 0x5c, 0xc9, 0x94, 0x03, 0x32, 0x80, 0xb5, 0x48, 0x46, 0x03, 0x3e, 0xb4, - 0xb2, 0x6c, 0xfb, 0x4e, 0xab, 0x0b, 0xc2, 0xbd, 0x04, 0x6e, 0x7a, 0x7f, 0x6d, 0x66, 0xe6, 0x74, 0xad, 0x44, 0xd3, - 0xa5, 0xb1, 0xb5, 0x2c, 0x55, 0xc0, 0xee, 0xf7, 0x9e, 0x64, 0xd3, 0xfc, 0x70, 0x39, 0xcd, 0x2d, 0x75, 0xdb, 0xb8, - 0x65, 0x03, 0x40, 0x88, 0x5d, 0x6b, 0x2b, 0x07, 0x90, 0xdc, 0x1e, 0x84, 0xf0, 0xb5, 0x22, 0xf4, 0x54, 0x89, 0xd0, - 0xa7, 0x69, 0xb3, 0x0f, 0x76, 0x55, 0xad, 0x1b, 0x71, 0x8e, 0x06, 0xa9, 0x66, 0xe4, 0x4f, 0xae, 0x79, 0x71, 0x91, - 0xcb, 0x1b, 0xc0, 0x40, 0x26, 0xb5, 0x51, 0x58, 0x5e, 0x81, 0x3b, 0x3f, 0x3a, 0x8e, 0x33, 0x31, 0xca, 0x31, 0x58, - 0x2b, 0xc2, 0x23, 0xeb, 0xc4, 0x19, 0x80, 0x20, 0xfb, 0x93, 0xa6, 0xe3, 0xb9, 0x16, 0x18, 0xd3, 0x17, 0xb8, 0xab, - 0x9c, 0x1d, 0x6d, 0x72, 0xbb, 0xe8, 0x9b, 0x33, 0xac, 0x3b, 0x52, 0x5a, 0x1b, 0x8b, 0xae, 0x3b, 0x58, 0x6b, 0x06, - 0x6d, 0x11, 0x4a, 0x3e, 0xe4, 0x4e, 0xda, 0x4f, 0x01, 0x0d, 0xce, 0xb2, 0xf4, 0xd6, 0x5a, 0xe5, 0x6f, 0xb4, 0x10, - 0x27, 0x8a, 0xa9, 0x13, 0xdf, 0x44, 0x89, 0x3e, 0x3f, 0x13, 0xe3, 0x06, 0x02, 0xa9, 0x3f, 0x60, 0x50, 0x8d, 0x22, - 0x4c, 0xe0, 0x3a, 0x10, 0xc5, 0xf6, 0x44, 0x6d, 0x2c, 0x47, 0xd0, 0x09, 0x21, 0xde, 0x41, 0x19, 0xc6, 0xea, 0xe2, - 0x40, 0x1b, 0x2c, 0x7d, 0xdd, 0x5a, 0xe7, 0x86, 0x50, 0x18, 0x27, 0x30, 0xc5, 0x20, 0xa9, 0xb3, 0xce, 0x32, 0x41, - 0x95, 0x1d, 0x93, 0xce, 0xfb, 0x00, 0xdd, 0x5d, 0x8b, 0xa6, 0xf8, 0xba, 0x73, 0x07, 0xdd, 0xc7, 0xf5, 0x6b, 0x2d, - 0x72, 0x83, 0x3f, 0x6f, 0x89, 0xb0, 0x08, 0x9c, 0xb5, 0x26, 0x5f, 0x35, 0xc2, 0x81, 0x29, 0xc9, 0x34, 0xec, 0x25, - 0xca, 0xa6, 0x7b, 0xbb, 0xed, 0xf5, 0xee, 0x15, 0x71, 0xf5, 0x18, 0xab, 0xbc, 0x9b, 0xb9, 0xbd, 0x53, 0xad, 0xc5, - 0xee, 0x4d, 0xdb, 0x4f, 0xb1, 0xa3, 0xd6, 0xda, 0xed, 0x86, 0x13, 0x6a, 0xc8, 0xb7, 0xa2, 0x4a, 0xab, 0xd3, 0x8d, - 0x41, 0x3b, 0xc4, 0xb3, 0x16, 0x19, 0xdc, 0x28, 0x5f, 0x38, 0xa1, 0x93, 0x8a, 0xb3, 0xea, 0xd4, 0x05, 0x9b, 0x2b, - 0x5e, 0x2d, 0x65, 0x1a, 0x09, 0x8a, 0x36, 0xe7, 0x51, 0x49, 0x13, 0xb9, 0x16, 0x55, 0x24, 0x6b, 0xd4, 0x8b, 0x5a, - 0x8d, 0x01, 0x02, 0x32, 0x9d, 0x35, 0x3d, 0xa8, 0x82, 0xd9, 0x50, 0x46, 0x72, 0xfa, 0x1e, 0x2c, 0xed, 0x91, 0x63, - 0xad, 0xef, 0xab, 0xb3, 0xc5, 0xb7, 0x7a, 0x42, 0x30, 0x85, 0xd9, 0x03, 0x61, 0xe0, 0x9a, 0xc6, 0x90, 0xd3, 0x2e, - 0x71, 0x59, 0xd3, 0x2d, 0xe1, 0x1e, 0x6e, 0x57, 0xb2, 0x23, 0x37, 0x4f, 0x9a, 0x9b, 0x2b, 0xd8, 0x51, 0x31, 0x1f, - 0x83, 0xf6, 0x4b, 0xaa, 0x6b, 0x97, 0xe6, 0xd6, 0xe3, 0x41, 0x40, 0x83, 0x41, 0x61, 0xf8, 0xd7, 0x89, 0xf1, 0xf0, - 0xa4, 0x01, 0x41, 0x52, 0x2e, 0xc2, 0xb1, 0x6f, 0x44, 0x3f, 0x99, 0xca, 0x43, 0x8e, 0x16, 0xef, 0xd0, 0xea, 0x04, - 0xa2, 0x78, 0x89, 0x50, 0x12, 0xa3, 0x2a, 0x34, 0x22, 0x28, 0x4f, 0xcb, 0x5f, 0xaa, 0xea, 0x10, 0x50, 0x48, 0xfb, - 0x8a, 0x42, 0xd9, 0x26, 0x31, 0x34, 0xc3, 0x2f, 0xe7, 0x93, 0x85, 0x9e, 0x81, 0x81, 0x9c, 0x1f, 0x2c, 0xf4, 0x2c, - 0x0c, 0xe4, 0xfc, 0xc9, 0xa2, 0x76, 0xeb, 0x40, 0x13, 0x10, 0xcf, 0x85, 0xa3, 0x93, 0xd2, 0xaa, 0x6c, 0x01, 0xdd, - 0x3c, 0x44, 0xd0, 0x7f, 0xb2, 0x87, 0xa0, 0x93, 0x0b, 0xed, 0xc8, 0x0d, 0x68, 0x3b, 0x0e, 0x81, 0xbd, 0x62, 0x52, - 0x61, 0x02, 0x10, 0x1d, 0xb2, 0x31, 0x18, 0x62, 0xab, 0x0f, 0x0e, 0xd9, 0x78, 0xea, 0x93, 0x20, 0x60, 0x74, 0x7f, - 0x30, 0x90, 0xe0, 0xb7, 0x78, 0x95, 0x3e, 0xda, 0x08, 0x74, 0xd3, 0x77, 0x77, 0x43, 0xef, 0xe2, 0x0a, 0x4e, 0xd5, - 0xee, 0x9e, 0x84, 0x6e, 0x32, 0xed, 0x00, 0xbd, 0x86, 0xb8, 0x21, 0xbf, 0x32, 0x1a, 0x8d, 0x6c, 0x4a, 0x48, 0x88, - 0xe1, 0x1c, 0x9a, 0x39, 0x2d, 0x97, 0xaf, 0x6e, 0x3d, 0x1b, 0x90, 0x61, 0xa6, 0xb7, 0x4c, 0xd6, 0x0f, 0x50, 0x56, - 0x3d, 0x86, 0x76, 0xe8, 0x3d, 0x72, 0xfc, 0xf0, 0xe0, 0x9b, 0x8c, 0x9f, 0x39, 0x5c, 0x7b, 0x38, 0x17, 0xbe, 0xcb, - 0x9a, 0x91, 0x39, 0x74, 0x9e, 0x7d, 0x1c, 0xef, 0x61, 0x9c, 0x7c, 0x9e, 0x85, 0xf2, 0xc6, 0x6b, 0xfa, 0x1f, 0x95, - 0xde, 0xec, 0x70, 0xc8, 0xe9, 0x0a, 0x56, 0xdc, 0xac, 0x0a, 0x0d, 0x3f, 0x8b, 0xbc, 0x71, 0xc4, 0x6b, 0x12, 0x55, - 0xdd, 0xe7, 0xbd, 0x0d, 0x53, 0xda, 0x31, 0x0e, 0x00, 0x4e, 0xd4, 0xaa, 0x61, 0x57, 0x1a, 0xd7, 0xea, 0x20, 0x86, - 0xa1, 0x84, 0xad, 0x12, 0x47, 0x42, 0xf9, 0x1b, 0x80, 0xb0, 0x18, 0x8a, 0xe3, 0xad, 0x61, 0x7d, 0x80, 0xfd, 0xd0, - 0x05, 0x9a, 0xe6, 0x94, 0x6a, 0x06, 0x00, 0x49, 0xc0, 0x1f, 0x3d, 0xdd, 0x34, 0x54, 0xb6, 0x79, 0x1e, 0x5a, 0x56, - 0x57, 0xf0, 0x40, 0x4f, 0x5d, 0xc9, 0xc0, 0xb8, 0xaa, 0x63, 0x6f, 0x73, 0x7f, 0x7b, 0xb4, 0x8a, 0x7c, 0x67, 0x93, - 0xda, 0x66, 0x55, 0x68, 0xec, 0xe3, 0x09, 0x3d, 0x9d, 0x00, 0xad, 0xd7, 0x96, 0x8a, 0xf6, 0xfb, 0x28, 0x46, 0x8d, - 0x0b, 0x05, 0x56, 0x61, 0x22, 0xc1, 0x21, 0xc2, 0x08, 0xa1, 0xdf, 0x97, 0xe1, 0xc6, 0x17, 0x64, 0x10, 0x0d, 0xd7, - 0xa2, 0xe3, 0x0f, 0x39, 0x5e, 0xb4, 0x2d, 0x55, 0x35, 0x27, 0x4d, 0x5b, 0x02, 0x6f, 0xc2, 0x01, 0xb6, 0xf3, 0x4f, - 0x1b, 0x22, 0x57, 0xe1, 0xa2, 0x84, 0xef, 0x88, 0x6b, 0x41, 0x74, 0x53, 0x9b, 0x7a, 0x1b, 0x76, 0x88, 0x8e, 0xa6, - 0x78, 0x74, 0xc8, 0x3d, 0x77, 0xcf, 0x6d, 0x11, 0xdf, 0x7c, 0x86, 0xdc, 0x35, 0x9d, 0xbd, 0x14, 0x61, 0x50, 0xb7, - 0x6c, 0xa0, 0x58, 0x87, 0x4e, 0x50, 0x80, 0x51, 0x5b, 0x3e, 0x01, 0x1d, 0x1b, 0x0c, 0x2a, 0x82, 0x4f, 0x0a, 0xdb, - 0xa6, 0x41, 0xfe, 0x88, 0x77, 0x43, 0x87, 0xd7, 0x96, 0x3c, 0x10, 0xaf, 0xb0, 0xcf, 0x94, 0x70, 0xff, 0x82, 0x82, - 0xee, 0x28, 0x2f, 0x57, 0x85, 0xab, 0xd2, 0x00, 0x54, 0xd9, 0xf1, 0x5c, 0x6b, 0x4a, 0x5a, 0xc0, 0x4a, 0x49, 0xdd, - 0xf9, 0x4d, 0x44, 0xdc, 0x92, 0xa9, 0x98, 0xad, 0xba, 0x51, 0xe5, 0xa1, 0x44, 0x91, 0x8e, 0x3d, 0xdb, 0x39, 0x58, - 0x03, 0xe0, 0x29, 0x6c, 0x2f, 0xce, 0xb0, 0xa0, 0x8c, 0xcb, 0x96, 0xb9, 0x04, 0x8a, 0xfa, 0x61, 0x9c, 0x97, 0x1d, - 0x5f, 0xee, 0x8e, 0xb6, 0xf7, 0xd0, 0x1b, 0xb1, 0x31, 0x5e, 0x5f, 0x46, 0x4d, 0xbf, 0x78, 0x86, 0x2b, 0x4b, 0x41, - 0x1e, 0x68, 0xaa, 0x47, 0x18, 0x1d, 0x02, 0xd3, 0x94, 0x1f, 0xb1, 0xf1, 0x74, 0x38, 0x34, 0x64, 0xd0, 0x6b, 0x26, - 0xc6, 0xff, 0xfa, 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, 0x58, 0x12, 0xa3, 0x10, 0xbf, 0x38, - 0x55, 0xb6, 0x13, 0x42, 0x05, 0xc4, 0x43, 0xd7, 0xba, 0x71, 0x24, 0x55, 0xec, 0x49, 0xa1, 0xf1, 0xd4, 0x70, 0xdf, - 0x0b, 0x1d, 0xb3, 0x0e, 0xb3, 0xb8, 0xcd, 0x1a, 0x49, 0x8d, 0x71, 0x2a, 0x4c, 0x70, 0x4a, 0xb9, 0x8a, 0x04, 0x46, - 0xc7, 0xb3, 0x85, 0x41, 0x54, 0x49, 0x4c, 0x32, 0xb6, 0x16, 0xc2, 0xc4, 0xae, 0x73, 0x85, 0x69, 0xea, 0x22, 0xf5, - 0x9b, 0x81, 0xc9, 0x82, 0x86, 0xfc, 0x1e, 0x8d, 0xd6, 0x54, 0x4d, 0x01, 0x86, 0x71, 0x94, 0x6a, 0xfc, 0x5b, 0x84, - 0xda, 0x0c, 0x03, 0x00, 0xdb, 0xbc, 0x93, 0x99, 0xa8, 0x5e, 0x0b, 0x84, 0x40, 0x73, 0xf6, 0x53, 0x45, 0xb5, 0x33, - 0x0b, 0x46, 0xd1, 0x6e, 0xaf, 0x7c, 0x3e, 0x70, 0x42, 0x79, 0xac, 0x2e, 0x50, 0xaf, 0x64, 0xf1, 0x46, 0xa6, 0xbc, - 0x15, 0x17, 0x73, 0x4f, 0xb2, 0x0f, 0xf9, 0x08, 0xce, 0x2b, 0x74, 0x2a, 0x37, 0xdb, 0x44, 0x99, 0x25, 0x49, 0xc6, - 0x02, 0x63, 0xf3, 0x12, 0xcc, 0xa4, 0x66, 0xc6, 0xf0, 0x6b, 0x08, 0x2e, 0xb6, 0x73, 0x12, 0x6e, 0xee, 0xe7, 0x81, - 0x21, 0x34, 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, 0xe1, 0xce, 0x7f, 0x50, 0x58, - 0x83, 0xca, 0x88, 0xcb, 0x88, 0xf2, 0xcc, 0x81, 0x6e, 0x9a, 0x14, 0x71, 0x7a, 0xb6, 0x8a, 0x8b, 0x92, 0xa7, 0x50, - 0xa9, 0xa6, 0x6e, 0x51, 0x6f, 0x02, 0xf6, 0x86, 0x48, 0x92, 0xac, 0xa5, 0xb1, 0x15, 0xbb, 0x34, 0x48, 0xcf, 0xbd, - 0x61, 0x96, 0x5e, 0x55, 0x68, 0x48, 0x4b, 0xbd, 0xb3, 0x50, 0xc9, 0xfc, 0x15, 0xff, 0x19, 0xd4, 0x0a, 0x74, 0xb4, - 0x49, 0x31, 0x9e, 0x03, 0x23, 0xbe, 0x1b, 0xc1, 0xea, 0x01, 0xe2, 0xa2, 0x09, 0x4a, 0xbd, 0x23, 0x76, 0xfc, 0xdc, - 0xe4, 0xe1, 0x5d, 0xc8, 0x39, 0x83, 0x4f, 0x1f, 0x66, 0x89, 0x5a, 0xeb, 0x48, 0x8c, 0xd4, 0x0c, 0xa0, 0xe9, 0xa0, - 0xcc, 0x79, 0x2c, 0x82, 0x59, 0xcf, 0x24, 0x46, 0x3d, 0xae, 0x7f, 0x81, 0x86, 0xda, 0x6f, 0x56, 0x96, 0x67, 0xd5, - 0xdd, 0x97, 0x70, 0x60, 0x53, 0x5b, 0x41, 0x8f, 0xd7, 0x95, 0xbc, 0xbc, 0x54, 0xdd, 0xf6, 0x0b, 0x31, 0x72, 0xba, - 0xc6, 0xb5, 0x74, 0x5e, 0x2d, 0x58, 0xaf, 0x3b, 0xdd, 0x2c, 0xee, 0x66, 0x19, 0x0d, 0x84, 0xb5, 0x9d, 0x4f, 0x34, - 0x7f, 0xd6, 0x6c, 0xbb, 0x8f, 0xb7, 0x20, 0x66, 0x01, 0x00, 0xa4, 0x07, 0x51, 0xb0, 0xcc, 0x52, 0x1e, 0x50, 0x79, - 0x1f, 0x47, 0x59, 0x28, 0xbd, 0x9c, 0x65, 0xfc, 0xb4, 0x69, 0xac, 0x75, 0x56, 0x28, 0x43, 0x6b, 0xa3, 0x3b, 0x5d, - 0x65, 0x88, 0xed, 0x27, 0x71, 0xb6, 0x00, 0xf7, 0xc7, 0x0c, 0x85, 0x86, 0xce, 0x32, 0xd2, 0x44, 0xc3, 0x77, 0xdd, - 0x33, 0xc8, 0x28, 0x4e, 0xd6, 0x79, 0x25, 0xdd, 0xe8, 0xb3, 0x36, 0x12, 0xe6, 0x1e, 0xa2, 0x5f, 0xc5, 0xe0, 0x51, - 0xee, 0xf3, 0xda, 0xe8, 0x64, 0x5a, 0x46, 0xda, 0x9d, 0x9f, 0xd4, 0xcb, 0x2c, 0xd5, 0x3a, 0x6c, 0x9f, 0x61, 0x6f, - 0x8d, 0x49, 0x6f, 0x42, 0x6a, 0x18, 0x89, 0xcf, 0x67, 0xd4, 0x08, 0x01, 0x6d, 0x39, 0xfe, 0x0e, 0x9f, 0x61, 0x68, - 0x0a, 0x2c, 0x55, 0xdc, 0xc2, 0x6e, 0xf8, 0x9a, 0x4f, 0x56, 0x2d, 0x00, 0x11, 0xac, 0x7c, 0xbd, 0x8b, 0x57, 0x42, - 0x7d, 0xa6, 0xcd, 0x00, 0x90, 0x05, 0xa5, 0xdc, 0xf1, 0x53, 0x2a, 0x1d, 0x2c, 0x51, 0xb4, 0xbd, 0x9c, 0xbe, 0xd1, - 0xb1, 0xf1, 0x43, 0x7a, 0x2e, 0x60, 0xbb, 0x90, 0xdf, 0xba, 0x57, 0x2f, 0x51, 0x91, 0xda, 0x36, 0xeb, 0x01, 0xbe, - 0xdc, 0xa0, 0x49, 0x18, 0x41, 0x99, 0x32, 0x05, 0x30, 0xb8, 0xa9, 0x46, 0xc1, 0xa4, 0xd5, 0x48, 0xd8, 0x52, 0x4f, - 0xb2, 0xdc, 0xf4, 0xc1, 0xa9, 0xee, 0x11, 0xf4, 0x68, 0x87, 0x93, 0x96, 0xfd, 0x5a, 0xc1, 0xd1, 0xc9, 0xd5, 0x10, - 0x35, 0xf3, 0x5e, 0xdb, 0x91, 0x21, 0xe5, 0x32, 0x0c, 0x04, 0x53, 0x8e, 0x79, 0x7a, 0x6c, 0x3d, 0x23, 0xa2, 0x07, - 0xce, 0x3e, 0xd3, 0xad, 0xba, 0x92, 0x80, 0xe8, 0xf8, 0xcd, 0xd3, 0xd7, 0x57, 0xf1, 0xa5, 0x41, 0x51, 0x6a, 0x58, - 0xc4, 0x28, 0xd3, 0xbe, 0x4a, 0xc2, 0xe0, 0xfd, 0xfa, 0xfe, 0x67, 0x95, 0xa5, 0xf6, 0x7b, 0xb0, 0xb1, 0xa2, 0xaa, - 0x5f, 0x4b, 0x5e, 0x34, 0x05, 0x58, 0xf7, 0x59, 0xa2, 0x40, 0xee, 0xf7, 0x36, 0xcd, 0x7c, 0x13, 0x35, 0x6e, 0x36, - 0xac, 0x37, 0xae, 0xdb, 0xa5, 0xb6, 0x64, 0x47, 0x56, 0x22, 0x67, 0x16, 0x83, 0x19, 0x3f, 0x2a, 0x0c, 0x4a, 0xc3, - 0x06, 0x55, 0xa9, 0xf8, 0xbd, 0x11, 0xc1, 0xa9, 0x63, 0x55, 0x61, 0x4c, 0x03, 0x66, 0x5b, 0x51, 0x6b, 0x50, 0x07, - 0xa5, 0xb4, 0x35, 0x51, 0xd8, 0x7e, 0x67, 0x05, 0x35, 0xbf, 0xff, 0x69, 0x0c, 0xf9, 0x9a, 0x52, 0x50, 0x49, 0xc0, - 0xce, 0xa0, 0xd1, 0x53, 0x25, 0x0c, 0xa4, 0x20, 0x78, 0x02, 0x94, 0x2f, 0xa2, 0xc6, 0x6a, 0xb7, 0xaf, 0x4e, 0x8d, - 0xd1, 0x16, 0x10, 0x5a, 0x48, 0x8f, 0x2e, 0xfb, 0xb8, 0x8d, 0x75, 0x20, 0xf1, 0xe0, 0x04, 0xdb, 0xb9, 0xba, 0x46, - 0x23, 0xa1, 0xf9, 0x43, 0xa3, 0x01, 0xaf, 0x69, 0x05, 0x0a, 0xf5, 0x1c, 0x47, 0x43, 0x67, 0x87, 0x14, 0x44, 0x6c, - 0xd0, 0xc2, 0xbe, 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, 0x82, 0x61, 0x0b, 0xbf, - 0x39, 0x35, 0x05, 0x60, 0xc3, 0x63, 0x5d, 0x96, 0x6f, 0xd4, 0x44, 0x66, 0x71, 0x48, 0x22, 0x90, 0x6c, 0x37, 0x37, - 0xb7, 0x11, 0x6c, 0x7b, 0x0b, 0xb5, 0xa1, 0xfe, 0xf2, 0xb6, 0xfb, 0x3d, 0xc3, 0xcb, 0x3d, 0xb9, 0x77, 0xd3, 0x86, - 0xf2, 0x87, 0xfb, 0x57, 0xc9, 0xff, 0x55, 0x25, 0xf7, 0x5b, 0x65, 0xd6, 0x6d, 0xf1, 0x7e, 0xd7, 0x71, 0xcb, 0x31, - 0x1a, 0x04, 0xd6, 0x14, 0x18, 0x48, 0x4f, 0x1a, 0xd3, 0x44, 0x87, 0x54, 0x66, 0xcc, 0xe0, 0xd1, 0x05, 0x68, 0x0e, - 0xd3, 0x79, 0x1e, 0x03, 0x70, 0x80, 0x7f, 0xe4, 0x11, 0xea, 0x9f, 0xce, 0xf3, 0xe0, 0x2c, 0x18, 0x94, 0x83, 0x40, - 0x7f, 0xe2, 0x9a, 0x13, 0x2c, 0x40, 0xe7, 0x16, 0x33, 0x08, 0x36, 0x69, 0xcd, 0x1c, 0xe2, 0xc3, 0x64, 0x3a, 0x18, - 0xc4, 0x64, 0x03, 0x20, 0x7d, 0xf1, 0xc2, 0x3a, 0x07, 0x15, 0x7a, 0x41, 0xb6, 0xea, 0x2e, 0x9a, 0x15, 0x7b, 0xd5, - 0x4e, 0xf3, 0x7e, 0x3f, 0x9f, 0x97, 0x83, 0xa0, 0x51, 0x61, 0x61, 0xbc, 0xff, 0x68, 0xf3, 0x4b, 0xa3, 0x93, 0x26, - 0x18, 0xa6, 0xf6, 0x18, 0xd5, 0x2b, 0x9e, 0x66, 0xb4, 0x71, 0x3b, 0x56, 0xca, 0x17, 0x10, 0xc5, 0x03, 0x43, 0xd6, - 0xca, 0xbb, 0x73, 0xf0, 0xba, 0xdc, 0x78, 0x73, 0x44, 0x01, 0x76, 0x53, 0x18, 0x27, 0x35, 0x17, 0x5d, 0xd4, 0xc4, - 0x33, 0xd8, 0xe9, 0xea, 0xad, 0x44, 0xab, 0xf1, 0x5e, 0xbc, 0x6b, 0x36, 0xfe, 0x56, 0xee, 0xe9, 0x32, 0xf7, 0x2e, - 0x00, 0x71, 0x76, 0x2f, 0xae, 0xf6, 0xb0, 0xd4, 0xbd, 0x60, 0x60, 0x91, 0x43, 0xda, 0xd5, 0xea, 0xa1, 0x88, 0xd4, - 0x79, 0x0c, 0x06, 0x4c, 0xa6, 0x21, 0x35, 0x99, 0xf6, 0x0a, 0x05, 0x69, 0x63, 0xad, 0x05, 0xb4, 0xe1, 0xb0, 0xd8, - 0xb1, 0x1b, 0x76, 0xa7, 0x5b, 0x87, 0x42, 0x09, 0xa3, 0x57, 0xd7, 0xcd, 0x43, 0xad, 0xe1, 0x89, 0xa0, 0x07, 0xd5, - 0x68, 0x3f, 0x3d, 0x94, 0x27, 0xed, 0xb1, 0x00, 0x17, 0x3d, 0x7c, 0xf9, 0x52, 0xe0, 0x45, 0x7b, 0x07, 0x79, 0xce, - 0x7c, 0xaa, 0x7c, 0x10, 0x1b, 0x6e, 0x19, 0x3e, 0xb4, 0x8f, 0x6f, 0x05, 0x32, 0xa9, 0x3b, 0x9a, 0xda, 0xda, 0x1d, - 0x8d, 0x63, 0x02, 0xfd, 0xa6, 0x1c, 0xa5, 0x4c, 0x4c, 0x2d, 0x4b, 0x76, 0xd4, 0xcb, 0x95, 0x37, 0x54, 0xca, 0x8e, - 0x96, 0x6d, 0xce, 0x2f, 0x6d, 0x24, 0xf4, 0xfb, 0xda, 0x1d, 0x08, 0xdf, 0xa8, 0xf5, 0x86, 0xbc, 0x6c, 0x88, 0x58, - 0x0e, 0x31, 0x03, 0xc7, 0x0b, 0xa9, 0x5c, 0xbb, 0x8b, 0xa6, 0xaa, 0x6e, 0x67, 0x2b, 0x17, 0xb4, 0xc4, 0x5b, 0x29, - 0xb0, 0x8a, 0xd4, 0xe9, 0xf5, 0x54, 0xe2, 0x7d, 0x1f, 0xc5, 0xf6, 0x23, 0x60, 0x1b, 0x1b, 0x47, 0x63, 0xe3, 0x16, - 0xb1, 0xc1, 0x57, 0x51, 0x45, 0x0b, 0x0e, 0x10, 0xdc, 0x6d, 0x49, 0x2d, 0xcd, 0x1c, 0xe2, 0xbe, 0xe2, 0x01, 0xda, - 0x77, 0x71, 0xc4, 0xa9, 0x00, 0xdb, 0xba, 0xd6, 0x39, 0xab, 0xe5, 0x80, 0xcd, 0x44, 0xcf, 0x3f, 0xad, 0x1a, 0x89, - 0x18, 0x56, 0xd9, 0x48, 0x59, 0xa1, 0x3d, 0x28, 0x5d, 0xc2, 0xc5, 0x17, 0xe0, 0x65, 0xfb, 0x7e, 0x65, 0xf7, 0xd9, - 0x12, 0xfb, 0x87, 0x79, 0xd5, 0x04, 0x8f, 0xbc, 0xc6, 0xdb, 0x7b, 0x98, 0xf8, 0x52, 0x29, 0x84, 0x57, 0x29, 0x0d, - 0x25, 0x00, 0x83, 0x24, 0xa8, 0xe1, 0x4a, 0xdb, 0x66, 0x90, 0xca, 0x18, 0x76, 0xb7, 0x7a, 0xab, 0xff, 0xd3, 0x2a, - 0x5c, 0x54, 0xb2, 0x18, 0x93, 0x40, 0xe7, 0x54, 0xcb, 0x4d, 0x4c, 0xc1, 0xb3, 0x5d, 0x72, 0x04, 0x0a, 0x3b, 0x01, - 0xdc, 0x50, 0xc2, 0x7e, 0xc5, 0xdb, 0x50, 0xce, 0x5e, 0x59, 0xc9, 0x93, 0xdb, 0x97, 0x54, 0xd0, 0x84, 0x4c, 0x85, - 0xdd, 0xbf, 0xad, 0x0d, 0xfb, 0x22, 0x94, 0x23, 0x29, 0x70, 0x71, 0xd0, 0x39, 0x80, 0xfd, 0x41, 0x2e, 0x63, 0xf3, - 0x99, 0xf4, 0xfb, 0xea, 0xfd, 0xf3, 0x3c, 0x4b, 0x3e, 0xee, 0xbc, 0x37, 0x3c, 0xcd, 0x92, 0x01, 0x95, 0x88, 0xa9, - 0x75, 0x55, 0x0c, 0x97, 0xda, 0xc5, 0xb8, 0x41, 0x32, 0xe2, 0x7b, 0xa9, 0x43, 0x8c, 0x18, 0x5f, 0x64, 0x87, 0xa4, - 0xe4, 0x74, 0x59, 0x77, 0xf6, 0x5c, 0x8b, 0x66, 0xd0, 0x18, 0x6e, 0xc7, 0x7b, 0x49, 0xaf, 0x00, 0x15, 0x15, 0xba, - 0x67, 0x81, 0x6b, 0x78, 0x73, 0x49, 0x34, 0xb6, 0xf4, 0xb4, 0x25, 0x1a, 0xb8, 0x57, 0x26, 0x24, 0xd5, 0xc6, 0x01, - 0x16, 0xb1, 0xae, 0x3f, 0x86, 0x12, 0x80, 0x5a, 0x0d, 0xd2, 0x2b, 0x7d, 0x45, 0xa8, 0x4a, 0x42, 0x30, 0x3a, 0x91, - 0xf0, 0x32, 0xa0, 0x71, 0x66, 0x12, 0x2d, 0x6c, 0x70, 0x40, 0x5f, 0x54, 0x26, 0xd1, 0xd8, 0x90, 0x07, 0xb4, 0xb2, - 0x69, 0x00, 0x83, 0x0f, 0x92, 0x24, 0xfa, 0x7a, 0x69, 0x92, 0x40, 0x50, 0x82, 0xf2, 0x0d, 0xfa, 0x4b, 0xe9, 0xf9, - 0x58, 0xfe, 0xcb, 0x3b, 0x94, 0x7e, 0x08, 0x25, 0xc8, 0x14, 0x75, 0xc5, 0x34, 0x63, 0x47, 0x59, 0xb7, 0x31, 0x89, - 0xe7, 0x69, 0x77, 0x5b, 0x28, 0x97, 0x2e, 0xf0, 0x2b, 0xcb, 0x10, 0xc7, 0xfa, 0x79, 0xbc, 0x62, 0xc7, 0x21, 0xd7, - 0x78, 0xe9, 0xcf, 0xe3, 0x15, 0xce, 0x10, 0xad, 0x5a, 0x09, 0x44, 0xf9, 0xaf, 0xda, 0xc0, 0x21, 0xee, 0x13, 0x0c, - 0x72, 0x51, 0x79, 0x0f, 0x04, 0xf2, 0xb6, 0x82, 0x88, 0x34, 0xb3, 0xeb, 0x30, 0x22, 0xd5, 0x4e, 0x92, 0xf9, 0xf2, - 0x47, 0x99, 0x09, 0xef, 0x1b, 0x78, 0x6c, 0x36, 0xcb, 0xa6, 0x98, 0x2f, 0x54, 0x30, 0x07, 0xf7, 0x89, 0x8a, 0x4b, - 0x51, 0xf9, 0x4f, 0xd8, 0x05, 0x2f, 0xc6, 0x83, 0xd7, 0x6b, 0x04, 0xd8, 0xaf, 0xfc, 0x27, 0x6f, 0xcc, 0xde, 0x5a, - 0x37, 0xbe, 0xcc, 0x44, 0x7c, 0xe0, 0xa3, 0x5b, 0xca, 0x47, 0x77, 0x5e, 0xa6, 0x3f, 0x1b, 0x50, 0x22, 0xa3, 0xb2, - 0xe2, 0xab, 0x15, 0x4f, 0x67, 0xb7, 0x49, 0x94, 0x8d, 0x2a, 0x2e, 0x60, 0x7a, 0xc1, 0xf1, 0x2e, 0x59, 0x9f, 0x67, - 0xc9, 0x6b, 0x88, 0x3d, 0xb0, 0x92, 0x0a, 0x8b, 0x1f, 0x96, 0x99, 0x5a, 0xcc, 0x42, 0x56, 0x52, 0xf0, 0x60, 0x76, - 0x9d, 0x44, 0x6f, 0x97, 0x1e, 0x92, 0x9a, 0x99, 0xb2, 0x4d, 0xed, 0x08, 0xb5, 0xf1, 0x75, 0xa4, 0x1b, 0x6d, 0x01, - 0x00, 0xf7, 0x6c, 0x91, 0x46, 0x92, 0x89, 0xe1, 0xa4, 0x66, 0xdc, 0xa4, 0x17, 0x98, 0x1a, 0xd7, 0xac, 0xa2, 0x89, - 0xb3, 0x90, 0x01, 0xbd, 0x3f, 0xe0, 0xe5, 0xe0, 0x73, 0x06, 0xf7, 0x1f, 0xb4, 0x06, 0x2e, 0x0f, 0x8b, 0x7e, 0x5f, - 0x1e, 0x16, 0xdb, 0x6d, 0x79, 0x14, 0xf7, 0xfb, 0xf2, 0x28, 0x36, 0xfc, 0x83, 0x52, 0x6c, 0x1b, 0x73, 0x83, 0x84, - 0xe6, 0x12, 0xa2, 0x16, 0x8d, 0xe0, 0x0f, 0xcd, 0x72, 0x2e, 0xa2, 0xfc, 0x30, 0xe9, 0xf7, 0x7b, 0xcb, 0x99, 0x18, - 0xe4, 0xc3, 0x24, 0xca, 0x87, 0x89, 0xe7, 0x84, 0xf8, 0x9b, 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, 0x5d, 0x84, 0x25, - 0x96, 0x42, 0x97, 0xec, 0xcf, 0x25, 0xf0, 0x44, 0x39, 0xaf, 0x36, 0xc0, 0xc0, 0x46, 0x78, 0xe7, 0x30, 0xe1, 0x24, - 0xd6, 0x35, 0xa0, 0x9d, 0x6e, 0x6a, 0x7a, 0x41, 0x57, 0xf4, 0x12, 0xf9, 0xd9, 0x0b, 0x30, 0x58, 0x3a, 0x64, 0xf9, - 0x74, 0x30, 0xb8, 0x20, 0x2b, 0x56, 0xce, 0xc3, 0x78, 0x10, 0xae, 0x67, 0xf9, 0xf0, 0x22, 0xba, 0x20, 0xe4, 0xab, - 0x62, 0x41, 0x7b, 0xab, 0x51, 0xf9, 0x31, 0x83, 0xe0, 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, 0x86, 0xe8, - 0xb6, 0xc7, 0x49, 0x02, 0x8e, 0xc9, 0xae, 0xf8, 0x68, 0xac, 0x0a, 0xef, 0xfa, 0x8e, 0xd0, 0x5e, 0x2f, 0x71, 0x83, - 0xf4, 0x5d, 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, 0xde, 0xc0, 0x81, 0x3d, 0x08, 0xf3, 0x59, 0x3c, 0x7c, 0x13, 0xbd, - 0x21, 0xe4, 0x2b, 0x49, 0xaf, 0xd5, 0xa5, 0x0c, 0xc2, 0x20, 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, 0xdd, 0x11, 0xb0, 0xf0, 0x1a, 0x4f, 0xd7, 0x87, - 0x2c, 0x9e, 0x0e, 0x06, 0x6b, 0xa4, 0xea, 0x2a, 0xf7, 0x9a, 0x2c, 0xe8, 0x05, 0x4e, 0x04, 0x01, 0x86, 0x3e, 0x13, - 0x6b, 0x43, 0xc3, 0xdf, 0x30, 0xf8, 0xf8, 0x8e, 0x5d, 0x8c, 0xee, 0xe8, 0x2d, 0x7b, 0xb3, 0x1d, 0x4f, 0x81, 0x99, - 0x5a, 0xcd, 0xc2, 0xbb, 0xc3, 0xcb, 0xd9, 0x25, 0xbb, 0x8b, 0xee, 0x8e, 0xa0, 0xa1, 0x57, 0xec, 0x0e, 0x01, 0x97, - 0xd2, 0xc7, 0xcb, 0xc1, 0x1b, 0xb2, 0x3f, 0x18, 0xa4, 0x24, 0x0a, 0xaf, 0x43, 0xaf, 0x95, 0x6f, 0xe8, 0x1d, 0xa1, - 0x2b, 0x76, 0x8b, 0xa3, 0x71, 0xc9, 0xf0, 0x83, 0x73, 0x76, 0x57, 0x5f, 0x87, 0xde, 0x6e, 0x4e, 0x44, 0x27, 0x88, - 0x11, 0xfa, 0x1a, 0x38, 0x9a, 0xe5, 0xc2, 0x4c, 0xc0, 0x93, 0xb9, 0xc8, 0x68, 0x51, 0x68, 0x06, 0xe2, 0xac, 0x04, - 0xc4, 0x92, 0xa8, 0xfb, 0xcd, 0x46, 0x67, 0xb0, 0x9c, 0xfb, 0xfd, 0x5e, 0x65, 0xe8, 0x01, 0x22, 0x67, 0x76, 0xd2, - 0x83, 0x9e, 0x4f, 0x0f, 0xf0, 0x13, 0xbd, 0x6a, 0x10, 0x27, 0xf3, 0xbb, 0x65, 0xf4, 0x9b, 0x47, 0x1f, 0x7e, 0xe8, - 0xa6, 0x3c, 0x22, 0xff, 0xf7, 0x29, 0x4f, 0x99, 0x47, 0x6f, 0x2a, 0x0f, 0x04, 0xcf, 0x5b, 0x93, 0x4a, 0x23, 0x51, - 0x8d, 0xce, 0x56, 0x31, 0x68, 0x23, 0x51, 0xdb, 0xa0, 0x9f, 0xd0, 0xc2, 0x0a, 0x22, 0xe4, 0x1c, 0xbc, 0x00, 0x83, - 0x54, 0x08, 0x95, 0xa3, 0x16, 0x25, 0x1a, 0x82, 0xe4, 0xb2, 0xe4, 0x2a, 0x7c, 0x0e, 0xa1, 0xea, 0xf4, 0x71, 0x26, - 0xc2, 0x86, 0x1e, 0x87, 0x3e, 0x00, 0xfc, 0xaf, 0x3b, 0xe4, 0xa2, 0xe4, 0x97, 0x78, 0x36, 0xb7, 0x09, 0x46, 0xc1, - 0x12, 0xd1, 0x0c, 0x6d, 0x83, 0xd8, 0x8f, 0x25, 0xc1, 0x7a, 0x24, 0x8d, 0x47, 0xa5, 0x39, 0x22, 0xfc, 0x28, 0x3e, - 0x8a, 0x9e, 0xc6, 0x86, 0x44, 0x72, 0x24, 0x91, 0x7c, 0x00, 0x84, 0x93, 0xa0, 0xbf, 0xb8, 0x6b, 0xb2, 0x6b, 0x21, - 0x31, 0xe8, 0x4f, 0x4b, 0xa6, 0x65, 0xf7, 0xaa, 0xc7, 0xbe, 0x22, 0xc8, 0x1d, 0xd3, 0x7f, 0x79, 0x7d, 0xf8, 0xe7, - 0x12, 0x67, 0xd0, 0x7a, 0xbe, 0xa8, 0xce, 0xcc, 0xbc, 0xc1, 0x8d, 0xbc, 0x2e, 0x6b, 0xd7, 0xe5, 0x0b, 0xbe, 0xc7, - 0x6f, 0x2b, 0x2e, 0xd2, 0x72, 0xef, 0x97, 0xaa, 0x8d, 0xe7, 0x54, 0xae, 0x57, 0x2e, 0xce, 0x8a, 0x32, 0x4e, 0xf5, - 0xa4, 0x2e, 0xc6, 0x1a, 0xb6, 0xe1, 0xf7, 0x88, 0xba, 0x92, 0x96, 0xa3, 0xa7, 0x94, 0xab, 0x66, 0xca, 0xc5, 0x3a, - 0xcf, 0x7f, 0xde, 0x49, 0xc5, 0x29, 0x6e, 0xa6, 0x20, 0x55, 0x6a, 0xb9, 0x80, 0xea, 0x39, 0x6a, 0xb9, 0x5b, 0x9a, - 0x1d, 0xe0, 0xdc, 0x36, 0xd5, 0xc7, 0xca, 0xec, 0xc2, 0x4b, 0x6e, 0xdc, 0x9f, 0x4c, 0x19, 0x16, 0x8c, 0x42, 0x9b, - 0x55, 0x57, 0xda, 0xbe, 0xd0, 0x3a, 0x0d, 0xc3, 0x95, 0x1f, 0x2f, 0x20, 0x5d, 0xc0, 0x38, 0x5e, 0x94, 0x4c, 0x8c, - 0xdb, 0xa3, 0xb7, 0x82, 0xf8, 0x92, 0xad, 0x40, 0xc0, 0x5c, 0xc3, 0xdb, 0x75, 0x1d, 0x6d, 0xf7, 0xc4, 0x29, 0xa3, - 0x72, 0x15, 0x8b, 0xef, 0xe3, 0x95, 0x81, 0x4c, 0x56, 0xc7, 0x63, 0x63, 0x4c, 0xa7, 0x3f, 0x25, 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, 0x9e, 0x31, 0x57, 0x08, 0x56, 0xaa, 0xec, 0xf6, - 0x9d, 0x1a, 0x53, 0x31, 0x83, 0x29, 0xb6, 0x9d, 0xc5, 0xa4, 0x5b, 0xf9, 0xa7, 0x9d, 0xfb, 0x65, 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, 0x59, 0x49, 0xbe, 0x2b, 0x8d, 0xb9, 0xf4, - 0xa9, 0xd2, 0xc4, 0x70, 0xb2, 0x18, 0x71, 0x91, 0x2e, 0xea, 0xcc, 0xae, 0x85, 0xcf, 0x78, 0x19, 0xce, 0xf9, 0xc2, - 0xe8, 0xa6, 0x74, 0xe9, 0x05, 0x8b, 0x75, 0xa7, 0x37, 0x2b, 0x8d, 0x95, 0x12, 0x71, 0x6b, 0x96, 0x09, 0x94, 0xa5, - 0xac, 0x95, 0xf0, 0xa6, 0x68, 0xd9, 0x4a, 0x1a, 0x79, 0xcf, 0x1c, 0xdc, 0xc7, 0x7e, 0x40, 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, 0x26, 0x56, 0x0a, 0xd8, 0x0b, 0xbc, 0xbc, 0xe1, 0x99, 0xaa, 0x69, 0xd9, 0xa5, 0xe2, 0x00, 0xe3, 0xf3, - 0x32, 0x0c, 0xcb, 0xe1, 0x05, 0x58, 0x4b, 0xec, 0x87, 0xab, 0x39, 0x5f, 0xa8, 0xdf, 0x10, 0x70, 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, 0x9e, 0xaa, 0x99, 0x69, 0xc9, 0x7f, 0x12, 0xb5, 0xa1, 0x89, - 0xbe, 0xc1, 0x2a, 0xf2, 0x87, 0xc7, 0x47, 0x97, 0x40, 0xc6, 0xce, 0xae, 0x64, 0xe6, 0x43, 0xdf, 0x47, 0x06, 0xf7, - 0xdc, 0x94, 0x33, 0xae, 0x82, 0x44, 0x19, 0xb8, 0x7b, 0x35, 0x4b, 0xc6, 0x5a, 0x84, 0xef, 0x1e, 0x15, 0x45, 0x9f, - 0x49, 0xd3, 0x80, 0xee, 0x23, 0xc1, 0x1c, 0xe8, 0xbd, 0x42, 0x87, 0xcb, 0x6a, 0x9b, 0x09, 0xf8, 0x8b, 0x04, 0xf9, - 0xad, 0xd0, 0xab, 0x1a, 0x83, 0x2a, 0xda, 0x45, 0x2c, 0xfd, 0xfb, 0x88, 0x1f, 0x65, 0xf3, 0x2f, 0x73, 0x8f, 0x57, - 0x12, 0x06, 0x3f, 0xa4, 0x66, 0x93, 0xcc, 0xdb, 0x2b, 0xf6, 0x3d, 0x74, 0xd4, 0xa3, 0xd6, 0x78, 0x5f, 0xbd, 0xe0, - 0x14, 0x62, 0x94, 0x50, 0x74, 0x12, 0x0c, 0xe0, 0x76, 0x09, 0x29, 0xee, 0x06, 0xbb, 0x69, 0x5e, 0xf3, 0xa2, 0xe0, - 0x7c, 0x5d, 0x55, 0x81, 0x1f, 0xd0, 0x70, 0xbe, 0xd8, 0x0d, 0x61, 0x38, 0xa6, 0xad, 0x6b, 0x18, 0x84, 0x19, 0xc3, - 0x48, 0x08, 0x5e, 0xff, 0xa2, 0x27, 0x34, 0x89, 0x57, 0xdf, 0xf1, 0x4f, 0x19, 0x2f, 0x14, 0x91, 0x06, 0x11, 0x52, - 0x37, 0xf1, 0x8d, 0x4c, 0x93, 0x02, 0x0a, 0x01, 0x46, 0x01, 0x95, 0xd8, 0xd0, 0x54, 0xfc, 0xad, 0x16, 0x1f, 0xfc, - 0xd4, 0x74, 0x3c, 0x1a, 0xd7, 0xad, 0xce, 0xa8, 0xa0, 0x33, 0xd0, 0xa3, 0x56, 0xd4, 0xd3, 0xa0, 0x95, 0x60, 0x1a, - 0x69, 0xde, 0xba, 0x87, 0xc0, 0x2b, 0xd3, 0xe2, 0x9d, 0x07, 0x74, 0x73, 0xe6, 0x83, 0x27, 0x8f, 0xe9, 0x99, 0x43, - 0x4f, 0xae, 0xd8, 0x51, 0xd5, 0x43, 0xed, 0xbd, 0x19, 0xa1, 0xa0, 0xdf, 0xc7, 0x14, 0xe8, 0x46, 0x50, 0x7b, 0x57, - 0xf7, 0x1f, 0xcb, 0x5d, 0x0e, 0xdf, 0x71, 0x96, 0x1b, 0xc0, 0x52, 0x91, 0xb5, 0x02, 0x8f, 0x02, 0xd4, 0xa5, 0x32, - 0x84, 0x2d, 0xe6, 0x70, 0xa8, 0xec, 0x56, 0xad, 0x86, 0x92, 0x1c, 0x96, 0x23, 0x70, 0x08, 0x5d, 0x97, 0x83, 0x72, - 0xb4, 0xcc, 0xaa, 0xf7, 0xf8, 0x5b, 0xb3, 0x0e, 0x49, 0x76, 0x1f, 0xeb, 0xc0, 0x2d, 0xeb, 0x30, 0xfd, 0x68, 0x90, - 0x02, 0xd0, 0x64, 0x23, 0x70, 0x09, 0xc0, 0x7b, 0xfb, 0x8f, 0x08, 0xb5, 0x32, 0xbd, 0x97, 0xb1, 0x50, 0xdf, 0x37, - 0x92, 0xa0, 0x84, 0x66, 0x42, 0xe5, 0x58, 0x0a, 0xde, 0x79, 0xa4, 0x73, 0x52, 0x67, 0xe2, 0x3d, 0x88, 0xd3, 0xc2, - 0x07, 0xf6, 0x16, 0x04, 0xe7, 0x2c, 0xe8, 0x1d, 0xde, 0x66, 0xb5, 0xd4, 0x46, 0x0f, 0x14, 0xc0, 0xef, 0x06, 0x77, - 0x08, 0xf2, 0xd5, 0x18, 0xae, 0x95, 0xbc, 0x09, 0xf9, 0xb0, 0xa0, 0x07, 0x64, 0x60, 0x9f, 0xc5, 0x30, 0xa6, 0x07, - 0xe4, 0xd0, 0x3e, 0x4b, 0x37, 0x80, 0x03, 0xa9, 0x47, 0x95, 0x1e, 0x40, 0x83, 0x7e, 0xb7, 0x2d, 0xb2, 0x24, 0xeb, - 0xc7, 0xd2, 0x28, 0x62, 0xa0, 0x4a, 0x10, 0x51, 0x8b, 0x7f, 0x3e, 0x98, 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, 0xbd, 0xc9, 0xe0, 0xc0, 0xc8, 0xf0, - 0xa5, 0xb7, 0x7f, 0xe1, 0x6b, 0x2d, 0xdd, 0x13, 0x83, 0x92, 0x3c, 0x3e, 0x50, 0xf4, 0xef, 0x5e, 0x59, 0xf9, 0xd4, - 0x4e, 0xff, 0x76, 0x6b, 0xd6, 0xe7, 0xe1, 0x68, 0xb2, 0xdd, 0xf6, 0xb4, 0x81, 0x2b, 0xd5, 0x2a, 0x04, 0xec, 0x42, - 0x49, 0xf6, 0x0f, 0x20, 0x2a, 0x42, 0x33, 0xee, 0x66, 0xd9, 0x90, 0xc8, 0xf8, 0x71, 0x3a, 0xcb, 0x86, 0x60, 0x87, - 0x7b, 0x51, 0x89, 0xcb, 0x51, 0x6b, 0x83, 0xd3, 0xb3, 0x24, 0x84, 0x50, 0x0e, 0x58, 0xd9, 0xad, 0xfa, 0x73, 0xa7, - 0xcc, 0x84, 0xd4, 0x64, 0x75, 0x3b, 0xa5, 0x7b, 0x98, 0xe6, 0x7b, 0x66, 0x04, 0x07, 0xdc, 0xdb, 0x5f, 0xf5, 0xc7, - 0x30, 0xc9, 0x34, 0x39, 0x45, 0xf2, 0x8b, 0xf4, 0x14, 0x92, 0x76, 0xe8, 0xa9, 0x22, 0x80, 0x13, 0x6a, 0x3f, 0x86, - 0xdf, 0x30, 0xee, 0xdf, 0x35, 0x5f, 0xbb, 0xa9, 0x88, 0x9e, 0x52, 0x2c, 0x53, 0x93, 0xd3, 0x24, 0x2b, 0x12, 0x88, - 0xda, 0xa8, 0x9a, 0x11, 0x3d, 0x71, 0x31, 0x1f, 0x15, 0xe1, 0xf3, 0x6a, 0xfd, 0x9f, 0x21, 0x7c, 0x46, 0xe1, 0x06, - 0x70, 0x79, 0xc5, 0xe5, 0x79, 0xf8, 0xec, 0x29, 0xdd, 0x9b, 0x7c, 0x73, 0x40, 0xf7, 0x0e, 0x9e, 0x3c, 0x23, 0x00, - 0x8b, 0x76, 0x79, 0x1e, 0x1e, 0x3c, 0x7b, 0x46, 0xf7, 0xbe, 0xfd, 0x96, 0xee, 0x4d, 0x9e, 0x1c, 0x34, 0xd2, 0x26, - 0xcf, 0xbe, 0xa5, 0x7b, 0xdf, 0x3c, 0x6d, 0xa4, 0x1d, 0x8c, 0x9f, 0xd1, 0xbd, 0xbf, 0x7f, 0x63, 0xd2, 0xfe, 0x06, - 0xd9, 0xbe, 0x3d, 0xc0, 0xff, 0x4c, 0xda, 0xe4, 0xd9, 0x13, 0xba, 0x37, 0x19, 0x43, 0x25, 0xcf, 0x5c, 0x25, 0xe3, - 0x09, 0x7c, 0xfc, 0x04, 0xfe, 0xfb, 0x1b, 0x09, 0x16, 0xb4, 0x92, 0x2c, 0x17, 0xa8, 0x3f, 0x43, 0x11, 0x27, 0xaa, - 0x26, 0x12, 0x1e, 0x62, 0x66, 0xf5, 0x4d, 0x1c, 0x06, 0xc4, 0xa5, 0x43, 0x41, 0x74, 0x6f, 0x3c, 0x7a, 0x46, 0x02, - 0x1f, 0x9e, 0xee, 0xc6, 0x07, 0x19, 0xcb, 0xc5, 0x3c, 0xfb, 0x2a, 0x37, 0xb1, 0x15, 0x3c, 0x00, 0xab, 0x8f, 0x7e, - 0xae, 0x4a, 0xce, 0xb3, 0xaf, 0x2a, 0xb9, 0x9b, 0xeb, 0xf7, 0x16, 0xa0, 0xbc, 0xbf, 0x6a, 0xd9, 0x4d, 0xa1, 0x42, - 0xa7, 0xb5, 0x46, 0x9f, 0x7d, 0xc4, 0xf4, 0xc1, 0xc0, 0xbb, 0x61, 0xff, 0xb4, 0x53, 0x4e, 0xeb, 0x1b, 0x8d, 0x42, - 0x8d, 0xca, 0x43, 0xc2, 0x8e, 0xa0, 0xe8, 0xc1, 0x00, 0x78, 0x02, 0x0f, 0xf7, 0xed, 0xdf, 0x2c, 0xe3, 0x63, 0x47, - 0x19, 0xbf, 0xa0, 0x0c, 0x01, 0x8d, 0x7a, 0x98, 0xdd, 0xf4, 0xb0, 0xd1, 0xad, 0x5e, 0xb2, 0x54, 0x27, 0x53, 0xd3, - 0x33, 0xd8, 0xd7, 0xba, 0x96, 0x7b, 0x46, 0x14, 0x2d, 0x2f, 0xf6, 0x52, 0x3e, 0xab, 0xd8, 0x4f, 0x4b, 0x54, 0x6f, - 0x45, 0x8d, 0x37, 0x32, 0x9b, 0x55, 0xec, 0x7b, 0xf3, 0x06, 0xb8, 0x19, 0xf6, 0xbb, 0x7a, 0xf2, 0x03, 0x67, 0x70, - 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, 0x5c, 0xd9, 0xff, 0x6a, 0xc8, 0x4b, 0x50, 0xb8, 0xd5, 0x2c, 0x6f, - 0xa7, 0x30, 0x84, 0x10, 0xfc, 0x71, 0xc9, 0x00, 0x70, 0x20, 0xc0, 0x60, 0xac, 0x65, 0x40, 0xcd, 0x96, 0x8f, 0x36, - 0x5c, 0xa9, 0x27, 0x81, 0x33, 0xb8, 0x90, 0x45, 0xc2, 0x4f, 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, 0xb0, 0x05, 0x91, 0x21, - 0x78, 0xb8, 0xfd, 0x6b, 0xa9, 0x02, 0x47, 0xf5, 0xfb, 0x5c, 0xfa, 0x6e, 0x4f, 0xc6, 0x8e, 0x1c, 0xa7, 0x7e, 0x2a, - 0x1c, 0xfc, 0x37, 0xa9, 0x6b, 0x63, 0xb9, 0x92, 0x32, 0xcb, 0xb2, 0xb0, 0xa3, 0x50, 0xcb, 0x3d, 0x2a, 0x0f, 0x92, - 0x2f, 0xe4, 0x10, 0xc9, 0x02, 0xa3, 0x50, 0x90, 0xe1, 0x84, 0x8a, 0xd1, 0x5a, 0x94, 0xcb, 0xec, 0xa2, 0x0a, 0x37, - 0x4a, 0xa1, 0xcc, 0x29, 0xfa, 0x76, 0x83, 0x03, 0x09, 0x89, 0xb2, 0xf2, 0x6d, 0xfc, 0x36, 0x44, 0xb0, 0x3a, 0xae, - 0x6d, 0xa1, 0xb8, 0xb7, 0x3f, 0x79, 0xda, 0xc5, 0x1f, 0x19, 0x17, 0x50, 0x17, 0x8b, 0x69, 0x38, 0xb1, 0xb1, 0x6f, - 0xdc, 0x17, 0x56, 0xd3, 0x03, 0x50, 0xdf, 0xa5, 0x12, 0x23, 0xa8, 0xaf, 0x8c, 0x7d, 0x6c, 0x8f, 0x31, 0x39, 0x83, - 0x58, 0xc3, 0x2a, 0x67, 0xa6, 0xfa, 0x46, 0xd8, 0x11, 0x00, 0x37, 0x42, 0x6b, 0x14, 0x04, 0x1e, 0xaf, 0x42, 0x3c, - 0x2f, 0x55, 0xf8, 0xd6, 0x8c, 0xd0, 0x31, 0x78, 0x53, 0xd9, 0x46, 0x66, 0xd2, 0x17, 0x0c, 0x9a, 0x63, 0x5b, 0x47, - 0x61, 0xb5, 0x95, 0x65, 0x47, 0x00, 0x37, 0x90, 0x1d, 0x9a, 0x8b, 0xe7, 0xac, 0x9a, 0x67, 0x8b, 0xc8, 0x04, 0x05, - 0x5c, 0x0a, 0xcb, 0xa0, 0x7d, 0xba, 0x47, 0xb6, 0xe3, 0x10, 0xba, 0xe1, 0x3e, 0x82, 0xf1, 0xb4, 0x9b, 0x82, 0x15, - 0x44, 0x23, 0xc4, 0xc3, 0x8c, 0x59, 0x7c, 0xaf, 0x34, 0xe5, 0xa9, 0x6a, 0x09, 0x04, 0x8e, 0x42, 0xa8, 0x8b, 0x5d, - 0xa3, 0x04, 0x97, 0xa9, 0x11, 0xcc, 0x60, 0xc7, 0x8e, 0xd4, 0x76, 0xc9, 0x39, 0x1d, 0xaa, 0x29, 0x2d, 0xf5, 0x94, - 0x6a, 0x5f, 0x43, 0x31, 0x2f, 0xd1, 0x43, 0x0f, 0x5c, 0x0f, 0xb4, 0x43, 0x5e, 0x49, 0x27, 0x26, 0x82, 0x4e, 0xab, - 0x4d, 0xd8, 0xb9, 0x91, 0x6e, 0x59, 0x8d, 0xbc, 0x63, 0x68, 0x76, 0xc4, 0x4b, 0x3f, 0x50, 0x17, 0x40, 0x84, 0xdc, - 0xdb, 0x22, 0x73, 0x44, 0xb3, 0xac, 0x7c, 0x05, 0x65, 0x71, 0xc4, 0xd6, 0x15, 0x70, 0x2d, 0x05, 0x93, 0x4b, 0x1e, - 0xf1, 0x14, 0x11, 0x01, 0x8f, 0x95, 0x76, 0x7d, 0xa7, 0x25, 0x84, 0x66, 0x29, 0x10, 0x37, 0x17, 0xc5, 0xb9, 0xb6, - 0x81, 0x2c, 0x80, 0xbe, 0xfd, 0x9c, 0x5d, 0x79, 0xe1, 0x60, 0x37, 0x57, 0x99, 0x78, 0xc1, 0x2f, 0x32, 0xc1, 0x53, - 0x04, 0xbb, 0xba, 0x35, 0x0f, 0xdc, 0xb1, 0x6d, 0x60, 0xf9, 0xf6, 0x1d, 0x2c, 0x98, 0x32, 0xd4, 0x4a, 0x89, 0x4c, - 0x44, 0x02, 0x32, 0xfb, 0xcc, 0xdd, 0x9b, 0x4c, 0xbc, 0x89, 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, 0x0e, 0xbf, 0xc4, 0x50, 0x2b, 0xe3, 0x7e, 0x1f, 0x24, 0x66, 0xd2, 0x36, 0x65, 0x26, 0x23, 0xa9, 0xd1, 0x42, - 0x2a, 0xca, 0x07, 0x13, 0xb2, 0xbb, 0x52, 0x2d, 0x23, 0x6a, 0xbf, 0x0a, 0xc5, 0x6c, 0x1c, 0x4d, 0x08, 0x9d, 0x74, - 0xac, 0x77, 0xd3, 0x5a, 0xc8, 0x34, 0x7a, 0x16, 0x79, 0x3e, 0x9d, 0x05, 0xab, 0xa6, 0xc5, 0x21, 0xe3, 0xd3, 0x62, - 0x30, 0x20, 0xda, 0xa5, 0x70, 0x83, 0xf5, 0x80, 0x29, 0x8d, 0x8b, 0xb7, 0x66, 0x5a, 0xfd, 0x4a, 0xaa, 0x90, 0xf4, - 0x9e, 0x01, 0x49, 0x26, 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, 0xde, 0xc6, 0x6f, 0x23, 0x7b, 0x59, 0xd0, 0x45, 0xbe, 0x40, 0x21, 0x6b, 0x1e, 0x86, 0xd5, 0xb0, 0x3d, - 0x88, 0x64, 0xbf, 0x3d, 0x09, 0x8d, 0xc6, 0xc0, 0x02, 0xd9, 0xa1, 0x11, 0xb8, 0x08, 0xad, 0xfc, 0xed, 0x10, 0x5c, - 0xb8, 0x2c, 0x22, 0xcb, 0x50, 0xc7, 0x6f, 0x6a, 0x37, 0x41, 0xf5, 0x0a, 0x9d, 0xa6, 0xb0, 0x2a, 0x65, 0x92, 0x0f, - 0xbf, 0x5e, 0xc9, 0x02, 0x33, 0x79, 0x5d, 0xf6, 0xe8, 0x6b, 0xbb, 0xbd, 0x03, 0x53, 0xb0, 0xee, 0x93, 0xf7, 0xf5, - 0xe3, 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, 0xa3, 0x4c, - 0xd6, 0xfe, 0xd5, 0x5d, 0xa4, 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, 0x86, 0x85, 0x57, 0xc3, - 0x4b, 0xb2, 0x1f, 0xa6, 0x83, 0x89, 0x12, 0x8c, 0xdd, 0xb1, 0x65, 0x19, 0xaa, 0xc4, 0xd5, 0xfe, 0x05, 0x79, 0x7c, - 0x41, 0x6f, 0xe9, 0x0d, 0x3d, 0xa5, 0x27, 0x40, 0xf8, 0xef, 0x0e, 0x27, 0x7c, 0x38, 0x79, 0xda, 0xef, 0xf7, 0xce, - 0xfb, 0xfd, 0xde, 0x99, 0x31, 0xa0, 0xd0, 0xbb, 0xe8, 0xb2, 0xa6, 0xfa, 0xd7, 0x55, 0xbd, 0x98, 0x9e, 0xa8, 0x8d, - 0x9b, 0xf0, 0x2c, 0x0f, 0xaf, 0xf6, 0xef, 0xc8, 0x10, 0x1f, 0x2f, 0x72, 0x29, 0x8b, 0xf0, 0x72, 0xff, 0x8e, 0xd0, - 0x93, 0x23, 0xd0, 0x9b, 0x62, 0x7d, 0x27, 0x8f, 0xef, 0x74, 0x6d, 0x84, 0xbe, 0x0c, 0x13, 0xd8, 0x26, 0xb7, 0xcc, - 0xde, 0xb5, 0x27, 0x63, 0x88, 0x65, 0x72, 0xe7, 0x95, 0x77, 0xf7, 0xf8, 0x96, 0xec, 0xdf, 0x82, 0xa7, 0xa8, 0x25, - 0x7f, 0xb3, 0xf0, 0x86, 0xb5, 0x6a, 0x78, 0x7c, 0x47, 0x4f, 0x5b, 0x8d, 0x78, 0x7c, 0x47, 0xa2, 0xf0, 0x86, 0x5d, - 0xd2, 0x53, 0x76, 0x45, 0xe8, 0x79, 0xbf, 0x7f, 0xd6, 0xef, 0xcb, 0x7e, 0xff, 0xa7, 0x38, 0x0c, 0xe3, 0x61, 0x41, - 0xf6, 0x25, 0xbd, 0xdb, 0x9f, 0xf0, 0x27, 0x64, 0x16, 0xea, 0xe6, 0xab, 0x05, 0x67, 0x55, 0xde, 0x2a, 0xd7, 0x1d, - 0x05, 0x6b, 0x85, 0x3b, 0xa6, 0x9e, 0x4e, 0xe8, 0x0d, 0x2b, 0xe8, 0x29, 0x8b, 0x49, 0x74, 0x0d, 0xad, 0x38, 0x9f, - 0x15, 0xd1, 0x0d, 0x3d, 0x65, 0x67, 0xb3, 0x38, 0x3a, 0xa5, 0x27, 0x2c, 0x1f, 0x4e, 0x20, 0xef, 0xe9, 0xf0, 0x86, - 0xec, 0x9f, 0x90, 0x28, 0x3c, 0xd1, 0xbf, 0xef, 0xe8, 0x25, 0x0f, 0x4f, 0xa8, 0x57, 0xcd, 0x09, 0x31, 0xd5, 0x37, - 0x6a, 0x3f, 0x21, 0x91, 0x3f, 0x98, 0x27, 0xd6, 0x9e, 0xe6, 0x91, 0xa3, 0x8d, 0x69, 0x19, 0x82, 0xbe, 0xb9, 0x0c, - 0x6f, 0x08, 0x99, 0x36, 0xc7, 0x0e, 0x06, 0x74, 0xf6, 0x28, 0x4a, 0x08, 0xbd, 0xf1, 0x4b, 0xbd, 0xc1, 0x31, 0x34, - 0x23, 0xa4, 0xd2, 0x4e, 0x31, 0x0d, 0xd7, 0xc1, 0x6b, 0x0d, 0xd6, 0x71, 0xde, 0xef, 0x87, 0xeb, 0x7e, 0x1f, 0x22, - 0xdd, 0x17, 0x33, 0x13, 0xdb, 0xcd, 0x91, 0x4d, 0x7a, 0x03, 0xda, 0xff, 0xd7, 0x83, 0x01, 0x74, 0xc6, 0x2b, 0x29, - 0xbc, 0x19, 0xbc, 0x7e, 0x7c, 0x47, 0x54, 0x1d, 0x05, 0x15, 0x32, 0x2c, 0xe8, 0x1b, 0x9a, 0x01, 0xe0, 0xd7, 0xeb, - 0xc1, 0x80, 0x44, 0xe6, 0x33, 0x32, 0x7d, 0x7d, 0x78, 0x32, 0x1d, 0x0c, 0x5e, 0x9b, 0x6d, 0xf2, 0x96, 0xdd, 0x53, - 0x0a, 0xac, 0xbf, 0xb3, 0x7e, 0xff, 0xed, 0x51, 0x4c, 0xce, 0x0b, 0x1e, 0x7f, 0x9c, 0x36, 0xdb, 0xf2, 0xd6, 0x45, - 0x55, 0x3b, 0xeb, 0xf7, 0xd7, 0xfd, 0xfe, 0x29, 0x60, 0x17, 0xcd, 0x9c, 0xaf, 0x27, 0x48, 0x5b, 0xe6, 0x8e, 0x22, - 0x69, 0x92, 0x43, 0x63, 0x68, 0x5b, 0xac, 0xda, 0x36, 0xeb, 0xc8, 0xc0, 0xe2, 0xa8, 0x59, 0x51, 0x5c, 0x93, 0x28, - 0xec, 0x9d, 0x6d, 0xb7, 0xa7, 0x8c, 0xb1, 0x98, 0x80, 0xf4, 0xc3, 0x7f, 0x7d, 0x5a, 0x37, 0x62, 0x88, 0x09, 0x89, - 0xcc, 0xe6, 0x66, 0x69, 0x0f, 0x81, 0x88, 0xc3, 0xa6, 0x7f, 0x6f, 0xee, 0xe5, 0xa2, 0x76, 0x7c, 0xeb, 0x2f, 0x00, - 0x42, 0x24, 0x59, 0xc8, 0x67, 0x38, 0x06, 0x65, 0x06, 0x40, 0xe6, 0x91, 0x9a, 0x79, 0x09, 0x20, 0xc0, 0x64, 0xbb, - 0x1d, 0x8d, 0xc7, 0x13, 0x5a, 0xb0, 0xd1, 0xdf, 0x9e, 0x3d, 0xae, 0x1e, 0x87, 0x41, 0x30, 0xc8, 0x48, 0x4b, 0x4f, - 0x61, 0x17, 0x6b, 0xb5, 0x0f, 0x46, 0xf0, 0x9a, 0x7d, 0xbc, 0xce, 0xbe, 0x98, 0x7d, 0x44, 0xc2, 0xda, 0x60, 0x1c, - 0xb9, 0x48, 0x5b, 0x7a, 0xbb, 0x7b, 0x18, 0x4c, 0x2e, 0xd2, 0xcf, 0xb0, 0x9d, 0x3e, 0xff, 0xe6, 0xc1, 0x78, 0xc2, - 0xc1, 0xe8, 0x2e, 0x0a, 0xfa, 0x4c, 0xdb, 0x6e, 0x2b, 0xff, 0x12, 0xf8, 0x16, 0x53, 0x41, 0xc7, 0x66, 0x59, 0xb8, - 0x41, 0x45, 0xd4, 0xd1, 0x32, 0xa8, 0x6a, 0x65, 0x3b, 0x07, 0xd4, 0x12, 0xab, 0x32, 0x71, 0x0b, 0x0c, 0x43, 0x86, - 0xba, 0xdc, 0xe3, 0xea, 0x5f, 0xbc, 0x90, 0x06, 0x3e, 0xc3, 0x89, 0x08, 0x3d, 0x6e, 0x8d, 0xfb, 0xdc, 0x9a, 0xf8, - 0x0c, 0xb7, 0x56, 0x22, 0x89, 0x35, 0xb0, 0xa4, 0xe6, 0x72, 0x94, 0xb0, 0xa3, 0x92, 0xf1, 0x59, 0x19, 0x25, 0x34, - 0x86, 0x07, 0xc9, 0xc4, 0x4c, 0x46, 0x09, 0xda, 0x27, 0xba, 0x08, 0x83, 0x7f, 0x01, 0x66, 0x3f, 0xcd, 0xe1, 0xaf, - 0x24, 0xd3, 0xe4, 0x10, 0x02, 0x42, 0x1c, 0x8e, 0x67, 0x71, 0x38, 0x26, 0x51, 0x72, 0x04, 0x4f, 0xf0, 0x5f, 0x11, - 0x8e, 0x49, 0xad, 0xef, 0x30, 0x52, 0x5d, 0x6e, 0x13, 0x06, 0x70, 0x65, 0xe3, 0xd9, 0x24, 0xb2, 0xd2, 0x5d, 0xf9, - 0x78, 0x34, 0x7e, 0x46, 0xa6, 0x71, 0x28, 0x07, 0x09, 0xa1, 0xe0, 0xdd, 0x1b, 0x96, 0xc3, 0x44, 0xc3, 0xb3, 0x01, - 0x9b, 0x57, 0x3a, 0x36, 0x4f, 0xc2, 0x09, 0x08, 0xc3, 0x84, 0x1c, 0xeb, 0x3d, 0x48, 0x29, 0xfa, 0x3c, 0xc7, 0x7e, - 0xea, 0x23, 0x08, 0xb3, 0xa3, 0x96, 0x8a, 0xaf, 0x00, 0xe8, 0x12, 0x07, 0x87, 0xda, 0x33, 0x5f, 0xcc, 0xc2, 0xd2, - 0xa3, 0x52, 0xa6, 0xba, 0x7d, 0xd1, 0xa0, 0xfc, 0xa6, 0x41, 0xfb, 0x82, 0x0c, 0x26, 0xb4, 0x3c, 0x9a, 0xf0, 0x27, - 0x10, 0xc0, 0xa3, 0x11, 0xf1, 0x4b, 0xe1, 0xc4, 0x40, 0x78, 0x15, 0x64, 0xa0, 0xd2, 0x5a, 0x35, 0x66, 0x64, 0x2b, - 0xde, 0x83, 0x30, 0x29, 0x7b, 0x37, 0x72, 0x9d, 0xa7, 0x10, 0x15, 0x6c, 0x9d, 0x57, 0x7b, 0x97, 0x60, 0xc9, 0x1e, - 0x57, 0x10, 0x27, 0x6c, 0xbd, 0x02, 0xec, 0xdc, 0x47, 0x9b, 0xb2, 0xde, 0x53, 0xdf, 0xed, 0x61, 0xcb, 0xe1, 0x55, - 0x25, 0xf7, 0x26, 0xe3, 0xf1, 0x78, 0xf4, 0x07, 0x1c, 0x1d, 0x40, 0x68, 0x49, 0x64, 0xf8, 0x64, 0x80, 0xc6, 0x5d, - 0x57, 0xdc, 0x1b, 0x17, 0x8a, 0xb2, 0xd2, 0xc9, 0x84, 0x80, 0xf8, 0xd9, 0xf4, 0x0d, 0xf6, 0x15, 0xd7, 0xf1, 0x4f, - 0x76, 0x3f, 0x31, 0x2b, 0x5a, 0xad, 0xd4, 0xd1, 0xbb, 0x93, 0xd3, 0xd7, 0x1f, 0x5e, 0xff, 0xf6, 0xf2, 0xec, 0xf5, - 0xdb, 0x57, 0xaf, 0xdf, 0xbe, 0xfe, 0xf0, 0xcf, 0x07, 0x18, 0x6c, 0xdf, 0x56, 0xc4, 0x8e, 0xbd, 0x77, 0x8f, 0xf1, - 0x6a, 0xf1, 0x85, 0xb3, 0x07, 0xee, 0x16, 0x0b, 0xb0, 0x09, 0x86, 0x5b, 0x10, 0x54, 0x33, 0x1a, 0x95, 0xbe, 0x27, - 0x20, 0xa3, 0x51, 0x21, 0x1b, 0x0f, 0x2b, 0xb6, 0x42, 0x2e, 0xde, 0x31, 0x1c, 0x7c, 0x64, 0x7f, 0x2b, 0xce, 0x84, - 0xdb, 0xd1, 0xd6, 0xac, 0x08, 0xf8, 0x7c, 0xad, 0x45, 0xe5, 0x71, 0x21, 0x6a, 0x6f, 0xdb, 0xe7, 0x90, 0x50, 0x8f, - 0xc8, 0x75, 0xf0, 0xbe, 0x0d, 0xb2, 0xc7, 0x47, 0xde, 0x93, 0xf2, 0x0c, 0xf5, 0x39, 0x1a, 0x3e, 0x6a, 0x3c, 0xa3, - 0x13, 0x73, 0x6d, 0x74, 0xa8, 0x67, 0x05, 0xec, 0x6f, 0x25, 0xc6, 0x86, 0x68, 0x0f, 0x29, 0x62, 0x7d, 0x38, 0xdd, - 0xef, 0xee, 0xcd, 0xe8, 0x7b, 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, 0xf7, 0x5c, 0x29, 0x9a, 0xb7, 0x2e, 0xb0, 0x07, 0x6a, 0x5e, 0xc7, 0x4b, 0x16, 0x02, 0x36, 0xe3, - 0xbe, 0x5d, 0x24, 0xce, 0xef, 0x9d, 0x4e, 0xc8, 0xfe, 0xc1, 0x94, 0x0f, 0x59, 0x49, 0xc5, 0x80, 0x95, 0xf5, 0x0e, - 0x35, 0xe7, 0x6d, 0x42, 0x2e, 0x76, 0x69, 0xb8, 0x18, 0xf2, 0x87, 0x2e, 0x49, 0x1f, 0x78, 0xc3, 0xa1, 0xda, 0x36, - 0x17, 0x43, 0x9a, 0x72, 0xba, 0x4b, 0x65, 0x40, 0x88, 0x74, 0x15, 0x57, 0xa4, 0xd6, 0x47, 0x55, 0xea, 0x24, 0x1d, - 0xd7, 0xd9, 0xe6, 0x33, 0x97, 0x6c, 0x75, 0xbb, 0xf6, 0xaf, 0xd5, 0xed, 0x0b, 0x33, 0x90, 0xbf, 0x3f, 0x11, 0xd5, - 0xc4, 0x40, 0x74, 0x01, 0x15, 0xfc, 0x13, 0xbc, 0x3c, 0x79, 0xa4, 0x15, 0xa0, 0xf7, 0x9d, 0x1d, 0x5d, 0x7b, 0xbc, - 0x31, 0x8b, 0xad, 0x25, 0xce, 0x59, 0xe5, 0x3b, 0xcb, 0xab, 0xb2, 0x15, 0xba, 0x8e, 0x60, 0xbf, 0x84, 0x1d, 0x7d, - 0xf7, 0xb6, 0x01, 0x10, 0xa5, 0xb0, 0x72, 0x67, 0xbf, 0xf0, 0xce, 0x7e, 0x61, 0xcf, 0x7e, 0xbb, 0x09, 0x94, 0x0f, - 0x2b, 0xb4, 0xec, 0x95, 0x14, 0x95, 0x69, 0xf2, 0xb8, 0xa9, 0xcb, 0x42, 0x5a, 0xcc, 0xf7, 0x2d, 0xed, 0x7a, 0x3a, - 0xa6, 0x12, 0xd5, 0x23, 0x3f, 0x60, 0xab, 0xf6, 0x4b, 0xf2, 0xf0, 0x3d, 0xf3, 0x7f, 0xf6, 0x06, 0x79, 0xdf, 0xdd, - 0xee, 0xff, 0xe6, 0x42, 0x07, 0xb7, 0xb5, 0x54, 0x78, 0xea, 0xea, 0xb8, 0xc0, 0xbb, 0x5a, 0xfa, 0xf0, 0x5d, 0xed, - 0x5d, 0xa6, 0x97, 0x5d, 0x05, 0xa8, 0x41, 0x62, 0x7d, 0xc5, 0x8b, 0x2c, 0xa9, 0xad, 0x42, 0xe3, 0x84, 0x43, 0x68, - 0x0f, 0xef, 0xe0, 0x02, 0x39, 0x2c, 0x21, 0xf4, 0x63, 0x65, 0x04, 0x80, 0x3e, 0x8b, 0x7d, 0xc2, 0xc3, 0x8c, 0x0c, - 0x7c, 0x89, 0x5f, 0x29, 0x7d, 0x71, 0xf1, 0xfe, 0x4e, 0x66, 0x82, 0x5e, 0x25, 0x36, 0xbb, 0x94, 0xed, 0x98, 0x1f, - 0xfe, 0x17, 0x18, 0x0d, 0xc2, 0x6b, 0x4b, 0xb6, 0x2f, 0x3a, 0x66, 0xb9, 0x82, 0xa3, 0xb6, 0x74, 0x65, 0x96, 0xad, - 0xeb, 0x67, 0x35, 0xcc, 0xf4, 0x99, 0x72, 0x02, 0xb2, 0x2f, 0xe4, 0xee, 0xa7, 0xba, 0x62, 0x41, 0x8e, 0x26, 0xe3, - 0x29, 0x11, 0x83, 0x41, 0x2b, 0xf9, 0x10, 0x93, 0x87, 0xc3, 0x1d, 0xe6, 0x52, 0xe8, 0x7e, 0x78, 0x7d, 0x80, 0xfa, - 0x1a, 0x5b, 0x92, 0x6c, 0x2a, 0xf6, 0x17, 0x98, 0xc5, 0x02, 0x71, 0x74, 0xf0, 0x8b, 0xf3, 0x05, 0x80, 0x2c, 0xc3, - 0x32, 0xd3, 0xc2, 0xa2, 0x32, 0x55, 0x3e, 0xb2, 0x05, 0x93, 0x87, 0xe3, 0x99, 0xdf, 0x73, 0xc7, 0xe0, 0x10, 0x12, - 0x4d, 0xac, 0xf1, 0x8b, 0x9f, 0x05, 0xe3, 0x38, 0x94, 0x47, 0xb2, 0xf1, 0x5d, 0x49, 0xa2, 0xb1, 0x31, 0x55, 0xd6, - 0x57, 0x89, 0x6a, 0x98, 0x90, 0xc7, 0x05, 0xd9, 0x2f, 0xe8, 0xd2, 0x1f, 0x4b, 0x4c, 0xdf, 0x8f, 0xf7, 0x27, 0x63, - 0xf2, 0x38, 0x7e, 0x3c, 0x31, 0x70, 0xc3, 0x7e, 0x8e, 0x7c, 0xb8, 0x24, 0xfb, 0xcd, 0x2a, 0xc1, 0x14, 0xd5, 0xf4, - 0xcc, 0xaf, 0x24, 0x19, 0x2c, 0x07, 0xe9, 0xe3, 0x56, 0x5e, 0xac, 0x55, 0x8f, 0xf7, 0xfa, 0x90, 0x4f, 0x89, 0x68, - 0xdc, 0x18, 0xd6, 0xf4, 0x2a, 0xfe, 0x53, 0x16, 0x51, 0x29, 0x01, 0x91, 0x10, 0xd4, 0xdb, 0xd9, 0x45, 0x96, 0xc4, - 0x22, 0x8d, 0xd2, 0x9a, 0xd0, 0xf4, 0x88, 0x4d, 0xc6, 0xb3, 0x94, 0xa5, 0x87, 0x93, 0x67, 0xb3, 0xc9, 0xb3, 0xe8, - 0x60, 0x1c, 0xa5, 0x83, 0x01, 0x24, 0x1f, 0x8c, 0xc1, 0xc5, 0x0e, 0x7e, 0xb3, 0x03, 0x18, 0xba, 0x23, 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, 0x0b, 0xf9, 0xff, 0xe3, 0x86, 0x71, 0xdf, 0x5d, 0xc2, 0x2c, - 0xae, 0xeb, 0x6c, 0xb4, 0x2a, 0x64, 0x25, 0xe1, 0x36, 0xa1, 0x44, 0x61, 0xa3, 0x78, 0xb5, 0xca, 0xb5, 0x8b, 0xd8, - 0xbc, 0xa2, 0x00, 0xee, 0x02, 0x71, 0x8a, 0x81, 0x85, 0x36, 0x06, 0x72, 0x9f, 0x78, 0x21, 0x99, 0x55, 0xfb, 0x98, - 0x7b, 0xe4, 0x9f, 0x21, 0x18, 0xa3, 0x8a, 0xa3, 0xf1, 0x4c, 0x61, 0x5d, 0x7c, 0x4e, 0xde, 0xfb, 0x6f, 0x1c, 0x45, - 0xf6, 0x68, 0x06, 0x3d, 0x41, 0xe4, 0x3c, 0xe2, 0xec, 0xc9, 0xe4, 0x65, 0xe0, 0x7e, 0x06, 0x2b, 0xfd, 0x75, 0xb7, - 0x19, 0x6b, 0xdb, 0xa3, 0x7b, 0x61, 0x84, 0xa2, 0x9f, 0xf0, 0x9d, 0xa9, 0x17, 0x70, 0x09, 0xd5, 0xc0, 0xae, 0x2f, - 0x2f, 0x79, 0x09, 0x20, 0x42, 0x99, 0xe8, 0xf7, 0x7b, 0x7f, 0x1a, 0x68, 0xd2, 0x92, 0x17, 0x6f, 0x32, 0x61, 0x9d, - 0x71, 0xa0, 0xa9, 0x40, 0xfd, 0x3f, 0x56, 0xf6, 0x99, 0x8e, 0xc9, 0xcc, 0x7f, 0x1c, 0x4e, 0x48, 0xd4, 0x7c, 0x4d, - 0x3e, 0x73, 0x9a, 0x7e, 0xe6, 0x8a, 0xf6, 0x1f, 0xc8, 0xcc, 0x0d, 0x87, 0x0c, 0xf5, 0x97, 0x8e, 0x79, 0x32, 0x7a, - 0x9d, 0x98, 0x1d, 0x09, 0x56, 0xcd, 0x20, 0x0a, 0x7b, 0x01, 0x0f, 0xea, 0x5a, 0x16, 0x4f, 0x61, 0xf6, 0x41, 0x8d, - 0x28, 0x0e, 0xd9, 0x78, 0x16, 0xca, 0x70, 0x02, 0xf6, 0xbd, 0x93, 0x31, 0xdc, 0x07, 0x64, 0xf8, 0xb1, 0x0a, 0xb1, - 0x73, 0x90, 0xf6, 0xb1, 0x42, 0xc5, 0x04, 0x40, 0x04, 0x42, 0xde, 0x7e, 0x5f, 0xaa, 0x24, 0x7c, 0x5d, 0x62, 0x4a, - 0xa1, 0x3e, 0xf8, 0x4f, 0xa4, 0xea, 0x8e, 0xe9, 0x57, 0xeb, 0xc7, 0x9f, 0x09, 0xc5, 0xa7, 0xbb, 0x94, 0xf8, 0x16, - 0x82, 0x3b, 0x4b, 0xd0, 0x41, 0x54, 0x68, 0xc6, 0xf6, 0x30, 0xbf, 0x2b, 0xee, 0xe7, 0x77, 0xc5, 0xff, 0x3b, 0x7e, - 0x57, 0x3c, 0xc4, 0x18, 0x56, 0x16, 0x1a, 0x7e, 0x16, 0x8c, 0x83, 0xe8, 0x3f, 0xe7, 0x13, 0xef, 0xe5, 0xa9, 0xaf, - 0x32, 0x31, 0xbd, 0x87, 0x69, 0xf6, 0x09, 0x0a, 0xc2, 0x2a, 0xee, 0xd2, 0x93, 0x75, 0x65, 0x6f, 0xad, 0x64, 0x88, - 0x79, 0x1e, 0x60, 0x8d, 0xc2, 0xca, 0x03, 0xba, 0x47, 0xd5, 0x06, 0x71, 0x22, 0x78, 0x18, 0x33, 0x2b, 0x7d, 0xdf, - 0x6e, 0x8d, 0x0a, 0xf3, 0x41, 0x2e, 0x0a, 0xb2, 0x9b, 0x8f, 0x67, 0xe3, 0x28, 0xc4, 0x06, 0xfc, 0xc7, 0x8c, 0x55, - 0x43, 0x36, 0xdf, 0xc9, 0x48, 0xed, 0x98, 0x3c, 0x4d, 0x76, 0x49, 0xef, 0x80, 0x77, 0xc8, 0xcf, 0xeb, 0x8f, 0x61, - 0x21, 0x0d, 0xbf, 0x25, 0x2f, 0xe3, 0x22, 0xab, 0x96, 0x57, 0x59, 0x82, 0x4c, 0x17, 0xbc, 0xf8, 0x62, 0xa6, 0xcb, - 0xfb, 0x58, 0x1f, 0x30, 0x9e, 0x52, 0xbc, 0x6e, 0x88, 0xd2, 0xd7, 0x2d, 0xcf, 0x0a, 0x75, 0x79, 0x52, 0x31, 0xdb, - 0xb3, 0x12, 0x9c, 0x4e, 0xc1, 0x04, 0x5f, 0xff, 0x74, 0xbd, 0x8f, 0x01, 0x17, 0x14, 0x6a, 0x4e, 0x0b, 0xb9, 0x32, - 0x58, 0x4e, 0x16, 0xba, 0x13, 0x30, 0x43, 0xa5, 0xc0, 0x0b, 0x14, 0xfc, 0x45, 0x03, 0x23, 0xfa, 0xca, 0xfd, 0x26, - 0x03, 0x83, 0x74, 0x69, 0x4e, 0x84, 0xb1, 0xe3, 0x76, 0x8a, 0xb4, 0x15, 0xe5, 0x8c, 0xb3, 0xf7, 0xea, 0x4a, 0x01, - 0x06, 0x78, 0x9b, 0x9b, 0xe8, 0x3c, 0x41, 0xaf, 0x05, 0xa5, 0xf3, 0x06, 0xee, 0x66, 0x19, 0x19, 0xe1, 0xe2, 0xe3, - 0xca, 0x63, 0xc1, 0x3d, 0xfb, 0x85, 0x58, 0x1a, 0xcd, 0x34, 0x18, 0xb3, 0x79, 0xc1, 0x02, 0x85, 0x0a, 0x14, 0x58, - 0xce, 0xb4, 0xa5, 0x69, 0x35, 0xe4, 0xfb, 0x07, 0x68, 0x6d, 0x5a, 0x0d, 0xf8, 0xfe, 0x41, 0x1d, 0x65, 0x87, 0x90, - 0xe5, 0xc8, 0xcf, 0xa0, 0x5e, 0xd7, 0x91, 0x49, 0x31, 0xd9, 0xfd, 0xfa, 0x52, 0x7f, 0x54, 0x37, 0xe0, 0xfa, 0x01, - 0x08, 0x60, 0x03, 0x70, 0x08, 0x54, 0x83, 0xa5, 0x11, 0xc1, 0xa2, 0x4c, 0xa1, 0x7d, 0x0d, 0xbd, 0x37, 0x1a, 0xfe, - 0x0b, 0xdc, 0x45, 0xe4, 0xca, 0xff, 0x04, 0x81, 0xbf, 0xa2, 0x4c, 0x2b, 0x53, 0xfc, 0x4f, 0xb4, 0x7a, 0x85, 0x72, - 0xd6, 0xb4, 0xe6, 0x83, 0x68, 0x4d, 0x84, 0x6a, 0xc6, 0x10, 0xfc, 0x5b, 0x59, 0xa6, 0x2d, 0x55, 0x95, 0xfa, 0xd0, - 0x78, 0xad, 0x15, 0xce, 0xf2, 0x71, 0xe4, 0xbd, 0xc6, 0xd0, 0xb1, 0x89, 0xb3, 0x94, 0x53, 0xa9, 0xb3, 0x4f, 0xfb, - 0x32, 0x72, 0x80, 0xd3, 0x09, 0x1b, 0x4f, 0x93, 0x43, 0x39, 0x4d, 0x1c, 0x64, 0x7e, 0xce, 0x30, 0xb2, 0xaa, 0x01, - 0x61, 0x51, 0x36, 0x94, 0xb6, 0x00, 0x93, 0x9c, 0x10, 0x32, 0xc5, 0x50, 0x14, 0xf9, 0x48, 0xf7, 0xc3, 0x7a, 0xb3, - 0xba, 0x2f, 0xde, 0x69, 0x80, 0xd3, 0x30, 0x81, 0x40, 0xe0, 0x45, 0x7c, 0x93, 0x89, 0x4b, 0xf0, 0x18, 0x1e, 0xc0, - 0x97, 0xe0, 0x26, 0x97, 0xb2, 0xdf, 0xab, 0x30, 0xc7, 0xb5, 0x05, 0x0c, 0x1a, 0xac, 0x1e, 0x44, 0x87, 0x4b, 0x69, - 0xb3, 0xab, 0x00, 0xb1, 0x31, 0x85, 0x58, 0x16, 0x6c, 0x6d, 0xd9, 0xb3, 0xef, 0x55, 0xd3, 0xd0, 0x3a, 0xe1, 0x58, - 0x5c, 0xe6, 0x10, 0x45, 0x65, 0x10, 0x83, 0x3b, 0x92, 0xc7, 0xe7, 0x3d, 0x12, 0xe1, 0x05, 0x01, 0xb7, 0xb2, 0x58, - 0x86, 0x2b, 0xba, 0x1c, 0xdd, 0xd2, 0xf5, 0xe8, 0x86, 0x8e, 0xe9, 0xe4, 0xef, 0x63, 0xb0, 0xc8, 0xd6, 0xa9, 0x77, - 0x74, 0x3d, 0x5a, 0xd2, 0x6f, 0xc7, 0xf4, 0xe0, 0x6f, 0x60, 0xc2, 0x87, 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, 0xae, 0xf8, 0x55, 0xc9, 0x52, - 0xd8, 0x16, 0xb0, 0x7c, 0x3d, 0xaf, 0xa8, 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, 0x8e, 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, 0xca, 0xd3, 0xf6, - 0x75, 0xb0, 0xb1, 0xaa, 0xe8, 0x86, 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, 0xbe, 0x87, 0x88, 0xca, 0x50, 0xde, 0xe0, 0x1f, 0x18, 0x3c, 0x99, 0xad, 0xd2, 0x30, - 0x19, 0xdd, 0xd1, 0x78, 0xb4, 0x44, 0x38, 0x18, 0xb6, 0x4e, 0x15, 0xde, 0xfa, 0x05, 0xa4, 0xdf, 0xd2, 0x78, 0x74, - 0x43, 0x53, 0x6b, 0x73, 0x6a, 0xa0, 0xae, 0x7a, 0x63, 0x7a, 0x1b, 0xc1, 0xeb, 0xbb, 0x68, 0x49, 0x61, 0x2b, 0x1d, - 0xe7, 0xd9, 0xa5, 0x88, 0x52, 0x8a, 0x08, 0x84, 0x6b, 0x44, 0x0e, 0x5c, 0x6a, 0xb4, 0xc1, 0xf5, 0x00, 0xca, 0xd0, - 0x70, 0x81, 0xcb, 0x41, 0x3c, 0x5a, 0x7a, 0x64, 0x6a, 0xa9, 0x2f, 0xb2, 0x08, 0x1f, 0xed, 0x6c, 0xb4, 0x14, 0xcf, - 0x88, 0x85, 0x71, 0x05, 0x43, 0xa8, 0x0b, 0x2b, 0x4d, 0x41, 0xd2, 0x05, 0x8e, 0xec, 0x85, 0x45, 0x15, 0x6e, 0xc0, - 0xb4, 0xe8, 0x0e, 0xcc, 0xa3, 0x40, 0xe1, 0xe0, 0x12, 0xa4, 0x9f, 0x50, 0xb6, 0x73, 0x94, 0x26, 0x87, 0x37, 0x41, - 0xe9, 0xce, 0x04, 0x21, 0xed, 0xea, 0x26, 0x5b, 0xd2, 0x37, 0xd8, 0xde, 0xa1, 0x53, 0x51, 0x41, 0xf5, 0xb9, 0x05, - 0x93, 0x25, 0x1b, 0x84, 0x2d, 0x61, 0x7a, 0xa6, 0xd7, 0x80, 0x3d, 0xbd, 0x7f, 0xb0, 0x33, 0xdf, 0xc5, 0xec, 0xd3, - 0x7e, 0x19, 0x8d, 0x95, 0x05, 0x6f, 0x6e, 0x89, 0xdd, 0x92, 0x8d, 0xa7, 0xcb, 0xc3, 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, - 0x96, 0x69, 0x98, 0xe2, 0x22, 0x30, 0x29, 0xfd, 0x7e, 0x98, 0xb3, 0x94, 0x78, 0xd0, 0xa1, 0xee, 0xd4, 0x4e, 0x7d, - 0x21, 0x08, 0xf0, 0x48, 0xea, 0x1c, 0x9b, 0xfc, 0x7d, 0x3c, 0x0b, 0xd4, 0x40, 0x04, 0x51, 0x76, 0x88, 0x8f, 0x18, - 0xb8, 0x28, 0xd2, 0x71, 0x3b, 0x5d, 0x11, 0x17, 0xbb, 0xc7, 0x2c, 0xc4, 0x49, 0xc2, 0x5c, 0xb3, 0x6c, 0xc8, 0xaa, - 0x08, 0x13, 0x74, 0x61, 0x60, 0x96, 0x37, 0x64, 0xd5, 0xfe, 0x01, 0x44, 0x6a, 0xb5, 0x65, 0xac, 0xba, 0xca, 0xf8, - 0x16, 0x80, 0xac, 0x19, 0x63, 0x07, 0x7f, 0x1b, 0xcf, 0xd4, 0x37, 0x51, 0xc8, 0x8f, 0x0e, 0xfe, 0x06, 0xc9, 0x87, - 0xdf, 0x22, 0x33, 0x07, 0xc9, 0x8d, 0x82, 0x2e, 0x9b, 0xb3, 0xae, 0xa1, 0x34, 0x71, 0xed, 0x95, 0x7a, 0xed, 0x49, - 0xb3, 0xf6, 0x0a, 0x74, 0xa7, 0x36, 0xbc, 0x87, 0xb2, 0x9d, 0x05, 0x13, 0x74, 0x34, 0xbb, 0x03, 0x1d, 0xbc, 0x53, - 0x04, 0xbd, 0x4c, 0x42, 0xe3, 0x11, 0xaa, 0x8c, 0x7a, 0x61, 0x47, 0x76, 0xb3, 0x2e, 0x99, 0x67, 0xc0, 0x1c, 0xdb, - 0x73, 0x48, 0x0c, 0x73, 0x75, 0x50, 0xa7, 0xac, 0x1c, 0xe6, 0x78, 0x00, 0xaf, 0x99, 0x1c, 0x8a, 0x41, 0xae, 0x51, - 0xbe, 0x2f, 0x58, 0x31, 0x2c, 0x07, 0xb9, 0xe6, 0x66, 0xa6, 0xcd, 0xd8, 0xb4, 0x89, 0x0e, 0xcf, 0xbc, 0x62, 0x47, - 0xab, 0x1e, 0xf0, 0xb1, 0xe0, 0xc9, 0xec, 0x7b, 0x3e, 0xbe, 0x01, 0x4e, 0x66, 0x73, 0x1b, 0x2d, 0xe9, 0x5d, 0x94, - 0xd2, 0x9b, 0x68, 0x4d, 0x97, 0xd1, 0x85, 0x31, 0x31, 0x4e, 0x6a, 0x38, 0x07, 0xa0, 0x55, 0x00, 0x89, 0xa7, 0x7e, - 0xbd, 0xe7, 0x49, 0x15, 0x2e, 0x69, 0x0a, 0x6e, 0xc3, 0xbe, 0x7d, 0xe6, 0x95, 0x2f, 0x91, 0xda, 0x20, 0xc6, 0x9a, - 0x35, 0x54, 0xdc, 0x78, 0xeb, 0x3e, 0x12, 0x35, 0xec, 0x5c, 0x17, 0x9b, 0xa8, 0x1a, 0x4e, 0xa6, 0x25, 0x20, 0xb6, - 0x96, 0xc3, 0xa1, 0x3b, 0x42, 0x76, 0x8f, 0x1f, 0x1d, 0xe8, 0xb9, 0x27, 0x2d, 0xb6, 0x6d, 0xcb, 0x1f, 0x18, 0xc2, - 0x94, 0x7e, 0xfe, 0xc8, 0x07, 0xc4, 0x8a, 0x4b, 0x38, 0x1b, 0x81, 0x3a, 0x5a, 0xa1, 0xd3, 0xef, 0x55, 0x58, 0xe8, - 0x03, 0x7c, 0x73, 0x1b, 0x25, 0xf4, 0x2e, 0xca, 0x3d, 0xb2, 0xb6, 0xac, 0x99, 0x9c, 0x9e, 0x65, 0x21, 0x6f, 0x1f, - 0xe8, 0xe5, 0x02, 0x40, 0xb4, 0x06, 0xb1, 0x2f, 0x75, 0x3d, 0x00, 0xa7, 0x21, 0x34, 0x09, 0x8d, 0xe0, 0xaa, 0x82, - 0x30, 0x02, 0xae, 0x24, 0xfc, 0x0d, 0x26, 0x2a, 0xf0, 0x05, 0xb8, 0xc8, 0xa4, 0x69, 0xce, 0x83, 0xda, 0x1f, 0xc9, - 0xd3, 0xa2, 0xed, 0xed, 0x0a, 0xa3, 0x09, 0xc6, 0x9e, 0x68, 0x9f, 0x47, 0xca, 0x51, 0x5c, 0x24, 0x61, 0x36, 0xba, - 0x55, 0xe7, 0x39, 0xcd, 0x46, 0x77, 0xfa, 0x57, 0x45, 0xc7, 0xf4, 0x3b, 0x1d, 0xd0, 0x46, 0x49, 0xdf, 0x3a, 0xce, - 0x06, 0xb4, 0x5e, 0x2c, 0x8d, 0xff, 0xb5, 0x1c, 0xdd, 0x52, 0x39, 0xba, 0xf3, 0x2d, 0xa9, 0x26, 0xd3, 0xe2, 0x50, - 0xa0, 0x21, 0x55, 0xe7, 0xf7, 0x05, 0xf0, 0x73, 0xa5, 0xf1, 0x9d, 0x36, 0xdf, 0x7b, 0xed, 0x3f, 0xef, 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, 0xcb, 0xed, 0x56, 0xc5, 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, 0x5c, 0xd7, 0xcf, 0xda, 0xd4, 0xe8, 0x15, 0x58, 0xf8, - 0x6e, 0x94, 0x79, 0x24, 0xb7, 0x08, 0xa9, 0x0a, 0xac, 0xd4, 0x2d, 0x24, 0x98, 0x7f, 0x25, 0x67, 0xab, 0x32, 0x5f, - 0x3d, 0xf2, 0xa0, 0x9c, 0x4d, 0x4f, 0x7f, 0x43, 0x82, 0x76, 0xd7, 0x91, 0xe6, 0xf1, 0x16, 0x1d, 0x3e, 0xbb, 0xd6, - 0x12, 0x73, 0x27, 0x51, 0xf1, 0x7c, 0x0a, 0xd8, 0xea, 0x45, 0x76, 0xa5, 0x7c, 0xac, 0x76, 0x71, 0xfc, 0xcc, 0xf9, - 0x13, 0x57, 0xe1, 0x5a, 0x34, 0x94, 0x20, 0xe0, 0xcd, 0x61, 0xec, 0x0a, 0x55, 0x40, 0x43, 0x73, 0x03, 0xc7, 0xb9, - 0x1a, 0x56, 0x9a, 0x80, 0x69, 0x29, 0x8f, 0x0e, 0x70, 0x68, 0xf2, 0xa8, 0xdd, 0x34, 0xac, 0x0c, 0x5d, 0x6b, 0xf4, - 0xb9, 0xad, 0x74, 0xc6, 0x9b, 0x0d, 0xdf, 0x3f, 0x18, 0x54, 0xf8, 0x93, 0x34, 0x47, 0xa3, 0x9d, 0x1b, 0xee, 0x34, - 0x02, 0x33, 0x57, 0x72, 0x45, 0x76, 0x47, 0xc9, 0xcb, 0xef, 0xe9, 0x85, 0x05, 0xf4, 0xe7, 0x3f, 0x17, 0x13, 0x4e, - 0x5a, 0x62, 0x42, 0xb4, 0x74, 0xd0, 0xa2, 0x83, 0x1d, 0xe5, 0x95, 0x7d, 0x89, 0x97, 0xce, 0xf1, 0xbf, 0xaf, 0xc7, - 0xda, 0x55, 0x20, 0xb4, 0x3a, 0xb9, 0xdf, 0x9e, 0x2c, 0x10, 0x35, 0xa0, 0x9a, 0x5d, 0x95, 0xa3, 0x4c, 0x3b, 0x2b, - 0xb2, 0x69, 0xc8, 0x5c, 0x77, 0xb3, 0x34, 0x6c, 0x26, 0x3b, 0x16, 0x96, 0x19, 0x06, 0x6b, 0xa7, 0x8a, 0x3e, 0x07, - 0x2d, 0x3f, 0x82, 0x17, 0x4d, 0xe5, 0x99, 0xcf, 0x66, 0x19, 0xf1, 0x02, 0x9d, 0x73, 0x2a, 0x16, 0x4d, 0xe9, 0x58, - 0xb9, 0xdd, 0x96, 0x68, 0x2c, 0x51, 0x46, 0x41, 0x50, 0xdb, 0x20, 0xec, 0xba, 0x74, 0x4f, 0xfa, 0xb4, 0x8b, 0x4f, - 0x2b, 0xd0, 0xf7, 0xf8, 0x3e, 0x03, 0x89, 0xa9, 0x27, 0x79, 0xa8, 0x1a, 0xcd, 0xd1, 0xc9, 0xb3, 0x38, 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, 0x07, 0xd4, 0xa9, 0x8b, 0x75, 0x1b, 0x50, 0xb2, 0xe4, 0xdd, 0x3a, 0x3d, 0xb1, 0xd2, 0x77, 0xfb, - 0xe1, 0xce, 0x3c, 0x6a, 0x76, 0x77, 0xbb, 0x9d, 0x90, 0xb6, 0x7d, 0x30, 0xde, 0x97, 0xb0, 0x10, 0xe7, 0x1d, 0xb6, - 0xf7, 0x7d, 0x58, 0x3d, 0xe6, 0x83, 0x5f, 0x70, 0x9c, 0x61, 0xf4, 0x33, 0x65, 0xe8, 0xf3, 0xaa, 0x90, 0x57, 0xaa, - 0x53, 0xbe, 0xd0, 0xad, 0x65, 0xea, 0xfd, 0x36, 0x7e, 0xdb, 0x0a, 0x10, 0xe3, 0x75, 0xc5, 0x4a, 0xf1, 0x86, 0x56, - 0x18, 0xd7, 0xc0, 0x6d, 0x72, 0xa8, 0xa5, 0x5a, 0x20, 0xea, 0xf2, 0x93, 0xc7, 0x3c, 0x32, 0xea, 0x4c, 0xf8, 0xee, - 0x31, 0xf7, 0xa5, 0x6b, 0xbb, 0x4d, 0xfc, 0x5c, 0xd3, 0xf6, 0x77, 0x07, 0xba, 0xa3, 0x75, 0x0f, 0x37, 0xcf, 0xe6, - 0xe7, 0x91, 0xf9, 0x62, 0x80, 0xcd, 0xda, 0x65, 0x5c, 0x76, 0x0c, 0xf7, 0xbd, 0xe9, 0xc1, 0x58, 0x40, 0x20, 0x31, - 0x43, 0x2f, 0x03, 0x17, 0xb8, 0xc0, 0x5d, 0x61, 0xc0, 0x10, 0xd7, 0xb4, 0xe4, 0x4c, 0x5b, 0xd9, 0xfa, 0xc8, 0xdb, - 0xa8, 0x10, 0xac, 0xeb, 0x8e, 0x9b, 0x24, 0x87, 0xe0, 0x84, 0x2d, 0xf7, 0xbe, 0xf6, 0xda, 0x19, 0xfe, 0x63, 0x20, - 0x9c, 0x5b, 0xa2, 0x67, 0xd4, 0xf6, 0x58, 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, 0xde, 0xbf, 0xe6, 0x38, 0x71, 0x96, 0xc2, 0xf6, 0xc3, 0x87, 0x0b, 0x76, 0x4d, 0x00, 0x83, 0x16, 0x93, 0x05, - 0x4a, 0x50, 0xc9, 0x5a, 0xd5, 0x6e, 0xa7, 0xc4, 0x2f, 0xf7, 0x8b, 0x2e, 0xb3, 0x9d, 0xc7, 0xaf, 0x9b, 0xb4, 0xcf, - 0x7c, 0x8e, 0x7e, 0x98, 0xdf, 0x59, 0x27, 0x25, 0x67, 0x18, 0xd7, 0xf2, 0xff, 0xab, 0xe8, 0x65, 0x91, 0xa5, 0xd1, - 0xc6, 0xf0, 0x60, 0x36, 0xd4, 0xa6, 0x0f, 0x8d, 0x51, 0xb9, 0x65, 0xa3, 0x88, 0x68, 0x75, 0x0b, 0x82, 0x19, 0xc5, - 0x7d, 0x89, 0x36, 0xaf, 0x54, 0x59, 0x78, 0x87, 0xcf, 0x6c, 0xf4, 0x86, 0xed, 0x09, 0xa1, 0x7c, 0xf7, 0xb4, 0x30, - 0xab, 0x96, 0x8a, 0x06, 0xdb, 0x25, 0xbc, 0x8b, 0x51, 0xa5, 0x9f, 0x30, 0xd9, 0xb2, 0x60, 0xaa, 0xff, 0xdf, 0x17, - 0x59, 0xda, 0xa6, 0xe8, 0xc0, 0x74, 0x36, 0x7d, 0x3a, 0xe9, 0x06, 0xd7, 0x19, 0xb0, 0x88, 0x60, 0x4b, 0x85, 0xe3, - 0x51, 0x6a, 0x37, 0x48, 0x98, 0x08, 0x6e, 0xa2, 0x5e, 0x76, 0xb4, 0x4c, 0xc9, 0xaa, 0x80, 0xe7, 0x57, 0xae, 0x32, - 0x1d, 0x47, 0x43, 0xbf, 0x7f, 0x95, 0x9a, 0xd0, 0xaf, 0xd4, 0x4b, 0x55, 0x9c, 0x87, 0x51, 0x75, 0xa8, 0x30, 0x46, - 0x4b, 0x9a, 0xc2, 0x31, 0x98, 0x5d, 0x84, 0x29, 0x5e, 0xce, 0x36, 0x09, 0xfb, 0x82, 0x81, 0x5c, 0x6a, 0x83, 0x7a, - 0x4d, 0x89, 0xd6, 0xac, 0xbd, 0x99, 0x53, 0x42, 0x2f, 0x58, 0xe9, 0xdf, 0x85, 0xd6, 0x20, 0x50, 0x94, 0xcd, 0x94, - 0xe9, 0xb9, 0x6e, 0xe7, 0x05, 0x4d, 0x68, 0x41, 0x57, 0xa4, 0x06, 0x7d, 0xaf, 0x93, 0xb3, 0xa3, 0x93, 0x9d, 0x99, - 0xf5, 0x98, 0x15, 0xc3, 0xc9, 0x34, 0x86, 0x6b, 0x5a, 0xec, 0xae, 0x69, 0xcb, 0xe6, 0x8d, 0xab, 0xb1, 0x71, 0x1a, - 0xb4, 0x0b, 0xa4, 0x6d, 0x9a, 0xdb, 0x4f, 0x3d, 0x6e, 0x7f, 0x5d, 0xb3, 0xe5, 0xb4, 0xb7, 0xde, 0x6e, 0x7b, 0x29, - 0xd8, 0x88, 0x7a, 0x7c, 0xfc, 0x5a, 0x49, 0xd7, 0x2d, 0x97, 0x9f, 0xc2, 0xb3, 0xc7, 0xd7, 0x2f, 0x7d, 0x70, 0x39, - 0x5a, 0xb5, 0xb9, 0xfb, 0xe5, 0x2e, 0xb2, 0xdc, 0x17, 0x0d, 0x2d, 0xd7, 0x33, 0xd4, 0x24, 0xcf, 0x46, 0x7b, 0x87, - 0x5a, 0xb0, 0x9c, 0x75, 0x13, 0x9e, 0x18, 0xec, 0xd8, 0xab, 0xc6, 0xe6, 0xa8, 0xcc, 0x25, 0xab, 0x41, 0x02, 0x7d, - 0x92, 0x67, 0x9a, 0xfe, 0x41, 0x86, 0xf9, 0xe8, 0x96, 0xe6, 0x80, 0x2b, 0x56, 0xd9, 0x4b, 0x06, 0xa9, 0xab, 0xf6, - 0x12, 0x57, 0xbe, 0xc2, 0x21, 0xd9, 0xe0, 0x93, 0x61, 0xaa, 0x3e, 0xbb, 0xe4, 0xc1, 0xff, 0xdb, 0xaa, 0x55, 0x7a, - 0x6e, 0x92, 0x1b, 0x8e, 0x7f, 0x9d, 0xb4, 0x7d, 0x4c, 0x0c, 0x12, 0xf0, 0xd4, 0x2e, 0x86, 0x6a, 0x54, 0x15, 0xb1, - 0x28, 0x73, 0x13, 0x73, 0xec, 0xde, 0xae, 0xa1, 0x83, 0x32, 0xf8, 0x75, 0xc3, 0x27, 0xe6, 0x0e, 0x6c, 0x05, 0x3a, - 0x3a, 0xd1, 0x5c, 0x86, 0x99, 0xb9, 0x0c, 0xd3, 0xae, 0xad, 0x02, 0xc3, 0xab, 0xb6, 0x4a, 0xa2, 0x5c, 0x8d, 0x7a, - 0xdc, 0xcc, 0x52, 0xb3, 0x17, 0x79, 0xf7, 0x9a, 0xf4, 0x24, 0xfe, 0x74, 0xe9, 0xc9, 0xeb, 0x61, 0x40, 0xe4, 0x97, - 0x2c, 0x0d, 0xd7, 0x28, 0x08, 0x4e, 0xad, 0x76, 0x20, 0xcd, 0x47, 0x80, 0xcc, 0x8f, 0xd3, 0xf0, 0x9d, 0x16, 0xe7, - 0x90, 0x8d, 0xd2, 0x38, 0xb1, 0xa5, 0x51, 0x0f, 0xc1, 0x9d, 0xf7, 0x8a, 0xc7, 0x10, 0xf8, 0xf0, 0x03, 0x6e, 0x06, - 0x15, 0xdd, 0x96, 0x98, 0x28, 0x6d, 0x1e, 0x75, 0xcb, 0x47, 0x0d, 0xa1, 0x92, 0x95, 0xe1, 0xc5, 0xd0, 0xde, 0x1d, - 0x81, 0x51, 0xe5, 0x04, 0x32, 0xc3, 0x62, 0xff, 0x60, 0x98, 0x2a, 0x41, 0xd1, 0x50, 0x0e, 0x97, 0x28, 0x07, 0xc4, - 0x24, 0x10, 0x18, 0x15, 0x83, 0x54, 0x57, 0xa6, 0x5e, 0x0c, 0x52, 0x7d, 0xab, 0x22, 0xf5, 0x59, 0x16, 0x56, 0x54, - 0xb7, 0x88, 0x8e, 0xe9, 0x50, 0xd2, 0xa5, 0xd9, 0xa9, 0xb9, 0x96, 0x5e, 0xa8, 0xe5, 0xf8, 0x5c, 0xa7, 0xc1, 0x28, - 0x9e, 0xba, 0x14, 0xfd, 0x56, 0xed, 0x67, 0xff, 0x2d, 0xa6, 0xd4, 0x88, 0x4d, 0xed, 0x2d, 0x62, 0x58, 0xb5, 0x1f, - 0xb2, 0x2a, 0x07, 0xed, 0x2e, 0x28, 0x1b, 0x2b, 0xe3, 0x3c, 0xdf, 0x08, 0x66, 0x0e, 0xda, 0xc6, 0xaa, 0xe9, 0x43, - 0x6f, 0xc4, 0xa8, 0xbd, 0x31, 0xd5, 0xb8, 0x27, 0xf0, 0xd3, 0x06, 0x4d, 0xf7, 0x22, 0xcf, 0x51, 0x8f, 0xbc, 0xfb, - 0x9f, 0x39, 0xb2, 0x33, 0xf9, 0x2c, 0x96, 0x49, 0xdd, 0x3e, 0x26, 0xc1, 0x42, 0xd5, 0x31, 0xba, 0x70, 0x23, 0x53, - 0xda, 0xcf, 0x9d, 0xe9, 0x47, 0x3c, 0x93, 0x87, 0xed, 0xd0, 0xa8, 0x2f, 0x0d, 0x6b, 0x49, 0x11, 0xf5, 0x05, 0xbd, - 0x35, 0xd5, 0xd1, 0x01, 0xf5, 0x3a, 0x02, 0xab, 0x2b, 0xda, 0xa0, 0x06, 0x60, 0x32, 0xae, 0x6d, 0x6d, 0x3e, 0x07, - 0x53, 0x5b, 0x55, 0xc1, 0x33, 0xba, 0x2b, 0x94, 0xee, 0x4d, 0xea, 0xba, 0x35, 0xc4, 0x16, 0x30, 0x20, 0x70, 0xa3, - 0xa7, 0xa6, 0x3f, 0x68, 0xa2, 0x02, 0xd0, 0xa0, 0x71, 0x3b, 0xd3, 0x39, 0x12, 0xfd, 0x4e, 0x6d, 0xda, 0x66, 0xaa, - 0x57, 0x95, 0x0f, 0xa0, 0xe2, 0xcf, 0xd2, 0xd9, 0x85, 0x19, 0xb1, 0x00, 0xc6, 0x3d, 0x70, 0xa6, 0x7a, 0xc7, 0x19, - 0x58, 0x4f, 0xe4, 0x79, 0x56, 0xf2, 0x44, 0x0a, 0x98, 0x11, 0x79, 0x75, 0x25, 0x05, 0x0c, 0x83, 0x1a, 0x00, 0xb4, - 0x68, 0x2e, 0xa3, 0x09, 0x7f, 0x52, 0xd3, 0xfb, 0xf2, 0xf0, 0x27, 0x3a, 0xd7, 0x37, 0xe3, 0x1a, 0x0c, 0x95, 0xd7, - 0x15, 0xdf, 0xc9, 0xf4, 0x0d, 0x7f, 0xea, 0x65, 0x5a, 0xca, 0x75, 0xb1, 0x93, 0xe5, 0xc9, 0x37, 0xfc, 0x99, 0xce, - 0x73, 0xf0, 0xb4, 0xa6, 0x69, 0x7c, 0xb7, 0x93, 0xe5, 0xef, 0xdf, 0x3c, 0xb5, 0x79, 0x9e, 0x8c, 0x6b, 0x7a, 0xc3, - 0xf9, 0x47, 0x97, 0x69, 0xa2, 0xab, 0x1a, 0x3f, 0xfd, 0xbb, 0xcd, 0xf5, 0xb4, 0xa6, 0x57, 0x52, 0x54, 0xcb, 0x9d, - 0xa2, 0x0e, 0xbe, 0x39, 0xf8, 0x3b, 0xff, 0xc6, 0x74, 0xef, 0xa0, 0xa6, 0x7f, 0xad, 0xe3, 0xa2, 0xe2, 0xc5, 0x4e, - 0x71, 0x7f, 0xfb, 0xfb, 0xdf, 0x9f, 0xda, 0x8c, 0x4f, 0x6b, 0x7a, 0xc7, 0xe3, 0x8e, 0xb6, 0x4f, 0x9e, 0x3d, 0xe5, - 0x7f, 0xab, 0x6b, 0xfa, 0x2b, 0xf3, 0x83, 0xa3, 0x1e, 0x67, 0x9e, 0x1e, 0x3e, 0x91, 0x4d, 0xd4, 0x80, 0xa1, 0x87, - 0x06, 0x90, 0x4b, 0xab, 0xa6, 0xb9, 0xc7, 0x2b, 0x17, 0xdc, 0xbe, 0xcf, 0xe2, 0x34, 0x5e, 0xc1, 0x41, 0xb0, 0x41, - 0xe3, 0xac, 0x02, 0x38, 0x55, 0xe0, 0x3d, 0xa3, 0x92, 0x66, 0xa5, 0xfc, 0x07, 0xe7, 0x1f, 0x61, 0xd0, 0x10, 0xd2, - 0x46, 0x45, 0x06, 0x3a, 0x59, 0xe9, 0xc8, 0x46, 0xe8, 0xbf, 0xd9, 0x8c, 0x83, 0xe3, 0xc3, 0xe8, 0xf5, 0xfb, 0x61, - 0xc1, 0x44, 0x58, 0x10, 0x42, 0xff, 0x0c, 0x0b, 0x70, 0x28, 0x29, 0x98, 0x97, 0xcf, 0xf8, 0x9e, 0x6b, 0xa3, 0xb0, - 0x10, 0x44, 0x77, 0x91, 0x7d, 0x40, 0xd5, 0xa3, 0xef, 0xd0, 0x0d, 0xf1, 0xb2, 0xc2, 0x82, 0xa1, 0x55, 0x0d, 0xcc, - 0x10, 0x14, 0xff, 0x86, 0x87, 0x12, 0x7c, 0xe2, 0x01, 0x3e, 0x7a, 0x4c, 0x66, 0x5c, 0x5d, 0x6b, 0x4f, 0x2e, 0xc2, - 0x82, 0x06, 0xba, 0xed, 0x10, 0x74, 0x20, 0xf2, 0x5f, 0x80, 0xa7, 0xc0, 0xc0, 0x87, 0x85, 0x5d, 0xca, 0x5d, 0x7f, - 0xf5, 0x5f, 0x0d, 0xeb, 0xe8, 0xc2, 0x8f, 0xfe, 0x6a, 0x5d, 0xd8, 0x33, 0x32, 0x95, 0x87, 0xe5, 0x70, 0x32, 0x1d, - 0x0c, 0xa4, 0x8b, 0xe3, 0x76, 0x9c, 0xcd, 0x7f, 0x9d, 0xcb, 0xc5, 0x02, 0x75, 0xdf, 0x38, 0xaf, 0x33, 0xfd, 0x37, - 0xd2, 0xce, 0x07, 0x6f, 0x8e, 0x7f, 0x3f, 0x3b, 0x3d, 0x7e, 0x05, 0xce, 0x07, 0x1f, 0x5e, 0x7e, 0xff, 0xf2, 0xbd, - 0x0a, 0xee, 0xae, 0xe6, 0xbc, 0xdf, 0x77, 0x52, 0x9f, 0x90, 0x0f, 0x2b, 0xb2, 0x1f, 0xc6, 0x8f, 0x0b, 0x65, 0xf4, - 0x40, 0x0e, 0x99, 0x85, 0x42, 0x86, 0x2a, 0x6a, 0xfb, 0xbb, 0x1c, 0x4e, 0x3c, 0x30, 0x8b, 0xbb, 0x86, 0x08, 0xd7, - 0x6f, 0xb9, 0x0d, 0xb2, 0x26, 0x8f, 0xbc, 0x7e, 0x70, 0x32, 0x95, 0x8e, 0x2d, 0x2c, 0x18, 0x94, 0x0d, 0x6d, 0x3a, - 0xce, 0xe6, 0xc5, 0xc2, 0xb6, 0xcb, 0x2d, 0x90, 0x51, 0x9a, 0x5d, 0x5c, 0x84, 0x0a, 0xba, 0xfa, 0x08, 0x34, 0x00, - 0xa6, 0x51, 0x85, 0x6b, 0x11, 0x9f, 0xf9, 0xe5, 0x47, 0x63, 0xaf, 0x79, 0xb7, 0xa8, 0x7b, 0x32, 0xcd, 0xaa, 0x1a, - 0x03, 0x3a, 0x98, 0x50, 0xee, 0x06, 0xdd, 0x04, 0x93, 0x51, 0x6d, 0xf9, 0x75, 0x5e, 0x2d, 0x4c, 0x73, 0xdc, 0x30, - 0x54, 0x5e, 0xc9, 0x6b, 0xd9, 0x40, 0x64, 0x20, 0x19, 0x86, 0x3d, 0x1a, 0xa3, 0x48, 0x7d, 0x6f, 0xd7, 0x3b, 0x7e, - 0x93, 0x4b, 0x88, 0xa6, 0x98, 0x81, 0x74, 0xfe, 0x58, 0x28, 0xe7, 0x72, 0xc9, 0xf8, 0x5c, 0x2c, 0x8e, 0xc0, 0xed, - 0x7c, 0x2e, 0x16, 0x11, 0x06, 0xe5, 0xcb, 0x20, 0x56, 0x09, 0xd8, 0xbd, 0x38, 0x08, 0xdf, 0x4e, 0x68, 0x03, 0xbb, - 0x81, 0x24, 0x1b, 0x94, 0x76, 0xa5, 0x21, 0xca, 0x9d, 0xf2, 0x68, 0x83, 0xc8, 0x43, 0xac, 0x9a, 0x57, 0x6d, 0x4f, - 0x36, 0x73, 0x31, 0xc1, 0x55, 0x16, 0x33, 0x39, 0x8d, 0x0f, 0x59, 0x31, 0x8d, 0xa1, 0x94, 0x38, 0x4d, 0xc3, 0x98, - 0x4e, 0xa8, 0x20, 0x24, 0x61, 0x7c, 0x1e, 0x2f, 0x68, 0x82, 0x52, 0x82, 0x10, 0x42, 0x7e, 0x8c, 0xd0, 0x36, 0x07, - 0x96, 0xbc, 0xdd, 0x7e, 0x9e, 0x7e, 0x6e, 0xc7, 0x70, 0x19, 0x15, 0xa1, 0x1b, 0x74, 0xd6, 0xf0, 0x6f, 0x44, 0x05, - 0x8d, 0xb1, 0x62, 0x08, 0x02, 0x5e, 0x60, 0x54, 0xc2, 0x82, 0xc4, 0xac, 0x82, 0x28, 0x02, 0xe5, 0x3c, 0x5e, 0xb0, - 0x82, 0x36, 0x6d, 0x4e, 0x63, 0x6d, 0x12, 0xd4, 0x73, 0x58, 0x6a, 0x7b, 0x52, 0xa9, 0x10, 0x7b, 0x7c, 0x26, 0xa2, - 0x6b, 0x6d, 0x68, 0x00, 0x28, 0x50, 0x4a, 0x2e, 0x7e, 0xf3, 0xe5, 0x1e, 0x6e, 0x0a, 0xfa, 0x9f, 0x6d, 0x4c, 0xb4, - 0xb3, 0x5c, 0x1d, 0x7a, 0xf3, 0x05, 0x8d, 0xf3, 0x1c, 0x42, 0xb1, 0x19, 0x04, 0x72, 0x91, 0x55, 0x10, 0xd1, 0xe2, - 0x2e, 0x30, 0x21, 0xe1, 0xa0, 0x4d, 0xbf, 0x42, 0x6a, 0x43, 0x4c, 0xae, 0x3c, 0x31, 0xb0, 0xdb, 0x2a, 0x41, 0xc0, - 0x91, 0x9e, 0x67, 0x9f, 0x9a, 0x18, 0x6b, 0x9a, 0x9a, 0x99, 0x78, 0x1b, 0x0a, 0xd1, 0xa0, 0x05, 0xd1, 0x0c, 0xde, - 0x3f, 0x57, 0x1c, 0xaf, 0x3a, 0xf0, 0x03, 0xde, 0xb9, 0x38, 0xf3, 0x6a, 0xe6, 0x11, 0x39, 0xf5, 0x51, 0x8e, 0xe8, - 0x97, 0x3c, 0xac, 0x46, 0x3a, 0x19, 0x63, 0x25, 0x71, 0xd0, 0xdb, 0x60, 0xc1, 0x9c, 0xd0, 0x15, 0x0f, 0x2d, 0x1f, - 0xff, 0x0a, 0x99, 0x8c, 0x92, 0x1a, 0x2b, 0xba, 0xd2, 0x62, 0xc4, 0x79, 0x0d, 0xb3, 0x34, 0x59, 0xd1, 0xc5, 0x42, - 0x93, 0x66, 0xa1, 0x4c, 0x03, 0x7c, 0x02, 0x2d, 0x46, 0xee, 0xa1, 0xa6, 0x0d, 0x84, 0x86, 0xdd, 0x21, 0xe0, 0x23, - 0xf7, 0xd0, 0xe1, 0xff, 0xe7, 0xd9, 0x05, 0x22, 0xed, 0xcd, 0x4d, 0x64, 0x3c, 0x52, 0x37, 0x70, 0x50, 0x8c, 0x8f, - 0x7d, 0x33, 0xf1, 0x0b, 0x67, 0xf4, 0x21, 0xa9, 0x7c, 0x87, 0x0f, 0x96, 0x3f, 0xde, 0xd4, 0xcc, 0xca, 0x08, 0xd6, - 0xc3, 0x76, 0x8b, 0x0b, 0xa2, 0xed, 0x02, 0x48, 0x3d, 0xe3, 0xd5, 0xc2, 0x37, 0x5e, 0x8d, 0xef, 0x31, 0x5e, 0x75, - 0x67, 0x6a, 0x98, 0x93, 0x0d, 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, 0x6e, - 0xb7, 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, 0x5f, 0xc4, 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, 0x21, 0xbb, 0xe2, 0x65, 0x15, 0x5f, 0xad, 0x8c, 0x25, 0x31, - 0x67, 0xf7, 0xb9, 0xed, 0x51, 0x61, 0x5e, 0xbd, 0x7d, 0xf9, 0xfd, 0x71, 0xe3, 0xd5, 0x2e, 0xe2, 0x68, 0x08, 0xb6, - 0x15, 0x63, 0x8c, 0xde, 0xe2, 0xd3, 0x60, 0xa2, 0x5c, 0x23, 0xd0, 0xbb, 0x14, 0xf4, 0xdb, 0x5f, 0xea, 0x09, 0x78, - 0xc5, 0xf5, 0xf2, 0x4b, 0x3e, 0x02, 0x96, 0xa8, 0xd0, 0xb3, 0xc2, 0xdc, 0xac, 0xcc, 0xee, 0xed, 0x56, 0x64, 0xa6, - 0x5d, 0x69, 0x64, 0x20, 0x5e, 0x6d, 0x87, 0xb1, 0x70, 0xe9, 0x9a, 0x6e, 0x07, 0xbb, 0x5a, 0x7a, 0x96, 0xc8, 0xdb, - 0x6d, 0x09, 0x1d, 0xb2, 0x03, 0xee, 0xbd, 0x8c, 0x6f, 0xe1, 0x65, 0xe9, 0x75, 0xb3, 0x19, 0x3c, 0x01, 0xcc, 0x84, - 0x0b, 0x67, 0x59, 0x1c, 0x33, 0x9e, 0x84, 0x2a, 0x36, 0x57, 0x43, 0xe4, 0xad, 0x08, 0xad, 0xd9, 0x5f, 0xa1, 0x18, - 0x81, 0xdd, 0xc9, 0xe9, 0xc7, 0x6c, 0x35, 0x5b, 0x02, 0x6a, 0xfe, 0x55, 0x26, 0x80, 0xe6, 0xda, 0xb5, 0x60, 0x9b, - 0x42, 0x9b, 0xeb, 0xfa, 0x79, 0xbc, 0x8a, 0x13, 0x50, 0xdd, 0x80, 0xb7, 0xc8, 0x9d, 0x16, 0x5d, 0x19, 0x74, 0x51, - 0xfa, 0x40, 0x39, 0x96, 0x14, 0x3a, 0xfa, 0xde, 0x13, 0xea, 0xdc, 0x33, 0x80, 0x4b, 0x1a, 0x35, 0x4f, 0xb5, 0x94, - 0xb1, 0x00, 0x58, 0xe8, 0x60, 0xa6, 0xc8, 0x56, 0x74, 0x6b, 0x30, 0x29, 0xe0, 0xad, 0x01, 0xfe, 0x10, 0x59, 0xa5, - 0xee, 0x8a, 0x65, 0x58, 0x7a, 0xf6, 0xd7, 0xfd, 0x7e, 0xec, 0xd9, 0x5f, 0x5f, 0x68, 0x5a, 0x17, 0xb7, 0x1b, 0x40, - 0x6a, 0x0c, 0x20, 0x72, 0xac, 0x07, 0xc2, 0x44, 0x14, 0x6b, 0xfa, 0xfe, 0x1d, 0x9b, 0x2c, 0x0a, 0x84, 0x7e, 0xa7, - 0x5e, 0x4f, 0x4a, 0x02, 0x3a, 0xb5, 0x8a, 0x1d, 0x0d, 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, - 0xfb, 0xbf, 0x99, 0x2c, 0x08, 0x6a, 0xae, 0xfc, 0x40, 0x8e, 0x3b, 0x99, 0x1a, 0x7b, 0xaa, 0x51, 0x83, 0x60, 0x32, - 0x82, 0xc0, 0x70, 0xc3, 0x2f, 0xf8, 0xf8, 0x60, 0x41, 0x40, 0x45, 0x66, 0xcd, 0x42, 0xcc, 0x8b, 0xc3, 0x27, 0x80, - 0x1a, 0x33, 0x3a, 0x78, 0x06, 0xa0, 0xb0, 0x10, 0x10, 0x7d, 0x0c, 0x32, 0x5a, 0x01, 0xbf, 0x85, 0xfa, 0xdd, 0x3a, - 0xf1, 0x7d, 0xe8, 0x57, 0x41, 0x2f, 0x62, 0x60, 0x38, 0xa2, 0xc9, 0x7e, 0xc8, 0x07, 0x93, 0x01, 0x68, 0x4b, 0xbc, - 0xdd, 0xd7, 0xd2, 0x8a, 0x9b, 0xd3, 0xa5, 0xd3, 0xfd, 0x93, 0x36, 0x41, 0x12, 0xa9, 0x64, 0xa5, 0x22, 0x06, 0x10, - 0xca, 0x52, 0x6d, 0x93, 0x25, 0x58, 0x56, 0x98, 0x25, 0xcd, 0x0d, 0x4a, 0xe2, 0xee, 0x66, 0xe0, 0x18, 0x35, 0xeb, - 0x38, 0x2c, 0x5b, 0x6e, 0xd4, 0x00, 0x9f, 0x93, 0xb0, 0xc2, 0xde, 0x70, 0x66, 0xd2, 0x3b, 0xd3, 0xe1, 0xea, 0x98, - 0xb3, 0x37, 0x1c, 0xc1, 0x38, 0x12, 0xbc, 0xf1, 0xd0, 0x25, 0xd3, 0x50, 0x91, 0x29, 0xe3, 0x60, 0xda, 0x03, 0xdc, - 0x7b, 0x0e, 0xc6, 0x61, 0x6c, 0x50, 0x59, 0x52, 0x9f, 0x7a, 0x77, 0x21, 0x10, 0xa4, 0xb5, 0x5e, 0xe6, 0x33, 0x3c, - 0x3d, 0x23, 0x94, 0xfd, 0x21, 0x87, 0x2f, 0xc0, 0x8e, 0x82, 0x1c, 0x4d, 0xf8, 0xb3, 0xc7, 0xbb, 0x81, 0xaa, 0xf8, - 0x20, 0xd8, 0x8b, 0x45, 0xba, 0x17, 0x0c, 0x04, 0xfc, 0x2a, 0xf8, 0x5e, 0x25, 0xe5, 0xde, 0x45, 0x5c, 0xec, 0xc5, - 0xab, 0xb8, 0xa8, 0xf6, 0x6e, 0xb2, 0x6a, 0xb9, 0x67, 0x3a, 0x04, 0xd0, 0xbc, 0xc1, 0x20, 0x1e, 0x04, 0x7b, 0xc1, - 0xa0, 0x30, 0x53, 0xbb, 0x62, 0x65, 0xe3, 0x38, 0x33, 0x21, 0xca, 0x82, 0x66, 0x80, 0xb0, 0xc6, 0x69, 0x00, 0x7c, - 0xea, 0x9a, 0xa5, 0xf4, 0x02, 0xc3, 0x0d, 0x88, 0xe9, 0x1a, 0xfa, 0x00, 0x3c, 0xf2, 0x9a, 0xc6, 0xb0, 0x04, 0x2e, - 0x06, 0x03, 0xb2, 0x86, 0xc8, 0x05, 0x6b, 0x6a, 0x83, 0x38, 0x84, 0x6b, 0x65, 0xa7, 0xbd, 0x0b, 0xcc, 0xb4, 0xdd, - 0x02, 0xa2, 0xf2, 0x84, 0xf4, 0xfb, 0xf6, 0x1b, 0xea, 0x5f, 0xb0, 0x97, 0x60, 0x7f, 0x55, 0x54, 0x61, 0x22, 0x95, - 0xe6, 0xfb, 0x92, 0x1d, 0x0d, 0x54, 0xc4, 0xe1, 0x1d, 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, 0xaf, 0x34, 0xbb, 0xf4, 0x30, 0x90, 0x32, - 0x6e, 0x0f, 0x2d, 0x61, 0xd2, 0xf2, 0x22, 0xbc, 0xf7, 0x9a, 0x9b, 0xdc, 0x8b, 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, 0xcf, 0x74, 0x17, 0x80, 0xd1, 0x2f, 0x66, 0x69, 0xb4, 0xbc, 0xd7, 0xcc, 0x02, 0xc9, 0x33, 0xf4, 0x5d, - 0x07, 0xdb, 0x1b, 0xfb, 0x20, 0xe5, 0xfc, 0x50, 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, 0x3f, 0x91, 0x6f, 0x72, 0x07, 0x5d, 0x2e, 0xc7, - 0x9a, 0xb7, 0x1c, 0x80, 0x8a, 0x7e, 0xa4, 0xa8, 0xee, 0x17, 0x38, 0xc2, 0x3c, 0x58, 0xb7, 0xf9, 0x64, 0xdf, 0x14, - 0x38, 0x44, 0x9e, 0xb4, 0xd1, 0x14, 0xd0, 0xbd, 0x8b, 0xc7, 0x5d, 0xfd, 0xb6, 0x74, 0x17, 0x28, 0xd1, 0x4e, 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, - 0xeb, 0x33, 0x8e, 0xa2, 0x1f, 0xa3, 0x46, 0xbe, 0x89, 0xc4, 0x63, 0x39, 0x88, 0x1f, 0x17, 0x74, 0x19, 0x89, 0xc7, - 0xc5, 0x20, 0x7e, 0x2c, 0xeb, 0x7a, 0xf7, 0x5c, 0xb9, 0xbf, 0x8f, 0xc8, 0xb3, 0xee, 0xec, 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, 0xfd, 0x62, 0x74, 0xe3, 0xbb, 0xeb, 0xef, 0x17, 0xa3, 0x25, 0x19, 0x4e, 0xcc, 0xe4, 0xc7, 0x47, 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, 0xdf, 0xab, 0x76, 0xb4, 0x69, 0x6f, 0xe2, 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, 0x4d, 0xd9, 0xfc, 0x2a, 0xda, 0xe7, 0xc8, 0x48, - 0xd9, 0x26, 0x23, 0x15, 0x18, 0x61, 0x4a, 0x91, 0xc4, 0x55, 0x08, 0x81, 0xec, 0xbf, 0xa4, 0xb8, 0x16, 0x4b, 0xef, - 0x35, 0x08, 0x13, 0x6c, 0x17, 0xb4, 0x5f, 0xdd, 0xce, 0x6d, 0xa5, 0xc5, 0x1e, 0xa9, 0xef, 0x73, 0x67, 0xbb, 0xa2, - 0xc9, 0xdf, 0x97, 0x0d, 0x68, 0x03, 0x88, 0xf2, 0xbe, 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, 0x80, - 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, 0x53, 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, 0x11, 0xcb, 0xe6, 0x62, 0x31, 0x5a, 0x49, 0x08, 0x1b, 0x7c, 0xc8, 0xb2, 0x79, 0xa9, - 0x1f, 0x42, 0x5f, 0x58, 0x7a, 0x02, 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, 0x23, 0xd4, - 0xfe, 0x7e, 0x1e, 0xc5, 0x5a, 0x2e, 0xb9, 0x72, 0x7e, 0xf1, 0x37, 0x9f, 0xb1, 0xd7, 0x3d, 0xc3, 0x60, 0x01, 0xce, - 0xd2, 0xf6, 0x2a, 0x13, 0xef, 0x64, 0x2b, 0x38, 0x0e, 0x66, 0x51, 0x0e, 0xab, 0x9e, 0x1c, 0xd1, 0x5c, 0xe4, 0xda, - 0xbb, 0x08, 0x91, 0x83, 0xcc, 0x1e, 0x03, 0xec, 0x46, 0xf8, 0x3a, 0xb4, 0x36, 0xb7, 0xba, 0x42, 0xfc, 0x8d, 0x12, - 0x89, 0x9f, 0xa5, 0xfc, 0xb8, 0x5e, 0xa9, 0x5c, 0x95, 0xc1, 0x63, 0xd5, 0xcd, 0xe0, 0x99, 0xf6, 0x3d, 0xd6, 0xfe, - 0xad, 0xed, 0xe6, 0x78, 0xef, 0xc1, 0x83, 0xd6, 0xff, 0xd6, 0x93, 0x10, 0xda, 0x2b, 0x27, 0xa9, 0x3b, 0x6a, 0xf4, - 0xcc, 0x64, 0x8d, 0xa8, 0x84, 0xa9, 0xdd, 0xa9, 0x1c, 0x03, 0x35, 0x1d, 0xc0, 0xb5, 0x44, 0x4d, 0xd0, 0x93, 0x82, - 0x8d, 0xe1, 0x88, 0xb3, 0x38, 0x68, 0x87, 0x31, 0x8a, 0x97, 0x73, 0x25, 0x5e, 0xce, 0x8f, 0x18, 0x07, 0x68, 0x2d, - 0x40, 0xaa, 0xd7, 0xb0, 0x9f, 0xb9, 0x82, 0x05, 0x36, 0x77, 0xbe, 0x03, 0x0b, 0x64, 0x88, 0x93, 0xcd, 0x71, 0xb2, - 0xc7, 0xb5, 0x9e, 0x7b, 0x81, 0x8f, 0x93, 0x7a, 0xe1, 0xd5, 0x55, 0xb6, 0xeb, 0x5a, 0xb2, 0x72, 0x5e, 0x0c, 0x26, - 0x10, 0x94, 0xa5, 0x9c, 0x17, 0xc3, 0xc9, 0x82, 0xe6, 0xf0, 0x63, 0xd1, 0x40, 0x87, 0x58, 0x0e, 0x12, 0xb8, 0x74, - 0xf6, 0x18, 0xf0, 0x86, 0x52, 0x8b, 0xbb, 0xb1, 0x8e, 0x1c, 0xeb, 0x28, 0xf6, 0xc3, 0x18, 0x70, 0x65, 0x9d, 0xc0, - 0xfb, 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, 0x1d, 0x95, 0x43, - 0x2d, 0x84, 0xeb, 0x5a, 0x78, 0x1d, 0xa7, 0x65, 0x0c, 0x2e, 0xd2, 0xda, 0x36, 0xf1, 0x1e, 0xba, 0xee, 0xf9, 0x31, - 0xb7, 0x3a, 0x46, 0x5b, 0x48, 0xbf, 0x1d, 0x9d, 0xde, 0x73, 0x18, 0x80, 0xa6, 0x07, 0xb3, 0xaa, 0x7d, 0x26, 0x71, - 0x73, 0xda, 0x09, 0x42, 0x22, 0x10, 0x45, 0xe9, 0x8c, 0x30, 0xfd, 0x3b, 0xcd, 0x65, 0x15, 0xad, 0x1e, 0xe4, 0x99, - 0x43, 0x9e, 0x85, 0xde, 0xf6, 0xa0, 0x55, 0x73, 0x37, 0x18, 0x27, 0x6e, 0xb7, 0x77, 0xfe, 0xdf, 0xb2, 0xae, 0xad, - 0xd6, 0x88, 0xc7, 0xed, 0xea, 0x07, 0x8d, 0xbd, 0xda, 0x53, 0x31, 0x60, 0x56, 0xd2, 0x3b, 0xa3, 0x4a, 0x5e, 0x64, - 0xbc, 0xc4, 0x93, 0x6a, 0xd5, 0xf0, 0xf1, 0xbe, 0xc9, 0x46, 0xe6, 0x81, 0x4c, 0x01, 0xf1, 0xfc, 0x26, 0x35, 0xea, - 0xe3, 0x14, 0x25, 0xe0, 0xef, 0x74, 0x7c, 0x23, 0xfa, 0xd1, 0xbe, 0xb8, 0xe4, 0xd5, 0xc9, 0x8d, 0x30, 0x2f, 0x5e, - 0x58, 0x9d, 0x3f, 0x7d, 0x53, 0xf8, 0xd0, 0xe1, 0xa8, 0xbd, 0x83, 0x22, 0x4b, 0x26, 0x8e, 0x26, 0x46, 0xd6, 0x26, - 0x66, 0x1f, 0x15, 0x5c, 0x4c, 0x54, 0xa1, 0x67, 0x9d, 0x3d, 0x61, 0x0a, 0xd0, 0x37, 0x8e, 0x51, 0xc9, 0x18, 0x16, - 0x0c, 0xd4, 0x69, 0x4a, 0x88, 0x1e, 0x8a, 0x19, 0xc6, 0x2b, 0x06, 0x50, 0x98, 0x42, 0x81, 0x28, 0x3a, 0xfb, 0x70, - 0xa0, 0x09, 0xfd, 0xfe, 0x4d, 0xaa, 0x33, 0xd0, 0xb2, 0x9e, 0x4a, 0x10, 0xd5, 0x41, 0xb4, 0x55, 0x5e, 0x84, 0x3f, - 0x2e, 0x69, 0x99, 0xd1, 0xa5, 0xa0, 0xa9, 0xa0, 0x49, 0x46, 0x2f, 0xb8, 0x12, 0x15, 0x5f, 0x08, 0xa6, 0x68, 0xbb, - 0x21, 0xec, 0xff, 0x6a, 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, 0x9d, 0xae, 0xcf, 0x9f, 0xcb, 0xab, 0x95, 0x14, 0x5c, 0x54, 0x0a, 0xa2, 0xdf, 0xe0, 0xbe, 0x9b, 0xb8, - 0xea, 0xac, 0x59, 0x2b, 0x7d, 0xe8, 0x5b, 0x9f, 0xb5, 0x71, 0x5f, 0x18, 0x1c, 0x83, 0x9d, 0x8f, 0x88, 0x81, 0x34, - 0xa8, 0x74, 0x8b, 0x43, 0x13, 0xa0, 0x4b, 0x87, 0x14, 0xb2, 0x64, 0x2a, 0x53, 0x25, 0xa8, 0xf8, 0xc6, 0xef, 0xa5, - 0xac, 0x46, 0x7f, 0xad, 0x79, 0x71, 0x77, 0xca, 0x73, 0x8e, 0x63, 0x14, 0x24, 0xb1, 0xb8, 0x8e, 0xcb, 0x80, 0xf8, - 0x96, 0x57, 0xc1, 0x41, 0x6a, 0xc2, 0xc6, 0xec, 0x54, 0x8d, 0x5a, 0x2f, 0x89, 0xbe, 0x32, 0xca, 0x37, 0x06, 0x43, - 0x13, 0x51, 0x05, 0x7d, 0xaf, 0xd5, 0x3d, 0xad, 0x6e, 0x58, 0x40, 0xfc, 0xb9, 0xd2, 0x0b, 0xb5, 0x5e, 0x37, 0x63, - 0x6e, 0x98, 0x08, 0x41, 0xa3, 0x27, 0xf5, 0xa2, 0xf6, 0xdc, 0xd2, 0x54, 0x64, 0xdc, 0x68, 0x93, 0xf3, 0x4b, 0x90, - 0xf1, 0x39, 0x73, 0xa1, 0x49, 0x5d, 0x53, 0x05, 0x55, 0x18, 0x6d, 0x6e, 0x1b, 0xe9, 0xf4, 0x0e, 0xdc, 0xd9, 0x8c, - 0xd9, 0x91, 0x76, 0x69, 0xac, 0x69, 0xc1, 0xcb, 0x95, 0x14, 0x25, 0x84, 0x71, 0xee, 0x8d, 0xe9, 0x55, 0x9c, 0x89, - 0x2a, 0xce, 0xc4, 0x71, 0xb9, 0xe2, 0x49, 0xf5, 0x1e, 0x6e, 0x71, 0xca, 0xea, 0xa6, 0x2e, 0xe1, 0x4a, 0x97, 0xec, - 0x61, 0x30, 0x35, 0x15, 0xf7, 0xd8, 0x19, 0x5c, 0x54, 0x7f, 0x44, 0x4b, 0x89, 0xb1, 0x50, 0x75, 0xf1, 0xf1, 0x79, - 0x29, 0xf3, 0x75, 0x05, 0xda, 0xdd, 0x8b, 0x2a, 0x3a, 0x78, 0xba, 0xba, 0x9d, 0xaa, 0x1b, 0x4c, 0xf4, 0xf4, 0x60, - 0x75, 0xdb, 0xcb, 0xae, 0x56, 0xb2, 0xa8, 0x62, 0x51, 0x4d, 0x15, 0x22, 0x59, 0x12, 0xe7, 0x49, 0x38, 0x19, 0x8f, - 0xbf, 0xda, 0x1b, 0xee, 0x41, 0x06, 0x32, 0xfd, 0x34, 0x54, 0x2e, 0x47, 0xc3, 0xc9, 0x78, 0x3c, 0x95, 0xea, 0x6e, - 0x17, 0x8d, 0x26, 0x35, 0xd6, 0x33, 0x4c, 0xf4, 0xcc, 0x8c, 0xf8, 0xed, 0x2a, 0x16, 0x29, 0xc4, 0xaf, 0xd3, 0xc5, - 0x1f, 0x3c, 0x1d, 0x37, 0xca, 0xb7, 0x9f, 0x3e, 0xab, 0xff, 0xa8, 0x4d, 0x58, 0x6b, 0xd3, 0xee, 0xe7, 0x7f, 0x1c, - 0xaa, 0xf9, 0x3e, 0x3a, 0xdc, 0xd7, 0x3f, 0xfe, 0xa8, 0xeb, 0xe9, 0x9b, 0x22, 0x9c, 0xff, 0x33, 0x54, 0xf3, 0x79, - 0x5c, 0x14, 0xf1, 0x5d, 0x0d, 0x91, 0x3c, 0x85, 0xf3, 0x26, 0xa1, 0xde, 0x36, 0xa0, 0x07, 0x64, 0x7a, 0x21, 0x18, - 0x7c, 0xf3, 0xbe, 0x0a, 0x03, 0x5e, 0xae, 0x86, 0x5c, 0x54, 0x59, 0x75, 0x37, 0xc4, 0x3c, 0x01, 0x7e, 0x6a, 0x78, - 0xb3, 0xe7, 0x85, 0x21, 0x36, 0x17, 0x05, 0xe7, 0x9f, 0x78, 0xa8, 0x8c, 0xa3, 0xc7, 0x68, 0x1c, 0x3d, 0xa6, 0x6a, - 0x30, 0x26, 0xdf, 0x50, 0xdd, 0x99, 0xc9, 0x37, 0x60, 0x82, 0x94, 0xb5, 0xbf, 0x51, 0xc6, 0x89, 0xd1, 0x98, 0x5e, - 0xbf, 0xca, 0xb3, 0x15, 0x30, 0xc1, 0x4b, 0xfd, 0xa3, 0x26, 0xf4, 0x3d, 0x6f, 0x67, 0x1f, 0x8d, 0x46, 0xcf, 0x0b, - 0x3a, 0x1a, 0x8d, 0x3e, 0x66, 0x35, 0xa1, 0x2b, 0xd1, 0xf1, 0xfe, 0x3d, 0xa7, 0xe7, 0x32, 0xbd, 0x8b, 0x82, 0x80, - 0x2e, 0xb3, 0x34, 0xe5, 0x42, 0x95, 0x75, 0x9a, 0xb6, 0xf3, 0xaa, 0x16, 0x22, 0xf0, 0x8f, 0x6e, 0x23, 0x42, 0x10, - 0x11, 0x7a, 0xb2, 0xd3, 0xb3, 0xd1, 0x68, 0x74, 0x9a, 0x9a, 0x6a, 0x1d, 0x43, 0xfe, 0x06, 0xcd, 0x07, 0x9c, 0x5d, - 0x3e, 0x58, 0xdf, 0x98, 0x68, 0x27, 0xfb, 0xff, 0x3d, 0x9c, 0xcd, 0xc7, 0xc3, 0x6f, 0x47, 0x8b, 0xc7, 0xfb, 0x34, - 0x08, 0x7c, 0xd0, 0xea, 0x50, 0x5b, 0x73, 0x4c, 0xcb, 0xc3, 0xf1, 0x94, 0x94, 0x03, 0xf6, 0xd4, 0xfa, 0xd2, 0x7c, - 0xf5, 0x14, 0x90, 0x48, 0x51, 0x84, 0x1a, 0x38, 0xe9, 0x1f, 0x5e, 0x45, 0x5e, 0x0b, 0xc0, 0x47, 0xb3, 0x91, 0x0c, - 0x8c, 0x16, 0x70, 0x1c, 0x41, 0x79, 0xb5, 0x35, 0x8d, 0xe8, 0x31, 0x96, 0x99, 0xa8, 0xa0, 0xe3, 0x69, 0x79, 0x93, - 0x55, 0xc9, 0x12, 0x03, 0x1b, 0xc5, 0x25, 0x0f, 0xbe, 0x0a, 0xa2, 0x92, 0x1d, 0x3c, 0x9b, 0x2a, 0x78, 0x5f, 0x4c, - 0x4a, 0xf9, 0x25, 0x24, 0x7e, 0x3b, 0x46, 0x08, 0x54, 0xa2, 0x3d, 0x16, 0xb1, 0xc6, 0x57, 0xb9, 0x8c, 0xc1, 0x83, - 0xb3, 0xd4, 0x3c, 0x8b, 0x3d, 0x09, 0xac, 0xfd, 0x45, 0xab, 0x39, 0x12, 0x9a, 0x13, 0x4a, 0x26, 0xf7, 0x4b, 0x2a, - 0xbf, 0x9a, 0xa0, 0x57, 0x10, 0xb8, 0x55, 0x47, 0x70, 0xdc, 0x59, 0xcb, 0x06, 0xbd, 0x7c, 0x52, 0xb6, 0x3f, 0xff, - 0xdf, 0x25, 0x5d, 0x0c, 0xf6, 0xdd, 0xd0, 0x9c, 0x68, 0xf7, 0xd5, 0x0a, 0x19, 0xa5, 0x2a, 0x7c, 0x9e, 0x12, 0x6b, - 0x7c, 0xca, 0xd9, 0xd1, 0xc6, 0x74, 0x67, 0x54, 0x15, 0xd9, 0x55, 0x48, 0x74, 0xaf, 0x1c, 0x28, 0x66, 0x10, 0x65, - 0x23, 0x5c, 0x3f, 0x60, 0x2d, 0xe2, 0x75, 0xf2, 0x9a, 0x17, 0x55, 0x96, 0xa8, 0xf7, 0xd7, 0x8d, 0xf7, 0x40, 0x0d, - 0x54, 0x83, 0xde, 0x15, 0x0c, 0xe6, 0xf9, 0xa4, 0x00, 0xd0, 0xce, 0x92, 0x17, 0xd7, 0xdc, 0xa7, 0x1b, 0x41, 0x50, - 0xbb, 0x66, 0x5e, 0x36, 0x82, 0x4d, 0xc0, 0x57, 0xef, 0x0a, 0xc0, 0xdc, 0x08, 0x41, 0x6a, 0x0a, 0xa1, 0x70, 0xe0, - 0x02, 0x5f, 0x55, 0x45, 0x76, 0xbe, 0xae, 0x38, 0x06, 0xfb, 0xf0, 0xe2, 0x26, 0x2a, 0x27, 0x3c, 0x1e, 0x06, 0xf8, - 0x23, 0xa0, 0x2a, 0xe0, 0x86, 0xf1, 0xb0, 0x83, 0x17, 0xea, 0x97, 0x7b, 0xa3, 0xf6, 0x08, 0x7b, 0x93, 0x86, 0x10, - 0x5c, 0x07, 0x1f, 0x02, 0x58, 0x52, 0x84, 0x9e, 0xe0, 0xa9, 0x1a, 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, 0x28, 0xef, - 0xf4, 0xc4, 0xb8, 0x30, 0x7d, 0x1c, 0x22, 0xbf, 0xbc, 0x2b, 0x54, 0xe8, 0x17, 0xbe, 0x00, 0xf0, 0x2b, 0xb8, 0xdd, - 0xef, 0xc6, 0x77, 0x51, 0xd9, 0xcf, 0x38, 0xdb, 0xff, 0xef, 0x79, 0x3c, 0xfc, 0x34, 0x1e, 0x7e, 0xbb, 0x18, 0x84, - 0x43, 0xfb, 0x93, 0x3c, 0x7e, 0xb4, 0x4f, 0x5f, 0x71, 0xcb, 0x95, 0xc0, 0xc2, 0x6f, 0x04, 0xb7, 0x51, 0x2b, 0x21, - 0x88, 0x02, 0xbc, 0x51, 0xb8, 0xd5, 0x38, 0x01, 0x80, 0xbf, 0xe0, 0xbf, 0x02, 0x34, 0x12, 0x72, 0x17, 0x0d, 0xd0, - 0x0f, 0xa8, 0xdf, 0x47, 0x4f, 0x1a, 0x06, 0x72, 0x20, 0x9e, 0x50, 0x31, 0x50, 0x88, 0x2e, 0x63, 0xa2, 0x60, 0x7f, - 0x6d, 0xf6, 0xed, 0xb6, 0xd7, 0x96, 0xfc, 0xe0, 0x97, 0x7e, 0xa6, 0x89, 0x99, 0x77, 0xb8, 0xa1, 0xac, 0xe4, 0x2a, - 0x44, 0x6c, 0x3c, 0xfd, 0x2b, 0x67, 0x10, 0x6b, 0xf2, 0x3a, 0x03, 0x1f, 0x06, 0xfb, 0xc5, 0x78, 0x06, 0x6c, 0x03, - 0xdc, 0x71, 0x0a, 0x7e, 0x91, 0x81, 0x5b, 0xb3, 0x88, 0xf1, 0x82, 0x6d, 0x97, 0x44, 0xbf, 0xdf, 0xcb, 0xb3, 0x30, - 0xd7, 0x38, 0xcb, 0x79, 0x6d, 0xc4, 0xee, 0xa8, 0x13, 0x06, 0x71, 0xbb, 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, 0xb8, 0x2e, 0xb3, 0x5e, 0x2f, 0x0c, 0xd1, 0xa1, 0x11, 0x4b, 0xc5, - 0xda, 0x20, 0xbc, 0x8f, 0x49, 0x18, 0x5d, 0x81, 0xac, 0x2e, 0x3c, 0xe3, 0x04, 0xf9, 0x32, 0x30, 0x59, 0x53, 0xd5, - 0x7a, 0x39, 0xe1, 0xb1, 0x91, 0x2f, 0x1b, 0x41, 0x83, 0xbc, 0xa4, 0xa8, 0x37, 0x71, 0x3b, 0xf6, 0x51, 0x0b, 0xa9, - 0x71, 0x53, 0x4f, 0x7b, 0x9a, 0x54, 0xf4, 0x58, 0xaf, 0x52, 0xbf, 0xc0, 0xb2, 0xc0, 0x92, 0x0f, 0x42, 0x7b, 0x9a, - 0x56, 0x60, 0x86, 0x6b, 0x9b, 0xc1, 0xd0, 0x0f, 0x87, 0xb6, 0x08, 0x9d, 0x51, 0xdb, 0x12, 0xc2, 0xb6, 0x0d, 0xc2, - 0xca, 0x7b, 0x22, 0x5f, 0x3d, 0xf5, 0x18, 0xe1, 0x90, 0x9b, 0xcd, 0x2c, 0x1a, 0x18, 0xe6, 0x57, 0xb2, 0xd9, 0x3c, - 0xdd, 0x5c, 0x2f, 0x2a, 0xa6, 0x80, 0xed, 0xb6, 0x12, 0x04, 0xff, 0x7e, 0xcc, 0x66, 0xf8, 0x37, 0xeb, 0xf7, 0x7b, - 0x21, 0xfe, 0xe2, 0x18, 0xbc, 0x67, 0x2e, 0x16, 0xec, 0x23, 0xc8, 0x54, 0x48, 0x84, 0xa9, 0xca, 0xf8, 0x8d, 0x55, - 0x60, 0x01, 0x67, 0x3e, 0x50, 0xb9, 0x30, 0x93, 0xbd, 0xbc, 0xb8, 0x86, 0x1c, 0xb7, 0xc6, 0x29, 0x1b, 0x65, 0x89, - 0x72, 0x5d, 0xc8, 0x46, 0x71, 0x9e, 0xc5, 0x25, 0x2f, 0xb7, 0x5b, 0x7d, 0x38, 0x26, 0x05, 0x07, 0xf6, 0x54, 0x51, - 0xa9, 0x92, 0x75, 0xa4, 0xba, 0xf1, 0x97, 0x61, 0x81, 0xfb, 0x94, 0xcf, 0x0b, 0x43, 0x23, 0xf6, 0xe0, 0xf2, 0xce, - 0xd4, 0xad, 0xb4, 0x17, 0x16, 0xd0, 0xbc, 0x92, 0x90, 0x0d, 0xa6, 0x7a, 0x16, 0xad, 0x31, 0x13, 0xf3, 0x62, 0x01, - 0x61, 0x64, 0x8a, 0x05, 0xd8, 0x4c, 0x71, 0x01, 0x5e, 0x24, 0x31, 0xc0, 0xc4, 0xc5, 0x64, 0x0a, 0xf1, 0xcc, 0x55, - 0x39, 0xf1, 0xc2, 0xdc, 0x2f, 0x13, 0x87, 0x94, 0x01, 0xaf, 0x6a, 0x83, 0x26, 0x66, 0x1b, 0x8e, 0x3a, 0x41, 0x4e, - 0x4c, 0x7e, 0x3f, 0x55, 0x10, 0xe2, 0x4e, 0x1c, 0x09, 0x97, 0x15, 0xdb, 0x85, 0x97, 0x1d, 0x88, 0x31, 0x6a, 0x70, - 0xca, 0xcf, 0x0c, 0x8e, 0xc6, 0xe0, 0xdc, 0x78, 0x27, 0x48, 0x11, 0xc6, 0x64, 0x23, 0xd9, 0x95, 0x0c, 0xc5, 0x3c, - 0x5e, 0x80, 0xb2, 0x2e, 0x5e, 0x80, 0x65, 0x8d, 0x31, 0xc0, 0x04, 0x79, 0x15, 0xf7, 0x42, 0x3f, 0x51, 0x5c, 0x21, - 0xd2, 0xb3, 0x72, 0x7d, 0x54, 0xb4, 0x43, 0x5f, 0xe0, 0xf5, 0x5e, 0x99, 0xe3, 0x66, 0x3d, 0x16, 0x48, 0x6c, 0x08, - 0x18, 0x1b, 0xe9, 0x34, 0xd5, 0x5a, 0xf7, 0xc6, 0xcc, 0x03, 0x9f, 0x66, 0x23, 0x21, 0xab, 0xb3, 0x0b, 0x10, 0xa1, - 0xf8, 0x68, 0xf0, 0xc8, 0x2f, 0xe2, 0xce, 0x32, 0x6f, 0x6d, 0x8b, 0x4a, 0x76, 0xb4, 0x01, 0x90, 0x3e, 0x1d, 0x2d, - 0x4a, 0xc9, 0x29, 0x4a, 0x52, 0xbb, 0x4d, 0x01, 0x2b, 0xc9, 0x5f, 0xc0, 0x10, 0x6c, 0x6c, 0x4f, 0x38, 0x9d, 0x22, - 0xc4, 0x27, 0x9a, 0x22, 0xb2, 0x62, 0x58, 0x52, 0x1c, 0xdb, 0x12, 0x51, 0x3f, 0x6d, 0x59, 0x76, 0x30, 0x4c, 0x54, - 0xdc, 0x17, 0xa9, 0x47, 0x89, 0x82, 0x80, 0xea, 0x21, 0x07, 0x89, 0xad, 0x6d, 0x20, 0x3c, 0x20, 0x8f, 0xe8, 0x8d, - 0xf5, 0xf7, 0x59, 0xe7, 0xd9, 0x85, 0xe6, 0xa8, 0x5c, 0xef, 0x0a, 0x33, 0x46, 0x78, 0x92, 0x19, 0x98, 0x7c, 0xef, - 0x3c, 0x33, 0x6a, 0x8a, 0x9e, 0x87, 0x4f, 0x76, 0x8c, 0x11, 0xe9, 0xee, 0x19, 0x74, 0x13, 0xbc, 0xaa, 0xc3, 0x46, - 0xbb, 0x52, 0x10, 0x12, 0xa6, 0x16, 0x4d, 0xcc, 0x7a, 0xd6, 0x80, 0x7a, 0xbb, 0xed, 0xe9, 0xb9, 0xba, 0x7f, 0xee, - 0xb6, 0xdb, 0x1e, 0x76, 0xeb, 0x45, 0xda, 0x6d, 0x05, 0x5e, 0xa9, 0x0f, 0xda, 0xe3, 0xcf, 0xdd, 0xf8, 0x73, 0x83, - 0xe4, 0x51, 0x3a, 0x9a, 0x69, 0xeb, 0x83, 0x70, 0xb8, 0xe9, 0x5d, 0xa3, 0x49, 0xdf, 0x67, 0xa1, 0xa4, 0x2b, 0xd1, - 0xa8, 0xae, 0x76, 0x26, 0x95, 0x0f, 0xae, 0xff, 0x87, 0x57, 0x01, 0x1e, 0x71, 0x6a, 0x67, 0xdf, 0xdb, 0xa0, 0xa2, - 0xd1, 0x16, 0x8e, 0x14, 0xa1, 0x07, 0x24, 0xe1, 0xbe, 0x96, 0xb5, 0xb8, 0xcd, 0xd3, 0xec, 0x61, 0xfa, 0xf4, 0x3a, - 0xf5, 0xad, 0xee, 0xdd, 0x32, 0xcb, 0xcc, 0x81, 0x57, 0x51, 0x1c, 0xd0, 0xa8, 0x8b, 0xf6, 0x5d, 0x65, 0x65, 0x09, - 0x5e, 0x1e, 0x70, 0x7d, 0x3e, 0xe5, 0x3e, 0xdc, 0xdc, 0x65, 0xd5, 0xdc, 0xa4, 0xa7, 0xd9, 0x3c, 0x5b, 0x6c, 0xb7, - 0x21, 0xfe, 0xed, 0x6a, 0x91, 0xa3, 0xc9, 0x73, 0xd0, 0xe1, 0x61, 0xe4, 0x1e, 0xa6, 0x1b, 0xe7, 0x6d, 0xfe, 0x4f, - 0xa2, 0xe1, 0x24, 0x70, 0x0c, 0xf4, 0x62, 0xf6, 0x08, 0x64, 0x30, 0xc6, 0xa9, 0x5f, 0xcc, 0xf4, 0x9a, 0x81, 0xe8, - 0x5b, 0x22, 0x02, 0x1c, 0x5d, 0x6c, 0x24, 0x1a, 0x59, 0x70, 0x52, 0x13, 0xb0, 0xd8, 0xb4, 0xe5, 0x7d, 0xb0, 0xb4, - 0xad, 0x2a, 0xee, 0xbc, 0x25, 0xcd, 0x71, 0x1d, 0x38, 0xdb, 0x7e, 0x33, 0xc4, 0xa6, 0xec, 0x6a, 0x81, 0xdc, 0x2f, - 0xaf, 0x69, 0x6f, 0x5c, 0x27, 0x30, 0x6b, 0x9b, 0xda, 0x32, 0x7e, 0xb6, 0xf4, 0x9f, 0xf5, 0xe0, 0x2a, 0xe3, 0xa7, - 0xb9, 0xb1, 0x4a, 0xb0, 0xfb, 0xc6, 0xf3, 0x1d, 0x80, 0x70, 0x6c, 0x3e, 0x3d, 0x3e, 0xcd, 0x3c, 0x7a, 0x0c, 0x44, - 0xc7, 0x7c, 0x54, 0xba, 0x8f, 0xec, 0xee, 0xf5, 0x03, 0xe0, 0xcd, 0xab, 0x76, 0x41, 0xf3, 0x72, 0x01, 0x81, 0x44, - 0xbd, 0xf2, 0x0a, 0xcb, 0x67, 0xc6, 0xec, 0x12, 0xc8, 0x50, 0x41, 0xc0, 0x26, 0xa9, 0xeb, 0x5c, 0x88, 0x55, 0x87, - 0x95, 0xf9, 0x48, 0xc2, 0x8e, 0x42, 0x34, 0xe7, 0x0c, 0x66, 0xc1, 0x7f, 0x05, 0x83, 0x72, 0x10, 0x44, 0x41, 0x14, - 0x04, 0x64, 0x50, 0xc0, 0x2f, 0xc4, 0x19, 0x23, 0x18, 0xa3, 0x04, 0x3a, 0xfc, 0x8e, 0x33, 0x9f, 0x11, 0x79, 0xd9, - 0x08, 0x63, 0xe9, 0x06, 0xe0, 0x5c, 0xca, 0x9c, 0xc7, 0xe8, 0x63, 0xf1, 0x8e, 0xb3, 0x8c, 0xd0, 0x77, 0xde, 0xa9, - 0xfc, 0x88, 0x37, 0x82, 0xdb, 0xed, 0x0e, 0xdb, 0x2b, 0x1e, 0x66, 0xb4, 0x37, 0xa6, 0xef, 0x38, 0x89, 0xb2, 0x86, - 0xf3, 0x30, 0x87, 0x9e, 0x55, 0x96, 0xb5, 0xa2, 0x86, 0xdc, 0xa0, 0x58, 0x17, 0x59, 0x26, 0x27, 0xc3, 0x55, 0x73, - 0x2a, 0x70, 0xdd, 0xd9, 0xf5, 0x02, 0x92, 0x32, 0xa1, 0x59, 0x3a, 0x1b, 0xbe, 0xda, 0xb6, 0xec, 0x45, 0xeb, 0x14, - 0xf2, 0x1a, 0xa2, 0xa2, 0x1f, 0x3a, 0x02, 0x6a, 0x68, 0xc5, 0x65, 0x05, 0x2e, 0xbb, 0xa6, 0x3d, 0xdc, 0xb4, 0xc7, - 0x34, 0xe3, 0x03, 0xc4, 0x88, 0xe3, 0xd8, 0x32, 0xb0, 0x9b, 0x70, 0x78, 0x36, 0xce, 0xf7, 0x65, 0x97, 0xde, 0xba, - 0x5a, 0x3c, 0xc2, 0xda, 0xf3, 0x56, 0x48, 0x08, 0x90, 0x96, 0xa6, 0xd2, 0xed, 0x36, 0x08, 0x60, 0x80, 0xfb, 0xfd, - 0x1e, 0x70, 0xad, 0x86, 0x9d, 0x34, 0xb7, 0x66, 0x4b, 0xec, 0x15, 0x85, 0xc7, 0x40, 0x94, 0x9a, 0xff, 0x0c, 0x02, - 0x8a, 0xe7, 0x6e, 0x08, 0xf6, 0x95, 0xec, 0x68, 0x53, 0xf4, 0xfb, 0x2f, 0x0a, 0x7c, 0x40, 0x39, 0x28, 0x88, 0x75, - 0x75, 0xdc, 0x0a, 0xc3, 0x3e, 0xa9, 0x0f, 0x71, 0x2c, 0xf2, 0x2c, 0x74, 0x84, 0xa5, 0x32, 0x84, 0x85, 0x2b, 0x46, - 0x3a, 0x88, 0x83, 0x9a, 0x74, 0x0e, 0x56, 0xe5, 0x82, 0x0d, 0xf7, 0x7a, 0x9f, 0x00, 0x16, 0x3c, 0xf3, 0x86, 0xe5, - 0xbd, 0x07, 0x00, 0xd6, 0xeb, 0xe1, 0x42, 0x71, 0x2f, 0x5f, 0x35, 0xd0, 0x27, 0xf1, 0xa5, 0x65, 0xd7, 0x67, 0x5a, - 0x56, 0x32, 0x1a, 0x8d, 0xaa, 0x5a, 0x49, 0x3e, 0x1c, 0x79, 0x69, 0xa1, 0x56, 0xca, 0x38, 0xe5, 0x29, 0x58, 0x7a, - 0x1b, 0x4a, 0x37, 0x5f, 0xd0, 0x15, 0x17, 0xa9, 0xfa, 0xe9, 0xa1, 0x4d, 0x36, 0x88, 0x6b, 0xd6, 0xd4, 0x59, 0xd8, - 0xe1, 0x87, 0x80, 0x8f, 0xf6, 0x61, 0xe6, 0xd2, 0x35, 0x2c, 0x2d, 0x88, 0x23, 0xe3, 0x82, 0x87, 0x2e, 0x0f, 0x60, - 0xfd, 0x99, 0x43, 0x12, 0x3f, 0x85, 0x9f, 0x33, 0x93, 0xd6, 0xf1, 0x19, 0xce, 0x66, 0x54, 0xaa, 0x1b, 0x41, 0xfb, - 0x35, 0x24, 0x12, 0x83, 0x6c, 0xdc, 0x60, 0x28, 0x5a, 0x77, 0x1b, 0xb8, 0xf2, 0x5b, 0x7a, 0xe7, 0xd3, 0x20, 0xc0, - 0xb6, 0xc6, 0x62, 0x00, 0x30, 0x14, 0x7f, 0xa0, 0xaa, 0xc6, 0x5c, 0x51, 0x4c, 0xc3, 0x54, 0xa2, 0xbd, 0xe3, 0xb8, - 0x8e, 0x1a, 0x57, 0x59, 0xc1, 0x4a, 0x6b, 0xcb, 0xeb, 0xde, 0xd2, 0xc2, 0x96, 0x80, 0x6a, 0x30, 0xdc, 0x09, 0xe0, - 0x33, 0x22, 0xd5, 0x81, 0x20, 0xbb, 0x0f, 0x0e, 0x9a, 0xb3, 0x04, 0xcf, 0xc3, 0x10, 0xfe, 0xc0, 0xc2, 0x81, 0x65, - 0xa9, 0xfa, 0xb9, 0x9c, 0xc6, 0x70, 0xee, 0xe6, 0x6a, 0x87, 0xcf, 0x96, 0xa0, 0xc8, 0x53, 0x73, 0x6a, 0x2e, 0x5f, - 0x79, 0x63, 0xbf, 0xc7, 0x04, 0xf3, 0x98, 0xd9, 0x86, 0xdf, 0x7a, 0xba, 0xad, 0x2f, 0xac, 0x1b, 0x38, 0x69, 0x2f, - 0x9c, 0xf6, 0x62, 0xbb, 0x34, 0x10, 0x77, 0x75, 0x43, 0x88, 0xf0, 0x5a, 0x13, 0x8b, 0xac, 0x21, 0xd3, 0xb1, 0xd8, - 0x18, 0xaa, 0x4d, 0xc5, 0x73, 0xad, 0x10, 0x2f, 0xa7, 0xea, 0xc2, 0xd4, 0x4a, 0x65, 0xc2, 0x20, 0xcc, 0x94, 0xb0, - 0xa8, 0x32, 0xf0, 0xd9, 0xaf, 0x90, 0xe2, 0xda, 0x7a, 0xde, 0xe2, 0xf2, 0xcd, 0x4c, 0x9b, 0xed, 0xa7, 0xaf, 0xf2, - 0xf8, 0x72, 0xbb, 0x0d, 0xbb, 0x5f, 0x80, 0xf9, 0x65, 0xa9, 0x34, 0x6a, 0xe0, 0xf4, 0x10, 0xa2, 0x9f, 0xf3, 0x3d, - 0x39, 0x27, 0x8e, 0x93, 0x6b, 0x37, 0x6f, 0xb6, 0x93, 0x62, 0x04, 0x16, 0x70, 0xe2, 0x22, 0x1d, 0x68, 0xa9, 0xe0, - 0xb4, 0x65, 0xbc, 0xb7, 0xe9, 0x1d, 0xa5, 0xc2, 0xab, 0x85, 0x26, 0x21, 0x95, 0xbb, 0x97, 0xd8, 0x51, 0x03, 0xce, - 0x49, 0xdd, 0x41, 0xc0, 0x49, 0x4d, 0x37, 0xd6, 0x2a, 0x4e, 0x4d, 0x82, 0xf7, 0x4a, 0x0f, 0x5d, 0xa2, 0x9d, 0xb8, - 0xdd, 0xb6, 0x2a, 0x5b, 0xa8, 0x8f, 0x7b, 0x39, 0x4b, 0xd4, 0xf1, 0x80, 0x42, 0x17, 0x75, 0x34, 0xe4, 0x0b, 0x52, - 0xe8, 0x95, 0xa3, 0x55, 0xab, 0xbb, 0x92, 0x81, 0x52, 0xad, 0x82, 0xbc, 0x26, 0xd6, 0x5d, 0x2b, 0x6b, 0x2c, 0xae, - 0x9c, 0x90, 0xc2, 0x26, 0x7c, 0x69, 0x29, 0x16, 0x56, 0xb0, 0x37, 0xa6, 0xbe, 0x70, 0x89, 0xd0, 0x76, 0xb7, 0x21, - 0x26, 0x19, 0xac, 0x9b, 0xed, 0xf6, 0x75, 0x11, 0xce, 0xb3, 0x05, 0x95, 0xa3, 0x2c, 0x45, 0x08, 0x31, 0xe3, 0xa1, - 0x6b, 0xbb, 0x60, 0x26, 0x86, 0xba, 0xf6, 0x78, 0x49, 0xa6, 0x58, 0x9b, 0x24, 0x47, 0xf1, 0xb9, 0x2c, 0xd4, 0x5a, - 0x23, 0x04, 0x0f, 0xf7, 0x3f, 0x53, 0x88, 0xe1, 0x66, 0xd6, 0xdd, 0x6f, 0x3b, 0x37, 0xc4, 0x3f, 0x21, 0x90, 0x40, - 0xc9, 0x5e, 0x17, 0xa3, 0xf3, 0x4c, 0xa4, 0xb8, 0x53, 0x55, 0x54, 0x5c, 0xb5, 0x0e, 0x9a, 0x2d, 0xb7, 0xf7, 0x62, - 0x4b, 0x14, 0x20, 0xae, 0xb1, 0xd0, 0x8c, 0x67, 0xe5, 0x2c, 0x45, 0x32, 0x8a, 0x0d, 0x89, 0x4a, 0x2f, 0x2a, 0xba, - 0xcf, 0xd3, 0x98, 0x1e, 0xba, 0x35, 0x08, 0xae, 0x9a, 0x3b, 0x1b, 0x69, 0xbe, 0x20, 0x44, 0x4d, 0x80, 0x84, 0x8d, - 0x6a, 0x4e, 0xad, 0x4b, 0xf1, 0x30, 0xab, 0x7c, 0xa6, 0x0f, 0xe2, 0x4b, 0x01, 0x3c, 0xac, 0xb7, 0xbd, 0xaf, 0x84, - 0xc7, 0xda, 0xe0, 0xdb, 0xed, 0xf6, 0x52, 0xcc, 0x83, 0xc0, 0x63, 0x34, 0xbf, 0x53, 0x12, 0xf3, 0xde, 0x98, 0xc2, - 0x8a, 0xf7, 0x5d, 0xda, 0xba, 0x49, 0xad, 0xb5, 0x40, 0xdd, 0xe1, 0xfa, 0x80, 0xe7, 0x29, 0x71, 0xb4, 0xa3, 0x72, - 0x2a, 0xad, 0xae, 0x1c, 0xbb, 0x22, 0x30, 0x30, 0xf4, 0x0f, 0x29, 0xdb, 0x80, 0x39, 0x1e, 0x58, 0xdb, 0xa0, 0x9f, - 0x92, 0xd2, 0xc2, 0x8c, 0xd1, 0x98, 0x45, 0xae, 0xab, 0xe8, 0x80, 0xeb, 0xe8, 0xed, 0x3c, 0xfa, 0xdb, 0xb3, 0x31, - 0x2d, 0x62, 0x91, 0xca, 0x2b, 0x50, 0x41, 0x80, 0x32, 0x04, 0x0d, 0xff, 0x35, 0x35, 0x00, 0x0d, 0x82, 0x1b, 0x80, - 0x7f, 0x74, 0x3a, 0x0d, 0xda, 0x9a, 0x7c, 0x4c, 0x52, 0x55, 0xe4, 0xac, 0x0d, 0x65, 0xa6, 0x92, 0x43, 0xf2, 0xb8, - 0x04, 0x3c, 0x47, 0x6c, 0x96, 0xb2, 0xb9, 0x50, 0x9b, 0x4d, 0xbd, 0x56, 0xec, 0xc8, 0x6d, 0xa3, 0x68, 0xb3, 0x16, - 0xb5, 0x9d, 0xc4, 0x7c, 0x31, 0xbd, 0xb5, 0xc2, 0xc0, 0xa9, 0x69, 0xcd, 0xcd, 0x0e, 0x74, 0x9a, 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, 0x0d, 0x69, 0xaa, 0xd0, 0xa3, 0x03, 0xbd, 0x1d, 0x02, 0x9a, 0xb3, 0x31, - 0x5d, 0xd2, 0x14, 0x2f, 0xd0, 0x74, 0x0d, 0x66, 0x29, 0x17, 0xd0, 0xd7, 0x6e, 0x9f, 0xe4, 0x0b, 0xd5, 0x13, 0xe1, - 0x2d, 0x51, 0xf0, 0xe5, 0x48, 0xc1, 0x2b, 0x2b, 0xe7, 0xb1, 0x99, 0x43, 0xc0, 0x63, 0x51, 0x25, 0x7a, 0x27, 0xc5, - 0x25, 0x28, 0x53, 0xe1, 0x08, 0x34, 0x55, 0x23, 0x96, 0x70, 0x80, 0xdb, 0x8b, 0xa7, 0x01, 0xa1, 0x20, 0xd5, 0x5d, - 0xdb, 0x15, 0x79, 0xcb, 0x8e, 0x36, 0xb7, 0x60, 0x16, 0x5b, 0xad, 0xcb, 0xd6, 0x57, 0x36, 0xd9, 0x7d, 0x5c, 0x13, - 0x6c, 0xbb, 0xb7, 0x41, 0xc2, 0x5b, 0x7a, 0x43, 0x36, 0x37, 0xfd, 0x7e, 0x08, 0xfd, 0x21, 0x54, 0x77, 0xe8, 0xb6, - 0xb3, 0x43, 0xb7, 0x3e, 0xf3, 0x6b, 0xf5, 0x7c, 0xca, 0x1b, 0xe2, 0x03, 0x9a, 0x68, 0xd1, 0x55, 0x7c, 0x07, 0x9b, - 0x3a, 0xaa, 0xa8, 0xaa, 0x3c, 0x4a, 0x28, 0xa8, 0x80, 0x33, 0x5e, 0x9e, 0x72, 0x8c, 0x6d, 0xaa, 0x9f, 0xde, 0x69, - 0x5e, 0x6d, 0x6d, 0xd6, 0x66, 0xb9, 0x3e, 0x07, 0x8b, 0x80, 0x73, 0x1e, 0x5d, 0x69, 0x5a, 0x72, 0xe9, 0x31, 0xf5, - 0x67, 0x38, 0x2a, 0xc1, 0x45, 0x9c, 0xe5, 0x3c, 0x0d, 0xe8, 0x45, 0xb3, 0xff, 0xa1, 0xb6, 0x95, 0x5a, 0x36, 0xce, - 0xdc, 0xeb, 0x90, 0x6c, 0xfe, 0xc7, 0x06, 0xea, 0x4d, 0x88, 0x11, 0x51, 0xcd, 0x82, 0x3e, 0x61, 0x10, 0x1b, 0x33, - 0x28, 0xd7, 0x49, 0xc2, 0xcb, 0x32, 0x30, 0x4a, 0xad, 0x35, 0x5b, 0x9b, 0xf3, 0xec, 0x11, 0x3b, 0x7a, 0xd4, 0x63, - 0xec, 0x96, 0xd0, 0x44, 0xeb, 0x84, 0x4c, 0x8d, 0x91, 0xa7, 0x05, 0xd2, 0x1d, 0x8a, 0xb2, 0x8b, 0xf0, 0x04, 0x85, - 0x2c, 0xed, 0x7d, 0x6e, 0x4e, 0x64, 0xf5, 0x8d, 0x36, 0xba, 0x88, 0x54, 0x22, 0xc8, 0xc6, 0x6f, 0x10, 0xb0, 0x17, - 0x9a, 0x1d, 0x90, 0xcd, 0x92, 0x9d, 0xd2, 0x33, 0x6b, 0x02, 0x03, 0xaf, 0x4f, 0x54, 0xa2, 0x19, 0x65, 0x45, 0x74, - 0x95, 0x91, 0xcb, 0x5d, 0x48, 0xa2, 0xb3, 0x90, 0xf8, 0xb9, 0x61, 0x69, 0x5d, 0x87, 0x28, 0x66, 0x36, 0x1b, 0x5e, - 0x75, 0xf7, 0x51, 0x63, 0x5b, 0x19, 0x9f, 0xea, 0x5b, 0x9b, 0x46, 0xa6, 0xd0, 0xd7, 0xe1, 0xa4, 0xdf, 0x87, 0xbf, - 0x9a, 0x7e, 0xe0, 0x2d, 0x05, 0x7f, 0xb1, 0x47, 0xa4, 0x4e, 0x58, 0x00, 0x70, 0x84, 0x39, 0xaf, 0x9a, 0x13, 0xf8, - 0x88, 0x1d, 0x6d, 0x1e, 0x85, 0xa7, 0x8d, 0x99, 0xbb, 0x0b, 0xf1, 0x52, 0x95, 0xf4, 0xbc, 0x79, 0x32, 0x03, 0xb1, - 0x0a, 0xcd, 0x7e, 0xbd, 0x65, 0x56, 0x9f, 0x00, 0x44, 0xea, 0xd6, 0x3a, 0x94, 0xe2, 0xc7, 0xa6, 0xcb, 0x64, 0x93, - 0xb2, 0x36, 0x13, 0xa5, 0x54, 0x24, 0xcd, 0x45, 0x00, 0xfd, 0x86, 0xe1, 0xa8, 0x01, 0xde, 0x5b, 0x8f, 0xbd, 0x19, - 0x1a, 0x6f, 0x4c, 0x0d, 0x3d, 0xdb, 0xe8, 0xe5, 0xed, 0x28, 0x84, 0x19, 0x8b, 0xe8, 0xd6, 0x1d, 0x8b, 0xe1, 0x29, - 0x3d, 0x81, 0x0a, 0xdf, 0x84, 0x18, 0x4d, 0x97, 0xd4, 0xf5, 0x74, 0xad, 0xb6, 0xd2, 0x0d, 0xa1, 0x39, 0x46, 0xf1, - 0xf1, 0xda, 0x76, 0x47, 0x8d, 0xd0, 0x9e, 0x50, 0x1e, 0xde, 0xd2, 0x8a, 0xde, 0x58, 0x16, 0xc1, 0xc9, 0x8f, 0xbd, - 0xfc, 0x84, 0x9e, 0x7b, 0x02, 0x93, 0xa2, 0xad, 0x01, 0xfc, 0x01, 0xf5, 0xc3, 0x59, 0x3d, 0xb5, 0x52, 0x0e, 0x4f, - 0xe1, 0x4b, 0x36, 0x20, 0x57, 0xd0, 0x8b, 0x35, 0x66, 0x47, 0x31, 0xe8, 0xa0, 0x76, 0x76, 0x87, 0x37, 0x29, 0x65, - 0x88, 0xd6, 0x77, 0x0e, 0xe2, 0xe9, 0x1f, 0xa0, 0xe9, 0x83, 0xb4, 0x30, 0xa5, 0x6b, 0x14, 0xf0, 0x80, 0xbe, 0xa9, - 0xdf, 0xcf, 0xf1, 0xb9, 0xf6, 0x2c, 0xb1, 0xb0, 0xc7, 0x4b, 0x42, 0x97, 0x5e, 0xdc, 0x28, 0x90, 0x36, 0x3b, 0x56, - 0x01, 0x58, 0x91, 0x04, 0x1a, 0x91, 0x80, 0xa5, 0x8e, 0x27, 0x2e, 0xdb, 0xa0, 0x01, 0x49, 0x54, 0x52, 0xc8, 0x12, - 0x49, 0xe0, 0x87, 0x11, 0x84, 0x28, 0x8a, 0x41, 0xdc, 0xab, 0x97, 0x57, 0x5c, 0x53, 0x03, 0x4e, 0x14, 0xc1, 0x04, - 0xeb, 0x74, 0x0a, 0xc4, 0x56, 0xac, 0x57, 0xe0, 0x79, 0xe9, 0x38, 0x71, 0x64, 0x09, 0xd0, 0x20, 0xcd, 0x97, 0x4e, - 0xbb, 0xe5, 0xed, 0x89, 0x96, 0x2a, 0x36, 0xf7, 0x5e, 0x2c, 0x2c, 0xf7, 0x58, 0xf9, 0xdb, 0x81, 0xf6, 0xc2, 0x6a, - 0x47, 0x44, 0x0d, 0x56, 0x76, 0x6d, 0xbb, 0x36, 0x94, 0x86, 0xea, 0x5e, 0x39, 0x26, 0xa0, 0xa2, 0xab, 0xb8, 0x5a, - 0x46, 0xd9, 0x08, 0xfe, 0x6c, 0xb7, 0xc1, 0x7e, 0x00, 0x16, 0x90, 0xbf, 0xbe, 0xff, 0x39, 0xc2, 0xf0, 0x4c, 0xbf, - 0xbe, 0xff, 0x79, 0xbb, 0x7d, 0x36, 0x1e, 0x1b, 0xae, 0xc0, 0xa9, 0x75, 0x80, 0x3f, 0x30, 0x6c, 0x83, 0x5d, 0xb2, - 0xdb, 0xed, 0x33, 0xe0, 0x20, 0x14, 0xdb, 0x60, 0x76, 0xb1, 0x72, 0xe4, 0x52, 0xac, 0x86, 0xde, 0x91, 0x80, 0x55, - 0xb7, 0xc3, 0x52, 0xec, 0x52, 0x1f, 0x15, 0x82, 0x51, 0x2f, 0xfa, 0x97, 0x9d, 0x02, 0x4b, 0x0a, 0xa6, 0xab, 0xc1, - 0xb2, 0xaa, 0x56, 0x65, 0xb4, 0xbf, 0x1f, 0xaf, 0xb2, 0x51, 0x99, 0xc1, 0x36, 0x2f, 0xaf, 0x2f, 0x01, 0x50, 0x21, - 0xa0, 0x8d, 0x77, 0x6b, 0x91, 0x99, 0x17, 0x0b, 0xba, 0xcc, 0x70, 0x4d, 0x82, 0xd9, 0x41, 0xce, 0xad, 0x6e, 0x72, - 0x4a, 0xec, 0x03, 0xd8, 0x1c, 0x6e, 0xb7, 0x0d, 0x7e, 0xe1, 0x68, 0xf4, 0x6c, 0xb6, 0xcc, 0xb4, 0x41, 0x27, 0x37, - 0xfb, 0x9f, 0x44, 0x5e, 0x1a, 0x2a, 0x3e, 0xc9, 0xf4, 0x65, 0x06, 0x7c, 0x1e, 0x7b, 0x2b, 0x42, 0x9f, 0xe5, 0x6a, - 0xb4, 0x06, 0xd8, 0xd8, 0xec, 0xe2, 0x6e, 0x94, 0x72, 0x88, 0x48, 0x11, 0x58, 0x75, 0xcd, 0x32, 0x23, 0xbe, 0x4d, - 0xc5, 0x5d, 0x4b, 0x15, 0xf6, 0x56, 0x78, 0xce, 0x2a, 0xdc, 0x38, 0xca, 0xf4, 0x26, 0x51, 0xf8, 0x12, 0x85, 0xa8, - 0x1c, 0x8d, 0xe9, 0x9c, 0x40, 0x2a, 0xf3, 0x98, 0x50, 0xcc, 0xe1, 0xde, 0xfd, 0x9a, 0x3a, 0x73, 0x19, 0x5f, 0xb8, - 0xf7, 0xd2, 0x97, 0x99, 0xdc, 0x4a, 0x00, 0x45, 0x52, 0xb5, 0xff, 0xf2, 0x19, 0xa9, 0xf1, 0x3f, 0x53, 0xad, 0x01, - 0xe8, 0xfd, 0x02, 0x35, 0x39, 0x82, 0x80, 0xad, 0x98, 0xfa, 0x68, 0xfa, 0x56, 0x32, 0xff, 0x01, 0x75, 0x3b, 0x82, - 0x6d, 0x54, 0xfc, 0x9c, 0xa8, 0xa2, 0x05, 0x4f, 0xd7, 0x22, 0x8d, 0x45, 0x72, 0x17, 0xf1, 0x7a, 0x8a, 0x25, 0x31, - 0x1b, 0x21, 0xeb, 0x97, 0x66, 0x17, 0x7e, 0x2e, 0x1a, 0x26, 0xe0, 0xb4, 0xf4, 0xb7, 0x95, 0xb7, 0x99, 0x2c, 0xe3, - 0x8c, 0x4c, 0xb9, 0x42, 0xec, 0xb6, 0xfa, 0x1e, 0x73, 0x82, 0x3f, 0x3d, 0x78, 0x4a, 0xe8, 0xad, 0x9c, 0x96, 0x08, - 0x4a, 0x27, 0x52, 0xeb, 0xaa, 0x89, 0xfd, 0x9a, 0x42, 0x14, 0x07, 0xc1, 0x20, 0x74, 0xa7, 0x69, 0x9f, 0xe2, 0xfb, - 0x6c, 0xd9, 0x6f, 0x4d, 0xd9, 0x92, 0x6c, 0x04, 0x74, 0x4c, 0x3a, 0x6f, 0x4f, 0x6f, 0xcf, 0xce, 0xbc, 0xdf, 0xa0, - 0x09, 0x07, 0xd5, 0x0d, 0xb4, 0xab, 0x20, 0xd3, 0x18, 0xc5, 0x66, 0x31, 0xd6, 0x6e, 0x4d, 0x44, 0x10, 0x74, 0xba, - 0x9c, 0x85, 0xed, 0x76, 0x42, 0x7c, 0x09, 0x24, 0x50, 0xe0, 0xca, 0x45, 0x39, 0x09, 0x89, 0xba, 0x90, 0xe9, 0xc9, - 0xba, 0x96, 0x2c, 0xd0, 0x6b, 0xec, 0x20, 0xa0, 0xc7, 0xdc, 0x3e, 0x05, 0xf4, 0x7d, 0xc1, 0x8e, 0xf9, 0x20, 0x18, - 0x62, 0x7c, 0xd5, 0x80, 0xde, 0x48, 0xf5, 0x08, 0x1e, 0xc2, 0xc0, 0x72, 0xd1, 0x57, 0x05, 0x43, 0x58, 0xa1, 0xbf, - 0x52, 0x36, 0xf9, 0xe6, 0xef, 0x6e, 0x7e, 0xcf, 0xb5, 0x98, 0x1d, 0x84, 0xe2, 0xf6, 0x7a, 0x02, 0xc4, 0xaf, 0xe2, - 0x57, 0x60, 0x5d, 0xad, 0x25, 0xde, 0x6e, 0x7a, 0xfe, 0x14, 0xbe, 0x1c, 0xdd, 0x7e, 0x52, 0x9a, 0x4f, 0x20, 0x48, - 0x8d, 0x93, 0x94, 0xbb, 0xef, 0x3e, 0x4a, 0x57, 0x11, 0x8c, 0x16, 0x20, 0xd6, 0xdd, 0x5b, 0xc9, 0x59, 0x53, 0xf8, - 0x8f, 0x75, 0xbe, 0xc7, 0xd8, 0x21, 0xf2, 0x14, 0xa7, 0xbf, 0x01, 0x86, 0x7d, 0xe7, 0xdf, 0xca, 0xac, 0x21, 0xd1, - 0xb9, 0xfa, 0x08, 0xe8, 0xff, 0x58, 0x8f, 0xdf, 0x31, 0x4a, 0xfa, 0x92, 0x38, 0x47, 0xb8, 0x22, 0x5e, 0xa2, 0xa9, - 0x5e, 0x6f, 0x5c, 0xd3, 0x4f, 0x85, 0x79, 0xa1, 0x15, 0x1c, 0xf6, 0xad, 0x51, 0x78, 0xe0, 0x99, 0xf7, 0x9b, 0x68, - 0x08, 0xba, 0x7f, 0xc7, 0xbd, 0xf1, 0x9b, 0x60, 0x19, 0xde, 0x94, 0xb3, 0xcc, 0xdc, 0xe1, 0x6e, 0x32, 0x91, 0xca, - 0x1b, 0xc6, 0x82, 0xb5, 0x50, 0xe6, 0xab, 0x69, 0x30, 0xdb, 0xd4, 0x91, 0x4a, 0x76, 0xdf, 0xbf, 0x6d, 0x9c, 0xb0, - 0xd9, 0x20, 0x38, 0xad, 0x64, 0x11, 0x5f, 0xf2, 0x60, 0xaa, 0x55, 0x14, 0x59, 0xd6, 0xef, 0x67, 0x80, 0x0c, 0xe3, - 0xb4, 0x77, 0xf0, 0x64, 0xa9, 0x99, 0x09, 0x71, 0x6d, 0x75, 0x16, 0xf0, 0xd6, 0x8c, 0xe6, 0x71, 0x05, 0xbb, 0xcc, - 0x57, 0x52, 0xfc, 0xd9, 0x92, 0x64, 0x63, 0xfd, 0x0d, 0x19, 0xb6, 0x95, 0xcf, 0x9c, 0x03, 0xc6, 0xcc, 0x8d, 0x54, - 0x41, 0xee, 0x7a, 0xc0, 0x08, 0x21, 0x11, 0x10, 0xce, 0x62, 0xe2, 0x4e, 0x98, 0xf0, 0x8f, 0x2e, 0x30, 0x4e, 0x8c, - 0x81, 0x71, 0x3e, 0xca, 0x90, 0xd3, 0x63, 0x3e, 0x48, 0x1a, 0xb3, 0xf5, 0xa7, 0x2a, 0x91, 0x5e, 0x4b, 0x42, 0xcf, - 0xe0, 0xf7, 0xb8, 0xc5, 0x03, 0x35, 0x82, 0x53, 0xba, 0x9b, 0xd3, 0xfe, 0xab, 0x82, 0x0c, 0xff, 0x02, 0xef, 0xae, - 0xd8, 0x5e, 0x96, 0x13, 0x58, 0xdc, 0xb1, 0x57, 0x3c, 0xcd, 0x55, 0x8b, 0x13, 0xe2, 0x11, 0x8b, 0xdc, 0x27, 0x16, - 0x30, 0xa2, 0x86, 0xd1, 0xf8, 0xf1, 0xf4, 0xe4, 0xad, 0xc6, 0x6c, 0xca, 0xfd, 0x0f, 0x60, 0x44, 0xb5, 0xb4, 0xdd, - 0x0e, 0xf8, 0x72, 0x84, 0x06, 0xdb, 0xa9, 0x1b, 0xec, 0x7e, 0xdf, 0xa4, 0x1d, 0x95, 0x5e, 0x36, 0x27, 0x06, 0xdd, - 0x51, 0xda, 0x2c, 0x95, 0x41, 0x6d, 0x57, 0xe1, 0x68, 0x3e, 0x6b, 0xc4, 0xaa, 0xde, 0x87, 0xe1, 0x92, 0xc6, 0x56, - 0x56, 0x6e, 0x77, 0x13, 0x8e, 0x6c, 0x02, 0x5c, 0x9f, 0x82, 0xb2, 0x6a, 0xce, 0x41, 0x0b, 0x3a, 0x13, 0x38, 0xa2, - 0xed, 0x36, 0x84, 0x08, 0x1c, 0xc5, 0x70, 0x32, 0x0b, 0x8b, 0xe1, 0x50, 0x0d, 0x7c, 0x41, 0x48, 0xf4, 0xa9, 0x98, - 0x67, 0x0b, 0x85, 0xd8, 0xe3, 0xef, 0xa4, 0xdf, 0x0a, 0xc5, 0x29, 0xf7, 0x7e, 0x13, 0x64, 0xf3, 0x7b, 0x8a, 0x31, - 0x07, 0x9d, 0x66, 0x33, 0x03, 0x09, 0xeb, 0x71, 0x45, 0xd4, 0x3a, 0xb2, 0xb3, 0x01, 0xaa, 0x58, 0x34, 0x85, 0x05, - 0x75, 0x8b, 0x27, 0xd6, 0x33, 0x7a, 0x0f, 0x2a, 0x41, 0x54, 0x0b, 0x76, 0x63, 0xb8, 0xd6, 0x3e, 0x89, 0x50, 0x52, - 0x4e, 0x9a, 0xcc, 0x8c, 0x15, 0x0d, 0x16, 0x20, 0x24, 0x8d, 0xcb, 0xea, 0x8d, 0x4c, 0xb3, 0x8b, 0x0c, 0x10, 0x13, - 0x9c, 0xff, 0x9c, 0x6c, 0xbc, 0x79, 0xae, 0xe6, 0xa5, 0x2b, 0x71, 0x66, 0x61, 0x3e, 0xba, 0xde, 0xd2, 0x82, 0x44, - 0x05, 0xd0, 0x28, 0x5f, 0xcb, 0xf3, 0xd3, 0x8e, 0x55, 0xc8, 0xee, 0x87, 0x53, 0x65, 0x3b, 0xc4, 0x8f, 0x58, 0x45, - 0xbc, 0xd3, 0xba, 0x52, 0x22, 0x8d, 0x8e, 0xb6, 0x01, 0x31, 0x6c, 0xd9, 0xb7, 0xa8, 0xe1, 0x83, 0x30, 0x83, 0x4e, - 0xf2, 0x83, 0x9e, 0xd1, 0xb1, 0x35, 0x90, 0xf4, 0xb5, 0x08, 0xbe, 0x46, 0x47, 0x3a, 0x51, 0xa6, 0x91, 0x98, 0x42, - 0xa2, 0x5f, 0x2f, 0xb4, 0xc6, 0x32, 0xca, 0xbe, 0x22, 0xff, 0x7b, 0xdd, 0xbd, 0xdf, 0xc4, 0x76, 0x0b, 0x93, 0xec, - 0x79, 0x5c, 0xc1, 0xa6, 0x46, 0xad, 0x10, 0xce, 0xce, 0x71, 0x85, 0xda, 0xb1, 0x5e, 0x58, 0x02, 0x79, 0x00, 0x5b, - 0x91, 0x06, 0x65, 0x90, 0xec, 0x53, 0x31, 0x17, 0x0b, 0x27, 0xca, 0x91, 0x0a, 0xef, 0x4b, 0x8e, 0x52, 0x0e, 0x57, - 0xb1, 0xb0, 0x60, 0xc8, 0xaf, 0x8e, 0x2e, 0x0a, 0x79, 0x05, 0x92, 0x12, 0xc3, 0x50, 0x59, 0x5e, 0x17, 0x57, 0x6d, - 0x49, 0x68, 0xef, 0x0c, 0x40, 0x58, 0x0a, 0x10, 0xbc, 0x34, 0x6a, 0x88, 0xd9, 0x46, 0xed, 0xae, 0xe8, 0x5e, 0x72, - 0x40, 0x9d, 0xee, 0xda, 0xad, 0x37, 0x65, 0x9b, 0x6d, 0xc5, 0x85, 0x7f, 0x42, 0xe9, 0xc7, 0x7c, 0x50, 0xf8, 0x54, - 0x02, 0x37, 0xbe, 0xda, 0x64, 0xd9, 0xc5, 0x1d, 0x2e, 0xfd, 0xaa, 0x31, 0x7e, 0xfd, 0x7e, 0x4f, 0x2d, 0x84, 0x46, - 0x2a, 0x30, 0xdf, 0x3e, 0x33, 0x55, 0x19, 0x4d, 0xa9, 0xbd, 0x04, 0x57, 0xce, 0x7e, 0x04, 0x15, 0x71, 0x5d, 0x91, - 0xc9, 0xd4, 0x00, 0xed, 0x79, 0x59, 0xe1, 0x56, 0x16, 0xe0, 0xb1, 0x13, 0x90, 0xed, 0x96, 0x87, 0x81, 0x3e, 0x74, - 0x02, 0x7f, 0x4b, 0x9e, 0x22, 0xb3, 0x66, 0x1f, 0x7f, 0xd1, 0x82, 0x7f, 0x6c, 0xc1, 0xcf, 0x28, 0xee, 0xb4, 0x32, - 0xff, 0x56, 0x5a, 0xb7, 0xb8, 0x7f, 0x27, 0xd3, 0x84, 0xa2, 0x32, 0xa1, 0xf6, 0x2b, 0xfd, 0x97, 0x09, 0x96, 0xa4, - 0xb2, 0x7f, 0x90, 0xf0, 0xc1, 0xac, 0xf1, 0xc4, 0x1a, 0x4f, 0x86, 0xd3, 0xad, 0x34, 0x0c, 0x01, 0x0a, 0xfd, 0xbc, - 0xcc, 0x15, 0xd5, 0xcf, 0xbf, 0xac, 0xf9, 0x9a, 0x37, 0x5b, 0x6c, 0x93, 0x1e, 0x68, 0xb0, 0x97, 0x47, 0x53, 0x0a, - 0x27, 0x51, 0xe7, 0x46, 0xa2, 0x2e, 0x6a, 0x96, 0xa1, 0x3a, 0xc1, 0xab, 0x79, 0xaa, 0x87, 0xbd, 0x99, 0x88, 0xd6, - 0x4a, 0xca, 0x12, 0x03, 0xd6, 0x3a, 0xf2, 0x90, 0xdc, 0xad, 0x75, 0xdc, 0x69, 0xa8, 0x4b, 0x53, 0x28, 0x01, 0x56, - 0xb8, 0x00, 0x47, 0xd0, 0xcf, 0x45, 0xc8, 0xe1, 0x9a, 0xaa, 0xf4, 0x0b, 0x9a, 0x92, 0x27, 0x9e, 0xa2, 0x56, 0x2b, - 0xd2, 0xed, 0x47, 0x39, 0x76, 0xc3, 0x37, 0x4e, 0xc8, 0x89, 0x11, 0xfa, 0xbb, 0x63, 0x29, 0x67, 0x68, 0xf1, 0xa0, - 0x4e, 0xb0, 0x5e, 0xde, 0x52, 0xa0, 0x98, 0xa3, 0xcb, 0xaa, 0x6b, 0x5e, 0xa3, 0xed, 0xcb, 0xb2, 0xdf, 0xcf, 0x6d, - 0x3d, 0x29, 0x3b, 0xda, 0x2c, 0xcd, 0x3e, 0x44, 0xc5, 0x14, 0xee, 0xfa, 0x44, 0xf3, 0x57, 0xa1, 0xbe, 0x6a, 0xcb, - 0x9c, 0x8f, 0x38, 0xe2, 0x62, 0xe4, 0xa4, 0xfe, 0x45, 0x4d, 0xbd, 0x12, 0xf7, 0xab, 0x4a, 0xbe, 0x13, 0xc6, 0x8a, - 0xd1, 0x01, 0xf5, 0xa7, 0x4a, 0xe5, 0xfd, 0xb2, 0x00, 0xb8, 0x27, 0xc1, 0x3e, 0x81, 0x7d, 0x85, 0x46, 0xf8, 0x6d, - 0x09, 0xf8, 0x37, 0x8a, 0x1b, 0xb0, 0x0a, 0x0c, 0x30, 0x9a, 0x6c, 0xcf, 0x69, 0x02, 0x07, 0x9c, 0xd0, 0x2a, 0x0a, - 0x2a, 0xcc, 0xd0, 0x50, 0x5b, 0x18, 0x3d, 0x45, 0x19, 0xb7, 0xca, 0xec, 0xdd, 0x18, 0x3b, 0x2d, 0xf0, 0x1a, 0xfe, - 0x7c, 0x5e, 0xe8, 0x61, 0xa3, 0x0e, 0xd2, 0xa3, 0x93, 0x98, 0xfe, 0xb8, 0x85, 0x93, 0x9b, 0x85, 0xb3, 0xac, 0x59, - 0x02, 0xdd, 0x81, 0x0b, 0x62, 0xdc, 0xef, 0xe7, 0x70, 0x64, 0x9a, 0x91, 0x2f, 0x58, 0x4e, 0x63, 0xb6, 0xa4, 0xda, - 0xd3, 0xee, 0xb2, 0x0a, 0x73, 0xba, 0xb4, 0x32, 0xde, 0x94, 0x81, 0xca, 0x68, 0xbb, 0x0d, 0xe1, 0x4f, 0xb7, 0xb5, - 0x4b, 0x3a, 0x5f, 0x42, 0x06, 0xf8, 0x03, 0x12, 0x51, 0xc4, 0xbe, 0xfe, 0xb7, 0x1a, 0xa7, 0xf4, 0x44, 0x69, 0xcd, - 0x12, 0xba, 0x66, 0xba, 0x7e, 0x7a, 0xc1, 0xd6, 0x8d, 0xa5, 0xb0, 0xdd, 0x86, 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, 0xf9, 0x50, 0x99, 0xaf, 0x8d, 0x47, 0xdc, 0xbf, 0xd2, 0x30, 0x31, 0x45, 0xa2, 0x42, 0x74, 0xf6, - 0x1b, 0xc8, 0x72, 0x04, 0xe0, 0x58, 0x9e, 0xca, 0x9a, 0xfe, 0x98, 0x42, 0x1c, 0x74, 0x68, 0xd0, 0xbb, 0x42, 0x5e, - 0x65, 0x25, 0x0f, 0xf1, 0x9e, 0xe0, 0x69, 0x46, 0xef, 0x37, 0xf8, 0xd0, 0xd6, 0x1e, 0x3d, 0x41, 0x36, 0x9e, 0x72, - 0xbf, 0xfe, 0x4e, 0x84, 0x73, 0x88, 0x56, 0xb9, 0xa0, 0x5a, 0x5d, 0xed, 0x00, 0xa8, 0x3c, 0xdb, 0xab, 0x47, 0x70, - 0xba, 0xe9, 0xeb, 0x5b, 0x15, 0x3a, 0x73, 0x00, 0x69, 0x0f, 0xc9, 0xba, 0xe6, 0x7a, 0x07, 0xb8, 0x23, 0xb1, 0x5a, - 0x03, 0x8d, 0x75, 0x5b, 0xb3, 0xd3, 0x1e, 0xc5, 0x63, 0x22, 0x33, 0x63, 0x91, 0x62, 0xcc, 0xdd, 0x3a, 0x2d, 0x8a, - 0x36, 0x68, 0x86, 0xb0, 0x7b, 0xd7, 0xe1, 0xeb, 0x56, 0x84, 0xf5, 0xfb, 0x6d, 0x5f, 0x60, 0x34, 0x8c, 0xb9, 0x76, - 0xcf, 0x33, 0x74, 0xc3, 0x06, 0xdb, 0xc8, 0x79, 0x88, 0x7c, 0x98, 0xa9, 0x03, 0x51, 0xd6, 0xd6, 0x80, 0xed, 0x11, - 0xd7, 0x9b, 0x56, 0xf1, 0xf3, 0x2a, 0xe6, 0x6c, 0xcf, 0x1a, 0xa7, 0xb4, 0xbe, 0xc6, 0x35, 0xc7, 0x55, 0x21, 0xa2, - 0xb6, 0x9e, 0xf1, 0x30, 0xec, 0x7c, 0x81, 0x3b, 0xb3, 0xc2, 0xe0, 0x45, 0x58, 0x2a, 0xd9, 0xa9, 0x5c, 0x7f, 0x0e, - 0x5b, 0x1c, 0xa4, 0xf2, 0xa5, 0xd7, 0xdf, 0x7f, 0xf9, 0xe2, 0x0b, 0x74, 0x53, 0x73, 0x7e, 0x04, 0x41, 0x26, 0xd0, - 0x21, 0x4b, 0xa9, 0x1e, 0xbf, 0x2b, 0x80, 0xda, 0xc3, 0x3c, 0x7c, 0x57, 0x30, 0x11, 0x5f, 0x67, 0x97, 0x71, 0x25, - 0x8b, 0xd1, 0x35, 0x17, 0xa9, 0x2c, 0xac, 0xd4, 0x38, 0x38, 0x5e, 0xad, 0x72, 0x1e, 0x80, 0xa9, 0xbc, 0x65, 0x94, - 0x6d, 0x65, 0x99, 0x1e, 0x5c, 0x2d, 0x4f, 0xaf, 0xb4, 0xe8, 0xbc, 0xbc, 0xbe, 0x0c, 0x22, 0xfc, 0x75, 0x6e, 0x7e, - 0x5c, 0xc5, 0xe5, 0xc7, 0x20, 0xb2, 0x36, 0x75, 0xe6, 0x07, 0x4a, 0xe5, 0xc1, 0x7f, 0x0a, 0x64, 0xba, 0xdf, 0x15, - 0x60, 0x99, 0x6d, 0x2b, 0x3e, 0x8c, 0xb1, 0xd6, 0xe1, 0x84, 0xcc, 0x54, 0x89, 0xde, 0xbb, 0x64, 0x5d, 0x80, 0xb5, - 0x9f, 0xc2, 0x32, 0x56, 0xb9, 0x66, 0x58, 0x99, 0xaa, 0xc8, 0xcc, 0xca, 0x9a, 0xed, 0x87, 0xd6, 0x89, 0x66, 0x8e, - 0xde, 0x02, 0xfa, 0x81, 0xec, 0x5f, 0xd2, 0x72, 0xcd, 0x3c, 0x1f, 0x9b, 0xc6, 0xeb, 0x47, 0xfb, 0x97, 0x6e, 0xc1, - 0xde, 0xda, 0x3b, 0x39, 0x0a, 0x13, 0xc1, 0xb3, 0xd6, 0x8c, 0x2f, 0xf2, 0xac, 0x80, 0x95, 0x33, 0x19, 0x8f, 0xa9, - 0xb7, 0xb4, 0x5a, 0x37, 0x47, 0x87, 0xe4, 0x9a, 0x3d, 0xae, 0x1e, 0x73, 0xb2, 0xcf, 0x5b, 0xa6, 0xb6, 0x6d, 0xeb, - 0x38, 0x4f, 0x93, 0xaf, 0x4c, 0xf7, 0xc5, 0xda, 0x46, 0x44, 0x57, 0xce, 0x7d, 0xce, 0x2b, 0xb8, 0xf5, 0x4d, 0x69, - 0xe8, 0xb5, 0x04, 0x20, 0x3a, 0x6d, 0xc0, 0x5f, 0xb0, 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, 0xb1, 0xbb, 0xca, 0xa5, 0x13, 0xf5, - 0x5b, 0x26, 0x5c, 0xb9, 0x12, 0x04, 0x64, 0x5a, 0xb0, 0x5e, 0x61, 0x76, 0x91, 0x5c, 0x03, 0x21, 0x03, 0xc3, 0xd7, - 0x60, 0x2d, 0x4a, 0x6e, 0xac, 0x60, 0xbd, 0x7b, 0xbe, 0x4e, 0x10, 0x52, 0xf0, 0xc0, 0x4d, 0xd0, 0x0f, 0xad, 0x9b, - 0xb7, 0xa3, 0x44, 0x19, 0xc4, 0xe3, 0xd6, 0x4e, 0x39, 0x48, 0x20, 0x00, 0xf7, 0x54, 0x85, 0xe0, 0x50, 0x20, 0xeb, - 0xe0, 0x6a, 0xc6, 0x11, 0x5c, 0x5d, 0x39, 0x73, 0x71, 0x03, 0xb0, 0xae, 0xfc, 0xb9, 0x6c, 0x70, 0x61, 0x3d, 0xa2, - 0xca, 0x9c, 0x71, 0x8a, 0x41, 0x8c, 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, 0x20, 0x0a, 0xb5, 0x01, 0x43, 0xe0, 0x90, 0xf8, 0x83, 0x41, 0xa8, 0xf1, 0x4e, 0x06, 0x2a, 0x20, 0x16, - 0xf1, 0x78, 0x6c, 0xc4, 0xcd, 0x0a, 0xc7, 0x43, 0x0c, 0x7e, 0xd5, 0x7c, 0x41, 0x02, 0x42, 0x4d, 0x69, 0xe8, 0xf2, - 0x18, 0x0e, 0x27, 0x7b, 0x13, 0x48, 0xc5, 0xcc, 0x4c, 0x15, 0xc6, 0xc6, 0x24, 0x82, 0x78, 0xa7, 0x9d, 0xf5, 0x42, - 0xb9, 0xdd, 0x35, 0x1a, 0xc8, 0x95, 0xc1, 0x17, 0x55, 0x3c, 0xd9, 0x1b, 0x76, 0x55, 0x8c, 0xa3, 0x70, 0x6d, 0x94, - 0x6f, 0x67, 0x87, 0x00, 0x5e, 0x7b, 0x36, 0xf4, 0xe5, 0x12, 0x67, 0xfb, 0x4f, 0xc9, 0xe3, 0xa7, 0x84, 0x9e, 0xb1, - 0xb3, 0xaf, 0x9e, 0xd2, 0x33, 0x45, 0x4e, 0xf6, 0x26, 0xd1, 0x35, 0xb3, 0x98, 0x2f, 0x07, 0xaa, 0x09, 0xf4, 0x72, - 0xb4, 0x16, 0x6a, 0x81, 0x69, 0x87, 0xa6, 0xf0, 0xdb, 0xf1, 0x5e, 0x30, 0xb8, 0x6e, 0x37, 0xfd, 0xba, 0xdd, 0x56, - 0xcf, 0xab, 0x6b, 0xef, 0x20, 0xda, 0x2d, 0x66, 0xf2, 0xf7, 0xf1, 0x9e, 0x9b, 0x03, 0xac, 0xef, 0xe1, 0x31, 0x31, - 0x4d, 0xda, 0x19, 0x15, 0xbf, 0xa6, 0x27, 0xd8, 0x87, 0x66, 0x91, 0x1d, 0x7d, 0x18, 0xfe, 0x5b, 0x9d, 0xa8, 0xcf, - 0xbe, 0x3a, 0x00, 0x72, 0x04, 0x32, 0x50, 0x2c, 0x11, 0xcc, 0x70, 0xa0, 0x29, 0xa0, 0x20, 0xd3, 0xe3, 0x4e, 0xf5, - 0xf0, 0xab, 0x51, 0x53, 0x33, 0x72, 0x0d, 0x53, 0x83, 0x6d, 0xc1, 0x0f, 0x54, 0x37, 0xf4, 0x37, 0x1a, 0xdd, 0x48, - 0x3b, 0x99, 0x99, 0x97, 0xd4, 0xc6, 0x75, 0xbb, 0x86, 0x00, 0xc6, 0x0e, 0x5e, 0x50, 0xb2, 0xaf, 0x0f, 0x2f, 0xf7, - 0x70, 0x15, 0x01, 0x4a, 0x16, 0x0b, 0xbe, 0x1e, 0x5c, 0xea, 0xcd, 0xbd, 0x17, 0x90, 0xc1, 0xd7, 0xc1, 0xd1, 0xd7, - 0x03, 0x39, 0x08, 0x0e, 0xf7, 0x2f, 0x8f, 0x02, 0x67, 0xdc, 0x0f, 0x21, 0x1e, 0x55, 0x45, 0x31, 0x13, 0xa6, 0x8a, - 0xc4, 0xd6, 0x9e, 0xdb, 0x7a, 0x95, 0xf1, 0x19, 0x4d, 0xa7, 0x16, 0xf9, 0x3b, 0x4c, 0x59, 0x6c, 0x7e, 0x07, 0x13, - 0x7e, 0x15, 0x44, 0x2e, 0x08, 0xea, 0x2c, 0x8f, 0x62, 0xba, 0x64, 0xb7, 0x22, 0x4c, 0x69, 0xb2, 0x9f, 0x13, 0x12, - 0x85, 0x4b, 0x05, 0x9e, 0xa7, 0x5e, 0x27, 0x10, 0xc7, 0xd5, 0x7d, 0x7e, 0x2b, 0xc2, 0x25, 0xcd, 0xf7, 0x13, 0xd2, - 0x2a, 0xc2, 0x45, 0x64, 0xd9, 0xd4, 0xf4, 0x82, 0x85, 0x2b, 0x7a, 0x09, 0xcc, 0x94, 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, 0xed, 0x4d, 0x6c, 0x4e, 0xf6, 0x32, 0x5a, 0x2b, 0x97, 0x55, 0xcb, 0x90, 0x14, 0x6b, 0x86, - 0xfc, 0x3d, 0x4a, 0x4e, 0xad, 0xc0, 0x93, 0x5d, 0xf0, 0x2a, 0x59, 0xfa, 0x07, 0x95, 0xb5, 0x1a, 0xb0, 0xc7, 0x88, - 0x65, 0xa1, 0x70, 0xec, 0xdf, 0x64, 0xac, 0x58, 0xfb, 0x02, 0x8d, 0x18, 0xb9, 0xb7, 0x37, 0x19, 0xf3, 0x62, 0xae, - 0x26, 0x6b, 0x2f, 0x54, 0x9d, 0x97, 0x9e, 0xb7, 0x78, 0x2f, 0xa7, 0xd4, 0x30, 0x12, 0xd1, 0xbd, 0xb1, 0x32, 0xa3, - 0x54, 0x89, 0x5a, 0x83, 0x46, 0x04, 0x1b, 0xbb, 0xe0, 0x97, 0xe0, 0x84, 0xca, 0x3d, 0x75, 0xb6, 0x6f, 0xa7, 0x54, - 0x7a, 0xc0, 0xb2, 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, - 0x24, 0x77, 0xb9, 0x6e, 0x05, 0xc9, 0x7d, 0x3a, 0x7e, 0xaa, 0x07, 0x3a, 0x5d, 0x6b, 0xc7, 0x43, 0x9f, 0xdf, 0x46, - 0x7c, 0x6d, 0xdd, 0x7b, 0xaa, 0xb5, 0x0a, 0x65, 0xa0, 0xc5, 0x8a, 0xca, 0x95, 0x5a, 0xd2, 0xfb, 0x5d, 0x04, 0xc0, - 0x22, 0x36, 0x66, 0xe3, 0x5d, 0xdb, 0xac, 0x10, 0x34, 0xba, 0xec, 0x68, 0x13, 0x0f, 0x58, 0xa2, 0x5b, 0x3b, 0x98, - 0xd0, 0xf8, 0x88, 0x95, 0xfd, 0x7e, 0x7e, 0x04, 0xf4, 0x54, 0x1b, 0x31, 0x15, 0x70, 0xe4, 0x7f, 0x69, 0x45, 0xa6, - 0x28, 0xb0, 0x59, 0x53, 0x77, 0x6b, 0x2c, 0x23, 0xd1, 0x97, 0x29, 0x5d, 0x9e, 0xf0, 0x0c, 0x98, 0xd6, 0xeb, 0x96, - 0xe3, 0xca, 0xae, 0xe2, 0xc8, 0x53, 0x61, 0x59, 0x71, 0x5e, 0x85, 0xe3, 0xad, 0xc7, 0x37, 0xd8, 0x37, 0x6c, 0xda, - 0x85, 0x3f, 0x84, 0xb0, 0x10, 0xde, 0x64, 0x70, 0x1b, 0xd1, 0x76, 0x12, 0xa8, 0xbc, 0x31, 0xd7, 0x09, 0x65, 0x73, - 0xbb, 0x5e, 0x7b, 0x06, 0xe9, 0xc4, 0x1c, 0x28, 0xd5, 0x08, 0x5a, 0xa3, 0x59, 0x50, 0x35, 0xe2, 0x91, 0xe3, 0xe1, - 0x9d, 0x41, 0xac, 0x96, 0x2f, 0x69, 0x2a, 0x45, 0x03, 0x30, 0x2e, 0x80, 0xcb, 0xd3, 0xaf, 0xef, 0x7f, 0x3e, 0xe5, - 0x71, 0x91, 0x2c, 0xdf, 0xc5, 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, 0xdd, 0x07, 0x20, 0x4f, 0xe3, 0x42, 0x1a, 0x49, 0x5d, 0x88, 0x31, 0x17, 0xf1, 0xba, 0x3e, 0x1e, 0x37, - 0xba, 0x5e, 0xb2, 0x67, 0xe3, 0x27, 0xd3, 0x37, 0x59, 0x98, 0x0d, 0x04, 0x19, 0x55, 0x4b, 0x2e, 0x5a, 0xa6, 0x9c, - 0xca, 0x24, 0x00, 0x7d, 0x3c, 0x7b, 0x8c, 0x1d, 0x8c, 0xc7, 0x64, 0xd3, 0x16, 0x0f, 0xf0, 0x70, 0xb9, 0x0e, 0x0b, - 0x32, 0xd3, 0x75, 0x44, 0x81, 0xe0, 0xb7, 0x55, 0x00, 0x48, 0x8e, 0xb6, 0x2a, 0xc3, 0xa5, 0xb1, 0x67, 0xe3, 0x09, - 0x95, 0xd8, 0xed, 0x90, 0xd4, 0x5e, 0x85, 0x6e, 0xe6, 0xa5, 0xef, 0x51, 0x24, 0x8d, 0xcb, 0xd2, 0x4e, 0xa5, 0x52, - 0xed, 0x99, 0x99, 0xeb, 0x1a, 0xc4, 0x60, 0x08, 0x75, 0xdd, 0xa5, 0x57, 0xf7, 0x6e, 0x73, 0xad, 0xd9, 0x0e, 0x78, - 0xaf, 0x41, 0x33, 0x94, 0xbc, 0xc5, 0xbc, 0x75, 0x45, 0xd4, 0x74, 0xb5, 0x06, 0xb3, 0x62, 0x94, 0x2d, 0x45, 0xe9, - 0x9a, 0x82, 0x52, 0x30, 0xba, 0x58, 0x7b, 0x0b, 0xf7, 0x8d, 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, 0xc7, - 0x15, 0x39, 0x06, 0x47, 0x2f, 0x93, 0xd3, 0x50, 0xe0, 0x1f, 0x33, 0x05, 0x62, 0x3a, 0x54, 0xf7, 0x1b, 0xdc, 0xfc, - 0xff, 0x28, 0x58, 0xe0, 0xf1, 0xad, 0x97, 0xb8, 0x8d, 0xfe, 0x51, 0xf8, 0xb4, 0xf4, 0xb9, 0xf4, 0x5d, 0x5d, 0x3c, - 0x69, 0x6f, 0x36, 0x4a, 0x96, 0x59, 0x9e, 0xbe, 0x95, 0x29, 0x07, 0x91, 0x19, 0x5a, 0x83, 0xb2, 0x23, 0xd1, 0xb8, - 0xe1, 0x81, 0x11, 0x63, 0xe3, 0xc6, 0xf7, 0x63, 0x06, 0xb2, 0x61, 0xb0, 0xfa, 0x66, 0xa9, 0x4c, 0xd6, 0x57, 0x80, - 0x29, 0xa2, 0xe4, 0x27, 0x2f, 0x73, 0x0e, 0x4f, 0xa1, 0xbe, 0x7e, 0x81, 0xdb, 0x5c, 0xe9, 0xfb, 0x9c, 0xff, 0x98, - 0xd1, 0x1f, 0x11, 0xe8, 0x24, 0x5e, 0x81, 0xdc, 0xe3, 0x39, 0xd4, 0x8d, 0x30, 0xb5, 0x1c, 0x83, 0x03, 0x21, 0x1a, - 0x88, 0xa8, 0x58, 0xa0, 0xa0, 0x2e, 0x0c, 0xb0, 0x86, 0xba, 0x60, 0x0e, 0xcf, 0x73, 0x99, 0x7c, 0x9c, 0x1a, 0x9f, - 0xf9, 0x61, 0x8c, 0x31, 0x93, 0x83, 0x41, 0x58, 0xcd, 0x82, 0xe1, 0x78, 0x34, 0x39, 0x78, 0x06, 0xe7, 0x76, 0x30, - 0x0e, 0xc8, 0x20, 0xa8, 0xcb, 0x55, 0x2c, 0x68, 0x79, 0x7d, 0x69, 0xcb, 0xc0, 0x8f, 0xeb, 0x60, 0xf0, 0x8f, 0xc2, - 0x53, 0xbc, 0x83, 0xe6, 0xe4, 0x4c, 0x86, 0x60, 0x63, 0xbf, 0x26, 0x20, 0x29, 0xeb, 0x69, 0x7e, 0x52, 0x1f, 0x6e, - 0x4c, 0x69, 0xff, 0xcc, 0xe1, 0x05, 0x87, 0x1d, 0x12, 0x28, 0x90, 0xc6, 0xd3, 0x6c, 0xf4, 0x5a, 0x29, 0x72, 0xdf, - 0x15, 0x1c, 0xee, 0xcc, 0x3d, 0x67, 0x7a, 0xe4, 0x14, 0x12, 0xcd, 0x2c, 0xe0, 0x46, 0xfe, 0x5a, 0x5c, 0xc7, 0x79, - 0x96, 0xee, 0x35, 0xdf, 0xec, 0x95, 0x77, 0xa2, 0x8a, 0x6f, 0x47, 0x81, 0xb1, 0x26, 0xe4, 0xbe, 0xea, 0x09, 0xd0, - 0x13, 0x60, 0x0b, 0x80, 0x01, 0xf1, 0x8e, 0x99, 0xc9, 0x8c, 0x47, 0xe0, 0x11, 0xd8, 0xf4, 0x81, 0x2c, 0xee, 0x9c, - 0x4b, 0x92, 0xbf, 0x99, 0x4a, 0x7b, 0xd5, 0x2b, 0x77, 0x0a, 0xb2, 0x5e, 0x6d, 0xe5, 0xae, 0x5b, 0x9f, 0x7d, 0xd3, - 0xe1, 0x15, 0x78, 0x2e, 0xc1, 0x2d, 0xb2, 0xdf, 0x6f, 0x0a, 0x2a, 0x85, 0x51, 0x11, 0xef, 0x24, 0xd7, 0xe8, 0xdf, - 0xee, 0x8d, 0x8d, 0x22, 0xb9, 0xe5, 0xc3, 0x03, 0xa8, 0x33, 0x79, 0x57, 0xdc, 0xce, 0x21, 0x6a, 0xeb, 0x6e, 0x3c, - 0xb0, 0xda, 0xa0, 0x5d, 0xd6, 0x1c, 0xc1, 0x85, 0x17, 0x7b, 0x19, 0x8c, 0x05, 0xce, 0xca, 0x48, 0xa9, 0x71, 0x0d, - 0xa9, 0x05, 0x9f, 0xe4, 0xe9, 0x3d, 0x64, 0xa9, 0x27, 0x41, 0x91, 0xe3, 0x59, 0x0c, 0x99, 0xc6, 0xdb, 0xc0, 0xe3, - 0x77, 0x32, 0x04, 0x69, 0xda, 0x76, 0xdb, 0x1c, 0x81, 0xb2, 0x7b, 0x60, 0x4a, 0x52, 0xd7, 0xc6, 0xd4, 0x40, 0x43, - 0xed, 0xa1, 0x46, 0x2a, 0xe2, 0xec, 0xe8, 0x0d, 0xe8, 0x10, 0xc1, 0xf7, 0x3b, 0xcd, 0xca, 0x8e, 0x17, 0x13, 0x82, - 0x27, 0xef, 0xcb, 0xdb, 0xac, 0xac, 0xca, 0xe8, 0x7d, 0x8a, 0x86, 0x50, 0x89, 0x14, 0xd1, 0x2b, 0x88, 0xa7, 0x57, - 0xe2, 0xef, 0x32, 0xfa, 0x39, 0xa5, 0x71, 0x9a, 0x62, 0xfa, 0x8b, 0x02, 0x7e, 0x3e, 0x07, 0x54, 0x47, 0xdc, 0x09, - 0xd1, 0xb9, 0x04, 0x7b, 0x35, 0x88, 0x66, 0x55, 0x71, 0xc0, 0xd0, 0x8c, 0x6e, 0x05, 0x45, 0x8c, 0x36, 0xcc, 0xfe, - 0x43, 0x81, 0x42, 0x21, 0x55, 0xcc, 0x77, 0xc2, 0x3e, 0x44, 0x3f, 0x62, 0x91, 0xc7, 0xef, 0x5e, 0x9b, 0x21, 0x8d, - 0xee, 0x24, 0xd5, 0x5b, 0x1b, 0x8f, 0x2d, 0x0c, 0x5c, 0x16, 0x5d, 0xae, 0xe9, 0x59, 0xbc, 0xca, 0xa2, 0x0d, 0xe0, - 0x4f, 0xbc, 0x7b, 0xfd, 0x5c, 0x59, 0x98, 0xbc, 0xc8, 0x40, 0x71, 0x70, 0xfc, 0xee, 0xf5, 0x1b, 0x99, 0xae, 0x73, - 0x1e, 0x9d, 0x49, 0x24, 0xad, 0xc7, 0xef, 0x5e, 0xff, 0x82, 0xe6, 0x5e, 0x3f, 0x17, 0xf0, 0xfe, 0x15, 0xf0, 0x96, - 0x51, 0xbc, 0x86, 0x3e, 0xa9, 0xdf, 0xc9, 0x1a, 0x3b, 0xe5, 0xd5, 0x5a, 0x46, 0xbf, 0xa6, 0xb5, 0x27, 0xad, 0xfa, - 0x67, 0xe1, 0x53, 0x3b, 0x4f, 0xc0, 0x73, 0x9b, 0x67, 0xe2, 0x63, 0x64, 0x45, 0x3b, 0x41, 0xf4, 0xf5, 0xde, 0xed, - 0x55, 0x2e, 0xca, 0x08, 0x5f, 0x30, 0xb4, 0x0b, 0x8a, 0xf6, 0xf7, 0x6f, 0x6e, 0x6e, 0x46, 0x37, 0x4f, 0x46, 0xb2, - 0xb8, 0xdc, 0x9f, 0x7c, 0xfb, 0xed, 0xb7, 0xfb, 0xf8, 0x36, 0xf8, 0xba, 0xed, 0xf6, 0x5e, 0x11, 0x3e, 0x60, 0x01, - 0x22, 0x54, 0x7f, 0x0d, 0x57, 0x14, 0xd0, 0xc2, 0x0d, 0xbe, 0x0e, 0xbe, 0xd6, 0x87, 0xce, 0xd7, 0x87, 0xe5, 0xf5, - 0xa5, 0x2a, 0xbf, 0xab, 0xe4, 0x83, 0xf1, 0x78, 0xbc, 0x0f, 0x12, 0xa8, 0xaf, 0x07, 0x7c, 0x10, 0x1c, 0x05, 0x83, - 0x0c, 0x2e, 0x34, 0xe5, 0xf5, 0xe5, 0x51, 0xe0, 0x99, 0xe6, 0x36, 0x58, 0x44, 0x07, 0xe2, 0x12, 0xec, 0x5f, 0xd2, - 0xe0, 0xeb, 0x80, 0xb8, 0x94, 0xaf, 0x20, 0xe5, 0xab, 0x83, 0x67, 0x7e, 0xda, 0xff, 0x52, 0x69, 0x4f, 0xfc, 0xb4, - 0x43, 0x4c, 0x7b, 0xf2, 0xdc, 0x4f, 0x3b, 0x52, 0x69, 0x2f, 0xfd, 0xb4, 0xff, 0x5d, 0x0e, 0x20, 0x75, 0xcf, 0xb7, - 0xfe, 0x3b, 0xf7, 0x5a, 0x83, 0xa7, 0x50, 0x94, 0x5d, 0xc5, 0x97, 0x1c, 0x1a, 0x3d, 0xb8, 0xbd, 0xca, 0x69, 0x30, - 0xc0, 0xf6, 0x7a, 0x26, 0x21, 0xde, 0x07, 0x5f, 0xaf, 0x8b, 0x3c, 0x0c, 0xbe, 0x1e, 0x60, 0x21, 0x83, 0xaf, 0x03, - 0xf2, 0xb5, 0x31, 0x90, 0x11, 0x6c, 0x13, 0xb8, 0x50, 0xa4, 0x43, 0x1b, 0x20, 0xcc, 0x97, 0xc6, 0xd5, 0xf4, 0xaf, - 0xa2, 0x3b, 0x1b, 0xde, 0x12, 0x95, 0x9b, 0x6e, 0x50, 0xd3, 0x13, 0xf0, 0x4e, 0x80, 0x46, 0x45, 0xc1, 0x75, 0x5c, - 0x84, 0xc3, 0x61, 0x79, 0x7d, 0x49, 0xc0, 0x2e, 0x73, 0xc5, 0xe3, 0x2a, 0x0a, 0x84, 0x1c, 0xaa, 0x9f, 0x81, 0x8a, - 0x7c, 0x15, 0x20, 0x20, 0x12, 0xfc, 0x17, 0xd4, 0xf4, 0x9d, 0x64, 0x9b, 0x60, 0x78, 0xc3, 0xcf, 0x3f, 0x66, 0xd5, - 0x50, 0x89, 0x16, 0xaf, 0x05, 0x85, 0x1f, 0xf0, 0xd7, 0x55, 0x1d, 0xfd, 0x05, 0x6e, 0xdc, 0x4d, 0x0d, 0xfb, 0x3b, - 0xe9, 0x58, 0xd4, 0x77, 0x72, 0x9e, 0x2d, 0xa6, 0xad, 0x03, 0xfd, 0x44, 0x92, 0x6a, 0x9e, 0x0d, 0x82, 0x61, 0x30, - 0xe0, 0x0b, 0x76, 0x22, 0xe7, 0xdc, 0x33, 0x9f, 0x7a, 0x24, 0xfd, 0x69, 0x9e, 0x65, 0x03, 0xf0, 0x4d, 0x41, 0x7e, - 0x64, 0xff, 0xbf, 0xe7, 0x43, 0x14, 0x1e, 0x0e, 0x1e, 0xed, 0x93, 0x59, 0xb0, 0xba, 0x45, 0x8f, 0xce, 0x28, 0xc8, - 0xc4, 0x92, 0x17, 0x59, 0xe5, 0x2d, 0x95, 0xbb, 0x75, 0xdb, 0xcb, 0xe3, 0xde, 0xb3, 0x79, 0x15, 0x8b, 0x40, 0x9d, - 0x73, 0xa0, 0x78, 0x43, 0xd9, 0x53, 0xd9, 0x94, 0x90, 0x6a, 0x43, 0xde, 0xb0, 0x1c, 0xb0, 0xe0, 0xb0, 0x37, 0x1c, - 0xee, 0x05, 0x03, 0xa7, 0xce, 0x1d, 0x04, 0x7b, 0xc3, 0xe1, 0x51, 0xe0, 0xee, 0x43, 0xd9, 0xc8, 0xdd, 0x19, 0x69, - 0xc1, 0xfe, 0x59, 0x84, 0x25, 0x05, 0xf1, 0x98, 0xd4, 0xe2, 0x2f, 0x0d, 0x2e, 0x33, 0x00, 0xe8, 0x23, 0x25, 0x01, - 0x33, 0xb0, 0x32, 0x03, 0x08, 0xcd, 0x4d, 0x63, 0x76, 0x06, 0xcc, 0x23, 0x70, 0xcc, 0x23, 0x64, 0x1c, 0x00, 0xb1, - 0x24, 0xc0, 0xb9, 0x0b, 0xa2, 0x58, 0x17, 0xf2, 0x08, 0x40, 0xef, 0xf1, 0x27, 0x31, 0xa5, 0x60, 0x92, 0x8e, 0x55, - 0x08, 0x82, 0x38, 0x3e, 0xbb, 0x16, 0xad, 0xc9, 0x59, 0xa2, 0x83, 0x19, 0x49, 0x80, 0x0d, 0x31, 0xb0, 0x73, 0x70, - 0x3f, 0x07, 0xa5, 0x87, 0xd5, 0x3b, 0x21, 0x17, 0x7c, 0xc7, 0x3d, 0xd9, 0x2c, 0x5c, 0x3d, 0xe1, 0x20, 0xb8, 0xe3, - 0x9a, 0x05, 0x18, 0x55, 0xc5, 0xba, 0xac, 0x78, 0xfa, 0xe1, 0x6e, 0x05, 0xb1, 0xef, 0x70, 0x40, 0xdf, 0xc9, 0x3c, - 0x4b, 0xee, 0x42, 0x67, 0xcf, 0xb5, 0x51, 0xe9, 0x3f, 0x7c, 0x78, 0xf3, 0x73, 0x04, 0x22, 0xc7, 0xda, 0x50, 0xfa, - 0x3b, 0x8e, 0x67, 0x93, 0x1f, 0xe1, 0xc9, 0xdf, 0xd8, 0x77, 0xdc, 0x9e, 0x1e, 0xfd, 0x3e, 0xd4, 0x4d, 0xef, 0xf8, - 0xec, 0x8e, 0x8f, 0x5c, 0x71, 0xa8, 0xae, 0x70, 0x5f, 0xdf, 0xac, 0x7d, 0x23, 0xa4, 0x87, 0xe7, 0x99, 0xf2, 0xc6, - 0xfc, 0x68, 0x07, 0xc3, 0x20, 0x98, 0x6a, 0xa1, 0x24, 0x44, 0xdd, 0x60, 0x4a, 0xc0, 0x10, 0xed, 0xe9, 0x65, 0x35, - 0x45, 0xce, 0x4d, 0x8d, 0x2c, 0xbc, 0x1f, 0x30, 0x2d, 0x74, 0x68, 0xe4, 0x50, 0x7e, 0x70, 0x38, 0x61, 0xcc, 0xc2, - 0x6f, 0x95, 0x30, 0xfd, 0x6a, 0x51, 0x39, 0x07, 0xd1, 0x3d, 0x30, 0xc6, 0x15, 0xbc, 0x80, 0xae, 0xb0, 0xeb, 0xb5, - 0x8a, 0x8a, 0x81, 0xe0, 0x71, 0xc8, 0x01, 0x7a, 0xd8, 0x05, 0x2d, 0x2b, 0x4b, 0x75, 0xab, 0x72, 0x96, 0x2a, 0xea, - 0x32, 0x94, 0x95, 0xb1, 0xc2, 0x7c, 0x2f, 0xd9, 0x0f, 0x05, 0x7a, 0x96, 0x4f, 0x45, 0x17, 0xbc, 0x10, 0x4a, 0xb0, - 0x5c, 0xd7, 0x3b, 0x11, 0x88, 0x3a, 0x3f, 0xf4, 0xae, 0xfa, 0x1a, 0xc7, 0x8e, 0xa7, 0x6f, 0x64, 0xca, 0xb5, 0x09, - 0x85, 0xe6, 0xf3, 0xa5, 0xaf, 0x98, 0x28, 0xd8, 0x0d, 0xf4, 0xab, 0x6d, 0xa3, 0xcf, 0xee, 0xd6, 0x7a, 0x33, 0x28, - 0xd1, 0x31, 0xaf, 0x51, 0x70, 0xad, 0x14, 0x0a, 0x46, 0x7b, 0x1b, 0x7f, 0x86, 0x23, 0xb7, 0xba, 0x3d, 0xf4, 0x7e, - 0xab, 0xe2, 0xcb, 0xb7, 0xe8, 0xdb, 0x69, 0x7f, 0x8e, 0x2a, 0xf9, 0xeb, 0x6a, 0x05, 0x3e, 0x54, 0x10, 0x59, 0xc4, - 0xe2, 0xd2, 0x42, 0x3d, 0xa7, 0xef, 0x8e, 0xdf, 0x82, 0x1f, 0x25, 0xfe, 0xfe, 0xed, 0xfb, 0xa0, 0x26, 0xd3, 0x78, - 0x56, 0x98, 0x0f, 0x6d, 0x0e, 0x08, 0x4d, 0xe2, 0xd2, 0xec, 0xfb, 0x59, 0xdc, 0x64, 0xdf, 0x35, 0x5b, 0x4f, 0x8b, - 0x26, 0x92, 0x94, 0xe1, 0xf6, 0xc1, 0x80, 0x40, 0x1f, 0x20, 0x8a, 0xb3, 0x2f, 0x68, 0x0c, 0x69, 0x3e, 0xb3, 0xef, - 0x47, 0xc4, 0x7b, 0xb9, 0x13, 0x42, 0x8c, 0x2b, 0x2c, 0x1a, 0x3d, 0xe4, 0x33, 0x1e, 0x29, 0xc3, 0xa2, 0xf7, 0x98, - 0x40, 0x9c, 0xe1, 0xb4, 0x7a, 0x8f, 0x98, 0xc7, 0x78, 0x37, 0xd0, 0xb2, 0x87, 0x28, 0xa3, 0x2e, 0x7b, 0xc3, 0xe2, - 0xfb, 0xe3, 0x3a, 0xcc, 0xac, 0xe5, 0xe5, 0x10, 0xfe, 0x06, 0xda, 0x00, 0x9c, 0x72, 0x64, 0xf9, 0x2a, 0xb3, 0xd1, - 0xd5, 0x12, 0xd3, 0x9b, 0x08, 0x62, 0xf1, 0xe8, 0x74, 0x58, 0xbb, 0x3a, 0x55, 0xef, 0x6a, 0xe7, 0x33, 0xd1, 0xab, - 0x40, 0x2b, 0xd7, 0xb6, 0xc7, 0x43, 0xb8, 0x4b, 0x2d, 0xad, 0xb0, 0x11, 0xe5, 0x5c, 0x3c, 0xdd, 0x39, 0x36, 0x27, - 0xa0, 0xc1, 0x95, 0x4c, 0x01, 0x38, 0x4b, 0xab, 0xd1, 0xa8, 0x11, 0xf6, 0x59, 0x39, 0x9f, 0xc3, 0xd6, 0x42, 0x3c, - 0x2d, 0x00, 0xc3, 0x6d, 0x62, 0x50, 0xf2, 0x6e, 0x0c, 0xca, 0xe9, 0x47, 0x05, 0x6f, 0x1d, 0x9c, 0x95, 0xcb, 0x38, - 0x95, 0x37, 0x80, 0xc5, 0x18, 0xf8, 0xa9, 0x58, 0xaa, 0x97, 0x90, 0x2c, 0x79, 0xf2, 0x11, 0xad, 0x36, 0xd2, 0x00, - 0xb8, 0xca, 0xa9, 0xb1, 0xdc, 0x53, 0x20, 0xa1, 0xae, 0x14, 0x95, 0x10, 0x57, 0x55, 0x9c, 0x2c, 0x4f, 0x31, 0x35, - 0xdc, 0x40, 0x2f, 0xa2, 0x40, 0xae, 0xb8, 0x00, 0x92, 0x9e, 0xb3, 0x7f, 0x65, 0x1a, 0x6b, 0xfc, 0xb9, 0x44, 0x01, - 0x93, 0x46, 0x0d, 0xc6, 0x4a, 0xd9, 0x4b, 0x69, 0xa2, 0xbd, 0x05, 0x41, 0xed, 0x5e, 0xfe, 0x05, 0x75, 0x3f, 0x87, - 0x56, 0x84, 0x0d, 0x30, 0x44, 0x79, 0x8e, 0x3b, 0x34, 0xb5, 0x4b, 0xce, 0x03, 0x46, 0x74, 0xde, 0x67, 0xb5, 0xdd, - 0xea, 0xcf, 0x97, 0x80, 0x6d, 0x9a, 0x1a, 0x9f, 0xc2, 0x30, 0x21, 0x26, 0x36, 0xb0, 0x55, 0x56, 0xda, 0x0d, 0x65, - 0xda, 0x49, 0x97, 0xcc, 0x6b, 0xe1, 0x34, 0xef, 0x31, 0xb6, 0x1c, 0xa9, 0xdc, 0xfd, 0x7e, 0x68, 0x7e, 0xb2, 0x9c, - 0x3e, 0xd7, 0x21, 0x9b, 0xbd, 0xf1, 0xa0, 0x39, 0xd1, 0xea, 0xaa, 0x8e, 0x7e, 0x40, 0x07, 0x60, 0xa6, 0x2d, 0x40, - 0xa6, 0x0b, 0x36, 0xed, 0x2b, 0x51, 0x71, 0x49, 0xc2, 0x52, 0x49, 0x60, 0x67, 0x37, 0x25, 0x3b, 0x9b, 0x80, 0x78, - 0x86, 0xbb, 0x9e, 0x16, 0x3b, 0x21, 0x4d, 0x78, 0x8b, 0xbd, 0x04, 0x44, 0x1d, 0xaa, 0xba, 0x84, 0x6c, 0x8c, 0xa1, - 0x8b, 0x7f, 0x51, 0x0a, 0x13, 0xd6, 0x32, 0xa9, 0x4a, 0x4c, 0x10, 0xa4, 0x72, 0xb7, 0x45, 0x60, 0x89, 0x82, 0x1d, - 0xc0, 0xde, 0xbb, 0x51, 0x37, 0xa3, 0xa6, 0xaa, 0x53, 0x2f, 0xc1, 0xc7, 0x69, 0xd6, 0x55, 0x90, 0x59, 0xd8, 0x55, - 0xb1, 0xe6, 0x81, 0x8e, 0x4d, 0xa5, 0x8c, 0x89, 0xbb, 0xb4, 0xc8, 0x10, 0x0f, 0x18, 0x63, 0xe9, 0x42, 0x20, 0xdf, - 0x6c, 0x77, 0xdc, 0xf4, 0x04, 0xa1, 0x9f, 0xb0, 0xa1, 0x04, 0x6e, 0x3a, 0xdb, 0x53, 0xd3, 0xcc, 0x07, 0x44, 0x1c, - 0x06, 0x14, 0x48, 0x36, 0x0e, 0x69, 0x8e, 0xf4, 0x05, 0x49, 0x13, 0x06, 0x86, 0x56, 0x3c, 0x27, 0xc8, 0x8a, 0x42, - 0xcf, 0xd6, 0x55, 0x1b, 0xe7, 0xca, 0x30, 0x47, 0x4b, 0x4e, 0x85, 0xcf, 0x09, 0x32, 0xb1, 0x7b, 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, 0x68, 0x18, 0x62, 0xb7, 0x3f, 0xc1, 0x7e, 0xad, 0x9d, 0xd6, 0x65, 0x8a, 0xe5, 0x65, 0x0a, - 0xd1, 0x5e, 0xc8, 0xfc, 0x46, 0x91, 0xe8, 0x4e, 0x11, 0x86, 0x84, 0x75, 0x94, 0x3d, 0x69, 0x53, 0x03, 0xe8, 0xa9, - 0x17, 0xf0, 0xbc, 0x73, 0x2d, 0xc3, 0x2e, 0xd2, 0xfd, 0x55, 0xc1, 0xa7, 0x74, 0x83, 0x20, 0x45, 0x6f, 0x52, 0x30, - 0xe7, 0xf5, 0x28, 0xa9, 0x37, 0xa7, 0x2d, 0x33, 0xaa, 0x8e, 0x8a, 0x90, 0x72, 0x82, 0xff, 0xe4, 0xa5, 0xd4, 0xc4, - 0x26, 0x4c, 0xf0, 0xc0, 0x87, 0x79, 0x86, 0x0d, 0xbc, 0xdd, 0xbe, 0x4b, 0xc3, 0xa4, 0xcd, 0x36, 0xa4, 0x20, 0xad, - 0x30, 0x71, 0x31, 0xa0, 0xb2, 0xd7, 0xb8, 0x5f, 0xb0, 0x9d, 0x34, 0x05, 0x0f, 0xc2, 0x46, 0x03, 0x13, 0xb7, 0xba, - 0xf8, 0x3a, 0x4c, 0x68, 0xb8, 0xa4, 0xda, 0xd9, 0x49, 0x4b, 0x9a, 0xdb, 0xeb, 0xf2, 0xc2, 0xf6, 0x41, 0xc7, 0x0e, - 0xeb, 0x1a, 0x1e, 0x68, 0x5e, 0xb3, 0x8b, 0x2b, 0xa6, 0x69, 0xa2, 0xb1, 0x1e, 0x52, 0x96, 0x1c, 0xeb, 0x7a, 0xba, - 0xc2, 0xd5, 0x32, 0xd3, 0xc0, 0xee, 0x12, 0x2f, 0xf4, 0x80, 0x87, 0x1d, 0xae, 0x48, 0x74, 0x81, 0xcd, 0x66, 0xab, - 0x9a, 0x4c, 0xf3, 0xfb, 0xb2, 0xe5, 0x26, 0x20, 0x9c, 0xa5, 0xbe, 0xb9, 0x4f, 0x8e, 0x35, 0x6d, 0xf3, 0x93, 0x00, - 0xc7, 0xdb, 0x2b, 0x20, 0xe9, 0x58, 0x82, 0x2e, 0xbe, 0xa5, 0x3f, 0x88, 0xd4, 0x4c, 0x05, 0xbd, 0x77, 0xbe, 0x48, - 0xdd, 0xfc, 0x02, 0x6c, 0xa3, 0x36, 0xc6, 0x34, 0x2b, 0x5b, 0x87, 0x89, 0xb2, 0xb0, 0x46, 0x16, 0x72, 0x09, 0x3e, - 0x98, 0xbb, 0x4d, 0x9d, 0x1e, 0x77, 0x10, 0x61, 0xbf, 0x8b, 0x1e, 0x8f, 0x30, 0x56, 0xac, 0x41, 0x62, 0x58, 0x85, - 0x35, 0x6d, 0x2e, 0x87, 0x28, 0xa7, 0x66, 0xc9, 0x44, 0x4b, 0xea, 0x53, 0x8a, 0x28, 0x05, 0x73, 0xe3, 0x69, 0xd9, - 0x30, 0x25, 0x44, 0xc8, 0x0a, 0xe9, 0x80, 0x6a, 0x2d, 0xb4, 0x54, 0x13, 0xf4, 0x3a, 0xf4, 0xb2, 0xd0, 0x98, 0x82, - 0xe8, 0x23, 0x32, 0xdc, 0x88, 0x23, 0xa3, 0xbb, 0x63, 0x14, 0x13, 0x08, 0x55, 0xed, 0xe5, 0x85, 0xd5, 0xa7, 0x65, - 0x5b, 0x1d, 0xc4, 0x15, 0x22, 0xdf, 0x77, 0x13, 0xd4, 0x18, 0x05, 0x6d, 0x4e, 0x37, 0xfa, 0x6b, 0x11, 0xfa, 0x76, - 0xe1, 0xd8, 0x8d, 0x82, 0x48, 0x88, 0xc0, 0xea, 0x35, 0x15, 0x03, 0xb2, 0xce, 0x63, 0x17, 0xa1, 0x49, 0x77, 0x0b, - 0x51, 0xde, 0xa8, 0xac, 0x3f, 0xae, 0x43, 0xb2, 0xdd, 0x62, 0x59, 0xe0, 0xcb, 0x7e, 0xba, 0xbe, 0x07, 0xf2, 0xfb, - 0xcd, 0xfa, 0xb3, 0x90, 0xdf, 0xaf, 0xb3, 0x2f, 0x81, 0xfc, 0x7e, 0xb3, 0xfe, 0x9f, 0x86, 0xfc, 0x3e, 0x5d, 0x7b, - 0x90, 0xdf, 0x6a, 0x30, 0x7e, 0x2f, 0x58, 0x70, 0xf2, 0x36, 0xa0, 0x2f, 0x24, 0x0b, 0x4e, 0x5e, 0xbd, 0xf2, 0x8d, - 0x40, 0x84, 0x46, 0xae, 0x37, 0xb2, 0x60, 0xc4, 0x6d, 0x81, 0x57, 0xa8, 0x75, 0xf2, 0x81, 0x8a, 0x32, 0x00, 0x5e, - 0x2f, 0xff, 0x91, 0x55, 0xcb, 0x30, 0xd8, 0x0f, 0xc8, 0xcc, 0x41, 0x82, 0x0e, 0x27, 0x70, 0x7b, 0x43, 0x23, 0xcb, - 0xea, 0x8b, 0xe0, 0xc3, 0x47, 0xa3, 0x51, 0x5c, 0x5c, 0xe2, 0xa5, 0xce, 0x6c, 0x24, 0x04, 0x3c, 0xce, 0x78, 0x69, - 0x43, 0x44, 0x2c, 0xe3, 0xf2, 0x4c, 0xc7, 0x66, 0x29, 0xed, 0x56, 0x84, 0x88, 0xf3, 0x67, 0x80, 0x53, 0x6f, 0xf7, - 0x66, 0x8c, 0xfd, 0x50, 0x1c, 0xb1, 0x0e, 0x20, 0xfb, 0x7c, 0xad, 0xdf, 0x9d, 0xc7, 0x25, 0x7f, 0x17, 0x57, 0x4b, - 0x06, 0xbd, 0x84, 0xbb, 0x88, 0xe0, 0x49, 0xe5, 0xb1, 0x4d, 0x0a, 0xa8, 0x3c, 0xd3, 0x40, 0xe5, 0x1d, 0xef, 0x69, - 0x68, 0x87, 0x45, 0xfb, 0x00, 0x1b, 0xe9, 0x72, 0x06, 0x46, 0x8b, 0x2f, 0xaf, 0xb9, 0xa8, 0x7e, 0x06, 0x3c, 0x75, - 0xc1, 0x0b, 0xb8, 0x25, 0x20, 0x17, 0xdb, 0x70, 0x42, 0xa0, 0xc2, 0xf7, 0xec, 0x50, 0x51, 0x63, 0x8c, 0x68, 0xa2, - 0xd1, 0x6f, 0xbc, 0x09, 0xa1, 0x77, 0x27, 0xe8, 0x8a, 0x30, 0x12, 0xde, 0x5f, 0x6b, 0x7e, 0x96, 0x81, 0xf9, 0xbc, - 0x00, 0x28, 0x0d, 0x84, 0x43, 0x65, 0x4a, 0x6e, 0x81, 0x09, 0x1b, 0x63, 0xae, 0x94, 0xa5, 0x1e, 0x52, 0x29, 0x55, - 0x70, 0xba, 0x82, 0xa6, 0x12, 0x70, 0xb8, 0x23, 0x09, 0x60, 0xa6, 0xb6, 0x30, 0x88, 0x6e, 0x9b, 0xd2, 0x2c, 0x8d, - 0x9c, 0x22, 0xcd, 0xe1, 0x93, 0x52, 0x05, 0x3a, 0x7d, 0x96, 0xc4, 0x15, 0xbf, 0x94, 0x05, 0x84, 0xc2, 0x6d, 0xa5, - 0x50, 0xa4, 0xdf, 0x67, 0x62, 0x7d, 0xc5, 0x8b, 0x2c, 0x39, 0x5b, 0x66, 0x65, 0x05, 0xf9, 0xe6, 0xfa, 0xf4, 0x5b, - 0xd4, 0xd3, 0x02, 0xe7, 0x4d, 0x4d, 0x0a, 0x33, 0xf3, 0x78, 0xac, 0x76, 0x3a, 0xa8, 0x57, 0xbd, 0xd7, 0x06, 0xfb, - 0xbd, 0x39, 0xd1, 0xe3, 0xd6, 0x7a, 0xb0, 0x9a, 0xd4, 0x66, 0xaa, 0x82, 0x38, 0x02, 0xea, 0xc0, 0x8e, 0x70, 0x16, - 0x53, 0xba, 0xb6, 0x08, 0x2a, 0x60, 0xed, 0x80, 0x39, 0x32, 0x71, 0x79, 0x76, 0xa3, 0xe4, 0x27, 0x3d, 0x45, 0x61, - 0xd2, 0x28, 0x56, 0xc8, 0x3e, 0x4b, 0x16, 0xae, 0x59, 0x72, 0x4f, 0xae, 0x75, 0x94, 0x34, 0x30, 0xba, 0xe2, 0xf6, - 0x40, 0x1c, 0x26, 0xed, 0x94, 0xed, 0x76, 0x27, 0x13, 0xb0, 0x06, 0xad, 0x24, 0x88, 0xd6, 0xb1, 0x9c, 0x0d, 0x27, - 0x11, 0x40, 0xa8, 0x68, 0xb2, 0xf6, 0xd7, 0x9a, 0x1b, 0x90, 0xf9, 0x50, 0x7b, 0xfa, 0x39, 0x91, 0xbc, 0x1e, 0x59, - 0xcf, 0x38, 0x4e, 0x4f, 0xfb, 0x1c, 0x0c, 0xb3, 0xfc, 0x21, 0x81, 0x48, 0x30, 0x9d, 0xd3, 0xb3, 0x98, 0x6a, 0x33, - 0x61, 0xc3, 0xa3, 0xd0, 0x2f, 0xfb, 0x4e, 0x03, 0xe0, 0x26, 0x3c, 0x1c, 0x3e, 0x1b, 0x93, 0x5a, 0xdb, 0xac, 0xe3, - 0x02, 0xb2, 0xbf, 0xd5, 0x22, 0x73, 0xcf, 0x76, 0xa1, 0xd1, 0xa6, 0xb7, 0x41, 0xbb, 0x46, 0x2a, 0xee, 0xe9, 0x7e, - 0x4d, 0x6a, 0xb7, 0x60, 0xac, 0x04, 0xe9, 0x0f, 0x75, 0x6a, 0x9d, 0x3d, 0xda, 0x64, 0xba, 0xca, 0xfa, 0x8f, 0xcc, - 0xc6, 0x9b, 0x6b, 0x50, 0x80, 0x5a, 0x2f, 0x25, 0x1f, 0xee, 0xad, 0x23, 0x9b, 0x9e, 0x18, 0x96, 0x75, 0x92, 0x91, - 0x91, 0x7a, 0xe4, 0x2a, 0xfc, 0x56, 0x77, 0x16, 0x7e, 0xcb, 0x93, 0xb0, 0xab, 0x61, 0x8a, 0xc3, 0x37, 0x5d, 0x40, - 0x04, 0x4c, 0x90, 0xeb, 0x87, 0x7f, 0x3c, 0xda, 0x34, 0xc9, 0x52, 0xbd, 0xef, 0x7d, 0x86, 0xbf, 0xb3, 0x14, 0xfe, - 0x56, 0xf5, 0x1f, 0x74, 0x73, 0xc5, 0xab, 0xa5, 0x4c, 0xa3, 0xe0, 0xdd, 0xc9, 0xe9, 0x87, 0x40, 0x23, 0xab, 0xe3, - 0xfd, 0xc2, 0x68, 0x94, 0x0d, 0x86, 0x13, 0x68, 0x58, 0x72, 0x79, 0x89, 0xe0, 0x82, 0x1a, 0x9d, 0xfe, 0x74, 0x29, - 0x6f, 0x8e, 0xf3, 0xdc, 0x67, 0x82, 0x0d, 0xe1, 0xd4, 0x7c, 0x61, 0x83, 0xea, 0x84, 0x20, 0xcb, 0x1b, 0x65, 0xe5, - 0x99, 0xd6, 0xbe, 0xa4, 0x67, 0xe7, 0x77, 0x67, 0x5a, 0xc2, 0x63, 0xd1, 0x1d, 0x9f, 0xff, 0x71, 0x98, 0x66, 0xd7, - 0x7b, 0x48, 0xdd, 0x59, 0x00, 0xa6, 0xf1, 0x39, 0x3f, 0x5f, 0x57, 0x95, 0x14, 0xc3, 0x42, 0xde, 0x04, 0x47, 0x87, - 0xea, 0xc1, 0x64, 0x88, 0xd5, 0x63, 0xb0, 0xf7, 0x5f, 0x49, 0x9e, 0x25, 0x1f, 0x59, 0xf0, 0x68, 0x93, 0xb1, 0xa3, - 0x16, 0x0d, 0x1f, 0xd7, 0xc1, 0x11, 0xb4, 0x75, 0xef, 0x38, 0xcf, 0x0f, 0xf7, 0xd5, 0x17, 0x47, 0x87, 0xfb, 0x69, - 0x76, 0x7d, 0xe4, 0x01, 0xed, 0x3b, 0xbb, 0x59, 0x84, 0x34, 0x73, 0xf7, 0x62, 0x70, 0x90, 0x4d, 0x78, 0x68, 0x39, - 0x09, 0x90, 0xc6, 0x98, 0x30, 0x25, 0x28, 0xc1, 0x09, 0x63, 0x38, 0x37, 0xb7, 0xdb, 0xd0, 0x1a, 0xf5, 0x24, 0x1e, - 0xe2, 0x4d, 0x01, 0x9c, 0x06, 0x66, 0xa1, 0x09, 0xa1, 0x49, 0x4d, 0x42, 0x83, 0xcb, 0x13, 0x13, 0x5a, 0xd4, 0x14, - 0x8e, 0x92, 0x37, 0xf1, 0xca, 0x08, 0xb1, 0xb4, 0x50, 0xc0, 0xb4, 0x7e, 0xd6, 0x18, 0xc7, 0xa8, 0x3d, 0xaa, 0x06, - 0x29, 0xab, 0x57, 0xde, 0x37, 0xb0, 0x20, 0xb7, 0x0c, 0x2b, 0x1a, 0xb4, 0x28, 0x04, 0xc8, 0x1d, 0x7d, 0x71, 0x19, - 0xa7, 0xe1, 0xbc, 0xa4, 0x72, 0x41, 0xd8, 0x51, 0xb8, 0x41, 0xb6, 0xb9, 0x54, 0x54, 0x38, 0x92, 0xb5, 0x83, 0xad, - 0x54, 0xb3, 0x73, 0xf4, 0x68, 0x23, 0x10, 0x29, 0xb1, 0x64, 0x47, 0xcd, 0xf9, 0xaa, 0xe2, 0xf3, 0xe1, 0x92, 0x83, - 0x7f, 0x4d, 0xb0, 0xf7, 0x5f, 0xe9, 0x79, 0x6e, 0x27, 0x45, 0xad, 0xc8, 0x65, 0x2c, 0xd2, 0x9c, 0x7f, 0x88, 0xcf, - 0x7f, 0xc0, 0x3c, 0x2f, 0xce, 0xf3, 0xe7, 0x90, 0xa1, 0x0e, 0x8e, 0x1e, 0x6d, 0x92, 0x6a, 0xf4, 0xf2, 0xed, 0x87, - 0xd7, 0x1f, 0xfe, 0x79, 0xf6, 0xfc, 0xf8, 0xc3, 0xcb, 0xef, 0x4f, 0xde, 0xbf, 0x7e, 0x79, 0x3a, 0xb7, 0x0e, 0xad, - 0x0a, 0x27, 0x8d, 0x2c, 0xb6, 0x5b, 0x97, 0xef, 0xd7, 0xb7, 0x2f, 0x5e, 0xbe, 0x7a, 0xfd, 0xf6, 0xe5, 0x8b, 0x5a, - 0xcd, 0x65, 0xbb, 0x21, 0xb0, 0x43, 0xe3, 0x4c, 0xf0, 0x02, 0x8a, 0xd7, 0xd1, 0x1a, 0xb1, 0xd9, 0x1a, 0xde, 0xaf, - 0xd9, 0x74, 0x1d, 0x09, 0x01, 0x16, 0xd9, 0x9e, 0xde, 0x2c, 0xd0, 0x70, 0x69, 0x36, 0x8e, 0xbf, 0xc4, 0xfc, 0xde, - 0xbc, 0xc4, 0xef, 0xde, 0xcb, 0x1b, 0xd3, 0x15, 0x3d, 0x42, 0x0a, 0xb9, 0x6b, 0xf6, 0xfc, 0x8f, 0x43, 0x5f, 0x5a, - 0x86, 0x22, 0x05, 0x55, 0x2e, 0xfc, 0xaa, 0x83, 0x3d, 0x6d, 0xb9, 0x17, 0x40, 0xe0, 0x89, 0xe0, 0xe8, 0x70, 0xdf, - 0xcf, 0x7d, 0xf4, 0x47, 0xf4, 0xb3, 0xd7, 0x39, 0x2c, 0x15, 0xc6, 0xa1, 0x99, 0xb6, 0x73, 0xba, 0x41, 0x68, 0x24, - 0x77, 0xfe, 0xa9, 0x15, 0x64, 0xc8, 0x95, 0x24, 0x91, 0x9d, 0x44, 0x65, 0x91, 0x62, 0x4a, 0xfb, 0x43, 0xff, 0x75, - 0x7d, 0xc6, 0x1b, 0x3e, 0x17, 0xa5, 0x2c, 0x02, 0xe8, 0x47, 0x3b, 0x5e, 0xc4, 0x9e, 0x17, 0x97, 0x05, 0x7b, 0xd4, - 0x49, 0xde, 0x61, 0x44, 0xf6, 0xdb, 0x9f, 0x7a, 0x1d, 0xfb, 0x83, 0xb8, 0x1f, 0x7b, 0xba, 0x33, 0x2d, 0xf2, 0x62, - 0x1b, 0x78, 0x7f, 0x5c, 0x8f, 0xf9, 0x49, 0x46, 0xff, 0x21, 0xe9, 0x65, 0x4c, 0xaf, 0x62, 0x7a, 0x2a, 0x16, 0x75, - 0xe7, 0xec, 0xd8, 0x98, 0x31, 0x94, 0x4f, 0x43, 0x40, 0x9e, 0xd0, 0xf7, 0x01, 0xcd, 0x25, 0x67, 0x23, 0xad, 0x2b, - 0xfb, 0x10, 0x17, 0x97, 0xdc, 0x84, 0x6a, 0x31, 0x6f, 0x2b, 0x3d, 0x2a, 0xc4, 0x1b, 0x16, 0x80, 0x65, 0xe9, 0x69, - 0x93, 0x82, 0x6c, 0x94, 0x54, 0x45, 0xfe, 0x13, 0xbf, 0x03, 0xae, 0xad, 0xac, 0xe4, 0x0a, 0x78, 0xf5, 0xff, 0xd3, - 0xdc, 0xb3, 0x37, 0xb7, 0x6d, 0x23, 0xff, 0x7f, 0x3f, 0x05, 0xc3, 0xe4, 0x52, 0x31, 0x21, 0x69, 0x92, 0xb2, 0x6c, - 0x45, 0xb2, 0xec, 0x6b, 0xf3, 0x98, 0x4b, 0xc7, 0x6d, 0x3a, 0x89, 0x9b, 0xb9, 0xab, 0xeb, 0xb1, 0x28, 0x09, 0x92, - 0x78, 0xa1, 0x48, 0x0d, 0x49, 0xf9, 0x51, 0x85, 0xf7, 0x59, 0xee, 0xb3, 0xdc, 0x27, 0xfb, 0xcd, 0xee, 0x02, 0x20, - 0xf8, 0xd0, 0xc3, 0x4d, 0x7a, 0xf7, 0x9b, 0x36, 0x89, 0x08, 0x02, 0x4b, 0x60, 0x01, 0x2c, 0x16, 0xfb, 0xf4, 0x67, - 0x5c, 0xf6, 0x62, 0xb6, 0xd8, 0x7e, 0x9f, 0xfb, 0xfc, 0x99, 0xd9, 0xb8, 0x24, 0x81, 0xe1, 0xb3, 0xb3, 0x78, 0x36, - 0x0b, 0x59, 0x4b, 0x17, 0xc9, 0x43, 0x74, 0x53, 0x7e, 0xe6, 0xec, 0x91, 0x23, 0x22, 0x76, 0x1a, 0xf9, 0xa6, 0xad, - 0x25, 0x46, 0xcc, 0x64, 0x48, 0x3b, 0xe2, 0x5c, 0x51, 0x36, 0x7b, 0x83, 0xea, 0x0d, 0x3e, 0x2f, 0xc5, 0xd6, 0xb5, - 0x26, 0xf1, 0x6a, 0x14, 0x32, 0x0b, 0x97, 0x3b, 0x7c, 0x72, 0x3d, 0x5a, 0x8d, 0x46, 0x90, 0xa5, 0xe5, 0x91, 0x63, - 0x42, 0xdc, 0x99, 0x38, 0xc5, 0xfb, 0x60, 0x6e, 0xf4, 0x61, 0x50, 0x76, 0x56, 0xed, 0x3e, 0xd8, 0x8a, 0x80, 0xa8, - 0x87, 0x3e, 0x90, 0xc1, 0xdd, 0xaf, 0x61, 0xd7, 0x0e, 0xf4, 0x0f, 0xb0, 0xfa, 0x52, 0xbd, 0xdf, 0xb4, 0xf5, 0x07, - 0x97, 0xfa, 0x07, 0xc4, 0x31, 0x66, 0x2f, 0x7e, 0x49, 0xab, 0x57, 0x37, 0x75, 0x52, 0x7a, 0xaf, 0x30, 0x8f, 0x01, - 0x08, 0x7d, 0x5f, 0x05, 0xfe, 0x2c, 0x8a, 0xd3, 0x2c, 0x18, 0xeb, 0x57, 0xfd, 0xb7, 0x41, 0xeb, 0x72, 0x91, 0xb5, - 0x8c, 0x2b, 0x73, 0x9c, 0xa9, 0x29, 0x50, 0x04, 0xc1, 0xc4, 0x0c, 0x28, 0x9b, 0x2a, 0xa9, 0x3b, 0x68, 0x6b, 0x45, - 0x41, 0x9a, 0xb1, 0xd2, 0x38, 0x1b, 0x40, 0xbd, 0x4a, 0x3e, 0x15, 0x4c, 0x0c, 0xa5, 0x63, 0x4b, 0xa3, 0x4f, 0x37, - 0x95, 0x97, 0xab, 0x35, 0x1e, 0xe5, 0x59, 0x71, 0x5a, 0x62, 0x0c, 0x60, 0xe1, 0x38, 0x43, 0xcf, 0x8f, 0x54, 0xa3, - 0xcf, 0xd2, 0xb9, 0x3b, 0xfc, 0xae, 0xcc, 0x17, 0xc0, 0xf9, 0x0d, 0x16, 0x17, 0x51, 0x9c, 0x69, 0x10, 0xd8, 0x06, - 0xbe, 0x38, 0xac, 0x1a, 0x89, 0x71, 0xa8, 0x2d, 0x23, 0xe7, 0xc4, 0xe0, 0x7b, 0x3c, 0xfc, 0x5a, 0x3c, 0xbc, 0x59, - 0x29, 0x82, 0x05, 0x5d, 0x16, 0x22, 0x98, 0xc0, 0x2c, 0x3e, 0x8f, 0x6f, 0xab, 0x7a, 0x90, 0x97, 0xc3, 0xdd, 0x67, - 0x6f, 0x4b, 0xb0, 0xc9, 0x22, 0xab, 0x5f, 0x8b, 0x27, 0x26, 0x15, 0x8c, 0x4e, 0x65, 0x4f, 0xa1, 0xe1, 0x87, 0xe0, - 0x61, 0x32, 0xb0, 0x13, 0xc3, 0xb3, 0x00, 0x48, 0x12, 0x3f, 0xa6, 0x87, 0xf9, 0xb5, 0x48, 0x9d, 0x2c, 0x12, 0x17, - 0x2b, 0x87, 0x33, 0x50, 0xd7, 0x68, 0xb9, 0xca, 0x30, 0xd4, 0x2e, 0x74, 0x80, 0xe5, 0xba, 0x86, 0xa1, 0x3b, 0x81, - 0x4a, 0x17, 0x6c, 0x62, 0xae, 0x6b, 0xc1, 0xa4, 0x5e, 0xc6, 0x99, 0x5e, 0x20, 0x5e, 0x48, 0xdf, 0x51, 0x50, 0x05, - 0x8f, 0x09, 0x1f, 0xc6, 0xd8, 0x2c, 0xe2, 0xd4, 0xb7, 0xc6, 0xa8, 0xd0, 0x69, 0xa0, 0x0c, 0x63, 0x82, 0xd3, 0x6f, - 0x85, 0x8d, 0x83, 0x85, 0xf0, 0x9b, 0xa5, 0x61, 0x0e, 0x9f, 0xac, 0xa3, 0xfc, 0xec, 0xc9, 0x3a, 0xcd, 0x07, 0x4f, - 0xd6, 0xbe, 0xb4, 0x15, 0xd0, 0x2f, 0x74, 0x32, 0x14, 0x18, 0x22, 0x1a, 0x86, 0xf9, 0x75, 0xe1, 0xb9, 0x53, 0x8c, - 0x17, 0x56, 0x19, 0x95, 0x6b, 0xa8, 0xba, 0x1f, 0x70, 0x05, 0xfd, 0x32, 0x09, 0x16, 0x7e, 0x72, 0x4f, 0xfa, 0x7c, - 0x53, 0x55, 0xfa, 0x1b, 0xba, 0x46, 0x84, 0x9e, 0x10, 0x40, 0x34, 0x5f, 0xd7, 0xfe, 0x2a, 0xcb, 0x18, 0x1f, 0xad, - 0x54, 0x6a, 0xc2, 0xb7, 0xae, 0xf5, 0xe7, 0xcc, 0x9e, 0xb0, 0xcc, 0x0f, 0x42, 0x6a, 0xd2, 0x17, 0xd9, 0xea, 0x6b, - 0xc3, 0x4b, 0xcb, 0xc3, 0x8b, 0xca, 0xeb, 0x07, 0x07, 0x43, 0x47, 0x00, 0xf5, 0x1b, 0x47, 0x86, 0x59, 0xac, 0x9a, - 0x67, 0x94, 0xde, 0xfd, 0x57, 0xa7, 0x83, 0xc1, 0x74, 0x44, 0x30, 0x1d, 0x2c, 0x1a, 0xc7, 0x13, 0xf6, 0xcb, 0xfb, - 0xb7, 0x32, 0x6d, 0x16, 0x48, 0x80, 0x86, 0x7c, 0x61, 0xa6, 0xc8, 0x3f, 0x24, 0xc8, 0x3b, 0x50, 0x82, 0x2b, 0x4d, - 0x2e, 0xa1, 0x24, 0xd7, 0xb5, 0x33, 0xea, 0x3b, 0x9b, 0x50, 0xaf, 0x07, 0x31, 0xb6, 0x4a, 0xf2, 0x93, 0x03, 0xaa, - 0x4d, 0xa7, 0x1d, 0x55, 0x02, 0x34, 0x24, 0x30, 0xc2, 0x02, 0x0b, 0x90, 0xe1, 0x73, 0xe0, 0x16, 0x17, 0x0a, 0x7b, - 0x81, 0x72, 0x76, 0xf7, 0xac, 0xcc, 0xaa, 0x60, 0x2b, 0xfd, 0xf4, 0x04, 0x73, 0x76, 0xc1, 0x79, 0x0d, 0x51, 0x3e, - 0x4e, 0x0e, 0xe8, 0x51, 0xab, 0xec, 0x88, 0x02, 0x88, 0xb8, 0xda, 0xf5, 0x38, 0x80, 0x07, 0x6d, 0x15, 0x48, 0x11, - 0x0f, 0xa5, 0x7e, 0xae, 0x6b, 0x0b, 0xce, 0x1a, 0xf1, 0x70, 0x42, 0x10, 0x6b, 0xc0, 0x81, 0xbd, 0xab, 0x6b, 0x0b, - 0xff, 0x0e, 0x47, 0x2e, 0xde, 0xf8, 0x77, 0x2d, 0x97, 0xbf, 0x2a, 0xf6, 0x5a, 0x5a, 0xde, 0x6b, 0x63, 0x3e, 0xb9, - 0xe0, 0x48, 0x20, 0x6f, 0xd6, 0x73, 0x54, 0xd0, 0x36, 0x4c, 0xee, 0x5c, 0x4c, 0xee, 0x64, 0xc3, 0xe4, 0x4e, 0xb6, - 0x4c, 0x6e, 0xc8, 0x27, 0x52, 0x93, 0xa8, 0x4b, 0xd0, 0x39, 0x4c, 0x22, 0x8f, 0x33, 0x1a, 0x3d, 0xbe, 0xcf, 0x10, - 0x4f, 0x56, 0x1a, 0x82, 0x71, 0xd4, 0x06, 0x5c, 0x35, 0xe1, 0x45, 0x41, 0x44, 0x7d, 0xe0, 0x72, 0xd7, 0x89, 0x71, - 0x43, 0x0e, 0xce, 0x56, 0x58, 0x1d, 0x2f, 0xac, 0x52, 0xca, 0x2f, 0xde, 0x9a, 0x6f, 0x18, 0xe9, 0x7c, 0xcb, 0x48, - 0xc7, 0xa5, 0xad, 0xcb, 0x87, 0x4d, 0x9b, 0x50, 0x1d, 0x14, 0xac, 0x41, 0x30, 0x18, 0xc5, 0x25, 0x53, 0x5e, 0x87, - 0x9b, 0x69, 0xac, 0xb2, 0xa2, 0x96, 0x7e, 0x9a, 0xde, 0xc6, 0x09, 0x68, 0x5c, 0x00, 0xcc, 0xc3, 0x96, 0xd4, 0x22, - 0x88, 0x78, 0x30, 0x97, 0x8d, 0x8b, 0xa9, 0x78, 0xaf, 0x2e, 0x29, 0xaf, 0xd3, 0xa1, 0x1a, 0x4b, 0x3f, 0xcb, 0x58, - 0x82, 0x48, 0xf7, 0x21, 0xea, 0xf7, 0xff, 0x93, 0x65, 0xd6, 0x40, 0x43, 0x42, 0x85, 0xaa, 0x23, 0x85, 0x5e, 0x02, - 0x6f, 0x95, 0x88, 0x83, 0x58, 0x09, 0x0c, 0x97, 0x48, 0xc4, 0xff, 0x84, 0xdb, 0xb5, 0x95, 0x28, 0xae, 0x4b, 0xee, - 0x91, 0x61, 0x2f, 0xfd, 0xc9, 0x07, 0x50, 0xec, 0xb5, 0x3c, 0x13, 0x8c, 0x74, 0xd5, 0x30, 0x70, 0x09, 0x31, 0x7b, - 0xe3, 0x82, 0x48, 0x22, 0x95, 0xe4, 0x26, 0x50, 0xe0, 0x3d, 0xe9, 0x5b, 0xd3, 0xab, 0xb5, 0x97, 0x1f, 0xcc, 0x02, - 0xa3, 0x46, 0x35, 0x81, 0xb4, 0x85, 0x83, 0x53, 0x79, 0xe7, 0x0a, 0x4d, 0xf7, 0xc8, 0x00, 0xc9, 0xef, 0x25, 0xe4, - 0x33, 0x75, 0xc4, 0x85, 0x76, 0x98, 0xc0, 0xa9, 0x75, 0xe9, 0x5c, 0xe5, 0x4f, 0x67, 0xf8, 0xcb, 0xbd, 0xca, 0x9f, - 0x8e, 0xf0, 0x97, 0x77, 0x85, 0x99, 0xeb, 0x1a, 0x2e, 0xf2, 0xca, 0x98, 0xf5, 0xd3, 0xd2, 0x7a, 0x22, 0xfb, 0xb3, - 0x07, 0x2c, 0x1b, 0x3e, 0xc1, 0x8f, 0x9f, 0xac, 0x53, 0xf0, 0xb8, 0x54, 0xc7, 0x10, 0xd9, 0x89, 0x91, 0x37, 0x96, - 0xcf, 0x36, 0x94, 0x8f, 0x8c, 0xff, 0xf2, 0xc1, 0x8f, 0xab, 0x24, 0x2e, 0xce, 0x94, 0xb2, 0x18, 0xe2, 0x7a, 0x14, - 0x44, 0x7e, 0x72, 0x7f, 0x4d, 0xd7, 0x8b, 0x96, 0xe0, 0xdd, 0xa5, 0x78, 0x85, 0xd8, 0xcb, 0xb2, 0xba, 0x2b, 0x53, - 0x04, 0xbc, 0xf7, 0xfc, 0xa0, 0x1f, 0xfc, 0x3d, 0x51, 0xd8, 0xb6, 0xd2, 0x05, 0x94, 0x4f, 0x48, 0xe9, 0x43, 0xd7, - 0x4f, 0xd6, 0x2d, 0x56, 0x07, 0x53, 0x19, 0x6d, 0x85, 0x2f, 0x84, 0xe9, 0xc1, 0xcb, 0xec, 0x62, 0x12, 0xf4, 0x50, - 0x9f, 0x35, 0x8a, 0xef, 0xac, 0x27, 0xeb, 0xec, 0x4c, 0x5f, 0xf8, 0xc9, 0x27, 0x36, 0xb1, 0xc6, 0x41, 0x32, 0x0e, - 0x99, 0xde, 0xd3, 0x47, 0xa1, 0x1f, 0x7d, 0xe2, 0x8f, 0x56, 0xbc, 0xca, 0x50, 0x43, 0xbd, 0xf3, 0xee, 0x2b, 0x70, - 0x42, 0x22, 0x3b, 0x64, 0x56, 0x1b, 0xb0, 0xa0, 0xbd, 0x94, 0x02, 0xaf, 0x82, 0x51, 0x2c, 0x6a, 0x99, 0x60, 0x60, - 0x09, 0x4a, 0x73, 0xf0, 0x58, 0x35, 0x75, 0x9c, 0x2f, 0xdd, 0x54, 0x87, 0x4a, 0xc2, 0x4a, 0x99, 0x72, 0xf1, 0x1a, - 0x21, 0xfc, 0xf1, 0xcf, 0x51, 0x32, 0xec, 0xfd, 0x3f, 0x27, 0xa1, 0x7c, 0xd9, 0x08, 0xa1, 0xd4, 0x22, 0x4f, 0x89, - 0x07, 0x7c, 0x9c, 0x33, 0x98, 0x9b, 0x3f, 0xad, 0x36, 0xf6, 0xd3, 0x74, 0xb5, 0x60, 0x13, 0xd2, 0x0c, 0x9e, 0x15, - 0x9d, 0x2a, 0xdf, 0x2c, 0xd4, 0x8e, 0xfd, 0xb6, 0xf2, 0x8e, 0x0f, 0x5f, 0x82, 0xc5, 0x02, 0x30, 0x94, 0xf1, 0x74, - 0xaa, 0x17, 0x77, 0xfc, 0x1d, 0xcd, 0xdc, 0xc3, 0xdf, 0x56, 0x6f, 0x5e, 0x3b, 0x6f, 0x64, 0xe3, 0x08, 0x18, 0x63, - 0xa1, 0x7e, 0xe5, 0x7c, 0xb1, 0xd2, 0x5f, 0x31, 0xa2, 0xa9, 0x1f, 0x6d, 0x1e, 0xce, 0x65, 0x69, 0x89, 0x2f, 0x19, - 0x9b, 0x00, 0xc3, 0x6d, 0xd6, 0x4a, 0xaf, 0x43, 0x76, 0xc3, 0xa4, 0x6a, 0xb7, 0xfe, 0xb1, 0x86, 0x16, 0x18, 0x7b, - 0x8e, 0xab, 0x8c, 0x39, 0x57, 0xa7, 0x0c, 0x69, 0x88, 0x63, 0xe0, 0x23, 0x57, 0xb7, 0x58, 0x65, 0x4b, 0x0d, 0x4d, - 0x5d, 0xe9, 0xc0, 0xc6, 0x9e, 0x9d, 0x6d, 0x28, 0xef, 0x61, 0xe2, 0xe9, 0xe6, 0xbe, 0x99, 0xae, 0xd1, 0x83, 0x58, - 0xdd, 0x1c, 0x4f, 0x21, 0xec, 0xbc, 0x56, 0x21, 0x0e, 0xd9, 0x84, 0xb1, 0x26, 0x21, 0x99, 0x4e, 0xd2, 0x17, 0x61, - 0xed, 0x88, 0x66, 0xbf, 0x42, 0x0e, 0xd5, 0x38, 0x37, 0x5a, 0x79, 0xe4, 0x23, 0x4c, 0xe8, 0x1a, 0xb1, 0x34, 0xdd, - 0x88, 0x30, 0x39, 0xe9, 0xa6, 0x5e, 0xd4, 0x2e, 0xe3, 0xa3, 0x28, 0x37, 0x1d, 0x13, 0x58, 0x02, 0x1c, 0x60, 0xf5, - 0x5b, 0x78, 0xbc, 0x5c, 0x2f, 0xb8, 0xbd, 0x4a, 0x32, 0x1b, 0xe9, 0xdc, 0x96, 0x60, 0xd3, 0xfb, 0x5b, 0x9d, 0x77, - 0xaa, 0x74, 0x4c, 0x37, 0x76, 0xad, 0x55, 0x22, 0xbd, 0x35, 0x71, 0x11, 0x02, 0x10, 0x7d, 0xaa, 0xd0, 0x57, 0x36, - 0x9d, 0xb2, 0x71, 0x96, 0x1a, 0x42, 0x78, 0x24, 0xa3, 0xc7, 0x82, 0xd7, 0xd0, 0xa3, 0x81, 0xfe, 0x13, 0xf8, 0xd0, - 0x8b, 0x20, 0x4b, 0xbc, 0x43, 0xe2, 0xce, 0xd4, 0x8c, 0x26, 0x82, 0x58, 0x46, 0x11, 0xff, 0x0a, 0x24, 0x07, 0x6f, - 0x28, 0xc7, 0xae, 0xf1, 0xf3, 0xa7, 0x58, 0x17, 0xb1, 0xb4, 0x6a, 0xd9, 0x4e, 0x8a, 0xb6, 0x6d, 0xdf, 0xb5, 0xfb, - 0xa6, 0xe3, 0x3a, 0xb9, 0x6e, 0x82, 0xef, 0xd6, 0xa7, 0x7d, 0x37, 0x3d, 0xb6, 0x6a, 0x43, 0xab, 0x55, 0xf4, 0x90, - 0x76, 0x9e, 0xfb, 0xc2, 0xd5, 0x4d, 0x32, 0x99, 0x53, 0x68, 0xdb, 0x38, 0xbe, 0x61, 0xc9, 0x17, 0x0f, 0xa5, 0x0c, - 0x7c, 0xbf, 0xfe, 0x1c, 0xb9, 0x0e, 0x10, 0xe1, 0x2c, 0x5e, 0x3e, 0x60, 0x08, 0x6d, 0xdd, 0xd4, 0xc7, 0x61, 0x9c, - 0x32, 0x75, 0x0c, 0x24, 0x04, 0xf9, 0xc2, 0x41, 0xfc, 0xfc, 0xfe, 0xf5, 0x87, 0x0f, 0xba, 0x89, 0x99, 0x40, 0x53, - 0x15, 0x3a, 0x5f, 0x50, 0x3b, 0xa8, 0x7f, 0xe3, 0xba, 0xa3, 0x13, 0x86, 0x2e, 0xb5, 0xe5, 0x35, 0x47, 0x65, 0xb5, - 0x25, 0xc7, 0x4f, 0x1e, 0xfe, 0x65, 0xba, 0x89, 0xee, 0x35, 0xae, 0x06, 0xda, 0xb0, 0xfd, 0x78, 0x2b, 0x95, 0x2c, - 0x82, 0xe8, 0xba, 0xa1, 0xd4, 0xbf, 0x6b, 0x28, 0x85, 0xab, 0x5c, 0x8d, 0x56, 0xad, 0xe2, 0x85, 0xc2, 0x1a, 0x40, - 0x22, 0xe7, 0x5d, 0xe8, 0x52, 0xee, 0x53, 0x5f, 0xd0, 0x69, 0x1e, 0xc9, 0xbd, 0xda, 0xeb, 0x86, 0x62, 0x7e, 0x09, - 0x92, 0xb8, 0x1d, 0x87, 0x60, 0xf0, 0xc7, 0x54, 0xad, 0x5c, 0x99, 0x6d, 0x94, 0xe6, 0xba, 0x0a, 0x10, 0x62, 0x6f, - 0xaf, 0x33, 0xb6, 0x58, 0xb2, 0xc4, 0xcf, 0x56, 0x09, 0xbb, 0x0e, 0xe3, 0xdb, 0x47, 0x85, 0x39, 0xfd, 0x8e, 0xca, - 0xf3, 0x60, 0x36, 0x97, 0xb5, 0xcf, 0x5a, 0x6c, 0x20, 0x27, 0x70, 0xeb, 0x07, 0xf2, 0xff, 0xfc, 0xdb, 0xb6, 0xff, - 0xf3, 0xef, 0x9d, 0x55, 0x01, 0x7c, 0x3e, 0x34, 0xb3, 0xc1, 0x1e, 0xeb, 0xa2, 0xf9, 0x4b, 0x65, 0x9c, 0x37, 0xd7, - 0xa9, 0x4d, 0x02, 0xbc, 0xaf, 0x4d, 0x41, 0xad, 0xb0, 0xbc, 0x6e, 0x1e, 0xd4, 0x31, 0x18, 0xd7, 0xce, 0x9e, 0x41, - 0xa5, 0x2f, 0xea, 0xda, 0xd0, 0xe8, 0xed, 0x35, 0x23, 0x7f, 0x1c, 0xc3, 0xbb, 0xc6, 0xf0, 0x85, 0xdd, 0xe7, 0x72, - 0xc9, 0x97, 0xc3, 0xa1, 0xcc, 0x2d, 0xa7, 0x36, 0x05, 0x13, 0xff, 0xb3, 0x5a, 0x09, 0x3f, 0x3c, 0x7b, 0x8e, 0x41, - 0xbe, 0xf7, 0x83, 0x97, 0x43, 0x34, 0x46, 0x3b, 0x19, 0x25, 0x05, 0xb3, 0xb2, 0x91, 0xb4, 0x91, 0x31, 0x79, 0x0d, - 0x68, 0x8d, 0xae, 0x41, 0x29, 0x26, 0x1c, 0xcb, 0x87, 0x86, 0xf9, 0x72, 0xc8, 0x05, 0x4b, 0xdc, 0xfe, 0xb5, 0x57, - 0x5d, 0xda, 0x5c, 0x2c, 0x5b, 0x42, 0xba, 0xa9, 0x91, 0xfe, 0x07, 0x2b, 0xb3, 0x42, 0x8e, 0x87, 0x02, 0x7e, 0x90, - 0x28, 0x0c, 0x73, 0xcc, 0x77, 0xf2, 0x6e, 0x93, 0x8d, 0xd8, 0xcf, 0xbb, 0x6d, 0xc4, 0x2e, 0xf6, 0xb2, 0x11, 0xfb, - 0xf9, 0xab, 0xdb, 0x88, 0xbd, 0x53, 0x6d, 0xc4, 0x60, 0x12, 0x5f, 0xb3, 0xbd, 0x0c, 0xb7, 0x84, 0xd5, 0x46, 0x7c, - 0x9b, 0x0e, 0x5c, 0xce, 0xd2, 0xa6, 0xe3, 0x39, 0x03, 0x19, 0x01, 0x9f, 0x95, 0x30, 0x9e, 0x81, 0x11, 0xd7, 0x9f, - 0x6f, 0x6e, 0x15, 0xc6, 0x33, 0xd5, 0xd8, 0x2a, 0xe2, 0x11, 0x5f, 0x8b, 0x28, 0x4e, 0x64, 0xe0, 0xe4, 0x98, 0x22, - 0xe6, 0x93, 0x75, 0x68, 0x28, 0x59, 0xad, 0xa5, 0xf5, 0x9a, 0x27, 0x4c, 0xa0, 0x7a, 0x68, 0x3d, 0x25, 0x1b, 0x7a, - 0xcf, 0x45, 0x6c, 0x0b, 0x15, 0x82, 0xb4, 0x12, 0xa6, 0x38, 0x11, 0x6b, 0xfd, 0xb7, 0x3b, 0xf7, 0xfb, 0x4b, 0xb7, - 0xdf, 0x76, 0xc1, 0x39, 0x1b, 0x6e, 0x98, 0x58, 0xe0, 0xf4, 0xdb, 0x6d, 0x28, 0xb8, 0x55, 0x0a, 0x3c, 0x28, 0x08, - 0x94, 0x82, 0x0e, 0x14, 0x8c, 0x95, 0x82, 0x23, 0x28, 0x98, 0x28, 0x05, 0xc7, 0x50, 0x70, 0xa3, 0xe7, 0x97, 0x91, - 0xec, 0xee, 0xb1, 0x71, 0x65, 0xd2, 0xa5, 0x42, 0x94, 0x1d, 0x9b, 0x2e, 0x58, 0x4d, 0xf9, 0xb3, 0x5e, 0x6c, 0x92, - 0x74, 0xb1, 0x97, 0x98, 0xb7, 0x73, 0x46, 0x81, 0xa2, 0x5f, 0xe1, 0x99, 0x63, 0x67, 0x31, 0xd8, 0x4d, 0x8b, 0x00, - 0x0c, 0x02, 0x0f, 0x9a, 0x6e, 0x80, 0xc0, 0xa8, 0x2f, 0x67, 0x4e, 0x04, 0xb1, 0x50, 0xe6, 0xb2, 0x78, 0x47, 0x9f, - 0xb3, 0xe4, 0x12, 0x28, 0x2c, 0x4e, 0x5a, 0xaa, 0x54, 0xf2, 0x6b, 0xd8, 0x1d, 0xbc, 0x62, 0xa3, 0xd5, 0x4c, 0x3b, - 0x8f, 0x67, 0x3b, 0x4d, 0x08, 0xd4, 0x57, 0xd0, 0x4b, 0x9d, 0xd4, 0x2f, 0x96, 0x58, 0x96, 0xfc, 0x5b, 0xf4, 0x98, - 0x97, 0xeb, 0x67, 0xd0, 0x37, 0x2d, 0x23, 0x03, 0x16, 0xf8, 0x0e, 0xe0, 0x48, 0xd1, 0xe1, 0x9f, 0x03, 0x9e, 0x95, - 0xe7, 0x0b, 0x5f, 0xe9, 0xcf, 0xe9, 0x8f, 0x2c, 0x4d, 0xfd, 0x99, 0xa8, 0x5f, 0xef, 0x27, 0x18, 0xed, 0xc8, 0xfb, - 0x17, 0x22, 0x10, 0x24, 0x79, 0x41, 0xcd, 0x36, 0x23, 0x89, 0x6f, 0x35, 0xb0, 0xfe, 0x81, 0x05, 0x55, 0xd8, 0x29, - 0x04, 0x36, 0x4c, 0x61, 0xd9, 0xa2, 0x00, 0x36, 0xff, 0x0d, 0x0b, 0xab, 0x85, 0x99, 0x3f, 0xab, 0x16, 0xd1, 0x3a, - 0xc8, 0xd5, 0xbe, 0x49, 0x85, 0x7e, 0xa9, 0xf0, 0x4b, 0x34, 0xd4, 0x61, 0x3c, 0xfb, 0x53, 0xd5, 0xd3, 0x5b, 0xcc, - 0x0a, 0x3e, 0x44, 0x66, 0x90, 0x0d, 0x6d, 0xc4, 0xb1, 0x66, 0x03, 0x0a, 0x7b, 0x51, 0x36, 0xb7, 0xd0, 0xb5, 0xac, - 0xe5, 0x45, 0x86, 0x69, 0xe3, 0xdc, 0xae, 0xab, 0x0e, 0xb5, 0xbd, 0x64, 0x36, 0xf2, 0x5b, 0xae, 0x77, 0x6c, 0x8a, - 0x3f, 0xb6, 0xd3, 0x31, 0x72, 0x84, 0xa0, 0x4d, 0x82, 0x9b, 0xf5, 0x34, 0x8e, 0x32, 0x6b, 0xea, 0x2f, 0x82, 0xf0, - 0xbe, 0xb7, 0x88, 0xa3, 0x38, 0x5d, 0xfa, 0x63, 0xd6, 0x2f, 0x2e, 0xd4, 0x7d, 0x0c, 0xd5, 0xc0, 0xbd, 0x05, 0x5d, - 0xdb, 0x4b, 0xd8, 0x82, 0x5a, 0xcb, 0x48, 0x0c, 0xd3, 0x90, 0xdd, 0xe5, 0xfc, 0xf3, 0xa5, 0xca, 0x54, 0x15, 0x97, - 0x1c, 0xb5, 0x00, 0x8e, 0x94, 0x87, 0x79, 0x80, 0xe0, 0x46, 0xfd, 0xa5, 0x3f, 0xc1, 0xc8, 0x84, 0xb6, 0xd7, 0x49, - 0xd8, 0x42, 0xb3, 0x3b, 0x1b, 0x81, 0x27, 0xf1, 0xed, 0x29, 0xf4, 0x16, 0x1b, 0x5b, 0x29, 0x0b, 0xa7, 0xf8, 0xc6, - 0x42, 0xcf, 0x12, 0x01, 0xc7, 0xc2, 0x8b, 0x38, 0x40, 0x63, 0x8b, 0x3e, 0xbc, 0xee, 0x79, 0x9a, 0xd3, 0x5f, 0x04, - 0x91, 0x45, 0xc3, 0x39, 0x76, 0x96, 0x0a, 0x2c, 0x15, 0x7f, 0xc6, 0x1a, 0xab, 0xbb, 0x9a, 0xd3, 0x87, 0xcb, 0xda, - 0x34, 0x8c, 0x6f, 0x7b, 0xf3, 0x60, 0x32, 0x61, 0x51, 0x1f, 0xfb, 0x2c, 0x0b, 0x59, 0x18, 0x06, 0xcb, 0x34, 0x48, - 0xfb, 0x0b, 0xff, 0x8e, 0x43, 0x3d, 0xdc, 0x04, 0xb5, 0xcd, 0xa1, 0xb6, 0xf7, 0x86, 0xaa, 0x80, 0x01, 0x2f, 0x16, - 0x82, 0xc3, 0xbb, 0xd6, 0xd1, 0x9c, 0xca, 0x38, 0xf7, 0x86, 0xba, 0x4c, 0xd8, 0x7a, 0xe1, 0x27, 0xb3, 0x20, 0xea, - 0x39, 0xb9, 0x7d, 0xb3, 0xa6, 0x85, 0xf1, 0xb8, 0xdb, 0xed, 0xe6, 0xf6, 0x44, 0x3c, 0x39, 0x93, 0x49, 0x6e, 0x8f, - 0xc5, 0xd3, 0x74, 0xea, 0x38, 0xd3, 0x69, 0x6e, 0x07, 0xa2, 0xa0, 0xed, 0x8d, 0x27, 0x6d, 0x2f, 0xb7, 0x6f, 0x95, - 0x1a, 0xb9, 0xcd, 0xf8, 0x53, 0xc2, 0x26, 0x7d, 0x5c, 0x48, 0x64, 0x56, 0xda, 0x3b, 0x76, 0x9c, 0x1c, 0x29, 0xc0, - 0x65, 0x89, 0x36, 0xa1, 0xac, 0xe7, 0x6a, 0xbd, 0x77, 0x4d, 0xad, 0xf8, 0xdc, 0x78, 0xdc, 0x58, 0x6f, 0xe2, 0x27, - 0x9f, 0xae, 0x34, 0x65, 0x14, 0xbe, 0x4f, 0xd5, 0xd6, 0x02, 0x0d, 0xd6, 0x5d, 0x0f, 0x42, 0x76, 0xf5, 0x47, 0x71, - 0x02, 0x7b, 0x36, 0xf1, 0x27, 0xc1, 0x2a, 0xed, 0xb9, 0xde, 0xf2, 0x4e, 0x14, 0xf1, 0xb5, 0x5e, 0x14, 0xe0, 0xde, - 0xeb, 0xa5, 0x71, 0x18, 0x4c, 0x44, 0xd1, 0xa6, 0xbd, 0xe4, 0x7a, 0x46, 0x1f, 0x1d, 0xd6, 0x03, 0x0c, 0xbb, 0xe0, - 0x87, 0xa1, 0x66, 0xb7, 0x53, 0x8d, 0xf9, 0x29, 0xca, 0x97, 0x35, 0x27, 0x25, 0xbc, 0xa0, 0x73, 0xba, 0x7b, 0xb8, - 0xbc, 0x93, 0x6b, 0xde, 0x3d, 0x5a, 0xde, 0xe5, 0x7f, 0x5d, 0xb0, 0x49, 0xe0, 0x6b, 0xad, 0x62, 0x35, 0xb9, 0x0e, - 0xc8, 0xa0, 0x8d, 0xf5, 0x86, 0x65, 0x2a, 0xb6, 0x05, 0x84, 0x36, 0x7c, 0x14, 0x2c, 0x96, 0x71, 0x92, 0xf9, 0x51, - 0x96, 0xe7, 0xc3, 0xab, 0x3c, 0xef, 0x5f, 0x04, 0xad, 0xcb, 0x7f, 0xb4, 0xe8, 0x9c, 0x26, 0x9d, 0x4d, 0x6e, 0x5c, - 0x99, 0xaf, 0x99, 0x6a, 0x33, 0x02, 0xc7, 0x18, 0xda, 0x8b, 0xa8, 0x95, 0xe9, 0x94, 0xac, 0x57, 0x26, 0x24, 0xcb, - 0xea, 0x64, 0x83, 0x52, 0xae, 0x82, 0x27, 0x10, 0x54, 0x78, 0xcd, 0x06, 0x17, 0x8a, 0xfd, 0x09, 0x30, 0x2b, 0x58, - 0x99, 0xfc, 0x0a, 0x9e, 0x6c, 0xe2, 0x19, 0xbf, 0xdb, 0xcd, 0x33, 0xfe, 0x9a, 0xed, 0xc3, 0x33, 0x7e, 0xf7, 0xd5, - 0x79, 0xc6, 0x27, 0x75, 0xbf, 0x82, 0xb7, 0xf1, 0x40, 0x97, 0x1a, 0x06, 0x38, 0x9a, 0x12, 0x8a, 0xd8, 0xf3, 0xf6, - 0x0f, 0xbb, 0x01, 0x08, 0x68, 0x94, 0x83, 0x8e, 0x4e, 0x6e, 0x90, 0xc7, 0xbe, 0x8b, 0x06, 0x7f, 0x4f, 0xd4, 0xe7, - 0xe9, 0x74, 0xf0, 0x2a, 0x56, 0x0a, 0xe4, 0x13, 0x37, 0xbe, 0x28, 0x45, 0x57, 0xa0, 0x37, 0xc2, 0x0a, 0x13, 0xf3, - 0x4f, 0x80, 0x73, 0x36, 0x59, 0x1d, 0x4f, 0xa4, 0xf5, 0x59, 0xbf, 0xdc, 0x85, 0x96, 0x34, 0xf9, 0x14, 0x2e, 0x38, - 0x35, 0x51, 0xe2, 0x8c, 0x65, 0xdc, 0x67, 0xf6, 0xfb, 0xfb, 0xb7, 0x93, 0xd6, 0xdb, 0xd8, 0xc8, 0x83, 0xf4, 0x5d, - 0xd5, 0x01, 0x86, 0xeb, 0x7e, 0x06, 0xea, 0x70, 0x72, 0x6e, 0x41, 0xa6, 0x26, 0x98, 0x86, 0xd7, 0xd4, 0xfc, 0xac, - 0x34, 0xd2, 0x9e, 0xda, 0x90, 0x27, 0xba, 0xaa, 0x1d, 0xc6, 0xdc, 0xfb, 0x60, 0xcd, 0x39, 0x40, 0xcc, 0xdd, 0x85, - 0x7e, 0xc3, 0x13, 0x6a, 0x1e, 0x4c, 0xf2, 0xdc, 0xe8, 0x0b, 0x44, 0x28, 0x07, 0x2d, 0xdb, 0xc5, 0xc4, 0xa5, 0xb7, - 0xd2, 0xa6, 0x81, 0x6b, 0x08, 0x49, 0xfd, 0xf7, 0x16, 0x14, 0xea, 0x5c, 0x59, 0xc8, 0x71, 0xa6, 0x6b, 0x84, 0x3e, - 0x32, 0xb4, 0x50, 0x06, 0x04, 0x1a, 0x60, 0x89, 0x7f, 0xf1, 0x4a, 0x14, 0xd4, 0x6d, 0x38, 0x09, 0x39, 0x68, 0x11, - 0x00, 0x5e, 0xfe, 0x42, 0xae, 0x4d, 0x64, 0x87, 0xd7, 0xc1, 0x87, 0x5c, 0x97, 0xbc, 0x1f, 0x2e, 0xbf, 0xd3, 0x93, - 0x03, 0x68, 0x70, 0x5a, 0x31, 0x1c, 0xd8, 0x61, 0xa1, 0x08, 0xac, 0x44, 0x7a, 0x6b, 0xda, 0xe9, 0xad, 0xf6, 0x6c, - 0x2d, 0x22, 0x64, 0x64, 0xfe, 0xd2, 0x82, 0x2b, 0x3e, 0xd2, 0x5e, 0x4e, 0xf1, 0x94, 0x60, 0x1c, 0xfd, 0x55, 0x0a, - 0xb4, 0x11, 0x2f, 0xaa, 0x48, 0x7f, 0xfa, 0xe3, 0x55, 0x92, 0xc6, 0x49, 0x6f, 0x19, 0x07, 0x51, 0xc6, 0x92, 0x1c, - 0x51, 0x75, 0x89, 0xf8, 0x11, 0xe8, 0xb9, 0x5a, 0xc7, 0x4b, 0x7f, 0x1c, 0x64, 0xf7, 0x3d, 0x87, 0xb3, 0x14, 0x4e, - 0x9f, 0x73, 0x07, 0x4e, 0x63, 0xfd, 0x1e, 0xc7, 0xe6, 0x73, 0x64, 0xfc, 0x92, 0x3a, 0x3b, 0xa3, 0x2e, 0xf3, 0xbe, - 0xf2, 0x96, 0x62, 0x84, 0x00, 0xfb, 0xe1, 0x27, 0xd6, 0x0c, 0xa8, 0x3c, 0x4c, 0xb5, 0x33, 0x61, 0x33, 0x13, 0xa9, - 0x36, 0xc8, 0xe5, 0xc5, 0x1f, 0xbb, 0x63, 0x68, 0x4e, 0x73, 0x31, 0x70, 0x3c, 0xc6, 0x3e, 0x3d, 0xeb, 0xf9, 0x90, - 0x51, 0xcb, 0xdc, 0xa7, 0xe6, 0x88, 0x4d, 0xe3, 0x84, 0x51, 0x3c, 0x59, 0xb7, 0xbb, 0xbc, 0xdb, 0x1f, 0xfc, 0xf6, - 0xe1, 0x37, 0xc3, 0x89, 0xe2, 0xac, 0x25, 0x80, 0x19, 0x3b, 0xa0, 0xd5, 0xcf, 0x33, 0x60, 0x0d, 0x09, 0xf3, 0x63, - 0x0a, 0xdd, 0xd5, 0xd3, 0xf5, 0x7e, 0x63, 0xd8, 0xae, 0x65, 0xcc, 0xcf, 0xbc, 0x84, 0x85, 0x7e, 0x16, 0xdc, 0x08, - 0x9e, 0xb1, 0x7d, 0xb4, 0xbc, 0x13, 0x73, 0x8c, 0x07, 0xde, 0x03, 0x26, 0xa9, 0xd2, 0x15, 0x31, 0x49, 0xd5, 0x62, - 0x9c, 0xa4, 0x7e, 0x6d, 0x34, 0x22, 0x92, 0x45, 0xe5, 0xa4, 0xef, 0x2c, 0xef, 0xd4, 0x23, 0xba, 0x68, 0x26, 0x4f, - 0xea, 0x6a, 0x08, 0xb2, 0x45, 0x30, 0x99, 0x84, 0x2c, 0x2f, 0x4d, 0x74, 0x79, 0x2e, 0x15, 0xe4, 0x48, 0x3c, 0xf8, - 0xa3, 0x34, 0x0e, 0x57, 0x19, 0x6b, 0x46, 0x17, 0x21, 0xc7, 0x73, 0x0a, 0xe4, 0xe0, 0xef, 0x72, 0x5f, 0x3b, 0xc0, - 0x6e, 0xc3, 0x32, 0x71, 0xfa, 0x10, 0x71, 0xd8, 0x6a, 0x97, 0xbb, 0x0e, 0xaf, 0x64, 0xa7, 0xcd, 0x86, 0x81, 0x98, - 0x70, 0x2c, 0x11, 0xf5, 0xd6, 0x6c, 0x97, 0x97, 0xc9, 0xa8, 0xab, 0xb2, 0x28, 0x2f, 0x0f, 0xe6, 0xcf, 0xd9, 0x63, - 0x2f, 0x9a, 0xf7, 0xd8, 0x0b, 0xb1, 0xc7, 0xb6, 0xaf, 0xcc, 0xc7, 0x53, 0x17, 0xfe, 0xeb, 0x17, 0x03, 0xea, 0x39, - 0x5a, 0x7b, 0x79, 0xa7, 0xb9, 0xcb, 0x3b, 0xcd, 0xf2, 0x96, 0x77, 0x1a, 0x82, 0x46, 0x7b, 0x10, 0xd3, 0xf6, 0x0c, - 0xd3, 0xd1, 0xa0, 0x10, 0xfe, 0x38, 0xa5, 0x57, 0xee, 0x21, 0xbc, 0x83, 0x56, 0x9d, 0xfa, 0x3b, 0x6f, 0xfb, 0x56, - 0xa7, 0xbd, 0x24, 0x88, 0xb6, 0x61, 0x67, 0xfe, 0x68, 0xc4, 0x26, 0xbd, 0x69, 0x3c, 0x5e, 0xa5, 0xff, 0xe2, 0xfd, - 0xe7, 0x48, 0xdc, 0x4a, 0x08, 0x2a, 0x70, 0x44, 0x53, 0x50, 0x94, 0xdc, 0x30, 0x01, 0x61, 0x2d, 0xe7, 0xa9, 0x47, - 0xe1, 0x91, 0x3d, 0xfb, 0xb0, 0x61, 0x91, 0x37, 0x23, 0xfa, 0x4f, 0x9b, 0xa5, 0xcd, 0x24, 0xe6, 0x0b, 0xd0, 0xb2, - 0x15, 0x1d, 0x0f, 0xc7, 0x06, 0x9f, 0x4d, 0xa7, 0xdb, 0xdc, 0xdd, 0x4b, 0xf1, 0xa5, 0x2b, 0x71, 0xa8, 0xf0, 0x73, - 0x8b, 0x3b, 0xa6, 0x6c, 0x87, 0xba, 0x69, 0x8d, 0xd4, 0xa0, 0x6e, 0x39, 0x10, 0x8a, 0xba, 0x7b, 0x52, 0xf9, 0xc7, - 0x2f, 0x0e, 0xe1, 0x3f, 0xe2, 0xea, 0x7f, 0xcd, 0x9a, 0x18, 0xf5, 0xb7, 0x65, 0x4b, 0x70, 0x62, 0x95, 0x90, 0x11, - 0xdf, 0xbf, 0xfe, 0x74, 0xfa, 0xb0, 0x06, 0x7b, 0xd7, 0x26, 0x53, 0xaa, 0x6a, 0xed, 0xef, 0xe3, 0x18, 0x52, 0x77, - 0xd6, 0xab, 0x0b, 0xf4, 0x90, 0xb1, 0x7b, 0x36, 0x80, 0x46, 0xe2, 0x1e, 0x41, 0x5a, 0x7c, 0x1d, 0xdb, 0xd0, 0x55, - 0xe2, 0xf5, 0xa6, 0xab, 0xc4, 0xab, 0xdd, 0x57, 0x89, 0x1f, 0xf6, 0xba, 0x4a, 0xbc, 0xfa, 0xea, 0x57, 0x89, 0xd7, - 0xf5, 0xab, 0xc4, 0x45, 0x2c, 0xec, 0x67, 0xcd, 0xb7, 0x2b, 0xfe, 0xf3, 0x23, 0x29, 0xe5, 0xce, 0xe3, 0x41, 0xc7, - 0xa1, 0x90, 0xc7, 0x17, 0x7f, 0xf8, 0x62, 0x81, 0x0b, 0xf1, 0x3d, 0x9a, 0x93, 0x15, 0x57, 0x0b, 0x4e, 0xd9, 0xf1, - 0x3b, 0x4a, 0x71, 0x18, 0x47, 0xb3, 0x9f, 0x41, 0x29, 0x0b, 0xe2, 0xc0, 0x44, 0x79, 0x11, 0xa4, 0x3f, 0xc7, 0xcb, - 0xd5, 0xf2, 0x2d, 0xc0, 0xfa, 0x18, 0xa4, 0xc1, 0x28, 0x64, 0xd2, 0x13, 0x99, 0xcc, 0xdf, 0xb8, 0x4c, 0x1c, 0x2c, - 0x4e, 0xc5, 0x4f, 0xff, 0x4e, 0xfc, 0x44, 0x9b, 0x54, 0xfe, 0x9b, 0xec, 0xea, 0xf4, 0xe6, 0x8b, 0x88, 0x50, 0x02, - 0x2a, 0x9d, 0x7e, 0xf8, 0x65, 0xe4, 0x22, 0x36, 0x1a, 0x46, 0x29, 0xec, 0x1d, 0x36, 0xc2, 0x61, 0xb5, 0x4b, 0xcd, - 0xca, 0x30, 0x65, 0x08, 0xae, 0xba, 0x18, 0x7e, 0x11, 0xaf, 0x52, 0x36, 0x89, 0x6f, 0x23, 0xdd, 0x8c, 0xa4, 0x93, - 0x01, 0x68, 0x38, 0x65, 0x1b, 0x4c, 0x1e, 0xf9, 0x01, 0x19, 0xe5, 0x38, 0x69, 0xe9, 0x90, 0xbb, 0x74, 0xb5, 0xb4, - 0x48, 0xd5, 0x6c, 0xe1, 0x10, 0x75, 0x99, 0xe5, 0xe8, 0x51, 0xab, 0x15, 0x0f, 0x1e, 0xd6, 0x52, 0x98, 0x6a, 0xc4, - 0x36, 0x97, 0x0a, 0xa7, 0xad, 0x48, 0x08, 0x17, 0x45, 0x1c, 0x8c, 0x86, 0x89, 0xe3, 0x6f, 0xc8, 0x75, 0xb5, 0x78, - 0x0b, 0x51, 0x44, 0xf2, 0x15, 0x9f, 0x0f, 0x1e, 0x15, 0x82, 0x1e, 0x5f, 0x2a, 0x68, 0x7c, 0x77, 0xc3, 0x92, 0xd0, - 0xbf, 0x6f, 0x19, 0x79, 0x1c, 0xfd, 0x08, 0x08, 0x78, 0x15, 0xdf, 0x46, 0x6a, 0x05, 0x4c, 0xd6, 0xd2, 0xb0, 0x96, - 0x1a, 0xe3, 0x97, 0x80, 0xe3, 0x8a, 0xd2, 0x03, 0x48, 0x93, 0x3b, 0x63, 0x7f, 0x37, 0xe9, 0xdf, 0x7f, 0x18, 0xb9, - 0x79, 0x1e, 0xcb, 0x0f, 0xfd, 0xb2, 0xdc, 0xe3, 0x33, 0x4f, 0x9f, 0x3e, 0xda, 0x3c, 0xec, 0x72, 0x7a, 0xf6, 0x86, - 0xd6, 0xc6, 0xc6, 0x5d, 0x00, 0xbd, 0xb8, 0x88, 0x57, 0xe3, 0x39, 0x1a, 0xba, 0x7e, 0xbd, 0xf1, 0x66, 0x00, 0x13, - 0xb3, 0x94, 0xca, 0xa1, 0x57, 0x8a, 0x0a, 0x2c, 0xe0, 0xf7, 0x5f, 0x43, 0x00, 0xce, 0xff, 0x21, 0x1a, 0xea, 0xab, - 0x86, 0xdf, 0xe2, 0x83, 0x87, 0x2d, 0xde, 0x3e, 0x24, 0xd3, 0xe4, 0xa1, 0x2d, 0x84, 0x72, 0xad, 0x99, 0xc8, 0xe4, - 0x55, 0xa4, 0xa9, 0x61, 0xe4, 0x36, 0x45, 0xc8, 0x13, 0x5f, 0x61, 0x36, 0x5d, 0xd3, 0xb9, 0xa3, 0x81, 0xc9, 0x38, - 0xb5, 0xaa, 0x10, 0x19, 0x6e, 0xf2, 0xc0, 0x90, 0x7c, 0x55, 0xdf, 0x2d, 0x82, 0xc8, 0xc4, 0x28, 0xf0, 0xf5, 0x37, - 0xfe, 0x1d, 0xc4, 0x41, 0x06, 0xe2, 0x56, 0x7d, 0x05, 0x85, 0xa6, 0xea, 0x37, 0x07, 0xa9, 0x9e, 0xf4, 0x46, 0x4c, - 0x08, 0x2d, 0xde, 0xf0, 0x1b, 0x4d, 0xd3, 0x34, 0x79, 0x8d, 0xd0, 0xe4, 0x3d, 0x02, 0xcb, 0xf1, 0x3a, 0x00, 0xda, - 0x92, 0x7c, 0x79, 0x47, 0x25, 0x70, 0x33, 0x40, 0x9d, 0xac, 0x28, 0xe0, 0xa1, 0xfe, 0x3a, 0x8e, 0x28, 0x10, 0x17, - 0x7a, 0x08, 0xd3, 0xe6, 0x27, 0x10, 0x11, 0xb8, 0xa7, 0xe1, 0x85, 0x1d, 0xdf, 0x72, 0x49, 0xb0, 0xe6, 0xd0, 0xe3, - 0xb0, 0xcf, 0x9a, 0x63, 0xc2, 0x45, 0x0a, 0x15, 0x04, 0xad, 0x43, 0x25, 0xc4, 0xb3, 0xc9, 0x1a, 0x68, 0x23, 0xde, - 0x8b, 0xee, 0xb2, 0x05, 0x8b, 0x56, 0x3a, 0xe6, 0x84, 0xc2, 0x18, 0x7d, 0x50, 0xe7, 0x15, 0x31, 0x5b, 0x40, 0x6d, - 0x9a, 0x5b, 0xce, 0xe9, 0x2c, 0x4c, 0x39, 0x49, 0xf5, 0xcd, 0x31, 0x57, 0x6c, 0xa6, 0x9c, 0xb6, 0x55, 0x4f, 0x08, - 0x3e, 0xa5, 0x71, 0xd5, 0x91, 0x8b, 0x2c, 0xa1, 0x01, 0x06, 0x45, 0xc7, 0xe0, 0xe2, 0x22, 0x81, 0xf6, 0x96, 0x5f, - 0x9d, 0x34, 0xa9, 0x91, 0xf1, 0x2b, 0x82, 0xa2, 0xc4, 0xa8, 0x83, 0xe1, 0xfd, 0x84, 0xc0, 0x44, 0x1b, 0xe1, 0x8c, - 0x6b, 0x70, 0x36, 0x0c, 0xfa, 0x13, 0xbb, 0xa7, 0x83, 0x84, 0x50, 0xf5, 0x89, 0xdd, 0x83, 0xed, 0xdf, 0x6b, 0x90, - 0xa6, 0xe8, 0x5b, 0xc8, 0xb5, 0x09, 0xa1, 0xfe, 0xc7, 0x10, 0xac, 0x6a, 0xcb, 0x06, 0x72, 0xf2, 0x2d, 0x54, 0x1c, - 0x51, 0x0c, 0x59, 0x9d, 0xc5, 0x26, 0xe6, 0x26, 0xfe, 0xad, 0x46, 0x1c, 0x5b, 0x0d, 0x5b, 0xc3, 0x78, 0xe6, 0x3a, - 0xce, 0x41, 0xad, 0x3e, 0x08, 0xb2, 0x9b, 0x6a, 0x1b, 0x66, 0x36, 0x70, 0x1d, 0x2b, 0x78, 0x66, 0x7b, 0xfd, 0xda, - 0x19, 0xad, 0xc4, 0x92, 0x1c, 0xa2, 0xf8, 0xeb, 0xf4, 0xc9, 0xba, 0x55, 0xdb, 0x90, 0x46, 0xd5, 0x64, 0x1e, 0xfb, - 0x96, 0x73, 0xf9, 0xd7, 0xb0, 0x7e, 0xf4, 0x53, 0x24, 0x4b, 0xca, 0x6b, 0x32, 0x84, 0x68, 0xc8, 0x2d, 0xd8, 0x46, - 0x7f, 0xd1, 0x9e, 0x6b, 0x2d, 0xda, 0x3e, 0x86, 0x31, 0x94, 0xe9, 0xb2, 0x85, 0x4f, 0x99, 0x0a, 0xa0, 0xf2, 0xc5, - 0xb4, 0x4a, 0xe1, 0x78, 0xdc, 0x55, 0x56, 0x68, 0xf4, 0xb6, 0x72, 0x0b, 0x08, 0x7f, 0xc3, 0xf1, 0x69, 0x8f, 0x20, - 0x2e, 0x01, 0xd4, 0x80, 0xd8, 0xe9, 0x3b, 0x01, 0xae, 0x96, 0x65, 0x70, 0xe5, 0x43, 0x72, 0x7f, 0x60, 0x78, 0xe8, - 0xa0, 0x0e, 0x4d, 0xc2, 0x6b, 0x3e, 0xee, 0x1e, 0x08, 0x92, 0x45, 0x93, 0x32, 0xc0, 0xca, 0xf9, 0xb5, 0x3f, 0xb8, - 0x12, 0x45, 0x81, 0xa4, 0x02, 0x71, 0x03, 0x45, 0xc9, 0xe3, 0x08, 0x17, 0x3f, 0x6d, 0xb7, 0x60, 0x2f, 0x2e, 0x06, - 0x1b, 0x50, 0x44, 0x30, 0xd9, 0x4c, 0x11, 0x8a, 0x43, 0xe4, 0x6a, 0x74, 0x0b, 0x6e, 0x09, 0x46, 0x74, 0xe3, 0x4a, - 0xcc, 0x84, 0x4d, 0x61, 0xd1, 0x26, 0xe0, 0xb1, 0x28, 0xf7, 0x95, 0x5a, 0x07, 0xbb, 0xa5, 0xd6, 0xd9, 0x2e, 0xa9, - 0x35, 0xb9, 0x53, 0xdd, 0x26, 0xfe, 0x52, 0xf1, 0xc8, 0x13, 0xcc, 0xb9, 0xea, 0x98, 0x57, 0x12, 0x75, 0xa3, 0xf7, - 0x95, 0x68, 0x55, 0x83, 0x46, 0x56, 0x82, 0x28, 0xfe, 0x56, 0x2e, 0x28, 0x42, 0xa1, 0xae, 0xca, 0xc6, 0x2f, 0x0a, - 0xd9, 0x38, 0xdd, 0x6a, 0x0a, 0x47, 0x1a, 0xc1, 0xfd, 0x2b, 0x4e, 0x6a, 0xf2, 0x76, 0x50, 0x38, 0xab, 0x15, 0x3d, - 0x55, 0xdc, 0xaf, 0x8a, 0x8b, 0x86, 0xe2, 0xd4, 0x27, 0x6e, 0x19, 0x65, 0xdf, 0xbe, 0x72, 0xd5, 0xc2, 0xfb, 0xaa, - 0x28, 0x07, 0xa9, 0x3b, 0x76, 0x59, 0x16, 0xab, 0xcb, 0xa6, 0xec, 0x7e, 0xa3, 0xbe, 0x56, 0x16, 0x89, 0xf4, 0x93, - 0x21, 0x04, 0x0b, 0x31, 0x7d, 0x45, 0xaf, 0x2d, 0x6d, 0x20, 0xb0, 0x93, 0x0d, 0x6e, 0x7d, 0xbb, 0xa5, 0xf3, 0x94, - 0x2f, 0xa1, 0xd0, 0xc2, 0xab, 0x32, 0x08, 0xc4, 0xef, 0xd5, 0xba, 0xe1, 0x94, 0xc7, 0x43, 0x9e, 0x9f, 0xef, 0x20, - 0x5e, 0xd4, 0x1c, 0x55, 0x91, 0x8f, 0x3b, 0xd3, 0x22, 0xf3, 0x5c, 0xac, 0x5a, 0x07, 0x4a, 0x42, 0x9c, 0x35, 0xf7, - 0x8c, 0x29, 0xcb, 0xe8, 0x79, 0x8d, 0x9e, 0xf8, 0x2e, 0x5f, 0x3a, 0xc9, 0x2a, 0xc2, 0xd8, 0xf6, 0x56, 0x96, 0xf8, - 0xe3, 0x4f, 0x4a, 0x97, 0x85, 0x9c, 0x13, 0x64, 0xc0, 0x65, 0x4d, 0x41, 0xdf, 0xc7, 0x50, 0x90, 0xac, 0x67, 0x7b, - 0xa9, 0x22, 0x7d, 0xe9, 0x3d, 0x76, 0xda, 0xfe, 0x8b, 0xe9, 0x61, 0x45, 0x28, 0xea, 0x75, 0xca, 0x22, 0xf3, 0x0d, - 0xfd, 0xc8, 0xe6, 0xab, 0xc5, 0x68, 0xad, 0xca, 0x56, 0x15, 0x91, 0x6b, 0x5d, 0xcc, 0xaa, 0x7e, 0x76, 0x3a, 0x9d, - 0x96, 0x05, 0x8d, 0x8e, 0x76, 0x88, 0xc2, 0xc2, 0xc7, 0x8e, 0xe3, 0x54, 0xfb, 0xbe, 0x1d, 0xed, 0x16, 0xca, 0x6d, - 0xbb, 0x8d, 0x3d, 0x46, 0xdc, 0xee, 0xc2, 0x5f, 0x1d, 0x1d, 0xb9, 0x5d, 0xec, 0xec, 0x92, 0x59, 0x44, 0x9f, 0x8c, - 0x21, 0x82, 0x8c, 0x2d, 0xd2, 0xde, 0x98, 0xa1, 0x0e, 0xc6, 0x56, 0x36, 0x34, 0x1a, 0x0e, 0x58, 0x33, 0x30, 0x15, - 0x71, 0xc5, 0xaa, 0x70, 0x34, 0x94, 0x87, 0xd7, 0x84, 0xf7, 0xe2, 0x23, 0xb8, 0x51, 0xd6, 0x75, 0x99, 0x36, 0x0e, - 0xab, 0xe3, 0xfc, 0xa5, 0x54, 0x4f, 0x83, 0x03, 0x70, 0x2d, 0x14, 0xda, 0x24, 0x9f, 0xc5, 0xbf, 0xa5, 0xfc, 0xff, - 0xc5, 0xf2, 0xae, 0x6c, 0x3f, 0xd2, 0x05, 0x89, 0x76, 0xb1, 0x5b, 0xa8, 0xd7, 0x4d, 0x6b, 0x40, 0x5a, 0x19, 0x4c, - 0x55, 0x05, 0x3a, 0x28, 0xe9, 0x4b, 0x09, 0x40, 0x1a, 0xc4, 0xef, 0xc8, 0x31, 0xc3, 0x14, 0x17, 0x22, 0xc4, 0x22, - 0x7d, 0x1d, 0x8c, 0xc1, 0x7c, 0xde, 0x45, 0xfd, 0x41, 0x69, 0x4d, 0x80, 0x36, 0xbe, 0x36, 0xb6, 0xbd, 0xc4, 0xfd, - 0x55, 0xbd, 0x96, 0x00, 0x0c, 0x28, 0x73, 0x61, 0x13, 0xa2, 0x21, 0x81, 0x56, 0x59, 0xdc, 0xd4, 0x4b, 0xf9, 0x56, - 0xd5, 0xb3, 0x89, 0x8e, 0x21, 0xb8, 0xe6, 0x2a, 0x04, 0x5b, 0x68, 0x0b, 0x60, 0xb0, 0x7c, 0xf9, 0xe1, 0xb3, 0x05, - 0x53, 0xac, 0xae, 0x47, 0x17, 0xa7, 0x1c, 0xd7, 0xaf, 0x85, 0x67, 0x67, 0x4a, 0xfb, 0x1f, 0xe5, 0x8b, 0x3f, 0x34, - 0x0a, 0xf4, 0x2e, 0x4a, 0x12, 0x3a, 0x6e, 0x2d, 0xee, 0x19, 0x7b, 0xd5, 0x5e, 0x04, 0xd1, 0xfe, 0x75, 0xfd, 0xbb, - 0xbd, 0xeb, 0xc2, 0x81, 0xb1, 0x77, 0x65, 0x38, 0x71, 0xc8, 0x72, 0x21, 0x1b, 0xfc, 0xa0, 0x08, 0x14, 0x55, 0xaf, - 0x63, 0x1d, 0x5b, 0x11, 0x97, 0x7f, 0xb1, 0x1a, 0x0c, 0x4f, 0xce, 0xee, 0x16, 0xa1, 0x76, 0xc3, 0x12, 0x48, 0xed, - 0x33, 0xd0, 0x5d, 0xdb, 0xd1, 0x35, 0xf4, 0xa1, 0x0d, 0xa2, 0xd9, 0x40, 0xff, 0xe5, 0xe2, 0x8d, 0xd5, 0xd5, 0xcf, - 0x40, 0x45, 0x7b, 0x33, 0xc3, 0x63, 0xef, 0xdc, 0xbf, 0x67, 0xc9, 0xb5, 0xa7, 0x6b, 0x98, 0xc1, 0x87, 0x0e, 0x3c, - 0x2c, 0xd3, 0x3c, 0x7d, 0x8f, 0x44, 0x11, 0x9a, 0xc8, 0xf5, 0xa6, 0x03, 0xc9, 0x71, 0xbd, 0xae, 0xe6, 0x7a, 0x87, - 0xf6, 0x51, 0x57, 0x3f, 0xfd, 0x46, 0xd3, 0x4e, 0x26, 0x6c, 0x9a, 0x9e, 0xe2, 0x15, 0xed, 0x04, 0xcf, 0x08, 0xfa, - 0xad, 0x69, 0xf6, 0x38, 0x4c, 0x2d, 0x57, 0x5b, 0xf3, 0x47, 0x4d, 0x9b, 0x06, 0x61, 0xd8, 0xd3, 0x1e, 0x4f, 0xbd, - 0xe9, 0xe1, 0xf4, 0x45, 0x9f, 0x17, 0xe7, 0xdf, 0x94, 0xaa, 0x9b, 0xf4, 0xaf, 0xa7, 0x34, 0x4b, 0xb3, 0x24, 0xfe, - 0xc4, 0xb8, 0xd9, 0x89, 0x26, 0x2f, 0x8f, 0xd5, 0xa6, 0x5e, 0xfd, 0x4b, 0x6e, 0x77, 0x34, 0x9e, 0x7a, 0x45, 0x75, - 0xec, 0xe3, 0x81, 0xec, 0xe4, 0xc9, 0x81, 0xe8, 0xfa, 0x89, 0x8a, 0x26, 0xd7, 0x6a, 0x42, 0x94, 0xab, 0xf3, 0x31, - 0xce, 0xc4, 0xf8, 0x4e, 0x20, 0x0e, 0xa3, 0x74, 0xd7, 0x85, 0x1e, 0xe8, 0xda, 0x64, 0xa0, 0xff, 0xe8, 0x7a, 0x5d, - 0xd3, 0x75, 0x8f, 0xec, 0xa3, 0xee, 0xd8, 0x31, 0x0f, 0xed, 0x43, 0xab, 0x6d, 0x1f, 0x99, 0x5d, 0xab, 0x6b, 0x76, - 0xff, 0xd6, 0x1d, 0x5b, 0x87, 0xf6, 0xa1, 0xe9, 0x58, 0x5d, 0x28, 0xb4, 0xba, 0x56, 0xf7, 0xc6, 0x3a, 0xec, 0x8e, - 0x1d, 0x2c, 0xf5, 0xec, 0x4e, 0xc7, 0x72, 0x1d, 0xbb, 0xd3, 0x31, 0x3b, 0xf6, 0xd1, 0x91, 0xe5, 0xb6, 0xed, 0xa3, - 0xa3, 0xf3, 0x4e, 0xd7, 0x6e, 0xc3, 0xbb, 0x76, 0x7b, 0xdc, 0xb6, 0x5d, 0xd7, 0x82, 0xbf, 0xcc, 0xae, 0xed, 0xd1, - 0x0f, 0xd7, 0xb5, 0xdb, 0xae, 0xe9, 0x84, 0x1d, 0xcf, 0x3e, 0x7a, 0x61, 0xe2, 0xdf, 0x58, 0xcd, 0xc4, 0xbf, 0x00, - 0x8c, 0xf9, 0xc2, 0xf6, 0x8e, 0xe8, 0x17, 0x02, 0xbc, 0x39, 0xec, 0xfe, 0xaa, 0x1f, 0x6c, 0x1c, 0x83, 0x4b, 0x63, - 0xe8, 0x76, 0xec, 0x76, 0xdb, 0x3c, 0x74, 0xed, 0x6e, 0x7b, 0x6e, 0x1d, 0x7a, 0xf6, 0xd1, 0xf1, 0xd8, 0x72, 0xed, - 0xe3, 0x63, 0xd3, 0xb1, 0xda, 0xb6, 0x67, 0xba, 0xf6, 0x61, 0x1b, 0x7f, 0xb4, 0x6d, 0xef, 0xe6, 0xf8, 0x85, 0x7d, - 0xd4, 0x99, 0x1f, 0xd9, 0x87, 0x1f, 0x0f, 0xbb, 0xb6, 0xd7, 0x9e, 0xb7, 0x8f, 0x6c, 0xef, 0xf8, 0xe6, 0xc8, 0x3e, - 0x9c, 0x5b, 0xde, 0xd1, 0xd6, 0x96, 0xae, 0x67, 0x03, 0x8e, 0xf0, 0x35, 0xbc, 0x30, 0xf9, 0x0b, 0xf8, 0x33, 0xc7, - 0xb6, 0xff, 0x45, 0x30, 0x69, 0xbd, 0xe9, 0x0b, 0xbb, 0x7b, 0x3c, 0xa6, 0xea, 0x50, 0x60, 0x89, 0x1a, 0xd0, 0xe4, - 0xc6, 0xa2, 0xcf, 0x22, 0x38, 0x4b, 0x00, 0x12, 0x7f, 0xf8, 0xc7, 0x6e, 0x2c, 0xf8, 0x30, 0x7d, 0xf7, 0x7f, 0x0a, - 0x47, 0x4e, 0x39, 0x64, 0xae, 0xfc, 0x86, 0xff, 0x43, 0x49, 0x5f, 0x86, 0xe6, 0xf9, 0x26, 0x45, 0xc5, 0xfb, 0xdd, - 0x8a, 0x8a, 0x37, 0xab, 0x7d, 0x14, 0x15, 0xef, 0xbf, 0xba, 0xa2, 0xe2, 0xbc, 0x6a, 0x27, 0xff, 0xbe, 0x1a, 0x9b, - 0xfe, 0xd7, 0x75, 0xf5, 0x1a, 0x12, 0xf8, 0xad, 0xcb, 0x8b, 0xd5, 0x15, 0x44, 0x57, 0x7a, 0x1f, 0x0f, 0xde, 0xac, - 0x4a, 0x46, 0x60, 0x31, 0xd0, 0xd8, 0xf7, 0x31, 0xd1, 0xd8, 0xdf, 0x57, 0x03, 0xb0, 0x3c, 0xe1, 0x7c, 0x49, 0x30, - 0xb1, 0xe6, 0x7e, 0x38, 0x95, 0x3c, 0x0d, 0x94, 0xf4, 0xb1, 0x18, 0xbc, 0x12, 0xe0, 0xb8, 0x06, 0x75, 0xd8, 0x6a, - 0x11, 0xa5, 0xbd, 0x23, 0x07, 0x0e, 0x52, 0x6f, 0x9a, 0xe4, 0x95, 0xc6, 0xb6, 0x88, 0x47, 0x75, 0xcd, 0xbd, 0x26, - 0x36, 0xbe, 0x47, 0xa3, 0xc0, 0x66, 0xe8, 0x6e, 0x1d, 0xae, 0x06, 0xd6, 0x36, 0xc2, 0x68, 0x12, 0xd8, 0xb9, 0xa6, - 0xf7, 0x65, 0xd3, 0xbc, 0x8a, 0x31, 0xe6, 0xe6, 0x9e, 0x42, 0x4f, 0xaa, 0xed, 0xdd, 0xb2, 0x69, 0xdf, 0xae, 0x61, - 0x36, 0x7c, 0xbe, 0xd4, 0x7c, 0x8b, 0x5d, 0xa1, 0x04, 0x5c, 0x45, 0x55, 0x25, 0xb3, 0x5a, 0x23, 0x42, 0x0a, 0xee, - 0xbe, 0x30, 0x3e, 0x2c, 0x58, 0x4b, 0x47, 0x43, 0x7e, 0xc7, 0x51, 0xde, 0x95, 0x60, 0xaa, 0x06, 0x8b, 0xcf, 0xd6, - 0xc8, 0x71, 0x07, 0xbf, 0x03, 0xeb, 0xc8, 0x39, 0x9e, 0x51, 0xac, 0xe2, 0x79, 0xad, 0xc0, 0xa5, 0xcb, 0x4c, 0x3e, - 0x77, 0xd7, 0x75, 0xe6, 0x71, 0xa3, 0xa9, 0xb2, 0xcb, 0x16, 0x82, 0x0b, 0xc2, 0xcf, 0x93, 0x61, 0x70, 0x4e, 0xc6, - 0xdb, 0x68, 0xfb, 0xbc, 0x0d, 0x98, 0xa8, 0xf7, 0x18, 0x16, 0xb1, 0xc9, 0x1f, 0xd4, 0xb8, 0x00, 0xeb, 0x29, 0x64, - 0xc1, 0xee, 0x21, 0x9b, 0xa6, 0xf0, 0xa8, 0x1e, 0x5a, 0x31, 0xf7, 0xb7, 0x18, 0xd8, 0xa8, 0x80, 0x39, 0x10, 0xb4, - 0x86, 0xde, 0x66, 0x93, 0x23, 0x9d, 0x47, 0xd6, 0x25, 0x15, 0xb5, 0xdb, 0x39, 0x36, 0xdd, 0x23, 0xd3, 0x3e, 0xee, - 0x18, 0xb9, 0xd8, 0x70, 0x2a, 0xc8, 0x12, 0x42, 0xc0, 0x28, 0x5a, 0x76, 0x33, 0x88, 0x82, 0x2c, 0xf0, 0xc3, 0x1c, - 0xf8, 0xe3, 0xf2, 0xad, 0xe2, 0x9f, 0xab, 0x34, 0x83, 0x31, 0x0a, 0xa6, 0x17, 0x0d, 0xc2, 0xad, 0x11, 0xcb, 0x6e, - 0x19, 0x8b, 0x36, 0x28, 0xcb, 0xab, 0xf6, 0xe5, 0x7f, 0x9e, 0xb5, 0x6d, 0x4e, 0x96, 0x2c, 0xa3, 0x2c, 0xe2, 0xeb, - 0x43, 0x18, 0x43, 0xe7, 0x43, 0xf3, 0xa7, 0x4d, 0x04, 0xf7, 0x9f, 0xbb, 0x09, 0x6e, 0xc6, 0xf6, 0x21, 0xb8, 0xff, - 0xfc, 0xea, 0x04, 0xf7, 0x27, 0x95, 0xe0, 0x96, 0x7c, 0x81, 0x0a, 0xa9, 0xf3, 0x07, 0x7c, 0x6e, 0x41, 0x50, 0xe7, - 0xe7, 0xfa, 0x01, 0x31, 0xf0, 0xba, 0x92, 0x6c, 0xf7, 0x63, 0x29, 0x7b, 0x10, 0x0a, 0x45, 0x30, 0x08, 0x2d, 0x65, - 0x2a, 0x81, 0x44, 0xb4, 0x32, 0xa5, 0x3a, 0xc0, 0x7c, 0x1b, 0x65, 0xa1, 0xfd, 0x9e, 0x5f, 0xfc, 0x40, 0xc9, 0xf3, - 0x26, 0x4e, 0x16, 0x3e, 0x06, 0xe0, 0xd3, 0x31, 0xeb, 0x20, 0x3c, 0x38, 0xe0, 0x7f, 0x36, 0x8e, 0xa3, 0x89, 0xd4, - 0x54, 0xb0, 0xc1, 0x25, 0x71, 0xdc, 0xfa, 0x3d, 0xf3, 0x13, 0xdd, 0xa4, 0xd7, 0x30, 0xb9, 0xcf, 0xda, 0xce, 0x33, - 0xef, 0xf0, 0xd9, 0x91, 0x03, 0xff, 0xbb, 0xac, 0x9d, 0x9b, 0xbc, 0xe2, 0x22, 0x8e, 0x20, 0xf1, 0x89, 0xa8, 0xb9, - 0xa9, 0xda, 0x2d, 0x63, 0x9f, 0x8a, 0x5a, 0xc7, 0xcd, 0x95, 0x26, 0xfe, 0x7d, 0x51, 0xa7, 0xb1, 0xc6, 0x3c, 0x5e, - 0x29, 0xdd, 0x6a, 0xe8, 0x4d, 0x10, 0xad, 0x40, 0xf6, 0xa6, 0xd4, 0x50, 0x5f, 0xf3, 0xe1, 0x16, 0xe3, 0x62, 0xed, - 0xfc, 0xaa, 0xc8, 0xae, 0x24, 0xb2, 0xbc, 0xec, 0xc4, 0x20, 0x57, 0x5b, 0x38, 0x18, 0x9b, 0x1d, 0xf3, 0x0b, 0x69, - 0x90, 0xdb, 0x50, 0x4c, 0x90, 0x4f, 0x13, 0x94, 0x25, 0xab, 0x68, 0xdc, 0xc2, 0x9f, 0xfe, 0x28, 0x6d, 0x05, 0x07, - 0x10, 0x9d, 0x15, 0x3f, 0x6c, 0xe0, 0xac, 0xf9, 0xa7, 0x4e, 0x91, 0x8a, 0x22, 0x15, 0xb3, 0xe2, 0x3f, 0xcb, 0xcc, - 0x84, 0x12, 0xd8, 0xe2, 0xd4, 0x5a, 0x03, 0xff, 0x99, 0x6c, 0xf8, 0x2c, 0x33, 0x21, 0x89, 0x2c, 0x4c, 0xf7, 0xd3, - 0xa7, 0x54, 0x0b, 0xd2, 0x3a, 0xd2, 0xb0, 0xce, 0xc6, 0x45, 0x78, 0x37, 0xcd, 0x9f, 0xc5, 0x14, 0xe1, 0xad, 0x37, - 0x36, 0xe3, 0xe7, 0xcf, 0x4f, 0x07, 0xae, 0xc1, 0x93, 0x92, 0x96, 0x32, 0x68, 0x9d, 0xef, 0x67, 0x7c, 0x60, 0x34, - 0xba, 0xc5, 0x2d, 0xe1, 0xce, 0xe4, 0x08, 0x13, 0x65, 0x4e, 0xbd, 0x20, 0xa3, 0x05, 0x29, 0x19, 0x7d, 0x61, 0x04, - 0x20, 0xea, 0xc8, 0x5b, 0x57, 0xdb, 0x76, 0x6c, 0x47, 0x97, 0x0d, 0xa7, 0xc1, 0x6c, 0xb0, 0x8e, 0x33, 0x1f, 0x72, - 0x03, 0x85, 0xf1, 0x0c, 0x7c, 0x6b, 0xb2, 0x20, 0x0b, 0x21, 0xd1, 0x0c, 0x38, 0xd9, 0x2c, 0xe8, 0x5e, 0x9e, 0x73, - 0x8b, 0x67, 0x3f, 0xf9, 0x84, 0xc9, 0x06, 0x85, 0x5b, 0x1d, 0x46, 0x1c, 0xfa, 0x11, 0x0e, 0xc3, 0x96, 0xde, 0x82, - 0x54, 0x97, 0x2c, 0x49, 0x2d, 0xd5, 0x83, 0xa0, 0xa7, 0x41, 0x1b, 0x48, 0x43, 0x8f, 0x00, 0xa6, 0x89, 0xbf, 0x80, - 0x98, 0xec, 0xeb, 0xdc, 0xe4, 0x94, 0x56, 0xe7, 0xa4, 0x56, 0x73, 0x5f, 0x1c, 0x99, 0x9a, 0xe7, 0x9a, 0x9a, 0x03, - 0xe4, 0x56, 0xcf, 0xcd, 0x75, 0x7e, 0xd5, 0xdf, 0xa5, 0x04, 0x25, 0xfa, 0xf2, 0x98, 0xc6, 0x41, 0xea, 0x4f, 0x2e, - 0x5e, 0xce, 0x28, 0x80, 0x64, 0x4b, 0x89, 0x96, 0x1e, 0x90, 0x22, 0xe4, 0x82, 0xdd, 0x65, 0x06, 0x26, 0x62, 0xe1, - 0x55, 0x02, 0x63, 0x8d, 0xce, 0x7f, 0x41, 0xa4, 0x05, 0x9f, 0x3f, 0xb7, 0x02, 0x70, 0x70, 0x18, 0x28, 0xf8, 0x81, - 0x67, 0xa3, 0x84, 0xb0, 0xa0, 0x50, 0xdd, 0x21, 0xb2, 0xc0, 0xfb, 0x08, 0xfe, 0x2d, 0x8a, 0xc5, 0x0f, 0xae, 0x3a, - 0xb5, 0x43, 0x3f, 0x9a, 0x01, 0x49, 0xf3, 0xa3, 0x59, 0xcd, 0x44, 0x83, 0xfc, 0x17, 0x2b, 0xa5, 0x05, 0xa8, 0xc2, - 0x7c, 0x22, 0xfd, 0xfe, 0xfe, 0x82, 0x12, 0x4d, 0x41, 0x52, 0x73, 0x7f, 0x82, 0xce, 0x76, 0x85, 0x76, 0xe7, 0xf9, - 0xe0, 0xdb, 0x93, 0x05, 0xcb, 0x7c, 0x12, 0x0d, 0xc3, 0xe5, 0x17, 0xd8, 0x01, 0x6d, 0x2c, 0x92, 0xc4, 0x52, 0x32, - 0xf9, 0x09, 0xbb, 0x09, 0xc6, 0xfc, 0x5e, 0x6a, 0x6a, 0xfc, 0x9c, 0xb2, 0xd0, 0x0a, 0x6c, 0xe0, 0x9a, 0x64, 0x84, - 0x3c, 0xf6, 0x31, 0xcc, 0xe4, 0x20, 0x8a, 0xf5, 0xd3, 0x6f, 0xa5, 0xbf, 0xd6, 0xa6, 0x49, 0x80, 0x6c, 0x8f, 0x97, - 0x09, 0x0b, 0xff, 0x35, 0xf8, 0x16, 0x0e, 0xee, 0x6f, 0xaf, 0x74, 0xa3, 0x9f, 0xd9, 0xf3, 0x84, 0x4d, 0x07, 0xdf, - 0x36, 0x64, 0x3d, 0xc4, 0xeb, 0x3d, 0xf5, 0x45, 0x6f, 0x7b, 0x45, 0x70, 0xa0, 0xf6, 0x5e, 0x97, 0xfa, 0x53, 0x7e, - 0x5b, 0x87, 0x1b, 0xe0, 0xba, 0x74, 0xc7, 0x76, 0xfb, 0x78, 0x7f, 0x1e, 0x85, 0xfe, 0xf8, 0x53, 0x9f, 0xde, 0x94, - 0x1e, 0x2c, 0x38, 0xad, 0xc7, 0xfe, 0xb2, 0x87, 0xc7, 0xab, 0x5a, 0x08, 0xee, 0x9a, 0x54, 0x2a, 0x39, 0xbb, 0xc6, - 0xb5, 0x8c, 0x4b, 0x79, 0x8d, 0x5f, 0xc6, 0x4f, 0xdd, 0xce, 0x83, 0x8c, 0x89, 0x4f, 0xe1, 0x43, 0x9e, 0x8b, 0x8b, - 0x3a, 0x5d, 0x51, 0xf1, 0x62, 0x6d, 0xb7, 0x35, 0xb7, 0xfb, 0xb7, 0xce, 0x8d, 0xeb, 0xcc, 0x3d, 0xd7, 0xee, 0x7e, - 0x74, 0xbb, 0xf3, 0xb6, 0x7d, 0x1c, 0x5a, 0x6d, 0xfb, 0x18, 0xfe, 0x7c, 0x3c, 0xb6, 0xbb, 0x73, 0xcb, 0xb3, 0x0f, - 0x3f, 0xba, 0x5e, 0x68, 0x75, 0xed, 0x63, 0xf8, 0x73, 0x4e, 0xad, 0xe0, 0x02, 0x44, 0xf7, 0x9d, 0x6f, 0x4b, 0x54, - 0x40, 0xf9, 0x2d, 0xf5, 0x34, 0x66, 0xe9, 0x78, 0x6b, 0xd0, 0xf5, 0x00, 0xc9, 0xd0, 0x4d, 0x11, 0x04, 0x32, 0xea, - 0xb7, 0x20, 0x0d, 0x3b, 0x26, 0x10, 0x10, 0x26, 0x2f, 0xc2, 0x2f, 0x55, 0x84, 0xd2, 0x6f, 0xdc, 0x46, 0xbc, 0x4d, - 0x73, 0xc0, 0x75, 0x91, 0x99, 0x8a, 0x94, 0x43, 0xbf, 0x2c, 0x31, 0x88, 0x91, 0x08, 0x11, 0xaf, 0x50, 0xa5, 0x22, - 0x3b, 0x62, 0xbe, 0xbb, 0xe3, 0xe8, 0x99, 0xcb, 0x64, 0x76, 0x9e, 0xaf, 0x0a, 0x9b, 0x2b, 0x8c, 0x24, 0xf4, 0x3f, - 0x0a, 0x07, 0x93, 0xd2, 0x12, 0x1c, 0x11, 0xcd, 0x75, 0x12, 0x24, 0xb2, 0x7b, 0x0a, 0x89, 0x76, 0x9b, 0x23, 0xd5, - 0x1b, 0x90, 0xc6, 0xe4, 0x2d, 0x70, 0xc9, 0x37, 0x7e, 0xa8, 0x18, 0xb7, 0x28, 0x2d, 0x1f, 0x49, 0xca, 0xff, 0xf4, - 0x69, 0xd1, 0x39, 0xab, 0xd2, 0xef, 0x13, 0xb7, 0x03, 0xc7, 0x6e, 0x87, 0xb5, 0xb7, 0xda, 0x59, 0xed, 0x0e, 0x07, - 0x5c, 0x84, 0x0b, 0x15, 0xb6, 0x14, 0x42, 0x8b, 0xbb, 0xd1, 0xd8, 0xab, 0xa6, 0xc3, 0x85, 0x40, 0xca, 0x95, 0xab, - 0x8e, 0x6e, 0xf4, 0x23, 0xa1, 0x92, 0x8c, 0xb6, 0x84, 0x40, 0xe6, 0x77, 0x31, 0x1d, 0x50, 0xb3, 0x65, 0x1c, 0x3b, - 0x9c, 0x46, 0xff, 0xd7, 0x83, 0x40, 0x07, 0x2e, 0xd0, 0xa1, 0x56, 0x76, 0x6b, 0xc9, 0xa1, 0x47, 0x9e, 0xab, 0x74, - 0xa0, 0xb2, 0xf4, 0x4c, 0x87, 0x22, 0xc8, 0x6f, 0x85, 0x29, 0xed, 0xa4, 0x01, 0x99, 0x3c, 0x2d, 0x8a, 0x02, 0x33, - 0x80, 0x18, 0xe0, 0x2d, 0xe1, 0x4c, 0x66, 0x3c, 0x7d, 0xba, 0xf1, 0x10, 0x22, 0x85, 0xbd, 0x9a, 0xd9, 0x53, 0x57, - 0xe9, 0x9b, 0xae, 0x92, 0x18, 0x09, 0x17, 0xa9, 0x86, 0xb0, 0x7b, 0xa3, 0xb5, 0x87, 0x3f, 0x47, 0xcc, 0xcf, 0x6c, - 0xae, 0x69, 0x6a, 0x29, 0x87, 0xbb, 0xe9, 0xb2, 0x36, 0x58, 0xbc, 0xf1, 0x58, 0x67, 0x3c, 0x96, 0xe0, 0x93, 0xf5, - 0xc7, 0x15, 0xf7, 0xf4, 0x06, 0x18, 0x9f, 0x9d, 0x22, 0x3c, 0xcd, 0xbb, 0xcc, 0xa7, 0x18, 0x26, 0xea, 0x91, 0x1b, - 0x67, 0xbe, 0xc8, 0x23, 0x03, 0x7c, 0x79, 0xbf, 0x51, 0x25, 0xab, 0x78, 0x83, 0x9f, 0xbe, 0xbb, 0xf8, 0x4e, 0xe3, - 0xeb, 0x9f, 0x34, 0x88, 0x78, 0x91, 0xa1, 0xac, 0x07, 0x03, 0xca, 0x7a, 0xa0, 0xf1, 0x34, 0x22, 0x90, 0x3b, 0x20, - 0x3f, 0x20, 0x0c, 0xa2, 0x00, 0x9a, 0xf4, 0xaa, 0x8b, 0x55, 0x98, 0x05, 0x4b, 0x3f, 0xc9, 0x0e, 0xa0, 0xa9, 0x05, - 0x44, 0x4e, 0xdf, 0xe4, 0x23, 0x4e, 0xaa, 0x59, 0x11, 0x62, 0x2f, 0x8b, 0x84, 0x6e, 0x76, 0x1a, 0x84, 0x52, 0x35, - 0x2b, 0x3e, 0xe0, 0x8f, 0xc7, 0x6c, 0x99, 0x0d, 0x74, 0x7f, 0x09, 0xd9, 0x2f, 0x30, 0x9e, 0xf5, 0x41, 0x3c, 0xce, - 0x58, 0x66, 0xa5, 0x59, 0xc2, 0xfc, 0x85, 0x2e, 0x43, 0xb9, 0xd6, 0xe1, 0xa5, 0xab, 0xd1, 0x22, 0xc8, 0x64, 0x2c, - 0x44, 0x1a, 0x20, 0x28, 0x49, 0xa1, 0x8b, 0xa7, 0xc3, 0x9c, 0xa3, 0xf0, 0x3c, 0x9e, 0x55, 0x56, 0x54, 0xc1, 0xb9, - 0x9c, 0x61, 0xa4, 0x5d, 0x9e, 0xf1, 0x60, 0x82, 0x3e, 0x4f, 0xd7, 0xdc, 0xaf, 0x5d, 0x86, 0x6c, 0xd4, 0x4f, 0x4f, - 0xf8, 0xf5, 0x56, 0xc3, 0x50, 0x0c, 0x7a, 0xc7, 0x81, 0x58, 0xc2, 0x9b, 0x3c, 0xde, 0x0f, 0x78, 0x65, 0x38, 0x9a, - 0x08, 0x32, 0xc6, 0x79, 0xa7, 0xbe, 0x5c, 0x00, 0x23, 0x54, 0x52, 0xa2, 0xcf, 0xdd, 0x53, 0xe9, 0x62, 0x85, 0xbd, - 0x42, 0x5e, 0xe9, 0xf3, 0xe7, 0x97, 0xc3, 0xff, 0xfc, 0x1b, 0x82, 0xd1, 0xcf, 0x5d, 0xe1, 0x67, 0x7e, 0xa9, 0xd6, - 0xe2, 0xdc, 0xa7, 0x39, 0x44, 0x03, 0x0a, 0x36, 0x11, 0x81, 0x57, 0xc4, 0xd2, 0xca, 0x87, 0x57, 0x22, 0x98, 0x16, - 0x24, 0x9c, 0x30, 0x84, 0x37, 0xfc, 0x10, 0xa6, 0x77, 0x28, 0x82, 0x30, 0x68, 0xbf, 0xdd, 0x7d, 0x7f, 0x0c, 0xc1, - 0x96, 0x6b, 0x79, 0x20, 0x94, 0x0e, 0xe2, 0x1a, 0x3a, 0x3d, 0xf1, 0x35, 0x64, 0x5a, 0x90, 0xfd, 0x48, 0x7b, 0x07, - 0x30, 0xcc, 0x79, 0xbc, 0x60, 0x76, 0x10, 0x1f, 0xdc, 0xb2, 0x91, 0xe5, 0x2f, 0x03, 0xd2, 0xd5, 0xa3, 0xdc, 0x4d, - 0x23, 0xce, 0x4f, 0xaa, 0xc0, 0x89, 0xbf, 0xce, 0x0b, 0x54, 0xc6, 0xe5, 0xe8, 0x69, 0x1d, 0xaf, 0x50, 0xdc, 0x81, - 0x4f, 0xb3, 0x82, 0xc7, 0xf8, 0xf4, 0xe4, 0xc0, 0x3f, 0x2d, 0x87, 0x6f, 0xb4, 0x45, 0x02, 0x81, 0xf2, 0x21, 0x70, - 0x46, 0x51, 0x18, 0x45, 0xc0, 0xc5, 0xe2, 0xc1, 0x8a, 0xa7, 0x53, 0x35, 0xe4, 0xa2, 0x5d, 0xee, 0x9e, 0x44, 0x5a, - 0xb1, 0xa4, 0xe3, 0x25, 0x7d, 0xa9, 0xfe, 0x09, 0xf9, 0x13, 0x92, 0x27, 0xf3, 0xe8, 0x9c, 0xb0, 0xdd, 0x6b, 0xa1, - 0x1b, 0x25, 0xc6, 0x1e, 0x53, 0x25, 0x4e, 0x47, 0xaa, 0x81, 0xc2, 0x37, 0x70, 0x2e, 0x8f, 0x06, 0x03, 0x22, 0x73, - 0x55, 0x6a, 0x07, 0x48, 0x6c, 0x48, 0xa6, 0x00, 0x83, 0xcd, 0xa0, 0xa1, 0x45, 0x2e, 0x74, 0xd8, 0xa8, 0x3a, 0x9c, - 0x7a, 0x1f, 0x0f, 0x7c, 0xb1, 0xfc, 0x4a, 0x0b, 0x14, 0x16, 0x1e, 0x9f, 0x77, 0xa0, 0xef, 0x02, 0x4e, 0x85, 0xcc, - 0x6b, 0x7f, 0x25, 0x8a, 0x6e, 0x85, 0xfe, 0x7d, 0xac, 0x98, 0x36, 0xf0, 0x28, 0x07, 0xe7, 0x58, 0x7a, 0x21, 0xbc, - 0x0b, 0x6b, 0x1b, 0x4d, 0x06, 0xa4, 0xaf, 0x6f, 0x36, 0x35, 0x82, 0xfc, 0xae, 0xbd, 0xa6, 0xd6, 0x2d, 0x0f, 0x06, - 0x89, 0x67, 0x5e, 0xec, 0xc3, 0xd2, 0x4b, 0x24, 0x0b, 0xf9, 0xc9, 0x01, 0x8c, 0x0f, 0x22, 0x33, 0x94, 0x18, 0xa7, - 0xc0, 0x80, 0xf0, 0x0f, 0x7e, 0x4a, 0xe6, 0x19, 0x6f, 0x27, 0x82, 0xe7, 0xc3, 0x8b, 0xa5, 0x8c, 0x0d, 0x5b, 0xaa, - 0x52, 0xe7, 0x65, 0x9c, 0x66, 0x26, 0x70, 0x77, 0x02, 0x87, 0xdf, 0x57, 0x98, 0xbd, 0x21, 0xef, 0x67, 0x4c, 0x38, - 0x3e, 0x9f, 0x67, 0x1b, 0x7c, 0xa3, 0x37, 0x55, 0x21, 0x7e, 0x76, 0x4b, 0x85, 0x62, 0x1d, 0x6f, 0xab, 0x55, 0x70, - 0x4e, 0xb2, 0xda, 0xd2, 0x6f, 0xe9, 0x8f, 0x71, 0xc5, 0xd7, 0x6a, 0x63, 0x29, 0xd4, 0x3b, 0xcf, 0x06, 0x50, 0x55, - 0xc8, 0xe2, 0xfd, 0xe5, 0x92, 0x2a, 0x1b, 0xfd, 0x93, 0x03, 0xba, 0x96, 0x9e, 0xd2, 0x0a, 0x3b, 0x3d, 0x01, 0xf3, - 0x4e, 0x9a, 0x74, 0x7f, 0xb9, 0xe4, 0x53, 0x4a, 0xbf, 0xe8, 0xcd, 0xc1, 0x3c, 0x5b, 0x84, 0xa7, 0xff, 0x07, 0xc0, - 0xb1, 0x34, 0x8b, 0x20, 0x5c, 0x03, 0x00}; + 0x10, 0xc1, 0x11, 0x73, 0xdb, 0xae, 0x69, 0xb2, 0x36, 0xe8, 0x75, 0x92, 0xe5, 0x7c, 0x46, 0x35, 0x33, 0x70, 0x0e, + 0x48, 0x8d, 0x9b, 0x7c, 0xda, 0x6e, 0xcd, 0x6f, 0xf7, 0x5a, 0x7b, 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, 0xe9, 0xe8, 0x92, 0x6d, 0xf1, 0xb4, 0xf5, 0x43, 0x3d, 0x37, 0xa7, 0x43, 0x96, 0x2f, 0xed, 0x46, 0xf5, 0xc0, + 0x75, 0x5b, 0x35, 0x5c, 0xe6, 0x80, 0x64, 0x18, 0x10, 0x0d, 0xd2, 0xb4, 0x79, 0xc3, 0x86, 0x9f, 0xb9, 0xb6, 0x5b, + 0xa6, 0xa9, 0x6e, 0xc0, 0x79, 0xc7, 0x8c, 0x69, 0xce, 0x8a, 0xa5, 0x3f, 0x8e, 0x5a, 0x35, 0x02, 0x7a, 0x25, 0xcc, + 0x41, 0xa8, 0xe9, 0xb0, 0x09, 0xa1, 0xcc, 0x58, 0xb1, 0xdc, 0x35, 0xb9, 0xcd, 0x0d, 0x1f, 0x1e, 0x67, 0x27, 0xad, + 0x96, 0x3f, 0xea, 0x9a, 0xb6, 0x4e, 0xda, 0x4e, 0x4e, 0xd9, 0x6c, 0x17, 0xa9, 0xa9, 0xd3, 0xd5, 0x76, 0x67, 0x7e, + 0xbb, 0x67, 0xfe, 0x69, 0xed, 0xb5, 0xb6, 0xe9, 0xe8, 0xf6, 0x92, 0x1f, 0x23, 0x8f, 0xa4, 0x5a, 0xce, 0xd3, 0x36, + 0x9b, 0x75, 0x17, 0x0a, 0xce, 0x4c, 0x03, 0x4e, 0x73, 0x16, 0xaf, 0xcd, 0x4c, 0x00, 0x6a, 0x94, 0x0b, 0x38, 0xa2, + 0xec, 0x31, 0x0d, 0x7d, 0x28, 0x09, 0x36, 0xe5, 0x3b, 0x1b, 0xad, 0x0f, 0xab, 0xb5, 0x57, 0x0d, 0x0c, 0xfe, 0x59, + 0xff, 0x55, 0x31, 0xb9, 0x2f, 0x58, 0x20, 0x64, 0xf0, 0x46, 0x72, 0xba, 0x6a, 0x39, 0xc1, 0x62, 0xa4, 0x2b, 0x79, + 0xc7, 0xb8, 0x65, 0xcc, 0xe8, 0xad, 0xf5, 0xcf, 0x98, 0x71, 0x01, 0xd6, 0x5f, 0x08, 0xeb, 0xc0, 0x4e, 0x7e, 0x1a, + 0x36, 0x34, 0xd2, 0x31, 0x34, 0x7c, 0xd8, 0x49, 0x4e, 0x4f, 0x11, 0x6e, 0xe1, 0xce, 0xe9, 0x69, 0x20, 0xd8, 0x8c, + 0xf5, 0xae, 0xa2, 0xbb, 0x4a, 0xaa, 0x1d, 0x25, 0x8f, 0x4c, 0xa3, 0x47, 0xed, 0x56, 0x0b, 0x1b, 0x1f, 0xf4, 0xb2, + 0x30, 0x57, 0x3b, 0x9a, 0x6d, 0xb7, 0x5a, 0xd0, 0x2c, 0xfc, 0x71, 0xf3, 0xfa, 0x85, 0x2c, 0x5b, 0x69, 0x0b, 0xb7, + 0xd3, 0x36, 0xee, 0xa4, 0x1d, 0x7c, 0x9c, 0x1e, 0xe3, 0x93, 0xf4, 0x04, 0x9f, 0xa6, 0xa7, 0xf8, 0x2c, 0x3d, 0xc3, + 0xf7, 0xd3, 0xfb, 0xf8, 0x3c, 0x3d, 0xc7, 0x0f, 0xd2, 0x07, 0xf8, 0x61, 0xda, 0x6e, 0xe1, 0x47, 0x69, 0xbb, 0x8d, + 0x1f, 0xa7, 0xed, 0x0e, 0x7e, 0x92, 0xb6, 0x8f, 0xf1, 0xd3, 0xb4, 0x7d, 0x82, 0x9f, 0xa5, 0xed, 0x53, 0x4c, 0x21, + 0x77, 0x08, 0xb9, 0x19, 0xe4, 0x8e, 0x20, 0x97, 0x41, 0xee, 0x38, 0x6d, 0x9f, 0xae, 0xb1, 0xb2, 0x71, 0x2b, 0xa2, + 0x56, 0xbb, 0x73, 0x7c, 0x72, 0x7a, 0x76, 0xff, 0xfc, 0xc1, 0xc3, 0x47, 0x8f, 0x9f, 0x3c, 0x7d, 0x16, 0x0d, 0xf0, + 0xd0, 0xb8, 0x8f, 0x28, 0xd1, 0xe7, 0x07, 0xed, 0xd3, 0x01, 0xbe, 0xf6, 0x9f, 0x31, 0x3f, 0xe8, 0x9c, 0xb4, 0xd0, + 0xe5, 0xe5, 0xc9, 0xa0, 0x51, 0xe6, 0xbe, 0x37, 0x5e, 0x2b, 0x55, 0x16, 0x21, 0x24, 0x86, 0x1c, 0x84, 0xef, 0x4c, + 0xbd, 0xf7, 0x2c, 0xe6, 0x49, 0x81, 0x0e, 0x0e, 0xcc, 0x8f, 0x89, 0xff, 0x31, 0xf4, 0x3f, 0x68, 0xb0, 0x48, 0xb7, + 0x34, 0x76, 0x6e, 0xcb, 0xba, 0x74, 0x1a, 0x28, 0xed, 0x71, 0xf6, 0xb8, 0xb3, 0x8c, 0xff, 0xaf, 0xc8, 0x5a, 0xbe, + 0x90, 0x13, 0xab, 0x5d, 0x3a, 0xed, 0x31, 0xb2, 0x2c, 0xd2, 0xce, 0xe9, 0xe9, 0xc1, 0x2f, 0x7d, 0xde, 0x6f, 0x0f, + 0x06, 0x87, 0xed, 0xfb, 0x78, 0x52, 0x26, 0x74, 0x6c, 0xc2, 0xb0, 0x4c, 0x38, 0xb6, 0x09, 0x34, 0xb5, 0xb5, 0x21, + 0xe9, 0xc4, 0x24, 0x41, 0x89, 0x75, 0x6a, 0xda, 0xbe, 0x6f, 0xdb, 0x7e, 0x00, 0x26, 0x59, 0xa6, 0x79, 0xd7, 0xf4, + 0xc5, 0xc5, 0xc9, 0xca, 0x35, 0x8a, 0x27, 0xa9, 0x6b, 0xcd, 0x27, 0x9e, 0x0c, 0x06, 0x78, 0x68, 0x12, 0x4f, 0xab, + 0xc4, 0xb3, 0xc1, 0xc0, 0x75, 0xf5, 0xc0, 0x74, 0x75, 0xbf, 0xca, 0x3a, 0x1f, 0x0c, 0x4c, 0x97, 0xc8, 0x39, 0xe0, + 0x2b, 0xbd, 0xf7, 0xa5, 0x54, 0x82, 0xf0, 0x8b, 0xce, 0xe9, 0x69, 0x0f, 0x30, 0xcc, 0x18, 0xd6, 0x7a, 0x18, 0xdd, + 0x04, 0x30, 0xba, 0x83, 0xdf, 0xbd, 0x21, 0x4d, 0xaf, 0x69, 0x09, 0xa4, 0x5e, 0xf4, 0x5f, 0x51, 0x43, 0x1b, 0x98, + 0x9b, 0x3f, 0x13, 0xfb, 0x67, 0x88, 0x1a, 0x5f, 0x28, 0x80, 0x1b, 0xd4, 0x3a, 0x5e, 0x2f, 0x6b, 0x7a, 0xfc, 0x4c, + 0xc1, 0x4f, 0x66, 0xaa, 0x72, 0xda, 0x5b, 0x4d, 0x6f, 0x86, 0xab, 0xa9, 0xfa, 0x82, 0xfe, 0x8c, 0xff, 0x54, 0x87, + 0x71, 0xbf, 0xd9, 0x48, 0xd8, 0x9f, 0x23, 0x70, 0xc8, 0xe9, 0xa5, 0x23, 0x36, 0x41, 0xbd, 0xfe, 0x9f, 0x0a, 0x0f, + 0x1a, 0x41, 0xc6, 0x0f, 0xdb, 0x29, 0xe0, 0xae, 0xb3, 0x99, 0x18, 0xff, 0x80, 0x7a, 0xa8, 0xf7, 0xa7, 0x3a, 0xfc, + 0x13, 0xdd, 0x3b, 0xaa, 0xe6, 0xf2, 0xbb, 0x74, 0x5b, 0xb8, 0x8a, 0xe1, 0x73, 0x58, 0x6e, 0x61, 0x86, 0xdb, 0x4d, + 0x06, 0x11, 0xcf, 0xc0, 0x9f, 0x9b, 0xc4, 0xb2, 0xc1, 0x8f, 0x8e, 0x5b, 0xe8, 0x87, 0x76, 0x07, 0x34, 0x14, 0x4d, + 0x71, 0xb8, 0xbd, 0xe9, 0x8b, 0xe6, 0x31, 0x7e, 0xd0, 0x2c, 0x70, 0x1b, 0xe1, 0x66, 0xdb, 0xab, 0x8e, 0xfb, 0x2a, + 0x6e, 0x21, 0xac, 0xe2, 0x73, 0xf8, 0xe7, 0x04, 0x0d, 0xaa, 0x0d, 0x79, 0x45, 0x37, 0x7b, 0x07, 0xe7, 0x53, 0x12, + 0xab, 0x06, 0x3f, 0x3a, 0x6b, 0xa1, 0x1f, 0xce, 0x4c, 0x47, 0xec, 0x50, 0xef, 0xe8, 0x4a, 0xe2, 0x93, 0xa6, 0x84, + 0x8e, 0x5a, 0x65, 0x3f, 0x22, 0x3e, 0x45, 0x58, 0xc4, 0xc7, 0xf0, 0x4f, 0x3b, 0xec, 0xe7, 0xd7, 0xad, 0x7e, 0xcc, + 0xbc, 0xdb, 0x38, 0x39, 0xb5, 0xbe, 0xac, 0xca, 0x5e, 0x2c, 0x37, 0xd8, 0x65, 0xdb, 0xdc, 0x88, 0xb5, 0x8f, 0xe0, + 0x03, 0x61, 0x7d, 0x48, 0x14, 0x66, 0x87, 0xe0, 0x04, 0x0b, 0xb6, 0x1f, 0xea, 0xe2, 0xb8, 0xab, 0x1a, 0x0d, 0x24, + 0xfa, 0x6a, 0x70, 0x48, 0xda, 0x4d, 0xdd, 0x64, 0x18, 0x7e, 0x37, 0x48, 0x19, 0x59, 0x4d, 0x54, 0xbd, 0x3e, 0x76, + 0xbd, 0xda, 0xeb, 0x73, 0x8f, 0x1d, 0x84, 0x10, 0xd5, 0x8b, 0x75, 0x93, 0xa1, 0x23, 0xd1, 0x88, 0xf5, 0x05, 0xeb, + 0x9d, 0xa5, 0x2d, 0x64, 0xb0, 0x53, 0xf5, 0x62, 0xd6, 0xe4, 0x90, 0xde, 0x49, 0x63, 0xde, 0xd4, 0xf0, 0xeb, 0x24, + 0x98, 0x85, 0x00, 0xbc, 0xab, 0x5c, 0x7a, 0x8a, 0xa3, 0xce, 0xe9, 0x29, 0x16, 0x84, 0x27, 0x13, 0xf3, 0x4b, 0x11, + 0x9e, 0x0c, 0xcd, 0x2f, 0x49, 0x4a, 0x78, 0xd9, 0xde, 0x71, 0x41, 0x82, 0x55, 0x35, 0x29, 0x14, 0x16, 0xb4, 0x40, + 0x47, 0x1d, 0x7f, 0xb7, 0x8e, 0xa7, 0x7e, 0x0e, 0xa0, 0x4b, 0x28, 0x8c, 0x59, 0xa5, 0x6c, 0x16, 0x38, 0x27, 0xf4, + 0x32, 0x39, 0xed, 0x4d, 0x8f, 0xe2, 0x4e, 0x53, 0x36, 0x0b, 0x94, 0x4e, 0x8f, 0x4c, 0x4d, 0x9c, 0x91, 0xc7, 0xd4, + 0xb6, 0x86, 0xa7, 0x70, 0x21, 0x9a, 0x91, 0xec, 0xf0, 0xac, 0xd5, 0x48, 0x4e, 0x11, 0xee, 0x67, 0xab, 0x16, 0xce, + 0x57, 0xab, 0x16, 0xa6, 0xc1, 0x32, 0x3c, 0x16, 0x1e, 0x20, 0xa5, 0xba, 0x6b, 0x33, 0xc0, 0x4d, 0x8f, 0xc7, 0x1a, + 0x2e, 0xf7, 0x35, 0xb8, 0xcc, 0x68, 0x70, 0xe6, 0x49, 0xb9, 0xbb, 0x55, 0x43, 0x26, 0xc4, 0xdf, 0x38, 0x54, 0x80, + 0xbd, 0x16, 0x7e, 0x5d, 0xbd, 0x79, 0xa6, 0x88, 0x7f, 0x97, 0xd8, 0xa6, 0x05, 0xc5, 0xe8, 0x76, 0xb1, 0x5f, 0xe9, + 0x56, 0xb1, 0x37, 0x3b, 0x8a, 0x5d, 0x6d, 0x17, 0xfb, 0x28, 0x03, 0x75, 0x1d, 0xff, 0xe1, 0xf8, 0xac, 0xd5, 0x38, + 0x06, 0x64, 0x3d, 0x3e, 0x6b, 0x55, 0x85, 0xee, 0xd1, 0x6a, 0xad, 0x34, 0xf9, 0x4c, 0xad, 0xc3, 0x02, 0xf7, 0x9e, + 0xd3, 0x66, 0xe1, 0xac, 0xdf, 0x76, 0xe9, 0xa4, 0xdd, 0x3f, 0x05, 0x83, 0x10, 0x61, 0xa8, 0x9d, 0xee, 0x9f, 0x0d, + 0x7a, 0x53, 0x16, 0x37, 0x20, 0x15, 0xa5, 0x63, 0xed, 0x7e, 0xa1, 0xf2, 0x5e, 0xf8, 0xa3, 0x84, 0xa4, 0xce, 0x00, + 0x61, 0x49, 0x1a, 0xba, 0x7f, 0x3c, 0x30, 0xe7, 0x5d, 0x01, 0xbf, 0x4f, 0xcc, 0xef, 0x52, 0x2b, 0xe3, 0xbc, 0x1a, + 0xa6, 0x37, 0xc3, 0xa8, 0x27, 0xc8, 0x6b, 0x1a, 0x1b, 0x43, 0x75, 0x94, 0x96, 0x19, 0xea, 0x0b, 0x64, 0xbc, 0x29, + 0x33, 0x04, 0x79, 0x2d, 0xdc, 0x6f, 0xbc, 0x2c, 0x52, 0x30, 0x5a, 0xc1, 0x93, 0x14, 0x0c, 0x56, 0xf0, 0x30, 0x15, + 0xe0, 0x54, 0x41, 0x53, 0x16, 0x98, 0xc2, 0x3f, 0x74, 0x6a, 0x30, 0x73, 0x75, 0x4b, 0x0c, 0x96, 0x76, 0x19, 0x9c, + 0x14, 0x1f, 0x65, 0x0c, 0x7f, 0x1b, 0x1a, 0x61, 0x06, 0x6d, 0x32, 0x84, 0x79, 0x52, 0x10, 0x48, 0xc3, 0x3c, 0x99, + 0x10, 0x06, 0x4d, 0xf2, 0x64, 0x48, 0x58, 0xbf, 0x13, 0xa0, 0xc9, 0x53, 0x03, 0x3b, 0x00, 0x0e, 0xaf, 0xdf, 0x86, + 0x6b, 0xdb, 0x38, 0x5c, 0xb3, 0x43, 0x13, 0x82, 0x70, 0x15, 0xc3, 0x2c, 0x60, 0x73, 0x9a, 0x9f, 0x9d, 0x2a, 0x86, + 0x24, 0x4f, 0xa8, 0xa1, 0xde, 0x7f, 0x01, 0x59, 0x8d, 0xef, 0x2d, 0xd9, 0x1a, 0xef, 0xdd, 0x5b, 0x8a, 0xf5, 0x0f, + 0xf0, 0x47, 0xb9, 0x3f, 0xda, 0x9c, 0x7e, 0x6b, 0xf4, 0x57, 0x0a, 0xc5, 0x76, 0x94, 0x42, 0x7f, 0x79, 0x9f, 0x3a, + 0x45, 0x96, 0xb7, 0x69, 0x34, 0xa2, 0xc5, 0xe7, 0x08, 0x7f, 0x4a, 0xa3, 0x1c, 0x18, 0xc1, 0x08, 0x7f, 0x4c, 0xa3, + 0x82, 0x45, 0xf8, 0x8f, 0x34, 0x1a, 0xe6, 0x8b, 0x08, 0x7f, 0x48, 0xa3, 0x49, 0x11, 0xe1, 0xf7, 0xa0, 0xf1, 0x1c, + 0xf1, 0xc5, 0x2c, 0xc2, 0xbf, 0xa7, 0x91, 0x32, 0x2e, 0x05, 0xf8, 0x61, 0x1a, 0x31, 0x16, 0xe1, 0x77, 0x69, 0x24, + 0xf3, 0x08, 0x5f, 0xa5, 0x91, 0x2c, 0x22, 0xfc, 0x28, 0x8d, 0x0a, 0x1a, 0xe1, 0xc7, 0x69, 0x04, 0x85, 0x26, 0x11, + 0x7e, 0x92, 0x46, 0xd0, 0xb2, 0x8a, 0xf0, 0xdb, 0x34, 0xe2, 0x22, 0xc2, 0xbf, 0xa5, 0x91, 0x5e, 0x14, 0xff, 0x2c, + 0x24, 0x57, 0x11, 0x7e, 0x9a, 0x46, 0x53, 0x1e, 0xe1, 0x37, 0x69, 0x54, 0xc8, 0x08, 0xbf, 0x4e, 0x23, 0x9a, 0x47, + 0xf8, 0x55, 0x1a, 0xe5, 0x2c, 0xc2, 0xbf, 0xa6, 0xd1, 0x88, 0x45, 0xf8, 0x65, 0x1a, 0xdd, 0xb1, 0x3c, 0x97, 0x11, + 0x7e, 0x96, 0x46, 0x4c, 0x44, 0xf8, 0x97, 0x34, 0xca, 0xa6, 0x11, 0xfe, 0x29, 0x8d, 0x68, 0xf1, 0x59, 0x45, 0xf8, + 0x79, 0x1a, 0x31, 0x1a, 0xe1, 0x17, 0xb6, 0xa3, 0x49, 0x84, 0x7f, 0x4e, 0xa3, 0x9b, 0x69, 0xb4, 0xc6, 0x4a, 0x91, + 0xe5, 0x6b, 0x9e, 0xb1, 0x3f, 0x58, 0x1a, 0x8d, 0x5b, 0xe3, 0xf3, 0xf1, 0x38, 0xc2, 0x54, 0x68, 0xfe, 0xcf, 0x82, + 0xdd, 0x3c, 0xd5, 0x90, 0x48, 0xd9, 0x70, 0x74, 0x3f, 0xc2, 0xf4, 0x9f, 0x05, 0x4d, 0xa3, 0xf1, 0xd8, 0x14, 0xf8, + 0x67, 0x41, 0x67, 0xb4, 0x78, 0xcb, 0xd2, 0xe8, 0xfe, 0x78, 0x3c, 0x1e, 0x9d, 0x44, 0x98, 0x7e, 0x5d, 0x7c, 0x34, + 0x2d, 0x98, 0x02, 0x43, 0xc6, 0x27, 0x50, 0xf7, 0x74, 0x7c, 0x3a, 0xca, 0x22, 0x3c, 0xe4, 0xea, 0x9f, 0x05, 0x7c, + 0x8f, 0xd9, 0x49, 0x76, 0x12, 0xe1, 0x61, 0x4e, 0xb3, 0xcf, 0x69, 0xd4, 0x32, 0xbf, 0xc4, 0x2f, 0x6c, 0xf4, 0x7a, + 0x26, 0xcd, 0x7d, 0xc0, 0x98, 0x0d, 0xb3, 0x51, 0x84, 0xcd, 0x60, 0xc6, 0xf0, 0xf7, 0x0b, 0x7f, 0xc7, 0x74, 0x1a, + 0x9d, 0xd3, 0xce, 0x90, 0x75, 0x22, 0x3c, 0x7c, 0x73, 0x23, 0xd2, 0x88, 0x9e, 0x76, 0x68, 0x87, 0x46, 0x78, 0xb8, + 0x28, 0xf2, 0xbb, 0x1b, 0x29, 0x47, 0x00, 0x84, 0xe1, 0xf9, 0xf9, 0xfd, 0x08, 0x67, 0xf4, 0x57, 0x0d, 0xb5, 0x4f, + 0xc7, 0x0f, 0x18, 0x6d, 0x45, 0xf8, 0x17, 0x5a, 0xe8, 0x8f, 0x0b, 0xe5, 0x06, 0xda, 0x82, 0x14, 0x99, 0xbd, 0x03, + 0x5d, 0x79, 0x34, 0xea, 0x9c, 0x3d, 0x68, 0xb3, 0x08, 0x67, 0x57, 0xaf, 0xa1, 0xb7, 0xfb, 0xe3, 0xd3, 0x16, 0x7c, + 0x08, 0x10, 0x3a, 0x59, 0x01, 0x8d, 0x9c, 0x9d, 0x3c, 0x38, 0x65, 0x23, 0x93, 0xa8, 0x78, 0xfe, 0xd9, 0xcc, 0xfe, + 0x1c, 0xe6, 0x93, 0x15, 0x7c, 0xa6, 0xa4, 0x48, 0xa3, 0x51, 0xd6, 0x3e, 0x39, 0x86, 0x84, 0x3b, 0x2a, 0x3c, 0x70, + 0x6e, 0xa1, 0xea, 0xf9, 0x30, 0xc2, 0xb7, 0x36, 0xf5, 0x7c, 0x68, 0x3e, 0x26, 0xef, 0x7e, 0x15, 0x6f, 0x46, 0x69, + 0x34, 0x3c, 0x3f, 0x3f, 0x6b, 0x41, 0xc2, 0x07, 0x7a, 0x97, 0x46, 0xf4, 0x01, 0xfc, 0x07, 0xd9, 0x1f, 0x9f, 0x41, + 0x87, 0x30, 0xc2, 0xdb, 0xc9, 0xc7, 0x30, 0xe7, 0xf3, 0x94, 0x7e, 0xe6, 0x69, 0x34, 0x1c, 0x0d, 0xef, 0x9f, 0x41, + 0xbd, 0x19, 0x9d, 0x3c, 0xd3, 0x14, 0xda, 0x6d, 0xb5, 0x4c, 0xcb, 0xef, 0xf8, 0x17, 0x66, 0xaa, 0x9f, 0x9e, 0x9e, + 0x0d, 0x3b, 0x30, 0x82, 0x2b, 0xd0, 0x96, 0xc0, 0x78, 0xce, 0x33, 0xd3, 0xe0, 0x55, 0xf6, 0x74, 0x94, 0x46, 0x0f, + 0x1e, 0x1c, 0x77, 0xb2, 0x2c, 0xc2, 0xb7, 0x1f, 0x47, 0xb6, 0xb6, 0xc9, 0x53, 0x00, 0xfb, 0x34, 0x62, 0x0f, 0x1e, + 0x9c, 0xdd, 0xa7, 0xf0, 0xfd, 0xdc, 0xb4, 0x75, 0x3e, 0x1e, 0x66, 0xe7, 0xd0, 0xd6, 0xef, 0x30, 0x9d, 0x93, 0xf3, + 0xe3, 0x91, 0xe9, 0xeb, 0x77, 0x33, 0xea, 0xce, 0xf8, 0x64, 0x7c, 0x62, 0x32, 0xcd, 0x50, 0xcb, 0xcf, 0xdf, 0x58, + 0x1a, 0x65, 0x6c, 0xd4, 0x8e, 0xf0, 0xad, 0x5b, 0xb8, 0x07, 0x27, 0xad, 0xd6, 0xe8, 0x38, 0xc2, 0xa3, 0x87, 0xf3, + 0xf9, 0x5b, 0x03, 0xc1, 0xf6, 0xc9, 0x03, 0xfb, 0xad, 0x3e, 0xdf, 0x41, 0xd3, 0x43, 0x03, 0xb4, 0x11, 0x9f, 0x99, + 0x96, 0xcf, 0x1e, 0xc0, 0x7f, 0xe6, 0xdb, 0x34, 0x5d, 0x7e, 0xcb, 0xd1, 0xc4, 0x2e, 0x4a, 0x9b, 0x3d, 0x68, 0x41, + 0x8d, 0x31, 0xff, 0x38, 0x2c, 0x38, 0xa0, 0xd1, 0xb0, 0x03, 0xff, 0x17, 0xe1, 0x71, 0x7e, 0xf5, 0xda, 0xe1, 0xec, + 0x78, 0x4c, 0xc7, 0xad, 0x08, 0x8f, 0xe5, 0x47, 0xa5, 0x3f, 0x3c, 0x14, 0x69, 0xd4, 0xe9, 0x9c, 0x0f, 0x4d, 0x99, + 0xc5, 0x2f, 0x8a, 0x1b, 0x3c, 0x6e, 0x99, 0x56, 0x26, 0xf4, 0xad, 0x1a, 0x5e, 0x49, 0x58, 0x49, 0xf8, 0x2f, 0xc2, + 0x13, 0x50, 0xb1, 0xb9, 0x56, 0xce, 0xed, 0x76, 0x98, 0xbc, 0x33, 0xa8, 0x39, 0xba, 0x0f, 0xf0, 0xf2, 0xcb, 0x38, + 0xa2, 0xf4, 0xb4, 0xd3, 0x8a, 0xb0, 0x19, 0xf5, 0x79, 0x0b, 0xfe, 0x8b, 0xb0, 0x85, 0x9c, 0x81, 0xeb, 0xe4, 0xe3, + 0xb3, 0x97, 0x37, 0x69, 0x44, 0x47, 0xe3, 0x31, 0x2c, 0x89, 0x99, 0x8c, 0x2f, 0x36, 0x95, 0x82, 0xdd, 0xfd, 0x7a, + 0xe3, 0xb6, 0x8b, 0x49, 0xd0, 0x0e, 0x3a, 0x67, 0x0f, 0x86, 0x27, 0x11, 0x7e, 0x3b, 0xe2, 0x54, 0xc0, 0x2a, 0x65, + 0xa3, 0xd3, 0xec, 0x34, 0x33, 0x09, 0x13, 0x99, 0x46, 0x27, 0xb0, 0xe4, 0x9d, 0x08, 0xf3, 0x2f, 0x57, 0x77, 0x16, + 0xdd, 0xa0, 0xb6, 0x43, 0x90, 0x71, 0x8b, 0x9d, 0x9d, 0x67, 0x11, 0xce, 0xe9, 0x97, 0x67, 0xbf, 0x16, 0x69, 0xc4, + 0xce, 0xd8, 0xd9, 0x98, 0xfa, 0xef, 0x3f, 0xd4, 0xd4, 0xd4, 0x68, 0x8d, 0x4f, 0x21, 0xe9, 0x46, 0x98, 0xb1, 0xde, + 0xcf, 0xc6, 0x06, 0x43, 0x5e, 0xcd, 0xa4, 0xc8, 0x9e, 0x8e, 0xc7, 0xd2, 0x62, 0x31, 0x85, 0x4d, 0xf8, 0x09, 0xa0, + 0x4d, 0x47, 0xa3, 0x73, 0x76, 0x16, 0xe1, 0x4f, 0x76, 0x97, 0xb8, 0x09, 0x7c, 0xb2, 0x98, 0xcd, 0xdc, 0x6e, 0xff, + 0x64, 0x81, 0x02, 0xf3, 0x1d, 0xd3, 0x31, 0x1d, 0x75, 0x22, 0xfc, 0xc9, 0xc0, 0x65, 0x74, 0x0c, 0xff, 0x41, 0x01, + 0xe8, 0xec, 0x41, 0x8b, 0xb1, 0x07, 0x2d, 0xf3, 0x15, 0xe6, 0xb9, 0x99, 0x0f, 0xcf, 0xb2, 0x76, 0x84, 0x3f, 0x39, + 0x74, 0x1c, 0x8f, 0x69, 0x0b, 0xd0, 0xf1, 0x93, 0x43, 0xc7, 0x4e, 0x6b, 0xd8, 0xa1, 0xe6, 0xdb, 0x62, 0xcd, 0xf9, + 0xfd, 0x8c, 0xc1, 0xe4, 0x3e, 0x59, 0x84, 0xbc, 0x7f, 0xff, 0xfc, 0xfc, 0xc1, 0x03, 0xf8, 0x34, 0x6d, 0x97, 0x9f, + 0x4a, 0x3f, 0xcc, 0x0d, 0x92, 0xb5, 0xb2, 0x13, 0xa0, 0x93, 0x9f, 0xcc, 0x18, 0xc7, 0xe3, 0x31, 0x6b, 0x45, 0x38, + 0xe7, 0x33, 0x66, 0x31, 0xc1, 0xfe, 0x36, 0x1d, 0x1d, 0x77, 0xb2, 0xd1, 0x71, 0x27, 0xc2, 0xf9, 0xdb, 0x67, 0x66, + 0x36, 0x2d, 0x98, 0xbd, 0xdf, 0x72, 0x1e, 0x6b, 0x66, 0xf4, 0x0d, 0x0c, 0x12, 0x56, 0x1a, 0x2a, 0xbf, 0x0f, 0xe8, + 0xe1, 0xd9, 0x59, 0x36, 0x82, 0x81, 0xbe, 0x87, 0x6e, 0x01, 0x8c, 0xef, 0xed, 0xe6, 0x1b, 0xd2, 0xd3, 0x53, 0x98, + 0xee, 0xfb, 0xf9, 0xa2, 0x98, 0xbf, 0x4a, 0xa3, 0x07, 0xc7, 0xf7, 0x5b, 0xa3, 0x61, 0x84, 0xdf, 0xbb, 0x09, 0x1e, + 0x67, 0xc3, 0xe3, 0xfb, 0xed, 0x08, 0xbf, 0x37, 0xfb, 0xed, 0xfe, 0xf0, 0xec, 0x1c, 0xce, 0x8d, 0xf7, 0x6a, 0x5e, + 0xbc, 0x9d, 0x98, 0x02, 0x63, 0xfa, 0x00, 0x9a, 0xfd, 0xcd, 0xec, 0xc6, 0x51, 0x1b, 0x36, 0xf2, 0x7b, 0xb3, 0xc9, + 0x0c, 0x9e, 0xdc, 0x6f, 0x9f, 0x9e, 0x9f, 0x46, 0x78, 0xc6, 0x47, 0x02, 0x08, 0xbc, 0xd9, 0x28, 0x0f, 0xda, 0x0f, + 0xee, 0xb7, 0x22, 0x3c, 0x7b, 0xab, 0xb3, 0x8f, 0x74, 0x66, 0xa8, 0xf1, 0x18, 0x60, 0x36, 0xe3, 0x4a, 0xdf, 0xbd, + 0x51, 0x8e, 0x1e, 0xb3, 0x76, 0x84, 0x67, 0x32, 0xcb, 0xa8, 0x7a, 0x6b, 0x13, 0x86, 0xa7, 0x11, 0x16, 0xf4, 0x0b, + 0xfd, 0x5b, 0xfa, 0xcd, 0x34, 0x62, 0x74, 0x64, 0xd2, 0x0c, 0x0e, 0x47, 0xf8, 0xdd, 0x08, 0x6e, 0xf4, 0xd2, 0x68, + 0x3c, 0x1a, 0x9f, 0x02, 0x78, 0x80, 0x00, 0x59, 0xec, 0x06, 0x68, 0xc0, 0xd7, 0xe8, 0xd1, 0x30, 0x8d, 0xce, 0x86, + 0xe7, 0xac, 0x73, 0x1c, 0xe1, 0x92, 0x1a, 0xd1, 0x53, 0xc8, 0x37, 0x9f, 0x1f, 0xcd, 0x96, 0x3a, 0xb1, 0x09, 0x06, + 0x40, 0x23, 0x7a, 0xbf, 0x35, 0x3a, 0x8b, 0xf0, 0xfc, 0x35, 0xf3, 0x7b, 0x8c, 0x31, 0x76, 0x0e, 0xb0, 0x84, 0x24, + 0x83, 0x40, 0xe7, 0xe3, 0xe1, 0x83, 0x73, 0xf3, 0x0d, 0x60, 0xa0, 0x63, 0xc6, 0x00, 0x48, 0xf3, 0xd7, 0xac, 0x04, + 0xc4, 0x68, 0x78, 0xbf, 0x05, 0xf4, 0x65, 0x4e, 0xe7, 0xf4, 0x8e, 0xde, 0x3c, 0x9d, 0x9b, 0x39, 0x8d, 0x47, 0xa7, + 0x11, 0x9e, 0x3f, 0xff, 0x65, 0xbe, 0x18, 0x8f, 0xcd, 0x84, 0xe8, 0xf0, 0x41, 0x84, 0xe7, 0xac, 0x58, 0xc0, 0x1a, + 0x9d, 0x9f, 0x1e, 0x8f, 0x23, 0xec, 0xd0, 0x30, 0x6b, 0x65, 0x43, 0xb8, 0xb2, 0x5c, 0xcc, 0xd2, 0x68, 0x34, 0xa2, + 0xad, 0x11, 0x5c, 0x60, 0xca, 0x9b, 0x5f, 0x0b, 0x8b, 0x46, 0xcc, 0xe0, 0x83, 0x5b, 0x43, 0x98, 0x2f, 0xc0, 0xe3, + 0xe3, 0x90, 0x65, 0x19, 0x75, 0x89, 0x67, 0x67, 0xc7, 0xc7, 0x80, 0x7b, 0x76, 0x86, 0x16, 0x41, 0xde, 0xa8, 0xbb, + 0x61, 0x21, 0xe1, 0xe8, 0x02, 0xa2, 0x0a, 0x64, 0xf5, 0xcd, 0xdd, 0x6b, 0x43, 0x57, 0xdb, 0x67, 0x0f, 0x60, 0x01, + 0x14, 0x1d, 0x8d, 0x5e, 0xd9, 0xc3, 0xed, 0x7c, 0x78, 0x72, 0xda, 0x3e, 0x8e, 0xb0, 0xdf, 0x08, 0xf4, 0xbc, 0x75, + 0xbf, 0x03, 0x25, 0xc4, 0xe8, 0xce, 0x96, 0x18, 0x9f, 0xd0, 0x93, 0xb3, 0x56, 0x84, 0xfd, 0xd6, 0x60, 0xe7, 0xc3, + 0xd3, 0xfb, 0xf0, 0xa9, 0xa6, 0x2c, 0xcf, 0x0d, 0x7e, 0x9f, 0x02, 0x5c, 0x14, 0x7f, 0x26, 0x68, 0x1a, 0xd1, 0xd6, + 0x69, 0xa7, 0x33, 0x82, 0xcf, 0xfc, 0x0b, 0x2b, 0xd2, 0x28, 0x6b, 0xc1, 0x7f, 0x11, 0x0e, 0x76, 0x12, 0x1b, 0x46, + 0xd8, 0xe0, 0xdd, 0x19, 0x3d, 0x35, 0x7b, 0xdf, 0xed, 0xaa, 0xd6, 0x79, 0x0b, 0x36, 0xac, 0xdb, 0x54, 0xee, 0x4b, + 0x09, 0x79, 0xe3, 0x48, 0x2c, 0x8d, 0x70, 0x80, 0xa0, 0xe3, 0xfb, 0xe3, 0x08, 0xfb, 0x1d, 0x77, 0x72, 0x76, 0xde, + 0x01, 0x52, 0xa6, 0x81, 0x50, 0x8c, 0x3a, 0xc3, 0x13, 0x20, 0x4d, 0x9a, 0xbd, 0xb6, 0x78, 0x12, 0x61, 0xfd, 0x54, + 0xe9, 0x57, 0x69, 0x34, 0x3a, 0x1f, 0x8e, 0x47, 0xe7, 0x11, 0xd6, 0x72, 0x46, 0xb5, 0x34, 0x14, 0xf0, 0xf8, 0xe4, + 0x7e, 0x84, 0x0d, 0x9a, 0xb7, 0x58, 0x6b, 0xd4, 0x8a, 0xb0, 0x3b, 0x4a, 0x18, 0x3b, 0xef, 0xc0, 0xb4, 0x7e, 0x7e, + 0xae, 0x01, 0x97, 0x47, 0x6c, 0x78, 0x1c, 0xe1, 0x92, 0xde, 0x1b, 0x42, 0x04, 0x5f, 0x6a, 0x26, 0x3f, 0x3b, 0xd6, + 0x03, 0x48, 0x9d, 0xdf, 0xf0, 0xb0, 0x0c, 0x2f, 0x6f, 0x2c, 0x1a, 0x51, 0xb3, 0xc5, 0x83, 0x2b, 0xdd, 0x27, 0x34, + 0xf6, 0x6c, 0x3b, 0x27, 0xcb, 0x35, 0x2e, 0x23, 0xa5, 0x7e, 0x66, 0x77, 0x2a, 0x56, 0xca, 0x70, 0xb2, 0x41, 0x0a, + 0x78, 0x33, 0x38, 0xdf, 0x00, 0xe7, 0xfe, 0x09, 0x82, 0xa4, 0x20, 0xad, 0xae, 0xb8, 0xf0, 0x2e, 0xa9, 0x5d, 0x01, + 0xf1, 0x13, 0x20, 0xbd, 0x20, 0x94, 0x68, 0x08, 0x33, 0x63, 0x85, 0x49, 0x6f, 0xa9, 0x6f, 0x64, 0x4a, 0x69, 0x6d, + 0xff, 0x29, 0xa1, 0x3e, 0xc0, 0x3c, 0xdc, 0x37, 0x43, 0x08, 0x26, 0xd4, 0x95, 0xc4, 0x84, 0x8b, 0x7e, 0x21, 0x74, + 0xac, 0x54, 0xbf, 0x18, 0xe0, 0xf6, 0x19, 0xc2, 0x10, 0x88, 0x81, 0xf4, 0xe5, 0xe5, 0x65, 0xfb, 0xec, 0xc0, 0x08, + 0x7d, 0x97, 0x97, 0xe7, 0xf6, 0x07, 0xfc, 0x3b, 0xa8, 0x82, 0x5f, 0xc3, 0xf8, 0x1e, 0xb1, 0x40, 0xa3, 0x67, 0xf8, + 0xeb, 0x47, 0x6c, 0xb5, 0x8a, 0x1f, 0x31, 0x02, 0x33, 0xc6, 0x8f, 0x58, 0x62, 0x2e, 0x40, 0xac, 0x9b, 0x0d, 0xe9, + 0x83, 0xe6, 0xac, 0x85, 0x21, 0x24, 0xbb, 0xe7, 0xbc, 0x1f, 0xb1, 0x3e, 0xaf, 0xbb, 0x68, 0x57, 0x71, 0x90, 0x0f, + 0x0e, 0x96, 0x45, 0xaa, 0xad, 0x98, 0xa0, 0xad, 0x98, 0xa0, 0xad, 0x98, 0xa0, 0xab, 0x48, 0xf4, 0x27, 0x3d, 0x90, + 0x52, 0x8c, 0xb2, 0xc5, 0xf1, 0xd4, 0xef, 0x40, 0xed, 0x01, 0xda, 0xc9, 0x5e, 0xa5, 0xec, 0x28, 0x75, 0x15, 0x3b, + 0x15, 0x18, 0x3b, 0x13, 0x9d, 0xb6, 0xe3, 0xe8, 0xdf, 0x51, 0x77, 0xbc, 0xac, 0x89, 0x65, 0xef, 0x76, 0x8a, 0x65, + 0xb0, 0x92, 0x46, 0x34, 0xdb, 0xb7, 0x41, 0x3d, 0x74, 0xff, 0xbe, 0x11, 0xcc, 0xaa, 0x48, 0x73, 0x0d, 0x48, 0xea, + 0x82, 0x14, 0x72, 0x6e, 0xa4, 0xb4, 0x02, 0xa5, 0x23, 0x1d, 0x17, 0xa0, 0xa1, 0xf4, 0x0a, 0xca, 0x32, 0x20, 0x6a, + 0xc3, 0x00, 0x44, 0x59, 0x19, 0xcd, 0xca, 0x6a, 0xa7, 0x20, 0xba, 0x80, 0x26, 0xcc, 0x48, 0x2c, 0xd0, 0x80, 0x30, + 0x0d, 0x08, 0x57, 0x19, 0xc4, 0x19, 0x97, 0x7d, 0x62, 0xb2, 0x95, 0xc9, 0x56, 0x65, 0xb6, 0xf4, 0xd9, 0x56, 0x48, + 0x94, 0x26, 0x5b, 0x96, 0xd9, 0x20, 0xb3, 0xe1, 0x49, 0xaa, 0xf0, 0x30, 0x95, 0x56, 0x54, 0xab, 0x64, 0xab, 0xb7, + 0x34, 0xd4, 0xe6, 0x1e, 0x1c, 0xc4, 0xa5, 0x9c, 0x64, 0xd4, 0xc4, 0xf7, 0x96, 0x3c, 0x29, 0x8c, 0x0c, 0xc4, 0x93, + 0x89, 0xfb, 0x3b, 0x5c, 0x6f, 0xca, 0x4a, 0xc5, 0x64, 0xf8, 0x8d, 0x92, 0xe8, 0x2f, 0xaf, 0x44, 0x7d, 0xc4, 0x4d, + 0x28, 0x9d, 0x0b, 0x92, 0xb4, 0x5a, 0xc7, 0xed, 0xe3, 0xd6, 0x79, 0x8f, 0x1f, 0xb6, 0x3b, 0xc9, 0x83, 0x4e, 0x6a, + 0x14, 0x11, 0x73, 0x79, 0x03, 0x0a, 0x98, 0xa3, 0x4e, 0x72, 0x82, 0x0e, 0xdb, 0x49, 0xeb, 0xf4, 0xb4, 0x09, 0xff, + 0xe0, 0xf7, 0xba, 0xac, 0x76, 0xd2, 0x3a, 0x39, 0xed, 0xf1, 0xa3, 0x8d, 0x4a, 0x31, 0x6f, 0x40, 0x41, 0x74, 0x64, + 0x2a, 0x61, 0xa8, 0x5f, 0x2d, 0xef, 0xb3, 0x2d, 0x3d, 0xcf, 0x7b, 0x1d, 0x2b, 0xab, 0x8a, 0x03, 0xa8, 0xfa, 0xaf, + 0x89, 0x01, 0xa2, 0xff, 0x1a, 0x96, 0xe1, 0x6e, 0x97, 0x05, 0x88, 0xda, 0x8f, 0x78, 0x2c, 0x1a, 0xec, 0x30, 0xb6, + 0xf9, 0x1a, 0xea, 0x36, 0x21, 0x04, 0x1d, 0x9e, 0xb8, 0x5c, 0x15, 0xe6, 0x4e, 0x10, 0x6a, 0x2a, 0xc8, 0x1d, 0xba, + 0x5c, 0x19, 0xe6, 0x0e, 0x11, 0x6a, 0x4a, 0xc8, 0xa5, 0x29, 0x4f, 0x28, 0xe4, 0xe8, 0x84, 0x36, 0x0d, 0x24, 0xab, + 0x45, 0x79, 0xce, 0xfc, 0xb0, 0xf9, 0x18, 0x96, 0xc7, 0x10, 0x14, 0x27, 0x48, 0x0b, 0x78, 0xa6, 0xa4, 0xd4, 0xe6, + 0xb4, 0x70, 0xa9, 0xc6, 0x81, 0x8c, 0x06, 0xfc, 0x73, 0xc8, 0xcc, 0xdb, 0x15, 0xad, 0xde, 0xf1, 0x59, 0x2b, 0x6d, + 0x83, 0xbf, 0x35, 0xc8, 0xda, 0xc2, 0xca, 0xda, 0xc2, 0xcb, 0xda, 0xc2, 0xcb, 0xda, 0x20, 0xc0, 0x07, 0x7d, 0xff, + 0x23, 0x6b, 0x36, 0x2c, 0xbc, 0x34, 0x88, 0xb1, 0x16, 0x0f, 0xb1, 0x5e, 0xad, 0x96, 0x6b, 0x30, 0x57, 0x2a, 0x6b, + 0x48, 0x55, 0xa9, 0x3f, 0x97, 0x45, 0xda, 0xc2, 0x93, 0x14, 0xb4, 0xdc, 0x2d, 0x4c, 0xcd, 0xe6, 0xf6, 0x54, 0x61, + 0x33, 0x14, 0x4e, 0xcf, 0xab, 0x93, 0x2f, 0xc9, 0xb1, 0xd1, 0x1e, 0x2f, 0x8b, 0x94, 0x5b, 0x9a, 0xc1, 0x2d, 0xcd, + 0xe0, 0x96, 0x66, 0x40, 0x23, 0xb8, 0x2c, 0x6c, 0xca, 0x26, 0x94, 0xc0, 0x95, 0x40, 0xff, 0x78, 0x00, 0x91, 0x00, + 0x63, 0x4d, 0xcc, 0xa8, 0x37, 0x3a, 0x6f, 0x43, 0xe4, 0x33, 0x5b, 0x52, 0x27, 0xd4, 0x38, 0x80, 0x97, 0x63, 0xfe, + 0x5a, 0x43, 0xfb, 0x04, 0x9e, 0xa5, 0x79, 0xa8, 0xe3, 0x16, 0xd8, 0x7f, 0x44, 0x45, 0xd4, 0x33, 0x64, 0x21, 0x35, + 0x3a, 0x1b, 0x67, 0xd7, 0xfd, 0x79, 0xc3, 0x9d, 0xd6, 0x52, 0x82, 0xf0, 0x31, 0x86, 0xcf, 0xac, 0xf2, 0xef, 0x2f, + 0xcd, 0x56, 0x9d, 0xcd, 0x99, 0x3d, 0x12, 0xba, 0x60, 0x7b, 0xee, 0x03, 0x47, 0xf5, 0x04, 0x91, 0xca, 0x78, 0x3e, + 0x92, 0x2a, 0xf4, 0x31, 0x78, 0x02, 0x93, 0x5b, 0x6a, 0xfc, 0x62, 0x5e, 0xd8, 0x3f, 0x5f, 0x69, 0xe0, 0x38, 0x58, + 0x4c, 0x86, 0xde, 0xdf, 0xf6, 0xda, 0x04, 0x08, 0x22, 0xfb, 0xfb, 0xd6, 0x2c, 0xdc, 0x7c, 0x6d, 0xda, 0x85, 0x9b, + 0x44, 0x93, 0x0d, 0x3b, 0xd4, 0xaf, 0xd1, 0x3f, 0xde, 0xed, 0xad, 0x98, 0x0c, 0x51, 0x40, 0xb3, 0x0d, 0x58, 0x55, + 0x05, 0x2c, 0xe5, 0xea, 0x95, 0xde, 0x90, 0xd0, 0xbb, 0x19, 0xf3, 0xba, 0x98, 0x0c, 0x77, 0xbe, 0x5f, 0x62, 0x7b, + 0xec, 0xbd, 0xa5, 0x41, 0x0f, 0x5e, 0xb5, 0x3d, 0x65, 0xb7, 0xdf, 0xab, 0x73, 0xb3, 0xb3, 0x8e, 0xca, 0xbf, 0x57, + 0xe7, 0xe9, 0xae, 0x3a, 0x33, 0x7e, 0x1b, 0xfb, 0xbd, 0xa3, 0x03, 0x35, 0xb6, 0xb1, 0x35, 0x9a, 0x0c, 0x21, 0xe0, + 0x3c, 0xfc, 0xb5, 0x61, 0x61, 0xba, 0x9e, 0x84, 0xc3, 0x2a, 0xc8, 0x5e, 0x72, 0x9a, 0x32, 0x4c, 0x49, 0xe7, 0xb0, + 0x30, 0x81, 0x61, 0x44, 0x42, 0x9b, 0x2a, 0xa1, 0x38, 0x27, 0x71, 0x4c, 0x0f, 0x33, 0x08, 0x6f, 0xd3, 0xee, 0xd1, + 0x34, 0xa6, 0x8d, 0x0c, 0x1d, 0xc5, 0xed, 0x06, 0x3d, 0xcc, 0x10, 0x6a, 0xb4, 0x41, 0x67, 0x2a, 0x49, 0xbb, 0x99, + 0x43, 0xc0, 0x4b, 0x43, 0x8a, 0xf3, 0x43, 0x91, 0x14, 0x0d, 0x79, 0xa8, 0x92, 0xa2, 0x91, 0x9c, 0x62, 0x91, 0x4c, + 0xca, 0xe4, 0x89, 0x49, 0x9e, 0xd8, 0xe4, 0x61, 0x99, 0x3c, 0x34, 0xc9, 0x43, 0x9b, 0x4c, 0x49, 0x71, 0x28, 0x12, + 0xda, 0x88, 0xdb, 0xcd, 0x02, 0x1d, 0xc2, 0x08, 0xfc, 0xe8, 0x89, 0x08, 0xe3, 0x8c, 0xaf, 0x8d, 0xa1, 0xce, 0x5c, + 0xe6, 0x2e, 0xf2, 0x67, 0x05, 0xa4, 0xd2, 0x7b, 0x0a, 0xea, 0x3c, 0x0b, 0xc0, 0x84, 0xb5, 0xfd, 0xe3, 0xe3, 0xda, + 0xad, 0xb3, 0x5c, 0x8a, 0xc0, 0x3b, 0x0c, 0x0c, 0xda, 0x3f, 0x3b, 0x9f, 0x18, 0x80, 0xea, 0x9a, 0xe6, 0xf3, 0x29, + 0xdd, 0x72, 0xc1, 0x2d, 0x26, 0x43, 0xb7, 0xb3, 0xca, 0x66, 0x18, 0x2d, 0x6c, 0xbc, 0xe8, 0xba, 0xb3, 0x24, 0x80, + 0xda, 0x3b, 0x68, 0x26, 0xd4, 0x28, 0xc9, 0x6d, 0x8d, 0x49, 0xc1, 0xee, 0x54, 0x46, 0x73, 0x16, 0x57, 0x07, 0x70, + 0x35, 0x4c, 0x46, 0x5e, 0x80, 0x59, 0x7d, 0x71, 0x98, 0x1c, 0x37, 0x74, 0x32, 0x39, 0x4c, 0x4e, 0x1f, 0x34, 0x74, + 0x32, 0x3c, 0x4c, 0xda, 0xed, 0x0a, 0x67, 0x93, 0x82, 0xe8, 0x64, 0x42, 0x34, 0x68, 0x0c, 0x6d, 0xa3, 0x72, 0x4e, + 0xc1, 0x4e, 0xec, 0xdf, 0x18, 0x46, 0xc3, 0x0d, 0x43, 0xb0, 0x89, 0x0d, 0x9d, 0xb9, 0x35, 0x86, 0xb0, 0x9b, 0xce, + 0xe9, 0x69, 0x53, 0x27, 0x05, 0xd6, 0x76, 0x25, 0x9b, 0x3a, 0x99, 0x60, 0x6d, 0x97, 0xaf, 0xa9, 0x93, 0xa1, 0x6d, + 0xca, 0xe8, 0x00, 0x99, 0x08, 0x80, 0xf5, 0x9c, 0x05, 0x90, 0xef, 0x78, 0x4f, 0x97, 0x35, 0x68, 0x0d, 0xbf, 0x57, + 0xae, 0xe9, 0x0b, 0x2a, 0xaa, 0xc1, 0x5e, 0x88, 0x7d, 0xab, 0x68, 0xbb, 0x6a, 0x92, 0xfd, 0xeb, 0xb2, 0x65, 0xb3, + 0x85, 0xd4, 0xf5, 0x82, 0x0f, 0x6b, 0x18, 0xe2, 0x4a, 0xb9, 0x83, 0xfb, 0x15, 0x25, 0x31, 0x04, 0xc8, 0x33, 0xa7, + 0x10, 0x27, 0x5e, 0x8f, 0x0c, 0x49, 0xbc, 0xd1, 0x58, 0xa3, 0x38, 0x38, 0x6f, 0x9f, 0x86, 0x54, 0x75, 0x2b, 0x6a, + 0x1e, 0x21, 0xd1, 0x42, 0x58, 0xbb, 0xca, 0x51, 0x14, 0xb0, 0x20, 0x4e, 0xbb, 0x5b, 0x3b, 0x20, 0x0e, 0x0e, 0x36, + 0xcf, 0x0b, 0xff, 0x7e, 0xc1, 0xd6, 0x9b, 0x05, 0x95, 0x51, 0x9e, 0x7f, 0x55, 0xc9, 0x9a, 0xeb, 0xf2, 0x00, 0x51, + 0x7c, 0xfc, 0xaa, 0xfb, 0x86, 0xc2, 0xf7, 0xab, 0xe0, 0x7d, 0x2e, 0xa7, 0x79, 0x66, 0x32, 0x4c, 0x5f, 0x83, 0x60, + 0x6c, 0x6f, 0xc2, 0x09, 0x95, 0x06, 0x87, 0xff, 0xb2, 0xe3, 0xa0, 0x13, 0xf7, 0xea, 0x4b, 0xd8, 0xe8, 0xdf, 0xa1, + 0x79, 0x6f, 0x05, 0x1b, 0xe7, 0xd8, 0xbd, 0x5a, 0xd5, 0xde, 0xf8, 0xb1, 0x2f, 0xc9, 0xa0, 0x83, 0x03, 0xae, 0x9e, + 0x81, 0x45, 0x32, 0x8b, 0x1b, 0xe1, 0xe1, 0xfb, 0x4f, 0xed, 0xb4, 0xfe, 0xdb, 0x9c, 0xab, 0x69, 0x70, 0xd0, 0x3d, + 0xac, 0xe5, 0xef, 0x5c, 0x89, 0x9e, 0x4e, 0xb9, 0x5b, 0xeb, 0xbf, 0x2b, 0x7b, 0xef, 0xad, 0xd7, 0xa6, 0x0e, 0x0e, + 0x78, 0x15, 0xf3, 0x29, 0xfa, 0x21, 0x42, 0x3d, 0x23, 0x83, 0x3c, 0xcb, 0x25, 0x85, 0x1b, 0x51, 0xb8, 0x62, 0x48, + 0x1b, 0xfc, 0x48, 0xe3, 0x3f, 0xe4, 0xff, 0xa7, 0x46, 0x0e, 0x75, 0xda, 0xe0, 0x81, 0x00, 0x16, 0xb2, 0x42, 0x55, + 0xb4, 0x45, 0x03, 0xe9, 0xd0, 0x7c, 0x1b, 0x95, 0x87, 0x39, 0x9d, 0xcf, 0xf3, 0x3b, 0xf3, 0xe0, 0x56, 0xc0, 0x51, + 0x55, 0x17, 0x4d, 0x2e, 0xd4, 0x1d, 0x2e, 0x80, 0xa7, 0x07, 0xdc, 0x43, 0xc6, 0x55, 0xb5, 0xbc, 0xdc, 0x16, 0x08, + 0x24, 0x33, 0x45, 0x64, 0xb3, 0xdd, 0x55, 0x97, 0x20, 0x97, 0x35, 0x9b, 0x48, 0xbb, 0x08, 0xe0, 0x98, 0x83, 0x4c, + 0xa6, 0xac, 0x3b, 0xea, 0x9e, 0x2d, 0x08, 0x92, 0x9b, 0x34, 0x22, 0xdb, 0xee, 0x52, 0x7c, 0x1c, 0x03, 0x1a, 0x21, + 0x2b, 0xf0, 0x85, 0xc2, 0x22, 0x07, 0xae, 0xb3, 0xf0, 0x1d, 0x7f, 0xa3, 0xa5, 0xa2, 0xaf, 0x06, 0x03, 0x5c, 0x98, + 0x37, 0x26, 0xca, 0xf9, 0x14, 0x2a, 0x78, 0xb3, 0x28, 0x10, 0x51, 0xf8, 0x6a, 0xb5, 0x0f, 0x4f, 0x02, 0xb9, 0x36, + 0xc1, 0x7f, 0xd5, 0xfd, 0xac, 0x9e, 0xff, 0x80, 0x71, 0x30, 0xd2, 0x32, 0x17, 0x85, 0x4e, 0xde, 0x64, 0x17, 0xa2, + 0xdb, 0x68, 0x30, 0x13, 0xad, 0x89, 0x40, 0x68, 0x36, 0x70, 0x2e, 0x84, 0x3f, 0x36, 0x00, 0x93, 0x62, 0x36, 0x8c, + 0x1d, 0xc4, 0xd7, 0xae, 0x25, 0xac, 0x56, 0xca, 0x86, 0x49, 0x31, 0x39, 0x36, 0x60, 0x4a, 0xd9, 0x4f, 0x19, 0x8f, + 0xb5, 0x32, 0xe3, 0xe0, 0x6e, 0xab, 0xbf, 0xad, 0xf6, 0xf3, 0x1e, 0xb7, 0xd7, 0x78, 0xdc, 0x04, 0x1f, 0x30, 0x80, + 0x5a, 0x6e, 0x6c, 0x70, 0x6b, 0x2c, 0x1f, 0x5b, 0xcb, 0x5e, 0xb6, 0x09, 0x41, 0x51, 0x3a, 0xdb, 0xdb, 0x9b, 0x5b, + 0x1f, 0x7c, 0x50, 0x99, 0x39, 0x29, 0xa4, 0xfb, 0x20, 0x47, 0x0f, 0x08, 0x74, 0x6e, 0x7f, 0x56, 0x74, 0xa1, 0x92, + 0x89, 0xcb, 0x31, 0xfe, 0x12, 0xdc, 0xe6, 0xf5, 0xa3, 0xeb, 0x6b, 0xb3, 0xc9, 0xaf, 0xaf, 0x23, 0x1c, 0x5a, 0xa8, + 0x47, 0x01, 0x2f, 0x18, 0x0d, 0xca, 0xf8, 0x54, 0x66, 0xe3, 0x37, 0xdb, 0x55, 0x63, 0xef, 0x69, 0x85, 0x77, 0xb0, + 0x3c, 0xa6, 0xf1, 0x2d, 0x8f, 0xce, 0x3e, 0x07, 0x78, 0xb3, 0x3e, 0x1f, 0x74, 0xdf, 0xc4, 0x0a, 0x1d, 0x1c, 0xbc, + 0x89, 0x25, 0xea, 0x5d, 0x31, 0x73, 0xe7, 0x06, 0x2e, 0xdd, 0x7d, 0x6e, 0x86, 0x2f, 0x03, 0x04, 0xb8, 0x62, 0x9b, + 0x92, 0xcd, 0x5b, 0x13, 0x40, 0x23, 0x85, 0x00, 0xdd, 0x10, 0x26, 0xd8, 0x81, 0x04, 0x7a, 0x7d, 0x13, 0x42, 0xbb, + 0xcb, 0x08, 0x03, 0x16, 0xbe, 0x74, 0xb8, 0x63, 0xc9, 0x8c, 0x15, 0x13, 0x56, 0xac, 0x56, 0xef, 0xa9, 0x75, 0xa2, + 0xdb, 0x88, 0xf7, 0xa8, 0xba, 0x8d, 0x06, 0x35, 0xe3, 0x07, 0xf1, 0x81, 0x0e, 0xf0, 0xfe, 0x9b, 0xb8, 0x40, 0x08, + 0x2c, 0x8c, 0xb8, 0x58, 0x78, 0x87, 0xb1, 0xac, 0xb6, 0x2e, 0x05, 0x2a, 0x1b, 0xc9, 0x49, 0x0b, 0x4f, 0x49, 0x56, + 0xae, 0xd1, 0xc5, 0xb4, 0xdb, 0x68, 0xe4, 0x48, 0xc6, 0x59, 0x3f, 0x1f, 0x60, 0x8e, 0x0b, 0xb8, 0x4c, 0xdd, 0x5e, + 0x87, 0x39, 0xab, 0x51, 0x2e, 0x37, 0xdf, 0xa5, 0x1d, 0x6b, 0xfa, 0x88, 0xae, 0x03, 0x60, 0x3c, 0xa2, 0x01, 0x91, + 0xd8, 0x05, 0x64, 0x61, 0x81, 0xac, 0x3c, 0x90, 0x85, 0x01, 0xb2, 0x42, 0xbd, 0x39, 0x44, 0x3e, 0x52, 0x28, 0xdd, + 0xa2, 0xe8, 0xf5, 0x18, 0x9d, 0xce, 0xff, 0x03, 0x73, 0x13, 0x26, 0xc2, 0x2d, 0x07, 0xf8, 0x82, 0x38, 0x97, 0x42, + 0x45, 0x96, 0x51, 0x64, 0xc2, 0xd5, 0xe2, 0x5b, 0xf3, 0x27, 0xb9, 0xc5, 0x77, 0xf6, 0xc7, 0x5d, 0xa0, 0x4c, 0x7a, + 0x5e, 0xd3, 0x36, 0x70, 0x17, 0xdc, 0x2d, 0x4a, 0x22, 0x40, 0x6b, 0x17, 0xa9, 0x50, 0xd4, 0x1f, 0x6f, 0x53, 0x36, + 0xa6, 0x84, 0x68, 0x10, 0x85, 0x45, 0x40, 0x3a, 0xff, 0xfc, 0x33, 0x42, 0x3d, 0x01, 0x21, 0x81, 0xdc, 0xc9, 0xd6, + 0x6c, 0xa3, 0x46, 0x94, 0x44, 0x69, 0xec, 0x23, 0x4e, 0xc0, 0xce, 0x88, 0xa2, 0xe0, 0xe1, 0x96, 0x72, 0x18, 0x1f, + 0x6a, 0xc3, 0x30, 0x83, 0xaa, 0x62, 0x68, 0x5c, 0x2e, 0x37, 0x23, 0x16, 0x19, 0xa8, 0x0a, 0x13, 0x2e, 0x06, 0xd9, + 0xd7, 0xcc, 0x18, 0x61, 0x07, 0x07, 0xac, 0x2f, 0x06, 0xc1, 0xf3, 0x64, 0xd5, 0x75, 0xb8, 0x0e, 0x17, 0x2e, 0xa6, + 0x10, 0x32, 0x7e, 0xb5, 0xb2, 0x7f, 0xc9, 0x07, 0x23, 0xcd, 0xc0, 0x3b, 0x73, 0xc1, 0x19, 0x2b, 0x76, 0xcb, 0x62, + 0x89, 0x96, 0xbf, 0x83, 0xd9, 0x9e, 0x0b, 0x00, 0xc8, 0xdd, 0x54, 0xdb, 0x1e, 0xea, 0x73, 0xa3, 0x51, 0x08, 0xc2, + 0xef, 0x56, 0x47, 0x1a, 0x9e, 0xeb, 0x30, 0xaf, 0x16, 0x46, 0x37, 0x53, 0x65, 0x34, 0x54, 0x38, 0x52, 0x12, 0x30, + 0x41, 0x37, 0x74, 0x12, 0x7e, 0xd4, 0xa9, 0xa4, 0x63, 0x21, 0x01, 0x0a, 0x1c, 0x99, 0xcb, 0x79, 0x13, 0xed, 0x9e, + 0xa1, 0x1d, 0x44, 0x2e, 0x30, 0xa1, 0xa9, 0xcb, 0x96, 0x2e, 0x2c, 0x55, 0x34, 0x93, 0x0b, 0xc5, 0x16, 0x73, 0x38, + 0xdf, 0xcb, 0xb4, 0x2c, 0xe7, 0xd9, 0xe7, 0x7a, 0x0a, 0x58, 0x3b, 0xde, 0xea, 0x19, 0x13, 0x8b, 0xc8, 0xcd, 0xf3, + 0xab, 0x15, 0xf7, 0xdf, 0xbc, 0xc0, 0x8f, 0x48, 0xe7, 0xf0, 0x2b, 0xfe, 0x48, 0xc9, 0xa3, 0xc6, 0x57, 0x3c, 0xe1, + 0xc4, 0xf2, 0x06, 0xc9, 0x9b, 0xd7, 0x57, 0x2f, 0xde, 0xbd, 0x78, 0xff, 0xf4, 0xfa, 0xc5, 0xab, 0x67, 0x2f, 0x5e, + 0xbd, 0x78, 0xf7, 0x11, 0xff, 0x43, 0xc9, 0xd7, 0xa3, 0xf6, 0x79, 0x0b, 0x7f, 0x20, 0x5f, 0x8f, 0x3a, 0xf8, 0x56, + 0x93, 0xaf, 0x47, 0x27, 0x38, 0x57, 0xe4, 0xeb, 0x61, 0xe7, 0xe8, 0x18, 0x2f, 0xb4, 0x6d, 0x32, 0x97, 0x93, 0x76, + 0x0b, 0xff, 0xe3, 0xbe, 0x40, 0xbc, 0xaf, 0x66, 0x31, 0x61, 0x1b, 0xc6, 0x0f, 0xa6, 0x0c, 0x1d, 0x2a, 0x63, 0x88, + 0x72, 0x11, 0xa0, 0xd3, 0x54, 0x85, 0xe8, 0x64, 0xe3, 0x31, 0x83, 0x0d, 0x23, 0xa0, 0x15, 0x27, 0xae, 0x1d, 0x7e, + 0xd4, 0x66, 0xc7, 0x40, 0x9f, 0x78, 0x29, 0x1c, 0x97, 0x2a, 0x9c, 0xb6, 0xd3, 0x62, 0x8c, 0x73, 0x29, 0x8b, 0x78, + 0x01, 0x8c, 0x80, 0xd1, 0x5a, 0xf0, 0xa3, 0x32, 0xf0, 0x93, 0xb8, 0x20, 0xed, 0x5e, 0x3b, 0x15, 0x17, 0xa4, 0xd3, + 0xeb, 0xc0, 0x9f, 0xd3, 0xde, 0x69, 0xda, 0x6e, 0xa1, 0xc3, 0x60, 0x1c, 0x7f, 0xd4, 0xd0, 0xba, 0x3f, 0xc0, 0xae, + 0x0b, 0xf5, 0x4f, 0xa1, 0xbd, 0x4a, 0x4f, 0x38, 0x75, 0x6c, 0xbb, 0x2b, 0x2e, 0x98, 0xd1, 0xc3, 0xf2, 0x1f, 0x00, + 0xb5, 0x8d, 0x6f, 0x4a, 0xb9, 0x71, 0xdc, 0x2f, 0x7e, 0x24, 0x50, 0x2d, 0xba, 0x4c, 0xcc, 0x56, 0x2d, 0x04, 0x4c, + 0xa3, 0xc9, 0x06, 0x73, 0xa0, 0x44, 0xc9, 0x42, 0xfb, 0x08, 0xf9, 0xaa, 0x29, 0x51, 0x32, 0x97, 0xf3, 0xb8, 0xa6, + 0x6a, 0xf8, 0x35, 0x30, 0x73, 0xdc, 0xe7, 0xea, 0x15, 0x7d, 0x15, 0xd7, 0x78, 0x9e, 0x90, 0xb5, 0x0b, 0xb7, 0xc5, + 0x2f, 0xce, 0x8a, 0xa2, 0x06, 0xae, 0x12, 0xb0, 0x7e, 0x54, 0x4d, 0x7d, 0x01, 0x4f, 0x01, 0xb2, 0x86, 0xbe, 0x24, + 0x01, 0xf5, 0xfc, 0xa9, 0x34, 0xe3, 0x2a, 0x95, 0xd1, 0x5e, 0x11, 0x6d, 0xcc, 0x82, 0xbc, 0x22, 0xfa, 0x42, 0x19, + 0x20, 0x48, 0xc2, 0xfb, 0x62, 0x00, 0x07, 0xbe, 0x1d, 0xa0, 0x34, 0x74, 0x0e, 0xd4, 0x4a, 0x95, 0x99, 0x90, 0xf9, + 0x34, 0x71, 0x0e, 0x40, 0xf3, 0x54, 0xa9, 0xa0, 0xcc, 0x27, 0x96, 0x28, 0x18, 0xfa, 0x6f, 0xe1, 0x06, 0x38, 0x8c, + 0x0d, 0x2a, 0x06, 0xd9, 0xf7, 0x44, 0x3d, 0xbf, 0x7d, 0xde, 0x3a, 0xfa, 0x1a, 0xe4, 0x8f, 0x94, 0xb7, 0xf7, 0xf8, + 0x3b, 0xa0, 0xe4, 0x36, 0x32, 0x57, 0x1b, 0xfb, 0xa0, 0x6a, 0xdd, 0x10, 0x20, 0x87, 0x1a, 0x1d, 0x99, 0x57, 0x11, + 0xbb, 0x48, 0x1f, 0x92, 0x76, 0x0b, 0x22, 0xa1, 0xed, 0xa0, 0x7c, 0x3f, 0x6d, 0xc0, 0x54, 0x27, 0xb7, 0x4d, 0xa0, + 0xd5, 0xf0, 0x50, 0xd2, 0x5d, 0x93, 0x27, 0x77, 0x58, 0x05, 0x38, 0xc3, 0x0e, 0x59, 0x43, 0x1c, 0x0a, 0xe4, 0x22, + 0xc8, 0xda, 0x0d, 0xa0, 0xa9, 0xe8, 0xd8, 0x07, 0xfb, 0xbc, 0x71, 0xd4, 0x45, 0x33, 0x39, 0x3d, 0xfc, 0x7a, 0x70, + 0x10, 0xcb, 0x06, 0x79, 0x84, 0xf0, 0x92, 0x82, 0x41, 0x36, 0x38, 0xb0, 0x71, 0xcb, 0xc4, 0xa7, 0x2a, 0xa0, 0x8e, + 0x0b, 0x55, 0x3b, 0xd6, 0xaa, 0xce, 0xca, 0xdd, 0xe0, 0xc7, 0xd4, 0x41, 0x8d, 0x20, 0xcd, 0x8e, 0xae, 0x53, 0x83, + 0x72, 0xcd, 0xdb, 0x0c, 0xb6, 0x65, 0xe3, 0x23, 0x45, 0x3f, 0x3c, 0x6a, 0x7e, 0x0d, 0x26, 0x5c, 0x33, 0x4d, 0x7a, + 0xd4, 0x78, 0x84, 0x7e, 0x78, 0x14, 0xf8, 0x0b, 0xf2, 0x8a, 0x3d, 0xf1, 0xdc, 0xc8, 0x4f, 0x96, 0x2b, 0xfd, 0x09, + 0x24, 0xfb, 0x82, 0xfc, 0x04, 0x58, 0x4e, 0xc9, 0x4f, 0xb1, 0x6c, 0x42, 0x1c, 0x45, 0xf2, 0x53, 0x5c, 0xc0, 0x8f, + 0x9c, 0xfc, 0x14, 0x03, 0xb6, 0xe3, 0xa9, 0xf9, 0x51, 0x94, 0xc0, 0x00, 0x1f, 0x35, 0x69, 0x5d, 0xd5, 0x8a, 0xd5, + 0x4a, 0x1c, 0x1c, 0x48, 0xfb, 0x8b, 0x5e, 0x66, 0x07, 0x07, 0xf9, 0xc5, 0xb4, 0xea, 0x9b, 0xe9, 0x5d, 0xf4, 0xc5, + 0x20, 0x14, 0x0e, 0x4c, 0xd3, 0x78, 0x38, 0xe3, 0x4f, 0x21, 0x65, 0x35, 0x0d, 0x34, 0x8f, 0x3b, 0xf7, 0xcf, 0xce, + 0x31, 0xfc, 0x7b, 0x3f, 0x28, 0xf8, 0x73, 0xc9, 0x77, 0x91, 0x36, 0x6b, 0x9e, 0x55, 0xc8, 0x76, 0x19, 0xe0, 0x33, + 0x66, 0xa8, 0x29, 0x0e, 0x0e, 0xf8, 0x45, 0x80, 0xcb, 0x98, 0xa1, 0x46, 0x60, 0xb1, 0xf7, 0xb0, 0xb4, 0x27, 0x33, + 0x5c, 0x13, 0xbc, 0x90, 0xcb, 0xfb, 0xc5, 0xe0, 0x42, 0x3b, 0x6a, 0x12, 0xc6, 0xd1, 0x56, 0xa4, 0xe5, 0x36, 0x59, + 0x57, 0x34, 0xd5, 0x65, 0xbb, 0x8b, 0x24, 0x51, 0x0d, 0x71, 0x79, 0xd9, 0xc6, 0xa0, 0x92, 0xef, 0x29, 0x22, 0x53, + 0x41, 0xbc, 0xaf, 0xdf, 0x32, 0x97, 0xa9, 0xc2, 0x53, 0x9e, 0x0a, 0x2f, 0x67, 0xbf, 0xf6, 0xd6, 0xd3, 0xc6, 0xfb, + 0xd2, 0xf4, 0xcc, 0xb0, 0xe8, 0xa9, 0xd2, 0x6b, 0x10, 0x36, 0xa9, 0x1a, 0xc0, 0x03, 0x84, 0x25, 0xe6, 0x31, 0xeb, + 0x2a, 0xc7, 0x20, 0xc0, 0xb3, 0x6a, 0xb4, 0x21, 0x13, 0x3e, 0xd7, 0xa9, 0x82, 0x81, 0x9a, 0xc2, 0x17, 0x40, 0xa6, + 0xb2, 0xca, 0x30, 0xdb, 0x37, 0x0c, 0x05, 0x04, 0x14, 0xb8, 0x24, 0x2c, 0x90, 0xe0, 0xe1, 0xf6, 0x23, 0x20, 0x1c, + 0x75, 0x72, 0x61, 0x27, 0x77, 0xa1, 0xa0, 0x3b, 0x31, 0xb8, 0xd0, 0x5d, 0x24, 0x1a, 0x0d, 0xc7, 0x6d, 0x5f, 0x0a, + 0x33, 0x88, 0x66, 0x7b, 0x70, 0xc9, 0xba, 0x48, 0x35, 0x9b, 0xa5, 0x01, 0xe4, 0x65, 0x6b, 0xb5, 0x52, 0x17, 0xbe, + 0x91, 0x9e, 0x3f, 0xc7, 0x0d, 0xdf, 0xe5, 0x05, 0xcf, 0xdf, 0x24, 0xe9, 0x47, 0x40, 0x55, 0x81, 0xcf, 0x96, 0xf3, + 0x08, 0x47, 0xe6, 0x6d, 0x3a, 0xf8, 0x6b, 0xde, 0x14, 0x8b, 0x70, 0xe4, 0x9e, 0xab, 0x8b, 0x06, 0xd5, 0x60, 0x79, + 0x56, 0x46, 0x5a, 0xe7, 0xc9, 0x35, 0x30, 0x0e, 0xfa, 0x6f, 0x85, 0x96, 0xd5, 0xef, 0x24, 0x77, 0x31, 0x47, 0x94, + 0x7f, 0x41, 0xcd, 0x8d, 0x6a, 0xbd, 0xdb, 0xcb, 0x93, 0xe3, 0xc8, 0x57, 0x85, 0x97, 0x08, 0xbe, 0xf3, 0x84, 0x63, + 0xdb, 0xbd, 0x1c, 0xbe, 0x2c, 0x7b, 0x00, 0xce, 0x7b, 0xbd, 0x46, 0xf8, 0x37, 0xb9, 0xf3, 0x19, 0xe1, 0xe8, 0x5a, + 0x8a, 0x27, 0x54, 0xd3, 0xa8, 0xf1, 0xc6, 0x18, 0xbe, 0x59, 0x39, 0xab, 0xfb, 0xad, 0x71, 0xb0, 0x7f, 0xab, 0x7b, + 0x88, 0x02, 0x51, 0x7b, 0xf1, 0xc8, 0xca, 0xbe, 0x26, 0xf6, 0x87, 0x0c, 0x4c, 0xdf, 0x76, 0xc0, 0xc3, 0x8f, 0x91, + 0x82, 0x6f, 0xb2, 0xe5, 0x93, 0x28, 0x84, 0x57, 0xad, 0x79, 0x44, 0x43, 0x8a, 0xed, 0xc3, 0x78, 0xcf, 0xae, 0x51, + 0xc8, 0x75, 0x8f, 0x55, 0x9d, 0x98, 0x56, 0xdd, 0x18, 0xa9, 0x83, 0x6d, 0xb2, 0xe0, 0xac, 0xea, 0xdd, 0x48, 0x28, + 0xd5, 0xe3, 0x70, 0xe6, 0x81, 0xcf, 0x66, 0xdb, 0xbc, 0x98, 0x6c, 0x9f, 0x90, 0x53, 0x60, 0xc8, 0xbb, 0x5f, 0x46, + 0xbe, 0xba, 0x84, 0x63, 0x37, 0x0e, 0x20, 0x2b, 0xc9, 0xe5, 0xd2, 0x3d, 0xef, 0xc6, 0xfb, 0x72, 0xb0, 0x2e, 0x1f, + 0x7b, 0x0b, 0xf0, 0xa0, 0x1a, 0xa9, 0xc8, 0x42, 0xce, 0xc0, 0xbf, 0x94, 0x58, 0xd3, 0x0f, 0xf1, 0xaf, 0x70, 0xc0, + 0x57, 0x48, 0x9a, 0x5a, 0xf5, 0x13, 0x3c, 0xc2, 0x04, 0x0a, 0x6f, 0x5b, 0xf7, 0x93, 0x0c, 0xbd, 0x5d, 0xeb, 0x3a, + 0x15, 0xeb, 0x50, 0x5a, 0x57, 0xac, 0x94, 0x85, 0x83, 0xe3, 0x2e, 0x46, 0xeb, 0xd4, 0x39, 0x9f, 0xba, 0x97, 0x9b, + 0x1e, 0x0a, 0x70, 0x7c, 0xe1, 0x52, 0x3c, 0x2b, 0x20, 0x14, 0x57, 0xa8, 0x4f, 0xfb, 0x59, 0x86, 0x4f, 0x13, 0xf7, + 0xe1, 0x9e, 0xb0, 0xe4, 0x39, 0xcb, 0xe7, 0xb4, 0x61, 0x81, 0x14, 0x50, 0x28, 0x85, 0xc5, 0x6a, 0x15, 0x0b, 0x13, + 0xa0, 0xc1, 0xc5, 0xe7, 0x75, 0x0f, 0x71, 0x18, 0xfd, 0x1d, 0xd4, 0xc5, 0x5e, 0x3d, 0x62, 0x4c, 0x58, 0x51, 0x78, + 0xe9, 0xa4, 0xb2, 0xa0, 0xaf, 0x5d, 0x7d, 0x88, 0x6a, 0xca, 0xbd, 0xd8, 0xe8, 0x7b, 0xdf, 0xf1, 0x19, 0x93, 0x0b, + 0x78, 0x01, 0x09, 0x33, 0xa2, 0x98, 0xf6, 0xdf, 0x40, 0x41, 0xe0, 0x19, 0x1d, 0x1e, 0xe2, 0x23, 0xf0, 0x55, 0x9e, + 0xd6, 0xc9, 0xcc, 0xbf, 0xab, 0x11, 0x99, 0xb8, 0x97, 0x51, 0x2f, 0x02, 0x17, 0x21, 0x10, 0xa1, 0x08, 0x89, 0x98, + 0x18, 0x45, 0xbd, 0xc8, 0xf8, 0x5b, 0x45, 0x60, 0x35, 0x06, 0x4a, 0xee, 0x08, 0xcf, 0x55, 0x45, 0xc4, 0xc2, 0x9a, + 0x3a, 0xa8, 0xc4, 0x52, 0x63, 0xa6, 0x7d, 0xd4, 0xa9, 0x40, 0x58, 0x64, 0x9b, 0x82, 0xb2, 0xde, 0x50, 0x17, 0x60, + 0x49, 0x8c, 0xe9, 0x2d, 0x4f, 0xae, 0x81, 0x9b, 0x63, 0x23, 0x57, 0x74, 0xc9, 0xaf, 0x40, 0x3d, 0x9d, 0x16, 0xf8, + 0xda, 0x30, 0x6c, 0xa3, 0x94, 0xae, 0x09, 0xc7, 0x19, 0x29, 0x12, 0x7a, 0x0b, 0x01, 0x2a, 0x66, 0x5c, 0xa4, 0x39, + 0x9e, 0xd1, 0xdb, 0x74, 0x8a, 0x67, 0x5c, 0x3c, 0xb1, 0xcb, 0x9e, 0x8e, 0x20, 0xc9, 0x7f, 0x2c, 0xd6, 0xc4, 0xbc, + 0xaf, 0xf5, 0xbb, 0x62, 0xc5, 0x23, 0xe0, 0x55, 0x54, 0x8c, 0xba, 0x23, 0x63, 0x53, 0xce, 0x74, 0x65, 0xbc, 0xfe, + 0x5a, 0xc7, 0x14, 0x67, 0x38, 0x47, 0x49, 0x2e, 0x31, 0xeb, 0x89, 0xf4, 0x35, 0x04, 0xa7, 0xce, 0xb0, 0x7d, 0x9b, + 0x8b, 0xdf, 0xb2, 0xfc, 0x99, 0x2c, 0xde, 0x9b, 0x2d, 0x9f, 0x23, 0x28, 0x04, 0x2e, 0x2a, 0xa2, 0x09, 0xb7, 0x7b, + 0x8b, 0x9e, 0xac, 0x9a, 0xa2, 0xb7, 0xb6, 0x29, 0x37, 0xc4, 0x29, 0x44, 0xf5, 0x4d, 0xa6, 0xbc, 0xd1, 0xc6, 0xac, + 0xd7, 0xfa, 0x4e, 0xa3, 0x53, 0x54, 0x96, 0x44, 0x18, 0xd6, 0xaa, 0xa9, 0x52, 0x49, 0x44, 0x53, 0x39, 0x09, 0x6f, + 0x69, 0x80, 0x9d, 0x2a, 0x9c, 0xc9, 0x85, 0xd0, 0xa9, 0x0c, 0xf0, 0x86, 0x56, 0x9b, 0x6b, 0x79, 0x6b, 0x21, 0xa6, + 0xf1, 0x9d, 0xfd, 0xc1, 0xf0, 0xb5, 0x51, 0xf1, 0xbf, 0x05, 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, + 0x5b, 0xfa, 0xbe, 0xa8, 0x94, 0x45, 0x61, 0x83, 0x44, 0xe1, 0x52, 0x1d, 0x2c, 0x89, 0x48, 0xa0, 0x5d, 0x23, 0xca, + 0xcd, 0xb8, 0x80, 0xf8, 0x84, 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, 0x7e, 0x28, 0x5f, 0x83, 0x69, 0x99, 0x57, + 0xb7, 0x49, 0x1b, 0x4f, 0x02, 0xa4, 0x6c, 0x56, 0x3c, 0x5c, 0x07, 0xb7, 0x5b, 0x87, 0x31, 0x6f, 0x92, 0x36, 0x42, + 0x87, 0x4e, 0xb8, 0x12, 0xb1, 0x91, 0x9c, 0x0e, 0x1f, 0x1d, 0xc1, 0xdd, 0xcb, 0x4c, 0x6d, 0xf8, 0x4a, 0xd9, 0x6a, + 0xcd, 0x76, 0xeb, 0x90, 0xef, 0xac, 0xd2, 0x68, 0xe3, 0x19, 0x23, 0x4b, 0x70, 0x2e, 0xa3, 0x85, 0x55, 0x35, 0x80, + 0x3f, 0xea, 0x0b, 0xf1, 0xdb, 0x82, 0x8e, 0xcc, 0xf7, 0xa1, 0x4d, 0x79, 0xbd, 0xd0, 0x3e, 0xa9, 0xc9, 0x61, 0x10, + 0x1d, 0xe4, 0x4a, 0x06, 0x39, 0x31, 0x3f, 0x22, 0xc9, 0x29, 0xba, 0x68, 0xf7, 0x92, 0xd3, 0x43, 0x7e, 0xc8, 0x53, + 0xe0, 0x61, 0xe3, 0xa6, 0xaf, 0xd0, 0x6c, 0xfb, 0x3a, 0x8f, 0x17, 0x43, 0x9e, 0xb9, 0xe6, 0xab, 0x0e, 0xca, 0x54, + 0x3b, 0x47, 0xc8, 0x02, 0x14, 0xf3, 0xbd, 0x04, 0xd9, 0xf5, 0x6e, 0x0e, 0x79, 0x0a, 0xfd, 0x40, 0xad, 0x8e, 0xad, + 0x55, 0x0e, 0xee, 0xb7, 0x05, 0x20, 0x98, 0xef, 0xa8, 0x36, 0x17, 0x9b, 0xde, 0x8c, 0xab, 0xce, 0x0e, 0x79, 0x35, + 0xc2, 0xb0, 0xcc, 0x76, 0x7f, 0x7e, 0x6a, 0x55, 0x97, 0x87, 0x01, 0x44, 0x7e, 0x5b, 0x70, 0x11, 0x76, 0x1a, 0x76, + 0xeb, 0x72, 0xc2, 0x4e, 0xeb, 0xb3, 0x0c, 0x8a, 0x6c, 0xf7, 0xba, 0x35, 0xd3, 0xfa, 0x6c, 0xaf, 0xc0, 0x47, 0x10, + 0x26, 0x65, 0x56, 0x3a, 0x83, 0x2b, 0xf4, 0xc3, 0x0f, 0xc8, 0xb5, 0xfe, 0x7a, 0xa1, 0x7d, 0x7e, 0x89, 0x08, 0x90, + 0x5d, 0x75, 0x5d, 0x56, 0x87, 0x3e, 0xca, 0x26, 0xbe, 0x1e, 0xf2, 0x60, 0xe5, 0x9e, 0xde, 0xce, 0x65, 0xea, 0xf1, + 0xb5, 0xd7, 0x4a, 0xb7, 0x90, 0x13, 0x88, 0x87, 0xeb, 0x2e, 0x2c, 0x0b, 0x72, 0x76, 0x73, 0x0b, 0x25, 0xc3, 0x89, + 0xfb, 0xd2, 0x1f, 0x98, 0xbd, 0x6e, 0xe0, 0x17, 0xc9, 0x29, 0x4c, 0x7d, 0xb3, 0x87, 0xc3, 0x0e, 0xf4, 0x61, 0xe0, + 0xb0, 0xd9, 0xa0, 0xcf, 0xac, 0x20, 0xf2, 0x98, 0x17, 0x16, 0xcf, 0x2e, 0x49, 0xbb, 0xc7, 0x53, 0xb7, 0x99, 0x8c, + 0x68, 0xd4, 0x6e, 0xf2, 0x60, 0x66, 0x80, 0x5f, 0xae, 0x6c, 0x58, 0xc4, 0xaf, 0x53, 0x00, 0x25, 0x5f, 0xac, 0x5a, + 0x9f, 0x0a, 0x5e, 0xf5, 0x86, 0xd3, 0xcd, 0x74, 0xbf, 0x6e, 0x70, 0xbb, 0xeb, 0xe1, 0x09, 0xaf, 0xb9, 0x58, 0xb4, + 0xf6, 0x13, 0x9f, 0x00, 0x07, 0x94, 0xb4, 0xee, 0x9f, 0x82, 0x0b, 0x65, 0x09, 0xcb, 0xed, 0x72, 0xb3, 0xad, 0x72, + 0x16, 0x8e, 0xb6, 0x64, 0xc0, 0x1d, 0x6c, 0x42, 0x14, 0x3a, 0x38, 0xec, 0xe0, 0xa4, 0xdd, 0xee, 0x9c, 0xe2, 0xe4, + 0xe4, 0x14, 0x06, 0xda, 0x48, 0x4e, 0x0f, 0x67, 0xca, 0x02, 0x30, 0xc8, 0x59, 0xbb, 0x76, 0x1f, 0x41, 0xe4, 0xa7, + 0x50, 0xbc, 0xe6, 0x87, 0x71, 0xdc, 0x4e, 0xee, 0xb7, 0xda, 0xa7, 0xe7, 0x0d, 0x00, 0x50, 0xd3, 0x7d, 0xb8, 0x1a, + 0xaf, 0x17, 0xba, 0x5e, 0xa5, 0x44, 0xf8, 0x7a, 0xb5, 0x86, 0xaf, 0xd6, 0x68, 0xaf, 0xab, 0x29, 0xf8, 0xaa, 0x4e, + 0x38, 0xb7, 0x45, 0xbc, 0xd2, 0x26, 0xdc, 0x16, 0xb1, 0x1d, 0x48, 0x0c, 0xd2, 0x79, 0x72, 0xda, 0x39, 0x45, 0x76, + 0x2c, 0xda, 0xe1, 0x47, 0xb9, 0x4f, 0xb6, 0x8a, 0x34, 0x34, 0x20, 0x49, 0x39, 0x3b, 0xb9, 0x00, 0x89, 0x9a, 0x93, + 0xcb, 0x76, 0x73, 0xc6, 0x12, 0x3f, 0x01, 0x93, 0x0a, 0xcb, 0x59, 0xae, 0x82, 0x4b, 0x0a, 0x00, 0x71, 0x01, 0xc6, + 0x45, 0xf7, 0x4f, 0x7b, 0xf7, 0x93, 0xd3, 0xb3, 0x8e, 0x25, 0x7a, 0xfc, 0xa2, 0x53, 0x4b, 0x33, 0x53, 0x4f, 0x4e, + 0x4d, 0x1a, 0x74, 0x9d, 0xdc, 0x3f, 0x85, 0x32, 0x2e, 0x25, 0x2c, 0x05, 0x11, 0x2b, 0xaa, 0x62, 0x10, 0xa6, 0x22, + 0xad, 0xe5, 0x9e, 0xd5, 0xb2, 0xcf, 0x4f, 0x8e, 0xef, 0x9f, 0x86, 0x50, 0x2b, 0x67, 0x61, 0x16, 0xda, 0x4d, 0xc4, + 0xcf, 0x0e, 0x96, 0x16, 0x1d, 0x26, 0xa7, 0xe9, 0xd6, 0x04, 0xed, 0xa6, 0x39, 0x34, 0x38, 0x10, 0x28, 0x1c, 0x9f, + 0x0a, 0xa7, 0x2f, 0x09, 0xee, 0xc7, 0x2a, 0x43, 0x93, 0x50, 0xe1, 0xec, 0xef, 0x29, 0x83, 0x47, 0x29, 0xc3, 0xab, + 0xca, 0xc7, 0x54, 0x7c, 0xa1, 0xea, 0x0d, 0x85, 0x30, 0x1c, 0x62, 0x10, 0xb9, 0x20, 0xe1, 0xf5, 0xdc, 0x9f, 0xc0, + 0x45, 0x98, 0x09, 0xb8, 0xd0, 0xf4, 0x4a, 0xd0, 0x8a, 0x17, 0x18, 0x86, 0x0e, 0xb5, 0x66, 0x58, 0x3d, 0x9e, 0x3a, + 0x93, 0x82, 0x50, 0xb7, 0xf5, 0x9c, 0x7f, 0xaf, 0x5c, 0x52, 0x5e, 0x65, 0x27, 0xa7, 0x28, 0x71, 0x97, 0xe5, 0x49, + 0x1b, 0x25, 0x81, 0x09, 0x89, 0x3b, 0x92, 0xb3, 0x8c, 0xf4, 0xa3, 0xdb, 0x08, 0x47, 0x77, 0x11, 0x8e, 0xac, 0x0f, + 0xf3, 0x07, 0x70, 0x10, 0x8f, 0x70, 0x64, 0x5d, 0x99, 0x23, 0x1c, 0x69, 0x26, 0x20, 0x3a, 0x57, 0x34, 0xc0, 0x39, + 0x94, 0x36, 0x9e, 0xd5, 0x65, 0xe9, 0xc7, 0xfe, 0xab, 0x74, 0xbd, 0xb6, 0x29, 0x81, 0x94, 0x39, 0x35, 0x3b, 0xd4, + 0xbe, 0x2e, 0x1d, 0x51, 0xcf, 0xac, 0x47, 0x18, 0x04, 0x10, 0x7a, 0xe7, 0x5f, 0xa7, 0xab, 0x02, 0x7b, 0xb0, 0x63, + 0x58, 0x69, 0xf0, 0x33, 0x8f, 0xc2, 0x33, 0x2c, 0xc2, 0x63, 0xe1, 0x0b, 0x83, 0x58, 0xe1, 0x7f, 0xe7, 0x52, 0xce, + 0xfd, 0x6f, 0x2d, 0xcb, 0x5f, 0xf0, 0xa6, 0x89, 0xb3, 0x68, 0x01, 0xcb, 0x2d, 0x1b, 0x47, 0x68, 0xc8, 0xea, 0x23, + 0xb8, 0x1e, 0xbb, 0x58, 0x6f, 0x20, 0x11, 0x5e, 0x1b, 0x81, 0xca, 0xcb, 0x87, 0xd7, 0x36, 0xee, 0x90, 0xf9, 0x84, + 0xc0, 0x63, 0x10, 0x5b, 0x58, 0xc2, 0x85, 0xc6, 0xa4, 0x60, 0x4a, 0x45, 0x36, 0x20, 0x5f, 0x24, 0x85, 0x7f, 0x61, + 0xd1, 0xa7, 0x8c, 0x45, 0x64, 0x3a, 0xac, 0xcf, 0xd6, 0x8a, 0xc3, 0xb9, 0x2c, 0x54, 0x6a, 0x9f, 0x5b, 0xf1, 0x60, + 0x9c, 0x97, 0x6f, 0x19, 0xa6, 0x79, 0xb6, 0xc6, 0xf6, 0x0e, 0xbb, 0x2c, 0xe4, 0xae, 0xb4, 0xc3, 0x52, 0x59, 0xb6, + 0xfe, 0xd6, 0x84, 0x54, 0x6d, 0x46, 0xc1, 0x44, 0xab, 0x01, 0x55, 0x51, 0x39, 0xa0, 0xb0, 0x8d, 0xec, 0x92, 0x2e, + 0xcb, 0x92, 0xe9, 0xb2, 0x5c, 0x86, 0x93, 0x56, 0x6b, 0xbd, 0xc6, 0x05, 0x33, 0x11, 0x66, 0x76, 0x96, 0x80, 0x7c, + 0x35, 0x95, 0x37, 0x41, 0xae, 0x4a, 0xcb, 0x59, 0x9a, 0x25, 0x8a, 0x02, 0x23, 0xd8, 0x68, 0x8d, 0xbf, 0x70, 0xc5, + 0x01, 0x9e, 0x6e, 0x76, 0x43, 0x29, 0x73, 0x46, 0x21, 0x10, 0x59, 0xd0, 0xe4, 0x1a, 0x4f, 0xf9, 0x88, 0xed, 0x6e, + 0x13, 0xcc, 0x98, 0xff, 0xbd, 0x16, 0x3d, 0x02, 0x59, 0x76, 0xcf, 0xa0, 0x0e, 0x2c, 0xe2, 0x0a, 0x3a, 0x08, 0x65, + 0xf0, 0x51, 0x88, 0x9b, 0x39, 0xbd, 0x93, 0x0b, 0x0d, 0x70, 0x59, 0x68, 0xf9, 0xc6, 0xc5, 0x3a, 0xd8, 0x6f, 0x61, + 0x1f, 0xf6, 0x60, 0x09, 0x21, 0x03, 0x5a, 0xd8, 0x86, 0xbb, 0x68, 0xe1, 0xa1, 0xd4, 0x5a, 0xce, 0xd2, 0x16, 0x36, + 0xb1, 0x27, 0x5a, 0xeb, 0x32, 0x40, 0xd8, 0x75, 0xf9, 0x2e, 0x65, 0xb5, 0x09, 0x16, 0x4e, 0x3a, 0xd4, 0x44, 0x07, + 0xb7, 0x87, 0x8c, 0xf0, 0xc6, 0xcf, 0x57, 0xaf, 0x5f, 0xb9, 0xf0, 0xcf, 0x7c, 0x0c, 0x2e, 0x9b, 0x4e, 0x35, 0x76, + 0x6d, 0x1e, 0x74, 0x8a, 0x2b, 0x45, 0xa9, 0x15, 0x4e, 0xa1, 0xe5, 0x17, 0x42, 0xe7, 0x89, 0xbd, 0xbc, 0x78, 0x26, + 0x8b, 0x19, 0xb5, 0x37, 0x46, 0xf8, 0x5a, 0xb9, 0x17, 0xdc, 0xcd, 0x23, 0x31, 0xd5, 0x24, 0xdf, 0x6d, 0x5e, 0x45, + 0x2c, 0x32, 0x23, 0xbf, 0x82, 0x36, 0xc0, 0x54, 0x2e, 0x1f, 0xe0, 0x2d, 0x88, 0x0b, 0xa2, 0x1f, 0x90, 0x97, 0xb7, + 0x96, 0xba, 0x44, 0x51, 0x83, 0x1b, 0xfc, 0x64, 0x05, 0xcf, 0x82, 0xeb, 0x42, 0xc3, 0x1e, 0x39, 0xf1, 0x22, 0x6a, + 0x45, 0xf5, 0x07, 0x6c, 0x8d, 0x2a, 0xc1, 0x07, 0x60, 0x4d, 0x72, 0x09, 0xa2, 0x47, 0xf9, 0x56, 0x1e, 0x07, 0xd1, + 0xc4, 0xdf, 0x3d, 0x5f, 0xb6, 0x3d, 0x9d, 0xcd, 0x2b, 0x75, 0x62, 0x79, 0x65, 0x02, 0x1e, 0x8e, 0xf6, 0x35, 0x1a, + 0x84, 0x83, 0x44, 0x56, 0x6a, 0x0f, 0x7d, 0x2e, 0xea, 0xc6, 0xf9, 0x45, 0x9b, 0x35, 0x4f, 0x56, 0xab, 0xfc, 0xb2, + 0xcd, 0xda, 0xa7, 0xf6, 0xed, 0xba, 0x48, 0x65, 0x40, 0x73, 0xf9, 0x98, 0x67, 0x11, 0x68, 0x67, 0xc7, 0x99, 0x09, + 0xa7, 0xe0, 0xa3, 0x2d, 0x93, 0x85, 0xae, 0xfa, 0x92, 0x60, 0x5c, 0x4a, 0xac, 0x1e, 0xbf, 0x40, 0xbd, 0x76, 0xba, + 0xed, 0x2a, 0xdd, 0x6c, 0x1f, 0x06, 0x17, 0x2e, 0x05, 0xc2, 0x1d, 0x08, 0x79, 0x00, 0xfa, 0xdd, 0xa5, 0x00, 0xd3, + 0x20, 0x40, 0x65, 0x05, 0x22, 0x2d, 0x9f, 0x2d, 0x66, 0xcf, 0x0a, 0x6a, 0x96, 0xe1, 0x09, 0x9f, 0x70, 0xad, 0x52, + 0x0a, 0xd2, 0xed, 0xae, 0xf4, 0xf5, 0x6e, 0x09, 0x2a, 0xab, 0x05, 0xb1, 0x4d, 0x34, 0xcf, 0x3e, 0x2b, 0xb7, 0x70, + 0x08, 0x9b, 0x95, 0x15, 0x38, 0x43, 0x6b, 0x9c, 0xcb, 0x09, 0x2d, 0xb8, 0x9e, 0xce, 0xfe, 0xad, 0xd5, 0x61, 0x7d, + 0x3d, 0x30, 0x17, 0x56, 0x00, 0x12, 0x2a, 0x46, 0xab, 0x15, 0x3f, 0xfa, 0xfe, 0x7d, 0x92, 0xf7, 0x09, 0x6f, 0xe3, + 0x0e, 0x3e, 0xc6, 0xa7, 0xb8, 0xdd, 0xc2, 0xed, 0x53, 0xb8, 0xba, 0xcf, 0xf2, 0xc5, 0x88, 0xa9, 0x18, 0x1e, 0x31, + 0xd3, 0x97, 0xc9, 0xf9, 0x61, 0x19, 0xba, 0x5f, 0x17, 0x89, 0x43, 0x97, 0x20, 0x82, 0xbc, 0x0b, 0xbd, 0x17, 0x45, + 0x61, 0xdc, 0xb7, 0x71, 0xa8, 0x3a, 0x29, 0xf5, 0x0b, 0x97, 0xc7, 0x3d, 0xb0, 0xe7, 0xb6, 0x2b, 0xdb, 0x04, 0xb3, + 0x6f, 0xfb, 0x33, 0xad, 0x7e, 0x36, 0x75, 0x89, 0x18, 0x1e, 0x7a, 0x15, 0x7a, 0xa0, 0x4b, 0xd2, 0x3e, 0x38, 0x00, + 0xab, 0xa3, 0x60, 0x36, 0xdc, 0x46, 0x3f, 0xe0, 0xcd, 0x5a, 0x1a, 0x04, 0x2b, 0x00, 0xe3, 0xce, 0x37, 0x9c, 0x2c, + 0x2d, 0x6c, 0x35, 0x50, 0x61, 0x5d, 0x84, 0xc1, 0xe9, 0x42, 0x52, 0x61, 0x84, 0x68, 0x38, 0xc2, 0x5c, 0xa4, 0x93, + 0xfd, 0x16, 0x96, 0xe3, 0xb1, 0x62, 0x1a, 0x8e, 0x8e, 0x82, 0x7d, 0x61, 0x85, 0x32, 0xa7, 0xc8, 0x90, 0x4d, 0xb8, + 0x78, 0xa8, 0x3f, 0xb1, 0x42, 0x9a, 0x4f, 0xa3, 0xc1, 0x48, 0x23, 0xb3, 0x8a, 0x11, 0xce, 0x72, 0x3e, 0x87, 0xaa, + 0x93, 0x02, 0x9c, 0x7e, 0xe0, 0x2f, 0x1f, 0xa5, 0x61, 0x9b, 0x40, 0xbe, 0x3e, 0xd8, 0x80, 0x2d, 0x78, 0x54, 0xd0, + 0x9b, 0xd7, 0xe2, 0x31, 0xec, 0xa8, 0x87, 0x05, 0xa3, 0x90, 0x0d, 0x49, 0xef, 0xa0, 0x29, 0xf8, 0x80, 0x36, 0x5f, + 0x1a, 0xc0, 0xa5, 0xe7, 0xe6, 0xc3, 0x56, 0xf4, 0x01, 0x10, 0x93, 0xb2, 0x2d, 0x93, 0x69, 0x4e, 0xe9, 0x2a, 0xd3, + 0x86, 0x98, 0x2a, 0xa7, 0xb0, 0xc6, 0x2e, 0xea, 0x49, 0x38, 0x98, 0x11, 0x55, 0xd3, 0xb4, 0x3f, 0x30, 0x7f, 0x5f, + 0xdb, 0x92, 0x2d, 0xec, 0xc2, 0xc9, 0xac, 0xb1, 0x79, 0x7d, 0x34, 0x28, 0xdf, 0xc6, 0x70, 0x0f, 0x0b, 0x4f, 0x60, + 0xd6, 0xc8, 0xe7, 0x89, 0x27, 0x9b, 0x27, 0xeb, 0xb5, 0x19, 0x88, 0x4a, 0x41, 0x0f, 0xf4, 0xd6, 0x6f, 0x9b, 0x16, + 0x6c, 0x8f, 0xf2, 0xeb, 0xb4, 0x85, 0x67, 0x1c, 0x5e, 0xf4, 0xf4, 0xed, 0x5d, 0xe9, 0x42, 0x7e, 0x76, 0x20, 0x69, + 0x05, 0x29, 0x76, 0x3a, 0x41, 0x67, 0xc7, 0x38, 0x18, 0x39, 0xd0, 0xf3, 0xab, 0xcf, 0x16, 0xd6, 0xfe, 0xf7, 0x9b, + 0xb2, 0xa0, 0x09, 0x96, 0x53, 0x4e, 0x28, 0xf3, 0xe7, 0xe7, 0x1b, 0x9e, 0x54, 0xa8, 0xe0, 0x9e, 0xc2, 0x82, 0x3d, + 0x6d, 0xa3, 0x65, 0xce, 0xe8, 0xdf, 0xf6, 0x87, 0x0d, 0xd0, 0x53, 0x6a, 0xd9, 0xb2, 0x42, 0x2a, 0xf5, 0xd0, 0xa6, + 0xd9, 0xa3, 0x07, 0x8e, 0xc8, 0x97, 0xd0, 0x05, 0xf0, 0xfa, 0xa3, 0x42, 0xce, 0x0d, 0x22, 0xb8, 0xdf, 0x6e, 0xdc, + 0xc6, 0x57, 0x00, 0xbc, 0x1d, 0xf6, 0xaa, 0x7f, 0x5a, 0xc0, 0xfe, 0x46, 0x65, 0x49, 0x3f, 0xde, 0x8e, 0x3d, 0xfe, + 0x0b, 0x09, 0xa1, 0xd7, 0x2d, 0x1e, 0x26, 0x0e, 0x9d, 0x4a, 0xd6, 0xac, 0xfc, 0xb9, 0x55, 0x12, 0x30, 0xac, 0x5e, + 0x30, 0x64, 0xe3, 0xb6, 0x8a, 0xdb, 0xcc, 0xff, 0xa0, 0x82, 0xc1, 0x82, 0x6f, 0x8d, 0xa4, 0x62, 0x59, 0xfc, 0xf6, + 0xa9, 0xf3, 0x5f, 0x75, 0x8e, 0x6b, 0x5f, 0xd7, 0x9e, 0xdb, 0x1c, 0x9a, 0x50, 0xc7, 0x11, 0x3a, 0x38, 0xd8, 0xc8, + 0xa0, 0x63, 0x00, 0x3c, 0x72, 0xec, 0x97, 0x5f, 0x3e, 0xcf, 0x8e, 0x19, 0xcd, 0x63, 0x11, 0x85, 0xcc, 0x9d, 0xe7, + 0xe6, 0xec, 0x44, 0x9e, 0x50, 0x35, 0xf5, 0x85, 0x01, 0x8e, 0x8f, 0xb6, 0x52, 0x01, 0xdf, 0xa3, 0xf5, 0x8e, 0x09, + 0x6c, 0xf0, 0x5b, 0x76, 0x52, 0xbb, 0x0a, 0xfa, 0x05, 0x5a, 0xee, 0x62, 0x2a, 0x37, 0x16, 0x38, 0xda, 0x9c, 0xc8, + 0xce, 0xa1, 0x6f, 0xd4, 0x29, 0x59, 0x8f, 0x27, 0xbb, 0x8d, 0xbe, 0xa4, 0xd8, 0x95, 0x5c, 0xd1, 0xb6, 0x21, 0xab, + 0x9e, 0xdc, 0xd5, 0x95, 0xa9, 0x53, 0x75, 0xcd, 0x5b, 0x59, 0xda, 0x94, 0x76, 0x49, 0xf6, 0x6e, 0x8b, 0x85, 0x57, + 0xe1, 0x8d, 0x46, 0x79, 0x11, 0x0a, 0xf6, 0x58, 0x62, 0xd0, 0xe5, 0x04, 0xae, 0x17, 0x56, 0xab, 0x18, 0xfe, 0xec, + 0x1a, 0xc3, 0x2e, 0xd3, 0xa5, 0x0f, 0x7c, 0x83, 0x5f, 0x09, 0xa2, 0xfe, 0x3a, 0x3b, 0x48, 0xb0, 0xee, 0x72, 0x83, + 0x86, 0xe3, 0xc4, 0x7f, 0xc1, 0x9b, 0xd3, 0xda, 0xbb, 0x1c, 0x4c, 0xb2, 0x6f, 0xbc, 0x53, 0x57, 0xb2, 0x96, 0xb5, + 0x90, 0xf1, 0x1b, 0x12, 0x0c, 0xb1, 0x9b, 0xd2, 0x39, 0x6e, 0x25, 0x6d, 0x14, 0xb9, 0x62, 0x15, 0xfa, 0x7f, 0xab, + 0x48, 0x66, 0x33, 0xff, 0xeb, 0xec, 0xec, 0xcc, 0xa5, 0x38, 0x9b, 0x3f, 0x65, 0x3c, 0xe0, 0x4c, 0x02, 0xfb, 0xc2, + 0x33, 0x66, 0x74, 0xc8, 0x6f, 0x61, 0x28, 0x44, 0x90, 0x4b, 0xe1, 0xd8, 0x25, 0x78, 0x32, 0x11, 0x28, 0x0f, 0xb0, + 0x7f, 0x4f, 0x36, 0xca, 0xf9, 0x37, 0x97, 0x7c, 0x4c, 0xe2, 0xb2, 0x41, 0xf6, 0xc5, 0x7c, 0xf6, 0xad, 0x99, 0x0c, + 0x3c, 0x33, 0x10, 0x61, 0xfb, 0xdb, 0xb0, 0xb4, 0xce, 0x52, 0x06, 0x47, 0x5a, 0x2e, 0xb2, 0xa9, 0xd5, 0xfc, 0xbb, + 0x0f, 0x53, 0xd6, 0xbd, 0xd7, 0x03, 0x41, 0xb9, 0xc8, 0xd2, 0x85, 0xd6, 0x8c, 0x7e, 0x2c, 0xa3, 0x68, 0xee, 0xbd, + 0x62, 0x0b, 0xf6, 0x23, 0xde, 0xab, 0x52, 0xe0, 0xe3, 0x61, 0xc1, 0x69, 0xfe, 0x23, 0xde, 0xab, 0xa2, 0x69, 0x82, + 0x2b, 0xa4, 0x09, 0x48, 0x89, 0xcd, 0xdb, 0xd4, 0x69, 0x24, 0x80, 0x82, 0xe6, 0x91, 0x39, 0xc8, 0x9e, 0xbb, 0x00, + 0x8c, 0x49, 0x07, 0xbb, 0xb8, 0x5f, 0x36, 0xac, 0xaa, 0x8d, 0x46, 0x0e, 0x41, 0xe9, 0xca, 0xd9, 0x98, 0xaf, 0x47, + 0x1b, 0x0b, 0x62, 0x94, 0xc9, 0xe4, 0xf2, 0x39, 0x8f, 0xb7, 0x16, 0x0b, 0x85, 0xd5, 0x82, 0x05, 0xaa, 0x55, 0xa9, + 0xd2, 0xc3, 0xe2, 0xdb, 0x05, 0xb3, 0xa0, 0x88, 0xd9, 0x7a, 0x0f, 0x6f, 0xb9, 0x22, 0x20, 0x25, 0xbb, 0x24, 0x78, + 0x5e, 0xdc, 0x60, 0xaa, 0x7f, 0x4d, 0x1e, 0x08, 0x3d, 0x53, 0x3a, 0xc2, 0x26, 0x4f, 0x41, 0x24, 0xb1, 0xfd, 0x16, + 0x76, 0xac, 0xd1, 0x0b, 0xe1, 0x85, 0x14, 0x38, 0x57, 0x4d, 0x13, 0x33, 0xca, 0x4d, 0x74, 0xb1, 0x87, 0x6a, 0xce, + 0x32, 0x6d, 0x11, 0x60, 0xdf, 0xa1, 0xa1, 0x14, 0xcf, 0x0d, 0x28, 0xcc, 0xbb, 0xd8, 0x2e, 0xe5, 0x31, 0x2c, 0x5e, + 0x90, 0x02, 0x44, 0x8d, 0x8b, 0x49, 0x59, 0x67, 0x9e, 0x2f, 0x26, 0x5c, 0x54, 0xc8, 0x50, 0x30, 0x35, 0x97, 0x02, + 0x9e, 0xa5, 0x28, 0x8b, 0x18, 0x3a, 0x54, 0xc3, 0x77, 0x4b, 0xc2, 0xca, 0x3a, 0xe6, 0x98, 0xe2, 0xa2, 0xaa, 0x01, + 0xcc, 0xc5, 0xc3, 0xf0, 0xfd, 0x7a, 0xf5, 0x5a, 0xbc, 0x93, 0xf3, 0x2a, 0xdf, 0xd3, 0x38, 0x1f, 0xfd, 0xdd, 0xd9, + 0x0d, 0xa3, 0xb5, 0x79, 0x39, 0x2a, 0xd8, 0xbe, 0x1f, 0x78, 0xf5, 0x9a, 0xda, 0xda, 0xbc, 0x3d, 0x55, 0x66, 0x0d, + 0x59, 0xf9, 0xd0, 0x42, 0xd5, 0x5e, 0xbd, 0xaa, 0x14, 0xb6, 0x22, 0x40, 0xa5, 0xe0, 0xa3, 0xad, 0xfc, 0x27, 0xda, + 0xe6, 0xdb, 0x73, 0xa8, 0x0c, 0x0f, 0xe4, 0xc9, 0x50, 0xd5, 0x03, 0x2e, 0xca, 0x0f, 0x01, 0x2c, 0x7e, 0x64, 0x82, + 0xf0, 0xee, 0xba, 0x40, 0xe6, 0x4c, 0xc5, 0x12, 0x2f, 0xfb, 0x74, 0x90, 0x5a, 0x79, 0x28, 0x95, 0x60, 0xdb, 0x73, + 0x53, 0x70, 0xed, 0xa3, 0xfd, 0xe2, 0x3e, 0x1b, 0xa4, 0xcb, 0x7a, 0x44, 0x60, 0x1b, 0x93, 0xd8, 0x9b, 0x73, 0x9a, + 0x10, 0xba, 0x74, 0x80, 0x73, 0x02, 0xb6, 0xc7, 0x9e, 0x3d, 0x7d, 0x13, 0x67, 0xa8, 0x57, 0xe7, 0xf0, 0x97, 0x6b, + 0x9c, 0xe3, 0x0c, 0xa5, 0x0f, 0x63, 0xb8, 0xc0, 0x5a, 0x63, 0x00, 0x5f, 0x66, 0x49, 0x15, 0x78, 0xa4, 0x66, 0x46, + 0x62, 0x75, 0x17, 0x81, 0x68, 0xa9, 0xc3, 0xdb, 0x71, 0xe6, 0x63, 0x6a, 0x1b, 0xee, 0xf5, 0x99, 0x11, 0x0e, 0x27, + 0x59, 0x5c, 0x3b, 0x67, 0x38, 0xb9, 0xdc, 0xe7, 0xb5, 0x13, 0x13, 0xac, 0xbd, 0xc3, 0x53, 0x05, 0xf4, 0x68, 0x70, + 0xaa, 0x58, 0x1a, 0x02, 0x31, 0x13, 0xc0, 0x9b, 0x39, 0x3c, 0xda, 0x02, 0x9c, 0x8f, 0xd6, 0x38, 0xf8, 0x4a, 0x6b, + 0x5d, 0x6d, 0x2a, 0x51, 0xd6, 0x6b, 0xdc, 0x9f, 0x66, 0x78, 0x94, 0xe1, 0x79, 0x36, 0x08, 0x8e, 0x9b, 0x59, 0x16, + 0x9a, 0x74, 0xad, 0x56, 0x4f, 0x9d, 0x19, 0x21, 0xb2, 0x3f, 0x2d, 0xfd, 0x41, 0x3d, 0x40, 0xf8, 0x14, 0xb2, 0x80, + 0x96, 0xf4, 0xdc, 0xdf, 0x86, 0x7d, 0x72, 0x1b, 0x35, 0x62, 0x9e, 0x58, 0x32, 0xd2, 0xf3, 0x3f, 0xca, 0x2c, 0xdb, + 0x5a, 0x23, 0x9a, 0xdf, 0xee, 0x45, 0x0d, 0xdf, 0x5e, 0xa0, 0x65, 0x2b, 0xcd, 0x76, 0x00, 0x51, 0xac, 0x71, 0x92, + 0x0e, 0xd6, 0x48, 0xae, 0x56, 0xb1, 0x4d, 0x21, 0x3c, 0x99, 0x31, 0xaa, 0x16, 0x85, 0x79, 0x85, 0x2e, 0x56, 0x28, + 0x31, 0xfc, 0x2e, 0x76, 0x36, 0xa2, 0xf0, 0xe8, 0x9b, 0x04, 0xc3, 0x8d, 0x58, 0x10, 0x59, 0x13, 0xb9, 0x87, 0x59, + 0x65, 0x19, 0x24, 0x88, 0x30, 0x22, 0xbf, 0xbd, 0x2e, 0x15, 0xf6, 0x9d, 0x3b, 0xfb, 0xc7, 0xf8, 0x02, 0xc2, 0xcd, + 0xdb, 0x84, 0x16, 0x43, 0x3a, 0x01, 0x36, 0x16, 0xe2, 0x10, 0x6e, 0x25, 0xac, 0x56, 0xfd, 0x41, 0x57, 0x18, 0xf2, + 0xec, 0x5e, 0xe1, 0x2b, 0x1b, 0xda, 0xdd, 0x00, 0x5c, 0x75, 0x5b, 0x6a, 0xae, 0x8d, 0xee, 0x87, 0x9a, 0x87, 0xc2, + 0xb8, 0x4b, 0x72, 0x6f, 0x7d, 0x54, 0xcf, 0x79, 0xd7, 0x2c, 0xc0, 0x4d, 0xe8, 0x2a, 0x3c, 0xc2, 0x0b, 0x6b, 0xc3, + 0x69, 0x5e, 0x85, 0xa2, 0xe6, 0x31, 0x28, 0x78, 0x83, 0x9a, 0xb0, 0x7e, 0x36, 0xc0, 0x23, 0x1f, 0x33, 0x7c, 0xff, + 0x6d, 0x3c, 0x42, 0xa8, 0x20, 0x06, 0xa6, 0xd6, 0x65, 0x7b, 0x54, 0xd9, 0xed, 0x9b, 0x4c, 0xc3, 0x30, 0x18, 0x23, + 0xe6, 0x51, 0x68, 0xc4, 0x9c, 0x37, 0x1a, 0x68, 0x41, 0x46, 0x60, 0xc4, 0xbc, 0x08, 0x5a, 0x5b, 0xd8, 0x17, 0x43, + 0x83, 0xf6, 0x16, 0x08, 0x75, 0x39, 0xd0, 0x34, 0x0d, 0x6f, 0x83, 0x54, 0x6f, 0xb3, 0xfb, 0x97, 0xaa, 0x8e, 0x3a, + 0xa0, 0x48, 0x18, 0x5f, 0xfa, 0x49, 0x58, 0xd7, 0x70, 0x3b, 0xee, 0xb1, 0x19, 0xb7, 0xb3, 0x6d, 0x50, 0x7d, 0xd9, + 0xcf, 0x06, 0x83, 0xae, 0xf4, 0x56, 0x12, 0x2d, 0x3c, 0xae, 0x5e, 0x13, 0xa9, 0x16, 0xef, 0x8b, 0xde, 0xbc, 0xf2, + 0xe6, 0xfe, 0x91, 0xd2, 0xcd, 0xf3, 0x18, 0x38, 0xa0, 0x7d, 0xb8, 0x1f, 0xaa, 0xe2, 0x83, 0x1d, 0x75, 0x20, 0x0a, + 0x5a, 0xda, 0xaa, 0x09, 0xa4, 0xd6, 0xcc, 0x2e, 0xd6, 0x4d, 0x85, 0x0e, 0x05, 0x84, 0x21, 0x53, 0x55, 0x77, 0x77, + 0x2a, 0x50, 0x0d, 0x71, 0x38, 0xf5, 0x1f, 0x5b, 0x23, 0xd6, 0x38, 0xea, 0x8c, 0x22, 0x63, 0x24, 0x69, 0x97, 0x0f, + 0x1e, 0x10, 0x02, 0x2b, 0x01, 0x1f, 0xc8, 0xd9, 0x24, 0x19, 0x43, 0x82, 0xb7, 0x2c, 0xd3, 0x86, 0x0f, 0xe1, 0x0e, + 0x41, 0x79, 0x62, 0x63, 0x6d, 0xba, 0x4a, 0x16, 0x72, 0x55, 0x97, 0xd7, 0x01, 0x7a, 0xde, 0x95, 0xbf, 0xb1, 0xe1, + 0xc8, 0x82, 0x81, 0x65, 0x5b, 0xfb, 0x04, 0x3c, 0xf2, 0x71, 0x85, 0x20, 0x7e, 0x29, 0x74, 0x62, 0x82, 0x5e, 0x5f, + 0xc1, 0x06, 0xc5, 0x73, 0x70, 0x10, 0x74, 0x12, 0x1c, 0x06, 0xef, 0x32, 0xab, 0x49, 0x36, 0xb8, 0x35, 0x23, 0xf1, + 0x7c, 0xb5, 0x6a, 0xa1, 0xc3, 0x7f, 0xcc, 0xbb, 0xce, 0xe3, 0x52, 0xe1, 0x3e, 0xae, 0x14, 0xee, 0x60, 0x09, 0x48, + 0xc6, 0x81, 0xae, 0x1d, 0xcb, 0x50, 0x8d, 0x0e, 0x21, 0xc7, 0x5f, 0x40, 0x00, 0x6a, 0x77, 0x2c, 0x81, 0x9e, 0x7d, + 0xab, 0x80, 0xd5, 0xb5, 0x97, 0x25, 0x90, 0x11, 0xdc, 0xfd, 0x26, 0x30, 0x2a, 0x44, 0xe3, 0xf3, 0x67, 0x9e, 0x86, + 0xe0, 0x89, 0xf3, 0xe7, 0x9a, 0x19, 0xd6, 0xbd, 0xa0, 0x37, 0xa6, 0xf9, 0x78, 0x8c, 0x9b, 0x63, 0x0b, 0xce, 0xa3, + 0x0e, 0xfc, 0xb4, 0x10, 0x3d, 0xea, 0x60, 0x97, 0x8a, 0xc7, 0x25, 0x90, 0x43, 0xf4, 0x74, 0x06, 0x52, 0xc0, 0x4a, + 0xc7, 0x56, 0x8b, 0x34, 0x41, 0xab, 0xd5, 0xe4, 0x82, 0xb4, 0x10, 0x5a, 0xaa, 0x1b, 0xae, 0xb3, 0x29, 0xf8, 0x48, + 0x83, 0x62, 0xe0, 0x0d, 0xd5, 0xd3, 0x18, 0xe1, 0x31, 0x5a, 0x8e, 0xd8, 0x98, 0x2e, 0x72, 0x9d, 0xaa, 0x1e, 0x4f, + 0x6c, 0x54, 0x5e, 0x66, 0x23, 0xc1, 0x1d, 0x75, 0xf0, 0xc4, 0xf0, 0x97, 0x8f, 0x8c, 0x39, 0x48, 0x91, 0x99, 0xe4, + 0x89, 0x49, 0xc0, 0x3c, 0xc9, 0x72, 0xa9, 0x98, 0x6d, 0xa6, 0x6b, 0x6d, 0xcb, 0x21, 0xae, 0x77, 0xa4, 0x0b, 0x6e, + 0xac, 0x28, 0xa3, 0x74, 0x4a, 0x54, 0x4f, 0x1d, 0x75, 0xd2, 0x09, 0xe6, 0x09, 0x70, 0x7a, 0xef, 0x64, 0xcc, 0x1a, + 0xe5, 0xad, 0xe8, 0x0c, 0x1d, 0x4e, 0xb1, 0xa8, 0x2e, 0x51, 0x67, 0xe8, 0x70, 0x82, 0xf0, 0xac, 0x41, 0x72, 0x05, + 0x1e, 0xc3, 0x5c, 0xfc, 0x1f, 0x29, 0xff, 0xcd, 0x61, 0x43, 0xfc, 0xe8, 0xb7, 0xb0, 0x53, 0xd8, 0x28, 0x4a, 0x73, + 0x02, 0x5e, 0x8b, 0xed, 0x33, 0x9c, 0x91, 0x49, 0x33, 0xf7, 0x01, 0xf7, 0x4c, 0x2b, 0x8d, 0x5b, 0x8d, 0x0e, 0x33, + 0x3c, 0xda, 0x4c, 0x8a, 0xcd, 0x5c, 0x9b, 0x79, 0x9a, 0xc1, 0xf9, 0x5e, 0x8d, 0xc2, 0x95, 0x5f, 0x6c, 0x26, 0x85, + 0xe5, 0x1d, 0x70, 0x9b, 0x23, 0x2c, 0x9a, 0x14, 0xe7, 0x78, 0xd6, 0xfc, 0x8a, 0x67, 0xcd, 0x0f, 0x65, 0x46, 0x63, + 0x81, 0x05, 0x04, 0xef, 0x83, 0x44, 0x3c, 0xab, 0x92, 0x47, 0x58, 0x34, 0x4c, 0x79, 0x3c, 0x6b, 0x54, 0xa5, 0x9b, + 0x0b, 0x2c, 0x1a, 0xa6, 0x74, 0xe3, 0x03, 0x9e, 0x35, 0xbe, 0xfe, 0x8b, 0x49, 0x47, 0x29, 0xa0, 0xcb, 0x1c, 0x2d, + 0x33, 0x3b, 0xc4, 0xab, 0xdf, 0xde, 0xbe, 0x6b, 0x5f, 0x77, 0x0e, 0x27, 0xd8, 0xaf, 0x5f, 0x66, 0x70, 0x2c, 0xd3, + 0x31, 0x6b, 0x02, 0x44, 0x33, 0xdc, 0x39, 0x9c, 0xe2, 0xce, 0x61, 0xe6, 0x9a, 0x5a, 0xcf, 0x1a, 0xe4, 0x56, 0x87, + 0x50, 0xd4, 0x51, 0x1a, 0xc2, 0xc7, 0x4f, 0x36, 0x9d, 0xa0, 0x1a, 0x28, 0xd1, 0xe1, 0xa4, 0x06, 0x2a, 0xf8, 0x5e, + 0xd4, 0xbe, 0xab, 0x7a, 0x15, 0x06, 0x59, 0x28, 0xa1, 0x70, 0xcd, 0x0d, 0x78, 0x6a, 0x29, 0x06, 0x32, 0x61, 0x8a, + 0x05, 0xca, 0x77, 0x40, 0x61, 0x94, 0x27, 0x66, 0xe8, 0xc1, 0x74, 0x4c, 0xe2, 0xff, 0xcf, 0x93, 0x29, 0x87, 0x5e, + 0x6e, 0x99, 0xad, 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, 0x3f, 0xac, 0xa0, 0xfb, 0x62, 0xab, 0xfb, 0xc2, + 0x74, 0x1f, 0x36, 0x6d, 0x54, 0x39, 0x69, 0x55, 0xc9, 0x92, 0xff, 0x3a, 0xdd, 0xda, 0x02, 0x8d, 0xa8, 0xd1, 0xb3, + 0x49, 0xd8, 0xe0, 0x7e, 0x3b, 0xdd, 0x81, 0xcc, 0x6b, 0x6e, 0x9f, 0x19, 0x85, 0xc3, 0x37, 0xb8, 0x53, 0xbd, 0x6c, + 0x81, 0xf7, 0xa6, 0x32, 0xfa, 0xca, 0x38, 0xb4, 0x1c, 0x2c, 0x36, 0x4d, 0xb9, 0x8d, 0xb1, 0x74, 0x72, 0x8a, 0x8d, + 0x2b, 0x22, 0x54, 0xba, 0xbd, 0x04, 0xa5, 0xf8, 0x58, 0x37, 0x99, 0xf9, 0xba, 0xd0, 0x89, 0xb9, 0x84, 0x6a, 0x98, + 0xcf, 0xbb, 0x4b, 0x9d, 0x68, 0x39, 0xb7, 0x79, 0x77, 0x17, 0xd0, 0x27, 0x68, 0x58, 0x1b, 0x81, 0xdd, 0x3e, 0x2b, + 0x9c, 0x7e, 0xa7, 0x3a, 0x04, 0xc3, 0x03, 0xc8, 0x91, 0x16, 0xdb, 0x07, 0x36, 0xad, 0x61, 0xd7, 0x45, 0xb3, 0x4c, + 0xb4, 0xad, 0x36, 0x4d, 0xae, 0xdd, 0xc3, 0x7c, 0x1e, 0xf2, 0x14, 0xbc, 0xb0, 0xfa, 0xf1, 0x1d, 0xec, 0xc6, 0x6d, + 0x8d, 0x91, 0xa8, 0x2b, 0x99, 0x4a, 0xe8, 0x27, 0xb7, 0x98, 0x25, 0x77, 0xc6, 0x8b, 0x51, 0x19, 0x7f, 0x1f, 0x13, + 0x74, 0x3f, 0xaa, 0x24, 0x39, 0xb0, 0xec, 0x6f, 0xb0, 0xe4, 0x16, 0xcc, 0x13, 0xcb, 0x6a, 0x12, 0xeb, 0xe4, 0x2e, + 0x58, 0x44, 0x69, 0x1a, 0x59, 0x1b, 0x06, 0xd4, 0x34, 0x63, 0xd5, 0x83, 0xfb, 0x10, 0xe8, 0xa1, 0x57, 0x96, 0xd2, + 0xae, 0xb3, 0xb4, 0xd6, 0xbd, 0x36, 0xdd, 0x6f, 0x0e, 0x28, 0xe0, 0x0b, 0x03, 0xae, 0xe9, 0x5f, 0x4d, 0x22, 0x19, + 0xb2, 0xaf, 0x9c, 0x15, 0x8f, 0x17, 0x85, 0xc1, 0x34, 0xd1, 0xd3, 0x49, 0x36, 0x6f, 0x83, 0xa9, 0x5e, 0x36, 0xef, + 0xdc, 0x62, 0xf7, 0x7d, 0x67, 0xbf, 0xef, 0xb0, 0xe8, 0x31, 0x93, 0x91, 0x32, 0x53, 0xcc, 0x7f, 0xdf, 0xd9, 0xef, + 0x3b, 0xbc, 0x3d, 0x98, 0x1b, 0x7f, 0xa1, 0x58, 0xb2, 0x33, 0x5c, 0x82, 0x09, 0x79, 0xc0, 0xdd, 0xd4, 0xb2, 0x4c, + 0x10, 0xd8, 0x5a, 0x02, 0xc4, 0xf9, 0x7c, 0x1a, 0x57, 0xbc, 0x1a, 0x02, 0xee, 0xd3, 0xbb, 0xb6, 0x57, 0xa9, 0xc0, + 0x63, 0x82, 0x46, 0xc4, 0xc4, 0xb6, 0x31, 0x4f, 0x84, 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, 0x79, 0x13, 0x79, 0xec, 0x63, 0xb9, 0x9f, 0x99, 0x9e, 0x16, 0x72, 0x31, 0x99, 0x82, 0x0f, + 0x2d, 0xb0, 0x0c, 0x85, 0xa9, 0x57, 0xd9, 0xfa, 0xd7, 0x24, 0x37, 0x01, 0x14, 0x4e, 0x37, 0x65, 0x42, 0x33, 0xbd, + 0xa0, 0xb9, 0xb1, 0x24, 0xe5, 0x62, 0xf2, 0x48, 0xde, 0xbe, 0x04, 0xec, 0xa6, 0x44, 0x37, 0x76, 0xe4, 0xbd, 0x85, + 0x1d, 0x80, 0x33, 0xc2, 0x76, 0x55, 0x7c, 0xa8, 0x40, 0xe7, 0x8f, 0x73, 0xc2, 0x76, 0x55, 0x7d, 0xc2, 0x6c, 0xf6, + 0x94, 0x6c, 0x0c, 0xb7, 0x17, 0x67, 0x8d, 0x1c, 0x1d, 0x75, 0xd2, 0xbc, 0xeb, 0x89, 0x81, 0x05, 0x68, 0x00, 0xdc, + 0xad, 0xed, 0x59, 0xde, 0xdd, 0x10, 0xd0, 0xbb, 0x64, 0xd2, 0x5e, 0x97, 0x9b, 0x94, 0xd5, 0xaa, 0x53, 0x51, 0xc1, + 0x02, 0x4f, 0x83, 0xbd, 0x40, 0xed, 0xd7, 0x0e, 0x8a, 0x73, 0x95, 0x6d, 0x9a, 0x9e, 0x97, 0x7d, 0x77, 0x77, 0x2c, + 0x32, 0xb6, 0x69, 0x6f, 0x77, 0x10, 0x09, 0xcb, 0x09, 0xeb, 0x80, 0x13, 0xae, 0x6a, 0x07, 0x04, 0xe8, 0x3a, 0x10, + 0xb9, 0xb1, 0x24, 0xcb, 0x75, 0x65, 0x74, 0x1f, 0xf8, 0xdd, 0x52, 0x22, 0xdd, 0x68, 0x4b, 0x82, 0xe9, 0x13, 0x8c, + 0x9a, 0xce, 0xbc, 0xef, 0x5c, 0x7b, 0xba, 0x78, 0x53, 0xb4, 0xf5, 0x0f, 0x29, 0x63, 0xb3, 0x3d, 0x4c, 0x0c, 0x65, + 0x10, 0x03, 0xbd, 0x8f, 0x78, 0xb7, 0xd1, 0xc8, 0x10, 0x28, 0x64, 0xb2, 0x01, 0x96, 0x89, 0xd7, 0xa2, 0x1f, 0x1c, + 0x18, 0x78, 0x54, 0x09, 0x08, 0x53, 0x10, 0x42, 0xc2, 0xae, 0x0d, 0xc2, 0x86, 0xcb, 0x55, 0xcb, 0x85, 0x8d, 0x54, + 0x1b, 0x3a, 0xf8, 0x7f, 0x85, 0xcb, 0x56, 0xcf, 0x2c, 0x17, 0xc5, 0xe0, 0x66, 0x6e, 0xc0, 0x22, 0x41, 0x7a, 0xb4, + 0xd9, 0x1e, 0x8a, 0xbb, 0x73, 0xb1, 0xd9, 0x10, 0x90, 0x98, 0xc3, 0x04, 0x45, 0xc3, 0xb9, 0x31, 0xc6, 0x2a, 0xa9, + 0xb4, 0xac, 0x35, 0x89, 0x39, 0xf0, 0xa5, 0x0b, 0xd7, 0x7d, 0x79, 0x9b, 0x32, 0x7c, 0x97, 0x0a, 0x7c, 0x03, 0x9e, + 0x34, 0xa9, 0xc4, 0xee, 0xf1, 0x82, 0x62, 0x4d, 0x74, 0xd7, 0xb3, 0xb7, 0x05, 0xac, 0xb3, 0xd9, 0x23, 0x22, 0xf8, + 0x5d, 0xfd, 0x6a, 0x83, 0xef, 0x16, 0xfe, 0x0a, 0xd6, 0xcf, 0xc1, 0x49, 0x8a, 0x45, 0x43, 0x36, 0x0b, 0x77, 0x64, + 0x40, 0xb9, 0x8a, 0x5f, 0x0e, 0x53, 0xb7, 0x8a, 0xe1, 0xda, 0xc7, 0x57, 0xfc, 0x61, 0xa3, 0xdd, 0x86, 0x2a, 0x8b, + 0xdb, 0xbd, 0x29, 0x1a, 0xb2, 0x6a, 0x7a, 0x47, 0xe6, 0x46, 0x4a, 0xfd, 0xeb, 0x03, 0x6e, 0x6d, 0xb5, 0xef, 0xa7, + 0xf9, 0xd6, 0xa3, 0x73, 0xd5, 0xb4, 0x4f, 0xad, 0x15, 0xc1, 0xc1, 0xcf, 0x16, 0x6e, 0x6e, 0x0d, 0x38, 0x80, 0x9f, + 0xbf, 0xa3, 0x79, 0x9c, 0x41, 0x74, 0x7a, 0xab, 0x19, 0x5f, 0xc5, 0x7f, 0x8e, 0x1a, 0x71, 0x2f, 0xfd, 0x33, 0xf9, + 0x73, 0xd4, 0x40, 0x3d, 0x14, 0xcf, 0x6f, 0x57, 0x6c, 0xb6, 0x82, 0x60, 0x6b, 0xf7, 0x8e, 0xf0, 0xeb, 0xb0, 0x24, + 0xd7, 0x34, 0xe7, 0xd9, 0xca, 0xbd, 0xaa, 0xb7, 0x72, 0x4f, 0x0e, 0xad, 0xcc, 0x43, 0x51, 0xab, 0x58, 0x0e, 0x73, + 0x08, 0x2c, 0x1c, 0xef, 0x35, 0x7b, 0xfd, 0x56, 0xf3, 0xc1, 0xc0, 0xfe, 0x6b, 0x22, 0xdc, 0xa3, 0x5a, 0xc4, 0xb6, + 0x37, 0x1b, 0x5b, 0x3f, 0x06, 0xc3, 0x0e, 0x08, 0x05, 0x0e, 0x72, 0xe9, 0xe3, 0x0c, 0x59, 0xdf, 0x93, 0xd5, 0x8a, + 0xb9, 0x68, 0xd6, 0x4e, 0x83, 0x5f, 0xc6, 0x66, 0x3a, 0x6c, 0x27, 0x9d, 0xae, 0x17, 0x63, 0x49, 0x03, 0x22, 0x4d, + 0x63, 0x06, 0x81, 0xa4, 0x96, 0x86, 0xc3, 0x9a, 0xdf, 0x46, 0x69, 0x75, 0x7f, 0x04, 0x29, 0x3f, 0x44, 0x29, 0x3f, + 0x22, 0x10, 0x40, 0xdb, 0x32, 0x47, 0x65, 0x43, 0xde, 0x77, 0xe9, 0x9e, 0x71, 0x66, 0x68, 0xf0, 0xd5, 0xaa, 0x55, + 0x0d, 0x53, 0x14, 0xf5, 0x61, 0x2e, 0xd7, 0x58, 0x90, 0x37, 0xa0, 0x6b, 0x56, 0x44, 0xf4, 0x42, 0x57, 0x79, 0x78, + 0x54, 0x18, 0x4b, 0x02, 0x4e, 0xfa, 0x3d, 0xd1, 0x2b, 0xc8, 0xe5, 0xc3, 0x18, 0x7c, 0xcc, 0x30, 0xef, 0xeb, 0x7e, + 0x31, 0x18, 0xa0, 0xd4, 0x39, 0x9d, 0xa5, 0x26, 0xe2, 0x4a, 0xe0, 0x97, 0x5c, 0x80, 0x5f, 0xb2, 0x42, 0xac, 0x5f, + 0x0c, 0xc8, 0xbd, 0x2c, 0x96, 0xe0, 0x94, 0xbf, 0xc3, 0xe7, 0xf1, 0x61, 0x68, 0x60, 0x6a, 0x86, 0x65, 0x2e, 0xb2, + 0xc1, 0x62, 0xce, 0x5a, 0x02, 0xc1, 0xcd, 0x80, 0xbb, 0xd4, 0x86, 0x44, 0x63, 0x0d, 0x14, 0xdd, 0x46, 0xa1, 0x99, + 0xd1, 0xd3, 0xad, 0x36, 0xfa, 0x91, 0xc3, 0x0b, 0x73, 0x0d, 0x63, 0x11, 0xc8, 0x5c, 0xae, 0x7a, 0xec, 0x2f, 0x3f, + 0x6c, 0x56, 0x18, 0xbc, 0xc2, 0x98, 0xec, 0x94, 0x56, 0x89, 0x66, 0x7c, 0x95, 0x27, 0x8e, 0x21, 0xc8, 0xc4, 0x52, + 0xe9, 0x86, 0x63, 0xe2, 0x4a, 0xfa, 0x4c, 0x0c, 0xd9, 0x6e, 0x78, 0x66, 0x2e, 0x74, 0xb3, 0xfd, 0xc3, 0xb9, 0x9d, + 0x73, 0xc2, 0x8d, 0x56, 0xd2, 0x68, 0xa3, 0x9e, 0x19, 0xaa, 0xea, 0x82, 0xf9, 0x3d, 0x74, 0x5a, 0x5a, 0xec, 0x5c, + 0xbd, 0xbb, 0xe1, 0x13, 0x77, 0x65, 0xfc, 0x2d, 0x56, 0x85, 0x56, 0x64, 0xb8, 0xdd, 0x42, 0xde, 0x9c, 0xe9, 0xa1, + 0x57, 0xe4, 0x42, 0x75, 0xf8, 0x8b, 0xba, 0xc2, 0xbc, 0x7a, 0x19, 0x35, 0x84, 0x47, 0xbf, 0xd7, 0x19, 0x28, 0xff, + 0x60, 0x62, 0x32, 0x67, 0xc9, 0x0d, 0x2d, 0x44, 0xfc, 0xe3, 0x0b, 0x61, 0x62, 0x55, 0xed, 0xc1, 0x40, 0xf6, 0x4c, + 0xc5, 0x3d, 0xb8, 0x35, 0xe1, 0x63, 0xce, 0x46, 0xe9, 0x5e, 0xf4, 0x63, 0x43, 0x34, 0x7e, 0x8c, 0x7e, 0x04, 0x77, + 0x67, 0xf7, 0xc4, 0x62, 0x19, 0x17, 0xc2, 0xdf, 0x63, 0x3d, 0x2c, 0x55, 0xca, 0x58, 0x7b, 0xdd, 0x72, 0x78, 0x21, + 0xf5, 0x26, 0x8b, 0x1f, 0x3a, 0x62, 0x6d, 0x53, 0xb0, 0x0e, 0x29, 0x29, 0x3c, 0xbb, 0x62, 0x6e, 0xb5, 0x98, 0xbb, + 0xd4, 0x12, 0xfe, 0xfa, 0xea, 0x61, 0xa9, 0x82, 0x86, 0x83, 0xd0, 0x95, 0xb6, 0x90, 0x00, 0x03, 0x97, 0xd2, 0xa7, + 0xd3, 0x9d, 0x49, 0x64, 0x96, 0xc5, 0xf0, 0xee, 0x41, 0x05, 0xf3, 0xdf, 0xd9, 0x46, 0x58, 0x15, 0xb8, 0x5c, 0xa9, + 0xa2, 0x5e, 0x4a, 0x02, 0x01, 0xe8, 0x4b, 0xef, 0x41, 0x79, 0x51, 0x74, 0x1b, 0x0d, 0x09, 0x5a, 0x58, 0x6a, 0xae, + 0x55, 0x31, 0xdd, 0x0f, 0x9f, 0x06, 0x0c, 0x3e, 0xbc, 0x43, 0xda, 0xc6, 0xfb, 0x9c, 0x94, 0x50, 0xbb, 0x83, 0xf6, + 0xc1, 0x2a, 0x3b, 0x28, 0xff, 0x36, 0xa6, 0xc8, 0xe6, 0xf7, 0xd9, 0x0f, 0xd4, 0x75, 0x38, 0x70, 0x05, 0xab, 0x5e, + 0xca, 0x28, 0x18, 0xb0, 0x72, 0x0a, 0xd4, 0xde, 0x49, 0x46, 0xb3, 0x29, 0x03, 0x75, 0xbf, 0x2d, 0x5a, 0xcd, 0xed, + 0x49, 0xdd, 0x6f, 0xc8, 0x38, 0xfb, 0x08, 0xe3, 0xec, 0xa3, 0xc0, 0x8b, 0x45, 0x92, 0x3f, 0x64, 0xac, 0x71, 0xac, + 0x9a, 0x02, 0x1d, 0x75, 0x80, 0x3b, 0x03, 0x07, 0x1e, 0xb0, 0x45, 0x39, 0x38, 0xa0, 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, 0xb0, 0xa6, 0xaa, 0xdf, 0x40, 0x73, 0x54, 0x0b, 0x72, 0xf3, 0xc4, 0x78, 0xab, 0x92, 0x7e, + 0x14, 0x0d, 0x2c, 0xa7, 0x42, 0x0c, 0xc9, 0xe8, 0xb7, 0x06, 0xc1, 0xad, 0xf6, 0x6a, 0xc5, 0x3d, 0xe2, 0x8b, 0x9a, + 0xb7, 0x9a, 0xb9, 0x05, 0xa0, 0x45, 0x1c, 0x95, 0xf7, 0x26, 0x11, 0x78, 0xdf, 0x96, 0x11, 0xd2, 0x96, 0x7d, 0xfb, + 0xfe, 0x63, 0xa9, 0xd8, 0x7c, 0x47, 0x27, 0x83, 0x34, 0xb2, 0x23, 0x8a, 0xf0, 0x75, 0x09, 0x49, 0xb8, 0x4a, 0xba, + 0x56, 0x99, 0x9c, 0x33, 0x95, 0x72, 0x7c, 0x5d, 0x48, 0xa9, 0xaf, 0xec, 0x97, 0xc4, 0xd5, 0x9d, 0x8c, 0xc0, 0xd7, + 0x13, 0xa6, 0xdf, 0xd1, 0x62, 0xc2, 0xc0, 0xaf, 0xc8, 0xdf, 0x8e, 0xa5, 0x94, 0x5c, 0x3e, 0x11, 0x71, 0x9f, 0x62, + 0x78, 0xbc, 0x74, 0x80, 0xb5, 0x09, 0x81, 0x52, 0xe2, 0x22, 0x5c, 0x10, 0xbd, 0x29, 0xe4, 0xed, 0x5d, 0x5c, 0x60, + 0xe7, 0x00, 0x58, 0x3a, 0x4d, 0x02, 0xfc, 0xcb, 0xc7, 0x7c, 0xac, 0xc6, 0x9c, 0x1a, 0x5d, 0xbf, 0xfb, 0x9d, 0x5c, + 0x03, 0xbd, 0x2d, 0x1d, 0x05, 0xfb, 0xad, 0x01, 0xe4, 0xc2, 0x5d, 0x18, 0x5c, 0x7c, 0x85, 0xb5, 0x65, 0x61, 0xbc, + 0xb1, 0x00, 0x7a, 0x7f, 0x67, 0x60, 0xc1, 0x86, 0x39, 0xa6, 0xf0, 0xf2, 0xeb, 0x84, 0xe9, 0x20, 0x2a, 0xc8, 0x93, + 0xf2, 0x6d, 0xcf, 0x5a, 0xed, 0xb7, 0x6c, 0x0c, 0x77, 0x18, 0xc9, 0xb7, 0x0b, 0x27, 0x0e, 0x3c, 0x20, 0xd3, 0x64, + 0xb6, 0xd9, 0x37, 0x3e, 0xf2, 0xc8, 0xeb, 0x71, 0xbc, 0xab, 0xa5, 0x30, 0xdf, 0xac, 0xe8, 0x1a, 0x43, 0x28, 0x8a, + 0xb0, 0xdf, 0x2f, 0x2a, 0xa6, 0xa8, 0x32, 0x68, 0x83, 0x86, 0xe5, 0x8d, 0xf8, 0x05, 0xce, 0x18, 0x5a, 0x2f, 0x64, + 0xef, 0xe8, 0xac, 0xc3, 0x99, 0xc3, 0x8c, 0x29, 0x81, 0x51, 0x69, 0x59, 0xd0, 0x09, 0x38, 0x3a, 0x57, 0x1f, 0x44, + 0xc5, 0xd5, 0xb1, 0x02, 0xf0, 0x24, 0x53, 0xf8, 0x27, 0xdf, 0x04, 0xeb, 0x7e, 0xab, 0x66, 0x98, 0xfa, 0x8b, 0xde, + 0x76, 0x2d, 0x5f, 0x86, 0x38, 0xd2, 0xc6, 0x10, 0x5a, 0xe7, 0xf6, 0x0e, 0x50, 0xc4, 0x05, 0xbd, 0x48, 0x35, 0xbe, + 0x56, 0x8b, 0xa1, 0x59, 0x5f, 0xe3, 0x3a, 0xa6, 0x0d, 0xa2, 0x58, 0x77, 0x4d, 0x7c, 0x5d, 0x3d, 0xa5, 0xaa, 0x52, + 0x05, 0x67, 0x90, 0x40, 0x58, 0x95, 0x97, 0x0d, 0xa9, 0x24, 0x97, 0xa6, 0x53, 0x69, 0x3a, 0xad, 0x10, 0xca, 0xa5, + 0x27, 0xe5, 0xfd, 0x2b, 0x84, 0x30, 0x30, 0x65, 0x76, 0x60, 0x95, 0xda, 0xc2, 0x2a, 0x78, 0xf5, 0x62, 0x03, 0xab, + 0x24, 0x1c, 0xcf, 0x25, 0x1a, 0x15, 0x15, 0x0e, 0x19, 0xd2, 0x17, 0x62, 0x11, 0x24, 0x00, 0x16, 0xbd, 0xcb, 0x5c, + 0xde, 0xf7, 0x70, 0x28, 0xec, 0x49, 0x26, 0xe1, 0x74, 0x13, 0x9a, 0xc3, 0x1b, 0xbb, 0xaa, 0xe7, 0x11, 0x02, 0x96, + 0x9e, 0x63, 0x78, 0x5b, 0xf9, 0xfb, 0x6f, 0xba, 0x3a, 0x0b, 0xf2, 0xf4, 0x5f, 0xa2, 0x24, 0x34, 0xf6, 0x9f, 0xe3, + 0xa1, 0x43, 0xc2, 0x70, 0xe0, 0x9b, 0x23, 0xac, 0x70, 0x70, 0xab, 0x88, 0xcf, 0xe0, 0x0e, 0x1f, 0xeb, 0xd0, 0x03, + 0xc0, 0x12, 0x8a, 0x43, 0x90, 0x6f, 0xa0, 0x98, 0xc1, 0x01, 0x4d, 0x96, 0xe1, 0x05, 0x2e, 0x58, 0x2d, 0x94, 0xf7, + 0xb7, 0x2d, 0x2f, 0xa5, 0xd5, 0x2e, 0x79, 0x8d, 0x39, 0x50, 0xf9, 0x19, 0x5e, 0xf8, 0x0a, 0xf3, 0xe8, 0xb3, 0xfb, + 0xc2, 0xd7, 0x0e, 0xe8, 0x29, 0x04, 0x8c, 0x74, 0xbf, 0xd7, 0x84, 0x7b, 0x8a, 0x5e, 0xe6, 0xe2, 0xb0, 0xed, 0xa0, + 0x7b, 0x81, 0xb9, 0xba, 0xaa, 0xb2, 0xe6, 0x60, 0x0a, 0x0d, 0x0e, 0xaa, 0x70, 0x46, 0x60, 0xae, 0x5e, 0x94, 0x05, + 0xe7, 0x20, 0xde, 0xf7, 0x84, 0xc9, 0x29, 0xa3, 0x01, 0xbc, 0xc8, 0xca, 0x47, 0xa7, 0x7a, 0x1c, 0x5c, 0xc6, 0x0d, + 0x9b, 0xf8, 0x42, 0xf8, 0x54, 0x60, 0x25, 0xad, 0x71, 0x68, 0x44, 0x47, 0x74, 0x0e, 0x66, 0x1b, 0x40, 0xc1, 0xdd, + 0xf9, 0xb0, 0xb1, 0x50, 0xc1, 0xbb, 0xb6, 0xb5, 0x67, 0xa8, 0x09, 0x71, 0x26, 0x4d, 0xc1, 0xdd, 0xb6, 0x41, 0x06, + 0x6f, 0x7e, 0xfb, 0x6f, 0x85, 0x45, 0x82, 0x01, 0x95, 0x9a, 0x24, 0x08, 0x4f, 0x50, 0x1a, 0xe9, 0x56, 0x6e, 0x26, + 0x90, 0x4e, 0x44, 0xcd, 0xa8, 0x7b, 0xe3, 0x7c, 0x75, 0xd4, 0x40, 0x54, 0xd4, 0x40, 0x05, 0xd4, 0x40, 0xd6, 0xb7, + 0x7f, 0x01, 0x0b, 0x61, 0x23, 0x54, 0x89, 0x20, 0x20, 0xc2, 0x5c, 0x1b, 0x3e, 0xa0, 0x48, 0x42, 0xc8, 0x1b, 0x40, + 0xc5, 0x94, 0xbc, 0x04, 0xa3, 0x71, 0x78, 0xbd, 0x07, 0xdc, 0x2f, 0x2d, 0xc3, 0xe0, 0x39, 0x05, 0x93, 0xff, 0xd6, + 0xe7, 0x43, 0xf5, 0x72, 0x75, 0x10, 0xc2, 0x2f, 0x20, 0x56, 0x84, 0xe3, 0x2f, 0x7e, 0x01, 0xb2, 0xa9, 0xb0, 0x3c, + 0x38, 0x90, 0x20, 0xf0, 0x43, 0x14, 0xe1, 0x80, 0x67, 0x78, 0x99, 0x6d, 0x10, 0x3d, 0x3f, 0x2b, 0x55, 0xcd, 0x4a, + 0x06, 0xb3, 0x2a, 0x3c, 0x8d, 0xa3, 0x6b, 0xc2, 0x40, 0x70, 0xa1, 0x76, 0xdf, 0x20, 0x04, 0xca, 0x96, 0x1b, 0x43, + 0x97, 0x9e, 0x82, 0xf9, 0x68, 0x1c, 0xbd, 0x65, 0xf0, 0x3a, 0xaf, 0x31, 0xf9, 0x67, 0x9a, 0x65, 0xda, 0x30, 0x8f, + 0x8d, 0xc0, 0x49, 0x9d, 0xa2, 0xe4, 0x6f, 0xc9, 0x45, 0x1c, 0x35, 0x2f, 0x23, 0xd4, 0x80, 0x7f, 0x1b, 0x1c, 0x75, + 0x69, 0x42, 0x47, 0x23, 0x1f, 0xfc, 0x26, 0x23, 0x66, 0x93, 0xad, 0x56, 0xa2, 0x22, 0xe8, 0x89, 0xdd, 0x60, 0xc0, + 0x4a, 0xbc, 0x00, 0xf6, 0xc1, 0x72, 0xb0, 0xe4, 0x9d, 0x88, 0x95, 0x3f, 0xa5, 0x30, 0x58, 0x3d, 0x67, 0x08, 0xe1, + 0x2c, 0x88, 0xd9, 0xf8, 0x9f, 0xcf, 0x34, 0x5c, 0x3f, 0x3f, 0x5f, 0xc7, 0x88, 0x48, 0x1f, 0x44, 0xae, 0xc6, 0x8e, + 0x88, 0x20, 0x6c, 0x99, 0xee, 0xbb, 0x32, 0x3f, 0x78, 0xeb, 0xea, 0x81, 0x0d, 0x17, 0x07, 0x06, 0xd4, 0x28, 0x30, + 0x5a, 0xc1, 0x39, 0x29, 0x07, 0x0e, 0x4a, 0x08, 0xcd, 0x8a, 0x78, 0x4a, 0x2e, 0x21, 0x12, 0x5e, 0x86, 0xba, 0x60, + 0x58, 0x10, 0x48, 0x50, 0x53, 0x90, 0xa0, 0x32, 0x5f, 0x7b, 0x04, 0xb3, 0xce, 0xcd, 0x6c, 0xa7, 0xa8, 0xeb, 0x82, + 0xfc, 0xfc, 0xa2, 0xe3, 0x11, 0xb0, 0xb4, 0x07, 0x07, 0x05, 0x44, 0x10, 0x03, 0x0a, 0x5e, 0x4a, 0x80, 0x81, 0x06, + 0xbc, 0xd8, 0xd0, 0x80, 0xcf, 0xb5, 0xf1, 0x3a, 0x30, 0xb6, 0x3e, 0x65, 0x90, 0x8b, 0x67, 0xd5, 0x9e, 0x26, 0x84, + 0xec, 0xb7, 0x7a, 0x3a, 0xdd, 0x8e, 0x90, 0xd8, 0xfb, 0xa8, 0x4d, 0xa0, 0x31, 0x47, 0xba, 0xab, 0x8d, 0xf9, 0xb5, + 0xa6, 0x47, 0xac, 0x26, 0x21, 0x5d, 0x90, 0x2e, 0xcf, 0xa7, 0x3d, 0x83, 0x2b, 0x56, 0x69, 0xe4, 0xe0, 0x02, 0xf4, + 0xd9, 0x80, 0x00, 0x05, 0x2a, 0x4d, 0x25, 0x8a, 0x22, 0x2e, 0x92, 0x92, 0x0d, 0xc3, 0x0c, 0xc2, 0x14, 0x56, 0x2b, + 0x41, 0x37, 0xd6, 0x00, 0x78, 0x67, 0x66, 0xff, 0x94, 0x3e, 0xd8, 0x74, 0xed, 0xcd, 0x23, 0x80, 0x80, 0xec, 0xb7, + 0x4b, 0x76, 0x5d, 0x6c, 0x54, 0x66, 0x61, 0x2d, 0x63, 0x2b, 0xb7, 0xed, 0x31, 0xf6, 0x4e, 0x6c, 0xf3, 0x09, 0x10, + 0xa2, 0xb6, 0x64, 0x1a, 0x21, 0x42, 0x62, 0x11, 0xeb, 0xda, 0x90, 0x8d, 0x36, 0xb4, 0x6f, 0x5e, 0xb7, 0x87, 0xd8, + 0x07, 0xa0, 0x78, 0x73, 0x5c, 0x82, 0x43, 0x78, 0xe1, 0x11, 0xfe, 0x16, 0x58, 0xa4, 0x02, 0x33, 0x2c, 0x57, 0x2b, + 0xa8, 0xe7, 0xf1, 0x3e, 0xdb, 0x0c, 0x4e, 0x2a, 0x37, 0xc6, 0x2e, 0xed, 0xc4, 0xe3, 0xb2, 0x09, 0x89, 0x33, 0xe8, + 0xd7, 0x57, 0x44, 0xbd, 0xfd, 0x76, 0xfa, 0xc4, 0xbf, 0x57, 0xe6, 0x76, 0x20, 0x36, 0xac, 0x37, 0x58, 0x7d, 0x00, + 0x2d, 0x7f, 0x95, 0xf9, 0x87, 0xca, 0x82, 0x9b, 0x04, 0xb5, 0xb9, 0x88, 0x5d, 0xd6, 0x45, 0x8c, 0xd4, 0x16, 0x77, + 0x87, 0x10, 0xff, 0x6a, 0x2b, 0x8a, 0x01, 0x4f, 0x2a, 0xfe, 0x39, 0x46, 0x5d, 0x08, 0x45, 0x6d, 0x3d, 0x6c, 0x80, + 0xd2, 0x2e, 0xd7, 0x95, 0x18, 0x19, 0x12, 0xc8, 0xb7, 0x2e, 0xbc, 0xa0, 0x39, 0x89, 0x14, 0xc8, 0xc9, 0x41, 0x54, + 0xd2, 0x6c, 0x43, 0x98, 0xeb, 0x6e, 0xe1, 0x98, 0xb9, 0xda, 0xa0, 0x45, 0xfc, 0x02, 0xd8, 0x19, 0x6e, 0x24, 0x4b, + 0x07, 0x3e, 0x55, 0x03, 0x9f, 0x5f, 0x73, 0x43, 0x51, 0x14, 0xea, 0xbd, 0xb3, 0x8f, 0xcc, 0xc1, 0xef, 0x34, 0x10, + 0x1f, 0xa9, 0xd3, 0x91, 0x6c, 0x84, 0x5a, 0x73, 0x76, 0xbc, 0x6c, 0x33, 0xc2, 0xa0, 0xb0, 0xd1, 0xfb, 0x2a, 0x64, + 0x15, 0x3b, 0x3b, 0x15, 0xc1, 0x9c, 0xbe, 0xa8, 0xca, 0x39, 0x95, 0x5b, 0x46, 0xb5, 0xd4, 0x34, 0x40, 0x84, 0x2b, + 0x9f, 0x48, 0xde, 0x67, 0x26, 0xfc, 0x83, 0xc1, 0xb8, 0x7a, 0xa4, 0xf0, 0xf7, 0xbb, 0x62, 0x87, 0x6c, 0x47, 0x87, + 0xdb, 0x08, 0x9a, 0x17, 0x2a, 0x78, 0xc0, 0x51, 0xc9, 0x12, 0x22, 0x45, 0x2e, 0xf7, 0x55, 0xcd, 0x94, 0xed, 0x3a, + 0x42, 0x08, 0x69, 0x8f, 0xb3, 0x6e, 0x68, 0xf5, 0xd0, 0x23, 0x55, 0x94, 0xc3, 0x2d, 0x9a, 0xeb, 0x02, 0x54, 0x18, + 0x81, 0x74, 0xf9, 0x99, 0xdd, 0xa5, 0x12, 0xa2, 0x97, 0xaf, 0x5d, 0x08, 0x63, 0x67, 0x65, 0x89, 0x0b, 0x33, 0x6a, + 0x1b, 0x46, 0xd7, 0x6d, 0x0c, 0x67, 0x03, 0x63, 0xa6, 0x41, 0x49, 0x0b, 0x42, 0x5d, 0x77, 0xe9, 0x45, 0x66, 0x02, + 0x3d, 0xe6, 0x84, 0x36, 0x18, 0x9e, 0x12, 0x0d, 0x96, 0x4d, 0x05, 0x58, 0xf0, 0x2d, 0x8b, 0xd4, 0xda, 0x6c, 0xb2, + 0xf8, 0xa3, 0x8e, 0xcd, 0xd3, 0x7e, 0x79, 0xc5, 0x3c, 0x17, 0x8e, 0xba, 0x3d, 0xcf, 0x7c, 0x3c, 0xba, 0xa7, 0x6f, + 0xae, 0x5e, 0xbc, 0x7c, 0xfd, 0x6a, 0xb5, 0x6a, 0xb3, 0x66, 0xfb, 0x04, 0xff, 0xa4, 0xcb, 0x78, 0xb0, 0x65, 0x14, + 0xa0, 0x83, 0x83, 0x7d, 0x6e, 0x5c, 0x78, 0x3e, 0xf3, 0x39, 0xc4, 0x0d, 0xd2, 0x03, 0x9c, 0x15, 0x65, 0x4c, 0x90, + 0xdb, 0xa8, 0x17, 0xdd, 0x45, 0xa0, 0x84, 0xaa, 0xc8, 0xdf, 0x87, 0xcd, 0xd9, 0xef, 0x41, 0x60, 0x22, 0xa8, 0x0f, + 0x11, 0x40, 0x20, 0x5e, 0x29, 0x2e, 0x08, 0xf3, 0x09, 0x10, 0xc5, 0x7b, 0x01, 0x9c, 0xa9, 0x89, 0x5a, 0xb5, 0x50, + 0x71, 0x01, 0x24, 0xd1, 0x86, 0xa3, 0xa4, 0x47, 0x26, 0x80, 0x37, 0x04, 0xa5, 0xb4, 0xbf, 0xba, 0xb9, 0x73, 0x97, + 0xca, 0x51, 0xaf, 0x95, 0xe6, 0x78, 0xea, 0x3e, 0xa7, 0xf0, 0x39, 0xed, 0xfa, 0xd3, 0x41, 0x1c, 0xe6, 0x78, 0x41, + 0xc4, 0xa1, 0x7f, 0x16, 0x71, 0x39, 0x2f, 0xd8, 0x17, 0x2e, 0x17, 0x2a, 0x5d, 0xde, 0xa6, 0x32, 0xb9, 0x6d, 0x8e, + 0x0e, 0xe3, 0x22, 0xb9, 0x6d, 0xaa, 0xe4, 0x16, 0xe1, 0xbb, 0x54, 0x26, 0x77, 0x36, 0xe5, 0xae, 0xa9, 0xe0, 0xe6, + 0x0b, 0x0b, 0x38, 0x14, 0x6d, 0xd1, 0xc6, 0x62, 0xb3, 0xa8, 0x4d, 0x71, 0x45, 0x03, 0x0c, 0xfe, 0x7d, 0xc7, 0xc6, + 0x0f, 0xc3, 0x97, 0xe0, 0xd2, 0xa4, 0x89, 0xfc, 0x04, 0xd2, 0x4f, 0xab, 0x32, 0x70, 0x9f, 0x92, 0x56, 0x77, 0x7a, + 0x21, 0x9a, 0xed, 0x6e, 0xa3, 0x31, 0x85, 0xbd, 0x9b, 0x91, 0xdc, 0x17, 0x9b, 0x36, 0x4c, 0x7c, 0x9d, 0xfd, 0x6c, + 0xb5, 0xda, 0xcf, 0x91, 0xd9, 0x70, 0x13, 0x16, 0xeb, 0xfe, 0x74, 0x80, 0x5b, 0xf8, 0x79, 0x86, 0xd0, 0x92, 0xf5, + 0xa7, 0x03, 0xc2, 0xfa, 0xd3, 0x46, 0x7b, 0x60, 0x0d, 0xed, 0xcc, 0x56, 0x5c, 0x43, 0x08, 0xcd, 0xe9, 0xe0, 0xc8, + 0x94, 0x94, 0x2e, 0xdf, 0x7e, 0xd1, 0x2a, 0xa0, 0x9f, 0xaa, 0x05, 0x2f, 0x93, 0xb8, 0x03, 0x7d, 0xd1, 0x0b, 0xfb, + 0x74, 0x6b, 0x41, 0x8e, 0x8f, 0x2a, 0x57, 0x7b, 0x8a, 0xb0, 0xe9, 0x49, 0x1d, 0x16, 0x87, 0xa6, 0x19, 0xd7, 0xa5, + 0x74, 0xdf, 0xa1, 0x66, 0xe4, 0xa3, 0x83, 0x05, 0x20, 0x48, 0x05, 0x8f, 0xac, 0x70, 0xe1, 0x94, 0x42, 0xb8, 0x38, + 0xa8, 0x6c, 0xc1, 0x24, 0x27, 0xad, 0x6e, 0x6e, 0x2c, 0xfd, 0x73, 0x17, 0xd1, 0x94, 0x62, 0x4a, 0x32, 0x5f, 0x32, + 0x37, 0x60, 0xa1, 0x9b, 0x94, 0x67, 0x0a, 0x7a, 0xa5, 0x01, 0x1e, 0x11, 0x88, 0x87, 0xd4, 0x2d, 0x8c, 0x81, 0x57, + 0x3c, 0x6d, 0x16, 0x7d, 0x36, 0x40, 0x47, 0xc7, 0x98, 0xf6, 0xff, 0xca, 0xe6, 0x6d, 0x78, 0x2c, 0xf0, 0xaf, 0x01, + 0x99, 0x36, 0x65, 0x99, 0x20, 0x20, 0x61, 0xd4, 0x94, 0x87, 0xb0, 0x97, 0x10, 0xce, 0x6c, 0xc5, 0xac, 0xcf, 0x06, + 0xcd, 0x69, 0x59, 0xb1, 0xe3, 0x2b, 0x36, 0x64, 0x99, 0x60, 0x2b, 0x36, 0x5c, 0xc5, 0xf0, 0x75, 0x06, 0x03, 0x82, + 0x10, 0x00, 0x0c, 0x00, 0xa0, 0x51, 0x10, 0xcd, 0x17, 0x2b, 0xe2, 0x37, 0xbb, 0xbd, 0xc7, 0x6f, 0x81, 0x05, 0x5a, + 0x6d, 0xff, 0xef, 0x42, 0x19, 0xb0, 0xa7, 0x2c, 0x4c, 0xcc, 0xdc, 0xc2, 0xaa, 0xe8, 0x00, 0x2a, 0x25, 0xc2, 0x14, + 0x06, 0x32, 0xfb, 0x99, 0x81, 0x5a, 0xa0, 0x35, 0xc8, 0xfb, 0x7a, 0xd0, 0xcc, 0xe0, 0x88, 0x81, 0x77, 0x68, 0xc8, + 0xd4, 0x18, 0x13, 0xc6, 0x39, 0x4c, 0x31, 0x33, 0xe0, 0x99, 0xa6, 0xad, 0xb5, 0x34, 0xb2, 0x5c, 0x2f, 0xef, 0xfd, + 0xa3, 0x63, 0xd5, 0x2f, 0x9a, 0xed, 0x01, 0xda, 0x27, 0xc4, 0x7e, 0x0c, 0x60, 0x93, 0xb9, 0xd4, 0x86, 0xf9, 0x3e, + 0xea, 0xa4, 0xf6, 0x13, 0xfe, 0x0c, 0xd6, 0x66, 0x07, 0x80, 0x8e, 0x0c, 0x9b, 0xf5, 0x97, 0x35, 0x95, 0xd7, 0xc7, + 0x9d, 0x51, 0x2a, 0x77, 0xbd, 0x3b, 0x1d, 0x68, 0x8a, 0x43, 0x6f, 0x3d, 0x5c, 0x3e, 0xd4, 0x43, 0xc0, 0x8c, 0xc1, + 0xdc, 0x32, 0xa3, 0xef, 0x85, 0x48, 0x2e, 0x88, 0xc4, 0xd2, 0x60, 0x0d, 0x83, 0xbd, 0x75, 0x70, 0x60, 0xaa, 0xb1, + 0x06, 0x3c, 0x4f, 0x8a, 0x40, 0x30, 0xf0, 0x11, 0x94, 0x01, 0x4d, 0x94, 0xb9, 0x0d, 0x27, 0x1f, 0x99, 0xfb, 0x85, + 0xcb, 0xdb, 0xc7, 0xc2, 0x69, 0x5b, 0xcd, 0xf5, 0x78, 0x59, 0xe0, 0xae, 0xbc, 0x97, 0xb4, 0x0a, 0x6e, 0x64, 0x6f, + 0xf2, 0x94, 0xb9, 0x5b, 0xf7, 0xa5, 0x3a, 0xbb, 0x9b, 0xe9, 0x94, 0xcd, 0x74, 0xb6, 0x9b, 0x09, 0x35, 0x33, 0xdf, + 0xb2, 0x8a, 0x34, 0x27, 0x6b, 0xa2, 0xe6, 0x54, 0xfc, 0x44, 0xe7, 0xa0, 0x1d, 0xe5, 0xf6, 0x5e, 0x15, 0x4e, 0xae, + 0x9c, 0x5c, 0xee, 0xe7, 0x86, 0xb8, 0x22, 0x73, 0xa1, 0x0e, 0x01, 0x5e, 0x5e, 0x94, 0x8f, 0x0f, 0x70, 0x29, 0x7e, + 0x95, 0x23, 0x17, 0xe5, 0x54, 0x48, 0x2d, 0x05, 0x8b, 0x90, 0x41, 0x55, 0x17, 0x03, 0x7b, 0x69, 0xf7, 0x9e, 0xe8, + 0xf1, 0x7e, 0x15, 0x31, 0x6f, 0x60, 0x9e, 0xfb, 0xf8, 0x9e, 0xa6, 0xd8, 0xa9, 0x89, 0x33, 0xf2, 0x21, 0x8b, 0x73, + 0x90, 0xcd, 0xfa, 0xd5, 0x6b, 0xbf, 0x8d, 0x36, 0x2e, 0x9a, 0xb1, 0xe8, 0x99, 0x27, 0x4e, 0x7e, 0x28, 0x8c, 0x71, + 0x80, 0x75, 0xf4, 0x47, 0x98, 0x5a, 0xb0, 0x67, 0x89, 0xa7, 0xd0, 0xc9, 0xad, 0x4d, 0xbb, 0x0b, 0xd3, 0xee, 0x4c, + 0x5a, 0x07, 0xca, 0x01, 0x69, 0x76, 0x65, 0x3a, 0x77, 0xfe, 0xfb, 0x0e, 0x5e, 0xba, 0x5d, 0x43, 0x24, 0xee, 0xf9, + 0x23, 0x63, 0x0c, 0xf1, 0x06, 0x6c, 0x44, 0xd5, 0xc1, 0xc1, 0x1f, 0xce, 0xfb, 0xb6, 0x92, 0xfb, 0xbe, 0x15, 0x0e, + 0x6c, 0x83, 0xa9, 0x74, 0x79, 0x23, 0x99, 0x2d, 0xc0, 0xae, 0x73, 0xff, 0x1b, 0xf1, 0xf0, 0x45, 0xc8, 0xb4, 0x58, + 0x57, 0xf1, 0x57, 0x72, 0x54, 0x7a, 0x88, 0x6a, 0x88, 0x40, 0x5a, 0x59, 0x97, 0x86, 0xa6, 0xa3, 0x57, 0x53, 0x3a, + 0x92, 0x37, 0x6f, 0xa5, 0xd4, 0x03, 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, 0x5f, 0x93, 0xd9, 0x07, 0x80, 0x40, 0xed, 0xc3, 0x8a, 0x27, 0x0e, 0x04, 0x89, 0x33, 0x1c, 0x7d, 0xcf, 0xd9, + 0x8d, 0xb5, 0x1c, 0x9e, 0xcd, 0x17, 0x9a, 0x8d, 0xcc, 0x1d, 0x35, 0xa8, 0xf8, 0xea, 0x7e, 0x5e, 0x3f, 0x65, 0x35, + 0xdd, 0xf8, 0x3d, 0x08, 0x23, 0xe1, 0x94, 0x1d, 0x46, 0x21, 0x61, 0x83, 0x59, 0x95, 0xf1, 0xda, 0x7e, 0x83, 0x78, + 0x0f, 0xda, 0x84, 0x13, 0x2c, 0x6a, 0x17, 0x54, 0x11, 0xb6, 0xf1, 0xc6, 0x82, 0x28, 0x0f, 0x6f, 0xb6, 0x8c, 0xa6, + 0x97, 0x6b, 0x08, 0x74, 0xdc, 0x8b, 0x9a, 0x51, 0x83, 0xa5, 0x2e, 0x28, 0xb3, 0x8f, 0x30, 0xae, 0x2e, 0x4e, 0x4c, + 0x9c, 0xf6, 0x52, 0xaf, 0xfe, 0x5b, 0x06, 0x06, 0xf8, 0x02, 0xbc, 0xc4, 0xc2, 0xe8, 0xae, 0x7d, 0xdd, 0x80, 0xfa, + 0xb2, 0xc1, 0x06, 0x68, 0xb5, 0x6a, 0x95, 0xcf, 0x40, 0xb9, 0x6b, 0x2e, 0x61, 0xaf, 0xb9, 0x84, 0xbb, 0xe6, 0x12, + 0xfe, 0x9a, 0x4b, 0x98, 0x6b, 0x2e, 0xe1, 0xaf, 0xb9, 0x3c, 0x08, 0x3f, 0x05, 0x71, 0x1c, 0x63, 0x0e, 0x71, 0x15, + 0xb5, 0x8d, 0x8c, 0x07, 0x17, 0x9e, 0xfb, 0x2c, 0x51, 0xe5, 0xf2, 0x87, 0x31, 0xe4, 0xb6, 0x6c, 0x25, 0x8c, 0xdb, + 0x14, 0x53, 0x10, 0x39, 0xfd, 0xe0, 0xa0, 0x74, 0x77, 0x06, 0x1f, 0xf5, 0x94, 0xe3, 0xa5, 0x75, 0xa2, 0xfd, 0x03, + 0x74, 0xf2, 0xe6, 0xd7, 0xc7, 0x54, 0xae, 0x89, 0x70, 0x26, 0xf7, 0xfb, 0x6d, 0x4f, 0x29, 0x3e, 0x65, 0x26, 0x3c, + 0x39, 0x4f, 0xb4, 0x11, 0x41, 0x10, 0xa2, 0x44, 0xe1, 0x8c, 0x48, 0xbb, 0xdf, 0xbd, 0x2b, 0xbc, 0x51, 0x45, 0x79, + 0xb3, 0x92, 0xc7, 0x39, 0x38, 0xb1, 0x1b, 0x2b, 0x0c, 0xd4, 0x05, 0x17, 0x82, 0xcc, 0x24, 0xfc, 0xd1, 0xcc, 0x2d, + 0x39, 0xcb, 0xca, 0xa4, 0x8f, 0xcd, 0xdc, 0x10, 0xb0, 0x82, 0xec, 0x7b, 0x98, 0x2d, 0x6f, 0x53, 0x8a, 0xef, 0xd2, + 0x0c, 0x0f, 0xe5, 0x6d, 0x5a, 0x84, 0xb6, 0x20, 0xfe, 0xe2, 0xef, 0xff, 0x65, 0xef, 0x5d, 0x9b, 0xdb, 0x36, 0xb2, + 0x76, 0xd1, 0xbf, 0x22, 0xb1, 0x6c, 0x06, 0x30, 0x9b, 0x14, 0xe5, 0xbd, 0x67, 0xaa, 0x0e, 0xa8, 0x16, 0xcb, 0xb1, + 0xe3, 0x89, 0x33, 0xf1, 0x65, 0x2c, 0x4f, 0x26, 0x19, 0x16, 0x0f, 0x03, 0x01, 0x4d, 0x01, 0x0e, 0x08, 0x30, 0x00, + 0x28, 0x91, 0x26, 0xf1, 0xdf, 0x77, 0xad, 0xb5, 0xfa, 0x0a, 0x82, 0xb2, 0xe7, 0x7d, 0xf7, 0xfb, 0xe9, 0x9c, 0x2f, + 0xb6, 0xd8, 0x68, 0x34, 0xfa, 0xde, 0xab, 0xd7, 0xe5, 0x79, 0x96, 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, + 0x9f, 0xa4, 0x20, 0x4e, 0x14, 0x1c, 0x02, 0xae, 0xb6, 0x37, 0xe9, 0x17, 0x30, 0x7c, 0xe9, 0x60, 0xcb, 0xe1, 0x6d, + 0xb1, 0xed, 0xb1, 0x92, 0x7f, 0x00, 0xf6, 0xad, 0x9e, 0x8c, 0xd5, 0xed, 0x81, 0xb3, 0x2e, 0xa5, 0xe8, 0x78, 0x53, + 0x1c, 0xde, 0x9e, 0xcf, 0xf6, 0xdb, 0x20, 0x62, 0xbb, 0x20, 0xc3, 0x5a, 0x27, 0x0d, 0xff, 0x89, 0xb6, 0x0e, 0x16, + 0x23, 0xec, 0xff, 0xb2, 0x1e, 0x78, 0x09, 0xa9, 0xa1, 0xc0, 0xc5, 0x60, 0xc3, 0xd1, 0xda, 0x2e, 0xd3, 0xc0, 0x4d, + 0x0d, 0x7a, 0x7d, 0x4f, 0x21, 0xca, 0x4b, 0x46, 0x73, 0x23, 0x58, 0x37, 0x86, 0x5c, 0x1c, 0x8e, 0x9b, 0xe5, 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, 0xcb, 0x67, 0x42, 0xba, 0x88, 0xe7, 0x20, 0x88, 0xda, 0xcf, 0xb3, 0xe1, 0xc6, + 0xbf, 0x58, 0x3f, 0x13, 0xca, 0x6f, 0x3c, 0xb7, 0xe5, 0x90, 0x3a, 0x6b, 0xe1, 0x0b, 0xe3, 0xe1, 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, + 0x0f, 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, 0x97, 0x32, 0x5d, 0x06, 0x5c, 0xd2, 0xef, + 0x52, 0xa5, 0x14, 0xfe, 0x13, 0x01, 0xe8, 0x1c, 0xdc, 0xe3, 0xcb, 0x31, 0x90, 0x66, 0x58, 0xf8, 0xad, 0xd9, 0xf1, + 0x35, 0x09, 0xb7, 0x49, 0x70, 0x31, 0xc0, 0x39, 0xba, 0x0a, 0xcb, 0xbb, 0x14, 0x22, 0xa8, 0x4a, 0xa8, 0x6f, 0x65, + 0x1a, 0x94, 0xb6, 0x1a, 0x84, 0x35, 0x09, 0x75, 0x26, 0xd9, 0xa8, 0xb4, 0xdd, 0x28, 0xcc, 0x16, 0x71, 0x3d, 0x23, + 0xac, 0x39, 0x9b, 0xa9, 0x06, 0x26, 0x0d, 0xc7, 0x4d, 0xa3, 0xb5, 0xa8, 0x50, 0x53, 0x98, 0xd7, 0xb8, 0xaa, 0x54, + 0x75, 0x37, 0xa7, 0x96, 0xd2, 0xb2, 0xbd, 0xea, 0x26, 0xd9, 0x90, 0xcb, 0x50, 0x86, 0xc1, 0x46, 0x8e, 0x60, 0x02, + 0x49, 0x72, 0xe6, 0x6f, 0xe4, 0x1f, 0x6a, 0xd3, 0xb5, 0x80, 0x39, 0xc6, 0x2c, 0x1b, 0x16, 0xf4, 0x0a, 0xdc, 0x03, + 0xad, 0xf4, 0x7c, 0x9a, 0x5d, 0xe4, 0x41, 0x32, 0x2c, 0xf4, 0xb2, 0xc9, 0xf8, 0x9f, 0xc2, 0x48, 0x93, 0x19, 0x2b, + 0x59, 0x64, 0xbb, 0x3a, 0x25, 0xce, 0xe3, 0x04, 0xb6, 0x47, 0xd3, 0x5b, 0xbe, 0xcf, 0x20, 0x2a, 0x08, 0x14, 0xcc, + 0x98, 0x2f, 0xbb, 0x78, 0xee, 0xfb, 0xcc, 0x32, 0x75, 0x1f, 0x0e, 0xc6, 0x8c, 0xed, 0xf7, 0xfb, 0x79, 0xbf, 0xaf, + 0xe6, 0x5b, 0xbf, 0x9f, 0x5c, 0x9b, 0xbf, 0x3d, 0x60, 0x50, 0x90, 0x13, 0xd1, 0x54, 0x88, 0xe0, 0x1f, 0x92, 0x67, + 0x48, 0x46, 0x77, 0xdc, 0xe7, 0x96, 0xb3, 0x65, 0x75, 0x04, 0x82, 0x79, 0x38, 0x5c, 0x2a, 0xb0, 0x6b, 0x89, 0x22, + 0x21, 0xcb, 0x7f, 0x06, 0xc6, 0x33, 0xf7, 0x01, 0x96, 0x0c, 0x40, 0xd8, 0x2a, 0x4f, 0xd7, 0x7b, 0xbe, 0x0a, 0xde, + 0xe9, 0x78, 0xd7, 0x58, 0x91, 0x81, 0xb8, 0x05, 0x36, 0x62, 0xad, 0x3d, 0x20, 0x67, 0x0a, 0x70, 0xbc, 0x38, 0x1c, + 0xce, 0xe5, 0x2f, 0xdd, 0x6c, 0x9d, 0x40, 0xa5, 0xc0, 0xed, 0xd1, 0xc9, 0xc1, 0x7f, 0x07, 0x9a, 0x41, 0x39, 0xcc, + 0xeb, 0xed, 0xef, 0xcc, 0xc9, 0x4f, 0x4f, 0xf1, 0x4f, 0x78, 0x88, 0x4e, 0xbf, 0xdd, 0x9b, 0x3f, 0x28, 0x2a, 0x0f, + 0x07, 0xb5, 0xf8, 0xcf, 0x39, 0xaf, 0xe0, 0x17, 0xbe, 0x09, 0xcc, 0x26, 0x53, 0xef, 0xe4, 0x9b, 0x3c, 0x67, 0xea, + 0x35, 0x5e, 0x31, 0xf9, 0x0e, 0x87, 0x73, 0x31, 0xaa, 0xb7, 0x23, 0x27, 0xda, 0x29, 0xc7, 0x38, 0x18, 0xfc, 0x17, + 0xd1, 0x36, 0x21, 0xc0, 0x90, 0xba, 0x25, 0xcd, 0x6c, 0x5c, 0x59, 0xe2, 0x59, 0x3a, 0xbf, 0x9c, 0xd4, 0xe5, 0x4e, + 0x2b, 0x9e, 0xf6, 0xc0, 0xe2, 0xb6, 0x06, 0x2f, 0x80, 0x7b, 0x8b, 0xad, 0x2b, 0x05, 0x87, 0x0b, 0x88, 0x53, 0x9c, + 0x80, 0x08, 0xda, 0xef, 0x4b, 0xbc, 0x57, 0xd0, 0x27, 0xfd, 0x00, 0xc1, 0x90, 0x3f, 0x4b, 0xc0, 0x5d, 0xaf, 0x57, + 0x63, 0x7c, 0x2f, 0x85, 0xe0, 0xfa, 0x4c, 0x03, 0xd0, 0x82, 0xdf, 0xe5, 0x63, 0x39, 0xfd, 0x26, 0x02, 0xcf, 0x96, + 0xbd, 0x89, 0x72, 0xb7, 0xe1, 0x69, 0xff, 0x68, 0x21, 0x00, 0x4b, 0xf1, 0x4c, 0x09, 0x16, 0xe4, 0x14, 0x73, 0xf1, + 0xff, 0x82, 0x8f, 0x98, 0xef, 0x49, 0x17, 0xb1, 0xf5, 0xf6, 0xc9, 0x85, 0x81, 0x04, 0x9a, 0x0e, 0xc0, 0x8f, 0x57, + 0x01, 0x5d, 0x19, 0x3f, 0x3f, 0xcb, 0x7a, 0xac, 0x8f, 0xff, 0x14, 0xdc, 0xa7, 0x9f, 0x29, 0x7c, 0x74, 0x38, 0xae, + 0xd2, 0xd1, 0x8e, 0x52, 0x10, 0x1d, 0xdd, 0x3e, 0x9f, 0xf2, 0xec, 0x9b, 0x0a, 0xc8, 0x2d, 0x47, 0xed, 0xa9, 0x00, + 0x2c, 0xb6, 0x74, 0x04, 0x3e, 0xcd, 0xf2, 0x09, 0xf9, 0x5e, 0x4f, 0xc5, 0xd5, 0xa5, 0x4e, 0x17, 0xd7, 0xe3, 0x29, + 0xfc, 0x0f, 0xc4, 0x1e, 0x96, 0x29, 0xb2, 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, 0xb7, + 0x35, 0x0a, 0x56, 0x02, 0xce, 0xb4, 0xb7, 0x60, 0xb0, 0x81, 0x75, 0xcb, 0x32, 0xf8, 0x1b, 0xae, 0x69, 0x02, 0x37, + 0x2c, 0xb2, 0xde, 0x1b, 0x6c, 0xa5, 0xb7, 0xe0, 0x68, 0x99, 0x38, 0x97, 0x92, 0xac, 0x6c, 0x91, 0x71, 0xf5, 0x28, + 0xa4, 0x6a, 0xba, 0xbf, 0x15, 0xf5, 0x83, 0x10, 0x79, 0xb0, 0x4a, 0x59, 0x54, 0xac, 0x40, 0x66, 0x0f, 0xfe, 0x11, + 0x32, 0x72, 0x94, 0x03, 0x47, 0xa1, 0xbf, 0x35, 0x81, 0xce, 0xf3, 0x53, 0xa8, 0xf3, 0x48, 0xb0, 0x95, 0x7a, 0x28, + 0xac, 0xbc, 0x80, 0xe8, 0x60, 0x0b, 0x63, 0x95, 0x27, 0xa1, 0x62, 0x53, 0x26, 0xf2, 0x38, 0xa8, 0x25, 0x60, 0xac, + 0x20, 0x98, 0xb3, 0x5c, 0xba, 0x20, 0x55, 0x8d, 0x1e, 0x16, 0x99, 0xfb, 0xa9, 0xa0, 0xfc, 0x4f, 0x55, 0x4e, 0xb8, + 0xbe, 0x0c, 0x01, 0x8e, 0xf6, 0x29, 0x88, 0x12, 0x63, 0xfd, 0xa2, 0xc5, 0x3b, 0x99, 0x39, 0x9b, 0xda, 0x5e, 0x82, + 0x8c, 0xed, 0xf0, 0x2b, 0x84, 0x56, 0x0b, 0x45, 0x16, 0x0d, 0x17, 0x4c, 0xb7, 0xa7, 0xb4, 0xea, 0x1e, 0x36, 0x3c, + 0x2b, 0x3d, 0x54, 0xea, 0xdb, 0x98, 0xc0, 0xb2, 0x4a, 0x19, 0xbe, 0x9d, 0x50, 0x75, 0x62, 0x50, 0xb1, 0x6e, 0xd8, + 0x12, 0x0e, 0xb1, 0x98, 0x34, 0xd6, 0xd9, 0x80, 0x47, 0x2c, 0x81, 0x7f, 0x36, 0x7c, 0xcc, 0x96, 0x3c, 0x9a, 0x6c, + 0xae, 0x96, 0xfd, 0x7e, 0xe9, 0x85, 0x5e, 0x3d, 0xcb, 0x9e, 0x46, 0xf3, 0x59, 0x3e, 0xf7, 0x51, 0x71, 0x31, 0x19, + 0x0c, 0x36, 0x7e, 0x36, 0x1c, 0xb2, 0x64, 0x38, 0x9c, 0x64, 0x4f, 0xe1, 0xb5, 0xa7, 0x3c, 0x52, 0x4b, 0x2a, 0xb9, + 0xca, 0x60, 0x7f, 0x1f, 0xf0, 0xc8, 0x67, 0x9d, 0x9f, 0x96, 0x4d, 0x97, 0xee, 0x67, 0x76, 0xdc, 0x85, 0xee, 0x00, + 0x1b, 0x6f, 0x1b, 0x74, 0xe4, 0x5f, 0xef, 0x90, 0x52, 0x37, 0x19, 0x80, 0xdd, 0x68, 0x80, 0x43, 0xa6, 0x7a, 0x29, + 0xb2, 0x7a, 0x29, 0x53, 0xbd, 0x24, 0x2b, 0x97, 0x60, 0x21, 0x31, 0x55, 0x6e, 0x23, 0x2b, 0xb7, 0x6c, 0xb8, 0x1e, + 0x0e, 0xb6, 0x56, 0x5c, 0x36, 0x77, 0x70, 0x5f, 0x58, 0x51, 0xe0, 0xff, 0x2d, 0x5b, 0xb0, 0x7b, 0x79, 0x0c, 0xbc, + 0x45, 0xc7, 0x24, 0xb8, 0x40, 0xdc, 0xb3, 0x5b, 0xb0, 0xc3, 0xc2, 0x5f, 0x70, 0x9d, 0x1c, 0xb3, 0x1d, 0x3e, 0x0a, + 0xbd, 0x82, 0xdd, 0xfa, 0x04, 0xb4, 0x0b, 0xb6, 0x06, 0xc8, 0xc6, 0xb6, 0xf8, 0xe8, 0xee, 0x70, 0x78, 0xeb, 0xf9, + 0xec, 0x01, 0x7f, 0x9c, 0xdf, 0x1d, 0x0e, 0x3b, 0xcf, 0xa8, 0xf7, 0x6e, 0x78, 0xc2, 0xde, 0xf3, 0x64, 0x72, 0x73, + 0xc5, 0xe3, 0xc9, 0x60, 0x70, 0xe3, 0x2f, 0x78, 0x3d, 0xbb, 0x01, 0xed, 0xc0, 0xf9, 0x42, 0xea, 0x9a, 0xbd, 0x5b, + 0x9e, 0x79, 0x0b, 0x1c, 0x9b, 0x5b, 0x38, 0x7a, 0xfb, 0x7d, 0xef, 0x8e, 0x47, 0xde, 0x2d, 0xa9, 0x98, 0x56, 0x5c, + 0x71, 0xbc, 0x6d, 0x71, 0x3f, 0x5d, 0xf1, 0x10, 0x1e, 0x61, 0x55, 0xa6, 0x37, 0xc1, 0x7b, 0x9f, 0xad, 0x34, 0x0b, + 0xdc, 0x03, 0xe6, 0x58, 0x93, 0x9d, 0xd0, 0x4c, 0xfc, 0x15, 0xf6, 0xcf, 0x8d, 0xea, 0x1f, 0x9a, 0xff, 0xa5, 0xee, + 0x27, 0x70, 0xfb, 0x22, 0x0b, 0x12, 0x7b, 0xcf, 0x6f, 0xd8, 0x3d, 0x37, 0x6c, 0xb3, 0x67, 0xa6, 0xec, 0x13, 0xa5, + 0xc6, 0x8f, 0x94, 0xba, 0xb6, 0x0c, 0x2b, 0x99, 0xbb, 0x2f, 0x23, 0x70, 0x38, 0x20, 0x3f, 0xdd, 0x21, 0x0e, 0x42, + 0xeb, 0x26, 0xab, 0xb9, 0xa2, 0x9c, 0x0b, 0x6d, 0x99, 0x79, 0x39, 0xb0, 0x98, 0xa5, 0x14, 0x1a, 0x0b, 0x00, 0x04, + 0x93, 0x42, 0x6b, 0xef, 0x65, 0x00, 0x39, 0x41, 0xc3, 0x1f, 0x9b, 0xab, 0xa2, 0xac, 0x65, 0x4b, 0x42, 0x94, 0xed, + 0x7a, 0x78, 0x89, 0x90, 0x69, 0xfd, 0xfe, 0x39, 0x91, 0xac, 0x4d, 0xaa, 0xab, 0x1a, 0x2d, 0x01, 0x15, 0x59, 0x02, + 0x26, 0x7e, 0xa5, 0xf9, 0x04, 0xe0, 0x49, 0xc7, 0x83, 0xea, 0x29, 0xaf, 0x99, 0x20, 0xb2, 0x8d, 0xca, 0x9f, 0x14, + 0xd7, 0x48, 0x46, 0x50, 0x3c, 0xad, 0x55, 0xc6, 0xc2, 0x30, 0x0f, 0x14, 0x90, 0x77, 0xef, 0x4e, 0x7d, 0x6b, 0x7f, + 0xec, 0xd8, 0xb3, 0xb5, 0x0a, 0xb5, 0x50, 0x53, 0xb8, 0xe4, 0x10, 0x5d, 0x41, 0x06, 0x0a, 0x19, 0x4f, 0x5e, 0x0f, + 0x2e, 0x27, 0xd1, 0x15, 0x17, 0xe8, 0x8c, 0xaf, 0x6f, 0xba, 0xe9, 0x2c, 0x7a, 0x5a, 0xcd, 0x27, 0xa4, 0x24, 0x3b, + 0x1c, 0xb2, 0x51, 0x55, 0x17, 0xeb, 0x69, 0x28, 0x7f, 0x7a, 0x08, 0xbe, 0x5e, 0x50, 0xaf, 0xc9, 0x2a, 0xd5, 0x4f, + 0xa9, 0x52, 0x5e, 0x34, 0xbc, 0xf4, 0x9f, 0x56, 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, 0xea, 0x9e, 0xac, 0xad, 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, 0x1f, 0x36, 0x3c, 0x02, 0x32, 0x3b, 0xe2, 0x33, 0x9b, 0x48, 0x3a, 0xa9, 0x73, + 0x05, 0xec, 0x76, 0xf6, 0x16, 0xe4, 0x88, 0x99, 0xfb, 0x0a, 0xd5, 0xb7, 0x68, 0xc0, 0x95, 0xb1, 0xf6, 0x35, 0xc9, + 0x58, 0x78, 0x55, 0x4e, 0xc3, 0x01, 0xc0, 0xd0, 0x65, 0xf4, 0xb5, 0xe5, 0x26, 0xcb, 0x7e, 0x2e, 0x20, 0x08, 0xa2, + 0x24, 0x1e, 0x1f, 0xf0, 0xbe, 0xac, 0x86, 0x1a, 0x25, 0x1f, 0xcb, 0x46, 0x2a, 0xbd, 0x12, 0xfd, 0xdd, 0x98, 0x4b, + 0x0c, 0xf8, 0xb6, 0x6a, 0x0b, 0x0a, 0xe7, 0xf9, 0xe1, 0x70, 0x9e, 0x8f, 0x8c, 0x67, 0x19, 0xa8, 0x56, 0xa6, 0x75, + 0x10, 0x9b, 0xf9, 0x62, 0xe1, 0x2f, 0x76, 0x4e, 0x22, 0xa2, 0x20, 0xb0, 0x23, 0xe1, 0x41, 0xa4, 0x7e, 0x59, 0x79, + 0xba, 0x53, 0x7d, 0xb6, 0x5f, 0xd8, 0x44, 0x7a, 0x41, 0xc9, 0xe4, 0x93, 0x60, 0xaf, 0xfa, 0x3b, 0x08, 0x1b, 0xc2, + 0x9b, 0x57, 0xbd, 0xce, 0x32, 0x35, 0x2b, 0x41, 0xc2, 0x8c, 0x39, 0x82, 0xc7, 0x61, 0xa7, 0xb1, 0x0d, 0x8f, 0x2d, + 0x38, 0x3a, 0x6f, 0xcd, 0xee, 0xd8, 0x8a, 0xdd, 0xaa, 0x3a, 0x2d, 0x78, 0x38, 0x1d, 0x5e, 0x06, 0xb8, 0xfa, 0xd6, + 0xe7, 0x9c, 0xdf, 0xd1, 0x09, 0xb6, 0x1e, 0xf0, 0x68, 0x22, 0x66, 0xeb, 0xa7, 0x91, 0x5a, 0x3c, 0xeb, 0x21, 0x5f, + 0xd0, 0xfa, 0x13, 0xb3, 0x3b, 0x93, 0x7c, 0x37, 0xe0, 0x8b, 0xc9, 0xfa, 0x69, 0x04, 0xaf, 0x3e, 0x05, 0x2b, 0x46, + 0xe6, 0xcc, 0xb2, 0xf5, 0xd3, 0x08, 0xc7, 0xec, 0xee, 0x69, 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, 0xa7, 0xd1, 0x9c, 0xad, 0xb0, 0x22, 0x1b, 0x1e, 0x0f, 0x2e, 0x27, 0x9b, 0x2b, + 0xbe, 0x06, 0xf2, 0xb3, 0xc9, 0xc6, 0x6c, 0x51, 0xb7, 0x5c, 0xcc, 0x36, 0x4f, 0xa3, 0xf9, 0x64, 0x05, 0x3d, 0x6b, + 0x0f, 0x98, 0xf7, 0x1a, 0x44, 0x28, 0x09, 0xa9, 0x29, 0x37, 0xbd, 0x1e, 0x5b, 0x8f, 0x83, 0x3b, 0xb6, 0xbe, 0x0c, + 0x6e, 0xd9, 0x7a, 0x0c, 0x44, 0x1c, 0xd4, 0xef, 0xde, 0x06, 0x16, 0x5f, 0xc4, 0xd6, 0x97, 0x26, 0x6d, 0xf3, 0x34, + 0x62, 0xee, 0xe0, 0x34, 0x70, 0xc1, 0xda, 0x64, 0xde, 0x8a, 0xc1, 0x25, 0x64, 0xe9, 0xc5, 0x6c, 0x33, 0xbc, 0x64, + 0xeb, 0x11, 0x4e, 0xf5, 0xc4, 0x67, 0x77, 0xfc, 0x96, 0x25, 0x7c, 0xd5, 0xc4, 0x57, 0x1b, 0xd0, 0x88, 0x1e, 0x65, + 0xd0, 0x57, 0x50, 0x33, 0x73, 0x5e, 0x5a, 0x18, 0x95, 0xfb, 0x16, 0x1c, 0x50, 0x90, 0xb6, 0x01, 0x82, 0x24, 0x9e, + 0xdd, 0xcb, 0x70, 0x7d, 0x23, 0x85, 0x01, 0x37, 0x81, 0x19, 0x30, 0x30, 0xfd, 0x0c, 0x7e, 0x58, 0xe9, 0x12, 0x21, + 0xce, 0x7e, 0x4a, 0x49, 0x32, 0xcf, 0x4f, 0x45, 0x9a, 0xbb, 0x85, 0xeb, 0x14, 0x66, 0x45, 0x81, 0xea, 0xa7, 0xa4, + 0x34, 0xb0, 0x50, 0x89, 0x4c, 0xa5, 0xe0, 0x97, 0xcd, 0x79, 0x94, 0x1d, 0xa3, 0x73, 0x9d, 0x5f, 0x4e, 0x9c, 0xd3, + 0x49, 0xdf, 0x7f, 0xe0, 0x18, 0xb6, 0x90, 0x81, 0x0b, 0x7f, 0xea, 0x09, 0xe3, 0xd4, 0x0a, 0xc4, 0x54, 0xf2, 0xec, + 0x29, 0x7c, 0x26, 0xb4, 0x3a, 0xba, 0xf0, 0xfd, 0xa0, 0xd0, 0x26, 0xe9, 0x16, 0x24, 0x29, 0x78, 0x8a, 0x9e, 0x73, + 0xde, 0x06, 0x2a, 0xc5, 0x88, 0x16, 0x44, 0xda, 0x5a, 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, + 0xaf, 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, 0x6f, 0x6a, 0xb1, 0xae, 0x82, 0x52, 0x29, 0x37, 0xe1, 0x67, 0x60, 0x98, 0xe1, + 0x87, 0x42, 0x6e, 0x13, 0x25, 0x72, 0x7e, 0x2c, 0x4a, 0xb1, 0x2c, 0x45, 0x95, 0xb4, 0x1b, 0x0a, 0x1e, 0x11, 0x6e, + 0x83, 0xc6, 0xcc, 0xed, 0x89, 0x2e, 0x5a, 0x11, 0xca, 0xb1, 0x59, 0xc7, 0x48, 0xa3, 0xcc, 0x4e, 0x76, 0x9d, 0x2c, + 0xb4, 0xdf, 0x57, 0x39, 0x64, 0x1d, 0xb0, 0x46, 0xf2, 0xf5, 0x9a, 0x43, 0xb7, 0x8d, 0xf2, 0xe2, 0xc1, 0xf3, 0x15, + 0x9c, 0xe6, 0x78, 0x62, 0x77, 0xbd, 0xee, 0x14, 0x89, 0x78, 0x85, 0x93, 0x2a, 0x1f, 0xc9, 0xc2, 0x71, 0xe7, 0x4e, + 0x6b, 0xb1, 0xaa, 0x5c, 0xd6, 0x53, 0x8b, 0x23, 0x02, 0x9f, 0xca, 0xa3, 0xbd, 0xd0, 0xb6, 0x28, 0x16, 0xc2, 0xe8, + 0xd1, 0x09, 0x3f, 0x29, 0x81, 0xf5, 0x75, 0x38, 0x2c, 0xfd, 0x88, 0xa3, 0xdf, 0x69, 0x34, 0x5a, 0x10, 0xd2, 0xf0, + 0xd4, 0x8b, 0x46, 0x8b, 0xba, 0xa8, 0xc3, 0xec, 0x3a, 0xd7, 0x03, 0x85, 0x61, 0x04, 0xea, 0x07, 0x57, 0x19, 0x7c, + 0x16, 0x21, 0x6a, 0x1e, 0x98, 0x66, 0x43, 0x38, 0xea, 0x02, 0x0f, 0xad, 0xa0, 0xc5, 0xcc, 0x7c, 0x14, 0x62, 0xf8, + 0x90, 0x2e, 0xce, 0x9f, 0x90, 0x95, 0x0f, 0xb0, 0x3b, 0x74, 0x17, 0xca, 0x39, 0x53, 0x31, 0xc0, 0x8f, 0x02, 0xf2, + 0x51, 0x02, 0x6e, 0x06, 0xc8, 0x1e, 0x59, 0x02, 0x88, 0x15, 0xa3, 0xa3, 0xc9, 0xe7, 0xbe, 0x17, 0x29, 0x78, 0x67, + 0x9f, 0xe5, 0x6a, 0xc2, 0x50, 0xf8, 0xc4, 0x40, 0x37, 0xbf, 0xf1, 0xdb, 0xf3, 0x16, 0x8c, 0xec, 0x92, 0x14, 0xaf, + 0x35, 0xc3, 0xfd, 0x06, 0xdc, 0x8e, 0x80, 0xb2, 0xa6, 0x3a, 0x26, 0xd9, 0xa6, 0x21, 0x92, 0x01, 0x33, 0x62, 0x44, + 0x50, 0x59, 0x2e, 0xfc, 0xef, 0x5e, 0x16, 0x05, 0x0e, 0xe0, 0x6a, 0x26, 0x83, 0xd7, 0x2e, 0x8c, 0x0a, 0x80, 0x73, + 0x1a, 0x3a, 0xa5, 0xbd, 0xaa, 0x3a, 0x24, 0xab, 0xe6, 0x07, 0xb3, 0x79, 0xd3, 0x30, 0x31, 0x22, 0x88, 0x2e, 0xc2, + 0x09, 0xa6, 0x57, 0xa4, 0xaf, 0x95, 0x9c, 0x8e, 0x56, 0x1d, 0xad, 0x25, 0x26, 0xe6, 0x8a, 0xe2, 0xaf, 0x01, 0x8f, + 0x1b, 0xbc, 0x3a, 0x49, 0xd3, 0x89, 0xea, 0xd1, 0xe3, 0xd7, 0x69, 0x3a, 0x29, 0x71, 0x57, 0xf8, 0x0d, 0xb8, 0x68, + 0xb6, 0xf9, 0xd0, 0x8f, 0x5f, 0x50, 0xc4, 0x45, 0x0d, 0xae, 0xbc, 0x53, 0x7d, 0xa5, 0xfa, 0x08, 0x6a, 0xe1, 0x89, + 0x91, 0xb5, 0xf0, 0xe4, 0x92, 0xb5, 0x16, 0x04, 0x33, 0x9b, 0x03, 0x17, 0xf2, 0x2b, 0xa5, 0x88, 0x37, 0x91, 0x50, + 0x8b, 0x41, 0xeb, 0x31, 0x73, 0x56, 0x8d, 0x16, 0x2a, 0x33, 0x42, 0xfb, 0xb6, 0x16, 0x9d, 0xdf, 0xc8, 0x4f, 0x79, + 0x6a, 0x5f, 0xb6, 0xc7, 0xf9, 0x78, 0x8f, 0xee, 0xaa, 0xb3, 0xcc, 0xa4, 0x8c, 0x4f, 0x66, 0x09, 0x0a, 0x77, 0x09, + 0x36, 0x20, 0xc9, 0x7e, 0xad, 0x03, 0x64, 0xd4, 0x5e, 0xfb, 0x5d, 0x67, 0xf9, 0xea, 0x66, 0x6b, 0x28, 0x2a, 0xb5, + 0x92, 0x14, 0x07, 0x19, 0xae, 0xdb, 0xca, 0x87, 0x8b, 0x0b, 0xe8, 0x19, 0x23, 0x91, 0x79, 0xfe, 0x44, 0xbe, 0x04, + 0xe7, 0x8c, 0xb3, 0x42, 0x60, 0xc2, 0x58, 0xbd, 0x6b, 0x2d, 0x95, 0x86, 0x14, 0x63, 0x47, 0xa3, 0x2c, 0xab, 0x2c, + 0x5d, 0x66, 0x6b, 0x09, 0x5b, 0x96, 0x93, 0x5b, 0xd8, 0x32, 0x93, 0xd5, 0x7c, 0x5f, 0x71, 0x07, 0xe5, 0x9b, 0xad, + 0x33, 0xbe, 0x97, 0xc8, 0xde, 0x6d, 0xa0, 0x84, 0xeb, 0xd1, 0x5f, 0x90, 0x7e, 0x9b, 0x61, 0x9c, 0x72, 0x5b, 0x49, + 0x0b, 0x70, 0xfa, 0x87, 0xc3, 0xfb, 0x0a, 0x83, 0x06, 0x47, 0x18, 0x47, 0xd6, 0xef, 0xdf, 0x56, 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, 0x09, 0xfe, 0xf6, + 0xcb, 0xfc, 0x70, 0x58, 0x67, 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, 0x63, 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, 0xe9, 0x73, 0x20, 0x2d, 0xeb, 0xf7, 0xa3, 0xeb, 0xcb, 0xe9, + 0xf3, 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, 0x0f, 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, 0x56, 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, 0x6d, 0x30, 0x7d, 0x7d, 0xbb, 0x2d, 0xf2, 0x53, 0x13, 0x13, 0xd6, 0x63, 0x45, 0xdf, 0xbc, + 0x0b, 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, 0xd1, 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, 0x93, 0x92, + 0xc3, 0x73, 0x8e, 0x39, 0xa1, 0xb4, 0x22, 0xac, 0xe2, 0x8b, 0x0c, 0xe5, 0xba, 0x53, 0x0a, 0x26, 0x39, 0x24, 0x18, + 0xfe, 0xaa, 0x79, 0x13, 0x2b, 0x10, 0x76, 0xcd, 0xbc, 0x1a, 0x3d, 0xa9, 0x92, 0xb0, 0x14, 0x70, 0x54, 0x66, 0x9e, + 0x61, 0x6f, 0x78, 0x62, 0x18, 0x39, 0x58, 0xee, 0x8f, 0xea, 0x44, 0xe4, 0x1e, 0x5d, 0x60, 0x54, 0x16, 0x9e, 0x37, + 0x74, 0xa5, 0x41, 0x25, 0xd9, 0xf1, 0x57, 0x5c, 0x03, 0x6a, 0x6b, 0x8c, 0x18, 0x0a, 0x18, 0x05, 0xaf, 0xed, 0x0f, + 0x21, 0x8b, 0xb2, 0xf5, 0x1b, 0x1c, 0xf3, 0x59, 0xc9, 0x5d, 0xef, 0x70, 0x16, 0x5a, 0x42, 0x9e, 0xdc, 0x31, 0x48, + 0xd3, 0x58, 0x1a, 0x01, 0x27, 0x22, 0xd9, 0xc6, 0x52, 0x38, 0x02, 0x08, 0x08, 0x74, 0x53, 0x66, 0x18, 0xd3, 0xc1, + 0xc8, 0xf3, 0xa4, 0x67, 0xbc, 0x57, 0xe1, 0x29, 0xa4, 0xc9, 0xf6, 0xf5, 0xfc, 0xbd, 0x11, 0x64, 0xe5, 0x96, 0x73, + 0x3c, 0x2c, 0xbe, 0x71, 0xf6, 0x55, 0x4e, 0x9e, 0x62, 0x96, 0x91, 0xde, 0x29, 0xe6, 0x05, 0xfc, 0xa9, 0x2c, 0xf5, + 0x39, 0x4a, 0x6f, 0x99, 0x4f, 0x56, 0x91, 0x74, 0xe9, 0x6d, 0xfa, 0xfd, 0x78, 0xa4, 0x0e, 0x35, 0x7f, 0x1f, 0x8f, + 0xe4, 0x19, 0xb6, 0x61, 0x09, 0x0b, 0xad, 0x82, 0x31, 0x80, 0x24, 0x36, 0x22, 0x1a, 0x8c, 0xf6, 0xe6, 0x70, 0x38, + 0xdf, 0x98, 0xb3, 0x64, 0x0f, 0xae, 0xaf, 0x3c, 0x31, 0xef, 0xc0, 0x97, 0x79, 0x4c, 0x10, 0xb1, 0x99, 0xb7, 0x61, + 0x35, 0x78, 0xb0, 0x83, 0xeb, 0x23, 0xb6, 0x28, 0xd6, 0x3a, 0x96, 0xca, 0x3a, 0x38, 0xad, 0x63, 0xd3, 0x8c, 0x94, + 0x22, 0xfb, 0x1c, 0xfb, 0x7b, 0x37, 0xb8, 0xba, 0x36, 0x06, 0xb5, 0xc6, 0x1d, 0xe6, 0xce, 0xa9, 0x80, 0x7a, 0x4c, + 0x57, 0x50, 0x3d, 0xcb, 0xc9, 0x97, 0xdf, 0xda, 0x39, 0x20, 0x68, 0x04, 0x02, 0x17, 0x0d, 0xb4, 0x6a, 0x97, 0x72, + 0xde, 0x05, 0x84, 0xf8, 0x26, 0x05, 0x7d, 0x3a, 0x83, 0x4d, 0x6c, 0x3e, 0x81, 0x58, 0x34, 0xdd, 0xe7, 0x5a, 0x33, + 0x5f, 0x8c, 0x68, 0x67, 0xd6, 0xdd, 0x22, 0xb7, 0x5a, 0x88, 0x64, 0xf4, 0x6c, 0x33, 0xe1, 0xa2, 0x43, 0x39, 0x23, + 0x01, 0x13, 0xb4, 0xb6, 0x52, 0xf2, 0xb9, 0xee, 0x75, 0x82, 0xf6, 0x40, 0xd2, 0xba, 0x7f, 0xb3, 0xe8, 0x8c, 0x92, + 0x93, 0xeb, 0x4d, 0xce, 0x20, 0x05, 0x0b, 0xb6, 0x97, 0x39, 0xe1, 0x06, 0xf8, 0xc4, 0x66, 0xc9, 0x69, 0x1a, 0xe4, + 0xb1, 0x30, 0x1e, 0x79, 0x6d, 0x7e, 0x59, 0x40, 0x87, 0x92, 0x45, 0x23, 0xc4, 0x03, 0xec, 0x1c, 0x92, 0xab, 0x02, + 0x75, 0xd3, 0x40, 0x57, 0xae, 0x9c, 0x29, 0xa6, 0xc0, 0x85, 0x50, 0x10, 0xb5, 0xa3, 0x93, 0xa8, 0x9c, 0xf7, 0x49, + 0x75, 0x99, 0x4f, 0x0b, 0x69, 0x1a, 0xc8, 0xa7, 0x95, 0x63, 0x1e, 0xd8, 0xd9, 0xc6, 0x35, 0x81, 0x81, 0x4e, 0xed, + 0x6b, 0x51, 0xce, 0xb1, 0x8a, 0xe8, 0x7d, 0xfe, 0xa1, 0xb2, 0xa7, 0x0f, 0x22, 0x6c, 0x54, 0xa0, 0xb1, 0x94, 0x18, + 0x1b, 0x39, 0xfe, 0x2d, 0x51, 0x36, 0x64, 0x08, 0x08, 0x21, 0x6d, 0xe4, 0xf4, 0xc3, 0xfa, 0xf2, 0x36, 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, 0x3a, 0x50, + 0x76, 0x9a, 0x91, 0xe0, 0xb2, 0x7b, 0x83, 0x44, 0xa9, 0xaf, 0x48, 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, 0x4f, 0xb4, 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, 0xec, 0x65, + 0x60, 0xf9, 0x2b, 0x88, 0x1f, 0x6d, 0x7c, 0x38, 0xfc, 0x59, 0x53, 0x88, 0xed, 0x9f, 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, 0x8f, 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, 0x93, 0x7d, 0x2d, 0xff, 0x17, 0xf4, 0x32, 0xe8, 0x6f, 0xe1, 0x96, + 0xd7, 0xfc, 0x6e, 0x41, 0xa4, 0x99, 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, 0xf8, 0xdb, + 0x8b, 0x4f, 0x6f, 0x7e, 0xf9, 0x61, 0xf1, 0xe6, 0xdd, 0xeb, 0x37, 0xef, 0xde, 0x7c, 0xfa, 0x8d, 0x20, 0x3c, 0xa6, + 0x42, 0x65, 0xf8, 0xf0, 0xfe, 0xe6, 0x8d, 0x93, 0xc1, 0xf6, 0x66, 0xc8, 0xda, 0x37, 0x72, 0x30, 0x04, 0x22, 0x1b, + 0x84, 0x0c, 0xb2, 0x53, 0xdb, 0xfe, 0x4c, 0xcc, 0x31, 0xf6, 0x4e, 0x60, 0xb2, 0x05, 0x9c, 0x63, 0x99, 0x97, 0x8c, + 0xc8, 0x55, 0xa1, 0xf5, 0x03, 0x5a, 0xf0, 0x16, 0x5c, 0x64, 0xd2, 0xfc, 0xee, 0x17, 0x82, 0xd8, 0xa7, 0x95, 0x94, + 0xfb, 0x6a, 0x5b, 0xf3, 0x7c, 0x7b, 0xbf, 0x97, 0x70, 0xfe, 0x73, 0x69, 0x44, 0x2d, 0xc0, 0x01, 0xf8, 0x1c, 0xfe, + 0xb8, 0xd2, 0x96, 0x34, 0x99, 0x45, 0xfb, 0x19, 0x43, 0xd0, 0xa5, 0xc1, 0x07, 0xb1, 0x47, 0x5e, 0xea, 0x93, 0x85, + 0x04, 0xee, 0x88, 0xe1, 0xd3, 0x8a, 0xa0, 0x57, 0x8c, 0x28, 0x2e, 0xb9, 0x42, 0xa5, 0x94, 0xfc, 0x1b, 0x65, 0x17, + 0x15, 0x72, 0x56, 0xb0, 0x7b, 0x45, 0x8e, 0x8c, 0x1f, 0x04, 0x13, 0x5f, 0x0e, 0xee, 0xbf, 0xc4, 0x3b, 0x9c, 0x29, + 0x8e, 0xe4, 0x84, 0x3f, 0x64, 0x18, 0xd8, 0x9f, 0x83, 0xcf, 0xab, 0xc3, 0xbc, 0xbc, 0xd1, 0xa7, 0xdc, 0x92, 0x8f, + 0x27, 0xcb, 0x2b, 0x30, 0xd8, 0x2f, 0x55, 0x73, 0xd7, 0xbc, 0x9e, 0x2d, 0xe7, 0x6c, 0x3f, 0x8b, 0xe6, 0xc1, 0x1d, + 0x9b, 0x65, 0xf3, 0x60, 0xd5, 0xf0, 0x35, 0xbb, 0xe5, 0x6b, 0xab, 0x6a, 0x6b, 0xbb, 0x6a, 0x93, 0x0d, 0xbf, 0x05, + 0x09, 0xe1, 0x26, 0xf3, 0x80, 0xf7, 0xf8, 0xce, 0x67, 0x1b, 0x90, 0x68, 0x57, 0x6c, 0x03, 0x17, 0xb1, 0x35, 0xff, + 0xa1, 0xf2, 0x36, 0xac, 0x64, 0xe7, 0x63, 0x96, 0xe3, 0xfc, 0xf3, 0xe1, 0x01, 0xed, 0x85, 0xfa, 0xd9, 0xa5, 0x7a, + 0x36, 0x51, 0x76, 0xb3, 0xcd, 0x68, 0x71, 0x9f, 0x56, 0x9b, 0x30, 0x43, 0xcf, 0x72, 0xf8, 0x68, 0x2b, 0x05, 0x3f, + 0xbd, 0xc0, 0x2f, 0xd9, 0x51, 0x5b, 0x69, 0xdb, 0xae, 0x4a, 0x6c, 0x05, 0x2d, 0x8a, 0xac, 0x56, 0x78, 0x60, 0xce, + 0xaf, 0x61, 0x01, 0x63, 0xcf, 0x71, 0xce, 0x6b, 0x7f, 0x84, 0x8c, 0xf7, 0x0e, 0x00, 0x5a, 0xe6, 0x38, 0xc0, 0x23, + 0x56, 0x8c, 0xa2, 0xc1, 0x3b, 0xbf, 0x54, 0x56, 0x2b, 0xcd, 0x49, 0x68, 0x1b, 0xb1, 0x6a, 0x39, 0x52, 0x35, 0x23, + 0xd2, 0x07, 0xe9, 0x79, 0xdf, 0x23, 0xaa, 0xc1, 0x9e, 0xcc, 0xeb, 0xc0, 0x3e, 0xbd, 0x6c, 0xad, 0xea, 0xce, 0xef, + 0xa9, 0xd2, 0x25, 0x47, 0xb6, 0xfc, 0x74, 0x19, 0x3e, 0xa8, 0x3f, 0x25, 0xd7, 0x87, 0x02, 0x47, 0x78, 0xac, 0x02, + 0xce, 0xd7, 0x2b, 0xd1, 0xee, 0x44, 0xd8, 0x95, 0x4b, 0x40, 0x88, 0x2f, 0x69, 0x9a, 0xe3, 0x71, 0x44, 0x13, 0x11, + 0x36, 0x31, 0xfa, 0x0b, 0xbb, 0x0f, 0x25, 0x96, 0xf3, 0x5c, 0x83, 0x92, 0x4b, 0x06, 0xef, 0x49, 0x7b, 0x0d, 0x9a, + 0xe5, 0x55, 0xa9, 0xc9, 0x44, 0x0e, 0xca, 0x87, 0x43, 0x01, 0x7b, 0xa9, 0xf1, 0xd3, 0x84, 0x9f, 0xb0, 0xbc, 0xb5, + 0xb7, 0xa6, 0x14, 0x95, 0x34, 0x40, 0x05, 0x3e, 0x66, 0xf0, 0xbf, 0x3b, 0x43, 0x2c, 0x98, 0xa2, 0xe3, 0x87, 0x33, + 0x31, 0xb7, 0x9e, 0x5b, 0x65, 0x1d, 0x65, 0x6b, 0x94, 0x13, 0xf0, 0x6f, 0xa9, 0x8e, 0x93, 0x44, 0x38, 0xf5, 0x1e, + 0x71, 0x51, 0xf7, 0x72, 0x88, 0xba, 0x61, 0x6f, 0x2a, 0x1d, 0x6c, 0x39, 0x4d, 0x83, 0x23, 0xf1, 0x2b, 0xf5, 0xd9, + 0xfb, 0xcc, 0xe2, 0x51, 0x47, 0x36, 0xa2, 0x24, 0x8d, 0x63, 0x91, 0xc3, 0xf6, 0xbe, 0x90, 0xfb, 0x7f, 0xbf, 0x0f, + 0xe1, 0xa4, 0x55, 0x90, 0x94, 0x9e, 0x40, 0x44, 0x38, 0x3a, 0xfc, 0x88, 0xf0, 0x44, 0xaa, 0x0a, 0x9f, 0xd4, 0x27, + 0x6e, 0xcc, 0xee, 0x85, 0x39, 0xaa, 0xb7, 0x00, 0xc3, 0x58, 0x6f, 0x2d, 0x42, 0x12, 0xad, 0x34, 0xa3, 0xad, 0x07, + 0xc4, 0x88, 0xf7, 0x6b, 0x8b, 0x0c, 0xc6, 0xda, 0x92, 0x48, 0x00, 0xbf, 0x23, 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, 0x75, 0x94, 0x4e, 0x12, 0xeb, 0xfb, 0xae, 0x52, 0xc1, 0x66, 0x73, 0x83, 0xfa, 0xb2, + 0xa3, 0xe4, 0x97, 0xe0, 0xa4, 0xe3, 0x24, 0x8b, 0x1c, 0x44, 0x2d, 0x2a, 0xe7, 0x26, 0x09, 0x4b, 0xbb, 0x3a, 0xd5, + 0x66, 0xbd, 0x2e, 0xca, 0xba, 0x7a, 0x25, 0x22, 0x45, 0xef, 0xa3, 0x1e, 0x3d, 0x91, 0x90, 0x0a, 0xad, 0x4a, 0xed, + 0xf2, 0x08, 0xdc, 0x36, 0xb5, 0x62, 0x5b, 0x2e, 0x61, 0x89, 0x1a, 0xff, 0x09, 0xfa, 0x28, 0x17, 0x0f, 0x32, 0x40, + 0xa3, 0xe3, 0xa9, 0x79, 0xeb, 0x91, 0x57, 0x8e, 0xf2, 0x4b, 0xab, 0x4d, 0xfa, 0x05, 0x90, 0x19, 0xed, 0x1f, 0x2d, + 0x25, 0x90, 0x19, 0x98, 0x49, 0x4b, 0x43, 0x22, 0x47, 0x31, 0x4b, 0xf3, 0x3f, 0x70, 0xc5, 0x56, 0x88, 0x34, 0xac, + 0xe6, 0x1e, 0x7f, 0x51, 0x79, 0xb5, 0x5c, 0xcb, 0x4c, 0x73, 0xb3, 0xc4, 0xb1, 0x62, 0x71, 0x51, 0xaf, 0x2b, 0x91, + 0x05, 0x42, 0x1c, 0x61, 0x1a, 0xeb, 0xa9, 0x37, 0x4a, 0xab, 0x0f, 0x48, 0x28, 0xf3, 0x03, 0xf6, 0x76, 0xec, 0xf5, + 0x20, 0x0b, 0x71, 0x6c, 0x39, 0xd8, 0x6c, 0xbd, 0x4f, 0x65, 0x2a, 0xe2, 0xb3, 0xba, 0x38, 0xdb, 0x54, 0xe2, 0xac, + 0x4e, 0xc4, 0xd9, 0x77, 0x90, 0xf3, 0xbb, 0x33, 0x2a, 0xfa, 0xec, 0x21, 0xad, 0x93, 0x62, 0x53, 0xd3, 0x93, 0xd7, + 0x58, 0xc6, 0x77, 0x67, 0xc4, 0x55, 0x73, 0x46, 0x23, 0x19, 0x8f, 0xce, 0x3e, 0x64, 0x40, 0xf2, 0x7a, 0x96, 0xae, + 0x60, 0xf0, 0xce, 0xc2, 0x3c, 0x3e, 0x2b, 0xc5, 0x1d, 0x58, 0x9c, 0xca, 0xce, 0xf7, 0x20, 0xc3, 0x2a, 0xfc, 0x43, + 0x9c, 0x01, 0xb4, 0xeb, 0x59, 0x5a, 0x9f, 0xa5, 0xd5, 0x59, 0x5e, 0xd4, 0x67, 0x4a, 0x0a, 0x87, 0x30, 0x7e, 0x78, + 0x4f, 0x5f, 0xd9, 0xe5, 0x6d, 0x16, 0x77, 0x59, 0xe4, 0x4f, 0xd1, 0xab, 0x88, 0x98, 0x34, 0x2a, 0xe1, 0xb5, 0xfb, + 0xdb, 0xe6, 0xfe, 0xe1, 0x75, 0x63, 0xf7, 0xb3, 0x3b, 0x46, 0x74, 0x41, 0x3d, 0x5e, 0x49, 0x4a, 0x05, 0x05, 0x04, + 0x4e, 0x34, 0x6b, 0x3c, 0xb8, 0xe3, 0x80, 0x57, 0x03, 0x5b, 0xb2, 0xb5, 0xcf, 0xaf, 0x63, 0x19, 0xa6, 0xbd, 0x09, + 0xf0, 0xaf, 0xb2, 0x37, 0x5d, 0x07, 0x4b, 0xbc, 0x6f, 0x21, 0xdb, 0xd0, 0x9b, 0x57, 0xfc, 0x85, 0x97, 0xab, 0xbf, + 0xd9, 0x3f, 0x01, 0x08, 0x03, 0x62, 0x56, 0x7d, 0x34, 0x71, 0xef, 0xac, 0x2c, 0x3b, 0x27, 0xcb, 0xae, 0x87, 0x7e, + 0x4d, 0x62, 0x54, 0x5a, 0x59, 0x4a, 0x27, 0x4b, 0x09, 0x59, 0xc0, 0x27, 0x46, 0x53, 0x1b, 0x01, 0x84, 0xed, 0x28, + 0x95, 0x2f, 0x54, 0x5e, 0x44, 0xe1, 0x9c, 0xe0, 0x79, 0x22, 0x46, 0xf7, 0x56, 0x32, 0x60, 0x38, 0x84, 0x60, 0x0e, + 0xda, 0x62, 0x6f, 0xe8, 0x26, 0xe2, 0xaf, 0xd7, 0x45, 0xf9, 0x26, 0x26, 0x9f, 0x82, 0xdd, 0xc9, 0xc7, 0x25, 0x3c, + 0x2e, 0x4f, 0x3e, 0x0e, 0xd1, 0x23, 0xe1, 0xe4, 0x63, 0xf0, 0x3d, 0x92, 0xf3, 0xba, 0xeb, 0x71, 0x82, 0xdc, 0x42, + 0xba, 0xbf, 0x1d, 0x93, 0x00, 0xcd, 0x6b, 0x58, 0x8e, 0x9a, 0x8a, 0x6b, 0x66, 0xc6, 0x78, 0xde, 0xe8, 0xfd, 0xb1, + 0xe3, 0x2d, 0x53, 0x28, 0x66, 0x31, 0xaf, 0xe1, 0xf7, 0xac, 0x0a, 0xd4, 0x5d, 0x6f, 0x93, 0xdc, 0x32, 0xab, 0xe7, + 0x68, 0xf7, 0x7d, 0x5f, 0x27, 0x82, 0xda, 0xdf, 0x61, 0xcf, 0x33, 0xeb, 0x5d, 0x15, 0x03, 0x97, 0x2a, 0xd9, 0x21, + 0x53, 0xd5, 0xf4, 0x40, 0xa5, 0x34, 0x78, 0x7a, 0x69, 0x5d, 0xbe, 0x54, 0xda, 0xc8, 0x33, 0xcd, 0x6f, 0x00, 0x2f, + 0xa6, 0x2e, 0x8b, 0xdd, 0x57, 0xf7, 0x15, 0xdc, 0xc6, 0xfb, 0xfd, 0x65, 0xe5, 0x99, 0x9f, 0xb8, 0x00, 0xec, 0x4d, + 0x85, 0xd6, 0x09, 0x94, 0x1a, 0xd6, 0xe1, 0xcb, 0x44, 0x44, 0x7f, 0xb4, 0xcb, 0x75, 0xe6, 0x3a, 0x60, 0x44, 0x11, + 0xbf, 0x8d, 0x47, 0x7f, 0x80, 0xe2, 0xda, 0xd8, 0x03, 0xc2, 0x3a, 0x24, 0xf4, 0x19, 0x01, 0x48, 0x3d, 0xe6, 0x28, + 0x01, 0xcd, 0x8a, 0xe6, 0x8e, 0xc9, 0xcf, 0xf5, 0x95, 0xd2, 0xdf, 0x2f, 0x2b, 0x8f, 0xcc, 0x29, 0x6d, 0x33, 0x8d, + 0xd5, 0x9a, 0x4a, 0x20, 0xbc, 0xa2, 0x92, 0x55, 0xf8, 0x6c, 0xde, 0x88, 0x7e, 0x5f, 0x1e, 0xe1, 0x69, 0xf5, 0xc3, + 0x16, 0xe3, 0x5b, 0x01, 0xd1, 0x48, 0x00, 0xf4, 0x13, 0xc0, 0xbc, 0xc8, 0x66, 0x76, 0x1f, 0x07, 0x54, 0x29, 0xd1, + 0x34, 0xce, 0xe6, 0xf9, 0x2d, 0xbd, 0x29, 0x3b, 0xe8, 0xd4, 0xa9, 0x02, 0x17, 0x5c, 0x95, 0x8c, 0x57, 0xd6, 0x13, + 0xf9, 0xfc, 0xe6, 0x76, 0x93, 0x66, 0xf1, 0xfb, 0xf2, 0x9f, 0x38, 0xb6, 0xba, 0x0e, 0x8f, 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, 0x57, + 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, 0x8a, 0xaa, 0xc8, 0xee, 0xe1, 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, 0xe8, + 0xc1, 0x16, 0xe7, 0x4f, 0x37, 0xd4, 0x7e, 0xcc, 0x8d, 0x7a, 0x18, 0x68, 0x2d, 0x78, 0x53, 0x10, 0xeb, 0xef, 0x87, + 0x8e, 0x6c, 0xef, 0xb5, 0xc8, 0x68, 0xf2, 0xd9, 0xcf, 0x3f, 0x94, 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, 0x5b, 0xea, 0xb8, 0x47, 0xd9, 0xe6, 0xef, 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, 0x56, 0x7b, 0x4b, 0x90, 0x9f, 0x36, 0x76, 0xa3, 0x30, 0x31, 0x82, 0x44, 0xdd, + 0xae, 0x0c, 0xe4, 0x87, 0x0f, 0x38, 0x1d, 0x8f, 0x3d, 0x65, 0xcc, 0xad, 0x4c, 0x2f, 0xd3, 0xb9, 0x92, 0x6f, 0xe4, + 0x5e, 0xfa, 0xd8, 0x4b, 0xb0, 0x73, 0xc0, 0x1b, 0x48, 0x1b, 0x78, 0x03, 0xdb, 0x85, 0xd7, 0x06, 0x09, 0x33, 0x02, + 0x6c, 0x71, 0x7c, 0x8c, 0x94, 0xc0, 0x10, 0x8e, 0xb3, 0x14, 0x80, 0x69, 0xf4, 0x65, 0xb6, 0xb2, 0x2f, 0xb3, 0x5a, + 0xb3, 0xa5, 0x72, 0xba, 0x77, 0x6e, 0xdd, 0xce, 0x27, 0x12, 0x00, 0x4c, 0xea, 0x1c, 0x88, 0x33, 0x13, 0xec, 0xd2, + 0x24, 0xb2, 0x7c, 0x0c, 0xf3, 0x3b, 0xf1, 0xba, 0x2c, 0x56, 0xaa, 0x2b, 0xda, 0x3e, 0x33, 0xf9, 0x8c, 0x74, 0x12, + 0x2a, 0xa0, 0xa0, 0x90, 0x6b, 0x7d, 0xfa, 0x2e, 0x7c, 0x17, 0x14, 0x1a, 0x98, 0xad, 0xc2, 0x3d, 0x4d, 0xd6, 0x48, + 0xbd, 0x51, 0xf5, 0xfb, 0xe4, 0x1a, 0x48, 0x75, 0xe6, 0xd0, 0xb2, 0x27, 0x15, 0x06, 0x88, 0x1d, 0xf5, 0x19, 0x09, + 0x75, 0x20, 0xf5, 0x80, 0x21, 0x44, 0xdb, 0xf4, 0xf1, 0x27, 0x43, 0xa2, 0x0b, 0xb0, 0x85, 0x68, 0x03, 0x3f, 0xfe, + 0x04, 0xfb, 0x2c, 0x08, 0x8f, 0x69, 0xfe, 0x16, 0x92, 0x8e, 0x0d, 0x9c, 0x56, 0x9f, 0x82, 0x0f, 0x92, 0x1c, 0x4c, + 0xd4, 0xc1, 0xcb, 0xfd, 0xa5, 0xdf, 0x87, 0x2d, 0x3b, 0x97, 0x52, 0x1d, 0x2b, 0xf5, 0xb6, 0xad, 0xfd, 0x20, 0xda, + 0x82, 0x23, 0x8b, 0xf8, 0xfb, 0x0c, 0x11, 0xc1, 0xcc, 0x20, 0xc2, 0xae, 0x85, 0xba, 0xdb, 0x53, 0x6a, 0x59, 0xd4, + 0xdb, 0x9e, 0x52, 0xea, 0x36, 0x0c, 0xdf, 0x4d, 0x30, 0x53, 0xdc, 0xf0, 0x3f, 0x32, 0x2f, 0xd4, 0x1b, 0x8f, 0x45, + 0x81, 0xee, 0xf9, 0xfb, 0x25, 0xaf, 0x66, 0x1b, 0x65, 0xc2, 0xbc, 0xe3, 0xcb, 0x59, 0x28, 0xbb, 0x5a, 0x1a, 0x77, + 0x3e, 0x7b, 0x4b, 0x35, 0x1f, 0xfc, 0xc3, 0x21, 0x81, 0x78, 0xa3, 0xf8, 0xea, 0xae, 0x91, 0x5b, 0xd7, 0x64, 0x73, + 0x55, 0x02, 0xea, 0xf7, 0xf9, 0x1a, 0xf7, 0x5b, 0xac, 0x7f, 0xf7, 0x34, 0xc8, 0x58, 0xcd, 0x70, 0xc5, 0x14, 0x3e, + 0x05, 0x80, 0xc1, 0xe1, 0x54, 0x90, 0x16, 0x78, 0xc3, 0xcb, 0xe1, 0xe5, 0x64, 0x43, 0x26, 0xdd, 0x8d, 0x8f, 0xdc, + 0x59, 0xa0, 0xea, 0xfd, 0x86, 0xe2, 0xa4, 0x41, 0xa2, 0xb1, 0xd7, 0xe0, 0x8b, 0x2c, 0xa3, 0x5c, 0x34, 0x71, 0x1f, + 0x93, 0xaf, 0xf4, 0x00, 0xe6, 0x2a, 0x94, 0x00, 0xd1, 0x6f, 0x2c, 0x8b, 0x8d, 0x68, 0x5b, 0x6c, 0x60, 0x29, 0x55, + 0x73, 0xbd, 0x9a, 0x3e, 0x7b, 0x25, 0x9a, 0xf7, 0xd1, 0x8c, 0x53, 0x1a, 0x0d, 0x38, 0x4e, 0xa3, 0x70, 0xfb, 0xfe, + 0x5e, 0x94, 0xcb, 0x0c, 0x2c, 0xd9, 0x2a, 0x9c, 0xe2, 0xb2, 0x51, 0x67, 0xc4, 0x8b, 0x3c, 0x56, 0x00, 0x1d, 0x8f, + 0x09, 0x80, 0xea, 0x82, 0x80, 0x8a, 0x68, 0x29, 0xbd, 0x15, 0x5a, 0x2c, 0xd4, 0x1b, 0x8e, 0x52, 0xf8, 0x23, 0xfd, + 0x79, 0x90, 0x4f, 0x01, 0x88, 0x5d, 0x1f, 0x47, 0xaf, 0x8b, 0x92, 0x3e, 0x55, 0xcc, 0x72, 0x39, 0x98, 0xc0, 0xae, + 0x4e, 0x64, 0xa8, 0x15, 0xe4, 0xad, 0xba, 0xf2, 0x56, 0x26, 0x6f, 0x63, 0x9c, 0x92, 0x1f, 0xb9, 0xe9, 0x58, 0x23, + 0x06, 0x5e, 0x79, 0x5a, 0xa7, 0x09, 0xd2, 0xe4, 0x02, 0x18, 0x86, 0xf8, 0x36, 0xf3, 0x5e, 0x78, 0x8e, 0x54, 0x05, + 0xc9, 0x6c, 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, 0x51, 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, + 0x72, 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, 0x7c, 0x0d, 0x62, 0x74, 0x7d, 0xd5, 0x59, 0x43, 0xcd, 0x34, 0xaa, + 0x3c, 0x82, 0x4e, 0x1d, 0xc0, 0x93, 0x82, 0x97, 0x5a, 0xfd, 0x78, 0x38, 0x78, 0xe6, 0x07, 0x7f, 0x99, 0xe9, 0x5b, + 0x88, 0x89, 0x72, 0xaa, 0x11, 0x12, 0x57, 0x4a, 0x12, 0xf1, 0xf1, 0xa2, 0x65, 0xc5, 0xa8, 0x0c, 0x1f, 0x78, 0xa5, + 0xca, 0x57, 0xa7, 0x2a, 0x2f, 0x46, 0xda, 0x96, 0xc0, 0x6b, 0xf2, 0x0f, 0x91, 0x6b, 0xde, 0xfa, 0xba, 0xab, 0x0c, + 0x7d, 0x2b, 0x2b, 0xd0, 0x11, 0x6c, 0x65, 0x29, 0x39, 0xe0, 0x93, 0xea, 0xae, 0x5a, 0xb5, 0x3e, 0xa7, 0x6c, 0x23, + 0xdc, 0xe4, 0xd7, 0xb1, 0x83, 0x23, 0xe5, 0x37, 0x78, 0x2e, 0x80, 0xbd, 0x06, 0xec, 0xcd, 0x39, 0x2b, 0x9a, 0x47, + 0x87, 0xb4, 0x2d, 0xd0, 0xc8, 0xcc, 0xed, 0x5c, 0xdd, 0xb7, 0xe5, 0x51, 0x1a, 0x43, 0x64, 0xda, 0x23, 0xd3, 0xc1, + 0x66, 0x94, 0xff, 0x96, 0xf2, 0x5b, 0x85, 0x63, 0xe0, 0xdb, 0xa9, 0x77, 0x00, 0x55, 0x4f, 0x1b, 0x64, 0xac, 0x19, + 0x86, 0x56, 0x76, 0xb9, 0x14, 0x5a, 0x82, 0x96, 0xba, 0x09, 0x82, 0xf3, 0x23, 0xa2, 0x1c, 0x01, 0xe8, 0x22, 0x05, + 0x4c, 0xf0, 0x53, 0xda, 0xee, 0x7e, 0x7f, 0x9d, 0x7a, 0xe4, 0xde, 0x15, 0x6a, 0x94, 0x50, 0x82, 0xb1, 0x9f, 0x68, + 0xcc, 0xa0, 0xa3, 0x2b, 0x72, 0xc2, 0xb3, 0x56, 0x87, 0x75, 0xdd, 0x94, 0x41, 0x59, 0x1c, 0xf3, 0x6a, 0x3a, 0xfb, + 0xfd, 0xc9, 0xbe, 0x6e, 0x90, 0x85, 0xfc, 0x77, 0xd6, 0x43, 0x32, 0xe8, 0x1e, 0x84, 0x42, 0xf4, 0xe6, 0xc1, 0x0c, + 0xff, 0x63, 0x1b, 0x9e, 0x7d, 0xc3, 0x8d, 0x3a, 0x01, 0xcc, 0x11, 0xd7, 0x4b, 0x4f, 0xd1, 0xd6, 0xc3, 0x2d, 0x90, + 0xad, 0xf1, 0xf2, 0xd6, 0x5e, 0x03, 0x39, 0xc5, 0xf1, 0xdf, 0xf1, 0x4c, 0xad, 0x6c, 0xf0, 0xd3, 0x53, 0xb6, 0x03, + 0x0f, 0x2f, 0x42, 0x40, 0x31, 0x2c, 0x1b, 0x7f, 0x67, 0x39, 0xce, 0xe8, 0xbf, 0x79, 0xc4, 0x30, 0x58, 0x44, 0x7e, + 0x7c, 0x59, 0x0a, 0xf1, 0x45, 0x78, 0x6f, 0x2a, 0xef, 0x8e, 0x9c, 0x32, 0xef, 0xf4, 0x30, 0xba, 0x2e, 0x49, 0xdf, + 0x24, 0x1f, 0x5b, 0xc3, 0xf6, 0xbb, 0x76, 0xbf, 0x19, 0x22, 0x08, 0xa1, 0x1c, 0x3f, 0x67, 0x74, 0x42, 0xe3, 0xc3, + 0x6a, 0x76, 0x7a, 0xfd, 0xde, 0x39, 0x5e, 0xb0, 0x35, 0x1a, 0xe0, 0xf1, 0xd0, 0xc5, 0x3c, 0x51, 0x43, 0xa7, 0xeb, + 0xda, 0x39, 0x78, 0x60, 0x90, 0xe5, 0xc9, 0x37, 0x0c, 0x4b, 0xec, 0x4f, 0x22, 0x9e, 0xb4, 0x55, 0x1b, 0x9b, 0x23, + 0xd5, 0x46, 0xcd, 0xc0, 0x0f, 0x5e, 0x41, 0x81, 0xd1, 0x05, 0x69, 0x05, 0xc6, 0xe1, 0x08, 0x40, 0x56, 0x8c, 0xe3, + 0x91, 0xc1, 0x04, 0x86, 0x74, 0x43, 0x51, 0x00, 0x1e, 0x1e, 0xc7, 0x83, 0x90, 0x01, 0xa4, 0x0b, 0x1e, 0x1a, 0xb6, + 0x49, 0x48, 0xf9, 0x79, 0x9e, 0xd7, 0x6a, 0x08, 0x7d, 0x67, 0xa1, 0x3a, 0xf6, 0x23, 0xed, 0x15, 0xeb, 0x5a, 0x95, + 0x8e, 0x6c, 0x75, 0x80, 0xbe, 0x21, 0x03, 0xdf, 0x3a, 0xb6, 0x00, 0x88, 0x96, 0xf8, 0x2d, 0xf5, 0x6a, 0x5f, 0xc6, + 0xac, 0x50, 0xaf, 0x2f, 0x4c, 0xbb, 0x5e, 0x49, 0x8b, 0x02, 0x2a, 0x6e, 0x5b, 0xb5, 0x3d, 0x92, 0xf3, 0x1f, 0xdf, + 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, 0x2d, 0xf5, 0xaa, 0x36, 0x55, 0x3d, 0x78, 0xe3, 0x05, + 0xce, 0xde, 0x69, 0x2d, 0x20, 0x80, 0xc2, 0xd6, 0xb2, 0x1c, 0x9c, 0xbb, 0x5d, 0xd5, 0x52, 0x51, 0x46, 0xfd, 0xfe, + 0xf9, 0x6f, 0x29, 0x2a, 0x62, 0x4f, 0x15, 0xa7, 0xac, 0xdf, 0x6e, 0x99, 0x8b, 0xca, 0x92, 0x37, 0xa8, 0xa2, 0xb5, + 0x3a, 0x6a, 0x2a, 0xd7, 0xcd, 0x55, 0x4b, 0x26, 0x88, 0xd1, 0x7d, 0xba, 0xd6, 0xb9, 0x53, 0xef, 0xbd, 0x8a, 0x23, + 0x06, 0x82, 0x9b, 0xee, 0xf1, 0xc1, 0x41, 0x68, 0x54, 0x94, 0x0b, 0x6e, 0x94, 0x56, 0x95, 0x94, 0x42, 0xde, 0xaa, + 0x68, 0xce, 0xf4, 0x11, 0x00, 0x11, 0x60, 0x95, 0xa8, 0xff, 0xc3, 0x97, 0xc6, 0x78, 0xf0, 0xc0, 0xd7, 0xe4, 0x3a, + 0xb6, 0xde, 0x3f, 0xad, 0x91, 0x56, 0x1b, 0xc7, 0xa4, 0x56, 0xbd, 0x6c, 0x15, 0x2f, 0xbb, 0xd7, 0xa9, 0x18, 0x3c, + 0xff, 0x9f, 0xfb, 0x00, 0x35, 0xa2, 0xa5, 0x0c, 0x6e, 0x5d, 0x0d, 0xd0, 0xf8, 0x70, 0x2c, 0x7c, 0xe3, 0x87, 0x8c, + 0xf3, 0xc1, 0x0c, 0x1d, 0xd5, 0xe6, 0xe0, 0x80, 0xe0, 0xa8, 0xee, 0xd1, 0x98, 0x30, 0x0b, 0xe7, 0x1e, 0x04, 0xaa, + 0x4f, 0xdc, 0x67, 0x5c, 0x7b, 0x41, 0x9b, 0xc0, 0x27, 0xeb, 0xba, 0xa6, 0x08, 0x70, 0x11, 0x1b, 0x13, 0x31, 0xc4, + 0x65, 0x93, 0x48, 0x7d, 0x33, 0x06, 0x05, 0x40, 0x71, 0x5d, 0x91, 0x5c, 0xba, 0x48, 0xf3, 0x4a, 0x94, 0xb5, 0x6e, + 0x46, 0xc5, 0x8a, 0x21, 0x00, 0x3c, 0x04, 0xc5, 0x55, 0x65, 0x26, 0x34, 0x62, 0x03, 0xa9, 0x2c, 0x05, 0xab, 0x86, + 0x85, 0xdf, 0xb4, 0xdf, 0x24, 0x27, 0xbd, 0xf3, 0x71, 0xeb, 0xdc, 0xb1, 0xef, 0x1d, 0x85, 0x94, 0xf6, 0x50, 0x4c, + 0x10, 0x04, 0x3f, 0xad, 0xc3, 0xf9, 0x33, 0x7e, 0x4d, 0x60, 0x2a, 0xb2, 0x19, 0x03, 0x0e, 0x42, 0x44, 0x66, 0xfc, + 0x9e, 0xc3, 0x6b, 0x5e, 0x4e, 0xc2, 0xe1, 0xd0, 0x07, 0x7d, 0x28, 0xcf, 0x66, 0xe1, 0x50, 0xcc, 0xa5, 0xf7, 0x3a, + 0x58, 0xeb, 0x42, 0x5e, 0x4f, 0x42, 0x44, 0x0b, 0x0d, 0x7d, 0x70, 0x5e, 0x77, 0xcd, 0x11, 0x96, 0x00, 0x34, 0x71, + 0xf4, 0x65, 0xfd, 0x7e, 0xe4, 0x69, 0x43, 0x8b, 0x14, 0x17, 0x8d, 0x32, 0x9b, 0xe5, 0xb2, 0x13, 0x36, 0xae, 0xdd, + 0x02, 0xa1, 0x78, 0x98, 0xb6, 0x50, 0xb5, 0x9e, 0xea, 0xf5, 0xdc, 0xb4, 0xfb, 0xee, 0x51, 0xb5, 0xca, 0x91, 0xce, + 0xda, 0x74, 0xa5, 0x56, 0xb7, 0x8c, 0xaa, 0x75, 0x96, 0x46, 0x54, 0xb9, 0x49, 0xee, 0x1a, 0xb5, 0xe0, 0x93, 0x0d, + 0x5d, 0xa6, 0xec, 0x6c, 0x0d, 0x4e, 0x1c, 0x79, 0x2e, 0xb9, 0xe5, 0xbb, 0xf3, 0x8a, 0xee, 0x4e, 0xb5, 0x6f, 0x01, + 0xee, 0xcd, 0xb0, 0x21, 0x73, 0x5e, 0x63, 0xa7, 0x41, 0x98, 0x04, 0x7e, 0xc4, 0x3e, 0x66, 0xc8, 0x06, 0x03, 0x3a, + 0x0a, 0xe9, 0x7f, 0x6d, 0x99, 0x23, 0x01, 0x93, 0xbf, 0x9e, 0xfb, 0xcd, 0xa2, 0xc8, 0x61, 0x31, 0x7e, 0xd8, 0x60, + 0xa4, 0xb1, 0x5a, 0x83, 0x61, 0x79, 0x87, 0xc8, 0x9f, 0xda, 0x1d, 0xd3, 0x54, 0xc7, 0x9b, 0xf5, 0x5a, 0xf3, 0xab, + 0xa7, 0x4f, 0x75, 0x7d, 0xfe, 0xdb, 0xf7, 0x97, 0x61, 0xcd, 0xec, 0x0f, 0x41, 0x28, 0xed, 0xde, 0x2d, 0xce, 0x1d, + 0x89, 0xde, 0xb1, 0xd2, 0xcc, 0x2e, 0xed, 0x92, 0x5d, 0x9a, 0xd2, 0x6e, 0xc8, 0xf5, 0xea, 0x2b, 0xe5, 0x8d, 0x9d, + 0x57, 0x4c, 0xf7, 0xef, 0x85, 0xde, 0x51, 0x4e, 0xd5, 0x04, 0x22, 0x9a, 0xb4, 0x23, 0x71, 0xbb, 0x57, 0x86, 0xcf, + 0x27, 0x79, 0xbb, 0x84, 0xa3, 0xae, 0x61, 0xb9, 0xf9, 0xf6, 0x3f, 0xf3, 0xaa, 0xb3, 0xc2, 0xed, 0x97, 0xc6, 0xac, + 0xfd, 0x29, 0x88, 0xab, 0xfa, 0xc3, 0x7b, 0x52, 0x33, 0x25, 0xff, 0x57, 0x3d, 0x06, 0xae, 0x7e, 0x32, 0xed, 0xe8, + 0x9e, 0x42, 0xd8, 0x60, 0xf6, 0xf3, 0xe3, 0x87, 0x16, 0xac, 0xaa, 0x0b, 0x14, 0xc9, 0x01, 0x74, 0xee, 0x92, 0x11, + 0xde, 0xef, 0x18, 0xe7, 0xfe, 0xd5, 0xf7, 0x6a, 0x72, 0x84, 0x88, 0x76, 0x11, 0x0e, 0x00, 0xe2, 0x4e, 0x53, 0x59, + 0x87, 0x1a, 0xa0, 0x0f, 0x08, 0xac, 0x43, 0xdf, 0x66, 0x00, 0x07, 0x7d, 0xb4, 0x79, 0x16, 0x81, 0xbc, 0xee, 0xdd, + 0xb3, 0xb7, 0x6c, 0xe7, 0xf3, 0xeb, 0x55, 0xea, 0xdd, 0xa3, 0x43, 0xf0, 0xf9, 0xd8, 0x9f, 0x5e, 0x06, 0x06, 0x17, + 0x9a, 0xbd, 0x7d, 0x26, 0xd8, 0x8e, 0xed, 0x9e, 0x21, 0x52, 0x51, 0x77, 0xfe, 0xe1, 0xa5, 0x89, 0x9e, 0x77, 0x5e, + 0xb8, 0xe3, 0x4b, 0x00, 0x0f, 0x64, 0x31, 0xa0, 0xf8, 0x2c, 0xbd, 0x7f, 0xb1, 0x04, 0xd4, 0xe4, 0xb7, 0x7c, 0xed, + 0x7d, 0xa1, 0xd4, 0x05, 0xfc, 0x39, 0xa0, 0xf4, 0x49, 0xce, 0xbd, 0xbb, 0xe1, 0xad, 0x7f, 0xf1, 0x1c, 0x9c, 0x27, + 0x56, 0xc3, 0x05, 0xfc, 0x55, 0xf0, 0xa1, 0x77, 0x37, 0xc0, 0xc4, 0x92, 0x0f, 0xbd, 0xd5, 0x00, 0x52, 0x15, 0x2e, + 0x24, 0xc6, 0x3e, 0xfc, 0x1a, 0xe4, 0x0c, 0xff, 0xf8, 0x4d, 0x63, 0xb0, 0xfe, 0x1a, 0x14, 0x1a, 0x8d, 0xb5, 0x54, + 0x21, 0x4b, 0xb1, 0x38, 0x13, 0x60, 0x13, 0x8e, 0xbb, 0x7d, 0xb1, 0xaa, 0xcd, 0x5a, 0xd0, 0x9f, 0x8f, 0xf8, 0x1e, + 0x8d, 0xd5, 0x55, 0x39, 0x17, 0xe5, 0x47, 0xa4, 0x4f, 0x75, 0x7c, 0x8c, 0x8a, 0x4d, 0xdd, 0x9d, 0x4e, 0xb5, 0xea, + 0x48, 0xfb, 0x4d, 0xb9, 0x06, 0x3b, 0x5e, 0x27, 0x47, 0x96, 0xc2, 0xb3, 0x0e, 0x3b, 0x2f, 0x9d, 0x12, 0x1d, 0x86, + 0xf1, 0x6e, 0xab, 0x9e, 0x31, 0x94, 0xe7, 0x06, 0x63, 0xba, 0xe0, 0x11, 0xbf, 0x1e, 0xe4, 0x32, 0x34, 0xe6, 0x03, + 0xb2, 0x61, 0x28, 0x1f, 0x5a, 0x64, 0x48, 0x88, 0x78, 0x0f, 0x95, 0x80, 0x6d, 0x0b, 0xca, 0xa4, 0x80, 0xb3, 0x68, + 0xf0, 0x5b, 0xed, 0xe5, 0xc0, 0x7b, 0x10, 0xf9, 0x8d, 0x74, 0x29, 0x97, 0xd8, 0xe8, 0xc4, 0xb1, 0x2c, 0xb4, 0xf3, + 0xb8, 0xfe, 0x3a, 0x06, 0xf5, 0x7b, 0xa5, 0xdf, 0xa0, 0x9c, 0xfd, 0x51, 0xb2, 0x4e, 0x1b, 0x4f, 0x8c, 0x7f, 0xb8, + 0xca, 0x3f, 0x45, 0x4b, 0x3d, 0xfc, 0x7f, 0xc6, 0x14, 0x4a, 0xff, 0x32, 0x2d, 0xa3, 0xcd, 0x6a, 0x29, 0x4a, 0x91, + 0x47, 0xe2, 0xe4, 0x6b, 0x91, 0x9d, 0xcb, 0x77, 0x3e, 0x85, 0x7e, 0x01, 0x68, 0xd9, 0x27, 0xc8, 0xe8, 0xef, 0x99, + 0xe0, 0xc3, 0xef, 0xb5, 0x73, 0x6d, 0xce, 0xc7, 0x93, 0xfc, 0xca, 0xda, 0xbb, 0x1d, 0x2f, 0x12, 0xa3, 0x18, 0xcb, + 0x7d, 0xd5, 0xcd, 0xca, 0x89, 0x4a, 0x0e, 0x8c, 0x74, 0x4d, 0xf6, 0x72, 0x25, 0xeb, 0x76, 0xba, 0x95, 0x40, 0x44, + 0x15, 0x78, 0x8f, 0x71, 0x15, 0xfb, 0x08, 0xa6, 0xeb, 0x8e, 0xcb, 0x68, 0xc7, 0x7b, 0xc6, 0xab, 0x13, 0x65, 0x05, + 0xb7, 0x1b, 0xd1, 0x9e, 0xd0, 0xd1, 0x4f, 0x93, 0xda, 0xb2, 0x70, 0x00, 0x72, 0x97, 0x30, 0x96, 0x0d, 0xc1, 0x8a, + 0x41, 0xe9, 0xeb, 0x35, 0x25, 0xcb, 0x02, 0x2c, 0x3a, 0xbb, 0x8c, 0x40, 0x0c, 0xeb, 0xa6, 0x39, 0xa1, 0xe3, 0xa5, + 0x8b, 0xf3, 0x5e, 0xab, 0x48, 0xc1, 0x33, 0x5a, 0x74, 0xcc, 0x4d, 0x47, 0xba, 0x31, 0xda, 0xdb, 0xef, 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, 0x7d, + 0x0e, 0x5b, 0x13, 0x66, 0x53, 0x17, 0x1b, 0xa0, 0xad, 0x62, 0x68, 0x10, 0xd6, 0x86, 0x98, 0x8f, 0x69, 0x7e, 0xf7, + 0x2f, 0x2c, 0xc6, 0xf6, 0x04, 0x62, 0x7b, 0xb7, 0x6b, 0x12, 0xa6, 0x7b, 0x2d, 0x6e, 0xac, 0x97, 0xdb, 0x53, 0x8e, + 0xa9, 0x1d, 0x6b, 0xa3, 0x76, 0xac, 0xa5, 0xde, 0xb1, 0xd6, 0x7a, 0xc7, 0xba, 0x6b, 0xf8, 0x87, 0xcc, 0x8b, 0x59, + 0x02, 0xfa, 0xdd, 0x15, 0x57, 0x0d, 0x82, 0x66, 0x6c, 0xd8, 0x2d, 0xfc, 0x96, 0x58, 0xbb, 0xa5, 0x7f, 0xb1, 0x64, + 0x0b, 0xd3, 0x07, 0xba, 0x75, 0x80, 0x65, 0x44, 0x4d, 0xbe, 0x47, 0xde, 0x4d, 0x67, 0x45, 0xe1, 0xf6, 0xc4, 0x16, + 0x3e, 0x7b, 0x6b, 0xde, 0xbc, 0x7f, 0x16, 0x41, 0xee, 0x1d, 0xf7, 0xee, 0x87, 0x6f, 0xfd, 0x0b, 0xdd, 0x02, 0x39, + 0x99, 0xe5, 0x0c, 0xa4, 0x8e, 0xf8, 0x04, 0xd1, 0xca, 0x9e, 0xf2, 0x9d, 0x90, 0x3b, 0xdb, 0xfa, 0xd9, 0xbd, 0xbb, + 0xad, 0xdd, 0x3d, 0xbb, 0x67, 0xd5, 0x88, 0x62, 0xc5, 0x69, 0x8a, 0x84, 0x59, 0xb4, 0x01, 0x9e, 0x7a, 0xf9, 0x7e, + 0xc7, 0x8e, 0x39, 0xdc, 0x3d, 0xeb, 0xe8, 0x78, 0x39, 0x07, 0xec, 0xee, 0x3f, 0xda, 0x84, 0x8d, 0x95, 0xae, 0x55, + 0xe8, 0x70, 0xf7, 0x2c, 0xd3, 0x78, 0x0e, 0x47, 0xf2, 0xe9, 0x58, 0x63, 0x83, 0xa0, 0xae, 0xcf, 0x19, 0xd4, 0x8e, + 0xdd, 0xd7, 0x84, 0x5d, 0x76, 0xcc, 0x6b, 0x5d, 0xf3, 0xf6, 0xca, 0x53, 0xb1, 0x21, 0xa0, 0xc3, 0xd7, 0xea, 0x06, + 0xf9, 0x97, 0xc0, 0x29, 0x02, 0x40, 0x0e, 0xc7, 0x4b, 0x1e, 0xfb, 0x3e, 0xcd, 0xd2, 0x7a, 0x87, 0x5a, 0x8b, 0xca, + 0xb2, 0x0c, 0x6b, 0xef, 0x07, 0xad, 0x18, 0x96, 0x9a, 0xfe, 0xe9, 0x38, 0x70, 0x3b, 0xdb, 0xad, 0x8c, 0x5d, 0xc6, + 0xb3, 0xe2, 0xe2, 0xfb, 0xd3, 0x42, 0xb9, 0x76, 0xf3, 0x36, 0x7e, 0xd3, 0x6a, 0xc9, 0xd2, 0x5a, 0x0f, 0x79, 0x69, + 0x59, 0x44, 0x20, 0x80, 0xe1, 0x48, 0xd9, 0xc5, 0x12, 0xee, 0x11, 0x56, 0xf7, 0x20, 0x94, 0xcc, 0x0b, 0x17, 0xcf, + 0x59, 0x0c, 0x89, 0x00, 0xdb, 0x1d, 0x2a, 0xb6, 0x85, 0x8b, 0xe7, 0x6c, 0xc3, 0x8b, 0x7e, 0x3f, 0x53, 0x9d, 0x42, + 0xd6, 0x9d, 0x25, 0xdf, 0xa8, 0xe6, 0x58, 0x43, 0xcd, 0xd6, 0x26, 0xd9, 0x1a, 0xe7, 0xb6, 0xe2, 0xe3, 0xae, 0xad, + 0xf8, 0x58, 0x59, 0xeb, 0xd2, 0xbd, 0xde, 0xa3, 0xba, 0x00, 0xb6, 0xfe, 0xdb, 0xe3, 0x95, 0xeb, 0xf9, 0x8c, 0x00, + 0xbe, 0x16, 0x7c, 0x3c, 0x59, 0xa0, 0x57, 0xc9, 0xc2, 0xbf, 0x1d, 0xa8, 0xf1, 0x77, 0x3a, 0x77, 0x01, 0xd0, 0x95, + 0x94, 0x57, 0x40, 0xde, 0x41, 0x8e, 0xb9, 0x65, 0x57, 0xde, 0x9f, 0x7c, 0x87, 0xbd, 0xe5, 0xf5, 0x6c, 0x31, 0x67, + 0x3b, 0x70, 0x2a, 0x48, 0x06, 0xf6, 0xb2, 0x62, 0xbb, 0x20, 0xb6, 0x13, 0x7e, 0x23, 0x60, 0xca, 0x17, 0x10, 0xc4, + 0x15, 0xdc, 0x42, 0x1c, 0x9e, 0xfc, 0x73, 0x70, 0xdf, 0xda, 0xac, 0xef, 0x99, 0xd5, 0x39, 0xc1, 0x9a, 0x59, 0x3d, + 0x18, 0x2c, 0x9b, 0xc9, 0xaa, 0xdf, 0xf7, 0x76, 0xda, 0xf1, 0xe9, 0x4e, 0xea, 0xc4, 0x4e, 0x6b, 0xb5, 0x16, 0xec, + 0xad, 0xd4, 0xba, 0x18, 0x43, 0x0f, 0x10, 0x3f, 0xdd, 0x0e, 0xf8, 0x7d, 0xc7, 0xda, 0xf2, 0xde, 0xb2, 0x05, 0xdb, + 0xc1, 0x25, 0xa8, 0x69, 0x2f, 0xfb, 0x93, 0xca, 0x05, 0xed, 0xd8, 0x25, 0xf1, 0x70, 0xc6, 0xac, 0x52, 0x66, 0xd6, + 0x49, 0x75, 0x25, 0x3a, 0x63, 0x3a, 0x6b, 0x3d, 0x9f, 0xab, 0xf9, 0xa4, 0xd0, 0xa0, 0x7e, 0xe7, 0xc4, 0x47, 0x54, + 0x74, 0x9e, 0xc0, 0xd6, 0xb2, 0x82, 0x58, 0xed, 0x73, 0xb0, 0xd6, 0x6a, 0x97, 0x7e, 0x2f, 0x1f, 0x70, 0x9b, 0x72, + 0x58, 0x07, 0x06, 0x35, 0x27, 0x56, 0xd4, 0x63, 0xb6, 0x63, 0xdc, 0xfc, 0xf4, 0xf2, 0x07, 0x27, 0x2c, 0x59, 0xb1, + 0xda, 0x9f, 0x7e, 0xff, 0xcc, 0xd3, 0xdf, 0xa9, 0xfd, 0x0b, 0xe1, 0x07, 0xe3, 0xff, 0xd4, 0xee, 0x6b, 0x2d, 0x46, + 0x65, 0xab, 0x1c, 0xa1, 0x71, 0xb7, 0x92, 0x26, 0xcb, 0x4f, 0xc2, 0x13, 0xd6, 0x82, 0x67, 0xb9, 0x5e, 0xa2, 0x59, + 0x01, 0x2b, 0xac, 0x65, 0x12, 0xae, 0x30, 0x56, 0x4b, 0x5b, 0x7d, 0x8b, 0xa6, 0x39, 0x3e, 0x9c, 0x6b, 0x83, 0x32, + 0xe5, 0xec, 0x8c, 0x58, 0x0d, 0x97, 0x61, 0x69, 0x42, 0x11, 0xb2, 0x7b, 0x3b, 0xb8, 0xb1, 0x53, 0x96, 0x52, 0x86, + 0x73, 0x0c, 0x26, 0x3c, 0x12, 0xa3, 0x2a, 0xdf, 0xdf, 0x97, 0x14, 0x39, 0x6d, 0xcb, 0x41, 0x15, 0xc2, 0x3e, 0x92, + 0x28, 0x81, 0x5b, 0x91, 0x16, 0x8a, 0x94, 0xc5, 0xdf, 0x0e, 0xd0, 0x05, 0x5e, 0x40, 0x5d, 0x8d, 0xba, 0xfd, 0xe1, + 0x88, 0x87, 0x8f, 0x4c, 0x7d, 0x60, 0xc4, 0x92, 0x40, 0x6d, 0x2f, 0xb2, 0xf4, 0x0e, 0x54, 0xf8, 0x3d, 0x5c, 0x4d, + 0xc4, 0x7e, 0x6e, 0x49, 0x51, 0x91, 0x8d, 0xf4, 0x86, 0xd6, 0xe0, 0x11, 0x5a, 0x53, 0xbe, 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, 0xf7, 0x2a, 0xc1, 0x82, 0x25, 0xed, 0x3e, 0x7e, 0x3b, + 0x6b, 0x07, 0xa2, 0x32, 0x56, 0xe9, 0x6b, 0x92, 0xb0, 0x27, 0x06, 0x9d, 0x42, 0x55, 0x6e, 0x77, 0x47, 0x5b, 0xe0, + 0x3a, 0x66, 0x29, 0x7a, 0x61, 0x8b, 0xdc, 0x2d, 0xff, 0xee, 0xb9, 0x22, 0x67, 0xbf, 0x04, 0x04, 0xa7, 0xe6, 0x2b, + 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, 0x97, 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, 0x3f, 0xed, 0x19, + 0x19, 0x79, 0xdc, 0x3a, 0xac, 0xfe, 0xd7, 0x5f, 0x21, 0x00, 0x0e, 0xcf, 0xa6, 0xde, 0xe5, 0x18, 0xb2, 0xca, 0x32, + 0x02, 0xc9, 0x4f, 0x0c, 0xbe, 0x7c, 0x01, 0x50, 0xf5, 0x99, 0xae, 0xd5, 0xe4, 0xa8, 0x3d, 0xe6, 0xd0, 0x15, 0x03, + 0xc0, 0x36, 0x2c, 0x51, 0x55, 0x0b, 0x9b, 0xb0, 0xb8, 0xfd, 0x0c, 0xa3, 0xb9, 0x6c, 0x7a, 0x41, 0x03, 0xf5, 0x08, + 0xc1, 0x2f, 0xad, 0x87, 0xd6, 0x5a, 0xa6, 0x1c, 0xba, 0x36, 0x8a, 0x2a, 0x1b, 0xea, 0x12, 0x56, 0x6b, 0x11, 0xd5, + 0x44, 0x91, 0x72, 0xc9, 0x28, 0x8a, 0xa5, 0x0a, 0xf6, 0x99, 0xb8, 0x83, 0xa8, 0x79, 0xda, 0x6a, 0xab, 0x60, 0x7f, + 0x07, 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, 0x0f, 0xa1, 0x9f, 0x1a, 0xf8, 0x4b, 0xb6, 0x2c, 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, 0xbf, 0xcc, 0x52, 0xe3, 0x1c, 0x99, + 0xcb, 0xf5, 0x5d, 0x17, 0x77, 0x77, 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, 0x57, 0xb5, 0x48, 0x5d, 0x11, 0x6c, + 0x63, 0x86, 0x7a, 0x28, 0x37, 0x6a, 0xec, 0xeb, 0x8e, 0x55, 0x7a, 0x87, 0x09, 0x72, 0x46, 0x5e, 0xe4, 0xe0, 0xa2, + 0xa4, 0x20, 0x73, 0x35, 0x84, 0xf9, 0xa3, 0x86, 0x4f, 0x0b, 0xcb, 0x3d, 0x94, 0x80, 0xd9, 0x51, 0xc3, 0xcb, 0x08, + 0x81, 0x88, 0x4b, 0x65, 0x5f, 0x31, 0xf1, 0x7b, 0x0a, 0x66, 0xc9, 0x84, 0xee, 0x45, 0x2c, 0x8c, 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, 0xe1, 0xe7, 0x34, 0x07, 0x14, 0xc1, 0xcc, 0x9e, 0x62, + 0x7c, 0xec, 0xb3, 0x4c, 0x01, 0x7f, 0xbb, 0xde, 0x5a, 0x32, 0xb1, 0x4b, 0xda, 0xcd, 0x95, 0xf1, 0x4b, 0x6d, 0xd8, + 0x71, 0x70, 0x6e, 0x00, 0x8a, 0xb3, 0x46, 0x87, 0xe5, 0xb5, 0x6e, 0x5b, 0x15, 0x2a, 0x50, 0xeb, 0xff, 0xec, 0x16, + 0xa6, 0xbc, 0xcd, 0x4b, 0xe5, 0x6d, 0x1e, 0x9a, 0x00, 0x81, 0xc8, 0x0c, 0x79, 0xd6, 0x74, 0x4c, 0x12, 0xf7, 0x8e, + 0x94, 0xb4, 0xef, 0x48, 0xf1, 0xa3, 0x77, 0x24, 0xe4, 0x5b, 0x42, 0x47, 0xf6, 0x25, 0x27, 0x27, 0x50, 0x66, 0xb0, + 0x97, 0xd7, 0x4c, 0xf6, 0x0f, 0x68, 0x2f, 0x9c, 0xcb, 0xf2, 0x8a, 0xbf, 0x15, 0xde, 0xda, 0x9f, 0xae, 0x4f, 0xbb, + 0xaa, 0xde, 0x7e, 0x65, 0x66, 0x1e, 0x0e, 0xc5, 0xe1, 0x50, 0x99, 0xa0, 0xdd, 0x05, 0x17, 0x83, 0x9c, 0xdd, 0xbb, + 0xf1, 0xf1, 0x6f, 0x39, 0x8a, 0xd8, 0x4a, 0x79, 0x24, 0x5d, 0xa8, 0xc4, 0xf0, 0xd2, 0xc0, 0xc3, 0xec, 0xf8, 0x78, + 0xb2, 0xbb, 0xba, 0x9f, 0x0c, 0x06, 0x3b, 0xd5, 0xb7, 0x5b, 0x5e, 0xcf, 0x76, 0x73, 0xf6, 0xc0, 0x6f, 0xa7, 0xdb, + 0x60, 0xdf, 0xc0, 0xb6, 0xbb, 0xbb, 0x12, 0x87, 0xc3, 0xee, 0x9a, 0x2f, 0xfc, 0xfd, 0x03, 0x02, 0x3a, 0xf3, 0xf3, + 0x71, 0x1b, 0xe3, 0xe7, 0xa6, 0xed, 0xaa, 0xb5, 0x03, 0x78, 0xfa, 0x1f, 0xbc, 0x9b, 0xd9, 0x72, 0xee, 0xb3, 0x27, + 0xfc, 0x01, 0xfc, 0xf3, 0x71, 0x93, 0x44, 0xea, 0x13, 0xed, 0x32, 0x79, 0x03, 0x0e, 0xe4, 0x3b, 0x9f, 0xbd, 0xe1, + 0x0f, 0xb3, 0xe5, 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, 0x76, 0xc3, 0x22, 0x3f, 0x80, 0x0f, 0xb2, 0x9d, 0x3f, 0x91, + 0x35, 0xa5, 0xfb, 0xc5, 0x13, 0xff, 0x70, 0xa0, 0xbf, 0xde, 0xf8, 0x87, 0xc3, 0x7b, 0xf6, 0x80, 0xe0, 0xe8, 0x7c, + 0x07, 0xfd, 0xa3, 0x6f, 0x1d, 0x50, 0x95, 0xe1, 0xdb, 0xd9, 0x66, 0xee, 0x5f, 0xaf, 0xd8, 0x1d, 0x70, 0xa1, 0x28, + 0x2f, 0xb4, 0x1b, 0xf6, 0x80, 0x5e, 0x67, 0xe4, 0x44, 0x34, 0xdb, 0xcd, 0x7d, 0x16, 0xe3, 0x73, 0x75, 0x5f, 0x4c, + 0xbe, 0x7a, 0x5f, 0xdc, 0xb1, 0x6d, 0xf7, 0x7d, 0x51, 0xbe, 0xe9, 0xae, 0x9f, 0x2d, 0xdb, 0xb1, 0x07, 0x98, 0x61, + 0x6f, 0xf9, 0x4d, 0x73, 0xec, 0x18, 0xfb, 0xd5, 0x1b, 0x23, 0x80, 0x32, 0x5b, 0xb0, 0x58, 0x70, 0x50, 0xaa, 0x55, + 0xdb, 0x92, 0xc8, 0x2b, 0x1d, 0xa8, 0x36, 0x23, 0xb8, 0xaf, 0x16, 0x72, 0xe6, 0x99, 0x81, 0xbe, 0xad, 0x10, 0x2d, + 0x1c, 0x36, 0xe0, 0xaf, 0xb4, 0x75, 0x8c, 0x61, 0x9a, 0xd5, 0x4c, 0xdb, 0xa2, 0x2e, 0xbf, 0xed, 0x3d, 0x93, 0xdf, + 0xc8, 0xc0, 0x16, 0x22, 0x29, 0x1c, 0xc7, 0x17, 0xcf, 0x4f, 0xf8, 0xaf, 0x5a, 0x1e, 0xb5, 0xda, 0x2f, 0x94, 0xfa, + 0xf4, 0x25, 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, 0x17, 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, 0x42, 0x49, 0xb3, 0x51, 0x58, 0x8b, 0xbb, 0xa2, 0xdc, 0xf5, + 0x1a, 0xb6, 0xc0, 0x0b, 0xaa, 0x7e, 0x42, 0xd8, 0x96, 0x3d, 0xeb, 0x50, 0x2e, 0xd2, 0xff, 0xc8, 0xd2, 0xf3, 0xed, + 0xd6, 0x9c, 0xff, 0xe9, 0x2b, 0xfa, 0xa8, 0xfc, 0xcf, 0x2f, 0xe9, 0x27, 0x83, 0x65, 0xe4, 0x94, 0xfa, 0x3e, 0x1a, + 0xdd, 0xa6, 0x39, 0x61, 0x6c, 0xf9, 0xfa, 0xe9, 0x37, 0xc8, 0x14, 0x24, 0x87, 0x52, 0xaa, 0x72, 0xb2, 0x87, 0xbe, + 0xf0, 0xba, 0x0f, 0x33, 0xc1, 0x00, 0x84, 0xd7, 0x68, 0x53, 0x4d, 0x98, 0xc4, 0xa3, 0x2b, 0xf8, 0xbf, 0x11, 0xc4, + 0xa0, 0x7d, 0xa2, 0xa8, 0x63, 0xdb, 0x48, 0xd7, 0x6d, 0xe7, 0x20, 0xb9, 0x53, 0x57, 0xfe, 0xa8, 0x9c, 0xfc, 0x27, + 0x1a, 0x22, 0xaf, 0xb8, 0x42, 0xac, 0x2c, 0xb8, 0xc4, 0x62, 0xa8, 0x48, 0x01, 0xae, 0x21, 0x88, 0x94, 0x45, 0x49, + 0xe1, 0x96, 0x83, 0xaa, 0x08, 0xc0, 0xb8, 0x5a, 0x1d, 0x75, 0x22, 0x7c, 0xdc, 0x5a, 0x8b, 0x10, 0xac, 0x68, 0xd4, + 0xca, 0x5a, 0x81, 0x2f, 0x48, 0x5f, 0x3a, 0x14, 0xc4, 0xf4, 0x28, 0xa4, 0xaa, 0x74, 0x28, 0x90, 0xe6, 0x50, 0xf1, + 0x8d, 0xc1, 0x46, 0x51, 0x91, 0x9e, 0xbf, 0x34, 0x29, 0xb9, 0x34, 0x66, 0x7c, 0x10, 0x65, 0x24, 0xf2, 0x3a, 0xbc, + 0x13, 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, 0x59, 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, + 0xa5, 0x00, 0xba, 0x5d, 0x16, 0xf3, 0x6c, 0xb4, 0x93, 0x7f, 0x4b, 0x37, 0x56, 0x94, 0x36, 0xf1, 0x2e, 0xeb, 0x8d, + 0xfd, 0xe1, 0xe8, 0x2f, 0xcf, 0xbe, 0x4c, 0x08, 0x55, 0x67, 0xc3, 0xd6, 0x3a, 0xce, 0xe5, 0x7f, 0xfd, 0x75, 0x4c, + 0x56, 0x10, 0x14, 0x84, 0x65, 0xa7, 0x98, 0xa8, 0x60, 0x14, 0x29, 0xd6, 0x7c, 0x3c, 0x59, 0xa3, 0x4e, 0x78, 0xed, + 0x2f, 0xb5, 0x4e, 0x98, 0x18, 0x59, 0xa9, 0xfc, 0x35, 0xab, 0xd8, 0x9d, 0xca, 0x2c, 0x20, 0xf3, 0x20, 0x9f, 0xac, + 0x8d, 0x06, 0x73, 0xc5, 0xeb, 0xd9, 0x7a, 0x2e, 0x95, 0xcf, 0x60, 0xca, 0x59, 0x0e, 0x4e, 0x96, 0xc2, 0xee, 0x49, + 0xa0, 0x68, 0xcd, 0xd0, 0xb5, 0x3f, 0xc5, 0x56, 0xbd, 0x4a, 0xab, 0x1a, 0xe0, 0x01, 0x21, 0x06, 0x86, 0xda, 0xab, + 0x85, 0x87, 0xd6, 0x02, 0x58, 0xfb, 0xa3, 0xd2, 0x0f, 0xc6, 0x93, 0x25, 0x5f, 0x20, 0xff, 0x72, 0xe4, 0xa8, 0xdd, + 0xfb, 0x7d, 0xef, 0x1e, 0xa4, 0xe0, 0xc8, 0xb5, 0x50, 0x20, 0x11, 0xd0, 0x82, 0x6f, 0x7c, 0xe5, 0x83, 0xf1, 0x16, + 0xb5, 0xd5, 0xa0, 0xa0, 0x76, 0x74, 0xcb, 0x63, 0x47, 0xef, 0x7c, 0x7f, 0x42, 0x5f, 0xbd, 0xd0, 0xc2, 0xf1, 0x57, + 0xce, 0xc8, 0x35, 0x5b, 0x75, 0xc8, 0x11, 0xcd, 0xa4, 0x43, 0x88, 0x58, 0xb1, 0x35, 0x7b, 0x4b, 0x2a, 0xe7, 0xce, + 0x21, 0x3b, 0x7d, 0x84, 0x2a, 0xbd, 0xd6, 0xe3, 0xdb, 0x89, 0xd2, 0xdd, 0x1e, 0xef, 0x26, 0xdf, 0xb2, 0x89, 0x88, + 0xc1, 0x80, 0x36, 0x08, 0x67, 0x64, 0x1d, 0x22, 0x95, 0x0e, 0x10, 0x02, 0xc7, 0x04, 0x34, 0xfd, 0xc7, 0xd7, 0x24, + 0x0a, 0x38, 0xd2, 0x46, 0xc8, 0x5a, 0x76, 0x38, 0xe4, 0xa0, 0x51, 0x6e, 0xfe, 0xf0, 0x0a, 0x75, 0x9a, 0x03, 0xf3, + 0x74, 0x09, 0x7b, 0x0e, 0x1e, 0xe9, 0xc5, 0xf1, 0x91, 0xfe, 0xdf, 0xd1, 0x44, 0x8d, 0xff, 0x73, 0x4d, 0x94, 0xd2, + 0x22, 0x39, 0xaa, 0xa5, 0x6f, 0x52, 0x47, 0xc1, 0x45, 0xde, 0x51, 0x0b, 0xd9, 0xb3, 0x6c, 0xdc, 0xa8, 0xe6, 0xfd, + 0xff, 0x5a, 0x99, 0xff, 0xaf, 0x69, 0x65, 0x98, 0x92, 0x1d, 0x4b, 0x35, 0xf3, 0x40, 0xab, 0x18, 0x66, 0x3f, 0x93, + 0x84, 0xc8, 0x70, 0x69, 0xc0, 0x8f, 0x2a, 0xd8, 0xc7, 0x69, 0xb5, 0xce, 0xc2, 0x1d, 0x2a, 0x51, 0x6f, 0xc5, 0x5d, + 0x9a, 0xbf, 0xa8, 0xff, 0x2d, 0xca, 0x02, 0xa6, 0xf6, 0x5d, 0x99, 0xc6, 0x01, 0x59, 0xf8, 0xb3, 0xb0, 0xc4, 0xc9, + 0x8d, 0x6d, 0xfc, 0x59, 0x8e, 0xa7, 0xfd, 0xaa, 0x33, 0xf3, 0x40, 0x02, 0x35, 0x10, 0x7f, 0xe4, 0x5c, 0x56, 0x16, + 0x0f, 0x08, 0xdd, 0xfc, 0x43, 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, 0x3e, 0x8d, + 0x45, 0x3c, 0xea, 0x29, 0x4a, 0x96, 0xd7, 0xb9, 0x2b, 0xe7, 0xfa, 0xfb, 0x3f, 0x28, 0x80, 0xdd, 0x80, 0xd9, 0xb6, + 0xc0, 0x0e, 0x00, 0x12, 0x14, 0xc8, 0x16, 0xea, 0x34, 0x3a, 0x53, 0x4b, 0x05, 0xde, 0x73, 0x3d, 0xc0, 0x5f, 0xe7, + 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, 0xbe, 0x9d, 0x2a, 0xf2, 0xf8, 0x28, 0x0d, 0x79, 0x05, 0x9e, 0x64, 0x1c, 0x49, 0xa2, 0x44, 0xf0, + 0x3a, 0x6f, 0xcc, 0x38, 0xbc, 0x68, 0x53, 0x4e, 0xed, 0xcd, 0x7a, 0x01, 0x38, 0x4f, 0xd0, 0x96, 0x01, 0xc6, 0x02, + 0x06, 0xe7, 0x42, 0x2c, 0x79, 0x8a, 0xe0, 0x97, 0x4e, 0xa4, 0x30, 0xee, 0x72, 0x18, 0xe6, 0x41, 0xd1, 0xbb, 0xa4, + 0xfe, 0xe8, 0xf7, 0x51, 0x9b, 0x0c, 0x86, 0xa0, 0x12, 0x40, 0x65, 0xdd, 0x20, 0x31, 0xb0, 0x2a, 0x2d, 0x24, 0x2e, + 0x21, 0x5e, 0xe6, 0xab, 0x69, 0x1d, 0x05, 0xef, 0xeb, 0x09, 0x21, 0x9c, 0x60, 0x7c, 0x88, 0x1b, 0x20, 0x60, 0xb0, + 0x8a, 0x0b, 0x0c, 0x92, 0xe7, 0x12, 0xdd, 0x1f, 0xcf, 0x77, 0x0c, 0x70, 0xe5, 0xbc, 0xa7, 0xda, 0xd5, 0x03, 0x7b, + 0xb9, 0x4a, 0x97, 0x8c, 0x10, 0x56, 0xfc, 0x5f, 0x44, 0xde, 0xb7, 0xc3, 0x04, 0xd4, 0x36, 0xf2, 0xc7, 0x20, 0x31, + 0x97, 0x89, 0x22, 0x88, 0x47, 0x59, 0xc1, 0x92, 0x34, 0xd8, 0x8c, 0x92, 0x14, 0x34, 0x9a, 0x18, 0x43, 0xa6, 0x42, + 0x3b, 0x24, 0x8d, 0x66, 0x63, 0xb2, 0x8f, 0x21, 0xaf, 0xe1, 0x62, 0xb1, 0xc0, 0xfb, 0x7e, 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, 0x64, 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, 0x30, 0x94, 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, 0x9f, 0x65, 0x4d, 0xe6, 0xe2, 0x75, 0xf1, 0xe0, 0x15, 0xec, 0xb9, 0x3f, 0xd0, 0xbf, 0x4a, 0xf6, + 0xdc, 0xb7, 0x99, 0x5c, 0xff, 0x4c, 0xbb, 0x46, 0x63, 0xa6, 0xe3, 0xb5, 0x2b, 0xb0, 0x42, 0x03, 0xe4, 0x17, 0xec, + 0x68, 0x6f, 0x72, 0x10, 0x08, 0xd0, 0xbd, 0x04, 0x47, 0x51, 0x40, 0xd4, 0xb4, 0xaa, 0x3c, 0x3a, 0xdd, 0xfb, 0x7b, + 0x7c, 0xa3, 0x04, 0x6c, 0xf2, 0xd4, 0xba, 0xb7, 0x8c, 0xfd, 0xc3, 0x01, 0x42, 0xe8, 0xe5, 0xf4, 0x1b, 0x6d, 0x59, + 0x3d, 0xda, 0xb1, 0xdc, 0x37, 0x8c, 0x7a, 0x0a, 0xc6, 0x30, 0x74, 0x61, 0x15, 0x23, 0x79, 0x06, 0x64, 0x8d, 0xdf, + 0x20, 0xba, 0x80, 0x45, 0xaf, 0xf7, 0xea, 0x88, 0x06, 0x11, 0x50, 0xe9, 0x35, 0x7f, 0x29, 0xf2, 0xb9, 0x2a, 0x44, + 0xef, 0xbd, 0xb5, 0xf3, 0x66, 0x46, 0xb2, 0x4c, 0x1a, 0xa9, 0x76, 0x2b, 0x8b, 0x75, 0xe5, 0xcd, 0x4e, 0x48, 0x17, + 0x73, 0x0c, 0x95, 0xc1, 0xe3, 0x00, 0x94, 0x9e, 0x7f, 0x0b, 0xbd, 0x92, 0x21, 0xd3, 0x2c, 0xd1, 0xcc, 0xee, 0x1a, + 0x7f, 0xb2, 0x4a, 0xbd, 0x18, 0x11, 0xb3, 0x81, 0x2d, 0xc4, 0x6d, 0x51, 0xe9, 0xb6, 0x28, 0x94, 0x2d, 0x8a, 0xf4, + 0xa1, 0x76, 0xa6, 0x3b, 0xb3, 0xf0, 0x59, 0x65, 0xda, 0xf7, 0x26, 0x33, 0x63, 0x03, 0xb4, 0x5d, 0x84, 0x6f, 0xa0, + 0x03, 0x15, 0x42, 0xfe, 0x03, 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, 0x9a, 0xba, 0x3d, 0x2b, 0x27, 0x7b, 0xd1, 0x39, 0xd9, + 0xa7, 0xb3, 0x79, 0x20, 0xb8, 0xdc, 0xb9, 0xcf, 0xf3, 0xa9, 0x9e, 0x76, 0x95, 0x1f, 0xb4, 0x86, 0xc8, 0x7c, 0xe1, + 0x53, 0xd5, 0xbd, 0xae, 0x60, 0x01, 0x4b, 0x70, 0xb7, 0x5e, 0x9a, 0xff, 0x8a, 0xdd, 0xdf, 0x0b, 0x7a, 0x69, 0xfe, + 0x1b, 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, 0x4f, 0x19, 0xdf, 0x0b, 0x50, + 0x1b, 0x21, 0x3c, 0x5e, 0x2d, 0xca, 0x10, 0x5b, 0xf6, 0x06, 0xa9, 0xa4, 0x7e, 0x16, 0x88, 0x32, 0x5a, 0x05, 0xb4, + 0xd5, 0x1e, 0xb3, 0x34, 0xde, 0x40, 0xa8, 0x58, 0xea, 0x63, 0x08, 0x0d, 0x1c, 0x7e, 0x87, 0x03, 0x48, 0xf0, 0x25, + 0xd7, 0x64, 0x73, 0x6f, 0xf2, 0x7b, 0xda, 0xe7, 0x0f, 0x87, 0xf3, 0x4b, 0x04, 0xa5, 0x4b, 0xe1, 0x23, 0x95, 0x88, + 0xea, 0x29, 0x6e, 0x4a, 0xc8, 0x66, 0xc9, 0x4a, 0x3f, 0xf8, 0x55, 0xfd, 0x02, 0x00, 0x59, 0x08, 0xb4, 0x89, 0xcc, + 0xfe, 0x74, 0xa6, 0xa2, 0x0b, 0x80, 0x43, 0xfc, 0xf1, 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, 0xb6, 0xce, 0xd9, + 0x9d, 0xee, 0x1d, 0x39, 0x27, 0xbe, 0xbd, 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, 0xf5, 0x32, 0xee, 0x01, 0x15, 0x3a, 0x40, 0x38, 0xaf, 0xfb, 0x0d, 0xdb, 0x7d, 0xf3, + 0xcb, 0xbb, 0xa3, 0x97, 0x81, 0x4d, 0x8a, 0xc4, 0xb6, 0x92, 0xcf, 0x7a, 0xa0, 0xf0, 0xeb, 0xb1, 0x5e, 0x5d, 0xac, + 0x7b, 0xac, 0x87, 0x5a, 0x40, 0xf4, 0xb0, 0x00, 0xf5, 0x5f, 0xcf, 0x3e, 0x0d, 0x85, 0x83, 0x6c, 0x9c, 0x2a, 0x50, + 0x64, 0xc1, 0xaf, 0xc5, 0x68, 0x5d, 0x10, 0x20, 0xb2, 0x25, 0xa4, 0x55, 0x27, 0xb3, 0xc7, 0xa5, 0x96, 0x64, 0xf0, + 0x4d, 0x40, 0x66, 0x07, 0x56, 0x4e, 0x50, 0x3a, 0x6e, 0x0d, 0xb8, 0xb2, 0xc5, 0xa3, 0xdd, 0xfe, 0x34, 0xc8, 0xce, + 0x9a, 0x93, 0x46, 0xfb, 0xb0, 0x4f, 0xf3, 0x00, 0x81, 0x48, 0xa6, 0x22, 0xc8, 0x35, 0xf7, 0x96, 0xf4, 0xd1, 0xe1, + 0x9c, 0x17, 0xf2, 0xcf, 0xa9, 0xd4, 0x21, 0x0e, 0x25, 0xd6, 0x40, 0xa0, 0xf2, 0x0c, 0x55, 0x0e, 0x1b, 0xe4, 0xf8, + 0x67, 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, 0x20, 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, 0x97, 0x22, 0xaf, 0xc3, 0x2c, 0xa8, 0x46, 0x69, 0xf5, 0xa3, 0xfe, 0x09, 0xcc, 0xdb, 0x54, 0x8c, 0x6a, 0x15, + 0x93, 0xdf, 0xe8, 0xf7, 0x8b, 0x41, 0xeb, 0x43, 0x06, 0x1f, 0xbd, 0x36, 0x0d, 0xfe, 0xe8, 0x34, 0xd8, 0x61, 0xa2, + 0x11, 0x00, 0xc9, 0x9c, 0x5a, 0xf2, 0x50, 0xf4, 0x47, 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, 0x75, 0x8b, + 0xc6, 0x03, 0xdb, 0xc5, 0xf6, 0xf7, 0xdf, 0x17, 0xdb, 0xb7, 0xe1, 0x96, 0xf4, 0x0a, 0x39, 0x4b, 0xe8, 0xe7, 0x8f, + 0xb2, 0xcf, 0x1a, 0x4e, 0x4e, 0x85, 0x66, 0x68, 0x29, 0x12, 0x4a, 0xf1, 0x4e, 0x4f, 0x0a, 0x8c, 0x65, 0x2c, 0xfc, + 0x3d, 0x70, 0x4e, 0x17, 0x8a, 0xc8, 0x1d, 0x38, 0x8e, 0x6f, 0xa0, 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, 0x2c, 0x0f, 0x22, 0x80, 0x7c, 0x0e, 0xef, 0xc3, + 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, 0x5f, 0x9c, 0xc1, 0xc6, 0xb9, 0xce, 0x04, 0x07, 0x5e, 0x24, 0xb5, 0x5e, + 0x33, 0x7e, 0x9d, 0xe1, 0xba, 0x54, 0x6d, 0xf4, 0x51, 0x88, 0xce, 0x21, 0x53, 0x01, 0x0a, 0x45, 0xda, 0x3f, 0x28, + 0xb5, 0x32, 0xa9, 0xb4, 0x91, 0x00, 0xba, 0x87, 0x49, 0x83, 0x2d, 0x86, 0x32, 0x96, 0x26, 0x51, 0xee, 0x34, 0x88, + 0x2b, 0xfb, 0x73, 0x25, 0x71, 0x68, 0x59, 0x24, 0xff, 0xde, 0xf5, 0xf4, 0x15, 0x52, 0x77, 0xb2, 0x40, 0x66, 0x8c, + 0x17, 0x79, 0xfc, 0x09, 0x08, 0xb3, 0x41, 0x1b, 0x15, 0x85, 0x10, 0xb2, 0x41, 0x0c, 0x1a, 0x2f, 0xf2, 0xf8, 0x7b, + 0x45, 0xe3, 0x21, 0x1f, 0x45, 0xbe, 0xfa, 0xab, 0xd4, 0x7f, 0x85, 0x3e, 0x33, 0xc1, 0x23, 0x54, 0x13, 0xfd, 0xbb, + 0xe7, 0xb3, 0x7b, 0x50, 0x1b, 0x46, 0x61, 0x66, 0xca, 0xaf, 0x7c, 0x53, 0x9c, 0xbd, 0xfe, 0x8a, 0xae, 0xb2, 0xad, + 0xfb, 0xd1, 0xc7, 0x23, 0x02, 0x6b, 0x63, 0x74, 0xc5, 0x8d, 0x01, 0xe4, 0x30, 0x79, 0xbf, 0xa2, 0xb4, 0x1c, 0xd2, + 0x20, 0x74, 0xd0, 0x10, 0xf4, 0x4a, 0xa2, 0x0f, 0x24, 0x16, 0x31, 0x86, 0x17, 0xe2, 0x19, 0xa9, 0xc9, 0x44, 0x43, + 0xbc, 0x22, 0xf6, 0x43, 0xb4, 0xe4, 0xd4, 0x44, 0x37, 0xc2, 0x14, 0x03, 0x89, 0x9d, 0x41, 0x72, 0x92, 0xd4, 0xca, + 0x2f, 0x9e, 0x49, 0xc2, 0x12, 0x3b, 0x0f, 0x31, 0x98, 0xd4, 0xd2, 0x9d, 0xde, 0x54, 0xe9, 0xdd, 0x91, 0x96, 0x83, + 0xf6, 0x01, 0xd8, 0xa5, 0xa4, 0xf7, 0x4f, 0x0a, 0x45, 0x7c, 0x08, 0xe3, 0x18, 0xc2, 0xb7, 0x88, 0xea, 0x0a, 0x9c, + 0x6b, 0x05, 0x1a, 0xab, 0x81, 0x87, 0x66, 0x56, 0xcd, 0x87, 0x9c, 0x7e, 0x2a, 0x2d, 0x7f, 0x8c, 0x68, 0x6c, 0xb4, + 0x6e, 0x0e, 0x87, 0x3d, 0xad, 0x7a, 0xe9, 0x1c, 0x74, 0xd9, 0x4c, 0x62, 0xe2, 0x06, 0xd2, 0xf5, 0xa3, 0xdf, 0x4c, + 0xd8, 0x8b, 0xa8, 0x90, 0x4b, 0x21, 0x28, 0x68, 0x75, 0x20, 0x70, 0x28, 0xbc, 0x45, 0x99, 0x2f, 0x62, 0xda, 0x40, + 0x18, 0x7c, 0x7e, 0x20, 0x3f, 0xdf, 0x14, 0xa4, 0x62, 0xc7, 0xba, 0xf6, 0xfb, 0x9b, 0xd2, 0x03, 0x3c, 0x39, 0x93, + 0xe4, 0x69, 0x33, 0x84, 0x15, 0x01, 0x34, 0x66, 0x35, 0x59, 0x9c, 0x70, 0x65, 0x0e, 0x3f, 0x56, 0x5e, 0xc9, 0x52, + 0xa6, 0xce, 0x53, 0xbd, 0x00, 0xa2, 0x8e, 0x37, 0x68, 0x45, 0xea, 0x57, 0xe8, 0xec, 0x35, 0x2b, 0x21, 0xe3, 0xe1, + 0x39, 0xe7, 0xe9, 0xe8, 0x81, 0x25, 0x3c, 0xc2, 0xbf, 0x92, 0x89, 0x3e, 0xfc, 0x1e, 0x38, 0xdc, 0x8c, 0x13, 0x1e, + 0xb9, 0xcd, 0xde, 0x57, 0xe1, 0x0a, 0x6e, 0xa6, 0x05, 0x20, 0xb9, 0x05, 0x49, 0x13, 0x50, 0x42, 0x22, 0x13, 0x32, + 0x6b, 0x4a, 0x7e, 0x6e, 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, 0x69, 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, 0xbf, 0xde, 0x23, 0x66, 0x88, + 0xd5, 0xa0, 0x12, 0x58, 0x59, 0xca, 0xb9, 0x8f, 0x9c, 0x62, 0xca, 0x29, 0xc3, 0x4b, 0xa7, 0x33, 0x77, 0x20, 0xe7, + 0xc1, 0xcc, 0x1d, 0x26, 0x67, 0x7d, 0x8a, 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, 0x0f, 0x7a, 0xa7, 0x87, 0x5f, 0x09, 0xfb, 0x25, 0xf3, 0xec, 0x13, 0x04, 0x30, 0x49, 0xe4, 0x99, 0x84, 0xa3, + 0x1f, 0xcb, 0xd1, 0xdf, 0x34, 0xfc, 0x5d, 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, 0xac, 0xbb, 0xb0, 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, 0x3a, 0xbf, 0xab, + 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, 0x7a, 0x78, 0x96, 0xa0, 0xb9, + 0xb7, 0xc2, 0xde, 0x8b, 0x64, 0x7b, 0x26, 0xeb, 0xd4, 0xcb, 0xc8, 0xa7, 0x17, 0xee, 0xd9, 0x25, 0x57, 0x3f, 0xac, + 0xbe, 0x9e, 0xfe, 0x2a, 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, 0x77, 0xc1, 0xf7, 0x61, 0x1c, + 0x7f, 0x5f, 0x6c, 0xd5, 0x81, 0x78, 0x5b, 0x6c, 0x91, 0xf6, 0x45, 0xfe, 0x85, 0x38, 0xe0, 0xb5, 0xae, 0x29, 0xaf, + 0xad, 0x39, 0x0d, 0x6c, 0x0d, 0x23, 0x25, 0x85, 0x73, 0xf3, 0xe7, 0xe1, 0x40, 0x2b, 0xbb, 0x56, 0x77, 0x85, 0x5a, + 0x8f, 0x39, 0x6c, 0xd8, 0x8b, 0x2c, 0xdc, 0x89, 0x12, 0x1c, 0xb9, 0xe4, 0x5f, 0x87, 0x83, 0x56, 0x59, 0xaa, 0x23, + 0x7d, 0xb6, 0xff, 0x12, 0x8c, 0x19, 0xba, 0x34, 0x01, 0xcb, 0xc6, 0x48, 0xfe, 0xd5, 0x34, 0xf3, 0x86, 0xc9, 0x9a, + 0x29, 0x1c, 0x87, 0x86, 0x11, 0xd2, 0x80, 0x6e, 0x83, 0xda, 0xf0, 0x64, 0xbe, 0xa9, 0xca, 0xaf, 0xee, 0x48, 0xb5, + 0x1f, 0x0c, 0x2f, 0x27, 0xe2, 0x9c, 0x2e, 0x49, 0xea, 0xa9, 0x84, 0x92, 0x10, 0xec, 0xd2, 0x07, 0x72, 0x62, 0x05, + 0x64, 0x2d, 0x63, 0xf9, 0xad, 0x1e, 0x10, 0xfa, 0x4f, 0xbb, 0xf5, 0x42, 0xff, 0x69, 0x9a, 0x2d, 0xd4, 0xf5, 0x87, + 0xc9, 0x7d, 0x47, 0xaf, 0x3f, 0x38, 0xbc, 0x53, 0x57, 0x15, 0x57, 0xf1, 0xb0, 0x36, 0x4c, 0x72, 0xa3, 0x2c, 0xdc, + 0x15, 0x9b, 0x5a, 0x2d, 0x4f, 0xc7, 0x61, 0x04, 0x66, 0x04, 0x05, 0xc8, 0xba, 0x6e, 0x23, 0x62, 0x58, 0xc9, 0x65, + 0x42, 0x3e, 0x21, 0x20, 0x8b, 0x52, 0xe3, 0x7c, 0xdc, 0x02, 0x95, 0x08, 0x06, 0xa7, 0xa1, 0xb5, 0xea, 0x26, 0x3f, + 0xaa, 0x6c, 0xec, 0x0e, 0xc8, 0x21, 0xc9, 0x64, 0x71, 0x37, 0xba, 0x15, 0xcb, 0xa2, 0x14, 0x3f, 0x63, 0x3d, 0x5c, + 0xb3, 0x85, 0xfb, 0x0c, 0x08, 0xed, 0x27, 0x4a, 0x7b, 0x13, 0x69, 0x82, 0xee, 0x3b, 0xb6, 0x02, 0x90, 0x01, 0x14, + 0x75, 0xb5, 0x5b, 0x9f, 0xf3, 0x73, 0x24, 0xcd, 0x70, 0x18, 0xdd, 0x3e, 0xbd, 0x0b, 0xee, 0x06, 0x97, 0xa8, 0x95, + 0xbe, 0x64, 0x71, 0x0b, 0x83, 0x6a, 0x6f, 0x96, 0x70, 0x50, 0x33, 0x6b, 0x6d, 0x04, 0x82, 0xc9, 0x1e, 0x0a, 0x2a, + 0xe6, 0x0a, 0xf6, 0x41, 0xc1, 0x5a, 0xf2, 0x3a, 0x38, 0xdc, 0xda, 0x97, 0x95, 0xe2, 0xe2, 0xf9, 0x45, 0xd2, 0xba, + 0xb0, 0x94, 0x17, 0xcf, 0x1b, 0x30, 0xb8, 0x1c, 0x61, 0x53, 0x55, 0xfe, 0x64, 0x03, 0xa0, 0x5b, 0x21, 0x45, 0xbc, + 0x28, 0x85, 0x6d, 0x2b, 0x9f, 0x39, 0x61, 0x83, 0x0d, 0x7b, 0x80, 0x7b, 0x65, 0x50, 0x32, 0xb8, 0x10, 0xe3, 0x76, + 0xb3, 0x0b, 0x70, 0x05, 0x43, 0x61, 0x6c, 0xcd, 0x5f, 0x67, 0x5e, 0xa4, 0x04, 0xdc, 0x0c, 0x51, 0xbe, 0x36, 0x70, + 0x32, 0xe9, 0xc9, 0xb5, 0x64, 0x31, 0x60, 0x41, 0x83, 0xef, 0xa8, 0xf5, 0x77, 0x26, 0xff, 0xc6, 0xd3, 0x43, 0x3f, + 0xf8, 0x9c, 0x79, 0x4b, 0x9f, 0xbd, 0xae, 0x64, 0xb4, 0x26, 0x89, 0xf2, 0xea, 0xe1, 0x12, 0xe4, 0x86, 0xe5, 0xe8, + 0x81, 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, 0x3d, 0x34, 0xec, 0x47, 0x2f, 0xb4, 0xec, 0x0f, 0x77, + 0x5a, 0xd3, 0xb0, 0xe2, 0x77, 0x30, 0x2d, 0x26, 0x6e, 0x5f, 0xae, 0xec, 0xaa, 0xf8, 0x6c, 0xa5, 0xce, 0x6e, 0x6a, + 0x48, 0xc2, 0xbe, 0x22, 0xab, 0x00, 0x07, 0xab, 0x22, 0xee, 0x59, 0x96, 0xfb, 0x30, 0xfa, 0x73, 0x93, 0x96, 0xc2, + 0x42, 0x95, 0xf4, 0xf7, 0x4d, 0x29, 0x90, 0xca, 0x44, 0x27, 0x5a, 0x08, 0xae, 0xc0, 0x20, 0x70, 0x2f, 0xf2, 0x1a, + 0x00, 0x63, 0xc0, 0xa5, 0x40, 0x59, 0xb6, 0x25, 0x84, 0x54, 0xf7, 0x33, 0x50, 0xdb, 0x89, 0xfb, 0x34, 0x22, 0x6b, + 0x21, 0xfa, 0x2a, 0x18, 0x33, 0xe7, 0xa5, 0x74, 0x8b, 0x4d, 0x57, 0x9b, 0xd5, 0x0d, 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, 0x45, 0x5d, 0xa3, + 0x29, 0xd4, 0x6a, 0xe1, 0xb8, 0xd1, 0xce, 0xa6, 0xcb, 0xf4, 0x0e, 0x71, 0x56, 0xa5, 0x1d, 0xfa, 0xfb, 0x4c, 0xbb, + 0x5e, 0x76, 0xf4, 0x9b, 0x71, 0x75, 0x81, 0x0b, 0xb1, 0x01, 0x9f, 0x73, 0x7f, 0x79, 0xbd, 0xe7, 0x71, 0xcf, 0x3f, + 0x1c, 0x90, 0x3d, 0xa9, 0xfd, 0xa1, 0xfa, 0xd8, 0x15, 0x0c, 0x59, 0x18, 0xa5, 0xfe, 0x22, 0xe5, 0xbd, 0x27, 0x38, + 0xee, 0x9f, 0xab, 0x1e, 0xfb, 0x31, 0xe3, 0xfb, 0xba, 0xd8, 0x44, 0x09, 0x45, 0x35, 0xf4, 0x56, 0xc5, 0xa6, 0x12, + 0x71, 0xf1, 0x90, 0xf7, 0x18, 0x26, 0xc3, 0x58, 0xc8, 0x54, 0xf8, 0x53, 0xa6, 0x82, 0x47, 0x08, 0x25, 0x6e, 0xd6, + 0x3d, 0xd2, 0x6e, 0x42, 0x9c, 0x52, 0x2d, 0x4a, 0x99, 0x8c, 0x7f, 0xeb, 0x27, 0x50, 0x9e, 0x53, 0xb4, 0x4c, 0x3f, + 0x2a, 0x5c, 0xa6, 0x6f, 0xd6, 0xc7, 0xa5, 0x67, 0x22, 0xd4, 0x99, 0x8b, 0x4d, 0xad, 0xd3, 0x31, 0x76, 0x4a, 0xa7, + 0x36, 0xec, 0x4b, 0xa5, 0xb8, 0xac, 0x28, 0xfc, 0x1b, 0x89, 0xac, 0x7a, 0x46, 0x1c, 0xff, 0x57, 0xd6, 0x3e, 0xc3, + 0x2a, 0xf0, 0xcb, 0x40, 0xde, 0x2f, 0x00, 0x3e, 0xae, 0xeb, 0x32, 0xbd, 0xdd, 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, 0x36, 0x2b, 0xa2, + 0x3f, 0x7a, 0xe8, 0xef, 0xb8, 0xbd, 0x49, 0xbf, 0x40, 0xb4, 0x8c, 0xf5, 0x37, 0x64, 0x40, 0xc7, 0x93, 0xe1, 0x6d, + 0xb1, 0xed, 0xb1, 0x2f, 0xa8, 0xc1, 0xd2, 0xd7, 0x8f, 0x3f, 0x40, 0x42, 0xd5, 0xb5, 0x2f, 0x2c, 0x9e, 0x30, 0x4f, + 0x89, 0xb6, 0x85, 0x0f, 0x61, 0xa1, 0x5f, 0x20, 0x32, 0x12, 0xc2, 0x4d, 0x65, 0xf7, 0x28, 0x69, 0x17, 0xfa, 0xd2, + 0xd7, 0xb2, 0xaf, 0x7c, 0xe7, 0x02, 0x60, 0x65, 0x9f, 0xdb, 0x70, 0x4f, 0xfa, 0x53, 0xaa, 0x0f, 0xdb, 0xdf, 0x92, + 0x05, 0x14, 0x5a, 0x58, 0x4f, 0xe5, 0xec, 0x5c, 0x97, 0x3c, 0xcd, 0xa6, 0xfb, 0x35, 0xec, 0x51, 0xf7, 0xe8, 0x35, + 0x15, 0x9c, 0x5f, 0x9a, 0xd1, 0xfb, 0xa7, 0xa1, 0x50, 0x1d, 0x75, 0xee, 0x20, 0xeb, 0xd2, 0xba, 0xe4, 0xfc, 0x66, + 0xe5, 0x8e, 0xc2, 0xfc, 0x3e, 0x04, 0xcf, 0xb0, 0xee, 0xdd, 0xc5, 0x79, 0xef, 0xcf, 0xd6, 0x1c, 0xf9, 0x31, 0x9b, + 0xa5, 0x88, 0x45, 0x32, 0x07, 0xab, 0x1f, 0xfa, 0x79, 0xec, 0xb7, 0x41, 0x0e, 0xc7, 0x4d, 0x03, 0x3a, 0x6c, 0xc8, + 0xac, 0x7d, 0x89, 0xc0, 0xa9, 0x46, 0x90, 0xa6, 0x26, 0xa8, 0x59, 0x1e, 0x22, 0xb1, 0x5d, 0xca, 0xb6, 0x41, 0xae, + 0xbb, 0x60, 0x9a, 0x23, 0xed, 0x19, 0xbc, 0x6f, 0xd2, 0x24, 0x15, 0x9a, 0x45, 0xda, 0x2a, 0x19, 0xff, 0x8e, 0xb4, + 0x99, 0x92, 0x3d, 0xb6, 0x06, 0xde, 0x4b, 0x50, 0x4e, 0x86, 0x29, 0x86, 0xef, 0xf8, 0x7a, 0xe7, 0x31, 0xf7, 0x9c, + 0x63, 0xb6, 0x49, 0xd9, 0x11, 0x4c, 0x92, 0x8d, 0x6f, 0x28, 0xde, 0xf0, 0xfd, 0x6d, 0x25, 0x4a, 0x00, 0xbd, 0x2c, + 0xf8, 0xb5, 0xb4, 0xb9, 0x42, 0xb7, 0xbb, 0x77, 0x94, 0xc2, 0x2f, 0x79, 0x79, 0x38, 0x6c, 0x53, 0x2f, 0x84, 0xce, + 0x17, 0xf1, 0x3b, 0x30, 0x87, 0x31, 0xc4, 0x66, 0x04, 0x08, 0x73, 0x7c, 0x40, 0x1d, 0xac, 0x1f, 0x01, 0x68, 0x9c, + 0x40, 0x01, 0x46, 0x5f, 0x6d, 0x0b, 0xfa, 0x96, 0x17, 0x17, 0x11, 0xa2, 0x46, 0x01, 0x26, 0x4a, 0x9a, 0xc5, 0x30, + 0x1c, 0xe8, 0xfc, 0xbe, 0xb9, 0xad, 0x4b, 0x81, 0x43, 0xef, 0x58, 0x86, 0xff, 0xfe, 0x3f, 0xd6, 0x96, 0x56, 0x95, + 0xed, 0xd6, 0x38, 0xcd, 0xfc, 0x6f, 0xb7, 0x85, 0xbe, 0xff, 0x52, 0x28, 0x9e, 0x77, 0xbc, 0x6e, 0xbf, 0x83, 0xe8, + 0x7d, 0xdd, 0xca, 0xbb, 0x52, 0xbb, 0x61, 0xa6, 0xfc, 0x21, 0xcd, 0xe3, 0xe2, 0x61, 0x14, 0xb7, 0x8e, 0xbc, 0x49, + 0x7a, 0xce, 0xf9, 0xbb, 0xaa, 0xdf, 0xf7, 0xde, 0x01, 0x19, 0xef, 0x4b, 0x61, 0x1c, 0x31, 0x89, 0x83, 0x6f, 0x2f, + 0x46, 0xd1, 0xa6, 0x84, 0x0d, 0xb9, 0x7d, 0x5a, 0x82, 0x66, 0xa6, 0xdf, 0x47, 0x89, 0xd2, 0x9a, 0xef, 0x7f, 0x93, + 0xf3, 0xfd, 0xa5, 0x90, 0x37, 0x2b, 0xf9, 0xe1, 0xa3, 0x15, 0x06, 0xbe, 0xc7, 0xe9, 0x17, 0xd1, 0x63, 0x77, 0xa5, + 0x0f, 0xdf, 0x95, 0x96, 0x3e, 0xab, 0xa8, 0x7f, 0xa0, 0xa2, 0xe6, 0xa5, 0x18, 0x11, 0xf1, 0x20, 0x68, 0x67, 0xdb, + 0xa5, 0x76, 0x2d, 0x41, 0xbb, 0x60, 0x53, 0xd8, 0xbf, 0x1f, 0x1d, 0xf2, 0x7e, 0xff, 0x63, 0xee, 0xb5, 0x78, 0xdd, + 0x75, 0x68, 0xca, 0x4f, 0x85, 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, 0x11, 0xeb, 0xa6, + 0xa7, 0x55, 0x68, 0xf9, 0x1a, 0x82, 0x75, 0x91, 0x65, 0x1c, 0xc5, 0x4c, 0x00, 0xb0, 0xf9, 0x08, 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, 0x7b, 0xaa, 0x7a, 0x44, 0xa0, 0x57, 0x65, 0x5a, + 0x45, 0x45, 0x9e, 0x8b, 0x08, 0x11, 0xaa, 0xa5, 0x73, 0x38, 0xf4, 0x63, 0xbf, 0x8f, 0x03, 0x61, 0x5e, 0xfc, 0xe9, + 0xb1, 0xae, 0xfc, 0xa9, 0xc0, 0xb5, 0x92, 0x02, 0xa7, 0xa2, 0x46, 0x88, 0x10, 0xde, 0x9f, 0xc0, 0xb3, 0x9a, 0xfa, + 0x7e, 0x63, 0x99, 0xe8, 0xfe, 0x99, 0x01, 0xe5, 0x0f, 0xc8, 0xd7, 0x95, 0x14, 0x67, 0xea, 0xe4, 0x31, 0x71, 0xc6, + 0x01, 0x88, 0xf9, 0xba, 0x44, 0xa3, 0xb1, 0xff, 0x01, 0x09, 0x86, 0xea, 0x07, 0x3b, 0xdd, 0xd4, 0xfb, 0x57, 0x26, + 0x71, 0x14, 0x7d, 0xda, 0x26, 0x8f, 0x25, 0x4b, 0xa3, 0x85, 0xa3, 0xf7, 0x88, 0x61, 0x1c, 0x4e, 0xe7, 0x63, 0x92, + 0x6d, 0x4c, 0x56, 0x01, 0xa4, 0x93, 0x99, 0x3a, 0xa6, 0xd4, 0xd1, 0x38, 0xd7, 0x0b, 0xaa, 0xd0, 0x63, 0x5d, 0xf2, + 0x1c, 0xac, 0x27, 0x3f, 0x78, 0xa5, 0x3f, 0x15, 0x72, 0x0e, 0x1b, 0x89, 0xa0, 0xf0, 0x03, 0x5c, 0x0d, 0x56, 0x0a, + 0x18, 0x4c, 0x7d, 0x0b, 0x5f, 0x13, 0xcf, 0x51, 0xf0, 0x28, 0xec, 0x62, 0x6c, 0xad, 0x7c, 0xe7, 0x93, 0x82, 0x72, + 0xcf, 0x8a, 0x39, 0xaf, 0x80, 0x73, 0x19, 0x14, 0xc2, 0x74, 0x3c, 0xcb, 0xff, 0x99, 0xe4, 0xf5, 0xc4, 0x86, 0x00, + 0x19, 0xfc, 0x29, 0x71, 0x5a, 0xba, 0x43, 0x77, 0x1e, 0x7a, 0x16, 0x71, 0xd8, 0xe8, 0xc9, 0xba, 0x2c, 0xb6, 0x29, + 0xea, 0x25, 0xcc, 0x0f, 0xe4, 0xe7, 0x2d, 0xf9, 0x3e, 0x44, 0xf1, 0x36, 0xf8, 0x35, 0x63, 0xb1, 0xc0, 0xbf, 0xfe, + 0x9e, 0x31, 0x9a, 0x68, 0xc1, 0xbf, 0xb3, 0x06, 0x89, 0x8a, 0x7f, 0xca, 0x26, 0x00, 0xeb, 0xc8, 0xd5, 0x87, 0x4f, + 0x89, 0xf1, 0xd6, 0x6c, 0x78, 0xe4, 0x9b, 0x15, 0xe8, 0xd4, 0xe7, 0xee, 0xca, 0xf6, 0x54, 0x35, 0xfe, 0x9e, 0xea, + 0x6a, 0xa4, 0xaa, 0x1a, 0x7f, 0x4f, 0xa9, 0x1a, 0xbf, 0x65, 0x14, 0xbf, 0x53, 0xf9, 0x0c, 0x99, 0x93, 0x4d, 0x4c, + 0xd2, 0xe9, 0x7b, 0xc3, 0x89, 0x5d, 0xf6, 0xab, 0xb7, 0x89, 0xcc, 0x44, 0x0a, 0xb9, 0x37, 0x00, 0x6d, 0xbf, 0xcb, + 0x0d, 0xa7, 0xc4, 0xf9, 0xb9, 0x87, 0x2b, 0x36, 0xad, 0x5e, 0xd2, 0x82, 0x05, 0x36, 0x2f, 0xb3, 0x3c, 0x45, 0x02, + 0xdb, 0xa6, 0xcc, 0xfa, 0x73, 0xee, 0x01, 0x04, 0x33, 0xa9, 0x09, 0x00, 0x69, 0x21, 0x2a, 0x85, 0xc8, 0x5f, 0xe2, + 0xac, 0x3e, 0xe7, 0xbd, 0x4d, 0x1e, 0x13, 0x69, 0x75, 0xaf, 0xdf, 0x4f, 0xcf, 0xd2, 0x9c, 0x82, 0x1a, 0x8e, 0xb3, + 0x4e, 0xbf, 0xcf, 0x82, 0x3a, 0x91, 0xab, 0xf4, 0x1f, 0x6e, 0x90, 0x97, 0xf1, 0x7d, 0xdd, 0xf6, 0xfc, 0x89, 0xfa, + 0x7b, 0x67, 0xfd, 0x6d, 0x81, 0xe0, 0x4e, 0x8e, 0xfd, 0x64, 0x55, 0xca, 0x13, 0xe3, 0xd2, 0xde, 0xf3, 0x9b, 0xba, + 0x28, 0xb2, 0x3a, 0x5d, 0x7f, 0x90, 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, 0xe8, 0x40, 0xbd, 0xb4, 0xd2, 0x3e, 0x82, 0x6e, 0x05, 0x7a, 0x50, 0x0f, 0x7d, 0x9a, 0xb4, 0x2f, + 0x24, 0xea, 0xf6, 0x56, 0xa7, 0xd1, 0x1f, 0x15, 0x5c, 0x4e, 0x61, 0x72, 0xb8, 0xa1, 0x4f, 0xab, 0x70, 0xfb, 0x09, + 0x9e, 0xfe, 0x0c, 0x94, 0x5b, 0x87, 0x43, 0x0e, 0x62, 0x0b, 0xb8, 0x79, 0xac, 0xc2, 0xcf, 0x45, 0x29, 0x23, 0xea, + 0xe3, 0x69, 0x01, 0xda, 0xbb, 0x00, 0x1d, 0xb0, 0x34, 0x88, 0x57, 0x48, 0x9e, 0xb3, 0x11, 0xc0, 0xb2, 0x03, 0xcb, + 0x59, 0xc6, 0x29, 0xcc, 0xb3, 0xbc, 0x56, 0x2b, 0xed, 0xac, 0x4c, 0xbc, 0x9a, 0x65, 0xe0, 0x2c, 0x70, 0x51, 0xf9, + 0x2c, 0xd3, 0xaa, 0xa7, 0x2a, 0x41, 0x9f, 0x57, 0x72, 0x82, 0x2b, 0xc1, 0xc9, 0x06, 0xe4, 0x17, 0x20, 0x49, 0x53, + 0xca, 0x9a, 0xf2, 0xfa, 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, 0x0f, 0xde, 0xd2, 0x9f, 0x8e, 0x83, 0x70, 0x88, 0xdc, + 0x50, 0x31, 0x07, 0xf6, 0x34, 0x60, 0xb1, 0x89, 0xaf, 0x36, 0x93, 0x78, 0x30, 0xf0, 0x75, 0xc6, 0x62, 0x16, 0x03, + 0x0d, 0x72, 0x3c, 0xb8, 0x9c, 0xeb, 0x13, 0x42, 0x3f, 0x8c, 0xa8, 0x1c, 0x15, 0xe8, 0x1c, 0x44, 0x83, 0x25, 0xe0, + 0xa9, 0xb7, 0xb2, 0x41, 0x92, 0x31, 0xc9, 0x24, 0xae, 0x35, 0x49, 0x75, 0x38, 0xa1, 0x75, 0xa0, 0xe3, 0xea, 0x02, + 0x3a, 0x1f, 0xd7, 0xbd, 0x8f, 0x57, 0xc3, 0x05, 0x95, 0x7e, 0x21, 0x06, 0x5e, 0x3d, 0x1d, 0x07, 0x97, 0x74, 0x2b, + 0x5c, 0xac, 0xc2, 0xed, 0xcf, 0xf2, 0x81, 0xe3, 0x8e, 0x4a, 0x1a, 0x02, 0x83, 0xb7, 0x87, 0xee, 0x66, 0x86, 0x86, + 0x3a, 0x69, 0x1f, 0xc6, 0xa1, 0x1c, 0x62, 0xd5, 0x8a, 0x0b, 0xe9, 0x8d, 0xe0, 0xdb, 0x85, 0x62, 0x2c, 0x1b, 0xbb, + 0x34, 0x14, 0x85, 0xbf, 0x02, 0xd8, 0xa1, 0xf6, 0x57, 0x2a, 0xf9, 0x18, 0x19, 0xd5, 0x34, 0xd0, 0x31, 0x00, 0x4b, + 0x96, 0x26, 0x92, 0x2a, 0xd2, 0x48, 0xfc, 0x91, 0x19, 0xeb, 0xa8, 0xe9, 0xfa, 0x82, 0xa9, 0x6a, 0x91, 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, 0x28, 0x93, 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, 0x99, 0x63, 0x92, 0xfe, 0x5b, 0xa7, 0x13, 0xf6, 0x0b, + 0x2f, 0xb7, 0xb5, 0xbc, 0x69, 0xee, 0xbd, 0xf0, 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, 0x13, 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, 0x61, 0x6b, 0xa6, 0x5b, 0x60, 0x00, 0x30, 0x88, 0x08, + 0x96, 0xfb, 0xdc, 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, 0x92, 0x25, 0x9a, 0x4a, + 0x1c, 0x8d, 0x91, 0x53, 0x69, 0x8c, 0x0c, 0x88, 0x5d, 0x1c, 0xff, 0x9e, 0xd2, 0xa3, 0x20, 0x65, 0x9f, 0x2b, 0x43, + 0x1c, 0x8e, 0xe2, 0x2b, 0x58, 0x35, 0x0e, 0x87, 0xda, 0xbc, 0x9e, 0xce, 0xea, 0xf9, 0x40, 0x04, 0xf0, 0xdf, 0x50, + 0xb0, 0x5f, 0x34, 0x15, 0xb9, 0x41, 0xea, 0x3c, 0x1c, 0x52, 0x90, 0x4f, 0x75, 0x93, 0xbf, 0xaf, 0xdc, 0xfd, 0x74, + 0x36, 0xb7, 0xe6, 0xe8, 0x45, 0x8d, 0xeb, 0xd6, 0xea, 0x86, 0x42, 0xa2, 0x35, 0x4d, 0x8a, 0xab, 0x6a, 0x52, 0x0c, + 0x78, 0xee, 0x0b, 0xd5, 0xc5, 0xd6, 0x08, 0x16, 0xfe, 0xdc, 0x02, 0x61, 0x32, 0xee, 0xc5, 0x47, 0x0b, 0x39, 0xa5, + 0x5d, 0x5b, 0xed, 0xb6, 0x95, 0x0d, 0x29, 0x9a, 0x0f, 0x2f, 0x61, 0x97, 0x4e, 0x11, 0x6d, 0xbb, 0x24, 0xf8, 0x02, + 0xb4, 0xac, 0x2e, 0x44, 0x1e, 0xd3, 0xaf, 0x90, 0x5f, 0x8a, 0xe1, 0x5f, 0xa5, 0x7b, 0x73, 0x6a, 0x83, 0x1c, 0xc0, + 0x76, 0xef, 0xe1, 0x76, 0x8c, 0x1e, 0xc8, 0xe0, 0x8d, 0x90, 0x73, 0xce, 0x2f, 0xa7, 0xd6, 0x8c, 0x89, 0x86, 0x05, + 0x2b, 0x87, 0x91, 0x1f, 0x20, 0xe3, 0xe5, 0x14, 0x58, 0xd9, 0x8f, 0x8a, 0xb8, 0xf4, 0x87, 0x91, 0x7f, 0xf1, 0x3c, + 0xc8, 0xb8, 0x17, 0x0d, 0x3b, 0xbe, 0x00, 0x7b, 0xf5, 0xc5, 0x73, 0x16, 0x0d, 0x78, 0x75, 0x55, 0x4f, 0xb3, 0x60, + 0x98, 0xb1, 0xe8, 0xaa, 0x18, 0x82, 0x0f, 0xed, 0x75, 0x39, 0x08, 0x7d, 0xdf, 0xec, 0x1c, 0xba, 0x1b, 0x12, 0x79, + 0x84, 0xfd, 0x08, 0x6e, 0xbb, 0x5a, 0x62, 0x06, 0x93, 0xcd, 0x5d, 0xc4, 0x0c, 0xb6, 0xfc, 0xc5, 0x73, 0xc3, 0x25, + 0x54, 0x5d, 0x4b, 0xcd, 0x46, 0x81, 0xe6, 0xe4, 0x0a, 0xcd, 0xc9, 0x4a, 0xa8, 0x25, 0x9f, 0x54, 0x38, 0x61, 0xe7, + 0x93, 0x5c, 0xd9, 0x8d, 0xc6, 0x18, 0xb8, 0x68, 0xcf, 0x6d, 0x61, 0x64, 0xa6, 0xb3, 0x14, 0x0d, 0x58, 0x78, 0x26, + 0x4e, 0x69, 0x0c, 0x68, 0x5f, 0x0e, 0x2c, 0x6d, 0xc8, 0x8f, 0x72, 0x66, 0xa0, 0x6d, 0x48, 0x69, 0xd4, 0x0c, 0xfc, + 0x99, 0x9a, 0x30, 0xbf, 0x82, 0x95, 0x08, 0xa2, 0xba, 0x00, 0x93, 0x24, 0x27, 0xa3, 0x91, 0xb2, 0x12, 0xc9, 0x39, + 0xe0, 0x7d, 0x04, 0x4f, 0x16, 0xb1, 0xad, 0xfd, 0x29, 0xfd, 0xaf, 0x0e, 0x9f, 0x4b, 0xff, 0x99, 0x00, 0x16, 0x72, + 0x69, 0x10, 0x19, 0x28, 0x1c, 0x52, 0x53, 0x89, 0x38, 0x71, 0x3c, 0x03, 0x5f, 0xc3, 0x05, 0x9a, 0x02, 0xfa, 0x83, + 0x9a, 0x51, 0x44, 0x16, 0xfe, 0xea, 0xd9, 0x4d, 0xdd, 0xe8, 0x79, 0xe6, 0xbc, 0x06, 0xcd, 0x0c, 0x84, 0xf4, 0x38, + 0x55, 0x6f, 0x43, 0xa2, 0xf3, 0xf2, 0x52, 0xbf, 0x4c, 0x88, 0x64, 0x45, 0xe4, 0xe9, 0xfb, 0x1c, 0xcc, 0x23, 0x8a, + 0xd0, 0xc1, 0x95, 0x79, 0x38, 0x9c, 0x0b, 0x0a, 0xdf, 0x51, 0x9e, 0x0f, 0x38, 0xcd, 0xa2, 0x04, 0xb4, 0x81, 0x2c, + 0x37, 0x65, 0xae, 0x93, 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, 0x5f, 0x57, 0x08, 0x06, 0x11, 0xfa, 0x0c, 0xf9, 0x93, 0xe5, 0xfc, 0xbb, 0x75, 0x98, 0x76, 0x84, + 0x0f, 0xbb, 0xda, 0x82, 0x8b, 0xd9, 0xed, 0x7c, 0x02, 0xf1, 0x2d, 0xb7, 0xf3, 0x63, 0x0c, 0x91, 0x85, 0x3f, 0xb8, + 0x1b, 0x4a, 0xae, 0x28, 0x74, 0x59, 0x8f, 0x48, 0x91, 0x3d, 0x5d, 0x73, 0x04, 0xc1, 0x81, 0x56, 0x0d, 0x32, 0x34, + 0x12, 0x5f, 0x3c, 0x87, 0xac, 0xc1, 0x9a, 0x7f, 0xae, 0xc8, 0x59, 0xdd, 0x9f, 0x6c, 0xa0, 0x9a, 0x64, 0xb2, 0x56, + 0x54, 0xce, 0x5f, 0xaf, 0xca, 0xf2, 0x64, 0x55, 0x86, 0xab, 0x41, 0x57, 0x55, 0x96, 0x1c, 0xa9, 0x0d, 0xd0, 0x9a, + 0xae, 0x10, 0x43, 0x21, 0x6b, 0xb0, 0xb4, 0xaa, 0xb2, 0xa6, 0x3e, 0x81, 0x40, 0x1f, 0x60, 0x19, 0x35, 0xfb, 0xe9, + 0xf0, 0x5f, 0xc1, 0xbf, 0x54, 0xc8, 0x52, 0x9d, 0xd6, 0x99, 0xf8, 0x35, 0x58, 0x32, 0xfc, 0xe3, 0xb7, 0x60, 0x0d, + 0x58, 0x02, 0x64, 0xb9, 0xdb, 0xd8, 0x68, 0xbd, 0xf2, 0x0a, 0xf1, 0xa5, 0xd6, 0x17, 0xfd, 0xd6, 0x6d, 0xa2, 0x56, + 0x80, 0x11, 0x0a, 0x2d, 0x02, 0x6c, 0xf5, 0xc0, 0x3d, 0x05, 0x3f, 0x10, 0xc3, 0xb9, 0x26, 0xad, 0xa9, 0x13, 0x5e, + 0x67, 0xe3, 0x48, 0x44, 0xf5, 0x16, 0x2e, 0xee, 0xf5, 0xd6, 0xe2, 0x6f, 0x54, 0x20, 0x00, 0xb2, 0x98, 0x62, 0xed, + 0xbc, 0x21, 0xbd, 0x32, 0xec, 0x24, 0xf4, 0xde, 0xb0, 0x13, 0xc8, 0x8b, 0xc3, 0x4e, 0xa1, 0x4b, 0xb4, 0x9d, 0x22, + 0x35, 0xd1, 0x76, 0xd2, 0x62, 0x15, 0x96, 0x10, 0xfc, 0xaa, 0xbd, 0x75, 0x94, 0xed, 0x8b, 0x2c, 0x61, 0xda, 0x02, + 0x46, 0xb9, 0x55, 0x9f, 0x39, 0x45, 0xac, 0x94, 0xbd, 0xd3, 0x49, 0x95, 0xbb, 0xc8, 0xa7, 0x56, 0x53, 0x64, 0xf2, + 0xf7, 0xc7, 0x2d, 0x92, 0x4f, 0x7e, 0x6e, 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, 0x4f, + 0x62, 0x5b, 0xbf, 0x84, 0x2b, 0x36, 0xdf, 0x37, 0x8a, 0x9e, 0x5c, 0x9f, 0xa2, 0x6e, 0xc5, 0xd5, 0x69, 0xda, 0x6a, + 0x8e, 0x1d, 0x67, 0xc8, 0xc1, 0xb3, 0x82, 0x60, 0x3b, 0x2a, 0x51, 0xbe, 0x6d, 0x37, 0x1d, 0x13, 0x5b, 0xfd, 0xb3, + 0xa8, 0x36, 0x77, 0x50, 0x11, 0x11, 0x1f, 0x65, 0x37, 0x4f, 0xda, 0xef, 0x60, 0x8f, 0xb5, 0x1a, 0x44, 0xf6, 0x19, + 0x5c, 0xe5, 0x3a, 0x2d, 0x72, 0x5b, 0x06, 0xe7, 0x1f, 0x5e, 0xed, 0x2a, 0x6c, 0x72, 0xac, 0xab, 0xab, 0x99, 0xea, + 0xa4, 0x62, 0x03, 0x63, 0x4d, 0x6b, 0xa9, 0xe6, 0x31, 0x24, 0xdd, 0x95, 0xc5, 0x59, 0x95, 0x74, 0xd3, 0x73, 0xe3, + 0x4c, 0x21, 0x06, 0xce, 0x56, 0xa3, 0xe5, 0x0c, 0x43, 0x74, 0x7d, 0x98, 0x25, 0x7e, 0xab, 0xa7, 0xdc, 0xe7, 0xe1, + 0xd6, 0xef, 0xea, 0x05, 0x27, 0x93, 0xfd, 0xe4, 0x38, 0x77, 0xbb, 0x48, 0xfb, 0x89, 0x6f, 0xc3, 0xfc, 0xeb, 0x1b, + 0xc4, 0x9d, 0xa8, 0xff, 0x59, 0x01, 0xd0, 0xe0, 0x26, 0x8f, 0x25, 0x4a, 0xfd, 0x5e, 0x55, 0x3f, 0xa8, 0x99, 0xaa, + 0x69, 0x20, 0x98, 0x53, 0x29, 0xe0, 0x0f, 0xb7, 0x0b, 0x57, 0x3c, 0xe2, 0x86, 0x85, 0xf1, 0x4f, 0xaf, 0x66, 0xa7, + 0x82, 0xca, 0xc0, 0xcd, 0xf8, 0x4f, 0x4f, 0xb0, 0x53, 0x58, 0x2b, 0x20, 0x2b, 0xfc, 0xe9, 0xe5, 0x8f, 0xbc, 0x5f, + 0xf1, 0x3f, 0xbd, 0xea, 0x91, 0xf7, 0x11, 0xe7, 0xe5, 0x4f, 0x24, 0x75, 0x42, 0x54, 0x97, 0x3f, 0x09, 0x53, 0x6c, + 0x95, 0xe6, 0xaf, 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, 0x0d, 0xeb, 0x28, 0x49, + 0xf3, 0x3b, 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, + 0xeb, 0x1c, 0x63, 0x2b, 0x72, 0xe0, 0x40, 0x86, 0x1f, 0x10, 0x78, 0x2f, 0xfb, 0x57, 0x30, 0x18, 0x26, 0xb8, 0x91, + 0x51, 0x27, 0xe7, 0xec, 0x4f, 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, 0xd6, 0xad, 0x51, 0xbe, 0xf7, 0x4f, 0x89, 0x72, 0xb0, 0x7f, 0xe5, + 0xa2, 0xf9, 0xdb, 0x4f, 0x19, 0x92, 0x0a, 0xcd, 0x0d, 0xb6, 0x93, 0x2d, 0xc2, 0xda, 0x18, 0x07, 0x15, 0xbb, 0x2b, + 0xc3, 0x08, 0x18, 0xd4, 0xb1, 0xff, 0xd1, 0x67, 0xd3, 0x86, 0xec, 0x03, 0x40, 0xe5, 0x2a, 0x04, 0xec, 0x01, 0x38, + 0xd1, 0x08, 0x37, 0xc0, 0xad, 0x46, 0x4b, 0x3a, 0xa8, 0xdb, 0x82, 0x81, 0x68, 0x09, 0x1b, 0x79, 0xdb, 0xd5, 0xe9, + 0x2b, 0xc2, 0x87, 0xda, 0x49, 0xe9, 0x50, 0xfe, 0xea, 0x39, 0xfb, 0x9f, 0x1d, 0xd6, 0xd4, 0x94, 0x1b, 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, 0x2b, 0xfd, 0x54, 0xd5, 0x24, 0x16, 0xe0, 0x72, 0x92, + 0xe6, 0x1d, 0x8f, 0xb0, 0xfa, 0xc7, 0xc9, 0x52, 0x04, 0x7a, 0x15, 0xd1, 0xae, 0x04, 0x24, 0x68, 0x27, 0x67, 0xa1, + 0x22, 0x50, 0xa0, 0xaf, 0x7f, 0xbf, 0x49, 0xb3, 0x58, 0xae, 0x66, 0x7b, 0x98, 0x28, 0x8b, 0xf5, 0x10, 0x41, 0xce, + 0x4c, 0x1d, 0xec, 0xf7, 0x34, 0xa3, 0x59, 0x78, 0x65, 0x4a, 0x70, 0x29, 0xae, 0xa2, 0x22, 0x07, 0x9f, 0x43, 0x7c, + 0xe1, 0x53, 0x21, 0x37, 0x88, 0x68, 0xfa, 0xbd, 0x44, 0xb5, 0x23, 0x05, 0x72, 0x28, 0xf9, 0x09, 0xf1, 0x97, 0xac, + 0x8d, 0x71, 0xbf, 0x74, 0xaa, 0xfd, 0x52, 0x21, 0xb8, 0xff, 0x6c, 0x8b, 0x8d, 0x2a, 0x4f, 0xf4, 0xe8, 0x53, 0xac, + 0xff, 0xc9, 0x02, 0x4a, 0x75, 0xdf, 0x06, 0xa7, 0xe2, 0x51, 0xb8, 0xa9, 0x8b, 0x1b, 0x84, 0x16, 0x28, 0x47, 0x55, + 0xb1, 0x29, 0x23, 0xe2, 0x84, 0xdd, 0xd4, 0x45, 0x4f, 0x73, 0xa0, 0x53, 0x87, 0xa5, 0x89, 0x3c, 0x11, 0xda, 0x2d, + 0xe8, 0x9e, 0xe6, 0x58, 0x89, 0x17, 0xb2, 0x74, 0x90, 0x75, 0x22, 0x4d, 0xa8, 0xdc, 0xd5, 0x55, 0x47, 0xa5, 0x52, + 0x37, 0xbc, 0x4e, 0x35, 0xe3, 0xef, 0xd2, 0xfc, 0x89, 0x65, 0xbf, 0x6e, 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, 0x16, 0xc5, 0x1f, 0x95, 0xbe, + 0x23, 0xd0, 0xd1, 0x9d, 0x17, 0x75, 0xba, 0xdc, 0x7d, 0x20, 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, 0x97, 0xb8, 0xbf, 0x54, 0xe4, 0x62, 0xdf, 0x39, 0xa3, 0x3b, 0x33, 0xeb, 0x5e, 0x55, 0xb8, 0x5a, 0x90, + 0xab, 0x03, 0x5b, 0xcb, 0x2e, 0x0e, 0x37, 0x2c, 0xa2, 0x00, 0x81, 0x98, 0x5e, 0xa9, 0xb5, 0x3f, 0xa2, 0x41, 0xc8, + 0x07, 0x03, 0xbf, 0xc0, 0x60, 0x55, 0xa0, 0xf0, 0x81, 0x22, 0xf9, 0x2b, 0x4f, 0xc0, 0x2e, 0x9e, 0x01, 0xba, 0x15, + 0x9b, 0x15, 0x23, 0x44, 0xc8, 0x64, 0x39, 0xab, 0xe9, 0x0c, 0xf2, 0xa9, 0x2f, 0xbe, 0xb1, 0x55, 0xa7, 0xf3, 0xb6, + 0xa6, 0xca, 0xa9, 0x43, 0xa1, 0xbb, 0x9b, 0xba, 0x73, 0xeb, 0x22, 0x4f, 0x1d, 0x42, 0xae, 0x54, 0xac, 0xc4, 0x34, + 0xd4, 0x3c, 0x49, 0x33, 0xea, 0x2f, 0xf6, 0x7e, 0xaf, 0x51, 0x38, 0xe5, 0x4f, 0xc7, 0xa0, 0x0a, 0x57, 0x35, 0xc4, + 0xb1, 0x54, 0xc5, 0x23, 0x1b, 0x04, 0x9a, 0x57, 0xb7, 0x2a, 0x69, 0x42, 0x26, 0x37, 0xc2, 0xa7, 0x26, 0xa5, 0x3c, + 0x4d, 0x9b, 0xb4, 0x52, 0xa4, 0x0e, 0x3e, 0xa8, 0x53, 0x8d, 0xe7, 0x66, 0x75, 0x0d, 0x60, 0xc6, 0xf9, 0x15, 0xbf, + 0x54, 0x5c, 0x46, 0x6d, 0x65, 0x26, 0xed, 0x4f, 0x8e, 0xc6, 0x46, 0x5d, 0x4e, 0x1b, 0x65, 0x84, 0x95, 0xd2, 0x9c, + 0x14, 0xcb, 0xf1, 0xfc, 0x03, 0x06, 0x6b, 0x9e, 0xc0, 0x0e, 0x26, 0x2a, 0xe5, 0x7d, 0x04, 0xc4, 0xd7, 0x49, 0x7a, + 0x97, 0x40, 0x8a, 0xf4, 0x2f, 0x5d, 0x72, 0x97, 0xb1, 0x81, 0x18, 0xb3, 0x62, 0x66, 0xf4, 0x3f, 0xb8, 0x4b, 0xfa, + 0x93, 0x10, 0x00, 0x37, 0xd1, 0x14, 0x3a, 0x75, 0x9e, 0x5c, 0xe4, 0xc1, 0xf2, 0xc2, 0x43, 0x2b, 0x46, 0x3c, 0xf8, + 0xeb, 0x75, 0x88, 0x20, 0xe6, 0x98, 0xe2, 0xe9, 0x17, 0x46, 0x7f, 0x09, 0x2e, 0x31, 0x82, 0xd0, 0xdd, 0x3b, 0x87, + 0x21, 0xdc, 0xec, 0x41, 0x06, 0xf5, 0x87, 0x3a, 0x24, 0x6a, 0xf8, 0x63, 0xe5, 0x41, 0xff, 0xd7, 0x99, 0xb0, 0xd4, + 0x7e, 0x7a, 0x3a, 0x80, 0x0a, 0xde, 0x57, 0xbc, 0x8d, 0x88, 0xef, 0x13, 0x3f, 0x8b, 0x07, 0x9b, 0x67, 0x1b, 0xb0, + 0xd6, 0x3d, 0xc9, 0x8d, 0x75, 0x95, 0xb0, 0x81, 0x80, 0xaf, 0x51, 0xd4, 0x9e, 0xd7, 0x6e, 0xf7, 0xe0, 0xaf, 0xfe, + 0x45, 0xc8, 0x80, 0x89, 0xd3, 0xf7, 0x99, 0x93, 0x35, 0xba, 0xc8, 0x64, 0xfa, 0xd0, 0x49, 0xdf, 0xe8, 0x74, 0xdf, + 0x09, 0xff, 0xa8, 0x98, 0xc5, 0x87, 0x5b, 0xfa, 0x4a, 0x93, 0xe2, 0x0e, 0x58, 0xd9, 0x3c, 0x2a, 0x08, 0x75, 0x2e, + 0xa2, 0xaf, 0x4c, 0xf9, 0x96, 0x50, 0xb3, 0x6f, 0x2c, 0x29, 0xa5, 0x7b, 0x0d, 0xbd, 0x4e, 0x6b, 0xfd, 0x36, 0x4a, + 0x30, 0x26, 0x3a, 0x9e, 0xbc, 0x8c, 0xc7, 0xca, 0xfb, 0x78, 0xdc, 0x48, 0x85, 0x3c, 0x00, 0x11, 0xa8, 0x18, 0x7f, + 0xba, 0xf2, 0xe4, 0xa4, 0x17, 0xc6, 0xab, 0x50, 0x0a, 0x0a, 0x03, 0xba, 0x02, 0x29, 0xe0, 0x51, 0x7b, 0xa2, 0xb3, + 0xb0, 0x4b, 0xb8, 0x47, 0x37, 0x01, 0x63, 0x7d, 0xfe, 0x11, 0xd0, 0xdc, 0x85, 0x3b, 0xbc, 0x18, 0xa0, 0x36, 0xf5, + 0xea, 0xee, 0xe3, 0x5a, 0x9d, 0xc3, 0x21, 0x38, 0x58, 0x0d, 0x22, 0x38, 0x9d, 0x4f, 0x1d, 0xcd, 0xb2, 0x00, 0x95, + 0x93, 0xe5, 0x46, 0xde, 0x3c, 0x5a, 0xf4, 0xea, 0xbe, 0xb7, 0x4c, 0xcb, 0xaa, 0x0e, 0x32, 0x96, 0x85, 0x15, 0xe0, + 0xea, 0xd0, 0xfa, 0x41, 0xb8, 0x2c, 0x9c, 0x3f, 0x10, 0x82, 0xd8, 0xbd, 0xda, 0x96, 0x3c, 0x57, 0x73, 0xf8, 0xd9, + 0x73, 0xb6, 0xe6, 0x12, 0x75, 0xd2, 0x99, 0x08, 0x40, 0xec, 0xa9, 0x59, 0x45, 0xd7, 0x40, 0x52, 0xa7, 0x59, 0x45, + 0xd7, 0xd4, 0x6c, 0x63, 0x1c, 0xc8, 0x47, 0xab, 0x14, 0xb0, 0xef, 0xa6, 0xe3, 0x60, 0xf5, 0x2c, 0x96, 0xd7, 0xa1, + 0xbb, 0x67, 0x1b, 0xe5, 0x33, 0xa8, 0x5b, 0x6d, 0x8c, 0x89, 0xed, 0xe6, 0xcb, 0xb9, 0x7e, 0x3b, 0x58, 0xfa, 0x76, + 0xd0, 0x9c, 0x53, 0xf6, 0x9d, 0x2e, 0x7b, 0x65, 0x97, 0x4d, 0x3d, 0x77, 0x54, 0xb4, 0x1a, 0x03, 0x7a, 0x03, 0x0b, + 0xd6, 0xe7, 0x22, 0xcd, 0x56, 0xa5, 0x2a, 0x01, 0x2f, 0x8c, 0x15, 0xbb, 0xf3, 0x1b, 0x99, 0x21, 0x09, 0xf3, 0x38, + 0x13, 0x6f, 0xe9, 0x5e, 0x0b, 0x93, 0xe3, 0x58, 0x24, 0x53, 0x42, 0xa7, 0x74, 0x67, 0x1b, 0x3a, 0x57, 0x61, 0x14, + 0xd1, 0x5a, 0x49, 0xa5, 0x91, 0xc0, 0xd4, 0x0c, 0x50, 0x32, 0x57, 0xe0, 0x94, 0x2e, 0xf7, 0xbf, 0x23, 0x31, 0xce, + 0x7c, 0x51, 0x32, 0x03, 0xba, 0xe5, 0xd7, 0xc5, 0xba, 0x95, 0x22, 0x23, 0xcc, 0x9b, 0xe3, 0xf6, 0xba, 0x3e, 0x04, + 0x72, 0xb5, 0xec, 0x51, 0x34, 0x0e, 0x0a, 0x1d, 0x2e, 0x55, 0x02, 0xec, 0x8b, 0xc4, 0xcf, 0x08, 0x5b, 0xda, 0x03, + 0xb9, 0x3d, 0x3a, 0x13, 0xe6, 0x9c, 0x93, 0xb2, 0xec, 0x5c, 0x9a, 0xc1, 0xe5, 0xc4, 0x95, 0xe0, 0x22, 0xbd, 0x6d, + 0x4f, 0x93, 0x96, 0xb6, 0x8f, 0x0d, 0xe7, 0x68, 0x68, 0x1b, 0x74, 0xc7, 0xfe, 0xd0, 0x5c, 0x2c, 0x62, 0xeb, 0x62, + 0x31, 0xec, 0xcc, 0x7e, 0xb4, 0x58, 0x80, 0x1c, 0x00, 0x8e, 0xba, 0x0d, 0x1f, 0xb3, 0x25, 0x70, 0x5a, 0x4d, 0xb3, + 0xa9, 0xb7, 0xe1, 0xd5, 0x33, 0xd5, 0xd3, 0x4b, 0x9e, 0x3f, 0x13, 0x66, 0x2c, 0x36, 0x3c, 0x7f, 0x66, 0x1d, 0x39, + 0xd5, 0x33, 0xa1, 0x44, 0xeb, 0x02, 0x9a, 0x81, 0xd7, 0x14, 0x30, 0x62, 0xc9, 0x64, 0x4a, 0x15, 0x79, 0xdc, 0x9b, + 0x6e, 0xd4, 0xe0, 0x05, 0x85, 0x43, 0x20, 0xa5, 0xd3, 0x2f, 0x9e, 0x33, 0xfd, 0xde, 0xc5, 0xf3, 0x0e, 0x59, 0xdb, + 0x30, 0x5d, 0x6e, 0x86, 0xc9, 0xa0, 0xf4, 0x9f, 0x99, 0x89, 0x71, 0x61, 0x4d, 0x12, 0x40, 0xfc, 0x1b, 0xfb, 0x1d, + 0x52, 0xb8, 0x79, 0x7f, 0x39, 0x8c, 0x1f, 0x79, 0x3f, 0x46, 0xf6, 0x24, 0xcd, 0x10, 0x6b, 0x26, 0x15, 0x72, 0xf7, + 0xd5, 0xfa, 0xc7, 0xc4, 0x6e, 0xb2, 0x07, 0x16, 0x80, 0xd8, 0x9a, 0xb6, 0xba, 0xe5, 0xfd, 0xbe, 0x67, 0x8a, 0x00, + 0x3f, 0x28, 0xff, 0xe8, 0xce, 0x90, 0x0c, 0xca, 0xae, 0x1b, 0x42, 0x3c, 0x28, 0x9b, 0xa6, 0xbd, 0xde, 0xf6, 0xce, + 0x3c, 0x56, 0xd7, 0x69, 0x67, 0x71, 0xb5, 0xc8, 0x20, 0xad, 0x3e, 0x64, 0xc7, 0x99, 0x7d, 0x76, 0xb4, 0x54, 0xba, + 0xdf, 0x87, 0x88, 0xb8, 0xa3, 0xac, 0xed, 0xb7, 0x5b, 0x70, 0x0d, 0x47, 0x83, 0xd0, 0x95, 0xbd, 0x5d, 0x46, 0x1b, + 0x17, 0xe2, 0xb8, 0x67, 0x3a, 0x5f, 0xf0, 0xe5, 0x51, 0xda, 0x79, 0x70, 0xaa, 0x27, 0xfa, 0xdc, 0x74, 0x57, 0x99, + 0x5c, 0xeb, 0xb0, 0x1a, 0x83, 0xda, 0x2c, 0x6c, 0xe1, 0x2e, 0x6c, 0xa3, 0x83, 0xd6, 0xbe, 0x2c, 0xf8, 0xa7, 0x0c, + 0xc0, 0x97, 0x9e, 0x2d, 0xdb, 0x5e, 0x93, 0x56, 0xaf, 0x65, 0x14, 0x62, 0x4b, 0xdb, 0xab, 0x4f, 0x47, 0xf9, 0xb8, + 0x39, 0xa1, 0xb8, 0x90, 0xa3, 0xfc, 0xe8, 0x35, 0x44, 0x5d, 0xeb, 0x3a, 0x2e, 0x16, 0x1d, 0x6e, 0x5c, 0x75, 0xdb, + 0x8d, 0xeb, 0x07, 0xc4, 0x5b, 0xa3, 0x4d, 0x0a, 0xb5, 0x32, 0x76, 0x04, 0x2f, 0xcb, 0x87, 0x43, 0x26, 0x86, 0x43, + 0x09, 0x99, 0xfa, 0xd8, 0xbd, 0xa1, 0x69, 0x9f, 0x9f, 0xb6, 0x7e, 0xc4, 0x52, 0xe3, 0x28, 0x36, 0xbc, 0xd3, 0x77, + 0x1e, 0x5b, 0xe3, 0x4a, 0xbe, 0x0c, 0x66, 0xbb, 0x82, 0x6a, 0x6b, 0xbc, 0x61, 0x2f, 0xe7, 0xdf, 0x57, 0x52, 0xc9, + 0xdf, 0xfe, 0x0c, 0xd7, 0xf0, 0xd6, 0x96, 0x0e, 0x9a, 0x6a, 0x96, 0xb3, 0x5c, 0xdf, 0x0b, 0x8e, 0x3f, 0xee, 0x5e, + 0x11, 0x0c, 0x7e, 0x4f, 0x47, 0x41, 0x2e, 0x96, 0x6a, 0x0d, 0x28, 0x48, 0x47, 0x76, 0x4c, 0x65, 0x81, 0x61, 0x00, + 0x6f, 0xc8, 0x00, 0x79, 0x4c, 0xe1, 0x6e, 0xa8, 0xf0, 0xc2, 0x5f, 0x2a, 0xb2, 0x4b, 0x60, 0x5b, 0x33, 0x3e, 0x66, + 0xb8, 0x83, 0x90, 0x7f, 0x04, 0xbb, 0x63, 0x2b, 0x76, 0xcb, 0x16, 0x0c, 0xc9, 0xc6, 0x71, 0x18, 0x63, 0x3e, 0x9e, + 0xc4, 0x57, 0x62, 0x12, 0x0f, 0x78, 0x84, 0x8e, 0x11, 0x6b, 0x5e, 0xcf, 0x62, 0x39, 0x80, 0xec, 0x8e, 0x2b, 0x1d, + 0x10, 0x42, 0x63, 0x43, 0x4b, 0x5e, 0x17, 0x06, 0x17, 0x3b, 0xf6, 0x19, 0x89, 0x64, 0x1c, 0x82, 0x45, 0xab, 0x1a, + 0x58, 0x98, 0xd8, 0x2d, 0x2f, 0x66, 0xab, 0x39, 0xfe, 0x73, 0x38, 0x20, 0x00, 0x76, 0xb0, 0x6f, 0xd8, 0x5d, 0x84, + 0x48, 0x6f, 0x0b, 0x7e, 0x67, 0x79, 0xba, 0xb0, 0x7b, 0xfe, 0x96, 0x8f, 0xd9, 0xf9, 0x0f, 0x1e, 0x44, 0xce, 0x9e, + 0x7f, 0x04, 0x34, 0xc4, 0x7b, 0x7e, 0x9b, 0x7a, 0x15, 0xbb, 0x25, 0x0a, 0xc2, 0x5b, 0x70, 0x06, 0xba, 0x87, 0x08, + 0xd8, 0xb7, 0x7c, 0x81, 0xb1, 0x62, 0x67, 0xe9, 0xd2, 0xc3, 0x8c, 0x50, 0x7b, 0x3a, 0x5f, 0xd6, 0x6a, 0x12, 0x6e, + 0xae, 0x96, 0x93, 0xc1, 0x60, 0xe3, 0xef, 0xf8, 0x1a, 0xf8, 0x60, 0xce, 0x7f, 0xf0, 0x76, 0x54, 0x2e, 0xfc, 0xe7, + 0x75, 0x96, 0xbc, 0xf3, 0xd9, 0xdb, 0x01, 0x5f, 0x00, 0xde, 0x12, 0x3a, 0x70, 0xdd, 0xfb, 0x4c, 0xe2, 0xb5, 0xbd, + 0xd5, 0xd7, 0x08, 0x24, 0xf2, 0x05, 0x60, 0xc4, 0xc4, 0xfc, 0x7e, 0x0b, 0x11, 0x18, 0x09, 0xf8, 0xb6, 0x6a, 0x8f, + 0xf8, 0x2d, 0x37, 0x80, 0x5f, 0x99, 0xcf, 0x1e, 0x78, 0xa8, 0x7f, 0x26, 0x3e, 0xbb, 0xe1, 0xef, 0xf9, 0xb5, 0x27, + 0x25, 0xe9, 0x72, 0xf6, 0x7e, 0x0e, 0xd7, 0x43, 0x29, 0x4f, 0x87, 0xf4, 0xb3, 0x31, 0x18, 0x40, 0x28, 0x64, 0xde, + 0x78, 0xc0, 0x9a, 0x14, 0xe2, 0x5f, 0xc0, 0xb7, 0xa3, 0x84, 0xcd, 0x1b, 0x6f, 0xeb, 0x6b, 0x79, 0xf3, 0xc6, 0x7b, + 0xf0, 0x29, 0x0a, 0xb0, 0x0a, 0x4a, 0x59, 0x60, 0x15, 0x84, 0x8d, 0x36, 0xc2, 0x18, 0xb8, 0x7a, 0xd7, 0x18, 0xea, + 0x7a, 0x8e, 0xd8, 0xb6, 0xd2, 0x77, 0xe1, 0x3b, 0xc8, 0x80, 0x0f, 0x5e, 0x17, 0x25, 0xd1, 0xe7, 0xd4, 0x14, 0x49, + 0xeb, 0x9e, 0xfb, 0xad, 0x75, 0x47, 0x6b, 0x4a, 0x7d, 0xe4, 0x6a, 0x7c, 0x38, 0xd4, 0xd7, 0x42, 0x8b, 0x04, 0x53, + 0xd0, 0xb8, 0x06, 0x6d, 0x01, 0x82, 0x3e, 0x0f, 0x90, 0xb5, 0xa4, 0x58, 0xf0, 0xed, 0xaf, 0x10, 0x83, 0x57, 0xa6, + 0x77, 0x2e, 0x57, 0x19, 0x09, 0xdb, 0x0b, 0xbf, 0x1c, 0xd6, 0xfe, 0xc4, 0xa9, 0x85, 0xa5, 0xd5, 0x1c, 0xd4, 0xcf, + 0x6c, 0x39, 0x4e, 0x55, 0xed, 0xdf, 0x92, 0xa4, 0xda, 0x55, 0x5a, 0x4e, 0xef, 0xed, 0x9b, 0x2e, 0x13, 0x6c, 0xec, + 0x07, 0x54, 0x1d, 0x59, 0x0d, 0xbb, 0x2f, 0xd4, 0x17, 0x3d, 0x25, 0x13, 0x9a, 0x8f, 0x2a, 0x9a, 0x67, 0xf7, 0x9b, + 0x1d, 0xf5, 0x9f, 0x5e, 0x0e, 0x45, 0x80, 0x64, 0x95, 0x16, 0x4b, 0x91, 0xb3, 0xb1, 0x1f, 0x0f, 0x93, 0x4c, 0x85, + 0x17, 0xa4, 0xa3, 0xbb, 0xdf, 0xb8, 0xbf, 0xe5, 0x06, 0xb2, 0x42, 0xab, 0x36, 0x18, 0x2b, 0x45, 0xcb, 0x60, 0x7d, + 0x35, 0xee, 0xf7, 0xc5, 0xd5, 0x78, 0x2a, 0x82, 0x1a, 0x88, 0x8b, 0xc4, 0xf5, 0x78, 0x5a, 0x13, 0x4b, 0x6a, 0x57, + 0x60, 0x8c, 0x1e, 0x57, 0x45, 0xed, 0x53, 0x5f, 0x43, 0x28, 0x52, 0xad, 0x99, 0x63, 0x8d, 0x1b, 0x23, 0xe2, 0x0e, + 0x2b, 0xd7, 0x4e, 0xed, 0x75, 0x00, 0x96, 0x57, 0xe3, 0x82, 0xb0, 0x49, 0x8e, 0x9d, 0x0b, 0x58, 0x8d, 0x86, 0x54, + 0xbb, 0xe1, 0xd6, 0xcb, 0xce, 0x6f, 0x1e, 0x27, 0xb6, 0x36, 0xc2, 0x2d, 0x05, 0x94, 0x51, 0x7e, 0x63, 0x39, 0x61, + 0x77, 0xaa, 0x77, 0xa4, 0x6a, 0x47, 0x9c, 0xb8, 0x80, 0xe5, 0x86, 0xa7, 0x56, 0xdf, 0xc4, 0xe0, 0x44, 0xa8, 0x5a, + 0xe9, 0x78, 0xed, 0x47, 0xdc, 0xaf, 0xee, 0xeb, 0x5e, 0x09, 0x7e, 0x12, 0xf2, 0xfa, 0x2d, 0xef, 0x00, 0xb0, 0xe2, + 0x43, 0x5e, 0x4c, 0x0b, 0x47, 0xeb, 0x32, 0x28, 0x03, 0x44, 0x68, 0x06, 0x40, 0x27, 0x57, 0x07, 0x51, 0x1a, 0xb8, + 0xe2, 0x0e, 0x11, 0x7e, 0x1a, 0x3d, 0xcb, 0xaf, 0xc3, 0x67, 0xd5, 0x34, 0xbc, 0xc8, 0x83, 0xe8, 0xa2, 0x0a, 0xa2, + 0x67, 0xd5, 0x55, 0xf8, 0x2c, 0x9f, 0x46, 0x17, 0x79, 0x10, 0x5e, 0x54, 0x8d, 0x7d, 0xd7, 0xee, 0xee, 0x09, 0x79, + 0xdb, 0xd5, 0x1f, 0x39, 0x57, 0xf6, 0x94, 0xe9, 0xf9, 0x79, 0xad, 0x57, 0x6a, 0xb7, 0xb9, 0x5e, 0xa3, 0x66, 0xea, + 0xa3, 0xec, 0x6f, 0xb6, 0xb1, 0xf0, 0x68, 0x0e, 0xa1, 0xcf, 0x48, 0x8b, 0xb9, 0xc7, 0xb9, 0xde, 0xec, 0x49, 0x61, + 0x60, 0xc4, 0xa4, 0x92, 0x91, 0xd3, 0x0b, 0x5c, 0x84, 0x2a, 0xc4, 0xb0, 0x96, 0xae, 0xf6, 0x59, 0x97, 0xde, 0x40, + 0x5d, 0x53, 0xec, 0x6b, 0xc8, 0xc0, 0x8b, 0xa6, 0x97, 0xc1, 0x18, 0x90, 0x23, 0xf0, 0x8e, 0xcf, 0x96, 0x70, 0x60, + 0xae, 0x01, 0xfa, 0xe6, 0x51, 0x5f, 0x97, 0x3b, 0xbe, 0x56, 0x7d, 0x33, 0x5d, 0x8f, 0x94, 0xf2, 0x63, 0xc5, 0xef, + 0x2e, 0x9e, 0xb3, 0x5b, 0xae, 0x51, 0x51, 0x7e, 0xd1, 0x8b, 0xf5, 0x1e, 0xb8, 0xea, 0x7e, 0x81, 0xdb, 0x2c, 0x1e, + 0xbb, 0xf2, 0x80, 0x65, 0x5b, 0xf6, 0xc0, 0x6e, 0xd8, 0x7b, 0xf6, 0x84, 0xbd, 0x61, 0xef, 0xd8, 0x4f, 0xa8, 0xda, + 0x50, 0x42, 0x9e, 0xbf, 0xe0, 0xb7, 0xd2, 0xf4, 0x28, 0x51, 0xc9, 0x1e, 0x6c, 0x33, 0xcd, 0x70, 0xc3, 0xde, 0xf3, + 0xc5, 0x70, 0xc5, 0xde, 0x40, 0x36, 0x94, 0x89, 0x07, 0x2b, 0xf6, 0x13, 0x57, 0x20, 0x66, 0xfa, 0x2c, 0x2c, 0x2d, + 0x51, 0xd1, 0x94, 0x89, 0x32, 0xf4, 0x1b, 0x8e, 0x2f, 0xb2, 0x9f, 0xb0, 0x08, 0xf9, 0x99, 0xe1, 0x8a, 0x3d, 0xf0, + 0xc5, 0x60, 0xc5, 0xde, 0x6b, 0x03, 0xd1, 0x60, 0xe3, 0x96, 0x46, 0x48, 0x56, 0xba, 0x2c, 0x29, 0x4d, 0x6f, 0xed, + 0x6b, 0xe0, 0x86, 0xdd, 0x60, 0xed, 0x9e, 0x60, 0xd1, 0x28, 0xf0, 0x0f, 0x56, 0xec, 0x1d, 0x97, 0x00, 0x6a, 0x6e, + 0x79, 0xd2, 0x2b, 0x54, 0x17, 0x48, 0xf7, 0x83, 0x27, 0x9c, 0x5e, 0x64, 0xef, 0xb0, 0x0c, 0xfa, 0xca, 0x70, 0xc5, + 0xb6, 0x58, 0xbb, 0x1b, 0x63, 0xd9, 0xb2, 0xaa, 0x27, 0x11, 0x81, 0x51, 0x50, 0x29, 0x2d, 0xff, 0x46, 0x2c, 0x9b, + 0xba, 0x69, 0x50, 0x1b, 0xfa, 0xf3, 0xc1, 0xe8, 0x2f, 0xbe, 0x7e, 0xf7, 0x83, 0x57, 0xea, 0x6b, 0xef, 0x2f, 0x8e, + 0x6b, 0x65, 0x89, 0xae, 0x95, 0xbf, 0xf2, 0x72, 0xf6, 0xcb, 0x7c, 0xa2, 0x6b, 0x49, 0x3b, 0x0c, 0xf9, 0x9a, 0xce, + 0x7e, 0xe9, 0x70, 0xb6, 0xfc, 0xd5, 0xf7, 0x1b, 0xd3, 0xc5, 0xea, 0xb3, 0xba, 0x77, 0x1f, 0x06, 0x9b, 0xc6, 0xa9, + 0xf7, 0xee, 0x74, 0xbd, 0xb1, 0x99, 0xb5, 0xf6, 0xcc, 0xfc, 0x1f, 0xae, 0xf4, 0x16, 0x87, 0xee, 0x86, 0x6f, 0x87, + 0x1b, 0x7b, 0x14, 0xe4, 0xf7, 0xa5, 0xd2, 0x38, 0xab, 0xf9, 0x0b, 0xaf, 0x53, 0x8a, 0x05, 0x44, 0xa3, 0x4f, 0x46, + 0x12, 0xba, 0x64, 0x26, 0x9e, 0x21, 0xbe, 0xc8, 0x00, 0x99, 0x0b, 0x44, 0xb3, 0x7b, 0x3e, 0x9e, 0xdc, 0x5f, 0xc5, + 0x93, 0xfb, 0x01, 0xff, 0x64, 0x5a, 0xd0, 0x5e, 0x6c, 0xf7, 0x3e, 0xfb, 0x95, 0x17, 0xf6, 0x72, 0xfc, 0xc5, 0x67, + 0x5f, 0x84, 0xbb, 0x42, 0x7f, 0xf1, 0xd9, 0x3b, 0xc1, 0x7f, 0x1d, 0x69, 0xa2, 0x0c, 0xf6, 0xae, 0xe6, 0xbf, 0x8e, + 0x90, 0xf1, 0x83, 0x7d, 0x16, 0xfc, 0x0b, 0xf8, 0x7e, 0x57, 0x09, 0x5a, 0xc5, 0x3f, 0xd7, 0xea, 0xe7, 0x7b, 0x19, + 0x97, 0x03, 0x6f, 0x42, 0x2b, 0xe8, 0xcd, 0xdb, 0x5a, 0xfe, 0x24, 0x1e, 0x8e, 0x54, 0x3d, 0x35, 0xfc, 0xb3, 0x58, + 0xcc, 0xa2, 0x3e, 0x4a, 0xa7, 0xf2, 0x26, 0x6f, 0x79, 0x26, 0xad, 0xcb, 0xf7, 0x10, 0x0a, 0xfc, 0xd6, 0x86, 0x28, + 0xd8, 0x71, 0xdc, 0x08, 0xde, 0xb2, 0x77, 0xc2, 0x67, 0xd9, 0x74, 0xcb, 0x6f, 0xf8, 0x13, 0xfe, 0x8e, 0xef, 0x82, + 0x07, 0xfe, 0x9e, 0xbf, 0xe1, 0x3f, 0xf1, 0x1d, 0x5b, 0x4a, 0xb4, 0xd3, 0x7a, 0x7b, 0x19, 0x6c, 0x59, 0xbd, 0xbb, + 0x0c, 0x1e, 0x58, 0xbd, 0x7d, 0x1e, 0xdc, 0xb0, 0x7a, 0xf7, 0x3c, 0x78, 0xcf, 0xb6, 0x97, 0xc1, 0x13, 0xb6, 0xbb, + 0x0c, 0xde, 0xb0, 0xed, 0xf3, 0xe0, 0x1d, 0xdb, 0x3d, 0x0f, 0x7e, 0x92, 0x18, 0x0f, 0xef, 0x84, 0xe4, 0x38, 0x79, + 0x57, 0x33, 0xc3, 0xa7, 0x1b, 0x7c, 0x16, 0xd6, 0x2f, 0xaa, 0x63, 0xf0, 0xb9, 0x66, 0xba, 0xc5, 0x81, 0x10, 0x4c, + 0xb7, 0x37, 0xb8, 0xa5, 0x27, 0xa6, 0x55, 0x41, 0x2a, 0x58, 0x57, 0x3b, 0x83, 0x45, 0xdd, 0xb4, 0xce, 0x64, 0xc7, + 0x2f, 0x31, 0xee, 0xf0, 0x4b, 0x5c, 0xb0, 0x65, 0xd3, 0xe9, 0xa4, 0x73, 0xfa, 0x24, 0xd0, 0x9b, 0xbf, 0xde, 0xf5, + 0x2b, 0xe9, 0x3b, 0x53, 0x34, 0x3c, 0x57, 0x5a, 0xe3, 0xd6, 0x4e, 0x1f, 0x5a, 0x3b, 0x3d, 0x93, 0x2a, 0xb4, 0x88, + 0x45, 0x65, 0x51, 0x55, 0xc8, 0x24, 0x1e, 0x64, 0x5a, 0x9f, 0x96, 0x30, 0x52, 0x64, 0x02, 0x1a, 0x7d, 0x41, 0xc7, + 0x40, 0x4e, 0x16, 0x05, 0xb6, 0xe4, 0x9b, 0x41, 0xc2, 0xd6, 0x3c, 0x9e, 0x0e, 0x93, 0x60, 0xc9, 0xee, 0xf8, 0xb0, + 0x5b, 0x20, 0x58, 0xa9, 0x00, 0x26, 0x7d, 0x71, 0x6a, 0xef, 0xeb, 0xbc, 0xb7, 0x4a, 0xe3, 0x38, 0x13, 0xa8, 0x6c, + 0xab, 0xf4, 0x06, 0xbf, 0x75, 0xf6, 0xf3, 0xb5, 0xda, 0xdf, 0x41, 0x52, 0xf8, 0x15, 0x18, 0x76, 0x88, 0xf0, 0x0e, + 0x2a, 0x8c, 0x3c, 0x4b, 0x66, 0xd1, 0x57, 0xf6, 0x96, 0xbe, 0x35, 0xdb, 0xf4, 0x7f, 0x5a, 0x04, 0xed, 0xe3, 0xb2, + 0xf3, 0x3f, 0x99, 0x57, 0x7f, 0xeb, 0x78, 0x75, 0xe3, 0x4f, 0x1e, 0xf8, 0x27, 0x0c, 0x4b, 0xc0, 0x44, 0xb6, 0xe3, + 0x9f, 0x46, 0xdb, 0xc6, 0x29, 0x4f, 0xee, 0xe3, 0xff, 0x57, 0x0a, 0xb4, 0x77, 0xf2, 0xca, 0xde, 0x11, 0xb7, 0xbc, + 0x63, 0x1f, 0x5f, 0x5a, 0x1b, 0xa2, 0x81, 0x26, 0xf9, 0xc4, 0xdd, 0x68, 0x68, 0xd8, 0x10, 0x7f, 0xe1, 0xd5, 0xec, + 0xd3, 0x7c, 0xb2, 0xe5, 0xc7, 0xdb, 0xe1, 0xa7, 0x8e, 0xed, 0xf0, 0x17, 0x7f, 0xb0, 0x6c, 0xbe, 0xd6, 0xab, 0x9d, + 0xdb, 0xb8, 0x53, 0xe9, 0x1d, 0x3f, 0xde, 0xc4, 0x87, 0xff, 0x71, 0xa5, 0x77, 0xdf, 0x5c, 0x69, 0xbb, 0xca, 0xdd, + 0x9d, 0x6f, 0x3a, 0xbe, 0x91, 0xb5, 0xc6, 0x38, 0x33, 0xa3, 0x59, 0xfc, 0x89, 0x66, 0x69, 0x10, 0x59, 0x0a, 0xc5, + 0x9f, 0xcc, 0xb4, 0x53, 0x77, 0xaa, 0xac, 0xee, 0x96, 0x6f, 0x71, 0x8f, 0xbf, 0xe5, 0x63, 0xb6, 0x30, 0x9e, 0x9a, + 0xb7, 0x57, 0x8b, 0xc9, 0x60, 0x70, 0xeb, 0xef, 0xef, 0x79, 0x38, 0xbb, 0x9d, 0xb3, 0xb7, 0xfc, 0x9e, 0x16, 0xd3, + 0x44, 0x35, 0xbd, 0x78, 0x4c, 0xf0, 0xba, 0xf5, 0xfd, 0x89, 0xc5, 0xff, 0x6a, 0x5f, 0x34, 0x6f, 0xfd, 0x81, 0xb4, + 0x46, 0xcb, 0x5d, 0xfd, 0xfd, 0xe3, 0x8a, 0x89, 0x5b, 0x10, 0x2f, 0xde, 0xdb, 0x9a, 0x86, 0x37, 0xfc, 0xa3, 0xf7, + 0xd6, 0x9f, 0xbe, 0xd5, 0x31, 0x37, 0x13, 0x75, 0x24, 0xbd, 0xb9, 0x78, 0xce, 0x7e, 0xe5, 0x9f, 0xe4, 0x71, 0xf2, + 0x45, 0xc8, 0x49, 0x7b, 0x83, 0xdc, 0x4d, 0x74, 0x4a, 0xbc, 0x73, 0x13, 0x09, 0x0b, 0x02, 0x61, 0x38, 0x6a, 0xfe, + 0x30, 0x29, 0xa7, 0xde, 0x0e, 0xb8, 0x5d, 0xb9, 0xad, 0x7f, 0xbe, 0xe5, 0x9c, 0x2f, 0x86, 0x97, 0xd3, 0x77, 0xdd, + 0x2e, 0x3d, 0x2a, 0x9a, 0x4d, 0x05, 0xba, 0xdd, 0x62, 0xec, 0xd5, 0xc9, 0xcc, 0x32, 0x97, 0x7c, 0xe9, 0x5d, 0x6d, + 0x66, 0x1e, 0xd3, 0xfb, 0xcd, 0x34, 0x43, 0x22, 0x5f, 0x20, 0x64, 0x3a, 0x1c, 0xee, 0xce, 0xb1, 0x3c, 0x3e, 0x7c, + 0xf3, 0xec, 0xc9, 0xe0, 0x09, 0x46, 0x6e, 0x59, 0xd1, 0x20, 0xef, 0xf8, 0x30, 0xab, 0x5b, 0xb7, 0x8d, 0x8b, 0xe7, + 0xc3, 0x5f, 0x20, 0x6f, 0xd0, 0xf5, 0xd0, 0x14, 0xd1, 0x2a, 0xbf, 0xa3, 0xe8, 0x13, 0x25, 0x07, 0x1d, 0x4f, 0xa0, + 0x76, 0x48, 0x81, 0xfb, 0xee, 0x19, 0x07, 0xfd, 0x06, 0x96, 0xda, 0xef, 0x9f, 0x7f, 0x22, 0x1e, 0x69, 0x18, 0xef, + 0xef, 0xc3, 0xe8, 0x8f, 0xb8, 0x2c, 0xd6, 0x70, 0xba, 0x0e, 0xe0, 0x73, 0xcf, 0xf4, 0xed, 0xeb, 0xce, 0xf7, 0xfd, + 0xc0, 0xdb, 0xf2, 0x1b, 0xf6, 0x8e, 0x7b, 0x97, 0xc3, 0x37, 0xfe, 0xb3, 0x27, 0x20, 0x3a, 0xc1, 0xb8, 0x7c, 0xc6, + 0x48, 0xd8, 0x8e, 0x62, 0xd4, 0x2a, 0xfc, 0x5c, 0x43, 0x88, 0xd6, 0x27, 0x64, 0xec, 0x82, 0xf4, 0x0f, 0x0a, 0xd0, + 0x4f, 0x08, 0xac, 0x26, 0xa9, 0x51, 0x60, 0x12, 0xdf, 0xd6, 0x90, 0x40, 0x0a, 0x16, 0x08, 0xbd, 0x81, 0xe2, 0x53, + 0xc1, 0xdf, 0x0d, 0x3f, 0x93, 0xe4, 0xb7, 0xa8, 0xf9, 0x18, 0xfe, 0x86, 0xa1, 0x99, 0x54, 0x0f, 0x69, 0x1d, 0x25, + 0xde, 0x4f, 0xfe, 0x3e, 0x0a, 0x2b, 0xa1, 0x8e, 0x85, 0x20, 0x15, 0x43, 0x2e, 0xc4, 0xc5, 0xf3, 0xc9, 0x6d, 0x29, + 0xc2, 0x3f, 0x26, 0xf8, 0x4c, 0x2e, 0x34, 0xf9, 0x8c, 0x9e, 0x34, 0xf2, 0xfd, 0x07, 0xf9, 0xbe, 0xec, 0xd4, 0x60, + 0x51, 0x0f, 0xf9, 0x6d, 0xed, 0xbe, 0x2f, 0xa7, 0x04, 0x3d, 0xb2, 0x1f, 0xd0, 0x14, 0x0c, 0xd4, 0x04, 0xa4, 0x0c, + 0xc1, 0x2d, 0x5c, 0xf5, 0x3d, 0x55, 0x90, 0x2f, 0xbf, 0xf7, 0x59, 0xc8, 0x70, 0x95, 0x05, 0x21, 0xc9, 0xa5, 0x42, + 0x0a, 0x1b, 0xb7, 0xf5, 0xe0, 0xb3, 0xc6, 0x24, 0x91, 0x90, 0x53, 0x02, 0x92, 0xa4, 0xbd, 0x81, 0x24, 0x11, 0xd3, + 0x7f, 0xb8, 0x4e, 0x9a, 0x66, 0x25, 0xa5, 0x1b, 0xe2, 0x54, 0x7d, 0x8b, 0x34, 0x67, 0xc1, 0x7b, 0x06, 0x4b, 0x47, + 0x8a, 0x15, 0xef, 0x8c, 0xc1, 0x58, 0x07, 0x0b, 0xdd, 0xc9, 0xe2, 0x7e, 0x95, 0x84, 0x69, 0x24, 0xaa, 0x7c, 0x11, + 0xf2, 0xe7, 0xbf, 0x94, 0xf8, 0xa3, 0xb7, 0x34, 0x10, 0x81, 0xe0, 0x07, 0x68, 0x3d, 0x60, 0x8d, 0x07, 0x3f, 0xb1, + 0xba, 0x0c, 0xf3, 0x2a, 0xa3, 0xf2, 0x66, 0x3b, 0xb6, 0x9d, 0x33, 0x55, 0xb5, 0xe0, 0xb3, 0x30, 0xb4, 0x68, 0x67, + 0xab, 0xe6, 0xe4, 0x36, 0x6f, 0xf0, 0x9d, 0x49, 0x12, 0xa9, 0xa5, 0x24, 0xd2, 0x56, 0xd7, 0xa7, 0x4b, 0xaf, 0x5b, + 0x54, 0xd0, 0x18, 0x01, 0x7a, 0x49, 0xba, 0xab, 0x7c, 0x42, 0xf1, 0xca, 0x6a, 0x58, 0x0d, 0x2f, 0x1d, 0x8a, 0x30, + 0xd6, 0xde, 0x5c, 0xc9, 0xb3, 0x3b, 0xb0, 0x1e, 0xa1, 0xb5, 0xab, 0x52, 0x87, 0xb0, 0xfd, 0x44, 0xef, 0x39, 0x95, + 0xfa, 0x1b, 0x50, 0x05, 0x4e, 0x1d, 0x0d, 0xf5, 0x51, 0x3b, 0x85, 0x6c, 0xe7, 0xde, 0x92, 0xa0, 0x72, 0x25, 0x37, + 0x55, 0x5a, 0x94, 0x52, 0xa6, 0x7c, 0x2d, 0xb3, 0x95, 0xdd, 0x27, 0x03, 0x88, 0x67, 0x83, 0x02, 0xc9, 0x45, 0x6d, + 0x35, 0x07, 0xe9, 0xa3, 0x59, 0xe2, 0x58, 0x3b, 0x28, 0xbc, 0xac, 0x02, 0x33, 0x97, 0xb9, 0x5c, 0x0e, 0x0a, 0x96, + 0xeb, 0xad, 0x66, 0x9a, 0xa9, 0xbe, 0xc8, 0xed, 0x6d, 0xc6, 0xcb, 0xf4, 0xdf, 0x2c, 0x19, 0xf0, 0xe8, 0xe2, 0xb9, + 0x1f, 0x40, 0x9a, 0xe4, 0x75, 0x80, 0x24, 0xd8, 0x1c, 0xec, 0x62, 0x87, 0x61, 0xab, 0x58, 0xd9, 0x93, 0xa7, 0xcb, + 0x1d, 0x9a, 0x72, 0x09, 0x23, 0x39, 0x31, 0x97, 0x52, 0xdf, 0x97, 0x54, 0x37, 0x14, 0x9c, 0x6c, 0x9a, 0x80, 0x52, + 0x40, 0xbb, 0x05, 0xff, 0x85, 0x4f, 0x0d, 0x9d, 0x16, 0x60, 0xa9, 0xed, 0x06, 0xfc, 0x17, 0xfa, 0xc5, 0xf6, 0x11, + 0xf5, 0x03, 0xf3, 0x60, 0x6f, 0xd6, 0x56, 0xc6, 0x80, 0x88, 0xc4, 0x15, 0xe4, 0x91, 0xe0, 0x07, 0xc5, 0x9e, 0x2e, + 0x13, 0x07, 0xce, 0x14, 0x17, 0x4b, 0xa9, 0xcd, 0xcc, 0x6b, 0xbf, 0xa5, 0x26, 0xde, 0x44, 0x49, 0x54, 0xd8, 0x0e, + 0x69, 0xf4, 0x92, 0x32, 0xa6, 0x0a, 0x36, 0x44, 0xf7, 0x75, 0x13, 0x4c, 0x81, 0x37, 0x55, 0x15, 0x10, 0xa1, 0xf6, + 0x22, 0xcb, 0xf3, 0x9b, 0x2e, 0xb0, 0xba, 0xe0, 0x63, 0x63, 0x9a, 0x5d, 0xb0, 0x92, 0xab, 0x99, 0xf4, 0x99, 0xb7, + 0x03, 0x2d, 0xe4, 0x5d, 0x5e, 0x16, 0xad, 0xd0, 0xf5, 0x20, 0x5a, 0xf8, 0x7b, 0xcd, 0xf1, 0xe8, 0xd9, 0xb6, 0x9a, + 0xda, 0xec, 0x6b, 0x2d, 0x16, 0xc8, 0x40, 0x34, 0xf4, 0x85, 0x9c, 0x51, 0xb8, 0xab, 0x34, 0x57, 0xab, 0x7d, 0x55, + 0x06, 0x09, 0x4c, 0x04, 0x59, 0xcb, 0xc2, 0x7b, 0x74, 0xaf, 0x1e, 0x69, 0x5e, 0x49, 0xf0, 0xcc, 0xc5, 0x5f, 0x00, + 0x08, 0xe5, 0x49, 0x42, 0x0e, 0xc8, 0x01, 0xfc, 0x2d, 0x45, 0xa9, 0x34, 0xc0, 0x3f, 0xab, 0xcb, 0xb1, 0xad, 0xef, + 0xef, 0xb4, 0x8a, 0xc1, 0xf5, 0xe7, 0xeb, 0xae, 0x67, 0xed, 0x10, 0xe7, 0xca, 0x56, 0xaf, 0x2d, 0xd3, 0x3c, 0x46, + 0xea, 0x1a, 0x80, 0x3b, 0x91, 0x1e, 0x81, 0x48, 0x66, 0xa2, 0x41, 0xce, 0xae, 0xf9, 0x78, 0x2a, 0x1e, 0x93, 0xf6, + 0x2a, 0xdf, 0x37, 0x17, 0xfa, 0x60, 0x8c, 0x7d, 0x0b, 0x1a, 0xc4, 0x47, 0xab, 0xad, 0x15, 0x88, 0xf5, 0x56, 0xa9, + 0x0f, 0xdd, 0x18, 0x05, 0x1d, 0x3c, 0xe2, 0x46, 0x2e, 0x38, 0xb6, 0xbb, 0xb6, 0x9e, 0xd2, 0x57, 0x00, 0xe6, 0x3a, + 0x50, 0xc9, 0x30, 0x48, 0x9d, 0x27, 0x0a, 0x93, 0xfc, 0x3c, 0x21, 0x09, 0x11, 0xd5, 0xd9, 0x72, 0x94, 0x72, 0xd3, + 0x02, 0x2e, 0x33, 0x32, 0xc0, 0x6c, 0xd2, 0xac, 0x9f, 0x5c, 0xbe, 0x04, 0xa9, 0x34, 0x44, 0x70, 0xc3, 0xf6, 0x92, + 0xd1, 0xad, 0xa3, 0x6e, 0x50, 0x25, 0x99, 0xeb, 0x37, 0xb7, 0xb3, 0x48, 0x99, 0x37, 0x1f, 0x61, 0xac, 0xc9, 0x87, + 0xb0, 0x4e, 0xf0, 0xdb, 0x00, 0x95, 0xf4, 0xa9, 0xf0, 0xa2, 0x11, 0x40, 0xa8, 0xef, 0x54, 0x19, 0x9f, 0x0a, 0x2f, + 0x1b, 0x6d, 0x59, 0x46, 0x29, 0x54, 0x17, 0xcc, 0x6e, 0x4d, 0x17, 0xa2, 0x5b, 0x55, 0x03, 0x6d, 0xe0, 0xda, 0x75, + 0xa0, 0x80, 0x86, 0x6a, 0x57, 0x6e, 0x58, 0x00, 0x56, 0x33, 0x11, 0x18, 0x2e, 0xff, 0x3e, 0x7f, 0xa9, 0x62, 0x78, + 0xfa, 0xfd, 0xd0, 0xdb, 0x6f, 0x83, 0x68, 0xb4, 0xbd, 0x64, 0xbb, 0x20, 0x1a, 0xed, 0x2e, 0x1b, 0x46, 0xbf, 0x9f, + 0xd3, 0xef, 0xe7, 0x0d, 0xe8, 0x48, 0x84, 0x09, 0xb3, 0xd7, 0x6f, 0xd4, 0xf2, 0x95, 0x5a, 0xbf, 0x53, 0xcb, 0x97, + 0x6a, 0x78, 0x6b, 0x4f, 0x12, 0x41, 0x64, 0xa9, 0x6a, 0x1e, 0x24, 0x45, 0xaa, 0xa5, 0xcb, 0x31, 0x5a, 0x8c, 0xa8, + 0xa5, 0xac, 0x39, 0xd6, 0x89, 0xb4, 0x73, 0x50, 0x32, 0xc0, 0xd1, 0xe2, 0xaa, 0xc6, 0x74, 0xb3, 0xa2, 0x25, 0x10, + 0x23, 0xac, 0x6c, 0xcb, 0xc5, 0x4d, 0xea, 0xa3, 0x73, 0xf2, 0x6d, 0xab, 0x94, 0x6f, 0x5b, 0xc1, 0xf3, 0xaf, 0x28, + 0x94, 0x4b, 0xae, 0x5d, 0xcb, 0xa6, 0x85, 0x52, 0x28, 0xe3, 0x1a, 0x6c, 0xed, 0x9b, 0xc0, 0x90, 0xf9, 0x48, 0x51, + 0x63, 0x7b, 0xd1, 0x28, 0x87, 0x20, 0x5b, 0x07, 0xa3, 0x4e, 0x59, 0xb0, 0xf8, 0x76, 0x87, 0x0c, 0x64, 0xa0, 0xa3, + 0xaa, 0x8d, 0x57, 0x3b, 0x2b, 0xfd, 0x61, 0x79, 0xf1, 0x9c, 0x25, 0x56, 0x3a, 0xf9, 0x4d, 0x85, 0xfe, 0x20, 0x44, + 0xdf, 0x94, 0x0d, 0x07, 0x2f, 0xba, 0xd8, 0xca, 0x80, 0x78, 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, 0xcd, 0xa3, 0x50, 0xb3, 0x3c, 0x01, 0x2c, 0x78, 0x61, 0x66, 0xb8, + 0x30, 0x33, 0x1c, 0x87, 0xd4, 0x38, 0x3d, 0xe8, 0xbd, 0xce, 0x3d, 0xb7, 0xdc, 0x8d, 0x4e, 0xc3, 0xbc, 0x1d, 0x6d, + 0x30, 0xc7, 0x07, 0xe1, 0x04, 0xe2, 0x03, 0x4b, 0x04, 0xe8, 0xd1, 0xb0, 0x3a, 0x6a, 0xa8, 0x1c, 0xc5, 0x97, 0x05, + 0x20, 0x59, 0x12, 0x80, 0xe4, 0x5e, 0x8d, 0x73, 0x69, 0xf9, 0x75, 0x95, 0x84, 0x1c, 0x91, 0xf1, 0x52, 0xda, 0xdd, + 0x13, 0x5e, 0x8e, 0x8c, 0xd0, 0x3c, 0x59, 0xa4, 0x5e, 0xce, 0x32, 0x36, 0x46, 0xe0, 0xa2, 0xd0, 0x6f, 0xaa, 0x7e, + 0x3f, 0x2d, 0xbd, 0x9c, 0xda, 0xf9, 0x09, 0xfc, 0x2d, 0x4f, 0x9d, 0x45, 0x8e, 0x90, 0x57, 0x23, 0x93, 0xb0, 0xbc, + 0x54, 0xea, 0xe9, 0x4b, 0x98, 0x41, 0xdd, 0xbd, 0x51, 0x00, 0xae, 0x45, 0x2e, 0x9d, 0x6a, 0x4b, 0xb8, 0x32, 0xe5, + 0x06, 0xfb, 0x3c, 0xe4, 0x39, 0x09, 0xa1, 0x12, 0x79, 0xa4, 0xb0, 0xee, 0xdb, 0x17, 0xcf, 0x27, 0xae, 0x0f, 0x8b, + 0x8d, 0x46, 0x70, 0x38, 0x00, 0xcc, 0xc1, 0xd4, 0x8b, 0x06, 0xbc, 0x54, 0x73, 0xe6, 0xa3, 0x97, 0x13, 0x36, 0x06, + 0xa8, 0x29, 0x06, 0x4e, 0x59, 0xcf, 0xe4, 0x23, 0xe3, 0x5b, 0xe6, 0xfb, 0x01, 0xbe, 0x5b, 0x17, 0x12, 0xf2, 0x41, + 0xa1, 0x12, 0x64, 0x0a, 0x95, 0x20, 0x31, 0xa8, 0x04, 0xb1, 0x41, 0x25, 0xd8, 0x34, 0x7c, 0x2d, 0x95, 0xb7, 0x11, + 0x70, 0x44, 0xf8, 0xd0, 0xb3, 0xb0, 0xb1, 0x42, 0xf1, 0x6c, 0xcc, 0xc6, 0xac, 0x50, 0x3b, 0x4f, 0x2e, 0xa7, 0x62, + 0x67, 0x31, 0xd6, 0x4d, 0x64, 0x99, 0x78, 0x21, 0x41, 0xc7, 0x39, 0x17, 0x12, 0x75, 0xf5, 0x73, 0xef, 0x25, 0x19, + 0x4b, 0xe6, 0x0d, 0x8d, 0x1a, 0xcc, 0xcb, 0xae, 0x03, 0x98, 0x96, 0x7c, 0x5b, 0xd0, 0x60, 0x3a, 0x55, 0x1e, 0x91, + 0x26, 0x41, 0xed, 0x5c, 0x26, 0x45, 0x4e, 0x08, 0x93, 0xa0, 0x57, 0x82, 0xdf, 0x48, 0x68, 0xff, 0xaf, 0x7a, 0xbe, + 0x03, 0x06, 0x13, 0xad, 0x92, 0x2f, 0x60, 0xb5, 0xcc, 0xf9, 0x0b, 0xe9, 0x89, 0x8d, 0xf8, 0x8b, 0x65, 0x1a, 0x8f, + 0xbe, 0xb0, 0x21, 0xe2, 0x59, 0xbd, 0x40, 0xd3, 0x12, 0xd4, 0x01, 0x1e, 0xd1, 0x5f, 0xa3, 0x2f, 0x86, 0x37, 0xa5, + 0xab, 0x91, 0xba, 0x66, 0xe7, 0x9c, 0x7f, 0xa9, 0x0d, 0x11, 0x32, 0xa6, 0x4d, 0x81, 0x64, 0x40, 0x20, 0xc9, 0x40, + 0x00, 0x60, 0x6a, 0x3a, 0xb3, 0x57, 0x00, 0xd1, 0x40, 0x00, 0x8f, 0xf3, 0x8e, 0xc7, 0x8f, 0xf4, 0x57, 0x71, 0xdc, + 0x3b, 0x4d, 0xc3, 0xf6, 0x5f, 0x80, 0xa6, 0x18, 0xca, 0xf1, 0x7c, 0xa7, 0x20, 0xd9, 0xa3, 0x94, 0xa5, 0xab, 0x26, + 0xb2, 0x43, 0xb1, 0x3e, 0xcd, 0x29, 0x0b, 0x69, 0x5b, 0x8e, 0xd1, 0x16, 0xeb, 0xc7, 0xc8, 0x7b, 0x73, 0xa3, 0x22, + 0x1f, 0xf4, 0xe0, 0xf6, 0xf6, 0xe6, 0x55, 0x8f, 0xd9, 0x24, 0x2b, 0x16, 0xb9, 0x8a, 0x38, 0x71, 0x5a, 0x87, 0x1c, + 0x30, 0x20, 0x27, 0x21, 0x30, 0x8d, 0x71, 0xa9, 0x40, 0x07, 0x25, 0xcb, 0x79, 0x0d, 0xd4, 0xb2, 0x88, 0xac, 0x01, + 0xa2, 0x9a, 0xe6, 0x5f, 0x35, 0xe4, 0x27, 0x55, 0x73, 0x4a, 0xa1, 0xf6, 0x15, 0x0f, 0xab, 0xd3, 0x27, 0x56, 0x6d, + 0x62, 0xac, 0x7f, 0xad, 0x3d, 0x41, 0x5b, 0x49, 0x03, 0xf1, 0x9d, 0xaf, 0xd2, 0x3b, 0x0a, 0xdd, 0x71, 0x66, 0xe2, + 0xa9, 0x0a, 0x8c, 0x7d, 0x6b, 0x47, 0x50, 0x38, 0x34, 0x5d, 0x07, 0x1c, 0xa6, 0xd1, 0x09, 0x8b, 0x7f, 0x4a, 0xc7, + 0xc9, 0x8b, 0x5a, 0x21, 0x92, 0xfc, 0x43, 0xb8, 0x30, 0x24, 0x16, 0xe4, 0x25, 0xa1, 0x8e, 0xc8, 0x88, 0xd5, 0xa8, + 0x58, 0x0b, 0x15, 0x15, 0xa7, 0x78, 0xbc, 0x55, 0x50, 0x5c, 0x8a, 0x52, 0xa5, 0x54, 0xe4, 0x46, 0xa5, 0x80, 0x58, + 0x36, 0xf0, 0x6e, 0x01, 0x07, 0x40, 0xd0, 0x59, 0xee, 0xd6, 0xb6, 0xbb, 0x8d, 0xcc, 0x67, 0xa6, 0x79, 0x5a, 0x7d, + 0x50, 0x7f, 0xbf, 0x5f, 0x62, 0x6c, 0x8d, 0xa7, 0xbf, 0x6f, 0xd3, 0x82, 0x9b, 0xbf, 0x61, 0x88, 0xee, 0x00, 0x11, + 0xb3, 0xb4, 0x87, 0x42, 0x16, 0x4c, 0x58, 0x86, 0xaa, 0x3c, 0xe5, 0xa8, 0x97, 0x4f, 0x6e, 0x01, 0x42, 0x0d, 0xfd, + 0xda, 0xe8, 0x54, 0x57, 0x25, 0x08, 0xdf, 0x77, 0x85, 0x7a, 0x6c, 0x0e, 0x78, 0x32, 0x00, 0xfe, 0x8a, 0xbc, 0xd6, + 0x63, 0xfb, 0x07, 0xbd, 0x51, 0x6f, 0x80, 0x20, 0x3a, 0xe7, 0x85, 0x7f, 0xc4, 0xb9, 0x4e, 0xfd, 0x19, 0x17, 0x82, + 0xf8, 0xd6, 0x93, 0xf0, 0x5e, 0x9c, 0xa5, 0x71, 0x70, 0xd6, 0x1b, 0x98, 0x8b, 0x40, 0x71, 0x96, 0xe6, 0x67, 0x20, + 0x96, 0x23, 0x26, 0x62, 0xcd, 0xee, 0x00, 0x26, 0xb0, 0xd4, 0x71, 0xc8, 0xaa, 0x63, 0xfb, 0xfd, 0xd7, 0x23, 0x43, + 0x96, 0x8e, 0x30, 0x30, 0xfa, 0x77, 0x05, 0x02, 0x14, 0x2c, 0x33, 0xdb, 0x83, 0x49, 0x57, 0x7b, 0x56, 0xcf, 0x9b, + 0x4d, 0xde, 0xd5, 0x3b, 0x56, 0xd3, 0x72, 0x6a, 0x5a, 0x65, 0x35, 0x6d, 0x92, 0x43, 0xcd, 0x44, 0xbf, 0xaf, 0x41, + 0x51, 0xf3, 0x39, 0x80, 0xb1, 0x61, 0xf2, 0xeb, 0x59, 0x35, 0xef, 0xf7, 0x3d, 0xf9, 0x08, 0x7e, 0x21, 0x5b, 0x99, + 0x5b, 0x63, 0xf9, 0xf4, 0x15, 0x91, 0x98, 0x19, 0x98, 0xa3, 0xbb, 0x23, 0x7c, 0xaf, 0x1b, 0xe1, 0x75, 0xcc, 0x15, + 0x36, 0x13, 0xd3, 0xd7, 0x30, 0x78, 0x9e, 0xf0, 0xc1, 0x45, 0x8e, 0xfe, 0x46, 0x0e, 0x33, 0x85, 0x05, 0x39, 0xf7, + 0x27, 0xaf, 0x11, 0x2f, 0x19, 0xe1, 0x1d, 0x74, 0x3a, 0xe1, 0x41, 0xf6, 0xfb, 0x2b, 0xe8, 0xcc, 0x56, 0x2a, 0x65, + 0xab, 0xa2, 0x32, 0x5d, 0xd7, 0x45, 0x59, 0x41, 0xc7, 0xd2, 0xcf, 0x5b, 0x21, 0x33, 0xeb, 0x67, 0x16, 0xdc, 0xd3, + 0x4a, 0x02, 0x4c, 0xd9, 0xb6, 0x89, 0xda, 0xc0, 0xcb, 0xba, 0xf8, 0x5c, 0xe0, 0xd1, 0x59, 0x7b, 0xbd, 0x11, 0x6a, + 0x9f, 0xf3, 0xd1, 0xba, 0x58, 0x7b, 0xe0, 0x07, 0x33, 0x4b, 0xe7, 0x8a, 0x38, 0x23, 0xf7, 0x47, 0x9f, 0x8b, 0x34, + 0xa7, 0x3c, 0xc0, 0x7d, 0x28, 0xe6, 0xf6, 0x5b, 0x20, 0xfd, 0xd0, 0x5b, 0x20, 0xfb, 0xe8, 0x9c, 0x93, 0xd7, 0x80, + 0x48, 0x87, 0x30, 0xb8, 0x15, 0x09, 0x3a, 0x56, 0x0d, 0x6f, 0x2d, 0xb0, 0xd3, 0x5e, 0x1a, 0xf7, 0xd2, 0xfc, 0x2c, + 0xed, 0xf7, 0x0d, 0x6a, 0x66, 0x8a, 0x70, 0xf0, 0x38, 0x23, 0x17, 0x49, 0x0b, 0xb6, 0x94, 0xf6, 0x5f, 0x0d, 0x1c, + 0x41, 0xc8, 0xdf, 0xff, 0x10, 0xde, 0x13, 0x80, 0xd8, 0xa4, 0x0d, 0xb8, 0xea, 0x31, 0x1d, 0x8d, 0x2d, 0x89, 0x5a, + 0x75, 0x36, 0x40, 0xe2, 0x54, 0x69, 0x3d, 0xe5, 0x66, 0x4d, 0x61, 0x90, 0x2a, 0x0b, 0xf5, 0x1b, 0xeb, 0xc9, 0x64, + 0x95, 0x8b, 0x8c, 0x38, 0x2a, 0xd3, 0x97, 0x9a, 0x11, 0x4c, 0x97, 0x7e, 0xbe, 0x80, 0x25, 0x1b, 0x7f, 0xc4, 0xc9, + 0x5b, 0x02, 0x8e, 0xed, 0xac, 0x5d, 0x55, 0xbb, 0x1c, 0xb7, 0x76, 0x73, 0x80, 0xef, 0xf5, 0x46, 0xa3, 0x91, 0x76, + 0x8e, 0x13, 0x30, 0x54, 0x3d, 0xb5, 0x14, 0x7a, 0xac, 0x56, 0x80, 0xba, 0x1d, 0xb9, 0xcc, 0x92, 0xc1, 0x7c, 0x61, + 0x1c, 0xbf, 0x34, 0x1f, 0x7d, 0xbc, 0x54, 0xd6, 0xae, 0x23, 0xbe, 0xfe, 0x83, 0xac, 0xd6, 0xb7, 0xbc, 0xab, 0x9a, + 0x80, 0x2f, 0xaa, 0x80, 0xd2, 0x6f, 0x78, 0x4f, 0xf6, 0x2e, 0xbe, 0x76, 0x83, 0x5d, 0xf2, 0x2d, 0x6f, 0x51, 0xe7, + 0xf9, 0xca, 0xc1, 0x8d, 0x2a, 0xdd, 0xde, 0x4b, 0x16, 0xb8, 0xf6, 0x8e, 0x9a, 0xc6, 0x7a, 0xe6, 0x47, 0x0f, 0x8b, + 0x90, 0xed, 0x7c, 0xec, 0x7d, 0xd5, 0x3c, 0x3d, 0x6b, 0xe8, 0x4d, 0x6a, 0xe8, 0x63, 0x2f, 0xca, 0xf6, 0xa9, 0x69, + 0x44, 0xaf, 0x61, 0x43, 0x1f, 0x7b, 0x4b, 0x4e, 0x0e, 0x89, 0x00, 0xa7, 0xc6, 0xfc, 0xf1, 0xe1, 0x74, 0x86, 0xbf, + 0x63, 0x40, 0x25, 0x10, 0xf3, 0xe9, 0x31, 0xed, 0x28, 0xc0, 0x8c, 0x2a, 0xbd, 0x7d, 0x7a, 0x60, 0x3b, 0x5e, 0xd6, + 0x43, 0x4b, 0xef, 0x9e, 0x1c, 0xdd, 0x8e, 0x57, 0xd5, 0xf8, 0x52, 0x0e, 0x79, 0x9e, 0xcf, 0x46, 0xa3, 0x91, 0x30, + 0x90, 0xdc, 0x95, 0xde, 0xc0, 0x0a, 0xa4, 0x6d, 0x51, 0x7d, 0x28, 0x97, 0xde, 0x4e, 0x1d, 0xda, 0x95, 0x3f, 0xc9, + 0x0f, 0x87, 0x62, 0x64, 0x8e, 0x71, 0x00, 0x37, 0x29, 0x94, 0x1c, 0x25, 0x6b, 0x09, 0xa2, 0x53, 0x1a, 0x4f, 0x65, + 0xbd, 0xb6, 0x22, 0xf2, 0x6a, 0xc4, 0x79, 0x08, 0x7e, 0xf4, 0x40, 0x2d, 0x7e, 0xad, 0x05, 0xb1, 0xc7, 0x3e, 0x55, + 0x4a, 0x2f, 0x78, 0x55, 0x40, 0x88, 0xd8, 0xdf, 0x0d, 0xb4, 0x83, 0x12, 0x1c, 0x4a, 0xb8, 0x0f, 0x08, 0x0b, 0xfd, + 0xca, 0xcb, 0x67, 0x32, 0x46, 0xb9, 0x37, 0xa8, 0xe6, 0x0c, 0x60, 0x2a, 0x7d, 0x06, 0x7e, 0x97, 0x00, 0x75, 0x8a, + 0x4f, 0xd1, 0xa9, 0xde, 0x3c, 0x6c, 0xba, 0x3e, 0x2d, 0x51, 0x14, 0xd1, 0x9d, 0x9f, 0x8f, 0x01, 0xb1, 0xb3, 0x6b, + 0x33, 0xd2, 0xae, 0xfd, 0x06, 0x0d, 0x56, 0x4a, 0x12, 0xed, 0x9c, 0x12, 0x76, 0x3b, 0x1f, 0xd9, 0xd2, 0x8f, 0x52, + 0x20, 0xe6, 0x8e, 0x13, 0x89, 0xec, 0xc1, 0x46, 0x4e, 0xe0, 0x16, 0xed, 0x1d, 0x1d, 0x80, 0xca, 0x8d, 0x82, 0xfc, + 0x6a, 0x8e, 0xe4, 0x8e, 0xef, 0x7a, 0xdf, 0x0d, 0xea, 0xc1, 0x77, 0xbd, 0xb3, 0x94, 0xe4, 0x8e, 0xf0, 0x4c, 0x4d, + 0x09, 0x11, 0x9f, 0x7d, 0x37, 0xc8, 0x07, 0x78, 0x96, 0x68, 0x91, 0x16, 0x09, 0xd5, 0xea, 0x1a, 0x37, 0xe1, 0x45, + 0x22, 0xb9, 0x87, 0x76, 0x9d, 0x47, 0xc4, 0x02, 0x90, 0xb1, 0xf8, 0x6c, 0xde, 0x50, 0xa8, 0xbb, 0x89, 0xd9, 0xa2, + 0xbb, 0x2c, 0xf6, 0xfb, 0x9b, 0x3c, 0xad, 0x7b, 0x3a, 0x3e, 0x06, 0x5f, 0x90, 0x6a, 0x02, 0x3c, 0xda, 0x5f, 0x99, + 0xe3, 0xd5, 0xab, 0xcd, 0x91, 0xb2, 0x50, 0x25, 0xea, 0xb7, 0x58, 0xcd, 0x7a, 0x08, 0xc3, 0x9d, 0x65, 0xc6, 0xda, + 0x5e, 0xf0, 0x4a, 0xce, 0xaa, 0xd8, 0x2e, 0xc7, 0x57, 0x2c, 0xb5, 0x95, 0x44, 0xe5, 0x68, 0x3d, 0xd6, 0xa6, 0x18, + 0xf9, 0x95, 0x42, 0xa2, 0x2c, 0x3a, 0xb6, 0x16, 0x0a, 0x88, 0x17, 0xa0, 0x2f, 0xd9, 0x99, 0x06, 0x58, 0x6f, 0xf4, + 0x2a, 0x22, 0xb4, 0x7c, 0xa4, 0xc2, 0x9b, 0xdc, 0x54, 0x99, 0x95, 0xcd, 0xa2, 0xdd, 0x4f, 0x15, 0xaf, 0x10, 0xac, + 0xde, 0xa8, 0x3d, 0x0a, 0x50, 0x7b, 0x68, 0xa1, 0x0c, 0x20, 0xa5, 0x69, 0x06, 0x80, 0x0c, 0x00, 0x32, 0x55, 0xc4, + 0x67, 0x02, 0x54, 0xda, 0xea, 0x46, 0x81, 0x13, 0xe9, 0x15, 0xd0, 0x2c, 0xb0, 0xd2, 0x47, 0x0a, 0x32, 0x58, 0x6c, + 0x11, 0x80, 0x95, 0x23, 0x67, 0x98, 0xc6, 0x90, 0x6d, 0x34, 0x71, 0x49, 0x9a, 0xdf, 0x87, 0x59, 0x2a, 0xf1, 0x24, + 0x7e, 0x90, 0x35, 0x46, 0x00, 0x20, 0x7d, 0x9f, 0x5e, 0x14, 0x59, 0x4c, 0x38, 0x70, 0xd6, 0x53, 0x07, 0x45, 0x4d, + 0xce, 0xb5, 0xa6, 0xd5, 0xb3, 0xda, 0xe4, 0x21, 0x0b, 0x74, 0xf6, 0x60, 0x4c, 0x6a, 0xf9, 0x9e, 0x47, 0xf6, 0x57, + 0x8e, 0x67, 0x84, 0xef, 0xba, 0x83, 0x53, 0xff, 0xdd, 0xd4, 0xc0, 0xc4, 0x94, 0x00, 0x6c, 0x0c, 0x8e, 0x26, 0xc4, + 0xef, 0x74, 0x4c, 0xa6, 0x36, 0x29, 0x02, 0x81, 0x87, 0xe0, 0x15, 0x3c, 0x37, 0x5c, 0x6e, 0xb9, 0xb1, 0xb3, 0xc8, + 0xd3, 0x04, 0xe0, 0xc4, 0x0b, 0xbe, 0x05, 0x38, 0x4e, 0xbd, 0x2a, 0x64, 0xcf, 0x9e, 0x8b, 0xe9, 0x6c, 0x1e, 0x3c, + 0x24, 0xb4, 0x7f, 0x31, 0xe1, 0x37, 0xdd, 0x55, 0x72, 0x65, 0x6a, 0xdd, 0x9b, 0xe8, 0x2a, 0x97, 0x3b, 0x7d, 0x5a, + 0x71, 0x0c, 0x73, 0x06, 0xab, 0x80, 0x9c, 0xb3, 0x21, 0xbf, 0x3e, 0x07, 0xc0, 0x96, 0x95, 0xf0, 0x22, 0x7e, 0x1d, + 0xca, 0x6a, 0x01, 0xdc, 0x23, 0xe7, 0x91, 0xf9, 0xe5, 0xab, 0xed, 0x50, 0xce, 0x29, 0x0a, 0x63, 0x39, 0x35, 0x2d, + 0x29, 0x4e, 0x87, 0x9e, 0x82, 0xc9, 0xd4, 0x96, 0xbf, 0xb7, 0x89, 0xcb, 0xec, 0xcd, 0x24, 0x9c, 0xaf, 0x23, 0xdb, + 0xd6, 0xaa, 0x7b, 0xe8, 0x86, 0x60, 0xd0, 0xc7, 0x08, 0x5a, 0x36, 0xd7, 0x77, 0xeb, 0xc1, 0x40, 0x61, 0xfb, 0xd6, + 0x74, 0xd3, 0xa2, 0x53, 0x1c, 0x70, 0x66, 0xad, 0x6b, 0x54, 0xaa, 0x8a, 0x43, 0x2f, 0x79, 0xb7, 0xac, 0xca, 0x2e, + 0x4b, 0x2f, 0x04, 0xa9, 0x51, 0x57, 0x11, 0x22, 0xa5, 0x62, 0x87, 0xf7, 0xe4, 0xd7, 0xc0, 0xc4, 0x33, 0x2b, 0x47, + 0x69, 0x3c, 0x07, 0x98, 0x20, 0x85, 0xbe, 0x29, 0xbf, 0x02, 0xdc, 0xd0, 0x45, 0x14, 0x66, 0x6f, 0xe2, 0x2a, 0xa8, + 0xad, 0xa6, 0xdf, 0x3b, 0x38, 0xb1, 0xe7, 0x75, 0xbf, 0x9f, 0x12, 0x8d, 0x1f, 0x86, 0x5e, 0xe0, 0xdf, 0xe3, 0xe9, + 0xbe, 0x09, 0x52, 0xf3, 0xca, 0x03, 0xbc, 0xa2, 0xcb, 0xad, 0x4d, 0xb9, 0xa2, 0x71, 0x31, 0xaf, 0x11, 0x11, 0x3e, + 0x75, 0x14, 0xdb, 0x6d, 0x7e, 0x9c, 0xda, 0x18, 0x0c, 0x42, 0xb8, 0x6f, 0x65, 0xfc, 0x3e, 0xf1, 0xf2, 0x59, 0x34, + 0x07, 0x45, 0x69, 0xa6, 0x49, 0x42, 0x0a, 0xe9, 0x25, 0x40, 0x1f, 0x0d, 0x42, 0xad, 0xae, 0xfc, 0x23, 0xf1, 0x52, + 0x35, 0xad, 0xcd, 0x53, 0xac, 0x51, 0x20, 0x66, 0xd1, 0xbc, 0x61, 0x19, 0x1d, 0x92, 0xea, 0x72, 0x69, 0x9a, 0xf1, + 0x87, 0xd5, 0x0c, 0xd5, 0x8a, 0xa3, 0x26, 0xa8, 0x51, 0xba, 0x81, 0x0b, 0xe0, 0xdf, 0xe9, 0x8e, 0xa3, 0x1a, 0x45, + 0x8a, 0x06, 0x7c, 0x82, 0xc0, 0xb0, 0x66, 0xf3, 0x84, 0xb5, 0xa6, 0xae, 0x19, 0xfd, 0xbe, 0x8c, 0x13, 0x32, 0x49, + 0x48, 0xce, 0x87, 0xcb, 0xf5, 0x23, 0xa9, 0x2e, 0x80, 0x54, 0xb9, 0x62, 0xb3, 0x5e, 0x6f, 0x0e, 0x18, 0xbd, 0xb0, + 0x7e, 0x61, 0xe3, 0x0a, 0xce, 0x2f, 0x09, 0x73, 0x57, 0xfd, 0x08, 0xb3, 0x0c, 0xaa, 0x80, 0x34, 0x3f, 0x16, 0xbc, + 0x79, 0xee, 0x02, 0x51, 0xbf, 0x1e, 0xa9, 0x0b, 0xca, 0x2c, 0x9d, 0x5b, 0x44, 0x20, 0xe0, 0x35, 0xac, 0x9e, 0x40, + 0xb2, 0x2f, 0x1f, 0xfb, 0x34, 0xa3, 0x40, 0x75, 0x04, 0xa0, 0x6c, 0xd6, 0x0f, 0x61, 0xff, 0x80, 0x70, 0x42, 0xfd, + 0xcd, 0x1b, 0x39, 0x6b, 0x48, 0x1e, 0x48, 0x35, 0xe1, 0x31, 0x9c, 0x1a, 0x0b, 0x7c, 0x69, 0xd1, 0x9b, 0x0a, 0x5e, + 0x13, 0x1c, 0xf7, 0x02, 0xad, 0x7d, 0x0b, 0x38, 0x42, 0x04, 0x97, 0xa1, 0x89, 0xd3, 0xde, 0xae, 0x17, 0x20, 0xa1, + 0xb9, 0x85, 0x73, 0xfd, 0xd6, 0x05, 0x2d, 0x4e, 0x91, 0x93, 0x45, 0x17, 0x18, 0xe8, 0x82, 0xcc, 0x1b, 0xff, 0xaa, + 0x60, 0xe5, 0x02, 0x64, 0x2f, 0x15, 0x2b, 0x89, 0xd8, 0x76, 0xea, 0x8f, 0x52, 0xd9, 0x6f, 0xcf, 0xac, 0x09, 0xfc, + 0x32, 0xb1, 0x5f, 0x22, 0x93, 0x6f, 0x7a, 0x6c, 0xf2, 0x95, 0xb1, 0xd0, 0xa9, 0x65, 0x70, 0x4e, 0x8f, 0x0c, 0xce, + 0xbd, 0x9d, 0x55, 0x9b, 0x10, 0x86, 0x82, 0x24, 0xd0, 0x74, 0xe9, 0x61, 0xdd, 0xf4, 0xe7, 0x27, 0x2d, 0x7e, 0xad, + 0xda, 0xb7, 0xee, 0xc7, 0x21, 0x76, 0xf1, 0xcb, 0xc4, 0x33, 0xec, 0xa3, 0x3e, 0x70, 0x80, 0xc9, 0x88, 0x89, 0xcb, + 0x7e, 0x1f, 0x0a, 0x9b, 0x8d, 0xe7, 0xa3, 0xba, 0xf8, 0xb9, 0x78, 0x00, 0x28, 0x87, 0x0a, 0xec, 0x72, 0x28, 0x43, + 0x19, 0xb1, 0xa9, 0x2d, 0xf7, 0xfc, 0xfe, 0x32, 0xcc, 0x41, 0xde, 0xd1, 0x98, 0x38, 0x67, 0x20, 0x86, 0xc1, 0xd7, + 0xbf, 0x7b, 0xb2, 0x4f, 0x9b, 0xef, 0xce, 0xe0, 0xbb, 0xa3, 0xb3, 0x0f, 0xc8, 0x71, 0x73, 0xb6, 0x2e, 0x8b, 0xfb, + 0x34, 0x16, 0x67, 0xdf, 0x41, 0xea, 0x77, 0x67, 0x45, 0x79, 0xf6, 0x9d, 0xaa, 0xcc, 0x77, 0x67, 0xb4, 0xe0, 0x46, + 0xbf, 0x5b, 0x13, 0xef, 0x9f, 0x95, 0xa6, 0x3d, 0x5b, 0x42, 0x38, 0x96, 0x56, 0x3f, 0x82, 0x12, 0x51, 0x91, 0xa2, + 0xca, 0x50, 0x56, 0x6b, 0xc7, 0x79, 0x9f, 0x68, 0x78, 0x6c, 0x9a, 0x90, 0xb8, 0x5a, 0xc2, 0x3a, 0xd4, 0xb3, 0xd3, + 0x26, 0xd9, 0x71, 0x1e, 0xa8, 0x03, 0x22, 0xe7, 0xd7, 0xf9, 0x68, 0x4b, 0x5f, 0x83, 0x6f, 0x1d, 0x0e, 0xf9, 0x68, + 0x67, 0x7e, 0xfa, 0x64, 0xad, 0x94, 0xc1, 0x46, 0x8a, 0x51, 0x08, 0x89, 0xe2, 0xb6, 0x3d, 0x06, 0xc0, 0xff, 0xfe, + 0xe1, 0x40, 0xbf, 0x77, 0xf2, 0xb7, 0xda, 0x2d, 0xad, 0x7a, 0x7e, 0x68, 0x11, 0x66, 0xbc, 0xaa, 0x0d, 0x3b, 0xdb, + 0x5e, 0x02, 0x4a, 0xef, 0x9b, 0x06, 0x35, 0x45, 0xf4, 0x13, 0x56, 0x13, 0xab, 0x38, 0x2c, 0x48, 0x89, 0x43, 0x0c, + 0xc7, 0x68, 0x87, 0x1e, 0xa7, 0x8b, 0x9a, 0x27, 0xf7, 0x1d, 0x32, 0x6e, 0x7d, 0x1f, 0x90, 0x5c, 0x0a, 0xe7, 0x1f, + 0xbc, 0xd0, 0x60, 0xa2, 0x17, 0x79, 0x55, 0x64, 0x62, 0x24, 0x68, 0x94, 0xdf, 0x90, 0x38, 0x73, 0x86, 0xb5, 0x38, + 0x53, 0x08, 0x61, 0x21, 0xa1, 0x72, 0x17, 0x25, 0xa5, 0x07, 0x67, 0x4f, 0xf6, 0x65, 0xf3, 0x3b, 0x61, 0x42, 0x8c, + 0x16, 0x40, 0x83, 0xb3, 0x6b, 0x97, 0xf7, 0x10, 0x96, 0xb9, 0xf7, 0xfb, 0x9b, 0xbb, 0xbc, 0x80, 0xb8, 0xcc, 0x33, + 0xa9, 0x58, 0x2d, 0xcf, 0x80, 0x26, 0x4f, 0xc4, 0x67, 0x61, 0x25, 0xa7, 0x41, 0xd5, 0x51, 0xac, 0xde, 0xc6, 0x73, + 0x0f, 0x78, 0xbd, 0xdf, 0x27, 0x40, 0xe0, 0xee, 0xb3, 0xd7, 0xca, 0x2d, 0x95, 0xf4, 0xc8, 0x73, 0x0c, 0x91, 0x4c, + 0x80, 0xd7, 0x19, 0x82, 0x23, 0x85, 0xd5, 0x73, 0x13, 0xe4, 0x1f, 0x5f, 0x9f, 0x50, 0x7c, 0xd1, 0x3c, 0x8a, 0x1a, + 0x16, 0xb2, 0x04, 0x8e, 0x87, 0x64, 0x96, 0xcd, 0x91, 0x9a, 0x3c, 0x6d, 0x4f, 0x91, 0x8e, 0x4e, 0x2c, 0xf1, 0xdb, + 0x9a, 0x54, 0x2f, 0x52, 0x61, 0x97, 0xb4, 0xb3, 0x95, 0xb9, 0x17, 0xc2, 0x50, 0x25, 0xdc, 0x7b, 0x55, 0xcf, 0x42, + 0xb9, 0x29, 0x5a, 0x15, 0xb3, 0x87, 0x29, 0x31, 0xc3, 0x14, 0xeb, 0x2f, 0x6c, 0xf8, 0x4d, 0xe2, 0xc5, 0x60, 0xb8, + 0x5e, 0xf2, 0x72, 0xb6, 0x31, 0x0b, 0xe1, 0x70, 0xd8, 0x4c, 0x8a, 0xd9, 0x12, 0x62, 0x5b, 0x97, 0xf3, 0xc3, 0xa1, + 0xab, 0x65, 0x6b, 0xe1, 0xc1, 0x43, 0xd5, 0xc2, 0x4d, 0xc3, 0x72, 0xf8, 0x99, 0xcc, 0x62, 0x6c, 0x5f, 0xe3, 0x33, + 0xfb, 0xf3, 0x45, 0xf7, 0x2c, 0x41, 0xc6, 0x8d, 0x35, 0x70, 0x8d, 0xcd, 0xda, 0x1d, 0xae, 0x46, 0x40, 0xf2, 0xb8, + 0x1b, 0xfd, 0x5d, 0xd9, 0x49, 0x4e, 0x82, 0x84, 0xd1, 0x0a, 0xe1, 0x77, 0xdf, 0xf8, 0x13, 0x2d, 0xf6, 0xa0, 0xdd, + 0xc6, 0x96, 0x10, 0xd5, 0xb4, 0xe7, 0x72, 0xa5, 0x58, 0x9a, 0xb7, 0xd2, 0x86, 0xcc, 0x87, 0xf5, 0xb9, 0x6f, 0xe4, + 0x40, 0xc1, 0x18, 0xf1, 0xd4, 0x3a, 0x88, 0x66, 0x73, 0xe0, 0xbe, 0x40, 0xf3, 0x08, 0x4f, 0x2d, 0x48, 0x50, 0x66, + 0x6d, 0xd8, 0x4f, 0x92, 0x93, 0xe5, 0x71, 0xf8, 0x16, 0xfe, 0xe5, 0x33, 0x6c, 0x12, 0x53, 0x14, 0x8f, 0xbf, 0x55, + 0x8a, 0xff, 0x8e, 0x2d, 0x88, 0x60, 0xed, 0x46, 0xd4, 0x86, 0xbf, 0xe1, 0xdf, 0xc2, 0x3e, 0xc2, 0x7e, 0x43, 0x13, + 0x84, 0x01, 0xac, 0x3f, 0x13, 0x88, 0x0b, 0x0b, 0x41, 0x82, 0xbf, 0x55, 0x92, 0x7f, 0x4e, 0xf8, 0x6c, 0x51, 0x02, + 0x59, 0x1d, 0x46, 0xf1, 0x09, 0xc5, 0x44, 0x21, 0x0c, 0xb7, 0x84, 0xde, 0xd1, 0x7f, 0x23, 0x4a, 0xb2, 0x49, 0x6e, + 0xc5, 0x7a, 0x20, 0x93, 0x24, 0x98, 0x60, 0xe5, 0x85, 0xf2, 0x85, 0x7b, 0xa1, 0xd4, 0x5a, 0x0b, 0x5a, 0xbf, 0xfc, + 0x49, 0xe2, 0x19, 0xd0, 0x3d, 0x90, 0x31, 0xe8, 0x36, 0xa2, 0x9a, 0xe4, 0x98, 0x3e, 0x4a, 0xe7, 0x19, 0xa8, 0x80, + 0xce, 0xd6, 0x59, 0x58, 0x2f, 0x8b, 0x72, 0xd5, 0x0a, 0x0f, 0x95, 0xa5, 0x8f, 0xd4, 0x63, 0xcc, 0x0b, 0xf3, 0xe4, + 0x44, 0x3e, 0x78, 0x04, 0x68, 0x78, 0x94, 0xa7, 0x55, 0x47, 0x69, 0xfd, 0xc0, 0x32, 0x60, 0x04, 0x4e, 0x94, 0x01, + 0x8f, 0xb0, 0x0c, 0xcc, 0xd3, 0x2e, 0x43, 0x0d, 0x62, 0x8d, 0xaa, 0x2b, 0xb5, 0xc1, 0x9c, 0x28, 0x4a, 0x3e, 0xc5, + 0xd2, 0x0a, 0x63, 0x68, 0xea, 0xca, 0x23, 0xeb, 0x25, 0x27, 0xec, 0xc9, 0x6e, 0x20, 0xdd, 0xc2, 0x46, 0x81, 0x0b, + 0xba, 0x96, 0x25, 0xca, 0x45, 0xb7, 0x8c, 0x28, 0x13, 0x21, 0xf5, 0xb3, 0x87, 0x33, 0xad, 0xf6, 0x1b, 0x3b, 0x69, + 0xdf, 0x1e, 0x29, 0x7a, 0xc1, 0x40, 0x7c, 0xda, 0x23, 0xa5, 0x9e, 0x35, 0x72, 0x19, 0xd8, 0xd2, 0xa5, 0xaa, 0xe7, + 0xbf, 0x41, 0xf9, 0x0e, 0x66, 0xc6, 0xd9, 0xec, 0x77, 0xbd, 0xb9, 0x3d, 0xd9, 0xd7, 0xcd, 0xef, 0xac, 0xd7, 0x83, + 0xad, 0x41, 0x26, 0xbe, 0x50, 0xd4, 0x53, 0x56, 0x21, 0x56, 0x64, 0xf6, 0xbf, 0x85, 0xf7, 0x3b, 0xbc, 0x35, 0x42, + 0xb3, 0x32, 0x1e, 0xe6, 0xa3, 0x27, 0x7b, 0xd1, 0xfc, 0xde, 0x59, 0xb6, 0x95, 0xab, 0x92, 0xd9, 0x7e, 0x3f, 0x4a, + 0x9a, 0xb3, 0xc7, 0x6b, 0x24, 0x75, 0x80, 0x8f, 0xd7, 0x67, 0xf8, 0x48, 0x25, 0x94, 0x5a, 0x50, 0xd5, 0xa0, 0xf5, + 0xb1, 0xdf, 0x5b, 0xcf, 0xe9, 0xe3, 0xc7, 0x72, 0xba, 0x25, 0x45, 0x18, 0x3f, 0x30, 0x98, 0xb2, 0x13, 0xa7, 0x2e, + 0x79, 0x33, 0xa4, 0x77, 0xdd, 0x2a, 0xa9, 0xcb, 0x1e, 0x25, 0x82, 0x50, 0x07, 0xeb, 0x17, 0xfb, 0x21, 0xcc, 0x6c, + 0xd1, 0x1f, 0x36, 0xab, 0x39, 0xa1, 0x20, 0x02, 0x44, 0xab, 0xbc, 0x0f, 0x1c, 0x93, 0x84, 0x59, 0x73, 0x43, 0xba, + 0xf5, 0xe6, 0x4a, 0x7b, 0x25, 0x05, 0xf4, 0x73, 0x90, 0xb9, 0x7d, 0x74, 0xcb, 0x55, 0xcb, 0x3c, 0x97, 0xb6, 0x1c, + 0xb0, 0x68, 0x21, 0x3a, 0xb3, 0x73, 0xe9, 0x70, 0xf0, 0x1f, 0xd4, 0x95, 0xa8, 0x22, 0x82, 0x8e, 0xa2, 0x05, 0xa3, + 0xd5, 0xaa, 0x5d, 0x4e, 0x36, 0x15, 0xb2, 0x25, 0x11, 0x4e, 0x94, 0xec, 0x95, 0x50, 0x1f, 0xe5, 0x6a, 0xcf, 0x34, + 0xc4, 0x9f, 0x09, 0xd8, 0xb4, 0xc1, 0xdf, 0x02, 0xf7, 0x32, 0x38, 0x33, 0xed, 0xd3, 0x30, 0x02, 0x22, 0x73, 0x08, + 0xf6, 0xf3, 0xbb, 0x1e, 0x54, 0xf0, 0xa0, 0x23, 0xfd, 0x55, 0x3d, 0x2b, 0xf0, 0xcc, 0x3d, 0xf1, 0xfc, 0xf5, 0x89, + 0xf4, 0x22, 0x87, 0x07, 0x9a, 0xfb, 0x30, 0xe3, 0x2f, 0xca, 0x32, 0xdc, 0x8d, 0x96, 0x65, 0xb1, 0xf2, 0x22, 0xbd, + 0x8f, 0x67, 0x52, 0x0c, 0x24, 0x3a, 0xcc, 0x8c, 0xae, 0x62, 0x1d, 0xe7, 0x30, 0xee, 0xed, 0x49, 0x58, 0xa1, 0xfd, + 0xb3, 0xc4, 0x5e, 0x17, 0x00, 0xe0, 0x90, 0x35, 0x68, 0x85, 0x77, 0xba, 0xbd, 0xdd, 0xe3, 0x92, 0x12, 0xc5, 0x8d, + 0x9a, 0x9f, 0xd5, 0xd0, 0x32, 0x41, 0x2d, 0xb3, 0xee, 0x64, 0x32, 0x45, 0x12, 0xf8, 0x36, 0xec, 0x35, 0x2b, 0xf2, + 0x79, 0x23, 0xb7, 0x87, 0x77, 0xe1, 0x4a, 0xc4, 0xda, 0x82, 0x4e, 0x3a, 0x32, 0x0e, 0xf7, 0x42, 0x73, 0x23, 0xdd, + 0x3f, 0xa9, 0x92, 0xb0, 0x14, 0x31, 0xdc, 0x02, 0xd9, 0x5e, 0x6d, 0x2b, 0x41, 0x09, 0x24, 0xb0, 0x1f, 0x4a, 0xb1, + 0x4c, 0xb7, 0x02, 0xc0, 0x1c, 0xf8, 0x9f, 0x12, 0x86, 0xd0, 0xdd, 0x79, 0x88, 0x57, 0x8d, 0xbc, 0x6f, 0x10, 0x82, + 0xfd, 0x15, 0xc8, 0x69, 0xc0, 0x20, 0x52, 0x8c, 0x64, 0xc1, 0x40, 0x02, 0x90, 0xf3, 0x35, 0x98, 0xe4, 0xa6, 0xb9, + 0xe7, 0x07, 0xb9, 0xee, 0x60, 0xda, 0x07, 0xdd, 0x8b, 0x6b, 0xcd, 0x72, 0xf0, 0x8a, 0x89, 0xf8, 0xdf, 0x6b, 0xaf, + 0x64, 0x39, 0xcb, 0xfc, 0xc6, 0x5c, 0x74, 0x32, 0xb8, 0x6a, 0x08, 0xbf, 0x98, 0x65, 0x73, 0x1e, 0xcd, 0x32, 0x1d, + 0xea, 0x5f, 0x34, 0x47, 0xa5, 0x00, 0x86, 0x3a, 0x5e, 0x80, 0x35, 0xde, 0x95, 0x6e, 0x5a, 0xf1, 0x48, 0x63, 0x8c, + 0x82, 0x0a, 0x1d, 0x84, 0xfe, 0x5e, 0x03, 0xbc, 0x06, 0x93, 0xdc, 0x08, 0x95, 0x0f, 0x2e, 0xe8, 0x86, 0x6e, 0xb9, + 0x72, 0x09, 0x6a, 0x52, 0xb5, 0xfc, 0x72, 0x84, 0x7a, 0x57, 0x4b, 0x2e, 0xd5, 0xe6, 0x53, 0xa3, 0xac, 0x11, 0x64, + 0x72, 0x94, 0x7e, 0x9f, 0x72, 0xe1, 0x56, 0xc6, 0x64, 0x7d, 0x38, 0x78, 0x05, 0x37, 0x35, 0x7e, 0x95, 0x13, 0x8b, + 0xa8, 0x3d, 0x24, 0xc2, 0xd6, 0x6e, 0x85, 0xee, 0x3d, 0x6e, 0x94, 0xe6, 0x51, 0xb6, 0x89, 0x45, 0xe5, 0xf5, 0x12, + 0xb0, 0x16, 0xf7, 0x80, 0x0c, 0x95, 0x96, 0x7e, 0xc5, 0x0a, 0x80, 0x0c, 0x90, 0xc2, 0xc6, 0x0f, 0x48, 0x7b, 0xf5, + 0xc1, 0x4b, 0xfd, 0x7e, 0xdf, 0x98, 0xf2, 0xdf, 0x3f, 0xe4, 0xc0, 0x4c, 0x28, 0xca, 0x7a, 0x07, 0x13, 0x08, 0xae, + 0x9d, 0xa4, 0x3d, 0xab, 0xf9, 0xf5, 0xba, 0xf6, 0x80, 0xd4, 0xca, 0xb7, 0x98, 0xab, 0x5e, 0xd9, 0x17, 0x9b, 0x7d, + 0x5a, 0xdd, 0x18, 0x8d, 0x83, 0x60, 0x69, 0xf5, 0x46, 0xab, 0x1c, 0xf2, 0x86, 0x57, 0x20, 0x52, 0x59, 0x57, 0xd7, + 0xca, 0xb9, 0xba, 0x16, 0x1c, 0x09, 0x64, 0x4b, 0x9e, 0xc3, 0x7f, 0x21, 0xf7, 0xca, 0xc3, 0xa1, 0xf0, 0xfb, 0xfd, + 0x74, 0x46, 0x5a, 0x59, 0xa0, 0x4c, 0x5b, 0xd7, 0x5e, 0xe8, 0x1f, 0x0e, 0x3f, 0x80, 0xd7, 0x88, 0x7f, 0x38, 0x94, + 0xfd, 0xfe, 0x47, 0x73, 0x93, 0x39, 0x1f, 0x2b, 0xa5, 0xec, 0x25, 0x2a, 0xdd, 0xdf, 0x24, 0xbc, 0xf7, 0xbf, 0x47, + 0xff, 0x7b, 0x74, 0xd9, 0x53, 0x01, 0x60, 0x09, 0x9f, 0xe1, 0x0d, 0x9d, 0xa9, 0xcb, 0x39, 0x93, 0xee, 0xee, 0xca, + 0x0f, 0xbd, 0xa7, 0xf1, 0xe1, 0x7b, 0x73, 0xd3, 0xc6, 0x5f, 0xab, 0x23, 0x4d, 0x42, 0xc7, 0x45, 0xff, 0x70, 0xf8, + 0x94, 0x68, 0x7d, 0x5a, 0xaa, 0xf4, 0x69, 0x0a, 0x3c, 0xc9, 0xb0, 0xe1, 0xba, 0x85, 0xe9, 0x68, 0x7e, 0xdc, 0x7c, + 0x95, 0xbc, 0x38, 0x4b, 0xe1, 0xda, 0x9b, 0xcf, 0xd2, 0xf9, 0x14, 0xac, 0x2b, 0xc3, 0x7c, 0x56, 0xcf, 0x03, 0x48, + 0x1d, 0x42, 0x9a, 0x35, 0x0d, 0xff, 0x56, 0xb9, 0x82, 0xb7, 0xf6, 0x78, 0x37, 0x18, 0x51, 0xea, 0x48, 0x9f, 0xb4, + 0x21, 0x74, 0x49, 0x25, 0xff, 0x51, 0xe4, 0x31, 0xc6, 0x6c, 0xbc, 0x22, 0xb2, 0xcf, 0x22, 0x7f, 0x59, 0x00, 0x60, + 0x11, 0x20, 0x20, 0xa7, 0x73, 0x47, 0x12, 0xff, 0x39, 0xf9, 0xf6, 0x8f, 0xe9, 0xd2, 0x3e, 0x94, 0xc5, 0x5d, 0x29, + 0xaa, 0xea, 0xa8, 0xb4, 0x9d, 0x2d, 0xd7, 0x03, 0x7d, 0x68, 0xbf, 0x2f, 0xe9, 0x43, 0x53, 0x0c, 0x45, 0x81, 0x5b, + 0x63, 0x6f, 0x9a, 0x72, 0x45, 0x53, 0x3d, 0x32, 0xd6, 0xcf, 0xef, 0x77, 0x6f, 0x62, 0x2f, 0xf5, 0x83, 0x14, 0x04, + 0x61, 0x8d, 0x9f, 0x94, 0x22, 0x09, 0x9c, 0xcf, 0x30, 0x95, 0xf8, 0x74, 0x29, 0x55, 0xfe, 0x30, 0xd2, 0x7c, 0x98, + 0x82, 0x5e, 0xf6, 0x1f, 0x15, 0xcc, 0x7f, 0xdd, 0x1e, 0xac, 0x4f, 0xeb, 0x32, 0x8d, 0x2a, 0xa2, 0xca, 0x0b, 0x53, + 0x6d, 0x02, 0x11, 0xfc, 0x5a, 0x58, 0x24, 0xbf, 0x3e, 0x39, 0x12, 0x34, 0x66, 0xb2, 0x7c, 0x3c, 0x72, 0xbf, 0xb0, + 0xaf, 0x5c, 0xc7, 0xf3, 0x3f, 0x37, 0xf3, 0x7f, 0x80, 0xce, 0x90, 0xc5, 0x35, 0xb7, 0x0c, 0x16, 0x38, 0xfb, 0xa5, + 0xab, 0x07, 0xfc, 0xcd, 0x3c, 0x71, 0x0d, 0x1c, 0xcc, 0xd7, 0xe8, 0xaa, 0x98, 0xce, 0x8a, 0x01, 0x10, 0xd8, 0xfa, + 0x8d, 0x35, 0x27, 0x5e, 0x5b, 0x3c, 0x57, 0x72, 0x41, 0xe8, 0xeb, 0x2a, 0xcc, 0xc6, 0x55, 0xb1, 0xa9, 0x44, 0xb1, + 0xa9, 0x7b, 0xa4, 0x96, 0xcd, 0xa7, 0xb5, 0xad, 0x90, 0xfd, 0x49, 0xb4, 0x68, 0xbb, 0x0c, 0xd5, 0x64, 0x94, 0xa5, + 0xeb, 0x29, 0x90, 0xea, 0x05, 0x70, 0x16, 0x99, 0x57, 0xbe, 0x38, 0x7b, 0xc0, 0x16, 0x8d, 0xa7, 0xc0, 0x88, 0x4a, + 0x7f, 0xe4, 0x8d, 0xd1, 0xe9, 0x89, 0x7e, 0x3f, 0x9f, 0x52, 0xc8, 0xd7, 0x4f, 0x80, 0xc9, 0x55, 0xcb, 0x05, 0xe8, + 0xcb, 0x50, 0x07, 0x95, 0x28, 0xb5, 0x62, 0x18, 0xb1, 0xf0, 0x93, 0x40, 0xf6, 0x66, 0x0a, 0x6a, 0x56, 0x51, 0x12, + 0x2a, 0x51, 0x29, 0xd9, 0x9a, 0xa0, 0x96, 0xde, 0x17, 0x45, 0xbd, 0xaf, 0xc0, 0x51, 0x32, 0xd2, 0x66, 0x39, 0x65, + 0xc6, 0x45, 0x99, 0x8b, 0x7e, 0xb0, 0x7f, 0x57, 0x9e, 0xdf, 0xc8, 0x7c, 0x96, 0xfb, 0x8e, 0xce, 0x69, 0x3b, 0x2e, + 0x50, 0xe6, 0x96, 0xd3, 0x56, 0x4b, 0x1e, 0x93, 0xf7, 0x2c, 0xd8, 0xf6, 0x5f, 0x24, 0xc8, 0xab, 0x08, 0xf3, 0x09, + 0x55, 0x36, 0xff, 0x80, 0x30, 0x5b, 0x1c, 0xd8, 0x63, 0x17, 0x26, 0x22, 0xbd, 0x05, 0x4b, 0x62, 0x98, 0x95, 0x22, + 0x8c, 0x77, 0xe0, 0xfd, 0xb3, 0xa9, 0xc4, 0xe8, 0x0c, 0x9d, 0xdc, 0xcf, 0x1e, 0xd2, 0x3a, 0x39, 0x7b, 0xf3, 0xea, + 0xec, 0xbb, 0xde, 0xa0, 0x18, 0xa5, 0xf1, 0xa0, 0xf7, 0xdd, 0xd9, 0x6a, 0x03, 0x10, 0x99, 0xe2, 0x2c, 0x26, 0x53, + 0x9a, 0x88, 0xcf, 0xc8, 0x30, 0x78, 0x56, 0x27, 0xe2, 0x8c, 0x26, 0xa6, 0xfb, 0x1a, 0xa5, 0xc9, 0xb7, 0xa3, 0x30, + 0x87, 0x97, 0x4b, 0xb1, 0xa9, 0x44, 0x0c, 0x76, 0x4a, 0x35, 0xcf, 0xf2, 0xf6, 0x59, 0x9c, 0x8f, 0x3a, 0x64, 0x95, + 0x0e, 0xd0, 0xed, 0x89, 0xb4, 0xab, 0xd2, 0x15, 0x10, 0x7a, 0x00, 0x9c, 0x74, 0xe5, 0xcf, 0xc3, 0x41, 0x24, 0x10, + 0x6a, 0xc1, 0x9c, 0x4c, 0x23, 0xba, 0x21, 0xbd, 0xc4, 0x3e, 0x03, 0xb3, 0x90, 0xd2, 0x3c, 0xb8, 0xb9, 0x5a, 0xb4, + 0xdc, 0x15, 0x2b, 0x47, 0x61, 0xb5, 0x16, 0x51, 0x8d, 0x54, 0xc7, 0xe0, 0xbc, 0x03, 0x11, 0x00, 0x8a, 0x11, 0x3c, + 0xe3, 0x51, 0xbf, 0x1f, 0xa9, 0xa0, 0x9c, 0x84, 0x7e, 0x51, 0xe8, 0x97, 0xc6, 0xa0, 0x8c, 0xf9, 0xbb, 0x50, 0x13, + 0x03, 0xd4, 0x5b, 0x1e, 0x2a, 0x8e, 0x00, 0x5c, 0xce, 0x11, 0x33, 0xce, 0x7b, 0xdc, 0x45, 0xe3, 0x54, 0xbc, 0x13, + 0xea, 0x3a, 0x58, 0x2a, 0xd4, 0x79, 0x53, 0x1f, 0xe9, 0x39, 0x69, 0x12, 0x34, 0x88, 0x1b, 0x78, 0xbc, 0x1a, 0x02, + 0xaa, 0x95, 0x90, 0x7a, 0x0b, 0x9d, 0x52, 0xd5, 0x21, 0xb0, 0x06, 0xb8, 0x44, 0x61, 0x5b, 0x61, 0x72, 0x44, 0x9b, + 0xb2, 0x14, 0xf9, 0x11, 0x1b, 0xb4, 0x4b, 0x46, 0xa6, 0x0e, 0xae, 0xff, 0xc3, 0xdb, 0xb7, 0x70, 0xb7, 0x6d, 0x63, + 0xeb, 0xfe, 0x15, 0x8b, 0x37, 0x55, 0x89, 0x08, 0x92, 0x25, 0x37, 0xe9, 0xb4, 0x94, 0x21, 0x1d, 0x37, 0x8f, 0x36, + 0x9d, 0xe6, 0xd1, 0x38, 0xed, 0x74, 0x46, 0x57, 0xc7, 0xa5, 0x49, 0xd8, 0x62, 0x43, 0x03, 0x2a, 0x49, 0xf9, 0x51, + 0x89, 0xff, 0xfd, 0xae, 0xbd, 0xf1, 0x24, 0x45, 0x3b, 0x99, 0xb9, 0xe7, 0xde, 0x95, 0xb5, 0x62, 0x11, 0x04, 0xf1, + 0xc6, 0xc6, 0xc6, 0x7e, 0x7c, 0xbb, 0x19, 0xcb, 0x49, 0x85, 0xfe, 0x75, 0x75, 0x01, 0x9c, 0x17, 0xc6, 0xb7, 0x6e, + 0x66, 0xcb, 0x75, 0xb4, 0xeb, 0xd2, 0xc5, 0x2c, 0x29, 0x78, 0xb9, 0x96, 0xa2, 0xcc, 0xae, 0xf9, 0x4f, 0xf6, 0x65, + 0x33, 0x80, 0x14, 0xda, 0x91, 0xbe, 0x6e, 0x77, 0x47, 0x8b, 0x71, 0x6c, 0x39, 0xbe, 0xa5, 0xd2, 0x9d, 0x1e, 0x55, + 0x2f, 0x6e, 0xb6, 0xce, 0xb5, 0xca, 0xd2, 0x94, 0x8b, 0x57, 0x22, 0xcd, 0x12, 0x2f, 0x39, 0xd6, 0x01, 0xaa, 0x5d, + 0xe4, 0x2b, 0x17, 0x1b, 0xf9, 0x79, 0x56, 0x62, 0xc0, 0xe0, 0x46, 0xa3, 0x5a, 0xa1, 0xa6, 0x4c, 0xe0, 0x0b, 0xf9, + 0x1e, 0x23, 0x6e, 0xb3, 0x32, 0x01, 0x86, 0x1f, 0x13, 0xf5, 0x25, 0x3d, 0x85, 0x28, 0x0f, 0x2a, 0x1e, 0xf7, 0x73, + 0x8e, 0x88, 0xd7, 0x56, 0x65, 0x0e, 0x4c, 0xb6, 0x56, 0x41, 0x22, 0xd8, 0x5d, 0xb6, 0xd0, 0x8b, 0x68, 0xa9, 0xee, + 0x42, 0xbd, 0x78, 0xb7, 0xeb, 0x25, 0x8a, 0x0e, 0x38, 0xf9, 0x69, 0xf0, 0x32, 0xce, 0x72, 0x9e, 0x1e, 0x54, 0xf2, + 0x40, 0x6d, 0xa8, 0x03, 0xe5, 0xcc, 0x01, 0x3b, 0xef, 0xcb, 0xea, 0x40, 0xaf, 0xe9, 0x03, 0xdd, 0xce, 0x03, 0xb8, + 0x60, 0xe0, 0xce, 0xbd, 0xcc, 0xae, 0xb9, 0x38, 0x00, 0x65, 0xa0, 0x35, 0x1e, 0xa8, 0x45, 0x35, 0x52, 0x13, 0xa3, + 0x03, 0x57, 0x27, 0xfa, 0x60, 0x0e, 0xe8, 0xf7, 0x10, 0x2b, 0xbc, 0xf5, 0x76, 0xad, 0x0f, 0xda, 0x80, 0xfe, 0xb4, + 0x32, 0x7d, 0xd0, 0xd1, 0xe2, 0x55, 0x48, 0xe0, 0xc6, 0x90, 0x6a, 0xa4, 0x56, 0x23, 0xab, 0x40, 0xf1, 0x86, 0xb7, + 0x78, 0xf7, 0xae, 0x25, 0x5b, 0xef, 0x25, 0x02, 0x7b, 0x65, 0xa2, 0x8a, 0x33, 0x71, 0xe2, 0xa5, 0xf2, 0x5a, 0x3b, + 0xc9, 0x08, 0xe3, 0x5b, 0x56, 0x52, 0x7f, 0x87, 0x98, 0x5b, 0xa4, 0x39, 0x0c, 0x5e, 0x84, 0x15, 0x99, 0xf3, 0x7e, + 0x5f, 0xce, 0x65, 0x54, 0xce, 0xc5, 0x61, 0x19, 0x29, 0x84, 0xb6, 0xfb, 0x44, 0x40, 0x0f, 0x4a, 0x80, 0x7c, 0x01, + 0x50, 0xf5, 0x90, 0xf0, 0xe7, 0x21, 0xa9, 0x4f, 0xa7, 0xd0, 0xa7, 0xd0, 0xd6, 0x2b, 0x5e, 0x41, 0x55, 0xdd, 0x18, + 0xd9, 0x46, 0x05, 0x2d, 0x1e, 0xcb, 0xb3, 0xda, 0x30, 0x36, 0xa7, 0xd6, 0xbb, 0xde, 0x6c, 0x30, 0x65, 0x73, 0xa1, + 0x56, 0x61, 0x48, 0xa2, 0x9b, 0xd2, 0x0b, 0x1f, 0x62, 0xb1, 0xb2, 0x5a, 0x9b, 0xdf, 0xc4, 0xfe, 0xc8, 0x44, 0x8a, + 0xfb, 0xd9, 0x12, 0xe7, 0x2e, 0x1e, 0xcf, 0xab, 0xbe, 0xd6, 0xd2, 0x22, 0xd3, 0xe6, 0x3b, 0x7d, 0x19, 0xd2, 0x54, + 0xd4, 0x90, 0x46, 0x9d, 0x19, 0x74, 0xdf, 0x2e, 0xaf, 0xa8, 0x46, 0x98, 0x00, 0xaf, 0x74, 0x06, 0xdd, 0x68, 0x3c, + 0x10, 0x45, 0x35, 0x2a, 0x36, 0x42, 0x20, 0xda, 0x30, 0xe4, 0x98, 0x5b, 0x42, 0x92, 0xfd, 0xc5, 0xbf, 0x53, 0xc1, + 0x15, 0x8a, 0xf8, 0xc6, 0xc0, 0x79, 0x57, 0xd6, 0xb3, 0xbb, 0x8e, 0xfc, 0x9c, 0x58, 0x58, 0xed, 0x3f, 0x34, 0x8f, + 0x5a, 0xe3, 0x2c, 0xa0, 0xad, 0x69, 0x75, 0xc3, 0xe1, 0x1e, 0xd5, 0xb1, 0x28, 0x0d, 0x20, 0xb1, 0x47, 0x96, 0x8b, + 0xd6, 0x31, 0x83, 0x06, 0xf4, 0xb7, 0xd9, 0xd5, 0xe6, 0x0a, 0x51, 0xdb, 0x4a, 0x64, 0x9d, 0xa4, 0xf2, 0x2f, 0x69, + 0x8f, 0xba, 0xb6, 0xa7, 0xf2, 0xbf, 0x6d, 0x53, 0xe5, 0xd0, 0x02, 0xc9, 0x63, 0x37, 0xe7, 0x81, 0xea, 0x48, 0x10, + 0x05, 0x6a, 0xeb, 0x05, 0x53, 0xef, 0x94, 0x29, 0x3a, 0x90, 0x9f, 0x0b, 0x73, 0x86, 0x7d, 0xc6, 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, 0xe8, 0x58, 0x5a, 0xe8, 0x60, 0x0a, 0x9d, 0x44, 0xc2, 0x12, 0xd0, 0x30, 0x21, 0x3a, + 0xa9, 0xc0, 0x5b, 0x03, 0x38, 0xf3, 0x71, 0x51, 0x6e, 0x0a, 0x6d, 0x30, 0xf7, 0x43, 0x7c, 0xcd, 0x5f, 0x3d, 0x77, + 0x46, 0xf5, 0x2d, 0x6b, 0x7d, 0x4f, 0x0b, 0xf2, 0x43, 0xc8, 0x29, 0x3a, 0x30, 0xb1, 0xd9, 0x16, 0x8d, 0x31, 0xca, + 0x5a, 0x87, 0xba, 0x78, 0xab, 0xe3, 0xaf, 0x68, 0x13, 0xbc, 0x07, 0x3c, 0x45, 0xb4, 0xe1, 0xa1, 0x30, 0x56, 0xd5, + 0xf8, 0x54, 0xb2, 0x96, 0x1e, 0xac, 0xe0, 0xe9, 0x26, 0xe1, 0x21, 0xe8, 0x91, 0x08, 0x9b, 0x85, 0xc5, 0x22, 0x5e, + 0xc2, 0x71, 0x52, 0x10, 0x50, 0x3b, 0xe8, 0x2b, 0xf8, 0x62, 0x89, 0xee, 0xaf, 0x12, 0x3d, 0xc0, 0xd0, 0x82, 0xb8, + 0x19, 0xfa, 0x74, 0x74, 0x15, 0xaf, 0x1b, 0x2a, 0x12, 0xbe, 0x28, 0xc0, 0x76, 0x48, 0xa9, 0xa7, 0x40, 0x0b, 0x95, + 0x28, 0xfd, 0x30, 0xf0, 0x1d, 0x1a, 0xf8, 0x5a, 0xeb, 0x00, 0x0d, 0xfd, 0x8c, 0x69, 0x6a, 0x9d, 0xa1, 0xf2, 0xb9, + 0x77, 0xcf, 0x8c, 0x56, 0x73, 0x0b, 0xc6, 0xa0, 0x6f, 0xa3, 0x29, 0x8a, 0x73, 0xf2, 0x79, 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, 0x03, 0x58, 0xbd, 0x34, 0x74, 0x54, 0xce, 0xbb, 0x4b, 0x9b, 0x42, 0xc4, 0x22, 0x04, 0x9b, 0x66, 0xba, + 0x62, 0x27, 0xa1, 0xd2, 0xe6, 0x40, 0x7c, 0x23, 0x34, 0xee, 0x9f, 0x86, 0xb1, 0xd5, 0x14, 0x5b, 0xbb, 0xb7, 0xdd, + 0xee, 0xb7, 0xd2, 0x4b, 0xa7, 0x39, 0xe9, 0x31, 0xf6, 0x5b, 0x19, 0x16, 0x23, 0xdb, 0x11, 0x02, 0x4b, 0xce, 0xfb, + 0xd4, 0x7f, 0x45, 0xcb, 0x45, 0x02, 0xa6, 0x23, 0x3a, 0x42, 0x2e, 0x50, 0x76, 0x8c, 0xe2, 0x0e, 0x0c, 0xae, 0xe8, + 0xf7, 0xc1, 0x2a, 0xc3, 0x5c, 0x48, 0x56, 0x24, 0x65, 0xf0, 0x3c, 0xf5, 0x30, 0xe0, 0x37, 0x4c, 0x99, 0xbb, 0x28, + 0xeb, 0xd3, 0x15, 0x99, 0xa6, 0xc8, 0x40, 0x6c, 0xc2, 0x6d, 0x96, 0x46, 0x89, 0x12, 0x91, 0xad, 0xd0, 0x3f, 0xd2, + 0x50, 0x2c, 0x1d, 0xae, 0x17, 0xa9, 0x12, 0xa1, 0x62, 0x91, 0xe2, 0x49, 0x9d, 0xd6, 0xe9, 0x08, 0xe3, 0x4d, 0x82, + 0x52, 0xae, 0x86, 0x81, 0x2a, 0xa9, 0x5e, 0x0a, 0xdb, 0x62, 0xb7, 0xd3, 0x17, 0x2b, 0xb1, 0x88, 0x97, 0xf8, 0x52, + 0xe0, 0x28, 0xfe, 0x9d, 0x7b, 0xb1, 0xa6, 0xd4, 0xf6, 0xa0, 0x76, 0x44, 0x09, 0xfd, 0x3b, 0x87, 0x8b, 0xc4, 0x77, + 0x52, 0xc7, 0xfd, 0x43, 0x8b, 0x90, 0x33, 0x75, 0x90, 0x1a, 0x6e, 0x68, 0x4f, 0xf8, 0x6f, 0xb8, 0x3e, 0xe3, 0x8c, + 0xde, 0x54, 0x33, 0x6a, 0xfc, 0x5e, 0x0f, 0xcf, 0x18, 0xf5, 0xd9, 0xc0, 0x61, 0x85, 0x28, 0xb4, 0x61, 0xb3, 0x52, + 0x89, 0x16, 0x86, 0x52, 0xfd, 0x25, 0x54, 0xcc, 0xb8, 0x33, 0xa3, 0x2c, 0x19, 0x9f, 0x96, 0xc7, 0x62, 0x3a, 0x18, + 0x94, 0xa4, 0x32, 0x16, 0x7a, 0x70, 0x3d, 0xf0, 0xfc, 0x7b, 0xe0, 0x16, 0xe2, 0xc1, 0x21, 0x8b, 0x21, 0x37, 0xe0, + 0xf8, 0x2d, 0x4e, 0xae, 0x1a, 0x95, 0x2a, 0x78, 0x35, 0x51, 0x2d, 0xf8, 0x7b, 0x19, 0x06, 0xe8, 0x93, 0x14, 0x80, + 0xc9, 0x60, 0xca, 0x6f, 0x41, 0xa2, 0x74, 0xa6, 0x6e, 0x48, 0xbf, 0x88, 0x82, 0x5f, 0xf0, 0x82, 0x8b, 0xc4, 0x15, + 0x60, 0x79, 0x07, 0xdb, 0xeb, 0xa8, 0xa2, 0x0a, 0x88, 0xd7, 0xf4, 0x38, 0xe2, 0xc6, 0xfb, 0xcf, 0xf4, 0xd8, 0x02, + 0xb5, 0x5a, 0xc7, 0x06, 0x9f, 0x39, 0x06, 0x17, 0x74, 0x2d, 0xb1, 0x35, 0x54, 0xc3, 0x8a, 0xc0, 0xc0, 0x05, 0x1c, + 0x84, 0x25, 0x8a, 0x63, 0x2b, 0x79, 0x45, 0x1a, 0x52, 0xda, 0x07, 0x86, 0xa3, 0x4d, 0x72, 0x7c, 0x9b, 0x65, 0x37, + 0x81, 0x8b, 0x65, 0xe7, 0xa4, 0x99, 0x58, 0x36, 0x78, 0x9f, 0x37, 0xe7, 0xd7, 0xfd, 0x43, 0x42, 0x55, 0xb0, 0x1b, + 0xde, 0x0e, 0x76, 0xe3, 0x84, 0x5f, 0x0b, 0xb1, 0xd4, 0xf1, 0x59, 0xcc, 0x25, 0xcb, 0x6f, 0xad, 0x77, 0x4b, 0x92, + 0x5a, 0x01, 0xed, 0xb3, 0x2c, 0xa8, 0x89, 0x00, 0x74, 0x3f, 0xfc, 0x05, 0x42, 0x67, 0xf8, 0xdb, 0x63, 0x70, 0x45, + 0x0a, 0xef, 0x1d, 0x02, 0x61, 0x4d, 0x37, 0xf7, 0x6a, 0x03, 0xbe, 0x18, 0xf7, 0x67, 0x4c, 0x3d, 0xfd, 0x36, 0x93, + 0xfb, 0xba, 0x6e, 0x8f, 0x2c, 0xc3, 0x47, 0xb8, 0x52, 0x00, 0x2c, 0x13, 0xfe, 0x62, 0x6c, 0x49, 0xf5, 0x09, 0xc0, + 0xa9, 0xe9, 0x88, 0x3e, 0x41, 0x60, 0xe0, 0x94, 0x68, 0x31, 0xba, 0x56, 0x8e, 0x68, 0x06, 0x69, 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, 0x36, 0xb5, 0x4d, 0x1f, 0x90, + 0xfe, 0xe2, 0x9a, 0xf5, 0x53, 0x56, 0xb5, 0x6f, 0x0f, 0x15, 0x2f, 0xa7, 0xcd, 0xe0, 0x87, 0x89, 0x2a, 0xc6, 0xff, + 0xa2, 0xf2, 0xa5, 0x56, 0x00, 0xc3, 0xdc, 0x55, 0x4f, 0xbf, 0xdf, 0xcc, 0x96, 0x03, 0xa1, 0xf2, 0x3b, 0x83, 0xa4, + 0x4f, 0xc7, 0xf3, 0x03, 0x9b, 0x44, 0x6d, 0xa1, 0xe7, 0x8f, 0x4b, 0xdd, 0x84, 0xca, 0x6b, 0x53, 0x23, 0x5a, 0x21, + 0x43, 0x65, 0xeb, 0x80, 0xf5, 0xfd, 0x43, 0xb8, 0xbf, 0xa8, 0x69, 0xa8, 0x75, 0xcf, 0x5d, 0x8b, 0x82, 0x13, 0x7f, + 0x80, 0xb1, 0xb8, 0x90, 0xd4, 0x3a, 0x08, 0x93, 0x7e, 0xb4, 0x38, 0xc9, 0x8d, 0xba, 0x3a, 0x39, 0x53, 0xcc, 0x13, + 0xb8, 0xa8, 0x96, 0x6d, 0x7f, 0x45, 0xa5, 0x2e, 0xe5, 0xf6, 0x8a, 0xd2, 0xf4, 0x90, 0xb6, 0x57, 0x71, 0xde, 0x16, + 0x5c, 0xf0, 0xcf, 0x14, 0x5c, 0x58, 0x07, 0xeb, 0x8e, 0x3b, 0x65, 0x4f, 0x78, 0xa2, 0x4c, 0x6b, 0x83, 0xbb, 0x69, + 0x30, 0x26, 0xc6, 0x7e, 0x77, 0xc5, 0x93, 0x8f, 0xc8, 0x82, 0x7f, 0x97, 0x09, 0xf0, 0x4c, 0x76, 0xaf, 0x54, 0xfe, + 0x1f, 0xfc, 0xab, 0xad, 0x7d, 0x67, 0xcd, 0x3f, 0x3d, 0xeb, 0xe1, 0xce, 0x61, 0xf2, 0x03, 0x74, 0x06, 0x74, 0x7b, + 0x25, 0x53, 0x0e, 0xc8, 0x00, 0xd6, 0x22, 0x19, 0x0d, 0xf8, 0xd0, 0xca, 0xb2, 0xed, 0x3b, 0xad, 0x2e, 0x08, 0xf7, + 0x12, 0xb8, 0xe9, 0xfd, 0xb5, 0x99, 0x99, 0xd3, 0xb5, 0x12, 0x4d, 0x97, 0xc6, 0xd6, 0xb2, 0x54, 0x01, 0xbb, 0xdf, + 0x7b, 0x92, 0x4d, 0xf3, 0xe3, 0xd5, 0x34, 0xb7, 0xd4, 0x6d, 0xeb, 0x96, 0x0d, 0x00, 0x21, 0x76, 0xad, 0xad, 0x1c, + 0x40, 0x72, 0x7b, 0x10, 0xc2, 0xd7, 0x8a, 0xd0, 0x53, 0x25, 0x42, 0x9f, 0xa6, 0xcd, 0x3e, 0xd8, 0x55, 0xb5, 0x69, + 0xc4, 0x39, 0x1a, 0xa4, 0x9a, 0x91, 0x7f, 0x7b, 0xcd, 0x8b, 0x8b, 0x5c, 0xde, 0x00, 0x06, 0x32, 0xa9, 0x8d, 0xc2, + 0xf2, 0x0a, 0xdc, 0xf9, 0xd1, 0x71, 0x9c, 0x89, 0x51, 0x8e, 0xc1, 0x5a, 0x11, 0x1e, 0x59, 0x27, 0xce, 0x01, 0x04, + 0xd9, 0x9f, 0x34, 0x1d, 0xcf, 0xb5, 0xc0, 0x98, 0xbe, 0xc0, 0x5d, 0xe5, 0x6c, 0xb6, 0xcd, 0xed, 0xa2, 0x6f, 0xce, + 0xb0, 0xee, 0x48, 0x69, 0x6d, 0x2c, 0xba, 0xee, 0x60, 0xad, 0x19, 0xb4, 0x45, 0x28, 0xf9, 0x90, 0x3b, 0x69, 0xff, + 0x0a, 0x68, 0x70, 0x96, 0xa5, 0xb7, 0xd6, 0x2a, 0x7f, 0xab, 0x85, 0x38, 0x51, 0x4c, 0x9d, 0xf8, 0x26, 0x4a, 0xf4, + 0xf9, 0x99, 0x18, 0x37, 0x10, 0x48, 0xfd, 0x01, 0x83, 0x6a, 0x14, 0x61, 0x02, 0xd7, 0x81, 0x28, 0xb6, 0x27, 0x6a, + 0x63, 0x39, 0x82, 0x4e, 0x08, 0xf1, 0x0e, 0xca, 0x30, 0x56, 0x17, 0x07, 0xda, 0x60, 0xe9, 0xeb, 0xd6, 0x3a, 0x37, + 0x84, 0xc2, 0x38, 0x81, 0x29, 0x06, 0x49, 0x9d, 0x75, 0x96, 0x09, 0xaa, 0xec, 0x98, 0x74, 0xde, 0x07, 0xe8, 0xfe, + 0x5a, 0x34, 0xc5, 0xd7, 0x9d, 0x3b, 0xe8, 0x3e, 0xae, 0x5f, 0x6b, 0x91, 0x1b, 0xfc, 0x79, 0x4b, 0x84, 0x45, 0xe0, + 0xac, 0x35, 0xf9, 0xaa, 0x11, 0x0e, 0x4c, 0x49, 0xa6, 0x61, 0x2f, 0x51, 0x36, 0xdd, 0xbb, 0x5d, 0xaf, 0x77, 0xaf, + 0x88, 0xab, 0xc7, 0x58, 0xe5, 0xdd, 0xcc, 0xed, 0x9d, 0x6a, 0x23, 0xf6, 0x6f, 0xda, 0x7e, 0x8a, 0x1d, 0xb5, 0xd6, + 0x6e, 0x37, 0x9c, 0x50, 0x43, 0xbe, 0x15, 0x55, 0x5a, 0x9d, 0x6e, 0x0c, 0xda, 0x21, 0x9e, 0xb5, 0xc8, 0xe0, 0x46, + 0xf9, 0xdc, 0x09, 0x9d, 0x54, 0x9c, 0x55, 0xa7, 0x2e, 0xd8, 0x5e, 0xf1, 0x6a, 0x25, 0xd3, 0x48, 0x50, 0xb4, 0x39, + 0x8f, 0x4a, 0x9a, 0xc8, 0x8d, 0xa8, 0x22, 0x59, 0xa3, 0x5e, 0xd4, 0x6a, 0x0c, 0x10, 0x90, 0xe9, 0xac, 0xe9, 0x41, + 0x15, 0xcc, 0x87, 0x32, 0x92, 0xd3, 0xf7, 0x60, 0x69, 0x8f, 0x1c, 0x6b, 0x7d, 0x5f, 0x9d, 0x2d, 0xbe, 0xd5, 0x13, + 0x82, 0x29, 0xcc, 0x1e, 0x08, 0x03, 0xd7, 0x34, 0x86, 0x9c, 0x76, 0x89, 0xcb, 0x9a, 0x6e, 0x09, 0xf7, 0x70, 0xbb, + 0x92, 0xcd, 0xdc, 0x3c, 0x69, 0x6e, 0xae, 0x60, 0xb3, 0x62, 0x31, 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, 0x09, 0x44, 0xf1, 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, + 0x2e, 0x26, 0x4b, 0x3d, 0x03, 0x03, 0xb9, 0x38, 0x5a, 0xea, 0x59, 0x18, 0xc8, 0xc5, 0x57, 0xcb, 0xda, 0xad, 0x03, + 0x4d, 0x40, 0x3c, 0x17, 0x8e, 0x4e, 0x4a, 0xab, 0xb2, 0x05, 0x74, 0xfb, 0x10, 0x41, 0xff, 0xbb, 0x3d, 0x04, 0x9d, + 0x5c, 0x68, 0x4f, 0x6e, 0x40, 0xdb, 0x71, 0x08, 0xec, 0x15, 0x93, 0x0a, 0x13, 0x80, 0xe8, 0x98, 0x8d, 0xc1, 0x10, + 0x5b, 0x7d, 0x70, 0xcc, 0xc6, 0x53, 0x9f, 0x04, 0x01, 0xa3, 0xfb, 0x83, 0x81, 0x04, 0xbf, 0xc5, 0xab, 0xf4, 0x6c, + 0x2b, 0xd0, 0x4d, 0xdf, 0xdd, 0x0d, 0xbd, 0x8b, 0x2b, 0x38, 0x55, 0xbb, 0x7b, 0x12, 0xba, 0xc9, 0xb4, 0x03, 0xf4, + 0x1a, 0xe2, 0x86, 0xfc, 0xca, 0x68, 0x34, 0xb2, 0x29, 0x21, 0x21, 0x86, 0x73, 0x68, 0xe6, 0xb4, 0x5c, 0xbe, 0xba, + 0xf5, 0x6c, 0x41, 0x86, 0x99, 0xde, 0x32, 0x59, 0x3f, 0x40, 0x59, 0xf5, 0x18, 0xda, 0xa1, 0xf7, 0xc8, 0xf1, 0xc3, + 0x83, 0x6f, 0x32, 0x7e, 0xe2, 0x70, 0xed, 0xe1, 0x5c, 0xf8, 0x2e, 0x6b, 0x46, 0xe6, 0xd0, 0x79, 0xf6, 0x71, 0xbc, + 0x87, 0x71, 0xf2, 0x69, 0x16, 0xca, 0x1b, 0xaf, 0xe9, 0x7f, 0x54, 0x7a, 0xb3, 0xc3, 0x21, 0xa7, 0x6b, 0x58, 0x71, + 0xf3, 0x2a, 0x34, 0xfc, 0x2c, 0xf2, 0xc6, 0x11, 0xaf, 0x49, 0x54, 0x75, 0x9f, 0xf7, 0x36, 0x4c, 0x69, 0xc7, 0x38, + 0x00, 0x38, 0x51, 0xab, 0x86, 0x7d, 0x69, 0x5c, 0xab, 0x83, 0x18, 0x86, 0x12, 0xb6, 0x4a, 0x1c, 0x09, 0xe5, 0x6f, + 0x00, 0xc2, 0x62, 0x28, 0x8e, 0xb7, 0x86, 0xf5, 0x01, 0xf6, 0x43, 0x17, 0x68, 0x9a, 0x53, 0xaa, 0x19, 0x00, 0x24, + 0x01, 0x7f, 0xf4, 0x74, 0xd3, 0x50, 0xd9, 0xe6, 0x79, 0x68, 0x59, 0x5d, 0xc1, 0x03, 0x3d, 0x75, 0x25, 0x03, 0xe3, + 0xaa, 0x8e, 0xbd, 0xed, 0xfd, 0xed, 0xd1, 0x2a, 0xf2, 0xbd, 0x4d, 0x6a, 0x9b, 0x55, 0xa1, 0xb1, 0x8f, 0x27, 0xf4, + 0x74, 0x02, 0xb4, 0x5e, 0x5b, 0x2a, 0xda, 0xef, 0xa3, 0x18, 0x35, 0x2e, 0x14, 0x58, 0x85, 0x89, 0x04, 0x87, 0x08, + 0x23, 0x84, 0x7e, 0x5f, 0x86, 0x5b, 0x5f, 0x90, 0x41, 0x34, 0x5c, 0x8b, 0x8e, 0x3f, 0xe4, 0x78, 0xd1, 0xb6, 0x54, + 0xd5, 0x9c, 0x34, 0x6d, 0x09, 0xbc, 0x09, 0x07, 0xd8, 0xce, 0x3f, 0x6d, 0x88, 0x5c, 0x85, 0x8b, 0x12, 0xbe, 0x27, + 0xae, 0x05, 0xd1, 0x4d, 0x6d, 0xea, 0x6d, 0xd8, 0x21, 0x3a, 0x9a, 0xe2, 0xd1, 0x21, 0xf7, 0xdc, 0x3d, 0xb7, 0x45, + 0x7c, 0xf3, 0x09, 0x72, 0xd7, 0x74, 0xf6, 0x52, 0x84, 0x41, 0xdd, 0xb2, 0x81, 0x62, 0x1d, 0x3b, 0x41, 0x01, 0x46, + 0x6d, 0xf9, 0x0b, 0xe8, 0xd8, 0x60, 0x50, 0x11, 0x7c, 0x52, 0xd8, 0x36, 0x0d, 0xf2, 0x47, 0xbc, 0x1b, 0x3a, 0xbc, + 0xb6, 0xe4, 0x81, 0x78, 0x85, 0x7d, 0xa2, 0x84, 0xfb, 0x17, 0x14, 0x74, 0x47, 0x79, 0xb9, 0x2a, 0x5c, 0x95, 0x06, + 0xa0, 0xca, 0x9e, 0xe7, 0x5a, 0x53, 0xd2, 0x02, 0x56, 0x4a, 0xea, 0xce, 0x6f, 0x22, 0xe2, 0x96, 0x4c, 0xc5, 0x6c, + 0xd5, 0x8d, 0x2a, 0x8f, 0x25, 0x8a, 0x74, 0xec, 0xd9, 0xce, 0xc1, 0x1a, 0x00, 0x4f, 0x61, 0x7b, 0x71, 0x86, 0x05, + 0x65, 0x5c, 0xb6, 0xcc, 0x25, 0x50, 0xd4, 0x0f, 0xe3, 0xbc, 0xec, 0xf9, 0x72, 0x77, 0xb4, 0xbd, 0x87, 0xde, 0x88, + 0x8d, 0xf1, 0xfa, 0x3c, 0x6a, 0xfa, 0xd9, 0x33, 0x5c, 0x59, 0x0a, 0xf2, 0x40, 0x53, 0x3d, 0xc2, 0xe8, 0x10, 0x98, + 0xa6, 0x7c, 0xc6, 0xc6, 0xd3, 0xe1, 0xd0, 0x90, 0x41, 0xaf, 0x99, 0x18, 0xff, 0xeb, 0x33, 0x68, 0x9d, 0x99, 0xb8, + 0xc6, 0xa7, 0xed, 0x2b, 0x68, 0x75, 0x8b, 0x32, 0xb9, 0x33, 0x30, 0x7c, 0xa0, 0x25, 0x53, 0x30, 0x55, 0x78, 0x43, + 0xa4, 0x92, 0xfd, 0xb5, 0xb2, 0x0e, 0xfb, 0x76, 0xa1, 0xd0, 0x42, 0x13, 0xbf, 0xca, 0x10, 0x3f, 0x75, 0x9d, 0xf9, + 0xb7, 0x69, 0x9f, 0x1a, 0xc4, 0xc2, 0x92, 0x18, 0x85, 0xf8, 0xc5, 0xa9, 0xb2, 0x9d, 0x10, 0x2a, 0x20, 0x1e, 0xba, + 0xd6, 0x8d, 0x23, 0xa9, 0x62, 0x4f, 0x0a, 0x8d, 0xa7, 0x86, 0xfb, 0x5e, 0xe8, 0x98, 0x75, 0x98, 0xc5, 0x6d, 0xd6, + 0x48, 0x6a, 0x8c, 0x53, 0x61, 0x82, 0x53, 0xca, 0x75, 0x24, 0x30, 0x3a, 0x9e, 0x2d, 0x0c, 0xa2, 0x4a, 0x62, 0x92, + 0xb1, 0xb5, 0x10, 0x26, 0x76, 0x9d, 0x2b, 0x4c, 0x53, 0x17, 0xa9, 0xdf, 0x0c, 0x4c, 0x16, 0x34, 0xe4, 0xf7, 0x68, + 0xb4, 0xa6, 0x6a, 0x0a, 0x30, 0x8c, 0xa3, 0x54, 0xe3, 0xdf, 0x22, 0xd4, 0x66, 0x18, 0x00, 0xd8, 0xe6, 0x9d, 0xcc, + 0x44, 0xf5, 0x4a, 0x20, 0x04, 0x9a, 0xb3, 0x9f, 0x2a, 0xaa, 0xbd, 0x59, 0x30, 0x8a, 0x76, 0x7b, 0xe5, 0xf3, 0x81, + 0x13, 0xca, 0x13, 0x75, 0x81, 0x7a, 0x29, 0x8b, 0xd7, 0x32, 0xe5, 0xad, 0xb8, 0x98, 0x07, 0x92, 0x7d, 0xc8, 0x47, + 0x70, 0x5e, 0xa1, 0x53, 0xb9, 0xd9, 0x26, 0xca, 0x2c, 0x49, 0x32, 0x16, 0x18, 0x9b, 0x97, 0x60, 0x2e, 0x35, 0x33, + 0x86, 0x5f, 0x43, 0x70, 0xb1, 0xbd, 0x93, 0x70, 0x7b, 0x3f, 0x0f, 0x0c, 0xa1, 0xc9, 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, 0xba, 0x58, 0x1a, 0x31, 0x93, 0x4a, 0xf4, 0x6e, 0xdf, 0xf8, 0xac, 0xee, + 0x22, 0xea, 0xb7, 0xf6, 0x7b, 0x52, 0x0f, 0x77, 0xfe, 0x83, 0xc2, 0x1a, 0x54, 0x46, 0x5c, 0x46, 0x94, 0x67, 0x0e, + 0x74, 0xd3, 0xa4, 0x88, 0xd3, 0xb3, 0x75, 0x5c, 0x94, 0x3c, 0x85, 0x4a, 0x35, 0x75, 0x8b, 0x7a, 0x13, 0xb0, 0x37, + 0x44, 0x92, 0x64, 0x2d, 0x8d, 0xad, 0xd8, 0xa5, 0x41, 0x7a, 0xee, 0x0d, 0xb3, 0xf4, 0xb2, 0x42, 0x43, 0x5a, 0xea, + 0x9d, 0x85, 0x4a, 0xe6, 0xaf, 0xf8, 0xcf, 0xa0, 0x56, 0xa0, 0xa3, 0x4d, 0x8a, 0xf1, 0x0c, 0x18, 0xf1, 0xfd, 0x08, + 0x56, 0x0f, 0x10, 0x17, 0x4d, 0x50, 0xea, 0x3d, 0xb1, 0xe3, 0xa7, 0x26, 0x0f, 0xef, 0x42, 0xce, 0x19, 0x7c, 0xfa, + 0x30, 0x4b, 0xd4, 0x5a, 0x47, 0x62, 0xa4, 0x66, 0x00, 0x4d, 0x07, 0x65, 0xce, 0x63, 0x11, 0xcc, 0x7b, 0x26, 0x31, + 0xea, 0x71, 0xfd, 0x0b, 0x34, 0xd4, 0x7e, 0xb3, 0xb2, 0x3c, 0xab, 0xee, 0x3e, 0x87, 0x03, 0x9b, 0xda, 0x0a, 0x7a, + 0xbc, 0xae, 0xe4, 0xe5, 0xa5, 0xea, 0xb6, 0x5f, 0x88, 0x91, 0xd3, 0x35, 0xae, 0xa5, 0x8b, 0x6a, 0xc9, 0x7a, 0xdd, + 0xe9, 0x66, 0x71, 0x37, 0xcb, 0x68, 0x20, 0xac, 0xed, 0x7d, 0xa2, 0xf9, 0xb3, 0x66, 0xdb, 0x7d, 0xbc, 0x05, 0x31, + 0x0f, 0x00, 0x20, 0x3d, 0x88, 0x82, 0x55, 0x96, 0xf2, 0x80, 0xca, 0xfb, 0x38, 0xca, 0x42, 0xe9, 0xe5, 0x2c, 0xe3, + 0xa7, 0x4d, 0x63, 0xad, 0xb3, 0x42, 0x19, 0x5a, 0x1b, 0xdd, 0xe9, 0x3a, 0x43, 0x6c, 0x3f, 0x89, 0xb3, 0x05, 0xb8, + 0x3f, 0x66, 0x28, 0x34, 0x74, 0x96, 0x91, 0x26, 0x1a, 0xbe, 0xeb, 0x9e, 0x41, 0x46, 0x71, 0xb2, 0xce, 0x2b, 0xe9, + 0x56, 0x9f, 0xb5, 0x91, 0x30, 0xf7, 0x10, 0xfd, 0x2a, 0x06, 0x8f, 0x72, 0x9f, 0xd7, 0x46, 0x27, 0xd3, 0x32, 0xd2, + 0xee, 0xfc, 0xa4, 0x5e, 0x65, 0xa9, 0xd6, 0x61, 0xfb, 0x0c, 0x7b, 0x6b, 0x4c, 0x7a, 0x13, 0x52, 0xc3, 0x48, 0x7c, + 0x3a, 0xa3, 0x46, 0x08, 0x68, 0xcb, 0xf1, 0xf7, 0xf8, 0x0c, 0x43, 0x53, 0x60, 0xa9, 0xe2, 0x16, 0x76, 0xc3, 0xd7, + 0x7c, 0xb2, 0x6a, 0x01, 0x88, 0x60, 0xe5, 0xeb, 0x5d, 0xbc, 0x12, 0xea, 0x33, 0x6d, 0x06, 0x80, 0x2c, 0x28, 0xe5, + 0x8e, 0x9f, 0x52, 0xe9, 0x60, 0x89, 0xa2, 0xed, 0xe5, 0xf4, 0x8d, 0x8e, 0x8d, 0x1f, 0xd2, 0x73, 0x01, 0xdb, 0x85, + 0xfc, 0xd6, 0xbd, 0x7a, 0x89, 0x8a, 0xd4, 0xb6, 0x59, 0x0f, 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, 0x75, 0x8f, 0xa0, + 0x47, 0x3b, 0x9c, 0xb4, 0xec, 0xd7, 0x0a, 0x8e, 0x4e, 0xae, 0x86, 0xa8, 0x99, 0xf7, 0xda, 0x8e, 0x0c, 0x29, 0x97, + 0x61, 0x20, 0x98, 0x72, 0xcc, 0xd3, 0x63, 0xeb, 0x19, 0x11, 0x3d, 0x70, 0xf6, 0x99, 0x6e, 0xd5, 0x95, 0x04, 0x44, + 0xc7, 0xaf, 0x9f, 0xbc, 0xba, 0x8a, 0x2f, 0x0d, 0x8a, 0x52, 0xc3, 0x22, 0x46, 0x99, 0xf6, 0x55, 0x12, 0x06, 0xef, + 0x97, 0xf7, 0x3f, 0xa9, 0x2c, 0xb5, 0xdf, 0x83, 0xad, 0x15, 0x55, 0xfd, 0x52, 0xf2, 0xa2, 0x29, 0xc0, 0xba, 0xcf, + 0x12, 0x05, 0x72, 0xbf, 0xb7, 0x69, 0xe6, 0x9b, 0xa8, 0x71, 0xb3, 0x61, 0xbd, 0x71, 0xdd, 0x2e, 0xb5, 0x25, 0x3b, + 0xb2, 0x12, 0x39, 0xb3, 0x18, 0xcc, 0xf8, 0x51, 0x61, 0x50, 0x1a, 0xb6, 0xa8, 0x4a, 0xc5, 0xef, 0x8d, 0x08, 0x4e, + 0x1d, 0xab, 0x0a, 0x63, 0x1a, 0x30, 0xdb, 0x8a, 0x5a, 0x83, 0x3a, 0x28, 0xa5, 0xad, 0x89, 0xc2, 0xf6, 0x1b, 0x2b, + 0xa8, 0xf9, 0xfd, 0x4f, 0x63, 0xc8, 0xd7, 0x94, 0x82, 0x4a, 0x02, 0x76, 0x06, 0x8d, 0x9e, 0x2a, 0x61, 0x20, 0x05, + 0xc1, 0x13, 0xa0, 0x7c, 0x11, 0x35, 0x56, 0xfb, 0x7d, 0x75, 0x6a, 0x8c, 0xb6, 0x80, 0xd0, 0x42, 0x7a, 0x74, 0xd9, + 0xc7, 0x6d, 0xad, 0x03, 0x89, 0x07, 0x27, 0xd8, 0xce, 0xd5, 0x35, 0x1a, 0x09, 0xcd, 0x1f, 0x1a, 0x0d, 0x78, 0x4d, + 0x2b, 0x50, 0xa8, 0xe7, 0x38, 0x1a, 0x3a, 0x3b, 0xa4, 0x20, 0x62, 0x83, 0x16, 0xf6, 0xdd, 0xf3, 0xa1, 0xd9, 0xd7, + 0x8b, 0x64, 0x49, 0x6a, 0x2a, 0xdd, 0xe7, 0x6e, 0x09, 0x59, 0xab, 0x0e, 0x65, 0xe5, 0x01, 0x8e, 0x17, 0x4a, 0xe6, + 0xef, 0x30, 0xa9, 0x51, 0x1a, 0x13, 0x1a, 0x23, 0x16, 0xb0, 0x24, 0x68, 0xaf, 0x07, 0xea, 0x97, 0x41, 0xa8, 0x70, + 0xa6, 0x27, 0x12, 0x9f, 0x52, 0xae, 0x3e, 0x2d, 0x48, 0x3d, 0x2d, 0x98, 0x03, 0xbd, 0xf4, 0xad, 0xfc, 0xca, 0xc6, + 0x47, 0xfb, 0x7b, 0xd7, 0x5c, 0x58, 0xc7, 0x10, 0x0c, 0x5b, 0xf8, 0xcd, 0xa9, 0x29, 0x00, 0x1b, 0x9e, 0xe8, 0xb2, + 0x7c, 0xa3, 0x26, 0x32, 0x8f, 0x43, 0x12, 0x81, 0x64, 0xbb, 0xb9, 0xb9, 0x8d, 0x60, 0xdb, 0x5b, 0xa8, 0x0d, 0xf5, + 0x97, 0xb7, 0xdd, 0xef, 0x19, 0x5e, 0xee, 0xc9, 0xbd, 0x9b, 0x36, 0x94, 0x3f, 0xdc, 0xbf, 0x4a, 0xfe, 0xaf, 0x2a, + 0xb9, 0xdf, 0x2a, 0xb3, 0x6e, 0x8b, 0xf7, 0xbb, 0x8e, 0x5b, 0x8e, 0xd1, 0x20, 0xb0, 0xa6, 0xc0, 0x40, 0x7a, 0xd2, + 0x98, 0x26, 0x3a, 0xa4, 0x32, 0x63, 0x06, 0x8f, 0x2e, 0x40, 0x73, 0x98, 0xce, 0xf3, 0x18, 0x80, 0x03, 0xfc, 0x23, + 0x8f, 0x50, 0xff, 0x74, 0x5e, 0x04, 0x67, 0xc1, 0xa0, 0x1c, 0x04, 0xfa, 0x13, 0xd7, 0x9c, 0x60, 0x09, 0x3a, 0xb7, + 0x98, 0x41, 0xb0, 0x49, 0x6b, 0xe6, 0x10, 0x1f, 0x27, 0xd3, 0xc1, 0x20, 0x26, 0x5b, 0x00, 0xe9, 0x8b, 0x97, 0xd6, + 0x39, 0xa8, 0xd0, 0x0b, 0xb2, 0x55, 0x77, 0xd1, 0xac, 0xd8, 0xab, 0x76, 0x9a, 0xf7, 0xfb, 0xf9, 0xa2, 0x1c, 0x04, + 0x8d, 0x0a, 0x0b, 0xe3, 0xfd, 0x47, 0x9b, 0x5f, 0x1a, 0x9d, 0x34, 0xc1, 0x30, 0xb5, 0x27, 0xa8, 0x5e, 0xf1, 0x34, + 0xa3, 0x8d, 0xdb, 0xb1, 0x52, 0xbe, 0x80, 0x28, 0x1e, 0x18, 0xb2, 0x56, 0xde, 0xbd, 0x83, 0xd7, 0xe5, 0xc6, 0x9b, + 0x23, 0x0a, 0xb0, 0x9b, 0xc2, 0x38, 0xa9, 0xb9, 0xe8, 0xa2, 0x26, 0x9e, 0xc1, 0x4e, 0x57, 0x6f, 0x25, 0x5a, 0x8d, + 0xf7, 0xe2, 0x7d, 0xb3, 0xf1, 0x37, 0xf2, 0x40, 0x97, 0x79, 0x70, 0x01, 0x88, 0xb3, 0x07, 0x71, 0x75, 0x80, 0xa5, + 0x1e, 0x04, 0x03, 0x8b, 0x1c, 0xd2, 0xae, 0x56, 0x0f, 0x45, 0xa4, 0xce, 0x63, 0x30, 0x60, 0x32, 0x0d, 0xa9, 0xc9, + 0xb4, 0x57, 0x28, 0x48, 0x1b, 0x6b, 0x2d, 0xa0, 0x0d, 0x87, 0xc5, 0x9e, 0xdd, 0xb0, 0x3b, 0xdd, 0x3a, 0x14, 0x4a, + 0x18, 0xbd, 0xba, 0x6e, 0x1e, 0x6a, 0x0d, 0x4f, 0x04, 0x3d, 0xa8, 0x46, 0xfb, 0xe9, 0xa1, 0x3c, 0x69, 0x8f, 0x05, + 0xb8, 0xe8, 0xe1, 0xcb, 0x17, 0x02, 0x2f, 0xda, 0x7b, 0xc8, 0x73, 0xe6, 0x53, 0xe5, 0x83, 0xd8, 0x70, 0xcb, 0xf0, + 0xa1, 0x7d, 0x7c, 0x2b, 0x90, 0x49, 0xdd, 0xd1, 0xd4, 0xd6, 0xee, 0x68, 0x1c, 0x13, 0xe8, 0x37, 0xe5, 0x28, 0x65, + 0x62, 0x6a, 0x59, 0xb1, 0x59, 0x2f, 0x57, 0xde, 0x50, 0x29, 0x9b, 0xad, 0xda, 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, 0xfb, + 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, 0x88, 0x53, 0x01, 0xb6, 0x75, 0xad, + 0x73, 0x56, 0xcb, 0x01, 0x9b, 0x89, 0x9e, 0x7f, 0x5a, 0x35, 0x12, 0x31, 0xac, 0xb2, 0x91, 0xb2, 0x42, 0x7b, 0x50, + 0xba, 0x84, 0x8b, 0x2f, 0xc0, 0xcb, 0xf6, 0xfd, 0xca, 0xee, 0xb3, 0x15, 0xf6, 0x0f, 0xf3, 0xaa, 0x09, 0x1e, 0x79, + 0x8d, 0xb7, 0xf7, 0x30, 0xf1, 0xb9, 0x52, 0x08, 0xaf, 0x52, 0x1a, 0x4a, 0x00, 0x06, 0x49, 0x50, 0xc3, 0x95, 0xb6, + 0xcd, 0x20, 0x95, 0x31, 0xec, 0x7e, 0xf5, 0x56, 0xff, 0xa7, 0x55, 0xb8, 0xa8, 0x64, 0x31, 0x26, 0x81, 0xce, 0xa9, + 0x96, 0x9b, 0x98, 0x82, 0x67, 0xfb, 0xe4, 0x08, 0x14, 0x76, 0x02, 0xb8, 0xa1, 0x84, 0xfd, 0x82, 0xb7, 0xa1, 0x9c, + 0xbd, 0xb4, 0x92, 0x27, 0xb7, 0x2f, 0xa9, 0xa0, 0x09, 0x99, 0x0a, 0xbb, 0x7f, 0x5b, 0x1b, 0xf6, 0x79, 0x28, 0x47, + 0x52, 0xe0, 0xe2, 0xa0, 0x0b, 0x00, 0xfb, 0x83, 0x5c, 0xc6, 0xe6, 0x33, 0xe9, 0xf7, 0xd5, 0xfb, 0x67, 0x79, 0x96, + 0x7c, 0xdc, 0x7b, 0x6f, 0x78, 0x9a, 0x15, 0x03, 0x2a, 0x11, 0x53, 0xeb, 0xaa, 0x18, 0xae, 0xb4, 0x8b, 0x71, 0x83, + 0x64, 0xc4, 0xf7, 0x52, 0x87, 0x18, 0x31, 0xbe, 0xc8, 0x1e, 0x49, 0xc9, 0xe9, 0xaa, 0xee, 0xec, 0xb9, 0x16, 0xcd, + 0xa0, 0x31, 0xdc, 0x9e, 0xf7, 0x92, 0x5e, 0x01, 0x2a, 0x2a, 0x74, 0xcf, 0x02, 0xd7, 0xf0, 0xe6, 0x92, 0x68, 0x6c, + 0xe9, 0x69, 0x4b, 0x34, 0x70, 0xaf, 0x4c, 0x48, 0xaa, 0x8d, 0x03, 0x2c, 0x62, 0x5d, 0x7f, 0x0c, 0x25, 0x00, 0xb5, + 0x1a, 0xa4, 0x57, 0xfa, 0x92, 0x50, 0x95, 0x84, 0x60, 0x74, 0x22, 0xe1, 0x65, 0x40, 0xe3, 0xcc, 0x24, 0x5a, 0xd8, + 0xe0, 0x80, 0x3e, 0xaf, 0x4c, 0xa2, 0xb1, 0x21, 0x0f, 0x68, 0x65, 0xd3, 0x00, 0x06, 0x1f, 0x24, 0x49, 0xf4, 0xd5, + 0xca, 0x24, 0x81, 0xa0, 0x04, 0xe5, 0x1b, 0xf4, 0xe7, 0xd2, 0xf3, 0xb1, 0xfc, 0x97, 0x77, 0x28, 0xfd, 0x10, 0x4a, + 0x90, 0x29, 0xea, 0x8a, 0x69, 0xc6, 0x66, 0x59, 0xb7, 0x31, 0x89, 0xe7, 0x69, 0x77, 0x5b, 0x28, 0x97, 0x2e, 0xf0, + 0x2b, 0xcb, 0x10, 0xc7, 0xfa, 0x59, 0xbc, 0x66, 0x27, 0x21, 0xd7, 0x78, 0xe9, 0xcf, 0xe2, 0x35, 0xce, 0x10, 0xad, + 0x5a, 0x09, 0x44, 0xf9, 0xaf, 0xda, 0xc0, 0x21, 0xee, 0x13, 0x0c, 0x72, 0x51, 0x79, 0x0f, 0x04, 0xf2, 0xb6, 0x82, + 0x88, 0x34, 0xb3, 0xeb, 0x30, 0x22, 0xd5, 0x5e, 0x92, 0xf9, 0xf2, 0x47, 0x99, 0x09, 0xef, 0x1b, 0x78, 0x6c, 0x36, + 0xcb, 0xa6, 0x98, 0x2f, 0x54, 0x30, 0x07, 0xf7, 0x89, 0x8a, 0x4b, 0x51, 0xf9, 0x4f, 0xd8, 0x05, 0x2f, 0xc6, 0x83, + 0xd7, 0x6b, 0x04, 0xd8, 0xaf, 0xfc, 0x27, 0x6f, 0xcc, 0xde, 0x58, 0x37, 0xbe, 0xcc, 0x44, 0x7c, 0xe0, 0xa3, 0x5b, + 0xca, 0x47, 0x77, 0x5e, 0xa6, 0x3f, 0x1a, 0x50, 0x22, 0xa3, 0xb2, 0xe2, 0xeb, 0x35, 0x4f, 0xe7, 0xb7, 0x49, 0x94, + 0x8d, 0x2a, 0x2e, 0x60, 0x7a, 0xc1, 0xf1, 0x2e, 0xd9, 0x9c, 0x67, 0xc9, 0x2b, 0x88, 0x3d, 0xb0, 0x96, 0x0a, 0x8b, + 0x1f, 0x96, 0x99, 0x5a, 0xcc, 0x42, 0x56, 0x52, 0xf0, 0x60, 0x7e, 0x9d, 0x44, 0x6f, 0x56, 0x1e, 0x92, 0x9a, 0x99, + 0xb2, 0x6d, 0xed, 0x08, 0xb5, 0xf1, 0x75, 0xa4, 0x5b, 0x6d, 0x01, 0x00, 0xf7, 0x6c, 0x91, 0x46, 0x92, 0x89, 0xe1, + 0xa4, 0x66, 0xdc, 0xa4, 0x17, 0x98, 0x1a, 0xd7, 0xac, 0xa2, 0x89, 0xb3, 0x90, 0x01, 0xbd, 0x3f, 0xe0, 0xe5, 0xe0, + 0x73, 0x06, 0xf7, 0x1f, 0xb4, 0x06, 0x2e, 0x8f, 0x8b, 0x7e, 0x5f, 0x1e, 0x17, 0xbb, 0x5d, 0x39, 0x8b, 0xfb, 0x7d, + 0x39, 0x8b, 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, 0x6a, 0x2e, 0x06, 0xf9, 0x30, 0x89, 0xf2, 0x61, 0xe2, 0x39, 0x21, + 0xfe, 0xea, 0x39, 0x21, 0x2a, 0x1a, 0xb8, 0x86, 0x33, 0x03, 0x10, 0x05, 0x7c, 0xfa, 0x47, 0x75, 0x2d, 0x85, 0xae, + 0x25, 0x56, 0xb5, 0x24, 0xba, 0x82, 0x9a, 0x5d, 0x17, 0x61, 0x89, 0xa5, 0xd0, 0x15, 0xfb, 0x63, 0x05, 0x3c, 0x51, + 0xce, 0xab, 0x2d, 0x30, 0xb0, 0x11, 0xde, 0x39, 0x4c, 0x38, 0x89, 0x4d, 0x0d, 0x68, 0xa7, 0xdb, 0x9a, 0x5e, 0xd0, + 0x35, 0xbd, 0x44, 0x7e, 0xf6, 0x02, 0x0c, 0x96, 0x8e, 0x59, 0x3e, 0x1d, 0x0c, 0x2e, 0xc8, 0x9a, 0x95, 0x8b, 0x30, + 0x1e, 0x84, 0x9b, 0x79, 0x3e, 0xbc, 0x88, 0x2e, 0x08, 0xf9, 0xa2, 0x58, 0xd2, 0xde, 0x7a, 0x54, 0x7e, 0xcc, 0x20, + 0xb8, 0x5f, 0x3a, 0x0f, 0x33, 0x13, 0xe7, 0x63, 0x3d, 0xba, 0xa5, 0x6b, 0x88, 0x5f, 0x03, 0x37, 0x12, 0x12, 0x41, + 0x47, 0x2e, 0xe9, 0x9a, 0x6e, 0xa8, 0x34, 0x33, 0x8c, 0x21, 0xba, 0xed, 0x71, 0x92, 0x80, 0x63, 0xb2, 0x2b, 0x3e, + 0x1a, 0xab, 0xc2, 0xbb, 0xbe, 0x23, 0xb4, 0xd7, 0x4b, 0xdc, 0x20, 0x7d, 0xd7, 0x1e, 0x24, 0x60, 0x44, 0x46, 0x6a, + 0xa0, 0xcc, 0xc8, 0x48, 0x6a, 0x26, 0x15, 0x87, 0x24, 0xf6, 0x87, 0x44, 0x8d, 0x43, 0xe2, 0x8f, 0x43, 0xae, 0xc7, + 0x01, 0xb9, 0xfb, 0x15, 0x1b, 0xd3, 0x94, 0x8d, 0xe9, 0x46, 0x8d, 0x0a, 0xbd, 0xa2, 0xe7, 0x9a, 0x3a, 0x9e, 0xb1, + 0xd7, 0x70, 0x60, 0x0f, 0xc2, 0x7c, 0x1e, 0x0f, 0x5f, 0x47, 0xaf, 0x09, 0xf9, 0x42, 0xd2, 0x6b, 0x75, 0x29, 0x83, + 0x30, 0x88, 0x57, 0xe0, 0x5c, 0xea, 0x42, 0x9d, 0x5c, 0x99, 0x1d, 0x87, 0x4f, 0x97, 0x8d, 0xa7, 0x73, 0x88, 0xe8, + 0x83, 0x56, 0x2a, 0xfd, 0x7e, 0x78, 0xc1, 0xca, 0xc5, 0x59, 0x38, 0x26, 0x80, 0xc3, 0xa3, 0x87, 0xf3, 0x62, 0x74, + 0x4b, 0x2f, 0x46, 0x77, 0x04, 0x2c, 0xbc, 0xc6, 0xd3, 0xcd, 0x31, 0x8b, 0xa7, 0x83, 0xc1, 0x06, 0xa9, 0xba, 0xca, + 0xbd, 0x21, 0x4b, 0x7a, 0x81, 0x13, 0x41, 0x80, 0xa1, 0xcf, 0xc4, 0xc6, 0xd0, 0xf0, 0xd7, 0x0c, 0x3e, 0xbe, 0x63, + 0x17, 0xa3, 0x3b, 0x7a, 0xcb, 0x5e, 0xef, 0xc6, 0x53, 0x60, 0xa6, 0xd6, 0xf3, 0xf0, 0xee, 0xf8, 0x72, 0x7e, 0xc9, + 0xee, 0xa2, 0xbb, 0x19, 0x34, 0xf4, 0x8a, 0xdd, 0x21, 0xe0, 0x52, 0xfa, 0x78, 0x35, 0x78, 0x4d, 0x0e, 0x07, 0x83, + 0x94, 0x44, 0xe1, 0x75, 0xe8, 0xb5, 0xf2, 0x35, 0xbd, 0x23, 0x74, 0xcd, 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, 0x7e, 0xb7, 0x8a, 0x7e, 0xf5, 0xe8, 0xc3, 0x0f, 0xdd, 0x94, 0x47, 0xe4, 0xff, 0x3e, 0xe5, 0x29, 0xf3, + 0xe8, 0x75, 0xe5, 0x81, 0xe0, 0x79, 0x6b, 0x52, 0x69, 0x24, 0xaa, 0xd1, 0xd9, 0x3a, 0x06, 0x6d, 0x24, 0x6a, 0x1b, + 0xf4, 0x13, 0x5a, 0x58, 0x41, 0x84, 0x9c, 0xa3, 0xe7, 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, 0x65, + 0x8f, 0x5c, 0x94, 0xfc, 0x12, 0xcf, 0xe6, 0x36, 0xc1, 0x28, 0x58, 0x22, 0x9a, 0xa1, 0x6d, 0x10, 0xfb, 0xb1, 0x24, + 0x58, 0x8f, 0xa4, 0xf1, 0xa8, 0x34, 0x47, 0x84, 0x1f, 0xc5, 0x47, 0xd1, 0xd3, 0xd8, 0x90, 0x48, 0x8e, 0x24, 0x92, + 0x0f, 0x80, 0x70, 0x12, 0xf4, 0x17, 0x77, 0x4d, 0x76, 0x2d, 0x24, 0x06, 0xfd, 0x69, 0xc5, 0xb4, 0xec, 0x5e, 0xf5, + 0xd8, 0x57, 0x04, 0xb9, 0x63, 0xfa, 0x4f, 0xaf, 0x0f, 0xff, 0x5c, 0xe1, 0x0c, 0x5a, 0xcf, 0x17, 0xd5, 0x99, 0xb9, + 0x37, 0xb8, 0x91, 0xd7, 0x65, 0xed, 0xba, 0x7c, 0xc1, 0x0f, 0xf8, 0x6d, 0xc5, 0x45, 0x5a, 0x1e, 0xfc, 0x5c, 0xb5, + 0xf1, 0x9c, 0xca, 0xcd, 0xda, 0xc5, 0x59, 0x51, 0xc6, 0xa9, 0x9e, 0xd4, 0xc5, 0x58, 0xc3, 0x36, 0xfc, 0x1e, 0x51, + 0x57, 0xd2, 0x72, 0xf4, 0x94, 0x72, 0xdd, 0x4c, 0xb9, 0xd8, 0xe4, 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, 0x9f, 0xb3, 0x15, 0x08, + 0x98, 0x6b, 0x78, 0xbb, 0xae, 0xa3, 0xed, 0x9e, 0x38, 0x65, 0x54, 0xae, 0x63, 0xf1, 0x7d, 0xbc, 0x36, 0x90, 0xc9, + 0xea, 0x78, 0x6c, 0x8c, 0xe9, 0xf4, 0xef, 0x49, 0xe8, 0x17, 0x42, 0xc1, 0x67, 0xbd, 0xb4, 0xf2, 0xe4, 0xf6, 0xb0, + 0x8c, 0x6b, 0xf4, 0x4a, 0x5c, 0xeb, 0xbe, 0x19, 0x29, 0xa4, 0x1e, 0xf9, 0xaa, 0x29, 0xa0, 0x37, 0x63, 0xdf, 0x4c, + 0x85, 0x79, 0xbb, 0x67, 0xcc, 0x15, 0x82, 0x95, 0x2a, 0xbb, 0x7d, 0xa7, 0xc6, 0x54, 0xcc, 0x60, 0x8a, 0x6d, 0x67, + 0x31, 0xe9, 0x56, 0xfe, 0x69, 0xe7, 0x7e, 0x95, 0x77, 0xb8, 0x2b, 0xea, 0xb7, 0xc0, 0x85, 0x66, 0x45, 0x59, 0xb5, + 0x65, 0xc3, 0xb6, 0xf1, 0x46, 0x16, 0x8a, 0x0d, 0xb0, 0xec, 0xb9, 0x6f, 0xe1, 0x01, 0xe2, 0x26, 0xdc, 0xb3, 0xcb, + 0x1a, 0x6e, 0x0c, 0x9f, 0x57, 0x92, 0xef, 0x4a, 0x63, 0x2e, 0x7d, 0xaa, 0x34, 0x31, 0x9c, 0x2c, 0x47, 0x5c, 0xa4, + 0xcb, 0x3a, 0xb3, 0x6b, 0xe1, 0x13, 0x5e, 0x86, 0x0b, 0xbe, 0x34, 0xba, 0x29, 0x5d, 0x7a, 0xc1, 0x62, 0xdd, 0xe9, + 0xed, 0x5a, 0x63, 0xa5, 0x44, 0xdc, 0x9a, 0x65, 0x02, 0x65, 0x29, 0x6b, 0x25, 0xbc, 0x29, 0x5a, 0xb6, 0x92, 0x46, + 0xde, 0xb3, 0x00, 0xf7, 0xb1, 0x1f, 0x10, 0x13, 0xd9, 0x04, 0x26, 0x45, 0x43, 0x07, 0xb4, 0xab, 0x2e, 0x7c, 0x33, + 0xea, 0xc1, 0x20, 0xb7, 0x24, 0x11, 0x2b, 0x48, 0xb1, 0x82, 0x4d, 0xcd, 0x8a, 0x45, 0xbe, 0xa4, 0x17, 0x4c, 0x2e, + 0xd2, 0x25, 0x5d, 0x33, 0xb9, 0xd8, 0xe0, 0x4d, 0xe8, 0x02, 0x4e, 0x48, 0xb2, 0x8d, 0x95, 0x02, 0xf6, 0x02, 0x2f, + 0x6f, 0x78, 0xa6, 0x6a, 0x5a, 0x76, 0xa9, 0x38, 0xc0, 0xf8, 0xbc, 0x0c, 0xc3, 0x72, 0x78, 0x01, 0xd6, 0x12, 0x87, + 0xe1, 0x7a, 0xc1, 0x97, 0xea, 0x37, 0x04, 0x9c, 0x4f, 0x42, 0xc5, 0x2e, 0xd8, 0xbd, 0x40, 0xa6, 0x57, 0x0b, 0xbe, + 0x54, 0x23, 0xa1, 0x0b, 0xbe, 0xb2, 0xc6, 0x26, 0xb1, 0x27, 0x68, 0x99, 0xc7, 0x8b, 0xf1, 0x32, 0x8a, 0x6b, 0x58, + 0x86, 0xa7, 0x6a, 0x66, 0x5a, 0xf2, 0x9f, 0x44, 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, 0xd3, 0xdc, 0xe3, 0x95, 0x84, 0xc1, 0x0f, 0xa9, 0xd9, 0x24, 0xf3, 0xf6, + 0x8a, 0x7d, 0x0f, 0x1d, 0xf5, 0xa8, 0x35, 0xde, 0x57, 0x2f, 0x38, 0x85, 0x18, 0x25, 0x14, 0x9d, 0x04, 0x03, 0xb8, + 0x5d, 0x42, 0x8a, 0xbb, 0xc1, 0x6e, 0x9b, 0xd7, 0xbc, 0x28, 0x38, 0xdf, 0x54, 0x55, 0xe0, 0x07, 0x34, 0x5c, 0x2c, + 0xf7, 0x43, 0x18, 0x8e, 0x69, 0xeb, 0x1a, 0x06, 0x61, 0xc6, 0x30, 0x12, 0x82, 0xd7, 0xbf, 0xe8, 0x2b, 0x9a, 0xc4, + 0xeb, 0xef, 0xf8, 0x5f, 0x19, 0x2f, 0x14, 0x91, 0x06, 0x11, 0x52, 0x37, 0xf1, 0x8d, 0x4c, 0x93, 0x02, 0x0a, 0x01, + 0x46, 0x01, 0x95, 0xd8, 0xd0, 0x54, 0xfc, 0xad, 0x16, 0x1f, 0xfc, 0xd4, 0x74, 0x3c, 0x1a, 0xd7, 0xad, 0xce, 0xa8, + 0xa0, 0x33, 0xd0, 0xa3, 0x56, 0xd4, 0xd3, 0xa0, 0x95, 0x60, 0x1a, 0x69, 0xde, 0xba, 0x87, 0xc0, 0x2b, 0xd3, 0xe2, + 0x9d, 0x07, 0x74, 0x7b, 0xe6, 0x83, 0x27, 0x8f, 0xe9, 0x99, 0x43, 0x4f, 0xae, 0xd8, 0xac, 0xea, 0xa1, 0xf6, 0xde, + 0x8c, 0x50, 0xd0, 0xef, 0x63, 0x0a, 0x74, 0x23, 0xa8, 0xbd, 0xab, 0xfb, 0x8f, 0xe5, 0x3e, 0x87, 0xef, 0x38, 0xcb, + 0x2d, 0x60, 0xa9, 0xc8, 0x5a, 0x81, 0x47, 0x01, 0xea, 0x52, 0x19, 0xc2, 0x16, 0x73, 0x38, 0x54, 0x76, 0xab, 0x56, + 0x43, 0x49, 0x8e, 0xcb, 0x11, 0x38, 0x84, 0x6e, 0xca, 0x41, 0x39, 0x5a, 0x65, 0xd5, 0x7b, 0xfc, 0xad, 0x59, 0x87, + 0x24, 0xbb, 0x8f, 0x75, 0xe0, 0x96, 0x75, 0x98, 0x7e, 0x34, 0x48, 0x01, 0x68, 0xb2, 0x11, 0xb8, 0x04, 0xe0, 0xbd, + 0xfd, 0x47, 0x84, 0x5a, 0x99, 0xde, 0xcb, 0x58, 0xa8, 0xef, 0x1b, 0x49, 0x50, 0x42, 0x33, 0xa1, 0x72, 0x2c, 0x05, + 0xef, 0x3c, 0xd2, 0x39, 0xa9, 0x33, 0xf1, 0x1e, 0xc4, 0x69, 0xe1, 0x03, 0x7b, 0x0b, 0x82, 0x73, 0x16, 0xf4, 0x0e, + 0x6f, 0xb3, 0x5a, 0x6a, 0xa3, 0x07, 0x0a, 0xe0, 0x77, 0x83, 0x3b, 0x04, 0xf9, 0x6a, 0x0c, 0xd7, 0x5a, 0xde, 0x84, + 0x7c, 0x58, 0xd0, 0x23, 0x32, 0xb0, 0xcf, 0x62, 0x18, 0xd3, 0x23, 0x72, 0x6c, 0x9f, 0xa5, 0x1b, 0xc0, 0x81, 0xd4, + 0xa3, 0x4a, 0x8f, 0xa0, 0x41, 0xbf, 0xd9, 0x16, 0x59, 0x92, 0xf5, 0x63, 0x69, 0x14, 0x31, 0x50, 0x25, 0x88, 0xa8, + 0xc5, 0x3f, 0x1f, 0xcc, 0x75, 0x87, 0xb9, 0x40, 0x98, 0x83, 0x01, 0x07, 0x71, 0x1b, 0x84, 0xe6, 0x80, 0xd9, 0xde, + 0x46, 0x82, 0xde, 0x59, 0xc3, 0xcc, 0x8e, 0xfe, 0x70, 0x2b, 0xc1, 0x37, 0x59, 0x6b, 0xd4, 0x79, 0x71, 0x08, 0x04, + 0xc1, 0x9b, 0x42, 0x55, 0x7b, 0xd5, 0x03, 0x1b, 0x6f, 0xd5, 0x8f, 0xdd, 0x6e, 0x3c, 0x15, 0xee, 0xda, 0x2f, 0x28, + 0x9c, 0x7c, 0x4a, 0xfe, 0xf5, 0xde, 0x64, 0x70, 0x60, 0x64, 0xf8, 0xd2, 0xdb, 0xbf, 0xf0, 0xb5, 0x96, 0xee, 0x89, + 0x41, 0x49, 0x1e, 0x1f, 0x29, 0xfa, 0x77, 0xaf, 0xac, 0x7c, 0x6a, 0xa7, 0x7f, 0xb7, 0x33, 0xeb, 0xf3, 0x78, 0x34, + 0xd9, 0xed, 0x7a, 0xda, 0xc0, 0x95, 0x6a, 0x15, 0x02, 0x76, 0xa1, 0x24, 0x87, 0x47, 0x10, 0x15, 0xa1, 0x19, 0x77, + 0xb3, 0x6c, 0x48, 0x64, 0xfc, 0x38, 0x9d, 0x65, 0x43, 0xb0, 0xc3, 0xbd, 0xa8, 0xc4, 0xe5, 0xa8, 0xb5, 0xc1, 0xe9, + 0x59, 0x12, 0x42, 0x28, 0x07, 0xac, 0xec, 0x56, 0xfd, 0xb9, 0x53, 0x66, 0x42, 0x6a, 0xb2, 0xba, 0x9d, 0xd2, 0x3d, + 0x4c, 0xf3, 0x03, 0x33, 0x82, 0x03, 0xee, 0xed, 0xaf, 0xfa, 0x63, 0x98, 0x64, 0x9a, 0x9c, 0x22, 0xf9, 0x45, 0x7a, + 0x0a, 0x49, 0x7b, 0xf4, 0x54, 0x11, 0xc0, 0x09, 0xb5, 0x1f, 0xc3, 0x6f, 0x18, 0xf7, 0xef, 0x9a, 0xaf, 0xdd, 0x54, + 0x44, 0x4f, 0x28, 0x96, 0xa9, 0xc9, 0x69, 0x92, 0x15, 0x09, 0x44, 0x6d, 0x54, 0xcd, 0x88, 0xbe, 0x72, 0x31, 0x1f, + 0x15, 0xe1, 0xf3, 0x6a, 0xfd, 0x9f, 0x21, 0x7c, 0x46, 0xe1, 0x06, 0x70, 0x79, 0xc5, 0xe5, 0x79, 0xf8, 0xf4, 0x09, + 0x3d, 0x98, 0x7c, 0x7d, 0x44, 0x0f, 0x8e, 0xbe, 0x7a, 0x4a, 0x00, 0x16, 0xed, 0xf2, 0x3c, 0x3c, 0x7a, 0xfa, 0x94, + 0x1e, 0x7c, 0xfb, 0x2d, 0x3d, 0x98, 0x7c, 0x75, 0xd4, 0x48, 0x9b, 0x3c, 0xfd, 0x96, 0x1e, 0x7c, 0xfd, 0xa4, 0x91, + 0x76, 0x34, 0x7e, 0x4a, 0x0f, 0xbe, 0xf9, 0xda, 0xa4, 0xfd, 0x0d, 0xb2, 0x7d, 0x7b, 0x84, 0xff, 0x99, 0xb4, 0xc9, + 0xd3, 0xaf, 0xe8, 0xc1, 0x64, 0x0c, 0x95, 0x3c, 0x75, 0x95, 0x8c, 0x27, 0xf0, 0xf1, 0x57, 0xf0, 0xdf, 0xdf, 0x48, + 0xb0, 0xa4, 0x95, 0x64, 0xb9, 0x40, 0xfd, 0x19, 0x8a, 0x38, 0x51, 0x35, 0x91, 0xf0, 0x10, 0x33, 0xab, 0x6f, 0xe2, + 0x30, 0x20, 0x2e, 0x1d, 0x0a, 0xa2, 0x07, 0xe3, 0xd1, 0x53, 0x12, 0xf8, 0xf0, 0x74, 0x37, 0x3e, 0xc8, 0x58, 0x2e, + 0x16, 0xd9, 0x17, 0xb9, 0x89, 0xad, 0xe0, 0x01, 0x58, 0x7d, 0xf4, 0x73, 0x55, 0x72, 0x91, 0x7d, 0x51, 0xc9, 0xfd, + 0x5c, 0xbf, 0xb5, 0x00, 0xe5, 0xfd, 0x55, 0xcb, 0x6e, 0x0a, 0x15, 0x3a, 0xad, 0x35, 0xfa, 0xec, 0x23, 0xa6, 0x0f, + 0x06, 0xde, 0x0d, 0xfb, 0xef, 0x7b, 0xe5, 0xb4, 0xbe, 0xd1, 0x28, 0xd4, 0xa8, 0x3c, 0x24, 0x6c, 0x06, 0x45, 0x0f, + 0x06, 0xc0, 0x13, 0x78, 0xb8, 0x6f, 0xff, 0x66, 0x19, 0x1f, 0x3b, 0xca, 0xf8, 0x19, 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, 0x79, 0xc5, 0xfe, 0xbe, 0x42, 0xf5, 0x56, 0xd4, 0x78, 0x23, 0xb3, 0x79, 0xc5, 0xbe, + 0x37, 0x6f, 0x80, 0x9b, 0x61, 0xbf, 0xa9, 0x27, 0x3f, 0x70, 0x06, 0x97, 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, 0xfd, 0xaf, 0x86, 0xbc, 0x04, 0x85, 0x5b, 0xcd, 0xf2, 0xf6, 0x0a, 0x43, 0x08, 0xc1, 0x1f, 0x57, 0x0c, + 0x00, 0x07, 0x02, 0x0c, 0xc6, 0x5a, 0x06, 0xd4, 0x6c, 0xf9, 0x68, 0xcb, 0x95, 0x7a, 0x12, 0x38, 0x83, 0x0b, 0x59, + 0x24, 0xfc, 0xad, 0x16, 0xfb, 0xa3, 0xf5, 0xa3, 0xef, 0xdb, 0xe3, 0xc1, 0xda, 0xf7, 0xf8, 0x48, 0x7f, 0xd6, 0xb8, + 0x0e, 0x6c, 0x5b, 0xbe, 0xf1, 0xa2, 0xb6, 0x12, 0x8f, 0x12, 0x78, 0x03, 0x13, 0x91, 0xc2, 0x20, 0xd5, 0x02, 0xc7, + 0xa0, 0xbc, 0xb1, 0x10, 0x4b, 0xd5, 0xd5, 0x0d, 0xb6, 0x20, 0x32, 0x04, 0x0f, 0xb7, 0x7f, 0xad, 0x54, 0xe0, 0xa8, + 0x7e, 0x9f, 0x4b, 0xdf, 0xed, 0xc9, 0xd8, 0x91, 0xe3, 0xd4, 0x4f, 0x85, 0x83, 0xff, 0x26, 0x75, 0x6d, 0x2c, 0x57, + 0x52, 0x66, 0x59, 0x16, 0x36, 0x0b, 0xb5, 0xdc, 0xa3, 0xf2, 0x20, 0xf9, 0x42, 0x0e, 0x91, 0x2c, 0x30, 0x0a, 0x05, + 0x19, 0x4e, 0xa8, 0x18, 0x6d, 0x44, 0xb9, 0xca, 0x2e, 0xaa, 0x70, 0xab, 0x14, 0xca, 0x9c, 0xa2, 0x6f, 0x37, 0x38, + 0x90, 0x90, 0x28, 0x2b, 0xdf, 0xc4, 0x6f, 0x42, 0x04, 0xab, 0xe3, 0xda, 0x16, 0x8a, 0x7b, 0xfb, 0x93, 0xa7, 0x5d, + 0xfc, 0x91, 0x71, 0x01, 0x75, 0xb1, 0x98, 0x86, 0x13, 0x1b, 0xfb, 0xc6, 0x7d, 0x61, 0x35, 0x3d, 0x00, 0xf5, 0x5d, + 0x2a, 0x31, 0x82, 0xfa, 0xca, 0xd8, 0xc7, 0xf6, 0x18, 0x93, 0x73, 0x88, 0x35, 0xac, 0x72, 0x66, 0xaa, 0x6f, 0x84, + 0xcd, 0x00, 0xb8, 0x11, 0x5a, 0xa3, 0x20, 0xf0, 0x78, 0x15, 0xe2, 0x79, 0xa9, 0xc2, 0xb7, 0x66, 0x84, 0x8e, 0xc1, + 0x9b, 0xca, 0x36, 0x32, 0x93, 0xbe, 0x60, 0xd0, 0x1c, 0xdb, 0x3a, 0x0a, 0xab, 0xad, 0x2c, 0x9b, 0x01, 0xdc, 0x40, + 0x76, 0x6c, 0x2e, 0x9e, 0xf3, 0x6a, 0x91, 0x2d, 0x23, 0x13, 0x14, 0x70, 0x25, 0x2c, 0x83, 0xf6, 0xd7, 0x3d, 0xb2, + 0x1d, 0x87, 0xd0, 0x0d, 0xf7, 0x11, 0x8c, 0xa7, 0xdd, 0x14, 0xac, 0x20, 0x1a, 0x21, 0x1e, 0x66, 0xcc, 0xe2, 0x7b, + 0xa5, 0x29, 0x4f, 0x55, 0x4b, 0x20, 0x70, 0x14, 0x42, 0x5d, 0xec, 0x1b, 0x25, 0xb8, 0x4c, 0x8d, 0x60, 0x06, 0x7b, + 0x76, 0xa4, 0xb6, 0x4b, 0xce, 0xe9, 0x50, 0x4d, 0x69, 0xa9, 0xa7, 0x54, 0xfb, 0x1a, 0x8a, 0x45, 0x89, 0x1e, 0x7a, + 0xe0, 0x7a, 0xa0, 0x1d, 0xf2, 0x4a, 0x3a, 0x31, 0x11, 0x74, 0x5a, 0x6d, 0xc2, 0xce, 0x8d, 0x74, 0xcb, 0x6a, 0xe4, + 0x1d, 0x43, 0xb3, 0x23, 0x5e, 0xf8, 0x81, 0xba, 0x00, 0x22, 0xe4, 0xde, 0x16, 0x99, 0x23, 0x9a, 0x65, 0xe5, 0x4b, + 0x28, 0x8b, 0x23, 0xb6, 0xae, 0x80, 0x6b, 0x29, 0x98, 0x5c, 0xf2, 0x88, 0xa7, 0x88, 0x08, 0x78, 0xa2, 0xb4, 0xeb, + 0x7b, 0x2d, 0x21, 0x34, 0x4b, 0x81, 0xb8, 0xb9, 0x28, 0xce, 0xb5, 0x0d, 0x64, 0x01, 0xf4, 0xed, 0xa7, 0xec, 0xca, + 0x0b, 0x07, 0xbb, 0xbd, 0xca, 0xc4, 0x73, 0x7e, 0x91, 0x09, 0x9e, 0x22, 0xd8, 0xd5, 0xad, 0x79, 0xe0, 0x8e, 0x6d, + 0x03, 0xcb, 0xb7, 0xef, 0x60, 0xc1, 0x94, 0xa1, 0x56, 0x4a, 0x64, 0x22, 0x12, 0x90, 0xd9, 0x67, 0xee, 0x5e, 0x67, + 0xe2, 0x75, 0x7c, 0x0b, 0xde, 0x14, 0x0d, 0x7e, 0x7a, 0x74, 0x8e, 0x5f, 0x22, 0x92, 0x28, 0xc4, 0xb0, 0xc5, 0x88, + 0x58, 0x88, 0x1c, 0x3b, 0x26, 0x94, 0x2b, 0x41, 0x6b, 0x6b, 0x08, 0xbc, 0xf8, 0xd3, 0xaa, 0x7b, 0x57, 0x99, 0x30, + 0xf6, 0x19, 0x57, 0xf1, 0x2d, 0x2b, 0x15, 0x98, 0x05, 0xc6, 0xb9, 0x6f, 0x4b, 0x49, 0xae, 0x32, 0x61, 0x04, 0x24, + 0x57, 0xf1, 0x2d, 0x6d, 0xca, 0x38, 0xb4, 0x15, 0x9d, 0x17, 0xe7, 0x77, 0x7f, 0xf8, 0x25, 0x86, 0x5a, 0x19, 0xf7, + 0xfb, 0x20, 0x31, 0x93, 0xb6, 0x29, 0x73, 0x19, 0x49, 0x8d, 0x16, 0x52, 0x51, 0x3e, 0x98, 0x90, 0xfd, 0x95, 0x6a, + 0x19, 0x51, 0xfb, 0x55, 0x28, 0xe6, 0xe3, 0x68, 0x42, 0xe8, 0xa4, 0x63, 0xbd, 0x9b, 0xd6, 0x42, 0xa6, 0xd1, 0xd3, + 0xc8, 0xf3, 0xe9, 0x2c, 0x58, 0x35, 0x2d, 0x8e, 0x19, 0x9f, 0x16, 0x83, 0x01, 0xd1, 0x2e, 0x85, 0x5b, 0xac, 0x07, + 0x4c, 0x69, 0x5c, 0xbc, 0x35, 0xd3, 0xea, 0x97, 0x52, 0x85, 0xa4, 0xf7, 0x0c, 0x48, 0x32, 0xe9, 0x82, 0xdd, 0x82, + 0x44, 0xd1, 0xf3, 0xbf, 0x53, 0x5b, 0x70, 0xdf, 0x83, 0xb1, 0x19, 0xdd, 0xd7, 0x33, 0xfe, 0x43, 0x6d, 0x0b, 0xa2, + 0x3e, 0x95, 0xac, 0xd7, 0x91, 0xa8, 0x42, 0x2e, 0xc2, 0xcf, 0x8e, 0x86, 0x18, 0xa2, 0xda, 0x63, 0x81, 0xd8, 0x5c, + 0x9d, 0xf3, 0x02, 0xa7, 0x9f, 0xb9, 0xcb, 0x15, 0x6c, 0x0b, 0x5a, 0x19, 0x1a, 0xf5, 0x26, 0x7e, 0x13, 0xd9, 0xcb, + 0x82, 0x2e, 0xf2, 0x39, 0x0a, 0x59, 0xf3, 0x30, 0xac, 0x86, 0xed, 0x41, 0x24, 0x87, 0xed, 0x49, 0x68, 0x34, 0x06, + 0x16, 0xc8, 0x1e, 0x8d, 0xc0, 0x45, 0x68, 0xe5, 0x6f, 0xc7, 0xe0, 0xc2, 0x65, 0x11, 0x59, 0x86, 0x3a, 0x7e, 0x53, + 0xbb, 0x09, 0xaa, 0x57, 0xe8, 0x34, 0x85, 0x55, 0x29, 0x93, 0x7c, 0xf8, 0xf5, 0x52, 0x16, 0x98, 0xc9, 0xeb, 0xb2, + 0x47, 0x5f, 0xdb, 0xed, 0x1d, 0x98, 0x82, 0x75, 0x9f, 0xbc, 0xaf, 0x1f, 0x77, 0xf6, 0x04, 0x8c, 0x62, 0x55, 0x8e, + 0xa6, 0x90, 0x52, 0xfb, 0xa0, 0xd4, 0x1f, 0xc3, 0x95, 0xd0, 0x1c, 0xbb, 0x05, 0x4c, 0x02, 0xf6, 0x19, 0x52, 0x3d, + 0xa6, 0x1d, 0xfb, 0x1c, 0x6d, 0x61, 0x49, 0xc0, 0xe1, 0x1f, 0x65, 0xb2, 0xf6, 0xaf, 0xee, 0x22, 0x6d, 0x86, 0x6c, + 0x59, 0x2c, 0x81, 0xcf, 0x87, 0x5d, 0x1b, 0x95, 0x28, 0x9b, 0x88, 0x24, 0x85, 0x2d, 0x8f, 0x41, 0xda, 0xa3, 0x98, + 0xae, 0x0b, 0x9e, 0x64, 0x28, 0xa5, 0x48, 0xb4, 0x4f, 0x70, 0x0e, 0x6f, 0x70, 0x3f, 0xaa, 0x80, 0xf0, 0x2a, 0xe4, + 0x74, 0x94, 0x52, 0x6d, 0x01, 0xa3, 0xa8, 0x07, 0x88, 0xf2, 0x32, 0x90, 0xe3, 0xed, 0x76, 0x13, 0xba, 0x66, 0xab, + 0xe1, 0x84, 0x22, 0x29, 0xb9, 0xc4, 0x72, 0xaf, 0x40, 0xe7, 0x71, 0xce, 0x7a, 0x2f, 0x00, 0x8b, 0xe0, 0x0c, 0xfe, + 0xc6, 0x84, 0x5e, 0xc3, 0xdf, 0x9c, 0xd0, 0xd7, 0x2c, 0xbc, 0x1a, 0x5e, 0x92, 0xc3, 0x30, 0x1d, 0x4c, 0x94, 0x60, + 0xec, 0x8e, 0xad, 0xca, 0x50, 0x25, 0xae, 0x0f, 0x2f, 0xc8, 0xe3, 0x0b, 0x7a, 0x4b, 0x6f, 0xe8, 0x29, 0x7d, 0x0b, + 0x84, 0xff, 0xee, 0x78, 0xc2, 0x87, 0x93, 0x27, 0xfd, 0x7e, 0xef, 0xbc, 0xdf, 0xef, 0x9d, 0x19, 0x03, 0x0a, 0xbd, + 0x8b, 0x2e, 0x6b, 0xaa, 0x7f, 0x5d, 0xd5, 0xcb, 0xe9, 0x5b, 0xb5, 0x71, 0x13, 0x9e, 0xe5, 0xe1, 0xd5, 0xe1, 0x1d, + 0x19, 0xe2, 0xe3, 0x45, 0x2e, 0x65, 0x11, 0x5e, 0x1e, 0xde, 0x11, 0xfa, 0x76, 0x06, 0x7a, 0x53, 0xac, 0xef, 0xed, + 0xe3, 0x3b, 0x5d, 0x1b, 0xa1, 0x2f, 0xc2, 0x04, 0xb6, 0xc9, 0x2d, 0xb3, 0x77, 0xed, 0xc9, 0x18, 0x62, 0x99, 0xdc, + 0x79, 0xe5, 0xdd, 0x3d, 0xbe, 0x25, 0x87, 0xb7, 0xe0, 0x29, 0x6a, 0xc9, 0xdf, 0x3c, 0xbc, 0x61, 0xad, 0x1a, 0x1e, + 0xdf, 0xd1, 0xd3, 0x56, 0x23, 0x1e, 0xdf, 0x91, 0x28, 0xbc, 0x61, 0x97, 0xf4, 0x94, 0x5d, 0x11, 0x7a, 0xde, 0xef, + 0x9f, 0xf5, 0xfb, 0xb2, 0xdf, 0xff, 0x7b, 0x1c, 0x86, 0xf1, 0xb0, 0x20, 0x87, 0x92, 0xde, 0x1d, 0x4e, 0xf8, 0x57, + 0x64, 0x1e, 0xea, 0xe6, 0xab, 0x05, 0x67, 0x55, 0xde, 0x2a, 0xd7, 0x1d, 0x05, 0x6b, 0x85, 0x3b, 0xa6, 0x9e, 0xde, + 0xd2, 0x1b, 0x56, 0xd0, 0x53, 0x16, 0x93, 0xe8, 0x1a, 0x5a, 0x71, 0x3e, 0x2f, 0xa2, 0x1b, 0x7a, 0xca, 0xce, 0xe6, + 0x71, 0x74, 0x4a, 0xdf, 0xb2, 0x7c, 0x38, 0x81, 0xbc, 0xa7, 0xc3, 0x1b, 0x72, 0xf8, 0x96, 0x44, 0xe1, 0x5b, 0xfd, + 0xfb, 0x8e, 0x5e, 0xf2, 0xf0, 0x2d, 0xf5, 0xaa, 0x79, 0x4b, 0x4c, 0xf5, 0x8d, 0xda, 0xdf, 0x92, 0xc8, 0x1f, 0xcc, + 0xb7, 0xd6, 0x9e, 0xe6, 0x91, 0xa3, 0x8d, 0x69, 0x19, 0x82, 0xbe, 0xb9, 0x0c, 0x6f, 0x08, 0x99, 0x36, 0xc7, 0x0e, + 0x06, 0x74, 0xfe, 0x28, 0x4a, 0x08, 0xbd, 0xf1, 0x4b, 0xbd, 0xc1, 0x31, 0x34, 0x23, 0xa4, 0xd2, 0x4e, 0x31, 0x0d, + 0xd7, 0xc1, 0x2b, 0x0d, 0xd6, 0x71, 0xde, 0xef, 0x87, 0x9b, 0x7e, 0x1f, 0x22, 0xdd, 0x17, 0x73, 0x13, 0xdb, 0xcd, + 0x91, 0x4d, 0x7a, 0x03, 0xda, 0xff, 0x57, 0x83, 0x01, 0x74, 0xc6, 0x2b, 0x29, 0xbc, 0x19, 0xbc, 0x7a, 0x7c, 0x47, + 0x54, 0x1d, 0x05, 0x15, 0x32, 0x2c, 0xe8, 0x6b, 0x9a, 0x01, 0xe0, 0xd7, 0xab, 0xc1, 0x80, 0x44, 0xe6, 0x33, 0x32, + 0x7d, 0x75, 0xfc, 0x76, 0x3a, 0x18, 0xbc, 0x32, 0xdb, 0xe4, 0x0d, 0xbb, 0xa7, 0x14, 0x58, 0x7f, 0x67, 0xfd, 0xfe, + 0x9b, 0x59, 0x4c, 0xce, 0x0b, 0x1e, 0x7f, 0x9c, 0x36, 0xdb, 0xf2, 0xc6, 0x45, 0x55, 0x3b, 0xeb, 0xf7, 0x37, 0xfd, + 0xfe, 0x29, 0x60, 0x17, 0xcd, 0x9d, 0xaf, 0x27, 0x48, 0x5b, 0x16, 0x8e, 0x22, 0x69, 0x92, 0x43, 0x63, 0x68, 0x5b, + 0xac, 0xda, 0x36, 0xef, 0xc8, 0xc0, 0xe2, 0xa8, 0x59, 0x51, 0x5c, 0x93, 0x28, 0xec, 0x9d, 0xed, 0x76, 0xa7, 0x8c, + 0xb1, 0x98, 0x80, 0xf4, 0xc3, 0x7f, 0x7d, 0x5a, 0x37, 0x62, 0x88, 0x09, 0x89, 0xcc, 0xe6, 0x76, 0x65, 0x0f, 0x81, + 0x88, 0xc3, 0xa6, 0x7f, 0x6f, 0xee, 0xe5, 0xa2, 0x76, 0x7c, 0xeb, 0xcf, 0x00, 0x42, 0x24, 0x59, 0xc8, 0xe7, 0x38, + 0x06, 0x65, 0x06, 0x40, 0xe6, 0x91, 0x9a, 0x79, 0x09, 0x20, 0xc0, 0x64, 0xb7, 0x1b, 0x8d, 0xc7, 0x13, 0x5a, 0xb0, + 0xd1, 0xdf, 0x9e, 0x3e, 0xae, 0x1e, 0x87, 0x41, 0x30, 0xc8, 0x48, 0x4b, 0x4f, 0x61, 0x17, 0x6b, 0x75, 0x08, 0x46, + 0xf0, 0x9a, 0x7d, 0xbc, 0xce, 0x3e, 0x9b, 0x7d, 0x44, 0xc2, 0xda, 0x60, 0x1c, 0xb9, 0x48, 0x5b, 0x7a, 0xbb, 0x7b, + 0x18, 0x4c, 0x2e, 0xd2, 0x4f, 0xb0, 0x9d, 0x3e, 0xff, 0xe6, 0xc1, 0x78, 0xc2, 0xc1, 0xe8, 0x2e, 0x0a, 0xfa, 0x4c, + 0xdb, 0xed, 0x2a, 0xff, 0x12, 0xf8, 0x06, 0x53, 0x41, 0xc7, 0x66, 0x59, 0xb8, 0x41, 0x45, 0xd4, 0xd1, 0x32, 0xa8, + 0x6a, 0x65, 0x3b, 0x07, 0xd4, 0x12, 0xab, 0x32, 0x71, 0x0b, 0x0c, 0x43, 0x86, 0xba, 0xdc, 0x93, 0xea, 0x5f, 0xbc, + 0x90, 0x06, 0x3e, 0xc3, 0x89, 0x08, 0x3d, 0x6e, 0x8d, 0xfb, 0xdc, 0x9a, 0xf8, 0x04, 0xb7, 0x56, 0x22, 0x89, 0x35, + 0xb0, 0xa4, 0xe6, 0x72, 0x94, 0xb0, 0x59, 0xc9, 0xf8, 0xbc, 0x8c, 0x12, 0x1a, 0xc3, 0x83, 0x64, 0x62, 0x2e, 0xa3, + 0x04, 0xed, 0x13, 0x5d, 0x84, 0xc1, 0x3f, 0x01, 0xb3, 0x9f, 0xe6, 0xf0, 0x57, 0x92, 0x69, 0x72, 0x0c, 0x01, 0x21, + 0x8e, 0xc7, 0xf3, 0x38, 0x1c, 0x93, 0x28, 0x99, 0xc1, 0x13, 0xfc, 0x57, 0x84, 0x63, 0x52, 0xeb, 0x3b, 0x8c, 0x54, + 0x97, 0xdb, 0x84, 0x01, 0x5c, 0xd9, 0x78, 0x3e, 0x89, 0xac, 0x74, 0x57, 0x3e, 0x1e, 0x8d, 0x9f, 0x92, 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, 0x7a, 0x0f, 0x52, 0x8a, 0x3e, 0xcf, 0xb1, 0x9f, 0xfa, 0x08, 0xc2, 0xec, 0xa8, 0xa5, + 0xe2, 0x6b, 0x00, 0xba, 0xc4, 0xc1, 0xa1, 0xf6, 0xcc, 0x17, 0xf3, 0xb0, 0xf4, 0xa8, 0x94, 0xa9, 0xee, 0x50, 0x34, + 0x28, 0xbf, 0x69, 0xd0, 0xa1, 0x20, 0x83, 0x09, 0x2d, 0x67, 0x13, 0xfe, 0x15, 0x04, 0xf0, 0x68, 0x44, 0xfc, 0x52, + 0x38, 0x31, 0x10, 0x5e, 0x05, 0x19, 0xa8, 0xb4, 0x56, 0x8d, 0x19, 0xd9, 0x8a, 0x0f, 0x20, 0x4c, 0xca, 0xc1, 0x8d, + 0xdc, 0xe4, 0x29, 0x44, 0x05, 0xdb, 0xe4, 0xd5, 0xc1, 0x25, 0x58, 0xb2, 0xc7, 0x15, 0xc4, 0x09, 0xdb, 0xac, 0x01, + 0x3b, 0xf7, 0xd1, 0xb6, 0xac, 0x0f, 0xd4, 0x77, 0x07, 0xd8, 0x72, 0x78, 0x55, 0xc9, 0x83, 0xc9, 0x78, 0x3c, 0x1e, + 0xfd, 0x0e, 0x47, 0x07, 0x10, 0x5a, 0x12, 0x19, 0x3e, 0x19, 0xa0, 0x71, 0x37, 0x15, 0xf7, 0xc6, 0x85, 0xa2, 0xac, + 0x74, 0x32, 0x21, 0x20, 0x7e, 0x36, 0x7d, 0x83, 0x7d, 0xc5, 0x75, 0xfc, 0x93, 0xfd, 0x4f, 0xcc, 0x8a, 0x56, 0x2b, + 0x75, 0xf4, 0xee, 0xed, 0xe9, 0xab, 0x0f, 0xaf, 0x7e, 0x7d, 0x71, 0xf6, 0xea, 0xcd, 0xcb, 0x57, 0x6f, 0x5e, 0x7d, + 0xf8, 0xe7, 0x03, 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, 0x36, 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, 0x43, 0xb4, 0x87, 0x14, 0xb1, 0x3e, 0x9c, 0xee, 0x77, 0xff, 0x66, 0xf4, 0x3d, 0x1c, + 0x3f, 0x4a, 0x35, 0x81, 0xb4, 0x28, 0x50, 0xba, 0x32, 0xe4, 0xb6, 0xe7, 0x61, 0x61, 0x7e, 0x86, 0x0d, 0x02, 0x68, + 0x2f, 0x3b, 0x96, 0x04, 0x9a, 0xc5, 0x6b, 0x5d, 0xff, 0xbc, 0x7c, 0x99, 0x68, 0xe7, 0x8b, 0x6f, 0x21, 0xc4, 0xb0, + 0x7f, 0x45, 0x68, 0x4c, 0xb8, 0x9b, 0x64, 0x77, 0x69, 0x31, 0xf7, 0xaa, 0xab, 0x18, 0x8f, 0xbb, 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, 0x8f, 0x9a, 0xf3, 0x36, 0x21, 0x17, 0xfb, + 0x34, 0x5c, 0x0c, 0xf9, 0x43, 0x97, 0xa4, 0x0f, 0xbc, 0xe1, 0x50, 0x6d, 0x9b, 0x8b, 0x21, 0x4d, 0x39, 0xdd, 0xa7, + 0x32, 0x20, 0x44, 0xba, 0x8a, 0x2b, 0x52, 0xeb, 0xa3, 0x2a, 0x75, 0x92, 0x8e, 0xeb, 0x6c, 0xfb, 0x89, 0x4b, 0xb6, + 0xba, 0x5d, 0xfb, 0xd7, 0xea, 0xf6, 0x85, 0x19, 0xc8, 0xdf, 0x1f, 0x88, 0x6a, 0x62, 0x20, 0xba, 0x80, 0x0a, 0xfe, + 0x01, 0x5e, 0x9e, 0x3c, 0xd2, 0x0a, 0xd0, 0xfb, 0xce, 0x8e, 0xae, 0x3d, 0xde, 0x98, 0xc5, 0xd6, 0x12, 0xe7, 0xac, + 0xf2, 0x9d, 0xe5, 0x55, 0xd9, 0x0a, 0x5d, 0x47, 0xb0, 0x9f, 0xc3, 0x8e, 0xbe, 0x7b, 0xdb, 0x00, 0x88, 0x52, 0x58, + 0xb9, 0xb3, 0x5f, 0x78, 0x67, 0xbf, 0xb0, 0x67, 0xbf, 0xdd, 0x04, 0xca, 0x87, 0x15, 0x5a, 0xf6, 0x52, 0x8a, 0xca, + 0x34, 0x79, 0xdc, 0xd4, 0x65, 0x21, 0x2d, 0xe6, 0x87, 0x96, 0x76, 0x3d, 0x19, 0x53, 0x89, 0xea, 0x91, 0x1f, 0xb0, + 0x55, 0x87, 0x25, 0x79, 0xf8, 0x9e, 0xf9, 0x3f, 0x7b, 0x83, 0xbc, 0xef, 0x6e, 0xf7, 0x7f, 0x73, 0xa1, 0x83, 0xdb, + 0x5a, 0x2a, 0x3c, 0x75, 0x75, 0x5c, 0xe0, 0x5d, 0x2d, 0x7d, 0xf8, 0xae, 0xf6, 0x2e, 0xd3, 0xcb, 0xae, 0x02, 0xd4, + 0x20, 0xb1, 0xb9, 0xe2, 0x45, 0x96, 0xd4, 0x56, 0xa1, 0xf1, 0x96, 0x43, 0x68, 0x0f, 0xef, 0xe0, 0x02, 0x39, 0x2c, + 0x21, 0xf4, 0x63, 0x65, 0x04, 0x80, 0x3e, 0x8b, 0xfd, 0x96, 0x87, 0x19, 0x19, 0xf8, 0x12, 0xbf, 0x52, 0xfa, 0xe2, + 0xe2, 0xc3, 0xbd, 0xcc, 0x04, 0xbd, 0x4a, 0x6c, 0x76, 0x29, 0xdb, 0x31, 0x3f, 0xfc, 0x2f, 0x30, 0x1a, 0x84, 0xd7, + 0x96, 0xec, 0x50, 0x74, 0xcc, 0x72, 0x05, 0x47, 0x6d, 0xe9, 0xca, 0x2c, 0x5b, 0xd7, 0xcf, 0x6a, 0x98, 0xe9, 0x33, + 0xe5, 0x2d, 0xc8, 0xbe, 0x90, 0xbb, 0x9f, 0xea, 0x8a, 0x05, 0x99, 0x4d, 0xc6, 0x53, 0x22, 0x06, 0x83, 0x56, 0xf2, + 0x31, 0x26, 0x0f, 0x87, 0x7b, 0xcc, 0xa5, 0xd0, 0xfd, 0xf0, 0xfa, 0x00, 0xf5, 0x35, 0xb6, 0x24, 0xd9, 0x56, 0xec, + 0x4f, 0x30, 0x8b, 0x05, 0xe2, 0xe8, 0xe0, 0x17, 0x17, 0x4b, 0x00, 0x59, 0x86, 0x65, 0xa6, 0x85, 0x45, 0x65, 0xaa, + 0x7c, 0x64, 0x0b, 0x26, 0x8f, 0xc7, 0x73, 0xbf, 0xe7, 0x8e, 0xc1, 0x21, 0x24, 0x9a, 0x58, 0xe3, 0x17, 0x3f, 0x0b, + 0xc6, 0x71, 0x28, 0x67, 0xb2, 0xf1, 0x5d, 0x49, 0xa2, 0xb1, 0x31, 0x55, 0xd6, 0x57, 0x89, 0x6a, 0x98, 0x90, 0xc7, + 0x05, 0x39, 0x2c, 0xe8, 0xca, 0x1f, 0x4b, 0x4c, 0x3f, 0x8c, 0x0f, 0x27, 0x63, 0xf2, 0x38, 0x7e, 0x3c, 0x31, 0x70, + 0xc3, 0x7e, 0x8e, 0x7c, 0xb8, 0x22, 0x87, 0xcd, 0x2a, 0xc1, 0x14, 0xd5, 0xf4, 0xcc, 0xaf, 0x24, 0x19, 0xac, 0x06, + 0xe9, 0xe3, 0x56, 0x5e, 0xac, 0x55, 0x8f, 0xf7, 0xe6, 0x98, 0x4f, 0x89, 0x68, 0xdc, 0x18, 0x36, 0xf4, 0x2a, 0xfe, + 0x43, 0x16, 0x51, 0x29, 0x01, 0x91, 0x10, 0xd4, 0xdb, 0xd9, 0x45, 0x96, 0xc4, 0x22, 0x8d, 0xd2, 0x9a, 0xd0, 0x74, + 0xc6, 0x26, 0xe3, 0x79, 0xca, 0xd2, 0xe3, 0xc9, 0xd3, 0xf9, 0xe4, 0x69, 0x74, 0x34, 0x8e, 0xd2, 0xc1, 0x00, 0x92, + 0x8f, 0xc6, 0xe0, 0x62, 0x07, 0xbf, 0xd9, 0x11, 0x0c, 0xdd, 0x0c, 0x59, 0xc2, 0x02, 0x9a, 0xf6, 0x79, 0x4d, 0xd2, + 0xc3, 0x79, 0xa1, 0x7a, 0x12, 0xdf, 0xd2, 0x8d, 0xe7, 0xe0, 0xe2, 0xb7, 0xf0, 0xc2, 0xb5, 0xf0, 0x62, 0xbf, 0x85, + 0x42, 0x93, 0xed, 0x42, 0xfe, 0xff, 0xb8, 0x61, 0xdc, 0x77, 0x97, 0x30, 0x8b, 0xeb, 0x3a, 0x1b, 0xad, 0x0b, 0x59, + 0x49, 0xb8, 0x4d, 0x28, 0x51, 0xd8, 0x28, 0x5e, 0xaf, 0x73, 0xed, 0x22, 0xb6, 0xa8, 0x28, 0x80, 0xbb, 0x40, 0x9c, + 0x62, 0x60, 0xa1, 0x8d, 0x81, 0xdc, 0x5f, 0xbc, 0x90, 0xcc, 0xaa, 0x7d, 0xcc, 0x3d, 0xf2, 0x8f, 0x10, 0x8c, 0x51, + 0xc5, 0x6c, 0x3c, 0x57, 0x58, 0x17, 0x9f, 0x92, 0xf7, 0xfe, 0x1b, 0x47, 0x91, 0x3d, 0x9a, 0x41, 0x4f, 0x10, 0x39, + 0x8f, 0x38, 0x7b, 0x32, 0x79, 0x19, 0xb8, 0x9f, 0xc1, 0x4a, 0x7f, 0xdd, 0x6d, 0xc6, 0xda, 0xf6, 0xe8, 0x5e, 0x18, + 0xa1, 0xe8, 0x5f, 0xf8, 0xce, 0xd4, 0x0b, 0xb8, 0x84, 0x6a, 0x60, 0x37, 0x97, 0x97, 0xbc, 0x04, 0x10, 0xa1, 0x4c, + 0xf4, 0xfb, 0xbd, 0x3f, 0x0c, 0x34, 0x69, 0xc9, 0x8b, 0xd7, 0x99, 0xb0, 0xce, 0x38, 0xd0, 0x54, 0xa0, 0xfe, 0x1f, + 0x2b, 0xfb, 0x4c, 0xc7, 0x64, 0xee, 0x3f, 0x0e, 0x27, 0x24, 0x6a, 0xbe, 0x26, 0x9f, 0x38, 0x4d, 0x3f, 0x71, 0x45, + 0xfb, 0x0f, 0x64, 0xe6, 0x86, 0x43, 0x86, 0xfa, 0x4b, 0xc7, 0x3c, 0x19, 0xbd, 0x4e, 0xcc, 0x66, 0x82, 0x55, 0x73, + 0x88, 0xc2, 0x5e, 0xc0, 0x83, 0xba, 0x96, 0xc5, 0x53, 0x98, 0x7d, 0x50, 0x23, 0x8a, 0x63, 0x36, 0x9e, 0x87, 0x32, + 0x9c, 0x80, 0x7d, 0xef, 0x64, 0x0c, 0xf7, 0x01, 0x19, 0x7e, 0xac, 0x42, 0xec, 0x1c, 0xa4, 0x7d, 0xac, 0x50, 0x31, + 0x01, 0x10, 0x81, 0x90, 0xb7, 0xdf, 0x97, 0x2a, 0x09, 0x5f, 0x97, 0x98, 0x52, 0xa8, 0x0f, 0xfe, 0x13, 0xa9, 0xba, + 0x63, 0xfa, 0xd5, 0xfa, 0xf1, 0x67, 0x42, 0xf1, 0xe9, 0x2e, 0x25, 0xbe, 0x85, 0xe0, 0xce, 0x12, 0x74, 0x10, 0x15, + 0x9a, 0xb1, 0x3d, 0xcc, 0xef, 0x8a, 0xfb, 0xf9, 0x5d, 0xf1, 0xff, 0x8e, 0xdf, 0x15, 0x0f, 0x31, 0x86, 0x95, 0x85, + 0x86, 0x9f, 0x07, 0xe3, 0x20, 0xfa, 0xcf, 0xf9, 0xc4, 0x7b, 0x79, 0xea, 0xab, 0x4c, 0x4c, 0xef, 0x61, 0x9a, 0x7d, + 0x82, 0x82, 0xb0, 0x8a, 0xfb, 0xf4, 0x64, 0x53, 0xd9, 0x5b, 0x2b, 0x19, 0x62, 0x9e, 0x07, 0x58, 0xa3, 0xb0, 0xf2, + 0x80, 0xee, 0x51, 0xb5, 0x41, 0x9c, 0x08, 0x1e, 0xc6, 0xcc, 0x4a, 0xdf, 0x77, 0x3b, 0xa3, 0xc2, 0x7c, 0x90, 0x8b, + 0x82, 0xec, 0xe6, 0xe3, 0xf9, 0x38, 0x0a, 0xb1, 0x01, 0xff, 0x31, 0x63, 0xd5, 0x90, 0xcd, 0x77, 0x32, 0x52, 0x7b, + 0x26, 0x4f, 0x93, 0x7d, 0xd2, 0x3b, 0xe0, 0x1d, 0xf2, 0xf3, 0xfa, 0x63, 0x58, 0x48, 0xc3, 0x6f, 0xc9, 0xcb, 0xb8, + 0xc8, 0xaa, 0xd5, 0x55, 0x96, 0x20, 0xd3, 0x05, 0x2f, 0x3e, 0x9b, 0xe9, 0xf2, 0x3e, 0xd6, 0x07, 0x8c, 0xa7, 0x14, + 0xaf, 0x1b, 0xa2, 0xf4, 0x4d, 0xcb, 0xb3, 0x42, 0x5d, 0x9e, 0x54, 0xcc, 0xf6, 0xac, 0x04, 0xa7, 0x53, 0x30, 0xc1, + 0xd7, 0x3f, 0x5d, 0xef, 0x63, 0xc0, 0x05, 0x85, 0x9a, 0xd3, 0x42, 0xae, 0x0d, 0x96, 0x93, 0x85, 0xee, 0x04, 0xcc, + 0x50, 0x29, 0xf0, 0x02, 0x05, 0x7f, 0xd1, 0xc0, 0x88, 0xbe, 0x74, 0xbf, 0xc9, 0xc0, 0x20, 0x5d, 0x9a, 0x13, 0x61, + 0xec, 0xb8, 0x9d, 0x22, 0x6d, 0x45, 0x39, 0xe3, 0xec, 0xbd, 0xba, 0x52, 0x80, 0x01, 0xde, 0xf6, 0x26, 0x3a, 0x4f, + 0xd0, 0x6b, 0x41, 0xe9, 0xbc, 0x81, 0xbb, 0x59, 0x45, 0x46, 0xb8, 0xf8, 0xb8, 0xf2, 0x58, 0x70, 0xcf, 0x7e, 0x21, + 0x96, 0x46, 0x33, 0x0d, 0xc6, 0x6c, 0x5e, 0xb0, 0x40, 0xa1, 0x02, 0x05, 0x96, 0x73, 0x6d, 0x69, 0x5a, 0x0d, 0xf9, + 0xe1, 0x11, 0x5a, 0x9b, 0x56, 0x03, 0x7e, 0x78, 0x54, 0x47, 0xd9, 0x31, 0x64, 0x99, 0xf9, 0x19, 0xd4, 0xeb, 0x3a, + 0x32, 0x29, 0x26, 0xbb, 0x5f, 0x5f, 0xea, 0x8f, 0xea, 0x16, 0x5c, 0x3f, 0x00, 0x01, 0x6c, 0x00, 0x0e, 0x81, 0x6a, + 0xb0, 0x34, 0x22, 0x58, 0x94, 0x29, 0xb4, 0xaf, 0xa1, 0xf7, 0x46, 0xc3, 0x7f, 0x81, 0xbb, 0x88, 0x5c, 0xfb, 0x9f, + 0x20, 0xf0, 0x57, 0x94, 0x69, 0x65, 0x8a, 0xff, 0x89, 0x56, 0xaf, 0x50, 0xce, 0x9a, 0xd6, 0x7c, 0x10, 0xad, 0x89, + 0x50, 0xcd, 0x18, 0x82, 0x7f, 0x2b, 0xcb, 0xb4, 0xa5, 0xaa, 0x52, 0x1f, 0x1a, 0xaf, 0xb5, 0xc2, 0x59, 0x3e, 0x8e, + 0xbc, 0xd7, 0x18, 0x3a, 0x36, 0x71, 0x96, 0x72, 0x2a, 0x75, 0xfe, 0xd7, 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, 0xb7, + 0x2a, 0xcc, 0x71, 0x6d, 0x01, 0x83, 0x06, 0xab, 0x07, 0xd1, 0xe1, 0x52, 0xda, 0xec, 0x2a, 0x40, 0x6c, 0x4c, 0x21, + 0x96, 0x05, 0xdb, 0x58, 0xf6, 0xec, 0x7b, 0xd5, 0x34, 0xb4, 0x4e, 0x38, 0x11, 0x97, 0x39, 0x44, 0x51, 0x19, 0xc4, + 0xe0, 0x8e, 0xe4, 0xf1, 0x79, 0x8f, 0x44, 0x78, 0x41, 0xc0, 0xad, 0x2c, 0x96, 0xe1, 0x9a, 0xae, 0x46, 0xb7, 0x74, + 0x33, 0xba, 0xa1, 0x63, 0x3a, 0xf9, 0x66, 0x0c, 0x16, 0xd9, 0x3a, 0xf5, 0x8e, 0x6e, 0x46, 0x2b, 0xfa, 0xed, 0x98, + 0x1e, 0xfd, 0x0d, 0x4c, 0xf8, 0xf0, 0x30, 0xa1, 0x17, 0xe0, 0xd8, 0x45, 0x6a, 0xf4, 0xd4, 0xf4, 0x0d, 0x0e, 0xab, + 0x51, 0x3e, 0xe4, 0xa3, 0x9c, 0xf2, 0x51, 0x31, 0xac, 0x46, 0xe0, 0xe9, 0x58, 0x0d, 0xf9, 0xa8, 0xa2, 0x7c, 0x74, + 0x3e, 0xac, 0x46, 0xe7, 0xa4, 0xd9, 0xf4, 0x57, 0x15, 0xbf, 0x2a, 0x59, 0x0a, 0xdb, 0x02, 0x96, 0xaf, 0xe7, 0x15, + 0x95, 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, 0xc3, 0x98, 0x61, 0x33, 0x75, + 0x1a, 0x28, 0x70, 0xb2, 0x91, 0xe7, 0xa2, 0x98, 0x8d, 0x72, 0x0a, 0xef, 0x63, 0x42, 0x22, 0x01, 0x67, 0xd5, 0xac, + 0x1a, 0x15, 0x10, 0x73, 0x84, 0x85, 0xf8, 0x08, 0xfd, 0x52, 0x1f, 0x79, 0x48, 0xe0, 0x19, 0xf6, 0xb5, 0x18, 0xc4, + 0x70, 0xc4, 0xdb, 0xca, 0xaa, 0x79, 0x98, 0x40, 0x65, 0xd5, 0xb0, 0x34, 0x95, 0x15, 0x34, 0x1b, 0x55, 0x7e, 0x65, + 0x15, 0x8e, 0x51, 0x42, 0x48, 0x54, 0xea, 0xca, 0x40, 0x7d, 0x92, 0xb0, 0xb0, 0xd4, 0x95, 0x9d, 0xab, 0x8f, 0xce, + 0xfd, 0xca, 0xce, 0xc1, 0x85, 0x74, 0x90, 0xf8, 0x57, 0xa9, 0x3c, 0x6d, 0x5f, 0x07, 0x1b, 0xab, 0x8a, 0x6e, 0xf9, + 0x6d, 0x55, 0xc4, 0x51, 0x49, 0x5d, 0x0c, 0x68, 0x5c, 0x18, 0x91, 0xa4, 0x7a, 0x8d, 0x82, 0x3f, 0x24, 0x88, 0x4a, + 0x63, 0xf0, 0xea, 0x4c, 0xba, 0x56, 0x6a, 0x45, 0xc5, 0xa0, 0x1c, 0x14, 0x70, 0x7f, 0xca, 0x5b, 0x0b, 0xe9, 0x7b, + 0x88, 0xa8, 0x0c, 0xe5, 0x0d, 0xfe, 0x81, 0xc1, 0x93, 0xd9, 0x3a, 0x0d, 0x93, 0xd1, 0x1d, 0x8d, 0x47, 0x2b, 0x84, + 0x83, 0x61, 0x9b, 0x54, 0xe1, 0xad, 0x5f, 0x40, 0xfa, 0x2d, 0x8d, 0x47, 0x37, 0x34, 0xb5, 0x36, 0xa7, 0x06, 0xea, + 0xaa, 0x37, 0xa6, 0xb7, 0x11, 0xbc, 0xbe, 0x8b, 0x56, 0x14, 0xb6, 0xd2, 0x49, 0x9e, 0x5d, 0x8a, 0x28, 0xa5, 0x88, + 0x40, 0xb8, 0x41, 0xe4, 0xc0, 0x95, 0x46, 0x1b, 0xdc, 0x0c, 0xa0, 0x0c, 0x0d, 0x17, 0xb8, 0x1a, 0xc4, 0xa3, 0x95, + 0x47, 0xa6, 0x56, 0xfa, 0x22, 0x8b, 0xf0, 0xd1, 0xce, 0x46, 0x4b, 0xf1, 0x8c, 0x58, 0x18, 0x57, 0x30, 0x84, 0xba, + 0xb0, 0xd2, 0x14, 0x24, 0x5d, 0xe0, 0xc8, 0x5e, 0x58, 0x54, 0xe1, 0x16, 0x4c, 0x8b, 0xee, 0xc0, 0x3c, 0x0a, 0x14, + 0x0e, 0x2e, 0x41, 0xfa, 0x09, 0x65, 0x3b, 0x47, 0x69, 0x72, 0x78, 0x13, 0x94, 0xee, 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, 0x7a, 0x03, 0xd8, 0xd3, 0x87, 0x47, 0x7b, 0xf3, 0x5d, 0xcc, 0xff, 0x3a, 0x2c, 0xa3, 0xb1, 0xb2, 0xe0, 0xcd, + 0x2d, 0xb1, 0x5b, 0xb1, 0xf1, 0x74, 0x75, 0x5c, 0x4e, 0x57, 0x48, 0xec, 0x0c, 0xdd, 0x62, 0x7c, 0xb1, 0x5a, 0xd2, + 0x04, 0xcf, 0x36, 0x56, 0x2d, 0x56, 0x06, 0x2d, 0x25, 0x65, 0xb8, 0xde, 0x56, 0xe8, 0xff, 0xaf, 0x2e, 0x7e, 0x29, + 0xc0, 0x4b, 0x30, 0x16, 0x00, 0xc2, 0x3d, 0x98, 0x16, 0xa4, 0x36, 0xca, 0xc6, 0x2a, 0x0d, 0x53, 0x5c, 0x04, 0x26, + 0xa5, 0xdf, 0x0f, 0x73, 0x96, 0x12, 0x0f, 0x3a, 0xd4, 0x9d, 0xda, 0xa9, 0x2f, 0x04, 0x01, 0x1e, 0x49, 0x9d, 0x63, + 0x93, 0x6f, 0xc6, 0xf3, 0x40, 0x0d, 0x44, 0x10, 0x65, 0xc7, 0xf8, 0x88, 0x81, 0x8b, 0x22, 0x1d, 0xb7, 0xd3, 0x15, + 0x71, 0xb1, 0x7f, 0xcc, 0x42, 0x9c, 0x24, 0xcc, 0x35, 0xcf, 0x86, 0xac, 0x8a, 0x30, 0x41, 0x17, 0x06, 0x66, 0x79, + 0x43, 0x56, 0x1d, 0x1e, 0x41, 0xa4, 0x56, 0x5b, 0xc6, 0xba, 0xab, 0x8c, 0x6f, 0x01, 0xc8, 0x9a, 0x31, 0x76, 0xf4, + 0xb7, 0xf1, 0x5c, 0x7d, 0x13, 0x85, 0x7c, 0x76, 0xf4, 0x37, 0x48, 0x3e, 0xfe, 0x16, 0x99, 0x39, 0x48, 0x6e, 0x14, + 0x74, 0xd9, 0x9c, 0x75, 0x0d, 0xa5, 0x89, 0x6b, 0xaf, 0xd4, 0x6b, 0x4f, 0x9a, 0xb5, 0x57, 0xa0, 0x3b, 0xb5, 0xe1, + 0x3d, 0x94, 0xed, 0x2c, 0x98, 0xa0, 0xa3, 0xd9, 0x1d, 0xe8, 0xe0, 0x9d, 0x22, 0xe8, 0x45, 0x12, 0x1a, 0x8f, 0x50, + 0x65, 0xd4, 0x0b, 0x3b, 0xb2, 0x9b, 0x75, 0xc9, 0x3c, 0x03, 0xe6, 0xd8, 0x9e, 0x43, 0x62, 0x98, 0xab, 0x83, 0x3a, + 0x65, 0xe5, 0x30, 0xc7, 0x03, 0x78, 0xc3, 0xe4, 0x50, 0x0c, 0x72, 0x8d, 0xf2, 0x7d, 0xc1, 0x8a, 0x61, 0x39, 0xc8, + 0x35, 0x37, 0x33, 0x6d, 0xc6, 0xa6, 0x4d, 0x74, 0x78, 0xe6, 0x35, 0x9b, 0xad, 0x7b, 0xc0, 0xc7, 0x82, 0x27, 0xb3, + 0xef, 0xf9, 0xf8, 0x1a, 0x38, 0x99, 0xed, 0x6d, 0xb4, 0xa2, 0x77, 0x51, 0x4a, 0x6f, 0xa2, 0x0d, 0x5d, 0x45, 0x17, + 0xc6, 0xc4, 0x38, 0xa9, 0xe1, 0x1c, 0x80, 0x56, 0x01, 0x24, 0x9e, 0xfa, 0xf5, 0x9e, 0x27, 0x55, 0xb8, 0xa2, 0x29, + 0xb8, 0x0d, 0xfb, 0xf6, 0x99, 0x57, 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, 0xe9, 0x23, 0x1f, 0x10, 0x2b, + 0x2e, 0xe1, 0x6c, 0x04, 0xea, 0x68, 0x85, 0x4e, 0xbf, 0x55, 0x61, 0xa1, 0x0f, 0xf0, 0xed, 0x6d, 0x94, 0xd0, 0xbb, + 0x28, 0xf7, 0xc8, 0xda, 0xaa, 0x66, 0x72, 0x7a, 0x96, 0x85, 0xbc, 0x7d, 0xa0, 0x97, 0x4b, 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, 0x4f, 0x8b, 0xb6, 0xb7, 0x2b, 0x8c, 0x26, + 0x18, 0x7b, 0xa2, 0x7d, 0x1e, 0x29, 0x47, 0x71, 0x91, 0x84, 0xd9, 0xe8, 0x56, 0x9d, 0xe7, 0x34, 0x1b, 0xdd, 0xe9, + 0x5f, 0x15, 0x1d, 0xd3, 0xef, 0x74, 0x40, 0x1b, 0x25, 0x7d, 0xeb, 0x38, 0x1b, 0xd0, 0x7a, 0xb1, 0x34, 0xfe, 0xd7, + 0x72, 0x74, 0x4b, 0xe5, 0xe8, 0xce, 0xb7, 0xa4, 0x9a, 0x4c, 0x8b, 0x63, 0x81, 0x86, 0x54, 0x9d, 0xdf, 0x17, 0xc0, + 0xcf, 0x95, 0xc6, 0x77, 0xda, 0x7c, 0xef, 0xb5, 0xff, 0xbc, 0x93, 0x27, 0x50, 0x2c, 0x51, 0xc1, 0xaa, 0x11, 0xd8, + 0xb1, 0x6f, 0xf2, 0xb8, 0x30, 0xa3, 0x14, 0x53, 0x6b, 0xd2, 0x8f, 0x81, 0x2b, 0xa6, 0xbd, 0x02, 0x5c, 0x2d, 0x77, + 0x3b, 0x15, 0x43, 0x13, 0xf6, 0xec, 0x18, 0xa2, 0x9e, 0x1b, 0xc7, 0x28, 0xd9, 0x70, 0x0f, 0x88, 0xb5, 0xcc, 0x5b, + 0xb9, 0x04, 0x24, 0xf0, 0xd6, 0xc3, 0xa4, 0x00, 0x8c, 0xc1, 0x72, 0x45, 0x74, 0x1e, 0x0f, 0x7d, 0x42, 0xbd, 0xd0, + 0xa8, 0x13, 0xb2, 0xb1, 0x25, 0x70, 0xfc, 0x61, 0x7d, 0x08, 0x04, 0xaf, 0xf2, 0x5c, 0x7f, 0xa5, 0x75, 0xfd, 0xa5, + 0xd2, 0x73, 0xc7, 0x72, 0x5d, 0x3f, 0x6b, 0x53, 0xa3, 0x97, 0x60, 0xe1, 0xbb, 0x55, 0xe6, 0x91, 0xdc, 0x22, 0xa4, + 0x2a, 0xb0, 0x52, 0xb7, 0x90, 0x60, 0xfe, 0x95, 0x9c, 0xad, 0xca, 0x7c, 0xf5, 0xc8, 0x83, 0x72, 0x36, 0x3d, 0xfd, + 0x0d, 0x09, 0xda, 0x5d, 0x47, 0x9a, 0xc7, 0x5b, 0x74, 0xf8, 0xec, 0x5a, 0x4b, 0xcc, 0xbd, 0x44, 0xc5, 0xf3, 0x29, + 0x60, 0xab, 0xe7, 0xd9, 0x95, 0xf2, 0xb1, 0xda, 0xc7, 0xf1, 0x33, 0xe7, 0x4f, 0x5c, 0x85, 0x1b, 0xd1, 0x50, 0x82, + 0x80, 0x37, 0x87, 0xb1, 0x2b, 0x54, 0x01, 0x0d, 0xcd, 0x0d, 0x1c, 0xe7, 0x6a, 0x58, 0x69, 0x02, 0xa6, 0xa5, 0x3c, + 0x3a, 0xc0, 0xa1, 0xc9, 0xa3, 0x76, 0xd3, 0xb0, 0x32, 0x74, 0xad, 0xd1, 0xe7, 0xb6, 0xd2, 0x19, 0x6f, 0x36, 0xfc, + 0xf0, 0x68, 0x50, 0xe1, 0x4f, 0xd2, 0x1c, 0x8d, 0x76, 0x6e, 0xb8, 0xd3, 0x08, 0xcc, 0x5c, 0xc9, 0x35, 0xd9, 0x1f, + 0x25, 0x2f, 0xbf, 0xa7, 0x17, 0x16, 0xd0, 0x9f, 0xff, 0x5c, 0x4c, 0x38, 0x69, 0x89, 0x09, 0xd1, 0xd2, 0x41, 0x8b, + 0x0e, 0xf6, 0x94, 0x57, 0xf6, 0x25, 0x5e, 0x3a, 0xc7, 0xff, 0xbe, 0x1e, 0x6b, 0x5f, 0x81, 0xd0, 0xea, 0xe4, 0x61, + 0x7b, 0xb2, 0x40, 0xd4, 0x80, 0x6a, 0x76, 0x55, 0x8e, 0x32, 0xed, 0xac, 0xc8, 0xb6, 0x21, 0x73, 0xdd, 0xcf, 0xd2, + 0xb0, 0x99, 0xec, 0x58, 0x58, 0x66, 0x18, 0xac, 0x9d, 0x2a, 0xfa, 0x1c, 0xb4, 0xfc, 0x08, 0x9e, 0x37, 0x95, 0x67, + 0x3e, 0x9b, 0x65, 0xc4, 0x0b, 0x74, 0xc1, 0xa9, 0x58, 0x36, 0xa5, 0x63, 0xe5, 0x6e, 0x57, 0xa2, 0xb1, 0x44, 0x19, + 0x05, 0x41, 0x6d, 0x83, 0xb0, 0xeb, 0xd2, 0x3d, 0xe9, 0xd3, 0x3e, 0x3e, 0xad, 0x40, 0xdf, 0xe3, 0xfb, 0x0c, 0x24, + 0xa6, 0x9e, 0xe4, 0xa1, 0x6a, 0x34, 0x47, 0x27, 0xcf, 0xe3, 0x54, 0xe3, 0xf3, 0x2b, 0xd9, 0x59, 0xf3, 0x6e, 0x35, + 0xa6, 0xf8, 0x8f, 0xd4, 0xed, 0x3b, 0x97, 0xa1, 0x89, 0xfe, 0x5a, 0x1e, 0xb4, 0x14, 0x16, 0x1c, 0xb7, 0x8d, 0xbf, + 0x7e, 0x9b, 0x39, 0xc4, 0xb0, 0x74, 0x39, 0xbc, 0x09, 0x1d, 0xba, 0xbb, 0xca, 0xde, 0x5c, 0x1f, 0x51, 0xa7, 0x2e, + 0xd6, 0x6d, 0x40, 0xc9, 0x92, 0x77, 0xeb, 0xf4, 0xc4, 0x4a, 0xdf, 0x1d, 0x86, 0x7b, 0xf3, 0xa8, 0xd9, 0xdd, 0xdd, + 0x6e, 0x42, 0xda, 0xf6, 0xc1, 0x78, 0x5f, 0xc2, 0x42, 0x9c, 0x77, 0xd8, 0xc1, 0xf7, 0x61, 0xf5, 0x98, 0x0f, 0x7e, + 0xc6, 0x71, 0x86, 0xd1, 0xcf, 0x94, 0xa1, 0xcf, 0xcb, 0x42, 0x5e, 0xa9, 0x4e, 0xf9, 0x42, 0xb7, 0x96, 0xa9, 0xf7, + 0x9b, 0xf8, 0x4d, 0x2b, 0x40, 0x8c, 0xd7, 0x15, 0x2b, 0xc5, 0x1b, 0x5a, 0x61, 0x5c, 0x03, 0xb7, 0xc9, 0xa1, 0x96, + 0x6a, 0x81, 0xa8, 0xcb, 0x4f, 0x1e, 0xf3, 0xc8, 0xa8, 0x33, 0xe1, 0xbb, 0xc7, 0xdc, 0x97, 0xae, 0xed, 0x37, 0xf1, + 0x53, 0x4d, 0x3b, 0xdc, 0x1f, 0xe8, 0x8e, 0xd6, 0x3d, 0xdc, 0x3c, 0x9b, 0x9f, 0x47, 0xe6, 0x8b, 0x01, 0x36, 0x6b, + 0x9f, 0x71, 0xd9, 0x33, 0xdc, 0xf7, 0xa6, 0x07, 0x63, 0x01, 0x81, 0xc4, 0x0c, 0xbd, 0x0c, 0x5c, 0xe0, 0x02, 0x77, + 0x85, 0x01, 0x43, 0x5c, 0xd3, 0x92, 0x33, 0x6d, 0x65, 0xeb, 0x23, 0x6f, 0xa3, 0x42, 0xb0, 0xae, 0x3b, 0x6e, 0x92, + 0x1c, 0x82, 0x13, 0xb6, 0xdc, 0xfb, 0xda, 0x6b, 0x67, 0xf8, 0x8f, 0x81, 0x70, 0x6e, 0x89, 0x9e, 0x51, 0xdb, 0x63, + 0xad, 0xee, 0x35, 0xbc, 0xca, 0x5d, 0xe4, 0x59, 0xbf, 0x99, 0x97, 0x86, 0x7d, 0xc1, 0x6b, 0x29, 0x38, 0x34, 0xb6, + 0x5b, 0xe1, 0x16, 0x8b, 0x77, 0xb4, 0x5a, 0x59, 0x6b, 0xab, 0xbd, 0x56, 0x2a, 0x7a, 0xff, 0x9a, 0xe3, 0xc4, 0x59, + 0x0a, 0xdb, 0x0f, 0x1f, 0x2e, 0xd8, 0x35, 0x01, 0x0c, 0x5a, 0x4c, 0x16, 0x28, 0x41, 0x25, 0x6b, 0x55, 0xbb, 0x9d, + 0x12, 0xbf, 0xdc, 0xcf, 0xba, 0xcc, 0x76, 0x1e, 0xbf, 0x6e, 0xd2, 0x3e, 0xf1, 0x39, 0xfa, 0x61, 0x7e, 0x67, 0x9d, + 0x94, 0x9c, 0x61, 0x5c, 0xcb, 0xff, 0xaf, 0xa2, 0x97, 0x45, 0x96, 0x46, 0x5b, 0xc3, 0x83, 0xd9, 0x50, 0x9b, 0x3e, + 0x34, 0x46, 0xe5, 0x96, 0x8d, 0x22, 0xa2, 0xd5, 0x2d, 0x08, 0x66, 0x14, 0xf7, 0x25, 0xda, 0xbc, 0x52, 0x65, 0xe1, + 0x1d, 0x3e, 0xb1, 0xd1, 0x1b, 0xb6, 0x27, 0x84, 0xf2, 0xfd, 0xd3, 0xc2, 0xac, 0x5a, 0x2a, 0x1a, 0x6c, 0x97, 0xf0, + 0x2e, 0x46, 0x95, 0x7e, 0xc2, 0x64, 0xcb, 0x82, 0xa9, 0xfe, 0x7f, 0x5f, 0x64, 0x69, 0x9b, 0xa2, 0x03, 0xd3, 0xd9, + 0xf4, 0xe9, 0xa4, 0x5b, 0x5c, 0x67, 0xc0, 0x22, 0x82, 0x2d, 0x15, 0x8e, 0x47, 0xa9, 0xdd, 0x20, 0x61, 0x22, 0xb8, + 0x89, 0x7a, 0xd9, 0xd1, 0x32, 0x25, 0xab, 0x02, 0x9e, 0x5f, 0xb9, 0xca, 0x74, 0x1c, 0x0d, 0xfd, 0xfe, 0x55, 0x6a, + 0x42, 0xbf, 0x52, 0x2f, 0x55, 0x71, 0x1e, 0x46, 0xd5, 0xa1, 0xc2, 0x18, 0xad, 0x68, 0x0a, 0xc7, 0x60, 0x76, 0x11, + 0xa6, 0x78, 0x39, 0xdb, 0x26, 0xec, 0x33, 0x06, 0x72, 0xa5, 0x0d, 0xea, 0x35, 0x25, 0xda, 0xb0, 0xf6, 0x66, 0x4e, + 0x09, 0xbd, 0x60, 0xa5, 0x7f, 0x17, 0xda, 0x80, 0x40, 0x51, 0x36, 0x53, 0xa6, 0xe7, 0xba, 0x9d, 0x17, 0x34, 0xa1, + 0x05, 0x5d, 0x93, 0x1a, 0xf4, 0xbd, 0x4e, 0xce, 0x8e, 0x4e, 0x76, 0x66, 0xd6, 0x63, 0x56, 0x0c, 0x27, 0xd3, 0x18, + 0xae, 0x69, 0xb1, 0xbb, 0xa6, 0xad, 0x9a, 0x37, 0xae, 0xc6, 0xc6, 0x69, 0xd0, 0x2e, 0x90, 0xb6, 0x69, 0x6e, 0x3f, + 0xf5, 0xb8, 0xfd, 0x4d, 0xcd, 0x56, 0xd3, 0xde, 0x66, 0xb7, 0xeb, 0xa5, 0x60, 0x23, 0xea, 0xf1, 0xf1, 0x1b, 0x25, + 0x5d, 0xb7, 0x5c, 0x7e, 0x0a, 0xcf, 0x1e, 0x5f, 0xbf, 0xf2, 0xc1, 0xe5, 0x68, 0xd5, 0xe6, 0xee, 0x57, 0xfb, 0xc8, + 0x72, 0x9f, 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, 0x07, 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, 0xe4, 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, 0x7b, 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, 0x95, 0x27, 0xaf, 0x87, 0x01, 0x91, 0x9f, 0xb3, 0x34, 0x5c, 0xa3, 0x20, 0x38, 0xb5, + 0xda, 0x81, 0x34, 0x1f, 0x01, 0x32, 0x3f, 0x4e, 0xc3, 0x77, 0x5a, 0x9c, 0x43, 0xb6, 0x4a, 0xe3, 0xc4, 0x56, 0x46, + 0x3d, 0x04, 0x77, 0xde, 0x2b, 0x1e, 0x43, 0xe0, 0xc3, 0x0f, 0xb8, 0x19, 0x54, 0x74, 0x5b, 0x62, 0xa2, 0xb4, 0x79, + 0xd4, 0x2d, 0x1f, 0x35, 0x84, 0x4a, 0x56, 0x86, 0x17, 0x43, 0x7b, 0xf7, 0x04, 0x46, 0x95, 0x13, 0xc8, 0x0c, 0x8b, + 0xc3, 0xa3, 0x61, 0xaa, 0x04, 0x45, 0x43, 0x39, 0x5c, 0xa1, 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, 0x57, + 0x66, 0xa7, 0xe6, 0x5a, 0x7a, 0xa1, 0x96, 0xe3, 0x33, 0x9d, 0x06, 0xa3, 0x78, 0xea, 0x52, 0xf4, 0x5b, 0xb5, 0x9f, + 0xfd, 0xb7, 0x98, 0x52, 0x23, 0x36, 0xb5, 0xb7, 0x88, 0x61, 0xd5, 0x7e, 0xc8, 0xaa, 0x1c, 0xb4, 0xbb, 0xa0, 0x6c, + 0xac, 0x8c, 0xf3, 0x7c, 0x23, 0x98, 0x39, 0x68, 0x1b, 0xab, 0xa6, 0x0f, 0xbd, 0x11, 0xa3, 0xf6, 0xc6, 0x54, 0xe3, + 0x9e, 0xc0, 0x4f, 0x1b, 0x34, 0xdd, 0x8b, 0x3c, 0x47, 0x3d, 0xf2, 0xee, 0x7f, 0xe6, 0xc8, 0xce, 0xe4, 0x93, 0x58, + 0x26, 0x75, 0xfb, 0x98, 0x04, 0x0b, 0x55, 0xc7, 0xe8, 0xc2, 0x8d, 0x4c, 0x69, 0x3f, 0xf7, 0xa6, 0x1f, 0xf1, 0x4c, + 0x1e, 0xb6, 0x43, 0xa3, 0xbe, 0x34, 0xac, 0x25, 0x45, 0xd4, 0x17, 0xf4, 0xd6, 0x54, 0x47, 0x47, 0xd4, 0xeb, 0x08, + 0xac, 0xae, 0x68, 0x8b, 0x1a, 0x80, 0xc9, 0xb8, 0xb6, 0xb5, 0xf9, 0x1c, 0x4c, 0x6d, 0x55, 0x05, 0x4f, 0xe9, 0xbe, + 0x50, 0xba, 0x37, 0xa9, 0xeb, 0xd6, 0x10, 0x5b, 0xc0, 0x80, 0xc0, 0x8d, 0x9e, 0x9a, 0xfe, 0xa0, 0x89, 0x0a, 0x40, + 0x83, 0xc6, 0xed, 0x4c, 0xe7, 0x48, 0xf4, 0x3b, 0xb5, 0x69, 0x9b, 0xa9, 0x5e, 0x55, 0x3e, 0x80, 0x8a, 0x3f, 0x4b, + 0x67, 0x17, 0x66, 0xc4, 0x02, 0x18, 0xf7, 0xc0, 0x99, 0xea, 0x9d, 0x64, 0x60, 0x3d, 0x91, 0xe7, 0x59, 0xc9, 0x13, + 0x29, 0x60, 0x46, 0xe4, 0xd5, 0x95, 0x14, 0x30, 0x0c, 0x6a, 0x00, 0xd0, 0xa2, 0xb9, 0x8c, 0x26, 0xfc, 0xab, 0x9a, + 0xde, 0x97, 0x87, 0x7f, 0xa5, 0x73, 0x7d, 0x3d, 0xae, 0xc1, 0x50, 0x79, 0x53, 0xf1, 0xbd, 0x4c, 0x5f, 0xf3, 0x27, + 0x5e, 0xa6, 0x95, 0xdc, 0x14, 0x7b, 0x59, 0xbe, 0xfa, 0x9a, 0x3f, 0xd5, 0x79, 0x8e, 0x9e, 0xd4, 0x34, 0x8d, 0xef, + 0xf6, 0xb2, 0x7c, 0xf3, 0xf5, 0x13, 0x9b, 0xe7, 0xab, 0x71, 0x4d, 0x6f, 0x38, 0xff, 0xe8, 0x32, 0x4d, 0x74, 0x55, + 0xe3, 0x27, 0xdf, 0xd8, 0x5c, 0x4f, 0x6a, 0x7a, 0x25, 0x45, 0xb5, 0xda, 0x2b, 0xea, 0xe8, 0xeb, 0xa3, 0x6f, 0xf8, + 0xd7, 0xa6, 0x7b, 0x47, 0x35, 0xfd, 0x73, 0x13, 0x17, 0x15, 0x2f, 0xf6, 0x8a, 0xfb, 0xdb, 0x37, 0xdf, 0x3c, 0xb1, + 0x19, 0x9f, 0xd4, 0xf4, 0x8e, 0xc7, 0x1d, 0x6d, 0x9f, 0x3c, 0x7d, 0xc2, 0xff, 0x56, 0xd7, 0xf4, 0x17, 0xe6, 0x07, + 0x47, 0x3d, 0xc9, 0x3c, 0x3d, 0x7c, 0x22, 0x9b, 0xa8, 0x01, 0x43, 0x0f, 0x0d, 0x20, 0x97, 0x56, 0x4d, 0x73, 0x8f, + 0x57, 0x2e, 0xb8, 0x7d, 0x9f, 0xc5, 0x69, 0xbc, 0x86, 0x83, 0x60, 0x8b, 0xc6, 0x59, 0x05, 0x70, 0xaa, 0xc0, 0x7b, + 0x46, 0x25, 0xcd, 0x4a, 0xf9, 0x0f, 0xce, 0x3f, 0xc2, 0xa0, 0x21, 0xa4, 0x8d, 0x8a, 0x0c, 0xf4, 0x76, 0xad, 0x23, + 0x1b, 0xa1, 0xff, 0x66, 0x33, 0x0e, 0x8e, 0x0f, 0xa3, 0xd7, 0xef, 0x87, 0x05, 0x13, 0x61, 0x41, 0x08, 0xfd, 0x23, + 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, 0x73, 0x75, 0xad, 0x7d, 0x7b, 0x11, 0x16, 0x34, 0xd0, 0x6d, 0x87, 0xa0, 0x03, + 0x91, 0xff, 0x02, 0x3c, 0x05, 0x06, 0x3e, 0x2c, 0xec, 0x4a, 0xee, 0xfb, 0xab, 0xff, 0x62, 0x58, 0x47, 0x17, 0x7e, + 0xf4, 0x17, 0xeb, 0xc2, 0x9e, 0x91, 0xa9, 0x3c, 0x2e, 0x87, 0x93, 0xe9, 0x60, 0x20, 0x5d, 0x1c, 0xb7, 0x93, 0x6c, + 0xf1, 0xcb, 0x42, 0x2e, 0x97, 0xa8, 0xfb, 0xc6, 0x79, 0x9d, 0xeb, 0xbf, 0x91, 0x76, 0x3e, 0x78, 0x7d, 0xf2, 0xdb, + 0xd9, 0xe9, 0xc9, 0x4b, 0x70, 0x3e, 0xf8, 0xf0, 0xe2, 0xfb, 0x17, 0xef, 0x55, 0x70, 0x77, 0x35, 0xe7, 0xfd, 0xbe, + 0x93, 0xfa, 0x84, 0x7c, 0x58, 0x91, 0xc3, 0x30, 0x7e, 0x5c, 0x28, 0xa3, 0x07, 0x72, 0xcc, 0x2c, 0x14, 0x32, 0x54, + 0x51, 0xdb, 0xdf, 0xe5, 0x70, 0xe2, 0x81, 0x59, 0xdc, 0x35, 0x44, 0xb8, 0x7e, 0xcb, 0x6d, 0x90, 0x35, 0x39, 0xf3, + 0xfa, 0xc1, 0xc9, 0x54, 0x3a, 0xb6, 0xb0, 0x60, 0x50, 0x36, 0xb4, 0xe9, 0x24, 0x5b, 0x14, 0x4b, 0xdb, 0x2e, 0xb7, + 0x40, 0x46, 0x69, 0x76, 0x71, 0x11, 0x2a, 0xe8, 0xea, 0x19, 0x68, 0x00, 0x4c, 0xa3, 0x0a, 0xd7, 0x22, 0x3e, 0xf7, + 0xcb, 0x8f, 0xc6, 0x5e, 0xf3, 0x6e, 0x51, 0xf7, 0x64, 0x9a, 0x55, 0x35, 0x06, 0x74, 0x30, 0xa1, 0xdc, 0x0d, 0xba, + 0x09, 0x26, 0xa3, 0xda, 0xf2, 0xcb, 0xa2, 0x5a, 0x9a, 0xe6, 0xb8, 0x61, 0xa8, 0xbc, 0x92, 0x37, 0xb2, 0x81, 0xc8, + 0x40, 0x32, 0x0c, 0x7b, 0x34, 0x46, 0x91, 0xfa, 0xc1, 0xbe, 0x77, 0xfc, 0x36, 0x97, 0x10, 0x4d, 0x31, 0x03, 0xe9, + 0xfc, 0x89, 0x50, 0xce, 0xe5, 0x92, 0xf1, 0x85, 0x58, 0xce, 0xc0, 0xed, 0x7c, 0x21, 0x96, 0x11, 0x06, 0xe5, 0xcb, + 0x20, 0x56, 0x09, 0xd8, 0xbd, 0x38, 0x08, 0xdf, 0x4e, 0x68, 0x03, 0xbb, 0x81, 0x24, 0x1b, 0x94, 0x76, 0xa5, 0x21, + 0xca, 0x9d, 0xf2, 0x68, 0x83, 0xc8, 0x43, 0xac, 0x5a, 0x54, 0x6d, 0x4f, 0x36, 0x73, 0x31, 0xc1, 0x55, 0x16, 0x33, + 0x39, 0x8d, 0x8f, 0x59, 0x31, 0x8d, 0xa1, 0x94, 0x38, 0x4d, 0xc3, 0x98, 0x4e, 0xa8, 0x20, 0x24, 0x61, 0x7c, 0x11, + 0x2f, 0x69, 0x82, 0x52, 0x82, 0x10, 0x42, 0x7e, 0x8c, 0xd0, 0x36, 0x07, 0x96, 0xbc, 0xdd, 0x7e, 0x9e, 0x7e, 0x6e, + 0xcf, 0x70, 0x19, 0x15, 0xa1, 0x5b, 0x74, 0xd6, 0xf0, 0x6f, 0x44, 0x05, 0x8d, 0xb1, 0x62, 0x08, 0x02, 0x5e, 0x60, + 0x54, 0xc2, 0x82, 0xc4, 0xac, 0x82, 0x28, 0x02, 0xe5, 0x22, 0x5e, 0xb2, 0x82, 0x36, 0x6d, 0x4e, 0x63, 0x6d, 0x12, + 0xd4, 0x73, 0x58, 0x6a, 0x07, 0x52, 0xa9, 0x10, 0x7b, 0x7c, 0x2e, 0xa2, 0x6b, 0x6d, 0x68, 0x00, 0x28, 0x50, 0x4a, + 0x2e, 0x7e, 0xf3, 0xf9, 0x1e, 0x6e, 0x0a, 0xfa, 0x9f, 0x6d, 0x4d, 0xb4, 0xb3, 0x5c, 0x1d, 0x7a, 0x8b, 0x25, 0x8d, + 0xf3, 0x1c, 0x42, 0xb1, 0x19, 0x04, 0x72, 0x91, 0x55, 0x10, 0xd1, 0xe2, 0x2e, 0x30, 0x21, 0xe1, 0xa0, 0x4d, 0xbf, + 0x40, 0x6a, 0x43, 0x4c, 0xae, 0x3c, 0x31, 0xb0, 0xdb, 0x2a, 0x41, 0xc0, 0x91, 0x9e, 0x67, 0x7f, 0x35, 0x31, 0xd6, + 0x34, 0x35, 0x33, 0xf1, 0x36, 0x14, 0xa2, 0x41, 0x0b, 0xa2, 0x19, 0xbc, 0x7f, 0xae, 0x38, 0x5e, 0x75, 0xe0, 0x07, + 0xbc, 0x73, 0x71, 0xe6, 0xd5, 0xcc, 0x23, 0x72, 0xea, 0xa3, 0x1c, 0xd1, 0x2f, 0x79, 0x58, 0x8d, 0x74, 0x32, 0xc6, + 0x4a, 0xe2, 0xa0, 0xb7, 0xc1, 0x82, 0x39, 0xa1, 0x6b, 0x1e, 0x5a, 0x3e, 0xfe, 0x25, 0x32, 0x19, 0x25, 0x35, 0x56, + 0x74, 0xa5, 0xc5, 0x88, 0xf3, 0x1a, 0x66, 0x69, 0xb2, 0xa2, 0x8b, 0x85, 0x26, 0xcd, 0x42, 0x99, 0x06, 0xf8, 0x04, + 0x5a, 0x8c, 0xdc, 0x43, 0x4d, 0x1b, 0x08, 0x0d, 0xfb, 0x43, 0xc0, 0x47, 0xee, 0xa1, 0xc3, 0xff, 0xcf, 0xb3, 0x0b, + 0x44, 0xda, 0x9b, 0x9b, 0xc8, 0x78, 0xa4, 0x6e, 0xe0, 0xa0, 0x18, 0x1f, 0xfb, 0x66, 0xe2, 0x67, 0xce, 0xe8, 0x43, + 0x52, 0xf9, 0x0e, 0x1f, 0x2c, 0x7f, 0xbc, 0xa9, 0x99, 0x95, 0x11, 0xac, 0x87, 0xdd, 0x0e, 0x17, 0x44, 0xdb, 0x05, + 0x90, 0x7a, 0xc6, 0xab, 0x85, 0x6f, 0xbc, 0x1a, 0xdf, 0x63, 0xbc, 0xea, 0xce, 0xd4, 0x30, 0x27, 0x5b, 0xd4, 0x67, + 0x29, 0x79, 0x7e, 0x8e, 0x32, 0xc1, 0xa6, 0xcb, 0x59, 0x49, 0x55, 0x2a, 0xa1, 0xbd, 0xd8, 0xcf, 0x18, 0xdf, 0x12, + 0x8c, 0xb3, 0xe2, 0x30, 0x12, 0xa8, 0x4a, 0x25, 0x75, 0xd8, 0x2b, 0x40, 0x3d, 0x06, 0xef, 0x0d, 0x86, 0xa8, 0x91, + 0xb1, 0x9b, 0x36, 0x10, 0x1a, 0x1a, 0xeb, 0xd1, 0x9e, 0xb5, 0x1e, 0xdd, 0xed, 0x2a, 0xe3, 0x6f, 0x27, 0x37, 0x45, + 0x82, 0xa8, 0xc2, 0x6a, 0x34, 0x01, 0xde, 0x34, 0xb1, 0xb7, 0x25, 0xa7, 0xb4, 0xc0, 0xf0, 0xd9, 0x7f, 0x84, 0xa5, + 0x53, 0x49, 0x94, 0x64, 0x5e, 0x46, 0x03, 0x77, 0x0e, 0x3e, 0x8f, 0x2b, 0x58, 0x03, 0x10, 0xc9, 0x11, 0x3d, 0x5c, + 0xff, 0x08, 0xa5, 0xcb, 0x2c, 0xc9, 0x5c, 0x42, 0x66, 0x2e, 0xd2, 0x76, 0xd6, 0xc1, 0xc4, 0x99, 0xd4, 0x7a, 0x63, + 0x21, 0x87, 0x06, 0xf9, 0x01, 0x94, 0x21, 0x0e, 0x9f, 0x7c, 0x30, 0xa1, 0x52, 0x85, 0x52, 0x6d, 0x74, 0xb3, 0x1b, + 0x78, 0xe5, 0x43, 0x76, 0xc5, 0xcb, 0x2a, 0xbe, 0x5a, 0x1b, 0x4b, 0x62, 0xce, 0xee, 0x73, 0xdb, 0xa3, 0xc2, 0xbc, + 0x7a, 0xf3, 0xe2, 0xfb, 0x93, 0xc6, 0xab, 0x7d, 0xc4, 0xd1, 0x10, 0x6c, 0x2b, 0xc6, 0x18, 0xbd, 0xc5, 0xa7, 0xc1, + 0x44, 0xb9, 0x46, 0xa0, 0x77, 0x29, 0xe8, 0xb7, 0x3f, 0xd7, 0x13, 0xf0, 0x8a, 0xeb, 0xe5, 0x97, 0x7c, 0x04, 0x2c, + 0x51, 0xa1, 0x67, 0x85, 0xb9, 0x59, 0x99, 0xdf, 0xdb, 0xad, 0xc8, 0x4c, 0xbb, 0xd2, 0xc8, 0x40, 0xbc, 0xda, 0x0e, + 0x63, 0xe1, 0xd2, 0x35, 0xdd, 0x0e, 0x76, 0xb5, 0xf2, 0x2c, 0x91, 0x77, 0xbb, 0x12, 0x3a, 0x64, 0x07, 0xdc, 0x7b, + 0x19, 0xdf, 0xc2, 0xcb, 0xd2, 0xeb, 0x66, 0x33, 0x78, 0x02, 0x98, 0x09, 0x17, 0xce, 0xb2, 0x38, 0x66, 0x3c, 0x09, + 0x55, 0x6c, 0xae, 0x86, 0xc8, 0x5b, 0x11, 0x5a, 0xb3, 0xbf, 0x42, 0x31, 0x02, 0xbb, 0x93, 0xd3, 0x8f, 0xd9, 0x7a, + 0xbe, 0x02, 0xd4, 0xfc, 0xab, 0x4c, 0x00, 0xcd, 0xb5, 0x6b, 0xc1, 0x36, 0x85, 0x36, 0xd7, 0xf5, 0xb3, 0x78, 0x1d, + 0x27, 0xa0, 0xba, 0x01, 0x6f, 0x91, 0x3b, 0x2d, 0xba, 0x32, 0xe8, 0xa2, 0xf4, 0x81, 0x72, 0x2c, 0x29, 0x74, 0xf4, + 0xbd, 0x27, 0xd4, 0xb9, 0x67, 0x00, 0x97, 0x34, 0x6a, 0x9e, 0x6a, 0x29, 0x63, 0x01, 0xb0, 0xd0, 0xc1, 0x5c, 0x91, + 0xad, 0xe8, 0xd6, 0x60, 0x52, 0xc0, 0x5b, 0x03, 0xfc, 0x21, 0xb2, 0x4a, 0xdd, 0x15, 0xcb, 0xb0, 0xf4, 0xec, 0xaf, + 0xfb, 0xfd, 0xd8, 0xb3, 0xbf, 0xbe, 0xd0, 0xb4, 0x2e, 0x6e, 0x37, 0x80, 0xd4, 0x18, 0x40, 0xe4, 0x44, 0x0f, 0x84, + 0x89, 0x28, 0xd6, 0xf4, 0xfd, 0x3b, 0x31, 0x59, 0x14, 0x08, 0xfd, 0x5e, 0xbd, 0x9e, 0x94, 0x04, 0x74, 0x6a, 0x15, + 0x9b, 0x0d, 0xb4, 0xd9, 0x07, 0x04, 0x44, 0xf5, 0x33, 0xb2, 0xc5, 0x52, 0x39, 0x17, 0xab, 0xf0, 0xe1, 0x63, 0x0a, + 0x01, 0x85, 0x3b, 0x6a, 0x74, 0xde, 0x86, 0x48, 0xa0, 0xac, 0x50, 0xc4, 0x9a, 0x17, 0x6b, 0x49, 0xc8, 0x62, 0xbc, + 0x44, 0xc1, 0x95, 0x03, 0x76, 0xe5, 0x6c, 0x32, 0x2c, 0x23, 0xce, 0xc2, 0xfb, 0xbf, 0x99, 0x2c, 0x09, 0x6a, 0xae, + 0xfc, 0x40, 0x8e, 0x7b, 0x99, 0x1a, 0x7b, 0xaa, 0x51, 0x83, 0x60, 0x32, 0x82, 0xc0, 0x70, 0xc3, 0xcf, 0xf8, 0xf8, + 0x68, 0x49, 0x40, 0x45, 0x66, 0xcd, 0x42, 0xcc, 0x8b, 0xe3, 0xaf, 0x00, 0x35, 0x66, 0x74, 0xf4, 0x14, 0x40, 0x61, + 0x21, 0x20, 0xfa, 0x18, 0x64, 0xb4, 0x02, 0x7e, 0x0b, 0xf5, 0xbb, 0x75, 0xe2, 0xfb, 0xd0, 0xaf, 0x82, 0x5e, 0xc4, + 0xc0, 0x70, 0x44, 0x93, 0xc3, 0x90, 0x0f, 0x26, 0x03, 0xd0, 0x96, 0x78, 0xbb, 0xaf, 0xa5, 0x15, 0x37, 0xa7, 0x4b, + 0xa7, 0xfb, 0x27, 0x6d, 0x82, 0x24, 0x52, 0xc9, 0x4a, 0x45, 0x0c, 0x20, 0x94, 0xa5, 0xda, 0x26, 0x2b, 0xb0, 0xac, + 0x30, 0x4b, 0x9a, 0x1b, 0x94, 0xc4, 0xfd, 0xcd, 0xc0, 0x31, 0x6a, 0xd6, 0x49, 0x58, 0xb6, 0xdc, 0xa8, 0x01, 0x3e, + 0x27, 0x61, 0x85, 0xbd, 0xe1, 0xcc, 0xa5, 0x77, 0xa6, 0xc3, 0xd5, 0x31, 0x67, 0xaf, 0x39, 0x82, 0x71, 0x24, 0x78, + 0xe3, 0xa1, 0x2b, 0xa6, 0xa1, 0x22, 0x53, 0xc6, 0xc1, 0xb4, 0x07, 0xb8, 0xf7, 0x1c, 0x8c, 0xc3, 0xd8, 0xa0, 0xb2, + 0xa4, 0x3e, 0xf5, 0xee, 0x42, 0x20, 0x48, 0x6b, 0xbd, 0xcc, 0xe7, 0x78, 0x7a, 0x46, 0x28, 0xfb, 0x43, 0x0e, 0x5f, + 0x80, 0x1d, 0x05, 0x99, 0x4d, 0xf8, 0xd3, 0xc7, 0xfb, 0x81, 0xaa, 0xf8, 0x20, 0x38, 0x88, 0x45, 0x7a, 0x10, 0x0c, + 0x04, 0xfc, 0x2a, 0xf8, 0x41, 0x25, 0xe5, 0xc1, 0x45, 0x5c, 0x1c, 0xc4, 0xeb, 0xb8, 0xa8, 0x0e, 0x6e, 0xb2, 0x6a, + 0x75, 0x60, 0x3a, 0x04, 0xd0, 0xbc, 0xc1, 0x20, 0x1e, 0x04, 0x07, 0xc1, 0xa0, 0x30, 0x53, 0xbb, 0x66, 0x65, 0xe3, + 0x38, 0x33, 0x21, 0xca, 0x82, 0x66, 0x80, 0xb0, 0xc6, 0x69, 0x00, 0x7c, 0xea, 0x86, 0xa5, 0xf4, 0x02, 0xc3, 0x0d, + 0x88, 0xe9, 0x06, 0xfa, 0x00, 0x3c, 0xf2, 0x86, 0xc6, 0xb0, 0x04, 0x2e, 0x06, 0x03, 0xb2, 0x81, 0xc8, 0x05, 0x1b, + 0x6a, 0x83, 0x38, 0x84, 0x1b, 0x65, 0xa7, 0xbd, 0x0f, 0xcc, 0xb4, 0xdb, 0x01, 0xa2, 0xf2, 0x84, 0xf4, 0xfb, 0xf6, + 0x1b, 0xea, 0x5f, 0xb0, 0x57, 0x60, 0x7f, 0x55, 0x54, 0x61, 0x22, 0x95, 0xe6, 0xfb, 0x92, 0xcd, 0x06, 0x2a, 0xe2, + 0xf0, 0x9e, 0x23, 0x45, 0x1b, 0x95, 0xcb, 0xb2, 0x27, 0xab, 0x86, 0xaf, 0xc4, 0x15, 0x77, 0x7e, 0x5c, 0x95, 0x94, + 0x79, 0x95, 0xad, 0x15, 0xfb, 0x37, 0xe7, 0x9a, 0xfb, 0x03, 0xeb, 0xcf, 0xe6, 0x2b, 0xb8, 0xb6, 0x7a, 0xef, 0x9a, + 0x5c, 0x23, 0x72, 0x96, 0x50, 0x2e, 0xa9, 0x6d, 0x1e, 0xde, 0xd2, 0xf7, 0xf9, 0xd5, 0xb7, 0x99, 0x4e, 0xe3, 0xb3, + 0x0a, 0x0b, 0x17, 0xa2, 0x15, 0xc1, 0xa1, 0x21, 0x97, 0xcd, 0x23, 0xc0, 0x5c, 0xfb, 0x6c, 0x05, 0x05, 0xa9, 0xcf, + 0x2a, 0xf4, 0x6e, 0x85, 0x84, 0x97, 0x9a, 0x5d, 0x7a, 0x18, 0x48, 0x19, 0xb7, 0x87, 0x96, 0x30, 0x69, 0x79, 0x11, + 0xde, 0x7b, 0xcd, 0x4d, 0xee, 0x79, 0x88, 0xd1, 0x8b, 0x3c, 0x3b, 0x01, 0x63, 0xdd, 0x25, 0x3b, 0x1b, 0x9e, 0xf8, + 0x0d, 0xcf, 0x59, 0x8b, 0x46, 0xd3, 0x15, 0x4b, 0xfa, 0xfd, 0x18, 0x4c, 0xbc, 0x53, 0x96, 0xc3, 0xaf, 0x7c, 0x49, + 0x37, 0x0c, 0x30, 0xc5, 0xe8, 0x05, 0x24, 0xa4, 0x88, 0x44, 0xb2, 0x51, 0x27, 0xc9, 0x27, 0xba, 0x0b, 0xc0, 0xe8, + 0x17, 0xf3, 0x34, 0x5a, 0xdd, 0x6b, 0x66, 0x81, 0xe4, 0x19, 0xfa, 0xae, 0x83, 0xed, 0x8d, 0x7d, 0x90, 0x72, 0x7e, + 0x2c, 0xa6, 0x83, 0x01, 0x27, 0x1a, 0x6e, 0xbc, 0x54, 0xe2, 0x5a, 0xdd, 0xe2, 0x8e, 0x61, 0x2c, 0xf5, 0x6d, 0x11, + 0x83, 0x03, 0x76, 0xd1, 0xca, 0x6e, 0x1f, 0x60, 0x5f, 0x39, 0xde, 0xa5, 0xca, 0xee, 0xf4, 0x98, 0x69, 0x2e, 0x5b, + 0x4d, 0x3a, 0xa9, 0xb8, 0x9f, 0xc8, 0x37, 0xb9, 0x83, 0x2e, 0x97, 0x63, 0xcd, 0x5b, 0x0e, 0x40, 0x45, 0x3f, 0x52, + 0x54, 0xf7, 0x33, 0x1c, 0x61, 0x1e, 0xac, 0xdb, 0x7c, 0x72, 0x68, 0x0a, 0x1c, 0x22, 0x4f, 0xda, 0x68, 0x0a, 0xe8, + 0xde, 0xc5, 0xe3, 0xae, 0x7e, 0x5b, 0xba, 0x0b, 0x94, 0x68, 0xaf, 0xe2, 0x86, 0x1f, 0x13, 0x75, 0x3a, 0xd3, 0x86, + 0xd0, 0xbf, 0x32, 0xe2, 0xfe, 0xd2, 0xb8, 0x8a, 0x37, 0xbd, 0xcb, 0xe7, 0x1c, 0xea, 0xec, 0x86, 0x50, 0x00, 0xae, + 0xda, 0xd3, 0xa9, 0x1b, 0x43, 0x7a, 0xa5, 0x44, 0xb7, 0xc1, 0xc1, 0xee, 0xf5, 0x19, 0x47, 0xd1, 0x8f, 0x51, 0x23, + 0xdf, 0x44, 0xe2, 0xb1, 0x1c, 0xc4, 0x8f, 0x0b, 0xba, 0x8a, 0xc4, 0xe3, 0x62, 0x10, 0x3f, 0x96, 0x75, 0xbd, 0x7f, + 0xae, 0xdc, 0xdf, 0x47, 0xe4, 0x59, 0xf7, 0xf6, 0x52, 0x09, 0x1b, 0x03, 0xcf, 0xae, 0x25, 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, 0x8a, 0x0c, 0x27, 0x66, 0xf2, 0xe3, 0xd9, 0x78, 0x1e, 0x47, 0x93, 0xba, 0xe3, 0xb4, 0xd0, + 0xf8, 0xa7, 0xde, 0x2d, 0x14, 0x81, 0x53, 0x31, 0x82, 0x23, 0xa7, 0x42, 0x39, 0x29, 0x35, 0x30, 0xfc, 0x0f, 0xaa, + 0x3d, 0x6d, 0xda, 0xeb, 0xb8, 0x4a, 0x56, 0x99, 0xb8, 0xd4, 0xe1, 0xc3, 0x75, 0x74, 0x71, 0x1b, 0xd0, 0xce, 0xbb, + 0x4c, 0x3b, 0x7e, 0x9d, 0x34, 0xe8, 0x89, 0xab, 0x99, 0x01, 0xb7, 0xee, 0x47, 0x68, 0x86, 0xc0, 0x68, 0x79, 0xfe, + 0x0e, 0x31, 0xb7, 0x7f, 0x55, 0x36, 0xbf, 0x8a, 0xf6, 0x39, 0x32, 0x52, 0xb6, 0xc9, 0x48, 0x05, 0x46, 0x98, 0x52, + 0x24, 0x71, 0x15, 0x42, 0x20, 0xfb, 0xcf, 0x29, 0xae, 0xc5, 0xd2, 0x7b, 0x0d, 0xc2, 0x04, 0xdb, 0x05, 0xed, 0x57, + 0xb7, 0x77, 0x5b, 0x69, 0xb1, 0x47, 0xea, 0xfb, 0xdc, 0xd9, 0xae, 0x68, 0xf2, 0xf7, 0x79, 0x03, 0xda, 0x00, 0xa2, + 0xbc, 0xaf, 0x8f, 0x4a, 0xe0, 0x64, 0xc4, 0x0d, 0x25, 0x46, 0x2f, 0xe8, 0xea, 0x44, 0xee, 0xd9, 0xa9, 0x79, 0x53, + 0x31, 0x57, 0x71, 0xe5, 0x9b, 0x3d, 0xf3, 0x1f, 0x0c, 0x05, 0x15, 0x60, 0xe0, 0x6d, 0xce, 0x78, 0x74, 0xa0, 0xbb, + 0x31, 0x3a, 0x2d, 0xd8, 0x2c, 0xa8, 0xcb, 0xba, 0x69, 0xe3, 0x41, 0x23, 0x0e, 0x8a, 0x62, 0x55, 0xa8, 0x91, 0xf0, + 0x44, 0x20, 0x60, 0xca, 0xae, 0x78, 0x64, 0x04, 0x35, 0xbd, 0x09, 0x85, 0x0d, 0x05, 0x7f, 0x95, 0xa8, 0xa6, 0x37, + 0xa1, 0x4d, 0x26, 0x4e, 0x33, 0x88, 0x60, 0x46, 0x6c, 0xf7, 0x5b, 0x40, 0x9b, 0x5b, 0x33, 0xda, 0xd6, 0xb5, 0xd5, + 0x56, 0x21, 0x97, 0x14, 0x29, 0xcb, 0x7f, 0xa7, 0xa6, 0x82, 0x92, 0x5a, 0x2e, 0x7a, 0x93, 0xa6, 0x8b, 0x1e, 0xcf, + 0x8c, 0x24, 0x50, 0xb9, 0xe5, 0x8e, 0xd1, 0x1f, 0xc2, 0x02, 0x8f, 0x98, 0x38, 0xb1, 0x60, 0x6e, 0x35, 0x63, 0xd9, + 0x42, 0x2c, 0x47, 0x6b, 0x09, 0x61, 0x83, 0x8f, 0x59, 0xb6, 0x28, 0xf5, 0x43, 0xe8, 0x0b, 0x4b, 0xdf, 0x82, 0x5d, + 0x6c, 0xb0, 0x96, 0x65, 0x00, 0xbe, 0x17, 0x74, 0xbb, 0x96, 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, 0x1e, 0x0f, 0xc2, 0x64, 0x18, 0x93, 0xc7, 0x08, 0xb5, 0x7f, 0x98, 0x47, 0xb1, 0x96, 0x4b, 0xae, + 0x9d, 0x5f, 0xfc, 0xcd, 0x27, 0xec, 0x75, 0xcf, 0x30, 0x58, 0x80, 0xb3, 0xb4, 0xbd, 0xca, 0xc4, 0x3b, 0xd9, 0x0a, + 0x8e, 0x83, 0x59, 0x94, 0xc3, 0xaa, 0x27, 0x47, 0x34, 0x17, 0xb9, 0xf6, 0x2e, 0x42, 0xe4, 0x20, 0xb3, 0xc7, 0x00, + 0xbb, 0x11, 0xbe, 0x0e, 0xad, 0xcd, 0xad, 0xae, 0x10, 0x7f, 0xa3, 0x44, 0xe2, 0x27, 0x29, 0x3f, 0x6e, 0xd6, 0x2a, + 0x57, 0x65, 0xf0, 0x58, 0x75, 0x33, 0x78, 0xa6, 0x7d, 0x8f, 0xb5, 0x7f, 0x6b, 0xbb, 0x39, 0xde, 0x7b, 0xf0, 0xa0, + 0xf5, 0xbf, 0xf5, 0x24, 0x84, 0xf6, 0xca, 0x49, 0xea, 0x8e, 0x1a, 0x3d, 0x33, 0x59, 0x23, 0x2a, 0x61, 0x6a, 0x77, + 0x2a, 0xc7, 0x40, 0x4d, 0x07, 0x70, 0x2d, 0x51, 0x13, 0xf4, 0xa4, 0x60, 0x63, 0x38, 0xe2, 0x2c, 0x0e, 0xda, 0x71, + 0x8c, 0xe2, 0xe5, 0x5c, 0x89, 0x97, 0xf3, 0x19, 0xe3, 0x00, 0xad, 0x05, 0x48, 0xf5, 0x1a, 0xf6, 0x33, 0x57, 0xb0, + 0xc0, 0xe6, 0xce, 0x77, 0x64, 0x81, 0x0c, 0x71, 0xb2, 0x39, 0x4e, 0xf6, 0xb8, 0xd6, 0x73, 0x2f, 0xf0, 0x71, 0x52, + 0x2f, 0xbd, 0xba, 0xca, 0x76, 0x5d, 0x2b, 0x56, 0x2e, 0x8a, 0xc1, 0x04, 0x82, 0xb2, 0x94, 0x8b, 0x62, 0x38, 0x59, + 0xd2, 0x1c, 0x7e, 0x2c, 0x1b, 0xe8, 0x10, 0xab, 0x41, 0x02, 0x97, 0xce, 0x1e, 0x03, 0xde, 0x50, 0x6a, 0x71, 0x37, + 0xd6, 0x91, 0x63, 0x1d, 0xc5, 0x61, 0x18, 0x03, 0xae, 0xac, 0x13, 0x78, 0xdf, 0x7f, 0x7d, 0x6c, 0x02, 0xb2, 0x6a, + 0x57, 0x78, 0x35, 0xca, 0x5d, 0x57, 0x1a, 0x7d, 0x49, 0xe9, 0x09, 0x2f, 0x78, 0x2a, 0xd9, 0xed, 0x7a, 0x06, 0xce, + 0x96, 0x78, 0x48, 0xbc, 0x63, 0x44, 0x2f, 0xa6, 0x8d, 0xcc, 0x9c, 0xc0, 0x99, 0xed, 0x2e, 0xdb, 0x98, 0x1f, 0x3b, + 0xc0, 0xc1, 0x22, 0x08, 0x89, 0x1b, 0xc2, 0x30, 0xb1, 0x59, 0x39, 0xd4, 0x42, 0xb8, 0xae, 0x85, 0xd7, 0x71, 0x5a, + 0xc6, 0xe0, 0x22, 0xad, 0x6d, 0x13, 0xef, 0xa1, 0xeb, 0x9e, 0x1f, 0x73, 0xab, 0x63, 0xb4, 0x85, 0xf4, 0xdb, 0xd1, + 0xe9, 0x03, 0x87, 0x01, 0x68, 0x7a, 0x30, 0xaf, 0xda, 0x67, 0x12, 0x37, 0xa7, 0x9d, 0x20, 0x24, 0x02, 0x51, 0x94, + 0xce, 0x08, 0xd3, 0xbf, 0xd7, 0x5c, 0x56, 0xd1, 0xea, 0x41, 0x9e, 0x39, 0xe4, 0x59, 0xe8, 0x6d, 0x0f, 0x5a, 0x35, + 0x77, 0x83, 0x71, 0xe2, 0x76, 0x7b, 0xe7, 0xff, 0x2d, 0xeb, 0xda, 0x6a, 0x8d, 0x78, 0xdc, 0xae, 0x7e, 0xd0, 0xd8, + 0xab, 0x3d, 0x15, 0x03, 0x66, 0x2d, 0xbd, 0x33, 0xaa, 0xe4, 0x45, 0xc6, 0x4b, 0x3c, 0xa9, 0xd6, 0x0d, 0x1f, 0xef, + 0x9b, 0x6c, 0x64, 0x1e, 0xc8, 0x14, 0x10, 0xcf, 0x6f, 0x52, 0xa3, 0x3e, 0x4e, 0x51, 0x02, 0xfe, 0x4e, 0xc7, 0x37, + 0xa2, 0x1f, 0xed, 0x8b, 0x4b, 0x5e, 0xbd, 0xbd, 0x11, 0xe6, 0xc5, 0x73, 0xab, 0xf3, 0xa7, 0xaf, 0x0b, 0x1f, 0x3a, + 0x1c, 0xb5, 0x77, 0x50, 0x64, 0xc9, 0xc4, 0x6c, 0x62, 0x64, 0x6d, 0x62, 0xfe, 0x51, 0xc1, 0xc5, 0x44, 0x15, 0x7a, + 0xd6, 0xd9, 0x13, 0xa6, 0x00, 0x7d, 0xe3, 0x18, 0x95, 0x8c, 0x61, 0xc1, 0x40, 0x9d, 0xa6, 0x84, 0xe8, 0xa1, 0x98, + 0x63, 0xbc, 0x62, 0x00, 0x85, 0x29, 0x14, 0x88, 0xa2, 0xb3, 0x0f, 0x07, 0x9a, 0xd0, 0xef, 0xdf, 0xa4, 0x3a, 0x03, + 0x2d, 0xeb, 0xa9, 0x04, 0x51, 0x1d, 0x44, 0x5b, 0xe5, 0x45, 0xf8, 0xe3, 0x8a, 0x96, 0x19, 0x5d, 0x09, 0x9a, 0x0a, + 0x9a, 0x64, 0xf4, 0x82, 0x2b, 0x51, 0xf1, 0x85, 0x60, 0x8a, 0xb6, 0x1b, 0xc2, 0xfe, 0xaf, 0x06, 0x5d, 0x6f, 0xc5, + 0x5a, 0x43, 0xbb, 0x13, 0x64, 0x84, 0x16, 0x4b, 0x1d, 0x84, 0x0c, 0x95, 0x93, 0xd0, 0xb5, 0x4a, 0xe3, 0x15, 0xb8, + 0x64, 0x9a, 0x8d, 0x56, 0x71, 0x19, 0x06, 0xf6, 0xab, 0xc0, 0x62, 0x72, 0x60, 0xd2, 0xe9, 0xe6, 0xfc, 0x99, 0xbc, + 0x5a, 0x4b, 0xc1, 0x45, 0xa5, 0x20, 0xfa, 0x0d, 0xee, 0xbb, 0x89, 0xab, 0xce, 0x9a, 0xb5, 0xd2, 0x87, 0xbe, 0xf5, + 0x59, 0x1b, 0xf7, 0x85, 0xc1, 0x31, 0xd8, 0xfb, 0x88, 0x18, 0x48, 0x83, 0x4a, 0xb7, 0x38, 0x34, 0x01, 0xba, 0x74, + 0x48, 0x21, 0x4b, 0xa6, 0x32, 0x55, 0x82, 0x8a, 0x6f, 0xfc, 0x5e, 0xca, 0x6a, 0xf4, 0xe7, 0x86, 0x17, 0x77, 0xa7, + 0x3c, 0xe7, 0x38, 0x46, 0x41, 0x12, 0x8b, 0xeb, 0xb8, 0x0c, 0x88, 0x6f, 0x79, 0x15, 0x1c, 0xa5, 0x26, 0x6c, 0xcc, + 0x5e, 0xd5, 0xa8, 0xf5, 0x92, 0xe8, 0x2b, 0xa3, 0x7c, 0x63, 0x30, 0x34, 0x11, 0x55, 0xd0, 0xf7, 0x5a, 0xdd, 0xd3, + 0xea, 0x86, 0x05, 0xc4, 0x5f, 0x28, 0xbd, 0x50, 0xeb, 0x75, 0x33, 0xe6, 0x86, 0x89, 0x10, 0x34, 0xfa, 0xaa, 0x5e, + 0xd6, 0x9e, 0x5b, 0x9a, 0x8a, 0x8c, 0x1b, 0x6d, 0x73, 0x7e, 0x09, 0x32, 0x3e, 0x67, 0x2e, 0x34, 0xa9, 0x6b, 0xaa, + 0xa0, 0x0a, 0xa3, 0xed, 0x6d, 0x23, 0x9d, 0xde, 0x81, 0x3b, 0x9b, 0x31, 0x3b, 0xd2, 0x2e, 0x8d, 0x35, 0x2d, 0x78, + 0xb9, 0x96, 0xa2, 0x84, 0x30, 0xce, 0xbd, 0x31, 0xbd, 0x8a, 0x33, 0x51, 0xc5, 0x99, 0x38, 0x29, 0xd7, 0x3c, 0xa9, + 0xde, 0xc3, 0x2d, 0x4e, 0x59, 0xdd, 0xd4, 0x25, 0x5c, 0xe9, 0x92, 0x03, 0x0c, 0xa6, 0xa6, 0xe2, 0x1e, 0x3b, 0x83, + 0x8b, 0xea, 0xf7, 0x68, 0x25, 0x31, 0x16, 0xaa, 0x2e, 0x3e, 0x3e, 0x2f, 0x65, 0xbe, 0xa9, 0x40, 0xbb, 0x7b, 0x51, + 0x45, 0x47, 0x4f, 0xd6, 0xb7, 0x53, 0x75, 0x83, 0x89, 0x9e, 0x1c, 0xad, 0x6f, 0x7b, 0xd9, 0xd5, 0x5a, 0x16, 0x55, + 0x2c, 0xaa, 0xa9, 0x42, 0x24, 0x4b, 0xe2, 0x3c, 0x09, 0x27, 0xe3, 0xf1, 0x17, 0x07, 0xc3, 0x03, 0xc8, 0x40, 0xa6, + 0x7f, 0x0d, 0x95, 0xcb, 0xd1, 0x70, 0x32, 0x1e, 0x4f, 0xa5, 0xba, 0xdb, 0x45, 0xa3, 0x49, 0x8d, 0xf5, 0x0c, 0x13, + 0x3d, 0x33, 0x23, 0x7e, 0xbb, 0x8e, 0x45, 0x0a, 0xf1, 0xeb, 0x74, 0xf1, 0x47, 0x4f, 0xc6, 0x8d, 0xf2, 0xed, 0xa7, + 0x4f, 0xeb, 0xdf, 0x6b, 0x13, 0xd6, 0xda, 0xb4, 0xfb, 0xd9, 0xef, 0xc7, 0x6a, 0xbe, 0x67, 0xc7, 0x87, 0xfa, 0xc7, + 0xef, 0x75, 0x3d, 0x7d, 0x5d, 0x84, 0x8b, 0x7f, 0x86, 0x6a, 0x3e, 0x4f, 0x8a, 0x22, 0xbe, 0xab, 0x21, 0x92, 0xa7, + 0x70, 0xde, 0x24, 0xd4, 0xdb, 0x06, 0xf4, 0x88, 0x4c, 0x2f, 0x04, 0x83, 0x6f, 0xde, 0x57, 0x61, 0xc0, 0xcb, 0xf5, + 0x90, 0x8b, 0x2a, 0xab, 0xee, 0x86, 0x98, 0x27, 0xc0, 0x4f, 0x0d, 0x6f, 0xf6, 0xac, 0x30, 0xc4, 0xe6, 0xa2, 0xe0, + 0xfc, 0x2f, 0x1e, 0x2a, 0xe3, 0xe8, 0x31, 0x1a, 0x47, 0x8f, 0xa9, 0x1a, 0x8c, 0xc9, 0xd7, 0x54, 0x77, 0x66, 0xf2, + 0x35, 0x98, 0x20, 0x65, 0xed, 0x6f, 0x94, 0x71, 0x62, 0x34, 0xa6, 0xd7, 0x2f, 0xf3, 0x6c, 0x0d, 0x4c, 0xf0, 0x4a, + 0xff, 0xa8, 0x09, 0x7d, 0xcf, 0xdb, 0xd9, 0x47, 0xa3, 0xd1, 0xb3, 0x82, 0x8e, 0x46, 0xa3, 0x8f, 0x59, 0x4d, 0xe8, + 0x5a, 0x74, 0xbc, 0x7f, 0xcf, 0xe9, 0xb9, 0x4c, 0xef, 0xa2, 0x20, 0xa0, 0xab, 0x2c, 0x4d, 0xb9, 0x50, 0x65, 0x9d, + 0xa6, 0xed, 0xbc, 0xaa, 0x85, 0x08, 0xfc, 0xa3, 0xdb, 0x88, 0x10, 0x44, 0x84, 0xbe, 0xdd, 0xeb, 0xd9, 0x68, 0x34, + 0x3a, 0x4d, 0x4d, 0xb5, 0x8e, 0x21, 0x7f, 0x8d, 0xe6, 0x03, 0xce, 0x2e, 0x1f, 0xac, 0x6f, 0x4c, 0xb4, 0x93, 0xc3, + 0xff, 0x1e, 0xce, 0x17, 0xe3, 0xe1, 0xb7, 0xa3, 0xe5, 0xe3, 0x43, 0x1a, 0x04, 0x3e, 0x68, 0x75, 0xa8, 0xad, 0x39, + 0xa6, 0xe5, 0xf1, 0x78, 0x4a, 0xca, 0x01, 0x7b, 0x62, 0x7d, 0x69, 0xbe, 0x78, 0x02, 0x48, 0xa4, 0x28, 0x42, 0x0d, + 0x9c, 0xf4, 0x0f, 0xaf, 0x22, 0xaf, 0x04, 0xe0, 0xa3, 0xd9, 0x48, 0x06, 0x46, 0x0b, 0x38, 0x8e, 0xa0, 0xbc, 0xda, + 0x9a, 0x46, 0xf4, 0x18, 0xcb, 0x4c, 0x54, 0xd0, 0xf1, 0xb4, 0xbc, 0xc9, 0xaa, 0x64, 0x85, 0x81, 0x8d, 0xe2, 0x92, + 0x07, 0x5f, 0x04, 0x51, 0xc9, 0x8e, 0x9e, 0x4e, 0x15, 0xbc, 0x2f, 0x26, 0xa5, 0xfc, 0x12, 0x12, 0xbf, 0x1d, 0x23, + 0x04, 0x2a, 0xd1, 0x1e, 0x8b, 0x58, 0xe3, 0xcb, 0x5c, 0xc6, 0xe0, 0xc1, 0x59, 0x6a, 0x9e, 0xc5, 0x9e, 0x04, 0xd6, + 0xfe, 0xa2, 0xd5, 0x1c, 0x09, 0xcd, 0x09, 0x25, 0x93, 0x87, 0x25, 0x95, 0x5f, 0x4c, 0xd0, 0x2b, 0x08, 0xdc, 0xaa, + 0x23, 0x38, 0xee, 0xac, 0x65, 0x83, 0x5e, 0x3e, 0x29, 0x3b, 0x5c, 0xfc, 0xef, 0x92, 0x2e, 0x07, 0x87, 0x6e, 0x68, + 0xde, 0x6a, 0xf7, 0xd5, 0x0a, 0x19, 0xa5, 0x2a, 0x7c, 0x96, 0x12, 0x6b, 0x7c, 0xca, 0xd9, 0x6c, 0x6b, 0xba, 0x33, + 0xaa, 0x8a, 0xec, 0x2a, 0x24, 0xba, 0x57, 0x0e, 0x14, 0x33, 0x88, 0xb2, 0x11, 0xae, 0x1f, 0xb0, 0x16, 0xf1, 0x3a, + 0x79, 0xcd, 0x8b, 0x2a, 0x4b, 0xd4, 0xfb, 0xeb, 0xc6, 0x7b, 0xa0, 0x06, 0xaa, 0x41, 0xef, 0x0a, 0x06, 0xf3, 0xfc, + 0xb6, 0x00, 0xd0, 0xce, 0x92, 0x17, 0xd7, 0xdc, 0xa7, 0x1b, 0x41, 0x50, 0xbb, 0x66, 0x5e, 0x36, 0x82, 0x4d, 0xc0, + 0x57, 0xef, 0x0a, 0xc0, 0xdc, 0x08, 0x41, 0x6a, 0x0a, 0xa1, 0x70, 0xe0, 0x02, 0x5f, 0x55, 0x45, 0x76, 0xbe, 0xa9, + 0x38, 0x06, 0xfb, 0xf0, 0xe2, 0x26, 0x2a, 0x27, 0x3c, 0x1e, 0x06, 0xf8, 0x23, 0xa0, 0x2a, 0xe0, 0x86, 0xf1, 0xb0, + 0x83, 0x17, 0xea, 0x97, 0x7b, 0xa3, 0xf6, 0x08, 0x7b, 0x9d, 0x86, 0x10, 0x5c, 0x07, 0x1f, 0x02, 0x58, 0x52, 0x84, + 0xbe, 0xc5, 0x53, 0x35, 0x0c, 0x2e, 0xf2, 0x6c, 0xad, 0x93, 0xaa, 0x51, 0x47, 0xf3, 0xa1, 0xd4, 0x8e, 0xe4, 0x80, + 0x7a, 0xe9, 0x31, 0xa6, 0x17, 0x2a, 0x5d, 0x15, 0xe5, 0x8c, 0x50, 0xde, 0xe9, 0x89, 0x71, 0x61, 0xfa, 0x38, 0x44, + 0x7e, 0x79, 0x57, 0xa8, 0xd0, 0x2f, 0x7c, 0x09, 0xe0, 0x57, 0x70, 0xbb, 0xdf, 0x8f, 0xef, 0xa2, 0xb2, 0x9f, 0x71, + 0x76, 0xf8, 0xdf, 0x8b, 0x78, 0xf8, 0xd7, 0x78, 0xf8, 0xed, 0x72, 0x10, 0x0e, 0xed, 0x4f, 0xf2, 0xf8, 0xd1, 0x21, + 0x7d, 0xc9, 0x2d, 0x57, 0x02, 0x0b, 0xbf, 0x11, 0xdc, 0x46, 0xad, 0x84, 0x20, 0x0a, 0xf0, 0x46, 0xe1, 0x56, 0xe3, + 0x04, 0x00, 0xfe, 0x82, 0xff, 0x0a, 0xd0, 0x48, 0xc8, 0x5d, 0x34, 0x40, 0x3f, 0xa0, 0x7e, 0xcf, 0xbe, 0x6a, 0x18, + 0xc8, 0x81, 0x78, 0x42, 0xc5, 0x40, 0x21, 0xba, 0x8c, 0x89, 0x82, 0xfd, 0xb5, 0xd9, 0x77, 0xbb, 0x5e, 0x5b, 0xf2, + 0x83, 0x5f, 0xfa, 0x99, 0x26, 0x66, 0xde, 0xe1, 0x86, 0xb2, 0x96, 0xeb, 0x10, 0xb1, 0xf1, 0xf4, 0xaf, 0x9c, 0x41, + 0xac, 0xc9, 0xeb, 0x0c, 0x7c, 0x18, 0xec, 0x17, 0xe3, 0x39, 0xb0, 0x0d, 0x70, 0xc7, 0x29, 0xf8, 0x45, 0x06, 0x6e, + 0xcd, 0x22, 0xc6, 0x0b, 0xb6, 0x5d, 0x12, 0xfd, 0x7e, 0x2f, 0xcf, 0xc2, 0x5c, 0xe3, 0x2c, 0xe7, 0xb5, 0x11, 0xbb, + 0xa3, 0x4e, 0x18, 0xc4, 0xed, 0x7a, 0x08, 0x86, 0x6a, 0x08, 0x8a, 0x8e, 0xb6, 0xb8, 0x7a, 0x6d, 0x3d, 0x85, 0xe9, + 0xad, 0xaa, 0xaf, 0x18, 0xfd, 0x21, 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, 0xba, 0xcc, 0x7b, 0xbd, 0x30, 0x44, 0x87, 0x46, 0x2c, 0x15, 0x6b, 0x83, 0xf0, 0x3e, 0x26, 0x61, 0x74, + 0x05, 0xb2, 0xba, 0xf0, 0x8c, 0x13, 0xe4, 0xcb, 0xc0, 0x64, 0x4d, 0x55, 0xeb, 0xe5, 0x84, 0xc7, 0x46, 0xbe, 0x6c, + 0x04, 0x0d, 0xf2, 0x92, 0xa2, 0xde, 0xc4, 0xed, 0xd8, 0x47, 0x2d, 0xa4, 0xc6, 0x6d, 0x3d, 0xed, 0x69, 0x52, 0xd1, + 0x63, 0xbd, 0x4a, 0xfd, 0x02, 0xcb, 0x02, 0x4b, 0x3e, 0x08, 0xed, 0x69, 0x5a, 0x81, 0x19, 0xae, 0x6d, 0x06, 0x43, + 0x3f, 0x1c, 0xda, 0x22, 0x74, 0x46, 0x6d, 0x4b, 0x08, 0xdb, 0x36, 0x08, 0x2b, 0xef, 0x89, 0x7c, 0xf1, 0xc4, 0x63, + 0x84, 0x43, 0x6e, 0x36, 0xb3, 0x68, 0x60, 0x98, 0x5f, 0xc9, 0x66, 0xf3, 0x74, 0x73, 0xbd, 0xa8, 0x98, 0x02, 0xb6, + 0xdb, 0x5a, 0x10, 0xfc, 0xfb, 0x31, 0x9b, 0xe3, 0xdf, 0xac, 0xdf, 0xef, 0x85, 0xf8, 0x8b, 0x63, 0xf0, 0x9e, 0x85, + 0x58, 0xb2, 0x8f, 0x20, 0x53, 0x21, 0x11, 0xa6, 0x2a, 0xe3, 0x37, 0x56, 0x81, 0x05, 0x9c, 0xf9, 0x40, 0xe5, 0xc2, + 0x4c, 0xf6, 0xf2, 0xe2, 0x1a, 0x72, 0xd2, 0x1a, 0xa7, 0x6c, 0x94, 0x25, 0xca, 0x75, 0x21, 0x1b, 0xc5, 0x79, 0x16, + 0x97, 0xbc, 0xdc, 0xed, 0xf4, 0xe1, 0x98, 0x14, 0x1c, 0xd8, 0x53, 0x45, 0xa5, 0x4a, 0xd6, 0x91, 0xea, 0xc6, 0x5f, + 0x86, 0x05, 0xee, 0x53, 0xbe, 0x28, 0x0c, 0x8d, 0x38, 0x80, 0xcb, 0x3b, 0x53, 0xb7, 0xd2, 0x5e, 0x58, 0x40, 0xf3, + 0x4a, 0x42, 0xb6, 0x98, 0xea, 0x59, 0xb4, 0xc6, 0x4c, 0x2c, 0x8a, 0x25, 0x84, 0x91, 0x29, 0x96, 0x60, 0x33, 0xc5, + 0x05, 0x78, 0x91, 0xc4, 0x00, 0x13, 0x17, 0x93, 0x29, 0xc4, 0x33, 0x57, 0xe5, 0xc4, 0x4b, 0x73, 0xbf, 0x4c, 0x1c, + 0x52, 0x06, 0xbc, 0xaa, 0x0d, 0x9a, 0x98, 0x6d, 0x38, 0xea, 0x04, 0x39, 0x31, 0xf9, 0xfd, 0x54, 0x41, 0x88, 0x3b, + 0x71, 0x24, 0x5c, 0x56, 0x6c, 0x17, 0x5e, 0x74, 0x20, 0xc6, 0xa8, 0xc1, 0x29, 0x3f, 0x31, 0x38, 0x1a, 0x83, 0x73, + 0xeb, 0x9d, 0x20, 0x45, 0x18, 0x93, 0xad, 0x64, 0x57, 0x32, 0x14, 0x8b, 0x78, 0x09, 0xca, 0xba, 0x78, 0x09, 0x96, + 0x35, 0xc6, 0x00, 0x13, 0xe4, 0x55, 0xdc, 0x0b, 0xfd, 0x44, 0x71, 0x85, 0x48, 0xcf, 0xca, 0xf5, 0x51, 0xd1, 0x0e, + 0x7d, 0x81, 0xd7, 0x7b, 0x65, 0x8e, 0x9b, 0xf5, 0x58, 0x20, 0xb1, 0x21, 0x60, 0x6c, 0xa4, 0xd3, 0x54, 0x6b, 0xdd, + 0x1b, 0x33, 0x0f, 0x7c, 0x9a, 0x8d, 0x84, 0xac, 0xce, 0x2e, 0x40, 0x84, 0xe2, 0xa3, 0xc1, 0x23, 0xbf, 0x88, 0x3b, + 0xcb, 0xbc, 0xb5, 0x2d, 0x2a, 0xd9, 0x6c, 0x0b, 0x20, 0x7d, 0x3a, 0x5a, 0x94, 0x92, 0x53, 0x94, 0xa4, 0x76, 0x9b, + 0x02, 0x56, 0x92, 0xbf, 0x80, 0x21, 0xd8, 0xd8, 0x81, 0x70, 0x3a, 0x45, 0x88, 0x4f, 0x34, 0x45, 0x64, 0xc5, 0xb0, + 0xa4, 0x38, 0xb6, 0x25, 0xa2, 0x7e, 0xda, 0xb2, 0xec, 0x60, 0x98, 0xa8, 0xb8, 0xcf, 0x53, 0x8f, 0x12, 0x05, 0x01, + 0xd5, 0x43, 0x0e, 0x12, 0x5b, 0xdb, 0x40, 0x78, 0x40, 0x1e, 0xd1, 0x1b, 0xeb, 0xef, 0xb3, 0xce, 0xb3, 0x0b, 0xcd, + 0x51, 0xb9, 0xde, 0x15, 0x66, 0x8c, 0xf0, 0x24, 0x33, 0x30, 0xf9, 0xde, 0x79, 0x66, 0xd4, 0x14, 0x3d, 0x0f, 0x9f, + 0xec, 0x04, 0x23, 0xd2, 0xdd, 0x33, 0xe8, 0x26, 0x78, 0x55, 0x87, 0x8d, 0x76, 0xa5, 0x20, 0x24, 0x4c, 0x2d, 0x9a, + 0x98, 0xf5, 0xac, 0x01, 0xf5, 0x6e, 0xd7, 0xd3, 0x73, 0x75, 0xff, 0xdc, 0xed, 0x76, 0x3d, 0xec, 0xd6, 0xf3, 0xb4, + 0xdb, 0x0a, 0xbc, 0x52, 0x1f, 0xb4, 0xc7, 0x9f, 0xbb, 0xf1, 0xe7, 0x06, 0xc9, 0xa3, 0x74, 0x34, 0xd3, 0xd6, 0x07, + 0xe1, 0x70, 0xd3, 0xbb, 0x46, 0x93, 0xbe, 0xcf, 0x42, 0x49, 0xd7, 0xa2, 0x51, 0x5d, 0xed, 0x4c, 0x2a, 0x1f, 0x5c, + 0xff, 0x0f, 0xaf, 0x02, 0x3c, 0xe2, 0xd4, 0xce, 0xbe, 0xb7, 0x41, 0x45, 0xa3, 0x2d, 0x1c, 0x29, 0x42, 0x0f, 0x48, + 0xc2, 0x7d, 0x2d, 0x6b, 0x71, 0x9b, 0xa7, 0xd9, 0xc3, 0xf4, 0xe9, 0x55, 0xea, 0x5b, 0xdd, 0xbb, 0x65, 0x96, 0x99, + 0x03, 0xaf, 0xa2, 0x38, 0xa0, 0x51, 0x17, 0xed, 0xbb, 0xca, 0xca, 0x12, 0xbc, 0x3c, 0xe0, 0xfa, 0x7c, 0xca, 0x7d, + 0xb8, 0xb9, 0xcb, 0xaa, 0xb9, 0x49, 0x4f, 0xb3, 0x45, 0xb6, 0xdc, 0xed, 0x42, 0xfc, 0xdb, 0xd5, 0x22, 0x47, 0x93, + 0x17, 0xa0, 0xc3, 0xc3, 0xc8, 0x3d, 0x4c, 0x37, 0xce, 0xdb, 0xfc, 0x7f, 0x89, 0x86, 0x93, 0xc0, 0x09, 0xd0, 0x8b, + 0xf9, 0x23, 0x90, 0xc1, 0x18, 0xa7, 0x7e, 0x31, 0xd7, 0x6b, 0x06, 0xa2, 0x6f, 0x89, 0x08, 0x70, 0x74, 0xb1, 0x91, + 0x68, 0x64, 0xc1, 0x49, 0x4d, 0xc0, 0x62, 0xd3, 0x96, 0xf7, 0xc1, 0xd2, 0xb6, 0xaa, 0xb8, 0xf3, 0x96, 0x34, 0xc7, + 0x75, 0xe0, 0x6c, 0xfb, 0xcd, 0x10, 0x9b, 0xb2, 0xab, 0x25, 0x72, 0xbf, 0xbc, 0xa6, 0xbd, 0x71, 0x9d, 0xc0, 0xac, + 0x6d, 0x6b, 0xcb, 0xf8, 0xd9, 0xd2, 0x7f, 0xd2, 0x83, 0xab, 0x8c, 0x9f, 0x16, 0xc6, 0x2a, 0xc1, 0xee, 0x1b, 0xcf, + 0x77, 0x00, 0xc2, 0xb1, 0xf9, 0xf4, 0xf8, 0x34, 0xf3, 0xe8, 0x31, 0x10, 0x1d, 0xf3, 0x51, 0xe9, 0x3e, 0xb2, 0xbb, + 0xd7, 0x0f, 0x80, 0xb7, 0xa8, 0xda, 0x05, 0x2d, 0xca, 0x25, 0x04, 0x12, 0xf5, 0xca, 0x2b, 0x2c, 0x9f, 0x19, 0xb3, + 0x4b, 0x20, 0x43, 0x05, 0x01, 0x9b, 0xa4, 0xae, 0x73, 0x21, 0x56, 0x1d, 0x56, 0xe6, 0x23, 0x09, 0x9b, 0x85, 0x68, + 0xce, 0x19, 0xcc, 0x83, 0xff, 0x0a, 0x06, 0xe5, 0x20, 0x88, 0x82, 0x28, 0x08, 0xc8, 0xa0, 0x80, 0x5f, 0x88, 0x33, + 0x46, 0x30, 0x46, 0x09, 0x74, 0xf8, 0x1d, 0x67, 0x3e, 0x23, 0xf2, 0xa2, 0x11, 0xc6, 0xd2, 0x0d, 0xc0, 0xb9, 0x94, + 0x39, 0x8f, 0xd1, 0xc7, 0xe2, 0x1d, 0x67, 0x19, 0xa1, 0xef, 0xbc, 0x53, 0xf9, 0x11, 0x6f, 0x04, 0xb7, 0xdb, 0x1f, + 0xb6, 0x97, 0x3c, 0xcc, 0x68, 0x6f, 0x4c, 0xdf, 0x71, 0x12, 0x65, 0x0d, 0xe7, 0x61, 0x0e, 0x3d, 0xab, 0x2c, 0x6b, + 0x45, 0x0d, 0xb9, 0x41, 0xb1, 0x2e, 0xb2, 0x4c, 0x4e, 0x86, 0xab, 0xe6, 0x54, 0xe0, 0xba, 0xb3, 0xeb, 0x05, 0x24, + 0x65, 0x42, 0xb3, 0x74, 0x36, 0x7c, 0xb5, 0x6d, 0xd9, 0xf3, 0xd6, 0x29, 0xe4, 0x35, 0x44, 0x45, 0x3f, 0x74, 0x04, + 0xd4, 0xd0, 0x8a, 0xcb, 0x0a, 0x5c, 0x76, 0x4d, 0x7b, 0xb8, 0x69, 0x8f, 0x69, 0xc6, 0x07, 0x88, 0x11, 0xc7, 0xb1, + 0x65, 0x60, 0x37, 0xe1, 0xf0, 0x6c, 0x9c, 0xef, 0xcb, 0x3e, 0xbd, 0x75, 0xb5, 0x78, 0x84, 0xb5, 0xe7, 0xad, 0x90, + 0x10, 0x20, 0x2d, 0x4d, 0xa5, 0xbb, 0x5d, 0x10, 0xc0, 0x00, 0xf7, 0xfb, 0x3d, 0xe0, 0x5a, 0x0d, 0x3b, 0x69, 0x6e, + 0xcd, 0x96, 0xd8, 0x2b, 0x0a, 0x8f, 0x81, 0x28, 0x35, 0xff, 0x19, 0x04, 0x14, 0xcf, 0xdd, 0x10, 0xec, 0x2b, 0xd9, + 0x6c, 0x5b, 0xf4, 0xfb, 0xcf, 0x0b, 0x7c, 0x40, 0x39, 0x28, 0x88, 0x75, 0x75, 0xdc, 0x0a, 0xc3, 0x3e, 0xa9, 0x0f, + 0x71, 0x2c, 0xf2, 0x2c, 0x74, 0x84, 0xa5, 0x32, 0x84, 0x85, 0x2b, 0x46, 0x3a, 0x88, 0x83, 0x9a, 0x74, 0x0e, 0x56, + 0xe5, 0x82, 0x0d, 0xf7, 0x7a, 0x7f, 0x01, 0x2c, 0x78, 0xe6, 0x0d, 0xcb, 0x7b, 0x0f, 0x00, 0xac, 0xd7, 0xc3, 0x85, + 0xe2, 0x5e, 0xbe, 0x6c, 0xa0, 0x4f, 0xe2, 0x4b, 0xcb, 0xae, 0xcf, 0xb5, 0xac, 0x64, 0x34, 0x1a, 0x55, 0xb5, 0x92, + 0x7c, 0x38, 0xf2, 0xd2, 0x42, 0xad, 0x94, 0x71, 0xca, 0x53, 0xb0, 0xf4, 0x36, 0x94, 0x6e, 0xb1, 0xa4, 0x6b, 0x2e, + 0x52, 0xf5, 0xd3, 0x43, 0x9b, 0x6c, 0x10, 0xd7, 0xac, 0xa9, 0xb3, 0xb0, 0xc3, 0x0f, 0x01, 0x1f, 0xed, 0xc3, 0xdc, + 0xa5, 0x6b, 0x58, 0x5a, 0x10, 0x47, 0xc6, 0x05, 0x0f, 0x5d, 0x1e, 0xc0, 0xfa, 0x33, 0x87, 0x24, 0x7e, 0x0a, 0x3f, + 0xe7, 0x26, 0xad, 0xe3, 0x33, 0x9c, 0xcd, 0xa8, 0x54, 0x37, 0x82, 0xf6, 0x6b, 0x48, 0x24, 0x06, 0xd9, 0xb8, 0xc1, + 0x50, 0xb4, 0xee, 0x36, 0x70, 0xe5, 0xb7, 0xf4, 0xce, 0xa7, 0x41, 0x80, 0x6d, 0x8d, 0xc5, 0x00, 0x60, 0x28, 0xfe, + 0x40, 0x55, 0x8d, 0xb9, 0xa2, 0x98, 0x86, 0xa9, 0x44, 0x7b, 0xc7, 0x71, 0x1d, 0x35, 0xae, 0xb2, 0x82, 0x95, 0xd6, + 0x96, 0xd7, 0xbd, 0xa5, 0x85, 0x2d, 0x01, 0xd5, 0x60, 0xb8, 0x13, 0xc0, 0x67, 0x44, 0xaa, 0x03, 0x41, 0x76, 0x1f, + 0x1c, 0x34, 0x67, 0x09, 0x9e, 0x87, 0x21, 0xfc, 0x81, 0x85, 0x03, 0xcb, 0x52, 0xf5, 0x73, 0x35, 0x8d, 0xe1, 0xdc, + 0xcd, 0xd5, 0x0e, 0x9f, 0xaf, 0x40, 0x91, 0xa7, 0xe6, 0xd4, 0x5c, 0xbe, 0xf2, 0xc6, 0x7e, 0x8f, 0x09, 0xe6, 0x31, + 0xb3, 0x0d, 0xbf, 0xf5, 0x74, 0x5b, 0x5f, 0x58, 0x37, 0x70, 0xd2, 0x5e, 0x38, 0xed, 0xc5, 0x76, 0x65, 0x20, 0xee, + 0xea, 0x86, 0x10, 0xe1, 0x95, 0x26, 0x16, 0x59, 0x43, 0xa6, 0x63, 0xb1, 0x31, 0x54, 0x9b, 0x8a, 0x67, 0x5a, 0x21, + 0x5e, 0x4e, 0xd5, 0x85, 0xa9, 0x95, 0xca, 0x84, 0x41, 0x98, 0x29, 0x61, 0x51, 0x65, 0xe0, 0xb3, 0x5f, 0x21, 0xc5, + 0xb5, 0xf5, 0xbc, 0xc1, 0xe5, 0x9b, 0x99, 0x36, 0xdb, 0x4f, 0x5f, 0xe6, 0xf1, 0xe5, 0x6e, 0x17, 0x76, 0xbf, 0x00, + 0xf3, 0xcb, 0x52, 0x69, 0xd4, 0xc0, 0xe9, 0x21, 0x44, 0x3f, 0xe7, 0x7b, 0x72, 0x4e, 0x1c, 0x27, 0xd7, 0x6e, 0xde, + 0x7c, 0x2f, 0xc5, 0x08, 0x2c, 0xe0, 0xc4, 0x45, 0x3a, 0xd0, 0x52, 0xc1, 0x69, 0xcb, 0x78, 0x6f, 0xd3, 0x3b, 0x4a, + 0x85, 0x57, 0x0b, 0x4d, 0x42, 0x2a, 0x77, 0x2f, 0xb1, 0xa3, 0x06, 0x9c, 0x93, 0xba, 0x83, 0x80, 0x93, 0x9a, 0x6e, + 0xac, 0x55, 0x9c, 0x9a, 0x04, 0xef, 0x95, 0x1e, 0xba, 0x44, 0x3b, 0x71, 0xbb, 0x6d, 0x55, 0xb6, 0x50, 0x1f, 0x0f, + 0x72, 0x96, 0xa8, 0xe3, 0x01, 0x85, 0x2e, 0xea, 0x68, 0xc8, 0x97, 0xa4, 0xd0, 0x2b, 0x47, 0xab, 0x56, 0xf7, 0x25, + 0x03, 0xa5, 0x5a, 0x05, 0x79, 0x4d, 0xac, 0xbb, 0x56, 0xd6, 0x58, 0x5c, 0x39, 0x21, 0x85, 0x4d, 0xf8, 0xdc, 0x52, + 0x2c, 0xac, 0x60, 0x6f, 0x4c, 0x7d, 0xe1, 0x12, 0xa1, 0xed, 0x6e, 0x43, 0x4c, 0x32, 0x58, 0x37, 0xbb, 0xdd, 0xab, + 0x22, 0x5c, 0x64, 0x4b, 0x2a, 0x47, 0x59, 0x8a, 0x10, 0x62, 0xc6, 0x43, 0xd7, 0x76, 0xc1, 0x4c, 0x0c, 0x75, 0xed, + 0xf1, 0x92, 0x4c, 0xb1, 0x36, 0x49, 0x8e, 0xe2, 0x73, 0x59, 0xa8, 0xb5, 0x46, 0x08, 0x1e, 0xee, 0x7f, 0xa4, 0x10, + 0xc3, 0xcd, 0xac, 0xbb, 0x5f, 0xf7, 0x6e, 0x88, 0x7f, 0x40, 0x20, 0x81, 0x92, 0xbd, 0x2a, 0x46, 0xe7, 0x99, 0x48, + 0x71, 0xa7, 0xaa, 0xa8, 0xb8, 0x6a, 0x1d, 0x34, 0x5b, 0x6e, 0xef, 0xc5, 0x96, 0x28, 0x40, 0x5c, 0x63, 0xa1, 0x19, + 0xcf, 0xca, 0x59, 0x8a, 0x64, 0x14, 0x1b, 0x12, 0x95, 0x5e, 0x54, 0x74, 0x9f, 0xa7, 0x31, 0x3d, 0x74, 0x6b, 0x10, + 0x5c, 0x35, 0xf7, 0x36, 0xd2, 0x62, 0x49, 0x88, 0x9a, 0x00, 0x09, 0x1b, 0xd5, 0x9c, 0x5a, 0x97, 0xe2, 0x61, 0x56, + 0xf9, 0x4c, 0x1f, 0xc4, 0x97, 0x02, 0x78, 0x58, 0x6f, 0x7b, 0x5f, 0x09, 0x8f, 0xb5, 0xc1, 0xb7, 0xbb, 0xdd, 0xa5, + 0x58, 0x04, 0x81, 0xc7, 0x68, 0x7e, 0xa7, 0x24, 0xe6, 0xbd, 0x31, 0x85, 0x15, 0xef, 0xbb, 0xb4, 0x75, 0x93, 0x5a, + 0x6b, 0x81, 0xba, 0xc7, 0xf5, 0x01, 0xcf, 0x53, 0xe2, 0x68, 0x47, 0xe5, 0x54, 0x5a, 0x5d, 0x39, 0x76, 0x45, 0x60, + 0x60, 0xe8, 0x1f, 0x52, 0xb6, 0x05, 0x73, 0x3c, 0xb0, 0xb6, 0x41, 0x3f, 0x25, 0xa5, 0x85, 0x19, 0xa3, 0x31, 0x8b, + 0xdc, 0x54, 0xd1, 0x11, 0xd7, 0xd1, 0xdb, 0x79, 0xf4, 0xb7, 0xa7, 0x63, 0x5a, 0xc4, 0x22, 0x95, 0x57, 0xa0, 0x82, + 0x00, 0x65, 0x08, 0x1a, 0xfe, 0x6b, 0x6a, 0x00, 0x1a, 0x04, 0x37, 0x00, 0xff, 0xe8, 0x74, 0x1a, 0xb4, 0x35, 0xf9, + 0x98, 0xa4, 0xaa, 0xc8, 0x79, 0x1b, 0xca, 0x4c, 0x25, 0x87, 0xe4, 0x71, 0x09, 0x78, 0x8e, 0xd8, 0x2c, 0x65, 0x73, + 0xa1, 0x36, 0x9b, 0x7a, 0xad, 0xd8, 0x91, 0xdb, 0x46, 0xd1, 0x66, 0x2d, 0x6a, 0x3b, 0x89, 0xc5, 0x72, 0x7a, 0x6b, + 0x85, 0x81, 0x53, 0xd3, 0x9a, 0x9b, 0x3d, 0xe8, 0x34, 0x5b, 0x9f, 0xc9, 0x4d, 0x80, 0x38, 0xc0, 0x70, 0xdd, 0x2e, + 0x6e, 0x96, 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, + 0x1b, 0xd2, 0x54, 0xa1, 0x47, 0x07, 0x7a, 0x3b, 0x04, 0x34, 0x67, 0x63, 0xba, 0xa2, 0x29, 0x5e, 0xa0, 0xe9, 0x06, + 0xcc, 0x52, 0x2e, 0xa0, 0xaf, 0xdd, 0x3e, 0xc9, 0x17, 0xaa, 0x27, 0xc2, 0x5b, 0xa2, 0xe0, 0xcb, 0x91, 0x82, 0x57, + 0x56, 0xce, 0x63, 0x33, 0x87, 0x80, 0xc7, 0xa2, 0x4a, 0xf4, 0x4e, 0x8a, 0x4b, 0x50, 0xa6, 0xc2, 0x11, 0x68, 0xaa, + 0x46, 0x2c, 0xe1, 0x00, 0xb7, 0x17, 0x4f, 0x03, 0x42, 0x41, 0xaa, 0xbb, 0xb1, 0x2b, 0xf2, 0x96, 0xcd, 0xb6, 0xb7, + 0x60, 0x16, 0x5b, 0x6d, 0xca, 0xd6, 0x57, 0x36, 0xd9, 0x7d, 0x5c, 0x13, 0x6c, 0xbb, 0xb7, 0x41, 0xc2, 0x5b, 0x7a, + 0x43, 0xb6, 0x37, 0xfd, 0x7e, 0x08, 0xfd, 0x21, 0x54, 0x77, 0xe8, 0xb6, 0xb3, 0x43, 0xb7, 0x3e, 0xf3, 0x6b, 0xf5, + 0x7c, 0xca, 0x1b, 0xe2, 0x03, 0x9a, 0x68, 0xd1, 0x75, 0x7c, 0x07, 0x9b, 0x3a, 0xaa, 0xa8, 0xaa, 0x3c, 0x4a, 0x28, + 0xa8, 0x80, 0x33, 0x5e, 0x9e, 0x72, 0x8c, 0x6d, 0xaa, 0x9f, 0xde, 0x69, 0x5e, 0x6d, 0x63, 0xd6, 0x66, 0xb9, 0x39, + 0x07, 0x8b, 0x80, 0x73, 0x1e, 0x5d, 0x69, 0x5a, 0x72, 0xe9, 0x31, 0xf5, 0x67, 0x38, 0x2a, 0xc1, 0x45, 0x9c, 0xe5, + 0x3c, 0x0d, 0xe8, 0x45, 0xb3, 0xff, 0xa1, 0xb6, 0x95, 0x5a, 0x35, 0xce, 0xdc, 0xeb, 0x90, 0x6c, 0xff, 0xc7, 0x06, + 0xea, 0x75, 0x88, 0x11, 0x51, 0xcd, 0x82, 0x7e, 0xcb, 0x20, 0x36, 0x66, 0x50, 0x6e, 0x92, 0x84, 0x97, 0x65, 0x60, + 0x94, 0x5a, 0x1b, 0xb6, 0x31, 0xe7, 0xd9, 0x23, 0x36, 0x7b, 0xd4, 0x63, 0xec, 0x96, 0xd0, 0x44, 0xeb, 0x84, 0x4c, + 0x8d, 0x91, 0xa7, 0x05, 0xd2, 0x1d, 0x8a, 0xb2, 0x8b, 0xf0, 0x2d, 0x0a, 0x59, 0xda, 0xfb, 0xdc, 0x9c, 0xc8, 0xea, + 0x1b, 0x6d, 0x74, 0x11, 0xa9, 0x44, 0x90, 0x8d, 0xdf, 0x20, 0x60, 0x2f, 0x34, 0x3b, 0x20, 0xdb, 0x15, 0x3b, 0xa5, + 0x67, 0xd6, 0x04, 0x06, 0x5e, 0xbf, 0x55, 0x89, 0x66, 0x94, 0x15, 0xd1, 0x55, 0x46, 0x2e, 0x77, 0x21, 0x89, 0xce, + 0x42, 0xe2, 0xe7, 0x86, 0xa5, 0x75, 0x1d, 0xa2, 0x98, 0xd9, 0x6c, 0x78, 0xd5, 0xdd, 0x47, 0x8d, 0x6d, 0x65, 0x7c, + 0xaa, 0x6f, 0x6d, 0x1a, 0x99, 0x42, 0x5f, 0x87, 0x93, 0x7e, 0x1f, 0xfe, 0x6a, 0xfa, 0x81, 0xb7, 0x14, 0xfc, 0xc5, + 0x1e, 0x91, 0x3a, 0x61, 0x01, 0xc0, 0x11, 0xe6, 0xbc, 0x6a, 0x4e, 0xe0, 0x23, 0x36, 0xdb, 0x3e, 0x0a, 0x4f, 0x1b, + 0x33, 0x77, 0x17, 0xe2, 0xa5, 0x2a, 0xe9, 0x79, 0xf3, 0x64, 0x06, 0x62, 0x1d, 0x9a, 0xfd, 0x7a, 0xcb, 0xac, 0x3e, + 0x01, 0x88, 0xd4, 0xad, 0x75, 0x28, 0xc5, 0x8f, 0x4d, 0x97, 0xc9, 0x36, 0x65, 0x6d, 0x26, 0x4a, 0xa9, 0x48, 0x9a, + 0x8b, 0x00, 0xfa, 0x0d, 0xc3, 0x51, 0x03, 0xbc, 0xb7, 0x1e, 0x7b, 0x33, 0x34, 0xde, 0x98, 0x1a, 0x7a, 0xb6, 0xd5, + 0xcb, 0xdb, 0x51, 0x08, 0x33, 0x16, 0xd1, 0xad, 0x3b, 0x16, 0xc3, 0x53, 0xfa, 0x16, 0x2a, 0x7c, 0x1d, 0x62, 0x34, + 0x5d, 0x52, 0xd7, 0xd3, 0x8d, 0xda, 0x4a, 0x37, 0x84, 0xe6, 0x18, 0xc5, 0xc7, 0x6b, 0xdb, 0x1d, 0x35, 0x42, 0x7b, + 0x42, 0x79, 0x78, 0x4b, 0x2b, 0x7a, 0x63, 0x59, 0x04, 0x27, 0x3f, 0xf6, 0xf2, 0x13, 0x7a, 0xee, 0x09, 0x4c, 0x8a, + 0xb6, 0x06, 0xf0, 0x07, 0xd4, 0x0f, 0x67, 0xf5, 0xd4, 0x4a, 0x39, 0x3c, 0x85, 0x2f, 0xd9, 0x82, 0x5c, 0x41, 0x2f, + 0xd6, 0x98, 0xcd, 0x62, 0xd0, 0x41, 0xed, 0xed, 0x0e, 0x6f, 0x52, 0xca, 0x10, 0xad, 0xef, 0x1c, 0xc4, 0xd3, 0x3f, + 0x40, 0xd3, 0x07, 0x69, 0x61, 0x4a, 0x37, 0x28, 0xe0, 0x01, 0x7d, 0x53, 0xbf, 0x9f, 0xe3, 0x73, 0xed, 0x59, 0x62, + 0x61, 0x8f, 0x57, 0x84, 0xae, 0xbc, 0xb8, 0x51, 0x20, 0x6d, 0x76, 0xac, 0x02, 0xb0, 0x22, 0x09, 0x34, 0x22, 0x01, + 0x4b, 0x1d, 0x4f, 0x5c, 0xb6, 0x45, 0x03, 0x92, 0xa8, 0xa4, 0x90, 0x25, 0x92, 0xc0, 0x0f, 0x23, 0x08, 0x51, 0x14, + 0x83, 0xb8, 0x57, 0x2f, 0xaf, 0xb8, 0xa6, 0x06, 0x9c, 0x28, 0x82, 0x09, 0xd6, 0xe9, 0x14, 0x88, 0xad, 0xd8, 0xac, + 0xc1, 0xf3, 0xd2, 0x71, 0xe2, 0xc8, 0x12, 0xa0, 0x41, 0x9a, 0x2f, 0x9d, 0x76, 0xcb, 0xdb, 0x13, 0x2d, 0x55, 0x6c, + 0xe1, 0xbd, 0x58, 0x5a, 0xee, 0xb1, 0xf2, 0xb7, 0x03, 0xed, 0x85, 0xd5, 0x9e, 0x88, 0x1a, 0xac, 0xec, 0xda, 0x76, + 0x6d, 0x28, 0x0d, 0xd5, 0xbd, 0x72, 0x4c, 0x40, 0x45, 0xd7, 0x71, 0xb5, 0x8a, 0xb2, 0x11, 0xfc, 0xd9, 0xed, 0x82, + 0xc3, 0x00, 0x2c, 0x20, 0x7f, 0x79, 0xff, 0x53, 0x84, 0xe1, 0x99, 0x7e, 0x79, 0xff, 0xd3, 0x6e, 0xf7, 0x74, 0x3c, + 0x36, 0x5c, 0x81, 0x53, 0xeb, 0x00, 0x7f, 0x60, 0xd8, 0x06, 0xbb, 0x64, 0x77, 0xbb, 0xa7, 0xc0, 0x41, 0x28, 0xb6, + 0xc1, 0xec, 0x62, 0xe5, 0xc8, 0xa5, 0x58, 0x0d, 0xbd, 0x23, 0x01, 0xab, 0x6e, 0x8f, 0xa5, 0xd8, 0xa7, 0x3e, 0x2a, + 0x04, 0xa3, 0x5e, 0xf4, 0x2f, 0x3a, 0x05, 0x96, 0x14, 0x4c, 0x57, 0x83, 0x55, 0x55, 0xad, 0xcb, 0xe8, 0xf0, 0x30, + 0x5e, 0x67, 0xa3, 0x32, 0x83, 0x6d, 0x5e, 0x5e, 0x5f, 0x02, 0xa0, 0x42, 0x40, 0x1b, 0xef, 0x36, 0x22, 0x33, 0x2f, + 0x96, 0x74, 0x95, 0xe1, 0x9a, 0x04, 0xb3, 0x83, 0x9c, 0x5b, 0xdd, 0xe4, 0x94, 0xd8, 0x07, 0xb0, 0x39, 0xdc, 0xed, + 0x1a, 0xfc, 0xc2, 0x6c, 0xf4, 0x74, 0xbe, 0xca, 0xb4, 0x41, 0x27, 0x37, 0xfb, 0x9f, 0x44, 0x5e, 0x1a, 0x2a, 0x3e, + 0xc9, 0xf4, 0x45, 0x06, 0x7c, 0x1e, 0x7b, 0x23, 0x42, 0x9f, 0xe5, 0x6a, 0xb4, 0x06, 0xd8, 0xd8, 0xec, 0xe2, 0x6e, + 0x94, 0x72, 0x88, 0x48, 0x11, 0x58, 0x75, 0xcd, 0x2a, 0x23, 0xbe, 0x4d, 0xc5, 0x5d, 0x4b, 0x15, 0xf6, 0x46, 0x78, + 0xce, 0x2a, 0xdc, 0x38, 0xca, 0xf4, 0x26, 0x51, 0xf8, 0x02, 0x85, 0xa8, 0x1c, 0x8d, 0xe9, 0x9c, 0x40, 0x2a, 0xf3, + 0x98, 0x50, 0xcc, 0xe1, 0xde, 0xfd, 0x92, 0x3a, 0x73, 0x19, 0x5f, 0xb8, 0xf7, 0xc2, 0x97, 0x99, 0xdc, 0x4a, 0x00, + 0x45, 0x52, 0xb5, 0xff, 0xfc, 0x09, 0xa9, 0xf1, 0x3f, 0x53, 0xad, 0x01, 0xe8, 0xfd, 0x0c, 0x35, 0x39, 0x82, 0x80, + 0xad, 0x98, 0xfa, 0x68, 0xfa, 0x56, 0x32, 0xff, 0x01, 0x75, 0x3b, 0x82, 0x6d, 0x55, 0xfc, 0x9c, 0xa8, 0xa2, 0x05, + 0x4f, 0x37, 0x22, 0x8d, 0x45, 0x72, 0x17, 0xf1, 0x7a, 0x8a, 0x25, 0x31, 0x1b, 0x21, 0xeb, 0xe7, 0x66, 0x17, 0x7e, + 0x2a, 0x1a, 0x26, 0xe0, 0xb4, 0xf4, 0xb7, 0x95, 0xb7, 0x99, 0x2c, 0xe3, 0x8c, 0x4c, 0xb9, 0x42, 0xec, 0xb6, 0xfa, + 0x1e, 0x73, 0x82, 0x3f, 0x39, 0x7a, 0x42, 0xe8, 0xad, 0x9c, 0x96, 0x08, 0x4a, 0x27, 0x52, 0xeb, 0xaa, 0x89, 0xfd, + 0x9a, 0x42, 0x14, 0x07, 0xc1, 0x20, 0x74, 0xa7, 0x69, 0x9f, 0xe2, 0xfb, 0x6c, 0xd9, 0x6f, 0x4c, 0xd9, 0x92, 0x6c, + 0x05, 0x74, 0x4c, 0x3a, 0x6f, 0x4f, 0x6f, 0xcf, 0xce, 0xbd, 0xdf, 0xa0, 0x09, 0x07, 0xd5, 0x0d, 0xb4, 0xab, 0x20, + 0xd3, 0x18, 0xc5, 0x66, 0x31, 0xd6, 0x6e, 0x4d, 0x44, 0x10, 0x74, 0xba, 0x9c, 0x87, 0xed, 0x76, 0x42, 0x7c, 0x09, + 0x24, 0x50, 0xe0, 0xca, 0x45, 0x39, 0x09, 0x89, 0xba, 0x90, 0xe9, 0xc9, 0xba, 0x96, 0x2c, 0xd0, 0x6b, 0xec, 0x28, + 0xa0, 0x27, 0xdc, 0x3e, 0x05, 0xf4, 0x7d, 0xc1, 0x4e, 0xf8, 0x20, 0x18, 0x62, 0x7c, 0xd5, 0x80, 0xde, 0x48, 0xf5, + 0x08, 0x1e, 0xc2, 0xc0, 0x72, 0xd1, 0x97, 0x05, 0x43, 0x58, 0xa1, 0x3f, 0x53, 0x36, 0xf9, 0xfa, 0x1b, 0x37, 0xbf, + 0xe7, 0x5a, 0xcc, 0x0e, 0x42, 0x71, 0x7b, 0x3d, 0x01, 0xe2, 0x57, 0xf1, 0x2b, 0xb0, 0xae, 0xd6, 0x12, 0x6f, 0x37, + 0x3d, 0x7f, 0x08, 0x5f, 0x8e, 0x6e, 0x3f, 0x29, 0xcd, 0x27, 0x10, 0xa4, 0xc6, 0x49, 0xca, 0xdd, 0x77, 0x1f, 0xa5, + 0xab, 0x08, 0x46, 0x0b, 0x10, 0xeb, 0xee, 0xad, 0xe4, 0xac, 0x29, 0xfc, 0xc7, 0x3a, 0xdf, 0x63, 0xec, 0x10, 0x79, + 0x8a, 0xd3, 0xdf, 0x00, 0xc3, 0xbe, 0xf3, 0x6f, 0x65, 0xd6, 0x90, 0xe8, 0x5c, 0x7d, 0x04, 0xf4, 0x7f, 0xac, 0xc7, + 0xef, 0x04, 0x25, 0x7d, 0x49, 0x9c, 0x23, 0x5c, 0x11, 0x2f, 0xd1, 0x54, 0xaf, 0x37, 0xae, 0xe9, 0x5f, 0x85, 0x79, + 0xa1, 0x15, 0x1c, 0xf6, 0xad, 0x51, 0x78, 0xe0, 0x99, 0xf7, 0xab, 0x68, 0x08, 0xba, 0x7f, 0xc3, 0xbd, 0xf1, 0xab, + 0x60, 0x19, 0xde, 0x94, 0xb3, 0xcc, 0xdc, 0xe1, 0x6e, 0x32, 0x91, 0xca, 0x1b, 0xc6, 0x82, 0x8d, 0x50, 0xe6, 0xab, + 0x69, 0x30, 0xdf, 0xd6, 0x91, 0x4a, 0x76, 0xdf, 0xbf, 0x69, 0x9c, 0xb0, 0xd9, 0x20, 0x38, 0xad, 0x64, 0x11, 0x5f, + 0xf2, 0x60, 0xaa, 0x55, 0x14, 0x59, 0xd6, 0xef, 0x67, 0x80, 0x0c, 0xe3, 0xb4, 0x77, 0xf0, 0x64, 0xa9, 0x99, 0x09, + 0x71, 0x6d, 0x75, 0x16, 0xf0, 0xd6, 0x8c, 0xe6, 0x49, 0x05, 0xbb, 0xcc, 0x57, 0x52, 0xfc, 0xd1, 0x92, 0x64, 0x63, + 0xfd, 0x0d, 0x19, 0xb6, 0x95, 0xcf, 0x9c, 0x03, 0xc6, 0xcc, 0x8d, 0x54, 0x41, 0xee, 0x7a, 0xc0, 0x08, 0x21, 0x11, + 0x10, 0xce, 0x62, 0xe2, 0x4e, 0x98, 0xf0, 0x8f, 0x2e, 0x30, 0x4e, 0x8c, 0x81, 0x71, 0x3e, 0xca, 0x90, 0xd3, 0x13, + 0x3e, 0x48, 0x1a, 0xb3, 0xf5, 0x87, 0x2a, 0x91, 0x5e, 0x4b, 0x42, 0xcf, 0xe0, 0xf7, 0xb8, 0xc5, 0x03, 0x35, 0x82, + 0x53, 0xba, 0x9b, 0xd3, 0xe1, 0xcb, 0x82, 0x0c, 0xff, 0x04, 0xef, 0xae, 0xd8, 0x5e, 0x96, 0x13, 0x58, 0xdc, 0xb1, + 0x57, 0x3c, 0xcd, 0x55, 0x8b, 0x13, 0xe2, 0x11, 0x8b, 0xdc, 0x27, 0x16, 0x30, 0xa2, 0x86, 0xd1, 0xf8, 0xf1, 0xf4, + 0xed, 0x1b, 0x8d, 0xd9, 0x94, 0xfb, 0x1f, 0xc0, 0x88, 0x6a, 0x69, 0xbb, 0x1d, 0xf0, 0xd5, 0x08, 0x0d, 0xb6, 0x53, + 0x37, 0xd8, 0xfd, 0xbe, 0x49, 0x9b, 0x95, 0x5e, 0x36, 0x27, 0x06, 0xdd, 0x53, 0xda, 0xac, 0x94, 0x41, 0x6d, 0x57, + 0xe1, 0x68, 0x3e, 0x6b, 0xc4, 0xaa, 0xde, 0x87, 0xe1, 0x8a, 0xc6, 0x56, 0x56, 0x6e, 0x77, 0x13, 0x8e, 0x6c, 0x02, + 0x5c, 0x9f, 0x82, 0xb2, 0x6a, 0xce, 0x41, 0x0b, 0x3a, 0x13, 0x38, 0xa2, 0xdd, 0x2e, 0x84, 0x08, 0x1c, 0xc5, 0x70, + 0x32, 0x0f, 0x8b, 0xe1, 0x50, 0x0d, 0x7c, 0x41, 0x48, 0xf4, 0x57, 0xb1, 0xc8, 0x96, 0x0a, 0xb1, 0xc7, 0xdf, 0x49, + 0xbf, 0x16, 0x8a, 0x53, 0xee, 0xfd, 0x2a, 0xc8, 0xf6, 0xb7, 0x14, 0x63, 0x0e, 0x3a, 0xcd, 0x66, 0x06, 0x12, 0xd6, + 0x93, 0x8a, 0xa8, 0x75, 0x64, 0x67, 0x03, 0x54, 0xb1, 0x68, 0x0a, 0x0b, 0xea, 0x16, 0x4f, 0xac, 0x67, 0xf4, 0x1e, + 0x54, 0x82, 0xa8, 0x16, 0xec, 0xc6, 0x70, 0xad, 0xfd, 0x25, 0x42, 0x49, 0x39, 0x69, 0x32, 0x33, 0x56, 0x34, 0x58, + 0x80, 0x90, 0x34, 0x2e, 0xab, 0xd7, 0x32, 0xcd, 0x2e, 0x32, 0x40, 0x4c, 0x70, 0xfe, 0x73, 0xb2, 0xf1, 0xe6, 0x99, + 0x9a, 0x97, 0xae, 0xc4, 0xb9, 0x85, 0xf9, 0xe8, 0x7a, 0x4b, 0x0b, 0x12, 0x15, 0x40, 0xa3, 0x7c, 0x2d, 0xcf, 0xdf, + 0xf7, 0xac, 0x42, 0xf6, 0x3f, 0x9c, 0x2a, 0xdb, 0x21, 0x3e, 0x63, 0x15, 0xf1, 0x4e, 0xeb, 0x4a, 0x89, 0x34, 0x3a, + 0xda, 0x06, 0xc4, 0xb0, 0x65, 0xdf, 0xa2, 0x86, 0x0f, 0xc2, 0x0c, 0x3a, 0xc9, 0x0f, 0x7a, 0x46, 0xc7, 0xd6, 0x40, + 0xd2, 0xd7, 0x22, 0xf8, 0x1a, 0x1d, 0xe9, 0x44, 0x99, 0x46, 0x62, 0x0a, 0x89, 0x7e, 0xbd, 0xd0, 0x1a, 0xcb, 0x28, + 0xfb, 0x8a, 0xfc, 0xef, 0x75, 0xf7, 0x7e, 0x15, 0xbb, 0x1d, 0x4c, 0xb2, 0xe7, 0x71, 0x05, 0x9b, 0x1a, 0xb5, 0x42, + 0x38, 0x3b, 0x27, 0x15, 0x6a, 0xc7, 0x7a, 0x61, 0x09, 0xe4, 0x01, 0x6c, 0x45, 0x1a, 0x94, 0x41, 0xb2, 0xbf, 0x8a, + 0x85, 0x58, 0x3a, 0x51, 0x8e, 0x54, 0x78, 0x5f, 0x72, 0x94, 0x72, 0xb8, 0x8a, 0x85, 0x05, 0x43, 0x7e, 0x75, 0x74, + 0x51, 0xc8, 0x2b, 0x90, 0x94, 0x18, 0x86, 0xca, 0xf2, 0xba, 0xb8, 0x6a, 0x4b, 0x42, 0x7b, 0x67, 0x00, 0xc2, 0x52, + 0x80, 0xe0, 0xa5, 0x51, 0x43, 0xcc, 0xb6, 0x6a, 0x77, 0x45, 0xf7, 0x92, 0x03, 0xea, 0x74, 0xd7, 0x6e, 0xbd, 0x29, + 0xdb, 0x6c, 0x2b, 0x2e, 0xfc, 0x03, 0x4a, 0x3f, 0xe1, 0x83, 0xc2, 0xa7, 0x12, 0xb8, 0xf1, 0xd5, 0x26, 0xcb, 0x2e, + 0xee, 0x70, 0xe9, 0x57, 0x8d, 0xf1, 0xeb, 0xf7, 0x7b, 0x6a, 0x21, 0x34, 0x52, 0x81, 0xf9, 0xf6, 0x99, 0xa9, 0xca, + 0x68, 0x4a, 0xed, 0x25, 0xb8, 0x72, 0xf6, 0x23, 0xa8, 0x88, 0xeb, 0x8a, 0x4c, 0xa6, 0x06, 0xe8, 0xc0, 0xcb, 0x0a, + 0xb7, 0xb2, 0x00, 0x8f, 0x9d, 0x80, 0xec, 0x76, 0x3c, 0x0c, 0xf4, 0xa1, 0x13, 0xf8, 0x5b, 0xf2, 0x14, 0x99, 0x35, + 0xfb, 0xf8, 0xb3, 0x16, 0xfc, 0x63, 0x0b, 0x7e, 0x42, 0x71, 0xa7, 0x95, 0xf9, 0xb7, 0xd2, 0xba, 0xc5, 0xfd, 0x7b, + 0x99, 0x26, 0x14, 0x95, 0x09, 0xb5, 0x5f, 0xe9, 0xbf, 0x4c, 0xb0, 0x24, 0x95, 0xfd, 0x83, 0x84, 0x0f, 0xe6, 0x8d, + 0x27, 0xd6, 0x78, 0x32, 0x9c, 0x6e, 0xa5, 0x61, 0x08, 0x50, 0xe8, 0xe7, 0x65, 0xae, 0xa8, 0x7e, 0xfe, 0x79, 0xc3, + 0x37, 0xbc, 0xd9, 0x62, 0x9b, 0xf4, 0x40, 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, 0x09, 0xb0, 0xc2, 0x05, 0x38, 0x82, 0x7e, 0x2a, 0x42, + 0x0e, 0xd7, 0x54, 0xa5, 0x5f, 0xd0, 0x94, 0x3c, 0xf1, 0x14, 0xb5, 0x5a, 0x91, 0x6e, 0x3f, 0xca, 0xb1, 0x1b, 0xbe, + 0x71, 0x42, 0x4e, 0x8c, 0xd0, 0xdf, 0x1d, 0x4b, 0x39, 0x43, 0x8b, 0x07, 0x75, 0x82, 0xf5, 0xf2, 0x96, 0x02, 0xc5, + 0x1c, 0x5d, 0x56, 0x5d, 0xf3, 0x0a, 0x6d, 0x5f, 0x56, 0xfd, 0x7e, 0x6e, 0xeb, 0x49, 0xd9, 0x6c, 0xbb, 0x32, 0xfb, + 0x10, 0x15, 0x53, 0xb8, 0xeb, 0x13, 0xcd, 0x5f, 0x85, 0xfa, 0xaa, 0x2d, 0x73, 0x3e, 0xe2, 0x88, 0x8b, 0x91, 0x93, + 0xfa, 0x67, 0x35, 0xf5, 0x4a, 0xdc, 0xaf, 0x2a, 0xf9, 0x4e, 0x18, 0x2b, 0x46, 0x07, 0xd4, 0x9f, 0x2a, 0x95, 0xf7, + 0x8b, 0x02, 0xe0, 0x9e, 0x04, 0xfb, 0x0b, 0xec, 0x2b, 0x34, 0xc2, 0x6f, 0x4b, 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, + 0x29, 0xca, 0xb8, 0x55, 0x66, 0xef, 0xc6, 0xd8, 0x69, 0x81, 0xd7, 0xf0, 0xe7, 0xf3, 0x42, 0x0f, 0x1b, 0x75, 0x90, + 0x1e, 0x9d, 0xc4, 0xf4, 0xc7, 0x2d, 0x9c, 0xdc, 0x2c, 0x9c, 0x55, 0xcd, 0x12, 0xe8, 0x0e, 0x5c, 0x10, 0xe3, 0x7e, + 0x3f, 0x87, 0x23, 0xd3, 0x8c, 0x7c, 0xc1, 0x72, 0x1a, 0xb3, 0x15, 0xd5, 0x9e, 0x76, 0x97, 0x55, 0x98, 0xd3, 0x95, + 0x95, 0xf1, 0xa6, 0x0c, 0x54, 0x46, 0xbb, 0x5d, 0x08, 0x7f, 0xba, 0xad, 0x5d, 0xd2, 0xc5, 0x0a, 0x32, 0xc0, 0x1f, + 0x90, 0x88, 0x22, 0xf6, 0xf5, 0xbf, 0xd5, 0x38, 0xa5, 0x27, 0x4a, 0x6b, 0x96, 0xd0, 0x0d, 0xd3, 0xf5, 0xd3, 0x0b, + 0xb6, 0x69, 0x2c, 0x85, 0xdd, 0x2e, 0x6c, 0x26, 0x30, 0xcd, 0xb9, 0x92, 0xe9, 0x05, 0xea, 0xa4, 0x80, 0x8a, 0x85, + 0x17, 0xb8, 0xfc, 0x52, 0x42, 0xa1, 0xb9, 0x8b, 0xd5, 0xd2, 0x28, 0x31, 0xa1, 0x55, 0xf2, 0xf3, 0x87, 0xca, 0x7c, + 0x6d, 0x3c, 0xe2, 0xfe, 0x95, 0x86, 0x89, 0x29, 0x12, 0x15, 0xa2, 0xf3, 0x5f, 0x41, 0x96, 0x23, 0x00, 0xc7, 0xf2, + 0x54, 0xd6, 0xf4, 0xc7, 0x14, 0xe2, 0xa0, 0x43, 0x83, 0xde, 0x15, 0xf2, 0x2a, 0x2b, 0x79, 0x88, 0xf7, 0x04, 0x4f, + 0x33, 0x7a, 0xbf, 0xc1, 0x87, 0xb6, 0xf6, 0xe8, 0x09, 0xb2, 0xf5, 0x94, 0xfb, 0xf5, 0x77, 0x22, 0x5c, 0x40, 0xb4, + 0xca, 0x25, 0xd5, 0xea, 0x6a, 0x07, 0x40, 0xe5, 0xd9, 0x5e, 0x3d, 0x82, 0xd3, 0x4d, 0x5f, 0xdf, 0xaa, 0xd0, 0x99, + 0x03, 0x48, 0x7b, 0x48, 0xd6, 0x35, 0xd7, 0x3b, 0xc0, 0x1d, 0x89, 0xd5, 0x06, 0x68, 0xac, 0xdb, 0x9a, 0x9d, 0xf6, + 0x28, 0x1e, 0x13, 0x99, 0x19, 0x8b, 0x14, 0x63, 0xee, 0xd6, 0x69, 0x51, 0xb4, 0x45, 0x33, 0x84, 0xfd, 0xbb, 0x0e, + 0xdf, 0xb4, 0x22, 0xac, 0xdf, 0x6f, 0xfb, 0x02, 0xa3, 0x61, 0xcc, 0xb5, 0x7b, 0x9e, 0xa1, 0x1b, 0x36, 0xd8, 0x46, + 0xce, 0x43, 0xe4, 0xc3, 0x4c, 0x1d, 0x88, 0xb2, 0xb6, 0x06, 0x6c, 0x8f, 0xb8, 0xde, 0xb4, 0x8a, 0x9f, 0x57, 0x31, + 0x67, 0x7b, 0xd6, 0x38, 0xa5, 0xf5, 0x35, 0xae, 0x39, 0xae, 0x0a, 0x11, 0xb5, 0xf5, 0x8c, 0x87, 0x61, 0xe7, 0x4b, + 0xdc, 0x99, 0x15, 0x06, 0x2f, 0xc2, 0x52, 0xc9, 0x5e, 0xe5, 0xfa, 0x73, 0xd8, 0xe2, 0x20, 0x95, 0x2f, 0xbd, 0xfe, + 0xfe, 0xcb, 0x17, 0x5f, 0xa0, 0x9b, 0x9a, 0xf3, 0x23, 0x08, 0x32, 0x81, 0x0e, 0x59, 0x4a, 0xf5, 0xf8, 0x5d, 0x01, + 0xd4, 0x1e, 0xe6, 0xe1, 0xbb, 0x82, 0x89, 0xf8, 0x3a, 0xbb, 0x8c, 0x2b, 0x59, 0x8c, 0xae, 0xb9, 0x48, 0x65, 0x61, + 0xa5, 0xc6, 0xc1, 0xc9, 0x7a, 0x9d, 0xf3, 0x00, 0x4c, 0xe5, 0x2d, 0xa3, 0x6c, 0x2b, 0xcb, 0xf4, 0xe0, 0x6a, 0x79, + 0x7a, 0xa5, 0x45, 0xe7, 0xe5, 0xf5, 0x65, 0x10, 0xe1, 0xaf, 0x73, 0xf3, 0xe3, 0x2a, 0x2e, 0x3f, 0x06, 0x91, 0xb5, + 0xa9, 0x33, 0x3f, 0x50, 0x2a, 0x0f, 0xfe, 0x53, 0x20, 0xd3, 0xfd, 0xae, 0x00, 0xcb, 0x6c, 0x5b, 0xf1, 0x71, 0x8c, + 0xb5, 0x0e, 0x27, 0x64, 0xae, 0x4a, 0xf4, 0xde, 0x25, 0x9b, 0x02, 0xac, 0xfd, 0x14, 0x96, 0xb1, 0xca, 0x35, 0xc7, + 0xca, 0x54, 0x45, 0x66, 0x56, 0x36, 0xec, 0x30, 0xb4, 0x4e, 0x34, 0x0b, 0xf4, 0x16, 0xd0, 0x0f, 0xe4, 0xf0, 0x92, + 0x96, 0x1b, 0xe6, 0xf9, 0xd8, 0x34, 0x5e, 0x3f, 0x3a, 0xbc, 0x74, 0x0b, 0xf6, 0xd6, 0xde, 0xc9, 0x51, 0x98, 0x08, + 0x9e, 0xb5, 0x66, 0x7c, 0x91, 0x67, 0x05, 0xac, 0x9c, 0xc9, 0x78, 0x4c, 0xbd, 0xa5, 0xd5, 0xba, 0x39, 0x3a, 0x24, + 0xd7, 0xec, 0x71, 0xf5, 0x98, 0x93, 0x43, 0xde, 0x32, 0xb5, 0x6d, 0x5b, 0xc7, 0x79, 0x9a, 0x7c, 0x65, 0xba, 0x2f, + 0x36, 0x36, 0x22, 0xba, 0x72, 0xee, 0x73, 0x5e, 0xc1, 0xad, 0x6f, 0x4a, 0x43, 0xaf, 0x25, 0x00, 0xd1, 0x69, 0x03, + 0xfe, 0x82, 0x95, 0x9b, 0x51, 0xc5, 0xcb, 0x0a, 0x24, 0x2c, 0x28, 0xc2, 0x9b, 0x62, 0x6f, 0x0a, 0x77, 0xe3, 0xf4, + 0x1c, 0x76, 0xe0, 0x62, 0x8a, 0xee, 0x38, 0x31, 0x99, 0x97, 0x46, 0x2b, 0x1a, 0xe9, 0x5f, 0xae, 0x2f, 0xb1, 0xee, + 0x8b, 0x56, 0xe6, 0xd9, 0x9c, 0x0a, 0x8b, 0xdd, 0x55, 0x2e, 0x9d, 0xa8, 0xdf, 0x32, 0xe1, 0xca, 0x95, 0x20, 0x20, + 0xd3, 0x82, 0xf5, 0x0a, 0xb3, 0x8b, 0xe4, 0x06, 0x08, 0x19, 0x18, 0xbe, 0x06, 0x1b, 0x51, 0x72, 0x63, 0x05, 0xeb, + 0xdd, 0xf3, 0x75, 0x82, 0x90, 0x82, 0x07, 0x6e, 0x82, 0x7e, 0x68, 0xdd, 0xbc, 0x1d, 0x25, 0xca, 0x20, 0x1e, 0xb7, + 0x76, 0xca, 0x41, 0x02, 0x01, 0xb8, 0xa7, 0x2a, 0x04, 0x87, 0x02, 0x59, 0x07, 0x57, 0x33, 0x8e, 0xe0, 0xea, 0xca, + 0x99, 0x8b, 0x1b, 0x80, 0x75, 0xe5, 0xcf, 0x65, 0x83, 0x0b, 0xeb, 0x11, 0x55, 0xe6, 0x8c, 0x53, 0x0c, 0x62, 0x64, + 0x09, 0xfa, 0xda, 0x52, 0xda, 0x4b, 0xd0, 0x34, 0x5e, 0xb1, 0xb5, 0xf2, 0x01, 0xa0, 0xe7, 0x6c, 0xad, 0x8c, 0xfd, + 0xf1, 0xeb, 0x33, 0xb6, 0xd6, 0xd2, 0xe0, 0xe9, 0xd5, 0xfc, 0x7c, 0x7e, 0x36, 0x60, 0x47, 0x51, 0xa8, 0x0d, 0x18, + 0x02, 0x87, 0xc4, 0x1f, 0x0c, 0x42, 0x8d, 0x77, 0x32, 0x50, 0x01, 0xb1, 0x88, 0xc7, 0x63, 0x23, 0x6e, 0x56, 0x38, + 0x1e, 0x62, 0xf0, 0xab, 0xe6, 0x0b, 0x12, 0x10, 0x6a, 0x4a, 0x43, 0x97, 0xc7, 0x70, 0x38, 0x39, 0x98, 0x40, 0x2a, + 0x66, 0x66, 0xaa, 0x30, 0x36, 0x26, 0x11, 0xc4, 0x3b, 0xed, 0xac, 0x17, 0xca, 0xed, 0xae, 0xd1, 0x40, 0xae, 0x0c, + 0x3e, 0xab, 0xe2, 0xc9, 0xc1, 0xb0, 0xab, 0x62, 0x1c, 0x85, 0x6b, 0xa3, 0x7c, 0x3b, 0x3b, 0x06, 0xf0, 0xda, 0xb3, + 0xa1, 0x2f, 0x97, 0x38, 0x3b, 0x7c, 0x42, 0x1e, 0x3f, 0x21, 0xf4, 0x8c, 0x9d, 0x7d, 0xf1, 0x84, 0x9e, 0x29, 0x72, + 0x72, 0x30, 0x89, 0xae, 0x99, 0xc5, 0x7c, 0x39, 0x52, 0x4d, 0xa0, 0x97, 0xa3, 0x8d, 0x50, 0x0b, 0x4c, 0x3b, 0x34, + 0x85, 0xdf, 0x8e, 0x0f, 0x82, 0xc1, 0x75, 0xbb, 0xe9, 0xd7, 0xed, 0xb6, 0x7a, 0x5e, 0x5d, 0x07, 0x47, 0xd1, 0x7e, + 0x31, 0x93, 0x6f, 0xc6, 0x07, 0x6e, 0x0e, 0xb0, 0xbe, 0x87, 0xc7, 0xc4, 0x34, 0x69, 0x6f, 0x54, 0xfc, 0x9a, 0xbe, + 0xc2, 0x3e, 0x34, 0x8b, 0xec, 0xe8, 0xc3, 0xf0, 0xdf, 0xea, 0x44, 0x7d, 0xf6, 0xc5, 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, 0xe8, 0x46, 0xda, 0xc9, 0xcc, 0xbc, 0xa4, 0x36, 0xae, + 0xdb, 0x35, 0x04, 0x30, 0x76, 0xf0, 0x82, 0x92, 0x7d, 0x79, 0x7c, 0x79, 0x80, 0xab, 0x08, 0x50, 0xb2, 0x58, 0xf0, + 0xe5, 0xe0, 0x52, 0x6f, 0xee, 0x83, 0x80, 0x0c, 0xbe, 0x0c, 0x66, 0x5f, 0x0e, 0xe4, 0x20, 0x38, 0x3e, 0xbc, 0x9c, + 0x05, 0xce, 0xb8, 0x1f, 0x42, 0x3c, 0xaa, 0x8a, 0x62, 0x26, 0x4c, 0x15, 0x89, 0xad, 0x3d, 0xb7, 0xf5, 0x2a, 0xe3, + 0x33, 0x9a, 0x4e, 0x2d, 0xf2, 0x77, 0x98, 0xb2, 0xd8, 0xfc, 0x0e, 0x26, 0xfc, 0x2a, 0x88, 0x5c, 0x10, 0xd4, 0x79, + 0x1e, 0xc5, 0x74, 0xc5, 0x6e, 0x45, 0x98, 0xd2, 0xe4, 0x30, 0x27, 0x24, 0x0a, 0x57, 0x0a, 0x3c, 0x4f, 0xbd, 0x4e, + 0x20, 0x8e, 0xab, 0xfb, 0xfc, 0x56, 0x84, 0x2b, 0x9a, 0x1f, 0x26, 0xa4, 0x55, 0x84, 0x8b, 0xc8, 0xb2, 0xad, 0xe9, + 0x05, 0x0b, 0xd7, 0xf4, 0x12, 0x98, 0x29, 0xb9, 0x09, 0x2f, 0x81, 0xcb, 0xdb, 0x2c, 0xd6, 0x4b, 0x76, 0xd9, 0x90, + 0xbe, 0x19, 0xbe, 0xf8, 0xc2, 0xfa, 0xe4, 0x01, 0x0f, 0xe9, 0xfc, 0xf0, 0x52, 0xb0, 0x01, 0xb8, 0xce, 0xf8, 0xcd, + 0x77, 0xf2, 0x56, 0xcf, 0x4b, 0x7b, 0x8a, 0x71, 0x66, 0xda, 0x89, 0x49, 0x3b, 0x21, 0xf7, 0xef, 0xdb, 0xdb, 0xd8, + 0x9c, 0xec, 0x65, 0xb4, 0x51, 0x2e, 0xab, 0x96, 0x21, 0x29, 0x36, 0x0c, 0xf9, 0x7b, 0x94, 0x9c, 0x5a, 0x81, 0x27, + 0xbb, 0xe0, 0x55, 0xb2, 0xf2, 0x0f, 0x2a, 0x6b, 0x35, 0x60, 0x8f, 0x11, 0xcb, 0x42, 0xe1, 0xd8, 0xbf, 0xce, 0x58, + 0xb1, 0xf1, 0x05, 0x1a, 0x31, 0x72, 0x6f, 0xaf, 0x33, 0xe6, 0xc5, 0x5c, 0x4d, 0x36, 0x5e, 0xa8, 0x3a, 0x2f, 0x3d, + 0x6f, 0xf1, 0x5e, 0x4e, 0xa9, 0x61, 0x24, 0xa2, 0x07, 0x63, 0x65, 0x46, 0xa9, 0x12, 0xb5, 0x06, 0x8d, 0x08, 0x36, + 0x76, 0xc1, 0x2f, 0xc1, 0x09, 0x95, 0x7b, 0xea, 0x6c, 0xdf, 0x4e, 0xa9, 0xf4, 0x80, 0x65, 0xa9, 0x51, 0x95, 0xbb, + 0x65, 0x26, 0x59, 0x35, 0x08, 0x46, 0x7f, 0x94, 0x52, 0xcc, 0xf1, 0xce, 0xc8, 0x82, 0x29, 0x58, 0x09, 0xaa, 0x5a, + 0x86, 0xe5, 0x90, 0xa3, 0x16, 0xcf, 0xf8, 0xa4, 0x4a, 0xfd, 0xa3, 0x23, 0x48, 0xee, 0x6a, 0xd3, 0x0a, 0x92, 0xfb, + 0x64, 0xfc, 0x44, 0x0f, 0x74, 0xba, 0xd1, 0x8e, 0x87, 0x3e, 0xbf, 0x8d, 0xf8, 0xda, 0xba, 0xf7, 0x54, 0x6b, 0x15, + 0xca, 0x40, 0x8b, 0x15, 0x95, 0x2b, 0xb5, 0xa4, 0xf7, 0xbb, 0x08, 0x80, 0x45, 0x6c, 0xcc, 0xc6, 0xfb, 0xb6, 0x59, + 0x21, 0x68, 0x74, 0xd9, 0x6c, 0x1b, 0x0f, 0x58, 0xa2, 0x5b, 0x3b, 0x98, 0xd0, 0x78, 0xc6, 0xca, 0x7e, 0x3f, 0x9f, + 0x01, 0x3d, 0xd5, 0x46, 0x4c, 0x05, 0x1c, 0xf9, 0x9f, 0x5b, 0x91, 0x29, 0x0a, 0x6c, 0xd6, 0xd4, 0xdd, 0x1a, 0xcb, + 0x48, 0xf4, 0x65, 0x4a, 0x97, 0x27, 0x3c, 0x03, 0xa6, 0xcd, 0xa6, 0xe5, 0xb8, 0xb2, 0xaf, 0x38, 0xf2, 0x54, 0x58, + 0x56, 0x9c, 0x57, 0xe1, 0x78, 0xeb, 0xf1, 0x0d, 0x0e, 0x0d, 0x9b, 0x76, 0xe1, 0x0f, 0x21, 0x2c, 0x84, 0xd7, 0x19, + 0xdc, 0x46, 0xb4, 0x9d, 0x04, 0x2a, 0x6f, 0xcc, 0x75, 0x42, 0xd9, 0xdc, 0x6e, 0x36, 0x9e, 0x41, 0x3a, 0x31, 0x07, + 0x4a, 0x35, 0x82, 0xd6, 0x68, 0x16, 0x54, 0x8d, 0x78, 0xe4, 0x78, 0x78, 0x67, 0x10, 0xab, 0xe5, 0x4b, 0x9a, 0x4a, + 0xd1, 0x00, 0x8c, 0x0b, 0xe0, 0xf2, 0xf4, 0xcb, 0xfb, 0x9f, 0x4e, 0x79, 0x5c, 0x24, 0xab, 0x77, 0x71, 0x11, 0x5f, + 0x95, 0xe1, 0x56, 0x8d, 0x51, 0x5c, 0x93, 0xa9, 0x18, 0x30, 0x69, 0x56, 0x52, 0x73, 0x57, 0x6a, 0x42, 0x8c, 0x75, + 0x26, 0x9b, 0xb2, 0x92, 0x57, 0x8d, 0x4a, 0x37, 0x45, 0x86, 0x1f, 0xb7, 0x7c, 0x4e, 0x0f, 0x01, 0xc8, 0xd3, 0xb8, + 0x90, 0x46, 0x52, 0x17, 0x62, 0xcc, 0x45, 0xbc, 0xae, 0x8f, 0xc7, 0x8d, 0xae, 0x97, 0xec, 0xe9, 0xf8, 0xab, 0xe9, + 0xeb, 0x2c, 0xcc, 0x06, 0x82, 0x8c, 0xaa, 0x15, 0x17, 0x2d, 0x53, 0x4e, 0x65, 0x12, 0x80, 0x3e, 0x9e, 0x3d, 0xc6, + 0x8e, 0xc6, 0x63, 0xb2, 0x6d, 0x8b, 0x07, 0x78, 0xb8, 0xda, 0x84, 0x05, 0x99, 0xeb, 0x3a, 0xa2, 0x40, 0xf0, 0xdb, + 0x2a, 0x00, 0x24, 0x47, 0x5b, 0x95, 0xe1, 0xd2, 0xd8, 0xd3, 0xf1, 0x84, 0x4a, 0xec, 0x76, 0x48, 0x6a, 0xaf, 0x42, + 0x37, 0xf3, 0xd2, 0xf7, 0x28, 0x92, 0xc6, 0x65, 0x69, 0xaf, 0x52, 0xa9, 0xf6, 0xcc, 0xdc, 0x75, 0x0d, 0x62, 0x30, + 0x84, 0xba, 0xee, 0xd2, 0xab, 0x7b, 0xbf, 0xb9, 0xd6, 0x6c, 0x07, 0xbc, 0xd7, 0xa0, 0x19, 0x4a, 0xde, 0x62, 0xde, + 0xba, 0x22, 0x6a, 0xba, 0xde, 0x80, 0x59, 0x31, 0xca, 0x96, 0xa2, 0x74, 0x43, 0x41, 0x29, 0x18, 0x5d, 0x6c, 0xbc, + 0x85, 0xfb, 0x5a, 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, 0x93, 0x8a, 0x9c, 0x80, 0xa3, 0x97, 0xc9, 0x69, + 0x28, 0xf0, 0x8f, 0x99, 0x02, 0x31, 0x1d, 0xaa, 0xfb, 0x0d, 0x6e, 0xfe, 0x7f, 0x14, 0x2c, 0xf0, 0xf8, 0xd6, 0x4b, + 0xdc, 0x46, 0xff, 0x28, 0x7c, 0x5a, 0xfa, 0x4c, 0xfa, 0xae, 0x2e, 0x9e, 0xb4, 0x37, 0x1b, 0x25, 0xab, 0x2c, 0x4f, + 0xdf, 0xc8, 0x94, 0x83, 0xc8, 0x0c, 0xad, 0x41, 0xd9, 0x4c, 0x34, 0x6e, 0x78, 0x60, 0xc4, 0xd8, 0xb8, 0xf1, 0xfd, + 0x98, 0x81, 0x6c, 0x18, 0xac, 0xbe, 0x59, 0x2a, 0x93, 0xcd, 0x15, 0x60, 0x8a, 0x28, 0xf9, 0xc9, 0x8b, 0x9c, 0xc3, + 0x53, 0xa8, 0xaf, 0x5f, 0xe0, 0x36, 0x57, 0xfa, 0x3e, 0xe7, 0x3f, 0x66, 0xf4, 0x47, 0x04, 0x3a, 0x89, 0xd7, 0x20, + 0xf7, 0x78, 0x06, 0x75, 0x23, 0x4c, 0x2d, 0xc7, 0xe0, 0x40, 0x88, 0x06, 0x22, 0x2a, 0x16, 0x28, 0xa8, 0x0b, 0x03, + 0xac, 0xa1, 0x2e, 0x98, 0xc3, 0xf3, 0x5c, 0x26, 0x1f, 0xa7, 0xc6, 0x67, 0x7e, 0x18, 0x63, 0xcc, 0xe4, 0x60, 0x10, + 0x56, 0xf3, 0x60, 0x38, 0x1e, 0x4d, 0x8e, 0x9e, 0xc2, 0xb9, 0x1d, 0x8c, 0x03, 0x32, 0x08, 0xea, 0x72, 0x1d, 0x0b, + 0x5a, 0x5e, 0x5f, 0xda, 0x32, 0xf0, 0xe3, 0x3a, 0x18, 0xfc, 0xa3, 0xf0, 0x14, 0xef, 0xa0, 0x39, 0x39, 0x93, 0x21, + 0xd8, 0xd8, 0x6f, 0x08, 0x48, 0xca, 0x7a, 0x9a, 0x9f, 0xd4, 0x87, 0x1b, 0x53, 0xda, 0x3f, 0x73, 0x78, 0xc1, 0x61, + 0x87, 0x04, 0x0a, 0xa4, 0xf1, 0x34, 0x1b, 0xbd, 0x52, 0x8a, 0xdc, 0x77, 0x05, 0x87, 0x3b, 0x73, 0xcf, 0x99, 0x1e, + 0x39, 0x85, 0x44, 0x33, 0x0b, 0xb8, 0x91, 0xbf, 0x12, 0xd7, 0x71, 0x9e, 0xa5, 0x07, 0xcd, 0x37, 0x07, 0xe5, 0x9d, + 0xa8, 0xe2, 0xdb, 0x51, 0x60, 0xac, 0x09, 0xb9, 0xaf, 0x7a, 0x02, 0xf4, 0x04, 0xd8, 0x02, 0x60, 0x40, 0xbc, 0x67, + 0x66, 0x32, 0xe7, 0x11, 0x78, 0x04, 0x36, 0x7d, 0x20, 0x8b, 0x3b, 0xe7, 0x92, 0xe4, 0x6f, 0xa6, 0xd2, 0x5e, 0xf5, + 0xca, 0xbd, 0x82, 0xac, 0x57, 0x5b, 0xb9, 0xef, 0xd6, 0x67, 0xdf, 0x74, 0x78, 0x05, 0x9e, 0x4b, 0x70, 0x8b, 0xec, + 0xf7, 0x9b, 0x82, 0x4a, 0x61, 0x54, 0xc4, 0x7b, 0xc9, 0x35, 0xfa, 0xb7, 0x7b, 0x63, 0xa3, 0x48, 0x6e, 0xf9, 0xf0, + 0x00, 0xea, 0x4c, 0xde, 0x15, 0xb7, 0x73, 0x88, 0xda, 0xba, 0x1b, 0x0f, 0xac, 0x36, 0x68, 0x97, 0xb5, 0x40, 0x70, + 0xe1, 0xe5, 0x41, 0x06, 0x63, 0x81, 0xb3, 0x32, 0x52, 0x6a, 0x5c, 0x43, 0x6a, 0xc1, 0x27, 0x79, 0x7a, 0x0f, 0x59, + 0xea, 0x49, 0x50, 0xe4, 0x78, 0x16, 0x43, 0xa6, 0xf1, 0x36, 0xf0, 0xf8, 0x9d, 0x0c, 0x41, 0x9a, 0xb6, 0xdb, 0x35, + 0x47, 0xa0, 0xec, 0x1e, 0x98, 0x92, 0xd4, 0xb5, 0x31, 0x35, 0xd0, 0x50, 0x7b, 0xa8, 0x91, 0x8a, 0x38, 0x9b, 0xbd, + 0x06, 0x1d, 0x22, 0xf8, 0x7e, 0xa7, 0x59, 0xd9, 0xf1, 0x62, 0x42, 0xf0, 0xe4, 0x7d, 0x71, 0x9b, 0x95, 0x55, 0x19, + 0xbd, 0x4f, 0xd1, 0x10, 0x2a, 0x91, 0x22, 0x7a, 0x09, 0xf1, 0xf4, 0x4a, 0xfc, 0x5d, 0x46, 0x3f, 0xa5, 0x34, 0x4e, + 0x53, 0x4c, 0x7f, 0x5e, 0xc0, 0xcf, 0x67, 0x80, 0xea, 0x88, 0x3b, 0x21, 0x3a, 0x97, 0x60, 0xaf, 0x06, 0xd1, 0xac, + 0x2a, 0x0e, 0x18, 0x9a, 0xd1, 0xad, 0xa0, 0x88, 0xd1, 0x86, 0xd9, 0x7f, 0x28, 0x50, 0x28, 0xa4, 0x8a, 0xf9, 0x4e, + 0xd8, 0x87, 0xe8, 0x47, 0x2c, 0xf2, 0xe4, 0xdd, 0x2b, 0x33, 0xa4, 0xd1, 0x9d, 0xa4, 0x7a, 0x6b, 0xe3, 0xb1, 0x85, + 0x81, 0xcb, 0xa2, 0xcb, 0x0d, 0x3d, 0x8b, 0xd7, 0x59, 0xb4, 0x05, 0xfc, 0x89, 0x77, 0xaf, 0x9e, 0x29, 0x0b, 0x93, + 0xe7, 0x19, 0x28, 0x0e, 0x4e, 0xde, 0xbd, 0x7a, 0x2d, 0xd3, 0x4d, 0xce, 0xa3, 0x33, 0x89, 0xa4, 0xf5, 0xe4, 0xdd, + 0xab, 0x9f, 0xd1, 0xdc, 0xeb, 0xa7, 0x02, 0xde, 0xbf, 0x04, 0xde, 0x32, 0x8a, 0x37, 0xd0, 0x27, 0xf5, 0x3b, 0xd9, + 0x60, 0xa7, 0xbc, 0x5a, 0xcb, 0xe8, 0x97, 0xb4, 0xf6, 0xa4, 0x55, 0xff, 0x2c, 0x7c, 0x6a, 0xe7, 0x09, 0x78, 0x6e, + 0xf3, 0x4c, 0x7c, 0x8c, 0xac, 0x68, 0x27, 0x88, 0xbe, 0x3c, 0xb8, 0xbd, 0xca, 0x45, 0x19, 0xe1, 0x0b, 0x86, 0x76, + 0x41, 0xd1, 0xe1, 0xe1, 0xcd, 0xcd, 0xcd, 0xe8, 0xe6, 0xab, 0x91, 0x2c, 0x2e, 0x0f, 0x27, 0xdf, 0x7e, 0xfb, 0xed, + 0x21, 0xbe, 0x0d, 0xbe, 0x6c, 0xbb, 0xbd, 0x57, 0x84, 0x0f, 0x58, 0x80, 0x08, 0xd5, 0x5f, 0xc2, 0x15, 0x05, 0xb4, + 0x70, 0x83, 0x2f, 0x83, 0x2f, 0xf5, 0xa1, 0xf3, 0xe5, 0x71, 0x79, 0x7d, 0xa9, 0xca, 0xef, 0x2a, 0xf9, 0x68, 0x3c, + 0x1e, 0x1f, 0x82, 0x04, 0xea, 0xcb, 0x01, 0x1f, 0x04, 0xb3, 0x60, 0x90, 0xc1, 0x85, 0xa6, 0xbc, 0xbe, 0x9c, 0x05, + 0x9e, 0x69, 0x6e, 0x83, 0x45, 0x74, 0x20, 0x2e, 0xc1, 0xe1, 0x25, 0x0d, 0xbe, 0x0c, 0x88, 0x4b, 0xf9, 0x02, 0x52, + 0xbe, 0x38, 0x7a, 0xea, 0xa7, 0xfd, 0x2f, 0x95, 0xf6, 0x95, 0x9f, 0x76, 0x8c, 0x69, 0x5f, 0x3d, 0xf3, 0xd3, 0x66, + 0x2a, 0xed, 0x85, 0x9f, 0xf6, 0xbf, 0xcb, 0x01, 0xa4, 0x1e, 0xf8, 0xd6, 0x7f, 0xe7, 0x5e, 0x6b, 0xf0, 0x14, 0x8a, + 0xb2, 0xab, 0xf8, 0x92, 0x43, 0xa3, 0x07, 0xb7, 0x57, 0x39, 0x0d, 0x06, 0xd8, 0x5e, 0xcf, 0x24, 0xc4, 0xfb, 0xe0, + 0xcb, 0x4d, 0x91, 0x87, 0xc1, 0x97, 0x03, 0x2c, 0x64, 0xf0, 0x65, 0x40, 0xbe, 0x34, 0x06, 0x32, 0x82, 0x6d, 0x03, + 0x17, 0x8a, 0x74, 0x68, 0x03, 0x84, 0xf9, 0xd2, 0xb8, 0x9a, 0xfe, 0x59, 0x74, 0x67, 0xc3, 0x5b, 0xa2, 0x72, 0xd3, + 0x0d, 0x6a, 0xfa, 0x16, 0xbc, 0x13, 0xa0, 0x51, 0x51, 0x70, 0x1d, 0x17, 0xe1, 0x70, 0x58, 0x5e, 0x5f, 0x12, 0xb0, + 0xcb, 0x5c, 0xf3, 0xb8, 0x8a, 0x02, 0x21, 0x87, 0xea, 0x67, 0xa0, 0x22, 0x5f, 0x05, 0x08, 0x88, 0x04, 0xff, 0x05, + 0x35, 0x7d, 0x27, 0xd9, 0x36, 0x18, 0xde, 0xf0, 0xf3, 0x8f, 0x59, 0x35, 0x54, 0xa2, 0xc5, 0x6b, 0x41, 0xe1, 0x07, + 0xfc, 0x75, 0x55, 0x47, 0x7f, 0x82, 0x1b, 0x77, 0x53, 0xc3, 0xfe, 0x4e, 0x3a, 0x16, 0xf5, 0x9d, 0x5c, 0x64, 0xcb, + 0x69, 0xeb, 0x40, 0x7f, 0x2b, 0x49, 0xb5, 0xc8, 0x06, 0xc1, 0x30, 0x18, 0xf0, 0x25, 0x7b, 0x2b, 0x17, 0xdc, 0x33, + 0x9f, 0x7a, 0x24, 0xfd, 0x69, 0x9e, 0x67, 0x03, 0xf0, 0x4d, 0x41, 0x7e, 0xe4, 0xf0, 0xbf, 0x17, 0x43, 0x14, 0x1e, + 0x0e, 0x1e, 0x1d, 0x92, 0x79, 0xb0, 0xbe, 0x45, 0x8f, 0xce, 0x28, 0xc8, 0xc4, 0x8a, 0x17, 0x59, 0xe5, 0x2d, 0x95, + 0xbb, 0x4d, 0xdb, 0xcb, 0xe3, 0xde, 0xb3, 0x79, 0x1d, 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, 0x2c, 0x70, 0xf7, 0xa1, 0x6c, 0xe4, 0xee, 0x8c, 0xb4, 0x60, 0xff, 0x2c, 0xc2, 0x92, 0x82, 0x78, + 0x4c, 0x6a, 0xf1, 0x97, 0x06, 0x97, 0x19, 0x00, 0xf4, 0x91, 0x92, 0x80, 0x19, 0x58, 0x99, 0x01, 0x84, 0xe6, 0xa6, + 0x31, 0x3b, 0x03, 0xe6, 0x11, 0x38, 0xe6, 0x11, 0x32, 0x0e, 0x80, 0x58, 0x12, 0xe0, 0xdc, 0x05, 0x51, 0xac, 0x0b, + 0x79, 0x04, 0xa0, 0xf7, 0xf8, 0x93, 0x98, 0x52, 0x30, 0x49, 0xc7, 0x2a, 0x04, 0x41, 0x1c, 0x9f, 0x5f, 0x8b, 0xd6, + 0xe4, 0xac, 0xd0, 0xc1, 0x8c, 0x24, 0xc0, 0x86, 0x18, 0xd8, 0x39, 0xb8, 0x9f, 0x83, 0xd2, 0xc3, 0xea, 0x9d, 0x90, + 0x0b, 0xbe, 0xe3, 0x9e, 0x6c, 0x16, 0xae, 0x9e, 0x70, 0x10, 0xdc, 0x71, 0xcd, 0x02, 0x8c, 0xaa, 0x62, 0x53, 0x56, + 0x3c, 0xfd, 0x70, 0xb7, 0x86, 0xd8, 0x77, 0x38, 0xa0, 0xef, 0x64, 0x9e, 0x25, 0x77, 0xa1, 0xb3, 0xe7, 0xda, 0xaa, + 0xf4, 0x1f, 0x3e, 0xbc, 0xfe, 0x29, 0x02, 0x91, 0x63, 0x6d, 0x28, 0xfd, 0x1d, 0xc7, 0xb3, 0xc9, 0x8f, 0xf0, 0xe4, + 0x6f, 0xec, 0x3b, 0x6e, 0x4f, 0x8f, 0x7e, 0x1f, 0xea, 0xa6, 0x77, 0x7c, 0x7e, 0xc7, 0x47, 0xae, 0x38, 0x54, 0x57, + 0xb8, 0xaf, 0x6f, 0x36, 0xbe, 0x11, 0xd2, 0xc3, 0xf3, 0x4c, 0x79, 0x63, 0x7e, 0xb4, 0x83, 0x61, 0x10, 0x4c, 0xb5, + 0x50, 0x12, 0xa2, 0x6e, 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, 0xf5, 0x46, 0x45, 0xc5, 0x40, 0xf0, 0x38, 0xe4, 0x00, + 0x3d, 0xec, 0x82, 0x96, 0x95, 0xa5, 0xba, 0x55, 0x39, 0x4b, 0x15, 0x75, 0x19, 0xca, 0xca, 0x58, 0x61, 0xbe, 0x97, + 0xec, 0x87, 0x02, 0x3d, 0xcb, 0xa7, 0xa2, 0x0b, 0x5e, 0x08, 0x25, 0x58, 0xae, 0xeb, 0x9d, 0x08, 0x44, 0x9d, 0x1f, + 0x7a, 0x57, 0x7d, 0x8d, 0x63, 0xc7, 0xd3, 0xd7, 0x32, 0xe5, 0xda, 0x84, 0x42, 0xf3, 0xf9, 0xd2, 0x57, 0x4c, 0x14, + 0xec, 0x06, 0xfa, 0xd5, 0xb6, 0xd1, 0x67, 0x77, 0x1b, 0xbd, 0x19, 0x94, 0xe8, 0x98, 0xd7, 0x28, 0xb8, 0x56, 0x0a, + 0x05, 0xa3, 0xbd, 0x8d, 0x3f, 0xc1, 0x91, 0x5b, 0xdd, 0x1e, 0x7a, 0xbf, 0x55, 0xf1, 0xe5, 0x1b, 0xf4, 0xed, 0xb4, + 0x3f, 0x47, 0x95, 0xfc, 0x65, 0xbd, 0x06, 0x1f, 0x2a, 0x88, 0x2c, 0x62, 0x71, 0x69, 0xa1, 0x9e, 0xd3, 0x77, 0x27, + 0x6f, 0xc0, 0x8f, 0x12, 0x7f, 0xff, 0xfa, 0x7d, 0x50, 0x93, 0x69, 0x3c, 0x2f, 0xcc, 0x87, 0x36, 0x07, 0x84, 0x26, + 0x71, 0x69, 0xf6, 0xfd, 0x3c, 0x6e, 0xb2, 0xef, 0x9a, 0xad, 0xa7, 0x45, 0x13, 0x49, 0xca, 0x70, 0xfb, 0x60, 0x40, + 0xa0, 0x0f, 0x10, 0xc5, 0xd9, 0x17, 0x34, 0x86, 0x34, 0x9f, 0xd9, 0xf7, 0x23, 0xe2, 0xbd, 0xd8, 0x0b, 0x21, 0xc6, + 0x15, 0x16, 0x8d, 0x1e, 0xf2, 0x39, 0x8f, 0x94, 0x61, 0xd1, 0x7b, 0x4c, 0x20, 0xce, 0x70, 0x5a, 0xbd, 0x47, 0xcc, + 0x63, 0xbc, 0x1b, 0x68, 0xd9, 0x43, 0x94, 0x51, 0x97, 0xbd, 0x61, 0xf1, 0xfd, 0x71, 0x13, 0x66, 0xd6, 0xf2, 0x72, + 0x08, 0x7f, 0x03, 0x6d, 0x00, 0x4e, 0x39, 0xb2, 0x7c, 0x95, 0xd9, 0xe8, 0x6a, 0x89, 0xe9, 0x4d, 0x04, 0xb1, 0x78, + 0x74, 0x3a, 0xac, 0x5d, 0x9d, 0xaa, 0x77, 0xb5, 0xf3, 0x99, 0xe8, 0x55, 0xa0, 0x95, 0x6b, 0xdb, 0xe3, 0x21, 0xdc, + 0xa5, 0x96, 0x56, 0xd8, 0x88, 0x72, 0x2e, 0x9e, 0xee, 0x02, 0x9b, 0x13, 0xd0, 0xe0, 0x4a, 0xa6, 0x00, 0x9c, 0xa5, + 0xd5, 0x68, 0xd4, 0x08, 0xfb, 0xac, 0x9c, 0xcf, 0x61, 0x6b, 0x21, 0x9e, 0x16, 0x80, 0xe1, 0x36, 0x31, 0x28, 0x79, + 0x37, 0x06, 0xe5, 0xf4, 0xa3, 0x82, 0xb7, 0x0e, 0xce, 0xca, 0x55, 0x9c, 0xca, 0x1b, 0xc0, 0x62, 0x0c, 0xfc, 0x54, + 0x2c, 0xd5, 0x4b, 0x48, 0x56, 0x3c, 0xf9, 0x88, 0x56, 0x1b, 0x69, 0x00, 0x5c, 0xe5, 0xd4, 0x58, 0xee, 0x29, 0x90, + 0x50, 0x57, 0x8a, 0x4a, 0x88, 0xab, 0x2a, 0x4e, 0x56, 0xa7, 0x98, 0x1a, 0x6e, 0xa1, 0x17, 0x51, 0x20, 0xd7, 0x5c, + 0x00, 0x49, 0xcf, 0xd9, 0xbf, 0x32, 0x8d, 0x35, 0xfe, 0x4c, 0xa2, 0x80, 0x49, 0xa3, 0x06, 0x63, 0xa5, 0xec, 0x85, + 0x34, 0xd1, 0xde, 0x82, 0xa0, 0x76, 0x2f, 0xff, 0x84, 0xba, 0x9f, 0x41, 0x2b, 0xc2, 0x06, 0x18, 0xa2, 0x3c, 0xc7, + 0x1d, 0x9a, 0xda, 0x25, 0xe7, 0x01, 0x23, 0x3a, 0xef, 0xb3, 0xda, 0x6e, 0xf5, 0x67, 0x2b, 0xc0, 0x36, 0x4d, 0x8d, + 0x4f, 0x61, 0x98, 0x10, 0x13, 0x1b, 0xd8, 0x2a, 0x2b, 0xed, 0x86, 0x32, 0xed, 0xa4, 0x2b, 0xe6, 0xb5, 0x70, 0x9a, + 0xf7, 0x18, 0x5b, 0x8d, 0x54, 0xee, 0x7e, 0x3f, 0x34, 0x3f, 0x59, 0x4e, 0x9f, 0xe9, 0x90, 0xcd, 0xde, 0x78, 0xd0, + 0x9c, 0x68, 0x75, 0x55, 0x47, 0x3f, 0xa0, 0x03, 0x30, 0xd3, 0x16, 0x20, 0xd3, 0x05, 0x9b, 0xf6, 0x95, 0xa8, 0xb8, + 0x24, 0x61, 0xa9, 0x24, 0xb0, 0xb3, 0x9b, 0x92, 0x9d, 0x6d, 0x40, 0x3c, 0xc3, 0x5d, 0x4f, 0x8b, 0x9d, 0x90, 0x26, + 0xbc, 0xc5, 0x41, 0x02, 0xa2, 0x0e, 0x55, 0x5d, 0x42, 0xb6, 0xc6, 0xd0, 0xc5, 0xbf, 0x28, 0x85, 0x09, 0x6b, 0x99, + 0x54, 0x25, 0x26, 0x08, 0x52, 0xb9, 0xdf, 0x22, 0xb0, 0x44, 0xc1, 0x0e, 0x60, 0xef, 0xdd, 0xa8, 0x9b, 0x51, 0x53, + 0xd5, 0xa9, 0x97, 0xe0, 0xe3, 0x34, 0xef, 0x2a, 0xc8, 0x2c, 0xec, 0xaa, 0xd8, 0xf0, 0x40, 0xc7, 0xa6, 0x52, 0xc6, + 0xc4, 0x5d, 0x5a, 0x64, 0x88, 0x07, 0x8c, 0xb1, 0x74, 0x21, 0x90, 0x6f, 0xb6, 0x3f, 0x6e, 0x7a, 0x82, 0xd0, 0x4f, + 0xd8, 0x50, 0x02, 0x37, 0x9d, 0xed, 0xa9, 0x69, 0xe6, 0x03, 0x22, 0x0e, 0x03, 0x0a, 0x24, 0x1b, 0x87, 0x34, 0x47, + 0xfa, 0x82, 0xa4, 0x09, 0x03, 0x43, 0x2b, 0x9e, 0x13, 0x64, 0x45, 0xa1, 0x67, 0xeb, 0xaa, 0x8d, 0x73, 0x65, 0x98, + 0xa3, 0x25, 0xa7, 0xc2, 0xe7, 0x04, 0x99, 0xd8, 0x3d, 0x6d, 0x33, 0x93, 0xe1, 0x28, 0x59, 0x60, 0x7e, 0x05, 0x51, + 0xe2, 0xce, 0x34, 0xab, 0x72, 0x30, 0x2e, 0x60, 0x81, 0x56, 0xbe, 0x07, 0x75, 0x63, 0x0d, 0x6d, 0x35, 0x0c, 0xb1, + 0xdb, 0x9f, 0x60, 0xbf, 0xd6, 0x4e, 0xeb, 0x32, 0xc5, 0xf2, 0x32, 0x85, 0x68, 0x2f, 0x64, 0x7e, 0xa3, 0x48, 0x74, + 0xaf, 0x08, 0x43, 0xc2, 0x3a, 0xca, 0x9e, 0xb4, 0xa9, 0x01, 0xf4, 0xd4, 0x0b, 0x78, 0xde, 0xb9, 0x96, 0x61, 0x17, + 0xe9, 0xfe, 0xaa, 0xe0, 0x53, 0xba, 0x41, 0x90, 0xa2, 0x37, 0x29, 0x98, 0xf3, 0x7a, 0x94, 0xd4, 0x9b, 0xd3, 0x96, + 0x19, 0x55, 0x47, 0x45, 0x48, 0x39, 0xc1, 0x7f, 0xf2, 0x52, 0x6a, 0x62, 0x13, 0x26, 0x78, 0xe0, 0xc3, 0x3c, 0xc3, + 0x06, 0xde, 0xed, 0xde, 0xa5, 0x61, 0xd2, 0x66, 0x1b, 0x52, 0x90, 0x56, 0x98, 0xb8, 0x18, 0x50, 0xd9, 0x2b, 0xdc, + 0x2f, 0xd8, 0x4e, 0x9a, 0x82, 0x07, 0x61, 0xa3, 0x81, 0x89, 0x5b, 0x5d, 0x7c, 0x13, 0x26, 0x34, 0x5c, 0x51, 0xed, + 0xec, 0xa4, 0x25, 0xcd, 0xed, 0x75, 0x79, 0x61, 0xfb, 0xa0, 0x63, 0x87, 0x75, 0x0d, 0x0f, 0x34, 0xaf, 0xd9, 0xc5, + 0x35, 0xd3, 0x34, 0xd1, 0x58, 0x0f, 0x29, 0x4b, 0x8e, 0x4d, 0x3d, 0x5d, 0xe3, 0x6a, 0x99, 0x6b, 0x60, 0x77, 0x89, + 0x17, 0x7a, 0xc0, 0xc3, 0x0e, 0xd7, 0x24, 0xba, 0xc0, 0x66, 0xb3, 0x75, 0x4d, 0xa6, 0xf9, 0x7d, 0xd9, 0x72, 0x13, + 0x10, 0xce, 0x52, 0xdf, 0xdc, 0x27, 0xc7, 0x9a, 0xb6, 0xf9, 0x49, 0x80, 0xe3, 0xed, 0x15, 0x90, 0x74, 0x2c, 0x41, + 0x17, 0xdf, 0xd2, 0x1f, 0x44, 0x6a, 0xa6, 0x82, 0xde, 0x3b, 0x5f, 0xa4, 0x6e, 0x7e, 0x01, 0xb6, 0x51, 0x5b, 0x63, + 0x9a, 0x95, 0x6d, 0xc2, 0x44, 0x59, 0x58, 0x23, 0x0b, 0xb9, 0x02, 0x1f, 0xcc, 0xfd, 0xa6, 0x4e, 0x4f, 0x3a, 0x88, + 0xb0, 0xdf, 0x45, 0x8f, 0x47, 0x18, 0x2b, 0xd6, 0x20, 0x31, 0xac, 0xc2, 0x86, 0x36, 0x97, 0x43, 0x94, 0x53, 0xb3, + 0x64, 0xa2, 0x15, 0xf5, 0x29, 0x45, 0x94, 0x82, 0xb9, 0xf1, 0xb4, 0x6c, 0x98, 0x12, 0x22, 0x64, 0x85, 0x74, 0x40, + 0xb5, 0x16, 0x5a, 0xaa, 0x09, 0x7a, 0x1d, 0x7a, 0x59, 0x68, 0x4c, 0x41, 0xf4, 0x11, 0x19, 0x6e, 0xc4, 0x91, 0xd1, + 0xfd, 0x31, 0x8a, 0x09, 0x84, 0xaa, 0xf6, 0xf2, 0xc2, 0xea, 0xd3, 0xb2, 0xad, 0x0e, 0xe2, 0x0a, 0x91, 0xef, 0xbb, + 0x09, 0x6a, 0x8c, 0x82, 0x36, 0xa7, 0x1b, 0xfd, 0xa5, 0x08, 0x7d, 0xbb, 0x70, 0xec, 0x46, 0x41, 0x24, 0x44, 0x60, + 0xf5, 0x9a, 0x8a, 0x01, 0x59, 0x17, 0xb1, 0x8b, 0xd0, 0xa4, 0xbb, 0x85, 0x28, 0x6f, 0x54, 0xd6, 0x1f, 0x37, 0x21, + 0xd9, 0xed, 0xb0, 0x2c, 0xf0, 0x65, 0x3f, 0xdd, 0xdc, 0x03, 0xf9, 0xfd, 0x7a, 0xf3, 0x49, 0xc8, 0xef, 0x57, 0xd9, + 0xe7, 0x40, 0x7e, 0xbf, 0xde, 0xfc, 0x4f, 0x43, 0x7e, 0x9f, 0x6e, 0x3c, 0xc8, 0x6f, 0x35, 0x18, 0xbf, 0x15, 0x2c, + 0x78, 0xfb, 0x26, 0xa0, 0xcf, 0x25, 0x0b, 0xde, 0xbe, 0x7c, 0xe9, 0x1b, 0x81, 0x08, 0x8d, 0x5c, 0x6f, 0x64, 0xc1, + 0x88, 0xdb, 0x02, 0xaf, 0x50, 0xeb, 0xe4, 0x03, 0x15, 0x65, 0x00, 0xbc, 0x5e, 0xfe, 0x23, 0xab, 0x56, 0x61, 0x70, + 0x18, 0x90, 0xb9, 0x83, 0x04, 0x1d, 0x4e, 0xe0, 0xf6, 0x86, 0x46, 0x96, 0xd5, 0x67, 0xc1, 0x87, 0x8f, 0x46, 0xa3, + 0xb8, 0xb8, 0xc4, 0x4b, 0x9d, 0xd9, 0x48, 0x08, 0x78, 0x9c, 0xf1, 0xd2, 0x86, 0x88, 0x58, 0xc5, 0xe5, 0x99, 0x8e, + 0xcd, 0x52, 0xda, 0xad, 0x08, 0x11, 0xe7, 0xcf, 0x00, 0xa7, 0xde, 0xee, 0xcd, 0x18, 0xfb, 0xa1, 0x38, 0x62, 0x1d, + 0x40, 0xf6, 0xd9, 0x46, 0xbf, 0x3b, 0x8f, 0x4b, 0xfe, 0x2e, 0xae, 0x56, 0x0c, 0x7a, 0x09, 0x77, 0x11, 0xc1, 0x93, + 0xca, 0x63, 0x9b, 0x14, 0x50, 0x79, 0xa6, 0x81, 0xca, 0x3b, 0xde, 0xd3, 0xd0, 0x0e, 0x8b, 0xf6, 0x01, 0x36, 0xd2, + 0xe5, 0x0c, 0x8c, 0x16, 0x5f, 0x5c, 0x73, 0x51, 0xfd, 0x04, 0x78, 0xea, 0x82, 0x17, 0x70, 0x4b, 0x40, 0x2e, 0xb6, + 0xe1, 0x84, 0x40, 0x85, 0xef, 0xd9, 0xa1, 0xa2, 0xc6, 0x18, 0xd1, 0x44, 0xa3, 0xdf, 0x78, 0x13, 0x42, 0xef, 0x4e, + 0xd0, 0x15, 0x61, 0x24, 0xbc, 0x3f, 0x37, 0xfc, 0x2c, 0x03, 0xf3, 0x79, 0x01, 0x50, 0x1a, 0x08, 0x87, 0xca, 0x94, + 0xdc, 0x02, 0x13, 0xb6, 0xc6, 0x5c, 0x29, 0x4b, 0x3d, 0xa4, 0x52, 0xaa, 0xe0, 0x74, 0x05, 0x4d, 0x25, 0xe0, 0x70, + 0x47, 0x12, 0xc0, 0x4c, 0x6d, 0x61, 0x10, 0xdd, 0x36, 0xa5, 0x59, 0x1a, 0x39, 0x45, 0x9a, 0xc3, 0x27, 0xa5, 0x0a, + 0x74, 0xfa, 0x2c, 0x89, 0x2b, 0x7e, 0x29, 0x0b, 0x08, 0x85, 0xdb, 0x4a, 0xa1, 0x48, 0xbf, 0xcf, 0xc4, 0xe6, 0x8a, + 0x17, 0x59, 0x72, 0xb6, 0xca, 0xca, 0x0a, 0xf2, 0x2d, 0xf4, 0xe9, 0xb7, 0xac, 0xa7, 0x05, 0xce, 0x9b, 0x9a, 0x14, + 0x66, 0xe6, 0xf1, 0x44, 0xed, 0x74, 0x50, 0xaf, 0x7a, 0xaf, 0x0d, 0xf6, 0x7b, 0x73, 0xa2, 0xc7, 0xad, 0xf5, 0x60, + 0x35, 0xa9, 0xcd, 0x54, 0x05, 0x71, 0x04, 0xd4, 0x81, 0xcd, 0x70, 0x16, 0x53, 0xba, 0xb1, 0x08, 0x2a, 0x60, 0xed, + 0x80, 0x39, 0x32, 0x71, 0x79, 0x76, 0xa3, 0xe4, 0x27, 0x3d, 0x45, 0x61, 0xd2, 0x28, 0x56, 0xc8, 0x3e, 0x2b, 0x16, + 0x6e, 0x58, 0x72, 0x4f, 0xae, 0x4d, 0x94, 0x34, 0x30, 0xba, 0xe2, 0xf6, 0x40, 0x1c, 0x27, 0xed, 0x94, 0xf9, 0x70, + 0x12, 0xed, 0x65, 0x03, 0xe6, 0xa0, 0x9d, 0x0f, 0xae, 0xaa, 0xab, 0xb9, 0x6a, 0xc5, 0xa8, 0x92, 0x3f, 0xc9, 0x1b, + 0x73, 0xb1, 0x3d, 0x4e, 0x3a, 0x12, 0xa1, 0xdc, 0x49, 0x94, 0x1f, 0xaf, 0xd4, 0x0f, 0x80, 0x5e, 0xd1, 0xe4, 0xf0, + 0xcf, 0x0d, 0x37, 0xe0, 0xf4, 0xa1, 0xf6, 0x10, 0x74, 0xa2, 0x7c, 0x3d, 0x23, 0x9e, 0x51, 0x9d, 0x5e, 0x2e, 0x0b, + 0x30, 0xe8, 0xf2, 0x87, 0x12, 0x22, 0xc8, 0x74, 0x4e, 0xeb, 0x72, 0xaa, 0xcd, 0x8b, 0x0d, 0x6f, 0x43, 0x3f, 0xef, + 0x3b, 0x0d, 0x9c, 0x9b, 0xf0, 0x70, 0xf8, 0x74, 0x4c, 0x6a, 0x6d, 0xeb, 0x8e, 0x0b, 0xcf, 0xfe, 0x56, 0x8b, 0xd3, + 0x3d, 0xdb, 0x05, 0x4a, 0x9b, 0x5e, 0x0a, 0xed, 0x1a, 0xa9, 0xb8, 0xa7, 0xfb, 0x35, 0xa9, 0xdd, 0x42, 0xb3, 0x92, + 0xa7, 0xdf, 0xd5, 0x69, 0x77, 0xf6, 0x68, 0x9b, 0xe9, 0x2a, 0xeb, 0xdf, 0x33, 0x1b, 0xa7, 0xae, 0x41, 0x39, 0x6a, + 0xbd, 0x04, 0x7d, 0x98, 0xb8, 0x8e, 0x6c, 0x7a, 0x3a, 0x59, 0xd6, 0x49, 0x7e, 0x46, 0xea, 0x91, 0xab, 0xb0, 0x5d, + 0xdd, 0x59, 0xf8, 0x2d, 0x4f, 0xc2, 0xae, 0x86, 0xa9, 0x9b, 0x81, 0xe9, 0x02, 0x22, 0x67, 0x82, 0x3e, 0x20, 0xfc, + 0xfd, 0xd1, 0xb6, 0x49, 0xce, 0xea, 0x43, 0xef, 0x33, 0xfc, 0x9d, 0xa5, 0xf0, 0xb7, 0xaa, 0x7f, 0xa7, 0xdb, 0x2b, + 0x5e, 0xad, 0x64, 0x1a, 0x05, 0xef, 0xde, 0x9e, 0x7e, 0x08, 0x34, 0x22, 0x3b, 0xde, 0x4b, 0x8c, 0x26, 0xda, 0x60, + 0x3f, 0x81, 0x66, 0x26, 0x97, 0x97, 0x08, 0x4a, 0xa8, 0x51, 0xed, 0x4f, 0x57, 0xf2, 0xe6, 0x24, 0xcf, 0x7d, 0xe6, + 0xd9, 0x10, 0x5c, 0xcd, 0x4f, 0x36, 0xa8, 0x55, 0x08, 0x32, 0xc0, 0x51, 0x56, 0x9e, 0x69, 0xad, 0x4d, 0x7a, 0x76, + 0x7e, 0x77, 0xa6, 0x25, 0x43, 0x16, 0x15, 0xf2, 0xd9, 0xef, 0xc7, 0x69, 0x76, 0x7d, 0x80, 0xa7, 0x02, 0x0b, 0xc0, + 0xa4, 0x3e, 0xe7, 0xe7, 0x9b, 0xaa, 0x92, 0x62, 0x58, 0xc8, 0x9b, 0x60, 0x76, 0xac, 0x1e, 0x4c, 0x86, 0x58, 0x3d, + 0x06, 0x07, 0xff, 0x95, 0xe4, 0x59, 0xf2, 0x91, 0x05, 0x8f, 0xb6, 0x19, 0x9b, 0xb5, 0x68, 0xff, 0xb8, 0x0e, 0x66, + 0xd0, 0xd6, 0x83, 0x93, 0x3c, 0x3f, 0x3e, 0x54, 0x5f, 0xcc, 0x8e, 0x0f, 0xd3, 0xec, 0x7a, 0xe6, 0x01, 0xf4, 0x3b, + 0x7b, 0x5b, 0x84, 0x42, 0x73, 0xf7, 0x69, 0x70, 0xac, 0x4d, 0x78, 0x68, 0x39, 0x10, 0x90, 0xe2, 0x98, 0xf0, 0x26, + 0x28, 0xf9, 0x09, 0x63, 0x38, 0x6f, 0x77, 0xbb, 0xd0, 0x1a, 0x03, 0x25, 0x1e, 0x52, 0x4e, 0x01, 0x1c, 0x0a, 0x66, + 0xa1, 0x09, 0xa1, 0x49, 0x4d, 0x42, 0x83, 0xe7, 0x13, 0x13, 0x5a, 0xd4, 0x14, 0x8e, 0xa0, 0xd7, 0xf1, 0xda, 0x08, + 0xbf, 0xb4, 0x30, 0xc1, 0xb4, 0x7e, 0xde, 0x18, 0xc7, 0xa8, 0x3d, 0xaa, 0x06, 0x61, 0xab, 0x57, 0xde, 0x37, 0xb0, + 0x20, 0xef, 0x0c, 0x2b, 0x1a, 0xb4, 0xe8, 0x0a, 0xc8, 0x2b, 0x7d, 0x31, 0x1b, 0xa7, 0xe1, 0xa2, 0xa4, 0x72, 0x49, + 0xd8, 0x2c, 0xdc, 0x22, 0xbb, 0x5d, 0x2a, 0xea, 0x1d, 0xc9, 0xda, 0xc1, 0x5d, 0xaa, 0xd9, 0x99, 0x3d, 0xda, 0x0a, + 0x44, 0x58, 0x2c, 0xd9, 0xac, 0x39, 0x5f, 0x55, 0x7c, 0x3e, 0x5c, 0x71, 0xf0, 0xcb, 0x09, 0x0e, 0xfe, 0x2b, 0x3d, + 0xcf, 0xed, 0xa4, 0xa8, 0x15, 0xb9, 0x8a, 0x45, 0x9a, 0xf3, 0x0f, 0xf1, 0xf9, 0x0f, 0x98, 0xe7, 0xf9, 0x79, 0xfe, + 0x0c, 0x32, 0xd4, 0xc1, 0xec, 0xd1, 0x36, 0xa9, 0x46, 0x2f, 0xde, 0x7c, 0x78, 0xf5, 0xe1, 0x9f, 0x67, 0xcf, 0x4e, + 0x3e, 0xbc, 0xf8, 0xfe, 0xed, 0xfb, 0x57, 0x2f, 0x4e, 0x17, 0xd6, 0x11, 0x56, 0xe1, 0xab, 0x91, 0xe5, 0x6e, 0xe7, + 0xf2, 0xfd, 0xf2, 0xe6, 0xf9, 0x8b, 0x97, 0xaf, 0xde, 0xbc, 0x78, 0x5e, 0xab, 0xb9, 0x6c, 0x37, 0x04, 0x76, 0x68, + 0x9c, 0x09, 0x5e, 0x40, 0xf1, 0x3a, 0xca, 0x23, 0x36, 0x5b, 0xc3, 0x02, 0x36, 0x9b, 0xae, 0x23, 0x28, 0xc0, 0x22, + 0x3b, 0xd0, 0x9b, 0x05, 0x1a, 0x2e, 0xcd, 0xc6, 0xf1, 0x97, 0x98, 0xdf, 0x9b, 0x17, 0xf8, 0xdd, 0x7b, 0x79, 0x63, + 0xba, 0xa2, 0x47, 0x48, 0x21, 0x7e, 0xcd, 0x9f, 0xfd, 0x7e, 0xec, 0x4b, 0xd9, 0x50, 0x14, 0xa1, 0xca, 0x85, 0x5f, + 0x75, 0x70, 0xa0, 0x2d, 0xfe, 0x02, 0x08, 0x58, 0x11, 0xcc, 0x8e, 0x0f, 0xfd, 0xdc, 0xb3, 0xdf, 0xa3, 0x9f, 0xbc, + 0xce, 0x61, 0xa9, 0x30, 0x0e, 0xcd, 0xb4, 0xbd, 0x53, 0x11, 0x42, 0x2a, 0xb9, 0x73, 0x53, 0xad, 0x20, 0x43, 0xae, + 0x24, 0x89, 0xec, 0x24, 0x2a, 0x4b, 0x16, 0x53, 0xda, 0xef, 0xfa, 0xaf, 0xeb, 0x33, 0x4a, 0x06, 0xb8, 0x28, 0x65, + 0x11, 0x40, 0x3f, 0xda, 0x71, 0x26, 0x0e, 0xbc, 0x78, 0x2e, 0xd8, 0xa3, 0x4e, 0xf2, 0x0e, 0x23, 0x72, 0xd8, 0xfe, + 0xd4, 0xeb, 0xd8, 0xef, 0xc4, 0xfd, 0xf8, 0x3f, 0xcd, 0x3d, 0xeb, 0x76, 0xdb, 0x36, 0xd2, 0xff, 0xfb, 0x14, 0x0c, + 0x93, 0x4d, 0xc5, 0x84, 0xa4, 0x49, 0xc9, 0xb2, 0x15, 0xc9, 0xb2, 0xdb, 0xe6, 0x72, 0x36, 0xfb, 0xb9, 0x4d, 0x4f, + 0xe2, 0xe6, 0xdb, 0xad, 0xeb, 0x63, 0x51, 0x12, 0x24, 0x71, 0x43, 0x91, 0x3a, 0x24, 0xe5, 0x4b, 0x15, 0xee, 0xb3, + 0xec, 0x23, 0x7c, 0xcf, 0xd0, 0x27, 0xfb, 0xce, 0xcc, 0x00, 0x20, 0x78, 0x93, 0x94, 0x26, 0xed, 0xee, 0x69, 0x93, + 0x88, 0xb8, 0x63, 0x00, 0x0c, 0x06, 0x73, 0xd5, 0xf8, 0x64, 0x4a, 0xe8, 0x45, 0x0e, 0xb0, 0x39, 0x1e, 0xc8, 0xe5, + 0x1b, 0xdf, 0xfc, 0xdf, 0xc8, 0x9c, 0x7b, 0xe6, 0xd2, 0x33, 0xdf, 0x85, 0x57, 0x59, 0xed, 0xea, 0xc8, 0x58, 0x33, + 0x26, 0x1b, 0xb4, 0xc0, 0x63, 0x05, 0x7f, 0x47, 0x70, 0xea, 0xda, 0xb7, 0xb9, 0x8c, 0xed, 0xc2, 0x8b, 0xe7, 0x4c, + 0x84, 0x78, 0x11, 0xb9, 0x29, 0x87, 0x8a, 0xa1, 0x80, 0x05, 0xdc, 0xb9, 0x3c, 0xe0, 0xaa, 0x08, 0xbe, 0x3d, 0x49, + 0xe3, 0xe0, 0x7f, 0xd8, 0x3d, 0x50, 0x7b, 0x49, 0x1a, 0xad, 0x80, 0xc6, 0xf7, 0xe6, 0x9c, 0x67, 0x63, 0xb6, 0xd8, + 0x7e, 0xdd, 0x7d, 0xfc, 0xc8, 0x6c, 0xdc, 0x92, 0x40, 0x28, 0xda, 0x69, 0x34, 0x9f, 0x07, 0xac, 0xa5, 0x8b, 0xa0, + 0x23, 0xba, 0x29, 0xbb, 0x39, 0x7b, 0xe0, 0x08, 0x4f, 0x9f, 0x46, 0xd6, 0x74, 0xb4, 0xc4, 0x8c, 0x99, 0x74, 0x85, + 0x47, 0x14, 0x2f, 0xf2, 0x74, 0x6f, 0x50, 0x2c, 0xc2, 0xd7, 0x25, 0x3f, 0xba, 0xd6, 0x34, 0x5a, 0x8f, 0x03, 0x66, + 0xe1, 0x76, 0x87, 0x2e, 0x37, 0xe3, 0xf5, 0x78, 0x0c, 0xd1, 0x5d, 0x1e, 0x38, 0x26, 0xf8, 0xab, 0x89, 0x12, 0x7c, + 0x47, 0x66, 0xc6, 0x00, 0x26, 0x65, 0xa7, 0xe5, 0xe1, 0x83, 0x8e, 0x09, 0xb0, 0x88, 0xa8, 0x83, 0x14, 0xde, 0x8c, + 0x35, 0xa7, 0x76, 0xa8, 0xbf, 0x83, 0xdd, 0x97, 0xe8, 0x83, 0xba, 0xa3, 0x3f, 0xbc, 0xd4, 0xdf, 0x21, 0x8c, 0x31, + 0xea, 0xf1, 0x73, 0xda, 0xbd, 0xba, 0xa9, 0x93, 0xb0, 0x7c, 0x8d, 0xf1, 0x0f, 0x80, 0x59, 0xfc, 0xc2, 0xf7, 0xe6, + 0x61, 0x94, 0xa4, 0xfe, 0x44, 0xbf, 0x1a, 0xbc, 0xf6, 0x5b, 0x97, 0xcb, 0xb4, 0x65, 0x5c, 0x99, 0x93, 0x54, 0x0d, + 0x9d, 0x22, 0x10, 0x26, 0x46, 0x4e, 0x69, 0x2a, 0xa4, 0x9e, 0xa0, 0xad, 0x05, 0x05, 0x6a, 0xc6, 0x42, 0x93, 0x74, + 0x08, 0xe5, 0x4a, 0x71, 0x58, 0x30, 0xa0, 0x94, 0x8e, 0x35, 0x8d, 0x01, 0xbd, 0x70, 0x9e, 0xaf, 0x37, 0x78, 0x95, + 0xa7, 0xf9, 0x6d, 0x89, 0xbe, 0x83, 0x85, 0xc1, 0x0d, 0x7d, 0x3f, 0x50, 0x95, 0x45, 0x0b, 0xf7, 0xee, 0xe8, 0xdb, + 0x22, 0x5d, 0x00, 0xf7, 0x37, 0x68, 0x6a, 0x84, 0x51, 0xaa, 0x81, 0x43, 0x1c, 0xe8, 0x71, 0x54, 0x56, 0x2e, 0xe3, + 0xad, 0xb6, 0x8c, 0x8c, 0x23, 0x83, 0xef, 0xf0, 0xf2, 0x6b, 0x71, 0xb7, 0x68, 0x05, 0xcf, 0x17, 0xf4, 0xc8, 0x08, + 0x61, 0x01, 0x0b, 0x14, 0xa5, 0x82, 0xfb, 0x77, 0xde, 0xbd, 0x2d, 0x41, 0x5e, 0x8b, 0x68, 0x80, 0x2d, 0x1e, 0xd0, + 0x54, 0x10, 0x3a, 0xa5, 0x33, 0x85, 0x0a, 0x23, 0x82, 0x86, 0x49, 0x41, 0xbf, 0x0c, 0xef, 0x02, 0x40, 0x49, 0xfc, + 0x9a, 0x1e, 0x65, 0xd7, 0x22, 0xe4, 0xb2, 0x08, 0x78, 0xac, 0x5c, 0xce, 0x80, 0x5d, 0xc3, 0xd5, 0x3a, 0x45, 0x17, + 0xbd, 0x30, 0x00, 0x96, 0xe9, 0x1a, 0xba, 0xfc, 0x04, 0x2c, 0x9d, 0x93, 0x89, 0x99, 0xae, 0xf9, 0xd3, 0x6a, 0x1a, + 0x27, 0x7a, 0x01, 0x79, 0x21, 0x7e, 0x47, 0x06, 0x17, 0x7c, 0xc6, 0x7c, 0x1a, 0x13, 0x33, 0xf7, 0x6f, 0xdf, 0x9a, + 0xa0, 0x20, 0xa8, 0x06, 0x33, 0x4c, 0xa8, 0x9d, 0x41, 0x2b, 0xa8, 0x9d, 0x2c, 0xb8, 0xed, 0x2c, 0x4c, 0x73, 0xf4, + 0x68, 0x13, 0x66, 0x67, 0x8f, 0x36, 0x49, 0x36, 0x7c, 0xb4, 0xf1, 0xa4, 0x8e, 0x81, 0x7e, 0xa1, 0x93, 0x82, 0xc1, + 0x08, 0xc1, 0x30, 0xca, 0xae, 0x73, 0x8b, 0x9f, 0x7c, 0xbe, 0xb0, 0xcb, 0x28, 0x5d, 0x43, 0x91, 0xff, 0x90, 0x0b, + 0xf6, 0x57, 0xb1, 0xbf, 0xf4, 0xe2, 0x7b, 0xd2, 0x03, 0x30, 0x55, 0x65, 0x01, 0x43, 0xd7, 0x08, 0xd1, 0x13, 0x00, + 0x08, 0xe7, 0xeb, 0xda, 0x37, 0x32, 0x8d, 0xf1, 0xd9, 0x4a, 0x61, 0x28, 0xf4, 0x75, 0xad, 0x3f, 0x65, 0xf6, 0x94, + 0xa5, 0x9e, 0x1f, 0x50, 0x95, 0x81, 0x88, 0x72, 0x5f, 0x99, 0x5e, 0x52, 0x9c, 0x5e, 0x58, 0xdc, 0x3f, 0x38, 0x19, + 0xba, 0x02, 0x68, 0xdc, 0x38, 0x33, 0x8c, 0x7e, 0x55, 0xbf, 0xa2, 0x94, 0xf7, 0xa7, 0x2e, 0x07, 0x83, 0xe5, 0x08, + 0x61, 0x39, 0x58, 0x38, 0x89, 0xa6, 0xec, 0xa7, 0xb7, 0xaf, 0x65, 0xb8, 0x2d, 0xe0, 0x1c, 0x8d, 0xf8, 0xc6, 0x4c, + 0x90, 0x7e, 0x88, 0x91, 0x76, 0xa0, 0xc0, 0x58, 0x9a, 0xdc, 0x42, 0x71, 0xa6, 0x6b, 0x67, 0x34, 0x76, 0x36, 0xa5, + 0x51, 0x0f, 0x23, 0xac, 0x15, 0x67, 0x27, 0x07, 0x54, 0x9a, 0x6e, 0x3b, 0x2a, 0x04, 0x60, 0x88, 0x61, 0x86, 0x39, + 0x14, 0x20, 0x32, 0xe8, 0xd0, 0xcd, 0x1f, 0x14, 0xf6, 0x12, 0xf9, 0xf3, 0xee, 0x59, 0x91, 0x54, 0xc1, 0x5a, 0xfa, + 0xe9, 0x09, 0xc6, 0xfa, 0x82, 0xfb, 0x1a, 0xbc, 0x83, 0x9c, 0x1c, 0xd0, 0xa7, 0x56, 0x3a, 0x11, 0x79, 0x23, 0xe2, + 0x69, 0xd7, 0xe7, 0x0d, 0x7c, 0xd2, 0x51, 0x81, 0xd0, 0xf2, 0x90, 0xea, 0x65, 0xba, 0xb6, 0xe4, 0xa4, 0x11, 0x77, + 0x43, 0x04, 0x3e, 0x0a, 0x1c, 0x38, 0xbb, 0xba, 0xb6, 0xf4, 0xee, 0x70, 0xe6, 0x22, 0xc7, 0xbb, 0x6b, 0xb9, 0x3c, + 0x2b, 0x3f, 0x6b, 0x49, 0xf1, 0xac, 0x4d, 0xf8, 0xe2, 0x82, 0x01, 0x82, 0x7c, 0x91, 0x2f, 0x50, 0xb0, 0x5b, 0xb3, + 0xb8, 0x0b, 0xb1, 0xb8, 0xd3, 0x86, 0xc5, 0x9d, 0x6e, 0x59, 0xdc, 0x80, 0x2f, 0xa4, 0x26, 0x41, 0x17, 0xa3, 0x51, + 0x99, 0x04, 0x1e, 0x27, 0x34, 0xfa, 0xfc, 0x9c, 0x21, 0x9c, 0xac, 0x24, 0x00, 0xa5, 0xaa, 0x06, 0x58, 0xd5, 0xc1, + 0x45, 0x01, 0x44, 0x75, 0xe2, 0xf2, 0xd4, 0x89, 0x79, 0x43, 0xec, 0xce, 0x56, 0x50, 0x9e, 0x2f, 0xec, 0x52, 0x8a, + 0x4b, 0xde, 0x5a, 0x34, 0xcc, 0x74, 0xb1, 0x65, 0xa6, 0x93, 0xc2, 0xd1, 0xe5, 0xd3, 0xa6, 0x43, 0xa8, 0x4e, 0x0a, + 0xf6, 0x20, 0x28, 0x9a, 0xe2, 0x96, 0x29, 0xee, 0xc3, 0x66, 0x1c, 0xab, 0xec, 0xa8, 0x95, 0x97, 0x24, 0xb7, 0x51, + 0x0c, 0x92, 0x1a, 0x68, 0xe6, 0xd3, 0xb6, 0xd4, 0xd2, 0x0f, 0xb9, 0x13, 0x98, 0xc6, 0xcd, 0x94, 0xe7, 0xab, 0x5b, + 0xaa, 0xdd, 0xed, 0x52, 0x89, 0x95, 0x97, 0xa6, 0x2c, 0x46, 0xa0, 0x7b, 0xe0, 0x2d, 0xfc, 0xbf, 0x64, 0x9b, 0xd5, + 0xe0, 0x90, 0x40, 0xc1, 0xea, 0x88, 0xa1, 0x57, 0x40, 0x5b, 0xc5, 0xe2, 0x22, 0x56, 0x1c, 0xca, 0xc5, 0x12, 0xf0, + 0x3f, 0xe0, 0x71, 0x6d, 0xc5, 0x8a, 0xc9, 0x93, 0x7b, 0x64, 0xd8, 0x2b, 0x6f, 0xfa, 0x0e, 0x04, 0x82, 0xad, 0xb6, + 0x09, 0xca, 0xbd, 0xaa, 0xfb, 0xb8, 0x98, 0x88, 0xbd, 0x49, 0x8e, 0x24, 0x11, 0x4b, 0x72, 0xd5, 0x29, 0xb0, 0xba, + 0xf4, 0xac, 0xd9, 0xd5, 0xa6, 0x9d, 0x1d, 0xcc, 0x7d, 0xa3, 0x82, 0x35, 0x01, 0xb5, 0x05, 0xc3, 0x53, 0xf9, 0xe6, + 0x0a, 0x4c, 0xf7, 0xc8, 0x00, 0x8e, 0xf1, 0x25, 0xc4, 0x41, 0x75, 0xc4, 0x83, 0x76, 0x14, 0xc3, 0xad, 0x75, 0xe9, + 0x5c, 0x65, 0x8f, 0xe7, 0xf8, 0xcb, 0xbd, 0xca, 0x1e, 0x8f, 0xf1, 0x57, 0xfb, 0x0a, 0x23, 0xde, 0xd5, 0x3c, 0xe4, + 0x95, 0x39, 0xeb, 0xa7, 0x85, 0xfd, 0x44, 0x7a, 0x6b, 0x9f, 0xb0, 0x6d, 0xf8, 0x02, 0x3f, 0x7c, 0xb4, 0x49, 0xc0, + 0x52, 0x53, 0x9d, 0x43, 0x68, 0xc7, 0x46, 0x56, 0x9b, 0x3e, 0x6f, 0x48, 0x1f, 0x1b, 0x7f, 0xf2, 0xc5, 0x8f, 0xbb, + 0x24, 0xca, 0xef, 0x94, 0x22, 0x1b, 0xe2, 0x7a, 0xec, 0x87, 0x5e, 0x7c, 0x7f, 0x4d, 0xcf, 0x8b, 0x96, 0xa0, 0xdd, + 0x25, 0x7b, 0x85, 0xc8, 0xcb, 0xa2, 0x98, 0x2c, 0x55, 0x18, 0xc3, 0xf7, 0xfc, 0xa2, 0x1f, 0xfe, 0x3d, 0x56, 0xc8, + 0xb6, 0xc2, 0x03, 0x94, 0x2f, 0x48, 0xa1, 0xa3, 0xeb, 0x47, 0x9b, 0x16, 0xab, 0x36, 0x53, 0x9a, 0x6d, 0x89, 0x2e, + 0x84, 0xe5, 0xc1, 0xc7, 0xec, 0x72, 0xea, 0xf7, 0x51, 0x0e, 0x36, 0x8e, 0xee, 0xac, 0x47, 0x9b, 0xf4, 0x4c, 0x5f, + 0x7a, 0xf1, 0x07, 0x36, 0xb5, 0x26, 0x7e, 0x3c, 0x09, 0x98, 0xde, 0xd7, 0xc7, 0x81, 0x17, 0x7e, 0xe0, 0x9f, 0x56, + 0xb4, 0x4e, 0x51, 0xb2, 0xbd, 0xf3, 0xed, 0x2b, 0x60, 0x42, 0x2c, 0x3b, 0x24, 0x56, 0x6b, 0xa0, 0xa0, 0x3d, 0x97, + 0x0c, 0xaf, 0x9c, 0x50, 0xcc, 0x4b, 0x99, 0xa0, 0x98, 0x09, 0xc2, 0x76, 0xb0, 0x74, 0x35, 0x75, 0x5c, 0x2f, 0xdd, + 0x54, 0xa7, 0x4a, 0xcc, 0x4a, 0x19, 0xaa, 0xf1, 0x1a, 0x5b, 0xf8, 0xfd, 0xdd, 0x51, 0x10, 0xed, 0xfd, 0xbb, 0x93, + 0xad, 0x7c, 0xde, 0x0c, 0x21, 0xd5, 0x22, 0x0b, 0x8b, 0x4f, 0xe8, 0x9c, 0x13, 0x98, 0xcd, 0x5d, 0xab, 0x95, 0xbd, + 0x24, 0x59, 0x2f, 0xd9, 0x94, 0x24, 0x8a, 0x67, 0xf9, 0xa0, 0x8a, 0x2f, 0x0b, 0x75, 0x60, 0xbf, 0xac, 0xdb, 0xc7, + 0x87, 0xcf, 0x41, 0xd3, 0x01, 0x08, 0xca, 0x68, 0x36, 0xd3, 0xf3, 0x37, 0xfe, 0x8e, 0x6a, 0xee, 0xe1, 0x2f, 0xeb, + 0x57, 0x2f, 0x9d, 0x57, 0xb2, 0x72, 0x08, 0x84, 0xb1, 0x10, 0xdb, 0x72, 0xba, 0x58, 0x19, 0xaf, 0x98, 0xd1, 0xcc, + 0x0b, 0x9b, 0xa7, 0x73, 0x59, 0xd8, 0xe2, 0x2b, 0xc6, 0xa6, 0x40, 0x70, 0x9b, 0x95, 0xd4, 0xeb, 0x80, 0xdd, 0x30, + 0x29, 0x12, 0xae, 0x76, 0x56, 0x53, 0x03, 0x7d, 0xd6, 0x71, 0x51, 0x33, 0xa7, 0xea, 0x94, 0x29, 0x8d, 0x70, 0x0e, + 0x7c, 0xe6, 0xea, 0x11, 0x2b, 0x1d, 0xa9, 0x91, 0xa9, 0x2b, 0x03, 0x68, 0x1c, 0xd9, 0x59, 0x43, 0x7a, 0x1f, 0x03, + 0x56, 0xd7, 0x8f, 0xcd, 0x74, 0x8d, 0x3e, 0xf8, 0xf8, 0xe6, 0x70, 0x0a, 0xe0, 0xe4, 0xb5, 0x72, 0x76, 0x48, 0x13, + 0xc4, 0xea, 0x98, 0x64, 0x3a, 0x71, 0x5f, 0x84, 0x96, 0x24, 0xaa, 0x0b, 0x0b, 0x3e, 0x54, 0xed, 0xda, 0x68, 0xc5, + 0x99, 0x8f, 0x31, 0x10, 0x6c, 0xc8, 0x92, 0xa4, 0x11, 0x60, 0x72, 0xd1, 0x4d, 0x3d, 0x2f, 0x5d, 0x84, 0x47, 0x9e, + 0x6e, 0x3a, 0x26, 0x90, 0x04, 0x38, 0xc1, 0x72, 0x5f, 0x78, 0xbd, 0x5c, 0x2f, 0xb9, 0x9e, 0x4b, 0x3c, 0x1f, 0xeb, + 0x5c, 0x07, 0xa1, 0x29, 0xff, 0x56, 0xe7, 0x83, 0x2a, 0x5c, 0xd3, 0xb5, 0x43, 0x6b, 0x15, 0x50, 0x6f, 0x85, 0x5d, + 0x84, 0x0d, 0x88, 0x31, 0x95, 0xf0, 0x2b, 0x9b, 0xcd, 0xd8, 0x24, 0x4d, 0x0c, 0xc1, 0x3c, 0x92, 0x5e, 0x67, 0xc1, + 0xda, 0xe8, 0xc1, 0x50, 0xff, 0x01, 0x6c, 0xef, 0x85, 0x73, 0x26, 0x3e, 0x20, 0xf1, 0x66, 0xaa, 0x07, 0x13, 0xb5, + 0x58, 0x04, 0x11, 0xef, 0x05, 0x82, 0x8a, 0xd7, 0xa4, 0xe3, 0xd0, 0xf8, 0xfd, 0x93, 0xef, 0x8b, 0x48, 0x6a, 0xc3, + 0x6c, 0x47, 0x45, 0xdb, 0x8e, 0xef, 0xc6, 0x7d, 0xd5, 0x75, 0x9d, 0x4c, 0x37, 0xc1, 0xe6, 0xeb, 0xc3, 0xbe, 0x87, + 0x1e, 0x6b, 0x75, 0xa0, 0xd6, 0x3a, 0xfc, 0x94, 0x7a, 0x6d, 0xf7, 0x99, 0xab, 0x9b, 0xa4, 0x6a, 0xa7, 0xe0, 0xb6, + 0x49, 0x74, 0xc3, 0xe2, 0xcf, 0x9e, 0x4a, 0xb1, 0xf1, 0xfd, 0xc6, 0x73, 0xe4, 0x3a, 0x80, 0x84, 0xd3, 0x68, 0xf5, + 0x09, 0x53, 0xe8, 0xe8, 0xa6, 0x3e, 0x09, 0xa2, 0x84, 0xa9, 0x73, 0x20, 0x26, 0xc8, 0x67, 0x4e, 0xe2, 0xc7, 0xb7, + 0x2f, 0xdf, 0xbd, 0xd3, 0x4d, 0x8c, 0x20, 0x9a, 0xa8, 0xad, 0xf3, 0x0d, 0xb5, 0x03, 0xfb, 0xd7, 0xee, 0x3b, 0xba, + 0x61, 0xe8, 0x51, 0x5b, 0xdc, 0x73, 0x94, 0x56, 0xd9, 0x72, 0xfc, 0xe6, 0xe1, 0x3d, 0xd3, 0x4b, 0x74, 0xaf, 0x79, + 0xd5, 0xe0, 0x86, 0xed, 0xd7, 0x5b, 0x21, 0x65, 0xe9, 0x87, 0xd7, 0x35, 0xa9, 0xde, 0x5d, 0x4d, 0x2a, 0x3c, 0xe5, + 0x2a, 0xb8, 0x6a, 0x1d, 0x2d, 0x15, 0xd2, 0x00, 0x02, 0x40, 0xef, 0x02, 0x97, 0xf2, 0x9e, 0xfa, 0x8c, 0x41, 0x73, + 0x0f, 0xf0, 0xe5, 0x51, 0xd7, 0x24, 0xf3, 0x47, 0x90, 0x84, 0xed, 0x24, 0x00, 0x45, 0x41, 0xa6, 0x4a, 0xe5, 0x8a, + 0x64, 0x23, 0x57, 0xf3, 0x1d, 0x96, 0x28, 0x74, 0xaa, 0x46, 0x02, 0x10, 0x8e, 0xdf, 0x57, 0xde, 0x14, 0xb4, 0xef, + 0xac, 0x71, 0x94, 0xa6, 0xd1, 0xb2, 0xef, 0x3a, 0xab, 0x3b, 0x5d, 0x1b, 0x08, 0xc6, 0x03, 0x57, 0x0e, 0xec, 0xff, + 0xf6, 0xef, 0x12, 0xca, 0xa5, 0xf4, 0xeb, 0x94, 0x2d, 0x57, 0x2c, 0xf6, 0xd2, 0x75, 0xcc, 0x32, 0xed, 0xb7, 0xff, + 0x7b, 0x5e, 0x7a, 0x64, 0x0f, 0xd4, 0x3a, 0x44, 0x5e, 0xab, 0x55, 0xae, 0x83, 0xe8, 0xf6, 0x41, 0x6e, 0x06, 0xb0, + 0xa3, 0xf0, 0xc2, 0x9f, 0x2f, 0x64, 0xe9, 0xb3, 0x74, 0xcb, 0xdc, 0xc4, 0xe8, 0x89, 0xe9, 0xae, 0x9d, 0x47, 0xb7, + 0xfd, 0xdf, 0xfe, 0x2d, 0x99, 0x27, 0x3b, 0x77, 0x5d, 0xfd, 0x40, 0x8b, 0x2b, 0x5a, 0x5f, 0xa6, 0xb2, 0xc4, 0x90, + 0x5f, 0x59, 0xe0, 0x4a, 0x22, 0xed, 0xca, 0xaa, 0x84, 0x6b, 0xcb, 0x9c, 0xfe, 0xea, 0xcf, 0x17, 0x9f, 0x3b, 0x29, + 0x00, 0xe8, 0xce, 0x59, 0x41, 0xa1, 0x2f, 0x30, 0xad, 0x51, 0x7f, 0xff, 0x05, 0xfb, 0xcc, 0x79, 0xed, 0x9a, 0xd2, + 0x97, 0x98, 0x0d, 0xe7, 0xa2, 0x3e, 0x1f, 0x8d, 0x64, 0x04, 0x3d, 0xb5, 0x3e, 0x18, 0x32, 0x9c, 0x55, 0x52, 0xf8, + 0x55, 0xdf, 0x77, 0x0c, 0xf2, 0x30, 0xb0, 0x07, 0x40, 0x50, 0x25, 0xaf, 0x06, 0x1c, 0xcd, 0xf8, 0x9a, 0x34, 0xeb, + 0x2b, 0x7d, 0x57, 0x90, 0x35, 0xa4, 0x62, 0xf4, 0x35, 0x29, 0x9a, 0x33, 0xeb, 0x87, 0x73, 0x1b, 0x7b, 0x2b, 0x62, + 0xd8, 0x6b, 0x28, 0x8f, 0x00, 0x06, 0x88, 0x78, 0xd1, 0x62, 0x70, 0x97, 0x37, 0x4d, 0x0a, 0x71, 0x3f, 0xee, 0x56, + 0x88, 0xbb, 0xd8, 0x4b, 0x21, 0xee, 0xc7, 0x2f, 0xae, 0x10, 0xf7, 0x46, 0x55, 0x88, 0x83, 0xb5, 0x7c, 0xc9, 0xf6, + 0xd2, 0x52, 0x13, 0xaa, 0x26, 0xd1, 0x6d, 0x32, 0x74, 0x39, 0x1d, 0x9e, 0x4c, 0x16, 0x0c, 0x18, 0x1b, 0x1c, 0xea, + 0x41, 0x34, 0x07, 0x8d, 0xb5, 0x3f, 0x5e, 0xb7, 0x2c, 0x88, 0xe6, 0xaa, 0x66, 0x59, 0xc8, 0xdd, 0xdb, 0xe6, 0x2e, + 0xab, 0x48, 0x9b, 0xcb, 0x31, 0x85, 0x83, 0x2b, 0xeb, 0xd0, 0x50, 0x42, 0x78, 0x4b, 0x55, 0xbd, 0xb6, 0xd0, 0xf7, + 0xea, 0xa3, 0xaa, 0x98, 0xac, 0xd8, 0x7e, 0x2a, 0x1c, 0x79, 0xa8, 0x2d, 0x48, 0x95, 0x68, 0x72, 0x8a, 0xb1, 0xd1, + 0x7f, 0xb9, 0x73, 0xbf, 0xbb, 0x74, 0x07, 0x1d, 0x17, 0x2c, 0xd1, 0xe1, 0x59, 0x8c, 0x09, 0xce, 0xa0, 0xd3, 0x81, + 0x84, 0x5b, 0x25, 0xa1, 0x0d, 0x09, 0xbe, 0x92, 0xd0, 0x85, 0x84, 0x89, 0x92, 0x70, 0x04, 0x09, 0x53, 0x25, 0xe1, + 0x18, 0x12, 0x6e, 0xf4, 0xec, 0x32, 0x94, 0xc3, 0x3d, 0x36, 0xae, 0x4c, 0x7a, 0x09, 0x89, 0xb4, 0x63, 0xd3, 0x05, + 0x15, 0x31, 0x6f, 0xde, 0x8f, 0x4c, 0x62, 0x89, 0xf6, 0x63, 0xf3, 0x76, 0xc1, 0xc8, 0x2b, 0xf6, 0x0b, 0xbc, 0x28, + 0xed, 0x34, 0x02, 0x25, 0x71, 0xe1, 0x6d, 0x42, 0xc0, 0x41, 0xd3, 0x0d, 0xe0, 0x72, 0x0d, 0xe4, 0xca, 0x09, 0x8f, + 0x1d, 0xca, 0x5a, 0xe6, 0x79, 0xd4, 0x9d, 0x25, 0xb7, 0x40, 0xae, 0x26, 0xd3, 0x52, 0x59, 0xa9, 0x5f, 0x42, 0x59, + 0xe2, 0x05, 0x1b, 0xaf, 0xe7, 0xda, 0x79, 0x34, 0xdf, 0xa9, 0xf7, 0xa0, 0x66, 0xc1, 0x28, 0x75, 0x92, 0x19, 0x59, + 0x62, 0x5b, 0xf2, 0xbe, 0xe8, 0x33, 0x2b, 0x96, 0x4f, 0x61, 0x6c, 0x5a, 0x4a, 0x18, 0x07, 0xfa, 0x01, 0x18, 0x29, + 0x8a, 0x07, 0xe7, 0x00, 0x67, 0xe5, 0xfb, 0xc2, 0x53, 0xc6, 0x73, 0xfa, 0x3d, 0x4b, 0x12, 0x6f, 0x2e, 0xca, 0x57, + 0xc7, 0x09, 0x9a, 0x46, 0xf2, 0xd1, 0x88, 0x00, 0x04, 0xf6, 0xa3, 0x5f, 0x51, 0x28, 0x89, 0xa3, 0x5b, 0x0d, 0x54, + 0x96, 0x60, 0x43, 0xe5, 0xca, 0x15, 0xbe, 0x0d, 0x4b, 0x58, 0x54, 0x83, 0x80, 0xc3, 0x7f, 0xc3, 0x82, 0x72, 0x62, + 0xea, 0xcd, 0xcb, 0x49, 0xb4, 0x0f, 0x32, 0x75, 0x6c, 0x52, 0x0b, 0xa1, 0x90, 0xf8, 0x39, 0x62, 0xf5, 0x20, 0x9a, + 0xff, 0xa1, 0x32, 0xf5, 0x2d, 0xba, 0x10, 0xef, 0x42, 0xd3, 0x4f, 0x47, 0x36, 0xc2, 0x58, 0xb3, 0x01, 0x84, 0xfd, + 0x30, 0x5d, 0x58, 0x68, 0x47, 0xd7, 0x6a, 0x87, 0x86, 0x69, 0xe3, 0xda, 0x6e, 0xca, 0xd6, 0xc3, 0xfd, 0x78, 0x3e, + 0xf6, 0x5a, 0x6e, 0xfb, 0xd8, 0x14, 0x7f, 0x6c, 0xa7, 0x6b, 0x64, 0xd8, 0x82, 0x36, 0xf5, 0x6f, 0x36, 0xb3, 0x28, + 0x4c, 0xad, 0x99, 0xb7, 0xf4, 0x83, 0xfb, 0xfe, 0x32, 0x0a, 0xa3, 0x64, 0xe5, 0x4d, 0xd8, 0x20, 0xe7, 0x02, 0x0c, + 0xd0, 0x2f, 0x05, 0x37, 0x8d, 0x74, 0xed, 0x76, 0xcc, 0x96, 0x54, 0x5b, 0xba, 0x9d, 0x98, 0x05, 0xec, 0x2e, 0xe3, + 0xdd, 0x17, 0x0a, 0x53, 0x51, 0xdc, 0x72, 0x54, 0x03, 0xc8, 0x68, 0xee, 0xd3, 0x02, 0x3c, 0x39, 0x0d, 0x38, 0x2d, + 0xda, 0xb7, 0xdb, 0xdd, 0x98, 0x2d, 0x35, 0xbb, 0xdb, 0xd8, 0x78, 0x1c, 0xdd, 0x9e, 0xc2, 0x68, 0xb1, 0xb2, 0x95, + 0xb0, 0x60, 0x86, 0x39, 0x16, 0x9a, 0xd1, 0x88, 0x76, 0x2c, 0xe4, 0x1e, 0x40, 0x6b, 0x6c, 0x39, 0x80, 0xec, 0x7e, + 0x5b, 0x73, 0x06, 0x4b, 0x3f, 0xb4, 0x68, 0x3a, 0xc7, 0xce, 0x4a, 0x69, 0x4b, 0x85, 0x9f, 0xb1, 0xc1, 0xe2, 0xae, + 0xe6, 0x0c, 0xe0, 0x85, 0x39, 0x0b, 0xa2, 0xdb, 0xfe, 0xc2, 0x9f, 0x4e, 0x59, 0x38, 0xc0, 0x31, 0xcb, 0x44, 0x16, + 0x04, 0xfe, 0x2a, 0xf1, 0x93, 0xc1, 0xd2, 0xbb, 0xe3, 0xad, 0x1e, 0x36, 0xb5, 0xda, 0xe1, 0xad, 0x76, 0xf6, 0x6e, + 0x55, 0x69, 0x06, 0x4c, 0x76, 0xa8, 0x1d, 0x3e, 0xb4, 0xae, 0xe6, 0x94, 0xe6, 0xb9, 0x77, 0xab, 0xab, 0x98, 0x6d, + 0x96, 0x5e, 0x3c, 0xf7, 0xc3, 0xbe, 0x93, 0xd9, 0x37, 0x1b, 0xda, 0x18, 0x0f, 0x7b, 0xbd, 0x5e, 0x66, 0x4f, 0xc5, + 0x97, 0x33, 0x9d, 0x66, 0xf6, 0x44, 0x7c, 0xcd, 0x66, 0x8e, 0x33, 0x9b, 0x65, 0xb6, 0x2f, 0x12, 0x3a, 0xed, 0xc9, + 0xb4, 0xd3, 0xce, 0xec, 0x5b, 0xa5, 0x44, 0x66, 0x33, 0xfe, 0x15, 0xb3, 0xe9, 0x00, 0x37, 0x12, 0xe9, 0xd0, 0xf6, + 0x8f, 0x1d, 0x27, 0x43, 0x0c, 0x70, 0x59, 0xc0, 0x4d, 0xc8, 0xa0, 0xba, 0xda, 0xec, 0x5d, 0x52, 0xcb, 0xbb, 0x9b, + 0x4c, 0x6a, 0xcb, 0x4d, 0xbd, 0xf8, 0xc3, 0x95, 0xa6, 0xcc, 0xc2, 0xf3, 0xa8, 0xd8, 0x46, 0x80, 0xc1, 0xba, 0xeb, + 0x83, 0x7f, 0xb2, 0xc1, 0x38, 0x8a, 0xe1, 0xcc, 0xc6, 0xde, 0xd4, 0x5f, 0x27, 0x7d, 0xb7, 0xbd, 0xba, 0x13, 0x49, + 0x7c, 0xaf, 0xe7, 0x09, 0x78, 0xf6, 0xfa, 0x49, 0x14, 0xf8, 0x53, 0x91, 0xd4, 0x74, 0x96, 0xdc, 0xb6, 0x31, 0x40, + 0xeb, 0x7c, 0x1f, 0x7d, 0x4c, 0x78, 0x41, 0xa0, 0xd9, 0x9d, 0x44, 0x63, 0x5e, 0x82, 0x4c, 0x71, 0xcd, 0x49, 0x08, + 0x2e, 0x68, 0x89, 0xef, 0x1e, 0xae, 0xee, 0xe4, 0x9e, 0x77, 0x8f, 0x56, 0x77, 0xd9, 0x37, 0x4b, 0x36, 0xf5, 0x3d, + 0xad, 0x95, 0xef, 0x26, 0xd7, 0x01, 0xc6, 0xb9, 0xb1, 0x69, 0xd8, 0xa6, 0xe2, 0x58, 0x80, 0x1f, 0xc7, 0x07, 0xfe, + 0x72, 0x15, 0xc5, 0xa9, 0x17, 0xa6, 0x59, 0x36, 0xba, 0xca, 0xb2, 0xc1, 0x85, 0xdf, 0xba, 0xfc, 0x47, 0x8b, 0xee, + 0x69, 0x12, 0x34, 0x65, 0xc6, 0x95, 0xf9, 0x92, 0xa9, 0x8a, 0x2e, 0x70, 0x8d, 0xa1, 0x92, 0x8b, 0x5a, 0x98, 0x6e, + 0xc9, 0x6a, 0x61, 0x02, 0xb2, 0x2c, 0x4e, 0x8a, 0x33, 0xc5, 0x22, 0x78, 0x03, 0x41, 0x81, 0x97, 0x6c, 0x78, 0xa1, + 0x28, 0xcd, 0x00, 0xb1, 0x82, 0x85, 0xc9, 0x88, 0xe2, 0x51, 0x13, 0xcd, 0xf8, 0xed, 0x6e, 0x9a, 0xf1, 0xe7, 0x74, + 0x1f, 0x9a, 0xf1, 0xdb, 0x2f, 0x4e, 0x33, 0x3e, 0xaa, 0x1a, 0x51, 0xbc, 0x8e, 0x86, 0xba, 0x14, 0x8b, 0xc0, 0xd5, + 0x14, 0x93, 0x7b, 0xa2, 0xd7, 0xbf, 0xdb, 0xe6, 0x41, 0xb4, 0x46, 0x01, 0xf7, 0xe8, 0xe6, 0x06, 0x26, 0xf2, 0x9b, + 0x70, 0xf8, 0xf7, 0x58, 0xfd, 0x9e, 0xcd, 0x86, 0x2f, 0x22, 0x25, 0x41, 0x7e, 0x71, 0x8d, 0x91, 0x82, 0x2b, 0x09, + 0xca, 0x11, 0xaa, 0xa3, 0x18, 0x6c, 0x03, 0x2c, 0xd1, 0x49, 0x55, 0x7a, 0x2a, 0x55, 0xe6, 0x06, 0xc5, 0x21, 0xb4, + 0xa4, 0x9e, 0xaa, 0xb0, 0x37, 0xaa, 0xf0, 0x3f, 0xe7, 0x2c, 0xe5, 0x06, 0xc2, 0xdf, 0xdd, 0xbf, 0x9e, 0xb6, 0x5e, + 0x47, 0x46, 0xe6, 0x27, 0x6f, 0xca, 0xd6, 0x3e, 0x5c, 0x60, 0x35, 0x54, 0xa7, 0x93, 0x71, 0xb5, 0x37, 0x35, 0x9a, + 0x36, 0x64, 0x53, 0xf5, 0xb3, 0xc2, 0x4c, 0xfb, 0x6a, 0x45, 0x1e, 0xd5, 0xab, 0x72, 0x19, 0x73, 0x53, 0x8b, 0x0d, + 0xa7, 0x00, 0x31, 0x50, 0x19, 0x1a, 0x49, 0x4f, 0xa9, 0xba, 0x3f, 0xcd, 0x32, 0x63, 0x20, 0x00, 0xa1, 0x5c, 0xb4, + 0x6c, 0x17, 0x11, 0x97, 0xe4, 0xef, 0x31, 0x2e, 0xd6, 0x24, 0x99, 0xe5, 0x6b, 0xd0, 0x02, 0xe0, 0x12, 0x4e, 0x0e, + 0x33, 0x5d, 0x23, 0xf0, 0x91, 0x76, 0x88, 0x32, 0x21, 0x10, 0x5b, 0x4b, 0xf8, 0x8b, 0x2c, 0x91, 0x50, 0x55, 0x3c, + 0x25, 0xe0, 0xa0, 0x1a, 0x03, 0xb8, 0x34, 0x10, 0xcc, 0x1a, 0x42, 0x3b, 0xbc, 0x0c, 0x7e, 0x64, 0xba, 0xa4, 0xfd, + 0x70, 0xfb, 0x9d, 0x9e, 0x1c, 0x40, 0x85, 0xd3, 0x12, 0x23, 0x66, 0x87, 0x5a, 0x25, 0x90, 0x12, 0xc9, 0xad, 0x69, + 0x27, 0xb7, 0xda, 0x93, 0x8d, 0x70, 0x07, 0x92, 0x7a, 0x2b, 0x0b, 0x5e, 0xff, 0x88, 0x7b, 0x39, 0xc6, 0x53, 0x3c, + 0x8f, 0x0c, 0xd6, 0x09, 0xe0, 0x46, 0x7c, 0x88, 0x22, 0xfe, 0x19, 0x4c, 0xd6, 0x71, 0x12, 0xc5, 0xfd, 0x55, 0xe4, + 0x87, 0x29, 0x8b, 0x33, 0x04, 0xd5, 0x25, 0xc2, 0x47, 0x80, 0xe7, 0x6a, 0x13, 0xad, 0xbc, 0x89, 0x9f, 0xde, 0xf7, + 0x1d, 0x4e, 0x52, 0x38, 0x03, 0x4e, 0x1d, 0x38, 0xb5, 0xe5, 0xfb, 0x1c, 0x9a, 0x4f, 0x91, 0xf0, 0x8b, 0xab, 0xe4, + 0x8c, 0xba, 0xcd, 0x07, 0x4a, 0x2e, 0x39, 0x44, 0x01, 0xf2, 0xc3, 0x8b, 0xad, 0x39, 0x60, 0x79, 0x58, 0x6a, 0x67, + 0xca, 0xe6, 0x26, 0x62, 0x6d, 0x10, 0x26, 0x88, 0x3f, 0x76, 0xd7, 0xd0, 0x9c, 0xfa, 0x64, 0xa0, 0x78, 0x8c, 0x7d, + 0x46, 0xd6, 0xf7, 0x20, 0x7c, 0x98, 0xb9, 0x4f, 0xc9, 0x31, 0x9b, 0x45, 0x31, 0x23, 0xe7, 0xb9, 0x6e, 0x6f, 0x75, + 0xb7, 0x7f, 0xf3, 0xdb, 0xa7, 0x5f, 0xdf, 0x4e, 0x18, 0xa5, 0x2d, 0xd1, 0x98, 0xb1, 0xa3, 0xb5, 0xea, 0x7d, 0x06, + 0xa4, 0x21, 0x41, 0x7e, 0x42, 0x7e, 0xca, 0xfa, 0xba, 0x3e, 0xa8, 0xf5, 0x51, 0xb6, 0x8a, 0xf8, 0x9d, 0x17, 0xb3, + 0xc0, 0x4b, 0xfd, 0x1b, 0x41, 0x33, 0x76, 0x8e, 0x56, 0x77, 0x62, 0x8d, 0xf1, 0xc2, 0xfb, 0x84, 0x45, 0x2a, 0x0d, + 0x45, 0x2c, 0x52, 0x39, 0x19, 0x17, 0x69, 0x50, 0x99, 0x8d, 0x70, 0xdb, 0x51, 0xba, 0xe9, 0xbb, 0xab, 0x3b, 0xf5, + 0x8a, 0xce, 0xab, 0xc9, 0x9b, 0xba, 0xec, 0x6f, 0x6d, 0xe9, 0x4f, 0xa7, 0x01, 0xcb, 0x0a, 0x0b, 0x5d, 0x5c, 0x4b, + 0x05, 0x38, 0x12, 0x0e, 0xde, 0x38, 0x89, 0x82, 0x75, 0xca, 0xea, 0xc1, 0x45, 0xc0, 0x69, 0x3b, 0x39, 0x70, 0xf0, + 0x77, 0x71, 0xac, 0x5d, 0x20, 0xb7, 0x61, 0x9b, 0x38, 0x03, 0x70, 0xaf, 0x6c, 0x75, 0x8a, 0x43, 0x87, 0x2c, 0x39, + 0x68, 0xb3, 0x66, 0x22, 0x26, 0x5c, 0x4b, 0x84, 0xbd, 0x35, 0xdb, 0xe5, 0x69, 0xd2, 0xc5, 0xac, 0x4c, 0xca, 0x8a, + 0x93, 0xf9, 0x63, 0xce, 0xd8, 0xb3, 0xfa, 0x33, 0xf6, 0x4c, 0x9c, 0xb1, 0xed, 0x3b, 0xf3, 0xe1, 0xcc, 0x85, 0xff, + 0x06, 0xf9, 0x84, 0xfa, 0x8e, 0xd6, 0x59, 0xdd, 0x69, 0xee, 0xea, 0x4e, 0xb3, 0xda, 0xab, 0x3b, 0x0d, 0x9b, 0x46, + 0x25, 0x16, 0xd3, 0x6e, 0x1b, 0xa6, 0xa3, 0x41, 0x22, 0xfc, 0x71, 0x0a, 0x59, 0xee, 0x21, 0xe4, 0x41, 0xad, 0x6e, + 0x35, 0xaf, 0xbd, 0xfd, 0xa8, 0xd3, 0x59, 0x12, 0x48, 0xdb, 0xb0, 0x53, 0x6f, 0x3c, 0x66, 0xd3, 0xfe, 0x2c, 0x9a, + 0xac, 0x93, 0x7f, 0xf1, 0xf1, 0x73, 0x20, 0x6e, 0x45, 0x04, 0xa5, 0x76, 0x44, 0x55, 0x90, 0xee, 0xdc, 0x30, 0xd1, + 0xc2, 0x46, 0xae, 0x53, 0x9f, 0x7c, 0x41, 0xb7, 0xed, 0xc3, 0x9a, 0x4d, 0x5e, 0x0f, 0xe8, 0x3f, 0x6c, 0x95, 0x9a, + 0x51, 0xcc, 0x67, 0x80, 0x65, 0x2b, 0x38, 0x3e, 0x1d, 0x1a, 0x7c, 0x35, 0x9d, 0x5e, 0xfd, 0x70, 0x2f, 0x45, 0x4f, + 0x57, 0xe2, 0x52, 0xe1, 0xf7, 0x16, 0xb7, 0xa6, 0xd9, 0xde, 0x6a, 0xd3, 0x1e, 0xa9, 0xb4, 0xba, 0xe5, 0x42, 0xc8, + 0xcb, 0xee, 0x89, 0xe5, 0x1f, 0x3e, 0x3b, 0x84, 0xff, 0x88, 0xaa, 0xff, 0x39, 0xad, 0x23, 0xd4, 0x5f, 0x17, 0xd5, + 0xd7, 0x89, 0x54, 0x42, 0x42, 0x7c, 0xff, 0xf2, 0xb3, 0xd9, 0xa7, 0x55, 0xd8, 0xbb, 0x34, 0xe9, 0x7f, 0x95, 0x4b, + 0x7f, 0x17, 0x45, 0x10, 0xa7, 0xb4, 0x5a, 0x5c, 0x80, 0x87, 0x34, 0xf4, 0xd3, 0x21, 0x54, 0x12, 0xef, 0x08, 0x52, + 0x3d, 0xd0, 0xb1, 0x0e, 0x3d, 0x25, 0x5e, 0x36, 0x3d, 0x25, 0x5e, 0xec, 0x7e, 0x4a, 0xfc, 0x6d, 0xaf, 0xa7, 0xc4, + 0x8b, 0x2f, 0xfe, 0x94, 0x78, 0x59, 0x7d, 0x4a, 0x5c, 0x44, 0x42, 0xe9, 0xd7, 0x7c, 0xbd, 0xe6, 0x3f, 0xdf, 0x93, + 0x24, 0xf1, 0x3c, 0x1a, 0x76, 0x1d, 0xf2, 0xef, 0x7c, 0xf1, 0xbb, 0x1f, 0x16, 0xb8, 0x11, 0xdf, 0xa2, 0x0e, 0x5c, + 0xfe, 0xb4, 0xe0, 0x98, 0x1d, 0xfb, 0x51, 0x92, 0x83, 0x28, 0x9c, 0xff, 0x08, 0x92, 0x64, 0x60, 0x07, 0xc6, 0x4a, + 0x86, 0x9f, 0xfc, 0x18, 0xad, 0xd6, 0xab, 0xd7, 0xd0, 0xd6, 0x7b, 0x3f, 0xf1, 0xc7, 0x01, 0x93, 0x66, 0xd7, 0xa4, + 0xb3, 0xc7, 0x79, 0xe2, 0xa0, 0x26, 0x2b, 0x7e, 0x7a, 0x77, 0xe2, 0x27, 0x2a, 0xd2, 0xf2, 0xdf, 0xa4, 0x0c, 0xa8, + 0xd7, 0x3f, 0x44, 0xc0, 0x41, 0x51, 0x69, 0xd0, 0x9f, 0xfe, 0x18, 0xb9, 0x88, 0x8c, 0x9a, 0x59, 0x0a, 0x25, 0x8d, + 0xc6, 0x76, 0x58, 0xe5, 0x51, 0xb3, 0x36, 0x4c, 0xe9, 0x6f, 0xac, 0xca, 0x86, 0x5f, 0x46, 0xeb, 0x84, 0x4d, 0xa3, + 0xdb, 0x50, 0x37, 0x43, 0x69, 0x19, 0x01, 0x62, 0x59, 0x59, 0x07, 0x23, 0x65, 0xbe, 0x43, 0x42, 0x39, 0x8a, 0x5b, + 0x3a, 0x04, 0x6a, 0x5d, 0xaf, 0x2c, 0x92, 0x8f, 0x5b, 0x38, 0x45, 0x5d, 0x86, 0x74, 0x7a, 0xd0, 0x6a, 0x45, 0xc3, + 0x4f, 0xab, 0x29, 0xf4, 0x4b, 0x22, 0x9b, 0x73, 0x85, 0x93, 0x56, 0x28, 0x98, 0x8b, 0xc2, 0xe9, 0x47, 0xcd, 0xc2, + 0xf1, 0x1c, 0xb2, 0xb7, 0xcd, 0x73, 0xc1, 0x65, 0x4a, 0xb6, 0xe6, 0xeb, 0xc1, 0x5d, 0x60, 0xd0, 0xe7, 0x73, 0x05, + 0x8c, 0x6f, 0x6e, 0x58, 0x1c, 0x78, 0xf7, 0x2d, 0x23, 0x8b, 0xc2, 0xef, 0x01, 0x00, 0x2f, 0xa2, 0xdb, 0x50, 0x2d, + 0x80, 0x91, 0x69, 0x6a, 0xf6, 0x52, 0xad, 0xb3, 0x16, 0xb0, 0xb6, 0x51, 0x46, 0x00, 0x31, 0x81, 0xe7, 0xec, 0xef, + 0x26, 0xfd, 0xfb, 0x0f, 0x23, 0x33, 0xcf, 0x23, 0xd9, 0xd1, 0x4f, 0xab, 0x3d, 0xba, 0x79, 0xfc, 0xf8, 0x41, 0xf3, + 0xb4, 0x8b, 0xb1, 0xe8, 0x6b, 0x6a, 0x1b, 0x8d, 0xa7, 0x00, 0x46, 0x71, 0x11, 0xad, 0x27, 0x0b, 0xd4, 0xce, 0xfd, + 0x72, 0xf3, 0x4d, 0xa1, 0x4d, 0x0c, 0xc9, 0x2a, 0xa7, 0x5e, 0x4a, 0xca, 0xa1, 0x80, 0xfd, 0xbf, 0x04, 0x6f, 0xa3, + 0xff, 0x41, 0x30, 0x54, 0x77, 0x0d, 0x7f, 0xc5, 0xfb, 0x9f, 0xb6, 0x79, 0x07, 0x10, 0x39, 0x94, 0xfb, 0xf1, 0x10, + 0xc2, 0xb5, 0x7a, 0x24, 0x93, 0x95, 0x81, 0xa6, 0xfa, 0xcc, 0x6b, 0x72, 0x07, 0x28, 0x7a, 0x61, 0x36, 0x3d, 0xd3, + 0xb9, 0x75, 0x84, 0xc9, 0x38, 0xb6, 0x2a, 0x21, 0x19, 0xae, 0xa7, 0xc1, 0x10, 0x7d, 0x95, 0xf3, 0x96, 0x7e, 0x68, + 0xa2, 0xcb, 0xfb, 0x6a, 0x8e, 0x77, 0x07, 0x4e, 0x9f, 0x01, 0xb9, 0x95, 0xb3, 0x20, 0xd1, 0x54, 0x8d, 0xfd, 0x20, + 0xae, 0x95, 0x5e, 0x0b, 0x09, 0x21, 0xc5, 0x1b, 0x7d, 0xa5, 0x69, 0x9a, 0x26, 0x9f, 0x11, 0x9a, 0x7c, 0x47, 0x60, + 0x3a, 0x3e, 0x07, 0x40, 0x5a, 0x92, 0xad, 0xee, 0x28, 0x05, 0x5e, 0x06, 0x28, 0x99, 0x15, 0x09, 0xdc, 0xaf, 0x61, + 0xd7, 0x11, 0x09, 0xe2, 0x41, 0x0f, 0x3e, 0xe9, 0xbc, 0x18, 0xdc, 0x1f, 0xf7, 0x35, 0x7c, 0xb0, 0x63, 0x2e, 0xe7, + 0x04, 0x6b, 0x0e, 0x7d, 0x8e, 0x06, 0xac, 0xde, 0x01, 0x5e, 0xa8, 0x60, 0x41, 0x90, 0x3a, 0x94, 0xfc, 0x59, 0x9b, + 0xac, 0x06, 0x37, 0xe2, 0xbb, 0xe8, 0x2e, 0x5d, 0xb2, 0x70, 0xad, 0x63, 0x00, 0x2c, 0x74, 0x48, 0x08, 0x65, 0x5e, + 0x10, 0xb1, 0x05, 0xd8, 0xa6, 0xbe, 0xe6, 0x82, 0xee, 0xc2, 0x84, 0xa3, 0x54, 0xcf, 0x9c, 0x70, 0xc1, 0x66, 0xc2, + 0x71, 0x5b, 0xf9, 0x86, 0xe0, 0x4b, 0x1a, 0x95, 0xad, 0xcf, 0x48, 0x7d, 0x1b, 0xda, 0x20, 0x57, 0x20, 0x9c, 0x5d, + 0x24, 0xc0, 0xde, 0xf2, 0xca, 0x8b, 0x26, 0x25, 0x32, 0x5e, 0x89, 0x51, 0x14, 0x1b, 0xd5, 0x66, 0xf8, 0x38, 0xc1, + 0x0b, 0x53, 0x63, 0x3b, 0x93, 0x4a, 0x3b, 0x0d, 0x93, 0xfe, 0xc0, 0xee, 0xe9, 0x22, 0x21, 0x50, 0x7d, 0x60, 0xf7, + 0xa0, 0xb0, 0xf8, 0x12, 0xb8, 0x29, 0xfa, 0x16, 0x74, 0x6d, 0x42, 0x5c, 0x83, 0x09, 0x78, 0xe6, 0xda, 0x72, 0x80, + 0x9c, 0x6c, 0x0b, 0x16, 0x47, 0x10, 0x43, 0x08, 0x6b, 0x71, 0x88, 0xb9, 0x5d, 0x42, 0xab, 0x16, 0xc6, 0x56, 0xcd, + 0xd1, 0x30, 0x9e, 0xb8, 0x8e, 0x73, 0x50, 0x29, 0x0f, 0x8c, 0xec, 0xba, 0xd2, 0x86, 0x99, 0x0e, 0x5d, 0xc7, 0xf2, + 0x9f, 0xd8, 0xed, 0x41, 0xe5, 0x8e, 0x56, 0x1c, 0x67, 0x8e, 0x90, 0xfd, 0x75, 0xfa, 0x68, 0xd3, 0xaa, 0x1c, 0x48, + 0xa3, 0xac, 0xe7, 0x8f, 0x63, 0xcb, 0x38, 0xff, 0x6b, 0x54, 0xbd, 0xfa, 0xc9, 0x6d, 0x27, 0x05, 0x71, 0x19, 0x81, + 0xeb, 0xe7, 0x16, 0x1c, 0xa3, 0xbf, 0x68, 0x4f, 0xb5, 0x16, 0x1d, 0x1f, 0xc3, 0x18, 0xc9, 0xd8, 0xe0, 0xc2, 0x10, + 0x4e, 0x6d, 0xa0, 0xd4, 0x63, 0x52, 0xc6, 0x70, 0xdc, 0xc9, 0x2c, 0xcb, 0x25, 0x7a, 0x5b, 0xa9, 0x05, 0x6c, 0xbf, + 0xe1, 0xfa, 0xb4, 0xc7, 0xe0, 0x4c, 0x01, 0x4a, 0x80, 0xa3, 0xf8, 0x9d, 0x0d, 0xae, 0x57, 0xc5, 0xe6, 0x8a, 0x97, + 0xe4, 0xfe, 0x8d, 0xe1, 0xa5, 0x83, 0x32, 0x34, 0xd9, 0x5e, 0xfd, 0x75, 0xf7, 0x89, 0x4d, 0xb2, 0x70, 0x5a, 0x6c, + 0xb0, 0x74, 0x7f, 0xed, 0xdf, 0x5c, 0x01, 0xa3, 0x40, 0x04, 0x85, 0xa8, 0x06, 0xa3, 0x64, 0x51, 0x88, 0x9b, 0x9f, + 0x8e, 0x9b, 0xbf, 0x17, 0x15, 0x83, 0x15, 0xc8, 0xfd, 0x99, 0xac, 0xa6, 0x30, 0xc5, 0xc1, 0x4d, 0x37, 0xda, 0x32, + 0xb7, 0x04, 0x21, 0xda, 0xb8, 0x13, 0x53, 0xa1, 0x08, 0x99, 0xd7, 0xf1, 0xb9, 0xe3, 0xcd, 0x7d, 0xb9, 0xd6, 0xfe, + 0x6e, 0xae, 0x75, 0xba, 0x8b, 0x6b, 0x4d, 0x36, 0x60, 0xa4, 0xbd, 0x23, 0x6d, 0xe1, 0x04, 0x71, 0xae, 0x5a, 0x13, + 0x16, 0x58, 0xdd, 0x68, 0x32, 0x26, 0x6a, 0x55, 0x5a, 0x23, 0xd5, 0x46, 0x64, 0x7f, 0x2b, 0x0f, 0x14, 0x21, 0x50, + 0x57, 0x79, 0xe3, 0x17, 0x39, 0x6f, 0x9c, 0x5e, 0x35, 0xb9, 0xf5, 0x8f, 0xa0, 0xfe, 0x15, 0xcb, 0x3a, 0xf9, 0x3a, + 0xc8, 0x2d, 0xec, 0xf2, 0x91, 0x2a, 0x36, 0x63, 0xf9, 0x43, 0x43, 0xb1, 0x44, 0x14, 0xaf, 0x8c, 0xa2, 0x41, 0x62, + 0xb1, 0x68, 0x6e, 0x32, 0x96, 0xa7, 0x03, 0xd7, 0x1d, 0x87, 0x2c, 0x93, 0xd5, 0x6d, 0x53, 0xb4, 0x19, 0x52, 0xb3, + 0x95, 0x4d, 0x22, 0x8d, 0x7b, 0x08, 0xc0, 0x82, 0x4d, 0x5f, 0x92, 0x6b, 0x4b, 0x1d, 0x08, 0x1c, 0x64, 0x8d, 0x2d, + 0xe2, 0x6e, 0xee, 0x3c, 0x05, 0x87, 0xc8, 0x45, 0xd7, 0x2e, 0xde, 0xee, 0x24, 0x09, 0x56, 0xf9, 0x11, 0x08, 0xeb, + 0x2b, 0x85, 0x83, 0xd0, 0x77, 0x34, 0x67, 0x50, 0x43, 0x00, 0xe0, 0xfd, 0x5f, 0xfe, 0xe6, 0xa4, 0x00, 0x70, 0x22, + 0x35, 0x47, 0x95, 0xf9, 0xe3, 0x21, 0xb6, 0x48, 0xfd, 0x18, 0x8b, 0x56, 0xfb, 0x24, 0x7e, 0xcf, 0x86, 0x5b, 0xfe, + 0x14, 0xd9, 0xf9, 0xbc, 0x44, 0x5f, 0x8c, 0x83, 0xef, 0xb2, 0x78, 0x1d, 0xa2, 0xcf, 0x7f, 0x2b, 0x8d, 0xbd, 0xc9, + 0x87, 0x8d, 0xd2, 0x1f, 0x67, 0x89, 0x02, 0xbb, 0xb8, 0x28, 0x54, 0x18, 0x78, 0xe8, 0x22, 0x93, 0xf5, 0xed, 0x76, + 0xa2, 0x30, 0x6a, 0xfa, 0x0f, 0x9d, 0x8e, 0xf7, 0x6c, 0x76, 0x58, 0xe2, 0x9f, 0xb6, 0xbb, 0x45, 0xee, 0xba, 0x1c, + 0xc7, 0x32, 0xfa, 0x95, 0xdb, 0x48, 0xfe, 0xf9, 0x5d, 0x27, 0xbc, 0xcf, 0xd2, 0x1a, 0x7d, 0xce, 0x10, 0xa0, 0x7e, + 0x41, 0x30, 0xad, 0x8a, 0x69, 0x2a, 0x29, 0x4d, 0xc3, 0x9a, 0xf9, 0x41, 0x60, 0x05, 0x60, 0xa9, 0xb2, 0xf9, 0xac, + 0xe9, 0x61, 0x3b, 0x6b, 0x70, 0xce, 0xfc, 0x19, 0xed, 0x14, 0x77, 0x4a, 0xba, 0x58, 0x2f, 0xc7, 0x1b, 0x95, 0x51, + 0xae, 0xf0, 0xcf, 0xab, 0x3c, 0x73, 0xb5, 0xdb, 0xd9, 0x6c, 0x56, 0xe4, 0x1a, 0x3b, 0xda, 0x21, 0x72, 0x7e, 0x1f, + 0x3a, 0x8e, 0x53, 0x86, 0x6f, 0xd3, 0x41, 0xa1, 0x83, 0x61, 0x21, 0x13, 0xbe, 0xb7, 0x7b, 0x4f, 0xfd, 0x49, 0xa3, + 0xa5, 0xa6, 0x9a, 0xce, 0x23, 0x6d, 0xb5, 0xff, 0x8a, 0xa1, 0x20, 0x6a, 0xd8, 0x75, 0xfc, 0xab, 0x7b, 0x65, 0x4b, + 0x4b, 0xe5, 0x03, 0xfc, 0x69, 0x95, 0x77, 0xec, 0xf5, 0x3d, 0xaa, 0x36, 0x6d, 0xef, 0xcc, 0xce, 0xaf, 0xdd, 0x82, + 0xce, 0xd2, 0x80, 0x34, 0x95, 0xfc, 0x94, 0x2d, 0x93, 0xfe, 0x84, 0xa1, 0x80, 0xd4, 0x56, 0x6e, 0x5b, 0xd4, 0xea, + 0xb1, 0xe6, 0xa0, 0xc7, 0xe5, 0x0a, 0x3c, 0xec, 0x68, 0x28, 0xac, 0xaa, 0x48, 0xd6, 0x44, 0x27, 0x78, 0x8b, 0x6d, + 0xaa, 0x02, 0x27, 0xdc, 0xa6, 0x5d, 0xe7, 0x2f, 0x85, 0x72, 0x1a, 0x50, 0xa7, 0x1b, 0xa1, 0x6d, 0x42, 0xc2, 0x13, + 0xfc, 0x5b, 0x0a, 0xe7, 0x9e, 0xad, 0xee, 0x8a, 0xca, 0x5d, 0x3d, 0x10, 0x37, 0xe5, 0x57, 0x19, 0x8d, 0xba, 0x0e, + 0xf5, 0x49, 0x15, 0xa0, 0x99, 0xaa, 0xdd, 0x02, 0x1a, 0x34, 0x85, 0x50, 0x44, 0x35, 0xb2, 0x31, 0x7c, 0xce, 0xc2, + 0xce, 0xcb, 0xf9, 0xfb, 0x79, 0x20, 0x4d, 0x98, 0x83, 0xf9, 0xb4, 0x87, 0xc2, 0xbd, 0xc2, 0x56, 0x45, 0x55, 0x19, + 0xdc, 0x03, 0xe2, 0x45, 0xaa, 0xad, 0xe3, 0xc0, 0xa2, 0x38, 0x3d, 0x2d, 0x63, 0x53, 0x9d, 0x77, 0x73, 0xf3, 0x6e, + 0x17, 0xe4, 0x1a, 0x55, 0x50, 0xed, 0x25, 0xda, 0x2b, 0xcb, 0xb0, 0xc5, 0x38, 0x61, 0x05, 0xc0, 0x92, 0x42, 0x43, + 0xa5, 0x21, 0xad, 0x84, 0xfb, 0x68, 0xd2, 0x32, 0x57, 0x45, 0xd6, 0x62, 0x9e, 0xd8, 0x5c, 0x7d, 0x11, 0x6a, 0x5b, + 0x48, 0x06, 0x01, 0x76, 0x1c, 0x3b, 0xe1, 0xb7, 0x05, 0x3b, 0x46, 0x45, 0x57, 0x2e, 0xee, 0x20, 0x3c, 0xa5, 0x16, + 0xd2, 0xc9, 0x09, 0x9d, 0x52, 0x94, 0x25, 0xfc, 0xad, 0x96, 0x79, 0x7f, 0x51, 0xe0, 0xc6, 0x73, 0x73, 0x96, 0xb6, + 0xb1, 0x57, 0xe9, 0xa5, 0x1f, 0xee, 0x5f, 0xd6, 0xbb, 0xdb, 0xbb, 0x2c, 0x10, 0x87, 0x7b, 0x17, 0x06, 0xea, 0x92, + 0xb4, 0x94, 0xd2, 0xe1, 0xdf, 0x14, 0xe1, 0x81, 0xea, 0x16, 0x41, 0xc7, 0x5a, 0xf4, 0xa2, 0xbf, 0x58, 0x0f, 0x47, + 0x27, 0x67, 0x77, 0xcb, 0x40, 0xbb, 0x61, 0x31, 0xc4, 0x2c, 0x1b, 0xea, 0xae, 0xed, 0xe8, 0x1a, 0x1a, 0xf9, 0xfb, + 0xe1, 0x7c, 0xa8, 0xff, 0x74, 0xf1, 0xca, 0xea, 0xe9, 0x67, 0xa0, 0x8e, 0x71, 0x33, 0x47, 0x12, 0xf7, 0xdc, 0xbb, + 0x67, 0xf1, 0x75, 0x5b, 0xd7, 0x30, 0x34, 0x19, 0x11, 0xb7, 0x98, 0xa6, 0xb5, 0xf5, 0x3d, 0x22, 0xe0, 0x68, 0x22, + 0x88, 0xa5, 0x0e, 0x88, 0xd5, 0x6d, 0xf7, 0x34, 0xb7, 0x7d, 0x68, 0x1f, 0xf5, 0xf4, 0xd3, 0xaf, 0x34, 0xed, 0x64, + 0xca, 0x66, 0xc9, 0x29, 0xb2, 0x63, 0x4e, 0x90, 0x1e, 0xa4, 0xdf, 0x9a, 0x66, 0x4f, 0x82, 0xc4, 0x72, 0xb5, 0x0d, + 0xff, 0xd4, 0x34, 0x40, 0x46, 0x7d, 0xed, 0xe1, 0xac, 0x3d, 0x3b, 0x9c, 0x3d, 0x1b, 0xf0, 0xe4, 0xec, 0xab, 0x42, + 0x71, 0x93, 0xfe, 0x6d, 0x2b, 0xd5, 0x92, 0x34, 0x8e, 0x3e, 0x30, 0x4e, 0x4b, 0x6a, 0x92, 0x51, 0x54, 0xae, 0xda, + 0xae, 0xf6, 0xe4, 0xf6, 0xc6, 0x93, 0x59, 0x3b, 0x2f, 0x8e, 0x63, 0x3c, 0x90, 0x83, 0x3c, 0x39, 0x10, 0x43, 0x3f, + 0x51, 0xc1, 0xe4, 0x5a, 0x75, 0x80, 0x72, 0x75, 0x3e, 0xc7, 0xb9, 0x98, 0xdf, 0x09, 0x38, 0x98, 0xcd, 0x0d, 0x10, + 0x12, 0xac, 0x36, 0xd4, 0xbf, 0x77, 0xdb, 0x3d, 0xd3, 0x75, 0x8f, 0xec, 0xa3, 0xde, 0xc4, 0x31, 0x0f, 0xed, 0x43, + 0xab, 0x63, 0x1f, 0x99, 0x3d, 0xab, 0x67, 0xf6, 0xfe, 0xda, 0x9b, 0x58, 0x87, 0xf6, 0xa1, 0xe9, 0x58, 0x3d, 0x48, + 0xb4, 0x7a, 0x56, 0xef, 0xc6, 0x3a, 0xec, 0x4d, 0x1c, 0x4c, 0x6d, 0xdb, 0xdd, 0xae, 0xe5, 0x3a, 0x76, 0xb7, 0x6b, + 0x76, 0xed, 0xa3, 0x23, 0xcb, 0xed, 0xd8, 0x47, 0x47, 0xe7, 0xdd, 0x9e, 0xdd, 0x81, 0xbc, 0x4e, 0x67, 0xd2, 0xb1, + 0x5d, 0xd7, 0x82, 0xbf, 0xcc, 0x9e, 0xdd, 0xa6, 0x1f, 0xae, 0x6b, 0x77, 0x5c, 0xd3, 0x09, 0xba, 0x6d, 0xfb, 0xe8, + 0x99, 0x89, 0x7f, 0x63, 0x31, 0x13, 0xff, 0x82, 0x66, 0xcc, 0x67, 0x76, 0xfb, 0x88, 0x7e, 0x61, 0x83, 0x37, 0x87, + 0xbd, 0x9f, 0xf5, 0x83, 0xc6, 0x39, 0xb8, 0x34, 0x87, 0x5e, 0xd7, 0xee, 0x74, 0xcc, 0x43, 0xd7, 0xee, 0x75, 0x16, + 0xd6, 0x61, 0xdb, 0x3e, 0x3a, 0x9e, 0x58, 0xae, 0x7d, 0x7c, 0x6c, 0x3a, 0x56, 0xc7, 0x6e, 0x9b, 0xae, 0x7d, 0xd8, + 0xc1, 0x1f, 0x1d, 0xbb, 0x7d, 0x73, 0xfc, 0xcc, 0x3e, 0xea, 0x2e, 0x8e, 0xec, 0xc3, 0xf7, 0x87, 0x3d, 0xbb, 0xdd, + 0x59, 0x74, 0x8e, 0xec, 0xf6, 0xf1, 0xcd, 0x91, 0x7d, 0xb8, 0xb0, 0xda, 0x47, 0x5b, 0x6b, 0xba, 0x6d, 0x1b, 0x60, + 0x84, 0xd9, 0x90, 0x61, 0xf2, 0x0c, 0xf8, 0xb3, 0xc0, 0xba, 0x7f, 0x62, 0x33, 0x49, 0xb5, 0xea, 0x33, 0xbb, 0x77, + 0x3c, 0xa1, 0xe2, 0x90, 0x60, 0x89, 0x12, 0x50, 0xe5, 0xc6, 0xa2, 0x6e, 0xb1, 0x39, 0x4b, 0x34, 0x24, 0xfe, 0xf0, + 0xce, 0x6e, 0x2c, 0xe8, 0x98, 0xfa, 0xfd, 0x8f, 0xb6, 0x23, 0x97, 0x1c, 0x42, 0xf2, 0x7e, 0xc5, 0xff, 0xa1, 0x68, + 0x56, 0x23, 0xf3, 0xbc, 0x49, 0x28, 0xf9, 0x76, 0xb7, 0x50, 0xf2, 0xd5, 0x7a, 0x1f, 0xa1, 0xe4, 0xdb, 0x2f, 0x2e, + 0x94, 0x3c, 0x2f, 0xdb, 0xc4, 0xbc, 0x2d, 0x07, 0xdd, 0xf8, 0x79, 0x53, 0x66, 0x39, 0xf8, 0x5e, 0xeb, 0xf2, 0x62, + 0x7d, 0x05, 0xee, 0xdf, 0xde, 0x46, 0xc3, 0x57, 0xeb, 0x82, 0xc2, 0x67, 0x04, 0x38, 0xf6, 0x6d, 0x44, 0x38, 0xf6, + 0xd7, 0xf5, 0x10, 0xb4, 0xcc, 0x38, 0x99, 0xe3, 0x4f, 0xad, 0x85, 0x17, 0xcc, 0x24, 0x89, 0x04, 0x29, 0x03, 0x4c, + 0x06, 0xbb, 0x2b, 0xb8, 0x9e, 0xe1, 0x25, 0xb3, 0x5e, 0x86, 0x09, 0x68, 0x04, 0x83, 0x26, 0xc7, 0x2c, 0xce, 0x4a, + 0x95, 0x6d, 0xe1, 0x30, 0xef, 0x9a, 0x5b, 0x40, 0x35, 0xe6, 0xa3, 0x02, 0x70, 0x7d, 0xeb, 0x6e, 0xb5, 0x5d, 0x0d, + 0x34, 0xeb, 0x84, 0x82, 0x34, 0x50, 0xfb, 0x75, 0xf9, 0x45, 0x35, 0xdc, 0x92, 0xe2, 0x75, 0xf3, 0x48, 0x61, 0x24, + 0xe5, 0xfa, 0x6e, 0x51, 0x8d, 0x77, 0xd7, 0x34, 0x6b, 0xba, 0x2f, 0x54, 0xdf, 0xa2, 0x43, 0x2c, 0x1b, 0x2e, 0x83, + 0xaa, 0x14, 0x32, 0xb2, 0x16, 0x20, 0xf9, 0x03, 0x35, 0x57, 0x34, 0xce, 0x29, 0x55, 0x47, 0x43, 0x7a, 0xc7, 0x51, + 0xf2, 0x0a, 0x6d, 0xaa, 0xca, 0xc9, 0x4f, 0x36, 0xf8, 0xae, 0xf0, 0x7f, 0x05, 0x4a, 0x94, 0x53, 0x3c, 0xe3, 0x48, + 0x85, 0xf3, 0x46, 0x69, 0x97, 0xb8, 0x11, 0xd9, 0xc2, 0xdd, 0x54, 0x69, 0xd1, 0x46, 0xb3, 0x04, 0x97, 0x2d, 0x05, + 0x15, 0x84, 0xdd, 0x93, 0x11, 0x40, 0x46, 0x86, 0x1a, 0x68, 0xe7, 0xb0, 0xad, 0x31, 0x51, 0xee, 0x21, 0x6c, 0x62, + 0x93, 0x7f, 0xa8, 0x8e, 0x4b, 0x36, 0xb3, 0x20, 0xf2, 0xd2, 0x3e, 0x92, 0x69, 0x0a, 0xc9, 0xdb, 0x46, 0x8b, 0x85, + 0xc1, 0x16, 0x65, 0x3a, 0xb5, 0x61, 0xde, 0x08, 0x5a, 0x3e, 0x6c, 0xd3, 0xbf, 0x93, 0x86, 0x62, 0x9b, 0x82, 0x3a, + 0x8a, 0xdb, 0x3d, 0x36, 0xdd, 0x23, 0xd3, 0x3e, 0xee, 0x1a, 0x99, 0x38, 0x70, 0x6a, 0x93, 0x05, 0x80, 0x80, 0x01, + 0x84, 0x1c, 0xa6, 0x1f, 0xfa, 0xa9, 0xef, 0x05, 0x19, 0xd0, 0xc3, 0xc5, 0x47, 0xca, 0x3f, 0xd7, 0x49, 0x0a, 0x73, + 0x14, 0x44, 0x2f, 0x1a, 0x7f, 0x58, 0x63, 0x96, 0xde, 0x32, 0x16, 0x36, 0x28, 0xc6, 0x94, 0x6d, 0x49, 0xfe, 0x38, + 0xcd, 0xfa, 0x8c, 0xb4, 0xd6, 0xc6, 0x69, 0xc8, 0xf7, 0x87, 0x30, 0x7c, 0xc8, 0x46, 0xe6, 0x0f, 0x4d, 0x08, 0xf7, + 0x9f, 0xbb, 0x11, 0x6e, 0xca, 0xf6, 0x41, 0xb8, 0xff, 0xfc, 0xe2, 0x08, 0xf7, 0x07, 0x15, 0xe1, 0x16, 0xec, 0xfe, + 0x72, 0x09, 0xd3, 0x3b, 0xfc, 0x6e, 0x81, 0xb7, 0xfa, 0xa7, 0xfa, 0x01, 0x11, 0xf0, 0xba, 0x12, 0x45, 0xfc, 0x7d, + 0x21, 0x2c, 0x1a, 0x32, 0x40, 0xd1, 0x4b, 0x36, 0x85, 0x60, 0x82, 0x08, 0xdb, 0x8e, 0x0c, 0xc3, 0xc4, 0x6e, 0xb5, + 0xd7, 0x61, 0x1a, 0xd8, 0x6f, 0xf9, 0x3b, 0x12, 0x04, 0xba, 0xaf, 0xa2, 0x78, 0xe9, 0xa1, 0x87, 0x50, 0x1d, 0xc3, + 0xa9, 0xc2, 0x87, 0x03, 0xb6, 0xa4, 0x93, 0x28, 0x9c, 0x4a, 0xa9, 0x24, 0x1b, 0x5e, 0x12, 0xc5, 0xad, 0xdf, 0x33, + 0x2f, 0xd6, 0x4d, 0xca, 0x86, 0xc5, 0x7d, 0xd2, 0x71, 0x9e, 0xb4, 0x0f, 0x9f, 0x1c, 0x39, 0xf0, 0xbf, 0xcb, 0x3a, + 0x99, 0xc9, 0x0b, 0x2e, 0xa3, 0x10, 0x22, 0x3a, 0x89, 0x92, 0x4d, 0xc5, 0x6e, 0x19, 0xfb, 0x90, 0x97, 0x3a, 0xae, + 0x2f, 0x34, 0xf5, 0xee, 0xf3, 0x32, 0xb5, 0x25, 0x16, 0xd1, 0x5a, 0x19, 0x56, 0xcd, 0x68, 0xfc, 0x70, 0x0d, 0x7c, + 0x76, 0xa5, 0x84, 0x9a, 0xcd, 0xa7, 0x9b, 0xcf, 0x8b, 0x75, 0xb2, 0xab, 0x3c, 0x6c, 0x9c, 0x08, 0x5f, 0xb5, 0x13, + 0x82, 0x5c, 0x44, 0xe9, 0x60, 0xd0, 0x09, 0x0c, 0x9c, 0xa6, 0x41, 0xd0, 0x56, 0xb1, 0x40, 0x1e, 0x2d, 0x50, 0x1a, + 0xaf, 0xc3, 0x49, 0x0b, 0x7f, 0x7a, 0xe3, 0xa4, 0xe5, 0x1f, 0x80, 0xfb, 0x68, 0xec, 0xd8, 0xc0, 0x55, 0xf3, 0x4e, + 0x9d, 0x3c, 0xc6, 0x4e, 0x22, 0x56, 0xc5, 0x7b, 0x92, 0x9a, 0x31, 0x45, 0xe6, 0xc6, 0xa5, 0xb5, 0x86, 0xde, 0x13, + 0x59, 0xf1, 0x49, 0x6a, 0x42, 0x74, 0x6c, 0x58, 0xee, 0xc7, 0x8f, 0xa9, 0x14, 0xc4, 0xab, 0xa5, 0x69, 0x9d, 0x4d, + 0x72, 0xff, 0x93, 0x9a, 0x37, 0x8f, 0xc8, 0x05, 0x65, 0x7f, 0x62, 0x46, 0x4f, 0x9f, 0x9e, 0x0e, 0x5d, 0x83, 0x47, + 0x5b, 0x2e, 0x84, 0x06, 0x3c, 0xdf, 0x4f, 0xd1, 0xc8, 0xa8, 0x35, 0x81, 0x5d, 0xc1, 0x9b, 0xc9, 0x11, 0xe6, 0x08, + 0x1c, 0x7b, 0x41, 0xa8, 0x1e, 0x52, 0x28, 0xf0, 0x84, 0xc2, 0x8f, 0x28, 0x23, 0x5f, 0x5d, 0x1d, 0xdb, 0xb1, 0x1d, + 0x5d, 0x56, 0x9c, 0xf9, 0xf3, 0xe1, 0x26, 0x4a, 0x3d, 0x08, 0x7a, 0x16, 0x44, 0x73, 0xb0, 0xa3, 0x4b, 0xfd, 0x34, + 0x80, 0x08, 0x5a, 0x60, 0x50, 0xb7, 0xa4, 0x77, 0x79, 0xc6, 0xad, 0x1b, 0xbc, 0xf8, 0x03, 0x46, 0x51, 0x15, 0x26, + 0xb4, 0xe8, 0x12, 0xed, 0x7b, 0xb8, 0x0c, 0x5b, 0x7a, 0x0b, 0x78, 0x03, 0x2c, 0x4e, 0x2c, 0xd5, 0x5a, 0xa8, 0xaf, + 0x41, 0x1d, 0x43, 0xe7, 0x93, 0x98, 0xc5, 0xde, 0x12, 0x82, 0x4d, 0x6c, 0x32, 0x93, 0x63, 0x5a, 0x9d, 0xa3, 0x5a, + 0xcd, 0x7d, 0x76, 0x64, 0x6a, 0x6d, 0xd7, 0xd4, 0x1c, 0x40, 0xb7, 0x7a, 0x66, 0x6e, 0xb2, 0xab, 0xc1, 0x2e, 0x85, + 0x07, 0xc2, 0x2f, 0x0f, 0x69, 0x1e, 0xa4, 0xea, 0xc0, 0x45, 0x49, 0x29, 0x79, 0xb8, 0x6d, 0x29, 0x61, 0x20, 0x7c, + 0x12, 0x7a, 0x5e, 0xb0, 0xbb, 0xd4, 0xc0, 0x08, 0x53, 0xbc, 0x88, 0x6f, 0x6c, 0xd0, 0xd0, 0xd7, 0x0f, 0x35, 0xff, + 0xe3, 0xc7, 0x96, 0x0f, 0xc6, 0x4c, 0x43, 0x05, 0x3e, 0xf0, 0x6d, 0x14, 0x00, 0xe6, 0xe7, 0x62, 0x7a, 0x04, 0x16, + 0x58, 0x1a, 0xc2, 0xbf, 0x79, 0xb2, 0xf8, 0xc1, 0xd5, 0x24, 0xec, 0xc0, 0x0b, 0xe7, 0x80, 0xd2, 0xbc, 0x70, 0x5e, + 0x51, 0xc7, 0x22, 0x5b, 0xe5, 0x52, 0x6a, 0xde, 0x54, 0xae, 0x2a, 0x95, 0x7c, 0x77, 0x7f, 0x41, 0x11, 0xf4, 0x5a, + 0x3a, 0xdc, 0x72, 0x68, 0x58, 0x9b, 0x4b, 0x72, 0x9f, 0x0e, 0xbf, 0x3e, 0x59, 0xb2, 0xd4, 0x23, 0x31, 0x10, 0x3c, + 0x7e, 0x81, 0x1c, 0xd0, 0x26, 0x22, 0xfa, 0x35, 0x5e, 0x0d, 0xc3, 0x29, 0xbb, 0xf1, 0x27, 0xfc, 0x5d, 0x6a, 0x6a, + 0xfc, 0x9e, 0xb2, 0x50, 0xe3, 0x73, 0xe8, 0x9a, 0x64, 0x70, 0x30, 0xf1, 0xd0, 0x0f, 0xee, 0x30, 0x8c, 0xf4, 0xd3, + 0xaf, 0xa5, 0x6d, 0x66, 0xd3, 0x22, 0x40, 0x18, 0xdb, 0xcb, 0x98, 0x05, 0xff, 0x1a, 0x7e, 0x0d, 0x17, 0xf7, 0xd7, + 0x57, 0xba, 0x31, 0x48, 0xed, 0x45, 0xcc, 0x66, 0xc3, 0xaf, 0x6b, 0xc2, 0xb9, 0xe2, 0xf3, 0x9e, 0xc6, 0xa2, 0x77, + 0xda, 0xb9, 0xf7, 0xb2, 0xce, 0x5e, 0x8f, 0xfa, 0x53, 0xfe, 0x5a, 0x87, 0x17, 0xe0, 0xa6, 0xf0, 0xc6, 0x76, 0x07, + 0xf8, 0x7e, 0x1e, 0x07, 0xde, 0xe4, 0xc3, 0x80, 0x72, 0x0a, 0x1f, 0x16, 0xdc, 0xd6, 0x13, 0x6f, 0xd5, 0xc7, 0xeb, + 0x55, 0x4d, 0x04, 0xd3, 0x6c, 0x4a, 0x95, 0x94, 0x5d, 0xed, 0x5e, 0xc6, 0xad, 0xbc, 0xc1, 0x9e, 0xb1, 0xab, 0xdb, + 0x85, 0x9f, 0x32, 0xd1, 0x15, 0x7e, 0x64, 0x99, 0x78, 0xa8, 0xd3, 0x13, 0x15, 0x1f, 0xd6, 0x76, 0x47, 0x73, 0x7b, + 0x7f, 0xed, 0xde, 0xb8, 0xce, 0xa2, 0xed, 0xda, 0xbd, 0xf7, 0x6e, 0x6f, 0xd1, 0xb1, 0x8f, 0x03, 0xab, 0x63, 0x1f, + 0xc3, 0x9f, 0xf7, 0xc7, 0x76, 0x6f, 0x61, 0xb5, 0xed, 0xc3, 0xf7, 0x6e, 0x3b, 0xb0, 0x7a, 0xf6, 0x31, 0xfc, 0x39, + 0xa7, 0x5a, 0xf0, 0x00, 0xa2, 0xf7, 0xce, 0xd7, 0x05, 0x2c, 0xa0, 0xfc, 0x96, 0x32, 0x59, 0xb3, 0x70, 0xbd, 0xd5, + 0xc8, 0x75, 0x01, 0x65, 0xe8, 0xa6, 0xf0, 0x52, 0x1b, 0x0e, 0x5a, 0xe1, 0x90, 0x47, 0x46, 0x11, 0xea, 0x6d, 0xc2, + 0x06, 0x5d, 0xc4, 0x08, 0xa9, 0x3d, 0x46, 0xbc, 0x4e, 0x7d, 0x44, 0x08, 0x11, 0x72, 0x8f, 0x04, 0xc1, 0x3f, 0xad, + 0xd0, 0xcb, 0x9a, 0x88, 0x61, 0xa1, 0x60, 0xa5, 0x3c, 0xec, 0x6b, 0xb6, 0x7b, 0xe0, 0x68, 0x85, 0xcf, 0x64, 0xd8, + 0xb1, 0x2f, 0xda, 0x36, 0x17, 0x0e, 0xcb, 0xd6, 0x7f, 0x6f, 0x3b, 0x18, 0x6d, 0x9b, 0xda, 0x11, 0xee, 0xa6, 0xa7, + 0x7e, 0x2c, 0x87, 0xa7, 0xa0, 0x68, 0xb7, 0x3e, 0x94, 0x86, 0x01, 0xf1, 0x99, 0x5e, 0x03, 0x95, 0x7c, 0xe3, 0x05, + 0x8a, 0x22, 0x9b, 0x52, 0xf3, 0x81, 0xc4, 0xfc, 0x8f, 0x1f, 0xe7, 0x83, 0xb3, 0x4a, 0xe3, 0x3e, 0x71, 0xbb, 0x70, + 0xed, 0x76, 0x59, 0x67, 0xab, 0x4e, 0xe5, 0x6e, 0x7f, 0xe5, 0xb9, 0x3f, 0x63, 0xa1, 0x37, 0x25, 0x34, 0x36, 0x1a, + 0x15, 0x3b, 0x2b, 0xfa, 0x1a, 0xe0, 0xe9, 0xbd, 0xf4, 0xd4, 0xd1, 0x8d, 0x41, 0x28, 0xd4, 0x0f, 0xc2, 0x2d, 0x3e, + 0xda, 0xf9, 0x5b, 0x4c, 0x07, 0xd0, 0x6c, 0x99, 0xc7, 0x0e, 0x03, 0xf1, 0xff, 0xf4, 0x24, 0xd0, 0x58, 0x13, 0xf4, + 0x25, 0x4a, 0xa7, 0xb5, 0x60, 0xbc, 0x27, 0xef, 0x55, 0xba, 0x50, 0x59, 0x72, 0xa6, 0x43, 0x12, 0x04, 0xee, 0xc3, + 0x58, 0x9d, 0x52, 0x59, 0x54, 0xde, 0x16, 0x79, 0x82, 0xe9, 0x43, 0x90, 0x82, 0x96, 0x30, 0x1c, 0x35, 0x1e, 0x3f, + 0x6e, 0xbc, 0x84, 0x48, 0x39, 0x47, 0x0d, 0x59, 0xac, 0xab, 0xf8, 0x4d, 0x57, 0x51, 0x8c, 0x6c, 0x17, 0xb1, 0x86, + 0xd0, 0x71, 0xa5, 0xbd, 0x87, 0x3f, 0xc7, 0xcc, 0x4b, 0x6d, 0x2e, 0x2c, 0x6d, 0x29, 0x97, 0xbb, 0xe9, 0xb2, 0x0e, + 0x68, 0xb7, 0x72, 0x67, 0x8c, 0xdc, 0xd9, 0xe9, 0xa3, 0xcd, 0xfb, 0x35, 0xf7, 0xea, 0x00, 0x6d, 0x7c, 0x74, 0x72, + 0xff, 0x59, 0x6f, 0x52, 0x8f, 0x9c, 0x2c, 0xa9, 0x57, 0x6e, 0x94, 0x7a, 0x22, 0x40, 0x16, 0xd0, 0xe5, 0x83, 0x5a, + 0xf5, 0x0b, 0xc5, 0xf3, 0xc3, 0xe9, 0x9b, 0x8b, 0x6f, 0x35, 0xbe, 0xff, 0x49, 0x5b, 0x00, 0x1f, 0x32, 0x14, 0x96, + 0x65, 0x48, 0x61, 0x59, 0x34, 0x1e, 0x1f, 0x09, 0x82, 0x9b, 0x64, 0x07, 0x04, 0x41, 0x64, 0x40, 0x93, 0x0e, 0xc5, + 0x72, 0x1d, 0xa4, 0xfe, 0xca, 0x8b, 0xd3, 0x03, 0xa8, 0x6a, 0x01, 0x92, 0xd3, 0x9b, 0xfc, 0x41, 0x90, 0x1a, 0x86, + 0xf0, 0x01, 0x9a, 0x86, 0x42, 0x0f, 0x63, 0xe6, 0x07, 0x52, 0x0d, 0x43, 0x74, 0xe0, 0x4d, 0x26, 0x6c, 0x95, 0x0e, + 0x75, 0x6f, 0x05, 0xe1, 0x79, 0xd0, 0xe1, 0xfe, 0x41, 0x34, 0x49, 0x59, 0x6a, 0x25, 0x69, 0xcc, 0xbc, 0xa5, 0x2e, + 0x7d, 0x4d, 0x57, 0xdb, 0x4b, 0xd6, 0xe3, 0xa5, 0x9f, 0x4a, 0x67, 0xad, 0x34, 0x41, 0x50, 0x88, 0x80, 0x21, 0x82, + 0x73, 0x18, 0x02, 0xe1, 0x79, 0x34, 0x2f, 0xed, 0xa8, 0x9c, 0x72, 0x39, 0x43, 0x57, 0xe0, 0x3c, 0x24, 0xcb, 0x14, + 0xed, 0x1b, 0xaf, 0xb9, 0x0f, 0x0b, 0xe9, 0x53, 0x56, 0x3f, 0x3d, 0xe1, 0xcf, 0x5b, 0x0d, 0xdd, 0xae, 0xe8, 0x5d, + 0x07, 0x9c, 0x9d, 0x37, 0x79, 0xb7, 0x38, 0xe0, 0x85, 0xe1, 0x6a, 0xa2, 0x96, 0x31, 0x10, 0x05, 0x8d, 0xe5, 0x02, + 0x08, 0xa1, 0x82, 0xc2, 0xcc, 0xc2, 0x3d, 0x95, 0xe6, 0x94, 0x38, 0x2a, 0xa4, 0x95, 0x3e, 0x7e, 0x7c, 0x3e, 0xfa, + 0xed, 0xdf, 0x10, 0x2d, 0x63, 0xe1, 0x0a, 0x9f, 0x12, 0x97, 0x6a, 0x29, 0x4e, 0x7d, 0x9a, 0x23, 0x54, 0x96, 0x62, + 0x53, 0xe1, 0x98, 0x47, 0x6c, 0xad, 0x6c, 0x74, 0x25, 0xbc, 0xfd, 0x41, 0x44, 0x1c, 0x43, 0x78, 0xbe, 0x18, 0xc1, + 0xf2, 0x8e, 0x84, 0xc3, 0x15, 0xed, 0x97, 0xbb, 0xef, 0x8e, 0xb5, 0xdc, 0x05, 0x4f, 0x9d, 0x46, 0x0f, 0xed, 0xa1, + 0xd3, 0x13, 0x4f, 0x43, 0xa2, 0x05, 0xc9, 0x8f, 0xa4, 0x7f, 0x00, 0xd3, 0x5c, 0x44, 0x4b, 0x66, 0xfb, 0xd1, 0xc1, + 0x2d, 0x1b, 0x5b, 0xde, 0xca, 0x27, 0xbd, 0x1c, 0xe4, 0xbb, 0x69, 0x44, 0xf9, 0x49, 0x75, 0x17, 0xa2, 0xaf, 0xb3, + 0x1c, 0x94, 0x51, 0xd1, 0xbd, 0x63, 0xb7, 0x9d, 0xcb, 0x01, 0xc1, 0x7f, 0x81, 0x02, 0xc7, 0xe8, 0xf4, 0xe4, 0xc0, + 0x3b, 0x2d, 0xfa, 0x97, 0xb5, 0x45, 0x84, 0x93, 0xe2, 0x25, 0x70, 0x46, 0x6e, 0x62, 0x85, 0x47, 0xd8, 0xfc, 0xc3, + 0x8a, 0x66, 0x33, 0xd5, 0x27, 0xac, 0x5d, 0x1c, 0x9e, 0x04, 0x5a, 0xbe, 0xa5, 0xa3, 0x15, 0xf5, 0x54, 0xed, 0x42, + 0xfe, 0x84, 0xa8, 0xf0, 0xdc, 0x7d, 0x30, 0x1c, 0xf7, 0x8a, 0x6f, 0x59, 0x09, 0xb1, 0x87, 0x54, 0x88, 0xe3, 0x91, + 0x72, 0x24, 0x83, 0x06, 0xca, 0xe5, 0xc1, 0x70, 0x48, 0x68, 0xae, 0x8c, 0xed, 0x00, 0x88, 0x35, 0xd1, 0x5e, 0x60, + 0xb2, 0x29, 0x54, 0xb4, 0xc8, 0x5c, 0x16, 0x2b, 0x95, 0xa7, 0x53, 0x1d, 0xe3, 0x81, 0x27, 0xb6, 0x5f, 0x61, 0x83, + 0xc2, 0xc6, 0xe3, 0xeb, 0x0e, 0xf8, 0x5d, 0xb4, 0x53, 0x42, 0xf3, 0xda, 0x37, 0x84, 0xd1, 0xad, 0xc0, 0xbb, 0x8f, + 0x14, 0x35, 0x26, 0xee, 0xd1, 0xe4, 0x1c, 0x53, 0x2f, 0x84, 0x25, 0x71, 0xe5, 0xa0, 0xc9, 0x88, 0x19, 0xd5, 0xc3, + 0xa6, 0x86, 0xb8, 0xd8, 0x75, 0xd6, 0xd4, 0xb2, 0xc5, 0xc9, 0x20, 0xf2, 0xcc, 0xf2, 0x73, 0x58, 0xc8, 0x44, 0xb4, + 0x90, 0x9d, 0x1c, 0xc0, 0xfc, 0xc0, 0x0b, 0x4b, 0x81, 0x70, 0xf2, 0x0d, 0x70, 0xf5, 0xe2, 0x25, 0xa4, 0x8a, 0xf5, + 0x7a, 0x2a, 0x68, 0x3e, 0x7c, 0x58, 0x4a, 0xe7, 0xd5, 0x85, 0x22, 0x55, 0x5a, 0xc6, 0xa9, 0x27, 0x02, 0x77, 0x47, + 0x98, 0xf9, 0x75, 0x8d, 0xe1, 0x65, 0xb2, 0x41, 0xca, 0x84, 0x93, 0x83, 0xf3, 0xb4, 0xc1, 0x0f, 0x42, 0x53, 0x11, + 0xa2, 0x67, 0xb7, 0x14, 0xc8, 0xf7, 0xf1, 0xb6, 0x52, 0x39, 0xe5, 0x24, 0x8b, 0xad, 0xbc, 0x96, 0xfe, 0x10, 0x77, + 0x7c, 0xa5, 0x34, 0xa6, 0x42, 0xb9, 0xf3, 0x74, 0x08, 0x45, 0x05, 0x2f, 0xde, 0x5b, 0xad, 0xa8, 0xb0, 0x31, 0x38, + 0x39, 0xa0, 0x67, 0xe9, 0x29, 0xed, 0xb0, 0xd3, 0x13, 0x50, 0xe5, 0xa6, 0x45, 0xf7, 0x56, 0x2b, 0xbe, 0xa4, 0xf4, + 0x8b, 0x72, 0x0e, 0x16, 0xe9, 0x32, 0x38, 0xfd, 0x7f, 0x8a, 0xa5, 0x7c, 0x2e, 0xc4, 0x61, 0x03, 0x00}; } // namespace web_server } // namespace esphome From 1f3754684adccccc54a4795d8a685d13ba59e352 Mon Sep 17 00:00:00 2001 From: dentra Date: Wed, 24 Jul 2024 06:50:59 +0300 Subject: [PATCH 1819/2101] [http_request] Allow configure buffer size on ESP-IDF (#7125) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/http_request/__init__.py | 11 +++++++++++ esphome/components/http_request/http_request_idf.cpp | 9 +++++++++ esphome/components/http_request/http_request_idf.h | 10 ++++++++++ 3 files changed, 30 insertions(+) diff --git a/esphome/components/http_request/__init__.py b/esphome/components/http_request/__init__.py index 161486fbb2..3ca97b9611 100644 --- a/esphome/components/http_request/__init__.py +++ b/esphome/components/http_request/__init__.py @@ -40,6 +40,8 @@ CONF_VERIFY_SSL = "verify_ssl" CONF_FOLLOW_REDIRECTS = "follow_redirects" CONF_REDIRECT_LIMIT = "redirect_limit" CONF_WATCHDOG_TIMEOUT = "watchdog_timeout" +CONF_BUFFER_SIZE_RX = "buffer_size_rx" +CONF_BUFFER_SIZE_TX = "buffer_size_tx" CONF_MAX_RESPONSE_BUFFER_SIZE = "max_response_buffer_size" CONF_ON_RESPONSE = "on_response" @@ -110,6 +112,12 @@ CONFIG_SCHEMA = cv.All( cv.positive_not_null_time_period, cv.positive_time_period_milliseconds, ), + cv.SplitDefault(CONF_BUFFER_SIZE_RX, esp32_idf=512): cv.All( + cv.uint16_t, cv.only_with_esp_idf + ), + cv.SplitDefault(CONF_BUFFER_SIZE_TX, esp32_idf=512): cv.All( + cv.uint16_t, cv.only_with_esp_idf + ), } ).extend(cv.COMPONENT_SCHEMA), cv.require_framework_version( @@ -137,6 +145,9 @@ async def to_code(config): if CORE.is_esp32: if CORE.using_esp_idf: + cg.add(var.set_buffer_size_rx(config[CONF_BUFFER_SIZE_RX])) + cg.add(var.set_buffer_size_tx(config[CONF_BUFFER_SIZE_TX])) + esp32.add_idf_sdkconfig_option( "CONFIG_MBEDTLS_CERTIFICATE_BUNDLE", config.get(CONF_VERIFY_SSL), diff --git a/esphome/components/http_request/http_request_idf.cpp b/esphome/components/http_request/http_request_idf.cpp index 1f03b5f3bf..4fe5585723 100644 --- a/esphome/components/http_request/http_request_idf.cpp +++ b/esphome/components/http_request/http_request_idf.cpp @@ -18,6 +18,12 @@ namespace http_request { static const char *const TAG = "http_request.idf"; +void HttpRequestIDF::dump_config() { + HttpRequestComponent::dump_config(); + ESP_LOGCONFIG(TAG, " Buffer Size RX: %u", this->buffer_size_rx_); + ESP_LOGCONFIG(TAG, " Buffer Size TX: %u", this->buffer_size_tx_); +} + std::shared_ptr HttpRequestIDF::start(std::string url, std::string method, std::string body, std::list
headers) { if (!network::is_connected()) { @@ -63,6 +69,9 @@ std::shared_ptr HttpRequestIDF::start(std::string url, std::strin config.user_agent = this->useragent_; } + config.buffer_size = this->buffer_size_rx_; + config.buffer_size_tx = this->buffer_size_tx_; + const uint32_t start = millis(); watchdog::WatchdogManager wdm(this->get_watchdog_timeout()); diff --git a/esphome/components/http_request/http_request_idf.h b/esphome/components/http_request/http_request_idf.h index 79f850a636..431794924b 100644 --- a/esphome/components/http_request/http_request_idf.h +++ b/esphome/components/http_request/http_request_idf.h @@ -24,8 +24,18 @@ class HttpContainerIDF : public HttpContainer { class HttpRequestIDF : public HttpRequestComponent { public: + void dump_config() override; + std::shared_ptr start(std::string url, std::string method, std::string body, std::list
headers) override; + + 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; } + + protected: + // if zero ESP-IDF will use DEFAULT_HTTP_BUF_SIZE + uint16_t buffer_size_rx_{}; + uint16_t buffer_size_tx_{}; }; } // namespace http_request From 75635956cd707237f44aab63c652555d635e3428 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Thu, 25 Jul 2024 05:30:39 +1000 Subject: [PATCH 1820/2101] Give more info on import errors. (#7128) --- esphome/loader.py | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/esphome/loader.py b/esphome/loader.py index e0457eb425..9399c4cb31 100644 --- a/esphome/loader.py +++ b/esphome/loader.py @@ -1,17 +1,17 @@ -import logging -from typing import Callable, Optional, Any, ContextManager -from types import ModuleType -import importlib -import importlib.util -import importlib.resources -import importlib.abc -import sys -from pathlib import Path from dataclasses import dataclass +import importlib +import importlib.abc +import importlib.resources +import importlib.util +import logging +from pathlib import Path +import sys +from types import ModuleType +from typing import Any, Callable, ContextManager, Optional from esphome.const import SOURCE_FILE_EXTENSIONS -import esphome.core.config from esphome.core import CORE +import esphome.core.config from esphome.types import ConfigType _LOGGER = logging.getLogger(__name__) @@ -175,7 +175,11 @@ def _lookup_module(domain): try: module = importlib.import_module(f"esphome.components.{domain}") except ImportError as e: - if "No module named" not in str(e): + if "No module named" in str(e): + _LOGGER.error( + "Unable to import component %s: %s", domain, str(e), exc_info=False + ) + else: _LOGGER.error("Unable to import component %s:", domain, exc_info=True) return None except Exception: # pylint: disable=broad-except From 6e863305aae0589103fa9dfdf2d36d2ff50858c9 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 23 Jul 2024 13:51:32 +1200 Subject: [PATCH 1821/2101] [http_request] Change default timeout to 4.5s (#7123) --- esphome/components/http_request/__init__.py | 2 +- esphome/components/http_request/http_request.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/http_request/__init__.py b/esphome/components/http_request/__init__.py index ade7024bed..ef387553fe 100644 --- a/esphome/components/http_request/__init__.py +++ b/esphome/components/http_request/__init__.py @@ -99,7 +99,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_FOLLOW_REDIRECTS, True): cv.boolean, cv.Optional(CONF_REDIRECT_LIMIT, 3): cv.int_, cv.Optional( - CONF_TIMEOUT, default="5s" + CONF_TIMEOUT, default="4.5s" ): cv.positive_time_period_milliseconds, cv.SplitDefault(CONF_ESP8266_DISABLE_SSL_SUPPORT, esp8266=False): cv.All( cv.only_on_esp8266, cv.boolean diff --git a/esphome/components/http_request/http_request.h b/esphome/components/http_request/http_request.h index 82b7392648..c01baf8644 100644 --- a/esphome/components/http_request/http_request.h +++ b/esphome/components/http_request/http_request.h @@ -80,7 +80,7 @@ class HttpRequestComponent : public Component { const char *useragent_{nullptr}; bool follow_redirects_; uint16_t redirect_limit_; - uint16_t timeout_{5000}; + uint16_t timeout_{4500}; uint32_t watchdog_timeout_{0}; }; From 7c24f1ba6dac36d839c5fe34f16d6b52f12264da Mon Sep 17 00:00:00 2001 From: dentra Date: Wed, 24 Jul 2024 03:12:59 +0300 Subject: [PATCH 1822/2101] [http_request] Fix ESP-IDF follow redirect (#7101) --- esphome/components/http_request/__init__.py | 14 ++-- .../http_request/http_request_idf.cpp | 66 +++++++++++++++---- 2 files changed, 62 insertions(+), 18 deletions(-) diff --git a/esphome/components/http_request/__init__.py b/esphome/components/http_request/__init__.py index ef387553fe..161486fbb2 100644 --- a/esphome/components/http_request/__init__.py +++ b/esphome/components/http_request/__init__.py @@ -1,17 +1,17 @@ -import esphome.codegen as cg -import esphome.config_validation as cv from esphome import automation +import esphome.codegen as cg +from esphome.components import esp32 +import esphome.config_validation as cv from esphome.const import ( - __version__, + CONF_ESP8266_DISABLE_SSL_SUPPORT, CONF_ID, - CONF_TIMEOUT, CONF_METHOD, + CONF_TIMEOUT, CONF_TRIGGER_ID, CONF_URL, - CONF_ESP8266_DISABLE_SSL_SUPPORT, + __version__, ) -from esphome.core import Lambda, CORE -from esphome.components import esp32 +from esphome.core import CORE, Lambda DEPENDENCIES = ["network"] AUTO_LOAD = ["json"] diff --git a/esphome/components/http_request/http_request_idf.cpp b/esphome/components/http_request/http_request_idf.cpp index 68e0639b99..1f03b5f3bf 100644 --- a/esphome/components/http_request/http_request_idf.cpp +++ b/esphome/components/http_request/http_request_idf.cpp @@ -77,7 +77,7 @@ std::shared_ptr HttpRequestIDF::start(std::string url, std::strin esp_http_client_set_header(client, header.name, header.value); } - int body_len = body.length(); + const int body_len = body.length(); esp_err_t err = esp_http_client_open(client, body_len); if (err != ESP_OK) { @@ -109,18 +109,62 @@ std::shared_ptr HttpRequestIDF::start(std::string url, std::strin return nullptr; } - container->content_length = esp_http_client_fetch_headers(client); - const auto status_code = esp_http_client_get_status_code(client); - container->status_code = status_code; + auto is_ok = [](int code) { return code >= HttpStatus_Ok && code < HttpStatus_MultipleChoices; }; - if (status_code < 200 || status_code >= 300) { - ESP_LOGE(TAG, "HTTP Request failed; URL: %s; Code: %d", url.c_str(), status_code); - this->status_momentary_error("failed", 1000); - esp_http_client_cleanup(client); - return nullptr; + container->content_length = esp_http_client_fetch_headers(client); + container->status_code = esp_http_client_get_status_code(client); + if (is_ok(container->status_code)) { + container->duration_ms = millis() - start; + return container; } - container->duration_ms = millis() - start; - return container; + + if (this->follow_redirects_) { + auto is_redirect = [](int code) { + return code == HttpStatus_MovedPermanently || code == HttpStatus_Found || code == HttpStatus_SeeOther || + code == HttpStatus_TemporaryRedirect || code == HttpStatus_PermanentRedirect; + }; + auto num_redirects = this->redirect_limit_; + while (is_redirect(container->status_code) && num_redirects > 0) { + 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); + esp_http_client_cleanup(client); + return nullptr; + } +#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE + char url[256]{}; + if (esp_http_client_get_url(client, url, sizeof(url) - 1) == ESP_OK) { + ESP_LOGV(TAG, "redirecting to url: %s", url); + } +#endif + 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); + esp_http_client_cleanup(client); + return nullptr; + } + + container->content_length = esp_http_client_fetch_headers(client); + container->status_code = esp_http_client_get_status_code(client); + if (is_ok(container->status_code)) { + container->duration_ms = millis() - start; + return container; + } + + num_redirects--; + } + + if (num_redirects == 0) { + ESP_LOGW(TAG, "Reach redirect limit count=%d", this->redirect_limit_); + } + } + + ESP_LOGE(TAG, "HTTP Request failed; URL: %s; Code: %d", url.c_str(), container->status_code); + this->status_momentary_error("failed", 1000); + esp_http_client_cleanup(client); + return nullptr; } int HttpContainerIDF::read(uint8_t *buf, size_t max_len) { From ad0118dd4a47f1566ee6146d69004957d5555d12 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 25 Jul 2024 09:13:05 +1200 Subject: [PATCH 1823/2101] Bump version to 2024.7.2 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index ff5f7b699d..9abfafc4a4 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.7.1" +__version__ = "2024.7.2" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 23ffc3ddfb1504a0f3f5ad7f3cc2f9ea1d3cddf6 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Thu, 25 Jul 2024 09:12:04 +1000 Subject: [PATCH 1824/2101] [lvgl] base implementation (#7116) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- CODEOWNERS | 1 + esphome/components/lvgl/__init__.py | 212 ++++++++++ esphome/components/lvgl/defines.py | 487 ++++++++++++++++++++++ esphome/components/lvgl/font.cpp | 76 ++++ esphome/components/lvgl/helpers.py | 70 ++++ esphome/components/lvgl/label.py | 34 ++ esphome/components/lvgl/lv_validation.py | 170 ++++++++ esphome/components/lvgl/lvcode.py | 237 +++++++++++ esphome/components/lvgl/lvgl_esphome.cpp | 129 ++++++ esphome/components/lvgl/lvgl_esphome.h | 119 ++++++ esphome/components/lvgl/lvgl_hal.h | 21 + esphome/components/lvgl/obj.py | 22 + esphome/components/lvgl/schemas.py | 260 ++++++++++++ esphome/components/lvgl/types.py | 64 +++ esphome/components/lvgl/widget.py | 347 +++++++++++++++ esphome/core/defines.h | 3 + platformio.ini | 1 + tests/components/lvgl/common.yaml | 0 tests/components/lvgl/lvgl-package.yaml | 24 ++ tests/components/lvgl/test.esp32-ard.yaml | 30 ++ tests/components/lvgl/test.esp32-idf.yaml | 52 +++ 21 files changed, 2359 insertions(+) create mode 100644 esphome/components/lvgl/__init__.py create mode 100644 esphome/components/lvgl/defines.py create mode 100644 esphome/components/lvgl/font.cpp create mode 100644 esphome/components/lvgl/helpers.py create mode 100644 esphome/components/lvgl/label.py create mode 100644 esphome/components/lvgl/lv_validation.py create mode 100644 esphome/components/lvgl/lvcode.py create mode 100644 esphome/components/lvgl/lvgl_esphome.cpp create mode 100644 esphome/components/lvgl/lvgl_esphome.h create mode 100644 esphome/components/lvgl/lvgl_hal.h create mode 100644 esphome/components/lvgl/obj.py create mode 100644 esphome/components/lvgl/schemas.py create mode 100644 esphome/components/lvgl/types.py create mode 100644 esphome/components/lvgl/widget.py create mode 100644 tests/components/lvgl/common.yaml create mode 100644 tests/components/lvgl/lvgl-package.yaml create mode 100644 tests/components/lvgl/test.esp32-ard.yaml create mode 100644 tests/components/lvgl/test.esp32-idf.yaml diff --git a/CODEOWNERS b/CODEOWNERS index c5e144bdfa..2fc030453f 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -217,6 +217,7 @@ esphome/components/lock/* @esphome/core esphome/components/logger/* @esphome/core esphome/components/ltr390/* @latonita @sjtrny esphome/components/ltr_als_ps/* @latonita +esphome/components/lvgl/* @clydebarrow esphome/components/m5stack_8angle/* @rnauber esphome/components/matrix_keypad/* @ssieb esphome/components/max31865/* @DAVe3283 diff --git a/esphome/components/lvgl/__init__.py b/esphome/components/lvgl/__init__.py new file mode 100644 index 0000000000..2f3bd69546 --- /dev/null +++ b/esphome/components/lvgl/__init__.py @@ -0,0 +1,212 @@ +import logging + +import esphome.codegen as cg +from esphome.components.display import Display +import esphome.config_validation as cv +from esphome.const import ( + CONF_AUTO_CLEAR_ENABLED, + CONF_BUFFER_SIZE, + CONF_ID, + CONF_LAMBDA, + CONF_PAGES, +) +from esphome.core import CORE, ID, Lambda +from esphome.cpp_generator import MockObj +from esphome.final_validate import full_config +from esphome.helpers import write_file_if_changed + +from . import defines as df, helpers, lv_validation as lvalid +from .label import label_spec +from .lvcode import ConstantLiteral, LvContext + +# from .menu import menu_spec +from .obj import obj_spec +from .schemas import WIDGET_TYPES, any_widget_schema, obj_schema +from .types import FontEngine, LvglComponent, lv_disp_t_ptr, lv_font_t, lvgl_ns +from .widget import LvScrActType, Widget, add_widgets, set_obj_properties + +DOMAIN = "lvgl" +DEPENDENCIES = ("display",) +AUTO_LOAD = ("key_provider",) +CODEOWNERS = ("@clydebarrow",) +LOGGER = logging.getLogger(__name__) + +for widg in ( + label_spec, + obj_spec, +): + WIDGET_TYPES[widg.name] = widg + +lv_scr_act_spec = LvScrActType() +lv_scr_act = Widget.create( + None, ConstantLiteral("lv_scr_act()"), lv_scr_act_spec, {}, parent=None +) + +WIDGET_SCHEMA = any_widget_schema() + + +async def add_init_lambda(lv_component, init): + if init: + lamb = await cg.process_lambda(Lambda(init), [(lv_disp_t_ptr, "lv_disp")]) + cg.add(lv_component.add_init_lambda(lamb)) + + +lv_defines = {} # Dict of #defines to provide as build flags + + +def add_define(macro, value="1"): + if macro in lv_defines and lv_defines[macro] != value: + LOGGER.error( + "Redefinition of %s - was %s now %s", macro, lv_defines[macro], value + ) + lv_defines[macro] = value + + +def as_macro(macro, value): + if value is None: + return f"#define {macro}" + return f"#define {macro} {value}" + + +LV_CONF_FILENAME = "lv_conf.h" +LV_CONF_H_FORMAT = """\ +#pragma once +{} +""" + + +def generate_lv_conf_h(): + definitions = [as_macro(m, v) for m, v in lv_defines.items()] + definitions.sort() + return LV_CONF_H_FORMAT.format("\n".join(definitions)) + + +def final_validation(config): + global_config = full_config.get() + 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) + if CONF_LAMBDA in display: + raise cv.Invalid("Using lambda: in display config not compatible with LVGL") + if display[CONF_AUTO_CLEAR_ENABLED]: + raise cv.Invalid( + "Using auto_clear_enabled: true in display config not compatible with LVGL" + ) + buffer_frac = config[CONF_BUFFER_SIZE] + if not CORE.is_host and buffer_frac > 0.5 and "psram" not in global_config: + LOGGER.warning("buffer_size: may need to be reduced without PSRAM") + + +async def to_code(config): + cg.add_library("lvgl/lvgl", "8.4.0") + CORE.add_define("USE_LVGL") + # suppress default enabling of extra widgets + 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"') + + add_define("LV_LOG_LEVEL", f"LV_LOG_LEVEL_{config[df.CONF_LOG_LEVEL]}") + add_define("LV_COLOR_DEPTH", config[df.CONF_COLOR_DEPTH]) + for font in helpers.lv_fonts_used: + add_define(f"LV_FONT_{font.upper()}") + + if config[df.CONF_COLOR_DEPTH] == 16: + add_define( + "LV_COLOR_16_SWAP", + "1" if config[df.CONF_BYTE_ORDER] == "big_endian" else "0", + ) + add_define( + "LV_COLOR_CHROMA_KEY", + await lvalid.lv_color.process(config[df.CONF_TRANSPARENCY_KEY]), + ) + CORE.add_build_flag("-Isrc") + + cg.add_global(lvgl_ns.using) + lv_component = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(lv_component, config) + Widget.create(config[CONF_ID], lv_component, WIDGET_TYPES[df.CONF_OBJ], config) + for display in config[df.CONF_DISPLAYS]: + cg.add(lv_component.add_display(await cg.get_variable(display))) + + frac = config[CONF_BUFFER_SIZE] + if frac >= 0.75: + frac = 1 + elif frac >= 0.375: + frac = 2 + elif frac > 0.19: + frac = 4 + else: + frac = 8 + cg.add(lv_component.set_buffer_frac(int(frac))) + cg.add(lv_component.set_full_refresh(config[df.CONF_FULL_REFRESH])) + + for font in helpers.esphome_fonts_used: + await cg.get_variable(font) + cg.new_Pvariable(ID(f"{font}_engine", True, type=FontEngine), MockObj(font)) + default_font = config[df.CONF_DEFAULT_FONT] + if default_font not in helpers.lv_fonts_used: + add_define( + "LV_FONT_CUSTOM_DECLARE", f"LV_FONT_DECLARE(*{df.DEFAULT_ESPHOME_FONT})" + ) + globfont_id = ID( + df.DEFAULT_ESPHOME_FONT, + True, + type=lv_font_t.operator("ptr").operator("const"), + ) + cg.new_variable(globfont_id, MockObj(default_font)) + add_define("LV_FONT_DEFAULT", df.DEFAULT_ESPHOME_FONT) + else: + add_define("LV_FONT_DEFAULT", default_font) + + with LvContext(): + await set_obj_properties(lv_scr_act, config) + await add_widgets(lv_scr_act, config) + Widget.set_completed() + await add_init_lambda(lv_component, LvContext.get_code()) + for comp in helpers.lvgl_components_required: + CORE.add_define(f"USE_LVGL_{comp.upper()}") + for use in helpers.lv_uses: + add_define(f"LV_USE_{use.upper()}") + lv_conf_h_file = CORE.relative_src_path(LV_CONF_FILENAME) + write_file_if_changed(lv_conf_h_file, generate_lv_conf_h()) + CORE.add_build_flag("-DLV_CONF_H=1") + CORE.add_build_flag(f'-DLV_CONF_PATH="{LV_CONF_FILENAME}"') + + +def display_schema(config): + value = cv.ensure_list(cv.use_id(Display))(config) + return value or [cv.use_id(Display)(config)] + + +FINAL_VALIDATE_SCHEMA = final_validation + +CONFIG_SCHEMA = ( + cv.polling_component_schema("1s") + .extend(obj_schema("obj")) + .extend( + { + cv.GenerateID(CONF_ID): cv.declare_id(LvglComponent), + cv.GenerateID(df.CONF_DISPLAYS): display_schema, + cv.Optional(df.CONF_COLOR_DEPTH, default=16): cv.one_of(16), + cv.Optional(df.CONF_DEFAULT_FONT, default="montserrat_14"): lvalid.lv_font, + cv.Optional(df.CONF_FULL_REFRESH, default=False): cv.boolean, + cv.Optional(CONF_BUFFER_SIZE, default="100%"): cv.percentage, + cv.Optional(df.CONF_LOG_LEVEL, default="WARN"): cv.one_of( + *df.LOG_LEVELS, upper=True + ), + cv.Optional(df.CONF_BYTE_ORDER, default="big_endian"): cv.one_of( + "big_endian", "little_endian" + ), + cv.Optional(df.CONF_WIDGETS): cv.ensure_list(WIDGET_SCHEMA), + cv.Optional(df.CONF_TRANSPARENCY_KEY, default=0x000400): lvalid.lv_color, + } + ) +).add_extra(cv.has_at_least_one_key(CONF_PAGES, df.CONF_WIDGETS)) diff --git a/esphome/components/lvgl/defines.py b/esphome/components/lvgl/defines.py new file mode 100644 index 0000000000..50bdac3865 --- /dev/null +++ b/esphome/components/lvgl/defines.py @@ -0,0 +1,487 @@ +""" +This is the base of the import tree for LVGL. It contains constant definitions used elsewhere. +Constants already defined in esphome.const are not duplicated here and must be imported where used. + +""" + +from esphome import codegen as cg, config_validation as cv +from esphome.core import ID, Lambda +from esphome.cpp_types import uint32 +from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor + +from .lvcode import ConstantLiteral + + +class LValidator: + """ + A validator for a particular type used in LVGL. Usable in configs as a validator, also + has `process()` to convert a value during code generation + """ + + def __init__(self, validator, rtype, idtype=None, idexpr=None, retmapper=None): + self.validator = validator + self.rtype = rtype + self.idtype = idtype + self.idexpr = idexpr + self.retmapper = retmapper + + def __call__(self, value): + if isinstance(value, cv.Lambda): + return cv.returning_lambda(value) + if self.idtype is not None and isinstance(value, ID): + return cv.use_id(self.idtype)(value) + return self.validator(value) + + async def process(self, value, args=()): + if value is None: + return None + if isinstance(value, Lambda): + return cg.RawExpression( + f"{await cg.process_lambda(value, args, return_type=self.rtype)}()" + ) + if self.idtype is not None and isinstance(value, ID): + return cg.RawExpression(f"{value}->{self.idexpr}") + if self.retmapper is not None: + return self.retmapper(value) + return cg.safe_exp(value) + + +class LvConstant(LValidator): + """ + Allow one of a list of choices, mapped to upper case, and prepend the choice with the prefix. + It's also permitted to include the prefix in the value + The property `one_of` has the single case validator, and `several_of` allows a list of constants. + """ + + def __init__(self, prefix: str, *choices): + self.prefix = prefix + self.choices = choices + prefixed_choices = [prefix + v for v in choices] + prefixed_validator = cv.one_of(*prefixed_choices, upper=True) + + @schema_extractor("one_of") + def validator(value): + if value == SCHEMA_EXTRACT: + return self.choices + if isinstance(value, str) and value.startswith(self.prefix): + return prefixed_validator(value) + return self.prefix + cv.one_of(*choices, upper=True)(value) + + super().__init__(validator, rtype=uint32) + self.one_of = LValidator(validator, uint32, retmapper=self.mapper) + self.several_of = LValidator( + cv.ensure_list(self.one_of), uint32, retmapper=self.mapper + ) + + def mapper(self, value, args=()): + if isinstance(value, list): + value = "|".join(value) + return ConstantLiteral(value) + + def extend(self, *choices): + """ + Extend an LVCconstant with additional choices. + :param choices: The extra choices + :return: A new LVConstant instance + """ + return LvConstant(self.prefix, *(self.choices + choices)) + + +# Widgets +CONF_LABEL = "label" + +# Parts +CONF_MAIN = "main" +CONF_SCROLLBAR = "scrollbar" +CONF_INDICATOR = "indicator" +CONF_KNOB = "knob" +CONF_SELECTED = "selected" +CONF_ITEMS = "items" +CONF_TICKS = "ticks" +CONF_TICK_STYLE = "tick_style" +CONF_CURSOR = "cursor" +CONF_TEXTAREA_PLACEHOLDER = "textarea_placeholder" + +LV_FONTS = list(f"montserrat_{s}" for s in range(8, 50, 2)) + [ + "dejavu_16_persian_hebrew", + "simsun_16_cjk", + "unscii_8", + "unscii_16", +] + +LV_EVENT = { + "PRESS": "PRESSED", + "SHORT_CLICK": "SHORT_CLICKED", + "LONG_PRESS": "LONG_PRESSED", + "LONG_PRESS_REPEAT": "LONG_PRESSED_REPEAT", + "CLICK": "CLICKED", + "RELEASE": "RELEASED", + "SCROLL_BEGIN": "SCROLL_BEGIN", + "SCROLL_END": "SCROLL_END", + "SCROLL": "SCROLL", + "FOCUS": "FOCUSED", + "DEFOCUS": "DEFOCUSED", + "READY": "READY", + "CANCEL": "CANCEL", +} + +LV_EVENT_TRIGGERS = tuple(f"on_{x.lower()}" for x in LV_EVENT) + + +LV_ANIM = LvConstant( + "LV_SCR_LOAD_ANIM_", + "NONE", + "OVER_LEFT", + "OVER_RIGHT", + "OVER_TOP", + "OVER_BOTTOM", + "MOVE_LEFT", + "MOVE_RIGHT", + "MOVE_TOP", + "MOVE_BOTTOM", + "FADE_IN", + "FADE_OUT", + "OUT_LEFT", + "OUT_RIGHT", + "OUT_TOP", + "OUT_BOTTOM", +) + +LOG_LEVELS = ( + "TRACE", + "INFO", + "WARN", + "ERROR", + "USER", + "NONE", +) + +LV_LONG_MODES = LvConstant( + "LV_LABEL_LONG_", + "WRAP", + "DOT", + "SCROLL", + "SCROLL_CIRCULAR", + "CLIP", +) + +STATES = ( + "default", + "checked", + "focused", + "focus_key", + "edited", + "hovered", + "pressed", + "scrolled", + "disabled", + "user_1", + "user_2", + "user_3", + "user_4", +) + +PARTS = ( + CONF_MAIN, + CONF_SCROLLBAR, + CONF_INDICATOR, + CONF_KNOB, + CONF_SELECTED, + CONF_ITEMS, + CONF_TICKS, + CONF_CURSOR, + CONF_TEXTAREA_PLACEHOLDER, +) + +KEYBOARD_MODES = LvConstant( + "LV_KEYBOARD_MODE_", + "TEXT_LOWER", + "TEXT_UPPER", + "SPECIAL", + "NUMBER", +) +ROLLER_MODES = LvConstant("LV_ROLLER_MODE_", "NORMAL", "INFINITE") +DIRECTIONS = LvConstant("LV_DIR_", "LEFT", "RIGHT", "BOTTOM", "TOP") +TILE_DIRECTIONS = DIRECTIONS.extend("HOR", "VER", "ALL") +CHILD_ALIGNMENTS = LvConstant( + "LV_ALIGN_", + "TOP_LEFT", + "TOP_MID", + "TOP_RIGHT", + "LEFT_MID", + "CENTER", + "RIGHT_MID", + "BOTTOM_LEFT", + "BOTTOM_MID", + "BOTTOM_RIGHT", +) + +SIBLING_ALIGNMENTS = LvConstant( + "LV_ALIGN_", + "OUT_LEFT_TOP", + "OUT_TOP_LEFT", + "OUT_TOP_MID", + "OUT_TOP_RIGHT", + "OUT_RIGHT_TOP", + "OUT_LEFT_MID", + "OUT_RIGHT_MID", + "OUT_LEFT_BOTTOM", + "OUT_BOTTOM_LEFT", + "OUT_BOTTOM_MID", + "OUT_BOTTOM_RIGHT", + "OUT_RIGHT_BOTTOM", +) +ALIGN_ALIGNMENTS = CHILD_ALIGNMENTS.extend(*SIBLING_ALIGNMENTS.choices) + +FLEX_FLOWS = LvConstant( + "LV_FLEX_FLOW_", + "ROW", + "COLUMN", + "ROW_WRAP", + "COLUMN_WRAP", + "ROW_REVERSE", + "COLUMN_REVERSE", + "ROW_WRAP_REVERSE", + "COLUMN_WRAP_REVERSE", +) + +OBJ_FLAGS = ( + "hidden", + "clickable", + "click_focusable", + "checkable", + "scrollable", + "scroll_elastic", + "scroll_momentum", + "scroll_one", + "scroll_chain_hor", + "scroll_chain_ver", + "scroll_chain", + "scroll_on_focus", + "scroll_with_arrow", + "snappable", + "press_lock", + "event_bubble", + "gesture_bubble", + "adv_hittest", + "ignore_layout", + "floating", + "overflow_visible", + "layout_1", + "layout_2", + "widget_1", + "widget_2", + "user_1", + "user_2", + "user_3", + "user_4", +) + +ARC_MODES = LvConstant("LV_ARC_MODE_", "NORMAL", "REVERSE", "SYMMETRICAL") +BAR_MODES = LvConstant("LV_BAR_MODE_", "NORMAL", "SYMMETRICAL", "RANGE") + +BTNMATRIX_CTRLS = ( + "HIDDEN", + "NO_REPEAT", + "DISABLED", + "CHECKABLE", + "CHECKED", + "CLICK_TRIG", + "POPOVER", + "RECOLOR", + "CUSTOM_1", + "CUSTOM_2", +) + +LV_BASE_ALIGNMENTS = ( + "START", + "CENTER", + "END", +) +LV_CELL_ALIGNMENTS = LvConstant( + "LV_GRID_ALIGN_", + *LV_BASE_ALIGNMENTS, +) +LV_GRID_ALIGNMENTS = LV_CELL_ALIGNMENTS.extend( + "STRETCH", + "SPACE_EVENLY", + "SPACE_AROUND", + "SPACE_BETWEEN", +) + +LV_FLEX_ALIGNMENTS = LvConstant( + "LV_FLEX_ALIGN_", + *LV_BASE_ALIGNMENTS, + "SPACE_EVENLY", + "SPACE_AROUND", + "SPACE_BETWEEN", +) + +LV_MENU_MODES = LvConstant( + "LV_MENU_HEADER_", + "TOP_FIXED", + "TOP_UNFIXED", + "BOTTOM_FIXED", +) + +LV_CHART_TYPES = ( + "NONE", + "LINE", + "BAR", + "SCATTER", +) +LV_CHART_AXES = ( + "PRIMARY_Y", + "SECONDARY_Y", + "PRIMARY_X", + "SECONDARY_X", +) + +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_ANTIALIAS = "antialias" +CONF_ARC_LENGTH = "arc_length" +CONF_AUTO_START = "auto_start" +CONF_BACKGROUND_STYLE = "background_style" +CONF_DECIMAL_PLACES = "decimal_places" +CONF_COLUMN = "column" +CONF_DIGITS = "digits" +CONF_DISP_BG_COLOR = "disp_bg_color" +CONF_DISP_BG_IMAGE = "disp_bg_image" +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_CONTROL = "control" +CONF_DEFAULT = "default" +CONF_DEFAULT_FONT = "default_font" +CONF_DIR = "dir" +CONF_DISPLAYS = "displays" +CONF_END_ANGLE = "end_angle" +CONF_END_VALUE = "end_value" +CONF_ENTER_BUTTON = "enter_button" +CONF_ENTRIES = "entries" +CONF_FLAGS = "flags" +CONF_FLEX_FLOW = "flex_flow" +CONF_FLEX_ALIGN_MAIN = "flex_align_main" +CONF_FLEX_ALIGN_CROSS = "flex_align_cross" +CONF_FLEX_ALIGN_TRACK = "flex_align_track" +CONF_FLEX_GROW = "flex_grow" +CONF_FULL_REFRESH = "full_refresh" +CONF_GRID_CELL_ROW_POS = "grid_cell_row_pos" +CONF_GRID_CELL_COLUMN_POS = "grid_cell_column_pos" +CONF_GRID_CELL_ROW_SPAN = "grid_cell_row_span" +CONF_GRID_CELL_COLUMN_SPAN = "grid_cell_column_span" +CONF_GRID_CELL_X_ALIGN = "grid_cell_x_align" +CONF_GRID_CELL_Y_ALIGN = "grid_cell_y_align" +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_MODE = "header_mode" +CONF_HOME = "home" +CONF_INDICATORS = "indicators" +CONF_KEY_CODE = "key_code" +CONF_LABEL_GAP = "label_gap" +CONF_LAYOUT = "layout" +CONF_LEFT_BUTTON = "left_button" +CONF_LINE_WIDTH = "line_width" +CONF_LOG_LEVEL = "log_level" +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 = "major" +CONF_MSGBOXES = "msgboxes" +CONF_OBJ = "obj" +CONF_OFFSET_X = "offset_x" +CONF_OFFSET_Y = "offset_y" +CONF_ONE_LINE = "one_line" +CONF_ON_SELECT = "on_select" +CONF_ONE_CHECKED = "one_checked" +CONF_NEXT = "next" +CONF_PAGE_WRAP = "page_wrap" +CONF_PASSWORD_MODE = "password_mode" +CONF_PIVOT_X = "pivot_x" +CONF_PIVOT_Y = "pivot_y" +CONF_PLACEHOLDER_TEXT = "placeholder_text" +CONF_POINTS = "points" +CONF_PREVIOUS = "previous" +CONF_REPEAT_COUNT = "repeat_count" +CONF_R_MOD = "r_mod" +CONF_RECOLOR = "recolor" +CONF_RIGHT_BUTTON = "right_button" +CONF_ROLLOVER = "rollover" +CONF_ROOT_BACK_BTN = "root_back_btn" +CONF_ROWS = "rows" +CONF_SCALES = "scales" +CONF_SCALE_LINES = "scale_lines" +CONF_SCROLLBAR_MODE = "scrollbar_mode" +CONF_SELECTED_INDEX = "selected_index" +CONF_SHOW_SNOW = "show_snow" +CONF_SPIN_TIME = "spin_time" +CONF_SRC = "src" +CONF_START_ANGLE = "start_angle" +CONF_START_VALUE = "start_value" +CONF_STATES = "states" +CONF_STRIDE = "stride" +CONF_STYLE = "style" +CONF_STYLE_ID = "style_id" +CONF_SKIP = "skip" +CONF_SYMBOL = "symbol" +CONF_TAB_ID = "tab_id" +CONF_TABS = "tabs" +CONF_TEXT = "text" +CONF_TILE = "tile" +CONF_TILE_ID = "tile_id" +CONF_TILES = "tiles" +CONF_TITLE = "title" +CONF_TOP_LAYER = "top_layer" +CONF_TRANSPARENCY_KEY = "transparency_key" +CONF_THEME = "theme" +CONF_VISIBLE_ROW_COUNT = "visible_row_count" +CONF_WIDGET = "widget" +CONF_WIDGETS = "widgets" +CONF_X = "x" +CONF_Y = "y" +CONF_ZOOM = "zoom" + +# Keypad keys + +LV_KEYS = LvConstant( + "LV_KEY_", + "UP", + "DOWN", + "RIGHT", + "LEFT", + "ESC", + "DEL", + "BACKSPACE", + "ENTER", + "NEXT", + "PREV", + "HOME", + "END", +) + + +# list of widgets and the parts allowed +WIDGET_PARTS = { + CONF_LABEL: (CONF_MAIN, CONF_SCROLLBAR, CONF_SELECTED), + CONF_OBJ: (CONF_MAIN,), +} + +DEFAULT_ESPHOME_FONT = "esphome_lv_default_font" + + +def join_enums(enums, prefix=""): + return "|".join(f"(int){prefix}{e.upper()}" for e in enums) diff --git a/esphome/components/lvgl/font.cpp b/esphome/components/lvgl/font.cpp new file mode 100644 index 0000000000..9c172f07f5 --- /dev/null +++ b/esphome/components/lvgl/font.cpp @@ -0,0 +1,76 @@ +#include "lvgl_esphome.h" + +#ifdef USE_LVGL_FONT +namespace esphome { +namespace lvgl { + +static const uint8_t *get_glyph_bitmap(const lv_font_t *font, uint32_t unicode_letter) { + auto *fe = (FontEngine *) font->dsc; + const auto *gd = fe->get_glyph_data(unicode_letter); + if (gd == nullptr) + return nullptr; + // esph_log_d(TAG, "Returning bitmap @ %X", (uint32_t)gd->data); + + return gd->data; +} + +static bool get_glyph_dsc_cb(const lv_font_t *font, lv_font_glyph_dsc_t *dsc, uint32_t unicode_letter, uint32_t next) { + auto *fe = (FontEngine *) font->dsc; + const auto *gd = fe->get_glyph_data(unicode_letter); + if (gd == nullptr) + return false; + dsc->adv_w = gd->offset_x + gd->width; + dsc->ofs_x = gd->offset_x; + dsc->ofs_y = fe->height - gd->height - gd->offset_y - fe->baseline; + dsc->box_w = gd->width; + dsc->box_h = gd->height; + dsc->is_placeholder = 0; + dsc->bpp = fe->bpp; + return true; +} + +FontEngine::FontEngine(font::Font *esp_font) : font_(esp_font) { + this->bpp = esp_font->get_bpp(); + this->lv_font_.dsc = this; + this->lv_font_.line_height = this->height = esp_font->get_height(); + this->lv_font_.base_line = this->baseline = this->lv_font_.line_height - esp_font->get_baseline(); + this->lv_font_.get_glyph_dsc = get_glyph_dsc_cb; + this->lv_font_.get_glyph_bitmap = get_glyph_bitmap; + this->lv_font_.subpx = LV_FONT_SUBPX_NONE; + this->lv_font_.underline_position = -1; + this->lv_font_.underline_thickness = 1; +} + +const lv_font_t *FontEngine::get_lv_font() { return &this->lv_font_; } + +const font::GlyphData *FontEngine::get_glyph_data(uint32_t unicode_letter) { + if (unicode_letter == last_letter_) + return this->last_data_; + uint8_t unicode[5]; + memset(unicode, 0, sizeof unicode); + if (unicode_letter > 0xFFFF) { + unicode[0] = 0xF0 + ((unicode_letter >> 18) & 0x7); + unicode[1] = 0x80 + ((unicode_letter >> 12) & 0x3F); + unicode[2] = 0x80 + ((unicode_letter >> 6) & 0x3F); + unicode[3] = 0x80 + (unicode_letter & 0x3F); + } else if (unicode_letter > 0x7FF) { + unicode[0] = 0xE0 + ((unicode_letter >> 12) & 0xF); + unicode[1] = 0x80 + ((unicode_letter >> 6) & 0x3F); + unicode[2] = 0x80 + (unicode_letter & 0x3F); + } else if (unicode_letter > 0x7F) { + unicode[0] = 0xC0 + ((unicode_letter >> 6) & 0x1F); + unicode[1] = 0x80 + (unicode_letter & 0x3F); + } else { + unicode[0] = unicode_letter; + } + int match_length; + int glyph_n = this->font_->match_next_glyph(unicode, &match_length); + if (glyph_n < 0) + return nullptr; + this->last_data_ = this->font_->get_glyphs()[glyph_n].get_glyph_data(); + this->last_letter_ = unicode_letter; + return this->last_data_; +} +} // namespace lvgl +} // namespace esphome +#endif // USES_LVGL_FONT diff --git a/esphome/components/lvgl/helpers.py b/esphome/components/lvgl/helpers.py new file mode 100644 index 0000000000..c8d4948fb1 --- /dev/null +++ b/esphome/components/lvgl/helpers.py @@ -0,0 +1,70 @@ +import re + +from esphome import config_validation as cv +from esphome.config import Config +from esphome.const import CONF_ARGS, CONF_FORMAT +from esphome.core import CORE, ID +from esphome.yaml_util import ESPHomeDataBase + +lv_uses = { + "USER_DATA", + "LOG", + "STYLE", + "FONT_PLACEHOLDER", + "THEME_DEFAULT", +} + + +def add_lv_use(*names): + for name in names: + lv_uses.add(name) + + +lv_fonts_used = set() +esphome_fonts_used = set() +REQUIRED_COMPONENTS = {} +lvgl_components_required = set() + + +def validate_printf(value): + cfmt = r""" + ( # start of capture group 1 + % # literal "%" + (?:[-+0 #]{0,5}) # optional flags + (?:\d+|\*)? # width + (?:\.(?:\d+|\*))? # precision + (?:h|l|ll|w|I|I32|I64)? # size + [cCdiouxXeEfgGaAnpsSZ] # type + ) + """ # noqa + matches = re.findall(cfmt, value[CONF_FORMAT], flags=re.X) + if len(matches) != len(value[CONF_ARGS]): + raise cv.Invalid( + f"Found {len(matches)} printf-patterns ({', '.join(matches)}), but {len(value[CONF_ARGS])} args were given!" + ) + return value + + +def get_line_marks(value) -> list: + """ + If possible, return a preprocessor directive to identify the line number where the given id was defined. + :param id: The id in question + :return: A list containing zero or more line directives + """ + path = None + if isinstance(value, ESPHomeDataBase): + path = value.esp_range + elif isinstance(value, ID) and isinstance(CORE.config, Config): + path = CORE.config.get_path_for_id(value)[:-1] + path = CORE.config.get_deepest_document_range_for_path(path) + if path is None: + return [] + return [path.start_mark.as_line_directive] + + +def requires_component(comp): + def validator(value): + lvgl_components_required.add(comp) + return cv.requires_component(comp)(value) + + return validator diff --git a/esphome/components/lvgl/label.py b/esphome/components/lvgl/label.py new file mode 100644 index 0000000000..5c4ae6ab0d --- /dev/null +++ b/esphome/components/lvgl/label.py @@ -0,0 +1,34 @@ +import esphome.config_validation as cv + +from .defines import CONF_LABEL, CONF_LONG_MODE, CONF_RECOLOR, CONF_TEXT, LV_LONG_MODES +from .lv_validation import lv_bool, lv_text +from .schemas import TEXT_SCHEMA +from .types import lv_label_t +from .widget import Widget, WidgetType + + +class LabelType(WidgetType): + def __init__(self): + super().__init__( + CONF_LABEL, + TEXT_SCHEMA.extend( + { + cv.Optional(CONF_RECOLOR): lv_bool, + cv.Optional(CONF_LONG_MODE): LV_LONG_MODES.one_of, + } + ), + ) + + @property + def w_type(self): + return lv_label_t + + async def to_code(self, w: Widget, config): + """For a text object, create and set text""" + if value := config.get(CONF_TEXT): + w.set_property(CONF_TEXT, await lv_text.process(value)) + w.set_property(CONF_LONG_MODE, config) + w.set_property(CONF_RECOLOR, config) + + +label_spec = LabelType() diff --git a/esphome/components/lvgl/lv_validation.py b/esphome/components/lvgl/lv_validation.py new file mode 100644 index 0000000000..1de63c30ce --- /dev/null +++ b/esphome/components/lvgl/lv_validation.py @@ -0,0 +1,170 @@ +import esphome.codegen as cg +from esphome.components.binary_sensor import BinarySensor +from esphome.components.color import ColorStruct +from esphome.components.font import Font +from esphome.components.sensor import Sensor +from esphome.components.text_sensor import TextSensor +import esphome.config_validation as cv +from esphome.const import CONF_ARGS, CONF_COLOR, CONF_FORMAT +from esphome.core import HexInt +from esphome.cpp_generator import MockObj +from esphome.helpers import cpp_string_escape +from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor + +from . import types as ty +from .defines import LV_FONTS, LValidator, LvConstant +from .helpers import ( + esphome_fonts_used, + lv_fonts_used, + lvgl_components_required, + requires_component, +) +from .lvcode import ConstantLiteral, lv_expr +from .types import lv_font_t + + +@schema_extractor("one_of") +def color(value): + if value == SCHEMA_EXTRACT: + return ["hex color value", "color ID"] + if isinstance(value, int): + return value + return cv.use_id(ColorStruct)(value) + + +def color_retmapper(value): + if isinstance(value, cv.Lambda): + return cv.returning_lambda(value) + if isinstance(value, int): + hexval = HexInt(value) + return lv_expr.color_hex(hexval) + # Must be an id + lvgl_components_required.add(CONF_COLOR) + return lv_expr.color_from(MockObj(value)) + + +def pixels_or_percent(value): + """A length in one axis - either a number (pixels) or a percentage""" + if value == SCHEMA_EXTRACT: + return ["pixels", "..%"] + if isinstance(value, int): + return str(cv.int_(value)) + # Will throw an exception if not a percentage. + return f"lv_pct({int(cv.percentage(value) * 100)})" + + +def zoom(value): + value = cv.float_range(0.1, 10.0)(value) + return int(value * 256) + + +def angle(value): + """ + Validation for an angle in degrees, converted to an integer representing 0.1deg units + :param value: The input in the range 0..360 + :return: An angle in 1/10 degree units. + """ + return int(cv.float_range(0.0, 360.0)(cv.angle(value)) * 10) + + +@schema_extractor("one_of") +def size(value): + """A size in one axis - one of "size_content", a number (pixels) or a percentage""" + if value == SCHEMA_EXTRACT: + return ["size_content", "pixels", "..%"] + if isinstance(value, str) and value.lower().endswith("px"): + value = cv.int_(value[:-2]) + if isinstance(value, str) and not value.endswith("%"): + if value.upper() == "SIZE_CONTENT": + return "LV_SIZE_CONTENT" + raise cv.Invalid("must be 'size_content', a pixel position or a percentage") + if isinstance(value, int): + return str(cv.int_(value)) + # Will throw an exception if not a percentage. + return f"lv_pct({int(cv.percentage(value) * 100)})" + + +@schema_extractor("one_of") +def opacity(value): + consts = LvConstant("LV_OPA_", "TRANSP", "COVER") + if value == SCHEMA_EXTRACT: + return consts.choices + value = cv.Any(cv.percentage, consts.one_of)(value) + if isinstance(value, float): + return int(value * 255) + return value + + +def stop_value(value): + return cv.int_range(0, 255)(value) + + +lv_color = LValidator(color, ty.lv_color_t, retmapper=color_retmapper) +lv_bool = LValidator(cv.boolean, cg.bool_, BinarySensor, "get_state()") + + +def lvms_validator_(value): + if value == "never": + value = "2147483647ms" + return cv.positive_time_period_milliseconds(value) + + +lv_milliseconds = LValidator( + lvms_validator_, + cg.int32, + retmapper=lambda x: x.total_milliseconds, +) + + +class TextValidator(LValidator): + def __init__(self): + super().__init__( + cv.string, + cg.const_char_ptr, + TextSensor, + "get_state().c_str()", + lambda s: cg.safe_exp(f"{s}"), + ) + + def __call__(self, value): + if isinstance(value, dict): + return value + return super().__call__(value) + + async def process(self, value, args=()): + if isinstance(value, dict): + args = [str(x) for x in value[CONF_ARGS]] + arg_expr = cg.RawExpression(",".join(args)) + format_str = cpp_string_escape(value[CONF_FORMAT]) + return f"str_sprintf({format_str}, {arg_expr}).c_str()" + return await super().process(value, args) + + +lv_text = TextValidator() +lv_float = LValidator(cv.float_, cg.float_, Sensor, "get_state()") +lv_int = LValidator(cv.int_, cg.int_, Sensor, "get_state()") + + +class LvFont(LValidator): + def __init__(self): + def lv_builtin_font(value): + fontval = cv.one_of(*LV_FONTS, lower=True)(value) + lv_fonts_used.add(fontval) + return "&lv_font_" + fontval + + def validator(value): + if value == SCHEMA_EXTRACT: + return LV_FONTS + if isinstance(value, str) and value.lower() in LV_FONTS: + return lv_builtin_font(value) + fontval = cv.use_id(Font)(value) + esphome_fonts_used.add(fontval) + return requires_component("font")(f"{fontval}_engine->get_lv_font()") + + super().__init__(validator, lv_font_t) + + async def process(self, value, args=()): + return ConstantLiteral(value) + + +lv_font = LvFont() diff --git a/esphome/components/lvgl/lvcode.py b/esphome/components/lvgl/lvcode.py new file mode 100644 index 0000000000..13b4862b4d --- /dev/null +++ b/esphome/components/lvgl/lvcode.py @@ -0,0 +1,237 @@ +import abc +import logging +from typing import Union + +from esphome import codegen as cg +from esphome.core import ID, Lambda +from esphome.cpp_generator import ( + AssignmentExpression, + CallExpression, + Expression, + LambdaExpression, + Literal, + MockObj, + RawExpression, + RawStatement, + SafeExpType, + Statement, + VariableDeclarationExpression, + statement, +) + +from .helpers import get_line_marks + +_LOGGER = logging.getLogger(__name__) + + +class CodeContext(abc.ABC): + """ + A class providing a context for code generation. Generated code will be added to the + current context. A new context will stack on the current context, and restore it + when done. Used with the `with` statement. + """ + + code_context = None + + @abc.abstractmethod + def add(self, expression: Union[Expression, Statement]): + pass + + @staticmethod + def append(expression: Union[Expression, Statement]): + if CodeContext.code_context is not None: + CodeContext.code_context.add(expression) + return expression + + def __init__(self): + self.previous: Union[CodeContext | None] = None + + def __enter__(self): + self.previous = CodeContext.code_context + CodeContext.code_context = self + + def __exit__(self, *args): + CodeContext.code_context = self.previous + + +class MainContext(CodeContext): + """ + Code generation into the main() function + """ + + def add(self, expression: Union[Expression, Statement]): + return cg.add(expression) + + +class LvContext(CodeContext): + """ + Code generation into the LVGL initialisation code (called in `setup()`) + """ + + lv_init_code: list["Statement"] = [] + + @staticmethod + def lv_add(expression: Union[Expression, Statement]): + if isinstance(expression, Expression): + expression = statement(expression) + if not isinstance(expression, Statement): + raise ValueError( + f"Add '{expression}' must be expression or statement, not {type(expression)}" + ) + LvContext.lv_init_code.append(expression) + _LOGGER.debug("LV Adding: %s", expression) + return expression + + @staticmethod + def get_code(): + code = [] + for exp in LvContext.lv_init_code: + text = str(statement(exp)) + text = text.rstrip() + code.append(text) + return "\n".join(code) + "\n\n" + + def add(self, expression: Union[Expression, Statement]): + return LvContext.lv_add(expression) + + def set_style(self, prop): + return MockObj("lv_set_style_{prop}", "") + + +class LambdaContext(CodeContext): + """ + A context that will accumlate code for use in a lambda. + """ + + def __init__( + self, + parameters: list[tuple[SafeExpType, str]], + return_type: SafeExpType = None, + ): + super().__init__() + self.code_list: list[Statement] = [] + self.parameters = parameters + self.return_type = return_type + + def add(self, expression: Union[Expression, Statement]): + self.code_list.append(expression) + return expression + + async def code(self) -> LambdaExpression: + code_text = [] + for exp in self.code_list: + text = str(statement(exp)) + text = text.rstrip() + code_text.append(text) + return await cg.process_lambda( + Lambda("\n".join(code_text) + "\n\n"), + self.parameters, + return_type=self.return_type, + ) + + +class LocalVariable(MockObj): + """ + Create a local variable and enclose the code using it within a block. + """ + + def __init__(self, name, type, modifier=None, rhs=None): + base = ID(name, True, type) + super().__init__(base, "") + self.modifier = modifier + self.rhs = rhs + + def __enter__(self): + CodeContext.append(RawStatement("{")) + CodeContext.append( + VariableDeclarationExpression(self.base.type, self.modifier, self.base.id) + ) + if self.rhs is not None: + CodeContext.append(AssignmentExpression(None, "", self.base, self.rhs)) + return self.base + + def __exit__(self, *args): + CodeContext.append(RawStatement("}")) + + +class MockLv: + """ + A mock object that can be used to generate LVGL calls. + """ + + def __init__(self, base): + self.base = base + + def __getattr__(self, attr: str) -> "MockLv": + return MockLv(f"{self.base}{attr}") + + def append(self, expression): + CodeContext.append(expression) + + def __call__(self, *args: SafeExpType) -> "MockObj": + call = CallExpression(self.base, *args) + result = MockObj(call, "") + self.append(result) + return result + + def __str__(self): + return str(self.base) + + def __repr__(self): + return f"MockLv<{str(self.base)}>" + + def call(self, prop, *args): + call = CallExpression(RawExpression(f"{self.base}{prop}"), *args) + result = MockObj(call, "") + self.append(result) + return result + + def cond_if(self, expression: Expression): + CodeContext.append(RawExpression(f"if({expression}) {{")) + + def cond_else(self): + CodeContext.append(RawExpression("} else {")) + + def cond_endif(self): + CodeContext.append(RawExpression("}")) + + +class LvExpr(MockLv): + def __getattr__(self, attr: str) -> "MockLv": + return LvExpr(f"{self.base}{attr}") + + def append(self, expression): + pass + + +# Top level mock for generic lv_ calls to be recorded +lv = MockLv("lv_") +# Just generate an expression +lv_expr = LvExpr("lv_") +# Mock for lv_obj_ calls +lv_obj = MockLv("lv_obj_") + + +# equivalent to cg.add() for the lvgl init context +def lv_add(expression: Union[Expression, Statement]): + return CodeContext.append(expression) + + +def add_line_marks(where): + for mark in get_line_marks(where): + lv_add(cg.RawStatement(mark)) + + +def lv_assign(target, expression): + lv_add(RawExpression(f"{target} = {expression}")) + + +class ConstantLiteral(Literal): + __slots__ = ("constant",) + + def __init__(self, constant: str): + super().__init__() + self.constant = constant + + def __str__(self): + return self.constant diff --git a/esphome/components/lvgl/lvgl_esphome.cpp b/esphome/components/lvgl/lvgl_esphome.cpp new file mode 100644 index 0000000000..bdaf8a4f18 --- /dev/null +++ b/esphome/components/lvgl/lvgl_esphome.cpp @@ -0,0 +1,129 @@ +#include "esphome/core/defines.h" +#include "esphome/core/log.h" +#include "esphome/core/helpers.h" +#include "esphome/core/hal.h" +#include "lvgl_hal.h" +#include "lvgl_esphome.h" + +namespace esphome { +namespace lvgl { +static const char *const TAG = "lvgl"; + +lv_event_code_t lv_custom_event; // NOLINT +void LvglComponent::dump_config() { ESP_LOGCONFIG(TAG, "LVGL:"); } +void LvglComponent::draw_buffer_(const lv_area_t *area, const uint8_t *ptr) { + for (auto *display : this->displays_) { + display->draw_pixels_at(area->x1, area->y1, lv_area_get_width(area), lv_area_get_height(area), ptr, + display::COLOR_ORDER_RGB, LV_BITNESS, LV_COLOR_16_SWAP); + } +} + +void LvglComponent::flush_cb_(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p) { + auto now = millis(); + this->draw_buffer_(area, (const uint8_t *) 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); +} + +void LvglComponent::setup() { + ESP_LOGCONFIG(TAG, "LVGL Setup starts"); +#if LV_USE_LOG + lv_log_register_print_cb(log_cb); +#endif + lv_init(); + lv_custom_event = static_cast(lv_event_register_id()); + auto *display = this->displays_[0]; + size_t buffer_pixels = display->get_width() * display->get_height() / this->buffer_frac_; + auto buf_bytes = buffer_pixels * LV_COLOR_DEPTH / 8; + auto *buf = lv_custom_mem_alloc(buf_bytes); + if (buf == nullptr) { + ESP_LOGE(TAG, "Malloc failed to allocate %zu bytes", buf_bytes); + this->mark_failed(); + this->status_set_error("Memory allocation failure"); + return; + } + lv_disp_draw_buf_init(&this->draw_buf_, buf, nullptr, buffer_pixels); + 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; + switch (display->get_rotation()) { + case display::DISPLAY_ROTATION_0_DEGREES: + break; + case display::DISPLAY_ROTATION_90_DEGREES: + this->disp_drv_.sw_rotate = true; + this->disp_drv_.rotated = LV_DISP_ROT_90; + break; + case display::DISPLAY_ROTATION_180_DEGREES: + this->disp_drv_.sw_rotate = true; + this->disp_drv_.rotated = LV_DISP_ROT_180; + break; + case display::DISPLAY_ROTATION_270_DEGREES: + this->disp_drv_.sw_rotate = true; + this->disp_drv_.rotated = LV_DISP_ROT_270; + break; + } + display->set_rotation(display::DISPLAY_ROTATION_0_DEGREES); + this->disp_drv_.hor_res = (lv_coord_t) display->get_width(); + this->disp_drv_.ver_res = (lv_coord_t) display->get_height(); + ESP_LOGV(TAG, "sw_rotate = %d, rotated=%d", this->disp_drv_.sw_rotate, this->disp_drv_.rotated); + this->disp_ = lv_disp_drv_register(&this->disp_drv_); + for (const auto &v : this->init_lambdas_) + v(this->disp_); + lv_disp_trig_activity(this->disp_); + ESP_LOGCONFIG(TAG, "LVGL Setup complete"); +} +} // namespace lvgl +} // namespace esphome + +size_t lv_millis(void) { return esphome::millis(); } + +#if defined(USE_HOST) || defined(USE_RP2040) || defined(USE_ESP8266) +void *lv_custom_mem_alloc(size_t size) { + auto *ptr = malloc(size); // NOLINT + if (ptr == nullptr) { + esphome::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 +static unsigned cap_bits = MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT; // NOLINT + +void *lv_custom_mem_alloc(size_t size) { + void *ptr; + ptr = heap_caps_malloc(size, cap_bits); + if (ptr == nullptr) { + cap_bits = MALLOC_CAP_8BIT; + ptr = heap_caps_malloc(size, cap_bits); + } + if (ptr == nullptr) { + esphome::ESP_LOGE(esphome::lvgl::TAG, "Failed to allocate %zu bytes", size); + return nullptr; + } +#ifdef ESPHOME_LOG_HAS_VERBOSE + esphome::ESP_LOGV(esphome::lvgl::TAG, "allocate %zu - > %p", size, ptr); +#endif + return ptr; +} + +void lv_custom_mem_free(void *ptr) { +#ifdef ESPHOME_LOG_HAS_VERBOSE + esphome::ESP_LOGV(esphome::lvgl::TAG, "free %p", ptr); +#endif + if (ptr == nullptr) + return; + heap_caps_free(ptr); +} + +void *lv_custom_mem_realloc(void *ptr, size_t size) { +#ifdef ESPHOME_LOG_HAS_VERBOSE + esphome::ESP_LOGV(esphome::lvgl::TAG, "realloc %p: %zu", ptr, size); +#endif + return heap_caps_realloc(ptr, size, cap_bits); +} +#endif diff --git a/esphome/components/lvgl/lvgl_esphome.h b/esphome/components/lvgl/lvgl_esphome.h new file mode 100644 index 0000000000..988c22917b --- /dev/null +++ b/esphome/components/lvgl/lvgl_esphome.h @@ -0,0 +1,119 @@ +#pragma once +#include "esphome/core/defines.h" +#ifdef USE_LVGL + +// required for clang-tidy +#ifndef LV_CONF_H +#define LV_CONF_SKIP 1 // NOLINT +#endif + +#include "esphome/components/display/display.h" +#include "esphome/components/display/display_color_utils.h" +#include "esphome/core/component.h" +#include "esphome/core/hal.h" +#include "esphome/core/log.h" +#include +#include + +#ifdef USE_LVGL_FONT +#include "esphome/components/font/font.h" +#endif +namespace esphome { +namespace lvgl { + +extern lv_event_code_t lv_custom_event; // NOLINT +#ifdef USE_LVGL_COLOR +static lv_color_t lv_color_from(Color color) { return lv_color_make(color.red, color.green, color.blue); } +#endif +#if LV_COLOR_DEPTH == 16 +static const display::ColorBitness LV_BITNESS = display::ColorBitness::COLOR_BITNESS_565; +#elif LV_COLOR_DEPTH == 32 +static const display::ColorBitness LV_BITNESS = display::ColorBitness::COLOR_BITNESS_888; +#else +static const display::ColorBitness LV_BITNESS = display::ColorBitness::COLOR_BITNESS_332; +#endif + +// Parent class for things that wrap an LVGL object +class LvCompound { + public: + virtual void set_obj(lv_obj_t *lv_obj) { this->obj = lv_obj; } + lv_obj_t *obj{}; +}; + +using LvLambdaType = std::function; +using set_value_lambda_t = std::function; +using event_callback_t = void(_lv_event_t *); +using text_lambda_t = std::function; + +#ifdef USE_LVGL_FONT +class FontEngine { + public: + FontEngine(font::Font *esp_font); + const lv_font_t *get_lv_font(); + + const font::GlyphData *get_glyph_data(uint32_t unicode_letter); + uint16_t baseline{}; + uint16_t height{}; + uint8_t bpp{}; + + protected: + font::Font *font_{}; + uint32_t last_letter_{}; + const font::GlyphData *last_data_{}; + lv_font_t lv_font_{}; +}; +#endif // USE_LVGL_FONT + +class LvglComponent : public PollingComponent { + constexpr static const char *const TAG = "lvgl"; + + public: + static void static_flush_cb(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p) { + reinterpret_cast(disp_drv->user_data)->flush_cb_(disp_drv, area, color_p); + } + + float get_setup_priority() const override { return setup_priority::PROCESSOR; } + static void log_cb(const char *buf) { + esp_log_printf_(ESPHOME_LOG_LEVEL_INFO, TAG, 0, "%.*s", (int) strlen(buf) - 1, buf); + } + static void rounder_cb(lv_disp_drv_t *disp_drv, lv_area_t *area) { + // make sure all coordinates are even + if (area->x1 & 1) + area->x1--; + if (!(area->x2 & 1)) + area->x2++; + if (area->y1 & 1) + area->y1--; + if (!(area->y2 & 1)) + area->y2++; + } + + void loop() override { lv_timer_handler_run_in_period(5); } + void setup() override; + + void update() override {} + + void add_display(display::Display *display) { this->displays_.push_back(display); } + void add_init_lambda(const std::function &lamb) { this->init_lambdas_.push_back(lamb); } + void dump_config() override; + void set_full_refresh(bool full_refresh) { this->full_refresh_ = full_refresh; } + void set_buffer_frac(size_t frac) { this->buffer_frac_ = frac; } + lv_disp_t *get_disp() { return this->disp_; } + + protected: + void draw_buffer_(const lv_area_t *area, const uint8_t *ptr); + void flush_cb_(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p); + std::vector displays_{}; + lv_disp_draw_buf_t draw_buf_{}; + lv_disp_drv_t disp_drv_{}; + lv_disp_t *disp_{}; + + std::vector> init_lambdas_; + size_t buffer_frac_{1}; + bool full_refresh_{}; +}; + +} // namespace lvgl +} // namespace esphome + +#endif diff --git a/esphome/components/lvgl/lvgl_hal.h b/esphome/components/lvgl/lvgl_hal.h new file mode 100644 index 0000000000..754cc70391 --- /dev/null +++ b/esphome/components/lvgl/lvgl_hal.h @@ -0,0 +1,21 @@ +// +// Created by Clyde Stubbs on 20/9/2023. +// + +#pragma once + +#ifdef __cplusplus +#define EXTERNC extern "C" +#include +namespace esphome { +namespace lvgl {} +} // namespace esphome +#else +#define EXTERNC extern +#include +#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/obj.py b/esphome/components/lvgl/obj.py new file mode 100644 index 0000000000..fba20bef36 --- /dev/null +++ b/esphome/components/lvgl/obj.py @@ -0,0 +1,22 @@ +from .defines import CONF_OBJ +from .types import lv_obj_t +from .widget import WidgetType + + +class ObjType(WidgetType): + """ + The base LVGL object. All other widgets inherit from this. + """ + + def __init__(self): + super().__init__(CONF_OBJ, schema={}, modify_schema={}) + + @property + def w_type(self): + return lv_obj_t + + async def to_code(self, w, config): + return [] + + +obj_spec = ObjType() diff --git a/esphome/components/lvgl/schemas.py b/esphome/components/lvgl/schemas.py new file mode 100644 index 0000000000..4ae5824151 --- /dev/null +++ b/esphome/components/lvgl/schemas.py @@ -0,0 +1,260 @@ +from esphome import config_validation as cv +from esphome.const import CONF_ARGS, CONF_FORMAT, CONF_ID, CONF_STATE, CONF_TYPE +from esphome.schema_extractors import SCHEMA_EXTRACT + +from . import defines as df, lv_validation as lvalid, types as ty +from .defines import WIDGET_PARTS +from .helpers import ( + REQUIRED_COMPONENTS, + add_lv_use, + requires_component, + validate_printf, +) +from .lv_validation import lv_font +from .types import WIDGET_TYPES, get_widget_type + +# A schema for text properties +TEXT_SCHEMA = cv.Schema( + { + cv.Optional(df.CONF_TEXT): cv.Any( + cv.All( + cv.Schema( + { + cv.Required(CONF_FORMAT): cv.string, + cv.Optional(CONF_ARGS, default=list): cv.ensure_list( + cv.lambda_ + ), + }, + ), + validate_printf, + ), + lvalid.lv_text, + ) + } +) + +# All LVGL styles and their validators +STYLE_PROPS = { + "align": df.CHILD_ALIGNMENTS.one_of, + "arc_opa": lvalid.opacity, + "arc_color": lvalid.lv_color, + "arc_rounded": lvalid.lv_bool, + "arc_width": cv.positive_int, + "anim_time": lvalid.lv_milliseconds, + "bg_color": lvalid.lv_color, + "bg_grad_color": lvalid.lv_color, + "bg_dither_mode": df.LvConstant("LV_DITHER_", "NONE", "ORDERED", "ERR_DIFF").one_of, + "bg_grad_dir": df.LvConstant("LV_GRAD_DIR_", "NONE", "HOR", "VER").one_of, + "bg_grad_stop": lvalid.stop_value, + "bg_img_opa": lvalid.opacity, + "bg_img_recolor": lvalid.lv_color, + "bg_img_recolor_opa": lvalid.opacity, + "bg_main_stop": lvalid.stop_value, + "bg_opa": lvalid.opacity, + "border_color": lvalid.lv_color, + "border_opa": lvalid.opacity, + "border_post": lvalid.lv_bool, + "border_side": df.LvConstant( + "LV_BORDER_SIDE_", "NONE", "TOP", "BOTTOM", "LEFT", "RIGHT", "INTERNAL" + ).several_of, + "border_width": cv.positive_int, + "clip_corner": lvalid.lv_bool, + "height": lvalid.size, + "img_recolor": lvalid.lv_color, + "img_recolor_opa": lvalid.opacity, + "line_width": cv.positive_int, + "line_dash_width": cv.positive_int, + "line_dash_gap": cv.positive_int, + "line_rounded": lvalid.lv_bool, + "line_color": lvalid.lv_color, + "opa": lvalid.opacity, + "opa_layered": lvalid.opacity, + "outline_color": lvalid.lv_color, + "outline_opa": lvalid.opacity, + "outline_pad": lvalid.size, + "outline_width": lvalid.size, + "pad_all": lvalid.size, + "pad_bottom": lvalid.size, + "pad_column": lvalid.size, + "pad_left": lvalid.size, + "pad_right": lvalid.size, + "pad_row": lvalid.size, + "pad_top": lvalid.size, + "shadow_color": lvalid.lv_color, + "shadow_ofs_x": cv.int_, + "shadow_ofs_y": cv.int_, + "shadow_opa": lvalid.opacity, + "shadow_spread": cv.int_, + "shadow_width": cv.positive_int, + "text_align": df.LvConstant( + "LV_TEXT_ALIGN_", "LEFT", "CENTER", "RIGHT", "AUTO" + ).one_of, + "text_color": lvalid.lv_color, + "text_decor": df.LvConstant( + "LV_TEXT_DECOR_", "NONE", "UNDERLINE", "STRIKETHROUGH" + ).several_of, + "text_font": lv_font, + "text_letter_space": cv.positive_int, + "text_line_space": cv.positive_int, + "text_opa": lvalid.opacity, + "transform_angle": lvalid.angle, + "transform_height": lvalid.pixels_or_percent, + "transform_pivot_x": lvalid.pixels_or_percent, + "transform_pivot_y": lvalid.pixels_or_percent, + "transform_zoom": lvalid.zoom, + "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": cv.Any(lvalid.size, df.LvConstant("LV_RADIUS_", "CIRCLE").one_of), + "width": lvalid.size, + "x": lvalid.pixels_or_percent, + "y": lvalid.pixels_or_percent, +} + +# Complete object style schema +STYLE_SCHEMA = cv.Schema({cv.Optional(k): v for k, v in STYLE_PROPS.items()}).extend( + { + cv.Optional(df.CONF_SCROLLBAR_MODE): df.LvConstant( + "LV_SCROLLBAR_MODE_", "OFF", "ON", "ACTIVE", "AUTO" + ).one_of, + } +) + +# Object states. Top level properties apply to MAIN +STATE_SCHEMA = cv.Schema( + {cv.Optional(state): STYLE_SCHEMA for state in df.STATES} +).extend(STYLE_SCHEMA) +# Setting object states +SET_STATE_SCHEMA = cv.Schema( + {cv.Optional(state): lvalid.lv_bool for state in df.STATES} +) +# Setting object flags +FLAG_SCHEMA = cv.Schema({cv.Optional(flag): cv.boolean for flag in df.OBJ_FLAGS}) +FLAG_LIST = cv.ensure_list(df.LvConstant("LV_OBJ_FLAG_", *df.OBJ_FLAGS).one_of) + + +def part_schema(widget_type): + """ + Generate a schema for the various parts (e.g. main:, indicator:) of a widget type + :param widget_type: The type of widget to generate for + :return: + """ + parts = WIDGET_PARTS.get(widget_type) + if parts is None: + parts = (df.CONF_MAIN,) + return cv.Schema({cv.Optional(part): STATE_SCHEMA for part in parts}).extend( + STATE_SCHEMA + ) + + +def obj_schema(widget_type: str): + """ + Create a schema for a widget type itself i.e. no allowance for children + :param widget_type: + :return: + """ + return ( + part_schema(widget_type) + .extend(FLAG_SCHEMA) + .extend(ALIGN_TO_SCHEMA) + .extend( + cv.Schema( + { + cv.Optional(CONF_STATE): SET_STATE_SCHEMA, + } + ) + ) + ) + + +ALIGN_TO_SCHEMA = { + cv.Optional(df.CONF_ALIGN_TO): cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(ty.lv_obj_t), + cv.Required(df.CONF_ALIGN): df.ALIGN_ALIGNMENTS.one_of, + cv.Optional(df.CONF_X, default=0): lvalid.pixels_or_percent, + cv.Optional(df.CONF_Y, default=0): lvalid.pixels_or_percent, + } + ) +} + + +# A style schema that can include text +STYLED_TEXT_SCHEMA = cv.maybe_simple_value( + STYLE_SCHEMA.extend(TEXT_SCHEMA), key=df.CONF_TEXT +) + + +ALL_STYLES = { + **STYLE_PROPS, +} + + +def container_validator(schema, widget_type): + """ + Create a validator for a container given the widget type + :param schema: Base schema to extend + :param widget_type: + :return: + """ + + def validator(value): + result = schema + if w_sch := WIDGET_TYPES[widget_type].schema: + result = result.extend(w_sch) + if value and (layout := value.get(df.CONF_LAYOUT)): + if not isinstance(layout, dict): + raise cv.Invalid("Layout value must be a dict") + ltype = layout.get(CONF_TYPE) + add_lv_use(ltype) + if value == SCHEMA_EXTRACT: + return result + return result(value) + + return validator + + +def container_schema(widget_type, extras=None): + """ + Create a schema for a container widget of a given type. All obj properties are available, plus + the extras passed in, plus any defined for the specific widget being specified. + :param widget_type: The widget type, e.g. "img" + :param extras: Additional options to be made available, e.g. layout properties for children + :return: The schema for this type of widget. + """ + lv_type = get_widget_type(widget_type) + schema = obj_schema(widget_type).extend({cv.GenerateID(): cv.declare_id(lv_type)}) + if extras: + schema = schema.extend(extras) + # Delayed evaluation for recursion + return container_validator(schema, widget_type) + + +def widget_schema(widget_type, extras=None): + """ + Create a schema for a given widget type + :param widget_type: The name of the widget + :param extras: + :return: + """ + validator = container_schema(widget_type, extras=extras) + if required := REQUIRED_COMPONENTS.get(widget_type): + validator = cv.All(validator, requires_component(required)) + return cv.Exclusive(widget_type, df.CONF_WIDGETS), validator + + +# All widget schemas must be defined before this is called. + + +def any_widget_schema(extras=None): + """ + Generate schemas for all possible LVGL widgets. This is what implements the ability to have a list of any kind of + widget under the widgets: key. + + :param extras: Additional schema to be applied to each generated one + :return: + """ + return cv.Any(dict(widget_schema(wt, extras) for wt in WIDGET_PARTS)) diff --git a/esphome/components/lvgl/types.py b/esphome/components/lvgl/types.py new file mode 100644 index 0000000000..3c043d266d --- /dev/null +++ b/esphome/components/lvgl/types.py @@ -0,0 +1,64 @@ +from esphome import codegen as cg +from esphome.core import ID + +from .defines import CONF_LABEL, CONF_OBJ, CONF_TEXT + +uint16_t_ptr = cg.uint16.operator("ptr") +lvgl_ns = cg.esphome_ns.namespace("lvgl") +char_ptr = cg.global_ns.namespace("char").operator("ptr") +void_ptr = cg.void.operator("ptr") +LvglComponent = lvgl_ns.class_("LvglComponent", cg.PollingComponent) +lv_event_code_t = cg.global_ns.namespace("lv_event_code_t") +FontEngine = lvgl_ns.class_("FontEngine") +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") +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_ptr = cg.global_ns.struct("lv_disp_t").operator("ptr") +lv_color_t = cg.global_ns.struct("lv_color_t") + + +# this will be populated later, in __init__.py to avoid circular imports. +WIDGET_TYPES: dict = {} + + +class LvType(cg.MockObjClass): + def __init__(self, *args, **kwargs): + parens = kwargs.pop("parents", ()) + super().__init__(*args, parents=parens + (lv_obj_base_t,)) + self.args = kwargs.pop("largs", [(lv_obj_t_ptr, "obj")]) + self.value = kwargs.pop("lvalue", lambda w: w.obj) + self.has_on_value = kwargs.pop("has_on_value", False) + self.value_property = None + + def get_arg_type(self): + return self.args[0][0] if len(self.args) else None + + +class LvText(LvType): + def __init__(self, *args, **kwargs): + super().__init__( + *args, + largs=[(cg.std_string, "text")], + lvalue=lambda w: w.get_property("text")[0], + **kwargs, + ) + self.value_property = CONF_TEXT + + +lv_obj_t = LvType("lv_obj_t") +lv_label_t = LvText("lv_label_t") + +LV_TYPES = { + CONF_LABEL: lv_label_t, + CONF_OBJ: lv_obj_t, +} + + +def get_widget_type(typestr: str) -> LvType: + return LV_TYPES[typestr] + + +CUSTOM_EVENT = ID("lv_custom_event", False, type=lv_event_code_t) diff --git a/esphome/components/lvgl/widget.py b/esphome/components/lvgl/widget.py new file mode 100644 index 0000000000..44f277f1c3 --- /dev/null +++ b/esphome/components/lvgl/widget.py @@ -0,0 +1,347 @@ +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_GROUP, CONF_ID, CONF_STATE +from esphome.core import ID, TimePeriod +from esphome.coroutine import FakeAwaitable +from esphome.cpp_generator import MockObjClass + +from .defines import ( + CONF_DEFAULT, + CONF_MAIN, + CONF_SCROLLBAR_MODE, + CONF_WIDGETS, + OBJ_FLAGS, + PARTS, + STATES, + LValidator, + join_enums, +) +from .helpers import add_lv_use +from .lvcode import ConstantLiteral, add_line_marks, lv, lv_add, lv_assign, lv_obj +from .schemas import ALL_STYLES +from .types import WIDGET_TYPES, LvCompound, lv_obj_t + +EVENT_LAMB = "event_lamb__" + + +class WidgetType: + """ + Describes a type of Widget, e.g. "bar" or "line" + """ + + def __init__(self, name, schema=None, modify_schema=None): + """ + :param name: The widget name, e.g. "bar" + :param schema: The config schema for defining a widget + :param modify_schema: A schema to update the widget + """ + self.name = name + self.schema = schema or {} + if modify_schema is None: + self.modify_schema = schema + else: + self.modify_schema = modify_schema + + @property + def animated(self): + return False + + @property + def w_type(self): + """ + Get the type associated with this widget + :return: + """ + return lv_obj_t + + 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 + :return: Generated code as a list of text lines + """ + raise NotImplementedError(f"No to_code defined for {self.name}") + + 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 f"lv_{self.name}_create({parent})" + + def get_uses(self): + """ + Get a list of other widgets used by this one + :return: + """ + return () + + +class LvScrActType(WidgetType): + """ + A "widget" representing the active screen. + """ + + def __init__(self): + super().__init__("lv_scr_act()") + + def obj_creator(self, parent: MockObjClass, config: dict): + return [] + + async def to_code(self, w, config: dict): + return [] + + +class Widget: + """ + Represents a Widget. + """ + + widgets_completed = False + + @staticmethod + def set_completed(): + Widget.widgets_completed = True + + def __init__(self, var, wtype: WidgetType, config: dict = None, parent=None): + self.var = var + self.type = wtype + self.config = config + self.scale = 1.0 + self.step = 1.0 + self.range_from = -sys.maxsize + self.range_to = sys.maxsize + self.parent = parent + + @staticmethod + def create(name, var, wtype: WidgetType, config: dict = None, parent=None): + w = Widget(var, wtype, config, parent) + if name is not None: + widget_map[name] = w + return w + + @property + def obj(self): + if self.type.is_compound(): + return f"{self.var}->obj" + return self.var + + def add_state(self, *args): + return lv_obj.add_state(self.obj, *args) + + def clear_state(self, *args): + return lv_obj.clear_state(self.obj, *args) + + def add_flag(self, *args): + return lv_obj.add_flag(self.obj, *args) + + def clear_flag(self, *args): + return lv_obj.clear_flag(self.obj, *args) + + def set_property(self, prop, value, animated: bool = None, ltype=None): + if isinstance(value, dict): + value = value.get(prop) + if value is None: + return + if isinstance(value, TimePeriod): + value = value.total_milliseconds + ltype = ltype or self.__type_base() + if animated is None or self.type.animated is not True: + lv.call(f"{ltype}_set_{prop}", self.obj, value) + else: + lv.call( + f"{ltype}_set_{prop}", + self.obj, + value, + "LV_ANIM_ON" if animated else "LV_ANIM_OFF", + ) + + def get_property(self, prop, ltype=None): + ltype = ltype or self.__type_base() + return f"lv_{ltype}_get_{prop}({self.obj})" + + def set_style(self, prop, value, state): + if value is None: + return [] + return lv.call(f"obj_set_style_{prop}", self.obj, value, state) + + def __type_base(self): + wtype = self.type.w_type + base = str(wtype) + if base.startswith("Lv"): + return f"{wtype}".removeprefix("Lv").removesuffix("Type").lower() + return f"{wtype}".removeprefix("lv_").removesuffix("_t") + + def __str__(self): + return f"({self.var}, {self.type})" + + +# Map of widgets to their config, used for trigger generation +widget_map: dict[Any, Widget] = {} + + +def get_widget_generator(wid): + """ + Used to wait for a widget during code generation. + :param wid: + :return: + """ + while True: + if obj := widget_map.get(wid): + return obj + if Widget.widgets_completed: + raise Invalid( + f"Widget {wid} not found, yet all widgets should be defined by now" + ) + yield + + +async def get_widget(wid: ID) -> Widget: + if obj := widget_map.get(wid): + return obj + return await FakeAwaitable(get_widget_generator(wid)) + + +def collect_props(config): + """ + Collect all properties from a configuration + :param config: + :return: + """ + props = {} + for prop in [*ALL_STYLES, *OBJ_FLAGS, CONF_GROUP]: + if prop in config: + props[prop] = config[prop] + return props + + +def collect_states(config): + """ + Collect prperties for each state of a widget + :param config: + :return: + """ + states = {CONF_DEFAULT: collect_props(config)} + for state in STATES: + if state in config: + states[state] = collect_props(config[state]) + return states + + +def collect_parts(config): + """ + Collect properties and states for all widget parts + :param config: + :return: + """ + parts = {CONF_MAIN: collect_states(config)} + for part in PARTS: + if part in config: + parts[part] = collect_states(config[part]) + return parts + + +async def set_obj_properties(w: Widget, config): + """Generate a list of C++ statements to apply properties to an lv_obj_t""" + parts = collect_parts(config) + for part, states in parts.items(): + for state, props in states.items(): + lv_state = ConstantLiteral( + f"(int)LV_STATE_{state.upper()}|(int)LV_PART_{part.upper()}" + ) + 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) + w.set_style(prop, value, lv_state) + flag_clr = set() + flag_set = set() + props = parts[CONF_MAIN][CONF_DEFAULT] + for prop, value in {k: v for k, v in props.items() if k in OBJ_FLAGS}.items(): + if value: + flag_set.add(prop) + else: + flag_clr.add(prop) + if flag_set: + adds = join_enums(flag_set, "LV_OBJ_FLAG_") + w.add_flag(adds) + if flag_clr: + clrs = join_enums(flag_clr, "LV_OBJ_FLAG_") + w.clear_flag(clrs) + + if states := config.get(CONF_STATE): + adds = set() + clears = set() + lambs = {} + for key, value in states.items(): + if isinstance(value, cv.Lambda): + lambs[key] = value + elif value == "true": + adds.add(key) + else: + clears.add(key) + if adds: + adds = ConstantLiteral(join_enums(adds, "LV_STATE_")) + w.add_state(adds) + if clears: + clears = ConstantLiteral(join_enums(clears, "LV_STATE_")) + w.clear_state(clears) + for key, value in lambs.items(): + lamb = await cg.process_lambda(value, [], return_type=cg.bool_) + state = ConstantLiteral(f"LV_STATE_{key.upper}") + lv.cond_if(lamb) + w.add_state(state) + lv.cond_else() + w.clear_state(state) + lv.cond_endif() + if scrollbar_mode := config.get(CONF_SCROLLBAR_MODE): + lv_obj.set_scrollbar_mode(w.obj, scrollbar_mode) + + +async def add_widgets(parent: Widget, config: dict): + """ + Add all widgets to an object + :param parent: The enclosing obj + :param config: The configuration + :return: + """ + for w in config.get(CONF_WIDGETS) or (): + w_type, w_cnfig = next(iter(w.items())) + await widget_to_code(w_cnfig, w_type, parent.obj) + + +async def widget_to_code(w_cnfig, w_type, parent): + """ + Converts a Widget definition to C code. + :param w_cnfig: The widget configuration + :param w_type: The Widget type + :param parent: The parent to which the widget should be added + :return: + """ + spec: WidgetType = WIDGET_TYPES[w_type] + creator = 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)) + else: + var = cg.Pvariable(wid, cg.nullptr, type_=lv_obj_t) + lv_assign(var, creator) + + widget = Widget.create(wid, var, spec, w_cnfig, parent) + await set_obj_properties(widget, w_cnfig) + await add_widgets(widget, w_cnfig) + await spec.to_code(widget, w_cnfig) diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 4831ed2c9e..9d453260ab 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -38,6 +38,9 @@ #define USE_LIGHT #define USE_LOCK #define USE_LOGGER +#define USE_LVGL +#define USE_LVGL_FONT +#define USE_LVGL_IMAGE #define USE_MDNS #define USE_MEDIA_PLAYER #define USE_MQTT diff --git a/platformio.ini b/platformio.ini index fc7f35b6c3..baf0a85d73 100644 --- a/platformio.ini +++ b/platformio.ini @@ -42,6 +42,7 @@ lib_deps = pavlodn/HaierProtocol@0.9.31 ; haier ; 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 build_flags = -DESPHOME_LOG_LEVEL=ESPHOME_LOG_LEVEL_VERY_VERBOSE src_filter = diff --git a/tests/components/lvgl/common.yaml b/tests/components/lvgl/common.yaml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/components/lvgl/lvgl-package.yaml b/tests/components/lvgl/lvgl-package.yaml new file mode 100644 index 0000000000..856e7c3e9d --- /dev/null +++ b/tests/components/lvgl/lvgl-package.yaml @@ -0,0 +1,24 @@ +color: + - id: light_blue + hex: "3340FF" + +lvgl: + bg_color: light_blue + widgets: + - label: + text: Hello world + text_color: 0xFF8000 + align: center + text_font: montserrat_40 + border_post: true + + - label: + text: "Hello shiny day" + text_color: 0xFFFFFF + align: bottom_mid + text_font: space16 + +font: + - file: "gfonts://Roboto" + id: space16 + bpp: 4 diff --git a/tests/components/lvgl/test.esp32-ard.yaml b/tests/components/lvgl/test.esp32-ard.yaml new file mode 100644 index 0000000000..abfb324ea5 --- /dev/null +++ b/tests/components/lvgl/test.esp32-ard.yaml @@ -0,0 +1,30 @@ +spi: + clk_pin: 14 + mosi_pin: 13 + +i2c: + sda: GPIO18 + scl: GPIO19 + +display: + - platform: ili9xxx + model: st7789v + id: tft_display + dimensions: + width: 240 + height: 320 + transform: + swap_xy: false + mirror_x: true + mirror_y: true + data_rate: 80MHz + cs_pin: GPIO22 + dc_pin: GPIO21 + auto_clear_enabled: false + invert_colors: false + update_interval: never + +packages: + lvgl: !include lvgl-package.yaml + +<<: !include common.yaml diff --git a/tests/components/lvgl/test.esp32-idf.yaml b/tests/components/lvgl/test.esp32-idf.yaml new file mode 100644 index 0000000000..f159431b99 --- /dev/null +++ b/tests/components/lvgl/test.esp32-idf.yaml @@ -0,0 +1,52 @@ +spi: + clk_pin: 14 + mosi_pin: 13 + +i2c: + sda: GPIO18 + scl: GPIO19 + +display: + - platform: ili9xxx + model: st7789v + id: second_display + dimensions: + width: 240 + height: 320 + transform: + swap_xy: false + mirror_x: true + mirror_y: true + data_rate: 80MHz + cs_pin: GPIO20 + dc_pin: GPIO15 + auto_clear_enabled: false + invert_colors: false + update_interval: never + + - platform: ili9xxx + model: st7789v + id: tft_display + dimensions: + width: 240 + height: 320 + transform: + swap_xy: false + mirror_x: true + mirror_y: true + data_rate: 80MHz + cs_pin: GPIO22 + dc_pin: GPIO21 + auto_clear_enabled: false + invert_colors: false + update_interval: never + +packages: + lvgl: !include lvgl-package.yaml + +lvgl: + displays: + - tft_display + - second_display + +<<: !include common.yaml From d3f2434c57034c0cac30c997f80850df59e40028 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 24 Jul 2024 19:45:42 -0500 Subject: [PATCH 1825/2101] Bump aioesphomeapi to 24.6.2 and cryptography to 43.0.0 (#7131) --- requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 0cbe5e7265..3e658de8ad 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ async_timeout==4.0.3; python_version <= "3.10" -cryptography==42.0.2 +cryptography==43.0.0 voluptuous==0.14.2 PyYAML==6.0.1 paho-mqtt==1.6.1 @@ -13,7 +13,7 @@ platformio==6.1.15 # When updating platformio, also update Dockerfile esptool==4.7.0 click==8.1.7 esphome-dashboard==20240620.0 -aioesphomeapi==24.3.0 +aioesphomeapi==24.6.2 zeroconf==0.132.2 python-magic==0.4.27 ruamel.yaml==0.18.6 # dashboard_import From f61582f82600b26e5747afe5b5f1f5b642a47ee6 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 25 Jul 2024 13:19:33 +1200 Subject: [PATCH 1826/2101] [dependabot] Group docker action bumps into single PR (#7133) --- .github/dependabot.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 3b6495653b..bb35f16048 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -13,6 +13,13 @@ updates: schedule: interval: daily open-pull-requests-limit: 10 + groups: + docker-actions: + applies-to: version-updates + patterns: + - "docker/setup-qemu-action" + - "docker/login-action" + - "docker/setup-buildx-action" - package-ecosystem: github-actions directory: "/.github/actions/build-image" schedule: From 39c0019534f5e6aa67d2e71f69a04d8c3ff28343 Mon Sep 17 00:00:00 2001 From: thevogoncoder <6619878+thevogoncoder@users.noreply.github.com> Date: Thu, 25 Jul 2024 04:06:23 +0200 Subject: [PATCH 1827/2101] Add delay after sending REG_READ_START (#7130) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/pmwcs3/pmwcs3.cpp | 61 ++++++++++++++-------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/esphome/components/pmwcs3/pmwcs3.cpp b/esphome/components/pmwcs3/pmwcs3.cpp index 812018b52e..97ce4c9ae0 100644 --- a/esphome/components/pmwcs3/pmwcs3.cpp +++ b/esphome/components/pmwcs3/pmwcs3.cpp @@ -72,43 +72,44 @@ void PMWCS3Component::dump_config() { LOG_SENSOR(" ", "vwc", this->vwc_sensor_); } void PMWCS3Component::read_data_() { - uint8_t data[8]; - float e25, ec, temperature, vwc; - /////// Super important !!!! first activate reading PMWCS3_REG_READ_START (if not, return always the same values) //// - if (!this->write_bytes(PMWCS3_REG_READ_START, nullptr, 0)) { this->status_set_warning(); ESP_LOGVV(TAG, "Failed to write into REG_READ_START register !!!"); return; } - // NOLINT delay(100); - if (!this->read_bytes(PMWCS3_REG_GET_DATA, (uint8_t *) &data, 8)) { - ESP_LOGVV(TAG, "Error reading PMWCS3_REG_GET_DATA registers"); - this->mark_failed(); - return; - } - if (this->e25_sensor_ != nullptr) { - e25 = ((data[1] << 8) | data[0]) / 100.0; - this->e25_sensor_->publish_state(e25); - ESP_LOGVV(TAG, "e25: data[0]=%d, data[1]=%d, result=%f", data[0], data[1], e25); - } - if (this->ec_sensor_ != nullptr) { - ec = ((data[3] << 8) | data[2]) / 10.0; - this->ec_sensor_->publish_state(ec); - ESP_LOGVV(TAG, "ec: data[2]=%d, data[3]=%d, result=%f", data[2], data[3], ec); - } - if (this->temperature_sensor_ != nullptr) { - temperature = ((data[5] << 8) | data[4]) / 100.0; - this->temperature_sensor_->publish_state(temperature); - ESP_LOGVV(TAG, "temp: data[4]=%d, data[5]=%d, result=%f", data[4], data[5], temperature); - } - if (this->vwc_sensor_ != nullptr) { - vwc = ((data[7] << 8) | data[6]) / 10.0; - this->vwc_sensor_->publish_state(vwc); - ESP_LOGVV(TAG, "vwc: data[6]=%d, data[7]=%d, result=%f", data[6], data[7], vwc); - } + // Wait for the sensor to be ready. + // 80ms empirically determined (conservative). + this->set_timeout(80, [this] { + uint8_t data[8]; + float e25, ec, temperature, vwc; + if (!this->read_bytes(PMWCS3_REG_GET_DATA, (uint8_t *) &data, 8)) { + ESP_LOGVV(TAG, "Error reading PMWCS3_REG_GET_DATA registers"); + this->mark_failed(); + return; + } + if (this->e25_sensor_ != nullptr) { + e25 = ((data[1] << 8) | data[0]) / 100.0; + this->e25_sensor_->publish_state(e25); + ESP_LOGVV(TAG, "e25: data[0]=%d, data[1]=%d, result=%f", data[0], data[1], e25); + } + if (this->ec_sensor_ != nullptr) { + ec = ((data[3] << 8) | data[2]) / 10.0; + this->ec_sensor_->publish_state(ec); + ESP_LOGVV(TAG, "ec: data[2]=%d, data[3]=%d, result=%f", data[2], data[3], ec); + } + if (this->temperature_sensor_ != nullptr) { + temperature = ((data[5] << 8) | data[4]) / 100.0; + this->temperature_sensor_->publish_state(temperature); + ESP_LOGVV(TAG, "temp: data[4]=%d, data[5]=%d, result=%f", data[4], data[5], temperature); + } + if (this->vwc_sensor_ != nullptr) { + vwc = ((data[7] << 8) | data[6]) / 10.0; + this->vwc_sensor_->publish_state(vwc); + ESP_LOGVV(TAG, "vwc: data[6]=%d, data[7]=%d, result=%f", data[6], data[7], vwc); + } + }); } } // namespace pmwcs3 From adfec578cfd301ee0295bd1dec6a649ff98fcb8b Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 29 Jul 2024 13:13:09 +1200 Subject: [PATCH 1828/2101] Add ``--version`` handler to cli (#7150) --- esphome/__main__.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/esphome/__main__.py b/esphome/__main__.py index b13f96daf7..9e7b7fa15b 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -747,7 +747,14 @@ def parse_args(argv): ) parser = argparse.ArgumentParser( - description=f"ESPHome v{const.__version__}", parents=[options_parser] + description=f"ESPHome {const.__version__}", parents=[options_parser] + ) + + parser.add_argument( + "--version", + action="version", + version=f"Version: {const.__version__}", + help="Print the ESPHome version and exit.", ) mqtt_options = argparse.ArgumentParser(add_help=False) From acf690c87d362b37dc3b8910bcc7ffd4882bc2f2 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 29 Jul 2024 14:05:41 +1200 Subject: [PATCH 1829/2101] [code-quality] Organise ethernet related imports (#7152) --- esphome/components/ethernet/__init__.py | 36 +++++++++---------- .../components/ethernet_info/text_sensor.py | 4 +-- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/esphome/components/ethernet/__init__.py b/esphome/components/ethernet/__init__.py index 697436415b..1c6acda724 100644 --- a/esphome/components/ethernet/__init__.py +++ b/esphome/components/ethernet/__init__.py @@ -1,6 +1,4 @@ from esphome import pins -import esphome.config_validation as cv -import esphome.final_validate as fv import esphome.codegen as cg from esphome.components.esp32 import add_idf_sdkconfig_option, get_esp32_variant from esphome.components.esp32.const import ( @@ -8,31 +6,33 @@ from esphome.components.esp32.const import ( VARIANT_ESP32S2, VARIANT_ESP32S3, ) +from esphome.components.network import IPAddress +from esphome.components.spi import CONF_INTERFACE_INDEX, get_spi_interface +import esphome.config_validation as cv from esphome.const import ( - CONF_DOMAIN, - CONF_ID, - CONF_VALUE, - CONF_MANUAL_IP, - CONF_STATIC_IP, - CONF_TYPE, - CONF_USE_ADDRESS, - CONF_GATEWAY, - CONF_SUBNET, + CONF_ADDRESS, + CONF_CLK_PIN, + CONF_CS_PIN, CONF_DNS1, CONF_DNS2, - CONF_CLK_PIN, + CONF_DOMAIN, + CONF_GATEWAY, + CONF_ID, + CONF_INTERRUPT_PIN, + CONF_MANUAL_IP, CONF_MISO_PIN, CONF_MOSI_PIN, - CONF_CS_PIN, - CONF_INTERRUPT_PIN, + CONF_PAGE_ID, CONF_RESET_PIN, CONF_SPI, - CONF_PAGE_ID, - CONF_ADDRESS, + CONF_STATIC_IP, + CONF_SUBNET, + CONF_TYPE, + CONF_USE_ADDRESS, + CONF_VALUE, ) from esphome.core import CORE, coroutine_with_priority -from esphome.components.network import IPAddress -from esphome.components.spi import get_spi_interface, CONF_INTERFACE_INDEX +import esphome.final_validate as fv CONFLICTS_WITH = ["wifi"] DEPENDENCIES = ["esp32"] diff --git a/esphome/components/ethernet_info/text_sensor.py b/esphome/components/ethernet_info/text_sensor.py index a545475870..31da516e44 100644 --- a/esphome/components/ethernet_info/text_sensor.py +++ b/esphome/components/ethernet_info/text_sensor.py @@ -1,9 +1,9 @@ import esphome.codegen as cg -import esphome.config_validation as cv from esphome.components import text_sensor +import esphome.config_validation as cv from esphome.const import ( - CONF_IP_ADDRESS, CONF_DNS_ADDRESS, + CONF_IP_ADDRESS, CONF_MAC_ADDRESS, ENTITY_CATEGORY_DIAGNOSTIC, ) From 20c22465335231017b4300827ad3e68ce968bd4f Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 29 Jul 2024 14:06:08 +1200 Subject: [PATCH 1830/2101] [code-quality] Organise wifi related imports (#7153) --- esphome/components/wifi/__init__.py | 31 +++++++++++---------- esphome/components/wifi/wpa2_eap.py | 13 ++++----- esphome/components/wifi_info/text_sensor.py | 6 ++-- esphome/components/wifi_signal/sensor.py | 2 +- 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/esphome/components/wifi/__init__.py b/esphome/components/wifi/__init__.py index 624bcdabdc..ea03cc16d1 100644 --- a/esphome/components/wifi/__init__.py +++ b/esphome/components/wifi/__init__.py @@ -1,15 +1,19 @@ -import esphome.codegen as cg -import esphome.config_validation as cv -import esphome.final_validate as fv from esphome import automation from esphome.automation import Condition +import esphome.codegen as cg +from esphome.components.esp32 import add_idf_sdkconfig_option, const, get_esp32_variant +from esphome.components.network import IPAddress +import esphome.config_validation as cv from esphome.const import ( CONF_AP, CONF_BSSID, + CONF_CERTIFICATE, + CONF_CERTIFICATE_AUTHORITY, CONF_CHANNEL, CONF_DNS1, CONF_DNS2, CONF_DOMAIN, + CONF_EAP, CONF_ENABLE_BTM, CONF_ENABLE_ON_BOOT, CONF_ENABLE_RRM, @@ -17,29 +21,26 @@ from esphome.const import ( CONF_GATEWAY, CONF_HIDDEN, CONF_ID, + CONF_IDENTITY, + CONF_KEY, CONF_MANUAL_IP, CONF_NETWORKS, + CONF_ON_CONNECT, + CONF_ON_DISCONNECT, CONF_PASSWORD, CONF_POWER_SAVE_MODE, + CONF_PRIORITY, CONF_REBOOT_TIMEOUT, CONF_SSID, CONF_STATIC_IP, CONF_SUBNET, - CONF_USE_ADDRESS, - CONF_PRIORITY, - CONF_IDENTITY, - CONF_CERTIFICATE_AUTHORITY, - CONF_CERTIFICATE, - CONF_KEY, - CONF_USERNAME, - CONF_EAP, CONF_TTLS_PHASE_2, - CONF_ON_CONNECT, - CONF_ON_DISCONNECT, + CONF_USE_ADDRESS, + CONF_USERNAME, ) from esphome.core import CORE, HexInt, coroutine_with_priority -from esphome.components.esp32 import add_idf_sdkconfig_option, get_esp32_variant, const -from esphome.components.network import IPAddress +import esphome.final_validate as fv + from . import wpa2_eap AUTO_LOAD = ["network"] diff --git a/esphome/components/wifi/wpa2_eap.py b/esphome/components/wifi/wpa2_eap.py index 3985dfef18..5d5bd8dca3 100644 --- a/esphome/components/wifi/wpa2_eap.py +++ b/esphome/components/wifi/wpa2_eap.py @@ -7,16 +7,15 @@ so that it doesn't crash if it's not installed. import logging from pathlib import Path -from esphome.core import CORE import esphome.config_validation as cv from esphome.const import ( - CONF_USERNAME, - CONF_IDENTITY, - CONF_PASSWORD, CONF_CERTIFICATE, + CONF_IDENTITY, CONF_KEY, + CONF_PASSWORD, + CONF_USERNAME, ) - +from esphome.core import CORE _LOGGER = logging.getLogger(__name__) @@ -49,8 +48,8 @@ def wrapped_load_pem_x509_certificate(value): def wrapped_load_pem_private_key(value, password): validate_cryptography_installed() - from cryptography.hazmat.primitives.serialization import load_pem_private_key from cryptography.hazmat.backends import default_backend + from cryptography.hazmat.primitives.serialization import load_pem_private_key if password: password = password.encode("UTF-8") @@ -91,7 +90,7 @@ def _validate_load_private_key(key, cert_pw): def _check_private_key_cert_match(key, cert): - from cryptography.hazmat.primitives.asymmetric import rsa, ec + from cryptography.hazmat.primitives.asymmetric import ec, rsa def check_match_a(): return key.public_key().public_numbers() == cert.public_key().public_numbers() diff --git a/esphome/components/wifi_info/text_sensor.py b/esphome/components/wifi_info/text_sensor.py index 75513712dd..4ceb73a695 100644 --- a/esphome/components/wifi_info/text_sensor.py +++ b/esphome/components/wifi_info/text_sensor.py @@ -1,13 +1,13 @@ import esphome.codegen as cg -import esphome.config_validation as cv from esphome.components import text_sensor +import esphome.config_validation as cv from esphome.const import ( CONF_BSSID, + CONF_DNS_ADDRESS, CONF_IP_ADDRESS, + CONF_MAC_ADDRESS, CONF_SCAN_RESULTS, CONF_SSID, - CONF_MAC_ADDRESS, - CONF_DNS_ADDRESS, ENTITY_CATEGORY_DIAGNOSTIC, ) diff --git a/esphome/components/wifi_signal/sensor.py b/esphome/components/wifi_signal/sensor.py index 77fabf272e..99b51adea0 100644 --- a/esphome/components/wifi_signal/sensor.py +++ b/esphome/components/wifi_signal/sensor.py @@ -1,6 +1,6 @@ import esphome.codegen as cg -import esphome.config_validation as cv from esphome.components import sensor +import esphome.config_validation as cv from esphome.const import ( DEVICE_CLASS_SIGNAL_STRENGTH, ENTITY_CATEGORY_DIAGNOSTIC, From e64709c37e22148572a182461f98430982e3228f Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 29 Jul 2024 14:07:44 +1200 Subject: [PATCH 1831/2101] [code-quality] Organise core imports (#7149) --- esphome/__main__.py | 12 ++-- esphome/automation.py | 2 +- esphome/codegen.py | 106 ++++++++++++++++---------------- esphome/config.py | 42 ++++++------- esphome/config_validation.py | 42 ++++++------- esphome/core/__init__.py | 19 +++--- esphome/core/config.py | 6 +- esphome/core/entity_helpers.py | 3 +- esphome/coroutine.py | 2 +- esphome/cpp_generator.py | 2 +- esphome/cpp_helpers.py | 8 +-- esphome/dashboard/core.py | 6 +- esphome/dashboard/dashboard.py | 6 +- esphome/dashboard/entries.py | 2 +- esphome/dashboard/util/file.py | 2 +- esphome/dashboard/web_server.py | 6 +- esphome/external_files.py | 10 +-- esphome/final_validate.py | 4 +- esphome/git.py | 10 +-- esphome/helpers.py | 12 ++-- esphome/mqtt.py | 6 +- esphome/pins.py | 12 ++-- esphome/platformio_api.py | 10 +-- esphome/storage_json.py | 3 +- esphome/types.py | 2 +- esphome/util.py | 5 +- esphome/voluptuous_schema.py | 1 + esphome/vscode.py | 9 +-- esphome/wizard.py | 2 +- esphome/writer.py | 16 ++--- esphome/yaml_util.py | 6 +- esphome/zeroconf.py | 2 +- 32 files changed, 190 insertions(+), 186 deletions(-) diff --git a/esphome/__main__.py b/esphome/__main__.py index 9e7b7fa15b..13f09e15ed 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -1,12 +1,12 @@ # PYTHON_ARGCOMPLETE_OK import argparse +from datetime import datetime import functools import logging import os import re import sys import time -from datetime import datetime import argcomplete @@ -39,14 +39,14 @@ from esphome.const import ( ) from esphome.core import CORE, EsphomeError, coroutine from esphome.helpers import indent, is_ip_address +from esphome.log import Fore, color, setup_log from esphome.util import ( + get_serial_ports, + list_yaml_files, run_external_command, run_external_process, safe_print, - list_yaml_files, - get_serial_ports, ) -from esphome.log import color, setup_log, Fore _LOGGER = logging.getLogger(__name__) @@ -116,6 +116,7 @@ def get_port_type(port): def run_miniterm(config, port): import serial + from esphome import platformio_api if CONF_LOGGER not in config: @@ -596,9 +597,10 @@ def command_update_all(args): def command_idedata(args, config): - from esphome import platformio_api import json + from esphome import platformio_api + logging.disable(logging.INFO) logging.disable(logging.WARNING) diff --git a/esphome/automation.py b/esphome/automation.py index b25ffa5abe..0bd6cf0af0 100644 --- a/esphome/automation.py +++ b/esphome/automation.py @@ -7,10 +7,10 @@ from esphome.const import ( CONF_ELSE, CONF_ID, CONF_THEN, + CONF_TIME, CONF_TIMEOUT, CONF_TRIGGER_ID, CONF_TYPE_ID, - CONF_TIME, CONF_UPDATE_INTERVAL, ) from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor diff --git a/esphome/codegen.py b/esphome/codegen.py index 6b000b53a1..bfa1683ce7 100644 --- a/esphome/codegen.py +++ b/esphome/codegen.py @@ -8,55 +8,78 @@ # want to break suddenly due to a rename (this file will get backports for features). # pylint: disable=unused-import -from esphome.cpp_generator import ( # noqa +from esphome.cpp_generator import ( # noqa: F401 + ArrayInitializer, Expression, + LineComment, + MockObj, + MockObjClass, + Pvariable, RawExpression, RawStatement, - TemplateArguments, - StructInitializer, - ArrayInitializer, - safe_exp, Statement, - LineComment, - progmem_array, - static_const_array, - statement, - variable, - with_local_variable, - new_variable, - Pvariable, - new_Pvariable, + StructInitializer, + TemplateArguments, add, - add_global, - add_library, add_build_flag, add_define, + add_global, + add_library, add_platformio_option, get_variable, get_variable_with_full_id, - process_lambda, is_template, + new_Pvariable, + new_variable, + process_lambda, + progmem_array, + safe_exp, + statement, + static_const_array, templatable, - MockObj, - MockObjClass, + variable, + with_local_variable, ) -from esphome.cpp_helpers import ( # noqa - gpio_pin_expression, - register_component, +from esphome.cpp_helpers import ( # noqa: F401 build_registry_entry, build_registry_list, extract_registry_entry_config, - register_parented, + gpio_pin_expression, past_safe_mode, + register_component, + register_parented, ) -from esphome.cpp_types import ( # noqa - global_ns, - void, - nullptr, - float_, - double, +from esphome.cpp_types import ( # noqa: F401 + NAN, + App, + Application, + Component, + ComponentPtr, + Controller, + EntityBase, + EntityCategory, + ESPTime, + GPIOPin, + InternalGPIOPin, + JsonObject, + JsonObjectConst, + Parented, + PollingComponent, + arduino_json_ns, bool_, + const_char_ptr, + double, + esphome_ns, + float_, + global_ns, + gpio_Flags, + int16, + int32, + int64, int_, + nullptr, + optional, + size_t, std_ns, std_shared_ptr, std_string, @@ -66,28 +89,5 @@ from esphome.cpp_types import ( # noqa uint16, uint32, uint64, - int16, - int32, - int64, - size_t, - const_char_ptr, - NAN, - esphome_ns, - App, - EntityBase, - Component, - ComponentPtr, - PollingComponent, - Application, - optional, - arduino_json_ns, - JsonObject, - JsonObjectConst, - Controller, - GPIOPin, - InternalGPIOPin, - gpio_Flags, - EntityCategory, - Parented, - ESPTime, + void, ) diff --git a/esphome/config.py b/esphome/config.py index 925a31fed0..a2d0d15477 100644 --- a/esphome/config.py +++ b/esphome/config.py @@ -1,40 +1,38 @@ from __future__ import annotations + import abc +from contextlib import contextmanager +import contextvars import functools import heapq import logging import re - -from typing import Union, Any - -from contextlib import contextmanager -import contextvars +from typing import Any, Union import voluptuous as vol -from esphome import core, yaml_util, loader, pins -import esphome.core.config as core_config +from esphome import core, loader, pins, yaml_util +from esphome.config_helpers import Extend, Remove +import esphome.config_validation as cv from esphome.const import ( CONF_ESPHOME, - CONF_ID, - CONF_PLATFORM, - CONF_PACKAGES, - CONF_SUBSTITUTIONS, CONF_EXTERNAL_COMPONENTS, + CONF_ID, + CONF_PACKAGES, + CONF_PLATFORM, + CONF_SUBSTITUTIONS, TARGET_PLATFORMS, ) -from esphome.core import CORE, EsphomeError, DocumentRange -from esphome.helpers import indent -from esphome.util import safe_print, OrderedDict - -from esphome.config_helpers import Extend, Remove -from esphome.loader import get_component, get_platform, ComponentManifest -from esphome.yaml_util import is_secret, ESPHomeDataBase, ESPForceValue -from esphome.voluptuous_schema import ExtraKeysInvalid -from esphome.log import color, Fore +from esphome.core import CORE, DocumentRange, EsphomeError +import esphome.core.config as core_config import esphome.final_validate as fv -import esphome.config_validation as cv -from esphome.types import ConfigType, ConfigFragmentType +from esphome.helpers import indent +from esphome.loader import ComponentManifest, get_component, get_platform +from esphome.log import Fore, color +from esphome.types import ConfigFragmentType, ConfigType +from esphome.util import OrderedDict, safe_print +from esphome.voluptuous_schema import ExtraKeysInvalid +from esphome.yaml_util import ESPForceValue, ESPHomeDataBase, is_secret _LOGGER = logging.getLogger(__name__) diff --git a/esphome/config_validation.py b/esphome/config_validation.py index 3ef92ad460..1cd1d6aa31 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -1,13 +1,13 @@ """Helpers for config validation using voluptuous.""" +from contextlib import contextmanager from dataclasses import dataclass +from datetime import datetime import logging import os import re -from contextlib import contextmanager -import uuid as uuid_ -from datetime import datetime from string import ascii_letters, digits +import uuid as uuid_ import voluptuous as vol @@ -17,37 +17,37 @@ from esphome.config_helpers import Extend, Remove from esphome.const import ( ALLOWED_NAME_CHARS, CONF_AVAILABILITY, - CONF_COMMAND_TOPIC, CONF_COMMAND_RETAIN, + CONF_COMMAND_TOPIC, + CONF_DAY, CONF_DISABLED_BY_DEFAULT, CONF_DISCOVERY, CONF_ENTITY_CATEGORY, + CONF_HOUR, CONF_ICON, CONF_ID, CONF_INTERNAL, + CONF_MINUTE, + CONF_MONTH, CONF_NAME, + CONF_PASSWORD, + CONF_PATH, CONF_PAYLOAD_AVAILABLE, CONF_PAYLOAD_NOT_AVAILABLE, - CONF_RETAIN, CONF_QOS, + CONF_REF, + CONF_RETAIN, + CONF_SECOND, CONF_SETUP_PRIORITY, CONF_STATE_TOPIC, CONF_TOPIC, - CONF_YEAR, - CONF_MONTH, - CONF_DAY, - CONF_HOUR, - CONF_MINUTE, - CONF_SECOND, - CONF_VALUE, - CONF_UPDATE_INTERVAL, - CONF_TYPE_ID, CONF_TYPE, - CONF_REF, + CONF_TYPE_ID, + CONF_UPDATE_INTERVAL, CONF_URL, - CONF_PATH, CONF_USERNAME, - CONF_PASSWORD, + CONF_VALUE, + CONF_YEAR, ENTITY_CATEGORY_CONFIG, ENTITY_CATEGORY_DIAGNOSTIC, ENTITY_CATEGORY_NONE, @@ -71,15 +71,15 @@ from esphome.core import ( TimePeriod, TimePeriodMicroseconds, TimePeriodMilliseconds, + TimePeriodMinutes, TimePeriodNanoseconds, TimePeriodSeconds, - TimePeriodMinutes, ) -from esphome.helpers import list_starts_with, add_class_to_obj +from esphome.helpers import add_class_to_obj, list_starts_with from esphome.schema_extractors import ( SCHEMA_EXTRACT, - schema_extractor_list, schema_extractor, + schema_extractor_list, schema_extractor_registry, schema_extractor_typed, ) @@ -1686,9 +1686,9 @@ class SplitDefault(Optional): if CORE.is_esp32: from esphome.components.esp32 import get_esp32_variant from esphome.components.esp32.const import ( + VARIANT_ESP32C3, VARIANT_ESP32S2, VARIANT_ESP32S3, - VARIANT_ESP32C3, ) variant = get_esp32_variant() diff --git a/esphome/core/__init__.py b/esphome/core/__init__.py index f25891965a..9d3d14492e 100644 --- a/esphome/core/__init__.py +++ b/esphome/core/__init__.py @@ -7,26 +7,29 @@ from typing import TYPE_CHECKING, Optional, Union from esphome.const import ( CONF_COMMENT, CONF_ESPHOME, - CONF_USE_ADDRESS, CONF_ETHERNET, + CONF_PORT, + CONF_USE_ADDRESS, CONF_WEB_SERVER, CONF_WIFI, - CONF_PORT, KEY_CORE, KEY_TARGET_FRAMEWORK, KEY_TARGET_PLATFORM, + PLATFORM_BK72XX, PLATFORM_ESP32, PLATFORM_ESP8266, - PLATFORM_BK72XX, - PLATFORM_RTL87XX, - PLATFORM_RP2040, PLATFORM_HOST, + PLATFORM_RP2040, + PLATFORM_RTL87XX, ) -from esphome.coroutine import FakeAwaitable as _FakeAwaitable -from esphome.coroutine import FakeEventLoop as _FakeEventLoop # pylint: disable=unused-import -from esphome.coroutine import coroutine, coroutine_with_priority # noqa +from esphome.coroutine import ( # noqa: F401 + FakeAwaitable as _FakeAwaitable, + FakeEventLoop as _FakeEventLoop, + coroutine, + coroutine_with_priority, +) from esphome.helpers import ensure_unique_string, get_str_env, is_ha_addon from esphome.util import OrderedDict diff --git a/esphome/core/config.py b/esphome/core/config.py index 80b731b905..739a8a1aea 100644 --- a/esphome/core/config.py +++ b/esphome/core/config.py @@ -3,9 +3,9 @@ import multiprocessing import os import re +from esphome import automation import esphome.codegen as cg import esphome.config_validation as cv -from esphome import automation from esphome.const import ( CONF_ARDUINO_VERSION, CONF_AREA, @@ -16,11 +16,11 @@ from esphome.const import ( CONF_COMPILE_PROCESS_LIMIT, CONF_ESPHOME, CONF_FRAMEWORK, + CONF_FRIENDLY_NAME, CONF_INCLUDES, CONF_LIBRARIES, CONF_MIN_VERSION, CONF_NAME, - CONF_FRIENDLY_NAME, CONF_ON_BOOT, CONF_ON_LOOP, CONF_ON_SHUTDOWN, @@ -34,8 +34,8 @@ from esphome.const import ( CONF_TYPE, CONF_VERSION, KEY_CORE, - TARGET_PLATFORMS, PLATFORM_ESP8266, + TARGET_PLATFORMS, __version__ as ESPHOME_VERSION, ) from esphome.core import CORE, coroutine_with_priority diff --git a/esphome/core/entity_helpers.py b/esphome/core/entity_helpers.py index f921711ec2..7f6a9b48ab 100644 --- a/esphome/core/entity_helpers.py +++ b/esphome/core/entity_helpers.py @@ -1,6 +1,5 @@ -import esphome.final_validate as fv - from esphome.const import CONF_ID +import esphome.final_validate as fv def inherit_property_from(property_to_inherit, parent_id_property, transform=None): diff --git a/esphome/coroutine.py b/esphome/coroutine.py index 5f391dc7ad..30ebb8147e 100644 --- a/esphome/coroutine.py +++ b/esphome/coroutine.py @@ -43,13 +43,13 @@ the last `yield` expression defines what is returned. """ import collections +from collections.abc import Awaitable, Generator, Iterator import functools import heapq import inspect import logging import types from typing import Any, Callable -from collections.abc import Awaitable, Generator, Iterator _LOGGER = logging.getLogger(__name__) diff --git a/esphome/cpp_generator.py b/esphome/cpp_generator.py index 9a4cb2269a..7a82d5cba1 100644 --- a/esphome/cpp_generator.py +++ b/esphome/cpp_generator.py @@ -1,8 +1,8 @@ import abc +from collections.abc import Sequence import inspect import math import re -from collections.abc import Sequence from typing import Any, Callable, Optional, Union from esphome.core import ( diff --git a/esphome/cpp_helpers.py b/esphome/cpp_helpers.py index 825224bb9d..9a775bad33 100644 --- a/esphome/cpp_helpers.py +++ b/esphome/cpp_helpers.py @@ -12,15 +12,13 @@ from esphome.const import ( CONF_UPDATE_INTERVAL, KEY_PAST_SAFE_MODE, ) - -from esphome.core import coroutine, ID, CORE +from esphome.core import CORE, ID, coroutine from esphome.coroutine import FakeAwaitable -from esphome.types import ConfigType, ConfigFragmentType from esphome.cpp_generator import add, get_variable from esphome.cpp_types import App +from esphome.helpers import sanitize, snake_case +from esphome.types import ConfigFragmentType, ConfigType from esphome.util import Registry, RegistryEntry -from esphome.helpers import snake_case, sanitize - _LOGGER = logging.getLogger(__name__) diff --git a/esphome/dashboard/core.py b/esphome/dashboard/core.py index 875ff6b91f..eec0777da6 100644 --- a/esphome/dashboard/core.py +++ b/esphome/dashboard/core.py @@ -1,13 +1,13 @@ from __future__ import annotations import asyncio +from collections.abc import Coroutine import contextlib -import logging -import threading from dataclasses import dataclass from functools import partial +import logging +import threading from typing import TYPE_CHECKING, Any, Callable -from collections.abc import Coroutine from ..zeroconf import DiscoveredImport from .dns import DNSCache diff --git a/esphome/dashboard/dashboard.py b/esphome/dashboard/dashboard.py index 2be98ab3e4..9de2d39ce2 100644 --- a/esphome/dashboard/dashboard.py +++ b/esphome/dashboard/dashboard.py @@ -1,14 +1,14 @@ from __future__ import annotations import asyncio +from asyncio import events +from concurrent.futures import ThreadPoolExecutor import logging import os import socket import threading -import traceback -from asyncio import events -from concurrent.futures import ThreadPoolExecutor from time import monotonic +import traceback from typing import Any from esphome.storage_json import EsphomeStorageJSON, esphome_storage_path diff --git a/esphome/dashboard/entries.py b/esphome/dashboard/entries.py index 7a9bff4ec1..cb0d4a3772 100644 --- a/esphome/dashboard/entries.py +++ b/esphome/dashboard/entries.py @@ -1,9 +1,9 @@ from __future__ import annotations import asyncio +from collections import defaultdict import logging import os -from collections import defaultdict from typing import TYPE_CHECKING, Any from esphome import const, util diff --git a/esphome/dashboard/util/file.py b/esphome/dashboard/util/file.py index 661d5f34cf..bb263f9ad7 100644 --- a/esphome/dashboard/util/file.py +++ b/esphome/dashboard/util/file.py @@ -1,7 +1,7 @@ import logging import os -import tempfile from pathlib import Path +import tempfile _LOGGER = logging.getLogger(__name__) diff --git a/esphome/dashboard/web_server.py b/esphome/dashboard/web_server.py index 33c83ffb1a..e4b7b8d342 100644 --- a/esphome/dashboard/web_server.py +++ b/esphome/dashboard/web_server.py @@ -2,6 +2,7 @@ from __future__ import annotations import asyncio import base64 +from collections.abc import Iterable import datetime import functools import gzip @@ -9,13 +10,12 @@ import hashlib import json import logging import os +from pathlib import Path import secrets import shutil import subprocess import threading import time -from collections.abc import Iterable -from pathlib import Path from typing import TYPE_CHECKING, Any, Callable, TypeVar from urllib.parse import urlparse @@ -26,13 +26,13 @@ import tornado.httpserver import tornado.httputil import tornado.ioloop import tornado.iostream +from tornado.log import access_log import tornado.netutil import tornado.process import tornado.queues import tornado.web import tornado.websocket import yaml -from tornado.log import access_log from yaml.nodes import Node from esphome import const, platformio_api, yaml_util diff --git a/esphome/external_files.py b/esphome/external_files.py index f8eb1dcabe..baf62286e4 100644 --- a/esphome/external_files.py +++ b/esphome/external_files.py @@ -1,13 +1,15 @@ from __future__ import annotations -import logging -from pathlib import Path -import os from datetime import datetime +import logging +import os +from pathlib import Path + import requests + import esphome.config_validation as cv -from esphome.core import CORE, TimePeriodSeconds from esphome.const import __version__ +from esphome.core import CORE, TimePeriodSeconds _LOGGER = logging.getLogger(__name__) CODEOWNERS = ["@landonr"] diff --git a/esphome/final_validate.py b/esphome/final_validate.py index 5e9d2207b0..cebd2f1cda 100644 --- a/esphome/final_validate.py +++ b/esphome/final_validate.py @@ -1,9 +1,9 @@ from abc import ABC, abstractmethod -from typing import Any import contextvars +from typing import Any -from esphome.types import ConfigFragmentType, ID, ConfigPathType import esphome.config_validation as cv +from esphome.types import ID, ConfigFragmentType, ConfigPathType class FinalValidateConfig(ABC): diff --git a/esphome/git.py b/esphome/git.py index e41777f425..144c160b20 100644 --- a/esphome/git.py +++ b/esphome/git.py @@ -1,12 +1,12 @@ -import hashlib -import logging -import re -import subprocess -import urllib.parse from dataclasses import dataclass from datetime import datetime +import hashlib +import logging from pathlib import Path +import re +import subprocess from typing import Callable, Optional +import urllib.parse import esphome.config_validation as cv from esphome.core import CORE, TimePeriodSeconds diff --git a/esphome/helpers.py b/esphome/helpers.py index 4c8cb4e2cc..2a7e5cd9b6 100644 --- a/esphome/helpers.py +++ b/esphome/helpers.py @@ -1,14 +1,13 @@ import codecs from contextlib import suppress - import logging import os -import platform from pathlib import Path -from typing import Union -import tempfile -from urllib.parse import urlparse +import platform import re +import tempfile +from typing import Union +from urllib.parse import urlparse _LOGGER = logging.getLogger(__name__) @@ -129,9 +128,10 @@ def _resolve_with_zeroconf(host): def resolve_ip_address(host): - from esphome.core import EsphomeError import socket + from esphome.core import EsphomeError + errs = [] if host.endswith(".local"): diff --git a/esphome/mqtt.py b/esphome/mqtt.py index 667a20bcf8..d7e14a1d08 100644 --- a/esphome/mqtt.py +++ b/esphome/mqtt.py @@ -1,10 +1,10 @@ from datetime import datetime import hashlib +import json import logging import ssl import sys import time -import json import paho.mqtt.client as mqtt @@ -24,9 +24,9 @@ from esphome.const import ( CONF_USERNAME, ) from esphome.core import CORE, EsphomeError -from esphome.log import color, Fore +from esphome.helpers import get_int_env, get_str_env +from esphome.log import Fore, color from esphome.util import safe_print -from esphome.helpers import get_str_env, get_int_env _LOGGER = logging.getLogger(__name__) diff --git a/esphome/pins.py b/esphome/pins.py index 5ccb696738..724cd25d82 100644 --- a/esphome/pins.py +++ b/esphome/pins.py @@ -1,20 +1,20 @@ -import operator from functools import reduce -import esphome.config_validation as cv -from esphome.core import CORE +import operator +import esphome.config_validation as cv from esphome.const import ( + CONF_ALLOW_OTHER_USES, + CONF_IGNORE_STRAPPING_WARNING, CONF_INPUT, + CONF_INVERTED, CONF_MODE, CONF_NUMBER, CONF_OPEN_DRAIN, CONF_OUTPUT, CONF_PULLDOWN, CONF_PULLUP, - CONF_IGNORE_STRAPPING_WARNING, - CONF_ALLOW_OTHER_USES, - CONF_INVERTED, ) +from esphome.core import CORE class PinRegistry(dict): diff --git a/esphome/platformio_api.py b/esphome/platformio_api.py index c46a3fc767..b81ec4ab37 100644 --- a/esphome/platformio_api.py +++ b/esphome/platformio_api.py @@ -1,12 +1,11 @@ from dataclasses import dataclass import json -from typing import Union -from pathlib import Path - import logging import os +from pathlib import Path import re import subprocess +from typing import Union from esphome.const import CONF_COMPILE_PROCESS_LIMIT, CONF_ESPHOME, KEY_CORE from esphome.core import CORE, EsphomeError @@ -20,9 +19,10 @@ def patch_structhash(): # removed/added. This might have unintended consequences, but this improves compile # times greatly when adding/removing components and a simple clean build solves # all issues - from platformio.run import helpers, cli - from os.path import join, isdir, getmtime from os import makedirs + from os.path import getmtime, isdir, join + + from platformio.run import cli, helpers def patched_clean_build_dir(build_dir, *args): from platformio import fs diff --git a/esphome/storage_json.py b/esphome/storage_json.py index 0a41a4f738..e2e7514904 100644 --- a/esphome/storage_json.py +++ b/esphome/storage_json.py @@ -1,10 +1,11 @@ from __future__ import annotations + import binascii import codecs +from datetime import datetime import json import logging import os -from datetime import datetime from esphome import const from esphome.const import CONF_DISABLED, CONF_MDNS diff --git a/esphome/types.py b/esphome/types.py index 27ec61ceff..4e69e3cbd7 100644 --- a/esphome/types.py +++ b/esphome/types.py @@ -2,7 +2,7 @@ from typing import Union -from esphome.core import ID, Lambda, EsphomeCore +from esphome.core import ID, EsphomeCore, Lambda ConfigFragmentType = Union[ str, diff --git a/esphome/util.py b/esphome/util.py index d5a4c60570..32fd90cd25 100644 --- a/esphome/util.py +++ b/esphome/util.py @@ -1,13 +1,12 @@ -from typing import Union - import collections import io import logging import os +from pathlib import Path import re import subprocess import sys -from pathlib import Path +from typing import Union from esphome import const diff --git a/esphome/voluptuous_schema.py b/esphome/voluptuous_schema.py index 9af6cb717c..7f1573b443 100644 --- a/esphome/voluptuous_schema.py +++ b/esphome/voluptuous_schema.py @@ -2,6 +2,7 @@ import difflib import itertools import voluptuous as vol + from esphome.schema_extractors import schema_extractor_extended diff --git a/esphome/vscode.py b/esphome/vscode.py index 8198d2659a..907ed88216 100644 --- a/esphome/vscode.py +++ b/esphome/vscode.py @@ -1,13 +1,14 @@ from __future__ import annotations + +from io import StringIO import json import os -from io import StringIO from typing import Any -from esphome.yaml_util import parse_yaml -from esphome.config import validate_config, _format_vol_invalid, Config -from esphome.core import CORE, DocumentRange +from esphome.config import Config, _format_vol_invalid, validate_config import esphome.config_validation as cv +from esphome.core import CORE, DocumentRange +from esphome.yaml_util import parse_yaml def _get_invalid_range(res: Config, invalid: cv.Invalid) -> DocumentRange | None: diff --git a/esphome/wizard.py b/esphome/wizard.py index f8911ae844..319fb31938 100644 --- a/esphome/wizard.py +++ b/esphome/wizard.py @@ -276,8 +276,8 @@ def wizard(path): from esphome.components.bk72xx import boards as bk72xx_boards from esphome.components.esp32 import boards as esp32_boards from esphome.components.esp8266 import boards as esp8266_boards - from esphome.components.rtl87xx import boards as rtl87xx_boards from esphome.components.rp2040 import boards as rp2040_boards + from esphome.components.rtl87xx import boards as rtl87xx_boards if not path.endswith(".yaml") and not path.endswith(".yml"): safe_print( diff --git a/esphome/writer.py b/esphome/writer.py index 3ad0e60d31..c6111cbe3f 100644 --- a/esphome/writer.py +++ b/esphome/writer.py @@ -1,27 +1,27 @@ import logging import os -import re from pathlib import Path +import re from typing import Union -from esphome.config import iter_components, iter_component_configs +from esphome import loader +from esphome.config import iter_component_configs, iter_components from esphome.const import ( + ENV_NOGITIGNORE, HEADER_FILE_EXTENSIONS, SOURCE_FILE_EXTENSIONS, __version__, - ENV_NOGITIGNORE, ) from esphome.core import CORE, EsphomeError from esphome.helpers import ( - mkdir_p, - read_file, - write_file_if_changed, - walk_files, copy_file_if_changed, get_bool_env, + mkdir_p, + read_file, + walk_files, + write_file_if_changed, ) from esphome.storage_json import StorageJSON, storage_path -from esphome import loader _LOGGER = logging.getLogger(__name__) diff --git a/esphome/yaml_util.py b/esphome/yaml_util.py index 06bfd8b217..d67511dfec 100644 --- a/esphome/yaml_util.py +++ b/esphome/yaml_util.py @@ -3,16 +3,16 @@ from __future__ import annotations import fnmatch import functools import inspect +from io import TextIOWrapper import logging import math import os -import uuid -from io import TextIOWrapper from typing import Any +import uuid import yaml -import yaml.constructor from yaml import SafeLoader as PurePythonLoader +import yaml.constructor try: from yaml import CSafeLoader as FastestAvailableSafeLoader diff --git a/esphome/zeroconf.py b/esphome/zeroconf.py index b67ea41323..b3ee64e259 100644 --- a/esphome/zeroconf.py +++ b/esphome/zeroconf.py @@ -1,8 +1,8 @@ from __future__ import annotations import asyncio -import logging from dataclasses import dataclass +import logging from typing import Callable from zeroconf import IPVersion, ServiceInfo, ServiceStateChange, Zeroconf From b3728697cc3997899bd7cb20fdeb9d8f3b1f06ae Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 29 Jul 2024 20:13:57 +1200 Subject: [PATCH 1832/2101] Remove deprecated argument parser (#7151) * Remove deprecated argument parser * Add back removed argcomplete line --- esphome/__main__.py | 68 --------------------------------------------- 1 file changed, 68 deletions(-) diff --git a/esphome/__main__.py b/esphome/__main__.py index 13f09e15ed..7237a04717 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -957,67 +957,6 @@ def parse_args(argv): # a deprecation warning). arguments = argv[1:] - # On Python 3.9+ we can simply set exit_on_error=False in the constructor - def _raise(x): - raise argparse.ArgumentError(None, x) - - # First, try new-style parsing, but don't exit in case of failure - try: - # duplicate parser so that we can use the original one to raise errors later on - current_parser = argparse.ArgumentParser(add_help=False, parents=[parser]) - current_parser.set_defaults(deprecated_argv_suggestion=None) - current_parser.error = _raise - return current_parser.parse_args(arguments) - except argparse.ArgumentError: - pass - - # Second, try compat parsing and rearrange the command-line if it succeeds - # Disable argparse's built-in help option and add it manually to prevent this - # parser from printing the help messagefor the old format when invoked with -h. - compat_parser = argparse.ArgumentParser(parents=[options_parser], add_help=False) - compat_parser.add_argument("-h", "--help", action="store_true") - compat_parser.add_argument("configuration", nargs="*") - compat_parser.add_argument( - "command", - choices=[ - "config", - "compile", - "upload", - "logs", - "run", - "clean-mqtt", - "wizard", - "mqtt-fingerprint", - "version", - "clean", - "dashboard", - "vscode", - "update-all", - ], - ) - - try: - compat_parser.error = _raise - result, unparsed = compat_parser.parse_known_args(argv[1:]) - last_option = len(arguments) - len(unparsed) - 1 - len(result.configuration) - unparsed = [ - "--device" if arg in ("--upload-port", "--serial-port") else arg - for arg in unparsed - ] - arguments = ( - arguments[0:last_option] - + [result.command] - + result.configuration - + unparsed - ) - deprecated_argv_suggestion = arguments - except argparse.ArgumentError: - # old-style parsing failed, don't suggest any argument - deprecated_argv_suggestion = None - - # Finally, run the new-style parser again with the possibly swapped arguments, - # and let it error out if the command is unparsable. - parser.set_defaults(deprecated_argv_suggestion=deprecated_argv_suggestion) argcomplete.autocomplete(parser) return parser.parse_args(arguments) @@ -1032,13 +971,6 @@ def run_esphome(argv): # Show timestamp for dashboard access logs args.command == "dashboard", ) - if args.deprecated_argv_suggestion is not None and args.command != "vscode": - _LOGGER.warning( - "Calling ESPHome with the configuration before the command is deprecated " - "and will be removed in the future. " - ) - _LOGGER.warning("Please instead use:") - _LOGGER.warning(" esphome %s", " ".join(args.deprecated_argv_suggestion)) if sys.version_info < (3, 8, 0): _LOGGER.error( From 24515546fd25a265dbb704890a6d7c9285775b17 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 29 Jul 2024 20:22:30 +1200 Subject: [PATCH 1833/2101] Move ``CONF_ON_ERROR`` to const.py (#7156) --- esphome/components/ota/__init__.py | 12 ++++++--- .../components/voice_assistant/__init__.py | 27 +++++++++---------- esphome/const.py | 1 + 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/esphome/components/ota/__init__.py b/esphome/components/ota/__init__.py index 4e447bfb2d..d9917a2aae 100644 --- a/esphome/components/ota/__init__.py +++ b/esphome/components/ota/__init__.py @@ -1,10 +1,15 @@ +from esphome import automation import esphome.codegen as cg import esphome.config_validation as cv -from esphome import automation +from esphome.const import ( + CONF_ESPHOME, + CONF_ON_ERROR, + CONF_OTA, + CONF_PLATFORM, + CONF_TRIGGER_ID, +) from esphome.core import CORE, coroutine_with_priority -from esphome.const import CONF_ESPHOME, CONF_OTA, CONF_PLATFORM, CONF_TRIGGER_ID - CODEOWNERS = ["@esphome/core"] AUTO_LOAD = ["md5", "safe_mode"] @@ -13,7 +18,6 @@ IS_PLATFORM_COMPONENT = True CONF_ON_ABORT = "on_abort" CONF_ON_BEGIN = "on_begin" CONF_ON_END = "on_end" -CONF_ON_ERROR = "on_error" CONF_ON_PROGRESS = "on_progress" CONF_ON_STATE_CHANGE = "on_state_change" diff --git a/esphome/components/voice_assistant/__init__.py b/esphome/components/voice_assistant/__init__.py index c18f0a6850..031edbf27a 100644 --- a/esphome/components/voice_assistant/__init__.py +++ b/esphome/components/voice_assistant/__init__.py @@ -1,18 +1,18 @@ -import esphome.config_validation as cv -import esphome.codegen as cg - -from esphome.const import ( - CONF_ID, - CONF_MICROPHONE, - CONF_SPEAKER, - CONF_MEDIA_PLAYER, - CONF_ON_CLIENT_CONNECTED, - CONF_ON_CLIENT_DISCONNECTED, - CONF_ON_IDLE, -) from esphome import automation from esphome.automation import register_action, register_condition -from esphome.components import microphone, speaker, media_player +import esphome.codegen as cg +from esphome.components import media_player, microphone, speaker +import esphome.config_validation as cv +from esphome.const import ( + CONF_ID, + CONF_MEDIA_PLAYER, + CONF_MICROPHONE, + CONF_ON_CLIENT_CONNECTED, + CONF_ON_CLIENT_DISCONNECTED, + CONF_ON_ERROR, + CONF_ON_IDLE, + CONF_SPEAKER, +) AUTO_LOAD = ["socket"] DEPENDENCIES = ["api", "microphone"] @@ -20,7 +20,6 @@ DEPENDENCIES = ["api", "microphone"] CODEOWNERS = ["@jesserockz"] CONF_ON_END = "on_end" -CONF_ON_ERROR = "on_error" CONF_ON_INTENT_END = "on_intent_end" CONF_ON_INTENT_START = "on_intent_start" CONF_ON_LISTENING = "on_listening" diff --git a/esphome/const.py b/esphome/const.py index faf6ce19fa..4357963384 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -539,6 +539,7 @@ CONF_ON_DOUBLE_CLICK = "on_double_click" CONF_ON_ENROLLMENT_DONE = "on_enrollment_done" CONF_ON_ENROLLMENT_FAILED = "on_enrollment_failed" CONF_ON_ENROLLMENT_SCAN = "on_enrollment_scan" +CONF_ON_ERROR = "on_error" CONF_ON_EVENT = "on_event" CONF_ON_FINGER_SCAN_INVALID = "on_finger_scan_invalid" CONF_ON_FINGER_SCAN_MATCHED = "on_finger_scan_matched" From 5b6b7c0d15098f7477bae68329fe76a1d8993cf5 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 29 Jul 2024 20:25:53 +1200 Subject: [PATCH 1834/2101] [code-quality] Organise esp32 imports (#7154) --- esphome/components/esp32/__init__.py | 19 ++++++++--------- esphome/components/esp32/boards.py | 2 +- esphome/components/esp32/gpio.py | 25 +++++++++++------------ esphome/components/esp32/gpio_esp32.py | 3 +-- esphome/components/esp32/gpio_esp32_c2.py | 3 +-- esphome/components/esp32/gpio_esp32_c3.py | 6 +----- esphome/components/esp32/gpio_esp32_c6.py | 3 +-- esphome/components/esp32/gpio_esp32_h2.py | 3 +-- esphome/components/esp32/gpio_esp32_s2.py | 3 +-- esphome/components/esp32/gpio_esp32_s3.py | 7 +------ 10 files changed, 29 insertions(+), 45 deletions(-) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 1effea708f..0a5dd46478 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -1,11 +1,12 @@ from dataclasses import dataclass -from typing import Union, Optional -from pathlib import Path import logging import os -import esphome.final_validate as fv +from pathlib import Path +from typing import Optional, Union -from esphome.helpers import copy_file_if_changed, write_file_if_changed, mkdir_p +from esphome import git +import esphome.codegen as cg +import esphome.config_validation as cv from esphome.const import ( CONF_ADVANCED, CONF_BOARD, @@ -15,6 +16,7 @@ from esphome.const import ( CONF_IGNORE_EFUSE_MAC_CRC, CONF_NAME, CONF_PATH, + CONF_PLATFORM_VERSION, CONF_PLATFORMIO_OPTIONS, CONF_REF, CONF_REFRESH, @@ -32,13 +34,12 @@ from esphome.const import ( TYPE_GIT, TYPE_LOCAL, __version__, - CONF_PLATFORM_VERSION, ) from esphome.core import CORE, HexInt, TimePeriod -import esphome.config_validation as cv -import esphome.codegen as cg -from esphome import git +import esphome.final_validate as fv +from esphome.helpers import copy_file_if_changed, mkdir_p, write_file_if_changed +from .boards import BOARDS from .const import ( # noqa KEY_BOARD, KEY_COMPONENTS, @@ -54,12 +55,10 @@ from .const import ( # noqa VARIANT_FRIENDLY, VARIANTS, ) -from .boards import BOARDS # force import gpio to register pin schema from .gpio import esp32_pin_to_code # noqa - _LOGGER = logging.getLogger(__name__) CODEOWNERS = ["@esphome/core"] AUTO_LOAD = ["preferences"] diff --git a/esphome/components/esp32/boards.py b/esphome/components/esp32/boards.py index cd85f3da97..60abcd447c 100644 --- a/esphome/components/esp32/boards.py +++ b/esphome/components/esp32/boards.py @@ -1,4 +1,4 @@ -from .const import VARIANT_ESP32, VARIANT_ESP32S2, VARIANT_ESP32C3, VARIANT_ESP32S3 +from .const import VARIANT_ESP32, VARIANT_ESP32C3, VARIANT_ESP32S2, VARIANT_ESP32S3 ESP32_BASE_PINS = { "TX": 1, diff --git a/esphome/components/esp32/gpio.py b/esphome/components/esp32/gpio.py index 0d9cb5daf0..558ff51af8 100644 --- a/esphome/components/esp32/gpio.py +++ b/esphome/components/esp32/gpio.py @@ -1,22 +1,22 @@ from dataclasses import dataclass -from typing import Any import logging +from typing import Any +from esphome import pins +import esphome.codegen as cg +import esphome.config_validation as cv from esphome.const import ( CONF_ID, + CONF_IGNORE_PIN_VALIDATION_ERROR, + CONF_IGNORE_STRAPPING_WARNING, CONF_INVERTED, CONF_MODE, CONF_NUMBER, CONF_OPEN_DRAIN, CONF_OUTPUT, - CONF_IGNORE_PIN_VALIDATION_ERROR, - CONF_IGNORE_STRAPPING_WARNING, PLATFORM_ESP32, ) -from esphome import pins from esphome.core import CORE -import esphome.config_validation as cv -import esphome.codegen as cg from . import boards from .const import ( @@ -24,22 +24,21 @@ from .const import ( KEY_ESP32, KEY_VARIANT, VARIANT_ESP32, - VARIANT_ESP32C3, - VARIANT_ESP32S2, - VARIANT_ESP32S3, VARIANT_ESP32C2, + VARIANT_ESP32C3, VARIANT_ESP32C6, VARIANT_ESP32H2, + VARIANT_ESP32S2, + VARIANT_ESP32S3, esp32_ns, ) - from .gpio_esp32 import esp32_validate_gpio_pin, esp32_validate_supports -from .gpio_esp32_s2 import esp32_s2_validate_gpio_pin, esp32_s2_validate_supports -from .gpio_esp32_c3 import esp32_c3_validate_gpio_pin, esp32_c3_validate_supports -from .gpio_esp32_s3 import esp32_s3_validate_gpio_pin, esp32_s3_validate_supports from .gpio_esp32_c2 import esp32_c2_validate_gpio_pin, esp32_c2_validate_supports +from .gpio_esp32_c3 import esp32_c3_validate_gpio_pin, esp32_c3_validate_supports from .gpio_esp32_c6 import esp32_c6_validate_gpio_pin, esp32_c6_validate_supports from .gpio_esp32_h2 import esp32_h2_validate_gpio_pin, esp32_h2_validate_supports +from .gpio_esp32_s2 import esp32_s2_validate_gpio_pin, esp32_s2_validate_supports +from .gpio_esp32_s3 import esp32_s3_validate_gpio_pin, esp32_s3_validate_supports ESP32InternalGPIOPin = esp32_ns.class_("ESP32InternalGPIOPin", cg.InternalGPIOPin) diff --git a/esphome/components/esp32/gpio_esp32.py b/esphome/components/esp32/gpio_esp32.py index d10b266c7a..e4d3b6aaf3 100644 --- a/esphome/components/esp32/gpio_esp32.py +++ b/esphome/components/esp32/gpio_esp32.py @@ -1,5 +1,6 @@ import logging +import esphome.config_validation as cv from esphome.const import ( CONF_INPUT, CONF_MODE, @@ -8,10 +9,8 @@ from esphome.const import ( CONF_PULLDOWN, CONF_PULLUP, ) -import esphome.config_validation as cv from esphome.pins import check_strapping_pin - _ESP_SDIO_PINS = { 6: "Flash Clock", 7: "Flash Data 0", diff --git a/esphome/components/esp32/gpio_esp32_c2.py b/esphome/components/esp32/gpio_esp32_c2.py index 0bee7d82bf..abdcb1b655 100644 --- a/esphome/components/esp32/gpio_esp32_c2.py +++ b/esphome/components/esp32/gpio_esp32_c2.py @@ -1,10 +1,9 @@ import logging +import esphome.config_validation as cv from esphome.const import CONF_INPUT, CONF_MODE, CONF_NUMBER from esphome.pins import check_strapping_pin -import esphome.config_validation as cv - _ESP32C2_STRAPPING_PINS = {8, 9} _LOGGER = logging.getLogger(__name__) diff --git a/esphome/components/esp32/gpio_esp32_c3.py b/esphome/components/esp32/gpio_esp32_c3.py index 6c70c09f9e..5b9ec0ebd9 100644 --- a/esphome/components/esp32/gpio_esp32_c3.py +++ b/esphome/components/esp32/gpio_esp32_c3.py @@ -1,11 +1,7 @@ import logging -from esphome.const import ( - CONF_INPUT, - CONF_MODE, - CONF_NUMBER, -) import esphome.config_validation as cv +from esphome.const import CONF_INPUT, CONF_MODE, CONF_NUMBER from esphome.pins import check_strapping_pin _ESP32C3_SPI_PSRAM_PINS = { diff --git a/esphome/components/esp32/gpio_esp32_c6.py b/esphome/components/esp32/gpio_esp32_c6.py index a1f777c625..bc735f85c4 100644 --- a/esphome/components/esp32/gpio_esp32_c6.py +++ b/esphome/components/esp32/gpio_esp32_c6.py @@ -1,8 +1,7 @@ import logging -from esphome.const import CONF_INPUT, CONF_MODE, CONF_NUMBER - import esphome.config_validation as cv +from esphome.const import CONF_INPUT, CONF_MODE, CONF_NUMBER from esphome.pins import check_strapping_pin _ESP32C6_SPI_PSRAM_PINS = { diff --git a/esphome/components/esp32/gpio_esp32_h2.py b/esphome/components/esp32/gpio_esp32_h2.py index d18ee8a2a6..7413bf4db5 100644 --- a/esphome/components/esp32/gpio_esp32_h2.py +++ b/esphome/components/esp32/gpio_esp32_h2.py @@ -1,8 +1,7 @@ import logging -from esphome.const import CONF_INPUT, CONF_MODE, CONF_NUMBER - import esphome.config_validation as cv +from esphome.const import CONF_INPUT, CONF_MODE, CONF_NUMBER _ESP32H2_SPI_FLASH_PINS = {6, 7, 15, 16, 17, 18, 19, 20, 21} diff --git a/esphome/components/esp32/gpio_esp32_s2.py b/esphome/components/esp32/gpio_esp32_s2.py index 82449532ec..331aeb9d94 100644 --- a/esphome/components/esp32/gpio_esp32_s2.py +++ b/esphome/components/esp32/gpio_esp32_s2.py @@ -1,5 +1,6 @@ import logging +import esphome.config_validation as cv from esphome.const import ( CONF_INPUT, CONF_MODE, @@ -8,8 +9,6 @@ from esphome.const import ( CONF_PULLDOWN, CONF_PULLUP, ) - -import esphome.config_validation as cv from esphome.pins import check_strapping_pin _ESP32S2_SPI_PSRAM_PINS = { diff --git a/esphome/components/esp32/gpio_esp32_s3.py b/esphome/components/esp32/gpio_esp32_s3.py index 8dcbf8c7bb..7120504693 100644 --- a/esphome/components/esp32/gpio_esp32_s3.py +++ b/esphome/components/esp32/gpio_esp32_s3.py @@ -1,12 +1,7 @@ import logging -from esphome.const import ( - CONF_INPUT, - CONF_MODE, - CONF_NUMBER, -) - 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 = { From 341fc659589a592fef60321227209f1014ccf34e Mon Sep 17 00:00:00 2001 From: FreeBear-nc <67865163+FreeBear-nc@users.noreply.github.com> Date: Mon, 29 Jul 2024 21:05:25 +0100 Subject: [PATCH 1835/2101] Add microAmp and milliAmp to defined units (#7157) --- esphome/const.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/const.py b/esphome/const.py index 4357963384..37844e1047 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1033,11 +1033,13 @@ UNIT_KILOWATT_HOURS = "kWh" UNIT_LUX = "lx" UNIT_METER = "m" UNIT_METER_PER_SECOND_SQUARED = "m/s²" +UNIT_MICROAMP = "µA" UNIT_MICROGRAMS_PER_CUBIC_METER = "µg/m³" UNIT_MICROMETER = "µm" UNIT_MICROSIEMENS_PER_CENTIMETER = "µS/cm" UNIT_MICROSILVERTS_PER_HOUR = "µSv/h" UNIT_MICROTESLA = "µT" +UNIT_MILLIAMP = "mA" UNIT_MILLIGRAMS_PER_CUBIC_METER = "mg/m³" UNIT_MILLIMETER = "mm" UNIT_MILLISECOND = "ms" From 25c8676d80cb9a6b75cd6413aa4f9a99f3a662e5 Mon Sep 17 00:00:00 2001 From: RubyBailey <60991881+RubyBailey@users.noreply.github.com> Date: Mon, 29 Jul 2024 16:20:29 -0700 Subject: [PATCH 1836/2101] Fix for Mitsubishi units that only support cooling (#7143) --- esphome/components/mitsubishi/mitsubishi.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/esphome/components/mitsubishi/mitsubishi.cpp b/esphome/components/mitsubishi/mitsubishi.cpp index a02aabf14d..449c8fc712 100644 --- a/esphome/components/mitsubishi/mitsubishi.cpp +++ b/esphome/components/mitsubishi/mitsubishi.cpp @@ -110,7 +110,7 @@ void MitsubishiClimate::transmit_state() { // Byte 15: HVAC specfic, i.e. POWERFUL, SMART SET, PLASMA, always 0x00 // Byte 16: Constant 0x00 // Byte 17: Checksum: SUM[Byte0...Byte16] - uint8_t remote_state[18] = {0x23, 0xCB, 0x26, 0x01, 0x00, 0x20, 0x08, 0x00, 0x00, + uint8_t remote_state[18] = {0x23, 0xCB, 0x26, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; switch (this->mode) { @@ -136,6 +136,12 @@ void MitsubishiClimate::transmit_state() { break; case climate::CLIMATE_MODE_OFF: default: + remote_state[6] = MITSUBISHI_MODE_COOL; + remote_state[8] = MITSUBISHI_MODE_A_COOL; + if (this->supports_heat_) { + remote_state[6] = MITSUBISHI_MODE_HEAT; + remote_state[8] = MITSUBISHI_MODE_A_HEAT; + } remote_state[5] = MITSUBISHI_OFF; break; } From 12e840ee88705b063817e48c7f8a15f817103ad5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Jul 2024 11:36:09 +1200 Subject: [PATCH 1837/2101] Bump docker/setup-buildx-action from 3.5.0 to 3.6.1 in the docker-actions group (#7159) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-docker.yml | 2 +- .github/workflows/release.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-docker.yml b/.github/workflows/ci-docker.yml index 2b4539105b..91c02b0a17 100644 --- a/.github/workflows/ci-docker.yml +++ b/.github/workflows/ci-docker.yml @@ -46,7 +46,7 @@ jobs: with: python-version: "3.9" - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3.5.0 + uses: docker/setup-buildx-action@v3.6.1 - name: Set up QEMU uses: docker/setup-qemu-action@v3.2.0 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index efec556059..d454076c84 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -90,7 +90,7 @@ jobs: python-version: "3.9" - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3.5.0 + uses: docker/setup-buildx-action@v3.6.1 - name: Set up QEMU if: matrix.platform != 'linux/amd64' uses: docker/setup-qemu-action@v3.2.0 @@ -184,7 +184,7 @@ jobs: merge-multiple: true - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3.5.0 + uses: docker/setup-buildx-action@v3.6.1 - name: Log in to docker hub if: matrix.registry == 'dockerhub' From 7c1aa771aaa9c9ea2f2c42a0b981ef8267a9d664 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Tue, 30 Jul 2024 09:41:34 +1000 Subject: [PATCH 1838/2101] LVGL stage 2 (#7129) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/lvgl/__init__.py | 38 +++++--- esphome/components/lvgl/btn.py | 25 +++++ esphome/components/lvgl/defines.py | 9 +- esphome/components/lvgl/helpers.py | 1 - esphome/components/lvgl/label.py | 21 ++-- esphome/components/lvgl/lv_validation.py | 79 ++++++++++++--- esphome/components/lvgl/lvgl_esphome.cpp | 6 ++ esphome/components/lvgl/lvgl_esphome.h | 59 ++++++++++-- esphome/components/lvgl/obj.py | 11 +-- esphome/components/lvgl/schemas.py | 64 +++++++------ esphome/components/lvgl/touchscreens.py | 46 +++++++++ esphome/components/lvgl/types.py | 112 +++++++++++++++++----- esphome/components/lvgl/widget.py | 73 ++------------ esphome/core/defines.h | 1 + tests/components/lvgl/common.yaml | 10 ++ tests/components/lvgl/logo-text.svg | 25 +++++ tests/components/lvgl/lvgl-package.yaml | 102 +++++++++++++++++++- tests/components/lvgl/test.esp32-idf.yaml | 4 +- 18 files changed, 503 insertions(+), 183 deletions(-) create mode 100644 esphome/components/lvgl/btn.py create mode 100644 esphome/components/lvgl/touchscreens.py create mode 100644 tests/components/lvgl/logo-text.svg diff --git a/esphome/components/lvgl/__init__.py b/esphome/components/lvgl/__init__.py index 2f3bd69546..c454a61957 100644 --- a/esphome/components/lvgl/__init__.py +++ b/esphome/components/lvgl/__init__.py @@ -16,13 +16,20 @@ from esphome.final_validate import full_config from esphome.helpers import write_file_if_changed from . import defines as df, helpers, lv_validation as lvalid +from .btn import btn_spec from .label import label_spec from .lvcode import ConstantLiteral, LvContext - -# from .menu import menu_spec from .obj import obj_spec -from .schemas import WIDGET_TYPES, any_widget_schema, obj_schema -from .types import FontEngine, LvglComponent, lv_disp_t_ptr, lv_font_t, lvgl_ns +from .schemas import any_widget_schema, obj_schema +from .touchscreens import touchscreen_schema, touchscreens_to_code +from .types import ( + WIDGET_TYPES, + FontEngine, + LvglComponent, + lv_disp_t_ptr, + lv_font_t, + lvgl_ns, +) from .widget import LvScrActType, Widget, add_widgets, set_obj_properties DOMAIN = "lvgl" @@ -31,11 +38,8 @@ AUTO_LOAD = ("key_provider",) CODEOWNERS = ("@clydebarrow",) LOGGER = logging.getLogger(__name__) -for widg in ( - label_spec, - obj_spec, -): - WIDGET_TYPES[widg.name] = widg +for w_type in (label_spec, obj_spec, btn_spec): + WIDGET_TYPES[w_type.name] = w_type lv_scr_act_spec = LvScrActType() lv_scr_act = Widget.create( @@ -93,7 +97,7 @@ def final_validation(config): "Using auto_clear_enabled: true in display config not compatible with LVGL" ) buffer_frac = config[CONF_BUFFER_SIZE] - if not CORE.is_host and buffer_frac > 0.5 and "psram" not in global_config: + if CORE.is_esp32 and buffer_frac > 0.5 and "psram" not in global_config: LOGGER.warning("buffer_size: may need to be reduced without PSRAM") @@ -132,7 +136,7 @@ async def to_code(config): cg.add_global(lvgl_ns.using) lv_component = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(lv_component, config) - Widget.create(config[CONF_ID], lv_component, WIDGET_TYPES[df.CONF_OBJ], config) + Widget.create(config[CONF_ID], lv_component, obj_spec, config) for display in config[df.CONF_DISPLAYS]: cg.add(lv_component.add_display(await cg.get_variable(display))) @@ -152,7 +156,7 @@ async def to_code(config): await cg.get_variable(font) cg.new_Pvariable(ID(f"{font}_engine", True, type=FontEngine), MockObj(font)) default_font = config[df.CONF_DEFAULT_FONT] - if default_font not in helpers.lv_fonts_used: + if not lvalid.is_lv_font(default_font): add_define( "LV_FONT_CUSTOM_DECLARE", f"LV_FONT_DECLARE(*{df.DEFAULT_ESPHOME_FONT})" ) @@ -161,12 +165,15 @@ async def to_code(config): True, type=lv_font_t.operator("ptr").operator("const"), ) - cg.new_variable(globfont_id, MockObj(default_font)) + cg.new_variable( + globfont_id, MockObj(await lvalid.lv_font.process(default_font)) + ) add_define("LV_FONT_DEFAULT", df.DEFAULT_ESPHOME_FONT) else: - add_define("LV_FONT_DEFAULT", default_font) + add_define("LV_FONT_DEFAULT", await lvalid.lv_font.process(default_font)) with LvContext(): + await touchscreens_to_code(lv_component, config) await set_obj_properties(lv_scr_act, config) await add_widgets(lv_scr_act, config) Widget.set_completed() @@ -190,7 +197,7 @@ FINAL_VALIDATE_SCHEMA = final_validation CONFIG_SCHEMA = ( cv.polling_component_schema("1s") - .extend(obj_schema("obj")) + .extend(obj_schema(obj_spec)) .extend( { cv.GenerateID(CONF_ID): cv.declare_id(LvglComponent), @@ -207,6 +214,7 @@ CONFIG_SCHEMA = ( ), cv.Optional(df.CONF_WIDGETS): cv.ensure_list(WIDGET_SCHEMA), cv.Optional(df.CONF_TRANSPARENCY_KEY, default=0x000400): lvalid.lv_color, + cv.GenerateID(df.CONF_TOUCHSCREENS): touchscreen_schema, } ) ).add_extra(cv.has_at_least_one_key(CONF_PAGES, df.CONF_WIDGETS)) diff --git a/esphome/components/lvgl/btn.py b/esphome/components/lvgl/btn.py new file mode 100644 index 0000000000..4f5f88d9e6 --- /dev/null +++ b/esphome/components/lvgl/btn.py @@ -0,0 +1,25 @@ +from esphome.const import CONF_BUTTON +from esphome.cpp_generator import MockObjClass + +from .defines import CONF_MAIN +from .types import LvBoolean, WidgetType + + +class BtnType(WidgetType): + def __init__(self): + super().__init__(CONF_BUTTON, LvBoolean("lv_btn_t"), (CONF_MAIN,)) + + async def to_code(self, w, config): + return [] + + def obj_creator(self, parent: MockObjClass, config: dict): + """ + LVGL 8 calls buttons `btn` + """ + return f"lv_btn_create({parent})" + + def get_uses(self): + return ("btn",) + + +btn_spec = BtnType() diff --git a/esphome/components/lvgl/defines.py b/esphome/components/lvgl/defines.py index 50bdac3865..a2b4ac13fb 100644 --- a/esphome/components/lvgl/defines.py +++ b/esphome/components/lvgl/defines.py @@ -446,6 +446,7 @@ CONF_TILE_ID = "tile_id" CONF_TILES = "tiles" CONF_TITLE = "title" CONF_TOP_LAYER = "top_layer" +CONF_TOUCHSCREENS = "touchscreens" CONF_TRANSPARENCY_KEY = "transparency_key" CONF_THEME = "theme" CONF_VISIBLE_ROW_COUNT = "visible_row_count" @@ -474,14 +475,8 @@ LV_KEYS = LvConstant( ) -# list of widgets and the parts allowed -WIDGET_PARTS = { - CONF_LABEL: (CONF_MAIN, CONF_SCROLLBAR, CONF_SELECTED), - CONF_OBJ: (CONF_MAIN,), -} - DEFAULT_ESPHOME_FONT = "esphome_lv_default_font" def join_enums(enums, prefix=""): - return "|".join(f"(int){prefix}{e.upper()}" for e in enums) + return ConstantLiteral("|".join(f"(int){prefix}{e.upper()}" for e in enums)) diff --git a/esphome/components/lvgl/helpers.py b/esphome/components/lvgl/helpers.py index c8d4948fb1..d67739155c 100644 --- a/esphome/components/lvgl/helpers.py +++ b/esphome/components/lvgl/helpers.py @@ -22,7 +22,6 @@ def add_lv_use(*names): lv_fonts_used = set() esphome_fonts_used = set() -REQUIRED_COMPONENTS = {} lvgl_components_required = set() diff --git a/esphome/components/lvgl/label.py b/esphome/components/lvgl/label.py index 5c4ae6ab0d..0498f39474 100644 --- a/esphome/components/lvgl/label.py +++ b/esphome/components/lvgl/label.py @@ -1,16 +1,27 @@ import esphome.config_validation as cv -from .defines import CONF_LABEL, CONF_LONG_MODE, CONF_RECOLOR, CONF_TEXT, LV_LONG_MODES +from .defines import ( + CONF_LABEL, + CONF_LONG_MODE, + CONF_MAIN, + CONF_RECOLOR, + CONF_SCROLLBAR, + CONF_SELECTED, + CONF_TEXT, + LV_LONG_MODES, +) from .lv_validation import lv_bool, lv_text from .schemas import TEXT_SCHEMA -from .types import lv_label_t -from .widget import Widget, WidgetType +from .types import LvText, WidgetType +from .widget import Widget class LabelType(WidgetType): def __init__(self): super().__init__( CONF_LABEL, + LvText("lv_label_t"), + (CONF_MAIN, CONF_SCROLLBAR, CONF_SELECTED), TEXT_SCHEMA.extend( { cv.Optional(CONF_RECOLOR): lv_bool, @@ -19,10 +30,6 @@ class LabelType(WidgetType): ), ) - @property - def w_type(self): - return lv_label_t - async def to_code(self, w: Widget, config): """For a text object, create and set text""" if value := config.get(CONF_TEXT): diff --git a/esphome/components/lvgl/lv_validation.py b/esphome/components/lvgl/lv_validation.py index 1de63c30ce..533dc582f0 100644 --- a/esphome/components/lvgl/lv_validation.py +++ b/esphome/components/lvgl/lv_validation.py @@ -8,6 +8,7 @@ import esphome.config_validation as cv from esphome.const import CONF_ARGS, CONF_COLOR, CONF_FORMAT from esphome.core import HexInt from esphome.cpp_generator import MockObj +from esphome.cpp_types import uint32 from esphome.helpers import cpp_string_escape from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor @@ -23,6 +24,28 @@ from .lvcode import ConstantLiteral, lv_expr from .types import lv_font_t +def literal_mapper(value, args=()): + if isinstance(value, str): + return ConstantLiteral(value) + return value + + +opacity_consts = 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 + + +opacity = LValidator(opacity_validator, uint32, retmapper=literal_mapper) + + @schema_extractor("one_of") def color(value): if value == SCHEMA_EXTRACT: @@ -43,16 +66,24 @@ def color_retmapper(value): return lv_expr.color_from(MockObj(value)) -def pixels_or_percent(value): +lv_color = LValidator(color, ty.lv_color_t, retmapper=color_retmapper) + + +def pixels_or_percent_validator(value): """A length in one axis - either a number (pixels) or a percentage""" if value == SCHEMA_EXTRACT: return ["pixels", "..%"] if isinstance(value, int): - return str(cv.int_(value)) + return cv.int_(value) # Will throw an exception if not a percentage. return f"lv_pct({int(cv.percentage(value) * 100)})" +pixels_or_percent = LValidator( + pixels_or_percent_validator, uint32, retmapper=literal_mapper +) + + def zoom(value): value = cv.float_range(0.1, 10.0)(value) return int(value * 256) @@ -68,7 +99,7 @@ def angle(value): @schema_extractor("one_of") -def size(value): +def size_validator(value): """A size in one axis - one of "size_content", a number (pixels) or a percentage""" if value == SCHEMA_EXTRACT: return ["size_content", "pixels", "..%"] @@ -79,28 +110,42 @@ def size(value): return "LV_SIZE_CONTENT" raise cv.Invalid("must be 'size_content', a pixel position or a percentage") if isinstance(value, int): - return str(cv.int_(value)) + return cv.int_(value) # Will throw an exception if not a percentage. return f"lv_pct({int(cv.percentage(value) * 100)})" +size = LValidator(size_validator, uint32, retmapper=literal_mapper) + +radius_consts = LvConstant("LV_RADIUS_", "CIRCLE") + + @schema_extractor("one_of") -def opacity(value): - consts = LvConstant("LV_OPA_", "TRANSP", "COVER") +def radius_validator(value): if value == SCHEMA_EXTRACT: - return consts.choices - value = cv.Any(cv.percentage, consts.one_of)(value) + return radius_consts.choices + value = cv.Any(size, cv.percentage, radius_consts.one_of)(value) if isinstance(value, float): return int(value * 255) return value +def id_name(value): + if value == SCHEMA_EXTRACT: + return "id" + return cv.validate_id_name(value) + + +radius = LValidator(radius_validator, uint32, retmapper=literal_mapper) + + def stop_value(value): return cv.int_range(0, 255)(value) -lv_color = LValidator(color, ty.lv_color_t, retmapper=color_retmapper) -lv_bool = LValidator(cv.boolean, cg.bool_, BinarySensor, "get_state()") +lv_bool = LValidator( + cv.boolean, cg.bool_, BinarySensor, "get_state()", retmapper=literal_mapper +) def lvms_validator_(value): @@ -145,26 +190,32 @@ lv_float = LValidator(cv.float_, cg.float_, Sensor, "get_state()") lv_int = LValidator(cv.int_, cg.int_, Sensor, "get_state()") +def is_lv_font(font): + return isinstance(font, str) and font.lower() in LV_FONTS + + class LvFont(LValidator): def __init__(self): def lv_builtin_font(value): fontval = cv.one_of(*LV_FONTS, lower=True)(value) lv_fonts_used.add(fontval) - return "&lv_font_" + fontval + return fontval def validator(value): if value == SCHEMA_EXTRACT: return LV_FONTS - if isinstance(value, str) and value.lower() in LV_FONTS: + if is_lv_font(value): return lv_builtin_font(value) fontval = cv.use_id(Font)(value) esphome_fonts_used.add(fontval) - return requires_component("font")(f"{fontval}_engine->get_lv_font()") + return requires_component("font")(fontval) super().__init__(validator, lv_font_t) async def process(self, value, args=()): - return ConstantLiteral(value) + if is_lv_font(value): + return ConstantLiteral(f"&lv_font_{value}") + return ConstantLiteral(f"{value}_engine->get_lv_font()") lv_font = LvFont() diff --git a/esphome/components/lvgl/lvgl_esphome.cpp b/esphome/components/lvgl/lvgl_esphome.cpp index bdaf8a4f18..74a1b0e7af 100644 --- a/esphome/components/lvgl/lvgl_esphome.cpp +++ b/esphome/components/lvgl/lvgl_esphome.cpp @@ -38,7 +38,9 @@ void LvglComponent::setup() { auto buf_bytes = buffer_pixels * LV_COLOR_DEPTH / 8; auto *buf = lv_custom_mem_alloc(buf_bytes); if (buf == nullptr) { +#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_ERROR ESP_LOGE(TAG, "Malloc failed to allocate %zu bytes", buf_bytes); +#endif this->mark_failed(); this->status_set_error("Memory allocation failure"); return; @@ -85,7 +87,9 @@ size_t lv_millis(void) { return esphome::millis(); } void *lv_custom_mem_alloc(size_t size) { auto *ptr = malloc(size); // NOLINT if (ptr == nullptr) { +#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_ERROR esphome::ESP_LOGE(esphome::lvgl::TAG, "Failed to allocate %zu bytes", size); +#endif } return ptr; } @@ -102,7 +106,9 @@ void *lv_custom_mem_alloc(size_t size) { ptr = heap_caps_malloc(size, cap_bits); } if (ptr == nullptr) { +#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_ERROR esphome::ESP_LOGE(esphome::lvgl::TAG, "Failed to allocate %zu bytes", size); +#endif return nullptr; } #ifdef ESPHOME_LOG_HAS_VERBOSE diff --git a/esphome/components/lvgl/lvgl_esphome.h b/esphome/components/lvgl/lvgl_esphome.h index 988c22917b..a884a27042 100644 --- a/esphome/components/lvgl/lvgl_esphome.h +++ b/esphome/components/lvgl/lvgl_esphome.h @@ -18,23 +18,27 @@ #ifdef USE_LVGL_FONT #include "esphome/components/font/font.h" #endif +#ifdef USE_LVGL_TOUCHSCREEN +#include "esphome/components/touchscreen/touchscreen.h" +#endif // USE_LVGL_TOUCHSCREEN + namespace esphome { namespace lvgl { extern lv_event_code_t lv_custom_event; // NOLINT #ifdef USE_LVGL_COLOR -static lv_color_t lv_color_from(Color color) { return lv_color_make(color.red, color.green, color.blue); } -#endif +inline lv_color_t lv_color_from(Color color) { return lv_color_make(color.red, color.green, color.blue); } +#endif // USE_LVGL_COLOR #if LV_COLOR_DEPTH == 16 static const display::ColorBitness LV_BITNESS = display::ColorBitness::COLOR_BITNESS_565; #elif LV_COLOR_DEPTH == 32 static const display::ColorBitness LV_BITNESS = display::ColorBitness::COLOR_BITNESS_888; -#else +#else // LV_COLOR_DEPTH static const display::ColorBitness LV_BITNESS = display::ColorBitness::COLOR_BITNESS_332; -#endif +#endif // LV_COLOR_DEPTH // Parent class for things that wrap an LVGL object -class LvCompound { +class LvCompound final { public: virtual void set_obj(lv_obj_t *lv_obj) { this->obj = lv_obj; } lv_obj_t *obj{}; @@ -99,6 +103,14 @@ class LvglComponent : public PollingComponent { void set_full_refresh(bool full_refresh) { this->full_refresh_ = full_refresh; } void set_buffer_frac(size_t frac) { this->buffer_frac_ = frac; } lv_disp_t *get_disp() { return this->disp_; } + void set_paused(bool paused, bool show_snow) { + this->paused_ = paused; + if (!paused && lv_scr_act() != nullptr) { + lv_disp_trig_activity(this->disp_); // resets the inactivity time + lv_obj_invalidate(lv_scr_act()); + } + } + bool is_paused() const { return this->paused_; } protected: void draw_buffer_(const lv_area_t *area, const uint8_t *ptr); @@ -107,13 +119,48 @@ class LvglComponent : public PollingComponent { lv_disp_draw_buf_t draw_buf_{}; lv_disp_drv_t disp_drv_{}; lv_disp_t *disp_{}; + bool paused_{}; std::vector> init_lambdas_; size_t buffer_frac_{1}; bool full_refresh_{}; }; +#ifdef USE_LVGL_TOUCHSCREEN +class LVTouchListener : public touchscreen::TouchListener, public Parented { + public: + LVTouchListener(uint16_t long_press_time, uint16_t long_press_repeat_time) { + lv_indev_drv_init(&this->drv_); + 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(d->user_data); + if (l->touch_pressed_) { + data->point.x = l->touch_point_.x; + data->point.y = l->touch_point_.y; + data->state = LV_INDEV_STATE_PRESSED; + } else { + data->state = LV_INDEV_STATE_RELEASED; + } + }; + } + void update(const touchscreen::TouchPoints_t &tpoints) override { + this->touch_pressed_ = !this->parent_->is_paused() && !tpoints.empty(); + if (this->touch_pressed_) + this->touch_point_ = tpoints[0]; + } + void release() override { touch_pressed_ = false; } + lv_indev_drv_t *get_drv() { return &this->drv_; } + + protected: + lv_indev_drv_t drv_{}; + touchscreen::TouchPoint touch_point_{}; + bool touch_pressed_{}; +}; +#endif // USE_LVGL_TOUCHSCREEN } // namespace lvgl } // namespace esphome -#endif +#endif // USE_LVGL diff --git a/esphome/components/lvgl/obj.py b/esphome/components/lvgl/obj.py index fba20bef36..92c4f63d2d 100644 --- a/esphome/components/lvgl/obj.py +++ b/esphome/components/lvgl/obj.py @@ -1,6 +1,5 @@ -from .defines import CONF_OBJ -from .types import lv_obj_t -from .widget import WidgetType +from .defines import CONF_MAIN, CONF_OBJ +from .types import WidgetType, lv_obj_t class ObjType(WidgetType): @@ -9,11 +8,7 @@ class ObjType(WidgetType): """ def __init__(self): - super().__init__(CONF_OBJ, schema={}, modify_schema={}) - - @property - def w_type(self): - return lv_obj_t + super().__init__(CONF_OBJ, lv_obj_t, (CONF_MAIN,), schema={}, modify_schema={}) async def to_code(self, w, config): return [] diff --git a/esphome/components/lvgl/schemas.py b/esphome/components/lvgl/schemas.py index 4ae5824151..9f6d984545 100644 --- a/esphome/components/lvgl/schemas.py +++ b/esphome/components/lvgl/schemas.py @@ -3,15 +3,9 @@ from esphome.const import CONF_ARGS, CONF_FORMAT, CONF_ID, CONF_STATE, CONF_TYPE from esphome.schema_extractors import SCHEMA_EXTRACT from . import defines as df, lv_validation as lvalid, types as ty -from .defines import WIDGET_PARTS -from .helpers import ( - REQUIRED_COMPONENTS, - add_lv_use, - requires_component, - validate_printf, -) +from .helpers import add_lv_use, requires_component, validate_printf from .lv_validation import lv_font -from .types import WIDGET_TYPES, get_widget_type +from .types import WIDGET_TYPES, WidgetType # A schema for text properties TEXT_SCHEMA = cv.Schema( @@ -46,9 +40,9 @@ STYLE_PROPS = { "bg_dither_mode": df.LvConstant("LV_DITHER_", "NONE", "ORDERED", "ERR_DIFF").one_of, "bg_grad_dir": df.LvConstant("LV_GRAD_DIR_", "NONE", "HOR", "VER").one_of, "bg_grad_stop": lvalid.stop_value, - "bg_img_opa": lvalid.opacity, - "bg_img_recolor": lvalid.lv_color, - "bg_img_recolor_opa": lvalid.opacity, + "bg_image_opa": lvalid.opacity, + "bg_image_recolor": lvalid.lv_color, + "bg_image_recolor_opa": lvalid.opacity, "bg_main_stop": lvalid.stop_value, "bg_opa": lvalid.opacity, "border_color": lvalid.lv_color, @@ -60,8 +54,8 @@ STYLE_PROPS = { "border_width": cv.positive_int, "clip_corner": lvalid.lv_bool, "height": lvalid.size, - "img_recolor": lvalid.lv_color, - "img_recolor_opa": lvalid.opacity, + "image_recolor": lvalid.lv_color, + "image_recolor_opa": lvalid.opacity, "line_width": cv.positive_int, "line_dash_width": cv.positive_int, "line_dash_gap": cv.positive_int, @@ -108,12 +102,21 @@ STYLE_PROPS = { "max_width": lvalid.pixels_or_percent, "min_height": lvalid.pixels_or_percent, "min_width": lvalid.pixels_or_percent, - "radius": cv.Any(lvalid.size, df.LvConstant("LV_RADIUS_", "CIRCLE").one_of), + "radius": lvalid.radius, "width": lvalid.size, "x": lvalid.pixels_or_percent, "y": lvalid.pixels_or_percent, } +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", + "image_recolor": "img_recolor", + "image_recolor_opa": "img_recolor_opa", +} + # Complete object style schema STYLE_SCHEMA = cv.Schema({cv.Optional(k): v for k, v in STYLE_PROPS.items()}).extend( { @@ -132,25 +135,23 @@ SET_STATE_SCHEMA = cv.Schema( {cv.Optional(state): lvalid.lv_bool for state in df.STATES} ) # Setting object flags -FLAG_SCHEMA = cv.Schema({cv.Optional(flag): cv.boolean for flag in df.OBJ_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) -def part_schema(widget_type): +def part_schema(widget_type: WidgetType): """ Generate a schema for the various parts (e.g. main:, indicator:) of a widget type :param widget_type: The type of widget to generate for :return: """ - parts = WIDGET_PARTS.get(widget_type) - if parts is None: - parts = (df.CONF_MAIN,) + parts = widget_type.parts return cv.Schema({cv.Optional(part): STATE_SCHEMA for part in parts}).extend( STATE_SCHEMA ) -def obj_schema(widget_type: str): +def obj_schema(widget_type: WidgetType): """ Create a schema for a widget type itself i.e. no allowance for children :param widget_type: @@ -187,13 +188,12 @@ STYLED_TEXT_SCHEMA = cv.maybe_simple_value( STYLE_SCHEMA.extend(TEXT_SCHEMA), key=df.CONF_TEXT ) - ALL_STYLES = { **STYLE_PROPS, } -def container_validator(schema, widget_type): +def container_validator(schema, widget_type: WidgetType): """ Create a validator for a container given the widget type :param schema: Base schema to extend @@ -203,13 +203,16 @@ def container_validator(schema, widget_type): def validator(value): result = schema - if w_sch := WIDGET_TYPES[widget_type].schema: + if w_sch := widget_type.schema: result = result.extend(w_sch) if value and (layout := value.get(df.CONF_LAYOUT)): if not isinstance(layout, dict): raise cv.Invalid("Layout value must be a dict") ltype = layout.get(CONF_TYPE) add_lv_use(ltype) + result = result.extend( + {cv.Optional(df.CONF_WIDGETS): cv.ensure_list(any_widget_schema())} + ) if value == SCHEMA_EXTRACT: return result return result(value) @@ -217,7 +220,7 @@ def container_validator(schema, widget_type): return validator -def container_schema(widget_type, extras=None): +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 the extras passed in, plus any defined for the specific widget being specified. @@ -225,15 +228,16 @@ def container_schema(widget_type, extras=None): :param extras: Additional options to be made available, e.g. layout properties for children :return: The schema for this type of widget. """ - lv_type = get_widget_type(widget_type) - schema = obj_schema(widget_type).extend({cv.GenerateID(): cv.declare_id(lv_type)}) + schema = obj_schema(widget_type).extend( + {cv.GenerateID(): cv.declare_id(widget_type.w_type)} + ) if extras: schema = schema.extend(extras) # Delayed evaluation for recursion return container_validator(schema, widget_type) -def widget_schema(widget_type, extras=None): +def widget_schema(widget_type: WidgetType, extras=None): """ Create a schema for a given widget type :param widget_type: The name of the widget @@ -241,9 +245,9 @@ def widget_schema(widget_type, extras=None): :return: """ validator = container_schema(widget_type, extras=extras) - if required := REQUIRED_COMPONENTS.get(widget_type): + if required := widget_type.required_component: validator = cv.All(validator, requires_component(required)) - return cv.Exclusive(widget_type, df.CONF_WIDGETS), validator + return cv.Exclusive(widget_type.name, df.CONF_WIDGETS), validator # All widget schemas must be defined before this is called. @@ -257,4 +261,4 @@ def any_widget_schema(extras=None): :param extras: Additional schema to be applied to each generated one :return: """ - return cv.Any(dict(widget_schema(wt, extras) for wt in WIDGET_PARTS)) + return cv.Any(dict(widget_schema(wt, extras) for wt in WIDGET_TYPES.values())) diff --git a/esphome/components/lvgl/touchscreens.py b/esphome/components/lvgl/touchscreens.py new file mode 100644 index 0000000000..a0d4a3e4ad --- /dev/null +++ b/esphome/components/lvgl/touchscreens.py @@ -0,0 +1,46 @@ +import esphome.codegen as cg +from esphome.components.touchscreen import CONF_TOUCHSCREEN_ID, Touchscreen +import esphome.config_validation as cv +from esphome.const import CONF_ID +from esphome.core import CORE, TimePeriod + +from .defines import ( + CONF_LONG_PRESS_REPEAT_TIME, + CONF_LONG_PRESS_TIME, + CONF_TOUCHSCREENS, +) +from .helpers import lvgl_components_required +from .lv_validation import lv_milliseconds +from .lvcode import lv +from .types import LVTouchListener + +PRESS_TIME = cv.All(lv_milliseconds, cv.Range(max=TimePeriod(milliseconds=65535))) +CONF_TOUCHSCREEN = "touchscreen" +TOUCHSCREENS_CONFIG = cv.maybe_simple_value( + { + cv.Required(CONF_TOUCHSCREEN_ID): cv.use_id(Touchscreen), + cv.Optional(CONF_LONG_PRESS_TIME, default="400ms"): PRESS_TIME, + cv.Optional(CONF_LONG_PRESS_REPEAT_TIME, default="100ms"): PRESS_TIME, + cv.GenerateID(): cv.declare_id(LVTouchListener), + }, + key=CONF_TOUCHSCREEN_ID, +) + + +def touchscreen_schema(config): + value = cv.ensure_list(TOUCHSCREENS_CONFIG)(config) + if value or CONF_TOUCHSCREEN not in CORE.loaded_integrations: + return value + return [TOUCHSCREENS_CONFIG(config)] + + +async def touchscreens_to_code(var, config): + for tconf in config.get(CONF_TOUCHSCREENS) or (): + lvgl_components_required.add(CONF_TOUCHSCREEN) + touchscreen = await cg.get_variable(tconf[CONF_TOUCHSCREEN_ID]) + 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) + await cg.register_parented(listener, var) + lv.indev_drv_register(listener.get_drv()) + cg.add(touchscreen.register_listener(listener)) diff --git a/esphome/components/lvgl/types.py b/esphome/components/lvgl/types.py index 3c043d266d..60291ea54a 100644 --- a/esphome/components/lvgl/types.py +++ b/esphome/components/lvgl/types.py @@ -1,7 +1,22 @@ from esphome import codegen as cg from esphome.core import ID +from esphome.cpp_generator import MockObjClass + +from .defines import CONF_TEXT + + +class LvType(cg.MockObjClass): + def __init__(self, *args, **kwargs): + parens = kwargs.pop("parents", ()) + super().__init__(*args, parents=parens + (lv_obj_base_t,)) + self.args = kwargs.pop("largs", [(lv_obj_t_ptr, "obj")]) + self.value = kwargs.pop("lvalue", lambda w: w.obj) + self.has_on_value = kwargs.pop("has_on_value", False) + self.value_property = None + + def get_arg_type(self): + return self.args[0][0] if len(self.args) else None -from .defines import CONF_LABEL, CONF_OBJ, CONF_TEXT uint16_t_ptr = cg.uint16.operator("ptr") lvgl_ns = cg.esphome_ns.namespace("lvgl") @@ -18,25 +33,15 @@ 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_ptr = cg.global_ns.struct("lv_disp_t").operator("ptr") lv_color_t = cg.global_ns.struct("lv_color_t") +LVTouchListener = lvgl_ns.class_("LVTouchListener") +LVEncoderListener = lvgl_ns.class_("LVEncoderListener") +lv_obj_t = LvType("lv_obj_t") # this will be populated later, in __init__.py to avoid circular imports. WIDGET_TYPES: dict = {} -class LvType(cg.MockObjClass): - def __init__(self, *args, **kwargs): - parens = kwargs.pop("parents", ()) - super().__init__(*args, parents=parens + (lv_obj_base_t,)) - self.args = kwargs.pop("largs", [(lv_obj_t_ptr, "obj")]) - self.value = kwargs.pop("lvalue", lambda w: w.obj) - self.has_on_value = kwargs.pop("has_on_value", False) - self.value_property = None - - def get_arg_type(self): - return self.args[0][0] if len(self.args) else None - - class LvText(LvType): def __init__(self, *args, **kwargs): super().__init__( @@ -48,17 +53,74 @@ class LvText(LvType): self.value_property = CONF_TEXT -lv_obj_t = LvType("lv_obj_t") -lv_label_t = LvText("lv_label_t") - -LV_TYPES = { - CONF_LABEL: lv_label_t, - CONF_OBJ: lv_obj_t, -} - - -def get_widget_type(typestr: str) -> LvType: - return LV_TYPES[typestr] +class LvBoolean(LvType): + def __init__(self, *args, **kwargs): + super().__init__( + *args, + largs=[(cg.bool_, "x")], + lvalue=lambda w: w.is_checked(), + has_on_value=True, + **kwargs, + ) CUSTOM_EVENT = ID("lv_custom_event", False, type=lv_event_code_t) + + +class WidgetType: + """ + Describes a type of Widget, e.g. "bar" or "line" + """ + + def __init__(self, name, w_type, parts, schema=None, modify_schema=None): + """ + :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 + """ + self.name = name + self.w_type = w_type + self.parts = parts + self.schema = schema or {} + if modify_schema is None: + self.modify_schema = schema + else: + self.modify_schema = modify_schema + + @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 + :return: Generated code as a list of text lines + """ + raise NotImplementedError(f"No to_code defined for {self.name}") + + 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 f"lv_{self.name}_create({parent})" + + def get_uses(self): + """ + Get a list of other widgets used by this one + :return: + """ + return () diff --git a/esphome/components/lvgl/widget.py b/esphome/components/lvgl/widget.py index 44f277f1c3..4755d8b21d 100644 --- a/esphome/components/lvgl/widget.py +++ b/esphome/components/lvgl/widget.py @@ -21,78 +21,19 @@ from .defines import ( ) from .helpers import add_lv_use from .lvcode import ConstantLiteral, add_line_marks, lv, lv_add, lv_assign, lv_obj -from .schemas import ALL_STYLES -from .types import WIDGET_TYPES, LvCompound, lv_obj_t +from .schemas import ALL_STYLES, STYLE_REMAP +from .types import WIDGET_TYPES, WidgetType, lv_obj_t EVENT_LAMB = "event_lamb__" -class WidgetType: - """ - Describes a type of Widget, e.g. "bar" or "line" - """ - - def __init__(self, name, schema=None, modify_schema=None): - """ - :param name: The widget name, e.g. "bar" - :param schema: The config schema for defining a widget - :param modify_schema: A schema to update the widget - """ - self.name = name - self.schema = schema or {} - if modify_schema is None: - self.modify_schema = schema - else: - self.modify_schema = modify_schema - - @property - def animated(self): - return False - - @property - def w_type(self): - """ - Get the type associated with this widget - :return: - """ - return lv_obj_t - - 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 - :return: Generated code as a list of text lines - """ - raise NotImplementedError(f"No to_code defined for {self.name}") - - 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 f"lv_{self.name}_create({parent})" - - def get_uses(self): - """ - Get a list of other widgets used by this one - :return: - """ - return () - - class LvScrActType(WidgetType): """ A "widget" representing the active screen. """ def __init__(self): - super().__init__("lv_scr_act()") + super().__init__("lv_scr_act()", lv_obj_t, ()) def obj_creator(self, parent: MockObjClass, config: dict): return [] @@ -263,7 +204,9 @@ async def set_obj_properties(w: Widget, config): }.items(): if isinstance(ALL_STYLES[prop], LValidator): value = await ALL_STYLES[prop].process(value) - w.set_style(prop, value, lv_state) + # Remapping for backwards compatibility of style names + prop_r = STYLE_REMAP.get(prop, prop) + w.set_style(prop_r, value, lv_state) flag_clr = set() flag_set = set() props = parts[CONF_MAIN][CONF_DEFAULT] @@ -291,10 +234,10 @@ async def set_obj_properties(w: Widget, config): else: clears.add(key) if adds: - adds = ConstantLiteral(join_enums(adds, "LV_STATE_")) + adds = join_enums(adds, "LV_STATE_") w.add_state(adds) if clears: - clears = ConstantLiteral(join_enums(clears, "LV_STATE_")) + clears = join_enums(clears, "LV_STATE_") w.clear_state(clears) for key, value in lambs.items(): lamb = await cg.process_lambda(value, [], return_type=cg.bool_) diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 9d453260ab..6ba5b64761 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -41,6 +41,7 @@ #define USE_LVGL #define USE_LVGL_FONT #define USE_LVGL_IMAGE +#define USE_LVGL_TOUCHSCREEN #define USE_MDNS #define USE_MEDIA_PLAYER #define USE_MQTT diff --git a/tests/components/lvgl/common.yaml b/tests/components/lvgl/common.yaml index e69de29bb2..8b92f8caa7 100644 --- a/tests/components/lvgl/common.yaml +++ b/tests/components/lvgl/common.yaml @@ -0,0 +1,10 @@ +touchscreen: + - platform: ft63x6 + id: tft_touch + display: tft_display + update_interval: 50ms + threshold: 1 + calibration: + x_max: 240 + y_max: 320 + diff --git a/tests/components/lvgl/logo-text.svg b/tests/components/lvgl/logo-text.svg new file mode 100644 index 0000000000..4950806a36 --- /dev/null +++ b/tests/components/lvgl/logo-text.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/tests/components/lvgl/lvgl-package.yaml b/tests/components/lvgl/lvgl-package.yaml index 856e7c3e9d..696c749876 100644 --- a/tests/components/lvgl/lvgl-package.yaml +++ b/tests/components/lvgl/lvgl-package.yaml @@ -1,9 +1,10 @@ -color: - - id: light_blue - hex: "3340FF" - lvgl: + log_level: TRACE bg_color: light_blue + touchscreens: + - touchscreen_id: tft_touch + long_press_repeat_time: 200ms + long_press_time: 500ms widgets: - label: text: Hello world @@ -17,8 +18,101 @@ lvgl: text_color: 0xFFFFFF align: bottom_mid text_font: space16 + - obj: + align: center + arc_opa: COVER + arc_color: 0xFF0000 + arc_rounded: false + arc_width: 3 + 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 + bg_image_recolor: light_blue + bg_image_recolor_opa: 50% + bg_main_stop: 0 + bg_opa: 20% + border_color: 0x00FF00 + border_opa: cover + border_post: true + border_side: [bottom, left] + border_width: 4 + clip_corner: false + height: 50% + image_recolor: light_blue + image_recolor_opa: cover + line_width: 10 + line_dash_width: 10 + line_dash_gap: 10 + line_rounded: false + line_color: light_blue + opa: cover + opa_layered: cover + outline_color: light_blue + outline_opa: cover + outline_pad: 10px + outline_width: 10px + pad_all: 10px + pad_bottom: 10px + pad_column: 10px + pad_left: 10px + pad_right: 10px + pad_row: 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 + text_align: auto + text_color: light_blue + text_decor: [underline, strikethrough] + text_font: montserrat_18 + text_letter_space: 4 + text_line_space: 4 + text_opa: cover + transform_angle: 180 + transform_height: 100 + transform_pivot_x: 50% + transform_pivot_y: 50% + transform_zoom: 0.5 + translate_x: 10 + translate_y: 10 + max_height: 100 + max_width: 200 + min_height: 20% + min_width: 20% + radius: circle + width: 10px + x: 100 + y: 120 + - button: + width: 20% + height: 10% + pressed: + bg_color: light_blue + widgets: + - label: + text: Button font: - file: "gfonts://Roboto" id: space16 bpp: 4 + +image: + - id: cat_img + resize: 256x48 + file: $component_dir/logo-text.svg + - id: dog_img + file: $component_dir/logo-text.svg + resize: 256x48 + type: TRANSPARENT_BINARY + +color: + - id: light_blue + hex: "3340FF" diff --git a/tests/components/lvgl/test.esp32-idf.yaml b/tests/components/lvgl/test.esp32-idf.yaml index f159431b99..eab75b05f3 100644 --- a/tests/components/lvgl/test.esp32-idf.yaml +++ b/tests/components/lvgl/test.esp32-idf.yaml @@ -19,7 +19,9 @@ display: mirror_y: true data_rate: 80MHz cs_pin: GPIO20 - dc_pin: GPIO15 + dc_pin: + number: GPIO15 + ignore_strapping_warning: true auto_clear_enabled: false invert_colors: false update_interval: never From 6e21d79bde02b90e4273b7a92f2caa8604a3d687 Mon Sep 17 00:00:00 2001 From: FreeBear-nc <67865163+FreeBear-nc@users.noreply.github.com> Date: Tue, 30 Jul 2024 02:15:27 +0100 Subject: [PATCH 1839/2101] [pid] Add get_min_integral() and get_max_integral() (#7162) --- esphome/components/pid/pid_climate.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/components/pid/pid_climate.h b/esphome/components/pid/pid_climate.h index 5ae97ee10b..b5275e9775 100644 --- a/esphome/components/pid/pid_climate.h +++ b/esphome/components/pid/pid_climate.h @@ -44,6 +44,8 @@ class PIDClimate : public climate::Climate, public Component { float get_kp() { return controller_.kp_; } float get_ki() { return controller_.ki_; } float get_kd() { return controller_.kd_; } + float get_min_integral() { return controller_.min_integral_; } + float get_max_integral() { return controller_.max_integral_; } float get_proportional_term() const { return controller_.proportional_term_; } float get_integral_term() const { return controller_.integral_term_; } float get_derivative_term() const { return controller_.derivative_term_; } From 83bb7d0266459ebae70d663addabc45a1f112092 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 30 Jul 2024 13:23:30 +1200 Subject: [PATCH 1840/2101] [code-quality] Organise bluetooth related imports (#7155) --- esphome/components/ble_client/__init__.py | 8 ++++---- esphome/components/ble_client/output/__init__.py | 2 +- esphome/components/ble_client/sensor/__init__.py | 7 ++++--- esphome/components/ble_client/switch/__init__.py | 3 ++- esphome/components/ble_client/text_sensor/__init__.py | 7 ++++--- esphome/components/ble_presence/binary_sensor.py | 6 +++--- esphome/components/ble_rssi/sensor.py | 4 ++-- esphome/components/ble_scanner/text_sensor.py | 2 +- esphome/components/bluetooth_proxy/__init__.py | 6 +++--- esphome/components/esp32_ble/__init__.py | 6 +++--- esphome/components/esp32_ble_beacon/__init__.py | 10 +++++----- esphome/components/esp32_ble_client/__init__.py | 1 - esphome/components/esp32_ble_server/__init__.py | 4 ++-- esphome/components/esp32_ble_tracker/__init__.py | 4 ++-- 14 files changed, 36 insertions(+), 34 deletions(-) diff --git a/esphome/components/ble_client/__init__.py b/esphome/components/ble_client/__init__.py index 34b9868edc..6bf4ff739e 100644 --- a/esphome/components/ble_client/__init__.py +++ b/esphome/components/ble_client/__init__.py @@ -1,7 +1,8 @@ -import esphome.codegen as cg -import esphome.config_validation as cv +from esphome import automation from esphome.automation import maybe_simple_id -from esphome.components import esp32_ble_tracker, esp32_ble_client +import esphome.codegen as cg +from esphome.components import esp32_ble_client, esp32_ble_tracker +import esphome.config_validation as cv from esphome.const import ( CONF_CHARACTERISTIC_UUID, CONF_ID, @@ -13,7 +14,6 @@ from esphome.const import ( CONF_TRIGGER_ID, CONF_VALUE, ) -from esphome import automation AUTO_LOAD = ["esp32_ble_client"] CODEOWNERS = ["@buxtronix", "@clydebarrow"] diff --git a/esphome/components/ble_client/output/__init__.py b/esphome/components/ble_client/output/__init__.py index fd847d80b8..729885eb8b 100644 --- a/esphome/components/ble_client/output/__init__.py +++ b/esphome/components/ble_client/output/__init__.py @@ -1,6 +1,6 @@ import esphome.codegen as cg -import esphome.config_validation as cv from esphome.components import ble_client, esp32_ble_tracker, output +import esphome.config_validation as cv from esphome.const import CONF_CHARACTERISTIC_UUID, CONF_ID, CONF_SERVICE_UUID from .. import ble_client_ns diff --git a/esphome/components/ble_client/sensor/__init__.py b/esphome/components/ble_client/sensor/__init__.py index d0b27c30a9..0c48902a90 100644 --- a/esphome/components/ble_client/sensor/__init__.py +++ b/esphome/components/ble_client/sensor/__init__.py @@ -1,17 +1,18 @@ +from esphome import automation import esphome.codegen as cg +from esphome.components import ble_client, esp32_ble_tracker, sensor import esphome.config_validation as cv -from esphome.components import sensor, ble_client, esp32_ble_tracker from esphome.const import ( CONF_CHARACTERISTIC_UUID, CONF_LAMBDA, + CONF_SERVICE_UUID, CONF_TRIGGER_ID, CONF_TYPE, - CONF_SERVICE_UUID, DEVICE_CLASS_SIGNAL_STRENGTH, STATE_CLASS_MEASUREMENT, UNIT_DECIBEL_MILLIWATT, ) -from esphome import automation + from .. import ble_client_ns DEPENDENCIES = ["ble_client"] diff --git a/esphome/components/ble_client/switch/__init__.py b/esphome/components/ble_client/switch/__init__.py index 2304d65c01..70314e8f30 100644 --- a/esphome/components/ble_client/switch/__init__.py +++ b/esphome/components/ble_client/switch/__init__.py @@ -1,7 +1,8 @@ import esphome.codegen as cg +from esphome.components import ble_client, switch import esphome.config_validation as cv -from esphome.components import switch, ble_client from esphome.const import ICON_BLUETOOTH + from .. import ble_client_ns BLEClientSwitch = ble_client_ns.class_( diff --git a/esphome/components/ble_client/text_sensor/__init__.py b/esphome/components/ble_client/text_sensor/__init__.py index 7a93c4e4ae..479af1a57e 100644 --- a/esphome/components/ble_client/text_sensor/__init__.py +++ b/esphome/components/ble_client/text_sensor/__init__.py @@ -1,13 +1,14 @@ +from esphome import automation import esphome.codegen as cg +from esphome.components import ble_client, esp32_ble_tracker, text_sensor import esphome.config_validation as cv -from esphome.components import text_sensor, ble_client, esp32_ble_tracker from esphome.const import ( CONF_CHARACTERISTIC_UUID, CONF_ID, - CONF_TRIGGER_ID, CONF_SERVICE_UUID, + CONF_TRIGGER_ID, ) -from esphome import automation + from .. import ble_client_ns DEPENDENCIES = ["ble_client"] diff --git a/esphome/components/ble_presence/binary_sensor.py b/esphome/components/ble_presence/binary_sensor.py index 9c24a91a05..d1fdc80289 100644 --- a/esphome/components/ble_presence/binary_sensor.py +++ b/esphome/components/ble_presence/binary_sensor.py @@ -1,13 +1,13 @@ import esphome.codegen as cg -import esphome.config_validation as cv from esphome.components import binary_sensor, esp32_ble_tracker +import esphome.config_validation as cv from esphome.const import ( - CONF_MAC_ADDRESS, - CONF_SERVICE_UUID, CONF_IBEACON_MAJOR, CONF_IBEACON_MINOR, CONF_IBEACON_UUID, + CONF_MAC_ADDRESS, CONF_MIN_RSSI, + CONF_SERVICE_UUID, CONF_TIMEOUT, ) diff --git a/esphome/components/ble_rssi/sensor.py b/esphome/components/ble_rssi/sensor.py index 0543eb0578..e3ba1abfd7 100644 --- a/esphome/components/ble_rssi/sensor.py +++ b/esphome/components/ble_rssi/sensor.py @@ -1,12 +1,12 @@ import esphome.codegen as cg +from esphome.components import esp32_ble_tracker, sensor import esphome.config_validation as cv -from esphome.components import sensor, esp32_ble_tracker from esphome.const import ( CONF_IBEACON_MAJOR, CONF_IBEACON_MINOR, CONF_IBEACON_UUID, - CONF_SERVICE_UUID, CONF_MAC_ADDRESS, + CONF_SERVICE_UUID, DEVICE_CLASS_SIGNAL_STRENGTH, STATE_CLASS_MEASUREMENT, UNIT_DECIBEL_MILLIWATT, diff --git a/esphome/components/ble_scanner/text_sensor.py b/esphome/components/ble_scanner/text_sensor.py index 743403c6a4..96d71a0399 100644 --- a/esphome/components/ble_scanner/text_sensor.py +++ b/esphome/components/ble_scanner/text_sensor.py @@ -1,6 +1,6 @@ import esphome.codegen as cg +from esphome.components import esp32_ble_tracker, text_sensor import esphome.config_validation as cv -from esphome.components import text_sensor, esp32_ble_tracker DEPENDENCIES = ["esp32_ble_tracker"] diff --git a/esphome/components/bluetooth_proxy/__init__.py b/esphome/components/bluetooth_proxy/__init__.py index bec1579d8e..5a4ba36666 100644 --- a/esphome/components/bluetooth_proxy/__init__.py +++ b/esphome/components/bluetooth_proxy/__init__.py @@ -1,8 +1,8 @@ -from esphome.components import esp32_ble_tracker, esp32_ble_client -import esphome.config_validation as cv import esphome.codegen as cg -from esphome.const import CONF_ACTIVE, CONF_ID +from esphome.components import esp32_ble_client, esp32_ble_tracker from esphome.components.esp32 import add_idf_sdkconfig_option +import esphome.config_validation as cv +from esphome.const import CONF_ACTIVE, CONF_ID AUTO_LOAD = ["esp32_ble_client", "esp32_ble_tracker"] DEPENDENCIES = ["api", "esp32"] diff --git a/esphome/components/esp32_ble/__init__.py b/esphome/components/esp32_ble/__init__.py index 472669a381..75cf9d707d 100644 --- a/esphome/components/esp32_ble/__init__.py +++ b/esphome/components/esp32_ble/__init__.py @@ -1,9 +1,9 @@ -import esphome.codegen as cg -import esphome.config_validation as cv from esphome import automation +import esphome.codegen as cg +from esphome.components.esp32 import add_idf_sdkconfig_option, const, get_esp32_variant +import esphome.config_validation as cv from esphome.const import CONF_ENABLE_ON_BOOT, CONF_ID from esphome.core import CORE -from esphome.components.esp32 import add_idf_sdkconfig_option, get_esp32_variant, const DEPENDENCIES = ["esp32"] CODEOWNERS = ["@jesserockz", "@Rapsssito"] diff --git a/esphome/components/esp32_ble_beacon/__init__.py b/esphome/components/esp32_ble_beacon/__init__.py index d063209478..f97f289a0a 100644 --- a/esphome/components/esp32_ble_beacon/__init__.py +++ b/esphome/components/esp32_ble_beacon/__init__.py @@ -1,10 +1,10 @@ import esphome.codegen as cg -import esphome.config_validation as cv -from esphome.components.esp32_ble import CONF_BLE_ID -from esphome.const import CONF_ID, CONF_TYPE, CONF_UUID, CONF_TX_POWER -from esphome.core import CORE, TimePeriod -from esphome.components.esp32 import add_idf_sdkconfig_option from esphome.components import esp32_ble +from esphome.components.esp32 import add_idf_sdkconfig_option +from esphome.components.esp32_ble import CONF_BLE_ID +import esphome.config_validation as cv +from esphome.const import CONF_ID, CONF_TX_POWER, CONF_TYPE, CONF_UUID +from esphome.core import CORE, TimePeriod AUTO_LOAD = ["esp32_ble"] DEPENDENCIES = ["esp32"] diff --git a/esphome/components/esp32_ble_client/__init__.py b/esphome/components/esp32_ble_client/__init__.py index 94a5576d0b..25957ed0da 100644 --- a/esphome/components/esp32_ble_client/__init__.py +++ b/esphome/components/esp32_ble_client/__init__.py @@ -1,5 +1,4 @@ import esphome.codegen as cg - from esphome.components import esp32_ble_tracker AUTO_LOAD = ["esp32_ble_tracker"] diff --git a/esphome/components/esp32_ble_server/__init__.py b/esphome/components/esp32_ble_server/__init__.py index ce9fdc2cf3..9da7d13999 100644 --- a/esphome/components/esp32_ble_server/__init__.py +++ b/esphome/components/esp32_ble_server/__init__.py @@ -1,9 +1,9 @@ import esphome.codegen as cg +from esphome.components import esp32_ble +from esphome.components.esp32 import add_idf_sdkconfig_option import esphome.config_validation as cv from esphome.const import CONF_ID, CONF_MODEL -from esphome.components import esp32_ble from esphome.core import CORE -from esphome.components.esp32 import add_idf_sdkconfig_option AUTO_LOAD = ["esp32_ble"] CODEOWNERS = ["@jesserockz", "@clydebarrow", "@Rapsssito"] diff --git a/esphome/components/esp32_ble_tracker/__init__.py b/esphome/components/esp32_ble_tracker/__init__.py index 1edeaadbfd..0aa8eadd0a 100644 --- a/esphome/components/esp32_ble_tracker/__init__.py +++ b/esphome/components/esp32_ble_tracker/__init__.py @@ -1,10 +1,10 @@ import re -import esphome.codegen as cg -import esphome.config_validation as cv from esphome import automation +import esphome.codegen as cg from esphome.components import esp32_ble from esphome.components.esp32 import add_idf_sdkconfig_option +import esphome.config_validation as cv from esphome.const import ( CONF_ACTIVE, CONF_DURATION, From caa2ea64e35ca883105f1fefeb1aeee5dbf28510 Mon Sep 17 00:00:00 2001 From: Olivier ARCHER Date: Tue, 30 Jul 2024 03:45:19 +0200 Subject: [PATCH 1841/2101] http_request watchdog as a component (#7161) --- CODEOWNERS | 1 + esphome/components/http_request/__init__.py | 2 +- esphome/components/http_request/http_request_arduino.cpp | 4 ++-- esphome/components/http_request/http_request_idf.cpp | 4 ++-- esphome/components/http_request/ota/ota_http_request.cpp | 2 +- esphome/components/watchdog/__init__.py | 1 + esphome/components/{http_request => watchdog}/watchdog.cpp | 2 -- esphome/components/{http_request => watchdog}/watchdog.h | 2 -- 8 files changed, 8 insertions(+), 10 deletions(-) create mode 100644 esphome/components/watchdog/__init__.py rename esphome/components/{http_request => watchdog}/watchdog.cpp (96%) rename esphome/components/{http_request => watchdog}/watchdog.h (88%) diff --git a/CODEOWNERS b/CODEOWNERS index 2fc030453f..d94c34c019 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -427,6 +427,7 @@ esphome/components/veml7700/* @latonita esphome/components/version/* @esphome/core esphome/components/voice_assistant/* @jesserockz esphome/components/wake_on_lan/* @clydebarrow @willwill2will54 +esphome/components/watchdog/* @oarcher esphome/components/waveshare_epaper/* @clydebarrow esphome/components/web_server_base/* @OttoWinter esphome/components/web_server_idf/* @dentra diff --git a/esphome/components/http_request/__init__.py b/esphome/components/http_request/__init__.py index 3ca97b9611..0407bbd326 100644 --- a/esphome/components/http_request/__init__.py +++ b/esphome/components/http_request/__init__.py @@ -14,7 +14,7 @@ from esphome.const import ( from esphome.core import CORE, Lambda DEPENDENCIES = ["network"] -AUTO_LOAD = ["json"] +AUTO_LOAD = ["json", "watchdog"] http_request_ns = cg.esphome_ns.namespace("http_request") HttpRequestComponent = http_request_ns.class_("HttpRequestComponent", cg.Component) diff --git a/esphome/components/http_request/http_request_arduino.cpp b/esphome/components/http_request/http_request_arduino.cpp index 95b1cdc38e..2148d92ad2 100644 --- a/esphome/components/http_request/http_request_arduino.cpp +++ b/esphome/components/http_request/http_request_arduino.cpp @@ -3,12 +3,12 @@ #ifdef USE_ARDUINO #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/log.h" -#include "watchdog.h" - namespace esphome { namespace http_request { diff --git a/esphome/components/http_request/http_request_idf.cpp b/esphome/components/http_request/http_request_idf.cpp index 4fe5585723..3819f5544e 100644 --- a/esphome/components/http_request/http_request_idf.cpp +++ b/esphome/components/http_request/http_request_idf.cpp @@ -3,6 +3,8 @@ #ifdef USE_ESP_IDF #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/log.h" @@ -11,8 +13,6 @@ #include "esp_crt_bundle.h" #endif -#include "watchdog.h" - namespace esphome { namespace http_request { diff --git a/esphome/components/http_request/ota/ota_http_request.cpp b/esphome/components/http_request/ota/ota_http_request.cpp index dcc783ea47..1553de0bc1 100644 --- a/esphome/components/http_request/ota/ota_http_request.cpp +++ b/esphome/components/http_request/ota/ota_http_request.cpp @@ -1,11 +1,11 @@ #include "ota_http_request.h" -#include "../watchdog.h" #include "esphome/core/application.h" #include "esphome/core/defines.h" #include "esphome/core/log.h" #include "esphome/components/md5/md5.h" +#include "esphome/components/watchdog/watchdog.h" #include "esphome/components/ota/ota_backend.h" #include "esphome/components/ota/ota_backend_arduino_esp32.h" #include "esphome/components/ota/ota_backend_arduino_esp8266.h" diff --git a/esphome/components/watchdog/__init__.py b/esphome/components/watchdog/__init__.py new file mode 100644 index 0000000000..6fb87e45a4 --- /dev/null +++ b/esphome/components/watchdog/__init__.py @@ -0,0 +1 @@ +CODEOWNERS = ["@oarcher"] diff --git a/esphome/components/http_request/watchdog.cpp b/esphome/components/watchdog/watchdog.cpp similarity index 96% rename from esphome/components/http_request/watchdog.cpp rename to esphome/components/watchdog/watchdog.cpp index a8519c59ed..3a94a658e8 100644 --- a/esphome/components/http_request/watchdog.cpp +++ b/esphome/components/watchdog/watchdog.cpp @@ -15,7 +15,6 @@ #endif namespace esphome { -namespace http_request { namespace watchdog { static const char *const TAG = "http_request.watchdog"; @@ -72,5 +71,4 @@ uint32_t WatchdogManager::get_timeout_() { } } // namespace watchdog -} // namespace http_request } // namespace esphome diff --git a/esphome/components/http_request/watchdog.h b/esphome/components/watchdog/watchdog.h similarity index 88% rename from esphome/components/http_request/watchdog.h rename to esphome/components/watchdog/watchdog.h index 9b54ae6c82..899ec3fde0 100644 --- a/esphome/components/http_request/watchdog.h +++ b/esphome/components/watchdog/watchdog.h @@ -5,7 +5,6 @@ #include namespace esphome { -namespace http_request { namespace watchdog { class WatchdogManager { @@ -22,5 +21,4 @@ class WatchdogManager { }; } // namespace watchdog -} // namespace http_request } // namespace esphome From d7231fadb1e174fe88f0d293c40265a26cd42ede Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 30 Jul 2024 16:50:12 +1200 Subject: [PATCH 1842/2101] [touchscreen] Allow binary sensor to have multiple pages in config (#7112) * [touchscreen] Allow binary sensor to have multiple pages in config * Sort imports --- .../touchscreen/binary_sensor/__init__.py | 34 +++++++++++++------ .../touchscreen_binary_sensor.cpp | 5 +-- .../binary_sensor/touchscreen_binary_sensor.h | 6 ++-- 3 files changed, 31 insertions(+), 14 deletions(-) diff --git a/esphome/components/touchscreen/binary_sensor/__init__.py b/esphome/components/touchscreen/binary_sensor/__init__.py index 800bc4c2a9..45fefbf814 100644 --- a/esphome/components/touchscreen/binary_sensor/__init__.py +++ b/esphome/components/touchscreen/binary_sensor/__init__.py @@ -1,10 +1,9 @@ import esphome.codegen as cg -import esphome.config_validation as cv - from esphome.components import binary_sensor, display -from esphome.const import CONF_PAGE_ID +import esphome.config_validation as cv +from esphome.const import CONF_PAGE_ID, CONF_PAGES -from .. import touchscreen_ns, CONF_TOUCHSCREEN_ID, Touchscreen, TouchListener +from .. import CONF_TOUCHSCREEN_ID, TouchListener, Touchscreen, touchscreen_ns DEPENDENCIES = ["touchscreen"] @@ -22,7 +21,7 @@ CONF_Y_MIN = "y_min" CONF_Y_MAX = "y_max" -def validate_coords(config): +def _validate_coords(config): if ( config[CONF_X_MAX] < config[CONF_X_MIN] or config[CONF_Y_MAX] < config[CONF_Y_MIN] @@ -33,6 +32,15 @@ def validate_coords(config): return config +def _set_pages(config: dict) -> dict: + if CONF_PAGES in config or CONF_PAGE_ID not in config: + return config + + config = config.copy() + config[CONF_PAGES] = [config.pop(CONF_PAGE_ID)] + return config + + CONFIG_SCHEMA = cv.All( binary_sensor.binary_sensor_schema(TouchscreenBinarySensor) .extend( @@ -42,11 +50,17 @@ CONFIG_SCHEMA = cv.All( cv.Required(CONF_X_MAX): cv.int_range(min=0, max=2000), cv.Required(CONF_Y_MIN): cv.int_range(min=0, max=2000), cv.Required(CONF_Y_MAX): cv.int_range(min=0, max=2000), - cv.Optional(CONF_PAGE_ID): cv.use_id(display.DisplayPage), + cv.Exclusive(CONF_PAGE_ID, group_of_exclusion=CONF_PAGES): cv.use_id( + display.DisplayPage + ), + cv.Exclusive(CONF_PAGES, group_of_exclusion=CONF_PAGES): cv.ensure_list( + cv.use_id(display.DisplayPage) + ), } ) .extend(cv.COMPONENT_SCHEMA), - validate_coords, + _validate_coords, + _set_pages, ) @@ -64,6 +78,6 @@ async def to_code(config): ) ) - if CONF_PAGE_ID in config: - page = await cg.get_variable(config[CONF_PAGE_ID]) - cg.add(var.set_page(page)) + for page_id in config.get(CONF_PAGES, []): + page = await cg.get_variable(page_id) + cg.add(var.add_page(page)) diff --git a/esphome/components/touchscreen/binary_sensor/touchscreen_binary_sensor.cpp b/esphome/components/touchscreen/binary_sensor/touchscreen_binary_sensor.cpp index 6c26ae3626..6cd12d4d0d 100644 --- a/esphome/components/touchscreen/binary_sensor/touchscreen_binary_sensor.cpp +++ b/esphome/components/touchscreen/binary_sensor/touchscreen_binary_sensor.cpp @@ -11,8 +11,9 @@ void TouchscreenBinarySensor::setup() { void TouchscreenBinarySensor::touch(TouchPoint tp) { bool touched = (tp.x >= this->x_min_ && tp.x <= this->x_max_ && tp.y >= this->y_min_ && tp.y <= this->y_max_); - if (this->page_ != nullptr) { - touched &= this->page_ == this->parent_->get_display()->get_active_page(); + if (!this->pages_.empty()) { + auto *current_page = this->parent_->get_display()->get_active_page(); + touched &= std::find(this->pages_.begin(), this->pages_.end(), current_page) != this->pages_.end(); } if (touched) { this->publish_state(true); diff --git a/esphome/components/touchscreen/binary_sensor/touchscreen_binary_sensor.h b/esphome/components/touchscreen/binary_sensor/touchscreen_binary_sensor.h index b56ae562b1..862f41064c 100644 --- a/esphome/components/touchscreen/binary_sensor/touchscreen_binary_sensor.h +++ b/esphome/components/touchscreen/binary_sensor/touchscreen_binary_sensor.h @@ -6,6 +6,8 @@ #include "esphome/core/component.h" #include "esphome/core/helpers.h" +#include + namespace esphome { namespace touchscreen { @@ -30,14 +32,14 @@ class TouchscreenBinarySensor : public binary_sensor::BinarySensor, int16_t get_width() { return this->x_max_ - this->x_min_; } int16_t get_height() { return this->y_max_ - this->y_min_; } - void set_page(display::DisplayPage *page) { this->page_ = page; } + void add_page(display::DisplayPage *page) { this->pages_.push_back(page); } void touch(TouchPoint tp) override; void release() override; protected: int16_t x_min_, x_max_, y_min_, y_max_; - display::DisplayPage *page_{nullptr}; + std::vector pages_{}; }; } // namespace touchscreen From dff6884bedd1585b49d7864e52039f0f14e74fa8 Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt Date: Tue, 30 Jul 2024 16:57:51 -0400 Subject: [PATCH 1843/2101] [micro_wake_word] Fix VAD detection and modify detection computation (#7164) --- esphome/components/micro_wake_word/streaming_model.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/esphome/components/micro_wake_word/streaming_model.cpp b/esphome/components/micro_wake_word/streaming_model.cpp index 013fa2ce6e..d0d2e2df05 100644 --- a/esphome/components/micro_wake_word/streaming_model.cpp +++ b/esphome/components/micro_wake_word/streaming_model.cpp @@ -148,7 +148,7 @@ WakeWordModel::WakeWordModel(const uint8_t *model_start, float probability_cutof }; bool WakeWordModel::determine_detected() { - int32_t sum = 0; + uint32_t sum = 0; for (auto &prob : this->recent_streaming_probabilities_) { sum += prob; } @@ -175,12 +175,14 @@ VADModel::VADModel(const uint8_t *model_start, float probability_cutoff, size_t }; bool VADModel::determine_detected() { - uint8_t max = 0; + uint32_t sum = 0; for (auto &prob : this->recent_streaming_probabilities_) { - max = std::max(prob, max); + sum += prob; } - return max > this->probability_cutoff_; + float sliding_window_average = static_cast(sum) / static_cast(255 * this->sliding_window_size_); + + return sliding_window_average > this->probability_cutoff_; } } // namespace micro_wake_word From dd3dd7a136b9f81a5d3ff7c7296edd031af38f4f Mon Sep 17 00:00:00 2001 From: Adam Allport Date: Tue, 30 Jul 2024 22:30:15 +0100 Subject: [PATCH 1844/2101] fix: Add `pin->setup();` to matrix_keypad.cpp (#7163) --- esphome/components/matrix_keypad/matrix_keypad.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/components/matrix_keypad/matrix_keypad.cpp b/esphome/components/matrix_keypad/matrix_keypad.cpp index 902e574846..f62c75c869 100644 --- a/esphome/components/matrix_keypad/matrix_keypad.cpp +++ b/esphome/components/matrix_keypad/matrix_keypad.cpp @@ -8,6 +8,7 @@ static const char *const TAG = "matrix_keypad"; void MatrixKeypad::setup() { for (auto *pin : this->rows_) { + pin->setup(); if (!has_diodes_) { pin->pin_mode(gpio::FLAG_INPUT); } else { @@ -15,6 +16,7 @@ void MatrixKeypad::setup() { } } for (auto *pin : this->columns_) { + pin->setup(); if (has_pulldowns_) { pin->pin_mode(gpio::FLAG_INPUT); } else { From 8849443bf6e9f56e5c0f682a25a78a6782007a1e Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 31 Jul 2024 16:08:11 +1200 Subject: [PATCH 1845/2101] [update] Implement ``update.perform`` action and ``update.is_available`` condition (#7165) * [update] Fix unimplemented yaml action/condition * Add/update tests --------- Co-authored-by: Keith Burzinski --- .../update/http_request_update.cpp | 4 +- .../http_request/update/http_request_update.h | 2 +- esphome/components/update/__init__.py | 48 +++++++++++++------ esphome/components/update/automation.h | 23 +++++++++ esphome/components/update/update_entity.h | 4 +- tests/components/update/common.yaml | 27 +++++++++++ tests/components/update/test.esp32-ard.yaml | 3 ++ tests/components/update/test.esp8266-ard.yaml | 3 ++ tests/components/update/test.rp2040-ard.yaml | 3 ++ 9 files changed, 98 insertions(+), 19 deletions(-) create mode 100644 esphome/components/update/automation.h diff --git a/esphome/components/http_request/update/http_request_update.cpp b/esphome/components/http_request/update/http_request_update.cpp index 0a14dfd933..059148e7e5 100644 --- a/esphome/components/http_request/update/http_request_update.cpp +++ b/esphome/components/http_request/update/http_request_update.cpp @@ -138,8 +138,8 @@ void HttpRequestUpdate::update() { this->publish_state(); } -void HttpRequestUpdate::perform() { - if (this->state_ != update::UPDATE_STATE_AVAILABLE) { +void HttpRequestUpdate::perform(bool force) { + if (this->state_ != update::UPDATE_STATE_AVAILABLE && !force) { return; } diff --git a/esphome/components/http_request/update/http_request_update.h b/esphome/components/http_request/update/http_request_update.h index a6bc97392b..943231a906 100644 --- a/esphome/components/http_request/update/http_request_update.h +++ b/esphome/components/http_request/update/http_request_update.h @@ -15,7 +15,7 @@ class HttpRequestUpdate : public update::UpdateEntity, public PollingComponent { void setup() override; void update() override; - void perform() override; + void perform(bool force) override; void set_source_url(const std::string &source_url) { this->source_url_ = source_url; } diff --git a/esphome/components/update/__init__.py b/esphome/components/update/__init__.py index 45bf082fa4..ba3b2f20df 100644 --- a/esphome/components/update/__init__.py +++ b/esphome/components/update/__init__.py @@ -1,10 +1,11 @@ from esphome import automation +import esphome.codegen as cg from esphome.components import mqtt, web_server import esphome.config_validation as cv -import esphome.codegen as cg from esphome.const import ( CONF_DEVICE_CLASS, CONF_ENTITY_CATEGORY, + CONF_FORCE_UPDATE, CONF_ID, CONF_MQTT_ID, CONF_WEB_SERVER_ID, @@ -23,8 +24,12 @@ UpdateEntity = update_ns.class_("UpdateEntity", cg.EntityBase) UpdateInfo = update_ns.struct("UpdateInfo") -PerformAction = update_ns.class_("PerformAction", automation.Action) -IsAvailableCondition = update_ns.class_("IsAvailableCondition", automation.Condition) +PerformAction = update_ns.class_( + "PerformAction", automation.Action, cg.Parented.template(UpdateEntity) +) +IsAvailableCondition = update_ns.class_( + "IsAvailableCondition", automation.Condition, cg.Parented.template(UpdateEntity) +) DEVICE_CLASSES = [ DEVICE_CLASS_EMPTY, @@ -92,24 +97,37 @@ async def to_code(config): cg.add_global(update_ns.using) -UPDATE_AUTOMATION_SCHEMA = cv.Schema( - { - cv.GenerateID(): cv.use_id(UpdateEntity), - } +@automation.register_action( + "update.perform", + PerformAction, + automation.maybe_simple_id( + { + cv.GenerateID(): cv.use_id(UpdateEntity), + cv.Optional(CONF_FORCE_UPDATE, default=False): cv.templatable(cv.boolean), + } + ), ) - - -@automation.register_action("update.perform", PerformAction, UPDATE_AUTOMATION_SCHEMA) async def update_perform_action_to_code(config, action_id, template_arg, args): - paren = await cg.get_variable(config[CONF_ID]) - return cg.new_Pvariable(action_id, paren, paren) + var = cg.new_Pvariable(action_id, template_arg) + await cg.register_parented(var, config[CONF_ID]) + + force = await cg.templatable(config[CONF_FORCE_UPDATE], args, cg.bool_) + cg.add(var.set_force(force)) + return var @automation.register_condition( - "update.is_available", IsAvailableCondition, UPDATE_AUTOMATION_SCHEMA + "update.is_available", + IsAvailableCondition, + automation.maybe_simple_id( + { + cv.GenerateID(): cv.use_id(UpdateEntity), + } + ), ) async def update_is_available_condition_to_code( config, condition_id, template_arg, args ): - paren = await cg.get_variable(config[CONF_ID]) - return cg.new_Pvariable(condition_id, paren, paren) + var = cg.new_Pvariable(condition_id, template_arg) + await cg.register_parented(var, config[CONF_ID]) + return var diff --git a/esphome/components/update/automation.h b/esphome/components/update/automation.h new file mode 100644 index 0000000000..df50f86a0c --- /dev/null +++ b/esphome/components/update/automation.h @@ -0,0 +1,23 @@ +#pragma once + +#include "update_entity.h" + +#include "esphome/core/automation.h" + +namespace esphome { +namespace update { + +template class PerformAction : public Action, public Parented { + TEMPLATABLE_VALUE(bool, force) + + public: + void play(Ts... x) override { this->parent_->perform(this->force_.value(x...)); } +}; + +template class IsAvailableCondition : public Condition, public Parented { + public: + bool check(Ts... x) override { return this->parent_->state == UPDATE_STATE_AVAILABLE; } +}; + +} // namespace update +} // namespace esphome diff --git a/esphome/components/update/update_entity.h b/esphome/components/update/update_entity.h index 5984c8e35b..568fbe3bb0 100644 --- a/esphome/components/update/update_entity.h +++ b/esphome/components/update/update_entity.h @@ -32,7 +32,9 @@ class UpdateEntity : public EntityBase, public EntityBase_DeviceClass { void publish_state(); - virtual void perform() = 0; + void perform() { this->perform(false); } + + virtual void perform(bool force) = 0; const UpdateInfo &update_info = update_info_; const UpdateState &state = state_; diff --git a/tests/components/update/common.yaml b/tests/components/update/common.yaml index 91b8669505..dcb4f42527 100644 --- a/tests/components/update/common.yaml +++ b/tests/components/update/common.yaml @@ -1 +1,28 @@ +substitutions: + verify_ssl: "true" + +esphome: + on_boot: + then: + - if: + condition: + update.is_available: + then: + - logger.log: "Update available" + - update.perform: + force_update: true + +wifi: + ssid: MySSID + password: password1 + +http_request: + verify_ssl: ${verify_ssl} + +ota: + - platform: http_request + update: + - platform: http_request + name: Firmware Update + source: http://example.com/manifest.json diff --git a/tests/components/update/test.esp32-ard.yaml b/tests/components/update/test.esp32-ard.yaml index dade44d145..c1937b5a10 100644 --- a/tests/components/update/test.esp32-ard.yaml +++ b/tests/components/update/test.esp32-ard.yaml @@ -1 +1,4 @@ +substitutions: + verify_ssl: "false" + <<: !include common.yaml diff --git a/tests/components/update/test.esp8266-ard.yaml b/tests/components/update/test.esp8266-ard.yaml index dade44d145..c1937b5a10 100644 --- a/tests/components/update/test.esp8266-ard.yaml +++ b/tests/components/update/test.esp8266-ard.yaml @@ -1 +1,4 @@ +substitutions: + verify_ssl: "false" + <<: !include common.yaml diff --git a/tests/components/update/test.rp2040-ard.yaml b/tests/components/update/test.rp2040-ard.yaml index dade44d145..c1937b5a10 100644 --- a/tests/components/update/test.rp2040-ard.yaml +++ b/tests/components/update/test.rp2040-ard.yaml @@ -1 +1,4 @@ +substitutions: + verify_ssl: "false" + <<: !include common.yaml From 3920029aff9dd85fd5f0775945b8426c03da471c Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Wed, 31 Jul 2024 14:31:15 +1000 Subject: [PATCH 1846/2101] [lvgl] PR stage 3 (#7160) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/lvgl/__init__.py | 58 +++++-- esphome/components/lvgl/automation.py | 188 +++++++++++++++++++++ esphome/components/lvgl/btn.py | 6 +- esphome/components/lvgl/defines.py | 30 +++- esphome/components/lvgl/lv_validation.py | 46 ++--- esphome/components/lvgl/lvcode.py | 64 ++++--- esphome/components/lvgl/lvgl_esphome.cpp | 75 +++++++- esphome/components/lvgl/lvgl_esphome.h | 165 ++++++++++++++++-- esphome/components/lvgl/obj.py | 13 +- esphome/components/lvgl/rotary_encoders.py | 62 +++++++ esphome/components/lvgl/schemas.py | 80 ++++++++- esphome/components/lvgl/touchscreens.py | 5 +- esphome/components/lvgl/trigger.py | 61 +++++++ esphome/components/lvgl/types.py | 23 ++- esphome/components/lvgl/widget.py | 58 +++++-- esphome/core/defines.h | 3 + tests/components/lvgl/lvgl-package.yaml | 35 ++++ tests/components/lvgl/test.esp32-idf.yaml | 21 +++ 18 files changed, 895 insertions(+), 98 deletions(-) create mode 100644 esphome/components/lvgl/automation.py create mode 100644 esphome/components/lvgl/rotary_encoders.py create mode 100644 esphome/components/lvgl/trigger.py diff --git a/esphome/components/lvgl/__init__.py b/esphome/components/lvgl/__init__.py index c454a61957..182d04e038 100644 --- a/esphome/components/lvgl/__init__.py +++ b/esphome/components/lvgl/__init__.py @@ -1,5 +1,6 @@ import logging +from esphome.automation import build_automation, register_action, validate_automation import esphome.codegen as cg from esphome.components.display import Display import esphome.config_validation as cv @@ -8,7 +9,11 @@ from esphome.const import ( CONF_BUFFER_SIZE, CONF_ID, CONF_LAMBDA, + CONF_ON_IDLE, CONF_PAGES, + CONF_TIMEOUT, + CONF_TRIGGER_ID, + CONF_TYPE, ) from esphome.core import CORE, ID, Lambda from esphome.cpp_generator import MockObj @@ -16,21 +21,26 @@ from esphome.final_validate import full_config from esphome.helpers import write_file_if_changed from . import defines as df, helpers, lv_validation as lvalid +from .automation import update_to_code from .btn import btn_spec from .label import label_spec -from .lvcode import ConstantLiteral, LvContext +from .lv_validation import lv_images_used +from .lvcode import LvContext from .obj import obj_spec -from .schemas import any_widget_schema, obj_schema +from .rotary_encoders import ROTARY_ENCODER_CONFIG, rotary_encoders_to_code +from .schemas import any_widget_schema, create_modify_schema, obj_schema from .touchscreens import touchscreen_schema, touchscreens_to_code +from .trigger import generate_triggers from .types import ( WIDGET_TYPES, FontEngine, + IdleTrigger, LvglComponent, - lv_disp_t_ptr, + ObjUpdateAction, lv_font_t, lvgl_ns, ) -from .widget import LvScrActType, Widget, add_widgets, set_obj_properties +from .widget import Widget, add_widgets, lv_scr_act, set_obj_properties DOMAIN = "lvgl" DEPENDENCIES = ("display",) @@ -41,17 +51,21 @@ LOGGER = logging.getLogger(__name__) for w_type in (label_spec, obj_spec, btn_spec): WIDGET_TYPES[w_type.name] = w_type -lv_scr_act_spec = LvScrActType() -lv_scr_act = Widget.create( - None, ConstantLiteral("lv_scr_act()"), lv_scr_act_spec, {}, parent=None -) - WIDGET_SCHEMA = any_widget_schema() +for w_type in WIDGET_TYPES.values(): + register_action( + f"lvgl.{w_type.name}.update", + ObjUpdateAction, + create_modify_schema(w_type), + )(update_to_code) + async def add_init_lambda(lv_component, init): if init: - lamb = await cg.process_lambda(Lambda(init), [(lv_disp_t_ptr, "lv_disp")]) + lamb = await cg.process_lambda( + Lambda(init), [(LvglComponent.operator("ptr"), "lv_component")] + ) cg.add(lv_component.add_init_lambda(lamb)) @@ -99,6 +113,13 @@ def final_validation(config): buffer_frac = config[CONF_BUFFER_SIZE] if CORE.is_esp32 and buffer_frac > 0.5 and "psram" 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 + ) async def to_code(config): @@ -174,9 +195,15 @@ async def to_code(config): with LvContext(): await touchscreens_to_code(lv_component, config) + await rotary_encoders_to_code(lv_component, config) await set_obj_properties(lv_scr_act, config) await add_widgets(lv_scr_act, config) - Widget.set_completed() + Widget.set_completed() + await generate_triggers(lv_component) + for conf in config.get(CONF_ON_IDLE, ()): + templ = await cg.templatable(conf[CONF_TIMEOUT], [], cg.uint32) + idle_trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], lv_component, templ) + await build_automation(idle_trigger, [], conf) await add_init_lambda(lv_component, LvContext.get_code()) for comp in helpers.lvgl_components_required: CORE.add_define(f"USE_LVGL_{comp.upper()}") @@ -212,9 +239,18 @@ CONFIG_SCHEMA = ( cv.Optional(df.CONF_BYTE_ORDER, default="big_endian"): cv.one_of( "big_endian", "little_endian" ), + cv.Optional(CONF_ON_IDLE): validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(IdleTrigger), + cv.Required(CONF_TIMEOUT): cv.templatable( + cv.positive_time_period_milliseconds + ), + } + ), cv.Optional(df.CONF_WIDGETS): cv.ensure_list(WIDGET_SCHEMA), cv.Optional(df.CONF_TRANSPARENCY_KEY, default=0x000400): lvalid.lv_color, cv.GenerateID(df.CONF_TOUCHSCREENS): touchscreen_schema, + cv.GenerateID(df.CONF_ROTARY_ENCODERS): ROTARY_ENCODER_CONFIG, } ) ).add_extra(cv.has_at_least_one_key(CONF_PAGES, df.CONF_WIDGETS)) diff --git a/esphome/components/lvgl/automation.py b/esphome/components/lvgl/automation.py new file mode 100644 index 0000000000..4fd0be185e --- /dev/null +++ b/esphome/components/lvgl/automation.py @@ -0,0 +1,188 @@ +from esphome import automation +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.const import CONF_ID, CONF_TIMEOUT +from esphome.core import Lambda +from esphome.cpp_generator import RawStatement +from esphome.cpp_types import nullptr + +from .defines import CONF_LVGL_ID, CONF_SHOW_SNOW, literal +from .lv_validation import lv_bool +from .lvcode import ( + LambdaContext, + ReturnStatement, + add_line_marks, + lv, + lv_add, + lv_obj, + lvgl_comp, +) +from .schemas import ACTION_SCHEMA, LVGL_SCHEMA +from .types import ( + LvglAction, + LvglComponent, + LvglComponentPtr, + LvglCondition, + ObjUpdateAction, + lv_obj_t, +) +from .widget import Widget, get_widget, lv_scr_act, set_obj_properties + + +async def action_to_code(action: list, action_id, widget: Widget, template_arg, args): + with LambdaContext() as context: + lv.cond_if(widget.obj == nullptr) + lv_add(RawStatement(" return;")) + lv.cond_endif() + code = context.get_code() + code.extend(action) + action = "\n".join(code) + "\n\n" + lamb = await cg.process_lambda(Lambda(action), args) + var = cg.new_Pvariable(action_id, template_arg, lamb) + return var + + +async def update_to_code(config, action_id, template_arg, args): + if config is not None: + widget = await get_widget(config) + with LambdaContext() as context: + add_line_marks(action_id) + await set_obj_properties(widget, config) + await widget.type.to_code(widget, config) + if ( + widget.type.w_type.value_property is not None + and widget.type.w_type.value_property in config + ): + lv.event_send(widget.obj, literal("LV_EVENT_VALUE_CHANGED"), nullptr) + return await action_to_code( + context.get_code(), action_id, widget, template_arg, args + ) + + +@automation.register_condition( + "lvgl.is_paused", + LvglCondition, + LVGL_SCHEMA, +) +async def lvgl_is_paused(config, condition_id, template_arg, args): + lvgl = config[CONF_LVGL_ID] + with LambdaContext( + [(LvglComponentPtr, "lvgl_comp")], return_type=cg.bool_ + ) as context: + lv_add(ReturnStatement(lvgl_comp.is_paused())) + var = cg.new_Pvariable(condition_id, template_arg, await context.get_lambda()) + await cg.register_parented(var, lvgl) + return var + + +@automation.register_condition( + "lvgl.is_idle", + LvglCondition, + LVGL_SCHEMA.extend( + { + cv.Required(CONF_TIMEOUT): cv.templatable( + cv.positive_time_period_milliseconds + ) + } + ), +) +async def lvgl_is_idle(config, condition_id, template_arg, args): + lvgl = config[CONF_LVGL_ID] + timeout = await cg.templatable(config[CONF_TIMEOUT], [], cg.uint32) + with LambdaContext( + [(LvglComponentPtr, "lvgl_comp")], return_type=cg.bool_ + ) as context: + lv_add(ReturnStatement(lvgl_comp.is_idle(timeout))) + var = cg.new_Pvariable(condition_id, template_arg, await context.get_lambda()) + await cg.register_parented(var, lvgl) + return var + + +@automation.register_action( + "lvgl.widget.redraw", + ObjUpdateAction, + cv.Schema( + { + cv.Optional(CONF_ID): cv.use_id(lv_obj_t), + cv.GenerateID(CONF_LVGL_ID): cv.use_id(LvglComponent), + } + ), +) +async def obj_invalidate_to_code(config, action_id, template_arg, args): + if CONF_ID in config: + w = await get_widget(config) + else: + w = lv_scr_act + with LambdaContext() as context: + add_line_marks(action_id) + lv_obj.invalidate(w.obj) + return await action_to_code(context.get_code(), action_id, w, template_arg, args) + + +@automation.register_action( + "lvgl.pause", + LvglAction, + { + cv.GenerateID(): cv.use_id(LvglComponent), + cv.Optional(CONF_SHOW_SNOW, default=False): lv_bool, + }, +) +async def pause_action_to_code(config, action_id, template_arg, args): + with LambdaContext([(LvglComponentPtr, "lvgl_comp")]) as context: + add_line_marks(action_id) + lv_add(lvgl_comp.set_paused(True, config[CONF_SHOW_SNOW])) + var = cg.new_Pvariable(action_id, template_arg, await context.get_lambda()) + await cg.register_parented(var, config[CONF_ID]) + return var + + +@automation.register_action( + "lvgl.resume", + LvglAction, + { + cv.GenerateID(): cv.use_id(LvglComponent), + }, +) +async def resume_action_to_code(config, action_id, template_arg, args): + with LambdaContext([(LvglComponentPtr, "lvgl_comp")]) as context: + add_line_marks(action_id) + lv_add(lvgl_comp.set_paused(False, False)) + var = cg.new_Pvariable(action_id, template_arg, await context.get_lambda()) + await cg.register_parented(var, config[CONF_ID]) + return var + + +@automation.register_action("lvgl.widget.disable", ObjUpdateAction, ACTION_SCHEMA) +async def obj_disable_to_code(config, action_id, template_arg, args): + w = await get_widget(config) + with LambdaContext() as context: + add_line_marks(action_id) + w.add_state("LV_STATE_DISABLED") + return await action_to_code(context.get_code(), action_id, w, template_arg, args) + + +@automation.register_action("lvgl.widget.enable", ObjUpdateAction, ACTION_SCHEMA) +async def obj_enable_to_code(config, action_id, template_arg, args): + w = await get_widget(config) + with LambdaContext() as context: + add_line_marks(action_id) + w.clear_state("LV_STATE_DISABLED") + return await action_to_code(context.get_code(), action_id, w, template_arg, args) + + +@automation.register_action("lvgl.widget.hide", ObjUpdateAction, ACTION_SCHEMA) +async def obj_hide_to_code(config, action_id, template_arg, args): + w = await get_widget(config) + with LambdaContext() as context: + add_line_marks(action_id) + w.add_flag("LV_OBJ_FLAG_HIDDEN") + return await action_to_code(context.get_code(), action_id, w, template_arg, args) + + +@automation.register_action("lvgl.widget.show", ObjUpdateAction, ACTION_SCHEMA) +async def obj_show_to_code(config, action_id, template_arg, args): + w = await get_widget(config) + with LambdaContext() as context: + add_line_marks(action_id) + w.clear_flag("LV_OBJ_FLAG_HIDDEN") + return await action_to_code(context.get_code(), action_id, w, template_arg, args) diff --git a/esphome/components/lvgl/btn.py b/esphome/components/lvgl/btn.py index 4f5f88d9e6..064d886d47 100644 --- a/esphome/components/lvgl/btn.py +++ b/esphome/components/lvgl/btn.py @@ -9,9 +9,6 @@ class BtnType(WidgetType): def __init__(self): super().__init__(CONF_BUTTON, LvBoolean("lv_btn_t"), (CONF_MAIN,)) - async def to_code(self, w, config): - return [] - def obj_creator(self, parent: MockObjClass, config: dict): """ LVGL 8 calls buttons `btn` @@ -21,5 +18,8 @@ class BtnType(WidgetType): def get_uses(self): return ("btn",) + async def to_code(self, w, config): + return [] + btn_spec = BtnType() diff --git a/esphome/components/lvgl/defines.py b/esphome/components/lvgl/defines.py index a2b4ac13fb..9f349e3943 100644 --- a/esphome/components/lvgl/defines.py +++ b/esphome/components/lvgl/defines.py @@ -4,12 +4,32 @@ Constants already defined in esphome.const are not duplicated here and must be i """ +from typing import Union + from esphome import codegen as cg, config_validation as cv from esphome.core import ID, Lambda +from esphome.cpp_generator import Literal from esphome.cpp_types import uint32 from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor -from .lvcode import ConstantLiteral +from .helpers import requires_component + + +class ConstantLiteral(Literal): + __slots__ = ("constant",) + + def __init__(self, constant: str): + super().__init__() + self.constant = constant + + def __str__(self): + return self.constant + + +def literal(arg: Union[str, ConstantLiteral]): + if isinstance(arg, str): + return ConstantLiteral(arg) + return arg class LValidator: @@ -18,14 +38,19 @@ class LValidator: has `process()` to convert a value during code generation """ - def __init__(self, validator, rtype, idtype=None, idexpr=None, retmapper=None): + def __init__( + self, validator, rtype, idtype=None, idexpr=None, retmapper=None, requires=None + ): self.validator = validator self.rtype = rtype self.idtype = idtype self.idexpr = idexpr self.retmapper = retmapper + self.requires = requires def __call__(self, value): + if self.requires: + value = requires_component(self.requires)(value) if isinstance(value, cv.Lambda): return cv.returning_lambda(value) if self.idtype is not None and isinstance(value, ID): @@ -422,6 +447,7 @@ CONF_RECOLOR = "recolor" CONF_RIGHT_BUTTON = "right_button" CONF_ROLLOVER = "rollover" CONF_ROOT_BACK_BTN = "root_back_btn" +CONF_ROTARY_ENCODERS = "rotary_encoders" CONF_ROWS = "rows" CONF_SCALES = "scales" CONF_SCALE_LINES = "scale_lines" diff --git a/esphome/components/lvgl/lv_validation.py b/esphome/components/lvgl/lv_validation.py index 533dc582f0..818bde6aed 100644 --- a/esphome/components/lvgl/lv_validation.py +++ b/esphome/components/lvgl/lv_validation.py @@ -2,6 +2,7 @@ import esphome.codegen as cg from esphome.components.binary_sensor import BinarySensor from esphome.components.color import ColorStruct from esphome.components.font import Font +from esphome.components.image import Image_ from esphome.components.sensor import Sensor from esphome.components.text_sensor import TextSensor import esphome.config_validation as cv @@ -13,22 +14,15 @@ from esphome.helpers import cpp_string_escape from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor from . import types as ty -from .defines import LV_FONTS, LValidator, LvConstant +from .defines import LV_FONTS, ConstantLiteral, LValidator, LvConstant, literal from .helpers import ( esphome_fonts_used, lv_fonts_used, lvgl_components_required, requires_component, ) -from .lvcode import ConstantLiteral, lv_expr -from .types import lv_font_t - - -def literal_mapper(value, args=()): - if isinstance(value, str): - return ConstantLiteral(value) - return value - +from .lvcode import lv_expr +from .types import lv_font_t, lv_img_t opacity_consts = LvConstant("LV_OPA_", "TRANSP", "COVER") @@ -43,7 +37,7 @@ def opacity_validator(value): return value -opacity = LValidator(opacity_validator, uint32, retmapper=literal_mapper) +opacity = LValidator(opacity_validator, uint32, retmapper=literal) @schema_extractor("one_of") @@ -79,9 +73,7 @@ def pixels_or_percent_validator(value): return f"lv_pct({int(cv.percentage(value) * 100)})" -pixels_or_percent = LValidator( - pixels_or_percent_validator, uint32, retmapper=literal_mapper -) +pixels_or_percent = LValidator(pixels_or_percent_validator, uint32, retmapper=literal) def zoom(value): @@ -115,7 +107,7 @@ def size_validator(value): return f"lv_pct({int(cv.percentage(value) * 100)})" -size = LValidator(size_validator, uint32, retmapper=literal_mapper) +size = LValidator(size_validator, uint32, retmapper=literal) radius_consts = LvConstant("LV_RADIUS_", "CIRCLE") @@ -130,21 +122,37 @@ def radius_validator(value): return value +radius = LValidator(radius_validator, uint32, retmapper=literal) + + def id_name(value): if value == SCHEMA_EXTRACT: return "id" return cv.validate_id_name(value) -radius = LValidator(radius_validator, uint32, retmapper=literal_mapper) - - def stop_value(value): return cv.int_range(0, 255)(value) +lv_images_used = set() + + +def image_validator(value): + value = requires_component("image")(value) + value = cv.use_id(Image_)(value) + lv_images_used.add(value) + return value + + +lv_image = LValidator( + image_validator, + lv_img_t, + retmapper=lambda x: lv_expr.img_from(MockObj(x)), + requires="image", +) lv_bool = LValidator( - cv.boolean, cg.bool_, BinarySensor, "get_state()", retmapper=literal_mapper + cv.boolean, cg.bool_, BinarySensor, "get_state()", retmapper=literal ) diff --git a/esphome/components/lvgl/lvcode.py b/esphome/components/lvgl/lvcode.py index 13b4862b4d..3a8a958f2e 100644 --- a/esphome/components/lvgl/lvcode.py +++ b/esphome/components/lvgl/lvcode.py @@ -8,8 +8,8 @@ from esphome.cpp_generator import ( AssignmentExpression, CallExpression, Expression, + ExpressionStatement, LambdaExpression, - Literal, MockObj, RawExpression, RawStatement, @@ -19,7 +19,9 @@ from esphome.cpp_generator import ( statement, ) +from .defines import ConstantLiteral from .helpers import get_line_marks +from .types import lv_group_t _LOGGER = logging.getLogger(__name__) @@ -105,29 +107,40 @@ class LambdaContext(CodeContext): def __init__( self, - parameters: list[tuple[SafeExpType, str]], - return_type: SafeExpType = None, + parameters: list[tuple[SafeExpType, str]] = None, + return_type: SafeExpType = cg.void, + capture: str = "", ): super().__init__() self.code_list: list[Statement] = [] self.parameters = parameters self.return_type = return_type + self.capture = capture def add(self, expression: Union[Expression, Statement]): self.code_list.append(expression) return expression - async def code(self) -> LambdaExpression: + async def get_lambda(self) -> LambdaExpression: + code_text = self.get_code() + return await cg.process_lambda( + Lambda("\n".join(code_text) + "\n\n"), + self.parameters, + capture=self.capture, + return_type=self.return_type, + ) + + def get_code(self): code_text = [] for exp in self.code_list: text = str(statement(exp)) text = text.rstrip() code_text.append(text) - return await cg.process_lambda( - Lambda("\n".join(code_text) + "\n\n"), - self.parameters, - return_type=self.return_type, - ) + return code_text + + def __enter__(self): + super().__enter__() + return self class LocalVariable(MockObj): @@ -187,13 +200,18 @@ class MockLv: return result def cond_if(self, expression: Expression): - CodeContext.append(RawExpression(f"if({expression}) {{")) + CodeContext.append(RawStatement(f"if {expression} {{")) def cond_else(self): - CodeContext.append(RawExpression("} else {")) + CodeContext.append(RawStatement("} else {")) def cond_endif(self): - CodeContext.append(RawExpression("}")) + CodeContext.append(RawStatement("}")) + + +class ReturnStatement(ExpressionStatement): + def __str__(self): + return f"return {self.expression};" class LvExpr(MockLv): @@ -210,6 +228,7 @@ lv = MockLv("lv_") lv_expr = LvExpr("lv_") # Mock for lv_obj_ calls lv_obj = MockLv("lv_obj_") +lvgl_comp = MockObj("lvgl_comp", "->") # equivalent to cg.add() for the lvgl init context @@ -226,12 +245,19 @@ def lv_assign(target, expression): lv_add(RawExpression(f"{target} = {expression}")) -class ConstantLiteral(Literal): - __slots__ = ("constant",) +lv_groups = {} # Widget group names - def __init__(self, constant: str): - super().__init__() - self.constant = constant - def __str__(self): - return self.constant +def add_group(name): + if name is None: + return None + fullname = f"lv_esp_group_{name}" + if name not in lv_groups: + gid = ID(fullname, True, type=lv_group_t.operator("ptr")) + lv_add( + AssignmentExpression( + type_=gid.type, modifier="", name=fullname, rhs=lv_expr.group_create() + ) + ) + lv_groups[name] = ConstantLiteral(fullname) + return lv_groups[name] diff --git a/esphome/components/lvgl/lvgl_esphome.cpp b/esphome/components/lvgl/lvgl_esphome.cpp index 74a1b0e7af..34f8eaf21f 100644 --- a/esphome/components/lvgl/lvgl_esphome.cpp +++ b/esphome/components/lvgl/lvgl_esphome.cpp @@ -19,13 +19,35 @@ void LvglComponent::draw_buffer_(const lv_area_t *area, const uint8_t *ptr) { } void LvglComponent::flush_cb_(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p) { - auto now = millis(); - this->draw_buffer_(area, (const uint8_t *) 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)); + if (!this->paused_) { + auto now = millis(); + this->draw_buffer_(area, (const uint8_t *) 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); } +void LvglComponent::write_random_() { + // length of 2 lines in 32 bit units + // we write 2 lines for the benefit of displays that won't write one line at a time. + size_t line_len = this->disp_drv_.hor_res * LV_COLOR_DEPTH / 8 / 4 * 2; + for (size_t i = 0; i != line_len; i++) { + ((uint32_t *) (this->draw_buf_.buf1))[i] = random_uint32(); + } + lv_area_t area; + area.x1 = 0; + area.x2 = this->disp_drv_.hor_res - 1; + if (this->snow_line_ == this->disp_drv_.ver_res / 2) { + area.y1 = static_cast(random_uint32() % (this->disp_drv_.ver_res / 2) * 2); + } else { + area.y1 = this->snow_line_++ * 2; + } + // write 2 lines + area.y2 = area.y1 + 1; + this->draw_buffer_(&area, (const uint8_t *) this->draw_buf_.buf1); +} + void LvglComponent::setup() { ESP_LOGCONFIG(TAG, "LVGL Setup starts"); #if LV_USE_LOG @@ -74,10 +96,53 @@ void LvglComponent::setup() { ESP_LOGV(TAG, "sw_rotate = %d, rotated=%d", this->disp_drv_.sw_rotate, this->disp_drv_.rotated); this->disp_ = lv_disp_drv_register(&this->disp_drv_); for (const auto &v : this->init_lambdas_) - v(this->disp_); + v(this); lv_disp_trig_activity(this->disp_); ESP_LOGCONFIG(TAG, "LVGL Setup complete"); } + +#ifdef USE_LVGL_IMAGE +lv_img_dsc_t *lv_img_from(image::Image *src, lv_img_dsc_t *img_dsc) { + if (img_dsc == nullptr) + img_dsc = new lv_img_dsc_t(); // NOLINT + img_dsc->header.always_zero = 0; + img_dsc->header.reserved = 0; + img_dsc->header.w = src->get_width(); + img_dsc->header.h = src->get_height(); + img_dsc->data = src->get_data_start(); + img_dsc->data_size = image_type_to_width_stride(img_dsc->header.w * img_dsc->header.h, src->get_type()); + switch (src->get_type()) { + case image::IMAGE_TYPE_BINARY: + img_dsc->header.cf = LV_IMG_CF_ALPHA_1BIT; + break; + + case image::IMAGE_TYPE_GRAYSCALE: + img_dsc->header.cf = LV_IMG_CF_ALPHA_8BIT; + break; + + case image::IMAGE_TYPE_RGB24: + img_dsc->header.cf = LV_IMG_CF_RGB888; + break; + + case image::IMAGE_TYPE_RGB565: +#if LV_COLOR_DEPTH == 16 + img_dsc->header.cf = src->has_transparency() ? LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED : LV_IMG_CF_TRUE_COLOR; +#else + img_dsc->header.cf = LV_IMG_CF_RGB565; +#endif + break; + + case image::IMAGE_TYPE_RGBA: +#if LV_COLOR_DEPTH == 32 + img_dsc->header.cf = LV_IMG_CF_TRUE_COLOR; +#else + img_dsc->header.cf = LV_IMG_CF_RGBA8888; +#endif + break; + } + return img_dsc; +} +#endif } // namespace lvgl } // namespace esphome diff --git a/esphome/components/lvgl/lvgl_esphome.h b/esphome/components/lvgl/lvgl_esphome.h index a884a27042..a0d3d226ce 100644 --- a/esphome/components/lvgl/lvgl_esphome.h +++ b/esphome/components/lvgl/lvgl_esphome.h @@ -1,23 +1,32 @@ #pragma once #include "esphome/core/defines.h" -#ifdef USE_LVGL + +#ifdef USE_LVGL_BINARY_SENSOR +#include "esphome/components/binary_sensor/binary_sensor.h" +#endif // USE_LVGL_BINARY_SENSOR +#ifdef USE_LVGL_ROTARY_ENCODER +#include "esphome/components/rotary_encoder/rotary_encoder.h" +#endif // USE_LVGL_ROTARY_ENCODER // required for clang-tidy #ifndef LV_CONF_H #define LV_CONF_SKIP 1 // NOLINT -#endif +#endif // LV_CONF_H #include "esphome/components/display/display.h" #include "esphome/components/display/display_color_utils.h" #include "esphome/core/component.h" -#include "esphome/core/hal.h" #include "esphome/core/log.h" #include +#include #include +#ifdef USE_LVGL_IMAGE +#include "esphome/components/image/image.h" +#endif // USE_LVGL_IMAGE #ifdef USE_LVGL_FONT #include "esphome/components/font/font.h" -#endif +#endif // USE_LVGL_FONT #ifdef USE_LVGL_TOUCHSCREEN #include "esphome/components/touchscreen/touchscreen.h" #endif // USE_LVGL_TOUCHSCREEN @@ -40,7 +49,7 @@ static const display::ColorBitness LV_BITNESS = display::ColorBitness::COLOR_BIT // Parent class for things that wrap an LVGL object class LvCompound final { public: - virtual void set_obj(lv_obj_t *lv_obj) { this->obj = lv_obj; } + void set_obj(lv_obj_t *lv_obj) { this->obj = lv_obj; } lv_obj_t *obj{}; }; @@ -49,6 +58,15 @@ using set_value_lambda_t = std::function; using event_callback_t = void(_lv_event_t *); using text_lambda_t = std::function; +template class ObjUpdateAction : public Action { + public: + explicit ObjUpdateAction(std::function &&lamb) : lamb_(std::move(lamb)) {} + + void play(Ts... x) override { this->lamb_(x...); } + + protected: + std::function lamb_; +}; #ifdef USE_LVGL_FONT class FontEngine { public: @@ -67,6 +85,9 @@ class FontEngine { lv_font_t lv_font_{}; }; #endif // USE_LVGL_FONT +#ifdef USE_LVGL_IMAGE +lv_img_dsc_t *lv_img_from(image::Image *src, lv_img_dsc_t *img_dsc = nullptr); +#endif // USE_LVGL_IMAGE class LvglComponent : public PollingComponent { constexpr static const char *const TAG = "lvgl"; @@ -92,27 +113,54 @@ class LvglComponent : public PollingComponent { area->y2++; } - void loop() override { lv_timer_handler_run_in_period(5); } void setup() override; - void update() override {} + void update() override { + // update indicators + if (this->paused_) { + return; + } + this->idle_callbacks_.call(lv_disp_get_inactive_time(this->disp_)); + } + void loop() override { + if (this->paused_) { + if (this->show_snow_) + this->write_random_(); + } + lv_timer_handler_run_in_period(5); + } + + void add_on_idle_callback(std::function &&callback) { + this->idle_callbacks_.add(std::move(callback)); + } void add_display(display::Display *display) { this->displays_.push_back(display); } - void add_init_lambda(const std::function &lamb) { this->init_lambdas_.push_back(lamb); } + void add_init_lambda(const std::function &lamb) { this->init_lambdas_.push_back(lamb); } void dump_config() override; void set_full_refresh(bool full_refresh) { this->full_refresh_ = full_refresh; } + bool is_idle(uint32_t idle_ms) { return lv_disp_get_inactive_time(this->disp_) > idle_ms; } void set_buffer_frac(size_t frac) { this->buffer_frac_ = frac; } lv_disp_t *get_disp() { return this->disp_; } void set_paused(bool paused, bool show_snow) { this->paused_ = paused; + this->show_snow_ = show_snow; + this->snow_line_ = 0; if (!paused && lv_scr_act() != nullptr) { lv_disp_trig_activity(this->disp_); // resets the inactivity time lv_obj_invalidate(lv_scr_act()); } } + + void add_event_cb(lv_obj_t *obj, event_callback_t callback, lv_event_code_t event) { + lv_obj_add_event_cb(obj, callback, event, this); + if (event == LV_EVENT_VALUE_CHANGED) { + lv_obj_add_event_cb(obj, callback, lv_custom_event, this); + } + } bool is_paused() const { return this->paused_; } protected: + void write_random_(); void draw_buffer_(const lv_area_t *area, const uint8_t *ptr); void flush_cb_(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p); std::vector displays_{}; @@ -120,12 +168,52 @@ class LvglComponent : public PollingComponent { lv_disp_drv_t disp_drv_{}; lv_disp_t *disp_{}; bool paused_{}; + bool show_snow_{}; + lv_coord_t snow_line_{}; - std::vector> init_lambdas_; + std::vector> init_lambdas_; + CallbackManager idle_callbacks_{}; size_t buffer_frac_{1}; bool full_refresh_{}; }; +class IdleTrigger : public Trigger<> { + public: + explicit IdleTrigger(LvglComponent *parent, TemplatableValue timeout) : timeout_(std::move(timeout)) { + parent->add_on_idle_callback([this](uint32_t idle_time) { + if (!this->is_idle_ && idle_time > this->timeout_.value()) { + this->is_idle_ = true; + this->trigger(); + } else if (this->is_idle_ && idle_time < this->timeout_.value()) { + this->is_idle_ = false; + } + }); + } + + protected: + TemplatableValue timeout_; + bool is_idle_{}; +}; + +template class LvglAction : public Action, public Parented { + public: + explicit LvglAction(std::function &&lamb) : action_(std::move(lamb)) {} + void play(Ts... x) override { this->action_(this->parent_); } + + protected: + std::function action_{}; +}; + +template class LvglCondition : public Condition, public Parented { + public: + LvglCondition(std::function &&condition_lambda) + : condition_lambda_(std::move(condition_lambda)) {} + bool check(Ts... x) override { return this->condition_lambda_(this->parent_); } + + protected: + std::function condition_lambda_{}; +}; + #ifdef USE_LVGL_TOUCHSCREEN class LVTouchListener : public touchscreen::TouchListener, public Parented { public: @@ -160,7 +248,62 @@ class LVTouchListener : public touchscreen::TouchListener, public Parented { + public: + 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(d->user_data); + 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; + }; + } + + void set_left_button(binary_sensor::BinarySensor *left_button) { + left_button->add_on_state_callback([this](bool state) { this->event(LV_KEY_LEFT, state); }); + } + void set_right_button(binary_sensor::BinarySensor *right_button) { + right_button->add_on_state_callback([this](bool state) { this->event(LV_KEY_RIGHT, state); }); + } + + void set_enter_button(binary_sensor::BinarySensor *enter_button) { + enter_button->add_on_state_callback([this](bool state) { this->event(LV_KEY_ENTER, state); }); + } + + void set_sensor(rotary_encoder::RotaryEncoderSensor *sensor) { + sensor->register_listener([this](int32_t count) { this->set_count(count); }); + } + + void event(int key, bool pressed) { + if (!this->parent_->is_paused()) { + this->pressed_ = pressed; + this->key_ = key; + } + } + + void set_count(int32_t count) { + if (!this->parent_->is_paused()) + this->count_ = count; + } + + lv_indev_drv_t *get_drv() { return &this->drv_; } + + protected: + lv_indev_drv_t drv_{}; + bool pressed_{}; + int32_t count_{}; + int32_t last_count_{}; + int key_{}; +}; +#endif // USE_LVGL_KEY_LISTENER } // namespace lvgl } // namespace esphome - -#endif // USE_LVGL diff --git a/esphome/components/lvgl/obj.py b/esphome/components/lvgl/obj.py index 92c4f63d2d..40d7e55381 100644 --- a/esphome/components/lvgl/obj.py +++ b/esphome/components/lvgl/obj.py @@ -1,5 +1,9 @@ +from esphome import automation + +from .automation import update_to_code from .defines import CONF_MAIN, CONF_OBJ -from .types import WidgetType, lv_obj_t +from .schemas import create_modify_schema +from .types import ObjUpdateAction, WidgetType, lv_obj_t class ObjType(WidgetType): @@ -15,3 +19,10 @@ class ObjType(WidgetType): obj_spec = ObjType() + + +@automation.register_action( + "lvgl.widget.update", ObjUpdateAction, create_modify_schema(obj_spec) +) +async def obj_update_to_code(config, action_id, template_arg, args): + return await update_to_code(config, action_id, template_arg, args) diff --git a/esphome/components/lvgl/rotary_encoders.py b/esphome/components/lvgl/rotary_encoders.py new file mode 100644 index 0000000000..77dc397c3e --- /dev/null +++ b/esphome/components/lvgl/rotary_encoders.py @@ -0,0 +1,62 @@ +import esphome.codegen as cg +from esphome.components.binary_sensor import BinarySensor +from esphome.components.rotary_encoder.sensor import RotaryEncoderSensor +import esphome.config_validation as cv +from esphome.const import CONF_GROUP, CONF_ID, CONF_SENSOR + +from .defines import ( + CONF_ENTER_BUTTON, + CONF_LEFT_BUTTON, + CONF_LONG_PRESS_REPEAT_TIME, + CONF_LONG_PRESS_TIME, + CONF_RIGHT_BUTTON, + CONF_ROTARY_ENCODERS, +) +from .helpers import lvgl_components_required +from .lvcode import add_group, lv, lv_add, lv_expr +from .schemas import ENCODER_SCHEMA +from .types import lv_indev_type_t + +ROTARY_ENCODER_CONFIG = cv.ensure_list( + ENCODER_SCHEMA.extend( + { + cv.Required(CONF_ENTER_BUTTON): cv.use_id(BinarySensor), + cv.Required(CONF_SENSOR): cv.Any( + cv.use_id(RotaryEncoderSensor), + cv.Schema( + { + cv.Required(CONF_LEFT_BUTTON): cv.use_id(BinarySensor), + cv.Required(CONF_RIGHT_BUTTON): cv.use_id(BinarySensor), + } + ), + ), + } + ) +) + + +async def rotary_encoders_to_code(var, config): + for enc_conf in config.get(CONF_ROTARY_ENCODERS, ()): + lvgl_components_required.add("KEY_LISTENER") + lvgl_components_required.add("ROTARY_ENCODER") + lpt = enc_conf[CONF_LONG_PRESS_TIME].total_milliseconds + lprt = enc_conf[CONF_LONG_PRESS_REPEAT_TIME].total_milliseconds + listener = cg.new_Pvariable( + enc_conf[CONF_ID], lv_indev_type_t.LV_INDEV_TYPE_ENCODER, lpt, lprt + ) + await cg.register_parented(listener, var) + if sensor_config := enc_conf.get(CONF_SENSOR): + if isinstance(sensor_config, dict): + b_sensor = await cg.get_variable(sensor_config[CONF_LEFT_BUTTON]) + cg.add(listener.set_left_button(b_sensor)) + b_sensor = await cg.get_variable(sensor_config[CONF_RIGHT_BUTTON]) + cg.add(listener.set_right_button(b_sensor)) + else: + sensor_config = await cg.get_variable(sensor_config) + lv_add(listener.set_sensor(sensor_config)) + b_sensor = await cg.get_variable(enc_conf[CONF_ENTER_BUTTON]) + cg.add(listener.set_enter_button(b_sensor)) + if group := add_group(enc_conf.get(CONF_GROUP)): + lv.indev_set_group(lv_expr.indev_drv_register(listener.get_drv()), group) + else: + lv.indev_drv_register(listener.get_drv()) diff --git a/esphome/components/lvgl/schemas.py b/esphome/components/lvgl/schemas.py index 9f6d984545..ebef56a882 100644 --- a/esphome/components/lvgl/schemas.py +++ b/esphome/components/lvgl/schemas.py @@ -1,10 +1,21 @@ from esphome import config_validation as cv -from esphome.const import CONF_ARGS, CONF_FORMAT, CONF_ID, CONF_STATE, CONF_TYPE +from esphome.automation import Trigger, validate_automation +from esphome.const import ( + CONF_ARGS, + CONF_FORMAT, + CONF_GROUP, + CONF_ID, + CONF_ON_VALUE, + CONF_STATE, + CONF_TRIGGER_ID, + CONF_TYPE, +) +from esphome.core import TimePeriod from esphome.schema_extractors import SCHEMA_EXTRACT from . import defines as df, lv_validation as lvalid, types as ty from .helpers import add_lv_use, requires_component, validate_printf -from .lv_validation import lv_font +from .lv_validation import id_name, lv_font from .types import WIDGET_TYPES, WidgetType # A schema for text properties @@ -27,6 +38,28 @@ TEXT_SCHEMA = cv.Schema( } ) +ACTION_SCHEMA = cv.maybe_simple_value( + { + cv.Required(CONF_ID): cv.use_id(ty.lv_pseudo_button_t), + }, + key=CONF_ID, +) + +PRESS_TIME = cv.All( + lvalid.lv_milliseconds, cv.Range(max=TimePeriod(milliseconds=65535)) +) + +ENCODER_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.All( + cv.declare_id(ty.LVEncoderListener), requires_component("binary_sensor") + ), + cv.Optional(CONF_GROUP): lvalid.id_name, + cv.Optional(df.CONF_LONG_PRESS_TIME, default="400ms"): PRESS_TIME, + cv.Optional(df.CONF_LONG_PRESS_REPEAT_TIME, default="100ms"): PRESS_TIME, + } +) + # All LVGL styles and their validators STYLE_PROPS = { "align": df.CHILD_ALIGNMENTS.one_of, @@ -43,6 +76,7 @@ STYLE_PROPS = { "bg_image_opa": lvalid.opacity, "bg_image_recolor": lvalid.lv_color, "bg_image_recolor_opa": lvalid.opacity, + "bg_image_src": lvalid.lv_image, "bg_main_stop": lvalid.stop_value, "bg_opa": lvalid.opacity, "border_color": lvalid.lv_color, @@ -151,6 +185,39 @@ def part_schema(widget_type: WidgetType): ) +def automation_schema(typ: ty.LvType): + if typ.has_on_value: + events = df.LV_EVENT_TRIGGERS + (CONF_ON_VALUE,) + else: + events = df.LV_EVENT_TRIGGERS + if isinstance(typ, ty.LvType): + template = Trigger.template(typ.get_arg_type()) + else: + template = Trigger.template() + return { + cv.Optional(event): validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(template), + } + ) + for event in events + } + + +def create_modify_schema(widget_type): + return ( + part_schema(widget_type) + .extend( + { + cv.Required(CONF_ID): cv.use_id(widget_type), + cv.Optional(CONF_STATE): SET_STATE_SCHEMA, + } + ) + .extend(FLAG_SCHEMA) + .extend(widget_type.modify_schema) + ) + + def obj_schema(widget_type: WidgetType): """ Create a schema for a widget type itself i.e. no allowance for children @@ -161,10 +228,12 @@ def obj_schema(widget_type: WidgetType): part_schema(widget_type) .extend(FLAG_SCHEMA) .extend(ALIGN_TO_SCHEMA) + .extend(automation_schema(widget_type.w_type)) .extend( cv.Schema( { cv.Optional(CONF_STATE): SET_STATE_SCHEMA, + cv.Optional(CONF_GROUP): id_name, } ) ) @@ -188,6 +257,13 @@ STYLED_TEXT_SCHEMA = cv.maybe_simple_value( STYLE_SCHEMA.extend(TEXT_SCHEMA), key=df.CONF_TEXT ) +# For use by platform components +LVGL_SCHEMA = cv.Schema( + { + cv.GenerateID(df.CONF_LVGL_ID): cv.use_id(ty.LvglComponent), + } +) + ALL_STYLES = { **STYLE_PROPS, } diff --git a/esphome/components/lvgl/touchscreens.py b/esphome/components/lvgl/touchscreens.py index a0d4a3e4ad..499b33aa02 100644 --- a/esphome/components/lvgl/touchscreens.py +++ b/esphome/components/lvgl/touchscreens.py @@ -2,7 +2,7 @@ import esphome.codegen as cg from esphome.components.touchscreen import CONF_TOUCHSCREEN_ID, Touchscreen import esphome.config_validation as cv from esphome.const import CONF_ID -from esphome.core import CORE, TimePeriod +from esphome.core import CORE from .defines import ( CONF_LONG_PRESS_REPEAT_TIME, @@ -10,11 +10,10 @@ from .defines import ( CONF_TOUCHSCREENS, ) from .helpers import lvgl_components_required -from .lv_validation import lv_milliseconds from .lvcode import lv +from .schemas import PRESS_TIME from .types import LVTouchListener -PRESS_TIME = cv.All(lv_milliseconds, cv.Range(max=TimePeriod(milliseconds=65535))) CONF_TOUCHSCREEN = "touchscreen" TOUCHSCREENS_CONFIG = cv.maybe_simple_value( { diff --git a/esphome/components/lvgl/trigger.py b/esphome/components/lvgl/trigger.py new file mode 100644 index 0000000000..bf92bda5b0 --- /dev/null +++ b/esphome/components/lvgl/trigger.py @@ -0,0 +1,61 @@ +from esphome import automation +import esphome.codegen as cg +from esphome.const import CONF_ID, CONF_ON_VALUE, CONF_TRIGGER_ID + +from .defines import ( + CONF_ALIGN, + CONF_ALIGN_TO, + CONF_X, + CONF_Y, + LV_EVENT, + LV_EVENT_TRIGGERS, + literal, +) +from .lvcode import LambdaContext, add_line_marks, lv, lv_add +from .widget import widget_map + +lv_event_t_ptr = cg.global_ns.namespace("lv_event_t").operator("ptr") + + +async def generate_triggers(lv_component): + """ + Generate LVGL triggers for all defined widgets + Must be done after all widgets completed + :param lv_component: The parent component + :return: + """ + + for w in widget_map.values(): + if w.config: + for event, conf in { + event: conf + for event, conf in w.config.items() + if event in LV_EVENT_TRIGGERS + }.items(): + conf = conf[0] + w.add_flag("LV_OBJ_FLAG_CLICKABLE") + event = "LV_EVENT_" + LV_EVENT[event[3:].upper()] + await add_trigger(conf, event, lv_component, w) + for conf in w.config.get(CONF_ON_VALUE, ()): + await add_trigger(conf, "LV_EVENT_VALUE_CHANGED", lv_component, w) + + # Generate align to directives while we're here + if align_to := w.config.get(CONF_ALIGN_TO): + target = widget_map[align_to[CONF_ID]].obj + align = align_to[CONF_ALIGN] + x = align_to[CONF_X] + y = align_to[CONF_Y] + lv.obj_align_to(w.obj, target, align, x, y) + + +async def add_trigger(conf, event, lv_component, w): + tid = conf[CONF_TRIGGER_ID] + add_line_marks(tid) + trigger = cg.new_Pvariable(tid) + args = w.get_args() + value = w.get_value() + await automation.build_automation(trigger, args, conf) + with LambdaContext([(lv_event_t_ptr, "event_data")]) as context: + add_line_marks(tid) + lv_add(trigger.trigger(value)) + lv_add(lv_component.add_event_cb(w.obj, await context.get_lambda(), literal(event))) diff --git a/esphome/components/lvgl/types.py b/esphome/components/lvgl/types.py index 60291ea54a..6997207dac 100644 --- a/esphome/components/lvgl/types.py +++ b/esphome/components/lvgl/types.py @@ -1,4 +1,4 @@ -from esphome import codegen as cg +from esphome import automation, codegen as cg from esphome.core import ID from esphome.cpp_generator import MockObjClass @@ -23,8 +23,14 @@ lvgl_ns = cg.esphome_ns.namespace("lvgl") char_ptr = cg.global_ns.namespace("char").operator("ptr") void_ptr = cg.void.operator("ptr") LvglComponent = lvgl_ns.class_("LvglComponent", cg.PollingComponent) +LvglComponentPtr = LvglComponent.operator("ptr") lv_event_code_t = cg.global_ns.namespace("lv_event_code_t") +lv_indev_type_t = cg.global_ns.enum("lv_indev_type_t") FontEngine = lvgl_ns.class_("FontEngine") +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) 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") @@ -33,9 +39,11 @@ 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_ptr = cg.global_ns.struct("lv_disp_t").operator("ptr") lv_color_t = cg.global_ns.struct("lv_color_t") +lv_group_t = cg.global_ns.struct("lv_group_t") LVTouchListener = lvgl_ns.class_("LVTouchListener") LVEncoderListener = lvgl_ns.class_("LVEncoderListener") lv_obj_t = LvType("lv_obj_t") +lv_img_t = LvType("lv_img_t") # this will be populated later, in __init__.py to avoid circular imports. @@ -58,7 +66,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, ) @@ -83,11 +91,14 @@ class WidgetType: self.name = name self.w_type = w_type self.parts = parts - self.schema = schema or {} - if modify_schema is None: - self.modify_schema = schema + if schema is None: + self.schema = {} else: - self.modify_schema = modify_schema + self.schema = schema + if modify_schema is None: + self.modify_schema = self.schema + else: + self.modify_schema = self.schema @property def animated(self): diff --git a/esphome/components/lvgl/widget.py b/esphome/components/lvgl/widget.py index 4755d8b21d..83aed341e7 100644 --- a/esphome/components/lvgl/widget.py +++ b/esphome/components/lvgl/widget.py @@ -4,9 +4,9 @@ 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_GROUP, CONF_ID, CONF_STATE -from esphome.core import ID, TimePeriod +from esphome.core import CORE, TimePeriod from esphome.coroutine import FakeAwaitable -from esphome.cpp_generator import MockObjClass +from esphome.cpp_generator import MockObj, MockObjClass, VariableDeclarationExpression from .defines import ( CONF_DEFAULT, @@ -16,13 +16,15 @@ from .defines import ( OBJ_FLAGS, PARTS, STATES, + ConstantLiteral, LValidator, join_enums, + literal, ) from .helpers import add_lv_use -from .lvcode import ConstantLiteral, add_line_marks, lv, lv_add, lv_assign, lv_obj +from .lvcode import add_group, add_line_marks, lv, lv_add, lv_assign, lv_expr, lv_obj from .schemas import ALL_STYLES, STYLE_REMAP -from .types import WIDGET_TYPES, WidgetType, lv_obj_t +from .types import WIDGET_TYPES, LvType, WidgetType, lv_obj_t, lv_obj_t_ptr EVENT_LAMB = "event_lamb__" @@ -76,17 +78,20 @@ class Widget: return f"{self.var}->obj" return self.var - def add_state(self, *args): - return lv_obj.add_state(self.obj, *args) + def add_state(self, state): + return lv_obj.add_state(self.obj, literal(state)) - def clear_state(self, *args): - return lv_obj.clear_state(self.obj, *args) + def clear_state(self, state): + return lv_obj.clear_state(self.obj, literal(state)) - def add_flag(self, *args): - return lv_obj.add_flag(self.obj, *args) + def has_state(self, state): + return lv_expr.obj_get_state(self.obj) & literal(state) != 0 - def clear_flag(self, *args): - return lv_obj.clear_flag(self.obj, *args) + def add_flag(self, flag): + return lv_obj.add_flag(self.obj, literal(flag)) + + def clear_flag(self, flag): + return lv_obj.clear_flag(self.obj, literal(flag)) def set_property(self, prop, value, animated: bool = None, ltype=None): if isinstance(value, dict): @@ -125,6 +130,16 @@ class Widget: def __str__(self): return f"({self.var}, {self.type})" + def get_args(self): + if isinstance(self.type.w_type, LvType): + return self.type.w_type.args + return [(lv_obj_t_ptr, "obj")] + + def get_value(self): + if isinstance(self.type.w_type, LvType): + return self.type.w_type.value(self) + return self.obj + # Map of widgets to their config, used for trigger generation widget_map: dict[Any, Widget] = {} @@ -146,7 +161,8 @@ def get_widget_generator(wid): yield -async def get_widget(wid: ID) -> Widget: +async def get_widget(config: dict, id: str = CONF_ID) -> Widget: + wid = config[id] if obj := widget_map.get(wid): return obj return await FakeAwaitable(get_widget_generator(wid)) @@ -204,9 +220,10 @@ async def set_obj_properties(w: Widget, config): }.items(): if isinstance(ALL_STYLES[prop], LValidator): value = await ALL_STYLES[prop].process(value) - # Remapping for backwards compatibility of style names prop_r = STYLE_REMAP.get(prop, prop) w.set_style(prop_r, value, lv_state) + if group := add_group(config.get(CONF_GROUP)): + lv.group_add_obj(group, w.obj) flag_clr = set() flag_set = set() props = parts[CONF_MAIN][CONF_DEFAULT] @@ -241,7 +258,7 @@ async def set_obj_properties(w: Widget, config): w.clear_state(clears) for key, value in lambs.items(): lamb = await cg.process_lambda(value, [], return_type=cg.bool_) - state = ConstantLiteral(f"LV_STATE_{key.upper}") + state = f"LV_STATE_{key.upper}" lv.cond_if(lamb) w.add_state(state) lv.cond_else() @@ -281,10 +298,19 @@ async def widget_to_code(w_cnfig, w_type, parent): var = cg.new_Pvariable(wid) lv_add(var.set_obj(creator)) else: - var = cg.Pvariable(wid, cg.nullptr, type_=lv_obj_t) + var = MockObj(wid, "->") + decl = VariableDeclarationExpression(lv_obj_t, "*", wid) + CORE.add_global(decl) + CORE.register_variable(wid, var) lv_assign(var, creator) widget = Widget.create(wid, var, spec, w_cnfig, parent) await set_obj_properties(widget, w_cnfig) await add_widgets(widget, w_cnfig) await spec.to_code(widget, w_cnfig) + + +lv_scr_act_spec = LvScrActType() +lv_scr_act = Widget.create( + None, ConstantLiteral("lv_scr_act()"), lv_scr_act_spec, {}, parent=None +) diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 6ba5b64761..726db24592 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -39,9 +39,12 @@ #define USE_LOCK #define USE_LOGGER #define USE_LVGL +#define USE_LVGL_BINARY_SENSOR #define USE_LVGL_FONT #define USE_LVGL_IMAGE +#define USE_LVGL_KEY_LISTENER #define USE_LVGL_TOUCHSCREEN +#define USE_LVGL_ROTARY_ENCODER #define USE_MDNS #define USE_MEDIA_PLAYER #define USE_MQTT diff --git a/tests/components/lvgl/lvgl-package.yaml b/tests/components/lvgl/lvgl-package.yaml index 696c749876..fde700e0bd 100644 --- a/tests/components/lvgl/lvgl-package.yaml +++ b/tests/components/lvgl/lvgl-package.yaml @@ -7,6 +7,7 @@ lvgl: long_press_time: 500ms widgets: - label: + id: hello_label text: Hello world text_color: 0xFF8000 align: center @@ -95,9 +96,43 @@ lvgl: height: 10% pressed: bg_color: light_blue + checkable: true + checked: + bg_color: 0x000000 widgets: - label: text: Button + on_click: + lvgl.label.update: + id: hello_label + bg_color: 0x123456 + text: clicked + on_value: + logger.log: + format: "state now %d" + args: [x] + on_short_click: + lvgl.widget.hide: hello_label + on_long_press: + lvgl.widget.show: hello_label + on_cancel: + lvgl.widget.enable: hello_label + on_ready: + lvgl.widget.disable: hello_label + on_defocus: + lvgl.widget.hide: hello_label + on_focus: + logger.log: Button clicked + on_scroll: + logger.log: Button clicked + on_scroll_end: + logger.log: Button clicked + on_scroll_begin: + logger.log: Button clicked + on_release: + logger.log: Button clicked + on_long_press_repeat: + logger.log: Button clicked font: - file: "gfonts://Roboto" diff --git a/tests/components/lvgl/test.esp32-idf.yaml b/tests/components/lvgl/test.esp32-idf.yaml index eab75b05f3..0f740db980 100644 --- a/tests/components/lvgl/test.esp32-idf.yaml +++ b/tests/components/lvgl/test.esp32-idf.yaml @@ -6,6 +6,23 @@ i2c: sda: GPIO18 scl: GPIO19 +sensor: + - platform: rotary_encoder + name: "Rotary Encoder" + id: encoder + pin_a: 2 + pin_b: 1 + internal: true + +binary_sensor: + - platform: gpio + id: pushbutton + name: Pushbutton + pin: + number: 0 + inverted: true + ignore_strapping_warning: true + display: - platform: ili9xxx model: st7789v @@ -50,5 +67,9 @@ lvgl: displays: - tft_display - second_display + rotary_encoders: + sensor: encoder + enter_button: pushbutton + group: general <<: !include common.yaml From dfacf1bbfe3aef5ca6796f92e8a46cb62212e924 Mon Sep 17 00:00:00 2001 From: thevogoncoder <6619878+thevogoncoder@users.noreply.github.com> Date: Thu, 25 Jul 2024 04:06:23 +0200 Subject: [PATCH 1847/2101] Add delay after sending REG_READ_START (#7130) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/pmwcs3/pmwcs3.cpp | 61 ++++++++++++++-------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/esphome/components/pmwcs3/pmwcs3.cpp b/esphome/components/pmwcs3/pmwcs3.cpp index 812018b52e..97ce4c9ae0 100644 --- a/esphome/components/pmwcs3/pmwcs3.cpp +++ b/esphome/components/pmwcs3/pmwcs3.cpp @@ -72,43 +72,44 @@ void PMWCS3Component::dump_config() { LOG_SENSOR(" ", "vwc", this->vwc_sensor_); } void PMWCS3Component::read_data_() { - uint8_t data[8]; - float e25, ec, temperature, vwc; - /////// Super important !!!! first activate reading PMWCS3_REG_READ_START (if not, return always the same values) //// - if (!this->write_bytes(PMWCS3_REG_READ_START, nullptr, 0)) { this->status_set_warning(); ESP_LOGVV(TAG, "Failed to write into REG_READ_START register !!!"); return; } - // NOLINT delay(100); - if (!this->read_bytes(PMWCS3_REG_GET_DATA, (uint8_t *) &data, 8)) { - ESP_LOGVV(TAG, "Error reading PMWCS3_REG_GET_DATA registers"); - this->mark_failed(); - return; - } - if (this->e25_sensor_ != nullptr) { - e25 = ((data[1] << 8) | data[0]) / 100.0; - this->e25_sensor_->publish_state(e25); - ESP_LOGVV(TAG, "e25: data[0]=%d, data[1]=%d, result=%f", data[0], data[1], e25); - } - if (this->ec_sensor_ != nullptr) { - ec = ((data[3] << 8) | data[2]) / 10.0; - this->ec_sensor_->publish_state(ec); - ESP_LOGVV(TAG, "ec: data[2]=%d, data[3]=%d, result=%f", data[2], data[3], ec); - } - if (this->temperature_sensor_ != nullptr) { - temperature = ((data[5] << 8) | data[4]) / 100.0; - this->temperature_sensor_->publish_state(temperature); - ESP_LOGVV(TAG, "temp: data[4]=%d, data[5]=%d, result=%f", data[4], data[5], temperature); - } - if (this->vwc_sensor_ != nullptr) { - vwc = ((data[7] << 8) | data[6]) / 10.0; - this->vwc_sensor_->publish_state(vwc); - ESP_LOGVV(TAG, "vwc: data[6]=%d, data[7]=%d, result=%f", data[6], data[7], vwc); - } + // Wait for the sensor to be ready. + // 80ms empirically determined (conservative). + this->set_timeout(80, [this] { + uint8_t data[8]; + float e25, ec, temperature, vwc; + if (!this->read_bytes(PMWCS3_REG_GET_DATA, (uint8_t *) &data, 8)) { + ESP_LOGVV(TAG, "Error reading PMWCS3_REG_GET_DATA registers"); + this->mark_failed(); + return; + } + if (this->e25_sensor_ != nullptr) { + e25 = ((data[1] << 8) | data[0]) / 100.0; + this->e25_sensor_->publish_state(e25); + ESP_LOGVV(TAG, "e25: data[0]=%d, data[1]=%d, result=%f", data[0], data[1], e25); + } + if (this->ec_sensor_ != nullptr) { + ec = ((data[3] << 8) | data[2]) / 10.0; + this->ec_sensor_->publish_state(ec); + ESP_LOGVV(TAG, "ec: data[2]=%d, data[3]=%d, result=%f", data[2], data[3], ec); + } + if (this->temperature_sensor_ != nullptr) { + temperature = ((data[5] << 8) | data[4]) / 100.0; + this->temperature_sensor_->publish_state(temperature); + ESP_LOGVV(TAG, "temp: data[4]=%d, data[5]=%d, result=%f", data[4], data[5], temperature); + } + if (this->vwc_sensor_ != nullptr) { + vwc = ((data[7] << 8) | data[6]) / 10.0; + this->vwc_sensor_->publish_state(vwc); + ESP_LOGVV(TAG, "vwc: data[6]=%d, data[7]=%d, result=%f", data[6], data[7], vwc); + } + }); } } // namespace pmwcs3 From a70f926971264501287ac93b8e39d533461990dc Mon Sep 17 00:00:00 2001 From: RubyBailey <60991881+RubyBailey@users.noreply.github.com> Date: Mon, 29 Jul 2024 16:20:29 -0700 Subject: [PATCH 1848/2101] Fix for Mitsubishi units that only support cooling (#7143) --- esphome/components/mitsubishi/mitsubishi.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/esphome/components/mitsubishi/mitsubishi.cpp b/esphome/components/mitsubishi/mitsubishi.cpp index a02aabf14d..449c8fc712 100644 --- a/esphome/components/mitsubishi/mitsubishi.cpp +++ b/esphome/components/mitsubishi/mitsubishi.cpp @@ -110,7 +110,7 @@ void MitsubishiClimate::transmit_state() { // Byte 15: HVAC specfic, i.e. POWERFUL, SMART SET, PLASMA, always 0x00 // Byte 16: Constant 0x00 // Byte 17: Checksum: SUM[Byte0...Byte16] - uint8_t remote_state[18] = {0x23, 0xCB, 0x26, 0x01, 0x00, 0x20, 0x08, 0x00, 0x00, + uint8_t remote_state[18] = {0x23, 0xCB, 0x26, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; switch (this->mode) { @@ -136,6 +136,12 @@ void MitsubishiClimate::transmit_state() { break; case climate::CLIMATE_MODE_OFF: default: + remote_state[6] = MITSUBISHI_MODE_COOL; + remote_state[8] = MITSUBISHI_MODE_A_COOL; + if (this->supports_heat_) { + remote_state[6] = MITSUBISHI_MODE_HEAT; + remote_state[8] = MITSUBISHI_MODE_A_HEAT; + } remote_state[5] = MITSUBISHI_OFF; break; } From 5ac9d301eaca1d46cc0db942e828a7995289640e Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt Date: Tue, 30 Jul 2024 16:57:51 -0400 Subject: [PATCH 1849/2101] [micro_wake_word] Fix VAD detection and modify detection computation (#7164) --- esphome/components/micro_wake_word/streaming_model.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/esphome/components/micro_wake_word/streaming_model.cpp b/esphome/components/micro_wake_word/streaming_model.cpp index 013fa2ce6e..d0d2e2df05 100644 --- a/esphome/components/micro_wake_word/streaming_model.cpp +++ b/esphome/components/micro_wake_word/streaming_model.cpp @@ -148,7 +148,7 @@ WakeWordModel::WakeWordModel(const uint8_t *model_start, float probability_cutof }; bool WakeWordModel::determine_detected() { - int32_t sum = 0; + uint32_t sum = 0; for (auto &prob : this->recent_streaming_probabilities_) { sum += prob; } @@ -175,12 +175,14 @@ VADModel::VADModel(const uint8_t *model_start, float probability_cutoff, size_t }; bool VADModel::determine_detected() { - uint8_t max = 0; + uint32_t sum = 0; for (auto &prob : this->recent_streaming_probabilities_) { - max = std::max(prob, max); + sum += prob; } - return max > this->probability_cutoff_; + float sliding_window_average = static_cast(sum) / static_cast(255 * this->sliding_window_size_); + + return sliding_window_average > this->probability_cutoff_; } } // namespace micro_wake_word From 0af10c58f53466da19d9e065f764124e3bd31810 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 1 Aug 2024 07:51:23 +1200 Subject: [PATCH 1850/2101] Bump version to 2024.7.3 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 9abfafc4a4..1f63497982 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.7.2" +__version__ = "2024.7.3" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From cb9906b9215f17903ac004af160cc1537998b5a6 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 1 Aug 2024 22:38:36 +1200 Subject: [PATCH 1851/2101] [api] ``homeassistant.action`` replaces ``homeassistant.service`` (#7171) --- esphome/components/api/__init__.py | 130 +++++++++++++-------- esphome/config_validation.py | 10 ++ esphome/const.py | 2 + tests/components/api/common.yaml | 16 +-- tests/components/homeassistant/common.yaml | 8 +- 5 files changed, 103 insertions(+), 63 deletions(-) diff --git a/esphome/components/api/__init__.py b/esphome/components/api/__init__.py index d6b4416af8..38b50d4b9d 100644 --- a/esphome/components/api/__init__.py +++ b/esphome/components/api/__init__.py @@ -1,25 +1,27 @@ import base64 -import esphome.codegen as cg -import esphome.config_validation as cv from esphome import automation from esphome.automation import Condition +import esphome.codegen as cg +import esphome.config_validation as cv from esphome.const import ( + CONF_ACTION, + CONF_ACTIONS, CONF_DATA, CONF_DATA_TEMPLATE, + CONF_EVENT, CONF_ID, CONF_KEY, + CONF_ON_CLIENT_CONNECTED, + CONF_ON_CLIENT_DISCONNECTED, CONF_PASSWORD, CONF_PORT, CONF_REBOOT_TIMEOUT, CONF_SERVICE, - CONF_VARIABLES, CONF_SERVICES, - CONF_TRIGGER_ID, - CONF_EVENT, CONF_TAG, - CONF_ON_CLIENT_CONNECTED, - CONF_ON_CLIENT_DISCONNECTED, + CONF_TRIGGER_ID, + CONF_VARIABLES, ) from esphome.core import coroutine_with_priority @@ -63,40 +65,51 @@ def validate_encryption_key(value): return value -CONFIG_SCHEMA = cv.Schema( +ACTIONS_SCHEMA = automation.validate_automation( { - cv.GenerateID(): cv.declare_id(APIServer), - cv.Optional(CONF_PORT, default=6053): cv.port, - cv.Optional(CONF_PASSWORD, default=""): cv.string_strict, - cv.Optional( - CONF_REBOOT_TIMEOUT, default="15min" - ): cv.positive_time_period_milliseconds, - cv.Optional(CONF_SERVICES): automation.validate_automation( + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(UserServiceTrigger), + cv.Exclusive(CONF_SERVICE, group_of_exclusion=CONF_ACTION): cv.valid_name, + cv.Exclusive(CONF_ACTION, group_of_exclusion=CONF_ACTION): cv.valid_name, + cv.Optional(CONF_VARIABLES, default={}): cv.Schema( { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(UserServiceTrigger), - cv.Required(CONF_SERVICE): cv.valid_name, - cv.Optional(CONF_VARIABLES, default={}): cv.Schema( - { - cv.validate_id_name: cv.one_of( - *SERVICE_ARG_NATIVE_TYPES, lower=True - ), - } - ), + cv.validate_id_name: cv.one_of(*SERVICE_ARG_NATIVE_TYPES, lower=True), } ), - cv.Optional(CONF_ENCRYPTION): cv.Schema( - { - cv.Required(CONF_KEY): validate_encryption_key, - } - ), - cv.Optional(CONF_ON_CLIENT_CONNECTED): automation.validate_automation( - single=True - ), - cv.Optional(CONF_ON_CLIENT_DISCONNECTED): automation.validate_automation( - single=True - ), - } -).extend(cv.COMPONENT_SCHEMA) + }, + cv.All( + cv.has_exactly_one_key(CONF_SERVICE, CONF_ACTION), + cv.rename_key(CONF_SERVICE, CONF_ACTION), + ), +) + +CONFIG_SCHEMA = cv.All( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(APIServer), + cv.Optional(CONF_PORT, default=6053): cv.port, + cv.Optional(CONF_PASSWORD, default=""): cv.string_strict, + cv.Optional( + CONF_REBOOT_TIMEOUT, default="15min" + ): cv.positive_time_period_milliseconds, + cv.Exclusive( + CONF_SERVICES, group_of_exclusion=CONF_ACTIONS + ): ACTIONS_SCHEMA, + cv.Exclusive(CONF_ACTIONS, group_of_exclusion=CONF_ACTIONS): ACTIONS_SCHEMA, + cv.Optional(CONF_ENCRYPTION): cv.Schema( + { + cv.Required(CONF_KEY): validate_encryption_key, + } + ), + cv.Optional(CONF_ON_CLIENT_CONNECTED): automation.validate_automation( + single=True + ), + cv.Optional(CONF_ON_CLIENT_DISCONNECTED): automation.validate_automation( + single=True + ), + } + ).extend(cv.COMPONENT_SCHEMA), + cv.rename_key(CONF_SERVICES, CONF_ACTIONS), +) @coroutine_with_priority(40.0) @@ -108,7 +121,7 @@ async def to_code(config): cg.add(var.set_password(config[CONF_PASSWORD])) cg.add(var.set_reboot_timeout(config[CONF_REBOOT_TIMEOUT])) - for conf in config.get(CONF_SERVICES, []): + for conf in config.get(CONF_ACTIONS, []): template_args = [] func_args = [] service_arg_names = [] @@ -119,7 +132,7 @@ async def to_code(config): service_arg_names.append(name) templ = cg.TemplateArguments(*template_args) trigger = cg.new_Pvariable( - conf[CONF_TRIGGER_ID], templ, conf[CONF_SERVICE], service_arg_names + conf[CONF_TRIGGER_ID], templ, conf[CONF_ACTION], service_arg_names ) cg.add(var.register_user_service(trigger)) await automation.build_automation(trigger, func_args, conf) @@ -152,28 +165,43 @@ async def to_code(config): KEY_VALUE_SCHEMA = cv.Schema({cv.string: cv.templatable(cv.string_strict)}) -HOMEASSISTANT_SERVICE_ACTION_SCHEMA = cv.Schema( - { - cv.GenerateID(): cv.use_id(APIServer), - cv.Required(CONF_SERVICE): cv.templatable(cv.string), - cv.Optional(CONF_DATA, default={}): KEY_VALUE_SCHEMA, - cv.Optional(CONF_DATA_TEMPLATE, default={}): KEY_VALUE_SCHEMA, - cv.Optional(CONF_VARIABLES, default={}): cv.Schema( - {cv.string: cv.returning_lambda} - ), - } + +HOMEASSISTANT_ACTION_ACTION_SCHEMA = cv.All( + cv.Schema( + { + cv.GenerateID(): cv.use_id(APIServer), + cv.Exclusive(CONF_SERVICE, group_of_exclusion=CONF_ACTION): cv.templatable( + cv.string + ), + cv.Exclusive(CONF_ACTION, group_of_exclusion=CONF_ACTION): cv.templatable( + cv.string + ), + cv.Optional(CONF_DATA, default={}): KEY_VALUE_SCHEMA, + cv.Optional(CONF_DATA_TEMPLATE, default={}): KEY_VALUE_SCHEMA, + cv.Optional(CONF_VARIABLES, default={}): cv.Schema( + {cv.string: cv.returning_lambda} + ), + } + ), + cv.has_exactly_one_key(CONF_SERVICE, CONF_ACTION), + cv.rename_key(CONF_SERVICE, CONF_ACTION), ) +@automation.register_action( + "homeassistant.action", + HomeAssistantServiceCallAction, + HOMEASSISTANT_ACTION_ACTION_SCHEMA, +) @automation.register_action( "homeassistant.service", HomeAssistantServiceCallAction, - HOMEASSISTANT_SERVICE_ACTION_SCHEMA, + HOMEASSISTANT_ACTION_ACTION_SCHEMA, ) async def homeassistant_service_to_code(config, action_id, template_arg, args): serv = await cg.get_variable(config[CONF_ID]) var = cg.new_Pvariable(action_id, template_arg, serv, False) - templ = await cg.templatable(config[CONF_SERVICE], args, None) + templ = await cg.templatable(config[CONF_ACTION], args, None) cg.add(var.set_service(templ)) for key, value in config[CONF_DATA].items(): templ = await cg.templatable(value, args, None) diff --git a/esphome/config_validation.py b/esphome/config_validation.py index 1cd1d6aa31..d93f8aed9a 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -2181,3 +2181,13 @@ SOURCE_SCHEMA = Any( } ), ) + + +def rename_key(old_key, new_key): + def validator(config: dict) -> dict: + config = config.copy() + if old_key in config: + config[new_key] = config.pop(old_key) + return config + + return validator diff --git a/esphome/const.py b/esphome/const.py index 37844e1047..39dd48d3f8 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -37,8 +37,10 @@ CONF_ACCELERATION_Y = "acceleration_y" CONF_ACCELERATION_Z = "acceleration_z" CONF_ACCURACY = "accuracy" CONF_ACCURACY_DECIMALS = "accuracy_decimals" +CONF_ACTION = "action" CONF_ACTION_ID = "action_id" CONF_ACTION_STATE_TOPIC = "action_state_topic" +CONF_ACTIONS = "actions" CONF_ACTIVE = "active" CONF_ACTIVE_POWER = "active_power" CONF_ACTUAL_GAIN = "actual_gain" diff --git a/tests/components/api/common.yaml b/tests/components/api/common.yaml index e0b900f92d..6c2a333598 100644 --- a/tests/components/api/common.yaml +++ b/tests/components/api/common.yaml @@ -5,8 +5,8 @@ esphome: event: esphome.button_pressed data: message: Button was pressed - - homeassistant.service: - service: notify.html5 + - homeassistant.action: + action: notify.html5 data: message: Button was pressed - homeassistant.tag_scanned: pulse @@ -21,8 +21,8 @@ api: reboot_timeout: 0min encryption: key: bOFFzzvfpg5DB94DuBGLXD/hMnhpDKgP9UQyBulwWVU= - services: - - service: hello_world + actions: + - action: hello_world variables: name: string then: @@ -30,10 +30,10 @@ api: format: Hello World %s! args: - name.c_str() - - service: empty_service + - action: empty_action then: - - logger.log: Service Called - - service: all_types + - logger.log: Action Called + - action: all_types variables: bool_: bool int_: int @@ -41,7 +41,7 @@ api: string_: string then: - logger.log: Something happened - - service: array_types + - action: array_types variables: bool_arr: bool[] int_arr: int[] diff --git a/tests/components/homeassistant/common.yaml b/tests/components/homeassistant/common.yaml index ae016a3bea..07a6e8090c 100644 --- a/tests/components/homeassistant/common.yaml +++ b/tests/components/homeassistant/common.yaml @@ -13,12 +13,12 @@ esphome: message: The humidity is {{ my_variable }}%. variables: my_variable: "return id(ha_hello_world_temperature).state;" - - homeassistant.service: - service: notify.html5 + - homeassistant.action: + action: notify.html5 data: message: Button was pressed - - homeassistant.service: - service: notify.html5 + - homeassistant.action: + action: notify.html5 data: title: New Humidity data_template: From a5f18dfe7fda26d0311cfeb2fde42d0bf528f576 Mon Sep 17 00:00:00 2001 From: SimoPk Date: Thu, 1 Aug 2024 12:39:54 +0200 Subject: [PATCH 1852/2101] ade7953_spi wrong size specified in read_array call (#7172) --- esphome/components/ade7953_spi/ade7953_spi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/ade7953_spi/ade7953_spi.cpp b/esphome/components/ade7953_spi/ade7953_spi.cpp index cfd5d71d0a..77a2a8adc7 100644 --- a/esphome/components/ade7953_spi/ade7953_spi.cpp +++ b/esphome/components/ade7953_spi/ade7953_spi.cpp @@ -60,7 +60,7 @@ bool AdE7953Spi::ade_read_16(uint16_t reg, uint16_t *value) { this->write_byte16(reg); this->transfer_byte(0x80); uint8_t recv[2]; - this->read_array(recv, 4); + this->read_array(recv, 2); *value = encode_uint16(recv[0], recv[1]); this->disable(); return false; From aedfb32482cf11feaa6373b73cc8ce8a2da50658 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 2 Aug 2024 10:01:21 +1200 Subject: [PATCH 1853/2101] Bump improv library to 1.2.4 (#7174) --- esphome/components/improv_base/__init__.py | 5 ++--- platformio.ini | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/esphome/components/improv_base/__init__.py b/esphome/components/improv_base/__init__.py index 5c2853a5c6..aa75f4d89c 100644 --- a/esphome/components/improv_base/__init__.py +++ b/esphome/components/improv_base/__init__.py @@ -1,8 +1,7 @@ import re -import esphome.config_validation as cv import esphome.codegen as cg - +import esphome.config_validation as cv from esphome.const import __version__ CODEOWNERS = ["@esphome/core"] @@ -39,4 +38,4 @@ def _process_next_url(url: str): async def setup_improv_core(var, config): if CONF_NEXT_URL in config: cg.add(var.set_next_url(_process_next_url(config[CONF_NEXT_URL]))) - cg.add_library("esphome/Improv", "1.2.3") + cg.add_library("improv/Improv", "1.2.4") diff --git a/platformio.ini b/platformio.ini index baf0a85d73..e4f363d650 100644 --- a/platformio.ini +++ b/platformio.ini @@ -35,7 +35,7 @@ build_flags = lib_deps = esphome/noise-c@0.1.4 ; api makuna/NeoPixelBus@2.7.3 ; neopixelbus - esphome/Improv@1.2.3 ; improv_serial / esp32_improv + improv/Improv@1.2.4 ; improv_serial / esp32_improv bblanchon/ArduinoJson@6.18.5 ; json wjtje/qr-code-generator-library@1.7.0 ; qr_code functionpointer/arduino-MLX90393@1.0.0 ; mlx90393 From 4a7570770b0b36cfc2495ad3795d4ae3c7df66bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Ebbinghaus?= Date: Fri, 2 Aug 2024 01:58:59 +0200 Subject: [PATCH 1854/2101] Implement 'round to nearest multiple' filter (#7142) --- esphome/components/sensor/__init__.py | 19 +++++++++++++++++++ esphome/components/sensor/filter.cpp | 8 ++++++++ esphome/components/sensor/filter.h | 9 +++++++++ esphome/config_validation.py | 1 + esphome/const.py | 1 + 5 files changed, 38 insertions(+) diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index 262e69d75b..3b76466dec 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -17,6 +17,7 @@ from esphome.const import ( CONF_ICON, CONF_ID, CONF_IGNORE_OUT_OF_RANGE, + CONF_MULTIPLE, CONF_ON_RAW_VALUE, CONF_ON_VALUE, CONF_ON_VALUE_RANGE, @@ -249,6 +250,7 @@ CalibratePolynomialFilter = sensor_ns.class_("CalibratePolynomialFilter", Filter SensorInRangeCondition = sensor_ns.class_("SensorInRangeCondition", Filter) 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_accuracy_decimals = cv.int_ @@ -734,6 +736,23 @@ async def round_filter_to_code(config, filter_id): ) +@FILTER_REGISTRY.register( + "round_to_multiple_of", + RoundMultipleFilter, + cv.maybe_simple_value( + { + cv.Required(CONF_MULTIPLE): cv.positive_not_null_float, + }, + key=CONF_MULTIPLE, + ), +) +async def round_multiple_filter_to_code(config, filter_id): + return cg.new_Pvariable( + filter_id, + config[CONF_MULTIPLE], + ) + + async def build_filters(config): return await cg.build_registry_list(FILTER_REGISTRY, config) diff --git a/esphome/components/sensor/filter.cpp b/esphome/components/sensor/filter.cpp index eaa909429b..bcf1fc8269 100644 --- a/esphome/components/sensor/filter.cpp +++ b/esphome/components/sensor/filter.cpp @@ -472,5 +472,13 @@ optional RoundFilter::new_value(float value) { return value; } +RoundMultipleFilter::RoundMultipleFilter(float multiple) : multiple_(multiple) {} +optional RoundMultipleFilter::new_value(float value) { + if (std::isfinite(value)) { + return value - remainderf(value, this->multiple_); + } + return value; +} + } // namespace sensor } // namespace esphome diff --git a/esphome/components/sensor/filter.h b/esphome/components/sensor/filter.h index c13cb3420a..92b1d8d240 100644 --- a/esphome/components/sensor/filter.h +++ b/esphome/components/sensor/filter.h @@ -431,5 +431,14 @@ class RoundFilter : public Filter { uint8_t precision_; }; +class RoundMultipleFilter : public Filter { + public: + explicit RoundMultipleFilter(float multiple); + optional new_value(float value) override; + + protected: + float multiple_; +}; + } // namespace sensor } // namespace esphome diff --git a/esphome/config_validation.py b/esphome/config_validation.py index d93f8aed9a..6e1d3ba2f9 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -464,6 +464,7 @@ zero_to_one_float = float_range(min=0, max=1) negative_one_to_one_float = float_range(min=-1, max=1) positive_int = int_range(min=0) positive_not_null_int = int_range(min=0, min_included=False) +positive_not_null_float = float_range(min=0, min_included=False) def validate_id_name(value): diff --git a/esphome/const.py b/esphome/const.py index 39dd48d3f8..fcb630badd 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -503,6 +503,7 @@ CONF_MOTION = "motion" CONF_MOVEMENT_COUNTER = "movement_counter" CONF_MQTT = "mqtt" CONF_MQTT_ID = "mqtt_id" +CONF_MULTIPLE = "multiple" CONF_MULTIPLEXER = "multiplexer" CONF_MULTIPLY = "multiply" CONF_NAME = "name" From 61c65811233eb1b678fcfa077d6370e7f07ba091 Mon Sep 17 00:00:00 2001 From: Olivier ARCHER Date: Sat, 3 Aug 2024 01:00:18 +0200 Subject: [PATCH 1855/2101] git ignore managed_components (#7180) --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 0c9a878400..79820249ac 100644 --- a/.gitignore +++ b/.gitignore @@ -138,3 +138,5 @@ sdkconfig.* .tests/ /components +/managed_components + From 81ac9391d1af48bc02b4df9886954474c1fd7d01 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Mon, 5 Aug 2024 12:04:06 +1000 Subject: [PATCH 1856/2101] [core] Eliminate nuisance messages from `build_codeowners` (#7185) --- esphome/loader.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/esphome/loader.py b/esphome/loader.py index 9399c4cb31..d808805119 100644 --- a/esphome/loader.py +++ b/esphome/loader.py @@ -1,3 +1,4 @@ +from contextlib import AbstractContextManager from dataclasses import dataclass import importlib import importlib.abc @@ -7,7 +8,7 @@ import logging from pathlib import Path import sys from types import ModuleType -from typing import Any, Callable, ContextManager, Optional +from typing import Any, Callable, Optional from esphome.const import SOURCE_FILE_EXTENSIONS from esphome.core import CORE @@ -22,7 +23,7 @@ class FileResource: package: str resource: str - def path(self) -> ContextManager[Path]: + def path(self) -> AbstractContextManager[Path]: return importlib.resources.as_file( importlib.resources.files(self.package) / self.resource ) @@ -176,7 +177,7 @@ def _lookup_module(domain): module = importlib.import_module(f"esphome.components.{domain}") except ImportError as e: if "No module named" in str(e): - _LOGGER.error( + _LOGGER.info( "Unable to import component %s: %s", domain, str(e), exc_info=False ) else: From 38c25dec93b17ede8999f0cc6f295ba4a730ab6d Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 5 Aug 2024 16:15:19 +1200 Subject: [PATCH 1857/2101] [code-quality] More portable shebangs (#7189) Co-authored-by: Keith Burzinski --- docker/docker_entrypoint.sh | 2 +- script/devcontainer-post-create | 2 +- script/quicklint | 2 +- script/setup | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docker/docker_entrypoint.sh b/docker/docker_entrypoint.sh index 397b1528c5..1b9224244c 100755 --- a/docker/docker_entrypoint.sh +++ b/docker/docker_entrypoint.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # If /cache is mounted, use that as PIO's coredir # otherwise use path in /config (so that PIO packages aren't downloaded on each compile) diff --git a/script/devcontainer-post-create b/script/devcontainer-post-create index 272d350519..2d376786ac 100755 --- a/script/devcontainer-post-create +++ b/script/devcontainer-post-create @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e # set -x diff --git a/script/quicklint b/script/quicklint index a4fae98195..84e4c97667 100755 --- a/script/quicklint +++ b/script/quicklint @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e diff --git a/script/setup b/script/setup index aeb1b39bc1..824840c392 100755 --- a/script/setup +++ b/script/setup @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Set up ESPHome dev environment set -e From 87944f0c1b5df3019407bc20f0f0c29f8cf13033 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 5 Aug 2024 16:58:20 +1200 Subject: [PATCH 1858/2101] Add support for doing update entity refresh/check via API. (#7190) --- esphome/components/api/api.proto | 7 +++++- esphome/components/api/api_connection.cpp | 12 +++++++++- esphome/components/api/api_pb2.cpp | 22 +++++++++++++++---- esphome/components/api/api_pb2.h | 7 +++++- .../http_request/update/http_request_update.h | 1 + esphome/components/update/update_entity.h | 2 +- 6 files changed, 43 insertions(+), 8 deletions(-) diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index 812a1d74ae..b62fddf815 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -1872,6 +1872,11 @@ message UpdateStateResponse { string release_summary = 9; string release_url = 10; } +enum UpdateCommand { + UPDATE_COMMAND_NONE = 0; + UPDATE_COMMAND_UPDATE = 1; + UPDATE_COMMAND_CHECK = 2; +} message UpdateCommandRequest { option (id) = 118; option (source) = SOURCE_CLIENT; @@ -1879,5 +1884,5 @@ message UpdateCommandRequest { option (no_delay) = true; fixed32 key = 1; - bool install = 2; + UpdateCommand command = 2; } diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 2e73a8336e..81fa4cb339 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1328,7 +1328,17 @@ void APIConnection::update_command(const UpdateCommandRequest &msg) { if (update == nullptr) return; - update->perform(); + switch (msg.command) { + case enums::UPDATE_COMMAND_UPDATE: + update->perform(); + break; + case enums::UPDATE_COMMAND_CHECK: + update->check(); + break; + default: + ESP_LOGW(TAG, "Unknown update command: %d", msg.command); + break; + } } #endif diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index e6e905c6d1..a57627a66c 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -567,6 +567,20 @@ template<> const char *proto_enum_to_string(enums::ValveO } } #endif +#ifdef HAS_PROTO_MESSAGE_DUMP +template<> const char *proto_enum_to_string(enums::UpdateCommand value) { + switch (value) { + case enums::UPDATE_COMMAND_NONE: + return "UPDATE_COMMAND_NONE"; + case enums::UPDATE_COMMAND_UPDATE: + return "UPDATE_COMMAND_UPDATE"; + case enums::UPDATE_COMMAND_CHECK: + return "UPDATE_COMMAND_CHECK"; + default: + return "UNKNOWN"; + } +} +#endif bool HelloRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { case 2: { @@ -8596,7 +8610,7 @@ void UpdateStateResponse::dump_to(std::string &out) const { bool UpdateCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { case 2: { - this->install = value.as_bool(); + this->command = value.as_enum(); return true; } default: @@ -8615,7 +8629,7 @@ bool UpdateCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { } void UpdateCommandRequest::encode(ProtoWriteBuffer buffer) const { buffer.encode_fixed32(1, this->key); - buffer.encode_bool(2, this->install); + buffer.encode_enum(2, this->command); } #ifdef HAS_PROTO_MESSAGE_DUMP void UpdateCommandRequest::dump_to(std::string &out) const { @@ -8626,8 +8640,8 @@ void UpdateCommandRequest::dump_to(std::string &out) const { out.append(buffer); out.append("\n"); - out.append(" install: "); - out.append(YESNO(this->install)); + out.append(" command: "); + out.append(proto_enum_to_string(this->command)); out.append("\n"); out.append("}"); } diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index ef051eecf1..bb5263cffa 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -227,6 +227,11 @@ enum ValveOperation : uint32_t { VALVE_OPERATION_IS_OPENING = 1, VALVE_OPERATION_IS_CLOSING = 2, }; +enum UpdateCommand : uint32_t { + UPDATE_COMMAND_NONE = 0, + UPDATE_COMMAND_UPDATE = 1, + UPDATE_COMMAND_CHECK = 2, +}; } // namespace enums @@ -2175,7 +2180,7 @@ class UpdateStateResponse : public ProtoMessage { class UpdateCommandRequest : public ProtoMessage { public: uint32_t key{0}; - bool install{false}; + enums::UpdateCommand command{}; void encode(ProtoWriteBuffer buffer) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; diff --git a/esphome/components/http_request/update/http_request_update.h b/esphome/components/http_request/update/http_request_update.h index 943231a906..45c7e6a447 100644 --- a/esphome/components/http_request/update/http_request_update.h +++ b/esphome/components/http_request/update/http_request_update.h @@ -16,6 +16,7 @@ class HttpRequestUpdate : public update::UpdateEntity, public PollingComponent { void update() override; void perform(bool force) override; + void check() override { this->update(); } void set_source_url(const std::string &source_url) { this->source_url_ = source_url; } diff --git a/esphome/components/update/update_entity.h b/esphome/components/update/update_entity.h index 568fbe3bb0..cc269e288f 100644 --- a/esphome/components/update/update_entity.h +++ b/esphome/components/update/update_entity.h @@ -33,8 +33,8 @@ class UpdateEntity : public EntityBase, public EntityBase_DeviceClass { void publish_state(); void perform() { this->perform(false); } - virtual void perform(bool force) = 0; + virtual void check() = 0; const UpdateInfo &update_info = update_info_; const UpdateState &state = state_; From d18bb34f87758cff3d1a6d881b1b167d1d6f79a1 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Mon, 5 Aug 2024 15:07:05 +1000 Subject: [PATCH 1859/2101] [lvgl] Stage 4 (#7166) --- esphome/components/lvgl/__init__.py | 110 +++++-- esphome/components/lvgl/animimg.py | 117 +++++++ esphome/components/lvgl/arc.py | 78 +++++ esphome/components/lvgl/automation.py | 186 ++++++----- esphome/components/lvgl/btn.py | 11 +- esphome/components/lvgl/checkbox.py | 25 ++ esphome/components/lvgl/defines.py | 64 ++-- esphome/components/lvgl/helpers.py | 20 -- esphome/components/lvgl/img.py | 85 +++++ esphome/components/lvgl/label.py | 9 +- esphome/components/lvgl/led.py | 29 ++ esphome/components/lvgl/line.py | 51 +++ esphome/components/lvgl/lv_bar.py | 53 ++++ esphome/components/lvgl/lv_switch.py | 20 ++ esphome/components/lvgl/lv_validation.py | 60 +++- esphome/components/lvgl/lvcode.py | 236 +++++++++----- esphome/components/lvgl/lvgl_esphome.cpp | 202 ++++++++++++ esphome/components/lvgl/lvgl_esphome.h | 164 ++++------ esphome/components/lvgl/page.py | 113 +++++++ esphome/components/lvgl/rotary_encoders.py | 3 +- esphome/components/lvgl/schemas.py | 105 ++++++- esphome/components/lvgl/slider.py | 63 ++++ esphome/components/lvgl/spinner.py | 43 +++ esphome/components/lvgl/styles.py | 58 ++++ esphome/components/lvgl/trigger.py | 22 +- esphome/components/lvgl/types.py | 92 ++++-- esphome/components/lvgl/widget.py | 219 +++++++++---- tests/components/lvgl/lvgl-package.yaml | 343 +++++++++++++-------- 28 files changed, 2002 insertions(+), 579 deletions(-) create mode 100644 esphome/components/lvgl/animimg.py create mode 100644 esphome/components/lvgl/arc.py create mode 100644 esphome/components/lvgl/checkbox.py create mode 100644 esphome/components/lvgl/img.py create mode 100644 esphome/components/lvgl/led.py create mode 100644 esphome/components/lvgl/line.py create mode 100644 esphome/components/lvgl/lv_bar.py create mode 100644 esphome/components/lvgl/lv_switch.py create mode 100644 esphome/components/lvgl/page.py create mode 100644 esphome/components/lvgl/slider.py create mode 100644 esphome/components/lvgl/spinner.py create mode 100644 esphome/components/lvgl/styles.py diff --git a/esphome/components/lvgl/__init__.py b/esphome/components/lvgl/__init__.py index 182d04e038..c154689199 100644 --- a/esphome/components/lvgl/__init__.py +++ b/esphome/components/lvgl/__init__.py @@ -15,44 +15,91 @@ from esphome.const import ( CONF_TRIGGER_ID, CONF_TYPE, ) -from esphome.core import CORE, ID, Lambda +from esphome.core import CORE, ID from esphome.cpp_generator import MockObj from esphome.final_validate import full_config from esphome.helpers import write_file_if_changed from . import defines as df, helpers, lv_validation as lvalid -from .automation import update_to_code +from .animimg import animimg_spec +from .arc import arc_spec +from .automation import disp_update, update_to_code from .btn import btn_spec +from .checkbox import checkbox_spec +from .defines import CONF_SKIP +from .img import img_spec from .label import label_spec -from .lv_validation import lv_images_used -from .lvcode import LvContext +from .led import led_spec +from .line import line_spec +from .lv_bar import bar_spec +from .lv_switch import switch_spec +from .lv_validation import lv_bool, lv_images_used +from .lvcode import LvContext, LvglComponent from .obj import obj_spec +from .page import add_pages, page_spec from .rotary_encoders import ROTARY_ENCODER_CONFIG, rotary_encoders_to_code -from .schemas import any_widget_schema, create_modify_schema, obj_schema +from .schemas import ( + DISP_BG_SCHEMA, + FLEX_OBJ_SCHEMA, + GRID_CELL_SCHEMA, + LAYOUT_SCHEMAS, + STYLE_SCHEMA, + WIDGET_TYPES, + any_widget_schema, + container_schema, + create_modify_schema, + grid_alignments, + obj_schema, +) +from .slider import slider_spec +from .spinner import spinner_spec +from .styles import add_top_layer, styles_to_code, theme_to_code from .touchscreens import touchscreen_schema, touchscreens_to_code from .trigger import generate_triggers from .types import ( - WIDGET_TYPES, FontEngine, IdleTrigger, - LvglComponent, ObjUpdateAction, lv_font_t, + lv_style_t, lvgl_ns, ) from .widget import Widget, add_widgets, lv_scr_act, set_obj_properties DOMAIN = "lvgl" -DEPENDENCIES = ("display",) -AUTO_LOAD = ("key_provider",) -CODEOWNERS = ("@clydebarrow",) +DEPENDENCIES = ["display"] +AUTO_LOAD = ["key_provider"] +CODEOWNERS = ["@clydebarrow"] LOGGER = logging.getLogger(__name__) -for w_type in (label_spec, obj_spec, btn_spec): +for w_type in ( + label_spec, + obj_spec, + btn_spec, + bar_spec, + slider_spec, + arc_spec, + line_spec, + spinner_spec, + led_spec, + animimg_spec, + checkbox_spec, + img_spec, + switch_spec, +): WIDGET_TYPES[w_type.name] = w_type WIDGET_SCHEMA = any_widget_schema() +LAYOUT_SCHEMAS[df.TYPE_GRID] = { + cv.Optional(df.CONF_WIDGETS): cv.ensure_list(any_widget_schema(GRID_CELL_SCHEMA)) +} +LAYOUT_SCHEMAS[df.TYPE_FLEX] = { + cv.Optional(df.CONF_WIDGETS): cv.ensure_list(any_widget_schema(FLEX_OBJ_SCHEMA)) +} +LAYOUT_SCHEMAS[df.TYPE_NONE] = { + cv.Optional(df.CONF_WIDGETS): cv.ensure_list(any_widget_schema()) +} for w_type in WIDGET_TYPES.values(): register_action( f"lvgl.{w_type.name}.update", @@ -61,14 +108,6 @@ for w_type in WIDGET_TYPES.values(): )(update_to_code) -async def add_init_lambda(lv_component, init): - if init: - lamb = await cg.process_lambda( - Lambda(init), [(LvglComponent.operator("ptr"), "lv_component")] - ) - cg.add(lv_component.add_init_lambda(lamb)) - - lv_defines = {} # Dict of #defines to provide as build flags @@ -100,6 +139,9 @@ def generate_lv_conf_h(): def final_validation(config): + if pages := config.get(CONF_PAGES): + if all(p[CONF_SKIP] for p in pages): + raise cv.Invalid("At least one page must not be skipped") global_config = full_config.get() for display_id in config[df.CONF_DISPLAYS]: path = global_config.get_path_for_id(display_id)[:-1] @@ -193,18 +235,23 @@ async def to_code(config): else: add_define("LV_FONT_DEFAULT", await lvalid.lv_font.process(default_font)) - with LvContext(): + async with LvContext(lv_component): await touchscreens_to_code(lv_component, config) await rotary_encoders_to_code(lv_component, config) + await theme_to_code(config) + await styles_to_code(config) 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(config) + await disp_update(f"{lv_component}->get_disp()", config) Widget.set_completed() await generate_triggers(lv_component) for conf in config.get(CONF_ON_IDLE, ()): templ = await cg.templatable(conf[CONF_TIMEOUT], [], cg.uint32) idle_trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], lv_component, templ) await build_automation(idle_trigger, [], conf) - await add_init_lambda(lv_component, LvContext.get_code()) + for comp in helpers.lvgl_components_required: CORE.add_define(f"USE_LVGL_{comp.upper()}") for use in helpers.lv_uses: @@ -239,6 +286,16 @@ CONFIG_SCHEMA = ( cv.Optional(df.CONF_BYTE_ORDER, default="big_endian"): cv.one_of( "big_endian", "little_endian" ), + cv.Optional(df.CONF_STYLE_DEFINITIONS): cv.ensure_list( + cv.Schema({cv.Required(CONF_ID): cv.declare_id(lv_style_t)}) + .extend(STYLE_SCHEMA) + .extend( + { + cv.Optional(df.CONF_GRID_CELL_X_ALIGN): grid_alignments, + cv.Optional(df.CONF_GRID_CELL_Y_ALIGN): grid_alignments, + } + ) + ), cv.Optional(CONF_ON_IDLE): validate_automation( { cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(IdleTrigger), @@ -247,10 +304,19 @@ CONFIG_SCHEMA = ( ), } ), - cv.Optional(df.CONF_WIDGETS): cv.ensure_list(WIDGET_SCHEMA), + cv.Exclusive(df.CONF_WIDGETS, CONF_PAGES): cv.ensure_list(WIDGET_SCHEMA), + cv.Exclusive(CONF_PAGES, CONF_PAGES): cv.ensure_list( + container_schema(page_spec) + ), + cv.Optional(df.CONF_PAGE_WRAP, default=True): lv_bool, + cv.Optional(df.CONF_TOP_LAYER): container_schema(obj_spec), cv.Optional(df.CONF_TRANSPARENCY_KEY, default=0x000400): lvalid.lv_color, + cv.Optional(df.CONF_THEME): cv.Schema( + {cv.Optional(name): obj_schema(w) for name, w in WIDGET_TYPES.items()} + ), cv.GenerateID(df.CONF_TOUCHSCREENS): touchscreen_schema, cv.GenerateID(df.CONF_ROTARY_ENCODERS): ROTARY_ENCODER_CONFIG, } ) + .extend(DISP_BG_SCHEMA) ).add_extra(cv.has_at_least_one_key(CONF_PAGES, df.CONF_WIDGETS)) diff --git a/esphome/components/lvgl/animimg.py b/esphome/components/lvgl/animimg.py new file mode 100644 index 0000000000..20b85b019c --- /dev/null +++ b/esphome/components/lvgl/animimg.py @@ -0,0 +1,117 @@ +from esphome import automation +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.const import CONF_DURATION, CONF_ID + +from ...cpp_generator import MockObj +from .automation import action_to_code +from .defines import CONF_AUTO_START, CONF_MAIN, CONF_REPEAT_COUNT, CONF_SRC +from .helpers import lvgl_components_required +from .img import CONF_IMAGE +from .label import CONF_LABEL +from .lv_validation import lv_image, lv_milliseconds +from .lvcode import lv, lv_expr +from .types import LvType, ObjUpdateAction, void_ptr +from .widget import Widget, WidgetType, get_widgets + +CONF_ANIMIMG = "animimg" +CONF_SRC_LIST_ID = "src_list_id" + + +def lv_repeat_count(value): + if isinstance(value, str) and value.lower() in ("forever", "infinite"): + value = 0xFFFF + return cv.int_range(min=0, max=0xFFFF)(value) + + +ANIMIMG_BASE_SCHEMA = cv.Schema( + { + cv.Optional(CONF_REPEAT_COUNT, default="forever"): lv_repeat_count, + cv.Optional(CONF_AUTO_START, default=True): cv.boolean, + } +) +ANIMIMG_SCHEMA = ANIMIMG_BASE_SCHEMA.extend( + { + cv.Required(CONF_DURATION): lv_milliseconds, + cv.Required(CONF_SRC): cv.ensure_list(lv_image), + cv.GenerateID(CONF_SRC_LIST_ID): cv.declare_id(void_ptr), + } +) + +ANIMIMG_MODIFY_SCHEMA = ANIMIMG_BASE_SCHEMA.extend( + { + cv.Optional(CONF_DURATION): lv_milliseconds, + } +) + +lv_animimg_t = LvType("lv_animimg_t") + + +class AnimimgType(WidgetType): + def __init__(self): + super().__init__( + CONF_ANIMIMG, + lv_animimg_t, + (CONF_MAIN,), + ANIMIMG_SCHEMA, + ANIMIMG_MODIFY_SCHEMA, + ) + + async def to_code(self, w: Widget, config): + lvgl_components_required.add(CONF_IMAGE) + lvgl_components_required.add(CONF_ANIMIMG) + if CONF_SRC in config: + for x in config[CONF_SRC]: + await cg.get_variable(x) + srcs = [lv_expr.img_from(MockObj(x)) for x in config[CONF_SRC]] + src_id = cg.static_const_array(config[CONF_SRC_LIST_ID], srcs) + count = len(config[CONF_SRC]) + lv.animimg_set_src(w.obj, src_id, count) + lv.animimg_set_repeat_count(w.obj, config[CONF_REPEAT_COUNT]) + lv.animimg_set_duration(w.obj, config[CONF_DURATION]) + if config.get(CONF_AUTO_START): + lv.animimg_start(w.obj) + + def get_uses(self): + return CONF_IMAGE, CONF_LABEL + + +animimg_spec = AnimimgType() + + +@automation.register_action( + "lvgl.animimg.start", + ObjUpdateAction, + cv.maybe_simple_value( + { + cv.Required(CONF_ID): cv.use_id(lv_animimg_t), + }, + key=CONF_ID, + ), +) +async def animimg_start(config, action_id, template_arg, args): + widget = await get_widgets(config) + + async def do_start(w: Widget): + lv.animimg_start(w.obj) + + return await action_to_code(widget, do_start, action_id, template_arg, args) + + +@automation.register_action( + "lvgl.animimg.stop", + ObjUpdateAction, + cv.maybe_simple_value( + { + cv.Required(CONF_ID): cv.use_id(lv_animimg_t), + }, + key=CONF_ID, + ), +) +async def animimg_stop(config, action_id, template_arg, args): + widget = await get_widgets(config) + + async def do_stop(w: Widget): + lv.animimg_stop(w.obj) + + return await action_to_code(widget, do_stop, action_id, template_arg, args) diff --git a/esphome/components/lvgl/arc.py b/esphome/components/lvgl/arc.py new file mode 100644 index 0000000000..d036464c7a --- /dev/null +++ b/esphome/components/lvgl/arc.py @@ -0,0 +1,78 @@ +import esphome.config_validation as cv +from esphome.const import ( + CONF_MAX_VALUE, + CONF_MIN_VALUE, + CONF_MODE, + CONF_ROTATION, + CONF_VALUE, +) +from esphome.cpp_types import nullptr + +from .defines import ( + ARC_MODES, + CONF_ADJUSTABLE, + CONF_CHANGE_RATE, + CONF_END_ANGLE, + CONF_INDICATOR, + CONF_KNOB, + CONF_MAIN, + CONF_START_ANGLE, + literal, +) +from .lv_validation import angle, get_start_value, lv_float +from .lvcode import lv, lv_obj +from .types import LvNumber, NumberType +from .widget import Widget + +CONF_ARC = "arc" +ARC_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_START_ANGLE, default=135): angle, + cv.Optional(CONF_END_ANGLE, default=45): angle, + cv.Optional(CONF_ROTATION, default=0.0): angle, + cv.Optional(CONF_ADJUSTABLE, default=False): bool, + cv.Optional(CONF_MODE, default="NORMAL"): ARC_MODES.one_of, + cv.Optional(CONF_CHANGE_RATE, default=720): cv.uint16_t, + } +) + +ARC_MODIFY_SCHEMA = cv.Schema( + { + cv.Optional(CONF_VALUE): lv_float, + } +) + + +class ArcType(NumberType): + def __init__(self): + super().__init__( + CONF_ARC, + LvNumber("lv_arc_t"), + parts=(CONF_MAIN, CONF_INDICATOR, CONF_KNOB), + schema=ARC_SCHEMA, + modify_schema=ARC_MODIFY_SCHEMA, + ) + + async def to_code(self, w: Widget, config): + if CONF_MIN_VALUE in config: + lv.arc_set_range(w.obj, config[CONF_MIN_VALUE], config[CONF_MAX_VALUE]) + lv.arc_set_bg_angles( + w.obj, config[CONF_START_ANGLE] // 10, config[CONF_END_ANGLE] // 10 + ) + lv.arc_set_rotation(w.obj, config[CONF_ROTATION] // 10) + lv.arc_set_mode(w.obj, literal(config[CONF_MODE])) + lv.arc_set_change_rate(w.obj, config[CONF_CHANGE_RATE]) + + if config.get(CONF_ADJUSTABLE) is False: + lv_obj.remove_style(w.obj, nullptr, literal("LV_PART_KNOB")) + w.clear_flag("LV_OBJ_FLAG_CLICKABLE") + + value = await get_start_value(config) + if value is not None: + lv.arc_set_value(w.obj, value) + + +arc_spec = ArcType() diff --git a/esphome/components/lvgl/automation.py b/esphome/components/lvgl/automation.py index 4fd0be185e..ffa25783ad 100644 --- a/esphome/components/lvgl/automation.py +++ b/esphome/components/lvgl/automation.py @@ -1,15 +1,26 @@ +from collections.abc import Awaitable +from typing import Callable + from esphome import automation import esphome.codegen as cg import esphome.config_validation as cv from esphome.const import CONF_ID, CONF_TIMEOUT -from esphome.core import Lambda -from esphome.cpp_generator import RawStatement from esphome.cpp_types import nullptr -from .defines import CONF_LVGL_ID, CONF_SHOW_SNOW, literal -from .lv_validation import lv_bool +from .defines import ( + CONF_DISP_BG_COLOR, + CONF_DISP_BG_IMAGE, + CONF_LVGL_ID, + CONF_SHOW_SNOW, + literal, +) +from .lv_validation import lv_bool, lv_color, lv_image from .lvcode import ( + LVGL_COMP_ARG, LambdaContext, + LocalVariable, + LvConditional, + LvglComponent, ReturnStatement, add_line_marks, lv, @@ -17,46 +28,46 @@ from .lvcode import ( lv_obj, lvgl_comp, ) -from .schemas import ACTION_SCHEMA, LVGL_SCHEMA +from .schemas import DISP_BG_SCHEMA, LIST_ACTION_SCHEMA, LVGL_SCHEMA from .types import ( + LV_EVENT, + LV_STATE, LvglAction, - LvglComponent, - LvglComponentPtr, LvglCondition, ObjUpdateAction, + lv_disp_t, lv_obj_t, ) -from .widget import Widget, get_widget, lv_scr_act, set_obj_properties +from .widget import Widget, get_widgets, lv_scr_act, set_obj_properties -async def action_to_code(action: list, action_id, widget: Widget, template_arg, args): - with LambdaContext() as context: - lv.cond_if(widget.obj == nullptr) - lv_add(RawStatement(" return;")) - lv.cond_endif() - code = context.get_code() - code.extend(action) - action = "\n".join(code) + "\n\n" - lamb = await cg.process_lambda(Lambda(action), args) - var = cg.new_Pvariable(action_id, template_arg, lamb) +async def action_to_code( + widgets: list[Widget], + action: Callable[[Widget], Awaitable[None]], + action_id, + template_arg, + args, +): + async with LambdaContext(parameters=args, where=action_id) as context: + for widget in widgets: + with LvConditional(widget.obj != nullptr): + await action(widget) + var = cg.new_Pvariable(action_id, template_arg, await context.get_lambda()) return var async def update_to_code(config, action_id, template_arg, args): - if config is not None: - widget = await get_widget(config) - with LambdaContext() as context: - add_line_marks(action_id) - await set_obj_properties(widget, config) - await widget.type.to_code(widget, config) - if ( - widget.type.w_type.value_property is not None - and widget.type.w_type.value_property in config - ): - lv.event_send(widget.obj, literal("LV_EVENT_VALUE_CHANGED"), nullptr) - return await action_to_code( - context.get_code(), action_id, widget, template_arg, args - ) + async def do_update(widget: Widget): + await set_obj_properties(widget, config) + await widget.type.to_code(widget, config) + if ( + widget.type.w_type.value_property is not None + and widget.type.w_type.value_property in config + ): + lv.event_send(widget.obj, LV_EVENT.VALUE_CHANGED, nullptr) + + widgets = await get_widgets(config[CONF_ID]) + return await action_to_code(widgets, do_update, action_id, template_arg, args) @automation.register_condition( @@ -66,9 +77,7 @@ async def update_to_code(config, action_id, template_arg, args): ) async def lvgl_is_paused(config, condition_id, template_arg, args): lvgl = config[CONF_LVGL_ID] - with LambdaContext( - [(LvglComponentPtr, "lvgl_comp")], return_type=cg.bool_ - ) as context: + async with LambdaContext(LVGL_COMP_ARG, return_type=cg.bool_) as context: lv_add(ReturnStatement(lvgl_comp.is_paused())) var = cg.new_Pvariable(condition_id, template_arg, await context.get_lambda()) await cg.register_parented(var, lvgl) @@ -89,15 +98,23 @@ async def lvgl_is_paused(config, condition_id, template_arg, args): async def lvgl_is_idle(config, condition_id, template_arg, args): lvgl = config[CONF_LVGL_ID] timeout = await cg.templatable(config[CONF_TIMEOUT], [], cg.uint32) - with LambdaContext( - [(LvglComponentPtr, "lvgl_comp")], return_type=cg.bool_ - ) as context: + async with LambdaContext(LVGL_COMP_ARG, return_type=cg.bool_) as context: lv_add(ReturnStatement(lvgl_comp.is_idle(timeout))) var = cg.new_Pvariable(condition_id, template_arg, await context.get_lambda()) await cg.register_parented(var, lvgl) 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: + return + with LocalVariable("lv_disp_tmp", lv_disp_t, literal(disp)) as disp_temp: + if bg_color := config.get(CONF_DISP_BG_COLOR): + lv.disp_set_bg_color(disp_temp, await lv_color.process(bg_color)) + if bg_image := config.get(CONF_DISP_BG_IMAGE): + lv.disp_set_bg_image(disp_temp, await lv_image.process(bg_image)) + + @automation.register_action( "lvgl.widget.redraw", ObjUpdateAction, @@ -109,14 +126,32 @@ async def lvgl_is_idle(config, condition_id, template_arg, args): ), ) async def obj_invalidate_to_code(config, action_id, template_arg, args): - if CONF_ID in config: - w = await get_widget(config) - else: - w = lv_scr_act - with LambdaContext() as context: - add_line_marks(action_id) - lv_obj.invalidate(w.obj) - return await action_to_code(context.get_code(), action_id, w, template_arg, args) + widgets = await get_widgets(config) or [lv_scr_act] + + async def do_invalidate(widget: Widget): + lv_obj.invalidate(widget.obj) + + return await action_to_code(widgets, do_invalidate, action_id, template_arg, args) + + +@automation.register_action( + "lvgl.update", + LvglAction, + DISP_BG_SCHEMA.extend( + { + cv.GenerateID(): cv.use_id(LvglComponent), + } + ).add_extra(cv.has_at_least_one_key(CONF_DISP_BG_COLOR, CONF_DISP_BG_IMAGE)), +) +async def lvgl_update_to_code(config, action_id, template_arg, args): + widgets = await get_widgets(config) + w = widgets[0] + disp = f"{w.obj}->get_disp()" + async with LambdaContext(parameters=args, where=action_id) as context: + await disp_update(disp, config) + var = cg.new_Pvariable(action_id, template_arg, await context.get_lambda()) + await cg.register_parented(var, w.var) + return var @automation.register_action( @@ -128,8 +163,8 @@ async def obj_invalidate_to_code(config, action_id, template_arg, args): }, ) async def pause_action_to_code(config, action_id, template_arg, args): - with LambdaContext([(LvglComponentPtr, "lvgl_comp")]) as context: - add_line_marks(action_id) + async with LambdaContext(LVGL_COMP_ARG) as context: + add_line_marks(where=action_id) lv_add(lvgl_comp.set_paused(True, config[CONF_SHOW_SNOW])) var = cg.new_Pvariable(action_id, template_arg, await context.get_lambda()) await cg.register_parented(var, config[CONF_ID]) @@ -144,45 +179,48 @@ async def pause_action_to_code(config, action_id, template_arg, args): }, ) async def resume_action_to_code(config, action_id, template_arg, args): - with LambdaContext([(LvglComponentPtr, "lvgl_comp")]) as context: - add_line_marks(action_id) + async with LambdaContext(LVGL_COMP_ARG, where=action_id) as context: lv_add(lvgl_comp.set_paused(False, False)) var = cg.new_Pvariable(action_id, template_arg, await context.get_lambda()) await cg.register_parented(var, config[CONF_ID]) return var -@automation.register_action("lvgl.widget.disable", ObjUpdateAction, ACTION_SCHEMA) +@automation.register_action("lvgl.widget.disable", ObjUpdateAction, LIST_ACTION_SCHEMA) async def obj_disable_to_code(config, action_id, template_arg, args): - w = await get_widget(config) - with LambdaContext() as context: - add_line_marks(action_id) - w.add_state("LV_STATE_DISABLED") - return await action_to_code(context.get_code(), action_id, w, template_arg, args) + async def do_disable(widget: Widget): + widget.add_state(LV_STATE.DISABLED) + + return await action_to_code( + await get_widgets(config), do_disable, action_id, template_arg, args + ) -@automation.register_action("lvgl.widget.enable", ObjUpdateAction, ACTION_SCHEMA) +@automation.register_action("lvgl.widget.enable", ObjUpdateAction, LIST_ACTION_SCHEMA) async def obj_enable_to_code(config, action_id, template_arg, args): - w = await get_widget(config) - with LambdaContext() as context: - add_line_marks(action_id) - w.clear_state("LV_STATE_DISABLED") - return await action_to_code(context.get_code(), action_id, w, template_arg, args) + async def do_enable(widget: Widget): + widget.clear_state(LV_STATE.DISABLED) + + return await action_to_code( + await get_widgets(config), do_enable, action_id, template_arg, args + ) -@automation.register_action("lvgl.widget.hide", ObjUpdateAction, ACTION_SCHEMA) +@automation.register_action("lvgl.widget.hide", ObjUpdateAction, LIST_ACTION_SCHEMA) async def obj_hide_to_code(config, action_id, template_arg, args): - w = await get_widget(config) - with LambdaContext() as context: - add_line_marks(action_id) - w.add_flag("LV_OBJ_FLAG_HIDDEN") - return await action_to_code(context.get_code(), action_id, w, template_arg, args) + async def do_hide(widget: Widget): + widget.add_flag("LV_OBJ_FLAG_HIDDEN") + + return await action_to_code( + await get_widgets(config), do_hide, action_id, template_arg, args + ) -@automation.register_action("lvgl.widget.show", ObjUpdateAction, ACTION_SCHEMA) +@automation.register_action("lvgl.widget.show", ObjUpdateAction, LIST_ACTION_SCHEMA) async def obj_show_to_code(config, action_id, template_arg, args): - w = await get_widget(config) - with LambdaContext() as context: - add_line_marks(action_id) - w.clear_flag("LV_OBJ_FLAG_HIDDEN") - return await action_to_code(context.get_code(), action_id, w, template_arg, args) + async def do_show(widget: Widget): + widget.clear_flag("LV_OBJ_FLAG_HIDDEN") + + return await action_to_code( + await get_widgets(config), do_show, action_id, template_arg, args + ) diff --git a/esphome/components/lvgl/btn.py b/esphome/components/lvgl/btn.py index 064d886d47..2a2a53e1e2 100644 --- a/esphome/components/lvgl/btn.py +++ b/esphome/components/lvgl/btn.py @@ -1,19 +1,14 @@ from esphome.const import CONF_BUTTON -from esphome.cpp_generator import MockObjClass from .defines import CONF_MAIN from .types import LvBoolean, WidgetType +lv_btn_t = LvBoolean("lv_btn_t") + class BtnType(WidgetType): def __init__(self): - super().__init__(CONF_BUTTON, LvBoolean("lv_btn_t"), (CONF_MAIN,)) - - def obj_creator(self, parent: MockObjClass, config: dict): - """ - LVGL 8 calls buttons `btn` - """ - return f"lv_btn_create({parent})" + super().__init__(CONF_BUTTON, lv_btn_t, (CONF_MAIN,), lv_name="btn") def get_uses(self): return ("btn",) diff --git a/esphome/components/lvgl/checkbox.py b/esphome/components/lvgl/checkbox.py new file mode 100644 index 0000000000..7418d633cf --- /dev/null +++ b/esphome/components/lvgl/checkbox.py @@ -0,0 +1,25 @@ +from .defines import CONF_INDICATOR, CONF_MAIN, CONF_TEXT +from .lv_validation import lv_text +from .lvcode import lv +from .schemas import TEXT_SCHEMA +from .types import LvBoolean +from .widget import Widget, WidgetType + +CONF_CHECKBOX = "checkbox" + + +class CheckboxType(WidgetType): + def __init__(self): + super().__init__( + CONF_CHECKBOX, + LvBoolean("lv_checkbox_t"), + (CONF_MAIN, CONF_INDICATOR), + TEXT_SCHEMA, + ) + + async def to_code(self, w: Widget, config): + if value := config.get(CONF_TEXT): + lv.checkbox_set_text(w.obj, await lv_text.process(value)) + + +checkbox_spec = CheckboxType() diff --git a/esphome/components/lvgl/defines.py b/esphome/components/lvgl/defines.py index 9f349e3943..16ec45ae8a 100644 --- a/esphome/components/lvgl/defines.py +++ b/esphome/components/lvgl/defines.py @@ -4,31 +4,20 @@ Constants already defined in esphome.const are not duplicated here and must be i """ -from typing import Union - from esphome import codegen as cg, config_validation as cv from esphome.core import ID, Lambda -from esphome.cpp_generator import Literal +from esphome.cpp_generator import MockObj from esphome.cpp_types import uint32 from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor from .helpers import requires_component - -class ConstantLiteral(Literal): - __slots__ = ("constant",) - - def __init__(self, constant: str): - super().__init__() - self.constant = constant - - def __str__(self): - return self.constant +lvgl_ns = cg.esphome_ns.namespace("lvgl") -def literal(arg: Union[str, ConstantLiteral]): +def literal(arg): if isinstance(arg, str): - return ConstantLiteral(arg) + return MockObj(arg) return arg @@ -93,15 +82,23 @@ class LvConstant(LValidator): return self.prefix + cv.one_of(*choices, upper=True)(value) super().__init__(validator, rtype=uint32) + self.retmapper = self.mapper self.one_of = LValidator(validator, uint32, retmapper=self.mapper) self.several_of = LValidator( cv.ensure_list(self.one_of), uint32, retmapper=self.mapper ) def mapper(self, value, args=()): - if isinstance(value, list): - value = "|".join(value) - return ConstantLiteral(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() + ) def extend(self, *choices): """ @@ -112,9 +109,6 @@ class LvConstant(LValidator): return LvConstant(self.prefix, *(self.choices + choices)) -# Widgets -CONF_LABEL = "label" - # Parts CONF_MAIN = "main" CONF_SCROLLBAR = "scrollbar" @@ -123,10 +117,15 @@ CONF_KNOB = "knob" CONF_SELECTED = "selected" CONF_ITEMS = "items" CONF_TICKS = "ticks" -CONF_TICK_STYLE = "tick_style" CONF_CURSOR = "cursor" CONF_TEXTAREA_PLACEHOLDER = "textarea_placeholder" +# Layout types + +TYPE_FLEX = "flex" +TYPE_GRID = "grid" +TYPE_NONE = "none" + LV_FONTS = list(f"montserrat_{s}" for s in range(8, 50, 2)) + [ "dejavu_16_persian_hebrew", "simsun_16_cjk", @@ -134,7 +133,7 @@ LV_FONTS = list(f"montserrat_{s}" for s in range(8, 50, 2)) + [ "unscii_16", ] -LV_EVENT = { +LV_EVENT_MAP = { "PRESS": "PRESSED", "SHORT_CLICK": "SHORT_CLICKED", "LONG_PRESS": "LONG_PRESSED", @@ -150,7 +149,7 @@ LV_EVENT = { "CANCEL": "CANCEL", } -LV_EVENT_TRIGGERS = tuple(f"on_{x.lower()}" for x in LV_EVENT) +LV_EVENT_TRIGGERS = tuple(f"on_{x.lower()}" for x in LV_EVENT_MAP) LV_ANIM = LvConstant( @@ -305,7 +304,8 @@ OBJ_FLAGS = ( ARC_MODES = LvConstant("LV_ARC_MODE_", "NORMAL", "REVERSE", "SYMMETRICAL") BAR_MODES = LvConstant("LV_BAR_MODE_", "NORMAL", "SYMMETRICAL", "RANGE") -BTNMATRIX_CTRLS = ( +BTNMATRIX_CTRLS = LvConstant( + "LV_BTNMATRIX_CTRL_", "HIDDEN", "NO_REPEAT", "DISABLED", @@ -366,7 +366,6 @@ 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_ANTIALIAS = "antialias" @@ -384,8 +383,6 @@ 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_CONTROL = "control" CONF_DEFAULT = "default" CONF_DEFAULT_FONT = "default_font" @@ -414,9 +411,7 @@ CONF_GRID_ROW_ALIGN = "grid_row_align" CONF_GRID_ROWS = "grid_rows" CONF_HEADER_MODE = "header_mode" CONF_HOME = "home" -CONF_INDICATORS = "indicators" CONF_KEY_CODE = "key_code" -CONF_LABEL_GAP = "label_gap" CONF_LAYOUT = "layout" CONF_LEFT_BUTTON = "left_button" CONF_LINE_WIDTH = "line_width" @@ -425,7 +420,6 @@ 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 = "major" CONF_MSGBOXES = "msgboxes" CONF_OBJ = "obj" CONF_OFFSET_X = "offset_x" @@ -434,6 +428,7 @@ CONF_ONE_LINE = "one_line" CONF_ON_SELECT = "on_select" CONF_ONE_CHECKED = "one_checked" CONF_NEXT = "next" +CONF_PAGE = "page" CONF_PAGE_WRAP = "page_wrap" CONF_PASSWORD_MODE = "password_mode" CONF_PIVOT_X = "pivot_x" @@ -442,14 +437,12 @@ CONF_PLACEHOLDER_TEXT = "placeholder_text" CONF_POINTS = "points" CONF_PREVIOUS = "previous" CONF_REPEAT_COUNT = "repeat_count" -CONF_R_MOD = "r_mod" CONF_RECOLOR = "recolor" CONF_RIGHT_BUTTON = "right_button" CONF_ROLLOVER = "rollover" CONF_ROOT_BACK_BTN = "root_back_btn" CONF_ROTARY_ENCODERS = "rotary_encoders" CONF_ROWS = "rows" -CONF_SCALES = "scales" CONF_SCALE_LINES = "scale_lines" CONF_SCROLLBAR_MODE = "scrollbar_mode" CONF_SELECTED_INDEX = "selected_index" @@ -459,8 +452,9 @@ 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" CONF_STYLE_ID = "style_id" CONF_SKIP = "skip" CONF_SYMBOL = "symbol" @@ -505,4 +499,4 @@ DEFAULT_ESPHOME_FONT = "esphome_lv_default_font" def join_enums(enums, prefix=""): - return ConstantLiteral("|".join(f"(int){prefix}{e.upper()}" for e in enums)) + return literal("|".join(f"(int){prefix}{e.upper()}" for e in enums)) diff --git a/esphome/components/lvgl/helpers.py b/esphome/components/lvgl/helpers.py index d67739155c..e04a0105d5 100644 --- a/esphome/components/lvgl/helpers.py +++ b/esphome/components/lvgl/helpers.py @@ -1,10 +1,7 @@ import re from esphome import config_validation as cv -from esphome.config import Config from esphome.const import CONF_ARGS, CONF_FORMAT -from esphome.core import CORE, ID -from esphome.yaml_util import ESPHomeDataBase lv_uses = { "USER_DATA", @@ -44,23 +41,6 @@ def validate_printf(value): return value -def get_line_marks(value) -> list: - """ - If possible, return a preprocessor directive to identify the line number where the given id was defined. - :param id: The id in question - :return: A list containing zero or more line directives - """ - path = None - if isinstance(value, ESPHomeDataBase): - path = value.esp_range - elif isinstance(value, ID) and isinstance(CORE.config, Config): - path = CORE.config.get_path_for_id(value)[:-1] - path = CORE.config.get_deepest_document_range_for_path(path) - if path is None: - return [] - return [path.start_mark.as_line_directive] - - def requires_component(comp): def validator(value): lvgl_components_required.add(comp) diff --git a/esphome/components/lvgl/img.py b/esphome/components/lvgl/img.py new file mode 100644 index 0000000000..e9682def8c --- /dev/null +++ b/esphome/components/lvgl/img.py @@ -0,0 +1,85 @@ +import esphome.config_validation as cv +from esphome.const import CONF_ANGLE, CONF_MODE + +from .defines import ( + CONF_ANTIALIAS, + CONF_MAIN, + CONF_OFFSET_X, + CONF_OFFSET_Y, + CONF_PIVOT_X, + CONF_PIVOT_Y, + CONF_SRC, + CONF_ZOOM, + LvConstant, +) +from .label import CONF_LABEL +from .lv_validation import angle, lv_bool, lv_image, size, zoom +from .lvcode import lv +from .types import lv_img_t +from .widget import Widget, WidgetType + +CONF_IMAGE = "image" + +BASE_IMG_SCHEMA = cv.Schema( + { + cv.Optional(CONF_PIVOT_X, default="50%"): size, + cv.Optional(CONF_PIVOT_Y, default="50%"): size, + cv.Optional(CONF_ANGLE): angle, + cv.Optional(CONF_ZOOM): zoom, + 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, + } +) + +IMG_SCHEMA = BASE_IMG_SCHEMA.extend( + { + cv.Required(CONF_SRC): lv_image, + } +) + +IMG_MODIFY_SCHEMA = BASE_IMG_SCHEMA.extend( + { + cv.Optional(CONF_SRC): lv_image, + } +) + + +class ImgType(WidgetType): + def __init__(self): + super().__init__( + CONF_IMAGE, + lv_img_t, + (CONF_MAIN,), + IMG_SCHEMA, + IMG_MODIFY_SCHEMA, + lv_name="img", + ) + + def get_uses(self): + return "img", 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 cf_angle := config.get(CONF_ANGLE): + pivot_x = config[CONF_PIVOT_X] + pivot_y = config[CONF_PIVOT_Y] + lv.img_set_pivot(w.obj, pivot_x, pivot_y) + lv.img_set_angle(w.obj, cf_angle) + if img_zoom := config.get(CONF_ZOOM): + lv.img_set_zoom(w.obj, img_zoom) + if offset := config.get(CONF_OFFSET_X): + lv.img_set_offset_x(w.obj, offset) + if offset := config.get(CONF_OFFSET_Y): + lv.img_set_offset_y(w.obj, offset) + if CONF_ANTIALIAS in config: + lv.img_set_antialias(w.obj, config[CONF_ANTIALIAS]) + if mode := config.get(CONF_MODE): + lv.img_set_mode(w.obj, mode) + + +img_spec = ImgType() diff --git a/esphome/components/lvgl/label.py b/esphome/components/lvgl/label.py index 0498f39474..6c3e1f4a00 100644 --- a/esphome/components/lvgl/label.py +++ b/esphome/components/lvgl/label.py @@ -1,7 +1,6 @@ import esphome.config_validation as cv from .defines import ( - CONF_LABEL, CONF_LONG_MODE, CONF_MAIN, CONF_RECOLOR, @@ -15,6 +14,8 @@ from .schemas import TEXT_SCHEMA from .types import LvText, WidgetType from .widget import Widget +CONF_LABEL = "label" + class LabelType(WidgetType): def __init__(self): @@ -33,9 +34,9 @@ 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): - w.set_property(CONF_TEXT, await lv_text.process(value)) - w.set_property(CONF_LONG_MODE, config) - w.set_property(CONF_RECOLOR, config) + 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) label_spec = LabelType() diff --git a/esphome/components/lvgl/led.py b/esphome/components/lvgl/led.py new file mode 100644 index 0000000000..f920758efb --- /dev/null +++ b/esphome/components/lvgl/led.py @@ -0,0 +1,29 @@ +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 .lvcode import lv +from .types import LvType +from .widget import Widget, WidgetType + +LED_SCHEMA = cv.Schema( + { + cv.Optional(CONF_COLOR): lv_color, + cv.Optional(CONF_BRIGHTNESS): lv_brightness, + } +) + + +class LedType(WidgetType): + def __init__(self): + super().__init__(CONF_LED, LvType("lv_led_t"), (CONF_MAIN,), LED_SCHEMA) + + async def to_code(self, w: Widget, config): + if color := config.get(CONF_COLOR): + lv.led_set_color(w.obj, await lv_color.process(color)) + if brightness := config.get(CONF_BRIGHTNESS): + lv.led_set_brightness(w.obj, await lv_brightness.process(brightness)) + + +led_spec = LedType() diff --git a/esphome/components/lvgl/line.py b/esphome/components/lvgl/line.py new file mode 100644 index 0000000000..ab50832bbf --- /dev/null +++ b/esphome/components/lvgl/line.py @@ -0,0 +1,51 @@ +import functools + +import esphome.codegen as cg +import esphome.config_validation as cv + +from . import defines as df +from .defines import CONF_MAIN, literal +from .lvcode import lv +from .types import LvType +from .widget import Widget, WidgetType + +CONF_LINE = "line" +CONF_POINTS = "points" +CONF_POINT_LIST_ID = "point_list_id" + +lv_point_t = cg.global_ns.struct("lv_point_t") + + +def point_list(il): + il = cv.string(il) + nl = il.replace(" ", "").split(",") + return [int(n) for n in nl] + + +def cv_point_list(value): + if not isinstance(value, list): + raise cv.Invalid("List of points required") + values = [point_list(v) for v in value] + if not functools.reduce(lambda f, v: f and len(v) == 2, values, True): + raise cv.Invalid("Points must be a list of x,y integer pairs") + return values + + +LINE_SCHEMA = { + cv.Required(df.CONF_POINTS): cv_point_list, + cv.GenerateID(CONF_POINT_LIST_ID): cv.declare_id(lv_point_t), +} + + +class LineType(WidgetType): + def __init__(self): + super().__init__(CONF_LINE, LvType("lv_line_t"), (CONF_MAIN,), LINE_SCHEMA) + + async def to_code(self, w: Widget, config): + """For a line object, create and add the points""" + data = literal(config[CONF_POINTS]) + points = cg.static_const_array(config[CONF_POINT_LIST_ID], data) + lv.line_set_points(w.obj, points, len(data)) + + +line_spec = LineType() diff --git a/esphome/components/lvgl/lv_bar.py b/esphome/components/lvgl/lv_bar.py new file mode 100644 index 0000000000..d5dcff0bf0 --- /dev/null +++ b/esphome/components/lvgl/lv_bar.py @@ -0,0 +1,53 @@ +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_MAIN, literal +from .lv_validation import animated, get_start_value, lv_float +from .lvcode import lv +from .types import LvNumber, NumberType +from .widget import Widget + +CONF_BAR = "bar" +BAR_MODIFY_SCHEMA = cv.Schema( + { + cv.Optional(CONF_VALUE): lv_float, + cv.Optional(CONF_ANIMATED, default=True): animated, + } +) + +BAR_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_ANIMATED, default=True): animated, + } +) + + +class BarType(NumberType): + def __init__(self): + super().__init__( + CONF_BAR, + LvNumber("lv_bar_t"), + parts=(CONF_MAIN, CONF_INDICATOR), + schema=BAR_SCHEMA, + modify_schema=BAR_MODIFY_SCHEMA, + ) + + async def to_code(self, w: Widget, config): + var = w.obj + if CONF_MIN_VALUE in config: + lv.bar_set_range(var, config[CONF_MIN_VALUE], config[CONF_MAX_VALUE]) + lv.bar_set_mode(var, literal(config[CONF_MODE])) + value = await get_start_value(config) + if value is not None: + lv.bar_set_value(var, value, literal(config[CONF_ANIMATED])) + + @property + def animated(self): + return True + + +bar_spec = BarType() diff --git a/esphome/components/lvgl/lv_switch.py b/esphome/components/lvgl/lv_switch.py new file mode 100644 index 0000000000..5db2c2ce38 --- /dev/null +++ b/esphome/components/lvgl/lv_switch.py @@ -0,0 +1,20 @@ +from .defines import CONF_INDICATOR, CONF_KNOB, CONF_MAIN +from .types import LvBoolean +from .widget import WidgetType + +CONF_SWITCH = "switch" + + +class SwitchType(WidgetType): + def __init__(self): + super().__init__( + CONF_SWITCH, + LvBoolean("lv_switch_t"), + (CONF_MAIN, CONF_INDICATOR, CONF_KNOB), + ) + + async def to_code(self, w, config): + return [] + + +switch_spec = SwitchType() diff --git a/esphome/components/lvgl/lv_validation.py b/esphome/components/lvgl/lv_validation.py index 818bde6aed..b351b84af6 100644 --- a/esphome/components/lvgl/lv_validation.py +++ b/esphome/components/lvgl/lv_validation.py @@ -1,3 +1,5 @@ +from typing import Union + import esphome.codegen as cg from esphome.components.binary_sensor import BinarySensor from esphome.components.color import ColorStruct @@ -6,7 +8,7 @@ from esphome.components.image import Image_ from esphome.components.sensor import Sensor from esphome.components.text_sensor import TextSensor import esphome.config_validation as cv -from esphome.const import CONF_ARGS, CONF_COLOR, CONF_FORMAT +from esphome.const import CONF_ARGS, CONF_COLOR, CONF_FORMAT, CONF_VALUE from esphome.core import HexInt from esphome.cpp_generator import MockObj from esphome.cpp_types import uint32 @@ -14,7 +16,14 @@ from esphome.helpers import cpp_string_escape from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor from . import types as ty -from .defines import LV_FONTS, ConstantLiteral, LValidator, LvConstant, literal +from .defines import ( + CONF_END_VALUE, + CONF_START_VALUE, + LV_FONTS, + LValidator, + LvConstant, + literal, +) from .helpers import ( esphome_fonts_used, lv_fonts_used, @@ -60,6 +69,13 @@ def color_retmapper(value): return lv_expr.color_from(MockObj(value)) +def option_string(value): + value = cv.string(value).strip() + if value.find("\n") != -1: + raise cv.Invalid("Options strings must not contain newlines") + return value + + lv_color = LValidator(color, ty.lv_color_t, retmapper=color_retmapper) @@ -156,6 +172,12 @@ lv_bool = LValidator( ) +def lv_pct(value: Union[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" @@ -189,13 +211,16 @@ class TextValidator(LValidator): args = [str(x) for x in value[CONF_ARGS]] arg_expr = cg.RawExpression(",".join(args)) format_str = cpp_string_escape(value[CONF_FORMAT]) - return f"str_sprintf({format_str}, {arg_expr}).c_str()" + return literal(f"str_sprintf({format_str}, {arg_expr}).c_str()") return await super().process(value, args) lv_text = TextValidator() lv_float = LValidator(cv.float_, cg.float_, Sensor, "get_state()") lv_int = LValidator(cv.int_, cg.int_, Sensor, "get_state()") +lv_brightness = LValidator( + cv.percentage, cg.float_, Sensor, "get_state()", retmapper=lambda x: int(x * 255) +) def is_lv_font(font): @@ -222,8 +247,33 @@ class LvFont(LValidator): async def process(self, value, args=()): if is_lv_font(value): - return ConstantLiteral(f"&lv_font_{value}") - return ConstantLiteral(f"{value}_engine->get_lv_font()") + return literal(f"&lv_font_{value}") + return literal(f"{value}_engine->get_lv_font()") lv_font = LvFont() + + +def animated(value): + if isinstance(value, bool): + value = "ON" if value else "OFF" + return LvConstant("LV_ANIM_", "OFF", "ON").one_of(value) + + +def key_code(value): + value = cv.Any(cv.All(cv.string_strict, cv.Length(min=1, max=1)), cv.uint8_t)(value) + if isinstance(value, str): + return ord(value[0]) + return value + + +async def get_end_value(config): + return await lv_int.process(config.get(CONF_END_VALUE)) + + +async def get_start_value(config): + if CONF_START_VALUE in config: + value = config[CONF_START_VALUE] + else: + value = config.get(CONF_VALUE) + return await lv_int.process(value) diff --git a/esphome/components/lvgl/lvcode.py b/esphome/components/lvgl/lvcode.py index 3a8a958f2e..f54a032de2 100644 --- a/esphome/components/lvgl/lvcode.py +++ b/esphome/components/lvgl/lvcode.py @@ -1,9 +1,9 @@ import abc -import logging from typing import Union from esphome import codegen as cg -from esphome.core import ID, Lambda +from esphome.config import Config +from esphome.core import CORE, ID, Lambda from esphome.cpp_generator import ( AssignmentExpression, CallExpression, @@ -18,12 +18,47 @@ from esphome.cpp_generator import ( VariableDeclarationExpression, statement, ) +from esphome.yaml_util import ESPHomeDataBase -from .defines import ConstantLiteral -from .helpers import get_line_marks -from .types import lv_group_t +from .defines import literal, lvgl_ns -_LOGGER = logging.getLogger(__name__) +LVGL_COMP = "lv_component" # used as a lambda argument in lvgl_comp() + +# Argument tuple for use in lambdas +LvglComponent = lvgl_ns.class_("LvglComponent", cg.PollingComponent) +LVGL_COMP_ARG = [(LvglComponent.operator("ptr"), LVGL_COMP)] +lv_event_t_ptr = cg.global_ns.namespace("lv_event_t").operator("ptr") +EVENT_ARG = [(lv_event_t_ptr, "ev")] +CUSTOM_EVENT = literal("lvgl::lv_custom_event") + + +def get_line_marks(value) -> list: + """ + If possible, return a preprocessor directive to identify the line number where the given id was defined. + :param value: The id or other token to get the line number for + :return: A list containing zero or more line directives + """ + path = None + if isinstance(value, ESPHomeDataBase): + path = value.esp_range + elif isinstance(value, ID) and isinstance(CORE.config, Config): + path = CORE.config.get_path_for_id(value)[:-1] + path = CORE.config.get_deepest_document_range_for_path(path) + if path is None: + return [] + return [path.start_mark.as_line_directive] + + +class IndentedStatement(Statement): + def __init__(self, stmt: Statement, indent: int): + self.statement = stmt + self.indent = indent + + def __str__(self): + result = " " * self.indent * 4 + str(self.statement).strip() + if not isinstance(self.statement, RawStatement): + result += ";" + return result class CodeContext(abc.ABC): @@ -39,6 +74,16 @@ class CodeContext(abc.ABC): def add(self, expression: Union[Expression, Statement]): pass + @staticmethod + def start_block(): + CodeContext.append(RawStatement("{")) + CodeContext.code_context.indent() + + @staticmethod + def end_block(): + CodeContext.code_context.detent() + CodeContext.append(RawStatement("}")) + @staticmethod def append(expression: Union[Expression, Statement]): if CodeContext.code_context is not None: @@ -47,14 +92,25 @@ class CodeContext(abc.ABC): def __init__(self): self.previous: Union[CodeContext | None] = None + self.indent_level = 0 - def __enter__(self): + async def __aenter__(self): self.previous = CodeContext.code_context CodeContext.code_context = self + return self - def __exit__(self, *args): + async def __aexit__(self, *args): CodeContext.code_context = self.previous + def indent(self): + self.indent_level += 1 + + def detent(self): + self.indent_level -= 1 + + def indented_statement(self, stmt): + return IndentedStatement(stmt, self.indent_level) + class MainContext(CodeContext): """ @@ -62,42 +118,7 @@ class MainContext(CodeContext): """ def add(self, expression: Union[Expression, Statement]): - return cg.add(expression) - - -class LvContext(CodeContext): - """ - Code generation into the LVGL initialisation code (called in `setup()`) - """ - - lv_init_code: list["Statement"] = [] - - @staticmethod - def lv_add(expression: Union[Expression, Statement]): - if isinstance(expression, Expression): - expression = statement(expression) - if not isinstance(expression, Statement): - raise ValueError( - f"Add '{expression}' must be expression or statement, not {type(expression)}" - ) - LvContext.lv_init_code.append(expression) - _LOGGER.debug("LV Adding: %s", expression) - return expression - - @staticmethod - def get_code(): - code = [] - for exp in LvContext.lv_init_code: - text = str(statement(exp)) - text = text.rstrip() - code.append(text) - return "\n".join(code) + "\n\n" - - def add(self, expression: Union[Expression, Statement]): - return LvContext.lv_add(expression) - - def set_style(self, prop): - return MockObj("lv_set_style_{prop}", "") + return cg.add(self.indented_statement(expression)) class LambdaContext(CodeContext): @@ -110,21 +131,23 @@ class LambdaContext(CodeContext): parameters: list[tuple[SafeExpType, str]] = None, return_type: SafeExpType = cg.void, capture: str = "", + where=None, ): super().__init__() self.code_list: list[Statement] = [] - self.parameters = parameters + self.parameters = parameters or [] self.return_type = return_type self.capture = capture + self.where = where def add(self, expression: Union[Expression, Statement]): - self.code_list.append(expression) + self.code_list.append(self.indented_statement(expression)) return expression async def get_lambda(self) -> LambdaExpression: code_text = self.get_code() return await cg.process_lambda( - Lambda("\n".join(code_text) + "\n\n"), + Lambda("\n".join(code_text) + "\n"), self.parameters, capture=self.capture, return_type=self.return_type, @@ -138,33 +161,59 @@ class LambdaContext(CodeContext): code_text.append(text) return code_text - def __enter__(self): - super().__enter__() + async def __aenter__(self): + await super().__aenter__() + add_line_marks(self.where) return self +class LvContext(LambdaContext): + """ + Code generation into the LVGL initialisation code (called in `setup()`) + """ + + def __init__(self, lv_component, args=None): + self.args = args or LVGL_COMP_ARG + super().__init__(parameters=self.args) + self.lv_component = lv_component + + async def add_init_lambda(self): + cg.add(self.lv_component.add_init_lambda(await self.get_lambda())) + + async def __aexit__(self, exc_type, exc_val, exc_tb): + await super().__aexit__(exc_type, exc_val, exc_tb) + await self.add_init_lambda() + + def add(self, expression: Union[Expression, Statement]): + self.code_list.append(self.indented_statement(expression)) + return expression + + def __call__(self, *args): + return self.add(*args) + + class LocalVariable(MockObj): """ Create a local variable and enclose the code using it within a block. """ - def __init__(self, name, type, modifier=None, rhs=None): - base = ID(name, True, type) + def __init__(self, name, type, rhs=None, modifier="*"): + base = ID(name + "_VAR_", True, type) super().__init__(base, "") self.modifier = modifier self.rhs = rhs def __enter__(self): - CodeContext.append(RawStatement("{")) + CodeContext.start_block() CodeContext.append( VariableDeclarationExpression(self.base.type, self.modifier, self.base.id) ) if self.rhs is not None: CodeContext.append(AssignmentExpression(None, "", self.base, self.rhs)) - return self.base + return MockObj(self.base) def __exit__(self, *args): - CodeContext.append(RawStatement("}")) + CodeContext.end_block() class MockLv: @@ -199,14 +248,27 @@ class MockLv: self.append(result) return result - def cond_if(self, expression: Expression): - CodeContext.append(RawStatement(f"if {expression} {{")) - def cond_else(self): +class LvConditional: + def __init__(self, condition): + self.condition = condition + + def __enter__(self): + if self.condition is not None: + CodeContext.append(RawStatement(f"if ({self.condition}) {{")) + CodeContext.code_context.indent() + return self + + def __exit__(self, *args): + if self.condition is not None: + CodeContext.code_context.detent() + CodeContext.append(RawStatement("}")) + + def else_(self): + assert self.condition is not None + CodeContext.code_context.detent() CodeContext.append(RawStatement("} else {")) - - def cond_endif(self): - CodeContext.append(RawStatement("}")) + CodeContext.code_context.indent() class ReturnStatement(ExpressionStatement): @@ -228,36 +290,56 @@ lv = MockLv("lv_") lv_expr = LvExpr("lv_") # Mock for lv_obj_ calls lv_obj = MockLv("lv_obj_") -lvgl_comp = MockObj("lvgl_comp", "->") +# Operations on the LVGL component +lvgl_comp = MockObj(LVGL_COMP, "->") -# equivalent to cg.add() for the lvgl init context +# equivalent to cg.add() for the current code context def lv_add(expression: Union[Expression, Statement]): return CodeContext.append(expression) def add_line_marks(where): + """ + Add line marks for the current code context + :param where: An object to identify the source of the line marks + :return: + """ for mark in get_line_marks(where): lv_add(cg.RawStatement(mark)) def lv_assign(target, expression): - lv_add(RawExpression(f"{target} = {expression}")) + lv_add(AssignmentExpression("", "", target, expression)) -lv_groups = {} # Widget group names +def lv_Pvariable(type, name): + """ + Create but do not initialise a pointer variable + :param type: Type of the variable target + :param name: name of the variable, or an ID + :return: A MockObj of the variable + """ + if isinstance(name, str): + name = ID(name, True, type) + decl = VariableDeclarationExpression(type, "*", name) + CORE.add_global(decl) + var = MockObj(name, "->") + CORE.register_variable(name, var) + return var -def add_group(name): - if name is None: - return None - fullname = f"lv_esp_group_{name}" - if name not in lv_groups: - gid = ID(fullname, True, type=lv_group_t.operator("ptr")) - lv_add( - AssignmentExpression( - type_=gid.type, modifier="", name=fullname, rhs=lv_expr.group_create() - ) - ) - lv_groups[name] = ConstantLiteral(fullname) - return lv_groups[name] +def lv_variable(type, name): + """ + Create but do not initialise a variable + :param type: Type of the variable target + :param name: name of the variable, or an ID + :return: A MockObj of the variable + """ + if isinstance(name, str): + name = ID(name, True, type) + decl = VariableDeclarationExpression(type, "", name) + CORE.add_global(decl) + var = MockObj(name, ".") + CORE.register_variable(name, var) + return var diff --git a/esphome/components/lvgl/lvgl_esphome.cpp b/esphome/components/lvgl/lvgl_esphome.cpp index 34f8eaf21f..1221682d28 100644 --- a/esphome/components/lvgl/lvgl_esphome.cpp +++ b/esphome/components/lvgl/lvgl_esphome.cpp @@ -9,8 +9,72 @@ namespace esphome { namespace lvgl { static const char *const TAG = "lvgl"; +#if LV_USE_LOG +static void log_cb(const char *buf) { + esp_log_printf_(ESPHOME_LOG_LEVEL_INFO, TAG, 0, "%.*s", (int) strlen(buf) - 1, buf); +} +#endif // LV_USE_LOG + +static void rounder_cb(lv_disp_drv_t *disp_drv, lv_area_t *area) { + // make sure all coordinates are even + if (area->x1 & 1) + area->x1--; + if (!(area->x2 & 1)) + area->x2++; + if (area->y1 & 1) + area->y1--; + if (!(area->y2 & 1)) + area->y2++; +} + lv_event_code_t lv_custom_event; // NOLINT void LvglComponent::dump_config() { ESP_LOGCONFIG(TAG, "LVGL:"); } +void LvglComponent::set_paused(bool paused, bool show_snow) { + this->paused_ = paused; + this->show_snow_ = show_snow; + this->snow_line_ = 0; + if (!paused && lv_scr_act() != nullptr) { + lv_disp_trig_activity(this->disp_); // resets the inactivity time + lv_obj_invalidate(lv_scr_act()); + } +} +void LvglComponent::add_event_cb(lv_obj_t *obj, event_callback_t callback, lv_event_code_t event) { + lv_obj_add_event_cb(obj, callback, event, this); + if (event == LV_EVENT_VALUE_CHANGED) { + lv_obj_add_event_cb(obj, callback, lv_custom_event, this); + } +} +void LvglComponent::add_event_cb(lv_obj_t *obj, event_callback_t callback, lv_event_code_t event1, + lv_event_code_t event2) { + this->add_event_cb(obj, callback, event1); + this->add_event_cb(obj, callback, event2); +} +void LvglComponent::add_page(LvPageType *page) { + this->pages_.push_back(page); + page->setup(this->pages_.size() - 1); +} +void LvglComponent::show_page(size_t index, lv_scr_load_anim_t anim, uint32_t time) { + if (index >= this->pages_.size()) + return; + this->current_page_ = index; + 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) { + if (this->pages_.empty() || (this->current_page_ == this->pages_.size() - 1 && !this->page_wrap_)) + return; + do { + this->current_page_ = (this->current_page_ + 1) % this->pages_.size(); + } while (this->pages_[this->current_page_]->skip); // skip empty pages() + this->show_page(this->current_page_, anim, 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; + do { + this->current_page_ = (this->current_page_ + this->pages_.size() - 1) % this->pages_.size(); + } while (this->pages_[this->current_page_]->skip); // skip empty pages() + this->show_page(this->current_page_, anim, time); +} void LvglComponent::draw_buffer_(const lv_area_t *area, const uint8_t *ptr) { for (auto *display : this->displays_) { display->draw_pixels_at(area->x1, area->y1, lv_area_get_width(area), lv_area_get_height(area), ptr, @@ -27,6 +91,116 @@ void LvglComponent::flush_cb_(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv } lv_disp_flush_ready(disp_drv); } +IdleTrigger::IdleTrigger(LvglComponent *parent, TemplatableValue timeout) : timeout_(std::move(timeout)) { + parent->add_on_idle_callback([this](uint32_t idle_time) { + if (!this->is_idle_ && idle_time > this->timeout_.value()) { + this->is_idle_ = true; + this->trigger(); + } else if (this->is_idle_ && idle_time < this->timeout_.value()) { + this->is_idle_ = false; + } + }); +} + +#ifdef USE_LVGL_TOUCHSCREEN +LVTouchListener::LVTouchListener(uint16_t long_press_time, uint16_t long_press_repeat_time) { + lv_indev_drv_init(&this->drv_); + 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(d->user_data); + if (l->touch_pressed_) { + data->point.x = l->touch_point_.x; + data->point.y = l->touch_point_.y; + data->state = LV_INDEV_STATE_PRESSED; + } else { + data->state = LV_INDEV_STATE_RELEASED; + } + }; +} +void LVTouchListener::update(const touchscreen::TouchPoints_t &tpoints) { + this->touch_pressed_ = !this->parent_->is_paused() && !tpoints.empty(); + if (this->touch_pressed_) + this->touch_point_ = tpoints[0]; +} +#endif // USE_LVGL_TOUCHSCREEN + +#ifdef USE_LVGL_ROTARY_ENCODER +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(d->user_data); + 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_ROTARY_ENCODER + +#ifdef USE_LVGL_BUTTONMATRIX +void LvBtnmatrixType::set_obj(lv_obj_t *lv_obj) { + LvCompound::set_obj(lv_obj); + lv_obj_add_event_cb( + lv_obj, + [](lv_event_t *event) { + auto *self = static_cast(event->user_data); + if (self->key_callback_.size() == 0) + return; + auto key_idx = lv_btnmatrix_get_selected_btn(self->obj); + if (key_idx == LV_BTNMATRIX_BTN_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); + auto len = strlen(str); + while (len--) + self->send_key_(*str++); + }, + LV_EVENT_PRESSED, this); +} +#endif // USE_LVGL_BUTTONMATRIX + +#ifdef USE_LVGL_KEYBOARD +static const char *const KB_SPECIAL_KEYS[] = { + "abc", "ABC", "1#", + // maybe add other special keys here +}; + +void LvKeyboardType::set_obj(lv_obj_t *lv_obj) { + LvCompound::set_obj(lv_obj); + lv_obj_add_event_cb( + lv_obj, + [](lv_event_t *event) { + auto *self = static_cast(event->user_data); + if (self->key_callback_.size() == 0) + return; + + auto key_idx = lv_btnmatrix_get_selected_btn(self->obj); + if (key_idx == LV_BTNMATRIX_BTN_NONE) + return; + const char *txt = lv_btnmatrix_get_btn_text(self->obj, key_idx); + if (txt == nullptr) + return; + for (const auto *kb_special_key : KB_SPECIAL_KEYS) { + if (strcmp(txt, kb_special_key) == 0) + return; + } + while (*txt != 0) + self->send_key_(*txt++); + }, + LV_EVENT_PRESSED, this); +} +#endif // USE_LVGL_KEYBOARD void LvglComponent::write_random_() { // length of 2 lines in 32 bit units @@ -97,9 +271,24 @@ void LvglComponent::setup() { this->disp_ = lv_disp_drv_register(&this->disp_drv_); for (const auto &v : this->init_lambdas_) v(this); + this->show_page(0, LV_SCR_LOAD_ANIM_NONE, 0); lv_disp_trig_activity(this->disp_); ESP_LOGCONFIG(TAG, "LVGL Setup complete"); } +void LvglComponent::update() { + // update indicators + if (this->paused_) { + return; + } + this->idle_callbacks_.call(lv_disp_get_inactive_time(this->disp_)); +} +void LvglComponent::loop() { + if (this->paused_) { + if (this->show_snow_) + this->write_random_(); + } + lv_timer_handler_run_in_period(5); +} #ifdef USE_LVGL_IMAGE lv_img_dsc_t *lv_img_from(image::Image *src, lv_img_dsc_t *img_dsc) { @@ -142,7 +331,20 @@ lv_img_dsc_t *lv_img_from(image::Image *src, lv_img_dsc_t *img_dsc) { } return img_dsc; } +#endif // USE_LVGL_IMAGE + +#ifdef USE_LVGL_ANIMIMG +void lv_animimg_stop(lv_obj_t *obj) { + auto *animg = (lv_animimg_t *) obj; + int32_t duration = animg->anim.time; + 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(disp_drv->user_data)->flush_cb_(disp_drv, area, color_p); +} } // namespace lvgl } // namespace esphome diff --git a/esphome/components/lvgl/lvgl_esphome.h b/esphome/components/lvgl/lvgl_esphome.h index a0d3d226ce..b92799addd 100644 --- a/esphome/components/lvgl/lvgl_esphome.h +++ b/esphome/components/lvgl/lvgl_esphome.h @@ -18,7 +18,6 @@ #include "esphome/core/component.h" #include "esphome/core/log.h" #include -#include #include #ifdef USE_LVGL_IMAGE #include "esphome/components/image/image.h" @@ -31,6 +30,10 @@ #include "esphome/components/touchscreen/touchscreen.h" #endif // USE_LVGL_TOUCHSCREEN +#if defined(USE_LVGL_BUTTONMATRIX) || defined(USE_LVGL_KEYBOARD) +#include "esphome/components/key_provider/key_provider.h" +#endif // USE_LVGL_BUTTONMATRIX + namespace esphome { namespace lvgl { @@ -47,12 +50,25 @@ static const display::ColorBitness LV_BITNESS = display::ColorBitness::COLOR_BIT #endif // LV_COLOR_DEPTH // Parent class for things that wrap an LVGL object -class LvCompound final { +class LvCompound { public: - void set_obj(lv_obj_t *lv_obj) { this->obj = lv_obj; } + virtual void set_obj(lv_obj_t *lv_obj) { this->obj = lv_obj; } lv_obj_t *obj{}; }; +class LvPageType { + public: + LvPageType(bool skip) : skip(skip) {} + + void setup(size_t index) { + this->index = index; + this->obj = lv_obj_create(nullptr); + } + lv_obj_t *obj{}; + size_t index{}; + bool skip; +}; + using LvLambdaType = std::function; using set_value_lambda_t = std::function; using event_callback_t = void(_lv_event_t *); @@ -89,48 +105,20 @@ class FontEngine { lv_img_dsc_t *lv_img_from(image::Image *src, lv_img_dsc_t *img_dsc = nullptr); #endif // USE_LVGL_IMAGE +#ifdef USE_LVGL_ANIMIMG +void lv_animimg_stop(lv_obj_t *obj); +#endif // USE_LVGL_ANIMIMG + class LvglComponent : public PollingComponent { constexpr static const char *const TAG = "lvgl"; public: - static void static_flush_cb(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p) { - reinterpret_cast(disp_drv->user_data)->flush_cb_(disp_drv, area, color_p); - } + static void static_flush_cb(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p); float get_setup_priority() const override { return setup_priority::PROCESSOR; } - static void log_cb(const char *buf) { - esp_log_printf_(ESPHOME_LOG_LEVEL_INFO, TAG, 0, "%.*s", (int) strlen(buf) - 1, buf); - } - static void rounder_cb(lv_disp_drv_t *disp_drv, lv_area_t *area) { - // make sure all coordinates are even - if (area->x1 & 1) - area->x1--; - if (!(area->x2 & 1)) - area->x2++; - if (area->y1 & 1) - area->y1--; - if (!(area->y2 & 1)) - area->y2++; - } - void setup() override; - - void update() override { - // update indicators - if (this->paused_) { - return; - } - this->idle_callbacks_.call(lv_disp_get_inactive_time(this->disp_)); - } - - void loop() override { - if (this->paused_) { - if (this->show_snow_) - this->write_random_(); - } - lv_timer_handler_run_in_period(5); - } - + void update() override; + void loop() override; void add_on_idle_callback(std::function &&callback) { this->idle_callbacks_.add(std::move(callback)); } @@ -141,23 +129,15 @@ class LvglComponent : public PollingComponent { bool is_idle(uint32_t idle_ms) { return lv_disp_get_inactive_time(this->disp_) > idle_ms; } void set_buffer_frac(size_t frac) { this->buffer_frac_ = frac; } lv_disp_t *get_disp() { return this->disp_; } - void set_paused(bool paused, bool show_snow) { - this->paused_ = paused; - this->show_snow_ = show_snow; - this->snow_line_ = 0; - if (!paused && lv_scr_act() != nullptr) { - lv_disp_trig_activity(this->disp_); // resets the inactivity time - lv_obj_invalidate(lv_scr_act()); - } - } - - void add_event_cb(lv_obj_t *obj, event_callback_t callback, lv_event_code_t event) { - lv_obj_add_event_cb(obj, callback, event, this); - if (event == LV_EVENT_VALUE_CHANGED) { - lv_obj_add_event_cb(obj, callback, lv_custom_event, this); - } - } + void set_paused(bool paused, bool show_snow); + void add_event_cb(lv_obj_t *obj, event_callback_t callback, lv_event_code_t event); + void add_event_cb(lv_obj_t *obj, event_callback_t callback, lv_event_code_t event1, lv_event_code_t event2); bool is_paused() const { return this->paused_; } + 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; } protected: void write_random_(); @@ -168,8 +148,11 @@ class LvglComponent : public PollingComponent { lv_disp_drv_t disp_drv_{}; lv_disp_t *disp_{}; bool paused_{}; + std::vector pages_{}; + size_t current_page_{0}; bool show_snow_{}; lv_coord_t snow_line_{}; + bool page_wrap_{true}; std::vector> init_lambdas_; CallbackManager idle_callbacks_{}; @@ -179,16 +162,7 @@ class LvglComponent : public PollingComponent { class IdleTrigger : public Trigger<> { public: - explicit IdleTrigger(LvglComponent *parent, TemplatableValue timeout) : timeout_(std::move(timeout)) { - parent->add_on_idle_callback([this](uint32_t idle_time) { - if (!this->is_idle_ && idle_time > this->timeout_.value()) { - this->is_idle_ = true; - this->trigger(); - } else if (this->is_idle_ && idle_time < this->timeout_.value()) { - this->is_idle_ = false; - } - }); - } + explicit IdleTrigger(LvglComponent *parent, TemplatableValue timeout); protected: TemplatableValue timeout_; @@ -217,28 +191,8 @@ template class LvglCondition : public Condition, public P #ifdef USE_LVGL_TOUCHSCREEN class LVTouchListener : public touchscreen::TouchListener, public Parented { public: - LVTouchListener(uint16_t long_press_time, uint16_t long_press_repeat_time) { - lv_indev_drv_init(&this->drv_); - 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(d->user_data); - if (l->touch_pressed_) { - data->point.x = l->touch_point_.x; - data->point.y = l->touch_point_.y; - data->state = LV_INDEV_STATE_PRESSED; - } else { - data->state = LV_INDEV_STATE_RELEASED; - } - }; - } - void update(const touchscreen::TouchPoints_t &tpoints) override { - this->touch_pressed_ = !this->parent_->is_paused() && !tpoints.empty(); - if (this->touch_pressed_) - this->touch_point_ = tpoints[0]; - } + LVTouchListener(uint16_t long_press_time, uint16_t long_press_repeat_time); + void update(const touchscreen::TouchPoints_t &tpoints) override; void release() override { touch_pressed_ = false; } lv_indev_drv_t *get_drv() { return &this->drv_; } @@ -249,24 +203,10 @@ class LVTouchListener : public touchscreen::TouchListener, public Parented { public: - 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(d->user_data); - 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; - }; - } + LVEncoderListener(lv_indev_type_t type, uint16_t lpt, uint16_t lprt); void set_left_button(binary_sensor::BinarySensor *left_button) { left_button->add_on_state_callback([this](bool state) { this->event(LV_KEY_LEFT, state); }); @@ -304,6 +244,24 @@ class LVEncoderListener : public Parented { int32_t last_count_{}; int key_{}; }; -#endif // USE_LVGL_KEY_LISTENER +#endif // USE_LVGL_ROTARY_ENCODER +#ifdef USE_LVGL_BUTTONMATRIX +class LvBtnmatrixType : 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); } + void set_key(size_t idx, uint8_t key) { this->key_map_[idx] = key; } + + protected: + std::map key_map_{}; +}; +#endif // USE_LVGL_BUTTONMATRIX + +#ifdef USE_LVGL_KEYBOARD +class LvKeyboardType : public key_provider::KeyProvider, public LvCompound { + public: + void set_obj(lv_obj_t *lv_obj) override; +}; +#endif // USE_LVGL_KEYBOARD } // namespace lvgl } // namespace esphome diff --git a/esphome/components/lvgl/page.py b/esphome/components/lvgl/page.py new file mode 100644 index 0000000000..4566b7eea4 --- /dev/null +++ b/esphome/components/lvgl/page.py @@ -0,0 +1,113 @@ +from esphome import automation, codegen as cg +import esphome.config_validation as cv +from esphome.const import CONF_ID, CONF_PAGES, CONF_TIME + +from .defines import ( + CONF_ANIMATION, + CONF_LVGL_ID, + CONF_PAGE, + CONF_PAGE_WRAP, + CONF_SKIP, + LV_ANIM, +) +from .lv_validation import lv_bool, lv_milliseconds +from .lvcode import LVGL_COMP_ARG, LambdaContext, add_line_marks, lv_add, lvgl_comp +from .schemas import LVGL_SCHEMA +from .types import LvglAction, lv_page_t +from .widget import Widget, WidgetType, add_widgets, set_obj_properties + + +class PageType(WidgetType): + def __init__(self): + super().__init__( + CONF_PAGE, + lv_page_t, + (), + { + cv.Optional(CONF_SKIP, default=False): lv_bool, + }, + ) + + async def to_code(self, w: Widget, config: dict): + return [] + + +SHOW_SCHEMA = LVGL_SCHEMA.extend( + { + cv.Optional(CONF_ANIMATION, default="NONE"): LV_ANIM.one_of, + cv.Optional(CONF_TIME, default="50ms"): lv_milliseconds, + } +) + + +page_spec = PageType() + + +@automation.register_action( + "lvgl.page.next", + LvglAction, + SHOW_SCHEMA, +) +async def page_next_to_code(config, action_id, template_arg, args): + animation = await LV_ANIM.process(config[CONF_ANIMATION]) + time = await lv_milliseconds.process(config[CONF_TIME]) + async with LambdaContext(LVGL_COMP_ARG) as context: + add_line_marks(action_id) + lv_add(lvgl_comp.show_next_page(animation, time)) + var = cg.new_Pvariable(action_id, template_arg, await context.get_lambda()) + await cg.register_parented(var, config[CONF_LVGL_ID]) + return var + + +@automation.register_action( + "lvgl.page.previous", + LvglAction, + SHOW_SCHEMA, +) +async def page_previous_to_code(config, action_id, template_arg, args): + animation = await LV_ANIM.process(config[CONF_ANIMATION]) + time = await lv_milliseconds.process(config[CONF_TIME]) + async with LambdaContext(LVGL_COMP_ARG) as context: + add_line_marks(action_id) + lv_add(lvgl_comp.show_prev_page(animation, time)) + var = cg.new_Pvariable(action_id, template_arg, await context.get_lambda()) + await cg.register_parented(var, config[CONF_LVGL_ID]) + return var + + +@automation.register_action( + "lvgl.page.show", + LvglAction, + cv.maybe_simple_value( + SHOW_SCHEMA.extend( + { + cv.Required(CONF_ID): cv.use_id(lv_page_t), + } + ), + key=CONF_ID, + ), +) +async def page_show_to_code(config, action_id, template_arg, args): + widget = await cg.get_variable(config[CONF_ID]) + animation = await LV_ANIM.process(config[CONF_ANIMATION]) + time = await lv_milliseconds.process(config[CONF_TIME]) + async with LambdaContext(LVGL_COMP_ARG) as context: + add_line_marks(action_id) + lv_add(lvgl_comp.show_page(widget.index, animation, time)) + var = cg.new_Pvariable(action_id, template_arg, await context.get_lambda()) + await cg.register_parented(var, config[CONF_LVGL_ID]) + return var + + +async def add_pages(lv_component, config): + lv_add(lv_component.set_page_wrap(config[CONF_PAGE_WRAP])) + for pconf in config.get(CONF_PAGES, ()): + id = pconf[CONF_ID] + skip = pconf[CONF_SKIP] + var = cg.new_Pvariable(id, skip) + page = Widget.create(id, var, page_spec, pconf) + lv_add(lv_component.add_page(var)) + # Set outer config first + await set_obj_properties(page, config) + await set_obj_properties(page, pconf) + await add_widgets(page, pconf) diff --git a/esphome/components/lvgl/rotary_encoders.py b/esphome/components/lvgl/rotary_encoders.py index 77dc397c3e..ede6905a67 100644 --- a/esphome/components/lvgl/rotary_encoders.py +++ b/esphome/components/lvgl/rotary_encoders.py @@ -13,9 +13,10 @@ from .defines import ( CONF_ROTARY_ENCODERS, ) from .helpers import lvgl_components_required -from .lvcode import add_group, lv, lv_add, lv_expr +from .lvcode import lv, lv_add, lv_expr from .schemas import ENCODER_SCHEMA from .types import lv_indev_type_t +from .widget import add_group ROTARY_ENCODER_CONFIG = cv.ensure_list( ENCODER_SCHEMA.extend( diff --git a/esphome/components/lvgl/schemas.py b/esphome/components/lvgl/schemas.py index ebef56a882..796783890d 100644 --- a/esphome/components/lvgl/schemas.py +++ b/esphome/components/lvgl/schemas.py @@ -15,8 +15,12 @@ from esphome.schema_extractors import SCHEMA_EXTRACT from . import defines as df, lv_validation as lvalid, types as ty from .helpers import add_lv_use, requires_component, validate_printf -from .lv_validation import id_name, lv_font -from .types import WIDGET_TYPES, WidgetType +from .lv_validation import id_name, lv_color, lv_font, lv_image +from .lvcode import LvglComponent +from .types import WidgetType + +# this will be populated later, in __init__.py to avoid circular imports. +WIDGET_TYPES: dict = {} # A schema for text properties TEXT_SCHEMA = cv.Schema( @@ -38,11 +42,13 @@ TEXT_SCHEMA = cv.Schema( } ) -ACTION_SCHEMA = cv.maybe_simple_value( - { - cv.Required(CONF_ID): cv.use_id(ty.lv_pseudo_button_t), - }, - key=CONF_ID, +LIST_ACTION_SCHEMA = cv.ensure_list( + cv.maybe_simple_value( + { + cv.Required(CONF_ID): cv.use_id(ty.lv_pseudo_button_t), + }, + key=CONF_ID, + ) ) PRESS_TIME = cv.All( @@ -154,6 +160,7 @@ STYLE_REMAP = { # Complete object style schema STYLE_SCHEMA = cv.Schema({cv.Optional(k): v for k, v in STYLE_PROPS.items()}).extend( { + cv.Optional(df.CONF_STYLES): cv.ensure_list(cv.use_id(ty.lv_style_t)), cv.Optional(df.CONF_SCROLLBAR_MODE): df.LvConstant( "LV_SCROLLBAR_MODE_", "OFF", "ON", "ACTIVE", "AUTO" ).one_of, @@ -209,7 +216,14 @@ def create_modify_schema(widget_type): part_schema(widget_type) .extend( { - cv.Required(CONF_ID): cv.use_id(widget_type), + cv.Required(CONF_ID): cv.ensure_list( + cv.maybe_simple_value( + { + cv.Required(CONF_ID): cv.use_id(widget_type), + }, + key=CONF_ID, + ) + ), cv.Optional(CONF_STATE): SET_STATE_SCHEMA, } ) @@ -227,6 +241,7 @@ def obj_schema(widget_type: WidgetType): return ( part_schema(widget_type) .extend(FLAG_SCHEMA) + .extend(LAYOUT_SCHEMA) .extend(ALIGN_TO_SCHEMA) .extend(automation_schema(widget_type.w_type)) .extend( @@ -240,6 +255,8 @@ def obj_schema(widget_type: WidgetType): ) +LAYOUT_SCHEMAS = {} + ALIGN_TO_SCHEMA = { cv.Optional(df.CONF_ALIGN_TO): cv.Schema( { @@ -252,6 +269,65 @@ ALIGN_TO_SCHEMA = { } +def grid_free_space(value): + value = cv.Upper(value) + if value.startswith("FR(") and value.endswith(")"): + value = value.removesuffix(")").removeprefix("FR(") + return f"LV_GRID_FR({cv.positive_int(value)})" + raise cv.Invalid("must be a size in pixels, CONTENT or FR(nn)") + + +grid_spec = cv.Any( + lvalid.size, df.LvConstant("LV_GRID_", "CONTENT").one_of, grid_free_space +) + +cell_alignments = df.LV_CELL_ALIGNMENTS.one_of +grid_alignments = df.LV_GRID_ALIGNMENTS.one_of +flex_alignments = df.LV_FLEX_ALIGNMENTS.one_of + +LAYOUT_SCHEMA = { + cv.Optional(df.CONF_LAYOUT): cv.typed_schema( + { + df.TYPE_GRID: { + cv.Required(df.CONF_GRID_ROWS): [grid_spec], + cv.Required(df.CONF_GRID_COLUMNS): [grid_spec], + cv.Optional(df.CONF_GRID_COLUMN_ALIGN): grid_alignments, + cv.Optional(df.CONF_GRID_ROW_ALIGN): grid_alignments, + }, + df.TYPE_FLEX: { + cv.Optional( + df.CONF_FLEX_FLOW, default="row_wrap" + ): df.FLEX_FLOWS.one_of, + cv.Optional(df.CONF_FLEX_ALIGN_MAIN, default="start"): flex_alignments, + cv.Optional(df.CONF_FLEX_ALIGN_CROSS, default="start"): flex_alignments, + cv.Optional(df.CONF_FLEX_ALIGN_TRACK, default="start"): flex_alignments, + }, + }, + lower=True, + ) +} + +GRID_CELL_SCHEMA = { + cv.Required(df.CONF_GRID_CELL_ROW_POS): cv.positive_int, + cv.Required(df.CONF_GRID_CELL_COLUMN_POS): cv.positive_int, + cv.Optional(df.CONF_GRID_CELL_ROW_SPAN, default=1): cv.positive_int, + cv.Optional(df.CONF_GRID_CELL_COLUMN_SPAN, default=1): cv.positive_int, + cv.Optional(df.CONF_GRID_CELL_X_ALIGN): grid_alignments, + cv.Optional(df.CONF_GRID_CELL_Y_ALIGN): grid_alignments, +} + +FLEX_OBJ_SCHEMA = { + cv.Optional(df.CONF_FLEX_GROW): cv.int_, +} + +DISP_BG_SCHEMA = cv.Schema( + { + cv.Optional(df.CONF_DISP_BG_IMAGE): lv_image, + cv.Optional(df.CONF_DISP_BG_COLOR): lv_color, + } +) + + # A style schema that can include text STYLED_TEXT_SCHEMA = cv.maybe_simple_value( STYLE_SCHEMA.extend(TEXT_SCHEMA), key=df.CONF_TEXT @@ -260,13 +336,11 @@ STYLED_TEXT_SCHEMA = cv.maybe_simple_value( # For use by platform components LVGL_SCHEMA = cv.Schema( { - cv.GenerateID(df.CONF_LVGL_ID): cv.use_id(ty.LvglComponent), + cv.GenerateID(df.CONF_LVGL_ID): cv.use_id(LvglComponent), } ) -ALL_STYLES = { - **STYLE_PROPS, -} +ALL_STYLES = {**STYLE_PROPS, **GRID_CELL_SCHEMA, **FLEX_OBJ_SCHEMA} def container_validator(schema, widget_type: WidgetType): @@ -281,16 +355,17 @@ def container_validator(schema, widget_type: WidgetType): result = schema if w_sch := widget_type.schema: result = result.extend(w_sch) + ltype = df.TYPE_NONE if value and (layout := value.get(df.CONF_LAYOUT)): if not isinstance(layout, dict): raise cv.Invalid("Layout value must be a dict") ltype = layout.get(CONF_TYPE) + if not ltype: + raise (cv.Invalid("Layout schema requires type:")) add_lv_use(ltype) - result = result.extend( - {cv.Optional(df.CONF_WIDGETS): cv.ensure_list(any_widget_schema())} - ) if value == SCHEMA_EXTRACT: return result + result = result.extend(LAYOUT_SCHEMAS[ltype.lower()]) return result(value) return validator diff --git a/esphome/components/lvgl/slider.py b/esphome/components/lvgl/slider.py new file mode 100644 index 0000000000..1886f79b44 --- /dev/null +++ b/esphome/components/lvgl/slider.py @@ -0,0 +1,63 @@ +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, + literal, +) +from .helpers import add_lv_use +from .lv_bar import CONF_BAR +from .lv_validation import animated, get_start_value, lv_float +from .lvcode import lv +from .types import LvNumber, NumberType +from .widget import Widget + +CONF_SLIDER = "slider" +SLIDER_MODIFY_SCHEMA = cv.Schema( + { + cv.Optional(CONF_VALUE): lv_float, + cv.Optional(CONF_ANIMATED, default=True): animated, + } +) + +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_ANIMATED, default=True): animated, + } +) + + +class SliderType(NumberType): + def __init__(self): + super().__init__( + CONF_SLIDER, + LvNumber("lv_slider_t"), + parts=(CONF_MAIN, CONF_INDICATOR, CONF_KNOB), + schema=SLIDER_SCHEMA, + modify_schema=SLIDER_MODIFY_SCHEMA, + ) + + @property + def animated(self): + return True + + 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]) + lv.slider_set_mode(w.obj, literal(config[CONF_MODE])) + value = await get_start_value(config) + if value is not None: + lv.slider_set_value(w.obj, value, literal(config[CONF_ANIMATED])) + + +slider_spec = SliderType() diff --git a/esphome/components/lvgl/spinner.py b/esphome/components/lvgl/spinner.py new file mode 100644 index 0000000000..2f798d0fbf --- /dev/null +++ b/esphome/components/lvgl/spinner.py @@ -0,0 +1,43 @@ +import esphome.config_validation as cv +from esphome.cpp_generator import MockObjClass + +from .arc import CONF_ARC +from .defines import CONF_ARC_LENGTH, CONF_INDICATOR, CONF_MAIN, CONF_SPIN_TIME +from .lv_validation import angle +from .lvcode import lv_expr +from .types import LvType +from .widget import Widget, WidgetType + +CONF_SPINNER = "spinner" + +SPINNER_SCHEMA = cv.Schema( + { + cv.Required(CONF_ARC_LENGTH): angle, + cv.Required(CONF_SPIN_TIME): cv.positive_time_period_milliseconds, + } +) + + +class SpinnerType(WidgetType): + def __init__(self): + super().__init__( + CONF_SPINNER, + LvType("lv_spinner_t"), + (CONF_MAIN, CONF_INDICATOR), + SPINNER_SCHEMA, + {}, + ) + + async def to_code(self, w: Widget, config): + return [] + + def get_uses(self): + return (CONF_ARC,) + + def obj_creator(self, parent: MockObjClass, config: dict): + spin_time = config[CONF_SPIN_TIME].total_milliseconds + arc_length = config[CONF_ARC_LENGTH] // 10 + return lv_expr.call("spinner_create", parent, spin_time, arc_length) + + +spinner_spec = SpinnerType() diff --git a/esphome/components/lvgl/styles.py b/esphome/components/lvgl/styles.py new file mode 100644 index 0000000000..7a795bc99d --- /dev/null +++ b/esphome/components/lvgl/styles.py @@ -0,0 +1,58 @@ +import esphome.codegen as cg +from esphome.const import CONF_ID +from esphome.core import ID +from esphome.cpp_generator import MockObj + +from .defines import ( + CONF_STYLE_DEFINITIONS, + CONF_THEME, + CONF_TOP_LAYER, + LValidator, + literal, +) +from .helpers import add_lv_use +from .lvcode import LambdaContext, LocalVariable, lv, lv_assign, lv_variable +from .obj import obj_spec +from .schemas import ALL_STYLES +from .types import lv_lambda_t, lv_obj_t, lv_obj_t_ptr +from .widget import Widget, add_widgets, set_obj_properties, theme_widget_map + +TOP_LAYER = literal("lv_disp_get_layer_top(lv_component->get_disp())") + + +async def styles_to_code(config): + """Convert styles to C__ code.""" + for style in config.get(CONF_STYLE_DEFINITIONS, ()): + svar = cg.new_Pvariable(style[CONF_ID]) + lv.style_init(svar) + for prop, validator in ALL_STYLES.items(): + if value := style.get(prop): + if isinstance(validator, LValidator): + value = await validator.process(value) + if isinstance(value, list): + value = "|".join(value) + lv.call(f"style_set_{prop}", svar, literal(value)) + + +async def theme_to_code(config): + if theme := config.get(CONF_THEME): + add_lv_use(CONF_THEME) + for w_name, style in theme.items(): + if not isinstance(style, dict): + continue + + lname = "lv_theme_apply_" + w_name + apply = lv_variable(lv_lambda_t, lname) + theme_widget_map[w_name] = apply + ow = Widget.create("obj", MockObj(ID("obj")), obj_spec) + async with LambdaContext([(lv_obj_t_ptr, "obj")], where=w_name) as context: + await set_obj_properties(ow, style) + lv_assign(apply, await context.get_lambda()) + + +async def add_top_layer(config): + 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/trigger.py b/esphome/components/lvgl/trigger.py index bf92bda5b0..c640c8abd9 100644 --- a/esphome/components/lvgl/trigger.py +++ b/esphome/components/lvgl/trigger.py @@ -7,15 +7,14 @@ from .defines import ( CONF_ALIGN_TO, CONF_X, CONF_Y, - LV_EVENT, + LV_EVENT_MAP, LV_EVENT_TRIGGERS, literal, ) -from .lvcode import LambdaContext, add_line_marks, lv, lv_add +from .lvcode import EVENT_ARG, LambdaContext, LvConditional, lv, lv_add +from .types import LV_EVENT from .widget import widget_map -lv_event_t_ptr = cg.global_ns.namespace("lv_event_t").operator("ptr") - async def generate_triggers(lv_component): """ @@ -34,15 +33,15 @@ async def generate_triggers(lv_component): }.items(): conf = conf[0] w.add_flag("LV_OBJ_FLAG_CLICKABLE") - event = "LV_EVENT_" + LV_EVENT[event[3:].upper()] + event = literal("LV_EVENT_" + LV_EVENT_MAP[event[3:].upper()]) await add_trigger(conf, event, lv_component, w) for conf in w.config.get(CONF_ON_VALUE, ()): - await add_trigger(conf, "LV_EVENT_VALUE_CHANGED", lv_component, w) + await add_trigger(conf, LV_EVENT.VALUE_CHANGED, lv_component, w) # Generate align to directives while we're here if align_to := w.config.get(CONF_ALIGN_TO): target = widget_map[align_to[CONF_ID]].obj - align = align_to[CONF_ALIGN] + 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) @@ -50,12 +49,11 @@ async def generate_triggers(lv_component): async def add_trigger(conf, event, lv_component, w): tid = conf[CONF_TRIGGER_ID] - add_line_marks(tid) trigger = cg.new_Pvariable(tid) args = w.get_args() value = w.get_value() await automation.build_automation(trigger, args, conf) - with LambdaContext([(lv_event_t_ptr, "event_data")]) as context: - add_line_marks(tid) - lv_add(trigger.trigger(value)) - lv_add(lv_component.add_event_cb(w.obj, await context.get_lambda(), literal(event))) + async with LambdaContext(EVENT_ARG, where=tid) as context: + with LvConditional(w.is_selected()): + lv_add(trigger.trigger(value)) + lv_add(lv_component.add_event_cb(w.obj, await context.get_lambda(), event)) diff --git a/esphome/components/lvgl/types.py b/esphome/components/lvgl/types.py index 6997207dac..b6f65c8c1b 100644 --- a/esphome/components/lvgl/types.py +++ b/esphome/components/lvgl/types.py @@ -1,8 +1,11 @@ -from esphome import automation, codegen as cg -from esphome.core import ID -from esphome.cpp_generator import MockObjClass +import sys -from .defines import CONF_TEXT +from esphome import automation, codegen as cg +from esphome.const import CONF_MAX_VALUE, CONF_MIN_VALUE, CONF_VALUE +from esphome.cpp_generator import MockObj, MockObjClass + +from .defines import CONF_TEXT, lvgl_ns +from .lvcode import lv_expr class LvType(cg.MockObjClass): @@ -18,36 +21,48 @@ class LvType(cg.MockObjClass): return self.args[0][0] if len(self.args) else None +class LvNumber(LvType): + def __init__(self, *args): + super().__init__( + *args, + largs=[(cg.float_, "x")], + lvalue=lambda w: w.get_number_value(), + has_on_value=True, + ) + self.value_property = CONF_VALUE + + uint16_t_ptr = cg.uint16.operator("ptr") -lvgl_ns = cg.esphome_ns.namespace("lvgl") char_ptr = cg.global_ns.namespace("char").operator("ptr") void_ptr = cg.void.operator("ptr") -LvglComponent = lvgl_ns.class_("LvglComponent", cg.PollingComponent) -LvglComponentPtr = LvglComponent.operator("ptr") -lv_event_code_t = cg.global_ns.namespace("lv_event_code_t") +lv_coord_t = cg.global_ns.namespace("lv_coord_t") +lv_event_code_t = cg.global_ns.enum("lv_event_code_t") lv_indev_type_t = cg.global_ns.enum("lv_indev_type_t") FontEngine = lvgl_ns.class_("FontEngine") 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") 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") +# fake parent class for first class widgets and matrix buttons 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_ptr = cg.global_ns.struct("lv_disp_t").operator("ptr") +lv_disp_t = cg.global_ns.struct("lv_disp_t") lv_color_t = cg.global_ns.struct("lv_color_t") lv_group_t = cg.global_ns.struct("lv_group_t") LVTouchListener = lvgl_ns.class_("LVTouchListener") LVEncoderListener = lvgl_ns.class_("LVEncoderListener") lv_obj_t = LvType("lv_obj_t") +lv_page_t = cg.global_ns.class_("LvPageType", LvCompound) lv_img_t = LvType("lv_img_t") - -# this will be populated later, in __init__.py to avoid circular imports. -WIDGET_TYPES: dict = {} +LV_EVENT = MockObj(base="LV_EVENT_", op="") +LV_STATE = MockObj(base="LV_STATE_", op="") +LV_BTNMATRIX_CTRL = MockObj(base="LV_BTNMATRIX_CTRL_", op="") class LvText(LvType): @@ -55,7 +70,8 @@ class LvText(LvType): super().__init__( *args, largs=[(cg.std_string, "text")], - lvalue=lambda w: w.get_property("text")[0], + lvalue=lambda w: w.get_property("text"), + has_on_value=True, **kwargs, ) self.value_property = CONF_TEXT @@ -66,13 +82,21 @@ class LvBoolean(LvType): super().__init__( *args, largs=[(cg.bool_, "x")], - lvalue=lambda w: w.has_state("LV_STATE_CHECKED"), + lvalue=lambda w: w.is_checked(), has_on_value=True, **kwargs, ) -CUSTOM_EVENT = ID("lv_custom_event", False, type=lv_event_code_t) +class LvSelect(LvType): + def __init__(self, *args, **kwargs): + super().__init__( + *args, + largs=[(cg.int_, "x")], + lvalue=lambda w: w.get_property("selected"), + has_on_value=True, + **kwargs, + ) class WidgetType: @@ -80,7 +104,15 @@ class WidgetType: Describes a type of Widget, e.g. "bar" or "line" """ - def __init__(self, name, w_type, parts, schema=None, modify_schema=None): + def __init__( + self, + name: str, + w_type: LvType, + parts: tuple, + schema=None, + modify_schema=None, + lv_name=None, + ): """ :param name: The widget name, e.g. "bar" :param w_type: The C type of the widget @@ -89,6 +121,7 @@ class WidgetType: :param modify_schema: A schema to update the widget """ self.name = name + self.lv_name = lv_name or name self.w_type = w_type self.parts = parts if schema is None: @@ -98,7 +131,8 @@ class WidgetType: if modify_schema is None: self.modify_schema = self.schema else: - self.modify_schema = self.schema + self.modify_schema = modify_schema + self.mock_obj = MockObj(f"lv_{self.lv_name}", "_") @property def animated(self): @@ -118,7 +152,7 @@ class WidgetType: :param config: Its configuration :return: Generated code as a list of text lines """ - raise NotImplementedError(f"No to_code defined for {self.name}") + return [] def obj_creator(self, parent: MockObjClass, config: dict): """ @@ -127,7 +161,7 @@ class WidgetType: :param config: Its configuration :return: Generated code as a single text line """ - return f"lv_{self.name}_create({parent})" + return lv_expr.call(f"{self.lv_name}_create", parent) def get_uses(self): """ @@ -135,3 +169,23 @@ class WidgetType: :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 + + +class NumberType(WidgetType): + def get_max(self, config: dict): + return int(config[CONF_MAX_VALUE] or 100) + + def get_min(self, config: dict): + return int(config[CONF_MIN_VALUE] or 0) diff --git a/esphome/components/lvgl/widget.py b/esphome/components/lvgl/widget.py index 83aed341e7..5734aec7dc 100644 --- a/esphome/components/lvgl/widget.py +++ b/esphome/components/lvgl/widget.py @@ -1,33 +1,63 @@ import sys -from typing import Any +from typing import Any, Union from esphome import codegen as cg, config_validation as cv from esphome.config_validation import Invalid -from esphome.const import CONF_GROUP, CONF_ID, CONF_STATE -from esphome.core import CORE, TimePeriod +from esphome.const import CONF_GROUP, CONF_ID, CONF_STATE, CONF_TYPE +from esphome.core import ID, TimePeriod from esphome.coroutine import FakeAwaitable -from esphome.cpp_generator import MockObj, MockObjClass, VariableDeclarationExpression +from esphome.cpp_generator import AssignmentExpression, CallExpression, MockObj from .defines import ( CONF_DEFAULT, + CONF_FLEX_ALIGN_CROSS, + CONF_FLEX_ALIGN_MAIN, + CONF_FLEX_ALIGN_TRACK, + CONF_FLEX_FLOW, + CONF_GRID_COLUMN_ALIGN, + CONF_GRID_COLUMNS, + CONF_GRID_ROW_ALIGN, + CONF_GRID_ROWS, + CONF_LAYOUT, CONF_MAIN, CONF_SCROLLBAR_MODE, + CONF_STYLES, CONF_WIDGETS, OBJ_FLAGS, PARTS, STATES, - ConstantLiteral, + TYPE_FLEX, + TYPE_GRID, LValidator, join_enums, literal, ) from .helpers import add_lv_use -from .lvcode import add_group, add_line_marks, lv, lv_add, lv_assign, lv_expr, lv_obj -from .schemas import ALL_STYLES, STYLE_REMAP -from .types import WIDGET_TYPES, LvType, WidgetType, lv_obj_t, lv_obj_t_ptr +from .lvcode import ( + LvConditional, + add_line_marks, + lv, + lv_add, + lv_assign, + lv_expr, + lv_obj, + lv_Pvariable, +) +from .schemas import ALL_STYLES, STYLE_REMAP, WIDGET_TYPES +from .types import ( + LV_STATE, + LvType, + WidgetType, + lv_coord_t, + lv_group_t, + lv_obj_t, + lv_obj_t_ptr, +) EVENT_LAMB = "event_lamb__" +theme_widget_map = {} + class LvScrActType(WidgetType): """ @@ -37,9 +67,6 @@ class LvScrActType(WidgetType): def __init__(self): super().__init__("lv_scr_act()", lv_obj_t, ()) - def obj_creator(self, parent: MockObjClass, config: dict): - return [] - async def to_code(self, w, config: dict): return [] @@ -55,7 +82,7 @@ class Widget: def set_completed(): Widget.widgets_completed = True - def __init__(self, var, wtype: WidgetType, config: dict = None, parent=None): + def __init__(self, var, wtype: WidgetType, config: dict = None): self.var = var self.type = wtype self.config = config @@ -63,21 +90,18 @@ class Widget: self.step = 1.0 self.range_from = -sys.maxsize self.range_to = sys.maxsize - self.parent = parent + if wtype.is_compound(): + self.obj = MockObj(f"{self.var}->obj") + else: + self.obj = var @staticmethod - def create(name, var, wtype: WidgetType, config: dict = None, parent=None): - w = Widget(var, wtype, config, parent) + def create(name, var, wtype: WidgetType, config: dict = None): + w = Widget(var, wtype, config) if name is not None: widget_map[name] = w return w - @property - def obj(self): - if self.type.is_compound(): - return f"{self.var}->obj" - return self.var - def add_state(self, state): return lv_obj.add_state(self.obj, literal(state)) @@ -85,7 +109,13 @@ class Widget: return lv_obj.clear_state(self.obj, literal(state)) def has_state(self, state): - return lv_expr.obj_get_state(self.obj) & literal(state) != 0 + return (lv_expr.obj_get_state(self.obj) & literal(state)) != 0 + + def is_pressed(self): + return self.has_state(LV_STATE.PRESSED) + + def is_checked(self): + return self.has_state(LV_STATE.CHECKED) def add_flag(self, flag): return lv_obj.add_flag(self.obj, literal(flag)) @@ -93,32 +123,37 @@ class Widget: def clear_flag(self, flag): return lv_obj.clear_flag(self.obj, literal(flag)) - def set_property(self, prop, value, animated: bool = None, ltype=None): + async def set_property(self, prop, value, animated: bool = None): 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: return if isinstance(value, TimePeriod): value = value.total_milliseconds - ltype = ltype or self.__type_base() + if isinstance(value, str): + value = literal(value) if animated is None or self.type.animated is not True: - lv.call(f"{ltype}_set_{prop}", self.obj, value) + lv.call(f"{self.type.lv_name}_set_{prop}", self.obj, value) else: lv.call( - f"{ltype}_set_{prop}", + f"{self.type.lv_name}_set_{prop}", self.obj, value, - "LV_ANIM_ON" if animated else "LV_ANIM_OFF", + literal("LV_ANIM_ON" if animated else "LV_ANIM_OFF"), ) def get_property(self, prop, ltype=None): ltype = ltype or self.__type_base() - return f"lv_{ltype}_get_{prop}({self.obj})" + return cg.RawExpression(f"lv_{ltype}_get_{prop}({self.obj})") def set_style(self, prop, value, state): if value is None: - return [] - return lv.call(f"obj_set_style_{prop}", self.obj, value, state) + return + lv.call(f"obj_set_style_{prop}", self.obj, value, state) def __type_base(self): wtype = self.type.w_type @@ -140,6 +175,32 @@ class Widget: return self.type.w_type.value(self) return self.obj + def get_number_value(self): + value = self.type.mock_obj.get_value(self.obj) + if self.scale == 1.0: + return value + return value / float(self.scale) + + def is_selected(self): + """ + Overridable property to determine if the widget is selected. Will be None except + for matrix buttons + :return: + """ + return None + + 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) + # Map of widgets to their config, used for trigger generation widget_map: dict[Any, Widget] = {} @@ -161,13 +222,20 @@ def get_widget_generator(wid): yield -async def get_widget(config: dict, id: str = CONF_ID) -> Widget: - wid = config[id] +async def get_widget_(wid: Widget): if obj := widget_map.get(wid): return obj return await FakeAwaitable(get_widget_generator(wid)) +async def get_widgets(config: Union[dict, list], id: str = CONF_ID) -> list[Widget]: + if not config: + return [] + if not isinstance(config, list): + config = [config] + return [await get_widget_(c[id]) for c in config if id in c] + + def collect_props(config): """ Collect all properties from a configuration @@ -175,7 +243,7 @@ def collect_props(config): :return: """ props = {} - for prop in [*ALL_STYLES, *OBJ_FLAGS, CONF_GROUP]: + for prop in [*ALL_STYLES, *OBJ_FLAGS, CONF_STYLES, CONF_GROUP]: if prop in config: props[prop] = config[prop] return props @@ -209,12 +277,39 @@ def collect_parts(config): async def set_obj_properties(w: Widget, config): """Generate a list of C++ statements to apply properties to an lv_obj_t""" + if layout := config.get(CONF_LAYOUT): + layout_type: str = layout[CONF_TYPE] + lv_obj.set_layout(w.obj, literal(f"LV_LAYOUT_{layout_type.upper()}")) + if layout_type == TYPE_GRID: + wid = config[CONF_ID] + rows = "{" + ",".join(layout[CONF_GRID_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 = ( + "{" + ",".join(layout[CONF_GRID_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( + 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 + ) + if layout_type == TYPE_FLEX: + lv_obj.set_flex_flow(w.obj, literal(layout[CONF_FLEX_FLOW])) + main = literal(layout[CONF_FLEX_ALIGN_MAIN]) + cross = literal(layout[CONF_FLEX_ALIGN_CROSS]) + track = literal(layout[CONF_FLEX_ALIGN_TRACK]) + lv_obj.set_flex_align(w.obj, main, cross, track) parts = collect_parts(config) for part, states in parts.items(): for state, props in states.items(): - lv_state = ConstantLiteral( - f"(int)LV_STATE_{state.upper()}|(int)LV_PART_{part.upper()}" - ) + lv_state = join_enums((f"LV_STATE_{state}", f"LV_PART_{part}")) + for style_id in props.get(CONF_STYLES, ()): + lv_obj.add_style(w.obj, MockObj(style_id), lv_state) for prop, value in { k: v for k, v in props.items() if k in ALL_STYLES }.items(): @@ -258,14 +353,12 @@ async def set_obj_properties(w: Widget, config): w.clear_state(clears) for key, value in lambs.items(): lamb = await cg.process_lambda(value, [], return_type=cg.bool_) - state = f"LV_STATE_{key.upper}" - lv.cond_if(lamb) - w.add_state(state) - lv.cond_else() - w.clear_state(state) - lv.cond_endif() - if scrollbar_mode := config.get(CONF_SCROLLBAR_MODE): - lv_obj.set_scrollbar_mode(w.obj, scrollbar_mode) + state = f"LV_STATE_{key.upper()}" + with LvConditional(f"{lamb}()") as cond: + w.add_state(state) + cond.else_() + w.clear_state(state) + await w.set_property(CONF_SCROLLBAR_MODE, config) async def add_widgets(parent: Widget, config: dict): @@ -280,7 +373,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, parent): +async def widget_to_code(w_cnfig, w_type: WidgetType, parent): """ Converts a Widget definition to C code. :param w_cnfig: The widget configuration @@ -298,19 +391,33 @@ async def widget_to_code(w_cnfig, w_type, parent): var = cg.new_Pvariable(wid) lv_add(var.set_obj(creator)) else: - var = MockObj(wid, "->") - decl = VariableDeclarationExpression(lv_obj_t, "*", wid) - CORE.add_global(decl) - CORE.register_variable(wid, var) + var = lv_Pvariable(lv_obj_t, wid) lv_assign(var, creator) - widget = Widget.create(wid, var, spec, w_cnfig, parent) - await set_obj_properties(widget, w_cnfig) - await add_widgets(widget, w_cnfig) - await spec.to_code(widget, w_cnfig) + w = Widget.create(wid, var, spec, w_cnfig) + if theme := theme_widget_map.get(w_type): + lv_add(CallExpression(theme, w.obj)) + await set_obj_properties(w, w_cnfig) + await add_widgets(w, w_cnfig) + await spec.to_code(w, w_cnfig) lv_scr_act_spec = LvScrActType() -lv_scr_act = Widget.create( - None, ConstantLiteral("lv_scr_act()"), lv_scr_act_spec, {}, parent=None -) +lv_scr_act = Widget.create(None, literal("lv_scr_act()"), lv_scr_act_spec, {}) + +lv_groups = {} # Widget group names + + +def add_group(name): + if name is None: + return None + fullname = f"lv_esp_group_{name}" + if name not in lv_groups: + gid = ID(fullname, True, type=lv_group_t.operator("ptr")) + lv_add( + AssignmentExpression( + type_=gid.type, modifier="", name=fullname, rhs=lv_expr.group_create() + ) + ) + lv_groups[name] = literal(fullname) + return lv_groups[name] diff --git a/tests/components/lvgl/lvgl-package.yaml b/tests/components/lvgl/lvgl-package.yaml index fde700e0bd..0cca45d376 100644 --- a/tests/components/lvgl/lvgl-package.yaml +++ b/tests/components/lvgl/lvgl-package.yaml @@ -5,142 +5,229 @@ lvgl: - touchscreen_id: tft_touch long_press_repeat_time: 200ms long_press_time: 500ms - widgets: - - label: - id: hello_label - text: Hello world - text_color: 0xFF8000 - align: center - text_font: montserrat_40 - border_post: true - - - label: - text: "Hello shiny day" - text_color: 0xFFFFFF - align: bottom_mid - text_font: space16 - - obj: - align: center - arc_opa: COVER - arc_color: 0xFF0000 - arc_rounded: false - arc_width: 3 - 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 - bg_image_recolor: light_blue - bg_image_recolor_opa: 50% - bg_main_stop: 0 - bg_opa: 20% - border_color: 0x00FF00 - border_opa: cover - border_post: true - border_side: [bottom, left] - border_width: 4 - clip_corner: false - height: 50% - image_recolor: light_blue - image_recolor_opa: cover - line_width: 10 - line_dash_width: 10 - line_dash_gap: 10 - line_rounded: false - line_color: light_blue - opa: cover - opa_layered: cover - outline_color: light_blue - outline_opa: cover - outline_pad: 10px - outline_width: 10px - pad_all: 10px - pad_bottom: 10px - pad_column: 10px - pad_left: 10px - pad_right: 10px - pad_row: 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 - text_align: auto - text_color: light_blue - text_decor: [underline, strikethrough] - text_font: montserrat_18 - text_letter_space: 4 - text_line_space: 4 - text_opa: cover - transform_angle: 180 - transform_height: 100 - transform_pivot_x: 50% - transform_pivot_y: 50% - transform_zoom: 0.5 - translate_x: 10 - translate_y: 10 - max_height: 100 - max_width: 200 - min_height: 20% - min_width: 20% - radius: circle - width: 10px - x: 100 - y: 120 - - button: - width: 20% - height: 10% - pressed: - bg_color: light_blue - checkable: true - checked: - bg_color: 0x000000 - widgets: - - label: - text: Button - on_click: - lvgl.label.update: + pages: + - id: page1 + skip: true + widgets: + - label: id: hello_label - bg_color: 0x123456 - text: clicked - on_value: - logger.log: - format: "state now %d" - args: [x] - on_short_click: - lvgl.widget.hide: hello_label - on_long_press: - lvgl.widget.show: hello_label - on_cancel: - lvgl.widget.enable: hello_label - on_ready: - lvgl.widget.disable: hello_label - on_defocus: - lvgl.widget.hide: hello_label - on_focus: - logger.log: Button clicked - on_scroll: - logger.log: Button clicked - on_scroll_end: - logger.log: Button clicked - on_scroll_begin: - logger.log: Button clicked - on_release: - logger.log: Button clicked - on_long_press_repeat: - logger.log: Button clicked + text: Hello world + text_color: 0xFF8000 + align: center + text_font: montserrat_40 + border_post: true + - label: + text: "Hello shiny day" + text_color: 0xFFFFFF + align: bottom_mid + text_font: space16 + - obj: + align: center + arc_opa: COVER + arc_color: 0xFF0000 + arc_rounded: false + arc_width: 3 + 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 + bg_image_recolor: light_blue + bg_image_recolor_opa: 50% + bg_main_stop: 0 + bg_opa: 20% + border_color: 0x00FF00 + border_opa: cover + border_post: true + border_side: [bottom, left] + border_width: 4 + clip_corner: false + height: 50% + image_recolor: light_blue + image_recolor_opa: cover + line_width: 10 + line_dash_width: 10 + line_dash_gap: 10 + line_rounded: false + line_color: light_blue + opa: cover + opa_layered: cover + outline_color: light_blue + outline_opa: cover + outline_pad: 10px + outline_width: 10px + pad_all: 10px + pad_bottom: 10px + pad_column: 10px + pad_left: 10px + pad_right: 10px + pad_row: 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 + text_align: auto + text_color: light_blue + text_decor: [underline, strikethrough] + text_font: montserrat_18 + text_letter_space: 4 + text_line_space: 4 + text_opa: cover + transform_angle: 180 + transform_height: 100 + transform_pivot_x: 50% + transform_pivot_y: 50% + transform_zoom: 0.5 + translate_x: 10 + translate_y: 10 + max_height: 100 + max_width: 200 + min_height: 20% + min_width: 20% + radius: circle + width: 10px + x: 100 + y: 120 + - button: + width: 20% + height: 10% + pressed: + bg_color: light_blue + checkable: true + checked: + bg_color: 0x000000 + widgets: + - label: + text: Button + on_click: + lvgl.label.update: + id: hello_label + bg_color: 0x123456 + text: clicked + on_value: + logger.log: + format: "state now %d" + args: [x] + on_short_click: + lvgl.widget.hide: hello_label + on_long_press: + lvgl.widget.show: hello_label + on_cancel: + lvgl.widget.enable: hello_label + on_ready: + lvgl.widget.disable: hello_label + on_defocus: + lvgl.widget.hide: hello_label + on_focus: + logger.log: Button clicked + on_scroll: + logger.log: Button clicked + on_scroll_end: + logger.log: Button clicked + on_scroll_begin: + logger.log: Button clicked + on_release: + logger.log: Button clicked + on_long_press_repeat: + logger.log: Button clicked + - led: + color: 0x00FF00 + brightness: 50% + align: right_mid + - spinner: + arc_length: 120 + spin_time: 2s + align: left_mid + - image: + src: cat_image + align: top_left + y: 50 + + - id: page2 + widgets: + - arc: + align: left_mid + id: lv_arc + adjustable: true + on_value: + then: + - logger.log: + format: "Arc value is %f" + args: [x] + group: general + scroll_on_focus: true + value: 75 + min_value: 1 + max_value: 100 + arc_color: 0xFF0000 + indicator: + arc_color: 0xF000FF + pressed: + arc_color: 0xFFFF00 + focused: + arc_color: 0x808080 + - bar: + id: bar_id + align: top_mid + y: 20 + value: 30 + max_value: 100 + min_value: 10 + mode: range + on_click: + then: + - lvgl.bar.update: + id: bar_id + value: !lambda return (int)((float)rand() / RAND_MAX * 100); + - logger.log: + format: "bar value %f" + args: [x] + - line: + align: center + points: + - 5, 5 + - 70, 70 + - 120, 10 + - 180, 60 + - 240, 10 + on_click: + lvgl.page.next: + - switch: + align: right_mid + - checkbox: + text: Checkbox + align: bottom_right + - slider: + id: slider_id + align: top_mid + y: 40 + value: 30 + max_value: 100 + min_value: 10 + mode: normal + on_value: + then: + - logger.log: + format: "slider value %f" + args: [x] + on_click: + then: + - lvgl.slider.update: + id: slider_id + value: !lambda return (int)((float)rand() / RAND_MAX * 100); font: - file: "gfonts://Roboto" id: space16 bpp: 4 image: - - id: cat_img + - id: cat_image resize: 256x48 file: $component_dir/logo-text.svg - id: dog_img From e02319dcff75a003b5551866c701dd81803022c8 Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt Date: Mon, 5 Aug 2024 12:09:54 -0400 Subject: [PATCH 1860/2101] [esp32_improv] Update Improv library to reference new repo/version (#7195) --- esphome/components/esp32_improv/__init__.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/esphome/components/esp32_improv/__init__.py b/esphome/components/esp32_improv/__init__.py index 62d9cd376c..705dff0f1b 100644 --- a/esphome/components/esp32_improv/__init__.py +++ b/esphome/components/esp32_improv/__init__.py @@ -1,9 +1,8 @@ import esphome.codegen as cg +from esphome.components import binary_sensor, esp32_ble_server, output import esphome.config_validation as cv -from esphome.components import binary_sensor, output, esp32_ble_server from esphome.const import CONF_ID - AUTO_LOAD = ["esp32_ble_server"] CODEOWNERS = ["@jesserockz"] DEPENDENCIES = ["wifi", "esp32"] @@ -50,7 +49,7 @@ async def to_code(config): cg.add(ble_server.register_service_component(var)) cg.add_define("USE_IMPROV") - cg.add_library("esphome/Improv", "1.2.3") + cg.add_library("improv/Improv", "1.2.4") cg.add(var.set_identify_duration(config[CONF_IDENTIFY_DURATION])) cg.add(var.set_authorized_duration(config[CONF_AUTHORIZED_DURATION])) From f737ca6e286f36e243b5bae1bcb7515b9a4bf857 Mon Sep 17 00:00:00 2001 From: Daniel Kraft Date: Mon, 5 Aug 2024 23:17:02 +0200 Subject: [PATCH 1861/2101] hydreon_rgxx: Fix parsing of data line (#7192) --- esphome/components/hydreon_rgxx/hydreon_rgxx.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/hydreon_rgxx/hydreon_rgxx.cpp b/esphome/components/hydreon_rgxx/hydreon_rgxx.cpp index 95702fe9e8..92d7774193 100644 --- a/esphome/components/hydreon_rgxx/hydreon_rgxx.cpp +++ b/esphome/components/hydreon_rgxx/hydreon_rgxx.cpp @@ -236,7 +236,7 @@ void HydreonRGxxComponent::process_line_() { } bool is_data_line = false; for (int i = 0; i < NUM_SENSORS; i++) { - if (this->sensors_[i] != nullptr && this->buffer_starts_with_(PROTOCOL_NAMES[i])) { + if (this->sensors_[i] != nullptr && this->buffer_.find(PROTOCOL_NAMES[i]) != std::string::npos) { is_data_line = true; break; } From acaec41bb765949f37c04cf34b77e0f73df26272 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Tue, 6 Aug 2024 01:40:34 +0200 Subject: [PATCH 1862/2101] Remove outdated version block (#7177) --- esphome/__main__.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/esphome/__main__.py b/esphome/__main__.py index 7237a04717..5c197ff486 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -972,13 +972,6 @@ def run_esphome(argv): args.command == "dashboard", ) - if sys.version_info < (3, 8, 0): - _LOGGER.error( - "You're running ESPHome with Python <3.8. ESPHome is no longer compatible " - "with this Python version. Please reinstall ESPHome with Python 3.8+" - ) - return 1 - if args.command in PRE_CONFIG_ACTIONS: try: return PRE_CONFIG_ACTIONS[args.command](args) From 6b141102d62930778552db1f2bdf23bdc20b1d86 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Tue, 6 Aug 2024 11:17:29 +1000 Subject: [PATCH 1863/2101] [lvgl] Stage 5 (#7191) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/lvgl/__init__.py | 25 +- esphome/components/lvgl/animimg.py | 2 +- esphome/components/lvgl/automation.py | 2 +- esphome/components/lvgl/{btn.py => button.py} | 8 +- esphome/components/lvgl/buttonmatrix.py | 277 ++++++++++++++++ esphome/components/lvgl/checkbox.py | 2 +- esphome/components/lvgl/defines.py | 2 +- esphome/components/lvgl/dropdown.py | 76 +++++ esphome/components/lvgl/img.py | 8 +- esphome/components/lvgl/keyboard.py | 49 +++ esphome/components/lvgl/led.py | 4 +- esphome/components/lvgl/lvgl_esphome.cpp | 4 +- esphome/components/lvgl/lvgl_esphome.h | 2 +- esphome/components/lvgl/meter.py | 302 ++++++++++++++++++ esphome/components/lvgl/msgbox.py | 127 ++++++++ esphome/components/lvgl/roller.py | 77 +++++ esphome/components/lvgl/spinbox.py | 178 +++++++++++ esphome/components/lvgl/styles.py | 2 +- esphome/components/lvgl/tabview.py | 114 +++++++ esphome/components/lvgl/textarea.py | 67 ++++ esphome/components/lvgl/tileview.py | 128 ++++++++ esphome/components/lvgl/widget.py | 8 +- esphome/core/defines.h | 3 + tests/components/lvgl/.gitattributes | 2 + tests/components/lvgl/common.yaml | 46 +++ tests/components/lvgl/helvetica.ttf | Bin 0 -> 83644 bytes tests/components/lvgl/lvgl-package.yaml | 228 ++++++++++++- .../lvgl/materialdesignicons-webfont.ttf | Bin 0 -> 1307419 bytes tests/components/lvgl/roboto.ttf | Bin 0 -> 171676 bytes 29 files changed, 1716 insertions(+), 27 deletions(-) rename esphome/components/lvgl/{btn.py => button.py} (58%) create mode 100644 esphome/components/lvgl/buttonmatrix.py create mode 100644 esphome/components/lvgl/dropdown.py create mode 100644 esphome/components/lvgl/keyboard.py create mode 100644 esphome/components/lvgl/meter.py create mode 100644 esphome/components/lvgl/msgbox.py create mode 100644 esphome/components/lvgl/roller.py create mode 100644 esphome/components/lvgl/spinbox.py create mode 100644 esphome/components/lvgl/tabview.py create mode 100644 esphome/components/lvgl/textarea.py create mode 100644 esphome/components/lvgl/tileview.py create mode 100644 tests/components/lvgl/.gitattributes create mode 100644 tests/components/lvgl/helvetica.ttf create mode 100644 tests/components/lvgl/materialdesignicons-webfont.ttf create mode 100644 tests/components/lvgl/roboto.ttf diff --git a/esphome/components/lvgl/__init__.py b/esphome/components/lvgl/__init__.py index c154689199..a963fca98b 100644 --- a/esphome/components/lvgl/__init__.py +++ b/esphome/components/lvgl/__init__.py @@ -24,10 +24,13 @@ from . import defines as df, helpers, lv_validation as lvalid from .animimg import animimg_spec from .arc import arc_spec from .automation import disp_update, update_to_code -from .btn import btn_spec +from .button import button_spec +from .buttonmatrix import buttonmatrix_spec from .checkbox import checkbox_spec from .defines import CONF_SKIP +from .dropdown import dropdown_spec from .img import img_spec +from .keyboard import keyboard_spec from .label import label_spec from .led import led_spec from .line import line_spec @@ -35,8 +38,11 @@ from .lv_bar import bar_spec from .lv_switch import switch_spec from .lv_validation import lv_bool, lv_images_used from .lvcode import LvContext, LvglComponent +from .meter import meter_spec +from .msgbox import MSGBOX_SCHEMA, msgboxes_to_code from .obj import obj_spec from .page import add_pages, page_spec +from .roller import roller_spec from .rotary_encoders import ROTARY_ENCODER_CONFIG, rotary_encoders_to_code from .schemas import ( DISP_BG_SCHEMA, @@ -52,8 +58,12 @@ from .schemas import ( obj_schema, ) from .slider import slider_spec +from .spinbox import spinbox_spec from .spinner import spinner_spec from .styles import add_top_layer, styles_to_code, theme_to_code +from .tabview import tabview_spec +from .textarea import textarea_spec +from .tileview import tileview_spec from .touchscreens import touchscreen_schema, touchscreens_to_code from .trigger import generate_triggers from .types import ( @@ -75,7 +85,7 @@ LOGGER = logging.getLogger(__name__) for w_type in ( label_spec, obj_spec, - btn_spec, + button_spec, bar_spec, slider_spec, arc_spec, @@ -86,6 +96,15 @@ for w_type in ( checkbox_spec, img_spec, switch_spec, + tabview_spec, + buttonmatrix_spec, + meter_spec, + dropdown_spec, + roller_spec, + textarea_spec, + spinbox_spec, + keyboard_spec, + tileview_spec, ): WIDGET_TYPES[w_type.name] = w_type @@ -244,6 +263,7 @@ async def to_code(config): await add_widgets(lv_scr_act, config) await add_pages(lv_component, config) await add_top_layer(config) + await msgboxes_to_code(config) await disp_update(f"{lv_component}->get_disp()", config) Widget.set_completed() await generate_triggers(lv_component) @@ -308,6 +328,7 @@ CONFIG_SCHEMA = ( cv.Exclusive(CONF_PAGES, CONF_PAGES): cv.ensure_list( container_schema(page_spec) ), + 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_TRANSPARENCY_KEY, default=0x000400): lvalid.lv_color, diff --git a/esphome/components/lvgl/animimg.py b/esphome/components/lvgl/animimg.py index 20b85b019c..ad84713d7f 100644 --- a/esphome/components/lvgl/animimg.py +++ b/esphome/components/lvgl/animimg.py @@ -2,8 +2,8 @@ from esphome import automation import esphome.codegen as cg import esphome.config_validation as cv from esphome.const import CONF_DURATION, CONF_ID +from esphome.cpp_generator import MockObj -from ...cpp_generator import MockObj from .automation import action_to_code from .defines import CONF_AUTO_START, CONF_MAIN, CONF_REPEAT_COUNT, CONF_SRC from .helpers import lvgl_components_required diff --git a/esphome/components/lvgl/automation.py b/esphome/components/lvgl/automation.py index ffa25783ad..7a862fb58b 100644 --- a/esphome/components/lvgl/automation.py +++ b/esphome/components/lvgl/automation.py @@ -109,7 +109,7 @@ async def disp_update(disp, config: dict): if CONF_DISP_BG_COLOR not in config and CONF_DISP_BG_IMAGE not in config: return with LocalVariable("lv_disp_tmp", lv_disp_t, literal(disp)) as disp_temp: - if bg_color := config.get(CONF_DISP_BG_COLOR): + 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): lv.disp_set_bg_image(disp_temp, await lv_image.process(bg_image)) diff --git a/esphome/components/lvgl/btn.py b/esphome/components/lvgl/button.py similarity index 58% rename from esphome/components/lvgl/btn.py rename to esphome/components/lvgl/button.py index 2a2a53e1e2..96329b3fa9 100644 --- a/esphome/components/lvgl/btn.py +++ b/esphome/components/lvgl/button.py @@ -3,12 +3,12 @@ from esphome.const import CONF_BUTTON from .defines import CONF_MAIN from .types import LvBoolean, WidgetType -lv_btn_t = LvBoolean("lv_btn_t") +lv_button_t = LvBoolean("lv_btn_t") -class BtnType(WidgetType): +class ButtonType(WidgetType): def __init__(self): - super().__init__(CONF_BUTTON, lv_btn_t, (CONF_MAIN,), lv_name="btn") + super().__init__(CONF_BUTTON, lv_button_t, (CONF_MAIN,), lv_name="btn") def get_uses(self): return ("btn",) @@ -17,4 +17,4 @@ class BtnType(WidgetType): return [] -btn_spec = BtnType() +button_spec = ButtonType() diff --git a/esphome/components/lvgl/buttonmatrix.py b/esphome/components/lvgl/buttonmatrix.py new file mode 100644 index 0000000000..75ed43f909 --- /dev/null +++ b/esphome/components/lvgl/buttonmatrix.py @@ -0,0 +1,277 @@ +from esphome import automation +import esphome.codegen as cg +from esphome.components.key_provider import KeyProvider +import esphome.config_validation as cv +from esphome.const import CONF_ID, CONF_WIDTH +from esphome.cpp_generator import MockObj + +from .automation import action_to_code +from .button import lv_button_t +from .defines import ( + BUTTONMATRIX_CTRLS, + CONF_BUTTONS, + CONF_CONTROL, + CONF_ITEMS, + CONF_KEY_CODE, + CONF_MAIN, + CONF_ONE_CHECKED, + CONF_ROWS, + CONF_SELECTED, + CONF_TEXT, +) +from .helpers import lvgl_components_required +from .lv_validation import key_code, lv_bool +from .lvcode import lv, lv_add, lv_expr +from .schemas import automation_schema +from .types import ( + LV_BTNMATRIX_CTRL, + LV_STATE, + LvBoolean, + LvCompound, + LvType, + ObjUpdateAction, + char_ptr, + lv_pseudo_button_t, +) +from .widget import Widget, WidgetType, get_widgets, widget_map + +CONF_BUTTONMATRIX = "buttonmatrix" +CONF_BUTTON_TEXT_LIST_ID = "button_text_list_id" + +LvButtonMatrixButton = LvBoolean( + str(cg.uint16), + parents=(lv_pseudo_button_t,), +) +BUTTONMATRIX_BUTTON_SCHEMA = cv.Schema( + { + cv.Optional(CONF_TEXT): cv.string, + cv.Optional(CONF_KEY_CODE): key_code, + cv.GenerateID(): cv.declare_id(LvButtonMatrixButton), + cv.Optional(CONF_WIDTH, default=1): cv.positive_int, + cv.Optional(CONF_CONTROL): cv.ensure_list( + cv.Schema( + {cv.Optional(k.lower()): cv.boolean for k in BUTTONMATRIX_CTRLS.choices} + ) + ), + } +).extend(automation_schema(lv_button_t)) + +BUTTONMATRIX_SCHEMA = cv.Schema( + { + cv.Optional(CONF_ONE_CHECKED, default=False): lv_bool, + cv.GenerateID(CONF_BUTTON_TEXT_LIST_ID): cv.declare_id(char_ptr), + cv.Required(CONF_ROWS): cv.ensure_list( + cv.Schema( + { + cv.Required(CONF_BUTTONS): cv.ensure_list( + BUTTONMATRIX_BUTTON_SCHEMA + ), + } + ) + ), + } +) + + +class ButtonmatrixButtonType(WidgetType): + """ + A pseudo-widget for the matrix buttons + """ + + def __init__(self): + super().__init__("btnmatrix_btn", LvButtonMatrixButton, (), {}, {}) + + async def to_code(self, w, config: dict): + return [] + + +btn_btn_spec = ButtonmatrixButtonType() + + +class MatrixButton(Widget): + """ + Describes a button within a button matrix. + """ + + @staticmethod + def create_button(id, parent, config: dict, index): + w = MatrixButton(id, parent, config, index) + widget_map[id] = w + return w + + def __init__(self, id, parent: Widget, config, index): + super().__init__(id, btn_btn_spec, config) + self.parent = parent + self.index = index + self.obj = parent.obj + + def is_selected(self): + return self.parent.var.get_selected() == MockObj(self.var) + + @staticmethod + def map_ctrls(state): + state = str(state).upper().removeprefix("LV_STATE_") + assert state in BUTTONMATRIX_CTRLS.choices + return getattr(LV_BTNMATRIX_CTRL, state) + + def has_state(self, state): + state = self.map_ctrls(state) + return lv_expr.btnmatrix_has_btn_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) + + def clear_state(self, state): + state = self.map_ctrls(state) + return lv.btnmatrix_clear_btn_ctrl(self.obj, self.index, state) + + def is_pressed(self): + return self.is_selected() & self.parent.has_state(LV_STATE.PRESSED) + + def is_checked(self): + return self.has_state(LV_STATE.CHECKED) + + def get_value(self): + return self.is_checked() + + def check_null(self): + return None + + +async def get_button_data(config, buttonmatrix: Widget): + """ + Process a button matrix button list + :param config: The row list + :param buttonmatrix: The parent variable + :return: text array id, control list, width list + """ + text_list = [] + ctrl_list = [] + width_list = [] + key_list = [] + for row in config: + for button_conf in row.get(CONF_BUTTONS) or (): + bid = button_conf[CONF_ID] + index = len(width_list) + MatrixButton.create_button(bid, buttonmatrix, button_conf, index) + cg.new_variable(bid, index) + 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"] + 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)) + text_list.append("\n") + text_list = text_list[:-1] + text_list.append(cg.nullptr) + return text_list, ctrl_list, width_list, key_list + + +lv_buttonmatrix_t = LvType( + "LvButtonMatrixType", + parents=(KeyProvider, LvCompound), + largs=[(cg.uint16, "x")], + lvalue=lambda w: w.var.get_selected(), +) + + +class ButtonMatrixType(WidgetType): + def __init__(self): + super().__init__( + CONF_BUTTONMATRIX, + lv_buttonmatrix_t, + (CONF_MAIN, CONF_ITEMS), + BUTTONMATRIX_SCHEMA, + {}, + lv_name="btnmatrix", + ) + + async def to_code(self, w: Widget, config): + lvgl_components_required.add("BUTTONMATRIX") + if CONF_ROWS not in config: + return [] + text_list, ctrl_list, width_list, key_list = await get_button_data( + config[CONF_ROWS], w + ) + 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) + set_btn_data(w.obj, ctrl_list, width_list) + lv.btnmatrix_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",) + + +def set_btn_data(obj, ctrl_list, width_list): + for index, ctrl in enumerate(ctrl_list): + lv.btnmatrix_set_btn_ctrl(obj, index, ctrl) + for index, width in enumerate(width_list): + lv.btnmatrix_set_btn_width(obj, index, width) + + +buttonmatrix_spec = ButtonMatrixType() + + +@automation.register_action( + "lvgl.matrix.button.update", + ObjUpdateAction, + cv.Schema( + { + cv.Optional(CONF_WIDTH): cv.positive_int, + cv.Optional(CONF_CONTROL): cv.ensure_list( + cv.Schema( + { + cv.Optional(k.lower()): cv.boolean + for k in BUTTONMATRIX_CTRLS.choices + } + ), + ), + cv.Required(CONF_ID): cv.ensure_list( + cv.maybe_simple_value( + { + cv.Required(CONF_ID): cv.use_id(LvButtonMatrixButton), + }, + key=CONF_ID, + ) + ), + cv.Optional(CONF_SELECTED): lv_bool, + } + ), +) +async def button_update_to_code(config, action_id, template_arg, args): + widgets = await get_widgets(config[CONF_ID]) + assert all(isinstance(w, MatrixButton) for w in widgets) + + async def do_button_update(w: MatrixButton): + if (width := config.get(CONF_WIDTH)) is not None: + lv.btnmatrix_set_btn_width(w.obj, w.index, width) + if config.get(CONF_SELECTED): + lv.btnmatrix_set_selected_btn(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] + ) + if adds: + lv.btnmatrix_set_btn_ctrl( + w.obj, w.index, await BUTTONMATRIX_CTRLS.process(adds) + ) + if clrs: + lv.btnmatrix_clear_btn_ctrl( + w.obj, w.index, await BUTTONMATRIX_CTRLS.process(clrs) + ) + + return await action_to_code( + widgets, do_button_update, action_id, template_arg, args + ) diff --git a/esphome/components/lvgl/checkbox.py b/esphome/components/lvgl/checkbox.py index 7418d633cf..be7b029269 100644 --- a/esphome/components/lvgl/checkbox.py +++ b/esphome/components/lvgl/checkbox.py @@ -18,7 +18,7 @@ class CheckboxType(WidgetType): ) async def to_code(self, w: Widget, config): - if value := config.get(CONF_TEXT): + if (value := config.get(CONF_TEXT)) is not None: lv.checkbox_set_text(w.obj, await lv_text.process(value)) diff --git a/esphome/components/lvgl/defines.py b/esphome/components/lvgl/defines.py index 16ec45ae8a..ac28f9ed5f 100644 --- a/esphome/components/lvgl/defines.py +++ b/esphome/components/lvgl/defines.py @@ -304,7 +304,7 @@ OBJ_FLAGS = ( ARC_MODES = LvConstant("LV_ARC_MODE_", "NORMAL", "REVERSE", "SYMMETRICAL") BAR_MODES = LvConstant("LV_BAR_MODE_", "NORMAL", "SYMMETRICAL", "RANGE") -BTNMATRIX_CTRLS = LvConstant( +BUTTONMATRIX_CTRLS = LvConstant( "LV_BTNMATRIX_CTRL_", "HIDDEN", "NO_REPEAT", diff --git a/esphome/components/lvgl/dropdown.py b/esphome/components/lvgl/dropdown.py new file mode 100644 index 0000000000..d7bdebaade --- /dev/null +++ b/esphome/components/lvgl/dropdown.py @@ -0,0 +1,76 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.const import CONF_OPTIONS + +from .defines import ( + CONF_DIR, + CONF_INDICATOR, + CONF_MAIN, + CONF_SELECTED_INDEX, + CONF_SYMBOL, + DIRECTIONS, + literal, +) +from .label import CONF_LABEL +from .lv_validation import lv_int, lv_text, option_string +from .lvcode import LocalVariable, lv, lv_expr +from .schemas import part_schema +from .types import LvSelect, LvType, lv_obj_t +from .widget import Widget, WidgetType, set_obj_properties + +CONF_DROPDOWN = "dropdown" +CONF_DROPDOWN_LIST = "dropdown_list" + +lv_dropdown_t = LvSelect("lv_dropdown_t") +lv_dropdown_list_t = LvType("lv_dropdown_list_t") +dropdown_list_spec = WidgetType(CONF_DROPDOWN_LIST, lv_dropdown_list_t, (CONF_MAIN,)) + +DROPDOWN_BASE_SCHEMA = cv.Schema( + { + cv.Optional(CONF_SYMBOL): lv_text, + cv.Optional(CONF_SELECTED_INDEX): cv.templatable(cv.int_), + cv.Optional(CONF_DIR, default="BOTTOM"): DIRECTIONS.one_of, + cv.Optional(CONF_DROPDOWN_LIST): part_schema(dropdown_list_spec), + } +) + +DROPDOWN_SCHEMA = DROPDOWN_BASE_SCHEMA.extend( + { + cv.Required(CONF_OPTIONS): cv.ensure_list(option_string), + } +) + + +class DropdownType(WidgetType): + def __init__(self): + super().__init__( + CONF_DROPDOWN, + lv_dropdown_t, + (CONF_MAIN, CONF_INDICATOR), + DROPDOWN_SCHEMA, + DROPDOWN_BASE_SCHEMA, + ) + + async def to_code(self, w: Widget, config): + if options := config.get(CONF_OPTIONS): + text = cg.safe_exp("\n".join(options)) + lv.dropdown_set_options(w.obj, text) + if symbol := config.get(CONF_SYMBOL): + lv.dropdown_set_symbol(w.obj, await lv_text.process(symbol)) + if (selected := config.get(CONF_SELECTED_INDEX)) is not None: + value = await lv_int.process(selected) + lv.dropdown_set_selected(w.obj, value) + if dirn := config.get(CONF_DIR): + lv.dropdown_set_dir(w.obj, literal(dirn)) + if dlist := config.get(CONF_DROPDOWN_LIST): + with LocalVariable( + "dropdown_list", lv_obj_t, lv_expr.dropdown_get_list(w.obj) + ) as dlist_obj: + dwid = Widget(dlist_obj, dropdown_list_spec, dlist) + await set_obj_properties(dwid, dlist) + + def get_uses(self): + return (CONF_LABEL,) + + +dropdown_spec = DropdownType() diff --git a/esphome/components/lvgl/img.py b/esphome/components/lvgl/img.py index e9682def8c..dd962fcf31 100644 --- a/esphome/components/lvgl/img.py +++ b/esphome/components/lvgl/img.py @@ -65,16 +65,16 @@ class ImgType(WidgetType): 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 cf_angle := config.get(CONF_ANGLE): + if (cf_angle := config.get(CONF_ANGLE)) is not None: pivot_x = config[CONF_PIVOT_X] pivot_y = config[CONF_PIVOT_Y] lv.img_set_pivot(w.obj, pivot_x, pivot_y) lv.img_set_angle(w.obj, cf_angle) - if img_zoom := config.get(CONF_ZOOM): + if (img_zoom := config.get(CONF_ZOOM)) is not None: lv.img_set_zoom(w.obj, img_zoom) - if offset := config.get(CONF_OFFSET_X): + if (offset := config.get(CONF_OFFSET_X)) is not None: lv.img_set_offset_x(w.obj, offset) - if offset := config.get(CONF_OFFSET_Y): + if (offset := config.get(CONF_OFFSET_Y)) is not None: lv.img_set_offset_y(w.obj, offset) if CONF_ANTIALIAS in config: lv.img_set_antialias(w.obj, config[CONF_ANTIALIAS]) diff --git a/esphome/components/lvgl/keyboard.py b/esphome/components/lvgl/keyboard.py new file mode 100644 index 0000000000..7ce73d2170 --- /dev/null +++ b/esphome/components/lvgl/keyboard.py @@ -0,0 +1,49 @@ +from esphome.components.key_provider import KeyProvider +import esphome.config_validation as cv +from esphome.const import CONF_MODE +from esphome.cpp_types import std_string + +from .defines import CONF_ITEMS, CONF_MAIN, KEYBOARD_MODES, literal +from .helpers import add_lv_use, lvgl_components_required +from .textarea import CONF_TEXTAREA, lv_textarea_t +from .types import LvCompound, LvType +from .widget import Widget, WidgetType, get_widgets + +CONF_KEYBOARD = "keyboard" + +KEYBOARD_SCHEMA = { + cv.Optional(CONF_MODE, default="TEXT_UPPER"): KEYBOARD_MODES.one_of, + cv.Optional(CONF_TEXTAREA): cv.use_id(lv_textarea_t), +} + +lv_keyboard_t = LvType( + "LvKeyboardType", + parents=(KeyProvider, LvCompound), + largs=[(std_string, "text")], + has_on_value=True, + lvalue=lambda w: literal(f"lv_textarea_get_text({w.obj})"), +) + + +class KeyboardType(WidgetType): + def __init__(self): + super().__init__( + CONF_KEYBOARD, + lv_keyboard_t, + (CONF_MAIN, CONF_ITEMS), + KEYBOARD_SCHEMA, + ) + + def get_uses(self): + return CONF_KEYBOARD, CONF_TEXTAREA + + 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") + await w.set_property(CONF_MODE, await KEYBOARD_MODES.process(config[CONF_MODE])) + if ta := await get_widgets(config, CONF_TEXTAREA): + await w.set_property(CONF_TEXTAREA, ta[0].obj) + + +keyboard_spec = KeyboardType() diff --git a/esphome/components/lvgl/led.py b/esphome/components/lvgl/led.py index f920758efb..9b6e819278 100644 --- a/esphome/components/lvgl/led.py +++ b/esphome/components/lvgl/led.py @@ -20,9 +20,9 @@ class LedType(WidgetType): super().__init__(CONF_LED, LvType("lv_led_t"), (CONF_MAIN,), LED_SCHEMA) async def to_code(self, w: Widget, config): - if color := config.get(CONF_COLOR): + 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): + if (brightness := config.get(CONF_BRIGHTNESS)) is not None: lv.led_set_brightness(w.obj, await lv_brightness.process(brightness)) diff --git a/esphome/components/lvgl/lvgl_esphome.cpp b/esphome/components/lvgl/lvgl_esphome.cpp index 1221682d28..544643d532 100644 --- a/esphome/components/lvgl/lvgl_esphome.cpp +++ b/esphome/components/lvgl/lvgl_esphome.cpp @@ -146,12 +146,12 @@ LVEncoderListener::LVEncoderListener(lv_indev_type_t type, uint16_t lpt, uint16_ #endif // USE_LVGL_ROTARY_ENCODER #ifdef USE_LVGL_BUTTONMATRIX -void LvBtnmatrixType::set_obj(lv_obj_t *lv_obj) { +void LvButtonMatrixType::set_obj(lv_obj_t *lv_obj) { LvCompound::set_obj(lv_obj); lv_obj_add_event_cb( lv_obj, [](lv_event_t *event) { - auto *self = static_cast(event->user_data); + auto *self = static_cast(event->user_data); if (self->key_callback_.size() == 0) return; auto key_idx = lv_btnmatrix_get_selected_btn(self->obj); diff --git a/esphome/components/lvgl/lvgl_esphome.h b/esphome/components/lvgl/lvgl_esphome.h index b92799addd..71e0fd069f 100644 --- a/esphome/components/lvgl/lvgl_esphome.h +++ b/esphome/components/lvgl/lvgl_esphome.h @@ -246,7 +246,7 @@ class LVEncoderListener : public Parented { }; #endif // USE_LVGL_ROTARY_ENCODER #ifdef USE_LVGL_BUTTONMATRIX -class LvBtnmatrixType : public key_provider::KeyProvider, public LvCompound { +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); } diff --git a/esphome/components/lvgl/meter.py b/esphome/components/lvgl/meter.py new file mode 100644 index 0000000000..1a6bef7c57 --- /dev/null +++ b/esphome/components/lvgl/meter.py @@ -0,0 +1,302 @@ +from esphome import automation +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.const import ( + CONF_COLOR, + CONF_COUNT, + CONF_ID, + CONF_LENGTH, + CONF_LOCAL, + CONF_RANGE_FROM, + CONF_RANGE_TO, + CONF_ROTATION, + CONF_VALUE, + CONF_WIDTH, +) + +from .arc import CONF_ARC +from .automation import action_to_code +from .defines import ( + CONF_END_VALUE, + CONF_MAIN, + CONF_PIVOT_X, + CONF_PIVOT_Y, + CONF_SRC, + CONF_START_VALUE, + CONF_TICKS, +) +from .helpers import add_lv_use +from .img import CONF_IMAGE +from .line import CONF_LINE +from .lv_validation import ( + angle, + get_end_value, + get_start_value, + lv_bool, + lv_color, + lv_float, + lv_image, + requires_component, + size, +) +from .lvcode import LocalVariable, lv, lv_assign, lv_expr +from .obj import obj_spec +from .types import LvType, ObjUpdateAction +from .widget import Widget, WidgetType, get_widgets + +CONF_ANGLE_RANGE = "angle_range" +CONF_COLOR_END = "color_end" +CONF_COLOR_START = "color_start" +CONF_INDICATORS = "indicators" +CONF_LABEL_GAP = "label_gap" +CONF_MAJOR = "major" +CONF_METER = "meter" +CONF_R_MOD = "r_mod" +CONF_SCALES = "scales" +CONF_STRIDE = "stride" +CONF_TICK_STYLE = "tick_style" + +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) + + +INDICATOR_LINE_SCHEMA = cv.Schema( + { + cv.Optional(CONF_WIDTH, default=4): size, + cv.Optional(CONF_COLOR, default=0): lv_color, + cv.Optional(CONF_R_MOD, default=0): size, + cv.Optional(CONF_VALUE): lv_float, + } +) +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_VALUE): lv_float, + } +) +INDICATOR_ARC_SCHEMA = cv.Schema( + { + cv.Optional(CONF_WIDTH, default=4): size, + 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_END_VALUE): lv_float, + } +) +INDICATOR_TICKS_SCHEMA = cv.Schema( + { + cv.Optional(CONF_WIDTH, default=4): size, + 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_END_VALUE): lv_float, + cv.Optional(CONF_LOCAL, default=False): lv_bool, + } +) +INDICATOR_SCHEMA = cv.Schema( + { + cv.Exclusive(CONF_LINE, CONF_INDICATORS): INDICATOR_LINE_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(lv_meter_indicator_t), + } + ), + cv.Exclusive(CONF_IMAGE, CONF_INDICATORS): cv.All( + INDICATOR_IMG_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(lv_meter_indicator_t), + } + ), + requires_component("image"), + ), + cv.Exclusive(CONF_ARC, CONF_INDICATORS): INDICATOR_ARC_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(lv_meter_indicator_t), + } + ), + cv.Exclusive(CONF_TICK_STYLE, CONF_INDICATORS): INDICATOR_TICKS_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(lv_meter_indicator_t), + } + ), + } +) + +SCALE_SCHEMA = cv.Schema( + { + 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_LENGTH, default=10): 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_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): angle, + cv.Optional(CONF_INDICATORS): cv.ensure_list(INDICATOR_SCHEMA), + } +) + +METER_SCHEMA = {cv.Optional(CONF_SCALES): cv.ensure_list(SCALE_SCHEMA)} + + +class MeterType(WidgetType): + def __init__(self): + super().__init__(CONF_METER, lv_meter_t, (CONF_MAIN,), METER_SCHEMA) + + async def to_code(self, w: Widget, config): + """For a meter object, create and set parameters""" + + var = w.obj + for scale_conf in config.get(CONF_SCALES) or (): + rotation = 90 + (360 - scale_conf[CONF_ANGLE_RANGE]) / 2 + if CONF_ROTATION in scale_conf: + rotation = scale_conf[CONF_ROTATION] // 10 + 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], + ticks[CONF_WIDTH], + ticks[CONF_LENGTH], + color, + ) + if CONF_MAJOR in ticks: + major = ticks[CONF_MAJOR] + color = await lv_color.process(major[CONF_COLOR]) + lv.meter_set_scale_major_ticks( + var, + meter_var, + major[CONF_STRIDE], + major[CONF_WIDTH], + major[CONF_LENGTH], + color, + major[CONF_LABEL_GAP], + ) + for indicator in scale_conf.get(CONF_INDICATORS) or (): + (t, v) = next(iter(indicator.items())) + iid = v[CONF_ID] + ivar = cg.new_variable( + iid, cg.nullptr, type_=lv_meter_indicator_t_ptr + ) + # 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, v[CONF_WIDTH], color, 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, v[CONF_WIDTH], color, 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, + color_start, + color_end, + v[CONF_LOCAL], + v[CONF_WIDTH], + ), + ) + 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], + ), + ) + start_value = await get_start_value(v) + end_value = await get_end_value(v) + set_indicator_values(var, ivar, start_value, end_value) + + +meter_spec = MeterType() + + +@automation.register_action( + "lvgl.indicator.update", + ObjUpdateAction, + cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(lv_meter_indicator_t), + cv.Exclusive(CONF_VALUE, CONF_VALUE): lv_float, + cv.Exclusive(CONF_START_VALUE, CONF_VALUE): lv_float, + cv.Optional(CONF_END_VALUE): lv_float, + } + ), +) +async def indicator_update_to_code(config, action_id, template_arg, args): + widget = await get_widgets(config) + start_value = await get_start_value(config) + end_value = await get_end_value(config) + + async def set_value(w: Widget): + set_indicator_values(w.var, w.obj, start_value, end_value) + + return await action_to_code(widget, set_value, action_id, template_arg, args) + + +def set_indicator_values(meter, indicator, start_value, end_value): + 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) diff --git a/esphome/components/lvgl/msgbox.py b/esphome/components/lvgl/msgbox.py new file mode 100644 index 0000000000..6dd529d77f --- /dev/null +++ b/esphome/components/lvgl/msgbox.py @@ -0,0 +1,127 @@ +from esphome import config_validation as cv +from esphome.const import CONF_BUTTON, CONF_ID +from esphome.core import ID +from esphome.cpp_generator import new_Pvariable, static_const_array +from esphome.cpp_types import nullptr + +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 .defines import ( + CONF_BODY, + CONF_BUTTONS, + CONF_CLOSE_BUTTON, + CONF_MSGBOXES, + CONF_TEXT, + CONF_TITLE, + TYPE_FLEX, + literal, +) +from .helpers import add_lv_use +from .label import CONF_LABEL +from .lv_validation import lv_bool, lv_pct, lv_text +from .lvcode import ( + EVENT_ARG, + LambdaContext, + LocalVariable, + lv_add, + lv_assign, + lv_expr, + lv_obj, + lv_Pvariable, +) +from .obj import obj_spec +from .schemas import STYLE_SCHEMA, STYLED_TEXT_SCHEMA, container_schema +from .styles import TOP_LAYER +from .types import LV_EVENT, char_ptr, lv_obj_t +from .widget import Widget, set_obj_properties + +CONF_MSGBOX = "msgbox" +MSGBOX_SCHEMA = container_schema( + obj_spec, + STYLE_SCHEMA.extend( + { + cv.GenerateID(CONF_ID): cv.declare_id(lv_obj_t), + cv.Required(CONF_TITLE): STYLED_TEXT_SCHEMA, + cv.Optional(CONF_BODY): STYLED_TEXT_SCHEMA, + cv.Optional(CONF_BUTTONS): cv.ensure_list(BUTTONMATRIX_BUTTON_SCHEMA), + cv.Optional(CONF_CLOSE_BUTTON): lv_bool, + cv.GenerateID(CONF_BUTTON_TEXT_LIST_ID): cv.declare_id(char_ptr), + } + ), +) + + +async def msgbox_to_code(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 + :param conf: The config data + :return: code to add to the init lambda + """ + add_lv_use( + TYPE_FLEX, + CONF_BUTTON, + CONF_LABEL, + CONF_MSGBOX, + *buttonmatrix_spec.get_uses(), + *button_spec.get_uses(), + ) + mbid = conf[CONF_ID] + outer = lv_Pvariable(lv_obj_t, mbid.id) + btnm = new_Pvariable( + ID(f"{mbid.id}_btnm_", is_declaration=True, type=lv_buttonmatrix_t) + ) + msgbox = lv_Pvariable(lv_obj_t, f"{mbid.id}_msgbox") + outer_w = Widget.create(mbid, outer, obj_spec, conf) + btnm_widg = Widget.create(str(btnm), btnm, buttonmatrix_spec, conf) + text_list, ctrl_list, width_list, _ = await get_button_data((conf,), btnm_widg) + text_id = conf[CONF_BUTTON_TEXT_LIST_ID] + text_list = static_const_array(text_id, text_list) + if (text := conf.get(CONF_BODY)) is not None: + text = await lv_text.process(text.get(CONF_TEXT)) + if (title := conf.get(CONF_TITLE)) is not None: + title = await lv_text.process(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_w.add_flag("LV_OBJ_FLAG_HIDDEN") + lv_assign( + msgbox, lv_expr.msgbox_create(outer, title, text, text_list, close_button) + ) + lv_obj.set_style_align(msgbox, literal("LV_ALIGN_CENTER"), 0) + lv_add(btnm.set_obj(lv_expr.msgbox_get_btns(msgbox))) + await set_obj_properties(outer_w, conf) + if close_button: + async with LambdaContext(EVENT_ARG, where=mbid) as context: + outer_w.add_flag("LV_OBJ_FLAG_HIDDEN") + with LocalVariable( + "close_btn_", lv_obj_t, lv_expr.msgbox_get_close_btn(msgbox) + ) as close_btn: + lv_obj.remove_event_cb(close_btn, nullptr) + lv_obj.add_event_cb( + close_btn, + await context.get_lambda(), + LV_EVENT.CLICKED, + nullptr, + ) + + if len(ctrl_list) != 0 or len(width_list) != 0: + set_btn_data(btnm.obj, ctrl_list, width_list) + + +async def msgboxes_to_code(config): + for conf in config.get(CONF_MSGBOXES, ()): + await msgbox_to_code(conf) diff --git a/esphome/components/lvgl/roller.py b/esphome/components/lvgl/roller.py new file mode 100644 index 0000000000..7af3ef3c3d --- /dev/null +++ b/esphome/components/lvgl/roller.py @@ -0,0 +1,77 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.const import CONF_MODE, CONF_OPTIONS + +from .defines import ( + CONF_ANIMATED, + CONF_MAIN, + CONF_SELECTED, + CONF_SELECTED_INDEX, + CONF_VISIBLE_ROW_COUNT, + ROLLER_MODES, + literal, +) +from .label import CONF_LABEL +from .lv_validation import animated, lv_int, option_string +from .lvcode import lv +from .types import LvSelect +from .widget import WidgetType + +CONF_ROLLER = "roller" +lv_roller_t = LvSelect("lv_roller_t") + +ROLLER_BASE_SCHEMA = cv.Schema( + { + cv.Optional(CONF_SELECTED_INDEX): cv.templatable(cv.int_), + cv.Optional(CONF_VISIBLE_ROW_COUNT): lv_int, + } +) + +ROLLER_SCHEMA = ROLLER_BASE_SCHEMA.extend( + { + cv.Required(CONF_OPTIONS): cv.ensure_list(option_string), + cv.Optional(CONF_MODE, default="NORMAL"): ROLLER_MODES.one_of, + } +) + +ROLLER_MODIFY_SCHEMA = ROLLER_BASE_SCHEMA.extend( + { + cv.Optional(CONF_ANIMATED, default=True): animated, + } +) + + +class RollerType(WidgetType): + def __init__(self): + super().__init__( + CONF_ROLLER, + lv_roller_t, + (CONF_MAIN, CONF_SELECTED), + ROLLER_SCHEMA, + ROLLER_MODIFY_SCHEMA, + ) + + async def to_code(self, w, config): + if options := config.get(CONF_OPTIONS): + mode = await ROLLER_MODES.process(config[CONF_MODE]) + text = cg.safe_exp("\n".join(options)) + lv.roller_set_options(w.obj, text, mode) + animopt = literal(config.get(CONF_ANIMATED) or "LV_ANIM_OFF") + if CONF_SELECTED_INDEX in config: + if selected := config[CONF_SELECTED_INDEX]: + value = await lv_int.process(selected) + lv.roller_set_selected(w.obj, value, animopt) + await w.set_property( + CONF_VISIBLE_ROW_COUNT, + await lv_int.process(config.get(CONF_VISIBLE_ROW_COUNT)), + ) + + @property + def animated(self): + return True + + def get_uses(self): + return (CONF_LABEL,) + + +roller_spec = RollerType() diff --git a/esphome/components/lvgl/spinbox.py b/esphome/components/lvgl/spinbox.py new file mode 100644 index 0000000000..62c58c54a3 --- /dev/null +++ b/esphome/components/lvgl/spinbox.py @@ -0,0 +1,178 @@ +from esphome import automation +import esphome.config_validation as cv +from esphome.const import CONF_ID, CONF_RANGE_FROM, CONF_RANGE_TO, CONF_STEP, CONF_VALUE + +from .automation import action_to_code, update_to_code +from .defines import ( + CONF_CURSOR, + CONF_DECIMAL_PLACES, + CONF_DIGITS, + CONF_MAIN, + CONF_ROLLOVER, + CONF_SCROLLBAR, + CONF_SELECTED, + CONF_TEXTAREA_PLACEHOLDER, +) +from .label import CONF_LABEL +from .lv_validation import lv_bool, lv_float +from .lvcode import lv +from .textarea import CONF_TEXTAREA +from .types import LvNumber, ObjUpdateAction +from .widget import Widget, WidgetType, get_widgets + +CONF_SPINBOX = "spinbox" + +lv_spinbox_t = LvNumber("lv_spinbox_t") + +SPIN_ACTIONS = ( + "INCREMENT", + "DECREMENT", + "STEP_NEXT", + "STEP_PREV", + "CLEAR", +) + + +def validate_spinbox(config): + max_val = 2**31 - 1 + min_val = -1 - max_val + range_from = int(config[CONF_RANGE_FROM]) + range_to = int(config[CONF_RANGE_TO]) + step = int(config[CONF_STEP]) + if ( + range_from > max_val + or range_from < min_val + or range_to > max_val + or range_to < min_val + ): + raise cv.Invalid("Range outside allowed limits") + if step <= 0 or step >= (range_to - range_from) / 2: + raise cv.Invalid("Invalid step value") + if config[CONF_DIGITS] <= config[CONF_DECIMAL_PLACES]: + raise cv.Invalid("Number of digits must exceed number of decimal places") + return config + + +SPINBOX_SCHEMA = cv.Schema( + { + cv.Optional(CONF_VALUE): lv_float, + cv.Optional(CONF_RANGE_FROM, default=0): cv.float_, + cv.Optional(CONF_RANGE_TO, default=100): cv.float_, + cv.Optional(CONF_DIGITS, default=4): cv.int_range(1, 10), + cv.Optional(CONF_STEP, default=1.0): cv.positive_float, + cv.Optional(CONF_DECIMAL_PLACES, default=0): cv.int_range(0, 6), + cv.Optional(CONF_ROLLOVER, default=False): lv_bool, + } +).add_extra(validate_spinbox) + + +SPINBOX_MODIFY_SCHEMA = { + cv.Required(CONF_VALUE): lv_float, +} + + +class SpinboxType(WidgetType): + def __init__(self): + super().__init__( + CONF_SPINBOX, + lv_spinbox_t, + ( + CONF_MAIN, + CONF_SCROLLBAR, + CONF_SELECTED, + CONF_CURSOR, + CONF_TEXTAREA_PLACEHOLDER, + ), + SPINBOX_SCHEMA, + SPINBOX_MODIFY_SCHEMA, + ) + + async def to_code(self, w: Widget, config): + if CONF_DIGITS in config: + digits = config[CONF_DIGITS] + scale = 10 ** config[CONF_DECIMAL_PLACES] + range_from = int(config[CONF_RANGE_FROM]) * scale + range_to = int(config[CONF_RANGE_TO]) * scale + step = int(config[CONF_STEP]) * scale + w.scale = scale + w.step = step + w.range_to = range_to + w.range_from = range_from + lv.spinbox_set_range(w.obj, range_from, range_to) + await w.set_property(CONF_STEP, step) + await w.set_property(CONF_ROLLOVER, config) + lv.spinbox_set_digit_format( + w.obj, digits, digits - config[CONF_DECIMAL_PLACES] + ) + if (value := config.get(CONF_VALUE)) is not None: + lv.spinbox_set_value(w.obj, await lv_float.process(value)) + + def get_scale(self, config): + return 10 ** config[CONF_DECIMAL_PLACES] + + def get_uses(self): + return CONF_TEXTAREA, CONF_LABEL + + def get_max(self, config: dict): + return config[CONF_RANGE_TO] + + def get_min(self, config: dict): + return config[CONF_RANGE_FROM] + + def get_step(self, config: dict): + return config[CONF_STEP] + + +spinbox_spec = SpinboxType() + + +@automation.register_action( + "lvgl.spinbox.increment", + ObjUpdateAction, + cv.maybe_simple_value( + { + cv.Required(CONF_ID): cv.use_id(lv_spinbox_t), + }, + key=CONF_ID, + ), +) +async def spinbox_increment(config, action_id, template_arg, args): + widgets = await get_widgets(config) + + async def do_increment(w: Widget): + lv.spinbox_increment(w.obj) + + return await action_to_code(widgets, do_increment, action_id, template_arg, args) + + +@automation.register_action( + "lvgl.spinbox.decrement", + ObjUpdateAction, + cv.maybe_simple_value( + { + cv.Required(CONF_ID): cv.use_id(lv_spinbox_t), + }, + key=CONF_ID, + ), +) +async def spinbox_decrement(config, action_id, template_arg, args): + widgets = await get_widgets(config) + + async def do_increment(w: Widget): + lv.spinbox_decrement(w.obj) + + return await action_to_code(widgets, do_increment, action_id, template_arg, args) + + +@automation.register_action( + "lvgl.spinbox.update", + ObjUpdateAction, + cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(lv_spinbox_t), + cv.Required(CONF_VALUE): lv_float, + } + ), +) +async def spinbox_update_to_code(config, action_id, template_arg, args): + return await update_to_code(config, action_id, template_arg, args) diff --git a/esphome/components/lvgl/styles.py b/esphome/components/lvgl/styles.py index 7a795bc99d..09f1c376d0 100644 --- a/esphome/components/lvgl/styles.py +++ b/esphome/components/lvgl/styles.py @@ -26,7 +26,7 @@ async def styles_to_code(config): svar = cg.new_Pvariable(style[CONF_ID]) lv.style_init(svar) for prop, validator in ALL_STYLES.items(): - if value := style.get(prop): + if (value := style.get(prop)) is not None: if isinstance(validator, LValidator): value = await validator.process(value) if isinstance(value, list): diff --git a/esphome/components/lvgl/tabview.py b/esphome/components/lvgl/tabview.py new file mode 100644 index 0000000000..7b6a864e21 --- /dev/null +++ b/esphome/components/lvgl/tabview.py @@ -0,0 +1,114 @@ +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 . import buttonmatrix_spec +from .automation import action_to_code +from .defines import ( + CONF_ANIMATED, + CONF_MAIN, + CONF_TAB_ID, + CONF_TABS, + DIRECTIONS, + TYPE_FLEX, + literal, +) +from .lv_validation import animated, lv_int, size +from .lvcode import LocalVariable, lv, lv_assign, lv_expr +from .obj import obj_spec +from .schemas import container_schema, part_schema +from .types import LV_EVENT, LvType, ObjUpdateAction, lv_obj_t, lv_obj_t_ptr +from .widget import Widget, WidgetType, add_widgets, get_widgets, set_obj_properties + +CONF_TABVIEW = "tabview" +CONF_TAB_STYLE = "tab_style" + +lv_tab_t = LvType("lv_obj_t") + +TABVIEW_SCHEMA = cv.Schema( + { + cv.Required(CONF_TABS): cv.ensure_list( + container_schema( + obj_spec, + { + cv.Required(CONF_NAME): cv.string, + cv.GenerateID(): cv.declare_id(lv_tab_t), + }, + ) + ), + cv.Optional(CONF_TAB_STYLE): part_schema(buttonmatrix_spec), + cv.Optional(CONF_POSITION, default="top"): DIRECTIONS.one_of, + cv.Optional(CONF_SIZE, default="10%"): size, + } +) + + +class TabviewType(WidgetType): + def __init__(self): + super().__init__( + CONF_TABVIEW, + LvType( + "lv_tabview_t", + largs=[(lv_obj_t_ptr, "tab")], + lvalue=lambda w: lv_expr.obj_get_child( + lv_expr.tabview_get_content(w.obj), + lv_expr.tabview_get_tab_act(w.obj), + ), + has_on_value=True, + ), + parts=(CONF_MAIN,), + schema=TABVIEW_SCHEMA, + modify_schema={}, + ) + + def get_uses(self): + return "btnmatrix", TYPE_FLEX + + async def to_code(self, w: Widget, config: dict): + 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) + tab_widget = Widget.create(w_id, tab_obj, obj_spec) + 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): + 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) + + def obj_creator(self, parent: MockObjClass, config: dict): + return lv_expr.call( + "tabview_create", + parent, + literal(config[CONF_POSITION]), + literal(config[CONF_SIZE]), + ) + + +tabview_spec = TabviewType() + + +@automation.register_action( + "lvgl.tabview.select", + ObjUpdateAction, + cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(tabview_spec.w_type), + cv.Optional(CONF_ANIMATED, default=False): animated, + cv.Required(CONF_INDEX): lv_int, + }, + ).add_extra(cv.has_at_least_one_key(CONF_INDEX, CONF_TAB_ID)), +) +async def tabview_select(config, action_id, template_arg, args): + widget = await get_widgets(config) + index = config[CONF_INDEX] + + 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) + + return await action_to_code(widget, do_select, action_id, template_arg, args) diff --git a/esphome/components/lvgl/textarea.py b/esphome/components/lvgl/textarea.py new file mode 100644 index 0000000000..d383e1f098 --- /dev/null +++ b/esphome/components/lvgl/textarea.py @@ -0,0 +1,67 @@ +import esphome.config_validation as cv +from esphome.const import CONF_MAX_LENGTH + +from .defines import ( + CONF_ACCEPTED_CHARS, + CONF_CURSOR, + CONF_MAIN, + CONF_ONE_LINE, + CONF_PASSWORD_MODE, + CONF_PLACEHOLDER_TEXT, + CONF_SCROLLBAR, + CONF_SELECTED, + CONF_TEXT, + CONF_TEXTAREA_PLACEHOLDER, +) +from .lv_validation import lv_bool, lv_int, lv_text +from .schemas import TEXT_SCHEMA +from .types import LvText +from .widget import Widget, WidgetType + +CONF_TEXTAREA = "textarea" + +lv_textarea_t = LvText("lv_textarea_t") + +TEXTAREA_SCHEMA = TEXT_SCHEMA.extend( + { + cv.Optional(CONF_PLACEHOLDER_TEXT): lv_text, + cv.Optional(CONF_ACCEPTED_CHARS): lv_text, + cv.Optional(CONF_ONE_LINE): lv_bool, + cv.Optional(CONF_PASSWORD_MODE): lv_bool, + cv.Optional(CONF_MAX_LENGTH): lv_int, + } +) + + +class TextareaType(WidgetType): + def __init__(self): + super().__init__( + CONF_TEXTAREA, + lv_textarea_t, + ( + CONF_MAIN, + CONF_SCROLLBAR, + CONF_SELECTED, + CONF_CURSOR, + CONF_TEXTAREA_PLACEHOLDER, + ), + TEXTAREA_SCHEMA, + ) + + 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: + await w.set_property(prop, await lv_text.process(value)) + await w.set_property( + CONF_MAX_LENGTH, await lv_int.process(config.get(CONF_MAX_LENGTH)) + ) + await w.set_property( + CONF_PASSWORD_MODE, + await lv_bool.process(config.get(CONF_PASSWORD_MODE)), + ) + await w.set_property( + CONF_ONE_LINE, await lv_bool.process(config.get(CONF_ONE_LINE)) + ) + + +textarea_spec = TextareaType() diff --git a/esphome/components/lvgl/tileview.py b/esphome/components/lvgl/tileview.py new file mode 100644 index 0000000000..aa841fa23e --- /dev/null +++ b/esphome/components/lvgl/tileview.py @@ -0,0 +1,128 @@ +from esphome import automation +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.const import CONF_ID, CONF_ON_VALUE, CONF_ROW, CONF_TRIGGER_ID + +from .automation import action_to_code +from .defines import ( + CONF_ANIMATED, + CONF_COLUMN, + CONF_DIR, + CONF_MAIN, + CONF_TILE_ID, + CONF_TILES, + TILE_DIRECTIONS, + literal, +) +from .lv_validation import animated, lv_int +from .lvcode import lv, lv_assign, lv_expr, lv_obj, lv_Pvariable +from .obj import obj_spec +from .schemas import container_schema +from .types import LV_EVENT, LvType, ObjUpdateAction, lv_obj_t, lv_obj_t_ptr +from .widget import Widget, WidgetType, add_widgets, get_widgets, set_obj_properties + +CONF_TILEVIEW = "tileview" + +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"), +) + +tile_spec = WidgetType("lv_tileview_tile_t", lv_tile_t, (CONF_MAIN,), {}) + +TILEVIEW_SCHEMA = cv.Schema( + { + cv.Required(CONF_TILES): cv.ensure_list( + container_schema( + obj_spec, + { + cv.Required(CONF_ROW): lv_int, + cv.Required(CONF_COLUMN): lv_int, + cv.GenerateID(): cv.declare_id(lv_tile_t), + cv.Optional(CONF_DIR, default="ALL"): TILE_DIRECTIONS.several_of, + }, + ) + ), + cv.Optional(CONF_ON_VALUE): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( + automation.Trigger.template(lv_obj_t_ptr) + ) + } + ), + } +) + + +class TileviewType(WidgetType): + def __init__(self): + super().__init__( + CONF_TILEVIEW, + lv_tileview_t, + (CONF_MAIN,), + schema=TILEVIEW_SCHEMA, + modify_schema={}, + ) + + async def to_code(self, w: Widget, config: dict): + for tile_conf in config.get(CONF_TILES) or (): + 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) + lv_assign( + tile_obj, + lv_expr.tileview_add_tile( + w.obj, tile_conf[CONF_COLUMN], tile_conf[CONF_ROW], literal(dirs) + ), + ) + await set_obj_properties(tile, tile_conf) + await add_widgets(tile, tile_conf) + + +tileview_spec = TileviewType() + + +def tile_select_validate(config): + row = CONF_ROW in config + column = CONF_COLUMN in config + tile = CONF_TILE_ID in config + if tile and (row or column) or not tile and not (row and column): + raise cv.Invalid("Specify either a tile id, or both a row and a column") + return config + + +@automation.register_action( + "lvgl.tileview.select", + ObjUpdateAction, + cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(lv_tileview_t), + cv.Optional(CONF_ANIMATED, default=False): animated, + cv.Optional(CONF_ROW): lv_int, + cv.Optional(CONF_COLUMN): lv_int, + cv.Optional(CONF_TILE_ID): cv.use_id(lv_tile_t), + }, + ).add_extra(tile_select_validate), +) +async def tileview_select(config, action_id, template_arg, args): + widgets = await get_widgets(config) + + 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])) + else: + row = await lv_int.process(config[CONF_ROW]) + column = await lv_int.process(config[CONF_COLUMN]) + lv_obj.set_tile_id( + widgets[0].obj, column, row, literal(config[CONF_ANIMATED]) + ) + lv.event_send(w.obj, LV_EVENT.VALUE_CHANGED, cg.nullptr) + + return await action_to_code(widgets, do_select, action_id, template_arg, args) diff --git a/esphome/components/lvgl/widget.py b/esphome/components/lvgl/widget.py index 5734aec7dc..fcaee29085 100644 --- a/esphome/components/lvgl/widget.py +++ b/esphome/components/lvgl/widget.py @@ -282,13 +282,13 @@ async def set_obj_properties(w: Widget, config): lv_obj.set_layout(w.obj, literal(f"LV_LAYOUT_{layout_type.upper()}")) if layout_type == TYPE_GRID: wid = config[CONF_ID] - rows = "{" + ",".join(layout[CONF_GRID_ROWS]) + ", LV_GRID_TEMPLATE_LAST}" + rows = [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 = ( - "{" + ",".join(layout[CONF_GRID_COLUMNS]) + ", LV_GRID_TEMPLATE_LAST}" - ) + columns = [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) diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 726db24592..b7bdbb1f9d 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -39,9 +39,12 @@ #define USE_LOCK #define USE_LOGGER #define USE_LVGL +#define USE_LVGL_ANIMIMG #define USE_LVGL_BINARY_SENSOR +#define USE_LVGL_BUTTONMATRIX #define USE_LVGL_FONT #define USE_LVGL_IMAGE +#define USE_LVGL_KEYBOARD #define USE_LVGL_KEY_LISTENER #define USE_LVGL_TOUCHSCREEN #define USE_LVGL_ROTARY_ENCODER diff --git a/tests/components/lvgl/.gitattributes b/tests/components/lvgl/.gitattributes new file mode 100644 index 0000000000..75e7a44254 --- /dev/null +++ b/tests/components/lvgl/.gitattributes @@ -0,0 +1,2 @@ +*.ttf -text + diff --git a/tests/components/lvgl/common.yaml b/tests/components/lvgl/common.yaml index 8b92f8caa7..6d0c1967b4 100644 --- a/tests/components/lvgl/common.yaml +++ b/tests/components/lvgl/common.yaml @@ -8,3 +8,49 @@ touchscreen: x_max: 240 y_max: 320 +font: + - file: "$component_dir/roboto.ttf" + id: roboto20 + size: 20 + extras: + - file: '$component_dir/materialdesignicons-webfont.ttf' + glyphs: [ + "\U000F004B", + "\U0000f0ed", + "\U000F006E", + "\U000F012C", + "\U000F179B", + "\U000F0748", + "\U000F1A1B", + "\U000F02DC", + "\U000F0A02", + "\U000F035F", + "\U000F0156", + "\U000F0C5F", + "\U000f0084", + "\U000f0091", + ] + - file: "$component_dir/helvetica.ttf" + id: helvetica20 + - file: "$component_dir/roboto.ttf" + id: roboto10 + size: 10 + bpp: 4 + extras: + - file: '$component_dir/materialdesignicons-webfont.ttf' + glyphs: [ + "\U000F004B", + "\U0000f0ed", + "\U000F006E", + "\U000F012C", + "\U000F179B", + "\U000F0748", + "\U000F1A1B", + "\U000F02DC", + "\U000F0A02", + "\U000F035F", + "\U000F0156", + "\U000F0C5F", + "\U000f0084", + "\U000f0091", + ] diff --git a/tests/components/lvgl/helvetica.ttf b/tests/components/lvgl/helvetica.ttf new file mode 100644 index 0000000000000000000000000000000000000000..7aec6f3f3cc74a7138ce350def27a2209b44ad89 GIT binary patch literal 83644 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

y})F$tjs}{ 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�Gn-^3|F$D~HG0GN#m0p3RY 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

f5LEo{ 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


C~-^J9kuf1f~B&vG+GBd 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
-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%0D=QdD>Z6>?g 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 ZcAgz$Pp~K2ZnnEU$(~HkLK9l*e*jr~ZsGs{ literal 0 HcmV?d00001 From 3ba9caa1184687611affb4ce5b4b7378a92c98b3 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 6 Aug 2024 02:50:36 +0100 Subject: [PATCH 1864/2101] socket: socket::set_sockaddr() for IPv4 addresses in IPv6 builds (#7196) --- esphome/components/socket/socket.cpp | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/esphome/components/socket/socket.cpp b/esphome/components/socket/socket.cpp index b200046d7f..5d3528dad8 100644 --- a/esphome/components/socket/socket.cpp +++ b/esphome/components/socket/socket.cpp @@ -19,24 +19,22 @@ std::unique_ptr socket_ip(int type, int protocol) { socklen_t set_sockaddr(struct sockaddr *addr, socklen_t addrlen, const std::string &ip_address, uint16_t port) { #if USE_NETWORK_IPV6 - if (addrlen < sizeof(sockaddr_in6)) { - errno = EINVAL; - return 0; - } - auto *server = reinterpret_cast(addr); - memset(server, 0, sizeof(sockaddr_in6)); - server->sin6_family = AF_INET6; - server->sin6_port = htons(port); + if (ip_address.find(':') != std::string::npos) { + if (addrlen < sizeof(sockaddr_in6)) { + errno = EINVAL; + return 0; + } + auto *server = reinterpret_cast(addr); + memset(server, 0, sizeof(sockaddr_in6)); + server->sin6_family = AF_INET6; + server->sin6_port = htons(port); - if (ip_address.find('.') != std::string::npos) { - server->sin6_addr.un.u32_addr[3] = inet_addr(ip_address.c_str()); - } else { ip6_addr_t ip6; inet6_aton(ip_address.c_str(), &ip6); memcpy(server->sin6_addr.un.u32_addr, ip6.addr, sizeof(ip6.addr)); + return sizeof(sockaddr_in6); } - return sizeof(sockaddr_in6); -#else +#endif /* USE_NETWORK_IPV6 */ if (addrlen < sizeof(sockaddr_in)) { errno = EINVAL; return 0; @@ -47,7 +45,6 @@ socklen_t set_sockaddr(struct sockaddr *addr, socklen_t addrlen, const std::stri server->sin_addr.s_addr = inet_addr(ip_address.c_str()); server->sin_port = htons(port); return sizeof(sockaddr_in); -#endif /* USE_NETWORK_IPV6 */ } socklen_t set_sockaddr_any(struct sockaddr *addr, socklen_t addrlen, uint16_t port) { From 7074fa06ae98c8f42821269b3fcfcce7f052854e Mon Sep 17 00:00:00 2001 From: Nate Clark Date: Mon, 5 Aug 2024 23:53:52 -0400 Subject: [PATCH 1865/2101] Adds MQTT component to Alarm Control panel component (#7188) --- .../alarm_control_panel/__init__.py | 141 ++++++++++-------- esphome/components/mqtt/__init__.py | 21 +-- .../mqtt/mqtt_alarm_control_panel.cpp | 128 ++++++++++++++++ .../mqtt/mqtt_alarm_control_panel.h | 39 +++++ tests/components/mqtt/common.yaml | 6 + 5 files changed, 260 insertions(+), 75 deletions(-) create mode 100644 esphome/components/mqtt/mqtt_alarm_control_panel.cpp create mode 100644 esphome/components/mqtt/mqtt_alarm_control_panel.h diff --git a/esphome/components/alarm_control_panel/__init__.py b/esphome/components/alarm_control_panel/__init__.py index 7ad4358011..8987d708fd 100644 --- a/esphome/components/alarm_control_panel/__init__.py +++ b/esphome/components/alarm_control_panel/__init__.py @@ -1,16 +1,17 @@ -import esphome.codegen as cg -import esphome.config_validation as cv -from esphome.components import web_server from esphome import automation from esphome.automation import maybe_simple_id -from esphome.core import CORE, coroutine_with_priority +import esphome.codegen as cg +from esphome.components import mqtt, web_server +import esphome.config_validation as cv from esphome.const import ( + CONF_CODE, CONF_ID, + CONF_MQTT_ID, CONF_ON_STATE, CONF_TRIGGER_ID, - CONF_CODE, CONF_WEB_SERVER_ID, ) +from esphome.core import CORE, coroutine_with_priority from esphome.cpp_helpers import setup_entity CODEOWNERS = ["@grahambrown11", "@hwstar"] @@ -77,67 +78,72 @@ AlarmControlPanelCondition = alarm_control_panel_ns.class_( "AlarmControlPanelCondition", automation.Condition ) -ALARM_CONTROL_PANEL_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend( - web_server.WEBSERVER_SORTING_SCHEMA -).extend( - { - cv.GenerateID(): cv.declare_id(AlarmControlPanel), - 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), - } - ), - } +ALARM_CONTROL_PANEL_SCHEMA = ( + cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA) + .extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA) + .extend( + { + cv.GenerateID(): cv.declare_id(AlarmControlPanel), + 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), + } + ), + } + ) ) ALARM_CONTROL_PANEL_ACTION_SCHEMA = maybe_simple_id( @@ -192,6 +198,9 @@ async def setup_alarm_control_panel_core_(var, config): if (webserver_id := config.get(CONF_WEB_SERVER_ID)) is not None: web_server_ = await cg.get_variable(webserver_id) web_server.add_entity_to_sorting_list(web_server_, var, config) + if mqtt_id := config.get(CONF_MQTT_ID): + mqtt_ = cg.new_Pvariable(mqtt_id, var) + await mqtt.register_mqtt_component(mqtt_, config) async def register_alarm_control_panel(var, config): diff --git a/esphome/components/mqtt/__init__.py b/esphome/components/mqtt/__init__.py index f4bd34bfd3..240b407819 100644 --- a/esphome/components/mqtt/__init__.py +++ b/esphome/components/mqtt/__init__.py @@ -1,10 +1,11 @@ import re -import esphome.codegen as cg -import esphome.config_validation as cv from esphome import automation from esphome.automation import Condition +import esphome.codegen as cg from esphome.components import logger +from esphome.components.esp32 import add_idf_sdkconfig_option +import esphome.config_validation as cv from esphome.const import ( CONF_AVAILABILITY, CONF_BIRTH_MESSAGE, @@ -13,21 +14,21 @@ from esphome.const import ( CONF_CLIENT_CERTIFICATE, CONF_CLIENT_CERTIFICATE_KEY, CONF_CLIENT_ID, - CONF_COMMAND_TOPIC, CONF_COMMAND_RETAIN, + CONF_COMMAND_TOPIC, CONF_DISCOVERY, + CONF_DISCOVERY_OBJECT_ID_GENERATOR, CONF_DISCOVERY_PREFIX, CONF_DISCOVERY_RETAIN, CONF_DISCOVERY_UNIQUE_ID_GENERATOR, - CONF_DISCOVERY_OBJECT_ID_GENERATOR, CONF_ID, CONF_KEEPALIVE, CONF_LEVEL, CONF_LOG_TOPIC, - CONF_ON_JSON_MESSAGE, - CONF_ON_MESSAGE, CONF_ON_CONNECT, CONF_ON_DISCONNECT, + CONF_ON_JSON_MESSAGE, + CONF_ON_MESSAGE, CONF_PASSWORD, CONF_PAYLOAD, CONF_PAYLOAD_AVAILABLE, @@ -45,12 +46,11 @@ from esphome.const import ( CONF_USE_ABBREVIATIONS, CONF_USERNAME, CONF_WILL_MESSAGE, + PLATFORM_BK72XX, PLATFORM_ESP32, PLATFORM_ESP8266, - PLATFORM_BK72XX, ) -from esphome.core import coroutine_with_priority, CORE -from esphome.components.esp32 import add_idf_sdkconfig_option +from esphome.core import CORE, coroutine_with_priority DEPENDENCIES = ["network"] @@ -110,6 +110,9 @@ MQTTDisconnectTrigger = mqtt_ns.class_( MQTTComponent = mqtt_ns.class_("MQTTComponent", cg.Component) MQTTConnectedCondition = mqtt_ns.class_("MQTTConnectedCondition", Condition) +MQTTAlarmControlPanelComponent = mqtt_ns.class_( + "MQTTAlarmControlPanelComponent", MQTTComponent +) MQTTBinarySensorComponent = mqtt_ns.class_("MQTTBinarySensorComponent", MQTTComponent) MQTTClimateComponent = mqtt_ns.class_("MQTTClimateComponent", MQTTComponent) MQTTCoverComponent = mqtt_ns.class_("MQTTCoverComponent", MQTTComponent) diff --git a/esphome/components/mqtt/mqtt_alarm_control_panel.cpp b/esphome/components/mqtt/mqtt_alarm_control_panel.cpp new file mode 100644 index 0000000000..660a030d11 --- /dev/null +++ b/esphome/components/mqtt/mqtt_alarm_control_panel.cpp @@ -0,0 +1,128 @@ +#include "mqtt_alarm_control_panel.h" +#include "esphome/core/log.h" + +#include "mqtt_const.h" + +#ifdef USE_MQTT +#ifdef USE_ALARM_CONTROL_PANEL + +namespace esphome { +namespace mqtt { + +static const char *const TAG = "mqtt.alarm_control_panel"; + +using namespace esphome::alarm_control_panel; + +MQTTAlarmControlPanelComponent::MQTTAlarmControlPanelComponent(AlarmControlPanel *alarm_control_panel) + : alarm_control_panel_(alarm_control_panel) {} +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) { + call.arm_away(); + } else if (strcasecmp(payload.c_str(), "ARM_HOME") == 0) { + call.arm_home(); + } else if (strcasecmp(payload.c_str(), "ARM_NIGHT") == 0) { + call.arm_night(); + } else if (strcasecmp(payload.c_str(), "ARM_VACATION") == 0) { + call.arm_vacation(); + } else if (strcasecmp(payload.c_str(), "ARM_CUSTOM_BYPASS") == 0) { + call.arm_custom_bypass(); + } else if (strcasecmp(payload.c_str(), "DISARM") == 0) { + call.disarm(); + } else if (strcasecmp(payload.c_str(), "PENDING") == 0) { + call.pending(); + } else if (strcasecmp(payload.c_str(), "TRIGGERED") == 0) { + call.triggered(); + } else { + ESP_LOGW(TAG, "'%s': Received unknown command payload %s", this->friendly_name().c_str(), payload.c_str()); + } + call.perform(); + }); +} + +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) + ESP_LOGCONFIG(TAG, " Supported Features: %" PRIu32, this->alarm_control_panel_->get_supported_features()); + ESP_LOGCONFIG(TAG, " Requires Code to Disarm: %s", YESNO(this->alarm_control_panel_->get_requires_code())); + ESP_LOGCONFIG(TAG, " Requires Code To Arm: %s", YESNO(this->alarm_control_panel_->get_requires_code_to_arm())); +} + +void MQTTAlarmControlPanelComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { + JsonArray supported_features = root.createNestedArray(MQTT_SUPPORTED_FEATURES); + const uint32_t acp_supported_features = this->alarm_control_panel_->get_supported_features(); + if (acp_supported_features & ACP_FEAT_ARM_AWAY) { + supported_features.add("arm_away"); + } + if (acp_supported_features & ACP_FEAT_ARM_HOME) { + supported_features.add("arm_home"); + } + if (acp_supported_features & ACP_FEAT_ARM_NIGHT) { + supported_features.add("arm_night"); + } + if (acp_supported_features & ACP_FEAT_ARM_VACATION) { + supported_features.add("arm_vacation"); + } + if (acp_supported_features & ACP_FEAT_ARM_CUSTOM_BYPASS) { + supported_features.add("arm_custom_bypass"); + } + if (acp_supported_features & ACP_FEAT_TRIGGER) { + supported_features.add("trigger"); + } + root[MQTT_CODE_DISARM_REQUIRED] = this->alarm_control_panel_->get_requires_code(); + root[MQTT_CODE_ARM_REQUIRED] = this->alarm_control_panel_->get_requires_code_to_arm(); +} + +std::string MQTTAlarmControlPanelComponent::component_type() const { return "alarm_control_panel"; } +const EntityBase *MQTTAlarmControlPanelComponent::get_entity() const { return this->alarm_control_panel_; } + +bool MQTTAlarmControlPanelComponent::send_initial_state() { return this->publish_state(); } +bool MQTTAlarmControlPanelComponent::publish_state() { + bool success = true; + 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"; + } + if (!this->publish(this->get_state_topic_(), state_s)) + success = false; + return success; +} + +} // namespace mqtt +} // namespace esphome + +#endif +#endif // USE_MQTT diff --git a/esphome/components/mqtt/mqtt_alarm_control_panel.h b/esphome/components/mqtt/mqtt_alarm_control_panel.h new file mode 100644 index 0000000000..4ad37b7314 --- /dev/null +++ b/esphome/components/mqtt/mqtt_alarm_control_panel.h @@ -0,0 +1,39 @@ +#pragma once + +#include "esphome/core/defines.h" + +#ifdef USE_MQTT +#ifdef USE_ALARM_CONTROL_PANEL + +#include "mqtt_component.h" +#include "esphome/components/alarm_control_panel/alarm_control_panel.h" + +namespace esphome { +namespace mqtt { + +class MQTTAlarmControlPanelComponent : public mqtt::MQTTComponent { + public: + explicit MQTTAlarmControlPanelComponent(alarm_control_panel::AlarmControlPanel *alarm_control_panel); + + void setup() override; + + void send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) override; + + bool send_initial_state() override; + + bool publish_state(); + + void dump_config() override; + + protected: + std::string component_type() const override; + const EntityBase *get_entity() const override; + + alarm_control_panel::AlarmControlPanel *alarm_control_panel_; +}; + +} // namespace mqtt +} // namespace esphome + +#endif +#endif // USE_MQTT diff --git a/tests/components/mqtt/common.yaml b/tests/components/mqtt/common.yaml index a2a751df63..b7d1655ec9 100644 --- a/tests/components/mqtt/common.yaml +++ b/tests/components/mqtt/common.yaml @@ -426,3 +426,9 @@ valve: } else { return VALVE_CLOSED; } + +alarm_control_panel: + - platform: template + name: Alarm Control Panel + binary_sensors: + - input: some_binary_sensor From 71ea2cec1f21d5ea66c84f7bbe2c063a705d063b Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Tue, 6 Aug 2024 13:56:48 +1000 Subject: [PATCH 1866/2101] [lvgl] Final stage (#7184) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/lvgl/__init__.py | 50 ++++++------- esphome/components/lvgl/automation.py | 2 +- .../components/lvgl/binary_sensor/__init__.py | 43 +++++++++++ esphome/components/lvgl/light/__init__.py | 32 +++++++++ esphome/components/lvgl/light/lvgl_light.h | 48 +++++++++++++ esphome/components/lvgl/lvgl_esphome.h | 13 ++-- esphome/components/lvgl/number/__init__.py | 52 ++++++++++++++ esphome/components/lvgl/number/lvgl_number.h | 33 +++++++++ esphome/components/lvgl/rotary_encoders.py | 2 +- esphome/components/lvgl/select/__init__.py | 46 ++++++++++++ esphome/components/lvgl/select/lvgl_select.h | 62 ++++++++++++++++ esphome/components/lvgl/sensor/__init__.py | 35 +++++++++ esphome/components/lvgl/styles.py | 4 +- esphome/components/lvgl/switch/__init__.py | 54 ++++++++++++++ esphome/components/lvgl/switch/lvgl_switch.h | 33 +++++++++ esphome/components/lvgl/text/__init__.py | 39 ++++++++++ esphome/components/lvgl/text/lvgl_text.h | 33 +++++++++ .../components/lvgl/text_sensor/__init__.py | 40 +++++++++++ esphome/components/lvgl/touchscreens.py | 2 +- esphome/components/lvgl/trigger.py | 2 +- .../lvgl/{widget.py => widgets/__init__.py} | 12 ++-- .../components/lvgl/{ => widgets}/animimg.py | 14 ++-- esphome/components/lvgl/{ => widgets}/arc.py | 10 +-- .../components/lvgl/{ => widgets}/button.py | 4 +- .../lvgl/{ => widgets}/buttonmatrix.py | 20 +++--- .../components/lvgl/{ => widgets}/checkbox.py | 12 ++-- .../components/lvgl/{ => widgets}/dropdown.py | 12 ++-- esphome/components/lvgl/{ => widgets}/img.py | 10 +-- .../components/lvgl/{ => widgets}/keyboard.py | 8 +-- .../components/lvgl/{ => widgets}/label.py | 10 +-- esphome/components/lvgl/{ => widgets}/led.py | 10 +-- esphome/components/lvgl/{ => widgets}/line.py | 11 ++- .../components/lvgl/{ => widgets}/lv_bar.py | 12 ++-- .../components/lvgl/{ => widgets}/meter.py | 24 +++---- .../components/lvgl/{ => widgets}/msgbox.py | 72 ++++++++++--------- esphome/components/lvgl/{ => widgets}/obj.py | 8 +-- esphome/components/lvgl/{ => widgets}/page.py | 12 ++-- .../components/lvgl/{ => widgets}/roller.py | 10 +-- .../components/lvgl/{ => widgets}/slider.py | 12 ++-- .../components/lvgl/{ => widgets}/spinbox.py | 12 ++-- .../components/lvgl/{ => widgets}/spinner.py | 10 +-- .../lvgl/{lv_switch.py => widgets/switch.py} | 6 +- .../components/lvgl/{ => widgets}/tabview.py | 16 ++--- .../components/lvgl/{ => widgets}/textarea.py | 10 +-- .../components/lvgl/{ => widgets}/tileview.py | 16 ++--- tests/components/lvgl/common.yaml | 72 +++++++++++++++++++ 46 files changed, 840 insertions(+), 210 deletions(-) create mode 100644 esphome/components/lvgl/binary_sensor/__init__.py create mode 100644 esphome/components/lvgl/light/__init__.py create mode 100644 esphome/components/lvgl/light/lvgl_light.h create mode 100644 esphome/components/lvgl/number/__init__.py create mode 100644 esphome/components/lvgl/number/lvgl_number.h create mode 100644 esphome/components/lvgl/select/__init__.py create mode 100644 esphome/components/lvgl/select/lvgl_select.h create mode 100644 esphome/components/lvgl/sensor/__init__.py create mode 100644 esphome/components/lvgl/switch/__init__.py create mode 100644 esphome/components/lvgl/switch/lvgl_switch.h create mode 100644 esphome/components/lvgl/text/__init__.py create mode 100644 esphome/components/lvgl/text/lvgl_text.h create mode 100644 esphome/components/lvgl/text_sensor/__init__.py rename esphome/components/lvgl/{widget.py => widgets/__init__.py} (98%) rename esphome/components/lvgl/{ => widgets}/animimg.py (89%) rename esphome/components/lvgl/{ => widgets}/arc.py (92%) rename esphome/components/lvgl/{ => widgets}/button.py (82%) rename esphome/components/lvgl/{ => widgets}/buttonmatrix.py (95%) rename esphome/components/lvgl/{ => widgets}/checkbox.py (68%) rename esphome/components/lvgl/{ => widgets}/dropdown.py (89%) rename esphome/components/lvgl/{ => widgets}/img.py (92%) rename esphome/components/lvgl/{ => widgets}/keyboard.py (86%) rename esphome/components/lvgl/{ => widgets}/label.py (85%) rename esphome/components/lvgl/{ => widgets}/led.py (80%) rename esphome/components/lvgl/{ => widgets}/line.py (85%) rename esphome/components/lvgl/{ => widgets}/lv_bar.py (81%) rename esphome/components/lvgl/{ => widgets}/meter.py (96%) rename esphome/components/lvgl/{ => widgets}/msgbox.py (72%) rename esphome/components/lvgl/{ => widgets}/obj.py (76%) rename esphome/components/lvgl/{ => widgets}/page.py (91%) rename esphome/components/lvgl/{ => widgets}/roller.py (92%) rename esphome/components/lvgl/{ => widgets}/slider.py (88%) rename esphome/components/lvgl/{ => widgets}/spinbox.py (95%) rename esphome/components/lvgl/{ => widgets}/spinner.py (82%) rename esphome/components/lvgl/{lv_switch.py => widgets/switch.py} (72%) rename esphome/components/lvgl/{ => widgets}/tabview.py (88%) rename esphome/components/lvgl/{ => widgets}/textarea.py (90%) rename esphome/components/lvgl/{ => widgets}/tileview.py (89%) diff --git a/esphome/components/lvgl/__init__.py b/esphome/components/lvgl/__init__.py index a963fca98b..9eb4665874 100644 --- a/esphome/components/lvgl/__init__.py +++ b/esphome/components/lvgl/__init__.py @@ -21,28 +21,10 @@ from esphome.final_validate import full_config from esphome.helpers import write_file_if_changed from . import defines as df, helpers, lv_validation as lvalid -from .animimg import animimg_spec -from .arc import arc_spec from .automation import disp_update, update_to_code -from .button import button_spec -from .buttonmatrix import buttonmatrix_spec -from .checkbox import checkbox_spec from .defines import CONF_SKIP -from .dropdown import dropdown_spec -from .img import img_spec -from .keyboard import keyboard_spec -from .label import label_spec -from .led import led_spec -from .line import line_spec -from .lv_bar import bar_spec -from .lv_switch import switch_spec from .lv_validation import lv_bool, lv_images_used from .lvcode import LvContext, LvglComponent -from .meter import meter_spec -from .msgbox import MSGBOX_SCHEMA, msgboxes_to_code -from .obj import obj_spec -from .page import add_pages, page_spec -from .roller import roller_spec from .rotary_encoders import ROTARY_ENCODER_CONFIG, rotary_encoders_to_code from .schemas import ( DISP_BG_SCHEMA, @@ -57,13 +39,7 @@ from .schemas import ( grid_alignments, obj_schema, ) -from .slider import slider_spec -from .spinbox import spinbox_spec -from .spinner import spinner_spec from .styles import add_top_layer, styles_to_code, theme_to_code -from .tabview import tabview_spec -from .textarea import textarea_spec -from .tileview import tileview_spec from .touchscreens import touchscreen_schema, touchscreens_to_code from .trigger import generate_triggers from .types import ( @@ -74,7 +50,31 @@ from .types import ( lv_style_t, lvgl_ns, ) -from .widget import Widget, add_widgets, lv_scr_act, set_obj_properties +from .widgets import Widget, add_widgets, lv_scr_act, set_obj_properties +from .widgets.animimg import animimg_spec +from .widgets.arc import arc_spec +from .widgets.button import button_spec +from .widgets.buttonmatrix import buttonmatrix_spec +from .widgets.checkbox import checkbox_spec +from .widgets.dropdown import dropdown_spec +from .widgets.img import img_spec +from .widgets.keyboard import keyboard_spec +from .widgets.label import label_spec +from .widgets.led import led_spec +from .widgets.line import line_spec +from .widgets.lv_bar import bar_spec +from .widgets.meter import meter_spec +from .widgets.msgbox import MSGBOX_SCHEMA, msgboxes_to_code +from .widgets.obj import obj_spec +from .widgets.page import add_pages, page_spec +from .widgets.roller import roller_spec +from .widgets.slider import slider_spec +from .widgets.spinbox import spinbox_spec +from .widgets.spinner import spinner_spec +from .widgets.switch import switch_spec +from .widgets.tabview import tabview_spec +from .widgets.textarea import textarea_spec +from .widgets.tileview import tileview_spec DOMAIN = "lvgl" DEPENDENCIES = ["display"] diff --git a/esphome/components/lvgl/automation.py b/esphome/components/lvgl/automation.py index 7a862fb58b..556e286208 100644 --- a/esphome/components/lvgl/automation.py +++ b/esphome/components/lvgl/automation.py @@ -38,7 +38,7 @@ from .types import ( lv_disp_t, lv_obj_t, ) -from .widget import Widget, get_widgets, lv_scr_act, set_obj_properties +from .widgets import Widget, get_widgets, lv_scr_act, set_obj_properties async def action_to_code( diff --git a/esphome/components/lvgl/binary_sensor/__init__.py b/esphome/components/lvgl/binary_sensor/__init__.py new file mode 100644 index 0000000000..8789a06375 --- /dev/null +++ b/esphome/components/lvgl/binary_sensor/__init__.py @@ -0,0 +1,43 @@ +import esphome.codegen as cg +from esphome.components.binary_sensor import ( + BinarySensor, + binary_sensor_schema, + new_binary_sensor, +) +import esphome.config_validation as cv + +from ..defines import CONF_LVGL_ID, CONF_WIDGET +from ..lvcode import EVENT_ARG, LambdaContext, LvContext +from ..schemas import LVGL_SCHEMA +from ..types import LV_EVENT, lv_pseudo_button_t +from ..widgets import Widget, get_widgets + +CONFIG_SCHEMA = ( + binary_sensor_schema(BinarySensor) + .extend(LVGL_SCHEMA) + .extend( + { + cv.Required(CONF_WIDGET): cv.use_id(lv_pseudo_button_t), + } + ) +) + + +async def to_code(config): + sensor = await new_binary_sensor(config) + paren = await cg.get_variable(config[CONF_LVGL_ID]) + widget = await get_widgets(config, CONF_WIDGET) + widget = widget[0] + assert isinstance(widget, Widget) + async with LambdaContext(EVENT_ARG) as pressed_ctx: + pressed_ctx.add(sensor.publish_state(widget.is_pressed())) + async with LvContext(paren) as ctx: + ctx.add(sensor.publish_initial_state(widget.is_pressed())) + ctx.add( + paren.add_event_cb( + widget.obj, + await pressed_ctx.get_lambda(), + LV_EVENT.PRESSING, + LV_EVENT.RELEASED, + ) + ) diff --git a/esphome/components/lvgl/light/__init__.py b/esphome/components/lvgl/light/__init__.py new file mode 100644 index 0000000000..27c160dff6 --- /dev/null +++ b/esphome/components/lvgl/light/__init__.py @@ -0,0 +1,32 @@ +import esphome.codegen as cg +from esphome.components import light +from esphome.components.light import LightOutput +import esphome.config_validation as cv +from esphome.const import CONF_GAMMA_CORRECT, CONF_LED, CONF_OUTPUT_ID + +from ..defines import CONF_LVGL_ID +from ..lvcode import LvContext +from ..schemas import LVGL_SCHEMA +from ..types import LvType, lvgl_ns +from ..widgets import get_widgets + +lv_led_t = LvType("lv_led_t") +LVLight = lvgl_ns.class_("LVLight", LightOutput) +CONFIG_SCHEMA = light.RGB_LIGHT_SCHEMA.extend( + { + cv.Optional(CONF_GAMMA_CORRECT, default=0.0): cv.positive_float, + cv.Required(CONF_LED): cv.use_id(lv_led_t), + cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(LVLight), + } +).extend(LVGL_SCHEMA) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_OUTPUT_ID]) + await light.register_light(var, config) + + paren = await cg.get_variable(config[CONF_LVGL_ID]) + widget = await get_widgets(config, CONF_LED) + widget = widget[0] + async with LvContext(paren) as ctx: + ctx.add(var.set_obj(widget.obj)) diff --git a/esphome/components/lvgl/light/lvgl_light.h b/esphome/components/lvgl/light/lvgl_light.h new file mode 100644 index 0000000000..67372d89dd --- /dev/null +++ b/esphome/components/lvgl/light/lvgl_light.h @@ -0,0 +1,48 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/components/light/light_output.h" +#include "../lvgl_esphome.h" + +namespace esphome { +namespace lvgl { + +class LVLight : public light::LightOutput { + public: + light::LightTraits get_traits() override { + auto traits = light::LightTraits(); + traits.set_supported_color_modes({light::ColorMode::RGB}); + return traits; + } + void write_state(light::LightState *state) override { + float red, green, blue; + state->current_values_as_rgb(&red, &green, &blue, false); + auto color = lv_color_make(red * 255, green * 255, blue * 255); + if (this->obj_ != nullptr) { + this->set_value_(color); + } else { + this->initial_value_ = color; + } + } + + void set_obj(lv_obj_t *obj) { + this->obj_ = obj; + if (this->initial_value_) { + lv_led_set_color(obj, this->initial_value_.value()); + lv_led_on(obj); + this->initial_value_.reset(); + } + } + + protected: + 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_custom_event, nullptr); + } + lv_obj_t *obj_{}; + optional initial_value_{}; +}; + +} // namespace lvgl +} // namespace esphome diff --git a/esphome/components/lvgl/lvgl_esphome.h b/esphome/components/lvgl/lvgl_esphome.h index 71e0fd069f..5f2f0ea8df 100644 --- a/esphome/components/lvgl/lvgl_esphome.h +++ b/esphome/components/lvgl/lvgl_esphome.h @@ -1,13 +1,6 @@ #pragma once #include "esphome/core/defines.h" -#ifdef USE_LVGL_BINARY_SENSOR -#include "esphome/components/binary_sensor/binary_sensor.h" -#endif // USE_LVGL_BINARY_SENSOR -#ifdef USE_LVGL_ROTARY_ENCODER -#include "esphome/components/rotary_encoder/rotary_encoder.h" -#endif // USE_LVGL_ROTARY_ENCODER - // required for clang-tidy #ifndef LV_CONF_H #define LV_CONF_SKIP 1 // NOLINT @@ -19,6 +12,12 @@ #include "esphome/core/log.h" #include #include + +#ifdef USE_LVGL_ROTARY_ENCODER +#include "esphome/components/binary_sensor/binary_sensor.h" +#include "esphome/components/rotary_encoder/rotary_encoder.h" +#endif // USE_LVGL_ROTARY_ENCODER + #ifdef USE_LVGL_IMAGE #include "esphome/components/image/image.h" #endif // USE_LVGL_IMAGE diff --git a/esphome/components/lvgl/number/__init__.py b/esphome/components/lvgl/number/__init__.py new file mode 100644 index 0000000000..53aef2790d --- /dev/null +++ b/esphome/components/lvgl/number/__init__.py @@ -0,0 +1,52 @@ +import esphome.codegen as cg +from esphome.components import number +import esphome.config_validation as cv +from esphome.cpp_generator import MockObj + +from ..defines import CONF_ANIMATED, CONF_LVGL_ID, CONF_WIDGET +from ..lv_validation import animated +from ..lvcode import CUSTOM_EVENT, EVENT_ARG, LambdaContext, LvContext, lv, lv_add +from ..schemas import LVGL_SCHEMA +from ..types import LV_EVENT, LvNumber, lvgl_ns +from ..widgets import get_widgets + +LVGLNumber = lvgl_ns.class_("LVGLNumber", number.Number) + +CONFIG_SCHEMA = ( + number.number_schema(LVGLNumber) + .extend(LVGL_SCHEMA) + .extend( + { + cv.Required(CONF_WIDGET): cv.use_id(LvNumber), + cv.Optional(CONF_ANIMATED, default=True): animated, + } + ) +) + + +async def to_code(config): + paren = await cg.get_variable(config[CONF_LVGL_ID]) + widget = await get_widgets(config, CONF_WIDGET) + widget = widget[0] + var = await number.new_number( + config, + max_value=widget.get_max(), + min_value=widget.get_min(), + step=widget.get_step(), + ) + + async with LambdaContext([(cg.float_, "v")]) as control: + await widget.set_property( + "value", MockObj("v") * MockObj(widget.get_scale()), config[CONF_ANIMATED] + ) + lv.event_send(widget.obj, CUSTOM_EVENT, cg.nullptr) + async with LambdaContext(EVENT_ARG) as event: + event.add(var.publish_state(widget.get_value())) + async with LvContext(paren): + lv_add(var.set_control_lambda(await control.get_lambda())) + lv_add( + paren.add_event_cb( + widget.obj, await event.get_lambda(), LV_EVENT.VALUE_CHANGED + ) + ) + lv_add(var.publish_state(widget.get_value())) diff --git a/esphome/components/lvgl/number/lvgl_number.h b/esphome/components/lvgl/number/lvgl_number.h new file mode 100644 index 0000000000..461ea51be4 --- /dev/null +++ b/esphome/components/lvgl/number/lvgl_number.h @@ -0,0 +1,33 @@ +#pragma once + +#include "esphome/components/number/number.h" +#include "esphome/core/automation.h" +#include "esphome/core/component.h" +#include "esphome/core/preferences.h" + +namespace esphome { +namespace lvgl { + +class LVGLNumber : public number::Number { + public: + void set_control_lambda(std::function control_lambda) { + this->control_lambda_ = control_lambda; + if (this->initial_state_.has_value()) { + this->control_lambda_(this->initial_state_.value()); + this->initial_state_.reset(); + } + } + + protected: + void control(float value) { + if (this->control_lambda_ != nullptr) + this->control_lambda_(value); + else + this->initial_state_ = value; + } + std::function control_lambda_{}; + optional initial_state_{}; +}; + +} // namespace lvgl +} // namespace esphome diff --git a/esphome/components/lvgl/rotary_encoders.py b/esphome/components/lvgl/rotary_encoders.py index ede6905a67..d8a82dbc78 100644 --- a/esphome/components/lvgl/rotary_encoders.py +++ b/esphome/components/lvgl/rotary_encoders.py @@ -16,7 +16,7 @@ from .helpers import lvgl_components_required from .lvcode import lv, lv_add, lv_expr from .schemas import ENCODER_SCHEMA from .types import lv_indev_type_t -from .widget import add_group +from .widgets import add_group ROTARY_ENCODER_CONFIG = cv.ensure_list( ENCODER_SCHEMA.extend( diff --git a/esphome/components/lvgl/select/__init__.py b/esphome/components/lvgl/select/__init__.py new file mode 100644 index 0000000000..34a70a23f7 --- /dev/null +++ b/esphome/components/lvgl/select/__init__.py @@ -0,0 +1,46 @@ +import esphome.codegen as cg +from esphome.components import select +import esphome.config_validation as cv +from esphome.const import CONF_OPTIONS + +from ..defines import CONF_ANIMATED, CONF_LVGL_ID, CONF_WIDGET +from ..lvcode import CUSTOM_EVENT, EVENT_ARG, LambdaContext, LvContext, lv, lv_add +from ..schemas import LVGL_SCHEMA +from ..types import LV_EVENT, LvSelect, lvgl_ns +from ..widgets import get_widgets + +LVGLSelect = lvgl_ns.class_("LVGLSelect", select.Select) + +CONFIG_SCHEMA = ( + select.select_schema(LVGLSelect) + .extend(LVGL_SCHEMA) + .extend( + { + cv.Required(CONF_WIDGET): cv.use_id(LvSelect), + cv.Optional(CONF_ANIMATED, default=False): cv.boolean, + } + ) +) + + +async def to_code(config): + widget = await get_widgets(config, CONF_WIDGET) + widget = widget[0] + options = widget.config.get(CONF_OPTIONS, []) + selector = await select.new_select(config, options=options) + paren = await cg.get_variable(config[CONF_LVGL_ID]) + async with LambdaContext(EVENT_ARG) as pub_ctx: + pub_ctx.add(selector.publish_index(widget.get_value())) + async with LambdaContext([(cg.uint16, "v")]) as control: + await widget.set_property("selected", "v", animated=config[CONF_ANIMATED]) + lv.event_send(widget.obj, CUSTOM_EVENT, cg.nullptr) + async with LvContext(paren) as ctx: + lv_add(selector.set_control_lambda(await control.get_lambda())) + ctx.add( + paren.add_event_cb( + widget.obj, + await pub_ctx.get_lambda(), + LV_EVENT.VALUE_CHANGED, + ) + ) + lv_add(selector.publish_index(widget.get_value())) diff --git a/esphome/components/lvgl/select/lvgl_select.h b/esphome/components/lvgl/select/lvgl_select.h new file mode 100644 index 0000000000..407045d605 --- /dev/null +++ b/esphome/components/lvgl/select/lvgl_select.h @@ -0,0 +1,62 @@ +#pragma once + +#include "esphome/components/select/select.h" +#include "esphome/core/automation.h" +#include "esphome/core/component.h" +#include "esphome/core/preferences.h" + +namespace esphome { +namespace lvgl { + +static std::vector split_string(const std::string &str) { + std::vector strings; + auto delimiter = std::string("\n"); + + std::string::size_type pos; + std::string::size_type prev = 0; + while ((pos = str.find(delimiter, prev)) != std::string::npos) { + strings.push_back(str.substr(prev, pos - prev)); + prev = pos + delimiter.size(); + } + + // To get the last substring (or only, if delimiter is not found) + strings.push_back(str.substr(prev)); + + return strings; +} + +class LVGLSelect : public select::Select { + public: + void set_control_lambda(std::function lambda) { + this->control_lambda_ = lambda; + if (this->initial_state_.has_value()) { + this->control(this->initial_state_.value()); + this->initial_state_.reset(); + } + } + + void publish_index(size_t index) { + auto value = this->at(index); + if (value) + this->publish_state(value.value()); + } + + void set_options(const char *str) { this->traits.set_options(split_string(str)); } + + protected: + void control(const std::string &value) override { + if (this->control_lambda_ != nullptr) { + auto index = index_of(value); + if (index) + this->control_lambda_(index.value()); + } else { + this->initial_state_ = value.c_str(); + } + } + + std::function control_lambda_{}; + optional initial_state_{}; +}; + +} // namespace lvgl +} // namespace esphome diff --git a/esphome/components/lvgl/sensor/__init__.py b/esphome/components/lvgl/sensor/__init__.py new file mode 100644 index 0000000000..6e495eb685 --- /dev/null +++ b/esphome/components/lvgl/sensor/__init__.py @@ -0,0 +1,35 @@ +import esphome.codegen as cg +from esphome.components.sensor import Sensor, new_sensor, sensor_schema +import esphome.config_validation as cv + +from ..defines import CONF_LVGL_ID, CONF_WIDGET +from ..lvcode import EVENT_ARG, LVGL_COMP_ARG, LambdaContext, LvContext, lv_add +from ..schemas import LVGL_SCHEMA +from ..types import LV_EVENT, LvNumber +from ..widgets import Widget, get_widgets + +CONFIG_SCHEMA = ( + sensor_schema(Sensor) + .extend(LVGL_SCHEMA) + .extend( + { + cv.Required(CONF_WIDGET): cv.use_id(LvNumber), + } + ) +) + + +async def to_code(config): + sensor = await new_sensor(config) + paren = await cg.get_variable(config[CONF_LVGL_ID]) + widget = await get_widgets(config, CONF_WIDGET) + widget = widget[0] + assert isinstance(widget, Widget) + async with LambdaContext(EVENT_ARG) as lamb: + lv_add(sensor.publish_state(widget.get_value())) + async with LvContext(paren, LVGL_COMP_ARG): + lv_add( + paren.add_event_cb( + widget.obj, await lamb.get_lambda(), LV_EVENT.VALUE_CHANGED + ) + ) diff --git a/esphome/components/lvgl/styles.py b/esphome/components/lvgl/styles.py index 09f1c376d0..26c2694a52 100644 --- a/esphome/components/lvgl/styles.py +++ b/esphome/components/lvgl/styles.py @@ -12,10 +12,10 @@ from .defines import ( ) from .helpers import add_lv_use from .lvcode import LambdaContext, LocalVariable, lv, lv_assign, lv_variable -from .obj import obj_spec from .schemas import ALL_STYLES from .types import lv_lambda_t, lv_obj_t, lv_obj_t_ptr -from .widget import Widget, add_widgets, set_obj_properties, theme_widget_map +from .widgets import Widget, add_widgets, set_obj_properties, theme_widget_map +from .widgets.obj import obj_spec TOP_LAYER = literal("lv_disp_get_layer_top(lv_component->get_disp())") diff --git a/esphome/components/lvgl/switch/__init__.py b/esphome/components/lvgl/switch/__init__.py new file mode 100644 index 0000000000..831fa9308b --- /dev/null +++ b/esphome/components/lvgl/switch/__init__.py @@ -0,0 +1,54 @@ +import esphome.codegen as cg +from esphome.components.switch import Switch, new_switch, switch_schema +import esphome.config_validation as cv +from esphome.cpp_generator import MockObj + +from ..defines import CONF_LVGL_ID, CONF_WIDGET +from ..lvcode import ( + CUSTOM_EVENT, + EVENT_ARG, + LambdaContext, + LvConditional, + LvContext, + lv, + lv_add, +) +from ..schemas import LVGL_SCHEMA +from ..types import LV_EVENT, LV_STATE, lv_pseudo_button_t, lvgl_ns +from ..widgets import get_widgets + +LVGLSwitch = lvgl_ns.class_("LVGLSwitch", Switch) +CONFIG_SCHEMA = ( + switch_schema(LVGLSwitch) + .extend(LVGL_SCHEMA) + .extend( + { + cv.Required(CONF_WIDGET): cv.use_id(lv_pseudo_button_t), + } + ) +) + + +async def to_code(config): + switch = await new_switch(config) + paren = await cg.get_variable(config[CONF_LVGL_ID]) + widget = await get_widgets(config, CONF_WIDGET) + widget = widget[0] + async with LambdaContext(EVENT_ARG) as checked_ctx: + checked_ctx.add(switch.publish_state(widget.get_value())) + async with LambdaContext([(cg.bool_, "v")]) as control: + with LvConditional(MockObj("v")) as cond: + widget.add_state(LV_STATE.CHECKED) + cond.else_() + widget.clear_state(LV_STATE.CHECKED) + lv.event_send(widget.obj, CUSTOM_EVENT, cg.nullptr) + async with LvContext(paren) as ctx: + lv_add(switch.set_control_lambda(await control.get_lambda())) + ctx.add( + paren.add_event_cb( + widget.obj, + await checked_ctx.get_lambda(), + LV_EVENT.VALUE_CHANGED, + ) + ) + lv_add(switch.publish_state(widget.get_value())) diff --git a/esphome/components/lvgl/switch/lvgl_switch.h b/esphome/components/lvgl/switch/lvgl_switch.h new file mode 100644 index 0000000000..f20f4ed960 --- /dev/null +++ b/esphome/components/lvgl/switch/lvgl_switch.h @@ -0,0 +1,33 @@ +#pragma once + +#include "esphome/components/switch/switch.h" +#include "esphome/core/automation.h" +#include "esphome/core/component.h" +#include "esphome/core/preferences.h" + +namespace esphome { +namespace lvgl { + +class LVGLSwitch : public switch_::Switch { + public: + void set_control_lambda(std::function state_lambda) { + this->state_lambda_ = state_lambda; + if (this->initial_state_.has_value()) { + this->state_lambda_(this->initial_state_.value()); + this->initial_state_.reset(); + } + } + + protected: + void write_state(bool value) { + if (this->state_lambda_ != nullptr) + this->state_lambda_(value); + else + this->initial_state_ = value; + } + std::function state_lambda_{}; + optional initial_state_{}; +}; + +} // namespace lvgl +} // namespace esphome diff --git a/esphome/components/lvgl/text/__init__.py b/esphome/components/lvgl/text/__init__.py new file mode 100644 index 0000000000..55f1b2b3fc --- /dev/null +++ b/esphome/components/lvgl/text/__init__.py @@ -0,0 +1,39 @@ +import esphome.codegen as cg +from esphome.components import text +from esphome.components.text import new_text +import esphome.config_validation as cv + +from ..defines import CONF_LVGL_ID, CONF_WIDGET +from ..lvcode import CUSTOM_EVENT, EVENT_ARG, LambdaContext, LvContext, lv, lv_add +from ..schemas import LVGL_SCHEMA +from ..types import LV_EVENT, LvText, lvgl_ns +from ..widgets import get_widgets + +LVGLText = lvgl_ns.class_("LVGLText", text.Text) + +CONFIG_SCHEMA = text.TEXT_SCHEMA.extend(LVGL_SCHEMA).extend( + { + cv.GenerateID(): cv.declare_id(LVGLText), + cv.Required(CONF_WIDGET): cv.use_id(LvText), + } +) + + +async def to_code(config): + textvar = await new_text(config) + paren = await cg.get_variable(config[CONF_LVGL_ID]) + widget = await get_widgets(config, CONF_WIDGET) + widget = widget[0] + async with LambdaContext([(cg.std_string, "text_value")]) as control: + await widget.set_property("text", "text_value.c_str())") + lv.event_send(widget.obj, CUSTOM_EVENT, None) + async with LambdaContext(EVENT_ARG) as lamb: + lv_add(textvar.publish_state(widget.get_value())) + async with LvContext(paren): + widget.var.set_control_lambda(await control.get_lambda()) + lv_add( + paren.add_event_cb( + widget.obj, await lamb.get_lambda(), LV_EVENT.VALUE_CHANGED + ) + ) + lv_add(textvar.publish_state(widget.get_value())) diff --git a/esphome/components/lvgl/text/lvgl_text.h b/esphome/components/lvgl/text/lvgl_text.h new file mode 100644 index 0000000000..8dc0281364 --- /dev/null +++ b/esphome/components/lvgl/text/lvgl_text.h @@ -0,0 +1,33 @@ +#pragma once + +#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 control_lambda) { + this->control_lambda_ = control_lambda; + if (this->initial_state_.has_value()) { + this->control_lambda_(this->initial_state_.value()); + this->initial_state_.reset(); + } + } + + protected: + void control(const std::string &value) { + if (this->control_lambda_ != nullptr) + this->control_lambda_(value); + else + this->initial_state_ = value; + } + std::function control_lambda_{}; + optional initial_state_{}; +}; + +} // namespace lvgl +} // namespace esphome diff --git a/esphome/components/lvgl/text_sensor/__init__.py b/esphome/components/lvgl/text_sensor/__init__.py new file mode 100644 index 0000000000..c0f0bc36a8 --- /dev/null +++ b/esphome/components/lvgl/text_sensor/__init__.py @@ -0,0 +1,40 @@ +import esphome.codegen as cg +from esphome.components.text_sensor import ( + TextSensor, + new_text_sensor, + text_sensor_schema, +) +import esphome.config_validation as cv + +from ..defines import CONF_LVGL_ID, CONF_WIDGET +from ..lvcode import EVENT_ARG, LambdaContext, LvContext +from ..schemas import LVGL_SCHEMA +from ..types import LV_EVENT, LvText +from ..widgets import get_widgets + +CONFIG_SCHEMA = ( + text_sensor_schema(TextSensor) + .extend(LVGL_SCHEMA) + .extend( + { + cv.Required(CONF_WIDGET): cv.use_id(LvText), + } + ) +) + + +async def to_code(config): + sensor = await new_text_sensor(config) + paren = await cg.get_variable(config[CONF_LVGL_ID]) + widget = await get_widgets(config, CONF_WIDGET) + widget = widget[0] + async with LambdaContext(EVENT_ARG) as pressed_ctx: + pressed_ctx.add(sensor.publish_state(widget.get_value())) + async with LvContext(paren) as ctx: + ctx.add( + paren.add_event_cb( + widget.obj, + await pressed_ctx.get_lambda(), + LV_EVENT.VALUE_CHANGED, + ) + ) diff --git a/esphome/components/lvgl/touchscreens.py b/esphome/components/lvgl/touchscreens.py index 499b33aa02..292b0873f3 100644 --- a/esphome/components/lvgl/touchscreens.py +++ b/esphome/components/lvgl/touchscreens.py @@ -34,7 +34,7 @@ def touchscreen_schema(config): async def touchscreens_to_code(var, config): - for tconf in config.get(CONF_TOUCHSCREENS) or (): + for tconf in config.get(CONF_TOUCHSCREENS, ()): lvgl_components_required.add(CONF_TOUCHSCREEN) touchscreen = await cg.get_variable(tconf[CONF_TOUCHSCREEN_ID]) lpt = tconf[CONF_LONG_PRESS_TIME].total_milliseconds diff --git a/esphome/components/lvgl/trigger.py b/esphome/components/lvgl/trigger.py index c640c8abd9..df87be718b 100644 --- a/esphome/components/lvgl/trigger.py +++ b/esphome/components/lvgl/trigger.py @@ -13,7 +13,7 @@ from .defines import ( ) from .lvcode import EVENT_ARG, LambdaContext, LvConditional, lv, lv_add from .types import LV_EVENT -from .widget import widget_map +from .widgets import widget_map async def generate_triggers(lv_component): diff --git a/esphome/components/lvgl/widget.py b/esphome/components/lvgl/widgets/__init__.py similarity index 98% rename from esphome/components/lvgl/widget.py rename to esphome/components/lvgl/widgets/__init__.py index fcaee29085..dff43cf257 100644 --- a/esphome/components/lvgl/widget.py +++ b/esphome/components/lvgl/widgets/__init__.py @@ -8,7 +8,7 @@ from esphome.core import ID, TimePeriod from esphome.coroutine import FakeAwaitable from esphome.cpp_generator import AssignmentExpression, CallExpression, MockObj -from .defines import ( +from ..defines import ( CONF_DEFAULT, CONF_FLEX_ALIGN_CROSS, CONF_FLEX_ALIGN_MAIN, @@ -32,8 +32,8 @@ from .defines import ( join_enums, literal, ) -from .helpers import add_lv_use -from .lvcode import ( +from ..helpers import add_lv_use +from ..lvcode import ( LvConditional, add_line_marks, lv, @@ -43,8 +43,8 @@ from .lvcode import ( lv_obj, lv_Pvariable, ) -from .schemas import ALL_STYLES, STYLE_REMAP, WIDGET_TYPES -from .types import ( +from ..schemas import ALL_STYLES, STYLE_REMAP, WIDGET_TYPES +from ..types import ( LV_STATE, LvType, WidgetType, @@ -368,7 +368,7 @@ async def add_widgets(parent: Widget, config: dict): :param config: The configuration :return: """ - for w in config.get(CONF_WIDGETS) or (): + for w in config.get(CONF_WIDGETS, ()): w_type, w_cnfig = next(iter(w.items())) await widget_to_code(w_cnfig, w_type, parent.obj) diff --git a/esphome/components/lvgl/animimg.py b/esphome/components/lvgl/widgets/animimg.py similarity index 89% rename from esphome/components/lvgl/animimg.py rename to esphome/components/lvgl/widgets/animimg.py index ad84713d7f..a973ca0702 100644 --- a/esphome/components/lvgl/animimg.py +++ b/esphome/components/lvgl/widgets/animimg.py @@ -4,15 +4,15 @@ import esphome.config_validation as cv from esphome.const import CONF_DURATION, CONF_ID from esphome.cpp_generator import MockObj -from .automation import action_to_code -from .defines import CONF_AUTO_START, CONF_MAIN, CONF_REPEAT_COUNT, CONF_SRC -from .helpers import lvgl_components_required +from ..automation import action_to_code +from ..defines import CONF_AUTO_START, CONF_MAIN, CONF_REPEAT_COUNT, CONF_SRC +from ..helpers import lvgl_components_required +from ..lv_validation import lv_image, lv_milliseconds +from ..lvcode import lv, lv_expr +from ..types import LvType, ObjUpdateAction, void_ptr +from . import Widget, WidgetType, get_widgets from .img import CONF_IMAGE from .label import CONF_LABEL -from .lv_validation import lv_image, lv_milliseconds -from .lvcode import lv, lv_expr -from .types import LvType, ObjUpdateAction, void_ptr -from .widget import Widget, WidgetType, get_widgets CONF_ANIMIMG = "animimg" CONF_SRC_LIST_ID = "src_list_id" diff --git a/esphome/components/lvgl/arc.py b/esphome/components/lvgl/widgets/arc.py similarity index 92% rename from esphome/components/lvgl/arc.py rename to esphome/components/lvgl/widgets/arc.py index d036464c7a..a6f8918e2f 100644 --- a/esphome/components/lvgl/arc.py +++ b/esphome/components/lvgl/widgets/arc.py @@ -8,7 +8,7 @@ from esphome.const import ( ) from esphome.cpp_types import nullptr -from .defines import ( +from ..defines import ( ARC_MODES, CONF_ADJUSTABLE, CONF_CHANGE_RATE, @@ -19,10 +19,10 @@ from .defines import ( CONF_START_ANGLE, literal, ) -from .lv_validation import angle, get_start_value, lv_float -from .lvcode import lv, lv_obj -from .types import LvNumber, NumberType -from .widget import Widget +from ..lv_validation import angle, get_start_value, lv_float +from ..lvcode import lv, lv_obj +from ..types import LvNumber, NumberType +from . import Widget CONF_ARC = "arc" ARC_SCHEMA = cv.Schema( diff --git a/esphome/components/lvgl/button.py b/esphome/components/lvgl/widgets/button.py similarity index 82% rename from esphome/components/lvgl/button.py rename to esphome/components/lvgl/widgets/button.py index 96329b3fa9..b59884ee67 100644 --- a/esphome/components/lvgl/button.py +++ b/esphome/components/lvgl/widgets/button.py @@ -1,7 +1,7 @@ from esphome.const import CONF_BUTTON -from .defines import CONF_MAIN -from .types import LvBoolean, WidgetType +from ..defines import CONF_MAIN +from ..types import LvBoolean, WidgetType lv_button_t = LvBoolean("lv_btn_t") diff --git a/esphome/components/lvgl/buttonmatrix.py b/esphome/components/lvgl/widgets/buttonmatrix.py similarity index 95% rename from esphome/components/lvgl/buttonmatrix.py rename to esphome/components/lvgl/widgets/buttonmatrix.py index 75ed43f909..274b4de5ab 100644 --- a/esphome/components/lvgl/buttonmatrix.py +++ b/esphome/components/lvgl/widgets/buttonmatrix.py @@ -5,9 +5,8 @@ import esphome.config_validation as cv from esphome.const import CONF_ID, CONF_WIDTH from esphome.cpp_generator import MockObj -from .automation import action_to_code -from .button import lv_button_t -from .defines import ( +from ..automation import action_to_code +from ..defines import ( BUTTONMATRIX_CTRLS, CONF_BUTTONS, CONF_CONTROL, @@ -19,11 +18,11 @@ from .defines import ( CONF_SELECTED, CONF_TEXT, ) -from .helpers import lvgl_components_required -from .lv_validation import key_code, lv_bool -from .lvcode import lv, lv_add, lv_expr -from .schemas import automation_schema -from .types import ( +from ..helpers import lvgl_components_required +from ..lv_validation import key_code, lv_bool +from ..lvcode import lv, lv_add, lv_expr +from ..schemas import automation_schema +from ..types import ( LV_BTNMATRIX_CTRL, LV_STATE, LvBoolean, @@ -33,7 +32,8 @@ from .types import ( char_ptr, lv_pseudo_button_t, ) -from .widget import Widget, WidgetType, get_widgets, widget_map +from . import Widget, WidgetType, get_widgets, widget_map +from .button import lv_button_t CONF_BUTTONMATRIX = "buttonmatrix" CONF_BUTTON_TEXT_LIST_ID = "button_text_list_id" @@ -151,7 +151,7 @@ async def get_button_data(config, buttonmatrix: Widget): width_list = [] key_list = [] for row in config: - for button_conf in row.get(CONF_BUTTONS) or (): + for button_conf in row.get(CONF_BUTTONS, ()): bid = button_conf[CONF_ID] index = len(width_list) MatrixButton.create_button(bid, buttonmatrix, button_conf, index) diff --git a/esphome/components/lvgl/checkbox.py b/esphome/components/lvgl/widgets/checkbox.py similarity index 68% rename from esphome/components/lvgl/checkbox.py rename to esphome/components/lvgl/widgets/checkbox.py index be7b029269..6299a2a6a2 100644 --- a/esphome/components/lvgl/checkbox.py +++ b/esphome/components/lvgl/widgets/checkbox.py @@ -1,9 +1,9 @@ -from .defines import CONF_INDICATOR, CONF_MAIN, CONF_TEXT -from .lv_validation import lv_text -from .lvcode import lv -from .schemas import TEXT_SCHEMA -from .types import LvBoolean -from .widget import Widget, WidgetType +from ..defines import CONF_INDICATOR, CONF_MAIN, CONF_TEXT +from ..lv_validation import lv_text +from ..lvcode import lv +from ..schemas import TEXT_SCHEMA +from ..types import LvBoolean +from . import Widget, WidgetType CONF_CHECKBOX = "checkbox" diff --git a/esphome/components/lvgl/dropdown.py b/esphome/components/lvgl/widgets/dropdown.py similarity index 89% rename from esphome/components/lvgl/dropdown.py rename to esphome/components/lvgl/widgets/dropdown.py index d7bdebaade..dc0346b080 100644 --- a/esphome/components/lvgl/dropdown.py +++ b/esphome/components/lvgl/widgets/dropdown.py @@ -2,7 +2,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.const import CONF_OPTIONS -from .defines import ( +from ..defines import ( CONF_DIR, CONF_INDICATOR, CONF_MAIN, @@ -11,12 +11,12 @@ from .defines import ( DIRECTIONS, literal, ) +from ..lv_validation import lv_int, lv_text, option_string +from ..lvcode import LocalVariable, lv, lv_expr +from ..schemas import part_schema +from ..types import LvSelect, LvType, lv_obj_t +from . import Widget, WidgetType, set_obj_properties from .label import CONF_LABEL -from .lv_validation import lv_int, lv_text, option_string -from .lvcode import LocalVariable, lv, lv_expr -from .schemas import part_schema -from .types import LvSelect, LvType, lv_obj_t -from .widget import Widget, WidgetType, set_obj_properties CONF_DROPDOWN = "dropdown" CONF_DROPDOWN_LIST = "dropdown_list" diff --git a/esphome/components/lvgl/img.py b/esphome/components/lvgl/widgets/img.py similarity index 92% rename from esphome/components/lvgl/img.py rename to esphome/components/lvgl/widgets/img.py index dd962fcf31..59b2c97c63 100644 --- a/esphome/components/lvgl/img.py +++ b/esphome/components/lvgl/widgets/img.py @@ -1,7 +1,7 @@ import esphome.config_validation as cv from esphome.const import CONF_ANGLE, CONF_MODE -from .defines import ( +from ..defines import ( CONF_ANTIALIAS, CONF_MAIN, CONF_OFFSET_X, @@ -12,11 +12,11 @@ from .defines import ( CONF_ZOOM, LvConstant, ) +from ..lv_validation import angle, lv_bool, lv_image, size, zoom +from ..lvcode import lv +from ..types import lv_img_t +from . import Widget, WidgetType from .label import CONF_LABEL -from .lv_validation import angle, lv_bool, lv_image, size, zoom -from .lvcode import lv -from .types import lv_img_t -from .widget import Widget, WidgetType CONF_IMAGE = "image" diff --git a/esphome/components/lvgl/keyboard.py b/esphome/components/lvgl/widgets/keyboard.py similarity index 86% rename from esphome/components/lvgl/keyboard.py rename to esphome/components/lvgl/widgets/keyboard.py index 7ce73d2170..cff322f5af 100644 --- a/esphome/components/lvgl/keyboard.py +++ b/esphome/components/lvgl/widgets/keyboard.py @@ -3,11 +3,11 @@ import esphome.config_validation as cv from esphome.const import CONF_MODE from esphome.cpp_types import std_string -from .defines import CONF_ITEMS, CONF_MAIN, KEYBOARD_MODES, literal -from .helpers import add_lv_use, lvgl_components_required +from ..defines import CONF_ITEMS, CONF_MAIN, KEYBOARD_MODES, literal +from ..helpers import add_lv_use, lvgl_components_required +from ..types import LvCompound, LvType +from . import Widget, WidgetType, get_widgets from .textarea import CONF_TEXTAREA, lv_textarea_t -from .types import LvCompound, LvType -from .widget import Widget, WidgetType, get_widgets CONF_KEYBOARD = "keyboard" diff --git a/esphome/components/lvgl/label.py b/esphome/components/lvgl/widgets/label.py similarity index 85% rename from esphome/components/lvgl/label.py rename to esphome/components/lvgl/widgets/label.py index 6c3e1f4a00..38f688f2b0 100644 --- a/esphome/components/lvgl/label.py +++ b/esphome/components/lvgl/widgets/label.py @@ -1,6 +1,6 @@ import esphome.config_validation as cv -from .defines import ( +from ..defines import ( CONF_LONG_MODE, CONF_MAIN, CONF_RECOLOR, @@ -9,10 +9,10 @@ from .defines import ( CONF_TEXT, LV_LONG_MODES, ) -from .lv_validation import lv_bool, lv_text -from .schemas import TEXT_SCHEMA -from .types import LvText, WidgetType -from .widget import Widget +from ..lv_validation import lv_bool, lv_text +from ..schemas import TEXT_SCHEMA +from ..types import LvText, WidgetType +from . import Widget CONF_LABEL = "label" diff --git a/esphome/components/lvgl/led.py b/esphome/components/lvgl/widgets/led.py similarity index 80% rename from esphome/components/lvgl/led.py rename to esphome/components/lvgl/widgets/led.py index 9b6e819278..647973c9b7 100644 --- a/esphome/components/lvgl/led.py +++ b/esphome/components/lvgl/widgets/led.py @@ -1,11 +1,11 @@ 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 .lvcode import lv -from .types import LvType -from .widget import Widget, WidgetType +from ..defines import CONF_MAIN +from ..lv_validation import lv_brightness, lv_color +from ..lvcode import lv +from ..types import LvType +from . import Widget, WidgetType LED_SCHEMA = cv.Schema( { diff --git a/esphome/components/lvgl/line.py b/esphome/components/lvgl/widgets/line.py similarity index 85% rename from esphome/components/lvgl/line.py rename to esphome/components/lvgl/widgets/line.py index ab50832bbf..8ce4b1965f 100644 --- a/esphome/components/lvgl/line.py +++ b/esphome/components/lvgl/widgets/line.py @@ -3,11 +3,10 @@ import functools import esphome.codegen as cg import esphome.config_validation as cv -from . import defines as df -from .defines import CONF_MAIN, literal -from .lvcode import lv -from .types import LvType -from .widget import Widget, WidgetType +from ..defines import CONF_MAIN, literal +from ..lvcode import lv +from ..types import LvType +from . import Widget, WidgetType CONF_LINE = "line" CONF_POINTS = "points" @@ -32,7 +31,7 @@ def cv_point_list(value): LINE_SCHEMA = { - cv.Required(df.CONF_POINTS): cv_point_list, + cv.Required(CONF_POINTS): cv_point_list, cv.GenerateID(CONF_POINT_LIST_ID): cv.declare_id(lv_point_t), } diff --git a/esphome/components/lvgl/lv_bar.py b/esphome/components/lvgl/widgets/lv_bar.py similarity index 81% rename from esphome/components/lvgl/lv_bar.py rename to esphome/components/lvgl/widgets/lv_bar.py index d5dcff0bf0..57209370c0 100644 --- a/esphome/components/lvgl/lv_bar.py +++ b/esphome/components/lvgl/widgets/lv_bar.py @@ -1,11 +1,13 @@ 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_MAIN, literal -from .lv_validation import animated, get_start_value, lv_float -from .lvcode import lv -from .types import LvNumber, NumberType -from .widget import Widget +from ..defines import BAR_MODES, CONF_ANIMATED, CONF_INDICATOR, CONF_MAIN, literal +from ..lv_validation import animated, get_start_value, lv_float +from ..lvcode import lv +from ..types import LvNumber, NumberType +from . import Widget + +# Note this file cannot be called "bar.py" because that name is disallowed. CONF_BAR = "bar" BAR_MODIFY_SCHEMA = cv.Schema( diff --git a/esphome/components/lvgl/meter.py b/esphome/components/lvgl/widgets/meter.py similarity index 96% rename from esphome/components/lvgl/meter.py rename to esphome/components/lvgl/widgets/meter.py index 1a6bef7c57..7cf154d6f3 100644 --- a/esphome/components/lvgl/meter.py +++ b/esphome/components/lvgl/widgets/meter.py @@ -14,9 +14,8 @@ from esphome.const import ( CONF_WIDTH, ) -from .arc import CONF_ARC -from .automation import action_to_code -from .defines import ( +from ..automation import action_to_code +from ..defines import ( CONF_END_VALUE, CONF_MAIN, CONF_PIVOT_X, @@ -25,10 +24,8 @@ from .defines import ( CONF_START_VALUE, CONF_TICKS, ) -from .helpers import add_lv_use -from .img import CONF_IMAGE -from .line import CONF_LINE -from .lv_validation import ( +from ..helpers import add_lv_use +from ..lv_validation import ( angle, get_end_value, get_start_value, @@ -39,10 +36,13 @@ from .lv_validation import ( requires_component, size, ) -from .lvcode import LocalVariable, lv, lv_assign, lv_expr +from ..lvcode import LocalVariable, lv, lv_assign, lv_expr +from ..types import LvType, ObjUpdateAction +from . import Widget, WidgetType, get_widgets +from .arc import CONF_ARC +from .img import CONF_IMAGE +from .line import CONF_LINE from .obj import obj_spec -from .types import LvType, ObjUpdateAction -from .widget import Widget, WidgetType, get_widgets CONF_ANGLE_RANGE = "angle_range" CONF_COLOR_END = "color_end" @@ -171,7 +171,7 @@ class MeterType(WidgetType): """For a meter object, create and set parameters""" var = w.obj - for scale_conf in config.get(CONF_SCALES) or (): + for scale_conf in config.get(CONF_SCALES, ()): rotation = 90 + (360 - scale_conf[CONF_ANGLE_RANGE]) / 2 if CONF_ROTATION in scale_conf: rotation = scale_conf[CONF_ROTATION] // 10 @@ -208,7 +208,7 @@ class MeterType(WidgetType): color, major[CONF_LABEL_GAP], ) - for indicator in scale_conf.get(CONF_INDICATORS) or (): + for indicator in scale_conf.get(CONF_INDICATORS, ()): (t, v) = next(iter(indicator.items())) iid = v[CONF_ID] ivar = cg.new_variable( diff --git a/esphome/components/lvgl/msgbox.py b/esphome/components/lvgl/widgets/msgbox.py similarity index 72% rename from esphome/components/lvgl/msgbox.py rename to esphome/components/lvgl/widgets/msgbox.py index 6dd529d77f..4ae5be7701 100644 --- a/esphome/components/lvgl/msgbox.py +++ b/esphome/components/lvgl/widgets/msgbox.py @@ -4,16 +4,7 @@ from esphome.core import ID from esphome.cpp_generator import new_Pvariable, static_const_array from esphome.cpp_types import nullptr -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 .defines import ( +from ..defines import ( CONF_BODY, CONF_BUTTONS, CONF_CLOSE_BUTTON, @@ -23,10 +14,9 @@ from .defines import ( TYPE_FLEX, literal, ) -from .helpers import add_lv_use -from .label import CONF_LABEL -from .lv_validation import lv_bool, lv_pct, lv_text -from .lvcode import ( +from ..helpers import add_lv_use +from ..lv_validation import lv_bool, lv_pct, lv_text +from ..lvcode import ( EVENT_ARG, LambdaContext, LocalVariable, @@ -36,11 +26,21 @@ from .lvcode import ( lv_obj, lv_Pvariable, ) +from ..schemas import STYLE_SCHEMA, STYLED_TEXT_SCHEMA, container_schema +from ..styles import TOP_LAYER +from ..types import LV_EVENT, char_ptr, lv_obj_t +from . import Widget, 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 .label import CONF_LABEL from .obj import obj_spec -from .schemas import STYLE_SCHEMA, STYLED_TEXT_SCHEMA, container_schema -from .styles import TOP_LAYER -from .types import LV_EVENT, char_ptr, lv_obj_t -from .widget import Widget, set_obj_properties CONF_MSGBOX = "msgbox" MSGBOX_SCHEMA = container_schema( @@ -73,15 +73,23 @@ async def msgbox_to_code(conf): *buttonmatrix_spec.get_uses(), *button_spec.get_uses(), ) - mbid = conf[CONF_ID] - outer = lv_Pvariable(lv_obj_t, mbid.id) - btnm = new_Pvariable( - ID(f"{mbid.id}_btnm_", is_declaration=True, type=lv_buttonmatrix_t) + messagebox_id = conf[CONF_ID] + outer = lv_Pvariable(lv_obj_t, messagebox_id.id) + buttonmatrix = new_Pvariable( + ID( + f"{messagebox_id.id}_buttonmatrix_", + is_declaration=True, + type=lv_buttonmatrix_t, + ) + ) + msgbox = lv_Pvariable(lv_obj_t, f"{messagebox_id.id}_msgbox") + outer_widget = Widget.create(messagebox_id, outer, obj_spec, conf) + buttonmatrix_widget = Widget.create( + str(buttonmatrix), buttonmatrix, buttonmatrix_spec, conf + ) + text_list, ctrl_list, width_list, _ = await get_button_data( + (conf,), buttonmatrix_widget ) - msgbox = lv_Pvariable(lv_obj_t, f"{mbid.id}_msgbox") - outer_w = Widget.create(mbid, outer, obj_spec, conf) - btnm_widg = Widget.create(str(btnm), btnm, buttonmatrix_spec, conf) - text_list, ctrl_list, width_list, _ = await get_button_data((conf,), btnm_widg) text_id = conf[CONF_BUTTON_TEXT_LIST_ID] text_list = static_const_array(text_id, text_list) if (text := conf.get(CONF_BODY)) is not None: @@ -97,16 +105,16 @@ async def msgbox_to_code(conf): 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_w.add_flag("LV_OBJ_FLAG_HIDDEN") + outer_widget.add_flag("LV_OBJ_FLAG_HIDDEN") lv_assign( msgbox, lv_expr.msgbox_create(outer, title, text, text_list, close_button) ) lv_obj.set_style_align(msgbox, literal("LV_ALIGN_CENTER"), 0) - lv_add(btnm.set_obj(lv_expr.msgbox_get_btns(msgbox))) - await set_obj_properties(outer_w, conf) + lv_add(buttonmatrix.set_obj(lv_expr.msgbox_get_btns(msgbox))) + await set_obj_properties(outer_widget, conf) if close_button: - async with LambdaContext(EVENT_ARG, where=mbid) as context: - outer_w.add_flag("LV_OBJ_FLAG_HIDDEN") + async with LambdaContext(EVENT_ARG, where=messagebox_id) as context: + outer_widget.add_flag("LV_OBJ_FLAG_HIDDEN") with LocalVariable( "close_btn_", lv_obj_t, lv_expr.msgbox_get_close_btn(msgbox) ) as close_btn: @@ -119,7 +127,7 @@ async def msgbox_to_code(conf): ) if len(ctrl_list) != 0 or len(width_list) != 0: - set_btn_data(btnm.obj, ctrl_list, width_list) + set_btn_data(buttonmatrix.obj, ctrl_list, width_list) async def msgboxes_to_code(config): diff --git a/esphome/components/lvgl/obj.py b/esphome/components/lvgl/widgets/obj.py similarity index 76% rename from esphome/components/lvgl/obj.py rename to esphome/components/lvgl/widgets/obj.py index 40d7e55381..20a24c86f6 100644 --- a/esphome/components/lvgl/obj.py +++ b/esphome/components/lvgl/widgets/obj.py @@ -1,9 +1,9 @@ from esphome import automation -from .automation import update_to_code -from .defines import CONF_MAIN, CONF_OBJ -from .schemas import create_modify_schema -from .types import ObjUpdateAction, WidgetType, lv_obj_t +from ..automation import update_to_code +from ..defines import CONF_MAIN, CONF_OBJ +from ..schemas import create_modify_schema +from ..types import ObjUpdateAction, WidgetType, lv_obj_t class ObjType(WidgetType): diff --git a/esphome/components/lvgl/page.py b/esphome/components/lvgl/widgets/page.py similarity index 91% rename from esphome/components/lvgl/page.py rename to esphome/components/lvgl/widgets/page.py index 4566b7eea4..f80d802b33 100644 --- a/esphome/components/lvgl/page.py +++ b/esphome/components/lvgl/widgets/page.py @@ -2,7 +2,7 @@ from esphome import automation, codegen as cg import esphome.config_validation as cv from esphome.const import CONF_ID, CONF_PAGES, CONF_TIME -from .defines import ( +from ..defines import ( CONF_ANIMATION, CONF_LVGL_ID, CONF_PAGE, @@ -10,11 +10,11 @@ from .defines import ( CONF_SKIP, LV_ANIM, ) -from .lv_validation import lv_bool, lv_milliseconds -from .lvcode import LVGL_COMP_ARG, LambdaContext, add_line_marks, lv_add, lvgl_comp -from .schemas import LVGL_SCHEMA -from .types import LvglAction, lv_page_t -from .widget import Widget, WidgetType, add_widgets, set_obj_properties +from ..lv_validation import lv_bool, lv_milliseconds +from ..lvcode import LVGL_COMP_ARG, LambdaContext, add_line_marks, lv_add, lvgl_comp +from ..schemas import LVGL_SCHEMA +from ..types import LvglAction, lv_page_t +from . import Widget, WidgetType, add_widgets, set_obj_properties class PageType(WidgetType): diff --git a/esphome/components/lvgl/roller.py b/esphome/components/lvgl/widgets/roller.py similarity index 92% rename from esphome/components/lvgl/roller.py rename to esphome/components/lvgl/widgets/roller.py index 7af3ef3c3d..50fdf6113c 100644 --- a/esphome/components/lvgl/roller.py +++ b/esphome/components/lvgl/widgets/roller.py @@ -2,7 +2,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.const import CONF_MODE, CONF_OPTIONS -from .defines import ( +from ..defines import ( CONF_ANIMATED, CONF_MAIN, CONF_SELECTED, @@ -11,11 +11,11 @@ from .defines import ( ROLLER_MODES, literal, ) +from ..lv_validation import animated, lv_int, option_string +from ..lvcode import lv +from ..types import LvSelect +from . import WidgetType from .label import CONF_LABEL -from .lv_validation import animated, lv_int, option_string -from .lvcode import lv -from .types import LvSelect -from .widget import WidgetType CONF_ROLLER = "roller" lv_roller_t = LvSelect("lv_roller_t") diff --git a/esphome/components/lvgl/slider.py b/esphome/components/lvgl/widgets/slider.py similarity index 88% rename from esphome/components/lvgl/slider.py rename to esphome/components/lvgl/widgets/slider.py index 1886f79b44..d5017668e4 100644 --- a/esphome/components/lvgl/slider.py +++ b/esphome/components/lvgl/widgets/slider.py @@ -1,7 +1,7 @@ import esphome.config_validation as cv from esphome.const import CONF_MAX_VALUE, CONF_MIN_VALUE, CONF_MODE, CONF_VALUE -from .defines import ( +from ..defines import ( BAR_MODES, CONF_ANIMATED, CONF_INDICATOR, @@ -9,12 +9,12 @@ from .defines import ( CONF_MAIN, literal, ) -from .helpers import add_lv_use +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 .lv_bar import CONF_BAR -from .lv_validation import animated, get_start_value, lv_float -from .lvcode import lv -from .types import LvNumber, NumberType -from .widget import Widget CONF_SLIDER = "slider" SLIDER_MODIFY_SCHEMA = cv.Schema( diff --git a/esphome/components/lvgl/spinbox.py b/esphome/components/lvgl/widgets/spinbox.py similarity index 95% rename from esphome/components/lvgl/spinbox.py rename to esphome/components/lvgl/widgets/spinbox.py index 62c58c54a3..b84dc7cd23 100644 --- a/esphome/components/lvgl/spinbox.py +++ b/esphome/components/lvgl/widgets/spinbox.py @@ -2,8 +2,8 @@ from esphome import automation import esphome.config_validation as cv from esphome.const import CONF_ID, CONF_RANGE_FROM, CONF_RANGE_TO, CONF_STEP, CONF_VALUE -from .automation import action_to_code, update_to_code -from .defines import ( +from ..automation import action_to_code, update_to_code +from ..defines import ( CONF_CURSOR, CONF_DECIMAL_PLACES, CONF_DIGITS, @@ -13,12 +13,12 @@ from .defines import ( CONF_SELECTED, CONF_TEXTAREA_PLACEHOLDER, ) +from ..lv_validation import lv_bool, lv_float +from ..lvcode import lv +from ..types import LvNumber, ObjUpdateAction +from . import Widget, WidgetType, get_widgets from .label import CONF_LABEL -from .lv_validation import lv_bool, lv_float -from .lvcode import lv from .textarea import CONF_TEXTAREA -from .types import LvNumber, ObjUpdateAction -from .widget import Widget, WidgetType, get_widgets CONF_SPINBOX = "spinbox" diff --git a/esphome/components/lvgl/spinner.py b/esphome/components/lvgl/widgets/spinner.py similarity index 82% rename from esphome/components/lvgl/spinner.py rename to esphome/components/lvgl/widgets/spinner.py index 2f798d0fbf..2940feb594 100644 --- a/esphome/components/lvgl/spinner.py +++ b/esphome/components/lvgl/widgets/spinner.py @@ -1,12 +1,12 @@ 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 angle +from ..lvcode import lv_expr +from ..types import LvType +from . import Widget, WidgetType from .arc import CONF_ARC -from .defines import CONF_ARC_LENGTH, CONF_INDICATOR, CONF_MAIN, CONF_SPIN_TIME -from .lv_validation import angle -from .lvcode import lv_expr -from .types import LvType -from .widget import Widget, WidgetType CONF_SPINNER = "spinner" diff --git a/esphome/components/lvgl/lv_switch.py b/esphome/components/lvgl/widgets/switch.py similarity index 72% rename from esphome/components/lvgl/lv_switch.py rename to esphome/components/lvgl/widgets/switch.py index 5db2c2ce38..a7c1356bf2 100644 --- a/esphome/components/lvgl/lv_switch.py +++ b/esphome/components/lvgl/widgets/switch.py @@ -1,6 +1,6 @@ -from .defines import CONF_INDICATOR, CONF_KNOB, CONF_MAIN -from .types import LvBoolean -from .widget import WidgetType +from ..defines import CONF_INDICATOR, CONF_KNOB, CONF_MAIN +from ..types import LvBoolean +from . import WidgetType CONF_SWITCH = "switch" diff --git a/esphome/components/lvgl/tabview.py b/esphome/components/lvgl/widgets/tabview.py similarity index 88% rename from esphome/components/lvgl/tabview.py rename to esphome/components/lvgl/widgets/tabview.py index 7b6a864e21..226fc3f286 100644 --- a/esphome/components/lvgl/tabview.py +++ b/esphome/components/lvgl/widgets/tabview.py @@ -4,9 +4,8 @@ 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 . import buttonmatrix_spec -from .automation import action_to_code -from .defines import ( +from ..automation import action_to_code +from ..defines import ( CONF_ANIMATED, CONF_MAIN, CONF_TAB_ID, @@ -15,12 +14,13 @@ from .defines import ( TYPE_FLEX, literal, ) -from .lv_validation import animated, lv_int, size -from .lvcode import LocalVariable, lv, lv_assign, lv_expr +from ..lv_validation import animated, lv_int, size +from ..lvcode import LocalVariable, lv, lv_assign, lv_expr +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 .buttonmatrix import buttonmatrix_spec from .obj import obj_spec -from .schemas import container_schema, part_schema -from .types import LV_EVENT, LvType, ObjUpdateAction, lv_obj_t, lv_obj_t_ptr -from .widget import Widget, WidgetType, add_widgets, get_widgets, set_obj_properties CONF_TABVIEW = "tabview" CONF_TAB_STYLE = "tab_style" diff --git a/esphome/components/lvgl/textarea.py b/esphome/components/lvgl/widgets/textarea.py similarity index 90% rename from esphome/components/lvgl/textarea.py rename to esphome/components/lvgl/widgets/textarea.py index d383e1f098..61d83dee9c 100644 --- a/esphome/components/lvgl/textarea.py +++ b/esphome/components/lvgl/widgets/textarea.py @@ -1,7 +1,7 @@ import esphome.config_validation as cv from esphome.const import CONF_MAX_LENGTH -from .defines import ( +from ..defines import ( CONF_ACCEPTED_CHARS, CONF_CURSOR, CONF_MAIN, @@ -13,10 +13,10 @@ from .defines import ( CONF_TEXT, CONF_TEXTAREA_PLACEHOLDER, ) -from .lv_validation import lv_bool, lv_int, lv_text -from .schemas import TEXT_SCHEMA -from .types import LvText -from .widget import Widget, WidgetType +from ..lv_validation import lv_bool, lv_int, lv_text +from ..schemas import TEXT_SCHEMA +from ..types import LvText +from . import Widget, WidgetType CONF_TEXTAREA = "textarea" diff --git a/esphome/components/lvgl/tileview.py b/esphome/components/lvgl/widgets/tileview.py similarity index 89% rename from esphome/components/lvgl/tileview.py rename to esphome/components/lvgl/widgets/tileview.py index aa841fa23e..9a426c7daf 100644 --- a/esphome/components/lvgl/tileview.py +++ b/esphome/components/lvgl/widgets/tileview.py @@ -3,8 +3,8 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.const import CONF_ID, CONF_ON_VALUE, CONF_ROW, CONF_TRIGGER_ID -from .automation import action_to_code -from .defines import ( +from ..automation import action_to_code +from ..defines import ( CONF_ANIMATED, CONF_COLUMN, CONF_DIR, @@ -14,12 +14,12 @@ from .defines import ( TILE_DIRECTIONS, literal, ) -from .lv_validation import animated, lv_int -from .lvcode import lv, lv_assign, lv_expr, lv_obj, lv_Pvariable +from ..lv_validation import animated, lv_int +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 +from . import Widget, WidgetType, add_widgets, get_widgets, set_obj_properties from .obj import obj_spec -from .schemas import container_schema -from .types import LV_EVENT, LvType, ObjUpdateAction, lv_obj_t, lv_obj_t_ptr -from .widget import Widget, WidgetType, add_widgets, get_widgets, set_obj_properties CONF_TILEVIEW = "tileview" @@ -68,7 +68,7 @@ class TileviewType(WidgetType): ) async def to_code(self, w: Widget, config: dict): - for tile_conf in config.get(CONF_TILES) or (): + for tile_conf in config.get(CONF_TILES, ()): 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) diff --git a/tests/components/lvgl/common.yaml b/tests/components/lvgl/common.yaml index 6d0c1967b4..35d924d939 100644 --- a/tests/components/lvgl/common.yaml +++ b/tests/components/lvgl/common.yaml @@ -54,3 +54,75 @@ font: "\U000f0084", "\U000f0091", ] + +sensor: + - platform: lvgl + id: lvgl_sensor_id + name: "LVGL Arc Sensor" + widget: lv_arc + - platform: lvgl + widget: slider_id + name: LVGL Slider + - platform: lvgl + widget: bar_id + id: lvgl_bar_sensor + name: LVGL Bar + - platform: lvgl + widget: spinbox_id + name: LVGL Spinbox + +number: + - platform: lvgl + widget: slider_id + name: LVGL Slider + - platform: lvgl + widget: lv_arc + id: lvgl_arc_number + name: LVGL Arc + - platform: lvgl + widget: bar_id + id: lvgl_bar_number + name: LVGL Bar + - platform: lvgl + widget: spinbox_id + id: lvgl_spinbox_number + name: LVGL Spinbox + +light: + - platform: lvgl + name: LVGL LED + id: lv_light + led: lv_led + +binary_sensor: + - platform: lvgl + id: lvgl_pressbutton + name: Pressbutton + widget: spin_up + publish_initial_state: true + - platform: lvgl + name: ButtonMatrix button + widget: button_a + - platform: lvgl + id: switch_d + name: Matrix switch D + widget: button_d + on_click: + then: + - lvgl.page.previous: + animation: move_right + time: 600ms + - platform: lvgl + id: button_checker + name: LVGL button + widget: spin_up + on_state: + then: + - lvgl.checkbox.update: + id: checkbox_id + state: + checked: !lambda return x; + text: Unchecked + - platform: lvgl + name: LVGL checkbox + widget: checkbox_id From e6b1780a31d54b46628c919f90433db4e7681ec4 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 6 Aug 2024 21:39:47 +1200 Subject: [PATCH 1867/2101] Move ``CONF_BACKGROUND_COLOR`` and ``CONF_FOREGROUND_COLOR`` to const.py (#7202) --- .../graphical_display_menu/__init__.py | 17 ++++++++++------- esphome/components/nextion/base_component.py | 13 +++++-------- esphome/const.py | 2 ++ 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/esphome/components/graphical_display_menu/__init__.py b/esphome/components/graphical_display_menu/__init__.py index 1b3ed7f8cd..d7146a7381 100644 --- a/esphome/components/graphical_display_menu/__init__.py +++ b/esphome/components/graphical_display_menu/__init__.py @@ -1,19 +1,22 @@ -import esphome.codegen as cg -import esphome.config_validation as cv -from esphome.components import display, font, color -from esphome.const import CONF_DISPLAY, CONF_ID, CONF_TRIGGER_ID from esphome import automation, core - +import esphome.codegen as cg +from esphome.components import color, display, font from esphome.components.display_menu_base import ( DISPLAY_MENU_BASE_SCHEMA, DisplayMenuComponent, display_menu_to_code, ) +import esphome.config_validation as cv +from esphome.const import ( + CONF_BACKGROUND_COLOR, + CONF_DISPLAY, + CONF_FOREGROUND_COLOR, + CONF_ID, + CONF_TRIGGER_ID, +) CONF_FONT = "font" CONF_MENU_ITEM_VALUE = "menu_item_value" -CONF_FOREGROUND_COLOR = "foreground_color" -CONF_BACKGROUND_COLOR = "background_color" CONF_ON_REDRAW = "on_redraw" graphical_display_menu_ns = cg.esphome_ns.namespace("graphical_display_menu") diff --git a/esphome/components/nextion/base_component.py b/esphome/components/nextion/base_component.py index 784da35371..d12434ec8f 100644 --- a/esphome/components/nextion/base_component.py +++ b/esphome/components/nextion/base_component.py @@ -1,12 +1,11 @@ from string import ascii_letters, digits -import esphome.config_validation as cv + import esphome.codegen as cg from esphome.components import color -from esphome.const import ( - CONF_VISIBLE, -) -from . import CONF_NEXTION_ID -from . import Nextion +import esphome.config_validation as cv +from esphome.const import CONF_BACKGROUND_COLOR, CONF_FOREGROUND_COLOR, CONF_VISIBLE + +from . import CONF_NEXTION_ID, Nextion CONF_VARIABLE_NAME = "variable_name" CONF_COMPONENT_NAME = "component_name" @@ -24,9 +23,7 @@ CONF_WAKE_UP_PAGE = "wake_up_page" CONF_START_UP_PAGE = "start_up_page" CONF_AUTO_WAKE_ON_TOUCH = "auto_wake_on_touch" CONF_WAVE_MAX_LENGTH = "wave_max_length" -CONF_BACKGROUND_COLOR = "background_color" CONF_BACKGROUND_PRESSED_COLOR = "background_pressed_color" -CONF_FOREGROUND_COLOR = "foreground_color" CONF_FOREGROUND_PRESSED_COLOR = "foreground_pressed_color" CONF_FONT_ID = "font_id" CONF_EXIT_REPARSE_ON_START = "exit_reparse_on_start" diff --git a/esphome/const.py b/esphome/const.py index fcb630badd..d7b1f558a1 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -74,6 +74,7 @@ CONF_AWAY = "away" CONF_AWAY_COMMAND_TOPIC = "away_command_topic" CONF_AWAY_CONFIG = "away_config" CONF_AWAY_STATE_TOPIC = "away_state_topic" +CONF_BACKGROUND_COLOR = "background_color" CONF_BACKLIGHT_PIN = "backlight_pin" CONF_BASELINE = "baseline" CONF_BATTERY_LEVEL = "battery_level" @@ -309,6 +310,7 @@ CONF_FLOW = "flow" CONF_FLOW_CONTROL_PIN = "flow_control_pin" CONF_FOR = "for" CONF_FORCE_UPDATE = "force_update" +CONF_FOREGROUND_COLOR = "foreground_color" CONF_FORMALDEHYDE = "formaldehyde" CONF_FORMAT = "format" CONF_FORWARD_ACTIVE_ENERGY = "forward_active_energy" From b0d9800817921fe98f888b296596f3a4ccf39e18 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 6 Aug 2024 22:02:08 +1200 Subject: [PATCH 1868/2101] [helpers] Set default flags of ExternalRAMAllocator to ALLOW_FAILURE (#7201) --- 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 b4ad22b083..3e6fe9433e 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -680,7 +680,7 @@ template class ExternalRAMAllocator { } private: - Flags flags_{Flags::NONE}; + Flags flags_{Flags::ALLOW_FAILURE}; }; /// @} From 9188836f707db9924c95233cb604dbc51a8fa24f Mon Sep 17 00:00:00 2001 From: guillempages Date: Tue, 6 Aug 2024 13:08:06 +0200 Subject: [PATCH 1869/2101] Add runtime online image support (#4710) --- CODEOWNERS | 1 + esphome/components/online_image/__init__.py | 161 ++++++++++ .../components/online_image/image_decoder.cpp | 44 +++ .../components/online_image/image_decoder.h | 112 +++++++ .../components/online_image/online_image.cpp | 275 ++++++++++++++++++ .../components/online_image/online_image.h | 184 ++++++++++++ esphome/components/online_image/png_image.cpp | 68 +++++ esphome/components/online_image/png_image.h | 33 +++ esphome/core/defines.h | 1 + platformio.ini | 1 + .../components/online_image/common-esp32.yaml | 18 ++ .../online_image/common-esp8266.yaml | 18 ++ tests/components/online_image/common.yaml | 37 +++ .../online_image/test.esp32-ard.yaml | 4 + .../online_image/test.esp32-idf.yaml | 4 + 15 files changed, 961 insertions(+) create mode 100644 esphome/components/online_image/__init__.py create mode 100644 esphome/components/online_image/image_decoder.cpp create mode 100644 esphome/components/online_image/image_decoder.h create mode 100644 esphome/components/online_image/online_image.cpp create mode 100644 esphome/components/online_image/online_image.h create mode 100644 esphome/components/online_image/png_image.cpp create mode 100644 esphome/components/online_image/png_image.h create mode 100644 tests/components/online_image/common-esp32.yaml create mode 100644 tests/components/online_image/common-esp8266.yaml create mode 100644 tests/components/online_image/common.yaml create mode 100644 tests/components/online_image/test.esp32-ard.yaml create mode 100644 tests/components/online_image/test.esp32-idf.yaml diff --git a/CODEOWNERS b/CODEOWNERS index d94c34c019..82e6e0ea4b 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -276,6 +276,7 @@ esphome/components/nfc/* @jesserockz @kbx81 esphome/components/noblex/* @AGalfra esphome/components/number/* @esphome/core esphome/components/one_wire/* @ssieb +esphome/components/online_image/* @guillempages esphome/components/ota/* @esphome/core esphome/components/output/* @esphome/core esphome/components/pca6416a/* @Mat931 diff --git a/esphome/components/online_image/__init__.py b/esphome/components/online_image/__init__.py new file mode 100644 index 0000000000..ee5357457a --- /dev/null +++ b/esphome/components/online_image/__init__.py @@ -0,0 +1,161 @@ +import logging + +from esphome import automation +import esphome.codegen as cg +from esphome.components.http_request import CONF_HTTP_REQUEST_ID, HttpRequestComponent +from esphome.components.image import ( + CONF_USE_TRANSPARENCY, + IMAGE_TYPE, + Image_, + validate_cross_dependencies, +) +import esphome.config_validation as cv +from esphome.const import ( + CONF_BUFFER_SIZE, + CONF_FORMAT, + CONF_ID, + CONF_ON_ERROR, + CONF_RESIZE, + CONF_TRIGGER_ID, + CONF_TYPE, + CONF_URL, +) + +AUTO_LOAD = ["image"] +DEPENDENCIES = ["display", "http_request"] +CODEOWNERS = ["@guillempages"] +MULTI_CONF = True + +CONF_ON_DOWNLOAD_FINISHED = "on_download_finished" + +_LOGGER = logging.getLogger(__name__) + +online_image_ns = cg.esphome_ns.namespace("online_image") + +ImageFormat = online_image_ns.enum("ImageFormat") + +FORMAT_PNG = "PNG" + +IMAGE_FORMAT = {FORMAT_PNG: ImageFormat.PNG} # Add new supported formats here + +OnlineImage = online_image_ns.class_("OnlineImage", cg.PollingComponent, Image_) + +# Actions +SetUrlAction = online_image_ns.class_( + "OnlineImageSetUrlAction", automation.Action, cg.Parented.template(OnlineImage) +) +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 = cv.Schema( + { + cv.Required(CONF_ID): cv.declare_id(OnlineImage), + cv.GenerateID(CONF_HTTP_REQUEST_ID): cv.use_id(HttpRequestComponent), + # + # Common image options + # + cv.Optional(CONF_RESIZE): cv.dimensions, + cv.Optional(CONF_TYPE, default="BINARY"): cv.enum(IMAGE_TYPE, upper=True), + # Not setting default here on purpose; the default depends on the image type, + # and thus will be set in the "validate_cross_dependencies" validator. + cv.Optional(CONF_USE_TRANSPARENCY): cv.boolean, + # + # Online Image specific options + # + cv.Required(CONF_URL): cv.url, + cv.Required(CONF_FORMAT): cv.enum(IMAGE_FORMAT, upper=True), + cv.Optional(CONF_BUFFER_SIZE, default=2048): cv.int_range(256, 65536), + 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), + } + ), + } +).extend(cv.polling_component_schema("never")) + +CONFIG_SCHEMA = cv.Schema( + cv.All( + ONLINE_IMAGE_SCHEMA, + validate_cross_dependencies, + cv.require_framework_version( + # esp8266 not supported yet; if enabled in the future, minimum version of 2.7.0 is needed + # esp8266_arduino=cv.Version(2, 7, 0), + esp32_arduino=cv.Version(0, 0, 0), + esp_idf=cv.Version(4, 0, 0), + ), + ) +) + +SET_URL_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.use_id(OnlineImage), + cv.Required(CONF_URL): cv.templatable(cv.url), + } +) + +RELEASE_IMAGE_SCHEMA = automation.maybe_simple_id( + { + cv.GenerateID(): cv.use_id(OnlineImage), + } +) + + +@automation.register_action("online_image.set_url", SetUrlAction, SET_URL_SCHEMA) +@automation.register_action( + "online_image.release", ReleaseImageAction, RELEASE_IMAGE_SCHEMA +) +async def online_image_action_to_code(config, action_id, template_arg, args): + paren = await cg.get_variable(config[CONF_ID]) + var = cg.new_Pvariable(action_id, template_arg, paren) + + if CONF_URL in config: + template_ = await cg.templatable(config[CONF_URL], args, cg.const_char_ptr) + cg.add(var.set_url(template_)) + return var + + +async def to_code(config): + format = config[CONF_FORMAT] + if format in [FORMAT_PNG]: + cg.add_define("USE_ONLINE_IMAGE_PNG_SUPPORT") + cg.add_library("pngle", "1.0.2") + + url = config[CONF_URL] + width, height = config.get(CONF_RESIZE, (0, 0)) + transparent = config[CONF_USE_TRANSPARENCY] + + var = cg.new_Pvariable( + config[CONF_ID], + url, + width, + height, + format, + config[CONF_TYPE], + config[CONF_BUFFER_SIZE], + ) + await cg.register_component(var, config) + await cg.register_parented(var, config[CONF_HTTP_REQUEST_ID]) + + cg.add(var.set_transparency(transparent)) + + for conf in config.get(CONF_ON_DOWNLOAD_FINISHED, []): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + await automation.build_automation(trigger, [], conf) + + for conf in config.get(CONF_ON_ERROR, []): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + await automation.build_automation(trigger, [], conf) diff --git a/esphome/components/online_image/image_decoder.cpp b/esphome/components/online_image/image_decoder.cpp new file mode 100644 index 0000000000..50ec39dfcc --- /dev/null +++ b/esphome/components/online_image/image_decoder.cpp @@ -0,0 +1,44 @@ +#include "image_decoder.h" +#include "online_image.h" + +#include "esphome/core/log.h" + +namespace esphome { +namespace online_image { + +static const char *const TAG = "online_image.decoder"; + +void ImageDecoder::set_size(int width, int height) { + this->image_->resize_(width, height); + this->x_scale_ = static_cast(this->image_->buffer_width_) / width; + this->y_scale_ = static_cast(this->image_->buffer_height_) / height; +} + +void ImageDecoder::draw(int x, int y, int w, int h, const Color &color) { + auto width = std::min(this->image_->buffer_width_, static_cast(std::ceil((x + w) * this->x_scale_))); + auto height = std::min(this->image_->buffer_height_, static_cast(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); + } + } +} + +uint8_t *DownloadBuffer::data(size_t offset) { + if (offset > this->size_) { + ESP_LOGE(TAG, "Tried to access beyond download buffer bounds!!!"); + return this->buffer_; + } + return this->buffer_ + offset; +} + +size_t DownloadBuffer::read(size_t len) { + this->unread_ -= len; + if (this->unread_ > 0) { + memmove(this->data(), this->data(len), this->unread_); + } + return this->unread_; +} + +} // namespace online_image +} // namespace esphome diff --git a/esphome/components/online_image/image_decoder.h b/esphome/components/online_image/image_decoder.h new file mode 100644 index 0000000000..908efab987 --- /dev/null +++ b/esphome/components/online_image/image_decoder.h @@ -0,0 +1,112 @@ +#pragma once +#include "esphome/core/defines.h" +#include "esphome/core/color.h" + +namespace esphome { +namespace online_image { + +class OnlineImage; + +/** + * @brief Class to abstract decoding different image formats. + */ +class ImageDecoder { + public: + /** + * @brief Construct a new Image Decoder object + * + * @param image The image to decode the stream into. + */ + ImageDecoder(OnlineImage *image) : image_(image) {} + virtual ~ImageDecoder() = default; + + /** + * @brief Initialize the decoder. + * + * @param download_size The total number of bytes that need to be download for the image. + */ + virtual void prepare(uint32_t download_size) { this->download_size_ = download_size; } + + /** + * @brief Decode a part of the image. It will try reading from the buffer. + * There is no guarantee that the whole available buffer will be read/decoded; + * the method will return the amount of bytes actually decoded, so that the + * unread content can be moved to the beginning. + * + * @param buffer The buffer to read from. + * @param size The maximum amount of bytes that can be read from the buffer. + * @return int The amount of bytes read. It can be 0 if the buffer does not have enough content to meaningfully + * decode anything, or negative in case of a decoding error. + */ + virtual int decode(uint8_t *buffer, size_t size); + + /** + * @brief Request the image to be resized once the actual dimensions are known. + * Called by the callback functions, to be able to access the parent Image class. + * + * @param width The image's width. + * @param height The image's height. + */ + void set_size(int width, int height); + + /** + * @brief Draw a rectangle on the display_buffer using the defined color. + * Will check the given coordinates for out-of-bounds, and clip the rectangle accordingly. + * In case of binary displays, the color will be converted to binary as well. + * Called by the callback functions, to be able to access the parent Image class. + * + * @param x The left-most coordinate of the rectangle. + * @param y The top-most coordinate of the rectangle. + * @param w The width of the rectangle. + * @param h The height of the rectangle. + * @param color The color to draw the rectangle with. + */ + void draw(int x, int y, int w, int h, const Color &color); + + bool is_finished() const { return this->decoded_bytes_ == this->download_size_; } + + protected: + OnlineImage *image_; + // Initializing to 1, to ensure it is different than initial "decoded_bytes_". + // Will be overwritten anyway once the download size is known. + uint32_t download_size_ = 1; + uint32_t decoded_bytes_ = 0; + double x_scale_ = 1.0; + double y_scale_ = 1.0; +}; + +class DownloadBuffer { + public: + DownloadBuffer(size_t size) : size_(size) { + this->buffer_ = this->allocator_.allocate(size); + this->reset(); + } + + 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; } + + protected: + ExternalRAMAllocator allocator_; + uint8_t *buffer_; + size_t size_; + /** Total number of downloaded bytes not yet read. */ + size_t unread_; +}; + +} // namespace online_image +} // namespace esphome diff --git a/esphome/components/online_image/online_image.cpp b/esphome/components/online_image/online_image.cpp new file mode 100644 index 0000000000..a4cf0158aa --- /dev/null +++ b/esphome/components/online_image/online_image.cpp @@ -0,0 +1,275 @@ +#include "online_image.h" + +#include "esphome/core/log.h" + +static const char *const TAG = "online_image"; + +#include "image_decoder.h" + +#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, + uint32_t download_buffer_size) + : Image(nullptr, 0, 0, type), + buffer_(nullptr), + download_buffer_(download_buffer_size), + format_(format), + fixed_width_(width), + fixed_height_(height) { + this->set_url(url); +} + +void OnlineImage::release() { + if (this->buffer_) { + ESP_LOGD(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->end_connection_(); + } +} + +bool OnlineImage::resize_(int width_in, int height_in) { + int width = this->fixed_width_; + int height = this->fixed_height_; + if (this->auto_resize_()) { + width = width_in; + height = height_in; + if (this->width_ != width && this->height_ != height) { + this->release(); + } + } + if (this->buffer_) { + return false; + } + auto new_size = this->get_buffer_size_(width, height); + ESP_LOGD(TAG, "Allocating new buffer of %d Bytes...", new_size); + delay_microseconds_safe(2000); + this->buffer_ = this->allocator_.allocate(new_size); + if (this->buffer_) { + this->buffer_width_ = width; + this->buffer_height_ = height; + this->width_ = width; + ESP_LOGD(TAG, "New size: (%d, %d)", width, height); + } else { +#if defined(USE_ESP8266) + // NOLINTNEXTLINE(readability-static-accessed-through-instance) + int max_block = ESP.getMaxFreeBlockSize(); +#elif defined(USE_ESP32) + int max_block = heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL); +#else + int max_block = -1; +#endif + ESP_LOGE(TAG, "allocation failed. Biggest block in heap: %d Bytes", max_block); + this->end_connection_(); + return false; + } + return true; +} + +void OnlineImage::update() { + if (this->decoder_) { + ESP_LOGW(TAG, "Image already being updated."); + return; + } else { + ESP_LOGI(TAG, "Updating image"); + } + + this->downloader_ = this->parent_->get(this->url_); + + if (this->downloader_ == nullptr) { + ESP_LOGE(TAG, "Download failed."); + this->end_connection_(); + this->download_error_callback_.call(); + return; + } + + int http_code = this->downloader_->status_code; + if (http_code == HTTP_CODE_NOT_MODIFIED) { + // Image hasn't changed on server. Skip download. + this->end_connection_(); + return; + } + if (http_code != HTTP_CODE_OK) { + ESP_LOGE(TAG, "HTTP result: %d", http_code); + this->end_connection_(); + this->download_error_callback_.call(); + return; + } + + ESP_LOGD(TAG, "Starting download"); + size_t total_size = this->downloader_->content_length; + +#ifdef USE_ONLINE_IMAGE_PNG_SUPPORT + if (this->format_ == ImageFormat::PNG) { + this->decoder_ = esphome::make_unique(this); + } +#endif // ONLINE_IMAGE_PNG_SUPPORT + + if (!this->decoder_) { + ESP_LOGE(TAG, "Could not instantiate decoder. Image format unsupported."); + this->end_connection_(); + this->download_error_callback_.call(); + return; + } + this->decoder_->prepare(total_size); + ESP_LOGI(TAG, "Downloading image"); +} + +void OnlineImage::loop() { + if (!this->decoder_) { + // Not decoding at the moment => nothing to do. + return; + } + if (!this->downloader_ || this->decoder_->is_finished()) { + ESP_LOGD(TAG, "Image fully downloaded"); + this->data_start_ = buffer_; + this->width_ = buffer_width_; + this->height_ = buffer_height_; + this->end_connection_(); + this->download_finished_callback_.call(); + return; + } + if (this->downloader_ == nullptr) { + ESP_LOGE(TAG, "Downloader not instantiated; cannot download"); + return; + } + size_t available = this->download_buffer_.free_capacity(); + if (available) { + 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."); + this->end_connection_(); + this->download_error_callback_.call(); + return; + } + this->download_buffer_.read(fed); + } + } +} + +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; + const uint32_t pos = x + y * width_8; + if ((this->has_transparency() && color.w > 127) || is_color_on(color)) { + this->buffer_[pos / 8u] |= (0x80 >> (pos % 8u)); + } else { + this->buffer_[pos / 8u] &= ~(0x80 >> (pos % 8u)); + } + break; + } + case ImageType::IMAGE_TYPE_GRAYSCALE: { + uint8_t gray = static_cast(0.2125 * color.r + 0.7154 * color.g + 0.0721 * color.b); + if (this->has_transparency()) { + if (gray == 1) { + gray = 0; + } + if (color.w < 0x80) { + gray = 1; + } + } + this->buffer_[pos] = gray; + break; + } + case ImageType::IMAGE_TYPE_RGB565: { + uint16_t col565 = display::ColorUtil::color_to_565(color); + if (this->has_transparency()) { + if (col565 == 0x0020) { + col565 = 0; + } + if (color.w < 0x80) { + col565 = 0x0020; + } + } + this->buffer_[pos + 0] = static_cast((col565 >> 8) & 0xFF); + this->buffer_[pos + 1] = static_cast(col565 & 0xFF); + break; + } + case ImageType::IMAGE_TYPE_RGBA: { + this->buffer_[pos + 0] = color.r; + this->buffer_[pos + 1] = color.g; + this->buffer_[pos + 2] = color.b; + this->buffer_[pos + 3] = color.w; + break; + } + case ImageType::IMAGE_TYPE_RGB24: + default: { + if (this->has_transparency()) { + if (color.b == 1 && color.r == 0 && color.g == 0) { + color.b = 0; + } + if (color.w < 0x80) { + color.r = 0; + color.g = 0; + color.b = 1; + } + } + this->buffer_[pos + 0] = color.r; + this->buffer_[pos + 1] = color.g; + this->buffer_[pos + 2] = color.b; + break; + } + } +} + +void OnlineImage::end_connection_() { + 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.find("http") != 0) || (url.find("://") == std::string::npos)) { + ESP_LOGE(TAG, "URL is invalid and/or must be prefixed with 'http://' or 'https://'"); + return false; + } + return true; +} + +void OnlineImage::add_on_finished_callback(std::function &&callback) { + this->download_finished_callback_.add(std::move(callback)); +} + +void OnlineImage::add_on_error_callback(std::function &&callback) { + this->download_error_callback_.add(std::move(callback)); +} + +} // namespace online_image +} // namespace esphome diff --git a/esphome/components/online_image/online_image.h b/esphome/components/online_image/online_image.h new file mode 100644 index 0000000000..30e97760ea --- /dev/null +++ b/esphome/components/online_image/online_image.h @@ -0,0 +1,184 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/core/defines.h" +#include "esphome/core/helpers.h" +#include "esphome/components/http_request/http_request.h" +#include "esphome/components/image/image.h" + +#include "image_decoder.h" + +namespace esphome { +namespace online_image { + +using t_http_codes = enum { + HTTP_CODE_OK = 200, + HTTP_CODE_NOT_MODIFIED = 304, + 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. Not supported yet. */ + JPEG, + /** PNG format. */ + PNG, +}; + +/** + * @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 Parented { + public: + /** + * @brief Construct a new OnlineImage object. + * + * @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 buffer_size Size of the buffer used to download the image. + */ + OnlineImage(const std::string &url, int width, int height, ImageFormat format, image::ImageType type, + uint32_t buffer_size); + + void update() override; + void loop() override; + + /** Set the URL to download the image from. */ + void set_url(const std::string &url) { + if (this->validate_url_(url)) { + this->url_ = url; + } + } + + /** + * Release the buffer storing the image. The image will need to be downloaded again + * to be able to be displayed. + */ + void release(); + + void add_on_finished_callback(std::function &&callback); + void add_on_error_callback(std::function &&callback); + + protected: + bool validate_url_(const std::string &url); + + using Allocator = ExternalRAMAllocator; + Allocator allocator_{Allocator::Flags::ALLOW_FAILURE}; + + 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 std::ceil(image::image_type_to_bpp(this->type_) * width * height / 8.0); + } + + int get_position_(int x, int y) const { + return ((x + y * this->buffer_width_) * image::image_type_to_bpp(this->type_)) / 8; + } + + ESPHOME_ALWAYS_INLINE bool auto_resize_() const { return this->fixed_width_ == 0 || this->fixed_height_ == 0; } + + bool 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 download_finished_callback_{}; + CallbackManager download_error_callback_{}; + + std::shared_ptr downloader_{nullptr}; + std::unique_ptr decoder_{nullptr}; + + uint8_t *buffer_; + DownloadBuffer download_buffer_; + + const ImageFormat format_; + + std::string url_{""}; + + /** 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_; + /** + * 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_; + + friend void ImageDecoder::set_size(int width, int height); + friend void ImageDecoder::draw(int x, int y, int w, int h, const Color &color); +}; + +template class OnlineImageSetUrlAction : public Action { + public: + OnlineImageSetUrlAction(OnlineImage *parent) : parent_(parent) {} + TEMPLATABLE_VALUE(const char *, url) + void play(Ts... x) override { + this->parent_->set_url(this->url_.value(x...)); + this->parent_->update(); + } + + protected: + OnlineImage *parent_; +}; + +template class OnlineImageReleaseAction : public Action { + public: + OnlineImageReleaseAction(OnlineImage *parent) : parent_(parent) {} + TEMPLATABLE_VALUE(const char *, url) + void play(Ts... x) override { this->parent_->release(); } + + protected: + OnlineImage *parent_; +}; + +class DownloadFinishedTrigger : public Trigger<> { + public: + explicit DownloadFinishedTrigger(OnlineImage *parent) { + parent->add_on_finished_callback([this]() { this->trigger(); }); + } +}; + +class DownloadErrorTrigger : public Trigger<> { + public: + explicit DownloadErrorTrigger(OnlineImage *parent) { + parent->add_on_error_callback([this]() { this->trigger(); }); + } +}; + +} // namespace online_image +} // namespace esphome diff --git a/esphome/components/online_image/png_image.cpp b/esphome/components/online_image/png_image.cpp new file mode 100644 index 0000000000..c8e215a91d --- /dev/null +++ b/esphome/components/online_image/png_image.cpp @@ -0,0 +1,68 @@ +#include "png_image.h" +#ifdef USE_ONLINE_IMAGE_PNG_SUPPORT + +#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"; + +namespace esphome { +namespace online_image { + +/** + * @brief Callback method that will be called by the PNGLE engine when the basic + * data of the image is received (i.e. width and height); + * + * @param pngle The PNGLE object, including the context data. + * @param w The width of the image. + * @param h The height of the image. + */ +static void init_callback(pngle_t *pngle, uint32_t w, uint32_t h) { + PngDecoder *decoder = (PngDecoder *) pngle_get_user_data(pngle); + decoder->set_size(w, h); +} + +/** + * @brief Callback method that will be called by the PNGLE engine when a chunk + * of the image is decoded. + * + * @param pngle The PNGLE object, including the context data. + * @param x The X coordinate to draw the rectangle on. + * @param y The Y coordinate to draw the rectangle on. + * @param w The width of the rectangle to draw. + * @param h The height of the rectangle to draw. + * @param rgba The color to paint the rectangle in. + */ +static void draw_callback(pngle_t *pngle, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint8_t rgba[4]) { + PngDecoder *decoder = (PngDecoder *) pngle_get_user_data(pngle); + Color color(rgba[0], rgba[1], rgba[2], rgba[3]); + decoder->draw(x, y, w, h, color); +} + +void PngDecoder::prepare(uint32_t download_size) { + ImageDecoder::prepare(download_size); + pngle_set_user_data(this->pngle_, this); + pngle_set_init_callback(this->pngle_, init_callback); + pngle_set_draw_callback(this->pngle_, draw_callback); +} + +int HOT PngDecoder::decode(uint8_t *buffer, size_t size) { + if (size < 256 && size < this->download_size_ - this->decoded_bytes_) { + ESP_LOGD(TAG, "Waiting for data"); + return 0; + } + auto fed = pngle_feed(this->pngle_, buffer, size); + if (fed < 0) { + ESP_LOGE(TAG, "Error decoding image: %s", pngle_error(this->pngle_)); + } else { + this->decoded_bytes_ += fed; + } + return fed; +} + +} // namespace online_image +} // namespace esphome + +#endif // USE_ONLINE_IMAGE_PNG_SUPPORT diff --git a/esphome/components/online_image/png_image.h b/esphome/components/online_image/png_image.h new file mode 100644 index 0000000000..a928276dcc --- /dev/null +++ b/esphome/components/online_image/png_image.h @@ -0,0 +1,33 @@ +#pragma once + +#include "image_decoder.h" +#ifdef USE_ONLINE_IMAGE_PNG_SUPPORT +#include + +namespace esphome { +namespace online_image { + +/** + * @brief Image decoder specialization for PNG images. + */ +class PngDecoder : public ImageDecoder { + public: + /** + * @brief Construct a new PNG Decoder object. + * + * @param display The image to decode the stream into. + */ + PngDecoder(OnlineImage *image) : ImageDecoder(image), pngle_(pngle_new()) {} + ~PngDecoder() override { pngle_destroy(this->pngle_); } + + void prepare(uint32_t download_size) override; + int HOT decode(uint8_t *buffer, size_t size) override; + + protected: + pngle_t *pngle_; +}; + +} // namespace online_image +} // namespace esphome + +#endif // USE_ONLINE_IMAGE_PNG_SUPPORT diff --git a/esphome/core/defines.h b/esphome/core/defines.h index b7bdbb1f9d..61a4940d01 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -53,6 +53,7 @@ #define USE_MQTT #define USE_NEXTION_TFT_UPLOAD #define USE_NUMBER +#define USE_ONLINE_IMAGE_PNG_SUPPORT #define USE_OTA #define USE_OTA_PASSWORD #define USE_OTA_STATE_CALLBACK diff --git a/platformio.ini b/platformio.ini index e4f363d650..87a239207f 100644 --- a/platformio.ini +++ b/platformio.ini @@ -40,6 +40,7 @@ lib_deps = wjtje/qr-code-generator-library@1.7.0 ; qr_code functionpointer/arduino-MLX90393@1.0.0 ; mlx90393 pavlodn/HaierProtocol@0.9.31 ; haier + kikuchan98/pngle@1.0.2 ; online_image ; 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 diff --git a/tests/components/online_image/common-esp32.yaml b/tests/components/online_image/common-esp32.yaml new file mode 100644 index 0000000000..8cc50fc3e0 --- /dev/null +++ b/tests/components/online_image/common-esp32.yaml @@ -0,0 +1,18 @@ +<<: !include common.yaml + +spi: + - id: spi_main_lcd + clk_pin: 16 + mosi_pin: 17 + miso_pin: 15 + +display: + - platform: ili9xxx + id: main_lcd + model: ili9342 + cs_pin: 12 + dc_pin: 13 + reset_pin: 21 + lambda: |- + it.fill(Color(0, 0, 0)); + it.image(0, 0, id(online_rgba_image)); diff --git a/tests/components/online_image/common-esp8266.yaml b/tests/components/online_image/common-esp8266.yaml new file mode 100644 index 0000000000..01e3467413 --- /dev/null +++ b/tests/components/online_image/common-esp8266.yaml @@ -0,0 +1,18 @@ +<<: !include common.yaml + +spi: + - id: spi_main_lcd + clk_pin: 14 + mosi_pin: 13 + miso_pin: 12 + +display: + - platform: ili9xxx + id: main_lcd + model: ili9342 + cs_pin: 15 + dc_pin: 3 + reset_pin: 1 + lambda: |- + it.fill(Color(0, 0, 0)); + it.image(0, 0, id(online_rgba_image)); diff --git a/tests/components/online_image/common.yaml b/tests/components/online_image/common.yaml new file mode 100644 index 0000000000..8f7ea6238b --- /dev/null +++ b/tests/components/online_image/common.yaml @@ -0,0 +1,37 @@ +wifi: + ssid: MySSID + password: password1 + +# Purposely test that `online_image:` does auto-load `image:` +# Keep the `image:` undefined. +# image: +online_image: + - id: online_binary_image + url: http://www.libpng.org/pub/png/img_png/pnglogo-blk-tiny.png + format: PNG + type: BINARY + resize: 50x50 + - id: online_binary_transparent_image + url: http://www.libpng.org/pub/png/img_png/pnglogo-blk-tiny.png + type: TRANSPARENT_BINARY + format: png + - id: online_rgba_image + url: http://www.libpng.org/pub/png/img_png/pnglogo-blk-tiny.png + format: PNG + type: RGBA + - id: online_rgb24_image + url: http://www.libpng.org/pub/png/img_png/pnglogo-blk-tiny.png + format: PNG + type: RGB24 + use_transparency: true + +# Check the set_url action +time: + - platform: sntp + on_time: + - at: "13:37:42" + then: + - online_image.set_url: + id: online_rgba_image + url: http://www.example.org/example.png + diff --git a/tests/components/online_image/test.esp32-ard.yaml b/tests/components/online_image/test.esp32-ard.yaml new file mode 100644 index 0000000000..4111cbd0ad --- /dev/null +++ b/tests/components/online_image/test.esp32-ard.yaml @@ -0,0 +1,4 @@ +<<: !include common-esp32.yaml + +http_request: + verify_ssl: false diff --git a/tests/components/online_image/test.esp32-idf.yaml b/tests/components/online_image/test.esp32-idf.yaml new file mode 100644 index 0000000000..3f01009812 --- /dev/null +++ b/tests/components/online_image/test.esp32-idf.yaml @@ -0,0 +1,4 @@ +<<: !include common-esp32.yaml + +http_request: + From 455df35e50c5c83cdaf46e79156ee203b03dce3a Mon Sep 17 00:00:00 2001 From: Mimoja Date: Tue, 6 Aug 2024 13:17:02 +0200 Subject: [PATCH 1870/2101] Update i2s_audio_speaker.cppi2s_audio/speaker: Fix fallthrough compiler warning (#7167) --- esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp index 6b07ecb1b6..1c6c50d8c9 100644 --- a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +++ b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp @@ -233,6 +233,7 @@ void I2SAudioSpeaker::loop() { switch (this->state_) { case speaker::STATE_STARTING: this->start_(); + [[fallthrough]]; case speaker::STATE_RUNNING: case speaker::STATE_STOPPING: this->watch_(); From 8667f51cf08f1147cf02f56bd882beab837317ba Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 7 Aug 2024 07:15:15 +1200 Subject: [PATCH 1871/2101] Move CONF_ITEMS/CONF_FONT/CONF_TEXT to const.py (#7204) --- .../components/display_menu_base/__init__.py | 29 ++++++++++--------- .../graphical_display_menu/__init__.py | 2 +- esphome/components/lvgl/defines.py | 3 +- esphome/components/lvgl/schemas.py | 5 ++-- esphome/components/lvgl/types.py | 4 +-- .../components/lvgl/widgets/buttonmatrix.py | 4 +-- esphome/components/lvgl/widgets/checkbox.py | 4 ++- esphome/components/lvgl/widgets/keyboard.py | 4 +-- esphome/components/lvgl/widgets/label.py | 2 +- esphome/components/lvgl/widgets/msgbox.py | 3 +- esphome/components/lvgl/widgets/textarea.py | 3 +- esphome/const.py | 3 ++ 12 files changed, 34 insertions(+), 32 deletions(-) diff --git a/esphome/components/display_menu_base/__init__.py b/esphome/components/display_menu_base/__init__.py index 0c738ba838..8ae9cbc2a4 100644 --- a/esphome/components/display_menu_base/__init__.py +++ b/esphome/components/display_menu_base/__init__.py @@ -1,23 +1,26 @@ import re -import esphome.codegen as cg -import esphome.config_validation as cv + from esphome import automation, core +from esphome.automation import maybe_simple_id +import esphome.codegen as cg +from esphome.components.number import Number +from esphome.components.select import Select +from esphome.components.switch import Switch +import esphome.config_validation as cv from esphome.const import ( - CONF_ID, - CONF_TYPE, - CONF_TRIGGER_ID, - CONF_ON_VALUE, + CONF_ACTIVE, CONF_COMMAND, CONF_CUSTOM, - CONF_NUMBER, CONF_FORMAT, + CONF_ID, + CONF_ITEMS, CONF_MODE, - CONF_ACTIVE, + CONF_NUMBER, + CONF_ON_VALUE, + CONF_TEXT, + CONF_TRIGGER_ID, + CONF_TYPE, ) -from esphome.automation import maybe_simple_id -from esphome.components.select import Select -from esphome.components.number import Number -from esphome.components.switch import Switch CODEOWNERS = ["@numo68"] @@ -29,10 +32,8 @@ CONF_JOYSTICK = "joystick" CONF_LABEL = "label" CONF_MENU = "menu" CONF_BACK = "back" -CONF_TEXT = "text" CONF_SELECT = "select" CONF_SWITCH = "switch" -CONF_ITEMS = "items" CONF_ON_TEXT = "on_text" CONF_OFF_TEXT = "off_text" CONF_VALUE_LAMBDA = "value_lambda" diff --git a/esphome/components/graphical_display_menu/__init__.py b/esphome/components/graphical_display_menu/__init__.py index d7146a7381..f4d59b22b8 100644 --- a/esphome/components/graphical_display_menu/__init__.py +++ b/esphome/components/graphical_display_menu/__init__.py @@ -10,12 +10,12 @@ import esphome.config_validation as cv from esphome.const import ( CONF_BACKGROUND_COLOR, CONF_DISPLAY, + CONF_FONT, CONF_FOREGROUND_COLOR, CONF_ID, CONF_TRIGGER_ID, ) -CONF_FONT = "font" CONF_MENU_ITEM_VALUE = "menu_item_value" CONF_ON_REDRAW = "on_redraw" diff --git a/esphome/components/lvgl/defines.py b/esphome/components/lvgl/defines.py index ac28f9ed5f..1b41b32c90 100644 --- a/esphome/components/lvgl/defines.py +++ b/esphome/components/lvgl/defines.py @@ -5,6 +5,7 @@ Constants already defined in esphome.const are not duplicated here and must be i """ from esphome import codegen as cg, config_validation as cv +from esphome.const import CONF_ITEMS from esphome.core import ID, Lambda from esphome.cpp_generator import MockObj from esphome.cpp_types import uint32 @@ -115,7 +116,6 @@ CONF_SCROLLBAR = "scrollbar" CONF_INDICATOR = "indicator" CONF_KNOB = "knob" CONF_SELECTED = "selected" -CONF_ITEMS = "items" CONF_TICKS = "ticks" CONF_CURSOR = "cursor" CONF_TEXTAREA_PLACEHOLDER = "textarea_placeholder" @@ -460,7 +460,6 @@ CONF_SKIP = "skip" CONF_SYMBOL = "symbol" CONF_TAB_ID = "tab_id" CONF_TABS = "tabs" -CONF_TEXT = "text" CONF_TILE = "tile" CONF_TILE_ID = "tile_id" CONF_TILES = "tiles" diff --git a/esphome/components/lvgl/schemas.py b/esphome/components/lvgl/schemas.py index 796783890d..62536bf4d5 100644 --- a/esphome/components/lvgl/schemas.py +++ b/esphome/components/lvgl/schemas.py @@ -7,6 +7,7 @@ from esphome.const import ( CONF_ID, CONF_ON_VALUE, CONF_STATE, + CONF_TEXT, CONF_TRIGGER_ID, CONF_TYPE, ) @@ -25,7 +26,7 @@ WIDGET_TYPES: dict = {} # A schema for text properties TEXT_SCHEMA = cv.Schema( { - cv.Optional(df.CONF_TEXT): cv.Any( + cv.Optional(CONF_TEXT): cv.Any( cv.All( cv.Schema( { @@ -330,7 +331,7 @@ DISP_BG_SCHEMA = cv.Schema( # A style schema that can include text STYLED_TEXT_SCHEMA = cv.maybe_simple_value( - STYLE_SCHEMA.extend(TEXT_SCHEMA), key=df.CONF_TEXT + STYLE_SCHEMA.extend(TEXT_SCHEMA), key=CONF_TEXT ) # For use by platform components diff --git a/esphome/components/lvgl/types.py b/esphome/components/lvgl/types.py index b6f65c8c1b..be17cf62c2 100644 --- a/esphome/components/lvgl/types.py +++ b/esphome/components/lvgl/types.py @@ -1,10 +1,10 @@ import sys from esphome import automation, codegen as cg -from esphome.const import CONF_MAX_VALUE, CONF_MIN_VALUE, CONF_VALUE +from esphome.const import CONF_MAX_VALUE, CONF_MIN_VALUE, CONF_TEXT, CONF_VALUE from esphome.cpp_generator import MockObj, MockObjClass -from .defines import CONF_TEXT, lvgl_ns +from .defines import lvgl_ns from .lvcode import lv_expr diff --git a/esphome/components/lvgl/widgets/buttonmatrix.py b/esphome/components/lvgl/widgets/buttonmatrix.py index 274b4de5ab..e61c5e3477 100644 --- a/esphome/components/lvgl/widgets/buttonmatrix.py +++ b/esphome/components/lvgl/widgets/buttonmatrix.py @@ -2,7 +2,7 @@ from esphome import automation import esphome.codegen as cg from esphome.components.key_provider import KeyProvider import esphome.config_validation as cv -from esphome.const import CONF_ID, CONF_WIDTH +from esphome.const import CONF_ID, CONF_ITEMS, CONF_TEXT, CONF_WIDTH from esphome.cpp_generator import MockObj from ..automation import action_to_code @@ -10,13 +10,11 @@ from ..defines import ( BUTTONMATRIX_CTRLS, CONF_BUTTONS, CONF_CONTROL, - CONF_ITEMS, CONF_KEY_CODE, CONF_MAIN, CONF_ONE_CHECKED, CONF_ROWS, CONF_SELECTED, - CONF_TEXT, ) from ..helpers import lvgl_components_required from ..lv_validation import key_code, lv_bool diff --git a/esphome/components/lvgl/widgets/checkbox.py b/esphome/components/lvgl/widgets/checkbox.py index 6299a2a6a2..79c60a8669 100644 --- a/esphome/components/lvgl/widgets/checkbox.py +++ b/esphome/components/lvgl/widgets/checkbox.py @@ -1,4 +1,6 @@ -from ..defines import CONF_INDICATOR, CONF_MAIN, CONF_TEXT +from esphome.const import CONF_TEXT + +from ..defines import CONF_INDICATOR, CONF_MAIN from ..lv_validation import lv_text from ..lvcode import lv from ..schemas import TEXT_SCHEMA diff --git a/esphome/components/lvgl/widgets/keyboard.py b/esphome/components/lvgl/widgets/keyboard.py index cff322f5af..ba7edb302e 100644 --- a/esphome/components/lvgl/widgets/keyboard.py +++ b/esphome/components/lvgl/widgets/keyboard.py @@ -1,9 +1,9 @@ from esphome.components.key_provider import KeyProvider import esphome.config_validation as cv -from esphome.const import CONF_MODE +from esphome.const import CONF_ITEMS, CONF_MODE from esphome.cpp_types import std_string -from ..defines import CONF_ITEMS, CONF_MAIN, KEYBOARD_MODES, literal +from ..defines import CONF_MAIN, KEYBOARD_MODES, literal from ..helpers import add_lv_use, lvgl_components_required from ..types import LvCompound, LvType from . import Widget, WidgetType, get_widgets diff --git a/esphome/components/lvgl/widgets/label.py b/esphome/components/lvgl/widgets/label.py index 38f688f2b0..6b04235674 100644 --- a/esphome/components/lvgl/widgets/label.py +++ b/esphome/components/lvgl/widgets/label.py @@ -1,4 +1,5 @@ import esphome.config_validation as cv +from esphome.const import CONF_TEXT from ..defines import ( CONF_LONG_MODE, @@ -6,7 +7,6 @@ from ..defines import ( CONF_RECOLOR, CONF_SCROLLBAR, CONF_SELECTED, - CONF_TEXT, LV_LONG_MODES, ) from ..lv_validation import lv_bool, lv_text diff --git a/esphome/components/lvgl/widgets/msgbox.py b/esphome/components/lvgl/widgets/msgbox.py index 4ae5be7701..63c4326c7c 100644 --- a/esphome/components/lvgl/widgets/msgbox.py +++ b/esphome/components/lvgl/widgets/msgbox.py @@ -1,5 +1,5 @@ from esphome import config_validation as cv -from esphome.const import CONF_BUTTON, CONF_ID +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_types import nullptr @@ -9,7 +9,6 @@ from ..defines import ( CONF_BUTTONS, CONF_CLOSE_BUTTON, CONF_MSGBOXES, - CONF_TEXT, CONF_TITLE, TYPE_FLEX, literal, diff --git a/esphome/components/lvgl/widgets/textarea.py b/esphome/components/lvgl/widgets/textarea.py index 61d83dee9c..23d50b3894 100644 --- a/esphome/components/lvgl/widgets/textarea.py +++ b/esphome/components/lvgl/widgets/textarea.py @@ -1,5 +1,5 @@ import esphome.config_validation as cv -from esphome.const import CONF_MAX_LENGTH +from esphome.const import CONF_MAX_LENGTH, CONF_TEXT from ..defines import ( CONF_ACCEPTED_CHARS, @@ -10,7 +10,6 @@ from ..defines import ( CONF_PLACEHOLDER_TEXT, CONF_SCROLLBAR, CONF_SELECTED, - CONF_TEXT, CONF_TEXTAREA_PLACEHOLDER, ) from ..lv_validation import lv_bool, lv_int, lv_text diff --git a/esphome/const.py b/esphome/const.py index d7b1f558a1..13559ecf95 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -308,6 +308,7 @@ CONF_FLASH_LENGTH = "flash_length" CONF_FLASH_TRANSITION_LENGTH = "flash_transition_length" CONF_FLOW = "flow" CONF_FLOW_CONTROL_PIN = "flow_control_pin" +CONF_FONT = "font" CONF_FOR = "for" CONF_FORCE_UPDATE = "force_update" CONF_FOREGROUND_COLOR = "foreground_color" @@ -407,6 +408,7 @@ CONF_INVERTED = "inverted" CONF_IP_ADDRESS = "ip_address" CONF_IRQ_PIN = "irq_pin" CONF_IS_RGBW = "is_rgbw" +CONF_ITEMS = "items" CONF_JS_INCLUDE = "js_include" CONF_JS_URL = "js_url" CONF_JVC = "jvc" @@ -841,6 +843,7 @@ CONF_TEMPERATURE = "temperature" CONF_TEMPERATURE_OFFSET = "temperature_offset" CONF_TEMPERATURE_SOURCE = "temperature_source" CONF_TEMPERATURE_STEP = "temperature_step" +CONF_TEXT = "text" CONF_TEXT_SENSORS = "text_sensors" CONF_THEN = "then" CONF_THRESHOLD = "threshold" From eccc5a3ea31853986aeae1b66ceaca438aede161 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Wed, 7 Aug 2024 05:15:28 +1000 Subject: [PATCH 1872/2101] [lvgl] Fix compile error when using encoder with buttons only. (#7203) --- esphome/components/lvgl/__init__.py | 6 ++-- esphome/components/lvgl/defines.py | 2 +- .../lvgl/{rotary_encoders.py => encoders.py} | 24 +++++++------- esphome/components/lvgl/lvgl_esphome.cpp | 4 +-- esphome/components/lvgl/lvgl_esphome.h | 21 +++++++----- esphome/components/lvgl/schemas.py | 8 ++--- esphome/components/lvgl/widgets/__init__.py | 32 +++---------------- tests/components/lvgl/test.esp32-ard.yaml | 27 ++++++++++++++++ tests/components/lvgl/test.esp32-idf.yaml | 2 +- 9 files changed, 68 insertions(+), 58 deletions(-) rename esphome/components/lvgl/{rotary_encoders.py => encoders.py} (77%) diff --git a/esphome/components/lvgl/__init__.py b/esphome/components/lvgl/__init__.py index 9eb4665874..87fbcab4dc 100644 --- a/esphome/components/lvgl/__init__.py +++ b/esphome/components/lvgl/__init__.py @@ -23,9 +23,9 @@ from esphome.helpers import write_file_if_changed from . import defines as df, helpers, lv_validation as lvalid from .automation import disp_update, update_to_code from .defines import CONF_SKIP +from .encoders import ENCODERS_CONFIG, encoders_to_code from .lv_validation import lv_bool, lv_images_used from .lvcode import LvContext, LvglComponent -from .rotary_encoders import ROTARY_ENCODER_CONFIG, rotary_encoders_to_code from .schemas import ( DISP_BG_SCHEMA, FLEX_OBJ_SCHEMA, @@ -256,7 +256,7 @@ async def to_code(config): async with LvContext(lv_component): await touchscreens_to_code(lv_component, config) - await rotary_encoders_to_code(lv_component, config) + await encoders_to_code(lv_component, config) await theme_to_code(config) await styles_to_code(config) await set_obj_properties(lv_scr_act, config) @@ -336,7 +336,7 @@ CONFIG_SCHEMA = ( {cv.Optional(name): obj_schema(w) for name, w in WIDGET_TYPES.items()} ), cv.GenerateID(df.CONF_TOUCHSCREENS): touchscreen_schema, - cv.GenerateID(df.CONF_ROTARY_ENCODERS): ROTARY_ENCODER_CONFIG, + cv.GenerateID(df.CONF_ENCODERS): ENCODERS_CONFIG, } ) .extend(DISP_BG_SCHEMA) diff --git a/esphome/components/lvgl/defines.py b/esphome/components/lvgl/defines.py index 1b41b32c90..d0047b59f7 100644 --- a/esphome/components/lvgl/defines.py +++ b/esphome/components/lvgl/defines.py @@ -388,6 +388,7 @@ CONF_DEFAULT = "default" CONF_DEFAULT_FONT = "default_font" CONF_DIR = "dir" CONF_DISPLAYS = "displays" +CONF_ENCODERS = "encoders" CONF_END_ANGLE = "end_angle" CONF_END_VALUE = "end_value" CONF_ENTER_BUTTON = "enter_button" @@ -441,7 +442,6 @@ CONF_RECOLOR = "recolor" CONF_RIGHT_BUTTON = "right_button" CONF_ROLLOVER = "rollover" CONF_ROOT_BACK_BTN = "root_back_btn" -CONF_ROTARY_ENCODERS = "rotary_encoders" CONF_ROWS = "rows" CONF_SCALE_LINES = "scale_lines" CONF_SCROLLBAR_MODE = "scrollbar_mode" diff --git a/esphome/components/lvgl/rotary_encoders.py b/esphome/components/lvgl/encoders.py similarity index 77% rename from esphome/components/lvgl/rotary_encoders.py rename to esphome/components/lvgl/encoders.py index d8a82dbc78..caddc2e47f 100644 --- a/esphome/components/lvgl/rotary_encoders.py +++ b/esphome/components/lvgl/encoders.py @@ -5,25 +5,26 @@ import esphome.config_validation as cv from esphome.const import CONF_GROUP, CONF_ID, CONF_SENSOR from .defines import ( + CONF_ENCODERS, CONF_ENTER_BUTTON, CONF_LEFT_BUTTON, CONF_LONG_PRESS_REPEAT_TIME, CONF_LONG_PRESS_TIME, CONF_RIGHT_BUTTON, - CONF_ROTARY_ENCODERS, ) -from .helpers import lvgl_components_required -from .lvcode import lv, lv_add, lv_expr +from .helpers import lvgl_components_required, requires_component +from .lvcode import lv, lv_add, lv_assign, lv_expr, lv_Pvariable from .schemas import ENCODER_SCHEMA -from .types import lv_indev_type_t -from .widgets import add_group +from .types import lv_group_t, lv_indev_type_t -ROTARY_ENCODER_CONFIG = cv.ensure_list( +ENCODERS_CONFIG = cv.ensure_list( ENCODER_SCHEMA.extend( { cv.Required(CONF_ENTER_BUTTON): cv.use_id(BinarySensor), cv.Required(CONF_SENSOR): cv.Any( - cv.use_id(RotaryEncoderSensor), + cv.All( + cv.use_id(RotaryEncoderSensor), requires_component("rotary_encoder") + ), cv.Schema( { cv.Required(CONF_LEFT_BUTTON): cv.use_id(BinarySensor), @@ -36,10 +37,9 @@ ROTARY_ENCODER_CONFIG = cv.ensure_list( ) -async def rotary_encoders_to_code(var, config): - for enc_conf in config.get(CONF_ROTARY_ENCODERS, ()): +async def encoders_to_code(var, config): + for enc_conf in config.get(CONF_ENCODERS, ()): lvgl_components_required.add("KEY_LISTENER") - lvgl_components_required.add("ROTARY_ENCODER") lpt = enc_conf[CONF_LONG_PRESS_TIME].total_milliseconds lprt = enc_conf[CONF_LONG_PRESS_REPEAT_TIME].total_milliseconds listener = cg.new_Pvariable( @@ -57,7 +57,9 @@ async def rotary_encoders_to_code(var, config): lv_add(listener.set_sensor(sensor_config)) b_sensor = await cg.get_variable(enc_conf[CONF_ENTER_BUTTON]) cg.add(listener.set_enter_button(b_sensor)) - if group := add_group(enc_conf.get(CONF_GROUP)): + if group := enc_conf.get(CONF_GROUP): + group = lv_Pvariable(lv_group_t, group) + lv_assign(group, lv_expr.group_create()) lv.indev_set_group(lv_expr.indev_drv_register(listener.get_drv()), group) else: lv.indev_drv_register(listener.get_drv()) diff --git a/esphome/components/lvgl/lvgl_esphome.cpp b/esphome/components/lvgl/lvgl_esphome.cpp index 544643d532..6f23c2421b 100644 --- a/esphome/components/lvgl/lvgl_esphome.cpp +++ b/esphome/components/lvgl/lvgl_esphome.cpp @@ -127,7 +127,7 @@ void LVTouchListener::update(const touchscreen::TouchPoints_t &tpoints) { } #endif // USE_LVGL_TOUCHSCREEN -#ifdef USE_LVGL_ROTARY_ENCODER +#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; @@ -143,7 +143,7 @@ LVEncoderListener::LVEncoderListener(lv_indev_type_t type, uint16_t lpt, uint16_ data->continue_reading = false; }; } -#endif // USE_LVGL_ROTARY_ENCODER +#endif // USE_LVGL_KEY_LISTENER #ifdef USE_LVGL_BUTTONMATRIX void LvButtonMatrixType::set_obj(lv_obj_t *lv_obj) { diff --git a/esphome/components/lvgl/lvgl_esphome.h b/esphome/components/lvgl/lvgl_esphome.h index 5f2f0ea8df..45841b99d9 100644 --- a/esphome/components/lvgl/lvgl_esphome.h +++ b/esphome/components/lvgl/lvgl_esphome.h @@ -1,6 +1,13 @@ #pragma once #include "esphome/core/defines.h" +#ifdef USE_LVGL_BINARY_SENSOR +#include "esphome/components/binary_sensor/binary_sensor.h" +#endif // USE_LVGL_BINARY_SENSOR +#ifdef USE_LVGL_ROTARY_ENCODER +#include "esphome/components/rotary_encoder/rotary_encoder.h" +#endif // USE_LVGL_ROTARY_ENCODER + // required for clang-tidy #ifndef LV_CONF_H #define LV_CONF_SKIP 1 // NOLINT @@ -12,12 +19,7 @@ #include "esphome/core/log.h" #include #include - -#ifdef USE_LVGL_ROTARY_ENCODER -#include "esphome/components/binary_sensor/binary_sensor.h" -#include "esphome/components/rotary_encoder/rotary_encoder.h" -#endif // USE_LVGL_ROTARY_ENCODER - +#include #ifdef USE_LVGL_IMAGE #include "esphome/components/image/image.h" #endif // USE_LVGL_IMAGE @@ -202,7 +204,7 @@ class LVTouchListener : public touchscreen::TouchListener, public Parented { public: LVEncoderListener(lv_indev_type_t type, uint16_t lpt, uint16_t lprt); @@ -218,9 +220,11 @@ class LVEncoderListener : public Parented { enter_button->add_on_state_callback([this](bool state) { this->event(LV_KEY_ENTER, state); }); } +#ifdef USE_LVGL_ROTARY_ENCODER void set_sensor(rotary_encoder::RotaryEncoderSensor *sensor) { sensor->register_listener([this](int32_t count) { this->set_count(count); }); } +#endif // USE_LVGL_ROTARY_ENCODER void event(int key, bool pressed) { if (!this->parent_->is_paused()) { @@ -243,7 +247,8 @@ class LVEncoderListener : public Parented { int32_t last_count_{}; int key_{}; }; -#endif // USE_LVGL_ROTARY_ENCODER +#endif // USE_LVGL_KEY_LISTENER + #ifdef USE_LVGL_BUTTONMATRIX class LvButtonMatrixType : public key_provider::KeyProvider, public LvCompound { public: diff --git a/esphome/components/lvgl/schemas.py b/esphome/components/lvgl/schemas.py index 62536bf4d5..f172ba9f2b 100644 --- a/esphome/components/lvgl/schemas.py +++ b/esphome/components/lvgl/schemas.py @@ -16,9 +16,9 @@ from esphome.schema_extractors import SCHEMA_EXTRACT from . import defines as df, lv_validation as lvalid, types as ty from .helpers import add_lv_use, requires_component, validate_printf -from .lv_validation import id_name, lv_color, lv_font, lv_image +from .lv_validation import lv_color, lv_font, lv_image from .lvcode import LvglComponent -from .types import WidgetType +from .types import WidgetType, lv_group_t # this will be populated later, in __init__.py to avoid circular imports. WIDGET_TYPES: dict = {} @@ -61,7 +61,7 @@ ENCODER_SCHEMA = cv.Schema( cv.GenerateID(): cv.All( cv.declare_id(ty.LVEncoderListener), requires_component("binary_sensor") ), - cv.Optional(CONF_GROUP): lvalid.id_name, + cv.Optional(CONF_GROUP): cv.declare_id(lv_group_t), cv.Optional(df.CONF_LONG_PRESS_TIME, default="400ms"): PRESS_TIME, cv.Optional(df.CONF_LONG_PRESS_REPEAT_TIME, default="100ms"): PRESS_TIME, } @@ -249,7 +249,7 @@ def obj_schema(widget_type: WidgetType): cv.Schema( { cv.Optional(CONF_STATE): SET_STATE_SCHEMA, - cv.Optional(CONF_GROUP): id_name, + cv.Optional(CONF_GROUP): cv.use_id(lv_group_t), } ) ) diff --git a/esphome/components/lvgl/widgets/__init__.py b/esphome/components/lvgl/widgets/__init__.py index dff43cf257..f1946015bc 100644 --- a/esphome/components/lvgl/widgets/__init__.py +++ b/esphome/components/lvgl/widgets/__init__.py @@ -6,7 +6,7 @@ from esphome.config_validation import Invalid from esphome.const import CONF_GROUP, CONF_ID, CONF_STATE, CONF_TYPE from esphome.core import ID, TimePeriod from esphome.coroutine import FakeAwaitable -from esphome.cpp_generator import AssignmentExpression, CallExpression, MockObj +from esphome.cpp_generator import CallExpression, MockObj from ..defines import ( CONF_DEFAULT, @@ -44,15 +44,7 @@ from ..lvcode import ( lv_Pvariable, ) from ..schemas import ALL_STYLES, STYLE_REMAP, WIDGET_TYPES -from ..types import ( - LV_STATE, - LvType, - WidgetType, - lv_coord_t, - lv_group_t, - lv_obj_t, - lv_obj_t_ptr, -) +from ..types import LV_STATE, LvType, WidgetType, lv_coord_t, lv_obj_t, lv_obj_t_ptr EVENT_LAMB = "event_lamb__" @@ -317,7 +309,8 @@ async def set_obj_properties(w: Widget, config): value = await ALL_STYLES[prop].process(value) prop_r = STYLE_REMAP.get(prop, prop) w.set_style(prop_r, value, lv_state) - if group := add_group(config.get(CONF_GROUP)): + if group := config.get(CONF_GROUP): + group = await cg.get_variable(group) lv.group_add_obj(group, w.obj) flag_clr = set() flag_set = set() @@ -404,20 +397,3 @@ async def widget_to_code(w_cnfig, w_type: WidgetType, parent): lv_scr_act_spec = LvScrActType() lv_scr_act = Widget.create(None, literal("lv_scr_act()"), lv_scr_act_spec, {}) - -lv_groups = {} # Widget group names - - -def add_group(name): - if name is None: - return None - fullname = f"lv_esp_group_{name}" - if name not in lv_groups: - gid = ID(fullname, True, type=lv_group_t.operator("ptr")) - lv_add( - AssignmentExpression( - type_=gid.type, modifier="", name=fullname, rhs=lv_expr.group_create() - ) - ) - lv_groups[name] = literal(fullname) - return lv_groups[name] diff --git a/tests/components/lvgl/test.esp32-ard.yaml b/tests/components/lvgl/test.esp32-ard.yaml index abfb324ea5..2d6a6871ba 100644 --- a/tests/components/lvgl/test.esp32-ard.yaml +++ b/tests/components/lvgl/test.esp32-ard.yaml @@ -24,6 +24,33 @@ display: invert_colors: false update_interval: never +binary_sensor: + - platform: gpio + internal: true + id: up_button + pin: + number: GPIO38 + inverted: true + - platform: gpio + internal: true + id: down_button + pin: + number: GPIO37 + inverted: true + - platform: gpio + internal: true + id: select_button + pin: + number: GPIO39 + inverted: true +lvgl: + encoders: + group: switches + enter_button: select_button + sensor: + left_button: up_button + right_button: down_button + packages: lvgl: !include lvgl-package.yaml diff --git a/tests/components/lvgl/test.esp32-idf.yaml b/tests/components/lvgl/test.esp32-idf.yaml index 0f740db980..927d72d15c 100644 --- a/tests/components/lvgl/test.esp32-idf.yaml +++ b/tests/components/lvgl/test.esp32-idf.yaml @@ -67,7 +67,7 @@ lvgl: displays: - tft_display - second_display - rotary_encoders: + encoders: sensor: encoder enter_button: pushbutton group: general From da0dbe8753645b753a9dc64fb6ad21ccd29a867c Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 7 Aug 2024 07:29:05 +1200 Subject: [PATCH 1873/2101] Revert "Add null GPIO pin " (#6621) --- .../cst226/touchscreen/cst226_touchscreen.cpp | 18 +++++++++++------- .../cst226/touchscreen/cst226_touchscreen.h | 2 +- esphome/core/gpio.h | 18 ------------------ 3 files changed, 12 insertions(+), 26 deletions(-) diff --git a/esphome/components/cst226/touchscreen/cst226_touchscreen.cpp b/esphome/components/cst226/touchscreen/cst226_touchscreen.cpp index 69728dc666..d4e43d30f5 100644 --- a/esphome/components/cst226/touchscreen/cst226_touchscreen.cpp +++ b/esphome/components/cst226/touchscreen/cst226_touchscreen.cpp @@ -5,13 +5,17 @@ namespace cst226 { void CST226Touchscreen::setup() { esph_log_config(TAG, "Setting up CST226 Touchscreen..."); - this->reset_pin_->setup(); - this->reset_pin_->digital_write(true); - delay(5); - this->reset_pin_->digital_write(false); - delay(5); - this->reset_pin_->digital_write(true); - this->set_timeout(30, [this] { this->continue_setup_(); }); + if (this->reset_pin_ != nullptr) { + this->reset_pin_->setup(); + this->reset_pin_->digital_write(true); + delay(5); + this->reset_pin_->digital_write(false); + delay(5); + this->reset_pin_->digital_write(true); + this->set_timeout(30, [this] { this->continue_setup_(); }); + } else { + this->continue_setup_(); + } } void CST226Touchscreen::update_touches() { diff --git a/esphome/components/cst226/touchscreen/cst226_touchscreen.h b/esphome/components/cst226/touchscreen/cst226_touchscreen.h index 1b15b952c4..9f518e5068 100644 --- a/esphome/components/cst226/touchscreen/cst226_touchscreen.h +++ b/esphome/components/cst226/touchscreen/cst226_touchscreen.h @@ -35,7 +35,7 @@ class CST226Touchscreen : public touchscreen::Touchscreen, public i2c::I2CDevice void continue_setup_(); InternalGPIOPin *interrupt_pin_{}; - GPIOPin *reset_pin_{NULL_PIN}; + GPIOPin *reset_pin_{}; uint8_t chip_id_{}; bool setup_complete_{}; }; diff --git a/esphome/core/gpio.h b/esphome/core/gpio.h index b3f6b00196..1b6f2ba1e6 100644 --- a/esphome/core/gpio.h +++ b/esphome/core/gpio.h @@ -62,24 +62,6 @@ class GPIOPin { virtual bool is_internal() { return false; } }; -/** - * A pin to replace those that don't exist. - */ -class NullPin : public GPIOPin { - public: - void setup() override {} - - void pin_mode(gpio::Flags _) override {} - - bool digital_read() override { return false; } - - void digital_write(bool _) override {} - - std::string dump_summary() const override { return {"Not used"}; } -}; - -static GPIOPin *const NULL_PIN = new NullPin(); - /// Copy of GPIOPin that is safe to use from ISRs (with no virtual functions) class ISRInternalGPIOPin { public: From 1e63fddf36390794c4aa70e6a9e508b23b4fa852 Mon Sep 17 00:00:00 2001 From: iannisimo <11798717+iannisimo@users.noreply.github.com> Date: Wed, 7 Aug 2024 01:02:30 +0200 Subject: [PATCH 1874/2101] [remote_transmitter] Change default carrier_frequency to valid value (#7176) set current_carrier_frequency_ default value to esp-idf's default (38000) --- esphome/components/remote_transmitter/remote_transmitter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/remote_transmitter/remote_transmitter.h b/esphome/components/remote_transmitter/remote_transmitter.h index b897fa8fab..a5896796c0 100644 --- a/esphome/components/remote_transmitter/remote_transmitter.h +++ b/esphome/components/remote_transmitter/remote_transmitter.h @@ -49,7 +49,7 @@ class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase, #ifdef USE_ESP32 void configure_rmt_(); - uint32_t current_carrier_frequency_{UINT32_MAX}; + uint32_t current_carrier_frequency_{38000}; bool initialized_{false}; std::vector rmt_temp_; esp_err_t error_code_{ESP_OK}; From 73f786c606dd3ad913e4d27553acd620548a0349 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 7 Aug 2024 15:46:37 +1200 Subject: [PATCH 1875/2101] [code-quality] Organise script imports (#7198) --- script/build_codeowners.py | 8 ++++---- script/build_language_schema.py | 14 +++++++------- script/bump-version.py | 2 +- script/clang-format | 12 +++--------- script/clang-tidy | 29 ++++++++++++++--------------- script/helpers.py | 2 +- script/lint-python | 19 ++++++++++--------- script/list-components.py | 9 +++++---- 8 files changed, 45 insertions(+), 50 deletions(-) diff --git a/script/build_codeowners.py b/script/build_codeowners.py index 6bc558d351..db34ad7702 100755 --- a/script/build_codeowners.py +++ b/script/build_codeowners.py @@ -1,13 +1,13 @@ #!/usr/bin/env python3 -from pathlib import Path -import sys import argparse from collections import defaultdict +from pathlib import Path +import sys -from esphome.helpers import write_file_if_changed from esphome.config import get_component, get_platform -from esphome.core import CORE from esphome.const import KEY_CORE, KEY_TARGET_FRAMEWORK +from esphome.core import CORE +from esphome.helpers import write_file_if_changed parser = argparse.ArgumentParser() parser.add_argument( diff --git a/script/build_language_schema.py b/script/build_language_schema.py index cb3dc1832d..8b2c28b06b 100644 --- a/script/build_language_schema.py +++ b/script/build_language_schema.py @@ -1,9 +1,10 @@ +import argparse +import glob import inspect import json -import argparse import os -import glob import re + import voluptuous as vol # NOTE: Cannot import other esphome components globally as a modification in vol_schema @@ -94,13 +95,12 @@ load_components() # Import esphome after loading components (so schema is tracked) # pylint: disable=wrong-import-position -import esphome.core as esphome_core -import esphome.config_validation as cv -from esphome import automation -from esphome import pins +from esphome import automation, pins from esphome.components import remote_base -from esphome.loader import get_platform, CORE_COMPONENTS_PATH +import esphome.config_validation as cv +import esphome.core as esphome_core from esphome.helpers import write_file_if_changed +from esphome.loader import CORE_COMPONENTS_PATH, get_platform from esphome.util import Registry # pylint: enable=wrong-import-position diff --git a/script/bump-version.py b/script/bump-version.py index a55bb65cd6..8389d482b8 100755 --- a/script/bump-version.py +++ b/script/bump-version.py @@ -1,8 +1,8 @@ #!/usr/bin/env python3 import argparse -import re from dataclasses import dataclass +import re import sys diff --git a/script/clang-format b/script/clang-format index b065d80795..d922c5b6f1 100755 --- a/script/clang-format +++ b/script/clang-format @@ -1,15 +1,6 @@ #!/usr/bin/env python3 -from helpers import ( - print_error_for_file, - get_output, - git_ls_files, - filter_changed, - get_binary, -) import argparse -import click -import colorama import multiprocessing import os import queue @@ -18,6 +9,9 @@ import subprocess import sys import threading +import click +import colorama +from helpers import filter_changed, get_binary, git_ls_files, print_error_for_file def run_format(executable, args, queue, lock, failed_files): diff --git a/script/clang-tidy b/script/clang-tidy index bd919825fd..ea522157c5 100755 --- a/script/clang-tidy +++ b/script/clang-tidy @@ -1,21 +1,6 @@ #!/usr/bin/env python3 -from helpers import ( - print_error_for_file, - get_output, - filter_grep, - build_all_include, - temp_header_file, - git_ls_files, - filter_changed, - load_idedata, - root_path, - basepath, - get_binary, -) import argparse -import click -import colorama import multiprocessing import os import queue @@ -26,6 +11,20 @@ import sys import tempfile import threading +import click +import colorama +from helpers import ( + basepath, + build_all_include, + filter_changed, + filter_grep, + get_binary, + git_ls_files, + load_idedata, + print_error_for_file, + root_path, + temp_header_file, +) def clang_options(idedata): diff --git a/script/helpers.py b/script/helpers.py index 52b0658fb6..56349b6052 100644 --- a/script/helpers.py +++ b/script/helpers.py @@ -1,8 +1,8 @@ import json import os.path +from pathlib import Path import re import subprocess -from pathlib import Path import colorama diff --git a/script/lint-python b/script/lint-python index 7de1de80b0..01e5e76190 100755 --- a/script/lint-python +++ b/script/lint-python @@ -1,19 +1,20 @@ #!/usr/bin/env python3 -from helpers import ( - styled, - print_error_for_file, - get_output, - get_err, - git_ls_files, - filter_changed, -) import argparse -import colorama import os import re import sys +import colorama +from helpers import ( + filter_changed, + get_err, + get_output, + git_ls_files, + print_error_for_file, + styled, +) + curfile = None diff --git a/script/list-components.py b/script/list-components.py index 559919bb8a..0d4777436b 100755 --- a/script/list-components.py +++ b/script/list-components.py @@ -1,11 +1,10 @@ #!/usr/bin/env python3 +import argparse from pathlib import Path import sys -import argparse -from helpers import git_ls_files, changed_files -from esphome.loader import get_component, get_platform -from esphome.core import CORE +from helpers import changed_files, git_ls_files + from esphome.const import ( KEY_CORE, KEY_TARGET_FRAMEWORK, @@ -13,6 +12,8 @@ from esphome.const import ( PLATFORM_ESP32, PLATFORM_ESP8266, ) +from esphome.core import CORE +from esphome.loader import get_component, get_platform def filter_component_files(str): From 9b0c2234d89c4f6a642a9fefc77f2e7f0a1c5ef7 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 7 Aug 2024 15:47:46 +1200 Subject: [PATCH 1876/2101] [max31856] Use cv.frequency as validator (#7212) --- esphome/components/max31856/sensor.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/esphome/components/max31856/sensor.py b/esphome/components/max31856/sensor.py index 71f1f3bfa5..bf9741aeed 100644 --- a/esphome/components/max31856/sensor.py +++ b/esphome/components/max31856/sensor.py @@ -1,6 +1,6 @@ import esphome.codegen as cg -import esphome.config_validation as cv from esphome.components import sensor, spi +import esphome.config_validation as cv from esphome.const import ( CONF_MAINS_FILTER, DEVICE_CLASS_TEMPERATURE, @@ -15,8 +15,8 @@ MAX31856Sensor = max31856_ns.class_( MAX31865ConfigFilter = max31856_ns.enum("MAX31856ConfigFilter") FILTER = { - "50HZ": MAX31865ConfigFilter.FILTER_50HZ, - "60HZ": MAX31865ConfigFilter.FILTER_60HZ, + 50: MAX31865ConfigFilter.FILTER_50HZ, + 60: MAX31865ConfigFilter.FILTER_60HZ, } CONFIG_SCHEMA = ( @@ -29,8 +29,8 @@ CONFIG_SCHEMA = ( ) .extend( { - cv.Optional(CONF_MAINS_FILTER, default="60HZ"): cv.enum( - FILTER, upper=True, space="" + cv.Optional(CONF_MAINS_FILTER, default="60Hz"): cv.All( + cv.frequency, cv.enum(FILTER, int=True) ), } ) From c348efa401ea64b6a07ae6671fc16f62f3dcb1e2 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Wed, 7 Aug 2024 05:49:51 +0200 Subject: [PATCH 1877/2101] [code-quality] Organise base entities imports (#7208) --- esphome/components/binary_sensor/__init__.py | 10 +++--- esphome/components/button/__init__.py | 8 ++--- esphome/components/climate/__init__.py | 10 +++--- esphome/components/cover/__init__.py | 16 +++++----- esphome/components/datetime/__init__.py | 26 +++++++-------- esphome/components/event/__init__.py | 10 +++--- esphome/components/fan/__init__.py | 28 ++++++++--------- esphome/components/light/__init__.py | 33 ++++++++++---------- esphome/components/lock/__init__.py | 6 ++-- esphome/components/media_player/__init__.py | 8 ++--- esphome/components/number/__init__.py | 17 +++++----- esphome/components/select/__init__.py | 14 ++++----- esphome/components/sensor/__init__.py | 20 ++++++------ esphome/components/switch/__init__.py | 6 ++-- esphome/components/text/__init__.py | 10 +++--- esphome/components/text_sensor/__init__.py | 14 ++++----- esphome/components/valve/__init__.py | 6 ++-- 17 files changed, 119 insertions(+), 123 deletions(-) diff --git a/esphome/components/binary_sensor/__init__.py b/esphome/components/binary_sensor/__init__.py index 11a1887206..95fd17bcc0 100644 --- a/esphome/components/binary_sensor/__init__.py +++ b/esphome/components/binary_sensor/__init__.py @@ -1,10 +1,8 @@ -import esphome.codegen as cg -import esphome.config_validation as cv -from esphome.cpp_generator import MockObjClass -from esphome.cpp_helpers import setup_entity from esphome import automation, core from esphome.automation import Condition, maybe_simple_id +import esphome.codegen as cg from esphome.components import mqtt, web_server +import esphome.config_validation as cv from esphome.const import ( CONF_DELAY, CONF_DEVICE_CLASS, @@ -16,6 +14,7 @@ from esphome.const import ( CONF_INVERTED, CONF_MAX_LENGTH, CONF_MIN_LENGTH, + CONF_MQTT_ID, CONF_ON_CLICK, CONF_ON_DOUBLE_CLICK, CONF_ON_MULTI_CLICK, @@ -26,7 +25,6 @@ from esphome.const import ( CONF_STATE, CONF_TIMING, CONF_TRIGGER_ID, - CONF_MQTT_ID, CONF_WEB_SERVER_ID, DEVICE_CLASS_BATTERY, DEVICE_CLASS_BATTERY_CHARGING, @@ -59,6 +57,8 @@ from esphome.const import ( DEVICE_CLASS_WINDOW, ) from esphome.core import CORE, coroutine_with_priority +from esphome.cpp_generator import MockObjClass +from esphome.cpp_helpers import setup_entity from esphome.util import Registry CODEOWNERS = ["@esphome/core"] diff --git a/esphome/components/button/__init__.py b/esphome/components/button/__init__.py index 773ab9d37f..3010d3006a 100644 --- a/esphome/components/button/__init__.py +++ b/esphome/components/button/__init__.py @@ -1,16 +1,16 @@ -import esphome.codegen as cg -import esphome.config_validation as cv from esphome import automation from esphome.automation import maybe_simple_id +import esphome.codegen as cg from esphome.components import mqtt, web_server +import esphome.config_validation as cv from esphome.const import ( CONF_DEVICE_CLASS, CONF_ENTITY_CATEGORY, CONF_ICON, CONF_ID, + CONF_MQTT_ID, CONF_ON_PRESS, CONF_TRIGGER_ID, - CONF_MQTT_ID, CONF_WEB_SERVER_ID, DEVICE_CLASS_EMPTY, DEVICE_CLASS_IDENTIFY, @@ -18,8 +18,8 @@ from esphome.const import ( DEVICE_CLASS_UPDATE, ) from esphome.core import CORE, coroutine_with_priority -from esphome.cpp_helpers import setup_entity from esphome.cpp_generator import MockObjClass +from esphome.cpp_helpers import setup_entity CODEOWNERS = ["@esphome/core"] IS_PLATFORM_COMPONENT = True diff --git a/esphome/components/climate/__init__.py b/esphome/components/climate/__init__.py index ccd7a3da4e..c7e4ce7745 100644 --- a/esphome/components/climate/__init__.py +++ b/esphome/components/climate/__init__.py @@ -1,8 +1,7 @@ -import esphome.codegen as cg -import esphome.config_validation as cv -from esphome.cpp_helpers import setup_entity from esphome import automation +import esphome.codegen as cg from esphome.components import mqtt, web_server +import esphome.config_validation as cv from esphome.const import ( CONF_ACTION_STATE_TOPIC, CONF_AWAY, @@ -21,6 +20,7 @@ from esphome.const import ( CONF_MODE, CONF_MODE_COMMAND_TOPIC, CONF_MODE_STATE_TOPIC, + CONF_MQTT_ID, CONF_ON_CONTROL, CONF_ON_STATE, CONF_PRESET, @@ -33,20 +33,20 @@ from esphome.const import ( CONF_TARGET_HUMIDITY_STATE_TOPIC, CONF_TARGET_TEMPERATURE, CONF_TARGET_TEMPERATURE_COMMAND_TOPIC, - CONF_TARGET_TEMPERATURE_STATE_TOPIC, CONF_TARGET_TEMPERATURE_HIGH, CONF_TARGET_TEMPERATURE_HIGH_COMMAND_TOPIC, CONF_TARGET_TEMPERATURE_HIGH_STATE_TOPIC, CONF_TARGET_TEMPERATURE_LOW, CONF_TARGET_TEMPERATURE_LOW_COMMAND_TOPIC, CONF_TARGET_TEMPERATURE_LOW_STATE_TOPIC, + CONF_TARGET_TEMPERATURE_STATE_TOPIC, CONF_TEMPERATURE_STEP, CONF_TRIGGER_ID, CONF_VISUAL, - CONF_MQTT_ID, CONF_WEB_SERVER_ID, ) from esphome.core import CORE, coroutine_with_priority +from esphome.cpp_helpers import setup_entity IS_PLATFORM_COMPONENT = True diff --git a/esphome/components/cover/__init__.py b/esphome/components/cover/__init__.py index 313b2c5928..d25dd91148 100644 --- a/esphome/components/cover/__init__.py +++ b/esphome/components/cover/__init__.py @@ -1,23 +1,23 @@ -import esphome.codegen as cg -import esphome.config_validation as cv from esphome import automation -from esphome.automation import maybe_simple_id, Condition +from esphome.automation import Condition, maybe_simple_id +import esphome.codegen as cg from esphome.components import mqtt, web_server +import esphome.config_validation as cv from esphome.const import ( - CONF_ID, CONF_DEVICE_CLASS, - CONF_STATE, + CONF_ID, + CONF_MQTT_ID, CONF_ON_OPEN, CONF_POSITION, CONF_POSITION_COMMAND_TOPIC, CONF_POSITION_STATE_TOPIC, + CONF_STATE, + CONF_STOP, CONF_TILT, CONF_TILT_COMMAND_TOPIC, CONF_TILT_STATE_TOPIC, - CONF_STOP, - CONF_MQTT_ID, - CONF_WEB_SERVER_ID, CONF_TRIGGER_ID, + CONF_WEB_SERVER_ID, DEVICE_CLASS_AWNING, DEVICE_CLASS_BLIND, DEVICE_CLASS_CURTAIN, diff --git a/esphome/components/datetime/__init__.py b/esphome/components/datetime/__init__.py index c118216a2d..4fda97c5bc 100644 --- a/esphome/components/datetime/__init__.py +++ b/esphome/components/datetime/__init__.py @@ -1,32 +1,30 @@ -import esphome.codegen as cg - -import esphome.config_validation as cv from esphome import automation -from esphome.components import mqtt, web_server, time +import esphome.codegen as cg +from esphome.components import mqtt, time, web_server +import esphome.config_validation as cv from esphome.const import ( + CONF_DATE, + CONF_DATETIME, + CONF_DAY, + CONF_HOUR, CONF_ID, + CONF_MINUTE, + CONF_MONTH, + CONF_MQTT_ID, CONF_ON_TIME, CONF_ON_VALUE, + CONF_SECOND, + CONF_TIME, CONF_TIME_ID, CONF_TRIGGER_ID, CONF_TYPE, - CONF_MQTT_ID, CONF_WEB_SERVER_ID, - CONF_DATE, - CONF_DATETIME, - CONF_TIME, CONF_YEAR, - CONF_MONTH, - CONF_DAY, - CONF_SECOND, - CONF_HOUR, - CONF_MINUTE, ) from esphome.core import CORE, coroutine_with_priority from esphome.cpp_generator import MockObjClass from esphome.cpp_helpers import setup_entity - CODEOWNERS = ["@rfdarter", "@jesserockz"] DEPENDENCIES = ["time"] diff --git a/esphome/components/event/__init__.py b/esphome/components/event/__init__.py index 241e884386..031a4c0de8 100644 --- a/esphome/components/event/__init__.py +++ b/esphome/components/event/__init__.py @@ -1,24 +1,24 @@ -import esphome.codegen as cg -import esphome.config_validation as cv from esphome import automation +import esphome.codegen as cg from esphome.components import mqtt +import esphome.config_validation as cv from esphome.const import ( CONF_DEVICE_CLASS, CONF_ENTITY_CATEGORY, + CONF_EVENT_TYPE, CONF_ICON, CONF_ID, + CONF_MQTT_ID, CONF_ON_EVENT, CONF_TRIGGER_ID, - CONF_MQTT_ID, - CONF_EVENT_TYPE, DEVICE_CLASS_BUTTON, DEVICE_CLASS_DOORBELL, DEVICE_CLASS_EMPTY, DEVICE_CLASS_MOTION, ) from esphome.core import CORE, coroutine_with_priority -from esphome.cpp_helpers import setup_entity from esphome.cpp_generator import MockObjClass +from esphome.cpp_helpers import setup_entity CODEOWNERS = ["@nohat"] IS_PLATFORM_COMPONENT = True diff --git a/esphome/components/fan/__init__.py b/esphome/components/fan/__init__.py index 847a59baa1..62624ec6e3 100644 --- a/esphome/components/fan/__init__.py +++ b/esphome/components/fan/__init__.py @@ -1,31 +1,31 @@ -import esphome.codegen as cg -import esphome.config_validation as cv from esphome import automation from esphome.automation import maybe_simple_id +import esphome.codegen as cg from esphome.components import mqtt, web_server +import esphome.config_validation as cv from esphome.const import ( + CONF_DIRECTION, CONF_ID, CONF_MQTT_ID, - CONF_WEB_SERVER_ID, - CONF_OSCILLATING, - CONF_OSCILLATION_COMMAND_TOPIC, - CONF_OSCILLATION_STATE_TOPIC, - CONF_SPEED, - CONF_SPEED_LEVEL_COMMAND_TOPIC, - CONF_SPEED_LEVEL_STATE_TOPIC, - CONF_SPEED_COMMAND_TOPIC, - CONF_SPEED_STATE_TOPIC, CONF_OFF_SPEED_CYCLE, CONF_ON_DIRECTION_SET, CONF_ON_OSCILLATING_SET, + CONF_ON_PRESET_SET, CONF_ON_SPEED_SET, CONF_ON_STATE, CONF_ON_TURN_OFF, CONF_ON_TURN_ON, - CONF_ON_PRESET_SET, - CONF_TRIGGER_ID, - CONF_DIRECTION, + CONF_OSCILLATING, + CONF_OSCILLATION_COMMAND_TOPIC, + CONF_OSCILLATION_STATE_TOPIC, CONF_RESTORE_MODE, + CONF_SPEED, + CONF_SPEED_COMMAND_TOPIC, + CONF_SPEED_LEVEL_COMMAND_TOPIC, + CONF_SPEED_LEVEL_STATE_TOPIC, + CONF_SPEED_STATE_TOPIC, + CONF_TRIGGER_ID, + CONF_WEB_SERVER_ID, ) from esphome.core import CORE, coroutine_with_priority from esphome.cpp_helpers import setup_entity diff --git a/esphome/components/light/__init__.py b/esphome/components/light/__init__.py index 161b4d8cd9..d9f139d2f4 100644 --- a/esphome/components/light/__init__.py +++ b/esphome/components/light/__init__.py @@ -1,8 +1,9 @@ -import esphome.codegen as cg -import esphome.config_validation as cv import esphome.automation as auto +import esphome.codegen as cg from esphome.components import mqtt, power_supply, web_server +import esphome.config_validation as cv from esphome.const import ( + CONF_COLD_WHITE_COLOR_TEMPERATURE, CONF_COLOR_CORRECT, CONF_DEFAULT_TRANSITION_LENGTH, CONF_EFFECTS, @@ -10,36 +11,36 @@ from esphome.const import ( CONF_GAMMA_CORRECT, CONF_ID, CONF_MQTT_ID, - CONF_WEB_SERVER_ID, - CONF_POWER_SUPPLY, - CONF_RESTORE_MODE, + CONF_ON_STATE, CONF_ON_TURN_OFF, CONF_ON_TURN_ON, - CONF_ON_STATE, + CONF_POWER_SUPPLY, + CONF_RESTORE_MODE, CONF_TRIGGER_ID, - CONF_COLD_WHITE_COLOR_TEMPERATURE, CONF_WARM_WHITE_COLOR_TEMPERATURE, + CONF_WEB_SERVER_ID, ) from esphome.core import coroutine_with_priority from esphome.cpp_helpers import setup_entity + from .automation import light_control_to_code # noqa from .effects import ( - validate_effects, + ADDRESSABLE_EFFECTS, BINARY_EFFECTS, + EFFECTS_REGISTRY, MONOCHROMATIC_EFFECTS, RGB_EFFECTS, - ADDRESSABLE_EFFECTS, - EFFECTS_REGISTRY, + validate_effects, ) from .types import ( # noqa - LightState, - AddressableLightState, - light_ns, - LightOutput, AddressableLight, - LightTurnOnTrigger, - LightTurnOffTrigger, + AddressableLightState, + LightOutput, + LightState, LightStateTrigger, + LightTurnOffTrigger, + LightTurnOnTrigger, + light_ns, ) CODEOWNERS = ["@esphome/core"] diff --git a/esphome/components/lock/__init__.py b/esphome/components/lock/__init__.py index c2d6054ed9..6b92bc264b 100644 --- a/esphome/components/lock/__init__.py +++ b/esphome/components/lock/__init__.py @@ -1,14 +1,14 @@ -import esphome.codegen as cg -import esphome.config_validation as cv from esphome import automation from esphome.automation import Condition, maybe_simple_id +import esphome.codegen as cg from esphome.components import mqtt, web_server +import esphome.config_validation as cv from esphome.const import ( CONF_ID, + CONF_MQTT_ID, CONF_ON_LOCK, CONF_ON_UNLOCK, CONF_TRIGGER_ID, - CONF_MQTT_ID, CONF_WEB_SERVER_ID, ) from esphome.core import CORE, coroutine_with_priority diff --git a/esphome/components/media_player/__init__.py b/esphome/components/media_player/__init__.py index 320014e355..423cb065dc 100644 --- a/esphome/components/media_player/__init__.py +++ b/esphome/components/media_player/__init__.py @@ -1,20 +1,18 @@ from esphome import automation -import esphome.config_validation as cv -import esphome.codegen as cg - from esphome.automation import maybe_simple_id +import esphome.codegen as cg +import esphome.config_validation as cv from esphome.const import ( CONF_ID, + CONF_ON_IDLE, CONF_ON_STATE, CONF_TRIGGER_ID, CONF_VOLUME, - CONF_ON_IDLE, ) from esphome.core import CORE from esphome.coroutine import coroutine_with_priority from esphome.cpp_helpers import setup_entity - CODEOWNERS = ["@jesserockz"] IS_PLATFORM_COMPONENT = True diff --git a/esphome/components/number/__init__.py b/esphome/components/number/__init__.py index d9c16fd7a9..ece738af49 100644 --- a/esphome/components/number/__init__.py +++ b/esphome/components/number/__init__.py @@ -1,24 +1,23 @@ -import esphome.codegen as cg -import esphome.config_validation as cv from esphome import automation -from esphome.components import mqtt -from esphome.components import web_server +import esphome.codegen as cg +from esphome.components import mqtt, web_server +import esphome.config_validation as cv from esphome.const import ( CONF_ABOVE, CONF_BELOW, + CONF_CYCLE, CONF_DEVICE_CLASS, CONF_ENTITY_CATEGORY, - CONF_ID, CONF_ICON, + CONF_ID, CONF_MODE, + CONF_MQTT_ID, CONF_ON_VALUE, CONF_ON_VALUE_RANGE, + CONF_OPERATION, CONF_TRIGGER_ID, CONF_UNIT_OF_MEASUREMENT, - CONF_MQTT_ID, CONF_VALUE, - CONF_OPERATION, - CONF_CYCLE, CONF_WEB_SERVER_ID, DEVICE_CLASS_APPARENT_POWER, DEVICE_CLASS_AQI, @@ -72,8 +71,8 @@ from esphome.const import ( DEVICE_CLASS_WIND_SPEED, ) from esphome.core import CORE, coroutine_with_priority -from esphome.cpp_helpers import setup_entity from esphome.cpp_generator import MockObjClass +from esphome.cpp_helpers import setup_entity CODEOWNERS = ["@esphome/core"] DEVICE_CLASSES = [ diff --git a/esphome/components/select/__init__.py b/esphome/components/select/__init__.py index 073fbef1d4..2bc68d43ec 100644 --- a/esphome/components/select/__init__.py +++ b/esphome/components/select/__init__.py @@ -1,20 +1,20 @@ -import esphome.codegen as cg -import esphome.config_validation as cv from esphome import automation +import esphome.codegen as cg from esphome.components import mqtt, web_server +import esphome.config_validation as cv from esphome.const import ( + CONF_CYCLE, CONF_ENTITY_CATEGORY, CONF_ICON, CONF_ID, + CONF_INDEX, + CONF_MODE, + CONF_MQTT_ID, CONF_ON_VALUE, + CONF_OPERATION, CONF_OPTION, CONF_TRIGGER_ID, - CONF_MQTT_ID, CONF_WEB_SERVER_ID, - CONF_CYCLE, - CONF_MODE, - CONF_OPERATION, - CONF_INDEX, ) from esphome.core import CORE, coroutine_with_priority from esphome.cpp_generator import MockObjClass diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index 3b76466dec..867cdc1f48 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -1,22 +1,27 @@ import math -import esphome.codegen as cg -import esphome.config_validation as cv from esphome import automation +import esphome.codegen as cg from esphome.components import mqtt, web_server +import esphome.config_validation as cv from esphome.const import ( - CONF_DEVICE_CLASS, CONF_ABOVE, CONF_ACCURACY_DECIMALS, CONF_ALPHA, CONF_BELOW, + CONF_DEVICE_CLASS, CONF_ENTITY_CATEGORY, CONF_EXPIRE_AFTER, CONF_FILTERS, + CONF_FORCE_UPDATE, CONF_FROM, CONF_ICON, CONF_ID, CONF_IGNORE_OUT_OF_RANGE, + CONF_MAX_VALUE, + CONF_METHOD, + CONF_MIN_VALUE, + CONF_MQTT_ID, CONF_MULTIPLE, CONF_ON_RAW_VALUE, CONF_ON_VALUE, @@ -30,14 +35,9 @@ from esphome.const import ( CONF_TRIGGER_ID, CONF_TYPE, CONF_UNIT_OF_MEASUREMENT, - CONF_WINDOW_SIZE, - CONF_MQTT_ID, - CONF_WEB_SERVER_ID, - CONF_FORCE_UPDATE, CONF_VALUE, - CONF_MIN_VALUE, - CONF_MAX_VALUE, - CONF_METHOD, + CONF_WEB_SERVER_ID, + CONF_WINDOW_SIZE, DEVICE_CLASS_APPARENT_POWER, DEVICE_CLASS_AQI, DEVICE_CLASS_ATMOSPHERIC_PRESSURE, diff --git a/esphome/components/switch/__init__.py b/esphome/components/switch/__init__.py index 3539d0e34e..fef4f7f007 100644 --- a/esphome/components/switch/__init__.py +++ b/esphome/components/switch/__init__.py @@ -1,8 +1,8 @@ -import esphome.codegen as cg -import esphome.config_validation as cv from esphome import automation from esphome.automation import Condition, maybe_simple_id +import esphome.codegen as cg from esphome.components import mqtt, web_server +import esphome.config_validation as cv from esphome.const import ( CONF_DEVICE_CLASS, CONF_ENTITY_CATEGORY, @@ -10,11 +10,11 @@ from esphome.const import ( CONF_ID, CONF_INVERTED, CONF_MQTT_ID, - CONF_WEB_SERVER_ID, CONF_ON_TURN_OFF, CONF_ON_TURN_ON, CONF_RESTORE_MODE, CONF_TRIGGER_ID, + CONF_WEB_SERVER_ID, DEVICE_CLASS_EMPTY, DEVICE_CLASS_OUTLET, DEVICE_CLASS_SWITCH, diff --git a/esphome/components/text/__init__.py b/esphome/components/text/__init__.py index 5a8e763495..386baaf756 100644 --- a/esphome/components/text/__init__.py +++ b/esphome/components/text/__init__.py @@ -1,18 +1,18 @@ from typing import Optional -import esphome.codegen as cg -import esphome.config_validation as cv + from esphome import automation +import esphome.codegen as cg from esphome.components import mqtt, web_server +import esphome.config_validation as cv from esphome.const import ( CONF_ID, CONF_MODE, + CONF_MQTT_ID, CONF_ON_VALUE, CONF_TRIGGER_ID, - CONF_MQTT_ID, - CONF_WEB_SERVER_ID, CONF_VALUE, + CONF_WEB_SERVER_ID, ) - from esphome.core import CORE, coroutine_with_priority from esphome.cpp_helpers import setup_entity diff --git a/esphome/components/text_sensor/__init__.py b/esphome/components/text_sensor/__init__.py index f4e795924c..ba8a2def41 100644 --- a/esphome/components/text_sensor/__init__.py +++ b/esphome/components/text_sensor/__init__.py @@ -1,21 +1,21 @@ -import esphome.codegen as cg -import esphome.config_validation as cv from esphome import automation +import esphome.codegen as cg from esphome.components import mqtt, web_server +import esphome.config_validation as cv from esphome.const import ( CONF_DEVICE_CLASS, CONF_ENTITY_CATEGORY, CONF_FILTERS, + CONF_FROM, CONF_ICON, CONF_ID, - CONF_ON_VALUE, - CONF_ON_RAW_VALUE, - CONF_TRIGGER_ID, CONF_MQTT_ID, - CONF_WEB_SERVER_ID, + CONF_ON_RAW_VALUE, + CONF_ON_VALUE, CONF_STATE, - CONF_FROM, CONF_TO, + CONF_TRIGGER_ID, + CONF_WEB_SERVER_ID, DEVICE_CLASS_DATE, DEVICE_CLASS_EMPTY, DEVICE_CLASS_TIMESTAMP, diff --git a/esphome/components/valve/__init__.py b/esphome/components/valve/__init__.py index c03d13fec8..3c03bab857 100644 --- a/esphome/components/valve/__init__.py +++ b/esphome/components/valve/__init__.py @@ -1,8 +1,8 @@ -import esphome.codegen as cg -import esphome.config_validation as cv from esphome import automation -from esphome.automation import maybe_simple_id, Condition +from esphome.automation import Condition, maybe_simple_id +import esphome.codegen as cg from esphome.components import mqtt, web_server +import esphome.config_validation as cv from esphome.const import ( CONF_DEVICE_CLASS, CONF_ID, From ddd80272386c923db6043e3659997c1e34398b3f Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 7 Aug 2024 18:33:12 +1200 Subject: [PATCH 1878/2101] [spi] Remove ``SPIDelegateDummy`` (#7215) --- esphome/components/spi/spi.cpp | 6 ------ esphome/components/spi/spi.h | 21 ++------------------- 2 files changed, 2 insertions(+), 25 deletions(-) diff --git a/esphome/components/spi/spi.cpp b/esphome/components/spi/spi.cpp index b13826c443..f9435b0424 100644 --- a/esphome/components/spi/spi.cpp +++ b/esphome/components/spi/spi.cpp @@ -7,10 +7,6 @@ namespace spi { const char *const TAG = "spi"; -SPIDelegate *const SPIDelegate::NULL_DELEGATE = // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) - new SPIDelegateDummy(); -// https://bugs.llvm.org/show_bug.cgi?id=48040 - bool SPIDelegate::is_ready() { return true; } GPIOPin *const NullPin::NULL_PIN = new NullPin(); // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) @@ -79,8 +75,6 @@ void SPIComponent::dump_config() { } } -void SPIDelegateDummy::begin_transaction() { ESP_LOGE(TAG, "SPIDevice not initialised - did you call spi_setup()?"); } - uint8_t SPIDelegateBitBash::transfer(uint8_t data) { return this->transfer_(data, 8); } void SPIDelegateBitBash::write(uint16_t data, size_t num_bits) { this->transfer_(data, num_bits); } diff --git a/esphome/components/spi/spi.h b/esphome/components/spi/spi.h index f581dc3f56..4cd8d3383c 100644 --- a/esphome/components/spi/spi.h +++ b/esphome/components/spi/spi.h @@ -163,8 +163,6 @@ class Utility { } }; -class SPIDelegateDummy; - // represents a device attached to an SPI bus, with a defined clock rate, mode and bit order. On Arduino this is // a thin wrapper over SPIClass. class SPIDelegate { @@ -250,21 +248,6 @@ class SPIDelegate { uint32_t data_rate_{1000000}; SPIMode mode_{MODE0}; GPIOPin *cs_pin_{NullPin::NULL_PIN}; - static SPIDelegate *const NULL_DELEGATE; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) -}; - -/** - * A dummy SPIDelegate that complains if it's used. - */ - -class SPIDelegateDummy : public SPIDelegate { - public: - SPIDelegateDummy() = default; - - uint8_t transfer(uint8_t data) override { return 0; } - void end_transaction() override{}; - - void begin_transaction() override; }; /** @@ -382,7 +365,7 @@ class SPIClient { virtual void spi_teardown() { this->parent_->unregister_device(this); - this->delegate_ = SPIDelegate::NULL_DELEGATE; + this->delegate_ = nullptr; } bool spi_is_ready() { return this->delegate_->is_ready(); } @@ -393,7 +376,7 @@ class SPIClient { uint32_t data_rate_{1000000}; SPIComponent *parent_{nullptr}; GPIOPin *cs_{nullptr}; - SPIDelegate *delegate_{SPIDelegate::NULL_DELEGATE}; + SPIDelegate *delegate_{nullptr}; }; /** From 132269c5b84c6c7502db239094bb14b27615de7e Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Wed, 7 Aug 2024 09:31:44 +0200 Subject: [PATCH 1879/2101] [code-quality] Apply ruff linting suggestions (#7206) --- esphome/config_validation.py | 2 +- esphome/mqtt.py | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/esphome/config_validation.py b/esphome/config_validation.py index 6e1d3ba2f9..ef60d6e0d6 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -91,7 +91,7 @@ _LOGGER = logging.getLogger(__name__) # pylint: disable=consider-using-f-string VARIABLE_PROG = re.compile( - "\\$([{0}]+|\\{{[{0}]*\\}})".format(VALID_SUBSTITUTIONS_CHARACTERS) + f"\\$([{VALID_SUBSTITUTIONS_CHARACTERS}]+|\\{{[{VALID_SUBSTITUTIONS_CHARACTERS}]*\\}})" ) # pylint: disable=invalid-name diff --git a/esphome/mqtt.py b/esphome/mqtt.py index d7e14a1d08..c1c45799cc 100644 --- a/esphome/mqtt.py +++ b/esphome/mqtt.py @@ -3,7 +3,6 @@ import hashlib import json import logging import ssl -import sys import time import paho.mqtt.client as mqtt @@ -103,10 +102,7 @@ def prepare( if config[CONF_MQTT].get(CONF_SSL_FINGERPRINTS) or config[CONF_MQTT].get( CONF_CERTIFICATE_AUTHORITY ): - if sys.version_info >= (2, 7, 13): - tls_version = ssl.PROTOCOL_TLS # pylint: disable=no-member - else: - tls_version = ssl.PROTOCOL_SSLv23 + tls_version = ssl.PROTOCOL_TLS # pylint: disable=no-member client.tls_set( ca_certs=None, certfile=None, From 2a8424a7f2022dced130a80139729015792b7f39 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Wed, 7 Aug 2024 09:32:06 +0200 Subject: [PATCH 1880/2101] [code-quality] Organise logger imports (#7205) --- esphome/components/logger/__init__.py | 33 ++++++++++++--------------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/esphome/components/logger/__init__.py b/esphome/components/logger/__init__.py index 99aa39c4ba..f30bc23e38 100644 --- a/esphome/components/logger/__init__.py +++ b/esphome/components/logger/__init__.py @@ -1,9 +1,21 @@ import re -import esphome.codegen as cg -import esphome.config_validation as cv from esphome import automation from esphome.automation import LambdaAction +import esphome.codegen as cg +from esphome.components.esp32 import add_idf_sdkconfig_option, get_esp32_variant +from esphome.components.esp32.const import ( + VARIANT_ESP32, + VARIANT_ESP32C2, + VARIANT_ESP32C3, + VARIANT_ESP32C6, + VARIANT_ESP32H2, + VARIANT_ESP32S2, + VARIANT_ESP32S3, +) +from esphome.components.libretiny import get_libretiny_component, get_libretiny_family +from esphome.components.libretiny.const import COMPONENT_BK72XX, COMPONENT_RTL87XX +import esphome.config_validation as cv from esphome.const import ( CONF_ARGS, CONF_BAUD_RATE, @@ -18,27 +30,12 @@ from esphome.const import ( CONF_TRIGGER_ID, CONF_TX_BUFFER_SIZE, PLATFORM_BK72XX, - PLATFORM_RTL87XX, PLATFORM_ESP32, PLATFORM_ESP8266, PLATFORM_RP2040, + PLATFORM_RTL87XX, ) from esphome.core import CORE, EsphomeError, Lambda, coroutine_with_priority -from esphome.components.esp32 import add_idf_sdkconfig_option, get_esp32_variant -from esphome.components.esp32.const import ( - VARIANT_ESP32, - VARIANT_ESP32S2, - VARIANT_ESP32C3, - VARIANT_ESP32S3, - VARIANT_ESP32C2, - VARIANT_ESP32C6, - VARIANT_ESP32H2, -) -from esphome.components.libretiny import get_libretiny_component, get_libretiny_family -from esphome.components.libretiny.const import ( - COMPONENT_BK72XX, - COMPONENT_RTL87XX, -) CODEOWNERS = ["@esphome/core"] logger_ns = cg.esphome_ns.namespace("logger") From 4b91ef5123e064d33975c928fa40e7cffaa5b468 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Wed, 7 Aug 2024 09:33:41 +0200 Subject: [PATCH 1881/2101] [code-quality] Apply ruff linting suggestions to core (#7207) --- esphome/core/__init__.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/esphome/core/__init__.py b/esphome/core/__init__.py index 9d3d14492e..a97c3b18c9 100644 --- a/esphome/core/__init__.py +++ b/esphome/core/__init__.py @@ -336,7 +336,7 @@ class ID: else: self.is_manual = is_manual self.is_declaration = is_declaration - self.type: Optional["MockObjClass"] = type + self.type: Optional[MockObjClass] = type def resolve(self, registered_ids): from esphome.config_validation import RESERVED_IDS @@ -500,7 +500,7 @@ class EsphomeCore: # The relative path to where all build files are stored self.build_path: Optional[str] = None # The validated configuration, this is None until the config has been validated - self.config: Optional["ConfigType"] = None + self.config: Optional[ConfigType] = None # The pending tasks in the task queue (mostly for C++ generation) # This is a priority queue (with heapq) # Each item is a tuple of form: (-priority, unique number, task) @@ -508,17 +508,17 @@ class EsphomeCore: # Task counter for pending tasks self.task_counter = 0 # The variable cache, for each ID this holds a MockObj of the variable obj - self.variables: dict[str, "MockObj"] = {} + self.variables: dict[str, MockObj] = {} # A list of statements that go in the main setup() block - self.main_statements: list["Statement"] = [] + self.main_statements: list[Statement] = [] # A list of statements to insert in the global block (includes and global variables) - self.global_statements: list["Statement"] = [] + self.global_statements: list[Statement] = [] # A set of platformio libraries to add to the project self.libraries: list[Library] = [] # A set of build flags to set in the platformio project self.build_flags: set[str] = set() # A set of defines to set for the compile process in esphome/core/defines.h - self.defines: set["Define"] = set() + self.defines: set[Define] = set() # A map of all platformio options to apply self.platformio_options: dict[str, Union[str, list[str]]] = {} # A set of strings of names of loaded integrations, used to find namespace ID conflicts From 9a9757ddebfc025d19c65c6c0c3467eeb887061f Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Thu, 8 Aug 2024 02:29:32 +0200 Subject: [PATCH 1882/2101] [code-quality] fix clang-tidy sprinkler (#7222) * fix clang-tidy * fix build error * clang-tidy * clang-tidy --- esphome/components/sprinkler/sprinkler.cpp | 4 ++-- esphome/components/sprinkler/sprinkler.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/sprinkler/sprinkler.cpp b/esphome/components/sprinkler/sprinkler.cpp index 982d9add1a..59565251c3 100644 --- a/esphome/components/sprinkler/sprinkler.cpp +++ b/esphome/components/sprinkler/sprinkler.cpp @@ -647,7 +647,7 @@ void Sprinkler::set_valve_run_duration(const optional 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() == min_str) { + if (this->valve_[valve_number.value()].run_duration_number->traits.get_unit_of_measurement() == MIN_STR) { call.set_value(run_duration.value() / 60.0); } else { call.set_value(run_duration.value()); @@ -729,7 +729,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() == min_str) { + if (this->valve_[valve_number].run_duration_number->traits.get_unit_of_measurement() == MIN_STR) { return static_cast(roundf(this->valve_[valve_number].run_duration_number->state * 60)); } else { return static_cast(roundf(this->valve_[valve_number].run_duration_number->state)); diff --git a/esphome/components/sprinkler/sprinkler.h b/esphome/components/sprinkler/sprinkler.h index 5311ae4c05..c4a8b8aeb8 100644 --- a/esphome/components/sprinkler/sprinkler.h +++ b/esphome/components/sprinkler/sprinkler.h @@ -11,7 +11,7 @@ namespace esphome { namespace sprinkler { -const std::string min_str = "min"; +const std::string MIN_STR = "min"; enum SprinklerState : uint8_t { // NOTE: these states are used by both SprinklerValveOperator and Sprinkler (the controller)! From 24b6c1d3eb85e1c50552a2aff040e0250d749e26 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Thu, 8 Aug 2024 02:30:49 +0200 Subject: [PATCH 1883/2101] [code-quality] __attribute__((packed)) (#7221) --- esphome/components/climate/climate.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/climate/climate.h b/esphome/components/climate/climate.h index 7c2a0b1ed3..d81702fb0c 100644 --- a/esphome/components/climate/climate.h +++ b/esphome/components/climate/climate.h @@ -141,7 +141,7 @@ struct ClimateDeviceRestoreState { float target_temperature_low; float target_temperature_high; }; - }; + } __attribute__((packed)); float target_humidity; /// Convert this struct to a climate call that can be performed. From 7fd65987d33f21433975ef252c29f20a33ef33a0 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 8 Aug 2024 03:29:49 +0100 Subject: [PATCH 1884/2101] hx711: Check for DOUT going high after a reading (#7214) --- esphome/components/hx711/hx711.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/esphome/components/hx711/hx711.cpp b/esphome/components/hx711/hx711.cpp index dbbf4c91f4..1a7169eed7 100644 --- a/esphome/components/hx711/hx711.cpp +++ b/esphome/components/hx711/hx711.cpp @@ -39,8 +39,8 @@ bool HX711Sensor::read_sensor_(uint32_t *result) { return false; } - this->status_clear_warning(); uint32_t data = 0; + bool final_dout; { InterruptLock lock; @@ -59,8 +59,17 @@ bool HX711Sensor::read_sensor_(uint32_t *result) { this->sck_pin_->digital_write(false); delayMicroseconds(1); } + final_dout = this->dout_pin_->digital_read(); } + if (!final_dout) { + ESP_LOGW(TAG, "HX711 DOUT pin not high after reading (data 0x%" PRIx32 ")!", data); + this->status_set_warning(); + return false; + } + + this->status_clear_warning(); + if (data & 0x800000ULL) { data |= 0xFF000000ULL; } From 3f1d2c0cafe246c88e4d257b36e70c5e3be4ec71 Mon Sep 17 00:00:00 2001 From: dentra Date: Thu, 8 Aug 2024 07:49:37 +0300 Subject: [PATCH 1885/2101] [mqtt] Add extended device info (#7194) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/mqtt/mqtt_component.cpp | 36 +++++++++++++++++++--- esphome/components/mqtt/mqtt_const.h | 2 ++ 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/esphome/components/mqtt/mqtt_component.cpp b/esphome/components/mqtt/mqtt_component.cpp index bb46ce732d..295fbba5e5 100644 --- a/esphome/components/mqtt/mqtt_component.cpp +++ b/esphome/components/mqtt/mqtt_component.cpp @@ -150,12 +150,40 @@ bool MQTTComponent::send_discovery_() { const std::string &node_area = App.get_area(); JsonObject device_info = root.createNestedObject(MQTT_DEVICE); - device_info[MQTT_DEVICE_IDENTIFIERS] = get_mac_address(); + const auto mac = get_mac_address(); + device_info[MQTT_DEVICE_IDENTIFIERS] = mac; device_info[MQTT_DEVICE_NAME] = node_friendly_name; - device_info[MQTT_DEVICE_SW_VERSION] = "esphome v" ESPHOME_VERSION " " + App.get_compilation_time(); +#ifdef ESPHOME_PROJECT_NAME + device_info[MQTT_DEVICE_SW_VERSION] = ESPHOME_PROJECT_VERSION " (ESPHome " ESPHOME_VERSION ")"; + const char *model = std::strchr(ESPHOME_PROJECT_NAME, '.'); + if (model == nullptr) { // must never happen but check anyway + device_info[MQTT_DEVICE_MODEL] = ESPHOME_BOARD; + device_info[MQTT_DEVICE_MANUFACTURER] = ESPHOME_PROJECT_NAME; + } else { + device_info[MQTT_DEVICE_MODEL] = model + 1; + device_info[MQTT_DEVICE_MANUFACTURER] = std::string(ESPHOME_PROJECT_NAME, model - ESPHOME_PROJECT_NAME); + } +#else + device_info[MQTT_DEVICE_SW_VERSION] = ESPHOME_VERSION " (" + App.get_compilation_time() + ")"; device_info[MQTT_DEVICE_MODEL] = ESPHOME_BOARD; - device_info[MQTT_DEVICE_MANUFACTURER] = "espressif"; - device_info[MQTT_DEVICE_SUGGESTED_AREA] = node_area; +#if defined(USE_ESP8266) || defined(USE_ESP32) + device_info[MQTT_DEVICE_MANUFACTURER] = "Espressif"; +#elif defined(USE_RP2040) + device_info[MQTT_DEVICE_MANUFACTURER] = "Raspberry Pi"; +#elif defined(USE_BK72XX) + device_info[MQTT_DEVICE_MANUFACTURER] = "Beken"; +#elif defined(USE_RTL87XX) + device_info[MQTT_DEVICE_MANUFACTURER] = "Realtek"; +#elif defined(USE_HOST) + device_info[MQTT_DEVICE_MANUFACTURER] = "Host"; +#endif +#endif + if (!node_area.empty()) { + device_info[MQTT_DEVICE_SUGGESTED_AREA] = node_area; + } + + device_info[MQTT_DEVICE_CONNECTIONS][0][0] = "mac"; + device_info[MQTT_DEVICE_CONNECTIONS][0][1] = mac; }, this->qos_, discovery_info.retain); } diff --git a/esphome/components/mqtt/mqtt_const.h b/esphome/components/mqtt/mqtt_const.h index 0e063c66d2..71f169fbe8 100644 --- a/esphome/components/mqtt/mqtt_const.h +++ b/esphome/components/mqtt/mqtt_const.h @@ -62,6 +62,7 @@ constexpr const char *const MQTT_DEVICE_MODEL = "mdl"; constexpr const char *const MQTT_DEVICE_NAME = "name"; constexpr const char *const MQTT_DEVICE_SUGGESTED_AREA = "sa"; constexpr const char *const MQTT_DEVICE_SW_VERSION = "sw"; +constexpr const char *const MQTT_DEVICE_HW_VERSION = "hw"; constexpr const char *const MQTT_DOCKED_TEMPLATE = "dock_tpl"; constexpr const char *const MQTT_DOCKED_TOPIC = "dock_t"; constexpr const char *const MQTT_EFFECT_COMMAND_TOPIC = "fx_cmd_t"; @@ -322,6 +323,7 @@ constexpr const char *const MQTT_DEVICE_MODEL = "model"; constexpr const char *const MQTT_DEVICE_NAME = "name"; constexpr const char *const MQTT_DEVICE_SUGGESTED_AREA = "suggested_area"; constexpr const char *const MQTT_DEVICE_SW_VERSION = "sw_version"; +constexpr const char *const MQTT_DEVICE_HW_VERSION = "hw_version"; constexpr const char *const MQTT_DOCKED_TEMPLATE = "docked_template"; constexpr const char *const MQTT_DOCKED_TOPIC = "docked_topic"; constexpr const char *const MQTT_EFFECT_COMMAND_TOPIC = "effect_command_topic"; From a3d5b69a9c7690efcfb3441e2d69166bb8cc703e Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Thu, 8 Aug 2024 07:02:41 +0200 Subject: [PATCH 1886/2101] [code-quality] NOLINT readability-identifier-naming (#7220) --- esphome/core/entity_base.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/core/entity_base.h b/esphome/core/entity_base.h index 434111de79..4ca21f9ee5 100644 --- a/esphome/core/entity_base.h +++ b/esphome/core/entity_base.h @@ -63,7 +63,7 @@ class EntityBase { EntityCategory entity_category_{ENTITY_CATEGORY_NONE}; }; -class EntityBase_DeviceClass { +class EntityBase_DeviceClass { // NOLINT(readability-identifier-naming) public: /// Get the device class, using the manual override if set. std::string get_device_class(); @@ -74,7 +74,7 @@ class EntityBase_DeviceClass { const char *device_class_{nullptr}; ///< Device class override }; -class EntityBase_UnitOfMeasurement { +class EntityBase_UnitOfMeasurement { // NOLINT(readability-identifier-naming) public: /// Get the unit of measurement, using the manual override if set. std::string get_unit_of_measurement(); From b71c03424ecf1aaa74a12bdc86e28bdbed9488dd Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Thu, 8 Aug 2024 07:02:55 +0200 Subject: [PATCH 1887/2101] [code-quality] Organise time imports (#7219) --- esphome/components/time/__init__.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/esphome/components/time/__init__.py b/esphome/components/time/__init__.py index c888705ba2..6a3368ca73 100644 --- a/esphome/components/time/__init__.py +++ b/esphome/components/time/__init__.py @@ -1,32 +1,32 @@ -import logging from importlib import resources +import logging from typing import Optional import tzlocal +from esphome import automation +from esphome.automation import Condition import esphome.codegen as cg import esphome.config_validation as cv -from esphome import automation from esphome.const import ( - CONF_ID, + CONF_AT, CONF_CRON, CONF_DAYS_OF_MONTH, CONF_DAYS_OF_WEEK, + CONF_HOUR, CONF_HOURS, + CONF_ID, + CONF_MINUTE, CONF_MINUTES, CONF_MONTHS, CONF_ON_TIME, CONF_ON_TIME_SYNC, + CONF_SECOND, CONF_SECONDS, CONF_TIMEZONE, CONF_TRIGGER_ID, - CONF_AT, - CONF_SECOND, - CONF_HOUR, - CONF_MINUTE, ) from esphome.core import coroutine_with_priority -from esphome.automation import Condition _LOGGER = logging.getLogger(__name__) From a47a17d7e7d4649d7a92c3fb96c921374b14d2d6 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Thu, 8 Aug 2024 18:24:10 +1000 Subject: [PATCH 1888/2101] [lvgl] Fix set state on updates (#7227) --- esphome/components/lvgl/lvgl_esphome.h | 4 ++-- esphome/components/lvgl/widgets/__init__.py | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/esphome/components/lvgl/lvgl_esphome.h b/esphome/components/lvgl/lvgl_esphome.h index 45841b99d9..1497e1004a 100644 --- a/esphome/components/lvgl/lvgl_esphome.h +++ b/esphome/components/lvgl/lvgl_esphome.h @@ -1,9 +1,9 @@ #pragma once #include "esphome/core/defines.h" -#ifdef USE_LVGL_BINARY_SENSOR +#ifdef USE_BINARY_SENSOR #include "esphome/components/binary_sensor/binary_sensor.h" -#endif // USE_LVGL_BINARY_SENSOR +#endif // USE_BINARY_SENSOR #ifdef USE_LVGL_ROTARY_ENCODER #include "esphome/components/rotary_encoder/rotary_encoder.h" #endif // USE_LVGL_ROTARY_ENCODER diff --git a/esphome/components/lvgl/widgets/__init__.py b/esphome/components/lvgl/widgets/__init__.py index f1946015bc..603de6aa3e 100644 --- a/esphome/components/lvgl/widgets/__init__.py +++ b/esphome/components/lvgl/widgets/__init__.py @@ -271,6 +271,7 @@ async def set_obj_properties(w: Widget, config): """Generate a list of C++ statements to apply properties to an lv_obj_t""" 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 layout_type == TYPE_GRID: wid = config[CONF_ID] @@ -334,7 +335,7 @@ async def set_obj_properties(w: Widget, config): for key, value in states.items(): if isinstance(value, cv.Lambda): lambs[key] = value - elif value == "true": + elif value: adds.add(key) else: clears.add(key) From b43c5b851aaaf15f170dbaf23a6ec5feaf4ee664 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Fri, 9 Aug 2024 13:15:25 +0200 Subject: [PATCH 1889/2101] add missing overrides (#7231) --- esphome/components/lvgl/number/lvgl_number.h | 2 +- esphome/components/lvgl/switch/lvgl_switch.h | 2 +- esphome/components/lvgl/text/lvgl_text.h | 2 +- esphome/components/spi_led_strip/spi_led_strip.h | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/esphome/components/lvgl/number/lvgl_number.h b/esphome/components/lvgl/number/lvgl_number.h index 461ea51be4..659fc615c9 100644 --- a/esphome/components/lvgl/number/lvgl_number.h +++ b/esphome/components/lvgl/number/lvgl_number.h @@ -19,7 +19,7 @@ class LVGLNumber : public number::Number { } protected: - void control(float value) { + void control(float value) override { if (this->control_lambda_ != nullptr) this->control_lambda_(value); else diff --git a/esphome/components/lvgl/switch/lvgl_switch.h b/esphome/components/lvgl/switch/lvgl_switch.h index f20f4ed960..67be11faba 100644 --- a/esphome/components/lvgl/switch/lvgl_switch.h +++ b/esphome/components/lvgl/switch/lvgl_switch.h @@ -19,7 +19,7 @@ class LVGLSwitch : public switch_::Switch { } protected: - void write_state(bool value) { + void write_state(bool value) override { if (this->state_lambda_ != nullptr) this->state_lambda_(value); else diff --git a/esphome/components/lvgl/text/lvgl_text.h b/esphome/components/lvgl/text/lvgl_text.h index 8dc0281364..4bd5b76744 100644 --- a/esphome/components/lvgl/text/lvgl_text.h +++ b/esphome/components/lvgl/text/lvgl_text.h @@ -19,7 +19,7 @@ class LVGLText : public text::Text { } protected: - void control(const std::string &value) { + void control(const std::string &value) override { if (this->control_lambda_ != nullptr) this->control_lambda_(value); else diff --git a/esphome/components/spi_led_strip/spi_led_strip.h b/esphome/components/spi_led_strip/spi_led_strip.h index 0d8c1c1e1c..8b713378ec 100644 --- a/esphome/components/spi_led_strip/spi_led_strip.h +++ b/esphome/components/spi_led_strip/spi_led_strip.h @@ -13,7 +13,7 @@ class SpiLedStrip : public light::AddressableLight, public spi::SPIDevice { public: - void setup() { this->spi_setup(); } + void setup() override { this->spi_setup(); } int32_t size() const override { return this->num_leds_; } @@ -43,7 +43,7 @@ class SpiLedStrip : public light::AddressableLight, memset(this->buf_, 0, 4); } - void dump_config() { + void dump_config() override { esph_log_config(TAG, "SPI LED Strip:"); esph_log_config(TAG, " LEDs: %d", this->num_leds_); if (this->data_rate_ >= spi::DATA_RATE_1MHZ) From 15602b0664b71ac6362e5cf4ff3c0e94cf066c38 Mon Sep 17 00:00:00 2001 From: Michael Davidson Date: Mon, 12 Aug 2024 06:06:29 +1000 Subject: [PATCH 1890/2101] Add text_align_to_string (#7243) --- esphome/components/display/display.cpp | 31 ++++++++++++++++++++++++++ esphome/components/display/display.h | 3 +++ 2 files changed, 34 insertions(+) diff --git a/esphome/components/display/display.cpp b/esphome/components/display/display.cpp index 75205292f7..63c74e09ca 100644 --- a/esphome/components/display/display.cpp +++ b/esphome/components/display/display.cpp @@ -675,5 +675,36 @@ void DisplayPage::set_prev(DisplayPage *prev) { this->prev_ = prev; } void DisplayPage::set_next(DisplayPage *next) { this->next_ = next; } const display_writer_t &DisplayPage::get_writer() const { return this->writer_; } +const LogString *text_align_to_string(TextAlign textalign) { + switch (textalign) { + case TextAlign::TOP_LEFT: + return LOG_STR("TOP_LEFT"); + case TextAlign::TOP_CENTER: + return LOG_STR("TOP_CENTER"); + case TextAlign::TOP_RIGHT: + return LOG_STR("TOP_RIGHT"); + case TextAlign::CENTER_LEFT: + return LOG_STR("CENTER_LEFT"); + case TextAlign::CENTER: + return LOG_STR("CENTER"); + case TextAlign::CENTER_RIGHT: + return LOG_STR("CENTER_RIGHT"); + case TextAlign::BASELINE_LEFT: + return LOG_STR("BASELINE_LEFT"); + case TextAlign::BASELINE_CENTER: + return LOG_STR("BASELINE_CENTER"); + case TextAlign::BASELINE_RIGHT: + return LOG_STR("BASELINE_RIGHT"); + case TextAlign::BOTTOM_LEFT: + return LOG_STR("BOTTOM_LEFT"); + case TextAlign::BOTTOM_CENTER: + return LOG_STR("BOTTOM_CENTER"); + case TextAlign::BOTTOM_RIGHT: + return LOG_STR("BOTTOM_RIGHT"); + default: + return LOG_STR("UNKNOWN"); + } +} + } // namespace display } // namespace esphome diff --git a/esphome/components/display/display.h b/esphome/components/display/display.h index 4ee7ef93cb..34feafea6e 100644 --- a/esphome/components/display/display.h +++ b/esphome/components/display/display.h @@ -8,6 +8,7 @@ #include "esphome/core/color.h" #include "esphome/core/automation.h" #include "esphome/core/time.h" +#include "esphome/core/log.h" #include "display_color_utils.h" #ifdef USE_GRAPH @@ -737,5 +738,7 @@ class DisplayOnPageChangeTrigger : public Trigger DisplayPage *to_{nullptr}; }; +const LogString *text_align_to_string(TextAlign textalign); + } // namespace display } // namespace esphome From 442e765187e73aeff3e24f727de5662359943493 Mon Sep 17 00:00:00 2001 From: Nis Wechselberg Date: Mon, 12 Aug 2024 04:18:11 +0200 Subject: [PATCH 1891/2101] [sml] Fixed crashing sml parser (#7235) --- esphome/components/sml/sml_parser.cpp | 72 ++++++++++++++++++--------- 1 file changed, 49 insertions(+), 23 deletions(-) diff --git a/esphome/components/sml/sml_parser.cpp b/esphome/components/sml/sml_parser.cpp index c782c0fc5e..2cc71e87fa 100644 --- a/esphome/components/sml/sml_parser.cpp +++ b/esphome/components/sml/sml_parser.cpp @@ -10,7 +10,7 @@ SmlFile::SmlFile(bytes buffer) : buffer_(std::move(buffer)) { this->pos_ = 0; while (this->pos_ < this->buffer_.size()) { if (this->buffer_[this->pos_] == 0x00) - break; // fill byte detected -> no more messages + break; // EndOfSmlMsg SmlNode message = SmlNode(); if (!this->setup_node(&message)) @@ -20,40 +20,66 @@ SmlFile::SmlFile(bytes buffer) : buffer_(std::move(buffer)) { } bool SmlFile::setup_node(SmlNode *node) { - uint8_t type = this->buffer_[this->pos_] >> 4; // type including overlength info - uint8_t length = this->buffer_[this->pos_] & 0x0f; // length including TL bytes - bool is_list = (type & 0x07) == SML_LIST; - bool has_extended_length = type & 0x08; // we have a long list/value (>15 entries) - uint8_t parse_length = length; - if (has_extended_length) { - length = (length << 4) + (this->buffer_[this->pos_ + 1] & 0x0f); - parse_length = length; + // If the TL field is 0x00, this is the end of the message + // (see 6.3.1 of SML protocol definition) + if (this->buffer_[this->pos_] == 0x00) { + // Increment past this byte and signal that the message is done this->pos_ += 1; + return true; } - if (this->pos_ + parse_length >= this->buffer_.size()) + // Extract data from initial TL field + uint8_t type = (this->buffer_[this->pos_] >> 4) & 0x07; // type without overlength info + bool overlength = (this->buffer_[this->pos_] >> 4) & 0x08; // overlength information + uint8_t length = this->buffer_[this->pos_] & 0x0f; // length (including TL bytes) + + // Check if we need additional length bytes + if (overlength) { + // 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); + // We are basically done with the first TL field now, + // so increment past that, we now point to the second TL field + this->pos_ += 1; + // Decrement the length for value fields (not lists), + // since the byte we just handled is counted as part of the field + // in case of values but not for lists + if (type != SML_LIST) + length -= 1; + + // Technically, this is not enough, the standard allows for more than two length fields. + // However I don't think it is very common to have more than 255 entries in a list + } + + // We are done with the last TL field(s), so advance the position + this->pos_ += 1; + // and decrement the length for non-list fields + if (type != SML_LIST) + length -= 1; + + // Check if the buffer length is long enough + if (this->pos_ + length > this->buffer_.size()) return false; - node->type = type & 0x07; + node->type = type; node->nodes.clear(); node->value_bytes.clear(); - // if the list is a has_extended_length list with e.g. 16 elements this is a 0x00 byte but not the end of message - if (!has_extended_length && this->buffer_[this->pos_] == 0x00) { // end of message - this->pos_ += 1; - } else if (is_list) { // list - this->pos_ += 1; - node->nodes.reserve(parse_length); - for (size_t i = 0; i != parse_length; i++) { + if (type == SML_LIST) { + node->nodes.reserve(length); + for (size_t i = 0; i != length; i++) { SmlNode child_node = SmlNode(); if (!this->setup_node(&child_node)) return false; node->nodes.emplace_back(child_node); } - } else { // value - node->value_bytes = - bytes(this->buffer_.begin() + this->pos_ + 1, this->buffer_.begin() + this->pos_ + parse_length); - this->pos_ += parse_length; + } else { + // Value starts at the current position + // Value ends "length" bytes later, + // (since the TL field is counted but already subtracted from length) + node->value_bytes = bytes(this->buffer_.begin() + this->pos_, this->buffer_.begin() + this->pos_ + length); + // Increment the pointer past all consumed bytes + this->pos_ += length; } return true; } @@ -101,7 +127,7 @@ int64_t bytes_to_int(const bytes &buffer) { // see https://stackoverflow.com/questions/42534749/signed-extension-from-24-bit-to-32-bit-in-c if (buffer.size() < 8) { const int bits = buffer.size() * 8; - const uint64_t m = 1u << (bits - 1); + const uint64_t m = 1ull << (bits - 1); tmp = (tmp ^ m) - m; } From d04e706295a495c0b8dbbf08c6ad95bbfa623712 Mon Sep 17 00:00:00 2001 From: Flo Date: Mon, 12 Aug 2024 04:20:51 +0200 Subject: [PATCH 1892/2101] Allow project name and version as improv_serial identity (#7248) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/improv_serial/__init__.py | 14 ++++---------- .../improv_serial/improv_serial_component.cpp | 4 ++++ 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/esphome/components/improv_serial/__init__.py b/esphome/components/improv_serial/__init__.py index 2b377d77b8..544af212e0 100644 --- a/esphome/components/improv_serial/__init__.py +++ b/esphome/components/improv_serial/__init__.py @@ -1,12 +1,10 @@ +import esphome.codegen as cg from esphome.components import improv_base from esphome.components.esp32 import get_esp32_variant -from esphome.components.esp32.const import ( - VARIANT_ESP32S3, -) +from esphome.components.esp32.const import VARIANT_ESP32S3 from esphome.components.logger import USB_CDC -from esphome.const import CONF_BAUD_RATE, CONF_HARDWARE_UART, CONF_ID, CONF_LOGGER -import esphome.codegen as cg import esphome.config_validation as cv +from esphome.const import CONF_BAUD_RATE, CONF_HARDWARE_UART, CONF_ID, CONF_LOGGER from esphome.core import CORE import esphome.final_validate as fv @@ -19,11 +17,7 @@ improv_serial_ns = cg.esphome_ns.namespace("improv_serial") ImprovSerialComponent = improv_serial_ns.class_("ImprovSerialComponent", cg.Component) CONFIG_SCHEMA = ( - cv.Schema( - { - cv.GenerateID(): cv.declare_id(ImprovSerialComponent), - } - ) + cv.Schema({cv.GenerateID(): cv.declare_id(ImprovSerialComponent)}) .extend(improv_base.IMPROV_SCHEMA) .extend(cv.COMPONENT_SCHEMA) ) diff --git a/esphome/components/improv_serial/improv_serial_component.cpp b/esphome/components/improv_serial/improv_serial_component.cpp index 12809e38cb..425a5c8576 100644 --- a/esphome/components/improv_serial/improv_serial_component.cpp +++ b/esphome/components/improv_serial/improv_serial_component.cpp @@ -170,7 +170,11 @@ std::vector ImprovSerialComponent::build_rpc_settings_response_(improv: } std::vector ImprovSerialComponent::build_version_info_() { +#ifdef ESPHOME_PROJECT_NAME + std::vector infos = {ESPHOME_PROJECT_NAME, ESPHOME_PROJECT_VERSION, ESPHOME_VARIANT, App.get_name()}; +#else std::vector infos = {"ESPHome", ESPHOME_VERSION, ESPHOME_VARIANT, App.get_name()}; +#endif std::vector data = improv::build_rpc_response(improv::GET_DEVICE_INFO, infos, false); return data; }; From 34d435c99643280c297e0741a14a58574e7c879e Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Mon, 12 Aug 2024 13:56:54 +1000 Subject: [PATCH 1893/2101] [lvgl] Implement default group for encoders (#7242) Co-authored-by: clydeps --- esphome/components/lvgl/__init__.py | 6 ++++-- esphome/components/lvgl/defines.py | 1 + esphome/components/lvgl/encoders.py | 10 +++++++--- esphome/components/lvgl/touchscreens.py | 2 +- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/esphome/components/lvgl/__init__.py b/esphome/components/lvgl/__init__.py index 87fbcab4dc..6bf6e287f8 100644 --- a/esphome/components/lvgl/__init__.py +++ b/esphome/components/lvgl/__init__.py @@ -47,6 +47,7 @@ from .types import ( IdleTrigger, ObjUpdateAction, lv_font_t, + lv_group_t, lv_style_t, lvgl_ns, ) @@ -335,8 +336,9 @@ CONFIG_SCHEMA = ( cv.Optional(df.CONF_THEME): cv.Schema( {cv.Optional(name): obj_schema(w) for name, w in WIDGET_TYPES.items()} ), - cv.GenerateID(df.CONF_TOUCHSCREENS): touchscreen_schema, - cv.GenerateID(df.CONF_ENCODERS): ENCODERS_CONFIG, + cv.Optional(df.CONF_TOUCHSCREENS, default=None): touchscreen_schema, + cv.Optional(df.CONF_ENCODERS, default=None): ENCODERS_CONFIG, + cv.GenerateID(df.CONF_DEFAULT_GROUP): cv.declare_id(lv_group_t), } ) .extend(DISP_BG_SCHEMA) diff --git a/esphome/components/lvgl/defines.py b/esphome/components/lvgl/defines.py index d0047b59f7..1c6fd2678c 100644 --- a/esphome/components/lvgl/defines.py +++ b/esphome/components/lvgl/defines.py @@ -386,6 +386,7 @@ CONF_COLOR_DEPTH = "color_depth" CONF_CONTROL = "control" CONF_DEFAULT = "default" CONF_DEFAULT_FONT = "default_font" +CONF_DEFAULT_GROUP = "default_group" CONF_DIR = "dir" CONF_DISPLAYS = "displays" CONF_ENCODERS = "encoders" diff --git a/esphome/components/lvgl/encoders.py b/esphome/components/lvgl/encoders.py index caddc2e47f..cfd0e42996 100644 --- a/esphome/components/lvgl/encoders.py +++ b/esphome/components/lvgl/encoders.py @@ -5,6 +5,7 @@ import esphome.config_validation as cv from esphome.const import CONF_GROUP, CONF_ID, CONF_SENSOR from .defines import ( + CONF_DEFAULT_GROUP, CONF_ENCODERS, CONF_ENTER_BUTTON, CONF_LEFT_BUTTON, @@ -38,7 +39,10 @@ ENCODERS_CONFIG = cv.ensure_list( async def encoders_to_code(var, config): - for enc_conf in config.get(CONF_ENCODERS, ()): + default_group = lv_Pvariable(lv_group_t, config[CONF_DEFAULT_GROUP]) + lv_assign(default_group, lv_expr.group_create()) + lv.group_set_default(default_group) + for enc_conf in config[CONF_ENCODERS]: lvgl_components_required.add("KEY_LISTENER") lpt = enc_conf[CONF_LONG_PRESS_TIME].total_milliseconds lprt = enc_conf[CONF_LONG_PRESS_REPEAT_TIME].total_milliseconds @@ -60,6 +64,6 @@ async def encoders_to_code(var, config): if group := enc_conf.get(CONF_GROUP): group = lv_Pvariable(lv_group_t, group) lv_assign(group, lv_expr.group_create()) - lv.indev_set_group(lv_expr.indev_drv_register(listener.get_drv()), group) else: - lv.indev_drv_register(listener.get_drv()) + group = default_group + lv.indev_set_group(lv_expr.indev_drv_register(listener.get_drv()), group) diff --git a/esphome/components/lvgl/touchscreens.py b/esphome/components/lvgl/touchscreens.py index 292b0873f3..4d430a428e 100644 --- a/esphome/components/lvgl/touchscreens.py +++ b/esphome/components/lvgl/touchscreens.py @@ -34,7 +34,7 @@ def touchscreen_schema(config): async def touchscreens_to_code(var, config): - for tconf in config.get(CONF_TOUCHSCREENS, ()): + for tconf in config[CONF_TOUCHSCREENS]: lvgl_components_required.add(CONF_TOUCHSCREEN) touchscreen = await cg.get_variable(tconf[CONF_TOUCHSCREEN_ID]) lpt = tconf[CONF_LONG_PRESS_TIME].total_milliseconds From f2e99fa3192f3792189c73326be5fa6563cdf032 Mon Sep 17 00:00:00 2001 From: "David K." <142583+neffs@users.noreply.github.com> Date: Mon, 12 Aug 2024 06:14:58 +0200 Subject: [PATCH 1894/2101] [bme68x_bsec2_i2c] BME68X Temperature+Pressure+Humidity+Gas Sensor via BSEC2 (#4585) * Added initial bme68x component * Initialize all child sensors to nullptr This was added to all other sensors in #3808 * Update BSEC2 and BME68x Libraries Current versions from Bosch Sensortec * Add myself to codeowners for bme68x_bsec * Move constants to const.py, according to ci-custom checks Move constants to const.py, according to ci-custom checks * Update library dependencies We'll stick with 1.4.2200 for now. 1.4.2200 is not on platform.io registry, use tag instead. Update to 1.5.2400 needs some work due to multi instance support. * Update BSEC2 to 1.6.2400 * Add consts to bme680x_bsec Enable inclusion with external_components * Update device class for pressure * Update to use multisensor API * Tidy up some constants * Add tests * Remove scd30 changes * Import CONF_SAMPLE_RATE * Pull BSEC config blob from repo based on config * Rename component to `bme68x_bsec_i2c` * Fix tests + codeowners * Cleanup for review * Rename using `bsec2` * Apply suggestions from code review Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> * Download file during validation stage, instead * Make `dump_config()` only dump stuff * Compile safely without sensor and text sensor headers * Use `intf_ptr` * Save state if measuring static IAQ, too * Update CODEOWNERS * Simplify esphome/components/bme68x_bsec2_i2c/__init__.py Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> * Remove extraneous colon & imports * Track & save the maximum accuracy value * Polish up accuracy sensor handling * Log static sensor, update `defines.h` * Walruses make it better * Add some logging of setup failures * Update esphome/components/bme68x_bsec2_i2c/bme68x_bsec2_i2c.cpp Co-authored-by: Trevor North * Break out some things * Update CODEOWNERS * Update CODEOWNERS take 2 * Use `add_extra` in base schema * Another walrus in the sensor Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --------- Co-authored-by: Keith Burzinski Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Co-authored-by: Trevor North --- CODEOWNERS | 2 + esphome/components/bme68x_bsec2/__init__.py | 196 +++++++ .../components/bme68x_bsec2/bme68x_bsec2.cpp | 523 ++++++++++++++++++ .../components/bme68x_bsec2/bme68x_bsec2.h | 163 ++++++ esphome/components/bme68x_bsec2/sensor.py | 130 +++++ .../components/bme68x_bsec2/text_sensor.py | 33 ++ .../components/bme68x_bsec2_i2c/__init__.py | 28 + .../bme68x_bsec2_i2c/bme68x_bsec2_i2c.cpp | 53 ++ .../bme68x_bsec2_i2c/bme68x_bsec2_i2c.h | 28 + esphome/core/defines.h | 3 +- tests/components/bme68x_bsec2_i2c/common.yaml | 34 ++ .../bme68x_bsec2_i2c/test.esp32-ard.yaml | 5 + .../bme68x_bsec2_i2c/test.esp32-c3-ard.yaml | 5 + .../bme68x_bsec2_i2c/test.esp32-s2-ard.yaml | 5 + .../bme68x_bsec2_i2c/test.esp32-s3-ard.yaml | 5 + .../bme68x_bsec2_i2c/test.esp8266-ard.yaml | 5 + 16 files changed, 1217 insertions(+), 1 deletion(-) create mode 100644 esphome/components/bme68x_bsec2/__init__.py create mode 100644 esphome/components/bme68x_bsec2/bme68x_bsec2.cpp create mode 100644 esphome/components/bme68x_bsec2/bme68x_bsec2.h create mode 100644 esphome/components/bme68x_bsec2/sensor.py create mode 100644 esphome/components/bme68x_bsec2/text_sensor.py create mode 100644 esphome/components/bme68x_bsec2_i2c/__init__.py create mode 100644 esphome/components/bme68x_bsec2_i2c/bme68x_bsec2_i2c.cpp create mode 100644 esphome/components/bme68x_bsec2_i2c/bme68x_bsec2_i2c.h create mode 100644 tests/components/bme68x_bsec2_i2c/common.yaml create mode 100644 tests/components/bme68x_bsec2_i2c/test.esp32-ard.yaml create mode 100644 tests/components/bme68x_bsec2_i2c/test.esp32-c3-ard.yaml create mode 100644 tests/components/bme68x_bsec2_i2c/test.esp32-s2-ard.yaml create mode 100644 tests/components/bme68x_bsec2_i2c/test.esp32-s3-ard.yaml create mode 100644 tests/components/bme68x_bsec2_i2c/test.esp8266-ard.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 82e6e0ea4b..999449a3df 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -65,6 +65,8 @@ esphome/components/bluetooth_proxy/* @jesserockz esphome/components/bme280_base/* @esphome/core esphome/components/bme280_spi/* @apbodrov esphome/components/bme680_bsec/* @trvrnrth +esphome/components/bme68x_bsec2/* @kbx81 @neffs +esphome/components/bme68x_bsec2_i2c/* @kbx81 @neffs esphome/components/bmi160/* @flaviut esphome/components/bmp3xx/* @latonita esphome/components/bmp3xx_base/* @latonita @martgras diff --git a/esphome/components/bme68x_bsec2/__init__.py b/esphome/components/bme68x_bsec2/__init__.py new file mode 100644 index 0000000000..1930c7c9e3 --- /dev/null +++ b/esphome/components/bme68x_bsec2/__init__.py @@ -0,0 +1,196 @@ +import hashlib +from pathlib import Path + +from esphome import core, external_files +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.const import ( + CONF_ID, + CONF_MODEL, + CONF_RAW_DATA_ID, + CONF_SAMPLE_RATE, + CONF_TEMPERATURE_OFFSET, +) + +CODEOWNERS = ["@neffs", "@kbx81"] + +DOMAIN = "bme68x_bsec2" + +BSEC2_LIBRARY_VERSION = "v1.7.2502" + +CONF_ALGORITHM_OUTPUT = "algorithm_output" +CONF_BME68X_BSEC2_ID = "bme68x_bsec2_id" +CONF_IAQ_MODE = "iaq_mode" +CONF_OPERATING_AGE = "operating_age" +CONF_STATE_SAVE_INTERVAL = "state_save_interval" +CONF_SUPPLY_VOLTAGE = "supply_voltage" + +bme68x_bsec2_ns = cg.esphome_ns.namespace("bme68x_bsec2") +BME68xBSEC2Component = bme68x_bsec2_ns.class_("BME68xBSEC2Component", cg.Component) + + +MODEL_OPTIONS = ["bme680", "bme688"] + +AlgorithmOutput = bme68x_bsec2_ns.enum("AlgorithmOutput") +ALGORITHM_OUTPUT_OPTIONS = { + "classification": AlgorithmOutput.ALGORITHM_OUTPUT_CLASSIFICATION, + "regression": AlgorithmOutput.ALGORITHM_OUTPUT_REGRESSION, +} + +OperatingAge = bme68x_bsec2_ns.enum("OperatingAge") +OPERATING_AGE_OPTIONS = { + "4d": OperatingAge.OPERATING_AGE_4D, + "28d": OperatingAge.OPERATING_AGE_28D, +} + +SampleRate = bme68x_bsec2_ns.enum("SampleRate") +SAMPLE_RATE_OPTIONS = { + "LP": SampleRate.SAMPLE_RATE_LP, + "ULP": SampleRate.SAMPLE_RATE_ULP, +} + +Voltage = bme68x_bsec2_ns.enum("Voltage") +VOLTAGE_OPTIONS = { + "1.8V": Voltage.VOLTAGE_1_8V, + "3.3V": Voltage.VOLTAGE_3_3V, +} + +ALGORITHM_OUTPUT_FILE_NAME = { + "classification": "sel", + "regression": "reg", +} + +SAMPLE_RATE_FILE_NAME = { + "LP": "3s", + "ULP": "300s", +} + +VOLTAGE_FILE_NAME = { + "1.8V": "18v", + "3.3V": "33v", +} + + +def _compute_local_file_path(url: str) -> Path: + h = hashlib.new("sha256") + h.update(url.encode()) + key = h.hexdigest()[:8] + base_dir = external_files.compute_local_file_dir(DOMAIN) + return base_dir / key + + +def _compute_url(config: dict) -> str: + model = config.get(CONF_MODEL) + operating_age = config.get(CONF_OPERATING_AGE) + sample_rate = SAMPLE_RATE_FILE_NAME[config.get(CONF_SAMPLE_RATE)] + volts = VOLTAGE_FILE_NAME[config.get(CONF_SUPPLY_VOLTAGE)] + if model == "bme688": + algo = ALGORITHM_OUTPUT_FILE_NAME[ + config.get(CONF_ALGORITHM_OUTPUT, "classification") + ] + filename = "bsec_selectivity" + else: + algo = "iaq" + filename = "bsec_iaq" + return f"https://raw.githubusercontent.com/boschsensortec/Bosch-BSEC2-Library/{BSEC2_LIBRARY_VERSION}/src/config/{model}/{model}_{algo}_{volts}_{sample_rate}_{operating_age}/{filename}.txt" + + +def download_bme68x_blob(config): + url = _compute_url(config) + path = _compute_local_file_path(url) + external_files.download_content(url, path) + + return config + + +def validate_bme68x(config): + if CONF_ALGORITHM_OUTPUT not in config: + return config + + if config[CONF_MODEL] != "bme688": + raise cv.Invalid(f"{CONF_ALGORITHM_OUTPUT} is only valid for BME688") + + if config[CONF_ALGORITHM_OUTPUT] == "regression" and ( + config[CONF_OPERATING_AGE] != "4d" + or config[CONF_SAMPLE_RATE] != "ULP" + or config[CONF_SUPPLY_VOLTAGE] != "1.8V" + ): + raise cv.Invalid( + f" To use '{CONF_ALGORITHM_OUTPUT}: regression', {CONF_OPERATING_AGE} must be '4d', {CONF_SAMPLE_RATE} must be 'ULP' and {CONF_SUPPLY_VOLTAGE} must be '1.8V'" + ) + return config + + +CONFIG_SCHEMA_BASE = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(BME68xBSEC2Component), + cv.GenerateID(CONF_RAW_DATA_ID): cv.declare_id(cg.uint8), + cv.Required(CONF_MODEL): cv.one_of(*MODEL_OPTIONS, lower=True), + cv.Optional(CONF_ALGORITHM_OUTPUT): cv.enum( + ALGORITHM_OUTPUT_OPTIONS, lower=True + ), + cv.Optional(CONF_OPERATING_AGE, default="28d"): cv.enum( + OPERATING_AGE_OPTIONS, lower=True + ), + cv.Optional(CONF_SAMPLE_RATE, default="LP"): cv.enum( + SAMPLE_RATE_OPTIONS, upper=True + ), + cv.Optional(CONF_SUPPLY_VOLTAGE, default="3.3V"): cv.enum( + VOLTAGE_OPTIONS, upper=True + ), + cv.Optional(CONF_TEMPERATURE_OFFSET, default=0): cv.temperature, + cv.Optional( + CONF_STATE_SAVE_INTERVAL, default="6hours" + ): cv.positive_time_period_minutes, + }, + ) + .add_extra(cv.only_with_arduino) + .add_extra(validate_bme68x) + .add_extra(download_bme68x_blob) +) + + +async def to_code_base(config): + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, config) + + if algo_output := config.get(CONF_ALGORITHM_OUTPUT): + cg.add(var.set_algorithm_output(algo_output)) + cg.add(var.set_operating_age(config[CONF_OPERATING_AGE])) + cg.add(var.set_sample_rate(config[CONF_SAMPLE_RATE])) + cg.add(var.set_voltage(config[CONF_SUPPLY_VOLTAGE])) + cg.add(var.set_temperature_offset(config[CONF_TEMPERATURE_OFFSET])) + cg.add( + var.set_state_save_interval(config[CONF_STATE_SAVE_INTERVAL].total_milliseconds) + ) + + path = _compute_local_file_path(_compute_url(config)) + + try: + with open(path, encoding="utf-8") as f: + bsec2_iaq_config = f.read() + except Exception as e: + raise core.EsphomeError(f"Could not open binary configuration file {path}: {e}") + + # Convert retrieved BSEC2 config to an array of ints + rhs = [int(x) for x in bsec2_iaq_config.split(",")] + # Create an array which will reside in program memory and configure the sensor instance to use it + 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 library requires the SPI library + cg.add_library("SPI", None) + cg.add_library( + "BME68x Sensor library", + "1.1.40407", + ) + cg.add_library( + "BSEC2 Software Library", + None, + f"https://github.com/boschsensortec/Bosch-BSEC2-Library.git#{BSEC2_LIBRARY_VERSION}", + ) + + cg.add_define("USE_BSEC2") + + return var diff --git a/esphome/components/bme68x_bsec2/bme68x_bsec2.cpp b/esphome/components/bme68x_bsec2/bme68x_bsec2.cpp new file mode 100644 index 0000000000..5425bbd5b7 --- /dev/null +++ b/esphome/components/bme68x_bsec2/bme68x_bsec2.cpp @@ -0,0 +1,523 @@ +#include "esphome/core/defines.h" +#include "esphome/core/helpers.h" +#include "esphome/core/log.h" + +#ifdef USE_BSEC2 +#include "bme68x_bsec2.h" + +#include + +namespace esphome { +namespace 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") +#define BME68X_BSEC2_SAMPLE_RATE_LOG(r) (r == SAMPLE_RATE_DEFAULT ? "Default" : (r == SAMPLE_RATE_ULP ? "ULP" : "LP")) +#define BME68X_BSEC2_VOLTAGE_LOG(v) (v == VOLTAGE_3_3V ? "3.3V" : "1.8V") + +static const char *const TAG = "bme68x_bsec2.sensor"; + +static const std::string IAQ_ACCURACY_STATES[4] = {"Stabilizing", "Uncertain", "Calibrating", "Calibrated"}; + +void BME68xBSEC2Component::setup() { + ESP_LOGCONFIG(TAG, "Setting up BME68X via BSEC2..."); + + this->bsec_status_ = bsec_init_m(&this->bsec_instance_); + if (this->bsec_status_ != BSEC_OK) { + this->mark_failed(); + ESP_LOGE(TAG, "bsec_init_m failed: status %d", this->bsec_status_); + return; + } + + bsec_get_version_m(&this->bsec_instance_, &this->version_); + + this->bme68x_status_ = bme68x_init(&this->bme68x_); + if (this->bme68x_status_ != BME68X_OK) { + this->mark_failed(); + ESP_LOGE(TAG, "bme68x_init failed: status %d", this->bme68x_status_); + return; + } + if (this->bsec2_configuration_ != nullptr && this->bsec2_configuration_length_) { + this->set_config_(this->bsec2_configuration_, this->bsec2_configuration_length_); + if (this->bsec_status_ != BSEC_OK) { + this->mark_failed(); + ESP_LOGE(TAG, "bsec_set_configuration_m failed: status %d", this->bsec_status_); + return; + } + } + + this->update_subscription_(); + if (this->bsec_status_ != BSEC_OK) { + this->mark_failed(); + ESP_LOGE(TAG, "bsec_update_subscription_m failed: status %d", this->bsec_status_); + return; + } + + this->load_state_(); +} + +void BME68xBSEC2Component::dump_config() { + ESP_LOGCONFIG(TAG, "BME68X via BSEC2:"); + + ESP_LOGCONFIG(TAG, " BSEC2 version: %d.%d.%d.%d", this->version_.major, this->version_.minor, + this->version_.major_bugfix, this->version_.minor_bugfix); + + ESP_LOGCONFIG(TAG, " BSEC2 configuration blob:"); + ESP_LOGCONFIG(TAG, " Configured: %s", YESNO(this->bsec2_blob_configured_)); + if (this->bsec2_configuration_ != nullptr && this->bsec2_configuration_length_) { + ESP_LOGCONFIG(TAG, " Size: %" PRIu32, this->bsec2_configuration_length_); + } + + if (this->is_failed()) { + ESP_LOGE(TAG, "Communication failed (BSEC2 status: %d, BME68X status: %d)", this->bsec_status_, + this->bme68x_status_); + } + + if (this->algorithm_output_ != ALGORITHM_OUTPUT_IAQ) { + ESP_LOGCONFIG(TAG, " Algorithm output: %s", BME68X_BSEC2_ALGORITHM_OUTPUT_LOG(this->algorithm_output_)); + } + ESP_LOGCONFIG(TAG, " Operating age: %s", BME68X_BSEC2_OPERATING_AGE_LOG(this->operating_age_)); + ESP_LOGCONFIG(TAG, " Sample rate: %s", BME68X_BSEC2_SAMPLE_RATE_LOG(this->sample_rate_)); + ESP_LOGCONFIG(TAG, " Voltage: %s", BME68X_BSEC2_VOLTAGE_LOG(this->voltage_)); + ESP_LOGCONFIG(TAG, " State save interval: %ims", this->state_save_interval_ms_); + ESP_LOGCONFIG(TAG, " Temperature offset: %.2f", this->temperature_offset_); + +#ifdef USE_SENSOR + LOG_SENSOR(" ", "Temperature", this->temperature_sensor_); + ESP_LOGCONFIG(TAG, " Sample rate: %s", BME68X_BSEC2_SAMPLE_RATE_LOG(this->temperature_sample_rate_)); + LOG_SENSOR(" ", "Pressure", this->pressure_sensor_); + ESP_LOGCONFIG(TAG, " Sample rate: %s", BME68X_BSEC2_SAMPLE_RATE_LOG(this->pressure_sample_rate_)); + LOG_SENSOR(" ", "Humidity", this->humidity_sensor_); + ESP_LOGCONFIG(TAG, " Sample rate: %s", BME68X_BSEC2_SAMPLE_RATE_LOG(this->humidity_sample_rate_)); + LOG_SENSOR(" ", "Gas resistance", this->gas_resistance_sensor_); + LOG_SENSOR(" ", "CO2 equivalent", this->co2_equivalent_sensor_); + LOG_SENSOR(" ", "Breath VOC equivalent", this->breath_voc_equivalent_sensor_); + LOG_SENSOR(" ", "IAQ", this->iaq_sensor_); + LOG_SENSOR(" ", "IAQ static", this->iaq_static_sensor_); + LOG_SENSOR(" ", "Numeric IAQ accuracy", this->iaq_accuracy_sensor_); +#endif +#ifdef USE_TEXT_SENSOR + LOG_TEXT_SENSOR(" ", "IAQ accuracy", this->iaq_accuracy_text_sensor_); +#endif +} + +float BME68xBSEC2Component::get_setup_priority() const { return setup_priority::DATA; } + +void BME68xBSEC2Component::loop() { + this->run_(); + + if (this->bsec_status_ < BSEC_OK || this->bme68x_status_ < BME68X_OK) { + this->status_set_error(); + } else { + this->status_clear_error(); + } + if (this->bsec_status_ > BSEC_OK || this->bme68x_status_ > BME68X_OK) { + this->status_set_warning(); + } else { + this->status_clear_warning(); + } + // Process a single action from the queue. These are primarily sensor state publishes + // that in totality take too long to send in a single call. + if (this->queue_.size()) { + auto action = std::move(this->queue_.front()); + this->queue_.pop(); + action(); + } +} + +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"); + this->mark_failed(); + return; + } + uint8_t work_buffer[BSEC_MAX_PROPERTY_BLOB_SIZE]; + this->bsec_status_ = bsec_set_configuration_m(&this->bsec_instance_, config, len, work_buffer, sizeof(work_buffer)); + if (this->bsec_status_ == BSEC_OK) { + this->bsec2_blob_configured_ = true; + } +} + +float BME68xBSEC2Component::calc_sensor_sample_rate_(SampleRate sample_rate) { + if (sample_rate == SAMPLE_RATE_DEFAULT) { + sample_rate = this->sample_rate_; + } + return sample_rate == SAMPLE_RATE_ULP ? BSEC_SAMPLE_RATE_ULP : BSEC_SAMPLE_RATE_LP; +} + +void BME68xBSEC2Component::update_subscription_() { + bsec_sensor_configuration_t virtual_sensors[BSEC_NUMBER_OUTPUTS]; + uint8_t num_virtual_sensors = 0; +#ifdef USE_SENSOR + if (this->iaq_sensor_) { + virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_IAQ; + virtual_sensors[num_virtual_sensors].sample_rate = this->calc_sensor_sample_rate_(SAMPLE_RATE_DEFAULT); + num_virtual_sensors++; + } + + if (this->iaq_static_sensor_) { + virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_STATIC_IAQ; + virtual_sensors[num_virtual_sensors].sample_rate = this->calc_sensor_sample_rate_(SAMPLE_RATE_DEFAULT); + num_virtual_sensors++; + } + + if (this->co2_equivalent_sensor_) { + virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_CO2_EQUIVALENT; + virtual_sensors[num_virtual_sensors].sample_rate = this->calc_sensor_sample_rate_(SAMPLE_RATE_DEFAULT); + num_virtual_sensors++; + } + + if (this->breath_voc_equivalent_sensor_) { + virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_BREATH_VOC_EQUIVALENT; + virtual_sensors[num_virtual_sensors].sample_rate = this->calc_sensor_sample_rate_(SAMPLE_RATE_DEFAULT); + num_virtual_sensors++; + } + + if (this->pressure_sensor_) { + virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_RAW_PRESSURE; + virtual_sensors[num_virtual_sensors].sample_rate = this->calc_sensor_sample_rate_(this->pressure_sample_rate_); + num_virtual_sensors++; + } + + if (this->gas_resistance_sensor_) { + virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_RAW_GAS; + virtual_sensors[num_virtual_sensors].sample_rate = this->calc_sensor_sample_rate_(SAMPLE_RATE_DEFAULT); + num_virtual_sensors++; + } + + if (this->temperature_sensor_) { + virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE; + virtual_sensors[num_virtual_sensors].sample_rate = this->calc_sensor_sample_rate_(this->temperature_sample_rate_); + num_virtual_sensors++; + } + + if (this->humidity_sensor_) { + virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY; + virtual_sensors[num_virtual_sensors].sample_rate = this->calc_sensor_sample_rate_(this->humidity_sample_rate_); + num_virtual_sensors++; + } +#endif + bsec_sensor_configuration_t sensor_settings[BSEC_MAX_PHYSICAL_SENSOR]; + uint8_t num_sensor_settings = BSEC_MAX_PHYSICAL_SENSOR; + this->bsec_status_ = bsec_update_subscription_m(&this->bsec_instance_, virtual_sensors, num_virtual_sensors, + sensor_settings, &num_sensor_settings); +} + +void BME68xBSEC2Component::run_() { + int64_t curr_time_ns = this->get_time_ns_(); + if (curr_time_ns < this->next_call_ns_) { + return; + } + this->op_mode_ = this->bsec_settings_.op_mode; + 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_); + return; + } + this->next_call_ns_ = this->bsec_settings_.next_call; + + if (this->bsec_settings_.trigger_measurement) { + bme68x_get_conf(&bme68x_conf, &this->bme68x_); + + bme68x_conf.os_hum = this->bsec_settings_.humidity_oversampling; + bme68x_conf.os_temp = this->bsec_settings_.temperature_oversampling; + bme68x_conf.os_pres = this->bsec_settings_.pressure_oversampling; + bme68x_set_conf(&bme68x_conf, &this->bme68x_); + + switch (this->bsec_settings_.op_mode) { + case BME68X_FORCED_MODE: + this->bme68x_heatr_conf_.enable = BME68X_ENABLE; + 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->op_mode_ = BME68X_FORCED_MODE; + this->sleep_mode_ = false; + ESP_LOGV(TAG, "Using forced mode"); + + break; + case BME68X_PARALLEL_MODE: + if (this->op_mode_ != this->bsec_settings_.op_mode) { + this->bme68x_heatr_conf_.enable = BME68X_ENABLE; + this->bme68x_heatr_conf_.heatr_temp_prof = this->bsec_settings_.heater_temperature_profile; + this->bme68x_heatr_conf_.heatr_dur_prof = this->bsec_settings_.heater_duration_profile; + this->bme68x_heatr_conf_.profile_len = this->bsec_settings_.heater_profile_len; + this->bme68x_heatr_conf_.shared_heatr_dur = + 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->op_mode_ = BME68X_PARALLEL_MODE; + this->sleep_mode_ = false; + ESP_LOGV(TAG, "Using parallel mode"); + } + break; + case BME68X_SLEEP_MODE: + if (!this->sleep_mode_) { + bme68x_set_op_mode(BME68X_SLEEP_MODE, &this->bme68x_); + this->sleep_mode_ = true; + ESP_LOGV(TAG, "Using sleep mode"); + } + break; + } + + 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); }); + } else { + ESP_LOGV(TAG, "Measurement not required"); + this->read_(curr_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; + } + + struct bme68x_data data[3]; + uint8_t nFields = 0; + this->bme68x_status_ = bme68x_get_data(this->op_mode_, &data[0], &nFields, &this->bme68x_); + + if (this->bme68x_status_ != BME68X_OK) { + ESP_LOGW(TAG, "Failed to get sensor data (BME68X error code %d)", this->bme68x_status_); + return; + } + if (nFields < 1) { + ESP_LOGD(TAG, "BME68X did not provide new data"); + return; + } + + for (uint8_t i = 0; i < nFields; i++) { + bsec_input_t inputs[BSEC_MAX_PHYSICAL_SENSOR]; // Temperature, Pressure, Humidity & Gas Resistance + uint8_t num_inputs = 0; + + if (BSEC_CHECK_INPUT(this->bsec_settings_.process_data, BSEC_INPUT_TEMPERATURE)) { + inputs[num_inputs].sensor_id = BSEC_INPUT_TEMPERATURE; + inputs[num_inputs].signal = data[i].temperature; + inputs[num_inputs].time_stamp = trigger_time_ns; + num_inputs++; + } + if (BSEC_CHECK_INPUT(this->bsec_settings_.process_data, BSEC_INPUT_HEATSOURCE)) { + inputs[num_inputs].sensor_id = BSEC_INPUT_HEATSOURCE; + inputs[num_inputs].signal = this->temperature_offset_; + inputs[num_inputs].time_stamp = trigger_time_ns; + num_inputs++; + } + if (BSEC_CHECK_INPUT(this->bsec_settings_.process_data, BSEC_INPUT_HUMIDITY)) { + inputs[num_inputs].sensor_id = BSEC_INPUT_HUMIDITY; + inputs[num_inputs].signal = data[i].humidity; + inputs[num_inputs].time_stamp = trigger_time_ns; + num_inputs++; + } + if (BSEC_CHECK_INPUT(this->bsec_settings_.process_data, BSEC_INPUT_PRESSURE)) { + inputs[num_inputs].sensor_id = BSEC_INPUT_PRESSURE; + inputs[num_inputs].signal = data[i].pressure; + inputs[num_inputs].time_stamp = trigger_time_ns; + num_inputs++; + } + if (BSEC_CHECK_INPUT(this->bsec_settings_.process_data, BSEC_INPUT_GASRESISTOR)) { + if (data[i].status & BME68X_GASM_VALID_MSK) { + inputs[num_inputs].sensor_id = BSEC_INPUT_GASRESISTOR; + inputs[num_inputs].signal = data[i].gas_resistance; + inputs[num_inputs].time_stamp = trigger_time_ns; + num_inputs++; + } else { + ESP_LOGD(TAG, "BME68X did not report gas data"); + } + } + if (BSEC_CHECK_INPUT(this->bsec_settings_.process_data, BSEC_INPUT_PROFILE_PART) && + (data[i].status & BME68X_GASM_VALID_MSK)) { + inputs[num_inputs].sensor_id = BSEC_INPUT_PROFILE_PART; + inputs[num_inputs].signal = (this->op_mode_ == BME68X_FORCED_MODE) ? 0 : data[i].gas_index; + inputs[num_inputs].time_stamp = trigger_time_ns; + num_inputs++; + } + + if (num_inputs < 1) { + ESP_LOGD(TAG, "No signal inputs available for BSEC2"); + return; + } + + bsec_output_t outputs[BSEC_NUMBER_OUTPUTS]; + 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_); + return; + } + if (num_outputs < 1) { + ESP_LOGD(TAG, "No signal outputs provided by BSEC2"); + return; + } + + this->publish_(outputs, num_outputs); + } +} + +void BME68xBSEC2Component::publish_(const bsec_output_t *outputs, uint8_t num_outputs) { + ESP_LOGV(TAG, "Publishing sensor states"); + bool update_accuracy = false; + uint8_t max_accuracy = 0; + for (uint8_t i = 0; i < num_outputs; i++) { + float signal = outputs[i].signal; + switch (outputs[i].sensor_id) { + case BSEC_OUTPUT_IAQ: + max_accuracy = std::max(outputs[i].accuracy, max_accuracy); + update_accuracy = true; +#ifdef USE_SENSOR + this->queue_push_([this, signal]() { this->publish_sensor_(this->iaq_sensor_, signal); }); +#endif + break; + case BSEC_OUTPUT_STATIC_IAQ: + max_accuracy = std::max(outputs[i].accuracy, max_accuracy); + update_accuracy = true; +#ifdef USE_SENSOR + this->queue_push_([this, signal]() { this->publish_sensor_(this->iaq_static_sensor_, signal); }); +#endif + break; + case BSEC_OUTPUT_CO2_EQUIVALENT: +#ifdef USE_SENSOR + this->queue_push_([this, signal]() { this->publish_sensor_(this->co2_equivalent_sensor_, signal); }); +#endif + break; + case BSEC_OUTPUT_BREATH_VOC_EQUIVALENT: +#ifdef USE_SENSOR + this->queue_push_([this, signal]() { this->publish_sensor_(this->breath_voc_equivalent_sensor_, signal); }); +#endif + break; + case BSEC_OUTPUT_RAW_PRESSURE: +#ifdef USE_SENSOR + this->queue_push_([this, signal]() { this->publish_sensor_(this->pressure_sensor_, signal / 100.0f); }); +#endif + break; + case BSEC_OUTPUT_RAW_GAS: +#ifdef USE_SENSOR + this->queue_push_([this, signal]() { this->publish_sensor_(this->gas_resistance_sensor_, signal); }); +#endif + break; + case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE: +#ifdef USE_SENSOR + this->queue_push_([this, signal]() { this->publish_sensor_(this->temperature_sensor_, signal); }); +#endif + break; + case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY: +#ifdef USE_SENSOR + this->queue_push_([this, signal]() { this->publish_sensor_(this->humidity_sensor_, signal); }); +#endif + break; + } + } + if (update_accuracy) { +#ifdef USE_SENSOR + this->queue_push_( + [this, max_accuracy]() { this->publish_sensor_(this->iaq_accuracy_sensor_, max_accuracy, true); }); +#endif +#ifdef USE_TEXT_SENSOR + this->queue_push_([this, max_accuracy]() { + this->publish_sensor_(this->iaq_accuracy_text_sensor_, IAQ_ACCURACY_STATES[max_accuracy]); + }); +#endif + // Queue up an opportunity to save state + this->queue_push_([this, max_accuracy]() { this->save_state_(max_accuracy); }); + } +} + +int64_t BME68xBSEC2Component::get_time_ns_() { + int64_t time_ms = millis(); + if (this->last_time_ms_ > time_ms) { + this->millis_overflow_counter_++; + } + this->last_time_ms_ = time_ms; + + return (time_ms + ((int64_t) this->millis_overflow_counter_ << 32)) * INT64_C(1000000); +} + +#ifdef USE_SENSOR +void BME68xBSEC2Component::publish_sensor_(sensor::Sensor *sensor, float value, bool change_only) { + if (!sensor || (change_only && sensor->has_state() && sensor->state == value)) { + return; + } + sensor->publish_state(value); +} +#endif + +#ifdef USE_TEXT_SENSOR +void BME68xBSEC2Component::publish_sensor_(text_sensor::TextSensor *sensor, const std::string &value) { + if (!sensor || (sensor->has_state() && sensor->state == value)) { + return; + } + sensor->publish_state(value); +} +#endif + +void BME68xBSEC2Component::load_state_() { + uint32_t hash = this->get_hash(); + this->bsec_state_ = global_preferences->make_preference(hash, true); + + uint8_t state[BSEC_MAX_STATE_BLOB_SIZE]; + if (this->bsec_state_.load(&state)) { + ESP_LOGV(TAG, "Loading state"); + uint8_t work_buffer[BSEC_MAX_WORKBUFFER_SIZE]; + this->bsec_status_ = + bsec_set_state_m(&this->bsec_instance_, state, BSEC_MAX_STATE_BLOB_SIZE, work_buffer, sizeof(work_buffer)); + if (this->bsec_status_ != BSEC_OK) { + ESP_LOGW(TAG, "Failed to load state (BSEC2 error code %d)", this->bsec_status_); + } + ESP_LOGI(TAG, "Loaded state"); + } +} + +void BME68xBSEC2Component::save_state_(uint8_t accuracy) { + if (accuracy < 3 || (millis() - this->last_state_save_ms_ < this->state_save_interval_ms_)) { + return; + } + + ESP_LOGV(TAG, "Saving state"); + + uint8_t state[BSEC_MAX_STATE_BLOB_SIZE]; + uint8_t work_buffer[BSEC_MAX_STATE_BLOB_SIZE]; + uint32_t num_serialized_state = BSEC_MAX_STATE_BLOB_SIZE; + + this->bsec_status_ = bsec_get_state_m(&this->bsec_instance_, 0, state, BSEC_MAX_STATE_BLOB_SIZE, work_buffer, + BSEC_MAX_STATE_BLOB_SIZE, &num_serialized_state); + if (this->bsec_status_ != BSEC_OK) { + ESP_LOGW(TAG, "Failed fetch state for save (BSEC2 error code %d)", this->bsec_status_); + return; + } + + if (!this->bsec_state_.save(&state)) { + ESP_LOGW(TAG, "Failed to save state"); + return; + } + this->last_state_save_ms_ = millis(); + + ESP_LOGI(TAG, "Saved state"); +} + +} // namespace bme68x_bsec2 +} // namespace esphome +#endif diff --git a/esphome/components/bme68x_bsec2/bme68x_bsec2.h b/esphome/components/bme68x_bsec2/bme68x_bsec2.h new file mode 100644 index 0000000000..7b9db2b7bf --- /dev/null +++ b/esphome/components/bme68x_bsec2/bme68x_bsec2.h @@ -0,0 +1,163 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/core/defines.h" +#include "esphome/core/preferences.h" + +#ifdef USE_BSEC2 + +#ifdef USE_SENSOR +#include "esphome/components/sensor/sensor.h" +#endif + +#ifdef USE_TEXT_SENSOR +#include "esphome/components/text_sensor/text_sensor.h" +#endif + +#include +#include + +#include + +namespace esphome { +namespace bme68x_bsec2 { + +enum AlgorithmOutput { + ALGORITHM_OUTPUT_IAQ, + ALGORITHM_OUTPUT_CLASSIFICATION, + ALGORITHM_OUTPUT_REGRESSION, +}; + +enum OperatingAge { + OPERATING_AGE_4D, + OPERATING_AGE_28D, +}; + +enum SampleRate { + SAMPLE_RATE_LP = 0, + SAMPLE_RATE_ULP = 1, + SAMPLE_RATE_DEFAULT = 2, +}; + +enum Voltage { + VOLTAGE_1_8V, + VOLTAGE_3_3V, +}; + +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; } + void set_operating_age(OperatingAge operating_age) { this->operating_age_ = operating_age; } + void set_temperature_offset(float offset) { this->temperature_offset_ = offset; } + void set_voltage(Voltage voltage) { this->voltage_ = voltage; } + + void set_sample_rate(SampleRate sample_rate) { this->sample_rate_ = sample_rate; } + void set_temperature_sample_rate(SampleRate sample_rate) { this->temperature_sample_rate_ = sample_rate; } + void set_pressure_sample_rate(SampleRate sample_rate) { this->pressure_sample_rate_ = sample_rate; } + void set_humidity_sample_rate(SampleRate sample_rate) { this->humidity_sample_rate_ = sample_rate; } + + void set_bsec2_configuration(const uint8_t *data, const uint32_t len) { + this->bsec2_configuration_ = data; + this->bsec2_configuration_length_ = len; + } + + void set_state_save_interval(uint32_t interval) { this->state_save_interval_ms_ = interval; } + +#ifdef USE_SENSOR + void set_temperature_sensor(sensor::Sensor *sensor) { this->temperature_sensor_ = sensor; } + void set_pressure_sensor(sensor::Sensor *sensor) { this->pressure_sensor_ = sensor; } + void set_humidity_sensor(sensor::Sensor *sensor) { this->humidity_sensor_ = sensor; } + void set_gas_resistance_sensor(sensor::Sensor *sensor) { this->gas_resistance_sensor_ = sensor; } + void set_iaq_sensor(sensor::Sensor *sensor) { this->iaq_sensor_ = sensor; } + void set_iaq_static_sensor(sensor::Sensor *sensor) { this->iaq_static_sensor_ = sensor; } + void set_iaq_accuracy_sensor(sensor::Sensor *sensor) { this->iaq_accuracy_sensor_ = sensor; } + void set_co2_equivalent_sensor(sensor::Sensor *sensor) { this->co2_equivalent_sensor_ = sensor; } + void set_breath_voc_equivalent_sensor(sensor::Sensor *sensor) { this->breath_voc_equivalent_sensor_ = sensor; } +#endif +#ifdef USE_TEXT_SENSOR + void set_iaq_accuracy_text_sensor(text_sensor::TextSensor *sensor) { this->iaq_accuracy_text_sensor_ = sensor; } +#endif + virtual uint32_t get_hash() = 0; + + protected: + void set_config_(const uint8_t *config, u_int32_t len); + float calc_sensor_sample_rate_(SampleRate sample_rate); + void update_subscription_(); + + void run_(); + void read_(int64_t trigger_time_ns); + void publish_(const bsec_output_t *outputs, uint8_t num_outputs); + int64_t get_time_ns_(); + +#ifdef USE_SENSOR + 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); +#endif + + void load_state_(); + void save_state_(uint8_t accuracy); + + void queue_push_(std::function &&f) { this->queue_.push(std::move(f)); } + + 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 + bool sleep_mode_; + bsec_library_return_t bsec_status_{BSEC_OK}; + int8_t bme68x_status_{BME68X_OK}; + + int64_t last_time_ms_{0}; + uint32_t millis_overflow_counter_{0}; + int64_t next_call_ns_{0}; + + std::queue> queue_; + + 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}; + sensor::Sensor *humidity_sensor_{nullptr}; + sensor::Sensor *gas_resistance_sensor_{nullptr}; + sensor::Sensor *iaq_sensor_{nullptr}; + sensor::Sensor *iaq_static_sensor_{nullptr}; + sensor::Sensor *iaq_accuracy_sensor_{nullptr}; + sensor::Sensor *co2_equivalent_sensor_{nullptr}; + sensor::Sensor *breath_voc_equivalent_sensor_{nullptr}; +#endif +#ifdef USE_TEXT_SENSOR + text_sensor::TextSensor *iaq_accuracy_text_sensor_{nullptr}; +#endif +}; + +} // namespace bme68x_bsec2 +} // namespace esphome +#endif diff --git a/esphome/components/bme68x_bsec2/sensor.py b/esphome/components/bme68x_bsec2/sensor.py new file mode 100644 index 0000000000..419f47b248 --- /dev/null +++ b/esphome/components/bme68x_bsec2/sensor.py @@ -0,0 +1,130 @@ +import esphome.codegen as cg +from esphome.components import sensor +import esphome.config_validation as cv +from esphome.const import ( + CONF_GAS_RESISTANCE, + CONF_HUMIDITY, + CONF_IAQ_ACCURACY, + CONF_PRESSURE, + CONF_SAMPLE_RATE, + CONF_TEMPERATURE, + DEVICE_CLASS_ATMOSPHERIC_PRESSURE, + DEVICE_CLASS_HUMIDITY, + DEVICE_CLASS_TEMPERATURE, + ICON_GAS_CYLINDER, + ICON_GAUGE, + ICON_THERMOMETER, + ICON_WATER_PERCENT, + STATE_CLASS_MEASUREMENT, + UNIT_CELSIUS, + UNIT_HECTOPASCAL, + UNIT_OHM, + UNIT_PARTS_PER_MILLION, + UNIT_PERCENT, +) + +from . import CONF_BME68X_BSEC2_ID, SAMPLE_RATE_OPTIONS, BME68xBSEC2Component + +DEPENDENCIES = ["bme68x_bsec2"] + +CONF_BREATH_VOC_EQUIVALENT = "breath_voc_equivalent" +CONF_CO2_EQUIVALENT = "co2_equivalent" +CONF_IAQ = "iaq" +CONF_IAQ_STATIC = "iaq_static" +ICON_ACCURACY = "mdi:checkbox-marked-circle-outline" +ICON_TEST_TUBE = "mdi:test-tube" +UNIT_IAQ = "IAQ" + +TYPES = [ + CONF_TEMPERATURE, + CONF_PRESSURE, + CONF_HUMIDITY, + CONF_GAS_RESISTANCE, + CONF_IAQ, + CONF_IAQ_STATIC, + CONF_IAQ_ACCURACY, + CONF_CO2_EQUIVALENT, + CONF_BREATH_VOC_EQUIVALENT, +] + +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(CONF_BME68X_BSEC2_ID): cv.use_id(BME68xBSEC2Component), + 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.Optional(CONF_SAMPLE_RATE): cv.enum(SAMPLE_RATE_OPTIONS, upper=True)} + ), + cv.Optional(CONF_PRESSURE): sensor.sensor_schema( + unit_of_measurement=UNIT_HECTOPASCAL, + icon=ICON_GAUGE, + accuracy_decimals=1, + device_class=DEVICE_CLASS_ATMOSPHERIC_PRESSURE, + state_class=STATE_CLASS_MEASUREMENT, + ).extend( + {cv.Optional(CONF_SAMPLE_RATE): cv.enum(SAMPLE_RATE_OPTIONS, upper=True)} + ), + cv.Optional(CONF_HUMIDITY): sensor.sensor_schema( + unit_of_measurement=UNIT_PERCENT, + icon=ICON_WATER_PERCENT, + accuracy_decimals=1, + device_class=DEVICE_CLASS_HUMIDITY, + state_class=STATE_CLASS_MEASUREMENT, + ).extend( + {cv.Optional(CONF_SAMPLE_RATE): cv.enum(SAMPLE_RATE_OPTIONS, upper=True)} + ), + cv.Optional(CONF_GAS_RESISTANCE): sensor.sensor_schema( + unit_of_measurement=UNIT_OHM, + icon=ICON_GAS_CYLINDER, + accuracy_decimals=0, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_IAQ): sensor.sensor_schema( + unit_of_measurement=UNIT_IAQ, + icon=ICON_GAUGE, + accuracy_decimals=0, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_IAQ_STATIC): sensor.sensor_schema( + unit_of_measurement=UNIT_IAQ, + icon=ICON_GAUGE, + accuracy_decimals=0, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_IAQ_ACCURACY): sensor.sensor_schema( + icon=ICON_ACCURACY, + accuracy_decimals=0, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_CO2_EQUIVALENT): sensor.sensor_schema( + unit_of_measurement=UNIT_PARTS_PER_MILLION, + icon=ICON_TEST_TUBE, + accuracy_decimals=1, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_BREATH_VOC_EQUIVALENT): sensor.sensor_schema( + unit_of_measurement=UNIT_PARTS_PER_MILLION, + icon=ICON_TEST_TUBE, + accuracy_decimals=1, + state_class=STATE_CLASS_MEASUREMENT, + ), + } +) + + +async def setup_conf(config, key, hub): + if conf := config.get(key): + sens = await sensor.new_sensor(conf) + cg.add(getattr(hub, f"set_{key}_sensor")(sens)) + if sample_rate := conf.get(CONF_SAMPLE_RATE): + cg.add(getattr(hub, f"set_{key}_sample_rate")(sample_rate)) + + +async def to_code(config): + hub = await cg.get_variable(config[CONF_BME68X_BSEC2_ID]) + for key in TYPES: + await setup_conf(config, key, hub) diff --git a/esphome/components/bme68x_bsec2/text_sensor.py b/esphome/components/bme68x_bsec2/text_sensor.py new file mode 100644 index 0000000000..fce00afe34 --- /dev/null +++ b/esphome/components/bme68x_bsec2/text_sensor.py @@ -0,0 +1,33 @@ +import esphome.codegen as cg +from esphome.components import text_sensor +import esphome.config_validation as cv +from esphome.const import CONF_IAQ_ACCURACY + +from . import CONF_BME68X_BSEC2_ID, BME68xBSEC2Component + +DEPENDENCIES = ["bme68x_bsec2"] + +ICON_ACCURACY = "mdi:checkbox-marked-circle-outline" + +TYPES = [CONF_IAQ_ACCURACY] + +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(CONF_BME68X_BSEC2_ID): cv.use_id(BME68xBSEC2Component), + cv.Optional(CONF_IAQ_ACCURACY): text_sensor.text_sensor_schema( + icon=ICON_ACCURACY + ), + } +) + + +async def setup_conf(config, key, hub): + if conf := config.get(key): + sens = await text_sensor.new_text_sensor(conf) + cg.add(getattr(hub, f"set_{key}_text_sensor")(sens)) + + +async def to_code(config): + hub = await cg.get_variable(config[CONF_BME68X_BSEC2_ID]) + for key in TYPES: + await setup_conf(config, key, hub) diff --git a/esphome/components/bme68x_bsec2_i2c/__init__.py b/esphome/components/bme68x_bsec2_i2c/__init__.py new file mode 100644 index 0000000000..d6fb7fa9be --- /dev/null +++ b/esphome/components/bme68x_bsec2_i2c/__init__.py @@ -0,0 +1,28 @@ +import esphome.codegen as cg +from esphome.components import i2c +from esphome.components.bme68x_bsec2 import ( + CONFIG_SCHEMA_BASE, + BME68xBSEC2Component, + to_code_base, +) +import esphome.config_validation as cv + +CODEOWNERS = ["@neffs", "@kbx81"] + +AUTO_LOAD = ["bme68x_bsec2"] +DEPENDENCIES = ["i2c"] + +bme68x_bsec2_i2c_ns = cg.esphome_ns.namespace("bme68x_bsec2_i2c") +BME68xBSEC2I2CComponent = bme68x_bsec2_i2c_ns.class_( + "BME68xBSEC2I2CComponent", BME68xBSEC2Component, i2c.I2CDevice +) + + +CONFIG_SCHEMA = CONFIG_SCHEMA_BASE.extend( + cv.Schema({cv.GenerateID(): cv.declare_id(BME68xBSEC2I2CComponent)}) +).extend(i2c.i2c_device_schema(0x76)) + + +async def to_code(config): + var = await to_code_base(config) + await i2c.register_i2c_device(var, config) diff --git a/esphome/components/bme68x_bsec2_i2c/bme68x_bsec2_i2c.cpp b/esphome/components/bme68x_bsec2_i2c/bme68x_bsec2_i2c.cpp new file mode 100644 index 0000000000..874c8bf388 --- /dev/null +++ b/esphome/components/bme68x_bsec2_i2c/bme68x_bsec2_i2c.cpp @@ -0,0 +1,53 @@ +#include "esphome/core/defines.h" +#include "esphome/core/helpers.h" +#include "esphome/core/log.h" + +#ifdef USE_BSEC2 +#include "bme68x_bsec2_i2c.h" +#include "esphome/components/i2c/i2c.h" + +#include + +namespace esphome { +namespace bme68x_bsec2_i2c { + +static const char *const TAG = "bme68x_bsec2_i2c.sensor"; + +void BME68xBSEC2I2CComponent::setup() { + // must set up our bme68x_dev instance before calling setup() + this->bme68x_.intf_ptr = (void *) this; + this->bme68x_.intf = BME68X_I2C_INTF; + this->bme68x_.read = BME68xBSEC2I2CComponent::read_bytes_wrapper; + this->bme68x_.write = BME68xBSEC2I2CComponent::write_bytes_wrapper; + this->bme68x_.delay_us = BME68xBSEC2I2CComponent::delay_us; + this->bme68x_.amb_temp = 25; + + BME68xBSEC2Component::setup(); +} + +void BME68xBSEC2I2CComponent::dump_config() { + LOG_I2C_DEVICE(this); + BME68xBSEC2Component::dump_config(); +} + +uint32_t BME68xBSEC2I2CComponent::get_hash() { return fnv1_hash("bme68x_bsec_state_" + to_string(this->address_)); } + +int8_t BME68xBSEC2I2CComponent::read_bytes_wrapper(uint8_t a_register, uint8_t *data, uint32_t len, void *intfPtr) { + ESP_LOGVV(TAG, "read_bytes_wrapper: reg = %u", a_register); + return static_cast(intfPtr)->read_bytes(a_register, data, len) ? 0 : -1; +} + +int8_t BME68xBSEC2I2CComponent::write_bytes_wrapper(uint8_t a_register, const uint8_t *data, uint32_t len, + void *intfPtr) { + ESP_LOGVV(TAG, "write_bytes_wrapper: reg = %u", a_register); + return static_cast(intfPtr)->write_bytes(a_register, data, len) ? 0 : -1; +} + +void BME68xBSEC2I2CComponent::delay_us(uint32_t period, void *intfPtr) { + ESP_LOGVV(TAG, "Delaying for %" PRIu32 "us", period); + delayMicroseconds(period); +} + +} // namespace bme68x_bsec2_i2c +} // namespace esphome +#endif diff --git a/esphome/components/bme68x_bsec2_i2c/bme68x_bsec2_i2c.h b/esphome/components/bme68x_bsec2_i2c/bme68x_bsec2_i2c.h new file mode 100644 index 0000000000..a21a123f7b --- /dev/null +++ b/esphome/components/bme68x_bsec2_i2c/bme68x_bsec2_i2c.h @@ -0,0 +1,28 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/core/defines.h" +#include "esphome/core/preferences.h" + +#ifdef USE_BSEC2 + +#include "esphome/components/bme68x_bsec2/bme68x_bsec2.h" +#include "esphome/components/i2c/i2c.h" + +namespace esphome { +namespace bme68x_bsec2_i2c { + +class BME68xBSEC2I2CComponent : public bme68x_bsec2::BME68xBSEC2Component, public i2c::I2CDevice { + void setup() override; + void dump_config() override; + + uint32_t get_hash() override; + + static int8_t read_bytes_wrapper(uint8_t a_register, uint8_t *data, uint32_t len, void *intfPtr); + static int8_t write_bytes_wrapper(uint8_t a_register, const uint8_t *data, uint32_t len, void *intfPtr); + static void delay_us(uint32_t period, void *intfPtr); +}; + +} // namespace bme68x_bsec2_i2c +} // namespace esphome +#endif diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 61a4940d01..a711148ec8 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -158,6 +158,7 @@ #endif // Disabled feature flags -// #define USE_BSEC // Requires a library with proprietary license. +// #define USE_BSEC // Requires a library with proprietary license +// #define USE_BSEC2 // Requires a library with proprietary license #define USE_DASHBOARD_IMPORT diff --git a/tests/components/bme68x_bsec2_i2c/common.yaml b/tests/components/bme68x_bsec2_i2c/common.yaml new file mode 100644 index 0000000000..b8a16ee7bb --- /dev/null +++ b/tests/components/bme68x_bsec2_i2c/common.yaml @@ -0,0 +1,34 @@ +i2c: + - id: i2c_bme68x + scl: ${scl_pin} + sda: ${sda_pin} + +bme68x_bsec2_i2c: + address: 0x76 + model: bme688 + algorithm_output: classification + operating_age: 28d + sample_rate: LP + supply_voltage: 3.3V + +sensor: + - platform: bme68x_bsec2 + temperature: + name: BME68X Temperature + pressure: + name: BME68X Pressure + humidity: + name: BME68X Humidity + gas_resistance: + name: BME68X Gas Sensor + iaq: + name: BME68X IAQ + co2_equivalent: + name: BME68X eCO2 + breath_voc_equivalent: + name: BME68X Breath eVOC + +text_sensor: + - platform: bme68x_bsec2 + iaq_accuracy: + name: BME68X Accuracy 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..63c3bd6afd --- /dev/null +++ b/tests/components/bme68x_bsec2_i2c/test.esp32-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO16 + sda_pin: GPIO17 + +<<: !include common.yaml diff --git a/tests/components/bme68x_bsec2_i2c/test.esp32-c3-ard.yaml b/tests/components/bme68x_bsec2_i2c/test.esp32-c3-ard.yaml new file mode 100644 index 0000000000..84a9dd4bb4 --- /dev/null +++ b/tests/components/bme68x_bsec2_i2c/test.esp32-c3-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO6 + sda_pin: GPIO7 + +<<: !include common.yaml diff --git a/tests/components/bme68x_bsec2_i2c/test.esp32-s2-ard.yaml b/tests/components/bme68x_bsec2_i2c/test.esp32-s2-ard.yaml new file mode 100644 index 0000000000..63c3bd6afd --- /dev/null +++ b/tests/components/bme68x_bsec2_i2c/test.esp32-s2-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO16 + sda_pin: GPIO17 + +<<: !include common.yaml diff --git a/tests/components/bme68x_bsec2_i2c/test.esp32-s3-ard.yaml b/tests/components/bme68x_bsec2_i2c/test.esp32-s3-ard.yaml new file mode 100644 index 0000000000..63c3bd6afd --- /dev/null +++ b/tests/components/bme68x_bsec2_i2c/test.esp32-s3-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO16 + sda_pin: GPIO17 + +<<: !include common.yaml diff --git a/tests/components/bme68x_bsec2_i2c/test.esp8266-ard.yaml b/tests/components/bme68x_bsec2_i2c/test.esp8266-ard.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/bme68x_bsec2_i2c/test.esp8266-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml From e769804fe6f2502e98ddd8ced9db78898ac8ff1e Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Mon, 12 Aug 2024 06:27:22 +0200 Subject: [PATCH 1895/2101] [code-quality] clang-tidy media_player (#7238) --- esphome/components/media_player/automation.h | 58 +++++++++++--------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/esphome/components/media_player/automation.h b/esphome/components/media_player/automation.h index fc3ce7a764..f0e0a5dd31 100644 --- a/esphome/components/media_player/automation.h +++ b/esphome/components/media_player/automation.h @@ -7,30 +7,24 @@ namespace esphome { namespace media_player { -#define MEDIA_PLAYER_SIMPLE_COMMAND_ACTION(ACTION_CLASS, ACTION_COMMAND) \ - template class ACTION_CLASS : public Action, public Parented { \ - void play(Ts... x) override { \ - this->parent_->make_call().set_command(MediaPlayerCommand::MEDIA_PLAYER_COMMAND_##ACTION_COMMAND).perform(); \ - } \ - }; +template +class MediaPlayerCommandAction : public Action, public Parented { + public: + void play(Ts... x) override { this->parent_->make_call().set_command(Command).perform(); } +}; -#define MEDIA_PLAYER_SIMPLE_STATE_TRIGGER(TRIGGER_CLASS, TRIGGER_STATE) \ - class TRIGGER_CLASS : public Trigger<> { \ - public: \ - explicit TRIGGER_CLASS(MediaPlayer *player) { \ - player->add_on_state_callback([this, player]() { \ - if (player->state == MediaPlayerState::MEDIA_PLAYER_STATE_##TRIGGER_STATE) \ - this->trigger(); \ - }); \ - } \ - }; - -MEDIA_PLAYER_SIMPLE_COMMAND_ACTION(PlayAction, PLAY) -MEDIA_PLAYER_SIMPLE_COMMAND_ACTION(PauseAction, PAUSE) -MEDIA_PLAYER_SIMPLE_COMMAND_ACTION(StopAction, STOP) -MEDIA_PLAYER_SIMPLE_COMMAND_ACTION(ToggleAction, TOGGLE) -MEDIA_PLAYER_SIMPLE_COMMAND_ACTION(VolumeUpAction, VOLUME_UP) -MEDIA_PLAYER_SIMPLE_COMMAND_ACTION(VolumeDownAction, VOLUME_DOWN) +template +using PlayAction = MediaPlayerCommandAction; +template +using PauseAction = MediaPlayerCommandAction; +template +using StopAction = MediaPlayerCommandAction; +template +using ToggleAction = MediaPlayerCommandAction; +template +using VolumeUpAction = MediaPlayerCommandAction; +template +using VolumeDownAction = MediaPlayerCommandAction; template class PlayMediaAction : public Action, public Parented { TEMPLATABLE_VALUE(std::string, media_url) @@ -49,10 +43,20 @@ class StateTrigger : public Trigger<> { } }; -MEDIA_PLAYER_SIMPLE_STATE_TRIGGER(IdleTrigger, IDLE) -MEDIA_PLAYER_SIMPLE_STATE_TRIGGER(PlayTrigger, PLAYING) -MEDIA_PLAYER_SIMPLE_STATE_TRIGGER(PauseTrigger, PAUSED) -MEDIA_PLAYER_SIMPLE_STATE_TRIGGER(AnnouncementTrigger, ANNOUNCING) +template class MediaPlayerStateTrigger : public Trigger<> { + public: + explicit MediaPlayerStateTrigger(MediaPlayer *player) { + player->add_on_state_callback([this, player]() { + if (player->state == State) + this->trigger(); + }); + } +}; + +using IdleTrigger = MediaPlayerStateTrigger; +using PlayTrigger = MediaPlayerStateTrigger; +using PauseTrigger = MediaPlayerStateTrigger; +using AnnouncementTrigger = MediaPlayerStateTrigger; template class IsIdleCondition : public Condition, public Parented { public: From 82c5cd18de86307cd6a047abc0f5489caf1af137 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Aug 2024 16:30:27 +1200 Subject: [PATCH 1896/2101] Bump docker/build-push-action from 6.5.0 to 6.6.1 in /.github/actions/build-image (#7232) 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 bd9ceb8072..f9c44cfb63 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -46,7 +46,7 @@ runs: - name: Build and push to ghcr by digest id: build-ghcr - uses: docker/build-push-action@v6.5.0 + uses: docker/build-push-action@v6.6.1 with: context: . file: ./docker/Dockerfile @@ -69,7 +69,7 @@ runs: - name: Build and push to dockerhub by digest id: build-dockerhub - uses: docker/build-push-action@v6.5.0 + uses: docker/build-push-action@v6.6.1 with: context: . file: ./docker/Dockerfile From 8a076cc9064612f51e2a356259544890c66d82a5 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Mon, 12 Aug 2024 06:49:35 +0200 Subject: [PATCH 1897/2101] fix build error (#7229) --- 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 81fa4cb339..8e4c6faaee 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1336,7 +1336,7 @@ void APIConnection::update_command(const UpdateCommandRequest &msg) { update->check(); break; default: - ESP_LOGW(TAG, "Unknown update command: %d", msg.command); + ESP_LOGW(TAG, "Unknown update command: %" PRIu32, msg.command); break; } } From f13cf1f7a02c6fbe3d867151aac276b306e0820a Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Mon, 12 Aug 2024 06:52:09 +0200 Subject: [PATCH 1898/2101] adjust to new python pre-commit hooks (#7178) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- script/clang-tidy | 35 +++++++++++++++++++++++++---------- script/helpers.py | 9 ++++----- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/script/clang-tidy b/script/clang-tidy index ea522157c5..5bb93846b2 100755 --- a/script/clang-tidy +++ b/script/clang-tidy @@ -115,9 +115,10 @@ def clang_options(idedata): pids = set() -def run_tidy(executable, args, options, tmpdir, queue, lock, failed_files): + +def run_tidy(executable, args, options, tmpdir, path_queue, lock, failed_files): while True: - path = queue.get() + path = path_queue.get() invocation = [executable] if tmpdir is not None: @@ -139,17 +140,20 @@ def run_tidy(executable, args, options, tmpdir, queue, lock, failed_files): invocation.append("--") invocation.extend(options) - proc = subprocess.run(invocation, capture_output=True, encoding="utf-8") + proc = subprocess.run( + invocation, capture_output=True, encoding="utf-8", check=False + ) if proc.returncode != 0: with lock: print_error_for_file(path, proc.stdout) failed_files.append(path) - queue.task_done() + path_queue.task_done() def progress_bar_show(value): if value is None: return "" + return None def split_list(a, n): @@ -237,7 +241,15 @@ def main(): for _ in range(args.jobs): t = threading.Thread( target=run_tidy, - args=(executable, args, options, tmpdir, task_queue, lock, failed_files), + args=( + executable, + args, + options, + tmpdir, + task_queue, + lock, + failed_files, + ), ) t.daemon = True t.start() @@ -245,14 +257,14 @@ def main(): # Fill the queue with files. with click.progressbar( files, width=30, file=sys.stderr, item_show_func=progress_bar_show - ) as bar: - for name in bar: + ) as progress_bar: + for name in progress_bar: task_queue.put(name) # Wait for all threads to be done. task_queue.join() - except FileNotFoundError as ex: + except FileNotFoundError: return 1 except KeyboardInterrupt: print() @@ -262,7 +274,7 @@ def main(): # Kill subprocesses (and ourselves!) # No simple, clean alternative appears to be available. os.kill(0, 9) - return 2 # Will not execute. + return 2 # Will not execute. if args.fix and failed_files: print("Applying fixes ...") @@ -272,7 +284,10 @@ def main(): except FileNotFoundError: subprocess.call(["clang-apply-replacements", tmpdir]) except FileNotFoundError: - print("Error please install clang-apply-replacements-14 or clang-apply-replacements.\n", file=sys.stderr) + print( + "Error please install clang-apply-replacements-14 or clang-apply-replacements.\n", + file=sys.stderr, + ) except: print("Error applying fixes.\n", file=sys.stderr) raise diff --git a/script/helpers.py b/script/helpers.py index 56349b6052..6f36faaeb1 100644 --- a/script/helpers.py +++ b/script/helpers.py @@ -159,20 +159,19 @@ def get_binary(name: str, version: str) -> str: binary_file = f"{name}-{version}" try: result = subprocess.check_output([binary_file, "-version"]) - if result.returncode == 0: - return binary_file - except Exception: + return binary_file + except FileNotFoundError: pass binary_file = name try: result = subprocess.run( - [binary_file, "-version"], text=True, capture_output=True + [binary_file, "-version"], text=True, capture_output=True, check=False ) if result.returncode == 0 and (f"version {version}") in result.stdout: return binary_file raise FileNotFoundError(f"{name} not found") - except FileNotFoundError as ex: + except FileNotFoundError: print( f""" Oops. It looks like {name} is not installed. It should be available under venv/bin From 8148eae1340c5de43c1333761b27d01f8e9d9ba9 Mon Sep 17 00:00:00 2001 From: NP v/d Spek Date: Tue, 13 Aug 2024 01:16:42 +0200 Subject: [PATCH 1899/2101] add windows script/setup.bat (#7140) Co-authored-by: Keith Burzinski --- script/setup.bat | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 script/setup.bat diff --git a/script/setup.bat b/script/setup.bat new file mode 100644 index 0000000000..0b49768139 --- /dev/null +++ b/script/setup.bat @@ -0,0 +1,28 @@ +@echo off + +if defined DEVCONTAINER goto :install +if defined VIRTUAL_ENV goto :install +if defined ESPHOME_NO_VENV goto :install + +echo Starting the Virtual Environment +python -m venv venv +call venv/Scripts/activate +echo Running the Virtual Environment + +:install + +echo Installing required packages... + +python.exe -m pip install --upgrade pip + +pip3 install -r requirements.txt -r requirements_optional.txt -r requirements_test.txt -r requirements_dev.txt +pip3 install setuptools wheel +pip3 install -e ".[dev,test,displays]" --config-settings editable_mode=compat + +pre-commit install + +python script/platformio_install_deps.py platformio.ini --libraries --tools --platforms + +echo . +echo . +echo Virtual environment created. Run 'venv/Scripts/activate' to use it. From 5f3f10628318d01d4a01e8fc23161f2ce075052b Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Tue, 13 Aug 2024 01:29:09 +0200 Subject: [PATCH 1900/2101] [code-quality] add NOLINT haier_base (#7236) --- esphome/components/haier/haier_base.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/haier/haier_base.h b/esphome/components/haier/haier_base.h index c0bf878519..7d92a6611c 100644 --- a/esphome/components/haier/haier_base.h +++ b/esphome/components/haier/haier_base.h @@ -80,8 +80,8 @@ class HaierClimateBase : public esphome::Component, const char *phase_to_string_(ProtocolPhases phase); virtual void set_handlers() = 0; virtual void process_phase(std::chrono::steady_clock::time_point now) = 0; - virtual haier_protocol::HaierMessage get_control_message() = 0; - virtual haier_protocol::HaierMessage get_power_message(bool state) = 0; + virtual haier_protocol::HaierMessage get_control_message() = 0; // NOLINT(readability-identifier-naming) + virtual haier_protocol::HaierMessage get_power_message(bool state) = 0; // NOLINT(readability-identifier-naming) virtual void initialization(){}; virtual bool prepare_pending_action(); virtual void process_protocol_reset(); From 64ee40d3704a4e40ffea6f962ada64fc803d4f62 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Tue, 13 Aug 2024 01:33:51 +0200 Subject: [PATCH 1901/2101] [code-quality] clang-tidy bedjet (#7251) --- esphome/components/bedjet/bedjet_codec.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/bedjet/bedjet_codec.h b/esphome/components/bedjet/bedjet_codec.h index 527e757d7f..07aee32d54 100644 --- a/esphome/components/bedjet/bedjet_codec.h +++ b/esphome/components/bedjet/bedjet_codec.h @@ -90,7 +90,7 @@ struct BedjetStatusPacket { int unused_6 : 1; // 0x4 bool is_dual_zone : 1; /// Is part of a Dual Zone configuration int unused_7 : 1; // 0x1 - } dual_zone_flags; + } dual_zone_flags; // NOLINT(clang-diagnostic-unaligned-access) uint8_t unused_4 : 8; // Unknown 23-24 = 0x1310 uint8_t unused_5 : 8; // Unknown 23-24 = 0x1310 From f24fd34d860ab39fa66d100aff96dc0f0ec43ee2 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Tue, 13 Aug 2024 01:38:13 +0200 Subject: [PATCH 1902/2101] fix name conflict with zephyr macro (#7252) --- esphome/components/fingerprint_grow/fingerprint_grow.cpp | 2 +- esphome/components/fingerprint_grow/fingerprint_grow.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/fingerprint_grow/fingerprint_grow.cpp b/esphome/components/fingerprint_grow/fingerprint_grow.cpp index c2cab368c9..0dfea49b8b 100644 --- a/esphome/components/fingerprint_grow/fingerprint_grow.cpp +++ b/esphome/components/fingerprint_grow/fingerprint_grow.cpp @@ -307,7 +307,7 @@ void FingerprintGrowComponent::delete_fingerprint(uint16_t finger_id) { void FingerprintGrowComponent::delete_all_fingerprints() { ESP_LOGI(TAG, "Deleting all stored fingerprints"); - this->data_ = {EMPTY}; + this->data_ = {DELETE_ALL}; switch (this->send_command_()) { case OK: ESP_LOGI(TAG, "Deleted all fingerprints"); diff --git a/esphome/components/fingerprint_grow/fingerprint_grow.h b/esphome/components/fingerprint_grow/fingerprint_grow.h index 20ff60997b..1c3098ef14 100644 --- a/esphome/components/fingerprint_grow/fingerprint_grow.h +++ b/esphome/components/fingerprint_grow/fingerprint_grow.h @@ -36,7 +36,7 @@ enum GrowCommand { LOAD = 0x07, UPLOAD = 0x08, DELETE = 0x0C, - EMPTY = 0x0D, + DELETE_ALL = 0x0D, // aka EMPTY READ_SYS_PARAM = 0x0F, SET_PASSWORD = 0x12, VERIFY_PASSWORD = 0x13, From 8d5be27746ed6a510b87f53cff6811a277a2589d Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Tue, 13 Aug 2024 02:47:18 +0200 Subject: [PATCH 1903/2101] [code-quality] Apply ruff linting suggestions (#7239) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/network/__init__.py | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/esphome/components/network/__init__.py b/esphome/components/network/__init__.py index 9ef75e0fb9..f5ddbc0da7 100644 --- a/esphome/components/network/__init__.py +++ b/esphome/components/network/__init__.py @@ -1,8 +1,6 @@ -from esphome.core import CORE import esphome.codegen as cg -import esphome.config_validation as cv from esphome.components.esp32 import add_idf_sdkconfig_option - +import esphome.config_validation as cv from esphome.const import ( CONF_ENABLE_IPV6, CONF_MIN_IPV6_ADDR_COUNT, @@ -10,6 +8,7 @@ from esphome.const import ( PLATFORM_ESP8266, PLATFORM_RP2040, ) +from esphome.core import CORE CODEOWNERS = ["@esphome/core"] AUTO_LOAD = ["mdns"] @@ -42,11 +41,10 @@ async def to_code(config): if CORE.using_esp_idf: add_idf_sdkconfig_option("CONFIG_LWIP_IPV6", enable_ipv6) add_idf_sdkconfig_option("CONFIG_LWIP_IPV6_AUTOCONFIG", enable_ipv6) - else: - if enable_ipv6: - cg.add_build_flag("-DCONFIG_LWIP_IPV6") - cg.add_build_flag("-DCONFIG_LWIP_IPV6_AUTOCONFIG") - if CORE.is_rp2040: - cg.add_build_flag("-DPIO_FRAMEWORK_ARDUINO_ENABLE_IPV6") - if CORE.is_esp8266: - cg.add_build_flag("-DPIO_FRAMEWORK_ARDUINO_LWIP2_IPV6_LOW_MEMORY") + elif enable_ipv6: + cg.add_build_flag("-DCONFIG_LWIP_IPV6") + cg.add_build_flag("-DCONFIG_LWIP_IPV6_AUTOCONFIG") + if CORE.is_rp2040: + cg.add_build_flag("-DPIO_FRAMEWORK_ARDUINO_ENABLE_IPV6") + if CORE.is_esp8266: + cg.add_build_flag("-DPIO_FRAMEWORK_ARDUINO_LWIP2_IPV6_LOW_MEMORY") From fc146dabed431ff1c7f314d329cad62ea9d06731 Mon Sep 17 00:00:00 2001 From: juanluss31 <40864809+juanluss31@users.noreply.github.com> Date: Tue, 13 Aug 2024 03:12:48 +0200 Subject: [PATCH 1904/2101] Add support for LYWSD02MMC Xiaomi device (#7080) --- CODEOWNERS | 1 + esphome/components/xiaomi_ble/xiaomi_ble.cpp | 23 +++++- esphome/components/xiaomi_ble/xiaomi_ble.h | 1 + .../components/xiaomi_lywsd02mmc/__init__.py | 0 .../components/xiaomi_lywsd02mmc/sensor.py | 77 +++++++++++++++++++ .../xiaomi_lywsd02mmc/xiaomi_lywsd02mmc.cpp | 73 ++++++++++++++++++ .../xiaomi_lywsd02mmc/xiaomi_lywsd02mmc.h | 37 +++++++++ .../components/xiaomi_lywsd02mmc/common.yaml | 12 +++ .../xiaomi_lywsd02mmc/test.esp32-ard.yaml | 1 + .../xiaomi_lywsd02mmc/test.esp32-c3-ard.yaml | 1 + .../xiaomi_lywsd02mmc/test.esp32-c3-idf.yaml | 1 + .../xiaomi_lywsd02mmc/test.esp32-idf.yaml | 1 + 12 files changed, 225 insertions(+), 3 deletions(-) create mode 100644 esphome/components/xiaomi_lywsd02mmc/__init__.py create mode 100644 esphome/components/xiaomi_lywsd02mmc/sensor.py create mode 100644 esphome/components/xiaomi_lywsd02mmc/xiaomi_lywsd02mmc.cpp create mode 100644 esphome/components/xiaomi_lywsd02mmc/xiaomi_lywsd02mmc.h create mode 100644 tests/components/xiaomi_lywsd02mmc/common.yaml create mode 100644 tests/components/xiaomi_lywsd02mmc/test.esp32-ard.yaml create mode 100644 tests/components/xiaomi_lywsd02mmc/test.esp32-c3-ard.yaml create mode 100644 tests/components/xiaomi_lywsd02mmc/test.esp32-c3-idf.yaml create mode 100644 tests/components/xiaomi_lywsd02mmc/test.esp32-idf.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 999449a3df..9865e51f11 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -453,6 +453,7 @@ esphome/components/wl_134/* @hobbypunk90 esphome/components/x9c/* @EtienneMD esphome/components/xgzp68xx/* @gcormier esphome/components/xiaomi_hhccjcy10/* @fariouche +esphome/components/xiaomi_lywsd02mmc/* @juanluss31 esphome/components/xiaomi_lywsd03mmc/* @ahpohl esphome/components/xiaomi_mhoc303/* @drug123 esphome/components/xiaomi_mhoc401/* @vevsvevs diff --git a/esphome/components/xiaomi_ble/xiaomi_ble.cpp b/esphome/components/xiaomi_ble/xiaomi_ble.cpp index 95faea0446..85434341cc 100644 --- a/esphome/components/xiaomi_ble/xiaomi_ble.cpp +++ b/esphome/components/xiaomi_ble/xiaomi_ble.cpp @@ -49,8 +49,8 @@ bool parse_xiaomi_value(uint16_t value_type, const uint8_t *data, uint8_t value_ const uint16_t conductivity = encode_uint16(data[1], data[0]); result.conductivity = conductivity; } - // battery, 1 byte, 8-bit unsigned integer, 1 % - else if ((value_type == 0x100A) && (value_length == 1)) { + // battery / MiaoMiaoce battery, 1 byte, 8-bit unsigned integer, 1 % + else if ((value_type == 0x100A || value_type == 0x4803) && (value_length == 1)) { result.battery_level = data[0]; } // temperature + humidity, 4 bytes, 16-bit signed integer (LE) each, 0.1 °C, 0.1 % @@ -80,6 +80,17 @@ bool parse_xiaomi_value(uint16_t value_type, const uint8_t *data, uint8_t value_ result.has_motion = !idle_time; } else if ((value_type == 0x1018) && (value_length == 1)) { result.is_light = data[0]; + } + // MiaoMiaoce temperature, 4 bytes, float, 0.1 °C + else if ((value_type == 0x4C01) && (value_length == 4)) { + const uint32_t int_number = encode_uint32(data[3], data[2], data[1], data[0]); + float temperature; + std::memcpy(&temperature, &int_number, sizeof(temperature)); + result.temperature = temperature; + } + // MiaoMiaoce humidity, 1 byte, 8-bit unsigned integer, 1 % + else if ((value_type == 0x4C02) && (value_length == 1)) { + result.humidity = data[0]; } else { return false; } @@ -111,7 +122,8 @@ bool parse_xiaomi_message(const std::vector &message, XiaomiParseResult } while (payload_length > 3) { - if (payload[payload_offset + 1] != 0x10 && payload[payload_offset + 1] != 0x00) { + if (payload[payload_offset + 1] != 0x10 && payload[payload_offset + 1] != 0x00 && + payload[payload_offset + 1] != 0x4C && payload[payload_offset + 1] != 0x48) { ESP_LOGVV(TAG, "parse_xiaomi_message(): fixed byte not found, stop parsing residual data."); break; } @@ -190,6 +202,11 @@ optional parse_xiaomi_header(const esp32_ble_tracker::Service } else if (device_uuid == 0x045b) { // rectangular body, e-ink display result.type = XiaomiParseResult::TYPE_LYWSD02; result.name = "LYWSD02"; + } else if (device_uuid == 0x2542) { // rectangular body, e-ink display — with bindkeys + result.type = XiaomiParseResult::TYPE_LYWSD02MMC; + result.name = "LYWSD02MMC"; + if (raw.size() == 19) + result.raw_offset -= 6; } else if (device_uuid == 0x040a) { // Mosquito Repellent Smart Version result.type = XiaomiParseResult::TYPE_WX08ZM; result.name = "WX08ZM"; diff --git a/esphome/components/xiaomi_ble/xiaomi_ble.h b/esphome/components/xiaomi_ble/xiaomi_ble.h index c1086605d1..6978be97f4 100644 --- a/esphome/components/xiaomi_ble/xiaomi_ble.h +++ b/esphome/components/xiaomi_ble/xiaomi_ble.h @@ -17,6 +17,7 @@ struct XiaomiParseResult { TYPE_HHCCPOT002, TYPE_LYWSDCGQ, TYPE_LYWSD02, + TYPE_LYWSD02MMC, TYPE_CGG1, TYPE_LYWSD03MMC, TYPE_CGD1, diff --git a/esphome/components/xiaomi_lywsd02mmc/__init__.py b/esphome/components/xiaomi_lywsd02mmc/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/xiaomi_lywsd02mmc/sensor.py b/esphome/components/xiaomi_lywsd02mmc/sensor.py new file mode 100644 index 0000000000..43784ef698 --- /dev/null +++ b/esphome/components/xiaomi_lywsd02mmc/sensor.py @@ -0,0 +1,77 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import sensor, esp32_ble_tracker +from esphome.const import ( + CONF_BATTERY_LEVEL, + CONF_HUMIDITY, + CONF_MAC_ADDRESS, + CONF_TEMPERATURE, + DEVICE_CLASS_TEMPERATURE, + ENTITY_CATEGORY_DIAGNOSTIC, + STATE_CLASS_MEASUREMENT, + UNIT_CELSIUS, + UNIT_PERCENT, + DEVICE_CLASS_HUMIDITY, + DEVICE_CLASS_BATTERY, + CONF_ID, + CONF_BINDKEY, +) + +AUTO_LOAD = ["xiaomi_ble"] +CODEOWNERS = ["@juanluss31"] +DEPENDENCIES = ["esp32_ble_tracker"] + +xiaomi_lywsd02mmc_ns = cg.esphome_ns.namespace("xiaomi_lywsd02mmc") +XiaomiLYWSD02MMC = xiaomi_lywsd02mmc_ns.class_( + "XiaomiLYWSD02MMC", esp32_ble_tracker.ESPBTDeviceListener, cg.Component +) + +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(XiaomiLYWSD02MMC), + cv.Required(CONF_MAC_ADDRESS): cv.mac_address, + cv.Required(CONF_BINDKEY): cv.bind_key, + 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, + ), + cv.Optional(CONF_BATTERY_LEVEL): sensor.sensor_schema( + unit_of_measurement=UNIT_PERCENT, + accuracy_decimals=0, + device_class=DEVICE_CLASS_BATTERY, + state_class=STATE_CLASS_MEASUREMENT, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + ), + } + ) + .extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA) + .extend(cv.COMPONENT_SCHEMA) +) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + 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)) + cg.add(var.set_bindkey(config[CONF_BINDKEY])) + + 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)) + if battery_level_config := config.get(CONF_BATTERY_LEVEL): + sens = await sensor.new_sensor(battery_level_config) + cg.add(var.set_battery_level(sens)) diff --git a/esphome/components/xiaomi_lywsd02mmc/xiaomi_lywsd02mmc.cpp b/esphome/components/xiaomi_lywsd02mmc/xiaomi_lywsd02mmc.cpp new file mode 100644 index 0000000000..cc122f2264 --- /dev/null +++ b/esphome/components/xiaomi_lywsd02mmc/xiaomi_lywsd02mmc.cpp @@ -0,0 +1,73 @@ +#include "xiaomi_lywsd02mmc.h" +#include "esphome/core/log.h" + +#ifdef USE_ESP32 + +namespace esphome { +namespace xiaomi_lywsd02mmc { + +static const char *const TAG = "xiaomi_lywsd02mmc"; + +void XiaomiLYWSD02MMC::dump_config() { + ESP_LOGCONFIG(TAG, "Xiaomi LYWSD02MMC"); + ESP_LOGCONFIG(TAG, " Bindkey: %s", format_hex_pretty(this->bindkey_, 16).c_str()); + LOG_SENSOR(" ", "Temperature", this->temperature_); + LOG_SENSOR(" ", "Humidity", this->humidity_); + LOG_SENSOR(" ", "Battery Level", this->battery_level_); +} + +bool XiaomiLYWSD02MMC::parse_device(const esp32_ble_tracker::ESPBTDevice &device) { + if (device.address_uint64() != this->address_) { + ESP_LOGVV(TAG, "parse_device(): unknown MAC address."); + return false; + } + ESP_LOGVV(TAG, "parse_device(): MAC address %s found.", device.address_str().c_str()); + + bool success = false; + for (auto &service_data : device.get_service_datas()) { + auto res = xiaomi_ble::parse_xiaomi_header(service_data); + if (!res.has_value()) { + continue; + } + if (res->is_duplicate) { + continue; + } + if (res->has_encryption && + (!(xiaomi_ble::decrypt_xiaomi_payload(const_cast &>(service_data.data), this->bindkey_, + this->address_)))) { + continue; + } + if (!(xiaomi_ble::parse_xiaomi_message(service_data.data, *res))) { + continue; + } + if (!(xiaomi_ble::report_xiaomi_results(res, device.address_str()))) { + continue; + } + if (res->temperature.has_value() && this->temperature_ != nullptr) + this->temperature_->publish_state(*res->temperature); + if (res->humidity.has_value() && this->humidity_ != nullptr) + this->humidity_->publish_state(*res->humidity); + if (res->battery_level.has_value() && this->battery_level_ != nullptr) + this->battery_level_->publish_state(*res->battery_level); + success = true; + } + + return success; +} + +void XiaomiLYWSD02MMC::set_bindkey(const std::string &bindkey) { + memset(this->bindkey_, 0, 16); + if (bindkey.size() != 32) { + return; + } + char temp[3] = {0}; + for (int i = 0; i < 16; i++) { + strncpy(temp, &(bindkey.c_str()[i * 2]), 2); + this->bindkey_[i] = std::strtoul(temp, nullptr, 16); + } +} + +} // namespace xiaomi_lywsd02mmc +} // namespace esphome + +#endif diff --git a/esphome/components/xiaomi_lywsd02mmc/xiaomi_lywsd02mmc.h b/esphome/components/xiaomi_lywsd02mmc/xiaomi_lywsd02mmc.h new file mode 100644 index 0000000000..19092aa2a9 --- /dev/null +++ b/esphome/components/xiaomi_lywsd02mmc/xiaomi_lywsd02mmc.h @@ -0,0 +1,37 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/components/sensor/sensor.h" +#include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h" +#include "esphome/components/xiaomi_ble/xiaomi_ble.h" + +#ifdef USE_ESP32 + +namespace esphome { +namespace xiaomi_lywsd02mmc { + +class XiaomiLYWSD02MMC : public Component, public esp32_ble_tracker::ESPBTDeviceListener { + public: + void set_address(uint64_t address) { this->address_ = address; } + void set_bindkey(const std::string &bindkey); + + bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override; + + void dump_config() override; + float get_setup_priority() const override { return setup_priority::DATA; } + void set_temperature(sensor::Sensor *temperature) { this->temperature_ = temperature; } + void set_humidity(sensor::Sensor *humidity) { this->humidity_ = humidity; } + void set_battery_level(sensor::Sensor *battery_level) { this->battery_level_ = battery_level; } + + protected: + uint64_t address_; + uint8_t bindkey_[16]; + sensor::Sensor *temperature_{nullptr}; + sensor::Sensor *humidity_{nullptr}; + sensor::Sensor *battery_level_{nullptr}; +}; + +} // namespace xiaomi_lywsd02mmc +} // namespace esphome + +#endif diff --git a/tests/components/xiaomi_lywsd02mmc/common.yaml b/tests/components/xiaomi_lywsd02mmc/common.yaml new file mode 100644 index 0000000000..e63f585830 --- /dev/null +++ b/tests/components/xiaomi_lywsd02mmc/common.yaml @@ -0,0 +1,12 @@ +esp32_ble_tracker: + +sensor: + - platform: xiaomi_lywsd02mmc + mac_address: A4:C1:38:54:5E:18 + bindkey: 2529d8e0d23150a588675cc54ad48400 + temperature: + name: Xiaomi LYWSD02MMC Temperature + humidity: + name: Xiaomi LYWSD02MMC Humidity + battery_level: + name: Xiaomi LYWSD02MMC Battery Level diff --git a/tests/components/xiaomi_lywsd02mmc/test.esp32-ard.yaml b/tests/components/xiaomi_lywsd02mmc/test.esp32-ard.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/xiaomi_lywsd02mmc/test.esp32-ard.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/xiaomi_lywsd02mmc/test.esp32-c3-ard.yaml b/tests/components/xiaomi_lywsd02mmc/test.esp32-c3-ard.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/xiaomi_lywsd02mmc/test.esp32-c3-ard.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/xiaomi_lywsd02mmc/test.esp32-c3-idf.yaml b/tests/components/xiaomi_lywsd02mmc/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/xiaomi_lywsd02mmc/test.esp32-c3-idf.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/xiaomi_lywsd02mmc/test.esp32-idf.yaml b/tests/components/xiaomi_lywsd02mmc/test.esp32-idf.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/xiaomi_lywsd02mmc/test.esp32-idf.yaml @@ -0,0 +1 @@ +<<: !include common.yaml From 8d106e97a2bd03239e11609fb6a53b1e493c634b Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Tue, 13 Aug 2024 03:14:25 +0200 Subject: [PATCH 1905/2101] [code-quality] fix clang-tidy web server (#7230) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/web_server/web_server.h | 2 +- esphome/components/web_server_base/web_server_base.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/esphome/components/web_server/web_server.h b/esphome/components/web_server/web_server.h index 5b98806af1..d4ab592b7b 100644 --- a/esphome/components/web_server/web_server.h +++ b/esphome/components/web_server/web_server.h @@ -334,7 +334,7 @@ class WebServer : public Controller, public Component, public AsyncWebHandler { /// Override the web handler's handleRequest method. void handleRequest(AsyncWebServerRequest *request) override; /// This web handle is not trivial. - bool isRequestHandlerTrivial() override; + bool isRequestHandlerTrivial() override; // NOLINT(readability-identifier-naming) void add_entity_to_sorting_list(EntityBase *entity, float weight); diff --git a/esphome/components/web_server_base/web_server_base.h b/esphome/components/web_server_base/web_server_base.h index c312126472..2282d55ec1 100644 --- a/esphome/components/web_server_base/web_server_base.h +++ b/esphome/components/web_server_base/web_server_base.h @@ -134,6 +134,7 @@ class OTARequestHandler : public AsyncWebHandler { return request->url() == "/update" && request->method() == HTTP_POST; } + // NOLINTNEXTLINE(readability-identifier-naming) bool isRequestHandlerTrivial() override { return false; } protected: From 390d5f2f9361c00c558d64fb00c9ce66b92703e1 Mon Sep 17 00:00:00 2001 From: RFDarter Date: Tue, 13 Aug 2024 03:26:39 +0200 Subject: [PATCH 1906/2101] [test][web_server] Rejig test for v3 (#7110) --- tests/components/web_server/common_v1.yaml | 3 ++- tests/components/web_server/common_v2.yaml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/components/web_server/common_v1.yaml b/tests/components/web_server/common_v1.yaml index bf5aab4ce6..3c51f894b8 100644 --- a/tests/components/web_server/common_v1.yaml +++ b/tests/components/web_server/common_v1.yaml @@ -1,4 +1,5 @@ -<<: !include common.yaml +packages: + device_base: !include common.yaml web_server: port: 8080 diff --git a/tests/components/web_server/common_v2.yaml b/tests/components/web_server/common_v2.yaml index 564c43e553..2af5ceca44 100644 --- a/tests/components/web_server/common_v2.yaml +++ b/tests/components/web_server/common_v2.yaml @@ -1,4 +1,5 @@ -<<: !include common.yaml +packages: + device_base: !include common.yaml web_server: port: 8080 From ab51bbd8f7a9ca8648f7a245cdec02f8fa08e14b Mon Sep 17 00:00:00 2001 From: Olivier ARCHER Date: Tue, 13 Aug 2024 03:52:31 +0200 Subject: [PATCH 1907/2101] [api] Error log when NONE Update command is sent (#7247) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/api/api_connection.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 8e4c6faaee..bd438265d4 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1335,6 +1335,9 @@ void APIConnection::update_command(const UpdateCommandRequest &msg) { case enums::UPDATE_COMMAND_CHECK: update->check(); break; + case enums::UPDATE_COMMAND_NONE: + ESP_LOGE(TAG, "UPDATE_COMMAND_NONE not handled. Check client is sending the correct command"); + break; default: ESP_LOGW(TAG, "Unknown update command: %" PRIu32, msg.command); break; From 2b25daa199b175e1f2d3f1db94b6516f37b90748 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 13 Aug 2024 17:12:06 +1200 Subject: [PATCH 1908/2101] [api] Add new flag to request state/attribute once from HA only (#7258) --- esphome/components/api/api.proto | 1 + esphome/components/api/api_pb2.cpp | 15 +++++++++++++++ esphome/components/api/api_pb2.h | 2 ++ esphome/components/api/api_server.cpp | 10 ++++++++++ esphome/components/api/api_server.h | 3 +++ 5 files changed, 31 insertions(+) diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index b62fddf815..72eaeed6d7 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -686,6 +686,7 @@ message SubscribeHomeAssistantStateResponse { option (source) = SOURCE_SERVER; string entity_id = 1; string attribute = 2; + bool once = 3; } message HomeAssistantStateResponse { diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index a57627a66c..bb37824403 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -3109,6 +3109,16 @@ void SubscribeHomeAssistantStatesRequest::dump_to(std::string &out) const { out.append("SubscribeHomeAssistantStatesRequest {}"); } #endif +bool SubscribeHomeAssistantStateResponse::decode_varint(uint32_t field_id, ProtoVarInt value) { + switch (field_id) { + case 3: { + this->once = value.as_bool(); + return true; + } + default: + return false; + } +} bool SubscribeHomeAssistantStateResponse::decode_length(uint32_t field_id, ProtoLengthDelimited value) { switch (field_id) { case 1: { @@ -3126,6 +3136,7 @@ bool SubscribeHomeAssistantStateResponse::decode_length(uint32_t field_id, Proto 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); } #ifdef HAS_PROTO_MESSAGE_DUMP void SubscribeHomeAssistantStateResponse::dump_to(std::string &out) const { @@ -3138,6 +3149,10 @@ void SubscribeHomeAssistantStateResponse::dump_to(std::string &out) const { out.append(" attribute: "); out.append("'").append(this->attribute).append("'"); out.append("\n"); + + out.append(" once: "); + out.append(YESNO(this->once)); + out.append("\n"); out.append("}"); } #endif diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index bb5263cffa..3eb945fd8d 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -836,6 +836,7 @@ class SubscribeHomeAssistantStateResponse : public ProtoMessage { public: std::string entity_id{}; std::string attribute{}; + bool once{false}; void encode(ProtoWriteBuffer buffer) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; @@ -843,6 +844,7 @@ class SubscribeHomeAssistantStateResponse : public ProtoMessage { protected: bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; + bool decode_varint(uint32_t field_id, ProtoVarInt value) override; }; class HomeAssistantStateResponse : public ProtoMessage { public: diff --git a/esphome/components/api/api_server.cpp b/esphome/components/api/api_server.cpp index a61ae89243..0fde3e47af 100644 --- a/esphome/components/api/api_server.cpp +++ b/esphome/components/api/api_server.cpp @@ -359,8 +359,18 @@ void APIServer::subscribe_home_assistant_state(std::string entity_id, optional attribute, + std::function f) { + this->state_subs_.push_back(HomeAssistantStateSubscription{ + .entity_id = std::move(entity_id), + .attribute = std::move(attribute), + .callback = std::move(f), + .once = true, + }); +}; const std::vector &APIServer::get_state_subs() const { return this->state_subs_; } diff --git a/esphome/components/api/api_server.h b/esphome/components/api/api_server.h index 43bc8a7348..899eaede49 100644 --- a/esphome/components/api/api_server.h +++ b/esphome/components/api/api_server.h @@ -112,10 +112,13 @@ class APIServer : public Component, public Controller { std::string entity_id; optional attribute; std::function callback; + bool once; }; void subscribe_home_assistant_state(std::string entity_id, optional attribute, std::function f); + void get_home_assistant_state(std::string entity_id, optional attribute, + std::function f); const std::vector &get_state_subs() const; const std::vector &get_user_services() const { return this->user_services_; } From 8696f922d120e787f7231d9d4b8a00f74eec0125 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 13 Aug 2024 17:33:16 +1200 Subject: [PATCH 1909/2101] [homeassistant] Add ``HOME_ASSISTANT_IMPORT_CONTROL_SCHEMA`` (#7259) --- CODEOWNERS | 2 +- esphome/components/homeassistant/__init__.py | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index 9865e51f11..663a942cb4 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -168,7 +168,7 @@ esphome/components/he60r/* @clydebarrow esphome/components/heatpumpir/* @rob-deutsch esphome/components/hitachi_ac424/* @sourabhjaiswal esphome/components/hm3301/* @freekode -esphome/components/homeassistant/* @OttoWinter +esphome/components/homeassistant/* @OttoWinter @esphome/core esphome/components/honeywell_hih_i2c/* @Benichou34 esphome/components/honeywellabp/* @RubyBailey esphome/components/honeywellabp2_i2c/* @jpfaff diff --git a/esphome/components/homeassistant/__init__.py b/esphome/components/homeassistant/__init__.py index 776aa7fd7b..6d997e48ca 100644 --- a/esphome/components/homeassistant/__init__.py +++ b/esphome/components/homeassistant/__init__.py @@ -2,7 +2,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.const import CONF_ATTRIBUTE, CONF_ENTITY_ID, CONF_INTERNAL -CODEOWNERS = ["@OttoWinter"] +CODEOWNERS = ["@OttoWinter", "@esphome/core"] homeassistant_ns = cg.esphome_ns.namespace("homeassistant") HOME_ASSISTANT_IMPORT_SCHEMA = cv.Schema( @@ -13,6 +13,13 @@ HOME_ASSISTANT_IMPORT_SCHEMA = cv.Schema( } ) +HOME_ASSISTANT_IMPORT_CONTROL_SCHEMA = cv.Schema( + { + cv.Required(CONF_ENTITY_ID): cv.entity_id, + cv.Optional(CONF_INTERNAL, default=True): cv.boolean, + } +) + def setup_home_assistant_entity(var, config): cg.add(var.set_entity_id(config[CONF_ENTITY_ID])) From 2a70ef05d17c0645fd4e9023d6b1bc5c2ea078ca Mon Sep 17 00:00:00 2001 From: nkinnan Date: Mon, 12 Aug 2024 23:48:12 -0700 Subject: [PATCH 1910/2101] [const] Add some units for future use and adjust case (#7260) --- esphome/const.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/esphome/const.py b/esphome/const.py index 13559ecf95..c5d0e8f838 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1034,8 +1034,10 @@ UNIT_KELVIN = "K" UNIT_KILOGRAM = "kg" UNIT_KILOMETER = "km" UNIT_KILOMETER_PER_HOUR = "km/h" -UNIT_KILOVOLT_AMPS_REACTIVE = "kVAr" -UNIT_KILOVOLT_AMPS_REACTIVE_HOURS = "kVArh" +UNIT_KILOVOLT_AMPS = "kVA" +UNIT_KILOVOLT_AMPS_HOURS = "kVAh" +UNIT_KILOVOLT_AMPS_REACTIVE = "kVAR" +UNIT_KILOVOLT_AMPS_REACTIVE_HOURS = "kVARh" UNIT_KILOWATT = "kW" UNIT_KILOWATT_HOURS = "kWh" UNIT_LUX = "lx" @@ -1066,6 +1068,7 @@ UNIT_SECOND = "s" UNIT_STEPS = "steps" UNIT_VOLT = "V" UNIT_VOLT_AMPS = "VA" +UNIT_VOLT_AMPS_HOURS = "VAh" UNIT_VOLT_AMPS_REACTIVE = "VAR" UNIT_VOLT_AMPS_REACTIVE_HOURS = "VARh" UNIT_WATT = "W" From 506e69addf81fc8cc542520d7db17937a8b74c5b Mon Sep 17 00:00:00 2001 From: guillempages Date: Tue, 13 Aug 2024 09:44:43 +0200 Subject: [PATCH 1911/2101] [online_image] add option to show placeholder while downloading (#7083) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/online_image/__init__.py | 6 ++++++ esphome/components/online_image/online_image.cpp | 8 ++++++++ esphome/components/online_image/online_image.h | 11 +++++++++++ 3 files changed, 25 insertions(+) diff --git a/esphome/components/online_image/__init__.py b/esphome/components/online_image/__init__.py index ee5357457a..d9a7609543 100644 --- a/esphome/components/online_image/__init__.py +++ b/esphome/components/online_image/__init__.py @@ -27,6 +27,7 @@ CODEOWNERS = ["@guillempages"] MULTI_CONF = True CONF_ON_DOWNLOAD_FINISHED = "on_download_finished" +CONF_PLACEHOLDER = "placeholder" _LOGGER = logging.getLogger(__name__) @@ -73,6 +74,7 @@ ONLINE_IMAGE_SCHEMA = cv.Schema( # cv.Required(CONF_URL): cv.url, cv.Required(CONF_FORMAT): cv.enum(IMAGE_FORMAT, upper=True), + cv.Optional(CONF_PLACEHOLDER): cv.use_id(Image_), cv.Optional(CONF_BUFFER_SIZE, default=2048): cv.int_range(256, 65536), cv.Optional(CONF_ON_DOWNLOAD_FINISHED): automation.validate_automation( { @@ -152,6 +154,10 @@ async def to_code(config): cg.add(var.set_transparency(transparent)) + 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, [], conf) diff --git a/esphome/components/online_image/online_image.cpp b/esphome/components/online_image/online_image.cpp index a4cf0158aa..480bad6aca 100644 --- a/esphome/components/online_image/online_image.cpp +++ b/esphome/components/online_image/online_image.cpp @@ -35,6 +35,14 @@ OnlineImage::OnlineImage(const std::string &url, int width, int height, ImageFor 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); + } +} + void OnlineImage::release() { if (this->buffer_) { ESP_LOGD(TAG, "Deallocating old buffer..."); diff --git a/esphome/components/online_image/online_image.h b/esphome/components/online_image/online_image.h index 30e97760ea..775cc46e0b 100644 --- a/esphome/components/online_image/online_image.h +++ b/esphome/components/online_image/online_image.h @@ -50,6 +50,8 @@ class OnlineImage : public PollingComponent, OnlineImage(const std::string &url, int width, int height, ImageFormat format, image::ImageType type, uint32_t buffer_size); + void draw(int x, int y, display::Display *display, Color color_on, Color color_off) override; + void update() override; void loop() override; @@ -60,6 +62,14 @@ class OnlineImage : public PollingComponent, } } + /** + * @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. @@ -113,6 +123,7 @@ class OnlineImage : public PollingComponent, DownloadBuffer download_buffer_; const ImageFormat format_; + image::Image *placeholder_{nullptr}; std::string url_{""}; From 3598560472b844c172a1ed2783f13ba258be378d Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Tue, 13 Aug 2024 18:06:01 +1000 Subject: [PATCH 1912/2101] [lvgl] Add initial_focus for encoders (#7256) --- esphome/components/lvgl/__init__.py | 3 ++- esphome/components/lvgl/defines.py | 1 + esphome/components/lvgl/encoders.py | 8 ++++++++ esphome/components/lvgl/schemas.py | 25 +++++++++++++++-------- tests/components/lvgl/test.esp32-ard.yaml | 1 + 5 files changed, 29 insertions(+), 9 deletions(-) diff --git a/esphome/components/lvgl/__init__.py b/esphome/components/lvgl/__init__.py index 6bf6e287f8..7c51d9c70d 100644 --- a/esphome/components/lvgl/__init__.py +++ b/esphome/components/lvgl/__init__.py @@ -23,7 +23,7 @@ from esphome.helpers import write_file_if_changed from . import defines as df, helpers, lv_validation as lvalid from .automation import disp_update, update_to_code from .defines import CONF_SKIP -from .encoders import ENCODERS_CONFIG, encoders_to_code +from .encoders import ENCODERS_CONFIG, encoders_to_code, initial_focus_to_code from .lv_validation import lv_bool, lv_images_used from .lvcode import LvContext, LvglComponent from .schemas import ( @@ -272,6 +272,7 @@ async def to_code(config): templ = await cg.templatable(conf[CONF_TIMEOUT], [], cg.uint32) idle_trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], lv_component, templ) await build_automation(idle_trigger, [], conf) + await initial_focus_to_code(config) for comp in helpers.lvgl_components_required: CORE.add_define(f"USE_LVGL_{comp.upper()}") diff --git a/esphome/components/lvgl/defines.py b/esphome/components/lvgl/defines.py index 1c6fd2678c..e48679996b 100644 --- a/esphome/components/lvgl/defines.py +++ b/esphome/components/lvgl/defines.py @@ -413,6 +413,7 @@ CONF_GRID_ROW_ALIGN = "grid_row_align" CONF_GRID_ROWS = "grid_rows" CONF_HEADER_MODE = "header_mode" CONF_HOME = "home" +CONF_INITIAL_FOCUS = "initial_focus" CONF_KEY_CODE = "key_code" CONF_LAYOUT = "layout" CONF_LEFT_BUTTON = "left_button" diff --git a/esphome/components/lvgl/encoders.py b/esphome/components/lvgl/encoders.py index cfd0e42996..81bcda95b4 100644 --- a/esphome/components/lvgl/encoders.py +++ b/esphome/components/lvgl/encoders.py @@ -8,6 +8,7 @@ from .defines import ( CONF_DEFAULT_GROUP, CONF_ENCODERS, CONF_ENTER_BUTTON, + CONF_INITIAL_FOCUS, CONF_LEFT_BUTTON, CONF_LONG_PRESS_REPEAT_TIME, CONF_LONG_PRESS_TIME, @@ -67,3 +68,10 @@ async def encoders_to_code(var, config): else: group = default_group lv.indev_set_group(lv_expr.indev_drv_register(listener.get_drv()), group) + + +async def initial_focus_to_code(config): + for enc_conf in config[CONF_ENCODERS]: + if default_focus := enc_conf.get(CONF_INITIAL_FOCUS): + obj = await cg.get_variable(default_focus) + lv.group_focus_obj(obj) diff --git a/esphome/components/lvgl/schemas.py b/esphome/components/lvgl/schemas.py index f172ba9f2b..e4b1c3f8fa 100644 --- a/esphome/components/lvgl/schemas.py +++ b/esphome/components/lvgl/schemas.py @@ -14,11 +14,19 @@ from esphome.const import ( from esphome.core import TimePeriod from esphome.schema_extractors import SCHEMA_EXTRACT -from . import defines as df, lv_validation as lvalid, types as ty +from . import defines as df, lv_validation as lvalid from .helpers import add_lv_use, requires_component, validate_printf from .lv_validation import lv_color, lv_font, lv_image from .lvcode import LvglComponent -from .types import WidgetType, lv_group_t +from .types import ( + LVEncoderListener, + LvType, + WidgetType, + lv_group_t, + lv_obj_t, + lv_pseudo_button_t, + lv_style_t, +) # this will be populated later, in __init__.py to avoid circular imports. WIDGET_TYPES: dict = {} @@ -46,7 +54,7 @@ TEXT_SCHEMA = cv.Schema( LIST_ACTION_SCHEMA = cv.ensure_list( cv.maybe_simple_value( { - cv.Required(CONF_ID): cv.use_id(ty.lv_pseudo_button_t), + cv.Required(CONF_ID): cv.use_id(lv_pseudo_button_t), }, key=CONF_ID, ) @@ -59,9 +67,10 @@ PRESS_TIME = cv.All( ENCODER_SCHEMA = cv.Schema( { cv.GenerateID(): cv.All( - cv.declare_id(ty.LVEncoderListener), requires_component("binary_sensor") + cv.declare_id(LVEncoderListener), requires_component("binary_sensor") ), cv.Optional(CONF_GROUP): cv.declare_id(lv_group_t), + cv.Optional(df.CONF_INITIAL_FOCUS): cv.use_id(lv_obj_t), cv.Optional(df.CONF_LONG_PRESS_TIME, default="400ms"): PRESS_TIME, cv.Optional(df.CONF_LONG_PRESS_REPEAT_TIME, default="100ms"): PRESS_TIME, } @@ -161,7 +170,7 @@ STYLE_REMAP = { # Complete object style schema STYLE_SCHEMA = cv.Schema({cv.Optional(k): v for k, v in STYLE_PROPS.items()}).extend( { - cv.Optional(df.CONF_STYLES): cv.ensure_list(cv.use_id(ty.lv_style_t)), + cv.Optional(df.CONF_STYLES): cv.ensure_list(cv.use_id(lv_style_t)), cv.Optional(df.CONF_SCROLLBAR_MODE): df.LvConstant( "LV_SCROLLBAR_MODE_", "OFF", "ON", "ACTIVE", "AUTO" ).one_of, @@ -193,12 +202,12 @@ def part_schema(widget_type: WidgetType): ) -def automation_schema(typ: ty.LvType): +def automation_schema(typ: LvType): if typ.has_on_value: events = df.LV_EVENT_TRIGGERS + (CONF_ON_VALUE,) else: events = df.LV_EVENT_TRIGGERS - if isinstance(typ, ty.LvType): + if isinstance(typ, LvType): template = Trigger.template(typ.get_arg_type()) else: template = Trigger.template() @@ -261,7 +270,7 @@ LAYOUT_SCHEMAS = {} ALIGN_TO_SCHEMA = { cv.Optional(df.CONF_ALIGN_TO): cv.Schema( { - cv.Required(CONF_ID): cv.use_id(ty.lv_obj_t), + cv.Required(CONF_ID): cv.use_id(lv_obj_t), cv.Required(df.CONF_ALIGN): df.ALIGN_ALIGNMENTS.one_of, cv.Optional(df.CONF_X, default=0): lvalid.pixels_or_percent, cv.Optional(df.CONF_Y, default=0): lvalid.pixels_or_percent, diff --git a/tests/components/lvgl/test.esp32-ard.yaml b/tests/components/lvgl/test.esp32-ard.yaml index 2d6a6871ba..51593e7967 100644 --- a/tests/components/lvgl/test.esp32-ard.yaml +++ b/tests/components/lvgl/test.esp32-ard.yaml @@ -46,6 +46,7 @@ binary_sensor: lvgl: encoders: group: switches + initial_focus: button_button enter_button: select_button sensor: left_button: up_button From c9979ad90c950198d3cc624e88d43975e5af497a Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Tue, 13 Aug 2024 21:46:23 +0200 Subject: [PATCH 1913/2101] [code-quality] fix order in esphome/const.py (#7267) --- esphome/const.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/esphome/const.py b/esphome/const.py index c5d0e8f838..55f1c23b40 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -7,22 +7,22 @@ VALID_SUBSTITUTIONS_CHARACTERS = ( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_" ) +PLATFORM_BK72XX = "bk72xx" PLATFORM_ESP32 = "esp32" PLATFORM_ESP8266 = "esp8266" -PLATFORM_RP2040 = "rp2040" PLATFORM_HOST = "host" -PLATFORM_BK72XX = "bk72xx" -PLATFORM_RTL87XX = "rtl87xx" PLATFORM_LIBRETINY_OLDSTYLE = "libretiny" +PLATFORM_RP2040 = "rp2040" +PLATFORM_RTL87XX = "rtl87xx" TARGET_PLATFORMS = [ + PLATFORM_BK72XX, PLATFORM_ESP32, PLATFORM_ESP8266, - PLATFORM_RP2040, PLATFORM_HOST, - PLATFORM_BK72XX, - PLATFORM_RTL87XX, PLATFORM_LIBRETINY_OLDSTYLE, + PLATFORM_RP2040, + PLATFORM_RTL87XX, ] SOURCE_FILE_EXTENSIONS = {".cpp", ".hpp", ".h", ".c", ".tcc", ".ino"} From b082a64d3248d4a272924f5887915109427b5d68 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Tue, 13 Aug 2024 21:48:27 +0200 Subject: [PATCH 1914/2101] [code-quality] fix clang-tidy network (#7266) --- esphome/components/network/__init__.py | 1 + esphome/components/network/ip_address.h | 3 +++ esphome/components/network/util.cpp | 3 ++- esphome/components/network/util.h | 4 +++- esphome/core/defines.h | 1 + 5 files changed, 10 insertions(+), 2 deletions(-) diff --git a/esphome/components/network/__init__.py b/esphome/components/network/__init__.py index f5ddbc0da7..96db322bde 100644 --- a/esphome/components/network/__init__.py +++ b/esphome/components/network/__init__.py @@ -32,6 +32,7 @@ CONFIG_SCHEMA = cv.Schema( async def to_code(config): + cg.add_define("USE_NETWORK") if (enable_ipv6 := config.get(CONF_ENABLE_IPV6, None)) is not None: cg.add_define("USE_NETWORK_IPV6", enable_ipv6) if enable_ipv6: diff --git a/esphome/components/network/ip_address.h b/esphome/components/network/ip_address.h index 30a426e458..941934cf0a 100644 --- a/esphome/components/network/ip_address.h +++ b/esphome/components/network/ip_address.h @@ -1,4 +1,6 @@ #pragma once +#include "esphome/core/defines.h" +#ifdef USE_NETWORK #include #include #include @@ -140,3 +142,4 @@ using IPAddresses = std::array; } // namespace network } // namespace esphome +#endif diff --git a/esphome/components/network/util.cpp b/esphome/components/network/util.cpp index 445485b644..ed519f738a 100644 --- a/esphome/components/network/util.cpp +++ b/esphome/components/network/util.cpp @@ -1,6 +1,6 @@ #include "util.h" #include "esphome/core/defines.h" - +#ifdef USE_NETWORK #ifdef USE_WIFI #include "esphome/components/wifi/wifi_component.h" #endif @@ -63,3 +63,4 @@ std::string get_use_address() { } // namespace network } // namespace esphome +#endif diff --git a/esphome/components/network/util.h b/esphome/components/network/util.h index 5377d44f2f..b518696e68 100644 --- a/esphome/components/network/util.h +++ b/esphome/components/network/util.h @@ -1,5 +1,6 @@ #pragma once - +#include "esphome/core/defines.h" +#ifdef USE_NETWORK #include #include "ip_address.h" @@ -16,3 +17,4 @@ IPAddresses get_ip_addresses(); } // namespace network } // namespace esphome +#endif diff --git a/esphome/core/defines.h b/esphome/core/defines.h index a711148ec8..a4d473b76e 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -51,6 +51,7 @@ #define USE_MDNS #define USE_MEDIA_PLAYER #define USE_MQTT +#define USE_NETWORK #define USE_NEXTION_TFT_UPLOAD #define USE_NUMBER #define USE_ONLINE_IMAGE_PNG_SUPPORT From 9663b7d67ccf2c2e188a709a512ffe0aaae45865 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Tue, 13 Aug 2024 21:53:42 +0200 Subject: [PATCH 1915/2101] [code-quality] fix clang-tidy core optional (#7265) --- esphome/core/optional.h | 1 - 1 file changed, 1 deletion(-) diff --git a/esphome/core/optional.h b/esphome/core/optional.h index 5b96781e63..770b77081e 100644 --- a/esphome/core/optional.h +++ b/esphome/core/optional.h @@ -104,7 +104,6 @@ template class optional { // NOLINT has_value_ = true; } - private: bool has_value_{false}; // NOLINT value_type value_; // NOLINT }; From 4bd7ba0d30dca6cb3c13cdd7a0cfab64253e9720 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Tue, 13 Aug 2024 21:54:37 +0200 Subject: [PATCH 1916/2101] [code-quality] Fix variable naming in base_light_effects (#7237) --- 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 f7829a3f44..9e02e889c9 100644 --- a/esphome/components/light/base_light_effects.h +++ b/esphome/components/light/base_light_effects.h @@ -25,7 +25,7 @@ class PulseLightEffect : public LightEffect { return; } auto call = this->state_->turn_on(); - float out = this->on_ ? this->max_brightness : this->min_brightness; + float out = this->on_ ? this->max_brightness_ : this->min_brightness_; call.set_brightness_if_supported(out); call.set_transition_length_if_supported(this->on_ ? this->transition_on_length_ : this->transition_off_length_); this->on_ = !this->on_; @@ -43,8 +43,8 @@ class PulseLightEffect : public LightEffect { void set_update_interval(uint32_t update_interval) { this->update_interval_ = update_interval; } void set_min_max_brightness(float min, float max) { - this->min_brightness = min; - this->max_brightness = max; + this->min_brightness_ = min; + this->max_brightness_ = max; } protected: @@ -53,8 +53,8 @@ class PulseLightEffect : public LightEffect { uint32_t transition_on_length_{}; uint32_t transition_off_length_{}; uint32_t update_interval_{}; - float min_brightness{0.0}; - float max_brightness{1.0}; + float min_brightness_{0.0}; + float max_brightness_{1.0}; }; /// Random effect. Sets random colors every 10 seconds and slowly transitions between them. From f81ce2c70743098796493ce703c7c388de10f783 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Tue, 13 Aug 2024 21:56:09 +0200 Subject: [PATCH 1917/2101] [code-quality] fix clang-tidy mqtt (#7253) --- esphome/components/mqtt/mqtt_backend.h | 4 +++- esphome/components/mqtt/mqtt_backend_esp32.cpp | 5 ++++- esphome/components/mqtt/mqtt_backend_esp32.h | 4 +++- esphome/components/mqtt/mqtt_backend_esp8266.h | 4 +++- esphome/components/mqtt/mqtt_backend_libretiny.h | 4 +++- 5 files changed, 16 insertions(+), 5 deletions(-) diff --git a/esphome/components/mqtt/mqtt_backend.h b/esphome/components/mqtt/mqtt_backend.h index d23cda578d..3962c40a42 100644 --- a/esphome/components/mqtt/mqtt_backend.h +++ b/esphome/components/mqtt/mqtt_backend.h @@ -1,5 +1,6 @@ #pragma once - +#include "esphome/core/defines.h" +#ifdef USE_MQTT #include #include #include "esphome/components/network/ip_address.h" @@ -67,3 +68,4 @@ class MQTTBackend { } // namespace mqtt } // namespace esphome +#endif diff --git a/esphome/components/mqtt/mqtt_backend_esp32.cpp b/esphome/components/mqtt/mqtt_backend_esp32.cpp index 9c2e487ae7..ed500c6d44 100644 --- a/esphome/components/mqtt/mqtt_backend_esp32.cpp +++ b/esphome/components/mqtt/mqtt_backend_esp32.cpp @@ -1,7 +1,9 @@ +#include "mqtt_backend_esp32.h" + +#ifdef USE_MQTT #ifdef USE_ESP32 #include -#include "mqtt_backend_esp32.h" #include "esphome/core/log.h" #include "esphome/core/helpers.h" @@ -189,3 +191,4 @@ void MQTTBackendESP32::mqtt_event_handler(void *handler_args, esp_event_base_t b } // namespace mqtt } // namespace esphome #endif // USE_ESP32 +#endif diff --git a/esphome/components/mqtt/mqtt_backend_esp32.h b/esphome/components/mqtt/mqtt_backend_esp32.h index b1f672da10..9054702115 100644 --- a/esphome/components/mqtt/mqtt_backend_esp32.h +++ b/esphome/components/mqtt/mqtt_backend_esp32.h @@ -1,5 +1,7 @@ #pragma once +#include "mqtt_backend.h" +#ifdef USE_MQTT #ifdef USE_ESP32 #include @@ -7,7 +9,6 @@ #include #include "esphome/components/network/ip_address.h" #include "esphome/core/helpers.h" -#include "mqtt_backend.h" namespace esphome { namespace mqtt { @@ -174,3 +175,4 @@ class MQTTBackendESP32 final : public MQTTBackend { } // namespace esphome #endif +#endif diff --git a/esphome/components/mqtt/mqtt_backend_esp8266.h b/esphome/components/mqtt/mqtt_backend_esp8266.h index 06d4993bdf..a979634bf4 100644 --- a/esphome/components/mqtt/mqtt_backend_esp8266.h +++ b/esphome/components/mqtt/mqtt_backend_esp8266.h @@ -1,8 +1,9 @@ #pragma once +#include "mqtt_backend.h" +#ifdef USE_MQTT #ifdef USE_ESP8266 -#include "mqtt_backend.h" #include namespace esphome { @@ -70,3 +71,4 @@ class MQTTBackendESP8266 final : public MQTTBackend { } // namespace esphome #endif // defined(USE_ESP8266) +#endif diff --git a/esphome/components/mqtt/mqtt_backend_libretiny.h b/esphome/components/mqtt/mqtt_backend_libretiny.h index ac4d4298fc..2578ae9941 100644 --- a/esphome/components/mqtt/mqtt_backend_libretiny.h +++ b/esphome/components/mqtt/mqtt_backend_libretiny.h @@ -1,8 +1,9 @@ #pragma once +#include "mqtt_backend.h" +#ifdef USE_MQTT #ifdef USE_LIBRETINY -#include "mqtt_backend.h" #include namespace esphome { @@ -70,3 +71,4 @@ class MQTTBackendLibreTiny final : public MQTTBackend { } // namespace esphome #endif // defined(USE_LIBRETINY) +#endif From 2e58297a16e2ea0e94235b5268fa98e19744f954 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Tue, 13 Aug 2024 21:58:30 +0200 Subject: [PATCH 1918/2101] [code-quality] fix clang-tidy wifi related (#7254) --- esphome/components/wifi/wifi_component.cpp | 2 ++ esphome/components/wifi/wifi_component.h | 4 +++- esphome/components/wifi/wifi_component_esp32_arduino.cpp | 2 ++ 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/components/wifi_info/wifi_info_text_sensor.cpp | 2 ++ esphome/components/wifi_info/wifi_info_text_sensor.h | 2 ++ esphome/components/wifi_signal/wifi_signal_sensor.cpp | 2 ++ esphome/components/wifi_signal/wifi_signal_sensor.h | 3 ++- 11 files changed, 23 insertions(+), 2 deletions(-) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 8c40f87879..583a27466a 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -1,4 +1,5 @@ #include "wifi_component.h" +#ifdef USE_WIFI #include #include @@ -856,3 +857,4 @@ WiFiComponent *global_wifi_component; // NOLINT(cppcoreguidelines-avoid-non-con } // namespace wifi } // namespace esphome +#endif diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index d79cde0b18..dde0d1d5a5 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -1,9 +1,10 @@ #pragma once +#include "esphome/core/defines.h" +#ifdef USE_WIFI #include "esphome/components/network/ip_address.h" #include "esphome/core/automation.h" #include "esphome/core/component.h" -#include "esphome/core/defines.h" #include "esphome/core/helpers.h" #include @@ -442,3 +443,4 @@ template class WiFiDisableAction : public Action { } // namespace wifi } // namespace esphome +#endif diff --git a/esphome/components/wifi/wifi_component_esp32_arduino.cpp b/esphome/components/wifi/wifi_component_esp32_arduino.cpp index 71548b7a3e..b8724838c8 100644 --- a/esphome/components/wifi/wifi_component_esp32_arduino.cpp +++ b/esphome/components/wifi/wifi_component_esp32_arduino.cpp @@ -1,5 +1,6 @@ #include "wifi_component.h" +#ifdef USE_WIFI #ifdef USE_ESP32_FRAMEWORK_ARDUINO #include @@ -802,3 +803,4 @@ network::IPAddress WiFiComponent::wifi_dns_ip_(int num) { return network::IPAddr } // namespace esphome #endif // USE_ESP32_FRAMEWORK_ARDUINO +#endif diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index 997457e2d2..92f80c1e52 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -1,6 +1,7 @@ #include "wifi_component.h" #include "esphome/core/defines.h" +#ifdef USE_WIFI #ifdef USE_ESP8266 #include @@ -834,3 +835,4 @@ void WiFiComponent::wifi_loop_() {} } // namespace esphome #endif +#endif diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index a8d67ed44d..6008acb95d 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -1,5 +1,6 @@ #include "wifi_component.h" +#ifdef USE_WIFI #ifdef USE_ESP_IDF #include @@ -1010,3 +1011,4 @@ network::IPAddress WiFiComponent::wifi_dns_ip_(int num) { } // namespace esphome #endif // USE_ESP_IDF +#endif diff --git a/esphome/components/wifi/wifi_component_libretiny.cpp b/esphome/components/wifi/wifi_component_libretiny.cpp index f6b0fb2699..19ade84a88 100644 --- a/esphome/components/wifi/wifi_component_libretiny.cpp +++ b/esphome/components/wifi/wifi_component_libretiny.cpp @@ -1,5 +1,6 @@ #include "wifi_component.h" +#ifdef USE_WIFI #ifdef USE_LIBRETINY #include @@ -468,3 +469,4 @@ void WiFiComponent::wifi_loop_() {} } // namespace esphome #endif // USE_LIBRETINY +#endif diff --git a/esphome/components/wifi/wifi_component_pico_w.cpp b/esphome/components/wifi/wifi_component_pico_w.cpp index 4afcf2d78b..bac986d899 100644 --- a/esphome/components/wifi/wifi_component_pico_w.cpp +++ b/esphome/components/wifi/wifi_component_pico_w.cpp @@ -1,6 +1,7 @@ #include "wifi_component.h" +#ifdef USE_WIFI #ifdef USE_RP2040 #include "lwip/dns.h" @@ -218,3 +219,4 @@ void WiFiComponent::wifi_pre_setup_() {} } // namespace esphome #endif +#endif diff --git a/esphome/components/wifi_info/wifi_info_text_sensor.cpp b/esphome/components/wifi_info/wifi_info_text_sensor.cpp index eeb4985398..150c7229f8 100644 --- a/esphome/components/wifi_info/wifi_info_text_sensor.cpp +++ b/esphome/components/wifi_info/wifi_info_text_sensor.cpp @@ -1,4 +1,5 @@ #include "wifi_info_text_sensor.h" +#ifdef USE_WIFI #include "esphome/core/log.h" namespace esphome { @@ -15,3 +16,4 @@ void DNSAddressWifiInfo::dump_config() { LOG_TEXT_SENSOR("", "WifiInfo DNS Addre } // namespace wifi_info } // namespace esphome +#endif diff --git a/esphome/components/wifi_info/wifi_info_text_sensor.h b/esphome/components/wifi_info/wifi_info_text_sensor.h index 0f31a57cc5..0aa44a0894 100644 --- a/esphome/components/wifi_info/wifi_info_text_sensor.h +++ b/esphome/components/wifi_info/wifi_info_text_sensor.h @@ -3,6 +3,7 @@ #include "esphome/core/component.h" #include "esphome/components/text_sensor/text_sensor.h" #include "esphome/components/wifi/wifi_component.h" +#ifdef USE_WIFI #include namespace esphome { @@ -131,3 +132,4 @@ class MacAddressWifiInfo : public Component, public text_sensor::TextSensor { } // namespace wifi_info } // namespace esphome +#endif diff --git a/esphome/components/wifi_signal/wifi_signal_sensor.cpp b/esphome/components/wifi_signal/wifi_signal_sensor.cpp index ba22138e2a..4347295421 100644 --- a/esphome/components/wifi_signal/wifi_signal_sensor.cpp +++ b/esphome/components/wifi_signal/wifi_signal_sensor.cpp @@ -1,4 +1,5 @@ #include "wifi_signal_sensor.h" +#ifdef USE_WIFI #include "esphome/core/log.h" namespace esphome { @@ -10,3 +11,4 @@ void WiFiSignalSensor::dump_config() { LOG_SENSOR("", "WiFi Signal", this); } } // namespace wifi_signal } // namespace esphome +#endif diff --git a/esphome/components/wifi_signal/wifi_signal_sensor.h b/esphome/components/wifi_signal/wifi_signal_sensor.h index f797aaa590..fbe03a6404 100644 --- a/esphome/components/wifi_signal/wifi_signal_sensor.h +++ b/esphome/components/wifi_signal/wifi_signal_sensor.h @@ -4,7 +4,7 @@ #include "esphome/core/helpers.h" #include "esphome/components/sensor/sensor.h" #include "esphome/components/wifi/wifi_component.h" - +#ifdef USE_WIFI namespace esphome { namespace wifi_signal { @@ -19,3 +19,4 @@ class WiFiSignalSensor : public sensor::Sensor, public PollingComponent { } // namespace wifi_signal } // namespace esphome +#endif From 9ec61cbff3ec79a7fb3d5fe7720ced35dd69989f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Aug 2024 08:12:56 +1200 Subject: [PATCH 1919/2101] Bump docker/build-push-action from 6.6.1 to 6.7.0 in /.github/actions/build-image (#7269) 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 f9c44cfb63..56be20bd87 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -46,7 +46,7 @@ runs: - name: Build and push to ghcr by digest id: build-ghcr - uses: docker/build-push-action@v6.6.1 + uses: docker/build-push-action@v6.7.0 with: context: . file: ./docker/Dockerfile @@ -69,7 +69,7 @@ runs: - name: Build and push to dockerhub by digest id: build-dockerhub - uses: docker/build-push-action@v6.6.1 + uses: docker/build-push-action@v6.7.0 with: context: . file: ./docker/Dockerfile From 0c567adf639585474881d8ee8aff8e316b501a80 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 14 Aug 2024 08:13:09 +1200 Subject: [PATCH 1920/2101] [CI] Dont run full CI on ``build-image`` action changes (#7270) --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a8e93248bb..126a541b3d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,6 +9,7 @@ on: paths: - "**" - "!.github/workflows/*.yml" + - "!.github/actions/build-image/*" - ".github/workflows/ci.yml" - "!.yamllint" - "!.github/dependabot.yml" From 68c56b3e03bffb47c4f4481ff534d8d3ac3bc38e Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Wed, 14 Aug 2024 07:29:31 +1000 Subject: [PATCH 1921/2101] Implement ByteBuffer (#6878) --- esphome/core/bytebuffer.cpp | 134 ++++++++++++++++++++++++++++++++++++ esphome/core/bytebuffer.h | 96 ++++++++++++++++++++++++++ 2 files changed, 230 insertions(+) create mode 100644 esphome/core/bytebuffer.cpp create mode 100644 esphome/core/bytebuffer.h diff --git a/esphome/core/bytebuffer.cpp b/esphome/core/bytebuffer.cpp new file mode 100644 index 0000000000..fb2ade3166 --- /dev/null +++ b/esphome/core/bytebuffer.cpp @@ -0,0 +1,134 @@ +#include "bytebuffer.h" +#include + +namespace esphome { + +ByteBuffer ByteBuffer::create(size_t capacity) { + std::vector data(capacity); + return {data}; +} + +ByteBuffer ByteBuffer::wrap(uint8_t *ptr, size_t len) { + std::vector data(ptr, ptr + len); + return {data}; +} + +ByteBuffer ByteBuffer::wrap(std::vector data) { return {std::move(data)}; } + +void ByteBuffer::set_limit(size_t limit) { + assert(limit <= this->get_capacity()); + this->limit_ = limit; +} +void ByteBuffer::set_position(size_t position) { + assert(position <= this->get_limit()); + this->position_ = position; +} +void ByteBuffer::clear() { + this->limit_ = this->get_capacity(); + this->position_ = 0; +} +uint16_t ByteBuffer::get_uint16() { + assert(this->get_remaining() >= 2); + uint16_t value; + if (endianness_ == LITTLE) { + value = this->data_[this->position_++]; + value |= this->data_[this->position_++] << 8; + } else { + value = this->data_[this->position_++] << 8; + value |= this->data_[this->position_++]; + } + return value; +} + +uint32_t ByteBuffer::get_uint32() { + assert(this->get_remaining() >= 4); + uint32_t value; + if (endianness_ == LITTLE) { + value = this->data_[this->position_++]; + value |= this->data_[this->position_++] << 8; + value |= this->data_[this->position_++] << 16; + value |= this->data_[this->position_++] << 24; + } else { + value = this->data_[this->position_++] << 24; + value |= this->data_[this->position_++] << 16; + value |= this->data_[this->position_++] << 8; + value |= this->data_[this->position_++]; + } + return value; +} +uint32_t ByteBuffer::get_uint24() { + assert(this->get_remaining() >= 3); + uint32_t value; + if (endianness_ == LITTLE) { + value = this->data_[this->position_++]; + value |= this->data_[this->position_++] << 8; + value |= this->data_[this->position_++] << 16; + } else { + value = this->data_[this->position_++] << 16; + value |= this->data_[this->position_++] << 8; + value |= this->data_[this->position_++]; + } + return value; +} +uint32_t ByteBuffer::get_int24() { + auto value = this->get_uint24(); + uint32_t mask = (~(uint32_t) 0) << 23; + if ((value & mask) != 0) + value |= mask; + return value; +} +uint8_t ByteBuffer::get_uint8() { + assert(this->get_remaining() >= 1); + return this->data_[this->position_++]; +} +float ByteBuffer::get_float() { + auto value = this->get_uint32(); + return *(float *) &value; +} +void ByteBuffer::put_uint8(uint8_t value) { + assert(this->get_remaining() >= 1); + this->data_[this->position_++] = value; +} + +void ByteBuffer::put_uint16(uint16_t value) { + assert(this->get_remaining() >= 2); + if (this->endianness_ == LITTLE) { + this->data_[this->position_++] = (uint8_t) value; + this->data_[this->position_++] = (uint8_t) (value >> 8); + } else { + this->data_[this->position_++] = (uint8_t) (value >> 8); + this->data_[this->position_++] = (uint8_t) value; + } +} +void ByteBuffer::put_uint24(uint32_t value) { + assert(this->get_remaining() >= 3); + if (this->endianness_ == LITTLE) { + this->data_[this->position_++] = (uint8_t) value; + this->data_[this->position_++] = (uint8_t) (value >> 8); + this->data_[this->position_++] = (uint8_t) (value >> 16); + } else { + this->data_[this->position_++] = (uint8_t) (value >> 16); + this->data_[this->position_++] = (uint8_t) (value >> 8); + this->data_[this->position_++] = (uint8_t) value; + } +} +void ByteBuffer::put_uint32(uint32_t value) { + assert(this->get_remaining() >= 4); + if (this->endianness_ == LITTLE) { + this->data_[this->position_++] = (uint8_t) value; + this->data_[this->position_++] = (uint8_t) (value >> 8); + this->data_[this->position_++] = (uint8_t) (value >> 16); + this->data_[this->position_++] = (uint8_t) (value >> 24); + } else { + this->data_[this->position_++] = (uint8_t) (value >> 24); + this->data_[this->position_++] = (uint8_t) (value >> 16); + this->data_[this->position_++] = (uint8_t) (value >> 8); + this->data_[this->position_++] = (uint8_t) value; + } +} +void ByteBuffer::put_float(float value) { this->put_uint32(*(uint32_t *) &value); } +void ByteBuffer::flip() { + this->limit_ = this->position_; + this->position_ = 0; +} +} // namespace esphome diff --git a/esphome/core/bytebuffer.h b/esphome/core/bytebuffer.h new file mode 100644 index 0000000000..f242e5e333 --- /dev/null +++ b/esphome/core/bytebuffer.h @@ -0,0 +1,96 @@ +#pragma once + +#include +#include +#include +#include + +namespace esphome { + +enum Endian { LITTLE, BIG }; + +/** + * A class modelled on the Java ByteBuffer class. It wraps a vector of bytes and permits putting and getting + * items of various sizes, with an automatically incremented position. + * + * There are three variables maintained pointing into the buffer: + * + * 0 <= position <= limit <= capacity + * + * capacity: the maximum amount of data that can be stored + * limit: the limit of the data currently available to get or put + * position: the current insert or extract position + * + * In addition a mark can be set to the current position with mark(). A subsequent call to reset() will restore + * the position to the mark. + * + * The buffer can be marked to be little-endian (default) or big-endian. All subsequent operations will use that order. + * + */ +class ByteBuffer { + public: + /** + * Create a new Bytebuffer with the given capacity + */ + static ByteBuffer create(size_t capacity); + /** + * Wrap an existing vector in a Bytebufffer + */ + static ByteBuffer wrap(std::vector data); + /** + * Wrap an existing array in a Bytebufffer + */ + static ByteBuffer wrap(uint8_t *ptr, size_t len); + + // Get one byte from the buffer, increment position by 1 + uint8_t get_uint8(); + // Get a 16 bit unsigned value, increment by 2 + uint16_t get_uint16(); + // Get a 24 bit unsigned value, increment by 3 + uint32_t get_uint24(); + // Get a 32 bit unsigned value, increment by 4 + uint32_t get_uint32(); + // signed versions of the get functions + uint8_t get_int8() { return (int8_t) this->get_uint8(); }; + int16_t get_int16() { return (int16_t) this->get_uint16(); } + uint32_t get_int24(); + int32_t get_int32() { return (int32_t) this->get_uint32(); } + // Get a float value, increment by 4 + float get_float(); + + // put values into the buffer, increment the position accordingly + void put_uint8(uint8_t value); + void put_uint16(uint16_t value); + void put_uint24(uint32_t value); + void put_uint32(uint32_t value); + void put_float(float value); + + inline size_t get_capacity() const { return this->data_.size(); } + inline size_t get_position() const { return this->position_; } + inline size_t get_limit() const { return this->limit_; } + inline size_t get_remaining() const { return this->get_limit() - this->get_position(); } + inline Endian get_endianness() const { return this->endianness_; } + inline void mark() { this->mark_ = this->position_; } + inline void big_endian() { this->endianness_ = BIG; } + inline void little_endian() { this->endianness_ = LITTLE; } + void set_limit(size_t limit); + void set_position(size_t position); + // set position to 0, limit to capacity. + void clear(); + // set limit to current position, postition to zero. Used when swapping from write to read operations. + void flip(); + // retrieve a pointer to the underlying data. + uint8_t *array() { return this->data_.data(); }; + void rewind() { this->position_ = 0; } + void reset() { this->position_ = this->mark_; } + + protected: + ByteBuffer(std::vector data) : data_(std::move(data)) { this->limit_ = this->get_capacity(); } + std::vector data_; + Endian endianness_{LITTLE}; + size_t position_{0}; + size_t mark_{0}; + size_t limit_{0}; +}; + +} // namespace esphome From c5b1a8eb81c4187c3c0f7ca4da40232425845113 Mon Sep 17 00:00:00 2001 From: PaoloTK <60204407+PaoloTK@users.noreply.github.com> Date: Tue, 13 Aug 2024 23:29:55 +0200 Subject: [PATCH 1922/2101] Add min and max brightness parameters for Light dim_relative Action (#6971) --- esphome/components/light/automation.h | 17 ++++++++++++++- esphome/components/light/automation.py | 21 +++++++++++++++++++ esphome/components/light/types.py | 7 +++++++ esphome/const.py | 2 ++ tests/components/light/test.esp32-ard.yaml | 2 ++ tests/components/light/test.esp32-c3-ard.yaml | 2 ++ tests/components/light/test.esp32-c3-idf.yaml | 2 ++ tests/components/light/test.esp32-idf.yaml | 2 ++ tests/components/light/test.esp8266-ard.yaml | 2 ++ tests/components/light/test.rp2040-ard.yaml | 2 ++ 10 files changed, 58 insertions(+), 1 deletion(-) diff --git a/esphome/components/light/automation.h b/esphome/components/light/automation.h index b63fc93dc5..6e055741da 100644 --- a/esphome/components/light/automation.h +++ b/esphome/components/light/automation.h @@ -7,6 +7,8 @@ namespace esphome { namespace light { +enum class LimitMode { CLAMP, DO_NOTHING }; + template class ToggleAction : public Action { public: explicit ToggleAction(LightState *state) : state_(state) {} @@ -77,7 +79,10 @@ template class DimRelativeAction : public Action { float rel = this->relative_brightness_.value(x...); float cur; this->parent_->remote_values.as_brightness(&cur); - float new_brightness = clamp(cur + rel, 0.0f, 1.0f); + if ((limit_mode_ == LimitMode::DO_NOTHING) && ((cur < min_brightness_) || (cur > max_brightness_))) { + return; + } + float new_brightness = clamp(cur + rel, min_brightness_, max_brightness_); call.set_state(new_brightness != 0.0f); call.set_brightness(new_brightness); @@ -85,8 +90,18 @@ template class DimRelativeAction : public Action { call.perform(); } + void set_min_max_brightness(float min, float max) { + this->min_brightness_ = min; + this->max_brightness_ = max; + } + + void set_limit_mode(LimitMode limit_mode) { this->limit_mode_ = limit_mode; } + protected: LightState *parent_; + float min_brightness_{0.0}; + float max_brightness_{1.0}; + LimitMode limit_mode_{LimitMode::CLAMP}; }; template class LightIsOnCondition : public Condition { diff --git a/esphome/components/light/automation.py b/esphome/components/light/automation.py index cfba273565..ec0375f54a 100644 --- a/esphome/components/light/automation.py +++ b/esphome/components/light/automation.py @@ -19,10 +19,15 @@ from esphome.const import ( CONF_WARM_WHITE, CONF_RANGE_FROM, CONF_RANGE_TO, + CONF_BRIGHTNESS_LIMITS, + CONF_LIMIT_MODE, + CONF_MIN_BRIGHTNESS, + CONF_MAX_BRIGHTNESS, ) from .types import ( ColorMode, COLOR_MODES, + LIMIT_MODES, DimRelativeAction, ToggleAction, LightState, @@ -167,6 +172,15 @@ LIGHT_DIM_RELATIVE_ACTION_SCHEMA = cv.Schema( cv.Optional(CONF_TRANSITION_LENGTH): cv.templatable( cv.positive_time_period_milliseconds ), + cv.Optional(CONF_BRIGHTNESS_LIMITS): cv.Schema( + { + cv.Optional(CONF_MIN_BRIGHTNESS, default="0%"): cv.percentage, + cv.Optional(CONF_MAX_BRIGHTNESS, default="100%"): cv.percentage, + cv.Optional(CONF_LIMIT_MODE, default="CLAMP"): cv.enum( + LIMIT_MODES, upper=True, space="_" + ), + } + ), } ) @@ -182,6 +196,13 @@ async def light_dim_relative_to_code(config, action_id, template_arg, args): if CONF_TRANSITION_LENGTH in config: templ = await cg.templatable(config[CONF_TRANSITION_LENGTH], args, cg.uint32) cg.add(var.set_transition_length(templ)) + if conf := config.get(CONF_BRIGHTNESS_LIMITS): + cg.add( + var.set_min_max_brightness( + conf[CONF_MIN_BRIGHTNESS], conf[CONF_MAX_BRIGHTNESS] + ) + ) + cg.add(var.set_limit_mode(conf[CONF_LIMIT_MODE])) return var diff --git a/esphome/components/light/types.py b/esphome/components/light/types.py index a453debd94..64483bcc9c 100644 --- a/esphome/components/light/types.py +++ b/esphome/components/light/types.py @@ -26,6 +26,13 @@ COLOR_MODES = { "RGB_COLD_WARM_WHITE": ColorMode.RGB_COLD_WARM_WHITE, } +# Limit modes +LimitMode = light_ns.enum("LimitMode", is_class=True) +LIMIT_MODES = { + "CLAMP": LimitMode.CLAMP, + "DO_NOTHING": LimitMode.DO_NOTHING, +} + # Actions ToggleAction = light_ns.class_("ToggleAction", automation.Action) LightControlAction = light_ns.class_("LightControlAction", automation.Action) diff --git a/esphome/const.py b/esphome/const.py index 55f1c23b40..37f20796b5 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -95,6 +95,7 @@ CONF_BOARD_FLASH_MODE = "board_flash_mode" CONF_BORDER = "border" CONF_BRANCH = "branch" CONF_BRIGHTNESS = "brightness" +CONF_BRIGHTNESS_LIMITS = "brightness_limits" CONF_BROKER = "broker" CONF_BSSID = "bssid" CONF_BUFFER_SIZE = "buffer_size" @@ -429,6 +430,7 @@ CONF_LIGHT = "light" CONF_LIGHT_ID = "light_id" CONF_LIGHTNING_ENERGY = "lightning_energy" CONF_LIGHTNING_THRESHOLD = "lightning_threshold" +CONF_LIMIT_MODE = "limit_mode" CONF_LINE_THICKNESS = "line_thickness" CONF_LINE_TYPE = "line_type" CONF_LOADED_INTEGRATIONS = "loaded_integrations" diff --git a/tests/components/light/test.esp32-ard.yaml b/tests/components/light/test.esp32-ard.yaml index 7e5718d8d4..1d0b4cd8f0 100644 --- a/tests/components/light/test.esp32-ard.yaml +++ b/tests/components/light/test.esp32-ard.yaml @@ -15,6 +15,8 @@ esphome: - light.dim_relative: id: test_monochromatic_light relative_brightness: 5% + brightness_limits: + max_brightness: 90% output: - platform: gpio diff --git a/tests/components/light/test.esp32-c3-ard.yaml b/tests/components/light/test.esp32-c3-ard.yaml index 8e1709838a..79171805a6 100644 --- a/tests/components/light/test.esp32-c3-ard.yaml +++ b/tests/components/light/test.esp32-c3-ard.yaml @@ -15,6 +15,8 @@ esphome: - light.dim_relative: id: test_monochromatic_light relative_brightness: 5% + brightness_limits: + max_brightness: 90% output: - platform: gpio diff --git a/tests/components/light/test.esp32-c3-idf.yaml b/tests/components/light/test.esp32-c3-idf.yaml index 8e1709838a..79171805a6 100644 --- a/tests/components/light/test.esp32-c3-idf.yaml +++ b/tests/components/light/test.esp32-c3-idf.yaml @@ -15,6 +15,8 @@ esphome: - light.dim_relative: id: test_monochromatic_light relative_brightness: 5% + brightness_limits: + max_brightness: 90% output: - platform: gpio diff --git a/tests/components/light/test.esp32-idf.yaml b/tests/components/light/test.esp32-idf.yaml index 7e5718d8d4..1d0b4cd8f0 100644 --- a/tests/components/light/test.esp32-idf.yaml +++ b/tests/components/light/test.esp32-idf.yaml @@ -15,6 +15,8 @@ esphome: - light.dim_relative: id: test_monochromatic_light relative_brightness: 5% + brightness_limits: + max_brightness: 90% output: - platform: gpio diff --git a/tests/components/light/test.esp8266-ard.yaml b/tests/components/light/test.esp8266-ard.yaml index 4611fb374a..555e1a1b67 100644 --- a/tests/components/light/test.esp8266-ard.yaml +++ b/tests/components/light/test.esp8266-ard.yaml @@ -15,6 +15,8 @@ esphome: - light.dim_relative: id: test_monochromatic_light relative_brightness: 5% + brightness_limits: + max_brightness: 90% output: - platform: gpio diff --git a/tests/components/light/test.rp2040-ard.yaml b/tests/components/light/test.rp2040-ard.yaml index 0215a17e71..a509bc85c9 100644 --- a/tests/components/light/test.rp2040-ard.yaml +++ b/tests/components/light/test.rp2040-ard.yaml @@ -15,6 +15,8 @@ esphome: - light.dim_relative: id: test_monochromatic_light relative_brightness: 5% + brightness_limits: + max_brightness: 90% output: - platform: gpio From 1d25db491c26b7400a8483ab2199fa8d05badfbc Mon Sep 17 00:00:00 2001 From: Markus <974709+Links2004@users.noreply.github.com> Date: Wed, 14 Aug 2024 04:03:12 +0200 Subject: [PATCH 1923/2101] [homeassistant] Native switch entity import and control (#7018) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- CODEOWNERS | 1 + .../homeassistant/switch/__init__.py | 30 ++++++++++ .../switch/homeassistant_switch.cpp | 59 +++++++++++++++++++ .../switch/homeassistant_switch.h | 22 +++++++ tests/components/homeassistant/common.yaml | 5 ++ 5 files changed, 117 insertions(+) create mode 100644 esphome/components/homeassistant/switch/__init__.py create mode 100644 esphome/components/homeassistant/switch/homeassistant_switch.cpp create mode 100644 esphome/components/homeassistant/switch/homeassistant_switch.h diff --git a/CODEOWNERS b/CODEOWNERS index 663a942cb4..0c36cda527 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -169,6 +169,7 @@ esphome/components/heatpumpir/* @rob-deutsch esphome/components/hitachi_ac424/* @sourabhjaiswal esphome/components/hm3301/* @freekode esphome/components/homeassistant/* @OttoWinter @esphome/core +esphome/components/homeassistant/switch/* @Links2004 esphome/components/honeywell_hih_i2c/* @Benichou34 esphome/components/honeywellabp/* @RubyBailey esphome/components/honeywellabp2_i2c/* @jpfaff diff --git a/esphome/components/homeassistant/switch/__init__.py b/esphome/components/homeassistant/switch/__init__.py new file mode 100644 index 0000000000..3d7c80682a --- /dev/null +++ b/esphome/components/homeassistant/switch/__init__.py @@ -0,0 +1,30 @@ +import esphome.codegen as cg +from esphome.components import switch +import esphome.config_validation as cv +from esphome.const import CONF_ID + +from .. import ( + HOME_ASSISTANT_IMPORT_CONTROL_SCHEMA, + homeassistant_ns, + setup_home_assistant_entity, +) + +CODEOWNERS = ["@Links2004"] +DEPENDENCIES = ["api"] + +HomeassistantSwitch = homeassistant_ns.class_( + "HomeassistantSwitch", switch.Switch, cg.Component +) + +CONFIG_SCHEMA = ( + switch.switch_schema(HomeassistantSwitch) + .extend(cv.COMPONENT_SCHEMA) + .extend(HOME_ASSISTANT_IMPORT_CONTROL_SCHEMA) +) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, config) + await switch.register_switch(var, config) + setup_home_assistant_entity(var, config) diff --git a/esphome/components/homeassistant/switch/homeassistant_switch.cpp b/esphome/components/homeassistant/switch/homeassistant_switch.cpp new file mode 100644 index 0000000000..05ef46e30e --- /dev/null +++ b/esphome/components/homeassistant/switch/homeassistant_switch.cpp @@ -0,0 +1,59 @@ +#include "homeassistant_switch.h" +#include "esphome/components/api/api_server.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace homeassistant { + +static const char *const TAG = "homeassistant.switch"; + +using namespace esphome::switch_; + +void HomeassistantSwitch::setup() { + api::global_api_server->subscribe_home_assistant_state(this->entity_id_, nullopt, [this](const std::string &state) { + auto val = parse_on_off(state.c_str()); + switch (val) { + case PARSE_NONE: + case PARSE_TOGGLE: + ESP_LOGW(TAG, "Can't convert '%s' to binary state!", state.c_str()); + break; + case PARSE_ON: + case PARSE_OFF: + bool new_state = val == PARSE_ON; + ESP_LOGD(TAG, "'%s': Got state %s", this->entity_id_.c_str(), ONOFF(new_state)); + this->publish_state(new_state); + break; + } + }); +} + +void HomeassistantSwitch::dump_config() { + LOG_SWITCH("", "Homeassistant Switch", this); + ESP_LOGCONFIG(TAG, " Entity ID: '%s'", this->entity_id_.c_str()); +} + +float HomeassistantSwitch::get_setup_priority() const { return setup_priority::AFTER_CONNECTION; } + +void HomeassistantSwitch::write_state(bool state) { + if (!api::global_api_server->is_connected()) { + ESP_LOGE(TAG, "No clients connected to API server"); + return; + } + + api::HomeassistantServiceResponse resp; + if (state) { + resp.service = "switch.turn_on"; + } else { + resp.service = "switch.turn_off"; + } + + api::HomeassistantServiceMap entity_id_kv; + entity_id_kv.key = "entity_id"; + entity_id_kv.value = this->entity_id_; + resp.data.push_back(entity_id_kv); + + api::global_api_server->send_homeassistant_service_call(resp); +} + +} // namespace homeassistant +} // namespace esphome diff --git a/esphome/components/homeassistant/switch/homeassistant_switch.h b/esphome/components/homeassistant/switch/homeassistant_switch.h new file mode 100644 index 0000000000..a4da257960 --- /dev/null +++ b/esphome/components/homeassistant/switch/homeassistant_switch.h @@ -0,0 +1,22 @@ +#pragma once + +#include "esphome/components/switch/switch.h" +#include "esphome/core/component.h" + +namespace esphome { +namespace homeassistant { + +class HomeassistantSwitch : public switch_::Switch, public Component { + public: + void set_entity_id(const std::string &entity_id) { this->entity_id_ = entity_id; } + void setup() override; + void dump_config() override; + float get_setup_priority() const override; + + protected: + void write_state(bool state) override; + std::string entity_id_; +}; + +} // namespace homeassistant +} // namespace esphome diff --git a/tests/components/homeassistant/common.yaml b/tests/components/homeassistant/common.yaml index 07a6e8090c..2b2805d06e 100644 --- a/tests/components/homeassistant/common.yaml +++ b/tests/components/homeassistant/common.yaml @@ -32,6 +32,11 @@ wifi: api: +switch: + - platform: homeassistant + entity_id: switch.my_cool_switch + id: my_cool_switch + binary_sensor: - platform: homeassistant entity_id: binary_sensor.hello_world From a5fdcb31fc56d928aa7a3b340829970f6ce0bbc0 Mon Sep 17 00:00:00 2001 From: Landon Rohatensky Date: Tue, 13 Aug 2024 19:04:12 -0700 Subject: [PATCH 1924/2101] [homeassistant] Native number entity import and control (#6455) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- CODEOWNERS | 1 + .../homeassistant/number/__init__.py | 33 ++++++ .../number/homeassistant_number.cpp | 100 ++++++++++++++++++ .../number/homeassistant_number.h | 31 ++++++ tests/components/homeassistant/common.yaml | 5 + 5 files changed, 170 insertions(+) create mode 100644 esphome/components/homeassistant/number/__init__.py create mode 100644 esphome/components/homeassistant/number/homeassistant_number.cpp create mode 100644 esphome/components/homeassistant/number/homeassistant_number.h diff --git a/CODEOWNERS b/CODEOWNERS index 0c36cda527..3ea9c75ac2 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -169,6 +169,7 @@ esphome/components/heatpumpir/* @rob-deutsch esphome/components/hitachi_ac424/* @sourabhjaiswal esphome/components/hm3301/* @freekode esphome/components/homeassistant/* @OttoWinter @esphome/core +esphome/components/homeassistant/number/* @landonr esphome/components/homeassistant/switch/* @Links2004 esphome/components/honeywell_hih_i2c/* @Benichou34 esphome/components/honeywellabp/* @RubyBailey diff --git a/esphome/components/homeassistant/number/__init__.py b/esphome/components/homeassistant/number/__init__.py new file mode 100644 index 0000000000..a6cc615a64 --- /dev/null +++ b/esphome/components/homeassistant/number/__init__.py @@ -0,0 +1,33 @@ +import esphome.codegen as cg +from esphome.components import number +import esphome.config_validation as cv + +from .. import ( + HOME_ASSISTANT_IMPORT_CONTROL_SCHEMA, + homeassistant_ns, + setup_home_assistant_entity, +) + +CODEOWNERS = ["@landonr"] +DEPENDENCIES = ["api"] + +HomeassistantNumber = homeassistant_ns.class_( + "HomeassistantNumber", number.Number, cg.Component +) + +CONFIG_SCHEMA = ( + number.number_schema(HomeassistantNumber) + .extend(HOME_ASSISTANT_IMPORT_CONTROL_SCHEMA) + .extend(cv.COMPONENT_SCHEMA) +) + + +async def to_code(config): + var = await number.new_number( + config, + min_value=0, + max_value=0, + step=0, + ) + await cg.register_component(var, config) + setup_home_assistant_entity(var, config) diff --git a/esphome/components/homeassistant/number/homeassistant_number.cpp b/esphome/components/homeassistant/number/homeassistant_number.cpp new file mode 100644 index 0000000000..d3e285f4ac --- /dev/null +++ b/esphome/components/homeassistant/number/homeassistant_number.cpp @@ -0,0 +1,100 @@ +#include "homeassistant_number.h" + +#include "esphome/components/api/api_pb2.h" +#include "esphome/components/api/api_server.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace homeassistant { + +static const char *const TAG = "homeassistant.number"; + +void HomeassistantNumber::state_changed_(const std::string &state) { + auto number_value = parse_number(state); + if (!number_value.has_value()) { + ESP_LOGW(TAG, "'%s': Can't convert '%s' to number!", this->entity_id_.c_str(), state.c_str()); + this->publish_state(NAN); + return; + } + if (this->state == number_value.value()) { + return; + } + ESP_LOGD(TAG, "'%s': Got state %s", this->entity_id_.c_str(), state.c_str()); + this->publish_state(number_value.value()); +} + +void HomeassistantNumber::min_retrieved_(const std::string &min) { + auto min_value = parse_number(min); + if (!min_value.has_value()) { + ESP_LOGE(TAG, "'%s': Can't convert 'min' value '%s' to number!", this->entity_id_.c_str(), min.c_str()); + } + ESP_LOGD(TAG, "'%s': Min retrieved: %s", get_name().c_str(), min.c_str()); + this->traits.set_min_value(min_value.value()); +} + +void HomeassistantNumber::max_retrieved_(const std::string &max) { + auto max_value = parse_number(max); + if (!max_value.has_value()) { + ESP_LOGE(TAG, "'%s': Can't convert 'max' value '%s' to number!", this->entity_id_.c_str(), max.c_str()); + } + ESP_LOGD(TAG, "'%s': Max retrieved: %s", get_name().c_str(), max.c_str()); + this->traits.set_max_value(max_value.value()); +} + +void HomeassistantNumber::step_retrieved_(const std::string &step) { + auto step_value = parse_number(step); + if (!step_value.has_value()) { + ESP_LOGE(TAG, "'%s': Can't convert 'step' value '%s' to number!", this->entity_id_.c_str(), step.c_str()); + } + ESP_LOGD(TAG, "'%s': Step Retrieved %s", get_name().c_str(), step.c_str()); + this->traits.set_step(step_value.value()); +} + +void HomeassistantNumber::setup() { + api::global_api_server->subscribe_home_assistant_state( + this->entity_id_, nullopt, std::bind(&HomeassistantNumber::state_changed_, this, std::placeholders::_1)); + + api::global_api_server->get_home_assistant_state( + this->entity_id_, optional("min"), + std::bind(&HomeassistantNumber::min_retrieved_, this, std::placeholders::_1)); + api::global_api_server->get_home_assistant_state( + this->entity_id_, optional("max"), + std::bind(&HomeassistantNumber::max_retrieved_, this, std::placeholders::_1)); + api::global_api_server->get_home_assistant_state( + this->entity_id_, optional("step"), + std::bind(&HomeassistantNumber::step_retrieved_, this, std::placeholders::_1)); +} + +void HomeassistantNumber::dump_config() { + LOG_NUMBER("", "Homeassistant Number", this); + ESP_LOGCONFIG(TAG, " Entity ID: '%s'", this->entity_id_.c_str()); +} + +float HomeassistantNumber::get_setup_priority() const { return setup_priority::AFTER_CONNECTION; } + +void HomeassistantNumber::control(float value) { + if (!api::global_api_server->is_connected()) { + ESP_LOGE(TAG, "No clients connected to API server"); + return; + } + + this->publish_state(value); + + api::HomeassistantServiceResponse resp; + resp.service = "number.set_value"; + + api::HomeassistantServiceMap entity_id; + entity_id.key = "entity_id"; + entity_id.value = this->entity_id_; + resp.data.push_back(entity_id); + + api::HomeassistantServiceMap entity_value; + entity_value.key = "value"; + entity_value.value = to_string(value); + resp.data.push_back(entity_value); + + api::global_api_server->send_homeassistant_service_call(resp); +} + +} // namespace homeassistant +} // namespace esphome diff --git a/esphome/components/homeassistant/number/homeassistant_number.h b/esphome/components/homeassistant/number/homeassistant_number.h new file mode 100644 index 0000000000..0860b4e91c --- /dev/null +++ b/esphome/components/homeassistant/number/homeassistant_number.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include + +#include "esphome/components/number/number.h" +#include "esphome/core/component.h" + +namespace esphome { +namespace homeassistant { + +class HomeassistantNumber : public number::Number, public Component { + public: + void set_entity_id(const std::string &entity_id) { this->entity_id_ = entity_id; } + + void setup() override; + void dump_config() override; + float get_setup_priority() const override; + + protected: + void state_changed_(const std::string &state); + void min_retrieved_(const std::string &min); + void max_retrieved_(const std::string &max); + void step_retrieved_(const std::string &step); + + void control(float value) override; + + std::string entity_id_; +}; +} // namespace homeassistant +} // namespace esphome diff --git a/tests/components/homeassistant/common.yaml b/tests/components/homeassistant/common.yaml index 2b2805d06e..8c9a4ad75f 100644 --- a/tests/components/homeassistant/common.yaml +++ b/tests/components/homeassistant/common.yaml @@ -46,6 +46,11 @@ binary_sensor: attribute: world id: ha_hello_world_binary_attribute +number: + - platform: homeassistant + entity_id: number.hello_world + id: ha_hello_world_number + sensor: - platform: homeassistant entity_id: sensor.hello_world From a0eff08f39c69059d74929e6c91b8b61fb7ee51f Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Wed, 14 Aug 2024 12:05:25 +1000 Subject: [PATCH 1925/2101] [lvgl] Rework events to avoid feedback loops (#7262) --- esphome/components/lvgl/automation.py | 4 +-- esphome/components/lvgl/defines.py | 1 + esphome/components/lvgl/light/lvgl_light.h | 2 +- esphome/components/lvgl/lvcode.py | 6 ++++- esphome/components/lvgl/lvgl_esphome.cpp | 15 +++++++---- esphome/components/lvgl/lvgl_esphome.h | 5 +++- esphome/components/lvgl/number/__init__.py | 22 +++++++++++++--- esphome/components/lvgl/select/__init__.py | 13 ++++++++-- esphome/components/lvgl/sensor/__init__.py | 16 ++++++++++-- esphome/components/lvgl/switch/__init__.py | 6 +++-- esphome/components/lvgl/text/__init__.py | 17 ++++++++++--- .../components/lvgl/text_sensor/__init__.py | 4 ++- esphome/components/lvgl/trigger.py | 25 +++++++++++++++---- tests/components/lvgl/common.yaml | 1 + 14 files changed, 108 insertions(+), 29 deletions(-) diff --git a/esphome/components/lvgl/automation.py b/esphome/components/lvgl/automation.py index 556e286208..a39f589136 100644 --- a/esphome/components/lvgl/automation.py +++ b/esphome/components/lvgl/automation.py @@ -17,6 +17,7 @@ from .defines import ( from .lv_validation import lv_bool, lv_color, lv_image from .lvcode import ( LVGL_COMP_ARG, + UPDATE_EVENT, LambdaContext, LocalVariable, LvConditional, @@ -30,7 +31,6 @@ from .lvcode import ( ) from .schemas import DISP_BG_SCHEMA, LIST_ACTION_SCHEMA, LVGL_SCHEMA from .types import ( - LV_EVENT, LV_STATE, LvglAction, LvglCondition, @@ -64,7 +64,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, LV_EVENT.VALUE_CHANGED, nullptr) + lv.event_send(widget.obj, UPDATE_EVENT, nullptr) widgets = await get_widgets(config[CONF_ID]) return await action_to_code(widgets, do_update, action_id, template_arg, args) diff --git a/esphome/components/lvgl/defines.py b/esphome/components/lvgl/defines.py index e48679996b..8f7a973722 100644 --- a/esphome/components/lvgl/defines.py +++ b/esphome/components/lvgl/defines.py @@ -470,6 +470,7 @@ CONF_TOP_LAYER = "top_layer" CONF_TOUCHSCREENS = "touchscreens" CONF_TRANSPARENCY_KEY = "transparency_key" CONF_THEME = "theme" +CONF_UPDATE_ON_RELEASE = "update_on_release" CONF_VISIBLE_ROW_COUNT = "visible_row_count" CONF_WIDGET = "widget" CONF_WIDGETS = "widgets" diff --git a/esphome/components/lvgl/light/lvgl_light.h b/esphome/components/lvgl/light/lvgl_light.h index 67372d89dd..50ae4c5327 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_custom_event, nullptr); + lv_event_send(this->obj_, lv_api_event, nullptr); } lv_obj_t *obj_{}; optional initial_value_{}; diff --git a/esphome/components/lvgl/lvcode.py b/esphome/components/lvgl/lvcode.py index f54a032de2..6d7e364e5d 100644 --- a/esphome/components/lvgl/lvcode.py +++ b/esphome/components/lvgl/lvcode.py @@ -29,7 +29,11 @@ LvglComponent = lvgl_ns.class_("LvglComponent", cg.PollingComponent) LVGL_COMP_ARG = [(LvglComponent.operator("ptr"), LVGL_COMP)] lv_event_t_ptr = cg.global_ns.namespace("lv_event_t").operator("ptr") EVENT_ARG = [(lv_event_t_ptr, "ev")] -CUSTOM_EVENT = literal("lvgl::lv_custom_event") +# Two custom events; API_EVENT is fired when an entity is updated remotely by an API interaction; +# UPDATE_EVENT is fired when an entity is programmatically updated locally. +# VALUE_CHANGED is the event generated by LVGL when an entity's value changes through user interaction. +API_EVENT = literal("lvgl::lv_api_event") +UPDATE_EVENT = literal("lvgl::lv_update_event") def get_line_marks(value) -> list: diff --git a/esphome/components/lvgl/lvgl_esphome.cpp b/esphome/components/lvgl/lvgl_esphome.cpp index 6f23c2421b..92f7a880c3 100644 --- a/esphome/components/lvgl/lvgl_esphome.cpp +++ b/esphome/components/lvgl/lvgl_esphome.cpp @@ -27,7 +27,8 @@ static void rounder_cb(lv_disp_drv_t *disp_drv, lv_area_t *area) { area->y2++; } -lv_event_code_t lv_custom_event; // NOLINT +lv_event_code_t lv_api_event; // NOLINT +lv_event_code_t lv_update_event; // NOLINT void LvglComponent::dump_config() { ESP_LOGCONFIG(TAG, "LVGL:"); } void LvglComponent::set_paused(bool paused, bool show_snow) { this->paused_ = paused; @@ -40,15 +41,18 @@ void LvglComponent::set_paused(bool paused, bool show_snow) { } void LvglComponent::add_event_cb(lv_obj_t *obj, event_callback_t callback, lv_event_code_t event) { lv_obj_add_event_cb(obj, callback, event, this); - if (event == LV_EVENT_VALUE_CHANGED) { - lv_obj_add_event_cb(obj, callback, lv_custom_event, this); - } } void LvglComponent::add_event_cb(lv_obj_t *obj, event_callback_t callback, lv_event_code_t event1, lv_event_code_t event2) { this->add_event_cb(obj, callback, event1); this->add_event_cb(obj, callback, event2); } +void LvglComponent::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) { + this->add_event_cb(obj, callback, event1); + this->add_event_cb(obj, callback, event2); + this->add_event_cb(obj, callback, event3); +} void LvglComponent::add_page(LvPageType *page) { this->pages_.push_back(page); page->setup(this->pages_.size() - 1); @@ -228,7 +232,8 @@ void LvglComponent::setup() { lv_log_register_print_cb(log_cb); #endif lv_init(); - lv_custom_event = static_cast(lv_event_register_id()); + lv_update_event = static_cast(lv_event_register_id()); + lv_api_event = static_cast(lv_event_register_id()); auto *display = this->displays_[0]; size_t buffer_pixels = display->get_width() * display->get_height() / this->buffer_frac_; auto buf_bytes = buffer_pixels * LV_COLOR_DEPTH / 8; diff --git a/esphome/components/lvgl/lvgl_esphome.h b/esphome/components/lvgl/lvgl_esphome.h index 1497e1004a..3a3d1aa6c5 100644 --- a/esphome/components/lvgl/lvgl_esphome.h +++ b/esphome/components/lvgl/lvgl_esphome.h @@ -38,7 +38,8 @@ namespace esphome { namespace lvgl { -extern lv_event_code_t lv_custom_event; // NOLINT +extern lv_event_code_t lv_api_event; // NOLINT +extern lv_event_code_t lv_update_event; // NOLINT #ifdef USE_LVGL_COLOR inline lv_color_t lv_color_from(Color color) { return lv_color_make(color.red, color.green, color.blue); } #endif // USE_LVGL_COLOR @@ -133,6 +134,8 @@ class LvglComponent : public PollingComponent { void set_paused(bool paused, bool show_snow); void add_event_cb(lv_obj_t *obj, event_callback_t callback, lv_event_code_t event); void add_event_cb(lv_obj_t *obj, event_callback_t callback, lv_event_code_t event1, lv_event_code_t event2); + 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); bool is_paused() const { return this->paused_; } void add_page(LvPageType *page); void show_page(size_t index, lv_scr_load_anim_t anim, uint32_t time); diff --git a/esphome/components/lvgl/number/__init__.py b/esphome/components/lvgl/number/__init__.py index 53aef2790d..6336bb0632 100644 --- a/esphome/components/lvgl/number/__init__.py +++ b/esphome/components/lvgl/number/__init__.py @@ -3,9 +3,17 @@ from esphome.components import number import esphome.config_validation as cv from esphome.cpp_generator import MockObj -from ..defines import CONF_ANIMATED, CONF_LVGL_ID, CONF_WIDGET +from ..defines import CONF_ANIMATED, CONF_LVGL_ID, CONF_UPDATE_ON_RELEASE, CONF_WIDGET from ..lv_validation import animated -from ..lvcode import CUSTOM_EVENT, EVENT_ARG, LambdaContext, LvContext, lv, lv_add +from ..lvcode import ( + API_EVENT, + EVENT_ARG, + UPDATE_EVENT, + LambdaContext, + LvContext, + lv, + lv_add, +) from ..schemas import LVGL_SCHEMA from ..types import LV_EVENT, LvNumber, lvgl_ns from ..widgets import get_widgets @@ -19,6 +27,7 @@ CONFIG_SCHEMA = ( { cv.Required(CONF_WIDGET): cv.use_id(LvNumber), cv.Optional(CONF_ANIMATED, default=True): animated, + cv.Optional(CONF_UPDATE_ON_RELEASE, default=False): cv.boolean, } ) ) @@ -39,14 +48,19 @@ async def to_code(config): await widget.set_property( "value", MockObj("v") * MockObj(widget.get_scale()), config[CONF_ANIMATED] ) - lv.event_send(widget.obj, CUSTOM_EVENT, cg.nullptr) + lv.event_send(widget.obj, API_EVENT, cg.nullptr) async with LambdaContext(EVENT_ARG) as event: event.add(var.publish_state(widget.get_value())) + event_code = ( + LV_EVENT.VALUE_CHANGED + if not config[CONF_UPDATE_ON_RELEASE] + else LV_EVENT.RELEASED + ) async with LvContext(paren): lv_add(var.set_control_lambda(await control.get_lambda())) lv_add( paren.add_event_cb( - widget.obj, await event.get_lambda(), LV_EVENT.VALUE_CHANGED + widget.obj, await event.get_lambda(), UPDATE_EVENT, event_code ) ) lv_add(var.publish_state(widget.get_value())) diff --git a/esphome/components/lvgl/select/__init__.py b/esphome/components/lvgl/select/__init__.py index 34a70a23f7..b55bde13bc 100644 --- a/esphome/components/lvgl/select/__init__.py +++ b/esphome/components/lvgl/select/__init__.py @@ -4,7 +4,15 @@ import esphome.config_validation as cv from esphome.const import CONF_OPTIONS from ..defines import CONF_ANIMATED, CONF_LVGL_ID, CONF_WIDGET -from ..lvcode import CUSTOM_EVENT, EVENT_ARG, LambdaContext, LvContext, lv, lv_add +from ..lvcode import ( + API_EVENT, + EVENT_ARG, + UPDATE_EVENT, + LambdaContext, + LvContext, + lv, + lv_add, +) from ..schemas import LVGL_SCHEMA from ..types import LV_EVENT, LvSelect, lvgl_ns from ..widgets import get_widgets @@ -33,7 +41,7 @@ async def to_code(config): pub_ctx.add(selector.publish_index(widget.get_value())) async with LambdaContext([(cg.uint16, "v")]) as control: await widget.set_property("selected", "v", animated=config[CONF_ANIMATED]) - lv.event_send(widget.obj, CUSTOM_EVENT, cg.nullptr) + lv.event_send(widget.obj, API_EVENT, cg.nullptr) async with LvContext(paren) as ctx: lv_add(selector.set_control_lambda(await control.get_lambda())) ctx.add( @@ -41,6 +49,7 @@ async def to_code(config): widget.obj, await pub_ctx.get_lambda(), LV_EVENT.VALUE_CHANGED, + UPDATE_EVENT, ) ) lv_add(selector.publish_index(widget.get_value())) diff --git a/esphome/components/lvgl/sensor/__init__.py b/esphome/components/lvgl/sensor/__init__.py index 6e495eb685..82e21d5e95 100644 --- a/esphome/components/lvgl/sensor/__init__.py +++ b/esphome/components/lvgl/sensor/__init__.py @@ -3,7 +3,15 @@ from esphome.components.sensor import Sensor, new_sensor, sensor_schema import esphome.config_validation as cv from ..defines import CONF_LVGL_ID, CONF_WIDGET -from ..lvcode import EVENT_ARG, LVGL_COMP_ARG, LambdaContext, LvContext, lv_add +from ..lvcode import ( + API_EVENT, + EVENT_ARG, + LVGL_COMP_ARG, + UPDATE_EVENT, + LambdaContext, + LvContext, + lv_add, +) from ..schemas import LVGL_SCHEMA from ..types import LV_EVENT, LvNumber from ..widgets import Widget, get_widgets @@ -30,6 +38,10 @@ async def to_code(config): async with LvContext(paren, LVGL_COMP_ARG): lv_add( paren.add_event_cb( - widget.obj, await lamb.get_lambda(), LV_EVENT.VALUE_CHANGED + widget.obj, + await lamb.get_lambda(), + LV_EVENT.VALUE_CHANGED, + API_EVENT, + UPDATE_EVENT, ) ) diff --git a/esphome/components/lvgl/switch/__init__.py b/esphome/components/lvgl/switch/__init__.py index 831fa9308b..957fce17ff 100644 --- a/esphome/components/lvgl/switch/__init__.py +++ b/esphome/components/lvgl/switch/__init__.py @@ -5,8 +5,9 @@ from esphome.cpp_generator import MockObj from ..defines import CONF_LVGL_ID, CONF_WIDGET from ..lvcode import ( - CUSTOM_EVENT, + API_EVENT, EVENT_ARG, + UPDATE_EVENT, LambdaContext, LvConditional, LvContext, @@ -41,7 +42,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, CUSTOM_EVENT, cg.nullptr) + lv.event_send(widget.obj, API_EVENT, cg.nullptr) async with LvContext(paren) as ctx: lv_add(switch.set_control_lambda(await control.get_lambda())) ctx.add( @@ -49,6 +50,7 @@ async def to_code(config): widget.obj, await checked_ctx.get_lambda(), LV_EVENT.VALUE_CHANGED, + UPDATE_EVENT, ) ) lv_add(switch.publish_state(widget.get_value())) diff --git a/esphome/components/lvgl/text/__init__.py b/esphome/components/lvgl/text/__init__.py index 55f1b2b3fc..9ee494d8a0 100644 --- a/esphome/components/lvgl/text/__init__.py +++ b/esphome/components/lvgl/text/__init__.py @@ -4,7 +4,15 @@ from esphome.components.text import new_text import esphome.config_validation as cv from ..defines import CONF_LVGL_ID, CONF_WIDGET -from ..lvcode import CUSTOM_EVENT, EVENT_ARG, LambdaContext, LvContext, lv, lv_add +from ..lvcode import ( + API_EVENT, + EVENT_ARG, + UPDATE_EVENT, + LambdaContext, + LvContext, + lv, + lv_add, +) from ..schemas import LVGL_SCHEMA from ..types import LV_EVENT, LvText, lvgl_ns from ..widgets import get_widgets @@ -26,14 +34,17 @@ async def to_code(config): widget = widget[0] async with LambdaContext([(cg.std_string, "text_value")]) as control: await widget.set_property("text", "text_value.c_str())") - lv.event_send(widget.obj, CUSTOM_EVENT, None) + lv.event_send(widget.obj, API_EVENT, None) async with LambdaContext(EVENT_ARG) as lamb: lv_add(textvar.publish_state(widget.get_value())) async with LvContext(paren): widget.var.set_control_lambda(await control.get_lambda()) lv_add( paren.add_event_cb( - widget.obj, await lamb.get_lambda(), LV_EVENT.VALUE_CHANGED + widget.obj, + await lamb.get_lambda(), + LV_EVENT.VALUE_CHANGED, + UPDATE_EVENT, ) ) lv_add(textvar.publish_state(widget.get_value())) diff --git a/esphome/components/lvgl/text_sensor/__init__.py b/esphome/components/lvgl/text_sensor/__init__.py index c0f0bc36a8..cab715dce0 100644 --- a/esphome/components/lvgl/text_sensor/__init__.py +++ b/esphome/components/lvgl/text_sensor/__init__.py @@ -7,7 +7,7 @@ from esphome.components.text_sensor import ( import esphome.config_validation as cv from ..defines import CONF_LVGL_ID, CONF_WIDGET -from ..lvcode import EVENT_ARG, LambdaContext, LvContext +from ..lvcode import API_EVENT, EVENT_ARG, UPDATE_EVENT, LambdaContext, LvContext from ..schemas import LVGL_SCHEMA from ..types import LV_EVENT, LvText from ..widgets import get_widgets @@ -36,5 +36,7 @@ async def to_code(config): widget.obj, await pressed_ctx.get_lambda(), LV_EVENT.VALUE_CHANGED, + API_EVENT, + UPDATE_EVENT, ) ) diff --git a/esphome/components/lvgl/trigger.py b/esphome/components/lvgl/trigger.py index df87be718b..ba93aabb2d 100644 --- a/esphome/components/lvgl/trigger.py +++ b/esphome/components/lvgl/trigger.py @@ -11,7 +11,15 @@ from .defines import ( LV_EVENT_TRIGGERS, literal, ) -from .lvcode import EVENT_ARG, LambdaContext, LvConditional, lv, lv_add +from .lvcode import ( + API_EVENT, + EVENT_ARG, + UPDATE_EVENT, + LambdaContext, + LvConditional, + lv, + lv_add, +) from .types import LV_EVENT from .widgets import widget_map @@ -34,9 +42,16 @@ async def generate_triggers(lv_component): conf = conf[0] w.add_flag("LV_OBJ_FLAG_CLICKABLE") event = literal("LV_EVENT_" + LV_EVENT_MAP[event[3:].upper()]) - await add_trigger(conf, event, lv_component, w) + await add_trigger(conf, lv_component, w, event) for conf in w.config.get(CONF_ON_VALUE, ()): - await add_trigger(conf, LV_EVENT.VALUE_CHANGED, lv_component, w) + await add_trigger( + conf, + lv_component, + w, + LV_EVENT.VALUE_CHANGED, + API_EVENT, + UPDATE_EVENT, + ) # Generate align to directives while we're here if align_to := w.config.get(CONF_ALIGN_TO): @@ -47,7 +62,7 @@ async def generate_triggers(lv_component): lv.obj_align_to(w.obj, target, align, x, y) -async def add_trigger(conf, event, lv_component, w): +async def add_trigger(conf, lv_component, w, *events): tid = conf[CONF_TRIGGER_ID] trigger = cg.new_Pvariable(tid) args = w.get_args() @@ -56,4 +71,4 @@ async def add_trigger(conf, event, lv_component, w): async with LambdaContext(EVENT_ARG, where=tid) as context: with LvConditional(w.is_selected()): lv_add(trigger.trigger(value)) - lv_add(lv_component.add_event_cb(w.obj, await context.get_lambda(), event)) + lv_add(lv_component.add_event_cb(w.obj, await context.get_lambda(), *events)) diff --git a/tests/components/lvgl/common.yaml b/tests/components/lvgl/common.yaml index 35d924d939..002c7a118d 100644 --- a/tests/components/lvgl/common.yaml +++ b/tests/components/lvgl/common.yaml @@ -75,6 +75,7 @@ number: - platform: lvgl widget: slider_id name: LVGL Slider + update_on_release: true - platform: lvgl widget: lv_arc id: lvgl_arc_number From bec2d42c793c59b18e15a0fbb5cbe22761858290 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Wed, 14 Aug 2024 12:06:13 +1000 Subject: [PATCH 1926/2101] Add `color_filter_opa` style property (#7276) --- esphome/components/lvgl/schemas.py | 1 + tests/components/lvgl/lvgl-package.yaml | 1 + 2 files changed, 2 insertions(+) diff --git a/esphome/components/lvgl/schemas.py b/esphome/components/lvgl/schemas.py index e4b1c3f8fa..f1c7ff4df6 100644 --- a/esphome/components/lvgl/schemas.py +++ b/esphome/components/lvgl/schemas.py @@ -103,6 +103,7 @@ STYLE_PROPS = { ).several_of, "border_width": cv.positive_int, "clip_corner": lvalid.lv_bool, + "color_filter_opa": lvalid.opacity, "height": lvalid.size, "image_recolor": lvalid.lv_color, "image_recolor_opa": lvalid.opacity, diff --git a/tests/components/lvgl/lvgl-package.yaml b/tests/components/lvgl/lvgl-package.yaml index 09ff9c9d39..54022354f5 100644 --- a/tests/components/lvgl/lvgl-package.yaml +++ b/tests/components/lvgl/lvgl-package.yaml @@ -101,6 +101,7 @@ lvgl: border_side: [bottom, left] border_width: 4 clip_corner: false + color_filter_opa: transp height: 50% image_recolor: light_blue image_recolor_opa: cover From 56e05998efb14b7e91fea7e4ef3cfe76a7128c61 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Wed, 14 Aug 2024 04:08:10 +0200 Subject: [PATCH 1927/2101] [code-quality] fix clang-tidy wake_on_lan (#7275) --- esphome/components/wake_on_lan/wake_on_lan.cpp | 2 ++ esphome/components/wake_on_lan/wake_on_lan.h | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/esphome/components/wake_on_lan/wake_on_lan.cpp b/esphome/components/wake_on_lan/wake_on_lan.cpp index 080e1bbac8..d18cdf89c8 100644 --- a/esphome/components/wake_on_lan/wake_on_lan.cpp +++ b/esphome/components/wake_on_lan/wake_on_lan.cpp @@ -1,4 +1,5 @@ #include "wake_on_lan.h" +#ifdef USE_NETWORK #include "esphome/core/log.h" #include "esphome/components/network/ip_address.h" #include "esphome/components/network/util.h" @@ -85,3 +86,4 @@ void WakeOnLanButton::setup() { } // namespace wake_on_lan } // namespace esphome +#endif diff --git a/esphome/components/wake_on_lan/wake_on_lan.h b/esphome/components/wake_on_lan/wake_on_lan.h index 42cb3a9268..f516c4d669 100644 --- a/esphome/components/wake_on_lan/wake_on_lan.h +++ b/esphome/components/wake_on_lan/wake_on_lan.h @@ -1,5 +1,6 @@ #pragma once - +#include "esphome/core/defines.h" +#ifdef USE_NETWORK #include "esphome/components/button/button.h" #include "esphome/core/component.h" #if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) @@ -32,3 +33,4 @@ class WakeOnLanButton : public button::Button, public Component { } // namespace wake_on_lan } // namespace esphome +#endif From 4cb174585c0521801d6e8ffda189d37b5a40aa30 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Wed, 14 Aug 2024 04:14:29 +0200 Subject: [PATCH 1928/2101] [code-quality] fix readability-braces-around-statements (#7273) --- .../binary/light/binary_light_output.h | 5 +- esphome/components/demo/demo_sensor.h | 5 +- .../light/addressable_light_effect.h | 20 +++--- esphome/components/lvgl/number/lvgl_number.h | 5 +- esphome/components/lvgl/switch/lvgl_switch.h | 5 +- esphome/components/lvgl/text/lvgl_text.h | 5 +- esphome/components/rgbct/rgbct_light_output.h | 5 +- esphome/components/rgbw/rgbw_light_output.h | 5 +- esphome/components/rgbww/rgbww_light_output.h | 5 +- .../components/spi_led_strip/spi_led_strip.h | 5 +- esphome/core/application.h | 63 ++++++++++++------- esphome/core/base_automation.h | 5 +- esphome/core/color.h | 40 +++++++----- 13 files changed, 108 insertions(+), 65 deletions(-) diff --git a/esphome/components/binary/light/binary_light_output.h b/esphome/components/binary/light/binary_light_output.h index 86c83aff5c..8346a82cf0 100644 --- a/esphome/components/binary/light/binary_light_output.h +++ b/esphome/components/binary/light/binary_light_output.h @@ -18,10 +18,11 @@ class BinaryLightOutput : public light::LightOutput { void write_state(light::LightState *state) override { bool binary; state->current_values_as_binary(&binary); - if (binary) + if (binary) { this->output_->turn_on(); - else + } else { this->output_->turn_off(); + } } protected: diff --git a/esphome/components/demo/demo_sensor.h b/esphome/components/demo/demo_sensor.h index b4afa03e11..d965d987de 100644 --- a/esphome/components/demo/demo_sensor.h +++ b/esphome/components/demo/demo_sensor.h @@ -16,10 +16,11 @@ class DemoSensor : public sensor::Sensor, public PollingComponent { float base = std::isnan(this->state) ? 0.0f : this->state; this->publish_state(base + val * 10); } else { - if (val < 0.1) + if (val < 0.1) { this->publish_state(NAN); - else + } else { this->publish_state(val * 100); + } } } }; diff --git a/esphome/components/light/addressable_light_effect.h b/esphome/components/light/addressable_light_effect.h index 73083a58b7..d622ec0375 100644 --- a/esphome/components/light/addressable_light_effect.h +++ b/esphome/components/light/addressable_light_effect.h @@ -114,10 +114,11 @@ class AddressableColorWipeEffect : public AddressableLightEffect { if (now - this->last_add_ < this->add_led_interval_) return; this->last_add_ = now; - if (this->reverse_) + if (this->reverse_) { it.shift_left(1); - else + } else { it.shift_right(1); + } const AddressableColorWipeEffectColor &color = this->colors_[this->at_color_]; Color esp_color = Color(color.r, color.g, color.b, color.w); if (color.gradient) { @@ -127,10 +128,11 @@ class AddressableColorWipeEffect : public AddressableLightEffect { uint8_t gradient = 255 * ((float) this->leds_added_ / color.num_leds); esp_color = esp_color.gradient(next_esp_color, gradient); } - if (this->reverse_) + if (this->reverse_) { it[-1] = esp_color; - else + } else { it[0] = esp_color; + } if (++this->leds_added_ >= color.num_leds) { this->leds_added_ = 0; this->at_color_ = (this->at_color_ + 1) % this->colors_.size(); @@ -207,10 +209,11 @@ class AddressableTwinkleEffect : public AddressableLightEffect { const uint8_t sine = half_sin8(view.get_effect_data()); view = current_color * sine; const uint8_t new_pos = view.get_effect_data() + pos_add; - if (new_pos < view.get_effect_data()) + if (new_pos < view.get_effect_data()) { view.set_effect_data(0); - else + } else { view.set_effect_data(new_pos); + } } else { view = Color::BLACK; } @@ -254,10 +257,11 @@ class AddressableRandomTwinkleEffect : public AddressableLightEffect { view = Color(((color >> 2) & 1) * sine, ((color >> 1) & 1) * sine, ((color >> 0) & 1) * sine); } const uint8_t new_x = x + pos_add; - if (new_x > 0b11111) + if (new_x > 0b11111) { view.set_effect_data(0); - else + } else { view.set_effect_data((new_x << 3) | color); + } } else { view = Color(0, 0, 0, 0); } diff --git a/esphome/components/lvgl/number/lvgl_number.h b/esphome/components/lvgl/number/lvgl_number.h index 659fc615c9..a70c9eab9c 100644 --- a/esphome/components/lvgl/number/lvgl_number.h +++ b/esphome/components/lvgl/number/lvgl_number.h @@ -20,10 +20,11 @@ class LVGLNumber : public number::Number { protected: void control(float value) override { - if (this->control_lambda_ != nullptr) + if (this->control_lambda_ != nullptr) { this->control_lambda_(value); - else + } else { this->initial_state_ = value; + } } std::function control_lambda_{}; optional initial_state_{}; diff --git a/esphome/components/lvgl/switch/lvgl_switch.h b/esphome/components/lvgl/switch/lvgl_switch.h index 67be11faba..dbc885219b 100644 --- a/esphome/components/lvgl/switch/lvgl_switch.h +++ b/esphome/components/lvgl/switch/lvgl_switch.h @@ -20,10 +20,11 @@ class LVGLSwitch : public switch_::Switch { protected: void write_state(bool value) override { - if (this->state_lambda_ != nullptr) + if (this->state_lambda_ != nullptr) { this->state_lambda_(value); - else + } else { this->initial_state_ = value; + } } std::function state_lambda_{}; optional initial_state_{}; diff --git a/esphome/components/lvgl/text/lvgl_text.h b/esphome/components/lvgl/text/lvgl_text.h index 4bd5b76744..d3513c3697 100644 --- a/esphome/components/lvgl/text/lvgl_text.h +++ b/esphome/components/lvgl/text/lvgl_text.h @@ -20,10 +20,11 @@ class LVGLText : public text::Text { protected: void control(const std::string &value) override { - if (this->control_lambda_ != nullptr) + if (this->control_lambda_ != nullptr) { this->control_lambda_(value); - else + } else { this->initial_state_ = value; + } } std::function control_lambda_{}; optional initial_state_{}; diff --git a/esphome/components/rgbct/rgbct_light_output.h b/esphome/components/rgbct/rgbct_light_output.h index 9257d67cd1..9e23f783ae 100644 --- a/esphome/components/rgbct/rgbct_light_output.h +++ b/esphome/components/rgbct/rgbct_light_output.h @@ -23,10 +23,11 @@ class RGBCTLightOutput : public light::LightOutput { light::LightTraits get_traits() override { auto traits = light::LightTraits(); - if (this->color_interlock_) + if (this->color_interlock_) { traits.set_supported_color_modes({light::ColorMode::RGB, light::ColorMode::COLOR_TEMPERATURE}); - else + } else { traits.set_supported_color_modes({light::ColorMode::RGB_COLOR_TEMPERATURE, light::ColorMode::COLOR_TEMPERATURE}); + } traits.set_min_mireds(this->cold_white_temperature_); traits.set_max_mireds(this->warm_white_temperature_); return traits; diff --git a/esphome/components/rgbw/rgbw_light_output.h b/esphome/components/rgbw/rgbw_light_output.h index 0f55775608..a2ab17b75d 100644 --- a/esphome/components/rgbw/rgbw_light_output.h +++ b/esphome/components/rgbw/rgbw_light_output.h @@ -16,10 +16,11 @@ class RGBWLightOutput : public light::LightOutput { void set_color_interlock(bool color_interlock) { color_interlock_ = color_interlock; } light::LightTraits get_traits() override { auto traits = light::LightTraits(); - if (this->color_interlock_) + if (this->color_interlock_) { traits.set_supported_color_modes({light::ColorMode::RGB, light::ColorMode::WHITE}); - else + } else { traits.set_supported_color_modes({light::ColorMode::RGB_WHITE}); + } return traits; } void write_state(light::LightState *state) override { diff --git a/esphome/components/rgbww/rgbww_light_output.h b/esphome/components/rgbww/rgbww_light_output.h index 5a86b88595..9687360059 100644 --- a/esphome/components/rgbww/rgbww_light_output.h +++ b/esphome/components/rgbww/rgbww_light_output.h @@ -20,10 +20,11 @@ class RGBWWLightOutput : public light::LightOutput { void set_color_interlock(bool color_interlock) { color_interlock_ = color_interlock; } light::LightTraits get_traits() override { auto traits = light::LightTraits(); - if (this->color_interlock_) + if (this->color_interlock_) { traits.set_supported_color_modes({light::ColorMode::RGB, light::ColorMode::COLD_WARM_WHITE}); - else + } else { traits.set_supported_color_modes({light::ColorMode::RGB_COLD_WARM_WHITE}); + } traits.set_min_mireds(this->cold_white_temperature_); traits.set_max_mireds(this->warm_white_temperature_); return traits; diff --git a/esphome/components/spi_led_strip/spi_led_strip.h b/esphome/components/spi_led_strip/spi_led_strip.h index 8b713378ec..1b317cdd69 100644 --- a/esphome/components/spi_led_strip/spi_led_strip.h +++ b/esphome/components/spi_led_strip/spi_led_strip.h @@ -46,10 +46,11 @@ class SpiLedStrip : public light::AddressableLight, void dump_config() override { esph_log_config(TAG, "SPI LED Strip:"); esph_log_config(TAG, " LEDs: %d", this->num_leds_); - if (this->data_rate_ >= spi::DATA_RATE_1MHZ) + if (this->data_rate_ >= spi::DATA_RATE_1MHZ) { esph_log_config(TAG, " Data rate: %uMHz", (unsigned) (this->data_rate_ / 1000000)); - else + } else { esph_log_config(TAG, " Data rate: %ukHz", (unsigned) (this->data_rate_ / 1000)); + } } void write_state(light::LightState *state) override { diff --git a/esphome/core/application.h b/esphome/core/application.h index 2697357456..462beb1f25 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -246,162 +246,180 @@ class Application { #ifdef USE_BINARY_SENSOR const std::vector &get_binary_sensors() { return this->binary_sensors_; } binary_sensor::BinarySensor *get_binary_sensor_by_key(uint32_t key, bool include_internal = false) { - for (auto *obj : this->binary_sensors_) + for (auto *obj : this->binary_sensors_) { if (obj->get_object_id_hash() == key && (include_internal || !obj->is_internal())) return obj; + } return nullptr; } #endif #ifdef USE_SWITCH const std::vector &get_switches() { return this->switches_; } switch_::Switch *get_switch_by_key(uint32_t key, bool include_internal = false) { - for (auto *obj : this->switches_) + for (auto *obj : this->switches_) { if (obj->get_object_id_hash() == key && (include_internal || !obj->is_internal())) return obj; + } return nullptr; } #endif #ifdef USE_BUTTON const std::vector &get_buttons() { return this->buttons_; } button::Button *get_button_by_key(uint32_t key, bool include_internal = false) { - for (auto *obj : this->buttons_) + for (auto *obj : this->buttons_) { if (obj->get_object_id_hash() == key && (include_internal || !obj->is_internal())) return obj; + } return nullptr; } #endif #ifdef USE_SENSOR const std::vector &get_sensors() { return this->sensors_; } sensor::Sensor *get_sensor_by_key(uint32_t key, bool include_internal = false) { - for (auto *obj : this->sensors_) + for (auto *obj : this->sensors_) { if (obj->get_object_id_hash() == key && (include_internal || !obj->is_internal())) return obj; + } return nullptr; } #endif #ifdef USE_TEXT_SENSOR const std::vector &get_text_sensors() { return this->text_sensors_; } text_sensor::TextSensor *get_text_sensor_by_key(uint32_t key, bool include_internal = false) { - for (auto *obj : this->text_sensors_) + for (auto *obj : this->text_sensors_) { if (obj->get_object_id_hash() == key && (include_internal || !obj->is_internal())) return obj; + } return nullptr; } #endif #ifdef USE_FAN const std::vector &get_fans() { return this->fans_; } fan::Fan *get_fan_by_key(uint32_t key, bool include_internal = false) { - for (auto *obj : this->fans_) + for (auto *obj : this->fans_) { if (obj->get_object_id_hash() == key && (include_internal || !obj->is_internal())) return obj; + } return nullptr; } #endif #ifdef USE_COVER const std::vector &get_covers() { return this->covers_; } cover::Cover *get_cover_by_key(uint32_t key, bool include_internal = false) { - for (auto *obj : this->covers_) + for (auto *obj : this->covers_) { if (obj->get_object_id_hash() == key && (include_internal || !obj->is_internal())) return obj; + } return nullptr; } #endif #ifdef USE_LIGHT const std::vector &get_lights() { return this->lights_; } light::LightState *get_light_by_key(uint32_t key, bool include_internal = false) { - for (auto *obj : this->lights_) + for (auto *obj : this->lights_) { if (obj->get_object_id_hash() == key && (include_internal || !obj->is_internal())) return obj; + } return nullptr; } #endif #ifdef USE_CLIMATE const std::vector &get_climates() { return this->climates_; } climate::Climate *get_climate_by_key(uint32_t key, bool include_internal = false) { - for (auto *obj : this->climates_) + for (auto *obj : this->climates_) { if (obj->get_object_id_hash() == key && (include_internal || !obj->is_internal())) return obj; + } return nullptr; } #endif #ifdef USE_NUMBER const std::vector &get_numbers() { return this->numbers_; } number::Number *get_number_by_key(uint32_t key, bool include_internal = false) { - for (auto *obj : this->numbers_) + for (auto *obj : this->numbers_) { if (obj->get_object_id_hash() == key && (include_internal || !obj->is_internal())) return obj; + } return nullptr; } #endif #ifdef USE_DATETIME_DATE const std::vector &get_dates() { return this->dates_; } datetime::DateEntity *get_date_by_key(uint32_t key, bool include_internal = false) { - for (auto *obj : this->dates_) + for (auto *obj : this->dates_) { if (obj->get_object_id_hash() == key && (include_internal || !obj->is_internal())) return obj; + } return nullptr; } #endif #ifdef USE_DATETIME_TIME const std::vector &get_times() { return this->times_; } datetime::TimeEntity *get_time_by_key(uint32_t key, bool include_internal = false) { - for (auto *obj : this->times_) + for (auto *obj : this->times_) { if (obj->get_object_id_hash() == key && (include_internal || !obj->is_internal())) return obj; + } return nullptr; } #endif #ifdef USE_DATETIME_DATETIME const std::vector &get_datetimes() { return this->datetimes_; } datetime::DateTimeEntity *get_datetime_by_key(uint32_t key, bool include_internal = false) { - for (auto *obj : this->datetimes_) + for (auto *obj : this->datetimes_) { if (obj->get_object_id_hash() == key && (include_internal || !obj->is_internal())) return obj; + } return nullptr; } #endif #ifdef USE_TEXT const std::vector &get_texts() { return this->texts_; } text::Text *get_text_by_key(uint32_t key, bool include_internal = false) { - for (auto *obj : this->texts_) + for (auto *obj : this->texts_) { if (obj->get_object_id_hash() == key && (include_internal || !obj->is_internal())) return obj; + } return nullptr; } #endif #ifdef USE_SELECT const std::vector &get_selects() { return this->selects_; } select::Select *get_select_by_key(uint32_t key, bool include_internal = false) { - for (auto *obj : this->selects_) + for (auto *obj : this->selects_) { if (obj->get_object_id_hash() == key && (include_internal || !obj->is_internal())) return obj; + } return nullptr; } #endif #ifdef USE_LOCK const std::vector &get_locks() { return this->locks_; } lock::Lock *get_lock_by_key(uint32_t key, bool include_internal = false) { - for (auto *obj : this->locks_) + for (auto *obj : this->locks_) { if (obj->get_object_id_hash() == key && (include_internal || !obj->is_internal())) return obj; + } return nullptr; } #endif #ifdef USE_VALVE const std::vector &get_valves() { return this->valves_; } valve::Valve *get_valve_by_key(uint32_t key, bool include_internal = false) { - for (auto *obj : this->valves_) + for (auto *obj : this->valves_) { if (obj->get_object_id_hash() == key && (include_internal || !obj->is_internal())) return obj; + } return nullptr; } #endif #ifdef USE_MEDIA_PLAYER const std::vector &get_media_players() { return this->media_players_; } media_player::MediaPlayer *get_media_player_by_key(uint32_t key, bool include_internal = false) { - for (auto *obj : this->media_players_) + for (auto *obj : this->media_players_) { if (obj->get_object_id_hash() == key && (include_internal || !obj->is_internal())) return obj; + } return nullptr; } #endif @@ -411,9 +429,10 @@ class Application { return this->alarm_control_panels_; } alarm_control_panel::AlarmControlPanel *get_alarm_control_panel_by_key(uint32_t key, bool include_internal = false) { - for (auto *obj : this->alarm_control_panels_) + for (auto *obj : this->alarm_control_panels_) { if (obj->get_object_id_hash() == key && (include_internal || !obj->is_internal())) return obj; + } return nullptr; } #endif @@ -421,9 +440,10 @@ class Application { #ifdef USE_EVENT const std::vector &get_events() { return this->events_; } event::Event *get_event_by_key(uint32_t key, bool include_internal = false) { - for (auto *obj : this->events_) + for (auto *obj : this->events_) { if (obj->get_object_id_hash() == key && (include_internal || !obj->is_internal())) return obj; + } return nullptr; } #endif @@ -431,9 +451,10 @@ class Application { #ifdef USE_UPDATE const std::vector &get_updates() { return this->updates_; } update::UpdateEntity *get_update_by_key(uint32_t key, bool include_internal = false) { - for (auto *obj : this->updates_) + for (auto *obj : this->updates_) { if (obj->get_object_id_hash() == key && (include_internal || !obj->is_internal())) return obj; + } return nullptr; } #endif diff --git a/esphome/core/base_automation.h b/esphome/core/base_automation.h index 1bf0efb9a4..dcf7da2f21 100644 --- a/esphome/core/base_automation.h +++ b/esphome/core/base_automation.h @@ -278,10 +278,11 @@ template class RepeatAction : public Action { this->then_.add_actions(actions); this->then_.add_action(new LambdaAction([this](uint32_t iteration, Ts... x) { iteration++; - if (iteration >= this->count_.value(x...)) + if (iteration >= this->count_.value(x...)) { this->play_next_tuple_(this->var_); - else + } else { this->then_.play(iteration, x...); + } })); } diff --git a/esphome/core/color.h b/esphome/core/color.h index 8965d9fc83..1c43fd9d3e 100644 --- a/esphome/core/color.h +++ b/esphome/core/color.h @@ -85,22 +85,26 @@ struct Color { } inline Color operator+(const Color &add) const ESPHOME_ALWAYS_INLINE { Color ret; - if (uint8_t(add.r + this->r) < this->r) + if (uint8_t(add.r + this->r) < this->r) { ret.r = 255; - else + } else { ret.r = this->r + add.r; - if (uint8_t(add.g + this->g) < this->g) + } + if (uint8_t(add.g + this->g) < this->g) { ret.g = 255; - else + } else { ret.g = this->g + add.g; - if (uint8_t(add.b + this->b) < this->b) + } + if (uint8_t(add.b + this->b) < this->b) { ret.b = 255; - else + } else { ret.b = this->b + add.b; - if (uint8_t(add.w + this->w) < this->w) + } + if (uint8_t(add.w + this->w) < this->w) { ret.w = 255; - else + } else { ret.w = this->w + add.w; + } return ret; } inline Color &operator+=(const Color &add) ESPHOME_ALWAYS_INLINE { return *this = (*this) + add; } @@ -108,22 +112,26 @@ struct Color { inline Color &operator+=(uint8_t add) ESPHOME_ALWAYS_INLINE { return *this = (*this) + add; } inline Color operator-(const Color &subtract) const ESPHOME_ALWAYS_INLINE { Color ret; - if (subtract.r > this->r) + if (subtract.r > this->r) { ret.r = 0; - else + } else { ret.r = this->r - subtract.r; - if (subtract.g > this->g) + } + if (subtract.g > this->g) { ret.g = 0; - else + } else { ret.g = this->g - subtract.g; - if (subtract.b > this->b) + } + if (subtract.b > this->b) { ret.b = 0; - else + } else { ret.b = this->b - subtract.b; - if (subtract.w > this->w) + } + if (subtract.w > this->w) { ret.w = 0; - else + } else { ret.w = this->w - subtract.w; + } return ret; } inline Color &operator-=(const Color &subtract) ESPHOME_ALWAYS_INLINE { return *this = (*this) - subtract; } From 8756b41b6344a61a49a3b4cdb66437b1b6064036 Mon Sep 17 00:00:00 2001 From: Olivier ARCHER Date: Wed, 14 Aug 2024 04:19:46 +0200 Subject: [PATCH 1929/2101] [mqtt] fix missing initializer in MQTTClientComponent::disable_discovery (#7271) --- esphome/components/mqtt/mqtt_client.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/mqtt/mqtt_client.cpp b/esphome/components/mqtt/mqtt_client.cpp index 876367aaea..c19b24c0cf 100644 --- a/esphome/components/mqtt/mqtt_client.cpp +++ b/esphome/components/mqtt/mqtt_client.cpp @@ -632,6 +632,7 @@ void MQTTClientComponent::disable_discovery() { this->discovery_info_ = MQTTDiscoveryInfo{ .prefix = "", .retain = false, + .discover_ip = false, .clean = false, .unique_id_generator = MQTT_LEGACY_UNIQUE_ID_GENERATOR, .object_id_generator = MQTT_NONE_OBJECT_ID_GENERATOR, From b2b23f2a4f2fbbba0ded4b77104df871a2f27260 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Wed, 14 Aug 2024 04:21:19 +0200 Subject: [PATCH 1930/2101] [code-quality] fix readability-named-parameter (#7272) --- esphome/core/automation.h | 8 +++++--- esphome/core/optional.h | 30 +++++++++++++++--------------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/esphome/core/automation.h b/esphome/core/automation.h index 5a0a17ea1a..e77e453431 100644 --- a/esphome/core/automation.h +++ b/esphome/core/automation.h @@ -82,7 +82,7 @@ template class Condition { } protected: - template bool check_tuple_(const std::tuple &tuple, seq) { + template bool check_tuple_(const std::tuple &tuple, seq /*unused*/) { return this->check(std::get(tuple)...); } }; @@ -156,7 +156,7 @@ template class Action { } } } - template void play_next_tuple_(const std::tuple &tuple, seq) { + template void play_next_tuple_(const std::tuple &tuple, seq /*unused*/) { this->play_next_(std::get(tuple)...); } void play_next_tuple_(const std::tuple &tuple) { @@ -223,7 +223,9 @@ template class ActionList { } protected: - template void play_tuple_(const std::tuple &tuple, seq) { this->play(std::get(tuple)...); } + template void play_tuple_(const std::tuple &tuple, seq /*unused*/) { + this->play(std::get(tuple)...); + } Action *actions_begin_{nullptr}; Action *actions_end_{nullptr}; diff --git a/esphome/core/optional.h b/esphome/core/optional.h index 770b77081e..1e28ef1354 100644 --- a/esphome/core/optional.h +++ b/esphome/core/optional.h @@ -24,7 +24,7 @@ namespace esphome { struct nullopt_t { // NOLINT struct init {}; // NOLINT - nullopt_t(init) {} + nullopt_t(init /*unused*/) {} }; // extra parenthesis to prevent the most vexing parse: @@ -42,13 +42,13 @@ template class optional { // NOLINT optional() {} - optional(nullopt_t) {} + optional(nullopt_t /*unused*/) {} optional(T const &arg) : has_value_(true), value_(arg) {} // NOLINT template optional(optional const &other) : has_value_(other.has_value()), value_(other.value()) {} - optional &operator=(nullopt_t) { + optional &operator=(nullopt_t /*unused*/) { reset(); return *this; } @@ -130,29 +130,29 @@ template inline bool operator>=(optional const &x, op // Comparison with nullopt -template inline bool operator==(optional const &x, nullopt_t) { return (!x); } +template inline bool operator==(optional const &x, nullopt_t /*unused*/) { return (!x); } -template inline bool operator==(nullopt_t, optional const &x) { return (!x); } +template inline bool operator==(nullopt_t /*unused*/, optional const &x) { return (!x); } -template inline bool operator!=(optional const &x, nullopt_t) { return bool(x); } +template inline bool operator!=(optional const &x, nullopt_t /*unused*/) { return bool(x); } -template inline bool operator!=(nullopt_t, optional const &x) { return bool(x); } +template inline bool operator!=(nullopt_t /*unused*/, optional const &x) { return bool(x); } -template inline bool operator<(optional const &, nullopt_t) { return false; } +template inline bool operator<(optional const & /*unused*/, nullopt_t /*unused*/) { return false; } -template inline bool operator<(nullopt_t, optional const &x) { return bool(x); } +template inline bool operator<(nullopt_t /*unused*/, optional const &x) { return bool(x); } -template inline bool operator<=(optional const &x, nullopt_t) { return (!x); } +template inline bool operator<=(optional const &x, nullopt_t /*unused*/) { return (!x); } -template inline bool operator<=(nullopt_t, optional const &) { return true; } +template inline bool operator<=(nullopt_t /*unused*/, optional const & /*unused*/) { return true; } -template inline bool operator>(optional const &x, nullopt_t) { return bool(x); } +template inline bool operator>(optional const &x, nullopt_t /*unused*/) { return bool(x); } -template inline bool operator>(nullopt_t, optional const &) { return false; } +template inline bool operator>(nullopt_t /*unused*/, optional const & /*unused*/) { return false; } -template inline bool operator>=(optional const &, nullopt_t) { return true; } +template inline bool operator>=(optional const & /*unused*/, nullopt_t /*unused*/) { return true; } -template inline bool operator>=(nullopt_t, optional const &x) { return (!x); } +template inline bool operator>=(nullopt_t /*unused*/, optional const &x) { return (!x); } // Comparison with T From 8f093823672a49d63d9276c4072d2a3189d194d6 Mon Sep 17 00:00:00 2001 From: Philippe Wechsler <29612400+MadMonkey87@users.noreply.github.com> Date: Wed, 14 Aug 2024 04:25:45 +0200 Subject: [PATCH 1931/2101] support illuminance for airthings wave plus device (#5203) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- .../airthings_wave_plus/airthings_wave_plus.cpp | 7 +++++-- .../airthings_wave_plus/airthings_wave_plus.h | 2 ++ esphome/components/airthings_wave_plus/sensor.py | 12 ++++++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/esphome/components/airthings_wave_plus/airthings_wave_plus.cpp b/esphome/components/airthings_wave_plus/airthings_wave_plus.cpp index a32128e992..8c8c514fdb 100644 --- a/esphome/components/airthings_wave_plus/airthings_wave_plus.cpp +++ b/esphome/components/airthings_wave_plus/airthings_wave_plus.cpp @@ -14,8 +14,6 @@ void AirthingsWavePlus::read_sensors(uint8_t *raw_value, uint16_t value_len) { ESP_LOGD(TAG, "version = %d", value->version); if (value->version == 1) { - ESP_LOGD(TAG, "ambient light = %d", value->ambientLight); - if (this->humidity_sensor_ != nullptr) { this->humidity_sensor_->publish_state(value->humidity / 2.0f); } @@ -43,6 +41,10 @@ void AirthingsWavePlus::read_sensors(uint8_t *raw_value, uint16_t value_len) { if ((this->tvoc_sensor_ != nullptr) && this->is_valid_voc_value_(value->voc)) { this->tvoc_sensor_->publish_state(value->voc); } + + if (this->illuminance_sensor_ != nullptr) { + this->illuminance_sensor_->publish_state(value->ambientLight); + } } else { ESP_LOGE(TAG, "Invalid payload version (%d != 1, newer version or not a Wave Plus?)", value->version); } @@ -68,6 +70,7 @@ void AirthingsWavePlus::dump_config() { LOG_SENSOR(" ", "Radon", this->radon_sensor_); LOG_SENSOR(" ", "Radon Long Term", this->radon_long_term_sensor_); LOG_SENSOR(" ", "CO2", this->co2_sensor_); + LOG_SENSOR(" ", "Illuminance", this->illuminance_sensor_); } AirthingsWavePlus::AirthingsWavePlus() { diff --git a/esphome/components/airthings_wave_plus/airthings_wave_plus.h b/esphome/components/airthings_wave_plus/airthings_wave_plus.h index 23c8cbb166..bd7a40ef8b 100644 --- a/esphome/components/airthings_wave_plus/airthings_wave_plus.h +++ b/esphome/components/airthings_wave_plus/airthings_wave_plus.h @@ -22,6 +22,7 @@ class AirthingsWavePlus : public airthings_wave_base::AirthingsWaveBase { void set_radon(sensor::Sensor *radon) { radon_sensor_ = radon; } void set_radon_long_term(sensor::Sensor *radon_long_term) { radon_long_term_sensor_ = radon_long_term; } void set_co2(sensor::Sensor *co2) { co2_sensor_ = co2; } + void set_illuminance(sensor::Sensor *illuminance) { illuminance_sensor_ = illuminance; } protected: bool is_valid_radon_value_(uint16_t radon); @@ -32,6 +33,7 @@ class AirthingsWavePlus : public airthings_wave_base::AirthingsWaveBase { sensor::Sensor *radon_sensor_{nullptr}; sensor::Sensor *radon_long_term_sensor_{nullptr}; sensor::Sensor *co2_sensor_{nullptr}; + sensor::Sensor *illuminance_sensor_{nullptr}; struct WavePlusReadings { uint8_t version; diff --git a/esphome/components/airthings_wave_plus/sensor.py b/esphome/components/airthings_wave_plus/sensor.py index 643a2bfb68..d28c7e2abc 100644 --- a/esphome/components/airthings_wave_plus/sensor.py +++ b/esphome/components/airthings_wave_plus/sensor.py @@ -12,6 +12,9 @@ from esphome.const import ( CONF_CO2, UNIT_BECQUEREL_PER_CUBIC_METER, UNIT_PARTS_PER_MILLION, + CONF_ILLUMINANCE, + UNIT_LUX, + DEVICE_CLASS_ILLUMINANCE, ) DEPENDENCIES = airthings_wave_base.DEPENDENCIES @@ -45,6 +48,12 @@ CONFIG_SCHEMA = airthings_wave_base.BASE_SCHEMA.extend( device_class=DEVICE_CLASS_CARBON_DIOXIDE, 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, + ), } ) @@ -62,3 +71,6 @@ async def to_code(config): if config_co2 := config.get(CONF_CO2): sens = await sensor.new_sensor(config_co2) cg.add(var.set_co2(sens)) + if config_illuminance := config.get(CONF_ILLUMINANCE): + sens = await sensor.new_sensor(config_illuminance) + cg.add(var.set_illuminance(sens)) From d6f130e35ab2ecd0d2c09ef31459c205852aa751 Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt Date: Tue, 13 Aug 2024 23:40:07 -0400 Subject: [PATCH 1932/2101] [micro_wake_word] Bump ESPMicroSpeechFeatures version to 1.1.0 (#7249) --- .../components/micro_wake_word/__init__.py | 47 +++++++++---------- platformio.ini | 2 +- 2 files changed, 22 insertions(+), 27 deletions(-) diff --git a/esphome/components/micro_wake_word/__init__.py b/esphome/components/micro_wake_word/__init__.py index c2faca25f4..cd45f75b01 100644 --- a/esphome/components/micro_wake_word/__init__.py +++ b/esphome/components/micro_wake_word/__init__.py @@ -1,39 +1,34 @@ -import logging - -import json import hashlib -from urllib.parse import urljoin +import json +import logging from pathlib import Path +from urllib.parse import urljoin + import requests -import esphome.config_validation as cv -import esphome.codegen as cg - -from esphome.core import CORE, HexInt - -from esphome.components import esp32, microphone -from esphome import automation, git, external_files +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 +import esphome.config_validation as cv from esphome.const import ( - __version__, + CONF_FILE, CONF_ID, CONF_MICROPHONE, CONF_MODEL, - CONF_URL, - CONF_FILE, + CONF_PASSWORD, CONF_PATH, + CONF_RAW_DATA_ID, CONF_REF, CONF_REFRESH, CONF_TYPE, + CONF_URL, CONF_USERNAME, - CONF_PASSWORD, - CONF_RAW_DATA_ID, TYPE_GIT, TYPE_LOCAL, + __version__, ) - +from esphome.core import CORE, HexInt _LOGGER = logging.getLogger(__name__) @@ -174,12 +169,12 @@ def _convert_manifest_v1_to_v2(v1_manifest): CONF_SLIDING_WINDOW_AVERAGE_SIZE ] del v2_manifest[KEY_MICRO][CONF_SLIDING_WINDOW_AVERAGE_SIZE] - v2_manifest[KEY_MICRO][ - CONF_TENSOR_ARENA_SIZE - ] = 45672 # Original Inception-based V1 manifest models require a minimum of 45672 bytes - v2_manifest[KEY_MICRO][ - CONF_FEATURE_STEP_SIZE - ] = 20 # Original Inception-based V1 manifest models use a 20 ms feature step size + + # Original Inception-based V1 manifest models require a minimum of 45672 bytes + v2_manifest[KEY_MICRO][CONF_TENSOR_ARENA_SIZE] = 45672 + + # Original Inception-based V1 manifest models use a 20 ms feature step size + v2_manifest[KEY_MICRO][CONF_FEATURE_STEP_SIZE] = 20 return v2_manifest @@ -502,7 +497,7 @@ async def to_code(config): ) cg.add(var.set_features_step_size(manifest[KEY_MICRO][CONF_FEATURE_STEP_SIZE])) - cg.add_library("kahrendt/ESPMicroSpeechFeatures", "1.0.0") + cg.add_library("kahrendt/ESPMicroSpeechFeatures", "1.1.0") MICRO_WAKE_WORD_ACTION_SCHEMA = cv.Schema({cv.GenerateID(): cv.use_id(MicroWakeWord)}) diff --git a/platformio.ini b/platformio.ini index 87a239207f..4a0a3f2ef4 100644 --- a/platformio.ini +++ b/platformio.ini @@ -145,7 +145,7 @@ framework = espidf lib_deps = ${common:idf.lib_deps} droscy/esp_wireguard@0.4.2 ; wireguard - kahrendt/ESPMicroSpeechFeatures@1.0.0 ; micro_wake_word + kahrendt/ESPMicroSpeechFeatures@1.1.0 ; micro_wake_word build_flags = ${common:idf.build_flags} -Wno-nonnull-compare From cf6ea7cb2cf1636cb18e60ecf010fa6bb559c464 Mon Sep 17 00:00:00 2001 From: NP v/d Spek Date: Wed, 14 Aug 2024 05:42:43 +0200 Subject: [PATCH 1933/2101] Implement the finish() method and action. implement the is_stopped condition (#7255) --- .../i2s_audio/speaker/i2s_audio_speaker.cpp | 12 ++++++++++-- .../i2s_audio/speaker/i2s_audio_speaker.h | 2 ++ esphome/components/speaker/__init__.py | 19 ++++++++++++++----- esphome/components/speaker/automation.h | 10 ++++++++++ esphome/components/speaker/speaker.h | 5 +++++ tests/components/speaker/test.esp32-ard.yaml | 11 +++++++++-- .../components/speaker/test.esp32-c3-ard.yaml | 11 +++++++++-- .../components/speaker/test.esp32-c3-idf.yaml | 11 +++++++++-- tests/components/speaker/test.esp32-idf.yaml | 11 +++++++++-- 9 files changed, 77 insertions(+), 15 deletions(-) diff --git a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp index 1c6c50d8c9..cf5a2c2766 100644 --- a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +++ b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp @@ -180,7 +180,11 @@ void I2SAudioSpeaker::player_task(void *params) { } } -void I2SAudioSpeaker::stop() { +void I2SAudioSpeaker::stop() { this->stop_(false); } + +void I2SAudioSpeaker::finish() { this->stop_(true); } + +void I2SAudioSpeaker::stop_(bool wait_on_empty) { if (this->is_failed()) return; if (this->state_ == speaker::STATE_STOPPED) @@ -192,7 +196,11 @@ void I2SAudioSpeaker::stop() { this->state_ = speaker::STATE_STOPPING; DataEvent data; data.stop = true; - xQueueSendToFront(this->buffer_queue_, &data, portMAX_DELAY); + if (wait_on_empty) { + xQueueSend(this->buffer_queue_, &data, portMAX_DELAY); + } else { + xQueueSendToFront(this->buffer_queue_, &data, portMAX_DELAY); + } } void I2SAudioSpeaker::watch_() { diff --git a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h index 1800feaeec..0bdb67ceba 100644 --- a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +++ b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h @@ -53,6 +53,7 @@ class I2SAudioSpeaker : public Component, public speaker::Speaker, public I2SAud void start() override; void stop() override; + void finish() override; size_t play(const uint8_t *data, size_t length) override; @@ -60,6 +61,7 @@ class I2SAudioSpeaker : public Component, public speaker::Speaker, public I2SAud protected: void start_(); + void stop_(bool wait_on_empty); void watch_(); static void player_task(void *params); diff --git a/esphome/components/speaker/__init__.py b/esphome/components/speaker/__init__.py index 79d5df8c5a..d28b726d1f 100644 --- a/esphome/components/speaker/__init__.py +++ b/esphome/components/speaker/__init__.py @@ -1,13 +1,11 @@ from esphome import automation -import esphome.config_validation as cv -import esphome.codegen as cg - from esphome.automation import maybe_simple_id -from esphome.const import CONF_ID, CONF_DATA +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.const import CONF_DATA, CONF_ID from esphome.core import CORE from esphome.coroutine import coroutine_with_priority - CODEOWNERS = ["@jesserockz"] IS_PLATFORM_COMPONENT = True @@ -22,8 +20,12 @@ PlayAction = speaker_ns.class_( StopAction = speaker_ns.class_( "StopAction", automation.Action, cg.Parented.template(Speaker) ) +FinishAction = speaker_ns.class_( + "FinishAction", automation.Action, cg.Parented.template(Speaker) +) IsPlayingCondition = speaker_ns.class_("IsPlayingCondition", automation.Condition) +IsStoppedCondition = speaker_ns.class_("IsStoppedCondition", automation.Condition) async def setup_speaker_core_(var, config): @@ -75,11 +77,18 @@ async def speaker_play_action(config, action_id, template_arg, args): automation.register_action("speaker.stop", StopAction, SPEAKER_AUTOMATION_SCHEMA)( speaker_action ) +automation.register_action("speaker.finish", FinishAction, SPEAKER_AUTOMATION_SCHEMA)( + speaker_action +) automation.register_condition( "speaker.is_playing", IsPlayingCondition, SPEAKER_AUTOMATION_SCHEMA )(speaker_action) +automation.register_condition( + "speaker.is_stopped", IsStoppedCondition, SPEAKER_AUTOMATION_SCHEMA +)(speaker_action) + @coroutine_with_priority(100.0) async def to_code(config): diff --git a/esphome/components/speaker/automation.h b/esphome/components/speaker/automation.h index e28991a0d1..2716fe6100 100644 --- a/esphome/components/speaker/automation.h +++ b/esphome/components/speaker/automation.h @@ -39,10 +39,20 @@ template class StopAction : public Action, public Parente void play(Ts... x) override { this->parent_->stop(); } }; +template class FinishAction : public Action, public Parented { + public: + void play(Ts... x) override { this->parent_->finish(); } +}; + template class IsPlayingCondition : public Condition, public Parented { public: bool check(Ts... x) override { return this->parent_->is_running(); } }; +template class IsStoppedCondition : public Condition, public Parented { + public: + bool check(Ts... x) override { return this->parent_->is_stopped(); } +}; + } // namespace speaker } // namespace esphome diff --git a/esphome/components/speaker/speaker.h b/esphome/components/speaker/speaker.h index b494873160..142231881c 100644 --- a/esphome/components/speaker/speaker.h +++ b/esphome/components/speaker/speaker.h @@ -17,10 +17,15 @@ class Speaker { virtual void start() = 0; virtual void stop() = 0; + // In compare between *STOP()* and *FINISH()*; *FINISH()* will stop after emptying the play buffer, + // while *STOP()* will break directly. + // When finish() is not implemented on the plateform component it should just do a normal stop. + virtual void finish() { this->stop(); } virtual bool has_buffered_data() const = 0; bool is_running() const { return this->state_ == STATE_RUNNING; } + bool is_stopped() const { return this->state_ == STATE_STOPPED; } protected: State state_{STATE_STOPPED}; diff --git a/tests/components/speaker/test.esp32-ard.yaml b/tests/components/speaker/test.esp32-ard.yaml index 416e203d7b..e10c3e88c1 100644 --- a/tests/components/speaker/test.esp32-ard.yaml +++ b/tests/components/speaker/test.esp32-ard.yaml @@ -1,8 +1,15 @@ esphome: on_boot: then: - - speaker.play: [0, 1, 2, 3] - - speaker.stop + - if: + condition: speaker.is_stopped + then: + - speaker.play: [0, 1, 2, 3] + - if: + condition: speaker.is_playing + then: + - speaker.finish: + - speaker.stop: i2s_audio: i2s_lrclk_pin: 16 diff --git a/tests/components/speaker/test.esp32-c3-ard.yaml b/tests/components/speaker/test.esp32-c3-ard.yaml index c7809baace..08699d8b22 100644 --- a/tests/components/speaker/test.esp32-c3-ard.yaml +++ b/tests/components/speaker/test.esp32-c3-ard.yaml @@ -1,8 +1,15 @@ esphome: on_boot: then: - - speaker.play: [0, 1, 2, 3] - - speaker.stop + - if: + condition: speaker.is_stopped + then: + - speaker.play: [0, 1, 2, 3] + - if: + condition: speaker.is_playing + then: + - speaker.finish: + - speaker.stop: i2s_audio: i2s_lrclk_pin: 6 diff --git a/tests/components/speaker/test.esp32-c3-idf.yaml b/tests/components/speaker/test.esp32-c3-idf.yaml index c7809baace..08699d8b22 100644 --- a/tests/components/speaker/test.esp32-c3-idf.yaml +++ b/tests/components/speaker/test.esp32-c3-idf.yaml @@ -1,8 +1,15 @@ esphome: on_boot: then: - - speaker.play: [0, 1, 2, 3] - - speaker.stop + - if: + condition: speaker.is_stopped + then: + - speaker.play: [0, 1, 2, 3] + - if: + condition: speaker.is_playing + then: + - speaker.finish: + - speaker.stop: i2s_audio: i2s_lrclk_pin: 6 diff --git a/tests/components/speaker/test.esp32-idf.yaml b/tests/components/speaker/test.esp32-idf.yaml index 416e203d7b..e10c3e88c1 100644 --- a/tests/components/speaker/test.esp32-idf.yaml +++ b/tests/components/speaker/test.esp32-idf.yaml @@ -1,8 +1,15 @@ esphome: on_boot: then: - - speaker.play: [0, 1, 2, 3] - - speaker.stop + - if: + condition: speaker.is_stopped + then: + - speaker.play: [0, 1, 2, 3] + - if: + condition: speaker.is_playing + then: + - speaker.finish: + - speaker.stop: i2s_audio: i2s_lrclk_pin: 16 From ccf57488c5432372dcdb2e87072ed15a9c7953a4 Mon Sep 17 00:00:00 2001 From: Mike La Spina Date: Tue, 13 Aug 2024 23:43:35 -0500 Subject: [PATCH 1934/2101] Correct offset calibration (#7228) Co-authored-by: descipher Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- CODEOWNERS | 1 + esphome/components/atm90e32/__init__.py | 7 ++ esphome/components/atm90e32/atm90e32.cpp | 84 +++++++++++++++---- esphome/components/atm90e32/atm90e32.h | 27 ++++-- esphome/components/atm90e32/atm90e32_reg.h | 2 + .../components/atm90e32/button/__init__.py | 43 ++++++++++ .../atm90e32/button/atm90e32_button.cpp | 20 +++++ .../atm90e32/button/atm90e32_button.h | 27 ++++++ esphome/components/atm90e32/sensor.py | 26 +++--- tests/components/atm90e32/test.esp32-ard.yaml | 9 ++ .../atm90e32/test.esp32-c3-ard.yaml | 9 ++ .../atm90e32/test.esp32-c3-idf.yaml | 9 ++ tests/components/atm90e32/test.esp32-idf.yaml | 9 ++ .../components/atm90e32/test.esp8266-ard.yaml | 40 +++++++++ .../components/atm90e32/test.rp2040-ard.yaml | 9 ++ 15 files changed, 288 insertions(+), 34 deletions(-) create mode 100644 esphome/components/atm90e32/button/__init__.py create mode 100644 esphome/components/atm90e32/button/atm90e32_button.cpp create mode 100644 esphome/components/atm90e32/button/atm90e32_button.h diff --git a/CODEOWNERS b/CODEOWNERS index 3ea9c75ac2..1236c8d842 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -46,6 +46,7 @@ esphome/components/async_tcp/* @OttoWinter esphome/components/at581x/* @X-Ryl669 esphome/components/atc_mithermometer/* @ahpohl esphome/components/atm90e26/* @danieltwagner +esphome/components/atm90e32/* @circuitsetup @descipher esphome/components/b_parasite/* @rbaron esphome/components/ballu/* @bazuchan esphome/components/bang_bang/* @OttoWinter diff --git a/esphome/components/atm90e32/__init__.py b/esphome/components/atm90e32/__init__.py index e69de29bb2..8ce95be489 100644 --- a/esphome/components/atm90e32/__init__.py +++ b/esphome/components/atm90e32/__init__.py @@ -0,0 +1,7 @@ +import esphome.codegen as cg + +CODEOWNERS = ["@circuitsetup", "@descipher"] + +atm90e32_ns = cg.esphome_ns.namespace("atm90e32") + +CONF_ATM90E32_ID = "atm90e32_id" diff --git a/esphome/components/atm90e32/atm90e32.cpp b/esphome/components/atm90e32/atm90e32.cpp index e27459b18a..43647b1855 100644 --- a/esphome/components/atm90e32/atm90e32.cpp +++ b/esphome/components/atm90e32/atm90e32.cpp @@ -132,10 +132,77 @@ void ATM90E32Component::update() { this->status_clear_warning(); } +void ATM90E32Component::restore_calibrations_() { + if (enable_offset_calibration_) { + this->pref_.load(&this->offset_phase_); + } +}; + +void ATM90E32Component::run_offset_calibrations() { + // Run the calibrations and + // Setup voltage and current calibration offsets for PHASE A + this->offset_phase_[PHASEA].voltage_offset_ = calibrate_voltage_offset_phase(PHASEA); + this->phase_[PHASEA].voltage_offset_ = this->offset_phase_[PHASEA].voltage_offset_; + this->write16_(ATM90E32_REGISTER_UOFFSETA, this->phase_[PHASEA].voltage_offset_); // C Voltage offset + this->offset_phase_[PHASEA].current_offset_ = calibrate_current_offset_phase(PHASEA); + this->phase_[PHASEA].current_offset_ = this->offset_phase_[PHASEA].current_offset_; + this->write16_(ATM90E32_REGISTER_IOFFSETA, this->phase_[PHASEA].current_offset_); // C Current offset + // Setup voltage and current calibration offsets for PHASE B + this->offset_phase_[PHASEB].voltage_offset_ = calibrate_voltage_offset_phase(PHASEB); + this->phase_[PHASEB].voltage_offset_ = this->offset_phase_[PHASEB].voltage_offset_; + this->write16_(ATM90E32_REGISTER_UOFFSETB, this->phase_[PHASEB].voltage_offset_); // C Voltage offset + this->offset_phase_[PHASEB].current_offset_ = calibrate_current_offset_phase(PHASEB); + this->phase_[PHASEB].current_offset_ = this->offset_phase_[PHASEB].current_offset_; + this->write16_(ATM90E32_REGISTER_IOFFSETB, this->phase_[PHASEB].current_offset_); // C Current offset + // Setup voltage and current calibration offsets for PHASE C + this->offset_phase_[PHASEC].voltage_offset_ = calibrate_voltage_offset_phase(PHASEC); + this->phase_[PHASEC].voltage_offset_ = this->offset_phase_[PHASEC].voltage_offset_; + this->write16_(ATM90E32_REGISTER_UOFFSETC, this->phase_[PHASEC].voltage_offset_); // C Voltage offset + this->offset_phase_[PHASEC].current_offset_ = calibrate_current_offset_phase(PHASEC); + this->phase_[PHASEC].current_offset_ = this->offset_phase_[PHASEC].current_offset_; + this->write16_(ATM90E32_REGISTER_IOFFSETC, this->phase_[PHASEC].current_offset_); // C Current offset + this->pref_.save(&this->offset_phase_); + ESP_LOGI(TAG, "PhaseA Vo=%5d PhaseB Vo=%5d PhaseC Vo=%5d", this->offset_phase_[PHASEA].voltage_offset_, + this->offset_phase_[PHASEB].voltage_offset_, this->offset_phase_[PHASEC].voltage_offset_); + ESP_LOGI(TAG, "PhaseA Io=%5d PhaseB Io=%5d PhaseC Io=%5d", this->offset_phase_[PHASEA].current_offset_, + this->offset_phase_[PHASEB].current_offset_, this->offset_phase_[PHASEC].current_offset_); +} + +void ATM90E32Component::clear_offset_calibrations() { + // Clear the calibrations and + this->offset_phase_[PHASEA].voltage_offset_ = 0; + this->phase_[PHASEA].voltage_offset_ = this->offset_phase_[PHASEA].voltage_offset_; + this->write16_(ATM90E32_REGISTER_UOFFSETA, this->phase_[PHASEA].voltage_offset_); // C Voltage offset + this->offset_phase_[PHASEA].current_offset_ = 0; + this->phase_[PHASEA].current_offset_ = this->offset_phase_[PHASEA].current_offset_; + this->write16_(ATM90E32_REGISTER_IOFFSETA, this->phase_[PHASEA].current_offset_); // C Current offset + this->offset_phase_[PHASEB].voltage_offset_ = 0; + this->phase_[PHASEB].voltage_offset_ = this->offset_phase_[PHASEB].voltage_offset_; + this->write16_(ATM90E32_REGISTER_UOFFSETB, this->phase_[PHASEB].voltage_offset_); // C Voltage offset + this->offset_phase_[PHASEB].current_offset_ = 0; + this->phase_[PHASEB].current_offset_ = this->offset_phase_[PHASEB].current_offset_; + this->write16_(ATM90E32_REGISTER_IOFFSETB, this->phase_[PHASEB].current_offset_); // C Current offset + this->offset_phase_[PHASEC].voltage_offset_ = 0; + this->phase_[PHASEC].voltage_offset_ = this->offset_phase_[PHASEC].voltage_offset_; + this->write16_(ATM90E32_REGISTER_UOFFSETC, this->phase_[PHASEC].voltage_offset_); // C Voltage offset + this->offset_phase_[PHASEC].current_offset_ = 0; + this->phase_[PHASEC].current_offset_ = this->offset_phase_[PHASEC].current_offset_; + this->write16_(ATM90E32_REGISTER_IOFFSETC, this->phase_[PHASEC].current_offset_); // C Current offset + this->pref_.save(&this->offset_phase_); + ESP_LOGI(TAG, "PhaseA Vo=%5d PhaseB Vo=%5d PhaseC Vo=%5d", this->offset_phase_[PHASEA].voltage_offset_, + this->offset_phase_[PHASEB].voltage_offset_, this->offset_phase_[PHASEC].voltage_offset_); + ESP_LOGI(TAG, "PhaseA Io=%5d PhaseB Io=%5d PhaseC Io=%5d", this->offset_phase_[PHASEA].current_offset_, + this->offset_phase_[PHASEB].current_offset_, this->offset_phase_[PHASEC].current_offset_); +} + void ATM90E32Component::setup() { ESP_LOGCONFIG(TAG, "Setting up ATM90E32 Component..."); this->spi_setup(); - + if (this->enable_offset_calibration_) { + uint32_t hash = fnv1_hash(App.get_friendly_name()); + this->pref_ = global_preferences->make_preference(hash, true); + this->restore_calibrations_(); + } uint16_t mmode0 = 0x87; // 3P4W 50Hz if (line_freq_ == 60) { mmode0 |= 1 << 12; // sets 12th bit to 1, 60Hz @@ -167,27 +234,12 @@ void ATM90E32Component::setup() { this->write16_(ATM90E32_REGISTER_SSTARTTH, 0x1D4C); // All Reactive Startup Power Threshold - 50% this->write16_(ATM90E32_REGISTER_PPHASETH, 0x02EE); // Each Phase Active Phase Threshold - 0.002A/0.00032 = 750 this->write16_(ATM90E32_REGISTER_QPHASETH, 0x02EE); // Each phase Reactive Phase Threshold - 10% - // Setup voltage and current calibration offsets for PHASE A - this->phase_[PHASEA].voltage_offset_ = calibrate_voltage_offset_phase(PHASEA); - this->write16_(ATM90E32_REGISTER_UOFFSETA, this->phase_[PHASEA].voltage_offset_); // A Voltage offset - this->phase_[PHASEA].current_offset_ = calibrate_current_offset_phase(PHASEA); - this->write16_(ATM90E32_REGISTER_IOFFSETA, this->phase_[PHASEA].current_offset_); // A Current offset // Setup voltage and current gain for PHASE A this->write16_(ATM90E32_REGISTER_UGAINA, this->phase_[PHASEA].voltage_gain_); // A Voltage rms gain this->write16_(ATM90E32_REGISTER_IGAINA, this->phase_[PHASEA].ct_gain_); // A line current gain - // Setup voltage and current calibration offsets for PHASE B - this->phase_[PHASEB].voltage_offset_ = calibrate_voltage_offset_phase(PHASEB); - this->write16_(ATM90E32_REGISTER_UOFFSETB, this->phase_[PHASEB].voltage_offset_); // B Voltage offset - this->phase_[PHASEB].current_offset_ = calibrate_current_offset_phase(PHASEB); - this->write16_(ATM90E32_REGISTER_IOFFSETB, this->phase_[PHASEB].current_offset_); // B Current offset // Setup voltage and current gain for PHASE B this->write16_(ATM90E32_REGISTER_UGAINB, this->phase_[PHASEB].voltage_gain_); // B Voltage rms gain this->write16_(ATM90E32_REGISTER_IGAINB, this->phase_[PHASEB].ct_gain_); // B line current gain - // Setup voltage and current calibration offsets for PHASE C - this->phase_[PHASEC].voltage_offset_ = calibrate_voltage_offset_phase(PHASEC); - this->write16_(ATM90E32_REGISTER_UOFFSETC, this->phase_[PHASEC].voltage_offset_); // C Voltage offset - this->phase_[PHASEC].current_offset_ = calibrate_current_offset_phase(PHASEC); - this->write16_(ATM90E32_REGISTER_IOFFSETC, this->phase_[PHASEC].current_offset_); // C Current offset // Setup voltage and current gain for PHASE C this->write16_(ATM90E32_REGISTER_UGAINC, this->phase_[PHASEC].voltage_gain_); // C Voltage rms gain this->write16_(ATM90E32_REGISTER_IGAINC, this->phase_[PHASEC].ct_gain_); // C line current gain diff --git a/esphome/components/atm90e32/atm90e32.h b/esphome/components/atm90e32/atm90e32.h index 0a334dbe8b..35c61d1e05 100644 --- a/esphome/components/atm90e32/atm90e32.h +++ b/esphome/components/atm90e32/atm90e32.h @@ -1,9 +1,12 @@ #pragma once -#include "esphome/core/component.h" +#include "atm90e32_reg.h" #include "esphome/components/sensor/sensor.h" #include "esphome/components/spi/spi.h" -#include "atm90e32_reg.h" +#include "esphome/core/application.h" +#include "esphome/core/component.h" +#include "esphome/core/helpers.h" +#include "esphome/core/preferences.h" namespace esphome { namespace atm90e32 { @@ -20,7 +23,6 @@ class ATM90E32Component : public PollingComponent, void dump_config() override; float get_setup_priority() const override; void update() override; - void set_voltage_sensor(int phase, sensor::Sensor *obj) { this->phase_[phase].voltage_sensor_ = obj; } void set_current_sensor(int phase, sensor::Sensor *obj) { this->phase_[phase].current_sensor_ = obj; } void set_power_sensor(int phase, sensor::Sensor *obj) { this->phase_[phase].power_sensor_ = obj; } @@ -48,9 +50,11 @@ class ATM90E32Component : public PollingComponent, void set_line_freq(int freq) { line_freq_ = freq; } void set_current_phases(int phases) { current_phases_ = phases; } void set_pga_gain(uint16_t gain) { pga_gain_ = gain; } + void run_offset_calibrations(); + void clear_offset_calibrations(); + void set_enable_offset_calibration(bool flag) { enable_offset_calibration_ = flag; } uint16_t calibrate_voltage_offset_phase(uint8_t /*phase*/); uint16_t calibrate_current_offset_phase(uint8_t /*phase*/); - int32_t last_periodic_millis = millis(); protected: @@ -83,10 +87,11 @@ class ATM90E32Component : public PollingComponent, float get_chip_temperature_(); bool get_publish_interval_flag_() { return publish_interval_flag_; }; void set_publish_interval_flag_(bool flag) { publish_interval_flag_ = flag; }; + void restore_calibrations_(); struct ATM90E32Phase { - uint16_t voltage_gain_{7305}; - uint16_t ct_gain_{27961}; + uint16_t voltage_gain_{0}; + uint16_t ct_gain_{0}; uint16_t voltage_offset_{0}; uint16_t current_offset_{0}; float voltage_{0}; @@ -114,13 +119,21 @@ class ATM90E32Component : public PollingComponent, uint32_t cumulative_reverse_active_energy_{0}; } phase_[3]; + struct Calibration { + uint16_t voltage_offset_{0}; + uint16_t current_offset_{0}; + } offset_phase_[3]; + + ESPPreferenceObject pref_; + sensor::Sensor *freq_sensor_{nullptr}; sensor::Sensor *chip_temperature_sensor_{nullptr}; uint16_t pga_gain_{0x15}; int line_freq_{60}; int current_phases_{3}; - bool publish_interval_flag_{true}; + bool publish_interval_flag_{false}; bool peak_current_signed_{false}; + bool enable_offset_calibration_{false}; }; } // namespace atm90e32 diff --git a/esphome/components/atm90e32/atm90e32_reg.h b/esphome/components/atm90e32/atm90e32_reg.h index dac62aa6b4..954fb42e79 100644 --- a/esphome/components/atm90e32/atm90e32_reg.h +++ b/esphome/components/atm90e32/atm90e32_reg.h @@ -1,5 +1,7 @@ #pragma once +#include + namespace esphome { namespace atm90e32 { diff --git a/esphome/components/atm90e32/button/__init__.py b/esphome/components/atm90e32/button/__init__.py new file mode 100644 index 0000000000..931346b386 --- /dev/null +++ b/esphome/components/atm90e32/button/__init__.py @@ -0,0 +1,43 @@ +import esphome.codegen as cg +from esphome.components import button +import esphome.config_validation as cv +from esphome.const import CONF_ID, ENTITY_CATEGORY_CONFIG, ICON_CHIP, ICON_SCALE + +from .. import atm90e32_ns +from ..sensor import ATM90E32Component + +CONF_RUN_OFFSET_CALIBRATION = "run_offset_calibration" +CONF_CLEAR_OFFSET_CALIBRATION = "clear_offset_calibration" + +ATM90E32CalibrationButton = atm90e32_ns.class_( + "ATM90E32CalibrationButton", + button.Button, +) +ATM90E32ClearCalibrationButton = atm90e32_ns.class_( + "ATM90E32ClearCalibrationButton", + button.Button, +) + +CONFIG_SCHEMA = { + cv.GenerateID(CONF_ID): cv.use_id(ATM90E32Component), + cv.Optional(CONF_RUN_OFFSET_CALIBRATION): button.button_schema( + ATM90E32CalibrationButton, + entity_category=ENTITY_CATEGORY_CONFIG, + icon=ICON_SCALE, + ), + cv.Optional(CONF_CLEAR_OFFSET_CALIBRATION): button.button_schema( + ATM90E32ClearCalibrationButton, + entity_category=ENTITY_CATEGORY_CONFIG, + icon=ICON_CHIP, + ), +} + + +async def to_code(config): + parent = await cg.get_variable(config[CONF_ID]) + if run_offset := config.get(CONF_RUN_OFFSET_CALIBRATION): + b = await button.new_button(run_offset) + await cg.register_parented(b, parent) + if clear_offset := config.get(CONF_CLEAR_OFFSET_CALIBRATION): + b = await button.new_button(clear_offset) + await cg.register_parented(b, parent) diff --git a/esphome/components/atm90e32/button/atm90e32_button.cpp b/esphome/components/atm90e32/button/atm90e32_button.cpp new file mode 100644 index 0000000000..00715b61dd --- /dev/null +++ b/esphome/components/atm90e32/button/atm90e32_button.cpp @@ -0,0 +1,20 @@ +#include "atm90e32_button.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace atm90e32 { + +static const char *const TAG = "atm90e32.button"; + +void ATM90E32CalibrationButton::press_action() { + ESP_LOGI(TAG, "Running offset calibrations, Note: CTs and ACVs must be 0 during this process..."); + this->parent_->run_offset_calibrations(); +} + +void ATM90E32ClearCalibrationButton::press_action() { + ESP_LOGI(TAG, "Offset calibrations cleared."); + this->parent_->clear_offset_calibrations(); +} + +} // namespace atm90e32 +} // namespace esphome diff --git a/esphome/components/atm90e32/button/atm90e32_button.h b/esphome/components/atm90e32/button/atm90e32_button.h new file mode 100644 index 0000000000..0617099457 --- /dev/null +++ b/esphome/components/atm90e32/button/atm90e32_button.h @@ -0,0 +1,27 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/components/atm90e32/atm90e32.h" +#include "esphome/components/button/button.h" + +namespace esphome { +namespace atm90e32 { + +class ATM90E32CalibrationButton : public button::Button, public Parented { + public: + ATM90E32CalibrationButton() = default; + + protected: + void press_action() override; +}; + +class ATM90E32ClearCalibrationButton : public button::Button, public Parented { + public: + ATM90E32ClearCalibrationButton() = default; + + protected: + void press_action() override; +}; + +} // namespace atm90e32 +} // namespace esphome diff --git a/esphome/components/atm90e32/sensor.py b/esphome/components/atm90e32/sensor.py index 2bc7f0498d..be2196223c 100644 --- a/esphome/components/atm90e32/sensor.py +++ b/esphome/components/atm90e32/sensor.py @@ -1,21 +1,21 @@ import esphome.codegen as cg -import esphome.config_validation as cv from esphome.components import sensor, spi +import esphome.config_validation as cv from esphome.const import ( - CONF_ID, - CONF_REACTIVE_POWER, - CONF_VOLTAGE, + CONF_APPARENT_POWER, CONF_CURRENT, + CONF_FORWARD_ACTIVE_ENERGY, + CONF_FREQUENCY, + CONF_ID, CONF_PHASE_A, + CONF_PHASE_ANGLE, CONF_PHASE_B, CONF_PHASE_C, - CONF_PHASE_ANGLE, CONF_POWER, CONF_POWER_FACTOR, - CONF_APPARENT_POWER, - CONF_FREQUENCY, - CONF_FORWARD_ACTIVE_ENERGY, + CONF_REACTIVE_POWER, CONF_REVERSE_ACTIVE_ENERGY, + CONF_VOLTAGE, DEVICE_CLASS_CURRENT, DEVICE_CLASS_ENERGY, DEVICE_CLASS_POWER, @@ -23,13 +23,13 @@ from esphome.const import ( DEVICE_CLASS_TEMPERATURE, DEVICE_CLASS_VOLTAGE, ENTITY_CATEGORY_DIAGNOSTIC, - ICON_LIGHTBULB, ICON_CURRENT_AC, + ICON_LIGHTBULB, STATE_CLASS_MEASUREMENT, STATE_CLASS_TOTAL_INCREASING, UNIT_AMPERE, - UNIT_DEGREES, UNIT_CELSIUS, + UNIT_DEGREES, UNIT_HERTZ, UNIT_VOLT, UNIT_VOLT_AMPS_REACTIVE, @@ -37,6 +37,8 @@ from esphome.const import ( UNIT_WATT_HOURS, ) +from . import atm90e32_ns + CONF_LINE_FREQUENCY = "line_frequency" CONF_CHIP_TEMPERATURE = "chip_temperature" CONF_GAIN_PGA = "gain_pga" @@ -46,6 +48,7 @@ CONF_GAIN_CT = "gain_ct" CONF_HARMONIC_POWER = "harmonic_power" CONF_PEAK_CURRENT = "peak_current" CONF_PEAK_CURRENT_SIGNED = "peak_current_signed" +CONF_ENABLE_OFFSET_CALIBRATION = "enable_offset_calibration" UNIT_DEG = "degrees" LINE_FREQS = { "50HZ": 50, @@ -61,7 +64,6 @@ PGA_GAINS = { "4X": 0x2A, } -atm90e32_ns = cg.esphome_ns.namespace("atm90e32") ATM90E32Component = atm90e32_ns.class_( "ATM90E32Component", cg.PollingComponent, spi.SPIDevice ) @@ -164,6 +166,7 @@ CONFIG_SCHEMA = ( ), cv.Optional(CONF_GAIN_PGA, default="2X"): cv.enum(PGA_GAINS, upper=True), cv.Optional(CONF_PEAK_CURRENT_SIGNED, default=False): cv.boolean, + cv.Optional(CONF_ENABLE_OFFSET_CALIBRATION, default=False): cv.boolean, } ) .extend(cv.polling_component_schema("60s")) @@ -227,3 +230,4 @@ async def to_code(config): cg.add(var.set_current_phases(config[CONF_CURRENT_PHASES])) cg.add(var.set_pga_gain(config[CONF_GAIN_PGA])) cg.add(var.set_peak_current_signed(config[CONF_PEAK_CURRENT_SIGNED])) + cg.add(var.set_enable_offset_calibration(config[CONF_ENABLE_OFFSET_CALIBRATION])) diff --git a/tests/components/atm90e32/test.esp32-ard.yaml b/tests/components/atm90e32/test.esp32-ard.yaml index 131270f8ad..3bdc2bcec6 100644 --- a/tests/components/atm90e32/test.esp32-ard.yaml +++ b/tests/components/atm90e32/test.esp32-ard.yaml @@ -7,6 +7,7 @@ spi: sensor: - platform: atm90e32 cs_pin: 13 + id: chip1 phase_a: voltage: name: EMON Line Voltage A @@ -49,3 +50,11 @@ sensor: line_frequency: 60Hz current_phases: 3 gain_pga: 2X + enable_offset_calibration: True +button: + - platform: atm90e32 + id: chip1 + run_offset_calibration: + name: "Chip1 - Run Offset Calibration" + clear_offset_calibration: + name: "Chip1 - Clear Offset Calibration" diff --git a/tests/components/atm90e32/test.esp32-c3-ard.yaml b/tests/components/atm90e32/test.esp32-c3-ard.yaml index 263fb6d24e..9ec0037a61 100644 --- a/tests/components/atm90e32/test.esp32-c3-ard.yaml +++ b/tests/components/atm90e32/test.esp32-c3-ard.yaml @@ -7,6 +7,7 @@ spi: sensor: - platform: atm90e32 cs_pin: 8 + id: chip1 phase_a: voltage: name: EMON Line Voltage A @@ -49,3 +50,11 @@ sensor: line_frequency: 60Hz current_phases: 3 gain_pga: 2X + enable_offset_calibration: True +button: + - platform: atm90e32 + id: chip1 + run_offset_calibration: + name: "Chip1 - Run Offset Calibration" + clear_offset_calibration: + name: "Chip1 - Clear Offset Calibration" diff --git a/tests/components/atm90e32/test.esp32-c3-idf.yaml b/tests/components/atm90e32/test.esp32-c3-idf.yaml index 263fb6d24e..9ec0037a61 100644 --- a/tests/components/atm90e32/test.esp32-c3-idf.yaml +++ b/tests/components/atm90e32/test.esp32-c3-idf.yaml @@ -7,6 +7,7 @@ spi: sensor: - platform: atm90e32 cs_pin: 8 + id: chip1 phase_a: voltage: name: EMON Line Voltage A @@ -49,3 +50,11 @@ sensor: line_frequency: 60Hz current_phases: 3 gain_pga: 2X + enable_offset_calibration: True +button: + - platform: atm90e32 + id: chip1 + run_offset_calibration: + name: "Chip1 - Run Offset Calibration" + clear_offset_calibration: + name: "Chip1 - Clear Offset Calibration" diff --git a/tests/components/atm90e32/test.esp32-idf.yaml b/tests/components/atm90e32/test.esp32-idf.yaml index 131270f8ad..3bdc2bcec6 100644 --- a/tests/components/atm90e32/test.esp32-idf.yaml +++ b/tests/components/atm90e32/test.esp32-idf.yaml @@ -7,6 +7,7 @@ spi: sensor: - platform: atm90e32 cs_pin: 13 + id: chip1 phase_a: voltage: name: EMON Line Voltage A @@ -49,3 +50,11 @@ sensor: line_frequency: 60Hz current_phases: 3 gain_pga: 2X + enable_offset_calibration: True +button: + - platform: atm90e32 + id: chip1 + run_offset_calibration: + name: "Chip1 - Run Offset Calibration" + clear_offset_calibration: + name: "Chip1 - Clear Offset Calibration" diff --git a/tests/components/atm90e32/test.esp8266-ard.yaml b/tests/components/atm90e32/test.esp8266-ard.yaml index e8e2abc1a9..fbb3368efa 100644 --- a/tests/components/atm90e32/test.esp8266-ard.yaml +++ b/tests/components/atm90e32/test.esp8266-ard.yaml @@ -7,6 +7,7 @@ spi: sensor: - platform: atm90e32 cs_pin: 5 + id: chip1 phase_a: voltage: name: EMON Line Voltage A @@ -49,3 +50,42 @@ sensor: line_frequency: 60Hz current_phases: 3 gain_pga: 2X + enable_offset_calibration: True + - platform: atm90e32 + cs_pin: 4 + id: chip2 + phase_a: + voltage: + name: EMON Line Voltage A + current: + name: EMON CT1 Current + power: + name: EMON Active Power CT1 + reactive_power: + name: EMON Reactive Power CT1 + power_factor: + name: EMON Power Factor CT1 + gain_voltage: 7305 + gain_ct: 27961 + phase_c: + voltage: + name: EMON Line Voltage C + current: + name: EMON CT2 Current + power: + name: EMON Active Power CT2 + reactive_power: + name: EMON Reactive Power CT2 + power_factor: + name: EMON Power Factor CT2 + gain_voltage: 7305 + gain_ct: 27961 + line_frequency: 60Hz + current_phases: 2 +button: + - platform: atm90e32 + id: chip1 + run_offset_calibration: + name: "Chip1 - Run Offset Calibration" + clear_offset_calibration: + name: "Chip1 - Clear Offset Calibration" diff --git a/tests/components/atm90e32/test.rp2040-ard.yaml b/tests/components/atm90e32/test.rp2040-ard.yaml index 525e0b801a..a6b7956da7 100644 --- a/tests/components/atm90e32/test.rp2040-ard.yaml +++ b/tests/components/atm90e32/test.rp2040-ard.yaml @@ -7,6 +7,7 @@ spi: sensor: - platform: atm90e32 cs_pin: 5 + id: chip1 phase_a: voltage: name: EMON Line Voltage A @@ -49,3 +50,11 @@ sensor: line_frequency: 60Hz current_phases: 3 gain_pga: 2X + enable_offset_calibration: True +button: + - platform: atm90e32 + id: chip1 + run_offset_calibration: + name: "Chip1 - Run Offset Calibration" + clear_offset_calibration: + name: "Chip1 - Clear Offset Calibration" From 350f17e48f60cdd7100945c82a14e284adf517b5 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 14 Aug 2024 16:56:53 +1200 Subject: [PATCH 1935/2101] Bump version to 2024.9.0-dev --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 37f20796b5..6157ce32f7 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.8.0-dev" +__version__ = "2024.9.0-dev" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 7b233d6871eef2a9860b994940ee6669560e576c Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 14 Aug 2024 16:56:53 +1200 Subject: [PATCH 1936/2101] Bump version to 2024.8.0b1 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 37f20796b5..47aacd6452 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.8.0-dev" +__version__ = "2024.8.0b1" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 7133e08755fb9c65abc62af9dc0df47900caa0a3 Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Wed, 14 Aug 2024 00:55:23 -0700 Subject: [PATCH 1937/2101] remove extra number from pronto (#7263) --- esphome/components/remote_base/pronto_protocol.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/esphome/components/remote_base/pronto_protocol.cpp b/esphome/components/remote_base/pronto_protocol.cpp index 625af76235..35fd782248 100644 --- a/esphome/components/remote_base/pronto_protocol.cpp +++ b/esphome/components/remote_base/pronto_protocol.cpp @@ -201,9 +201,6 @@ std::string ProntoProtocol::compensate_and_dump_sequence_(const RawTimings &data out += dump_duration_(t_duration, timebase); } - // append minimum gap - out += dump_duration_(PRONTO_DEFAULT_GAP, timebase, true); - return out; } From 80a0f137224c82fdc3cf17dfdd5dd3683ad9e796 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Wed, 14 Aug 2024 23:05:16 +0200 Subject: [PATCH 1938/2101] [code-quality] fix performance-unnecessary-value-param (#7274) --- esphome/components/lvgl/number/lvgl_number.h | 4 +++- esphome/components/lvgl/select/lvgl_select.h | 4 +++- esphome/components/lvgl/switch/lvgl_switch.h | 4 +++- esphome/components/lvgl/text/lvgl_text.h | 4 +++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/esphome/components/lvgl/number/lvgl_number.h b/esphome/components/lvgl/number/lvgl_number.h index a70c9eab9c..77fadd2a29 100644 --- a/esphome/components/lvgl/number/lvgl_number.h +++ b/esphome/components/lvgl/number/lvgl_number.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "esphome/components/number/number.h" #include "esphome/core/automation.h" #include "esphome/core/component.h" @@ -11,7 +13,7 @@ namespace lvgl { class LVGLNumber : public number::Number { public: void set_control_lambda(std::function control_lambda) { - this->control_lambda_ = control_lambda; + this->control_lambda_ = std::move(control_lambda); if (this->initial_state_.has_value()) { this->control_lambda_(this->initial_state_.value()); this->initial_state_.reset(); diff --git a/esphome/components/lvgl/select/lvgl_select.h b/esphome/components/lvgl/select/lvgl_select.h index 407045d605..97cc8697eb 100644 --- a/esphome/components/lvgl/select/lvgl_select.h +++ b/esphome/components/lvgl/select/lvgl_select.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "esphome/components/select/select.h" #include "esphome/core/automation.h" #include "esphome/core/component.h" @@ -28,7 +30,7 @@ static std::vector split_string(const std::string &str) { class LVGLSelect : public select::Select { public: void set_control_lambda(std::function lambda) { - this->control_lambda_ = lambda; + this->control_lambda_ = std::move(lambda); if (this->initial_state_.has_value()) { this->control(this->initial_state_.value()); this->initial_state_.reset(); diff --git a/esphome/components/lvgl/switch/lvgl_switch.h b/esphome/components/lvgl/switch/lvgl_switch.h index dbc885219b..af839b8892 100644 --- a/esphome/components/lvgl/switch/lvgl_switch.h +++ b/esphome/components/lvgl/switch/lvgl_switch.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "esphome/components/switch/switch.h" #include "esphome/core/automation.h" #include "esphome/core/component.h" @@ -11,7 +13,7 @@ namespace lvgl { class LVGLSwitch : public switch_::Switch { public: void set_control_lambda(std::function state_lambda) { - this->state_lambda_ = state_lambda; + this->state_lambda_ = std::move(state_lambda); if (this->initial_state_.has_value()) { this->state_lambda_(this->initial_state_.value()); this->initial_state_.reset(); diff --git a/esphome/components/lvgl/text/lvgl_text.h b/esphome/components/lvgl/text/lvgl_text.h index d3513c3697..4c380d69a2 100644 --- a/esphome/components/lvgl/text/lvgl_text.h +++ b/esphome/components/lvgl/text/lvgl_text.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "esphome/components/text/text.h" #include "esphome/core/automation.h" #include "esphome/core/component.h" @@ -11,7 +13,7 @@ namespace lvgl { class LVGLText : public text::Text { public: void set_control_lambda(std::function control_lambda) { - this->control_lambda_ = control_lambda; + this->control_lambda_ = std::move(control_lambda); if (this->initial_state_.has_value()) { this->control_lambda_(this->initial_state_.value()); this->initial_state_.reset(); From 5646ec7f9c601b5b3a0c1917edeae5b4487eff79 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Wed, 14 Aug 2024 23:41:29 +0200 Subject: [PATCH 1939/2101] [code-quality] fix clang-tidy prometheus (#7284) --- esphome/components/prometheus/prometheus_handler.cpp | 2 ++ esphome/components/prometheus/prometheus_handler.h | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/esphome/components/prometheus/prometheus_handler.cpp b/esphome/components/prometheus/prometheus_handler.cpp index 09913bd713..3e9cf81e6e 100644 --- a/esphome/components/prometheus/prometheus_handler.cpp +++ b/esphome/components/prometheus/prometheus_handler.cpp @@ -1,4 +1,5 @@ #include "prometheus_handler.h" +#ifdef USE_NETWORK #include "esphome/core/application.h" namespace esphome { @@ -350,3 +351,4 @@ void PrometheusHandler::lock_row_(AsyncResponseStream *stream, lock::Lock *obj) } // namespace prometheus } // namespace esphome +#endif diff --git a/esphome/components/prometheus/prometheus_handler.h b/esphome/components/prometheus/prometheus_handler.h index a9505a3572..f5e49a1419 100644 --- a/esphome/components/prometheus/prometheus_handler.h +++ b/esphome/components/prometheus/prometheus_handler.h @@ -1,5 +1,6 @@ #pragma once - +#include "esphome/core/defines.h" +#ifdef USE_NETWORK #include #include @@ -117,3 +118,4 @@ class PrometheusHandler : public AsyncWebHandler, public Component { } // namespace prometheus } // namespace esphome +#endif From 1bc3ccd96907ff392d4e321e5cc1e5833e107ccd Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Thu, 15 Aug 2024 00:30:29 +0200 Subject: [PATCH 1940/2101] [code-quality] fix clang-tidy ota (#7282) --- esphome/components/esphome/ota/ota_esphome.cpp | 3 ++- esphome/components/esphome/ota/ota_esphome.h | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/esphome/components/esphome/ota/ota_esphome.cpp b/esphome/components/esphome/ota/ota_esphome.cpp index 9d5044aaeb..7e2ef42a97 100644 --- a/esphome/components/esphome/ota/ota_esphome.cpp +++ b/esphome/components/esphome/ota/ota_esphome.cpp @@ -1,5 +1,5 @@ #include "ota_esphome.h" - +#ifdef USE_OTA #include "esphome/components/md5/md5.h" #include "esphome/components/network/util.h" #include "esphome/components/ota/ota_backend.h" @@ -410,3 +410,4 @@ float ESPHomeOTAComponent::get_setup_priority() const { return setup_priority::A uint16_t ESPHomeOTAComponent::get_port() const { return this->port_; } void ESPHomeOTAComponent::set_port(uint16_t port) { this->port_ = port; } } // namespace esphome +#endif diff --git a/esphome/components/esphome/ota/ota_esphome.h b/esphome/components/esphome/ota/ota_esphome.h index 42629b4346..e0d09ff37e 100644 --- a/esphome/components/esphome/ota/ota_esphome.h +++ b/esphome/components/esphome/ota/ota_esphome.h @@ -1,6 +1,7 @@ #pragma once #include "esphome/core/defines.h" +#ifdef USE_OTA #include "esphome/core/helpers.h" #include "esphome/core/preferences.h" #include "esphome/components/ota/ota_backend.h" @@ -41,3 +42,4 @@ class ESPHomeOTAComponent : public ota::OTAComponent { }; } // namespace esphome +#endif From ce7adbae995ecd4dbb3368678d6de5be9d1d4855 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Thu, 15 Aug 2024 00:31:19 +0200 Subject: [PATCH 1941/2101] [code-quality] fix clang-tidy e131 (#7281) --- esphome/components/e131/e131.cpp | 2 ++ esphome/components/e131/e131.h | 4 +++- esphome/components/e131/e131_addressable_light_effect.cpp | 2 ++ esphome/components/e131/e131_addressable_light_effect.h | 3 ++- esphome/components/e131/e131_packet.cpp | 2 ++ 5 files changed, 11 insertions(+), 2 deletions(-) diff --git a/esphome/components/e131/e131.cpp b/esphome/components/e131/e131.cpp index c3ff21c1a0..a74fc9be4a 100644 --- a/esphome/components/e131/e131.cpp +++ b/esphome/components/e131/e131.cpp @@ -1,4 +1,5 @@ #include "e131.h" +#ifdef USE_NETWORK #include "e131_addressable_light_effect.h" #include "esphome/core/log.h" @@ -118,3 +119,4 @@ bool E131Component::process_(int universe, const E131Packet &packet) { } // namespace e131 } // namespace esphome +#endif diff --git a/esphome/components/e131/e131.h b/esphome/components/e131/e131.h index 91b67f62eb..d0e38fa98c 100644 --- a/esphome/components/e131/e131.h +++ b/esphome/components/e131/e131.h @@ -1,5 +1,6 @@ #pragma once - +#include "esphome/core/defines.h" +#ifdef USE_NETWORK #include "esphome/components/socket/socket.h" #include "esphome/core/component.h" @@ -53,3 +54,4 @@ class E131Component : public esphome::Component { } // namespace e131 } // namespace esphome +#endif diff --git a/esphome/components/e131/e131_addressable_light_effect.cpp b/esphome/components/e131/e131_addressable_light_effect.cpp index be3144f590..4d1f98ab6c 100644 --- a/esphome/components/e131/e131_addressable_light_effect.cpp +++ b/esphome/components/e131/e131_addressable_light_effect.cpp @@ -1,5 +1,6 @@ #include "e131_addressable_light_effect.h" #include "e131.h" +#ifdef USE_NETWORK #include "esphome/core/log.h" namespace esphome { @@ -90,3 +91,4 @@ bool E131AddressableLightEffect::process_(int universe, const E131Packet &packet } // namespace e131 } // namespace esphome +#endif diff --git a/esphome/components/e131/e131_addressable_light_effect.h b/esphome/components/e131/e131_addressable_light_effect.h index 56df9cd80f..17d7bd2829 100644 --- a/esphome/components/e131/e131_addressable_light_effect.h +++ b/esphome/components/e131/e131_addressable_light_effect.h @@ -2,7 +2,7 @@ #include "esphome/core/component.h" #include "esphome/components/light/addressable_light_effect.h" - +#ifdef USE_NETWORK namespace esphome { namespace e131 { @@ -42,3 +42,4 @@ class E131AddressableLightEffect : public light::AddressableLightEffect { } // namespace e131 } // namespace esphome +#endif diff --git a/esphome/components/e131/e131_packet.cpp b/esphome/components/e131/e131_packet.cpp index e1ae41cbaf..b8fa73b707 100644 --- a/esphome/components/e131/e131_packet.cpp +++ b/esphome/components/e131/e131_packet.cpp @@ -1,5 +1,6 @@ #include #include "e131.h" +#ifdef USE_NETWORK #include "esphome/components/network/ip_address.h" #include "esphome/core/log.h" #include "esphome/core/util.h" @@ -137,3 +138,4 @@ bool E131Component::packet_(const std::vector &data, int &universe, E13 } // namespace e131 } // namespace esphome +#endif From ecd3d838c937d59bd9ee71d0ea714034033d8c4c Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Thu, 15 Aug 2024 13:35:03 +1000 Subject: [PATCH 1942/2101] [api] Bump noise-c library version (#7288) --- .github/workflows/ci.yml | 4 ++-- esphome/components/api/__init__.py | 2 +- esphome/components/host/__init__.py | 10 +++------- tests/components/api/common.yaml | 4 ---- tests/components/api/test.esp32-ard.yaml | 4 ++++ tests/components/api/test.esp32-c3-ard.yaml | 4 ++++ tests/components/api/test.esp32-c3-idf.yaml | 4 ++++ tests/components/api/test.esp32-idf.yaml | 4 ++++ tests/components/api/test.esp8266-ard.yaml | 4 ++++ tests/components/api/test.host.yaml | 3 +++ tests/components/api/test.rp2040-ard.yaml | 4 ++++ 11 files changed, 33 insertions(+), 14 deletions(-) create mode 100644 tests/components/api/test.host.yaml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 126a541b3d..2437dd5b8d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -397,7 +397,7 @@ jobs: file: ${{ fromJson(needs.list-components.outputs.components) }} steps: - name: Install dependencies - run: sudo apt-get install libsodium-dev libsdl2-dev + run: sudo apt-get install libsdl2-dev - name: Check out code from GitHub uses: actions/checkout@v4.1.7 @@ -451,7 +451,7 @@ jobs: run: echo ${{ matrix.components }} - name: Install dependencies - run: sudo apt-get install libsodium-dev libsdl2-dev + run: sudo apt-get install libsdl2-dev - name: Check out code from GitHub uses: actions/checkout@v4.1.7 diff --git a/esphome/components/api/__init__.py b/esphome/components/api/__init__.py index 38b50d4b9d..27de5c873b 100644 --- a/esphome/components/api/__init__.py +++ b/esphome/components/api/__init__.py @@ -155,7 +155,7 @@ async def to_code(config): decoded = base64.b64decode(encryption_config[CONF_KEY]) cg.add(var.set_noise_psk(list(decoded))) cg.add_define("USE_API_NOISE") - cg.add_library("esphome/noise-c", "0.1.4") + cg.add_library("esphome/noise-c", "0.1.6") else: cg.add_define("USE_API_PLAINTEXT") diff --git a/esphome/components/host/__init__.py b/esphome/components/host/__init__.py index 39e418c9ea..e83bf2dba8 100644 --- a/esphome/components/host/__init__.py +++ b/esphome/components/host/__init__.py @@ -1,15 +1,14 @@ +import esphome.codegen as cg +import esphome.config_validation as cv from esphome.const import ( + CONF_MAC_ADDRESS, KEY_CORE, KEY_FRAMEWORK_VERSION, KEY_TARGET_FRAMEWORK, KEY_TARGET_PLATFORM, PLATFORM_HOST, - CONF_MAC_ADDRESS, ) from esphome.core import CORE -from esphome.helpers import IS_MACOS -import esphome.config_validation as cv -import esphome.codegen as cg from .const import KEY_HOST @@ -42,8 +41,5 @@ async def to_code(config): cg.add_build_flag("-DUSE_HOST") cg.add_define("USE_ESPHOME_HOST_MAC_ADDRESS", config[CONF_MAC_ADDRESS].parts) cg.add_build_flag("-std=c++17") - cg.add_build_flag("-lsodium") - if IS_MACOS: - cg.add_build_flag("-L/opt/homebrew/lib") cg.add_define("ESPHOME_BOARD", "host") cg.add_platformio_option("platform", "platformio/native") diff --git a/tests/components/api/common.yaml b/tests/components/api/common.yaml index 6c2a333598..7ac11e4da6 100644 --- a/tests/components/api/common.yaml +++ b/tests/components/api/common.yaml @@ -11,10 +11,6 @@ esphome: message: Button was pressed - homeassistant.tag_scanned: pulse -wifi: - ssid: MySSID - password: password1 - api: port: 8000 password: pwd diff --git a/tests/components/api/test.esp32-ard.yaml b/tests/components/api/test.esp32-ard.yaml index dade44d145..46c01d926f 100644 --- a/tests/components/api/test.esp32-ard.yaml +++ b/tests/components/api/test.esp32-ard.yaml @@ -1 +1,5 @@ <<: !include common.yaml + +wifi: + ssid: MySSID + password: password1 diff --git a/tests/components/api/test.esp32-c3-ard.yaml b/tests/components/api/test.esp32-c3-ard.yaml index dade44d145..46c01d926f 100644 --- a/tests/components/api/test.esp32-c3-ard.yaml +++ b/tests/components/api/test.esp32-c3-ard.yaml @@ -1 +1,5 @@ <<: !include common.yaml + +wifi: + ssid: MySSID + password: password1 diff --git a/tests/components/api/test.esp32-c3-idf.yaml b/tests/components/api/test.esp32-c3-idf.yaml index dade44d145..46c01d926f 100644 --- a/tests/components/api/test.esp32-c3-idf.yaml +++ b/tests/components/api/test.esp32-c3-idf.yaml @@ -1 +1,5 @@ <<: !include common.yaml + +wifi: + ssid: MySSID + password: password1 diff --git a/tests/components/api/test.esp32-idf.yaml b/tests/components/api/test.esp32-idf.yaml index dade44d145..46c01d926f 100644 --- a/tests/components/api/test.esp32-idf.yaml +++ b/tests/components/api/test.esp32-idf.yaml @@ -1 +1,5 @@ <<: !include common.yaml + +wifi: + ssid: MySSID + password: password1 diff --git a/tests/components/api/test.esp8266-ard.yaml b/tests/components/api/test.esp8266-ard.yaml index dade44d145..46c01d926f 100644 --- a/tests/components/api/test.esp8266-ard.yaml +++ b/tests/components/api/test.esp8266-ard.yaml @@ -1 +1,5 @@ <<: !include common.yaml + +wifi: + ssid: MySSID + password: password1 diff --git a/tests/components/api/test.host.yaml b/tests/components/api/test.host.yaml new file mode 100644 index 0000000000..1ecafeab77 --- /dev/null +++ b/tests/components/api/test.host.yaml @@ -0,0 +1,3 @@ +<<: !include common.yaml + +network: diff --git a/tests/components/api/test.rp2040-ard.yaml b/tests/components/api/test.rp2040-ard.yaml index dade44d145..46c01d926f 100644 --- a/tests/components/api/test.rp2040-ard.yaml +++ b/tests/components/api/test.rp2040-ard.yaml @@ -1 +1,5 @@ <<: !include common.yaml + +wifi: + ssid: MySSID + password: password1 From 965141fad75618afea619e9d4b7dfd8ac4007c89 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Thu, 15 Aug 2024 06:38:49 +0200 Subject: [PATCH 1943/2101] [code-quality] fix clang-tidy wireguard (#7287) --- esphome/components/wireguard/__init__.py | 15 +++++++++------ esphome/components/wireguard/wireguard.cpp | 3 ++- esphome/components/wireguard/wireguard.h | 4 +++- esphome/core/defines.h | 1 + 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/esphome/components/wireguard/__init__.py b/esphome/components/wireguard/__init__.py index 16d0d0226e..5e34a8a19b 100644 --- a/esphome/components/wireguard/__init__.py +++ b/esphome/components/wireguard/__init__.py @@ -1,19 +1,20 @@ -import re import ipaddress +import re + +from esphome import automation import esphome.codegen as cg +from esphome.components import time +from esphome.components.esp32 import CORE, add_idf_sdkconfig_option import esphome.config_validation as cv from esphome.const import ( - CONF_ID, - CONF_TIME_ID, CONF_ADDRESS, + CONF_ID, CONF_REBOOT_TIMEOUT, + CONF_TIME_ID, KEY_CORE, KEY_FRAMEWORK_VERSION, ) -from esphome.components.esp32 import CORE, add_idf_sdkconfig_option -from esphome.components import time from esphome.core import TimePeriod -from esphome import automation CONF_NETMASK = "netmask" CONF_PRIVATE_KEY = "private_key" @@ -91,6 +92,8 @@ CONFIG_SCHEMA = cv.Schema( async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) + cg.add_define("USE_WIREGUARD") + cg.add(var.set_address(str(config[CONF_ADDRESS]))) cg.add(var.set_netmask(str(config[CONF_NETMASK]))) cg.add(var.set_private_key(config[CONF_PRIVATE_KEY])) diff --git a/esphome/components/wireguard/wireguard.cpp b/esphome/components/wireguard/wireguard.cpp index 17ebc701e3..7b4011cb79 100644 --- a/esphome/components/wireguard/wireguard.cpp +++ b/esphome/components/wireguard/wireguard.cpp @@ -1,5 +1,5 @@ #include "wireguard.h" - +#ifdef USE_WIREGUARD #include #include #include @@ -289,3 +289,4 @@ std::string mask_key(const std::string &key) { return (key.substr(0, 5) + "[...] } // namespace wireguard } // namespace esphome +#endif diff --git a/esphome/components/wireguard/wireguard.h b/esphome/components/wireguard/wireguard.h index a0e9e27a1b..5db9a48c90 100644 --- a/esphome/components/wireguard/wireguard.h +++ b/esphome/components/wireguard/wireguard.h @@ -1,5 +1,6 @@ #pragma once - +#include "esphome/core/defines.h" +#ifdef USE_WIREGUARD #include #include #include @@ -170,3 +171,4 @@ template class WireguardDisableAction : public Action, pu } // namespace wireguard } // namespace esphome +#endif diff --git a/esphome/core/defines.h b/esphome/core/defines.h index a4d473b76e..52cf7d4dd0 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -75,6 +75,7 @@ #define USE_VALVE #define USE_WIFI #define USE_WIFI_AP +#define USE_WIREGUARD // Arduino-specific feature flags #ifdef USE_ARDUINO From 5c31ab40607a9418ada87ad19f59abb85eb5db83 Mon Sep 17 00:00:00 2001 From: NP v/d Spek Date: Thu, 15 Aug 2024 06:51:44 +0200 Subject: [PATCH 1944/2101] fix some small rtttl issues (#6817) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/rtttl/rtttl.cpp | 127 ++++++++++++++++++++++++----- esphome/components/rtttl/rtttl.h | 21 +++-- 2 files changed, 121 insertions(+), 27 deletions(-) diff --git a/esphome/components/rtttl/rtttl.cpp b/esphome/components/rtttl/rtttl.cpp index 0bdf65b7bd..a97120499d 100644 --- a/esphome/components/rtttl/rtttl.cpp +++ b/esphome/components/rtttl/rtttl.cpp @@ -29,6 +29,13 @@ inline double deg2rad(double degrees) { void Rtttl::dump_config() { ESP_LOGCONFIG(TAG, "Rtttl"); } void Rtttl::play(std::string rtttl) { + if (this->state_ != State::STATE_STOPPED && this->state_ != State::STATE_STOPPING) { + int pos = this->rtttl_.find(':'); + auto name = this->rtttl_.substr(0, pos); + ESP_LOGW(TAG, "RTTL Component is already playing: %s", name.c_str()); + return; + } + this->rtttl_ = std::move(rtttl); this->default_duration_ = 4; @@ -98,13 +105,20 @@ void Rtttl::play(std::string rtttl) { this->note_duration_ = 1; #ifdef USE_SPEAKER - this->samples_sent_ = 0; - this->samples_count_ = 0; + 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() { - this->note_duration_ = 0; #ifdef USE_OUTPUT if (this->output_ != nullptr) { this->output_->set_level(0.0); @@ -117,16 +131,35 @@ void Rtttl::stop() { } } #endif + this->note_duration_ = 0; + this->set_state_(STATE_STOPPING); } void Rtttl::loop() { - if (this->note_duration_ == 0) + if (this->note_duration_ == 0 || this->state_ == State::STATE_STOPPED) return; #ifdef USE_SPEAKER if (this->speaker_ != nullptr) { + if (this->state_ == State::STATE_STOPPING) { + if (this->speaker_->is_stopped()) { + this->set_state_(State::STATE_STOPPED); + } + } else if (this->state_ == State::STATE_INIT) { + if (this->speaker_->is_stopped()) { + this->speaker_->start(); + this->set_state_(State::STATE_STARTING); + } + } else if (this->state_ == State::STATE_STARTING) { + if (this->speaker_->is_running()) { + this->set_state_(State::STATE_RUNNING); + } + } + if (!this->speaker_->is_running()) { + return; + } if (this->samples_sent_ != this->samples_count_) { - SpeakerSample sample[SAMPLE_BUFFER_SIZE + 1]; + SpeakerSample sample[SAMPLE_BUFFER_SIZE + 2]; int x = 0; double rem = 0.0; @@ -136,7 +169,7 @@ void Rtttl::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 = (49152 * this->gain_) * sin(deg2rad(rem)); + int16_t val = (127 * this->gain_) * sin(deg2rad(rem)); // 16bit = 49152 sample[x].left = val; sample[x].right = val; @@ -153,9 +186,9 @@ void Rtttl::loop() { x++; } if (x > 0) { - int send = this->speaker_->play((uint8_t *) (&sample), x * 4); + int send = this->speaker_->play((uint8_t *) (&sample), x * 2); if (send != x * 4) { - this->samples_sent_ -= (x - (send / 4)); + this->samples_sent_ -= (x - (send / 2)); } return; } @@ -167,14 +200,7 @@ void Rtttl::loop() { return; #endif if (!this->rtttl_[position_]) { - this->note_duration_ = 0; -#ifdef USE_OUTPUT - if (this->output_ != nullptr) { - this->output_->set_level(0.0); - } -#endif - ESP_LOGD(TAG, "Playback finished"); - this->on_finished_playback_callback_.call(); + this->finish_(); return; } @@ -213,6 +239,7 @@ void Rtttl::loop() { case 'a': note = 10; break; + case 'h': case 'b': note = 12; break; @@ -238,14 +265,21 @@ void Rtttl::loop() { uint8_t scale = get_integer_(); if (scale == 0) scale = this->default_octave_; + + if (scale < 4 || scale > 7) { + ESP_LOGE(TAG, "Octave out of valid range. Should be between 4 and 7. (Octave: %d)", scale); + this->finish_(); + return; + } bool need_note_gap = false; // Now play the note if (note) { auto note_index = (scale - 4) * 12 + note; if (note_index < 0 || note_index >= (int) sizeof(NOTES)) { - ESP_LOGE(TAG, "Note out of valid range"); - this->note_duration_ = 0; + ESP_LOGE(TAG, "Note out of valid range (note: %d, scale: %d, index: %d, max: %d)", note, scale, note_index, + (int) sizeof(NOTES)); + this->finish_(); return; } auto freq = NOTES[note_index]; @@ -285,14 +319,17 @@ void Rtttl::loop() { this->samples_gap_ = (this->sample_rate_ * DOUBLE_NOTE_GAP_MS) / 1600; //(ms); } 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. uint16_t division = ((this->samples_count_ << 10) / this->samples_per_wave_) + 1; - uint16_t x = this->samples_count_; + this->samples_count_ = (division * this->samples_per_wave_); - ESP_LOGD(TAG, "play time old: %d div: %d new: %d %d", x, division, this->samples_count_, 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_); } // Convert from frequency in Hz to high and low samples in fixed point } @@ -301,5 +338,53 @@ void Rtttl::loop() { this->last_note_ = millis(); } +void Rtttl::finish_() { +#ifdef USE_OUTPUT + if (this->output_ != nullptr) { + this->output_->set_level(0.0); + } +#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(); + } +#endif + this->set_state_(State::STATE_STOPPING); + this->note_duration_ = 0; + this->on_finished_playback_callback_.call(); + ESP_LOGD(TAG, "Playback finished"); +} + +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"); + } +}; + +void Rtttl::set_state_(State state) { + State old_state = this->state_; + this->state_ = state; + ESP_LOGD(TAG, "State changed from %s to %s", LOG_STR_ARG(state_to_string(old_state)), + LOG_STR_ARG(state_to_string(state))); +} + } // namespace rtttl } // namespace esphome diff --git a/esphome/components/rtttl/rtttl.h b/esphome/components/rtttl/rtttl.h index bf089ce980..3cb6e3f5fb 100644 --- a/esphome/components/rtttl/rtttl.h +++ b/esphome/components/rtttl/rtttl.h @@ -14,12 +14,20 @@ namespace esphome { namespace rtttl { +enum State : uint8_t { + STATE_STOPPED = 0, + STATE_INIT, + STATE_STARTING, + STATE_RUNNING, + STATE_STOPPING, +}; + #ifdef USE_SPEAKER -static const size_t SAMPLE_BUFFER_SIZE = 512; +static const size_t SAMPLE_BUFFER_SIZE = 2048; struct SpeakerSample { - int16_t left{0}; - int16_t right{0}; + int8_t left{0}; + int8_t right{0}; }; #endif @@ -42,7 +50,7 @@ class Rtttl : public Component { void stop(); void dump_config() override; - bool is_playing() { return this->note_duration_ != 0; } + bool is_playing() { return this->state_ != State::STATE_STOPPED; } void loop() override; void add_on_finished_playback_callback(std::function callback) { @@ -57,6 +65,8 @@ class Rtttl : public Component { } return ret; } + void finish_(); + void set_state_(State state); std::string rtttl_{""}; size_t position_{0}; @@ -68,13 +78,12 @@ class Rtttl : public Component { uint32_t output_freq_; float gain_{0.6f}; + State state_{State::STATE_STOPPED}; #ifdef USE_OUTPUT output::FloatOutput *output_; #endif - void play_output_(); - #ifdef USE_SPEAKER speaker::Speaker *speaker_{nullptr}; int sample_rate_{16000}; From 9713458368dfb9fd9aab8016cfe8c85d77b04887 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Thu, 15 Aug 2024 07:17:38 +0200 Subject: [PATCH 1945/2101] [code-quality] fix clang-tidy improv_serial (#7283) --- esphome/components/improv_serial/improv_serial_component.cpp | 3 ++- esphome/components/improv_serial/improv_serial_component.h | 3 ++- 2 files 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 425a5c8576..c3a0f2eacc 100644 --- a/esphome/components/improv_serial/improv_serial_component.cpp +++ b/esphome/components/improv_serial/improv_serial_component.cpp @@ -1,5 +1,5 @@ #include "improv_serial_component.h" - +#ifdef USE_WIFI #include "esphome/core/application.h" #include "esphome/core/defines.h" #include "esphome/core/hal.h" @@ -313,3 +313,4 @@ ImprovSerialComponent *global_improv_serial_component = // NOLINT(cppcoreguidel } // namespace improv_serial } // namespace esphome +#endif diff --git a/esphome/components/improv_serial/improv_serial_component.h b/esphome/components/improv_serial/improv_serial_component.h index f737f93d86..5d2534c2fc 100644 --- a/esphome/components/improv_serial/improv_serial_component.h +++ b/esphome/components/improv_serial/improv_serial_component.h @@ -5,7 +5,7 @@ #include "esphome/core/component.h" #include "esphome/core/defines.h" #include "esphome/core/helpers.h" - +#ifdef USE_WIFI #include #include @@ -78,3 +78,4 @@ extern ImprovSerialComponent } // namespace improv_serial } // namespace esphome +#endif From abb2669f0fb94c72deb55781bb087c86fe2e382c Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Thu, 15 Aug 2024 23:16:06 +0200 Subject: [PATCH 1946/2101] [code-quality] fix clang-tidy captive_portal (#7280) --- esphome/components/captive_portal/captive_portal.cpp | 2 ++ esphome/components/captive_portal/captive_portal.h | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/esphome/components/captive_portal/captive_portal.cpp b/esphome/components/captive_portal/captive_portal.cpp index 630e00f0b7..d1960e9a93 100644 --- a/esphome/components/captive_portal/captive_portal.cpp +++ b/esphome/components/captive_portal/captive_portal.cpp @@ -1,4 +1,5 @@ #include "captive_portal.h" +#ifdef USE_CAPTIVE_PORTAL #include "esphome/core/log.h" #include "esphome/core/application.h" #include "esphome/components/wifi/wifi_component.h" @@ -91,3 +92,4 @@ CaptivePortal *global_captive_portal = nullptr; // NOLINT(cppcoreguidelines-avo } // namespace captive_portal } // namespace esphome +#endif diff --git a/esphome/components/captive_portal/captive_portal.h b/esphome/components/captive_portal/captive_portal.h index df45d40d12..24d1295e6a 100644 --- a/esphome/components/captive_portal/captive_portal.h +++ b/esphome/components/captive_portal/captive_portal.h @@ -1,5 +1,6 @@ #pragma once - +#include "esphome/core/defines.h" +#ifdef USE_CAPTIVE_PORTAL #include #ifdef USE_ARDUINO #include @@ -71,3 +72,4 @@ extern CaptivePortal *global_captive_portal; // NOLINT(cppcoreguidelines-avoid- } // namespace captive_portal } // namespace esphome +#endif From 9001d1c0d46cf214f989baac9c1f05f4ed321804 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Kiss?= <70820303+g-kiss@users.noreply.github.com> Date: Fri, 16 Aug 2024 00:35:00 +0200 Subject: [PATCH 1947/2101] Fix overflow in ESPColorCorrection object (#7268) --- esphome/components/light/esp_color_correction.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/esphome/components/light/esp_color_correction.h b/esphome/components/light/esp_color_correction.h index eedd71ab27..979a1acb07 100644 --- a/esphome/components/light/esp_color_correction.h +++ b/esphome/components/light/esp_color_correction.h @@ -41,29 +41,29 @@ class ESPColorCorrection { if (this->max_brightness_.red == 0 || this->local_brightness_ == 0) return 0; uint16_t uncorrected = this->gamma_reverse_table_[red] * 255UL; - uint8_t res = ((uncorrected / this->max_brightness_.red) * 255UL) / this->local_brightness_; - return res; + 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; - uint8_t res = ((uncorrected / this->max_brightness_.green) * 255UL) / this->local_brightness_; - return res; + 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; - uint8_t res = ((uncorrected / this->max_brightness_.blue) * 255UL) / this->local_brightness_; - return res; + 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; - uint8_t res = ((uncorrected / this->max_brightness_.white) * 255UL) / this->local_brightness_; - return res; + uint16_t res = ((uncorrected / this->max_brightness_.white) * 255UL) / this->local_brightness_; + return (uint8_t) std::min(res, uint16_t(255)); } protected: From c3668b9a4de8408c28089c8c0652e0c36119cdcd Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 16 Aug 2024 11:05:26 +1200 Subject: [PATCH 1948/2101] [validation] Allow ``maybe_simple_value`` to not have default key in complex value (#7294) --- 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 ef60d6e0d6..1c00e0699b 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -1850,7 +1850,7 @@ def maybe_simple_value(*validators, **kwargs): if value == SCHEMA_EXTRACT: return (validator, key) - if isinstance(value, dict) and key in value: + if isinstance(value, dict): return validator(value) return validator({key: value}) From a0c54504cdc54521309364609883c002f88ae137 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Fri, 16 Aug 2024 00:27:23 +0100 Subject: [PATCH 1949/2101] Add HMAC-MD5 support for authenticating OTA updates (#7200) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- CODEOWNERS | 1 + esphome/components/hmac_md5/__init__.py | 2 + esphome/components/hmac_md5/hmac_md5.cpp | 56 ++++++++++++++++++++++++ esphome/components/hmac_md5/hmac_md5.h | 48 ++++++++++++++++++++ 4 files changed, 107 insertions(+) create mode 100644 esphome/components/hmac_md5/__init__.py create mode 100644 esphome/components/hmac_md5/hmac_md5.cpp create mode 100644 esphome/components/hmac_md5/hmac_md5.h diff --git a/CODEOWNERS b/CODEOWNERS index 1236c8d842..9159f5f843 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -169,6 +169,7 @@ esphome/components/he60r/* @clydebarrow esphome/components/heatpumpir/* @rob-deutsch esphome/components/hitachi_ac424/* @sourabhjaiswal esphome/components/hm3301/* @freekode +esphome/components/hmac_md5/* @dwmw2 esphome/components/homeassistant/* @OttoWinter @esphome/core esphome/components/homeassistant/number/* @landonr esphome/components/homeassistant/switch/* @Links2004 diff --git a/esphome/components/hmac_md5/__init__.py b/esphome/components/hmac_md5/__init__.py new file mode 100644 index 0000000000..fe245c0cfd --- /dev/null +++ b/esphome/components/hmac_md5/__init__.py @@ -0,0 +1,2 @@ +AUTO_LOAD = ["md5"] +CODEOWNERS = ["@dwmw2"] diff --git a/esphome/components/hmac_md5/hmac_md5.cpp b/esphome/components/hmac_md5/hmac_md5.cpp new file mode 100644 index 0000000000..90bf91882f --- /dev/null +++ b/esphome/components/hmac_md5/hmac_md5.cpp @@ -0,0 +1,56 @@ +#include +#include +#include "hmac_md5.h" +#include "esphome/core/helpers.h" + +namespace esphome { +namespace hmac_md5 { +void HmacMD5::init(const uint8_t *key, size_t len) { + uint8_t ipad[64], opad[64]; + + memset(ipad, 0, sizeof(ipad)); + if (len > 64) { + md5::MD5Digest keymd5; + keymd5.init(); + keymd5.add(key, len); + keymd5.calculate(); + keymd5.get_bytes(ipad); + } else { + memcpy(ipad, key, len); + } + memcpy(opad, ipad, sizeof(opad)); + + for (int i = 0; i < 64; i++) { + ipad[i] ^= 0x36; + opad[i] ^= 0x5c; + } + + this->ihash_.init(); + this->ihash_.add(ipad, sizeof(ipad)); + + this->ohash_.init(); + this->ohash_.add(opad, sizeof(opad)); +} + +void HmacMD5::add(const uint8_t *data, size_t len) { this->ihash_.add(data, len); } + +void HmacMD5::calculate() { + uint8_t ibytes[16]; + + this->ihash_.calculate(); + this->ihash_.get_bytes(ibytes); + + this->ohash_.add(ibytes, sizeof(ibytes)); + this->ohash_.calculate(); +} + +void HmacMD5::get_bytes(uint8_t *output) { this->ohash_.get_bytes(output); } + +void HmacMD5::get_hex(char *output) { this->ohash_.get_hex(output); } + +bool HmacMD5::equals_bytes(const uint8_t *expected) { return this->ohash_.equals_bytes(expected); } + +bool HmacMD5::equals_hex(const char *expected) { return this->ohash_.equals_hex(expected); } + +} // namespace hmac_md5 +} // namespace esphome diff --git a/esphome/components/hmac_md5/hmac_md5.h b/esphome/components/hmac_md5/hmac_md5.h new file mode 100644 index 0000000000..e6a97ad2e3 --- /dev/null +++ b/esphome/components/hmac_md5/hmac_md5.h @@ -0,0 +1,48 @@ +#pragma once + +#include "esphome/core/defines.h" +#include "esphome/components/md5/md5.h" + +#include + +namespace esphome { +namespace hmac_md5 { + +class HmacMD5 { + public: + HmacMD5() = default; + ~HmacMD5() = default; + + /// Initialize a new MD5 digest computation. + void init(const uint8_t *key, size_t len); + void init(const char *key, size_t len) { this->init((const uint8_t *) key, len); } + void init(const std::string &key) { this->init(key.c_str(), key.length()); } + + /// Add bytes of data for the digest. + void add(const uint8_t *data, size_t len); + void add(const char *data, size_t len) { this->add((const uint8_t *) data, len); } + + /// Compute the digest, based on the provided data. + void calculate(); + + /// Retrieve the HMAC-MD5 digest as bytes. + /// The output must be able to hold 16 bytes or more. + void get_bytes(uint8_t *output); + + /// Retrieve the HMAC-MD5 digest as hex characters. + /// The output must be able to hold 32 bytes or more. + void get_hex(char *output); + + /// Compare the digest against a provided byte-encoded digest (16 bytes). + bool equals_bytes(const uint8_t *expected); + + /// Compare the digest against a provided hex-encoded digest (32 bytes). + bool equals_hex(const char *expected); + + protected: + md5::MD5Digest ihash_; + md5::MD5Digest ohash_; +}; + +} // namespace hmac_md5 +} // namespace esphome From a7167ec3bf1adaec467944586c71d442a93a68d2 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Fri, 16 Aug 2024 02:32:00 +0100 Subject: [PATCH 1950/2101] [network] Always allow ``enable_ipv6: false`` (#7291) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/network/__init__.py | 6 +++++- esphome/config_validation.py | 14 ++++++++++++++ tests/components/network/test-ipv6.bk72xx-ard.yaml | 4 ++++ 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 tests/components/network/test-ipv6.bk72xx-ard.yaml diff --git a/esphome/components/network/__init__.py b/esphome/components/network/__init__.py index 96db322bde..caa873a746 100644 --- a/esphome/components/network/__init__.py +++ b/esphome/components/network/__init__.py @@ -24,7 +24,11 @@ CONFIG_SCHEMA = cv.Schema( esp32=False, rp2040=False, ): cv.All( - cv.boolean, cv.only_on([PLATFORM_ESP32, PLATFORM_ESP8266, PLATFORM_RP2040]) + cv.boolean, + cv.Any( + cv.only_on([PLATFORM_ESP32, PLATFORM_ESP8266, PLATFORM_RP2040]), + cv.boolean_false, + ), ), cv.Optional(CONF_MIN_IPV6_ADDR_COUNT, default=0): cv.positive_int, } diff --git a/esphome/config_validation.py b/esphome/config_validation.py index 1c00e0699b..6d6cb451d6 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -370,6 +370,20 @@ def boolean(value): ) +def boolean_false(value): + """Validate the given config option to be a boolean, set to False. + + This option allows a bunch of different ways of expressing boolean values: + - instance of boolean + - 'true'/'false' + - 'yes'/'no' + - 'enable'/disable + """ + if boolean(value): + raise Invalid("Expected boolean value to be false") + return False + + @schema_extractor_list def ensure_list(*validators): """Validate this configuration option to be a list. diff --git a/tests/components/network/test-ipv6.bk72xx-ard.yaml b/tests/components/network/test-ipv6.bk72xx-ard.yaml new file mode 100644 index 0000000000..361ca09977 --- /dev/null +++ b/tests/components/network/test-ipv6.bk72xx-ard.yaml @@ -0,0 +1,4 @@ +substitutions: + network_enable_ipv6: "false" + +<<: !include common.yaml From bc20fd57fe3bdd52a5ed5000d29b90063f76dd0a Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Wed, 14 Aug 2024 00:55:23 -0700 Subject: [PATCH 1951/2101] remove extra number from pronto (#7263) --- esphome/components/remote_base/pronto_protocol.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/esphome/components/remote_base/pronto_protocol.cpp b/esphome/components/remote_base/pronto_protocol.cpp index 625af76235..35fd782248 100644 --- a/esphome/components/remote_base/pronto_protocol.cpp +++ b/esphome/components/remote_base/pronto_protocol.cpp @@ -201,9 +201,6 @@ std::string ProntoProtocol::compensate_and_dump_sequence_(const RawTimings &data out += dump_duration_(t_duration, timebase); } - // append minimum gap - out += dump_duration_(PRONTO_DEFAULT_GAP, timebase, true); - return out; } From e3bfbebb8fd3368ac3c351af33407cf77956910d Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Thu, 15 Aug 2024 13:35:03 +1000 Subject: [PATCH 1952/2101] [api] Bump noise-c library version (#7288) --- .github/workflows/ci.yml | 4 ++-- esphome/components/api/__init__.py | 2 +- esphome/components/host/__init__.py | 10 +++------- tests/components/api/common.yaml | 4 ---- tests/components/api/test.esp32-ard.yaml | 4 ++++ tests/components/api/test.esp32-c3-ard.yaml | 4 ++++ tests/components/api/test.esp32-c3-idf.yaml | 4 ++++ tests/components/api/test.esp32-idf.yaml | 4 ++++ tests/components/api/test.esp8266-ard.yaml | 4 ++++ tests/components/api/test.host.yaml | 3 +++ tests/components/api/test.rp2040-ard.yaml | 4 ++++ 11 files changed, 33 insertions(+), 14 deletions(-) create mode 100644 tests/components/api/test.host.yaml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 126a541b3d..2437dd5b8d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -397,7 +397,7 @@ jobs: file: ${{ fromJson(needs.list-components.outputs.components) }} steps: - name: Install dependencies - run: sudo apt-get install libsodium-dev libsdl2-dev + run: sudo apt-get install libsdl2-dev - name: Check out code from GitHub uses: actions/checkout@v4.1.7 @@ -451,7 +451,7 @@ jobs: run: echo ${{ matrix.components }} - name: Install dependencies - run: sudo apt-get install libsodium-dev libsdl2-dev + run: sudo apt-get install libsdl2-dev - name: Check out code from GitHub uses: actions/checkout@v4.1.7 diff --git a/esphome/components/api/__init__.py b/esphome/components/api/__init__.py index 38b50d4b9d..27de5c873b 100644 --- a/esphome/components/api/__init__.py +++ b/esphome/components/api/__init__.py @@ -155,7 +155,7 @@ async def to_code(config): decoded = base64.b64decode(encryption_config[CONF_KEY]) cg.add(var.set_noise_psk(list(decoded))) cg.add_define("USE_API_NOISE") - cg.add_library("esphome/noise-c", "0.1.4") + cg.add_library("esphome/noise-c", "0.1.6") else: cg.add_define("USE_API_PLAINTEXT") diff --git a/esphome/components/host/__init__.py b/esphome/components/host/__init__.py index 39e418c9ea..e83bf2dba8 100644 --- a/esphome/components/host/__init__.py +++ b/esphome/components/host/__init__.py @@ -1,15 +1,14 @@ +import esphome.codegen as cg +import esphome.config_validation as cv from esphome.const import ( + CONF_MAC_ADDRESS, KEY_CORE, KEY_FRAMEWORK_VERSION, KEY_TARGET_FRAMEWORK, KEY_TARGET_PLATFORM, PLATFORM_HOST, - CONF_MAC_ADDRESS, ) from esphome.core import CORE -from esphome.helpers import IS_MACOS -import esphome.config_validation as cv -import esphome.codegen as cg from .const import KEY_HOST @@ -42,8 +41,5 @@ async def to_code(config): cg.add_build_flag("-DUSE_HOST") cg.add_define("USE_ESPHOME_HOST_MAC_ADDRESS", config[CONF_MAC_ADDRESS].parts) cg.add_build_flag("-std=c++17") - cg.add_build_flag("-lsodium") - if IS_MACOS: - cg.add_build_flag("-L/opt/homebrew/lib") cg.add_define("ESPHOME_BOARD", "host") cg.add_platformio_option("platform", "platformio/native") diff --git a/tests/components/api/common.yaml b/tests/components/api/common.yaml index 6c2a333598..7ac11e4da6 100644 --- a/tests/components/api/common.yaml +++ b/tests/components/api/common.yaml @@ -11,10 +11,6 @@ esphome: message: Button was pressed - homeassistant.tag_scanned: pulse -wifi: - ssid: MySSID - password: password1 - api: port: 8000 password: pwd diff --git a/tests/components/api/test.esp32-ard.yaml b/tests/components/api/test.esp32-ard.yaml index dade44d145..46c01d926f 100644 --- a/tests/components/api/test.esp32-ard.yaml +++ b/tests/components/api/test.esp32-ard.yaml @@ -1 +1,5 @@ <<: !include common.yaml + +wifi: + ssid: MySSID + password: password1 diff --git a/tests/components/api/test.esp32-c3-ard.yaml b/tests/components/api/test.esp32-c3-ard.yaml index dade44d145..46c01d926f 100644 --- a/tests/components/api/test.esp32-c3-ard.yaml +++ b/tests/components/api/test.esp32-c3-ard.yaml @@ -1 +1,5 @@ <<: !include common.yaml + +wifi: + ssid: MySSID + password: password1 diff --git a/tests/components/api/test.esp32-c3-idf.yaml b/tests/components/api/test.esp32-c3-idf.yaml index dade44d145..46c01d926f 100644 --- a/tests/components/api/test.esp32-c3-idf.yaml +++ b/tests/components/api/test.esp32-c3-idf.yaml @@ -1 +1,5 @@ <<: !include common.yaml + +wifi: + ssid: MySSID + password: password1 diff --git a/tests/components/api/test.esp32-idf.yaml b/tests/components/api/test.esp32-idf.yaml index dade44d145..46c01d926f 100644 --- a/tests/components/api/test.esp32-idf.yaml +++ b/tests/components/api/test.esp32-idf.yaml @@ -1 +1,5 @@ <<: !include common.yaml + +wifi: + ssid: MySSID + password: password1 diff --git a/tests/components/api/test.esp8266-ard.yaml b/tests/components/api/test.esp8266-ard.yaml index dade44d145..46c01d926f 100644 --- a/tests/components/api/test.esp8266-ard.yaml +++ b/tests/components/api/test.esp8266-ard.yaml @@ -1 +1,5 @@ <<: !include common.yaml + +wifi: + ssid: MySSID + password: password1 diff --git a/tests/components/api/test.host.yaml b/tests/components/api/test.host.yaml new file mode 100644 index 0000000000..1ecafeab77 --- /dev/null +++ b/tests/components/api/test.host.yaml @@ -0,0 +1,3 @@ +<<: !include common.yaml + +network: diff --git a/tests/components/api/test.rp2040-ard.yaml b/tests/components/api/test.rp2040-ard.yaml index dade44d145..46c01d926f 100644 --- a/tests/components/api/test.rp2040-ard.yaml +++ b/tests/components/api/test.rp2040-ard.yaml @@ -1 +1,5 @@ <<: !include common.yaml + +wifi: + ssid: MySSID + password: password1 From e17c7124f48ac3fc2fbc2c45bbe01b23a203f65a Mon Sep 17 00:00:00 2001 From: NP v/d Spek Date: Thu, 15 Aug 2024 06:51:44 +0200 Subject: [PATCH 1953/2101] fix some small rtttl issues (#6817) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/rtttl/rtttl.cpp | 127 ++++++++++++++++++++++++----- esphome/components/rtttl/rtttl.h | 21 +++-- 2 files changed, 121 insertions(+), 27 deletions(-) diff --git a/esphome/components/rtttl/rtttl.cpp b/esphome/components/rtttl/rtttl.cpp index 0bdf65b7bd..a97120499d 100644 --- a/esphome/components/rtttl/rtttl.cpp +++ b/esphome/components/rtttl/rtttl.cpp @@ -29,6 +29,13 @@ inline double deg2rad(double degrees) { void Rtttl::dump_config() { ESP_LOGCONFIG(TAG, "Rtttl"); } void Rtttl::play(std::string rtttl) { + if (this->state_ != State::STATE_STOPPED && this->state_ != State::STATE_STOPPING) { + int pos = this->rtttl_.find(':'); + auto name = this->rtttl_.substr(0, pos); + ESP_LOGW(TAG, "RTTL Component is already playing: %s", name.c_str()); + return; + } + this->rtttl_ = std::move(rtttl); this->default_duration_ = 4; @@ -98,13 +105,20 @@ void Rtttl::play(std::string rtttl) { this->note_duration_ = 1; #ifdef USE_SPEAKER - this->samples_sent_ = 0; - this->samples_count_ = 0; + 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() { - this->note_duration_ = 0; #ifdef USE_OUTPUT if (this->output_ != nullptr) { this->output_->set_level(0.0); @@ -117,16 +131,35 @@ void Rtttl::stop() { } } #endif + this->note_duration_ = 0; + this->set_state_(STATE_STOPPING); } void Rtttl::loop() { - if (this->note_duration_ == 0) + if (this->note_duration_ == 0 || this->state_ == State::STATE_STOPPED) return; #ifdef USE_SPEAKER if (this->speaker_ != nullptr) { + if (this->state_ == State::STATE_STOPPING) { + if (this->speaker_->is_stopped()) { + this->set_state_(State::STATE_STOPPED); + } + } else if (this->state_ == State::STATE_INIT) { + if (this->speaker_->is_stopped()) { + this->speaker_->start(); + this->set_state_(State::STATE_STARTING); + } + } else if (this->state_ == State::STATE_STARTING) { + if (this->speaker_->is_running()) { + this->set_state_(State::STATE_RUNNING); + } + } + if (!this->speaker_->is_running()) { + return; + } if (this->samples_sent_ != this->samples_count_) { - SpeakerSample sample[SAMPLE_BUFFER_SIZE + 1]; + SpeakerSample sample[SAMPLE_BUFFER_SIZE + 2]; int x = 0; double rem = 0.0; @@ -136,7 +169,7 @@ void Rtttl::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 = (49152 * this->gain_) * sin(deg2rad(rem)); + int16_t val = (127 * this->gain_) * sin(deg2rad(rem)); // 16bit = 49152 sample[x].left = val; sample[x].right = val; @@ -153,9 +186,9 @@ void Rtttl::loop() { x++; } if (x > 0) { - int send = this->speaker_->play((uint8_t *) (&sample), x * 4); + int send = this->speaker_->play((uint8_t *) (&sample), x * 2); if (send != x * 4) { - this->samples_sent_ -= (x - (send / 4)); + this->samples_sent_ -= (x - (send / 2)); } return; } @@ -167,14 +200,7 @@ void Rtttl::loop() { return; #endif if (!this->rtttl_[position_]) { - this->note_duration_ = 0; -#ifdef USE_OUTPUT - if (this->output_ != nullptr) { - this->output_->set_level(0.0); - } -#endif - ESP_LOGD(TAG, "Playback finished"); - this->on_finished_playback_callback_.call(); + this->finish_(); return; } @@ -213,6 +239,7 @@ void Rtttl::loop() { case 'a': note = 10; break; + case 'h': case 'b': note = 12; break; @@ -238,14 +265,21 @@ void Rtttl::loop() { uint8_t scale = get_integer_(); if (scale == 0) scale = this->default_octave_; + + if (scale < 4 || scale > 7) { + ESP_LOGE(TAG, "Octave out of valid range. Should be between 4 and 7. (Octave: %d)", scale); + this->finish_(); + return; + } bool need_note_gap = false; // Now play the note if (note) { auto note_index = (scale - 4) * 12 + note; if (note_index < 0 || note_index >= (int) sizeof(NOTES)) { - ESP_LOGE(TAG, "Note out of valid range"); - this->note_duration_ = 0; + ESP_LOGE(TAG, "Note out of valid range (note: %d, scale: %d, index: %d, max: %d)", note, scale, note_index, + (int) sizeof(NOTES)); + this->finish_(); return; } auto freq = NOTES[note_index]; @@ -285,14 +319,17 @@ void Rtttl::loop() { this->samples_gap_ = (this->sample_rate_ * DOUBLE_NOTE_GAP_MS) / 1600; //(ms); } 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. uint16_t division = ((this->samples_count_ << 10) / this->samples_per_wave_) + 1; - uint16_t x = this->samples_count_; + this->samples_count_ = (division * this->samples_per_wave_); - ESP_LOGD(TAG, "play time old: %d div: %d new: %d %d", x, division, this->samples_count_, 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_); } // Convert from frequency in Hz to high and low samples in fixed point } @@ -301,5 +338,53 @@ void Rtttl::loop() { this->last_note_ = millis(); } +void Rtttl::finish_() { +#ifdef USE_OUTPUT + if (this->output_ != nullptr) { + this->output_->set_level(0.0); + } +#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(); + } +#endif + this->set_state_(State::STATE_STOPPING); + this->note_duration_ = 0; + this->on_finished_playback_callback_.call(); + ESP_LOGD(TAG, "Playback finished"); +} + +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"); + } +}; + +void Rtttl::set_state_(State state) { + State old_state = this->state_; + this->state_ = state; + ESP_LOGD(TAG, "State changed from %s to %s", LOG_STR_ARG(state_to_string(old_state)), + LOG_STR_ARG(state_to_string(state))); +} + } // namespace rtttl } // namespace esphome diff --git a/esphome/components/rtttl/rtttl.h b/esphome/components/rtttl/rtttl.h index bf089ce980..3cb6e3f5fb 100644 --- a/esphome/components/rtttl/rtttl.h +++ b/esphome/components/rtttl/rtttl.h @@ -14,12 +14,20 @@ namespace esphome { namespace rtttl { +enum State : uint8_t { + STATE_STOPPED = 0, + STATE_INIT, + STATE_STARTING, + STATE_RUNNING, + STATE_STOPPING, +}; + #ifdef USE_SPEAKER -static const size_t SAMPLE_BUFFER_SIZE = 512; +static const size_t SAMPLE_BUFFER_SIZE = 2048; struct SpeakerSample { - int16_t left{0}; - int16_t right{0}; + int8_t left{0}; + int8_t right{0}; }; #endif @@ -42,7 +50,7 @@ class Rtttl : public Component { void stop(); void dump_config() override; - bool is_playing() { return this->note_duration_ != 0; } + bool is_playing() { return this->state_ != State::STATE_STOPPED; } void loop() override; void add_on_finished_playback_callback(std::function callback) { @@ -57,6 +65,8 @@ class Rtttl : public Component { } return ret; } + void finish_(); + void set_state_(State state); std::string rtttl_{""}; size_t position_{0}; @@ -68,13 +78,12 @@ class Rtttl : public Component { uint32_t output_freq_; float gain_{0.6f}; + State state_{State::STATE_STOPPED}; #ifdef USE_OUTPUT output::FloatOutput *output_; #endif - void play_output_(); - #ifdef USE_SPEAKER speaker::Speaker *speaker_{nullptr}; int sample_rate_{16000}; From 033ab552068374f4ad06dca122a250f18ba2a979 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Kiss?= <70820303+g-kiss@users.noreply.github.com> Date: Fri, 16 Aug 2024 00:35:00 +0200 Subject: [PATCH 1954/2101] Fix overflow in ESPColorCorrection object (#7268) --- esphome/components/light/esp_color_correction.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/esphome/components/light/esp_color_correction.h b/esphome/components/light/esp_color_correction.h index eedd71ab27..979a1acb07 100644 --- a/esphome/components/light/esp_color_correction.h +++ b/esphome/components/light/esp_color_correction.h @@ -41,29 +41,29 @@ class ESPColorCorrection { if (this->max_brightness_.red == 0 || this->local_brightness_ == 0) return 0; uint16_t uncorrected = this->gamma_reverse_table_[red] * 255UL; - uint8_t res = ((uncorrected / this->max_brightness_.red) * 255UL) / this->local_brightness_; - return res; + 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; - uint8_t res = ((uncorrected / this->max_brightness_.green) * 255UL) / this->local_brightness_; - return res; + 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; - uint8_t res = ((uncorrected / this->max_brightness_.blue) * 255UL) / this->local_brightness_; - return res; + 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; - uint8_t res = ((uncorrected / this->max_brightness_.white) * 255UL) / this->local_brightness_; - return res; + uint16_t res = ((uncorrected / this->max_brightness_.white) * 255UL) / this->local_brightness_; + return (uint8_t) std::min(res, uint16_t(255)); } protected: From 2c47eb62a7f1060be9fc727c8a5fc70ed92c1fd8 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 16 Aug 2024 11:05:26 +1200 Subject: [PATCH 1955/2101] [validation] Allow ``maybe_simple_value`` to not have default key in complex value (#7294) --- 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 ef60d6e0d6..1c00e0699b 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -1850,7 +1850,7 @@ def maybe_simple_value(*validators, **kwargs): if value == SCHEMA_EXTRACT: return (validator, key) - if isinstance(value, dict) and key in value: + if isinstance(value, dict): return validator(value) return validator({key: value}) From 343650e37d29058a5f2ef7caf8c7f868c9b1746c Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Fri, 16 Aug 2024 02:32:00 +0100 Subject: [PATCH 1956/2101] [network] Always allow ``enable_ipv6: false`` (#7291) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/network/__init__.py | 6 +++++- esphome/config_validation.py | 14 ++++++++++++++ tests/components/network/test-ipv6.bk72xx-ard.yaml | 4 ++++ 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 tests/components/network/test-ipv6.bk72xx-ard.yaml diff --git a/esphome/components/network/__init__.py b/esphome/components/network/__init__.py index 96db322bde..caa873a746 100644 --- a/esphome/components/network/__init__.py +++ b/esphome/components/network/__init__.py @@ -24,7 +24,11 @@ CONFIG_SCHEMA = cv.Schema( esp32=False, rp2040=False, ): cv.All( - cv.boolean, cv.only_on([PLATFORM_ESP32, PLATFORM_ESP8266, PLATFORM_RP2040]) + cv.boolean, + cv.Any( + cv.only_on([PLATFORM_ESP32, PLATFORM_ESP8266, PLATFORM_RP2040]), + cv.boolean_false, + ), ), cv.Optional(CONF_MIN_IPV6_ADDR_COUNT, default=0): cv.positive_int, } diff --git a/esphome/config_validation.py b/esphome/config_validation.py index 1c00e0699b..6d6cb451d6 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -370,6 +370,20 @@ def boolean(value): ) +def boolean_false(value): + """Validate the given config option to be a boolean, set to False. + + This option allows a bunch of different ways of expressing boolean values: + - instance of boolean + - 'true'/'false' + - 'yes'/'no' + - 'enable'/disable + """ + if boolean(value): + raise Invalid("Expected boolean value to be false") + return False + + @schema_extractor_list def ensure_list(*validators): """Validate this configuration option to be a list. diff --git a/tests/components/network/test-ipv6.bk72xx-ard.yaml b/tests/components/network/test-ipv6.bk72xx-ard.yaml new file mode 100644 index 0000000000..361ca09977 --- /dev/null +++ b/tests/components/network/test-ipv6.bk72xx-ard.yaml @@ -0,0 +1,4 @@ +substitutions: + network_enable_ipv6: "false" + +<<: !include common.yaml From e779a09586e16f03f4544dff36044e6e1318e4a3 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 16 Aug 2024 13:38:06 +1200 Subject: [PATCH 1957/2101] Bump version to 2024.8.0b2 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 47aacd6452..39d2ee74a1 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.8.0b1" +__version__ = "2024.8.0b2" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 56aa58780da5fe73637ed9f583fafbd0b3a26db7 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Sun, 18 Aug 2024 20:27:03 +1200 Subject: [PATCH 1958/2101] Revert "[validation] Allow ``maybe_simple_value`` to not have default key in complex value" (#7305) --- 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 6d6cb451d6..719cc43b31 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -1864,7 +1864,7 @@ def maybe_simple_value(*validators, **kwargs): if value == SCHEMA_EXTRACT: return (validator, key) - if isinstance(value, dict): + if isinstance(value, dict) and key in value: return validator(value) return validator({key: value}) From ac9417d4694a69d843457ce3fa40f6e9c959c64a Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Mon, 19 Aug 2024 08:43:23 +1000 Subject: [PATCH 1959/2101] [lvgl] Bug fixes (#7300) --- esphome/components/lvgl/defines.py | 32 ++++---- esphome/components/lvgl/lv_validation.py | 86 +++++++++++++-------- esphome/components/lvgl/schemas.py | 32 +++++--- esphome/components/lvgl/widgets/__init__.py | 23 +++++- tests/components/lvgl/common.yaml | 8 ++ tests/components/lvgl/lvgl-package.yaml | 58 ++++++++++++-- 6 files changed, 173 insertions(+), 66 deletions(-) diff --git a/esphome/components/lvgl/defines.py b/esphome/components/lvgl/defines.py index 8f7a973722..6a8b20b505 100644 --- a/esphome/components/lvgl/defines.py +++ b/esphome/components/lvgl/defines.py @@ -6,8 +6,8 @@ Constants already defined in esphome.const are not duplicated here and must be i from esphome import codegen as cg, config_validation as cv from esphome.const import CONF_ITEMS -from esphome.core import ID, Lambda -from esphome.cpp_generator import MockObj +from esphome.core import Lambda +from esphome.cpp_generator import LambdaExpression, MockObj from esphome.cpp_types import uint32 from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor @@ -22,19 +22,22 @@ def literal(arg): return arg +def call_lambda(lamb: LambdaExpression): + expr = lamb.content.strip() + if expr.startswith("return") and expr.endswith(";"): + return expr[7:][:-1] + return f"{lamb}()" + + class LValidator: """ A validator for a particular type used in LVGL. Usable in configs as a validator, also has `process()` to convert a value during code generation """ - def __init__( - self, validator, rtype, idtype=None, idexpr=None, retmapper=None, requires=None - ): + def __init__(self, validator, rtype, retmapper=None, requires=None): self.validator = validator self.rtype = rtype - self.idtype = idtype - self.idexpr = idexpr self.retmapper = retmapper self.requires = requires @@ -43,8 +46,6 @@ class LValidator: value = requires_component(self.requires)(value) if isinstance(value, cv.Lambda): return cv.returning_lambda(value) - if self.idtype is not None and isinstance(value, ID): - return cv.use_id(self.idtype)(value) return self.validator(value) async def process(self, value, args=()): @@ -52,10 +53,10 @@ class LValidator: return None if isinstance(value, Lambda): return cg.RawExpression( - f"{await cg.process_lambda(value, args, return_type=self.rtype)}()" + call_lambda( + await cg.process_lambda(value, args, return_type=self.rtype) + ) ) - if self.idtype is not None and isinstance(value, ID): - return cg.RawExpression(f"{value}->{self.idexpr}") if self.retmapper is not None: return self.retmapper(value) return cg.safe_exp(value) @@ -89,7 +90,7 @@ class LvConstant(LValidator): cv.ensure_list(self.one_of), uint32, retmapper=self.mapper ) - def mapper(self, value, args=()): + def mapper(self, value): if not isinstance(value, list): value = [value] return literal( @@ -103,7 +104,7 @@ class LvConstant(LValidator): def extend(self, *choices): """ - Extend an LVCconstant with additional choices. + Extend an LVconstant with additional choices. :param choices: The extra choices :return: A new LVConstant instance """ @@ -431,6 +432,8 @@ CONF_ONE_LINE = "one_line" CONF_ON_SELECT = "on_select" CONF_ONE_CHECKED = "one_checked" CONF_NEXT = "next" +CONF_PAD_ROW = "pad_row" +CONF_PAD_COLUMN = "pad_column" CONF_PAGE = "page" CONF_PAGE_WRAP = "page_wrap" CONF_PASSWORD_MODE = "password_mode" @@ -462,6 +465,7 @@ CONF_SKIP = "skip" CONF_SYMBOL = "symbol" CONF_TAB_ID = "tab_id" CONF_TABS = "tabs" +CONF_TIME_FORMAT = "time_format" CONF_TILE = "tile" CONF_TILE_ID = "tile_id" CONF_TILES = "tiles" diff --git a/esphome/components/lvgl/lv_validation.py b/esphome/components/lvgl/lv_validation.py index b351b84af6..a2be4a2abe 100644 --- a/esphome/components/lvgl/lv_validation.py +++ b/esphome/components/lvgl/lv_validation.py @@ -1,17 +1,14 @@ from typing import Union import esphome.codegen as cg -from esphome.components.binary_sensor import BinarySensor from esphome.components.color import ColorStruct from esphome.components.font import Font from esphome.components.image import Image_ -from esphome.components.sensor import Sensor -from esphome.components.text_sensor import TextSensor import esphome.config_validation as cv -from esphome.const import CONF_ARGS, CONF_COLOR, CONF_FORMAT, CONF_VALUE -from esphome.core import HexInt +from esphome.const import CONF_ARGS, CONF_COLOR, CONF_FORMAT, CONF_TIME, CONF_VALUE +from esphome.core import HexInt, Lambda from esphome.cpp_generator import MockObj -from esphome.cpp_types import uint32 +from esphome.cpp_types import ESPTime, uint32 from esphome.helpers import cpp_string_escape from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor @@ -19,9 +16,11 @@ from . import types as ty from .defines import ( CONF_END_VALUE, CONF_START_VALUE, + CONF_TIME_FORMAT, LV_FONTS, LValidator, LvConstant, + call_lambda, literal, ) from .helpers import ( @@ -110,13 +109,13 @@ def angle(value): def size_validator(value): """A size in one axis - one of "size_content", a number (pixels) or a percentage""" if value == SCHEMA_EXTRACT: - return ["size_content", "pixels", "..%"] + return ["SIZE_CONTENT", "number of pixels", "percentage"] if isinstance(value, str) and value.lower().endswith("px"): value = cv.int_(value[:-2]) if isinstance(value, str) and not value.endswith("%"): if value.upper() == "SIZE_CONTENT": return "LV_SIZE_CONTENT" - raise cv.Invalid("must be 'size_content', a pixel position or a percentage") + raise cv.Invalid("must be 'size_content', a percentage or an integer (pixels)") if isinstance(value, int): return cv.int_(value) # Will throw an exception if not a percentage. @@ -125,6 +124,15 @@ def size_validator(value): size = LValidator(size_validator, uint32, retmapper=literal) + +def pixels_validator(value): + if isinstance(value, str) and value.lower().endswith("px"): + return cv.int_(value[:-2]) + return cv.int_(value) + + +pixels = LValidator(pixels_validator, uint32, retmapper=literal) + radius_consts = LvConstant("LV_RADIUS_", "CIRCLE") @@ -167,9 +175,7 @@ lv_image = LValidator( retmapper=lambda x: lv_expr.img_from(MockObj(x)), requires="image", ) -lv_bool = LValidator( - cv.boolean, cg.bool_, BinarySensor, "get_state()", retmapper=literal -) +lv_bool = LValidator(cv.boolean, cg.bool_, retmapper=literal) def lv_pct(value: Union[int, float]): @@ -185,42 +191,60 @@ def lvms_validator_(value): lv_milliseconds = LValidator( - lvms_validator_, - cg.int32, - retmapper=lambda x: x.total_milliseconds, + lvms_validator_, cg.int32, retmapper=lambda x: x.total_milliseconds ) class TextValidator(LValidator): def __init__(self): - super().__init__( - cv.string, - cg.const_char_ptr, - TextSensor, - "get_state().c_str()", - lambda s: cg.safe_exp(f"{s}"), - ) + super().__init__(cv.string, cg.std_string, lambda s: cg.safe_exp(f"{s}")) def __call__(self, value): - if isinstance(value, dict): + if isinstance(value, dict) and CONF_FORMAT in value: return value return super().__call__(value) async def process(self, value, args=()): if isinstance(value, dict): - args = [str(x) for x in value[CONF_ARGS]] - arg_expr = cg.RawExpression(",".join(args)) - format_str = cpp_string_escape(value[CONF_FORMAT]) - return literal(f"str_sprintf({format_str}, {arg_expr}).c_str()") + if format_str := value.get(CONF_FORMAT): + args = [str(x) for x in value[CONF_ARGS]] + arg_expr = cg.RawExpression(",".join(args)) + format_str = cpp_string_escape(format_str) + return literal(f"str_sprintf({format_str}, {arg_expr}).c_str()") + 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( + 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() + if isinstance(value, Lambda): + value = call_lambda( + await cg.process_lambda(value, args, return_type=self.rtype) + ) + + # Was the lambda call reduced to a string? + if value.endswith("c_str()") or ( + value.endswith('"') and value.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 await super().process(value, args) lv_text = TextValidator() -lv_float = LValidator(cv.float_, cg.float_, Sensor, "get_state()") -lv_int = LValidator(cv.int_, cg.int_, Sensor, "get_state()") -lv_brightness = LValidator( - cv.percentage, cg.float_, Sensor, "get_state()", retmapper=lambda x: int(x * 255) -) +lv_float = LValidator(cv.float_, cg.float_) +lv_int = LValidator(cv.int_, cg.int_) +lv_brightness = LValidator(cv.percentage, cg.float_, retmapper=lambda x: int(x * 255)) def is_lv_font(font): diff --git a/esphome/components/lvgl/schemas.py b/esphome/components/lvgl/schemas.py index f1c7ff4df6..e9714e3b1a 100644 --- a/esphome/components/lvgl/schemas.py +++ b/esphome/components/lvgl/schemas.py @@ -1,5 +1,6 @@ from esphome import config_validation as cv from esphome.automation import Trigger, validate_automation +from esphome.components.time import RealTimeClock from esphome.const import ( CONF_ARGS, CONF_FORMAT, @@ -8,6 +9,7 @@ from esphome.const import ( CONF_ON_VALUE, CONF_STATE, CONF_TEXT, + CONF_TIME, CONF_TRIGGER_ID, CONF_TYPE, ) @@ -15,6 +17,7 @@ from esphome.core import TimePeriod from esphome.schema_extractors import SCHEMA_EXTRACT from . import defines as df, lv_validation as lvalid +from .defines import CONF_TIME_FORMAT from .helpers import add_lv_use, requires_component, validate_printf from .lv_validation import lv_color, lv_font, lv_image from .lvcode import LvglComponent @@ -46,7 +49,13 @@ TEXT_SCHEMA = cv.Schema( ), validate_printf, ), - lvalid.lv_text, + cv.Schema( + { + cv.Required(CONF_TIME_FORMAT): cv.string, + cv.GenerateID(CONF_TIME): cv.templatable(cv.use_id(RealTimeClock)), + } + ), + cv.templatable(cv.string), ) } ) @@ -116,15 +125,13 @@ STYLE_PROPS = { "opa_layered": lvalid.opacity, "outline_color": lvalid.lv_color, "outline_opa": lvalid.opacity, - "outline_pad": lvalid.size, - "outline_width": lvalid.size, - "pad_all": lvalid.size, - "pad_bottom": lvalid.size, - "pad_column": lvalid.size, - "pad_left": lvalid.size, - "pad_right": lvalid.size, - "pad_row": lvalid.size, - "pad_top": lvalid.size, + "outline_pad": lvalid.pixels, + "outline_width": lvalid.pixels, + "pad_all": lvalid.pixels, + "pad_bottom": lvalid.pixels, + "pad_left": lvalid.pixels, + "pad_right": lvalid.pixels, + "pad_top": lvalid.pixels, "shadow_color": lvalid.lv_color, "shadow_ofs_x": cv.int_, "shadow_ofs_y": cv.int_, @@ -304,6 +311,8 @@ LAYOUT_SCHEMA = { cv.Required(df.CONF_GRID_COLUMNS): [grid_spec], cv.Optional(df.CONF_GRID_COLUMN_ALIGN): grid_alignments, cv.Optional(df.CONF_GRID_ROW_ALIGN): grid_alignments, + cv.Optional(df.CONF_PAD_ROW): lvalid.pixels, + cv.Optional(df.CONF_PAD_COLUMN): lvalid.pixels, }, df.TYPE_FLEX: { cv.Optional( @@ -312,6 +321,8 @@ LAYOUT_SCHEMA = { cv.Optional(df.CONF_FLEX_ALIGN_MAIN, default="start"): flex_alignments, cv.Optional(df.CONF_FLEX_ALIGN_CROSS, default="start"): flex_alignments, cv.Optional(df.CONF_FLEX_ALIGN_TRACK, default="start"): flex_alignments, + cv.Optional(df.CONF_PAD_ROW): lvalid.pixels, + cv.Optional(df.CONF_PAD_COLUMN): lvalid.pixels, }, }, lower=True, @@ -338,7 +349,6 @@ DISP_BG_SCHEMA = cv.Schema( } ) - # A style schema that can include text STYLED_TEXT_SCHEMA = cv.maybe_simple_value( STYLE_SCHEMA.extend(TEXT_SCHEMA), key=CONF_TEXT diff --git a/esphome/components/lvgl/widgets/__init__.py b/esphome/components/lvgl/widgets/__init__.py index 603de6aa3e..4abb25c61d 100644 --- a/esphome/components/lvgl/widgets/__init__.py +++ b/esphome/components/lvgl/widgets/__init__.py @@ -20,6 +20,8 @@ from ..defines import ( CONF_GRID_ROWS, CONF_LAYOUT, CONF_MAIN, + CONF_PAD_COLUMN, + CONF_PAD_ROW, CONF_SCROLLBAR_MODE, CONF_STYLES, CONF_WIDGETS, @@ -29,6 +31,7 @@ from ..defines import ( TYPE_FLEX, TYPE_GRID, LValidator, + call_lambda, join_enums, literal, ) @@ -273,6 +276,10 @@ async def set_obj_properties(w: Widget, config): 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) + if (pad_column := layout.get(CONF_PAD_COLUMN)) is not None: + w.set_style(CONF_PAD_COLUMN, pad_column, 0) if layout_type == TYPE_GRID: wid = config[CONF_ID] rows = [str(x) for x in layout[CONF_GRID_ROWS]] @@ -316,8 +323,13 @@ async def set_obj_properties(w: Widget, config): flag_clr = set() flag_set = set() props = parts[CONF_MAIN][CONF_DEFAULT] + lambs = {} + flag_set = set() + flag_clr = set() for prop, value in {k: v for k, v in props.items() if k in OBJ_FLAGS}.items(): - if value: + if isinstance(value, cv.Lambda): + lambs[prop] = value + elif value: flag_set.add(prop) else: flag_clr.add(prop) @@ -327,6 +339,13 @@ async def set_obj_properties(w: Widget, config): if flag_clr: clrs = join_enums(flag_clr, "LV_OBJ_FLAG_") w.clear_flag(clrs) + for key, value in lambs.items(): + lamb = await cg.process_lambda(value, [], return_type=cg.bool_) + flag = f"LV_OBJ_FLAG_{key.upper()}" + with LvConditional(call_lambda(lamb)) as cond: + w.add_flag(flag) + cond.else_() + w.clear_flag(flag) if states := config.get(CONF_STATE): adds = set() @@ -348,7 +367,7 @@ async def set_obj_properties(w: Widget, config): for key, value in lambs.items(): lamb = await cg.process_lambda(value, [], return_type=cg.bool_) state = f"LV_STATE_{key.upper()}" - with LvConditional(f"{lamb}()") as cond: + with LvConditional(call_lambda(lamb)) as cond: w.add_state(state) cond.else_() w.clear_state(state) diff --git a/tests/components/lvgl/common.yaml b/tests/components/lvgl/common.yaml index 002c7a118d..7ef7772ac9 100644 --- a/tests/components/lvgl/common.yaml +++ b/tests/components/lvgl/common.yaml @@ -127,3 +127,11 @@ binary_sensor: - platform: lvgl name: LVGL checkbox widget: checkbox_id + +wifi: + ssid: SSID + password: PASSWORD123 + +time: + platform: sntp + id: time_id diff --git a/tests/components/lvgl/lvgl-package.yaml b/tests/components/lvgl/lvgl-package.yaml index 54022354f5..800d6eff27 100644 --- a/tests/components/lvgl/lvgl-package.yaml +++ b/tests/components/lvgl/lvgl-package.yaml @@ -16,8 +16,6 @@ lvgl: border_width: 0 radius: 0 pad_all: 0 - pad_row: 0 - pad_column: 0 border_color: 0x0077b3 text_color: 0xFFFFFF width: 100% @@ -55,6 +53,13 @@ lvgl: pages: - id: page1 skip: true + layout: + type: flex + pad_row: 4 + pad_column: 4px + flex_align_main: center + flex_align_cross: start + flex_align_track: end widgets: - animimg: height: 60 @@ -118,10 +123,8 @@ lvgl: outline_width: 10px pad_all: 10px pad_bottom: 10px - pad_column: 10px pad_left: 10px pad_right: 10px - pad_row: 10px pad_top: 10px shadow_color: light_blue shadow_ofs_x: 5 @@ -221,10 +224,47 @@ lvgl: - label: text: Button on_click: - lvgl.label.update: - id: hello_label - bg_color: 0x123456 - text: clicked + - lvgl.label.update: + id: hello_label + bg_color: 0x123456 + text: clicked + - lvgl.label.update: + id: hello_label + text: !lambda return "hello world"; + - lvgl.label.update: + id: hello_label + text: !lambda |- + ESP_LOGD("label", "multi-line lambda"); + return "hello world"; + - lvgl.label.update: + id: hello_label + text: !lambda 'return str_sprintf("Hello space");' + - lvgl.label.update: + id: hello_label + text: + format: "sprintf format %s" + args: ['x ? "checked" : "unchecked"'] + - lvgl.label.update: + id: hello_label + text: + time_format: "%c" + - lvgl.label.update: + id: hello_label + text: + time_format: "%c" + time: time_id + - lvgl.label.update: + id: hello_label + text: + time_format: "%c" + time: !lambda return id(time_id).now(); + - lvgl.label.update: + id: hello_label + text: + time_format: "%c" + time: !lambda |- + ESP_LOGD("label", "multi-line lambda"); + return id(time_id).now(); on_value: logger.log: format: "state now %d" @@ -396,6 +436,8 @@ lvgl: grid_row_align: end grid_rows: [25px, fr(1), content] grid_columns: [40, fr(1), fr(1)] + pad_row: 6px + pad_column: 0 widgets: - image: grid_cell_row_pos: 0 From 8b6d6fe6616f0c83c72c9ff395f74134a8956dd4 Mon Sep 17 00:00:00 2001 From: NP v/d Spek Date: Mon, 19 Aug 2024 00:45:10 +0200 Subject: [PATCH 1960/2101] [speaker] Fix header includes (#7304) --- esphome/components/speaker/speaker.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/esphome/components/speaker/speaker.h b/esphome/components/speaker/speaker.h index 142231881c..193049402d 100644 --- a/esphome/components/speaker/speaker.h +++ b/esphome/components/speaker/speaker.h @@ -1,5 +1,9 @@ #pragma once +#include +#include +#include + namespace esphome { namespace speaker { From baedd74c7a5f54a871eb413a629d6dd94c15510a Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 19 Aug 2024 10:45:22 +1200 Subject: [PATCH 1961/2101] [microphone] Fix header includes (#7310) --- esphome/components/microphone/microphone.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/esphome/components/microphone/microphone.h b/esphome/components/microphone/microphone.h index e01a10e15c..883ca97710 100644 --- a/esphome/components/microphone/microphone.h +++ b/esphome/components/microphone/microphone.h @@ -1,6 +1,9 @@ #pragma once -#include "esphome/core/entity_base.h" +#include +#include +#include +#include #include "esphome/core/helpers.h" namespace esphome { From 7464b440c078794c0dec88c3a991e2c081695855 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Sun, 18 Aug 2024 20:27:03 +1200 Subject: [PATCH 1962/2101] Revert "[validation] Allow ``maybe_simple_value`` to not have default key in complex value" (#7305) --- 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 6d6cb451d6..719cc43b31 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -1864,7 +1864,7 @@ def maybe_simple_value(*validators, **kwargs): if value == SCHEMA_EXTRACT: return (validator, key) - if isinstance(value, dict): + if isinstance(value, dict) and key in value: return validator(value) return validator({key: value}) From 5c7d070307c7a04e452cd641cdc3fa4baa477e18 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Mon, 19 Aug 2024 08:43:23 +1000 Subject: [PATCH 1963/2101] [lvgl] Bug fixes (#7300) --- esphome/components/lvgl/defines.py | 32 ++++---- esphome/components/lvgl/lv_validation.py | 86 +++++++++++++-------- esphome/components/lvgl/schemas.py | 32 +++++--- esphome/components/lvgl/widgets/__init__.py | 23 +++++- tests/components/lvgl/common.yaml | 8 ++ tests/components/lvgl/lvgl-package.yaml | 58 ++++++++++++-- 6 files changed, 173 insertions(+), 66 deletions(-) diff --git a/esphome/components/lvgl/defines.py b/esphome/components/lvgl/defines.py index 8f7a973722..6a8b20b505 100644 --- a/esphome/components/lvgl/defines.py +++ b/esphome/components/lvgl/defines.py @@ -6,8 +6,8 @@ Constants already defined in esphome.const are not duplicated here and must be i from esphome import codegen as cg, config_validation as cv from esphome.const import CONF_ITEMS -from esphome.core import ID, Lambda -from esphome.cpp_generator import MockObj +from esphome.core import Lambda +from esphome.cpp_generator import LambdaExpression, MockObj from esphome.cpp_types import uint32 from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor @@ -22,19 +22,22 @@ def literal(arg): return arg +def call_lambda(lamb: LambdaExpression): + expr = lamb.content.strip() + if expr.startswith("return") and expr.endswith(";"): + return expr[7:][:-1] + return f"{lamb}()" + + class LValidator: """ A validator for a particular type used in LVGL. Usable in configs as a validator, also has `process()` to convert a value during code generation """ - def __init__( - self, validator, rtype, idtype=None, idexpr=None, retmapper=None, requires=None - ): + def __init__(self, validator, rtype, retmapper=None, requires=None): self.validator = validator self.rtype = rtype - self.idtype = idtype - self.idexpr = idexpr self.retmapper = retmapper self.requires = requires @@ -43,8 +46,6 @@ class LValidator: value = requires_component(self.requires)(value) if isinstance(value, cv.Lambda): return cv.returning_lambda(value) - if self.idtype is not None and isinstance(value, ID): - return cv.use_id(self.idtype)(value) return self.validator(value) async def process(self, value, args=()): @@ -52,10 +53,10 @@ class LValidator: return None if isinstance(value, Lambda): return cg.RawExpression( - f"{await cg.process_lambda(value, args, return_type=self.rtype)}()" + call_lambda( + await cg.process_lambda(value, args, return_type=self.rtype) + ) ) - if self.idtype is not None and isinstance(value, ID): - return cg.RawExpression(f"{value}->{self.idexpr}") if self.retmapper is not None: return self.retmapper(value) return cg.safe_exp(value) @@ -89,7 +90,7 @@ class LvConstant(LValidator): cv.ensure_list(self.one_of), uint32, retmapper=self.mapper ) - def mapper(self, value, args=()): + def mapper(self, value): if not isinstance(value, list): value = [value] return literal( @@ -103,7 +104,7 @@ class LvConstant(LValidator): def extend(self, *choices): """ - Extend an LVCconstant with additional choices. + Extend an LVconstant with additional choices. :param choices: The extra choices :return: A new LVConstant instance """ @@ -431,6 +432,8 @@ CONF_ONE_LINE = "one_line" CONF_ON_SELECT = "on_select" CONF_ONE_CHECKED = "one_checked" CONF_NEXT = "next" +CONF_PAD_ROW = "pad_row" +CONF_PAD_COLUMN = "pad_column" CONF_PAGE = "page" CONF_PAGE_WRAP = "page_wrap" CONF_PASSWORD_MODE = "password_mode" @@ -462,6 +465,7 @@ CONF_SKIP = "skip" CONF_SYMBOL = "symbol" CONF_TAB_ID = "tab_id" CONF_TABS = "tabs" +CONF_TIME_FORMAT = "time_format" CONF_TILE = "tile" CONF_TILE_ID = "tile_id" CONF_TILES = "tiles" diff --git a/esphome/components/lvgl/lv_validation.py b/esphome/components/lvgl/lv_validation.py index b351b84af6..a2be4a2abe 100644 --- a/esphome/components/lvgl/lv_validation.py +++ b/esphome/components/lvgl/lv_validation.py @@ -1,17 +1,14 @@ from typing import Union import esphome.codegen as cg -from esphome.components.binary_sensor import BinarySensor from esphome.components.color import ColorStruct from esphome.components.font import Font from esphome.components.image import Image_ -from esphome.components.sensor import Sensor -from esphome.components.text_sensor import TextSensor import esphome.config_validation as cv -from esphome.const import CONF_ARGS, CONF_COLOR, CONF_FORMAT, CONF_VALUE -from esphome.core import HexInt +from esphome.const import CONF_ARGS, CONF_COLOR, CONF_FORMAT, CONF_TIME, CONF_VALUE +from esphome.core import HexInt, Lambda from esphome.cpp_generator import MockObj -from esphome.cpp_types import uint32 +from esphome.cpp_types import ESPTime, uint32 from esphome.helpers import cpp_string_escape from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor @@ -19,9 +16,11 @@ from . import types as ty from .defines import ( CONF_END_VALUE, CONF_START_VALUE, + CONF_TIME_FORMAT, LV_FONTS, LValidator, LvConstant, + call_lambda, literal, ) from .helpers import ( @@ -110,13 +109,13 @@ def angle(value): def size_validator(value): """A size in one axis - one of "size_content", a number (pixels) or a percentage""" if value == SCHEMA_EXTRACT: - return ["size_content", "pixels", "..%"] + return ["SIZE_CONTENT", "number of pixels", "percentage"] if isinstance(value, str) and value.lower().endswith("px"): value = cv.int_(value[:-2]) if isinstance(value, str) and not value.endswith("%"): if value.upper() == "SIZE_CONTENT": return "LV_SIZE_CONTENT" - raise cv.Invalid("must be 'size_content', a pixel position or a percentage") + raise cv.Invalid("must be 'size_content', a percentage or an integer (pixels)") if isinstance(value, int): return cv.int_(value) # Will throw an exception if not a percentage. @@ -125,6 +124,15 @@ def size_validator(value): size = LValidator(size_validator, uint32, retmapper=literal) + +def pixels_validator(value): + if isinstance(value, str) and value.lower().endswith("px"): + return cv.int_(value[:-2]) + return cv.int_(value) + + +pixels = LValidator(pixels_validator, uint32, retmapper=literal) + radius_consts = LvConstant("LV_RADIUS_", "CIRCLE") @@ -167,9 +175,7 @@ lv_image = LValidator( retmapper=lambda x: lv_expr.img_from(MockObj(x)), requires="image", ) -lv_bool = LValidator( - cv.boolean, cg.bool_, BinarySensor, "get_state()", retmapper=literal -) +lv_bool = LValidator(cv.boolean, cg.bool_, retmapper=literal) def lv_pct(value: Union[int, float]): @@ -185,42 +191,60 @@ def lvms_validator_(value): lv_milliseconds = LValidator( - lvms_validator_, - cg.int32, - retmapper=lambda x: x.total_milliseconds, + lvms_validator_, cg.int32, retmapper=lambda x: x.total_milliseconds ) class TextValidator(LValidator): def __init__(self): - super().__init__( - cv.string, - cg.const_char_ptr, - TextSensor, - "get_state().c_str()", - lambda s: cg.safe_exp(f"{s}"), - ) + super().__init__(cv.string, cg.std_string, lambda s: cg.safe_exp(f"{s}")) def __call__(self, value): - if isinstance(value, dict): + if isinstance(value, dict) and CONF_FORMAT in value: return value return super().__call__(value) async def process(self, value, args=()): if isinstance(value, dict): - args = [str(x) for x in value[CONF_ARGS]] - arg_expr = cg.RawExpression(",".join(args)) - format_str = cpp_string_escape(value[CONF_FORMAT]) - return literal(f"str_sprintf({format_str}, {arg_expr}).c_str()") + if format_str := value.get(CONF_FORMAT): + args = [str(x) for x in value[CONF_ARGS]] + arg_expr = cg.RawExpression(",".join(args)) + format_str = cpp_string_escape(format_str) + return literal(f"str_sprintf({format_str}, {arg_expr}).c_str()") + 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( + 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() + if isinstance(value, Lambda): + value = call_lambda( + await cg.process_lambda(value, args, return_type=self.rtype) + ) + + # Was the lambda call reduced to a string? + if value.endswith("c_str()") or ( + value.endswith('"') and value.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 await super().process(value, args) lv_text = TextValidator() -lv_float = LValidator(cv.float_, cg.float_, Sensor, "get_state()") -lv_int = LValidator(cv.int_, cg.int_, Sensor, "get_state()") -lv_brightness = LValidator( - cv.percentage, cg.float_, Sensor, "get_state()", retmapper=lambda x: int(x * 255) -) +lv_float = LValidator(cv.float_, cg.float_) +lv_int = LValidator(cv.int_, cg.int_) +lv_brightness = LValidator(cv.percentage, cg.float_, retmapper=lambda x: int(x * 255)) def is_lv_font(font): diff --git a/esphome/components/lvgl/schemas.py b/esphome/components/lvgl/schemas.py index f1c7ff4df6..e9714e3b1a 100644 --- a/esphome/components/lvgl/schemas.py +++ b/esphome/components/lvgl/schemas.py @@ -1,5 +1,6 @@ from esphome import config_validation as cv from esphome.automation import Trigger, validate_automation +from esphome.components.time import RealTimeClock from esphome.const import ( CONF_ARGS, CONF_FORMAT, @@ -8,6 +9,7 @@ from esphome.const import ( CONF_ON_VALUE, CONF_STATE, CONF_TEXT, + CONF_TIME, CONF_TRIGGER_ID, CONF_TYPE, ) @@ -15,6 +17,7 @@ from esphome.core import TimePeriod from esphome.schema_extractors import SCHEMA_EXTRACT from . import defines as df, lv_validation as lvalid +from .defines import CONF_TIME_FORMAT from .helpers import add_lv_use, requires_component, validate_printf from .lv_validation import lv_color, lv_font, lv_image from .lvcode import LvglComponent @@ -46,7 +49,13 @@ TEXT_SCHEMA = cv.Schema( ), validate_printf, ), - lvalid.lv_text, + cv.Schema( + { + cv.Required(CONF_TIME_FORMAT): cv.string, + cv.GenerateID(CONF_TIME): cv.templatable(cv.use_id(RealTimeClock)), + } + ), + cv.templatable(cv.string), ) } ) @@ -116,15 +125,13 @@ STYLE_PROPS = { "opa_layered": lvalid.opacity, "outline_color": lvalid.lv_color, "outline_opa": lvalid.opacity, - "outline_pad": lvalid.size, - "outline_width": lvalid.size, - "pad_all": lvalid.size, - "pad_bottom": lvalid.size, - "pad_column": lvalid.size, - "pad_left": lvalid.size, - "pad_right": lvalid.size, - "pad_row": lvalid.size, - "pad_top": lvalid.size, + "outline_pad": lvalid.pixels, + "outline_width": lvalid.pixels, + "pad_all": lvalid.pixels, + "pad_bottom": lvalid.pixels, + "pad_left": lvalid.pixels, + "pad_right": lvalid.pixels, + "pad_top": lvalid.pixels, "shadow_color": lvalid.lv_color, "shadow_ofs_x": cv.int_, "shadow_ofs_y": cv.int_, @@ -304,6 +311,8 @@ LAYOUT_SCHEMA = { cv.Required(df.CONF_GRID_COLUMNS): [grid_spec], cv.Optional(df.CONF_GRID_COLUMN_ALIGN): grid_alignments, cv.Optional(df.CONF_GRID_ROW_ALIGN): grid_alignments, + cv.Optional(df.CONF_PAD_ROW): lvalid.pixels, + cv.Optional(df.CONF_PAD_COLUMN): lvalid.pixels, }, df.TYPE_FLEX: { cv.Optional( @@ -312,6 +321,8 @@ LAYOUT_SCHEMA = { cv.Optional(df.CONF_FLEX_ALIGN_MAIN, default="start"): flex_alignments, cv.Optional(df.CONF_FLEX_ALIGN_CROSS, default="start"): flex_alignments, cv.Optional(df.CONF_FLEX_ALIGN_TRACK, default="start"): flex_alignments, + cv.Optional(df.CONF_PAD_ROW): lvalid.pixels, + cv.Optional(df.CONF_PAD_COLUMN): lvalid.pixels, }, }, lower=True, @@ -338,7 +349,6 @@ DISP_BG_SCHEMA = cv.Schema( } ) - # A style schema that can include text STYLED_TEXT_SCHEMA = cv.maybe_simple_value( STYLE_SCHEMA.extend(TEXT_SCHEMA), key=CONF_TEXT diff --git a/esphome/components/lvgl/widgets/__init__.py b/esphome/components/lvgl/widgets/__init__.py index 603de6aa3e..4abb25c61d 100644 --- a/esphome/components/lvgl/widgets/__init__.py +++ b/esphome/components/lvgl/widgets/__init__.py @@ -20,6 +20,8 @@ from ..defines import ( CONF_GRID_ROWS, CONF_LAYOUT, CONF_MAIN, + CONF_PAD_COLUMN, + CONF_PAD_ROW, CONF_SCROLLBAR_MODE, CONF_STYLES, CONF_WIDGETS, @@ -29,6 +31,7 @@ from ..defines import ( TYPE_FLEX, TYPE_GRID, LValidator, + call_lambda, join_enums, literal, ) @@ -273,6 +276,10 @@ async def set_obj_properties(w: Widget, config): 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) + if (pad_column := layout.get(CONF_PAD_COLUMN)) is not None: + w.set_style(CONF_PAD_COLUMN, pad_column, 0) if layout_type == TYPE_GRID: wid = config[CONF_ID] rows = [str(x) for x in layout[CONF_GRID_ROWS]] @@ -316,8 +323,13 @@ async def set_obj_properties(w: Widget, config): flag_clr = set() flag_set = set() props = parts[CONF_MAIN][CONF_DEFAULT] + lambs = {} + flag_set = set() + flag_clr = set() for prop, value in {k: v for k, v in props.items() if k in OBJ_FLAGS}.items(): - if value: + if isinstance(value, cv.Lambda): + lambs[prop] = value + elif value: flag_set.add(prop) else: flag_clr.add(prop) @@ -327,6 +339,13 @@ async def set_obj_properties(w: Widget, config): if flag_clr: clrs = join_enums(flag_clr, "LV_OBJ_FLAG_") w.clear_flag(clrs) + for key, value in lambs.items(): + lamb = await cg.process_lambda(value, [], return_type=cg.bool_) + flag = f"LV_OBJ_FLAG_{key.upper()}" + with LvConditional(call_lambda(lamb)) as cond: + w.add_flag(flag) + cond.else_() + w.clear_flag(flag) if states := config.get(CONF_STATE): adds = set() @@ -348,7 +367,7 @@ async def set_obj_properties(w: Widget, config): for key, value in lambs.items(): lamb = await cg.process_lambda(value, [], return_type=cg.bool_) state = f"LV_STATE_{key.upper()}" - with LvConditional(f"{lamb}()") as cond: + with LvConditional(call_lambda(lamb)) as cond: w.add_state(state) cond.else_() w.clear_state(state) diff --git a/tests/components/lvgl/common.yaml b/tests/components/lvgl/common.yaml index 002c7a118d..7ef7772ac9 100644 --- a/tests/components/lvgl/common.yaml +++ b/tests/components/lvgl/common.yaml @@ -127,3 +127,11 @@ binary_sensor: - platform: lvgl name: LVGL checkbox widget: checkbox_id + +wifi: + ssid: SSID + password: PASSWORD123 + +time: + platform: sntp + id: time_id diff --git a/tests/components/lvgl/lvgl-package.yaml b/tests/components/lvgl/lvgl-package.yaml index 54022354f5..800d6eff27 100644 --- a/tests/components/lvgl/lvgl-package.yaml +++ b/tests/components/lvgl/lvgl-package.yaml @@ -16,8 +16,6 @@ lvgl: border_width: 0 radius: 0 pad_all: 0 - pad_row: 0 - pad_column: 0 border_color: 0x0077b3 text_color: 0xFFFFFF width: 100% @@ -55,6 +53,13 @@ lvgl: pages: - id: page1 skip: true + layout: + type: flex + pad_row: 4 + pad_column: 4px + flex_align_main: center + flex_align_cross: start + flex_align_track: end widgets: - animimg: height: 60 @@ -118,10 +123,8 @@ lvgl: outline_width: 10px pad_all: 10px pad_bottom: 10px - pad_column: 10px pad_left: 10px pad_right: 10px - pad_row: 10px pad_top: 10px shadow_color: light_blue shadow_ofs_x: 5 @@ -221,10 +224,47 @@ lvgl: - label: text: Button on_click: - lvgl.label.update: - id: hello_label - bg_color: 0x123456 - text: clicked + - lvgl.label.update: + id: hello_label + bg_color: 0x123456 + text: clicked + - lvgl.label.update: + id: hello_label + text: !lambda return "hello world"; + - lvgl.label.update: + id: hello_label + text: !lambda |- + ESP_LOGD("label", "multi-line lambda"); + return "hello world"; + - lvgl.label.update: + id: hello_label + text: !lambda 'return str_sprintf("Hello space");' + - lvgl.label.update: + id: hello_label + text: + format: "sprintf format %s" + args: ['x ? "checked" : "unchecked"'] + - lvgl.label.update: + id: hello_label + text: + time_format: "%c" + - lvgl.label.update: + id: hello_label + text: + time_format: "%c" + time: time_id + - lvgl.label.update: + id: hello_label + text: + time_format: "%c" + time: !lambda return id(time_id).now(); + - lvgl.label.update: + id: hello_label + text: + time_format: "%c" + time: !lambda |- + ESP_LOGD("label", "multi-line lambda"); + return id(time_id).now(); on_value: logger.log: format: "state now %d" @@ -396,6 +436,8 @@ lvgl: grid_row_align: end grid_rows: [25px, fr(1), content] grid_columns: [40, fr(1), fr(1)] + pad_row: 6px + pad_column: 0 widgets: - image: grid_cell_row_pos: 0 From 0f82114e64f50a167c85374ec299c43fd2cd84ff Mon Sep 17 00:00:00 2001 From: NP v/d Spek Date: Mon, 19 Aug 2024 00:45:10 +0200 Subject: [PATCH 1964/2101] [speaker] Fix header includes (#7304) --- esphome/components/speaker/speaker.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/esphome/components/speaker/speaker.h b/esphome/components/speaker/speaker.h index 142231881c..193049402d 100644 --- a/esphome/components/speaker/speaker.h +++ b/esphome/components/speaker/speaker.h @@ -1,5 +1,9 @@ #pragma once +#include +#include +#include + namespace esphome { namespace speaker { From c96784f59108b476597a6f09a83de358d18ef3b2 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 19 Aug 2024 10:45:22 +1200 Subject: [PATCH 1965/2101] [microphone] Fix header includes (#7310) --- esphome/components/microphone/microphone.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/esphome/components/microphone/microphone.h b/esphome/components/microphone/microphone.h index e01a10e15c..883ca97710 100644 --- a/esphome/components/microphone/microphone.h +++ b/esphome/components/microphone/microphone.h @@ -1,6 +1,9 @@ #pragma once -#include "esphome/core/entity_base.h" +#include +#include +#include +#include #include "esphome/core/helpers.h" namespace esphome { From 409e84090eff4d3c8aa536e2077f036cd51cda54 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 19 Aug 2024 13:09:59 +1200 Subject: [PATCH 1966/2101] Bump version to 2024.8.0b3 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 39d2ee74a1..a321ddd19f 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.8.0b2" +__version__ = "2024.8.0b3" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From b425912a80aea1ed71ebf5e3515963f09f559832 Mon Sep 17 00:00:00 2001 From: Roving Ronin <108674933+Roving-Ronin@users.noreply.github.com> Date: Tue, 20 Aug 2024 07:18:06 +1000 Subject: [PATCH 1967/2101] Update const.py - Add missing UNIT_LITRE (#7317) --- esphome/const.py | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/const.py b/esphome/const.py index 6157ce32f7..b9c37a53a8 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1042,6 +1042,7 @@ UNIT_KILOVOLT_AMPS_REACTIVE = "kVAR" UNIT_KILOVOLT_AMPS_REACTIVE_HOURS = "kVARh" UNIT_KILOWATT = "kW" UNIT_KILOWATT_HOURS = "kWh" +UNIT_LITRE = "L" UNIT_LUX = "lx" UNIT_METER = "m" UNIT_METER_PER_SECOND_SQUARED = "m/s²" From 1ffee9c4d2d89823346b48585a987e9ab7233a93 Mon Sep 17 00:00:00 2001 From: Ali Jafri Date: Tue, 20 Aug 2024 03:12:41 +0530 Subject: [PATCH 1968/2101] Fix RP2040 Neopixel flickering issue (#7307) --- .../rp2040_pio_led_strip/led_strip.cpp | 36 ++++++++++++++++--- .../rp2040_pio_led_strip/led_strip.h | 5 +++ 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/esphome/components/rp2040_pio_led_strip/led_strip.cpp b/esphome/components/rp2040_pio_led_strip/led_strip.cpp index 3e5e82898d..2aaa2ceb19 100644 --- a/esphome/components/rp2040_pio_led_strip/led_strip.cpp +++ b/esphome/components/rp2040_pio_led_strip/led_strip.cpp @@ -7,8 +7,10 @@ #include #include +#include #include #include +#include namespace esphome { namespace rp2040_pio_led_strip { @@ -23,6 +25,19 @@ static std::map conf_count_ = { {CHIPSET_WS2812, false}, {CHIPSET_WS2812B, false}, {CHIPSET_SK6812, false}, {CHIPSET_SM16703, false}, {CHIPSET_CUSTOM, false}, }; +static bool dma_chan_active_[12]; +static struct semaphore dma_write_complete_sem_[12]; + +// DMA interrupt service routine +void RP2040PIOLEDStripLightOutput::dma_write_complete_handler_() { + uint32_t channel = dma_hw->ints0; + for (uint dma_chan = 0; dma_chan < 12; ++dma_chan) { + if (RP2040PIOLEDStripLightOutput::dma_chan_active_[dma_chan] && (channel & (1u << dma_chan))) { + dma_hw->ints0 = (1u << dma_chan); // Clear the interrupt + sem_release(&RP2040PIOLEDStripLightOutput::dma_write_complete_sem_[dma_chan]); // Handle the interrupt + } + } +} void RP2040PIOLEDStripLightOutput::setup() { ESP_LOGCONFIG(TAG, "Setting up RP2040 LED Strip..."); @@ -57,22 +72,22 @@ 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 (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; } // keep track of how many instances of the PIO program are running on each PIO - num_instance_[this->pio_ == pio0 ? 0 : 1]++; + RP2040PIOLEDStripLightOutput::num_instance_[this->pio_ == pio0 ? 0 : 1]++; // if there are multiple strips of the same chipset, we can reuse the same PIO program and save space if (this->conf_count_[this->chipset_]) { - offset = chipset_offsets_[this->chipset_]; + offset = RP2040PIOLEDStripLightOutput::chipset_offsets_[this->chipset_]; } else { // Load the assembled program into the PIO and get its location in the PIO's instruction memory and save it offset = pio_add_program(this->pio_, this->program_); - chipset_offsets_[this->chipset_] = offset; - conf_count_[this->chipset_] = true; + RP2040PIOLEDStripLightOutput::chipset_offsets_[this->chipset_] = offset; + RP2040PIOLEDStripLightOutput::conf_count_[this->chipset_] = true; } // Configure the state machine's PIO, and start it @@ -93,6 +108,9 @@ void RP2040PIOLEDStripLightOutput::setup() { return; } + // Mark the DMA channel as active + RP2040PIOLEDStripLightOutput::dma_chan_active_[this->dma_chan_] = true; + this->dma_config_ = dma_channel_get_default_config(this->dma_chan_); channel_config_set_transfer_data_size( &this->dma_config_, @@ -109,6 +127,13 @@ void RP2040PIOLEDStripLightOutput::setup() { false // don't start yet ); + // Initialize the semaphore for this DMA channel + sem_init(&RP2040PIOLEDStripLightOutput::dma_write_complete_sem_[this->dma_chan_], 1, 1); + + irq_set_exclusive_handler(DMA_IRQ_0, dma_write_complete_handler_); // after DMA all data, raise an interrupt + dma_channel_set_irq0_enabled(this->dma_chan_, true); // map DMA channel to interrupt + irq_set_enabled(DMA_IRQ_0, true); // enable interrupt + this->init_(this->pio_, this->sm_, offset, this->pin_, this->max_refresh_rate_); } @@ -126,6 +151,7 @@ void RP2040PIOLEDStripLightOutput::write_state(light::LightState *state) { } // the bits are already in the correct order for the pio program so we can just copy the buffer using DMA + sem_acquire_blocking(&RP2040PIOLEDStripLightOutput::dma_write_complete_sem_[this->dma_chan_]); dma_channel_transfer_from_buffer_now(this->dma_chan_, this->buf_, this->get_buffer_size_()); } diff --git a/esphome/components/rp2040_pio_led_strip/led_strip.h b/esphome/components/rp2040_pio_led_strip/led_strip.h index 9976842f02..7b62648974 100644 --- a/esphome/components/rp2040_pio_led_strip/led_strip.h +++ b/esphome/components/rp2040_pio_led_strip/led_strip.h @@ -13,6 +13,7 @@ #include #include #include +#include #include namespace esphome { @@ -95,6 +96,8 @@ class RP2040PIOLEDStripLightOutput : public light::AddressableLight { size_t get_buffer_size_() const { return this->num_leds_ * (3 + this->is_rgbw_); } + static void dma_write_complete_handler_(); + uint8_t *buf_{nullptr}; uint8_t *effect_data_{nullptr}; @@ -120,6 +123,8 @@ class RP2040PIOLEDStripLightOutput : public light::AddressableLight { inline static int num_instance_[2]; inline static std::map conf_count_; inline static std::map chipset_offsets_; + inline static bool dma_chan_active_[12]; + inline static struct semaphore dma_write_complete_sem_[12]; }; } // namespace rp2040_pio_led_strip From 30414667d023c18767852d12f3da7bc119c6ae1e Mon Sep 17 00:00:00 2001 From: NP v/d Spek Date: Tue, 20 Aug 2024 00:22:19 +0200 Subject: [PATCH 1969/2101] add the ability to add more idf components to an existing setup (#7302) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/esp32/__init__.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 0a5dd46478..b630c7638e 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -172,6 +172,19 @@ def add_idf_component( KEY_COMPONENTS: components, KEY_SUBMODULES: submodules, } + else: + component_config = CORE.data[KEY_ESP32][KEY_COMPONENTS][name] + if components is not None: + component_config[KEY_COMPONENTS] = list( + set(component_config[KEY_COMPONENTS] + components) + ) + if submodules is not None: + if component_config[KEY_SUBMODULES] is None: + component_config[KEY_SUBMODULES] = submodules + else: + component_config[KEY_SUBMODULES] = list( + set(component_config[KEY_SUBMODULES] + submodules) + ) def add_extra_script(stage: str, filename: str, path: str): From 3cbdf63f567621bf559f7cf82b05d078b56a8e28 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Tue, 20 Aug 2024 00:53:15 +0200 Subject: [PATCH 1970/2101] [code-quality] fix clang-tidy socket (#7285) --- esphome/components/socket/socket.cpp | 2 ++ esphome/components/socket/socket.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/esphome/components/socket/socket.cpp b/esphome/components/socket/socket.cpp index 5d3528dad8..e260fce05e 100644 --- a/esphome/components/socket/socket.cpp +++ b/esphome/components/socket/socket.cpp @@ -1,4 +1,5 @@ #include "socket.h" +#if defined(USE_SOCKET_IMPL_LWIP_TCP) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) || defined(USE_SOCKET_IMPL_BSD_SOCKETS) #include #include #include @@ -74,3 +75,4 @@ socklen_t set_sockaddr_any(struct sockaddr *addr, socklen_t addrlen, uint16_t po } } // namespace socket } // namespace esphome +#endif diff --git a/esphome/components/socket/socket.h b/esphome/components/socket/socket.h index 5c12210d15..cefdb51e0d 100644 --- a/esphome/components/socket/socket.h +++ b/esphome/components/socket/socket.h @@ -5,6 +5,7 @@ #include "esphome/core/optional.h" #include "headers.h" +#if defined(USE_SOCKET_IMPL_LWIP_TCP) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) || defined(USE_SOCKET_IMPL_BSD_SOCKETS) namespace esphome { namespace socket { @@ -57,3 +58,4 @@ socklen_t set_sockaddr_any(struct sockaddr *addr, socklen_t addrlen, uint16_t po } // namespace socket } // namespace esphome +#endif From fa497d06b047334de87267ade785c9394b0074f5 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Wed, 21 Aug 2024 00:01:50 +0200 Subject: [PATCH 1971/2101] [code-quality] fix clang-tidy cstddef (#7324) --- esphome/components/microphone/microphone.h | 2 +- esphome/components/speaker/speaker.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/microphone/microphone.h b/esphome/components/microphone/microphone.h index 883ca97710..914ad80bea 100644 --- a/esphome/components/microphone/microphone.h +++ b/esphome/components/microphone/microphone.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include #include diff --git a/esphome/components/speaker/speaker.h b/esphome/components/speaker/speaker.h index 193049402d..375ccc4e8c 100644 --- a/esphome/components/speaker/speaker.h +++ b/esphome/components/speaker/speaker.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include From bd3d065a23693340fffdc887178e76ca93830be2 Mon Sep 17 00:00:00 2001 From: Sung-jin Brian Hong Date: Wed, 21 Aug 2024 08:44:21 +0900 Subject: [PATCH 1972/2101] Fix waveshare 2.13" epaper stride calculation error (#7303) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- .../components/waveshare_epaper/waveshare_epaper.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/esphome/components/waveshare_epaper/waveshare_epaper.cpp b/esphome/components/waveshare_epaper/waveshare_epaper.cpp index 24df428e6f..7c1d436673 100644 --- a/esphome/components/waveshare_epaper/waveshare_epaper.cpp +++ b/esphome/components/waveshare_epaper/waveshare_epaper.cpp @@ -480,7 +480,7 @@ void HOT WaveshareEPaperTypeA::display() { this->start_data_(); switch (this->model_) { case TTGO_EPAPER_2_13_IN_B1: { // block needed because of variable initializations - int16_t wb = ((this->get_width_internal()) >> 3); + int16_t wb = ((this->get_width_controller()) >> 3); for (int i = 0; i < this->get_height_internal(); i++) { for (int j = 0; j < wb; j++) { int idx = j + (this->get_height_internal() - 1 - i) * wb; @@ -766,7 +766,7 @@ void WaveshareEPaper2P7InV2::initialize() { // XRAM_START_AND_END_POSITION this->command(0x44); this->data(0x00); - this->data(((get_width_internal() - 1) >> 3) & 0xFF); + this->data(((this->get_width_controller() - 1) >> 3) & 0xFF); // YRAM_START_AND_END_POSITION this->command(0x45); this->data(0x00); @@ -928,8 +928,8 @@ void HOT WaveshareEPaper2P7InB::display() { // TCON_RESOLUTION this->command(0x61); - this->data(this->get_width_internal() >> 8); - this->data(this->get_width_internal() & 0xff); // 176 + this->data(this->get_width_controller() >> 8); + this->data(this->get_width_controller() & 0xff); // 176 this->data(this->get_height_internal() >> 8); this->data(this->get_height_internal() & 0xff); // 264 @@ -994,7 +994,7 @@ void WaveshareEPaper2P7InBV2::initialize() { // self.SetWindows(0, 0, self.width-1, self.height-1) // SetWindows(self, Xstart, Ystart, Xend, Yend): - uint32_t xend = this->get_width_internal() - 1; + uint32_t xend = this->get_width_controller() - 1; uint32_t yend = this->get_height_internal() - 1; this->command(0x44); this->data(0x00); From 848fd0442d67dece75bf8eddf6a5242ead5b6dc4 Mon Sep 17 00:00:00 2001 From: NewoPL <27411874+NewoPL@users.noreply.github.com> Date: Wed, 21 Aug 2024 01:46:15 +0200 Subject: [PATCH 1973/2101] [rtttl] fix STOPPED state (#7323) --- esphome/components/rtttl/rtttl.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/esphome/components/rtttl/rtttl.cpp b/esphome/components/rtttl/rtttl.cpp index a97120499d..495b5c1c8a 100644 --- a/esphome/components/rtttl/rtttl.cpp +++ b/esphome/components/rtttl/rtttl.cpp @@ -32,7 +32,7 @@ void Rtttl::play(std::string rtttl) { if (this->state_ != State::STATE_STOPPED && this->state_ != State::STATE_STOPPING) { int pos = this->rtttl_.find(':'); auto name = this->rtttl_.substr(0, pos); - ESP_LOGW(TAG, "RTTL Component is already playing: %s", name.c_str()); + ESP_LOGW(TAG, "RTTTL Component is already playing: %s", name.c_str()); return; } @@ -122,6 +122,7 @@ 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 @@ -129,10 +130,10 @@ void Rtttl::stop() { if (this->speaker_->is_running()) { this->speaker_->stop(); } + this->set_state_(STATE_STOPPING); } #endif this->note_duration_ = 0; - this->set_state_(STATE_STOPPING); } void Rtttl::loop() { @@ -342,6 +343,7 @@ void 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 @@ -354,9 +356,9 @@ void Rtttl::finish_() { this->speaker_->play((uint8_t *) (&sample), 8); this->speaker_->finish(); + this->set_state_(State::STATE_STOPPING); } #endif - this->set_state_(State::STATE_STOPPING); this->note_duration_ = 0; this->on_finished_playback_callback_.call(); ESP_LOGD(TAG, "Playback finished"); From 8fae60931622771feb31af6ee788e4cf8ac96f9c Mon Sep 17 00:00:00 2001 From: Ali Jafri Date: Tue, 20 Aug 2024 03:12:41 +0530 Subject: [PATCH 1974/2101] Fix RP2040 Neopixel flickering issue (#7307) --- .../rp2040_pio_led_strip/led_strip.cpp | 36 ++++++++++++++++--- .../rp2040_pio_led_strip/led_strip.h | 5 +++ 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/esphome/components/rp2040_pio_led_strip/led_strip.cpp b/esphome/components/rp2040_pio_led_strip/led_strip.cpp index 3e5e82898d..2aaa2ceb19 100644 --- a/esphome/components/rp2040_pio_led_strip/led_strip.cpp +++ b/esphome/components/rp2040_pio_led_strip/led_strip.cpp @@ -7,8 +7,10 @@ #include #include +#include #include #include +#include namespace esphome { namespace rp2040_pio_led_strip { @@ -23,6 +25,19 @@ static std::map conf_count_ = { {CHIPSET_WS2812, false}, {CHIPSET_WS2812B, false}, {CHIPSET_SK6812, false}, {CHIPSET_SM16703, false}, {CHIPSET_CUSTOM, false}, }; +static bool dma_chan_active_[12]; +static struct semaphore dma_write_complete_sem_[12]; + +// DMA interrupt service routine +void RP2040PIOLEDStripLightOutput::dma_write_complete_handler_() { + uint32_t channel = dma_hw->ints0; + for (uint dma_chan = 0; dma_chan < 12; ++dma_chan) { + if (RP2040PIOLEDStripLightOutput::dma_chan_active_[dma_chan] && (channel & (1u << dma_chan))) { + dma_hw->ints0 = (1u << dma_chan); // Clear the interrupt + sem_release(&RP2040PIOLEDStripLightOutput::dma_write_complete_sem_[dma_chan]); // Handle the interrupt + } + } +} void RP2040PIOLEDStripLightOutput::setup() { ESP_LOGCONFIG(TAG, "Setting up RP2040 LED Strip..."); @@ -57,22 +72,22 @@ 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 (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; } // keep track of how many instances of the PIO program are running on each PIO - num_instance_[this->pio_ == pio0 ? 0 : 1]++; + RP2040PIOLEDStripLightOutput::num_instance_[this->pio_ == pio0 ? 0 : 1]++; // if there are multiple strips of the same chipset, we can reuse the same PIO program and save space if (this->conf_count_[this->chipset_]) { - offset = chipset_offsets_[this->chipset_]; + offset = RP2040PIOLEDStripLightOutput::chipset_offsets_[this->chipset_]; } else { // Load the assembled program into the PIO and get its location in the PIO's instruction memory and save it offset = pio_add_program(this->pio_, this->program_); - chipset_offsets_[this->chipset_] = offset; - conf_count_[this->chipset_] = true; + RP2040PIOLEDStripLightOutput::chipset_offsets_[this->chipset_] = offset; + RP2040PIOLEDStripLightOutput::conf_count_[this->chipset_] = true; } // Configure the state machine's PIO, and start it @@ -93,6 +108,9 @@ void RP2040PIOLEDStripLightOutput::setup() { return; } + // Mark the DMA channel as active + RP2040PIOLEDStripLightOutput::dma_chan_active_[this->dma_chan_] = true; + this->dma_config_ = dma_channel_get_default_config(this->dma_chan_); channel_config_set_transfer_data_size( &this->dma_config_, @@ -109,6 +127,13 @@ void RP2040PIOLEDStripLightOutput::setup() { false // don't start yet ); + // Initialize the semaphore for this DMA channel + sem_init(&RP2040PIOLEDStripLightOutput::dma_write_complete_sem_[this->dma_chan_], 1, 1); + + irq_set_exclusive_handler(DMA_IRQ_0, dma_write_complete_handler_); // after DMA all data, raise an interrupt + dma_channel_set_irq0_enabled(this->dma_chan_, true); // map DMA channel to interrupt + irq_set_enabled(DMA_IRQ_0, true); // enable interrupt + this->init_(this->pio_, this->sm_, offset, this->pin_, this->max_refresh_rate_); } @@ -126,6 +151,7 @@ void RP2040PIOLEDStripLightOutput::write_state(light::LightState *state) { } // the bits are already in the correct order for the pio program so we can just copy the buffer using DMA + sem_acquire_blocking(&RP2040PIOLEDStripLightOutput::dma_write_complete_sem_[this->dma_chan_]); dma_channel_transfer_from_buffer_now(this->dma_chan_, this->buf_, this->get_buffer_size_()); } diff --git a/esphome/components/rp2040_pio_led_strip/led_strip.h b/esphome/components/rp2040_pio_led_strip/led_strip.h index 9976842f02..7b62648974 100644 --- a/esphome/components/rp2040_pio_led_strip/led_strip.h +++ b/esphome/components/rp2040_pio_led_strip/led_strip.h @@ -13,6 +13,7 @@ #include #include #include +#include #include namespace esphome { @@ -95,6 +96,8 @@ class RP2040PIOLEDStripLightOutput : public light::AddressableLight { size_t get_buffer_size_() const { return this->num_leds_ * (3 + this->is_rgbw_); } + static void dma_write_complete_handler_(); + uint8_t *buf_{nullptr}; uint8_t *effect_data_{nullptr}; @@ -120,6 +123,8 @@ class RP2040PIOLEDStripLightOutput : public light::AddressableLight { inline static int num_instance_[2]; inline static std::map conf_count_; inline static std::map chipset_offsets_; + inline static bool dma_chan_active_[12]; + inline static struct semaphore dma_write_complete_sem_[12]; }; } // namespace rp2040_pio_led_strip From c043bbe598f7b3d92c2a12969b1f2fbecc1f4fb6 Mon Sep 17 00:00:00 2001 From: NP v/d Spek Date: Tue, 20 Aug 2024 00:22:19 +0200 Subject: [PATCH 1975/2101] add the ability to add more idf components to an existing setup (#7302) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/esp32/__init__.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 0a5dd46478..b630c7638e 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -172,6 +172,19 @@ def add_idf_component( KEY_COMPONENTS: components, KEY_SUBMODULES: submodules, } + else: + component_config = CORE.data[KEY_ESP32][KEY_COMPONENTS][name] + if components is not None: + component_config[KEY_COMPONENTS] = list( + set(component_config[KEY_COMPONENTS] + components) + ) + if submodules is not None: + if component_config[KEY_SUBMODULES] is None: + component_config[KEY_SUBMODULES] = submodules + else: + component_config[KEY_SUBMODULES] = list( + set(component_config[KEY_SUBMODULES] + submodules) + ) def add_extra_script(stage: str, filename: str, path: str): From 436c6282da1a1c784ab7365f99e59fc00f88cf0f Mon Sep 17 00:00:00 2001 From: Sung-jin Brian Hong Date: Wed, 21 Aug 2024 08:44:21 +0900 Subject: [PATCH 1976/2101] Fix waveshare 2.13" epaper stride calculation error (#7303) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- .../components/waveshare_epaper/waveshare_epaper.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/esphome/components/waveshare_epaper/waveshare_epaper.cpp b/esphome/components/waveshare_epaper/waveshare_epaper.cpp index 24df428e6f..7c1d436673 100644 --- a/esphome/components/waveshare_epaper/waveshare_epaper.cpp +++ b/esphome/components/waveshare_epaper/waveshare_epaper.cpp @@ -480,7 +480,7 @@ void HOT WaveshareEPaperTypeA::display() { this->start_data_(); switch (this->model_) { case TTGO_EPAPER_2_13_IN_B1: { // block needed because of variable initializations - int16_t wb = ((this->get_width_internal()) >> 3); + int16_t wb = ((this->get_width_controller()) >> 3); for (int i = 0; i < this->get_height_internal(); i++) { for (int j = 0; j < wb; j++) { int idx = j + (this->get_height_internal() - 1 - i) * wb; @@ -766,7 +766,7 @@ void WaveshareEPaper2P7InV2::initialize() { // XRAM_START_AND_END_POSITION this->command(0x44); this->data(0x00); - this->data(((get_width_internal() - 1) >> 3) & 0xFF); + this->data(((this->get_width_controller() - 1) >> 3) & 0xFF); // YRAM_START_AND_END_POSITION this->command(0x45); this->data(0x00); @@ -928,8 +928,8 @@ void HOT WaveshareEPaper2P7InB::display() { // TCON_RESOLUTION this->command(0x61); - this->data(this->get_width_internal() >> 8); - this->data(this->get_width_internal() & 0xff); // 176 + this->data(this->get_width_controller() >> 8); + this->data(this->get_width_controller() & 0xff); // 176 this->data(this->get_height_internal() >> 8); this->data(this->get_height_internal() & 0xff); // 264 @@ -994,7 +994,7 @@ void WaveshareEPaper2P7InBV2::initialize() { // self.SetWindows(0, 0, self.width-1, self.height-1) // SetWindows(self, Xstart, Ystart, Xend, Yend): - uint32_t xend = this->get_width_internal() - 1; + uint32_t xend = this->get_width_controller() - 1; uint32_t yend = this->get_height_internal() - 1; this->command(0x44); this->data(0x00); From aaae8f4a87d2ed38c35e16705cea0186120e876e Mon Sep 17 00:00:00 2001 From: NewoPL <27411874+NewoPL@users.noreply.github.com> Date: Wed, 21 Aug 2024 01:46:15 +0200 Subject: [PATCH 1977/2101] [rtttl] fix STOPPED state (#7323) --- esphome/components/rtttl/rtttl.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/esphome/components/rtttl/rtttl.cpp b/esphome/components/rtttl/rtttl.cpp index a97120499d..495b5c1c8a 100644 --- a/esphome/components/rtttl/rtttl.cpp +++ b/esphome/components/rtttl/rtttl.cpp @@ -32,7 +32,7 @@ void Rtttl::play(std::string rtttl) { if (this->state_ != State::STATE_STOPPED && this->state_ != State::STATE_STOPPING) { int pos = this->rtttl_.find(':'); auto name = this->rtttl_.substr(0, pos); - ESP_LOGW(TAG, "RTTL Component is already playing: %s", name.c_str()); + ESP_LOGW(TAG, "RTTTL Component is already playing: %s", name.c_str()); return; } @@ -122,6 +122,7 @@ 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 @@ -129,10 +130,10 @@ void Rtttl::stop() { if (this->speaker_->is_running()) { this->speaker_->stop(); } + this->set_state_(STATE_STOPPING); } #endif this->note_duration_ = 0; - this->set_state_(STATE_STOPPING); } void Rtttl::loop() { @@ -342,6 +343,7 @@ void 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 @@ -354,9 +356,9 @@ void Rtttl::finish_() { this->speaker_->play((uint8_t *) (&sample), 8); this->speaker_->finish(); + this->set_state_(State::STATE_STOPPING); } #endif - this->set_state_(State::STATE_STOPPING); this->note_duration_ = 0; this->on_finished_playback_callback_.call(); ESP_LOGD(TAG, "Playback finished"); From 4ed6a648699c47c135ac992171757d49c75fbf74 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 21 Aug 2024 11:46:56 +1200 Subject: [PATCH 1978/2101] Bump version to 2024.8.0b4 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index a321ddd19f..788eca10a1 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.8.0b3" +__version__ = "2024.8.0b4" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 5d4bf5f8e5431cb3e08ccfddba9ce4bc269ab263 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 21 Aug 2024 14:20:29 +1200 Subject: [PATCH 1979/2101] Bump version to 2024.8.0 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 788eca10a1..f99d442be3 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.8.0b4" +__version__ = "2024.8.0" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 68272c39c0176ce33c13646ac29ccb3d3d0ca981 Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Thu, 22 Aug 2024 02:58:11 +0200 Subject: [PATCH 1980/2101] Add output source priority "hybrid" (#7322) --- esphome/components/pipsolar/pipsolar.cpp | 3 +++ esphome/components/pipsolar/pipsolar.h | 1 + esphome/components/pipsolar/switch/__init__.py | 2 ++ tests/components/pipsolar/test.esp32-ard.yaml | 2 ++ tests/components/pipsolar/test.esp32-c3-ard.yaml | 2 ++ tests/components/pipsolar/test.esp32-c3-idf.yaml | 2 ++ tests/components/pipsolar/test.esp32-idf.yaml | 2 ++ tests/components/pipsolar/test.esp8266-ard.yaml | 2 ++ tests/components/pipsolar/test.rp2040-ard.yaml | 2 ++ 9 files changed, 18 insertions(+) diff --git a/esphome/components/pipsolar/pipsolar.cpp b/esphome/components/pipsolar/pipsolar.cpp index 2cd1aeba44..c4bc018b75 100644 --- a/esphome/components/pipsolar/pipsolar.cpp +++ b/esphome/components/pipsolar/pipsolar.cpp @@ -136,6 +136,9 @@ void Pipsolar::loop() { if (this->output_source_priority_battery_switch_) { this->output_source_priority_battery_switch_->publish_state(value_output_source_priority_ == 2); } + if (this->output_source_priority_hybrid_switch_) { + this->output_source_priority_hybrid_switch_->publish_state(value_output_source_priority_ == 3); + } if (this->charger_source_priority_) { this->charger_source_priority_->publish_state(value_charger_source_priority_); } diff --git a/esphome/components/pipsolar/pipsolar.h b/esphome/components/pipsolar/pipsolar.h index f20f44f095..373911b2d7 100644 --- a/esphome/components/pipsolar/pipsolar.h +++ b/esphome/components/pipsolar/pipsolar.h @@ -174,6 +174,7 @@ class Pipsolar : public uart::UARTDevice, public PollingComponent { PIPSOLAR_SWITCH(output_source_priority_utility_switch, QPIRI) PIPSOLAR_SWITCH(output_source_priority_solar_switch, QPIRI) PIPSOLAR_SWITCH(output_source_priority_battery_switch, QPIRI) + PIPSOLAR_SWITCH(output_source_priority_hybrid_switch, QPIRI) PIPSOLAR_SWITCH(input_voltage_range_switch, QPIRI) PIPSOLAR_SWITCH(pv_ok_condition_for_parallel_switch, QPIRI) PIPSOLAR_SWITCH(pv_power_balance_switch, QPIRI) diff --git a/esphome/components/pipsolar/switch/__init__.py b/esphome/components/pipsolar/switch/__init__.py index 7658c7d4f8..80bcdad62e 100644 --- a/esphome/components/pipsolar/switch/__init__.py +++ b/esphome/components/pipsolar/switch/__init__.py @@ -9,6 +9,7 @@ DEPENDENCIES = ["uart"] CONF_OUTPUT_SOURCE_PRIORITY_UTILITY = "output_source_priority_utility" CONF_OUTPUT_SOURCE_PRIORITY_SOLAR = "output_source_priority_solar" CONF_OUTPUT_SOURCE_PRIORITY_BATTERY = "output_source_priority_battery" +CONF_OUTPUT_SOURCE_PRIORITY_HYBRID = "output_source_priority_hybrid" CONF_INPUT_VOLTAGE_RANGE = "input_voltage_range" CONF_PV_OK_CONDITION_FOR_PARALLEL = "pv_ok_condition_for_parallel" CONF_PV_POWER_BALANCE = "pv_power_balance" @@ -17,6 +18,7 @@ TYPES = { CONF_OUTPUT_SOURCE_PRIORITY_UTILITY: ("POP00", None), CONF_OUTPUT_SOURCE_PRIORITY_SOLAR: ("POP01", None), CONF_OUTPUT_SOURCE_PRIORITY_BATTERY: ("POP02", None), + CONF_OUTPUT_SOURCE_PRIORITY_HYBRID: ("POP03", None), CONF_INPUT_VOLTAGE_RANGE: ("PGR01", "PGR00"), CONF_PV_OK_CONDITION_FOR_PARALLEL: ("PPVOKC1", "PPVOKC0"), CONF_PV_POWER_BALANCE: ("PSPB1", "PSPB0"), diff --git a/tests/components/pipsolar/test.esp32-ard.yaml b/tests/components/pipsolar/test.esp32-ard.yaml index fcd4575739..b7a7e0cbd9 100644 --- a/tests/components/pipsolar/test.esp32-ard.yaml +++ b/tests/components/pipsolar/test.esp32-ard.yaml @@ -220,6 +220,8 @@ switch: name: inverter0_output_source_priority_solar output_source_priority_battery: name: inverter0_output_source_priority_battery + output_source_priority_hybrid: + name: inverter0_output_source_priority_hybrid input_voltage_range: name: inverter0_input_voltage_range pv_ok_condition_for_parallel: diff --git a/tests/components/pipsolar/test.esp32-c3-ard.yaml b/tests/components/pipsolar/test.esp32-c3-ard.yaml index 12e9266343..83d7070669 100644 --- a/tests/components/pipsolar/test.esp32-c3-ard.yaml +++ b/tests/components/pipsolar/test.esp32-c3-ard.yaml @@ -220,6 +220,8 @@ switch: name: inverter0_output_source_priority_solar output_source_priority_battery: name: inverter0_output_source_priority_battery + output_source_priority_hybrid: + name: inverter0_output_source_priority_hybrid input_voltage_range: name: inverter0_input_voltage_range pv_ok_condition_for_parallel: diff --git a/tests/components/pipsolar/test.esp32-c3-idf.yaml b/tests/components/pipsolar/test.esp32-c3-idf.yaml index 12e9266343..83d7070669 100644 --- a/tests/components/pipsolar/test.esp32-c3-idf.yaml +++ b/tests/components/pipsolar/test.esp32-c3-idf.yaml @@ -220,6 +220,8 @@ switch: name: inverter0_output_source_priority_solar output_source_priority_battery: name: inverter0_output_source_priority_battery + output_source_priority_hybrid: + name: inverter0_output_source_priority_hybrid input_voltage_range: name: inverter0_input_voltage_range pv_ok_condition_for_parallel: diff --git a/tests/components/pipsolar/test.esp32-idf.yaml b/tests/components/pipsolar/test.esp32-idf.yaml index fcd4575739..b7a7e0cbd9 100644 --- a/tests/components/pipsolar/test.esp32-idf.yaml +++ b/tests/components/pipsolar/test.esp32-idf.yaml @@ -220,6 +220,8 @@ switch: name: inverter0_output_source_priority_solar output_source_priority_battery: name: inverter0_output_source_priority_battery + output_source_priority_hybrid: + name: inverter0_output_source_priority_hybrid input_voltage_range: name: inverter0_input_voltage_range pv_ok_condition_for_parallel: diff --git a/tests/components/pipsolar/test.esp8266-ard.yaml b/tests/components/pipsolar/test.esp8266-ard.yaml index 12e9266343..83d7070669 100644 --- a/tests/components/pipsolar/test.esp8266-ard.yaml +++ b/tests/components/pipsolar/test.esp8266-ard.yaml @@ -220,6 +220,8 @@ switch: name: inverter0_output_source_priority_solar output_source_priority_battery: name: inverter0_output_source_priority_battery + output_source_priority_hybrid: + name: inverter0_output_source_priority_hybrid input_voltage_range: name: inverter0_input_voltage_range pv_ok_condition_for_parallel: diff --git a/tests/components/pipsolar/test.rp2040-ard.yaml b/tests/components/pipsolar/test.rp2040-ard.yaml index 12e9266343..83d7070669 100644 --- a/tests/components/pipsolar/test.rp2040-ard.yaml +++ b/tests/components/pipsolar/test.rp2040-ard.yaml @@ -220,6 +220,8 @@ switch: name: inverter0_output_source_priority_solar output_source_priority_battery: name: inverter0_output_source_priority_battery + output_source_priority_hybrid: + name: inverter0_output_source_priority_hybrid input_voltage_range: name: inverter0_input_voltage_range pv_ok_condition_for_parallel: From 11e155d86657c24014694cca23200d5a80b75cb2 Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Wed, 21 Aug 2024 17:58:43 -0700 Subject: [PATCH 1981/2101] Enable verbose mode from env ESPHOME_VERBOSE or --verbose (#6987) --- esphome/__main__.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/esphome/__main__.py b/esphome/__main__.py index 5c197ff486..cf2741dbdb 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -38,7 +38,7 @@ from esphome.const import ( SECRETS_FILES, ) from esphome.core import CORE, EsphomeError, coroutine -from esphome.helpers import indent, is_ip_address +from esphome.helpers import indent, is_ip_address, get_bool_env from esphome.log import Fore, color, setup_log from esphome.util import ( get_serial_ports, @@ -731,7 +731,11 @@ POST_CONFIG_ACTIONS = { def parse_args(argv): options_parser = argparse.ArgumentParser(add_help=False) options_parser.add_argument( - "-v", "--verbose", help="Enable verbose ESPHome logs.", action="store_true" + "-v", + "--verbose", + help="Enable verbose ESPHome logs.", + action="store_true", + default=get_bool_env("ESPHOME_VERBOSE"), ) options_parser.add_argument( "-q", "--quiet", help="Disable all ESPHome logs.", action="store_true" From ab620acd4f086242dd6ecbe6f5763962982dc303 Mon Sep 17 00:00:00 2001 From: Piotr Szulc Date: Thu, 22 Aug 2024 02:59:31 +0200 Subject: [PATCH 1982/2101] Tuya Number: allow to set hidden datapoints (#7024) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/tuya/__init__.py | 1 + esphome/components/tuya/number/__init__.py | 38 ++++++++++++++++++- .../components/tuya/number/tuya_number.cpp | 19 ++++++++++ esphome/components/tuya/number/tuya_number.h | 6 ++- 4 files changed, 61 insertions(+), 3 deletions(-) diff --git a/esphome/components/tuya/__init__.py b/esphome/components/tuya/__init__.py index 2eaaa2a625..0738f9b6a4 100644 --- a/esphome/components/tuya/__init__.py +++ b/esphome/components/tuya/__init__.py @@ -15,6 +15,7 @@ CONF_DATAPOINT_TYPE = "datapoint_type" CONF_STATUS_PIN = "status_pin" tuya_ns = cg.esphome_ns.namespace("tuya") +TuyaDatapointType = tuya_ns.enum("TuyaDatapointType", is_class=True) Tuya = tuya_ns.class_("Tuya", cg.Component, uart.UARTDevice) DPTYPE_ANY = "any" diff --git a/esphome/components/tuya/number/__init__.py b/esphome/components/tuya/number/__init__.py index 4dae6d8d60..25be6329ab 100644 --- a/esphome/components/tuya/number/__init__.py +++ b/esphome/components/tuya/number/__init__.py @@ -8,18 +8,36 @@ from esphome.const import ( CONF_MIN_VALUE, CONF_MULTIPLY, CONF_STEP, + CONF_INITIAL_VALUE, ) -from .. import tuya_ns, CONF_TUYA_ID, Tuya +from .. import tuya_ns, CONF_TUYA_ID, Tuya, TuyaDatapointType DEPENDENCIES = ["tuya"] CODEOWNERS = ["@frankiboy1"] +CONF_DATAPOINT_HIDDEN = "datapoint_hidden" +CONF_DATAPOINT_TYPE = "datapoint_type" + TuyaNumber = tuya_ns.class_("TuyaNumber", number.Number, cg.Component) +DATAPOINT_TYPES = { + "int": TuyaDatapointType.INTEGER, + "uint": TuyaDatapointType.INTEGER, + "enum": TuyaDatapointType.ENUM, +} + def validate_min_max(config): - if config[CONF_MAX_VALUE] <= config[CONF_MIN_VALUE]: + max_value = config[CONF_MAX_VALUE] + min_value = config[CONF_MIN_VALUE] + if max_value <= min_value: raise cv.Invalid("max_value must be greater than min_value") + if hidden_config := config.get(CONF_DATAPOINT_HIDDEN): + if (initial_value := hidden_config.get(CONF_INITIAL_VALUE, None)) is not None: + if (initial_value > max_value) or (initial_value < min_value): + raise cv.Invalid( + f"{CONF_INITIAL_VALUE} must be a value between {CONF_MAX_VALUE} and {CONF_MIN_VALUE}" + ) return config @@ -33,6 +51,16 @@ CONFIG_SCHEMA = cv.All( cv.Required(CONF_MIN_VALUE): cv.float_, cv.Required(CONF_STEP): cv.positive_float, cv.Optional(CONF_MULTIPLY, default=1.0): cv.float_, + cv.Optional(CONF_DATAPOINT_HIDDEN): cv.All( + cv.Schema( + { + cv.Required(CONF_DATAPOINT_TYPE): cv.enum( + DATAPOINT_TYPES, lower=True + ), + cv.Optional(CONF_INITIAL_VALUE): cv.float_, + } + ) + ), } ) .extend(cv.COMPONENT_SCHEMA), @@ -56,3 +84,9 @@ async def to_code(config): cg.add(var.set_tuya_parent(parent)) cg.add(var.set_number_id(config[CONF_NUMBER_DATAPOINT])) + if hidden_config := config.get(CONF_DATAPOINT_HIDDEN): + cg.add(var.set_datapoint_type(hidden_config[CONF_DATAPOINT_TYPE])) + if ( + hidden_init_value := hidden_config.get(CONF_INITIAL_VALUE, None) + ) is not None: + cg.add(var.set_datapoint_initial_value(hidden_init_value)) diff --git a/esphome/components/tuya/number/tuya_number.cpp b/esphome/components/tuya/number/tuya_number.cpp index e883c72d3d..7eeb08fde2 100644 --- a/esphome/components/tuya/number/tuya_number.cpp +++ b/esphome/components/tuya/number/tuya_number.cpp @@ -15,8 +15,18 @@ void TuyaNumber::setup() { ESP_LOGV(TAG, "MCU reported number %u is: %u", datapoint.id, datapoint.value_enum); this->publish_state(datapoint.value_enum); } + if ((this->type_) && (this->type_ != datapoint.type)) { + ESP_LOGW(TAG, "Reported type (%d) different than previously set (%d)!", static_cast(datapoint.type), + static_cast(*this->type_)); + } this->type_ = datapoint.type; }); + + this->parent_->add_on_initialized_callback([this] { + if ((this->initial_value_) && (this->type_)) { + this->control(*this->initial_value_); + } + }); } void TuyaNumber::control(float value) { @@ -33,6 +43,15 @@ void TuyaNumber::control(float value) { void TuyaNumber::dump_config() { LOG_NUMBER("", "Tuya Number", this); ESP_LOGCONFIG(TAG, " Number has datapoint ID %u", this->number_id_); + if (this->type_) { + ESP_LOGCONFIG(TAG, " Datapoint type is %d", static_cast(*this->type_)); + } else { + ESP_LOGCONFIG(TAG, " Datapoint type is unknown"); + } + + if (this->initial_value_) { + ESP_LOGCONFIG(TAG, " Initial Value: %f", *this->initial_value_); + } } } // namespace tuya diff --git a/esphome/components/tuya/number/tuya_number.h b/esphome/components/tuya/number/tuya_number.h index f64dac8957..545584128e 100644 --- a/esphome/components/tuya/number/tuya_number.h +++ b/esphome/components/tuya/number/tuya_number.h @@ -3,6 +3,7 @@ #include "esphome/core/component.h" #include "esphome/components/tuya/tuya.h" #include "esphome/components/number/number.h" +#include "esphome/core/optional.h" namespace esphome { namespace tuya { @@ -13,6 +14,8 @@ class TuyaNumber : public number::Number, public Component { void dump_config() override; void set_number_id(uint8_t number_id) { this->number_id_ = number_id; } void set_write_multiply(float factor) { multiply_by_ = factor; } + void set_datapoint_type(TuyaDatapointType type) { type_ = type; } + void set_datapoint_initial_value(float value) { this->initial_value_ = value; } void set_tuya_parent(Tuya *parent) { this->parent_ = parent; } @@ -22,7 +25,8 @@ class TuyaNumber : public number::Number, public Component { Tuya *parent_; uint8_t number_id_{0}; float multiply_by_{1.0}; - TuyaDatapointType type_{}; + optional type_{}; + optional initial_value_{}; }; } // namespace tuya From 5cc8dbace41f3f5863473d60367f0d32c876ac7c Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Fri, 23 Aug 2024 04:56:53 +1000 Subject: [PATCH 1983/2101] [lvgl] Bug fixes (#7338) --- esphome/components/lvgl/automation.py | 16 +++++++++++++--- esphome/components/lvgl/lvgl_esphome.cpp | 7 +++++++ esphome/components/lvgl/lvgl_esphome.h | 1 + esphome/components/lvgl/widgets/__init__.py | 6 ++++++ esphome/components/lvgl/widgets/line.py | 12 +++++++----- esphome/components/lvgl/widgets/msgbox.py | 3 ++- tests/components/lvgl/lvgl-package.yaml | 6 +++++- 7 files changed, 41 insertions(+), 10 deletions(-) diff --git a/esphome/components/lvgl/automation.py b/esphome/components/lvgl/automation.py index a39f589136..efcac977ab 100644 --- a/esphome/components/lvgl/automation.py +++ b/esphome/components/lvgl/automation.py @@ -5,6 +5,7 @@ from esphome import automation import esphome.codegen as cg import esphome.config_validation as cv from esphome.const import CONF_ID, CONF_TIMEOUT +from esphome.cpp_generator import RawExpression from esphome.cpp_types import nullptr from .defines import ( @@ -26,6 +27,7 @@ from .lvcode import ( add_line_marks, lv, lv_add, + lv_expr, lv_obj, lvgl_comp, ) @@ -38,7 +40,13 @@ from .types import ( lv_disp_t, lv_obj_t, ) -from .widgets import Widget, get_widgets, lv_scr_act, set_obj_properties +from .widgets import ( + Widget, + get_widgets, + lv_scr_act, + set_obj_properties, + wait_for_widgets, +) async def action_to_code( @@ -48,10 +56,12 @@ async def action_to_code( template_arg, args, ): + await wait_for_widgets() async with LambdaContext(parameters=args, where=action_id) as context: + with LvConditional(lv_expr.is_pre_initialise()): + context.add(RawExpression("return")) for widget in widgets: - with LvConditional(widget.obj != nullptr): - await action(widget) + await action(widget) var = cg.new_Pvariable(action_id, template_arg, await context.get_lambda()) return var diff --git a/esphome/components/lvgl/lvgl_esphome.cpp b/esphome/components/lvgl/lvgl_esphome.cpp index 92f7a880c3..6882986e7c 100644 --- a/esphome/components/lvgl/lvgl_esphome.cpp +++ b/esphome/components/lvgl/lvgl_esphome.cpp @@ -294,6 +294,13 @@ void LvglComponent::loop() { } lv_timer_handler_run_in_period(5); } +bool lv_is_pre_initialise() { + if (!lv_is_initialized()) { + ESP_LOGE(TAG, "LVGL call before component is initialised"); + return true; + } + return false; +} #ifdef USE_LVGL_IMAGE lv_img_dsc_t *lv_img_from(image::Image *src, lv_img_dsc_t *img_dsc) { diff --git a/esphome/components/lvgl/lvgl_esphome.h b/esphome/components/lvgl/lvgl_esphome.h index 3a3d1aa6c5..df3d4aa68c 100644 --- a/esphome/components/lvgl/lvgl_esphome.h +++ b/esphome/components/lvgl/lvgl_esphome.h @@ -40,6 +40,7 @@ namespace lvgl { extern lv_event_code_t lv_api_event; // NOLINT extern lv_event_code_t lv_update_event; // NOLINT +extern bool lv_is_pre_initialise(); #ifdef USE_LVGL_COLOR inline lv_color_t lv_color_from(Color color) { return lv_color_make(color.red, color.green, color.blue); } #endif // USE_LVGL_COLOR diff --git a/esphome/components/lvgl/widgets/__init__.py b/esphome/components/lvgl/widgets/__init__.py index 4abb25c61d..50da6e131d 100644 --- a/esphome/components/lvgl/widgets/__init__.py +++ b/esphome/components/lvgl/widgets/__init__.py @@ -1,3 +1,4 @@ +import asyncio import sys from typing import Any, Union @@ -223,6 +224,11 @@ async def get_widget_(wid: Widget): return await FakeAwaitable(get_widget_generator(wid)) +async def wait_for_widgets(): + while not Widget.widgets_completed: + await asyncio.sleep(0) + + async def get_widgets(config: Union[dict, list], id: str = CONF_ID) -> list[Widget]: if not config: return [] diff --git a/esphome/components/lvgl/widgets/line.py b/esphome/components/lvgl/widgets/line.py index 8ce4b1965f..4c6439fde4 100644 --- a/esphome/components/lvgl/widgets/line.py +++ b/esphome/components/lvgl/widgets/line.py @@ -3,7 +3,7 @@ import functools import esphome.codegen as cg import esphome.config_validation as cv -from ..defines import CONF_MAIN, literal +from ..defines import CONF_MAIN from ..lvcode import lv from ..types import LvType from . import Widget, WidgetType @@ -38,13 +38,15 @@ LINE_SCHEMA = { class LineType(WidgetType): def __init__(self): - super().__init__(CONF_LINE, LvType("lv_line_t"), (CONF_MAIN,), LINE_SCHEMA) + super().__init__( + CONF_LINE, LvType("lv_line_t"), (CONF_MAIN,), LINE_SCHEMA, modify_schema={} + ) async def to_code(self, w: Widget, config): """For a line object, create and add the points""" - data = literal(config[CONF_POINTS]) - points = cg.static_const_array(config[CONF_POINT_LIST_ID], data) - lv.line_set_points(w.obj, points, len(data)) + if data := config.get(CONF_POINTS): + points = cg.static_const_array(config[CONF_POINT_LIST_ID], data) + lv.line_set_points(w.obj, points, len(data)) line_spec = LineType() diff --git a/esphome/components/lvgl/widgets/msgbox.py b/esphome/components/lvgl/widgets/msgbox.py index 63c4326c7c..c377af6bde 100644 --- a/esphome/components/lvgl/widgets/msgbox.py +++ b/esphome/components/lvgl/widgets/msgbox.py @@ -13,7 +13,7 @@ from ..defines import ( TYPE_FLEX, literal, ) -from ..helpers import add_lv_use +from ..helpers import add_lv_use, lvgl_components_required from ..lv_validation import lv_bool, lv_pct, lv_text from ..lvcode import ( EVENT_ARG, @@ -72,6 +72,7 @@ async def msgbox_to_code(conf): *buttonmatrix_spec.get_uses(), *button_spec.get_uses(), ) + lvgl_components_required.add("BUTTONMATRIX") messagebox_id = conf[CONF_ID] outer = lv_Pvariable(lv_obj_t, messagebox_id.id) buttonmatrix = new_Pvariable( diff --git a/tests/components/lvgl/lvgl-package.yaml b/tests/components/lvgl/lvgl-package.yaml index 800d6eff27..1479ce7358 100644 --- a/tests/components/lvgl/lvgl-package.yaml +++ b/tests/components/lvgl/lvgl-package.yaml @@ -379,6 +379,7 @@ lvgl: format: "bar value %f" args: [x] - line: + id: lv_line_id align: center points: - 5, 5 @@ -387,7 +388,10 @@ lvgl: - 180, 60 - 240, 10 on_click: - lvgl.page.next: + - lvgl.widget.update: + id: lv_line_id + line_color: 0xFFFF + - lvgl.page.next: - switch: align: right_mid - checkbox: From 3c65cabe1dc7a1d94cb889617427f2239e6fb734 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20Mart=C3=ADn?= Date: Thu, 22 Aug 2024 23:30:22 +0200 Subject: [PATCH 1984/2101] feat: Expand ByteBuffer (#7316) Co-authored-by: clydebarrow <2366188+clydebarrow@users.noreply.github.com> Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/core/bytebuffer.cpp | 225 +++++++++++++++++++++--------------- esphome/core/bytebuffer.h | 90 +++++++++++---- 2 files changed, 201 insertions(+), 114 deletions(-) diff --git a/esphome/core/bytebuffer.cpp b/esphome/core/bytebuffer.cpp index fb2ade3166..65525ecfcf 100644 --- a/esphome/core/bytebuffer.cpp +++ b/esphome/core/bytebuffer.cpp @@ -1,19 +1,64 @@ #include "bytebuffer.h" #include +#include namespace esphome { -ByteBuffer ByteBuffer::create(size_t capacity) { - std::vector data(capacity); - return {data}; -} - -ByteBuffer ByteBuffer::wrap(uint8_t *ptr, size_t len) { +ByteBuffer ByteBuffer::wrap(const uint8_t *ptr, size_t len, Endian endianness) { + // there is a double copy happening here, could be optimized but at cost of clarity. std::vector data(ptr, ptr + len); - return {data}; + ByteBuffer buffer = {data}; + buffer.endianness_ = endianness; + return buffer; } -ByteBuffer ByteBuffer::wrap(std::vector data) { return {std::move(data)}; } +ByteBuffer ByteBuffer::wrap(std::vector const &data, Endian endianness) { + ByteBuffer buffer = {data}; + buffer.endianness_ = endianness; + return buffer; +} + +ByteBuffer ByteBuffer::wrap(uint8_t value) { + ByteBuffer buffer = ByteBuffer(1); + buffer.put_uint8(value); + buffer.flip(); + return buffer; +} + +ByteBuffer ByteBuffer::wrap(uint16_t value, Endian endianness) { + ByteBuffer buffer = ByteBuffer(2, endianness); + buffer.put_uint16(value); + buffer.flip(); + return buffer; +} + +ByteBuffer ByteBuffer::wrap(uint32_t value, Endian endianness) { + ByteBuffer buffer = ByteBuffer(4, endianness); + buffer.put_uint32(value); + buffer.flip(); + return buffer; +} + +ByteBuffer ByteBuffer::wrap(uint64_t value, Endian endianness) { + ByteBuffer buffer = ByteBuffer(8, endianness); + buffer.put_uint64(value); + buffer.flip(); + return buffer; +} + +ByteBuffer ByteBuffer::wrap(float value, Endian endianness) { + ByteBuffer buffer = ByteBuffer(sizeof(float), endianness); + buffer.put_float(value); + buffer.flip(); + return buffer; +} + +ByteBuffer ByteBuffer::wrap(double value, Endian endianness) { + ByteBuffer buffer = ByteBuffer(sizeof(double), endianness); + buffer.put_double(value); + buffer.flip(); + return buffer; +} void ByteBuffer::set_limit(size_t limit) { assert(limit <= this->get_capacity()); @@ -27,108 +72,102 @@ void ByteBuffer::clear() { this->limit_ = this->get_capacity(); this->position_ = 0; } -uint16_t ByteBuffer::get_uint16() { - assert(this->get_remaining() >= 2); - uint16_t value; - if (endianness_ == LITTLE) { - value = this->data_[this->position_++]; - value |= this->data_[this->position_++] << 8; - } else { - value = this->data_[this->position_++] << 8; - value |= this->data_[this->position_++]; - } - return value; +void ByteBuffer::flip() { + this->limit_ = this->position_; + this->position_ = 0; } -uint32_t ByteBuffer::get_uint32() { - assert(this->get_remaining() >= 4); - uint32_t value; - if (endianness_ == LITTLE) { - value = this->data_[this->position_++]; - value |= this->data_[this->position_++] << 8; - value |= this->data_[this->position_++] << 16; - value |= this->data_[this->position_++] << 24; - } else { - value = this->data_[this->position_++] << 24; - value |= this->data_[this->position_++] << 16; - value |= this->data_[this->position_++] << 8; - value |= this->data_[this->position_++]; - } - return value; -} -uint32_t ByteBuffer::get_uint24() { - assert(this->get_remaining() >= 3); - uint32_t value; - if (endianness_ == LITTLE) { - value = this->data_[this->position_++]; - value |= this->data_[this->position_++] << 8; - value |= this->data_[this->position_++] << 16; - } else { - value = this->data_[this->position_++] << 16; - value |= this->data_[this->position_++] << 8; - value |= this->data_[this->position_++]; - } - return value; -} -uint32_t ByteBuffer::get_int24() { - auto value = this->get_uint24(); - uint32_t mask = (~(uint32_t) 0) << 23; - if ((value & mask) != 0) - value |= mask; - return value; -} +/// Getters uint8_t ByteBuffer::get_uint8() { assert(this->get_remaining() >= 1); return this->data_[this->position_++]; } -float ByteBuffer::get_float() { - auto value = this->get_uint32(); - return *(float *) &value; +uint64_t ByteBuffer::get_uint(size_t length) { + assert(this->get_remaining() >= length); + uint64_t value = 0; + if (this->endianness_ == LITTLE) { + this->position_ += length; + auto index = this->position_; + while (length-- != 0) { + value <<= 8; + value |= this->data_[--index]; + } + } else { + while (length-- != 0) { + value <<= 8; + value |= this->data_[this->position_++]; + } + } + return value; } + +uint32_t ByteBuffer::get_int24() { + auto value = this->get_uint24(); + uint32_t mask = (~static_cast(0)) << 23; + if ((value & mask) != 0) + value |= mask; + return value; +} +float ByteBuffer::get_float() { + assert(this->get_remaining() >= sizeof(float)); + auto ui_value = this->get_uint32(); + float value; + memcpy(&value, &ui_value, sizeof(float)); + return value; +} +double ByteBuffer::get_double() { + assert(this->get_remaining() >= sizeof(double)); + auto ui_value = this->get_uint64(); + double value; + memcpy(&value, &ui_value, sizeof(double)); + return value; +} +std::vector ByteBuffer::get_vector(size_t length) { + assert(this->get_remaining() >= length); + auto start = this->data_.begin() + this->position_; + this->position_ += length; + return {start, start + length}; +} + +/// Putters void ByteBuffer::put_uint8(uint8_t value) { assert(this->get_remaining() >= 1); this->data_[this->position_++] = value; } -void ByteBuffer::put_uint16(uint16_t value) { - assert(this->get_remaining() >= 2); +void ByteBuffer::put_uint(uint64_t value, size_t length) { + assert(this->get_remaining() >= length); if (this->endianness_ == LITTLE) { - this->data_[this->position_++] = (uint8_t) value; - this->data_[this->position_++] = (uint8_t) (value >> 8); + while (length-- != 0) { + this->data_[this->position_++] = static_cast(value); + value >>= 8; + } } else { - this->data_[this->position_++] = (uint8_t) (value >> 8); - this->data_[this->position_++] = (uint8_t) value; + this->position_ += length; + auto index = this->position_; + while (length-- != 0) { + this->data_[--index] = static_cast(value); + value >>= 8; + } } } -void ByteBuffer::put_uint24(uint32_t value) { - assert(this->get_remaining() >= 3); - if (this->endianness_ == LITTLE) { - this->data_[this->position_++] = (uint8_t) value; - this->data_[this->position_++] = (uint8_t) (value >> 8); - this->data_[this->position_++] = (uint8_t) (value >> 16); - } else { - this->data_[this->position_++] = (uint8_t) (value >> 16); - this->data_[this->position_++] = (uint8_t) (value >> 8); - this->data_[this->position_++] = (uint8_t) value; - } +void ByteBuffer::put_float(float value) { + static_assert(sizeof(float) == sizeof(uint32_t), "Float sizes other than 32 bit not supported"); + assert(this->get_remaining() >= sizeof(float)); + uint32_t ui_value; + memcpy(&ui_value, &value, sizeof(float)); // this work-around required to silence compiler warnings + this->put_uint32(ui_value); } -void ByteBuffer::put_uint32(uint32_t value) { - assert(this->get_remaining() >= 4); - if (this->endianness_ == LITTLE) { - this->data_[this->position_++] = (uint8_t) value; - this->data_[this->position_++] = (uint8_t) (value >> 8); - this->data_[this->position_++] = (uint8_t) (value >> 16); - this->data_[this->position_++] = (uint8_t) (value >> 24); - } else { - this->data_[this->position_++] = (uint8_t) (value >> 24); - this->data_[this->position_++] = (uint8_t) (value >> 16); - this->data_[this->position_++] = (uint8_t) (value >> 8); - this->data_[this->position_++] = (uint8_t) value; - } +void ByteBuffer::put_double(double value) { + static_assert(sizeof(double) == sizeof(uint64_t), "Double sizes other than 64 bit not supported"); + assert(this->get_remaining() >= sizeof(double)); + uint64_t ui_value; + memcpy(&ui_value, &value, sizeof(double)); + this->put_uint64(ui_value); } -void ByteBuffer::put_float(float value) { this->put_uint32(*(uint32_t *) &value); } -void ByteBuffer::flip() { - this->limit_ = this->position_; - this->position_ = 0; +void ByteBuffer::put_vector(const std::vector &value) { + assert(this->get_remaining() >= value.size()); + std::copy(value.begin(), value.end(), this->data_.begin() + this->position_); + this->position_ += value.size(); } } // namespace esphome diff --git a/esphome/core/bytebuffer.h b/esphome/core/bytebuffer.h index f242e5e333..d44d01f275 100644 --- a/esphome/core/bytebuffer.h +++ b/esphome/core/bytebuffer.h @@ -15,55 +15,103 @@ enum Endian { LITTLE, BIG }; * * There are three variables maintained pointing into the buffer: * - * 0 <= position <= limit <= capacity - * - * capacity: the maximum amount of data that can be stored + * capacity: the maximum amount of data that can be stored - set on construction and cannot be changed * limit: the limit of the data currently available to get or put * position: the current insert or extract position * + * 0 <= position <= limit <= capacity + * * In addition a mark can be set to the current position with mark(). A subsequent call to reset() will restore * the position to the mark. * * The buffer can be marked to be little-endian (default) or big-endian. All subsequent operations will use that order. * + * The flip() operation will reset the position to 0 and limit to the current position. This is useful for reading + * data from a buffer after it has been written. + * */ class ByteBuffer { public: + // Default constructor (compatibility with TEMPLATABLE_VALUE) + ByteBuffer() : ByteBuffer(std::vector()) {} /** * Create a new Bytebuffer with the given capacity */ - static ByteBuffer create(size_t capacity); + ByteBuffer(size_t capacity, Endian endianness = LITTLE) + : data_(std::vector(capacity)), endianness_(endianness), limit_(capacity){}; /** - * Wrap an existing vector in a Bytebufffer + * Wrap an existing vector in a ByteBufffer */ - static ByteBuffer wrap(std::vector data); + static ByteBuffer wrap(std::vector const &data, Endian endianness = LITTLE); /** - * Wrap an existing array in a Bytebufffer + * Wrap an existing array in a ByteBuffer. Note that this will create a copy of the data. */ - static ByteBuffer wrap(uint8_t *ptr, size_t len); + static ByteBuffer wrap(const uint8_t *ptr, size_t len, Endian endianness = LITTLE); + // Convenience functions to create a ByteBuffer from a value + static ByteBuffer wrap(uint8_t value); + static ByteBuffer wrap(uint16_t value, Endian endianness = LITTLE); + static ByteBuffer wrap(uint32_t value, Endian endianness = LITTLE); + static ByteBuffer wrap(uint64_t value, Endian endianness = LITTLE); + static ByteBuffer wrap(int8_t value) { return wrap(static_cast(value)); } + static ByteBuffer wrap(int16_t value, Endian endianness = LITTLE) { + return wrap(static_cast(value), endianness); + } + static ByteBuffer wrap(int32_t value, Endian endianness = LITTLE) { + return wrap(static_cast(value), endianness); + } + static ByteBuffer wrap(int64_t value, Endian endianness = LITTLE) { + return wrap(static_cast(value), endianness); + } + static ByteBuffer wrap(float value, Endian endianness = LITTLE); + static ByteBuffer wrap(double value, Endian endianness = LITTLE); + static ByteBuffer wrap(bool value) { return wrap(static_cast(value)); } + // Get an integral value from the buffer, increment position by length + uint64_t get_uint(size_t length); // Get one byte from the buffer, increment position by 1 uint8_t get_uint8(); // Get a 16 bit unsigned value, increment by 2 - uint16_t get_uint16(); + uint16_t get_uint16() { return static_cast(this->get_uint(sizeof(uint16_t))); }; // Get a 24 bit unsigned value, increment by 3 - uint32_t get_uint24(); + uint32_t get_uint24() { return static_cast(this->get_uint(3)); }; // Get a 32 bit unsigned value, increment by 4 - uint32_t get_uint32(); - // signed versions of the get functions - uint8_t get_int8() { return (int8_t) this->get_uint8(); }; - int16_t get_int16() { return (int16_t) this->get_uint16(); } + uint32_t get_uint32() { return static_cast(this->get_uint(sizeof(uint32_t))); }; + // Get a 64 bit unsigned value, increment by 8 + uint64_t get_uint64() { return this->get_uint(sizeof(uint64_t)); }; + // Signed versions of the get functions + uint8_t get_int8() { return static_cast(this->get_uint8()); }; + int16_t get_int16() { return static_cast(this->get_uint(sizeof(int16_t))); } uint32_t get_int24(); - int32_t get_int32() { return (int32_t) this->get_uint32(); } + int32_t get_int32() { return static_cast(this->get_uint(sizeof(int32_t))); } + int64_t get_int64() { return static_cast(this->get_uint(sizeof(int64_t))); } // Get a float value, increment by 4 float get_float(); + // Get a double value, increment by 8 + double get_double(); + // Get a bool value, increment by 1 + bool get_bool() { return this->get_uint8(); } + // Get vector of bytes, increment by length + std::vector get_vector(size_t length); - // put values into the buffer, increment the position accordingly + // Put values into the buffer, increment the position accordingly + // put any integral value, length represents the number of bytes + void put_uint(uint64_t value, size_t length); void put_uint8(uint8_t value); - void put_uint16(uint16_t value); - void put_uint24(uint32_t value); - void put_uint32(uint32_t value); + void put_uint16(uint16_t value) { this->put_uint(value, sizeof(uint16_t)); } + void put_uint24(uint32_t value) { this->put_uint(value, 3); } + void put_uint32(uint32_t value) { this->put_uint(value, sizeof(uint32_t)); } + void put_uint64(uint64_t value) { this->put_uint(value, sizeof(uint64_t)); } + // Signed versions of the put functions + void put_int8(int8_t value) { this->put_uint8(static_cast(value)); } + void put_int16(int32_t value) { this->put_uint(static_cast(value), sizeof(uint16_t)); } + void put_int24(int32_t value) { this->put_uint(static_cast(value), 3); } + void put_int32(int32_t value) { this->put_uint(static_cast(value), sizeof(uint32_t)); } + void put_int64(int64_t value) { this->put_uint(static_cast(value), sizeof(uint64_t)); } + // Extra put functions void put_float(float value); + void put_double(double value); + void put_bool(bool value) { this->put_uint8(value); } + void put_vector(const std::vector &value); inline size_t get_capacity() const { return this->data_.size(); } inline size_t get_position() const { return this->position_; } @@ -80,12 +128,12 @@ class ByteBuffer { // set limit to current position, postition to zero. Used when swapping from write to read operations. void flip(); // retrieve a pointer to the underlying data. - uint8_t *array() { return this->data_.data(); }; + std::vector get_data() { return this->data_; }; void rewind() { this->position_ = 0; } void reset() { this->position_ = this->mark_; } protected: - ByteBuffer(std::vector data) : data_(std::move(data)) { this->limit_ = this->get_capacity(); } + ByteBuffer(std::vector const &data) : data_(data), limit_(data.size()) {} std::vector data_; Endian endianness_{LITTLE}; size_t position_{0}; From 43f8f2fd2ef30802025e078c4be0f0afcc08308f Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Fri, 23 Aug 2024 18:09:40 +1000 Subject: [PATCH 1985/2101] [core] Clean build if the loaded integrations changed (#7344) --- esphome/writer.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/esphome/writer.py b/esphome/writer.py index c6111cbe3f..57435d3463 100644 --- a/esphome/writer.py +++ b/esphome/writer.py @@ -106,6 +106,8 @@ def storage_should_clean(old: StorageJSON, new: StorageJSON) -> bool: return True if old.build_path != new.build_path: return True + if old.loaded_integrations != new.loaded_integrations: + return True return False @@ -117,7 +119,9 @@ def update_storage_json(): return if storage_should_clean(old, new): - _LOGGER.info("Core config or version changed, cleaning build files...") + _LOGGER.info( + "Core config, version or integrations changed, cleaning build files..." + ) clean_build() new.save(path) From a01fea54a03e26ce265cd44780c6166d73973a28 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Sat, 24 Aug 2024 02:32:08 -0500 Subject: [PATCH 1986/2101] [ledc] Tweak fix in #6997 (#7336) --- esphome/components/ledc/ledc_output.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/esphome/components/ledc/ledc_output.cpp b/esphome/components/ledc/ledc_output.cpp index 90e11fe4ad..7f91eb2d7a 100644 --- a/esphome/components/ledc/ledc_output.cpp +++ b/esphome/components/ledc/ledc_output.cpp @@ -8,6 +8,8 @@ #endif #include +#include + #define CLOCK_FREQUENCY 80e6f #ifdef USE_ARDUINO @@ -120,13 +122,17 @@ void LEDCOutput::write_state(float state) { ledcWrite(this->channel_, duty); #endif #ifdef USE_ESP_IDF +#if !defined(USE_ESP32_VARIANT_ESP32C3) || (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 1, 0)) // ensure that 100% on is not 99.975% on + // note: on the C3, this tweak will result in the outputs turning off at 100%, so it has been omitted if ((duty == max_duty) && (max_duty != 1)) { duty = max_duty + 1; } +#endif auto speed_mode = get_speed_mode(channel_); auto chan_num = static_cast(channel_ % 8); int hpoint = ledc_angle_to_htop(this->phase_angle_, this->bit_depth_); + ESP_LOGV(TAG, "Setting duty: %" PRIu32 " on channel %u", duty, this->channel_); ledc_set_duty_with_hpoint(speed_mode, chan_num, duty, hpoint); ledc_update_duty(speed_mode, chan_num); #endif From caaae59ea9db397bc80e6e51504bd698ece059f3 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Sat, 24 Aug 2024 19:56:13 +1000 Subject: [PATCH 1987/2101] [ledc] Fix maximum brightness on ESP-IDF 5.1 (#7342) Co-authored-by: Keith Burzinski --- esphome/components/ledc/ledc_output.cpp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/esphome/components/ledc/ledc_output.cpp b/esphome/components/ledc/ledc_output.cpp index 7f91eb2d7a..4ced4b8f76 100644 --- a/esphome/components/ledc/ledc_output.cpp +++ b/esphome/components/ledc/ledc_output.cpp @@ -117,24 +117,22 @@ 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(duty_rounded); + ESP_LOGV(TAG, "Setting duty: %" PRIu32 " on channel %u", duty, this->channel_); #ifdef USE_ARDUINO - ESP_LOGV(TAG, "Setting duty: %u on channel %u", duty, this->channel_); ledcWrite(this->channel_, duty); #endif #ifdef USE_ESP_IDF -#if !defined(USE_ESP32_VARIANT_ESP32C3) || (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 1, 0)) - // ensure that 100% on is not 99.975% on - // note: on the C3, this tweak will result in the outputs turning off at 100%, so it has been omitted - if ((duty == max_duty) && (max_duty != 1)) { - duty = max_duty + 1; - } -#endif auto speed_mode = get_speed_mode(channel_); auto chan_num = static_cast(channel_ % 8); int hpoint = ledc_angle_to_htop(this->phase_angle_, this->bit_depth_); - ESP_LOGV(TAG, "Setting duty: %" PRIu32 " on channel %u", duty, this->channel_); - ledc_set_duty_with_hpoint(speed_mode, chan_num, duty, hpoint); - ledc_update_duty(speed_mode, chan_num); + if (duty == max_duty) { + ledc_stop(speed_mode, chan_num, 1); + } else if (duty == 0) { + ledc_stop(speed_mode, chan_num, 0); + } else { + ledc_set_duty_with_hpoint(speed_mode, chan_num, duty, hpoint); + ledc_update_duty(speed_mode, chan_num); + } #endif } From 71d6bbc7e6e7389d00609bad87e6fbab37ad34a4 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Mon, 26 Aug 2024 08:03:25 +1000 Subject: [PATCH 1988/2101] [lvgl] Fix race condition involving numbers, switches etc. (#7345) --- esphome/components/lvgl/__init__.py | 5 ++++- esphome/components/lvgl/binary_sensor/__init__.py | 3 ++- esphome/components/lvgl/light/__init__.py | 3 ++- esphome/components/lvgl/lvcode.py | 3 +++ esphome/components/lvgl/number/__init__.py | 3 ++- esphome/components/lvgl/select/__init__.py | 3 ++- esphome/components/lvgl/sensor/__init__.py | 3 ++- esphome/components/lvgl/switch/__init__.py | 3 ++- esphome/components/lvgl/text/__init__.py | 3 ++- esphome/components/lvgl/text_sensor/__init__.py | 3 ++- esphome/components/lvgl/widgets/__init__.py | 13 ++++++++++--- 11 files changed, 33 insertions(+), 12 deletions(-) diff --git a/esphome/components/lvgl/__init__.py b/esphome/components/lvgl/__init__.py index 7c51d9c70d..ea020435dc 100644 --- a/esphome/components/lvgl/__init__.py +++ b/esphome/components/lvgl/__init__.py @@ -266,7 +266,10 @@ async def to_code(config): await add_top_layer(config) await msgboxes_to_code(config) await disp_update(f"{lv_component}->get_disp()", config) - Widget.set_completed() + # At this point only the setup code should be generated + assert LvContext.added_lambda_count == 1 + Widget.set_completed() + async with LvContext(lv_component): await generate_triggers(lv_component) for conf in config.get(CONF_ON_IDLE, ()): templ = await cg.templatable(conf[CONF_TIMEOUT], [], cg.uint32) diff --git a/esphome/components/lvgl/binary_sensor/__init__.py b/esphome/components/lvgl/binary_sensor/__init__.py index 8789a06375..56984405aa 100644 --- a/esphome/components/lvgl/binary_sensor/__init__.py +++ b/esphome/components/lvgl/binary_sensor/__init__.py @@ -10,7 +10,7 @@ from ..defines import CONF_LVGL_ID, CONF_WIDGET from ..lvcode import EVENT_ARG, LambdaContext, LvContext from ..schemas import LVGL_SCHEMA from ..types import LV_EVENT, lv_pseudo_button_t -from ..widgets import Widget, get_widgets +from ..widgets import Widget, get_widgets, wait_for_widgets CONFIG_SCHEMA = ( binary_sensor_schema(BinarySensor) @@ -29,6 +29,7 @@ async def to_code(config): widget = await get_widgets(config, CONF_WIDGET) widget = widget[0] assert isinstance(widget, Widget) + await wait_for_widgets() async with LambdaContext(EVENT_ARG) as pressed_ctx: pressed_ctx.add(sensor.publish_state(widget.is_pressed())) async with LvContext(paren) as ctx: diff --git a/esphome/components/lvgl/light/__init__.py b/esphome/components/lvgl/light/__init__.py index 27c160dff6..a0eeded349 100644 --- a/esphome/components/lvgl/light/__init__.py +++ b/esphome/components/lvgl/light/__init__.py @@ -8,7 +8,7 @@ from ..defines import CONF_LVGL_ID from ..lvcode import LvContext from ..schemas import LVGL_SCHEMA from ..types import LvType, lvgl_ns -from ..widgets import get_widgets +from ..widgets import get_widgets, wait_for_widgets lv_led_t = LvType("lv_led_t") LVLight = lvgl_ns.class_("LVLight", LightOutput) @@ -28,5 +28,6 @@ async def to_code(config): paren = await cg.get_variable(config[CONF_LVGL_ID]) widget = await get_widgets(config, CONF_LED) widget = widget[0] + await wait_for_widgets() async with LvContext(paren) as ctx: ctx.add(var.set_obj(widget.obj)) diff --git a/esphome/components/lvgl/lvcode.py b/esphome/components/lvgl/lvcode.py index 6d7e364e5d..8d029ce0ca 100644 --- a/esphome/components/lvgl/lvcode.py +++ b/esphome/components/lvgl/lvcode.py @@ -176,6 +176,8 @@ class LvContext(LambdaContext): Code generation into the LVGL initialisation code (called in `setup()`) """ + added_lambda_count = 0 + def __init__(self, lv_component, args=None): self.args = args or LVGL_COMP_ARG super().__init__(parameters=self.args) @@ -183,6 +185,7 @@ class LvContext(LambdaContext): async def add_init_lambda(self): cg.add(self.lv_component.add_init_lambda(await self.get_lambda())) + LvContext.added_lambda_count += 1 async def __aexit__(self, exc_type, exc_val, exc_tb): await super().__aexit__(exc_type, exc_val, exc_tb) diff --git a/esphome/components/lvgl/number/__init__.py b/esphome/components/lvgl/number/__init__.py index 6336bb0632..3e1ede0dec 100644 --- a/esphome/components/lvgl/number/__init__.py +++ b/esphome/components/lvgl/number/__init__.py @@ -16,7 +16,7 @@ from ..lvcode import ( ) from ..schemas import LVGL_SCHEMA from ..types import LV_EVENT, LvNumber, lvgl_ns -from ..widgets import get_widgets +from ..widgets import get_widgets, wait_for_widgets LVGLNumber = lvgl_ns.class_("LVGLNumber", number.Number) @@ -44,6 +44,7 @@ async def to_code(config): step=widget.get_step(), ) + await wait_for_widgets() async with LambdaContext([(cg.float_, "v")]) as control: await widget.set_property( "value", MockObj("v") * MockObj(widget.get_scale()), config[CONF_ANIMATED] diff --git a/esphome/components/lvgl/select/__init__.py b/esphome/components/lvgl/select/__init__.py index b55bde13bc..e77d0cfb32 100644 --- a/esphome/components/lvgl/select/__init__.py +++ b/esphome/components/lvgl/select/__init__.py @@ -15,7 +15,7 @@ from ..lvcode import ( ) from ..schemas import LVGL_SCHEMA from ..types import LV_EVENT, LvSelect, lvgl_ns -from ..widgets import get_widgets +from ..widgets import get_widgets, wait_for_widgets LVGLSelect = lvgl_ns.class_("LVGLSelect", select.Select) @@ -37,6 +37,7 @@ async def to_code(config): options = widget.config.get(CONF_OPTIONS, []) selector = await select.new_select(config, options=options) paren = await cg.get_variable(config[CONF_LVGL_ID]) + await wait_for_widgets() async with LambdaContext(EVENT_ARG) as pub_ctx: pub_ctx.add(selector.publish_index(widget.get_value())) async with LambdaContext([(cg.uint16, "v")]) as control: diff --git a/esphome/components/lvgl/sensor/__init__.py b/esphome/components/lvgl/sensor/__init__.py index 82e21d5e95..a2a2298c27 100644 --- a/esphome/components/lvgl/sensor/__init__.py +++ b/esphome/components/lvgl/sensor/__init__.py @@ -14,7 +14,7 @@ from ..lvcode import ( ) from ..schemas import LVGL_SCHEMA from ..types import LV_EVENT, LvNumber -from ..widgets import Widget, get_widgets +from ..widgets import Widget, get_widgets, wait_for_widgets CONFIG_SCHEMA = ( sensor_schema(Sensor) @@ -33,6 +33,7 @@ async def to_code(config): widget = await get_widgets(config, CONF_WIDGET) widget = widget[0] assert isinstance(widget, Widget) + await wait_for_widgets() async with LambdaContext(EVENT_ARG) as lamb: lv_add(sensor.publish_state(widget.get_value())) async with LvContext(paren, LVGL_COMP_ARG): diff --git a/esphome/components/lvgl/switch/__init__.py b/esphome/components/lvgl/switch/__init__.py index 957fce17ff..f855c2a034 100644 --- a/esphome/components/lvgl/switch/__init__.py +++ b/esphome/components/lvgl/switch/__init__.py @@ -16,7 +16,7 @@ from ..lvcode import ( ) from ..schemas import LVGL_SCHEMA from ..types import LV_EVENT, LV_STATE, lv_pseudo_button_t, lvgl_ns -from ..widgets import get_widgets +from ..widgets import get_widgets, wait_for_widgets LVGLSwitch = lvgl_ns.class_("LVGLSwitch", Switch) CONFIG_SCHEMA = ( @@ -35,6 +35,7 @@ async def to_code(config): paren = await cg.get_variable(config[CONF_LVGL_ID]) widget = await get_widgets(config, CONF_WIDGET) widget = widget[0] + await wait_for_widgets() async with LambdaContext(EVENT_ARG) as checked_ctx: checked_ctx.add(switch.publish_state(widget.get_value())) async with LambdaContext([(cg.bool_, "v")]) as control: diff --git a/esphome/components/lvgl/text/__init__.py b/esphome/components/lvgl/text/__init__.py index 9ee494d8a0..56fa42e131 100644 --- a/esphome/components/lvgl/text/__init__.py +++ b/esphome/components/lvgl/text/__init__.py @@ -15,7 +15,7 @@ from ..lvcode import ( ) from ..schemas import LVGL_SCHEMA from ..types import LV_EVENT, LvText, lvgl_ns -from ..widgets import get_widgets +from ..widgets import get_widgets, wait_for_widgets LVGLText = lvgl_ns.class_("LVGLText", text.Text) @@ -32,6 +32,7 @@ async def to_code(config): paren = await cg.get_variable(config[CONF_LVGL_ID]) widget = await get_widgets(config, CONF_WIDGET) widget = widget[0] + 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, None) diff --git a/esphome/components/lvgl/text_sensor/__init__.py b/esphome/components/lvgl/text_sensor/__init__.py index cab715dce0..ae39eec291 100644 --- a/esphome/components/lvgl/text_sensor/__init__.py +++ b/esphome/components/lvgl/text_sensor/__init__.py @@ -10,7 +10,7 @@ from ..defines import CONF_LVGL_ID, CONF_WIDGET from ..lvcode import API_EVENT, EVENT_ARG, UPDATE_EVENT, LambdaContext, LvContext from ..schemas import LVGL_SCHEMA from ..types import LV_EVENT, LvText -from ..widgets import get_widgets +from ..widgets import get_widgets, wait_for_widgets CONFIG_SCHEMA = ( text_sensor_schema(TextSensor) @@ -28,6 +28,7 @@ async def to_code(config): paren = await cg.get_variable(config[CONF_LVGL_ID]) widget = await get_widgets(config, CONF_WIDGET) widget = widget[0] + await wait_for_widgets() async with LambdaContext(EVENT_ARG) as pressed_ctx: pressed_ctx.add(sensor.publish_state(widget.get_value())) async with LvContext(paren) as ctx: diff --git a/esphome/components/lvgl/widgets/__init__.py b/esphome/components/lvgl/widgets/__init__.py index 50da6e131d..17d73c1714 100644 --- a/esphome/components/lvgl/widgets/__init__.py +++ b/esphome/components/lvgl/widgets/__init__.py @@ -1,4 +1,3 @@ -import asyncio import sys from typing import Any, Union @@ -224,9 +223,17 @@ async def get_widget_(wid: Widget): return await FakeAwaitable(get_widget_generator(wid)) +def widgets_wait_generator(): + while True: + if Widget.widgets_completed: + return + yield + + async def wait_for_widgets(): - while not Widget.widgets_completed: - await asyncio.sleep(0) + if Widget.widgets_completed: + return + await FakeAwaitable(widgets_wait_generator()) async def get_widgets(config: Union[dict, list], id: str = CONF_ID) -> list[Widget]: From 60fced53c214b5ccdb7fb0907cd01e06ba899456 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Mon, 26 Aug 2024 08:08:30 +1000 Subject: [PATCH 1989/2101] [lvgl] Bug fixes: (#7341) --- esphome/components/lvgl/automation.py | 2 +- esphome/components/lvgl/defines.py | 8 ++++++- esphome/components/lvgl/number/__init__.py | 1 + esphome/components/lvgl/select/__init__.py | 1 + esphome/components/lvgl/switch/__init__.py | 3 ++- esphome/components/lvgl/text/__init__.py | 1 + esphome/components/lvgl/widgets/__init__.py | 25 ++++++++++++++++----- tests/components/lvgl/lvgl-package.yaml | 16 +++++++++++++ 8 files changed, 49 insertions(+), 8 deletions(-) diff --git a/esphome/components/lvgl/automation.py b/esphome/components/lvgl/automation.py index efcac977ab..eb1b54e3ec 100644 --- a/esphome/components/lvgl/automation.py +++ b/esphome/components/lvgl/automation.py @@ -157,7 +157,7 @@ async def lvgl_update_to_code(config, action_id, template_arg, args): widgets = await get_widgets(config) w = widgets[0] disp = f"{w.obj}->get_disp()" - async with LambdaContext(parameters=args, where=action_id) as context: + async with LambdaContext(LVGL_COMP_ARG, where=action_id) as context: await disp_update(disp, config) var = cg.new_Pvariable(action_id, template_arg, await context.get_lambda()) await cg.register_parented(var, w.var) diff --git a/esphome/components/lvgl/defines.py b/esphome/components/lvgl/defines.py index 6a8b20b505..7bb1667e77 100644 --- a/esphome/components/lvgl/defines.py +++ b/esphome/components/lvgl/defines.py @@ -505,4 +505,10 @@ DEFAULT_ESPHOME_FONT = "esphome_lv_default_font" def join_enums(enums, prefix=""): - return literal("|".join(f"(int){prefix}{e.upper()}" for e in enums)) + enums = list(enums) + enums.sort() + # If a prefix is provided, prepend each constant with the prefix, and assume that all the constants are within the + # same namespace, otherwise cast to int to avoid triggering warnings about mixing enum types. + if prefix: + return literal("|".join(f"{prefix}{e.upper()}" for e in enums)) + return literal("|".join(f"(int){e.upper()}" for e in enums)) diff --git a/esphome/components/lvgl/number/__init__.py b/esphome/components/lvgl/number/__init__.py index 3e1ede0dec..07f92635b5 100644 --- a/esphome/components/lvgl/number/__init__.py +++ b/esphome/components/lvgl/number/__init__.py @@ -50,6 +50,7 @@ async def to_code(config): "value", MockObj("v") * MockObj(widget.get_scale()), config[CONF_ANIMATED] ) lv.event_send(widget.obj, API_EVENT, cg.nullptr) + control.add(var.publish_state(widget.get_value())) async with LambdaContext(EVENT_ARG) as event: event.add(var.publish_state(widget.get_value())) event_code = ( diff --git a/esphome/components/lvgl/select/__init__.py b/esphome/components/lvgl/select/__init__.py index e77d0cfb32..73ac50aa55 100644 --- a/esphome/components/lvgl/select/__init__.py +++ b/esphome/components/lvgl/select/__init__.py @@ -43,6 +43,7 @@ async def to_code(config): async with LambdaContext([(cg.uint16, "v")]) as control: await widget.set_property("selected", "v", animated=config[CONF_ANIMATED]) lv.event_send(widget.obj, API_EVENT, cg.nullptr) + control.add(selector.publish_index(widget.get_value())) async with LvContext(paren) as ctx: lv_add(selector.set_control_lambda(await control.get_lambda())) ctx.add( diff --git a/esphome/components/lvgl/switch/__init__.py b/esphome/components/lvgl/switch/__init__.py index f855c2a034..8c090543f9 100644 --- a/esphome/components/lvgl/switch/__init__.py +++ b/esphome/components/lvgl/switch/__init__.py @@ -3,7 +3,7 @@ from esphome.components.switch import Switch, new_switch, switch_schema import esphome.config_validation as cv from esphome.cpp_generator import MockObj -from ..defines import CONF_LVGL_ID, CONF_WIDGET +from ..defines import CONF_LVGL_ID, CONF_WIDGET, literal from ..lvcode import ( API_EVENT, EVENT_ARG, @@ -44,6 +44,7 @@ async def to_code(config): cond.else_() widget.clear_state(LV_STATE.CHECKED) lv.event_send(widget.obj, API_EVENT, cg.nullptr) + control.add(switch.publish_state(literal("v"))) async with LvContext(paren) as ctx: lv_add(switch.set_control_lambda(await control.get_lambda())) ctx.add( diff --git a/esphome/components/lvgl/text/__init__.py b/esphome/components/lvgl/text/__init__.py index 56fa42e131..540591d24b 100644 --- a/esphome/components/lvgl/text/__init__.py +++ b/esphome/components/lvgl/text/__init__.py @@ -36,6 +36,7 @@ async def to_code(config): 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, None) + control.add(textvar.publish_state(widget.get_value())) async with LambdaContext(EVENT_ARG) as lamb: lv_add(textvar.publish_state(widget.get_value())) async with LvContext(paren): diff --git a/esphome/components/lvgl/widgets/__init__.py b/esphome/components/lvgl/widgets/__init__.py index 17d73c1714..062c268135 100644 --- a/esphome/components/lvgl/widgets/__init__.py +++ b/esphome/components/lvgl/widgets/__init__.py @@ -118,7 +118,14 @@ class Widget: def clear_flag(self, flag): return lv_obj.clear_flag(self.obj, literal(flag)) - async def set_property(self, prop, value, animated: bool = None): + async def set_property(self, prop, value, animated: bool = None, lv_name=None): + """ + Set a property of the widget. + :param prop: The property name + :param value: The value + :param animated: If the change should be animated + :param lv_name: The base type of the widget e.g. "obj" + """ if isinstance(value, dict): value = value.get(prop) if isinstance(ALL_STYLES.get(prop), LValidator): @@ -131,11 +138,12 @@ class Widget: value = value.total_milliseconds if isinstance(value, str): value = literal(value) + lv_name = lv_name or self.type.lv_name if animated is None or self.type.animated is not True: - lv.call(f"{self.type.lv_name}_set_{prop}", self.obj, value) + lv.call(f"{lv_name}_set_{prop}", self.obj, value) else: lv.call( - f"{self.type.lv_name}_set_{prop}", + f"{lv_name}_set_{prop}", self.obj, value, literal("LV_ANIM_ON" if animated else "LV_ANIM_OFF"), @@ -319,8 +327,15 @@ async def set_obj_properties(w: Widget, config): lv_obj.set_flex_align(w.obj, main, cross, track) parts = collect_parts(config) for part, states in parts.items(): + part = "LV_PART_" + part.upper() for state, props in states.items(): - lv_state = join_enums((f"LV_STATE_{state}", f"LV_PART_{part}")) + 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)) for style_id in props.get(CONF_STYLES, ()): lv_obj.add_style(w.obj, MockObj(style_id), lv_state) for prop, value in { @@ -384,7 +399,7 @@ async def set_obj_properties(w: Widget, config): w.add_state(state) cond.else_() w.clear_state(state) - await w.set_property(CONF_SCROLLBAR_MODE, config) + await w.set_property(CONF_SCROLLBAR_MODE, config, lv_name="obj") async def add_widgets(parent: Widget, config: dict): diff --git a/tests/components/lvgl/lvgl-package.yaml b/tests/components/lvgl/lvgl-package.yaml index 1479ce7358..0e2c37048b 100644 --- a/tests/components/lvgl/lvgl-package.yaml +++ b/tests/components/lvgl/lvgl-package.yaml @@ -1,6 +1,8 @@ lvgl: log_level: TRACE bg_color: light_blue + disp_bg_color: 0xffff00 + disp_bg_image: cat_image theme: obj: border_width: 1 @@ -78,6 +80,9 @@ lvgl: on_click: then: - lvgl.animimg.stop: anim_img + - lvgl.update: + disp_bg_color: 0xffff00 + disp_bg_image: cat_image - label: text: "Hello shiny day" text_color: 0xFFFFFF @@ -304,6 +309,17 @@ lvgl: src: cat_image align: top_left y: 50 + - tileview: + id: tileview_id + scrollbar_mode: active + tiles: + - id: page_1 + row: 0 + column: 0 + dir: HOR + widgets: + - obj: + bg_color: 0x000000 - id: page2 widgets: From dc9c00105666276540fd3a634a4609c777f9b158 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 26 Aug 2024 13:07:18 +1200 Subject: [PATCH 1990/2101] [const] Move ``CONF_LINE_FREQUENCY`` to const.py (#7351) --- esphome/components/atm90e26/sensor.py | 20 ++++++++++---------- esphome/components/atm90e32/sensor.py | 2 +- esphome/const.py | 1 + 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/esphome/components/atm90e26/sensor.py b/esphome/components/atm90e26/sensor.py index a702e23cf0..42ef259100 100644 --- a/esphome/components/atm90e26/sensor.py +++ b/esphome/components/atm90e26/sensor.py @@ -1,34 +1,34 @@ import esphome.codegen as cg -import esphome.config_validation as cv from esphome.components import sensor, spi +import esphome.config_validation as cv from esphome.const import ( - CONF_ID, - CONF_REACTIVE_POWER, - CONF_VOLTAGE, CONF_CURRENT, + CONF_FORWARD_ACTIVE_ENERGY, + CONF_FREQUENCY, + CONF_ID, + CONF_LINE_FREQUENCY, CONF_POWER, CONF_POWER_FACTOR, - CONF_FREQUENCY, - CONF_FORWARD_ACTIVE_ENERGY, + CONF_REACTIVE_POWER, CONF_REVERSE_ACTIVE_ENERGY, + CONF_VOLTAGE, DEVICE_CLASS_CURRENT, DEVICE_CLASS_ENERGY, DEVICE_CLASS_POWER, DEVICE_CLASS_POWER_FACTOR, DEVICE_CLASS_VOLTAGE, - ICON_LIGHTBULB, ICON_CURRENT_AC, + ICON_LIGHTBULB, STATE_CLASS_MEASUREMENT, STATE_CLASS_TOTAL_INCREASING, + UNIT_AMPERE, UNIT_HERTZ, UNIT_VOLT, - UNIT_AMPERE, - UNIT_WATT, UNIT_VOLT_AMPS_REACTIVE, + UNIT_WATT, UNIT_WATT_HOURS, ) -CONF_LINE_FREQUENCY = "line_frequency" CONF_METER_CONSTANT = "meter_constant" CONF_PL_CONST = "pl_const" CONF_GAIN_PGA = "gain_pga" diff --git a/esphome/components/atm90e32/sensor.py b/esphome/components/atm90e32/sensor.py index be2196223c..0dc3bfdc4f 100644 --- a/esphome/components/atm90e32/sensor.py +++ b/esphome/components/atm90e32/sensor.py @@ -7,6 +7,7 @@ from esphome.const import ( CONF_FORWARD_ACTIVE_ENERGY, CONF_FREQUENCY, CONF_ID, + CONF_LINE_FREQUENCY, CONF_PHASE_A, CONF_PHASE_ANGLE, CONF_PHASE_B, @@ -39,7 +40,6 @@ from esphome.const import ( from . import atm90e32_ns -CONF_LINE_FREQUENCY = "line_frequency" CONF_CHIP_TEMPERATURE = "chip_temperature" CONF_GAIN_PGA = "gain_pga" CONF_CURRENT_PHASES = "current_phases" diff --git a/esphome/const.py b/esphome/const.py index b9c37a53a8..6e29667887 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -431,6 +431,7 @@ CONF_LIGHT_ID = "light_id" CONF_LIGHTNING_ENERGY = "lightning_energy" CONF_LIGHTNING_THRESHOLD = "lightning_threshold" CONF_LIMIT_MODE = "limit_mode" +CONF_LINE_FREQUENCY = "line_frequency" CONF_LINE_THICKNESS = "line_thickness" CONF_LINE_TYPE = "line_type" CONF_LOADED_INTEGRATIONS = "loaded_integrations" From 0f2064193f91a609ab64dc763aa17a194231be1e Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 27 Aug 2024 10:20:26 +1200 Subject: [PATCH 1991/2101] [api] Fix sending the ``once`` flag on ha entity subscription (#7357) --- esphome/components/api/api_connection.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index bd438265d4..195fcab0ab 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -179,6 +179,7 @@ void APIConnection::loop() { SubscribeHomeAssistantStateResponse resp; resp.entity_id = it.entity_id; resp.attribute = it.attribute.value(); + resp.once = it.once; if (this->send_subscribe_home_assistant_state_response(resp)) { state_subs_at_++; } From e10f8128c8f48fd63b1d09d4e3f059da0a9a573a Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Mon, 26 Aug 2024 23:41:09 +0100 Subject: [PATCH 1992/2101] bl0942: Fix init sequence, add address and line_frequency options (#7250) --- esphome/components/bl0942/bl0942.cpp | 109 ++++++++++++++----- esphome/components/bl0942/bl0942.h | 15 ++- esphome/components/bl0942/sensor.py | 28 ++++- tests/components/bl0942/test.bk72xx-ard.yaml | 22 ++++ 4 files changed, 138 insertions(+), 36 deletions(-) create mode 100644 tests/components/bl0942/test.bk72xx-ard.yaml diff --git a/esphome/components/bl0942/bl0942.cpp b/esphome/components/bl0942/bl0942.cpp index 38b1c89036..606d3629da 100644 --- a/esphome/components/bl0942/bl0942.cpp +++ b/esphome/components/bl0942/bl0942.cpp @@ -2,6 +2,8 @@ #include "esphome/core/log.h" #include +// Datasheet: https://www.belling.com.cn/media/file_object/bel_product/BL0942/datasheet/BL0942_V1.06_en.pdf + namespace esphome { namespace bl0942 { @@ -12,33 +14,41 @@ static const uint8_t BL0942_FULL_PACKET = 0xAA; static const uint8_t BL0942_PACKET_HEADER = 0x55; static const uint8_t BL0942_WRITE_COMMAND = 0xA8; -static const uint8_t BL0942_REG_I_FAST_RMS_CTRL = 0x10; -static const uint8_t BL0942_REG_MODE = 0x18; -static const uint8_t BL0942_REG_SOFT_RESET = 0x19; -static const uint8_t BL0942_REG_USR_WRPROT = 0x1A; + +static const uint8_t BL0942_REG_I_RMSOS = 0x12; +static const uint8_t BL0942_REG_WA_CREEP = 0x14; +static const uint8_t BL0942_REG_I_FAST_RMS_TH = 0x15; +static const uint8_t BL0942_REG_I_FAST_RMS_CYC = 0x16; +static const uint8_t BL0942_REG_FREQ_CYC = 0x17; +static const uint8_t BL0942_REG_OT_FUNX = 0x18; +static const uint8_t BL0942_REG_MODE = 0x19; +static const uint8_t BL0942_REG_SOFT_RESET = 0x1C; +static const uint8_t BL0942_REG_USR_WRPROT = 0x1D; static const uint8_t BL0942_REG_TPS_CTRL = 0x1B; -// TODO: Confirm insialisation works as intended -const uint8_t BL0942_INIT[5][6] = { - // Reset to default - {BL0942_WRITE_COMMAND, BL0942_REG_SOFT_RESET, 0x5A, 0x5A, 0x5A, 0x38}, - // Enable User Operation Write - {BL0942_WRITE_COMMAND, BL0942_REG_USR_WRPROT, 0x55, 0x00, 0x00, 0xF0}, - // 0x0100 = CF_UNABLE energy pulse, AC_FREQ_SEL 50Hz, RMS_UPDATE_SEL 800mS - {BL0942_WRITE_COMMAND, BL0942_REG_MODE, 0x00, 0x10, 0x00, 0x37}, - // 0x47FF = Over-current and leakage alarm on, Automatic temperature measurement, Interval 100mS - {BL0942_WRITE_COMMAND, BL0942_REG_TPS_CTRL, 0xFF, 0x47, 0x00, 0xFE}, - // 0x181C = Half cycle, Fast RMS threshold 6172 - {BL0942_WRITE_COMMAND, BL0942_REG_I_FAST_RMS_CTRL, 0x1C, 0x18, 0x00, 0x1B}}; +static const uint32_t BL0942_REG_MODE_RESV = 0x03; +static const uint32_t BL0942_REG_MODE_CF_EN = 0x04; +static const uint32_t BL0942_REG_MODE_RMS_UPDATE_SEL = 0x08; +static const uint32_t BL0942_REG_MODE_FAST_RMS_SEL = 0x10; +static const uint32_t BL0942_REG_MODE_AC_FREQ_SEL = 0x20; +static const uint32_t BL0942_REG_MODE_CF_CNT_CLR_SEL = 0x40; +static const uint32_t BL0942_REG_MODE_CF_CNT_ADD_SEL = 0x80; +static const uint32_t BL0942_REG_MODE_UART_RATE_19200 = 0x200; +static const uint32_t BL0942_REG_MODE_UART_RATE_38400 = 0x300; +static const uint32_t BL0942_REG_MODE_DEFAULT = + BL0942_REG_MODE_RESV | BL0942_REG_MODE_CF_EN | BL0942_REG_MODE_CF_CNT_ADD_SEL; + +static const uint32_t BL0942_REG_SOFT_RESET_MAGIC = 0x5a5a5a; +static const uint32_t BL0942_REG_USR_WRPROT_MAGIC = 0x55; void BL0942::loop() { DataPacket buffer; if (!this->available()) { return; } - if (read_array((uint8_t *) &buffer, sizeof(buffer))) { - if (validate_checksum(&buffer)) { - received_package_(&buffer); + if (this->read_array((uint8_t *) &buffer, sizeof(buffer))) { + if (this->validate_checksum_(&buffer)) { + this->received_package_(&buffer); } } else { ESP_LOGW(TAG, "Junk on wire. Throwing away partial message"); @@ -47,8 +57,8 @@ void BL0942::loop() { } } -bool BL0942::validate_checksum(DataPacket *data) { - uint8_t checksum = BL0942_READ_COMMAND; +bool BL0942::validate_checksum_(DataPacket *data) { + uint8_t checksum = BL0942_READ_COMMAND | this->address_; // Whole package but checksum uint8_t *raw = (uint8_t *) data; for (uint32_t i = 0; i < sizeof(*data) - 1; i++) { @@ -61,17 +71,58 @@ bool BL0942::validate_checksum(DataPacket *data) { return checksum == data->checksum; } -void BL0942::update() { +void BL0942::write_reg_(uint8_t reg, uint32_t val) { + uint8_t pkt[6]; + this->flush(); - this->write_byte(BL0942_READ_COMMAND); + pkt[0] = BL0942_WRITE_COMMAND | this->address_; + pkt[1] = reg; + pkt[2] = (val & 0xff); + pkt[3] = (val >> 8) & 0xff; + pkt[4] = (val >> 16) & 0xff; + pkt[5] = (pkt[0] + pkt[1] + pkt[2] + pkt[3] + pkt[4]) ^ 0xff; + this->write_array(pkt, 6); + delay(1); +} + +int BL0942::read_reg_(uint8_t reg) { + union { + uint8_t b[4]; + uint32_le_t le32; + } resp; + + this->write_byte(BL0942_READ_COMMAND | this->address_); + this->write_byte(reg); + this->flush(); + if (this->read_array(resp.b, 4) && + resp.b[3] == + (uint8_t) ((BL0942_READ_COMMAND + this->address_ + reg + resp.b[0] + resp.b[1] + resp.b[2]) ^ 0xff)) { + resp.b[3] = 0; + return resp.le32; + } + return -1; +} + +void BL0942::update() { + this->write_byte(BL0942_READ_COMMAND | this->address_); this->write_byte(BL0942_FULL_PACKET); } void BL0942::setup() { - for (auto *i : BL0942_INIT) { - this->write_array(i, 6); - delay(1); - } + this->write_reg_(BL0942_REG_USR_WRPROT, BL0942_REG_USR_WRPROT_MAGIC); + this->write_reg_(BL0942_REG_SOFT_RESET, BL0942_REG_SOFT_RESET_MAGIC); + + uint32_t mode = BL0942_REG_MODE_DEFAULT; + mode |= BL0942_REG_MODE_RMS_UPDATE_SEL; /* 800ms refresh time */ + if (this->line_freq_ == LINE_FREQUENCY_60HZ) + mode |= BL0942_REG_MODE_AC_FREQ_SEL; + this->write_reg_(BL0942_REG_MODE, mode); + + this->write_reg_(BL0942_REG_USR_WRPROT, 0); + + if (this->read_reg_(BL0942_REG_MODE) != mode) + this->status_set_warning("BL0942 setup failed!"); + this->flush(); } @@ -104,13 +155,15 @@ void BL0942::received_package_(DataPacket *data) { if (frequency_sensor_ != nullptr) { frequency_sensor_->publish_state(frequency); } - + this->status_clear_warning(); ESP_LOGV(TAG, "BL0942: U %fV, I %fA, P %fW, Cnt %" PRId32 ", ∫P %fkWh, frequency %fHz, status 0x%08X", v_rms, i_rms, watt, cf_cnt, total_energy_consumption, frequency, data->status); } void BL0942::dump_config() { // NOLINT(readability-function-cognitive-complexity) ESP_LOGCONFIG(TAG, "BL0942:"); + ESP_LOGCONFIG(TAG, " Address: %d", this->address_); + ESP_LOGCONFIG(TAG, " Nominal line frequency: %d Hz", this->line_freq_); LOG_SENSOR("", "Voltage", this->voltage_sensor_); LOG_SENSOR("", "Current", this->current_sensor_); LOG_SENSOR("", "Power", this->power_sensor_); diff --git a/esphome/components/bl0942/bl0942.h b/esphome/components/bl0942/bl0942.h index 12489915e1..52347c1bc3 100644 --- a/esphome/components/bl0942/bl0942.h +++ b/esphome/components/bl0942/bl0942.h @@ -28,6 +28,11 @@ struct DataPacket { uint8_t checksum; } __attribute__((packed)); +enum LineFrequency : uint8_t { + LINE_FREQUENCY_50HZ = 50, + LINE_FREQUENCY_60HZ = 60, +}; + class BL0942 : public PollingComponent, public uart::UARTDevice { public: void set_voltage_sensor(sensor::Sensor *voltage_sensor) { voltage_sensor_ = voltage_sensor; } @@ -35,9 +40,10 @@ class BL0942 : public PollingComponent, public uart::UARTDevice { 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_line_freq(LineFrequency freq) { this->line_freq_ = freq; } + void set_address(uint8_t address) { this->address_ = address; } void loop() override; - void update() override; void setup() override; void dump_config() override; @@ -59,9 +65,12 @@ class BL0942 : public PollingComponent, public uart::UARTDevice { float current_reference_ = BL0942_IREF; // Divide by this to turn into kWh float energy_reference_ = BL0942_EREF; + uint8_t address_ = 0; + LineFrequency line_freq_ = LINE_FREQUENCY_50HZ; - static bool validate_checksum(DataPacket *data); - + bool validate_checksum_(DataPacket *data); + int read_reg_(uint8_t reg); + void write_reg_(uint8_t reg, uint32_t val); void received_package_(DataPacket *data); }; } // namespace bl0942 diff --git a/esphome/components/bl0942/sensor.py b/esphome/components/bl0942/sensor.py index 9612df6d4c..c47da45b8c 100644 --- a/esphome/components/bl0942/sensor.py +++ b/esphome/components/bl0942/sensor.py @@ -1,25 +1,27 @@ import esphome.codegen as cg -import esphome.config_validation as cv from esphome.components import sensor, uart +import esphome.config_validation as cv from esphome.const import ( + CONF_ADDRESS, CONF_CURRENT, CONF_ENERGY, + CONF_FREQUENCY, CONF_ID, + CONF_LINE_FREQUENCY, CONF_POWER, CONF_VOLTAGE, - CONF_FREQUENCY, DEVICE_CLASS_CURRENT, DEVICE_CLASS_ENERGY, + DEVICE_CLASS_FREQUENCY, DEVICE_CLASS_POWER, DEVICE_CLASS_VOLTAGE, - DEVICE_CLASS_FREQUENCY, STATE_CLASS_MEASUREMENT, + STATE_CLASS_TOTAL_INCREASING, UNIT_AMPERE, + UNIT_HERTZ, UNIT_KILOWATT_HOURS, UNIT_VOLT, UNIT_WATT, - UNIT_HERTZ, - STATE_CLASS_TOTAL_INCREASING, ) DEPENDENCIES = ["uart"] @@ -27,6 +29,12 @@ DEPENDENCIES = ["uart"] bl0942_ns = cg.esphome_ns.namespace("bl0942") BL0942 = bl0942_ns.class_("BL0942", cg.PollingComponent, uart.UARTDevice) +LineFrequency = bl0942_ns.enum("LineFrequency") +LINE_FREQS = { + 50: LineFrequency.LINE_FREQUENCY_50HZ, + 60: LineFrequency.LINE_FREQUENCY_60HZ, +} + CONFIG_SCHEMA = ( cv.Schema( { @@ -61,6 +69,14 @@ CONFIG_SCHEMA = ( device_class=DEVICE_CLASS_FREQUENCY, state_class=STATE_CLASS_MEASUREMENT, ), + cv.Optional(CONF_LINE_FREQUENCY, default="50HZ"): cv.All( + cv.frequency, + cv.enum( + LINE_FREQS, + int=True, + ), + ), + cv.Optional(CONF_ADDRESS, default=0): cv.int_range(min=0, max=3), } ) .extend(cv.polling_component_schema("60s")) @@ -88,3 +104,5 @@ async def to_code(config): if frequency_config := config.get(CONF_FREQUENCY): sens = await sensor.new_sensor(frequency_config) cg.add(var.set_frequency_sensor(sens)) + cg.add(var.set_line_freq(config[CONF_LINE_FREQUENCY])) + cg.add(var.set_address(config[CONF_ADDRESS])) diff --git a/tests/components/bl0942/test.bk72xx-ard.yaml b/tests/components/bl0942/test.bk72xx-ard.yaml new file mode 100644 index 0000000000..4ed3eb391d --- /dev/null +++ b/tests/components/bl0942/test.bk72xx-ard.yaml @@ -0,0 +1,22 @@ +uart: + - id: uart_bl0942 + tx_pin: + number: TX1 + rx_pin: + number: RX1 + baud_rate: 2400 + +sensor: + - platform: bl0942 + address: 0 + line_frequency: 50Hz + voltage: + name: BL0942 Voltage + current: + name: BL0942 Current + power: + name: BL0942 Power + energy: + name: BL0942 Energy + frequency: + name: BL0942 Frequency From 5a707b558dbb9e1e0e2184fd8a0c5da2ec7f5514 Mon Sep 17 00:00:00 2001 From: Michael Hansen Date: Mon, 26 Aug 2024 18:38:49 -0500 Subject: [PATCH 1993/2101] Add supported formats to media player (#7318) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/api/api.proto | 15 ++++ esphome/components/api/api_connection.cpp | 9 ++ esphome/components/api/api_pb2.cpp | 83 +++++++++++++++++++ esphome/components/api/api_pb2.h | 20 +++++ esphome/components/api/api_pb2_service.cpp | 19 +++++ esphome/components/api/api_pb2_service.h | 4 + .../components/media_player/media_player.h | 15 ++++ 7 files changed, 165 insertions(+) diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index 72eaeed6d7..84183357dc 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -1107,6 +1107,19 @@ enum MediaPlayerCommand { MEDIA_PLAYER_COMMAND_MUTE = 3; MEDIA_PLAYER_COMMAND_UNMUTE = 4; } +enum MediaPlayerFormatPurpose { + MEDIA_PLAYER_FORMAT_PURPOSE_DEFAULT = 0; + MEDIA_PLAYER_FORMAT_PURPOSE_ANNOUNCEMENT = 1; +} +message MediaPlayerSupportedFormat { + option (id) = 119; + option (ifdef) = "USE_MEDIA_PLAYER"; + + string format = 1; + uint32 sample_rate = 2; + uint32 num_channels = 3; + MediaPlayerFormatPurpose purpose = 4; +} message ListEntitiesMediaPlayerResponse { option (id) = 63; option (source) = SOURCE_SERVER; @@ -1122,6 +1135,8 @@ message ListEntitiesMediaPlayerResponse { EntityCategory entity_category = 7; bool supports_pause = 8; + + repeated MediaPlayerSupportedFormat supported_formats = 9; } message MediaPlayerStateResponse { option (id) = 64; diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 195fcab0ab..a655d06e66 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1026,6 +1026,15 @@ bool APIConnection::send_media_player_info(media_player::MediaPlayer *media_play auto traits = media_player->get_traits(); msg.supports_pause = traits.get_supports_pause(); + for (auto &supported_format : traits.get_supported_formats()) { + MediaPlayerSupportedFormat media_format; + media_format.format = supported_format.format; + media_format.sample_rate = supported_format.sample_rate; + media_format.num_channels = supported_format.num_channels; + media_format.purpose = static_cast(supported_format.purpose); + msg.supported_formats.push_back(media_format); + } + return this->send_list_entities_media_player_response(msg); } void APIConnection::media_player_command(const MediaPlayerCommandRequest &msg) { diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index bb37824403..c944d0dae8 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -387,6 +387,18 @@ template<> const char *proto_enum_to_string(enums::Me } #endif #ifdef HAS_PROTO_MESSAGE_DUMP +template<> const char *proto_enum_to_string(enums::MediaPlayerFormatPurpose value) { + switch (value) { + case enums::MEDIA_PLAYER_FORMAT_PURPOSE_DEFAULT: + return "MEDIA_PLAYER_FORMAT_PURPOSE_DEFAULT"; + case enums::MEDIA_PLAYER_FORMAT_PURPOSE_ANNOUNCEMENT: + return "MEDIA_PLAYER_FORMAT_PURPOSE_ANNOUNCEMENT"; + default: + return "UNKNOWN"; + } +} +#endif +#ifdef HAS_PROTO_MESSAGE_DUMP template<> const char *proto_enum_to_string(enums::BluetoothDeviceRequestType value) { switch (value) { @@ -5123,6 +5135,64 @@ void ButtonCommandRequest::dump_to(std::string &out) const { out.append("}"); } #endif +bool MediaPlayerSupportedFormat::decode_varint(uint32_t field_id, ProtoVarInt value) { + switch (field_id) { + case 2: { + this->sample_rate = value.as_uint32(); + return true; + } + case 3: { + this->num_channels = value.as_uint32(); + return true; + } + case 4: { + this->purpose = value.as_enum(); + return true; + } + default: + return false; + } +} +bool MediaPlayerSupportedFormat::decode_length(uint32_t field_id, ProtoLengthDelimited value) { + switch (field_id) { + case 1: { + this->format = value.as_string(); + return true; + } + default: + return false; + } +} +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_enum(4, this->purpose); +} +#ifdef HAS_PROTO_MESSAGE_DUMP +void MediaPlayerSupportedFormat::dump_to(std::string &out) const { + __attribute__((unused)) char buffer[64]; + out.append("MediaPlayerSupportedFormat {\n"); + out.append(" format: "); + out.append("'").append(this->format).append("'"); + out.append("\n"); + + out.append(" sample_rate: "); + sprintf(buffer, "%" PRIu32, this->sample_rate); + out.append(buffer); + out.append("\n"); + + out.append(" num_channels: "); + sprintf(buffer, "%" PRIu32, this->num_channels); + out.append(buffer); + out.append("\n"); + + out.append(" purpose: "); + out.append(proto_enum_to_string(this->purpose)); + out.append("\n"); + out.append("}"); +} +#endif bool ListEntitiesMediaPlayerResponse::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { case 6: { @@ -5159,6 +5229,10 @@ bool ListEntitiesMediaPlayerResponse::decode_length(uint32_t field_id, ProtoLeng this->icon = value.as_string(); return true; } + case 9: { + this->supported_formats.push_back(value.as_message()); + return true; + } default: return false; } @@ -5182,6 +5256,9 @@ void ListEntitiesMediaPlayerResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_bool(6, this->disabled_by_default); buffer.encode_enum(7, this->entity_category); buffer.encode_bool(8, this->supports_pause); + for (auto &it : this->supported_formats) { + buffer.encode_message(9, it, true); + } } #ifdef HAS_PROTO_MESSAGE_DUMP void ListEntitiesMediaPlayerResponse::dump_to(std::string &out) const { @@ -5219,6 +5296,12 @@ void ListEntitiesMediaPlayerResponse::dump_to(std::string &out) const { out.append(" supports_pause: "); out.append(YESNO(this->supports_pause)); out.append("\n"); + + for (const auto &it : this->supported_formats) { + out.append(" supported_formats: "); + it.dump_to(out); + out.append("\n"); + } out.append("}"); } #endif diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index 3eb945fd8d..3f609c793c 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -156,6 +156,10 @@ enum MediaPlayerCommand : uint32_t { MEDIA_PLAYER_COMMAND_MUTE = 3, MEDIA_PLAYER_COMMAND_UNMUTE = 4, }; +enum MediaPlayerFormatPurpose : uint32_t { + MEDIA_PLAYER_FORMAT_PURPOSE_DEFAULT = 0, + MEDIA_PLAYER_FORMAT_PURPOSE_ANNOUNCEMENT = 1, +}; enum BluetoothDeviceRequestType : uint32_t { BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT = 0, BLUETOOTH_DEVICE_REQUEST_TYPE_DISCONNECT = 1, @@ -1267,6 +1271,21 @@ class ButtonCommandRequest : public ProtoMessage { protected: bool decode_32bit(uint32_t field_id, Proto32Bit value) override; }; +class MediaPlayerSupportedFormat : public ProtoMessage { + public: + std::string format{}; + uint32_t sample_rate{0}; + uint32_t num_channels{0}; + enums::MediaPlayerFormatPurpose purpose{}; + void encode(ProtoWriteBuffer buffer) const override; +#ifdef HAS_PROTO_MESSAGE_DUMP + void dump_to(std::string &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 ListEntitiesMediaPlayerResponse : public ProtoMessage { public: std::string object_id{}; @@ -1277,6 +1296,7 @@ class ListEntitiesMediaPlayerResponse : public ProtoMessage { bool disabled_by_default{false}; enums::EntityCategory entity_category{}; bool supports_pause{false}; + std::vector supported_formats{}; void encode(ProtoWriteBuffer buffer) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; diff --git a/esphome/components/api/api_pb2_service.cpp b/esphome/components/api/api_pb2_service.cpp index 269a755e9e..16c0e5654f 100644 --- a/esphome/components/api/api_pb2_service.cpp +++ b/esphome/components/api/api_pb2_service.cpp @@ -311,6 +311,14 @@ bool APIServerConnectionBase::send_list_entities_button_response(const ListEntit #ifdef USE_BUTTON #endif #ifdef USE_MEDIA_PLAYER +bool APIServerConnectionBase::send_media_player_supported_format(const MediaPlayerSupportedFormat &msg) { +#ifdef HAS_PROTO_MESSAGE_DUMP + ESP_LOGVV(TAG, "send_media_player_supported_format: %s", msg.dump().c_str()); +#endif + return this->send_message_(msg, 119); +} +#endif +#ifdef USE_MEDIA_PLAYER bool APIServerConnectionBase::send_list_entities_media_player_response(const ListEntitiesMediaPlayerResponse &msg) { #ifdef HAS_PROTO_MESSAGE_DUMP ESP_LOGVV(TAG, "send_list_entities_media_player_response: %s", msg.dump().c_str()); @@ -1135,6 +1143,17 @@ bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, ESP_LOGVV(TAG, "on_update_command_request: %s", msg.dump().c_str()); #endif this->on_update_command_request(msg); +#endif + break; + } + case 119: { +#ifdef USE_MEDIA_PLAYER + MediaPlayerSupportedFormat msg; + msg.decode(msg_data, msg_size); +#ifdef HAS_PROTO_MESSAGE_DUMP + ESP_LOGVV(TAG, "on_media_player_supported_format: %s", msg.dump().c_str()); +#endif + this->on_media_player_supported_format(msg); #endif break; } diff --git a/esphome/components/api/api_pb2_service.h b/esphome/components/api/api_pb2_service.h index 83bfc2ed98..83b5e3a444 100644 --- a/esphome/components/api/api_pb2_service.h +++ b/esphome/components/api/api_pb2_service.h @@ -145,6 +145,10 @@ class APIServerConnectionBase : public ProtoService { #ifdef USE_BUTTON virtual void on_button_command_request(const ButtonCommandRequest &value){}; #endif +#ifdef USE_MEDIA_PLAYER + bool send_media_player_supported_format(const MediaPlayerSupportedFormat &msg); + virtual void on_media_player_supported_format(const MediaPlayerSupportedFormat &value){}; +#endif #ifdef USE_MEDIA_PLAYER bool send_list_entities_media_player_response(const ListEntitiesMediaPlayerResponse &msg); #endif diff --git a/esphome/components/media_player/media_player.h b/esphome/components/media_player/media_player.h index 77746e1808..26bef55afc 100644 --- a/esphome/components/media_player/media_player.h +++ b/esphome/components/media_player/media_player.h @@ -27,6 +27,18 @@ enum MediaPlayerCommand : uint8_t { }; const char *media_player_command_to_string(MediaPlayerCommand command); +enum class MediaPlayerFormatPurpose : uint8_t { + PURPOSE_DEFAULT = 0, + PURPOSE_ANNOUNCEMENT = 1, +}; + +struct MediaPlayerSupportedFormat { + std::string format; + uint32_t sample_rate; + uint32_t num_channels; + MediaPlayerFormatPurpose purpose; +}; + class MediaPlayer; class MediaPlayerTraits { @@ -37,8 +49,11 @@ class MediaPlayerTraits { bool get_supports_pause() const { return this->supports_pause_; } + std::vector &get_supported_formats() { return this->supported_formats_; } + protected: bool supports_pause_{false}; + std::vector supported_formats_{}; }; class MediaPlayerCall { From 7e18a5c44f70a5eea4bff4d94e4c05a2311f8f0e Mon Sep 17 00:00:00 2001 From: Angel Nunez Mencias Date: Tue, 27 Aug 2024 03:26:01 +0200 Subject: [PATCH 1994/2101] Add reset to esp32_rmt_led_strip (#7354) --- .../esp32_rmt_led_strip/led_strip.cpp | 16 +++++++++++-- .../esp32_rmt_led_strip/led_strip.h | 5 ++-- .../components/esp32_rmt_led_strip/light.py | 24 +++++++++++++++---- 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/esphome/components/esp32_rmt_led_strip/led_strip.cpp b/esphome/components/esp32_rmt_led_strip/led_strip.cpp index 7727b64f29..71ab099de5 100644 --- a/esphome/components/esp32_rmt_led_strip/led_strip.cpp +++ b/esphome/components/esp32_rmt_led_strip/led_strip.cpp @@ -38,7 +38,8 @@ void ESP32RMTLEDStripLightOutput::setup() { } ExternalRAMAllocator rmt_allocator(ExternalRAMAllocator::ALLOW_FAILURE); - this->rmt_buf_ = rmt_allocator.allocate(buffer_size * 8); // 8 bits per byte, 1 rmt_item32_t per bit + this->rmt_buf_ = rmt_allocator.allocate(buffer_size * 8 + + 1); // 8 bits per byte, 1 rmt_item32_t per bit + 1 rmt_item32_t for reset rmt_config_t config; memset(&config, 0, sizeof(config)); @@ -66,7 +67,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 bit1_low, uint32_t reset_time_high, uint32_t reset_time_low) { float ratio = (float) RMT_CLK_FREQ / RMT_CLK_DIV / 1e09f; // 0-bit @@ -79,6 +80,11 @@ void ESP32RMTLEDStripLightOutput::set_led_params(uint32_t bit0_high, uint32_t bi this->bit1_.level0 = 1; this->bit1_.duration1 = (uint32_t) (ratio * bit1_low); this->bit1_.level1 = 0; + // reset + this->reset_.duration0 = (uint32_t) (ratio * reset_time_high); + this->reset_.level0 = 1; + this->reset_.duration1 = (uint32_t) (ratio * reset_time_low); + this->reset_.level1 = 0; } void ESP32RMTLEDStripLightOutput::write_state(light::LightState *state) { @@ -118,6 +124,12 @@ void ESP32RMTLEDStripLightOutput::write_state(light::LightState *state) { psrc++; } + if (this->reset_.duration0 > 0 || this->reset_.duration1 > 0) { + pdest->val = this->reset_.val; + pdest++; + len++; + } + if (rmt_write_items(this->channel_, this->rmt_buf_, len, false) != ESP_OK) { ESP_LOGE(TAG, "RMT TX error"); this->status_set_warning(); diff --git a/esphome/components/esp32_rmt_led_strip/led_strip.h b/esphome/components/esp32_rmt_led_strip/led_strip.h index e9b19c9399..43215cf12b 100644 --- a/esphome/components/esp32_rmt_led_strip/led_strip.h +++ b/esphome/components/esp32_rmt_led_strip/led_strip.h @@ -49,7 +49,8 @@ class ESP32RMTLEDStripLightOutput : public light::AddressableLight { /// Set a maximum refresh rate in µs as some lights do not like being updated too often. void set_max_refresh_rate(uint32_t interval_us) { this->max_refresh_rate_ = interval_us; } - void set_led_params(uint32_t bit0_high, uint32_t bit0_low, uint32_t bit1_high, uint32_t bit1_low); + void 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); void set_rgb_order(RGBOrder rgb_order) { this->rgb_order_ = rgb_order; } void set_rmt_channel(rmt_channel_t channel) { this->channel_ = channel; } @@ -75,7 +76,7 @@ class ESP32RMTLEDStripLightOutput : public light::AddressableLight { bool is_rgbw_; bool is_wrgb_; - rmt_item32_t bit0_, bit1_; + rmt_item32_t bit0_, bit1_, reset_; RGBOrder rgb_order_; rmt_channel_t channel_; diff --git a/esphome/components/esp32_rmt_led_strip/light.py b/esphome/components/esp32_rmt_led_strip/light.py index 4c8472b8d2..4a04918275 100644 --- a/esphome/components/esp32_rmt_led_strip/light.py +++ b/esphome/components/esp32_rmt_led_strip/light.py @@ -43,13 +43,15 @@ class LEDStripTimings: bit0_low: int bit1_high: int bit1_low: int + reset_high: int + reset_low: int CHIPSETS = { - "WS2812": LEDStripTimings(400, 1000, 1000, 400), - "SK6812": LEDStripTimings(300, 900, 600, 600), - "APA106": LEDStripTimings(350, 1360, 1360, 350), - "SM16703": LEDStripTimings(300, 900, 900, 300), + "WS2812": LEDStripTimings(400, 1000, 1000, 400, 0, 0), + "SK6812": LEDStripTimings(300, 900, 600, 600, 0, 0), + "APA106": LEDStripTimings(350, 1360, 1360, 350, 0, 0), + "SM16703": LEDStripTimings(300, 900, 900, 300, 0, 0), } @@ -58,6 +60,8 @@ CONF_BIT0_HIGH = "bit0_high" CONF_BIT0_LOW = "bit0_low" CONF_BIT1_HIGH = "bit1_high" CONF_BIT1_LOW = "bit1_low" +CONF_RESET_HIGH = "reset_high" +CONF_RESET_LOW = "reset_low" CONFIG_SCHEMA = cv.All( @@ -88,6 +92,14 @@ CONFIG_SCHEMA = cv.All( CONF_BIT1_LOW, "custom", ): cv.positive_time_period_nanoseconds, + cv.Optional( + CONF_RESET_HIGH, + default="0 us", + ): cv.positive_time_period_nanoseconds, + cv.Optional( + CONF_RESET_LOW, + default="0 us", + ): cv.positive_time_period_nanoseconds, } ), cv.has_exactly_one_key(CONF_CHIPSET, CONF_BIT0_HIGH), @@ -113,6 +125,8 @@ async def to_code(config): chipset.bit0_low, chipset.bit1_high, chipset.bit1_low, + chipset.reset_high, + chipset.reset_low, ) ) else: @@ -122,6 +136,8 @@ async def to_code(config): config[CONF_BIT0_LOW], config[CONF_BIT1_HIGH], config[CONF_BIT1_LOW], + config[CONF_RESET_HIGH], + config[CONF_RESET_LOW], ) ) From 34cce0e9201ab5408cfcd18ee7d2d7c5a24ffdd5 Mon Sep 17 00:00:00 2001 From: Gilles van den Hoven Date: Tue, 27 Aug 2024 14:07:32 +0200 Subject: [PATCH 1995/2101] [ili9xxx] Make `invert_colors` required (#7292) Co-authored-by: Gilles van den Hoven Co-authored-by: clydebarrow <2366188+clydebarrow@users.noreply.github.com> --- esphome/components/ili9xxx/display.py | 35 +++++++++--------- .../components/ili9xxx/ili9xxx_display.cpp | 2 +- esphome/components/ili9xxx/ili9xxx_display.h | 36 +++++++++---------- esphome/components/ili9xxx/ili9xxx_init.h | 3 -- tests/components/ili9xxx/test.esp32-ard.yaml | 1 + .../components/ili9xxx/test.esp32-c3-ard.yaml | 1 + .../components/ili9xxx/test.esp32-c3-idf.yaml | 1 + .../components/ili9xxx/test.esp8266-ard.yaml | 1 + tests/components/ili9xxx/test.rp2040-ard.yaml | 1 + 9 files changed, 41 insertions(+), 40 deletions(-) diff --git a/esphome/components/ili9xxx/display.py b/esphome/components/ili9xxx/display.py index 483f2b886c..2182ca9a6d 100644 --- a/esphome/components/ili9xxx/display.py +++ b/esphome/components/ili9xxx/display.py @@ -1,31 +1,31 @@ -import esphome.codegen as cg -import esphome.config_validation as cv from esphome import core, pins -from esphome.components import display, spi, font +import esphome.codegen as cg +from esphome.components import display, font, spi from esphome.components.display import validate_rotation -from esphome.core import CORE, HexInt +import esphome.config_validation as cv from esphome.const import ( + CONF_COLOR_ORDER, CONF_COLOR_PALETTE, CONF_DC_PIN, - CONF_ID, - CONF_LAMBDA, - CONF_MODEL, - CONF_RAW_DATA_ID, - CONF_PAGES, - CONF_RESET_PIN, CONF_DIMENSIONS, - CONF_WIDTH, CONF_HEIGHT, - CONF_ROTATION, + CONF_ID, + CONF_INVERT_COLORS, + CONF_LAMBDA, CONF_MIRROR_X, CONF_MIRROR_Y, - CONF_SWAP_XY, - CONF_COLOR_ORDER, + CONF_MODEL, CONF_OFFSET_HEIGHT, CONF_OFFSET_WIDTH, + CONF_PAGES, + CONF_RAW_DATA_ID, + CONF_RESET_PIN, + CONF_ROTATION, + CONF_SWAP_XY, CONF_TRANSFORM, - CONF_INVERT_COLORS, + CONF_WIDTH, ) +from esphome.core import CORE, HexInt DEPENDENCIES = ["spi"] @@ -177,7 +177,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_INVERT_DISPLAY): cv.invalid( "'invert_display' has been replaced by 'invert_colors'" ), - cv.Optional(CONF_INVERT_COLORS): cv.boolean, + cv.Required(CONF_INVERT_COLORS): cv.boolean, cv.Optional(CONF_COLOR_ORDER): cv.one_of(*COLOR_ORDERS.keys(), upper=True), cv.Exclusive(CONF_ROTATION, CONF_ROTATION): validate_rotation, cv.Exclusive(CONF_TRANSFORM, CONF_ROTATION): cv.Schema( @@ -287,5 +287,4 @@ async def to_code(config): prog_arr = cg.progmem_array(config[CONF_RAW_DATA_ID], rhs) cg.add(var.set_palette(prog_arr)) - if CONF_INVERT_COLORS in config: - cg.add(var.invert_colors(config[CONF_INVERT_COLORS])) + cg.add(var.invert_colors(config[CONF_INVERT_COLORS])) diff --git a/esphome/components/ili9xxx/ili9xxx_display.cpp b/esphome/components/ili9xxx/ili9xxx_display.cpp index 4f035edbb0..81976dd2c9 100644 --- a/esphome/components/ili9xxx/ili9xxx_display.cpp +++ b/esphome/components/ili9xxx/ili9xxx_display.cpp @@ -118,6 +118,7 @@ void ILI9XXXDisplay::dump_config() { ESP_LOGCONFIG(TAG, " Swap_xy: %s", YESNO(this->swap_xy_)); ESP_LOGCONFIG(TAG, " Mirror_x: %s", YESNO(this->mirror_x_)); ESP_LOGCONFIG(TAG, " Mirror_y: %s", YESNO(this->mirror_y_)); + ESP_LOGCONFIG(TAG, " Invert colors: %s", YESNO(this->pre_invertcolors_)); if (this->is_failed()) { ESP_LOGCONFIG(TAG, " => Failed to init Memory: YES!"); @@ -154,7 +155,6 @@ void ILI9XXXDisplay::fill(Color color) { } } return; - break; default: new_color = display::ColorUtil::color_to_332(color, display::ColorOrder::COLOR_ORDER_RGB); break; diff --git a/esphome/components/ili9xxx/ili9xxx_display.h b/esphome/components/ili9xxx/ili9xxx_display.h index 6121488d15..5033f702de 100644 --- a/esphome/components/ili9xxx/ili9xxx_display.h +++ b/esphome/components/ili9xxx/ili9xxx_display.h @@ -28,8 +28,8 @@ class ILI9XXXDisplay : public display::DisplayBuffer, spi::CLOCK_PHASE_LEADING, spi::DATA_RATE_40MHZ> { public: ILI9XXXDisplay() = default; - ILI9XXXDisplay(uint8_t const *init_sequence, int16_t width, int16_t height, bool invert_colors) - : init_sequence_{init_sequence}, width_{width}, height_{height}, pre_invertcolors_{invert_colors} { + ILI9XXXDisplay(uint8_t const *init_sequence, int16_t width, int16_t height) + : init_sequence_{init_sequence}, width_{width}, height_{height} { uint8_t cmd, num_args, bits; const uint8_t *addr = init_sequence; while ((cmd = *addr++) != 0) { @@ -144,7 +144,7 @@ class ILI9XXXDisplay : public display::DisplayBuffer, bool need_update_ = false; bool is_18bitdisplay_ = false; PixelMode pixel_mode_{}; - bool pre_invertcolors_ = false; + bool pre_invertcolors_{}; display::ColorOrder color_order_{display::COLOR_ORDER_BGR}; bool swap_xy_{}; bool mirror_x_{}; @@ -154,54 +154,54 @@ class ILI9XXXDisplay : public display::DisplayBuffer, //----------- M5Stack display -------------- class ILI9XXXM5Stack : public ILI9XXXDisplay { public: - ILI9XXXM5Stack() : ILI9XXXDisplay(INITCMD_M5STACK, 320, 240, true) {} + ILI9XXXM5Stack() : ILI9XXXDisplay(INITCMD_M5STACK, 320, 240) {} }; //----------- M5Stack display -------------- class ILI9XXXM5CORE : public ILI9XXXDisplay { public: - ILI9XXXM5CORE() : ILI9XXXDisplay(INITCMD_M5CORE, 320, 240, true) {} + ILI9XXXM5CORE() : ILI9XXXDisplay(INITCMD_M5CORE, 320, 240) {} }; //----------- ST7789V display -------------- class ILI9XXXST7789V : public ILI9XXXDisplay { public: - ILI9XXXST7789V() : ILI9XXXDisplay(INITCMD_ST7789V, 240, 320, false) {} + ILI9XXXST7789V() : ILI9XXXDisplay(INITCMD_ST7789V, 240, 320) {} }; //----------- ILI9XXX_24_TFT display -------------- class ILI9XXXILI9341 : public ILI9XXXDisplay { public: - ILI9XXXILI9341() : ILI9XXXDisplay(INITCMD_ILI9341, 240, 320, false) {} + ILI9XXXILI9341() : ILI9XXXDisplay(INITCMD_ILI9341, 240, 320) {} }; //----------- ILI9XXX_24_TFT rotated display -------------- class ILI9XXXILI9342 : public ILI9XXXDisplay { public: - ILI9XXXILI9342() : ILI9XXXDisplay(INITCMD_ILI9341, 320, 240, false) {} + ILI9XXXILI9342() : ILI9XXXDisplay(INITCMD_ILI9341, 320, 240) {} }; //----------- ILI9XXX_??_TFT rotated display -------------- class ILI9XXXILI9481 : public ILI9XXXDisplay { public: - ILI9XXXILI9481() : ILI9XXXDisplay(INITCMD_ILI9481, 480, 320, false) {} + ILI9XXXILI9481() : ILI9XXXDisplay(INITCMD_ILI9481, 480, 320) {} }; //----------- ILI9481 in 18 bit mode -------------- class ILI9XXXILI948118 : public ILI9XXXDisplay { public: - ILI9XXXILI948118() : ILI9XXXDisplay(INITCMD_ILI9481_18, 320, 480, true) {} + ILI9XXXILI948118() : ILI9XXXDisplay(INITCMD_ILI9481_18, 320, 480) {} }; //----------- ILI9XXX_35_TFT rotated display -------------- class ILI9XXXILI9486 : public ILI9XXXDisplay { public: - ILI9XXXILI9486() : ILI9XXXDisplay(INITCMD_ILI9486, 480, 320, false) {} + ILI9XXXILI9486() : ILI9XXXDisplay(INITCMD_ILI9486, 480, 320) {} }; class ILI9XXXILI9488 : public ILI9XXXDisplay { public: - ILI9XXXILI9488(const uint8_t *seq = INITCMD_ILI9488) : ILI9XXXDisplay(seq, 480, 320, true) {} + ILI9XXXILI9488(const uint8_t *seq = INITCMD_ILI9488) : ILI9XXXDisplay(seq, 480, 320) {} protected: void set_madctl() override { @@ -246,34 +246,34 @@ class WAVESHARERES35 : public ILI9XXXILI9488 { //----------- ILI9XXX_35_TFT origin colors rotated display -------------- class ILI9XXXILI9488A : public ILI9XXXDisplay { public: - ILI9XXXILI9488A() : ILI9XXXDisplay(INITCMD_ILI9488_A, 480, 320, true) {} + ILI9XXXILI9488A() : ILI9XXXDisplay(INITCMD_ILI9488_A, 480, 320) {} }; //----------- ILI9XXX_35_TFT rotated display -------------- class ILI9XXXST7796 : public ILI9XXXDisplay { public: - ILI9XXXST7796() : ILI9XXXDisplay(INITCMD_ST7796, 320, 480, false) {} + ILI9XXXST7796() : ILI9XXXDisplay(INITCMD_ST7796, 320, 480) {} }; class ILI9XXXS3Box : public ILI9XXXDisplay { public: - ILI9XXXS3Box() : ILI9XXXDisplay(INITCMD_S3BOX, 320, 240, false) {} + ILI9XXXS3Box() : ILI9XXXDisplay(INITCMD_S3BOX, 320, 240) {} }; class ILI9XXXS3BoxLite : public ILI9XXXDisplay { public: - ILI9XXXS3BoxLite() : ILI9XXXDisplay(INITCMD_S3BOXLITE, 320, 240, true) {} + ILI9XXXS3BoxLite() : ILI9XXXDisplay(INITCMD_S3BOXLITE, 320, 240) {} }; class ILI9XXXGC9A01A : public ILI9XXXDisplay { public: - ILI9XXXGC9A01A() : ILI9XXXDisplay(INITCMD_GC9A01A, 240, 240, true) {} + ILI9XXXGC9A01A() : ILI9XXXDisplay(INITCMD_GC9A01A, 240, 240) {} }; //----------- ILI9XXX_24_TFT display -------------- class ILI9XXXST7735 : public ILI9XXXDisplay { public: - ILI9XXXST7735() : ILI9XXXDisplay(INITCMD_ST7735, 128, 160, false) {} + ILI9XXXST7735() : ILI9XXXDisplay(INITCMD_ST7735, 128, 160) {} }; } // namespace ili9xxx diff --git a/esphome/components/ili9xxx/ili9xxx_init.h b/esphome/components/ili9xxx/ili9xxx_init.h index 5a67812bc1..b176680f43 100644 --- a/esphome/components/ili9xxx/ili9xxx_init.h +++ b/esphome/components/ili9xxx/ili9xxx_init.h @@ -101,7 +101,6 @@ static const uint8_t PROGMEM INITCMD_ILI9481[] = { ILI9XXX_MADCTL , 1, MADCTL_MV | MADCTL_BGR, // Memory Access Control ILI9XXX_CSCON , 1, 0x01, ILI9XXX_PIXFMT, 1, 0x55, // 16 bit mode - ILI9XXX_INVON, 0, ILI9XXX_DISPON, 0x80, // Set display on 0x00 // end }; @@ -121,7 +120,6 @@ static const uint8_t PROGMEM INITCMD_ILI9481_18[] = { ILI9XXX_MADCTL , 1, MADCTL_MX| MADCTL_BGR, // Memory Access Control ILI9XXX_CSCON , 1, 0x01, ILI9XXX_PIXFMT, 1, 0x66, // 18 bit mode - ILI9XXX_INVON, 0, ILI9XXX_DISPON, 0x80, // Set display on 0x00 // end }; @@ -204,7 +202,6 @@ static const uint8_t PROGMEM INITCMD_ILI9488_A[] = { ILI9XXX_SLPOUT, 0x80, // Exit sleep mode - //ILI9XXX_INVON , 0, ILI9XXX_DISPON, 0x80, // Set display on 0x00 // end }; diff --git a/tests/components/ili9xxx/test.esp32-ard.yaml b/tests/components/ili9xxx/test.esp32-ard.yaml index ecee21686e..850273230a 100644 --- a/tests/components/ili9xxx/test.esp32-ard.yaml +++ b/tests/components/ili9xxx/test.esp32-ard.yaml @@ -19,6 +19,7 @@ display: lambda: |- it.rectangle(0, 0, it.get_width(), it.get_height()); - platform: ili9xxx + invert_colors: false dimensions: width: 320 height: 240 diff --git a/tests/components/ili9xxx/test.esp32-c3-ard.yaml b/tests/components/ili9xxx/test.esp32-c3-ard.yaml index 9526ae1f6b..fd03bd54b7 100644 --- a/tests/components/ili9xxx/test.esp32-c3-ard.yaml +++ b/tests/components/ili9xxx/test.esp32-c3-ard.yaml @@ -20,6 +20,7 @@ display: lambda: |- it.rectangle(0, 0, it.get_width(), it.get_height()); - platform: ili9xxx + invert_colors: false dimensions: width: 320 height: 240 diff --git a/tests/components/ili9xxx/test.esp32-c3-idf.yaml b/tests/components/ili9xxx/test.esp32-c3-idf.yaml index 9526ae1f6b..fd03bd54b7 100644 --- a/tests/components/ili9xxx/test.esp32-c3-idf.yaml +++ b/tests/components/ili9xxx/test.esp32-c3-idf.yaml @@ -20,6 +20,7 @@ display: lambda: |- it.rectangle(0, 0, it.get_width(), it.get_height()); - platform: ili9xxx + invert_colors: false dimensions: width: 320 height: 240 diff --git a/tests/components/ili9xxx/test.esp8266-ard.yaml b/tests/components/ili9xxx/test.esp8266-ard.yaml index 0791c25aca..b8192e69d1 100644 --- a/tests/components/ili9xxx/test.esp8266-ard.yaml +++ b/tests/components/ili9xxx/test.esp8266-ard.yaml @@ -20,6 +20,7 @@ display: lambda: |- it.rectangle(0, 0, it.get_width(), it.get_height()); - platform: ili9xxx + invert_colors: false dimensions: width: 320 height: 240 diff --git a/tests/components/ili9xxx/test.rp2040-ard.yaml b/tests/components/ili9xxx/test.rp2040-ard.yaml index 54083ebce8..0423f41a1c 100644 --- a/tests/components/ili9xxx/test.rp2040-ard.yaml +++ b/tests/components/ili9xxx/test.rp2040-ard.yaml @@ -20,6 +20,7 @@ display: lambda: |- it.rectangle(0, 0, it.get_width(), it.get_height()); - platform: ili9xxx + invert_colors: false dimensions: width: 320 height: 240 From 92ae506ffb0c04d91cad1318fa13847325ed05a6 Mon Sep 17 00:00:00 2001 From: Angel Nunez Mencias Date: Wed, 28 Aug 2024 01:40:21 +0200 Subject: [PATCH 1996/2101] Add WS2811 to esp32_rmt_led_strip (#7353) --- esphome/components/esp32_rmt_led_strip/light.py | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/esp32_rmt_led_strip/light.py b/esphome/components/esp32_rmt_led_strip/light.py index 4a04918275..1e3c2d4f72 100644 --- a/esphome/components/esp32_rmt_led_strip/light.py +++ b/esphome/components/esp32_rmt_led_strip/light.py @@ -48,6 +48,7 @@ class LEDStripTimings: CHIPSETS = { + "WS2811": LEDStripTimings(300, 1090, 1090, 320, 0, 300000), "WS2812": LEDStripTimings(400, 1000, 1000, 400, 0, 0), "SK6812": LEDStripTimings(300, 900, 600, 600, 0, 0), "APA106": LEDStripTimings(350, 1360, 1360, 350, 0, 0), From 388abaf09f8a5d2da7e4b8355738dad8852b752f Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Fri, 23 Aug 2024 04:56:53 +1000 Subject: [PATCH 1997/2101] [lvgl] Bug fixes (#7338) --- esphome/components/lvgl/automation.py | 16 +++++++++++++--- esphome/components/lvgl/lvgl_esphome.cpp | 7 +++++++ esphome/components/lvgl/lvgl_esphome.h | 1 + esphome/components/lvgl/widgets/__init__.py | 6 ++++++ esphome/components/lvgl/widgets/line.py | 12 +++++++----- esphome/components/lvgl/widgets/msgbox.py | 3 ++- tests/components/lvgl/lvgl-package.yaml | 6 +++++- 7 files changed, 41 insertions(+), 10 deletions(-) diff --git a/esphome/components/lvgl/automation.py b/esphome/components/lvgl/automation.py index a39f589136..efcac977ab 100644 --- a/esphome/components/lvgl/automation.py +++ b/esphome/components/lvgl/automation.py @@ -5,6 +5,7 @@ from esphome import automation import esphome.codegen as cg import esphome.config_validation as cv from esphome.const import CONF_ID, CONF_TIMEOUT +from esphome.cpp_generator import RawExpression from esphome.cpp_types import nullptr from .defines import ( @@ -26,6 +27,7 @@ from .lvcode import ( add_line_marks, lv, lv_add, + lv_expr, lv_obj, lvgl_comp, ) @@ -38,7 +40,13 @@ from .types import ( lv_disp_t, lv_obj_t, ) -from .widgets import Widget, get_widgets, lv_scr_act, set_obj_properties +from .widgets import ( + Widget, + get_widgets, + lv_scr_act, + set_obj_properties, + wait_for_widgets, +) async def action_to_code( @@ -48,10 +56,12 @@ async def action_to_code( template_arg, args, ): + await wait_for_widgets() async with LambdaContext(parameters=args, where=action_id) as context: + with LvConditional(lv_expr.is_pre_initialise()): + context.add(RawExpression("return")) for widget in widgets: - with LvConditional(widget.obj != nullptr): - await action(widget) + await action(widget) var = cg.new_Pvariable(action_id, template_arg, await context.get_lambda()) return var diff --git a/esphome/components/lvgl/lvgl_esphome.cpp b/esphome/components/lvgl/lvgl_esphome.cpp index 92f7a880c3..6882986e7c 100644 --- a/esphome/components/lvgl/lvgl_esphome.cpp +++ b/esphome/components/lvgl/lvgl_esphome.cpp @@ -294,6 +294,13 @@ void LvglComponent::loop() { } lv_timer_handler_run_in_period(5); } +bool lv_is_pre_initialise() { + if (!lv_is_initialized()) { + ESP_LOGE(TAG, "LVGL call before component is initialised"); + return true; + } + return false; +} #ifdef USE_LVGL_IMAGE lv_img_dsc_t *lv_img_from(image::Image *src, lv_img_dsc_t *img_dsc) { diff --git a/esphome/components/lvgl/lvgl_esphome.h b/esphome/components/lvgl/lvgl_esphome.h index 3a3d1aa6c5..df3d4aa68c 100644 --- a/esphome/components/lvgl/lvgl_esphome.h +++ b/esphome/components/lvgl/lvgl_esphome.h @@ -40,6 +40,7 @@ namespace lvgl { extern lv_event_code_t lv_api_event; // NOLINT extern lv_event_code_t lv_update_event; // NOLINT +extern bool lv_is_pre_initialise(); #ifdef USE_LVGL_COLOR inline lv_color_t lv_color_from(Color color) { return lv_color_make(color.red, color.green, color.blue); } #endif // USE_LVGL_COLOR diff --git a/esphome/components/lvgl/widgets/__init__.py b/esphome/components/lvgl/widgets/__init__.py index 4abb25c61d..50da6e131d 100644 --- a/esphome/components/lvgl/widgets/__init__.py +++ b/esphome/components/lvgl/widgets/__init__.py @@ -1,3 +1,4 @@ +import asyncio import sys from typing import Any, Union @@ -223,6 +224,11 @@ async def get_widget_(wid: Widget): return await FakeAwaitable(get_widget_generator(wid)) +async def wait_for_widgets(): + while not Widget.widgets_completed: + await asyncio.sleep(0) + + async def get_widgets(config: Union[dict, list], id: str = CONF_ID) -> list[Widget]: if not config: return [] diff --git a/esphome/components/lvgl/widgets/line.py b/esphome/components/lvgl/widgets/line.py index 8ce4b1965f..4c6439fde4 100644 --- a/esphome/components/lvgl/widgets/line.py +++ b/esphome/components/lvgl/widgets/line.py @@ -3,7 +3,7 @@ import functools import esphome.codegen as cg import esphome.config_validation as cv -from ..defines import CONF_MAIN, literal +from ..defines import CONF_MAIN from ..lvcode import lv from ..types import LvType from . import Widget, WidgetType @@ -38,13 +38,15 @@ LINE_SCHEMA = { class LineType(WidgetType): def __init__(self): - super().__init__(CONF_LINE, LvType("lv_line_t"), (CONF_MAIN,), LINE_SCHEMA) + super().__init__( + CONF_LINE, LvType("lv_line_t"), (CONF_MAIN,), LINE_SCHEMA, modify_schema={} + ) async def to_code(self, w: Widget, config): """For a line object, create and add the points""" - data = literal(config[CONF_POINTS]) - points = cg.static_const_array(config[CONF_POINT_LIST_ID], data) - lv.line_set_points(w.obj, points, len(data)) + if data := config.get(CONF_POINTS): + points = cg.static_const_array(config[CONF_POINT_LIST_ID], data) + lv.line_set_points(w.obj, points, len(data)) line_spec = LineType() diff --git a/esphome/components/lvgl/widgets/msgbox.py b/esphome/components/lvgl/widgets/msgbox.py index 63c4326c7c..c377af6bde 100644 --- a/esphome/components/lvgl/widgets/msgbox.py +++ b/esphome/components/lvgl/widgets/msgbox.py @@ -13,7 +13,7 @@ from ..defines import ( TYPE_FLEX, literal, ) -from ..helpers import add_lv_use +from ..helpers import add_lv_use, lvgl_components_required from ..lv_validation import lv_bool, lv_pct, lv_text from ..lvcode import ( EVENT_ARG, @@ -72,6 +72,7 @@ async def msgbox_to_code(conf): *buttonmatrix_spec.get_uses(), *button_spec.get_uses(), ) + lvgl_components_required.add("BUTTONMATRIX") messagebox_id = conf[CONF_ID] outer = lv_Pvariable(lv_obj_t, messagebox_id.id) buttonmatrix = new_Pvariable( diff --git a/tests/components/lvgl/lvgl-package.yaml b/tests/components/lvgl/lvgl-package.yaml index 800d6eff27..1479ce7358 100644 --- a/tests/components/lvgl/lvgl-package.yaml +++ b/tests/components/lvgl/lvgl-package.yaml @@ -379,6 +379,7 @@ lvgl: format: "bar value %f" args: [x] - line: + id: lv_line_id align: center points: - 5, 5 @@ -387,7 +388,10 @@ lvgl: - 180, 60 - 240, 10 on_click: - lvgl.page.next: + - lvgl.widget.update: + id: lv_line_id + line_color: 0xFFFF + - lvgl.page.next: - switch: align: right_mid - checkbox: From 86777634922a9c1b695d2f3da30630a827ccd2cf Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Fri, 23 Aug 2024 18:09:40 +1000 Subject: [PATCH 1998/2101] [core] Clean build if the loaded integrations changed (#7344) --- esphome/writer.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/esphome/writer.py b/esphome/writer.py index c6111cbe3f..57435d3463 100644 --- a/esphome/writer.py +++ b/esphome/writer.py @@ -106,6 +106,8 @@ def storage_should_clean(old: StorageJSON, new: StorageJSON) -> bool: return True if old.build_path != new.build_path: return True + if old.loaded_integrations != new.loaded_integrations: + return True return False @@ -117,7 +119,9 @@ def update_storage_json(): return if storage_should_clean(old, new): - _LOGGER.info("Core config or version changed, cleaning build files...") + _LOGGER.info( + "Core config, version or integrations changed, cleaning build files..." + ) clean_build() new.save(path) From c1774c42c25350cebc4f649184ba9b1374c6397c Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Mon, 26 Aug 2024 08:03:25 +1000 Subject: [PATCH 1999/2101] [lvgl] Fix race condition involving numbers, switches etc. (#7345) --- esphome/components/lvgl/__init__.py | 5 ++++- esphome/components/lvgl/binary_sensor/__init__.py | 3 ++- esphome/components/lvgl/light/__init__.py | 3 ++- esphome/components/lvgl/lvcode.py | 3 +++ esphome/components/lvgl/number/__init__.py | 3 ++- esphome/components/lvgl/select/__init__.py | 3 ++- esphome/components/lvgl/sensor/__init__.py | 3 ++- esphome/components/lvgl/switch/__init__.py | 3 ++- esphome/components/lvgl/text/__init__.py | 3 ++- esphome/components/lvgl/text_sensor/__init__.py | 3 ++- esphome/components/lvgl/widgets/__init__.py | 13 ++++++++++--- 11 files changed, 33 insertions(+), 12 deletions(-) diff --git a/esphome/components/lvgl/__init__.py b/esphome/components/lvgl/__init__.py index 7c51d9c70d..ea020435dc 100644 --- a/esphome/components/lvgl/__init__.py +++ b/esphome/components/lvgl/__init__.py @@ -266,7 +266,10 @@ async def to_code(config): await add_top_layer(config) await msgboxes_to_code(config) await disp_update(f"{lv_component}->get_disp()", config) - Widget.set_completed() + # At this point only the setup code should be generated + assert LvContext.added_lambda_count == 1 + Widget.set_completed() + async with LvContext(lv_component): await generate_triggers(lv_component) for conf in config.get(CONF_ON_IDLE, ()): templ = await cg.templatable(conf[CONF_TIMEOUT], [], cg.uint32) diff --git a/esphome/components/lvgl/binary_sensor/__init__.py b/esphome/components/lvgl/binary_sensor/__init__.py index 8789a06375..56984405aa 100644 --- a/esphome/components/lvgl/binary_sensor/__init__.py +++ b/esphome/components/lvgl/binary_sensor/__init__.py @@ -10,7 +10,7 @@ from ..defines import CONF_LVGL_ID, CONF_WIDGET from ..lvcode import EVENT_ARG, LambdaContext, LvContext from ..schemas import LVGL_SCHEMA from ..types import LV_EVENT, lv_pseudo_button_t -from ..widgets import Widget, get_widgets +from ..widgets import Widget, get_widgets, wait_for_widgets CONFIG_SCHEMA = ( binary_sensor_schema(BinarySensor) @@ -29,6 +29,7 @@ async def to_code(config): widget = await get_widgets(config, CONF_WIDGET) widget = widget[0] assert isinstance(widget, Widget) + await wait_for_widgets() async with LambdaContext(EVENT_ARG) as pressed_ctx: pressed_ctx.add(sensor.publish_state(widget.is_pressed())) async with LvContext(paren) as ctx: diff --git a/esphome/components/lvgl/light/__init__.py b/esphome/components/lvgl/light/__init__.py index 27c160dff6..a0eeded349 100644 --- a/esphome/components/lvgl/light/__init__.py +++ b/esphome/components/lvgl/light/__init__.py @@ -8,7 +8,7 @@ from ..defines import CONF_LVGL_ID from ..lvcode import LvContext from ..schemas import LVGL_SCHEMA from ..types import LvType, lvgl_ns -from ..widgets import get_widgets +from ..widgets import get_widgets, wait_for_widgets lv_led_t = LvType("lv_led_t") LVLight = lvgl_ns.class_("LVLight", LightOutput) @@ -28,5 +28,6 @@ async def to_code(config): paren = await cg.get_variable(config[CONF_LVGL_ID]) widget = await get_widgets(config, CONF_LED) widget = widget[0] + await wait_for_widgets() async with LvContext(paren) as ctx: ctx.add(var.set_obj(widget.obj)) diff --git a/esphome/components/lvgl/lvcode.py b/esphome/components/lvgl/lvcode.py index 6d7e364e5d..8d029ce0ca 100644 --- a/esphome/components/lvgl/lvcode.py +++ b/esphome/components/lvgl/lvcode.py @@ -176,6 +176,8 @@ class LvContext(LambdaContext): Code generation into the LVGL initialisation code (called in `setup()`) """ + added_lambda_count = 0 + def __init__(self, lv_component, args=None): self.args = args or LVGL_COMP_ARG super().__init__(parameters=self.args) @@ -183,6 +185,7 @@ class LvContext(LambdaContext): async def add_init_lambda(self): cg.add(self.lv_component.add_init_lambda(await self.get_lambda())) + LvContext.added_lambda_count += 1 async def __aexit__(self, exc_type, exc_val, exc_tb): await super().__aexit__(exc_type, exc_val, exc_tb) diff --git a/esphome/components/lvgl/number/__init__.py b/esphome/components/lvgl/number/__init__.py index 6336bb0632..3e1ede0dec 100644 --- a/esphome/components/lvgl/number/__init__.py +++ b/esphome/components/lvgl/number/__init__.py @@ -16,7 +16,7 @@ from ..lvcode import ( ) from ..schemas import LVGL_SCHEMA from ..types import LV_EVENT, LvNumber, lvgl_ns -from ..widgets import get_widgets +from ..widgets import get_widgets, wait_for_widgets LVGLNumber = lvgl_ns.class_("LVGLNumber", number.Number) @@ -44,6 +44,7 @@ async def to_code(config): step=widget.get_step(), ) + await wait_for_widgets() async with LambdaContext([(cg.float_, "v")]) as control: await widget.set_property( "value", MockObj("v") * MockObj(widget.get_scale()), config[CONF_ANIMATED] diff --git a/esphome/components/lvgl/select/__init__.py b/esphome/components/lvgl/select/__init__.py index b55bde13bc..e77d0cfb32 100644 --- a/esphome/components/lvgl/select/__init__.py +++ b/esphome/components/lvgl/select/__init__.py @@ -15,7 +15,7 @@ from ..lvcode import ( ) from ..schemas import LVGL_SCHEMA from ..types import LV_EVENT, LvSelect, lvgl_ns -from ..widgets import get_widgets +from ..widgets import get_widgets, wait_for_widgets LVGLSelect = lvgl_ns.class_("LVGLSelect", select.Select) @@ -37,6 +37,7 @@ async def to_code(config): options = widget.config.get(CONF_OPTIONS, []) selector = await select.new_select(config, options=options) paren = await cg.get_variable(config[CONF_LVGL_ID]) + await wait_for_widgets() async with LambdaContext(EVENT_ARG) as pub_ctx: pub_ctx.add(selector.publish_index(widget.get_value())) async with LambdaContext([(cg.uint16, "v")]) as control: diff --git a/esphome/components/lvgl/sensor/__init__.py b/esphome/components/lvgl/sensor/__init__.py index 82e21d5e95..a2a2298c27 100644 --- a/esphome/components/lvgl/sensor/__init__.py +++ b/esphome/components/lvgl/sensor/__init__.py @@ -14,7 +14,7 @@ from ..lvcode import ( ) from ..schemas import LVGL_SCHEMA from ..types import LV_EVENT, LvNumber -from ..widgets import Widget, get_widgets +from ..widgets import Widget, get_widgets, wait_for_widgets CONFIG_SCHEMA = ( sensor_schema(Sensor) @@ -33,6 +33,7 @@ async def to_code(config): widget = await get_widgets(config, CONF_WIDGET) widget = widget[0] assert isinstance(widget, Widget) + await wait_for_widgets() async with LambdaContext(EVENT_ARG) as lamb: lv_add(sensor.publish_state(widget.get_value())) async with LvContext(paren, LVGL_COMP_ARG): diff --git a/esphome/components/lvgl/switch/__init__.py b/esphome/components/lvgl/switch/__init__.py index 957fce17ff..f855c2a034 100644 --- a/esphome/components/lvgl/switch/__init__.py +++ b/esphome/components/lvgl/switch/__init__.py @@ -16,7 +16,7 @@ from ..lvcode import ( ) from ..schemas import LVGL_SCHEMA from ..types import LV_EVENT, LV_STATE, lv_pseudo_button_t, lvgl_ns -from ..widgets import get_widgets +from ..widgets import get_widgets, wait_for_widgets LVGLSwitch = lvgl_ns.class_("LVGLSwitch", Switch) CONFIG_SCHEMA = ( @@ -35,6 +35,7 @@ async def to_code(config): paren = await cg.get_variable(config[CONF_LVGL_ID]) widget = await get_widgets(config, CONF_WIDGET) widget = widget[0] + await wait_for_widgets() async with LambdaContext(EVENT_ARG) as checked_ctx: checked_ctx.add(switch.publish_state(widget.get_value())) async with LambdaContext([(cg.bool_, "v")]) as control: diff --git a/esphome/components/lvgl/text/__init__.py b/esphome/components/lvgl/text/__init__.py index 9ee494d8a0..56fa42e131 100644 --- a/esphome/components/lvgl/text/__init__.py +++ b/esphome/components/lvgl/text/__init__.py @@ -15,7 +15,7 @@ from ..lvcode import ( ) from ..schemas import LVGL_SCHEMA from ..types import LV_EVENT, LvText, lvgl_ns -from ..widgets import get_widgets +from ..widgets import get_widgets, wait_for_widgets LVGLText = lvgl_ns.class_("LVGLText", text.Text) @@ -32,6 +32,7 @@ async def to_code(config): paren = await cg.get_variable(config[CONF_LVGL_ID]) widget = await get_widgets(config, CONF_WIDGET) widget = widget[0] + 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, None) diff --git a/esphome/components/lvgl/text_sensor/__init__.py b/esphome/components/lvgl/text_sensor/__init__.py index cab715dce0..ae39eec291 100644 --- a/esphome/components/lvgl/text_sensor/__init__.py +++ b/esphome/components/lvgl/text_sensor/__init__.py @@ -10,7 +10,7 @@ from ..defines import CONF_LVGL_ID, CONF_WIDGET from ..lvcode import API_EVENT, EVENT_ARG, UPDATE_EVENT, LambdaContext, LvContext from ..schemas import LVGL_SCHEMA from ..types import LV_EVENT, LvText -from ..widgets import get_widgets +from ..widgets import get_widgets, wait_for_widgets CONFIG_SCHEMA = ( text_sensor_schema(TextSensor) @@ -28,6 +28,7 @@ async def to_code(config): paren = await cg.get_variable(config[CONF_LVGL_ID]) widget = await get_widgets(config, CONF_WIDGET) widget = widget[0] + await wait_for_widgets() async with LambdaContext(EVENT_ARG) as pressed_ctx: pressed_ctx.add(sensor.publish_state(widget.get_value())) async with LvContext(paren) as ctx: diff --git a/esphome/components/lvgl/widgets/__init__.py b/esphome/components/lvgl/widgets/__init__.py index 50da6e131d..17d73c1714 100644 --- a/esphome/components/lvgl/widgets/__init__.py +++ b/esphome/components/lvgl/widgets/__init__.py @@ -1,4 +1,3 @@ -import asyncio import sys from typing import Any, Union @@ -224,9 +223,17 @@ async def get_widget_(wid: Widget): return await FakeAwaitable(get_widget_generator(wid)) +def widgets_wait_generator(): + while True: + if Widget.widgets_completed: + return + yield + + async def wait_for_widgets(): - while not Widget.widgets_completed: - await asyncio.sleep(0) + if Widget.widgets_completed: + return + await FakeAwaitable(widgets_wait_generator()) async def get_widgets(config: Union[dict, list], id: str = CONF_ID) -> list[Widget]: From 9975e8b544d0d2943503b90e75a4723d130e68b9 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 27 Aug 2024 10:20:26 +1200 Subject: [PATCH 2000/2101] [api] Fix sending the ``once`` flag on ha entity subscription (#7357) --- esphome/components/api/api_connection.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index bd438265d4..195fcab0ab 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -179,6 +179,7 @@ void APIConnection::loop() { SubscribeHomeAssistantStateResponse resp; resp.entity_id = it.entity_id; resp.attribute = it.attribute.value(); + resp.once = it.once; if (this->send_subscribe_home_assistant_state_response(resp)) { state_subs_at_++; } From 28eda4b220519edfd761d65c3d24f0df0aab4f3c Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 28 Aug 2024 12:54:31 +1200 Subject: [PATCH 2001/2101] Bump version to 2024.8.1 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index f99d442be3..b27949bf29 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.8.0" +__version__ = "2024.8.1" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From d6df466237142c542d4ea19ddabe0a7a2f7bb898 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Wed, 28 Aug 2024 14:29:41 +1000 Subject: [PATCH 2002/2101] [lvgl] Add lvgl.widget.focus action and related triggers. (#7315) --- esphome/components/lvgl/__init__.py | 15 +++- esphome/components/lvgl/automation.py | 81 ++++++++++++++++++++- esphome/components/lvgl/defines.py | 5 +- esphome/components/lvgl/lvcode.py | 6 +- esphome/components/lvgl/lvgl_esphome.cpp | 54 ++++++++++++++ esphome/components/lvgl/lvgl_esphome.h | 9 +++ esphome/components/lvgl/schemas.py | 10 +-- esphome/components/lvgl/trigger.py | 5 +- esphome/components/lvgl/types.py | 2 +- esphome/components/lvgl/widgets/__init__.py | 4 +- esphome/components/lvgl/widgets/arc.py | 6 +- esphome/components/lvgl/widgets/page.py | 58 +++++++++++++-- tests/components/lvgl/lvgl-package.yaml | 25 +++++++ 13 files changed, 253 insertions(+), 27 deletions(-) diff --git a/esphome/components/lvgl/__init__.py b/esphome/components/lvgl/__init__.py index ea020435dc..cab6462d1a 100644 --- a/esphome/components/lvgl/__init__.py +++ b/esphome/components/lvgl/__init__.py @@ -21,8 +21,8 @@ from esphome.final_validate import full_config from esphome.helpers import write_file_if_changed from . import defines as df, helpers, lv_validation as lvalid -from .automation import disp_update, update_to_code -from .defines import CONF_SKIP +from .automation import disp_update, focused_widgets, update_to_code +from .defines import CONF_ADJUSTABLE, CONF_SKIP from .encoders import ENCODERS_CONFIG, encoders_to_code, initial_focus_to_code from .lv_validation import lv_bool, lv_images_used from .lvcode import LvContext, LvglComponent @@ -67,7 +67,7 @@ from .widgets.lv_bar import bar_spec from .widgets.meter import meter_spec from .widgets.msgbox import MSGBOX_SCHEMA, msgboxes_to_code from .widgets.obj import obj_spec -from .widgets.page import add_pages, page_spec +from .widgets.page import add_pages, generate_page_triggers, page_spec from .widgets.roller import roller_spec from .widgets.slider import slider_spec from .widgets.spinbox import spinbox_spec @@ -182,6 +182,14 @@ def final_validation(config): raise cv.Invalid( "Using RGBA or RGB24 in image config not compatible with LVGL", path ) + for w in focused_widgets: + path = global_config.get_path_for_id(w) + widget_conf = global_config.get_config_for_path(path[:-1]) + if CONF_ADJUSTABLE in widget_conf and not widget_conf[CONF_ADJUSTABLE]: + raise cv.Invalid( + "A non adjustable arc may not be focused", + path, + ) async def to_code(config): @@ -271,6 +279,7 @@ async def to_code(config): Widget.set_completed() async with LvContext(lv_component): await generate_triggers(lv_component) + await generate_page_triggers(lv_component, config) for conf in config.get(CONF_ON_IDLE, ()): templ = await cg.templatable(conf[CONF_TIMEOUT], [], cg.uint32) idle_trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], lv_component, templ) diff --git a/esphome/components/lvgl/automation.py b/esphome/components/lvgl/automation.py index eb1b54e3ec..8138551c30 100644 --- a/esphome/components/lvgl/automation.py +++ b/esphome/components/lvgl/automation.py @@ -4,13 +4,15 @@ from typing import Callable from esphome import automation import esphome.codegen as cg import esphome.config_validation as cv -from esphome.const import CONF_ID, CONF_TIMEOUT -from esphome.cpp_generator import RawExpression +from esphome.const import CONF_ACTION, CONF_GROUP, CONF_ID, CONF_TIMEOUT +from esphome.cpp_generator import RawExpression, get_variable from esphome.cpp_types import nullptr from .defines import ( CONF_DISP_BG_COLOR, CONF_DISP_BG_IMAGE, + CONF_EDITING, + CONF_FREEZE, CONF_LVGL_ID, CONF_SHOW_SNOW, literal, @@ -30,6 +32,7 @@ from .lvcode import ( lv_expr, lv_obj, lvgl_comp, + static_cast, ) from .schemas import DISP_BG_SCHEMA, LIST_ACTION_SCHEMA, LVGL_SCHEMA from .types import ( @@ -38,7 +41,9 @@ from .types import ( LvglCondition, ObjUpdateAction, lv_disp_t, + lv_group_t, lv_obj_t, + lv_pseudo_button_t, ) from .widgets import ( Widget, @@ -48,6 +53,9 @@ from .widgets import ( wait_for_widgets, ) +# Record widgets that are used in a focused action here +focused_widgets = set() + async def action_to_code( widgets: list[Widget], @@ -234,3 +242,72 @@ async def obj_show_to_code(config, action_id, template_arg, args): return await action_to_code( await get_widgets(config), do_show, action_id, template_arg, args ) + + +def focused_id(value): + value = cv.use_id(lv_pseudo_button_t)(value) + focused_widgets.add(value) + return value + + +@automation.register_action( + "lvgl.widget.focus", + ObjUpdateAction, + cv.Any( + cv.maybe_simple_value( + { + cv.Optional(CONF_GROUP): cv.use_id(lv_group_t), + cv.Required(CONF_ACTION): cv.one_of( + "MARK", "RESTORE", "NEXT", "PREVIOUS", upper=True + ), + cv.GenerateID(CONF_LVGL_ID): cv.use_id(LvglComponent), + cv.Optional(CONF_FREEZE, default=False): cv.boolean, + }, + key=CONF_ACTION, + ), + cv.maybe_simple_value( + { + cv.Required(CONF_ID): focused_id, + cv.Optional(CONF_FREEZE, default=False): cv.boolean, + cv.Optional(CONF_EDITING, default=False): cv.boolean, + }, + key=CONF_ID, + ), + ), +) +async def widget_focus(config, action_id, template_arg, args): + widget = await get_widgets(config) + if widget: + widget = widget[0] + group = static_cast( + lv_group_t.operator("ptr"), lv_expr.obj_get_group(widget.obj) + ) + elif group := config.get(CONF_GROUP): + group = await get_variable(group) + else: + group = lv_expr.group_get_default() + + async with LambdaContext(parameters=args, where=action_id) as context: + if widget: + lv.group_focus_freeze(group, False) + lv.group_focus_obj(widget.obj) + if config[CONF_EDITING]: + lv.group_set_editing(group, True) + else: + action = config[CONF_ACTION] + lv_comp = await get_variable(config[CONF_LVGL_ID]) + if action == "MARK": + context.add(lv_comp.set_focus_mark(group)) + else: + lv.group_focus_freeze(group, False) + if action == "RESTORE": + context.add(lv_comp.restore_focus_mark(group)) + elif action == "NEXT": + lv.group_focus_next(group) + else: + lv.group_focus_prev(group) + + if config[CONF_FREEZE]: + lv.group_focus_freeze(group, True) + var = cg.new_Pvariable(action_id, template_arg, await context.get_lambda()) + return var diff --git a/esphome/components/lvgl/defines.py b/esphome/components/lvgl/defines.py index 7bb1667e77..e05bf52120 100644 --- a/esphome/components/lvgl/defines.py +++ b/esphome/components/lvgl/defines.py @@ -148,6 +148,7 @@ LV_EVENT_MAP = { "DEFOCUS": "DEFOCUSED", "READY": "READY", "CANCEL": "CANCEL", + "ALL_EVENTS": "ALL", } LV_EVENT_TRIGGERS = tuple(f"on_{x.lower()}" for x in LV_EVENT_MAP) @@ -390,6 +391,7 @@ CONF_DEFAULT_FONT = "default_font" CONF_DEFAULT_GROUP = "default_group" CONF_DIR = "dir" CONF_DISPLAYS = "displays" +CONF_EDITING = "editing" CONF_ENCODERS = "encoders" CONF_END_ANGLE = "end_angle" CONF_END_VALUE = "end_value" @@ -401,6 +403,7 @@ CONF_FLEX_ALIGN_MAIN = "flex_align_main" CONF_FLEX_ALIGN_CROSS = "flex_align_cross" CONF_FLEX_ALIGN_TRACK = "flex_align_track" CONF_FLEX_GROW = "flex_grow" +CONF_FREEZE = "freeze" CONF_FULL_REFRESH = "full_refresh" CONF_GRID_CELL_ROW_POS = "grid_cell_row_pos" CONF_GRID_CELL_COLUMN_POS = "grid_cell_column_pos" @@ -428,9 +431,9 @@ CONF_MSGBOXES = "msgboxes" CONF_OBJ = "obj" CONF_OFFSET_X = "offset_x" CONF_OFFSET_Y = "offset_y" +CONF_ONE_CHECKED = "one_checked" CONF_ONE_LINE = "one_line" CONF_ON_SELECT = "on_select" -CONF_ONE_CHECKED = "one_checked" CONF_NEXT = "next" CONF_PAD_ROW = "pad_row" CONF_PAD_COLUMN = "pad_column" diff --git a/esphome/components/lvgl/lvcode.py b/esphome/components/lvgl/lvcode.py index 8d029ce0ca..a3d13f7f8c 100644 --- a/esphome/components/lvgl/lvcode.py +++ b/esphome/components/lvgl/lvcode.py @@ -28,7 +28,7 @@ LVGL_COMP = "lv_component" # used as a lambda argument in lvgl_comp() LvglComponent = lvgl_ns.class_("LvglComponent", cg.PollingComponent) LVGL_COMP_ARG = [(LvglComponent.operator("ptr"), LVGL_COMP)] lv_event_t_ptr = cg.global_ns.namespace("lv_event_t").operator("ptr") -EVENT_ARG = [(lv_event_t_ptr, "ev")] +EVENT_ARG = [(lv_event_t_ptr, "event")] # Two custom events; API_EVENT is fired when an entity is updated remotely by an API interaction; # UPDATE_EVENT is fired when an entity is programmatically updated locally. # VALUE_CHANGED is the event generated by LVGL when an entity's value changes through user interaction. @@ -291,6 +291,10 @@ class LvExpr(MockLv): pass +def static_cast(type, value): + return literal(f"static_cast<{type}>({value})") + + # Top level mock for generic lv_ calls to be recorded lv = MockLv("lv_") # Just generate an expression diff --git a/esphome/components/lvgl/lvgl_esphome.cpp b/esphome/components/lvgl/lvgl_esphome.cpp index 6882986e7c..89c9828740 100644 --- a/esphome/components/lvgl/lvgl_esphome.cpp +++ b/esphome/components/lvgl/lvgl_esphome.cpp @@ -15,6 +15,60 @@ static void log_cb(const char *buf) { } #endif // LV_USE_LOG +static const char *const EVENT_NAMES[] = { + "NONE", + "PRESSED", + "PRESSING", + "PRESS_LOST", + "SHORT_CLICKED", + "LONG_PRESSED", + "LONG_PRESSED_REPEAT", + "CLICKED", + "RELEASED", + "SCROLL_BEGIN", + "SCROLL_END", + "SCROLL", + "GESTURE", + "KEY", + "FOCUSED", + "DEFOCUSED", + "LEAVE", + "HIT_TEST", + "COVER_CHECK", + "REFR_EXT_DRAW_SIZE", + "DRAW_MAIN_BEGIN", + "DRAW_MAIN", + "DRAW_MAIN_END", + "DRAW_POST_BEGIN", + "DRAW_POST", + "DRAW_POST_END", + "DRAW_PART_BEGIN", + "DRAW_PART_END", + "VALUE_CHANGED", + "INSERT", + "REFRESH", + "READY", + "CANCEL", + "DELETE", + "CHILD_CHANGED", + "CHILD_CREATED", + "CHILD_DELETED", + "SCREEN_UNLOAD_START", + "SCREEN_LOAD_START", + "SCREEN_LOADED", + "SCREEN_UNLOADED", + "SIZE_CHANGED", + "STYLE_CHANGED", + "LAYOUT_CHANGED", + "GET_SELF_SIZE", +}; + +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); +} static void rounder_cb(lv_disp_drv_t *disp_drv, lv_area_t *area) { // make sure all coordinates are even if (area->x1 & 1) diff --git a/esphome/components/lvgl/lvgl_esphome.h b/esphome/components/lvgl/lvgl_esphome.h index df3d4aa68c..e248530971 100644 --- a/esphome/components/lvgl/lvgl_esphome.h +++ b/esphome/components/lvgl/lvgl_esphome.h @@ -40,6 +40,7 @@ namespace lvgl { 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 bool lv_is_pre_initialise(); #ifdef USE_LVGL_COLOR inline lv_color_t lv_color_from(Color color) { return lv_color_make(color.red, color.green, color.blue); } @@ -143,6 +144,13 @@ class LvglComponent : public PollingComponent { 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_focus_mark(lv_group_t *group) { this->focus_marks_[group] = lv_group_get_focused(group); } + void restore_focus_mark(lv_group_t *group) { + auto *mark = this->focus_marks_[group]; + if (mark != nullptr) { + lv_group_focus_obj(mark); + } + } protected: void write_random_(); @@ -158,6 +166,7 @@ class LvglComponent : public PollingComponent { bool show_snow_{}; lv_coord_t snow_line_{}; bool page_wrap_{true}; + std::map focus_marks_{}; std::vector> init_lambdas_; CallbackManager idle_callbacks_{}; diff --git a/esphome/components/lvgl/schemas.py b/esphome/components/lvgl/schemas.py index e9714e3b1a..548ebda6dc 100644 --- a/esphome/components/lvgl/schemas.py +++ b/esphome/components/lvgl/schemas.py @@ -20,7 +20,7 @@ from . import defines as df, lv_validation as lvalid from .defines import CONF_TIME_FORMAT from .helpers import add_lv_use, requires_component, validate_printf from .lv_validation import lv_color, lv_font, lv_image -from .lvcode import LvglComponent +from .lvcode import LvglComponent, lv_event_t_ptr from .types import ( LVEncoderListener, LvType, @@ -215,14 +215,12 @@ def automation_schema(typ: LvType): events = df.LV_EVENT_TRIGGERS + (CONF_ON_VALUE,) else: events = df.LV_EVENT_TRIGGERS - if isinstance(typ, LvType): - template = Trigger.template(typ.get_arg_type()) - else: - template = Trigger.template() + args = [typ.get_arg_type()] if isinstance(typ, LvType) else [] + args.append(lv_event_t_ptr) return { cv.Optional(event): validate_automation( { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(template), + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(Trigger.template(*args)), } ) for event in events diff --git a/esphome/components/lvgl/trigger.py b/esphome/components/lvgl/trigger.py index ba93aabb2d..5288745fab 100644 --- a/esphome/components/lvgl/trigger.py +++ b/esphome/components/lvgl/trigger.py @@ -19,6 +19,7 @@ from .lvcode import ( LvConditional, lv, lv_add, + lv_event_t_ptr, ) from .types import LV_EVENT from .widgets import widget_map @@ -65,10 +66,10 @@ async def generate_triggers(lv_component): async def add_trigger(conf, lv_component, w, *events): tid = conf[CONF_TRIGGER_ID] trigger = cg.new_Pvariable(tid) - args = w.get_args() + args = w.get_args() + [(lv_event_t_ptr, "event")] value = w.get_value() await automation.build_automation(trigger, args, conf) async with LambdaContext(EVENT_ARG, where=tid) as context: with LvConditional(w.is_selected()): - lv_add(trigger.trigger(value)) + lv_add(trigger.trigger(value, literal("event"))) lv_add(lv_component.add_event_cb(w.obj, await context.get_lambda(), *events)) diff --git a/esphome/components/lvgl/types.py b/esphome/components/lvgl/types.py index be17cf62c2..e4735ea58d 100644 --- a/esphome/components/lvgl/types.py +++ b/esphome/components/lvgl/types.py @@ -57,7 +57,7 @@ lv_group_t = cg.global_ns.struct("lv_group_t") LVTouchListener = lvgl_ns.class_("LVTouchListener") LVEncoderListener = lvgl_ns.class_("LVEncoderListener") lv_obj_t = LvType("lv_obj_t") -lv_page_t = cg.global_ns.class_("LvPageType", LvCompound) +lv_page_t = LvType("LvPageType", parents=(LvCompound,)) lv_img_t = LvType("lv_img_t") LV_EVENT = MockObj(base="LV_EVENT_", op="") diff --git a/esphome/components/lvgl/widgets/__init__.py b/esphome/components/lvgl/widgets/__init__.py index 062c268135..ae06bf20b0 100644 --- a/esphome/components/lvgl/widgets/__init__.py +++ b/esphome/components/lvgl/widgets/__init__.py @@ -225,7 +225,7 @@ def get_widget_generator(wid): yield -async def get_widget_(wid: Widget): +async def get_widget_(wid): if obj := widget_map.get(wid): return obj return await FakeAwaitable(get_widget_generator(wid)) @@ -348,8 +348,6 @@ async def set_obj_properties(w: Widget, config): if group := config.get(CONF_GROUP): group = await cg.get_variable(group) lv.group_add_obj(group, w.obj) - flag_clr = set() - flag_set = set() props = parts[CONF_MAIN][CONF_DEFAULT] lambs = {} flag_set = set() diff --git a/esphome/components/lvgl/widgets/arc.py b/esphome/components/lvgl/widgets/arc.py index a6f8918e2f..dc120e4cbb 100644 --- a/esphome/components/lvgl/widgets/arc.py +++ b/esphome/components/lvgl/widgets/arc.py @@ -1,5 +1,6 @@ import esphome.config_validation as cv from esphome.const import ( + CONF_GROUP, CONF_MAX_VALUE, CONF_MIN_VALUE, CONF_MODE, @@ -20,7 +21,7 @@ from ..defines import ( literal, ) from ..lv_validation import angle, get_start_value, lv_float -from ..lvcode import lv, lv_obj +from ..lvcode import lv, lv_expr, lv_obj from ..types import LvNumber, NumberType from . import Widget @@ -69,6 +70,9 @@ class ArcType(NumberType): if config.get(CONF_ADJUSTABLE) is False: lv_obj.remove_style(w.obj, nullptr, literal("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) value = await get_start_value(config) if value is not None: diff --git a/esphome/components/lvgl/widgets/page.py b/esphome/components/lvgl/widgets/page.py index f80d802b33..0e84ab6791 100644 --- a/esphome/components/lvgl/widgets/page.py +++ b/esphome/components/lvgl/widgets/page.py @@ -1,6 +1,7 @@ from esphome import automation, codegen as cg +from esphome.automation import Trigger import esphome.config_validation as cv -from esphome.const import CONF_ID, CONF_PAGES, CONF_TIME +from esphome.const import CONF_ID, CONF_PAGES, CONF_TIME, CONF_TRIGGER_ID from ..defines import ( CONF_ANIMATION, @@ -9,12 +10,39 @@ from ..defines import ( CONF_PAGE_WRAP, CONF_SKIP, LV_ANIM, + literal, ) from ..lv_validation import lv_bool, lv_milliseconds -from ..lvcode import LVGL_COMP_ARG, LambdaContext, add_line_marks, lv_add, lvgl_comp +from ..lvcode import ( + EVENT_ARG, + LVGL_COMP_ARG, + LambdaContext, + add_line_marks, + lv_add, + lvgl_comp, +) from ..schemas import LVGL_SCHEMA from ..types import LvglAction, lv_page_t -from . import Widget, WidgetType, add_widgets, set_obj_properties +from . import Widget, WidgetType, add_widgets, get_widgets, set_obj_properties + +CONF_ON_LOAD = "on_load" +CONF_ON_UNLOAD = "on_unload" + +PAGE_SCHEMA = cv.Schema( + { + cv.Optional(CONF_SKIP, default=False): lv_bool, + cv.Optional(CONF_ON_LOAD): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(Trigger.template()), + } + ), + cv.Optional(CONF_ON_UNLOAD): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(Trigger.template()), + } + ), + } +) class PageType(WidgetType): @@ -23,9 +51,8 @@ class PageType(WidgetType): CONF_PAGE, lv_page_t, (), - { - cv.Optional(CONF_SKIP, default=False): lv_bool, - }, + PAGE_SCHEMA, + modify_schema={}, ) async def to_code(self, w: Widget, config: dict): @@ -39,7 +66,6 @@ SHOW_SCHEMA = LVGL_SCHEMA.extend( } ) - page_spec = PageType() @@ -111,3 +137,21 @@ async def add_pages(lv_component, config): await set_obj_properties(page, config) await set_obj_properties(page, pconf) await add_widgets(page, pconf) + + +async def generate_page_triggers(lv_component, config): + for pconf in config.get(CONF_PAGES, ()): + page = (await get_widgets(pconf))[0] + for ev in (CONF_ON_LOAD, CONF_ON_UNLOAD): + for loaded in pconf.get(ev, ()): + trigger = cg.new_Pvariable(loaded[CONF_TRIGGER_ID]) + await automation.build_automation(trigger, [], loaded) + async with LambdaContext(EVENT_ARG, where=id) as context: + lv_add(trigger.trigger()) + lv_add( + lv_component.add_event_cb( + page.obj, + await context.get_lambda(), + literal(f"LV_EVENT_SCREEN_{ev[3:].upper()}_START"), + ) + ) diff --git a/tests/components/lvgl/lvgl-package.yaml b/tests/components/lvgl/lvgl-package.yaml index 0e2c37048b..737d8703b0 100644 --- a/tests/components/lvgl/lvgl-package.yaml +++ b/tests/components/lvgl/lvgl-package.yaml @@ -54,6 +54,17 @@ lvgl: long_press_time: 500ms pages: - id: page1 + on_load: + - logger.log: page loaded + - lvgl.widget.focus: + action: restore + on_unload: + - logger.log: page unloaded + - lvgl.widget.focus: mark + on_all_events: + logger.log: + format: "Event %s" + args: ['lv_event_code_name_for(event->code).c_str()'] skip: true layout: type: flex @@ -70,6 +81,10 @@ lvgl: repeat_count: 10 duration: 1s auto_start: true + on_all_events: + logger.log: + format: "Event %s" + args: ['lv_event_code_name_for(event->code).c_str()'] - label: id: hello_label text: Hello world @@ -229,6 +244,16 @@ lvgl: - label: text: Button on_click: + - lvgl.widget.focus: spin_up + - lvgl.widget.focus: next + - lvgl.widget.focus: previous + - lvgl.widget.focus: + action: previous + freeze: true + - lvgl.widget.focus: + id: spin_up + freeze: true + editing: true - lvgl.label.update: id: hello_label bg_color: 0x123456 From 4b2032a98e7b93c359da92af00d0926bb2d9551d Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 29 Aug 2024 05:07:31 +1200 Subject: [PATCH 2003/2101] [datetime] Fix templated args (#7368) --- esphome/components/datetime/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/datetime/__init__.py b/esphome/components/datetime/__init__.py index 4fda97c5bc..5429121d56 100644 --- a/esphome/components/datetime/__init__.py +++ b/esphome/components/datetime/__init__.py @@ -186,7 +186,7 @@ async def datetime_date_set_to_code(config, action_id, template_arg, args): date_config = config[CONF_DATE] if cg.is_template(date_config): - template_ = await cg.templatable(date_config, [], cg.ESPTime) + template_ = await cg.templatable(date_config, args, cg.ESPTime) cg.add(action_var.set_date(template_)) else: date_struct = cg.StructInitializer( @@ -217,7 +217,7 @@ async def datetime_time_set_to_code(config, action_id, template_arg, args): time_config = config[CONF_TIME] if cg.is_template(time_config): - template_ = await cg.templatable(time_config, [], cg.ESPTime) + template_ = await cg.templatable(time_config, args, cg.ESPTime) cg.add(action_var.set_time(template_)) else: time_struct = cg.StructInitializer( @@ -248,7 +248,7 @@ async def datetime_datetime_set_to_code(config, action_id, template_arg, args): datetime_config = config[CONF_DATETIME] if cg.is_template(datetime_config): - template_ = await cg.templatable(datetime_config, [], cg.ESPTime) + template_ = await cg.templatable(datetime_config, args, cg.ESPTime) cg.add(action_var.set_datetime(template_)) else: datetime_struct = cg.StructInitializer( From b3f03c07c615ae072de8fc1c9f7e6171497a7e3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20Kry=C5=84ski?= Date: Thu, 29 Aug 2024 02:52:13 +0200 Subject: [PATCH 2004/2101] esp32_can: suppress compiler warning (#7372) --- esphome/components/esp32_can/esp32_can.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/esp32_can/esp32_can.cpp b/esphome/components/esp32_can/esp32_can.cpp index 79e4b70f97..214b72e864 100644 --- a/esphome/components/esp32_can/esp32_can.cpp +++ b/esphome/components/esp32_can/esp32_can.cpp @@ -111,6 +111,7 @@ canbus::Error ESP32Can::send_message(struct canbus::CanFrame *frame) { .flags = flags, .identifier = frame->can_id, .data_length_code = frame->can_data_length_code, + .data = {}, // to suppress warning, data is initialized properly below }; if (!frame->remote_transmission_request) { memcpy(message.data, frame->data, frame->can_data_length_code); From 0375072bdfe57d5f8eb50b622e9ad9d6d298fd4a Mon Sep 17 00:00:00 2001 From: Aiden <37043404+tarontop@users.noreply.github.com> Date: Thu, 29 Aug 2024 08:52:49 +0800 Subject: [PATCH 2005/2101] Add support for BL0906 energy meter (#7339) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- CODEOWNERS | 1 + esphome/components/bl0906/__init__.py | 1 + esphome/components/bl0906/bl0906.cpp | 238 ++++++++++++++++++ esphome/components/bl0906/bl0906.h | 96 +++++++ esphome/components/bl0906/const.py | 4 + esphome/components/bl0906/constants.h | 122 +++++++++ esphome/components/bl0906/sensor.py | 184 ++++++++++++++ tests/components/bl0906/common.yaml | 62 +++++ tests/components/bl0906/test.esp32-ard.yaml | 5 + .../components/bl0906/test.esp32-c3-ard.yaml | 5 + .../components/bl0906/test.esp32-c3-idf.yaml | 5 + tests/components/bl0906/test.esp32-idf.yaml | 5 + tests/components/bl0906/test.esp8266-ard.yaml | 5 + tests/components/bl0906/test.rp2040-ard.yaml | 5 + 14 files changed, 738 insertions(+) create mode 100644 esphome/components/bl0906/__init__.py create mode 100644 esphome/components/bl0906/bl0906.cpp create mode 100644 esphome/components/bl0906/bl0906.h create mode 100644 esphome/components/bl0906/const.py create mode 100644 esphome/components/bl0906/constants.h create mode 100644 esphome/components/bl0906/sensor.py create mode 100644 tests/components/bl0906/common.yaml create mode 100644 tests/components/bl0906/test.esp32-ard.yaml create mode 100644 tests/components/bl0906/test.esp32-c3-ard.yaml create mode 100644 tests/components/bl0906/test.esp32-c3-idf.yaml create mode 100644 tests/components/bl0906/test.esp32-idf.yaml create mode 100644 tests/components/bl0906/test.esp8266-ard.yaml create mode 100644 tests/components/bl0906/test.rp2040-ard.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 9159f5f843..40511e2f41 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -58,6 +58,7 @@ esphome/components/beken_spi_led_strip/* @Mat931 esphome/components/bh1750/* @OttoWinter esphome/components/binary_sensor/* @esphome/core esphome/components/bk72xx/* @kuba2k2 +esphome/components/bl0906/* @athom-tech @jesserockz @tarontop esphome/components/bl0939/* @ziceva esphome/components/bl0940/* @tobias- esphome/components/bl0942/* @dbuezas diff --git a/esphome/components/bl0906/__init__.py b/esphome/components/bl0906/__init__.py new file mode 100644 index 0000000000..b077792604 --- /dev/null +++ b/esphome/components/bl0906/__init__.py @@ -0,0 +1 @@ +CODEOWNERS = ["@athom-tech", "@tarontop", "@jesserockz"] diff --git a/esphome/components/bl0906/bl0906.cpp b/esphome/components/bl0906/bl0906.cpp new file mode 100644 index 0000000000..bddb62ff64 --- /dev/null +++ b/esphome/components/bl0906/bl0906.cpp @@ -0,0 +1,238 @@ +#include "bl0906.h" +#include "constants.h" + +#include "esphome/core/log.h" + +namespace esphome { +namespace bl0906 { + +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; } + +// 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) { + return (address + data->l + data->m + data->h) ^ 0xFF; +} + +void BL0906::loop() { + if (this->current_channel_ == UINT8_MAX) { + return; + } + + while (this->available()) + this->flush(); + + if (this->current_channel_ == 0) { + // Temperature + this->read_data_(BL0906_TEMPERATURE, BL0906_TREF, this->temperature_sensor_); + } else if (this->current_channel_ == 1) { + this->read_data_(BL0906_I_1_RMS, BL0906_IREF, this->current_1_sensor_); + this->read_data_(BL0906_WATT_1, BL0906_PREF, this->power_1_sensor_); + this->read_data_(BL0906_CF_1_CNT, BL0906_EREF, this->energy_1_sensor_); + } else if (this->current_channel_ == 2) { + this->read_data_(BL0906_I_2_RMS, BL0906_IREF, this->current_2_sensor_); + this->read_data_(BL0906_WATT_2, BL0906_PREF, this->power_2_sensor_); + this->read_data_(BL0906_CF_2_CNT, BL0906_EREF, this->energy_2_sensor_); + } else if (this->current_channel_ == 3) { + this->read_data_(BL0906_I_3_RMS, BL0906_IREF, this->current_3_sensor_); + this->read_data_(BL0906_WATT_3, BL0906_PREF, this->power_3_sensor_); + this->read_data_(BL0906_CF_3_CNT, BL0906_EREF, this->energy_3_sensor_); + } else if (this->current_channel_ == 4) { + this->read_data_(BL0906_I_4_RMS, BL0906_IREF, this->current_4_sensor_); + this->read_data_(BL0906_WATT_4, BL0906_PREF, this->power_4_sensor_); + this->read_data_(BL0906_CF_4_CNT, BL0906_EREF, this->energy_4_sensor_); + } else if (this->current_channel_ == 5) { + this->read_data_(BL0906_I_5_RMS, BL0906_IREF, this->current_5_sensor_); + this->read_data_(BL0906_WATT_5, BL0906_PREF, this->power_5_sensor_); + this->read_data_(BL0906_CF_5_CNT, BL0906_EREF, this->energy_5_sensor_); + } else if (this->current_channel_ == 6) { + this->read_data_(BL0906_I_6_RMS, BL0906_IREF, this->current_6_sensor_); + this->read_data_(BL0906_WATT_6, BL0906_PREF, this->power_6_sensor_); + this->read_data_(BL0906_CF_6_CNT, BL0906_EREF, this->energy_6_sensor_); + } else if (this->current_channel_ == UINT8_MAX - 2) { + // Frequency + this->read_data_(BL0906_FREQUENCY, BL0906_FREF, frequency_sensor_); + // Voltage + this->read_data_(BL0906_V_RMS, BL0906_UREF, voltage_sensor_); + } else if (this->current_channel_ == UINT8_MAX - 1) { + // Total power + this->read_data_(BL0906_WATT_SUM, BL0906_WATT, this->total_power_sensor_); + // Total Energy + this->read_data_(BL0906_CF_SUM_CNT, BL0906_CF, this->total_energy_sensor_); + } else { + this->current_channel_ = UINT8_MAX - 2; // Go to frequency and voltage + return; + } + this->current_channel_++; + this->handle_actions_(); +} + +void BL0906::setup() { + while (this->available()) + this->flush(); + this->write_array(USR_WRPROT_WITABLE, sizeof(USR_WRPROT_WITABLE)); + // Calibration (1: register address; 2: value before calibration; 3: value after calibration) + this->bias_correction_(BL0906_RMSOS_1, 0.01600, 0); // Calibration current_1 + this->bias_correction_(BL0906_RMSOS_2, 0.01500, 0); + this->bias_correction_(BL0906_RMSOS_3, 0.01400, 0); + this->bias_correction_(BL0906_RMSOS_4, 0.01300, 0); + this->bias_correction_(BL0906_RMSOS_5, 0.01200, 0); + this->bias_correction_(BL0906_RMSOS_6, 0.01200, 0); // Calibration current_6 + + this->write_array(USR_WRPROT_ONLYREAD, sizeof(USR_WRPROT_ONLYREAD)); +} + +void BL0906::update() { this->current_channel_ = 0; } + +size_t BL0906::enqueue_action_(ActionCallbackFuncPtr function) { + this->action_queue_.push_back(function); + return this->action_queue_.size(); +} + +void BL0906::handle_actions_() { + if (this->action_queue_.empty()) { + return; + } + ActionCallbackFuncPtr ptr_func = nullptr; + for (int i = 0; i < this->action_queue_.size(); i++) { + ptr_func = this->action_queue_[i]; + if (ptr_func) { + ESP_LOGI(TAG, "HandleActionCallback[%d]...", i); + (this->*ptr_func)(); + } + } + + while (this->available()) { + this->read(); + } + + this->action_queue_.clear(); +} + +// Reset energy +void BL0906::reset_energy_() { + this->write_array(BL0906_INIT[0], 6); + delay(1); + this->flush(); + + ESP_LOGW(TAG, "RMSOS:%02X%02X%02X%02X%02X%02X", BL0906_INIT[0][0], BL0906_INIT[0][1], BL0906_INIT[0][2], + BL0906_INIT[0][3], BL0906_INIT[0][4], BL0906_INIT[0][5]); +} + +// Read data +void BL0906::read_data_(const uint8_t address, const float reference, sensor::Sensor *sensor) { + if (sensor == nullptr) { + return; + } + DataPacket buffer; + ube24_t data_u24; + sbe24_t data_s24; + float value = 0; + + bool signed_result = reference == BL0906_TREF || reference == BL0906_WATT || reference == BL0906_PREF; + + 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; + } + } + // Power + if (reference == BL0906_PREF) { + value = (float) to_int32_t(data_s24) * reference; + } + + // Total power + if (reference == BL0906_WATT) { + value = (float) to_int32_t(data_s24) * reference; + } + + // Voltage, current, power, total power + if (reference == BL0906_UREF || reference == BL0906_IREF || reference == BL0906_EREF || reference == BL0906_CF) { + value = (float) to_uint32_t(data_u24) * reference; + } + + // Frequency + if (reference == BL0906_FREF) { + value = reference / (float) to_uint32_t(data_u24); + } + // Chip temperature + if (reference == BL0906_TREF) { + value = (float) to_int32_t(data_s24); + value = (value - 64) * 12.5 / 59 - 40; + } + sensor->publish_state(value); +} + +// RMS offset correction +void BL0906::bias_correction_(uint8_t address, float measurements, float correction) { + DataPacket data; + float ki = 12875 * 1 * (5.1 + 5.1) * 1000 / 2000 / 1.097; // Current coefficient + 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.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); + this->write_byte(address); + this->write_byte(data.l); + this->write_byte(data.m); + this->write_byte(data.h); + this->write_byte(data.address); +} + +void BL0906::dump_config() { + ESP_LOGCONFIG(TAG, "BL0906:"); + LOG_SENSOR(" ", "Voltage", this->voltage_sensor_); + + LOG_SENSOR(" ", "Current1", this->current_1_sensor_); + LOG_SENSOR(" ", "Current2", this->current_2_sensor_); + LOG_SENSOR(" ", "Current3", this->current_3_sensor_); + LOG_SENSOR(" ", "Current4", this->current_4_sensor_); + LOG_SENSOR(" ", "Current5", this->current_5_sensor_); + LOG_SENSOR(" ", "Current6", this->current_6_sensor_); + + LOG_SENSOR(" ", "Power1", this->power_1_sensor_); + LOG_SENSOR(" ", "Power2", this->power_2_sensor_); + LOG_SENSOR(" ", "Power3", this->power_3_sensor_); + LOG_SENSOR(" ", "Power4", this->power_4_sensor_); + LOG_SENSOR(" ", "Power5", this->power_5_sensor_); + LOG_SENSOR(" ", "Power6", this->power_6_sensor_); + + LOG_SENSOR(" ", "Energy1", this->energy_1_sensor_); + LOG_SENSOR(" ", "Energy2", this->energy_2_sensor_); + LOG_SENSOR(" ", "Energy3", this->energy_3_sensor_); + LOG_SENSOR(" ", "Energy4", this->energy_4_sensor_); + LOG_SENSOR(" ", "Energy5", this->energy_5_sensor_); + LOG_SENSOR(" ", "Energy6", this->energy_6_sensor_); + + LOG_SENSOR(" ", "Total Power", this->total_power_sensor_); + LOG_SENSOR(" ", "Total Energy", this->total_energy_sensor_); + LOG_SENSOR(" ", "Frequency", this->frequency_sensor_); + LOG_SENSOR(" ", "Temperature", this->temperature_sensor_); +} + +} // namespace bl0906 +} // namespace esphome diff --git a/esphome/components/bl0906/bl0906.h b/esphome/components/bl0906/bl0906.h new file mode 100644 index 0000000000..5a9ad0f028 --- /dev/null +++ b/esphome/components/bl0906/bl0906.h @@ -0,0 +1,96 @@ +#pragma once + +#include "esphome/components/sensor/sensor.h" +#include "esphome/components/uart/uart.h" +#include "esphome/core/automation.h" +#include "esphome/core/component.h" +#include "esphome/core/datatypes.h" + +// https://www.belling.com.cn/media/file_object/bel_product/BL0906/datasheet/BL0906_V1.02_cn.pdf +// https://www.belling.com.cn/media/file_object/bel_product/BL0906/guide/BL0906%20APP%20Note_V1.02.pdf + +namespace esphome { +namespace bl0906 { + +struct DataPacket { // NOLINT(altera-struct-pack-align) + uint8_t l{0}; + uint8_t m{0}; + uint8_t h{0}; + uint8_t checksum; // checksum + uint8_t address; +} __attribute__((packed)); + +struct ube24_t { // NOLINT(readability-identifier-naming,altera-struct-pack-align) + uint8_t l{0}; + uint8_t m{0}; + uint8_t h{0}; +} __attribute__((packed)); + +struct sbe24_t { // NOLINT(readability-identifier-naming,altera-struct-pack-align) + uint8_t l{0}; + uint8_t m{0}; + int8_t h{0}; +} __attribute__((packed)); + +template class ResetEnergyAction; + +class BL0906; + +using ActionCallbackFuncPtr = void (BL0906::*)(); + +class BL0906 : public PollingComponent, public uart::UARTDevice { + SUB_SENSOR(voltage) + SUB_SENSOR(current_1) + SUB_SENSOR(current_2) + SUB_SENSOR(current_3) + SUB_SENSOR(current_4) + SUB_SENSOR(current_5) + SUB_SENSOR(current_6) + SUB_SENSOR(power_1) + SUB_SENSOR(power_2) + SUB_SENSOR(power_3) + SUB_SENSOR(power_4) + SUB_SENSOR(power_5) + SUB_SENSOR(power_6) + SUB_SENSOR(total_power) + SUB_SENSOR(energy_1) + SUB_SENSOR(energy_2) + SUB_SENSOR(energy_3) + SUB_SENSOR(energy_4) + SUB_SENSOR(energy_5) + SUB_SENSOR(energy_6) + SUB_SENSOR(total_energy) + SUB_SENSOR(frequency) + SUB_SENSOR(temperature) + + public: + void loop() override; + + void update() override; + void setup() override; + void dump_config() override; + + protected: + template friend class ResetEnergyAction; + + void reset_energy_(); + + void read_data_(uint8_t address, float reference, sensor::Sensor *sensor); + + void bias_correction_(uint8_t address, float measurements, float correction); + + uint8_t current_channel_{0}; + size_t enqueue_action_(ActionCallbackFuncPtr function); + void handle_actions_(); + + private: + std::vector action_queue_{}; +}; + +template class ResetEnergyAction : public Action, public Parented { + public: + void play(Ts... x) override { this->parent_->enqueue_action_(&BL0906::reset_energy_); } +}; + +} // namespace bl0906 +} // namespace esphome diff --git a/esphome/components/bl0906/const.py b/esphome/components/bl0906/const.py new file mode 100644 index 0000000000..67f21d35b0 --- /dev/null +++ b/esphome/components/bl0906/const.py @@ -0,0 +1,4 @@ +# const.py +ICON_ENERGY = "mdi:lightning-bolt" +ICON_FREQUENCY = "mdi:cosine-wave" +ICON_VOLTAGE = "mdi:sine-wave" diff --git a/esphome/components/bl0906/constants.h b/esphome/components/bl0906/constants.h new file mode 100644 index 0000000000..546916aa3c --- /dev/null +++ b/esphome/components/bl0906/constants.h @@ -0,0 +1,122 @@ +#pragma once +#include + +namespace esphome { +namespace bl0906 { + +// Total power conversion +static const float BL0906_WATT = 16 * 1.097 * 1.097 * (20000 + 20000 + 20000 + 20000 + 20000) / + (40.41259 * ((5.1 + 5.1) * 1000 / 2000) * 1 * 100 * 1 * 1000); +// Total Energy conversion +static const float BL0906_CF = 16 * 4194304 * 0.032768 * 16 / + (3600000 * 16 * + (40.4125 * ((5.1 + 5.1) * 1000 / 2000) * 1 * 100 * 1 * 1000 / + (1.097 * 1.097 * (20000 + 20000 + 20000 + 20000 + 20000)))); +// Frequency conversion +static const float BL0906_FREF = 10000000; +// Temperature conversion +static const float BL0906_TREF = 12.5 / 59 - 40; +// Current conversion +static const float BL0906_IREF = 1.097 / (12875 * 1 * (5.1 + 5.1) * 1000 / 2000); +// Voltage conversion +static const float BL0906_UREF = 1.097 * (20000 + 20000 + 20000 + 20000 + 20000) / (13162 * 1 * 100 * 1000); +// Power conversion +static const float BL0906_PREF = 1.097 * 1.097 * (20000 + 20000 + 20000 + 20000 + 20000) / + (40.41259 * ((5.1 + 5.1) * 1000 / 2000) * 1 * 100 * 1 * 1000); +// Energy conversion +static const float BL0906_EREF = 4194304 * 0.032768 * 16 / + (3600000 * 16 * + (40.4125 * ((5.1 + 5.1) * 1000 / 2000) * 1 * 100 * 1 * 1000 / + (1.097 * 1.097 * (20000 + 20000 + 20000 + 20000 + 20000)))); +// Current coefficient +static const float BL0906_KI = 12875 * 1 * (5.1 + 5.1) * 1000 / 2000 / 1.097; +// Power coefficient +static const float BL0906_KP = 40.4125 * ((5.1 + 5.1) * 1000 / 2000) * 1 * 100 * 1 * 1000 / 1.097 / 1.097 / + (20000 + 20000 + 20000 + 20000 + 20000); + +static const uint8_t USR_WRPROT_WITABLE[6] = {0xCA, 0x9E, 0x55, 0x55, 0x00, 0xB7}; +static const uint8_t USR_WRPROT_ONLYREAD[6] = {0xCA, 0x9E, 0x00, 0x00, 0x00, 0x61}; + +static const uint8_t BL0906_READ_COMMAND = 0x35; +static const uint8_t BL0906_WRITE_COMMAND = 0xCA; + +// Register address +// Voltage +static const uint8_t BL0906_V_RMS = 0x16; + +// Total power +static const uint8_t BL0906_WATT_SUM = 0X2C; + +// Current1~6 +static const uint8_t BL0906_I_1_RMS = 0x0D; // current_1 +static const uint8_t BL0906_I_2_RMS = 0x0E; +static const uint8_t BL0906_I_3_RMS = 0x0F; +static const uint8_t BL0906_I_4_RMS = 0x10; +static const uint8_t BL0906_I_5_RMS = 0x13; +static const uint8_t BL0906_I_6_RMS = 0x14; // current_6 + +// Power1~6 +static const uint8_t BL0906_WATT_1 = 0X23; // power_1 +static const uint8_t BL0906_WATT_2 = 0X24; +static const uint8_t BL0906_WATT_3 = 0X25; +static const uint8_t BL0906_WATT_4 = 0X26; +static const uint8_t BL0906_WATT_5 = 0X29; +static const uint8_t BL0906_WATT_6 = 0X2A; // power_6 + +// Active pulse count, unsigned +static const uint8_t BL0906_CF_1_CNT = 0X30; // Channel_1 +static const uint8_t BL0906_CF_2_CNT = 0X31; +static const uint8_t BL0906_CF_3_CNT = 0X32; +static const uint8_t BL0906_CF_4_CNT = 0X33; +static const uint8_t BL0906_CF_5_CNT = 0X36; +static const uint8_t BL0906_CF_6_CNT = 0X37; // Channel_6 + +// Total active pulse count, unsigned +static const uint8_t BL0906_CF_SUM_CNT = 0X39; + +// Voltage frequency cycle +static const uint8_t BL0906_FREQUENCY = 0X4E; + +// Internal temperature +static const uint8_t BL0906_TEMPERATURE = 0X5E; + +// Calibration register +// RMS gain adjustment register +static const uint8_t BL0906_RMSGN_1 = 0x6D; // Channel_1 +static const uint8_t BL0906_RMSGN_2 = 0x6E; +static const uint8_t BL0906_RMSGN_3 = 0x6F; +static const uint8_t BL0906_RMSGN_4 = 0x70; +static const uint8_t BL0906_RMSGN_5 = 0x73; +static const uint8_t BL0906_RMSGN_6 = 0x74; // Channel_6 + +// RMS offset correction register +static const uint8_t BL0906_RMSOS_1 = 0x78; // Channel_1 +static const uint8_t BL0906_RMSOS_2 = 0x79; +static const uint8_t BL0906_RMSOS_3 = 0x7A; +static const uint8_t BL0906_RMSOS_4 = 0x7B; +static const uint8_t BL0906_RMSOS_5 = 0x7E; +static const uint8_t BL0906_RMSOS_6 = 0x7F; // Channel_6 + +// Active power gain adjustment register +static const uint8_t BL0906_WATTGN_1 = 0xB7; // Channel_1 +static const uint8_t BL0906_WATTGN_2 = 0xB8; +static const uint8_t BL0906_WATTGN_3 = 0xB9; +static const uint8_t BL0906_WATTGN_4 = 0xBA; +static const uint8_t BL0906_WATTGN_5 = 0xBD; +static const uint8_t BL0906_WATTGN_6 = 0xBE; // Channel_6 + +// User write protection setting register, +// You must first write 0x5555 to the write protection setting register before writing to other registers. +static const uint8_t BL0906_USR_WRPROT = 0x9E; + +// Reset Register +static const uint8_t BL0906_SOFT_RESET = 0x9F; + +const uint8_t BL0906_INIT[2][6] = { + // Reset to default + {BL0906_WRITE_COMMAND, BL0906_SOFT_RESET, 0x5A, 0x5A, 0x5A, 0x52}, + // Enable User Operation Write + {BL0906_WRITE_COMMAND, BL0906_USR_WRPROT, 0x55, 0x55, 0x00, 0xB7}}; + +} // namespace bl0906 +} // namespace esphome diff --git a/esphome/components/bl0906/sensor.py b/esphome/components/bl0906/sensor.py new file mode 100644 index 0000000000..bc370c9252 --- /dev/null +++ b/esphome/components/bl0906/sensor.py @@ -0,0 +1,184 @@ +from esphome import automation +from esphome.automation import maybe_simple_id +import esphome.codegen as cg +from esphome.components import sensor, uart +import esphome.config_validation as cv +from esphome.const import ( + CONF_CHANNEL, + CONF_CURRENT, + CONF_ENERGY, + CONF_FREQUENCY, + CONF_ID, + CONF_NAME, + CONF_POWER, + CONF_TEMPERATURE, + CONF_TOTAL_POWER, + CONF_VOLTAGE, + DEVICE_CLASS_CURRENT, + DEVICE_CLASS_ENERGY, + DEVICE_CLASS_FREQUENCY, + DEVICE_CLASS_POWER, + DEVICE_CLASS_TEMPERATURE, + DEVICE_CLASS_VOLTAGE, + ICON_CURRENT_AC, + ICON_POWER, + ICON_THERMOMETER, + STATE_CLASS_MEASUREMENT, + STATE_CLASS_TOTAL_INCREASING, + UNIT_AMPERE, + UNIT_CELSIUS, + UNIT_HERTZ, + UNIT_KILOWATT_HOURS, + UNIT_VOLT, + UNIT_WATT, +) + +# Import ICONS not included in esphome's const.py, from the local components const.py +from .const import ICON_ENERGY, ICON_FREQUENCY, ICON_VOLTAGE + +DEPENDENCIES = ["uart"] +AUTO_LOAD = ["bl0906"] +CONF_TOTAL_ENERGY = "total_energy" + +bl0906_ns = cg.esphome_ns.namespace("bl0906") +BL0906 = bl0906_ns.class_("BL0906", cg.PollingComponent, uart.UARTDevice) +ResetEnergyAction = bl0906_ns.class_("ResetEnergyAction", automation.Action) + +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(BL0906), + cv.Optional(CONF_FREQUENCY): sensor.sensor_schema( + icon=ICON_FREQUENCY, + accuracy_decimals=0, + device_class=DEVICE_CLASS_FREQUENCY, + unit_of_measurement=UNIT_HERTZ, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema( + icon=ICON_THERMOMETER, + accuracy_decimals=0, + device_class=DEVICE_CLASS_TEMPERATURE, + unit_of_measurement=UNIT_CELSIUS, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_VOLTAGE): sensor.sensor_schema( + icon=ICON_VOLTAGE, + accuracy_decimals=1, + device_class=DEVICE_CLASS_VOLTAGE, + unit_of_measurement=UNIT_VOLT, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_TOTAL_POWER): sensor.sensor_schema( + icon=ICON_POWER, + accuracy_decimals=3, + device_class=DEVICE_CLASS_POWER, + unit_of_measurement=UNIT_WATT, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_TOTAL_ENERGY): sensor.sensor_schema( + icon=ICON_ENERGY, + accuracy_decimals=3, + device_class=DEVICE_CLASS_ENERGY, + state_class=STATE_CLASS_TOTAL_INCREASING, + unit_of_measurement=UNIT_KILOWATT_HOURS, + ), + } + ) + .extend( + cv.Schema( + { + cv.Optional(f"{CONF_CHANNEL}_{i + 1}"): cv.Schema( + { + cv.Optional(CONF_CURRENT): cv.maybe_simple_value( + sensor.sensor_schema( + icon=ICON_CURRENT_AC, + accuracy_decimals=3, + device_class=DEVICE_CLASS_CURRENT, + unit_of_measurement=UNIT_AMPERE, + state_class=STATE_CLASS_MEASUREMENT, + ), + key=CONF_NAME, + ), + cv.Optional(CONF_POWER): cv.maybe_simple_value( + sensor.sensor_schema( + icon=ICON_POWER, + accuracy_decimals=0, + device_class=DEVICE_CLASS_POWER, + unit_of_measurement=UNIT_WATT, + state_class=STATE_CLASS_MEASUREMENT, + ), + key=CONF_NAME, + ), + cv.Optional(CONF_ENERGY): cv.maybe_simple_value( + sensor.sensor_schema( + icon=ICON_ENERGY, + accuracy_decimals=3, + device_class=DEVICE_CLASS_ENERGY, + unit_of_measurement=UNIT_KILOWATT_HOURS, + state_class=STATE_CLASS_TOTAL_INCREASING, + ), + key=CONF_NAME, + ), + } + ) + for i in range(6) + } + ) + ) + .extend(uart.UART_DEVICE_SCHEMA) + .extend(cv.polling_component_schema("60s")) +) + +FINAL_VALIDATE_SCHEMA = uart.final_validate_device_schema( + "bl0906", baud_rate=19200, require_tx=True, require_rx=True +) + + +@automation.register_action( + "bl0906.reset_energy", + ResetEnergyAction, + maybe_simple_id( + { + cv.Required(CONF_ID): cv.use_id(BL0906), + } + ), +) +async def reset_energy_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) + + +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) + if frequency_config := config.get(CONF_FREQUENCY): + sens = await sensor.new_sensor(frequency_config) + cg.add(var.set_frequency_sensor(sens)) + if temperature_config := config.get(CONF_TEMPERATURE): + sens = await sensor.new_sensor(temperature_config) + cg.add(var.set_temperature_sensor(sens)) + if voltage_config := config.get(CONF_VOLTAGE): + sens = await sensor.new_sensor(voltage_config) + cg.add(var.set_voltage_sensor(sens)) + + for i in range(6): + if channel_config := config.get(f"{CONF_CHANNEL}_{i + 1}"): + if current_config := channel_config.get(CONF_CURRENT): + sens = await sensor.new_sensor(current_config) + cg.add(getattr(var, f"set_current_{i + 1}_sensor")(sens)) + if power_config := channel_config.get(CONF_POWER): + sens = await sensor.new_sensor(power_config) + cg.add(getattr(var, f"set_power_{i + 1}_sensor")(sens)) + if energy_config := channel_config.get(CONF_ENERGY): + sens = await sensor.new_sensor(energy_config) + cg.add(getattr(var, f"set_energy_{i + 1}_sensor")(sens)) + + if total_power_config := config.get(CONF_TOTAL_POWER): + sens = await sensor.new_sensor(total_power_config) + cg.add(var.set_total_power_sensor(sens)) + + if total_energy_config := config.get(CONF_TOTAL_ENERGY): + sens = await sensor.new_sensor(total_energy_config) + cg.add(var.set_total_energy_sensor(sens)) diff --git a/tests/components/bl0906/common.yaml b/tests/components/bl0906/common.yaml new file mode 100644 index 0000000000..944791369c --- /dev/null +++ b/tests/components/bl0906/common.yaml @@ -0,0 +1,62 @@ +uart: + - id: uart_bl0906 + tx_pin: + number: ${tx_pin} + rx_pin: + number: ${rx_pin} + baud_rate: 19200 + +sensor: + - platform: bl0906 + frequency: + name: 'Frequency' + temperature: + name: 'Temperature' + voltage: + name: 'Voltage' + channel_1: + current: + name: 'Current_1' + power: + name: 'Power_1' + energy: + name: 'Energy_1' + channel_2: + current: + name: 'Current_2' + power: + name: 'Power_2' + energy: + name: 'Energy_2' + channel_3: + current: + name: 'Current_3' + power: + name: 'Power_3' + energy: + name: 'Energy_3' + channel_4: + current: + name: 'Current_4' + power: + name: 'Power_4' + energy: + name: 'Energy_4' + channel_5: + current: + name: 'Current_5' + power: + name: 'Power_5' + energy: + name: 'Energy_5' + channel_6: + current: + name: 'Current_6' + power: + name: 'Power_6' + energy: + name: 'Energy_6' + total_energy: + name: 'Total_Energy' + total_power: + name: 'Total_Power' diff --git a/tests/components/bl0906/test.esp32-ard.yaml b/tests/components/bl0906/test.esp32-ard.yaml new file mode 100644 index 0000000000..811f6b72a6 --- /dev/null +++ b/tests/components/bl0906/test.esp32-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + tx_pin: GPIO12 + rx_pin: GPIO14 + +<<: !include common.yaml diff --git a/tests/components/bl0906/test.esp32-c3-ard.yaml b/tests/components/bl0906/test.esp32-c3-ard.yaml new file mode 100644 index 0000000000..c79d14c740 --- /dev/null +++ b/tests/components/bl0906/test.esp32-c3-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + tx_pin: GPIO7 + rx_pin: GPIO8 + +<<: !include common.yaml diff --git a/tests/components/bl0906/test.esp32-c3-idf.yaml b/tests/components/bl0906/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..c79d14c740 --- /dev/null +++ b/tests/components/bl0906/test.esp32-c3-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + tx_pin: GPIO7 + rx_pin: GPIO8 + +<<: !include common.yaml diff --git a/tests/components/bl0906/test.esp32-idf.yaml b/tests/components/bl0906/test.esp32-idf.yaml new file mode 100644 index 0000000000..811f6b72a6 --- /dev/null +++ b/tests/components/bl0906/test.esp32-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + tx_pin: GPIO12 + rx_pin: GPIO14 + +<<: !include common.yaml diff --git a/tests/components/bl0906/test.esp8266-ard.yaml b/tests/components/bl0906/test.esp8266-ard.yaml new file mode 100644 index 0000000000..3b44f9c9c3 --- /dev/null +++ b/tests/components/bl0906/test.esp8266-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + tx_pin: GPIO1 + rx_pin: GPIO3 + +<<: !include common.yaml diff --git a/tests/components/bl0906/test.rp2040-ard.yaml b/tests/components/bl0906/test.rp2040-ard.yaml new file mode 100644 index 0000000000..b516342f3b --- /dev/null +++ b/tests/components/bl0906/test.rp2040-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + tx_pin: GPIO4 + rx_pin: GPIO5 + +<<: !include common.yaml From 1922f2bbee79ba1c4830ec286ef7032cd8b7d613 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Thu, 29 Aug 2024 10:55:37 +1000 Subject: [PATCH 2006/2101] [platformio] Add environments for ESP-IDF 5.3 for development (#7371) --- platformio.ini | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/platformio.ini b/platformio.ini index 4a0a3f2ef4..147159a841 100644 --- a/platformio.ini +++ b/platformio.ini @@ -153,6 +153,13 @@ build_flags = -DUSE_ESP32_FRAMEWORK_ESP_IDF extra_scripts = post:esphome/components/esp32/post_build.py.script +; This are common settings for the ESP32 using the latest ESP-IDF version. +[common:esp32-idf-5_3] +extends = common:esp32-idf +platform = platformio/espressif32@6.8.0 +platform_packages = + platformio/framework-espidf@~3.50300.0 + ; These are common settings for the RP2040 using Arduino. [common:rp2040-arduino] extends = common:arduino @@ -229,6 +236,15 @@ build_flags = ${flags:runtime.build_flags} -DUSE_ESP32_VARIANT_ESP32 +[env:esp32-idf-5_3] +extends = common:esp32-idf-5_3 +board = esp32dev +board_build.esp-idf.sdkconfig_path = .temp/sdkconfig-esp32-idf +build_flags = + ${common:esp32-idf.build_flags} + ${flags:runtime.build_flags} + -DUSE_ESP32_VARIANT_ESP32 + [env:esp32-idf-tidy] extends = common:esp32-idf board = esp32dev @@ -265,6 +281,15 @@ build_flags = ${flags:runtime.build_flags} -DUSE_ESP32_VARIANT_ESP32C3 +[env:esp32c3-idf-5_3] +extends = common:esp32-idf-5_3 +board = esp32-c3-devkitm-1 +board_build.esp-idf.sdkconfig_path = .temp/sdkconfig-esp32c3-idf +build_flags = + ${common:esp32-idf.build_flags} + ${flags:runtime.build_flags} + -DUSE_ESP32_VARIANT_ESP32C3 + [env:esp32c3-idf-tidy] extends = common:esp32-idf board = esp32-c3-devkitm-1 @@ -301,6 +326,15 @@ build_flags = ${flags:runtime.build_flags} -DUSE_ESP32_VARIANT_ESP32S2 +[env:esp32s2-idf-5_3] +extends = common:esp32-idf-5_3 +board = esp32-s2-kaluga-1 +board_build.esp-idf.sdkconfig_path = .temp/sdkconfig-esp32s2-idf +build_flags = + ${common:esp32-idf.build_flags} + ${flags:runtime.build_flags} + -DUSE_ESP32_VARIANT_ESP32S2 + [env:esp32s2-idf-tidy] extends = common:esp32-idf board = esp32-s2-kaluga-1 @@ -337,6 +371,15 @@ build_flags = ${flags:runtime.build_flags} -DUSE_ESP32_VARIANT_ESP32S3 +[env:esp32s3-idf-5_3] +extends = common:esp32-idf-5_3 +board = esp32-s3-devkitc-1 +board_build.esp-idf.sdkconfig_path = .temp/sdkconfig-esp32s3-idf +build_flags = + ${common:esp32-idf.build_flags} + ${flags:runtime.build_flags} + -DUSE_ESP32_VARIANT_ESP32S3 + [env:esp32s3-idf-tidy] extends = common:esp32-idf board = esp32-s3-devkitc-1 From f28418d0b472e9c641cb4ebcda206f65916fa3bc Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Thu, 29 Aug 2024 11:34:41 +1000 Subject: [PATCH 2007/2101] [lvgl] Bug fixes (#7370) --- esphome/components/lvgl/__init__.py | 2 ++ esphome/components/lvgl/lv_validation.py | 15 +++++---------- esphome/components/lvgl/schemas.py | 8 +++++++- .../components/lvgl/widgets/buttonmatrix.py | 6 +++++- esphome/components/lvgl/widgets/checkbox.py | 11 ++++++++--- esphome/components/lvgl/widgets/tileview.py | 10 ++-------- tests/components/lvgl/lvgl-package.yaml | 18 ++++++++++++++++-- 7 files changed, 45 insertions(+), 25 deletions(-) diff --git a/esphome/components/lvgl/__init__.py b/esphome/components/lvgl/__init__.py index cab6462d1a..a4ca9d56f3 100644 --- a/esphome/components/lvgl/__init__.py +++ b/esphome/components/lvgl/__init__.py @@ -327,6 +327,8 @@ CONFIG_SCHEMA = ( { cv.Optional(df.CONF_GRID_CELL_X_ALIGN): grid_alignments, cv.Optional(df.CONF_GRID_CELL_Y_ALIGN): grid_alignments, + cv.Optional(df.CONF_PAD_ROW): lvalid.pixels, + cv.Optional(df.CONF_PAD_COLUMN): lvalid.pixels, } ) ), diff --git a/esphome/components/lvgl/lv_validation.py b/esphome/components/lvgl/lv_validation.py index a2be4a2abe..d8af9f7aa9 100644 --- a/esphome/components/lvgl/lv_validation.py +++ b/esphome/components/lvgl/lv_validation.py @@ -52,9 +52,7 @@ opacity = LValidator(opacity_validator, uint32, retmapper=literal) def color(value): if value == SCHEMA_EXTRACT: return ["hex color value", "color ID"] - if isinstance(value, int): - return value - return cv.use_id(ColorStruct)(value) + return cv.Any(cv.int_, cv.use_id(ColorStruct))(value) def color_retmapper(value): @@ -82,10 +80,10 @@ def pixels_or_percent_validator(value): """A length in one axis - either a number (pixels) or a percentage""" if value == SCHEMA_EXTRACT: return ["pixels", "..%"] + value = cv.Any(cv.int_, cv.percentage)(value) if isinstance(value, int): - return cv.int_(value) - # Will throw an exception if not a percentage. - return f"lv_pct({int(cv.percentage(value) * 100)})" + return value + return f"lv_pct({int(value * 100)})" pixels_or_percent = LValidator(pixels_or_percent_validator, uint32, retmapper=literal) @@ -116,10 +114,7 @@ def size_validator(value): if value.upper() == "SIZE_CONTENT": return "LV_SIZE_CONTENT" raise cv.Invalid("must be 'size_content', a percentage or an integer (pixels)") - if isinstance(value, int): - return cv.int_(value) - # Will throw an exception if not a percentage. - return f"lv_pct({int(cv.percentage(value) * 100)})" + return pixels_or_percent_validator(value) size = LValidator(size_validator, uint32, retmapper=literal) diff --git a/esphome/components/lvgl/schemas.py b/esphome/components/lvgl/schemas.py index 548ebda6dc..9ff0fec5bc 100644 --- a/esphome/components/lvgl/schemas.py +++ b/esphome/components/lvgl/schemas.py @@ -359,7 +359,13 @@ LVGL_SCHEMA = cv.Schema( } ) -ALL_STYLES = {**STYLE_PROPS, **GRID_CELL_SCHEMA, **FLEX_OBJ_SCHEMA} +ALL_STYLES = { + **STYLE_PROPS, + **GRID_CELL_SCHEMA, + **FLEX_OBJ_SCHEMA, + cv.Optional(df.CONF_PAD_ROW): lvalid.pixels, + cv.Optional(df.CONF_PAD_COLUMN): lvalid.pixels, +} def container_validator(schema, widget_type: WidgetType): diff --git a/esphome/components/lvgl/widgets/buttonmatrix.py b/esphome/components/lvgl/widgets/buttonmatrix.py index e61c5e3477..c65bb4b354 100644 --- a/esphome/components/lvgl/widgets/buttonmatrix.py +++ b/esphome/components/lvgl/widgets/buttonmatrix.py @@ -13,11 +13,13 @@ from ..defines import ( CONF_KEY_CODE, CONF_MAIN, CONF_ONE_CHECKED, + CONF_PAD_COLUMN, + CONF_PAD_ROW, CONF_ROWS, CONF_SELECTED, ) from ..helpers import lvgl_components_required -from ..lv_validation import key_code, lv_bool +from ..lv_validation import key_code, lv_bool, pixels from ..lvcode import lv, lv_add, lv_expr from ..schemas import automation_schema from ..types import ( @@ -57,6 +59,8 @@ BUTTONMATRIX_BUTTON_SCHEMA = cv.Schema( BUTTONMATRIX_SCHEMA = cv.Schema( { cv.Optional(CONF_ONE_CHECKED, default=False): lv_bool, + cv.Optional(CONF_PAD_ROW): pixels, + cv.Optional(CONF_PAD_COLUMN): pixels, cv.GenerateID(CONF_BUTTON_TEXT_LIST_ID): cv.declare_id(char_ptr), cv.Required(CONF_ROWS): cv.ensure_list( cv.Schema( diff --git a/esphome/components/lvgl/widgets/checkbox.py b/esphome/components/lvgl/widgets/checkbox.py index 79c60a8669..75f4142eb1 100644 --- a/esphome/components/lvgl/widgets/checkbox.py +++ b/esphome/components/lvgl/widgets/checkbox.py @@ -1,7 +1,8 @@ +from esphome.config_validation import Optional from esphome.const import CONF_TEXT -from ..defines import CONF_INDICATOR, CONF_MAIN -from ..lv_validation import lv_text +from ..defines import CONF_INDICATOR, CONF_MAIN, CONF_PAD_COLUMN +from ..lv_validation import lv_text, pixels from ..lvcode import lv from ..schemas import TEXT_SCHEMA from ..types import LvBoolean @@ -16,7 +17,11 @@ class CheckboxType(WidgetType): CONF_CHECKBOX, LvBoolean("lv_checkbox_t"), (CONF_MAIN, CONF_INDICATOR), - TEXT_SCHEMA, + TEXT_SCHEMA.extend( + { + Optional(CONF_PAD_COLUMN): pixels, + } + ), ) async def to_code(self, w: Widget, config): diff --git a/esphome/components/lvgl/widgets/tileview.py b/esphome/components/lvgl/widgets/tileview.py index 9a426c7daf..05259fbd3c 100644 --- a/esphome/components/lvgl/widgets/tileview.py +++ b/esphome/components/lvgl/widgets/tileview.py @@ -1,7 +1,7 @@ from esphome import automation import esphome.codegen as cg import esphome.config_validation as cv -from esphome.const import CONF_ID, CONF_ON_VALUE, CONF_ROW, CONF_TRIGGER_ID +from esphome.const import CONF_ID, CONF_ROW from ..automation import action_to_code from ..defines import ( @@ -29,6 +29,7 @@ lv_tileview_t = LvType( "lv_tileview_t", largs=[(lv_obj_t_ptr, "tile")], lvalue=lambda w: w.get_property("tile_act"), + has_on_value=True, ) tile_spec = WidgetType("lv_tileview_tile_t", lv_tile_t, (CONF_MAIN,), {}) @@ -46,13 +47,6 @@ TILEVIEW_SCHEMA = cv.Schema( }, ) ), - cv.Optional(CONF_ON_VALUE): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - automation.Trigger.template(lv_obj_t_ptr) - ) - } - ), } ) diff --git a/tests/components/lvgl/lvgl-package.yaml b/tests/components/lvgl/lvgl-package.yaml index 737d8703b0..0feb6d6ce6 100644 --- a/tests/components/lvgl/lvgl-package.yaml +++ b/tests/components/lvgl/lvgl-package.yaml @@ -337,11 +337,25 @@ lvgl: - tileview: id: tileview_id scrollbar_mode: active + on_value: + then: + - if: + condition: + lambda: return tile == id(tile_1); + then: + - logger.log: "tile 1 is now showing" tiles: - - id: page_1 + - id: tile_1 row: 0 column: 0 - dir: HOR + dir: ALL + widgets: + - obj: + bg_color: 0x000000 + - id: tile_2 + row: 1 + column: 0 + dir: [VER, HOR] widgets: - obj: bg_color: 0x000000 From c09df3c05d4012da3b815ddccc5149a714094274 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Fri, 30 Aug 2024 06:16:16 +1000 Subject: [PATCH 2008/2101] [bytebuffer] Use existing bit_cast operations. (#7374) --- esphome/core/bytebuffer.cpp | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/esphome/core/bytebuffer.cpp b/esphome/core/bytebuffer.cpp index 65525ecfcf..9dd32bf87a 100644 --- a/esphome/core/bytebuffer.cpp +++ b/esphome/core/bytebuffer.cpp @@ -1,6 +1,9 @@ #include "bytebuffer.h" #include -#include +#include "esphome/core/helpers.h" + +#include +#include namespace esphome { @@ -110,18 +113,13 @@ uint32_t ByteBuffer::get_int24() { } float ByteBuffer::get_float() { assert(this->get_remaining() >= sizeof(float)); - auto ui_value = this->get_uint32(); - float value; - memcpy(&value, &ui_value, sizeof(float)); - return value; + return bit_cast(this->get_uint32()); } double ByteBuffer::get_double() { assert(this->get_remaining() >= sizeof(double)); - auto ui_value = this->get_uint64(); - double value; - memcpy(&value, &ui_value, sizeof(double)); - return value; + return bit_cast(this->get_uint64()); } + std::vector ByteBuffer::get_vector(size_t length) { assert(this->get_remaining() >= length); auto start = this->data_.begin() + this->position_; @@ -154,16 +152,12 @@ void ByteBuffer::put_uint(uint64_t value, size_t length) { void ByteBuffer::put_float(float value) { static_assert(sizeof(float) == sizeof(uint32_t), "Float sizes other than 32 bit not supported"); assert(this->get_remaining() >= sizeof(float)); - uint32_t ui_value; - memcpy(&ui_value, &value, sizeof(float)); // this work-around required to silence compiler warnings - this->put_uint32(ui_value); + this->put_uint32(bit_cast(value)); } void ByteBuffer::put_double(double value) { static_assert(sizeof(double) == sizeof(uint64_t), "Double sizes other than 64 bit not supported"); assert(this->get_remaining() >= sizeof(double)); - uint64_t ui_value; - memcpy(&ui_value, &value, sizeof(double)); - this->put_uint64(ui_value); + this->put_uint64(bit_cast(value)); } void ByteBuffer::put_vector(const std::vector &value) { assert(this->get_remaining() >= value.size()); From bb6693a2552f94b1b375a4e5d195e51e27523751 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 30 Aug 2024 08:17:28 +1200 Subject: [PATCH 2009/2101] Bump actions/setup-python from 5.1.0 to 5.2.0 (#7375) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-api-proto.yml | 2 +- .github/workflows/ci-docker.yml | 2 +- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 4 ++-- .github/workflows/sync-device-classes.yml | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-api-proto.yml b/.github/workflows/ci-api-proto.yml index ee08a0246d..8112c4e0ff 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@v4.1.7 - name: Set up Python - uses: actions/setup-python@v5.1.0 + uses: actions/setup-python@v5.2.0 with: python-version: "3.11" diff --git a/.github/workflows/ci-docker.yml b/.github/workflows/ci-docker.yml index 91c02b0a17..891367d16a 100644 --- a/.github/workflows/ci-docker.yml +++ b/.github/workflows/ci-docker.yml @@ -42,7 +42,7 @@ jobs: steps: - uses: actions/checkout@v4.1.7 - name: Set up Python - uses: actions/setup-python@v5.1.0 + uses: actions/setup-python@v5.2.0 with: python-version: "3.9" - name: Set up Docker Buildx diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2437dd5b8d..7c4fa65695 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,7 +41,7 @@ jobs: run: echo key="${{ hashFiles('requirements.txt', 'requirements_optional.txt', 'requirements_test.txt') }}" >> $GITHUB_OUTPUT - name: Set up Python ${{ env.DEFAULT_PYTHON }} id: python - uses: actions/setup-python@v5.1.0 + uses: actions/setup-python@v5.2.0 with: python-version: ${{ env.DEFAULT_PYTHON }} - name: Restore Python virtual environment diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d454076c84..937c7aac90 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -53,7 +53,7 @@ jobs: steps: - uses: actions/checkout@v4.1.7 - name: Set up Python - uses: actions/setup-python@v5.1.0 + uses: actions/setup-python@v5.2.0 with: python-version: "3.x" - name: Set up python environment @@ -85,7 +85,7 @@ jobs: steps: - uses: actions/checkout@v4.1.7 - name: Set up Python - uses: actions/setup-python@v5.1.0 + uses: actions/setup-python@v5.2.0 with: python-version: "3.9" diff --git a/.github/workflows/sync-device-classes.yml b/.github/workflows/sync-device-classes.yml index 89a3627c64..7677425236 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@v5.1.0 + uses: actions/setup-python@v5.2.0 with: python-version: 3.12 From acb00c9c59bd79847fdab7602e06486511bd6dc3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 30 Aug 2024 08:17:34 +1200 Subject: [PATCH 2010/2101] Bump actions/setup-python from 5.1.1 to 5.2.0 in /.github/actions/restore-python (#7376) 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 d3fe2a89dc..c618a5ca97 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@v5.1.1 + uses: actions/setup-python@v5.2.0 with: python-version: ${{ inputs.python-version }} - name: Restore Python virtual environment From 725e50348b240c00c2c287d09d9ba8dec138561d Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Fri, 30 Aug 2024 06:20:12 +1000 Subject: [PATCH 2011/2101] [gt911] Add reset pin config (#7373) --- .../components/gt911/touchscreen/__init__.py | 12 +++++---- .../gt911/touchscreen/gt911_touchscreen.cpp | 17 +++++++++++++ .../gt911/touchscreen/gt911_touchscreen.h | 2 ++ tests/components/gt911/common.yaml | 25 +++++++++++++++++++ tests/components/gt911/test.esp32-ard.yaml | 25 +------------------ tests/components/gt911/test.esp32-c3-ard.yaml | 25 +------------------ tests/components/gt911/test.esp32-c3-idf.yaml | 25 +------------------ tests/components/gt911/test.esp32-idf.yaml | 25 +------------------ tests/components/gt911/test.rp2040-ard.yaml | 25 +------------------ 9 files changed, 56 insertions(+), 125 deletions(-) create mode 100644 tests/components/gt911/common.yaml diff --git a/esphome/components/gt911/touchscreen/__init__.py b/esphome/components/gt911/touchscreen/__init__.py index 9a0d5cc169..6c80ff280f 100644 --- a/esphome/components/gt911/touchscreen/__init__.py +++ b/esphome/components/gt911/touchscreen/__init__.py @@ -1,11 +1,10 @@ -import esphome.codegen as cg -import esphome.config_validation as cv - from esphome import pins +import esphome.codegen as cg from esphome.components import i2c, touchscreen -from esphome.const import CONF_INTERRUPT_PIN, CONF_ID -from .. import gt911_ns +import esphome.config_validation as cv +from esphome.const import CONF_ID, CONF_INTERRUPT_PIN, CONF_RESET_PIN +from .. import gt911_ns GT911ButtonListener = gt911_ns.class_("GT911ButtonListener") GT911Touchscreen = gt911_ns.class_( @@ -18,6 +17,7 @@ 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_RESET_PIN): pins.gpio_output_pin_schema, } ).extend(i2c.i2c_device_schema(0x5D)) @@ -29,3 +29,5 @@ async def to_code(config): if interrupt_pin := config.get(CONF_INTERRUPT_PIN): cg.add(var.set_interrupt_pin(await cg.gpio_pin_expression(interrupt_pin))) + if reset_pin := config.get(CONF_RESET_PIN): + cg.add(var.set_reset_pin(await cg.gpio_pin_expression(reset_pin))) diff --git a/esphome/components/gt911/touchscreen/gt911_touchscreen.cpp b/esphome/components/gt911/touchscreen/gt911_touchscreen.cpp index 99dba66c22..84811b818f 100644 --- a/esphome/components/gt911/touchscreen/gt911_touchscreen.cpp +++ b/esphome/components/gt911/touchscreen/gt911_touchscreen.cpp @@ -26,6 +26,23 @@ static const size_t MAX_BUTTONS = 4; // max number of buttons scanned void GT911Touchscreen::setup() { i2c::ErrorCode err; ESP_LOGCONFIG(TAG, "Setting up GT911 Touchscreen..."); + if (this->reset_pin_ != nullptr) { + this->reset_pin_->setup(); + this->reset_pin_->digital_write(false); + if (this->interrupt_pin_ != nullptr) { + // The interrupt pin is used as an input during reset to select the I2C address. + this->interrupt_pin_->pin_mode(gpio::FLAG_OUTPUT); + this->interrupt_pin_->setup(); + this->interrupt_pin_->digital_write(false); + } + delay(2); + this->reset_pin_->digital_write(true); + delay(50); // NOLINT + if (this->interrupt_pin_ != nullptr) { + this->interrupt_pin_->pin_mode(gpio::FLAG_INPUT); + this->interrupt_pin_->setup(); + } + } // check the configuration of the int line. uint8_t data[4]; diff --git a/esphome/components/gt911/touchscreen/gt911_touchscreen.h b/esphome/components/gt911/touchscreen/gt911_touchscreen.h index a9e1279ed3..17636a2ada 100644 --- a/esphome/components/gt911/touchscreen/gt911_touchscreen.h +++ b/esphome/components/gt911/touchscreen/gt911_touchscreen.h @@ -19,12 +19,14 @@ class GT911Touchscreen : public touchscreen::Touchscreen, public i2c::I2CDevice void dump_config() override; void set_interrupt_pin(InternalGPIOPin *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); } protected: void update_touches() override; InternalGPIOPin *interrupt_pin_{}; + GPIOPin *reset_pin_{}; std::vector button_listeners_; uint8_t button_state_{0xFF}; // last button state. Initial FF guarantees first update. }; diff --git a/tests/components/gt911/common.yaml b/tests/components/gt911/common.yaml new file mode 100644 index 0000000000..7bb88108da --- /dev/null +++ b/tests/components/gt911/common.yaml @@ -0,0 +1,25 @@ +i2c: + - id: i2c_gt911 + scl: 5 + sda: 4 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 10 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: gt911 + display: ssd1306_display + interrupt_pin: 20 + reset_pin: 21 + +binary_sensor: + - platform: gt911 + id: touch_key_911 + index: 0 diff --git a/tests/components/gt911/test.esp32-ard.yaml b/tests/components/gt911/test.esp32-ard.yaml index a47f7bf260..dade44d145 100644 --- a/tests/components/gt911/test.esp32-ard.yaml +++ b/tests/components/gt911/test.esp32-ard.yaml @@ -1,24 +1 @@ -i2c: - - id: i2c_gt911 - scl: 16 - sda: 17 - -display: - - platform: ssd1306_i2c - id: ssd1306_display - model: SSD1306_128X64 - reset_pin: 13 - pages: - - id: page1 - lambda: |- - it.rectangle(0, 0, it.get_width(), it.get_height()); - -touchscreen: - - platform: gt911 - display: ssd1306_display - interrupt_pin: 14 - -binary_sensor: - - platform: gt911 - id: touch_key_911 - index: 0 +<<: !include common.yaml diff --git a/tests/components/gt911/test.esp32-c3-ard.yaml b/tests/components/gt911/test.esp32-c3-ard.yaml index 43f7ac5902..dade44d145 100644 --- a/tests/components/gt911/test.esp32-c3-ard.yaml +++ b/tests/components/gt911/test.esp32-c3-ard.yaml @@ -1,24 +1 @@ -i2c: - - id: i2c_gt911 - scl: 5 - sda: 4 - -display: - - platform: ssd1306_i2c - id: ssd1306_display - model: SSD1306_128X64 - reset_pin: 3 - pages: - - id: page1 - lambda: |- - it.rectangle(0, 0, it.get_width(), it.get_height()); - -touchscreen: - - platform: gt911 - display: ssd1306_display - interrupt_pin: 6 - -binary_sensor: - - platform: gt911 - id: touch_key_911 - index: 0 +<<: !include common.yaml diff --git a/tests/components/gt911/test.esp32-c3-idf.yaml b/tests/components/gt911/test.esp32-c3-idf.yaml index 43f7ac5902..dade44d145 100644 --- a/tests/components/gt911/test.esp32-c3-idf.yaml +++ b/tests/components/gt911/test.esp32-c3-idf.yaml @@ -1,24 +1 @@ -i2c: - - id: i2c_gt911 - scl: 5 - sda: 4 - -display: - - platform: ssd1306_i2c - id: ssd1306_display - model: SSD1306_128X64 - reset_pin: 3 - pages: - - id: page1 - lambda: |- - it.rectangle(0, 0, it.get_width(), it.get_height()); - -touchscreen: - - platform: gt911 - display: ssd1306_display - interrupt_pin: 6 - -binary_sensor: - - platform: gt911 - id: touch_key_911 - index: 0 +<<: !include common.yaml diff --git a/tests/components/gt911/test.esp32-idf.yaml b/tests/components/gt911/test.esp32-idf.yaml index a47f7bf260..dade44d145 100644 --- a/tests/components/gt911/test.esp32-idf.yaml +++ b/tests/components/gt911/test.esp32-idf.yaml @@ -1,24 +1 @@ -i2c: - - id: i2c_gt911 - scl: 16 - sda: 17 - -display: - - platform: ssd1306_i2c - id: ssd1306_display - model: SSD1306_128X64 - reset_pin: 13 - pages: - - id: page1 - lambda: |- - it.rectangle(0, 0, it.get_width(), it.get_height()); - -touchscreen: - - platform: gt911 - display: ssd1306_display - interrupt_pin: 14 - -binary_sensor: - - platform: gt911 - id: touch_key_911 - index: 0 +<<: !include common.yaml diff --git a/tests/components/gt911/test.rp2040-ard.yaml b/tests/components/gt911/test.rp2040-ard.yaml index 43f7ac5902..dade44d145 100644 --- a/tests/components/gt911/test.rp2040-ard.yaml +++ b/tests/components/gt911/test.rp2040-ard.yaml @@ -1,24 +1 @@ -i2c: - - id: i2c_gt911 - scl: 5 - sda: 4 - -display: - - platform: ssd1306_i2c - id: ssd1306_display - model: SSD1306_128X64 - reset_pin: 3 - pages: - - id: page1 - lambda: |- - it.rectangle(0, 0, it.get_width(), it.get_height()); - -touchscreen: - - platform: gt911 - display: ssd1306_display - interrupt_pin: 6 - -binary_sensor: - - platform: gt911 - id: touch_key_911 - index: 0 +<<: !include common.yaml From d754bdde1b74b39f6d78a40a5fa92b721ce4cd93 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Fri, 30 Aug 2024 06:27:35 +1000 Subject: [PATCH 2012/2101] [st7701s] Add delay feature in init sequences (#7343) --- esphome/components/st7701s/display.py | 88 +++++++++++++------------- esphome/components/st7701s/st7701s.cpp | 17 +++-- esphome/components/st7701s/st7701s.h | 1 + tests/components/st7701s/common.yaml | 7 +- 4 files changed, 61 insertions(+), 52 deletions(-) diff --git a/esphome/components/st7701s/display.py b/esphome/components/st7701s/display.py index 516d770f8b..9310e9d760 100644 --- a/esphome/components/st7701s/display.py +++ b/esphome/components/st7701s/display.py @@ -1,47 +1,39 @@ -import esphome.codegen as cg -import esphome.config_validation as cv from esphome import pins -from esphome.components import ( - spi, - display, -) -from esphome.const import ( - CONF_DC_PIN, - CONF_HSYNC_PIN, - CONF_RESET_PIN, - CONF_DATA_PINS, - CONF_ID, - CONF_DIMENSIONS, - CONF_VSYNC_PIN, - CONF_WIDTH, - CONF_HEIGHT, - CONF_LAMBDA, - CONF_MIRROR_X, - CONF_MIRROR_Y, - CONF_COLOR_ORDER, - CONF_TRANSFORM, - CONF_OFFSET_HEIGHT, - CONF_OFFSET_WIDTH, - CONF_INVERT_COLORS, - CONF_RED, - CONF_GREEN, - CONF_BLUE, - CONF_NUMBER, - CONF_IGNORE_STRAPPING_WARNING, -) - -from esphome.components.esp32 import ( - only_on_variant, - const, -) +import esphome.codegen as cg +from esphome.components import display, spi +from esphome.components.esp32 import const, only_on_variant from esphome.components.rpi_dpi_rgb.display import ( CONF_PCLK_FREQUENCY, CONF_PCLK_INVERTED, ) -from .init_sequences import ( - ST7701S_INITS, - cmd, +import esphome.config_validation as cv +from esphome.const import ( + CONF_BLUE, + CONF_COLOR_ORDER, + CONF_DATA_PINS, + CONF_DC_PIN, + CONF_DIMENSIONS, + CONF_GREEN, + CONF_HEIGHT, + CONF_HSYNC_PIN, + CONF_ID, + CONF_IGNORE_STRAPPING_WARNING, + CONF_INVERT_COLORS, + CONF_LAMBDA, + CONF_MIRROR_X, + CONF_MIRROR_Y, + CONF_NUMBER, + CONF_OFFSET_HEIGHT, + CONF_OFFSET_WIDTH, + CONF_RED, + CONF_RESET_PIN, + CONF_TRANSFORM, + CONF_VSYNC_PIN, + CONF_WIDTH, ) +from esphome.core import TimePeriod + +from .init_sequences import ST7701S_INITS, cmd CONF_INIT_SEQUENCE = "init_sequence" CONF_DE_PIN = "de_pin" @@ -59,6 +51,7 @@ DEPENDENCIES = ["spi", "esp32"] st7701s_ns = cg.esphome_ns.namespace("st7701s") ST7701S = st7701s_ns.class_("ST7701S", display.Display, cg.Component, spi.SPIDevice) ColorOrder = display.display_ns.enum("ColorMode") +ST7701S_DELAY_FLAG = 0xFF COLOR_ORDERS = { "RGB": ColorOrder.COLOR_ORDER_RGB, @@ -93,18 +86,23 @@ def map_sequence(value): """ An initialisation sequence can be selected from one of the pre-defined sequences in init_sequences.py, or can be a literal array of data bytes. - The format is a repeated sequence of [CMD, LEN, ] where is LEN bytes. + The format is a repeated sequence of [CMD, ] where is s a sequence of bytes. The length is inferred + from the length of the sequence and should not be explicit. + A delay can be inserted by specifying "- delay N" where N is in ms """ + if isinstance(value, str) and value.lower().startswith("delay "): + value = value.lower()[6:] + delay = cv.All( + cv.positive_time_period_milliseconds, + cv.Range(TimePeriod(milliseconds=1), TimePeriod(milliseconds=255)), + )(value) + return [delay, ST7701S_DELAY_FLAG] if not isinstance(value, list): value = cv.int_(value) value = cv.one_of(*ST7701S_INITS)(value) return ST7701S_INITS[value] - # value = cv.ensure_list(cv.uint8_t)(value) - data_length = len(value) - if data_length == 0: - raise cv.Invalid("Empty sequence") - value = cmd(*value) - return value + value = cv.Length(min=1, max=254)(value) + return cmd(*value) CONFIG_SCHEMA = cv.All( diff --git a/esphome/components/st7701s/st7701s.cpp b/esphome/components/st7701s/st7701s.cpp index 43d8653709..7f02fe1774 100644 --- a/esphome/components/st7701s/st7701s.cpp +++ b/esphome/components/st7701s/st7701s.cpp @@ -138,11 +138,16 @@ void ST7701S::write_init_sequence_() { for (size_t i = 0; i != this->init_sequence_.size();) { uint8_t cmd = this->init_sequence_[i++]; size_t len = this->init_sequence_[i++]; - this->write_sequence_(cmd, len, &this->init_sequence_[i]); - i += len; - esph_log_v(TAG, "Command %X, %d bytes", cmd, len); - if (cmd == SW_RESET_CMD) - delay(6); + if (len == ST7701S_DELAY_FLAG) { + ESP_LOGV(TAG, "Delay %dms", cmd); + delay(cmd); + } else { + this->write_sequence_(cmd, len, &this->init_sequence_[i]); + i += len; + ESP_LOGV(TAG, "Command %X, %d bytes", cmd, len); + if (cmd == SW_RESET_CMD) + delay(6); + } } // st7701 does not appear to support axis swapping this->write_sequence_(CMD2_BKSEL, sizeof(CMD2_BK0), CMD2_BK0); @@ -153,7 +158,7 @@ void ST7701S::write_init_sequence_() { val |= 0x10; this->write_command_(MADCTL_CMD); this->write_data_(val); - esph_log_d(TAG, "write MADCTL %X", val); + ESP_LOGD(TAG, "write MADCTL %X", val); this->write_command_(this->invert_colors_ ? INVERT_ON : INVERT_OFF); this->set_timeout(120, [this] { this->write_command_(SLEEP_OUT); diff --git a/esphome/components/st7701s/st7701s.h b/esphome/components/st7701s/st7701s.h index 2328bca965..80e5b81f4a 100644 --- a/esphome/components/st7701s/st7701s.h +++ b/esphome/components/st7701s/st7701s.h @@ -25,6 +25,7 @@ const uint8_t INVERT_ON = 0x21; const uint8_t DISPLAY_ON = 0x29; const uint8_t CMD2_BKSEL = 0xFF; const uint8_t CMD2_BK0[5] = {0x77, 0x01, 0x00, 0x00, 0x10}; +const uint8_t ST7701S_DELAY_FLAG = 0xFF; class ST7701S : public display::Display, public spi::SPIDevice Date: Fri, 30 Aug 2024 09:20:01 +1000 Subject: [PATCH 2013/2101] Add now required `invert_colors` option to test files referencing ili9xxx (#7367) --- tests/components/animation/test.esp32-ard.yaml | 1 + tests/components/animation/test.esp32-c3-ard.yaml | 1 + tests/components/animation/test.esp32-c3-idf.yaml | 1 + tests/components/animation/test.esp32-idf.yaml | 1 + tests/components/animation/test.esp8266-ard.yaml | 1 + tests/components/animation/test.rp2040-ard.yaml | 1 + tests/components/cst226/common.yaml | 1 + tests/components/cst816/common.yaml | 1 + tests/components/display/common.yaml | 1 + tests/components/ft63x6/test.esp32-ard.yaml | 1 + tests/components/image/test.esp32-ard.yaml | 1 + tests/components/image/test.esp32-c3-ard.yaml | 1 + tests/components/image/test.esp32-c3-idf.yaml | 1 + tests/components/image/test.esp32-idf.yaml | 1 + tests/components/image/test.esp8266-ard.yaml | 1 + tests/components/image/test.rp2040-ard.yaml | 1 + tests/components/online_image/common-esp32.yaml | 1 + tests/components/online_image/common-esp8266.yaml | 1 + tests/components/qr_code/test.esp32-ard.yaml | 1 + tests/components/qr_code/test.esp32-c3-ard.yaml | 1 + tests/components/qr_code/test.esp32-c3-idf.yaml | 1 + tests/components/qr_code/test.esp32-idf.yaml | 1 + tests/components/qr_code/test.esp8266-ard.yaml | 1 + tests/components/qr_code/test.rp2040-ard.yaml | 1 + tests/components/tt21100/test.esp32-s2-ard.yaml | 1 + tests/components/xpt2046/test.esp32-ard.yaml | 1 + tests/components/xpt2046/test.esp32-c3-ard.yaml | 1 + tests/components/xpt2046/test.esp32-c3-idf.yaml | 1 + tests/components/xpt2046/test.esp32-idf.yaml | 1 + tests/components/xpt2046/test.esp32-s2-ard.yaml | 1 + tests/components/xpt2046/test.esp8266-ard.yaml | 1 + tests/components/xpt2046/test.rp2040-ard.yaml | 1 + 32 files changed, 32 insertions(+) diff --git a/tests/components/animation/test.esp32-ard.yaml b/tests/components/animation/test.esp32-ard.yaml index 5dc132eb2d..af6cd202dd 100644 --- a/tests/components/animation/test.esp32-ard.yaml +++ b/tests/components/animation/test.esp32-ard.yaml @@ -11,6 +11,7 @@ display: cs_pin: 12 dc_pin: 13 reset_pin: 21 + invert_colors: false # Purposely test that `animation:` does auto-load `image:` # Keep the `image:` undefined. diff --git a/tests/components/animation/test.esp32-c3-ard.yaml b/tests/components/animation/test.esp32-c3-ard.yaml index 9bcfbdb118..10e8ccb47e 100644 --- a/tests/components/animation/test.esp32-c3-ard.yaml +++ b/tests/components/animation/test.esp32-c3-ard.yaml @@ -11,6 +11,7 @@ display: cs_pin: 8 dc_pin: 9 reset_pin: 10 + invert_colors: false # Purposely test that `animation:` does auto-load `image:` # Keep the `image:` undefined. diff --git a/tests/components/animation/test.esp32-c3-idf.yaml b/tests/components/animation/test.esp32-c3-idf.yaml index 9bcfbdb118..10e8ccb47e 100644 --- a/tests/components/animation/test.esp32-c3-idf.yaml +++ b/tests/components/animation/test.esp32-c3-idf.yaml @@ -11,6 +11,7 @@ display: cs_pin: 8 dc_pin: 9 reset_pin: 10 + invert_colors: false # Purposely test that `animation:` does auto-load `image:` # Keep the `image:` undefined. diff --git a/tests/components/animation/test.esp32-idf.yaml b/tests/components/animation/test.esp32-idf.yaml index 5dc132eb2d..af6cd202dd 100644 --- a/tests/components/animation/test.esp32-idf.yaml +++ b/tests/components/animation/test.esp32-idf.yaml @@ -11,6 +11,7 @@ display: cs_pin: 12 dc_pin: 13 reset_pin: 21 + invert_colors: false # Purposely test that `animation:` does auto-load `image:` # Keep the `image:` undefined. diff --git a/tests/components/animation/test.esp8266-ard.yaml b/tests/components/animation/test.esp8266-ard.yaml index ef0f483a79..ced4996f25 100644 --- a/tests/components/animation/test.esp8266-ard.yaml +++ b/tests/components/animation/test.esp8266-ard.yaml @@ -11,6 +11,7 @@ display: cs_pin: 5 dc_pin: 15 reset_pin: 16 + invert_colors: false # Purposely test that `animation:` does auto-load `image:` # Keep the `image:` undefined. diff --git a/tests/components/animation/test.rp2040-ard.yaml b/tests/components/animation/test.rp2040-ard.yaml index 6ee29a3347..0e33959cc6 100644 --- a/tests/components/animation/test.rp2040-ard.yaml +++ b/tests/components/animation/test.rp2040-ard.yaml @@ -11,6 +11,7 @@ display: cs_pin: 20 dc_pin: 21 reset_pin: 22 + invert_colors: false # Purposely test that `animation:` does auto-load `image:` # Keep the `image:` undefined. diff --git a/tests/components/cst226/common.yaml b/tests/components/cst226/common.yaml index 4cbf38ef50..7e1c5dde36 100644 --- a/tests/components/cst226/common.yaml +++ b/tests/components/cst226/common.yaml @@ -12,6 +12,7 @@ display: dc_pin: GPIO4 reset_pin: number: GPIO21 + invert_colors: false i2c: scl: GPIO18 diff --git a/tests/components/cst816/common.yaml b/tests/components/cst816/common.yaml index f8deea6e98..91abbfd4f6 100644 --- a/tests/components/cst816/common.yaml +++ b/tests/components/cst816/common.yaml @@ -26,6 +26,7 @@ display: mirror_x: true mirror_y: true auto_clear_enabled: false + invert_colors: false spi: clk_pin: 14 diff --git a/tests/components/display/common.yaml b/tests/components/display/common.yaml index a22aa76780..1df2665067 100644 --- a/tests/components/display/common.yaml +++ b/tests/components/display/common.yaml @@ -11,6 +11,7 @@ display: cs_pin: 12 dc_pin: 13 reset_pin: 21 + invert_colors: false lambda: |- // Draw an analog clock in the center of the screen int centerX = it.get_width() / 2; diff --git a/tests/components/ft63x6/test.esp32-ard.yaml b/tests/components/ft63x6/test.esp32-ard.yaml index 32d6634dae..5c43cdff45 100644 --- a/tests/components/ft63x6/test.esp32-ard.yaml +++ b/tests/components/ft63x6/test.esp32-ard.yaml @@ -19,6 +19,7 @@ display: mirror_x: true mirror_y: true auto_clear_enabled: false + invert_colors: false touchscreen: - platform: ft63x6 diff --git a/tests/components/image/test.esp32-ard.yaml b/tests/components/image/test.esp32-ard.yaml index ff9adde6b1..34c7914976 100644 --- a/tests/components/image/test.esp32-ard.yaml +++ b/tests/components/image/test.esp32-ard.yaml @@ -11,6 +11,7 @@ display: cs_pin: 12 dc_pin: 13 reset_pin: 21 + invert_colors: true image: - id: binary_image diff --git a/tests/components/image/test.esp32-c3-ard.yaml b/tests/components/image/test.esp32-c3-ard.yaml index c083a97c94..91ff0a0579 100644 --- a/tests/components/image/test.esp32-c3-ard.yaml +++ b/tests/components/image/test.esp32-c3-ard.yaml @@ -11,6 +11,7 @@ display: cs_pin: 8 dc_pin: 9 reset_pin: 10 + invert_colors: true image: - id: binary_image diff --git a/tests/components/image/test.esp32-c3-idf.yaml b/tests/components/image/test.esp32-c3-idf.yaml index c083a97c94..91ff0a0579 100644 --- a/tests/components/image/test.esp32-c3-idf.yaml +++ b/tests/components/image/test.esp32-c3-idf.yaml @@ -11,6 +11,7 @@ display: cs_pin: 8 dc_pin: 9 reset_pin: 10 + invert_colors: true image: - id: binary_image diff --git a/tests/components/image/test.esp32-idf.yaml b/tests/components/image/test.esp32-idf.yaml index ff9adde6b1..34c7914976 100644 --- a/tests/components/image/test.esp32-idf.yaml +++ b/tests/components/image/test.esp32-idf.yaml @@ -11,6 +11,7 @@ display: cs_pin: 12 dc_pin: 13 reset_pin: 21 + invert_colors: true image: - id: binary_image diff --git a/tests/components/image/test.esp8266-ard.yaml b/tests/components/image/test.esp8266-ard.yaml index 3632b95485..5a96ed9497 100644 --- a/tests/components/image/test.esp8266-ard.yaml +++ b/tests/components/image/test.esp8266-ard.yaml @@ -11,6 +11,7 @@ display: cs_pin: 5 dc_pin: 15 reset_pin: 16 + invert_colors: true image: - id: binary_image diff --git a/tests/components/image/test.rp2040-ard.yaml b/tests/components/image/test.rp2040-ard.yaml index b79c8a9195..4c40ca464f 100644 --- a/tests/components/image/test.rp2040-ard.yaml +++ b/tests/components/image/test.rp2040-ard.yaml @@ -11,6 +11,7 @@ display: cs_pin: 20 dc_pin: 21 reset_pin: 22 + invert_colors: true image: - id: binary_image diff --git a/tests/components/online_image/common-esp32.yaml b/tests/components/online_image/common-esp32.yaml index 8cc50fc3e0..d3a304cdc0 100644 --- a/tests/components/online_image/common-esp32.yaml +++ b/tests/components/online_image/common-esp32.yaml @@ -13,6 +13,7 @@ display: cs_pin: 12 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/common-esp8266.yaml b/tests/components/online_image/common-esp8266.yaml index 01e3467413..ba15b5025c 100644 --- a/tests/components/online_image/common-esp8266.yaml +++ b/tests/components/online_image/common-esp8266.yaml @@ -13,6 +13,7 @@ display: cs_pin: 15 dc_pin: 3 reset_pin: 1 + invert_colors: true lambda: |- it.fill(Color(0, 0, 0)); it.image(0, 0, id(online_rgba_image)); diff --git a/tests/components/qr_code/test.esp32-ard.yaml b/tests/components/qr_code/test.esp32-ard.yaml index 3e70d3258f..8689d4d73f 100644 --- a/tests/components/qr_code/test.esp32-ard.yaml +++ b/tests/components/qr_code/test.esp32-ard.yaml @@ -11,6 +11,7 @@ display: cs_pin: 12 dc_pin: 13 reset_pin: 21 + invert_colors: false lambda: |- // Draw a QR code in the center of the screen auto scale = 2; diff --git a/tests/components/qr_code/test.esp32-c3-ard.yaml b/tests/components/qr_code/test.esp32-c3-ard.yaml index 63973b1aa2..3690d2598c 100644 --- a/tests/components/qr_code/test.esp32-c3-ard.yaml +++ b/tests/components/qr_code/test.esp32-c3-ard.yaml @@ -11,6 +11,7 @@ display: cs_pin: 8 dc_pin: 9 reset_pin: 10 + invert_colors: false lambda: |- // Draw a QR code in the center of the screen auto scale = 2; diff --git a/tests/components/qr_code/test.esp32-c3-idf.yaml b/tests/components/qr_code/test.esp32-c3-idf.yaml index 63973b1aa2..3690d2598c 100644 --- a/tests/components/qr_code/test.esp32-c3-idf.yaml +++ b/tests/components/qr_code/test.esp32-c3-idf.yaml @@ -11,6 +11,7 @@ display: cs_pin: 8 dc_pin: 9 reset_pin: 10 + invert_colors: false lambda: |- // Draw a QR code in the center of the screen auto scale = 2; diff --git a/tests/components/qr_code/test.esp32-idf.yaml b/tests/components/qr_code/test.esp32-idf.yaml index 3e70d3258f..8689d4d73f 100644 --- a/tests/components/qr_code/test.esp32-idf.yaml +++ b/tests/components/qr_code/test.esp32-idf.yaml @@ -11,6 +11,7 @@ display: cs_pin: 12 dc_pin: 13 reset_pin: 21 + invert_colors: false lambda: |- // Draw a QR code in the center of the screen auto scale = 2; diff --git a/tests/components/qr_code/test.esp8266-ard.yaml b/tests/components/qr_code/test.esp8266-ard.yaml index 3c304d7575..02dc183440 100644 --- a/tests/components/qr_code/test.esp8266-ard.yaml +++ b/tests/components/qr_code/test.esp8266-ard.yaml @@ -11,6 +11,7 @@ display: cs_pin: 5 dc_pin: 15 reset_pin: 16 + invert_colors: false lambda: |- // Draw a QR code in the center of the screen auto scale = 2; diff --git a/tests/components/qr_code/test.rp2040-ard.yaml b/tests/components/qr_code/test.rp2040-ard.yaml index 94cb772ba3..0d86f8d213 100644 --- a/tests/components/qr_code/test.rp2040-ard.yaml +++ b/tests/components/qr_code/test.rp2040-ard.yaml @@ -11,6 +11,7 @@ display: cs_pin: 20 dc_pin: 21 reset_pin: 22 + invert_colors: false lambda: |- // Draw a QR code in the center of the screen auto scale = 2; diff --git a/tests/components/tt21100/test.esp32-s2-ard.yaml b/tests/components/tt21100/test.esp32-s2-ard.yaml index 7ebabcb130..86b9e7530d 100644 --- a/tests/components/tt21100/test.esp32-s2-ard.yaml +++ b/tests/components/tt21100/test.esp32-s2-ard.yaml @@ -18,6 +18,7 @@ display: data_rate: 40MHz dimensions: 320x240 update_interval: never + invert_colors: false transform: mirror_y: false mirror_x: false diff --git a/tests/components/xpt2046/test.esp32-ard.yaml b/tests/components/xpt2046/test.esp32-ard.yaml index bb166866f4..f15d1f9b41 100644 --- a/tests/components/xpt2046/test.esp32-ard.yaml +++ b/tests/components/xpt2046/test.esp32-ard.yaml @@ -12,6 +12,7 @@ display: cs_pin: 13 dc_pin: 14 reset_pin: 21 + invert_colors: false lambda: |- it.rectangle(0, 0, it.get_width(), it.get_height()); diff --git a/tests/components/xpt2046/test.esp32-c3-ard.yaml b/tests/components/xpt2046/test.esp32-c3-ard.yaml index f3a2cf9aae..ef4daa800d 100644 --- a/tests/components/xpt2046/test.esp32-c3-ard.yaml +++ b/tests/components/xpt2046/test.esp32-c3-ard.yaml @@ -12,6 +12,7 @@ display: cs_pin: 8 dc_pin: 9 reset_pin: 10 + invert_colors: false lambda: |- it.rectangle(0, 0, it.get_width(), it.get_height()); diff --git a/tests/components/xpt2046/test.esp32-c3-idf.yaml b/tests/components/xpt2046/test.esp32-c3-idf.yaml index f3a2cf9aae..ef4daa800d 100644 --- a/tests/components/xpt2046/test.esp32-c3-idf.yaml +++ b/tests/components/xpt2046/test.esp32-c3-idf.yaml @@ -12,6 +12,7 @@ display: cs_pin: 8 dc_pin: 9 reset_pin: 10 + invert_colors: false lambda: |- it.rectangle(0, 0, it.get_width(), it.get_height()); diff --git a/tests/components/xpt2046/test.esp32-idf.yaml b/tests/components/xpt2046/test.esp32-idf.yaml index bb166866f4..f15d1f9b41 100644 --- a/tests/components/xpt2046/test.esp32-idf.yaml +++ b/tests/components/xpt2046/test.esp32-idf.yaml @@ -12,6 +12,7 @@ display: cs_pin: 13 dc_pin: 14 reset_pin: 21 + invert_colors: false lambda: |- it.rectangle(0, 0, it.get_width(), it.get_height()); diff --git a/tests/components/xpt2046/test.esp32-s2-ard.yaml b/tests/components/xpt2046/test.esp32-s2-ard.yaml index 6232ca957b..df2a99b4f5 100644 --- a/tests/components/xpt2046/test.esp32-s2-ard.yaml +++ b/tests/components/xpt2046/test.esp32-s2-ard.yaml @@ -14,6 +14,7 @@ display: data_rate: 40MHz dimensions: 320x240 update_interval: never + invert_colors: false transform: mirror_y: false mirror_x: false diff --git a/tests/components/xpt2046/test.esp8266-ard.yaml b/tests/components/xpt2046/test.esp8266-ard.yaml index a917290e8e..0daa25ad60 100644 --- a/tests/components/xpt2046/test.esp8266-ard.yaml +++ b/tests/components/xpt2046/test.esp8266-ard.yaml @@ -12,6 +12,7 @@ display: cs_pin: 15 dc_pin: 4 reset_pin: 5 + invert_colors: false lambda: |- it.rectangle(0, 0, it.get_width(), it.get_height()); diff --git a/tests/components/xpt2046/test.rp2040-ard.yaml b/tests/components/xpt2046/test.rp2040-ard.yaml index a7a49309ac..8afc45d04d 100644 --- a/tests/components/xpt2046/test.rp2040-ard.yaml +++ b/tests/components/xpt2046/test.rp2040-ard.yaml @@ -12,6 +12,7 @@ display: cs_pin: 8 dc_pin: 9 reset_pin: 10 + invert_colors: false lambda: |- it.rectangle(0, 0, it.get_width(), it.get_height()); From 69f98e0f87eacdad0be79fc33287e869c37587ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20Kry=C5=84ski?= Date: Fri, 30 Aug 2024 01:43:47 +0200 Subject: [PATCH 2014/2101] esp32_can: make queue lengths configurable (#7361) --- esphome/components/esp32_can/canbus.py | 25 ++++++++++++++++------ esphome/components/esp32_can/esp32_can.cpp | 7 ++++++ esphome/components/esp32_can/esp32_can.h | 4 ++++ esphome/const.py | 2 ++ 4 files changed, 31 insertions(+), 7 deletions(-) diff --git a/esphome/components/esp32_can/canbus.py b/esphome/components/esp32_can/canbus.py index f4ba032009..37bdfa3962 100644 --- a/esphome/components/esp32_can/canbus.py +++ b/esphome/components/esp32_can/canbus.py @@ -1,18 +1,23 @@ -import esphome.codegen as cg -import esphome.config_validation as cv from esphome import pins +import esphome.codegen as cg from esphome.components import canbus -from esphome.const import CONF_ID, CONF_RX_PIN, CONF_TX_PIN -from esphome.components.canbus import CanbusComponent, CanSpeed, CONF_BIT_RATE - +from esphome.components.canbus import CONF_BIT_RATE, CanbusComponent, CanSpeed from esphome.components.esp32 import get_esp32_variant from esphome.components.esp32.const import ( VARIANT_ESP32, - VARIANT_ESP32S2, - VARIANT_ESP32S3, VARIANT_ESP32C3, VARIANT_ESP32C6, VARIANT_ESP32H2, + VARIANT_ESP32S2, + VARIANT_ESP32S3, +) +import esphome.config_validation as cv +from esphome.const import ( + CONF_ID, + CONF_RX_PIN, + CONF_RX_QUEUE_LEN, + CONF_TX_PIN, + CONF_TX_QUEUE_LEN, ) CODEOWNERS = ["@Sympatron"] @@ -77,6 +82,8 @@ 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_RX_QUEUE_LEN): cv.uint32_t, + cv.Optional(CONF_TX_QUEUE_LEN): cv.uint32_t, } ) @@ -87,3 +94,7 @@ async def to_code(config): cg.add(var.set_rx(config[CONF_RX_PIN])) cg.add(var.set_tx(config[CONF_TX_PIN])) + 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: + cg.add(var.set_tx_queue_len(tx_queue_len)) diff --git a/esphome/components/esp32_can/esp32_can.cpp b/esphome/components/esp32_can/esp32_can.cpp index 214b72e864..5a45859b1f 100644 --- a/esphome/components/esp32_can/esp32_can.cpp +++ b/esphome/components/esp32_can/esp32_can.cpp @@ -69,6 +69,13 @@ static bool get_bitrate(canbus::CanSpeed bitrate, twai_timing_config_t *t_config bool ESP32Can::setup_internal() { twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT((gpio_num_t) this->tx_, (gpio_num_t) this->rx_, TWAI_MODE_NORMAL); + if (this->tx_queue_len_.has_value()) { + g_config.tx_queue_len = this->tx_queue_len_.value(); + } + if (this->rx_queue_len_.has_value()) { + g_config.rx_queue_len = this->rx_queue_len_.value(); + } + twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL(); twai_timing_config_t t_config; diff --git a/esphome/components/esp32_can/esp32_can.h b/esphome/components/esp32_can/esp32_can.h index a428834f65..b3086f9a48 100644 --- a/esphome/components/esp32_can/esp32_can.h +++ b/esphome/components/esp32_can/esp32_can.h @@ -12,6 +12,8 @@ class ESP32Can : public canbus::Canbus { public: void set_rx(int rx) { rx_ = rx; } void set_tx(int tx) { tx_ = tx; } + 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; } ESP32Can(){}; protected: @@ -21,6 +23,8 @@ class ESP32Can : public canbus::Canbus { int rx_{-1}; int tx_{-1}; + optional tx_queue_len_{}; + optional rx_queue_len_{}; }; } // namespace esp32_can diff --git a/esphome/const.py b/esphome/const.py index 6e29667887..95773630d0 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -730,6 +730,7 @@ CONF_RW_PIN = "rw_pin" CONF_RX_BUFFER_SIZE = "rx_buffer_size" CONF_RX_ONLY = "rx_only" CONF_RX_PIN = "rx_pin" +CONF_RX_QUEUE_LEN = "rx_queue_len" CONF_SAFE_MODE = "safe_mode" CONF_SAMPLE_RATE = "sample_rate" CONF_SAMSUNG = "samsung" @@ -881,6 +882,7 @@ CONF_TVOC = "tvoc" CONF_TX_BUFFER_SIZE = "tx_buffer_size" CONF_TX_PIN = "tx_pin" CONF_TX_POWER = "tx_power" +CONF_TX_QUEUE_LEN = "tx_queue_len" CONF_TYPE = "type" CONF_TYPE_ID = "type_id" CONF_UART_ID = "uart_id" From f8e8bd2c24666fe1efaf60a44ea46dfae3093341 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Fri, 30 Aug 2024 02:03:44 +0200 Subject: [PATCH 2015/2101] [code-quality] fix clang-tidy web_server and web_server_base (#7286) --- esphome/components/web_server/__init__.py | 26 +++++++++---------- .../components/web_server/list_entities.cpp | 2 ++ esphome/components/web_server/list_entities.h | 4 ++- esphome/components/web_server/web_server.cpp | 3 ++- esphome/components/web_server/web_server.h | 2 ++ .../web_server_base/web_server_base.cpp | 2 ++ .../web_server_base/web_server_base.h | 4 ++- 7 files changed, 27 insertions(+), 16 deletions(-) diff --git a/esphome/components/web_server/__init__.py b/esphome/components/web_server/__init__.py index 232ab40d10..02074dcf11 100644 --- a/esphome/components/web_server/__init__.py +++ b/esphome/components/web_server/__init__.py @@ -1,35 +1,36 @@ from __future__ import annotations import gzip + import esphome.codegen as cg -import esphome.config_validation as cv -import esphome.final_validate as fv from esphome.components import web_server_base from esphome.components.web_server_base import CONF_WEB_SERVER_BASE_ID +import esphome.config_validation as cv from esphome.const import ( + CONF_AUTH, CONF_CSS_INCLUDE, CONF_CSS_URL, + CONF_ENABLE_PRIVATE_NETWORK_ACCESS, CONF_ID, + CONF_INCLUDE_INTERNAL, CONF_JS_INCLUDE, CONF_JS_URL, - CONF_ENABLE_PRIVATE_NETWORK_ACCESS, - CONF_PORT, - CONF_AUTH, - CONF_USERNAME, - CONF_PASSWORD, - CONF_INCLUDE_INTERNAL, - CONF_OTA, - CONF_LOG, - CONF_VERSION, CONF_LOCAL, + CONF_LOG, + CONF_OTA, + CONF_PASSWORD, + CONF_PORT, + CONF_USERNAME, + CONF_VERSION, CONF_WEB_SERVER_ID, CONF_WEB_SERVER_SORTING_WEIGHT, + PLATFORM_BK72XX, PLATFORM_ESP32, PLATFORM_ESP8266, - PLATFORM_BK72XX, PLATFORM_RTL87XX, ) from esphome.core import CORE, coroutine_with_priority +import esphome.final_validate as fv AUTO_LOAD = ["json", "web_server_base"] @@ -208,7 +209,6 @@ async def to_code(config): var = cg.new_Pvariable(config[CONF_ID], paren) await cg.register_component(var, config) - cg.add_define("USE_WEBSERVER") version = config[CONF_VERSION] cg.add(paren.set_port(config[CONF_PORT])) diff --git a/esphome/components/web_server/list_entities.cpp b/esphome/components/web_server/list_entities.cpp index 332f358352..a02f84c34b 100644 --- a/esphome/components/web_server/list_entities.cpp +++ b/esphome/components/web_server/list_entities.cpp @@ -1,4 +1,5 @@ #include "list_entities.h" +#ifdef USE_WEBSERVER #include "esphome/core/application.h" #include "esphome/core/log.h" #include "esphome/core/util.h" @@ -188,3 +189,4 @@ bool ListEntitiesIterator::on_update(update::UpdateEntity *update) { } // namespace web_server } // namespace esphome +#endif diff --git a/esphome/components/web_server/list_entities.h b/esphome/components/web_server/list_entities.h index 5ff6ec0412..53e5bc3355 100644 --- a/esphome/components/web_server/list_entities.h +++ b/esphome/components/web_server/list_entities.h @@ -1,8 +1,9 @@ #pragma once +#include "esphome/core/defines.h" +#ifdef USE_WEBSERVER #include "esphome/core/component.h" #include "esphome/core/component_iterator.h" -#include "esphome/core/defines.h" namespace esphome { namespace web_server { @@ -78,3 +79,4 @@ class ListEntitiesIterator : public ComponentIterator { } // namespace web_server } // namespace esphome +#endif diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index 6fb04f558a..1bb7c6c249 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -1,5 +1,5 @@ #include "web_server.h" - +#ifdef USE_WEBSERVER #include "esphome/components/json/json_util.h" #include "esphome/components/network/util.h" #include "esphome/core/application.h" @@ -1659,3 +1659,4 @@ void WebServer::schedule_(std::function &&f) { } // namespace web_server } // namespace esphome +#endif diff --git a/esphome/components/web_server/web_server.h b/esphome/components/web_server/web_server.h index d4ab592b7b..3195fa7109 100644 --- a/esphome/components/web_server/web_server.h +++ b/esphome/components/web_server/web_server.h @@ -3,6 +3,7 @@ #include "list_entities.h" #include "esphome/components/web_server_base/web_server_base.h" +#ifdef USE_WEBSERVER #include "esphome/core/component.h" #include "esphome/core/controller.h" #include "esphome/core/entity_base.h" @@ -366,3 +367,4 @@ class WebServer : public Controller, public Component, public AsyncWebHandler { } // namespace web_server } // namespace esphome +#endif diff --git a/esphome/components/web_server_base/web_server_base.cpp b/esphome/components/web_server_base/web_server_base.cpp index f90c7e56a3..7c09022f27 100644 --- a/esphome/components/web_server_base/web_server_base.cpp +++ b/esphome/components/web_server_base/web_server_base.cpp @@ -1,4 +1,5 @@ #include "web_server_base.h" +#ifdef USE_NETWORK #include "esphome/core/log.h" #include "esphome/core/application.h" #include "esphome/core/helpers.h" @@ -121,3 +122,4 @@ float WebServerBase::get_setup_priority() const { } // namespace web_server_base } // namespace esphome +#endif diff --git a/esphome/components/web_server_base/web_server_base.h b/esphome/components/web_server_base/web_server_base.h index 2282d55ec1..f876d163bc 100644 --- a/esphome/components/web_server_base/web_server_base.h +++ b/esphome/components/web_server_base/web_server_base.h @@ -1,5 +1,6 @@ #pragma once - +#include "esphome/core/defines.h" +#ifdef USE_NETWORK #include #include #include @@ -145,3 +146,4 @@ class OTARequestHandler : public AsyncWebHandler { } // namespace web_server_base } // namespace esphome +#endif From a5d46ae9e553d27e7f66dc3bd87c64dc86b2cf36 Mon Sep 17 00:00:00 2001 From: Trevor Schirmer <24777085+TrevorSchirmer@users.noreply.github.com> Date: Thu, 29 Aug 2024 20:36:32 -0400 Subject: [PATCH 2016/2101] Update MiCS Values (#7173) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/mics_4514/mics_4514.cpp | 62 +++++++++------------- 1 file changed, 26 insertions(+), 36 deletions(-) diff --git a/esphome/components/mics_4514/mics_4514.cpp b/esphome/components/mics_4514/mics_4514.cpp index a14d7f2f80..ed2fc6c826 100644 --- a/esphome/components/mics_4514/mics_4514.cpp +++ b/esphome/components/mics_4514/mics_4514.cpp @@ -70,72 +70,62 @@ void MICS4514Component::update() { if (this->carbon_monoxide_sensor_ != nullptr) { float co = 0.0f; - if (red_f <= 0.425f) { - co = (0.425f - red_f) / 0.000405f; - if (co < 1.0f) - co = 0.0f; - if (co > 1000.0f) - co = 1000.0f; + if (red_f > 3.4f) { + co = 0.0; + } else if (red_f < 0.01) { + co = 1000.0; + } else { + co = 4.2 / pow(red_f, 1.2); } this->carbon_monoxide_sensor_->publish_state(co); } if (this->nitrogen_dioxide_sensor_ != nullptr) { float nitrogendioxide = 0.0f; - if (ox_f >= 1.1f) { - nitrogendioxide = (ox_f - 0.045f) / 6.13f; - if (nitrogendioxide < 0.1f) - nitrogendioxide = 0.0f; - if (nitrogendioxide > 10.0f) - nitrogendioxide = 10.0f; + if (ox_f < 0.3f) { + nitrogendioxide = 0.0; + } else { + nitrogendioxide = 0.164 * pow(ox_f, 0.975); } this->nitrogen_dioxide_sensor_->publish_state(nitrogendioxide); } if (this->methane_sensor_ != nullptr) { float methane = 0.0f; - if (red_f <= 0.786f) { - methane = (0.786f - red_f) / 0.000023f; - if (methane < 1000.0f) - methane = 0.0f; - if (methane > 25000.0f) - methane = 25000.0f; + if (red_f > 0.9f || red_f < 0.5) { // outside the range->unlikely + methane = 0.0; + } else { + methane = 630 / pow(red_f, 4.4); } this->methane_sensor_->publish_state(methane); } if (this->ethanol_sensor_ != nullptr) { float ethanol = 0.0f; - if (red_f <= 0.306f) { - ethanol = (0.306f - red_f) / 0.00057f; - if (ethanol < 10.0f) - ethanol = 0.0f; - if (ethanol > 500.0f) - ethanol = 500.0f; + if (red_f > 1.0f || red_f < 0.02) { // outside the range->unlikely + ethanol = 0.0; + } else { + ethanol = 1.52 / pow(red_f, 1.55); } this->ethanol_sensor_->publish_state(ethanol); } if (this->hydrogen_sensor_ != nullptr) { float hydrogen = 0.0f; - if (red_f <= 0.279f) { - hydrogen = (0.279f - red_f) / 0.00026f; - if (hydrogen < 1.0f) - hydrogen = 0.0f; - if (hydrogen > 1000.0f) - hydrogen = 1000.0f; + if (red_f > 0.9f || red_f < 0.02) { // outside the range->unlikely + hydrogen = 0.0; + } else { + hydrogen = 0.85 / pow(red_f, 1.75); } this->hydrogen_sensor_->publish_state(hydrogen); } if (this->ammonia_sensor_ != nullptr) { float ammonia = 0.0f; - if (red_f <= 0.8f) { - ammonia = (0.8f - red_f) / 0.0015f; - if (ammonia < 1.0f) - ammonia = 0.0f; - if (ammonia > 500.0f) - ammonia = 500.0f; + if (red_f > 0.98f || red_f < 0.2532) { // outside the ammonia range->unlikely + ammonia = 0.0; + } else { + ammonia = 0.9 / pow(red_f, 4.6); } this->ammonia_sensor_->publish_state(ammonia); } From 721b532d71b4ca82c811e3db3b3e189e134704d8 Mon Sep 17 00:00:00 2001 From: Piotr Szulc Date: Fri, 30 Aug 2024 02:53:34 +0200 Subject: [PATCH 2017/2101] Tuya Number: allow restoring value of hidden datapoints (#7346) --- esphome/components/tuya/number/__init__.py | 3 ++ .../components/tuya/number/tuya_number.cpp | 45 +++++++++++++++++-- esphome/components/tuya/number/tuya_number.h | 9 +++- 3 files changed, 51 insertions(+), 6 deletions(-) diff --git a/esphome/components/tuya/number/__init__.py b/esphome/components/tuya/number/__init__.py index 25be6329ab..c00ea08d23 100644 --- a/esphome/components/tuya/number/__init__.py +++ b/esphome/components/tuya/number/__init__.py @@ -9,6 +9,7 @@ from esphome.const import ( CONF_MULTIPLY, CONF_STEP, CONF_INITIAL_VALUE, + CONF_RESTORE_VALUE, ) from .. import tuya_ns, CONF_TUYA_ID, Tuya, TuyaDatapointType @@ -58,6 +59,7 @@ CONFIG_SCHEMA = cv.All( DATAPOINT_TYPES, lower=True ), cv.Optional(CONF_INITIAL_VALUE): cv.float_, + cv.Optional(CONF_RESTORE_VALUE, default=False): cv.boolean, } ) ), @@ -90,3 +92,4 @@ async def to_code(config): hidden_init_value := hidden_config.get(CONF_INITIAL_VALUE, None) ) is not None: cg.add(var.set_datapoint_initial_value(hidden_init_value)) + cg.add(var.set_restore_value(hidden_config[CONF_RESTORE_VALUE])) diff --git a/esphome/components/tuya/number/tuya_number.cpp b/esphome/components/tuya/number/tuya_number.cpp index 7eeb08fde2..68a7f8f2a7 100644 --- a/esphome/components/tuya/number/tuya_number.cpp +++ b/esphome/components/tuya/number/tuya_number.cpp @@ -7,14 +7,28 @@ namespace tuya { static const char *const TAG = "tuya.number"; void TuyaNumber::setup() { + if (this->restore_value_) { + this->pref_ = global_preferences->make_preference(this->get_object_id_hash()); + } + this->parent_->register_listener(this->number_id_, [this](const TuyaDatapoint &datapoint) { if (datapoint.type == TuyaDatapointType::INTEGER) { ESP_LOGV(TAG, "MCU reported number %u is: %d", datapoint.id, datapoint.value_int); - this->publish_state(datapoint.value_int / multiply_by_); + float value = datapoint.value_int / multiply_by_; + this->publish_state(value); + if (this->restore_value_) + this->pref_.save(&value); } else if (datapoint.type == TuyaDatapointType::ENUM) { ESP_LOGV(TAG, "MCU reported number %u is: %u", datapoint.id, datapoint.value_enum); - this->publish_state(datapoint.value_enum); + float value = datapoint.value_enum; + this->publish_state(value); + if (this->restore_value_) + this->pref_.save(&value); + } else { + ESP_LOGW(TAG, "Reported type (%d) is not a number!", static_cast(datapoint.type)); + return; } + if ((this->type_) && (this->type_ != datapoint.type)) { ESP_LOGW(TAG, "Reported type (%d) different than previously set (%d)!", static_cast(datapoint.type), static_cast(*this->type_)); @@ -23,8 +37,26 @@ void TuyaNumber::setup() { }); this->parent_->add_on_initialized_callback([this] { - if ((this->initial_value_) && (this->type_)) { - this->control(*this->initial_value_); + if (this->type_) { + float value; + if (!this->restore_value_) { + if (this->initial_value_) { + value = *this->initial_value_; + } else { + return; + } + } else { + if (!this->pref_.load(&value)) { + if (this->initial_value_) { + value = *this->initial_value_; + } else { + value = this->traits.get_min_value(); + ESP_LOGW(TAG, "Failed to restore and there is no initial value defined. Setting min_value (%f)", value); + } + } + } + + this->control(value); } }); } @@ -38,6 +70,9 @@ void TuyaNumber::control(float value) { this->parent_->set_enum_datapoint_value(this->number_id_, value); } this->publish_state(value); + + if (this->restore_value_) + this->pref_.save(&value); } void TuyaNumber::dump_config() { @@ -52,6 +87,8 @@ void TuyaNumber::dump_config() { if (this->initial_value_) { ESP_LOGCONFIG(TAG, " Initial Value: %f", *this->initial_value_); } + + ESP_LOGCONFIG(TAG, " Restore Value: %s", YESNO(this->restore_value_)); } } // namespace tuya diff --git a/esphome/components/tuya/number/tuya_number.h b/esphome/components/tuya/number/tuya_number.h index 545584128e..53137d6f66 100644 --- a/esphome/components/tuya/number/tuya_number.h +++ b/esphome/components/tuya/number/tuya_number.h @@ -1,9 +1,10 @@ #pragma once -#include "esphome/core/component.h" -#include "esphome/components/tuya/tuya.h" #include "esphome/components/number/number.h" +#include "esphome/components/tuya/tuya.h" +#include "esphome/core/component.h" #include "esphome/core/optional.h" +#include "esphome/core/preferences.h" namespace esphome { namespace tuya { @@ -16,6 +17,7 @@ class TuyaNumber : public number::Number, public Component { void set_write_multiply(float factor) { multiply_by_ = factor; } void set_datapoint_type(TuyaDatapointType type) { type_ = type; } void set_datapoint_initial_value(float value) { this->initial_value_ = value; } + void set_restore_value(bool restore_value) { this->restore_value_ = restore_value; } void set_tuya_parent(Tuya *parent) { this->parent_ = parent; } @@ -27,6 +29,9 @@ class TuyaNumber : public number::Number, public Component { float multiply_by_{1.0}; optional type_{}; optional initial_value_{}; + bool restore_value_{false}; + + ESPPreferenceObject pref_; }; } // namespace tuya From ba6963cf72811cd75d4cd5510d1b81378c049ded Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Fri, 30 Aug 2024 18:59:55 +1000 Subject: [PATCH 2018/2101] [udp] Implement UDP sensor broadcast (#6865) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Co-authored-by: clydebarrow <366188+clydebarrow@users.noreply.github.com> --- CODEOWNERS | 1 + esphome/components/udp/__init__.py | 158 +++++ esphome/components/udp/binary_sensor.py | 27 + esphome/components/udp/sensor.py | 27 + esphome/components/udp/udp_component.cpp | 616 ++++++++++++++++++++ esphome/components/udp/udp_component.h | 158 +++++ tests/components/udp/common.yaml | 35 ++ tests/components/udp/test.bk72xx-ard.yaml | 1 + tests/components/udp/test.esp32-ard.yaml | 1 + tests/components/udp/test.esp32-c3-ard.yaml | 1 + tests/components/udp/test.esp32-c3-idf.yaml | 1 + tests/components/udp/test.esp32-idf.yaml | 1 + tests/components/udp/test.esp8266-ard.yaml | 1 + tests/components/udp/test.host.yaml | 4 + tests/components/udp/test.rp2040-ard.yaml | 1 + 15 files changed, 1033 insertions(+) create mode 100644 esphome/components/udp/__init__.py create mode 100644 esphome/components/udp/binary_sensor.py create mode 100644 esphome/components/udp/sensor.py create mode 100644 esphome/components/udp/udp_component.cpp create mode 100644 esphome/components/udp/udp_component.h create mode 100644 tests/components/udp/common.yaml create mode 100644 tests/components/udp/test.bk72xx-ard.yaml create mode 100644 tests/components/udp/test.esp32-ard.yaml create mode 100644 tests/components/udp/test.esp32-c3-ard.yaml create mode 100644 tests/components/udp/test.esp32-c3-idf.yaml create mode 100644 tests/components/udp/test.esp32-idf.yaml create mode 100644 tests/components/udp/test.esp8266-ard.yaml create mode 100644 tests/components/udp/test.host.yaml create mode 100644 tests/components/udp/test.rp2040-ard.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 40511e2f41..807829eafd 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -423,6 +423,7 @@ esphome/components/tuya/switch/* @jesserockz esphome/components/tuya/text_sensor/* @dentra esphome/components/uart/* @esphome/core esphome/components/uart/button/* @ssieb +esphome/components/udp/* @clydebarrow esphome/components/ufire_ec/* @pvizeli esphome/components/ufire_ise/* @pvizeli esphome/components/ultrasonic/* @OttoWinter diff --git a/esphome/components/udp/__init__.py b/esphome/components/udp/__init__.py new file mode 100644 index 0000000000..ca15be2a80 --- /dev/null +++ b/esphome/components/udp/__init__.py @@ -0,0 +1,158 @@ +import hashlib + +import esphome.codegen as cg +from esphome.components.api import CONF_ENCRYPTION +from esphome.components.binary_sensor import BinarySensor +from esphome.components.sensor import Sensor +import esphome.config_validation as cv +from esphome.const import ( + CONF_BINARY_SENSORS, + CONF_ID, + CONF_INTERNAL, + CONF_KEY, + CONF_NAME, + CONF_PORT, + CONF_SENSORS, +) +from esphome.cpp_generator import MockObjClass + +CODEOWNERS = ["@clydebarrow"] +DEPENDENCIES = ["network"] +AUTO_LOAD = ["socket"] +MULTI_CONF = True + +udp_ns = cg.esphome_ns.namespace("udp") +UDPComponent = udp_ns.class_("UDPComponent", cg.PollingComponent) + +CONF_BROADCAST = "broadcast" +CONF_BROADCAST_ID = "broadcast_id" +CONF_ADDRESSES = "addresses" +CONF_PROVIDER = "provider" +CONF_PROVIDERS = "providers" +CONF_REMOTE_ID = "remote_id" +CONF_UDP_ID = "udp_id" +CONF_PING_PONG_ENABLE = "ping_pong_enable" +CONF_PING_PONG_RECYCLE_TIME = "ping_pong_recycle_time" +CONF_ROLLING_CODE_ENABLE = "rolling_code_enable" + + +def sensor_validation(cls: MockObjClass): + return cv.maybe_simple_value( + cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(cls), + cv.Optional(CONF_BROADCAST_ID): cv.validate_id_name, + } + ), + key=CONF_ID, + ) + + +ENCRYPTION_SCHEMA = { + cv.Optional(CONF_ENCRYPTION): cv.maybe_simple_value( + cv.Schema( + { + cv.Required(CONF_KEY): cv.string, + } + ), + key=CONF_KEY, + ) +} + +PROVIDER_SCHEMA = cv.Schema( + { + cv.Required(CONF_NAME): cv.valid_name, + } +).extend(ENCRYPTION_SCHEMA) + + +def validate_(config): + if CONF_ENCRYPTION in config: + if CONF_SENSORS not in config and CONF_BINARY_SENSORS not in config: + raise cv.Invalid("No sensors or binary sensors to encrypt") + elif config[CONF_ROLLING_CODE_ENABLE]: + raise cv.Invalid("Rolling code requires an encryption key") + if config[CONF_PING_PONG_ENABLE]: + if not any(CONF_ENCRYPTION in p for p in config.get(CONF_PROVIDERS) or ()): + raise cv.Invalid("Ping-pong requires at least one encrypted provider") + return config + + +CONFIG_SCHEMA = cv.All( + cv.polling_component_schema("15s") + .extend( + { + cv.GenerateID(): cv.declare_id(UDPComponent), + cv.Optional(CONF_PORT, default=18511): cv.port, + cv.Optional(CONF_ADDRESSES, default=["255.255.255.255"]): cv.ensure_list( + cv.ipv4 + ), + cv.Optional(CONF_ROLLING_CODE_ENABLE, default=False): cv.boolean, + cv.Optional(CONF_PING_PONG_ENABLE, default=False): cv.boolean, + cv.Optional( + CONF_PING_PONG_RECYCLE_TIME, default="600s" + ): cv.positive_time_period_seconds, + cv.Optional(CONF_SENSORS): cv.ensure_list(sensor_validation(Sensor)), + cv.Optional(CONF_BINARY_SENSORS): cv.ensure_list( + sensor_validation(BinarySensor) + ), + cv.Optional(CONF_PROVIDERS): cv.ensure_list(PROVIDER_SCHEMA), + }, + ) + .extend(ENCRYPTION_SCHEMA), + validate_, +) + +SENSOR_SCHEMA = cv.Schema( + { + cv.Optional(CONF_REMOTE_ID): cv.string_strict, + cv.Required(CONF_PROVIDER): cv.valid_name, + cv.GenerateID(CONF_UDP_ID): cv.use_id(UDPComponent), + } +) + + +def require_internal_with_name(config): + if CONF_NAME in config and CONF_INTERNAL not in config: + raise cv.Invalid("Must provide internal: config when using name:") + return config + + +def hash_encryption_key(config: dict): + return list(hashlib.sha256(config[CONF_KEY].encode()).digest()) + + +async def to_code(config): + cg.add_define("USE_UDP") + cg.add_global(udp_ns.using) + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, config) + cg.add(var.set_port(config[CONF_PORT])) + cg.add(var.set_rolling_code_enable(config[CONF_ROLLING_CODE_ENABLE])) + cg.add(var.set_ping_pong_enable(config[CONF_PING_PONG_ENABLE])) + cg.add( + var.set_ping_pong_recycle_time( + config[CONF_PING_PONG_RECYCLE_TIME].total_seconds + ) + ) + for sens_conf in config.get(CONF_SENSORS, ()): + 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, ()): + 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_binary_sensor(bcst_id, sensor)) + for address in config[CONF_ADDRESSES]: + cg.add(var.add_address(str(address))) + + if encryption := config.get(CONF_ENCRYPTION): + cg.add(var.set_encryption_key(hash_encryption_key(encryption))) + + for provider in config.get(CONF_PROVIDERS, ()): + name = provider[CONF_NAME] + cg.add(var.add_provider(name)) + if encryption := provider.get(CONF_ENCRYPTION): + cg.add(var.set_provider_encryption(name, hash_encryption_key(encryption))) diff --git a/esphome/components/udp/binary_sensor.py b/esphome/components/udp/binary_sensor.py new file mode 100644 index 0000000000..d90e495527 --- /dev/null +++ b/esphome/components/udp/binary_sensor.py @@ -0,0 +1,27 @@ +import esphome.codegen as cg +from esphome.components import binary_sensor +from esphome.config_validation import All, has_at_least_one_key +from esphome.const import CONF_ID + +from . import ( + CONF_PROVIDER, + CONF_REMOTE_ID, + CONF_UDP_ID, + SENSOR_SCHEMA, + require_internal_with_name, +) + +DEPENDENCIES = ["udp"] + +CONFIG_SCHEMA = All( + binary_sensor.binary_sensor_schema().extend(SENSOR_SCHEMA), + has_at_least_one_key(CONF_ID, CONF_REMOTE_ID), + require_internal_with_name, +) + + +async def to_code(config): + var = await binary_sensor.new_binary_sensor(config) + comp = await cg.get_variable(config[CONF_UDP_ID]) + remote_id = str(config.get(CONF_REMOTE_ID) or config.get(CONF_ID)) + cg.add(comp.add_remote_binary_sensor(config[CONF_PROVIDER], remote_id, var)) diff --git a/esphome/components/udp/sensor.py b/esphome/components/udp/sensor.py new file mode 100644 index 0000000000..860c277c44 --- /dev/null +++ b/esphome/components/udp/sensor.py @@ -0,0 +1,27 @@ +import esphome.codegen as cg +from esphome.components.sensor import new_sensor, sensor_schema +from esphome.config_validation import All, has_at_least_one_key +from esphome.const import CONF_ID + +from . import ( + CONF_PROVIDER, + CONF_REMOTE_ID, + CONF_UDP_ID, + SENSOR_SCHEMA, + require_internal_with_name, +) + +DEPENDENCIES = ["udp"] + +CONFIG_SCHEMA = All( + sensor_schema().extend(SENSOR_SCHEMA), + has_at_least_one_key(CONF_ID, CONF_REMOTE_ID), + require_internal_with_name, +) + + +async def to_code(config): + var = await new_sensor(config) + comp = await cg.get_variable(config[CONF_UDP_ID]) + remote_id = str(config.get(CONF_REMOTE_ID) or config.get(CONF_ID)) + cg.add(comp.add_remote_sensor(config[CONF_PROVIDER], remote_id, var)) diff --git a/esphome/components/udp/udp_component.cpp b/esphome/components/udp/udp_component.cpp new file mode 100644 index 0000000000..799ed813d3 --- /dev/null +++ b/esphome/components/udp/udp_component.cpp @@ -0,0 +1,616 @@ +#include "esphome/core/log.h" +#include "esphome/core/application.h" +#include "esphome/components/network/util.h" +#include "udp_component.h" + +namespace esphome { +namespace udp { + +/** + * Structure of a data packet; everything is little-endian + * + * --- In clear text --- + * MAGIC_NUMBER: 16 bits + * host name length: 1 byte + * host name: (length) bytes + * padding: 0 or more null bytes to a 4 byte boundary + * + * --- Encrypted (if key set) ---- + * DATA_KEY: 1 byte: OR ROLLING_CODE_KEY: + * Rolling code (if enabled): 8 bytes + * Ping keys: if any + * repeat: + * PING_KEY: 1 byte + * ping code: 4 bytes + * Sensors: + * repeat: + * SENSOR_KEY: 1 byte + * float value: 4 bytes + * name length: 1 byte + * name + * Binary Sensors: + * repeat: + * BINARY_SENSOR_KEY: 1 byte + * bool value: 1 bytes + * name length: 1 byte + * name + * + * Padded to a 4 byte boundary with nulls + * + * Structure of a ping request packet: + * --- In clear text --- + * MAGIC_PING: 16 bits + * host name length: 1 byte + * host name: (length) bytes + * Ping key (4 bytes) + * + */ +static const char *const TAG = "udp"; + +/** + * XXTEA implementation, using 256 bit key. + */ + +static const uint32_t DELTA = 0x9e3779b9; +#define MX ((((z >> 5) ^ (y << 2)) + ((y >> 3) ^ (z << 4))) ^ ((sum ^ y) + (k[(p ^ e) & 7] ^ z))) + +/** + * Encrypt a block of data in-place + */ + +static void xxtea_encrypt(uint32_t *v, size_t n, const uint32_t *k) { + uint32_t z, y, sum, e; + size_t p; + size_t q = 6 + 52 / n; + sum = 0; + z = v[n - 1]; + while (q-- != 0) { + sum += DELTA; + e = (sum >> 2); + for (p = 0; p != n - 1; p++) { + y = v[p + 1]; + z = v[p] += MX; + } + y = v[0]; + z = v[n - 1] += MX; + } +} + +static void xxtea_decrypt(uint32_t *v, size_t n, const uint32_t *k) { + uint32_t z, y, sum, e; + size_t p; + size_t q = 6 + 52 / n; + sum = q * DELTA; + y = v[0]; + while (q-- != 0) { + e = (sum >> 2); + for (p = n - 1; p != 0; p--) { + z = v[p - 1]; + y = v[p] -= MX; + } + z = v[n - 1]; + y = v[0] -= MX; + sum -= DELTA; + } +} + +inline static size_t round4(size_t value) { return (value + 3) & ~3; } + +union FuData { + uint32_t u32; + float f32; +}; + +static const size_t MAX_PACKET_SIZE = 508; +static const uint16_t MAGIC_NUMBER = 0x4553; +static const uint16_t MAGIC_PING = 0x5048; +static const uint32_t PREF_HASH = 0x45535043; +enum DataKey { + ZERO_FILL_KEY, + DATA_KEY, + SENSOR_KEY, + BINARY_SENSOR_KEY, + PING_KEY, + ROLLING_CODE_KEY, +}; + +static const size_t MAX_PING_KEYS = 4; + +static inline void add(std::vector &vec, uint32_t data) { + vec.push_back(data & 0xFF); + vec.push_back((data >> 8) & 0xFF); + vec.push_back((data >> 16) & 0xFF); + vec.push_back((data >> 24) & 0xFF); +} + +static inline uint32_t get_uint32(uint8_t *&buf) { + uint32_t data = *buf++; + data += *buf++ << 8; + data += *buf++ << 16; + data += *buf++ << 24; + return data; +} + +static inline uint16_t get_uint16(uint8_t *&buf) { + uint16_t data = *buf++; + data += *buf++ << 8; + return data; +} + +static inline void add(std::vector &vec, uint8_t data) { vec.push_back(data); } +static inline void add(std::vector &vec, uint16_t data) { + vec.push_back((uint8_t) data); + vec.push_back((uint8_t) (data >> 8)); +} +static inline void add(std::vector &vec, DataKey data) { vec.push_back(data); } +static void add(std::vector &vec, const char *str) { + auto len = strlen(str); + vec.push_back(len); + for (size_t i = 0; i != len; i++) { + vec.push_back(*str++); + } +} + +void UDPComponent::setup() { + this->name_ = App.get_name().c_str(); + if (strlen(this->name_) > 255) { + this->mark_failed(); + this->status_set_error("Device name exceeds 255 chars"); + return; + } + this->resend_ping_key_ = this->ping_pong_enable_; + // restore the upper 32 bits of the rolling code, increment and save. + this->pref_ = global_preferences->make_preference(PREF_HASH, true); + this->pref_.load(&this->rolling_code_[1]); + this->rolling_code_[1]++; + this->pref_.save(&this->rolling_code_[1]); + this->ping_key_ = random_uint32(); + ESP_LOGV(TAG, "Rolling code incremented, upper part now %u", (unsigned) this->rolling_code_[1]); +#ifdef USE_SENSOR + for (auto &sensor : this->sensors_) { + sensor.sensor->add_on_state_callback([this, &sensor](float x) { + this->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.updated = true; + }); + } +#endif + this->should_send_ = this->ping_pong_enable_; +#ifdef USE_SENSOR + this->should_send_ |= !this->sensors_.empty(); +#endif +#ifdef USE_BINARY_SENSOR + this->should_send_ |= !this->binary_sensors_.empty(); +#endif + this->should_listen_ = !this->providers_.empty() || this->is_encrypted_(); + // initialise the header. This is invariant. + add(this->header_, MAGIC_NUMBER); + add(this->header_, this->name_); + // pad to a multiple of 4 bytes + while (this->header_.size() & 0x3) + this->header_.push_back(0); +#if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) + for (const auto &address : this->addresses_) { + struct sockaddr saddr {}; + socket::set_sockaddr(&saddr, sizeof(saddr), address, this->port_); + this->sockaddrs_.push_back(saddr); + } + // set up broadcast socket + if (this->should_send_) { + this->broadcast_socket_ = socket::socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); + if (this->broadcast_socket_ == nullptr) { + this->mark_failed(); + this->status_set_error("Could not create socket"); + return; + } + int enable = 1; + auto err = this->broadcast_socket_->setsockopt(SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)); + if (err != 0) { + this->status_set_warning("Socket unable to set reuseaddr"); + // we can still continue + } + err = this->broadcast_socket_->setsockopt(SOL_SOCKET, SO_BROADCAST, &enable, sizeof(int)); + if (err != 0) { + this->status_set_warning("Socket unable to set broadcast"); + } + } + // create listening socket if we either want to subscribe to providers, or need to listen + // for ping key broadcasts. + if (this->should_listen_) { + this->listen_socket_ = socket::socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); + if (this->listen_socket_ == nullptr) { + this->mark_failed(); + this->status_set_error("Could not create socket"); + return; + } + auto err = this->listen_socket_->setblocking(false); + if (err < 0) { + ESP_LOGE(TAG, "Unable to set nonblocking: errno %d", errno); + this->mark_failed(); + this->status_set_error("Unable to set nonblocking"); + return; + } + int enable = 1; + err = this->listen_socket_->setsockopt(SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)); + if (err != 0) { + this->status_set_warning("Socket unable to set reuseaddr"); + // we can still continue + } + struct sockaddr_in server {}; + + socklen_t sl = socket::set_sockaddr_any((struct sockaddr *) &server, sizeof(server), this->port_); + if (sl == 0) { + ESP_LOGE(TAG, "Socket unable to set sockaddr: errno %d", errno); + this->mark_failed(); + this->status_set_error("Unable to set sockaddr"); + return; + } + + err = this->listen_socket_->bind((struct sockaddr *) &server, sizeof(server)); + if (err != 0) { + ESP_LOGE(TAG, "Socket unable to bind: errno %d", errno); + this->mark_failed(); + this->status_set_error("Unable to bind socket"); + return; + } + } +#else + // 8266 and RP2040 `Duino + for (const auto &address : this->addresses_) { + auto ipaddr = IPAddress(); + ipaddr.fromString(address.c_str()); + this->ipaddrs_.push_back(ipaddr); + } + if (this->should_listen_) + this->udp_client_.begin(this->port_); +#endif +} + +void UDPComponent::init_data_() { + this->data_.clear(); + if (this->rolling_code_enable_) { + add(this->data_, ROLLING_CODE_KEY); + add(this->data_, this->rolling_code_[0]); + add(this->data_, this->rolling_code_[1]); + this->increment_code_(); + } else { + add(this->data_, DATA_KEY); + } + for (auto pkey : this->ping_keys_) { + add(this->data_, PING_KEY); + add(this->data_, pkey.second); + } +} + +void UDPComponent::flush_() { + if (!network::is_connected() || this->data_.empty()) + return; + uint32_t buffer[MAX_PACKET_SIZE / 4]; + memset(buffer, 0, sizeof buffer); + // len must be a multiple of 4 + auto header_len = round4(this->header_.size()) / 4; + auto len = round4(data_.size()) / 4; + memcpy(buffer, this->header_.data(), this->header_.size()); + memcpy(buffer + header_len, this->data_.data(), this->data_.size()); + if (this->is_encrypted_()) { + xxtea_encrypt(buffer + header_len, len, (uint32_t *) this->encryption_key_.data()); + } + auto total_len = (header_len + len) * 4; + this->send_packet_(buffer, total_len); +} + +void UDPComponent::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() > MAX_PACKET_SIZE) { + this->flush_(); + } + add(this->data_, key); + add(this->data_, (uint8_t) data); + add(this->data_, id); +} +void UDPComponent::add_data_(uint8_t key, const char *id, float data) { + FuData udata{.f32 = data}; + this->add_data_(key, id, udata.u32); +} + +void UDPComponent::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() > MAX_PACKET_SIZE) { + this->flush_(); + } + add(this->data_, key); + add(this->data_, data); + add(this->data_, id); +} +void UDPComponent::send_data_(bool all) { + if (!this->should_send_ || !network::is_connected()) + return; + this->init_data_(); +#ifdef USE_SENSOR + for (auto &sensor : this->sensors_) { + if (all || sensor.updated) { + sensor.updated = false; + this->add_data_(SENSOR_KEY, sensor.id, sensor.sensor->get_state()); + } + } +#endif +#ifdef USE_BINARY_SENSOR + for (auto &sensor : this->binary_sensors_) { + if (all || sensor.updated) { + sensor.updated = false; + this->add_binary_data_(BINARY_SENSOR_KEY, sensor.id, sensor.sensor->state); + } + } +#endif + this->flush_(); + this->updated_ = false; + this->resend_data_ = false; +} + +void UDPComponent::update() { + this->updated_ = true; + this->resend_data_ = this->should_send_; + auto now = millis() / 1000; + if (this->last_key_time_ + this->ping_pong_recyle_time_ < now) { + this->resend_ping_key_ = this->ping_pong_enable_; + this->last_key_time_ = now; + } +} + +void UDPComponent::loop() { + uint8_t buf[MAX_PACKET_SIZE]; + if (this->should_listen_) { + for (;;) { +#if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) + auto len = this->listen_socket_->read(buf, sizeof(buf)); +#else + auto len = this->udp_client_.parsePacket(); + if (len > 0) + len = this->udp_client_.read(buf, sizeof(buf)); +#endif + if (len > 0) { + this->process_(buf, len); + continue; + } + break; + } + } + if (this->resend_ping_key_) + this->send_ping_pong_request_(); + if (this->updated_) { + this->send_data_(this->resend_data_); + } +} + +void UDPComponent::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; + } + this->ping_keys_[name] = key; + this->resend_data_ = true; + ESP_LOGV(TAG, "Ping key from %s now %X", name, (unsigned) key); +} + +void UDPComponent::process_ping_request_(const char *name, uint8_t *ptr, size_t len) { + if (len != 4) { + ESP_LOGW(TAG, "Bad ping request"); + return; + } + auto key = get_uint32(ptr); + this->add_key_(name, key); + ESP_LOGV(TAG, "Updated ping key for %s to %08X", name, (unsigned) key); +} + +static bool process_rolling_code(Provider &provider, uint8_t *&buf, const uint8_t *end) { + if (end - buf < 8) + return false; + auto code0 = get_uint32(buf); + auto code1 = get_uint32(buf); + if (code1 < provider.last_code[1] || (code1 == provider.last_code[1] && code0 <= provider.last_code[0])) { + ESP_LOGW(TAG, "Rolling code for %s %08lX:%08lX is old", provider.name, (unsigned long) code1, + (unsigned long) code0); + return false; + } + provider.last_code[0] = code0; + provider.last_code[1] = code1; + return true; +} + +/** + * Process a received packet + */ +void UDPComponent::process_(uint8_t *buf, const size_t len) { + auto ping_key_seen = !this->ping_pong_enable_; + if (len < 8) { + return ESP_LOGV(TAG, "Bad length %zu", len); + } + char namebuf[256]{}; + uint8_t byte; + uint8_t *start_ptr = buf; + const uint8_t *end = buf + len; + FuData rdata{}; + auto magic = get_uint16(buf); + if (magic != MAGIC_NUMBER && magic != MAGIC_PING) + return ESP_LOGV(TAG, "Bad magic %X", magic); + + auto hlen = *buf++; + if (hlen > len - 3) { + return ESP_LOGV(TAG, "Bad hostname length %u > %zu", hlen, len - 3); + } + memcpy(namebuf, buf, hlen); + if (strcmp(this->name_, namebuf) == 0) { + return ESP_LOGV(TAG, "Ignoring our own data"); + } + buf += hlen; + if (magic == MAGIC_PING) + return this->process_ping_request_(namebuf, buf, end - buf); + if (round4(len) != len) { + return ESP_LOGW(TAG, "Bad length %zu", len); + } + hlen = round4(hlen + 3); + buf = start_ptr + hlen; + if (buf == end) { + return ESP_LOGV(TAG, "No data after header"); + } + + if (this->providers_.count(namebuf) == 0) { + return ESP_LOGVV(TAG, "Unknown hostname %s", namebuf); + } + 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; + + ESP_LOGV(TAG, "Found hostname %s", namebuf); +#ifdef USE_SENSOR + auto &sensors = this->remote_sensors_[namebuf]; +#endif +#ifdef USE_BINARY_SENSOR + auto &binary_sensors = this->remote_binary_sensors_[namebuf]; +#endif + + if (!provider.encryption_key.empty()) { + xxtea_decrypt((uint32_t *) buf, (end - buf) / 4, (uint32_t *) provider.encryption_key.data()); + } + byte = *buf++; + if (byte == ROLLING_CODE_KEY) { + if (!process_rolling_code(provider, buf, end)) + return; + } else if (byte != DATA_KEY) { + return ESP_LOGV(TAG, "Expected rolling_key or data_key, got %X", byte); + } + while (buf < end) { + byte = *buf++; + if (byte == ZERO_FILL_KEY) + continue; + if (byte == PING_KEY) { + if (end - buf < 4) { + return ESP_LOGV(TAG, "PING_KEY requires 4 more bytes"); + } + auto key = get_uint32(buf); + if (key == this->ping_key_) { + ping_key_seen = true; + ESP_LOGV(TAG, "Found good ping key %X", (unsigned) key); + } else { + ESP_LOGV(TAG, "Unknown ping key %X", (unsigned) key); + } + continue; + } + if (!ping_key_seen) { + ESP_LOGW(TAG, "Ping key not seen"); + this->resend_ping_key_ = true; + break; + } + if (byte == BINARY_SENSOR_KEY) { + if (end - buf < 3) { + return ESP_LOGV(TAG, "Binary sensor key requires at least 3 more bytes"); + } + rdata.u32 = *buf++; + } else if (byte == SENSOR_KEY) { + if (end - buf < 6) { + return ESP_LOGV(TAG, "Sensor key requires at least 6 more bytes"); + } + rdata.u32 = get_uint32(buf); + } else { + return ESP_LOGW(TAG, "Unknown key byte %X", byte); + } + + hlen = *buf++; + if (end - buf < hlen) { + return ESP_LOGV(TAG, "Name length of %u not available", hlen); + } + memset(namebuf, 0, sizeof namebuf); + memcpy(namebuf, buf, hlen); + ESP_LOGV(TAG, "Found sensor key %d, id %s, data %lX", byte, namebuf, (unsigned long) rdata.u32); + buf += hlen; +#ifdef USE_SENSOR + if (byte == SENSOR_KEY && sensors.count(namebuf) != 0) + sensors[namebuf]->publish_state(rdata.f32); +#endif +#ifdef USE_BINARY_SENSOR + if (byte == BINARY_SENSOR_KEY && binary_sensors.count(namebuf) != 0) + binary_sensors[namebuf]->publish_state(rdata.u32 != 0); +#endif + } +} + +void UDPComponent::dump_config() { + ESP_LOGCONFIG(TAG, "UDP:"); + ESP_LOGCONFIG(TAG, " Port: %u", this->port_); + ESP_LOGCONFIG(TAG, " Encrypted: %s", YESNO(this->is_encrypted_())); + ESP_LOGCONFIG(TAG, " Ping-pong: %s", YESNO(this->ping_pong_enable_)); + for (const auto &address : this->addresses_) + ESP_LOGCONFIG(TAG, " Address: %s", address.c_str()); +#ifdef USE_SENSOR + for (auto sensor : this->sensors_) + ESP_LOGCONFIG(TAG, " Sensor: %s", sensor.id); +#endif +#ifdef USE_BINARY_SENSOR + for (auto sensor : this->binary_sensors_) + ESP_LOGCONFIG(TAG, " Binary Sensor: %s", sensor.id); +#endif + for (const auto &host : this->providers_) { + 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()); +#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()); +#endif + } +} +void UDPComponent::increment_code_() { + if (this->rolling_code_enable_) { + if (++this->rolling_code_[0] == 0) { + this->rolling_code_[1]++; + this->pref_.save(&this->rolling_code_[1]); + } + } +} +void UDPComponent::send_packet_(void *data, size_t len) { +#if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) + for (const auto &saddr : this->sockaddrs_) { + auto result = this->broadcast_socket_->sendto(data, len, 0, &saddr, sizeof(saddr)); + if (result < 0) + ESP_LOGW(TAG, "sendto() error %d", errno); + } +#else + auto iface = IPAddress(0, 0, 0, 0); + for (const auto &saddr : this->ipaddrs_) { + if (this->udp_client_.beginPacketMulticast(saddr, this->port_, iface, 128) != 0) { + this->udp_client_.write((const uint8_t *) data, len); + auto result = this->udp_client_.endPacket(); + if (result == 0) + ESP_LOGW(TAG, "udp.write() error"); + } + } +#endif +} + +void UDPComponent::send_ping_pong_request_() { + if (!this->ping_pong_enable_ || !network::is_connected()) + return; + this->ping_key_ = random_uint32(); + this->ping_header_.clear(); + add(this->ping_header_, MAGIC_PING); + add(this->ping_header_, this->name_); + add(this->ping_header_, this->ping_key_); + this->send_packet_(this->ping_header_.data(), this->ping_header_.size()); + this->resend_ping_key_ = false; + ESP_LOGV(TAG, "Sent new ping request %08X", (unsigned) this->ping_key_); +} +} // namespace udp +} // namespace esphome diff --git a/esphome/components/udp/udp_component.h b/esphome/components/udp/udp_component.h new file mode 100644 index 0000000000..69bf335a90 --- /dev/null +++ b/esphome/components/udp/udp_component.h @@ -0,0 +1,158 @@ +#pragma once + +#include "esphome/core/component.h" +#ifdef USE_SENSOR +#include "esphome/components/sensor/sensor.h" +#endif +#ifdef USE_BINARY_SENSOR +#include "esphome/components/binary_sensor/binary_sensor.h" +#endif +#if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) +#include "esphome/components/socket/socket.h" +#else +#include +#endif +#include +#include + +namespace esphome { +namespace udp { + +struct Provider { + std::vector encryption_key; + const char *name; + uint32_t last_code[2]; +}; + +#ifdef USE_SENSOR +struct Sensor { + sensor::Sensor *sensor; + const char *id; + bool updated; +}; +#endif +#ifdef USE_BINARY_SENSOR +struct BinarySensor { + binary_sensor::BinarySensor *sensor; + const char *id; + bool updated; +}; +#endif + +class UDPComponent : public PollingComponent { + public: + void setup() override; + void loop() override; + void update() override; + void dump_config() override; + +#ifdef USE_SENSOR + void add_sensor(const char *id, sensor::Sensor *sensor) { + Sensor st{sensor, id, true}; + this->sensors_.push_back(st); + } + void add_remote_sensor(const char *hostname, const char *remote_id, sensor::Sensor *sensor) { + this->add_provider(hostname); + this->remote_sensors_[hostname][remote_id] = sensor; + } +#endif +#ifdef USE_BINARY_SENSOR + void add_binary_sensor(const char *id, binary_sensor::BinarySensor *sensor) { + BinarySensor st{sensor, id, true}; + this->binary_sensors_.push_back(st); + } + + void add_remote_binary_sensor(const char *hostname, const char *remote_id, binary_sensor::BinarySensor *sensor) { + this->add_provider(hostname); + this->remote_binary_sensors_[hostname][remote_id] = sensor; + } +#endif + void add_address(const char *addr) { this->addresses_.emplace_back(addr); } + void set_port(uint16_t port) { this->port_ = port; } + float get_setup_priority() const override { return setup_priority::AFTER_WIFI; } + + void add_provider(const char *hostname) { + if (this->providers_.count(hostname) == 0) { + Provider provider; + provider.encryption_key = std::vector{}; + provider.last_code[0] = 0; + provider.last_code[1] = 0; + provider.name = hostname; + this->providers_[hostname] = provider; +#ifdef USE_SENSOR + this->remote_sensors_[hostname] = std::map(); +#endif +#ifdef USE_BINARY_SENSOR + this->remote_binary_sensors_[hostname] = std::map(); +#endif + } + } + + void set_encryption_key(std::vector key) { this->encryption_key_ = std::move(key); } + void set_rolling_code_enable(bool enable) { this->rolling_code_enable_ = enable; } + void set_ping_pong_enable(bool enable) { this->ping_pong_enable_ = enable; } + void set_ping_pong_recycle_time(uint32_t recycle_time) { this->ping_pong_recyle_time_ = recycle_time; } + void set_provider_encryption(const char *name, std::vector key) { + this->providers_[name].encryption_key = std::move(key); + } + + protected: + void send_data_(bool all); + void process_(uint8_t *buf, size_t len); + void flush_(); + void add_data_(uint8_t key, const char *id, float data); + void add_data_(uint8_t key, const char *id, uint32_t data); + void increment_code_(); + void add_binary_data_(uint8_t key, const char *id, bool data); + void init_data_(); + + bool updated_{}; + uint16_t port_{18511}; + uint32_t ping_key_{}; + uint32_t rolling_code_[2]{}; + bool rolling_code_enable_{}; + bool ping_pong_enable_{}; + uint32_t ping_pong_recyle_time_{}; + uint32_t last_key_time_{}; + bool resend_ping_key_{}; + bool resend_data_{}; + bool should_send_{}; + const char *name_{}; + bool should_listen_{}; + ESPPreferenceObject pref_; + +#if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) + std::unique_ptr broadcast_socket_ = nullptr; + std::unique_ptr listen_socket_ = nullptr; + std::vector sockaddrs_{}; +#else + std::vector ipaddrs_{}; + WiFiUDP udp_client_{}; +#endif + std::vector encryption_key_{}; + std::vector addresses_{}; + +#ifdef USE_SENSOR + std::vector sensors_{}; + std::map> remote_sensors_{}; +#endif +#ifdef USE_BINARY_SENSOR + std::vector binary_sensors_{}; + std::map> remote_binary_sensors_{}; +#endif + + std::map providers_{}; + std::vector ping_header_{}; + std::vector header_{}; + std::vector data_{}; + std::map ping_keys_{}; + void add_key_(const char *name, uint32_t key); + void send_ping_pong_request_(); + void send_packet_(void *data, size_t len); + void process_ping_request_(const char *name, uint8_t *ptr, size_t len); + + inline bool is_encrypted_() { return !this->encryption_key_.empty(); } +}; + +} // namespace udp +} // namespace esphome diff --git a/tests/components/udp/common.yaml b/tests/components/udp/common.yaml new file mode 100644 index 0000000000..3bdc19ece5 --- /dev/null +++ b/tests/components/udp/common.yaml @@ -0,0 +1,35 @@ +wifi: + ssid: MySSID + password: password1 + +udp: + update_interval: 5s + encryption: "our key goes here" + rolling_code_enable: true + ping_pong_enable: true + binary_sensors: + - binary_sensor_id1 + - id: binary_sensor_id1 + broadcast_id: other_id + sensors: + - sensor_id1 + - id: sensor_id1 + broadcast_id: other_id + providers: + - name: some-device-name + encryption: "their key goes here" + +sensor: + - platform: template + id: sensor_id1 + - platform: udp + provider: some-device-name + id: our_id + remote_id: some_sensor_id + +binary_sensor: + - platform: udp + provider: unencrypted-device + id: other_binary_sensor_id + - platform: template + id: binary_sensor_id1 diff --git a/tests/components/udp/test.bk72xx-ard.yaml b/tests/components/udp/test.bk72xx-ard.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/udp/test.bk72xx-ard.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/udp/test.esp32-ard.yaml b/tests/components/udp/test.esp32-ard.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/udp/test.esp32-ard.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/udp/test.esp32-c3-ard.yaml b/tests/components/udp/test.esp32-c3-ard.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/udp/test.esp32-c3-ard.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/udp/test.esp32-c3-idf.yaml b/tests/components/udp/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/udp/test.esp32-c3-idf.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/udp/test.esp32-idf.yaml b/tests/components/udp/test.esp32-idf.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/udp/test.esp32-idf.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/udp/test.esp8266-ard.yaml b/tests/components/udp/test.esp8266-ard.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/udp/test.esp8266-ard.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/udp/test.host.yaml b/tests/components/udp/test.host.yaml new file mode 100644 index 0000000000..e735c37e4d --- /dev/null +++ b/tests/components/udp/test.host.yaml @@ -0,0 +1,4 @@ +packages: + common: !include common.yaml + +wifi: !remove diff --git a/tests/components/udp/test.rp2040-ard.yaml b/tests/components/udp/test.rp2040-ard.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/udp/test.rp2040-ard.yaml @@ -0,0 +1 @@ +<<: !include common.yaml From ca2f25e73bc04858d488540373475e600542d415 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Sun, 1 Sep 2024 13:20:31 +0200 Subject: [PATCH 2019/2101] update logs for bluetooth proxy (#7382) --- esphome/components/bluetooth_proxy/bluetooth_proxy.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp b/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp index f188439d0e..bd1c8b7ea4 100644 --- a/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +++ b/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp @@ -54,6 +54,9 @@ bool BluetoothProxy::parse_devices(esp_ble_gap_cb_param_t::ble_scan_result_evt_p } resp.advertisements.push_back(std::move(adv)); + + ESP_LOGV(TAG, "Proxying raw packet from %02X:%02X:%02X:%02X:%02X:%02X, length %d. RSSI: %d dB", result.bda[0], + result.bda[1], result.bda[2], result.bda[3], result.bda[4], result.bda[5], length, result.rssi); } ESP_LOGV(TAG, "Proxying %d packets", count); this->api_connection_->send_bluetooth_le_raw_advertisements_response(resp); @@ -87,6 +90,8 @@ void BluetoothProxy::send_api_packet_(const esp32_ble_tracker::ESPBTDevice &devi void BluetoothProxy::dump_config() { ESP_LOGCONFIG(TAG, "Bluetooth Proxy:"); ESP_LOGCONFIG(TAG, " Active: %s", YESNO(this->active_)); + ESP_LOGCONFIG(TAG, " Connections: %d", this->connections_.size()); + ESP_LOGCONFIG(TAG, " Raw advertisements: %s", YESNO(this->raw_advertisements_)); } int BluetoothProxy::get_bluetooth_connections_free() { From 61223a3cc9df12d07e9c8e288a691ef5cc1b30fd Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Mon, 2 Sep 2024 06:45:40 +1000 Subject: [PATCH 2020/2101] [font] Make display an auto-load, not a dependency (#7366) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/display/__init__.py | 9 +++---- esphome/components/font/__init__.py | 33 +++++++++----------------- esphome/components/font/font.cpp | 5 ++-- esphome/components/font/font.h | 15 +++++++++--- esphome/core/defines.h | 1 + tests/components/font/test.host.yaml | 23 ++++++++++++++++++ 6 files changed, 55 insertions(+), 31 deletions(-) create mode 100644 tests/components/font/test.host.yaml diff --git a/esphome/components/display/__init__.py b/esphome/components/display/__init__.py index c4bb12b75d..32a8b3b090 100644 --- a/esphome/components/display/__init__.py +++ b/esphome/components/display/__init__.py @@ -1,15 +1,15 @@ +from esphome import automation, core +from esphome.automation import maybe_simple_id import esphome.codegen as cg import esphome.config_validation as cv -from esphome import core, automation -from esphome.automation import maybe_simple_id from esphome.const import ( CONF_AUTO_CLEAR_ENABLED, + CONF_FROM, CONF_ID, CONF_LAMBDA, - CONF_PAGES, CONF_PAGE_ID, + CONF_PAGES, CONF_ROTATION, - CONF_FROM, CONF_TO, CONF_TRIGGER_ID, ) @@ -195,3 +195,4 @@ async def display_is_displaying_page_to_code(config, condition_id, template_arg, @coroutine_with_priority(100.0) async def to_code(config): cg.add_global(display_ns.using) + cg.add_define("USE_DISPLAY") diff --git a/esphome/components/font/__init__.py b/esphome/components/font/__init__.py index 7e4674ffda..b5ed02e89a 100644 --- a/esphome/components/font/__init__.py +++ b/esphome/components/font/__init__.py @@ -1,43 +1,35 @@ +import functools import hashlib import logging - -import functools -from pathlib import Path import os +from pathlib import Path import re + from packaging import version import requests -from esphome import core -from esphome import external_files -import esphome.config_validation as cv +from esphome import core, external_files import esphome.codegen as cg -from esphome.helpers import ( - copy_file_if_changed, - cpp_string_escape, -) +import esphome.config_validation as cv from esphome.const import ( CONF_FAMILY, CONF_FILE, CONF_GLYPHS, CONF_ID, + CONF_PATH, CONF_RAW_DATA_ID, - CONF_TYPE, CONF_REFRESH, CONF_SIZE, - CONF_PATH, - CONF_WEIGHT, + CONF_TYPE, CONF_URL, + CONF_WEIGHT, ) -from esphome.core import ( - CORE, - HexInt, -) +from esphome.core import CORE, HexInt +from esphome.helpers import copy_file_if_changed, cpp_string_escape _LOGGER = logging.getLogger(__name__) DOMAIN = "font" -DEPENDENCIES = ["display"] MULTI_CONF = True CODEOWNERS = ["@esphome/core", "@clydebarrow"] @@ -400,10 +392,7 @@ class EFont: def convert_bitmap_to_pillow_font(filepath): - from PIL import ( - PcfFontFile, - BdfFontFile, - ) + from PIL import BdfFontFile, PcfFontFile local_bitmap_font_file = external_files.compute_local_file_dir( DOMAIN, diff --git a/esphome/components/font/font.cpp b/esphome/components/font/font.cpp index 3b62b8ca66..aeca0f5cc0 100644 --- a/esphome/components/font/font.cpp +++ b/esphome/components/font/font.cpp @@ -1,9 +1,8 @@ #include "font.h" +#include "esphome/core/color.h" #include "esphome/core/hal.h" #include "esphome/core/log.h" -#include "esphome/core/color.h" -#include "esphome/components/display/display_buffer.h" namespace esphome { namespace font { @@ -68,6 +67,7 @@ int Font::match_next_glyph(const uint8_t *str, int *match_length) { return -1; return lo; } +#ifdef USE_DISPLAY void Font::measure(const char *str, int *width, int *x_offset, int *baseline, int *height) { *baseline = this->baseline_; *height = this->height_; @@ -164,6 +164,7 @@ void Font::print(int x_start, int y_start, display::Display *display, Color colo i += match_length; } } +#endif } // namespace font } // namespace esphome diff --git a/esphome/components/font/font.h b/esphome/components/font/font.h index 57002cf510..5cde694d91 100644 --- a/esphome/components/font/font.h +++ b/esphome/components/font/font.h @@ -1,8 +1,11 @@ #pragma once -#include "esphome/core/datatypes.h" #include "esphome/core/color.h" -#include "esphome/components/display/display_buffer.h" +#include "esphome/core/datatypes.h" +#include "esphome/core/defines.h" +#ifdef USE_DISPLAY +#include "esphome/components/display/display.h" +#endif namespace esphome { namespace font { @@ -38,7 +41,11 @@ class Glyph { const GlyphData *glyph_data_; }; -class Font : public display::BaseFont { +class Font +#ifdef USE_DISPLAY + : public display::BaseFont +#endif +{ public: /** Construct the font with the given glyphs. * @@ -50,9 +57,11 @@ class Font : public display::BaseFont { int match_next_glyph(const uint8_t *str, int *match_length); +#ifdef USE_DISPLAY void print(int x_start, int y_start, display::Display *display, Color color, const char *text, Color background) override; void measure(const char *str, int *width, int *x_offset, int *baseline, int *height) override; +#endif inline int get_baseline() { return this->baseline_; } inline int get_height() { return this->height_; } inline int get_bpp() { return this->bpp_; } diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 52cf7d4dd0..ffd5cc6f1b 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -28,6 +28,7 @@ #define USE_DATETIME_DATETIME #define USE_DATETIME_TIME #define USE_DEEP_SLEEP +#define USE_DISPLAY #define USE_EVENT #define USE_FAN #define USE_GRAPH diff --git a/tests/components/font/test.host.yaml b/tests/components/font/test.host.yaml new file mode 100644 index 0000000000..017328ec83 --- /dev/null +++ b/tests/components/font/test.host.yaml @@ -0,0 +1,23 @@ +font: + - file: "gfonts://Roboto" + id: roboto + size: 20 + glyphs: "0123456789." + extras: + - file: "gfonts://Roboto" + glyphs: ["\u00C4", "\u00C5", "\U000000C7"] + - file: "gfonts://Roboto" + id: roboto_web + size: 20 + - file: "https://github.com/IdreesInc/Monocraft/releases/download/v3.0/Monocraft.ttf" + id: monocraft + size: 20 + - file: + type: web + url: "https://github.com/IdreesInc/Monocraft/releases/download/v3.0/Monocraft.ttf" + id: monocraft2 + size: 24 + - file: $component_dir/Monocraft.ttf + id: monocraft3 + size: 28 + From 3a7aabb2eb3fe58c2925cd3f5e1f605e15797b1a Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 2 Sep 2024 10:36:18 +1200 Subject: [PATCH 2021/2101] Bump Dockerfile dependencies (#7386) --- docker/Dockerfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 16f37274c6..4393d5a447 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -34,8 +34,8 @@ RUN \ python3-wheel=0.38.4-2 \ iputils-ping=3:20221126-1 \ git=1:2.39.2-1.1 \ - curl=7.88.1-10+deb12u6 \ - openssh-client=1:9.2p1-2+deb12u2 \ + curl=7.88.1-10+deb12u7 \ + openssh-client=1:9.2p1-2+deb12u3 \ python3-cffi=1.15.1-5 \ libcairo2=1.16.0-7 \ libmagic1=1:5.44-3 \ @@ -49,7 +49,7 @@ RUN \ zlib1g-dev=1:1.2.13.dfsg-1 \ libjpeg-dev=1:2.1.5-2 \ libfreetype-dev=2.12.1+dfsg-5+deb12u3 \ - libssl-dev=3.0.13-1~deb12u1 \ + libssl-dev=3.0.14-1~deb12u1 \ libffi-dev=3.4.4-1 \ libopenjp2-7=2.5.0-2 \ libtiff6=4.5.0-6+deb12u1 \ From 6490fc9c620d602fae2957f31e2756be886354ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Skowro=C5=84ski?= Date: Mon, 2 Sep 2024 03:56:35 +0200 Subject: [PATCH 2022/2101] CH422G support (#7356) --- CODEOWNERS | 1 + esphome/components/ch422g/__init__.py | 67 ++++++++++ esphome/components/ch422g/ch422g.cpp | 122 ++++++++++++++++++ esphome/components/ch422g/ch422g.h | 70 ++++++++++ tests/components/ch422g/common.yaml | 20 +++ tests/components/ch422g/test.esp32-ard.yaml | 6 + .../components/ch422g/test.esp32-c3-ard.yaml | 6 + .../components/ch422g/test.esp32-c3-idf.yaml | 6 + tests/components/ch422g/test.esp32-idf.yaml | 6 + tests/components/ch422g/test.esp8266-ard.yaml | 6 + tests/components/ch422g/test.rp2040-ard.yaml | 6 + 11 files changed, 316 insertions(+) create mode 100644 esphome/components/ch422g/__init__.py create mode 100644 esphome/components/ch422g/ch422g.cpp create mode 100644 esphome/components/ch422g/ch422g.h create mode 100644 tests/components/ch422g/common.yaml create mode 100644 tests/components/ch422g/test.esp32-ard.yaml create mode 100644 tests/components/ch422g/test.esp32-c3-ard.yaml create mode 100644 tests/components/ch422g/test.esp32-c3-idf.yaml create mode 100644 tests/components/ch422g/test.esp32-idf.yaml create mode 100644 tests/components/ch422g/test.esp8266-ard.yaml create mode 100644 tests/components/ch422g/test.rp2040-ard.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 807829eafd..ab11086980 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -83,6 +83,7 @@ esphome/components/cap1188/* @mreditor97 esphome/components/captive_portal/* @OttoWinter esphome/components/ccs811/* @habbie esphome/components/cd74hc4067/* @asoehlke +esphome/components/ch422g/* @jesterret esphome/components/climate/* @esphome/core esphome/components/climate_ir/* @glmnet esphome/components/color_temperature/* @jesserockz diff --git a/esphome/components/ch422g/__init__.py b/esphome/components/ch422g/__init__.py new file mode 100644 index 0000000000..cf8b5f65d3 --- /dev/null +++ b/esphome/components/ch422g/__init__.py @@ -0,0 +1,67 @@ +from esphome import pins +import esphome.codegen as cg +from esphome.components import i2c +import esphome.config_validation as cv +from esphome.const import ( + CONF_ID, + CONF_INPUT, + CONF_INVERTED, + CONF_MODE, + CONF_NUMBER, + CONF_OUTPUT, + CONF_RESTORE_VALUE, +) + +CODEOWNERS = ["@jesterret"] +DEPENDENCIES = ["i2c"] +MULTI_CONF = True +ch422g_ns = cg.esphome_ns.namespace("ch422g") + +CH422GComponent = ch422g_ns.class_("CH422GComponent", cg.Component, i2c.I2CDevice) +CH422GGPIOPin = ch422g_ns.class_( + "CH422GGPIOPin", cg.GPIOPin, cg.Parented.template(CH422GComponent) +) + +CONF_CH422G = "ch422g" +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.Required(CONF_ID): cv.declare_id(CH422GComponent), + cv.Optional(CONF_RESTORE_VALUE, default=False): cv.boolean, + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(i2c.i2c_device_schema(0x24)) +) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + cg.add(var.set_restore_value(config[CONF_RESTORE_VALUE])) + await cg.register_component(var, config) + await i2c.register_i2c_device(var, config) + + +CH422G_PIN_SCHEMA = pins.gpio_base_schema( + CH422GGPIOPin, + cv.int_range(min=0, max=7), + modes=[CONF_INPUT, CONF_OUTPUT], +).extend( + { + cv.Required(CONF_CH422G): cv.use_id(CH422GComponent), + } +) + + +@pins.PIN_SCHEMA_REGISTRY.register(CONF_CH422G, CH422G_PIN_SCHEMA) +async def ch422g_pin_to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + parent = await cg.get_variable(config[CONF_CH422G]) + + 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/ch422g/ch422g.cpp b/esphome/components/ch422g/ch422g.cpp new file mode 100644 index 0000000000..25038991ed --- /dev/null +++ b/esphome/components/ch422g/ch422g.cpp @@ -0,0 +1,122 @@ +#include "ch422g.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace ch422g { + +const uint8_t CH422G_REG_IN = 0x26; +const uint8_t CH422G_REG_OUT = 0x38; +const uint8_t OUT_REG_DEFAULT_VAL = 0xdf; + +static const char *const TAG = "ch422g"; + +void CH422GComponent::setup() { + ESP_LOGCONFIG(TAG, "Setting up CH422G..."); + // Test to see if device exists + if (!this->read_inputs_()) { + ESP_LOGE(TAG, "CH422G not detected at 0x%02X", this->address_); + this->mark_failed(); + return; + } + + // restore defaults over whatever got saved on last boot + if (!this->restore_value_) { + this->write_output_(OUT_REG_DEFAULT_VAL); + } + + ESP_LOGD(TAG, "Initialization complete. Warning: %d, Error: %d", this->status_has_warning(), + this->status_has_error()); +} + +void CH422GComponent::loop() { + // Clear all the previously read flags. + this->pin_read_cache_ = 0x00; +} + +void CH422GComponent::dump_config() { + ESP_LOGCONFIG(TAG, "CH422G:"); + LOG_I2C_DEVICE(this) + if (this->is_failed()) { + ESP_LOGE(TAG, "Communication with CH422G failed!"); + } +} + +// ch422g doesn't have any flag support (needs docs?) +void CH422GComponent::pin_mode(uint8_t pin, gpio::Flags flags) {} + +bool CH422GComponent::digital_read(uint8_t pin) { + if (this->pin_read_cache_ == 0 || this->pin_read_cache_ & (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_cache_ |= (1 << pin); + return this->state_mask_ & (1 << pin); +} + +void CH422GComponent::digital_write(uint8_t pin, bool value) { + if (value) { + this->write_output_(this->state_mask_ | (1 << pin)); + } else { + this->write_output_(this->state_mask_ & ~(1 << pin)); + } +} + +bool CH422GComponent::read_inputs_() { + if (this->is_failed()) { + return false; + } + + uint8_t temp = 0; + if ((this->last_error_ = this->read(&temp, 1)) != esphome::i2c::ERROR_OK) { + this->status_set_warning(str_sprintf("read_inputs_(): I2C I/O error: %d", (int) this->last_error_).c_str()); + return false; + } + + uint8_t output = 0; + if ((this->last_error_ = this->bus_->read(CH422G_REG_IN, &output, 1)) != esphome::i2c::ERROR_OK) { + this->status_set_warning(str_sprintf("read_inputs_(): I2C I/O error: %d", (int) this->last_error_).c_str()); + return false; + } + + this->state_mask_ = output; + this->status_clear_warning(); + + return true; +} + +bool CH422GComponent::write_output_(uint8_t value) { + const uint8_t temp = 1; + if ((this->last_error_ = this->write(&temp, 1, false)) != esphome::i2c::ERROR_OK) { + this->status_set_warning(str_sprintf("write_output_(): I2C I/O error: %d", (int) this->last_error_).c_str()); + return false; + } + + uint8_t write_mask = value; + if ((this->last_error_ = this->bus_->write(CH422G_REG_OUT, &write_mask, 1)) != esphome::i2c::ERROR_OK) { + this->status_set_warning( + str_sprintf("write_output_(): I2C I/O error: %d for write_mask: %d", (int) this->last_error_, (int) write_mask) + .c_str()); + return false; + } + + this->state_mask_ = value; + this->status_clear_warning(); + return true; +} + +float CH422GComponent::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 CH422GComponent::get_loop_priority() const { return 9.0f; } // Just after WIFI + +void CH422GGPIOPin::setup() { pin_mode(flags_); } +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_; } + +void CH422GGPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value != this->inverted_); } +std::string CH422GGPIOPin::dump_summary() const { return str_sprintf("EXIO%u via CH422G", pin_); } + +} // namespace ch422g +} // namespace esphome diff --git a/esphome/components/ch422g/ch422g.h b/esphome/components/ch422g/ch422g.h new file mode 100644 index 0000000000..781df65437 --- /dev/null +++ b/esphome/components/ch422g/ch422g.h @@ -0,0 +1,70 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/core/hal.h" +#include "esphome/components/i2c/i2c.h" + +namespace esphome { +namespace ch422g { + +class CH422GComponent : public Component, public i2c::I2CDevice { + public: + CH422GComponent() = 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; + + void set_restore_value(bool restore_value) { this->restore_value_ = restore_value; } + + protected: + bool read_inputs_(); + + bool write_output_(uint8_t value); + + /// The mask to write as output state - 1 means HIGH, 0 means LOW + uint8_t state_mask_{0x00}; + /// Flags to check if read previously during this loop + uint8_t pin_read_cache_ = {0x00}; + /// Storage for last I2C error seen + esphome::i2c::ErrorCode last_error_; + /// Whether we want to override stored values on expander + bool restore_value_{false}; +}; + +/// Helper class to expose a CH422G pin as an internal input GPIO pin. +class CH422GGPIOPin : public GPIOPin { + public: + void setup() override; + void pin_mode(gpio::Flags flags) override; + bool digital_read() override; + void digital_write(bool value) override; + std::string dump_summary() const override; + + void set_parent(CH422GComponent *parent) { parent_ = parent; } + void set_pin(uint8_t pin) { pin_ = pin; } + void set_inverted(bool inverted) { inverted_ = inverted; } + void set_flags(gpio::Flags flags) { flags_ = flags; } + + protected: + CH422GComponent *parent_; + uint8_t pin_; + bool inverted_; + gpio::Flags flags_; +}; + +} // namespace ch422g +} // namespace esphome diff --git a/tests/components/ch422g/common.yaml b/tests/components/ch422g/common.yaml new file mode 100644 index 0000000000..02061bda59 --- /dev/null +++ b/tests/components/ch422g/common.yaml @@ -0,0 +1,20 @@ +ch422g: + - id: ch422g_hub + address: 0x24 + +binary_sensor: + - platform: gpio + id: ch422g_input + name: CH422G Binary Sensor + pin: + ch422g: ch422g_hub + number: 1 + mode: INPUT + inverted: true + - platform: gpio + id: ch422g_output + pin: + ch422g: ch422g_hub + number: 0 + mode: OUTPUT + inverted: false diff --git a/tests/components/ch422g/test.esp32-ard.yaml b/tests/components/ch422g/test.esp32-ard.yaml new file mode 100644 index 0000000000..cd3f1bbeef --- /dev/null +++ b/tests/components/ch422g/test.esp32-ard.yaml @@ -0,0 +1,6 @@ +i2c: + - id: i2c_ch422g + scl: 16 + sda: 17 + +<<: !include common.yaml diff --git a/tests/components/ch422g/test.esp32-c3-ard.yaml b/tests/components/ch422g/test.esp32-c3-ard.yaml new file mode 100644 index 0000000000..cd822cb308 --- /dev/null +++ b/tests/components/ch422g/test.esp32-c3-ard.yaml @@ -0,0 +1,6 @@ +i2c: + - id: i2c_ch422g + scl: 5 + sda: 4 + +<<: !include common.yaml diff --git a/tests/components/ch422g/test.esp32-c3-idf.yaml b/tests/components/ch422g/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..cd822cb308 --- /dev/null +++ b/tests/components/ch422g/test.esp32-c3-idf.yaml @@ -0,0 +1,6 @@ +i2c: + - id: i2c_ch422g + scl: 5 + sda: 4 + +<<: !include common.yaml diff --git a/tests/components/ch422g/test.esp32-idf.yaml b/tests/components/ch422g/test.esp32-idf.yaml new file mode 100644 index 0000000000..cd3f1bbeef --- /dev/null +++ b/tests/components/ch422g/test.esp32-idf.yaml @@ -0,0 +1,6 @@ +i2c: + - id: i2c_ch422g + scl: 16 + sda: 17 + +<<: !include common.yaml diff --git a/tests/components/ch422g/test.esp8266-ard.yaml b/tests/components/ch422g/test.esp8266-ard.yaml new file mode 100644 index 0000000000..cd822cb308 --- /dev/null +++ b/tests/components/ch422g/test.esp8266-ard.yaml @@ -0,0 +1,6 @@ +i2c: + - id: i2c_ch422g + scl: 5 + sda: 4 + +<<: !include common.yaml diff --git a/tests/components/ch422g/test.rp2040-ard.yaml b/tests/components/ch422g/test.rp2040-ard.yaml new file mode 100644 index 0000000000..cd822cb308 --- /dev/null +++ b/tests/components/ch422g/test.rp2040-ard.yaml @@ -0,0 +1,6 @@ +i2c: + - id: i2c_ch422g + scl: 5 + sda: 4 + +<<: !include common.yaml From fc930327b48989eb31e1cb38f45b5aeafb09c042 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20BOU=C3=89?= Date: Mon, 2 Sep 2024 04:30:13 +0200 Subject: [PATCH 2023/2101] [rpi_dpi_rgb] Add enable_pin and reset_display method to driver (#7383) Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> --- esphome/components/rpi_dpi_rgb/display.py | 6 ++++++ esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp | 18 ++++++++++++++++++ esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.h | 3 +++ 3 files changed, 27 insertions(+) diff --git a/esphome/components/rpi_dpi_rgb/display.py b/esphome/components/rpi_dpi_rgb/display.py index 969b9db78e..6cc8d2c27b 100644 --- a/esphome/components/rpi_dpi_rgb/display.py +++ b/esphome/components/rpi_dpi_rgb/display.py @@ -3,6 +3,7 @@ import esphome.config_validation as cv from esphome import pins from esphome.components import display from esphome.const import ( + CONF_ENABLE_PIN, CONF_HSYNC_PIN, CONF_RESET_PIN, CONF_DATA_PINS, @@ -112,6 +113,7 @@ CONFIG_SCHEMA = cv.All( cv.Required(CONF_PCLK_PIN): pins.internal_gpio_output_pin_schema, cv.Required(CONF_HSYNC_PIN): pins.internal_gpio_output_pin_schema, cv.Required(CONF_VSYNC_PIN): pins.internal_gpio_output_pin_schema, + cv.Optional(CONF_ENABLE_PIN): pins.gpio_output_pin_schema, cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, cv.Optional(CONF_HSYNC_PULSE_WIDTH, default=10): cv.int_, cv.Optional(CONF_HSYNC_BACK_PORCH, default=10): cv.int_, @@ -164,6 +166,10 @@ async def to_code(config): cg.add(var.add_data_pin(data_pin, index)) index += 1 + if enable_pin := config.get(CONF_ENABLE_PIN): + enable = await cg.gpio_pin_expression(enable_pin) + cg.add(var.set_enable_pin(enable)) + 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/rpi_dpi_rgb/rpi_dpi_rgb.cpp b/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp index 2ffdb3272a..f173a2ec44 100644 --- a/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp +++ b/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp @@ -104,12 +104,30 @@ void RpiDpiRgb::dump_config() { ESP_LOGCONFIG(TAG, " Height: %u", this->height_); ESP_LOGCONFIG(TAG, " Width: %u", this->width_); LOG_PIN(" DE Pin: ", this->de_pin_); + 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()); } +void RpiDpiRgb::reset_display_() const { + if (this->reset_pin_ != nullptr) { + this->reset_pin_->setup(); + this->reset_pin_->digital_write(false); + if (this->enable_pin_ != nullptr) { + this->enable_pin_->setup(); + this->enable_pin_->digital_write(false); + } + delay(1); + this->reset_pin_->digital_write(true); + if (this->enable_pin_ != nullptr) { + delay(11); + this->enable_pin_->digital_write(true); + } + } +} + } // namespace rpi_dpi_rgb } // namespace esphome diff --git a/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.h b/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.h index 0319b46391..6d9d6d4ae9 100644 --- a/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.h +++ b/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.h @@ -36,6 +36,7 @@ class RpiDpiRgb : public display::Display { void set_pclk_pin(InternalGPIOPin *pclk_pin) { this->pclk_pin_ = pclk_pin; } void set_vsync_pin(InternalGPIOPin *vsync_pin) { this->vsync_pin_ = vsync_pin; } void set_hsync_pin(InternalGPIOPin *hsync_pin) { this->hsync_pin_ = hsync_pin; } + void set_enable_pin(GPIOPin *enable_pin) { this->enable_pin_ = enable_pin; } void set_reset_pin(GPIOPin *reset_pin) { this->reset_pin_ = reset_pin; } void set_width(uint16_t width) { this->width_ = width; } void set_dimensions(uint16_t width, uint16_t height) { @@ -62,10 +63,12 @@ class RpiDpiRgb : public display::Display { protected: int get_width_internal() override { return this->width_; } int get_height_internal() override { return this->height_; } + void reset_display_() const; InternalGPIOPin *de_pin_{nullptr}; InternalGPIOPin *pclk_pin_{nullptr}; InternalGPIOPin *hsync_pin_{nullptr}; InternalGPIOPin *vsync_pin_{nullptr}; + GPIOPin *enable_pin_{nullptr}; GPIOPin *reset_pin_{nullptr}; InternalGPIOPin *data_pins_[16] = {}; uint16_t hsync_front_porch_ = 8; From 094c867fba5e329af1f6795318dee1936ccf5b35 Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Mon, 2 Sep 2024 04:32:34 +0200 Subject: [PATCH 2024/2101] Enable IPv6 when manual IPv4 is enabled (#7381) --- esphome/components/ethernet/ethernet_component.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index 962a864a29..fdb6eb2da0 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -472,13 +472,13 @@ void EthernetComponent::start_connect_() { if (err != ESP_ERR_ESP_NETIF_DHCP_ALREADY_STARTED) { ESPHL_ERROR_CHECK(err, "DHCPC start error"); } -#if USE_NETWORK_IPV6 - err = esp_netif_create_ip6_linklocal(this->eth_netif_); - if (err != ESP_OK) { - ESPHL_ERROR_CHECK(err, "Enable IPv6 link local failed"); - } -#endif /* USE_NETWORK_IPV6 */ } +#if USE_NETWORK_IPV6 + err = esp_netif_create_ip6_linklocal(this->eth_netif_); + if (err != ESP_OK) { + ESPHL_ERROR_CHECK(err, "Enable IPv6 link local failed"); + } +#endif /* USE_NETWORK_IPV6 */ this->connect_begin_ = millis(); this->status_set_warning(); From 854bafbd4a86316168717af4c1ebc72b55da48a9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Sep 2024 14:33:58 +1200 Subject: [PATCH 2025/2101] Bump actions/upload-artifact from 4.3.4 to 4.4.0 (#7379) 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 937c7aac90..7895e7624a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -141,7 +141,7 @@ jobs: echo name=$(cat /tmp/platform) >> $GITHUB_OUTPUT - name: Upload digests - uses: actions/upload-artifact@v4.3.4 + uses: actions/upload-artifact@v4.4.0 with: name: digests-${{ steps.sanitize.outputs.name }} path: /tmp/digests From ca8e45cf4c35785ac4417a3349825d26e21ad305 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 2 Sep 2024 19:11:21 +1200 Subject: [PATCH 2026/2101] [core] Only clean build files with esp-idf (#7388) --- esphome/storage_json.py | 16 ++++++++++++++++ esphome/writer.py | 6 +++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/esphome/storage_json.py b/esphome/storage_json.py index e2e7514904..2d12ee01a0 100644 --- a/esphome/storage_json.py +++ b/esphome/storage_json.py @@ -48,6 +48,8 @@ class StorageJSON: firmware_bin_path: str, loaded_integrations: set[str], no_mdns: bool, + framework: str | None = None, + core_platform: str | None = None, ) -> None: # Version of the storage JSON schema assert storage_version is None or isinstance(storage_version, int) @@ -78,6 +80,10 @@ class StorageJSON: self.loaded_integrations = loaded_integrations # Is mDNS disabled self.no_mdns = no_mdns + # The framework used to compile the firmware + self.framework = framework + # The core platform of this firmware. Like "esp32", "rp2040", "host" etc. + self.core_platform = core_platform def as_dict(self): return { @@ -94,6 +100,8 @@ class StorageJSON: "firmware_bin_path": self.firmware_bin_path, "loaded_integrations": sorted(self.loaded_integrations), "no_mdns": self.no_mdns, + "framework": self.framework, + "core_platform": self.core_platform, } def to_json(self): @@ -127,6 +135,8 @@ class StorageJSON: and CONF_DISABLED in esph.config[CONF_MDNS] and esph.config[CONF_MDNS][CONF_DISABLED] is True ), + framework=esph.target_framework, + core_platform=esph.target_platform, ) @staticmethod @@ -147,6 +157,8 @@ class StorageJSON: firmware_bin_path=None, loaded_integrations=set(), no_mdns=False, + framework=None, + core_platform=platform.lower(), ) @staticmethod @@ -168,6 +180,8 @@ class StorageJSON: firmware_bin_path = storage.get("firmware_bin_path") loaded_integrations = set(storage.get("loaded_integrations", [])) no_mdns = storage.get("no_mdns", False) + framework = storage.get("framework") + core_platform = storage.get("core_platform") return StorageJSON( storage_version, name, @@ -182,6 +196,8 @@ class StorageJSON: firmware_bin_path, loaded_integrations, no_mdns, + framework, + core_platform, ) @staticmethod diff --git a/esphome/writer.py b/esphome/writer.py index 57435d3463..79ee72996c 100644 --- a/esphome/writer.py +++ b/esphome/writer.py @@ -9,6 +9,7 @@ from esphome.config import iter_component_configs, iter_components from esphome.const import ( ENV_NOGITIGNORE, HEADER_FILE_EXTENSIONS, + PLATFORM_ESP32, SOURCE_FILE_EXTENSIONS, __version__, ) @@ -107,7 +108,10 @@ def storage_should_clean(old: StorageJSON, new: StorageJSON) -> bool: if old.build_path != new.build_path: return True if old.loaded_integrations != new.loaded_integrations: - return True + if new.core_platform == PLATFORM_ESP32: + from esphome.components.esp32 import FRAMEWORK_ESP_IDF + + return new.framework == FRAMEWORK_ESP_IDF return False From 91c7c436827ef7c538b8ee1be74dd00a2179f2d6 Mon Sep 17 00:00:00 2001 From: Mathieu Rene Date: Mon, 2 Sep 2024 17:26:10 -0400 Subject: [PATCH 2027/2101] Fix build for esp32h2 using esp-idf 5.3 (#7393) --- esphome/components/debug/debug_esp32.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/esphome/components/debug/debug_esp32.cpp b/esphome/components/debug/debug_esp32.cpp index cfdfdd2a61..34aea9e26b 100644 --- a/esphome/components/debug/debug_esp32.cpp +++ b/esphome/components/debug/debug_esp32.cpp @@ -16,6 +16,8 @@ #include #elif defined(USE_ESP32_VARIANT_ESP32S3) #include +#elif defined(USE_ESP32_VARIANT_ESP32H2) +#include #endif #ifdef USE_ARDUINO #include @@ -61,7 +63,7 @@ std::string DebugComponent::get_reset_reason_() { case RTCWDT_SYS_RESET: reset_reason = "RTC Watch Dog Reset Digital Core"; break; -#if !defined(USE_ESP32_VARIANT_ESP32C6) +#if !defined(USE_ESP32_VARIANT_ESP32C6) && !defined(USE_ESP32_VARIANT_ESP32H2) case INTRUSION_RESET: reset_reason = "Intrusion Reset CPU"; break; From 816b060edcdf5c579b7df0c5a7fecf329c48759d Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 29 Aug 2024 05:07:31 +1200 Subject: [PATCH 2028/2101] [datetime] Fix templated args (#7368) --- esphome/components/datetime/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/datetime/__init__.py b/esphome/components/datetime/__init__.py index 4fda97c5bc..5429121d56 100644 --- a/esphome/components/datetime/__init__.py +++ b/esphome/components/datetime/__init__.py @@ -186,7 +186,7 @@ async def datetime_date_set_to_code(config, action_id, template_arg, args): date_config = config[CONF_DATE] if cg.is_template(date_config): - template_ = await cg.templatable(date_config, [], cg.ESPTime) + template_ = await cg.templatable(date_config, args, cg.ESPTime) cg.add(action_var.set_date(template_)) else: date_struct = cg.StructInitializer( @@ -217,7 +217,7 @@ async def datetime_time_set_to_code(config, action_id, template_arg, args): time_config = config[CONF_TIME] if cg.is_template(time_config): - template_ = await cg.templatable(time_config, [], cg.ESPTime) + template_ = await cg.templatable(time_config, args, cg.ESPTime) cg.add(action_var.set_time(template_)) else: time_struct = cg.StructInitializer( @@ -248,7 +248,7 @@ async def datetime_datetime_set_to_code(config, action_id, template_arg, args): datetime_config = config[CONF_DATETIME] if cg.is_template(datetime_config): - template_ = await cg.templatable(datetime_config, [], cg.ESPTime) + template_ = await cg.templatable(datetime_config, args, cg.ESPTime) cg.add(action_var.set_datetime(template_)) else: datetime_struct = cg.StructInitializer( From 04ec6c5677201b47e74049509487e61b13bef246 Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Mon, 2 Sep 2024 04:32:34 +0200 Subject: [PATCH 2029/2101] Enable IPv6 when manual IPv4 is enabled (#7381) --- esphome/components/ethernet/ethernet_component.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index 962a864a29..fdb6eb2da0 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -472,13 +472,13 @@ void EthernetComponent::start_connect_() { if (err != ESP_ERR_ESP_NETIF_DHCP_ALREADY_STARTED) { ESPHL_ERROR_CHECK(err, "DHCPC start error"); } -#if USE_NETWORK_IPV6 - err = esp_netif_create_ip6_linklocal(this->eth_netif_); - if (err != ESP_OK) { - ESPHL_ERROR_CHECK(err, "Enable IPv6 link local failed"); - } -#endif /* USE_NETWORK_IPV6 */ } +#if USE_NETWORK_IPV6 + err = esp_netif_create_ip6_linklocal(this->eth_netif_); + if (err != ESP_OK) { + ESPHL_ERROR_CHECK(err, "Enable IPv6 link local failed"); + } +#endif /* USE_NETWORK_IPV6 */ this->connect_begin_ = millis(); this->status_set_warning(); From c9c5ca28d20f68f6412c0997c345217da2f971fd Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 2 Sep 2024 19:11:21 +1200 Subject: [PATCH 2030/2101] [core] Only clean build files with esp-idf (#7388) --- esphome/storage_json.py | 16 ++++++++++++++++ esphome/writer.py | 6 +++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/esphome/storage_json.py b/esphome/storage_json.py index e2e7514904..2d12ee01a0 100644 --- a/esphome/storage_json.py +++ b/esphome/storage_json.py @@ -48,6 +48,8 @@ class StorageJSON: firmware_bin_path: str, loaded_integrations: set[str], no_mdns: bool, + framework: str | None = None, + core_platform: str | None = None, ) -> None: # Version of the storage JSON schema assert storage_version is None or isinstance(storage_version, int) @@ -78,6 +80,10 @@ class StorageJSON: self.loaded_integrations = loaded_integrations # Is mDNS disabled self.no_mdns = no_mdns + # The framework used to compile the firmware + self.framework = framework + # The core platform of this firmware. Like "esp32", "rp2040", "host" etc. + self.core_platform = core_platform def as_dict(self): return { @@ -94,6 +100,8 @@ class StorageJSON: "firmware_bin_path": self.firmware_bin_path, "loaded_integrations": sorted(self.loaded_integrations), "no_mdns": self.no_mdns, + "framework": self.framework, + "core_platform": self.core_platform, } def to_json(self): @@ -127,6 +135,8 @@ class StorageJSON: and CONF_DISABLED in esph.config[CONF_MDNS] and esph.config[CONF_MDNS][CONF_DISABLED] is True ), + framework=esph.target_framework, + core_platform=esph.target_platform, ) @staticmethod @@ -147,6 +157,8 @@ class StorageJSON: firmware_bin_path=None, loaded_integrations=set(), no_mdns=False, + framework=None, + core_platform=platform.lower(), ) @staticmethod @@ -168,6 +180,8 @@ class StorageJSON: firmware_bin_path = storage.get("firmware_bin_path") loaded_integrations = set(storage.get("loaded_integrations", [])) no_mdns = storage.get("no_mdns", False) + framework = storage.get("framework") + core_platform = storage.get("core_platform") return StorageJSON( storage_version, name, @@ -182,6 +196,8 @@ class StorageJSON: firmware_bin_path, loaded_integrations, no_mdns, + framework, + core_platform, ) @staticmethod diff --git a/esphome/writer.py b/esphome/writer.py index 57435d3463..79ee72996c 100644 --- a/esphome/writer.py +++ b/esphome/writer.py @@ -9,6 +9,7 @@ from esphome.config import iter_component_configs, iter_components from esphome.const import ( ENV_NOGITIGNORE, HEADER_FILE_EXTENSIONS, + PLATFORM_ESP32, SOURCE_FILE_EXTENSIONS, __version__, ) @@ -107,7 +108,10 @@ def storage_should_clean(old: StorageJSON, new: StorageJSON) -> bool: if old.build_path != new.build_path: return True if old.loaded_integrations != new.loaded_integrations: - return True + if new.core_platform == PLATFORM_ESP32: + from esphome.components.esp32 import FRAMEWORK_ESP_IDF + + return new.framework == FRAMEWORK_ESP_IDF return False From e5e06a12ef22aeec591880ec53de572bad1f8a3b Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 3 Sep 2024 09:57:28 +1200 Subject: [PATCH 2031/2101] Bump version to 2024.8.2 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index b27949bf29..00f2d6a13b 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.8.1" +__version__ = "2024.8.2" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 01c50432c91b871a91a403778250d5b21121cd2a Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Tue, 3 Sep 2024 00:16:59 +0200 Subject: [PATCH 2032/2101] Bump mDNS and follow ruff's suggestions (#7308) --- esphome/components/mdns/__init__.py | 12 ++++++------ esphome/idf_component.yml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/esphome/components/mdns/__init__.py b/esphome/components/mdns/__init__.py index fb90986314..dd68fbb93c 100644 --- a/esphome/components/mdns/__init__.py +++ b/esphome/components/mdns/__init__.py @@ -1,17 +1,17 @@ +import esphome.codegen as cg +from esphome.components.esp32 import add_idf_component +import esphome.config_validation as cv from esphome.const import ( + CONF_DISABLED, CONF_ID, CONF_PORT, CONF_PROTOCOL, - CONF_SERVICES, CONF_SERVICE, + CONF_SERVICES, KEY_CORE, KEY_FRAMEWORK_VERSION, - CONF_DISABLED, ) -import esphome.codegen as cg -import esphome.config_validation as cv from esphome.core import CORE, coroutine_with_priority -from esphome.components.esp32 import add_idf_component CODEOWNERS = ["@esphome/core"] DEPENDENCIES = ["network"] @@ -91,7 +91,7 @@ async def to_code(config): add_idf_component( name="mdns", repo="https://github.com/espressif/esp-protocols.git", - ref="mdns-v1.2.5", + ref="mdns-v1.3.2", path="components/mdns", ) diff --git a/esphome/idf_component.yml b/esphome/idf_component.yml index 5f4701b5a3..c79ba1b0ed 100644 --- a/esphome/idf_component.yml +++ b/esphome/idf_component.yml @@ -7,7 +7,7 @@ dependencies: version: v2.0.9 mdns: git: https://github.com/espressif/esp-protocols.git - version: mdns-v1.2.5 + version: mdns-v1.3.2 path: components/mdns rules: - if: "idf_version >=5.0" From 29f0b504b9b5944d6b95d135d8ef973c57056604 Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Tue, 3 Sep 2024 00:28:18 +0200 Subject: [PATCH 2033/2101] Bump rp2040 Arduino platform and framework (#7134) --- esphome/components/rp2040/__init__.py | 15 +++++++-------- platformio.ini | 2 +- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/esphome/components/rp2040/__init__.py b/esphome/components/rp2040/__init__.py index f5c3b8bda2..8f1d26f780 100644 --- a/esphome/components/rp2040/__init__.py +++ b/esphome/components/rp2040/__init__.py @@ -1,6 +1,5 @@ import logging import os - from string import ascii_letters, digits import esphome.codegen as cg @@ -8,6 +7,7 @@ import esphome.config_validation as cv from esphome.const import ( CONF_BOARD, CONF_FRAMEWORK, + CONF_PLATFORM_VERSION, CONF_SOURCE, CONF_VERSION, KEY_CORE, @@ -15,10 +15,9 @@ from esphome.const import ( KEY_TARGET_FRAMEWORK, KEY_TARGET_PLATFORM, PLATFORM_RP2040, - CONF_PLATFORM_VERSION, ) -from esphome.core import CORE, coroutine_with_priority, EsphomeError -from esphome.helpers import mkdir_p, write_file, copy_file_if_changed +from esphome.core import CORE, EsphomeError, coroutine_with_priority +from esphome.helpers import copy_file_if_changed, mkdir_p, write_file from .const import KEY_BOARD, KEY_PIO_FILES, KEY_RP2040, rp2040_ns @@ -81,19 +80,19 @@ def _format_framework_arduino_version(ver: cv.Version) -> str: # 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, 7, 2) +RECOMMENDED_ARDUINO_FRAMEWORK_VERSION = cv.Version(3, 9, 4) # The platformio/raspberrypi version to use for arduino frameworks # - https://github.com/platformio/platform-raspberrypi/releases # - https://api.registry.platformio.org/v3/packages/platformio/platform/raspberrypi -ARDUINO_PLATFORM_VERSION = cv.Version(1, 12, 0) +ARDUINO_PLATFORM_VERSION = cv.Version(1, 13, 0) def _arduino_check_versions(value): value = value.copy() lookups = { - "dev": (cv.Version(3, 4, 0), "https://github.com/earlephilhower/arduino-pico"), - "latest": (cv.Version(3, 4, 0), None), + "dev": (cv.Version(3, 9, 4), "https://github.com/earlephilhower/arduino-pico"), + "latest": (cv.Version(3, 9, 4), None), "recommended": (RECOMMENDED_ARDUINO_FRAMEWORK_VERSION, None), } diff --git a/platformio.ini b/platformio.ini index 147159a841..ee18068a29 100644 --- a/platformio.ini +++ b/platformio.ini @@ -168,7 +168,7 @@ board_build.filesystem_size = 0.5m platform = https://github.com/maxgerhardt/platform-raspberrypi.git 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.7.2/rp2040-3.7.2.zip + earlephilhower/framework-arduinopico@https://github.com/earlephilhower/arduino-pico/releases/download/3.9.4/rp2040-3.9.4.zip framework = arduino lib_deps = From 3b14b0efce1e9be58f5da6364713ff3d7a12d06d Mon Sep 17 00:00:00 2001 From: Dan Greco <21044725+dangreco@users.noreply.github.com> Date: Mon, 2 Sep 2024 18:35:54 -0400 Subject: [PATCH 2034/2101] [gree] Add support for YX1FF remote (#7298) --- esphome/components/gree/climate.py | 3 +- esphome/components/gree/gree.cpp | 57 ++++++++++++++++++++++++++++-- esphome/components/gree/gree.h | 12 +++++-- 3 files changed, 66 insertions(+), 6 deletions(-) diff --git a/esphome/components/gree/climate.py b/esphome/components/gree/climate.py index c88a428391..75436f2cf5 100644 --- a/esphome/components/gree/climate.py +++ b/esphome/components/gree/climate.py @@ -1,6 +1,6 @@ import esphome.codegen as cg -import esphome.config_validation as cv from esphome.components import climate_ir +import esphome.config_validation as cv from esphome.const import CONF_ID, CONF_MODEL CODEOWNERS = ["@orestismers"] @@ -17,6 +17,7 @@ MODELS = { "yaa": Model.GREE_YAA, "yac": Model.GREE_YAC, "yac1fb9": Model.GREE_YAC1FB9, + "yx1ff": Model.GREE_YX1FF, } CONFIG_SCHEMA = climate_ir.CLIMATE_IR_WITH_RECEIVER_SCHEMA.extend( diff --git a/esphome/components/gree/gree.cpp b/esphome/components/gree/gree.cpp index cce2a8ffee..6d179a947b 100644 --- a/esphome/components/gree/gree.cpp +++ b/esphome/components/gree/gree.cpp @@ -6,7 +6,15 @@ namespace gree { static const char *const TAG = "gree.climate"; -void GreeClimate::set_model(Model model) { this->model_ = model; } +void GreeClimate::set_model(Model model) { + if (model == GREE_YX1FF) { + this->fan_modes_.insert(climate::CLIMATE_FAN_QUIET); // YX1FF 4 speed + this->presets_.insert(climate::CLIMATE_PRESET_NONE); // YX1FF sleep mode + this->presets_.insert(climate::CLIMATE_PRESET_SLEEP); // YX1FF sleep mode + } + + this->model_ = model; +} void GreeClimate::transmit_state() { uint8_t remote_state[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00}; @@ -14,7 +22,7 @@ void GreeClimate::transmit_state() { remote_state[0] = this->fan_speed_() | this->operation_mode_(); remote_state[1] = this->temperature_(); - if (this->model_ == GREE_YAN) { + if (this->model_ == GREE_YAN || this->model_ == GREE_YX1FF) { remote_state[2] = 0x60; remote_state[3] = 0x50; remote_state[4] = this->vertical_swing_(); @@ -36,8 +44,18 @@ void GreeClimate::transmit_state() { } } + if (this->model_ == GREE_YX1FF) { + if (this->fan_speed_() == GREE_FAN_TURBO) { + remote_state[2] |= GREE_FAN_TURBO_BIT; + } + + if (this->preset_() == GREE_PRESET_SLEEP) { + remote_state[0] |= GREE_PRESET_SLEEP_BIT; + } + } + // Calculate the checksum - if (this->model_ == GREE_YAN) { + if (this->model_ == GREE_YAN || this->model_ == GREE_YX1FF) { remote_state[7] = ((remote_state[0] << 4) + (remote_state[1] << 4) + 0xC0); } else { remote_state[7] = @@ -124,6 +142,23 @@ 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()) { + case climate::CLIMATE_FAN_QUIET: + return GREE_FAN_1; + case climate::CLIMATE_FAN_LOW: + return GREE_FAN_2; + case climate::CLIMATE_FAN_MEDIUM: + return GREE_FAN_3; + case climate::CLIMATE_FAN_HIGH: + return GREE_FAN_TURBO; + case climate::CLIMATE_FAN_AUTO: + default: + return GREE_FAN_AUTO; + } + } + switch (this->fan_mode.value()) { case climate::CLIMATE_FAN_LOW: return GREE_FAN_1; @@ -161,5 +196,21 @@ uint8_t GreeClimate::temperature_() { return (uint8_t) roundf(clamp(this->target_temperature, GREE_TEMP_MIN, GREE_TEMP_MAX)); } +uint8_t GreeClimate::preset_() { + // YX1FF has sleep preset + if (this->model_ == GREE_YX1FF) { + switch (this->preset.value()) { + case climate::CLIMATE_PRESET_NONE: + return GREE_PRESET_NONE; + case climate::CLIMATE_PRESET_SLEEP: + return GREE_PRESET_SLEEP; + default: + return GREE_PRESET_NONE; + } + } + + return GREE_PRESET_NONE; +} + } // namespace gree } // namespace esphome diff --git a/esphome/components/gree/gree.h b/esphome/components/gree/gree.h index 524a95aebd..6762b41eb0 100644 --- a/esphome/components/gree/gree.h +++ b/esphome/components/gree/gree.h @@ -25,7 +25,6 @@ const uint8_t GREE_FAN_AUTO = 0x00; const uint8_t GREE_FAN_1 = 0x10; const uint8_t GREE_FAN_2 = 0x20; const uint8_t GREE_FAN_3 = 0x30; -const uint8_t GREE_FAN_TURBO = 0x80; // IR Transmission const uint32_t GREE_IR_FREQUENCY = 38000; @@ -70,8 +69,16 @@ const uint8_t GREE_HDIR_MIDDLE = 0x04; const uint8_t GREE_HDIR_MRIGHT = 0x05; const uint8_t GREE_HDIR_RIGHT = 0x06; +// Only available on YX1FF +// Turbo (high) fan mode + sleep preset mode +const uint8_t GREE_FAN_TURBO = 0x80; +const uint8_t GREE_FAN_TURBO_BIT = 0x10; +const uint8_t GREE_PRESET_NONE = 0x00; +const uint8_t GREE_PRESET_SLEEP = 0x01; +const uint8_t GREE_PRESET_SLEEP_BIT = 0x80; + // Model codes -enum Model { GREE_GENERIC, GREE_YAN, GREE_YAA, GREE_YAC, GREE_YAC1FB9 }; +enum Model { GREE_GENERIC, GREE_YAN, GREE_YAA, GREE_YAC, GREE_YAC1FB9, GREE_YX1FF }; class GreeClimate : public climate_ir::ClimateIR { public: @@ -93,6 +100,7 @@ class GreeClimate : public climate_ir::ClimateIR { uint8_t horizontal_swing_(); uint8_t vertical_swing_(); uint8_t temperature_(); + uint8_t preset_(); Model model_{}; }; From d6eeac06199e562d2d25deaf8bd7cfe1ec90605f Mon Sep 17 00:00:00 2001 From: Tercio Filho Date: Mon, 2 Sep 2024 20:56:19 -0300 Subject: [PATCH 2035/2101] [modbus_controller] Allow duplicate command config (#7311) --- .../components/modbus_controller/__init__.py | 3 +++ esphome/components/modbus_controller/const.py | 1 + .../modbus_controller/modbus_controller.cpp | 22 ++++++++++--------- .../modbus_controller/modbus_controller.h | 8 +++++++ .../modbus_controller/test.esp32-ard.yaml | 1 + .../modbus_controller/test.esp32-idf.yaml | 1 + 6 files changed, 26 insertions(+), 10 deletions(-) diff --git a/esphome/components/modbus_controller/__init__.py b/esphome/components/modbus_controller/__init__.py index 1d0f406783..8146124c28 100644 --- a/esphome/components/modbus_controller/__init__.py +++ b/esphome/components/modbus_controller/__init__.py @@ -13,6 +13,7 @@ from esphome.const import ( ) from esphome.cpp_helpers import logging from .const import ( + CONF_ALLOW_DUPLICATE_COMMANDS, CONF_BITMASK, CONF_BYTE_OFFSET, CONF_COMMAND_THROTTLE, @@ -126,6 +127,7 @@ CONFIG_SCHEMA = cv.All( cv.Schema( { cv.GenerateID(): cv.declare_id(ModbusController), + cv.Optional(CONF_ALLOW_DUPLICATE_COMMANDS, default=False): cv.boolean, cv.Optional( CONF_COMMAND_THROTTLE, default="0ms" ): cv.positive_time_period_milliseconds, @@ -253,6 +255,7 @@ async def add_modbus_base_properties( async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) + cg.add(var.set_allow_duplicate_commands(config[CONF_ALLOW_DUPLICATE_COMMANDS])) cg.add(var.set_command_throttle(config[CONF_COMMAND_THROTTLE])) cg.add(var.set_offline_skip_updates(config[CONF_OFFLINE_SKIP_UPDATES])) if CONF_SERVER_REGISTERS in config: diff --git a/esphome/components/modbus_controller/const.py b/esphome/components/modbus_controller/const.py index 1f5c39895c..5d9a61dee7 100644 --- a/esphome/components/modbus_controller/const.py +++ b/esphome/components/modbus_controller/const.py @@ -1,3 +1,4 @@ +CONF_ALLOW_DUPLICATE_COMMANDS = "allow_duplicate_commands" CONF_BITMASK = "bitmask" CONF_BYTE_OFFSET = "byte_offset" CONF_COMMAND_THROTTLE = "command_throttle" diff --git a/esphome/components/modbus_controller/modbus_controller.cpp b/esphome/components/modbus_controller/modbus_controller.cpp index 378e5c06c0..8f48847a4f 100644 --- a/esphome/components/modbus_controller/modbus_controller.cpp +++ b/esphome/components/modbus_controller/modbus_controller.cpp @@ -175,16 +175,18 @@ void ModbusController::on_register_data(ModbusRegisterType register_type, uint16 } void ModbusController::queue_command(const ModbusCommandItem &command) { - // check if this command is already qeued. - // not very effective but the queue is never really large - for (auto &item : command_queue_) { - if (item->is_equal(command)) { - ESP_LOGW(TAG, "Duplicate modbus command found: type=0x%x address=%u count=%u", - static_cast(command.register_type), command.register_address, command.register_count); - // update the payload of the queued command - // replaces a previous command - item->payload = command.payload; - return; + if (!this->allow_duplicate_commands_) { + // check if this command is already qeued. + // not very effective but the queue is never really large + for (auto &item : command_queue_) { + if (item->is_equal(command)) { + ESP_LOGW(TAG, "Duplicate modbus command found: type=0x%x address=%u count=%u", + static_cast(command.register_type), command.register_address, command.register_count); + // update the payload of the queued command + // replaces a previous command + item->payload = command.payload; + return; + } } } command_queue_.push_back(make_unique(command)); diff --git a/esphome/components/modbus_controller/modbus_controller.h b/esphome/components/modbus_controller/modbus_controller.h index 3bc11da879..e88f4c07f7 100644 --- a/esphome/components/modbus_controller/modbus_controller.h +++ b/esphome/components/modbus_controller/modbus_controller.h @@ -448,6 +448,12 @@ class ModbusController : public PollingComponent, public modbus::ModbusDevice { /// incoming queue void on_write_register_response(ModbusRegisterType register_type, uint16_t start_address, const std::vector &data); + /// Allow a duplicate command to be sent + void set_allow_duplicate_commands(bool allow_duplicate_commands) { + this->allow_duplicate_commands_ = allow_duplicate_commands; + } + /// get if a duplicate command can be sent + bool get_allow_duplicate_commands() { return this->allow_duplicate_commands_; } /// called by esphome generated code to set the command_throttle period void set_command_throttle(uint16_t command_throttle) { this->command_throttle_ = command_throttle; } /// called by esphome generated code to set the offline_skip_updates @@ -482,6 +488,8 @@ class ModbusController : public PollingComponent, public modbus::ModbusDevice { std::list> command_queue_; /// modbus response data waiting to get processed std::queue> incoming_queue_; + /// if duplicate commands can be sent + bool allow_duplicate_commands_; /// when was the last send operation uint32_t last_command_timestamp_; /// min time in ms between sending modbus commands diff --git a/tests/components/modbus_controller/test.esp32-ard.yaml b/tests/components/modbus_controller/test.esp32-ard.yaml index 3e022b10ab..b6e38aeb9c 100644 --- a/tests/components/modbus_controller/test.esp32-ard.yaml +++ b/tests/components/modbus_controller/test.esp32-ard.yaml @@ -20,6 +20,7 @@ modbus_controller: - id: modbus_controller1 address: 0x2 modbus_id: mod_bus1 + allow_duplicate_commands: false - id: modbus_controller2 address: 0x2 modbus_id: mod_bus2 diff --git a/tests/components/modbus_controller/test.esp32-idf.yaml b/tests/components/modbus_controller/test.esp32-idf.yaml index c5fe3fd057..d5407ac406 100644 --- a/tests/components/modbus_controller/test.esp32-idf.yaml +++ b/tests/components/modbus_controller/test.esp32-idf.yaml @@ -12,3 +12,4 @@ modbus_controller: - id: modbus_controller1 address: 0x2 modbus_id: mod_bus1 + allow_duplicate_commands: true From f8ec5242c98649cb590e24667dd3791a5f6b6df1 Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt Date: Mon, 2 Sep 2024 20:47:54 -0400 Subject: [PATCH 2036/2101] Better support for task blocking ring buffer reads and writes (#7390) --- esphome/core/ring_buffer.cpp | 15 ++++++++-- esphome/core/ring_buffer.h | 56 ++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/esphome/core/ring_buffer.cpp b/esphome/core/ring_buffer.cpp index 9bd3d9d853..d8ca831de0 100644 --- a/esphome/core/ring_buffer.cpp +++ b/esphome/core/ring_buffer.cpp @@ -20,13 +20,20 @@ std::unique_ptr RingBuffer::create(size_t len) { return nullptr; } - rb->handle_ = xStreamBufferCreateStatic(len + 1, 0, rb->storage_, &rb->structure_); + rb->handle_ = xStreamBufferCreateStatic(len + 1, 1, rb->storage_, &rb->structure_); ESP_LOGD(TAG, "Created ring buffer with size %u", len); return rb; } size_t RingBuffer::read(void *data, size_t len, TickType_t ticks_to_wait) { - return xStreamBufferReceive(this->handle_, data, len, ticks_to_wait); + if (ticks_to_wait > 0) + xStreamBufferSetTriggerLevel(this->handle_, len); + + size_t bytes_read = xStreamBufferReceive(this->handle_, data, len, ticks_to_wait); + + xStreamBufferSetTriggerLevel(this->handle_, 1); + + return bytes_read; } size_t RingBuffer::write(void *data, size_t len) { @@ -39,6 +46,10 @@ size_t RingBuffer::write(void *data, size_t len) { return xStreamBufferSend(this->handle_, data, len, 0); } +size_t RingBuffer::write_without_replacement(void *data, size_t len, TickType_t ticks_to_wait) { + return xStreamBufferSend(this->handle_, data, len, ticks_to_wait); +} + size_t RingBuffer::available() const { return xStreamBufferBytesAvailable(this->handle_); } size_t RingBuffer::free() const { return xStreamBufferSpacesAvailable(this->handle_); } diff --git a/esphome/core/ring_buffer.h b/esphome/core/ring_buffer.h index e602068844..97ffefcefa 100644 --- a/esphome/core/ring_buffer.h +++ b/esphome/core/ring_buffer.h @@ -12,13 +12,69 @@ namespace esphome { class RingBuffer { public: + /** + * @brief Reads from the ring buffer, waiting up to a specified number of ticks if necessary. + * + * Available bytes are read into the provided data pointer. If not enough bytes are available, + * the function will wait up to `ticks_to_wait` FreeRTOS ticks before reading what is available. + * + * @param data Pointer to copy read data into + * @param len Number of bytes to read + * @param ticks_to_wait Maximum number of FreeRTOS ticks to wait (default: 0) + * @return Number of bytes read + */ size_t read(void *data, size_t len, TickType_t ticks_to_wait = 0); + /** + * @brief Writes to the ring buffer, overwriting oldest data if necessary. + * + * The provided data is written to the ring buffer. If not enough space is available, + * the function will overwrite the oldest data in the ring buffer. + * + * @param data Pointer to data for writing + * @param len Number of bytes to write + * @return Number of bytes written + */ size_t write(void *data, size_t len); + /** + * @brief Writes to the ring buffer without overwriting oldest data. + * + * The provided data is written to the ring buffer. If not enough space is available, + * the function will wait up to `ticks_to_wait` FreeRTOS ticks before writing as much as possible. + * + * @param data Pointer to data for writing + * @param len Number of bytes to write + * @param ticks_to_wait Maximum number of FreeRTOS ticks to wait (default: 0) + * @return Number of bytes written + */ + size_t write_without_replacement(void *data, size_t len, TickType_t ticks_to_wait = 0); + + /** + * @brief Returns the number of available bytes in the ring buffer. + * + * This function provides the number of bytes that can be read from the ring buffer + * without blocking the calling FreeRTOS task. + * + * @return Number of available bytes + */ size_t available() const; + + /** + * @brief Returns the number of free bytes in the ring buffer. + * + * This function provides the number of bytes that can be written to the ring buffer + * without overwriting data or blocking the calling FreeRTOS task. + * + * @return Number of free bytes + */ size_t free() const; + /** + * @brief Resets the ring buffer, discarding all stored data. + * + * @return pdPASS if successful, pdFAIL otherwise + */ BaseType_t reset(); static std::unique_ptr create(size_t len); From 39b2f30b16d263864a9d5fb8444d4814d8658cc4 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 2 Sep 2024 10:36:18 +1200 Subject: [PATCH 2037/2101] Bump Dockerfile dependencies (#7386) --- docker/Dockerfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 16f37274c6..4393d5a447 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -34,8 +34,8 @@ RUN \ python3-wheel=0.38.4-2 \ iputils-ping=3:20221126-1 \ git=1:2.39.2-1.1 \ - curl=7.88.1-10+deb12u6 \ - openssh-client=1:9.2p1-2+deb12u2 \ + curl=7.88.1-10+deb12u7 \ + openssh-client=1:9.2p1-2+deb12u3 \ python3-cffi=1.15.1-5 \ libcairo2=1.16.0-7 \ libmagic1=1:5.44-3 \ @@ -49,7 +49,7 @@ RUN \ zlib1g-dev=1:1.2.13.dfsg-1 \ libjpeg-dev=1:2.1.5-2 \ libfreetype-dev=2.12.1+dfsg-5+deb12u3 \ - libssl-dev=3.0.13-1~deb12u1 \ + libssl-dev=3.0.14-1~deb12u1 \ libffi-dev=3.4.4-1 \ libopenjp2-7=2.5.0-2 \ libtiff6=4.5.0-6+deb12u1 \ From cb4bede6d8790937e287cd69649c81871b1ac6b4 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 3 Sep 2024 16:06:54 +1200 Subject: [PATCH 2038/2101] Bump version to 2024.8.3 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 00f2d6a13b..05be1877b3 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.8.2" +__version__ = "2024.8.3" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From c6e64a9ed344dc8d34071fd3cfaefa9cd47d1f92 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Sep 2024 19:22:56 +1200 Subject: [PATCH 2039/2101] Bump pypa/gh-action-pypi-publish from 1.9.0 to 1.10.0 (#7395) 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 7895e7624a..9e932a3dfc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -65,7 +65,7 @@ jobs: pip3 install build python3 -m build - name: Publish - uses: pypa/gh-action-pypi-publish@v1.9.0 + uses: pypa/gh-action-pypi-publish@v1.10.0 deploy-docker: name: Build ESPHome ${{ matrix.platform }} From 10ccc5f12584c498c179974877a6b15f327066d7 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 4 Sep 2024 12:55:41 +1200 Subject: [PATCH 2040/2101] [api] Remove id from ``MediaPlayerSupportedFormat`` (#7406) --- esphome/components/api/api.proto | 1 - esphome/components/api/api_pb2_service.cpp | 19 ------------------- esphome/components/api/api_pb2_service.h | 4 ---- 3 files changed, 24 deletions(-) diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index 84183357dc..ad6fc79cf3 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -1112,7 +1112,6 @@ enum MediaPlayerFormatPurpose { MEDIA_PLAYER_FORMAT_PURPOSE_ANNOUNCEMENT = 1; } message MediaPlayerSupportedFormat { - option (id) = 119; option (ifdef) = "USE_MEDIA_PLAYER"; string format = 1; diff --git a/esphome/components/api/api_pb2_service.cpp b/esphome/components/api/api_pb2_service.cpp index 16c0e5654f..269a755e9e 100644 --- a/esphome/components/api/api_pb2_service.cpp +++ b/esphome/components/api/api_pb2_service.cpp @@ -311,14 +311,6 @@ bool APIServerConnectionBase::send_list_entities_button_response(const ListEntit #ifdef USE_BUTTON #endif #ifdef USE_MEDIA_PLAYER -bool APIServerConnectionBase::send_media_player_supported_format(const MediaPlayerSupportedFormat &msg) { -#ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "send_media_player_supported_format: %s", msg.dump().c_str()); -#endif - return this->send_message_(msg, 119); -} -#endif -#ifdef USE_MEDIA_PLAYER bool APIServerConnectionBase::send_list_entities_media_player_response(const ListEntitiesMediaPlayerResponse &msg) { #ifdef HAS_PROTO_MESSAGE_DUMP ESP_LOGVV(TAG, "send_list_entities_media_player_response: %s", msg.dump().c_str()); @@ -1143,17 +1135,6 @@ bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, ESP_LOGVV(TAG, "on_update_command_request: %s", msg.dump().c_str()); #endif this->on_update_command_request(msg); -#endif - break; - } - case 119: { -#ifdef USE_MEDIA_PLAYER - MediaPlayerSupportedFormat msg; - msg.decode(msg_data, msg_size); -#ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_media_player_supported_format: %s", msg.dump().c_str()); -#endif - this->on_media_player_supported_format(msg); #endif break; } diff --git a/esphome/components/api/api_pb2_service.h b/esphome/components/api/api_pb2_service.h index 83b5e3a444..83bfc2ed98 100644 --- a/esphome/components/api/api_pb2_service.h +++ b/esphome/components/api/api_pb2_service.h @@ -145,10 +145,6 @@ class APIServerConnectionBase : public ProtoService { #ifdef USE_BUTTON virtual void on_button_command_request(const ButtonCommandRequest &value){}; #endif -#ifdef USE_MEDIA_PLAYER - bool send_media_player_supported_format(const MediaPlayerSupportedFormat &msg); - virtual void on_media_player_supported_format(const MediaPlayerSupportedFormat &value){}; -#endif #ifdef USE_MEDIA_PLAYER bool send_list_entities_media_player_response(const ListEntitiesMediaPlayerResponse &msg); #endif From 1a71cc304740f7823ca77eb3bbab7128f7dd612a Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Wed, 4 Sep 2024 04:02:33 +0200 Subject: [PATCH 2041/2101] Drop max BLE client connections limitation (#7088) --- esphome/components/ble_client/__init__.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/esphome/components/ble_client/__init__.py b/esphome/components/ble_client/__init__.py index 6bf4ff739e..bc7d517695 100644 --- a/esphome/components/ble_client/__init__.py +++ b/esphome/components/ble_client/__init__.py @@ -65,9 +65,7 @@ CONF_ON_PASSKEY_NOTIFICATION = "on_passkey_notification" CONF_ON_NUMERIC_COMPARISON_REQUEST = "on_numeric_comparison_request" CONF_AUTO_CONNECT = "auto_connect" -# Espressif platformio framework is built with MAX_BLE_CONN to 3, so -# enforce this in yaml checks. -MULTI_CONF = 3 +MULTI_CONF = True CONFIG_SCHEMA = ( cv.Schema( From 188faa6530cd7d2a2f6a5a24eca6db1fcc9943f3 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Wed, 4 Sep 2024 04:38:47 +0100 Subject: [PATCH 2042/2101] [bl0942] loop and overflow cleanup (#7358) --- esphome/components/bl0942/bl0942.cpp | 32 ++++++++++++++++++++++------ esphome/components/bl0942/bl0942.h | 2 ++ 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/esphome/components/bl0942/bl0942.cpp b/esphome/components/bl0942/bl0942.cpp index 606d3629da..c70b5f1775 100644 --- a/esphome/components/bl0942/bl0942.cpp +++ b/esphome/components/bl0942/bl0942.cpp @@ -41,20 +41,33 @@ static const uint32_t BL0942_REG_MODE_DEFAULT = static const uint32_t BL0942_REG_SOFT_RESET_MAGIC = 0x5a5a5a; static const uint32_t BL0942_REG_USR_WRPROT_MAGIC = 0x55; +// 23-byte packet, 11 bits per byte, 2400 baud: about 105ms +static const uint32_t PKT_TIMEOUT_MS = 200; + void BL0942::loop() { DataPacket buffer; - if (!this->available()) { + int avail = this->available(); + + if (!avail) { return; } + 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); + this->read_array((uint8_t *) &buffer, avail); + this->rx_start_ = 0; + } + return; + } + if (this->read_array((uint8_t *) &buffer, sizeof(buffer))) { if (this->validate_checksum_(&buffer)) { this->received_package_(&buffer); } - } else { - ESP_LOGW(TAG, "Junk on wire. Throwing away partial message"); - while (read() >= 0) - ; } + this->rx_start_ = 0; } bool BL0942::validate_checksum_(DataPacket *data) { @@ -133,10 +146,17 @@ void BL0942::received_package_(DataPacket *data) { return; } + // cf_cnt is only 24 bits, so track overflows + uint32_t cf_cnt = (uint24_t) data->cf_cnt; + cf_cnt |= this->prev_cf_cnt_ & 0xff000000; + if (cf_cnt < this->prev_cf_cnt_) { + cf_cnt += 0x1000000; + } + this->prev_cf_cnt_ = cf_cnt; + float v_rms = (uint24_t) data->v_rms / voltage_reference_; float i_rms = (uint24_t) data->i_rms / current_reference_; float watt = (int24_t) data->watt / power_reference_; - uint32_t cf_cnt = (uint24_t) data->cf_cnt; float total_energy_consumption = cf_cnt / energy_reference_; float frequency = 1000000.0f / data->frequency; diff --git a/esphome/components/bl0942/bl0942.h b/esphome/components/bl0942/bl0942.h index 52347c1bc3..a5e48bdf1d 100644 --- a/esphome/components/bl0942/bl0942.h +++ b/esphome/components/bl0942/bl0942.h @@ -67,6 +67,8 @@ class BL0942 : public PollingComponent, public uart::UARTDevice { float energy_reference_ = BL0942_EREF; uint8_t address_ = 0; LineFrequency line_freq_ = LINE_FREQUENCY_50HZ; + uint32_t rx_start_ = 0; + uint32_t prev_cf_cnt_ = 0; bool validate_checksum_(DataPacket *data); int read_reg_(uint8_t reg); From a96de54d46f54a25a15eb889abeea4e53bb3d18f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Sep 2024 15:45:40 +1200 Subject: [PATCH 2043/2101] Bump peter-evans/create-pull-request from 6.1.0 to 7.0.0 (#7405) 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 7677425236..e834ff3793 100644 --- a/.github/workflows/sync-device-classes.yml +++ b/.github/workflows/sync-device-classes.yml @@ -36,7 +36,7 @@ jobs: python ./script/sync-device_class.py - name: Commit changes - uses: peter-evans/create-pull-request@v6.1.0 + uses: peter-evans/create-pull-request@v7.0.0 with: commit-message: "Synchronise Device Classes from Home Assistant" committer: esphomebot From a7fd3b34aae0b9465a6bea66c00b2746d8cfea12 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Sep 2024 15:47:59 +1200 Subject: [PATCH 2044/2101] Bump pypa/gh-action-pypi-publish from 1.10.0 to 1.10.1 (#7404) 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 9e932a3dfc..522de63360 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -65,7 +65,7 @@ jobs: pip3 install build python3 -m build - name: Publish - uses: pypa/gh-action-pypi-publish@v1.10.0 + uses: pypa/gh-action-pypi-publish@v1.10.1 deploy-docker: name: Build ESPHome ${{ matrix.platform }} From e882cea47e76c50db674baf8dae0fa8744aabc4c Mon Sep 17 00:00:00 2001 From: Jeff Cooper Date: Tue, 3 Sep 2024 23:48:13 -0400 Subject: [PATCH 2045/2101] Voice assist improvement - configurable conversation_id timeout (#7385) --- esphome/components/voice_assistant/__init__.py | 6 ++++++ esphome/components/voice_assistant/voice_assistant.cpp | 8 +++++++- esphome/components/voice_assistant/voice_assistant.h | 3 +++ tests/components/voice_assistant/test.esp32-ard.yaml | 1 + 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/esphome/components/voice_assistant/__init__.py b/esphome/components/voice_assistant/__init__.py index 031edbf27a..a4fb572208 100644 --- a/esphome/components/voice_assistant/__init__.py +++ b/esphome/components/voice_assistant/__init__.py @@ -43,6 +43,8 @@ CONF_VOLUME_MULTIPLIER = "volume_multiplier" CONF_WAKE_WORD = "wake_word" +CONF_CONVERSATION_TIMEOUT = "conversation_timeout" + CONF_ON_TIMER_STARTED = "on_timer_started" CONF_ON_TIMER_UPDATED = "on_timer_updated" CONF_ON_TIMER_CANCELLED = "on_timer_cancelled" @@ -100,6 +102,9 @@ CONFIG_SCHEMA = cv.All( cv.float_with_unit("decibel full scale", "(dBFS|dbfs|DBFS)"), cv.int_range(0, 31), ), + cv.Optional( + CONF_CONVERSATION_TIMEOUT, default="300s" + ): cv.positive_time_period_milliseconds, cv.Optional(CONF_VOLUME_MULTIPLIER, default=1.0): cv.float_range( min=0.0, min_included=False ), @@ -182,6 +187,7 @@ async def to_code(config): cg.add(var.set_noise_suppression_level(config[CONF_NOISE_SUPPRESSION_LEVEL])) cg.add(var.set_auto_gain(config[CONF_AUTO_GAIN])) cg.add(var.set_volume_multiplier(config[CONF_VOLUME_MULTIPLIER])) + cg.add(var.set_conversation_timeout(config[CONF_CONVERSATION_TIMEOUT])) if CONF_ON_LISTENING in config: await automation.build_automation( diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index e4f388db68..43c7428858 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -171,6 +171,11 @@ void VoiceAssistant::deallocate_buffers_() { #endif } +void VoiceAssistant::reset_conversation_id() { + this->conversation_id_ = ""; + ESP_LOGD(TAG, "reset conversation ID"); +} + int VoiceAssistant::read_microphone_() { size_t bytes_read = 0; if (this->mic_->is_running()) { // Read audio into input buffer @@ -299,7 +304,8 @@ void VoiceAssistant::loop() { break; } this->set_state_(State::STARTING_PIPELINE); - this->set_timeout("reset-conversation_id", 5 * 60 * 1000, [this]() { this->conversation_id_ = ""; }); + this->set_timeout("reset-conversation_id", this->conversation_timeout_, + [this]() { this->reset_conversation_id(); }); break; } case State::STARTING_PIPELINE: { diff --git a/esphome/components/voice_assistant/voice_assistant.h b/esphome/components/voice_assistant/voice_assistant.h index a160972e22..88cb0dd413 100644 --- a/esphome/components/voice_assistant/voice_assistant.h +++ b/esphome/components/voice_assistant/voice_assistant.h @@ -147,6 +147,8 @@ class VoiceAssistant : public Component { } void set_auto_gain(uint8_t auto_gain) { this->auto_gain_ = auto_gain; } void set_volume_multiplier(float volume_multiplier) { this->volume_multiplier_ = volume_multiplier; } + 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_; } @@ -262,6 +264,7 @@ class VoiceAssistant : public Component { uint8_t noise_suppression_level_; uint8_t auto_gain_; float volume_multiplier_; + uint32_t conversation_timeout_; uint8_t *send_buffer_; int16_t *input_buffer_; diff --git a/tests/components/voice_assistant/test.esp32-ard.yaml b/tests/components/voice_assistant/test.esp32-ard.yaml index 2e0209311d..7f6fd85303 100644 --- a/tests/components/voice_assistant/test.esp32-ard.yaml +++ b/tests/components/voice_assistant/test.esp32-ard.yaml @@ -33,6 +33,7 @@ speaker: voice_assistant: microphone: mic_id_external speaker: speaker_id + conversation_timeout: 60s on_listening: - logger.log: "Voice assistant microphone listening" on_start: From 71a7f6383f66d7e0730a7854d1f5739406310395 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 5 Sep 2024 01:08:39 +0100 Subject: [PATCH 2046/2101] Support BL0942 calibration (#7299) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- CODEOWNERS | 2 +- esphome/components/bl0942/__init__.py | 2 +- esphome/components/bl0942/bl0942.cpp | 20 +++++- esphome/components/bl0942/bl0942.h | 71 ++++++++++++++++++++ esphome/components/bl0942/sensor.py | 17 +++++ tests/components/bl0942/test.bk72xx-ard.yaml | 4 ++ tests/components/bl0942/test.rp2040-ard.yaml | 2 + 7 files changed, 115 insertions(+), 3 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index ab11086980..8c706fa2d6 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -61,7 +61,7 @@ esphome/components/bk72xx/* @kuba2k2 esphome/components/bl0906/* @athom-tech @jesserockz @tarontop esphome/components/bl0939/* @ziceva esphome/components/bl0940/* @tobias- -esphome/components/bl0942/* @dbuezas +esphome/components/bl0942/* @dbuezas @dwmw2 esphome/components/ble_client/* @buxtronix @clydebarrow esphome/components/bluetooth_proxy/* @jesserockz esphome/components/bme280_base/* @esphome/core diff --git a/esphome/components/bl0942/__init__.py b/esphome/components/bl0942/__init__.py index 8ef7857b7b..38b68d84b5 100644 --- a/esphome/components/bl0942/__init__.py +++ b/esphome/components/bl0942/__init__.py @@ -1 +1 @@ -CODEOWNERS = ["@dbuezas"] +CODEOWNERS = ["@dbuezas", "@dwmw2"] diff --git a/esphome/components/bl0942/bl0942.cpp b/esphome/components/bl0942/bl0942.cpp index c70b5f1775..af56e77de6 100644 --- a/esphome/components/bl0942/bl0942.cpp +++ b/esphome/components/bl0942/bl0942.cpp @@ -122,6 +122,20 @@ void BL0942::update() { } void BL0942::setup() { + // If either current or voltage references are set explicitly by the user, + // calculate the power reference from it unless that is also explicitly set. + if ((this->current_reference_set_ || this->voltage_reference_set_) && !this->power_reference_set_) { + this->power_reference_ = (this->voltage_reference_ * this->current_reference_ * 3537.0 / 305978.0) / 73989.0; + this->power_reference_set_ = true; + } + + // Similarly for energy reference, if the power reference was set by the user + // either implicitly or explicitly. + if (this->power_reference_set_ && !this->energy_reference_set_) { + this->energy_reference_ = this->power_reference_ * 3600000 / 419430.4; + this->energy_reference_set_ = true; + } + this->write_reg_(BL0942_REG_USR_WRPROT, BL0942_REG_USR_WRPROT_MAGIC); this->write_reg_(BL0942_REG_SOFT_RESET, BL0942_REG_SOFT_RESET_MAGIC); @@ -184,11 +198,15 @@ void BL0942::dump_config() { // NOLINT(readability-function-cognitive-complexit ESP_LOGCONFIG(TAG, "BL0942:"); ESP_LOGCONFIG(TAG, " Address: %d", this->address_); ESP_LOGCONFIG(TAG, " Nominal line frequency: %d Hz", this->line_freq_); + ESP_LOGCONFIG(TAG, " Current reference: %f", this->current_reference_); + ESP_LOGCONFIG(TAG, " Energy reference: %f", this->energy_reference_); + ESP_LOGCONFIG(TAG, " Power reference: %f", this->power_reference_); + ESP_LOGCONFIG(TAG, " Voltage reference: %f", this->voltage_reference_); LOG_SENSOR("", "Voltage", this->voltage_sensor_); LOG_SENSOR("", "Current", this->current_sensor_); LOG_SENSOR("", "Power", this->power_sensor_); LOG_SENSOR("", "Energy", this->energy_sensor_); - LOG_SENSOR("", "frequency", this->frequency_sensor_); + LOG_SENSOR("", "Frequency", this->frequency_sensor_); } } // namespace bl0942 diff --git a/esphome/components/bl0942/bl0942.h b/esphome/components/bl0942/bl0942.h index a5e48bdf1d..1dc930183f 100644 --- a/esphome/components/bl0942/bl0942.h +++ b/esphome/components/bl0942/bl0942.h @@ -8,6 +8,57 @@ namespace esphome { namespace bl0942 { +// The BL0942 IC is "calibration-free", which means that it doesn't care +// at all about calibration, and that's left to software. It measures a +// voltage differential on its IP/IN pins which linearly proportional to +// the current flow, and another on its VP pin which is proportional to +// the line voltage. It never knows the actual calibration; the values +// it reports are solely in terms of those inputs. +// +// The datasheet refers to the input voltages as I(A) and V(V), both +// in millivolts. It measures them against a reference voltage Vref, +// which is typically 1.218V (but that absolute value is meaningless +// without the actual calibration anyway). +// +// The reported I_RMS value is 305978 I(A)/Vref, and the reported V_RMS +// value is 73989 V(V)/Vref. So we can calibrate those by applying a +// simple meter with a resistive load. +// +// The chip also measures the phase difference between voltage and +// current, and uses it to calculate the power factor (cos φ). It +// reports the WATT value of 3537 * I_RMS * V_RMS * cos φ). +// +// It also integrates total energy based on the WATT value. The time for +// one CF_CNT pulse is 1638.4*256 / WATT. +// +// So... how do we calibrate that? +// +// Using a simple resistive load and an external meter, we can measure +// the true voltage and current for a given V_RMS and I_RMS reading, +// to calculate BL0942_UREF and BL0942_IREF. Those are in units of +// "305978 counts per amp" or "73989 counts per volt" respectively. +// +// We can derive BL0942_PREF from those. Let's eliminate the weird +// factors and express the calibration in plain counts per volt/amp: +// UREF1 = UREF/73989, IREF1 = IREF/305978. +// +// Next... the true power in Watts is V * I * cos φ, so that's equal +// to WATT/3537 * IREF1 * UREF1. Which means +// BL0942_PREF = BL0942_UREF * BL0942_IREF * 3537 / 305978 / 73989. +// +// Finally the accumulated energy. The period of a CF_CNT count is +// 1638.4*256 / WATT seconds, or 419230.4 / WATT seconds. Which means +// the energy represented by a CN_CNT pulse is 419230.4 WATT-seconds. +// Factoring in the calibration, that's 419230.4 / BL0942_PREF actual +// Watt-seconds (or Joules, as the physicists like to call them). +// +// But we're not being physicists today; we we're being engineers, so +// we want to convert to kWh instead. Which we do by dividing by 1000 +// and then by 3600, so the energy in kWh is +// CF_CNT * 419230.4 / BL0942_PREF / 3600000 +// +// 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 @@ -42,6 +93,22 @@ class BL0942 : public PollingComponent, public uart::UARTDevice { void set_frequency_sensor(sensor::Sensor *frequency_sensor) { 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_current_reference(float current_ref) { + this->current_reference_ = current_ref; + this->current_reference_set_ = true; + } + void set_energy_reference(float energy_ref) { + this->energy_reference_ = energy_ref; + this->energy_reference_set_ = true; + } + void set_power_reference(float power_ref) { + this->power_reference_ = power_ref; + this->power_reference_set_ = true; + } + void set_voltage_reference(float voltage_ref) { + this->voltage_reference_ = voltage_ref; + this->voltage_reference_set_ = true; + } void loop() override; void update() override; @@ -59,12 +126,16 @@ class BL0942 : public PollingComponent, public uart::UARTDevice { // Divide by this to turn into Watt float power_reference_ = BL0942_PREF; + bool power_reference_set_ = false; // Divide by this to turn into Volt float voltage_reference_ = BL0942_UREF; + bool voltage_reference_set_ = false; // Divide by this to turn into Ampere float current_reference_ = BL0942_IREF; + bool current_reference_set_ = false; // Divide by this to turn into kWh float energy_reference_ = BL0942_EREF; + bool energy_reference_set_ = false; uint8_t address_ = 0; LineFrequency line_freq_ = LINE_FREQUENCY_50HZ; uint32_t rx_start_ = 0; diff --git a/esphome/components/bl0942/sensor.py b/esphome/components/bl0942/sensor.py index c47da45b8c..3574443636 100644 --- a/esphome/components/bl0942/sensor.py +++ b/esphome/components/bl0942/sensor.py @@ -24,6 +24,11 @@ from esphome.const import ( UNIT_WATT, ) +CONF_CURRENT_REFERENCE = "current_reference" +CONF_ENERGY_REFERENCE = "energy_reference" +CONF_POWER_REFERENCE = "power_reference" +CONF_VOLTAGE_REFERENCE = "voltage_reference" + DEPENDENCIES = ["uart"] bl0942_ns = cg.esphome_ns.namespace("bl0942") @@ -77,6 +82,10 @@ CONFIG_SCHEMA = ( ), ), cv.Optional(CONF_ADDRESS, default=0): cv.int_range(min=0, max=3), + cv.Optional(CONF_CURRENT_REFERENCE): cv.float_, + cv.Optional(CONF_ENERGY_REFERENCE): cv.float_, + cv.Optional(CONF_POWER_REFERENCE): cv.float_, + cv.Optional(CONF_VOLTAGE_REFERENCE): cv.float_, } ) .extend(cv.polling_component_schema("60s")) @@ -106,3 +115,11 @@ async def to_code(config): cg.add(var.set_frequency_sensor(sens)) cg.add(var.set_line_freq(config[CONF_LINE_FREQUENCY])) cg.add(var.set_address(config[CONF_ADDRESS])) + if (current_reference := config.get(CONF_CURRENT_REFERENCE, None)) is not None: + cg.add(var.set_current_reference(current_reference)) + if (voltage_reference := config.get(CONF_VOLTAGE_REFERENCE, None)) is not None: + cg.add(var.set_voltage_reference(voltage_reference)) + if (power_reference := config.get(CONF_POWER_REFERENCE, None)) is not None: + cg.add(var.set_power_reference(power_reference)) + if (energy_reference := config.get(CONF_ENERGY_REFERENCE, None)) is not None: + cg.add(var.set_energy_reference(energy_reference)) diff --git a/tests/components/bl0942/test.bk72xx-ard.yaml b/tests/components/bl0942/test.bk72xx-ard.yaml index 4ed3eb391d..12772f9375 100644 --- a/tests/components/bl0942/test.bk72xx-ard.yaml +++ b/tests/components/bl0942/test.bk72xx-ard.yaml @@ -20,3 +20,7 @@ sensor: name: BL0942 Energy frequency: name: BL0942 Frequency + voltage_reference: 15968 + current_reference: 124180 + power_reference: 309.1 + energy_reference: 2653 diff --git a/tests/components/bl0942/test.rp2040-ard.yaml b/tests/components/bl0942/test.rp2040-ard.yaml index 8d16efed4f..d07e0c4402 100644 --- a/tests/components/bl0942/test.rp2040-ard.yaml +++ b/tests/components/bl0942/test.rp2040-ard.yaml @@ -18,3 +18,5 @@ sensor: name: BL0942 Energy frequency: name: BL0942 Frequency + voltage_reference: 15968 + current_reference: 124180 From dc4e60526cd63525363cf36be8625fd52840fea8 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 5 Sep 2024 12:49:01 +1200 Subject: [PATCH 2047/2101] [micro_wake_word] Remove duplicated download code (#7401) --- .../components/micro_wake_word/__init__.py | 27 ++----------------- esphome/external_files.py | 8 +++--- 2 files changed, 7 insertions(+), 28 deletions(-) diff --git a/esphome/components/micro_wake_word/__init__.py b/esphome/components/micro_wake_word/__init__.py index cd45f75b01..a8aa590951 100644 --- a/esphome/components/micro_wake_word/__init__.py +++ b/esphome/components/micro_wake_word/__init__.py @@ -4,8 +4,6 @@ import logging from pathlib import Path from urllib.parse import urljoin -import requests - from esphome import automation, external_files, git from esphome.automation import register_action, register_condition import esphome.codegen as cg @@ -26,7 +24,6 @@ from esphome.const import ( CONF_USERNAME, TYPE_GIT, TYPE_LOCAL, - __version__, ) from esphome.core import CORE, HexInt @@ -179,26 +176,6 @@ def _convert_manifest_v1_to_v2(v1_manifest): return v2_manifest -def _download_file(url: str, path: Path) -> bytes: - if not external_files.has_remote_file_changed(url, path): - _LOGGER.debug("Remote file has not changed, skipping download") - return path.read_bytes() - - try: - req = requests.get( - url, - timeout=external_files.NETWORK_TIMEOUT, - headers={"User-agent": f"ESPHome/{__version__} (https://esphome.io)"}, - ) - req.raise_for_status() - except requests.exceptions.RequestException as e: - raise cv.Invalid(f"Could not download file from {url}: {e}") from e - - path.parent.mkdir(parents=True, exist_ok=True) - path.write_bytes(req.content) - return req.content - - def _validate_manifest_version(manifest_data): if manifest_version := manifest_data.get(KEY_VERSION): if manifest_version == 1: @@ -223,7 +200,7 @@ def _process_http_source(config): json_path = path / "manifest.json" - json_contents = _download_file(url, json_path) + json_contents = external_files.download_content(url, json_path) manifest_data = json.loads(json_contents) if not isinstance(manifest_data, dict): @@ -234,7 +211,7 @@ def _process_http_source(config): model_path = path / model - _download_file(str(model_url), model_path) + external_files.download_content(str(model_url), model_path) return config diff --git a/esphome/external_files.py b/esphome/external_files.py index baf62286e4..057ff52f3f 100644 --- a/esphome/external_files.py +++ b/esphome/external_files.py @@ -80,10 +80,10 @@ def compute_local_file_dir(domain: str) -> Path: return base_directory -def download_content(url: str, path: Path, timeout=NETWORK_TIMEOUT) -> None: +def download_content(url: str, path: Path, timeout=NETWORK_TIMEOUT) -> bytes: if not has_remote_file_changed(url, path): _LOGGER.debug("Remote file has not changed %s", url) - return + return path.read_bytes() _LOGGER.debug( "Remote file has changed, downloading from %s to %s", @@ -102,4 +102,6 @@ def download_content(url: str, path: Path, timeout=NETWORK_TIMEOUT) -> None: raise cv.Invalid(f"Could not download from {url}: {e}") path.parent.mkdir(parents=True, exist_ok=True) - path.write_bytes(req.content) + data = req.content + path.write_bytes(data) + return data From b4962334251ee8920d46c912588a0adc4bd58201 Mon Sep 17 00:00:00 2001 From: Markus <974709+Links2004@users.noreply.github.com> Date: Thu, 5 Sep 2024 02:57:44 +0200 Subject: [PATCH 2048/2101] Add StatsD component (#6642) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- CODEOWNERS | 1 + esphome/components/statsd/__init__.py | 65 ++++++++ esphome/components/statsd/statsd.cpp | 156 ++++++++++++++++++ esphome/components/statsd/statsd.h | 86 ++++++++++ tests/components/statsD/common.yaml | 29 ++++ tests/components/statsD/test.bk72xx-ard.yaml | 2 + tests/components/statsD/test.esp32-ard.yaml | 2 + .../components/statsD/test.esp32-c3-ard.yaml | 2 + .../components/statsD/test.esp32-c3-idf.yaml | 2 + tests/components/statsD/test.esp32-idf.yaml | 2 + tests/components/statsD/test.esp8266-ard.yaml | 2 + tests/components/statsD/test.rp2040-ard.yaml | 2 + 12 files changed, 351 insertions(+) create mode 100644 esphome/components/statsd/__init__.py create mode 100644 esphome/components/statsd/statsd.cpp create mode 100644 esphome/components/statsd/statsd.h create mode 100644 tests/components/statsD/common.yaml create mode 100644 tests/components/statsD/test.bk72xx-ard.yaml create mode 100644 tests/components/statsD/test.esp32-ard.yaml create mode 100644 tests/components/statsD/test.esp32-c3-ard.yaml create mode 100644 tests/components/statsD/test.esp32-c3-idf.yaml create mode 100644 tests/components/statsD/test.esp32-idf.yaml create mode 100644 tests/components/statsD/test.esp8266-ard.yaml create mode 100644 tests/components/statsD/test.rp2040-ard.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 8c706fa2d6..52b5f48a34 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -385,6 +385,7 @@ esphome/components/st7701s/* @clydebarrow esphome/components/st7735/* @SenexCrenshaw esphome/components/st7789v/* @kbx81 esphome/components/st7920/* @marsjan155 +esphome/components/statsd/* @Links2004 esphome/components/substitutions/* @esphome/core esphome/components/sun/* @OttoWinter esphome/components/sun_gtil2/* @Mat931 diff --git a/esphome/components/statsd/__init__.py b/esphome/components/statsd/__init__.py new file mode 100644 index 0000000000..3623338aec --- /dev/null +++ b/esphome/components/statsd/__init__.py @@ -0,0 +1,65 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import sensor, binary_sensor +from esphome.const import ( + CONF_ID, + CONF_PORT, + CONF_NAME, + CONF_SENSORS, + CONF_BINARY_SENSORS, +) + +AUTO_LOAD = ["socket"] +CODEOWNERS = ["@Links2004"] +DEPENDENCIES = ["network"] + +CONF_HOST = "host" +CONF_PREFIX = "prefix" + +statsd_component_ns = cg.esphome_ns.namespace("statsd") +StatsdComponent = statsd_component_ns.class_("StatsdComponent", cg.PollingComponent) + +CONFIG_SENSORS_SCHEMA = cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(sensor.Sensor), + cv.Required(CONF_NAME): cv.string_strict, + } +) + +CONFIG_BINARY_SENSORS_SCHEMA = cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(binary_sensor.BinarySensor), + cv.Required(CONF_NAME): cv.string_strict, + } +) + +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.declare_id(StatsdComponent), + cv.Required(CONF_HOST): cv.string_strict, + cv.Optional(CONF_PORT, default=8125): cv.port, + cv.Optional(CONF_PREFIX, default=""): cv.string_strict, + cv.Optional(CONF_SENSORS): cv.ensure_list(CONFIG_SENSORS_SCHEMA), + cv.Optional(CONF_BINARY_SENSORS): cv.ensure_list(CONFIG_BINARY_SENSORS_SCHEMA), + } +).extend(cv.polling_component_schema("10s")) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, config) + cg.add( + var.configure( + config.get(CONF_HOST), + config.get(CONF_PORT), + config.get(CONF_PREFIX), + ) + ) + + for sensor_cfg in config.get(CONF_SENSORS, []): + s = await cg.get_variable(sensor_cfg[CONF_ID]) + cg.add(var.register_sensor(sensor_cfg[CONF_NAME], s)) + + for sensor_cfg in config.get(CONF_BINARY_SENSORS, []): + s = await cg.get_variable(sensor_cfg[CONF_ID]) + cg.add(var.register_binary_sensor(sensor_cfg[CONF_NAME], s)) diff --git a/esphome/components/statsd/statsd.cpp b/esphome/components/statsd/statsd.cpp new file mode 100644 index 0000000000..68b24908d2 --- /dev/null +++ b/esphome/components/statsd/statsd.cpp @@ -0,0 +1,156 @@ +#include "esphome/core/log.h" + +#include "statsd.h" + +namespace esphome { +namespace statsd { + +// send UDP packet if we reach 1Kb packed size +// this is needed since statsD does not support fragmented UDP packets +static const uint16_t SEND_THRESHOLD = 1024; + +static const char *const TAG = "statsD"; + +void StatsdComponent::setup() { +#ifndef USE_ESP8266 + this->sock_ = esphome::socket::socket(AF_INET, SOCK_DGRAM, 0); + + struct sockaddr_in source; + source.sin_family = AF_INET; + source.sin_addr.s_addr = htonl(INADDR_ANY); + source.sin_port = htons(this->port_); + this->sock_->bind((struct sockaddr *) &source, sizeof(source)); + + this->destination_.sin_family = AF_INET; + this->destination_.sin_port = htons(this->port_); + this->destination_.sin_addr.s_addr = inet_addr(this->host_); +#endif +} + +StatsdComponent::~StatsdComponent() { +#ifndef USE_ESP8266 + if (!this->sock_) { + return; + } + this->sock_->close(); +#endif +} + +void StatsdComponent::dump_config() { + ESP_LOGCONFIG(TAG, "statsD:"); + ESP_LOGCONFIG(TAG, " host: %s", this->host_); + ESP_LOGCONFIG(TAG, " port: %d", this->port_); + if (this->prefix_) { + ESP_LOGCONFIG(TAG, " prefix: %s", this->prefix_); + } + + ESP_LOGCONFIG(TAG, " metrics:"); + for (sensors_t s : this->sensors_) { + ESP_LOGCONFIG(TAG, " - name: %s", s.name); + ESP_LOGCONFIG(TAG, " type: %d", s.type); + } +} + +float StatsdComponent::get_setup_priority() const { return esphome::setup_priority::AFTER_WIFI; } + +#ifdef USE_SENSOR +void StatsdComponent::register_sensor(const char *name, esphome::sensor::Sensor *sensor) { + sensors_t s; + s.name = name; + s.sensor = sensor; + s.type = TYPE_SENSOR; + this->sensors_.push_back(s); +} +#endif + +#ifdef USE_BINARY_SENSOR +void StatsdComponent::register_binary_sensor(const char *name, esphome::binary_sensor::BinarySensor *binary_sensor) { + sensors_t s; + s.name = name; + s.binary_sensor = binary_sensor; + s.type = TYPE_BINARY_SENSOR; + this->sensors_.push_back(s); +} +#endif + +void StatsdComponent::update() { + std::string out; + out.reserve(SEND_THRESHOLD); + + for (sensors_t s : this->sensors_) { + double val = 0; + switch (s.type) { +#ifdef USE_SENSOR + case TYPE_SENSOR: + if (!s.sensor->has_state()) { + continue; + } + val = s.sensor->state; + break; +#endif +#ifdef USE_BINARY_SENSOR + case TYPE_BINARY_SENSOR: + if (!s.binary_sensor->has_state()) { + continue; + } + // map bool to double + if (s.binary_sensor->state) { + val = 1; + } + break; +#endif + default: + ESP_LOGE(TAG, "type not known, name: %s type: %d", s.name, s.type); + continue; + } + + // statsD gauge: + // https://github.com/statsd/statsd/blob/master/docs/metric_types.md + // 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(str_sprintf("%s:0|g\n", s.name)); + } + if (this->prefix_) { + out.append(str_sprintf("%s.", this->prefix_)); + } + out.append(str_sprintf("%s:%f|g\n", s.name, val)); + + if (out.length() > SEND_THRESHOLD) { + this->send_(&out); + out.clear(); + } + } + + this->send_(&out); +} + +void StatsdComponent::send_(std::string *out) { + if (out->empty()) { + return; + } +#ifdef USE_ESP8266 + IPAddress ip; + ip.fromString(this->host_); + + this->sock_.beginPacket(ip, this->port_); + this->sock_.write((const uint8_t *) out->c_str(), out->length()); + this->sock_.endPacket(); + +#else + if (!this->sock_) { + return; + } + + int n_bytes = this->sock_->sendto(out->c_str(), out->length(), 0, reinterpret_cast(&this->destination_), + sizeof(this->destination_)); + if (n_bytes != out->length()) { + ESP_LOGE(TAG, "Failed to send UDP packed (%d of %d)", n_bytes, out->length()); + } +#endif +} + +} // namespace statsd +} // namespace esphome diff --git a/esphome/components/statsd/statsd.h b/esphome/components/statsd/statsd.h new file mode 100644 index 0000000000..ef42579587 --- /dev/null +++ b/esphome/components/statsd/statsd.h @@ -0,0 +1,86 @@ +#pragma once + +#include + +#include "esphome/core/defines.h" +#include "esphome/core/component.h" +#include "esphome/components/socket/socket.h" +#include "esphome/components/network/ip_address.h" + +#ifdef USE_SENSOR +#include "esphome/components/sensor/sensor.h" +#endif + +#ifdef USE_BINARY_SENSOR +#include "esphome/components/binary_sensor/binary_sensor.h" +#endif + +#ifdef USE_LOGGER +#include "esphome/components/logger/logger.h" +#endif + +#ifdef USE_ESP8266 +#include "WiFiUdp.h" +#include "IPAddress.h" +#endif + +namespace esphome { +namespace statsd { + +using sensor_type_t = enum { TYPE_SENSOR, TYPE_BINARY_SENSOR }; + +using sensors_t = struct { + const char *name; + sensor_type_t type; + union { +#ifdef USE_SENSOR + esphome::sensor::Sensor *sensor; +#endif +#ifdef USE_BINARY_SENSOR + esphome::binary_sensor::BinarySensor *binary_sensor; +#endif + }; +}; + +class StatsdComponent : public PollingComponent { + public: + ~StatsdComponent(); + + void setup() override; + void dump_config() override; + void update() override; + float get_setup_priority() const override; + + void configure(const char *host, uint16_t port, const char *prefix) { + this->host_ = host; + this->port_ = port; + this->prefix_ = prefix; + } + +#ifdef USE_SENSOR + void register_sensor(const char *name, esphome::sensor::Sensor *sensor); +#endif + +#ifdef USE_BINARY_SENSOR + void register_binary_sensor(const char *name, esphome::binary_sensor::BinarySensor *binary_sensor); +#endif + + private: + const char *host_; + const char *prefix_; + uint16_t port_; + + std::vector sensors_; + +#ifdef USE_ESP8266 + WiFiUDP sock_; +#else + std::unique_ptr sock_; + struct sockaddr_in destination_; +#endif + + void send_(std::string *out); +}; + +} // namespace statsd +} // namespace esphome diff --git a/tests/components/statsD/common.yaml b/tests/components/statsD/common.yaml new file mode 100644 index 0000000000..5878101de8 --- /dev/null +++ b/tests/components/statsD/common.yaml @@ -0,0 +1,29 @@ +wifi: + ssid: MySSID + password: password1 + +statsd: + host: "192.168.1.1" + port: 8125 + prefix: esphome + update_interval: 60s + sensors: + id: s + name: sensors + binary_sensors: + id: bs + name: binary_sensors + +sensor: + - platform: template + id: s + name: "42.1" + lambda: |- + return 42.1f; + +binary_sensor: + - platform: template + id: bs + name: "On" + lambda: |- + return true; diff --git a/tests/components/statsD/test.bk72xx-ard.yaml b/tests/components/statsD/test.bk72xx-ard.yaml new file mode 100644 index 0000000000..25cb37a0b4 --- /dev/null +++ b/tests/components/statsD/test.bk72xx-ard.yaml @@ -0,0 +1,2 @@ +packages: + common: !include common.yaml diff --git a/tests/components/statsD/test.esp32-ard.yaml b/tests/components/statsD/test.esp32-ard.yaml new file mode 100644 index 0000000000..25cb37a0b4 --- /dev/null +++ b/tests/components/statsD/test.esp32-ard.yaml @@ -0,0 +1,2 @@ +packages: + common: !include common.yaml diff --git a/tests/components/statsD/test.esp32-c3-ard.yaml b/tests/components/statsD/test.esp32-c3-ard.yaml new file mode 100644 index 0000000000..25cb37a0b4 --- /dev/null +++ b/tests/components/statsD/test.esp32-c3-ard.yaml @@ -0,0 +1,2 @@ +packages: + common: !include common.yaml diff --git a/tests/components/statsD/test.esp32-c3-idf.yaml b/tests/components/statsD/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..25cb37a0b4 --- /dev/null +++ b/tests/components/statsD/test.esp32-c3-idf.yaml @@ -0,0 +1,2 @@ +packages: + common: !include common.yaml diff --git a/tests/components/statsD/test.esp32-idf.yaml b/tests/components/statsD/test.esp32-idf.yaml new file mode 100644 index 0000000000..25cb37a0b4 --- /dev/null +++ b/tests/components/statsD/test.esp32-idf.yaml @@ -0,0 +1,2 @@ +packages: + common: !include common.yaml diff --git a/tests/components/statsD/test.esp8266-ard.yaml b/tests/components/statsD/test.esp8266-ard.yaml new file mode 100644 index 0000000000..25cb37a0b4 --- /dev/null +++ b/tests/components/statsD/test.esp8266-ard.yaml @@ -0,0 +1,2 @@ +packages: + common: !include common.yaml diff --git a/tests/components/statsD/test.rp2040-ard.yaml b/tests/components/statsD/test.rp2040-ard.yaml new file mode 100644 index 0000000000..25cb37a0b4 --- /dev/null +++ b/tests/components/statsD/test.rp2040-ard.yaml @@ -0,0 +1,2 @@ +packages: + common: !include common.yaml From 1548fa0811144302fc9700a50bf8966b7a7d9157 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 5 Sep 2024 13:09:49 +1200 Subject: [PATCH 2049/2101] [homeassistant-switch] Support different entity domains (#7331) --- esphome/components/homeassistant/__init__.py | 13 ++++++++++++ .../homeassistant/switch/__init__.py | 17 +++++++++++++-- .../switch/homeassistant_switch.cpp | 4 ++-- tests/components/homeassistant/common.yaml | 21 +++++++++++++++++++ 4 files changed, 51 insertions(+), 4 deletions(-) diff --git a/esphome/components/homeassistant/__init__.py b/esphome/components/homeassistant/__init__.py index 6d997e48ca..223d6c18c3 100644 --- a/esphome/components/homeassistant/__init__.py +++ b/esphome/components/homeassistant/__init__.py @@ -5,6 +5,19 @@ from esphome.const import CONF_ATTRIBUTE, CONF_ENTITY_ID, CONF_INTERNAL CODEOWNERS = ["@OttoWinter", "@esphome/core"] homeassistant_ns = cg.esphome_ns.namespace("homeassistant") + +def validate_entity_domain(platform, supported_domains): + def validator(config): + domain = config[CONF_ENTITY_ID].split(".", 1)[0] + if domain not in supported_domains: + raise cv.Invalid( + f"Entity ID {config[CONF_ENTITY_ID]} is not supported by the {platform} platform." + ) + return config + + return validator + + HOME_ASSISTANT_IMPORT_SCHEMA = cv.Schema( { cv.Required(CONF_ENTITY_ID): cv.entity_id, diff --git a/esphome/components/homeassistant/switch/__init__.py b/esphome/components/homeassistant/switch/__init__.py index 3d7c80682a..384f82bbad 100644 --- a/esphome/components/homeassistant/switch/__init__.py +++ b/esphome/components/homeassistant/switch/__init__.py @@ -7,19 +7,32 @@ from .. import ( HOME_ASSISTANT_IMPORT_CONTROL_SCHEMA, homeassistant_ns, setup_home_assistant_entity, + validate_entity_domain, ) CODEOWNERS = ["@Links2004"] DEPENDENCIES = ["api"] +SUPPORTED_DOMAINS = [ + "automation", + "fan", + "humidifier", + "input_boolean", + "light", + "remote", + "siren", + "switch", +] + HomeassistantSwitch = homeassistant_ns.class_( "HomeassistantSwitch", switch.Switch, cg.Component ) -CONFIG_SCHEMA = ( +CONFIG_SCHEMA = cv.All( switch.switch_schema(HomeassistantSwitch) - .extend(cv.COMPONENT_SCHEMA) .extend(HOME_ASSISTANT_IMPORT_CONTROL_SCHEMA) + .extend(cv.COMPONENT_SCHEMA), + validate_entity_domain("switch", SUPPORTED_DOMAINS), ) diff --git a/esphome/components/homeassistant/switch/homeassistant_switch.cpp b/esphome/components/homeassistant/switch/homeassistant_switch.cpp index 05ef46e30e..0451c95069 100644 --- a/esphome/components/homeassistant/switch/homeassistant_switch.cpp +++ b/esphome/components/homeassistant/switch/homeassistant_switch.cpp @@ -42,9 +42,9 @@ void HomeassistantSwitch::write_state(bool state) { api::HomeassistantServiceResponse resp; if (state) { - resp.service = "switch.turn_on"; + resp.service = "homeassistant.turn_on"; } else { - resp.service = "switch.turn_off"; + resp.service = "homeassistant.turn_off"; } api::HomeassistantServiceMap entity_id_kv; diff --git a/tests/components/homeassistant/common.yaml b/tests/components/homeassistant/common.yaml index 8c9a4ad75f..9c6cb71b8b 100644 --- a/tests/components/homeassistant/common.yaml +++ b/tests/components/homeassistant/common.yaml @@ -33,6 +33,27 @@ wifi: api: switch: + - platform: homeassistant + entity_id: automation.my_cool_automation + id: my_cool_automation + - platform: homeassistant + entity_id: fan.my_cool_fan + id: my_cool_fan + - platform: homeassistant + entity_id: humidifier.my_cool_humidifier + id: my_cool_humidifier + - platform: homeassistant + entity_id: input_boolean.my_cool_input_boolean + id: my_cool_input_boolean + - platform: homeassistant + entity_id: light.my_cool_light + id: my_cool_light + - platform: homeassistant + entity_id: remote.my_cool_remote + id: my_cool_remote + - platform: homeassistant + entity_id: siren.my_cool_siren + id: my_cool_siren - platform: homeassistant entity_id: switch.my_cool_switch id: my_cool_switch From 18a1191e03578fb395156cb2578dc2f41d2a44f5 Mon Sep 17 00:00:00 2001 From: Adam DeMuri Date: Wed, 4 Sep 2024 23:08:02 -0600 Subject: [PATCH 2050/2101] Add support for using BMP280 with SPI (#7053) Co-authored-by: Keith Burzinski --- CODEOWNERS | 3 + esphome/components/bmp280/sensor.py | 97 +------------------ esphome/components/bmp280_base/__init__.py | 88 +++++++++++++++++ .../bmp280_base.cpp} | 15 ++- .../bmp280.h => bmp280_base/bmp280_base.h} | 14 ++- esphome/components/bmp280_i2c/__init__.py | 0 esphome/components/bmp280_i2c/bmp280_i2c.cpp | 27 ++++++ esphome/components/bmp280_i2c/bmp280_i2c.h | 22 +++++ esphome/components/bmp280_i2c/sensor.py | 22 +++++ esphome/components/bmp280_spi/__init__.py | 0 esphome/components/bmp280_spi/bmp280_spi.cpp | 65 +++++++++++++ esphome/components/bmp280_spi/bmp280_spi.h | 20 ++++ esphome/components/bmp280_spi/sensor.py | 22 +++++ tests/components/bmp280/test.esp32-ard.yaml | 15 --- .../components/bmp280/test.esp32-c3-ard.yaml | 15 --- tests/components/bmp280/test.esp32-idf.yaml | 15 --- tests/components/bmp280/test.esp8266-ard.yaml | 15 --- tests/components/bmp280/test.rp2040-ard.yaml | 15 --- .../common.yaml} | 10 +- .../components/bmp280_i2c/test.esp32-ard.yaml | 5 + .../bmp280_i2c/test.esp32-c3-ard.yaml | 5 + .../bmp280_i2c/test.esp32-c3-idf.yaml | 5 + .../components/bmp280_i2c/test.esp32-idf.yaml | 5 + .../bmp280_i2c/test.esp8266-ard.yaml | 5 + .../bmp280_i2c/test.rp2040-ard.yaml | 5 + tests/components/bmp280_spi/common.yaml | 18 ++++ .../components/bmp280_spi/test.esp32-ard.yaml | 7 ++ .../bmp280_spi/test.esp32-c3-ard.yaml | 7 ++ .../bmp280_spi/test.esp32-c3-idf.yaml | 7 ++ .../components/bmp280_spi/test.esp32-idf.yaml | 7 ++ .../bmp280_spi/test.esp8266-ard.yaml | 7 ++ .../bmp280_spi/test.rp2040-ard.yaml | 7 ++ 32 files changed, 388 insertions(+), 182 deletions(-) create mode 100644 esphome/components/bmp280_base/__init__.py rename esphome/components/{bmp280/bmp280.cpp => bmp280_base/bmp280_base.cpp} (95%) rename esphome/components/{bmp280/bmp280.h => bmp280_base/bmp280_base.h} (88%) create mode 100644 esphome/components/bmp280_i2c/__init__.py create mode 100644 esphome/components/bmp280_i2c/bmp280_i2c.cpp create mode 100644 esphome/components/bmp280_i2c/bmp280_i2c.h create mode 100644 esphome/components/bmp280_i2c/sensor.py create mode 100644 esphome/components/bmp280_spi/__init__.py create mode 100644 esphome/components/bmp280_spi/bmp280_spi.cpp create mode 100644 esphome/components/bmp280_spi/bmp280_spi.h create mode 100644 esphome/components/bmp280_spi/sensor.py delete mode 100644 tests/components/bmp280/test.esp32-ard.yaml delete mode 100644 tests/components/bmp280/test.esp32-c3-ard.yaml delete mode 100644 tests/components/bmp280/test.esp32-idf.yaml delete mode 100644 tests/components/bmp280/test.esp8266-ard.yaml delete mode 100644 tests/components/bmp280/test.rp2040-ard.yaml rename tests/components/{bmp280/test.esp32-c3-idf.yaml => bmp280_i2c/common.yaml} (56%) create mode 100644 tests/components/bmp280_i2c/test.esp32-ard.yaml create mode 100644 tests/components/bmp280_i2c/test.esp32-c3-ard.yaml create mode 100644 tests/components/bmp280_i2c/test.esp32-c3-idf.yaml create mode 100644 tests/components/bmp280_i2c/test.esp32-idf.yaml create mode 100644 tests/components/bmp280_i2c/test.esp8266-ard.yaml create mode 100644 tests/components/bmp280_i2c/test.rp2040-ard.yaml create mode 100644 tests/components/bmp280_spi/common.yaml create mode 100644 tests/components/bmp280_spi/test.esp32-ard.yaml create mode 100644 tests/components/bmp280_spi/test.esp32-c3-ard.yaml create mode 100644 tests/components/bmp280_spi/test.esp32-c3-idf.yaml create mode 100644 tests/components/bmp280_spi/test.esp32-idf.yaml create mode 100644 tests/components/bmp280_spi/test.esp8266-ard.yaml create mode 100644 tests/components/bmp280_spi/test.rp2040-ard.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 52b5f48a34..1d4df3ccb8 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -70,6 +70,9 @@ esphome/components/bme680_bsec/* @trvrnrth esphome/components/bme68x_bsec2/* @kbx81 @neffs esphome/components/bme68x_bsec2_i2c/* @kbx81 @neffs esphome/components/bmi160/* @flaviut +esphome/components/bmp280_base/* @ademuri +esphome/components/bmp280_i2c/* @ademuri +esphome/components/bmp280_spi/* @ademuri esphome/components/bmp3xx/* @latonita esphome/components/bmp3xx_base/* @latonita @martgras esphome/components/bmp3xx_i2c/* @latonita diff --git a/esphome/components/bmp280/sensor.py b/esphome/components/bmp280/sensor.py index a23bc0766a..a624889982 100644 --- a/esphome/components/bmp280/sensor.py +++ b/esphome/components/bmp280/sensor.py @@ -1,96 +1,5 @@ -import esphome.codegen as cg import esphome.config_validation as cv -from esphome.components import i2c, sensor -from esphome.const import ( - CONF_ID, - CONF_PRESSURE, - CONF_TEMPERATURE, - DEVICE_CLASS_PRESSURE, - DEVICE_CLASS_TEMPERATURE, - STATE_CLASS_MEASUREMENT, - UNIT_CELSIUS, - UNIT_HECTOPASCAL, - CONF_IIR_FILTER, - CONF_OVERSAMPLING, + +CONFIG_SCHEMA = cv.invalid( + "The bmp280 sensor component has been renamed to bmp280_i2c." ) - -DEPENDENCIES = ["i2c"] - -bmp280_ns = cg.esphome_ns.namespace("bmp280") -BMP280Oversampling = bmp280_ns.enum("BMP280Oversampling") -OVERSAMPLING_OPTIONS = { - "NONE": BMP280Oversampling.BMP280_OVERSAMPLING_NONE, - "1X": BMP280Oversampling.BMP280_OVERSAMPLING_1X, - "2X": BMP280Oversampling.BMP280_OVERSAMPLING_2X, - "4X": BMP280Oversampling.BMP280_OVERSAMPLING_4X, - "8X": BMP280Oversampling.BMP280_OVERSAMPLING_8X, - "16X": BMP280Oversampling.BMP280_OVERSAMPLING_16X, -} - -BMP280IIRFilter = bmp280_ns.enum("BMP280IIRFilter") -IIR_FILTER_OPTIONS = { - "OFF": BMP280IIRFilter.BMP280_IIR_FILTER_OFF, - "2X": BMP280IIRFilter.BMP280_IIR_FILTER_2X, - "4X": BMP280IIRFilter.BMP280_IIR_FILTER_4X, - "8X": BMP280IIRFilter.BMP280_IIR_FILTER_8X, - "16X": BMP280IIRFilter.BMP280_IIR_FILTER_16X, -} - -BMP280Component = bmp280_ns.class_( - "BMP280Component", cg.PollingComponent, i2c.I2CDevice -) - -CONFIG_SCHEMA = ( - cv.Schema( - { - cv.GenerateID(): cv.declare_id(BMP280Component), - 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="16X"): cv.enum( - OVERSAMPLING_OPTIONS, upper=True - ), - } - ), - cv.Optional(CONF_PRESSURE): sensor.sensor_schema( - unit_of_measurement=UNIT_HECTOPASCAL, - accuracy_decimals=1, - device_class=DEVICE_CLASS_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(0x77)) -) - - -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(temperature_config[CONF_OVERSAMPLING])) - - 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(pressure_config[CONF_OVERSAMPLING])) - - cg.add(var.set_iir_filter(config[CONF_IIR_FILTER])) diff --git a/esphome/components/bmp280_base/__init__.py b/esphome/components/bmp280_base/__init__.py new file mode 100644 index 0000000000..c0f9af9dd7 --- /dev/null +++ b/esphome/components/bmp280_base/__init__.py @@ -0,0 +1,88 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import sensor +from esphome.const import ( + CONF_ID, + CONF_IIR_FILTER, + CONF_OVERSAMPLING, + CONF_PRESSURE, + CONF_TEMPERATURE, + DEVICE_CLASS_PRESSURE, + DEVICE_CLASS_TEMPERATURE, + STATE_CLASS_MEASUREMENT, + UNIT_CELSIUS, + UNIT_HECTOPASCAL, +) + +CODEOWNERS = ["@ademuri"] + +bmp280_ns = cg.esphome_ns.namespace("bmp280_base") +BMP280Oversampling = bmp280_ns.enum("BMP280Oversampling") +OVERSAMPLING_OPTIONS = { + "NONE": BMP280Oversampling.BMP280_OVERSAMPLING_NONE, + "1X": BMP280Oversampling.BMP280_OVERSAMPLING_1X, + "2X": BMP280Oversampling.BMP280_OVERSAMPLING_2X, + "4X": BMP280Oversampling.BMP280_OVERSAMPLING_4X, + "8X": BMP280Oversampling.BMP280_OVERSAMPLING_8X, + "16X": BMP280Oversampling.BMP280_OVERSAMPLING_16X, +} + +BMP280IIRFilter = bmp280_ns.enum("BMP280IIRFilter") +IIR_FILTER_OPTIONS = { + "OFF": BMP280IIRFilter.BMP280_IIR_FILTER_OFF, + "2X": BMP280IIRFilter.BMP280_IIR_FILTER_2X, + "4X": BMP280IIRFilter.BMP280_IIR_FILTER_4X, + "8X": BMP280IIRFilter.BMP280_IIR_FILTER_8X, + "16X": BMP280IIRFilter.BMP280_IIR_FILTER_16X, +} + +CONFIG_SCHEMA_BASE = cv.Schema( + { + 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="16X"): cv.enum( + OVERSAMPLING_OPTIONS, upper=True + ), + } + ), + cv.Optional(CONF_PRESSURE): sensor.sensor_schema( + unit_of_measurement=UNIT_HECTOPASCAL, + accuracy_decimals=1, + device_class=DEVICE_CLASS_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(temperature_config[CONF_OVERSAMPLING])) + + 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(pressure_config[CONF_OVERSAMPLING])) + + cg.add(var.set_iir_filter(config[CONF_IIR_FILTER])) + + return var diff --git a/esphome/components/bmp280/bmp280.cpp b/esphome/components/bmp280_base/bmp280_base.cpp similarity index 95% rename from esphome/components/bmp280/bmp280.cpp rename to esphome/components/bmp280_base/bmp280_base.cpp index c92daa07fb..f94456f6e6 100644 --- a/esphome/components/bmp280/bmp280.cpp +++ b/esphome/components/bmp280_base/bmp280_base.cpp @@ -1,9 +1,9 @@ -#include "bmp280.h" +#include "bmp280_base.h" #include "esphome/core/hal.h" #include "esphome/core/log.h" namespace esphome { -namespace bmp280 { +namespace bmp280_base { static const char *const TAG = "bmp280.sensor"; @@ -59,6 +59,14 @@ static const char *iir_filter_to_str(BMP280IIRFilter filter) { void BMP280Component::setup() { ESP_LOGCONFIG(TAG, "Setting up BMP280..."); uint8_t chip_id = 0; + + // Read the chip id twice, to work around a bug where the first read is 0. + // https://community.st.com/t5/stm32-mcus-products/issue-with-reading-bmp280-chip-id-using-spi/td-p/691855 + if (!this->read_byte(0xD0, &chip_id)) { + this->error_code_ = COMMUNICATION_FAILED; + this->mark_failed(); + return; + } if (!this->read_byte(0xD0, &chip_id)) { this->error_code_ = COMMUNICATION_FAILED; this->mark_failed(); @@ -122,7 +130,6 @@ void BMP280Component::setup() { } void BMP280Component::dump_config() { ESP_LOGCONFIG(TAG, "BMP280:"); - LOG_I2C_DEVICE(this); switch (this->error_code_) { case COMMUNICATION_FAILED: ESP_LOGE(TAG, "Communication with BMP280 failed!"); @@ -262,5 +269,5 @@ uint16_t BMP280Component::read_u16_le_(uint8_t a_register) { } int16_t BMP280Component::read_s16_le_(uint8_t a_register) { return this->read_u16_le_(a_register); } -} // namespace bmp280 +} // namespace bmp280_base } // namespace esphome diff --git a/esphome/components/bmp280/bmp280.h b/esphome/components/bmp280_base/bmp280_base.h similarity index 88% rename from esphome/components/bmp280/bmp280.h rename to esphome/components/bmp280_base/bmp280_base.h index 96eb470155..4b22e98f13 100644 --- a/esphome/components/bmp280/bmp280.h +++ b/esphome/components/bmp280_base/bmp280_base.h @@ -2,10 +2,9 @@ #include "esphome/core/component.h" #include "esphome/components/sensor/sensor.h" -#include "esphome/components/i2c/i2c.h" namespace esphome { -namespace bmp280 { +namespace bmp280_base { /// Internal struct storing the calibration values of an BMP280. struct BMP280CalibrationData { @@ -50,8 +49,8 @@ enum BMP280IIRFilter { BMP280_IIR_FILTER_16X = 0b100, }; -/// This class implements support for the BMP280 Temperature+Pressure i2c sensor. -class BMP280Component : public PollingComponent, public i2c::I2CDevice { +/// This class implements support for the BMP280 Temperature+Pressure sensor. +class BMP280Component : public PollingComponent { public: void set_temperature_sensor(sensor::Sensor *temperature_sensor) { temperature_sensor_ = temperature_sensor; } void set_pressure_sensor(sensor::Sensor *pressure_sensor) { pressure_sensor_ = pressure_sensor; } @@ -68,6 +67,11 @@ class BMP280Component : public PollingComponent, public i2c::I2CDevice { float get_setup_priority() const override; void update() override; + virtual bool read_byte(uint8_t a_register, uint8_t *data) = 0; + virtual bool write_byte(uint8_t a_register, uint8_t data) = 0; + virtual bool read_bytes(uint8_t a_register, uint8_t *data, size_t len) = 0; + virtual bool read_byte_16(uint8_t a_register, uint16_t *data) = 0; + protected: /// Read the temperature value and store the calculated ambient temperature in t_fine. float read_temperature_(int32_t *t_fine); @@ -90,5 +94,5 @@ class BMP280Component : public PollingComponent, public i2c::I2CDevice { } error_code_{NONE}; }; -} // namespace bmp280 +} // namespace bmp280_base } // namespace esphome diff --git a/esphome/components/bmp280_i2c/__init__.py b/esphome/components/bmp280_i2c/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/bmp280_i2c/bmp280_i2c.cpp b/esphome/components/bmp280_i2c/bmp280_i2c.cpp new file mode 100644 index 0000000000..04b8bd8b10 --- /dev/null +++ b/esphome/components/bmp280_i2c/bmp280_i2c.cpp @@ -0,0 +1,27 @@ +#include "bmp280_i2c.h" +#include "esphome/core/hal.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace bmp280_i2c { + +bool BMP280I2CComponent::read_byte(uint8_t a_register, uint8_t *data) { + return I2CDevice::read_byte(a_register, data); +}; +bool BMP280I2CComponent::write_byte(uint8_t a_register, uint8_t data) { + return I2CDevice::write_byte(a_register, data); +}; +bool BMP280I2CComponent::read_bytes(uint8_t a_register, uint8_t *data, size_t len) { + return I2CDevice::read_bytes(a_register, data, len); +}; +bool BMP280I2CComponent::read_byte_16(uint8_t a_register, uint16_t *data) { + return I2CDevice::read_byte_16(a_register, data); +}; + +void BMP280I2CComponent::dump_config() { + LOG_I2C_DEVICE(this); + BMP280Component::dump_config(); +} + +} // namespace bmp280_i2c +} // namespace esphome diff --git a/esphome/components/bmp280_i2c/bmp280_i2c.h b/esphome/components/bmp280_i2c/bmp280_i2c.h new file mode 100644 index 0000000000..66d78d788b --- /dev/null +++ b/esphome/components/bmp280_i2c/bmp280_i2c.h @@ -0,0 +1,22 @@ +#pragma once + +#include "esphome/components/bmp280_base/bmp280_base.h" +#include "esphome/components/i2c/i2c.h" + +namespace esphome { +namespace bmp280_i2c { + +static const char *const TAG = "bmp280_i2c.sensor"; + +/// This class implements support for the BMP280 Temperature+Pressure i2c sensor. +class BMP280I2CComponent : public esphome::bmp280_base::BMP280Component, public i2c::I2CDevice { + public: + bool read_byte(uint8_t a_register, uint8_t *data) override; + bool write_byte(uint8_t a_register, uint8_t data) override; + bool read_bytes(uint8_t a_register, uint8_t *data, size_t len) override; + bool read_byte_16(uint8_t a_register, uint16_t *data) override; + void dump_config() override; +}; + +} // namespace bmp280_i2c +} // namespace esphome diff --git a/esphome/components/bmp280_i2c/sensor.py b/esphome/components/bmp280_i2c/sensor.py new file mode 100644 index 0000000000..991bb827a3 --- /dev/null +++ b/esphome/components/bmp280_i2c/sensor.py @@ -0,0 +1,22 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import i2c +from ..bmp280_base import to_code_base, CONFIG_SCHEMA_BASE + +AUTO_LOAD = ["bmp280_base"] +CODEOWNERS = ["@ademuri"] +DEPENDENCIES = ["i2c"] + +bmp280_ns = cg.esphome_ns.namespace("bmp280_i2c") +BMP280I2CComponent = bmp280_ns.class_( + "BMP280I2CComponent", cg.PollingComponent, i2c.I2CDevice +) + +CONFIG_SCHEMA = CONFIG_SCHEMA_BASE.extend( + i2c.i2c_device_schema(default_address=0x77) +).extend({cv.GenerateID(): cv.declare_id(BMP280I2CComponent)}) + + +async def to_code(config): + var = await to_code_base(config) + await i2c.register_i2c_device(var, config) diff --git a/esphome/components/bmp280_spi/__init__.py b/esphome/components/bmp280_spi/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/bmp280_spi/bmp280_spi.cpp b/esphome/components/bmp280_spi/bmp280_spi.cpp new file mode 100644 index 0000000000..a35e829432 --- /dev/null +++ b/esphome/components/bmp280_spi/bmp280_spi.cpp @@ -0,0 +1,65 @@ +#include +#include + +#include "bmp280_spi.h" +#include + +namespace esphome { +namespace bmp280_spi { + +uint8_t set_bit(uint8_t num, uint8_t position) { + uint8_t mask = 1 << position; + return num | mask; +} + +uint8_t clear_bit(uint8_t num, uint8_t position) { + uint8_t mask = 1 << position; + return num & ~mask; +} + +void BMP280SPIComponent::setup() { + this->spi_setup(); + BMP280Component::setup(); +}; + +// 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. +// https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmp280-ds001.pdf + +bool BMP280SPIComponent::read_byte(uint8_t a_register, uint8_t *data) { + this->enable(); + this->transfer_byte(set_bit(a_register, 7)); + *data = this->transfer_byte(0); + this->disable(); + return true; +} + +bool BMP280SPIComponent::write_byte(uint8_t a_register, uint8_t data) { + this->enable(); + this->transfer_byte(clear_bit(a_register, 7)); + this->transfer_byte(data); + this->disable(); + return true; +} + +bool BMP280SPIComponent::read_bytes(uint8_t a_register, uint8_t *data, size_t len) { + this->enable(); + this->transfer_byte(set_bit(a_register, 7)); + this->read_array(data, len); + this->disable(); + return true; +} + +bool BMP280SPIComponent::read_byte_16(uint8_t a_register, uint16_t *data) { + this->enable(); + this->transfer_byte(set_bit(a_register, 7)); + ((uint8_t *) data)[1] = this->transfer_byte(0); + ((uint8_t *) data)[0] = this->transfer_byte(0); + this->disable(); + return true; +} + +} // namespace bmp280_spi +} // namespace esphome diff --git a/esphome/components/bmp280_spi/bmp280_spi.h b/esphome/components/bmp280_spi/bmp280_spi.h new file mode 100644 index 0000000000..dd226502f6 --- /dev/null +++ b/esphome/components/bmp280_spi/bmp280_spi.h @@ -0,0 +1,20 @@ +#pragma once + +#include "esphome/components/bmp280_base/bmp280_base.h" +#include "esphome/components/spi/spi.h" + +namespace esphome { +namespace bmp280_spi { + +class BMP280SPIComponent : public esphome::bmp280_base::BMP280Component, + public spi::SPIDevice { + void setup() override; + bool read_byte(uint8_t a_register, uint8_t *data) override; + bool write_byte(uint8_t a_register, uint8_t data) override; + bool read_bytes(uint8_t a_register, uint8_t *data, size_t len) override; + bool read_byte_16(uint8_t a_register, uint16_t *data) override; +}; + +} // namespace bmp280_spi +} // namespace esphome diff --git a/esphome/components/bmp280_spi/sensor.py b/esphome/components/bmp280_spi/sensor.py new file mode 100644 index 0000000000..511d45b24e --- /dev/null +++ b/esphome/components/bmp280_spi/sensor.py @@ -0,0 +1,22 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import spi +from ..bmp280_base import to_code_base, CONFIG_SCHEMA_BASE + +AUTO_LOAD = ["bmp280_base"] +CODEOWNERS = ["@ademuri"] +DEPENDENCIES = ["spi"] + +bmp280_ns = cg.esphome_ns.namespace("bmp280_spi") +BMP280SPIComponent = bmp280_ns.class_( + "BMP280SPIComponent", cg.PollingComponent, spi.SPIDevice +) + +CONFIG_SCHEMA = CONFIG_SCHEMA_BASE.extend( + spi.spi_device_schema(default_mode="mode3") +).extend({cv.GenerateID(): cv.declare_id(BMP280SPIComponent)}) + + +async def to_code(config): + var = await to_code_base(config) + await spi.register_spi_device(var, config) diff --git a/tests/components/bmp280/test.esp32-ard.yaml b/tests/components/bmp280/test.esp32-ard.yaml deleted file mode 100644 index aeb1cb262b..0000000000 --- a/tests/components/bmp280/test.esp32-ard.yaml +++ /dev/null @@ -1,15 +0,0 @@ -i2c: - - id: i2c_bmp280 - scl: 16 - sda: 17 - -sensor: - - platform: bmp280 - address: 0x77 - temperature: - name: Outside Temperature - oversampling: 16x - pressure: - name: Outside Pressure - iir_filter: 16x - update_interval: 15s diff --git a/tests/components/bmp280/test.esp32-c3-ard.yaml b/tests/components/bmp280/test.esp32-c3-ard.yaml deleted file mode 100644 index 5f7f85d3e2..0000000000 --- a/tests/components/bmp280/test.esp32-c3-ard.yaml +++ /dev/null @@ -1,15 +0,0 @@ -i2c: - - id: i2c_bmp280 - scl: 5 - sda: 4 - -sensor: - - platform: bmp280 - address: 0x77 - temperature: - name: Outside Temperature - oversampling: 16x - pressure: - name: Outside Pressure - iir_filter: 16x - update_interval: 15s diff --git a/tests/components/bmp280/test.esp32-idf.yaml b/tests/components/bmp280/test.esp32-idf.yaml deleted file mode 100644 index aeb1cb262b..0000000000 --- a/tests/components/bmp280/test.esp32-idf.yaml +++ /dev/null @@ -1,15 +0,0 @@ -i2c: - - id: i2c_bmp280 - scl: 16 - sda: 17 - -sensor: - - platform: bmp280 - address: 0x77 - temperature: - name: Outside Temperature - oversampling: 16x - pressure: - name: Outside Pressure - iir_filter: 16x - update_interval: 15s diff --git a/tests/components/bmp280/test.esp8266-ard.yaml b/tests/components/bmp280/test.esp8266-ard.yaml deleted file mode 100644 index 5f7f85d3e2..0000000000 --- a/tests/components/bmp280/test.esp8266-ard.yaml +++ /dev/null @@ -1,15 +0,0 @@ -i2c: - - id: i2c_bmp280 - scl: 5 - sda: 4 - -sensor: - - platform: bmp280 - address: 0x77 - temperature: - name: Outside Temperature - oversampling: 16x - pressure: - name: Outside Pressure - iir_filter: 16x - update_interval: 15s diff --git a/tests/components/bmp280/test.rp2040-ard.yaml b/tests/components/bmp280/test.rp2040-ard.yaml deleted file mode 100644 index 5f7f85d3e2..0000000000 --- a/tests/components/bmp280/test.rp2040-ard.yaml +++ /dev/null @@ -1,15 +0,0 @@ -i2c: - - id: i2c_bmp280 - scl: 5 - sda: 4 - -sensor: - - platform: bmp280 - address: 0x77 - temperature: - name: Outside Temperature - oversampling: 16x - pressure: - name: Outside Pressure - iir_filter: 16x - update_interval: 15s diff --git a/tests/components/bmp280/test.esp32-c3-idf.yaml b/tests/components/bmp280_i2c/common.yaml similarity index 56% rename from tests/components/bmp280/test.esp32-c3-idf.yaml rename to tests/components/bmp280_i2c/common.yaml index 5f7f85d3e2..edf52b2cd4 100644 --- a/tests/components/bmp280/test.esp32-c3-idf.yaml +++ b/tests/components/bmp280_i2c/common.yaml @@ -1,15 +1,17 @@ i2c: - id: i2c_bmp280 - scl: 5 - sda: 4 + scl: ${scl_pin} + sda: ${sda_pin} sensor: - - platform: bmp280 + - platform: bmp280_i2c + i2c_id: i2c_bmp280 address: 0x77 temperature: + id: bmp280_temperature name: Outside Temperature - oversampling: 16x pressure: name: Outside Pressure + id: bmp280_pressure iir_filter: 16x update_interval: 15s diff --git a/tests/components/bmp280_i2c/test.esp32-ard.yaml b/tests/components/bmp280_i2c/test.esp32-ard.yaml new file mode 100644 index 0000000000..63c3bd6afd --- /dev/null +++ b/tests/components/bmp280_i2c/test.esp32-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO16 + sda_pin: GPIO17 + +<<: !include common.yaml diff --git a/tests/components/bmp280_i2c/test.esp32-c3-ard.yaml b/tests/components/bmp280_i2c/test.esp32-c3-ard.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/bmp280_i2c/test.esp32-c3-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/bmp280_i2c/test.esp32-c3-idf.yaml b/tests/components/bmp280_i2c/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/bmp280_i2c/test.esp32-c3-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/bmp280_i2c/test.esp32-idf.yaml b/tests/components/bmp280_i2c/test.esp32-idf.yaml new file mode 100644 index 0000000000..63c3bd6afd --- /dev/null +++ b/tests/components/bmp280_i2c/test.esp32-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO16 + sda_pin: GPIO17 + +<<: !include common.yaml diff --git a/tests/components/bmp280_i2c/test.esp8266-ard.yaml b/tests/components/bmp280_i2c/test.esp8266-ard.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/bmp280_i2c/test.esp8266-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/bmp280_i2c/test.rp2040-ard.yaml b/tests/components/bmp280_i2c/test.rp2040-ard.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/bmp280_i2c/test.rp2040-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/bmp280_spi/common.yaml b/tests/components/bmp280_spi/common.yaml new file mode 100644 index 0000000000..798804de5b --- /dev/null +++ b/tests/components/bmp280_spi/common.yaml @@ -0,0 +1,18 @@ +spi: + - id: spi_bmp280 + clk_pin: ${clk_pin} + mosi_pin: ${mosi_pin} + miso_pin: ${miso_pin} + +sensor: + - platform: bmp280_spi + spi_id: spi_bmp280 + cs_pin: ${cs_pin} + temperature: + id: bmp280_temperature + name: Outside Temperature + pressure: + name: Outside Pressure + id: bmp280_pressure + iir_filter: 16x + update_interval: 15s diff --git a/tests/components/bmp280_spi/test.esp32-ard.yaml b/tests/components/bmp280_spi/test.esp32-ard.yaml new file mode 100644 index 0000000000..54e027a614 --- /dev/null +++ b/tests/components/bmp280_spi/test.esp32-ard.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO16 + mosi_pin: GPIO17 + miso_pin: GPIO15 + cs_pin: GPIO5 + +<<: !include common.yaml diff --git a/tests/components/bmp280_spi/test.esp32-c3-ard.yaml b/tests/components/bmp280_spi/test.esp32-c3-ard.yaml new file mode 100644 index 0000000000..2415ba5dc6 --- /dev/null +++ b/tests/components/bmp280_spi/test.esp32-c3-ard.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO6 + mosi_pin: GPIO7 + miso_pin: GPIO5 + cs_pin: GPIO8 + +<<: !include common.yaml diff --git a/tests/components/bmp280_spi/test.esp32-c3-idf.yaml b/tests/components/bmp280_spi/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..2415ba5dc6 --- /dev/null +++ b/tests/components/bmp280_spi/test.esp32-c3-idf.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO6 + mosi_pin: GPIO7 + miso_pin: GPIO5 + cs_pin: GPIO8 + +<<: !include common.yaml diff --git a/tests/components/bmp280_spi/test.esp32-idf.yaml b/tests/components/bmp280_spi/test.esp32-idf.yaml new file mode 100644 index 0000000000..54e027a614 --- /dev/null +++ b/tests/components/bmp280_spi/test.esp32-idf.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO16 + mosi_pin: GPIO17 + miso_pin: GPIO15 + cs_pin: GPIO5 + +<<: !include common.yaml diff --git a/tests/components/bmp280_spi/test.esp8266-ard.yaml b/tests/components/bmp280_spi/test.esp8266-ard.yaml new file mode 100644 index 0000000000..dbd158d030 --- /dev/null +++ b/tests/components/bmp280_spi/test.esp8266-ard.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO14 + mosi_pin: GPIO13 + miso_pin: GPIO12 + cs_pin: GPIO15 + +<<: !include common.yaml diff --git a/tests/components/bmp280_spi/test.rp2040-ard.yaml b/tests/components/bmp280_spi/test.rp2040-ard.yaml new file mode 100644 index 0000000000..f6c3f1eeca --- /dev/null +++ b/tests/components/bmp280_spi/test.rp2040-ard.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO2 + mosi_pin: GPIO3 + miso_pin: GPIO4 + cs_pin: GPIO5 + +<<: !include common.yaml From 8bd46a43b94cb230298cf8d591af386f0022fcca Mon Sep 17 00:00:00 2001 From: Michael Hansen Date: Sun, 8 Sep 2024 19:54:20 -0500 Subject: [PATCH 2051/2101] Add voice assistant announce (#7377) --- esphome/components/api/api.proto | 17 ++++++ esphome/components/api/api_connection.cpp | 10 ++++ esphome/components/api/api_connection.h | 1 + esphome/components/api/api_pb2.cpp | 53 +++++++++++++++++++ esphome/components/api/api_pb2.h | 23 ++++++++ esphome/components/api/api_pb2_service.cpp | 21 ++++++++ esphome/components/api/api_pb2_service.h | 6 +++ .../voice_assistant/voice_assistant.cpp | 16 ++++++ .../voice_assistant/voice_assistant.h | 1 + 9 files changed, 148 insertions(+) diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index ad6fc79cf3..1c40e8014e 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -1553,6 +1553,23 @@ message VoiceAssistantTimerEventResponse { bool is_active = 6; } +message VoiceAssistantAnnounceRequest { + option (id) = 119; + option (source) = SOURCE_CLIENT; + option (ifdef) = "USE_VOICE_ASSISTANT"; + + string media_id = 1; + string text = 2; +} + +message VoiceAssistantAnnounceFinished { + option (id) = 120; + option (source) = SOURCE_SERVER; + option (ifdef) = "USE_VOICE_ASSISTANT"; + + bool success = 1; +} + // ==================== ALARM CONTROL PANEL ==================== enum AlarmControlPanelState { ALARM_STATE_DISARMED = 0; diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index a655d06e66..6b7051a704 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1213,6 +1213,16 @@ void APIConnection::on_voice_assistant_timer_event_response(const VoiceAssistant } }; +void APIConnection::on_voice_assistant_announce_request(const VoiceAssistantAnnounceRequest &msg) { + if (voice_assistant::global_voice_assistant != nullptr) { + if (voice_assistant::global_voice_assistant->get_api_connection() != this) { + return; + } + + voice_assistant::global_voice_assistant->on_announce(msg); + } +} + #endif #ifdef USE_ALARM_CONTROL_PANEL diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index 714e806470..e8d66a5e07 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -151,6 +151,7 @@ class APIConnection : public APIServerConnection { 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; #endif #ifdef USE_ALARM_CONTROL_PANEL diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index c944d0dae8..2a1552d6fc 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -7061,6 +7061,59 @@ void VoiceAssistantTimerEventResponse::dump_to(std::string &out) const { out.append("}"); } #endif +bool VoiceAssistantAnnounceRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) { + switch (field_id) { + case 1: { + this->media_id = value.as_string(); + return true; + } + case 2: { + this->text = value.as_string(); + return true; + } + default: + return false; + } +} +void VoiceAssistantAnnounceRequest::encode(ProtoWriteBuffer buffer) const { + buffer.encode_string(1, this->media_id); + buffer.encode_string(2, this->text); +} +#ifdef HAS_PROTO_MESSAGE_DUMP +void VoiceAssistantAnnounceRequest::dump_to(std::string &out) const { + __attribute__((unused)) char buffer[64]; + out.append("VoiceAssistantAnnounceRequest {\n"); + out.append(" media_id: "); + out.append("'").append(this->media_id).append("'"); + out.append("\n"); + + out.append(" text: "); + out.append("'").append(this->text).append("'"); + out.append("\n"); + out.append("}"); +} +#endif +bool VoiceAssistantAnnounceFinished::decode_varint(uint32_t field_id, ProtoVarInt value) { + switch (field_id) { + case 1: { + this->success = value.as_bool(); + return true; + } + default: + return false; + } +} +void VoiceAssistantAnnounceFinished::encode(ProtoWriteBuffer buffer) const { buffer.encode_bool(1, this->success); } +#ifdef HAS_PROTO_MESSAGE_DUMP +void VoiceAssistantAnnounceFinished::dump_to(std::string &out) const { + __attribute__((unused)) char buffer[64]; + out.append("VoiceAssistantAnnounceFinished {\n"); + out.append(" success: "); + out.append(YESNO(this->success)); + out.append("\n"); + out.append("}"); +} +#endif bool ListEntitiesAlarmControlPanelResponse::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { case 6: { diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index 3f609c793c..6fab1f57e0 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -1825,6 +1825,29 @@ class VoiceAssistantTimerEventResponse : public ProtoMessage { bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; bool decode_varint(uint32_t field_id, ProtoVarInt value) override; }; +class VoiceAssistantAnnounceRequest : public ProtoMessage { + public: + std::string media_id{}; + std::string text{}; + void encode(ProtoWriteBuffer buffer) const override; +#ifdef HAS_PROTO_MESSAGE_DUMP + void dump_to(std::string &out) const override; +#endif + + protected: + bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; +}; +class VoiceAssistantAnnounceFinished : public ProtoMessage { + public: + bool success{false}; + void encode(ProtoWriteBuffer buffer) const override; +#ifdef HAS_PROTO_MESSAGE_DUMP + void dump_to(std::string &out) const override; +#endif + + protected: + bool decode_varint(uint32_t field_id, ProtoVarInt value) override; +}; class ListEntitiesAlarmControlPanelResponse : public ProtoMessage { public: std::string object_id{}; diff --git a/esphome/components/api/api_pb2_service.cpp b/esphome/components/api/api_pb2_service.cpp index 269a755e9e..faa977389a 100644 --- a/esphome/components/api/api_pb2_service.cpp +++ b/esphome/components/api/api_pb2_service.cpp @@ -486,6 +486,16 @@ bool APIServerConnectionBase::send_voice_assistant_audio(const VoiceAssistantAud #endif #ifdef USE_VOICE_ASSISTANT #endif +#ifdef USE_VOICE_ASSISTANT +#endif +#ifdef USE_VOICE_ASSISTANT +bool APIServerConnectionBase::send_voice_assistant_announce_finished(const VoiceAssistantAnnounceFinished &msg) { +#ifdef HAS_PROTO_MESSAGE_DUMP + ESP_LOGVV(TAG, "send_voice_assistant_announce_finished: %s", msg.dump().c_str()); +#endif + return this->send_message_(msg, 120); +} +#endif #ifdef USE_ALARM_CONTROL_PANEL bool APIServerConnectionBase::send_list_entities_alarm_control_panel_response( const ListEntitiesAlarmControlPanelResponse &msg) { @@ -1135,6 +1145,17 @@ bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, ESP_LOGVV(TAG, "on_update_command_request: %s", msg.dump().c_str()); #endif this->on_update_command_request(msg); +#endif + break; + } + case 119: { +#ifdef USE_VOICE_ASSISTANT + 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()); +#endif + this->on_voice_assistant_announce_request(msg); #endif break; } diff --git a/esphome/components/api/api_pb2_service.h b/esphome/components/api/api_pb2_service.h index 83bfc2ed98..f3803ad628 100644 --- a/esphome/components/api/api_pb2_service.h +++ b/esphome/components/api/api_pb2_service.h @@ -247,6 +247,12 @@ class APIServerConnectionBase : public ProtoService { #ifdef USE_VOICE_ASSISTANT virtual 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){}; +#endif +#ifdef USE_VOICE_ASSISTANT + bool send_voice_assistant_announce_finished(const VoiceAssistantAnnounceFinished &msg); +#endif #ifdef USE_ALARM_CONTROL_PANEL bool send_list_entities_alarm_control_panel_response(const ListEntitiesAlarmControlPanelResponse &msg); #endif diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index 43c7428858..577de630fb 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -396,6 +396,10 @@ void VoiceAssistant::loop() { this->set_timeout("playing", 2000, [this]() { this->cancel_timeout("speaker-timeout"); this->set_state_(State::IDLE, State::IDLE); + + api::VoiceAssistantAnnounceFinished msg; + msg.success = true; + this->api_client_->send_voice_assistant_announce_finished(msg); }); } break; @@ -866,6 +870,18 @@ void VoiceAssistant::timer_tick_() { 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->media_player_->make_call().set_media_url(msg.media_id).set_announcement(true).perform(); + this->set_state_(State::STREAMING_RESPONSE, State::STREAMING_RESPONSE); + this->tts_end_trigger_->trigger(msg.media_id); + this->end_trigger_->trigger(); + } +#endif +} + VoiceAssistant *global_voice_assistant = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) } // namespace voice_assistant diff --git a/esphome/components/voice_assistant/voice_assistant.h b/esphome/components/voice_assistant/voice_assistant.h index 88cb0dd413..b0a172332f 100644 --- a/esphome/components/voice_assistant/voice_assistant.h +++ b/esphome/components/voice_assistant/voice_assistant.h @@ -132,6 +132,7 @@ class VoiceAssistant : public Component { void on_event(const api::VoiceAssistantEventResponse &msg); void on_audio(const api::VoiceAssistantAudio &msg); void on_timer_event(const api::VoiceAssistantTimerEventResponse &msg); + void on_announce(const api::VoiceAssistantAnnounceRequest &msg); bool is_running() const { return this->state_ != State::IDLE; } void set_continuous(bool continuous) { this->continuous_ = continuous; } From 9722876ef667a628e1df3d7623e73db14c8d2d2f Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Mon, 9 Sep 2024 13:59:09 +1000 Subject: [PATCH 2052/2101] [lvgl] Msgbox fixes and enhancements (#7380) --- esphome/components/lvgl/automation.py | 16 +++++--- esphome/components/lvgl/defines.py | 1 + esphome/components/lvgl/widgets/__init__.py | 2 + esphome/components/lvgl/widgets/msgbox.py | 41 +++++++++++++-------- tests/components/lvgl/lvgl-package.yaml | 24 ++++++++++++ 5 files changed, 63 insertions(+), 21 deletions(-) diff --git a/esphome/components/lvgl/automation.py b/esphome/components/lvgl/automation.py index 8138551c30..cdc7553e81 100644 --- a/esphome/components/lvgl/automation.py +++ b/esphome/components/lvgl/automation.py @@ -229,19 +229,23 @@ 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") - return await action_to_code( - await get_widgets(config), do_hide, action_id, template_arg, args - ) + widgets = [ + widget.outer if widget.outer else widget for widget in await get_widgets(config) + ] + return await action_to_code(widgets, do_hide, action_id, template_arg, args) @automation.register_action("lvgl.widget.show", ObjUpdateAction, LIST_ACTION_SCHEMA) 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") + if widget.move_to_foreground: + lv_obj.move_foreground(widget.obj) - return await action_to_code( - await get_widgets(config), do_show, action_id, template_arg, args - ) + widgets = [ + widget.outer if widget.outer else widget for widget in await get_widgets(config) + ] + return await action_to_code(widgets, do_show, action_id, template_arg, args) def focused_id(value): diff --git a/esphome/components/lvgl/defines.py b/esphome/components/lvgl/defines.py index e05bf52120..ee8472f90d 100644 --- a/esphome/components/lvgl/defines.py +++ b/esphome/components/lvgl/defines.py @@ -374,6 +374,7 @@ CONF_ANTIALIAS = "antialias" CONF_ARC_LENGTH = "arc_length" CONF_AUTO_START = "auto_start" CONF_BACKGROUND_STYLE = "background_style" +CONF_BUTTON_STYLE = "button_style" CONF_DECIMAL_PLACES = "decimal_places" CONF_COLUMN = "column" CONF_DIGITS = "digits" diff --git a/esphome/components/lvgl/widgets/__init__.py b/esphome/components/lvgl/widgets/__init__.py index ae06bf20b0..e093cebd16 100644 --- a/esphome/components/lvgl/widgets/__init__.py +++ b/esphome/components/lvgl/widgets/__init__.py @@ -89,6 +89,8 @@ class Widget: self.obj = MockObj(f"{self.var}->obj") else: self.obj = var + self.outer = None + self.move_to_foreground = False @staticmethod def create(name, var, wtype: WidgetType, config: dict = None): diff --git a/esphome/components/lvgl/widgets/msgbox.py b/esphome/components/lvgl/widgets/msgbox.py index c377af6bde..1af4ed6e05 100644 --- a/esphome/components/lvgl/widgets/msgbox.py +++ b/esphome/components/lvgl/widgets/msgbox.py @@ -1,11 +1,12 @@ from esphome import config_validation as cv -from esphome.const import CONF_BUTTON, CONF_ID, CONF_TEXT +from esphome.const import CONF_BUTTON, CONF_ID, CONF_ITEMS, CONF_TEXT from esphome.core import ID from esphome.cpp_generator import new_Pvariable, static_const_array from esphome.cpp_types import nullptr from ..defines import ( CONF_BODY, + CONF_BUTTON_STYLE, CONF_BUTTONS, CONF_CLOSE_BUTTON, CONF_MSGBOXES, @@ -25,7 +26,7 @@ from ..lvcode import ( lv_obj, lv_Pvariable, ) -from ..schemas import STYLE_SCHEMA, STYLED_TEXT_SCHEMA, container_schema +from ..schemas import STYLE_SCHEMA, STYLED_TEXT_SCHEMA, container_schema, part_schema from ..styles import TOP_LAYER from ..types import LV_EVENT, char_ptr, lv_obj_t from . import Widget, set_obj_properties @@ -48,9 +49,10 @@ 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): STYLED_TEXT_SCHEMA, + cv.Optional(CONF_BODY, default=""): STYLED_TEXT_SCHEMA, cv.Optional(CONF_BUTTONS): cv.ensure_list(BUTTONMATRIX_BUTTON_SCHEMA), - cv.Optional(CONF_CLOSE_BUTTON): lv_bool, + cv.Optional(CONF_BUTTON_STYLE): part_schema(buttonmatrix_spec), + cv.Optional(CONF_CLOSE_BUTTON, default=True): lv_bool, cv.GenerateID(CONF_BUTTON_TEXT_LIST_ID): cv.declare_id(char_ptr), } ), @@ -74,7 +76,8 @@ async def msgbox_to_code(conf): ) lvgl_components_required.add("BUTTONMATRIX") messagebox_id = conf[CONF_ID] - outer = lv_Pvariable(lv_obj_t, messagebox_id.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_", @@ -82,8 +85,11 @@ async def msgbox_to_code(conf): type=lv_buttonmatrix_t, ) ) - msgbox = lv_Pvariable(lv_obj_t, f"{messagebox_id.id}_msgbox") - outer_widget = Widget.create(messagebox_id, outer, obj_spec, conf) + msgbox = lv_Pvariable(lv_obj_t, messagebox_id.id) + outer_widget = Widget.create(outer_id, outer, obj_spec, conf) + 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 ) @@ -92,10 +98,8 @@ async def msgbox_to_code(conf): ) text_id = conf[CONF_BUTTON_TEXT_LIST_ID] text_list = static_const_array(text_id, text_list) - if (text := conf.get(CONF_BODY)) is not None: - text = await lv_text.process(text.get(CONF_TEXT)) - if (title := conf.get(CONF_TITLE)) is not None: - title = await lv_text.process(title.get(CONF_TEXT)) + 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)) @@ -111,20 +115,27 @@ async def msgbox_to_code(conf): ) lv_obj.set_style_align(msgbox, literal("LV_ALIGN_CENTER"), 0) lv_add(buttonmatrix.set_obj(lv_expr.msgbox_get_btns(msgbox))) - await set_obj_properties(outer_widget, conf) + 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) + async with LambdaContext(EVENT_ARG, where=messagebox_id) as close_action: + outer_widget.add_flag("LV_OBJ_FLAG_HIDDEN") if close_button: - async with LambdaContext(EVENT_ARG, where=messagebox_id) as context: - outer_widget.add_flag("LV_OBJ_FLAG_HIDDEN") with LocalVariable( "close_btn_", lv_obj_t, lv_expr.msgbox_get_close_btn(msgbox) ) as close_btn: lv_obj.remove_event_cb(close_btn, nullptr) lv_obj.add_event_cb( close_btn, - await context.get_lambda(), + await close_action.get_lambda(), LV_EVENT.CLICKED, nullptr, ) + else: + lv_obj.add_event_cb( + 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) diff --git a/tests/components/lvgl/lvgl-package.yaml b/tests/components/lvgl/lvgl-package.yaml index 0feb6d6ce6..0db6a6a995 100644 --- a/tests/components/lvgl/lvgl-package.yaml +++ b/tests/components/lvgl/lvgl-package.yaml @@ -52,6 +52,29 @@ lvgl: - touchscreen_id: tft_touch long_press_repeat_time: 200ms long_press_time: 500ms + + msgboxes: + - id: message_box + close_button: true + title: Messagebox + bg_color: 0xffff + body: + text: This is a sample messagebox + bg_color: 0x808080 + button_style: + bg_color: 0xff00 + border_width: 4 + buttons: + - id: msgbox_button + text: Button + - id: msgbox_apply + text: "Close" + on_click: + then: + - lvgl.widget.hide: message_box + - id: simple_msgbox + title: Simple + pages: - id: page1 on_load: @@ -98,6 +121,7 @@ lvgl: - lvgl.update: disp_bg_color: 0xffff00 disp_bg_image: cat_image + - lvgl.widget.show: message_box - label: text: "Hello shiny day" text_color: 0xFFFFFF From 32995a352bc224da579056969192c250717b8b51 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Mon, 9 Sep 2024 06:05:09 +0100 Subject: [PATCH 2053/2101] libretiny: Allow specifying version of explicitly imported sources (#7408) --- esphome/components/libretiny/__init__.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/esphome/components/libretiny/__init__.py b/esphome/components/libretiny/__init__.py index a8034f8fab..a640e2e9b9 100644 --- a/esphome/components/libretiny/__init__.py +++ b/esphome/components/libretiny/__init__.py @@ -1,10 +1,6 @@ import json import logging -from os.path import ( - dirname, - isfile, - join, -) +from os.path import dirname, isfile, join import esphome.codegen as cg import esphome.config_validation as cv @@ -282,10 +278,10 @@ async def component_to_code(config): # if platform version is a valid version constraint, prefix the default package framework = config[CONF_FRAMEWORK] cv.platformio_version_constraint(framework[CONF_VERSION]) - if str(framework[CONF_VERSION]) != "0.0.0": - cg.add_platformio_option("platform", f"libretiny @ {framework[CONF_VERSION]}") - elif framework[CONF_SOURCE]: + if framework[CONF_SOURCE]: cg.add_platformio_option("platform", framework[CONF_SOURCE]) + elif str(framework[CONF_VERSION]) != "0.0.0": + cg.add_platformio_option("platform", f"libretiny @ {framework[CONF_VERSION]}") else: cg.add_platformio_option("platform", "libretiny") From 7a93dde5d4611c22ee9471640f9c7e848bbe7d7e Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Mon, 9 Sep 2024 06:05:19 +0100 Subject: [PATCH 2054/2101] [libretiny] Report version 1.7.0 for 'dev' and 'latest' (#7415) --- esphome/components/libretiny/__init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/esphome/components/libretiny/__init__.py b/esphome/components/libretiny/__init__.py index a640e2e9b9..9ba889f493 100644 --- a/esphome/components/libretiny/__init__.py +++ b/esphome/components/libretiny/__init__.py @@ -172,9 +172,10 @@ def _notify_old_style(config): # NOTE: Keep this in mind when updating the recommended version: # * For all constants below, update platformio.ini (in this repo) +# The dev and latest branches will be at *least* this version, which is what matters. ARDUINO_VERSIONS = { - "dev": (cv.Version(0, 0, 0), "https://github.com/libretiny-eu/libretiny.git"), - "latest": (cv.Version(0, 0, 0), None), + "dev": (cv.Version(1, 7, 0), "https://github.com/libretiny-eu/libretiny.git"), + "latest": (cv.Version(1, 7, 0), "libretiny"), "recommended": (cv.Version(1, 5, 1), None), } From c90dcfc0ca681ffeb025cf520a2d9ac458c0e510 Mon Sep 17 00:00:00 2001 From: Anton Viktorov Date: Mon, 9 Sep 2024 19:25:37 +0200 Subject: [PATCH 2055/2101] LTR-501, LTR-301, LTR-558 Series of Lite-On Light (ALS) and Proximity(PS) sensors (#6262) Co-authored-by: root Co-authored-by: Keith Burzinski --- CODEOWNERS | 1 + esphome/components/ltr501/__init__.py | 1 + esphome/components/ltr501/ltr501.cpp | 542 ++++++++++++++++++ esphome/components/ltr501/ltr501.h | 184 ++++++ .../components/ltr501/ltr_definitions_501.h | 260 +++++++++ esphome/components/ltr501/sensor.py | 274 +++++++++ esphome/components/ltr_als_ps/sensor.py | 4 +- esphome/components/veml7700/sensor.py | 4 +- esphome/const.py | 2 + tests/components/ltr501/common.yaml | 9 + tests/components/ltr501/test.esp32-ard.yaml | 6 + .../components/ltr501/test.esp32-c3-ard.yaml | 6 + .../components/ltr501/test.esp32-c3-idf.yaml | 6 + tests/components/ltr501/test.esp32-idf.yaml | 6 + tests/components/ltr501/test.esp8266-ard.yaml | 6 + tests/components/ltr501/test.rp2040-ard.yaml | 6 + 16 files changed, 1313 insertions(+), 4 deletions(-) create mode 100644 esphome/components/ltr501/__init__.py create mode 100644 esphome/components/ltr501/ltr501.cpp create mode 100644 esphome/components/ltr501/ltr501.h create mode 100644 esphome/components/ltr501/ltr_definitions_501.h create mode 100644 esphome/components/ltr501/sensor.py create mode 100644 tests/components/ltr501/common.yaml create mode 100644 tests/components/ltr501/test.esp32-ard.yaml create mode 100644 tests/components/ltr501/test.esp32-c3-ard.yaml create mode 100644 tests/components/ltr501/test.esp32-c3-idf.yaml create mode 100644 tests/components/ltr501/test.esp32-idf.yaml create mode 100644 tests/components/ltr501/test.esp8266-ard.yaml create mode 100644 tests/components/ltr501/test.rp2040-ard.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 1d4df3ccb8..0b1b88fbc8 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -227,6 +227,7 @@ esphome/components/lilygo_t5_47/touchscreen/* @jesserockz esphome/components/lock/* @esphome/core esphome/components/logger/* @esphome/core esphome/components/ltr390/* @latonita @sjtrny +esphome/components/ltr501/* @latonita esphome/components/ltr_als_ps/* @latonita esphome/components/lvgl/* @clydebarrow esphome/components/m5stack_8angle/* @rnauber diff --git a/esphome/components/ltr501/__init__.py b/esphome/components/ltr501/__init__.py new file mode 100644 index 0000000000..dd06cfffea --- /dev/null +++ b/esphome/components/ltr501/__init__.py @@ -0,0 +1 @@ +CODEOWNERS = ["@latonita"] diff --git a/esphome/components/ltr501/ltr501.cpp b/esphome/components/ltr501/ltr501.cpp new file mode 100644 index 0000000000..4f4e26f44f --- /dev/null +++ b/esphome/components/ltr501/ltr501.cpp @@ -0,0 +1,542 @@ +#include "ltr501.h" +#include "esphome/core/application.h" +#include "esphome/core/log.h" +#include "esphome/core/helpers.h" + +using esphome::i2c::ErrorCode; + +namespace esphome { +namespace ltr501 { + +static const char *const TAG = "ltr501"; + +static const uint8_t MAX_TRIES = 5; +static const uint8_t MAX_SENSITIVITY_ADJUSTMENTS = 10; + +struct GainTimePair { + AlsGain501 gain; + IntegrationTime501 time; +}; + +bool operator==(const GainTimePair &lhs, const GainTimePair &rhs) { + return lhs.gain == rhs.gain && lhs.time == rhs.time; +} + +bool operator!=(const GainTimePair &lhs, const GainTimePair &rhs) { + return !(lhs.gain == rhs.gain && lhs.time == rhs.time); +} + +template T get_next(const T (&array)[size], const T val) { + size_t i = 0; + size_t idx = -1; + while (idx == -1 && i < size) { + if (array[i] == val) { + idx = i; + break; + } + i++; + } + if (idx == -1 || i + 1 >= size) + return val; + return array[i + 1]; +} + +template T get_prev(const T (&array)[size], const T val) { + size_t i = size - 1; + size_t idx = -1; + while (idx == -1 && i > 0) { + if (array[i] == val) { + idx = i; + break; + } + i--; + } + if (idx == -1 || i == 0) + return val; + return array[i - 1]; +} + +static uint16_t get_itime_ms(IntegrationTime501 time) { + static const uint16_t ALS_INT_TIME[4] = {100, 50, 200, 400}; + return ALS_INT_TIME[time & 0b11]; +} + +static uint16_t get_meas_time_ms(MeasurementRepeatRate rate) { + static const uint16_t ALS_MEAS_RATE[8] = {50, 100, 200, 500, 1000, 2000, 2000, 2000}; + return ALS_MEAS_RATE[rate & 0b111]; +} + +static float get_gain_coeff(AlsGain501 gain) { return gain == AlsGain501::GAIN_1 ? 1.0f : 150.0f; } + +static float get_ps_gain_coeff(PsGain501 gain) { + static const float PS_GAIN[4] = {1, 4, 8, 16}; + return PS_GAIN[gain & 0b11]; +} + +void LTRAlsPs501Component::setup() { + ESP_LOGCONFIG(TAG, "Setting up LTR-501/301/558"); + // As per datasheet we need to wait at least 100ms after power on to get ALS chip responsive + this->set_timeout(100, [this]() { this->state_ = State::DELAYED_SETUP; }); +} + +void LTRAlsPs501Component::dump_config() { + auto get_device_type = [](LtrType typ) { + switch (typ) { + case LtrType::LTR_TYPE_ALS_ONLY: + return "ALS only"; + case LtrType::LTR_TYPE_PS_ONLY: + return "PS only"; + case LtrType::LTR_TYPE_ALS_AND_PS: + return "Als + PS"; + default: + return "Unknown"; + } + }; + + LOG_I2C_DEVICE(this); + ESP_LOGCONFIG(TAG, " Device type: %s", get_device_type(this->ltr_type_)); + ESP_LOGCONFIG(TAG, " Automatic mode: %s", ONOFF(this->automatic_mode_enabled_)); + ESP_LOGCONFIG(TAG, " Gain: %.0fx", get_gain_coeff(this->gain_)); + ESP_LOGCONFIG(TAG, " Integration time: %d ms", get_itime_ms(this->integration_time_)); + ESP_LOGCONFIG(TAG, " Measurement repeat rate: %d ms", get_meas_time_ms(this->repeat_rate_)); + ESP_LOGCONFIG(TAG, " Glass attenuation factor: %f", this->glass_attenuation_factor_); + ESP_LOGCONFIG(TAG, " Proximity gain: %.0fx", get_ps_gain_coeff(this->ps_gain_)); + ESP_LOGCONFIG(TAG, " Proximity cooldown time: %d s", this->ps_cooldown_time_s_); + ESP_LOGCONFIG(TAG, " Proximity high threshold: %d", this->ps_threshold_high_); + ESP_LOGCONFIG(TAG, " Proximity low threshold: %d", this->ps_threshold_low_); + + LOG_UPDATE_INTERVAL(this); + + LOG_SENSOR(" ", "ALS calculated lux", this->ambient_light_sensor_); + LOG_SENSOR(" ", "CH1 Infrared counts", this->infrared_counts_sensor_); + LOG_SENSOR(" ", "CH0 Visible+IR counts", this->full_spectrum_counts_sensor_); + LOG_SENSOR(" ", "Actual gain", this->actual_gain_sensor_); + + if (this->is_failed()) { + ESP_LOGE(TAG, "Communication with I2C LTR-501/301/558 failed!"); + } +} + +void LTRAlsPs501Component::update() { + if (!this->is_als_()) { + ESP_LOGW(TAG, "Update. ALS data not available. Change configuration to ALS or ALS_PS."); + return; + } + if (this->is_ready() && this->is_als_() && this->state_ == State::IDLE) { + ESP_LOGV(TAG, "Update. Initiating new ALS data collection."); + + this->state_ = this->automatic_mode_enabled_ ? State::COLLECTING_DATA_AUTO : State::WAITING_FOR_DATA; + + this->als_readings_.ch0 = 0; + this->als_readings_.ch1 = 0; + this->als_readings_.gain = this->gain_; + this->als_readings_.integration_time = this->integration_time_; + this->als_readings_.lux = 0; + this->als_readings_.number_of_adjustments = 0; + + } else { + ESP_LOGV(TAG, "Update. Component not ready yet."); + } +} + +void LTRAlsPs501Component::loop() { + ErrorCode err = i2c::ERROR_OK; + static uint8_t tries{0}; + + switch (this->state_) { + case State::DELAYED_SETUP: + err = this->write(nullptr, 0); + if (err != i2c::ERROR_OK) { + ESP_LOGW(TAG, "i2c connection failed"); + this->mark_failed(); + } + this->configure_reset_(); + if (this->is_als_()) { + this->configure_als_(); + this->configure_integration_time_(this->integration_time_); + } + if (this->is_ps_()) { + this->configure_ps_(); + } + + this->state_ = State::IDLE; + break; + + case State::IDLE: + if (this->is_ps_()) { + this->check_and_trigger_ps_(); + } + break; + + case State::WAITING_FOR_DATA: + if (this->is_als_data_ready_(this->als_readings_) == DataAvail::DATA_OK) { + 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) { + ESP_LOGW(TAG, "Can't get data after several tries. Aborting."); + tries = 0; + this->status_set_warning(); + this->state_ = State::IDLE; + return; + } else { + tries++; + } + break; + + case State::COLLECTING_DATA_AUTO: + case State::DATA_COLLECTED: + // first measurement in auto mode (COLLECTING_DATA_AUTO state) require device reconfiguration + if (this->state_ == State::COLLECTING_DATA_AUTO || this->are_adjustments_required_(this->als_readings_)) { + this->state_ = State::ADJUSTMENT_IN_PROGRESS; + ESP_LOGD(TAG, "Reconfiguring sensitivity: gain = %.0fx, time = %d ms", get_gain_coeff(this->als_readings_.gain), + get_itime_ms(this->als_readings_.integration_time)); + this->configure_integration_time_(this->als_readings_.integration_time); + this->configure_gain_(this->als_readings_.gain); + // if sensitivity adjustment needed - need to wait for first data samples after setting new parameters + this->set_timeout(2 * get_meas_time_ms(this->repeat_rate_), + [this]() { this->state_ = State::WAITING_FOR_DATA; }); + } else { + this->state_ = State::READY_TO_PUBLISH; + } + break; + + case State::ADJUSTMENT_IN_PROGRESS: + // nothing to be done, just waiting for the timeout + break; + + case State::READY_TO_PUBLISH: + this->publish_data_part_1_(this->als_readings_); + this->state_ = State::KEEP_PUBLISHING; + break; + + case State::KEEP_PUBLISHING: + this->publish_data_part_2_(this->als_readings_); + this->status_clear_warning(); + this->state_ = State::IDLE; + break; + + default: + break; + } +} + +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; + 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; + 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(); + } + } +} + +bool LTRAlsPs501Component::check_part_number_() { + uint8_t manuf_id = this->reg((uint8_t) CommandRegisters::MANUFAC_ID).get(); + if (manuf_id != 0x05) { // 0x05 is Lite-On Semiconductor Corp. ID + ESP_LOGW(TAG, "Unknown manufacturer ID: 0x%02X", manuf_id); + this->mark_failed(); + return false; + } + + // Things getting not really funny here, we can't identify device type by part number ID + // ======================== ========= ===== ================= + // Device Part ID Rev Capabilities + // ======================== ========= ===== ================= + // ltr-558als 0x08 0 als + ps + // ltr-501als 0x08 0 als + ps + // ltr-301als - 0x08 0 als only + + PartIdRegister part_id{0}; + part_id.raw = this->reg((uint8_t) CommandRegisters::PART_ID).get(); + if (part_id.part_number_id != 0x08) { + ESP_LOGW(TAG, "Unknown part number ID: 0x%02X. LTR-501/301 shall have 0x08. It might not work properly.", + part_id.part_number_id); + this->status_set_warning(); + return true; + } + return true; +} + +void LTRAlsPs501Component::configure_reset_() { + ESP_LOGV(TAG, "Resetting"); + + AlsControlRegister501 als_ctrl{0}; + als_ctrl.sw_reset = true; + this->reg((uint8_t) CommandRegisters::ALS_CONTR) = als_ctrl.raw; + delay(2); + + uint8_t tries = MAX_TRIES; + do { + ESP_LOGV(TAG, "Waiting chip to reset"); + delay(2); + als_ctrl.raw = this->reg((uint8_t) CommandRegisters::ALS_CONTR).get(); + } while (als_ctrl.sw_reset && tries--); // while sw reset bit is on - keep waiting + + if (als_ctrl.sw_reset) { + ESP_LOGW(TAG, "Reset failed"); + } +} + +void LTRAlsPs501Component::configure_als_() { + AlsControlRegister501 als_ctrl{0}; + als_ctrl.sw_reset = false; + als_ctrl.als_mode_active = true; + als_ctrl.gain = this->gain_; + + ESP_LOGV(TAG, "Setting active mode and gain reg 0x%02X", als_ctrl.raw); + this->reg((uint8_t) CommandRegisters::ALS_CONTR) = als_ctrl.raw; + delay(5); + + uint8_t tries = MAX_TRIES; + do { + ESP_LOGV(TAG, "Waiting for ALS device to become active..."); + delay(2); + als_ctrl.raw = this->reg((uint8_t) CommandRegisters::ALS_CONTR).get(); + } while (!als_ctrl.als_mode_active && tries--); // while active mode is not set - keep waiting + + if (!als_ctrl.als_mode_active) { + ESP_LOGW(TAG, "Failed to activate ALS device"); + } +} + +void LTRAlsPs501Component::configure_ps_() { + PsMeasurementRateRegister ps_meas{0}; + ps_meas.ps_measurement_rate = PsMeasurementRate::PS_MEAS_RATE_50MS; + this->reg((uint8_t) CommandRegisters::PS_MEAS_RATE) = ps_meas.raw; + + PsControlRegister501 ps_ctrl{0}; + ps_ctrl.ps_mode_active = true; + ps_ctrl.ps_mode_xxx = true; + this->reg((uint8_t) CommandRegisters::PS_CONTR) = ps_ctrl.raw; +} + +uint16_t LTRAlsPs501Component::read_ps_data_() { + AlsPsStatusRegister als_status{0}; + als_status.raw = this->reg((uint8_t) CommandRegisters::ALS_PS_STATUS).get(); + if (!als_status.ps_new_data) { + return this->ps_readings_; + } + + uint8_t ps_low = this->reg((uint8_t) CommandRegisters::PS_DATA_0).get(); + PsData1Register ps_high; + ps_high.raw = this->reg((uint8_t) CommandRegisters::PS_DATA_1).get(); + + uint16_t val = encode_uint16(ps_high.ps_data_high, ps_low); + return val; +} + +void LTRAlsPs501Component::configure_gain_(AlsGain501 gain) { + AlsControlRegister501 als_ctrl{0}; + als_ctrl.als_mode_active = true; + als_ctrl.gain = gain; + this->reg((uint8_t) CommandRegisters::ALS_CONTR) = als_ctrl.raw; + delay(2); + + AlsControlRegister501 read_als_ctrl{0}; + read_als_ctrl.raw = this->reg((uint8_t) CommandRegisters::ALS_CONTR).get(); + if (read_als_ctrl.gain != gain) { + ESP_LOGW(TAG, "Failed to set gain. We will try one more time."); + this->reg((uint8_t) CommandRegisters::ALS_CONTR) = als_ctrl.raw; + delay(2); + } +} + +void LTRAlsPs501Component::configure_integration_time_(IntegrationTime501 time) { + MeasurementRateRegister501 meas{0}; + meas.measurement_repeat_rate = this->repeat_rate_; + meas.integration_time = time; + this->reg((uint8_t) CommandRegisters::MEAS_RATE) = meas.raw; + delay(2); + + MeasurementRateRegister501 read_meas{0}; + read_meas.raw = this->reg((uint8_t) CommandRegisters::MEAS_RATE).get(); + if (read_meas.integration_time != time) { + ESP_LOGW(TAG, "Failed to set integration time. We will try one more time."); + this->reg((uint8_t) CommandRegisters::MEAS_RATE) = meas.raw; + delay(2); + } +} + +DataAvail LTRAlsPs501Component::is_als_data_ready_(AlsReadings &data) { + AlsPsStatusRegister als_status{0}; + als_status.raw = this->reg((uint8_t) CommandRegisters::ALS_PS_STATUS).get(); + if (!als_status.als_new_data) + return DataAvail::NO_DATA; + ESP_LOGV(TAG, "Data ready, reported gain is %.0fx", get_gain_coeff(als_status.gain)); + if (data.gain != als_status.gain) { + ESP_LOGW(TAG, "Actual gain differs from requested (%.0f)", get_gain_coeff(data.gain)); + return DataAvail::BAD_DATA; + } + data.gain = als_status.gain; + return DataAvail::DATA_OK; +} + +void LTRAlsPs501Component::read_sensor_data_(AlsReadings &data) { + data.ch1 = 0; + data.ch0 = 0; + uint8_t ch1_0 = this->reg((uint8_t) CommandRegisters::ALS_DATA_CH1_0).get(); + uint8_t ch1_1 = this->reg((uint8_t) CommandRegisters::ALS_DATA_CH1_1).get(); + uint8_t ch0_0 = this->reg((uint8_t) CommandRegisters::ALS_DATA_CH0_0).get(); + uint8_t ch0_1 = this->reg((uint8_t) CommandRegisters::ALS_DATA_CH0_1).get(); + data.ch1 = encode_uint16(ch1_1, ch1_0); + data.ch0 = encode_uint16(ch0_1, ch0_0); + + ESP_LOGD(TAG, "Got sensor data: CH1 = %d, CH0 = %d", data.ch1, data.ch0); +} + +bool LTRAlsPs501Component::are_adjustments_required_(AlsReadings &data) { + if (!this->automatic_mode_enabled_) + return false; + + // sometimes sensors fail to change sensitivity. this prevents us from infinite loop + if (data.number_of_adjustments++ > MAX_SENSITIVITY_ADJUSTMENTS) { + ESP_LOGW(TAG, "Too many sensitivity adjustments done. Something wrong with the sensor. Stopping."); + return false; + } + + ESP_LOGV(TAG, "Adjusting sensitivity, run #%d", data.number_of_adjustments); + + // available combinations of gain and integration times: + static const GainTimePair GAIN_TIME_PAIRS[] = { + {AlsGain501::GAIN_1, INTEGRATION_TIME_50MS}, {AlsGain501::GAIN_1, INTEGRATION_TIME_100MS}, + {AlsGain501::GAIN_150, INTEGRATION_TIME_100MS}, {AlsGain501::GAIN_150, INTEGRATION_TIME_200MS}, + {AlsGain501::GAIN_150, INTEGRATION_TIME_400MS}, + }; + + GainTimePair current_pair = {data.gain, data.integration_time}; + + // Here comes funky business with this sensor. it has no internal error checking mechanism + // as in later versions (LTR-303/329/559/..) and sensor gets overwhelmed when saturated + // and readings are strange. We only check high sensitivity mode for now. + // Nothing is documented and it is a result of real-world testing. + if (data.gain == AlsGain501::GAIN_150) { + // when sensor is saturated it returns various crazy numbers + // CH1 = 1, CH0 = 0 + if (data.ch1 == 1 && data.ch0 == 0) { + ESP_LOGV(TAG, "Looks like sensor got saturated (?) CH1 = 1, CH0 = 0, Gain 150x"); + // fake saturation + data.ch0 = 0xffff; + data.ch1 = 0xffff; + } else if (data.ch1 == 65535 && data.ch0 == 0) { + ESP_LOGV(TAG, "Looks like sensor got saturated (?) CH1 = 65535, CH0 = 0, Gain 150x"); + data.ch0 = 0xffff; + } else if (data.ch1 > 1000 && data.ch0 == 0) { + ESP_LOGV(TAG, "Looks like sensor got saturated (?) CH1 = %d, CH0 = 0, Gain 150x", data.ch1); + data.ch0 = 0xffff; + } + } + + static const uint16_t LOW_INTENSITY_THRESHOLD_1 = 100; + static const uint16_t LOW_INTENSITY_THRESHOLD_200 = 2000; + static const uint16_t HIGH_INTENSITY_THRESHOLD = 25000; + + if (data.ch0 <= (data.gain == AlsGain501::GAIN_1 ? LOW_INTENSITY_THRESHOLD_1 : LOW_INTENSITY_THRESHOLD_200) || + (data.gain == AlsGain501::GAIN_1 && data.lux < 320)) { + GainTimePair next_pair = get_next(GAIN_TIME_PAIRS, current_pair); + if (next_pair != current_pair) { + data.gain = next_pair.gain; + data.integration_time = next_pair.time; + ESP_LOGV(TAG, "Low illuminance. Increasing sensitivity."); + return true; + } + + } else if (data.ch0 >= HIGH_INTENSITY_THRESHOLD || data.ch1 >= HIGH_INTENSITY_THRESHOLD) { + GainTimePair prev_pair = get_prev(GAIN_TIME_PAIRS, current_pair); + if (prev_pair != current_pair) { + data.gain = prev_pair.gain; + data.integration_time = prev_pair.time; + ESP_LOGV(TAG, "High illuminance. Decreasing sensitivity."); + return true; + } + } else { + ESP_LOGD(TAG, "Illuminance is good enough."); + return false; + } + ESP_LOGD(TAG, "Can't adjust sensitivity anymore."); + return false; +} + +void LTRAlsPs501Component::apply_lux_calculation_(AlsReadings &data) { + if ((data.ch0 == 0xFFFF) || (data.ch1 == 0xFFFF)) { + ESP_LOGW(TAG, "Sensors got saturated"); + data.lux = 0.0f; + return; + } + + if ((data.ch0 == 0x0000) && (data.ch1 == 0x0000)) { + ESP_LOGW(TAG, "Sensors blacked out"); + data.lux = 0.0f; + return; + } + + float ch0 = data.ch0; + float ch1 = data.ch1; + float ratio = ch1 / (ch0 + ch1); + float als_gain = get_gain_coeff(data.gain); + float als_time = ((float) get_itime_ms(data.integration_time)) / 100.0f; + float inv_pfactor = this->glass_attenuation_factor_; + float lux = 0.0f; + + // method from + // https://github.com/fards/Ainol_fire_kernel/blob/83832cf8a3082fd8e963230f4b1984479d1f1a84/customer/drivers/lightsensor/ltr501als.c#L295 + + if (ratio < 0.45) { + lux = 1.7743 * ch0 + 1.1059 * ch1; + } else if (ratio < 0.64) { + lux = 3.7725 * ch0 - 1.3363 * ch1; + } else if (ratio < 0.85) { + lux = 1.6903 * ch0 - 0.1693 * ch1; + } else { + ESP_LOGW(TAG, "Impossible ch1/(ch0 + ch1) ratio"); + lux = 0.0f; + } + + lux = inv_pfactor * lux / als_gain / als_time; + data.lux = lux; + + ESP_LOGD(TAG, "Lux calculation: ratio %.3f, gain %.0fx, int time %.1f, inv_pfactor %.3f, lux %.3f", ratio, als_gain, + als_time, inv_pfactor, lux); +} + +void LTRAlsPs501Component::publish_data_part_1_(AlsReadings &data) { + if (this->proximity_counts_sensor_ != nullptr) { + this->proximity_counts_sensor_->publish_state(this->ps_readings_); + } + if (this->ambient_light_sensor_ != nullptr) { + this->ambient_light_sensor_->publish_state(data.lux); + } + if (this->infrared_counts_sensor_ != nullptr) { + this->infrared_counts_sensor_->publish_state(data.ch1); + } + if (this->full_spectrum_counts_sensor_ != nullptr) { + this->full_spectrum_counts_sensor_->publish_state(data.ch0); + } +} + +void LTRAlsPs501Component::publish_data_part_2_(AlsReadings &data) { + if (this->actual_gain_sensor_ != nullptr) { + this->actual_gain_sensor_->publish_state(get_gain_coeff(data.gain)); + } + if (this->actual_integration_time_sensor_ != nullptr) { + this->actual_integration_time_sensor_->publish_state(get_itime_ms(data.integration_time)); + } +} +} // namespace ltr501 +} // namespace esphome diff --git a/esphome/components/ltr501/ltr501.h b/esphome/components/ltr501/ltr501.h new file mode 100644 index 0000000000..07b69fa0d0 --- /dev/null +++ b/esphome/components/ltr501/ltr501.h @@ -0,0 +1,184 @@ +#pragma once + +#include "esphome/components/i2c/i2c.h" +#include "esphome/components/sensor/sensor.h" +#include "esphome/core/component.h" +#include "esphome/core/optional.h" +#include "esphome/core/automation.h" + +#include "ltr_definitions_501.h" + +namespace esphome { +namespace ltr501 { + +enum DataAvail : uint8_t { NO_DATA, BAD_DATA, DATA_OK }; + +enum LtrType : uint8_t { + LTR_TYPE_UNKNOWN = 0, + LTR_TYPE_ALS_ONLY = 1, + LTR_TYPE_PS_ONLY = 2, + LTR_TYPE_ALS_AND_PS = 3, +}; + +class LTRAlsPs501Component : public PollingComponent, public i2c::I2CDevice { + public: + // + // EspHome framework functions + // + float get_setup_priority() const override { return setup_priority::DATA; } + void setup() override; + void dump_config() override; + void update() override; + void loop() override; + + // Configuration setters : General + // + void set_ltr_type(LtrType type) { this->ltr_type_ = type; } + + // Configuration setters : ALS + // + void set_als_auto_mode(bool enable) { this->automatic_mode_enabled_ = enable; } + void set_als_gain(AlsGain501 gain) { this->gain_ = gain; } + void set_als_integration_time(IntegrationTime501 time) { this->integration_time_ = time; } + void set_als_meas_repeat_rate(MeasurementRepeatRate rate) { this->repeat_rate_ = rate; } + void set_als_glass_attenuation_factor(float factor) { this->glass_attenuation_factor_ = factor; } + + // Configuration setters : PS + // + void set_ps_high_threshold(uint16_t threshold) { this->ps_threshold_high_ = threshold; } + void set_ps_low_threshold(uint16_t threshold) { this->ps_threshold_low_ = threshold; } + void set_ps_cooldown_time_s(uint16_t time) { this->ps_cooldown_time_s_ = time; } + void set_ps_gain(PsGain501 gain) { this->ps_gain_ = gain; } + + // Sensors setters + // + void set_ambient_light_sensor(sensor::Sensor *sensor) { this->ambient_light_sensor_ = sensor; } + void set_full_spectrum_counts_sensor(sensor::Sensor *sensor) { this->full_spectrum_counts_sensor_ = sensor; } + void set_infrared_counts_sensor(sensor::Sensor *sensor) { this->infrared_counts_sensor_ = sensor; } + void set_actual_gain_sensor(sensor::Sensor *sensor) { this->actual_gain_sensor_ = sensor; } + 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; } + + protected: + // + // Internal state machine, used to split all the actions into + // small steps in loop() to make sure we are not blocking execution + // + enum class State : uint8_t { + NOT_INITIALIZED, + DELAYED_SETUP, + IDLE, + WAITING_FOR_DATA, + COLLECTING_DATA_AUTO, + DATA_COLLECTED, + ADJUSTMENT_IN_PROGRESS, + READY_TO_PUBLISH, + KEEP_PUBLISHING + } state_{State::NOT_INITIALIZED}; + + LtrType ltr_type_{LtrType::LTR_TYPE_ALS_ONLY}; + + // + // Current measurements data + // + struct AlsReadings { + uint16_t ch0{0}; + uint16_t ch1{0}; + AlsGain501 gain{AlsGain501::GAIN_1}; + IntegrationTime501 integration_time{IntegrationTime501::INTEGRATION_TIME_100MS}; + float lux{0.0f}; + uint8_t number_of_adjustments{0}; + } als_readings_; + uint16_t ps_readings_{0xfffe}; + + inline bool is_als_() const { + return this->ltr_type_ == LtrType::LTR_TYPE_ALS_ONLY || this->ltr_type_ == LtrType::LTR_TYPE_ALS_AND_PS; + } + inline bool is_ps_() const { + return this->ltr_type_ == LtrType::LTR_TYPE_PS_ONLY || this->ltr_type_ == LtrType::LTR_TYPE_ALS_AND_PS; + } + + // + // Device interaction and data manipulation + // + bool check_part_number_(); + + void configure_reset_(); + void configure_als_(); + void configure_integration_time_(IntegrationTime501 time); + void configure_gain_(AlsGain501 gain); + DataAvail is_als_data_ready_(AlsReadings &data); + void read_sensor_data_(AlsReadings &data); + bool are_adjustments_required_(AlsReadings &data); + void apply_lux_calculation_(AlsReadings &data); + void publish_data_part_1_(AlsReadings &data); + void publish_data_part_2_(AlsReadings &data); + + void configure_ps_(); + uint16_t read_ps_data_(); + void check_and_trigger_ps_(); + + // + // Component configuration + // + bool automatic_mode_enabled_{false}; + AlsGain501 gain_{AlsGain501::GAIN_1}; + IntegrationTime501 integration_time_{IntegrationTime501::INTEGRATION_TIME_100MS}; + MeasurementRepeatRate repeat_rate_{MeasurementRepeatRate::REPEAT_RATE_500MS}; + float glass_attenuation_factor_{1.0}; + + uint16_t ps_cooldown_time_s_{5}; + PsGain501 ps_gain_{PsGain501::PS_GAIN_1}; + uint16_t ps_threshold_high_{0xffff}; + uint16_t ps_threshold_low_{0x0000}; + + // + // Sensors for publishing data + // + sensor::Sensor *infrared_counts_sensor_{nullptr}; // direct reading CH1, infrared only + sensor::Sensor *full_spectrum_counts_sensor_{nullptr}; // direct reading CH0, infrared + visible light + sensor::Sensor *ambient_light_sensor_{nullptr}; // calculated lux + sensor::Sensor *actual_gain_sensor_{nullptr}; // actual gain of reading + sensor::Sensor *actual_integration_time_sensor_{nullptr}; // actual integration time + sensor::Sensor *proximity_counts_sensor_{nullptr}; // proximity sensor + + bool is_any_als_sensor_enabled_() const { + return this->ambient_light_sensor_ != nullptr || this->full_spectrum_counts_sensor_ != nullptr || + this->infrared_counts_sensor_ != nullptr || this->actual_gain_sensor_ != nullptr || + this->actual_integration_time_sensor_ != nullptr; + } + 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 on_ps_high_trigger_callback_; + CallbackManager on_ps_low_trigger_callback_; + + void add_on_ps_high_trigger_callback_(std::function callback) { + this->on_ps_high_trigger_callback_.add(std::move(callback)); + } + + void add_on_ps_low_trigger_callback_(std::function callback) { + this->on_ps_low_trigger_callback_.add(std::move(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/ltr_definitions_501.h b/esphome/components/ltr501/ltr_definitions_501.h new file mode 100644 index 0000000000..604bd92b68 --- /dev/null +++ b/esphome/components/ltr501/ltr_definitions_501.h @@ -0,0 +1,260 @@ +#pragma once + +#include + +namespace esphome { +namespace ltr501 { + +enum class CommandRegisters : uint8_t { + ALS_CONTR = 0x80, // ALS operation mode control and SW reset + PS_CONTR = 0x81, // PS operation mode control + PS_LED = 0x82, // PS LED pulse frequency control + PS_N_PULSES = 0x83, // PS number of pulses control + PS_MEAS_RATE = 0x84, // PS measurement rate in active mode + MEAS_RATE = 0x85, // ALS measurement rate in active mode + PART_ID = 0x86, // Part Number ID and Revision ID + MANUFAC_ID = 0x87, // Manufacturer ID + ALS_DATA_CH1_0 = 0x88, // ALS measurement CH1 data, lower byte - infrared only + ALS_DATA_CH1_1 = 0x89, // ALS measurement CH1 data, upper byte - infrared only + ALS_DATA_CH0_0 = 0x8A, // ALS measurement CH0 data, lower byte - visible + infrared + ALS_DATA_CH0_1 = 0x8B, // ALS measurement CH0 data, upper byte - visible + infrared + ALS_PS_STATUS = 0x8C, // ALS PS new data status + PS_DATA_0 = 0x8D, // PS measurement data, lower byte + PS_DATA_1 = 0x8E, // PS measurement data, upper byte + ALS_PS_INTERRUPT = 0x8F, // Interrupt status + PS_THRES_UP_0 = 0x90, // PS interrupt upper threshold, lower byte + PS_THRES_UP_1 = 0x91, // PS interrupt upper threshold, upper byte + PS_THRES_LOW_0 = 0x92, // PS interrupt lower threshold, lower byte + PS_THRES_LOW_1 = 0x93, // PS interrupt lower threshold, upper byte + PS_OFFSET_1 = 0x94, // PS offset, upper byte + PS_OFFSET_0 = 0x95, // PS offset, lower byte + // 0x96 - reserved + ALS_THRES_UP_0 = 0x97, // ALS interrupt upper threshold, lower byte + ALS_THRES_UP_1 = 0x98, // ALS interrupt upper threshold, upper byte + ALS_THRES_LOW_0 = 0x99, // ALS interrupt lower threshold, lower byte + ALS_THRES_LOW_1 = 0x9A, // ALS interrupt lower threshold, upper byte + // 0x9B - reserved + // 0x9C - reserved + // 0x9D - reserved + INTERRUPT_PERSIST = 0x9E // Interrupt persistence filter +}; + +// ALS Sensor gain levels +enum AlsGain501 : uint8_t { + GAIN_1 = 0, // GAIN_RANGE_2 // default + GAIN_150 = 1, // GAIN_RANGE_1 +}; +static const uint8_t GAINS_COUNT = 2; + +// ALS Sensor integration times +enum IntegrationTime501 : uint8_t { + INTEGRATION_TIME_100MS = 0, // default + INTEGRATION_TIME_50MS = 1, // only in Dynamic GAIN_RANGE_2 + INTEGRATION_TIME_200MS = 2, // only in Dynamic GAIN_RANGE_1 + INTEGRATION_TIME_400MS = 3, // only in Dynamic GAIN_RANGE_1 +}; +static const uint8_t TIMES_COUNT = 4; + +// ALS Sensor measurement repeat rate +enum MeasurementRepeatRate { + REPEAT_RATE_50MS = 0, + REPEAT_RATE_100MS = 1, + REPEAT_RATE_200MS = 2, + REPEAT_RATE_500MS = 3, // default + REPEAT_RATE_1000MS = 4, + REPEAT_RATE_2000MS = 5 +}; + +// PS Sensor gain levels +enum PsGain501 : uint8_t { + PS_GAIN_1 = 0, // default + PS_GAIN_4 = 1, + PS_GAIN_8 = 2, + PS_GAIN_16 = 3, +}; + +// LED Pulse Modulation Frequency +enum PsLedFreq : uint8_t { + PS_LED_FREQ_30KHZ = 0, + PS_LED_FREQ_40KHZ = 1, + PS_LED_FREQ_50KHZ = 2, + PS_LED_FREQ_60KHZ = 3, // default + PS_LED_FREQ_70KHZ = 4, + PS_LED_FREQ_80KHZ = 5, + PS_LED_FREQ_90KHZ = 6, + PS_LED_FREQ_100KHZ = 7, +}; + +// LED current duty +enum PsLedDuty : uint8_t { + PS_LED_DUTY_25 = 0, + PS_LED_DUTY_50 = 1, // default + PS_LED_DUTY_75 = 2, + PS_LED_DUTY_100 = 3, +}; + +// LED pulsed current level +enum PsLedCurrent : uint8_t { + PS_LED_CURRENT_5MA = 0, + PS_LED_CURRENT_10MA = 1, + PS_LED_CURRENT_20MA = 2, + PS_LED_CURRENT_50MA = 3, // default + PS_LED_CURRENT_100MA = 4, + PS_LED_CURRENT_100MA1 = 5, + PS_LED_CURRENT_100MA2 = 6, + PS_LED_CURRENT_100MA3 = 7, +}; + +// PS measurement rate +enum PsMeasurementRate : uint8_t { + PS_MEAS_RATE_50MS = 0, + PS_MEAS_RATE_70MS = 1, + PS_MEAS_RATE_100MS = 2, // default + PS_MEAS_RATE_200MS = 3, + PS_MEAS_RATE_500MS = 4, + PS_MEAS_RATE_1000MS = 5, + PS_MEAS_RATE_2000MS = 6, + PS_MEAS_RATE_2000MS1 = 7, +}; + +// +// ALS_CONTR Register (0x80) +// +union AlsControlRegister501 { + uint8_t raw; + struct { + bool asl_mode_xxx : 1; + bool als_mode_active : 1; + bool sw_reset : 1; + AlsGain501 gain : 1; + uint8_t reserved : 4; + } __attribute__((packed)); +}; + +// +// PS_CONTR Register (0x81) +// +union PsControlRegister501 { + uint8_t raw; + struct { + bool ps_mode_xxx : 1; + bool ps_mode_active : 1; + PsGain501 ps_gain : 2; + bool reserved_4 : 1; + bool reserved_5 : 1; + bool reserved_6 : 1; + bool reserved_7 : 1; + } __attribute__((packed)); +}; + +// +// PS_LED Register (0x82) +// +union PsLedRegister { + uint8_t raw; + struct { + PsLedCurrent ps_led_current : 3; + PsLedDuty ps_led_duty : 2; + PsLedFreq ps_led_freq : 3; + } __attribute__((packed)); +}; + +// +// PS_N_PULSES Register (0x83) +// +union PsNPulsesRegister501 { + uint8_t raw; + uint8_t number_of_pulses; +}; + +// +// PS_MEAS_RATE Register (0x84) +// +union PsMeasurementRateRegister { + uint8_t raw; + struct { + PsMeasurementRate ps_measurement_rate : 4; + uint8_t reserved : 4; + } __attribute__((packed)); +}; + +// +// ALS_MEAS_RATE Register (0x85) +// +union MeasurementRateRegister501 { + uint8_t raw; + struct { + MeasurementRepeatRate measurement_repeat_rate : 3; + IntegrationTime501 integration_time : 2; + bool reserved_5 : 1; + bool reserved_6 : 1; + bool reserved_7 : 1; + } __attribute__((packed)); +}; + +// +// PART_ID Register (0x86) (Read Only) +// +union PartIdRegister { + uint8_t raw; + struct { + uint8_t part_number_id : 4; + uint8_t revision_id : 4; + } __attribute__((packed)); +}; + +// +// ALS_PS_STATUS Register (0x8C) (Read Only) +// +union AlsPsStatusRegister { + uint8_t raw; + struct { + bool ps_new_data : 1; // 0 - old data, 1 - new data + bool ps_interrupt : 1; // 0 - interrupt signal not active, 1 - interrupt signal active + bool als_new_data : 1; // 0 - old data, 1 - new data + bool als_interrupt : 1; // 0 - interrupt signal not active, 1 - interrupt signal active + AlsGain501 gain : 1; // current ALS gain + bool reserved_5 : 1; + bool reserved_6 : 1; + bool reserved_7 : 1; + } __attribute__((packed)); +}; + +// +// PS_DATA_1 Register (0x8E) (Read Only) +// +union PsData1Register { + uint8_t raw; + struct { + uint8_t ps_data_high : 3; + uint8_t reserved : 4; + bool ps_saturation_flag : 1; + } __attribute__((packed)); +}; + +// +// INTERRUPT Register (0x8F) (Read Only) +// +union InterruptRegister { + uint8_t raw; + struct { + bool ps_interrupt : 1; + bool als_interrupt : 1; + bool interrupt_polarity : 1; // 0 - active low (default), 1 - active high + uint8_t reserved : 5; + } __attribute__((packed)); +}; + +// +// INTERRUPT_PERSIST Register (0x9E) +// +union InterruptPersistRegister { + uint8_t raw; + struct { + uint8_t als_persist : 4; // 0 - every ALS cycle, 1 - every 2 ALS cycles, ... 15 - every 16 ALS cycles + uint8_t ps_persist : 4; // 0 - every PS cycle, 1 - every 2 PS cycles, ... 15 - every 16 PS cycles + } __attribute__((packed)); +}; + +} // namespace ltr501 +} // namespace esphome diff --git a/esphome/components/ltr501/sensor.py b/esphome/components/ltr501/sensor.py new file mode 100644 index 0000000000..153d1b3ad1 --- /dev/null +++ b/esphome/components/ltr501/sensor.py @@ -0,0 +1,274 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome import automation +from esphome.components import i2c, sensor +from esphome.const import ( + CONF_ACTUAL_GAIN, + CONF_ACTUAL_INTEGRATION_TIME, + CONF_AMBIENT_LIGHT, + CONF_AUTO_MODE, + CONF_FULL_SPECTRUM_COUNTS, + CONF_GAIN, + CONF_GLASS_ATTENUATION_FACTOR, + CONF_ID, + CONF_INTEGRATION_TIME, + CONF_NAME, + CONF_REPEAT, + CONF_TRIGGER_ID, + CONF_TYPE, + DEVICE_CLASS_DISTANCE, + DEVICE_CLASS_ILLUMINANCE, + ICON_BRIGHTNESS_5, + ICON_BRIGHTNESS_6, + ICON_TIMER, + STATE_CLASS_MEASUREMENT, + UNIT_LUX, + UNIT_MILLISECOND, +) + +CODEOWNERS = ["@latonita"] +DEPENDENCIES = ["i2c"] + +CONF_INFRARED_COUNTS = "infrared_counts" +CONF_ON_PS_HIGH_THRESHOLD = "on_ps_high_threshold" +CONF_ON_PS_LOW_THRESHOLD = "on_ps_low_threshold" +CONF_PS_COOLDOWN = "ps_cooldown" +CONF_PS_COUNTS = "ps_counts" +CONF_PS_GAIN = "ps_gain" +CONF_PS_HIGH_THRESHOLD = "ps_high_threshold" +CONF_PS_LOW_THRESHOLD = "ps_low_threshold" +ICON_BRIGHTNESS_7 = "mdi:brightness-7" +ICON_GAIN = "mdi:multiplication" +ICON_PROXIMITY = "mdi:hand-wave-outline" +UNIT_COUNTS = "#" + +ltr501_ns = cg.esphome_ns.namespace("ltr501") + +LTRAlsPsComponent = ltr501_ns.class_( + "LTRAlsPs501Component", cg.PollingComponent, i2c.I2CDevice +) + +LtrType = ltr501_ns.enum("LtrType") +LTR_TYPES = { + "ALS": LtrType.LTR_TYPE_ALS_ONLY, + "PS": LtrType.LTR_TYPE_PS_ONLY, + "ALS_PS": LtrType.LTR_TYPE_ALS_AND_PS, +} + +AlsGain = ltr501_ns.enum("AlsGain501") +ALS_GAINS = { + "1X": AlsGain.GAIN_1, + "150X": AlsGain.GAIN_150, +} + +IntegrationTime = ltr501_ns.enum("IntegrationTime501") +INTEGRATION_TIMES = { + 50: IntegrationTime.INTEGRATION_TIME_50MS, + 100: IntegrationTime.INTEGRATION_TIME_100MS, + 200: IntegrationTime.INTEGRATION_TIME_200MS, + 400: IntegrationTime.INTEGRATION_TIME_400MS, +} + +MeasurementRepeatRate = ltr501_ns.enum("MeasurementRepeatRate") +MEASUREMENT_REPEAT_RATES = { + 50: MeasurementRepeatRate.REPEAT_RATE_50MS, + 100: MeasurementRepeatRate.REPEAT_RATE_100MS, + 200: MeasurementRepeatRate.REPEAT_RATE_200MS, + 500: MeasurementRepeatRate.REPEAT_RATE_500MS, + 1000: MeasurementRepeatRate.REPEAT_RATE_1000MS, + 2000: MeasurementRepeatRate.REPEAT_RATE_2000MS, +} + +PsGain = ltr501_ns.enum("PsGain501") +PS_GAINS = { + "1X": PsGain.PS_GAIN_1, + "4X": PsGain.PS_GAIN_4, + "8X": PsGain.PS_GAIN_8, + "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 + return cv.enum(INTEGRATION_TIMES, int=True)(value) + + +def validate_repeat_rate(value): + value = cv.positive_time_period_milliseconds(value).total_milliseconds + return cv.enum(MEASUREMENT_REPEAT_RATES, int=True)(value) + + +def validate_time_and_repeat_rate(config): + integraton_time = config[CONF_INTEGRATION_TIME] + repeat_rate = config[CONF_REPEAT] + if integraton_time > repeat_rate: + raise cv.Invalid( + f"Measurement repeat rate ({repeat_rate}ms) shall be greater or equal to integration time ({integraton_time}ms)" + ) + return config + + +def validate_als_gain_and_integration_time(config): + integraton_time = config[CONF_INTEGRATION_TIME] + if config[CONF_GAIN] == "1X" and integraton_time > 100: + raise cv.Invalid( + "ALS gain 1X can only be used with integration time 50ms or 100ms" + ) + if config[CONF_GAIN] == "200X" and integraton_time == 50: + raise cv.Invalid("ALS gain 200X can not be used with integration time 50ms") + return config + + +CONFIG_SCHEMA = cv.All( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(LTRAlsPsComponent), + cv.Optional(CONF_TYPE, default="ALS_PS"): cv.enum(LTR_TYPES, upper=True), + cv.Optional(CONF_AUTO_MODE, default=True): cv.boolean, + cv.Optional(CONF_GAIN, default="1X"): cv.enum(ALS_GAINS, upper=True), + cv.Optional( + CONF_INTEGRATION_TIME, default="100ms" + ): validate_integration_time, + cv.Optional(CONF_REPEAT, default="500ms"): validate_repeat_rate, + cv.Optional(CONF_GLASS_ATTENUATION_FACTOR, default=1.0): cv.float_range( + min=1.0 + ), + cv.Optional( + CONF_PS_COOLDOWN, default="5s" + ): cv.positive_time_period_seconds, + cv.Optional(CONF_PS_GAIN, default="1X"): cv.enum(PS_GAINS, upper=True), + cv.Optional(CONF_PS_HIGH_THRESHOLD, default=65535): cv.int_range( + min=0, max=65535 + ), + 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_AMBIENT_LIGHT): cv.maybe_simple_value( + sensor.sensor_schema( + unit_of_measurement=UNIT_LUX, + icon=ICON_BRIGHTNESS_6, + accuracy_decimals=1, + device_class=DEVICE_CLASS_ILLUMINANCE, + state_class=STATE_CLASS_MEASUREMENT, + ), + key=CONF_NAME, + ), + cv.Optional(CONF_INFRARED_COUNTS): cv.maybe_simple_value( + sensor.sensor_schema( + 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, + ), + cv.Optional(CONF_FULL_SPECTRUM_COUNTS): cv.maybe_simple_value( + sensor.sensor_schema( + 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, + ), + cv.Optional(CONF_PS_COUNTS): cv.maybe_simple_value( + sensor.sensor_schema( + unit_of_measurement=UNIT_COUNTS, + icon=ICON_PROXIMITY, + accuracy_decimals=0, + device_class=DEVICE_CLASS_DISTANCE, + state_class=STATE_CLASS_MEASUREMENT, + ), + key=CONF_NAME, + ), + cv.Optional(CONF_ACTUAL_GAIN): cv.maybe_simple_value( + sensor.sensor_schema( + icon=ICON_GAIN, + accuracy_decimals=0, + device_class=DEVICE_CLASS_ILLUMINANCE, + state_class=STATE_CLASS_MEASUREMENT, + ), + key=CONF_NAME, + ), + cv.Optional(CONF_ACTUAL_INTEGRATION_TIME): cv.maybe_simple_value( + sensor.sensor_schema( + unit_of_measurement=UNIT_MILLISECOND, + icon=ICON_TIMER, + accuracy_decimals=0, + state_class=STATE_CLASS_MEASUREMENT, + ), + key=CONF_NAME, + ), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x23)), + validate_time_and_repeat_rate, + validate_als_gain_and_integration_time, +) + + +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 als_config := config.get(CONF_AMBIENT_LIGHT): + sens = await sensor.new_sensor(als_config) + cg.add(var.set_ambient_light_sensor(sens)) + + if infrared_cnt_config := config.get(CONF_INFRARED_COUNTS): + sens = await sensor.new_sensor(infrared_cnt_config) + cg.add(var.set_infrared_counts_sensor(sens)) + + if full_spect_cnt_config := config.get(CONF_FULL_SPECTRUM_COUNTS): + sens = await sensor.new_sensor(full_spect_cnt_config) + cg.add(var.set_full_spectrum_counts_sensor(sens)) + + if act_gain_config := config.get(CONF_ACTUAL_GAIN): + sens = await sensor.new_sensor(act_gain_config) + cg.add(var.set_actual_gain_sensor(sens)) + + if act_itime_config := config.get(CONF_ACTUAL_INTEGRATION_TIME): + sens = await sensor.new_sensor(act_itime_config) + cg.add(var.set_actual_integration_time_sensor(sens)) + + if prox_cnt_config := config.get(CONF_PS_COUNTS): + 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) + + cg.add(var.set_ltr_type(config[CONF_TYPE])) + + cg.add(var.set_als_auto_mode(config[CONF_AUTO_MODE])) + cg.add(var.set_als_gain(config[CONF_GAIN])) + cg.add(var.set_als_integration_time(config[CONF_INTEGRATION_TIME])) + cg.add(var.set_als_meas_repeat_rate(config[CONF_REPEAT])) + cg.add(var.set_als_glass_attenuation_factor(config[CONF_GLASS_ATTENUATION_FACTOR])) + + cg.add(var.set_ps_cooldown_time_s(config[CONF_PS_COOLDOWN])) + cg.add(var.set_ps_gain(config[CONF_PS_GAIN])) + cg.add(var.set_ps_high_threshold(config[CONF_PS_HIGH_THRESHOLD])) + cg.add(var.set_ps_low_threshold(config[CONF_PS_LOW_THRESHOLD])) diff --git a/esphome/components/ltr_als_ps/sensor.py b/esphome/components/ltr_als_ps/sensor.py index ac9f7e6788..e9a5264941 100644 --- a/esphome/components/ltr_als_ps/sensor.py +++ b/esphome/components/ltr_als_ps/sensor.py @@ -4,8 +4,10 @@ from esphome import automation from esphome.components import i2c, sensor from esphome.const import ( CONF_ACTUAL_GAIN, + CONF_ACTUAL_INTEGRATION_TIME, CONF_AMBIENT_LIGHT, CONF_AUTO_MODE, + CONF_FULL_SPECTRUM_COUNTS, CONF_GAIN, CONF_GLASS_ATTENUATION_FACTOR, CONF_ID, @@ -27,8 +29,6 @@ from esphome.const import ( CODEOWNERS = ["@latonita"] DEPENDENCIES = ["i2c"] -CONF_ACTUAL_INTEGRATION_TIME = "actual_integration_time" -CONF_FULL_SPECTRUM_COUNTS = "full_spectrum_counts" CONF_INFRARED_COUNTS = "infrared_counts" CONF_ON_PS_HIGH_THRESHOLD = "on_ps_high_threshold" CONF_ON_PS_LOW_THRESHOLD = "on_ps_low_threshold" diff --git a/esphome/components/veml7700/sensor.py b/esphome/components/veml7700/sensor.py index 7b0f75e70c..308f1c1c00 100644 --- a/esphome/components/veml7700/sensor.py +++ b/esphome/components/veml7700/sensor.py @@ -3,9 +3,11 @@ import esphome.config_validation as cv from esphome.components import i2c, sensor from esphome.const import ( CONF_ACTUAL_GAIN, + CONF_ACTUAL_INTEGRATION_TIME, CONF_AMBIENT_LIGHT, CONF_AUTO_MODE, CONF_FULL_SPECTRUM, + CONF_FULL_SPECTRUM_COUNTS, CONF_GAIN, CONF_GLASS_ATTENUATION_FACTOR, CONF_ID, @@ -28,9 +30,7 @@ UNIT_COUNTS = "#" ICON_MULTIPLICATION = "mdi:multiplication" ICON_BRIGHTNESS_7 = "mdi:brightness-7" -CONF_ACTUAL_INTEGRATION_TIME = "actual_integration_time" CONF_AMBIENT_LIGHT_COUNTS = "ambient_light_counts" -CONF_FULL_SPECTRUM_COUNTS = "full_spectrum_counts" CONF_LUX_COMPENSATION = "lux_compensation" veml7700_ns = cg.esphome_ns.namespace("veml7700") diff --git a/esphome/const.py b/esphome/const.py index 95773630d0..169b11a715 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -44,6 +44,7 @@ CONF_ACTIONS = "actions" CONF_ACTIVE = "active" CONF_ACTIVE_POWER = "active_power" CONF_ACTUAL_GAIN = "actual_gain" +CONF_ACTUAL_INTEGRATION_TIME = "actual_integration_time" CONF_ADDRESS = "address" CONF_ADDRESSABLE_LIGHT_ID = "addressable_light_id" CONF_ADVANCED = "advanced" @@ -323,6 +324,7 @@ CONF_FREQUENCY = "frequency" CONF_FRIENDLY_NAME = "friendly_name" CONF_FROM = "from" CONF_FULL_SPECTRUM = "full_spectrum" +CONF_FULL_SPECTRUM_COUNTS = "full_spectrum_counts" CONF_FULL_UPDATE_EVERY = "full_update_every" CONF_GAIN = "gain" CONF_GAMMA_CORRECT = "gamma_correct" diff --git a/tests/components/ltr501/common.yaml b/tests/components/ltr501/common.yaml new file mode 100644 index 0000000000..b7074f52f2 --- /dev/null +++ b/tests/components/ltr501/common.yaml @@ -0,0 +1,9 @@ +sensor: + - platform: ltr501 + address: 0x23 + i2c_id: i2c_ltr501 + type: ALS_PS + gain: 1X + integration_time: 100ms + ambient_light: "Ambient light" + ps_counts: "Proximity counts" diff --git a/tests/components/ltr501/test.esp32-ard.yaml b/tests/components/ltr501/test.esp32-ard.yaml new file mode 100644 index 0000000000..4c710c74fe --- /dev/null +++ b/tests/components/ltr501/test.esp32-ard.yaml @@ -0,0 +1,6 @@ +i2c: + - id: i2c_ltr501 + scl: 16 + sda: 17 + +<<: !include common.yaml diff --git a/tests/components/ltr501/test.esp32-c3-ard.yaml b/tests/components/ltr501/test.esp32-c3-ard.yaml new file mode 100644 index 0000000000..9e7de2768d --- /dev/null +++ b/tests/components/ltr501/test.esp32-c3-ard.yaml @@ -0,0 +1,6 @@ +i2c: + - id: i2c_ltr501 + scl: 5 + sda: 4 + +<<: !include common.yaml diff --git a/tests/components/ltr501/test.esp32-c3-idf.yaml b/tests/components/ltr501/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..9e7de2768d --- /dev/null +++ b/tests/components/ltr501/test.esp32-c3-idf.yaml @@ -0,0 +1,6 @@ +i2c: + - id: i2c_ltr501 + scl: 5 + sda: 4 + +<<: !include common.yaml diff --git a/tests/components/ltr501/test.esp32-idf.yaml b/tests/components/ltr501/test.esp32-idf.yaml new file mode 100644 index 0000000000..4c710c74fe --- /dev/null +++ b/tests/components/ltr501/test.esp32-idf.yaml @@ -0,0 +1,6 @@ +i2c: + - id: i2c_ltr501 + scl: 16 + sda: 17 + +<<: !include common.yaml diff --git a/tests/components/ltr501/test.esp8266-ard.yaml b/tests/components/ltr501/test.esp8266-ard.yaml new file mode 100644 index 0000000000..9e7de2768d --- /dev/null +++ b/tests/components/ltr501/test.esp8266-ard.yaml @@ -0,0 +1,6 @@ +i2c: + - id: i2c_ltr501 + scl: 5 + sda: 4 + +<<: !include common.yaml diff --git a/tests/components/ltr501/test.rp2040-ard.yaml b/tests/components/ltr501/test.rp2040-ard.yaml new file mode 100644 index 0000000000..9e7de2768d --- /dev/null +++ b/tests/components/ltr501/test.rp2040-ard.yaml @@ -0,0 +1,6 @@ +i2c: + - id: i2c_ltr501 + scl: 5 + sda: 4 + +<<: !include common.yaml From 198bd3b41afc46c499ccfacf32b90866e33a98d9 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 10 Sep 2024 10:35:39 +1200 Subject: [PATCH 2056/2101] Bump libssl-dev to 3.0.14-1~deb12u2 (#7426) --- docker/Dockerfile | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 4393d5a447..e255f4e2fc 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -49,7 +49,7 @@ RUN \ zlib1g-dev=1:1.2.13.dfsg-1 \ libjpeg-dev=1:2.1.5-2 \ libfreetype-dev=2.12.1+dfsg-5+deb12u3 \ - libssl-dev=3.0.14-1~deb12u1 \ + libssl-dev=3.0.14-1~deb12u2 \ libffi-dev=3.4.4-1 \ libopenjp2-7=2.5.0-2 \ libtiff6=4.5.0-6+deb12u1 \ @@ -96,14 +96,19 @@ RUN \ # First install requirements to leverage caching when requirements don't change # tmpfs is for https://github.com/rust-lang/cargo/issues/8719 -COPY requirements.txt requirements_optional.txt script/platformio_install_deps.py platformio.ini / +COPY requirements.txt requirements_optional.txt / RUN --mount=type=tmpfs,target=/root/.cargo if [ "$TARGETARCH$TARGETVARIANT" = "armv7" ]; then \ - export PIP_EXTRA_INDEX_URL="https://www.piwheels.org/simple"; \ + curl -L https://www.piwheels.org/cp311/cryptography-43.0.0-cp37-abi3-linux_armv7l.whl -o /tmp/cryptography-43.0.0-cp37-abi3-linux_armv7l.whl \ + && pip3 install --break-system-packages --no-cache-dir /tmp/cryptography-43.0.0-cp37-abi3-linux_armv7l.whl \ + && rm /tmp/cryptography-43.0.0-cp37-abi3-linux_armv7l.whl \ + && export PIP_EXTRA_INDEX_URL="https://www.piwheels.org/simple"; \ fi; \ CARGO_REGISTRIES_CRATES_IO_PROTOCOL=sparse CARGO_HOME=/root/.cargo \ pip3 install \ - --break-system-packages --no-cache-dir -r /requirements.txt -r /requirements_optional.txt \ - && /platformio_install_deps.py /platformio.ini --libraries + --break-system-packages --no-cache-dir -r /requirements.txt -r /requirements_optional.txt + +COPY script/platformio_install_deps.py platformio.ini / +RUN /platformio_install_deps.py /platformio.ini --libraries # Avoid unsafe git error when container user and file config volume permissions don't match RUN git config --system --add safe.directory '*' From 9f42b76de3679a1ef2fd5945766ccf9f78ae4fd2 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 10 Sep 2024 11:57:42 +1200 Subject: [PATCH 2057/2101] [gh-actions] Don't produce docker build summaries (#7430) --- .github/actions/build-image/action.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/actions/build-image/action.yaml b/.github/actions/build-image/action.yaml index 56be20bd87..d277ec06c7 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -47,6 +47,9 @@ runs: - name: Build and push to ghcr by digest id: build-ghcr uses: docker/build-push-action@v6.7.0 + env: + DOCKER_BUILD_SUMMARY: false + DOCKER_BUILD_RECORD_UPLOAD: false with: context: . file: ./docker/Dockerfile @@ -70,6 +73,9 @@ runs: - name: Build and push to dockerhub by digest id: build-dockerhub uses: docker/build-push-action@v6.7.0 + env: + DOCKER_BUILD_SUMMARY: false + DOCKER_BUILD_RECORD_UPLOAD: false with: context: . file: ./docker/Dockerfile From d10feafa9bb68301c060e190309ba6dbf6d7b483 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 10 Sep 2024 00:58:57 +0100 Subject: [PATCH 2058/2101] Add BK72xx support to require_framework_version() (#7409) --- esphome/config_validation.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/esphome/config_validation.py b/esphome/config_validation.py index 719cc43b31..e55879e37e 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -2045,6 +2045,7 @@ def require_framework_version( esp32_arduino=None, esp8266_arduino=None, rp2040_arduino=None, + bk72xx_libretiny=None, host=None, max_version=False, extra_message=None, @@ -2059,6 +2060,13 @@ def require_framework_version( msg += f". {extra_message}" raise Invalid(msg) required = esp_idf + elif CORE.is_bk72xx and framework == "arduino": + if bk72xx_libretiny is None: + msg = "This feature is incompatible with BK72XX" + if extra_message: + msg += f". {extra_message}" + raise Invalid(msg) + required = bk72xx_libretiny elif CORE.is_esp32 and framework == "arduino": if esp32_arduino is None: msg = "This feature is incompatible with ESP32 using arduino framework" From b5e5741ffdeb10f75285b45e5998a8cafcec768d Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 10 Sep 2024 00:59:46 +0100 Subject: [PATCH 2059/2101] Switch IPv6 platform check to use require_framework_version() (#7410) --- esphome/components/network/__init__.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/esphome/components/network/__init__.py b/esphome/components/network/__init__.py index caa873a746..772ba230d9 100644 --- a/esphome/components/network/__init__.py +++ b/esphome/components/network/__init__.py @@ -1,13 +1,7 @@ import esphome.codegen as cg from esphome.components.esp32 import add_idf_sdkconfig_option import esphome.config_validation as cv -from esphome.const import ( - CONF_ENABLE_IPV6, - CONF_MIN_IPV6_ADDR_COUNT, - PLATFORM_ESP32, - PLATFORM_ESP8266, - PLATFORM_RP2040, -) +from esphome.const import CONF_ENABLE_IPV6, CONF_MIN_IPV6_ADDR_COUNT from esphome.core import CORE CODEOWNERS = ["@esphome/core"] @@ -26,7 +20,12 @@ CONFIG_SCHEMA = cv.Schema( ): cv.All( cv.boolean, cv.Any( - cv.only_on([PLATFORM_ESP32, PLATFORM_ESP8266, PLATFORM_RP2040]), + cv.require_framework_version( + esp_idf=cv.Version(0, 0, 0), + esp32_arduino=cv.Version(0, 0, 0), + esp8266_arduino=cv.Version(0, 0, 0), + rp2040_arduino=cv.Version(0, 0, 0), + ), cv.boolean_false, ), ), From f5c2921b85dca99cd9591e968bba4f3b4d9c75ca Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 10 Sep 2024 02:11:26 +0100 Subject: [PATCH 2060/2101] [bl0942] Improve energy reporting (#7428) --- esphome/components/bl0942/bl0942.cpp | 4 +++- esphome/components/bl0942/bl0942.h | 2 ++ esphome/components/bl0942/sensor.py | 9 ++++++--- tests/components/bl0942/test.bk72xx-ard.yaml | 1 + tests/components/bl0942/test.esp32-ard.yaml | 1 + 5 files changed, 13 insertions(+), 4 deletions(-) diff --git a/esphome/components/bl0942/bl0942.cpp b/esphome/components/bl0942/bl0942.cpp index af56e77de6..e6f96c1b19 100644 --- a/esphome/components/bl0942/bl0942.cpp +++ b/esphome/components/bl0942/bl0942.cpp @@ -137,7 +137,8 @@ void BL0942::setup() { } this->write_reg_(BL0942_REG_USR_WRPROT, BL0942_REG_USR_WRPROT_MAGIC); - this->write_reg_(BL0942_REG_SOFT_RESET, BL0942_REG_SOFT_RESET_MAGIC); + if (this->reset_) + this->write_reg_(BL0942_REG_SOFT_RESET, BL0942_REG_SOFT_RESET_MAGIC); uint32_t mode = BL0942_REG_MODE_DEFAULT; mode |= BL0942_REG_MODE_RMS_UPDATE_SEL; /* 800ms refresh time */ @@ -196,6 +197,7 @@ void BL0942::received_package_(DataPacket *data) { void BL0942::dump_config() { // NOLINT(readability-function-cognitive-complexity) ESP_LOGCONFIG(TAG, "BL0942:"); + ESP_LOGCONFIG(TAG, " Reset: %s", TRUEFALSE(this->reset_)); ESP_LOGCONFIG(TAG, " Address: %d", this->address_); ESP_LOGCONFIG(TAG, " Nominal line frequency: %d Hz", this->line_freq_); ESP_LOGCONFIG(TAG, " Current reference: %f", this->current_reference_); diff --git a/esphome/components/bl0942/bl0942.h b/esphome/components/bl0942/bl0942.h index 1dc930183f..37b884e6ca 100644 --- a/esphome/components/bl0942/bl0942.h +++ b/esphome/components/bl0942/bl0942.h @@ -93,6 +93,7 @@ class BL0942 : public PollingComponent, public uart::UARTDevice { void set_frequency_sensor(sensor::Sensor *frequency_sensor) { 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; } void set_current_reference(float current_ref) { this->current_reference_ = current_ref; this->current_reference_set_ = true; @@ -137,6 +138,7 @@ class BL0942 : public PollingComponent, public uart::UARTDevice { float energy_reference_ = BL0942_EREF; bool energy_reference_set_ = false; uint8_t address_ = 0; + bool reset_ = false; LineFrequency line_freq_ = LINE_FREQUENCY_50HZ; uint32_t rx_start_ = 0; uint32_t prev_cf_cnt_ = 0; diff --git a/esphome/components/bl0942/sensor.py b/esphome/components/bl0942/sensor.py index 3574443636..550f534b74 100644 --- a/esphome/components/bl0942/sensor.py +++ b/esphome/components/bl0942/sensor.py @@ -27,6 +27,7 @@ from esphome.const import ( CONF_CURRENT_REFERENCE = "current_reference" CONF_ENERGY_REFERENCE = "energy_reference" CONF_POWER_REFERENCE = "power_reference" +CONF_RESET = "reset" CONF_VOLTAGE_REFERENCE = "voltage_reference" DEPENDENCIES = ["uart"] @@ -58,19 +59,19 @@ CONFIG_SCHEMA = ( ), cv.Optional(CONF_POWER): sensor.sensor_schema( unit_of_measurement=UNIT_WATT, - accuracy_decimals=0, + accuracy_decimals=1, device_class=DEVICE_CLASS_POWER, state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_ENERGY): sensor.sensor_schema( unit_of_measurement=UNIT_KILOWATT_HOURS, - accuracy_decimals=0, + accuracy_decimals=3, device_class=DEVICE_CLASS_ENERGY, state_class=STATE_CLASS_TOTAL_INCREASING, ), cv.Optional(CONF_FREQUENCY): sensor.sensor_schema( unit_of_measurement=UNIT_HERTZ, - accuracy_decimals=0, + accuracy_decimals=2, device_class=DEVICE_CLASS_FREQUENCY, state_class=STATE_CLASS_MEASUREMENT, ), @@ -82,6 +83,7 @@ CONFIG_SCHEMA = ( ), ), cv.Optional(CONF_ADDRESS, default=0): cv.int_range(min=0, max=3), + cv.Optional(CONF_RESET, default=True): cv.boolean, cv.Optional(CONF_CURRENT_REFERENCE): cv.float_, cv.Optional(CONF_ENERGY_REFERENCE): cv.float_, cv.Optional(CONF_POWER_REFERENCE): cv.float_, @@ -115,6 +117,7 @@ async def to_code(config): cg.add(var.set_frequency_sensor(sens)) cg.add(var.set_line_freq(config[CONF_LINE_FREQUENCY])) cg.add(var.set_address(config[CONF_ADDRESS])) + cg.add(var.set_reset(config[CONF_RESET])) if (current_reference := config.get(CONF_CURRENT_REFERENCE, None)) is not None: cg.add(var.set_current_reference(current_reference)) if (voltage_reference := config.get(CONF_VOLTAGE_REFERENCE, None)) is not None: diff --git a/tests/components/bl0942/test.bk72xx-ard.yaml b/tests/components/bl0942/test.bk72xx-ard.yaml index 12772f9375..ea61734441 100644 --- a/tests/components/bl0942/test.bk72xx-ard.yaml +++ b/tests/components/bl0942/test.bk72xx-ard.yaml @@ -10,6 +10,7 @@ sensor: - platform: bl0942 address: 0 line_frequency: 50Hz + reset: false voltage: name: BL0942 Voltage current: diff --git a/tests/components/bl0942/test.esp32-ard.yaml b/tests/components/bl0942/test.esp32-ard.yaml index 45ac85aa2a..4138543967 100644 --- a/tests/components/bl0942/test.esp32-ard.yaml +++ b/tests/components/bl0942/test.esp32-ard.yaml @@ -8,6 +8,7 @@ uart: sensor: - platform: bl0942 + reset: true voltage: name: BL0942 Voltage current: From dcfad31770b18fe917c9017325bc3a019a55e3b7 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Tue, 10 Sep 2024 11:15:56 +1000 Subject: [PATCH 2061/2101] [rpi_dpi_rgb] Add bounce_buffer config for ESP-IDF 5.x (#7423) --- esphome/components/rpi_dpi_rgb/display.py | 33 +++++++++---------- .../components/rpi_dpi_rgb/rpi_dpi_rgb.cpp | 24 ++++++++++---- esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.h | 1 + 3 files changed, 34 insertions(+), 24 deletions(-) diff --git a/esphome/components/rpi_dpi_rgb/display.py b/esphome/components/rpi_dpi_rgb/display.py index 6cc8d2c27b..c26143d63e 100644 --- a/esphome/components/rpi_dpi_rgb/display.py +++ b/esphome/components/rpi_dpi_rgb/display.py @@ -1,31 +1,28 @@ -import esphome.codegen as cg -import esphome.config_validation as cv from esphome import pins +import esphome.codegen as cg from esphome.components import display +from esphome.components.esp32 import const, only_on_variant +import esphome.config_validation as cv from esphome.const import ( - CONF_ENABLE_PIN, - CONF_HSYNC_PIN, - CONF_RESET_PIN, + CONF_BLUE, + CONF_COLOR_ORDER, CONF_DATA_PINS, + CONF_DIMENSIONS, + CONF_ENABLE_PIN, + CONF_GREEN, + CONF_HEIGHT, + CONF_HSYNC_PIN, CONF_ID, CONF_IGNORE_STRAPPING_WARNING, - CONF_DIMENSIONS, - CONF_VSYNC_PIN, - CONF_WIDTH, - CONF_HEIGHT, + CONF_INVERT_COLORS, CONF_LAMBDA, - CONF_COLOR_ORDER, - CONF_RED, - CONF_GREEN, - CONF_BLUE, CONF_NUMBER, CONF_OFFSET_HEIGHT, CONF_OFFSET_WIDTH, - CONF_INVERT_COLORS, -) -from esphome.components.esp32 import ( - only_on_variant, - const, + CONF_RED, + CONF_RESET_PIN, + CONF_VSYNC_PIN, + CONF_WIDTH, ) DEPENDENCIES = ["esp32"] diff --git a/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp b/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp index f173a2ec44..655b469b91 100644 --- a/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp +++ b/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp @@ -6,9 +6,14 @@ namespace esphome { namespace rpi_dpi_rgb { void RpiDpiRgb::setup() { - esph_log_config(TAG, "Setting up RPI_DPI_RGB"); + ESP_LOGCONFIG(TAG, "Setting up RPI_DPI_RGB"); + this->reset_display_(); esp_lcd_rgb_panel_config_t config{}; config.flags.fb_in_psram = 1; +#if ESP_IDF_VERSION_MAJOR >= 5 + config.bounce_buffer_size_px = this->width_ * 10; + config.num_fbs = 1; +#endif // ESP_IDF_VERSION_MAJOR config.timings.h_res = this->width_; config.timings.v_res = this->height_; config.timings.hsync_pulse_width = this->hsync_pulse_width_; @@ -20,7 +25,6 @@ void RpiDpiRgb::setup() { config.timings.flags.pclk_active_neg = this->pclk_inverted_; config.timings.pclk_hz = this->pclk_frequency_; config.clk_src = LCD_CLK_SRC_PLL160M; - config.sram_trans_align = 64; config.psram_trans_align = 64; size_t data_pin_count = sizeof(this->data_pins_) / sizeof(this->data_pins_[0]); for (size_t i = 0; i != data_pin_count; i++) { @@ -34,11 +38,19 @@ void RpiDpiRgb::setup() { config.pclk_gpio_num = 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)); + ESP_LOGE(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_)); - esph_log_config(TAG, "RPI_DPI_RGB setup complete"); + ESP_LOGCONFIG(TAG, "RPI_DPI_RGB setup complete"); +} +void RpiDpiRgb::loop() { +#if ESP_IDF_VERSION_MAJOR >= 5 + if (this->handle_ != nullptr) + esp_lcd_rgb_panel_restart(this->handle_); +#endif // ESP_IDF_VERSION_MAJOR } void RpiDpiRgb::draw_pixels_at(int x_start, int y_start, int w, int h, const uint8_t *ptr, display::ColorOrder order, @@ -53,7 +65,7 @@ void RpiDpiRgb::draw_pixels_at(int x_start, int y_start, int w, int h, const uin } x_start += this->offset_x_; y_start += this->offset_y_; - esp_err_t err; + esp_err_t err = ESP_OK; // x_ and y_offset are offsets into the source buffer, unrelated to our own offsets into the display. if (x_offset == 0 && x_pad == 0 && y_offset == 0) { // we could deal here with a non-zero y_offset, but if x_offset is zero, y_offset probably will be so don't bother @@ -69,7 +81,7 @@ void RpiDpiRgb::draw_pixels_at(int x_start, int y_start, int w, int h, const uin } } if (err != ESP_OK) - esph_log_e(TAG, "lcd_lcd_panel_draw_bitmap failed: %s", esp_err_to_name(err)); + ESP_LOGE(TAG, "lcd_lcd_panel_draw_bitmap failed: %s", esp_err_to_name(err)); } void RpiDpiRgb::draw_pixel_at(int x, int y, Color color) { diff --git a/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.h b/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.h index 6d9d6d4ae9..10f77a2624 100644 --- a/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.h +++ b/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.h @@ -23,6 +23,7 @@ class RpiDpiRgb : public display::Display { public: void update() override { this->do_update_(); } void setup() override; + void loop() 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 draw_pixel_at(int x, int y, Color color) override; From c8aed151571ba10b5ef679aef271f1c2089e84cd Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Tue, 10 Sep 2024 11:24:18 +1000 Subject: [PATCH 2062/2101] [LVGL] Add color gradients (#7427) --- esphome/components/lvgl/__init__.py | 22 +++------ esphome/components/lvgl/defines.py | 17 +++++++ esphome/components/lvgl/gradient.py | 61 ++++++++++++++++++++++++ esphome/components/lvgl/lv_validation.py | 57 +++++++++++++++------- esphome/components/lvgl/lvcode.py | 5 +- esphome/components/lvgl/lvgl_esphome.h | 3 -- esphome/components/lvgl/schemas.py | 9 ++-- esphome/components/lvgl/types.py | 1 + esphome/components/lvgl/widgets/meter.py | 9 +++- tests/components/lvgl/lvgl-package.yaml | 50 ++++++++++++++++++- 10 files changed, 190 insertions(+), 44 deletions(-) create mode 100644 esphome/components/lvgl/gradient.py diff --git a/esphome/components/lvgl/__init__.py b/esphome/components/lvgl/__init__.py index a4ca9d56f3..64f254cde8 100644 --- a/esphome/components/lvgl/__init__.py +++ b/esphome/components/lvgl/__init__.py @@ -22,8 +22,9 @@ from esphome.helpers import write_file_if_changed from . import defines as df, helpers, lv_validation as lvalid from .automation import disp_update, focused_widgets, update_to_code -from .defines import CONF_ADJUSTABLE, CONF_SKIP +from .defines import add_define from .encoders import ENCODERS_CONFIG, encoders_to_code, initial_focus_to_code +from .gradient import GRADIENT_SCHEMA, gradients_to_code from .lv_validation import lv_bool, lv_images_used from .lvcode import LvContext, LvglComponent from .schemas import ( @@ -128,17 +129,6 @@ for w_type in WIDGET_TYPES.values(): )(update_to_code) -lv_defines = {} # Dict of #defines to provide as build flags - - -def add_define(macro, value="1"): - if macro in lv_defines and lv_defines[macro] != value: - LOGGER.error( - "Redefinition of %s - was %s now %s", macro, lv_defines[macro], value - ) - lv_defines[macro] = value - - def as_macro(macro, value): if value is None: return f"#define {macro}" @@ -153,14 +143,14 @@ LV_CONF_H_FORMAT = """\ def generate_lv_conf_h(): - definitions = [as_macro(m, v) for m, v in lv_defines.items()] + definitions = [as_macro(m, v) for m, v in df.lv_defines.items()] definitions.sort() return LV_CONF_H_FORMAT.format("\n".join(definitions)) def final_validation(config): if pages := config.get(CONF_PAGES): - if all(p[CONF_SKIP] for p in pages): + if all(p[df.CONF_SKIP] for p in pages): raise cv.Invalid("At least one page must not be skipped") global_config = full_config.get() for display_id in config[df.CONF_DISPLAYS]: @@ -185,7 +175,7 @@ def final_validation(config): for w in focused_widgets: path = global_config.get_path_for_id(w) widget_conf = global_config.get_config_for_path(path[:-1]) - if CONF_ADJUSTABLE in widget_conf and not widget_conf[CONF_ADJUSTABLE]: + if df.CONF_ADJUSTABLE in widget_conf and not widget_conf[df.CONF_ADJUSTABLE]: raise cv.Invalid( "A non adjustable arc may not be focused", path, @@ -268,6 +258,7 @@ async def to_code(config): await encoders_to_code(lv_component, config) await theme_to_code(config) await styles_to_code(config) + await gradients_to_code(config) await set_obj_properties(lv_scr_act, config) await add_widgets(lv_scr_act, config) await add_pages(lv_component, config) @@ -351,6 +342,7 @@ CONFIG_SCHEMA = ( cv.Optional(df.CONF_THEME): cv.Schema( {cv.Optional(name): obj_schema(w) for name, w in WIDGET_TYPES.items()} ), + cv.Optional(df.CONF_GRADIENTS): GRADIENT_SCHEMA, cv.Optional(df.CONF_TOUCHSCREENS, default=None): touchscreen_schema, cv.Optional(df.CONF_ENCODERS, default=None): ENCODERS_CONFIG, cv.GenerateID(df.CONF_DEFAULT_GROUP): cv.declare_id(lv_group_t), diff --git a/esphome/components/lvgl/defines.py b/esphome/components/lvgl/defines.py index ee8472f90d..3db49d26a4 100644 --- a/esphome/components/lvgl/defines.py +++ b/esphome/components/lvgl/defines.py @@ -4,6 +4,8 @@ Constants already defined in esphome.const are not duplicated here and must be i """ +import logging + from esphome import codegen as cg, config_validation as cv from esphome.const import CONF_ITEMS from esphome.core import Lambda @@ -13,8 +15,19 @@ from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor from .helpers import requires_component +LOGGER = logging.getLogger(__name__) lvgl_ns = cg.esphome_ns.namespace("lvgl") +lv_defines = {} # Dict of #defines to provide as build flags + + +def add_define(macro, value="1"): + if macro in lv_defines and lv_defines[macro] != value: + LOGGER.error( + "Redefinition of %s - was %s now %s", macro, lv_defines[macro], value + ) + lv_defines[macro] = value + def literal(arg): if isinstance(arg, str): @@ -173,6 +186,9 @@ LV_ANIM = LvConstant( "OUT_BOTTOM", ) +LV_GRAD_DIR = LvConstant("LV_GRAD_DIR_", "NONE", "HOR", "VER") +LV_DITHER = LvConstant("LV_DITHER_", "NONE", "ORDERED", "ERR_DIFF") + LOG_LEVELS = ( "TRACE", "INFO", @@ -406,6 +422,7 @@ CONF_FLEX_ALIGN_TRACK = "flex_align_track" CONF_FLEX_GROW = "flex_grow" CONF_FREEZE = "freeze" CONF_FULL_REFRESH = "full_refresh" +CONF_GRADIENTS = "gradients" CONF_GRID_CELL_ROW_POS = "grid_cell_row_pos" CONF_GRID_CELL_COLUMN_POS = "grid_cell_column_pos" CONF_GRID_CELL_ROW_SPAN = "grid_cell_row_span" diff --git a/esphome/components/lvgl/gradient.py b/esphome/components/lvgl/gradient.py new file mode 100644 index 0000000000..bc89470d47 --- /dev/null +++ b/esphome/components/lvgl/gradient.py @@ -0,0 +1,61 @@ +from esphome import config_validation as cv +import esphome.codegen as cg +from esphome.const import ( + CONF_COLOR, + CONF_DIRECTION, + CONF_DITHER, + CONF_ID, + CONF_POSITION, +) +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 + +CONF_STOPS = "stops" + + +def min_stops(value): + if len(value) < 2: + raise cv.Invalid("Must have at least 2 stops") + return value + + +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.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, + } + ) + ], + min_stops, + ), + } + ) +) + + +async def gradients_to_code(config): + max_stops = 2 + 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]) + ) + add_define("LV_GRADIENT_MAX_STOPS", max_stops) diff --git a/esphome/components/lvgl/lv_validation.py b/esphome/components/lvgl/lv_validation.py index d8af9f7aa9..8593deb869 100644 --- a/esphome/components/lvgl/lv_validation.py +++ b/esphome/components/lvgl/lv_validation.py @@ -1,12 +1,19 @@ from typing import Union import esphome.codegen as cg -from esphome.components.color import ColorStruct +from esphome.components.color import CONF_HEX, ColorStruct, from_rgbw from esphome.components.font import Font from esphome.components.image import Image_ import esphome.config_validation as cv -from esphome.const import CONF_ARGS, CONF_COLOR, CONF_FORMAT, CONF_TIME, CONF_VALUE -from esphome.core import HexInt, Lambda +from esphome.const import ( + CONF_ARGS, + CONF_COLOR, + CONF_FORMAT, + CONF_ID, + CONF_TIME, + CONF_VALUE, +) +from esphome.core import CORE, ID, Lambda from esphome.cpp_generator import MockObj from esphome.cpp_types import ESPTime, uint32 from esphome.helpers import cpp_string_escape @@ -23,14 +30,9 @@ from .defines import ( call_lambda, literal, ) -from .helpers import ( - esphome_fonts_used, - lv_fonts_used, - lvgl_components_required, - requires_component, -) +from .helpers import esphome_fonts_used, lv_fonts_used, requires_component from .lvcode import lv_expr -from .types import lv_font_t, lv_img_t +from .types import lv_font_t, lv_gradient_t, lv_img_t opacity_consts = LvConstant("LV_OPA_", "TRANSP", "COVER") @@ -59,11 +61,17 @@ def color_retmapper(value): if isinstance(value, cv.Lambda): return cv.returning_lambda(value) if isinstance(value, int): - hexval = HexInt(value) - return lv_expr.color_hex(hexval) - # Must be an id - lvgl_components_required.add(CONF_COLOR) - return lv_expr.color_from(MockObj(value)) + return literal( + f"lv_color_make({(value >> 16) & 0xFF}, {(value >> 8) & 0xFF}, {value & 0xFF})" + ) + if isinstance(value, ID): + cval = [x for x in CORE.config[CONF_COLOR] if x[CONF_ID] == value][0] + if CONF_HEX in cval: + r, g, b = cval[CONF_HEX] + else: + r, g, b, _ = from_rgbw(cval) + return literal(f"lv_color_make({r}, {g}, {b})") + assert False def option_string(value): @@ -132,7 +140,7 @@ radius_consts = LvConstant("LV_RADIUS_", "CIRCLE") @schema_extractor("one_of") -def radius_validator(value): +def fraction_validator(value): if value == SCHEMA_EXTRACT: return radius_consts.choices value = cv.Any(size, cv.percentage, radius_consts.one_of)(value) @@ -141,7 +149,7 @@ def radius_validator(value): return value -radius = LValidator(radius_validator, uint32, retmapper=literal) +lv_fraction = LValidator(fraction_validator, uint32, retmapper=literal) def id_name(value): @@ -242,6 +250,21 @@ lv_int = LValidator(cv.int_, cg.int_) lv_brightness = LValidator(cv.percentage, cg.float_, retmapper=lambda x: int(x * 255)) +def gradient_mapper(value): + return MockObj(value) + + +def gradient_validator(value): + return cv.use_id(lv_gradient_t)(value) + + +lv_gradient = LValidator( + validator=gradient_validator, + rtype=lv_gradient_t, + retmapper=gradient_mapper, +) + + def is_lv_font(font): return isinstance(font, str) and font.lower() in LV_FONTS diff --git a/esphome/components/lvgl/lvcode.py b/esphome/components/lvgl/lvcode.py index a3d13f7f8c..3a080d63e9 100644 --- a/esphome/components/lvgl/lvcode.py +++ b/esphome/components/lvgl/lvcode.py @@ -184,8 +184,9 @@ class LvContext(LambdaContext): self.lv_component = lv_component async def add_init_lambda(self): - cg.add(self.lv_component.add_init_lambda(await self.get_lambda())) - LvContext.added_lambda_count += 1 + if self.code_list: + cg.add(self.lv_component.add_init_lambda(await self.get_lambda())) + LvContext.added_lambda_count += 1 async def __aexit__(self, exc_type, exc_val, exc_tb): await super().__aexit__(exc_type, exc_val, exc_tb) diff --git a/esphome/components/lvgl/lvgl_esphome.h b/esphome/components/lvgl/lvgl_esphome.h index e248530971..d5cff51de2 100644 --- a/esphome/components/lvgl/lvgl_esphome.h +++ b/esphome/components/lvgl/lvgl_esphome.h @@ -42,9 +42,6 @@ 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 bool lv_is_pre_initialise(); -#ifdef USE_LVGL_COLOR -inline lv_color_t lv_color_from(Color color) { return lv_color_make(color.red, color.green, color.blue); } -#endif // USE_LVGL_COLOR #if LV_COLOR_DEPTH == 16 static const display::ColorBitness LV_BITNESS = display::ColorBitness::COLOR_BITNESS_565; #elif LV_COLOR_DEPTH == 32 diff --git a/esphome/components/lvgl/schemas.py b/esphome/components/lvgl/schemas.py index 9ff0fec5bc..780057623a 100644 --- a/esphome/components/lvgl/schemas.py +++ b/esphome/components/lvgl/schemas.py @@ -17,9 +17,9 @@ from esphome.core import TimePeriod from esphome.schema_extractors import SCHEMA_EXTRACT from . import defines as df, lv_validation as lvalid -from .defines import CONF_TIME_FORMAT +from .defines import CONF_TIME_FORMAT, LV_GRAD_DIR from .helpers import add_lv_use, requires_component, validate_printf -from .lv_validation import lv_color, lv_font, lv_image +from .lv_validation import lv_color, lv_font, lv_gradient, lv_image from .lvcode import LvglComponent, lv_event_t_ptr from .types import ( LVEncoderListener, @@ -94,9 +94,10 @@ STYLE_PROPS = { "arc_width": cv.positive_int, "anim_time": lvalid.lv_milliseconds, "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": df.LvConstant("LV_GRAD_DIR_", "NONE", "HOR", "VER").one_of, + "bg_grad_dir": LV_GRAD_DIR.one_of, "bg_grad_stop": lvalid.stop_value, "bg_image_opa": lvalid.opacity, "bg_image_recolor": lvalid.lv_color, @@ -160,7 +161,7 @@ STYLE_PROPS = { "max_width": lvalid.pixels_or_percent, "min_height": lvalid.pixels_or_percent, "min_width": lvalid.pixels_or_percent, - "radius": lvalid.radius, + "radius": lvalid.lv_fraction, "width": lvalid.size, "x": lvalid.pixels_or_percent, "y": lvalid.pixels_or_percent, diff --git a/esphome/components/lvgl/types.py b/esphome/components/lvgl/types.py index e4735ea58d..b452ab5fb3 100644 --- a/esphome/components/lvgl/types.py +++ b/esphome/components/lvgl/types.py @@ -59,6 +59,7 @@ 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_gradient_t = LvType("lv_grad_dsc_t") LV_EVENT = MockObj(base="LV_EVENT_", op="") LV_STATE = MockObj(base="LV_STATE_", op="") diff --git a/esphome/components/lvgl/widgets/meter.py b/esphome/components/lvgl/widgets/meter.py index 7cf154d6f3..36f6643022 100644 --- a/esphome/components/lvgl/widgets/meter.py +++ b/esphome/components/lvgl/widgets/meter.py @@ -5,6 +5,7 @@ from esphome.const import ( CONF_COLOR, CONF_COUNT, CONF_ID, + CONF_ITEMS, CONF_LENGTH, CONF_LOCAL, CONF_RANGE_FROM, @@ -17,6 +18,7 @@ from esphome.const import ( from ..automation import action_to_code from ..defines import ( CONF_END_VALUE, + CONF_INDICATOR, CONF_MAIN, CONF_PIVOT_X, CONF_PIVOT_Y, @@ -165,7 +167,12 @@ METER_SCHEMA = {cv.Optional(CONF_SCALES): cv.ensure_list(SCALE_SCHEMA)} class MeterType(WidgetType): def __init__(self): - super().__init__(CONF_METER, lv_meter_t, (CONF_MAIN,), METER_SCHEMA) + super().__init__( + CONF_METER, + lv_meter_t, + (CONF_MAIN, CONF_INDICATOR, CONF_TICKS, CONF_ITEMS), + METER_SCHEMA, + ) async def to_code(self, w: Widget, config): """For a meter object, create and set parameters""" diff --git a/tests/components/lvgl/lvgl-package.yaml b/tests/components/lvgl/lvgl-package.yaml index 0db6a6a995..9d157ea5b0 100644 --- a/tests/components/lvgl/lvgl-package.yaml +++ b/tests/components/lvgl/lvgl-package.yaml @@ -1,12 +1,32 @@ lvgl: log_level: TRACE bg_color: light_blue - disp_bg_color: 0xffff00 + disp_bg_color: color_id disp_bg_image: cat_image theme: obj: border_width: 1 + gradients: + - id: color_bar + direction: hor + dither: err_diff + stops: + - color: 0xFF0000 + position: 0 + - color: 0xFFFF00 + position: 42 + - color: 0x00FF00 + position: 84 + - color: 0x00FFFF + position: 127 + - color: 0x0000FF + position: 169 + - color: 0xFF00FF + position: 212 + - color: 0xFF0000 + position: 255 + style_definitions: - id: style_test bg_color: 0x2F8CD8 @@ -31,7 +51,7 @@ lvgl: - id: date_style text_font: roboto10 align: center - text_color: 0x000000 + text_color: color_id2 bg_opa: cover radius: 4 pad_all: 2 @@ -386,6 +406,22 @@ lvgl: - id: page2 widgets: + - slider: + min_value: 0 + max_value: 255 + bg_opa: cover + bg_grad: color_bar + radius: 0 + indicator: + bg_opa: transp + knob: + radius: 1 + width: 4 + height: 10% + bg_color: 0x000000 + width: 100% + height: 10% + align: top_mid - button: styles: spin_button id: spin_up @@ -586,3 +622,13 @@ image: color: - id: light_blue hex: "3340FF" + - id: color_id + red: 0.5 + green: 0.5 + blue: 0.5 + white: 0.5 + - id: color_id2 + red_int: 0xFF + green_int: 123 + blue_int: 64 + white_int: 255 From de7d2c33e18246668a64993ce3badc4e1b053359 Mon Sep 17 00:00:00 2001 From: marcovaneck <67060615+marcovaneck@users.noreply.github.com> Date: Tue, 10 Sep 2024 10:22:58 +0200 Subject: [PATCH 2063/2101] [dsmr] Add internal 'telegram' text_sensor to support bridging (#6841) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/dsmr/dsmr.cpp | 6 ++++++ esphome/components/dsmr/dsmr.h | 6 ++++++ esphome/components/dsmr/text_sensor.py | 9 +++++++-- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/esphome/components/dsmr/dsmr.cpp b/esphome/components/dsmr/dsmr.cpp index f382730912..193ea1d4e5 100644 --- a/esphome/components/dsmr/dsmr.cpp +++ b/esphome/components/dsmr/dsmr.cpp @@ -256,6 +256,7 @@ bool Dsmr::parse_telegram() { MyData data; ESP_LOGV(TAG, "Trying to parse telegram"); this->stop_requesting_data_(); + ::dsmr::ParseResult res = ::dsmr::P1Parser::parse(&data, this->telegram_, this->bytes_read_, false, this->crc_check_); // Parse telegram according to data definition. Ignore unknown values. @@ -267,6 +268,11 @@ bool Dsmr::parse_telegram() { } else { this->status_clear_warning(); this->publish_sensors(data); + + // publish the telegram, after publishing the sensors so it can also trigger action based on latest values + if (this->s_telegram_ != nullptr) { + this->s_telegram_->publish_state(std::string(this->telegram_, this->bytes_read_)); + } return true; } } diff --git a/esphome/components/dsmr/dsmr.h b/esphome/components/dsmr/dsmr.h index 6621d02cae..7304737b50 100644 --- a/esphome/components/dsmr/dsmr.h +++ b/esphome/components/dsmr/dsmr.h @@ -85,6 +85,9 @@ class Dsmr : public Component, public uart::UARTDevice { void set_##s(text_sensor::TextSensor *sensor) { s_##s##_ = sensor; } DSMR_TEXT_SENSOR_LIST(DSMR_SET_TEXT_SENSOR, ) + // handled outside dsmr + void set_telegram(text_sensor::TextSensor *sensor) { s_telegram_ = sensor; } + protected: void receive_telegram_(); void receive_encrypted_telegram_(); @@ -124,6 +127,9 @@ class Dsmr : public Component, public uart::UARTDevice { bool header_found_{false}; bool footer_found_{false}; + // handled outside dsmr + text_sensor::TextSensor *s_telegram_{nullptr}; + // Sensor member pointers #define DSMR_DECLARE_SENSOR(s) sensor::Sensor *s_##s##_{nullptr}; DSMR_SENSOR_LIST(DSMR_DECLARE_SENSOR, ) diff --git a/esphome/components/dsmr/text_sensor.py b/esphome/components/dsmr/text_sensor.py index 202cc07020..7c13fe7d58 100644 --- a/esphome/components/dsmr/text_sensor.py +++ b/esphome/components/dsmr/text_sensor.py @@ -1,7 +1,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import text_sensor - +from esphome.const import CONF_INTERNAL from . import Dsmr, CONF_DSMR_ID AUTO_LOAD = ["dsmr"] @@ -22,6 +22,9 @@ CONFIG_SCHEMA = cv.Schema( cv.Optional("water_equipment_id"): text_sensor.text_sensor_schema(), cv.Optional("sub_equipment_id"): text_sensor.text_sensor_schema(), cv.Optional("gas_delivered_text"): text_sensor.text_sensor_schema(), + cv.Optional("telegram"): text_sensor.text_sensor_schema().extend( + {cv.Optional(CONF_INTERNAL, default=True): cv.boolean} + ), } ).extend(cv.COMPONENT_SCHEMA) @@ -37,7 +40,9 @@ async def to_code(config): if id and id.type == text_sensor.TextSensor: var = await text_sensor.new_text_sensor(conf) cg.add(getattr(hub, f"set_{key}")(var)) - text_sensors.append(f"F({key})") + if key != "telegram": + # telegram is not handled by dsmr + text_sensors.append(f"F({key})") if text_sensors: cg.add_define( From 7abbb0fb97de87469520b45909fb54e83a411b57 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 10 Sep 2024 20:42:46 +0100 Subject: [PATCH 2064/2101] Pull in new AsyncTCP for IPv6 on BK72xx (#7431) --- esphome/components/async_tcp/__init__.py | 6 +++--- platformio.ini | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/async_tcp/__init__.py b/esphome/components/async_tcp/__init__.py index eae8c0e2df..99e250b6fc 100644 --- a/esphome/components/async_tcp/__init__.py +++ b/esphome/components/async_tcp/__init__.py @@ -1,13 +1,13 @@ # Dummy integration to allow relying on AsyncTCP import esphome.codegen as cg import esphome.config_validation as cv -from esphome.core import CORE, coroutine_with_priority from esphome.const import ( + PLATFORM_BK72XX, PLATFORM_ESP32, PLATFORM_ESP8266, - PLATFORM_BK72XX, PLATFORM_RTL87XX, ) +from esphome.core import CORE, coroutine_with_priority CODEOWNERS = ["@OttoWinter"] @@ -22,7 +22,7 @@ CONFIG_SCHEMA = cv.All( async def to_code(config): if CORE.is_esp32 or CORE.is_libretiny: # https://github.com/esphome/AsyncTCP/blob/master/library.json - cg.add_library("esphome/AsyncTCP-esphome", "2.1.3") + cg.add_library("esphome/AsyncTCP-esphome", "2.1.4") elif CORE.is_esp8266: # https://github.com/esphome/ESPAsyncTCP cg.add_library("esphome/ESPAsyncTCP-esphome", "2.0.0") diff --git a/platformio.ini b/platformio.ini index ee18068a29..7d912aaf54 100644 --- a/platformio.ini +++ b/platformio.ini @@ -119,7 +119,7 @@ lib_deps = WiFi ; wifi,web_server_base,ethernet (Arduino built-in) Update ; ota,web_server_base (Arduino built-in) ${common:arduino.lib_deps} - esphome/AsyncTCP-esphome@2.1.3 ; async_tcp + esphome/AsyncTCP-esphome@2.1.4 ; async_tcp WiFiClientSecure ; http_request,nextion (Arduino built-in) HTTPClient ; http_request,nextion (Arduino built-in) ESPmDNS ; mdns (Arduino built-in) From 7b90bfaec69bf685f75ac44ec7e50b56bc614a0d Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 10 Sep 2024 20:43:19 +0100 Subject: [PATCH 2065/2101] Bump LibreTiny recommended version to 1.7.0 (#7432) --- esphome/components/libretiny/__init__.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/esphome/components/libretiny/__init__.py b/esphome/components/libretiny/__init__.py index 9ba889f493..cc7fae7e70 100644 --- a/esphome/components/libretiny/__init__.py +++ b/esphome/components/libretiny/__init__.py @@ -170,13 +170,11 @@ def _notify_old_style(config): return config -# NOTE: Keep this in mind when updating the recommended version: -# * For all constants below, update platformio.ini (in this repo) # The dev and latest branches will be at *least* this version, which is what matters. ARDUINO_VERSIONS = { "dev": (cv.Version(1, 7, 0), "https://github.com/libretiny-eu/libretiny.git"), "latest": (cv.Version(1, 7, 0), "libretiny"), - "recommended": (cv.Version(1, 5, 1), None), + "recommended": (cv.Version(1, 7, 0), None), } From 39ad358b51c105c78e7b060303aa0fb78372f6b3 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 10 Sep 2024 23:02:05 +0100 Subject: [PATCH 2066/2101] Enable IPv6 support for BK72xx (#7398) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/network/__init__.py | 4 ++++ .../components/wifi/wifi_component_libretiny.cpp | 16 +++++++++++++++- .../components/network/test-ipv6.bk72xx-ard.yaml | 6 +++++- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/esphome/components/network/__init__.py b/esphome/components/network/__init__.py index 772ba230d9..be4e102930 100644 --- a/esphome/components/network/__init__.py +++ b/esphome/components/network/__init__.py @@ -17,6 +17,7 @@ CONFIG_SCHEMA = cv.Schema( esp8266=False, esp32=False, rp2040=False, + bk72xx=False, ): cv.All( cv.boolean, cv.Any( @@ -25,6 +26,7 @@ CONFIG_SCHEMA = cv.Schema( esp32_arduino=cv.Version(0, 0, 0), esp8266_arduino=cv.Version(0, 0, 0), rp2040_arduino=cv.Version(0, 0, 0), + bk72xx_libretiny=cv.Version(1, 7, 0), ), cv.boolean_false, ), @@ -52,3 +54,5 @@ async def to_code(config): cg.add_build_flag("-DPIO_FRAMEWORK_ARDUINO_ENABLE_IPV6") if CORE.is_esp8266: cg.add_build_flag("-DPIO_FRAMEWORK_ARDUINO_LWIP2_IPV6_LOW_MEMORY") + if CORE.is_bk72xx: + cg.add_build_flag("-DCONFIG_IPV6") diff --git a/esphome/components/wifi/wifi_component_libretiny.cpp b/esphome/components/wifi/wifi_component_libretiny.cpp index 19ade84a88..afb30c3bcf 100644 --- a/esphome/components/wifi/wifi_component_libretiny.cpp +++ b/esphome/components/wifi/wifi_component_libretiny.cpp @@ -85,7 +85,16 @@ bool WiFiComponent::wifi_sta_ip_config_(optional manual_ip) { network::IPAddresses WiFiComponent::wifi_sta_ip_addresses() { if (!this->has_sta()) return {}; - return {WiFi.localIP()}; + network::IPAddresses addresses; + addresses[0] = WiFi.localIP(); +#if USE_NETWORK_IPV6 + int i = 1; + auto v6_addresses = WiFi.allLocalIPv6(); + for (auto address : v6_addresses) { + addresses[i++] = network::IPAddress(address.toString().c_str()); + } +#endif /* USE_NETWORK_IPV6 */ + return addresses; } bool WiFiComponent::wifi_apply_hostname_() { @@ -321,6 +330,11 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_ s_sta_connecting = false; break; } + case ESPHOME_EVENT_ID_WIFI_STA_GOT_IP6: { + // auto it = info.got_ip.ip_info; + ESP_LOGV(TAG, "Event: Got IPv6"); + break; + } case ESPHOME_EVENT_ID_WIFI_STA_LOST_IP: { ESP_LOGV(TAG, "Event: Lost IP"); break; diff --git a/tests/components/network/test-ipv6.bk72xx-ard.yaml b/tests/components/network/test-ipv6.bk72xx-ard.yaml index 361ca09977..d0c4bbfcb9 100644 --- a/tests/components/network/test-ipv6.bk72xx-ard.yaml +++ b/tests/components/network/test-ipv6.bk72xx-ard.yaml @@ -1,4 +1,8 @@ substitutions: - network_enable_ipv6: "false" + network_enable_ipv6: "true" + +bk72xx: + framework: + version: 1.7.0 <<: !include common.yaml From ffc2b587141d9984698214b2a4858df1756e275b Mon Sep 17 00:00:00 2001 From: NP v/d Spek Date: Wed, 11 Sep 2024 01:30:46 +0200 Subject: [PATCH 2067/2101] Move I2S config settings the the base i2sAudio files. Phase 1 (#7183) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/i2s_audio/__init__.py | 77 ++++++++++++++++--- esphome/components/i2s_audio/i2s_audio.h | 18 ++++- .../i2s_audio/microphone/__init__.py | 69 ++++------------- .../microphone/i2s_audio_microphone.h | 10 +-- .../components/i2s_audio/speaker/__init__.py | 50 +++++------- .../i2s_audio/speaker/i2s_audio_speaker.cpp | 10 +-- .../i2s_audio/speaker/i2s_audio_speaker.h | 4 +- 7 files changed, 129 insertions(+), 109 deletions(-) diff --git a/esphome/components/i2s_audio/__init__.py b/esphome/components/i2s_audio/__init__.py index 05e44696d8..90dc8a24ee 100644 --- a/esphome/components/i2s_audio/__init__.py +++ b/esphome/components/i2s_audio/__init__.py @@ -1,16 +1,16 @@ -import esphome.config_validation as cv -import esphome.final_validate as fv -import esphome.codegen as cg - from esphome import pins -from esphome.const import CONF_ID +import esphome.codegen as cg from esphome.components.esp32 import get_esp32_variant from esphome.components.esp32.const import ( VARIANT_ESP32, + VARIANT_ESP32C3, VARIANT_ESP32S2, VARIANT_ESP32S3, - VARIANT_ESP32C3, ) +import esphome.config_validation as cv +from esphome.const import CONF_CHANNEL, CONF_ID, CONF_SAMPLE_RATE +from esphome.cpp_generator import MockObjClass +import esphome.final_validate as fv CODEOWNERS = ["@jesserockz"] DEPENDENCIES = ["esp32"] @@ -25,16 +25,22 @@ CONF_I2S_LRCLK_PIN = "i2s_lrclk_pin" CONF_I2S_AUDIO = "i2s_audio" CONF_I2S_AUDIO_ID = "i2s_audio_id" +CONF_BITS_PER_SAMPLE = "bits_per_sample" CONF_I2S_MODE = "i2s_mode" CONF_PRIMARY = "primary" CONF_SECONDARY = "secondary" +CONF_LEFT = "left" +CONF_RIGHT = "right" +CONF_STEREO = "stereo" + i2s_audio_ns = cg.esphome_ns.namespace("i2s_audio") I2SAudioComponent = i2s_audio_ns.class_("I2SAudioComponent", cg.Component) -I2SAudioIn = i2s_audio_ns.class_("I2SAudioIn", cg.Parented.template(I2SAudioComponent)) -I2SAudioOut = i2s_audio_ns.class_( - "I2SAudioOut", cg.Parented.template(I2SAudioComponent) +I2SAudioBase = i2s_audio_ns.class_( + "I2SAudioBase", cg.Parented.template(I2SAudioComponent) ) +I2SAudioIn = i2s_audio_ns.class_("I2SAudioIn", I2SAudioBase) +I2SAudioOut = i2s_audio_ns.class_("I2SAudioOut", I2SAudioBase) i2s_mode_t = cg.global_ns.enum("i2s_mode_t") I2S_MODE_OPTIONS = { @@ -50,6 +56,59 @@ I2S_PORTS = { VARIANT_ESP32C3: 1, } +i2s_channel_fmt_t = cg.global_ns.enum("i2s_channel_fmt_t") +I2S_CHANNELS = { + CONF_LEFT: i2s_channel_fmt_t.I2S_CHANNEL_FMT_ONLY_LEFT, + CONF_RIGHT: i2s_channel_fmt_t.I2S_CHANNEL_FMT_ONLY_RIGHT, + CONF_STEREO: i2s_channel_fmt_t.I2S_CHANNEL_FMT_RIGHT_LEFT, +} + +i2s_bits_per_sample_t = cg.global_ns.enum("i2s_bits_per_sample_t") +I2S_BITS_PER_SAMPLE = { + 8: i2s_bits_per_sample_t.I2S_BITS_PER_SAMPLE_8BIT, + 16: i2s_bits_per_sample_t.I2S_BITS_PER_SAMPLE_16BIT, + 32: i2s_bits_per_sample_t.I2S_BITS_PER_SAMPLE_32BIT, +} + +INTERNAL_ADC_VARIANTS = [VARIANT_ESP32] +PDM_VARIANTS = [VARIANT_ESP32, VARIANT_ESP32S3] + +_validate_bits = cv.float_with_unit("bits", "bit") + + +def i2s_audio_component_schema( + class_: MockObjClass, + default_sample_rate: int, + default_channel: str, + default_bits_per_sample: str, +): + return cv.Schema( + { + cv.GenerateID(): cv.declare_id(class_), + cv.GenerateID(CONF_I2S_AUDIO_ID): cv.use_id(I2SAudioComponent), + cv.Optional(CONF_CHANNEL, default=default_channel): cv.enum(I2S_CHANNELS), + cv.Optional(CONF_SAMPLE_RATE, default=default_sample_rate): cv.int_range( + min=1 + ), + cv.Optional(CONF_BITS_PER_SAMPLE, default=default_bits_per_sample): cv.All( + _validate_bits, cv.enum(I2S_BITS_PER_SAMPLE) + ), + cv.Optional(CONF_I2S_MODE, default=CONF_PRIMARY): cv.enum( + I2S_MODE_OPTIONS, lower=True + ), + } + ) + + +async def register_i2s_audio_component(var, config): + await cg.register_parented(var, config[CONF_I2S_AUDIO_ID]) + + cg.add(var.set_i2s_mode(config[CONF_I2S_MODE])) + cg.add(var.set_channel(config[CONF_CHANNEL])) + cg.add(var.set_sample_rate(config[CONF_SAMPLE_RATE])) + cg.add(var.set_bits_per_sample(config[CONF_BITS_PER_SAMPLE])) + + CONFIG_SCHEMA = cv.Schema( { cv.GenerateID(): cv.declare_id(I2SAudioComponent), diff --git a/esphome/components/i2s_audio/i2s_audio.h b/esphome/components/i2s_audio/i2s_audio.h index d8d4a23dde..727fb6c4e1 100644 --- a/esphome/components/i2s_audio/i2s_audio.h +++ b/esphome/components/i2s_audio/i2s_audio.h @@ -11,9 +11,23 @@ namespace i2s_audio { class I2SAudioComponent; -class I2SAudioIn : public Parented {}; +class I2SAudioBase : public Parented { + public: + 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_sample_rate(uint32_t sample_rate) { this->sample_rate_ = sample_rate; } + void set_bits_per_sample(i2s_bits_per_sample_t bits_per_sample) { this->bits_per_sample_ = bits_per_sample; } -class I2SAudioOut : public Parented {}; + protected: + i2s_mode_t i2s_mode_{}; + i2s_channel_fmt_t channel_; + uint32_t sample_rate_; + i2s_bits_per_sample_t bits_per_sample_; +}; + +class I2SAudioIn : public I2SAudioBase {}; + +class I2SAudioOut : public I2SAudioBase {}; class I2SAudioComponent : public Component { public: diff --git a/esphome/components/i2s_audio/microphone/__init__.py b/esphome/components/i2s_audio/microphone/__init__.py index 844f176bea..e2ece03e68 100644 --- a/esphome/components/i2s_audio/microphone/__init__.py +++ b/esphome/components/i2s_audio/microphone/__init__.py @@ -1,20 +1,19 @@ -import esphome.config_validation as cv -import esphome.codegen as cg - from esphome import pins -from esphome.const import CONF_CHANNEL, CONF_ID, CONF_NUMBER, CONF_SAMPLE_RATE -from esphome.components import microphone, esp32 +import esphome.codegen as cg +from esphome.components import esp32, microphone from esphome.components.adc import ESP32_VARIANT_ADC1_PIN_TO_CHANNEL, validate_adc_pin +import esphome.config_validation as cv +from esphome.const import CONF_ID, CONF_NUMBER from .. import ( - CONF_I2S_MODE, - CONF_PRIMARY, - I2S_MODE_OPTIONS, - i2s_audio_ns, - I2SAudioComponent, - I2SAudioIn, - CONF_I2S_AUDIO_ID, CONF_I2S_DIN_PIN, + CONF_RIGHT, + INTERNAL_ADC_VARIANTS, + PDM_VARIANTS, + I2SAudioIn, + i2s_audio_component_schema, + i2s_audio_ns, + register_i2s_audio_component, ) CODEOWNERS = ["@jesserockz"] @@ -23,29 +22,13 @@ DEPENDENCIES = ["i2s_audio"] CONF_ADC_PIN = "adc_pin" CONF_ADC_TYPE = "adc_type" CONF_PDM = "pdm" -CONF_BITS_PER_SAMPLE = "bits_per_sample" + CONF_USE_APLL = "use_apll" I2SAudioMicrophone = i2s_audio_ns.class_( "I2SAudioMicrophone", I2SAudioIn, microphone.Microphone, cg.Component ) -i2s_channel_fmt_t = cg.global_ns.enum("i2s_channel_fmt_t") -CHANNELS = { - "left": i2s_channel_fmt_t.I2S_CHANNEL_FMT_ONLY_LEFT, - "right": i2s_channel_fmt_t.I2S_CHANNEL_FMT_ONLY_RIGHT, -} -i2s_bits_per_sample_t = cg.global_ns.enum("i2s_bits_per_sample_t") -BITS_PER_SAMPLE = { - 16: i2s_bits_per_sample_t.I2S_BITS_PER_SAMPLE_16BIT, - 32: i2s_bits_per_sample_t.I2S_BITS_PER_SAMPLE_32BIT, -} - -INTERNAL_ADC_VARIANTS = [esp32.const.VARIANT_ESP32] -PDM_VARIANTS = [esp32.const.VARIANT_ESP32, esp32.const.VARIANT_ESP32S3] - -_validate_bits = cv.float_with_unit("bits", "bit") - def validate_esp32_variant(config): variant = esp32.get_esp32_variant() @@ -62,19 +45,7 @@ def validate_esp32_variant(config): BASE_SCHEMA = microphone.MICROPHONE_SCHEMA.extend( - { - cv.GenerateID(): cv.declare_id(I2SAudioMicrophone), - cv.GenerateID(CONF_I2S_AUDIO_ID): cv.use_id(I2SAudioComponent), - cv.Optional(CONF_CHANNEL, default="right"): cv.enum(CHANNELS), - cv.Optional(CONF_SAMPLE_RATE, default=16000): cv.int_range(min=1), - cv.Optional(CONF_BITS_PER_SAMPLE, default="32bit"): cv.All( - _validate_bits, cv.enum(BITS_PER_SAMPLE) - ), - cv.Optional(CONF_USE_APLL, default=False): cv.boolean, - cv.Optional(CONF_I2S_MODE, default=CONF_PRIMARY): cv.enum( - I2S_MODE_OPTIONS, lower=True - ), - } + i2s_audio_component_schema(I2SAudioMicrophone, 16000, CONF_RIGHT, "32bit") ).extend(cv.COMPONENT_SCHEMA) CONFIG_SCHEMA = cv.All( @@ -89,6 +60,7 @@ CONFIG_SCHEMA = cv.All( { cv.Required(CONF_I2S_DIN_PIN): pins.internal_gpio_input_pin_number, cv.Required(CONF_PDM): cv.boolean, + cv.Optional(CONF_USE_APLL, default=False): cv.boolean, } ), }, @@ -101,8 +73,8 @@ CONFIG_SCHEMA = cv.All( async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) - - await cg.register_parented(var, config[CONF_I2S_AUDIO_ID]) + await register_i2s_audio_component(var, config) + await microphone.register_microphone(var, config) if config[CONF_ADC_TYPE] == "internal": variant = esp32.get_esp32_variant() @@ -112,11 +84,4 @@ async def to_code(config): else: cg.add(var.set_din_pin(config[CONF_I2S_DIN_PIN])) cg.add(var.set_pdm(config[CONF_PDM])) - - cg.add(var.set_i2s_mode(config[CONF_I2S_MODE])) - cg.add(var.set_channel(config[CONF_CHANNEL])) - cg.add(var.set_sample_rate(config[CONF_SAMPLE_RATE])) - cg.add(var.set_bits_per_sample(config[CONF_BITS_PER_SAMPLE])) - cg.add(var.set_use_apll(config[CONF_USE_APLL])) - - await microphone.register_microphone(var, config) + cg.add(var.set_use_apll(config[CONF_USE_APLL])) diff --git a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.h b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.h index 07ca0528aa..56fb4c252a 100644 --- a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.h +++ b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.h @@ -30,11 +30,6 @@ class I2SAudioMicrophone : public I2SAudioIn, public microphone::Microphone, pub } #endif - 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_sample_rate(uint32_t sample_rate) { this->sample_rate_ = sample_rate; } - void set_bits_per_sample(i2s_bits_per_sample_t bits_per_sample) { this->bits_per_sample_ = bits_per_sample; } void set_use_apll(uint32_t use_apll) { this->use_apll_ = use_apll; } protected: @@ -48,10 +43,7 @@ class I2SAudioMicrophone : public I2SAudioIn, public microphone::Microphone, pub bool adc_{false}; #endif bool pdm_{false}; - i2s_mode_t i2s_mode_{}; - i2s_channel_fmt_t channel_; - uint32_t sample_rate_; - i2s_bits_per_sample_t bits_per_sample_; + bool use_apll_; HighFrequencyLoopRequester high_freq_; diff --git a/esphome/components/i2s_audio/speaker/__init__.py b/esphome/components/i2s_audio/speaker/__init__.py index 72455af1b7..11fdae0436 100644 --- a/esphome/components/i2s_audio/speaker/__init__.py +++ b/esphome/components/i2s_audio/speaker/__init__.py @@ -1,15 +1,18 @@ -import esphome.codegen as cg -import esphome.config_validation as cv from esphome import pins -from esphome.const import CONF_ID, CONF_MODE +import esphome.codegen as cg from esphome.components import esp32, speaker +import esphome.config_validation as cv +from esphome.const import CONF_CHANNEL, CONF_ID from .. import ( - CONF_I2S_AUDIO_ID, CONF_I2S_DOUT_PIN, - I2SAudioComponent, + CONF_LEFT, + CONF_RIGHT, + CONF_STEREO, I2SAudioOut, + i2s_audio_component_schema, i2s_audio_ns, + register_i2s_audio_component, ) CODEOWNERS = ["@jesserockz"] @@ -19,18 +22,16 @@ I2SAudioSpeaker = i2s_audio_ns.class_( "I2SAudioSpeaker", cg.Component, speaker.Speaker, I2SAudioOut ) -i2s_dac_mode_t = cg.global_ns.enum("i2s_dac_mode_t") -CONF_MUTE_PIN = "mute_pin" CONF_DAC_TYPE = "dac_type" +i2s_dac_mode_t = cg.global_ns.enum("i2s_dac_mode_t") INTERNAL_DAC_OPTIONS = { - "left": i2s_dac_mode_t.I2S_DAC_CHANNEL_LEFT_EN, - "right": i2s_dac_mode_t.I2S_DAC_CHANNEL_RIGHT_EN, - "stereo": i2s_dac_mode_t.I2S_DAC_CHANNEL_BOTH_EN, + 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 = ["mono", "stereo"] NO_INTERNAL_DAC_VARIANTS = [esp32.const.VARIANT_ESP32S2] @@ -44,28 +45,21 @@ def validate_esp32_variant(config): return config +BASE_SCHEMA = speaker.SPEAKER_SCHEMA.extend( + i2s_audio_component_schema(I2SAudioSpeaker, 16000, "stereo", "16bit") +).extend(cv.COMPONENT_SCHEMA) + CONFIG_SCHEMA = cv.All( cv.typed_schema( { - "internal": speaker.SPEAKER_SCHEMA.extend( + "internal": BASE_SCHEMA, + "external": BASE_SCHEMA.extend( { - cv.GenerateID(): cv.declare_id(I2SAudioSpeaker), - 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": speaker.SPEAKER_SCHEMA.extend( - { - cv.GenerateID(): cv.declare_id(I2SAudioSpeaker), - 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_MODE, default="mono"): cv.one_of( - *EXTERNAL_DAC_OPTIONS, lower=True - ), } - ).extend(cv.COMPONENT_SCHEMA), + ), }, key=CONF_DAC_TYPE, ), @@ -76,12 +70,10 @@ CONFIG_SCHEMA = cv.All( async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) + await register_i2s_audio_component(var, config) await speaker.register_speaker(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])) + cg.add(var.set_internal_dac_mode(config[CONF_CHANNEL])) else: cg.add(var.set_dout_pin(config[CONF_I2S_DOUT_PIN])) - cg.add(var.set_external_dac_channels(2 if config[CONF_MODE] == "stereo" else 1)) diff --git a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp index cf5a2c2766..ab26edd8cf 100644 --- a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +++ b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp @@ -64,17 +64,17 @@ void I2SAudioSpeaker::player_task(void *params) { xQueueSend(this_speaker->event_queue_, &event, portMAX_DELAY); i2s_driver_config_t config = { - .mode = (i2s_mode_t) (I2S_MODE_MASTER | I2S_MODE_TX), - .sample_rate = 16000, - .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, - .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, + .mode = (i2s_mode_t) (this_speaker->i2s_mode_ | I2S_MODE_TX), + .sample_rate = this_speaker->sample_rate_, + .bits_per_sample = this_speaker->bits_per_sample_, + .channel_format = this_speaker->channel_, .communication_format = I2S_COMM_FORMAT_STAND_I2S, .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, .dma_buf_count = 8, .dma_buf_len = 128, .use_apll = false, .tx_desc_auto_clear = true, - .fixed_mclk = I2S_PIN_NO_CHANGE, + .fixed_mclk = 0, .mclk_multiple = I2S_MCLK_MULTIPLE_256, .bits_per_chan = I2S_BITS_PER_CHAN_DEFAULT, }; diff --git a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h index 0bdb67ceba..8d602e1ead 100644 --- a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +++ b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h @@ -38,7 +38,7 @@ struct DataEvent { uint8_t data[BUFFER_SIZE]; }; -class I2SAudioSpeaker : public Component, public speaker::Speaker, public I2SAudioOut { +class I2SAudioSpeaker : public I2SAudioOut, public speaker::Speaker, public Component { public: float get_setup_priority() const override { return esphome::setup_priority::LATE; } @@ -49,7 +49,6 @@ class I2SAudioSpeaker : public Component, public speaker::Speaker, public I2SAud #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 start() override; void stop() override; @@ -76,7 +75,6 @@ class I2SAudioSpeaker : public Component, public speaker::Speaker, public I2SAud #if SOC_I2S_SUPPORTS_DAC i2s_dac_mode_t internal_dac_mode_{I2S_DAC_CHANNEL_DISABLE}; #endif - uint8_t external_dac_channels_; }; } // namespace i2s_audio From dbecade12215d3db7362c2f003c12177561cfd02 Mon Sep 17 00:00:00 2001 From: ArkanStasarik <103874616+ArkanStasarik@users.noreply.github.com> Date: Wed, 11 Sep 2024 12:53:09 +0800 Subject: [PATCH 2068/2101] Implement all supported thermocouple types for MAX31856 (#7218) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> --- esphome/components/max31856/max31856.cpp | 13 +++++++++++- esphome/components/max31856/max31856.h | 7 +++++-- esphome/components/max31856/sensor.py | 20 +++++++++++++++++++ esphome/components/mcp9600/sensor.py | 4 ++-- esphome/const.py | 1 + tests/components/max31856/test.esp32-ard.yaml | 1 + .../max31856/test.esp32-c3-ard.yaml | 2 ++ .../max31856/test.esp32-c3-idf.yaml | 2 ++ tests/components/max31856/test.esp32-idf.yaml | 1 + .../components/max31856/test.esp8266-ard.yaml | 2 ++ .../components/max31856/test.rp2040-ard.yaml | 2 ++ 11 files changed, 50 insertions(+), 5 deletions(-) diff --git a/esphome/components/max31856/max31856.cpp b/esphome/components/max31856/max31856.cpp index 8ae4be6657..6a4d34b430 100644 --- a/esphome/components/max31856/max31856.cpp +++ b/esphome/components/max31856/max31856.cpp @@ -32,6 +32,12 @@ void MAX31856Sensor::dump_config() { LOG_PIN(" CS Pin: ", this->cs_); ESP_LOGCONFIG(TAG, " Mains Filter: %s", (filter_ == FILTER_60HZ ? "60 Hz" : (filter_ == FILTER_50HZ ? "50 Hz" : "Unknown!"))); + if (this->thermocouple_type_ < 0 || this->thermocouple_type_ > 7) { + ESP_LOGCONFIG(TAG, " Thermocouple Type: Unknown"); + } else { + ESP_LOGCONFIG(TAG, " Thermocouple Type: %c", "BEJKNRST"[this->thermocouple_type_]); + } + LOG_UPDATE_INTERVAL(this); } @@ -129,7 +135,12 @@ void MAX31856Sensor::clear_fault_() { } void MAX31856Sensor::set_thermocouple_type_() { - MAX31856ThermocoupleType type = MAX31856_TCTYPE_K; + MAX31856ThermocoupleType type; + if (this->thermocouple_type_ < 0 || this->thermocouple_type_ > 7) { + type = MAX31856_TCTYPE_K; + } else { + type = this->thermocouple_type_; + } ESP_LOGCONFIG(TAG, "set_thermocouple_type_: 0x%02X", type); uint8_t t = this->read_register_(MAX31856_CR1_REG); t &= 0xF0; // mask off bottom 4 bits diff --git a/esphome/components/max31856/max31856.h b/esphome/components/max31856/max31856.h index 4deb6bc855..8d64cfe8bc 100644 --- a/esphome/components/max31856/max31856.h +++ b/esphome/components/max31856/max31856.h @@ -50,7 +50,6 @@ enum MAX31856Registers { /** * Multiple types of thermocouples supported by the chip. - * Currently only K type implemented here. */ enum MAX31856ThermocoupleType { MAX31856_TCTYPE_B = 0b0000, // 0x00 @@ -78,11 +77,15 @@ class MAX31856Sensor : public sensor::Sensor, void setup() override; void dump_config() override; float get_setup_priority() const override; - void set_filter(MAX31856ConfigFilter filter) { filter_ = filter; } + void set_filter(MAX31856ConfigFilter filter) { this->filter_ = filter; } + void set_thermocouple_type(MAX31856ThermocoupleType thermocouple_type) { + this->thermocouple_type_ = thermocouple_type; + } void update() override; protected: MAX31856ConfigFilter filter_; + MAX31856ThermocoupleType thermocouple_type_; uint8_t read_register_(uint8_t reg); uint32_t read_register24_(uint8_t reg); diff --git a/esphome/components/max31856/sensor.py b/esphome/components/max31856/sensor.py index bf9741aeed..679e02b11d 100644 --- a/esphome/components/max31856/sensor.py +++ b/esphome/components/max31856/sensor.py @@ -3,6 +3,7 @@ from esphome.components import sensor, spi import esphome.config_validation as cv from esphome.const import ( CONF_MAINS_FILTER, + CONF_THERMOCOUPLE_TYPE, DEVICE_CLASS_TEMPERATURE, STATE_CLASS_MEASUREMENT, UNIT_CELSIUS, @@ -18,6 +19,17 @@ FILTER = { 50: MAX31865ConfigFilter.FILTER_50HZ, 60: MAX31865ConfigFilter.FILTER_60HZ, } +MAX31856ThermocoupleType = max31856_ns.enum("MAX31856ThermocoupleType") +THERMOCOUPLE_TYPE = { + "B": MAX31856ThermocoupleType.MAX31856_TCTYPE_B, + "E": MAX31856ThermocoupleType.MAX31856_TCTYPE_E, + "J": MAX31856ThermocoupleType.MAX31856_TCTYPE_J, + "K": MAX31856ThermocoupleType.MAX31856_TCTYPE_K, + "N": MAX31856ThermocoupleType.MAX31856_TCTYPE_N, + "R": MAX31856ThermocoupleType.MAX31856_TCTYPE_R, + "S": MAX31856ThermocoupleType.MAX31856_TCTYPE_S, + "T": MAX31856ThermocoupleType.MAX31856_TCTYPE_T, +} CONFIG_SCHEMA = ( sensor.sensor_schema( @@ -34,6 +46,13 @@ CONFIG_SCHEMA = ( ), } ) + .extend( + { + cv.Optional(CONF_THERMOCOUPLE_TYPE, default="K"): cv.enum( + THERMOCOUPLE_TYPE, upper=True, space="" + ), + } + ) .extend(cv.polling_component_schema("60s")) .extend(spi.spi_device_schema()) ) @@ -44,3 +63,4 @@ async def to_code(config): await cg.register_component(var, config) await spi.register_spi_device(var, config) cg.add(var.set_filter(config[CONF_MAINS_FILTER])) + cg.add(var.set_thermocouple_type(config[CONF_THERMOCOUPLE_TYPE])) diff --git a/esphome/components/mcp9600/sensor.py b/esphome/components/mcp9600/sensor.py index 8557c7205e..65ae5f2eec 100644 --- a/esphome/components/mcp9600/sensor.py +++ b/esphome/components/mcp9600/sensor.py @@ -1,14 +1,14 @@ import esphome.codegen as cg -import esphome.config_validation as cv from esphome.components import i2c, sensor +import esphome.config_validation as cv from esphome.const import ( CONF_ID, + CONF_THERMOCOUPLE_TYPE, DEVICE_CLASS_TEMPERATURE, STATE_CLASS_MEASUREMENT, UNIT_CELSIUS, ) -CONF_THERMOCOUPLE_TYPE = "thermocouple_type" CONF_HOT_JUNCTION = "hot_junction" CONF_COLD_JUNCTION = "cold_junction" diff --git a/esphome/const.py b/esphome/const.py index 169b11a715..7ad31f276f 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -852,6 +852,7 @@ CONF_TEMPERATURE_STEP = "temperature_step" CONF_TEXT = "text" CONF_TEXT_SENSORS = "text_sensors" CONF_THEN = "then" +CONF_THERMOCOUPLE_TYPE = "thermocouple_type" CONF_THRESHOLD = "threshold" CONF_THROTTLE = "throttle" CONF_TILT = "tilt" diff --git a/tests/components/max31856/test.esp32-ard.yaml b/tests/components/max31856/test.esp32-ard.yaml index 5561903207..9a4da6b2a2 100644 --- a/tests/components/max31856/test.esp32-ard.yaml +++ b/tests/components/max31856/test.esp32-ard.yaml @@ -10,3 +10,4 @@ sensor: cs_pin: 12 update_interval: 15s mains_filter: 50Hz + thermocouple_type: N diff --git a/tests/components/max31856/test.esp32-c3-ard.yaml b/tests/components/max31856/test.esp32-c3-ard.yaml index 2794866c59..71bbfffb7b 100644 --- a/tests/components/max31856/test.esp32-c3-ard.yaml +++ b/tests/components/max31856/test.esp32-c3-ard.yaml @@ -10,3 +10,5 @@ sensor: cs_pin: 8 update_interval: 15s mains_filter: 50Hz + thermocouple_type: N + diff --git a/tests/components/max31856/test.esp32-c3-idf.yaml b/tests/components/max31856/test.esp32-c3-idf.yaml index 2794866c59..71bbfffb7b 100644 --- a/tests/components/max31856/test.esp32-c3-idf.yaml +++ b/tests/components/max31856/test.esp32-c3-idf.yaml @@ -10,3 +10,5 @@ sensor: cs_pin: 8 update_interval: 15s mains_filter: 50Hz + thermocouple_type: N + diff --git a/tests/components/max31856/test.esp32-idf.yaml b/tests/components/max31856/test.esp32-idf.yaml index 5561903207..9a4da6b2a2 100644 --- a/tests/components/max31856/test.esp32-idf.yaml +++ b/tests/components/max31856/test.esp32-idf.yaml @@ -10,3 +10,4 @@ sensor: cs_pin: 12 update_interval: 15s mains_filter: 50Hz + thermocouple_type: N diff --git a/tests/components/max31856/test.esp8266-ard.yaml b/tests/components/max31856/test.esp8266-ard.yaml index dfd9572ca9..b9c42542fd 100644 --- a/tests/components/max31856/test.esp8266-ard.yaml +++ b/tests/components/max31856/test.esp8266-ard.yaml @@ -10,3 +10,5 @@ sensor: cs_pin: 15 update_interval: 15s mains_filter: 50Hz + thermocouple_type: N + diff --git a/tests/components/max31856/test.rp2040-ard.yaml b/tests/components/max31856/test.rp2040-ard.yaml index 0abc8a081b..8607eb18cf 100644 --- a/tests/components/max31856/test.rp2040-ard.yaml +++ b/tests/components/max31856/test.rp2040-ard.yaml @@ -10,3 +10,5 @@ sensor: cs_pin: 6 update_interval: 15s mains_filter: 50Hz + thermocouple_type: N + From 04248b6840211a9752e74252400230b68620a87a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=5Bp=CA=B2=C9=B5s=5D?= Date: Wed, 11 Sep 2024 07:12:20 +0200 Subject: [PATCH 2069/2101] [i2s_audio] Add more options to speakers and microphones (#7306) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/i2s_audio/__init__.py | 24 +++++- esphome/components/i2s_audio/i2s_audio.h | 4 + .../i2s_audio/media_player/__init__.py | 12 ++- .../media_player/i2s_audio_media_player.h | 2 +- .../i2s_audio/microphone/__init__.py | 19 +++-- .../microphone/i2s_audio_microphone.cpp | 33 ++++---- .../microphone/i2s_audio_microphone.h | 4 - .../components/i2s_audio/speaker/__init__.py | 32 ++++++-- .../i2s_audio/speaker/i2s_audio_speaker.cpp | 76 +++++++++++-------- .../i2s_audio/speaker/i2s_audio_speaker.h | 3 +- tests/components/speaker/test.esp32-ard.yaml | 1 - .../components/speaker/test.esp32-c3-ard.yaml | 1 - .../components/speaker/test.esp32-c3-idf.yaml | 1 - tests/components/speaker/test.esp32-idf.yaml | 1 - .../voice_assistant/test.esp32-ard.yaml | 1 - .../voice_assistant/test.esp32-c3-ard.yaml | 1 - .../voice_assistant/test.esp32-c3-idf.yaml | 1 - .../voice_assistant/test.esp32-idf.yaml | 1 - 18 files changed, 136 insertions(+), 81 deletions(-) diff --git a/esphome/components/i2s_audio/__init__.py b/esphome/components/i2s_audio/__init__.py index 90dc8a24ee..d376907925 100644 --- a/esphome/components/i2s_audio/__init__.py +++ b/esphome/components/i2s_audio/__init__.py @@ -30,6 +30,10 @@ CONF_I2S_MODE = "i2s_mode" CONF_PRIMARY = "primary" CONF_SECONDARY = "secondary" +CONF_USE_APLL = "use_apll" +CONF_BITS_PER_SAMPLE = "bits_per_sample" +CONF_BITS_PER_CHANNEL = "bits_per_channel" +CONF_MONO = "mono" CONF_LEFT = "left" CONF_RIGHT = "right" CONF_STEREO = "stereo" @@ -58,6 +62,7 @@ I2S_PORTS = { i2s_channel_fmt_t = cg.global_ns.enum("i2s_channel_fmt_t") I2S_CHANNELS = { + CONF_MONO: i2s_channel_fmt_t.I2S_CHANNEL_FMT_ALL_LEFT, CONF_LEFT: i2s_channel_fmt_t.I2S_CHANNEL_FMT_ONLY_LEFT, CONF_RIGHT: i2s_channel_fmt_t.I2S_CHANNEL_FMT_ONLY_RIGHT, CONF_STEREO: i2s_channel_fmt_t.I2S_CHANNEL_FMT_RIGHT_LEFT, @@ -67,17 +72,25 @@ i2s_bits_per_sample_t = cg.global_ns.enum("i2s_bits_per_sample_t") I2S_BITS_PER_SAMPLE = { 8: i2s_bits_per_sample_t.I2S_BITS_PER_SAMPLE_8BIT, 16: i2s_bits_per_sample_t.I2S_BITS_PER_SAMPLE_16BIT, + 24: i2s_bits_per_sample_t.I2S_BITS_PER_SAMPLE_24BIT, 32: i2s_bits_per_sample_t.I2S_BITS_PER_SAMPLE_32BIT, } -INTERNAL_ADC_VARIANTS = [VARIANT_ESP32] -PDM_VARIANTS = [VARIANT_ESP32, VARIANT_ESP32S3] +i2s_bits_per_chan_t = cg.global_ns.enum("i2s_bits_per_chan_t") +I2S_BITS_PER_CHANNEL = { + "default": i2s_bits_per_chan_t.I2S_BITS_PER_CHAN_DEFAULT, + 8: i2s_bits_per_chan_t.I2S_BITS_PER_CHAN_8BIT, + 16: i2s_bits_per_chan_t.I2S_BITS_PER_CHAN_16BIT, + 24: i2s_bits_per_chan_t.I2S_BITS_PER_CHAN_24BIT, + 32: i2s_bits_per_chan_t.I2S_BITS_PER_CHAN_32BIT, +} _validate_bits = cv.float_with_unit("bits", "bit") def i2s_audio_component_schema( class_: MockObjClass, + *, default_sample_rate: int, default_channel: str, default_bits_per_sample: str, @@ -96,6 +109,11 @@ def i2s_audio_component_schema( cv.Optional(CONF_I2S_MODE, default=CONF_PRIMARY): cv.enum( 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.enum(I2S_BITS_PER_CHANNEL), + ), } ) @@ -107,6 +125,8 @@ async def register_i2s_audio_component(var, config): cg.add(var.set_channel(config[CONF_CHANNEL])) cg.add(var.set_sample_rate(config[CONF_SAMPLE_RATE])) cg.add(var.set_bits_per_sample(config[CONF_BITS_PER_SAMPLE])) + cg.add(var.set_bits_per_channel(config[CONF_BITS_PER_CHANNEL])) + cg.add(var.set_use_apll(config[CONF_USE_APLL])) CONFIG_SCHEMA = cv.Schema( diff --git a/esphome/components/i2s_audio/i2s_audio.h b/esphome/components/i2s_audio/i2s_audio.h index 727fb6c4e1..7e2798c33d 100644 --- a/esphome/components/i2s_audio/i2s_audio.h +++ b/esphome/components/i2s_audio/i2s_audio.h @@ -17,12 +17,16 @@ class I2SAudioBase : public Parented { void set_channel(i2s_channel_fmt_t channel) { this->channel_ = channel; } void set_sample_rate(uint32_t sample_rate) { this->sample_rate_ = sample_rate; } 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; } + void set_use_apll(uint32_t use_apll) { this->use_apll_ = use_apll; } protected: i2s_mode_t i2s_mode_{}; i2s_channel_fmt_t channel_; uint32_t sample_rate_; i2s_bits_per_sample_t bits_per_sample_; + i2s_bits_per_chan_t bits_per_channel_; + bool use_apll_; }; class I2SAudioIn : public I2SAudioBase {}; diff --git a/esphome/components/i2s_audio/media_player/__init__.py b/esphome/components/i2s_audio/media_player/__init__.py index 600a308e6c..dfa69ecadd 100644 --- a/esphome/components/i2s_audio/media_player/__init__.py +++ b/esphome/components/i2s_audio/media_player/__init__.py @@ -12,6 +12,10 @@ from .. import ( I2SAudioOut, CONF_I2S_AUDIO_ID, CONF_I2S_DOUT_PIN, + CONF_LEFT, + CONF_RIGHT, + CONF_MONO, + CONF_STEREO, ) CODEOWNERS = ["@jesserockz"] @@ -30,12 +34,12 @@ CONF_DAC_TYPE = "dac_type" CONF_I2S_COMM_FMT = "i2s_comm_fmt" INTERNAL_DAC_OPTIONS = { - "left": i2s_dac_mode_t.I2S_DAC_CHANNEL_LEFT_EN, - "right": i2s_dac_mode_t.I2S_DAC_CHANNEL_RIGHT_EN, - "stereo": i2s_dac_mode_t.I2S_DAC_CHANNEL_BOTH_EN, + 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 = ["mono", "stereo"] +EXTERNAL_DAC_OPTIONS = [CONF_MONO, CONF_STEREO] NO_INTERNAL_DAC_VARIANTS = [esp32.const.VARIANT_ESP32S2] diff --git a/esphome/components/i2s_audio/media_player/i2s_audio_media_player.h b/esphome/components/i2s_audio/media_player/i2s_audio_media_player.h index 5afe778122..4672f94d7e 100644 --- a/esphome/components/i2s_audio/media_player/i2s_audio_media_player.h +++ b/esphome/components/i2s_audio/media_player/i2s_audio_media_player.h @@ -23,7 +23,7 @@ enum I2SState : uint8_t { I2S_STATE_STOPPING, }; -class I2SAudioMediaPlayer : public Component, public media_player::MediaPlayer, public I2SAudioOut { +class I2SAudioMediaPlayer : public Component, public Parented, public media_player::MediaPlayer { public: void setup() override; float get_setup_priority() const override { return esphome::setup_priority::LATE; } diff --git a/esphome/components/i2s_audio/microphone/__init__.py b/esphome/components/i2s_audio/microphone/__init__.py index e2ece03e68..161046e962 100644 --- a/esphome/components/i2s_audio/microphone/__init__.py +++ b/esphome/components/i2s_audio/microphone/__init__.py @@ -8,8 +8,6 @@ from esphome.const import CONF_ID, CONF_NUMBER from .. import ( CONF_I2S_DIN_PIN, CONF_RIGHT, - INTERNAL_ADC_VARIANTS, - PDM_VARIANTS, I2SAudioIn, i2s_audio_component_schema, i2s_audio_ns, @@ -23,12 +21,13 @@ CONF_ADC_PIN = "adc_pin" CONF_ADC_TYPE = "adc_type" CONF_PDM = "pdm" -CONF_USE_APLL = "use_apll" - I2SAudioMicrophone = i2s_audio_ns.class_( "I2SAudioMicrophone", I2SAudioIn, microphone.Microphone, cg.Component ) +INTERNAL_ADC_VARIANTS = [esp32.const.VARIANT_ESP32] +PDM_VARIANTS = [esp32.const.VARIANT_ESP32, esp32.const.VARIANT_ESP32S3] + def validate_esp32_variant(config): variant = esp32.get_esp32_variant() @@ -45,9 +44,15 @@ def validate_esp32_variant(config): BASE_SCHEMA = microphone.MICROPHONE_SCHEMA.extend( - i2s_audio_component_schema(I2SAudioMicrophone, 16000, CONF_RIGHT, "32bit") + i2s_audio_component_schema( + I2SAudioMicrophone, + default_sample_rate=16000, + default_channel=CONF_RIGHT, + default_bits_per_sample="32bit", + ) ).extend(cv.COMPONENT_SCHEMA) + CONFIG_SCHEMA = cv.All( cv.typed_schema( { @@ -59,8 +64,7 @@ CONFIG_SCHEMA = cv.All( "external": BASE_SCHEMA.extend( { cv.Required(CONF_I2S_DIN_PIN): pins.internal_gpio_input_pin_number, - cv.Required(CONF_PDM): cv.boolean, - cv.Optional(CONF_USE_APLL, default=False): cv.boolean, + cv.Optional(CONF_PDM, default=False): cv.boolean, } ), }, @@ -84,4 +88,3 @@ async def to_code(config): else: cg.add(var.set_din_pin(config[CONF_I2S_DIN_PIN])) cg.add(var.set_pdm(config[CONF_PDM])) - cg.add(var.set_use_apll(config[CONF_USE_APLL])) diff --git a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp index cb49a744fc..23689afb91 100644 --- a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +++ b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp @@ -58,7 +58,7 @@ void I2SAudioMicrophone::start_() { .tx_desc_auto_clear = false, .fixed_mclk = 0, .mclk_multiple = I2S_MCLK_MULTIPLE_256, - .bits_per_chan = I2S_BITS_PER_CHAN_DEFAULT, + .bits_per_chan = this->bits_per_channel_, }; esp_err_t err; @@ -167,21 +167,24 @@ size_t I2SAudioMicrophone::read(int16_t *buf, size_t len) { return 0; } this->status_clear_warning(); - if (this->bits_per_sample_ == I2S_BITS_PER_SAMPLE_16BIT) { - return bytes_read; - } else if (this->bits_per_sample_ == I2S_BITS_PER_SAMPLE_32BIT) { - std::vector samples; - size_t samples_read = bytes_read / sizeof(int32_t); - samples.resize(samples_read); - for (size_t i = 0; i < samples_read; i++) { - int32_t temp = reinterpret_cast(buf)[i] >> 14; - samples[i] = clamp(temp, INT16_MIN, INT16_MAX); + // ESP-IDF I2S implementation right-extends 8-bit data to 16 bits, + // and 24-bit data to 32 bits. + switch (this->bits_per_sample_) { + case I2S_BITS_PER_SAMPLE_8BIT: + case I2S_BITS_PER_SAMPLE_16BIT: + return bytes_read; + case I2S_BITS_PER_SAMPLE_24BIT: + case I2S_BITS_PER_SAMPLE_32BIT: { + size_t samples_read = bytes_read / sizeof(int32_t); + for (size_t i = 0; i < samples_read; i++) { + int32_t temp = reinterpret_cast(buf)[i] >> 14; + buf[i] = clamp(temp, INT16_MIN, INT16_MAX); + } + return samples_read * sizeof(int16_t); } - memcpy(buf, samples.data(), samples_read * sizeof(int16_t)); - return samples_read * sizeof(int16_t); - } else { - ESP_LOGE(TAG, "Unsupported bits per sample: %d", this->bits_per_sample_); - return 0; + default: + ESP_LOGE(TAG, "Unsupported bits per sample: %d", this->bits_per_sample_); + return 0; } } diff --git a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.h b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.h index 56fb4c252a..ea3f357624 100644 --- a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.h +++ b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.h @@ -30,8 +30,6 @@ class I2SAudioMicrophone : public I2SAudioIn, public microphone::Microphone, pub } #endif - void set_use_apll(uint32_t use_apll) { this->use_apll_ = use_apll; } - protected: void start_(); void stop_(); @@ -44,8 +42,6 @@ class I2SAudioMicrophone : public I2SAudioIn, public microphone::Microphone, pub #endif bool pdm_{false}; - bool use_apll_; - HighFrequencyLoopRequester high_freq_; }; diff --git a/esphome/components/i2s_audio/speaker/__init__.py b/esphome/components/i2s_audio/speaker/__init__.py index 11fdae0436..22a5af259d 100644 --- a/esphome/components/i2s_audio/speaker/__init__.py +++ b/esphome/components/i2s_audio/speaker/__init__.py @@ -2,11 +2,12 @@ from esphome import pins import esphome.codegen as cg from esphome.components import esp32, speaker import esphome.config_validation as cv -from esphome.const import CONF_CHANNEL, CONF_ID +from esphome.const import CONF_CHANNEL, CONF_ID, CONF_MODE, CONF_TIMEOUT from .. import ( CONF_I2S_DOUT_PIN, CONF_LEFT, + CONF_MONO, CONF_RIGHT, CONF_STEREO, I2SAudioOut, @@ -32,7 +33,6 @@ INTERNAL_DAC_OPTIONS = { CONF_STEREO: i2s_dac_mode_t.I2S_DAC_CHANNEL_BOTH_EN, } - NO_INTERNAL_DAC_VARIANTS = [esp32.const.VARIANT_ESP32S2] @@ -45,14 +45,33 @@ def validate_esp32_variant(config): return config -BASE_SCHEMA = speaker.SPEAKER_SCHEMA.extend( - i2s_audio_component_schema(I2SAudioSpeaker, 16000, "stereo", "16bit") -).extend(cv.COMPONENT_SCHEMA) +BASE_SCHEMA = ( + speaker.SPEAKER_SCHEMA.extend( + i2s_audio_component_schema( + I2SAudioSpeaker, + default_sample_rate=16000, + default_channel=CONF_MONO, + default_bits_per_sample="16bit", + ) + ) + .extend( + { + cv.Optional( + CONF_TIMEOUT, default="100ms" + ): cv.positive_time_period_milliseconds, + } + ) + .extend(cv.COMPONENT_SCHEMA) +) CONFIG_SCHEMA = cv.All( cv.typed_schema( { - "internal": BASE_SCHEMA, + "internal": BASE_SCHEMA.extend( + { + cv.Required(CONF_MODE): cv.enum(INTERNAL_DAC_OPTIONS, lower=True), + } + ), "external": BASE_SCHEMA.extend( { cv.Required( @@ -77,3 +96,4 @@ async def to_code(config): cg.add(var.set_internal_dac_mode(config[CONF_CHANNEL])) else: cg.add(var.set_dout_pin(config[CONF_I2S_DOUT_PIN])) + cg.add(var.set_timeout(config[CONF_TIMEOUT])) diff --git a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp index ab26edd8cf..4b427898a2 100644 --- a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +++ b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp @@ -56,6 +56,21 @@ void I2SAudioSpeaker::start_() { this->task_created_ = true; } +template const uint8_t *convert_data_format(const a *from, b *to, size_t &bytes, bool repeat) { + if (sizeof(a) == sizeof(b) && !repeat) { + return reinterpret_cast(from); + } + const b *result = to; + for (size_t i = 0; i < bytes; i += sizeof(a)) { + b value = static_cast(*from++) << (sizeof(b) - sizeof(a)) * 8; + *to++ = value; + if (repeat) + *to++ = value; + } + bytes *= (sizeof(b) / sizeof(a)) * (repeat ? 2 : 1); // NOLINT + return reinterpret_cast(result); +} + void I2SAudioSpeaker::player_task(void *params) { I2SAudioSpeaker *this_speaker = (I2SAudioSpeaker *) params; @@ -71,12 +86,12 @@ void I2SAudioSpeaker::player_task(void *params) { .communication_format = I2S_COMM_FORMAT_STAND_I2S, .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, .dma_buf_count = 8, - .dma_buf_len = 128, - .use_apll = false, + .dma_buf_len = 256, + .use_apll = this_speaker->use_apll_, .tx_desc_auto_clear = true, .fixed_mclk = 0, .mclk_multiple = I2S_MCLK_MULTIPLE_256, - .bits_per_chan = I2S_BITS_PER_CHAN_DEFAULT, + .bits_per_chan = this_speaker->bits_per_channel_, }; #if SOC_I2S_SUPPORTS_DAC if (this_speaker->internal_dac_mode_ != I2S_DAC_CHANNEL_DISABLE) { @@ -114,10 +129,11 @@ void I2SAudioSpeaker::player_task(void *params) { event.type = TaskEventType::STARTED; xQueueSend(this_speaker->event_queue_, &event, portMAX_DELAY); - int16_t buffer[BUFFER_SIZE / 2]; + int32_t buffer[BUFFER_SIZE]; while (true) { - if (xQueueReceive(this_speaker->buffer_queue_, &data_event, 100 / portTICK_PERIOD_MS) != pdTRUE) { + if (xQueueReceive(this_speaker->buffer_queue_, &data_event, this_speaker->timeout_ / portTICK_PERIOD_MS) != + pdTRUE) { break; // End of audio from main thread } if (data_event.stop) { @@ -125,17 +141,28 @@ void I2SAudioSpeaker::player_task(void *params) { xQueueReset(this_speaker->buffer_queue_); // Flush queue break; } - size_t bytes_written; - memmove(buffer, data_event.data, data_event.len); - size_t remaining = data_event.len / 2; - size_t current = 0; + const uint8_t *data = data_event.data; + size_t remaining = data_event.len; + switch (this_speaker->bits_per_sample_) { + case I2S_BITS_PER_SAMPLE_8BIT: + case I2S_BITS_PER_SAMPLE_16BIT: { + data = convert_data_format(reinterpret_cast(data), reinterpret_cast(buffer), + remaining, this_speaker->channel_ == I2S_CHANNEL_FMT_ALL_LEFT); + break; + } + case I2S_BITS_PER_SAMPLE_24BIT: + case I2S_BITS_PER_SAMPLE_32BIT: { + data = convert_data_format(reinterpret_cast(data), reinterpret_cast(buffer), + remaining, this_speaker->channel_ == I2S_CHANNEL_FMT_ALL_LEFT); + break; + } + } - while (remaining > 0) { - uint32_t sample = (buffer[current] << 16) | (buffer[current] & 0xFFFF); - - esp_err_t err = i2s_write(this_speaker->parent_->get_port(), &sample, sizeof(sample), &bytes_written, - (10 / portTICK_PERIOD_MS)); + while (remaining != 0) { + size_t bytes_written; + esp_err_t err = + i2s_write(this_speaker->parent_->get_port(), data, remaining, &bytes_written, (32 / portTICK_PERIOD_MS)); if (err != ESP_OK) { event = {.type = TaskEventType::WARNING, .err = err}; if (xQueueSend(this_speaker->event_queue_, &event, 10 / portTICK_PERIOD_MS) != pdTRUE) { @@ -143,21 +170,8 @@ void I2SAudioSpeaker::player_task(void *params) { } continue; } - if (bytes_written != sizeof(sample)) { - event = {.type = TaskEventType::WARNING, .err = ESP_FAIL}; - if (xQueueSend(this_speaker->event_queue_, &event, 10 / portTICK_PERIOD_MS) != pdTRUE) { - ESP_LOGW(TAG, "Failed to send WARNING event"); - } - continue; - } - remaining--; - current++; - } - - event.type = TaskEventType::PLAYING; - event.err = current; - if (xQueueSend(this_speaker->event_queue_, &event, 10 / portTICK_PERIOD_MS) != pdTRUE) { - ESP_LOGW(TAG, "Failed to send PLAYING event"); + data += bytes_written; + remaining -= bytes_written; } } @@ -213,13 +227,11 @@ void I2SAudioSpeaker::watch_() { case TaskEventType::STARTED: ESP_LOGD(TAG, "Started I2S Audio Speaker"); this->state_ = speaker::STATE_RUNNING; + this->status_clear_warning(); break; case TaskEventType::STOPPING: ESP_LOGD(TAG, "Stopping I2S Audio Speaker"); break; - case TaskEventType::PLAYING: - this->status_clear_warning(); - break; case TaskEventType::STOPPED: this->state_ = speaker::STATE_STOPPED; vTaskDelete(this->player_task_handle_); diff --git a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h index 8d602e1ead..7adc4e8a24 100644 --- a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +++ b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h @@ -21,7 +21,6 @@ static const size_t BUFFER_SIZE = 1024; enum class TaskEventType : uint8_t { STARTING = 0, STARTED, - PLAYING, STOPPING, STOPPED, WARNING = 255, @@ -45,6 +44,7 @@ class I2SAudioSpeaker : public I2SAudioOut, public speaker::Speaker, public Comp void setup() override; void loop() override; + void set_timeout(uint32_t ms) { this->timeout_ = ms; } void set_dout_pin(uint8_t pin) { this->dout_pin_ = pin; } #if SOC_I2S_SUPPORTS_DAC void set_internal_dac_mode(i2s_dac_mode_t mode) { this->internal_dac_mode_ = mode; } @@ -69,6 +69,7 @@ class I2SAudioSpeaker : public I2SAudioOut, public speaker::Speaker, public Comp QueueHandle_t buffer_queue_; QueueHandle_t event_queue_; + uint32_t timeout_{0}; uint8_t dout_pin_{0}; bool task_created_{false}; diff --git a/tests/components/speaker/test.esp32-ard.yaml b/tests/components/speaker/test.esp32-ard.yaml index e10c3e88c1..ab20f36eb6 100644 --- a/tests/components/speaker/test.esp32-ard.yaml +++ b/tests/components/speaker/test.esp32-ard.yaml @@ -21,4 +21,3 @@ speaker: id: speaker_id dac_type: external i2s_dout_pin: 13 - mode: mono diff --git a/tests/components/speaker/test.esp32-c3-ard.yaml b/tests/components/speaker/test.esp32-c3-ard.yaml index 08699d8b22..c966f9daa7 100644 --- a/tests/components/speaker/test.esp32-c3-ard.yaml +++ b/tests/components/speaker/test.esp32-c3-ard.yaml @@ -21,4 +21,3 @@ speaker: id: speaker_id dac_type: external i2s_dout_pin: 3 - mode: mono diff --git a/tests/components/speaker/test.esp32-c3-idf.yaml b/tests/components/speaker/test.esp32-c3-idf.yaml index 08699d8b22..c966f9daa7 100644 --- a/tests/components/speaker/test.esp32-c3-idf.yaml +++ b/tests/components/speaker/test.esp32-c3-idf.yaml @@ -21,4 +21,3 @@ speaker: id: speaker_id dac_type: external i2s_dout_pin: 3 - mode: mono diff --git a/tests/components/speaker/test.esp32-idf.yaml b/tests/components/speaker/test.esp32-idf.yaml index e10c3e88c1..ab20f36eb6 100644 --- a/tests/components/speaker/test.esp32-idf.yaml +++ b/tests/components/speaker/test.esp32-idf.yaml @@ -21,4 +21,3 @@ speaker: id: speaker_id dac_type: external i2s_dout_pin: 13 - mode: mono diff --git a/tests/components/voice_assistant/test.esp32-ard.yaml b/tests/components/voice_assistant/test.esp32-ard.yaml index 7f6fd85303..cbf9460087 100644 --- a/tests/components/voice_assistant/test.esp32-ard.yaml +++ b/tests/components/voice_assistant/test.esp32-ard.yaml @@ -28,7 +28,6 @@ speaker: id: speaker_id dac_type: external i2s_dout_pin: 12 - mode: mono voice_assistant: microphone: mic_id_external diff --git a/tests/components/voice_assistant/test.esp32-c3-ard.yaml b/tests/components/voice_assistant/test.esp32-c3-ard.yaml index 248ae4d0dc..86357fad36 100644 --- a/tests/components/voice_assistant/test.esp32-c3-ard.yaml +++ b/tests/components/voice_assistant/test.esp32-c3-ard.yaml @@ -28,7 +28,6 @@ speaker: id: speaker_id dac_type: external i2s_dout_pin: 2 - mode: mono voice_assistant: microphone: mic_id_external diff --git a/tests/components/voice_assistant/test.esp32-c3-idf.yaml b/tests/components/voice_assistant/test.esp32-c3-idf.yaml index 248ae4d0dc..86357fad36 100644 --- a/tests/components/voice_assistant/test.esp32-c3-idf.yaml +++ b/tests/components/voice_assistant/test.esp32-c3-idf.yaml @@ -28,7 +28,6 @@ speaker: id: speaker_id dac_type: external i2s_dout_pin: 2 - mode: mono voice_assistant: microphone: mic_id_external diff --git a/tests/components/voice_assistant/test.esp32-idf.yaml b/tests/components/voice_assistant/test.esp32-idf.yaml index 2e0209311d..da9b50721f 100644 --- a/tests/components/voice_assistant/test.esp32-idf.yaml +++ b/tests/components/voice_assistant/test.esp32-idf.yaml @@ -28,7 +28,6 @@ speaker: id: speaker_id dac_type: external i2s_dout_pin: 12 - mode: mono voice_assistant: microphone: mic_id_external From e3ae8cd31ec501541dbe5f93366ca0b6cac3d2e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Trevi=C3=B1o?= Date: Wed, 11 Sep 2024 07:16:52 +0200 Subject: [PATCH 2070/2101] [uponor_smatrix] Modifies sending algorithm (#7326) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Rafa Treviño --- esphome/components/uponor_smatrix/uponor_smatrix.cpp | 10 ++++------ esphome/components/uponor_smatrix/uponor_smatrix.h | 1 - 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/esphome/components/uponor_smatrix/uponor_smatrix.cpp b/esphome/components/uponor_smatrix/uponor_smatrix.cpp index a7014dc96c..e058de2852 100644 --- a/esphome/components/uponor_smatrix/uponor_smatrix.cpp +++ b/esphome/components/uponor_smatrix/uponor_smatrix.cpp @@ -45,11 +45,8 @@ void UponorSmatrixComponent::loop() { // Read incoming data while (this->available()) { - // The controller polls devices every 10 seconds, with around 200 ms between devices. - // Remember timestamps so we can send our own packets when the bus is expected to be silent. - if (now - this->last_rx_ > 500) { - this->last_poll_start_ = now; - } + // The controller polls devices every 10 seconds in some units or continuously in others with around 200 ms between + // devices. Remember timestamps so we can send our own packets when the bus is expected to be silent. this->last_rx_ = now; uint8_t byte; @@ -60,7 +57,8 @@ void UponorSmatrixComponent::loop() { } // Send packets during bus silence - if ((now - this->last_rx_ > 300) && (now - this->last_poll_start_ < 9500) && (now - this->last_tx_ > 200)) { + if (this->rx_buffer_.empty() && (now - this->last_rx_ > 50) && (now - this->last_rx_ < 100) && + (now - this->last_tx_ > 200)) { #ifdef USE_TIME // Only build time packet when bus is silent and queue is empty to make sure we can send it right away if (this->send_time_requested_ && this->tx_queue_.empty() && this->do_send_time_()) diff --git a/esphome/components/uponor_smatrix/uponor_smatrix.h b/esphome/components/uponor_smatrix/uponor_smatrix.h index b7667b5b87..e3e19a12fc 100644 --- a/esphome/components/uponor_smatrix/uponor_smatrix.h +++ b/esphome/components/uponor_smatrix/uponor_smatrix.h @@ -93,7 +93,6 @@ class UponorSmatrixComponent : public uart::UARTDevice, public Component { std::queue> tx_queue_; uint32_t last_rx_; uint32_t last_tx_; - uint32_t last_poll_start_; #ifdef USE_TIME time::RealTimeClock *time_id_{nullptr}; From 955a909846c45d93fa49e91079683a9eef053cdd Mon Sep 17 00:00:00 2001 From: ajwahab <1449672+ajwahab@users.noreply.github.com> Date: Wed, 11 Sep 2024 01:20:30 -0400 Subject: [PATCH 2071/2101] User configurable frame buffer. (#7360) --- esphome/components/esp32_camera/__init__.py | 4 ++++ esphome/components/esp32_camera/esp32_camera.cpp | 10 +++++++++- esphome/components/esp32_camera/esp32_camera.h | 3 +++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/esphome/components/esp32_camera/__init__.py b/esphome/components/esp32_camera/__init__.py index 4187429412..2f1f9b90bb 100644 --- a/esphome/components/esp32_camera/__init__.py +++ b/esphome/components/esp32_camera/__init__.py @@ -140,6 +140,8 @@ CONF_TEST_PATTERN = "test_pattern" # framerates CONF_MAX_FRAMERATE = "max_framerate" CONF_IDLE_FRAMERATE = "idle_framerate" +# frame buffer +CONF_FRAME_BUFFER_COUNT = "frame_buffer_count" # stream trigger CONF_ON_STREAM_START = "on_stream_start" @@ -213,6 +215,7 @@ CONFIG_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend( cv.Optional(CONF_IDLE_FRAMERATE, default="0.1 fps"): cv.All( cv.framerate, cv.Range(min=0, max=1) ), + cv.Optional(CONF_FRAME_BUFFER_COUNT, default=1): cv.int_range(min=1, max=2), cv.Optional(CONF_ON_STREAM_START): automation.validate_automation( { cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( @@ -285,6 +288,7 @@ async def to_code(config): cg.add(var.set_idle_update_interval(0)) else: cg.add(var.set_idle_update_interval(1000 / config[CONF_IDLE_FRAMERATE])) + cg.add(var.set_frame_buffer_count(config[CONF_FRAME_BUFFER_COUNT])) cg.add(var.set_frame_size(config[CONF_RESOLUTION])) cg.add_define("USE_ESP32_CAMERA") diff --git a/esphome/components/esp32_camera/esp32_camera.cpp b/esphome/components/esp32_camera/esp32_camera.cpp index 555f6ca5f1..e9e9d3cffb 100644 --- a/esphome/components/esp32_camera/esp32_camera.cpp +++ b/esphome/components/esp32_camera/esp32_camera.cpp @@ -127,7 +127,7 @@ void ESP32Camera::dump_config() { sensor_t *s = esp_camera_sensor_get(); auto st = s->status; ESP_LOGCONFIG(TAG, " JPEG Quality: %u", st.quality); - // ESP_LOGCONFIG(TAG, " Framebuffer Count: %u", conf.fb_count); + ESP_LOGCONFIG(TAG, " Framebuffer Count: %u", conf.fb_count); ESP_LOGCONFIG(TAG, " Contrast: %d", st.contrast); ESP_LOGCONFIG(TAG, " Brightness: %d", st.brightness); ESP_LOGCONFIG(TAG, " Saturation: %d", st.saturation); @@ -212,6 +212,8 @@ ESP32Camera::ESP32Camera() { this->config_.frame_size = FRAMESIZE_VGA; // 640x480 this->config_.jpeg_quality = 10; this->config_.fb_count = 1; + this->config_.grab_mode = CAMERA_GRAB_WHEN_EMPTY; + this->config_.fb_location = CAMERA_FB_IN_PSRAM; global_esp32_camera = this; } @@ -333,6 +335,12 @@ void ESP32Camera::set_max_update_interval(uint32_t max_update_interval) { void ESP32Camera::set_idle_update_interval(uint32_t idle_update_interval) { this->idle_update_interval_ = idle_update_interval; } +/* set frame buffer parameters */ +void ESP32Camera::set_frame_buffer_mode(camera_grab_mode_t mode) { this->config_.grab_mode = mode; } +void ESP32Camera::set_frame_buffer_count(uint8_t fb_count) { + this->config_.fb_count = fb_count; + this->set_frame_buffer_mode(fb_count > 1 ? CAMERA_GRAB_LATEST : CAMERA_GRAB_WHEN_EMPTY); +} /* ---------------- public API (specific) ---------------- */ void ESP32Camera::add_image_callback(std::function)> &&callback) { diff --git a/esphome/components/esp32_camera/esp32_camera.h b/esphome/components/esp32_camera/esp32_camera.h index 0c25381039..71f47d3c06 100644 --- a/esphome/components/esp32_camera/esp32_camera.h +++ b/esphome/components/esp32_camera/esp32_camera.h @@ -145,6 +145,9 @@ class ESP32Camera : public Component, public EntityBase { /* -- framerates */ void set_max_update_interval(uint32_t max_update_interval); void set_idle_update_interval(uint32_t idle_update_interval); + /* -- frame buffer */ + void set_frame_buffer_mode(camera_grab_mode_t mode); + void set_frame_buffer_count(uint8_t fb_count); /* public API (derivated) */ void setup() override; From 625726c65074530e06b74c31254db700956bc23b Mon Sep 17 00:00:00 2001 From: Tercio Filho Date: Wed, 11 Sep 2024 02:21:31 -0300 Subject: [PATCH 2072/2101] [Modbus Controller] Added preference to change command retries (#7312) Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- .../components/modbus_controller/__init__.py | 3 ++ esphome/components/modbus_controller/const.py | 1 + .../modbus_controller/modbus_controller.cpp | 37 ++++++++++--------- .../modbus_controller/modbus_controller.h | 18 +++++++-- .../modbus_controller/test.esp32-ard.yaml | 1 + .../modbus_controller/test.esp32-idf.yaml | 1 + 6 files changed, 39 insertions(+), 22 deletions(-) diff --git a/esphome/components/modbus_controller/__init__.py b/esphome/components/modbus_controller/__init__.py index 8146124c28..6917807b07 100644 --- a/esphome/components/modbus_controller/__init__.py +++ b/esphome/components/modbus_controller/__init__.py @@ -21,6 +21,7 @@ from .const import ( CONF_CUSTOM_COMMAND, CONF_FORCE_NEW_RANGE, CONF_MODBUS_CONTROLLER_ID, + CONF_MAX_CMD_RETRIES, CONF_ON_COMMAND_SENT, CONF_REGISTER_COUNT, CONF_REGISTER_TYPE, @@ -131,6 +132,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional( CONF_COMMAND_THROTTLE, default="0ms" ): cv.positive_time_period_milliseconds, + cv.Optional(CONF_MAX_CMD_RETRIES, default=4): cv.positive_int, cv.Optional(CONF_OFFLINE_SKIP_UPDATES, default=0): cv.positive_int, cv.Optional( CONF_SERVER_REGISTERS, @@ -257,6 +259,7 @@ async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) cg.add(var.set_allow_duplicate_commands(config[CONF_ALLOW_DUPLICATE_COMMANDS])) cg.add(var.set_command_throttle(config[CONF_COMMAND_THROTTLE])) + cg.add(var.set_max_cmd_retries(config[CONF_MAX_CMD_RETRIES])) cg.add(var.set_offline_skip_updates(config[CONF_OFFLINE_SKIP_UPDATES])) if CONF_SERVER_REGISTERS in config: for server_register in config[CONF_SERVER_REGISTERS]: diff --git a/esphome/components/modbus_controller/const.py b/esphome/components/modbus_controller/const.py index 5d9a61dee7..5cf7d230f1 100644 --- a/esphome/components/modbus_controller/const.py +++ b/esphome/components/modbus_controller/const.py @@ -5,6 +5,7 @@ CONF_COMMAND_THROTTLE = "command_throttle" CONF_OFFLINE_SKIP_UPDATES = "offline_skip_updates" CONF_CUSTOM_COMMAND = "custom_command" CONF_FORCE_NEW_RANGE = "force_new_range" +CONF_MAX_CMD_RETRIES = "max_cmd_retries" CONF_MODBUS_CONTROLLER_ID = "modbus_controller_id" CONF_MODBUS_FUNCTIONCODE = "modbus_functioncode" CONF_ON_COMMAND_SENT = "on_command_sent" diff --git a/esphome/components/modbus_controller/modbus_controller.cpp b/esphome/components/modbus_controller/modbus_controller.cpp index 8f48847a4f..1dcb533629 100644 --- a/esphome/components/modbus_controller/modbus_controller.cpp +++ b/esphome/components/modbus_controller/modbus_controller.cpp @@ -18,11 +18,11 @@ 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() && !command_queue_.empty()) { - auto &command = command_queue_.front(); + if ((last_send > this->command_throttle_) && !waiting_for_response() && !this->command_queue_.empty()) { + auto &command = this->command_queue_.front(); // remove from queue if command was sent too often - if (command->send_countdown < 1) { + if (!command->should_retry(this->max_cmd_retries_)) { if (!this->module_offline_) { ESP_LOGW(TAG, "Modbus device=%d set offline", this->address_); @@ -34,11 +34,9 @@ bool ModbusController::send_next_command_() { } } this->module_offline_ = true; - ESP_LOGD( - TAG, - "Modbus command to device=%d register=0x%02X countdown=%d no response received - removed from send queue", - this->address_, command->register_address, command->send_countdown); - command_queue_.pop_front(); + ESP_LOGD(TAG, "Modbus command to device=%d register=0x%02X no response received - removed from send queue", + this->address_, command->register_address); + this->command_queue_.pop_front(); } else { ESP_LOGV(TAG, "Sending next modbus command to device %d register 0x%02X count %d", this->address_, command->register_address, command->register_count); @@ -50,11 +48,11 @@ bool ModbusController::send_next_command_() { // remove from queue if no handler is defined if (!command->on_data_func) { - command_queue_.pop_front(); + this->command_queue_.pop_front(); } } } - return (!command_queue_.empty()); + return (!this->command_queue_.empty()); } // Queue incoming response @@ -77,7 +75,7 @@ void ModbusController::on_modbus_data(const std::vector &data) { current_command->payload = data; this->incoming_queue_.push(std::move(current_command)); ESP_LOGV(TAG, "Modbus response queued"); - command_queue_.pop_front(); + this->command_queue_.pop_front(); } } @@ -99,7 +97,7 @@ void ModbusController::on_modbus_error(uint8_t function_code, uint8_t exception_ "payload size=%zu", function_code, current_command->register_address, current_command->register_count, current_command->payload.size()); - command_queue_.pop_front(); + this->command_queue_.pop_front(); } } @@ -178,7 +176,7 @@ void ModbusController::queue_command(const ModbusCommandItem &command) { if (!this->allow_duplicate_commands_) { // check if this command is already qeued. // not very effective but the queue is never really large - for (auto &item : command_queue_) { + for (auto &item : this->command_queue_) { if (item->is_equal(command)) { ESP_LOGW(TAG, "Duplicate modbus command found: type=0x%x address=%u count=%u", static_cast(command.register_type), command.register_address, command.register_count); @@ -189,7 +187,7 @@ void ModbusController::queue_command(const ModbusCommandItem &command) { } } } - command_queue_.push_back(make_unique(command)); + this->command_queue_.push_back(make_unique(command)); } void ModbusController::update_range_(RegisterRange &r) { @@ -224,8 +222,8 @@ void ModbusController::update_range_(RegisterRange &r) { // Once we get a response to the command it is removed from the queue and the next command is send // void ModbusController::update() { - if (!command_queue_.empty()) { - ESP_LOGV(TAG, "%zu modbus commands already in queue", command_queue_.size()); + if (!this->command_queue_.empty()) { + ESP_LOGV(TAG, "%zu modbus commands already in queue", this->command_queue_.size()); } else { ESP_LOGV(TAG, "Updating modbus component"); } @@ -346,6 +344,8 @@ size_t ModbusController::create_register_ranges_() { void ModbusController::dump_config() { ESP_LOGCONFIG(TAG, "ModbusController:"); ESP_LOGCONFIG(TAG, " Address: 0x%02X", this->address_); + ESP_LOGCONFIG(TAG, " Max Command Retries: %d", this->max_cmd_retries_); + ESP_LOGCONFIG(TAG, " Offline Skip Updates: %d", this->offline_skip_updates_); #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE ESP_LOGCONFIG(TAG, "sensormap"); for (auto &it : sensorset_) { @@ -560,8 +560,9 @@ bool ModbusCommandItem::send() { } else { modbusdevice->send_raw(this->payload); } - ESP_LOGV(TAG, "Command sent %d 0x%X %d", uint8_t(this->function_code), this->register_address, this->register_count); - send_countdown--; + this->send_count_++; + ESP_LOGV(TAG, "Command sent %d 0x%X %d send_count: %d", uint8_t(this->function_code), this->register_address, + this->register_count, this->send_count_); return true; } diff --git a/esphome/components/modbus_controller/modbus_controller.h b/esphome/components/modbus_controller/modbus_controller.h index e88f4c07f7..1fa35e1535 100644 --- a/esphome/components/modbus_controller/modbus_controller.h +++ b/esphome/components/modbus_controller/modbus_controller.h @@ -312,7 +312,6 @@ struct RegisterRange { class ModbusCommandItem { public: static const size_t MAX_PAYLOAD_BYTES = 240; - static const uint8_t MAX_SEND_REPEATS = 5; ModbusController *modbusdevice; uint16_t register_address; uint16_t register_count; @@ -322,9 +321,9 @@ class ModbusCommandItem { on_data_func; std::vector payload = {}; bool send(); - // wrong commands (esp. custom commands) can block the send queue - // limit the number of repeats - uint8_t send_countdown{MAX_SEND_REPEATS}; + /// Check if the command should be retried based on the max_retries parameter + bool should_retry(uint8_t max_retries) { return this->send_count_ <= max_retries; }; + /// factory methods /** Create modbus read command * Function code 02-04 @@ -413,6 +412,11 @@ class ModbusCommandItem { &&handler = nullptr); bool is_equal(const ModbusCommandItem &other); + + protected: + // wrong commands (esp. custom commands) can block the send queue, limit the number of repeats. + /// How many times this command has been sent + uint8_t send_count_{0}; }; /** Modbus controller class. @@ -464,6 +468,10 @@ class ModbusController : public PollingComponent, public modbus::ModbusDevice { bool get_module_offline() { return module_offline_; } /// Set callback for commands void add_on_command_sent_callback(std::function &&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 + uint8_t get_max_cmd_retries() { return this->max_cmd_retries_; } protected: /// parse sensormap_ and create range of sequential addresses @@ -498,6 +506,8 @@ class ModbusController : public PollingComponent, public modbus::ModbusDevice { bool module_offline_; /// how many updates to skip if module is offline uint16_t offline_skip_updates_; + /// How many times we will retry a command if we get no response + uint8_t max_cmd_retries_{4}; CallbackManager command_sent_callback_{}; }; diff --git a/tests/components/modbus_controller/test.esp32-ard.yaml b/tests/components/modbus_controller/test.esp32-ard.yaml index b6e38aeb9c..cd95d149cb 100644 --- a/tests/components/modbus_controller/test.esp32-ard.yaml +++ b/tests/components/modbus_controller/test.esp32-ard.yaml @@ -29,3 +29,4 @@ modbus_controller: value_type: S_DWORD_R read_lambda: |- return 42.3; + max_cmd_retries: 0 diff --git a/tests/components/modbus_controller/test.esp32-idf.yaml b/tests/components/modbus_controller/test.esp32-idf.yaml index d5407ac406..ba28e94d73 100644 --- a/tests/components/modbus_controller/test.esp32-idf.yaml +++ b/tests/components/modbus_controller/test.esp32-idf.yaml @@ -13,3 +13,4 @@ modbus_controller: address: 0x2 modbus_id: mod_bus1 allow_duplicate_commands: true + max_cmd_retries: 10 From 63cda412f9e658b6c031ce47bdfb18a7a2e92d0a Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 11 Sep 2024 17:37:40 +1200 Subject: [PATCH 2073/2101] Bump version to 2024.9.0b1 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 7ad31f276f..fb745fd506 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.9.0-dev" +__version__ = "2024.9.0b1" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 664b219387b350197becdc552a2f68c62962dce4 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 11 Sep 2024 17:37:41 +1200 Subject: [PATCH 2074/2101] Bump version to 2024.10.0-dev --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 7ad31f276f..6e7bbdec98 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.9.0-dev" +__version__ = "2024.10.0-dev" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From cb7b4d93653f61a93e9416641df73c7e3d9a5b49 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 12 Sep 2024 14:08:41 +1200 Subject: [PATCH 2075/2101] [voice-assistant] Dont error on ``no_wake_word`` timeout error with streaming wake word (#7435) --- esphome/components/voice_assistant/voice_assistant.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index 577de630fb..a2210f188d 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -755,7 +755,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { message = std::move(arg.value); } } - if (code == "wake-word-timeout" || code == "wake_word_detection_aborted") { + if (code == "wake-word-timeout" || code == "wake_word_detection_aborted" || code == "no_wake_word") { // Don't change state here since either the "tts-end" or "run-end" events will do it. return; } else if (code == "wake-provider-missing" || code == "wake-engine-missing") { From 43f6793ad9abe54d2f87a9d07b0514c85911130a Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Wed, 11 Sep 2024 23:58:15 -0400 Subject: [PATCH 2076/2101] Create codeql.yml --- .github/workflows/codeql.yml | 90 ++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 .github/workflows/codeql.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000000..71ca55e907 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,90 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL Advanced" + +on: + schedule: + - cron: "30 18 * * 4" + +jobs: + analyze: + name: Analyze (${{ matrix.language }}) + # Runner size impacts CodeQL analysis time. To learn more, please see: + # - https://gh.io/recommended-hardware-resources-for-running-codeql + # - https://gh.io/supported-runners-and-hardware-resources + # - https://gh.io/using-larger-runners (GitHub.com only) + # Consider using larger runners or machines with greater resources for possible analysis time improvements. + runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} + permissions: + # required for all workflows + security-events: write + + # required to fetch internal or private CodeQL packs + packages: read + + # only required for workflows in private repositories + actions: read + contents: read + + strategy: + fail-fast: false + matrix: + include: + - language: c-cpp + build-mode: autobuild + - language: python + build-mode: none + # CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' + # Use `c-cpp` to analyze code written in C, C++ or both + # Use 'java-kotlin' to analyze code written in Java, Kotlin or both + # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both + # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis, + # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning. + # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how + # 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@v4 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + build-mode: ${{ matrix.build-mode }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + # If the analyze step fails for one of the languages you are analyzing with + # "We were unable to automatically build your code", modify the matrix above + # to set the build mode to "manual" for that language. Then modify this step + # to build your code. + # ℹ️ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + - if: matrix.build-mode == 'manual' + shell: bash + run: | + echo 'If you are using a "manual" build mode for one or more of the' \ + 'languages you are analyzing, replace this with the commands to build' \ + 'your code, for example:' + echo ' make bootstrap' + echo ' make release' + exit 1 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: "/language:${{matrix.language}}" From 6f9e725a2c86385339392751e235a3e7bb66f06f Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Wed, 11 Sep 2024 23:58:57 -0400 Subject: [PATCH 2077/2101] Update codeql.yml --- .github/workflows/codeql.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 71ca55e907..d4cda309db 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -12,6 +12,7 @@ name: "CodeQL Advanced" on: + workflow_dispatch: schedule: - cron: "30 18 * * 4" From 95a340d7a329a1a116b06cd7e479630ff4b53d80 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Thu, 12 Sep 2024 00:04:25 -0400 Subject: [PATCH 2078/2101] Update codeql.yml --- .github/workflows/codeql.yml | 80 ++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index d4cda309db..e9f212d7a8 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -40,10 +40,10 @@ jobs: fail-fast: false matrix: include: - - language: c-cpp - build-mode: autobuild - - language: python - build-mode: none + # - language: c-cpp + # build-mode: autobuild + - language: python + build-mode: none # CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' # Use `c-cpp` to analyze code written in C, C++ or both # Use 'java-kotlin' to analyze code written in Java, Kotlin or both @@ -53,39 +53,39 @@ jobs: # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how # 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@v4 - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v3 - with: - languages: ${{ matrix.language }} - build-mode: ${{ matrix.build-mode }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - - # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs - # queries: security-extended,security-and-quality - - # If the analyze step fails for one of the languages you are analyzing with - # "We were unable to automatically build your code", modify the matrix above - # to set the build mode to "manual" for that language. Then modify this step - # to build your code. - # ℹ️ Command-line programs to run using the OS shell. - # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - - if: matrix.build-mode == 'manual' - shell: bash - run: | - echo 'If you are using a "manual" build mode for one or more of the' \ - 'languages you are analyzing, replace this with the commands to build' \ - 'your code, for example:' - echo ' make bootstrap' - echo ' make release' - exit 1 - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 - with: - category: "/language:${{matrix.language}}" + - name: Checkout repository + uses: actions/checkout@v4 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + build-mode: ${{ matrix.build-mode }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + # If the analyze step fails for one of the languages you are analyzing with + # "We were unable to automatically build your code", modify the matrix above + # to set the build mode to "manual" for that language. Then modify this step + # to build your code. + # ℹ️ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + - if: matrix.build-mode == 'manual' + shell: bash + run: | + echo 'If you are using a "manual" build mode for one or more of the' \ + 'languages you are analyzing, replace this with the commands to build' \ + 'your code, for example:' + echo ' make bootstrap' + echo ' make release' + exit 1 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: "/language:${{matrix.language}}" From 6207510279673db4be7dc0612febb35d802e6543 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Thu, 12 Sep 2024 00:05:40 -0400 Subject: [PATCH 2079/2101] Update codeql.yml --- .github/workflows/codeql.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index e9f212d7a8..7f510782a8 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -55,7 +55,7 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 - + # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL uses: github/codeql-action/init@v3 @@ -65,10 +65,10 @@ jobs: # If you wish to specify custom queries, you can do so here or in a config file. # By default, queries listed here will override any specified in a config file. # Prefix the list here with "+" to use these queries and those in the config file. - + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs # queries: security-extended,security-and-quality - + # If the analyze step fails for one of the languages you are analyzing with # "We were unable to automatically build your code", modify the matrix above # to set the build mode to "manual" for that language. Then modify this step @@ -84,7 +84,7 @@ jobs: echo ' make bootstrap' echo ' make release' exit 1 - + - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v3 with: From 323c641ecdfaeb3769c3e9aae86d0079800ac474 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Thu, 12 Sep 2024 00:09:25 -0400 Subject: [PATCH 2080/2101] Update codeql.yml --- .github/workflows/codeql.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 7f510782a8..ddeb0a99d2 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -44,14 +44,14 @@ jobs: # build-mode: autobuild - language: python build-mode: none - # CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' - # Use `c-cpp` to analyze code written in C, C++ or both - # Use 'java-kotlin' to analyze code written in Java, Kotlin or both - # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both - # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis, - # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning. - # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how - # 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 + # CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' + # Use `c-cpp` to analyze code written in C, C++ or both + # Use 'java-kotlin' to analyze code written in Java, Kotlin or both + # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both + # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis, + # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning. + # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how + # 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@v4 From 78d0e0baae5efa3f918596be88192a45e7e10829 Mon Sep 17 00:00:00 2001 From: Tomer <57483589+tomer-w@users.noreply.github.com> Date: Fri, 13 Sep 2024 03:56:04 +0300 Subject: [PATCH 2081/2101] =?UTF-8?q?Improve=20manufacturer=20data=20traci?= =?UTF-8?q?ng=20to=20identify=20BLE=20devices=20a=20bit=20easie=E2=80=A6?= =?UTF-8?q?=20(#7332)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/ble_presence/binary_sensor.py | 4 ++-- esphome/components/esp32_ble/ble_uuid.cpp | 7 +++++++ esphome/components/esp32_ble/ble_uuid.h | 1 + .../esp32_ble_tracker/esp32_ble_tracker.cpp | 20 ++++++++++--------- .../esp32_ble_tracker/esp32_ble_tracker.h | 6 +++--- 5 files changed, 24 insertions(+), 14 deletions(-) diff --git a/esphome/components/ble_presence/binary_sensor.py b/esphome/components/ble_presence/binary_sensor.py index d1fdc80289..3a0f1ade98 100644 --- a/esphome/components/ble_presence/binary_sensor.py +++ b/esphome/components/ble_presence/binary_sensor.py @@ -41,7 +41,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_SERVICE_UUID): esp32_ble_tracker.bt_uuid, cv.Optional(CONF_IBEACON_MAJOR): cv.uint16_t, cv.Optional(CONF_IBEACON_MINOR): cv.uint16_t, - cv.Optional(CONF_IBEACON_UUID): cv.uuid, + cv.Optional(CONF_IBEACON_UUID): esp32_ble_tracker.bt_uuid, cv.Optional(CONF_TIMEOUT, default="5min"): cv.positive_time_period, cv.Optional(CONF_MIN_RSSI): cv.All( cv.decibel, cv.int_range(min=-100, max=-30) @@ -83,7 +83,7 @@ async def to_code(config): cg.add(var.set_service_uuid128(uuid128)) if ibeacon_uuid := config.get(CONF_IBEACON_UUID): - ibeacon_uuid = esp32_ble_tracker.as_hex_array(str(ibeacon_uuid)) + ibeacon_uuid = esp32_ble_tracker.as_reversed_hex_array(ibeacon_uuid) cg.add(var.set_ibeacon_uuid(ibeacon_uuid)) if (ibeacon_major := config.get(CONF_IBEACON_MAJOR)) is not None: diff --git a/esphome/components/esp32_ble/ble_uuid.cpp b/esphome/components/esp32_ble/ble_uuid.cpp index 57c2f9df94..07ac719434 100644 --- a/esphome/components/esp32_ble/ble_uuid.cpp +++ b/esphome/components/esp32_ble/ble_uuid.cpp @@ -31,6 +31,13 @@ ESPBTUUID ESPBTUUID::from_raw(const uint8_t *data) { memcpy(ret.uuid_.uuid.uuid128, data, ESP_UUID_LEN_128); return ret; } +ESPBTUUID ESPBTUUID::from_raw_reversed(const uint8_t *data) { + ESPBTUUID ret; + ret.uuid_.len = ESP_UUID_LEN_128; + for (int i = 0; i < ESP_UUID_LEN_128; i++) + ret.uuid_.uuid.uuid128[ESP_UUID_LEN_128 - 1 - i] = data[i]; + return ret; +} ESPBTUUID ESPBTUUID::from_raw(const std::string &data) { ESPBTUUID ret; if (data.length() == 4) { diff --git a/esphome/components/esp32_ble/ble_uuid.h b/esphome/components/esp32_ble/ble_uuid.h index 790a57c59d..d90db3a599 100644 --- a/esphome/components/esp32_ble/ble_uuid.h +++ b/esphome/components/esp32_ble/ble_uuid.h @@ -20,6 +20,7 @@ class ESPBTUUID { static ESPBTUUID from_uint32(uint32_t uuid); static ESPBTUUID from_raw(const uint8_t *data); + static ESPBTUUID from_raw_reversed(const uint8_t *data); static ESPBTUUID from_raw(const std::string &data); diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp index d154d4e519..74b4b9aa89 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp @@ -462,14 +462,16 @@ void ESPBTDevice::parse_scan_rst(const esp_ble_gap_cb_param_t::ble_scan_result_e ESP_LOGVV(TAG, " Service UUID: %s", uuid.to_string().c_str()); } for (auto &data : this->manufacturer_datas_) { - ESP_LOGVV(TAG, " Manufacturer data: %s", format_hex_pretty(data.data).c_str()); - if (this->get_ibeacon().has_value()) { - auto ibeacon = this->get_ibeacon().value(); - ESP_LOGVV(TAG, " iBeacon data:"); - ESP_LOGVV(TAG, " UUID: %s", ibeacon.get_uuid().to_string().c_str()); - ESP_LOGVV(TAG, " Major: %u", ibeacon.get_major()); - ESP_LOGVV(TAG, " Minor: %u", ibeacon.get_minor()); - ESP_LOGVV(TAG, " TXPower: %d", ibeacon.get_signal_power()); + auto ibeacon = ESPBLEiBeacon::from_manufacturer_data(data); + if (ibeacon.has_value()) { + ESP_LOGVV(TAG, " Manufacturer iBeacon:"); + ESP_LOGVV(TAG, " UUID: %s", ibeacon.value().get_uuid().to_string().c_str()); + ESP_LOGVV(TAG, " Major: %u", ibeacon.value().get_major()); + ESP_LOGVV(TAG, " Minor: %u", ibeacon.value().get_minor()); + ESP_LOGVV(TAG, " TXPower: %d", ibeacon.value().get_signal_power()); + } else { + ESP_LOGVV(TAG, " Manufacturer ID: %s, data: %s", data.uuid.to_string().c_str(), + format_hex_pretty(data.data).c_str()); } } for (auto &data : this->service_datas_) { @@ -478,7 +480,7 @@ void ESPBTDevice::parse_scan_rst(const esp_ble_gap_cb_param_t::ble_scan_result_e ESP_LOGVV(TAG, " Data: %s", format_hex_pretty(data.data).c_str()); } - ESP_LOGVV(TAG, "Adv data: %s", format_hex_pretty(param.ble_adv, param.adv_data_len + param.scan_rsp_len).c_str()); + ESP_LOGVV(TAG, " Adv data: %s", format_hex_pretty(param.ble_adv, param.adv_data_len + param.scan_rsp_len).c_str()); #endif } void ESPBTDevice::parse_adv_(const esp_ble_gap_cb_param_t::ble_scan_result_evt_param ¶m) { diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h index 3db7a54f6e..d2bb6a6e6d 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h @@ -44,10 +44,10 @@ class ESPBLEiBeacon { ESPBLEiBeacon(const uint8_t *data); static optional from_manufacturer_data(const ServiceData &data); - uint16_t get_major() { return ((this->beacon_data_.major & 0xFF) << 8) | (this->beacon_data_.major >> 8); } - uint16_t get_minor() { return ((this->beacon_data_.minor & 0xFF) << 8) | (this->beacon_data_.minor >> 8); } + uint16_t get_major() { return byteswap(this->beacon_data_.major); } + uint16_t get_minor() { return byteswap(this->beacon_data_.minor); } int8_t get_signal_power() { return this->beacon_data_.signal_power; } - ESPBTUUID get_uuid() { return ESPBTUUID::from_raw(this->beacon_data_.proximity_uuid); } + ESPBTUUID get_uuid() { return ESPBTUUID::from_raw_reversed(this->beacon_data_.proximity_uuid); } protected: struct { From e315b4d939e003e587d63a7e7bf67ea2beae51d4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Sep 2024 13:22:28 +1200 Subject: [PATCH 2082/2101] Bump peter-evans/create-pull-request from 7.0.0 to 7.0.2 (#7437) 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 e834ff3793..1418867240 100644 --- a/.github/workflows/sync-device-classes.yml +++ b/.github/workflows/sync-device-classes.yml @@ -36,7 +36,7 @@ jobs: python ./script/sync-device_class.py - name: Commit changes - uses: peter-evans/create-pull-request@v7.0.0 + uses: peter-evans/create-pull-request@v7.0.2 with: commit-message: "Synchronise Device Classes from Home Assistant" committer: esphomebot From 0df44b5df194a5b4b163ef2691e684dee89037f6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 13 Sep 2024 04:06:50 +0200 Subject: [PATCH 2083/2101] Bump recommended ESP-IDF to 4.4.8 (#7349) --- esphome/components/esp32/__init__.py | 2 +- platformio.ini | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index b630c7638e..9cb9ac257a 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -239,7 +239,7 @@ ARDUINO_PLATFORM_VERSION = cv.Version(5, 4, 0) # The default/recommended esp-idf framework version # - https://github.com/espressif/esp-idf/releases # - https://api.registry.platformio.org/v3/packages/platformio/tool/framework-espidf -RECOMMENDED_ESP_IDF_FRAMEWORK_VERSION = cv.Version(4, 4, 7) +RECOMMENDED_ESP_IDF_FRAMEWORK_VERSION = cv.Version(4, 4, 8) # The platformio/espressif32 version to use for esp-idf frameworks # - https://github.com/platformio/platform-espressif32/releases # - https://api.registry.platformio.org/v3/packages/platformio/platform/espressif32 diff --git a/platformio.ini b/platformio.ini index 7d912aaf54..e3593bf43f 100644 --- a/platformio.ini +++ b/platformio.ini @@ -139,7 +139,7 @@ extra_scripts = post:esphome/components/esp32/post_build.py.script extends = common:idf platform = platformio/espressif32@5.4.0 platform_packages = - platformio/framework-espidf@~3.40407.0 + platformio/framework-espidf@~3.40408.0 framework = espidf lib_deps = From 08c0715a30669fe76d43415ea76ce2d33a9939db Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 13 Sep 2024 16:15:00 +1200 Subject: [PATCH 2084/2101] [tm1638] Fix linting and formatting issues (#7443) --- esphome/components/tm1638/binary_sensor/__init__.py | 5 +++-- esphome/components/tm1638/display.py | 10 +++++----- esphome/components/tm1638/output/__init__.py | 5 +++-- esphome/components/tm1638/switch/__init__.py | 5 +++-- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/esphome/components/tm1638/binary_sensor/__init__.py b/esphome/components/tm1638/binary_sensor/__init__.py index 6623228555..de6ea35e54 100644 --- a/esphome/components/tm1638/binary_sensor/__init__.py +++ b/esphome/components/tm1638/binary_sensor/__init__.py @@ -1,8 +1,9 @@ import esphome.codegen as cg -import esphome.config_validation as cv from esphome.components import binary_sensor +import esphome.config_validation as cv from esphome.const import CONF_KEY -from ..display import tm1638_ns, TM1638Component, CONF_TM1638_ID + +from ..display import CONF_TM1638_ID, TM1638Component, tm1638_ns TM1638Key = tm1638_ns.class_("TM1638Key", binary_sensor.BinarySensor) diff --git a/esphome/components/tm1638/display.py b/esphome/components/tm1638/display.py index 2fb8dc7a55..14b70be94d 100644 --- a/esphome/components/tm1638/display.py +++ b/esphome/components/tm1638/display.py @@ -1,13 +1,13 @@ -import esphome.codegen as cg -import esphome.config_validation as cv from esphome import pins +import esphome.codegen as cg from esphome.components import display +import esphome.config_validation as cv from esphome.const import ( + CONF_CLK_PIN, + CONF_DIO_PIN, CONF_ID, CONF_INTENSITY, CONF_LAMBDA, - CONF_CLK_PIN, - CONF_DIO_PIN, CONF_STB_PIN, ) @@ -51,4 +51,4 @@ async def to_code(config): config[CONF_LAMBDA], [(TM1638ComponentRef, "it")], return_type=cg.void ) - cg.add(var.set_writer(lambda_)) + cg.add(var.set_writer(lambda_)) diff --git a/esphome/components/tm1638/output/__init__.py b/esphome/components/tm1638/output/__init__.py index 2d982e409d..b16b08d504 100644 --- a/esphome/components/tm1638/output/__init__.py +++ b/esphome/components/tm1638/output/__init__.py @@ -1,8 +1,9 @@ import esphome.codegen as cg -import esphome.config_validation as cv from esphome.components import output +import esphome.config_validation as cv from esphome.const import CONF_ID, CONF_LED -from ..display import tm1638_ns, TM1638Component, CONF_TM1638_ID + +from ..display import CONF_TM1638_ID, TM1638Component, tm1638_ns TM1638OutputLed = tm1638_ns.class_("TM1638OutputLed", output.BinaryOutput, cg.Component) diff --git a/esphome/components/tm1638/switch/__init__.py b/esphome/components/tm1638/switch/__init__.py index ed6aa91d03..8832cf8b92 100644 --- a/esphome/components/tm1638/switch/__init__.py +++ b/esphome/components/tm1638/switch/__init__.py @@ -1,8 +1,9 @@ import esphome.codegen as cg -import esphome.config_validation as cv from esphome.components import switch +import esphome.config_validation as cv from esphome.const import CONF_LED -from ..display import tm1638_ns, TM1638Component, CONF_TM1638_ID + +from ..display import CONF_TM1638_ID, TM1638Component, tm1638_ns TM1638SwitchLed = tm1638_ns.class_("TM1638SwitchLed", switch.Switch, cg.Component) From e4c90489f725b22f4c2abc8821b103a9fc37dce2 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 13 Sep 2024 16:16:24 +1200 Subject: [PATCH 2085/2101] [image] Fix linting and formatting issues (#7440) --- esphome/components/image/__init__.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/esphome/components/image/__init__.py b/esphome/components/image/__init__.py index e5a205f1e0..e80ba4498f 100644 --- a/esphome/components/image/__init__.py +++ b/esphome/components/image/__init__.py @@ -1,18 +1,17 @@ from __future__ import annotations -import logging - import hashlib import io +import logging from pathlib import Path import re + from magic import Magic -from esphome import core -from esphome.components import font -from esphome import external_files -import esphome.config_validation as cv +from esphome import core, external_files import esphome.codegen as cg +from esphome.components import font +import esphome.config_validation as cv from esphome.const import ( CONF_DITHER, CONF_FILE, @@ -239,12 +238,11 @@ CONFIG_SCHEMA = cv.All(font.validate_pillow_installed, IMAGE_SCHEMA) def load_svg_image(file: bytes, resize: tuple[int, int]): # Local import only to allow "validate_pillow_installed" to run *before* importing it - from PIL import Image - # This import is only needed in case of SVG images; adding it # to the top would force configurations not using SVG to also have it # installed for no reason. from cairosvg import svg2png + from PIL import Image if resize: req_width, req_height = resize @@ -274,6 +272,9 @@ async def to_code(config): elif conf_file[CONF_SOURCE] == SOURCE_WEB: path = compute_local_image_path(conf_file).as_posix() + else: + raise core.EsphomeError(f"Unknown image source: {conf_file[CONF_SOURCE]}") + try: with open(path, "rb") as f: file_contents = f.read() From c702a3f3ee09f779efc3d18b44e618628003141e Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 13 Sep 2024 16:16:57 +1200 Subject: [PATCH 2086/2101] [animation] Fix linting and formatting issues (#7439) --- esphome/components/animation/__init__.py | 28 ++++++++++++++---------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/esphome/components/animation/__init__.py b/esphome/components/animation/__init__.py index dbfc82c891..eb3d09ac96 100644 --- a/esphome/components/animation/__init__.py +++ b/esphome/components/animation/__init__.py @@ -1,26 +1,26 @@ import logging from esphome import automation, core +import esphome.codegen as cg from esphome.components import font import esphome.components.image as espImage from esphome.components.image import ( CONF_USE_TRANSPARENCY, LOCAL_SCHEMA, - WEB_SCHEMA, - SOURCE_WEB, SOURCE_LOCAL, + SOURCE_WEB, + WEB_SCHEMA, ) import esphome.config_validation as cv -import esphome.codegen as cg from esphome.const import ( CONF_FILE, CONF_ID, + CONF_PATH, CONF_RAW_DATA_ID, CONF_REPEAT, CONF_RESIZE, - CONF_TYPE, CONF_SOURCE, - CONF_PATH, + CONF_TYPE, CONF_URL, ) from esphome.core import CORE, HexInt @@ -172,6 +172,9 @@ async def to_code(config): path = CORE.relative_config_path(conf_file[CONF_PATH]) elif conf_file[CONF_SOURCE] == SOURCE_WEB: path = espImage.compute_local_image_path(conf_file).as_posix() + else: + raise core.EsphomeError(f"Unknown animation source: {conf_file[CONF_SOURCE]}") + try: image = Image.open(path) except Exception as e: @@ -183,13 +186,12 @@ async def to_code(config): new_width_max, new_height_max = config[CONF_RESIZE] ratio = min(new_width_max / width, new_height_max / height) width, height = int(width * ratio), int(height * ratio) - else: - if width > 500 or height > 500: - _LOGGER.warning( - 'The image "%s" you requested is very big. Please consider' - " using the resize parameter.", - path, - ) + elif width > 500 or height > 500: + _LOGGER.warning( + 'The image "%s" you requested is very big. Please consider' + " using the resize parameter.", + path, + ) transparent = config[CONF_USE_TRANSPARENCY] @@ -306,6 +308,8 @@ async def to_code(config): if transparent: alpha = image.split()[-1] has_alpha = alpha.getextrema()[0] < 0xFF + else: + has_alpha = False frame = image.convert("1", dither=Image.Dither.NONE) if CONF_RESIZE in config: frame = frame.resize([width, height]) From cf4bfcdce8b9492872ff22fbbd449d4079c1be9c Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 13 Sep 2024 22:03:25 +1200 Subject: [PATCH 2087/2101] [thermostat] Fix linting and formatting issues (#7442) --- esphome/components/thermostat/climate.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/esphome/components/thermostat/climate.py b/esphome/components/thermostat/climate.py index 89d6b13376..a529bbd474 100644 --- a/esphome/components/thermostat/climate.py +++ b/esphome/components/thermostat/climate.py @@ -1,7 +1,7 @@ -import esphome.codegen as cg -import esphome.config_validation as cv from esphome import automation +import esphome.codegen as cg from esphome.components import climate, sensor +import esphome.config_validation as cv from esphome.const import ( CONF_AUTO_MODE, CONF_AWAY_CONFIG, @@ -15,15 +15,15 @@ from esphome.const import ( CONF_DRY_ACTION, CONF_DRY_MODE, CONF_FAN_MODE, - CONF_FAN_MODE_ON_ACTION, - CONF_FAN_MODE_OFF_ACTION, CONF_FAN_MODE_AUTO_ACTION, + CONF_FAN_MODE_DIFFUSE_ACTION, + CONF_FAN_MODE_FOCUS_ACTION, + CONF_FAN_MODE_HIGH_ACTION, CONF_FAN_MODE_LOW_ACTION, CONF_FAN_MODE_MEDIUM_ACTION, - CONF_FAN_MODE_HIGH_ACTION, CONF_FAN_MODE_MIDDLE_ACTION, - CONF_FAN_MODE_FOCUS_ACTION, - CONF_FAN_MODE_DIFFUSE_ACTION, + CONF_FAN_MODE_OFF_ACTION, + CONF_FAN_MODE_ON_ACTION, CONF_FAN_MODE_QUIET_ACTION, CONF_FAN_ONLY_ACTION, CONF_FAN_ONLY_ACTION_USES_FAN_MODE_TIMER, @@ -50,8 +50,8 @@ from esphome.const import ( CONF_MIN_HEATING_RUN_TIME, CONF_MIN_IDLE_TIME, CONF_MIN_TEMPERATURE, - CONF_NAME, CONF_MODE, + CONF_NAME, CONF_OFF_MODE, CONF_PRESET, CONF_SENSOR, @@ -892,7 +892,7 @@ async def to_code(config): if name.upper() in climate.CLIMATE_PRESETS: standard_preset = climate.CLIMATE_PRESETS[name.upper()] - if two_points_available is True: + if two_points_available: preset_target_config = ThermostatClimateTargetTempConfig( preset_config[CONF_DEFAULT_TARGET_TEMPERATURE_LOW], preset_config[CONF_DEFAULT_TARGET_TEMPERATURE_HIGH], @@ -905,6 +905,8 @@ async def to_code(config): preset_target_config = ThermostatClimateTargetTempConfig( preset_config[CONF_DEFAULT_TARGET_TEMPERATURE_LOW] ) + else: + preset_target_config = None preset_target_variable = cg.new_variable( preset_config[CONF_ID], preset_target_config From de19d25a3c7f3993df2d51e89a7589eeaa6786b5 Mon Sep 17 00:00:00 2001 From: Oleg Tarasov Date: Mon, 16 Sep 2024 00:59:10 +0300 Subject: [PATCH 2088/2101] Add OpenTherm component (part 1: communication layer and hub) (#6645) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- CODEOWNERS | 1 + esphome/components/opentherm/__init__.py | 57 ++ esphome/components/opentherm/hub.cpp | 277 +++++++++ esphome/components/opentherm/hub.h | 110 ++++ esphome/components/opentherm/opentherm.cpp | 568 ++++++++++++++++++ esphome/components/opentherm/opentherm.h | 347 +++++++++++ tests/components/opentherm/common.yaml | 3 + .../components/opentherm/test.esp32-ard.yaml | 1 + .../opentherm/test.esp32-c3-ard.yaml | 1 + .../opentherm/test.esp32-c3-idf.yaml | 1 + .../components/opentherm/test.esp32-idf.yaml | 1 + .../opentherm/test.esp8266-ard.yaml | 1 + 12 files changed, 1368 insertions(+) create mode 100644 esphome/components/opentherm/__init__.py create mode 100644 esphome/components/opentherm/hub.cpp create mode 100644 esphome/components/opentherm/hub.h create mode 100644 esphome/components/opentherm/opentherm.cpp create mode 100644 esphome/components/opentherm/opentherm.h create mode 100644 tests/components/opentherm/common.yaml create mode 100644 tests/components/opentherm/test.esp32-ard.yaml create mode 100644 tests/components/opentherm/test.esp32-c3-ard.yaml create mode 100644 tests/components/opentherm/test.esp32-c3-idf.yaml create mode 100644 tests/components/opentherm/test.esp32-idf.yaml create mode 100644 tests/components/opentherm/test.esp8266-ard.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 0b1b88fbc8..f7fbbf9374 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -289,6 +289,7 @@ esphome/components/noblex/* @AGalfra esphome/components/number/* @esphome/core esphome/components/one_wire/* @ssieb esphome/components/online_image/* @guillempages +esphome/components/opentherm/* @olegtarasov esphome/components/ota/* @esphome/core esphome/components/output/* @esphome/core esphome/components/pca6416a/* @Mat931 diff --git a/esphome/components/opentherm/__init__.py b/esphome/components/opentherm/__init__.py new file mode 100644 index 0000000000..23443a4028 --- /dev/null +++ b/esphome/components/opentherm/__init__.py @@ -0,0 +1,57 @@ +from typing import Any + +from esphome import pins +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.const import CONF_ID, PLATFORM_ESP32, PLATFORM_ESP8266 + +CODEOWNERS = ["@olegtarasov"] +MULTI_CONF = True + +CONF_IN_PIN = "in_pin" +CONF_OUT_PIN = "out_pin" +CONF_CH_ENABLE = "ch_enable" +CONF_DHW_ENABLE = "dhw_enable" +CONF_COOLING_ENABLE = "cooling_enable" +CONF_OTC_ACTIVE = "otc_active" +CONF_CH2_ACTIVE = "ch2_active" +CONF_SYNC_MODE = "sync_mode" + +opentherm_ns = cg.esphome_ns.namespace("opentherm") +OpenthermHub = opentherm_ns.class_("OpenthermHub", cg.Component) + +CONFIG_SCHEMA = cv.All( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(OpenthermHub), + cv.Required(CONF_IN_PIN): pins.internal_gpio_input_pin_schema, + cv.Required(CONF_OUT_PIN): pins.internal_gpio_output_pin_schema, + cv.Optional(CONF_CH_ENABLE, True): cv.boolean, + cv.Optional(CONF_DHW_ENABLE, True): cv.boolean, + cv.Optional(CONF_COOLING_ENABLE, False): cv.boolean, + cv.Optional(CONF_OTC_ACTIVE, False): cv.boolean, + cv.Optional(CONF_CH2_ACTIVE, False): cv.boolean, + cv.Optional(CONF_SYNC_MODE, False): cv.boolean, + } + ).extend(cv.COMPONENT_SCHEMA), + cv.only_on([PLATFORM_ESP32, PLATFORM_ESP8266]), +) + + +async def to_code(config: dict[str, Any]) -> None: + # Create the hub, passing the two callbacks defined below + # Since the hub is used in the callbacks, we need to define it first + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, config) + + # Set pins + in_pin = await cg.gpio_pin_expression(config[CONF_IN_PIN]) + cg.add(var.set_in_pin(in_pin)) + + out_pin = await cg.gpio_pin_expression(config[CONF_OUT_PIN]) + cg.add(var.set_out_pin(out_pin)) + + non_sensors = {CONF_ID, CONF_IN_PIN, CONF_OUT_PIN} + for key, value in config.items(): + if key not in non_sensors: + cg.add(getattr(var, f"set_{key}")(value)) diff --git a/esphome/components/opentherm/hub.cpp b/esphome/components/opentherm/hub.cpp new file mode 100644 index 0000000000..c26fbced32 --- /dev/null +++ b/esphome/components/opentherm/hub.cpp @@ -0,0 +1,277 @@ +#include "hub.h" +#include "esphome/core/helpers.h" + +#include + +namespace esphome { +namespace opentherm { + +static const char *const TAG = "opentherm"; + +OpenthermData OpenthermHub::build_request_(MessageId request_id) { + OpenthermData data; + data.type = 0; + data.id = 0; + data.valueHB = 0; + data.valueLB = 0; + + // First, handle the status request. This requires special logic, because we + // wouldn't want to inadvertently disable domestic hot water, for example. + // It is also included in the macro-generated code below, but that will + // never be executed, because we short-circuit it here. + if (request_id == MessageId::STATUS) { + bool const ch_enabled = this->ch_enable; + bool dhw_enabled = this->dhw_enable; + bool cooling_enabled = this->cooling_enable; + bool otc_enabled = this->otc_active; + bool ch2_enabled = this->ch2_active; + + data.type = MessageType::READ_DATA; + data.id = MessageId::STATUS; + data.valueHB = ch_enabled | (dhw_enabled << 1) | (cooling_enabled << 2) | (otc_enabled << 3) | (ch2_enabled << 4); + +// Disable incomplete switch statement warnings, because the cases in each +// switch are generated based on the configured sensors and inputs. +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wswitch" + + // TODO: This is a placeholder for an auto-generated switch statement which builds request structure based on + // which sensors are enabled in config. + +#pragma GCC diagnostic pop + + return data; + } + return OpenthermData(); +} + +OpenthermHub::OpenthermHub() : Component() {} + +void OpenthermHub::process_response(OpenthermData &data) { + ESP_LOGD(TAG, "Received OpenTherm response with id %d (%s)", data.id, + this->opentherm_->message_id_to_str((MessageId) data.id)); + ESP_LOGD(TAG, "%s", this->opentherm_->debug_data(data).c_str()); +} + +void OpenthermHub::setup() { + ESP_LOGD(TAG, "Setting up OpenTherm component"); + this->opentherm_ = make_unique(this->in_pin_, this->out_pin_); + if (!this->opentherm_->initialize()) { + ESP_LOGE(TAG, "Failed to initialize OpenTherm protocol. See previous log messages for details."); + this->mark_failed(); + return; + } + + // Ensure that there is at least one request, as we are required to + // communicate at least once every second. Sending the status request is + // good practice anyway. + this->add_repeating_message(MessageId::STATUS); + + this->current_message_iterator_ = this->initial_messages_.begin(); +} + +void OpenthermHub::on_shutdown() { this->opentherm_->stop(); } + +void OpenthermHub::loop() { + if (this->sync_mode_) { + this->sync_loop_(); + return; + } + + auto cur_time = millis(); + auto const cur_mode = this->opentherm_->get_mode(); + switch (cur_mode) { + case OperationMode::WRITE: + case OperationMode::READ: + case OperationMode::LISTEN: + if (!this->check_timings_(cur_time)) { + break; + } + this->last_mode_ = cur_mode; + break; + case OperationMode::ERROR_PROTOCOL: + if (this->last_mode_ == OperationMode::WRITE) { + this->handle_protocol_write_error_(); + } else if (this->last_mode_ == OperationMode::READ) { + this->handle_protocol_read_error_(); + } + + this->stop_opentherm_(); + break; + case OperationMode::ERROR_TIMEOUT: + this->handle_timeout_error_(); + this->stop_opentherm_(); + break; + case OperationMode::IDLE: + if (this->should_skip_loop_(cur_time)) { + break; + } + this->start_conversation_(); + break; + case OperationMode::SENT: + // Message sent, now listen for the response. + this->opentherm_->listen(); + break; + case OperationMode::RECEIVED: + this->read_response_(); + break; + } +} + +void OpenthermHub::sync_loop_() { + if (!this->opentherm_->is_idle()) { + ESP_LOGE(TAG, "OpenTherm is not idle at the start of the loop"); + return; + } + + auto cur_time = millis(); + + this->check_timings_(cur_time); + + if (this->should_skip_loop_(cur_time)) { + return; + } + + this->start_conversation_(); + + if (!this->spin_wait_(1150, [&] { return this->opentherm_->is_active(); })) { + ESP_LOGE(TAG, "Hub timeout triggered during send"); + this->stop_opentherm_(); + return; + } + + if (this->opentherm_->is_error()) { + this->handle_protocol_write_error_(); + this->stop_opentherm_(); + return; + } else if (!this->opentherm_->is_sent()) { + ESP_LOGW(TAG, "Unexpected state after sending request: %s", + this->opentherm_->operation_mode_to_str(this->opentherm_->get_mode())); + this->stop_opentherm_(); + return; + } + + // Listen for the response + this->opentherm_->listen(); + if (!this->spin_wait_(1150, [&] { return this->opentherm_->is_active(); })) { + ESP_LOGE(TAG, "Hub timeout triggered during receive"); + this->stop_opentherm_(); + return; + } + + if (this->opentherm_->is_timeout()) { + this->handle_timeout_error_(); + this->stop_opentherm_(); + return; + } else if (this->opentherm_->is_protocol_error()) { + this->handle_protocol_read_error_(); + this->stop_opentherm_(); + return; + } else if (!this->opentherm_->has_message()) { + ESP_LOGW(TAG, "Unexpected state after receiving response: %s", + this->opentherm_->operation_mode_to_str(this->opentherm_->get_mode())); + this->stop_opentherm_(); + return; + } + + this->read_response_(); +} + +bool OpenthermHub::check_timings_(uint32_t cur_time) { + if (this->last_conversation_start_ > 0 && (cur_time - this->last_conversation_start_) > 1150) { + ESP_LOGW(TAG, + "%d ms elapsed since the start of the last convo, but 1150 ms are allowed at maximum. Look at other " + "components that might slow the loop down.", + (int) (cur_time - this->last_conversation_start_)); + this->stop_opentherm_(); + return false; + } + + return true; +} + +bool OpenthermHub::should_skip_loop_(uint32_t cur_time) const { + if (this->last_conversation_end_ > 0 && (cur_time - this->last_conversation_end_) < 100) { + ESP_LOGV(TAG, "Less than 100 ms elapsed since last convo, skipping this iteration"); + return true; + } + + return false; +} + +void OpenthermHub::start_conversation_() { + if (this->sending_initial_ && this->current_message_iterator_ == this->initial_messages_.end()) { + this->sending_initial_ = false; + this->current_message_iterator_ = this->repeating_messages_.begin(); + } else if (this->current_message_iterator_ == this->repeating_messages_.end()) { + this->current_message_iterator_ = this->repeating_messages_.begin(); + } + + auto request = this->build_request_(*this->current_message_iterator_); + + ESP_LOGD(TAG, "Sending request with id %d (%s)", request.id, + this->opentherm_->message_id_to_str((MessageId) request.id)); + ESP_LOGD(TAG, "%s", this->opentherm_->debug_data(request).c_str()); + // Send the request + this->last_conversation_start_ = millis(); + this->opentherm_->send(request); +} + +void OpenthermHub::read_response_() { + OpenthermData response; + if (!this->opentherm_->get_message(response)) { + ESP_LOGW(TAG, "Couldn't get the response, but flags indicated success. This is a bug."); + this->stop_opentherm_(); + return; + } + + this->stop_opentherm_(); + + this->process_response(response); + + this->current_message_iterator_++; +} + +void OpenthermHub::stop_opentherm_() { + this->opentherm_->stop(); + this->last_conversation_end_ = millis(); +} + +void OpenthermHub::handle_protocol_write_error_() { + ESP_LOGW(TAG, "Error while sending request: %s", + this->opentherm_->operation_mode_to_str(this->opentherm_->get_mode())); + ESP_LOGW(TAG, "%s", this->opentherm_->debug_data(this->last_request_).c_str()); +} + +void OpenthermHub::handle_protocol_read_error_() { + OpenThermError error; + this->opentherm_->get_protocol_error(error); + ESP_LOGW(TAG, "Protocol error occured while receiving response: %s", this->opentherm_->debug_error(error).c_str()); +} + +void OpenthermHub::handle_timeout_error_() { + ESP_LOGW(TAG, "Receive response timed out at a protocol level"); + this->stop_opentherm_(); +} + +#define ID(x) x +#define SHOW2(x) #x +#define SHOW(x) SHOW2(x) + +void OpenthermHub::dump_config() { + ESP_LOGCONFIG(TAG, "OpenTherm:"); + LOG_PIN(" In: ", this->in_pin_); + LOG_PIN(" Out: ", this->out_pin_); + ESP_LOGCONFIG(TAG, " Sync mode: %d", this->sync_mode_); + ESP_LOGCONFIG(TAG, " Initial requests:"); + for (auto type : this->initial_messages_) { + ESP_LOGCONFIG(TAG, " - %d", type); + } + ESP_LOGCONFIG(TAG, " Repeating requests:"); + for (auto type : this->repeating_messages_) { + ESP_LOGCONFIG(TAG, " - %d", type); + } +} + +} // namespace opentherm +} // namespace esphome diff --git a/esphome/components/opentherm/hub.h b/esphome/components/opentherm/hub.h new file mode 100644 index 0000000000..ce9f09fe33 --- /dev/null +++ b/esphome/components/opentherm/hub.h @@ -0,0 +1,110 @@ +#pragma once + +#include "esphome/core/defines.h" +#include "esphome/core/hal.h" +#include "esphome/core/component.h" +#include "esphome/core/log.h" + +#include "opentherm.h" + +#include +#include +#include +#include + +namespace esphome { +namespace opentherm { + +// OpenTherm component for ESPHome +class OpenthermHub : public Component { + protected: + // Communication pins for the OpenTherm interface + InternalGPIOPin *in_pin_, *out_pin_; + // The OpenTherm interface + std::unique_ptr opentherm_; + + // The set of initial messages to send on starting communication with the boiler + std::unordered_set initial_messages_; + // and the repeating messages which are sent repeatedly to update various sensors + // and boiler parameters (like the setpoint). + std::unordered_set repeating_messages_; + // Indicates if we are still working on the initial requests or not + bool sending_initial_ = true; + // Index for the current request in one of the _requests sets. + std::unordered_set::const_iterator current_message_iterator_; + + uint32_t last_conversation_start_ = 0; + uint32_t last_conversation_end_ = 0; + OperationMode last_mode_ = IDLE; + OpenthermData last_request_; + + // Synchronous communication mode prevents other components from disabling interrupts while + // we are talking to the boiler. Enable if you experience random intermittent invalid response errors. + // Very likely to happen while using Dallas temperature sensors. + bool sync_mode_ = false; + + // Create OpenTherm messages based on the message id + OpenthermData build_request_(MessageId request_id); + void handle_protocol_write_error_(); + void handle_protocol_read_error_(); + void handle_timeout_error_(); + void stop_opentherm_(); + void start_conversation_(); + void read_response_(); + bool check_timings_(uint32_t cur_time); + bool should_skip_loop_(uint32_t cur_time) const; + void sync_loop_(); + + template bool spin_wait_(uint32_t timeout, F func) { + auto start_time = millis(); + while (func()) { + yield(); + auto cur_time = millis(); + if (cur_time - start_time >= timeout) { + return false; + } + } + return true; + } + + public: + // Constructor with references to the global interrupt handlers + OpenthermHub(); + + // Handle responses from the OpenTherm interface + void process_response(OpenthermData &data); + + // Setters for the input and output OpenTherm interface pins + void set_in_pin(InternalGPIOPin *in_pin) { this->in_pin_ = in_pin; } + void set_out_pin(InternalGPIOPin *out_pin) { this->out_pin_ = out_pin; } + + // Add a request to the set of initial requests + void add_initial_message(MessageId message_id) { this->initial_messages_.insert(message_id); } + // Add a request to the set of repeating requests. Note that a large number of repeating + // requests will slow down communication with the boiler. Each request may take up to 1 second, + // so with all sensors enabled, it may take about half a minute before a change in setpoint + // will be processed. + void add_repeating_message(MessageId message_id) { this->repeating_messages_.insert(message_id); } + + // There are five status variables, which can either be set as a simple variable, + // or using a switch. ch_enable and dhw_enable default to true, the others to false. + bool ch_enable = true, dhw_enable = true, cooling_enable = false, otc_active = false, ch2_active = false; + + // Setters for the status variables + void set_ch_enable(bool value) { this->ch_enable = value; } + void set_dhw_enable(bool value) { this->dhw_enable = value; } + void set_cooling_enable(bool value) { this->cooling_enable = value; } + void set_otc_active(bool value) { this->otc_active = value; } + void set_ch2_active(bool value) { this->ch2_active = value; } + void set_sync_mode(bool sync_mode) { this->sync_mode_ = sync_mode; } + + float get_setup_priority() const override { return setup_priority::HARDWARE; } + + void setup() override; + void on_shutdown() override; + void loop() override; + void dump_config() override; +}; + +} // namespace opentherm +} // namespace esphome diff --git a/esphome/components/opentherm/opentherm.cpp b/esphome/components/opentherm/opentherm.cpp new file mode 100644 index 0000000000..b830cc01d3 --- /dev/null +++ b/esphome/components/opentherm/opentherm.cpp @@ -0,0 +1,568 @@ +/* + * OpenTherm protocol implementation. Originally taken from https://github.com/jpraus/arduino-opentherm, but + * heavily modified to comply with ESPHome coding standards and provide better logging. + * Original code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International + * Public License, which is compatible with GPLv3 license, which covers C++ part of ESPHome project. + */ + +#include "opentherm.h" +#include "esphome/core/helpers.h" +#if defined(ESP32) || defined(USE_ESP_IDF) +#include "driver/timer.h" +#include "esp_err.h" +#endif +#ifdef ESP8266 +#include "Arduino.h" +#endif +#include +#include +#include + +namespace esphome { +namespace opentherm { + +using std::string; +using std::bitset; +using std::stringstream; +using std::to_string; + +static const char *const TAG = "opentherm"; + +#ifdef ESP8266 +OpenTherm *OpenTherm::instance_ = nullptr; +#endif + +OpenTherm::OpenTherm(InternalGPIOPin *in_pin, InternalGPIOPin *out_pin, int32_t device_timeout) + : in_pin_(in_pin), + out_pin_(out_pin), +#if defined(ESP32) || defined(USE_ESP_IDF) + timer_group_(TIMER_GROUP_0), + timer_idx_(TIMER_0), +#endif + mode_(OperationMode::IDLE), + error_type_(ProtocolErrorType::NO_ERROR), + capture_(0), + clock_(0), + data_(0), + bit_pos_(0), + timeout_counter_(-1), + device_timeout_(device_timeout) { + this->isr_in_pin_ = in_pin->to_isr(); + this->isr_out_pin_ = out_pin->to_isr(); +} + +bool OpenTherm::initialize() { +#ifdef ESP8266 + OpenTherm::instance_ = this; +#endif + this->in_pin_->pin_mode(gpio::FLAG_INPUT); + this->out_pin_->pin_mode(gpio::FLAG_OUTPUT); + this->out_pin_->digital_write(true); + +#if defined(ESP32) || defined(USE_ESP_IDF) + return this->init_esp32_timer_(); +#else + return true; +#endif +} + +void OpenTherm::listen() { + this->stop_timer_(); + this->timeout_counter_ = this->device_timeout_ * 5; // timer_ ticks at 5 ticks/ms + + this->mode_ = OperationMode::LISTEN; + this->data_ = 0; + this->bit_pos_ = 0; + + this->start_read_timer_(); +} + +void OpenTherm::send(OpenthermData &data) { + this->stop_timer_(); + this->data_ = data.type; + this->data_ = (this->data_ << 12) | data.id; + this->data_ = (this->data_ << 8) | data.valueHB; + this->data_ = (this->data_ << 8) | data.valueLB; + if (!check_parity_(this->data_)) { + this->data_ = this->data_ | 0x80000000; + } + + this->clock_ = 1; // clock starts at HIGH + this->bit_pos_ = 33; // count down (33 == start bit, 32-1 data, 0 == stop bit) + this->mode_ = OperationMode::WRITE; + + this->start_write_timer_(); +} + +bool OpenTherm::get_message(OpenthermData &data) { + if (this->mode_ == OperationMode::RECEIVED) { + data.type = (this->data_ >> 28) & 0x7; + data.id = (this->data_ >> 16) & 0xFF; + data.valueHB = (this->data_ >> 8) & 0xFF; + data.valueLB = this->data_ & 0xFF; + return true; + } + return false; +} + +bool OpenTherm::get_protocol_error(OpenThermError &error) { + if (this->mode_ != OperationMode::ERROR_PROTOCOL) { + return false; + } + + error.error_type = this->error_type_; + error.bit_pos = this->bit_pos_; + error.capture = this->capture_; + error.clock = this->clock_; + error.data = this->data_; + + return true; +} + +void OpenTherm::stop() { + this->stop_timer_(); + this->mode_ = OperationMode::IDLE; +} + +void IRAM_ATTR OpenTherm::read_() { + this->data_ = 0; + this->bit_pos_ = 0; + this->mode_ = OperationMode::READ; + this->capture_ = 1; // reset counter and add as if read start bit + this->clock_ = 1; // clock is high at the start of comm + this->start_read_timer_(); // get us into 1/4 of manchester code. 5 timer ticks constitute 1 ms, which is 1 bit + // period in OpenTherm. +} + +bool IRAM_ATTR OpenTherm::timer_isr(OpenTherm *arg) { + if (arg->mode_ == OperationMode::LISTEN) { + if (arg->timeout_counter_ == 0) { + arg->mode_ = OperationMode::ERROR_TIMEOUT; + arg->stop_timer_(); + return false; + } + bool const value = arg->isr_in_pin_.digital_read(); + if (value) { // incoming data (rising signal) + arg->read_(); + } + if (arg->timeout_counter_ > 0) { + arg->timeout_counter_--; + } + } else if (arg->mode_ == OperationMode::READ) { + bool const value = arg->isr_in_pin_.digital_read(); + uint8_t const last = (arg->capture_ & 1); + if (value != last) { + // transition of signal from last sampling + if (arg->clock_ == 1 && arg->capture_ > 0xF) { + // no transition in the middle of the bit + arg->mode_ = OperationMode::ERROR_PROTOCOL; + arg->error_type_ = ProtocolErrorType::NO_TRANSITION; + arg->stop_timer_(); + return false; + } else if (arg->clock_ == 1 || arg->capture_ > 0xF) { + // transition in the middle of the bit OR no transition between two bit, both are valid data points + if (arg->bit_pos_ == BitPositions::STOP_BIT) { + // expecting stop bit + auto stop_bit_error = arg->verify_stop_bit_(last); + if (stop_bit_error == ProtocolErrorType::NO_ERROR) { + arg->mode_ = OperationMode::RECEIVED; + arg->stop_timer_(); + return false; + } else { + // end of data not verified, invalid data + arg->mode_ = OperationMode::ERROR_PROTOCOL; + arg->error_type_ = stop_bit_error; + arg->stop_timer_(); + return false; + } + } else { + // normal data point at clock high + arg->bit_read_(last); + arg->clock_ = 0; + } + } else { + // clock low, not a data point, switch clock + arg->clock_ = 1; + } + arg->capture_ = 1; // reset counter + } else if (arg->capture_ > 0xFF) { + // no change for too long, invalid mancheter encoding + arg->mode_ = OperationMode::ERROR_PROTOCOL; + arg->error_type_ = ProtocolErrorType::NO_CHANGE_TOO_LONG; + arg->stop_timer_(); + return false; + } + arg->capture_ = (arg->capture_ << 1) | value; + } else if (arg->mode_ == OperationMode::WRITE) { + // write data to pin + if (arg->bit_pos_ == 33 || arg->bit_pos_ == 0) { // start bit + arg->write_bit_(1, arg->clock_); + } else { // data bits + arg->write_bit_(read_bit(arg->data_, arg->bit_pos_ - 1), arg->clock_); + } + if (arg->clock_ == 0) { + if (arg->bit_pos_ <= 0) { // check termination + arg->mode_ = OperationMode::SENT; // all data written + arg->stop_timer_(); + } + arg->bit_pos_--; + arg->clock_ = 1; + } else { + arg->clock_ = 0; + } + } + + return false; +} + +#ifdef ESP8266 +void IRAM_ATTR OpenTherm::esp8266_timer_isr() { OpenTherm::timer_isr(OpenTherm::instance_); } +#endif + +void IRAM_ATTR OpenTherm::bit_read_(uint8_t value) { + this->data_ = (this->data_ << 1) | value; + this->bit_pos_++; +} + +ProtocolErrorType OpenTherm::verify_stop_bit_(uint8_t value) { + if (value) { // stop bit detected + return check_parity_(this->data_) ? ProtocolErrorType::NO_ERROR : ProtocolErrorType::PARITY_ERROR; + } else { // no stop bit detected, error + return ProtocolErrorType::INVALID_STOP_BIT; + } +} + +void IRAM_ATTR OpenTherm::write_bit_(uint8_t high, uint8_t clock) { + if (clock == 1) { // left part of manchester encoding + this->isr_out_pin_.digital_write(!high); // low means logical 1 to protocol + } else { // right part of manchester encoding + this->isr_out_pin_.digital_write(high); // high means logical 0 to protocol + } +} + +#if defined(ESP32) || defined(USE_ESP_IDF) + +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, +#if ESP_IDF_VERSION_MAJOR >= 5 + .clk_src = TIMER_SRC_CLK_DEFAULT, +#endif + .divider = 80, + }; + + esp_err_t result; + + result = timer_init(this->timer_group_, this->timer_idx_, &config); + if (result != ESP_OK) { + const auto *error = esp_err_to_name(result); + ESP_LOGE(TAG, "Failed to init timer. Error: %s", error); + return false; + } + + result = timer_set_counter_value(this->timer_group_, this->timer_idx_, 0); + if (result != ESP_OK) { + const auto *error = esp_err_to_name(result); + ESP_LOGE(TAG, "Failed to set counter value. Error: %s", error); + return false; + } + + result = timer_isr_callback_add(this->timer_group_, this->timer_idx_, reinterpret_cast(timer_isr), + this, 0); + if (result != ESP_OK) { + const auto *error = esp_err_to_name(result); + ESP_LOGE(TAG, "Failed to register timer interrupt. Error: %s", error); + return false; + } + + return true; +} + +void IRAM_ATTR OpenTherm::start_esp32_timer_(uint64_t alarm_value) { + esp_err_t result; + + result = timer_set_alarm_value(this->timer_group_, this->timer_idx_, alarm_value); + if (result != ESP_OK) { + const auto *error = esp_err_to_name(result); + ESP_LOGE(TAG, "Failed to set alarm value. Error: %s", error); + return; + } + + result = timer_start(this->timer_group_, this->timer_idx_); + if (result != ESP_OK) { + const auto *error = esp_err_to_name(result); + ESP_LOGE(TAG, "Failed to start the timer. Error: %s", error); + return; + } +} + +// 5 kHz timer_ +void IRAM_ATTR OpenTherm::start_read_timer_() { + InterruptLock const lock; + this->start_esp32_timer_(200); +} + +// 2 kHz timer_ +void IRAM_ATTR OpenTherm::start_write_timer_() { + InterruptLock const lock; + this->start_esp32_timer_(500); +} + +void IRAM_ATTR OpenTherm::stop_timer_() { + InterruptLock const lock; + + esp_err_t result; + + result = timer_pause(this->timer_group_, this->timer_idx_); + if (result != ESP_OK) { + const auto *error = esp_err_to_name(result); + ESP_LOGE(TAG, "Failed to pause the timer. Error: %s", error); + return; + } + + result = timer_set_counter_value(this->timer_group_, this->timer_idx_, 0); + if (result != ESP_OK) { + const auto *error = esp_err_to_name(result); + ESP_LOGE(TAG, "Failed to set timer counter to 0 after pausing. Error: %s", error); + return; + } +} + +#endif // END ESP32 + +#ifdef ESP8266 +// 5 kHz timer_ +void OpenTherm::start_read_timer_() { + InterruptLock const lock; + timer1_attachInterrupt(OpenTherm::esp8266_timer_isr); + timer1_enable(TIM_DIV16, TIM_EDGE, TIM_LOOP); // 5MHz (5 ticks/us - 1677721.4 us max) + timer1_write(1000); // 5kHz +} + +// 2 kHz timer_ +void OpenTherm::start_write_timer_() { + InterruptLock const lock; + timer1_attachInterrupt(OpenTherm::esp8266_timer_isr); + timer1_enable(TIM_DIV16, TIM_EDGE, TIM_LOOP); // 5MHz (5 ticks/us - 1677721.4 us max) + timer1_write(2500); // 2kHz +} + +void OpenTherm::stop_timer_() { + InterruptLock const lock; + timer1_disable(); + timer1_detachInterrupt(); +} + +#endif // END ESP8266 + +// https://stackoverflow.com/questions/21617970/how-to-check-if-value-has-even-parity-of-bits-or-odd +bool OpenTherm::check_parity_(uint32_t val) { + val ^= val >> 16; + val ^= val >> 8; + val ^= val >> 4; + val ^= val >> 2; + val ^= val >> 1; + return (~val) & 1; +} + +#define TO_STRING_MEMBER(name) \ + case name: \ + return #name; + +const char *OpenTherm::operation_mode_to_str(OperationMode mode) { + switch (mode) { + TO_STRING_MEMBER(IDLE) + TO_STRING_MEMBER(LISTEN) + TO_STRING_MEMBER(READ) + TO_STRING_MEMBER(RECEIVED) + TO_STRING_MEMBER(WRITE) + TO_STRING_MEMBER(SENT) + TO_STRING_MEMBER(ERROR_PROTOCOL) + TO_STRING_MEMBER(ERROR_TIMEOUT) + default: + return ""; + } +} +const char *OpenTherm::protocol_error_to_to_str(ProtocolErrorType error_type) { + switch (error_type) { + TO_STRING_MEMBER(NO_ERROR) + TO_STRING_MEMBER(NO_TRANSITION) + TO_STRING_MEMBER(INVALID_STOP_BIT) + TO_STRING_MEMBER(PARITY_ERROR) + TO_STRING_MEMBER(NO_CHANGE_TOO_LONG) + default: + return ""; + } +} +const char *OpenTherm::message_type_to_str(MessageType message_type) { + switch (message_type) { + TO_STRING_MEMBER(READ_DATA) + TO_STRING_MEMBER(READ_ACK) + TO_STRING_MEMBER(WRITE_DATA) + TO_STRING_MEMBER(WRITE_ACK) + TO_STRING_MEMBER(INVALID_DATA) + TO_STRING_MEMBER(DATA_INVALID) + TO_STRING_MEMBER(UNKNOWN_DATAID) + default: + return ""; + } +} + +const char *OpenTherm::message_id_to_str(MessageId id) { + switch (id) { + TO_STRING_MEMBER(STATUS) + TO_STRING_MEMBER(CH_SETPOINT) + TO_STRING_MEMBER(CONTROLLER_CONFIG) + TO_STRING_MEMBER(DEVICE_CONFIG) + TO_STRING_MEMBER(COMMAND_CODE) + TO_STRING_MEMBER(FAULT_FLAGS) + TO_STRING_MEMBER(REMOTE) + TO_STRING_MEMBER(COOLING_CONTROL) + TO_STRING_MEMBER(CH2_SETPOINT) + TO_STRING_MEMBER(CH_SETPOINT_OVERRIDE) + TO_STRING_MEMBER(TSP_COUNT) + TO_STRING_MEMBER(TSP_COMMAND) + TO_STRING_MEMBER(FHB_SIZE) + TO_STRING_MEMBER(FHB_COMMAND) + TO_STRING_MEMBER(MAX_MODULATION_LEVEL) + TO_STRING_MEMBER(MAX_BOILER_CAPACITY) + TO_STRING_MEMBER(ROOM_SETPOINT) + TO_STRING_MEMBER(MODULATION_LEVEL) + TO_STRING_MEMBER(CH_WATER_PRESSURE) + TO_STRING_MEMBER(DHW_FLOW_RATE) + TO_STRING_MEMBER(DAY_TIME) + TO_STRING_MEMBER(DATE) + TO_STRING_MEMBER(YEAR) + TO_STRING_MEMBER(ROOM_SETPOINT_CH2) + TO_STRING_MEMBER(ROOM_TEMP) + TO_STRING_MEMBER(FEED_TEMP) + TO_STRING_MEMBER(DHW_TEMP) + TO_STRING_MEMBER(OUTSIDE_TEMP) + TO_STRING_MEMBER(RETURN_WATER_TEMP) + TO_STRING_MEMBER(SOLAR_STORE_TEMP) + TO_STRING_MEMBER(SOLAR_COLLECT_TEMP) + TO_STRING_MEMBER(FEED_TEMP_CH2) + TO_STRING_MEMBER(DHW2_TEMP) + TO_STRING_MEMBER(EXHAUST_TEMP) + TO_STRING_MEMBER(FAN_SPEED) + TO_STRING_MEMBER(FLAME_CURRENT) + TO_STRING_MEMBER(DHW_BOUNDS) + TO_STRING_MEMBER(CH_BOUNDS) + TO_STRING_MEMBER(OTC_CURVE_BOUNDS) + TO_STRING_MEMBER(DHW_SETPOINT) + TO_STRING_MEMBER(MAX_CH_SETPOINT) + TO_STRING_MEMBER(OTC_CURVE_RATIO) + TO_STRING_MEMBER(HVAC_STATUS) + TO_STRING_MEMBER(REL_VENT_SETPOINT) + TO_STRING_MEMBER(DEVICE_VENT) + TO_STRING_MEMBER(REL_VENTILATION) + TO_STRING_MEMBER(REL_HUMID_EXHAUST) + TO_STRING_MEMBER(SUPPLY_INLET_TEMP) + TO_STRING_MEMBER(SUPPLY_OUTLET_TEMP) + TO_STRING_MEMBER(EXHAUST_INLET_TEMP) + TO_STRING_MEMBER(EXHAUST_OUTLET_TEMP) + TO_STRING_MEMBER(NOM_REL_VENTILATION) + TO_STRING_MEMBER(OVERRIDE_FUNC) + TO_STRING_MEMBER(OEM_DIAGNOSTIC) + TO_STRING_MEMBER(BURNER_STARTS) + TO_STRING_MEMBER(CH_PUMP_STARTS) + TO_STRING_MEMBER(DHW_PUMP_STARTS) + TO_STRING_MEMBER(DHW_BURNER_STARTS) + TO_STRING_MEMBER(BURNER_HOURS) + TO_STRING_MEMBER(CH_PUMP_HOURS) + TO_STRING_MEMBER(DHW_PUMP_HOURS) + TO_STRING_MEMBER(DHW_BURNER_HOURS) + TO_STRING_MEMBER(OT_VERSION_CONTROLLER) + TO_STRING_MEMBER(OT_VERSION_DEVICE) + TO_STRING_MEMBER(VERSION_CONTROLLER) + TO_STRING_MEMBER(VERSION_DEVICE) + default: + return ""; + } +} + +string OpenTherm::debug_data(OpenthermData &data) { + stringstream result; + result << bitset<8>(data.type) << " " << bitset<8>(data.id) << " " << bitset<8>(data.valueHB) << " " + << bitset<8>(data.valueLB) << "\n"; + result << "type: " << this->message_type_to_str((MessageType) data.type) << "; "; + result << "id: " << to_string(data.id) << "; "; + result << "HB: " << to_string(data.valueHB) << "; "; + result << "LB: " << to_string(data.valueLB) << "; "; + result << "uint_16: " << to_string(data.u16()) << "; "; + result << "float: " << to_string(data.f88()); + + return result.str(); +} +std::string OpenTherm::debug_error(OpenThermError &error) { + stringstream result; + result << "type: " << this->protocol_error_to_to_str(error.error_type) << "; "; + result << "data: "; + result << format_hex(error.data); + result << "; clock: " << to_string(clock_); + result << "; capture: " << bitset<32>(error.capture); + result << "; bit_pos: " << to_string(error.bit_pos); + + return result.str(); +} + +float OpenthermData::f88() { return ((float) this->s16()) / 256.0; } + +void OpenthermData::f88(float value) { this->s16((int16_t) (value * 256)); } + +uint16_t OpenthermData::u16() { + uint16_t const value = this->valueHB; + return (value << 8) | this->valueLB; +} + +void OpenthermData::u16(uint16_t value) { + this->valueLB = value & 0xFF; + this->valueHB = (value >> 8) & 0xFF; +} + +int16_t OpenthermData::s16() { + int16_t const value = this->valueHB; + return (value << 8) | this->valueLB; +} + +void OpenthermData::s16(int16_t value) { + this->valueLB = value & 0xFF; + this->valueHB = (value >> 8) & 0xFF; +} + +} // namespace opentherm +} // namespace esphome diff --git a/esphome/components/opentherm/opentherm.h b/esphome/components/opentherm/opentherm.h new file mode 100644 index 0000000000..609cfb6243 --- /dev/null +++ b/esphome/components/opentherm/opentherm.h @@ -0,0 +1,347 @@ +/* + * OpenTherm protocol implementation. Originally taken from https://github.com/jpraus/arduino-opentherm, but + * heavily modified to comply with ESPHome coding standards and provide better logging. + * Original code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International + * Public License, which is compatible with GPLv3 license, which covers C++ part of ESPHome project. + */ + +#pragma once + +#include +#include +#include +#include "esphome/core/hal.h" +#include "esphome/core/log.h" + +#if defined(ESP32) || defined(USE_ESP_IDF) +#include "driver/timer.h" +#endif + +namespace esphome { +namespace opentherm { + +// TODO: Account for immutable semantics change in hub.cpp when doing later installments of OpenTherm PR +template constexpr T read_bit(T value, uint8_t bit) { return (value >> bit) & 0x01; } + +template constexpr T set_bit(T value, uint8_t bit) { return value |= (1UL << bit); } + +template constexpr T clear_bit(T value, uint8_t bit) { return value &= ~(1UL << bit); } + +template constexpr T write_bit(T value, uint8_t bit, uint8_t bit_value) { + return bit_value ? setBit(value, bit) : clearBit(value, bit); +} + +enum OperationMode { + IDLE = 0, // no operation + + LISTEN = 1, // waiting for transmission to start + READ = 2, // reading 32-bit data frame + RECEIVED = 3, // data frame received with valid start and stop bit + + WRITE = 4, // writing data with timer_ + SENT = 5, // all data written to output + + ERROR_PROTOCOL = 8, // manchester protocol data transfer error + ERROR_TIMEOUT = 9 // read timeout +}; + +enum ProtocolErrorType { + NO_ERROR = 0, // No error + NO_TRANSITION = 1, // No transition in the middle of the bit + INVALID_STOP_BIT = 2, // Stop bit wasn't present when expected + PARITY_ERROR = 3, // Parity check didn't pass + NO_CHANGE_TOO_LONG = 4, // No level change for too much timer ticks +}; + +enum MessageType { + READ_DATA = 0, + READ_ACK = 4, + WRITE_DATA = 1, + WRITE_ACK = 5, + INVALID_DATA = 2, + DATA_INVALID = 6, + UNKNOWN_DATAID = 7 +}; + +enum MessageId { + STATUS = 0, + CH_SETPOINT = 1, + CONTROLLER_CONFIG = 2, + DEVICE_CONFIG = 3, + COMMAND_CODE = 4, + FAULT_FLAGS = 5, + REMOTE = 6, + COOLING_CONTROL = 7, + CH2_SETPOINT = 8, + CH_SETPOINT_OVERRIDE = 9, + TSP_COUNT = 10, + TSP_COMMAND = 11, + FHB_SIZE = 12, + FHB_COMMAND = 13, + MAX_MODULATION_LEVEL = 14, + MAX_BOILER_CAPACITY = 15, // u8_hb - u8_lb gives min modulation level + ROOM_SETPOINT = 16, + MODULATION_LEVEL = 17, + CH_WATER_PRESSURE = 18, + DHW_FLOW_RATE = 19, + DAY_TIME = 20, + DATE = 21, + YEAR = 22, + ROOM_SETPOINT_CH2 = 23, + ROOM_TEMP = 24, + FEED_TEMP = 25, + DHW_TEMP = 26, + OUTSIDE_TEMP = 27, + RETURN_WATER_TEMP = 28, + SOLAR_STORE_TEMP = 29, + SOLAR_COLLECT_TEMP = 30, + FEED_TEMP_CH2 = 31, + DHW2_TEMP = 32, + EXHAUST_TEMP = 33, + FAN_SPEED = 35, + FLAME_CURRENT = 36, + DHW_BOUNDS = 48, + CH_BOUNDS = 49, + OTC_CURVE_BOUNDS = 50, + DHW_SETPOINT = 56, + MAX_CH_SETPOINT = 57, + OTC_CURVE_RATIO = 58, + + // HVAC Specific Message IDs + HVAC_STATUS = 70, + REL_VENT_SETPOINT = 71, + DEVICE_VENT = 74, + REL_VENTILATION = 77, + REL_HUMID_EXHAUST = 78, + SUPPLY_INLET_TEMP = 80, + SUPPLY_OUTLET_TEMP = 81, + EXHAUST_INLET_TEMP = 82, + EXHAUST_OUTLET_TEMP = 83, + NOM_REL_VENTILATION = 87, + + OVERRIDE_FUNC = 100, + OEM_DIAGNOSTIC = 115, + BURNER_STARTS = 116, + CH_PUMP_STARTS = 117, + DHW_PUMP_STARTS = 118, + DHW_BURNER_STARTS = 119, + BURNER_HOURS = 120, + CH_PUMP_HOURS = 121, + DHW_PUMP_HOURS = 122, + DHW_BURNER_HOURS = 123, + OT_VERSION_CONTROLLER = 124, + OT_VERSION_DEVICE = 125, + VERSION_CONTROLLER = 126, + VERSION_DEVICE = 127 +}; + +enum BitPositions { STOP_BIT = 33 }; + +/** + * Structure to hold Opentherm data packet content. + * Use f88(), u16() or s16() functions to get appropriate value of data packet accoridng to id of message. + */ +struct OpenthermData { + uint8_t type; + uint8_t id; + uint8_t valueHB; + uint8_t valueLB; + + OpenthermData() : type(0), id(0), valueHB(0), valueLB(0) {} + + /** + * @return float representation of data packet value + */ + float f88(); + + /** + * @param float number to set as value of this data packet + */ + void f88(float value); + + /** + * @return unsigned 16b integer representation of data packet value + */ + uint16_t u16(); + + /** + * @param unsigned 16b integer number to set as value of this data packet + */ + void u16(uint16_t value); + + /** + * @return signed 16b integer representation of data packet value + */ + int16_t s16(); + + /** + * @param signed 16b integer number to set as value of this data packet + */ + void s16(int16_t value); +}; + +struct OpenThermError { + ProtocolErrorType error_type; + uint32_t capture; + uint8_t clock; + uint32_t data; + uint8_t bit_pos; +}; + +/** + * Opentherm static class that supports either listening or sending Opentherm data packets in the same time + */ +class OpenTherm { + public: + OpenTherm(InternalGPIOPin *in_pin, InternalGPIOPin *out_pin, int32_t device_timeout = 800); + + /** + * Setup pins. + */ + bool initialize(); + + /** + * Start listening for Opentherm data packet comming from line connected to given pin. + * If data packet is received then has_message() function returns true and data packet can be retrieved by calling + * get_message() function. If timeout > 0 then this function waits for incomming data package for timeout millis and + * if no data packet is recevived, error state is indicated by is_error() function. If either data packet is received + * or timeout is reached listening is stopped. + */ + void listen(); + + /** + * Use this function to check whether listen() function already captured a valid data packet. + * + * @return true if data packet has been captured from line by listen() function. + */ + bool has_message() { return mode_ == OperationMode::RECEIVED; } + + /** + * Use this to retrive data packed captured by listen() function. Data packet is ready when has_message() function + * returns true. This function can be called multiple times until stop() is called. + * + * @param data reference to data structure to which fill the data packet data. + * @return true if packet was ready and was filled into data structure passed, false otherwise. + */ + bool get_message(OpenthermData &data); + + /** + * Immediately send out Opentherm data packet to line connected on given pin. + * Completed data transfer is indicated by is_sent() function. + * Error state is indicated by is_error() function. + * + * @param data Opentherm data packet. + */ + void send(OpenthermData &data); + + /** + * Stops listening for data packet or sending out data packet and resets internal state of this class. + * Stops all timers and unattaches all interrupts. + */ + void stop(); + + /** + * Get protocol error details in case a protocol error occured. + * @param error reference to data structure to which fill the error details + * @return true if protocol error occured during last conversation, false otherwise. + */ + bool get_protocol_error(OpenThermError &error); + + /** + * Use this function to check whether send() function already finished sending data packed to line. + * + * @return true if data packet has been sent, false otherwise. + */ + bool is_sent() { return mode_ == OperationMode::SENT; } + + /** + * Indicates whether listinig or sending is not in progress. + * That also means that no timers are running and no interrupts are attached. + * + * @return true if listening nor sending is in progress. + */ + bool is_idle() { return mode_ == OperationMode::IDLE; } + + /** + * Indicates whether last listen() or send() operation ends up with an error. Includes both timeout and + * protocol errors. + * + * @return true if last listen() or send() operation ends up with an error. + */ + bool is_error() { return mode_ == OperationMode::ERROR_TIMEOUT || mode_ == OperationMode::ERROR_PROTOCOL; } + + /** + * Indicates whether last listen() or send() operation ends up with a *timeout* error + * @return true if last listen() or send() operation ends up with a *timeout* error. + */ + bool is_timeout() { return mode_ == OperationMode::ERROR_TIMEOUT; } + + /** + * Indicates whether last listen() or send() operation ends up with a *protocol* error + * @return true if last listen() or send() operation ends up with a *protocol* error. + */ + bool is_protocol_error() { return mode_ == OperationMode::ERROR_PROTOCOL; } + + bool is_active() { return mode_ == LISTEN || mode_ == READ || mode_ == WRITE; } + + OperationMode get_mode() { return mode_; } + + std::string debug_data(OpenthermData &data); + std::string debug_error(OpenThermError &error); + + const char *protocol_error_to_to_str(ProtocolErrorType error_type); + const char *message_type_to_str(MessageType message_type); + const char *operation_mode_to_str(OperationMode mode); + const char *message_id_to_str(MessageId id); + + static bool timer_isr(OpenTherm *arg); + +#ifdef ESP8266 + static void esp8266_timer_isr(); +#endif + + private: + InternalGPIOPin *in_pin_; + InternalGPIOPin *out_pin_; + ISRInternalGPIOPin isr_in_pin_; + ISRInternalGPIOPin isr_out_pin_; + +#if defined(ESP32) || defined(USE_ESP_IDF) + timer_group_t timer_group_; + timer_idx_t timer_idx_; +#endif + + OperationMode mode_; + ProtocolErrorType error_type_; + uint32_t capture_; + uint8_t clock_; + uint32_t data_; + uint8_t bit_pos_; + int32_t timeout_counter_; // <0 no timeout + + int32_t device_timeout_; + +#if defined(ESP32) || defined(USE_ESP_IDF) + bool init_esp32_timer_(); + void start_esp32_timer_(uint64_t alarm_value); +#endif + + void stop_timer_(); + + void read_(); // data detected start reading + void start_read_timer_(); // reading timer_ to sample at 1/5 of manchester code bit length (at 5kHz) + void start_write_timer_(); // writing timer_ to send manchester code (at 2kHz) + bool check_parity_(uint32_t val); + + void bit_read_(uint8_t value); + ProtocolErrorType verify_stop_bit_(uint8_t value); + void write_bit_(uint8_t high, uint8_t clock); + +#ifdef ESP8266 + // ESP8266 timer can accept callback with no parameters, so we have this hack to save a static instance of OpenTherm + static OpenTherm *instance_; +#endif +}; + +} // namespace opentherm +} // namespace esphome diff --git a/tests/components/opentherm/common.yaml b/tests/components/opentherm/common.yaml new file mode 100644 index 0000000000..4148b280d0 --- /dev/null +++ b/tests/components/opentherm/common.yaml @@ -0,0 +1,3 @@ +opentherm: + in_pin: 1 + out_pin: 2 diff --git a/tests/components/opentherm/test.esp32-ard.yaml b/tests/components/opentherm/test.esp32-ard.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/opentherm/test.esp32-ard.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/opentherm/test.esp32-c3-ard.yaml b/tests/components/opentherm/test.esp32-c3-ard.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/opentherm/test.esp32-c3-ard.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/opentherm/test.esp32-c3-idf.yaml b/tests/components/opentherm/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/opentherm/test.esp32-c3-idf.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/opentherm/test.esp32-idf.yaml b/tests/components/opentherm/test.esp32-idf.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/opentherm/test.esp32-idf.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/opentherm/test.esp8266-ard.yaml b/tests/components/opentherm/test.esp8266-ard.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/opentherm/test.esp8266-ard.yaml @@ -0,0 +1 @@ +<<: !include common.yaml From 7f00b5eb658e2871afb73c5988d49b8da0fbde8b Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 12 Sep 2024 14:08:41 +1200 Subject: [PATCH 2089/2101] [voice-assistant] Dont error on ``no_wake_word`` timeout error with streaming wake word (#7435) --- esphome/components/voice_assistant/voice_assistant.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index 577de630fb..a2210f188d 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -755,7 +755,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { message = std::move(arg.value); } } - if (code == "wake-word-timeout" || code == "wake_word_detection_aborted") { + if (code == "wake-word-timeout" || code == "wake_word_detection_aborted" || code == "no_wake_word") { // Don't change state here since either the "tts-end" or "run-end" events will do it. return; } else if (code == "wake-provider-missing" || code == "wake-engine-missing") { From 80e3de94d3d581f91f0197ea2ab49c2c5b6fca45 Mon Sep 17 00:00:00 2001 From: Tomer <57483589+tomer-w@users.noreply.github.com> Date: Fri, 13 Sep 2024 03:56:04 +0300 Subject: [PATCH 2090/2101] =?UTF-8?q?Improve=20manufacturer=20data=20traci?= =?UTF-8?q?ng=20to=20identify=20BLE=20devices=20a=20bit=20easie=E2=80=A6?= =?UTF-8?q?=20(#7332)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/ble_presence/binary_sensor.py | 4 ++-- esphome/components/esp32_ble/ble_uuid.cpp | 7 +++++++ esphome/components/esp32_ble/ble_uuid.h | 1 + .../esp32_ble_tracker/esp32_ble_tracker.cpp | 20 ++++++++++--------- .../esp32_ble_tracker/esp32_ble_tracker.h | 6 +++--- 5 files changed, 24 insertions(+), 14 deletions(-) diff --git a/esphome/components/ble_presence/binary_sensor.py b/esphome/components/ble_presence/binary_sensor.py index d1fdc80289..3a0f1ade98 100644 --- a/esphome/components/ble_presence/binary_sensor.py +++ b/esphome/components/ble_presence/binary_sensor.py @@ -41,7 +41,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_SERVICE_UUID): esp32_ble_tracker.bt_uuid, cv.Optional(CONF_IBEACON_MAJOR): cv.uint16_t, cv.Optional(CONF_IBEACON_MINOR): cv.uint16_t, - cv.Optional(CONF_IBEACON_UUID): cv.uuid, + cv.Optional(CONF_IBEACON_UUID): esp32_ble_tracker.bt_uuid, cv.Optional(CONF_TIMEOUT, default="5min"): cv.positive_time_period, cv.Optional(CONF_MIN_RSSI): cv.All( cv.decibel, cv.int_range(min=-100, max=-30) @@ -83,7 +83,7 @@ async def to_code(config): cg.add(var.set_service_uuid128(uuid128)) if ibeacon_uuid := config.get(CONF_IBEACON_UUID): - ibeacon_uuid = esp32_ble_tracker.as_hex_array(str(ibeacon_uuid)) + ibeacon_uuid = esp32_ble_tracker.as_reversed_hex_array(ibeacon_uuid) cg.add(var.set_ibeacon_uuid(ibeacon_uuid)) if (ibeacon_major := config.get(CONF_IBEACON_MAJOR)) is not None: diff --git a/esphome/components/esp32_ble/ble_uuid.cpp b/esphome/components/esp32_ble/ble_uuid.cpp index 57c2f9df94..07ac719434 100644 --- a/esphome/components/esp32_ble/ble_uuid.cpp +++ b/esphome/components/esp32_ble/ble_uuid.cpp @@ -31,6 +31,13 @@ ESPBTUUID ESPBTUUID::from_raw(const uint8_t *data) { memcpy(ret.uuid_.uuid.uuid128, data, ESP_UUID_LEN_128); return ret; } +ESPBTUUID ESPBTUUID::from_raw_reversed(const uint8_t *data) { + ESPBTUUID ret; + ret.uuid_.len = ESP_UUID_LEN_128; + for (int i = 0; i < ESP_UUID_LEN_128; i++) + ret.uuid_.uuid.uuid128[ESP_UUID_LEN_128 - 1 - i] = data[i]; + return ret; +} ESPBTUUID ESPBTUUID::from_raw(const std::string &data) { ESPBTUUID ret; if (data.length() == 4) { diff --git a/esphome/components/esp32_ble/ble_uuid.h b/esphome/components/esp32_ble/ble_uuid.h index 790a57c59d..d90db3a599 100644 --- a/esphome/components/esp32_ble/ble_uuid.h +++ b/esphome/components/esp32_ble/ble_uuid.h @@ -20,6 +20,7 @@ class ESPBTUUID { static ESPBTUUID from_uint32(uint32_t uuid); static ESPBTUUID from_raw(const uint8_t *data); + static ESPBTUUID from_raw_reversed(const uint8_t *data); static ESPBTUUID from_raw(const std::string &data); diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp index d154d4e519..74b4b9aa89 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp @@ -462,14 +462,16 @@ void ESPBTDevice::parse_scan_rst(const esp_ble_gap_cb_param_t::ble_scan_result_e ESP_LOGVV(TAG, " Service UUID: %s", uuid.to_string().c_str()); } for (auto &data : this->manufacturer_datas_) { - ESP_LOGVV(TAG, " Manufacturer data: %s", format_hex_pretty(data.data).c_str()); - if (this->get_ibeacon().has_value()) { - auto ibeacon = this->get_ibeacon().value(); - ESP_LOGVV(TAG, " iBeacon data:"); - ESP_LOGVV(TAG, " UUID: %s", ibeacon.get_uuid().to_string().c_str()); - ESP_LOGVV(TAG, " Major: %u", ibeacon.get_major()); - ESP_LOGVV(TAG, " Minor: %u", ibeacon.get_minor()); - ESP_LOGVV(TAG, " TXPower: %d", ibeacon.get_signal_power()); + auto ibeacon = ESPBLEiBeacon::from_manufacturer_data(data); + if (ibeacon.has_value()) { + ESP_LOGVV(TAG, " Manufacturer iBeacon:"); + ESP_LOGVV(TAG, " UUID: %s", ibeacon.value().get_uuid().to_string().c_str()); + ESP_LOGVV(TAG, " Major: %u", ibeacon.value().get_major()); + ESP_LOGVV(TAG, " Minor: %u", ibeacon.value().get_minor()); + ESP_LOGVV(TAG, " TXPower: %d", ibeacon.value().get_signal_power()); + } else { + ESP_LOGVV(TAG, " Manufacturer ID: %s, data: %s", data.uuid.to_string().c_str(), + format_hex_pretty(data.data).c_str()); } } for (auto &data : this->service_datas_) { @@ -478,7 +480,7 @@ void ESPBTDevice::parse_scan_rst(const esp_ble_gap_cb_param_t::ble_scan_result_e ESP_LOGVV(TAG, " Data: %s", format_hex_pretty(data.data).c_str()); } - ESP_LOGVV(TAG, "Adv data: %s", format_hex_pretty(param.ble_adv, param.adv_data_len + param.scan_rsp_len).c_str()); + ESP_LOGVV(TAG, " Adv data: %s", format_hex_pretty(param.ble_adv, param.adv_data_len + param.scan_rsp_len).c_str()); #endif } void ESPBTDevice::parse_adv_(const esp_ble_gap_cb_param_t::ble_scan_result_evt_param ¶m) { diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h index 3db7a54f6e..d2bb6a6e6d 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h @@ -44,10 +44,10 @@ class ESPBLEiBeacon { ESPBLEiBeacon(const uint8_t *data); static optional from_manufacturer_data(const ServiceData &data); - uint16_t get_major() { return ((this->beacon_data_.major & 0xFF) << 8) | (this->beacon_data_.major >> 8); } - uint16_t get_minor() { return ((this->beacon_data_.minor & 0xFF) << 8) | (this->beacon_data_.minor >> 8); } + uint16_t get_major() { return byteswap(this->beacon_data_.major); } + uint16_t get_minor() { return byteswap(this->beacon_data_.minor); } int8_t get_signal_power() { return this->beacon_data_.signal_power; } - ESPBTUUID get_uuid() { return ESPBTUUID::from_raw(this->beacon_data_.proximity_uuid); } + ESPBTUUID get_uuid() { return ESPBTUUID::from_raw_reversed(this->beacon_data_.proximity_uuid); } protected: struct { From 5d8fb7cdf4a21b649427318cd9d883bb679c8d80 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 16 Sep 2024 10:01:34 +1200 Subject: [PATCH 2091/2101] Bump version to 2024.9.0b2 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index fb745fd506..ce6b9f3d01 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.9.0b1" +__version__ = "2024.9.0b2" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From f652cd3851d17a4434876ab546021c6f698cb47f Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Mon, 16 Sep 2024 08:42:45 +1000 Subject: [PATCH 2092/2101] [st7701s] Make use of IDF5.x to speed up display operations (#7447) --- esphome/components/st7701s/st7701s.cpp | 32 +++++++++++++++++++------- esphome/components/st7701s/st7701s.h | 2 ++ 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/esphome/components/st7701s/st7701s.cpp b/esphome/components/st7701s/st7701s.cpp index 7f02fe1774..7248bc044e 100644 --- a/esphome/components/st7701s/st7701s.cpp +++ b/esphome/components/st7701s/st7701s.cpp @@ -8,8 +8,22 @@ namespace st7701s { void ST7701S::setup() { esph_log_config(TAG, "Setting up ST7701S"); this->spi_setup(); + this->write_init_sequence_(); +} + +// called after a delay after writing the init sequence +void ST7701S::complete_setup_() { + this->write_command_(SLEEP_OUT); + this->write_command_(DISPLAY_ON); + this->spi_teardown(); // SPI not needed after this + delay(10); + esp_lcd_rgb_panel_config_t config{}; config.flags.fb_in_psram = 1; +#if ESP_IDF_VERSION_MAJOR >= 5 + config.bounce_buffer_size_px = this->width_ * 10; + config.num_fbs = 1; +#endif // ESP_IDF_VERSION_MAJOR config.timings.h_res = this->width_; config.timings.v_res = this->height_; config.timings.hsync_pulse_width = this->hsync_pulse_width_; @@ -21,7 +35,6 @@ void ST7701S::setup() { config.timings.flags.pclk_active_neg = this->pclk_inverted_; config.timings.pclk_hz = this->pclk_frequency_; config.clk_src = LCD_CLK_SRC_PLL160M; - config.sram_trans_align = 64; config.psram_trans_align = 64; size_t data_pin_count = sizeof(this->data_pins_) / sizeof(this->data_pins_[0]); for (size_t i = 0; i != data_pin_count; i++) { @@ -34,15 +47,21 @@ 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)); } - ESP_ERROR_CHECK(esp_lcd_panel_reset(this->handle_)); - ESP_ERROR_CHECK(esp_lcd_panel_init(this->handle_)); - this->write_init_sequence_(); esph_log_config(TAG, "ST7701S setup complete"); } +void ST7701S::loop() { +#if ESP_IDF_VERSION_MAJOR >= 5 + if (this->handle_ != nullptr) + esp_lcd_rgb_panel_restart(this->handle_); +#endif // ESP_IDF_VERSION_MAJOR +} + void ST7701S::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) { if (w <= 0 || h <= 0) @@ -160,10 +179,7 @@ void ST7701S::write_init_sequence_() { this->write_data_(val); ESP_LOGD(TAG, "write MADCTL %X", val); this->write_command_(this->invert_colors_ ? INVERT_ON : INVERT_OFF); - this->set_timeout(120, [this] { - this->write_command_(SLEEP_OUT); - this->write_command_(DISPLAY_ON); - }); + this->set_timeout(120, [this] { this->complete_setup_(); }); } void ST7701S::dump_config() { diff --git a/esphome/components/st7701s/st7701s.h b/esphome/components/st7701s/st7701s.h index 80e5b81f4a..a1e3c2e54a 100644 --- a/esphome/components/st7701s/st7701s.h +++ b/esphome/components/st7701s/st7701s.h @@ -33,6 +33,8 @@ class ST7701S : public display::Display, public: void update() override { this->do_update_(); } void setup() override; + void complete_setup_(); + void loop() 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; From 857d79dc714f123dabafe46eacbbbae0e979a19c Mon Sep 17 00:00:00 2001 From: Michael Hansen Date: Sun, 15 Sep 2024 18:46:54 -0500 Subject: [PATCH 2093/2101] Add sample_bytes to media player supported format (#7451) --- esphome/components/api/api.proto | 1 + esphome/components/api/api_connection.cpp | 1 + esphome/components/api/api_pb2.cpp | 10 ++++++++++ esphome/components/api/api_pb2.h | 1 + esphome/components/media_player/media_player.h | 1 + 5 files changed, 14 insertions(+) diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index 1c40e8014e..a966643d30 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -1118,6 +1118,7 @@ message MediaPlayerSupportedFormat { uint32 sample_rate = 2; uint32 num_channels = 3; MediaPlayerFormatPurpose purpose = 4; + uint32 sample_bytes = 5; } message ListEntitiesMediaPlayerResponse { option (id) = 63; diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 6b7051a704..20e9a45314 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1032,6 +1032,7 @@ bool APIConnection::send_media_player_info(media_player::MediaPlayer *media_play media_format.sample_rate = supported_format.sample_rate; media_format.num_channels = supported_format.num_channels; media_format.purpose = static_cast(supported_format.purpose); + media_format.sample_bytes = supported_format.sample_bytes; msg.supported_formats.push_back(media_format); } diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index 2a1552d6fc..955f17612a 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -5149,6 +5149,10 @@ bool MediaPlayerSupportedFormat::decode_varint(uint32_t field_id, ProtoVarInt va this->purpose = value.as_enum(); return true; } + case 5: { + this->sample_bytes = value.as_uint32(); + return true; + } default: return false; } @@ -5168,6 +5172,7 @@ void MediaPlayerSupportedFormat::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(2, this->sample_rate); buffer.encode_uint32(3, this->num_channels); buffer.encode_enum(4, this->purpose); + buffer.encode_uint32(5, this->sample_bytes); } #ifdef HAS_PROTO_MESSAGE_DUMP void MediaPlayerSupportedFormat::dump_to(std::string &out) const { @@ -5190,6 +5195,11 @@ void MediaPlayerSupportedFormat::dump_to(std::string &out) const { out.append(" purpose: "); out.append(proto_enum_to_string(this->purpose)); out.append("\n"); + + out.append(" sample_bytes: "); + sprintf(buffer, "%" PRIu32, this->sample_bytes); + out.append(buffer); + out.append("\n"); out.append("}"); } #endif diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index 6fab1f57e0..1ce6482b09 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -1277,6 +1277,7 @@ class MediaPlayerSupportedFormat : public ProtoMessage { uint32_t sample_rate{0}; uint32_t num_channels{0}; enums::MediaPlayerFormatPurpose purpose{}; + uint32_t sample_bytes{0}; void encode(ProtoWriteBuffer buffer) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; diff --git a/esphome/components/media_player/media_player.h b/esphome/components/media_player/media_player.h index 26bef55afc..78b3ed6216 100644 --- a/esphome/components/media_player/media_player.h +++ b/esphome/components/media_player/media_player.h @@ -37,6 +37,7 @@ struct MediaPlayerSupportedFormat { uint32_t sample_rate; uint32_t num_channels; MediaPlayerFormatPurpose purpose; + uint32_t sample_bytes; }; class MediaPlayer; From bfde7fd9d796a2e65f92e6d074e432de00a8989b Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 16 Sep 2024 12:32:39 +1200 Subject: [PATCH 2094/2101] [docker] Bump git from 1:2.39.2-1.1 to 1:2.39.5-0+deb12u1 (#7452) --- docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index e255f4e2fc..85823687c2 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -33,7 +33,7 @@ RUN \ python3-venv=3.11.2-1+b1 \ python3-wheel=0.38.4-2 \ iputils-ping=3:20221126-1 \ - git=1:2.39.2-1.1 \ + git=1:2.39.5-0+deb12u1 \ curl=7.88.1-10+deb12u7 \ openssh-client=1:9.2p1-2+deb12u3 \ python3-cffi=1.15.1-5 \ From e7fe9b374fb8ac9c1e7c5ab5869f8114509fbe6a Mon Sep 17 00:00:00 2001 From: Michael Hansen Date: Sun, 15 Sep 2024 18:46:54 -0500 Subject: [PATCH 2095/2101] Add sample_bytes to media player supported format (#7451) --- esphome/components/api/api.proto | 1 + esphome/components/api/api_connection.cpp | 1 + esphome/components/api/api_pb2.cpp | 10 ++++++++++ esphome/components/api/api_pb2.h | 1 + esphome/components/media_player/media_player.h | 1 + 5 files changed, 14 insertions(+) diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index 1c40e8014e..a966643d30 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -1118,6 +1118,7 @@ message MediaPlayerSupportedFormat { uint32 sample_rate = 2; uint32 num_channels = 3; MediaPlayerFormatPurpose purpose = 4; + uint32 sample_bytes = 5; } message ListEntitiesMediaPlayerResponse { option (id) = 63; diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 6b7051a704..20e9a45314 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1032,6 +1032,7 @@ bool APIConnection::send_media_player_info(media_player::MediaPlayer *media_play media_format.sample_rate = supported_format.sample_rate; media_format.num_channels = supported_format.num_channels; media_format.purpose = static_cast(supported_format.purpose); + media_format.sample_bytes = supported_format.sample_bytes; msg.supported_formats.push_back(media_format); } diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index 2a1552d6fc..955f17612a 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -5149,6 +5149,10 @@ bool MediaPlayerSupportedFormat::decode_varint(uint32_t field_id, ProtoVarInt va this->purpose = value.as_enum(); return true; } + case 5: { + this->sample_bytes = value.as_uint32(); + return true; + } default: return false; } @@ -5168,6 +5172,7 @@ void MediaPlayerSupportedFormat::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(2, this->sample_rate); buffer.encode_uint32(3, this->num_channels); buffer.encode_enum(4, this->purpose); + buffer.encode_uint32(5, this->sample_bytes); } #ifdef HAS_PROTO_MESSAGE_DUMP void MediaPlayerSupportedFormat::dump_to(std::string &out) const { @@ -5190,6 +5195,11 @@ void MediaPlayerSupportedFormat::dump_to(std::string &out) const { out.append(" purpose: "); out.append(proto_enum_to_string(this->purpose)); out.append("\n"); + + out.append(" sample_bytes: "); + sprintf(buffer, "%" PRIu32, this->sample_bytes); + out.append(buffer); + out.append("\n"); out.append("}"); } #endif diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index 6fab1f57e0..1ce6482b09 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -1277,6 +1277,7 @@ class MediaPlayerSupportedFormat : public ProtoMessage { uint32_t sample_rate{0}; uint32_t num_channels{0}; enums::MediaPlayerFormatPurpose purpose{}; + uint32_t sample_bytes{0}; void encode(ProtoWriteBuffer buffer) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; diff --git a/esphome/components/media_player/media_player.h b/esphome/components/media_player/media_player.h index 26bef55afc..78b3ed6216 100644 --- a/esphome/components/media_player/media_player.h +++ b/esphome/components/media_player/media_player.h @@ -37,6 +37,7 @@ struct MediaPlayerSupportedFormat { uint32_t sample_rate; uint32_t num_channels; MediaPlayerFormatPurpose purpose; + uint32_t sample_bytes; }; class MediaPlayer; From 6483ceb6eb0b4aeee7f2fe1dc9c2cf8d5f3d448d Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 16 Sep 2024 12:32:39 +1200 Subject: [PATCH 2096/2101] [docker] Bump git from 1:2.39.2-1.1 to 1:2.39.5-0+deb12u1 (#7452) --- docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index e255f4e2fc..85823687c2 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -33,7 +33,7 @@ RUN \ python3-venv=3.11.2-1+b1 \ python3-wheel=0.38.4-2 \ iputils-ping=3:20221126-1 \ - git=1:2.39.2-1.1 \ + git=1:2.39.5-0+deb12u1 \ curl=7.88.1-10+deb12u7 \ openssh-client=1:9.2p1-2+deb12u3 \ python3-cffi=1.15.1-5 \ From a63b9a9e0c58b27279ead5d3238273fce45cd6ba Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 16 Sep 2024 13:17:06 +1200 Subject: [PATCH 2097/2101] Bump version to 2024.9.0b3 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index ce6b9f3d01..24deba1f15 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.9.0b2" +__version__ = "2024.9.0b3" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 3835ad8c1f793f19d21cf2a158744ae6228ae0b4 Mon Sep 17 00:00:00 2001 From: Michael Hansen Date: Sun, 15 Sep 2024 20:40:45 -0500 Subject: [PATCH 2098/2101] Add voice assistant configuration messages (#7445) --- esphome/components/api/api.proto | 30 +++++ esphome/components/api/api_pb2.cpp | 143 +++++++++++++++++++++ esphome/components/api/api_pb2.h | 48 +++++++ esphome/components/api/api_pb2_service.cpp | 35 +++++ esphome/components/api/api_pb2_service.h | 9 ++ 5 files changed, 265 insertions(+) diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index a966643d30..92fb57b711 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -1571,6 +1571,36 @@ message VoiceAssistantAnnounceFinished { bool success = 1; } +message VoiceAssistantWakeWord { + uint32 id = 1; + string wake_word = 2; + repeated string trained_languages = 3; +} + +message VoiceAssistantConfigurationRequest { + option (id) = 121; + option (source) = SOURCE_CLIENT; + option (ifdef) = "USE_VOICE_ASSISTANT"; +} + +message VoiceAssistantConfigurationResponse { + option (id) = 122; + option (source) = SOURCE_SERVER; + option (ifdef) = "USE_VOICE_ASSISTANT"; + + repeated VoiceAssistantWakeWord available_wake_words = 1; + repeated uint32 active_wake_words = 2; + uint32 max_active_wake_words = 3; +} + +message VoiceAssistantSetConfiguration { + option (id) = 123; + option (source) = SOURCE_CLIENT; + option (ifdef) = "USE_VOICE_ASSISTANT"; + + repeated uint32 active_wake_words = 1; +} + // ==================== ALARM CONTROL PANEL ==================== enum AlarmControlPanelState { ALARM_STATE_DISARMED = 0; diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index 955f17612a..791de29511 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -7124,6 +7124,149 @@ void VoiceAssistantAnnounceFinished::dump_to(std::string &out) const { out.append("}"); } #endif +bool VoiceAssistantWakeWord::decode_varint(uint32_t field_id, ProtoVarInt value) { + switch (field_id) { + case 1: { + this->id = value.as_uint32(); + return true; + } + default: + return false; + } +} +bool VoiceAssistantWakeWord::decode_length(uint32_t field_id, ProtoLengthDelimited value) { + switch (field_id) { + case 2: { + this->wake_word = value.as_string(); + return true; + } + case 3: { + this->trained_languages.push_back(value.as_string()); + return true; + } + default: + return false; + } +} +void VoiceAssistantWakeWord::encode(ProtoWriteBuffer buffer) const { + buffer.encode_uint32(1, this->id); + buffer.encode_string(2, this->wake_word); + for (auto &it : this->trained_languages) { + buffer.encode_string(3, it, true); + } +} +#ifdef HAS_PROTO_MESSAGE_DUMP +void VoiceAssistantWakeWord::dump_to(std::string &out) const { + __attribute__((unused)) char buffer[64]; + out.append("VoiceAssistantWakeWord {\n"); + out.append(" id: "); + sprintf(buffer, "%" PRIu32, this->id); + out.append(buffer); + out.append("\n"); + + out.append(" wake_word: "); + out.append("'").append(this->wake_word).append("'"); + out.append("\n"); + + for (const auto &it : this->trained_languages) { + out.append(" trained_languages: "); + out.append("'").append(it).append("'"); + out.append("\n"); + } + out.append("}"); +} +#endif +void VoiceAssistantConfigurationRequest::encode(ProtoWriteBuffer buffer) const {} +#ifdef HAS_PROTO_MESSAGE_DUMP +void VoiceAssistantConfigurationRequest::dump_to(std::string &out) const { + out.append("VoiceAssistantConfigurationRequest {}"); +} +#endif +bool VoiceAssistantConfigurationResponse::decode_varint(uint32_t field_id, ProtoVarInt value) { + switch (field_id) { + case 2: { + this->active_wake_words.push_back(value.as_uint32()); + return true; + } + case 3: { + this->max_active_wake_words = value.as_uint32(); + return true; + } + default: + return false; + } +} +bool VoiceAssistantConfigurationResponse::decode_length(uint32_t field_id, ProtoLengthDelimited value) { + switch (field_id) { + case 1: { + this->available_wake_words.push_back(value.as_message()); + return true; + } + default: + return false; + } +} +void VoiceAssistantConfigurationResponse::encode(ProtoWriteBuffer buffer) const { + for (auto &it : this->available_wake_words) { + buffer.encode_message(1, it, true); + } + for (auto &it : this->active_wake_words) { + buffer.encode_uint32(2, it, true); + } + buffer.encode_uint32(3, this->max_active_wake_words); +} +#ifdef HAS_PROTO_MESSAGE_DUMP +void VoiceAssistantConfigurationResponse::dump_to(std::string &out) const { + __attribute__((unused)) char buffer[64]; + out.append("VoiceAssistantConfigurationResponse {\n"); + for (const auto &it : this->available_wake_words) { + out.append(" available_wake_words: "); + it.dump_to(out); + out.append("\n"); + } + + for (const auto &it : this->active_wake_words) { + out.append(" active_wake_words: "); + sprintf(buffer, "%" PRIu32, it); + out.append(buffer); + out.append("\n"); + } + + out.append(" max_active_wake_words: "); + sprintf(buffer, "%" PRIu32, this->max_active_wake_words); + out.append(buffer); + out.append("\n"); + out.append("}"); +} +#endif +bool VoiceAssistantSetConfiguration::decode_varint(uint32_t field_id, ProtoVarInt value) { + switch (field_id) { + case 1: { + this->active_wake_words.push_back(value.as_uint32()); + return true; + } + default: + return false; + } +} +void VoiceAssistantSetConfiguration::encode(ProtoWriteBuffer buffer) const { + for (auto &it : this->active_wake_words) { + buffer.encode_uint32(1, it, true); + } +} +#ifdef HAS_PROTO_MESSAGE_DUMP +void VoiceAssistantSetConfiguration::dump_to(std::string &out) const { + __attribute__((unused)) char buffer[64]; + out.append("VoiceAssistantSetConfiguration {\n"); + for (const auto &it : this->active_wake_words) { + out.append(" active_wake_words: "); + sprintf(buffer, "%" PRIu32, it); + out.append(buffer); + out.append("\n"); + } + out.append("}"); +} +#endif bool ListEntitiesAlarmControlPanelResponse::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { case 6: { diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index 1ce6482b09..8631884f94 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -1849,6 +1849,54 @@ class VoiceAssistantAnnounceFinished : public ProtoMessage { protected: bool decode_varint(uint32_t field_id, ProtoVarInt value) override; }; +class VoiceAssistantWakeWord : public ProtoMessage { + public: + uint32_t id{0}; + std::string wake_word{}; + std::vector trained_languages{}; + void encode(ProtoWriteBuffer buffer) const override; +#ifdef HAS_PROTO_MESSAGE_DUMP + void dump_to(std::string &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 VoiceAssistantConfigurationRequest : public ProtoMessage { + public: + void encode(ProtoWriteBuffer buffer) const override; +#ifdef HAS_PROTO_MESSAGE_DUMP + void dump_to(std::string &out) const override; +#endif + + protected: +}; +class VoiceAssistantConfigurationResponse : public ProtoMessage { + public: + std::vector available_wake_words{}; + std::vector active_wake_words{}; + uint32_t max_active_wake_words{0}; + void encode(ProtoWriteBuffer buffer) const override; +#ifdef HAS_PROTO_MESSAGE_DUMP + void dump_to(std::string &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 VoiceAssistantSetConfiguration : public ProtoMessage { + public: + std::vector active_wake_words{}; + void encode(ProtoWriteBuffer buffer) const override; +#ifdef HAS_PROTO_MESSAGE_DUMP + void dump_to(std::string &out) const override; +#endif + + protected: + bool decode_varint(uint32_t field_id, ProtoVarInt value) override; +}; class ListEntitiesAlarmControlPanelResponse : public ProtoMessage { public: std::string object_id{}; diff --git a/esphome/components/api/api_pb2_service.cpp b/esphome/components/api/api_pb2_service.cpp index faa977389a..454f20d50a 100644 --- a/esphome/components/api/api_pb2_service.cpp +++ b/esphome/components/api/api_pb2_service.cpp @@ -496,6 +496,19 @@ bool APIServerConnectionBase::send_voice_assistant_announce_finished(const Voice return this->send_message_(msg, 120); } #endif +#ifdef USE_VOICE_ASSISTANT +#endif +#ifdef USE_VOICE_ASSISTANT +bool APIServerConnectionBase::send_voice_assistant_configuration_response( + const VoiceAssistantConfigurationResponse &msg) { +#ifdef HAS_PROTO_MESSAGE_DUMP + ESP_LOGVV(TAG, "send_voice_assistant_configuration_response: %s", msg.dump().c_str()); +#endif + return this->send_message_(msg, 122); +} +#endif +#ifdef USE_VOICE_ASSISTANT +#endif #ifdef USE_ALARM_CONTROL_PANEL bool APIServerConnectionBase::send_list_entities_alarm_control_panel_response( const ListEntitiesAlarmControlPanelResponse &msg) { @@ -1156,6 +1169,28 @@ bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, ESP_LOGVV(TAG, "on_voice_assistant_announce_request: %s", msg.dump().c_str()); #endif this->on_voice_assistant_announce_request(msg); +#endif + break; + } + case 121: { +#ifdef USE_VOICE_ASSISTANT + 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()); +#endif + this->on_voice_assistant_configuration_request(msg); +#endif + break; + } + case 123: { +#ifdef USE_VOICE_ASSISTANT + 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()); +#endif + this->on_voice_assistant_set_configuration(msg); #endif break; } diff --git a/esphome/components/api/api_pb2_service.h b/esphome/components/api/api_pb2_service.h index f3803ad628..e69954f7ab 100644 --- a/esphome/components/api/api_pb2_service.h +++ b/esphome/components/api/api_pb2_service.h @@ -253,6 +253,15 @@ class APIServerConnectionBase : public ProtoService { #ifdef USE_VOICE_ASSISTANT bool send_voice_assistant_announce_finished(const VoiceAssistantAnnounceFinished &msg); #endif +#ifdef USE_VOICE_ASSISTANT + virtual void on_voice_assistant_configuration_request(const VoiceAssistantConfigurationRequest &value){}; +#endif +#ifdef USE_VOICE_ASSISTANT + bool send_voice_assistant_configuration_response(const VoiceAssistantConfigurationResponse &msg); +#endif +#ifdef USE_VOICE_ASSISTANT + virtual void on_voice_assistant_set_configuration(const VoiceAssistantSetConfiguration &value){}; +#endif #ifdef USE_ALARM_CONTROL_PANEL bool send_list_entities_alarm_control_panel_response(const ListEntitiesAlarmControlPanelResponse &msg); #endif From 73e469ae528cb4a522f8125837416f97a91e50de Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 16 Sep 2024 13:43:45 +1200 Subject: [PATCH 2099/2101] [modbus_controller] Fix linting and formatting issues (#7441) --- .../components/modbus_controller/__init__.py | 12 ++++++---- .../binary_sensor/__init__.py | 14 +++++------ .../modbus_controller/number/__init__.py | 11 ++++----- .../modbus_controller/output/__init__.py | 24 ++++++++----------- .../modbus_controller/select/__init__.py | 2 +- .../modbus_controller/sensor/__init__.py | 16 ++++++------- .../modbus_controller/switch/__init__.py | 15 ++++++------ .../modbus_controller/text_sensor/__init__.py | 19 +++++++-------- 8 files changed, 54 insertions(+), 59 deletions(-) diff --git a/esphome/components/modbus_controller/__init__.py b/esphome/components/modbus_controller/__init__.py index 6917807b07..488baa245a 100644 --- a/esphome/components/modbus_controller/__init__.py +++ b/esphome/components/modbus_controller/__init__.py @@ -1,27 +1,29 @@ import binascii -import esphome.codegen as cg -import esphome.config_validation as cv + from esphome import automation +import esphome.codegen as cg from esphome.components import modbus +import esphome.config_validation as cv from esphome.const import ( CONF_ADDRESS, CONF_ID, - CONF_NAME, CONF_LAMBDA, + CONF_NAME, CONF_OFFSET, CONF_TRIGGER_ID, ) from esphome.cpp_helpers import logging + from .const import ( CONF_ALLOW_DUPLICATE_COMMANDS, CONF_BITMASK, CONF_BYTE_OFFSET, CONF_COMMAND_THROTTLE, - CONF_OFFLINE_SKIP_UPDATES, CONF_CUSTOM_COMMAND, CONF_FORCE_NEW_RANGE, - CONF_MODBUS_CONTROLLER_ID, CONF_MAX_CMD_RETRIES, + CONF_MODBUS_CONTROLLER_ID, + CONF_OFFLINE_SKIP_UPDATES, CONF_ON_COMMAND_SENT, CONF_REGISTER_COUNT, CONF_REGISTER_TYPE, diff --git a/esphome/components/modbus_controller/binary_sensor/__init__.py b/esphome/components/modbus_controller/binary_sensor/__init__.py index 5315167479..2ae008f630 100644 --- a/esphome/components/modbus_controller/binary_sensor/__init__.py +++ b/esphome/components/modbus_controller/binary_sensor/__init__.py @@ -1,16 +1,16 @@ +import esphome.codegen as cg from esphome.components import binary_sensor import esphome.config_validation as cv -import esphome.codegen as cg - from esphome.const import CONF_ADDRESS, CONF_ID + from .. import ( - add_modbus_base_properties, - modbus_controller_ns, - modbus_calc_properties, - validate_modbus_register, + MODBUS_REGISTER_TYPE, ModbusItemBaseSchema, SensorItem, - MODBUS_REGISTER_TYPE, + add_modbus_base_properties, + modbus_calc_properties, + modbus_controller_ns, + validate_modbus_register, ) from ..const import ( CONF_BITMASK, diff --git a/esphome/components/modbus_controller/number/__init__.py b/esphome/components/modbus_controller/number/__init__.py index fe99b28a00..b5efd7abf0 100644 --- a/esphome/components/modbus_controller/number/__init__.py +++ b/esphome/components/modbus_controller/number/__init__.py @@ -1,6 +1,6 @@ import esphome.codegen as cg -import esphome.config_validation as cv from esphome.components import number +import esphome.config_validation as cv from esphome.const import ( CONF_ADDRESS, CONF_ID, @@ -12,14 +12,13 @@ from esphome.const import ( from .. import ( MODBUS_WRITE_REGISTER_TYPE, - add_modbus_base_properties, - modbus_controller_ns, - modbus_calc_properties, + SENSOR_VALUE_TYPE, ModbusItemBaseSchema, SensorItem, - SENSOR_VALUE_TYPE, + add_modbus_base_properties, + modbus_calc_properties, + modbus_controller_ns, ) - from ..const import ( CONF_BITMASK, CONF_CUSTOM_COMMAND, diff --git a/esphome/components/modbus_controller/output/__init__.py b/esphome/components/modbus_controller/output/__init__.py index 1bf989ce8b..1800a90d57 100644 --- a/esphome/components/modbus_controller/output/__init__.py +++ b/esphome/components/modbus_controller/output/__init__.py @@ -1,20 +1,15 @@ import esphome.codegen as cg -import esphome.config_validation as cv from esphome.components import output -from esphome.const import ( - CONF_ADDRESS, - CONF_ID, - CONF_MULTIPLY, -) +import esphome.config_validation as cv +from esphome.const import CONF_ADDRESS, CONF_ID, CONF_MULTIPLY from .. import ( - modbus_controller_ns, - modbus_calc_properties, + SENSOR_VALUE_TYPE, ModbusItemBaseSchema, SensorItem, - SENSOR_VALUE_TYPE, + modbus_calc_properties, + modbus_controller_ns, ) - from ..const import ( CONF_MODBUS_CONTROLLER_ID, CONF_REGISTER_TYPE, @@ -65,6 +60,7 @@ CONFIG_SCHEMA = cv.typed_schema( async def to_code(config): byte_offset, reg_count = modbus_calc_properties(config) # Binary Output + write_template = None if config[CONF_REGISTER_TYPE] == "coil": var = cg.new_Pvariable( config[CONF_ID], @@ -72,7 +68,7 @@ async def to_code(config): byte_offset, ) if CONF_WRITE_LAMBDA in config: - template_ = await cg.process_lambda( + write_template = await cg.process_lambda( config[CONF_WRITE_LAMBDA], [ (ModbusBinaryOutput.operator("ptr"), "item"), @@ -92,7 +88,7 @@ async def to_code(config): ) cg.add(var.set_write_multiply(config[CONF_MULTIPLY])) if CONF_WRITE_LAMBDA in config: - template_ = await cg.process_lambda( + write_template = await cg.process_lambda( config[CONF_WRITE_LAMBDA], [ (ModbusFloatOutput.operator("ptr"), "item"), @@ -105,5 +101,5 @@ async def to_code(config): parent = await cg.get_variable(config[CONF_MODBUS_CONTROLLER_ID]) cg.add(var.set_use_write_mutiple(config[CONF_USE_WRITE_MULTIPLE])) cg.add(var.set_parent(parent)) - if CONF_WRITE_LAMBDA in config: - cg.add(var.set_write_template(template_)) + if write_template: + cg.add(var.set_write_template(write_template)) diff --git a/esphome/components/modbus_controller/select/__init__.py b/esphome/components/modbus_controller/select/__init__.py index 5692fea3e3..c94532da51 100644 --- a/esphome/components/modbus_controller/select/__init__.py +++ b/esphome/components/modbus_controller/select/__init__.py @@ -1,6 +1,6 @@ import esphome.codegen as cg -import esphome.config_validation as cv from esphome.components import select +import esphome.config_validation as cv from esphome.const import CONF_ADDRESS, CONF_ID, CONF_LAMBDA, CONF_OPTIMISTIC from .. import ( diff --git a/esphome/components/modbus_controller/sensor/__init__.py b/esphome/components/modbus_controller/sensor/__init__.py index 0e4588cfef..d8fce54ece 100644 --- a/esphome/components/modbus_controller/sensor/__init__.py +++ b/esphome/components/modbus_controller/sensor/__init__.py @@ -1,17 +1,17 @@ +import esphome.codegen as cg from esphome.components import sensor import esphome.config_validation as cv -import esphome.codegen as cg +from esphome.const import CONF_ADDRESS, CONF_ID -from esphome.const import CONF_ID, CONF_ADDRESS from .. import ( - add_modbus_base_properties, - modbus_controller_ns, - modbus_calc_properties, - validate_modbus_register, - ModbusItemBaseSchema, - SensorItem, MODBUS_REGISTER_TYPE, SENSOR_VALUE_TYPE, + ModbusItemBaseSchema, + SensorItem, + add_modbus_base_properties, + modbus_calc_properties, + modbus_controller_ns, + validate_modbus_register, ) from ..const import ( CONF_BITMASK, diff --git a/esphome/components/modbus_controller/switch/__init__.py b/esphome/components/modbus_controller/switch/__init__.py index 9490325968..258d87fd25 100644 --- a/esphome/components/modbus_controller/switch/__init__.py +++ b/esphome/components/modbus_controller/switch/__init__.py @@ -1,17 +1,16 @@ +import esphome.codegen as cg from esphome.components import switch import esphome.config_validation as cv -import esphome.codegen as cg +from esphome.const import CONF_ADDRESS, CONF_ID - -from esphome.const import CONF_ID, CONF_ADDRESS from .. import ( - add_modbus_base_properties, - modbus_controller_ns, - modbus_calc_properties, - validate_modbus_register, + MODBUS_REGISTER_TYPE, ModbusItemBaseSchema, SensorItem, - MODBUS_REGISTER_TYPE, + add_modbus_base_properties, + modbus_calc_properties, + modbus_controller_ns, + validate_modbus_register, ) from ..const import ( CONF_BITMASK, diff --git a/esphome/components/modbus_controller/text_sensor/__init__.py b/esphome/components/modbus_controller/text_sensor/__init__.py index 81d6453c6f..35cae645e1 100644 --- a/esphome/components/modbus_controller/text_sensor/__init__.py +++ b/esphome/components/modbus_controller/text_sensor/__init__.py @@ -1,26 +1,25 @@ +import esphome.codegen as cg from esphome.components import text_sensor import esphome.config_validation as cv -import esphome.codegen as cg - - from esphome.const import CONF_ADDRESS, CONF_ID + from .. import ( - add_modbus_base_properties, - modbus_controller_ns, - modbus_calc_properties, - validate_modbus_register, + MODBUS_REGISTER_TYPE, ModbusItemBaseSchema, SensorItem, - MODBUS_REGISTER_TYPE, + add_modbus_base_properties, + modbus_calc_properties, + modbus_controller_ns, + validate_modbus_register, ) from ..const import ( CONF_FORCE_NEW_RANGE, CONF_MODBUS_CONTROLLER_ID, + CONF_RAW_ENCODE, CONF_REGISTER_COUNT, + CONF_REGISTER_TYPE, CONF_RESPONSE_SIZE, CONF_SKIP_UPDATES, - CONF_RAW_ENCODE, - CONF_REGISTER_TYPE, ) DEPENDENCIES = ["modbus_controller"] From 435789a96020435b6d0c345bebb6ef19a98fd818 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 16 Sep 2024 17:21:42 +1200 Subject: [PATCH 2100/2101] Bump pylint from 3.1.0 to 3.2.7 (#7438) --- requirements_test.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements_test.txt b/requirements_test.txt index 94abe1cd76..5d94f7f640 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,4 +1,4 @@ -pylint==3.1.0 +pylint==3.2.7 flake8==7.0.0 # also change in .pre-commit-config.yaml when updating black==24.4.2 # also change in .pre-commit-config.yaml when updating pyupgrade==3.15.2 # also change in .pre-commit-config.yaml when updating From 857a3dcf72d74fa53fba2f6c63f2ceaaec3e5e59 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 16 Sep 2024 18:03:51 +1200 Subject: [PATCH 2101/2101] Dont replace project name spaces with underlines (#7455) --- esphome/core/config.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/esphome/core/config.py b/esphome/core/config.py index 739a8a1aea..f4253bee87 100644 --- a/esphome/core/config.py +++ b/esphome/core/config.py @@ -100,9 +100,6 @@ def valid_include(value): def valid_project_name(value: str): if value.count(".") != 1: raise cv.Invalid("project name needs to have a namespace") - - value = value.replace(" ", "_") - return value